From eb6918d59f661c0e5b469d6e007f91a82d46a302 Mon Sep 17 00:00:00 2001 From: "jonghyun.ho" Date: Wed, 22 Aug 2012 21:44:43 +0900 Subject: [PATCH] Initialize libbullet git in 2.0_beta. --- AUTHORS | 22 + BspDemo.bsp | Bin 0 -> 105100 bytes BulletLicense.txt | 18 + Bullet_User_Manual.pdf | Bin 0 -> 1168019 bytes CMakeLists.txt | 378 + COPYING | 17 + ChangeLog | 788 + Demos/AllBulletDemos/CMakeLists.txt | 104 + Demos/AllBulletDemos/DemoEntries.cpp | 178 + Demos/AllBulletDemos/DemoEntries.h | 34 + Demos/AllBulletDemos/Main.cpp | 579 + Demos/AllBulletDemos/Makefile.am | 34 + Demos/BasicDemo/BasicDemo.cpp | 237 + Demos/BasicDemo/BasicDemo.h | 82 + Demos/BasicDemo/CMakeLists.txt | 87 + Demos/BasicDemo/Makefile.am | 5 + Demos/BasicDemo/Makefile.original | 49 + Demos/BasicDemo/Win32BasicDemo.cpp | 25 + Demos/BasicDemo/main.cpp | 42 + Demos/Benchmarks/BenchmarkDemo.cpp | 1320 + Demos/Benchmarks/BenchmarkDemo.h | 265 + Demos/Benchmarks/CMakeLists.txt | 107 + Demos/Benchmarks/Taru.mdl | 49 + Demos/Benchmarks/Win32BenchmarkDemo.cpp | 25 + Demos/Benchmarks/landscape.mdl | 84369 +++++++++++++++++++ Demos/Benchmarks/main.cpp | 88 + Demos/Box2dDemo/Box2dDemo.cpp | 358 + Demos/Box2dDemo/Box2dDemo.h | 89 + Demos/Box2dDemo/CMakeLists.txt | 75 + Demos/Box2dDemo/Win32Box2dDemo.cpp | 25 + Demos/Box2dDemo/main.cpp | 61 + Demos/BspDemo/BspConverter.cpp | 207 + Demos/BspDemo/BspConverter.h | 39 + Demos/BspDemo/BspDemo.cpp | 321 + Demos/BspDemo/BspDemo.h | 71 + Demos/BspDemo/BspLoader.cpp | 730 + Demos/BspDemo/BspLoader.h | 295 + Demos/BspDemo/CMakeLists.txt | 60 + Demos/BspDemo/main.cpp | 59 + Demos/BulletDinoDemo/BulletDino.c | 996 + Demos/BulletDinoDemo/CMakeLists.txt | 61 + Demos/CMakeLists.txt | 61 + Demos/CcdPhysicsDemo/CMakeLists.txt | 57 + Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp | 413 + Demos/CcdPhysicsDemo/CcdPhysicsDemo.h | 94 + Demos/CcdPhysicsDemo/Makefile.am | 5 + Demos/CcdPhysicsDemo/main.cpp | 49 + Demos/CellSpuDemo/BasicDemo2.cpp | 277 + Demos/CellSpuDemo/BasicDemo2.h | 62 + Demos/CellSpuDemo/ibmsdk/Makefile | 69 + Demos/CharacterDemo/CMakeLists.txt | 75 + Demos/CharacterDemo/CharacterDemo.cpp | 531 + Demos/CharacterDemo/CharacterDemo.h | 153 + Demos/CharacterDemo/DynamicCharacterController.cpp | 204 + Demos/CharacterDemo/DynamicCharacterController.h | 55 + Demos/CharacterDemo/main.cpp | 19 + Demos/CollisionDemo/CMakeLists.txt | 54 + Demos/CollisionDemo/CollisionDemo.cpp | 380 + Demos/CollisionDemo/CollisionDemo.h | 38 + Demos/CollisionInterfaceDemo/CMakeLists.txt | 77 + .../CollisionInterfaceDemo.cpp | 292 + .../CollisionInterfaceDemo.h | 42 + .../Win32CollisionInterfaceDemo.cpp | 25 + Demos/CollisionInterfaceDemo/main.cpp | 19 + Demos/ConcaveConvexcastDemo/CMakeLists.txt | 48 + .../ConcaveConvexcastDemo.cpp | 516 + .../ConcaveConvexcastDemo/ConcaveConvexcastDemo.h | 84 + Demos/ConcaveConvexcastDemo/main.cpp | 15 + Demos/ConcaveDemo/CMakeLists.txt | 80 + Demos/ConcaveDemo/ConcaveDemo.h | 91 + Demos/ConcaveDemo/ConcavePhysicsDemo.cpp | 474 + Demos/ConcaveDemo/Jamfile | 3 + Demos/ConcaveDemo/Win32ConcaveDemo.cpp | 25 + Demos/ConcaveDemo/main.cpp | 19 + Demos/ConcaveRaycastDemo/CMakeLists.txt | 57 + Demos/ConcaveRaycastDemo/ConcaveRaycastDemo.cpp | 490 + Demos/ConcaveRaycastDemo/ConcaveRaycastDemo.h | 85 + Demos/ConcaveRaycastDemo/main.cpp | 15 + Demos/ConstraintDemo/CMakeLists.txt | 69 + Demos/ConstraintDemo/ConstraintDemo.cpp | 738 + Demos/ConstraintDemo/ConstraintDemo.h | 72 + Demos/ConstraintDemo/Win32ConstraintDemo.cpp | 25 + Demos/ConstraintDemo/main.cpp | 20 + Demos/ContinuousConvexCollision/CMakeLists.txt | 47 + .../ContinuousConvexCollision.h | 36 + .../ContinuousConvexCollisionDemo.cpp | 287 + Demos/ConvexDecompositionDemo/CMakeLists.txt | 83 + .../ConvexDecompositionDemo.cpp | 741 + .../ConvexDecompositionDemo.h | 88 + .../Win32ConvexDecompositionDemo.cpp | 25 + Demos/ConvexDecompositionDemo/main.cpp | 32 + .../testFile32Single.bullet | Bin 0 -> 67844 bytes Demos/ConvexHullDistance/CMakeLists.txt | 82 + .../ConvexHullDistance/ConvexHullDistanceDemo.cpp | 508 + Demos/DX11ClothDemo/CMakeLists.txt | 166 + Demos/DX11ClothDemo/DXUT/Core/DXUT.cpp | 5846 ++ Demos/DX11ClothDemo/DXUT/Core/DXUT.h | 378 + Demos/DX11ClothDemo/DXUT/Core/DXUTDevice11.cpp | 1154 + Demos/DX11ClothDemo/DXUT/Core/DXUTDevice11.h | 210 + Demos/DX11ClothDemo/DXUT/Core/DXUTDevice9.cpp | 1177 + Demos/DX11ClothDemo/DXUT/Core/DXUTDevice9.h | 207 + Demos/DX11ClothDemo/DXUT/Core/DXUTmisc.cpp | 1785 + Demos/DX11ClothDemo/DXUT/Core/DXUTmisc.h | 594 + Demos/DX11ClothDemo/DXUT/Core/dpiaware.manifest | 7 + .../DX11ClothDemo/DXUT/Optional/DXUTLockFreePipe.h | 227 + Demos/DX11ClothDemo/DXUT/Optional/DXUTShapes.cpp | 5663 ++ Demos/DX11ClothDemo/DXUT/Optional/DXUTShapes.h | 24 + Demos/DX11ClothDemo/DXUT/Optional/DXUTcamera.cpp | 1525 + Demos/DX11ClothDemo/DXUT/Optional/DXUTcamera.h | 517 + Demos/DX11ClothDemo/DXUT/Optional/DXUTgui.cpp | 7241 ++ Demos/DX11ClothDemo/DXUT/Optional/DXUTgui.h | 1383 + Demos/DX11ClothDemo/DXUT/Optional/DXUTguiIME.cpp | 990 + Demos/DX11ClothDemo/DXUT/Optional/DXUTguiIME.h | 141 + Demos/DX11ClothDemo/DXUT/Optional/DXUTres.cpp | 8338 ++ Demos/DX11ClothDemo/DXUT/Optional/DXUTres.h | 18 + .../DXUT/Optional/DXUTsettingsdlg.cpp | 2853 + .../DX11ClothDemo/DXUT/Optional/DXUTsettingsdlg.h | 248 + Demos/DX11ClothDemo/DXUT/Optional/ImeUi.cpp | 3662 + Demos/DX11ClothDemo/DXUT/Optional/ImeUi.h | 124 + Demos/DX11ClothDemo/DXUT/Optional/SDKmesh.cpp | 2348 + Demos/DX11ClothDemo/DXUT/Optional/SDKmesh.h | 589 + Demos/DX11ClothDemo/DXUT/Optional/SDKmisc.cpp | 1695 + Demos/DX11ClothDemo/DXUT/Optional/SDKmisc.h | 368 + Demos/DX11ClothDemo/DXUT/Optional/SDKsound.cpp | 1053 + Demos/DX11ClothDemo/DXUT/Optional/SDKsound.h | 124 + Demos/DX11ClothDemo/DXUT/Optional/SDKwavefile.cpp | 539 + Demos/DX11ClothDemo/DXUT/Optional/SDKwavefile.h | 59 + Demos/DX11ClothDemo/DXUT/Optional/directx.ico | Bin 0 -> 25214 bytes Demos/DX11ClothDemo/Media/Tiny/Tiny_skin.dds | Bin 0 -> 262272 bytes Demos/DX11ClothDemo/Media/Tiny/tiny.sdkmesh | Bin 0 -> 231612 bytes Demos/DX11ClothDemo/Media/Tiny/tiny.x | 53984 ++++++++++++ Demos/DX11ClothDemo/Media/UI/DXUTShared.fx | 69 + Demos/DX11ClothDemo/Media/UI/Font.dds | Bin 0 -> 76128 bytes Demos/DX11ClothDemo/Media/UI/arrow.x | 1050 + Demos/DX11ClothDemo/Media/UI/dxutcontrols.dds | Bin 0 -> 262272 bytes Demos/DX11ClothDemo/amdFlag.bmp | Bin 0 -> 1396038 bytes Demos/DX11ClothDemo/atiFlag.bmp | Bin 0 -> 1396038 bytes Demos/DX11ClothDemo/btDirectComputeSupport.h | 180 + Demos/DX11ClothDemo/cap.h | 298 + Demos/DX11ClothDemo/capsule.h | 67 + Demos/DX11ClothDemo/cloth.h | 312 + Demos/DX11ClothDemo/cloth_renderer.cpp | 1356 + Demos/DX11ClothDemo/cloth_renderer.fx | 157 + Demos/DX11ClothDemo/cloth_renderer.rc | 77 + Demos/DX11ClothDemo/cloth_renderer_PS.hlsl | 90 + Demos/DX11ClothDemo/cloth_renderer_VS.hlsl | 48 + Demos/DX11ClothDemo/cylinder.h | 297 + Demos/DX11ClothDemo/premake4.lua | 41 + Demos/DX11ClothDemo/resource.h | 16 + Demos/DX11ClothDemo/texture.bmp | Bin 0 -> 263222 bytes Demos/DX11ClothDemo/texture.png | Bin 0 -> 7922 bytes Demos/DoublePrecisionDemo/CMakeLists.txt | 49 + Demos/DoublePrecisionDemo/DoublePrecisionDemo.cpp | 280 + Demos/DoublePrecisionDemo/DoublePrecisionDemo.h | 41 + Demos/DynamicControlDemo/CMakeLists.txt | 49 + Demos/DynamicControlDemo/MotorDemo.cpp | 468 + Demos/DynamicControlDemo/MotorDemo.h | 80 + Demos/DynamicControlDemo/main.cpp | 28 + Demos/EPAPenDepthDemo/PenetrationTestBullet.cpp | 855 + Demos/ForkLiftDemo/CMakeLists.txt | 59 + Demos/ForkLiftDemo/ForkLiftDemo.cpp | 865 + Demos/ForkLiftDemo/ForkLiftDemo.h | 113 + Demos/ForkLiftDemo/main.cpp | 18 + Demos/FractureDemo/CMakeLists.txt | 95 + Demos/FractureDemo/FractureDemo.cpp | 362 + Demos/FractureDemo/FractureDemo.h | 87 + Demos/FractureDemo/Win32FractureDemo.cpp | 25 + Demos/FractureDemo/btFractureBody.cpp | 138 + Demos/FractureDemo/btFractureBody.h | 78 + Demos/FractureDemo/btFractureDynamicsWorld.cpp | 674 + Demos/FractureDemo/btFractureDynamicsWorld.h | 51 + Demos/FractureDemo/main.cpp | 42 + Demos/GenericJointDemo/CMakeLists.txt | 82 + Demos/GenericJointDemo/GenericJointDemo.cpp | 135 + Demos/GenericJointDemo/GenericJointDemo.h | 51 + Demos/GenericJointDemo/Ragdoll.cpp | 373 + Demos/GenericJointDemo/Ragdoll.h | 71 + Demos/GenericJointDemo/Win32GenericJointDemo.cpp | 25 + Demos/GenericJointDemo/main.cpp | 28 + Demos/GimpactTestDemo/BunnyMesh.h | 1379 + Demos/GimpactTestDemo/CMakeLists.txt | 58 + Demos/GimpactTestDemo/GimpactTestDemo.cpp | 688 + Demos/GimpactTestDemo/GimpactTestDemo.h | 145 + Demos/GimpactTestDemo/TorusMesh.h | 921 + Demos/GimpactTestDemo/Win32GimpactDemo.cpp | 25 + Demos/GimpactTestDemo/main.cpp | 13 + Demos/GjkConvexCastDemo/CMakeLists.txt | 48 + Demos/GjkConvexCastDemo/LinearConvexCastDemo.cpp | 185 + Demos/GjkConvexCastDemo/LinearConvexCastDemo.h | 44 + Demos/GjkConvexCastDemo/main.cpp | 17 + Demos/Gpu2dDemo/BasicDemo.cpp | 808 + Demos/Gpu2dDemo/BasicDemo.h | 99 + Demos/Gpu2dDemo/CMakeLists.txt | 38 + Demos/Gpu2dDemo/Makefile.am | 5 + Demos/Gpu2dDemo/btGpuDemo2dCpuFunc.cpp | 30 + Demos/Gpu2dDemo/btGpuDemo2dSharedCode.h | 497 + Demos/Gpu2dDemo/btGpuDemo2dSharedDefs.h | 33 + Demos/Gpu2dDemo/btGpuDemo2dSharedTypes.h | 35 + Demos/Gpu2dDemo/btGpuDemoDynamicsWorld.cpp | 592 + Demos/Gpu2dDemo/btGpuDemoDynamicsWorld.h | 291 + Demos/Gpu2dDemo/btGpuDemoPairCache.cpp | 76 + Demos/Gpu2dDemo/btGpuDemoPairCache.h | 136 + Demos/Gpu2dDemo/main.cpp | 62 + Demos/Gpu2dDemo/oecakeLoader.cpp | 264 + Demos/Gpu2dDemo/oecakeLoader.h | 35 + Demos/Gpu3dDemo/BasicDemo3d.cpp | 852 + Demos/Gpu3dDemo/BasicDemo3d.h | 93 + Demos/Gpu3dDemo/CMakeLists.txt | 34 + Demos/Gpu3dDemo/btGpuDemo3dCpuFunc.cpp | 32 + Demos/Gpu3dDemo/btGpuDemo3dSharedCode.h | 545 + Demos/Gpu3dDemo/btGpuDemo3dSharedDefs.h | 38 + Demos/Gpu3dDemo/btGpuDemo3dSharedTypes.h | 39 + Demos/Gpu3dDemo/btGpuDemoDynamicsWorld3D.cpp | 593 + Demos/Gpu3dDemo/btGpuDemoDynamicsWorld3D.h | 252 + Demos/Gpu3dDemo/main.cpp | 61 + .../BulletHfFluid/btHfFluid.cpp | 1045 + .../HeightFieldFluidDemo/BulletHfFluid/btHfFluid.h | 243 + .../BulletHfFluid/btHfFluidBuoyantConvexShape.cpp | 195 + .../BulletHfFluid/btHfFluidBuoyantConvexShape.h | 62 + .../btHfFluidBuoyantShapeCollisionAlgorithm.cpp | 74 + .../btHfFluidBuoyantShapeCollisionAlgorithm.h | 87 + .../BulletHfFluid/btHfFluidCollisionShape.cpp | 18 + .../BulletHfFluid/btHfFluidCollisionShape.h | 94 + .../btHfFluidRigidCollisionAlgorithm.cpp | 133 + .../btHfFluidRigidCollisionAlgorithm.h | 81 + .../btHfFluidRigidCollisionConfiguration.cpp | 88 + .../btHfFluidRigidCollisionConfiguration.h | 47 + .../BulletHfFluid/btHfFluidRigidDynamicsWorld.cpp | 273 + .../BulletHfFluid/btHfFluidRigidDynamicsWorld.h | 92 + Demos/HeightFieldFluidDemo/CMakeLists.txt | 35 + Demos/HeightFieldFluidDemo/HfFluidDemo.cpp | 1457 + Demos/HeightFieldFluidDemo/HfFluidDemo.h | 152 + .../HfFluidDemo_GL_ShapeDrawer.cpp | 606 + .../HfFluidDemo_GL_ShapeDrawer.h | 37 + Demos/HeightFieldFluidDemo/main.cpp | 39 + Demos/HelloWorld/CMakeLists.txt | 29 + Demos/HelloWorld/HelloWorld.cpp | 172 + Demos/InternalEdgeDemo/CMakeLists.txt | 69 + Demos/InternalEdgeDemo/InternalEdgeDemo.cpp | 623 + Demos/InternalEdgeDemo/InternalEdgeDemo.h | 93 + Demos/InternalEdgeDemo/Taru.mdl | 49 + Demos/InternalEdgeDemo/Win32InternalEdgeDemo.cpp | 25 + Demos/InternalEdgeDemo/main.cpp | 19 + Demos/Makefile.am | 5 + Demos/MovingConcaveDemo/CMakeLists.txt | 32 + Demos/MovingConcaveDemo/ConcaveDemo.h | 48 + Demos/MovingConcaveDemo/ConcavePhysicsDemo.cpp | 1925 + Demos/MultiMaterialDemo/CMakeLists.txt | 31 + Demos/MultiMaterialDemo/MultiMaterialDemo.cpp | 382 + Demos/MultiMaterialDemo/MultiMaterialDemo.h | 84 + Demos/MultiMaterialDemo/main.cpp | 22 + Demos/MultiThreadedDemo/CMakeLists.txt | 55 + Demos/MultiThreadedDemo/Makefile.am | 5 + Demos/MultiThreadedDemo/MultiThreadedDemo.cpp | 504 + Demos/MultiThreadedDemo/MultiThreadedDemo.h | 79 + Demos/MultiThreadedDemo/main.cpp | 36 + Demos/NativeClient/bin_html/bind.js | 22 + Demos/NativeClient/bin_html/dragger.js | 134 + Demos/NativeClient/bin_html/httpd.cmd | 9 + Demos/NativeClient/bin_html/httpd.py | 114 + Demos/NativeClient/bin_html/index.html | 33 + Demos/NativeClient/bin_html/trackball.js | 296 + Demos/NativeClient/bin_html/tumbler.js | 133 + Demos/NativeClient/bin_html/tumbler.nmf | 6 + Demos/NativeClient/bin_html/vector3.js | 91 + Demos/NativeClient/callback.h | 92 + Demos/NativeClient/cube.cc | 267 + Demos/NativeClient/cube.h | 97 + Demos/NativeClient/opengl_context.cc | 72 + Demos/NativeClient/opengl_context.h | 90 + Demos/NativeClient/opengl_context_ptrs.h | 22 + Demos/NativeClient/premake4.lua | 27 + Demos/NativeClient/scripting_bridge.cc | 95 + Demos/NativeClient/scripting_bridge.h | 52 + Demos/NativeClient/shader_util.cc | 95 + Demos/NativeClient/shader_util.h | 29 + Demos/NativeClient/transforms.cc | 116 + Demos/NativeClient/transforms.h | 45 + Demos/NativeClient/tumbler.cc | 136 + Demos/NativeClient/tumbler.h | 64 + Demos/NativeClient/tumbler_module.cc | 45 + Demos/OpenCLClothDemo/AMD/CMakeLists.txt | 86 + Demos/OpenCLClothDemo/AMD/premake4.lua | 67 + Demos/OpenCLClothDemo/Apple/CMakeLists.txt | 55 + Demos/OpenCLClothDemo/CLClothDemo.sln | 20 + Demos/OpenCLClothDemo/CLClothDemo.vcproj | 233 + Demos/OpenCLClothDemo/CMakeLists.txt | 17 + Demos/OpenCLClothDemo/Intel/CMakeLists.txt | 85 + Demos/OpenCLClothDemo/Intel/premake4.lua | 68 + Demos/OpenCLClothDemo/MiniCL/CMakeLists.txt | 88 + Demos/OpenCLClothDemo/NVidia/CMakeLists.txt | 86 + Demos/OpenCLClothDemo/NVidia/premake4.lua | 68 + Demos/OpenCLClothDemo/btOpenCLSupport.h | 84 + Demos/OpenCLClothDemo/cl_cloth_demo.cpp | 613 + Demos/OpenCLClothDemo/cloth.h | 258 + Demos/OpenCLClothDemo/clstuff.cpp | 71 + Demos/OpenCLClothDemo/clstuff.h | 11 + Demos/OpenCLClothDemo/clstuff.hpp | 10 + Demos/OpenCLClothDemo/fragment.glsl | 7 + Demos/OpenCLClothDemo/gl_win.cpp | 268 + Demos/OpenCLClothDemo/gl_win.h | 49 + Demos/OpenCLClothDemo/gl_win.hpp | 34 + Demos/OpenCLClothDemo/shaders.cl | 535 + Demos/OpenCLClothDemo/vertex.glsl | 7 + Demos/OpenGL/CMakeLists.txt | 67 + Demos/OpenGL/DebugCastResult.h | 88 + Demos/OpenGL/DemoApplication.cpp | 1383 + Demos/OpenGL/DemoApplication.h | 258 + Demos/OpenGL/GLDebugDrawer.cpp | 139 + Demos/OpenGL/GLDebugDrawer.h | 38 + Demos/OpenGL/GLDebugFont.cpp | 1000 + Demos/OpenGL/GLDebugFont.h | 29 + Demos/OpenGL/GL_DialogDynamicsWorld.cpp | 761 + Demos/OpenGL/GL_DialogDynamicsWorld.h | 91 + Demos/OpenGL/GL_DialogWindow.cpp | 358 + Demos/OpenGL/GL_DialogWindow.h | 285 + Demos/OpenGL/GL_ShapeDrawer.cpp | 987 + Demos/OpenGL/GL_ShapeDrawer.h | 70 + Demos/OpenGL/GL_Simplex1to4.cpp | 76 + Demos/OpenGL/GL_Simplex1to4.h | 40 + Demos/OpenGL/GlutDemoApplication.cpp | 87 + Demos/OpenGL/GlutDemoApplication.h | 34 + Demos/OpenGL/GlutStuff.cpp | 120 + Demos/OpenGL/GlutStuff.h | 86 + Demos/OpenGL/Makefile.am | 12 + Demos/OpenGL/RenderTexture.cpp | 86 + Demos/OpenGL/RenderTexture.h | 73 + Demos/OpenGL/Win32AppMain.cpp | 405 + Demos/OpenGL/Win32DemoApplication.cpp | 79 + Demos/OpenGL/Win32DemoApplication.h | 40 + Demos/OpenGL/ibmsdk/Makefile | 45 + Demos/OpenGL/premake4.lua | 18 + Demos/OpenGL/stb_image.cpp | 4342 + Demos/OpenGL/stb_image.h | 332 + Demos/OpenPL_Demo/CApi.cpp | 159 + Demos/OpenPL_Demo/OpenPL_Demo.c | 44 + Demos/ParticlesOpenCL/AMD/CMakeLists.txt | 86 + Demos/ParticlesOpenCL/Apple/CMakeLists.txt | 84 + Demos/ParticlesOpenCL/CMakeLists.txt | 19 + Demos/ParticlesOpenCL/Intel/CMakeLists.txt | 87 + Demos/ParticlesOpenCL/MiniCL/CMakeLists.txt | 94 + Demos/ParticlesOpenCL/MiniCL/MiniCLTaskWrap.cpp | 33 + Demos/ParticlesOpenCL/NVidia/CMakeLists.txt | 95 + Demos/ParticlesOpenCL/ParticlesDemo.cpp | 651 + Demos/ParticlesOpenCL/ParticlesDemo.h | 128 + Demos/ParticlesOpenCL/ParticlesOCL.cl | 467 + .../btParticlesDemoDynamicsWorld.cpp | 1177 + Demos/ParticlesOpenCL/btParticlesDynamicsWorld.h | 183 + Demos/ParticlesOpenCL/btParticlesSharedDefs.h | 14 + Demos/ParticlesOpenCL/btParticlesSharedTypes.h | 54 + Demos/ParticlesOpenCL/main.cpp | 51 + Demos/ParticlesOpenCL/shaders.cpp | 56 + Demos/ParticlesOpenCL/shaders.h | 2 + Demos/RagdollDemo/CMakeLists.txt | 49 + Demos/RagdollDemo/RagdollDemo.cpp | 507 + Demos/RagdollDemo/RagdollDemo.h | 77 + Demos/RagdollDemo/main.cpp | 31 + Demos/Raytracer/CMakeLists.txt | 49 + Demos/Raytracer/Raytracer.cpp | 625 + Demos/Raytracer/Raytracer.h | 65 + Demos/Raytracer/main.cpp | 16 + Demos/SerializeDemo/AMD/CMakeLists.txt | 164 + Demos/SerializeDemo/AMD/premake4.lua | 65 + Demos/SerializeDemo/CMakeLists.txt | 95 + Demos/SerializeDemo/SerializeDemo.cpp | 928 + Demos/SerializeDemo/SerializeDemo.h | 85 + Demos/SerializeDemo/Win32SerializeDemo.cpp | 25 + Demos/SerializeDemo/main.cpp | 109 + Demos/SerializeDemo/testFile.bullet | Bin 0 -> 171368 bytes Demos/SerializeDemo/testFileCloth.bullet | Bin 0 -> 98740 bytes Demos/SharedOpenCL/btOpenCLInclude.h | 43 + Demos/SharedOpenCL/btOpenCLUtils.cpp | 789 + Demos/SharedOpenCL/btOpenCLUtils.h | 107 + Demos/SharedOpenCL/clew.c | 313 + Demos/SharedOpenCL/clew.h | 1316 + Demos/SimplexDemo/CMakeLists.txt | 48 + Demos/SimplexDemo/SimplexDemo.cpp | 123 + Demos/SimplexDemo/SimplexDemo.h | 36 + Demos/SliderConstraintDemo/CMakeLists.txt | 51 + .../SliderConstraintDemo/SliderConstraintDemo.cpp | 512 + Demos/SliderConstraintDemo/SliderConstraintDemo.h | 73 + Demos/SliderConstraintDemo/main.cpp | 25 + Demos/SoftDemo/AMD/premake4.lua | 59 + Demos/SoftDemo/CMakeLists.txt | 64 + Demos/SoftDemo/Makefile.am | 5 + Demos/SoftDemo/SoftDemo.cpp | 2293 + Demos/SoftDemo/SoftDemo.h | 197 + Demos/SoftDemo/bunny.inl | 4 + Demos/SoftDemo/cube.inl | 4 + Demos/SoftDemo/main.cpp | 37 + Demos/TerrainDemo/Makefile.am | 6 + Demos/TerrainDemo/TerrainDemo.cpp | 921 + Demos/TerrainDemo/TerrainDemo.h | 27 + Demos/TerrainDemo/main.cpp | 14 + Demos/ThreadingDemo/CMakeLists.txt | 47 + Demos/ThreadingDemo/main.cpp | 177 + Demos/UserCollisionAlgorithm/CMakeLists.txt | 38 + .../UserCollisionAlgorithm.cpp | 175 + .../UserCollisionAlgorithm.h | 36 + Demos/VectorAdd_OpenCL/AMD/CMakeLists.txt | 34 + Demos/VectorAdd_OpenCL/Apple/CMakeLists.txt | 25 + Demos/VectorAdd_OpenCL/CMakeLists.txt | 16 + Demos/VectorAdd_OpenCL/MiniCL/CMakeLists.txt | 38 + Demos/VectorAdd_OpenCL/MiniCL_VectorAdd.cpp | 389 + Demos/VectorAdd_OpenCL/NVidia/CMakeLists.txt | 28 + Demos/VectorAdd_OpenCL/VectorAddKernels.cl | 35 + Demos/VehicleDemo/CMakeLists.txt | 31 + Demos/VehicleDemo/Makefile.am | 5 + Demos/VehicleDemo/VehicleDemo.cpp | 671 + Demos/VehicleDemo/VehicleDemo.h | 91 + Demos/VehicleDemo/main.cpp | 18 + Demos/VoronoiFractureDemo/CMakeLists.txt | 87 + Demos/VoronoiFractureDemo/Makefile.am | 5 + Demos/VoronoiFractureDemo/Makefile.original | 49 + Demos/VoronoiFractureDemo/VoronoiFractureDemo.cpp | 660 + Demos/VoronoiFractureDemo/VoronoiFractureDemo.h | 97 + .../Win32VoronoiFractureDemo.cpp | 25 + Demos/VoronoiFractureDemo/main.cpp | 51 + Demos/premake4.lua | 96 + Doxyfile | 780 + .../AllBulletDemos.xcodeproj/TemplateIcon.icns | Bin 0 -> 52318 bytes .../AllBulletDemos.xcodeproj/project.pbxproj | 1860 + .../AllBulletDemos.xcodeproj/zakariya.pbxuser | 248 + .../zakariya.perspectivev3 | 1517 + Extras/AllBulletDemosOSX/AllBulletDemos_Prefix.pch | 7 + Extras/AllBulletDemosOSX/BulletIcon.icns | Bin 0 -> 28472 bytes Extras/AllBulletDemosOSX/BulletIcon.psd | Bin 0 -> 101941 bytes Extras/AllBulletDemosOSX/English.lproj/Credits.rtf | 11 + .../English.lproj/InfoPlist.strings | Bin 0 -> 92 bytes .../AllBulletDemosOSX/English.lproj/MainMenu.xib | 2157 + Extras/AllBulletDemosOSX/Info.plist | 28 + Extras/AllBulletDemosOSX/README.txt | 6 + Extras/AllBulletDemosOSX/main.m | 14 + Extras/AllBulletDemosOSX/src/BTDemo.h | 106 + Extras/AllBulletDemosOSX/src/BTDemo.mm | 411 + .../AllBulletDemosOSX/src/BTDemosAppController.h | 54 + .../AllBulletDemosOSX/src/BTDemosAppController.m | 151 + .../AllBulletDemosOSX/src/BTSimulationParameters.h | 47 + .../AllBulletDemosOSX/src/BTSimulationParameters.m | 96 + .../src/toolkit/BTFullscreenWindow.h | 25 + .../src/toolkit/BTFullscreenWindow.m | 48 + .../src/toolkit/BTGLUTKeyAdapter.h | 46 + .../src/toolkit/BTGLUTKeyAdapter.m | 128 + .../src/toolkit/BTOpenGLDisplayDelegate.h | 50 + .../AllBulletDemosOSX/src/toolkit/BTOpenGLView.h | 65 + .../AllBulletDemosOSX/src/toolkit/BTOpenGLView.m | 603 + Extras/CDTestFramework/AntTweakBar/ChangeLog.txt | 23 + Extras/CDTestFramework/AntTweakBar/Clean.bat | 19 + Extras/CDTestFramework/AntTweakBar/License.txt | 23 + Extras/CDTestFramework/AntTweakBar/Readme.txt | 15 + .../AntTweakBar/examples/Examples.ncb | Bin 0 -> 150528 bytes .../AntTweakBar/examples/Examples.sln | 65 + .../AntTweakBar/examples/Examples.suo | Bin 0 -> 15360 bytes .../CDTestFramework/AntTweakBar/examples/Makefile | 80 + .../AntTweakBar/examples/Makefile.x86_64 | 82 + .../AntTweakBar/examples/TwAdvanced1.cpp | 693 + .../AntTweakBar/examples/TwAdvanced1.vcproj | 142 + .../AntTweakBar/examples/TwCopyDLL.vcproj | 53 + .../AntTweakBar/examples/TwSimpleDX9.cpp | 228 + .../AntTweakBar/examples/TwSimpleDX9.vcproj | 138 + .../AntTweakBar/examples/TwSimpleGLFW.c | 200 + .../AntTweakBar/examples/TwSimpleGLFW.vcproj | 137 + .../AntTweakBar/examples/TwSimpleGLUT.c | 194 + .../AntTweakBar/examples/TwSimpleGLUT.vcproj | 141 + .../AntTweakBar/examples/TwSimpleSDL.c | 216 + .../AntTweakBar/examples/TwSimpleSDL.vcproj | 178 + Extras/CDTestFramework/AntTweakBar/examples/glfw.h | 482 + .../AntTweakBar/examples/glfwdll.lib | Bin 0 -> 15196 bytes .../AntTweakBar/include/AntTweakBar.h | 288 + .../AntTweakBar/lib/AntTweakBar.dll | Bin 0 -> 315392 bytes .../AntTweakBar/lib/AntTweakBar.exp | Bin 0 -> 4769 bytes .../AntTweakBar/lib/AntTweakBar.lib | Bin 0 -> 8904 bytes Extras/CDTestFramework/AntTweakBar/lib/Readme.txt | 6 + .../AntTweakBar/lib/libAntTweakBar.so | Bin 0 -> 380940 bytes .../AntTweakBar/lib/libAntTweakBar.so.ldd | 4 + .../CDTestFramework/AntTweakBar/src/AntPerfTimer.h | 58 + .../CDTestFramework/AntTweakBar/src/AntTweakBar.rc | 83 + .../AntTweakBar/src/AntTweakBar.sln | 29 + .../AntTweakBar/src/AntTweakBar.vcproj | 380 + Extras/CDTestFramework/AntTweakBar/src/LoadOGL.cpp | 498 + Extras/CDTestFramework/AntTweakBar/src/LoadOGL.h | 393 + Extras/CDTestFramework/AntTweakBar/src/Makefile | 98 + .../AntTweakBar/src/Makefile.x86_64 | 97 + Extras/CDTestFramework/AntTweakBar/src/TwBar.cpp | 4841 ++ Extras/CDTestFramework/AntTweakBar/src/TwBar.h | 337 + .../CDTestFramework/AntTweakBar/src/TwColors.cpp | 161 + Extras/CDTestFramework/AntTweakBar/src/TwColors.h | 81 + .../AntTweakBar/src/TwDirect3D9.cpp | 674 + .../CDTestFramework/AntTweakBar/src/TwDirect3D9.h | 77 + .../CDTestFramework/AntTweakBar/src/TwEventGLFW.c | 191 + .../CDTestFramework/AntTweakBar/src/TwEventGLUT.c | 148 + .../CDTestFramework/AntTweakBar/src/TwEventSDL.c | 70 + .../CDTestFramework/AntTweakBar/src/TwEventWin32.c | 188 + Extras/CDTestFramework/AntTweakBar/src/TwFonts.cpp | 3935 + Extras/CDTestFramework/AntTweakBar/src/TwFonts.h | 67 + Extras/CDTestFramework/AntTweakBar/src/TwGraph.h | 54 + Extras/CDTestFramework/AntTweakBar/src/TwMgr.cpp | 3265 + Extras/CDTestFramework/AntTweakBar/src/TwMgr.h | 309 + .../CDTestFramework/AntTweakBar/src/TwOpenGL.cpp | 574 + Extras/CDTestFramework/AntTweakBar/src/TwOpenGL.h | 72 + .../CDTestFramework/AntTweakBar/src/TwPrecomp.cpp | 1 + Extras/CDTestFramework/AntTweakBar/src/TwPrecomp.h | 65 + .../AntTweakBar/src/res/FontChars.txt | 232 + .../AntTweakBar/src/res/FontLargeAA.pgm | 1197 + .../AntTweakBar/src/res/FontNormal.pgm | 895 + .../AntTweakBar/src/res/FontNormalAA.pgm | 1012 + .../AntTweakBar/src/res/FontSmall.pgm | 603 + .../AntTweakBar/src/res/TwXCursors.h | 909 + .../AntTweakBar/src/res/cur00000.cur | Bin 0 -> 326 bytes .../AntTweakBar/src/res/cur00001.cur | Bin 0 -> 326 bytes .../AntTweakBar/src/res/cur00002.cur | Bin 0 -> 326 bytes .../AntTweakBar/src/res/cur00003.cur | Bin 0 -> 326 bytes .../AntTweakBar/src/res/cur00004.cur | Bin 0 -> 326 bytes .../AntTweakBar/src/res/cur00005.cur | Bin 0 -> 326 bytes .../AntTweakBar/src/res/cur00006.cur | Bin 0 -> 326 bytes .../AntTweakBar/src/res/cur00007.cur | Bin 0 -> 326 bytes .../AntTweakBar/src/res/cur00008.cur | Bin 0 -> 326 bytes .../AntTweakBar/src/res/cur00009.cur | Bin 0 -> 326 bytes .../AntTweakBar/src/res/cur00010.cur | Bin 0 -> 326 bytes .../AntTweakBar/src/res/cur00011.cur | Bin 0 -> 326 bytes .../AntTweakBar/src/res/cur00012.cur | Bin 0 -> 326 bytes .../AntTweakBar/src/res/cur00013.cur | Bin 0 -> 326 bytes .../CDTestFramework/AntTweakBar/src/res/curs00.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/curs01.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/curs02.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/curs03.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/curs04.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/curs05.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/curs06.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/curs07.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/curs08.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/curs09.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/curs10.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/curs11.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/curs12.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/curs13.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/mask00.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/mask01.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/mask02.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/mask03.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/mask04.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/mask05.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/mask06.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/mask07.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/mask08.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/mask09.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/mask10.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/mask11.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/mask12.pbm | 32 + .../CDTestFramework/AntTweakBar/src/res/mask13.pbm | 32 + Extras/CDTestFramework/AntTweakBar/src/resource.h | 29 + Extras/CDTestFramework/Bin/AntTweakBar.dll | Bin 0 -> 315392 bytes Extras/CDTestFramework/Bin/Opcode.dll | Bin 0 -> 438272 bytes Extras/CDTestFramework/BipartiteBoxPruning.cpp | 165 + Extras/CDTestFramework/BipartiteBoxPruning.h | 51 + .../BulletSAPCompleteBoxPruningTest.cpp | 1069 + .../BulletSAPCompleteBoxPruningTest.h | 65 + Extras/CDTestFramework/CDTestFramework.cpp | 444 + Extras/CDTestFramework/CDTestFramework.h | 20 + Extras/CDTestFramework/CDTestFramework.sln | 96 + Extras/CDTestFramework/CDTestFramework.txt | 31 + Extras/CDTestFramework/CDTestFramework.vcproj | 363 + Extras/CDTestFramework/Camera.cpp | 156 + Extras/CDTestFramework/Camera.h | 32 + Extras/CDTestFramework/CapsuleMeshQuery.cpp | 127 + Extras/CDTestFramework/CapsuleMeshQuery.h | 49 + Extras/CDTestFramework/CollisionTest.cpp | 38 + Extras/CDTestFramework/CollisionTest.h | 50 + Extras/CDTestFramework/CompleteBoxPruning.cpp | 168 + Extras/CDTestFramework/CompleteBoxPruning.h | 53 + Extras/CDTestFramework/GLFontData.h | 1047 + Extras/CDTestFramework/GLFontRenderer.cpp | 207 + Extras/CDTestFramework/GLFontRenderer.h | 37 + Extras/CDTestFramework/GLUT32.DLL | Bin 0 -> 237568 bytes Extras/CDTestFramework/History.txt | 11 + Extras/CDTestFramework/IceHelpers.cpp | 358 + Extras/CDTestFramework/IceHelpers.h | 41 + Extras/CDTestFramework/License.txt | 49 + Extras/CDTestFramework/License.txt.bak | 0 Extras/CDTestFramework/OBBMeshQuery.cpp | 157 + Extras/CDTestFramework/OBBMeshQuery.h | 53 + Extras/CDTestFramework/Opcode/Ice/IceAABB.cpp | 422 + Extras/CDTestFramework/Opcode/Ice/IceAABB.h | 514 + Extras/CDTestFramework/Opcode/Ice/IceAllocator.cpp | 805 + Extras/CDTestFramework/Opcode/Ice/IceAllocator.h | 52 + Extras/CDTestFramework/Opcode/Ice/IceAssert.h | 48 + Extras/CDTestFramework/Opcode/Ice/IceAxes.h | 70 + Extras/CDTestFramework/Opcode/Ice/IceBitArray.cpp | 73 + Extras/CDTestFramework/Opcode/Ice/IceBitArray.h | 82 + .../CDTestFramework/Opcode/Ice/IceBoundingSphere.h | 158 + Extras/CDTestFramework/Opcode/Ice/IceContainer.cpp | 423 + Extras/CDTestFramework/Opcode/Ice/IceContainer.h | 254 + Extras/CDTestFramework/Opcode/Ice/IceFPU.h | 403 + Extras/CDTestFramework/Opcode/Ice/IceHPoint.cpp | 87 + Extras/CDTestFramework/Opcode/Ice/IceHPoint.h | 173 + Extras/CDTestFramework/Opcode/Ice/IceHashing.h | 78 + .../Opcode/Ice/IceIndexedTriangle.cpp | 564 + .../Opcode/Ice/IceIndexedTriangle.h | 84 + Extras/CDTestFramework/Opcode/Ice/IceLSS.h | 91 + Extras/CDTestFramework/Opcode/Ice/IceMatrix3x3.cpp | 64 + Extras/CDTestFramework/Opcode/Ice/IceMatrix3x3.h | 512 + Extras/CDTestFramework/Opcode/Ice/IceMatrix4x4.cpp | 152 + Extras/CDTestFramework/Opcode/Ice/IceMatrix4x4.h | 471 + .../CDTestFramework/Opcode/Ice/IceMemoryMacros.h | 180 + Extras/CDTestFramework/Opcode/Ice/IceOBB.cpp | 339 + Extras/CDTestFramework/Opcode/Ice/IceOBB.h | 193 + Extras/CDTestFramework/Opcode/Ice/IcePairs.h | 61 + Extras/CDTestFramework/Opcode/Ice/IcePlane.cpp | 61 + Extras/CDTestFramework/Opcode/Ice/IcePlane.h | 129 + Extras/CDTestFramework/Opcode/Ice/IcePoint.cpp | 209 + Extras/CDTestFramework/Opcode/Ice/IcePoint.h | 544 + .../CDTestFramework/Opcode/Ice/IcePreprocessor.h | 158 + Extras/CDTestFramework/Opcode/Ice/IceRandom.cpp | 52 + Extras/CDTestFramework/Opcode/Ice/IceRandom.h | 58 + Extras/CDTestFramework/Opcode/Ice/IceRay.cpp | 100 + Extras/CDTestFramework/Opcode/Ice/IceRay.h | 114 + .../Opcode/Ice/IceRevisitedRadix.cpp | 592 + .../CDTestFramework/Opcode/Ice/IceRevisitedRadix.h | 74 + Extras/CDTestFramework/Opcode/Ice/IceSegment.cpp | 73 + Extras/CDTestFramework/Opcode/Ice/IceSegment.h | 71 + Extras/CDTestFramework/Opcode/Ice/IceTriangle.cpp | 302 + Extras/CDTestFramework/Opcode/Ice/IceTriangle.h | 84 + Extras/CDTestFramework/Opcode/Ice/IceTrilist.h | 77 + Extras/CDTestFramework/Opcode/Ice/IceTypes.h | 181 + Extras/CDTestFramework/Opcode/Ice/IceUtils.cpp | 55 + Extras/CDTestFramework/Opcode/Ice/IceUtils.h | 377 + Extras/CDTestFramework/Opcode/Ice/_IceAABB.h | 522 + .../CDTestFramework/Opcode/Ice/_IceContainer.cpp | 361 + Extras/CDTestFramework/Opcode/Ice/_IceContainer.h | 228 + Extras/CDTestFramework/Opcode/Ice/_IceFPU.h | 333 + .../CDTestFramework/Opcode/Ice/_IceMemoryMacros.h | 121 + .../CDTestFramework/Opcode/Ice/_IcePreprocessor.h | 144 + .../Opcode/Ice/_IceRevisitedRadix.cpp | 536 + .../Opcode/Ice/_IceRevisitedRadix.h | 81 + Extras/CDTestFramework/Opcode/Ice/_IceTypes.h | 173 + Extras/CDTestFramework/Opcode/Ice/_IceUtils.h | 272 + Extras/CDTestFramework/Opcode/OPC_AABBCollider.cpp | 705 + Extras/CDTestFramework/Opcode/OPC_AABBCollider.h | 106 + Extras/CDTestFramework/Opcode/OPC_AABBTree.cpp | 582 + Extras/CDTestFramework/Opcode/OPC_AABBTree.h | 146 + Extras/CDTestFramework/Opcode/OPC_ArraySAP.cpp | 1228 + Extras/CDTestFramework/Opcode/OPC_ArraySAP.h | 159 + Extras/CDTestFramework/Opcode/OPC_BaseModel.cpp | 147 + Extras/CDTestFramework/Opcode/OPC_BaseModel.h | 184 + Extras/CDTestFramework/Opcode/OPC_BoxBoxOverlap.h | 139 + Extras/CDTestFramework/Opcode/OPC_BoxPruning.cpp | 376 + Extras/CDTestFramework/Opcode/OPC_BoxPruning.h | 40 + Extras/CDTestFramework/Opcode/OPC_Collider.cpp | 63 + Extras/CDTestFramework/Opcode/OPC_Collider.h | 185 + Extras/CDTestFramework/Opcode/OPC_Common.cpp | 57 + Extras/CDTestFramework/Opcode/OPC_Common.h | 110 + Extras/CDTestFramework/Opcode/OPC_HybridModel.cpp | 475 + Extras/CDTestFramework/Opcode/OPC_HybridModel.h | 115 + Extras/CDTestFramework/Opcode/OPC_IceHook.h | 92 + Extras/CDTestFramework/Opcode/OPC_LSSAABBOverlap.h | 539 + Extras/CDTestFramework/Opcode/OPC_LSSCollider.cpp | 734 + Extras/CDTestFramework/Opcode/OPC_LSSCollider.h | 108 + Extras/CDTestFramework/Opcode/OPC_LSSTriOverlap.h | 696 + .../CDTestFramework/Opcode/OPC_MeshInterface.cpp | 308 + Extras/CDTestFramework/Opcode/OPC_MeshInterface.h | 191 + Extras/CDTestFramework/Opcode/OPC_Model.cpp | 231 + Extras/CDTestFramework/Opcode/OPC_Model.h | 74 + Extras/CDTestFramework/Opcode/OPC_OBBCollider.cpp | 776 + Extras/CDTestFramework/Opcode/OPC_OBBCollider.h | 151 + .../CDTestFramework/Opcode/OPC_OptimizedTree.cpp | 791 + Extras/CDTestFramework/Opcode/OPC_OptimizedTree.h | 215 + Extras/CDTestFramework/Opcode/OPC_Picking.cpp | 191 + Extras/CDTestFramework/Opcode/OPC_Picking.h | 54 + .../CDTestFramework/Opcode/OPC_PlanesAABBOverlap.h | 67 + .../CDTestFramework/Opcode/OPC_PlanesCollider.cpp | 662 + Extras/CDTestFramework/Opcode/OPC_PlanesCollider.h | 130 + .../CDTestFramework/Opcode/OPC_PlanesTriOverlap.h | 57 + Extras/CDTestFramework/Opcode/OPC_RayAABBOverlap.h | 81 + Extras/CDTestFramework/Opcode/OPC_RayCollider.cpp | 771 + Extras/CDTestFramework/Opcode/OPC_RayCollider.h | 234 + Extras/CDTestFramework/Opcode/OPC_RayTriOverlap.h | 106 + Extras/CDTestFramework/Opcode/OPC_Settings.h | 58 + .../CDTestFramework/Opcode/OPC_SphereAABBOverlap.h | 145 + .../CDTestFramework/Opcode/OPC_SphereCollider.cpp | 735 + Extras/CDTestFramework/Opcode/OPC_SphereCollider.h | 105 + .../CDTestFramework/Opcode/OPC_SphereTriOverlap.h | 203 + .../CDTestFramework/Opcode/OPC_SweepAndPrune.cpp | 673 + Extras/CDTestFramework/Opcode/OPC_SweepAndPrune.h | 95 + Extras/CDTestFramework/Opcode/OPC_TreeBuilders.cpp | 264 + Extras/CDTestFramework/Opcode/OPC_TreeBuilders.h | 182 + Extras/CDTestFramework/Opcode/OPC_TreeCollider.cpp | 952 + Extras/CDTestFramework/Opcode/OPC_TreeCollider.h | 253 + Extras/CDTestFramework/Opcode/OPC_TriBoxOverlap.h | 356 + Extras/CDTestFramework/Opcode/OPC_TriTriOverlap.h | 295 + .../CDTestFramework/Opcode/OPC_VolumeCollider.cpp | 112 + Extras/CDTestFramework/Opcode/OPC_VolumeCollider.h | 147 + Extras/CDTestFramework/Opcode/Opcode.cpp | 74 + Extras/CDTestFramework/Opcode/Opcode.dsp | 517 + Extras/CDTestFramework/Opcode/Opcode.dsw | 29 + Extras/CDTestFramework/Opcode/Opcode.h | 99 + Extras/CDTestFramework/Opcode/Opcode.sln | 21 + Extras/CDTestFramework/Opcode/Opcode.vcproj | 1416 + Extras/CDTestFramework/Opcode/ReadMe.txt | 188 + Extras/CDTestFramework/Opcode/StdAfx.cpp | 19 + Extras/CDTestFramework/Opcode/StdAfx.h | 33 + Extras/CDTestFramework/OpcodeArraySAPTest.cpp | 215 + Extras/CDTestFramework/OpcodeArraySAPTest.h | 52 + Extras/CDTestFramework/Profiling.h | 102 + Extras/CDTestFramework/ReadMe.txt | 22 + Extras/CDTestFramework/RenderingHelpers.cpp | 1164 + Extras/CDTestFramework/RenderingHelpers.h | 26 + Extras/CDTestFramework/SphereMeshQuery.cpp | 141 + Extras/CDTestFramework/SphereMeshQuery.h | 48 + Extras/CDTestFramework/Terrain.cpp | 470 + Extras/CDTestFramework/Terrain.h | 47 + Extras/CDTestFramework/convex1.bin | Bin 0 -> 2924 bytes Extras/CDTestFramework/stdafx.cpp | 23 + Extras/CDTestFramework/stdafx.h | 23 + Extras/CMakeLists.txt | 7 + Extras/CUDA/btCudaBroadphase.cpp | 207 + Extras/CUDA/btCudaBroadphase.cu | 74 + Extras/CUDA/btCudaBroadphase.h | 69 + Extras/CUDA/btCudaDefines.h | 138 + Extras/CUDA/btCudaUtils.cu | 84 + Extras/CUDA/btGpuDemo2dCudaFunc.cu | 42 + Extras/CUDA/btGpuDemo3dCudaFunc.cu | 46 + Extras/CUDA/cutil_gl_error.h | 86 + Extras/CUDA/cutil_math.h | 767 + Extras/CUDA/libbulletcuda.vcproj | 665 + Extras/CUDA/radixsort.cu | 79 + Extras/CUDA/radixsort.cuh | 63 + Extras/CUDA/radixsort_kernel.cu | 577 + Extras/ConvexDecomposition/CMakeLists.txt | 64 + Extras/ConvexDecomposition/ConvexBuilder.cpp | 373 + Extras/ConvexDecomposition/ConvexBuilder.h | 112 + Extras/ConvexDecomposition/ConvexDecomposition.cpp | 375 + Extras/ConvexDecomposition/ConvexDecomposition.h | 220 + Extras/ConvexDecomposition/bestfit.cpp | 466 + Extras/ConvexDecomposition/bestfit.h | 65 + Extras/ConvexDecomposition/bestfitobb.cpp | 173 + Extras/ConvexDecomposition/bestfitobb.h | 43 + Extras/ConvexDecomposition/cd_hull.cpp | 3261 + Extras/ConvexDecomposition/cd_hull.h | 153 + Extras/ConvexDecomposition/cd_vector.h | 1185 + Extras/ConvexDecomposition/cd_wavefront.cpp | 860 + Extras/ConvexDecomposition/cd_wavefront.h | 62 + Extras/ConvexDecomposition/concavity.cpp | 795 + Extras/ConvexDecomposition/concavity.h | 60 + Extras/ConvexDecomposition/fitsphere.cpp | 202 + Extras/ConvexDecomposition/fitsphere.h | 43 + Extras/ConvexDecomposition/float_math.cpp | 257 + Extras/ConvexDecomposition/float_math.h | 72 + Extras/ConvexDecomposition/meshvolume.cpp | 128 + Extras/ConvexDecomposition/meshvolume.h | 45 + Extras/ConvexDecomposition/planetri.cpp | 238 + Extras/ConvexDecomposition/planetri.h | 58 + Extras/ConvexDecomposition/premake4.lua | 9 + Extras/ConvexDecomposition/raytri.cpp | 134 + Extras/ConvexDecomposition/raytri.h | 45 + Extras/ConvexDecomposition/splitplane.cpp | 306 + Extras/ConvexDecomposition/splitplane.h | 59 + Extras/ConvexDecomposition/vlookup.cpp | 326 + Extras/ConvexDecomposition/vlookup.h | 119 + Extras/GIMPACTUtils/CMakeLists.txt | 37 + .../btGImpactConvexDecompositionShape.cpp | 240 + .../btGImpactConvexDecompositionShape.h | 87 + Extras/HACD/CMakeLists.txt | 51 + Extras/HACD/hacdCircularList.h | 80 + Extras/HACD/hacdCircularList.inl | 163 + Extras/HACD/hacdGraph.cpp | 292 + Extras/HACD/hacdGraph.h | 120 + Extras/HACD/hacdHACD.cpp | 847 + Extras/HACD/hacdHACD.h | 282 + Extras/HACD/hacdICHull.cpp | 1010 + Extras/HACD/hacdICHull.h | 120 + Extras/HACD/hacdManifoldMesh.cpp | 577 + Extras/HACD/hacdManifoldMesh.h | 250 + Extras/HACD/hacdVector.h | 67 + Extras/HACD/hacdVector.inl | 178 + Extras/HACD/hacdVersion.h | 20 + Extras/HACD/premake4.lua | 9 + Extras/Makefile.am | 95 + Extras/PhysicsEffects/CMakeLists.txt | 344 + Extras/PhysicsEffects/README_Android.txt | 41 + Extras/PhysicsEffects/build/premake4.lua | 40 + Extras/PhysicsEffects/build/vs2008.bat | 3 + Extras/PhysicsEffects/build/vs2010.bat | 3 + .../btBulletPhysicsEffectsWorld.cpp | 479 + .../btBulletPhysicsEffectsWorld.h | 79 + .../BulletPhysicsEffects/btLowLevelBroadphase.cpp | 431 + .../BulletPhysicsEffects/btLowLevelBroadphase.h | 182 + .../btLowLevelCollisionDispatcher.cpp | Bin 0 -> 17292 bytes .../btLowLevelCollisionDispatcher.h | 127 + .../btLowLevelConstraintSolver.cpp | 1410 + .../btLowLevelConstraintSolver.h | 130 + .../btLowLevelConstraintSolver2.cpp | 190 + .../btLowLevelConstraintSolver2.h | 55 + .../BulletPhysicsEffects/btLowLevelData.cpp | 0 .../include/BulletPhysicsEffects/btLowLevelData.h | Bin 0 -> 4304 bytes Extras/PhysicsEffects/include/physics_effects.h | 23 + .../physics_effects/base_level/base/pfx_common.h | 181 + .../base_level/base/pfx_error_code.h | 30 + .../base_level/base/pfx_heap_manager.h | 141 + .../base_level/base/pfx_perf_counter.h | 168 + .../physics_effects/base_level/base/pfx_vec_int3.h | 166 + .../base_level/base/pfx_vec_utils.h | 181 + .../base_level/base/pfx_vectormath_include.h | 101 + .../base_level/base/pfx_vectormath_include.win32.h | 116 + .../base_level/broadphase/pfx_broadphase_pair.h | 46 + .../base_level/broadphase/pfx_broadphase_proxy.h | 42 + .../broadphase/pfx_update_broadphase_proxy.h | 80 + .../base_level/collision/pfx_aabb.h | 124 + .../physics_effects/base_level/collision/pfx_box.h | 61 + .../base_level/collision/pfx_capsule.h | 53 + .../base_level/collision/pfx_collidable.h | 74 + .../collision/pfx_collidable_implementation.h | 114 + .../base_level/collision/pfx_contact_manifold.h | 135 + .../base_level/collision/pfx_cylinder.h | 53 + .../base_level/collision/pfx_large_tri_mesh.h | 122 + .../physics_effects/base_level/collision/pfx_ray.h | 59 + .../base_level/collision/pfx_shape.h | 118 + .../collision/pfx_shape_implementation.h | 145 + .../base_level/collision/pfx_shape_iterator.h | 58 + .../base_level/collision/pfx_sphere.h | 49 + .../base_level/collision/pfx_sub_data.h | 63 + .../base_level/collision/pfx_tri_mesh.h | 154 + .../base_level/pfx_base_level_include.h | 50 + .../base_level/rigidbody/pfx_rigid_body.h | 71 + .../base_level/rigidbody/pfx_rigid_state.h | 196 + .../base_level/solver/pfx_constraint_pair.h | 39 + .../base_level/solver/pfx_constraint_row.h | 40 + .../base_level/solver/pfx_contact_constraint.h | 59 + .../base_level/solver/pfx_integrate.h | 121 + .../physics_effects/base_level/solver/pfx_joint.h | 90 + .../base_level/solver/pfx_joint_ball.h | 62 + .../base_level/solver/pfx_joint_constraint.h | 67 + .../base_level/solver/pfx_joint_fix.h | 49 + .../base_level/solver/pfx_joint_hinge.h | 56 + .../base_level/solver/pfx_joint_slider.h | 57 + .../base_level/solver/pfx_joint_swing_twist.h | 70 + .../base_level/solver/pfx_joint_universal.h | 65 + .../base_level/solver/pfx_solver_body.h | 37 + .../physics_effects/base_level/sort/pfx_sort.h | 33 + .../base_level/sort/pfx_sort_data.h | 82 + .../low_level/broadphase/pfx_broadphase.h | 124 + .../low_level/collision/pfx_batched_ray_cast.h | 38 + .../low_level/collision/pfx_collision_detection.h | 48 + .../low_level/collision/pfx_island_generation.h | 78 + .../low_level/collision/pfx_ray_cast.h | 50 + .../low_level/collision/pfx_refresh_contacts.h | 46 + .../low_level/pfx_low_level_include.h | 46 + .../low_level/solver/pfx_constraint_solver.h | 123 + .../low_level/solver/pfx_joint_constraint_func.h | 69 + .../low_level/solver/pfx_update_rigid_states.h | 45 + .../low_level/sort/pfx_parallel_sort.h | 40 + .../physics_effects/low_level/task/pfx_pthreads.h | 55 + .../low_level/task/pfx_sync_components.h | 53 + .../low_level/task/pfx_task_manager.h | 96 + .../include/physics_effects/util/pfx_mass.h | 60 + .../physics_effects/util/pfx_mesh_creator.h | 96 + .../physics_effects/util/pfx_util_include.h | 26 + .../include/vecmath/neon/boolInVec.h | 238 + .../include/vecmath/neon/floatInVec.h | 357 + .../PhysicsEffects/include/vecmath/neon/mat_aos.h | 1645 + .../PhysicsEffects/include/vecmath/neon/quat_aos.h | 446 + .../PhysicsEffects/include/vecmath/neon/vec_aos.h | 1526 + .../include/vecmath/neon/vectormath_aos.h | 1893 + .../vectormath_neon_assembly_implementations.S | 310 + .../neon/vectormath_neon_assembly_prototypes.h | 57 + .../PhysicsEffects/include/vecmath/sse/boolInVec.h | 247 + .../include/vecmath/sse/floatInVec.h | 340 + .../PhysicsEffects/include/vecmath/sse/mat_aos.h | 2190 + .../PhysicsEffects/include/vecmath/sse/quat_aos.h | 579 + .../PhysicsEffects/include/vecmath/sse/vec_aos.h | 1455 + .../include/vecmath/sse/vecidx_aos.h | 80 + .../include/vecmath/sse/vectormath_aos.h | 2547 + .../PhysicsEffects/include/vecmath/std/boolInVec.h | 238 + .../include/vecmath/std/floatInVec.h | 357 + .../PhysicsEffects/include/vecmath/std/mat_aos.h | 1643 + .../PhysicsEffects/include/vecmath/std/quat_aos.h | 446 + .../PhysicsEffects/include/vecmath/std/vec_aos.h | 1439 + .../include/vecmath/std/vectormath_aos.h | 1885 + Extras/PhysicsEffects/physics_effects_license.txt | 10 + .../project/Android/PfxApp_1_Simple/.classpath | 35 + .../project/Android/PfxApp_1_Simple/.cproject | 239 + .../BuildSampleJNICode.launch | 41 + .../project/Android/PfxApp_1_Simple/.project | 114 + .../Android/PfxApp_1_Simple/AndroidManifest.xml | 44 + .../project/Android/PfxApp_1_Simple/build.xml | 79 + .../Android/PfxApp_1_Simple/default.properties | 11 + .../project/Android/PfxApp_1_Simple/jni/Android.mk | 138 + .../Android/PfxApp_1_Simple/jni/Application.mk | 31 + .../Android/PfxApp_1_Simple/local.properties | 10 + .../project/Android/PfxApp_1_Simple/proguard.cfg | 36 + .../PfxApp_1_Simple/res/drawable-hdpi/icon.png | Bin 0 -> 2472 bytes .../PfxApp_1_Simple/res/drawable-ldpi/icon.png | Bin 0 -> 1117 bytes .../PfxApp_1_Simple/res/drawable-mdpi/icon.png | Bin 0 -> 1511 bytes .../Android/PfxApp_1_Simple/res/layout/main.xml | 34 + .../Android/PfxApp_1_Simple/res/values/strings.xml | 31 + .../PhysicsEffectsGLSurfaceView.java | 113 + .../renderingsupport/PhysicsEffectsRenderer.java | 101 + .../src/pfx/sample1/PfxApp_1_Simple.java | 64 + .../Android/PfxApp_1_Simple_Parallel/.classpath | 35 + .../Android/PfxApp_1_Simple_Parallel/.cproject | 240 + .../BuildSampleJNICode.launch | 41 + .../Android/PfxApp_1_Simple_Parallel/.project | 114 + .../PfxApp_1_Simple_Parallel/AndroidManifest.xml | 44 + .../Android/PfxApp_1_Simple_Parallel/build.xml | 79 + .../PfxApp_1_Simple_Parallel/default.properties | 11 + .../PfxApp_1_Simple_Parallel/jni/Android.mk | 109 + .../PfxApp_1_Simple_Parallel/jni/Application.mk | 31 + .../PfxApp_1_Simple_Parallel/local.properties | 10 + .../Android/PfxApp_1_Simple_Parallel/proguard.cfg | 36 + .../res/drawable-hdpi/icon.png | Bin 0 -> 2472 bytes .../res/drawable-ldpi/icon.png | Bin 0 -> 1117 bytes .../res/drawable-mdpi/icon.png | Bin 0 -> 1511 bytes .../PfxApp_1_Simple_Parallel/res/layout/main.xml | 34 + .../res/values/strings.xml | 31 + .../PhysicsEffectsGLSurfaceView.java | 113 + .../renderingsupport/PhysicsEffectsRenderer.java | 101 + .../src/pfx/sample1b/PfxApp_1_Simple_Parallel.java | 64 + .../project/Android/PfxApp_2_Stable/.classpath | 35 + .../BuildSampleJNICode.launch | 41 + .../project/Android/PfxApp_2_Stable/.project | 114 + .../Android/PfxApp_2_Stable/AndroidManifest.xml | 40 + .../project/Android/PfxApp_2_Stable/build.xml | 79 + .../Android/PfxApp_2_Stable/default.properties | 11 + .../project/Android/PfxApp_2_Stable/jni/Android.mk | 107 + .../Android/PfxApp_2_Stable/jni/Application.mk | 31 + .../Android/PfxApp_2_Stable/local.properties | 10 + .../project/Android/PfxApp_2_Stable/proguard.cfg | 36 + .../PfxApp_2_Stable/res/drawable-hdpi/icon.png | Bin 0 -> 2472 bytes .../PfxApp_2_Stable/res/drawable-ldpi/icon.png | Bin 0 -> 1117 bytes .../PfxApp_2_Stable/res/drawable-mdpi/icon.png | Bin 0 -> 1511 bytes .../Android/PfxApp_2_Stable/res/layout/main.xml | 34 + .../Android/PfxApp_2_Stable/res/values/strings.xml | 31 + .../PhysicsEffectsGLSurfaceView.java | 113 + .../renderingsupport/PhysicsEffectsRenderer.java | 101 + .../src/pfx/sample2/PfxApp_2_Stable.java | 58 + .../Android/PfxApp_2_Stable_Parallel/.classpath | 35 + .../BuildSampleJNICode.launch | 41 + .../Android/PfxApp_2_Stable_Parallel/.project | 114 + .../PfxApp_2_Stable_Parallel/AndroidManifest.xml | 40 + .../Android/PfxApp_2_Stable_Parallel/build.xml | 79 + .../PfxApp_2_Stable_Parallel/default.properties | 11 + .../PfxApp_2_Stable_Parallel/jni/Android.mk | 107 + .../PfxApp_2_Stable_Parallel/jni/Application.mk | 31 + .../PfxApp_2_Stable_Parallel/local.properties | 10 + .../Android/PfxApp_2_Stable_Parallel/proguard.cfg | 36 + .../res/drawable-hdpi/icon.png | Bin 0 -> 2472 bytes .../res/drawable-ldpi/icon.png | Bin 0 -> 1117 bytes .../res/drawable-mdpi/icon.png | Bin 0 -> 1511 bytes .../PfxApp_2_Stable_Parallel/res/layout/main.xml | 34 + .../res/values/strings.xml | 31 + .../PhysicsEffectsGLSurfaceView.java | 113 + .../renderingsupport/PhysicsEffectsRenderer.java | 101 + .../src/pfx/sample2b/PfxApp_2_Stable_Parallel.java | 58 + .../project/Android/PfxApp_3_Sleep/.classpath | 35 + .../BuildSampleJNICode.launch | 41 + .../project/Android/PfxApp_3_Sleep/.project | 114 + .../Android/PfxApp_3_Sleep/AndroidManifest.xml | 40 + .../project/Android/PfxApp_3_Sleep/build.xml | 79 + .../Android/PfxApp_3_Sleep/default.properties | 11 + .../project/Android/PfxApp_3_Sleep/jni/Android.mk | 107 + .../Android/PfxApp_3_Sleep/jni/Application.mk | 31 + .../Android/PfxApp_3_Sleep/local.properties | 10 + .../project/Android/PfxApp_3_Sleep/proguard.cfg | 36 + .../PfxApp_3_Sleep/res/drawable-hdpi/icon.png | Bin 0 -> 2472 bytes .../PfxApp_3_Sleep/res/drawable-ldpi/icon.png | Bin 0 -> 1117 bytes .../PfxApp_3_Sleep/res/drawable-mdpi/icon.png | Bin 0 -> 1511 bytes .../Android/PfxApp_3_Sleep/res/layout/main.xml | 34 + .../Android/PfxApp_3_Sleep/res/values/strings.xml | 31 + .../PhysicsEffectsGLSurfaceView.java | 113 + .../renderingsupport/PhysicsEffectsRenderer.java | 101 + .../src/pfx/sample3/PfxApp_3_Sleep.java | 58 + .../project/Android/PfxApp_4_MotionType/.classpath | 35 + .../BuildSampleJNICode.launch | 41 + .../project/Android/PfxApp_4_MotionType/.project | 114 + .../PfxApp_4_MotionType/AndroidManifest.xml | 40 + .../project/Android/PfxApp_4_MotionType/build.xml | 79 + .../Android/PfxApp_4_MotionType/default.properties | 11 + .../Android/PfxApp_4_MotionType/jni/Android.mk | 107 + .../Android/PfxApp_4_MotionType/jni/Application.mk | 31 + .../Android/PfxApp_4_MotionType/local.properties | 10 + .../Android/PfxApp_4_MotionType/proguard.cfg | 36 + .../PfxApp_4_MotionType/res/drawable-hdpi/icon.png | Bin 0 -> 2472 bytes .../PfxApp_4_MotionType/res/drawable-ldpi/icon.png | Bin 0 -> 1117 bytes .../PfxApp_4_MotionType/res/drawable-mdpi/icon.png | Bin 0 -> 1511 bytes .../PfxApp_4_MotionType/res/layout/main.xml | 34 + .../PfxApp_4_MotionType/res/values/strings.xml | 31 + .../PhysicsEffectsGLSurfaceView.java | 113 + .../renderingsupport/PhysicsEffectsRenderer.java | 101 + .../src/pfx/sample4/PfxApp_4_MotionType.java | 58 + .../project/Android/PfxApp_5_Raycast/.classpath | 35 + .../BuildSampleJNICode.launch | 41 + .../project/Android/PfxApp_5_Raycast/.project | 114 + .../Android/PfxApp_5_Raycast/AndroidManifest.xml | 40 + .../project/Android/PfxApp_5_Raycast/build.xml | 79 + .../Android/PfxApp_5_Raycast/default.properties | 11 + .../Android/PfxApp_5_Raycast/jni/Android.mk | 107 + .../Android/PfxApp_5_Raycast/jni/Application.mk | 31 + .../Android/PfxApp_5_Raycast/local.properties | 10 + .../project/Android/PfxApp_5_Raycast/proguard.cfg | 36 + .../PfxApp_5_Raycast/res/drawable-hdpi/icon.png | Bin 0 -> 2472 bytes .../PfxApp_5_Raycast/res/drawable-ldpi/icon.png | Bin 0 -> 1117 bytes .../PfxApp_5_Raycast/res/drawable-mdpi/icon.png | Bin 0 -> 1511 bytes .../Android/PfxApp_5_Raycast/res/layout/main.xml | 34 + .../PfxApp_5_Raycast/res/values/strings.xml | 31 + .../PhysicsEffectsGLSurfaceView.java | 113 + .../renderingsupport/PhysicsEffectsRenderer.java | 101 + .../src/pfx/sample5/PfxApp_5_Raycast.java | 58 + .../project/Android/PfxApp_6_Joint/.classpath | 35 + .../BuildSampleJNICode.launch | 41 + .../project/Android/PfxApp_6_Joint/.project | 114 + .../Android/PfxApp_6_Joint/AndroidManifest.xml | 40 + .../project/Android/PfxApp_6_Joint/build.xml | 79 + .../Android/PfxApp_6_Joint/default.properties | 11 + .../project/Android/PfxApp_6_Joint/jni/Android.mk | 107 + .../Android/PfxApp_6_Joint/jni/Application.mk | 31 + .../Android/PfxApp_6_Joint/local.properties | 10 + .../project/Android/PfxApp_6_Joint/proguard.cfg | 36 + .../PfxApp_6_Joint/res/drawable-hdpi/icon.png | Bin 0 -> 2472 bytes .../PfxApp_6_Joint/res/drawable-ldpi/icon.png | Bin 0 -> 1117 bytes .../PfxApp_6_Joint/res/drawable-mdpi/icon.png | Bin 0 -> 1511 bytes .../Android/PfxApp_6_Joint/res/layout/main.xml | 34 + .../Android/PfxApp_6_Joint/res/values/strings.xml | 31 + .../PhysicsEffectsGLSurfaceView.java | 113 + .../renderingsupport/PhysicsEffectsRenderer.java | 101 + .../src/pfx/sample6/PfxApp_6_Joint.java | 58 + .../project/Android/PfxLibrary/.cproject | 348 + .../.externalToolBuilders/PfxLibraryBuilder.launch | 41 + .../project/Android/PfxLibrary/.project | 157 + .../project/Android/PfxLibrary/jni/Android.mk | 173 + .../project/Android/PfxLibrary/jni/Application.mk | 31 + .../project/msvc2008_32/BulletCollision.vcproj | 1206 + .../project/msvc2008_32/BulletDynamics.vcproj | 566 + .../project/msvc2008_32/BulletMultiThreaded.vcproj | 558 + .../project/msvc2008_32/BulletSoftBody.vcproj | 298 + .../project/msvc2008_32/LinearMath.vcproj | 478 + .../project/msvc2008_32/MiniCL.vcproj | 268 + .../project/physics_effects_lib.oss.sln | 26 + .../project/physics_effects_lib.oss.vcproj | 1221 + Extras/PhysicsEffects/sample/CMakeLists.txt | 3 + .../api_physics_effects/0_console/CMakeLists.txt | 47 + .../sample/api_physics_effects/0_console/barrel.h | 202 + .../api_physics_effects/0_console/landscape.h | 318 + .../sample/api_physics_effects/0_console/main.cpp | 44 + .../api_physics_effects/0_console/physics_func.cpp | 861 + .../api_physics_effects/0_console/physics_func.h | 49 + .../api_physics_effects/0_console/premake4.lua | 18 + .../1_simple/1_simple.windows.vcproj | 713 + .../api_physics_effects/1_simple/CMakeLists.txt | 77 + .../sample/api_physics_effects/1_simple/barrel.h | 202 + .../api_physics_effects/1_simple/landscape.h | 318 + .../sample/api_physics_effects/1_simple/main.cpp | 495 + .../api_physics_effects/1_simple/physics.png | Bin 0 -> 24116 bytes .../api_physics_effects/1_simple/physics_func.cpp | 769 + .../api_physics_effects/1_simple/physics_func.h | 49 + .../api_physics_effects/1_simple/premake4.lua | 22 + .../api_physics_effects/1_simple_parallel/barrel.h | 202 + .../1_simple_parallel/landscape.h | 318 + .../api_physics_effects/1_simple_parallel/main.cpp | 448 + .../1_simple_parallel/physics_func.cpp | 857 + .../1_simple_parallel/physics_func.h | 49 + .../2_stable/2_stable.winsows.vcproj | 713 + .../api_physics_effects/2_stable/CMakeLists.txt | 77 + .../sample/api_physics_effects/2_stable/barrel.h | 202 + .../api_physics_effects/2_stable/landscape.h | 318 + .../sample/api_physics_effects/2_stable/main.cpp | 448 + .../api_physics_effects/2_stable/physics.png | Bin 0 -> 34719 bytes .../api_physics_effects/2_stable/physics_func.cpp | 869 + .../api_physics_effects/2_stable/physics_func.h | 49 + .../api_physics_effects/2_stable/premake4.lua | 22 + .../api_physics_effects/2_stable_parallel/barrel.h | 202 + .../2_stable_parallel/landscape.h | 318 + .../api_physics_effects/2_stable_parallel/main.cpp | 448 + .../2_stable_parallel/physics_func.cpp | 968 + .../2_stable_parallel/physics_func.h | 49 + .../3_sleep/3_sleep.windows.vcproj | 713 + .../api_physics_effects/3_sleep/CMakeLists.txt | 77 + .../sample/api_physics_effects/3_sleep/barrel.h | 202 + .../sample/api_physics_effects/3_sleep/landscape.h | 318 + .../sample/api_physics_effects/3_sleep/main.cpp | 512 + .../sample/api_physics_effects/3_sleep/physics.png | Bin 0 -> 24292 bytes .../api_physics_effects/3_sleep/physics_func.cpp | 1016 + .../api_physics_effects/3_sleep/physics_func.h | 53 + .../api_physics_effects/3_sleep/premake4.lua | 22 + .../4_motion_type/4_motion_type.windows.vcproj | 721 + .../4_motion_type/CMakeLists.txt | 75 + .../api_physics_effects/4_motion_type/main.cpp | 481 + .../api_physics_effects/4_motion_type/physics.png | Bin 0 -> 16126 bytes .../4_motion_type/physics_func.cpp | 822 + .../4_motion_type/physics_func.h | 53 + .../api_physics_effects/4_motion_type/premake4.lua | 22 + .../5_raycast/5_raycast.windows.vcproj | 721 + .../api_physics_effects/5_raycast/CMakeLists.txt | 77 + .../sample/api_physics_effects/5_raycast/barrel.h | 202 + .../api_physics_effects/5_raycast/landscape.h | 318 + .../sample/api_physics_effects/5_raycast/main.cpp | 544 + .../api_physics_effects/5_raycast/physics.png | Bin 0 -> 38457 bytes .../api_physics_effects/5_raycast/physics_func.cpp | 1085 + .../api_physics_effects/5_raycast/physics_func.h | 58 + .../api_physics_effects/5_raycast/premake4.lua | 22 + .../6_joint/6_joint.windows.vcproj | 713 + .../api_physics_effects/6_joint/CMakeLists.txt | 77 + .../sample/api_physics_effects/6_joint/barrel.h | 202 + .../sample/api_physics_effects/6_joint/landscape.h | 318 + .../sample/api_physics_effects/6_joint/main.cpp | 513 + .../sample/api_physics_effects/6_joint/physics.png | Bin 0 -> 28854 bytes .../api_physics_effects/6_joint/physics_func.cpp | 1641 + .../api_physics_effects/6_joint/physics_func.h | 53 + .../api_physics_effects/6_joint/premake4.lua | 22 + .../99_BulletPhysicsEffects.vcproj | 280 + .../99_bullet_highlevel/CMakeLists.txt | 89 + .../99_bullet_highlevel/barrel.h | 202 + .../99_bullet_highlevel/bullet_physics_func.cpp | 1241 + .../99_bullet_highlevel/landscape.h | 318 + .../99_bullet_highlevel/main.cpp | 485 + .../99_bullet_highlevel/physics_func.h | 49 + .../sample/api_physics_effects/CMakeLists.txt | 16 + .../api_physics_effects.windows.sln | 164 + .../sample/api_physics_effects/common/box.h | 70 + .../sample/api_physics_effects/common/common.h | 31 + .../common/ctrl_func.android.cpp | 57 + .../sample/api_physics_effects/common/ctrl_func.h | 51 + .../api_physics_effects/common/ctrl_func.win32.cpp | 78 + .../sample/api_physics_effects/common/cylinder.h | 154 + .../common/jni/physicseffects-android.cpp | 241 + .../common/jni/physicseffects-android.h | 40 + .../common/perf_func.android.cpp | 38 + .../sample/api_physics_effects/common/perf_func.h | 26 + .../api_physics_effects/common/perf_func.win32.cpp | 38 + .../common/render_func.android.cpp | 486 + .../api_physics_effects/common/render_func.h | 106 + .../common/render_func.win32.cpp | 491 + .../sample/api_physics_effects/common/sphere.h | 209 + .../test_ARM_NEON_performance/neon_cross_product.S | 146 + .../test_ARM_NEON_performance/neon_dot_product.S | 98 + .../neon_matrix3_operator_multiply.S | 62 + .../neon_matrix4_operator_multiply.S | 71 + .../neon_orthoInverse_transform3.S | 81 + .../neon_transform3_operator_multiply.S | 51 + .../neon_transpose_matrix3.S | 81 + .../sample/test_ARM_NEON_performance/test_neon.h | 43 + .../test_neon_cross_product.cpp | 229 + .../test_neon_dot_product.cpp | 330 + .../test_neon_matrix3_operator_multiply.cpp | 173 + .../test_neon_matrix4_operator_multiply.cpp | 188 + .../test_neon_orthoInverse_transform3.cpp | 173 + .../test_neon_solve_linear_constraint_row.cpp | 477 + .../test_neon_transform3_operator_multiply.cpp | 150 + .../test_neon_transpose_matrix3.cpp | 154 + Extras/PhysicsEffects/src/CMakeLists.txt | 11 + .../PhysicsEffects/src/base_level/CMakeLists.txt | 77 + .../base_level/broadphase/pfx_check_collidable.h | 80 + .../broadphase/pfx_update_broadphase_proxy.cpp | 234 + .../src/base_level/collision/pfx_collidable.cpp | 56 + .../base_level/collision/pfx_contact_box_box.cpp | 1106 + .../src/base_level/collision/pfx_contact_box_box.h | 33 + .../collision/pfx_contact_box_capsule.cpp | 608 + .../base_level/collision/pfx_contact_box_capsule.h | 34 + .../collision/pfx_contact_box_sphere.cpp | 236 + .../base_level/collision/pfx_contact_box_sphere.h | 34 + .../src/base_level/collision/pfx_contact_cache.cpp | 164 + .../src/base_level/collision/pfx_contact_cache.h | 100 + .../collision/pfx_contact_capsule_capsule.cpp | 144 + .../collision/pfx_contact_capsule_capsule.h | 34 + .../collision/pfx_contact_capsule_sphere.cpp | 108 + .../collision/pfx_contact_capsule_sphere.h | 34 + .../collision/pfx_contact_large_tri_mesh.cpp | 152 + .../collision/pfx_contact_large_tri_mesh.h | 38 + .../base_level/collision/pfx_contact_manifold.cpp | 234 + .../collision/pfx_contact_sphere_sphere.cpp | 76 + .../collision/pfx_contact_sphere_sphere.h | 33 + .../collision/pfx_contact_tri_mesh_box.cpp | 456 + .../collision/pfx_contact_tri_mesh_box.h | 38 + .../collision/pfx_contact_tri_mesh_capsule.cpp | 570 + .../collision/pfx_contact_tri_mesh_capsule.h | 39 + .../collision/pfx_contact_tri_mesh_convex.cpp | 167 + .../collision/pfx_contact_tri_mesh_convex.h | 37 + .../collision/pfx_contact_tri_mesh_cylinder.cpp | 165 + .../collision/pfx_contact_tri_mesh_cylinder.h | 38 + .../collision/pfx_contact_tri_mesh_sphere.cpp | 239 + .../collision/pfx_contact_tri_mesh_sphere.h | 38 + .../src/base_level/collision/pfx_gjk_solver.cpp | 485 + .../src/base_level/collision/pfx_gjk_solver.h | 190 + .../base_level/collision/pfx_gjk_support_func.cpp | 134 + .../base_level/collision/pfx_gjk_support_func.h | 36 + .../base_level/collision/pfx_intersect_common.h | 427 + .../base_level/collision/pfx_intersect_ray_box.cpp | 47 + .../base_level/collision/pfx_intersect_ray_box.h | 31 + .../collision/pfx_intersect_ray_capsule.cpp | 136 + .../collision/pfx_intersect_ray_capsule.h | 31 + .../collision/pfx_intersect_ray_convex.cpp | 56 + .../collision/pfx_intersect_ray_convex.h | 30 + .../collision/pfx_intersect_ray_cylinder.cpp | 106 + .../collision/pfx_intersect_ray_cylinder.h | 31 + .../collision/pfx_intersect_ray_large_tri_mesh.cpp | 169 + .../collision/pfx_intersect_ray_large_tri_mesh.h | 30 + .../collision/pfx_intersect_ray_sphere.cpp | 55 + .../collision/pfx_intersect_ray_sphere.h | 31 + .../src/base_level/collision/pfx_mesh_common.h | 194 + .../src/base_level/collision/pfx_shape.cpp | 95 + .../base_level/collision/pfx_simplex_solver.cpp | 284 + .../src/base_level/collision/pfx_simplex_solver.h | 153 + Extras/PhysicsEffects/src/base_level/premake4.lua | 12 + .../src/base_level/solver/pfx_check_solver.h | 67 + .../base_level/solver/pfx_constraint_row_solver.h | 296 + .../solver/pfx_constraint_row_solver_neon.cpp | 186 + .../base_level/solver/pfx_contact_constraint.cpp | 194 + .../src/base_level/solver/pfx_joint_ball.cpp | 179 + .../src/base_level/solver/pfx_joint_fix.cpp | 54 + .../src/base_level/solver/pfx_joint_hinge.cpp | 80 + .../src/base_level/solver/pfx_joint_slider.cpp | 78 + .../base_level/solver/pfx_joint_swing_twist.cpp | 268 + .../src/base_level/solver/pfx_joint_universal.cpp | 163 + .../src/base_level/sort/pfx_sort.cpp | 267 + Extras/PhysicsEffects/src/low_level/CMakeLists.txt | 29 + .../low_level/broadphase/pfx_broadphase_single.cpp | 294 + .../collision/pfx_batched_ray_cast_parallel.cpp | 95 + .../collision/pfx_batched_ray_cast_single.cpp | 47 + .../collision/pfx_collision_detection_parallel.cpp | 166 + .../collision/pfx_collision_detection_single.cpp | 125 + .../collision/pfx_detect_collision_func.cpp | 449 + .../collision/pfx_detect_collision_func.h | 37 + .../low_level/collision/pfx_intersect_ray_func.cpp | 129 + .../low_level/collision/pfx_intersect_ray_func.h | 36 + .../low_level/collision/pfx_island_generation.cpp | 231 + .../src/low_level/collision/pfx_ray_cast.cpp | 228 + .../collision/pfx_refresh_contacts_parallel.cpp | 115 + .../collision/pfx_refresh_contacts_single.cpp | 76 + Extras/PhysicsEffects/src/low_level/premake4.lua | 12 + .../solver/pfx_constraint_solver_parallel.cpp | 795 + .../solver/pfx_constraint_solver_single.cpp | 399 + .../low_level/solver/pfx_joint_constraint_func.cpp | 180 + .../src/low_level/solver/pfx_parallel_group.h | 44 + .../solver/pfx_update_rigid_states_parallel.cpp | 94 + .../solver/pfx_update_rigid_states_single.cpp | 51 + .../low_level/sort/pfx_parallel_sort_single.cpp | 56 + .../task/pfx_sync_components_pthreads.cpp | 237 + .../low_level/task/pfx_sync_components_pthreads.h | 93 + .../low_level/task/pfx_task_manager_pthreads.cpp | 311 + Extras/PhysicsEffects/src/util/CMakeLists.txt | 20 + Extras/PhysicsEffects/src/util/pfx_array.h | 187 + .../src/util/pfx_array_implementation.h | 159 + Extras/PhysicsEffects/src/util/pfx_mass.cpp | 102 + .../PhysicsEffects/src/util/pfx_mesh_creator.cpp | 944 + Extras/PhysicsEffects/src/util/pfx_util_common.h | 32 + Extras/PhysicsEffects/src/util/premake4.lua | 12 + Extras/RigidBodyGpuPipeline/bin/glut32.dll | Bin 0 -> 160256 bytes Extras/RigidBodyGpuPipeline/bin/glut64.dll | Bin 0 -> 272896 bytes .../RigidBodyGpuPipeline/build/findDirectX11.lua | 36 + Extras/RigidBodyGpuPipeline/build/findOpenCL.lua | 84 + .../build/findOpenGLGlewGlut.lua | 52 + Extras/RigidBodyGpuPipeline/build/premake4.lua | 55 + Extras/RigidBodyGpuPipeline/build/vs2008.bat | 10 + Extras/RigidBodyGpuPipeline/build/vs2010.bat | 5 + .../dynamics/basic_demo/AMD/premake4.lua | 45 + .../dynamics/basic_demo/BasicDemo.cpp | 538 + .../dynamics/basic_demo/BasicDemo.h | 86 + .../dynamics/basic_demo/ConvexHeightFieldShape.cpp | 507 + .../dynamics/basic_demo/ConvexHeightFieldShape.h | 143 + .../dynamics/basic_demo/CubeMapUtils.h | 111 + .../basic_demo/CustomCollisionDispatcher.cpp | 699 + .../basic_demo/CustomCollisionDispatcher.h | 70 + .../basic_demo/CustomConvexPairCollision.cpp | 409 + .../basic_demo/CustomConvexPairCollision.h | 56 + .../dynamics/basic_demo/CustomConvexShape.cpp | 45 + .../dynamics/basic_demo/CustomConvexShape.h | 35 + .../dynamics/basic_demo/Stubs/AdlAabb.cpp | 0 .../dynamics/basic_demo/Stubs/AdlAabb.h | 230 + .../dynamics/basic_demo/Stubs/AdlArray.h | 212 + .../dynamics/basic_demo/Stubs/AdlCollideUtils.h | 111 + .../dynamics/basic_demo/Stubs/AdlCollisionShape.h | 49 + .../dynamics/basic_demo/Stubs/AdlConstraint4.h | 49 + .../dynamics/basic_demo/Stubs/AdlContact4.h | 102 + .../dynamics/basic_demo/Stubs/AdlError.h | 80 + .../dynamics/basic_demo/Stubs/AdlMath.h | 216 + .../dynamics/basic_demo/Stubs/AdlMatrix3x3.h | 194 + .../dynamics/basic_demo/Stubs/AdlQuaternion.h | 155 + .../dynamics/basic_demo/Stubs/AdlRigidBody.h | 59 + .../dynamics/basic_demo/Stubs/AdlTransform.h | 61 + .../dynamics/basic_demo/Stubs/Adlfloat4.inl | 373 + .../dynamics/basic_demo/Stubs/Adlfloat4SSE.inl | 381 + .../dynamics/basic_demo/Stubs/ChNarrowPhase.h | 154 + .../dynamics/basic_demo/Stubs/ChNarrowphase.inl | 303 + .../basic_demo/Stubs/ChNarrowphaseKernels.cl | 1629 + .../basic_demo/Stubs/ChNarrowphaseKernels.h | 1616 + .../dynamics/basic_demo/Stubs/Solver.h | 203 + .../dynamics/basic_demo/Stubs/Solver.inl | 762 + .../dynamics/basic_demo/Stubs/SolverHost.inl | 848 + .../dynamics/basic_demo/Stubs/SolverKernels.cl | 1051 + .../dynamics/basic_demo/Stubs/SolverKernels.h | 1037 + .../dynamics/basic_demo/Stubs/batchingKernels.cl | 338 + .../dynamics/basic_demo/Stubs/batchingKernels.h | 371 + .../dynamics/basic_demo/Stubs/stringify.py | 13 + .../dynamics/basic_demo/Stubs/stringifykernels.bat | 6 + .../basic_demo/Stubs/stringifykernelsAll.bat | 10 + .../basic_demo/Stubs/stringifykernelsBatching.bat | 8 + .../Stubs/stringifykernelsNarrowphase.bat | 8 + .../basic_demo/Stubs/stringifykernelsSolver.bat | 8 + .../dynamics/basic_demo/main.cpp | 77 + .../dynamics/basic_demo/premake4.lua | 34 + .../dynamics/testbed/DebugCastResult.h | 88 + .../dynamics/testbed/DemoApplication.cpp | 1375 + .../dynamics/testbed/DemoApplication.h | 257 + .../dynamics/testbed/GLDebugDrawer.cpp | 139 + .../dynamics/testbed/GLDebugDrawer.h | 38 + .../dynamics/testbed/GLDebugFont.cpp | 1000 + .../dynamics/testbed/GLDebugFont.h | 29 + .../dynamics/testbed/GL_ShapeDrawer.cpp | 1058 + .../dynamics/testbed/GL_ShapeDrawer.h | 70 + .../dynamics/testbed/GL_Simplex1to4.cpp | 76 + .../dynamics/testbed/GL_Simplex1to4.h | 40 + .../dynamics/testbed/GlutDemoApplication.cpp | 87 + .../dynamics/testbed/GlutDemoApplication.h | 34 + .../dynamics/testbed/GlutStuff.cpp | 119 + .../dynamics/testbed/GlutStuff.h | 86 + .../dynamics/testbed/RenderTexture.cpp | 86 + .../dynamics/testbed/RenderTexture.h | 73 + .../dynamics/testbed/Win32AppMain.cpp | 405 + .../dynamics/testbed/Win32DemoApplication.cpp | 79 + .../dynamics/testbed/Win32DemoApplication.h | 40 + .../dynamics/testbed/premake4.lua | 18 + .../opencl/3dGridBroadphase/AMD/premake4.lua | 29 + .../3dGridBroadphase/MiniCL/MiniCLTaskWrap.cpp | 23 + .../Shared/bt3dGridBroadphaseOCL.cl | 349 + .../Shared/bt3dGridBroadphaseOCL.cpp | 697 + .../Shared/bt3dGridBroadphaseOCL.h | 146 + .../Shared/btGpu3DGridBroadphase.cpp | 626 + .../Shared/btGpu3DGridBroadphase.h | 154 + .../Shared/btGpu3DGridBroadphaseSharedCode.h | 428 + .../Shared/btGpu3DGridBroadphaseSharedDefs.h | 61 + .../Shared/btGpu3DGridBroadphaseSharedTypes.h | 64 + .../opencl/3dGridBroadphase/Shared/btGpuDefines.h | 211 + .../3dGridBroadphase/Shared/btGpuUtilsSharedCode.h | 55 + .../3dGridBroadphase/Shared/btGpuUtilsSharedDefs.h | 52 + .../opencl/3dGridBroadphase/premake4.lua | 5 + .../opencl/basic_initialize/AMD/premake4.lua | 23 + .../opencl/basic_initialize/Intel/premake4.lua | 23 + .../opencl/basic_initialize/NVIDIA/premake4.lua | 23 + .../opencl/basic_initialize/btOpenCLInclude.h | 43 + .../opencl/basic_initialize/btOpenCLUtils.cpp | 731 + .../opencl/basic_initialize/btOpenCLUtils.h | 104 + .../opencl/basic_initialize/main.cpp | 92 + .../opencl/basic_initialize/premake4.lua | 4 + .../opencl/broadphase_benchmark/AMD/premake4.lua | 49 + .../opencl/broadphase_benchmark/Intel/premake4.lua | 49 + .../broadphase_benchmark/NVIDIA/premake4.lua | 49 + .../broadphase_benchmark/broadphaseKernel.cl | 335 + .../broadphase_benchmark/btGridBroadphaseCL.cpp | 231 + .../broadphase_benchmark/btGridBroadphaseCL.h | 73 + .../broadphase_benchmark/computeAabbKernelOCL.cl | 112 + .../broadphase_benchmark/findPairsOpenCL.cpp | 204 + .../opencl/broadphase_benchmark/findPairsOpenCL.h | 90 + .../opencl/broadphase_benchmark/integrateKernel.cl | 116 + .../opencl/broadphase_benchmark/main.cpp | 1565 + .../opencl/broadphase_benchmark/premake4.lua | 5 + .../opencl/global_atomics/AMD/premake4.lua | 23 + .../opencl/global_atomics/globalAtomicsKernel.h | 36 + .../opencl/global_atomics/global_atomics.cl | 34 + .../opencl/global_atomics/main.cpp | 201 + .../opencl/global_atomics/premake4.lua | 4 + .../opencl/global_atomics/stringify.py | 13 + .../opencl/global_atomics/stringifykernels.bat | 5 + .../opencl/gpu_rigidbody_pipeline/AMD/premake4.lua | 58 + .../gpu_rigidbody_pipeline/CommandLineArgs.h | 91 + .../gpu_rigidbody_pipeline/Intel/premake4.lua | 58 + .../gpu_rigidbody_pipeline/NVIDIA/premake4.lua | 57 + .../gpu_rigidbody_pipeline/btConvexUtility.cpp | 240 + .../gpu_rigidbody_pipeline/btConvexUtility.h | 41 + .../btGpuNarrowPhaseAndSolver.cpp | 730 + .../btGpuNarrowPhaseAndSolver.h | 72 + .../opencl/gpu_rigidbody_pipeline/main.cpp | 1775 + .../opencl/gpu_rigidbody_pipeline/premake4.lua | 5 + .../gpu_rigidbody_pipeline2/AMD/premake4.lua | 64 + .../gpu_rigidbody_pipeline2/CLPhysicsDemo.cpp | 529 + .../opencl/gpu_rigidbody_pipeline2/CLPhysicsDemo.h | 53 + .../opencl/gpu_rigidbody_pipeline2/DemoSettings.h | 24 + .../GLInstancingRenderer.cpp | 861 + .../gpu_rigidbody_pipeline2/GLInstancingRenderer.h | 45 + .../gpu_rigidbody_pipeline2/GlutRenderer.cpp | 107 + .../opencl/gpu_rigidbody_pipeline2/GlutRenderer.h | 59 + .../gpu_rigidbody_pipeline2/NVIDIA/premake4.lua | 64 + .../opencl/gpu_rigidbody_pipeline2/OpenGLInclude.h | 41 + .../opencl/gpu_rigidbody_pipeline2/ShapeData.h | 210 + .../Win32OpenGLRenderManager.cpp | 465 + .../Win32OpenGLRenderManager.h | 70 + .../opencl/gpu_rigidbody_pipeline2/main.cpp | 224 + .../opencl/gpu_rigidbody_pipeline2/premake4.lua | 5 + .../opencl/integration/AMD/premake4.lua | 34 + .../opencl/integration/Intel/premake4.lua | 36 + .../opencl/integration/NVIDIA/premake4.lua | 35 + .../opencl/integration/integrateKernel.cl | 73 + .../opencl/integration/main.cpp | 1106 + .../opencl/integration/premake4.lua | 5 + .../opencl/opengl_interop/AMD/premake4.lua | 33 + .../opencl/opengl_interop/Intel/premake4.lua | 34 + .../opencl/opengl_interop/NVIDIA/premake4.lua | 34 + .../opengl_interop/btOpenCLGLInteropBuffer.cpp | 60 + .../opengl_interop/btOpenCLGLInteropBuffer.h | 49 + .../opencl/opengl_interop/btStopwatch.cpp | 182 + .../opencl/opengl_interop/btStopwatch.h | 45 + .../opencl/opengl_interop/interopKernel.cl | 13 + .../opencl/opengl_interop/main.cpp | 1057 + .../opencl/opengl_interop/premake4.lua | 5 + .../opencl/primitives/Adl/Adl.cpp | 19 + .../opencl/primitives/Adl/Adl.h | 235 + .../opencl/primitives/Adl/Adl.inl | 344 + .../opencl/primitives/Adl/AdlConfig.h | 27 + .../opencl/primitives/Adl/AdlError.h | 80 + .../opencl/primitives/Adl/AdlKernel.h | 142 + .../opencl/primitives/Adl/AdlKernel.inl | 223 + .../opencl/primitives/Adl/AdlStopwatch.h | 81 + .../opencl/primitives/Adl/AdlStopwatch.inl | 59 + .../opencl/primitives/Adl/CL/AdlCL.inl | 384 + .../opencl/primitives/Adl/CL/AdlKernelUtilsCL.inl | 541 + .../opencl/primitives/Adl/DX11/AdlDX11.inl | 512 + .../primitives/Adl/DX11/AdlKernelUtilsDX11.inl | 348 + .../primitives/Adl/DX11/AdlStopwatchDX11.inl | 131 + .../opencl/primitives/Adl/Host/AdlHost.inl | 107 + .../primitives/Adl/Host/AdlStopwatchHost.inl | 119 + .../opencl/primitives/AdlPrimitives/Copy/Copy.h | 73 + .../opencl/primitives/AdlPrimitives/Copy/Copy.inl | 151 + .../primitives/AdlPrimitives/Copy/CopyHost.inl | 85 + .../primitives/AdlPrimitives/Copy/CopyKernels.cl | 128 + .../primitives/AdlPrimitives/Copy/CopyKernels.hlsl | 130 + .../primitives/AdlPrimitives/Copy/CopyKernelsCL.h | 119 + .../AdlPrimitives/Copy/CopyKernelsDX11.h | 120 + .../opencl/primitives/AdlPrimitives/Fill/Fill.h | 77 + .../opencl/primitives/AdlPrimitives/Fill/Fill.inl | 123 + .../primitives/AdlPrimitives/Fill/FillHost.inl | 99 + .../primitives/AdlPrimitives/Fill/FillKernels.cl | 81 + .../primitives/AdlPrimitives/Fill/FillKernels.hlsl | 79 + .../primitives/AdlPrimitives/Fill/FillKernelsCL.h | 71 + .../AdlPrimitives/Fill/FillKernelsDX11.h | 69 + .../opencl/primitives/AdlPrimitives/Math/Array.h | 231 + .../primitives/AdlPrimitives/Math/Float2.inl | 173 + .../primitives/AdlPrimitives/Math/Float4.inl | 375 + .../opencl/primitives/AdlPrimitives/Math/Math.h | 224 + .../opencl/primitives/AdlPrimitives/Math/MathCL.h | 357 + .../primitives/AdlPrimitives/Math/Matrix3x3.h | 197 + .../primitives/AdlPrimitives/Math/Quaternion.h | 159 + .../primitives/AdlPrimitives/Scan/PrefixScan.h | 73 + .../primitives/AdlPrimitives/Scan/PrefixScan.inl | 125 + .../AdlPrimitives/Scan/PrefixScanHost.inl | 74 + .../AdlPrimitives/Scan/PrefixScanKernels.cl | 153 + .../AdlPrimitives/Scan/PrefixScanKernels.hlsl | 157 + .../AdlPrimitives/Scan/PrefixScanKernelsCL.h | 143 + .../AdlPrimitives/Scan/PrefixScanKernelsDX11.h | 147 + .../primitives/AdlPrimitives/Search/BoundSearch.h | 73 + .../AdlPrimitives/Search/BoundSearch.inl | 128 + .../AdlPrimitives/Search/BoundSearchHost.inl | 111 + .../AdlPrimitives/Search/BoundSearchKernels.cl | 112 + .../AdlPrimitives/Search/BoundSearchKernels.hlsl | 104 + .../AdlPrimitives/Search/BoundSearchKernelsCL.h | 102 + .../AdlPrimitives/Search/BoundSearchKernelsDX11.h | 94 + .../primitives/AdlPrimitives/Sort/RadixSort.h | 53 + .../primitives/AdlPrimitives/Sort/RadixSort.inl | 58 + .../primitives/AdlPrimitives/Sort/RadixSort32.h | 98 + .../primitives/AdlPrimitives/Sort/RadixSort32.inl | 346 + .../AdlPrimitives/Sort/RadixSort32Host.inl | 163 + .../AdlPrimitives/Sort/RadixSort32Kernels.cl | 1104 + .../AdlPrimitives/Sort/RadixSort32Kernels.hlsl | 1011 + .../AdlPrimitives/Sort/RadixSort32KernelsCL.h | 1106 + .../AdlPrimitives/Sort/RadixSort32KernelsDX11.h | 1013 + .../Sort/RadixSortAdvancedKernels.hlsl | 985 + .../Sort/RadixSortAdvancedKernelsDX11.h | 987 + .../AdlPrimitives/Sort/RadixSortHost.inl | 93 + .../AdlPrimitives/Sort/RadixSortSimpleCL.h | 134 + .../AdlPrimitives/Sort/RadixSortSimpleDX11.h | 131 + .../AdlPrimitives/Sort/RadixSortSimpleKernels.cl | 147 + .../AdlPrimitives/Sort/RadixSortSimpleKernels.hlsl | 133 + .../AdlPrimitives/Sort/RadixSortSimpleKernelsCL.h | 149 + .../Sort/RadixSortSimpleKernelsDX11.h | 135 + .../AdlPrimitives/Sort/RadixSortStandard.inl | 177 + .../AdlPrimitives/Sort/RadixSortStandardKernels.cl | 345 + .../Sort/RadixSortStandardKernels.hlsl | 322 + .../Sort/RadixSortStandardKernelsCL.h | 347 + .../Sort/RadixSortStandardKernelsDX11.h | 324 + .../primitives/AdlPrimitives/Sort/SortData.h | 31 + .../AdlPrimitives/Sort/radixsortadvanced.inl | 146 + .../AdlPrimitives/Sort/radixsortsimple.inl | 149 + .../opencl/primitives/AdlPrimitives/stringify.py | 13 + .../primitives/AdlPrimitives/stringifykernels.bat | 22 + .../opencl/primitives/AdlTest/AMD/premake4.lua | 31 + .../opencl/primitives/AdlTest/Intel/premake4.lua | 31 + .../primitives/AdlTest/LaunchOverheadBenchmark.h | 103 + .../opencl/primitives/AdlTest/NVIDIA/premake4.lua | 31 + .../opencl/primitives/AdlTest/RadixSortBenchmark.h | 121 + .../opencl/primitives/AdlTest/UnitTests.h | 801 + .../opencl/primitives/AdlTest/main.cpp | 118 + .../opencl/primitives/AdlTest/premake4.lua | 4 + .../opencl/primitives/benchmark/AMD/premake4.lua | 29 + .../primitives/benchmark/NVIDIA/premake4.lua | 29 + .../opencl/primitives/benchmark/premake4.lua | 2 + .../benchmark/test_large_problem_sorting.cpp | 705 + .../opencl/vector_add/AMD/premake4.lua | 21 + .../opencl/vector_add/Intel/premake4.lua | 23 + .../opencl/vector_add/NVIDIA/premake4.lua | 23 + .../opencl/vector_add/VectorAddKernels.cl | 16 + .../opencl/vector_add/VectorAddKernels.h | 18 + .../opencl/vector_add/main.cpp | 367 + .../opencl/vector_add/premake4.lua | 4 + .../opencl/vector_add/stringify.py | 13 + .../opencl/vector_add/stringifyVectorAddKernel.bat | 8 + Extras/RigidBodyGpuPipeline/readme.txt | 8 + Extras/Serialize/BlenderSerialize/CMakeLists.txt | 7 + Extras/Serialize/BlenderSerialize/bBlenderFile.cpp | 225 + Extras/Serialize/BlenderSerialize/bBlenderFile.h | 63 + Extras/Serialize/BlenderSerialize/bMain.cpp | 392 + Extras/Serialize/BlenderSerialize/bMain.h | 110 + Extras/Serialize/BlenderSerialize/dna249-64bit.cpp | 1411 + Extras/Serialize/BlenderSerialize/dna249.cpp | 1411 + Extras/Serialize/BulletFileLoader/CMakeLists.txt | 49 + .../BulletFileLoader/autogenerated/bullet.h | 966 + Extras/Serialize/BulletFileLoader/bChunk.cpp | 75 + Extras/Serialize/BulletFileLoader/bChunk.h | 92 + Extras/Serialize/BulletFileLoader/bCommon.h | 39 + Extras/Serialize/BulletFileLoader/bDNA.cpp | 636 + Extras/Serialize/BulletFileLoader/bDNA.h | 110 + Extras/Serialize/BulletFileLoader/bDefines.h | 140 + Extras/Serialize/BulletFileLoader/bFile.cpp | 1354 + Extras/Serialize/BulletFileLoader/bFile.h | 158 + Extras/Serialize/BulletFileLoader/btBulletFile.cpp | 401 + Extras/Serialize/BulletFileLoader/btBulletFile.h | 81 + Extras/Serialize/BulletFileLoader/premake4.lua | 12 + .../Serialize/BulletWorldImporter/CMakeLists.txt | 38 + .../BulletWorldImporter/btBulletWorldImporter.cpp | 1558 + .../BulletWorldImporter/btBulletWorldImporter.h | 208 + Extras/Serialize/BulletWorldImporter/premake4.lua | 13 + Extras/Serialize/CMakeLists.txt | 20 + Extras/Serialize/HeaderGenerator/CMakeLists.txt | 32 + Extras/Serialize/HeaderGenerator/apiGen.cpp | 464 + .../Serialize/HeaderGenerator/blenderGenerate.py | 111 + Extras/Serialize/HeaderGenerator/bulletGenerate.py | 83 + .../Serialize/HeaderGenerator/createDnaString.bat | 7 + .../ReadBulletSample/BulletDataExtractor.cpp | 345 + .../ReadBulletSample/BulletDataExtractor.h | 32 + Extras/Serialize/ReadBulletSample/CMakeLists.txt | 33 + Extras/Serialize/ReadBulletSample/main.cpp | 63 + Extras/Serialize/makesdna/CMakeLists.txt | 37 + Extras/Serialize/makesdna/DNA_rigidbody.h | 29 + Extras/Serialize/makesdna/makesdna.cpp | 1246 + Extras/glui/CMakeLists.txt | 66 + Extras/glui/GL/glui.h | 2723 + Extras/glui/algebra3.cpp | 1609 + Extras/glui/algebra3.h | 475 + Extras/glui/arcball.cpp | 237 + Extras/glui/arcball.h | 97 + Extras/glui/glui.cpp | 2171 + Extras/glui/glui_add_controls.cpp | 319 + Extras/glui/glui_bitmap_img_data.cpp | 138 + Extras/glui/glui_bitmaps.cpp | 176 + Extras/glui/glui_button.cpp | 186 + Extras/glui/glui_checkbox.cpp | 188 + Extras/glui/glui_column.cpp | 89 + Extras/glui/glui_commandline.cpp | 197 + Extras/glui/glui_control.cpp | 1203 + Extras/glui/glui_edittext.cpp | 1198 + Extras/glui/glui_filebrowser.cpp | 165 + Extras/glui/glui_internal.h | 107 + Extras/glui/glui_internal_control.h | 45 + Extras/glui/glui_list.cpp | 542 + Extras/glui/glui_listbox.cpp | 448 + Extras/glui/glui_mouse_iaction.cpp | 210 + Extras/glui/glui_node.cpp | 212 + Extras/glui/glui_panel.cpp | 186 + Extras/glui/glui_radio.cpp | 362 + Extras/glui/glui_rollout.cpp | 275 + Extras/glui/glui_rotation.cpp | 473 + Extras/glui/glui_scrollbar.cpp | 832 + Extras/glui/glui_separator.cpp | 75 + Extras/glui/glui_spinner.cpp | 630 + Extras/glui/glui_statictext.cpp | 105 + Extras/glui/glui_string.cpp | 62 + Extras/glui/glui_textbox.cpp | 1108 + Extras/glui/glui_translation.cpp | 559 + Extras/glui/glui_tree.cpp | 278 + Extras/glui/glui_treepanel.cpp | 388 + Extras/glui/glui_window.cpp | 44 + Extras/glui/quaternion.cpp | 243 + Extras/glui/quaternion.h | 114 + Extras/glui/readme.txt | 228 + Extras/iff/CMakeLists.txt | 11 + Extras/iff/IFF.txt | 1423 + Extras/iff/iff.h | 460 + Extras/iff/iffCheck/iffcheck.cpp | 233 + Extras/iff/iffCreateTest/main.cpp | 236 + Extras/iff/iffr.cpp | 370 + Extras/iff/iffw.cpp | 243 + Extras/khx2dae/Bullet_dae_screenshot.jpg | Bin 0 -> 18301 bytes Extras/khx2dae/Havok5.5toColladaPhysics.dae | 480 + Extras/khx2dae/Havok_hkx_screenshot.jpg | Bin 0 -> 16013 bytes Extras/khx2dae/SimpleLoadDemo.patch | 428 + Extras/khx2dae/readme.txt | 6 + Extras/premake4.lua | 6 + Extras/simdmathlibrary/LICENSE | 28 + Extras/simdmathlibrary/Make.defs | 92 + Extras/simdmathlibrary/Make.rules | 82 + Extras/simdmathlibrary/Make.test | 87 + Extras/simdmathlibrary/Makefile | 53 + Extras/simdmathlibrary/README | 128 + Extras/simdmathlibrary/common/Makefile | 47 + Extras/simdmathlibrary/common/absi4.c | 36 + Extras/simdmathlibrary/common/acosf4.c | 36 + Extras/simdmathlibrary/common/asinf4.c | 36 + Extras/simdmathlibrary/common/atan2f4.c | 36 + Extras/simdmathlibrary/common/atanf4.c | 36 + Extras/simdmathlibrary/common/cbrtf4.c | 36 + Extras/simdmathlibrary/common/ceild2.c | 36 + Extras/simdmathlibrary/common/ceilf4.c | 36 + Extras/simdmathlibrary/common/common-test.h | 228 + Extras/simdmathlibrary/common/copysignd2.c | 36 + Extras/simdmathlibrary/common/copysignf4.c | 36 + Extras/simdmathlibrary/common/cosd2.c | 36 + Extras/simdmathlibrary/common/cosf4.c | 36 + Extras/simdmathlibrary/common/divd2.c | 36 + Extras/simdmathlibrary/common/divf4.c | 36 + Extras/simdmathlibrary/common/divi4.c | 36 + Extras/simdmathlibrary/common/divu4.c | 36 + Extras/simdmathlibrary/common/exp2f4.c | 36 + Extras/simdmathlibrary/common/expf4.c | 36 + Extras/simdmathlibrary/common/expm1f4.c | 36 + Extras/simdmathlibrary/common/fabsd2.c | 36 + Extras/simdmathlibrary/common/fabsf4.c | 37 + Extras/simdmathlibrary/common/fdimd2.c | 36 + Extras/simdmathlibrary/common/fdimf4.c | 36 + Extras/simdmathlibrary/common/floord2.c | 36 + Extras/simdmathlibrary/common/floorf4.c | 36 + Extras/simdmathlibrary/common/fmad2.c | 36 + Extras/simdmathlibrary/common/fmaf4.c | 36 + Extras/simdmathlibrary/common/fmaxd2.c | 36 + Extras/simdmathlibrary/common/fmaxf4.c | 36 + Extras/simdmathlibrary/common/fmind2.c | 36 + Extras/simdmathlibrary/common/fminf4.c | 36 + Extras/simdmathlibrary/common/fmodd2.c | 36 + Extras/simdmathlibrary/common/fmodf4.c | 36 + Extras/simdmathlibrary/common/fpclassifyd2.c | 36 + Extras/simdmathlibrary/common/fpclassifyf4.c | 36 + Extras/simdmathlibrary/common/frexpd2.c | 36 + Extras/simdmathlibrary/common/frexpf4.c | 36 + Extras/simdmathlibrary/common/hypotd2.c | 36 + Extras/simdmathlibrary/common/hypotf4.c | 36 + Extras/simdmathlibrary/common/ilogbd2.c | 36 + Extras/simdmathlibrary/common/ilogbf4.c | 36 + Extras/simdmathlibrary/common/irintf4.c | 39 + Extras/simdmathlibrary/common/iroundf4.c | 38 + Extras/simdmathlibrary/common/is0denormd2.c | 36 + Extras/simdmathlibrary/common/is0denormf4.c | 35 + Extras/simdmathlibrary/common/isequald2.c | 35 + Extras/simdmathlibrary/common/isequalf4.c | 36 + Extras/simdmathlibrary/common/isfinited2.c | 37 + Extras/simdmathlibrary/common/isfinitef4.c | 36 + Extras/simdmathlibrary/common/isgreaterd2.c | 36 + Extras/simdmathlibrary/common/isgreaterequald2.c | 36 + Extras/simdmathlibrary/common/isgreaterequalf4.c | 36 + Extras/simdmathlibrary/common/isgreaterf4.c | 36 + Extras/simdmathlibrary/common/isinfd2.c | 36 + Extras/simdmathlibrary/common/isinff4.c | 36 + Extras/simdmathlibrary/common/islessd2.c | 36 + Extras/simdmathlibrary/common/islessequald2.c | 36 + Extras/simdmathlibrary/common/islessequalf4.c | 36 + Extras/simdmathlibrary/common/islessf4.c | 36 + Extras/simdmathlibrary/common/islessgreaterd2.c | 36 + Extras/simdmathlibrary/common/islessgreaterf4.c | 36 + Extras/simdmathlibrary/common/isnand2.c | 36 + Extras/simdmathlibrary/common/isnanf4.c | 36 + Extras/simdmathlibrary/common/isnormald2.c | 36 + Extras/simdmathlibrary/common/isnormalf4.c | 36 + Extras/simdmathlibrary/common/isunorderedd2.c | 36 + Extras/simdmathlibrary/common/isunorderedf4.c | 36 + Extras/simdmathlibrary/common/ldexpd2.c | 38 + Extras/simdmathlibrary/common/ldexpf4.c | 36 + Extras/simdmathlibrary/common/llabsi2.c | 36 + Extras/simdmathlibrary/common/lldivi2.c | 36 + Extras/simdmathlibrary/common/lldivu2.c | 36 + Extras/simdmathlibrary/common/llrintd2.c | 37 + Extras/simdmathlibrary/common/llrintf4.c | 37 + Extras/simdmathlibrary/common/llroundd2.c | 37 + Extras/simdmathlibrary/common/llroundf4.c | 37 + Extras/simdmathlibrary/common/log10f4.c | 36 + Extras/simdmathlibrary/common/log1pf4.c | 36 + Extras/simdmathlibrary/common/log2f4.c | 36 + Extras/simdmathlibrary/common/logbd2.c | 36 + Extras/simdmathlibrary/common/logbf4.c | 36 + Extras/simdmathlibrary/common/logf4.c | 36 + Extras/simdmathlibrary/common/modfd2.c | 36 + Extras/simdmathlibrary/common/modff4.c | 36 + Extras/simdmathlibrary/common/nearbyintd2.c | 37 + Extras/simdmathlibrary/common/nearbyintf4.c | 39 + Extras/simdmathlibrary/common/negated2.c | 37 + Extras/simdmathlibrary/common/negatef4.c | 36 + Extras/simdmathlibrary/common/negatei4.c | 36 + Extras/simdmathlibrary/common/negatell2.c | 36 + Extras/simdmathlibrary/common/nextafterd2.c | 36 + Extras/simdmathlibrary/common/nextafterf4.c | 38 + Extras/simdmathlibrary/common/powf4.c | 36 + Extras/simdmathlibrary/common/recipd2.c | 36 + Extras/simdmathlibrary/common/recipf4.c | 36 + Extras/simdmathlibrary/common/remainderd2.c | 37 + Extras/simdmathlibrary/common/remainderf4.c | 36 + Extras/simdmathlibrary/common/remquod2.c | 36 + Extras/simdmathlibrary/common/remquof4.c | 36 + Extras/simdmathlibrary/common/rintd2.c | 37 + Extras/simdmathlibrary/common/rintf4.c | 38 + Extras/simdmathlibrary/common/roundd2.c | 37 + Extras/simdmathlibrary/common/roundf4.c | 37 + Extras/simdmathlibrary/common/rsqrtd2.c | 36 + Extras/simdmathlibrary/common/rsqrtf4.c | 36 + Extras/simdmathlibrary/common/scalbllnd2.c | 38 + Extras/simdmathlibrary/common/scalbnf4.c | 38 + Extras/simdmathlibrary/common/signbitd2.c | 36 + Extras/simdmathlibrary/common/signbitf4.c | 36 + Extras/simdmathlibrary/common/simdmath.h | 732 + Extras/simdmathlibrary/common/simdmath/_sincos.h | 78 + Extras/simdmathlibrary/common/sincosd2.c | 36 + Extras/simdmathlibrary/common/sincosf4.c | 36 + Extras/simdmathlibrary/common/sind2.c | 36 + Extras/simdmathlibrary/common/sinf4.c | 36 + Extras/simdmathlibrary/common/sqrtd2.c | 36 + Extras/simdmathlibrary/common/sqrtf4.c | 36 + Extras/simdmathlibrary/common/tand2.c | 36 + Extras/simdmathlibrary/common/tanf4.c | 36 + Extras/simdmathlibrary/common/truncd2.c | 37 + Extras/simdmathlibrary/common/truncf4.c | 37 + Extras/simdmathlibrary/ppu/Makefile | 52 + Extras/simdmathlibrary/ppu/simdmath/_vec_utils.h | 51 + Extras/simdmathlibrary/ppu/simdmath/absi4.h | 42 + Extras/simdmathlibrary/ppu/simdmath/acosf4.h | 82 + Extras/simdmathlibrary/ppu/simdmath/asinf4.h | 95 + Extras/simdmathlibrary/ppu/simdmath/atan2f4.h | 67 + Extras/simdmathlibrary/ppu/simdmath/atanf4.h | 87 + Extras/simdmathlibrary/ppu/simdmath/cbrtf4.h | 97 + Extras/simdmathlibrary/ppu/simdmath/ceilf4.h | 42 + Extras/simdmathlibrary/ppu/simdmath/copysignf4.h | 45 + Extras/simdmathlibrary/ppu/simdmath/cosf4.h | 107 + Extras/simdmathlibrary/ppu/simdmath/divf4.h | 51 + Extras/simdmathlibrary/ppu/simdmath/divi4.h | 105 + Extras/simdmathlibrary/ppu/simdmath/exp2f4.h | 137 + Extras/simdmathlibrary/ppu/simdmath/expf4.h | 69 + Extras/simdmathlibrary/ppu/simdmath/expm1f4.h | 63 + Extras/simdmathlibrary/ppu/simdmath/fabsf4.h | 42 + Extras/simdmathlibrary/ppu/simdmath/fdimf4.h | 45 + Extras/simdmathlibrary/ppu/simdmath/floorf4.h | 43 + Extras/simdmathlibrary/ppu/simdmath/fmaf4.h | 42 + Extras/simdmathlibrary/ppu/simdmath/fmaxf4.h | 43 + Extras/simdmathlibrary/ppu/simdmath/fminf4.h | 43 + Extras/simdmathlibrary/ppu/simdmath/fmodf4.h | 88 + Extras/simdmathlibrary/ppu/simdmath/frexpf4.h | 54 + Extras/simdmathlibrary/ppu/simdmath/hypotf4.h | 46 + Extras/simdmathlibrary/ppu/simdmath/ilogbf4.h | 52 + Extras/simdmathlibrary/ppu/simdmath/ldexpf4.h | 63 + Extras/simdmathlibrary/ppu/simdmath/log10f4.h | 83 + Extras/simdmathlibrary/ppu/simdmath/log1pf4.h | 61 + Extras/simdmathlibrary/ppu/simdmath/log2f4.h | 77 + Extras/simdmathlibrary/ppu/simdmath/logbf4.h | 48 + Extras/simdmathlibrary/ppu/simdmath/logf4.h | 77 + Extras/simdmathlibrary/ppu/simdmath/modff4.h | 53 + Extras/simdmathlibrary/ppu/simdmath/negatef4.h | 44 + Extras/simdmathlibrary/ppu/simdmath/negatei4.h | 45 + Extras/simdmathlibrary/ppu/simdmath/powf4.h | 61 + Extras/simdmathlibrary/ppu/simdmath/recipf4.h | 50 + Extras/simdmathlibrary/ppu/simdmath/rsqrtf4.h | 57 + Extras/simdmathlibrary/ppu/simdmath/sincosf4.h | 113 + Extras/simdmathlibrary/ppu/simdmath/sinf4.h | 107 + Extras/simdmathlibrary/ppu/simdmath/sqrtf4.h | 59 + Extras/simdmathlibrary/ppu/simdmath/tanf4.h | 98 + Extras/simdmathlibrary/ppu/simdmath/truncf4.h | 43 + Extras/simdmathlibrary/ppu/tests/Makefile | 41 + Extras/simdmathlibrary/ppu/tests/absi4.c | 73 + Extras/simdmathlibrary/ppu/tests/ceilf4.c | 92 + Extras/simdmathlibrary/ppu/tests/copysignf4.c | 67 + Extras/simdmathlibrary/ppu/tests/divf4.c | 128 + Extras/simdmathlibrary/ppu/tests/divi4.c | 124 + Extras/simdmathlibrary/ppu/tests/fabsf4.c | 85 + Extras/simdmathlibrary/ppu/tests/floorf4.c | 92 + Extras/simdmathlibrary/ppu/tests/fminf4_fmaxf4.c | 91 + Extras/simdmathlibrary/ppu/tests/fmodf4.c | 129 + Extras/simdmathlibrary/ppu/tests/modff4.c | 108 + Extras/simdmathlibrary/ppu/tests/negatef4.c | 86 + Extras/simdmathlibrary/ppu/tests/negatei4.c | 83 + Extras/simdmathlibrary/ppu/tests/recipf4.c | 108 + Extras/simdmathlibrary/ppu/tests/rsqrtf4.c | 95 + Extras/simdmathlibrary/ppu/tests/sqrtf4.c | 100 + Extras/simdmathlibrary/ppu/tests/testutils.c | 67 + Extras/simdmathlibrary/ppu/tests/testutils.h | 110 + Extras/simdmathlibrary/ppu/tests/truncf4.c | 93 + Extras/simdmathlibrary/simdmath.spec | 108 + Extras/simdmathlibrary/spu/Makefile | 60 + Extras/simdmathlibrary/spu/simdmath/_lldiv.h | 116 + Extras/simdmathlibrary/spu/simdmath/_remainder.h | 84 + Extras/simdmathlibrary/spu/simdmath/_vec_utils.h | 57 + Extras/simdmathlibrary/spu/simdmath/absi4.h | 44 + Extras/simdmathlibrary/spu/simdmath/acosf4.h | 82 + Extras/simdmathlibrary/spu/simdmath/asinf4.h | 92 + Extras/simdmathlibrary/spu/simdmath/atan2f4.h | 66 + Extras/simdmathlibrary/spu/simdmath/atanf4.h | 81 + Extras/simdmathlibrary/spu/simdmath/cbrtf4.h | 95 + Extras/simdmathlibrary/spu/simdmath/ceild2.h | 99 + Extras/simdmathlibrary/spu/simdmath/ceilf4.h | 58 + Extras/simdmathlibrary/spu/simdmath/copysignd2.h | 43 + Extras/simdmathlibrary/spu/simdmath/copysignf4.h | 43 + Extras/simdmathlibrary/spu/simdmath/cosd2.h | 46 + Extras/simdmathlibrary/spu/simdmath/cosf4.h | 46 + Extras/simdmathlibrary/spu/simdmath/divd2.h | 47 + Extras/simdmathlibrary/spu/simdmath/divf4.h | 50 + Extras/simdmathlibrary/spu/simdmath/divi4.h | 67 + Extras/simdmathlibrary/spu/simdmath/divu4.h | 102 + Extras/simdmathlibrary/spu/simdmath/exp2f4.h | 135 + Extras/simdmathlibrary/spu/simdmath/expf4.h | 70 + Extras/simdmathlibrary/spu/simdmath/expm1f4.h | 62 + Extras/simdmathlibrary/spu/simdmath/fabsd2.h | 42 + Extras/simdmathlibrary/spu/simdmath/fabsf4.h | 42 + Extras/simdmathlibrary/spu/simdmath/fdimd2.h | 51 + Extras/simdmathlibrary/spu/simdmath/fdimf4.h | 43 + Extras/simdmathlibrary/spu/simdmath/floord2.h | 99 + Extras/simdmathlibrary/spu/simdmath/floorf4.h | 58 + Extras/simdmathlibrary/spu/simdmath/fmad2.h | 42 + Extras/simdmathlibrary/spu/simdmath/fmaf4.h | 42 + Extras/simdmathlibrary/spu/simdmath/fmaxd2.h | 71 + Extras/simdmathlibrary/spu/simdmath/fmaxf4.h | 43 + Extras/simdmathlibrary/spu/simdmath/fmind2.h | 71 + Extras/simdmathlibrary/spu/simdmath/fminf4.h | 43 + Extras/simdmathlibrary/spu/simdmath/fmodd2.h | 282 + Extras/simdmathlibrary/spu/simdmath/fmodf4.h | 94 + Extras/simdmathlibrary/spu/simdmath/fpclassifyd2.h | 83 + Extras/simdmathlibrary/spu/simdmath/fpclassifyf4.h | 67 + Extras/simdmathlibrary/spu/simdmath/frexpd2.h | 98 + Extras/simdmathlibrary/spu/simdmath/frexpf4.h | 52 + Extras/simdmathlibrary/spu/simdmath/hypotd2.h | 47 + Extras/simdmathlibrary/spu/simdmath/hypotf4.h | 47 + Extras/simdmathlibrary/spu/simdmath/ilogbd2.h | 83 + Extras/simdmathlibrary/spu/simdmath/ilogbf4.h | 50 + Extras/simdmathlibrary/spu/simdmath/irintf4.h | 45 + Extras/simdmathlibrary/spu/simdmath/iroundf4.h | 61 + Extras/simdmathlibrary/spu/simdmath/is0denormd2.h | 51 + Extras/simdmathlibrary/spu/simdmath/is0denormf4.h | 42 + Extras/simdmathlibrary/spu/simdmath/isequald2.h | 61 + Extras/simdmathlibrary/spu/simdmath/isequalf4.h | 42 + Extras/simdmathlibrary/spu/simdmath/isfinited2.h | 51 + Extras/simdmathlibrary/spu/simdmath/isfinitef4.h | 45 + Extras/simdmathlibrary/spu/simdmath/isgreaterd2.h | 71 + .../spu/simdmath/isgreaterequald2.h | 73 + .../spu/simdmath/isgreaterequalf4.h | 46 + Extras/simdmathlibrary/spu/simdmath/isgreaterf4.h | 42 + Extras/simdmathlibrary/spu/simdmath/isinfd2.h | 51 + Extras/simdmathlibrary/spu/simdmath/isinff4.h | 45 + Extras/simdmathlibrary/spu/simdmath/islessd2.h | 71 + .../simdmathlibrary/spu/simdmath/islessequald2.h | 73 + .../simdmathlibrary/spu/simdmath/islessequalf4.h | 46 + Extras/simdmathlibrary/spu/simdmath/islessf4.h | 42 + .../simdmathlibrary/spu/simdmath/islessgreaterd2.h | 61 + .../simdmathlibrary/spu/simdmath/islessgreaterf4.h | 46 + Extras/simdmathlibrary/spu/simdmath/isnand2.h | 56 + Extras/simdmathlibrary/spu/simdmath/isnanf4.h | 45 + Extras/simdmathlibrary/spu/simdmath/isnormald2.h | 53 + Extras/simdmathlibrary/spu/simdmath/isnormalf4.h | 43 + .../simdmathlibrary/spu/simdmath/isunorderedd2.h | 67 + .../simdmathlibrary/spu/simdmath/isunorderedf4.h | 46 + Extras/simdmathlibrary/spu/simdmath/ldexpd2.h | 266 + Extras/simdmathlibrary/spu/simdmath/ldexpf4.h | 62 + Extras/simdmathlibrary/spu/simdmath/llabsi2.h | 50 + Extras/simdmathlibrary/spu/simdmath/lldivi2.h | 85 + Extras/simdmathlibrary/spu/simdmath/lldivu2.h | 104 + Extras/simdmathlibrary/spu/simdmath/llrintd2.h | 115 + Extras/simdmathlibrary/spu/simdmath/llrintf4.h | 107 + Extras/simdmathlibrary/spu/simdmath/llroundd2.h | 97 + Extras/simdmathlibrary/spu/simdmath/llroundf4.h | 120 + Extras/simdmathlibrary/spu/simdmath/log10f4.h | 83 + Extras/simdmathlibrary/spu/simdmath/log1pf4.h | 60 + Extras/simdmathlibrary/spu/simdmath/log2f4.h | 78 + Extras/simdmathlibrary/spu/simdmath/logbd2.h | 86 + Extras/simdmathlibrary/spu/simdmath/logbf4.h | 46 + Extras/simdmathlibrary/spu/simdmath/logf4.h | 76 + Extras/simdmathlibrary/spu/simdmath/modfd2.h | 59 + Extras/simdmathlibrary/spu/simdmath/modff4.h | 52 + Extras/simdmathlibrary/spu/simdmath/nearbyintd2.h | 76 + Extras/simdmathlibrary/spu/simdmath/nearbyintf4.h | 55 + Extras/simdmathlibrary/spu/simdmath/negated2.h | 42 + Extras/simdmathlibrary/spu/simdmath/negatef4.h | 43 + Extras/simdmathlibrary/spu/simdmath/negatei4.h | 43 + Extras/simdmathlibrary/spu/simdmath/negatell2.h | 47 + Extras/simdmathlibrary/spu/simdmath/nextafterd2.h | 97 + Extras/simdmathlibrary/spu/simdmath/nextafterf4.h | 72 + Extras/simdmathlibrary/spu/simdmath/powf4.h | 60 + Extras/simdmathlibrary/spu/simdmath/recipd2.h | 88 + Extras/simdmathlibrary/spu/simdmath/recipf4.h | 50 + Extras/simdmathlibrary/spu/simdmath/remainderd2.h | 110 + Extras/simdmathlibrary/spu/simdmath/remainderf4.h | 115 + Extras/simdmathlibrary/spu/simdmath/remquod2.h | 155 + Extras/simdmathlibrary/spu/simdmath/remquof4.h | 191 + Extras/simdmathlibrary/spu/simdmath/rintd2.h | 72 + Extras/simdmathlibrary/spu/simdmath/rintf4.h | 54 + Extras/simdmathlibrary/spu/simdmath/roundd2.h | 78 + Extras/simdmathlibrary/spu/simdmath/roundf4.h | 69 + Extras/simdmathlibrary/spu/simdmath/rsqrtd2.h | 105 + Extras/simdmathlibrary/spu/simdmath/rsqrtf4.h | 51 + Extras/simdmathlibrary/spu/simdmath/scalbllnd2.h | 268 + Extras/simdmathlibrary/spu/simdmath/scalbnf4.h | 75 + Extras/simdmathlibrary/spu/simdmath/signbitd2.h | 48 + Extras/simdmathlibrary/spu/simdmath/signbitf4.h | 42 + Extras/simdmathlibrary/spu/simdmath/sincosd2.h | 149 + Extras/simdmathlibrary/spu/simdmath/sincosf4.h | 113 + Extras/simdmathlibrary/spu/simdmath/sind2.h | 49 + Extras/simdmathlibrary/spu/simdmath/sinf4.h | 49 + Extras/simdmathlibrary/spu/simdmath/sqrtd2.h | 113 + Extras/simdmathlibrary/spu/simdmath/sqrtf4.h | 52 + Extras/simdmathlibrary/spu/simdmath/tand2.h | 125 + Extras/simdmathlibrary/spu/simdmath/tanf4.h | 95 + Extras/simdmathlibrary/spu/simdmath/truncd2.h | 66 + Extras/simdmathlibrary/spu/simdmath/truncf4.h | 52 + Extras/simdmathlibrary/spu/tests/Makefile | 51 + Extras/simdmathlibrary/spu/tests/absi4.c | 90 + Extras/simdmathlibrary/spu/tests/ceild2.c | 156 + Extras/simdmathlibrary/spu/tests/ceilf4.c | 108 + Extras/simdmathlibrary/spu/tests/copysignd2.c | 74 + Extras/simdmathlibrary/spu/tests/copysignf4.c | 75 + Extras/simdmathlibrary/spu/tests/divd2.c | 153 + Extras/simdmathlibrary/spu/tests/divf4.c | 128 + Extras/simdmathlibrary/spu/tests/divi4.c | 123 + Extras/simdmathlibrary/spu/tests/divu4.c | 146 + Extras/simdmathlibrary/spu/tests/fabsd2.c | 103 + Extras/simdmathlibrary/spu/tests/fabsf4.c | 106 + Extras/simdmathlibrary/spu/tests/fdimd2.c | 173 + Extras/simdmathlibrary/spu/tests/floord2.c | 157 + Extras/simdmathlibrary/spu/tests/floorf4.c | 109 + Extras/simdmathlibrary/spu/tests/fmad2.c | 146 + Extras/simdmathlibrary/spu/tests/fmind2_fmaxd2.c | 225 + Extras/simdmathlibrary/spu/tests/fminf4_fmaxf4.c | 124 + Extras/simdmathlibrary/spu/tests/fmodd2.c | 364 + Extras/simdmathlibrary/spu/tests/fmodf4.c | 145 + Extras/simdmathlibrary/spu/tests/fpclassifyd2.c | 225 + Extras/simdmathlibrary/spu/tests/fpclassifyf4.c | 200 + Extras/simdmathlibrary/spu/tests/frexpd2.c | 418 + Extras/simdmathlibrary/spu/tests/frexpf4.c | 405 + Extras/simdmathlibrary/spu/tests/hypotd2.c | 341 + Extras/simdmathlibrary/spu/tests/hypotf4.c | 208 + Extras/simdmathlibrary/spu/tests/ilogbd2.c | 316 + Extras/simdmathlibrary/spu/tests/ilogbf4.c | 317 + Extras/simdmathlibrary/spu/tests/irintf4.c | 96 + Extras/simdmathlibrary/spu/tests/iroundf4.c | 96 + Extras/simdmathlibrary/spu/tests/is0denormd2.c | 225 + Extras/simdmathlibrary/spu/tests/is0denormf4.c | 200 + Extras/simdmathlibrary/spu/tests/isequald2.c | 271 + Extras/simdmathlibrary/spu/tests/isequalf4.c | 151 + Extras/simdmathlibrary/spu/tests/isfinited2.c | 225 + Extras/simdmathlibrary/spu/tests/isfinitef4.c | 131 + Extras/simdmathlibrary/spu/tests/isgreaterd2.c | 271 + .../simdmathlibrary/spu/tests/isgreaterequald2.c | 271 + .../simdmathlibrary/spu/tests/isgreaterequalf4.c | 151 + Extras/simdmathlibrary/spu/tests/isgreaterf4.c | 151 + Extras/simdmathlibrary/spu/tests/isinfd2.c | 225 + Extras/simdmathlibrary/spu/tests/isinff4.c | 131 + Extras/simdmathlibrary/spu/tests/islessd2.c | 272 + Extras/simdmathlibrary/spu/tests/islessequald2.c | 271 + Extras/simdmathlibrary/spu/tests/islessequalf4.c | 151 + Extras/simdmathlibrary/spu/tests/islessf4.c | 151 + Extras/simdmathlibrary/spu/tests/islessgreaterd2.c | 271 + Extras/simdmathlibrary/spu/tests/islessgreaterf4.c | 151 + Extras/simdmathlibrary/spu/tests/isnand2.c | 226 + Extras/simdmathlibrary/spu/tests/isnanf4.c | 130 + Extras/simdmathlibrary/spu/tests/isnormald2.c | 225 + Extras/simdmathlibrary/spu/tests/isnormalf4.c | 131 + Extras/simdmathlibrary/spu/tests/isunorderedd2.c | 271 + Extras/simdmathlibrary/spu/tests/isunorderedf4.c | 151 + Extras/simdmathlibrary/spu/tests/ldexpd2.c | 250 + Extras/simdmathlibrary/spu/tests/llabsi2.c | 94 + Extras/simdmathlibrary/spu/tests/lldivi2.c | 126 + Extras/simdmathlibrary/spu/tests/lldivu2.c | 125 + Extras/simdmathlibrary/spu/tests/llrintd2.c | 215 + Extras/simdmathlibrary/spu/tests/llrintf4.c | 123 + Extras/simdmathlibrary/spu/tests/llroundd2.c | 113 + Extras/simdmathlibrary/spu/tests/llroundf4.c | 125 + Extras/simdmathlibrary/spu/tests/logbd2.c | 314 + Extras/simdmathlibrary/spu/tests/logbf4.c | 316 + Extras/simdmathlibrary/spu/tests/modfd2.c | 109 + Extras/simdmathlibrary/spu/tests/modff4.c | 124 + Extras/simdmathlibrary/spu/tests/nearbyintd2.c | 178 + Extras/simdmathlibrary/spu/tests/nearbyintf4.c | 95 + Extras/simdmathlibrary/spu/tests/negated2.c | 83 + Extras/simdmathlibrary/spu/tests/negatef4.c | 87 + Extras/simdmathlibrary/spu/tests/negatei4.c | 83 + Extras/simdmathlibrary/spu/tests/negatell2.c | 86 + Extras/simdmathlibrary/spu/tests/nextafterd2.c | 153 + Extras/simdmathlibrary/spu/tests/nextafterf4.c | 162 + Extras/simdmathlibrary/spu/tests/recipd2.c | 131 + Extras/simdmathlibrary/spu/tests/recipf4.c | 114 + Extras/simdmathlibrary/spu/tests/remainderd2.c | 125 + Extras/simdmathlibrary/spu/tests/remainderf4.c | 143 + Extras/simdmathlibrary/spu/tests/remquod2.c | 151 + Extras/simdmathlibrary/spu/tests/remquof4.c | 145 + Extras/simdmathlibrary/spu/tests/rintd2.c | 180 + Extras/simdmathlibrary/spu/tests/rintf4.c | 94 + Extras/simdmathlibrary/spu/tests/roundd2.c | 151 + Extras/simdmathlibrary/spu/tests/roundf4.c | 100 + Extras/simdmathlibrary/spu/tests/rsqrtd2.c | 126 + Extras/simdmathlibrary/spu/tests/rsqrtf4.c | 93 + Extras/simdmathlibrary/spu/tests/scalbllnd2.c | 251 + Extras/simdmathlibrary/spu/tests/scalbnf4.c | 117 + Extras/simdmathlibrary/spu/tests/signbitd2.c | 195 + Extras/simdmathlibrary/spu/tests/signbitf4.c | 195 + Extras/simdmathlibrary/spu/tests/sqrtd2.c | 128 + Extras/simdmathlibrary/spu/tests/sqrtf4.c | 92 + Extras/simdmathlibrary/spu/tests/testutils.c | 321 + Extras/simdmathlibrary/spu/tests/testutils.h | 87 + Extras/simdmathlibrary/spu/tests/truncd2.c | 145 + Extras/simdmathlibrary/spu/tests/truncf4.c | 108 + .../software_cache/cache/CommonPublicLicense-1.0 | 213 + Extras/software_cache/cache/include/Makefile | 28 + Extras/software_cache/cache/include/README | 32 + Extras/software_cache/cache/include/api.h | 31 + Extras/software_cache/cache/include/cbe_mfc.h | 245 + Extras/software_cache/cache/include/defs.h | 149 + Extras/software_cache/cache/include/dma.h | 40 + Extras/software_cache/cache/include/ilog2.h | 35 + Extras/software_cache/cache/include/memset.h | 68 + Extras/software_cache/cache/include/nway-lookup.h | 194 + Extras/software_cache/cache/include/nway-miss.h | 51 + Extras/software_cache/cache/include/nway-opt.h | 153 + Extras/software_cache/cache/include/nway-replace.h | 38 + Extras/software_cache/cache/include/nway.h | 105 + Extras/software_cache/cache/include/spe_cache.h | 32 + Extras/software_cache/cache/include/vec_literal.h | 74 + Extras/sph/READ_ME.txt | 35 + Extras/sph/cmp.sh | 5 + Extras/sph/common/GLee.c | 18170 ++++ Extras/sph/common/GLee.h | 17647 ++++ Extras/sph/common/common_defs.h | 52 + Extras/sph/common/geomx.cpp | 443 + Extras/sph/common/geomx.h | 125 + Extras/sph/common/gl_helper.cpp | 402 + Extras/sph/common/gl_helper.h | 89 + Extras/sph/common/glext.h | 7139 ++ Extras/sph/common/glut.h | 791 + Extras/sph/common/image.cpp | 1948 + Extras/sph/common/image.h | 188 + Extras/sph/common/matrix-inline.h | 1879 + Extras/sph/common/matrix.cci | 2046 + Extras/sph/common/matrix.cpp | 23 + Extras/sph/common/matrix.h | 429 + Extras/sph/common/mdebug.cpp | 583 + Extras/sph/common/mdebug.h | 138 + Extras/sph/common/mesh.cpp | 955 + Extras/sph/common/mesh.h | 160 + Extras/sph/common/mesh_info.h | 97 + Extras/sph/common/mtime.cpp | 612 + Extras/sph/common/mtime.h | 234 + Extras/sph/common/particle.cpp | 23 + Extras/sph/common/particle.h | 29 + Extras/sph/common/point_set.cpp | 539 + Extras/sph/common/point_set.h | 165 + Extras/sph/common/vector-inline.h | 782 + Extras/sph/common/vector.cci | 761 + Extras/sph/common/vector.cpp | 70 + Extras/sph/common/vector.h | 785 + Extras/sph/fluid_system_host.linkinfo | 1 + Extras/sph/fluids.vcproj | 306 + Extras/sph/fluids/fluid.cpp | 22 + Extras/sph/fluids/fluid.h | 44 + Extras/sph/fluids/fluid_system.cpp | 869 + Extras/sph/fluids/fluid_system.cu | 71 + Extras/sph/fluids/fluid_system.h | 106 + Extras/sph/fluids/fluid_system_host.cu | 250 + Extras/sph/fluids/fluid_system_host.cuh | 63 + Extras/sph/fluids/fluid_system_kern.cu | 402 + Extras/sph/fluids/fluid_system_kern.cuh | 45 + Extras/sph/fluids/radixsort.cu | 79 + Extras/sph/fluids/radixsort.cuh | 63 + Extras/sph/fluids/radixsort_kernel.cu | 577 + Extras/sph/fluids_2005.sln | 23 + Extras/sph/fluids_2005.vcproj | 447 + Extras/sph/main.cpp | 594 + Extras/vectormathlibrary/LICENSE | 31 + Extras/vectormathlibrary/Makefile | 119 + Extras/vectormathlibrary/README | 86 + .../doc/Vector_Math_Library-Overview.pdf | Bin 0 -> 207118 bytes .../include/vectormath/SSE/cpp/boolInVec.h | 247 + .../include/vectormath/SSE/cpp/floatInVec.h | 340 + .../include/vectormath/SSE/cpp/mat_aos.h | 2190 + .../include/vectormath/SSE/cpp/quat_aos.h | 568 + .../include/vectormath/SSE/cpp/readme_e.txt | 1 + .../include/vectormath/SSE/cpp/vec_aos.h | 1431 + .../include/vectormath/SSE/cpp/vecidx_aos.h | 80 + .../include/vectormath/SSE/cpp/vectormath_aos.h | 2527 + .../include/vectormath/c/vectormath_aos.h | 41 + .../include/vectormath/c/vectormath_aos_v.h | 41 + .../include/vectormath/c/vectormath_soa.h | 41 + .../include/vectormath/c/vectormath_soa_v.h | 41 + .../include/vectormath/cpp/vectormath_aos.h | 43 + .../include/vectormath/cpp/vectormath_soa.h | 41 + .../include/vectormath/ppu/c/mat_aos.h | 1833 + .../include/vectormath/ppu/c/mat_aos_v.h | 1026 + .../include/vectormath/ppu/c/mat_soa.h | 1493 + .../include/vectormath/ppu/c/mat_soa_v.h | 1063 + .../include/vectormath/ppu/c/quat_aos.h | 379 + .../include/vectormath/ppu/c/quat_aos_v.h | 312 + .../include/vectormath/ppu/c/quat_soa.h | 415 + .../include/vectormath/ppu/c/quat_soa_v.h | 319 + .../include/vectormath/ppu/c/vec_aos.h | 1125 + .../include/vectormath/ppu/c/vec_aos_v.h | 953 + .../include/vectormath/ppu/c/vec_soa.h | 1223 + .../include/vectormath/ppu/c/vec_soa_v.h | 958 + .../include/vectormath/ppu/c/vec_types.h | 59 + .../include/vectormath/ppu/c/vectormath_aos.h | 1960 + .../include/vectormath/ppu/c/vectormath_aos_v.h | 1925 + .../include/vectormath/ppu/c/vectormath_soa.h | 2013 + .../include/vectormath/ppu/c/vectormath_soa_v.h | 1979 + .../include/vectormath/ppu/cpp/boolInVec.h | 261 + .../include/vectormath/ppu/cpp/floatInVec.h | 361 + .../include/vectormath/ppu/cpp/mat_aos.h | 2188 + .../include/vectormath/ppu/cpp/mat_soa.h | 1744 + .../include/vectormath/ppu/cpp/quat_aos.h | 536 + .../include/vectormath/ppu/cpp/quat_soa.h | 479 + .../include/vectormath/ppu/cpp/vec_aos.h | 1492 + .../include/vectormath/ppu/cpp/vec_soa.h | 1425 + .../include/vectormath/ppu/cpp/vecidx_aos.h | 80 + .../include/vectormath/ppu/cpp/vectormath_aos.h | 2244 + .../include/vectormath/ppu/cpp/vectormath_soa.h | 1919 + .../include/vectormath/scalar/c/mat_aos.h | 1452 + .../include/vectormath/scalar/c/mat_aos_v.h | 1006 + .../include/vectormath/scalar/c/quat_aos.h | 368 + .../include/vectormath/scalar/c/quat_aos_v.h | 300 + .../include/vectormath/scalar/c/vec_aos.h | 971 + .../include/vectormath/scalar/c/vec_aos_v.h | 848 + .../include/vectormath/scalar/c/vectormath_aos.h | 1879 + .../include/vectormath/scalar/c/vectormath_aos_v.h | 1845 + .../include/vectormath/scalar/cpp/boolInVec.h | 238 + .../include/vectormath/scalar/cpp/floatInVec.h | 357 + .../include/vectormath/scalar/cpp/mat_aos.h | 1643 + .../include/vectormath/scalar/cpp/quat_aos.h | 446 + .../include/vectormath/scalar/cpp/vec_aos.h | 1439 + .../include/vectormath/scalar/cpp/vectormath_aos.h | 1885 + .../include/vectormath/spu/c/mat_aos.h | 1833 + .../include/vectormath/spu/c/mat_aos_v.h | 1029 + .../include/vectormath/spu/c/mat_soa.h | 1493 + .../include/vectormath/spu/c/mat_soa_v.h | 1063 + .../include/vectormath/spu/c/quat_aos.h | 371 + .../include/vectormath/spu/c/quat_aos_v.h | 312 + .../include/vectormath/spu/c/quat_soa.h | 419 + .../include/vectormath/spu/c/quat_soa_v.h | 319 + .../include/vectormath/spu/c/vec_aos.h | 1029 + .../include/vectormath/spu/c/vec_aos_v.h | 951 + .../include/vectormath/spu/c/vec_soa.h | 1237 + .../include/vectormath/spu/c/vec_soa_v.h | 962 + .../include/vectormath/spu/c/vectormath_aos.h | 1951 + .../include/vectormath/spu/c/vectormath_aos_v.h | 1916 + .../include/vectormath/spu/c/vectormath_soa.h | 2012 + .../include/vectormath/spu/c/vectormath_soa_v.h | 1978 + .../include/vectormath/spu/cpp/boolInVec.h | 246 + .../include/vectormath/spu/cpp/floatInVec.h | 339 + .../include/vectormath/spu/cpp/mat_aos.h | 2027 + .../include/vectormath/spu/cpp/mat_soa.h | 1744 + .../include/vectormath/spu/cpp/quat_aos.h | 417 + .../include/vectormath/spu/cpp/quat_soa.h | 483 + .../include/vectormath/spu/cpp/vec_aos.h | 1167 + .../include/vectormath/spu/cpp/vec_soa.h | 1439 + .../include/vectormath/spu/cpp/vecidx_aos.h | 64 + .../include/vectormath/spu/cpp/vectormath_aos.h | 1851 + .../include/vectormath/spu/cpp/vectormath_soa.h | 1921 + Extras/vectormathlibrary/tests/Makefile | 138 + Extras/vectormathlibrary/tests/clean.pl | 109 + Extras/vectormathlibrary/tests/compare.pl | 95 + Extras/vectormathlibrary/tests/main_vmtest.cpp | 163 + Extras/vectormathlibrary/tests/test.h | 346 + Extras/vectormathlibrary/tests/test1_aos_c.c | 1153 + Extras/vectormathlibrary/tests/test1_aos_cpp.cpp | 1102 + Extras/vectormathlibrary/tests/test1_reference.txt | 680 + Extras/vectormathlibrary/tests/test1_soa_c.c | 1006 + Extras/vectormathlibrary/tests/test1_soa_cpp.cpp | 931 + Extras/vectormathlibrary/tests/test2_aos_c.c | 852 + Extras/vectormathlibrary/tests/test2_aos_cpp.cpp | 784 + Extras/vectormathlibrary/tests/test2_reference.txt | 1190 + Extras/vectormathlibrary/tests/test2_soa_c.c | 760 + Extras/vectormathlibrary/tests/test2_soa_cpp.cpp | 718 + Extras/vectormathlibrary/tests/test3_aos_c.c | 524 + Extras/vectormathlibrary/tests/test3_aos_cpp.cpp | 476 + Extras/vectormathlibrary/tests/test3_reference.txt | 392 + Extras/vectormathlibrary/tests/test3_soa_c.c | 433 + Extras/vectormathlibrary/tests/test3_soa_cpp.cpp | 410 + Extras/vectormathlibrary/tests/test4_aos_c.c | 567 + Extras/vectormathlibrary/tests/test4_aos_cpp.cpp | 492 + Extras/vectormathlibrary/tests/test4_reference.txt | 524 + Extras/vectormathlibrary/tests/test4_soa_c.c | 474 + Extras/vectormathlibrary/tests/test4_soa_cpp.cpp | 426 + Extras/vectormathlibrary/vectormath.spec | 81 + GLUT32.DLL | Bin 0 -> 160256 bytes Glut/EmptyGL/GL/egl_cpx.h | 13 + Glut/EmptyGL/GL/egl_defs.h | 706 + Glut/EmptyGL/GL/egl_logged.h | 20 + Glut/EmptyGL/GL/egl_tokens.h | 459 + Glut/EmptyGL/GL/egl_void.h | 422 + Glut/EmptyGL/GL/gl.h | 47 + Glut/EmptyGL/GL/glu.h | 23 + Glut/EmptyGL/GL/glut.h | 60 + Glut/GL/glew.h | 15507 ++++ Glut/GL/glext.h | 3326 + Glut/GL/glut.h | 607 + Glut/GL/glxew.h | 1587 + Glut/GL/glxext.h | 546 + Glut/GL/wglew.h | 1363 + Glut/GL/wglext.h | 466 + Glut/btGlutInclude.h | 43 + Glut/glew32s.lib | Bin 0 -> 1288450 bytes Glut/glew64s.lib | Bin 0 -> 1378464 bytes Glut/glut32.lib | Bin 0 -> 29180 bytes Glut/glut64.lib | Bin 0 -> 26180 bytes INSTALL | 111 + Makefile.am | 7 + NEWS | 5 + README | 6 + RELEASING.TXT | 34 + UnitTests/BulletUnitTests/CMakeLists.txt | 18 + UnitTests/BulletUnitTests/Main.cpp | 41 + UnitTests/BulletUnitTests/TestBulletOnly.h | 119 + UnitTests/BulletUnitTests/TestLinearMath.h | 206 + UnitTests/CMakeLists.txt | 2 + UnitTests/cppunit/AUTHORS | 6 + UnitTests/cppunit/BUGS | 6 + UnitTests/cppunit/CMakeLists.txt | 74 + UnitTests/cppunit/ChangeLog | 3749 + UnitTests/cppunit/CodingGuideLines.txt | 61 + UnitTests/cppunit/THANKS | 23 + UnitTests/cppunit/TODO | 35 + .../cppunit/include/cppunit/AdditionalMessage.h | 76 + UnitTests/cppunit/include/cppunit/Asserter.h | 143 + .../include/cppunit/BriefTestProgressListener.h | 43 + .../cppunit/include/cppunit/CompilerOutputter.h | 146 + UnitTests/cppunit/include/cppunit/Exception.h | 90 + UnitTests/cppunit/include/cppunit/Message.h | 156 + UnitTests/cppunit/include/cppunit/Outputter.h | 26 + UnitTests/cppunit/include/cppunit/Portability.h | 183 + UnitTests/cppunit/include/cppunit/Protector.h | 94 + UnitTests/cppunit/include/cppunit/SourceLine.h | 63 + .../cppunit/include/cppunit/SynchronizedObject.h | 80 + UnitTests/cppunit/include/cppunit/Test.h | 117 + UnitTests/cppunit/include/cppunit/TestAssert.h | 428 + UnitTests/cppunit/include/cppunit/TestCaller.h | 204 + UnitTests/cppunit/include/cppunit/TestCase.h | 55 + UnitTests/cppunit/include/cppunit/TestComposite.h | 45 + UnitTests/cppunit/include/cppunit/TestFailure.h | 58 + UnitTests/cppunit/include/cppunit/TestFixture.h | 99 + UnitTests/cppunit/include/cppunit/TestLeaf.h | 44 + UnitTests/cppunit/include/cppunit/TestListener.h | 148 + UnitTests/cppunit/include/cppunit/TestPath.h | 211 + UnitTests/cppunit/include/cppunit/TestResult.h | 156 + .../cppunit/include/cppunit/TestResultCollector.h | 87 + UnitTests/cppunit/include/cppunit/TestRunner.h | 135 + .../cppunit/include/cppunit/TestSuccessListener.h | 39 + UnitTests/cppunit/include/cppunit/TestSuite.h | 80 + UnitTests/cppunit/include/cppunit/TextOutputter.h | 59 + .../include/cppunit/TextTestProgressListener.h | 44 + UnitTests/cppunit/include/cppunit/TextTestResult.h | 39 + UnitTests/cppunit/include/cppunit/TextTestRunner.h | 6 + UnitTests/cppunit/include/cppunit/XmlOutputter.h | 167 + .../cppunit/include/cppunit/XmlOutputterHook.h | 163 + UnitTests/cppunit/include/cppunit/config-auto.h | 179 + .../cppunit/include/cppunit/config/CppUnitApi.h | 33 + .../include/cppunit/config/SelectDllLoader.h | 76 + .../cppunit/include/cppunit/config/SourcePrefix.h | 14 + .../cppunit/include/cppunit/config/config-bcb5.h | 47 + .../cppunit/include/cppunit/config/config-evc4.h | 78 + .../cppunit/include/cppunit/config/config-mac.h | 58 + .../cppunit/include/cppunit/config/config-msvc6.h | 86 + .../include/cppunit/extensions/AutoRegisterSuite.h | 83 + .../extensions/ExceptionTestCaseDecorator.h | 104 + .../include/cppunit/extensions/HelperMacros.h | 541 + .../cppunit/include/cppunit/extensions/Orthodox.h | 95 + .../include/cppunit/extensions/RepeatedTest.h | 43 + .../include/cppunit/extensions/TestCaseDecorator.h | 40 + .../include/cppunit/extensions/TestDecorator.h | 49 + .../include/cppunit/extensions/TestFactory.h | 27 + .../cppunit/extensions/TestFactoryRegistry.h | 182 + .../cppunit/extensions/TestFixtureFactory.h | 50 + .../cppunit/include/cppunit/extensions/TestNamer.h | 89 + .../cppunit/include/cppunit/extensions/TestSetUp.h | 34 + .../cppunit/extensions/TestSuiteBuilderContext.h | 131 + .../include/cppunit/extensions/TestSuiteFactory.h | 27 + .../include/cppunit/extensions/TypeInfoHelper.h | 33 + .../include/cppunit/extensions/XmlInputHelper.h | 23 + .../include/cppunit/plugin/DynamicLibraryManager.h | 121 + .../plugin/DynamicLibraryManagerException.h | 53 + .../cppunit/include/cppunit/plugin/PlugInManager.h | 113 + .../include/cppunit/plugin/PlugInParameters.h | 36 + .../cppunit/include/cppunit/plugin/TestPlugIn.h | 200 + .../include/cppunit/plugin/TestPlugInDefaultImpl.h | 61 + .../include/cppunit/portability/CppUnitDeque.h | 25 + .../include/cppunit/portability/CppUnitMap.h | 29 + .../include/cppunit/portability/CppUnitSet.h | 28 + .../include/cppunit/portability/CppUnitStack.h | 26 + .../include/cppunit/portability/CppUnitVector.h | 25 + .../include/cppunit/portability/FloatingPoint.h | 54 + .../cppunit/include/cppunit/portability/Stream.h | 347 + .../cppunit/include/cppunit/tools/Algorithm.h | 23 + .../cppunit/include/cppunit/tools/StringTools.h | 34 + .../cppunit/include/cppunit/tools/XmlDocument.h | 86 + .../cppunit/include/cppunit/tools/XmlElement.h | 149 + .../cppunit/include/cppunit/ui/text/TestRunner.h | 24 + .../include/cppunit/ui/text/TextTestRunner.h | 97 + .../cppunit/src/cppunit/AdditionalMessage.cpp | 41 + UnitTests/cppunit/src/cppunit/Asserter.cpp | 101 + .../src/cppunit/BeOsDynamicLibraryManager.cpp | 49 + .../src/cppunit/BriefTestProgressListener.cpp | 49 + .../cppunit/src/cppunit/CompilerOutputter.cpp | 216 + UnitTests/cppunit/src/cppunit/DefaultProtector.cpp | 42 + UnitTests/cppunit/src/cppunit/DefaultProtector.h | 27 + UnitTests/cppunit/src/cppunit/DllMain.cpp | 16 + .../cppunit/src/cppunit/DynamicLibraryManager.cpp | 77 + .../src/cppunit/DynamicLibraryManagerException.cpp | 41 + UnitTests/cppunit/src/cppunit/Exception.cpp | 126 + UnitTests/cppunit/src/cppunit/Message.cpp | 170 + UnitTests/cppunit/src/cppunit/PlugInManager.cpp | 110 + UnitTests/cppunit/src/cppunit/PlugInParameters.cpp | 28 + UnitTests/cppunit/src/cppunit/Protector.cpp | 86 + UnitTests/cppunit/src/cppunit/ProtectorChain.cpp | 86 + UnitTests/cppunit/src/cppunit/ProtectorChain.h | 51 + UnitTests/cppunit/src/cppunit/ProtectorContext.h | 38 + UnitTests/cppunit/src/cppunit/RepeatedTest.cpp | 29 + .../src/cppunit/ShlDynamicLibraryManager.cpp | 53 + UnitTests/cppunit/src/cppunit/SourceLine.cpp | 81 + UnitTests/cppunit/src/cppunit/StringTools.cpp | 80 + .../cppunit/src/cppunit/SynchronizedObject.cpp | 32 + UnitTests/cppunit/src/cppunit/Test.cpp | 97 + UnitTests/cppunit/src/cppunit/TestAssert.cpp | 46 + UnitTests/cppunit/src/cppunit/TestCase.cpp | 137 + .../cppunit/src/cppunit/TestCaseDecorator.cpp | 47 + UnitTests/cppunit/src/cppunit/TestComposite.cpp | 77 + UnitTests/cppunit/src/cppunit/TestDecorator.cpp | 53 + .../cppunit/src/cppunit/TestFactoryRegistry.cpp | 161 + UnitTests/cppunit/src/cppunit/TestFailure.cpp | 71 + UnitTests/cppunit/src/cppunit/TestLeaf.cpp | 28 + UnitTests/cppunit/src/cppunit/TestNamer.cpp | 44 + UnitTests/cppunit/src/cppunit/TestPath.cpp | 254 + .../cppunit/src/cppunit/TestPlugInDefaultImpl.cpp | 63 + UnitTests/cppunit/src/cppunit/TestResult.cpp | 199 + .../cppunit/src/cppunit/TestResultCollector.cpp | 117 + UnitTests/cppunit/src/cppunit/TestRunner.cpp | 101 + UnitTests/cppunit/src/cppunit/TestSetUp.cpp | 32 + .../cppunit/src/cppunit/TestSuccessListener.cpp | 44 + UnitTests/cppunit/src/cppunit/TestSuite.cpp | 64 + .../src/cppunit/TestSuiteBuilderContext.cpp | 85 + UnitTests/cppunit/src/cppunit/TextOutputter.cpp | 140 + .../src/cppunit/TextTestProgressListener.cpp | 45 + UnitTests/cppunit/src/cppunit/TextTestResult.cpp | 50 + UnitTests/cppunit/src/cppunit/TextTestRunner.cpp | 144 + UnitTests/cppunit/src/cppunit/TypeInfoHelper.cpp | 54 + .../src/cppunit/UnixDynamicLibraryManager.cpp | 44 + .../src/cppunit/Win32DynamicLibraryManager.cpp | 73 + UnitTests/cppunit/src/cppunit/XmlDocument.cpp | 106 + UnitTests/cppunit/src/cppunit/XmlElement.cpp | 226 + UnitTests/cppunit/src/cppunit/XmlOutputter.cpp | 205 + UnitTests/cppunit/src/cppunit/XmlOutputterHook.cpp | 44 + VERSION | 1 + acinclude.m4 | 3054 + autogen.sh | 61 + bullet.pc.cmake | 6 + bullet.pc.in | 11 + bullet_logo.png | Bin 0 -> 3380 bytes config.h.in | 113 + configure.ac | 160 + convex0.bin | Bin 0 -> 548 bytes file.obj | 3578 + glut64.dll | Bin 0 -> 272896 bytes heightfield128x128.raw | 37 + install-sh | 322 + jenga.dae | 5632 ++ lib/readme.txt | 13 + msvc/autoexp_dat.txt | 66 + msvc/bullet.rc | 29 + msvc/bullet_ico.ico | Bin 0 -> 21630 bytes msvc/findDirectX11.lua | 36 + msvc/findOpenCL.lua | 84 + msvc/premake4.exe | Bin 0 -> 281088 bytes msvc/premake4.lua | 142 + msvc/vs2005.bat | 4 + msvc/vs2008.bat | 10 + msvc/vs2010.bat | 4 + msvc/vs2010_dx11.bat | 5 + msvc/vs2010_opencl.bat | 8 + msvc/vs_all.bat | 36 + packaging/bullet.spec | 67 + src/Bullet-C-Api.h | 176 + .../BroadphaseCollision/btAxisSweep3.cpp | 37 + .../BroadphaseCollision/btAxisSweep3.h | 1051 + .../BroadphaseCollision/btBroadphaseInterface.h | 82 + .../BroadphaseCollision/btBroadphaseProxy.cpp | 17 + .../BroadphaseCollision/btBroadphaseProxy.h | 270 + .../BroadphaseCollision/btCollisionAlgorithm.cpp | 23 + .../BroadphaseCollision/btCollisionAlgorithm.h | 80 + src/BulletCollision/BroadphaseCollision/btDbvt.cpp | 1295 + src/BulletCollision/BroadphaseCollision/btDbvt.h | 1257 + .../BroadphaseCollision/btDbvtBroadphase.cpp | 796 + .../BroadphaseCollision/btDbvtBroadphase.h | 146 + .../BroadphaseCollision/btDispatcher.cpp | 22 + .../BroadphaseCollision/btDispatcher.h | 110 + .../BroadphaseCollision/btMultiSapBroadphase.cpp | 489 + .../BroadphaseCollision/btMultiSapBroadphase.h | 151 + .../BroadphaseCollision/btOverlappingPairCache.cpp | 633 + .../BroadphaseCollision/btOverlappingPairCache.h | 469 + .../btOverlappingPairCallback.h | 40 + .../BroadphaseCollision/btQuantizedBvh.cpp | 1375 + .../BroadphaseCollision/btQuantizedBvh.h | 579 + .../BroadphaseCollision/btSimpleBroadphase.cpp | 349 + .../BroadphaseCollision/btSimpleBroadphase.h | 171 + src/BulletCollision/CMakeLists.txt | 279 + .../CollisionDispatch/SphereTriangleDetector.cpp | 201 + .../CollisionDispatch/SphereTriangleDetector.h | 51 + .../btActivatingCollisionAlgorithm.cpp | 47 + .../btActivatingCollisionAlgorithm.h | 36 + .../btBox2dBox2dCollisionAlgorithm.cpp | 435 + .../btBox2dBox2dCollisionAlgorithm.h | 66 + .../btBoxBoxCollisionAlgorithm.cpp | 85 + .../CollisionDispatch/btBoxBoxCollisionAlgorithm.h | 66 + .../CollisionDispatch/btBoxBoxDetector.cpp | 718 + .../CollisionDispatch/btBoxBoxDetector.h | 44 + .../CollisionDispatch/btCollisionConfiguration.h | 48 + .../CollisionDispatch/btCollisionCreateFunc.h | 45 + .../CollisionDispatch/btCollisionDispatcher.cpp | 310 + .../CollisionDispatch/btCollisionDispatcher.h | 172 + .../CollisionDispatch/btCollisionObject.cpp | 116 + .../CollisionDispatch/btCollisionObject.h | 524 + .../CollisionDispatch/btCollisionWorld.cpp | 1518 + .../CollisionDispatch/btCollisionWorld.h | 509 + .../btCompoundCollisionAlgorithm.cpp | 353 + .../btCompoundCollisionAlgorithm.h | 86 + .../btConvex2dConvex2dAlgorithm.cpp | 247 + .../btConvex2dConvex2dAlgorithm.h | 95 + .../btConvexConcaveCollisionAlgorithm.cpp | 312 + .../btConvexConcaveCollisionAlgorithm.h | 116 + .../CollisionDispatch/btConvexConvexAlgorithm.cpp | 739 + .../CollisionDispatch/btConvexConvexAlgorithm.h | 109 + .../btConvexPlaneCollisionAlgorithm.cpp | 173 + .../btConvexPlaneCollisionAlgorithm.h | 84 + .../btDefaultCollisionConfiguration.cpp | 309 + .../btDefaultCollisionConfiguration.h | 137 + .../btEmptyCollisionAlgorithm.cpp | 34 + .../CollisionDispatch/btEmptyCollisionAlgorithm.h | 54 + .../CollisionDispatch/btGhostObject.cpp | 171 + .../CollisionDispatch/btGhostObject.h | 175 + .../CollisionDispatch/btInternalEdgeUtility.cpp | 842 + .../CollisionDispatch/btInternalEdgeUtility.h | 46 + .../CollisionDispatch/btManifoldResult.cpp | 135 + .../CollisionDispatch/btManifoldResult.h | 128 + .../btSimulationIslandManager.cpp | 450 + .../CollisionDispatch/btSimulationIslandManager.h | 81 + .../btSphereBoxCollisionAlgorithm.cpp | 260 + .../btSphereBoxCollisionAlgorithm.h | 75 + .../btSphereSphereCollisionAlgorithm.cpp | 105 + .../btSphereSphereCollisionAlgorithm.h | 66 + .../btSphereTriangleCollisionAlgorithm.cpp | 84 + .../btSphereTriangleCollisionAlgorithm.h | 69 + .../CollisionDispatch/btUnionFind.cpp | 82 + .../CollisionDispatch/btUnionFind.h | 129 + .../CollisionShapes/btBox2dShape.cpp | 42 + src/BulletCollision/CollisionShapes/btBox2dShape.h | 369 + src/BulletCollision/CollisionShapes/btBoxShape.cpp | 51 + src/BulletCollision/CollisionShapes/btBoxShape.h | 312 + .../CollisionShapes/btBvhTriangleMeshShape.cpp | 466 + .../CollisionShapes/btBvhTriangleMeshShape.h | 139 + .../CollisionShapes/btCapsuleShape.cpp | 171 + .../CollisionShapes/btCapsuleShape.h | 173 + .../CollisionShapes/btCollisionMargin.h | 27 + .../CollisionShapes/btCollisionShape.cpp | 119 + .../CollisionShapes/btCollisionShape.h | 150 + .../CollisionShapes/btCompoundShape.cpp | 356 + .../CollisionShapes/btCompoundShape.h | 212 + .../CollisionShapes/btConcaveShape.cpp | 27 + .../CollisionShapes/btConcaveShape.h | 60 + .../CollisionShapes/btConeShape.cpp | 143 + src/BulletCollision/CollisionShapes/btConeShape.h | 103 + .../CollisionShapes/btConvex2dShape.cpp | 92 + .../CollisionShapes/btConvex2dShape.h | 80 + .../CollisionShapes/btConvexHullShape.cpp | 255 + .../CollisionShapes/btConvexHullShape.h | 122 + .../CollisionShapes/btConvexInternalShape.cpp | 151 + .../CollisionShapes/btConvexInternalShape.h | 224 + .../CollisionShapes/btConvexPointCloudShape.cpp | 157 + .../CollisionShapes/btConvexPointCloudShape.h | 105 + .../CollisionShapes/btConvexPolyhedron.cpp | 296 + .../CollisionShapes/btConvexPolyhedron.h | 62 + .../CollisionShapes/btConvexShape.cpp | 446 + .../CollisionShapes/btConvexShape.h | 84 + .../CollisionShapes/btConvexTriangleMeshShape.cpp | 315 + .../CollisionShapes/btConvexTriangleMeshShape.h | 75 + .../CollisionShapes/btCylinderShape.cpp | 281 + .../CollisionShapes/btCylinderShape.h | 200 + .../CollisionShapes/btEmptyShape.cpp | 50 + src/BulletCollision/CollisionShapes/btEmptyShape.h | 70 + .../CollisionShapes/btHeightfieldTerrainShape.cpp | 411 + .../CollisionShapes/btHeightfieldTerrainShape.h | 161 + src/BulletCollision/CollisionShapes/btMaterial.h | 35 + .../CollisionShapes/btMinkowskiSumShape.cpp | 60 + .../CollisionShapes/btMinkowskiSumShape.h | 60 + .../CollisionShapes/btMultiSphereShape.cpp | 167 + .../CollisionShapes/btMultiSphereShape.h | 99 + .../btMultimaterialTriangleMeshShape.cpp | 45 + .../btMultimaterialTriangleMeshShape.h | 120 + .../CollisionShapes/btOptimizedBvh.cpp | 391 + .../CollisionShapes/btOptimizedBvh.h | 65 + .../CollisionShapes/btPolyhedralConvexShape.cpp | 475 + .../CollisionShapes/btPolyhedralConvexShape.h | 112 + .../btScaledBvhTriangleMeshShape.cpp | 123 + .../CollisionShapes/btScaledBvhTriangleMeshShape.h | 93 + .../CollisionShapes/btShapeHull.cpp | 170 + src/BulletCollision/CollisionShapes/btShapeHull.h | 59 + .../CollisionShapes/btSphereShape.cpp | 71 + .../CollisionShapes/btSphereShape.h | 73 + .../CollisionShapes/btStaticPlaneShape.cpp | 107 + .../CollisionShapes/btStaticPlaneShape.h | 103 + .../CollisionShapes/btStridingMeshInterface.cpp | 381 + .../CollisionShapes/btStridingMeshInterface.h | 162 + .../CollisionShapes/btTetrahedronShape.cpp | 218 + .../CollisionShapes/btTetrahedronShape.h | 74 + .../CollisionShapes/btTriangleBuffer.cpp | 35 + .../CollisionShapes/btTriangleBuffer.h | 69 + .../CollisionShapes/btTriangleCallback.cpp | 28 + .../CollisionShapes/btTriangleCallback.h | 42 + .../CollisionShapes/btTriangleIndexVertexArray.cpp | 95 + .../CollisionShapes/btTriangleIndexVertexArray.h | 133 + .../btTriangleIndexVertexMaterialArray.cpp | 86 + .../btTriangleIndexVertexMaterialArray.h | 84 + .../CollisionShapes/btTriangleInfoMap.h | 241 + .../CollisionShapes/btTriangleMesh.cpp | 140 + .../CollisionShapes/btTriangleMesh.h | 69 + .../CollisionShapes/btTriangleMeshShape.cpp | 211 + .../CollisionShapes/btTriangleMeshShape.h | 89 + .../CollisionShapes/btTriangleShape.h | 182 + .../CollisionShapes/btUniformScalingShape.cpp | 160 + .../CollisionShapes/btUniformScalingShape.h | 87 + src/BulletCollision/Doxyfile | 746 + src/BulletCollision/Gimpact/btBoxCollision.h | 647 + src/BulletCollision/Gimpact/btClipPolygon.h | 182 + .../Gimpact/btContactProcessing.cpp | 181 + src/BulletCollision/Gimpact/btContactProcessing.h | 145 + src/BulletCollision/Gimpact/btGImpactBvh.cpp | 498 + src/BulletCollision/Gimpact/btGImpactBvh.h | 396 + .../Gimpact/btGImpactCollisionAlgorithm.cpp | 904 + .../Gimpact/btGImpactCollisionAlgorithm.h | 306 + src/BulletCollision/Gimpact/btGImpactMassUtil.h | 60 + .../Gimpact/btGImpactQuantizedBvh.cpp | 528 + .../Gimpact/btGImpactQuantizedBvh.h | 372 + src/BulletCollision/Gimpact/btGImpactShape.cpp | 203 + src/BulletCollision/Gimpact/btGImpactShape.h | 1171 + .../Gimpact/btGenericPoolAllocator.cpp | 283 + .../Gimpact/btGenericPoolAllocator.h | 163 + src/BulletCollision/Gimpact/btGeometryOperations.h | 212 + src/BulletCollision/Gimpact/btQuantization.h | 88 + src/BulletCollision/Gimpact/btTriangleShapeEx.cpp | 218 + src/BulletCollision/Gimpact/btTriangleShapeEx.h | 180 + src/BulletCollision/Gimpact/gim_array.h | 326 + .../Gimpact/gim_basic_geometry_operations.h | 543 + src/BulletCollision/Gimpact/gim_bitset.h | 123 + src/BulletCollision/Gimpact/gim_box_collision.h | 590 + src/BulletCollision/Gimpact/gim_box_set.cpp | 182 + src/BulletCollision/Gimpact/gim_box_set.h | 674 + src/BulletCollision/Gimpact/gim_clip_polygon.h | 210 + src/BulletCollision/Gimpact/gim_contact.cpp | 146 + src/BulletCollision/Gimpact/gim_contact.h | 164 + src/BulletCollision/Gimpact/gim_geom_types.h | 97 + src/BulletCollision/Gimpact/gim_geometry.h | 42 + src/BulletCollision/Gimpact/gim_hash_table.h | 902 + src/BulletCollision/Gimpact/gim_linear_math.h | 1573 + src/BulletCollision/Gimpact/gim_math.h | 157 + src/BulletCollision/Gimpact/gim_memory.cpp | 135 + src/BulletCollision/Gimpact/gim_memory.h | 190 + src/BulletCollision/Gimpact/gim_radixsort.h | 406 + src/BulletCollision/Gimpact/gim_tri_collision.cpp | 640 + src/BulletCollision/Gimpact/gim_tri_collision.h | 379 + .../btContinuousConvexCollision.cpp | 243 + .../btContinuousConvexCollision.h | 59 + .../NarrowPhaseCollision/btConvexCast.cpp | 20 + .../NarrowPhaseCollision/btConvexCast.h | 73 + .../btConvexPenetrationDepthSolver.h | 42 + .../btDiscreteCollisionDetectorInterface.h | 91 + .../NarrowPhaseCollision/btGjkConvexCast.cpp | 176 + .../NarrowPhaseCollision/btGjkConvexCast.h | 50 + .../NarrowPhaseCollision/btGjkEpa2.cpp | 989 + .../NarrowPhaseCollision/btGjkEpa2.h | 75 + .../btGjkEpaPenetrationDepthSolver.cpp | 66 + .../btGjkEpaPenetrationDepthSolver.h | 43 + .../NarrowPhaseCollision/btGjkPairDetector.cpp | 457 + .../NarrowPhaseCollision/btGjkPairDetector.h | 103 + .../NarrowPhaseCollision/btManifoldPoint.h | 158 + .../btMinkowskiPenetrationDepthSolver.cpp | 362 + .../btMinkowskiPenetrationDepthSolver.h | 40 + .../NarrowPhaseCollision/btPersistentManifold.cpp | 302 + .../NarrowPhaseCollision/btPersistentManifold.h | 228 + .../NarrowPhaseCollision/btPointCollector.h | 64 + .../btPolyhedralContactClipping.cpp | 440 + .../btPolyhedralContactClipping.h | 46 + .../NarrowPhaseCollision/btRaycastCallback.cpp | 177 + .../NarrowPhaseCollision/btRaycastCallback.h | 72 + .../btSimplexSolverInterface.h | 63 + .../btSubSimplexConvexCast.cpp | 160 + .../NarrowPhaseCollision/btSubSimplexConvexCast.h | 50 + .../btVoronoiSimplexSolver.cpp | 609 + .../NarrowPhaseCollision/btVoronoiSimplexSolver.h | 179 + src/BulletCollision/ibmsdk/Makefile | 112 + src/BulletCollision/premake4.lua | 11 + src/BulletDynamics/CMakeLists.txt | 112 + .../Character/btCharacterControllerInterface.h | 46 + .../Character/btKinematicCharacterController.cpp | 641 + .../Character/btKinematicCharacterController.h | 163 + .../ConstraintSolver/btConeTwistConstraint.cpp | 1132 + .../ConstraintSolver/btConeTwistConstraint.h | 346 + .../ConstraintSolver/btConstraintSolver.h | 52 + .../ConstraintSolver/btContactConstraint.cpp | 178 + .../ConstraintSolver/btContactConstraint.h | 71 + .../ConstraintSolver/btContactSolverInfo.h | 87 + .../ConstraintSolver/btGeneric6DofConstraint.cpp | 1078 + .../ConstraintSolver/btGeneric6DofConstraint.h | 614 + .../btGeneric6DofSpringConstraint.cpp | 185 + .../btGeneric6DofSpringConstraint.h | 99 + .../ConstraintSolver/btHinge2Constraint.cpp | 66 + .../ConstraintSolver/btHinge2Constraint.h | 58 + .../ConstraintSolver/btHingeConstraint.cpp | 1034 + .../ConstraintSolver/btHingeConstraint.h | 381 + .../ConstraintSolver/btJacobianEntry.h | 156 + .../ConstraintSolver/btPoint2PointConstraint.cpp | 230 + .../ConstraintSolver/btPoint2PointConstraint.h | 161 + .../btSequentialImpulseConstraintSolver.cpp | 1269 + .../btSequentialImpulseConstraintSolver.h | 130 + .../ConstraintSolver/btSliderConstraint.cpp | 857 + .../ConstraintSolver/btSliderConstraint.h | 333 + .../ConstraintSolver/btSolve2LinearConstraint.cpp | 255 + .../ConstraintSolver/btSolve2LinearConstraint.h | 107 + src/BulletDynamics/ConstraintSolver/btSolverBody.h | 191 + .../ConstraintSolver/btSolverConstraint.h | 98 + .../ConstraintSolver/btTypedConstraint.cpp | 220 + .../ConstraintSolver/btTypedConstraint.h | 452 + .../ConstraintSolver/btUniversalConstraint.cpp | 87 + .../ConstraintSolver/btUniversalConstraint.h | 62 + src/BulletDynamics/Dynamics/Bullet-C-API.cpp | 405 + src/BulletDynamics/Dynamics/btActionInterface.h | 46 + .../Dynamics/btDiscreteDynamicsWorld.cpp | 1257 + .../Dynamics/btDiscreteDynamicsWorld.h | 203 + src/BulletDynamics/Dynamics/btDynamicsWorld.h | 151 + src/BulletDynamics/Dynamics/btRigidBody.cpp | 403 + src/BulletDynamics/Dynamics/btRigidBody.h | 691 + .../Dynamics/btSimpleDynamicsWorld.cpp | 280 + .../Dynamics/btSimpleDynamicsWorld.h | 89 + src/BulletDynamics/Vehicle/btRaycastVehicle.cpp | 771 + src/BulletDynamics/Vehicle/btRaycastVehicle.h | 236 + src/BulletDynamics/Vehicle/btVehicleRaycaster.h | 35 + src/BulletDynamics/Vehicle/btWheelInfo.cpp | 56 + src/BulletDynamics/Vehicle/btWheelInfo.h | 119 + src/BulletDynamics/ibmsdk/Makefile | 53 + src/BulletDynamics/premake4.lua | 11 + src/BulletMultiThreaded/CMakeLists.txt | 123 + .../GpuSoftBodySolvers/CMakeLists.txt | 13 + .../GpuSoftBodySolvers/DX11/CMakeLists.txt | 83 + .../GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl | 95 + .../DX11/HLSL/ComputeBounds.hlsl | 83 + .../GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl | 41 + .../DX11/HLSL/OutputToVertexArray.hlsl | 63 + .../GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl | 44 + .../DX11/HLSL/SolvePositions.hlsl | 55 + .../DX11/HLSL/SolvePositionsSIMDBatched.hlsl | 147 + .../DX11/HLSL/UpdateConstants.hlsl | 48 + .../GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl | 49 + .../DX11/HLSL/UpdateNormals.hlsl | 98 + .../DX11/HLSL/UpdatePositions.hlsl | 44 + .../DX11/HLSL/UpdatePositionsFromVelocities.hlsl | 35 + .../GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl | 55 + .../HLSL/solveCollisionsAndUpdateVelocities.hlsl | 170 + ...veCollisionsAndUpdateVelocitiesSIMDBatched.hlsl | 191 + .../DX11/btSoftBodySolverBuffer_DX11.h | 323 + .../DX11/btSoftBodySolverLinkData_DX11.h | 103 + .../DX11/btSoftBodySolverLinkData_DX11SIMDAware.h | 173 + .../DX11/btSoftBodySolverTriangleData_DX11.h | 96 + .../DX11/btSoftBodySolverVertexBuffer_DX11.h | 107 + .../DX11/btSoftBodySolverVertexData_DX11.h | 63 + .../DX11/btSoftBodySolver_DX11.cpp | 2236 + .../DX11/btSoftBodySolver_DX11.h | 691 + .../DX11/btSoftBodySolver_DX11SIMDAware.cpp | 1051 + .../DX11/btSoftBodySolver_DX11SIMDAware.h | 81 + .../GpuSoftBodySolvers/DX11/premake4.lua | 23 + .../GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt | 62 + .../GpuSoftBodySolvers/OpenCL/AMD/premake4.lua | 27 + .../GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt | 77 + .../GpuSoftBodySolvers/OpenCL/CMakeLists.txt | 17 + .../GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt | 82 + .../GpuSoftBodySolvers/OpenCL/Intel/premake4.lua | 27 + .../OpenCL/MiniCL/CMakeLists.txt | 75 + .../OpenCL/MiniCL/MiniCLTaskWrap.cpp | 249 + .../OpenCL/NVidia/CMakeLists.txt | 81 + .../GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua | 27 + .../OpenCL/OpenCLC10/ApplyForces.cl | 102 + .../OpenCL/OpenCLC10/ComputeBounds.cl | 82 + .../OpenCL/OpenCLC10/Integrate.cl | 35 + .../OpenCL/OpenCLC10/OutputToVertexArray.cl | 46 + .../OpenCL/OpenCLC10/PrepareLinks.cl | 38 + .../SolveCollisionsAndUpdateVelocities.cl | 204 + ...olveCollisionsAndUpdateVelocitiesSIMDBatched.cl | 242 + .../OpenCL/OpenCLC10/SolvePositions.cl | 57 + .../OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl | 130 + .../OpenCL/OpenCLC10/UpdateConstants.cl | 44 + .../OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl | 25 + .../OpenCL/OpenCLC10/UpdateNodes.cl | 39 + .../OpenCL/OpenCLC10/UpdateNormals.cl | 102 + .../OpenCL/OpenCLC10/UpdatePositions.cl | 34 + .../OpenCLC10/UpdatePositionsFromVelocities.cl | 28 + .../OpenCL/OpenCLC10/VSolveLinks.cl | 45 + .../OpenCL/btSoftBodySolverBuffer_OpenCL.h | 209 + .../OpenCL/btSoftBodySolverLinkData_OpenCL.h | 99 + .../btSoftBodySolverLinkData_OpenCLSIMDAware.h | 169 + .../OpenCL/btSoftBodySolverOutputCLtoGL.cpp | 126 + .../OpenCL/btSoftBodySolverOutputCLtoGL.h | 62 + .../OpenCL/btSoftBodySolverTriangleData_OpenCL.h | 84 + .../OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h | 166 + .../OpenCL/btSoftBodySolverVertexData_OpenCL.h | 52 + .../OpenCL/btSoftBodySolver_OpenCL.cpp | 1820 + .../OpenCL/btSoftBodySolver_OpenCL.h | 527 + .../OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp | 1101 + .../OpenCL/btSoftBodySolver_OpenCLSIMDAware.h | 81 + .../Shared/btSoftBodySolverData.h | 748 + src/BulletMultiThreaded/HeapManager.h | 117 + src/BulletMultiThreaded/Makefile.original | 187 + src/BulletMultiThreaded/PlatformDefinitions.h | 99 + src/BulletMultiThreaded/PosixThreadSupport.cpp | 399 + src/BulletMultiThreaded/PosixThreadSupport.h | 142 + src/BulletMultiThreaded/PpuAddressSpace.h | 37 + .../SequentialThreadSupport.cpp | 169 + src/BulletMultiThreaded/SequentialThreadSupport.h | 96 + .../SpuCollisionObjectWrapper.cpp | 48 + .../SpuCollisionObjectWrapper.h | 40 + .../SpuCollisionTaskProcess.cpp | 317 + src/BulletMultiThreaded/SpuCollisionTaskProcess.h | 163 + .../SpuContactManifoldCollisionAlgorithm.cpp | 69 + .../SpuContactManifoldCollisionAlgorithm.h | 120 + src/BulletMultiThreaded/SpuDoubleBuffer.h | 126 + src/BulletMultiThreaded/SpuFakeDma.cpp | 215 + src/BulletMultiThreaded/SpuFakeDma.h | 135 + .../SpuGatheringCollisionDispatcher.cpp | 276 + .../SpuGatheringCollisionDispatcher.h | 72 + src/BulletMultiThreaded/SpuLibspe2Support.cpp | 257 + src/BulletMultiThreaded/SpuLibspe2Support.h | 180 + .../SpuNarrowPhaseCollisionTask/Box.h | 167 + .../SpuCollisionShapes.cpp | 302 + .../SpuCollisionShapes.h | 128 + .../SpuContactResult.cpp | 248 + .../SpuNarrowPhaseCollisionTask/SpuContactResult.h | 106 + .../SpuConvexPenetrationDepthSolver.h | 51 + .../SpuGatheringCollisionTask.cpp | 1415 + .../SpuGatheringCollisionTask.h | 140 + .../SpuNarrowPhaseCollisionTask/SpuLocalSupport.h | 19 + .../SpuMinkowskiPenetrationDepthSolver.cpp | 348 + .../SpuMinkowskiPenetrationDepthSolver.h | 48 + .../SpuPreferredPenetrationDirections.h | 70 + .../SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp | 1160 + .../SpuNarrowPhaseCollisionTask/boxBoxDistance.h | 65 + .../SpuNarrowPhaseCollisionTask/readme.txt | 1 + .../SpuSampleTask/SpuSampleTask.cpp | 214 + .../SpuSampleTask/SpuSampleTask.h | 54 + src/BulletMultiThreaded/SpuSampleTask/readme.txt | 1 + src/BulletMultiThreaded/SpuSampleTaskProcess.cpp | 222 + src/BulletMultiThreaded/SpuSampleTaskProcess.h | 153 + src/BulletMultiThreaded/SpuSync.h | 149 + src/BulletMultiThreaded/TrbDynBody.h | 79 + src/BulletMultiThreaded/TrbStateVec.h | 339 + src/BulletMultiThreaded/Win32ThreadSupport.cpp | 446 + src/BulletMultiThreaded/Win32ThreadSupport.h | 138 + src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp | 590 + src/BulletMultiThreaded/btGpu3DGridBroadphase.h | 138 + .../btGpu3DGridBroadphaseSharedCode.h | 430 + .../btGpu3DGridBroadphaseSharedDefs.h | 61 + .../btGpu3DGridBroadphaseSharedTypes.h | 67 + src/BulletMultiThreaded/btGpuDefines.h | 211 + src/BulletMultiThreaded/btGpuUtilsSharedCode.h | 55 + src/BulletMultiThreaded/btGpuUtilsSharedDefs.h | 52 + .../btParallelConstraintSolver.cpp | 1391 + .../btParallelConstraintSolver.h | 285 + .../btThreadSupportInterface.cpp | 22 + src/BulletMultiThreaded/btThreadSupportInterface.h | 85 + src/BulletMultiThreaded/vectormath2bullet.h | 73 + src/BulletSoftBody/CMakeLists.txt | 65 + src/BulletSoftBody/btDefaultSoftBodySolver.cpp | 151 + src/BulletSoftBody/btDefaultSoftBodySolver.h | 63 + src/BulletSoftBody/btSoftBody.cpp | 3538 + src/BulletSoftBody/btSoftBody.h | 987 + .../btSoftBodyConcaveCollisionAlgorithm.cpp | 368 + .../btSoftBodyConcaveCollisionAlgorithm.h | 153 + src/BulletSoftBody/btSoftBodyData.h | 217 + src/BulletSoftBody/btSoftBodyHelpers.cpp | 1055 + src/BulletSoftBody/btSoftBodyHelpers.h | 143 + src/BulletSoftBody/btSoftBodyInternals.h | 930 + .../btSoftBodyRigidBodyCollisionConfiguration.cpp | 134 + .../btSoftBodyRigidBodyCollisionConfiguration.h | 48 + src/BulletSoftBody/btSoftBodySolverVertexBuffer.h | 165 + src/BulletSoftBody/btSoftBodySolvers.h | 154 + .../btSoftRigidCollisionAlgorithm.cpp | 84 + src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h | 75 + src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp | 365 + src/BulletSoftBody/btSoftRigidDynamicsWorld.h | 107 + .../btSoftSoftCollisionAlgorithm.cpp | 47 + src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h | 69 + src/BulletSoftBody/btSparseSDF.h | 306 + src/BulletSoftBody/premake4.lua | 11 + src/CMakeLists.txt | 28 + src/LinearMath/CMakeLists.txt | 66 + src/LinearMath/btAabbUtil2.h | 236 + src/LinearMath/btAlignedAllocator.cpp | 181 + src/LinearMath/btAlignedAllocator.h | 107 + src/LinearMath/btAlignedObjectArray.h | 494 + src/LinearMath/btConvexHull.cpp | 1174 + src/LinearMath/btConvexHull.h | 241 + src/LinearMath/btConvexHullComputer.cpp | 2751 + src/LinearMath/btConvexHullComputer.h | 103 + src/LinearMath/btDefaultMotionState.h | 40 + src/LinearMath/btGeometryUtil.cpp | 185 + src/LinearMath/btGeometryUtil.h | 42 + src/LinearMath/btGrahamScan2dConvexHull.h | 110 + src/LinearMath/btHashMap.h | 450 + src/LinearMath/btIDebugDraw.h | 418 + src/LinearMath/btList.h | 73 + src/LinearMath/btMatrix3x3.h | 771 + src/LinearMath/btMinMax.h | 71 + src/LinearMath/btMotionState.h | 40 + src/LinearMath/btPoolAllocator.h | 121 + src/LinearMath/btQuadWord.h | 180 + src/LinearMath/btQuaternion.h | 430 + src/LinearMath/btQuickprof.cpp | 566 + src/LinearMath/btQuickprof.h | 203 + src/LinearMath/btRandom.h | 42 + src/LinearMath/btScalar.h | 539 + src/LinearMath/btSerializer.cpp | 841 + src/LinearMath/btSerializer.h | 639 + src/LinearMath/btStackAlloc.h | 116 + src/LinearMath/btTransform.h | 307 + src/LinearMath/btTransformUtil.h | 228 + src/LinearMath/btVector3.h | 766 + src/LinearMath/ibmsdk/Makefile | 39 + src/LinearMath/premake4.lua | 11 + src/Makefile.am | 554 + src/MiniCL/CMakeLists.txt | 66 + src/MiniCL/MiniCL.cpp | 784 + src/MiniCL/MiniCLTask/MiniCLTask.cpp | 74 + src/MiniCL/MiniCLTask/MiniCLTask.h | 62 + src/MiniCL/MiniCLTaskScheduler.cpp | 519 + src/MiniCL/MiniCLTaskScheduler.h | 194 + src/MiniCL/cl.h | 867 + src/MiniCL/cl_MiniCL_Defs.h | 439 + src/MiniCL/cl_gl.h | 113 + src/MiniCL/cl_platform.h | 254 + src/btBulletCollisionCommon.h | 69 + src/btBulletDynamicsCommon.h | 48 + src/ibmsdk/Makefile | 16 + src/vectormath/scalar/boolInVec.h | 225 + src/vectormath/scalar/floatInVec.h | 343 + src/vectormath/scalar/mat_aos.h | 1630 + src/vectormath/scalar/quat_aos.h | 433 + src/vectormath/scalar/vec_aos.h | 1426 + src/vectormath/scalar/vectormath_aos.h | 1872 + src/vectormath/sse/boolInVec.h | 247 + src/vectormath/sse/floatInVec.h | 340 + src/vectormath/sse/mat_aos.h | 2190 + src/vectormath/sse/quat_aos.h | 579 + src/vectormath/sse/vec_aos.h | 1455 + src/vectormath/sse/vecidx_aos.h | 80 + src/vectormath/sse/vectormath_aos.h | 2547 + src/vectormath/vmInclude.h | 27 + test1.oec | 227 + 2857 files changed, 920891 insertions(+) create mode 100644 AUTHORS create mode 100644 BspDemo.bsp create mode 100644 BulletLicense.txt create mode 100644 Bullet_User_Manual.pdf create mode 100644 CMakeLists.txt create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 Demos/AllBulletDemos/CMakeLists.txt create mode 100644 Demos/AllBulletDemos/DemoEntries.cpp create mode 100644 Demos/AllBulletDemos/DemoEntries.h create mode 100644 Demos/AllBulletDemos/Main.cpp create mode 100644 Demos/AllBulletDemos/Makefile.am create mode 100644 Demos/BasicDemo/BasicDemo.cpp create mode 100644 Demos/BasicDemo/BasicDemo.h create mode 100644 Demos/BasicDemo/CMakeLists.txt create mode 100644 Demos/BasicDemo/Makefile.am create mode 100644 Demos/BasicDemo/Makefile.original create mode 100644 Demos/BasicDemo/Win32BasicDemo.cpp create mode 100644 Demos/BasicDemo/main.cpp create mode 100644 Demos/Benchmarks/BenchmarkDemo.cpp create mode 100644 Demos/Benchmarks/BenchmarkDemo.h create mode 100644 Demos/Benchmarks/CMakeLists.txt create mode 100644 Demos/Benchmarks/Taru.mdl create mode 100644 Demos/Benchmarks/Win32BenchmarkDemo.cpp create mode 100644 Demos/Benchmarks/landscape.mdl create mode 100644 Demos/Benchmarks/main.cpp create mode 100644 Demos/Box2dDemo/Box2dDemo.cpp create mode 100644 Demos/Box2dDemo/Box2dDemo.h create mode 100644 Demos/Box2dDemo/CMakeLists.txt create mode 100644 Demos/Box2dDemo/Win32Box2dDemo.cpp create mode 100644 Demos/Box2dDemo/main.cpp create mode 100644 Demos/BspDemo/BspConverter.cpp create mode 100644 Demos/BspDemo/BspConverter.h create mode 100644 Demos/BspDemo/BspDemo.cpp create mode 100644 Demos/BspDemo/BspDemo.h create mode 100644 Demos/BspDemo/BspLoader.cpp create mode 100644 Demos/BspDemo/BspLoader.h create mode 100644 Demos/BspDemo/CMakeLists.txt create mode 100644 Demos/BspDemo/main.cpp create mode 100644 Demos/BulletDinoDemo/BulletDino.c create mode 100644 Demos/BulletDinoDemo/CMakeLists.txt create mode 100644 Demos/CMakeLists.txt create mode 100644 Demos/CcdPhysicsDemo/CMakeLists.txt create mode 100644 Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp create mode 100644 Demos/CcdPhysicsDemo/CcdPhysicsDemo.h create mode 100644 Demos/CcdPhysicsDemo/Makefile.am create mode 100644 Demos/CcdPhysicsDemo/main.cpp create mode 100644 Demos/CellSpuDemo/BasicDemo2.cpp create mode 100644 Demos/CellSpuDemo/BasicDemo2.h create mode 100755 Demos/CellSpuDemo/ibmsdk/Makefile create mode 100644 Demos/CharacterDemo/CMakeLists.txt create mode 100644 Demos/CharacterDemo/CharacterDemo.cpp create mode 100644 Demos/CharacterDemo/CharacterDemo.h create mode 100644 Demos/CharacterDemo/DynamicCharacterController.cpp create mode 100644 Demos/CharacterDemo/DynamicCharacterController.h create mode 100644 Demos/CharacterDemo/main.cpp create mode 100644 Demos/CollisionDemo/CMakeLists.txt create mode 100644 Demos/CollisionDemo/CollisionDemo.cpp create mode 100644 Demos/CollisionDemo/CollisionDemo.h create mode 100644 Demos/CollisionInterfaceDemo/CMakeLists.txt create mode 100644 Demos/CollisionInterfaceDemo/CollisionInterfaceDemo.cpp create mode 100644 Demos/CollisionInterfaceDemo/CollisionInterfaceDemo.h create mode 100644 Demos/CollisionInterfaceDemo/Win32CollisionInterfaceDemo.cpp create mode 100644 Demos/CollisionInterfaceDemo/main.cpp create mode 100644 Demos/ConcaveConvexcastDemo/CMakeLists.txt create mode 100644 Demos/ConcaveConvexcastDemo/ConcaveConvexcastDemo.cpp create mode 100644 Demos/ConcaveConvexcastDemo/ConcaveConvexcastDemo.h create mode 100644 Demos/ConcaveConvexcastDemo/main.cpp create mode 100644 Demos/ConcaveDemo/CMakeLists.txt create mode 100644 Demos/ConcaveDemo/ConcaveDemo.h create mode 100644 Demos/ConcaveDemo/ConcavePhysicsDemo.cpp create mode 100644 Demos/ConcaveDemo/Jamfile create mode 100644 Demos/ConcaveDemo/Win32ConcaveDemo.cpp create mode 100644 Demos/ConcaveDemo/main.cpp create mode 100644 Demos/ConcaveRaycastDemo/CMakeLists.txt create mode 100644 Demos/ConcaveRaycastDemo/ConcaveRaycastDemo.cpp create mode 100644 Demos/ConcaveRaycastDemo/ConcaveRaycastDemo.h create mode 100644 Demos/ConcaveRaycastDemo/main.cpp create mode 100644 Demos/ConstraintDemo/CMakeLists.txt create mode 100644 Demos/ConstraintDemo/ConstraintDemo.cpp create mode 100644 Demos/ConstraintDemo/ConstraintDemo.h create mode 100644 Demos/ConstraintDemo/Win32ConstraintDemo.cpp create mode 100644 Demos/ConstraintDemo/main.cpp create mode 100644 Demos/ContinuousConvexCollision/CMakeLists.txt create mode 100644 Demos/ContinuousConvexCollision/ContinuousConvexCollision.h create mode 100644 Demos/ContinuousConvexCollision/ContinuousConvexCollisionDemo.cpp create mode 100644 Demos/ConvexDecompositionDemo/CMakeLists.txt create mode 100644 Demos/ConvexDecompositionDemo/ConvexDecompositionDemo.cpp create mode 100644 Demos/ConvexDecompositionDemo/ConvexDecompositionDemo.h create mode 100644 Demos/ConvexDecompositionDemo/Win32ConvexDecompositionDemo.cpp create mode 100644 Demos/ConvexDecompositionDemo/main.cpp create mode 100644 Demos/ConvexDecompositionDemo/testFile32Single.bullet create mode 100644 Demos/ConvexHullDistance/CMakeLists.txt create mode 100644 Demos/ConvexHullDistance/ConvexHullDistanceDemo.cpp create mode 100644 Demos/DX11ClothDemo/CMakeLists.txt create mode 100644 Demos/DX11ClothDemo/DXUT/Core/DXUT.cpp create mode 100644 Demos/DX11ClothDemo/DXUT/Core/DXUT.h create mode 100644 Demos/DX11ClothDemo/DXUT/Core/DXUTDevice11.cpp create mode 100644 Demos/DX11ClothDemo/DXUT/Core/DXUTDevice11.h create mode 100644 Demos/DX11ClothDemo/DXUT/Core/DXUTDevice9.cpp create mode 100644 Demos/DX11ClothDemo/DXUT/Core/DXUTDevice9.h create mode 100644 Demos/DX11ClothDemo/DXUT/Core/DXUTmisc.cpp create mode 100644 Demos/DX11ClothDemo/DXUT/Core/DXUTmisc.h create mode 100644 Demos/DX11ClothDemo/DXUT/Core/dpiaware.manifest create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/DXUTLockFreePipe.h create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/DXUTShapes.cpp create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/DXUTShapes.h create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/DXUTcamera.cpp create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/DXUTcamera.h create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/DXUTgui.cpp create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/DXUTgui.h create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/DXUTguiIME.cpp create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/DXUTguiIME.h create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/DXUTres.cpp create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/DXUTres.h create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/DXUTsettingsdlg.cpp create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/DXUTsettingsdlg.h create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/ImeUi.cpp create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/ImeUi.h create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/SDKmesh.cpp create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/SDKmesh.h create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/SDKmisc.cpp create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/SDKmisc.h create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/SDKsound.cpp create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/SDKsound.h create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/SDKwavefile.cpp create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/SDKwavefile.h create mode 100644 Demos/DX11ClothDemo/DXUT/Optional/directx.ico create mode 100644 Demos/DX11ClothDemo/Media/Tiny/Tiny_skin.dds create mode 100644 Demos/DX11ClothDemo/Media/Tiny/tiny.sdkmesh create mode 100644 Demos/DX11ClothDemo/Media/Tiny/tiny.x create mode 100644 Demos/DX11ClothDemo/Media/UI/DXUTShared.fx create mode 100644 Demos/DX11ClothDemo/Media/UI/Font.dds create mode 100644 Demos/DX11ClothDemo/Media/UI/arrow.x create mode 100644 Demos/DX11ClothDemo/Media/UI/dxutcontrols.dds create mode 100644 Demos/DX11ClothDemo/amdFlag.bmp create mode 100644 Demos/DX11ClothDemo/atiFlag.bmp create mode 100644 Demos/DX11ClothDemo/btDirectComputeSupport.h create mode 100644 Demos/DX11ClothDemo/cap.h create mode 100644 Demos/DX11ClothDemo/capsule.h create mode 100644 Demos/DX11ClothDemo/cloth.h create mode 100644 Demos/DX11ClothDemo/cloth_renderer.cpp create mode 100644 Demos/DX11ClothDemo/cloth_renderer.fx create mode 100644 Demos/DX11ClothDemo/cloth_renderer.rc create mode 100644 Demos/DX11ClothDemo/cloth_renderer_PS.hlsl create mode 100644 Demos/DX11ClothDemo/cloth_renderer_VS.hlsl create mode 100644 Demos/DX11ClothDemo/cylinder.h create mode 100644 Demos/DX11ClothDemo/premake4.lua create mode 100644 Demos/DX11ClothDemo/resource.h create mode 100644 Demos/DX11ClothDemo/texture.bmp create mode 100644 Demos/DX11ClothDemo/texture.png create mode 100644 Demos/DoublePrecisionDemo/CMakeLists.txt create mode 100644 Demos/DoublePrecisionDemo/DoublePrecisionDemo.cpp create mode 100644 Demos/DoublePrecisionDemo/DoublePrecisionDemo.h create mode 100644 Demos/DynamicControlDemo/CMakeLists.txt create mode 100644 Demos/DynamicControlDemo/MotorDemo.cpp create mode 100644 Demos/DynamicControlDemo/MotorDemo.h create mode 100644 Demos/DynamicControlDemo/main.cpp create mode 100644 Demos/EPAPenDepthDemo/PenetrationTestBullet.cpp create mode 100644 Demos/ForkLiftDemo/CMakeLists.txt create mode 100644 Demos/ForkLiftDemo/ForkLiftDemo.cpp create mode 100644 Demos/ForkLiftDemo/ForkLiftDemo.h create mode 100644 Demos/ForkLiftDemo/main.cpp create mode 100644 Demos/FractureDemo/CMakeLists.txt create mode 100644 Demos/FractureDemo/FractureDemo.cpp create mode 100644 Demos/FractureDemo/FractureDemo.h create mode 100644 Demos/FractureDemo/Win32FractureDemo.cpp create mode 100644 Demos/FractureDemo/btFractureBody.cpp create mode 100644 Demos/FractureDemo/btFractureBody.h create mode 100644 Demos/FractureDemo/btFractureDynamicsWorld.cpp create mode 100644 Demos/FractureDemo/btFractureDynamicsWorld.h create mode 100644 Demos/FractureDemo/main.cpp create mode 100644 Demos/GenericJointDemo/CMakeLists.txt create mode 100644 Demos/GenericJointDemo/GenericJointDemo.cpp create mode 100644 Demos/GenericJointDemo/GenericJointDemo.h create mode 100644 Demos/GenericJointDemo/Ragdoll.cpp create mode 100644 Demos/GenericJointDemo/Ragdoll.h create mode 100644 Demos/GenericJointDemo/Win32GenericJointDemo.cpp create mode 100644 Demos/GenericJointDemo/main.cpp create mode 100644 Demos/GimpactTestDemo/BunnyMesh.h create mode 100644 Demos/GimpactTestDemo/CMakeLists.txt create mode 100644 Demos/GimpactTestDemo/GimpactTestDemo.cpp create mode 100644 Demos/GimpactTestDemo/GimpactTestDemo.h create mode 100644 Demos/GimpactTestDemo/TorusMesh.h create mode 100644 Demos/GimpactTestDemo/Win32GimpactDemo.cpp create mode 100644 Demos/GimpactTestDemo/main.cpp create mode 100644 Demos/GjkConvexCastDemo/CMakeLists.txt create mode 100644 Demos/GjkConvexCastDemo/LinearConvexCastDemo.cpp create mode 100644 Demos/GjkConvexCastDemo/LinearConvexCastDemo.h create mode 100644 Demos/GjkConvexCastDemo/main.cpp create mode 100644 Demos/Gpu2dDemo/BasicDemo.cpp create mode 100644 Demos/Gpu2dDemo/BasicDemo.h create mode 100644 Demos/Gpu2dDemo/CMakeLists.txt create mode 100644 Demos/Gpu2dDemo/Makefile.am create mode 100644 Demos/Gpu2dDemo/btGpuDemo2dCpuFunc.cpp create mode 100644 Demos/Gpu2dDemo/btGpuDemo2dSharedCode.h create mode 100644 Demos/Gpu2dDemo/btGpuDemo2dSharedDefs.h create mode 100644 Demos/Gpu2dDemo/btGpuDemo2dSharedTypes.h create mode 100644 Demos/Gpu2dDemo/btGpuDemoDynamicsWorld.cpp create mode 100644 Demos/Gpu2dDemo/btGpuDemoDynamicsWorld.h create mode 100644 Demos/Gpu2dDemo/btGpuDemoPairCache.cpp create mode 100644 Demos/Gpu2dDemo/btGpuDemoPairCache.h create mode 100644 Demos/Gpu2dDemo/main.cpp create mode 100644 Demos/Gpu2dDemo/oecakeLoader.cpp create mode 100644 Demos/Gpu2dDemo/oecakeLoader.h create mode 100644 Demos/Gpu3dDemo/BasicDemo3d.cpp create mode 100644 Demos/Gpu3dDemo/BasicDemo3d.h create mode 100644 Demos/Gpu3dDemo/CMakeLists.txt create mode 100644 Demos/Gpu3dDemo/btGpuDemo3dCpuFunc.cpp create mode 100644 Demos/Gpu3dDemo/btGpuDemo3dSharedCode.h create mode 100644 Demos/Gpu3dDemo/btGpuDemo3dSharedDefs.h create mode 100644 Demos/Gpu3dDemo/btGpuDemo3dSharedTypes.h create mode 100644 Demos/Gpu3dDemo/btGpuDemoDynamicsWorld3D.cpp create mode 100644 Demos/Gpu3dDemo/btGpuDemoDynamicsWorld3D.h create mode 100644 Demos/Gpu3dDemo/main.cpp create mode 100644 Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluid.cpp create mode 100644 Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluid.h create mode 100644 Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidBuoyantConvexShape.cpp create mode 100644 Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidBuoyantConvexShape.h create mode 100644 Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidBuoyantShapeCollisionAlgorithm.cpp create mode 100644 Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidBuoyantShapeCollisionAlgorithm.h create mode 100644 Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidCollisionShape.cpp create mode 100644 Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidCollisionShape.h create mode 100644 Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidCollisionAlgorithm.cpp create mode 100644 Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidCollisionAlgorithm.h create mode 100644 Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidCollisionConfiguration.cpp create mode 100644 Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidCollisionConfiguration.h create mode 100644 Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidDynamicsWorld.cpp create mode 100644 Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidDynamicsWorld.h create mode 100644 Demos/HeightFieldFluidDemo/CMakeLists.txt create mode 100644 Demos/HeightFieldFluidDemo/HfFluidDemo.cpp create mode 100644 Demos/HeightFieldFluidDemo/HfFluidDemo.h create mode 100644 Demos/HeightFieldFluidDemo/HfFluidDemo_GL_ShapeDrawer.cpp create mode 100644 Demos/HeightFieldFluidDemo/HfFluidDemo_GL_ShapeDrawer.h create mode 100644 Demos/HeightFieldFluidDemo/main.cpp create mode 100644 Demos/HelloWorld/CMakeLists.txt create mode 100644 Demos/HelloWorld/HelloWorld.cpp create mode 100644 Demos/InternalEdgeDemo/CMakeLists.txt create mode 100644 Demos/InternalEdgeDemo/InternalEdgeDemo.cpp create mode 100644 Demos/InternalEdgeDemo/InternalEdgeDemo.h create mode 100644 Demos/InternalEdgeDemo/Taru.mdl create mode 100644 Demos/InternalEdgeDemo/Win32InternalEdgeDemo.cpp create mode 100644 Demos/InternalEdgeDemo/main.cpp create mode 100644 Demos/Makefile.am create mode 100644 Demos/MovingConcaveDemo/CMakeLists.txt create mode 100644 Demos/MovingConcaveDemo/ConcaveDemo.h create mode 100644 Demos/MovingConcaveDemo/ConcavePhysicsDemo.cpp create mode 100644 Demos/MultiMaterialDemo/CMakeLists.txt create mode 100644 Demos/MultiMaterialDemo/MultiMaterialDemo.cpp create mode 100644 Demos/MultiMaterialDemo/MultiMaterialDemo.h create mode 100644 Demos/MultiMaterialDemo/main.cpp create mode 100644 Demos/MultiThreadedDemo/CMakeLists.txt create mode 100644 Demos/MultiThreadedDemo/Makefile.am create mode 100644 Demos/MultiThreadedDemo/MultiThreadedDemo.cpp create mode 100644 Demos/MultiThreadedDemo/MultiThreadedDemo.h create mode 100644 Demos/MultiThreadedDemo/main.cpp create mode 100644 Demos/NativeClient/bin_html/bind.js create mode 100644 Demos/NativeClient/bin_html/dragger.js create mode 100644 Demos/NativeClient/bin_html/httpd.cmd create mode 100644 Demos/NativeClient/bin_html/httpd.py create mode 100644 Demos/NativeClient/bin_html/index.html create mode 100644 Demos/NativeClient/bin_html/trackball.js create mode 100644 Demos/NativeClient/bin_html/tumbler.js create mode 100644 Demos/NativeClient/bin_html/tumbler.nmf create mode 100644 Demos/NativeClient/bin_html/vector3.js create mode 100644 Demos/NativeClient/callback.h create mode 100644 Demos/NativeClient/cube.cc create mode 100644 Demos/NativeClient/cube.h create mode 100644 Demos/NativeClient/opengl_context.cc create mode 100644 Demos/NativeClient/opengl_context.h create mode 100644 Demos/NativeClient/opengl_context_ptrs.h create mode 100644 Demos/NativeClient/premake4.lua create mode 100644 Demos/NativeClient/scripting_bridge.cc create mode 100644 Demos/NativeClient/scripting_bridge.h create mode 100644 Demos/NativeClient/shader_util.cc create mode 100644 Demos/NativeClient/shader_util.h create mode 100644 Demos/NativeClient/transforms.cc create mode 100644 Demos/NativeClient/transforms.h create mode 100644 Demos/NativeClient/tumbler.cc create mode 100644 Demos/NativeClient/tumbler.h create mode 100644 Demos/NativeClient/tumbler_module.cc create mode 100644 Demos/OpenCLClothDemo/AMD/CMakeLists.txt create mode 100644 Demos/OpenCLClothDemo/AMD/premake4.lua create mode 100644 Demos/OpenCLClothDemo/Apple/CMakeLists.txt create mode 100644 Demos/OpenCLClothDemo/CLClothDemo.sln create mode 100644 Demos/OpenCLClothDemo/CLClothDemo.vcproj create mode 100644 Demos/OpenCLClothDemo/CMakeLists.txt create mode 100644 Demos/OpenCLClothDemo/Intel/CMakeLists.txt create mode 100644 Demos/OpenCLClothDemo/Intel/premake4.lua create mode 100644 Demos/OpenCLClothDemo/MiniCL/CMakeLists.txt create mode 100644 Demos/OpenCLClothDemo/NVidia/CMakeLists.txt create mode 100644 Demos/OpenCLClothDemo/NVidia/premake4.lua create mode 100644 Demos/OpenCLClothDemo/btOpenCLSupport.h create mode 100644 Demos/OpenCLClothDemo/cl_cloth_demo.cpp create mode 100644 Demos/OpenCLClothDemo/cloth.h create mode 100644 Demos/OpenCLClothDemo/clstuff.cpp create mode 100644 Demos/OpenCLClothDemo/clstuff.h create mode 100644 Demos/OpenCLClothDemo/clstuff.hpp create mode 100644 Demos/OpenCLClothDemo/fragment.glsl create mode 100644 Demos/OpenCLClothDemo/gl_win.cpp create mode 100644 Demos/OpenCLClothDemo/gl_win.h create mode 100644 Demos/OpenCLClothDemo/gl_win.hpp create mode 100644 Demos/OpenCLClothDemo/shaders.cl create mode 100644 Demos/OpenCLClothDemo/vertex.glsl create mode 100644 Demos/OpenGL/CMakeLists.txt create mode 100644 Demos/OpenGL/DebugCastResult.h create mode 100644 Demos/OpenGL/DemoApplication.cpp create mode 100644 Demos/OpenGL/DemoApplication.h create mode 100644 Demos/OpenGL/GLDebugDrawer.cpp create mode 100644 Demos/OpenGL/GLDebugDrawer.h create mode 100644 Demos/OpenGL/GLDebugFont.cpp create mode 100644 Demos/OpenGL/GLDebugFont.h create mode 100644 Demos/OpenGL/GL_DialogDynamicsWorld.cpp create mode 100644 Demos/OpenGL/GL_DialogDynamicsWorld.h create mode 100644 Demos/OpenGL/GL_DialogWindow.cpp create mode 100644 Demos/OpenGL/GL_DialogWindow.h create mode 100644 Demos/OpenGL/GL_ShapeDrawer.cpp create mode 100644 Demos/OpenGL/GL_ShapeDrawer.h create mode 100644 Demos/OpenGL/GL_Simplex1to4.cpp create mode 100644 Demos/OpenGL/GL_Simplex1to4.h create mode 100644 Demos/OpenGL/GlutDemoApplication.cpp create mode 100644 Demos/OpenGL/GlutDemoApplication.h create mode 100644 Demos/OpenGL/GlutStuff.cpp create mode 100644 Demos/OpenGL/GlutStuff.h create mode 100644 Demos/OpenGL/Makefile.am create mode 100644 Demos/OpenGL/RenderTexture.cpp create mode 100644 Demos/OpenGL/RenderTexture.h create mode 100644 Demos/OpenGL/Win32AppMain.cpp create mode 100644 Demos/OpenGL/Win32DemoApplication.cpp create mode 100644 Demos/OpenGL/Win32DemoApplication.h create mode 100644 Demos/OpenGL/ibmsdk/Makefile create mode 100644 Demos/OpenGL/premake4.lua create mode 100644 Demos/OpenGL/stb_image.cpp create mode 100644 Demos/OpenGL/stb_image.h create mode 100644 Demos/OpenPL_Demo/CApi.cpp create mode 100644 Demos/OpenPL_Demo/OpenPL_Demo.c create mode 100644 Demos/ParticlesOpenCL/AMD/CMakeLists.txt create mode 100644 Demos/ParticlesOpenCL/Apple/CMakeLists.txt create mode 100644 Demos/ParticlesOpenCL/CMakeLists.txt create mode 100644 Demos/ParticlesOpenCL/Intel/CMakeLists.txt create mode 100644 Demos/ParticlesOpenCL/MiniCL/CMakeLists.txt create mode 100644 Demos/ParticlesOpenCL/MiniCL/MiniCLTaskWrap.cpp create mode 100644 Demos/ParticlesOpenCL/NVidia/CMakeLists.txt create mode 100644 Demos/ParticlesOpenCL/ParticlesDemo.cpp create mode 100644 Demos/ParticlesOpenCL/ParticlesDemo.h create mode 100644 Demos/ParticlesOpenCL/ParticlesOCL.cl create mode 100644 Demos/ParticlesOpenCL/btParticlesDemoDynamicsWorld.cpp create mode 100644 Demos/ParticlesOpenCL/btParticlesDynamicsWorld.h create mode 100644 Demos/ParticlesOpenCL/btParticlesSharedDefs.h create mode 100644 Demos/ParticlesOpenCL/btParticlesSharedTypes.h create mode 100644 Demos/ParticlesOpenCL/main.cpp create mode 100644 Demos/ParticlesOpenCL/shaders.cpp create mode 100644 Demos/ParticlesOpenCL/shaders.h create mode 100644 Demos/RagdollDemo/CMakeLists.txt create mode 100644 Demos/RagdollDemo/RagdollDemo.cpp create mode 100644 Demos/RagdollDemo/RagdollDemo.h create mode 100644 Demos/RagdollDemo/main.cpp create mode 100644 Demos/Raytracer/CMakeLists.txt create mode 100644 Demos/Raytracer/Raytracer.cpp create mode 100644 Demos/Raytracer/Raytracer.h create mode 100644 Demos/Raytracer/main.cpp create mode 100644 Demos/SerializeDemo/AMD/CMakeLists.txt create mode 100644 Demos/SerializeDemo/AMD/premake4.lua create mode 100644 Demos/SerializeDemo/CMakeLists.txt create mode 100644 Demos/SerializeDemo/SerializeDemo.cpp create mode 100644 Demos/SerializeDemo/SerializeDemo.h create mode 100644 Demos/SerializeDemo/Win32SerializeDemo.cpp create mode 100644 Demos/SerializeDemo/main.cpp create mode 100644 Demos/SerializeDemo/testFile.bullet create mode 100644 Demos/SerializeDemo/testFileCloth.bullet create mode 100644 Demos/SharedOpenCL/btOpenCLInclude.h create mode 100644 Demos/SharedOpenCL/btOpenCLUtils.cpp create mode 100644 Demos/SharedOpenCL/btOpenCLUtils.h create mode 100644 Demos/SharedOpenCL/clew.c create mode 100644 Demos/SharedOpenCL/clew.h create mode 100644 Demos/SimplexDemo/CMakeLists.txt create mode 100644 Demos/SimplexDemo/SimplexDemo.cpp create mode 100644 Demos/SimplexDemo/SimplexDemo.h create mode 100644 Demos/SliderConstraintDemo/CMakeLists.txt create mode 100755 Demos/SliderConstraintDemo/SliderConstraintDemo.cpp create mode 100755 Demos/SliderConstraintDemo/SliderConstraintDemo.h create mode 100755 Demos/SliderConstraintDemo/main.cpp create mode 100644 Demos/SoftDemo/AMD/premake4.lua create mode 100644 Demos/SoftDemo/CMakeLists.txt create mode 100644 Demos/SoftDemo/Makefile.am create mode 100644 Demos/SoftDemo/SoftDemo.cpp create mode 100644 Demos/SoftDemo/SoftDemo.h create mode 100755 Demos/SoftDemo/bunny.inl create mode 100755 Demos/SoftDemo/cube.inl create mode 100644 Demos/SoftDemo/main.cpp create mode 100644 Demos/TerrainDemo/Makefile.am create mode 100644 Demos/TerrainDemo/TerrainDemo.cpp create mode 100644 Demos/TerrainDemo/TerrainDemo.h create mode 100644 Demos/TerrainDemo/main.cpp create mode 100644 Demos/ThreadingDemo/CMakeLists.txt create mode 100644 Demos/ThreadingDemo/main.cpp create mode 100644 Demos/UserCollisionAlgorithm/CMakeLists.txt create mode 100644 Demos/UserCollisionAlgorithm/UserCollisionAlgorithm.cpp create mode 100644 Demos/UserCollisionAlgorithm/UserCollisionAlgorithm.h create mode 100644 Demos/VectorAdd_OpenCL/AMD/CMakeLists.txt create mode 100644 Demos/VectorAdd_OpenCL/Apple/CMakeLists.txt create mode 100644 Demos/VectorAdd_OpenCL/CMakeLists.txt create mode 100644 Demos/VectorAdd_OpenCL/MiniCL/CMakeLists.txt create mode 100644 Demos/VectorAdd_OpenCL/MiniCL_VectorAdd.cpp create mode 100644 Demos/VectorAdd_OpenCL/NVidia/CMakeLists.txt create mode 100644 Demos/VectorAdd_OpenCL/VectorAddKernels.cl create mode 100644 Demos/VehicleDemo/CMakeLists.txt create mode 100644 Demos/VehicleDemo/Makefile.am create mode 100644 Demos/VehicleDemo/VehicleDemo.cpp create mode 100644 Demos/VehicleDemo/VehicleDemo.h create mode 100644 Demos/VehicleDemo/main.cpp create mode 100644 Demos/VoronoiFractureDemo/CMakeLists.txt create mode 100644 Demos/VoronoiFractureDemo/Makefile.am create mode 100644 Demos/VoronoiFractureDemo/Makefile.original create mode 100644 Demos/VoronoiFractureDemo/VoronoiFractureDemo.cpp create mode 100644 Demos/VoronoiFractureDemo/VoronoiFractureDemo.h create mode 100644 Demos/VoronoiFractureDemo/Win32VoronoiFractureDemo.cpp create mode 100644 Demos/VoronoiFractureDemo/main.cpp create mode 100644 Demos/premake4.lua create mode 100644 Doxyfile create mode 100644 Extras/AllBulletDemosOSX/AllBulletDemos.xcodeproj/TemplateIcon.icns create mode 100644 Extras/AllBulletDemosOSX/AllBulletDemos.xcodeproj/project.pbxproj create mode 100644 Extras/AllBulletDemosOSX/AllBulletDemos.xcodeproj/zakariya.pbxuser create mode 100644 Extras/AllBulletDemosOSX/AllBulletDemos.xcodeproj/zakariya.perspectivev3 create mode 100644 Extras/AllBulletDemosOSX/AllBulletDemos_Prefix.pch create mode 100644 Extras/AllBulletDemosOSX/BulletIcon.icns create mode 100644 Extras/AllBulletDemosOSX/BulletIcon.psd create mode 100644 Extras/AllBulletDemosOSX/English.lproj/Credits.rtf create mode 100644 Extras/AllBulletDemosOSX/English.lproj/InfoPlist.strings create mode 100644 Extras/AllBulletDemosOSX/English.lproj/MainMenu.xib create mode 100644 Extras/AllBulletDemosOSX/Info.plist create mode 100644 Extras/AllBulletDemosOSX/README.txt create mode 100644 Extras/AllBulletDemosOSX/main.m create mode 100644 Extras/AllBulletDemosOSX/src/BTDemo.h create mode 100644 Extras/AllBulletDemosOSX/src/BTDemo.mm create mode 100644 Extras/AllBulletDemosOSX/src/BTDemosAppController.h create mode 100644 Extras/AllBulletDemosOSX/src/BTDemosAppController.m create mode 100644 Extras/AllBulletDemosOSX/src/BTSimulationParameters.h create mode 100644 Extras/AllBulletDemosOSX/src/BTSimulationParameters.m create mode 100644 Extras/AllBulletDemosOSX/src/toolkit/BTFullscreenWindow.h create mode 100644 Extras/AllBulletDemosOSX/src/toolkit/BTFullscreenWindow.m create mode 100644 Extras/AllBulletDemosOSX/src/toolkit/BTGLUTKeyAdapter.h create mode 100644 Extras/AllBulletDemosOSX/src/toolkit/BTGLUTKeyAdapter.m create mode 100644 Extras/AllBulletDemosOSX/src/toolkit/BTOpenGLDisplayDelegate.h create mode 100644 Extras/AllBulletDemosOSX/src/toolkit/BTOpenGLView.h create mode 100644 Extras/AllBulletDemosOSX/src/toolkit/BTOpenGLView.m create mode 100644 Extras/CDTestFramework/AntTweakBar/ChangeLog.txt create mode 100644 Extras/CDTestFramework/AntTweakBar/Clean.bat create mode 100644 Extras/CDTestFramework/AntTweakBar/License.txt create mode 100644 Extras/CDTestFramework/AntTweakBar/Readme.txt create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/Examples.ncb create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/Examples.sln create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/Examples.suo create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/Makefile create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/Makefile.x86_64 create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/TwAdvanced1.cpp create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/TwAdvanced1.vcproj create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/TwCopyDLL.vcproj create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/TwSimpleDX9.cpp create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/TwSimpleDX9.vcproj create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/TwSimpleGLFW.c create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/TwSimpleGLFW.vcproj create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/TwSimpleGLUT.c create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/TwSimpleGLUT.vcproj create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/TwSimpleSDL.c create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/TwSimpleSDL.vcproj create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/glfw.h create mode 100644 Extras/CDTestFramework/AntTweakBar/examples/glfwdll.lib create mode 100644 Extras/CDTestFramework/AntTweakBar/include/AntTweakBar.h create mode 100644 Extras/CDTestFramework/AntTweakBar/lib/AntTweakBar.dll create mode 100644 Extras/CDTestFramework/AntTweakBar/lib/AntTweakBar.exp create mode 100644 Extras/CDTestFramework/AntTweakBar/lib/AntTweakBar.lib create mode 100644 Extras/CDTestFramework/AntTweakBar/lib/Readme.txt create mode 100644 Extras/CDTestFramework/AntTweakBar/lib/libAntTweakBar.so create mode 100644 Extras/CDTestFramework/AntTweakBar/lib/libAntTweakBar.so.ldd create mode 100644 Extras/CDTestFramework/AntTweakBar/src/AntPerfTimer.h create mode 100644 Extras/CDTestFramework/AntTweakBar/src/AntTweakBar.rc create mode 100644 Extras/CDTestFramework/AntTweakBar/src/AntTweakBar.sln create mode 100644 Extras/CDTestFramework/AntTweakBar/src/AntTweakBar.vcproj create mode 100644 Extras/CDTestFramework/AntTweakBar/src/LoadOGL.cpp create mode 100644 Extras/CDTestFramework/AntTweakBar/src/LoadOGL.h create mode 100644 Extras/CDTestFramework/AntTweakBar/src/Makefile create mode 100644 Extras/CDTestFramework/AntTweakBar/src/Makefile.x86_64 create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwBar.cpp create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwBar.h create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwColors.cpp create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwColors.h create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwDirect3D9.cpp create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwDirect3D9.h create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwEventGLFW.c create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwEventGLUT.c create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwEventSDL.c create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwEventWin32.c create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwFonts.cpp create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwFonts.h create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwGraph.h create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwMgr.cpp create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwMgr.h create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwOpenGL.cpp create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwOpenGL.h create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwPrecomp.cpp create mode 100644 Extras/CDTestFramework/AntTweakBar/src/TwPrecomp.h create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/FontChars.txt create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/FontLargeAA.pgm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/FontNormal.pgm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/FontNormalAA.pgm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/FontSmall.pgm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/TwXCursors.h create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/cur00000.cur create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/cur00001.cur create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/cur00002.cur create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/cur00003.cur create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/cur00004.cur create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/cur00005.cur create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/cur00006.cur create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/cur00007.cur create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/cur00008.cur create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/cur00009.cur create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/cur00010.cur create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/cur00011.cur create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/cur00012.cur create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/cur00013.cur create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/curs00.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/curs01.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/curs02.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/curs03.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/curs04.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/curs05.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/curs06.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/curs07.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/curs08.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/curs09.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/curs10.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/curs11.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/curs12.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/curs13.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/mask00.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/mask01.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/mask02.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/mask03.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/mask04.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/mask05.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/mask06.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/mask07.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/mask08.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/mask09.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/mask10.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/mask11.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/mask12.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/res/mask13.pbm create mode 100644 Extras/CDTestFramework/AntTweakBar/src/resource.h create mode 100644 Extras/CDTestFramework/Bin/AntTweakBar.dll create mode 100644 Extras/CDTestFramework/Bin/Opcode.dll create mode 100644 Extras/CDTestFramework/BipartiteBoxPruning.cpp create mode 100644 Extras/CDTestFramework/BipartiteBoxPruning.h create mode 100644 Extras/CDTestFramework/BulletSAPCompleteBoxPruningTest.cpp create mode 100644 Extras/CDTestFramework/BulletSAPCompleteBoxPruningTest.h create mode 100644 Extras/CDTestFramework/CDTestFramework.cpp create mode 100644 Extras/CDTestFramework/CDTestFramework.h create mode 100644 Extras/CDTestFramework/CDTestFramework.sln create mode 100644 Extras/CDTestFramework/CDTestFramework.txt create mode 100644 Extras/CDTestFramework/CDTestFramework.vcproj create mode 100644 Extras/CDTestFramework/Camera.cpp create mode 100644 Extras/CDTestFramework/Camera.h create mode 100644 Extras/CDTestFramework/CapsuleMeshQuery.cpp create mode 100644 Extras/CDTestFramework/CapsuleMeshQuery.h create mode 100644 Extras/CDTestFramework/CollisionTest.cpp create mode 100644 Extras/CDTestFramework/CollisionTest.h create mode 100644 Extras/CDTestFramework/CompleteBoxPruning.cpp create mode 100644 Extras/CDTestFramework/CompleteBoxPruning.h create mode 100644 Extras/CDTestFramework/GLFontData.h create mode 100644 Extras/CDTestFramework/GLFontRenderer.cpp create mode 100644 Extras/CDTestFramework/GLFontRenderer.h create mode 100644 Extras/CDTestFramework/GLUT32.DLL create mode 100644 Extras/CDTestFramework/History.txt create mode 100644 Extras/CDTestFramework/IceHelpers.cpp create mode 100644 Extras/CDTestFramework/IceHelpers.h create mode 100644 Extras/CDTestFramework/License.txt create mode 100644 Extras/CDTestFramework/License.txt.bak create mode 100644 Extras/CDTestFramework/OBBMeshQuery.cpp create mode 100644 Extras/CDTestFramework/OBBMeshQuery.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceAABB.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceAABB.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceAllocator.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceAllocator.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceAssert.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceAxes.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceBitArray.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceBitArray.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceBoundingSphere.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceContainer.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceContainer.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceFPU.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceHPoint.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceHPoint.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceHashing.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceIndexedTriangle.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceIndexedTriangle.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceLSS.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceMatrix3x3.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceMatrix3x3.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceMatrix4x4.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceMatrix4x4.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceMemoryMacros.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceOBB.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceOBB.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IcePairs.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IcePlane.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IcePlane.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IcePoint.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IcePoint.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IcePreprocessor.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceRandom.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceRandom.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceRay.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceRay.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceRevisitedRadix.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceRevisitedRadix.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceSegment.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceSegment.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceTriangle.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceTriangle.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceTrilist.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceTypes.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceUtils.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/IceUtils.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/_IceAABB.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/_IceContainer.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/_IceContainer.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/_IceFPU.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/_IceMemoryMacros.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/_IcePreprocessor.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/_IceRevisitedRadix.cpp create mode 100644 Extras/CDTestFramework/Opcode/Ice/_IceRevisitedRadix.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/_IceTypes.h create mode 100644 Extras/CDTestFramework/Opcode/Ice/_IceUtils.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_AABBCollider.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_AABBCollider.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_AABBTree.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_AABBTree.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_ArraySAP.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_ArraySAP.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_BaseModel.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_BaseModel.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_BoxBoxOverlap.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_BoxPruning.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_BoxPruning.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_Collider.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_Collider.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_Common.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_Common.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_HybridModel.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_HybridModel.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_IceHook.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_LSSAABBOverlap.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_LSSCollider.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_LSSCollider.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_LSSTriOverlap.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_MeshInterface.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_MeshInterface.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_Model.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_Model.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_OBBCollider.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_OBBCollider.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_OptimizedTree.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_OptimizedTree.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_Picking.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_Picking.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_PlanesAABBOverlap.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_PlanesCollider.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_PlanesCollider.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_PlanesTriOverlap.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_RayAABBOverlap.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_RayCollider.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_RayCollider.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_RayTriOverlap.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_Settings.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_SphereAABBOverlap.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_SphereCollider.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_SphereCollider.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_SphereTriOverlap.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_SweepAndPrune.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_SweepAndPrune.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_TreeBuilders.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_TreeBuilders.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_TreeCollider.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_TreeCollider.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_TriBoxOverlap.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_TriTriOverlap.h create mode 100644 Extras/CDTestFramework/Opcode/OPC_VolumeCollider.cpp create mode 100644 Extras/CDTestFramework/Opcode/OPC_VolumeCollider.h create mode 100644 Extras/CDTestFramework/Opcode/Opcode.cpp create mode 100644 Extras/CDTestFramework/Opcode/Opcode.dsp create mode 100644 Extras/CDTestFramework/Opcode/Opcode.dsw create mode 100644 Extras/CDTestFramework/Opcode/Opcode.h create mode 100644 Extras/CDTestFramework/Opcode/Opcode.sln create mode 100644 Extras/CDTestFramework/Opcode/Opcode.vcproj create mode 100644 Extras/CDTestFramework/Opcode/ReadMe.txt create mode 100644 Extras/CDTestFramework/Opcode/StdAfx.cpp create mode 100644 Extras/CDTestFramework/Opcode/StdAfx.h create mode 100644 Extras/CDTestFramework/OpcodeArraySAPTest.cpp create mode 100644 Extras/CDTestFramework/OpcodeArraySAPTest.h create mode 100644 Extras/CDTestFramework/Profiling.h create mode 100644 Extras/CDTestFramework/ReadMe.txt create mode 100644 Extras/CDTestFramework/RenderingHelpers.cpp create mode 100644 Extras/CDTestFramework/RenderingHelpers.h create mode 100644 Extras/CDTestFramework/SphereMeshQuery.cpp create mode 100644 Extras/CDTestFramework/SphereMeshQuery.h create mode 100644 Extras/CDTestFramework/Terrain.cpp create mode 100644 Extras/CDTestFramework/Terrain.h create mode 100644 Extras/CDTestFramework/convex1.bin create mode 100644 Extras/CDTestFramework/stdafx.cpp create mode 100644 Extras/CDTestFramework/stdafx.h create mode 100644 Extras/CMakeLists.txt create mode 100644 Extras/CUDA/btCudaBroadphase.cpp create mode 100644 Extras/CUDA/btCudaBroadphase.cu create mode 100644 Extras/CUDA/btCudaBroadphase.h create mode 100644 Extras/CUDA/btCudaDefines.h create mode 100644 Extras/CUDA/btCudaUtils.cu create mode 100644 Extras/CUDA/btGpuDemo2dCudaFunc.cu create mode 100644 Extras/CUDA/btGpuDemo3dCudaFunc.cu create mode 100644 Extras/CUDA/cutil_gl_error.h create mode 100644 Extras/CUDA/cutil_math.h create mode 100644 Extras/CUDA/libbulletcuda.vcproj create mode 100644 Extras/CUDA/radixsort.cu create mode 100644 Extras/CUDA/radixsort.cuh create mode 100644 Extras/CUDA/radixsort_kernel.cu create mode 100644 Extras/ConvexDecomposition/CMakeLists.txt create mode 100644 Extras/ConvexDecomposition/ConvexBuilder.cpp create mode 100644 Extras/ConvexDecomposition/ConvexBuilder.h create mode 100644 Extras/ConvexDecomposition/ConvexDecomposition.cpp create mode 100644 Extras/ConvexDecomposition/ConvexDecomposition.h create mode 100644 Extras/ConvexDecomposition/bestfit.cpp create mode 100644 Extras/ConvexDecomposition/bestfit.h create mode 100644 Extras/ConvexDecomposition/bestfitobb.cpp create mode 100644 Extras/ConvexDecomposition/bestfitobb.h create mode 100644 Extras/ConvexDecomposition/cd_hull.cpp create mode 100644 Extras/ConvexDecomposition/cd_hull.h create mode 100644 Extras/ConvexDecomposition/cd_vector.h create mode 100644 Extras/ConvexDecomposition/cd_wavefront.cpp create mode 100644 Extras/ConvexDecomposition/cd_wavefront.h create mode 100644 Extras/ConvexDecomposition/concavity.cpp create mode 100644 Extras/ConvexDecomposition/concavity.h create mode 100644 Extras/ConvexDecomposition/fitsphere.cpp create mode 100644 Extras/ConvexDecomposition/fitsphere.h create mode 100644 Extras/ConvexDecomposition/float_math.cpp create mode 100644 Extras/ConvexDecomposition/float_math.h create mode 100644 Extras/ConvexDecomposition/meshvolume.cpp create mode 100644 Extras/ConvexDecomposition/meshvolume.h create mode 100644 Extras/ConvexDecomposition/planetri.cpp create mode 100644 Extras/ConvexDecomposition/planetri.h create mode 100644 Extras/ConvexDecomposition/premake4.lua create mode 100644 Extras/ConvexDecomposition/raytri.cpp create mode 100644 Extras/ConvexDecomposition/raytri.h create mode 100644 Extras/ConvexDecomposition/splitplane.cpp create mode 100644 Extras/ConvexDecomposition/splitplane.h create mode 100644 Extras/ConvexDecomposition/vlookup.cpp create mode 100644 Extras/ConvexDecomposition/vlookup.h create mode 100644 Extras/GIMPACTUtils/CMakeLists.txt create mode 100644 Extras/GIMPACTUtils/btGImpactConvexDecompositionShape.cpp create mode 100644 Extras/GIMPACTUtils/btGImpactConvexDecompositionShape.h create mode 100644 Extras/HACD/CMakeLists.txt create mode 100644 Extras/HACD/hacdCircularList.h create mode 100644 Extras/HACD/hacdCircularList.inl create mode 100644 Extras/HACD/hacdGraph.cpp create mode 100644 Extras/HACD/hacdGraph.h create mode 100644 Extras/HACD/hacdHACD.cpp create mode 100644 Extras/HACD/hacdHACD.h create mode 100644 Extras/HACD/hacdICHull.cpp create mode 100644 Extras/HACD/hacdICHull.h create mode 100644 Extras/HACD/hacdManifoldMesh.cpp create mode 100644 Extras/HACD/hacdManifoldMesh.h create mode 100644 Extras/HACD/hacdVector.h create mode 100644 Extras/HACD/hacdVector.inl create mode 100644 Extras/HACD/hacdVersion.h create mode 100644 Extras/HACD/premake4.lua create mode 100644 Extras/Makefile.am create mode 100644 Extras/PhysicsEffects/CMakeLists.txt create mode 100644 Extras/PhysicsEffects/README_Android.txt create mode 100644 Extras/PhysicsEffects/build/premake4.lua create mode 100644 Extras/PhysicsEffects/build/vs2008.bat create mode 100644 Extras/PhysicsEffects/build/vs2010.bat create mode 100644 Extras/PhysicsEffects/include/BulletPhysicsEffects/btBulletPhysicsEffectsWorld.cpp create mode 100644 Extras/PhysicsEffects/include/BulletPhysicsEffects/btBulletPhysicsEffectsWorld.h create mode 100644 Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelBroadphase.cpp create mode 100644 Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelBroadphase.h create mode 100644 Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelCollisionDispatcher.cpp create mode 100644 Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelCollisionDispatcher.h create mode 100644 Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelConstraintSolver.cpp create mode 100644 Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelConstraintSolver.h create mode 100644 Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelConstraintSolver2.cpp create mode 100644 Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelConstraintSolver2.h create mode 100644 Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelData.cpp create mode 100644 Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelData.h create mode 100644 Extras/PhysicsEffects/include/physics_effects.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_common.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_error_code.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_heap_manager.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_perf_counter.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_vec_int3.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_vec_utils.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_vectormath_include.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_vectormath_include.win32.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/broadphase/pfx_broadphase_pair.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/broadphase/pfx_broadphase_proxy.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/broadphase/pfx_update_broadphase_proxy.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_aabb.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_box.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_capsule.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_collidable.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_collidable_implementation.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_contact_manifold.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_cylinder.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_large_tri_mesh.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_ray.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_shape.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_shape_implementation.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_shape_iterator.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_sphere.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_sub_data.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_tri_mesh.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/pfx_base_level_include.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/rigidbody/pfx_rigid_body.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/rigidbody/pfx_rigid_state.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_constraint_pair.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_constraint_row.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_contact_constraint.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_integrate.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_ball.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_constraint.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_fix.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_hinge.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_slider.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_swing_twist.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_universal.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_solver_body.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/sort/pfx_sort.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/base_level/sort/pfx_sort_data.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/low_level/broadphase/pfx_broadphase.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_batched_ray_cast.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_collision_detection.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_island_generation.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_ray_cast.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_refresh_contacts.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/low_level/pfx_low_level_include.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/low_level/solver/pfx_constraint_solver.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/low_level/solver/pfx_joint_constraint_func.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/low_level/solver/pfx_update_rigid_states.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/low_level/sort/pfx_parallel_sort.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/low_level/task/pfx_pthreads.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/low_level/task/pfx_sync_components.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/low_level/task/pfx_task_manager.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/util/pfx_mass.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/util/pfx_mesh_creator.h create mode 100644 Extras/PhysicsEffects/include/physics_effects/util/pfx_util_include.h create mode 100644 Extras/PhysicsEffects/include/vecmath/neon/boolInVec.h create mode 100644 Extras/PhysicsEffects/include/vecmath/neon/floatInVec.h create mode 100644 Extras/PhysicsEffects/include/vecmath/neon/mat_aos.h create mode 100644 Extras/PhysicsEffects/include/vecmath/neon/quat_aos.h create mode 100644 Extras/PhysicsEffects/include/vecmath/neon/vec_aos.h create mode 100644 Extras/PhysicsEffects/include/vecmath/neon/vectormath_aos.h create mode 100644 Extras/PhysicsEffects/include/vecmath/neon/vectormath_neon_assembly_implementations.S create mode 100644 Extras/PhysicsEffects/include/vecmath/neon/vectormath_neon_assembly_prototypes.h create mode 100644 Extras/PhysicsEffects/include/vecmath/sse/boolInVec.h create mode 100644 Extras/PhysicsEffects/include/vecmath/sse/floatInVec.h create mode 100644 Extras/PhysicsEffects/include/vecmath/sse/mat_aos.h create mode 100644 Extras/PhysicsEffects/include/vecmath/sse/quat_aos.h create mode 100644 Extras/PhysicsEffects/include/vecmath/sse/vec_aos.h create mode 100644 Extras/PhysicsEffects/include/vecmath/sse/vecidx_aos.h create mode 100644 Extras/PhysicsEffects/include/vecmath/sse/vectormath_aos.h create mode 100644 Extras/PhysicsEffects/include/vecmath/std/boolInVec.h create mode 100644 Extras/PhysicsEffects/include/vecmath/std/floatInVec.h create mode 100644 Extras/PhysicsEffects/include/vecmath/std/mat_aos.h create mode 100644 Extras/PhysicsEffects/include/vecmath/std/quat_aos.h create mode 100644 Extras/PhysicsEffects/include/vecmath/std/vec_aos.h create mode 100644 Extras/PhysicsEffects/include/vecmath/std/vectormath_aos.h create mode 100644 Extras/PhysicsEffects/physics_effects_license.txt create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/.classpath create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/.cproject create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/.externalToolBuilders/BuildSampleJNICode.launch create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/.project create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/AndroidManifest.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/build.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/default.properties create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/jni/Android.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/jni/Application.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/local.properties create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/proguard.cfg create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/res/drawable-hdpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/res/drawable-ldpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/res/drawable-mdpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/res/layout/main.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/res/values/strings.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/src/pfx/renderingsupport/PhysicsEffectsRenderer.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/src/pfx/sample1/PfxApp_1_Simple.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/.classpath create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/.cproject create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/.externalToolBuilders/BuildSampleJNICode.launch create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/.project create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/AndroidManifest.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/build.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/default.properties create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/jni/Android.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/jni/Application.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/local.properties create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/proguard.cfg create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/res/drawable-hdpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/res/drawable-ldpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/res/drawable-mdpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/res/layout/main.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/res/values/strings.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/src/pfx/renderingsupport/PhysicsEffectsRenderer.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/src/pfx/sample1b/PfxApp_1_Simple_Parallel.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/.classpath create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/.externalToolBuilders/BuildSampleJNICode.launch create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/.project create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/AndroidManifest.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/build.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/default.properties create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/jni/Android.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/jni/Application.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/local.properties create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/proguard.cfg create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/res/drawable-hdpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/res/drawable-ldpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/res/drawable-mdpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/res/layout/main.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/res/values/strings.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/src/pfx/renderingsupport/PhysicsEffectsRenderer.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/src/pfx/sample2/PfxApp_2_Stable.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/.classpath create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/.externalToolBuilders/BuildSampleJNICode.launch create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/.project create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/AndroidManifest.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/build.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/default.properties create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/jni/Android.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/jni/Application.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/local.properties create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/proguard.cfg create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/res/drawable-hdpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/res/drawable-ldpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/res/drawable-mdpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/res/layout/main.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/res/values/strings.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/src/pfx/renderingsupport/PhysicsEffectsRenderer.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/src/pfx/sample2b/PfxApp_2_Stable_Parallel.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/.classpath create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/.externalToolBuilders/BuildSampleJNICode.launch create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/.project create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/AndroidManifest.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/build.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/default.properties create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/jni/Android.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/jni/Application.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/local.properties create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/proguard.cfg create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/res/drawable-hdpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/res/drawable-ldpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/res/drawable-mdpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/res/layout/main.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/res/values/strings.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/src/pfx/renderingsupport/PhysicsEffectsRenderer.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/src/pfx/sample3/PfxApp_3_Sleep.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/.classpath create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/.externalToolBuilders/BuildSampleJNICode.launch create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/.project create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/AndroidManifest.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/build.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/default.properties create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/jni/Android.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/jni/Application.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/local.properties create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/proguard.cfg create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/res/drawable-hdpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/res/drawable-ldpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/res/drawable-mdpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/res/layout/main.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/res/values/strings.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/src/pfx/renderingsupport/PhysicsEffectsRenderer.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/src/pfx/sample4/PfxApp_4_MotionType.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/.classpath create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/.externalToolBuilders/BuildSampleJNICode.launch create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/.project create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/AndroidManifest.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/build.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/default.properties create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/jni/Android.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/jni/Application.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/local.properties create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/proguard.cfg create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/res/drawable-hdpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/res/drawable-ldpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/res/drawable-mdpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/res/layout/main.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/res/values/strings.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/src/pfx/renderingsupport/PhysicsEffectsRenderer.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/src/pfx/sample5/PfxApp_5_Raycast.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/.classpath create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/.externalToolBuilders/BuildSampleJNICode.launch create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/.project create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/AndroidManifest.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/build.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/default.properties create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/jni/Android.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/jni/Application.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/local.properties create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/proguard.cfg create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/res/drawable-hdpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/res/drawable-ldpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/res/drawable-mdpi/icon.png create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/res/layout/main.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/res/values/strings.xml create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/src/pfx/renderingsupport/PhysicsEffectsRenderer.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/src/pfx/sample6/PfxApp_6_Joint.java create mode 100644 Extras/PhysicsEffects/project/Android/PfxLibrary/.cproject create mode 100644 Extras/PhysicsEffects/project/Android/PfxLibrary/.externalToolBuilders/PfxLibraryBuilder.launch create mode 100644 Extras/PhysicsEffects/project/Android/PfxLibrary/.project create mode 100644 Extras/PhysicsEffects/project/Android/PfxLibrary/jni/Android.mk create mode 100644 Extras/PhysicsEffects/project/Android/PfxLibrary/jni/Application.mk create mode 100644 Extras/PhysicsEffects/project/msvc2008_32/BulletCollision.vcproj create mode 100644 Extras/PhysicsEffects/project/msvc2008_32/BulletDynamics.vcproj create mode 100644 Extras/PhysicsEffects/project/msvc2008_32/BulletMultiThreaded.vcproj create mode 100644 Extras/PhysicsEffects/project/msvc2008_32/BulletSoftBody.vcproj create mode 100644 Extras/PhysicsEffects/project/msvc2008_32/LinearMath.vcproj create mode 100644 Extras/PhysicsEffects/project/msvc2008_32/MiniCL.vcproj create mode 100644 Extras/PhysicsEffects/project/physics_effects_lib.oss.sln create mode 100644 Extras/PhysicsEffects/project/physics_effects_lib.oss.vcproj create mode 100644 Extras/PhysicsEffects/sample/CMakeLists.txt create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/0_console/CMakeLists.txt create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/0_console/barrel.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/0_console/landscape.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/0_console/main.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/0_console/physics_func.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/0_console/physics_func.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/0_console/premake4.lua create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/1_simple/1_simple.windows.vcproj create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/1_simple/CMakeLists.txt create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/1_simple/barrel.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/1_simple/landscape.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/1_simple/main.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/1_simple/physics.png create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/1_simple/physics_func.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/1_simple/physics_func.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/1_simple/premake4.lua create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/barrel.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/landscape.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/main.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/physics_func.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/physics_func.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/2_stable/2_stable.winsows.vcproj create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/2_stable/CMakeLists.txt create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/2_stable/barrel.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/2_stable/landscape.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/2_stable/main.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/2_stable/physics.png create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/2_stable/physics_func.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/2_stable/physics_func.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/2_stable/premake4.lua create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/barrel.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/landscape.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/main.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/physics_func.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/physics_func.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/3_sleep.windows.vcproj create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/CMakeLists.txt create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/barrel.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/landscape.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/main.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/physics.png create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/physics_func.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/physics_func.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/premake4.lua create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/4_motion_type.windows.vcproj create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/CMakeLists.txt create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/main.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/physics.png create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/physics_func.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/physics_func.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/premake4.lua create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/5_raycast.windows.vcproj create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/CMakeLists.txt create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/barrel.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/landscape.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/main.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/physics.png create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/physics_func.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/physics_func.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/premake4.lua create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/6_joint/6_joint.windows.vcproj create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/6_joint/CMakeLists.txt create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/6_joint/barrel.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/6_joint/landscape.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/6_joint/main.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/6_joint/physics.png create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/6_joint/physics_func.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/6_joint/physics_func.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/6_joint/premake4.lua create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/99_BulletPhysicsEffects.vcproj create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/CMakeLists.txt create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/barrel.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/bullet_physics_func.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/landscape.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/main.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/physics_func.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/CMakeLists.txt create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/api_physics_effects.windows.sln create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/common/box.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/common/common.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/common/ctrl_func.android.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/common/ctrl_func.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/common/ctrl_func.win32.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/common/cylinder.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/common/jni/physicseffects-android.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/common/jni/physicseffects-android.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/common/perf_func.android.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/common/perf_func.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/common/perf_func.win32.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/common/render_func.android.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/common/render_func.h create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/common/render_func.win32.cpp create mode 100644 Extras/PhysicsEffects/sample/api_physics_effects/common/sphere.h create mode 100644 Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_cross_product.S create mode 100644 Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_dot_product.S create mode 100644 Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_matrix3_operator_multiply.S create mode 100644 Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_matrix4_operator_multiply.S create mode 100644 Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_orthoInverse_transform3.S create mode 100644 Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_transform3_operator_multiply.S create mode 100644 Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_transpose_matrix3.S create mode 100644 Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon.h create mode 100644 Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_cross_product.cpp create mode 100644 Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_dot_product.cpp create mode 100644 Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_matrix3_operator_multiply.cpp create mode 100644 Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_matrix4_operator_multiply.cpp create mode 100644 Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_orthoInverse_transform3.cpp create mode 100644 Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_solve_linear_constraint_row.cpp create mode 100644 Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_transform3_operator_multiply.cpp create mode 100644 Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_transpose_matrix3.cpp create mode 100644 Extras/PhysicsEffects/src/CMakeLists.txt create mode 100644 Extras/PhysicsEffects/src/base_level/CMakeLists.txt create mode 100644 Extras/PhysicsEffects/src/base_level/broadphase/pfx_check_collidable.h create mode 100644 Extras/PhysicsEffects/src/base_level/broadphase/pfx_update_broadphase_proxy.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_collidable.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_box.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_box.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_capsule.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_capsule.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_sphere.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_sphere.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_cache.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_cache.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_capsule_capsule.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_capsule_capsule.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_capsule_sphere.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_capsule_sphere.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_large_tri_mesh.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_large_tri_mesh.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_manifold.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_sphere_sphere.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_sphere_sphere.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_box.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_box.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_capsule.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_capsule.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_convex.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_convex.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_cylinder.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_cylinder.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_sphere.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_sphere.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_gjk_solver.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_gjk_solver.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_gjk_support_func.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_gjk_support_func.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_common.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_box.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_box.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_capsule.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_capsule.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_convex.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_convex.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_cylinder.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_cylinder.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_large_tri_mesh.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_large_tri_mesh.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_sphere.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_sphere.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_mesh_common.h create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_shape.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_simplex_solver.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/collision/pfx_simplex_solver.h create mode 100644 Extras/PhysicsEffects/src/base_level/premake4.lua create mode 100644 Extras/PhysicsEffects/src/base_level/solver/pfx_check_solver.h create mode 100644 Extras/PhysicsEffects/src/base_level/solver/pfx_constraint_row_solver.h create mode 100644 Extras/PhysicsEffects/src/base_level/solver/pfx_constraint_row_solver_neon.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/solver/pfx_contact_constraint.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/solver/pfx_joint_ball.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/solver/pfx_joint_fix.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/solver/pfx_joint_hinge.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/solver/pfx_joint_slider.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/solver/pfx_joint_swing_twist.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/solver/pfx_joint_universal.cpp create mode 100644 Extras/PhysicsEffects/src/base_level/sort/pfx_sort.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/CMakeLists.txt create mode 100644 Extras/PhysicsEffects/src/low_level/broadphase/pfx_broadphase_single.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/collision/pfx_batched_ray_cast_parallel.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/collision/pfx_batched_ray_cast_single.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/collision/pfx_collision_detection_parallel.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/collision/pfx_collision_detection_single.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/collision/pfx_detect_collision_func.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/collision/pfx_detect_collision_func.h create mode 100644 Extras/PhysicsEffects/src/low_level/collision/pfx_intersect_ray_func.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/collision/pfx_intersect_ray_func.h create mode 100644 Extras/PhysicsEffects/src/low_level/collision/pfx_island_generation.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/collision/pfx_ray_cast.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/collision/pfx_refresh_contacts_parallel.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/collision/pfx_refresh_contacts_single.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/premake4.lua create mode 100644 Extras/PhysicsEffects/src/low_level/solver/pfx_constraint_solver_parallel.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/solver/pfx_constraint_solver_single.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/solver/pfx_joint_constraint_func.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/solver/pfx_parallel_group.h create mode 100644 Extras/PhysicsEffects/src/low_level/solver/pfx_update_rigid_states_parallel.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/solver/pfx_update_rigid_states_single.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/sort/pfx_parallel_sort_single.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/task/pfx_sync_components_pthreads.cpp create mode 100644 Extras/PhysicsEffects/src/low_level/task/pfx_sync_components_pthreads.h create mode 100644 Extras/PhysicsEffects/src/low_level/task/pfx_task_manager_pthreads.cpp create mode 100644 Extras/PhysicsEffects/src/util/CMakeLists.txt create mode 100644 Extras/PhysicsEffects/src/util/pfx_array.h create mode 100644 Extras/PhysicsEffects/src/util/pfx_array_implementation.h create mode 100644 Extras/PhysicsEffects/src/util/pfx_mass.cpp create mode 100644 Extras/PhysicsEffects/src/util/pfx_mesh_creator.cpp create mode 100644 Extras/PhysicsEffects/src/util/pfx_util_common.h create mode 100644 Extras/PhysicsEffects/src/util/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/bin/glut32.dll create mode 100644 Extras/RigidBodyGpuPipeline/bin/glut64.dll create mode 100644 Extras/RigidBodyGpuPipeline/build/findDirectX11.lua create mode 100644 Extras/RigidBodyGpuPipeline/build/findOpenCL.lua create mode 100644 Extras/RigidBodyGpuPipeline/build/findOpenGLGlewGlut.lua create mode 100644 Extras/RigidBodyGpuPipeline/build/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/build/vs2008.bat create mode 100644 Extras/RigidBodyGpuPipeline/build/vs2010.bat create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/AMD/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/BasicDemo.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/BasicDemo.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/ConvexHeightFieldShape.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/ConvexHeightFieldShape.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CubeMapUtils.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomCollisionDispatcher.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomCollisionDispatcher.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomConvexPairCollision.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomConvexPairCollision.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomConvexShape.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomConvexShape.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlAabb.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlAabb.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlArray.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlCollideUtils.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlCollisionShape.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlConstraint4.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlContact4.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlError.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlMath.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlMatrix3x3.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlQuaternion.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlRigidBody.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlTransform.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/Adlfloat4.inl create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/Adlfloat4SSE.inl create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/ChNarrowPhase.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/ChNarrowphase.inl create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/ChNarrowphaseKernels.cl create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/ChNarrowphaseKernels.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/Solver.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/Solver.inl create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/SolverHost.inl create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/SolverKernels.cl create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/SolverKernels.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/batchingKernels.cl create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/batchingKernels.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringify.py create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernels.bat create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernelsAll.bat create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernelsBatching.bat create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernelsNarrowphase.bat create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernelsSolver.bat create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/main.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/basic_demo/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/DebugCastResult.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/DemoApplication.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/DemoApplication.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/GLDebugDrawer.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/GLDebugDrawer.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/GLDebugFont.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/GLDebugFont.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/GL_ShapeDrawer.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/GL_ShapeDrawer.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/GL_Simplex1to4.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/GL_Simplex1to4.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/GlutDemoApplication.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/GlutDemoApplication.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/GlutStuff.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/GlutStuff.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/RenderTexture.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/RenderTexture.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/Win32AppMain.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/Win32DemoApplication.cpp create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/Win32DemoApplication.h create mode 100644 Extras/RigidBodyGpuPipeline/dynamics/testbed/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/AMD/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/MiniCL/MiniCLTaskWrap.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.cl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphase.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphase.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphaseSharedCode.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphaseSharedDefs.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphaseSharedTypes.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpuDefines.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpuUtilsSharedCode.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpuUtilsSharedDefs.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/basic_initialize/AMD/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/basic_initialize/Intel/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/basic_initialize/NVIDIA/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/basic_initialize/btOpenCLInclude.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/basic_initialize/btOpenCLUtils.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/basic_initialize/btOpenCLUtils.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/basic_initialize/main.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/basic_initialize/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/AMD/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/Intel/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/NVIDIA/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/broadphaseKernel.cl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/btGridBroadphaseCL.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/btGridBroadphaseCL.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/computeAabbKernelOCL.cl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/findPairsOpenCL.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/findPairsOpenCL.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/integrateKernel.cl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/main.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/global_atomics/AMD/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/global_atomics/globalAtomicsKernel.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/global_atomics/global_atomics.cl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/global_atomics/main.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/global_atomics/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/global_atomics/stringify.py create mode 100644 Extras/RigidBodyGpuPipeline/opencl/global_atomics/stringifykernels.bat create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/AMD/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/CommandLineArgs.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/Intel/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/NVIDIA/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/btConvexUtility.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/btConvexUtility.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/btGpuNarrowPhaseAndSolver.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/btGpuNarrowPhaseAndSolver.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/main.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/AMD/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/CLPhysicsDemo.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/CLPhysicsDemo.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/DemoSettings.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/GLInstancingRenderer.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/GLInstancingRenderer.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/GlutRenderer.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/GlutRenderer.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/NVIDIA/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/OpenGLInclude.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/ShapeData.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/Win32OpenGLRenderManager.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/Win32OpenGLRenderManager.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/main.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/integration/AMD/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/integration/Intel/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/integration/NVIDIA/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/integration/integrateKernel.cl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/integration/main.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/integration/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/opengl_interop/AMD/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/opengl_interop/Intel/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/opengl_interop/NVIDIA/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/opengl_interop/btOpenCLGLInteropBuffer.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/opengl_interop/btOpenCLGLInteropBuffer.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/opengl_interop/btStopwatch.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/opengl_interop/btStopwatch.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/opengl_interop/interopKernel.cl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/opengl_interop/main.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/opengl_interop/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Adl.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Adl.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Adl.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlConfig.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlError.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlKernel.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlKernel.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlStopwatch.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlStopwatch.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/CL/AdlCL.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/CL/AdlKernelUtilsCL.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/DX11/AdlDX11.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/DX11/AdlKernelUtilsDX11.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/DX11/AdlStopwatchDX11.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Host/AdlHost.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Host/AdlStopwatchHost.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/Copy.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/Copy.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/CopyHost.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/CopyKernels.cl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/CopyKernels.hlsl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/CopyKernelsCL.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/CopyKernelsDX11.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/Fill.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/Fill.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillHost.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillKernels.cl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillKernels.hlsl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillKernelsCL.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillKernelsDX11.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Array.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Float2.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Float4.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Math.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/MathCL.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Matrix3x3.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Quaternion.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Scan/PrefixScan.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Scan/PrefixScan.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Scan/PrefixScanHost.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Scan/PrefixScanKernels.cl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Scan/PrefixScanKernels.hlsl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Scan/PrefixScanKernelsCL.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Scan/PrefixScanKernelsDX11.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Search/BoundSearch.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Search/BoundSearch.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Search/BoundSearchHost.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Search/BoundSearchKernels.cl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Search/BoundSearchKernels.hlsl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Search/BoundSearchKernelsCL.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Search/BoundSearchKernelsDX11.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32Host.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32Kernels.cl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32Kernels.hlsl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32KernelsCL.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32KernelsDX11.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortAdvancedKernels.hlsl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortAdvancedKernelsDX11.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortHost.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortSimpleCL.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortSimpleDX11.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortSimpleKernels.cl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortSimpleKernels.hlsl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortSimpleKernelsCL.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortSimpleKernelsDX11.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandard.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandardKernels.cl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandardKernels.hlsl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandardKernelsCL.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandardKernelsDX11.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/SortData.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/radixsortadvanced.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/radixsortsimple.inl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/stringify.py create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/stringifykernels.bat create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/AMD/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/Intel/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/LaunchOverheadBenchmark.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/NVIDIA/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/RadixSortBenchmark.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/UnitTests.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/main.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/benchmark/AMD/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/benchmark/NVIDIA/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/benchmark/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/primitives/benchmark/test_large_problem_sorting.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/vector_add/AMD/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/vector_add/Intel/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/vector_add/NVIDIA/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/vector_add/VectorAddKernels.cl create mode 100644 Extras/RigidBodyGpuPipeline/opencl/vector_add/VectorAddKernels.h create mode 100644 Extras/RigidBodyGpuPipeline/opencl/vector_add/main.cpp create mode 100644 Extras/RigidBodyGpuPipeline/opencl/vector_add/premake4.lua create mode 100644 Extras/RigidBodyGpuPipeline/opencl/vector_add/stringify.py create mode 100644 Extras/RigidBodyGpuPipeline/opencl/vector_add/stringifyVectorAddKernel.bat create mode 100644 Extras/RigidBodyGpuPipeline/readme.txt create mode 100644 Extras/Serialize/BlenderSerialize/CMakeLists.txt create mode 100644 Extras/Serialize/BlenderSerialize/bBlenderFile.cpp create mode 100644 Extras/Serialize/BlenderSerialize/bBlenderFile.h create mode 100644 Extras/Serialize/BlenderSerialize/bMain.cpp create mode 100644 Extras/Serialize/BlenderSerialize/bMain.h create mode 100644 Extras/Serialize/BlenderSerialize/dna249-64bit.cpp create mode 100644 Extras/Serialize/BlenderSerialize/dna249.cpp create mode 100644 Extras/Serialize/BulletFileLoader/CMakeLists.txt create mode 100644 Extras/Serialize/BulletFileLoader/autogenerated/bullet.h create mode 100644 Extras/Serialize/BulletFileLoader/bChunk.cpp create mode 100644 Extras/Serialize/BulletFileLoader/bChunk.h create mode 100644 Extras/Serialize/BulletFileLoader/bCommon.h create mode 100644 Extras/Serialize/BulletFileLoader/bDNA.cpp create mode 100644 Extras/Serialize/BulletFileLoader/bDNA.h create mode 100644 Extras/Serialize/BulletFileLoader/bDefines.h create mode 100644 Extras/Serialize/BulletFileLoader/bFile.cpp create mode 100644 Extras/Serialize/BulletFileLoader/bFile.h create mode 100644 Extras/Serialize/BulletFileLoader/btBulletFile.cpp create mode 100644 Extras/Serialize/BulletFileLoader/btBulletFile.h create mode 100644 Extras/Serialize/BulletFileLoader/premake4.lua create mode 100644 Extras/Serialize/BulletWorldImporter/CMakeLists.txt create mode 100644 Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.cpp create mode 100644 Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.h create mode 100644 Extras/Serialize/BulletWorldImporter/premake4.lua create mode 100644 Extras/Serialize/CMakeLists.txt create mode 100644 Extras/Serialize/HeaderGenerator/CMakeLists.txt create mode 100644 Extras/Serialize/HeaderGenerator/apiGen.cpp create mode 100644 Extras/Serialize/HeaderGenerator/blenderGenerate.py create mode 100644 Extras/Serialize/HeaderGenerator/bulletGenerate.py create mode 100644 Extras/Serialize/HeaderGenerator/createDnaString.bat create mode 100644 Extras/Serialize/ReadBulletSample/BulletDataExtractor.cpp create mode 100644 Extras/Serialize/ReadBulletSample/BulletDataExtractor.h create mode 100644 Extras/Serialize/ReadBulletSample/CMakeLists.txt create mode 100644 Extras/Serialize/ReadBulletSample/main.cpp create mode 100644 Extras/Serialize/makesdna/CMakeLists.txt create mode 100644 Extras/Serialize/makesdna/DNA_rigidbody.h create mode 100644 Extras/Serialize/makesdna/makesdna.cpp create mode 100644 Extras/glui/CMakeLists.txt create mode 100644 Extras/glui/GL/glui.h create mode 100644 Extras/glui/algebra3.cpp create mode 100644 Extras/glui/algebra3.h create mode 100644 Extras/glui/arcball.cpp create mode 100644 Extras/glui/arcball.h create mode 100644 Extras/glui/glui.cpp create mode 100644 Extras/glui/glui_add_controls.cpp create mode 100644 Extras/glui/glui_bitmap_img_data.cpp create mode 100644 Extras/glui/glui_bitmaps.cpp create mode 100644 Extras/glui/glui_button.cpp create mode 100644 Extras/glui/glui_checkbox.cpp create mode 100644 Extras/glui/glui_column.cpp create mode 100644 Extras/glui/glui_commandline.cpp create mode 100644 Extras/glui/glui_control.cpp create mode 100644 Extras/glui/glui_edittext.cpp create mode 100644 Extras/glui/glui_filebrowser.cpp create mode 100644 Extras/glui/glui_internal.h create mode 100644 Extras/glui/glui_internal_control.h create mode 100644 Extras/glui/glui_list.cpp create mode 100644 Extras/glui/glui_listbox.cpp create mode 100644 Extras/glui/glui_mouse_iaction.cpp create mode 100644 Extras/glui/glui_node.cpp create mode 100644 Extras/glui/glui_panel.cpp create mode 100644 Extras/glui/glui_radio.cpp create mode 100644 Extras/glui/glui_rollout.cpp create mode 100644 Extras/glui/glui_rotation.cpp create mode 100644 Extras/glui/glui_scrollbar.cpp create mode 100644 Extras/glui/glui_separator.cpp create mode 100644 Extras/glui/glui_spinner.cpp create mode 100644 Extras/glui/glui_statictext.cpp create mode 100644 Extras/glui/glui_string.cpp create mode 100644 Extras/glui/glui_textbox.cpp create mode 100644 Extras/glui/glui_translation.cpp create mode 100644 Extras/glui/glui_tree.cpp create mode 100644 Extras/glui/glui_treepanel.cpp create mode 100644 Extras/glui/glui_window.cpp create mode 100644 Extras/glui/quaternion.cpp create mode 100644 Extras/glui/quaternion.h create mode 100644 Extras/glui/readme.txt create mode 100644 Extras/iff/CMakeLists.txt create mode 100644 Extras/iff/IFF.txt create mode 100644 Extras/iff/iff.h create mode 100644 Extras/iff/iffCheck/iffcheck.cpp create mode 100644 Extras/iff/iffCreateTest/main.cpp create mode 100644 Extras/iff/iffr.cpp create mode 100644 Extras/iff/iffw.cpp create mode 100644 Extras/khx2dae/Bullet_dae_screenshot.jpg create mode 100644 Extras/khx2dae/Havok5.5toColladaPhysics.dae create mode 100644 Extras/khx2dae/Havok_hkx_screenshot.jpg create mode 100644 Extras/khx2dae/SimpleLoadDemo.patch create mode 100644 Extras/khx2dae/readme.txt create mode 100644 Extras/premake4.lua create mode 100644 Extras/simdmathlibrary/LICENSE create mode 100644 Extras/simdmathlibrary/Make.defs create mode 100644 Extras/simdmathlibrary/Make.rules create mode 100644 Extras/simdmathlibrary/Make.test create mode 100644 Extras/simdmathlibrary/Makefile create mode 100644 Extras/simdmathlibrary/README create mode 100644 Extras/simdmathlibrary/common/Makefile create mode 100644 Extras/simdmathlibrary/common/absi4.c create mode 100644 Extras/simdmathlibrary/common/acosf4.c create mode 100644 Extras/simdmathlibrary/common/asinf4.c create mode 100644 Extras/simdmathlibrary/common/atan2f4.c create mode 100644 Extras/simdmathlibrary/common/atanf4.c create mode 100644 Extras/simdmathlibrary/common/cbrtf4.c create mode 100644 Extras/simdmathlibrary/common/ceild2.c create mode 100644 Extras/simdmathlibrary/common/ceilf4.c create mode 100644 Extras/simdmathlibrary/common/common-test.h create mode 100644 Extras/simdmathlibrary/common/copysignd2.c create mode 100644 Extras/simdmathlibrary/common/copysignf4.c create mode 100644 Extras/simdmathlibrary/common/cosd2.c create mode 100644 Extras/simdmathlibrary/common/cosf4.c create mode 100644 Extras/simdmathlibrary/common/divd2.c create mode 100644 Extras/simdmathlibrary/common/divf4.c create mode 100644 Extras/simdmathlibrary/common/divi4.c create mode 100644 Extras/simdmathlibrary/common/divu4.c create mode 100644 Extras/simdmathlibrary/common/exp2f4.c create mode 100644 Extras/simdmathlibrary/common/expf4.c create mode 100644 Extras/simdmathlibrary/common/expm1f4.c create mode 100644 Extras/simdmathlibrary/common/fabsd2.c create mode 100644 Extras/simdmathlibrary/common/fabsf4.c create mode 100644 Extras/simdmathlibrary/common/fdimd2.c create mode 100644 Extras/simdmathlibrary/common/fdimf4.c create mode 100644 Extras/simdmathlibrary/common/floord2.c create mode 100644 Extras/simdmathlibrary/common/floorf4.c create mode 100644 Extras/simdmathlibrary/common/fmad2.c create mode 100644 Extras/simdmathlibrary/common/fmaf4.c create mode 100644 Extras/simdmathlibrary/common/fmaxd2.c create mode 100644 Extras/simdmathlibrary/common/fmaxf4.c create mode 100644 Extras/simdmathlibrary/common/fmind2.c create mode 100644 Extras/simdmathlibrary/common/fminf4.c create mode 100644 Extras/simdmathlibrary/common/fmodd2.c create mode 100644 Extras/simdmathlibrary/common/fmodf4.c create mode 100644 Extras/simdmathlibrary/common/fpclassifyd2.c create mode 100644 Extras/simdmathlibrary/common/fpclassifyf4.c create mode 100644 Extras/simdmathlibrary/common/frexpd2.c create mode 100644 Extras/simdmathlibrary/common/frexpf4.c create mode 100644 Extras/simdmathlibrary/common/hypotd2.c create mode 100644 Extras/simdmathlibrary/common/hypotf4.c create mode 100644 Extras/simdmathlibrary/common/ilogbd2.c create mode 100644 Extras/simdmathlibrary/common/ilogbf4.c create mode 100644 Extras/simdmathlibrary/common/irintf4.c create mode 100644 Extras/simdmathlibrary/common/iroundf4.c create mode 100644 Extras/simdmathlibrary/common/is0denormd2.c create mode 100644 Extras/simdmathlibrary/common/is0denormf4.c create mode 100644 Extras/simdmathlibrary/common/isequald2.c create mode 100644 Extras/simdmathlibrary/common/isequalf4.c create mode 100644 Extras/simdmathlibrary/common/isfinited2.c create mode 100644 Extras/simdmathlibrary/common/isfinitef4.c create mode 100644 Extras/simdmathlibrary/common/isgreaterd2.c create mode 100644 Extras/simdmathlibrary/common/isgreaterequald2.c create mode 100644 Extras/simdmathlibrary/common/isgreaterequalf4.c create mode 100644 Extras/simdmathlibrary/common/isgreaterf4.c create mode 100644 Extras/simdmathlibrary/common/isinfd2.c create mode 100644 Extras/simdmathlibrary/common/isinff4.c create mode 100644 Extras/simdmathlibrary/common/islessd2.c create mode 100644 Extras/simdmathlibrary/common/islessequald2.c create mode 100644 Extras/simdmathlibrary/common/islessequalf4.c create mode 100644 Extras/simdmathlibrary/common/islessf4.c create mode 100644 Extras/simdmathlibrary/common/islessgreaterd2.c create mode 100644 Extras/simdmathlibrary/common/islessgreaterf4.c create mode 100644 Extras/simdmathlibrary/common/isnand2.c create mode 100644 Extras/simdmathlibrary/common/isnanf4.c create mode 100644 Extras/simdmathlibrary/common/isnormald2.c create mode 100644 Extras/simdmathlibrary/common/isnormalf4.c create mode 100644 Extras/simdmathlibrary/common/isunorderedd2.c create mode 100644 Extras/simdmathlibrary/common/isunorderedf4.c create mode 100644 Extras/simdmathlibrary/common/ldexpd2.c create mode 100644 Extras/simdmathlibrary/common/ldexpf4.c create mode 100644 Extras/simdmathlibrary/common/llabsi2.c create mode 100644 Extras/simdmathlibrary/common/lldivi2.c create mode 100644 Extras/simdmathlibrary/common/lldivu2.c create mode 100644 Extras/simdmathlibrary/common/llrintd2.c create mode 100644 Extras/simdmathlibrary/common/llrintf4.c create mode 100644 Extras/simdmathlibrary/common/llroundd2.c create mode 100644 Extras/simdmathlibrary/common/llroundf4.c create mode 100644 Extras/simdmathlibrary/common/log10f4.c create mode 100644 Extras/simdmathlibrary/common/log1pf4.c create mode 100644 Extras/simdmathlibrary/common/log2f4.c create mode 100644 Extras/simdmathlibrary/common/logbd2.c create mode 100644 Extras/simdmathlibrary/common/logbf4.c create mode 100644 Extras/simdmathlibrary/common/logf4.c create mode 100644 Extras/simdmathlibrary/common/modfd2.c create mode 100644 Extras/simdmathlibrary/common/modff4.c create mode 100644 Extras/simdmathlibrary/common/nearbyintd2.c create mode 100644 Extras/simdmathlibrary/common/nearbyintf4.c create mode 100644 Extras/simdmathlibrary/common/negated2.c create mode 100644 Extras/simdmathlibrary/common/negatef4.c create mode 100644 Extras/simdmathlibrary/common/negatei4.c create mode 100644 Extras/simdmathlibrary/common/negatell2.c create mode 100644 Extras/simdmathlibrary/common/nextafterd2.c create mode 100644 Extras/simdmathlibrary/common/nextafterf4.c create mode 100644 Extras/simdmathlibrary/common/powf4.c create mode 100644 Extras/simdmathlibrary/common/recipd2.c create mode 100644 Extras/simdmathlibrary/common/recipf4.c create mode 100644 Extras/simdmathlibrary/common/remainderd2.c create mode 100644 Extras/simdmathlibrary/common/remainderf4.c create mode 100644 Extras/simdmathlibrary/common/remquod2.c create mode 100644 Extras/simdmathlibrary/common/remquof4.c create mode 100644 Extras/simdmathlibrary/common/rintd2.c create mode 100644 Extras/simdmathlibrary/common/rintf4.c create mode 100644 Extras/simdmathlibrary/common/roundd2.c create mode 100644 Extras/simdmathlibrary/common/roundf4.c create mode 100644 Extras/simdmathlibrary/common/rsqrtd2.c create mode 100644 Extras/simdmathlibrary/common/rsqrtf4.c create mode 100644 Extras/simdmathlibrary/common/scalbllnd2.c create mode 100644 Extras/simdmathlibrary/common/scalbnf4.c create mode 100644 Extras/simdmathlibrary/common/signbitd2.c create mode 100644 Extras/simdmathlibrary/common/signbitf4.c create mode 100644 Extras/simdmathlibrary/common/simdmath.h create mode 100644 Extras/simdmathlibrary/common/simdmath/_sincos.h create mode 100644 Extras/simdmathlibrary/common/sincosd2.c create mode 100644 Extras/simdmathlibrary/common/sincosf4.c create mode 100644 Extras/simdmathlibrary/common/sind2.c create mode 100644 Extras/simdmathlibrary/common/sinf4.c create mode 100644 Extras/simdmathlibrary/common/sqrtd2.c create mode 100644 Extras/simdmathlibrary/common/sqrtf4.c create mode 100644 Extras/simdmathlibrary/common/tand2.c create mode 100644 Extras/simdmathlibrary/common/tanf4.c create mode 100644 Extras/simdmathlibrary/common/truncd2.c create mode 100644 Extras/simdmathlibrary/common/truncf4.c create mode 100644 Extras/simdmathlibrary/ppu/Makefile create mode 100644 Extras/simdmathlibrary/ppu/simdmath/_vec_utils.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/absi4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/acosf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/asinf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/atan2f4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/atanf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/cbrtf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/ceilf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/copysignf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/cosf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/divf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/divi4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/exp2f4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/expf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/expm1f4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/fabsf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/fdimf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/floorf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/fmaf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/fmaxf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/fminf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/fmodf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/frexpf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/hypotf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/ilogbf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/ldexpf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/log10f4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/log1pf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/log2f4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/logbf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/logf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/modff4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/negatef4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/negatei4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/powf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/recipf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/rsqrtf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/sincosf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/sinf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/sqrtf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/tanf4.h create mode 100644 Extras/simdmathlibrary/ppu/simdmath/truncf4.h create mode 100644 Extras/simdmathlibrary/ppu/tests/Makefile create mode 100644 Extras/simdmathlibrary/ppu/tests/absi4.c create mode 100644 Extras/simdmathlibrary/ppu/tests/ceilf4.c create mode 100644 Extras/simdmathlibrary/ppu/tests/copysignf4.c create mode 100644 Extras/simdmathlibrary/ppu/tests/divf4.c create mode 100644 Extras/simdmathlibrary/ppu/tests/divi4.c create mode 100644 Extras/simdmathlibrary/ppu/tests/fabsf4.c create mode 100644 Extras/simdmathlibrary/ppu/tests/floorf4.c create mode 100644 Extras/simdmathlibrary/ppu/tests/fminf4_fmaxf4.c create mode 100644 Extras/simdmathlibrary/ppu/tests/fmodf4.c create mode 100644 Extras/simdmathlibrary/ppu/tests/modff4.c create mode 100644 Extras/simdmathlibrary/ppu/tests/negatef4.c create mode 100644 Extras/simdmathlibrary/ppu/tests/negatei4.c create mode 100644 Extras/simdmathlibrary/ppu/tests/recipf4.c create mode 100644 Extras/simdmathlibrary/ppu/tests/rsqrtf4.c create mode 100644 Extras/simdmathlibrary/ppu/tests/sqrtf4.c create mode 100644 Extras/simdmathlibrary/ppu/tests/testutils.c create mode 100644 Extras/simdmathlibrary/ppu/tests/testutils.h create mode 100644 Extras/simdmathlibrary/ppu/tests/truncf4.c create mode 100644 Extras/simdmathlibrary/simdmath.spec create mode 100644 Extras/simdmathlibrary/spu/Makefile create mode 100644 Extras/simdmathlibrary/spu/simdmath/_lldiv.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/_remainder.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/_vec_utils.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/absi4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/acosf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/asinf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/atan2f4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/atanf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/cbrtf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/ceild2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/ceilf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/copysignd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/copysignf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/cosd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/cosf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/divd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/divf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/divi4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/divu4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/exp2f4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/expf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/expm1f4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/fabsd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/fabsf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/fdimd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/fdimf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/floord2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/floorf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/fmad2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/fmaf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/fmaxd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/fmaxf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/fmind2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/fminf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/fmodd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/fmodf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/fpclassifyd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/fpclassifyf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/frexpd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/frexpf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/hypotd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/hypotf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/ilogbd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/ilogbf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/irintf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/iroundf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/is0denormd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/is0denormf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/isequald2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/isequalf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/isfinited2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/isfinitef4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/isgreaterd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/isgreaterequald2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/isgreaterequalf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/isgreaterf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/isinfd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/isinff4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/islessd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/islessequald2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/islessequalf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/islessf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/islessgreaterd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/islessgreaterf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/isnand2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/isnanf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/isnormald2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/isnormalf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/isunorderedd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/isunorderedf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/ldexpd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/ldexpf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/llabsi2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/lldivi2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/lldivu2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/llrintd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/llrintf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/llroundd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/llroundf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/log10f4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/log1pf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/log2f4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/logbd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/logbf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/logf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/modfd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/modff4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/nearbyintd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/nearbyintf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/negated2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/negatef4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/negatei4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/negatell2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/nextafterd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/nextafterf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/powf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/recipd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/recipf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/remainderd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/remainderf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/remquod2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/remquof4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/rintd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/rintf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/roundd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/roundf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/rsqrtd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/rsqrtf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/scalbllnd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/scalbnf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/signbitd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/signbitf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/sincosd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/sincosf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/sind2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/sinf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/sqrtd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/sqrtf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/tand2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/tanf4.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/truncd2.h create mode 100644 Extras/simdmathlibrary/spu/simdmath/truncf4.h create mode 100644 Extras/simdmathlibrary/spu/tests/Makefile create mode 100644 Extras/simdmathlibrary/spu/tests/absi4.c create mode 100644 Extras/simdmathlibrary/spu/tests/ceild2.c create mode 100644 Extras/simdmathlibrary/spu/tests/ceilf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/copysignd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/copysignf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/divd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/divf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/divi4.c create mode 100644 Extras/simdmathlibrary/spu/tests/divu4.c create mode 100644 Extras/simdmathlibrary/spu/tests/fabsd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/fabsf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/fdimd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/floord2.c create mode 100644 Extras/simdmathlibrary/spu/tests/floorf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/fmad2.c create mode 100644 Extras/simdmathlibrary/spu/tests/fmind2_fmaxd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/fminf4_fmaxf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/fmodd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/fmodf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/fpclassifyd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/fpclassifyf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/frexpd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/frexpf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/hypotd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/hypotf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/ilogbd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/ilogbf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/irintf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/iroundf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/is0denormd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/is0denormf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/isequald2.c create mode 100644 Extras/simdmathlibrary/spu/tests/isequalf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/isfinited2.c create mode 100644 Extras/simdmathlibrary/spu/tests/isfinitef4.c create mode 100644 Extras/simdmathlibrary/spu/tests/isgreaterd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/isgreaterequald2.c create mode 100644 Extras/simdmathlibrary/spu/tests/isgreaterequalf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/isgreaterf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/isinfd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/isinff4.c create mode 100644 Extras/simdmathlibrary/spu/tests/islessd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/islessequald2.c create mode 100644 Extras/simdmathlibrary/spu/tests/islessequalf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/islessf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/islessgreaterd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/islessgreaterf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/isnand2.c create mode 100644 Extras/simdmathlibrary/spu/tests/isnanf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/isnormald2.c create mode 100644 Extras/simdmathlibrary/spu/tests/isnormalf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/isunorderedd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/isunorderedf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/ldexpd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/llabsi2.c create mode 100644 Extras/simdmathlibrary/spu/tests/lldivi2.c create mode 100644 Extras/simdmathlibrary/spu/tests/lldivu2.c create mode 100644 Extras/simdmathlibrary/spu/tests/llrintd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/llrintf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/llroundd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/llroundf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/logbd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/logbf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/modfd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/modff4.c create mode 100644 Extras/simdmathlibrary/spu/tests/nearbyintd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/nearbyintf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/negated2.c create mode 100644 Extras/simdmathlibrary/spu/tests/negatef4.c create mode 100644 Extras/simdmathlibrary/spu/tests/negatei4.c create mode 100644 Extras/simdmathlibrary/spu/tests/negatell2.c create mode 100644 Extras/simdmathlibrary/spu/tests/nextafterd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/nextafterf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/recipd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/recipf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/remainderd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/remainderf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/remquod2.c create mode 100644 Extras/simdmathlibrary/spu/tests/remquof4.c create mode 100644 Extras/simdmathlibrary/spu/tests/rintd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/rintf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/roundd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/roundf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/rsqrtd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/rsqrtf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/scalbllnd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/scalbnf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/signbitd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/signbitf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/sqrtd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/sqrtf4.c create mode 100644 Extras/simdmathlibrary/spu/tests/testutils.c create mode 100644 Extras/simdmathlibrary/spu/tests/testutils.h create mode 100644 Extras/simdmathlibrary/spu/tests/truncd2.c create mode 100644 Extras/simdmathlibrary/spu/tests/truncf4.c create mode 100644 Extras/software_cache/cache/CommonPublicLicense-1.0 create mode 100644 Extras/software_cache/cache/include/Makefile create mode 100644 Extras/software_cache/cache/include/README create mode 100644 Extras/software_cache/cache/include/api.h create mode 100644 Extras/software_cache/cache/include/cbe_mfc.h create mode 100644 Extras/software_cache/cache/include/defs.h create mode 100644 Extras/software_cache/cache/include/dma.h create mode 100644 Extras/software_cache/cache/include/ilog2.h create mode 100644 Extras/software_cache/cache/include/memset.h create mode 100644 Extras/software_cache/cache/include/nway-lookup.h create mode 100644 Extras/software_cache/cache/include/nway-miss.h create mode 100644 Extras/software_cache/cache/include/nway-opt.h create mode 100644 Extras/software_cache/cache/include/nway-replace.h create mode 100644 Extras/software_cache/cache/include/nway.h create mode 100644 Extras/software_cache/cache/include/spe_cache.h create mode 100644 Extras/software_cache/cache/include/vec_literal.h create mode 100644 Extras/sph/READ_ME.txt create mode 100644 Extras/sph/cmp.sh create mode 100644 Extras/sph/common/GLee.c create mode 100644 Extras/sph/common/GLee.h create mode 100644 Extras/sph/common/common_defs.h create mode 100644 Extras/sph/common/geomx.cpp create mode 100644 Extras/sph/common/geomx.h create mode 100644 Extras/sph/common/gl_helper.cpp create mode 100644 Extras/sph/common/gl_helper.h create mode 100644 Extras/sph/common/glext.h create mode 100644 Extras/sph/common/glut.h create mode 100644 Extras/sph/common/image.cpp create mode 100644 Extras/sph/common/image.h create mode 100644 Extras/sph/common/matrix-inline.h create mode 100644 Extras/sph/common/matrix.cci create mode 100644 Extras/sph/common/matrix.cpp create mode 100644 Extras/sph/common/matrix.h create mode 100644 Extras/sph/common/mdebug.cpp create mode 100644 Extras/sph/common/mdebug.h create mode 100644 Extras/sph/common/mesh.cpp create mode 100644 Extras/sph/common/mesh.h create mode 100644 Extras/sph/common/mesh_info.h create mode 100644 Extras/sph/common/mtime.cpp create mode 100644 Extras/sph/common/mtime.h create mode 100644 Extras/sph/common/particle.cpp create mode 100644 Extras/sph/common/particle.h create mode 100644 Extras/sph/common/point_set.cpp create mode 100644 Extras/sph/common/point_set.h create mode 100644 Extras/sph/common/vector-inline.h create mode 100644 Extras/sph/common/vector.cci create mode 100644 Extras/sph/common/vector.cpp create mode 100644 Extras/sph/common/vector.h create mode 100644 Extras/sph/fluid_system_host.linkinfo create mode 100644 Extras/sph/fluids.vcproj create mode 100644 Extras/sph/fluids/fluid.cpp create mode 100644 Extras/sph/fluids/fluid.h create mode 100644 Extras/sph/fluids/fluid_system.cpp create mode 100644 Extras/sph/fluids/fluid_system.cu create mode 100644 Extras/sph/fluids/fluid_system.h create mode 100644 Extras/sph/fluids/fluid_system_host.cu create mode 100644 Extras/sph/fluids/fluid_system_host.cuh create mode 100644 Extras/sph/fluids/fluid_system_kern.cu create mode 100644 Extras/sph/fluids/fluid_system_kern.cuh create mode 100644 Extras/sph/fluids/radixsort.cu create mode 100644 Extras/sph/fluids/radixsort.cuh create mode 100644 Extras/sph/fluids/radixsort_kernel.cu create mode 100644 Extras/sph/fluids_2005.sln create mode 100644 Extras/sph/fluids_2005.vcproj create mode 100644 Extras/sph/main.cpp create mode 100644 Extras/vectormathlibrary/LICENSE create mode 100644 Extras/vectormathlibrary/Makefile create mode 100644 Extras/vectormathlibrary/README create mode 100644 Extras/vectormathlibrary/doc/Vector_Math_Library-Overview.pdf create mode 100644 Extras/vectormathlibrary/include/vectormath/SSE/cpp/boolInVec.h create mode 100644 Extras/vectormathlibrary/include/vectormath/SSE/cpp/floatInVec.h create mode 100644 Extras/vectormathlibrary/include/vectormath/SSE/cpp/mat_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/SSE/cpp/quat_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/SSE/cpp/readme_e.txt create mode 100644 Extras/vectormathlibrary/include/vectormath/SSE/cpp/vec_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/SSE/cpp/vecidx_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/SSE/cpp/vectormath_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/c/vectormath_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/c/vectormath_aos_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/c/vectormath_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/c/vectormath_soa_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/cpp/vectormath_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/cpp/vectormath_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/mat_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/mat_aos_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/mat_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/mat_soa_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/quat_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/quat_aos_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/quat_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/quat_soa_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/vec_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/vec_aos_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/vec_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/vec_soa_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/vec_types.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/vectormath_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/vectormath_aos_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/vectormath_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/c/vectormath_soa_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/cpp/boolInVec.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/cpp/floatInVec.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/cpp/mat_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/cpp/mat_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/cpp/quat_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/cpp/quat_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/cpp/vec_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/cpp/vec_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/cpp/vecidx_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/cpp/vectormath_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/ppu/cpp/vectormath_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/scalar/c/mat_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/scalar/c/mat_aos_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/scalar/c/quat_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/scalar/c/quat_aos_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/scalar/c/vec_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/scalar/c/vec_aos_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/scalar/c/vectormath_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/scalar/c/vectormath_aos_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/scalar/cpp/boolInVec.h create mode 100644 Extras/vectormathlibrary/include/vectormath/scalar/cpp/floatInVec.h create mode 100644 Extras/vectormathlibrary/include/vectormath/scalar/cpp/mat_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/scalar/cpp/quat_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/scalar/cpp/vec_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/scalar/cpp/vectormath_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/c/mat_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/c/mat_aos_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/c/mat_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/c/mat_soa_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/c/quat_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/c/quat_aos_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/c/quat_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/c/quat_soa_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/c/vec_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/c/vec_aos_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/c/vec_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/c/vec_soa_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/c/vectormath_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/c/vectormath_aos_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/c/vectormath_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/c/vectormath_soa_v.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/cpp/boolInVec.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/cpp/floatInVec.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/cpp/mat_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/cpp/mat_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/cpp/quat_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/cpp/quat_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/cpp/vec_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/cpp/vec_soa.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/cpp/vecidx_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/cpp/vectormath_aos.h create mode 100644 Extras/vectormathlibrary/include/vectormath/spu/cpp/vectormath_soa.h create mode 100644 Extras/vectormathlibrary/tests/Makefile create mode 100644 Extras/vectormathlibrary/tests/clean.pl create mode 100644 Extras/vectormathlibrary/tests/compare.pl create mode 100644 Extras/vectormathlibrary/tests/main_vmtest.cpp create mode 100644 Extras/vectormathlibrary/tests/test.h create mode 100644 Extras/vectormathlibrary/tests/test1_aos_c.c create mode 100644 Extras/vectormathlibrary/tests/test1_aos_cpp.cpp create mode 100644 Extras/vectormathlibrary/tests/test1_reference.txt create mode 100644 Extras/vectormathlibrary/tests/test1_soa_c.c create mode 100644 Extras/vectormathlibrary/tests/test1_soa_cpp.cpp create mode 100644 Extras/vectormathlibrary/tests/test2_aos_c.c create mode 100644 Extras/vectormathlibrary/tests/test2_aos_cpp.cpp create mode 100644 Extras/vectormathlibrary/tests/test2_reference.txt create mode 100644 Extras/vectormathlibrary/tests/test2_soa_c.c create mode 100644 Extras/vectormathlibrary/tests/test2_soa_cpp.cpp create mode 100644 Extras/vectormathlibrary/tests/test3_aos_c.c create mode 100644 Extras/vectormathlibrary/tests/test3_aos_cpp.cpp create mode 100644 Extras/vectormathlibrary/tests/test3_reference.txt create mode 100644 Extras/vectormathlibrary/tests/test3_soa_c.c create mode 100644 Extras/vectormathlibrary/tests/test3_soa_cpp.cpp create mode 100644 Extras/vectormathlibrary/tests/test4_aos_c.c create mode 100644 Extras/vectormathlibrary/tests/test4_aos_cpp.cpp create mode 100644 Extras/vectormathlibrary/tests/test4_reference.txt create mode 100644 Extras/vectormathlibrary/tests/test4_soa_c.c create mode 100644 Extras/vectormathlibrary/tests/test4_soa_cpp.cpp create mode 100644 Extras/vectormathlibrary/vectormath.spec create mode 100644 GLUT32.DLL create mode 100644 Glut/EmptyGL/GL/egl_cpx.h create mode 100644 Glut/EmptyGL/GL/egl_defs.h create mode 100644 Glut/EmptyGL/GL/egl_logged.h create mode 100644 Glut/EmptyGL/GL/egl_tokens.h create mode 100644 Glut/EmptyGL/GL/egl_void.h create mode 100644 Glut/EmptyGL/GL/gl.h create mode 100644 Glut/EmptyGL/GL/glu.h create mode 100644 Glut/EmptyGL/GL/glut.h create mode 100644 Glut/GL/glew.h create mode 100644 Glut/GL/glext.h create mode 100644 Glut/GL/glut.h create mode 100644 Glut/GL/glxew.h create mode 100644 Glut/GL/glxext.h create mode 100644 Glut/GL/wglew.h create mode 100644 Glut/GL/wglext.h create mode 100644 Glut/btGlutInclude.h create mode 100644 Glut/glew32s.lib create mode 100644 Glut/glew64s.lib create mode 100644 Glut/glut32.lib create mode 100644 Glut/glut64.lib create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100644 RELEASING.TXT create mode 100644 UnitTests/BulletUnitTests/CMakeLists.txt create mode 100644 UnitTests/BulletUnitTests/Main.cpp create mode 100644 UnitTests/BulletUnitTests/TestBulletOnly.h create mode 100644 UnitTests/BulletUnitTests/TestLinearMath.h create mode 100644 UnitTests/CMakeLists.txt create mode 100644 UnitTests/cppunit/AUTHORS create mode 100644 UnitTests/cppunit/BUGS create mode 100644 UnitTests/cppunit/CMakeLists.txt create mode 100644 UnitTests/cppunit/ChangeLog create mode 100644 UnitTests/cppunit/CodingGuideLines.txt create mode 100644 UnitTests/cppunit/THANKS create mode 100644 UnitTests/cppunit/TODO create mode 100644 UnitTests/cppunit/include/cppunit/AdditionalMessage.h create mode 100644 UnitTests/cppunit/include/cppunit/Asserter.h create mode 100644 UnitTests/cppunit/include/cppunit/BriefTestProgressListener.h create mode 100644 UnitTests/cppunit/include/cppunit/CompilerOutputter.h create mode 100644 UnitTests/cppunit/include/cppunit/Exception.h create mode 100644 UnitTests/cppunit/include/cppunit/Message.h create mode 100644 UnitTests/cppunit/include/cppunit/Outputter.h create mode 100644 UnitTests/cppunit/include/cppunit/Portability.h create mode 100644 UnitTests/cppunit/include/cppunit/Protector.h create mode 100644 UnitTests/cppunit/include/cppunit/SourceLine.h create mode 100644 UnitTests/cppunit/include/cppunit/SynchronizedObject.h create mode 100644 UnitTests/cppunit/include/cppunit/Test.h create mode 100644 UnitTests/cppunit/include/cppunit/TestAssert.h create mode 100644 UnitTests/cppunit/include/cppunit/TestCaller.h create mode 100644 UnitTests/cppunit/include/cppunit/TestCase.h create mode 100644 UnitTests/cppunit/include/cppunit/TestComposite.h create mode 100644 UnitTests/cppunit/include/cppunit/TestFailure.h create mode 100644 UnitTests/cppunit/include/cppunit/TestFixture.h create mode 100644 UnitTests/cppunit/include/cppunit/TestLeaf.h create mode 100644 UnitTests/cppunit/include/cppunit/TestListener.h create mode 100644 UnitTests/cppunit/include/cppunit/TestPath.h create mode 100644 UnitTests/cppunit/include/cppunit/TestResult.h create mode 100644 UnitTests/cppunit/include/cppunit/TestResultCollector.h create mode 100644 UnitTests/cppunit/include/cppunit/TestRunner.h create mode 100644 UnitTests/cppunit/include/cppunit/TestSuccessListener.h create mode 100644 UnitTests/cppunit/include/cppunit/TestSuite.h create mode 100644 UnitTests/cppunit/include/cppunit/TextOutputter.h create mode 100644 UnitTests/cppunit/include/cppunit/TextTestProgressListener.h create mode 100644 UnitTests/cppunit/include/cppunit/TextTestResult.h create mode 100644 UnitTests/cppunit/include/cppunit/TextTestRunner.h create mode 100644 UnitTests/cppunit/include/cppunit/XmlOutputter.h create mode 100644 UnitTests/cppunit/include/cppunit/XmlOutputterHook.h create mode 100644 UnitTests/cppunit/include/cppunit/config-auto.h create mode 100644 UnitTests/cppunit/include/cppunit/config/CppUnitApi.h create mode 100644 UnitTests/cppunit/include/cppunit/config/SelectDllLoader.h create mode 100644 UnitTests/cppunit/include/cppunit/config/SourcePrefix.h create mode 100644 UnitTests/cppunit/include/cppunit/config/config-bcb5.h create mode 100644 UnitTests/cppunit/include/cppunit/config/config-evc4.h create mode 100644 UnitTests/cppunit/include/cppunit/config/config-mac.h create mode 100644 UnitTests/cppunit/include/cppunit/config/config-msvc6.h create mode 100644 UnitTests/cppunit/include/cppunit/extensions/AutoRegisterSuite.h create mode 100644 UnitTests/cppunit/include/cppunit/extensions/ExceptionTestCaseDecorator.h create mode 100644 UnitTests/cppunit/include/cppunit/extensions/HelperMacros.h create mode 100644 UnitTests/cppunit/include/cppunit/extensions/Orthodox.h create mode 100644 UnitTests/cppunit/include/cppunit/extensions/RepeatedTest.h create mode 100644 UnitTests/cppunit/include/cppunit/extensions/TestCaseDecorator.h create mode 100644 UnitTests/cppunit/include/cppunit/extensions/TestDecorator.h create mode 100644 UnitTests/cppunit/include/cppunit/extensions/TestFactory.h create mode 100644 UnitTests/cppunit/include/cppunit/extensions/TestFactoryRegistry.h create mode 100644 UnitTests/cppunit/include/cppunit/extensions/TestFixtureFactory.h create mode 100644 UnitTests/cppunit/include/cppunit/extensions/TestNamer.h create mode 100644 UnitTests/cppunit/include/cppunit/extensions/TestSetUp.h create mode 100644 UnitTests/cppunit/include/cppunit/extensions/TestSuiteBuilderContext.h create mode 100644 UnitTests/cppunit/include/cppunit/extensions/TestSuiteFactory.h create mode 100644 UnitTests/cppunit/include/cppunit/extensions/TypeInfoHelper.h create mode 100644 UnitTests/cppunit/include/cppunit/extensions/XmlInputHelper.h create mode 100644 UnitTests/cppunit/include/cppunit/plugin/DynamicLibraryManager.h create mode 100644 UnitTests/cppunit/include/cppunit/plugin/DynamicLibraryManagerException.h create mode 100644 UnitTests/cppunit/include/cppunit/plugin/PlugInManager.h create mode 100644 UnitTests/cppunit/include/cppunit/plugin/PlugInParameters.h create mode 100644 UnitTests/cppunit/include/cppunit/plugin/TestPlugIn.h create mode 100644 UnitTests/cppunit/include/cppunit/plugin/TestPlugInDefaultImpl.h create mode 100644 UnitTests/cppunit/include/cppunit/portability/CppUnitDeque.h create mode 100644 UnitTests/cppunit/include/cppunit/portability/CppUnitMap.h create mode 100644 UnitTests/cppunit/include/cppunit/portability/CppUnitSet.h create mode 100644 UnitTests/cppunit/include/cppunit/portability/CppUnitStack.h create mode 100644 UnitTests/cppunit/include/cppunit/portability/CppUnitVector.h create mode 100644 UnitTests/cppunit/include/cppunit/portability/FloatingPoint.h create mode 100644 UnitTests/cppunit/include/cppunit/portability/Stream.h create mode 100644 UnitTests/cppunit/include/cppunit/tools/Algorithm.h create mode 100644 UnitTests/cppunit/include/cppunit/tools/StringTools.h create mode 100644 UnitTests/cppunit/include/cppunit/tools/XmlDocument.h create mode 100644 UnitTests/cppunit/include/cppunit/tools/XmlElement.h create mode 100644 UnitTests/cppunit/include/cppunit/ui/text/TestRunner.h create mode 100644 UnitTests/cppunit/include/cppunit/ui/text/TextTestRunner.h create mode 100644 UnitTests/cppunit/src/cppunit/AdditionalMessage.cpp create mode 100644 UnitTests/cppunit/src/cppunit/Asserter.cpp create mode 100644 UnitTests/cppunit/src/cppunit/BeOsDynamicLibraryManager.cpp create mode 100644 UnitTests/cppunit/src/cppunit/BriefTestProgressListener.cpp create mode 100644 UnitTests/cppunit/src/cppunit/CompilerOutputter.cpp create mode 100644 UnitTests/cppunit/src/cppunit/DefaultProtector.cpp create mode 100644 UnitTests/cppunit/src/cppunit/DefaultProtector.h create mode 100644 UnitTests/cppunit/src/cppunit/DllMain.cpp create mode 100644 UnitTests/cppunit/src/cppunit/DynamicLibraryManager.cpp create mode 100644 UnitTests/cppunit/src/cppunit/DynamicLibraryManagerException.cpp create mode 100644 UnitTests/cppunit/src/cppunit/Exception.cpp create mode 100644 UnitTests/cppunit/src/cppunit/Message.cpp create mode 100644 UnitTests/cppunit/src/cppunit/PlugInManager.cpp create mode 100644 UnitTests/cppunit/src/cppunit/PlugInParameters.cpp create mode 100644 UnitTests/cppunit/src/cppunit/Protector.cpp create mode 100644 UnitTests/cppunit/src/cppunit/ProtectorChain.cpp create mode 100644 UnitTests/cppunit/src/cppunit/ProtectorChain.h create mode 100644 UnitTests/cppunit/src/cppunit/ProtectorContext.h create mode 100644 UnitTests/cppunit/src/cppunit/RepeatedTest.cpp create mode 100644 UnitTests/cppunit/src/cppunit/ShlDynamicLibraryManager.cpp create mode 100644 UnitTests/cppunit/src/cppunit/SourceLine.cpp create mode 100644 UnitTests/cppunit/src/cppunit/StringTools.cpp create mode 100644 UnitTests/cppunit/src/cppunit/SynchronizedObject.cpp create mode 100644 UnitTests/cppunit/src/cppunit/Test.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestAssert.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestCase.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestCaseDecorator.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestComposite.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestDecorator.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestFactoryRegistry.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestFailure.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestLeaf.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestNamer.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestPath.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestPlugInDefaultImpl.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestResult.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestResultCollector.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestRunner.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestSetUp.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestSuccessListener.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestSuite.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TestSuiteBuilderContext.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TextOutputter.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TextTestProgressListener.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TextTestResult.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TextTestRunner.cpp create mode 100644 UnitTests/cppunit/src/cppunit/TypeInfoHelper.cpp create mode 100644 UnitTests/cppunit/src/cppunit/UnixDynamicLibraryManager.cpp create mode 100644 UnitTests/cppunit/src/cppunit/Win32DynamicLibraryManager.cpp create mode 100644 UnitTests/cppunit/src/cppunit/XmlDocument.cpp create mode 100644 UnitTests/cppunit/src/cppunit/XmlElement.cpp create mode 100644 UnitTests/cppunit/src/cppunit/XmlOutputter.cpp create mode 100644 UnitTests/cppunit/src/cppunit/XmlOutputterHook.cpp create mode 100644 VERSION create mode 100644 acinclude.m4 create mode 100755 autogen.sh create mode 100644 bullet.pc.cmake create mode 100644 bullet.pc.in create mode 100644 bullet_logo.png create mode 100644 config.h.in create mode 100644 configure.ac create mode 100644 convex0.bin create mode 100644 file.obj create mode 100644 glut64.dll create mode 100644 heightfield128x128.raw create mode 100644 install-sh create mode 100644 jenga.dae create mode 100644 lib/readme.txt create mode 100644 msvc/autoexp_dat.txt create mode 100644 msvc/bullet.rc create mode 100644 msvc/bullet_ico.ico create mode 100644 msvc/findDirectX11.lua create mode 100644 msvc/findOpenCL.lua create mode 100644 msvc/premake4.exe create mode 100644 msvc/premake4.lua create mode 100644 msvc/vs2005.bat create mode 100644 msvc/vs2008.bat create mode 100644 msvc/vs2010.bat create mode 100644 msvc/vs2010_dx11.bat create mode 100644 msvc/vs2010_opencl.bat create mode 100644 msvc/vs_all.bat create mode 100644 packaging/bullet.spec create mode 100644 src/Bullet-C-Api.h create mode 100644 src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp create mode 100644 src/BulletCollision/BroadphaseCollision/btAxisSweep3.h create mode 100644 src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h create mode 100644 src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp create mode 100644 src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h create mode 100644 src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp create mode 100644 src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h create mode 100644 src/BulletCollision/BroadphaseCollision/btDbvt.cpp create mode 100644 src/BulletCollision/BroadphaseCollision/btDbvt.h create mode 100644 src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp create mode 100644 src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h create mode 100644 src/BulletCollision/BroadphaseCollision/btDispatcher.cpp create mode 100644 src/BulletCollision/BroadphaseCollision/btDispatcher.h create mode 100644 src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp create mode 100644 src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h create mode 100644 src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp create mode 100644 src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h create mode 100644 src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h create mode 100644 src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp create mode 100644 src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h create mode 100644 src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp create mode 100644 src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h create mode 100644 src/BulletCollision/CMakeLists.txt create mode 100644 src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp create mode 100644 src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h create mode 100644 src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h create mode 100644 src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h create mode 100644 src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h create mode 100644 src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h create mode 100644 src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h create mode 100644 src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h create mode 100644 src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h create mode 100644 src/BulletCollision/CollisionDispatch/btCollisionObject.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btCollisionObject.h create mode 100644 src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btCollisionWorld.h create mode 100644 src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h create mode 100644 src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h create mode 100644 src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h create mode 100644 src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h create mode 100644 src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h create mode 100644 src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h create mode 100644 src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h create mode 100644 src/BulletCollision/CollisionDispatch/btGhostObject.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btGhostObject.h create mode 100644 src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h create mode 100644 src/BulletCollision/CollisionDispatch/btManifoldResult.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btManifoldResult.h create mode 100644 src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h create mode 100644 src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h create mode 100644 src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h create mode 100644 src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h create mode 100644 src/BulletCollision/CollisionDispatch/btUnionFind.cpp create mode 100644 src/BulletCollision/CollisionDispatch/btUnionFind.h create mode 100644 src/BulletCollision/CollisionShapes/btBox2dShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btBox2dShape.h create mode 100644 src/BulletCollision/CollisionShapes/btBoxShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btBoxShape.h create mode 100644 src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h create mode 100644 src/BulletCollision/CollisionShapes/btCapsuleShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btCapsuleShape.h create mode 100644 src/BulletCollision/CollisionShapes/btCollisionMargin.h create mode 100644 src/BulletCollision/CollisionShapes/btCollisionShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btCollisionShape.h create mode 100644 src/BulletCollision/CollisionShapes/btCompoundShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btCompoundShape.h create mode 100644 src/BulletCollision/CollisionShapes/btConcaveShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btConcaveShape.h create mode 100644 src/BulletCollision/CollisionShapes/btConeShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btConeShape.h create mode 100644 src/BulletCollision/CollisionShapes/btConvex2dShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btConvex2dShape.h create mode 100644 src/BulletCollision/CollisionShapes/btConvexHullShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btConvexHullShape.h create mode 100644 src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btConvexInternalShape.h create mode 100644 src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h create mode 100644 src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp create mode 100644 src/BulletCollision/CollisionShapes/btConvexPolyhedron.h create mode 100644 src/BulletCollision/CollisionShapes/btConvexShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btConvexShape.h create mode 100644 src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h create mode 100644 src/BulletCollision/CollisionShapes/btCylinderShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btCylinderShape.h create mode 100644 src/BulletCollision/CollisionShapes/btEmptyShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btEmptyShape.h create mode 100644 src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h create mode 100644 src/BulletCollision/CollisionShapes/btMaterial.h create mode 100644 src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h create mode 100644 src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btMultiSphereShape.h create mode 100644 src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h create mode 100644 src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp create mode 100644 src/BulletCollision/CollisionShapes/btOptimizedBvh.h create mode 100644 src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h create mode 100644 src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h create mode 100644 src/BulletCollision/CollisionShapes/btShapeHull.cpp create mode 100644 src/BulletCollision/CollisionShapes/btShapeHull.h create mode 100644 src/BulletCollision/CollisionShapes/btSphereShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btSphereShape.h create mode 100644 src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btStaticPlaneShape.h create mode 100644 src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp create mode 100644 src/BulletCollision/CollisionShapes/btStridingMeshInterface.h create mode 100644 src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btTetrahedronShape.h create mode 100644 src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp create mode 100644 src/BulletCollision/CollisionShapes/btTriangleBuffer.h create mode 100644 src/BulletCollision/CollisionShapes/btTriangleCallback.cpp create mode 100644 src/BulletCollision/CollisionShapes/btTriangleCallback.h create mode 100644 src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp create mode 100644 src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h create mode 100644 src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp create mode 100644 src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h create mode 100644 src/BulletCollision/CollisionShapes/btTriangleInfoMap.h create mode 100644 src/BulletCollision/CollisionShapes/btTriangleMesh.cpp create mode 100644 src/BulletCollision/CollisionShapes/btTriangleMesh.h create mode 100644 src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btTriangleMeshShape.h create mode 100644 src/BulletCollision/CollisionShapes/btTriangleShape.h create mode 100644 src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp create mode 100644 src/BulletCollision/CollisionShapes/btUniformScalingShape.h create mode 100644 src/BulletCollision/Doxyfile create mode 100644 src/BulletCollision/Gimpact/btBoxCollision.h create mode 100644 src/BulletCollision/Gimpact/btClipPolygon.h create mode 100644 src/BulletCollision/Gimpact/btContactProcessing.cpp create mode 100644 src/BulletCollision/Gimpact/btContactProcessing.h create mode 100644 src/BulletCollision/Gimpact/btGImpactBvh.cpp create mode 100644 src/BulletCollision/Gimpact/btGImpactBvh.h create mode 100644 src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp create mode 100644 src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h create mode 100644 src/BulletCollision/Gimpact/btGImpactMassUtil.h create mode 100644 src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp create mode 100644 src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h create mode 100644 src/BulletCollision/Gimpact/btGImpactShape.cpp create mode 100644 src/BulletCollision/Gimpact/btGImpactShape.h create mode 100644 src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp create mode 100644 src/BulletCollision/Gimpact/btGenericPoolAllocator.h create mode 100644 src/BulletCollision/Gimpact/btGeometryOperations.h create mode 100644 src/BulletCollision/Gimpact/btQuantization.h create mode 100644 src/BulletCollision/Gimpact/btTriangleShapeEx.cpp create mode 100644 src/BulletCollision/Gimpact/btTriangleShapeEx.h create mode 100644 src/BulletCollision/Gimpact/gim_array.h create mode 100644 src/BulletCollision/Gimpact/gim_basic_geometry_operations.h create mode 100644 src/BulletCollision/Gimpact/gim_bitset.h create mode 100644 src/BulletCollision/Gimpact/gim_box_collision.h create mode 100644 src/BulletCollision/Gimpact/gim_box_set.cpp create mode 100644 src/BulletCollision/Gimpact/gim_box_set.h create mode 100644 src/BulletCollision/Gimpact/gim_clip_polygon.h create mode 100644 src/BulletCollision/Gimpact/gim_contact.cpp create mode 100644 src/BulletCollision/Gimpact/gim_contact.h create mode 100644 src/BulletCollision/Gimpact/gim_geom_types.h create mode 100644 src/BulletCollision/Gimpact/gim_geometry.h create mode 100644 src/BulletCollision/Gimpact/gim_hash_table.h create mode 100644 src/BulletCollision/Gimpact/gim_linear_math.h create mode 100644 src/BulletCollision/Gimpact/gim_math.h create mode 100644 src/BulletCollision/Gimpact/gim_memory.cpp create mode 100644 src/BulletCollision/Gimpact/gim_memory.h create mode 100644 src/BulletCollision/Gimpact/gim_radixsort.h create mode 100644 src/BulletCollision/Gimpact/gim_tri_collision.cpp create mode 100644 src/BulletCollision/Gimpact/gim_tri_collision.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp create mode 100644 src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp create mode 100644 src/BulletCollision/NarrowPhaseCollision/btConvexCast.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp create mode 100644 src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp create mode 100644 src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp create mode 100644 src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp create mode 100644 src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp create mode 100644 src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp create mode 100644 src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btPointCollector.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp create mode 100644 src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp create mode 100644 src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp create mode 100644 src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h create mode 100644 src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp create mode 100644 src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h create mode 100644 src/BulletCollision/ibmsdk/Makefile create mode 100644 src/BulletCollision/premake4.lua create mode 100644 src/BulletDynamics/CMakeLists.txt create mode 100644 src/BulletDynamics/Character/btCharacterControllerInterface.h create mode 100644 src/BulletDynamics/Character/btKinematicCharacterController.cpp create mode 100644 src/BulletDynamics/Character/btKinematicCharacterController.h create mode 100644 src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp create mode 100644 src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h create mode 100644 src/BulletDynamics/ConstraintSolver/btConstraintSolver.h create mode 100644 src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp create mode 100644 src/BulletDynamics/ConstraintSolver/btContactConstraint.h create mode 100644 src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h create mode 100644 src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp create mode 100644 src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h create mode 100644 src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp create mode 100644 src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h create mode 100644 src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp create mode 100644 src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h create mode 100644 src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp create mode 100644 src/BulletDynamics/ConstraintSolver/btHingeConstraint.h create mode 100644 src/BulletDynamics/ConstraintSolver/btJacobianEntry.h create mode 100644 src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp create mode 100644 src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h create mode 100644 src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp create mode 100644 src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h create mode 100755 src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp create mode 100755 src/BulletDynamics/ConstraintSolver/btSliderConstraint.h create mode 100644 src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp create mode 100644 src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h create mode 100644 src/BulletDynamics/ConstraintSolver/btSolverBody.h create mode 100644 src/BulletDynamics/ConstraintSolver/btSolverConstraint.h create mode 100644 src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp create mode 100644 src/BulletDynamics/ConstraintSolver/btTypedConstraint.h create mode 100644 src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp create mode 100644 src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h create mode 100644 src/BulletDynamics/Dynamics/Bullet-C-API.cpp create mode 100644 src/BulletDynamics/Dynamics/btActionInterface.h create mode 100644 src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp create mode 100644 src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h create mode 100644 src/BulletDynamics/Dynamics/btDynamicsWorld.h create mode 100644 src/BulletDynamics/Dynamics/btRigidBody.cpp create mode 100644 src/BulletDynamics/Dynamics/btRigidBody.h create mode 100644 src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp create mode 100644 src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h create mode 100644 src/BulletDynamics/Vehicle/btRaycastVehicle.cpp create mode 100644 src/BulletDynamics/Vehicle/btRaycastVehicle.h create mode 100644 src/BulletDynamics/Vehicle/btVehicleRaycaster.h create mode 100644 src/BulletDynamics/Vehicle/btWheelInfo.cpp create mode 100644 src/BulletDynamics/Vehicle/btWheelInfo.h create mode 100644 src/BulletDynamics/ibmsdk/Makefile create mode 100644 src/BulletDynamics/premake4.lua create mode 100644 src/BulletMultiThreaded/CMakeLists.txt create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h create mode 100644 src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h create mode 100644 src/BulletMultiThreaded/HeapManager.h create mode 100644 src/BulletMultiThreaded/Makefile.original create mode 100644 src/BulletMultiThreaded/PlatformDefinitions.h create mode 100644 src/BulletMultiThreaded/PosixThreadSupport.cpp create mode 100644 src/BulletMultiThreaded/PosixThreadSupport.h create mode 100644 src/BulletMultiThreaded/PpuAddressSpace.h create mode 100644 src/BulletMultiThreaded/SequentialThreadSupport.cpp create mode 100644 src/BulletMultiThreaded/SequentialThreadSupport.h create mode 100644 src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp create mode 100644 src/BulletMultiThreaded/SpuCollisionObjectWrapper.h create mode 100644 src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp create mode 100644 src/BulletMultiThreaded/SpuCollisionTaskProcess.h create mode 100644 src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp create mode 100644 src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h create mode 100644 src/BulletMultiThreaded/SpuDoubleBuffer.h create mode 100644 src/BulletMultiThreaded/SpuFakeDma.cpp create mode 100644 src/BulletMultiThreaded/SpuFakeDma.h create mode 100644 src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp create mode 100644 src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h create mode 100644 src/BulletMultiThreaded/SpuLibspe2Support.cpp create mode 100644 src/BulletMultiThreaded/SpuLibspe2Support.h create mode 100644 src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h create mode 100644 src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp create mode 100644 src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h create mode 100644 src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp create mode 100644 src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h create mode 100644 src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h create mode 100644 src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp create mode 100644 src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h create mode 100644 src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h create mode 100644 src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp create mode 100644 src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h create mode 100644 src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h create mode 100644 src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp create mode 100644 src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h create mode 100644 src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt create mode 100644 src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp create mode 100644 src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h create mode 100644 src/BulletMultiThreaded/SpuSampleTask/readme.txt create mode 100644 src/BulletMultiThreaded/SpuSampleTaskProcess.cpp create mode 100644 src/BulletMultiThreaded/SpuSampleTaskProcess.h create mode 100644 src/BulletMultiThreaded/SpuSync.h create mode 100644 src/BulletMultiThreaded/TrbDynBody.h create mode 100644 src/BulletMultiThreaded/TrbStateVec.h create mode 100644 src/BulletMultiThreaded/Win32ThreadSupport.cpp create mode 100644 src/BulletMultiThreaded/Win32ThreadSupport.h create mode 100644 src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp create mode 100644 src/BulletMultiThreaded/btGpu3DGridBroadphase.h create mode 100644 src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h create mode 100644 src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h create mode 100644 src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h create mode 100644 src/BulletMultiThreaded/btGpuDefines.h create mode 100644 src/BulletMultiThreaded/btGpuUtilsSharedCode.h create mode 100644 src/BulletMultiThreaded/btGpuUtilsSharedDefs.h create mode 100644 src/BulletMultiThreaded/btParallelConstraintSolver.cpp create mode 100644 src/BulletMultiThreaded/btParallelConstraintSolver.h create mode 100644 src/BulletMultiThreaded/btThreadSupportInterface.cpp create mode 100644 src/BulletMultiThreaded/btThreadSupportInterface.h create mode 100644 src/BulletMultiThreaded/vectormath2bullet.h create mode 100644 src/BulletSoftBody/CMakeLists.txt create mode 100644 src/BulletSoftBody/btDefaultSoftBodySolver.cpp create mode 100644 src/BulletSoftBody/btDefaultSoftBodySolver.h create mode 100644 src/BulletSoftBody/btSoftBody.cpp create mode 100644 src/BulletSoftBody/btSoftBody.h create mode 100644 src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp create mode 100644 src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h create mode 100644 src/BulletSoftBody/btSoftBodyData.h create mode 100644 src/BulletSoftBody/btSoftBodyHelpers.cpp create mode 100644 src/BulletSoftBody/btSoftBodyHelpers.h create mode 100644 src/BulletSoftBody/btSoftBodyInternals.h create mode 100644 src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp create mode 100644 src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h create mode 100644 src/BulletSoftBody/btSoftBodySolverVertexBuffer.h create mode 100644 src/BulletSoftBody/btSoftBodySolvers.h create mode 100644 src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp create mode 100644 src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h create mode 100644 src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp create mode 100644 src/BulletSoftBody/btSoftRigidDynamicsWorld.h create mode 100644 src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp create mode 100644 src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h create mode 100644 src/BulletSoftBody/btSparseSDF.h create mode 100644 src/BulletSoftBody/premake4.lua create mode 100644 src/CMakeLists.txt create mode 100644 src/LinearMath/CMakeLists.txt create mode 100644 src/LinearMath/btAabbUtil2.h create mode 100644 src/LinearMath/btAlignedAllocator.cpp create mode 100644 src/LinearMath/btAlignedAllocator.h create mode 100644 src/LinearMath/btAlignedObjectArray.h create mode 100644 src/LinearMath/btConvexHull.cpp create mode 100644 src/LinearMath/btConvexHull.h create mode 100644 src/LinearMath/btConvexHullComputer.cpp create mode 100644 src/LinearMath/btConvexHullComputer.h create mode 100644 src/LinearMath/btDefaultMotionState.h create mode 100644 src/LinearMath/btGeometryUtil.cpp create mode 100644 src/LinearMath/btGeometryUtil.h create mode 100644 src/LinearMath/btGrahamScan2dConvexHull.h create mode 100644 src/LinearMath/btHashMap.h create mode 100644 src/LinearMath/btIDebugDraw.h create mode 100644 src/LinearMath/btList.h create mode 100644 src/LinearMath/btMatrix3x3.h create mode 100644 src/LinearMath/btMinMax.h create mode 100644 src/LinearMath/btMotionState.h create mode 100755 src/LinearMath/btPoolAllocator.h create mode 100644 src/LinearMath/btQuadWord.h create mode 100644 src/LinearMath/btQuaternion.h create mode 100644 src/LinearMath/btQuickprof.cpp create mode 100644 src/LinearMath/btQuickprof.h create mode 100644 src/LinearMath/btRandom.h create mode 100644 src/LinearMath/btScalar.h create mode 100644 src/LinearMath/btSerializer.cpp create mode 100644 src/LinearMath/btSerializer.h create mode 100644 src/LinearMath/btStackAlloc.h create mode 100644 src/LinearMath/btTransform.h create mode 100644 src/LinearMath/btTransformUtil.h create mode 100644 src/LinearMath/btVector3.h create mode 100644 src/LinearMath/ibmsdk/Makefile create mode 100644 src/LinearMath/premake4.lua create mode 100644 src/Makefile.am create mode 100644 src/MiniCL/CMakeLists.txt create mode 100644 src/MiniCL/MiniCL.cpp create mode 100644 src/MiniCL/MiniCLTask/MiniCLTask.cpp create mode 100644 src/MiniCL/MiniCLTask/MiniCLTask.h create mode 100644 src/MiniCL/MiniCLTaskScheduler.cpp create mode 100644 src/MiniCL/MiniCLTaskScheduler.h create mode 100644 src/MiniCL/cl.h create mode 100644 src/MiniCL/cl_MiniCL_Defs.h create mode 100644 src/MiniCL/cl_gl.h create mode 100644 src/MiniCL/cl_platform.h create mode 100644 src/btBulletCollisionCommon.h create mode 100644 src/btBulletDynamicsCommon.h create mode 100644 src/ibmsdk/Makefile create mode 100644 src/vectormath/scalar/boolInVec.h create mode 100644 src/vectormath/scalar/floatInVec.h create mode 100644 src/vectormath/scalar/mat_aos.h create mode 100644 src/vectormath/scalar/quat_aos.h create mode 100644 src/vectormath/scalar/vec_aos.h create mode 100644 src/vectormath/scalar/vectormath_aos.h create mode 100644 src/vectormath/sse/boolInVec.h create mode 100644 src/vectormath/sse/floatInVec.h create mode 100644 src/vectormath/sse/mat_aos.h create mode 100644 src/vectormath/sse/quat_aos.h create mode 100644 src/vectormath/sse/vec_aos.h create mode 100644 src/vectormath/sse/vecidx_aos.h create mode 100644 src/vectormath/sse/vectormath_aos.h create mode 100644 src/vectormath/vmInclude.h create mode 100644 test1.oec diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..f2cc86d --- /dev/null +++ b/AUTHORS @@ -0,0 +1,22 @@ + +Bullet Physics Library is an open source project with help from the community at the Physics Forum +See the forum at http://bulletphysics.com + +The project was started by Erwin Coumans + +Following people contributed to Bullet +(random order, please let us know on the forum if your name should be in this list) + +Gino van den Bergen: LinearMath classes +Christer Ericson: parts of the voronoi simplex solver +Simon Hobbs: 3d axis sweep and prune, Extras/SATCollision, separating axis theorem + SIMD code +Dirk Gregorius: generic D6 constraint +Erin Catto: accumulated impulse in sequential impulse +Nathanael Presson: EPA penetration depth calculation +Francisco Leon: GIMPACT Concave Concave collision +Joerg Henrichs: make buildsystem (work in progress) +Eric Sunshine: jam + msvcgen buildsystem +Steve Baker: GPU physics and general implementation improvements +Jay Lee: Double precision support +KleMiX, aka Vsevolod Klementjev, managed version, rewritten in C# for XNA +Erwin Coumans: most other source code diff --git a/BspDemo.bsp b/BspDemo.bsp new file mode 100644 index 0000000000000000000000000000000000000000..4ed414d75b92d4d94b05589c46bc8f66bee34686 GIT binary patch literal 105100 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 HQ-1y*qN~We literal 0 HcmV?d00001 diff --git a/BulletLicense.txt b/BulletLicense.txt new file mode 100644 index 0000000..2e5680a --- /dev/null +++ b/BulletLicense.txt @@ -0,0 +1,18 @@ +/* +Copyright (c) 2003-2010 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. +*/ + + +Free for commercial use, please report projects in the forum at http://www.bulletphysics.org + +In case you want to display a Bullet logo in your software: you can download the Bullet logo in various vector formats and high resolution at the download section in http://bullet.googlecode.com diff --git a/Bullet_User_Manual.pdf b/Bullet_User_Manual.pdf new file mode 100644 index 0000000000000000000000000000000000000000..596241732184044bf31e290be8b03a9269cc5a97 GIT binary patch literal 1168019 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 z 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

LtkUCCGFAJ2V;ZHSiDPL{5gxB&J_E7X8A7n zE*i4u<~ziOF#2%M*v7!F&{aSbr5w$07hTc6<_<0U%8Hg*M6tK|&e$0dw5w@70!S;M zL+iN39q?L#1?Q!MB}>&uKvu(pfT6i0J};x$59t7gm*-`>i%>BLc{zc84$hQGdzP-}Monm%ChT2&ah7xD4qe`fgUI zlm_lqAvVHzQPbw^kRwnFl$=pmJ0Vl(6!bzYzu*I+s`wu`NgD32uJI;^rQTU-KcIk+ zXx?zGWgdSOR4-lVXEd7EW-cP3sr$;D6}j%5jQ+ct$Ia_$x(i9~7l+L7S9IVtlz$lPx^xSk+J-hmzgF9xDVJe{f@!pW*w zTYcAthCeoatx}&~{?USc^}34u>cDs{0k`Z!?aUVFl=)q~8@a1*snOQK{AS??Y|UG- zDF36B3urD`rseA+J*$R{3N2>;*CTqpv`pqoICCU5m0*8h$~*%+NlL=1&?Er}NKDD^ z1!5|wLUrkp8jDcNtQ{{>Fq3Dg@-7Zd{cm?ZK>Fx=>44Lzs%cqA_@)kuCtFaLG$#Gd zk`9rL^tJs2vPp^uh|Sk2KW3|%14Z!jbVkFF0)rFFdCBi6_xoC@Yq8MHj91upFK%>_ zw5?f`v-Xb;xQNZ0s+&VM(Qd0HC|pItO9@AOeqy!Hu_}&4PH8WaRnN_4^HC<+ZvYLFV=P!d!XwTp^n51CSPWfse-V{hanWTBdBu z$)}zkvs;-aqhaX&N>k7-E^OIqBO+9D{r#ZdM=%ywu0Spgjmx3@-%$n(&pPsjuzXJa zy^Hq_*k)Yin=Xc^9c+!v7&W1BRUfdGuCw+!S4vEFoh0BFSbF^rgcEbQnHo?V#JXc< zaR#NHy>X7|$L)uR;8kv_HFHP4LC>52n0c#+E%FItjjCGvB{h3a)^-sa`l^gZbWYM( zc5e4sZn+N672Y|EcMs8brlLJ}MVvj-V zc}u&b@YKxvjLdW=9wAU`Lv_2f$hBT znQxpU|0xnHEUh2GyZ*-VOXO;&G%0nBZf-RlL33!aMDS+&u>d|tW^z9k0_SNSH2nnX zRYR}CzFF#}*H2)-Lpdv!(5k{W^T}KLVo~NK{dUQgC%X`r;#5cOs+8TJd4*@VEwo&w zcgn_OnSoxGD$%FV`V6#|M}ngvwGh=y%it*ahk^h%35@zfOG?Rlf;b0H$wM}YPnQ*a zCdopB@*1c%A&Qmr8K{CH7lf$ITyT-*$QKM-P97e*T+0sF=wP7TR4$2xbFtDFCjygT zpb**4W!8S>f;;&W+RVDQD|OSxqz3+uJm*q($t_q+Ywn@vXxbI_MhcDgPu%x5f_yU% z$wyn$rl@}p;wIQn!FeR~r@A^1vbWWScl%{aGo_>{2cg@YaiN-tzi@ULrcX69a%n?1 zYVD+UJGN+8GB3?;`!!6ED}&G-!1aypB?%TTM4>BbPvy)Qipvl}~(wML+AOsd~l z4W6qpH1_Jg@U>!$nsz*-e;s2|KwpXm@Z0lqC4RRDcN7yWi%tNp(f7Uq@gTgJs%Yqh zQZFrH{pKX+z}AReSeT)~i{tXvOjTET)JX9km@rOz#`}}%BftB%E@E`FPTL0!;kjFw!V_ST4O}_ROo^+<_l;{si#wOeb8nyHKK%a8km0j4E%*DK zWYJQuSmR{q2)YP6_b$=^g7t!SSM)s7@(S5VV0A0Z=plRj?XLiTx$V8UD+9VO$Nk+0 zI}rTe2#(oa5nnh0PFqtSzqV<$8pOr?Tc%S}^iXz3-+Zi>1y{Qw)5gCj=6dJJ8!8bg zr=~kj%{Kb#F|vrl!Jpex2B7#t%O4+$gmWFy$-0`rQyYDzNVC(5ZpO!hWu9LI%lu4^ zPc_!+_?=Ir6i!x$(%UZCgRfogA-(Or26P@op_xTL-g+9oVZ<(utRheP@cZ3_?@7a+ z&gYx*{P~uGBNsq=WiwYuu%@lQ9Rz!)Wav9A7Ue%e0bx zaNvrYF=d@mRg%7KAoPzf0%Ap8D#Kyt{HMA#RYzU=6AFlCq$H~8Rn>(DkG}um&S~ad z=ya8~FvzYAeKzJ^VhiE7u>fP4>%0-@S;(K=zr7>g0EU##=#jI{2 zd|^&(PcIFBJOaL+4waKY{8nTJnuj9?V5(`nGScgxQOFb<(M$l7{~i_Tfho!2A%gTM zA}Mp#VuCpBd>3o8gUt)1#kP=u6CzB_oRPvEABvzBAN z`fnPh55rJI949_!7^c4!W2>if%vyuNY9?<1V}Drm=YJ?+N;%)wxNtQU9^vdmDzwOr zn$ez=+|WiNmryDakyE^6Ak-w8v#*?LBdBsb1STSw(>AEo2xN4PtHSg z9oj<&(mpvMjG<0@Uw>%3>=EzDQNK%Rq&`rlQyA~I#8lHz44Sn5I3)M>PK zkn78K??q=$WyWl`j^v^GFybbU8(GrM5V>BoqyI`aVjMxoGVpEL0N$#&u0WV-M{uWV zhLxg)ID^INt*%@sZlTe9PfO#LWYBobyvVG{T7l#e-0L#c&FCWy;>ssT!Pn4%rsGJ( z1iKI4{hQaRPAh5!l`nGvH^segHd6cuoZT6)Rc9aop+7O2H(jI>7)O=j5k z37-y5T$lv`*RI2paL(GeUA~ej3E)t@Ra}2At5wt1^uYQBjf46^+Y9+kAI1p|Pt7EM z2E&AYf1KA{lNIU4_Mg4-BHC@zq>(dF_()DifliL|tu_kNb&5#HRyX-ei4Z4BSsuyE zOJb%QjSSzP;jBkTM+G_#1xfCWqJcpOEiHJdeM6)in{-a>+LRYki>9UEg?`u2q$h7!pmirz&nLAcZ+l3amY_4(d(hvjB~ zOXI+s$x}%OnC12uG zmA4|gy>Z1~Nk(&*t6a_Irb$4rgoH=WE9`PTu}5k(^SQzb+ZJ3%zcPXOI8fciwWQ;~ zc=o-$e8uZYiKZntL`CIl#pSR0=9xVm2QHQR&V(2l-gt}+^PU$n6vwOa?qZuNM5!vp zepQVZB|A?qH5wpY?|t?(>qYQ*<8&YG4LTt$l9Y~YM+d6CL85B zbA(Io+_)v8m;^4HQ1c53C_VTv{yA0+LGzTh+GRkn?U1ZSfGX@(d5B>#wQ2~45K^xP zObAxxaFoRrZj*On>(SVdFfDU$1LKk&H2uut`IfyPr7x{7$5gDBmJ3$e;#y2{qWKF% za%!emMVaZf&qB=h=Awce%V}`wfQaS)n%h zvg|qeV34VURcd_$x;+6J*++|<#09qN@&pkDb&V56zeLg)liGqM=XzA!bVuh}((uwV zTqm!grfn+Xe|LO<#@%f1IJ?8l+?t z!pz@ru{1QvG1z`IRjn#~-7D3X52NJaGMLYI*8C-WjyXdgDz&FvyXkrZSAy8!d`UbX zkz1U&qjQG1^<>ITL^R^2qAwcd8-%a5Pk+;B6N%eyQb<~x8zMsq5(nzs8_5zRg|f`3K+{p~)|4mle0-H44&J5{(b zbV<1d&jJz7fWIZT9<5AgCagaH(#6->78iJ~(PMfpVHjcPv-E53NHvB96cjuOWyDgZ zy2?ki0!tOXp?oTp4vA^CCGd;q+0gg(a_{}ZP8Yg=6mVU3lxyNY=hNq}MV{mtB`-Wg zQ92U(;Q`^zpQu<{*QyD1!Y!cm1b^{8^(X((&=A}-q_L}d!MRSlOC$1>3ZW=>Vd@ya zs5cMmX!kZBA$dN_*2G%vE?m)!v|Lmg3RZ%t9JE|0u%sx_vr*4#ygdV{#Opfce5WG= zJm_t?B&|)5e`{53XxW>R?+_PIj2q_Hf_!zA;%$ly=ajX|CT_NYm`6sj67BRW%jKFt|UV+1u=^NMA@Ay2Q=B zLA?^w^#yhyEcyqWJPA_-a7DfA%QID}Dl*TL+AQTOPJv^OLUd|nw5Q8?Ep~+KR7VUa z19+^@^GOFYyGHw10i}*)NvgcK7Oc}tulrKnI48@pOX6VFp|#SWICDiAVhrW1qL(L1 zN%aeZ&J)}bu~itMm8rtK}2@0tOOQcs2Uww}~; zzgpbc;;U&)UdVjslzRr4w4C^GuBVYMj36Dk-|?{kgFbW7O@~_lVK44aD2}k8;6XVh z0fhM@h$W*8jv1M((0WKsFmze8_{MF9{UqXkgR*r{weAO5)*4KZc}@7tObUWmteXR| z45p+lA}fG|+)lBjqRd=`&V7vW>VnLUFC1ZDbhUt`--Q;+RfHC*t9c(YGZbsUF(4{d z{FHJG@D2}ziPGqQt@@n9bxU&s?uzHhh&|G?HJO;LJ72z#I91*0dy{)~Y7H zPcB)}c7isg?^hJ4y_PP=9^ErJ>X_t$ppZ~KtEiw!xvs_|OM1_4HL48BrLt}2TPrIo z{Tdma^wDK}GBoovSYe!9_u51OQUtilbmoMEZEctsXfZ=7}cc}FI1!8YKE@b(??@H;WB6-$kRvVP6vGAS=Dh@dCl zdg)V0wM*$!8x3R1E|}edT~*2>pazPU3s+h|zobz2CajDg0I5p8cl*zEOGF*h?uujV zR-)evw~0`*>2zU-s0P7Xu8T03?IISb^_bb+jx5iQAeV~kAkX14*PO@P?&^n?2o0-B z;&yo(Bi0naOY7s+=+wTj@bo&$bH@z>dc;5??#w$+f(Nd{zSb{m-!c;_t?^eJ1vwU) zF4ai=#m_SO^Aj~MJQ{^>e7A7rVRDSh&G?|&dHr#A#M~|wBm`BB9?9DI&uT&$@vP4! zPb$)<%Zs|(o3sf$0s0x%h>);j-Ka~)ed#;PealH&!dP=H&rgQ9q_ zkr1sg=w|K7GiJNEJ}ua8H(d4GSop~A-Mh;T{^tXI-6M|kwcU=J6$X&9K~ZVC`zdXF zoaN;8idC@AQks4e{HDmU`WoK?5BP=N5#@&Dh zrd~+nY!w>kLQTeLRt;Rm`NW&^?1$EKMW!O#JLiZg27A&0~fn99xY$3F`>_xD= zTJd|v7MJ3m-$WmhFlVS)X6jvV?=QT;oUY~HQ2pG5;j1SY?H!|WyrnqPuBAA$CV~-o zYGwIgxvxnjY;pY4cA8Zd!PD*eI)>BoS`JHHZNDa1B7!a_k|cp(I_>|$djYh{eSkF! zg?qYzBqL6-D7!dF5B4?#Hp^|ebN30W7im4l6$+o}etIL~<)yl@aKBw?KV+USadQ)r zxZk}3|G;bX>3Y8?^K_{!2cGH}_P!B@_795OaEgSuyT%}@_P0h|x^)4Bo(E}CHbDYG(aOpiVW9zHx>*%WjwA5xh+xVl z^2E&BmD>NPPeg8i@AHX|kDlzguGPwL?nsy)B0^z{l7!kc_ub93m z7t}BG7Nx0|zgVahJ{w-oo8td5hFn%CSBf(Ttxk-|4(-{SFVGEvXy&=}#JUu|NSsgt z5@naG(BZ4zE9y`|10waM{O2DMacD}ovz!AP6m_7m5(o zf4%w|6%qO255nUza;$qRYkjOHIj2BAQ9a_4=k`Xf2Kh_Y4eM)ZJ=Ncp5i&8YIC!TA% z?|}(4UhpA|426)5zZm)^SCBN<|6uPe3GVJ5+}%A`aCfL;4!M2bd%OGJZ%@y3e|YCNAL`_k

%Ger)e&tuI}w6>S@oSxhSIT*6AwcifW;xCRfUA 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

X0u@yA=f6b4JN=lNp%hFwYE?lfVBw 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 z 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

    +81ejuOwdf{5)^F>~KTyJ7D`6GDL9SBLpsrx|) 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

  1. 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�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πP6Rikks$j;6-FY=wQ$Zln)lX!Y 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%0Ayh}o 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

    uZP{aL?~S@>F3253Exf%P5|8|17~EF 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

  2. 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 literal 0 HcmV?d00001 diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..59a753a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,378 @@ +cmake_minimum_required(VERSION 2.4.3) +set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) + +#this line has to appear before 'PROJECT' in order to be able to disable incremental linking +SET(MSVC_INCREMENTAL_DEFAULT ON) + +PROJECT(BULLET_PHYSICS) +SET(BULLET_VERSION 2.80) + +IF(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + + +IF (NOT CMAKE_BUILD_TYPE) +# SET(CMAKE_BUILD_TYPE "Debug") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF (NOT CMAKE_BUILD_TYPE) + +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG") +#MESSAGE("CMAKE_CXX_FLAGS_DEBUG="+${CMAKE_CXX_FLAGS_DEBUG}) + +OPTION(USE_DOUBLE_PRECISION "Use double precision" OFF) +OPTION(USE_GRAPHICAL_BENCHMARK "Use Graphical Benchmark" ON) +OPTION(USE_MULTITHREADED_BENCHMARK "Use Multithreaded Benchmark" OFF) + +IF (USE_MULTITHREADED_BENCHMARK) + ADD_DEFINITIONS(-DUSE_PARALLEL_SOLVER_BENCHMARK -DUSE_PARALLEL_DISPATCHER_BENCHMARK) +ENDIF() + +OPTION(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC Runtime Library DLL (/MD or /MDd)" OFF) +OPTION(USE_MSVC_INCREMENTAL_LINKING "Use MSVC Incremental Linking" OFF) + +OPTION(USE_CUSTOM_VECTOR_MATH "Use custom vectormath library" OFF) + +IF (USE_CUSTOM_VECTOR_MATH) + ADD_DEFINITIONS(-DUSE_SYSTEM_VECTORMATH) + IF(WIN32) + SET (VECTOR_MATH_INCLUDE ${BULLET_PHYSICS_SOURCE_DIR}/src/vectormath/sse CACHE PATH "Vector Math library include path.") + ELSE(WIN32) + SET (VECTOR_MATH_INCLUDE ${BULLET_PHYSICS_SOURCE_DIR}/src/vectormath/scalar CACHE PATH "Vector Math library include path.") + ENDIF(WIN32) +ENDIF(USE_CUSTOM_VECTOR_MATH) + +IF (MSVC) + FIND_PATH(DIRECTX_SDK_BASE_DIR Include/D3D11.h PATH $ENV{DXSDK_DIR} ) + IF(DIRECTX_SDK_BASE_DIR) + OPTION(USE_DX11 "Use DirectX 11" ON) + ELSE() + OPTION(USE_DX11 "Use DirectX 11" OFF) + ENDIF() +ENDIF(MSVC) + + +#SET(CMAKE_EXE_LINKER_FLAGS_INIT "/STACK:10000000 /INCREMENTAL:NO") +#SET(CMAKE_EXE_LINKER_FLAGS "/STACK:10000000 /INCREMENTAL:NO") + +#MESSAGE("MSVC_INCREMENTAL_YES_FLAG"+${MSVC_INCREMENTAL_YES_FLAG}) + + +IF(MSVC) + IF (NOT USE_MSVC_INCREMENTAL_LINKING) + #MESSAGE("MSVC_INCREMENTAL_DEFAULT"+${MSVC_INCREMENTAL_DEFAULT}) + SET( MSVC_INCREMENTAL_YES_FLAG "/INCREMENTAL:NO") + + STRING(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replacementFlags ${CMAKE_EXE_LINKER_FLAGS_DEBUG}) + SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "/INCREMENTAL:NO ${replacementFlags}" ) + MESSAGE("CMAKE_EXE_LINKER_FLAGS_DEBUG=${CMAKE_EXE_LINKER_FLAGS_DEBUG}") + +# STRING(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replacementFlags2 ${CMAKE_EXE_LINKER_FLAGS}) +# SET(CMAKE_EXE_LINKER_FLAGS ${replacementFlag2}) +# STRING(REPLACE "INCREMENTAL:YES" "" replacementFlags3 ${CMAKE_EXTRA_LINK_FLAGS}) +# SET(CMAKE_EXTRA_LINK_FLAGS ${replacementFlag3}) + + + STRING(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replacementFlags3 ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}) + SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO ${replacementFlags3}) + SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/INCREMENTAL:NO ${replacementFlags3}" ) + + ENDIF (NOT USE_MSVC_INCREMENTAL_LINKING) + + IF (NOT USE_MSVC_RUNTIME_LIBRARY_DLL) + #We statically link to reduce dependancies + FOREACH(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + IF(${flag_var} MATCHES "/MD") + STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + ENDIF(${flag_var} MATCHES "/MD") + IF(${flag_var} MATCHES "/MDd") + STRING(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}") + ENDIF(${flag_var} MATCHES "/MDd") + ENDFOREACH(flag_var) + ENDIF (NOT USE_MSVC_RUNTIME_LIBRARY_DLL) + + OPTION(USE_MSVC_SSE "Use MSVC /arch:sse option" ON) + IF (USE_MSVC_SSE) + ADD_DEFINITIONS(/arch:SSE) + ENDIF() + OPTION(USE_MSVC_FAST_FLOATINGPOINT "Use MSVC /fp:fast option" ON) + IF (USE_MSVC_FAST_FLOATINGPOINT) + ADD_DEFINITIONS(/fp:fast) + ENDIF() +ENDIF(MSVC) + + + +IF (WIN32) +OPTION(INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES "Create MSVC projectfiles that can be distributed" OFF) + +IF (INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + SET (LIBRARY_OUTPUT_PATH ${BULLET_PHYSICS_SOURCE_DIR}/lib CACHE PATH "Single output directory for building all libraries.") + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BULLET_PHYSICS_SOURCE_DIR}) + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${BULLET_PHYSICS_SOURCE_DIR}) + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${BULLET_PHYSICS_SOURCE_DIR}) + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${BULLET_PHYSICS_SOURCE_DIR}) + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${BULLET_PHYSICS_SOURCE_DIR}) +ELSE() + SET (LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib CACHE PATH "Single output directory for building all libraries.") +ENDIF() + + + +OPTION(INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES "Create MSVC projectfiles with relative paths" OFF) +OPTION(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES "Add MSVC postfix for executable names (_Debug)" OFF) + +SET(CMAKE_DEBUG_POSTFIX "_Debug" CACHE STRING "Adds a postfix for debug-built libraries.") +SET(CMAKE_MINSIZEREL_POSTFIX "_MinsizeRel" CACHE STRING "Adds a postfix for MinsizeRelease-built libraries.") +SET(CMAKE_RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo" CACHE STRING "Adds a postfix for ReleaseWithDebug-built libraries.") + + + +IF(MSVC) + FIND_PATH(AMD_OPENCL_BASE_DIR include/CL/cl.h PATH $ENV{ATISTREAMSDKROOT} $ENV{AMDAPPSDKROOT} ) + IF(AMD_OPENCL_BASE_DIR) + #AMD adds an extras slash at the end of the ATISTREAMSDKROOT variable + SET(AMD_OPENCL_INCLUDES ${AMD_OPENCL_BASE_DIR}/include ) + MESSAGE("AMD OPENCL SDK FOUND") + MESSAGE(${AMD_OPENCL_INCLUDES}) + IF (CMAKE_CL_64) + SET(CMAKE_ATISTREAMSDK_LIBPATH ${AMD_OPENCL_BASE_DIR}/lib/x86_64 ) + ELSE(CMAKE_CL_64) + SET(CMAKE_ATISTREAMSDK_LIBPATH ${AMD_OPENCL_BASE_DIR}/lib/x86 ) + ENDIF(CMAKE_CL_64) + OPTION(BUILD_AMD_OPENCL_DEMOS "Build OpenCL demos for AMD (GPU or CPU)" ON) + ELSE() + OPTION(BUILD_AMD_OPENCL_DEMOS "Build OpenCL demos for AMD (GPU or CPU)" OFF) + ENDIF() + + FIND_PATH(INTEL_OPENCL_BASE_DIR include/CL/cl.h PATH $ENV{INTELOCLSDKROOT} ) + IF(INTEL_OPENCL_BASE_DIR) + SET(INTEL_OPENCL_INCLUDES ${INTEL_OPENCL_BASE_DIR}/include ) + MESSAGE("INTEL OPENCL SDK FOUND") + MESSAGE(${INTEL_OPENCL_INCLUDES}) + IF (CMAKE_CL_64) + SET(CMAKE_INTELOCLSDK_LIBPATH ${INTEL_OPENCL_BASE_DIR}/lib/x64 ) + ELSE(CMAKE_CL_64) + SET(CMAKE_INTELOCLSDK_LIBPATH ${INTEL_OPENCL_BASE_DIR}/lib/x86 ) + ENDIF(CMAKE_CL_64) + SET(INTEL_OPENCL_LIBRARIES ${CMAKE_INTELOCLSDK_LIBPATH}/OpenCL.lib) + OPTION(BUILD_INTEL_OPENCL_DEMOS "Build OpenCL demos for Intel (CPU)" ON) + ELSE() + OPTION(BUILD_INTEL_OPENCL_DEMOS "Build OpenCL demos for Intel (CPU)" OFF) + ENDIF() + + FIND_PATH(NVIDIA_OPENCL_BASE_DIR include/CL/cl.h PATH $ENV{CUDA_PATH} ) + IF(NVIDIA_OPENCL_BASE_DIR) + SET(NVIDIA_OPENCL_INCLUDES ${NVIDIA_OPENCL_BASE_DIR}/include ) + MESSAGE("NVIDIA OPENCL SDK FOUND") + MESSAGE(${NVIDIA_OPENCL_INCLUDES}) + IF (CMAKE_CL_64) + SET(CMAKE_NVSDKCOMPUTE_LIBPATH ${NVIDIA_OPENCL_BASE_DIR}/lib/x64 ) + ELSE(CMAKE_CL_64) + SET(CMAKE_NVSDKCOMPUTE_LIBPATH ${NVIDIA_OPENCL_BASE_DIR}/lib/Win32 ) + ENDIF(CMAKE_CL_64) + SET(NVIDIA_OPENCL_LIBRARIES ${CMAKE_NVSDKCOMPUTE_LIBPATH}/OpenCL.lib) + + OPTION(BUILD_NVIDIA_OPENCL_DEMOS "Build OpenCL demos for NVidia (GPU)" ON) + ELSE() + OPTION(BUILD_NVIDIA_OPENCL_DEMOS "Build OpenCL demos for NVidia (GPU)" OFF) + ENDIF() +ENDIF() + + + +IF (INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES) +SET(CMAKE_SUPPRESS_REGENERATION 1) +SET(CMAKE_USE_RELATIVE_PATHS 1) +ENDIF(INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES) + +ENDIF (WIN32) + +IF (MSVC OR APPLE) + OPTION(BUILD_MINICL_OPENCL_DEMOS "Build OpenCL demos for MiniCL (Generic CPU)" ON) +ELSE() + OPTION(BUILD_MINICL_OPENCL_DEMOS "Build OpenCL demos for MiniCL (Generic CPU)" OFF) + + FIND_PATH(INTEL_OPENCL_INCLUDES CL/cl.h) + FIND_PATH(INTEL_OPENCL_ICD_CFG intelocl64.icd /etc/OpenCL/vendors) + FIND_LIBRARY(INTEL_OPENCL_LIBRARIES OpenCL PATH /usr/lib64) + IF (INTEL_OPENCL_INCLUDES AND INTEL_OPENCL_LIBRARIES AND INTEL_OPENCL_ICD_CFG) + MESSAGE("INTEL OPENCL SDK FOUND") + MESSAGE(${INTEL_OPENCL_LIBRARIES}) + OPTION(BUILD_INTEL_OPENCL_DEMOS "Build OpenCL demos for Intel (CPU)" ON) + ELSE () + MESSAGE("INTEL OPENCL NOT FOUND") + OPTION(BUILD_INTEL_OPENCL_DEMOS "Build OpenCL demos for Intel (CPU)" OFF) + ENDIF () + + FIND_PATH(NVIDIA_OPENCL_INCLUDES CL/cl.h) + FIND_PATH(NVIDIA_OPENCL_ICD_CFG nvidia.icd /etc/OpenCL/vendors) + FIND_LIBRARY(NVIDIA_OPENCL_LIBRARIES OpenCL PATH /usr/lib64 /usr/local/lib) + IF (NVIDIA_OPENCL_INCLUDES AND NVIDIA_OPENCL_LIBRARIES AND NVIDIA_OPENCL_ICD_CFG) + MESSAGE("NVidia OPENCL FOUND") + MESSAGE(${NVIDIA_OPENCL_LIBRARIES}) + OPTION(BUILD_NVIDIA_OPENCL_DEMOS "Build OpenCL demos for NVidia (GPU)" ON) + ELSE () + MESSAGE("NVidia OPENCL NOT FOUND") + OPTION(BUILD_NVIDIA_OPENCL_DEMOS "Build OpenCL demos for NVidia (GPU)" OFF) + ENDIF () + +ENDIF() + +OPTION(BUILD_CPU_DEMOS "Build original Bullet CPU demos" ON) + + + +OPTION(INTERNAL_UPDATE_SERIALIZATION_STRUCTURES "Internal update serialization structures" OFF) +IF (INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) +ADD_DEFINITIONS( -DBT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) +ENDIF (INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) + +IF (USE_DOUBLE_PRECISION) +ADD_DEFINITIONS( -DBT_USE_DOUBLE_PRECISION) +SET( BULLET_DOUBLE_DEF "-DBT_USE_DOUBLE_PRECISION") +ENDIF (USE_DOUBLE_PRECISION) + +IF(USE_GRAPHICAL_BENCHMARK) +ADD_DEFINITIONS( -DUSE_GRAPHICAL_BENCHMARK) +ENDIF (USE_GRAPHICAL_BENCHMARK) + +IF (WIN32) +OPTION(USE_GLUT "Use Glut" ON) +ADD_DEFINITIONS( -D_IRR_STATIC_LIB_ ) +ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) +ADD_DEFINITIONS( -D_CRT_SECURE_NO_DEPRECATE ) +ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) + +IF (USE_GLUT AND MSVC) + string (REPLACE "/D_WINDOWS" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) + remove_definitions(-D_WINDOWS ) +ENDIF() + + + +ELSE(WIN32) +OPTION(USE_GLUT "Use Glut" ON) +ENDIF(WIN32) + + +IF(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + + +# This is the shortcut to finding GLU, GLUT and OpenGL if they are properly installed on your system +# This should be the case. + +FIND_PACKAGE(OpenGL) +IF (OPENGL_FOUND) + MESSAGE("OPENGL FOUND") + MESSAGE(${OPENGL_LIBRARIES}) +ELSE (OPENGL_FOUND) + MESSAGE("OPENGL NOT FOUND") + SET(OPENGL_gl_LIBRARY opengl32) + SET(OPENGL_glu_LIBRARY glu32) +ENDIF (OPENGL_FOUND) + +# ADD_DEFINITIONS(-DBT_USE_FREEGLUT) + +FIND_PACKAGE(GLU) + +IF (USE_GLUT) + FIND_PACKAGE(GLUT) + IF (GLUT_FOUND) + MESSAGE("GLUT FOUND") + MESSAGE(${GLUT_glut_LIBRARY}) + ELSE (GLUT_FOUND) + IF (MINGW) + MESSAGE ("GLUT NOT FOUND not found, trying to use MINGW glut32") + SET(GLUT_glut_LIBRARY glut32) + #TODO add better GLUT detection for MinGW + SET(GLUT_FOUND TRUE) + ENDIF (MINGW) + IF (MSVC) + SET(GLUT_FOUND TRUE) + IF (CMAKE_CL_64) + message("Win64 using Glut/glut64.lib") + SET(GLUT_glut_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glut64.lib) + ELSE(CMAKE_CL_64) + message("Win32 using Glut/glut32.lib") + SET(GLUT_glut_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glut32.lib) + ENDIF (CMAKE_CL_64) + INCLUDE_DIRECTORIES(${BULLET_PHYSICS_SOURCE_DIR}/Glut) + ELSE() + MESSAGE("GLUT NOT FOUND") + ENDIF (MSVC) + ENDIF (GLUT_FOUND) + + IF(NOT WIN32) + # This is added for linux. This should always work if everything is installed and working fine. + INCLUDE_DIRECTORIES(/usr/include /usr/local/include) + ENDIF() +ENDIF(USE_GLUT) + + +OPTION(BUILD_DEMOS "Set when you want to build the demos" ON) +IF(BUILD_DEMOS) + IF(EXISTS ${BULLET_PHYSICS_SOURCE_DIR}/Demos AND IS_DIRECTORY ${BULLET_PHYSICS_SOURCE_DIR}/Demos) + SUBDIRS(Demos) + ENDIF() +ENDIF(BUILD_DEMOS) + +# "Demos_ps3") +IF (MSVC) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF(EXISTS ${BULLET_PHYSICS_SOURCE_DIR}/Demos_ps3 AND IS_DIRECTORY ${BULLET_PHYSICS_SOURCE_DIR}/Demos_ps3) + MESSAGE("Demos_ps3 found") + SUBDIRS(Demos_ps3) + ENDIF() + ENDIF() +ENDIF(MSVC) + + +OPTION(BUILD_EXTRAS "Set when you want to build the extras" ON) +IF(BUILD_EXTRAS) + SUBDIRS(Extras) +ENDIF(BUILD_EXTRAS) + +#Maya Dynamica plugin is moved to http://dynamica.googlecode.com + +SUBDIRS(src) + +IF("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles") + OPTION(INSTALL_LIBS "Set when you want to install libraries" ON) +ELSE() + IF(APPLE AND FRAMEWORK) + OPTION(INSTALL_LIBS "Set when you want to install libraries" ON) + ELSE() +#by default, don't enable the 'INSTALL' option for Xcode and MSVC projectfiles + OPTION(INSTALL_LIBS "Set when you want to install libraries" OFF) + ENDIF() +ENDIF() + +IF(INSTALL_LIBS) + SET (LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) + SET (LIB_DESTINATION "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE STRING "Library directory name") + ## the following are directories where stuff will be installed to + SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include/bullet/" CACHE PATH "The subdirectory to the header prefix") + SET(PKGCONFIG_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/pkgconfig/" CACHE STRING "Base directory for pkgconfig files") + IF(NOT WIN32) + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/bullet.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/bullet.pc @ONLY) + INSTALL( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/bullet.pc + DESTINATION + ${PKGCONFIG_INSTALL_PREFIX}) + ENDIF(NOT WIN32) +ENDIF(INSTALL_LIBS) + +#INSTALL of other files requires CMake 2.6 +IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + OPTION(INSTALL_EXTRA_LIBS "Set when you want extra libraries installed" OFF) +ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + +OPTION(BUILD_UNIT_TESTS "Build Unit Tests" OFF) + +IF (BUILD_UNIT_TESTS) + SUBDIRS(UnitTests) +ENDIF() diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..794842d --- /dev/null +++ b/COPYING @@ -0,0 +1,17 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2011 Erwin Coumans http://bulletphysics.org + +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. +*/ + +All files in the Bullet/src folder are under this Zlib license. +Files in the Extras and Demos folder may have a different license, see the respective files. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..24e4100 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,788 @@ +Bullet Continuous Collision Detection and Physics Library +Primary author and maintainer: Erwin Coumans + +This ChangeLog is incomplete, for an up-to-date list of all fixed issues see http://bullet.googlecode.com +using http://tinyurl.com/yabmjjj + +2011 September 15 + - Bullet 2.79 release, revision 2433 (mainly a bugfix release) + - Revert a change in 2.78 related to speculative contacts (it has undesired side effects) + - Use HACD Hierachical Approximate Convex Decomposition (thanks to Khaled Mammou and Sujeon Kim) + - Add Intel cmake-build support for OpenCL accelerated cloth/particle + - add premake4 build system support to autogenerate visual studio project files that can be shipped (see msvc folder) + - preliminary build support for Google NativeClient, using premake4 (see msvc folder) + + +2011 April 8 + - Bullet 2.78 release 2383 + - Added FractureDemo + - Added Separatinx Axis Test and Polyhedral Clipping support (See InternalEdgeDemo) + - Added speculative contacts as CCD response method (See CcdPhysicsDemo) + - OpenCL and DirectCompute cloth as basic support for capsule collision + +2010 September 7 + - autotools now uses CamelCase naming for libraries just like cmake: + libbulletdynamics -> libBulletDynamics, libbulletmath -> libLinearMath + +2010 July 21 + - Preparing for Bullet 2.77 release, around revision r2135 + - Added an OpenCL particle demo, running on NVidia, AMD and MiniCL + Thanks to NVidia for the original particle demo from their OpenCL SDK + - Added GPU deformable object solvers for OpenCL and DirectCompute, and a DirectX 11 cloth demo + Thanks to AMD + - Create a separate library for MiniCL, + MiniCL is a rudimentary OpenCL wrapper that allows to compile OpenCL kernels for multi-core CPU, using Win32 Threads or Posix + - Moved vectormath into Bullet/src, and added a SSE implementation + - Added a btParallelConstraintSolver, mainly for PlayStation 3 Cell SPUs (although it runs fine on CPU too) + +2010 March 6 + - Dynamica Maya plugin (and COLLADA support) is moved to http://dynamica.googlecode.com + +2010 February + - Bullet 2.76 release, revision 2010 + - support for the .bullet binary file format + - btInternalEdgeUtility to adjust unwanted collisions against internal triangle edges + - Improved Maya Dynamica plugin with better constraint authoring and .bullet file export + + +2009 September 17 + - Minor update to Bullet 2.75 release, revision 1776 + - Support for btConvex2dShape, check out Bullet/Demos/Box2dDemo + - Fixes in build systems + - Minor fix in btGjkPairDetector + - Initialize world transform for btCollisionShape in constructor + + +2009 September 6 + - Bullet 2.75 release + - Added SPH fluid simulation in Extras, not integrated with rigid body / soft body yet + Thanks to Rama Hoetzlein to make this contribution available under the ZLib license + - add special capsule-capsule collider code in btConvexConvexCollisionAlgorithm, to speed up capsule-ragdolls + - soft body improvement: faster building of bending constraints + - soft body improvement: allow to disable/enable cluster self-collision + - soft body fix: 'exploding' soft bodies when using cluster collision + - fix some degenerate cases in continuous convex cast, could impact ray cast/convex cast + Thanks to Jacob Langford for the report and reproduction cases, see http://code.google.com/p/bullet/issues/detail?id=250&can=1&start=200 + - re-enabled split impulse + - added btHinge2Constraint, btUniversalConstraint, btGeneric6DofSpringConstraint + - demonstrate 2D physics with 2D/3D object interaction + + +2008 December 2 + - Fix contact refresh issues with btCompoundShape, introduced with btDbvt acceleration structure in btCompoundCollisionAlgorithm + - Made btSequentialImpulseConstraintSolver 100% compatible with ODE quickstep + constraints can use 'solveConstraint' method or 'getInfo/getInfo2' + +2008 November 30 + - Add highly optimized SIMD branchless PGS/SI solver innerloop + +2008 November 12 + - Add compound shape export to BulletColladaConverter + Thanks to JamesH for the report: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=12&t=2840 + - Fix compiler build for Visual Studio 6 + Thanks to JoF for the report: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2841 + +2008 November 11 + - Add CProfileManager::dumpAll() to dump performance statistics to console using printf. + - Add support for interaction between btSoftBody and btCollisionObject/btGhostObject + +2008 November 8 + - Fix PosixThreadSupport + - Add improved btHeightfieldTerrainShape support and new Demos/TerrainDemo + Thanks to tomva, http://code.google.com/p/bullet/issues/detail?id=63&can=1 + - Moved kinematic character controller from Demos/CharacterDemo into src/BulletDynamics/Character/btKinematicCharacterController.cpp + +2008 November 6 + - reduced default memory pool allocation from 40Mb to 3Mb. This should be more suitable for all platforms, including iPhone + - improved CUDA broadphase + - IBM Cell SDK 3.x support, fix ibmsdk Makefiles + - improved CMake support with 'install' and 'framework option + +2008 November 4 + - add btAxisSweep::resetPool to avoid non-determinism due to shuffled linked list + Thanks to Ole for the contribution, + +2008 October 30 + - disabled btTriangleMesh duplicate search by default, it is extremely slow + - added Extras/IFF binary chunk serialization library as preparation for in-game native platform serialization (planned COLLADA DOM -> IFF converter) + +2008 October 20 + - added SCE Physics Effects box-box collision detection for SPU/BulletMultiThreaded version + See Bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp + Thanks to Sony Computer Entertainment Japan, SCEI for the contribution + +2008 October 17 + - Added btGhostObject support, this helps character controller, explosions, triggers and other local spatial queries + +2008 October 10 + - Moved aabb to btBroadphaseProxy, improves rayTest dramatically. Further raytest improvements using the broadphase acceleration structures are planned + - Moved BulletMultiThreaded from Extras to /src/BulletMultiThreaded for better integration + + +2008 October 3 + - Add support for autoconf automake + ./autogen.sh and ./configure will create both Makefile and Jamfile. CMake and autogenerated Visual Studio projectfiles remain supported too. + - Improved ColladaConverter: plane shape export, and callback for shape construction to allow deletion of memory + +2008 Sept 30 + - Improved Soft Body support, fixed issues related to soft body colliding against concave triangle meshes + - Shared more code between regular version and SPU/BulletMultiThreaded, in particular GJK/EPA + +2008 Sept 28 + - Fixed rotation issues in Dynamic Maya Plugin + +2008 Sept 11 + - Enable CCD motion clamping for btDiscreteDynamicsWorld, to avoid tunneling. A more advanced solution will be implemented in btContinuousDynamicsWorld. + +2008 Sept 7 + - Add btScaledBvhTriangleMeshShape, to allow re-use of btBvhTriangleMeshShape of different sizes, without copying of the BVH data. + +2008 Sept 5 + - Enabled Demos/ForkLiftDemo + Thanks Roman Ponomarev. + +2008 Sept 4 + - Added btCudaBroadphase in Extras/CUDA: some research into accelerating Bullet using CUDA. + Thanks to the particle demo from the NVidia CUDA SDK. + +2008 Sept 3 + - Several bug fixes and contributions related to inertia tensor, memory leaks etc. + Thanks to Ole K. + +2008 Sept 1 + - Updated CDTestFramework, with latest version of OPCODE Array SAP. See Extras/CDTestFramework + Thanks to Pierre Terdiman for the update + +2008 August 25 + - Walt Disney Studios contributes their in-house Maya Plugin for simulating Bullet physics, with options for other engines such as PhysBam or PhysX. + Thanks to Nicola Candussi and Arthur Shek + +2008 August 14 + - Improved performance for btDbvtBroadphase, based on dual dynamic AABB trees (one for static, one for dynamic objects, where objects can move from one to the other tree) + Thanks to Nathanael Presson again, for all his work. + +2008 July 31 + - Added Havok .hkx to COLLADA Physics .dae converter patch+information + - Fix btSubsimplexConvexCast + Thanks to Nacho, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2422) + - Fix in rendering, GL_STENCIL + - btTriangleIndexVertexArray indices should be unsigned int/unsigned short int, + - Made InternalProcessAllTriangles virtual, thanks to + Both thank to Fullmetalcoder, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2401 + - clamp impulse for btPoint2PointConstraint + Thanks to Martijn Reuvers, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2418 + - Free memory of bvh, pass in scaling factor (optional) + Thanks to Roy Eltham, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2375 + +2008 July 27 + +btDbvtBroadphase: + - Fixed a performance issues reported by 'reltham' + - Added btDbvtBroadphase::optimize() for people who want good performances right +away or don't do dynamics. + - fixed compilation issues when DBVT_BP_PROFILE was set. +btSoftBody: + - Fixed singular matrix issues related to polar decomposition (flat meshes). +DemoApplication: + - Shadows (enable/disable through 'g' or DemoApplication::setShadows(bool)). + - Texture can be enable/disable through 'u' +CDFramework: + - fixed compilation issues. + All thanks to Nathanael Presson + +2008 July 10 + - Added btMultimaterialTriangleMeshShape and MultiMaterialDemo + Thanks to Alex Silverman for the contribution + +2008 June 30 + - Added initial support for kinematic character controller + Thanks to John McCutchan + +2008 April 14 + - Added ray cast support for Soft Bodies + Thanks to Nathanael Presson for the contribution + +2008 April 9 + - Cleanup of Stan Melax ConvexHull, removed Extras/ConvexHull, moved sources into LinearMath/BulletCollision + +2008 April 4 + - Added btSliderConstraint and demo + Thanks Roman Ponomarev + +2008 April 3 + - Fixed btMinkowskiSumShape, and added hitpoint to btSubsimplexConvexCast + +2008 April 2 + - Added Extras/CdTestFrameWork + Thanks Pierre Terdiman + +2008 April 1 + - Added posix thread (pthread) support + Thanks Enrico + +2008 March 30 + - Added Soft Body, cloth, rope and deformable volumes, including demos and interaction + Thanks Nathanael Presson for this great contribution + + 2008 March 17 + - Improved BulletColladaConverter + Thanks John McCutchan + +2008 March 15 + - btMultiSapBroadphase in a working state. Needs more optimizations to be fully useable. + - Allow btOptimizedBvh to be used for arbitrary objects, not just triangles + - added quicksort to btAlignedObjectArray + - removed btTypedUserInfo, added btHashMap + +2008 March 30 + - Moved quickstep solver and boxbox into Bullet/src folder + Thanks Russell L. Smith for permission to redistribute Open Dynamics Engine quickstep and box-box under the ZLib license + +2008 Feb 27 + - Added initial version for Character Control Demo + - Applied fixes to IBM Cell SDK 3.0 build makefiles + Thanks Jochen and mojo for reporting/providing patch: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1922 + +2008 Feb 8 + - Bugfixes in ConvexCast support against the world. + Thanks to Isgmasa for reporting/providing fix: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1823 + +2008 Feb 6 + - Added btCapsuleShapeX and btCapsuleShapeZ for capsules around X and Z axis (default capsule is around Y) + +2008 Feb 3 + - Added btTypedUserInfo, useful for serialization + +2008 Jan 31 + - Add support for 16 and 32-bit indices for SPU / BulletMultiThreaded version. + +2008 Jan 29 + - Added COLLADA Physics export/serialization/snapshot from any Bullet btDynamicsWorld. Saving the physics world into a text .xml file is useful for debugging etc. + +2008 Jan 23 + - Added Stan Melax Convex Hull utility library in Extras/ConvexHull. This is useful to render non-polyhedral convex objects, and to simplify convex polyhedra. + +2008 Jan 14 + - Add support for batch raycasting on SPU / BulletMultiThreaded + +2007 Dec 16 + - Added btRigidBodyConstructionInfo, to make it easier to set individual setting (and leave other untouched) during rigid body construction. + Thanks Vangelis Kokkevis for pointing this out. + - Fixed memoryleak in the ConstraintDemo and Raytracer demo. + - Fixed issue with clearing forces/gravity at the end of the stepSimulation, instead of during internalSingleStepSimulation. + Thanks chunky for pointing this out: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1780 + - Disabled additional damping in rigid body by default, but enable it in most demos. Set btRigidBodyConstructionInfo m_additionalDamping to true to enable this. + - Removed obsolete QUICKPROF BEGIN/END_PROFILE, and enabled BT_PROFILE. Profiling is enabled by default (see Bullet/Demos/OpenGL/DemoApplication.cpp how to use this). + User can switch off profiling by enabling define BT_NO_PROFILE in Bullet/src/btQuickprof.h. + +2007 Dec 14 + - Added Hello World and BulletMultiThreaded demos + - Add portable version of BulletMultiThreaded, through SequentialThreadSupport (non-parallel but sharing the same code-path) + - Add Cmake support for AllBulletDemos + + +2007 Dec 11 + - Moved the 'btRigidBody::clearForce' to the end of the stepSimulation, instead of in each substep. + See discussion http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1601 + - Added btConvexPlaneCollisionAlgorithm, makes planes perform better, and prevents tunneling + Thanks Andy O'Neil for reporting the performance/functionality issue + - Fixes for IBM Cell SDK 3.0 + Thanks to Jochen Roth for the patch. + +2007 Dec 10 + - Fixes in btHeightfieldTerrainShape + Thanks to Jay Lee for the patch. + +2007 Dec 9 + - Only update aabb of active objects + Thanks Peter Tchernev for reporting (http://bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1764 ) + - Added workaround to compile libxml under Visual Studio 2008 Beta 2 + - Make glui compile under MSVC 9.0 beta (vsnprintf is already defined) + +2007 Dec 6 + - Added DynamicControlDemo, showing dynamic control through constraint motors + Thanks to Eddy Boxerman + - Add support for generic concave shapes for convex cast. + - Added convex cast query to collision world. + - Added workaround for OpenGL bug in Mac OS X 10.5.0 (Leopard) + - Added concave raycast demo + All above thanks to John McCutchan (JMC) + - Fixed issues that prevent Linux version to compile. + Thanks to Enrico for reporting and patch, see + - Fixed misleading name 'numTriangleIndices' into 'numTriangles' + Thanks Sean Tasker for reporting: + +2007 Nov 28: + - Added raycast against trianglemesh. Will be extended to object cast soon. + Thanks John McCutchan (JMC) + - make getNumPoints const correct, add const getPoints(). + Thanks Dirk Gregorius + - Bugfix: allow btCollisionObjects (non-btRigidBody) to interact properly with btRigidBody for cache-friendly btSequentialImpulseConstraintSolver. + Thanks Andy O'Neil for pointing this out. + - Bugfix: don't fail if spheres have identical center, use arbitrary separating normal (1,0,0) + Thanks Sean Tasker for reporting! http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1681 + + +2007, November 20 + - Added hierarchical profiling + - Fixed memory leak in btMultiSapBroadphase, + - Fixed hash function (typo, should use 2 proxies) + Thanks to Stephen (shatcher) for reporting and fixes! http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1696 + +2007 Nov 11 + - Fixed parallel solver (BulletMultiThreaded) friction issue + - Terminate Win32 Threads when closing the CcdPhysicsDemo (when USE_PARALLEL_SOLVER/USE_PARALLEL_DISPATCHER is defined) + +2007 Nov 6 + - Added support for 16-bit indices for triangle meshes + - Added support for multiple mesh parts using btBvhTriangleMeshShape. + Thanks to Tim Johansson + +2007 Oct 22 + - All memory allocations go through btAlignedAlloc/btAlignedFree. User can override this to verify memory leaks + - added a few more demos to AllBulletDemos + - fix for one of the constructors of btHingeConstraint + Thanks Marcus Hennix + +2007 Oct 20 + - included glui, a GLUT/OpenGL based toolkit for some graphical user elements + Removed dynamic_cast from glui, to allow linkage without rtti + - added Box2D framework using glui, allowing all demos to run within one executable + Thanks Erin Catto for the FrameWork skeleton (http://www.box2d.org) + +2007 Ocy 17 + - Allow user to pass in their own memory (stack and pool) allocators, through collisionConfiguration. See demos how to use this + +2007 Oct 14 + - Included working version of Cell SPU parallel optimized version for Libspe2 SPU task scheduler. + This version compiles and runs on Playstation 3 Linux and IBM CellBlade, see BulletSpuOptimized.pdf for build instructions + (Official Playstation 3 developers can request a SPURS version through Sony PS3 Devnet.) + Thanks to IBM 'Extreme Blue' project for the contribution + http://www-913.ibm.com/employment/us/extremeblue/ + Thanks Minh Cuong Tran, Benjamin Hoeferlin, Frederick Roth and Martina Huellmann + for various contributions to get this initial Libspe2 parallel version up and running. + +2007 Oct 13 + - made 'btCollisionShape::calculateLocalInertia' const + Thanks to cgripeos, see http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1514 + - applied a large patch to remove warnings + Thanks to Enrico, see http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1568 + - removed SSE includes, added #incude for memset in Extras/quickstep, thanks Eternl Knight + +2007 Oct 11 + - added Hashed Overlapping Pair Cache, recommended by Pierre Terdiman. It works like a charm, thanks Pierre and Erin Catto (code from Box2D) + - modified some margins inside btBoxShape, btCylinderShape and btSphereShape + - added cone debug rendering (for cones with x, y and z up-axis) + - added improvements for optional Extra/quickstep, thanks to Remotion + - some performance improvements for Bullet constraint solver + +2007 Sept 28 + - upgraded GIMPACT to version 0.3 + Thanks to Francisco Leon + +2007 Sept 27 + - added contribution from IBM Extreme Blue project for Libspe2 support. This allow to execute BulletMultiThreaded on Cell SPU under PS3 Linux and Cell Blade. See http://www-913.ibm.com/employment/us/extremeblue + Thanks to Minh Cuong Tran, Frederick Roth, Martina Heullmann and Benjamin Hoeferlin. + +2007 Sept 13 + - Improved btGenericD6Constraint. It can be used to create ragdolls (similar to the new btConeTwistConstraint). See GenericJointDemo + - Added support for Bullet constraints in the optional Extras/quickstep ODE solver. See CcdPhysicsDemo, enable #COMPARE_WITH_QUICKSTEP and add libquickstep to the dependencies. + For both patches/improvements thanks Francisco Leon/projectileman + +2007 Sept 10 + - removed union from btQuadWordStorage, it caused issues under certain version of gcc/Linux + +2007 Sept 10 + - Reverted constraint solver, due to some issues. Need to review the recent memory allocation changes. + - Fixed issue with kinematic objects rotating at low speed: quaternion was de-normalized, passing value > 1 into acosf returns #IND00 invalid values + - 16 byte memory alignment for BVH serialization + - memory cleanup for btPoolAllocator + +2007 Sept 9 + - Added serialization for BVH/btBvhTriangleMeshShape, including endian swapping. See ConcaveDemo for an example. + Thanks to Phil Knight for the contribution. + - Fixed issues related to stack allocator/compound collision algorithm + Thanks Proctoid, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=18&t=1460 + - Increase some default memory pool settings, and added a fallback for the constraints solver to use heap memory + - Removed accidential testing code in btScalar.h related to operator new. + - Enable btAxis3Sweep and bt32BitAxis3Sweep to be linked in at the same time, using template + +2007 Sept 7 + - Replaced several dynamic memory allocations by stack allocation and pool allocations + - Added branch-free quantized aabb bounding box overlap check, works better on Playstation 3 and XBox 360 + Thanks to Phil Knight. Also see www.cellperformance.com for related articles + - Collision algorithms and settings for the memory/stack allocator can be done using btDefaultCollisionConfiguration + This is an API change. See demos how to modify existing implementations with a one-liner. + - Register several collision algorithms by default (sphere-sphere, sphere-box, sphere-triangle) + - Use other traveral method for BVH by default, this improves triangle mesh collision performance. + +2007 Aug 31 + - fixed MSVC 6 build + Thanks Proctoid, http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1375 + - fixed double precision build issues + Thanks Alex Silverman, http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1434 + +2007 Aug 24 + - fixed bug in btMatrix3x3::transposeTimes(const btMatrix3x3& m) const. Luckily it wasn't used in core parts of the library (yet). + Thanks to Jay Lee + +2007 Aug 15 + - fixed bug in Extras/GIMPACT 0.2 related to moving triangle meshes + Thanks Thomas, http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1368 + +2007 Aug 14 + - added parallel constraint solver. Works on Playstation 3 Cell SPU and multi core (Win Threads on PC and XBox 360). + See Extras/BulletMultiThreaded for SpuSolverTask subfolder and SpuParallelSolver.cpp + Thanks Marten Svanfeldt (Starbreeze Studios) + - fixed some bugs related to parallel collision detection (Extras/BulletMultiThreaded) + Thanks Marten Svanfeldt (Starbreeze Studios) + +2007 Aug 2 + - added compound and concave-convex (swapped) case for BulletMultiThreaded collision detection, thanks to Marten Svanfeldt + - refactored broadphase and overlapping pair cache. This allows performance improvement by combining multiple broadphases. This helps add/remove of large batches of objects and large worlds. See also Pierre Terdiman forum topic: + http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329 + + +2007 July 27 + - added Ragdoll Demo + Thanks to Marten Svanfeldt (Starbreeze Studios) + + - added Vector Math library for SIMD 3D graphics linear algebra (vector, matrix, quaternion) + See Bullet/Extras/vectormathlibrary + Supports SIMD SSE, PowerPC PPU and Cell SPU (including PS3 Linux and CellBlade), as well as generic portable scalar version + Will be used to improve BulletMultiThreaded performance + Open Sourced by Sony Computer Entertainment Inc. under the new BSD license + - added SIMD math library + 4-way SIMD for common math functions like atan2f4, cosf4, floorf4, fabsf4, rsqrtf4 etc. Used by Vector Math library under PPU and SPU. + Supports PowerPC (PPU) and Cell SPU, including PS3 Linux and CellBlade. + See Bullet/Extras/simdmathlibrary + Open sourced by Sony Computer Entertainment Inc. under the new BSD license + + +2007 July 25 + - added several patches: per-rigidbody sleeping threshold. added Assert to prevent deletion of rigidbody while constraints are still pointing at it + Thanks to Marten Svanfeldt (Starbreeze Studios) + +2007 July 13 + - fixed relative #include paths again. We can't use "../" relative paths: some compilers choke on it (it causes extreme long paths) + Within the libraries, we always need to start with "BulletCollision/" or "BulletDynamics/ or "LinearMath/" + +2007 July 10 + - Updated Bullet User Manual + +2007 July 5 + - added btConeTwistConstraint, especially useful for ragdolls. See Demos/RagdollDemo + Thanks to Marten Svanfeldt (Starbreeze Studios) + +2007 June 29 + - btHeightfieldTerrainShape: Added heightfield support, with customizations + - Upgraded to GIMPACT 0.2, see Extras/GIMPACT and MovingConcaveDemo + - Several patches from Marten Svanfeldt (Starbreeze Studios) + Improved collision filtering (in broadphase and rigidbody) + Improved debug rendering + Allow to set collision filter group/mask in addRigidBody + + +2007 June 15 + - Changed btAlignedObjectArray to call copy constructor/replacement new for duplication, rather then assignment operator (operator=). + +2007 June 11 + - Added multi-threading. Originally for Playstation 3 Cell SPU, but the same code can run using Win32 Threads using fake DMA transfers (memcpy) + Libspe2 support for Cell Blade / PS3 Linux is upcoming + See Extras/BulletMultiThreaded. Usage: replace btCollisionDispatcher by btSpuGatheringCollisionDispatcher + + - Added managed Bullet library, entirely rewritten in C# for Windows and XBox 360 XNA + See Extras/BulletX + Thanks to KleMiX, aka Vsevolod Klementjev + +2007 May 31 + - sign-bit went wrong in case of 32-bit broadphase, causing quantization problems. + Thanks DevO for reporting. + +2007 May 23 + - Fixed quantization problem for planar triangle meshes in btOptimizedBvh + Thanks Phil Knight for reporting and helping to fix this bug. + +2007 May 20 + - btAxisSweep3: Fixed a bug in btAxisSweep3 (sweep and prune) related to object removal. Only showed up when at least one btStaticPlaneShape was inserted. + Thanks tbp for more details on reproducing case. + - btAxisSweep3: Fixed issue with full 32bit precision btAxisSweep3 (define BP_USE_FIXEDPOINT_INT_32), it used only 0xffff/65536 for quantization instead of full integer space (0xffffffff) + - btRaycastVehicle: Added 'getForwardVector' and getCurrentSpeedKmHour utility functions + - Fixed local scaling issues (btConvexTriangleMeshShape, btBvhTriangleMeshShape, removed scaling from btMatrix3x3). + Thanks Volker for reporting! + - Added second filename search, so that starting BspDemo and ConvexDecompositionDemo from within Visual Studio (without setting the starting path) still works + +2007 April 22 + - Added braking functionality to btRaycastVehicle + - Removed tons of warnings, under MSVC 2005 compilation in -W4 + +2007 March 21 + - Fixed issues: comma at end of enum causes errors for some compilers + - Fixed initialization bug in LocalRayResult ( m_localShapeInfo(localShapeInfo) ) + +2007 March 20 + - Added refit tree to quantized stackless tree, and updated ConcaveDemo as example. + +2007 March 17 + - Added constraint solver optimizations, avoiding cross products during iterations, and gather rigidbody/constraint info in contiguous memory (btSolverBody/btSolverConstraint) + - These optimizations don't give large benefit yet, but it has good potential. Turned on by default. Can be switched off using solver->setSolverMode(SOLVER_RANDMIZE_ORDER). + - Enabled anti-jitter for rigid bodies. This is experimental, and can be switched off by setting a global (it is experimental so no proper interface) gJitterVelocityDampingFactor = 1.0; + - Fixed bug in islandmanifold.heapSort(btPersistentManifoldSortPredicate()); , thanks Noehrgel for reporting this (affected Sun Solaris) + +2007 March 12 + - Added compile-time toggle between on 16-bit and 32-bit fixed-point SAP broadphase. + This allows the number of bodies to exceed 32767 + - Enable useQuantizedAabbCompression on btTriangleMesh, see ColladaDemo + +2007 March 8 + - Fixed bug in constraint/island sorting (caused by replacing STL by dedicated btAlignedObjectArray with heapSort) + Thanks Clemens Unterkofler for pointing this out! + +2007 March 6 + - removed STL from the Bullet library: replace std::vector by btAlignedObjectArray. Also removed the std::set for overlapping pair set, and turned it into an overlapping pair array. The SAP only adds objects, never removed. Removal is postponed for during traversal of overlapping pairs (duplicates and non-overlapping pairs are removed during that traversal). + - added heap sort and binary search/linear search to btAlignedObjectArray + - fixed wrong cast, thanks Hamstray, http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1015 + + +2007 Feb 25 + - Improved performance of convex collision shapes, cache local AABB instead of recomputation. This fixes issue with very slow performance in larger .bsp levels + +2007 Feb 24 + - Added compressed/quantized AABB tree, 16 bytes per node, while supporting 32-bit (triangle) indices. + Should be faster and smaller then original version (quantized aabb check is done in integer space) + Original aabb tree nodes are still supported. They are 44 bytes, with full floating point precision and additional subPart index. + - added meter-unit scaling support in ColladaConverter.cpp + +2007 Feb 21 + - Build system: updated bullet.pc.in library names + - Updated EPA comparison integration (missing parameter) + +2007 Jan 04 + - fixed optimized AABB tree building: in some cases the tree building fails due to unbalanced trees, which generated stack overflow + +2006 Dec 15 + - added contribution to allow double precision collision detection/dynamics. Define BT_USE_DOUBLE_PRECISION in your project and libraries that include Bullet + +2006 Dec 14 + - merged contact and non-contact constraint solving into one loop, will improve stability of jointed bodies during collisions + - added first draft for hingeConstraint motor + +2006 Dec 8, Erwin Coumans + - preparation for SIMD: added btAlignedAllocator and btAlignedObjectArray, to replace stl std::vector, same interface, but compatible with 16 byte alignment + - cleaned up dependencies in autogenerated msvc projectfiles + - aligned btVector3 on 16 bytes boundary, under win32. see if developers will come up with problems + +2006 Dec 04, Erwin Coumans + Added btNearCallback. This is similar to Open Dynamics Engine (ODE) dNearCallback, but important differences: + - contact points are persistent (lifetime more then one frame, for warmstarting/incremental contact point management) + - continuous collision detection, time of impact + Added btRigidBody::isInWorld(), returns true if btRigidBody is inside a btCollisionWorld/btDynamicsWorld derived class + Added angularFactor to btRigidbody, this helps some character control (no angular impulse applied) + + +2006 Nov 28 + Moved StackAlloc from EPA into LinearMath/btStackAlloc + renamed internal class ConcaveShape into btConcaveShape + added btHeightfieldTerrainShape (not completed yet) + +2006 Nov 15 Nathanael Presson + Added EPA penetration depth algorithm, Expanding Polytope Algorithm + Added Pierre Terdiman penetration depth comparison/test DEMO + Fixed Bullet's Minkowski sampling penetration depth solver + Contributed by Nathanael Presson + +2006 Nov 11 Francisco León Nájera + Added GIMPACT trimesh collision detection: concave versus concave, + Contributed by Francisco León Nájera + +2006 Nov 2 + Minor refactoring: btCollisionObject changes from struct into class, added accessor methods + Force use of btMotionState to synchronize graphics transform, disabled old btRigidBody constructor that accepts btTransform + Renamed treshold into threshold throughout the code + +2006 Oct 30 + Enable decoupling of physics and graphics framerate using interpolation and internal fixed timestep, based on btMotionState + Enabled raycast vehicle demo (still needs tuning) + Refresh contact points, even when they are already persistent. + Fixed debugDraw colors (thanks pc0de for reporting) + Use Dispatcher in ConcaveConvexCollisionAlgorithm (so it uses the registered collision algorithm, not hardcoded convexconcave) + Improved performance of constraint solver by precalculating the cross product/impulse arm + Added collision comparison code: ODE box-box, also sphere-triangle + Added safety check into GJK, and an assert for AABB's that are very large + Fixed kinematic support (deriving velocities for animated objects) + Updated comparison/optional quickstep solver in Extras + UserCollisionAlgorithm demonstrates btTriangleMesh usage (easier trimesh compared to index array version) + Removed scaling from btTransform (we only want to deal with rigid transforms) + +2006 Oct 4 + Fixed minor leak in btOptimizeBVH + Cleanup of btRigidBody construction + added getW() in btQuaternion + assert when setLinearVelocity is called on btRigidBody + renamed projectfile library from collada-dom to colladadom (to make VC6 happy) + +2006 Sept 27 + Big Refactoring: renamed and moved files, create a replacement for CcdPhysicsEnvironment/CcdPhysicsController. + All Bullet classes in LinearMath, BulletCollision and BulletDynamics start with bt, and methods start with lowercase. + Moved classes into src folder, which is the only include folder needed. + Added 2 headerfiles in src: btBulletCollisionCommon.h and btBulletDynamicsCommon.h + +2006 Sept 23 + Fixed 2 bugs, causing crashes when removing objects. Should do better unit-testing. UnionFind and 3D SAP were involved. + +2006 Sept 19 + Allow programmable friction and contact solver model. User can register their own functions for several interaction types. + Improved performance, and removed hardcoded maximum overlaps (switched from C-array to stl::set) + +2006 Sept 16 + Added Bullet 2.0 User Manual + Allow registration of custom user collision algorithms + +2006 Sept 10 + Started cleaning up demos + +2006 Sept 4 + Fixed concave collision bug (caused instability/missing collisions in meshes/compounds) + Fixed memoryleak in OptimizedBvh, added RayTestSingle to CollisionWorld + Prepared for VehicleDemo + Increased Performance (island generation for sleeping objects took too much time) + Better COLLADA 1.4.1 physics conformance in ColladaDemo + +2006 August 11 + Added Quake BspDemo + Improved CCD for compound and non-convex objects + +2006 August 10 + Added per-triangle material (friction/restitution) support for non-convex meshes. See ConcaveDemo for usage. + +2006 August 9 + Added CMake support (see http://cmake.org) + This can autogenerate makefiles, projectfiles cross platform (including MacOS X Xcode ) + Just run cmake . in the root folder and it will autogenerate build files + +2006 July 26 Erwin Coumans + Upgraded to COLLADA-DOM 1.4.1, latest SVN version + ColladaDemo can export snapshots to .dae + +2006 July 24 Erwin Coumans + Added Compound CollisionShape support + (this is still low performance -> requires stackless tree-versus-tree traversal for better performance) + +2006 July 15 Erwin Coumans + Added initial support for Parallel execution (collision detection, constraint solving) + See ParallelPhysicsEnvironment in Extras\PhysicsInterface\CcdPhysics + +2006 July 10 Erwin Coumans + Added MacOS X support (some build issues mainly) + +2006 July 5 Erwin Coumans + Improved COLLADA 1.4 physics import, both COLLADA-DOM and FCollada + +2006 June 29 Erwin Coumans + Refactoring of the broadphase + Moved some optional files to Extras: Algebraic ccd and EPA, quickstep + Moved the limits on bodies/overlap to 32k and 65k + +2006 June 25 Erwin Coumans + Added basic Collision Filtering, during broadphase + Allow adding meshes to the TriangleIndexVertexArray, + (input for TriangleMeshShape) + Preparation for CompoundShape + +2006 June 19 Erwin Coumans + Added support for COLLADA Physics Import. + Both jam and Visual Studio can compile ColladaDemo + +2006 June 18 Dirk Gregorius + Started implementing Generic6DOF joint and setup basic interface + + +2006 June 17 Frank Richter + Bumped version in configure.ac to 1.5.6 (assuming that "1.5f" is + the next version released). + Updated files in mk/autoconf and mk/jam with copies from CS; fixes a + GLU detection issue on MinGW. + Set msvc/bullet_ico.ico as the default application icon. + Disabled exceptions for gcc builds. + Applied a patch from Michael D. Adams to fix a warning with gcc. +2006 jUNE 16 Erwin Coumans + Constraints now merge simulation islands. + +2006 May 24 + Improved GJK accuracy, fixed GjkConvexCast issue, thanks to ~MyXa~ for reporting + +2006 May 19 + Added restitution support + Moved out Friction and Dynamics info from ManifoldPoint (removed logical dependency) + Added a void* m_userPersistentData in ManifoldPoint. + Added a ContactDestroyedCallback, to allow user to handle destruction of m_userPersistentData + +2006 May 13 + Fixed some bugs in friction / jacobian calculations. Reported by Dirk Gregorius. Thanks! + +2006 May 9 + Fixed raycasting filtering + Moved repository to SVN at https://svn.sourceforge.net/svnroot/bullet + +2006 April 27 + Moved raycasting to CollisionWorld, to make it more generic + Added basic CCD option in the CcdCollisionDemo + Fixed 'noResponse' mode, for triggering rigidbodies (useful for Artificial Intelligence queries) + Improved Bullet/ODE sample (in Extras) + +2006 April 10 + Separating Axis Test (SAT) convex hull collision detector, contribution by Simon Hobbs + Added SIMD SSE Math classes (for above SAT) + Added Mouse picking in CcdPhysicsDemo + Improved penetration depth estimation in MinkowskiPenetrationDepthSolver, both accuracy and performance + Added Hinge constraint + Added quickprof profiling (see http://sourceforge.net/projects/quickprof ) + +2006 March 21 Frank Richter + Removed VC manifest files. + Removed superfluous "grpplugins" projects. + +2006 March 20 Erwin Coumans + Clamped the acculumated impulse rather then intermediate impulse (within the iteration) + Use the persistent contacts for reusing the impulse + Separated friction and normal solving for better stability + Decreased the default number of iterations of the constraint solver from 10 to 4 + +2006 March 19 Frank Richter + Removed a couple of CSisms from the VC projects. + Fixed VC include & lib paths to go to the Addtional* options + instead the command line arguments. + Added pkgconfig support. + +2006 March 14 Frank Richter + Added support for shipped GLUT on MinGW. + Fixed GLUT support on MinGW. + +2006 March 13 Frank Richter + Bolted on Jam-based build system. + Generated VC project files. + Fixed GCC warnings. + Fixed Linux build issues. + +2006 March 13 +Added 3D Sweep and Prune Broadphase Collision Detection, Contribution from Simon Hobbs. + +2006 March 2 + Minor change in license to ZLib/LibPNG + This makes it legally a bit easier to deploy on Playstation 3 + Prepared for more generic constraints, added ConstraintsDemo + +2006 Feb 23 + Rearranged files and dependencies to allow for easier standalone Collision Detection without Bullet Dynamics. + See Demos/CollisionInterfaceDemo and Extras/ode/ode/test/test_BulletGjk.cpp for examples how to use. + +2005 August 6 + Bullet 0.2 release with demos, sources, doxygen, draft manual + +2005 June 1 + First public release of Bullet + + +... todo: add history + +2003 Initial version (continuous collision detection) diff --git a/Demos/AllBulletDemos/CMakeLists.txt b/Demos/AllBulletDemos/CMakeLists.txt new file mode 100644 index 0000000..b1ab5b9 --- /dev/null +++ b/Demos/AllBulletDemos/CMakeLists.txt @@ -0,0 +1,104 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# You shouldn't have to modify anything below this line +######################################################## + + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/Extras +${BULLET_PHYSICS_SOURCE_DIR}/Extras/GIMPACTUtils +${BULLET_PHYSICS_SOURCE_DIR}/Extras/HACD +${BULLET_PHYSICS_SOURCE_DIR}/Extras/ConvexDecomposition +${BULLET_PHYSICS_SOURCE_DIR}/Extras/LibXML +${BULLET_PHYSICS_SOURCE_DIR}/Extras/LibXML/include +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletFileLoader +${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletWorldImporter +${VECTOR_MATH_INCLUDE} +) + +LINK_LIBRARIES( +GLUI GIMPACTUtils HACD ConvexDecomposition BulletMultiThreaded OpenGLSupport BulletWorldImporter BulletSoftBody BulletDynamics BulletCollision BulletFileLoader LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +SET(AllBulletDemos_SRCS + Main.cpp + DemoEntries.cpp + ../CcdPhysicsDemo/CcdPhysicsDemo.cpp + ../BasicDemo/BasicDemo.cpp + ../BspDemo/BspDemo.cpp + ../BspDemo/BspConverter.cpp + ../BspDemo/BspLoader.cpp + ../DynamicControlDemo/MotorDemo.cpp + ../ConcaveDemo/ConcavePhysicsDemo.cpp + ../ConcaveRaycastDemo/ConcaveRaycastDemo.cpp + ../ConcaveConvexcastDemo/ConcaveConvexcastDemo.cpp + ../ConvexDecompositionDemo/ConvexDecompositionDemo.cpp + ../SliderConstraintDemo/SliderConstraintDemo.cpp + ../RagdollDemo/RagdollDemo.cpp + ../GimpactTestDemo/GimpactTestDemo.cpp + ../Raytracer/Raytracer.cpp + ../GjkConvexCastDemo/LinearConvexCastDemo.cpp + ../ForkLiftDemo/ForkLiftDemo.cpp + ../SoftDemo/SoftDemo.cpp + ../ConstraintDemo/ConstraintDemo.cpp + ../Benchmarks/BenchmarkDemo.cpp + ../Box2dDemo/Box2dDemo.cpp + +) + +IF (WIN32) + ADD_EXECUTABLE(AppAllBulletDemos + ${AllBulletDemos_SRCS} + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) +ELSE() + ADD_EXECUTABLE(AppAllBulletDemos + ${AllBulletDemos_SRCS} + ) +ENDIF() + + +IF (WIN32) + IF (NOT INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppAllBulletDemos + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppAllBulletDemos + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES) +ENDIF(WIN32) + + +IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( + TARGET AppAllBulletDemos + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SerializeDemo/testFile.bullet ${CMAKE_CURRENT_BINARY_DIR}/testFile.bullet + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/file.obj ${CMAKE_CURRENT_BINARY_DIR} + ) +ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + + + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppAllBulletDemos PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppAllBulletDemos PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppAllBulletDemos PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) diff --git a/Demos/AllBulletDemos/DemoEntries.cpp b/Demos/AllBulletDemos/DemoEntries.cpp new file mode 100644 index 0000000..eb35f02 --- /dev/null +++ b/Demos/AllBulletDemos/DemoEntries.cpp @@ -0,0 +1,178 @@ +/* +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 "DemoEntries.h" + +#include "../CcdPhysicsDemo/CcdPhysicsDemo.h" +#include "../BspDemo/BspDemo.h" +#include "../BasicDemo/BasicDemo.h" +#include "../ConcaveDemo/ConcaveDemo.h" +#include "../ConcaveRaycastDemo/ConcaveRaycastDemo.h" +#include "../ConcaveConvexcastDemo/ConcaveConvexcastDemo.h" +#include "../ConvexDecompositionDemo/ConvexDecompositionDemo.h" +#include "../DynamicControlDemo/MotorDemo.h" +#include "../SliderConstraintDemo/SliderConstraintDemo.h" +#include "../RagdollDemo/RagdollDemo.h" +#include "../GimpactTestDemo/GimpactTestDemo.h" +#include "../Raytracer/Raytracer.h" +#include "../GjkConvexCastDemo/LinearConvexCastDemo.h" +#include "../ForkLiftDemo/ForkLiftDemo.h" +#include "../ConstraintDemo/ConstraintDemo.h" +//#include "../Benchmarks/BenchmarkDemo.h" +#include "../SoftDemo/SoftDemo.h" +//#include "../Box2dDemo/Box2dDemo.h" + +#include "GLDebugFont.h" + +#include "GlutStuff.h"//OpenGL stuff + + +extern int gNumAlignedAllocs; +extern int gNumAlignedFree; +extern int gTotalBytesAlignedAllocs; + +class btEmptyDebugDemo : public GlutDemoApplication +{ +public: + btEmptyDebugDemo() + { + + } + + virtual void clientMoveAndDisplay() + { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + float xOffset = 10.f; + float yStart = 20.f; + float yIncr = 20.f; + char buf[124]; + + + glColor3f(0, 0, 0); + + setOrthographicProjection(); + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"gNumAlignedAllocs= %d",gNumAlignedAllocs); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"gNumAlignedFree= %d",gNumAlignedFree); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"# alloc-free = %d",gNumAlignedAllocs-gNumAlignedFree); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; +#ifdef BT_DEBUG_MEMORY_ALLOCATIONS + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"gTotalBytesAlignedAllocs = %d",gTotalBytesAlignedAllocs); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; +#endif //BT_DEBUG_MEMORY_ALLOCATIONS + + glFlush(); + glutSwapBuffers(); + + } + + virtual void initPhysics() {} + + static DemoApplication* Create() + { + btEmptyDebugDemo* demo = new btEmptyDebugDemo(); + demo->myinit(); + return demo; + } + +}; + + +btDemoEntry g_demoEntries[] = +{ +// {"Box2dDemo",Box2dDemo::Create}, + {"ForkLift Demo",ForkLiftDemo::Create}, + {"Dynamic Control Demo",MotorDemo::Create}, + {"ConstraintDemo",ConstraintDemo::Create}, + + {"Ragdoll Demo",RagdollDemo::Create}, + {"Basic Demo", BasicDemo::Create}, + {"CcdPhysicsDemo", CcdPhysicsDemo::Create}, + {"Convex Decomposition",ConvexDecompositionDemo::Create}, + {"Concave Moving", GimpactConcaveDemo::Create}, + + {"ConcaveDemo",ConcaveDemo::Create}, + {"Concave Convexcast Demo",ConcaveConvexcastDemo::Create}, + {"SoftBody Cluster Collide1",SoftDemo19::Create}, + + {"SoftBody Ropes Attach",SoftDemo4::Create}, + + {"SoftBody Cloth Attach",SoftDemo5::Create}, + + {"SoftBody Cloth",SoftDemo0::Create}, + +// {"SoftBody Volume",SoftDemo2::Create}, + {"SoftBody Pressure",SoftDemo1::Create}, + {"SoftBody Cluster Car",SoftDemo24::Create}, + {"SoftBody Cluster Robot",SoftDemo25::Create}, + // {"SoftBody Ropes",SoftDemo3::Create}, + {"SoftBody Sticks",SoftDemo6::Create}, + {"SoftBody Collide",SoftDemo7::Create}, + {"SoftBody Collide2",SoftDemo8::Create}, +// {"SoftBody Collide3",SoftDemo9::Create}, +// {"SoftBody Impact",SoftDemo10::Create}, + {"SoftBody Aero",SoftDemo11::Create}, + {"SoftBody Friction",SoftDemo12::Create}, +// {"SoftBody Torus",SoftDemo13::Create}, +// {"SoftBody Torus Match",SoftDemo14::Create}, +// {"SoftBody Bunny",SoftDemo15::Create}, +// {"SoftBody Bunny Match",SoftDemo16::Create}, + {"SoftBody Init Cutting",SoftDemo17::Create}, +// {"SoftBody Cluster Deform",SoftDemo18::Create}, + +// {"SoftBody Cluster Collide2",SoftDemo20::Create}, +// {"SoftBody Cluster Socket",SoftDemo21::Create}, + {"SoftBody Cluster Hinge",SoftDemo22::Create}, + {"SoftBody Cluster Combine",SoftDemo23::Create}, +// {"SoftBody Cluster Stack Soft",SoftDemo26::Create}, + {"SoftBody Cluster Stack Mixed",SoftDemo27::Create}, + + {"SoftBody TetGen Tetrahedral Cube",SoftDemo28::Create}, + {"SoftBody TetGen Tetrahedral Bunny",SoftDemo29::Create}, + + +// {"SliderConstraint",SliderConstraintDemo::Create}, + +// {"ConcaveRaycastDemo",ConcaveRaycastDemo::Create}, + //{"BspDemo", BspDemo::Create}, +// {"Raytracer Test",Raytracer::Create}, +// {"GjkConvexCast",LinearConvexCastDemo::Create}, +// {"Benchmark 3000 FALL",BenchmarkDemo1::Create}, +// {"Benchmark 1000 STACK",BenchmarkDemo2::Create}, +// {"Benchmark 136 RAGDOLLS",BenchmarkDemo3::Create}, +// {"Benchmark 1000 CONVEX",BenchmarkDemo4::Create}, +// {"Benchmark Mesh-Prim",BenchmarkDemo5::Create}, +// {"Benchmark Mesh-Convex",BenchmarkDemo6::Create}, +// {"Benchmark Raycast",BenchmarkDemo7::Create}, + + {"MemoryLeak Checker",btEmptyDebugDemo::Create}, + {0, 0} +}; + + diff --git a/Demos/AllBulletDemos/DemoEntries.h b/Demos/AllBulletDemos/DemoEntries.h new file mode 100644 index 0000000..41fd857 --- /dev/null +++ b/Demos/AllBulletDemos/DemoEntries.h @@ -0,0 +1,34 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_DEMO_ENTRIES_H +#define BT_DEMO_ENTRIES_H + + +class DemoApplication; + +typedef DemoApplication* DemoCreateFcn(); + +struct btDemoEntry +{ + const char *name; + DemoCreateFcn *createFcn; +}; + +extern btDemoEntry g_demoEntries[]; + + + +#endif //BT_DEMO_ENTRIES_H diff --git a/Demos/AllBulletDemos/Main.cpp b/Demos/AllBulletDemos/Main.cpp new file mode 100644 index 0000000..4958ffe --- /dev/null +++ b/Demos/AllBulletDemos/Main.cpp @@ -0,0 +1,579 @@ +/* +* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com +* +* 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 + +#include "glui/GL/glui.h" +#include "LinearMath/btScalar.h" +#include "LinearMath/btMinMax.h" +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" +#include "DemoApplication.h" +#include "DemoEntries.h" +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +#include "BulletSoftBody/btSoftRigidDynamicsWorld.h" +#include "BulletSoftBody/btSoftBodyHelpers.h" + +#include "GLDebugDrawer.h" + +#include "LinearMath/btQuickprof.h" + + + +namespace +{ + int testIndex=1; + int testSelection=0; + btDemoEntry* entry; + DemoApplication* demo; + int iterationCount; + int width; + int height; + int framePeriod;//todo: test if this value should be 0 + int mainWindow; + GLUI *glui; + float hz; + float viewZoom=20.f; + float viewX; + float viewY; + int tx, ty, tw, th; + int gDrawAabb; + int gWireFrame; + int gDrawNormals; + int gHelpText; + int gDebugConstraints; + int gDebugContacts; + int gDrawTextures=1; + int gDrawShadows=0; + int gDrawClusters=0; + int gDebugNoDeactivation; + int gUseWarmstarting; + int gRandomizeConstraints; + int gUseSplitImpulse; + float gErp; + float gSlop; + float gErp2; + float gWarmStartingParameter; +} + + + +void setDefaultSettings() +{ + viewX = 0.0f; + viewY = 0.0f; + framePeriod = 6;//16;//16;//todo: test if this value should be 0 + + width = 1280; + height = 768;//480; + iterationCount = 10; + gDrawAabb=0; + gDrawNormals=0; + gWireFrame=0; + gDebugContacts=0; + //enable constraint debug visualization for first demo, only if user hasn't overridden the setting + if (testSelection>1) + { + gDebugConstraints=0; + } else + { + gDebugConstraints=1; + } + gHelpText = 0; + gDrawTextures=1; + gDrawShadows=0; + gDrawClusters=0; + + gDebugNoDeactivation = 0; + gUseSplitImpulse = 0; + gUseWarmstarting = 1; + gRandomizeConstraints = 1; + gErp = 0.2f; + gSlop=0.0f; + gErp2 = 0.1f; + gWarmStartingParameter = 0.85f; + +} + +void setDefaultSettingsAndSync() +{ + setDefaultSettings(); + glui->sync_live(); +} + + +void TogglePause() +{ + if (demo) + demo->toggleIdle(); +} + +void ResetScene() +{ + if (demo) + demo->clientResetScene(); +} + +void NextScene() +{ + testSelection++; + if (testSelection>1) + { + gDebugConstraints=0; + } else + { + gDebugConstraints=1; + } + + if(testSelection>28) + testSelection=0; + if (glui) + glui->sync_live(); +} + + +void SingleSimulationStep() +{ + if (demo) + demo->clientMoveAndDisplay(); +} + + +void Resize(int w, int h) +{ + width = w; + height = h; + + GLUI_Master.get_viewport_area( &tx, &ty, &tw, &th ); + glViewport( tx, ty, tw, th ); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if (demo) + demo->reshape(tw, th); +} + +DemoApplication* CreatDemo(btDemoEntry* entry) +{ + DemoApplication* demo = entry->createFcn(); + btAssert(demo); + if (demo->getDynamicsWorld()) + { + demo->getDynamicsWorld()->setDebugDrawer(new GLDebugDrawer()); + gDrawTextures = demo->getTexturing(); + gDrawShadows = demo->getShadows(); + if (glui) + glui->sync_live(); + } + +#ifndef BT_NO_PROFILE + CProfileManager::Reset(); +#endif //BT_NO_PROFILE + + return demo; + +} + +/*b2Vec2 ConvertScreenToWorld(int x, int y) +{ + b2Vec2 p; + + float ratio = float(tw) / float(th); + float u = x / float(tw); + float v = (th - y) / float(th); + p.x = viewZoom * (viewX - ratio) * (1.0f - u) + viewZoom * (ratio + viewX) * u; + p.y = viewZoom * (viewY - 0.1f) * (1.0f - v) + viewZoom * (viewY + 1.9f) * v; + return p; +} +*/ + +// This is used to control the frame rate (60Hz). +void Timer(int) +{ + glutSetWindow(mainWindow); + glutPostRedisplay(); + glutTimerFunc(framePeriod, Timer, 0); +} + +void SimulationLoop() +{ + Resize(width, height); + + + + if (gDrawAabb) + { + demo->setDebugMode(demo->getDebugMode() |btIDebugDraw::DBG_DrawAabb); + } else + { + demo->setDebugMode(demo->getDebugMode() & (~btIDebugDraw::DBG_DrawAabb)); + } + if (gWireFrame) + { + demo->setDebugMode(demo->getDebugMode() |btIDebugDraw::DBG_DrawWireframe); + } else + { + demo->setDebugMode(demo->getDebugMode() & (~btIDebugDraw::DBG_DrawWireframe)); + } + if (gDrawNormals) + { + demo->setDebugMode(demo->getDebugMode() |btIDebugDraw::DBG_DrawNormals); + } else + { + demo->setDebugMode(demo->getDebugMode() & (~btIDebugDraw::DBG_DrawNormals)); + } + if (gHelpText) + { + demo->setDebugMode(demo->getDebugMode() & (~btIDebugDraw::DBG_NoHelpText)); + } else + { + demo->setDebugMode(demo->getDebugMode() |btIDebugDraw::DBG_NoHelpText); + } + if (gDebugConstraints) + { + demo->setDebugMode(demo->getDebugMode() |btIDebugDraw::DBG_DrawConstraints+btIDebugDraw::DBG_DrawConstraintLimits); + } else + { + demo->setDebugMode(demo->getDebugMode() & (~btIDebugDraw::DBG_DrawConstraints+btIDebugDraw::DBG_DrawConstraintLimits)); + } + if (gDebugContacts) + { + demo->setDebugMode(demo->getDebugMode() |btIDebugDraw::DBG_DrawContactPoints); + } else + { + demo->setDebugMode(demo->getDebugMode() & (~btIDebugDraw::DBG_DrawContactPoints)); + } + + demo->setTexturing(0!=gDrawTextures); + demo->setShadows(0!=gDrawShadows); + demo->setDrawClusters(0!=gDrawClusters); + + if (gDebugNoDeactivation) + { + demo->setDebugMode(demo->getDebugMode() |btIDebugDraw::DBG_NoDeactivation); + } else + { + demo->setDebugMode(demo->getDebugMode() & (~btIDebugDraw::DBG_NoDeactivation)); + } + + + + + if (demo->getDynamicsWorld() && demo->getDynamicsWorld()->getWorldType() == BT_DISCRETE_DYNAMICS_WORLD) + { + btDiscreteDynamicsWorld* discreteWorld = (btDiscreteDynamicsWorld*) demo->getDynamicsWorld(); + discreteWorld->getSolverInfo().m_numIterations = iterationCount; + discreteWorld->getSolverInfo().m_erp = gErp; + discreteWorld->getSolverInfo().m_erp2 = gErp2; + + discreteWorld->getSolverInfo().m_linearSlop = gSlop; + + discreteWorld->getSolverInfo().m_warmstartingFactor = gWarmStartingParameter; + discreteWorld->getSolverInfo().m_splitImpulse = gUseSplitImpulse; + + // btSequentialImpulseConstraintSolver* solver = ((btSequentialImpulseConstraintSolver*) discreteWorld->getConstraintSolver()); + + if (gUseWarmstarting) + { + discreteWorld->getSolverInfo().m_solverMode |= SOLVER_USE_WARMSTARTING; + } else + { + discreteWorld->getSolverInfo().m_solverMode &= (~SOLVER_USE_WARMSTARTING); + } + if (gRandomizeConstraints) + { + discreteWorld->getSolverInfo().m_solverMode |= SOLVER_RANDMIZE_ORDER; + } else + { + discreteWorld->getSolverInfo().m_solverMode &= (~SOLVER_RANDMIZE_ORDER); + } + } + + if (!demo->isIdle()) + { + demo->clientMoveAndDisplay(); + + + } + else + { + demo->displayCallback(); + } + + if (demo->getDynamicsWorld() && demo->getDynamicsWorld()->getWorldType()==BT_SOFT_RIGID_DYNAMICS_WORLD) + { + btSoftRigidDynamicsWorld* softWorld = (btSoftRigidDynamicsWorld*)demo->getDynamicsWorld(); + for ( int i=0;igetSoftBodyArray().size();i++) + { + btSoftBody* psb=(btSoftBody*)softWorld->getSoftBodyArray()[i]; + if (softWorld->getDebugDrawer() && !(softWorld->getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe))) + { + btSoftBodyHelpers::DrawFrame(psb,softWorld->getDebugDrawer()); + btSoftBodyHelpers::Draw(psb,softWorld->getDebugDrawer(),softWorld->getDrawFlags()); + } + } + } + + if (testSelection != testIndex) + { + if (testSelection>1) + { + gDebugConstraints=0; + } else + { + gDebugConstraints=1; + } + + testIndex = testSelection; + if (demo->getDynamicsWorld() && demo->getDynamicsWorld()->getDebugDrawer()) + delete demo->getDynamicsWorld()->getDebugDrawer(); + delete demo; + entry = g_demoEntries + testIndex; + demo = CreatDemo(entry); + viewZoom = 20.0f; + viewX = 0.0f; + viewY = 0.0f; + Resize(width, height); + } +} + +void RestartScene() +{ + if (demo->getDynamicsWorld() && demo->getDynamicsWorld()->getDebugDrawer()) + delete demo->getDynamicsWorld()->getDebugDrawer(); + delete demo; + entry = g_demoEntries + testIndex; + demo = CreatDemo(entry); + viewZoom = 20.0f; + viewX = 0.0f; + viewY = 0.0f; + Resize(width, height); +} + +void Keyboard(unsigned char key, int x, int y) +{ + + + + + switch (key) + { + case 27: + exit(0); + break; + + // Press 'r' to reset. + case 'r': + if (demo->getDynamicsWorld() && demo->getDynamicsWorld()->getDebugDrawer()) + delete demo->getDynamicsWorld()->getDebugDrawer(); + delete demo; + demo = CreatDemo(entry); + Resize(width,height); + break; + + default: + if (demo) + { + demo->keyboardCallback(key,x,y); + } + } +} + +void KeyboardSpecialUp(int key, int x, int y) +{ + if (demo) + { + demo->specialKeyboardUp(key,x,y); + } + +} + + +void GlutIdleFunc() +{ + int current_window, new_window=-1; + current_window = glutGetWindow(); + if (GLUI_Master.gluis.first_child() != NULL ) + { + new_window = ((GLUI_Main*)GLUI_Master.gluis.first_child())->getMainWindowId(); + } + if ( (new_window > 0) && (new_window != current_window )) + { + //--- Window is changed only if its not already the current window --- + glutSetWindow( new_window ); + } + + if (demo) + demo->moveAndDisplay(); + + glutSetWindow( current_window ); +} + +void KeyboardSpecial(int key, int x, int y) +{ + + if (demo) + { + demo->specialKeyboard(key,x,y); + } + +} + + +void Mouse(int button, int state, int x, int y) +{ + if (demo) + demo->mouseFunc(button,state,x,y); +} + +void MouseMotion(int x, int y) +{ + demo->mouseMotionFunc(x,y); +} + +#ifdef BT_USE_FREEGLUT +#include "GL/freeglut_ext.h" +#endif + +int main(int argc, char** argv) +{ + +//#define CHECK_FPU_EXCEPTIONS 1 +#ifdef CHECK_FPU_EXCEPTIONS + + int cw = _control87(0, 0); + + // Set the exception masks off, turn exceptions on + cw &= ~(EM_ZERODIVIDE | EM_INVALID); + + printf("control87 = %#x\n", cw); + + // Set the control word + _control87(cw, MCW_EM); +#endif //CHECK_FPU_EXCEPTIONS + + + setDefaultSettings(); + + int bulletVersion = btGetVersion(); + printf("Bullet version %d\n",bulletVersion); + + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE |GLUT_DEPTH | GLUT_STENCIL); + glutInitWindowSize(width, height); + mainWindow = glutCreateWindow("http://bulletphysics.com"); +#ifdef BT_USE_FREEGLUT + glutSetOption (GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS); +#endif + entry = g_demoEntries + testIndex; + demo = CreatDemo(entry); + + glutDisplayFunc(SimulationLoop); + GLUI_Master.set_glutReshapeFunc(Resize); + GLUI_Master.set_glutKeyboardFunc(Keyboard); + GLUI_Master.set_glutSpecialFunc(KeyboardSpecial); + GLUI_Master.set_glutIdleFunc(GlutIdleFunc); + GLUI_Master.set_glutSpecialUpFunc(KeyboardSpecialUp); + GLUI_Master.set_glutMouseFunc(Mouse); + glutMotionFunc(MouseMotion); + + + glui = GLUI_Master.create_glui_subwindow( mainWindow, + GLUI_SUBWINDOW_RIGHT ); + + + + glui->add_statictext("Tests"); + GLUI_Listbox* testList = + glui->add_listbox("", &testSelection); + glui->add_button("Next Scene", 0,(GLUI_Update_CB)NextScene); + + glui->add_separator(); + + GLUI_Spinner* iterationSpinner = + glui->add_spinner("Iterations", GLUI_SPINNER_INT, &iterationCount); + iterationSpinner->set_int_limits(1, 250); + +/* GLUI_Spinner* hertzSpinner = + glui->add_spinner("Hertz", GLUI_SPINNER_FLOAT, &hz); + hertzSpinner->set_float_limits(5.0f, 200.0f); +*/ + + + glui->add_checkbox("DisableDeactivation", &gDebugNoDeactivation); + glui->add_checkbox("Split Impulse", &gUseSplitImpulse); + GLUI_Spinner* spinner = 0; + + spinner = glui->add_spinner("ERP", GLUI_SPINNER_FLOAT, &gErp); +// spinner->set_float_limits(0.f,1.f); +// spinner = glui->add_spinner("ERP2", GLUI_SPINNER_FLOAT, &gErp2); + spinner->set_float_limits(0.f,1.f); + spinner = glui->add_spinner("Slop", GLUI_SPINNER_FLOAT, &gSlop); + spinner->set_float_limits(0.f,1.f); +// spinner = glui->add_spinner("WSP", GLUI_SPINNER_FLOAT,&gWarmStartingParameter); +// spinner->set_float_limits (0.f,1.0); + glui->add_checkbox("Warmstarting", &gUseWarmstarting); + glui->add_checkbox("Randomize Constraints", &gRandomizeConstraints); + + + glui->add_button("Reset Defaults", 0,(GLUI_Update_CB)setDefaultSettingsAndSync); + glui->add_separator(); + + GLUI_Panel* drawPanel = glui->add_panel("Debug Draw"); + + + glui->add_checkbox_to_panel(drawPanel, "Help", &gHelpText); + glui->add_checkbox_to_panel(drawPanel, "AABBs", &gDrawAabb); + glui->add_checkbox_to_panel(drawPanel, "Wireframe", &gWireFrame); + glui->add_checkbox_to_panel(drawPanel, "Normals", &gDrawNormals); + glui->add_checkbox_to_panel(drawPanel, "Contacts", &gDebugContacts); + glui->add_checkbox_to_panel(drawPanel, "Constraints", &gDebugConstraints); + + glui->add_checkbox_to_panel(drawPanel, "Textures", &gDrawTextures); + glui->add_checkbox_to_panel(drawPanel, "Shadows", &gDrawShadows); + glui->add_checkbox_to_panel(drawPanel, "Clusters", &gDrawClusters); + + int testCount = 0; + btDemoEntry* e = g_demoEntries; + while (e->createFcn) + { + testList->add_item(testCount, e->name); + ++testCount; + ++e; + } + + glui->add_separator(); + + glui->add_button("Toggle Pause", 0,(GLUI_Update_CB)TogglePause); + + glui->add_button("Single Step", 0,(GLUI_Update_CB)SingleSimulationStep); + glui->add_button("Reset Scene", 0,(GLUI_Update_CB)ResetScene); + glui->add_button("Restart Scene", 0,(GLUI_Update_CB)RestartScene); + + glui->add_separator(); + +// glui->add_button("Exit", 0,(GLUI_Update_CB)exit); + + glui->set_main_gfx_window( mainWindow ); + + // Use a timer to control the frame rate. + glutTimerFunc(framePeriod, Timer, 0); + + glutMainLoop(); + + return 0; +} diff --git a/Demos/AllBulletDemos/Makefile.am b/Demos/AllBulletDemos/Makefile.am new file mode 100644 index 0000000..aab8b98 --- /dev/null +++ b/Demos/AllBulletDemos/Makefile.am @@ -0,0 +1,34 @@ +noinst_PROGRAMS=AllBulletDemo + +AllBulletDemo_SOURCES=\ + ../SoftDemo/SoftDemo.cpp \ + ../ConstraintDemo/ConstraintDemo.cpp \ + ../ForkLiftDemo/ForkLiftDemo.cpp \ + ../RagdollDemo/RagdollDemo.cpp \ + ../BasicDemo/BasicDemo.cpp \ + ../CcdPhysicsDemo/CcdPhysicsDemo.cpp \ + ../SliderConstraintDemo/SliderConstraintDemo.cpp \ + ../ConcaveRaycastDemo/ConcaveRaycastDemo.cpp \ + ../Raytracer/Raytracer.cpp \ + ../BspDemo/BspDemo.cpp \ + ../BspDemo/BspLoader.cpp \ + ../BspDemo/BspConverter.cpp \ + ../ConcaveConvexcastDemo/ConcaveConvexcastDemo.cpp \ + ../ConvexDecompositionDemo/ConvexDecompositionDemo.cpp \ + ../GimpactTestDemo/GimpactTestDemo.cpp \ + ../GjkConvexCastDemo/LinearConvexCastDemo.cpp \ + ../ConcaveDemo/ConcavePhysicsDemo.cpp \ + ../DynamicControlDemo/MotorDemo.cpp \ + DemoEntries.cpp \ + DemoEntries.h\ + Main.cpp +AllBulletDemo_CXXFLAGS=\ + -I@top_builddir@/src \ + -I@top_builddir@/Extras/GIMPACTUtils \ + -I@top_builddir@/Extras/ConvexDecomposition \ + -I@top_builddir@/Extras/HACD \ + -I@top_builddir@/Extras \ + -I@top_builddir@/Demos/OpenGL \ + -I@top_builddir@/Demos/SoftDemo \ + $(CXXFLAGS) +AllBulletDemo_LDADD=-L../OpenGL -lbulletopenglsupport -L../../src -L../../Extras -lgimpactutils -lconvexdecomposition -lHACD -lBulletSoftBody -lBulletDynamics -lBulletCollision -lLinearMath -lglui @opengl_LIBS@ diff --git a/Demos/BasicDemo/BasicDemo.cpp b/Demos/BasicDemo/BasicDemo.cpp new file mode 100644 index 0000000..8f2bfc8 --- /dev/null +++ b/Demos/BasicDemo/BasicDemo.cpp @@ -0,0 +1,237 @@ +/* +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. +*/ + + +///create 125 (5x5x5) dynamic object +#define ARRAY_SIZE_X 5 +#define ARRAY_SIZE_Y 5 +#define ARRAY_SIZE_Z 5 + +//maximum number of objects (and allow user to shoot additional boxes) +#define MAX_PROXIES (ARRAY_SIZE_X*ARRAY_SIZE_Y*ARRAY_SIZE_Z + 1024) + +///scaling of the objects (0.1 = 20 centimeter boxes ) +#define SCALING 1. +#define START_POS_X -5 +#define START_POS_Y -5 +#define START_POS_Z -3 + +#include "BasicDemo.h" +#include "GlutStuff.h" +///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files. +#include "btBulletDynamicsCommon.h" + +#include //printf debugging + + +void BasicDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //simple dynamics world doesn't handle fixed-time-stepping + float ms = getDeltaTimeMicroseconds(); + + ///step the simulation + if (m_dynamicsWorld) + { + m_dynamicsWorld->stepSimulation(ms / 1000000.f); + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + } + + renderme(); + + glFlush(); + + swapBuffers(); + +} + + + +void BasicDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + //optional but useful: debug drawing to detect problems + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + glFlush(); + swapBuffers(); +} + + + + + +void BasicDemo::initPhysics() +{ + setTexturing(true); + setShadows(true); + + setCameraDistance(btScalar(SCALING*50.)); + + ///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->setGravity(btVector3(0,-10,0)); + + ///create a few basic rigid bodies + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); +// btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); + + m_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + + //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here: + { + btScalar mass(0.); + + //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) + groundShape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + //add the body to the dynamics world + m_dynamicsWorld->addRigidBody(body); + } + + + { + //create a few dynamic rigidbodies + // Re-using the same collision is better for memory usage and performance + + btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,SCALING*1)); + //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); + m_collisionShapes.push_back(colShape); + + /// Create Dynamic Objects + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + + //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) + colShape->calculateLocalInertia(mass,localInertia); + + float start_x = START_POS_X - ARRAY_SIZE_X/2; + float start_y = START_POS_Y; + float start_z = START_POS_Z - ARRAY_SIZE_Z/2; + + for (int k=0;kaddRigidBody(body); + } + } + } + } + + +} +void BasicDemo::clientResetScene() +{ + exitPhysics(); + initPhysics(); +} + + +void BasicDemo::exitPhysics() +{ + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;j m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + public: + + BasicDemo() + { + } + virtual ~BasicDemo() + { + exitPhysics(); + } + void initPhysics(); + + void exitPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + virtual void clientResetScene(); + + static DemoApplication* Create() + { + BasicDemo* demo = new BasicDemo; + demo->myinit(); + demo->initPhysics(); + return demo; + } + + +}; + +#endif //BASIC_DEMO_H + diff --git a/Demos/BasicDemo/CMakeLists.txt b/Demos/BasicDemo/CMakeLists.txt new file mode 100644 index 0000000..0956803 --- /dev/null +++ b/Demos/BasicDemo/CMakeLists.txt @@ -0,0 +1,87 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# This is the variable for Windows. I use this to define the root of my directory structure. +SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/Glut) + +# You shouldn't have to modify anything below this line +######################################################## + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + + + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + +IF (WIN32) +ADD_EXECUTABLE(AppBasicDemo + main.cpp + BasicDemo.cpp + BasicDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) +ELSE() + ADD_EXECUTABLE(AppBasicDemo + main.cpp + BasicDemo.cpp + BasicDemo.h + ) +ENDIF() + + + + + IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppBasicDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppBasicDemo + POST_BUILD +# COMMAND copy /Y ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + + ENDIF(WIN32) +ELSE (USE_GLUT) + + + + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + + ADD_EXECUTABLE(AppBasicDemo + WIN32 + ../OpenGL/Win32AppMain.cpp + Win32BasicDemo.cpp + BasicDemo.cpp + BasicDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) + + +ENDIF (USE_GLUT) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppBasicDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppBasicDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppBasicDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/BasicDemo/Makefile.am b/Demos/BasicDemo/Makefile.am new file mode 100644 index 0000000..0554616 --- /dev/null +++ b/Demos/BasicDemo/Makefile.am @@ -0,0 +1,5 @@ +noinst_PROGRAMS=BasicDemo + +BasicDemo_SOURCES=BasicDemo.cpp BasicDemo.h main.cpp +BasicDemo_CXXFLAGS=-I@top_builddir@/src -I@top_builddir@/Demos/OpenGL $(CXXFLAGS) +BasicDemo_LDADD=-L../OpenGL -lbulletopenglsupport -L../../src -lBulletDynamics -lBulletCollision -lLinearMath @opengl_LIBS@ diff --git a/Demos/BasicDemo/Makefile.original b/Demos/BasicDemo/Makefile.original new file mode 100644 index 0000000..53d3eae --- /dev/null +++ b/Demos/BasicDemo/Makefile.original @@ -0,0 +1,49 @@ +__ARCH_BITS__ := 32 + +# define macros +RM=rm -f +OUTDIR=. +CELLSDKDIR=/opt/ibm/cell-sdk +ARCHITECTUREFLAG=-m$(__ARCH_BITS__) +USE_CESOF=1 +ifeq "$(__ARCH_BITS__)" "64" + DEFFLAGS= -DUSE_LIBSPE2 -DUSE_ADDR64 -DUSE_PARALLEL_DISPATCHER + GCC=ppu-g++ +else + DEFFLAGS= -DUSE_LIBSPE2 -DUSE_PARALLEL_DISPATCHER + GCC=ppu32-g++ +endif +DEBUGFLAG= +ifeq "$(USE_CESOF)" "1" + CFLAGS= $(ARCHITECTUREFLAG) $(DEBUGFLAG) -DUSE_CESOF -W -Wall -Winline -O3 -mabi=altivec -maltivec -include altivec.h -include stdbool.h -c +else + CFLAGS= $(ARCHITECTUREFLAG) $(DEBUGFLAG) -W -Wall -Winline -O3 -mabi=altivec -maltivec -include altivec.h -include stdbool.h -c +endif +INCLUDEDIR= -I. -I$(CELLSDKDIR)/prototype/sysroot/usr/include -I../../src -I../OpenGL +LFLAGS= $(ARCHITECTUREFLAG) -Wl,-m,elf$(__ARCH_BITS__)ppc +ifeq "$(USE_CESOF)" "1" + LIBRARIES= -lstdc++ -lsupc++ -lgcc -lgcov -lspe2 -lpthread -L../../out/linuxppc/optimize/libs \ + -lbulletmultithreaded -lspu -lbulletdynamics -lbulletcollision -lbulletmath \ + -L$(CELLSDKDIR)/prototype/sysroot/usr/lib$(__ARCH_BITS__) -R$(CELLSDKDIR)/prototype/sysroot/usr/lib +else + LIBRARIES= -lstdc++ -lsupc++ -lgcc -lgcov -lspe2 -lpthread -L../../out/linuxppc/optimize/libs \ + -lbulletmultithreaded -lbulletdynamics -lbulletcollision -lbulletmath \ + -L$(CELLSDKDIR)/prototype/sysroot/usr/lib$(__ARCH_BITS__) -R$(CELLSDKDIR)/prototype/sysroot/usr/lib +endif + +DemoApplication : + $(GCC) $(DEFFLAGS) $(CFLAGS) $(INCLUDEDIR) -o $(OUTDIR)/$@.o ../OpenGL/$@.cpp + + +BasicDemo : DemoApplication + $(GCC) $(DEFFLAGS) $(CFLAGS) $(INCLUDEDIR) -o $(OUTDIR)/$@.o $@.cpp + + + +all : BasicDemo + $(GCC) -o$(OUTDIR)/BasicDemo $(OUTDIR)/BasicDemo.o $(OUTDIR)/DemoApplication.o $(LFLAGS) $(LIBRARIES) + + +clean : + $(RM) $(OUTDIR)/BasicDemo ; $(RM) $(OUTDIR)/BasicDemo.o ; $(RM) $(OUTDIR)/DemoApplication.o + diff --git a/Demos/BasicDemo/Win32BasicDemo.cpp b/Demos/BasicDemo/Win32BasicDemo.cpp new file mode 100644 index 0000000..72f92a1 --- /dev/null +++ b/Demos/BasicDemo/Win32BasicDemo.cpp @@ -0,0 +1,25 @@ +#ifdef _WINDOWS +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "BasicDemo.h" + +///The 'createDemo' function is called from Bullet/Demos/OpenGL/Win32AppMain.cpp to instantiate this particular demo +DemoApplication* createDemo() +{ + return new BasicDemo(); +} + +#endif diff --git a/Demos/BasicDemo/main.cpp b/Demos/BasicDemo/main.cpp new file mode 100644 index 0000000..ac2d8da --- /dev/null +++ b/Demos/BasicDemo/main.cpp @@ -0,0 +1,42 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "BasicDemo.h" +#include "GlutStuff.h" +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btHashMap.h" + +#include "GLDebugDrawer.h" +static GLDebugDrawer sDebugDraw; + + + +int main(int argc,char** argv) +{ + + BasicDemo ccdDemo; + ccdDemo.initPhysics(); + ccdDemo.getDynamicsWorld()->setDebugDrawer(&sDebugDraw); + +#ifdef CHECK_MEMORY_LEAKS + ccdDemo.exitPhysics(); +#else + return glutmain(argc, argv,1024,600,"Bullet Physics Demo. http://bulletphysics.org",&ccdDemo); +#endif + + //default glut doesn't return from mainloop + return 0; +} + diff --git a/Demos/Benchmarks/BenchmarkDemo.cpp b/Demos/Benchmarks/BenchmarkDemo.cpp new file mode 100644 index 0000000..7c01e88 --- /dev/null +++ b/Demos/Benchmarks/BenchmarkDemo.cpp @@ -0,0 +1,1320 @@ +/* +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. +*/ + + + +// Collision Radius +#define COLLISION_RADIUS 0.0f + +#include "BenchmarkDemo.h" +#ifdef USE_GRAPHICAL_BENCHMARK +#include "GlutStuff.h" +#endif //USE_GRAPHICAL_BENCHMARK + +///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files. +#include "btBulletDynamicsCommon.h" +#include //printf debugging +#include "Taru.mdl" +#include "landscape.mdl" +#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h" +#ifdef USE_PARALLEL_DISPATCHER_BENCHMARK +#include "BulletMultiThreaded/SpuGatheringCollisionDispatcher.h" +#include "BulletMultiThreaded/SequentialThreadSupport.h" +#include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" +#endif + +#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" + + +#ifdef USE_PARALLEL_DISPATCHER_BENCHMARK +#ifdef _WIN32 +#include "BulletMultiThreaded/Win32ThreadSupport.h" +#elif defined (USE_PTHREADS) +#include "BulletMultiThreaded/PosixThreadSupport.h" +#endif +#include "BulletMultiThreaded/SpuGatheringCollisionDispatcher.h" +#include "BulletMultiThreaded/btParallelConstraintSolver.h" + + + + +btThreadSupportInterface* createSolverThreadSupport(int maxNumThreads) +{ +//#define SEQUENTIAL +#ifdef SEQUENTIAL + SequentialThreadSupport::SequentialThreadConstructionInfo tci("solverThreads",SolverThreadFunc,SolverlsMemoryFunc); + SequentialThreadSupport* threadSupport = new SequentialThreadSupport(tci); + threadSupport->startSPU(); +#else + +#ifdef _WIN32 + Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("solverThreads",SolverThreadFunc,SolverlsMemoryFunc,maxNumThreads); + Win32ThreadSupport* threadSupport = new Win32ThreadSupport(threadConstructionInfo); + threadSupport->startSPU(); +#elif defined (USE_PTHREADS) + PosixThreadSupport::ThreadConstructionInfo solverConstructionInfo("solver", SolverThreadFunc, + SolverlsMemoryFunc, maxNumThreads); + + PosixThreadSupport* threadSupport = new PosixThreadSupport(solverConstructionInfo); + +#else + SequentialThreadSupport::SequentialThreadConstructionInfo tci("solverThreads",SolverThreadFunc,SolverlsMemoryFunc); + SequentialThreadSupport* threadSupport = new SequentialThreadSupport(tci); + threadSupport->startSPU(); +#endif + +#endif + + return threadSupport; +} +#endif + +class btRaycastBar2 +{ +public: + btVector3 source[NUMRAYS]; + btVector3 dest[NUMRAYS]; + btVector3 direction[NUMRAYS]; + btVector3 hit[NUMRAYS]; + btVector3 normal[NUMRAYS]; + + int frame_counter; + int ms; + int sum_ms; + int sum_ms_samples; + int min_ms; + int max_ms; + +#ifdef USE_BT_CLOCK + btClock frame_timer; +#endif //USE_BT_CLOCK + + btScalar dx; + btScalar min_x; + btScalar max_x; + btScalar max_y; + btScalar sign; + + btRaycastBar2 () + { + ms = 0; + max_ms = 0; + min_ms = 9999; + sum_ms_samples = 0; + sum_ms = 0; + } + + + + btRaycastBar2 (btScalar ray_length, btScalar z,btScalar max_y) + { + frame_counter = 0; + ms = 0; + max_ms = 0; + min_ms = 9999; + sum_ms_samples = 0; + sum_ms = 0; + dx = 10.0; + min_x = 0; + max_x = 0; + this->max_y = max_y; + sign = 1.0; + btScalar dalpha = 2*SIMD_2_PI/NUMRAYS; + for (int i = 0; i < NUMRAYS; i++) + { + btScalar alpha = dalpha * i; + // rotate around by alpha degrees y + btQuaternion q(btVector3(0.0, 1.0, 0.0), alpha); + direction[i] = btVector3(1.0, 0.0, 0.0); + direction[i] = quatRotate(q , direction[i]); + direction[i] = direction[i] * ray_length; + + + source[i] = btVector3(min_x, max_y, z); + dest[i] = source[i] + direction[i]; + dest[i][1]=-1000; + normal[i] = btVector3(1.0, 0.0, 0.0); + } + } + + void move (btScalar dt) + { + if (dt > btScalar(1.0/60.0)) + dt = btScalar(1.0/60.0); + for (int i = 0; i < NUMRAYS; i++) + { + source[i][0] += dx * dt * sign; + dest[i][0] += dx * dt * sign; + } + if (source[0][0] < min_x) + sign = 1.0; + else if (source[0][0] > max_x) + sign = -1.0; + } + + void cast (btCollisionWorld* cw) + { +#ifdef USE_BT_CLOCK + frame_timer.reset (); +#endif //USE_BT_CLOCK + +#ifdef BATCH_RAYCASTER + if (!gBatchRaycaster) + return; + + gBatchRaycaster->clearRays (); + for (int i = 0; i < NUMRAYS; i++) + { + gBatchRaycaster->addRay (source[i], dest[i]); + } + gBatchRaycaster->performBatchRaycast (); + for (int i = 0; i < gBatchRaycaster->getNumRays (); i++) + { + const SpuRaycastTaskWorkUnitOut& out = (*gBatchRaycaster)[i]; + hit[i].setInterpolate3(source[i],dest[i],out.hitFraction); + normal[i] = out.hitNormal; + 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); + } + + } +#ifdef USE_BT_CLOCK + ms += frame_timer.getTimeMilliseconds (); +#endif //USE_BT_CLOCK + frame_counter++; + if (frame_counter > 50) + { + min_ms = ms < min_ms ? ms : min_ms; + max_ms = ms > max_ms ? ms : max_ms; + sum_ms += ms; + sum_ms_samples++; + btScalar mean_ms = (btScalar)sum_ms/(btScalar)sum_ms_samples; + printf("%d rays in %d ms %d %d %f\n", NUMRAYS * frame_counter, ms, min_ms, max_ms, mean_ms); + ms = 0; + frame_counter = 0; + } +#endif + } + + void draw () + { +#ifdef USE_GRAPHICAL_BENCHMARK + glDisable (GL_LIGHTING); + glColor3f (0.0, 1.0, 0.0); + glBegin (GL_LINES); + int i; + + for (i = 0; i < NUMRAYS; i++) + { + glVertex3f (source[i][0], source[i][1], source[i][2]); + glVertex3f (hit[i][0], hit[i][1], hit[i][2]); + } + glEnd (); + glColor3f (1.0, 1.0, 1.0); + glBegin (GL_LINES); + for (i = 0; i < NUMRAYS; i++) + { + glVertex3f (hit[i][0], hit[i][1], hit[i][2]); + glVertex3f (hit[i][0] + normal[i][0], hit[i][1] + normal[i][1], hit[i][2] + normal[i][2]); + } + glEnd (); + glColor3f (0.0, 1.0, 1.0); + glBegin (GL_POINTS); + for ( i = 0; i < NUMRAYS; i++) + { + glVertex3f (hit[i][0], hit[i][1], hit[i][2]); + } + glEnd (); + glEnable (GL_LIGHTING); +#endif //USE_GRAPHICAL_BENCHMARK + + } +}; + + +static btRaycastBar2 raycastBar; + + +void BenchmarkDemo::clientMoveAndDisplay() +{ +#ifdef USE_GRAPHICAL_BENCHMARK + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +#endif //USE_GRAPHICAL_BENCHMARK + + //simple dynamics world doesn't handle fixed-time-stepping + //float ms = getDeltaTimeMicroseconds(); + + ///step the simulation + if (m_dynamicsWorld) + { + m_dynamicsWorld->stepSimulation(btScalar(1./60.)); + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + } + + if (m_benchmark==7) + { + castRays(); + + raycastBar.draw(); + + } + + renderme(); + +#ifdef USE_GRAPHICAL_BENCHMARK + glFlush(); + + swapBuffers(); +#endif //USE_GRAPHICAL_BENCHMARK + +} + + + +void BenchmarkDemo::displayCallback(void) +{ + +#ifdef USE_GRAPHICAL_BENCHMARK + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + //optional but useful: debug drawing to detect problems + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + glFlush(); + swapBuffers(); +#endif //USE_GRAPHICAL_BENCHMARK +} + + + + +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); + + ///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); + +#if USE_PARALLEL_DISPATCHER_BENCHMARK + + int maxNumOutstandingTasks = 4; +#ifdef _WIN32 + Win32ThreadSupport* threadSupportCollision = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo( "collision",processCollisionTask, createCollisionLocalStoreMemory,maxNumOutstandingTasks)); +#elif defined (USE_PTHREADS) + PosixThreadSupport::ThreadConstructionInfo collisionConstructionInfo( "collision",processCollisionTask, createCollisionLocalStoreMemory,maxNumOutstandingTasks); + PosixThreadSupport* threadSupportCollision = new PosixThreadSupport(collisionConstructionInfo); +#endif + //SequentialThreadSupport::SequentialThreadConstructionInfo sci("spuCD", processCollisionTask, createCollisionLocalStoreMemory); + //SequentialThreadSupport* seq = new SequentialThreadSupport(sci); + m_dispatcher = new SpuGatheringCollisionDispatcher(threadSupportCollision,1,m_collisionConfiguration); +#endif + + + ///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_overlappingPairCache = new btAxisSweep3(worldAabbMin,worldAabbMax,3500,pairCache); +// m_overlappingPairCache = new btSimpleBroadphase(); +// m_overlappingPairCache = new btDbvtBroadphase(); + + + ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) +#ifdef USE_PARALLEL_DISPATCHER_BENCHMARK + + btThreadSupportInterface* thread = createSolverThreadSupport(4); + btConstraintSolver* sol = new btParallelConstraintSolver(thread); +#else + btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; +#endif //USE_PARALLEL_DISPATCHER_BENCHMARK + + + m_solver = sol; + + btDiscreteDynamicsWorld* dynamicsWorld; + m_dynamicsWorld = dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_solver,m_collisionConfiguration); + +#ifdef USE_PARALLEL_DISPATCHER_BENCHMARK + dynamicsWorld->getSimulationIslandManager()->setSplitIslands(false); +#endif //USE_PARALLEL_DISPATCHER_BENCHMARK + + ///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_defaultContactProcessingThreshold = 0.f;//used when creating bodies: body->setContactProcessingThreshold(...); + + + m_dynamicsWorld->setGravity(btVector3(0,-10,0)); + + if (m_benchmark<5) + { + ///create a few basic rigid bodies + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(250.),btScalar(50.),btScalar(250.))); + // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),0); + + m_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + + //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here: + { + btScalar mass(0.); + + //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) + groundShape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + //add the body to the dynamics world + m_dynamicsWorld->addRigidBody(body); + } + } + + switch (m_benchmark) + { + case 1: + { + createTest1(); + break; + } + case 2: + { + createTest2(); + break; + } + case 3: + { + createTest3(); + break; + } + case 4: + { + createTest4(); + break; + } + case 5: + { + createTest5(); + break; + } + case 6: + { + createTest6(); + break; + } + case 7: + { + createTest7(); + break; + } + + + default: + { + } + } + + + clientResetScene(); +} + + +void BenchmarkDemo::createTest1() +{ + // 3000 + int size = 8; + const float cubeSize = 1.0f; + float spacing = cubeSize; + btVector3 pos(0.0f, cubeSize * 2,0.f); + float offset = -size * (cubeSize * 2.0f + spacing) * 0.5f; + + btBoxShape* blockShape = new btBoxShape(btVector3(cubeSize-COLLISION_RADIUS,cubeSize-COLLISION_RADIUS,cubeSize-COLLISION_RADIUS)); + btVector3 localInertia(0,0,0); + float mass = 2.f; + blockShape->calculateLocalInertia(mass,localInertia); + + btTransform trans; + trans.setIdentity(); + + for(int k=0;k<47;k++) { + for(int j=0;jcalculateLocalInertia(mass,localInertia); + +// btScalar diffX = boxSize[0] * 1.0f; + btScalar diffY = boxSize[1] * 1.0f; + btScalar diffZ = boxSize[2] * 1.0f; + + btScalar offset = -stackSize * (diffZ * 2.0f) * 0.5f; + btVector3 pos(0.0f, diffY, 0.0f); + + btTransform trans; + trans.setIdentity(); + + while(stackSize) { + for(int i=0;icalculateLocalInertia(mass,localInertia); + + + btScalar diffX = boxSize[0]*1.02f; + btScalar diffY = boxSize[1]*1.02f; + btScalar diffZ = boxSize[2]*1.02f; + + btScalar offsetX = -stackSize * (diffX * 2.0f + space) * 0.5f; + btScalar offsetZ = -stackSize * (diffZ * 2.0f + space) * 0.5f; + while(stackSize) { + for(int j=0;jlocalCreateRigidBody(mass,trans,blockShape); + + + } + } + offsetX += diffX; + offsetZ += diffZ; + pos[1] += (diffY * 2.0f + space); + stackSize--; + } + +} + + const btVector3 rotate( const btQuaternion& quat, const btVector3 & vec ) +{ + float tmpX, tmpY, tmpZ, tmpW; + tmpX = ( ( ( quat.getW() * vec.getX() ) + ( quat.getY() * vec.getZ() ) ) - ( quat.getZ() * vec.getY() ) ); + tmpY = ( ( ( quat.getW() * vec.getY() ) + ( quat.getZ() * vec.getX() ) ) - ( quat.getX() * vec.getZ() ) ); + tmpZ = ( ( ( quat.getW() * vec.getZ() ) + ( quat.getX() * vec.getY() ) ) - ( quat.getY() * vec.getX() ) ); + tmpW = ( ( ( quat.getX() * vec.getX() ) + ( quat.getY() * vec.getY() ) ) + ( quat.getZ() * vec.getZ() ) ); + return btVector3( + ( ( ( ( tmpW * quat.getX() ) + ( tmpX * quat.getW() ) ) - ( tmpY * quat.getZ() ) ) + ( tmpZ * quat.getY() ) ), + ( ( ( ( tmpW * quat.getY() ) + ( tmpY * quat.getW() ) ) - ( tmpZ * quat.getX() ) ) + ( tmpX * quat.getZ() ) ), + ( ( ( ( tmpW * quat.getZ() ) + ( tmpZ * quat.getW() ) ) - ( tmpX * quat.getY() ) ) + ( tmpY * quat.getX() ) ) + ); +} + +void BenchmarkDemo::createTowerCircle(const btVector3& offsetPosition,int stackSize,int rotSize,const btVector3& boxSize) +{ + + btBoxShape* blockShape = new btBoxShape(btVector3(boxSize[0]-COLLISION_RADIUS,boxSize[1]-COLLISION_RADIUS,boxSize[2]-COLLISION_RADIUS)); + + btTransform trans; + trans.setIdentity(); + + float mass = 1.f; + btVector3 localInertia(0,0,0); + blockShape->calculateLocalInertia(mass,localInertia); + + + float radius = 1.3f * rotSize * boxSize[0] / SIMD_PI; + + // create active boxes + btQuaternion rotY(0,1,0,0); + float posY = boxSize[1]; + + for(int i=0;icalculateLocalInertia(mass,localInertia); + + btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + m_ownerWorld->addRigidBody(body); + + return body; + } + +public: + RagDoll (btDynamicsWorld* ownerWorld, const btVector3& positionOffset,btScalar scale) + : m_ownerWorld (ownerWorld) + { + // Setup the geometry + m_shapes[BODYPART_PELVIS] = new btCapsuleShape(btScalar(0.15)*scale, btScalar(0.20)*scale); + m_shapes[BODYPART_SPINE] = new btCapsuleShape(btScalar(0.15)*scale, btScalar(0.28)*scale); + m_shapes[BODYPART_HEAD] = new btCapsuleShape(btScalar(0.10)*scale, btScalar(0.05)*scale); + m_shapes[BODYPART_LEFT_UPPER_LEG] = new btCapsuleShape(btScalar(0.07)*scale, btScalar(0.45)*scale); + m_shapes[BODYPART_LEFT_LOWER_LEG] = new btCapsuleShape(btScalar(0.05)*scale, btScalar(0.37)*scale); + m_shapes[BODYPART_RIGHT_UPPER_LEG] = new btCapsuleShape(btScalar(0.07)*scale, btScalar(0.45)*scale); + m_shapes[BODYPART_RIGHT_LOWER_LEG] = new btCapsuleShape(btScalar(0.05)*scale, btScalar(0.37)*scale); + m_shapes[BODYPART_LEFT_UPPER_ARM] = new btCapsuleShape(btScalar(0.05)*scale, btScalar(0.33)*scale); + m_shapes[BODYPART_LEFT_LOWER_ARM] = new btCapsuleShape(btScalar(0.04)*scale, btScalar(0.25)*scale); + m_shapes[BODYPART_RIGHT_UPPER_ARM] = new btCapsuleShape(btScalar(0.05)*scale, btScalar(0.33)*scale); + m_shapes[BODYPART_RIGHT_LOWER_ARM] = new btCapsuleShape(btScalar(0.04)*scale, btScalar(0.25)*scale); + + // Setup all the rigid bodies + btTransform offset; offset.setIdentity(); + offset.setOrigin(positionOffset); + + btTransform transform; + transform.setIdentity(); + transform.setOrigin(scale*btVector3(btScalar(0.), btScalar(1.), btScalar(0.))); + m_bodies[BODYPART_PELVIS] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_PELVIS]); + + transform.setIdentity(); + transform.setOrigin(scale*btVector3(btScalar(0.), btScalar(1.2), btScalar(0.))); + m_bodies[BODYPART_SPINE] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_SPINE]); + + transform.setIdentity(); + transform.setOrigin(scale*btVector3(btScalar(0.), btScalar(1.6), btScalar(0.))); + m_bodies[BODYPART_HEAD] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_HEAD]); + + transform.setIdentity(); + transform.setOrigin(scale*btVector3(btScalar(-0.18), btScalar(0.65), btScalar(0.))); + m_bodies[BODYPART_LEFT_UPPER_LEG] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_LEFT_UPPER_LEG]); + + transform.setIdentity(); + transform.setOrigin(scale*btVector3(btScalar(-0.18), btScalar(0.2), btScalar(0.))); + m_bodies[BODYPART_LEFT_LOWER_LEG] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_LEFT_LOWER_LEG]); + + transform.setIdentity(); + transform.setOrigin(scale*btVector3(btScalar(0.18), btScalar(0.65), btScalar(0.))); + m_bodies[BODYPART_RIGHT_UPPER_LEG] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_RIGHT_UPPER_LEG]); + + transform.setIdentity(); + transform.setOrigin(scale*btVector3(btScalar(0.18), btScalar(0.2), btScalar(0.))); + m_bodies[BODYPART_RIGHT_LOWER_LEG] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_RIGHT_LOWER_LEG]); + + transform.setIdentity(); + transform.setOrigin(scale*btVector3(btScalar(-0.35), btScalar(1.45), btScalar(0.))); + transform.getBasis().setEulerZYX(0,0,M_PI_2); + m_bodies[BODYPART_LEFT_UPPER_ARM] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_LEFT_UPPER_ARM]); + + transform.setIdentity(); + transform.setOrigin(scale*btVector3(btScalar(-0.7), btScalar(1.45), btScalar(0.))); + transform.getBasis().setEulerZYX(0,0,M_PI_2); + m_bodies[BODYPART_LEFT_LOWER_ARM] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_LEFT_LOWER_ARM]); + + transform.setIdentity(); + transform.setOrigin(scale*btVector3(btScalar(0.35), btScalar(1.45), btScalar(0.))); + transform.getBasis().setEulerZYX(0,0,-M_PI_2); + m_bodies[BODYPART_RIGHT_UPPER_ARM] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_RIGHT_UPPER_ARM]); + + transform.setIdentity(); + transform.setOrigin(scale*btVector3(btScalar(0.7), btScalar(1.45), btScalar(0.))); + transform.getBasis().setEulerZYX(0,0,-M_PI_2); + m_bodies[BODYPART_RIGHT_LOWER_ARM] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_RIGHT_LOWER_ARM]); + + // Setup some damping on the m_bodies + for (int i = 0; i < BODYPART_COUNT; ++i) + { + m_bodies[i]->setDamping(btScalar(0.05), btScalar(0.85)); + m_bodies[i]->setDeactivationTime(btScalar(0.8)); + m_bodies[i]->setSleepingThresholds(btScalar(1.6), btScalar(2.5)); + } + + // Now setup the constraints + btHingeConstraint* hingeC; + btConeTwistConstraint* coneC; + + btTransform localA, localB; + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,M_PI_2,0); localA.setOrigin(scale*btVector3(btScalar(0.), btScalar(0.15), btScalar(0.))); + localB.getBasis().setEulerZYX(0,M_PI_2,0); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(-0.15), btScalar(0.))); + hingeC = new btHingeConstraint(*m_bodies[BODYPART_PELVIS], *m_bodies[BODYPART_SPINE], localA, localB); + hingeC->setLimit(btScalar(-M_PI_4), btScalar(M_PI_2)); + m_joints[JOINT_PELVIS_SPINE] = hingeC; + m_ownerWorld->addConstraint(m_joints[JOINT_PELVIS_SPINE], true); + + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,0,M_PI_2); localA.setOrigin(scale*btVector3(btScalar(0.), btScalar(0.30), btScalar(0.))); + localB.getBasis().setEulerZYX(0,0,M_PI_2); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(-0.14), btScalar(0.))); + coneC = new btConeTwistConstraint(*m_bodies[BODYPART_SPINE], *m_bodies[BODYPART_HEAD], localA, localB); + coneC->setLimit(M_PI_4, M_PI_4, M_PI_2); + m_joints[JOINT_SPINE_HEAD] = coneC; + m_ownerWorld->addConstraint(m_joints[JOINT_SPINE_HEAD], true); + + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,0,-M_PI_4*5); localA.setOrigin(scale*btVector3(btScalar(-0.18), btScalar(-0.10), btScalar(0.))); + localB.getBasis().setEulerZYX(0,0,-M_PI_4*5); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(0.225), btScalar(0.))); + coneC = new btConeTwistConstraint(*m_bodies[BODYPART_PELVIS], *m_bodies[BODYPART_LEFT_UPPER_LEG], localA, localB); + coneC->setLimit(M_PI_4, M_PI_4, 0); + m_joints[JOINT_LEFT_HIP] = coneC; + m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_HIP], true); + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,M_PI_2,0); localA.setOrigin(scale*btVector3(btScalar(0.), btScalar(-0.225), btScalar(0.))); + localB.getBasis().setEulerZYX(0,M_PI_2,0); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(0.185), btScalar(0.))); + hingeC = new btHingeConstraint(*m_bodies[BODYPART_LEFT_UPPER_LEG], *m_bodies[BODYPART_LEFT_LOWER_LEG], localA, localB); + hingeC->setLimit(btScalar(0), btScalar(M_PI_2)); + m_joints[JOINT_LEFT_KNEE] = hingeC; + m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_KNEE], true); + + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,0,M_PI_4); localA.setOrigin(scale*btVector3(btScalar(0.18), btScalar(-0.10), btScalar(0.))); + localB.getBasis().setEulerZYX(0,0,M_PI_4); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(0.225), btScalar(0.))); + coneC = new btConeTwistConstraint(*m_bodies[BODYPART_PELVIS], *m_bodies[BODYPART_RIGHT_UPPER_LEG], localA, localB); + coneC->setLimit(M_PI_4, M_PI_4, 0); + m_joints[JOINT_RIGHT_HIP] = coneC; + m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_HIP], true); + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,M_PI_2,0); localA.setOrigin(scale*btVector3(btScalar(0.), btScalar(-0.225), btScalar(0.))); + localB.getBasis().setEulerZYX(0,M_PI_2,0); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(0.185), btScalar(0.))); + hingeC = new btHingeConstraint(*m_bodies[BODYPART_RIGHT_UPPER_LEG], *m_bodies[BODYPART_RIGHT_LOWER_LEG], localA, localB); + hingeC->setLimit(btScalar(0), btScalar(M_PI_2)); + m_joints[JOINT_RIGHT_KNEE] = hingeC; + m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_KNEE], true); + + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,0,M_PI); localA.setOrigin(scale*btVector3(btScalar(-0.2), btScalar(0.15), btScalar(0.))); + localB.getBasis().setEulerZYX(0,0,M_PI_2); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(-0.18), btScalar(0.))); + coneC = new btConeTwistConstraint(*m_bodies[BODYPART_SPINE], *m_bodies[BODYPART_LEFT_UPPER_ARM], localA, localB); + coneC->setLimit(M_PI_2, M_PI_2, 0); + m_joints[JOINT_LEFT_SHOULDER] = coneC; + m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_SHOULDER], true); + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,M_PI_2,0); localA.setOrigin(scale*btVector3(btScalar(0.), btScalar(0.18), btScalar(0.))); + localB.getBasis().setEulerZYX(0,M_PI_2,0); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(-0.14), btScalar(0.))); + hingeC = new btHingeConstraint(*m_bodies[BODYPART_LEFT_UPPER_ARM], *m_bodies[BODYPART_LEFT_LOWER_ARM], localA, localB); + hingeC->setLimit(btScalar(-M_PI_2), btScalar(0)); + m_joints[JOINT_LEFT_ELBOW] = hingeC; + m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_ELBOW], true); + + + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,0,0); localA.setOrigin(scale*btVector3(btScalar(0.2), btScalar(0.15), btScalar(0.))); + localB.getBasis().setEulerZYX(0,0,M_PI_2); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(-0.18), btScalar(0.))); + coneC = new btConeTwistConstraint(*m_bodies[BODYPART_SPINE], *m_bodies[BODYPART_RIGHT_UPPER_ARM], localA, localB); + coneC->setLimit(M_PI_2, M_PI_2, 0); + m_joints[JOINT_RIGHT_SHOULDER] = coneC; + m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_SHOULDER], true); + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,M_PI_2,0); localA.setOrigin(scale*btVector3(btScalar(0.), btScalar(0.18), btScalar(0.))); + localB.getBasis().setEulerZYX(0,M_PI_2,0); localB.setOrigin(scale*btVector3(btScalar(0.), btScalar(-0.14), btScalar(0.))); + hingeC = new btHingeConstraint(*m_bodies[BODYPART_RIGHT_UPPER_ARM], *m_bodies[BODYPART_RIGHT_LOWER_ARM], localA, localB); + hingeC->setLimit(btScalar(-M_PI_2), btScalar(0)); + m_joints[JOINT_RIGHT_ELBOW] = hingeC; + m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_ELBOW], true); + } + + virtual ~RagDoll () + { + int i; + + // Remove all constraints + for ( i = 0; i < JOINT_COUNT; ++i) + { + m_ownerWorld->removeConstraint(m_joints[i]); + delete m_joints[i]; m_joints[i] = 0; + } + + // Remove all bodies and shapes + for ( i = 0; i < BODYPART_COUNT; ++i) + { + m_ownerWorld->removeRigidBody(m_bodies[i]); + + delete m_bodies[i]->getMotionState(); + + delete m_bodies[i]; m_bodies[i] = 0; + delete m_shapes[i]; m_shapes[i] = 0; + } + } +}; + +void BenchmarkDemo::createTest3() +{ + setCameraDistance(btScalar(50.)); + + int size = 16; + + float sizeX = 1.f; + float sizeY = 1.f; + + //int rc=0; + + btScalar scale(3.5); + btVector3 pos(0.0f, sizeY, 0.0f); + while(size) { + float offset = -size * (sizeX * 6.0f) * 0.5f; + for(int i=0;isetLocalScaling(btVector3(scaling,scaling,scaling)); + + for (int i=0;iaddPoint(vtx*btScalar(1./scaling)); + } + + //this will enable polyhedral contact clipping, better quality, slightly slower + //convexHullShape->initializePolyhedralFeatures(); + + btTransform trans; + trans.setIdentity(); + + float mass = 1.f; + btVector3 localInertia(0,0,0); + convexHullShape->calculateLocalInertia(mass,localInertia); + + for(int k=0;k<15;k++) { + for(int j=0;jaddIndexedMesh(part,PHY_SHORT); + + bool useQuantizedAabbCompression = true; + btBvhTriangleMeshShape* trimeshShape = new btBvhTriangleMeshShape(meshInterface,useQuantizedAabbCompression); + btVector3 localInertia(0,0,0); + trans.setOrigin(btVector3(0,-25,0)); + + btRigidBody* body = localCreateRigidBody(0,trans,trimeshShape); + body->setFriction (btScalar(0.9)); + + } + +} + + +void BenchmarkDemo::createTest5() +{ + setCameraDistance(btScalar(250.)); + btVector3 boxSize(1.5f,1.5f,1.5f); + float boxMass = 1.0f; + float sphereRadius = 1.5f; + float sphereMass = 1.0f; + float capsuleHalf = 2.0f; + float capsuleRadius = 1.0f; + float capsuleMass = 1.0f; + + { + int size = 10; + int height = 10; + + const float cubeSize = boxSize[0]; + float spacing = 2.0f; + btVector3 pos(0.0f, 20.0f, 0.0f); + float offset = -size * (cubeSize * 2.0f + spacing) * 0.5f; + + int numBodies = 0; + + for(int k=0;kaddPoint(vtx); + } + + btTransform trans; + trans.setIdentity(); + + float mass = 1.f; + btVector3 localInertia(0,0,0); + convexHullShape->calculateLocalInertia(mass,localInertia); + + + { + int size = 10; + int height = 10; + + const float cubeSize = boxSize[0]; + float spacing = 2.0f; + btVector3 pos(0.0f, 20.0f, 0.0f); + float offset = -size * (cubeSize * 2.0f + spacing) * 0.5f; + + + for(int k=0;kgetNumCollisionObjects()-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;jgetShapeType() != 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 + + btRigidBody* body = new btRigidBody(mass,0,shape,localInertia); + body->setWorldTransform(startTransform); + body->setContactProcessingThreshold(m_defaultContactProcessingThreshold); + m_dynamicsWorld->addRigidBody(body); + + return body; +} +#endif //USE_GRAPHICAL_BENCHMARK + diff --git a/Demos/Benchmarks/BenchmarkDemo.h b/Demos/Benchmarks/BenchmarkDemo.h new file mode 100644 index 0000000..b9f1052 --- /dev/null +++ b/Demos/Benchmarks/BenchmarkDemo.h @@ -0,0 +1,265 @@ +/* +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 BENCHMARK_DEMO_H +#define BENCHMARK_DEMO_H + + +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btTransform.h" + +class btDynamicsWorld; + +#define NUMRAYS 500 + +class btRigidBody; +class btBroadphaseInterface; +class btCollisionShape; +class btOverlappingPairCache; +class btCollisionDispatcher; +class btConstraintSolver; +struct btCollisionAlgorithmCreateFunc; +class btDefaultCollisionConfiguration; + + +#ifndef USE_GRAPHICAL_BENCHMARK +///empty placeholder +class DemoApplication +{ +protected: + + btDynamicsWorld* m_dynamicsWorld; + btScalar m_defaultContactProcessingThreshold; + +public: + DemoApplication() + :m_defaultContactProcessingThreshold(BT_LARGE_FLOAT) + { + } + virtual void myinit() {} + virtual btDynamicsWorld* getDynamicsWorld() + { + return m_dynamicsWorld; + } + + btScalar getDeltaTimeMicroseconds() + { + return 1.f; + } + + void renderme() {} + void setCameraDistance(btScalar dist){} + void clientResetScene(){} + btRigidBody* localCreateRigidBody(float mass, const btTransform& startTransform,btCollisionShape* shape); + +}; +///BenchmarkDemo is provides several performance tests +#define PlatformDemoApplication DemoApplication +#else //USE_GRAPHICAL_BENCHMARK + +#ifdef _WINDOWS +#include "Win32DemoApplication.h" +#define PlatformDemoApplication Win32DemoApplication +#else +#include "GlutDemoApplication.h" +#define PlatformDemoApplication GlutDemoApplication +#endif + +#endif //USE_GRAPHICAL_BENCHMARK + + +class BenchmarkDemo : public PlatformDemoApplication +{ + + //keep the collision shapes, for deletion/cleanup + btAlignedObjectArray m_collisionShapes; + + btAlignedObjectArray m_ragdolls; + + btBroadphaseInterface* m_overlappingPairCache; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + int m_benchmark; + + void createTest1(); + void createTest2(); + void createTest3(); + void createTest4(); + void createTest5(); + void createTest6(); + void createTest7(); + + void createWall(const btVector3& offsetPosition,int stackSize,const btVector3& boxSize); + void createPyramid(const btVector3& offsetPosition,int stackSize,const btVector3& boxSize); + void createTowerCircle(const btVector3& offsetPosition,int stackSize,int rotSize,const btVector3& boxSize); + void createLargeMeshBody(); + + + class SpuBatchRaycaster* m_batchRaycaster; + class btThreadSupportInterface* m_batchRaycasterThreadSupport; + + void castRays(); + void initRays(); + + public: + + BenchmarkDemo(int benchmark) + :m_benchmark(benchmark) + { + } + virtual ~BenchmarkDemo() + { + exitPhysics(); + } + void initPhysics(); + + void exitPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + + + +}; + +class BenchmarkDemo1 : public BenchmarkDemo +{ +public: + BenchmarkDemo1() + :BenchmarkDemo(1) + { + } + + static DemoApplication* Create() + { + BenchmarkDemo1* demo = new BenchmarkDemo1; + demo->myinit(); + demo->initPhysics(); + return demo; + } +}; + +class BenchmarkDemo2 : public BenchmarkDemo +{ +public: + BenchmarkDemo2() + :BenchmarkDemo(2) + { + } + + static DemoApplication* Create() + { + BenchmarkDemo2* demo = new BenchmarkDemo2; + demo->myinit(); + demo->initPhysics(); + return demo; + } +}; + +class BenchmarkDemo3 : public BenchmarkDemo +{ +public: + BenchmarkDemo3() + :BenchmarkDemo(3) + { + } + + static DemoApplication* Create() + { + BenchmarkDemo3* demo = new BenchmarkDemo3; + demo->myinit(); + demo->initPhysics(); + return demo; + } +}; + +class BenchmarkDemo4 : public BenchmarkDemo +{ +public: + BenchmarkDemo4() + :BenchmarkDemo(4) + { + } + + static DemoApplication* Create() + { + BenchmarkDemo4* demo = new BenchmarkDemo4; + demo->myinit(); + demo->initPhysics(); + return demo; + } +}; + + +class BenchmarkDemo5 : public BenchmarkDemo +{ +public: + BenchmarkDemo5() + :BenchmarkDemo(5) + { + } + + static DemoApplication* Create() + { + BenchmarkDemo5* demo = new BenchmarkDemo5; + demo->myinit(); + demo->initPhysics(); + return demo; + } +}; + + +class BenchmarkDemo6 : public BenchmarkDemo +{ +public: + BenchmarkDemo6() + :BenchmarkDemo(6) + { + } + + static DemoApplication* Create() + { + BenchmarkDemo6* demo = new BenchmarkDemo6; + demo->myinit(); + demo->initPhysics(); + return demo; + } +}; + +class BenchmarkDemo7 : public BenchmarkDemo +{ +public: + BenchmarkDemo7() + :BenchmarkDemo(7) + { + } + + static DemoApplication* Create() + { + BenchmarkDemo7* demo = new BenchmarkDemo7; + demo->myinit(); + demo->initPhysics(); + return demo; + } +}; + +#endif //BENCHMARK_DEMO_H + diff --git a/Demos/Benchmarks/CMakeLists.txt b/Demos/Benchmarks/CMakeLists.txt new file mode 100644 index 0000000..bcd771f --- /dev/null +++ b/Demos/Benchmarks/CMakeLists.txt @@ -0,0 +1,107 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# You shouldn't have to modify anything below this line +######################################################## + +IF (USE_GRAPHICAL_BENCHMARK) +IF (USE_GLUT) + INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL + ) + + IF (USE_MULTITHREADED_BENCHMARK) + INCLUDE_DIRECTORIES( ${VECTOR_MATH_INCLUDE} ) + LINK_LIBRARIES( OpenGLSupport BulletMultiThreaded BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}) + ELSE() + LINK_LIBRARIES( OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}) + ENDIF(USE_MULTITHREADED_BENCHMARK) + + IF (WIN32) + ADD_EXECUTABLE(AppBenchmarks + main.cpp + BenchmarkDemo.cpp + BenchmarkDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) + ELSE() + ADD_EXECUTABLE(AppBenchmarks + main.cpp + BenchmarkDemo.cpp + BenchmarkDemo.h + ) + ENDIF () + IF (WIN32) + IF (NOT INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppBenchmarks + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppBenchmarks + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES) + IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppBenchmarks PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppBenchmarks PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppBenchmarks PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") + ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + + ENDIF(WIN32) +ELSE (USE_GLUT) + INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL + ) + + IF (USE_MULTITHREADED_BENCHMARK) + INCLUDE_DIRECTORIES( ${VECTOR_MATH_INCLUDE} ) + LINK_LIBRARIES( + OpenGLSupport BulletMultiThreaded BulletDynamics BulletCollision LinearMath ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + ELSE() + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + ENDIF() + + ADD_EXECUTABLE(AppBenchmarks + WIN32 + ../OpenGL/Win32AppMain.cpp + BenchmarkDemo.cpp + BenchmarkDemo.h + Win32BenchmarkDemo.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) +ENDIF (USE_GLUT) +ELSE (USE_GRAPHICAL_BENCHMARK) + + INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL + ) + + IF (USE_MULTITHREADED_BENCHMARK) + LINK_LIBRARIES( BulletMultiThreaded BulletDynamics BulletCollision LinearMath ) + ELSE() + LINK_LIBRARIES( BulletDynamics BulletCollision LinearMath ) + ENDIF() + + + ADD_EXECUTABLE(AppBenchmarks + main.cpp + BenchmarkDemo.cpp + ) +ENDIF (USE_GRAPHICAL_BENCHMARK) \ No newline at end of file diff --git a/Demos/Benchmarks/Taru.mdl b/Demos/Benchmarks/Taru.mdl new file mode 100644 index 0000000..73f708c --- /dev/null +++ b/Demos/Benchmarks/Taru.mdl @@ -0,0 +1,49 @@ +#define TaruVtxCount 43 +#define TaruIdxCount 132 + +static float TaruVtx[] = { +1.08664f,-1.99237f,0.0f, +0.768369f,-1.99237f,-0.768369f, +1.28852f,1.34412e-007f,-1.28852f, +1.82224f,1.90735e-007f,0.0f, +0.0f,-1.99237f,-1.08664f, +0.0f,0.0f,-1.82224f, +0.0f,-1.99237f,-1.08664f, +-0.768369f,-1.99237f,-0.768369f, +-1.28852f,1.34412e-007f,-1.28852f, +0.0f,0.0f,-1.82224f, +-1.08664f,-1.99237f,1.82086e-007f, +-1.82224f,1.90735e-007f,1.59305e-007f, +-0.768369f,-1.99237f,0.76837f, +-1.28852f,2.47058e-007f,1.28852f, +1.42495e-007f,-1.99237f,1.08664f, +2.38958e-007f,2.70388e-007f,1.82224f, +0.768369f,-1.99237f,0.768369f, +1.28852f,2.47058e-007f,1.28852f, +0.768369f,1.99237f,-0.768369f, +1.08664f,1.99237f,0.0f, +0.0f,1.99237f,-1.08664f, +-0.768369f,1.99237f,-0.768369f, +0.0f,1.99237f,-1.08664f, +-1.08664f,1.99237f,0.0f, +-0.768369f,1.99237f,0.768369f, +1.42495e-007f,1.99237f,1.08664f, +0.768369f,1.99237f,0.768369f, +1.42495e-007f,-1.99237f,1.08664f, +-0.768369f,-1.99237f,0.76837f, +-1.08664f,-1.99237f,1.82086e-007f, +-0.768369f,-1.99237f,-0.768369f, +0.0f,-1.99237f,-1.08664f, +0.768369f,-1.99237f,-0.768369f, +1.08664f,-1.99237f,0.0f, +0.768369f,-1.99237f,0.768369f, +0.768369f,1.99237f,-0.768369f, +0.0f,1.99237f,-1.08664f, +-0.768369f,1.99237f,-0.768369f, +-1.08664f,1.99237f,0.0f, +-0.768369f,1.99237f,0.768369f, +1.42495e-007f,1.99237f,1.08664f, +0.768369f,1.99237f,0.768369f, +1.08664f,1.99237f,0.0f, +}; + diff --git a/Demos/Benchmarks/Win32BenchmarkDemo.cpp b/Demos/Benchmarks/Win32BenchmarkDemo.cpp new file mode 100644 index 0000000..486f308 --- /dev/null +++ b/Demos/Benchmarks/Win32BenchmarkDemo.cpp @@ -0,0 +1,25 @@ +#ifdef _WINDOWS +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "BenchmarkDemo.h" + +///The 'createDemo' function is called from Bullet/Demos/OpenGL/Win32AppMain.cpp to instantiate this particular demo +DemoApplication* createDemo() +{ + return new BenchmarkDemo(1); +} + +#endif diff --git a/Demos/Benchmarks/landscape.mdl b/Demos/Benchmarks/landscape.mdl new file mode 100644 index 0000000..6b879b2 --- /dev/null +++ b/Demos/Benchmarks/landscape.mdl @@ -0,0 +1,84369 @@ +#define Landscape02VtxCount 1980 +#define Landscape02IdxCount 11310 +#include "LinearMath/btScalar.h" + +btScalar Landscape02Vtx[] = { +-250.0f,2.99192f,113.281f, +-250.0f,2.18397f,117.188f, +-246.094f,1.62262f,113.281f, +-246.094f,1.51628f,117.188f, +-242.188f,0.847411f,113.281f, +-242.188f,0.628327f,117.188f, +-238.281f,-0.697436f,113.281f, +-238.281f,-0.567933f,117.188f, +-234.375f,-2.65115f,113.281f, +-234.375f,-2.01568f,117.188f, +-230.469f,-3.82201f,113.281f, +-230.469f,-3.41089f,117.188f, +-226.563f,-3.99138f,113.281f, +-226.563f,-3.82758f,117.188f, +-222.656f,-5.51066f,113.281f, +-222.656f,-5.01586f,117.188f, +-218.75f,-5.62904f,113.281f, +-218.75f,-4.74822f,117.188f, +-214.844f,-4.90514f,113.281f, +-214.844f,-3.30853f,117.188f, +-210.938f,-2.9572f,113.281f, +-210.938f,-2.32499f,117.188f, +-207.031f,-2.44242f,113.281f, +-207.031f,-1.71509f,117.188f, +-203.125f,-1.5086f,113.281f, +-203.125f,-1.19203f,117.188f, +-199.219f,-0.130838f,113.281f, +-199.219f,0.219498f,117.188f, +-195.313f,0.985417f,113.281f, +-195.313f,1.66304f,117.188f, +-191.406f,3.20064f,113.281f, +-191.406f,4.35105f,117.188f, +-187.5f,4.6779f,113.281f, +-187.5f,6.33228f,117.188f, +-183.594f,6.16902f,113.281f, +-183.594f,8.00972f,117.188f, +-179.688f,8.18835f,113.281f, +-179.688f,9.71486f,117.188f, +-175.781f,9.35082f,113.281f, +-175.781f,10.7727f,117.188f, +-171.875f,9.50665f,113.281f, +-171.875f,11.358f,117.188f, +-167.969f,12.1301f,113.281f, +-167.969f,12.5239f,117.188f, +-164.063f,14.8728f,113.281f, +-164.063f,14.6278f,117.188f, +-160.156f,16.3761f,113.281f, +-160.156f,17.2069f,117.188f, +-156.25f,18.5367f,113.281f, +-156.25f,19.9779f,117.188f, +-152.344f,22.4636f,113.281f, +-152.344f,23.4607f,117.188f, +-148.438f,26.1459f,113.281f, +-148.438f,26.6108f,117.188f, +-144.531f,28.6071f,113.281f, +-144.531f,28.4635f,117.188f, +-140.625f,30.2795f,113.281f, +-140.625f,29.7705f,117.188f, +-136.719f,32.2229f,113.281f, +-136.719f,31.0684f,117.188f, +-132.813f,32.8919f,113.281f, +-132.813f,31.8395f,117.188f, +-128.906f,33.5143f,113.281f, +-128.906f,32.1658f,117.188f, +-125.0f,34.6963f,113.281f, +-125.0f,34.7478f,117.188f, +-121.094f,37.3995f,113.281f, +-121.094f,36.0624f,117.188f, +-117.188f,38.0464f,113.281f, +-117.188f,37.2702f,117.188f, +-113.281f,37.8506f,113.281f, +-113.281f,37.3474f,117.188f, +-109.375f,37.8984f,113.281f, +-109.375f,37.242f,117.188f, +-105.469f,36.0464f,113.281f, +-105.469f,36.1544f,117.188f, +-101.563f,34.1136f,113.281f, +-101.563f,33.403f,117.188f, +-97.6563f,32.0925f,113.281f, +-97.6563f,31.294f,117.188f, +-93.75f,29.8306f,113.281f, +-93.75f,29.4961f,117.188f, +-89.8438f,30.1499f,113.281f, +-89.8438f,29.0556f,117.188f, +-85.9375f,28.8377f,113.281f, +-85.9375f,28.2757f,117.188f, +-82.0313f,26.9726f,113.281f, +-82.0313f,26.6322f,117.188f, +-78.125f,25.4597f,113.281f, +-78.125f,24.8286f,117.188f, +-74.2188f,23.3572f,113.281f, +-74.2188f,22.7019f,117.188f, +-70.3125f,21.1615f,113.281f, +-70.3125f,20.4725f,117.188f, +-66.4063f,18.1212f,113.281f, +-66.4063f,17.984f,117.188f, +-62.5f,16.3411f,113.281f, +-62.5f,16.3033f,117.188f, +-58.5938f,15.075f,113.281f, +-58.5938f,14.2087f,117.188f, +-54.6875f,14.2482f,113.281f, +-54.6875f,12.8086f,117.188f, +-50.7813f,13.7945f,113.281f, +-50.7813f,12.5463f,117.188f, +-46.875f,12.7086f,113.281f, +-46.875f,12.1781f,117.188f, +-42.9688f,10.5756f,113.281f, +-42.9688f,11.1391f,117.188f, +-39.0625f,9.99343f,113.281f, +-39.0625f,10.4623f,117.188f, +-35.1563f,11.0936f,113.281f, +-35.1563f,11.0528f,117.188f, +-31.25f,11.9553f,113.281f, +-31.25f,11.454f,117.188f, +-27.3438f,11.5734f,113.281f, +-27.3438f,10.5577f,117.188f, +-23.4375f,11.0397f,113.281f, +-23.4375f,10.6328f,117.188f, +-19.5313f,12.5166f,113.281f, +-19.5313f,12.5569f,117.188f, +-15.625f,13.856f,113.281f, +-15.625f,13.5389f,117.188f, +-11.7188f,14.525f,113.281f, +-11.7188f,14.3792f,117.188f, +-7.8125f,14.7554f,113.281f, +-7.8125f,15.4809f,117.188f, +-3.90625f,15.9168f,113.281f, +-3.90625f,16.1008f,117.188f, +0.0f,17.0728f,113.281f, +0.0f,17.3675f,117.188f, +3.90625f,18.3498f,113.281f, +3.90625f,18.919f,117.188f, +-250.0f,4.66213f,109.375f, +-246.094f,2.25542f,109.375f, +-242.188f,0.972654f,109.375f, +-238.281f,-1.95429f,109.375f, +-234.375f,-2.74128f,109.375f, +-230.469f,-3.62525f,109.375f, +-226.563f,-4.55305f,109.375f, +-222.656f,-6.4124f,109.375f, +-218.75f,-6.73329f,109.375f, +-214.844f,-5.91703f,109.375f, +-210.938f,-4.73996f,109.375f, +-207.031f,-3.31105f,109.375f, +-203.125f,-2.06764f,109.375f, +-199.219f,-0.969242f,109.375f, +-195.313f,0.268778f,109.375f, +-191.406f,1.94799f,109.375f, +-187.5f,2.80754f,109.375f, +-183.594f,4.22131f,109.375f, +-179.688f,5.20723f,109.375f, +-175.781f,7.47197f,109.375f, +-171.875f,9.45267f,109.375f, +-167.969f,12.6425f,109.375f, +-164.063f,14.9382f,109.375f, +-160.156f,16.7967f,109.375f, +-156.25f,19.5153f,109.375f, +-152.344f,21.4005f,109.375f, +-148.438f,25.1259f,109.375f, +-144.531f,28.4102f,109.375f, +-140.625f,30.7572f,109.375f, +-136.719f,33.0194f,109.375f, +-132.813f,33.072f,109.375f, +-128.906f,33.1358f,109.375f, +-125.0f,35.0549f,109.375f, +-121.094f,36.4427f,109.375f, +-117.188f,38.3265f,109.375f, +-113.281f,38.5339f,109.375f, +-109.375f,37.0126f,109.375f, +-105.469f,34.9063f,109.375f, +-101.563f,32.9886f,109.375f, +-97.6563f,30.8964f,109.375f, +-93.75f,30.5048f,109.375f, +-89.8438f,30.4943f,109.375f, +-85.9375f,28.8782f,109.375f, +-82.0313f,28.1966f,109.375f, +-78.125f,25.9164f,109.375f, +-74.2188f,23.3428f,109.375f, +-70.3125f,20.9839f,109.375f, +-66.4063f,18.3885f,109.375f, +-62.5f,16.9034f,109.375f, +-58.5938f,15.2602f,109.375f, +-54.6875f,14.3223f,109.375f, +-50.7813f,13.3767f,109.375f, +-46.875f,12.5798f,109.375f, +-42.9688f,11.3276f,109.375f, +-39.0625f,11.0169f,109.375f, +-35.1563f,11.7482f,109.375f, +-31.25f,12.5037f,109.375f, +-27.3438f,12.3832f,109.375f, +-23.4375f,12.3097f,109.375f, +-19.5313f,12.6165f,109.375f, +-15.625f,13.7744f,109.375f, +-11.7188f,14.363f,109.375f, +-7.8125f,14.828f,109.375f, +-3.90625f,15.599f,109.375f, +0.0f,16.3885f,109.375f, +3.90625f,18.0017f,109.375f, +-250.0f,5.23892f,105.469f, +-246.094f,2.90481f,105.469f, +-242.188f,0.264647f,105.469f, +-238.281f,-0.288927f,105.469f, +-234.375f,-0.910295f,105.469f, +-230.469f,-2.20742f,105.469f, +-226.563f,-3.6968f,105.469f, +-222.656f,-5.2145f,105.469f, +-218.75f,-6.07198f,105.469f, +-214.844f,-5.42535f,105.469f, +-210.938f,-4.82182f,105.469f, +-207.031f,-3.22017f,105.469f, +-203.125f,-2.28037f,105.469f, +-199.219f,-1.51966f,105.469f, +-195.313f,-0.0464115f,105.469f, +-191.406f,1.73523f,105.469f, +-187.5f,2.72489f,105.469f, +-183.594f,4.39996f,105.469f, +-179.688f,5.48007f,105.469f, +-175.781f,7.27769f,105.469f, +-171.875f,10.1115f,105.469f, +-167.969f,13.0557f,105.469f, +-164.063f,15.7105f,105.469f, +-160.156f,17.8448f,105.469f, +-156.25f,19.8398f,105.469f, +-152.344f,21.6672f,105.469f, +-148.438f,24.1475f,105.469f, +-144.531f,28.4217f,105.469f, +-140.625f,31.6921f,105.469f, +-136.719f,34.3814f,105.469f, +-132.813f,34.9011f,105.469f, +-128.906f,33.8056f,105.469f, +-125.0f,34.3226f,105.469f, +-121.094f,35.6061f,105.469f, +-117.188f,37.9636f,105.469f, +-113.281f,38.6673f,105.469f, +-109.375f,36.8831f,105.469f, +-105.469f,34.5846f,105.469f, +-101.563f,32.2221f,105.469f, +-97.6563f,30.3826f,105.469f, +-93.75f,30.4243f,105.469f, +-89.8438f,30.7761f,105.469f, +-85.9375f,29.8335f,105.469f, +-82.0313f,28.0208f,105.469f, +-78.125f,25.7215f,105.469f, +-74.2188f,22.9019f,105.469f, +-70.3125f,20.9096f,105.469f, +-66.4063f,18.2558f,105.469f, +-62.5f,16.689f,105.469f, +-58.5938f,15.8032f,105.469f, +-54.6875f,14.8311f,105.469f, +-50.7813f,13.7628f,105.469f, +-46.875f,13.0048f,105.469f, +-42.9688f,11.9222f,105.469f, +-39.0625f,12.021f,105.469f, +-35.1563f,12.2727f,105.469f, +-31.25f,12.6336f,105.469f, +-27.3438f,12.6865f,105.469f, +-23.4375f,12.3758f,105.469f, +-19.5313f,13.0149f,105.469f, +-15.625f,14.0448f,105.469f, +-11.7188f,14.6064f,105.469f, +-7.8125f,15.1105f,105.469f, +-3.90625f,15.8367f,105.469f, +0.0f,16.822f,105.469f, +3.90625f,17.9608f,105.469f, +-250.0f,4.27755f,101.563f, +-246.094f,2.84639f,101.563f, +-242.188f,2.00001f,101.563f, +-238.281f,1.59426f,101.563f, +-234.375f,0.494548f,101.563f, +-230.469f,-1.78619f,101.563f, +-226.563f,-2.8668f,101.563f, +-222.656f,-5.00406f,101.563f, +-218.75f,-6.01721f,101.563f, +-214.844f,-5.29731f,101.563f, +-210.938f,-4.08939f,101.563f, +-207.031f,-3.76734f,101.563f, +-203.125f,-2.53974f,101.563f, +-199.219f,-1.06933f,101.563f, +-195.313f,-0.447271f,101.563f, +-191.406f,1.52362f,101.563f, +-187.5f,3.40783f,101.563f, +-183.594f,4.48418f,101.563f, +-179.688f,6.791f,101.563f, +-175.781f,8.68642f,101.563f, +-171.875f,11.1511f,101.563f, +-167.969f,14.4536f,101.563f, +-164.063f,17.5923f,101.563f, +-160.156f,19.4108f,101.563f, +-156.25f,20.7669f,101.563f, +-152.344f,22.2683f,101.563f, +-148.438f,24.0251f,101.563f, +-144.531f,27.7431f,101.563f, +-140.625f,31.4827f,101.563f, +-136.719f,34.3945f,101.563f, +-132.813f,35.3451f,101.563f, +-128.906f,34.9912f,101.563f, +-125.0f,34.2253f,101.563f, +-121.094f,35.1765f,101.563f, +-117.188f,37.3095f,101.563f, +-113.281f,37.7256f,101.563f, +-109.375f,36.2331f,101.563f, +-105.469f,34.435f,101.563f, +-101.563f,32.1021f,101.563f, +-97.6563f,31.0728f,101.563f, +-93.75f,30.7462f,101.563f, +-89.8438f,30.8125f,101.563f, +-85.9375f,29.6802f,101.563f, +-82.0313f,27.3023f,101.563f, +-78.125f,25.1113f,101.563f, +-74.2188f,22.6475f,101.563f, +-70.3125f,20.1315f,101.563f, +-66.4063f,18.0132f,101.563f, +-62.5f,17.1414f,101.563f, +-58.5938f,16.7884f,101.563f, +-54.6875f,15.7107f,101.563f, +-50.7813f,14.6855f,101.563f, +-46.875f,13.3626f,101.563f, +-42.9688f,11.6073f,101.563f, +-39.0625f,11.3359f,101.563f, +-35.1563f,12.4227f,101.563f, +-31.25f,13.068f,101.563f, +-27.3438f,12.4485f,101.563f, +-23.4375f,11.8491f,101.563f, +-19.5313f,13.6925f,101.563f, +-15.625f,14.7114f,101.563f, +-11.7188f,14.963f,101.563f, +-7.8125f,15.0631f,101.563f, +-3.90625f,16.1214f,101.563f, +0.0f,17.0818f,101.563f, +3.90625f,17.7074f,101.563f, +-250.0f,4.24758f,97.6563f, +-246.094f,3.92716f,97.6563f, +-242.188f,3.12473f,97.6563f, +-238.281f,2.07357f,97.6563f, +-234.375f,0.407895f,97.6563f, +-230.469f,-0.904646f,97.6563f, +-226.563f,-2.62182f,97.6563f, +-222.656f,-3.89204f,97.6563f, +-218.75f,-5.61944f,97.6563f, +-214.844f,-4.00077f,97.6563f, +-210.938f,-2.40041f,97.6563f, +-207.031f,-2.40061f,97.6563f, +-203.125f,-1.96286f,97.6563f, +-199.219f,-1.48062f,97.6563f, +-195.313f,-0.101653f,97.6563f, +-191.406f,1.73583f,97.6563f, +-187.5f,3.67572f,97.6563f, +-183.594f,5.12213f,97.6563f, +-179.688f,7.63637f,97.6563f, +-175.781f,10.1724f,97.6563f, +-171.875f,12.2812f,97.6563f, +-167.969f,15.2851f,97.6563f, +-164.063f,18.2233f,97.6563f, +-160.156f,20.4971f,97.6563f, +-156.25f,21.878f,97.6563f, +-152.344f,23.2306f,97.6563f, +-148.438f,24.2686f,97.6563f, +-144.531f,28.1874f,97.6563f, +-140.625f,31.2597f,97.6563f, +-136.719f,33.3133f,97.6563f, +-132.813f,35.319f,97.6563f, +-128.906f,35.1009f,97.6563f, +-125.0f,34.8265f,97.6563f, +-121.094f,34.2935f,97.6563f, +-117.188f,36.4908f,97.6563f, +-113.281f,37.1964f,97.6563f, +-109.375f,36.1354f,97.6563f, +-105.469f,34.3852f,97.6563f, +-101.563f,30.8829f,97.6563f, +-97.6563f,30.1091f,97.6563f, +-93.75f,30.9329f,97.6563f, +-89.8438f,30.8751f,97.6563f, +-85.9375f,29.018f,97.6563f, +-82.0313f,27.3105f,97.6563f, +-78.125f,25.0087f,97.6563f, +-74.2188f,21.6466f,97.6563f, +-70.3125f,18.5043f,97.6563f, +-66.4063f,18.66f,97.6563f, +-62.5f,18.1592f,97.6563f, +-58.5938f,17.521f,97.6563f, +-54.6875f,16.3389f,97.6563f, +-50.7813f,14.8664f,97.6563f, +-46.875f,13.5991f,97.6563f, +-42.9688f,11.873f,97.6563f, +-39.0625f,11.498f,97.6563f, +-35.1563f,11.5171f,97.6563f, +-31.25f,12.5588f,97.6563f, +-27.3438f,12.2172f,97.6563f, +-23.4375f,11.2491f,97.6563f, +-19.5313f,13.2373f,97.6563f, +-15.625f,13.5683f,97.6563f, +-11.7188f,14.0875f,97.6563f, +-7.8125f,14.6591f,97.6563f, +-3.90625f,15.1275f,97.6563f, +0.0f,15.8243f,97.6563f, +3.90625f,18.0176f,97.6563f, +-250.0f,4.93619f,93.75f, +-246.094f,3.50077f,93.75f, +-242.188f,2.88532f,93.75f, +-238.281f,2.19691f,93.75f, +-234.375f,1.45343f,93.75f, +-230.469f,-0.151238f,93.75f, +-226.563f,-1.0856f,93.75f, +-222.656f,-2.29205f,93.75f, +-218.75f,-3.83678f,93.75f, +-214.844f,-2.73856f,93.75f, +-210.938f,-2.19574f,93.75f, +-207.031f,-0.222008f,93.75f, +-203.125f,-0.117961f,93.75f, +-199.219f,-0.17607f,93.75f, +-195.313f,1.32212f,93.75f, +-191.406f,2.64292f,93.75f, +-187.5f,3.72678f,93.75f, +-183.594f,5.78729f,93.75f, +-179.688f,9.09616f,93.75f, +-175.781f,11.4833f,93.75f, +-171.875f,13.1923f,93.75f, +-167.969f,15.68f,93.75f, +-164.063f,17.9844f,93.75f, +-160.156f,20.7688f,93.75f, +-156.25f,23.4925f,93.75f, +-152.344f,25.2252f,93.75f, +-148.438f,25.9373f,93.75f, +-144.531f,28.1941f,93.75f, +-140.625f,31.9896f,93.75f, +-136.719f,33.5688f,93.75f, +-132.813f,34.7177f,93.75f, +-128.906f,35.1459f,93.75f, +-125.0f,34.9785f,93.75f, +-121.094f,34.3971f,93.75f, +-117.188f,35.2455f,93.75f, +-113.281f,36.0209f,93.75f, +-109.375f,35.244f,93.75f, +-105.469f,33.4542f,93.75f, +-101.563f,30.3707f,93.75f, +-97.6563f,30.709f,93.75f, +-93.75f,31.2489f,93.75f, +-89.8438f,30.5476f,93.75f, +-85.9375f,28.5982f,93.75f, +-82.0313f,26.6838f,93.75f, +-78.125f,24.1646f,93.75f, +-74.2188f,21.261f,93.75f, +-70.3125f,19.8206f,93.75f, +-66.4063f,19.4952f,93.75f, +-62.5f,18.3276f,93.75f, +-58.5938f,18.1028f,93.75f, +-54.6875f,17.0878f,93.75f, +-50.7813f,15.0144f,93.75f, +-46.875f,13.5565f,93.75f, +-42.9688f,11.0211f,93.75f, +-39.0625f,11.1986f,93.75f, +-35.1563f,10.4097f,93.75f, +-31.25f,11.2207f,93.75f, +-27.3438f,11.4539f,93.75f, +-23.4375f,11.4014f,93.75f, +-19.5313f,12.2344f,93.75f, +-15.625f,13.5348f,93.75f, +-11.7188f,14.2772f,93.75f, +-7.8125f,14.0447f,93.75f, +-3.90625f,14.1587f,93.75f, +0.0f,15.3266f,93.75f, +3.90625f,17.1671f,93.75f, +-250.0f,5.40499f,89.8438f, +-246.094f,3.9236f,89.8438f, +-242.188f,2.78029f,89.8438f, +-238.281f,2.337f,89.8438f, +-234.375f,1.45614f,89.8438f, +-230.469f,0.487402f,89.8438f, +-226.563f,0.814658f,89.8438f, +-222.656f,-0.244101f,89.8438f, +-218.75f,-2.09422f,89.8438f, +-214.844f,-1.48441f,89.8438f, +-210.938f,-0.695794f,89.8438f, +-207.031f,0.742314f,89.8438f, +-203.125f,1.30594f,89.8438f, +-199.219f,1.49011f,89.8438f, +-195.313f,2.5687f,89.8438f, +-191.406f,3.72318f,89.8438f, +-187.5f,4.658f,89.8438f, +-183.594f,7.20615f,89.8438f, +-179.688f,9.85211f,89.8438f, +-175.781f,12.8482f,89.8438f, +-171.875f,14.6361f,89.8438f, +-167.969f,16.6036f,89.8438f, +-164.063f,19.7308f,89.8438f, +-160.156f,22.7068f,89.8438f, +-156.25f,24.421f,89.8438f, +-152.344f,25.8961f,89.8438f, +-148.438f,27.1249f,89.8438f, +-144.531f,29.0138f,89.8438f, +-140.625f,31.6384f,89.8438f, +-136.719f,33.9142f,89.8438f, +-132.813f,34.3317f,89.8438f, +-128.906f,36.0856f,89.8438f, +-125.0f,35.5134f,89.8438f, +-121.094f,34.7035f,89.8438f, +-117.188f,33.6847f,89.8438f, +-113.281f,34.2624f,89.8438f, +-109.375f,34.2147f,89.8438f, +-105.469f,32.2925f,89.8438f, +-101.563f,30.4889f,89.8438f, +-97.6563f,30.8562f,89.8438f, +-93.75f,31.4717f,89.8438f, +-89.8438f,30.2623f,89.8438f, +-85.9375f,28.4623f,89.8438f, +-82.0313f,26.6117f,89.8438f, +-78.125f,24.1755f,89.8438f, +-74.2188f,22.4752f,89.8438f, +-70.3125f,20.3246f,89.8438f, +-66.4063f,19.488f,89.8438f, +-62.5f,18.6447f,89.8438f, +-58.5938f,17.8933f,89.8438f, +-54.6875f,16.177f,89.8438f, +-50.7813f,15.2537f,89.8438f, +-46.875f,13.5232f,89.8438f, +-42.9688f,11.842f,89.8438f, +-39.0625f,10.223f,89.8438f, +-35.1563f,9.54441f,89.8438f, +-31.25f,9.73488f,89.8438f, +-27.3438f,10.7057f,89.8438f, +-23.4375f,11.9185f,89.8438f, +-19.5313f,13.2106f,89.8438f, +-15.625f,13.0807f,89.8438f, +-11.7188f,12.8112f,89.8438f, +-7.8125f,12.7972f,89.8438f, +-3.90625f,14.1049f,89.8438f, +0.0f,14.9674f,89.8438f, +3.90625f,15.6427f,89.8438f, +-250.0f,6.21462f,85.9375f, +-246.094f,4.66025f,85.9375f, +-242.188f,3.36279f,85.9375f, +-238.281f,1.97426f,85.9375f, +-234.375f,0.590897f,85.9375f, +-230.469f,2.01222f,85.9375f, +-226.563f,2.15192f,85.9375f, +-222.656f,0.78006f,85.9375f, +-218.75f,-0.424968f,85.9375f, +-214.844f,-0.512869f,85.9375f, +-210.938f,0.00319427f,85.9375f, +-207.031f,1.05715f,85.9375f, +-203.125f,2.11926f,85.9375f, +-199.219f,2.48862f,85.9375f, +-195.313f,3.89944f,85.9375f, +-191.406f,5.71899f,85.9375f, +-187.5f,6.41674f,85.9375f, +-183.594f,7.94295f,85.9375f, +-179.688f,10.9562f,85.9375f, +-175.781f,13.1951f,85.9375f, +-171.875f,15.7827f,85.9375f, +-167.969f,17.6951f,85.9375f, +-164.063f,20.2261f,85.9375f, +-160.156f,22.5211f,85.9375f, +-156.25f,24.8103f,85.9375f, +-152.344f,26.6666f,85.9375f, +-148.438f,27.7052f,85.9375f, +-144.531f,29.2234f,85.9375f, +-140.625f,31.4629f,85.9375f, +-136.719f,34.0955f,85.9375f, +-132.813f,34.7124f,85.9375f, +-128.906f,36.1712f,85.9375f, +-125.0f,36.4743f,85.9375f, +-121.094f,35.3967f,85.9375f, +-117.188f,34.3505f,85.9375f, +-113.281f,33.5175f,85.9375f, +-109.375f,32.9976f,85.9375f, +-105.469f,31.7882f,85.9375f, +-101.563f,31.1746f,85.9375f, +-97.6563f,31.0271f,85.9375f, +-93.75f,31.5303f,85.9375f, +-89.8438f,30.8744f,85.9375f, +-85.9375f,28.1434f,85.9375f, +-82.0313f,25.9196f,85.9375f, +-78.125f,24.4044f,85.9375f, +-74.2188f,21.9984f,85.9375f, +-70.3125f,20.0411f,85.9375f, +-66.4063f,19.9449f,85.9375f, +-62.5f,18.3893f,85.9375f, +-58.5938f,16.9846f,85.9375f, +-54.6875f,15.6155f,85.9375f, +-50.7813f,14.6152f,85.9375f, +-46.875f,12.7358f,85.9375f, +-42.9688f,12.1599f,85.9375f, +-39.0625f,10.1045f,85.9375f, +-35.1563f,9.61416f,85.9375f, +-31.25f,10.0784f,85.9375f, +-27.3438f,10.2188f,85.9375f, +-23.4375f,11.574f,85.9375f, +-19.5313f,11.8712f,85.9375f, +-15.625f,11.9109f,85.9375f, +-11.7188f,11.509f,85.9375f, +-7.8125f,13.9979f,85.9375f, +-3.90625f,14.8453f,85.9375f, +0.0f,14.7941f,85.9375f, +3.90625f,15.5916f,85.9375f, +-250.0f,6.94324f,82.0313f, +-246.094f,4.77131f,82.0313f, +-242.188f,3.62143f,82.0313f, +-238.281f,2.50324f,82.0313f, +-234.375f,1.40345f,82.0313f, +-230.469f,2.05881f,82.0313f, +-226.563f,2.41769f,82.0313f, +-222.656f,1.23736f,82.0313f, +-218.75f,1.59545f,82.0313f, +-214.844f,1.25313f,82.0313f, +-210.938f,1.53594f,82.0313f, +-207.031f,2.33073f,82.0313f, +-203.125f,2.59696f,82.0313f, +-199.219f,4.25487f,82.0313f, +-195.313f,5.86136f,82.0313f, +-191.406f,7.54631f,82.0313f, +-187.5f,8.7315f,82.0313f, +-183.594f,9.65737f,82.0313f, +-179.688f,11.5328f,82.0313f, +-175.781f,14.3069f,82.0313f, +-171.875f,16.2889f,82.0313f, +-167.969f,17.6379f,82.0313f, +-164.063f,20.4422f,82.0313f, +-160.156f,22.9557f,82.0313f, +-156.25f,25.0731f,82.0313f, +-152.344f,27.3881f,82.0313f, +-148.438f,28.7955f,82.0313f, +-144.531f,30.2575f,82.0313f, +-140.625f,32.5888f,82.0313f, +-136.719f,33.9884f,82.0313f, +-132.813f,34.4838f,82.0313f, +-128.906f,35.7672f,82.0313f, +-125.0f,36.1002f,82.0313f, +-121.094f,35.9318f,82.0313f, +-117.188f,34.9715f,82.0313f, +-113.281f,33.3187f,82.0313f, +-109.375f,31.9477f,82.0313f, +-105.469f,31.4437f,82.0313f, +-101.563f,31.2817f,82.0313f, +-97.6563f,32.08f,82.0313f, +-93.75f,31.4037f,82.0313f, +-89.8438f,30.2769f,82.0313f, +-85.9375f,28.1374f,82.0313f, +-82.0313f,25.4814f,82.0313f, +-78.125f,24.1831f,82.0313f, +-74.2188f,22.6148f,82.0313f, +-70.3125f,19.2585f,82.0313f, +-66.4063f,18.6785f,82.0313f, +-62.5f,17.7889f,82.0313f, +-58.5938f,16.5855f,82.0313f, +-54.6875f,14.6918f,82.0313f, +-50.7813f,12.9532f,82.0313f, +-46.875f,12.1502f,82.0313f, +-42.9688f,11.3533f,82.0313f, +-39.0625f,9.8302f,82.0313f, +-35.1563f,9.95311f,82.0313f, +-31.25f,10.7631f,82.0313f, +-27.3438f,10.2187f,82.0313f, +-23.4375f,10.1072f,82.0313f, +-19.5313f,11.299f,82.0313f, +-15.625f,11.5563f,82.0313f, +-11.7188f,13.9188f,82.0313f, +-7.8125f,15.247f,82.0313f, +-3.90625f,15.6866f,82.0313f, +0.0f,15.9694f,82.0313f, +3.90625f,16.9644f,82.0313f, +-250.0f,6.39735f,78.125f, +-246.094f,5.09353f,78.125f, +-242.188f,4.53503f,78.125f, +-238.281f,3.72522f,78.125f, +-234.375f,3.02648f,78.125f, +-230.469f,3.02057f,78.125f, +-226.563f,3.8807f,78.125f, +-222.656f,4.47382f,78.125f, +-218.75f,3.84005f,78.125f, +-214.844f,2.7347f,78.125f, +-210.938f,4.55018f,78.125f, +-207.031f,5.04579f,78.125f, +-203.125f,4.45937f,78.125f, +-199.219f,5.32656f,78.125f, +-195.313f,7.13791f,78.125f, +-191.406f,8.89822f,78.125f, +-187.5f,10.3911f,78.125f, +-183.594f,11.3679f,78.125f, +-179.688f,13.4068f,78.125f, +-175.781f,16.3393f,78.125f, +-171.875f,17.801f,78.125f, +-167.969f,19.0455f,78.125f, +-164.063f,21.4178f,78.125f, +-160.156f,23.555f,78.125f, +-156.25f,25.3953f,78.125f, +-152.344f,26.9657f,78.125f, +-148.438f,28.8194f,78.125f, +-144.531f,31.456f,78.125f, +-140.625f,33.3499f,78.125f, +-136.719f,34.2296f,78.125f, +-132.813f,34.5964f,78.125f, +-128.906f,35.7399f,78.125f, +-125.0f,35.4576f,78.125f, +-121.094f,35.7986f,78.125f, +-117.188f,34.4641f,78.125f, +-113.281f,33.925f,78.125f, +-109.375f,32.0574f,78.125f, +-105.469f,31.6743f,78.125f, +-101.563f,31.65f,78.125f, +-97.6563f,31.9461f,78.125f, +-93.75f,31.2261f,78.125f, +-89.8438f,30.4701f,78.125f, +-85.9375f,27.7569f,78.125f, +-82.0313f,25.4553f,78.125f, +-78.125f,23.3917f,78.125f, +-74.2188f,21.6944f,78.125f, +-70.3125f,18.6818f,78.125f, +-66.4063f,17.4066f,78.125f, +-62.5f,17.1317f,78.125f, +-58.5938f,16.5093f,78.125f, +-54.6875f,14.9512f,78.125f, +-50.7813f,13.228f,78.125f, +-46.875f,11.4638f,78.125f, +-42.9688f,10.3877f,78.125f, +-39.0625f,9.7131f,78.125f, +-35.1563f,10.0477f,78.125f, +-31.25f,10.325f,78.125f, +-27.3438f,10.317f,78.125f, +-23.4375f,10.9076f,78.125f, +-19.5313f,11.7808f,78.125f, +-15.625f,14.1905f,78.125f, +-11.7188f,15.6035f,78.125f, +-7.8125f,16.0979f,78.125f, +-3.90625f,16.6425f,78.125f, +0.0f,17.2837f,78.125f, +3.90625f,18.8244f,78.125f, +-250.0f,6.03592f,74.2188f, +-246.094f,5.17606f,74.2188f, +-242.188f,3.7036f,74.2188f, +-238.281f,3.69f,74.2188f, +-234.375f,4.60611f,74.2188f, +-230.469f,4.52682f,74.2188f, +-226.563f,5.59937f,74.2188f, +-222.656f,6.25837f,74.2188f, +-218.75f,5.11517f,74.2188f, +-214.844f,4.67242f,74.2188f, +-210.938f,5.76173f,74.2188f, +-207.031f,6.80461f,74.2188f, +-203.125f,6.95083f,74.2188f, +-199.219f,7.35893f,74.2188f, +-195.313f,8.63949f,74.2188f, +-191.406f,10.4144f,74.2188f, +-187.5f,11.8105f,74.2188f, +-183.594f,13.4583f,74.2188f, +-179.688f,15.5665f,74.2188f, +-175.781f,18.2568f,74.2188f, +-171.875f,19.1732f,74.2188f, +-167.969f,21.3098f,74.2188f, +-164.063f,23.6359f,74.2188f, +-160.156f,25.3154f,74.2188f, +-156.25f,27.6289f,74.2188f, +-152.344f,28.8953f,74.2188f, +-148.438f,30.5098f,74.2188f, +-144.531f,32.3942f,74.2188f, +-140.625f,33.3325f,74.2188f, +-136.719f,33.8009f,74.2188f, +-132.813f,35.0803f,74.2188f, +-128.906f,34.737f,74.2188f, +-125.0f,34.3656f,74.2188f, +-121.094f,34.2107f,74.2188f, +-117.188f,33.1645f,74.2188f, +-113.281f,32.0615f,74.2188f, +-109.375f,32.0827f,74.2188f, +-105.469f,32.4658f,74.2188f, +-101.563f,31.6315f,74.2188f, +-97.6563f,30.9698f,74.2188f, +-93.75f,30.6464f,74.2188f, +-89.8438f,29.9645f,74.2188f, +-85.9375f,27.4393f,74.2188f, +-82.0313f,25.2807f,74.2188f, +-78.125f,23.57f,74.2188f, +-74.2188f,20.653f,74.2188f, +-70.3125f,18.1395f,74.2188f, +-66.4063f,17.6585f,74.2188f, +-62.5f,17.2798f,74.2188f, +-58.5938f,16.6041f,74.2188f, +-54.6875f,14.6913f,74.2188f, +-50.7813f,13.1416f,74.2188f, +-46.875f,10.9374f,74.2188f, +-42.9688f,9.39485f,74.2188f, +-39.0625f,9.21956f,74.2188f, +-35.1563f,9.74875f,74.2188f, +-31.25f,10.3932f,74.2188f, +-27.3438f,10.7996f,74.2188f, +-23.4375f,11.5538f,74.2188f, +-19.5313f,13.5418f,74.2188f, +-15.625f,15.6336f,74.2188f, +-11.7188f,16.3846f,74.2188f, +-7.8125f,17.738f,74.2188f, +-3.90625f,17.98f,74.2188f, +0.0f,19.1669f,74.2188f, +3.90625f,20.6829f,74.2188f, +-250.0f,5.45149f,70.3125f, +-246.094f,4.83779f,70.3125f, +-242.188f,3.60093f,70.3125f, +-238.281f,3.26469f,70.3125f, +-234.375f,4.06145f,70.3125f, +-230.469f,5.31565f,70.3125f, +-226.563f,6.65809f,70.3125f, +-222.656f,6.70538f,70.3125f, +-218.75f,6.93258f,70.3125f, +-214.844f,6.84841f,70.3125f, +-210.938f,6.9662f,70.3125f, +-207.031f,7.74003f,70.3125f, +-203.125f,8.68749f,70.3125f, +-199.219f,9.06225f,70.3125f, +-195.313f,10.0803f,70.3125f, +-191.406f,12.202f,70.3125f, +-187.5f,14.063f,70.3125f, +-183.594f,15.732f,70.3125f, +-179.688f,18.3972f,70.3125f, +-175.781f,19.5054f,70.3125f, +-171.875f,20.8927f,70.3125f, +-167.969f,23.3843f,70.3125f, +-164.063f,25.5894f,70.3125f, +-160.156f,27.0506f,70.3125f, +-156.25f,28.6483f,70.3125f, +-152.344f,31.3986f,70.3125f, +-148.438f,32.5255f,70.3125f, +-144.531f,33.0315f,70.3125f, +-140.625f,33.0927f,70.3125f, +-136.719f,33.7595f,70.3125f, +-132.813f,34.1872f,70.3125f, +-128.906f,33.4924f,70.3125f, +-125.0f,34.1817f,70.3125f, +-121.094f,33.4642f,70.3125f, +-117.188f,32.3231f,70.3125f, +-113.281f,32.1235f,70.3125f, +-109.375f,32.674f,70.3125f, +-105.469f,32.7558f,70.3125f, +-101.563f,32.4896f,70.3125f, +-97.6563f,30.7945f,70.3125f, +-93.75f,30.1182f,70.3125f, +-89.8438f,28.6969f,70.3125f, +-85.9375f,26.606f,70.3125f, +-82.0313f,24.8053f,70.3125f, +-78.125f,23.3599f,70.3125f, +-74.2188f,20.5363f,70.3125f, +-70.3125f,18.2858f,70.3125f, +-66.4063f,17.647f,70.3125f, +-62.5f,17.3761f,70.3125f, +-58.5938f,16.3124f,70.3125f, +-54.6875f,14.016f,70.3125f, +-50.7813f,11.6317f,70.3125f, +-46.875f,9.68832f,70.3125f, +-42.9688f,8.63692f,70.3125f, +-39.0625f,8.52412f,70.3125f, +-35.1563f,10.3549f,70.3125f, +-31.25f,11.1185f,70.3125f, +-27.3438f,12.8223f,70.3125f, +-23.4375f,14.2548f,70.3125f, +-19.5313f,15.4066f,70.3125f, +-15.625f,16.875f,70.3125f, +-11.7188f,17.7202f,70.3125f, +-7.8125f,18.6716f,70.3125f, +-3.90625f,19.72f,70.3125f, +0.0f,21.3086f,70.3125f, +3.90625f,22.948f,70.3125f, +-250.0f,4.53118f,66.4063f, +-246.094f,3.73568f,66.4063f, +-242.188f,3.80679f,66.4063f, +-238.281f,4.42509f,66.4063f, +-234.375f,5.0317f,66.4063f, +-230.469f,6.63484f,66.4063f, +-226.563f,7.65599f,66.4063f, +-222.656f,8.55305f,66.4063f, +-218.75f,8.71866f,66.4063f, +-214.844f,7.68897f,66.4063f, +-210.938f,8.59141f,66.4063f, +-207.031f,9.73811f,66.4063f, +-203.125f,10.1348f,66.4063f, +-199.219f,10.1075f,66.4063f, +-195.313f,11.1394f,66.4063f, +-191.406f,13.5829f,66.4063f, +-187.5f,15.4951f,66.4063f, +-183.594f,17.5574f,66.4063f, +-179.688f,19.9291f,66.4063f, +-175.781f,21.0567f,66.4063f, +-171.875f,22.5003f,66.4063f, +-167.969f,25.5993f,66.4063f, +-164.063f,27.0097f,66.4063f, +-160.156f,27.9166f,66.4063f, +-156.25f,29.8989f,66.4063f, +-152.344f,32.1785f,66.4063f, +-148.438f,34.0669f,66.4063f, +-144.531f,34.5129f,66.4063f, +-140.625f,34.1795f,66.4063f, +-136.719f,33.3311f,66.4063f, +-132.813f,32.969f,66.4063f, +-128.906f,32.9477f,66.4063f, +-125.0f,33.5186f,66.4063f, +-121.094f,32.9715f,66.4063f, +-117.188f,32.4898f,66.4063f, +-113.281f,33.0858f,66.4063f, +-109.375f,32.6501f,66.4063f, +-105.469f,32.847f,66.4063f, +-101.563f,32.8074f,66.4063f, +-97.6563f,31.5661f,66.4063f, +-93.75f,29.4807f,66.4063f, +-89.8438f,28.6706f,66.4063f, +-85.9375f,26.408f,66.4063f, +-82.0313f,24.3989f,66.4063f, +-78.125f,22.4069f,66.4063f, +-74.2188f,20.2026f,66.4063f, +-70.3125f,18.5513f,66.4063f, +-66.4063f,17.0548f,66.4063f, +-62.5f,17.0623f,66.4063f, +-58.5938f,15.9909f,66.4063f, +-54.6875f,13.3885f,66.4063f, +-50.7813f,11.8657f,66.4063f, +-46.875f,9.02652f,66.4063f, +-42.9688f,8.99046f,66.4063f, +-39.0625f,10.0543f,66.4063f, +-35.1563f,11.7078f,66.4063f, +-31.25f,12.4956f,66.4063f, +-27.3438f,14.0575f,66.4063f, +-23.4375f,15.2147f,66.4063f, +-19.5313f,16.7089f,66.4063f, +-15.625f,17.8009f,66.4063f, +-11.7188f,19.0086f,66.4063f, +-7.8125f,20.9864f,66.4063f, +-3.90625f,22.6943f,66.4063f, +0.0f,23.9641f,66.4063f, +3.90625f,25.5564f,66.4063f, +-250.0f,4.6779f,62.5f, +-246.094f,4.41735f,62.5f, +-242.188f,3.93647f,62.5f, +-238.281f,4.50648f,62.5f, +-234.375f,5.52163f,62.5f, +-230.469f,7.10395f,62.5f, +-226.563f,8.10257f,62.5f, +-222.656f,8.36726f,62.5f, +-218.75f,8.58321f,62.5f, +-214.844f,8.56809f,62.5f, +-210.938f,9.95321f,62.5f, +-207.031f,10.4904f,62.5f, +-203.125f,10.812f,62.5f, +-199.219f,11.5942f,62.5f, +-195.313f,13.0371f,62.5f, +-191.406f,14.6432f,62.5f, +-187.5f,16.7375f,62.5f, +-183.594f,18.4129f,62.5f, +-179.688f,20.9534f,62.5f, +-175.781f,23.1161f,62.5f, +-171.875f,25.0267f,62.5f, +-167.969f,26.7355f,62.5f, +-164.063f,27.6983f,62.5f, +-160.156f,29.1111f,62.5f, +-156.25f,31.1905f,62.5f, +-152.344f,32.9766f,62.5f, +-148.438f,33.4703f,62.5f, +-144.531f,33.714f,62.5f, +-140.625f,33.649f,62.5f, +-136.719f,33.0246f,62.5f, +-132.813f,32.7386f,62.5f, +-128.906f,32.6069f,62.5f, +-125.0f,32.6579f,62.5f, +-121.094f,31.5955f,62.5f, +-117.188f,31.8589f,62.5f, +-113.281f,32.7188f,62.5f, +-109.375f,32.889f,62.5f, +-105.469f,32.7317f,62.5f, +-101.563f,32.4229f,62.5f, +-97.6563f,31.2118f,62.5f, +-93.75f,30.6824f,62.5f, +-89.8438f,28.584f,62.5f, +-85.9375f,26.1183f,62.5f, +-82.0313f,23.8148f,62.5f, +-78.125f,22.0333f,62.5f, +-74.2188f,20.178f,62.5f, +-70.3125f,18.704f,62.5f, +-66.4063f,16.8036f,62.5f, +-62.5f,15.7173f,62.5f, +-58.5938f,13.9284f,62.5f, +-54.6875f,13.0731f,62.5f, +-50.7813f,11.8974f,62.5f, +-46.875f,9.91347f,62.5f, +-42.9688f,10.1439f,62.5f, +-39.0625f,11.304f,62.5f, +-35.1563f,12.5111f,62.5f, +-31.25f,14.112f,62.5f, +-27.3438f,15.3325f,62.5f, +-23.4375f,16.6214f,62.5f, +-19.5313f,17.8469f,62.5f, +-15.625f,19.2987f,62.5f, +-11.7188f,20.9518f,62.5f, +-7.8125f,23.4289f,62.5f, +-3.90625f,24.9379f,62.5f, +0.0f,26.156f,62.5f, +3.90625f,27.1929f,62.5f, +-250.0f,4.23938f,58.5938f, +-246.094f,4.819f,58.5938f, +-242.188f,4.63067f,58.5938f, +-238.281f,5.29023f,58.5938f, +-234.375f,6.48193f,58.5938f, +-230.469f,6.85856f,58.5938f, +-226.563f,8.4748f,58.5938f, +-222.656f,8.76416f,58.5938f, +-218.75f,9.24425f,58.5938f, +-214.844f,9.67654f,58.5938f, +-210.938f,10.8063f,58.5938f, +-207.031f,12.3237f,58.5938f, +-203.125f,12.7409f,58.5938f, +-199.219f,12.7587f,58.5938f, +-195.313f,14.3653f,58.5938f, +-191.406f,16.1467f,58.5938f, +-187.5f,17.0489f,58.5938f, +-183.594f,19.2091f,58.5938f, +-179.688f,21.7856f,58.5938f, +-175.781f,24.7829f,58.5938f, +-171.875f,26.2396f,58.5938f, +-167.969f,27.2756f,58.5938f, +-164.063f,28.2919f,58.5938f, +-160.156f,30.5945f,58.5938f, +-156.25f,32.2617f,58.5938f, +-152.344f,32.9049f,58.5938f, +-148.438f,32.8002f,58.5938f, +-144.531f,32.4751f,58.5938f, +-140.625f,32.4049f,58.5938f, +-136.719f,33.5631f,58.5938f, +-132.813f,33.3828f,58.5938f, +-128.906f,33.1064f,58.5938f, +-125.0f,32.3054f,58.5938f, +-121.094f,32.5047f,58.5938f, +-117.188f,32.3246f,58.5938f, +-113.281f,32.4393f,58.5938f, +-109.375f,32.553f,58.5938f, +-105.469f,32.9281f,58.5938f, +-101.563f,31.8539f,58.5938f, +-97.6563f,30.9253f,58.5938f, +-93.75f,30.4328f,58.5938f, +-89.8438f,28.3295f,58.5938f, +-85.9375f,25.5393f,58.5938f, +-82.0313f,23.0691f,58.5938f, +-78.125f,21.505f,58.5938f, +-74.2188f,21.0748f,58.5938f, +-70.3125f,19.1186f,58.5938f, +-66.4063f,16.7814f,58.5938f, +-62.5f,15.2179f,58.5938f, +-58.5938f,14.1291f,58.5938f, +-54.6875f,13.2351f,58.5938f, +-50.7813f,11.896f,58.5938f, +-46.875f,11.0911f,58.5938f, +-42.9688f,12.7485f,58.5938f, +-39.0625f,13.7045f,58.5938f, +-35.1563f,14.6128f,58.5938f, +-31.25f,15.546f,58.5938f, +-27.3438f,16.7828f,58.5938f, +-23.4375f,18.7578f,58.5938f, +-19.5313f,19.7951f,58.5938f, +-15.625f,21.8594f,58.5938f, +-11.7188f,22.7269f,58.5938f, +-7.8125f,24.983f,58.5938f, +-3.90625f,26.43f,58.5938f, +0.0f,27.4466f,58.5938f, +3.90625f,28.3495f,58.5938f, +-250.0f,3.62748f,54.6875f, +-246.094f,3.83329f,54.6875f, +-242.188f,4.44022f,54.6875f, +-238.281f,5.27514f,54.6875f, +-234.375f,7.43995f,54.6875f, +-230.469f,7.59176f,54.6875f, +-226.563f,8.28985f,54.6875f, +-222.656f,9.62184f,54.6875f, +-218.75f,10.6613f,54.6875f, +-214.844f,11.0914f,54.6875f, +-210.938f,12.2186f,54.6875f, +-207.031f,13.1985f,54.6875f, +-203.125f,13.9982f,54.6875f, +-199.219f,14.3187f,54.6875f, +-195.313f,14.8791f,54.6875f, +-191.406f,16.5829f,54.6875f, +-187.5f,18.231f,54.6875f, +-183.594f,20.0621f,54.6875f, +-179.688f,22.8941f,54.6875f, +-175.781f,25.0841f,54.6875f, +-171.875f,26.5655f,54.6875f, +-167.969f,27.3542f,54.6875f, +-164.063f,29.2247f,54.6875f, +-160.156f,30.91f,54.6875f, +-156.25f,33.3376f,54.6875f, +-152.344f,32.8808f,54.6875f, +-148.438f,32.5783f,54.6875f, +-144.531f,32.6138f,54.6875f, +-140.625f,32.9002f,54.6875f, +-136.719f,34.2312f,54.6875f, +-132.813f,33.8335f,54.6875f, +-128.906f,32.8545f,54.6875f, +-125.0f,33.6683f,54.6875f, +-121.094f,32.9953f,54.6875f, +-117.188f,32.5096f,54.6875f, +-113.281f,32.4307f,54.6875f, +-109.375f,31.8214f,54.6875f, +-105.469f,31.851f,54.6875f, +-101.563f,31.6383f,54.6875f, +-97.6563f,30.4359f,54.6875f, +-93.75f,28.9306f,54.6875f, +-89.8438f,26.5955f,54.6875f, +-85.9375f,24.7234f,54.6875f, +-82.0313f,23.0595f,54.6875f, +-78.125f,21.3558f,54.6875f, +-74.2188f,20.3788f,54.6875f, +-70.3125f,19.3201f,54.6875f, +-66.4063f,16.9597f,54.6875f, +-62.5f,14.6652f,54.6875f, +-58.5938f,14.4899f,54.6875f, +-54.6875f,13.3432f,54.6875f, +-50.7813f,12.3286f,54.6875f, +-46.875f,12.6498f,54.6875f, +-42.9688f,14.2651f,54.6875f, +-39.0625f,15.6887f,54.6875f, +-35.1563f,16.2038f,54.6875f, +-31.25f,17.2337f,54.6875f, +-27.3438f,18.7628f,54.6875f, +-23.4375f,20.2472f,54.6875f, +-19.5313f,21.6809f,54.6875f, +-15.625f,24.084f,54.6875f, +-11.7188f,25.1582f,54.6875f, +-7.8125f,26.7f,54.6875f, +-3.90625f,27.5421f,54.6875f, +0.0f,28.3244f,54.6875f, +3.90625f,29.2057f,54.6875f, +-250.0f,3.74657f,50.7813f, +-246.094f,3.89172f,50.7813f, +-242.188f,4.12295f,50.7813f, +-238.281f,5.16915f,50.7813f, +-234.375f,6.30394f,50.7813f, +-230.469f,7.21975f,50.7813f, +-226.563f,8.61249f,50.7813f, +-222.656f,10.1295f,50.7813f, +-218.75f,12.2813f,50.7813f, +-214.844f,12.3309f,50.7813f, +-210.938f,13.3907f,50.7813f, +-207.031f,14.1528f,50.7813f, +-203.125f,14.0334f,50.7813f, +-199.219f,14.814f,50.7813f, +-195.313f,16.69f,50.7813f, +-191.406f,17.639f,50.7813f, +-187.5f,19.261f,50.7813f, +-183.594f,20.748f,50.7813f, +-179.688f,23.3343f,50.7813f, +-175.781f,25.4837f,50.7813f, +-171.875f,26.8456f,50.7813f, +-167.969f,27.7788f,50.7813f, +-164.063f,30.0174f,50.7813f, +-160.156f,31.0689f,50.7813f, +-156.25f,32.5898f,50.7813f, +-152.344f,32.5672f,50.7813f, +-148.438f,32.4654f,50.7813f, +-144.531f,33.702f,50.7813f, +-140.625f,34.7593f,50.7813f, +-136.719f,33.9086f,50.7813f, +-132.813f,33.681f,50.7813f, +-128.906f,33.6369f,50.7813f, +-125.0f,34.0371f,50.7813f, +-121.094f,34.0479f,50.7813f, +-117.188f,34.513f,50.7813f, +-113.281f,33.7072f,50.7813f, +-109.375f,32.2763f,50.7813f, +-105.469f,32.0608f,50.7813f, +-101.563f,31.0833f,50.7813f, +-97.6563f,29.9168f,50.7813f, +-93.75f,28.7604f,50.7813f, +-89.8438f,26.9563f,50.7813f, +-85.9375f,24.7908f,50.7813f, +-82.0313f,23.7925f,50.7813f, +-78.125f,21.7037f,50.7813f, +-74.2188f,19.5308f,50.7813f, +-70.3125f,19.3367f,50.7813f, +-66.4063f,17.8482f,50.7813f, +-62.5f,14.2491f,50.7813f, +-58.5938f,14.7414f,50.7813f, +-54.6875f,14.0395f,50.7813f, +-50.7813f,12.9738f,50.7813f, +-46.875f,13.9471f,50.7813f, +-42.9688f,15.8319f,50.7813f, +-39.0625f,16.6566f,50.7813f, +-35.1563f,17.1252f,50.7813f, +-31.25f,18.6998f,50.7813f, +-27.3438f,20.877f,50.7813f, +-23.4375f,22.0249f,50.7813f, +-19.5313f,22.9369f,50.7813f, +-15.625f,25.686f,50.7813f, +-11.7188f,26.1758f,50.7813f, +-7.8125f,28.3828f,50.7813f, +-3.90625f,28.7973f,50.7813f, +0.0f,29.7276f,50.7813f, +3.90625f,30.4306f,50.7813f, +-250.0f,3.69244f,46.875f, +-246.094f,3.88583f,46.875f, +-242.188f,3.98468f,46.875f, +-238.281f,5.01772f,46.875f, +-234.375f,7.23791f,46.875f, +-230.469f,7.78117f,46.875f, +-226.563f,8.55298f,46.875f, +-222.656f,10.2684f,46.875f, +-218.75f,11.1917f,46.875f, +-214.844f,12.411f,46.875f, +-210.938f,13.7214f,46.875f, +-207.031f,14.4662f,46.875f, +-203.125f,15.536f,46.875f, +-199.219f,15.6035f,46.875f, +-195.313f,16.8456f,46.875f, +-191.406f,18.4656f,46.875f, +-187.5f,19.415f,46.875f, +-183.594f,20.8504f,46.875f, +-179.688f,23.9388f,46.875f, +-175.781f,26.2956f,46.875f, +-171.875f,27.6728f,46.875f, +-167.969f,28.2497f,46.875f, +-164.063f,29.6503f,46.875f, +-160.156f,31.9344f,46.875f, +-156.25f,33.4163f,46.875f, +-152.344f,33.428f,46.875f, +-148.438f,33.3157f,46.875f, +-144.531f,33.6261f,46.875f, +-140.625f,35.1888f,46.875f, +-136.719f,34.8434f,46.875f, +-132.813f,34.1219f,46.875f, +-128.906f,34.4564f,46.875f, +-125.0f,34.9729f,46.875f, +-121.094f,34.8811f,46.875f, +-117.188f,35.185f,46.875f, +-113.281f,34.138f,46.875f, +-109.375f,32.7077f,46.875f, +-105.469f,32.2219f,46.875f, +-101.563f,31.2475f,46.875f, +-97.6563f,29.9637f,46.875f, +-93.75f,28.1214f,46.875f, +-89.8438f,27.0889f,46.875f, +-85.9375f,25.092f,46.875f, +-82.0313f,23.3983f,46.875f, +-78.125f,22.275f,46.875f, +-74.2188f,19.8598f,46.875f, +-70.3125f,18.8797f,46.875f, +-66.4063f,17.2468f,46.875f, +-62.5f,15.4985f,46.875f, +-58.5938f,14.5357f,46.875f, +-54.6875f,14.6964f,46.875f, +-50.7813f,13.3496f,46.875f, +-46.875f,15.6354f,46.875f, +-42.9688f,16.7177f,46.875f, +-39.0625f,17.4527f,46.875f, +-35.1563f,18.2826f,46.875f, +-31.25f,20.3293f,46.875f, +-27.3438f,22.684f,46.875f, +-23.4375f,23.538f,46.875f, +-19.5313f,24.3046f,46.875f, +-15.625f,26.1113f,46.875f, +-11.7188f,27.4881f,46.875f, +-7.8125f,29.3572f,46.875f, +-3.90625f,29.786f,46.875f, +0.0f,30.3637f,46.875f, +3.90625f,30.8772f,46.875f, +-250.0f,4.08083f,42.9688f, +-246.094f,4.09778f,42.9688f, +-242.188f,3.87631f,42.9688f, +-238.281f,5.12214f,42.9688f, +-234.375f,6.70993f,42.9688f, +-230.469f,7.75806f,42.9688f, +-226.563f,8.13676f,42.9688f, +-222.656f,8.85151f,42.9688f, +-218.75f,10.9378f,42.9688f, +-214.844f,12.4043f,42.9688f, +-210.938f,13.4636f,42.9688f, +-207.031f,14.7352f,42.9688f, +-203.125f,15.605f,42.9688f, +-199.219f,15.7497f,42.9688f, +-195.313f,17.184f,42.9688f, +-191.406f,19.3679f,42.9688f, +-187.5f,21.1701f,42.9688f, +-183.594f,22.7204f,42.9688f, +-179.688f,24.8128f,42.9688f, +-175.781f,26.7707f,42.9688f, +-171.875f,27.7521f,42.9688f, +-167.969f,28.8689f,42.9688f, +-164.063f,31.1205f,42.9688f, +-160.156f,33.289f,42.9688f, +-156.25f,34.2815f,42.9688f, +-152.344f,33.9797f,42.9688f, +-148.438f,34.2527f,42.9688f, +-144.531f,34.1886f,42.9688f, +-140.625f,34.868f,42.9688f, +-136.719f,35.6569f,42.9688f, +-132.813f,35.4999f,42.9688f, +-128.906f,35.4373f,42.9688f, +-125.0f,36.373f,42.9688f, +-121.094f,35.4304f,42.9688f, +-117.188f,34.3543f,42.9688f, +-113.281f,35.0651f,42.9688f, +-109.375f,33.5051f,42.9688f, +-105.469f,32.471f,42.9688f, +-101.563f,31.2764f,42.9688f, +-97.6563f,29.7633f,42.9688f, +-93.75f,27.9107f,42.9688f, +-89.8438f,26.5273f,42.9688f, +-85.9375f,25.2444f,42.9688f, +-82.0313f,23.6093f,42.9688f, +-78.125f,21.9684f,42.9688f, +-74.2188f,19.4992f,42.9688f, +-70.3125f,17.8231f,42.9688f, +-66.4063f,17.4082f,42.9688f, +-62.5f,17.0938f,42.9688f, +-58.5938f,15.3348f,42.9688f, +-54.6875f,14.7964f,42.9688f, +-50.7813f,14.9948f,42.9688f, +-46.875f,17.1807f,42.9688f, +-42.9688f,18.118f,42.9688f, +-39.0625f,19.0809f,42.9688f, +-35.1563f,19.6971f,42.9688f, +-31.25f,21.652f,42.9688f, +-27.3438f,23.4343f,42.9688f, +-23.4375f,24.5708f,42.9688f, +-19.5313f,25.2003f,42.9688f, +-15.625f,26.8391f,42.9688f, +-11.7188f,28.9343f,42.9688f, +-7.8125f,29.9079f,42.9688f, +-3.90625f,31.268f,42.9688f, +0.0f,31.3916f,42.9688f, +3.90625f,31.8945f,42.9688f, +-250.0f,4.27976f,39.0625f, +-246.094f,4.20341f,39.0625f, +-242.188f,3.80298f,39.0625f, +-238.281f,4.79243f,39.0625f, +-234.375f,5.51846f,39.0625f, +-230.469f,6.91597f,39.0625f, +-226.563f,8.25726f,39.0625f, +-222.656f,8.85037f,39.0625f, +-218.75f,9.57429f,39.0625f, +-214.844f,11.3899f,39.0625f, +-210.938f,12.5806f,39.0625f, +-207.031f,14.2509f,39.0625f, +-203.125f,14.7828f,39.0625f, +-199.219f,15.9801f,39.0625f, +-195.313f,17.4225f,39.0625f, +-191.406f,19.6018f,39.0625f, +-187.5f,22.1095f,39.0625f, +-183.594f,23.8333f,39.0625f, +-179.688f,25.0671f,39.0625f, +-175.781f,27.1067f,39.0625f, +-171.875f,28.5f,39.0625f, +-167.969f,29.9625f,39.0625f, +-164.063f,32.3895f,39.0625f, +-160.156f,33.8224f,39.0625f, +-156.25f,34.3349f,39.0625f, +-152.344f,34.4661f,39.0625f, +-148.438f,34.7236f,39.0625f, +-144.531f,34.1129f,39.0625f, +-140.625f,34.9033f,39.0625f, +-136.719f,35.6229f,39.0625f, +-132.813f,35.7143f,39.0625f, +-128.906f,36.7151f,39.0625f, +-125.0f,36.9574f,39.0625f, +-121.094f,36.0729f,39.0625f, +-117.188f,35.2171f,39.0625f, +-113.281f,34.9343f,39.0625f, +-109.375f,34.5707f,39.0625f, +-105.469f,33.5046f,39.0625f, +-101.563f,31.353f,39.0625f, +-97.6563f,30.0283f,39.0625f, +-93.75f,28.6272f,39.0625f, +-89.8438f,26.4389f,39.0625f, +-85.9375f,24.8159f,39.0625f, +-82.0313f,23.0295f,39.0625f, +-78.125f,21.1082f,39.0625f, +-74.2188f,19.1239f,39.0625f, +-70.3125f,18.0914f,39.0625f, +-66.4063f,17.3227f,39.0625f, +-62.5f,17.1022f,39.0625f, +-58.5938f,16.4298f,39.0625f, +-54.6875f,15.6704f,39.0625f, +-50.7813f,16.5664f,39.0625f, +-46.875f,18.478f,39.0625f, +-42.9688f,19.4144f,39.0625f, +-39.0625f,19.9351f,39.0625f, +-35.1563f,20.3447f,39.0625f, +-31.25f,22.4348f,39.0625f, +-27.3438f,24.5713f,39.0625f, +-23.4375f,25.5465f,39.0625f, +-19.5313f,26.485f,39.0625f, +-15.625f,28.292f,39.0625f, +-11.7188f,30.0016f,39.0625f, +-7.8125f,32.2532f,39.0625f, +-3.90625f,33.6327f,39.0625f, +0.0f,33.835f,39.0625f, +3.90625f,34.9171f,39.0625f, +-250.0f,3.91889f,35.1563f, +-246.094f,3.38127f,35.1563f, +-242.188f,3.26935f,35.1563f, +-238.281f,4.06778f,35.1563f, +-234.375f,4.87411f,35.1563f, +-230.469f,6.48873f,35.1563f, +-226.563f,7.17326f,35.1563f, +-222.656f,8.21235f,35.1563f, +-218.75f,8.21965f,35.1563f, +-214.844f,10.417f,35.1563f, +-210.938f,11.9497f,35.1563f, +-207.031f,13.4145f,35.1563f, +-203.125f,14.0876f,35.1563f, +-199.219f,15.5077f,35.1563f, +-195.313f,16.9011f,35.1563f, +-191.406f,20.4395f,35.1563f, +-187.5f,23.001f,35.1563f, +-183.594f,24.0199f,35.1563f, +-179.688f,25.7082f,35.1563f, +-175.781f,27.3018f,35.1563f, +-171.875f,28.9584f,35.1563f, +-167.969f,31.1478f,35.1563f, +-164.063f,32.8635f,35.1563f, +-160.156f,33.5517f,35.1563f, +-156.25f,34.5761f,35.1563f, +-152.344f,34.5761f,35.1563f, +-148.438f,34.2002f,35.1563f, +-144.531f,34.7177f,35.1563f, +-140.625f,35.5653f,35.1563f, +-136.719f,35.7993f,35.1563f, +-132.813f,37.1127f,35.1563f, +-128.906f,37.2477f,35.1563f, +-125.0f,36.8734f,35.1563f, +-121.094f,35.4154f,35.1563f, +-117.188f,34.8545f,35.1563f, +-113.281f,35.4317f,35.1563f, +-109.375f,34.9205f,35.1563f, +-105.469f,33.5115f,35.1563f, +-101.563f,32.2368f,35.1563f, +-97.6563f,30.3601f,35.1563f, +-93.75f,29.2913f,35.1563f, +-89.8438f,27.4791f,35.1563f, +-85.9375f,24.811f,35.1563f, +-82.0313f,23.4984f,35.1563f, +-78.125f,21.456f,35.1563f, +-74.2188f,19.8992f,35.1563f, +-70.3125f,17.7354f,35.1563f, +-66.4063f,17.3066f,35.1563f, +-62.5f,17.1745f,35.1563f, +-58.5938f,16.5285f,35.1563f, +-54.6875f,17.2826f,35.1563f, +-50.7813f,18.6936f,35.1563f, +-46.875f,19.4228f,35.1563f, +-42.9688f,20.2022f,35.1563f, +-39.0625f,21.4261f,35.1563f, +-35.1563f,21.5779f,35.1563f, +-31.25f,24.0097f,35.1563f, +-27.3438f,25.4481f,35.1563f, +-23.4375f,26.0036f,35.1563f, +-19.5313f,27.4346f,35.1563f, +-15.625f,30.2459f,35.1563f, +-11.7188f,32.81f,35.1563f, +-7.8125f,34.7924f,35.1563f, +-3.90625f,35.8907f,35.1563f, +0.0f,36.9755f,35.1563f, +3.90625f,38.5427f,35.1563f, +-250.0f,2.28536f,31.25f, +-246.094f,1.63842f,31.25f, +-242.188f,2.40273f,31.25f, +-238.281f,3.19518f,31.25f, +-234.375f,3.99394f,31.25f, +-230.469f,4.99674f,31.25f, +-226.563f,5.63235f,31.25f, +-222.656f,6.86331f,31.25f, +-218.75f,7.37515f,31.25f, +-214.844f,9.34737f,31.25f, +-210.938f,11.7034f,31.25f, +-207.031f,13.4309f,31.25f, +-203.125f,14.4474f,31.25f, +-199.219f,15.8817f,31.25f, +-195.313f,17.87f,31.25f, +-191.406f,20.9938f,31.25f, +-187.5f,23.5333f,31.25f, +-183.594f,24.4107f,31.25f, +-179.688f,26.0811f,31.25f, +-175.781f,27.9797f,31.25f, +-171.875f,29.4813f,31.25f, +-167.969f,31.7071f,31.25f, +-164.063f,33.0836f,31.25f, +-160.156f,33.5998f,31.25f, +-156.25f,33.5304f,31.25f, +-152.344f,33.9929f,31.25f, +-148.438f,35.4297f,31.25f, +-144.531f,36.4531f,31.25f, +-140.625f,35.9197f,31.25f, +-136.719f,36.6849f,31.25f, +-132.813f,37.8161f,31.25f, +-128.906f,37.6166f,31.25f, +-125.0f,36.9426f,31.25f, +-121.094f,35.6388f,31.25f, +-117.188f,35.0026f,31.25f, +-113.281f,35.386f,31.25f, +-109.375f,34.6287f,31.25f, +-105.469f,33.8962f,31.25f, +-101.563f,32.1844f,31.25f, +-97.6563f,30.7868f,31.25f, +-93.75f,29.267f,31.25f, +-89.8438f,27.2585f,31.25f, +-85.9375f,25.4236f,31.25f, +-82.0313f,23.0281f,31.25f, +-78.125f,21.4593f,31.25f, +-74.2188f,19.4556f,31.25f, +-70.3125f,18.0982f,31.25f, +-66.4063f,17.1214f,31.25f, +-62.5f,17.1751f,31.25f, +-58.5938f,17.1429f,31.25f, +-54.6875f,18.4434f,31.25f, +-50.7813f,19.9422f,31.25f, +-46.875f,21.2124f,31.25f, +-42.9688f,21.2106f,31.25f, +-39.0625f,22.1346f,31.25f, +-35.1563f,23.3082f,31.25f, +-31.25f,24.7044f,31.25f, +-27.3438f,26.2688f,31.25f, +-23.4375f,27.5692f,31.25f, +-19.5313f,30.4099f,31.25f, +-15.625f,33.0453f,31.25f, +-11.7188f,34.9857f,31.25f, +-7.8125f,37.0727f,31.25f, +-3.90625f,39.2219f,31.25f, +0.0f,40.3658f,31.25f, +3.90625f,41.4381f,31.25f, +-250.0f,0.4773f,27.3438f, +-246.094f,0.631847f,27.3438f, +-242.188f,1.21449f,27.3438f, +-238.281f,1.52728f,27.3438f, +-234.375f,2.73146f,27.3438f, +-230.469f,3.65375f,27.3438f, +-226.563f,5.03467f,27.3438f, +-222.656f,6.27065f,27.3438f, +-218.75f,7.56964f,27.3438f, +-214.844f,9.63719f,27.3438f, +-210.938f,11.4022f,27.3438f, +-207.031f,12.7085f,27.3438f, +-203.125f,14.3808f,27.3438f, +-199.219f,15.9121f,27.3438f, +-195.313f,17.8953f,27.3438f, +-191.406f,20.8456f,27.3438f, +-187.5f,22.7705f,27.3438f, +-183.594f,24.5794f,27.3437f, +-179.688f,27.055f,27.3438f, +-175.781f,29.3548f,27.3437f, +-171.875f,30.4534f,27.3438f, +-167.969f,32.4366f,27.3437f, +-164.063f,34.4967f,27.3438f, +-160.156f,34.9614f,27.3437f, +-156.25f,34.9405f,27.3438f, +-152.344f,35.7165f,27.3437f, +-148.438f,37.0387f,27.3438f, +-144.531f,38.0934f,27.3437f, +-140.625f,37.3872f,27.3438f, +-136.719f,36.4336f,27.3437f, +-132.813f,37.0365f,27.3438f, +-128.906f,37.2591f,27.3437f, +-125.0f,36.5502f,27.3438f, +-121.094f,35.4814f,27.3437f, +-117.188f,35.3267f,27.3438f, +-113.281f,34.3757f,27.3437f, +-109.375f,34.2455f,27.3438f, +-105.469f,33.6851f,27.3437f, +-101.563f,32.3527f,27.3438f, +-97.6563f,30.111f,27.3437f, +-93.75f,28.4912f,27.3438f, +-89.8438f,27.0398f,27.3437f, +-85.9375f,24.9699f,27.3438f, +-82.0313f,22.9703f,27.3437f, +-78.125f,21.7502f,27.3438f, +-74.2188f,18.8537f,27.3438f, +-70.3125f,18.2353f,27.3438f, +-66.4063f,18.3708f,27.3438f, +-62.5f,18.6738f,27.3438f, +-58.5938f,18.5559f,27.3438f, +-54.6875f,19.1603f,27.3438f, +-50.7813f,20.8349f,27.3438f, +-46.875f,21.6092f,27.3438f, +-42.9688f,21.9317f,27.3437f, +-39.0625f,23.0486f,27.3438f, +-35.1563f,24.8675f,27.3437f, +-31.25f,25.6906f,27.3438f, +-27.3438f,27.9695f,27.3437f, +-23.4375f,30.3105f,27.3438f, +-19.5313f,33.9897f,27.3437f, +-15.625f,35.6988f,27.3438f, +-11.7188f,37.9213f,27.3437f, +-7.8125f,40.1355f,27.3438f, +-3.90625f,41.6062f,27.3437f, +0.0f,42.273f,27.3438f, +3.90625f,42.7334f,27.3437f, +-250.0f,0.178144f,23.4375f, +-246.094f,1.07943f,23.4375f, +-242.188f,1.52473f,23.4375f, +-238.281f,2.58652f,23.4375f, +-234.375f,3.51451f,23.4375f, +-230.469f,4.23103f,23.4375f, +-226.563f,5.80506f,23.4375f, +-222.656f,7.26086f,23.4375f, +-218.75f,8.85201f,23.4375f, +-214.844f,10.9029f,23.4375f, +-210.938f,12.7138f,23.4375f, +-207.031f,14.9249f,23.4375f, +-203.125f,15.6506f,23.4375f, +-199.219f,16.529f,23.4375f, +-195.313f,17.1535f,23.4375f, +-191.406f,20.5632f,23.4375f, +-187.5f,23.1009f,23.4375f, +-183.594f,24.7859f,23.4375f, +-179.688f,26.8635f,23.4375f, +-175.781f,28.5723f,23.4375f, +-171.875f,30.2918f,23.4375f, +-167.969f,32.7768f,23.4375f, +-164.063f,34.6199f,23.4375f, +-160.156f,35.6902f,23.4375f, +-156.25f,37.1166f,23.4375f, +-152.344f,37.0816f,23.4375f, +-148.438f,37.9995f,23.4375f, +-144.531f,38.687f,23.4375f, +-140.625f,37.9261f,23.4375f, +-136.719f,36.7476f,23.4375f, +-132.813f,37.1839f,23.4375f, +-128.906f,36.8682f,23.4375f, +-125.0f,36.2555f,23.4375f, +-121.094f,34.8461f,23.4375f, +-117.188f,34.5757f,23.4375f, +-113.281f,33.8965f,23.4375f, +-109.375f,33.4987f,23.4375f, +-105.469f,33.02f,23.4375f, +-101.563f,31.4543f,23.4375f, +-97.6563f,29.5899f,23.4375f, +-93.75f,27.8808f,23.4375f, +-89.8438f,26.4886f,23.4375f, +-85.9375f,24.5413f,23.4375f, +-82.0313f,22.6097f,23.4375f, +-78.125f,21.38f,23.4375f, +-74.2188f,19.2574f,23.4375f, +-70.3125f,19.6862f,23.4375f, +-66.4063f,19.3283f,23.4375f, +-62.5f,20.3608f,23.4375f, +-58.5938f,20.9969f,23.4375f, +-54.6875f,20.5645f,23.4375f, +-50.7813f,21.6338f,23.4375f, +-46.875f,22.0705f,23.4375f, +-42.9688f,23.2924f,23.4375f, +-39.0625f,24.8627f,23.4375f, +-35.1563f,25.9292f,23.4375f, +-31.25f,27.2133f,23.4375f, +-27.3438f,29.7296f,23.4375f, +-23.4375f,32.8149f,23.4375f, +-19.5313f,35.5321f,23.4375f, +-15.625f,38.2144f,23.4375f, +-11.7188f,40.2421f,23.4375f, +-7.8125f,41.7479f,23.4375f, +-3.90625f,43.372f,23.4375f, +0.0f,43.7526f,23.4375f, +3.90625f,44.6783f,23.4375f, +-250.0f,0.138221f,19.5313f, +-246.094f,1.4004f,19.5313f, +-242.188f,3.26515f,19.5313f, +-238.281f,3.65276f,19.5313f, +-234.375f,4.90602f,19.5313f, +-230.469f,6.03349f,19.5313f, +-226.563f,7.99773f,19.5313f, +-222.656f,9.41728f,19.5313f, +-218.75f,10.0435f,19.5313f, +-214.844f,12.1613f,19.5313f, +-210.938f,13.6999f,19.5313f, +-207.031f,15.7603f,19.5313f, +-203.125f,16.1549f,19.5313f, +-199.219f,17.1021f,19.5313f, +-195.313f,18.1867f,19.5313f, +-191.406f,20.6836f,19.5313f, +-187.5f,23.0865f,19.5312f, +-183.594f,24.3015f,19.5313f, +-179.688f,26.6623f,19.5312f, +-175.781f,28.232f,19.5313f, +-171.875f,30.6454f,19.5312f, +-167.969f,32.8674f,19.5313f, +-164.063f,35.0881f,19.5312f, +-160.156f,37.2715f,19.5313f, +-156.25f,38.6025f,19.5312f, +-152.344f,38.2781f,19.5313f, +-148.438f,38.4813f,19.5312f, +-144.531f,38.3281f,19.5313f, +-140.625f,38.1441f,19.5312f, +-136.719f,37.6066f,19.5312f, +-132.813f,37.2097f,19.5312f, +-128.906f,36.5694f,19.5312f, +-125.0f,36.2416f,19.5312f, +-121.094f,34.5305f,19.5312f, +-117.188f,33.3684f,19.5312f, +-113.281f,32.7805f,19.5312f, +-109.375f,31.8563f,19.5312f, +-105.469f,31.3398f,19.5312f, +-101.563f,29.7387f,19.5312f, +-97.6563f,28.7121f,19.5312f, +-93.75f,27.8904f,19.5312f, +-89.8438f,26.0256f,19.5312f, +-85.9375f,24.5469f,19.5312f, +-82.0313f,23.3531f,19.5312f, +-78.125f,21.4621f,19.5313f, +-74.2188f,20.3507f,19.5313f, +-70.3125f,20.1879f,19.5313f, +-66.4063f,20.9838f,19.5313f, +-62.5f,22.229f,19.5312f, +-58.5938f,22.355f,19.5312f, +-54.6875f,22.7659f,19.5312f, +-50.7813f,22.9258f,19.5312f, +-46.875f,23.554f,19.5312f, +-42.9688f,24.3861f,19.5312f, +-39.0625f,25.5112f,19.5312f, +-35.1563f,26.8691f,19.5312f, +-31.25f,28.968f,19.5312f, +-27.3438f,31.0124f,19.5312f, +-23.4375f,34.8357f,19.5312f, +-19.5313f,37.2362f,19.5312f, +-15.625f,39.5924f,19.5312f, +-11.7188f,41.5691f,19.5312f, +-7.8125f,43.2441f,19.5312f, +-3.90625f,45.1168f,19.5312f, +0.0f,45.7555f,19.5312f, +3.90625f,46.9055f,19.5312f, +-250.0f,0.462936f,15.625f, +-246.094f,2.15489f,15.625f, +-242.188f,3.69232f,15.625f, +-238.281f,4.89361f,15.625f, +-234.375f,6.95706f,15.625f, +-230.469f,8.37916f,15.625f, +-226.563f,9.21515f,15.625f, +-222.656f,10.0624f,15.625f, +-218.75f,11.6477f,15.625f, +-214.844f,13.257f,15.625f, +-210.938f,14.8699f,15.625f, +-207.031f,15.9852f,15.625f, +-203.125f,17.025f,15.625f, +-199.219f,17.8511f,15.625f, +-195.313f,20.3581f,15.625f, +-191.406f,22.0829f,15.625f, +-187.5f,24.4216f,15.625f, +-183.594f,25.5625f,15.625f, +-179.688f,27.0961f,15.625f, +-175.781f,30.0958f,15.625f, +-171.875f,31.7977f,15.625f, +-167.969f,34.7043f,15.625f, +-164.063f,37.1655f,15.625f, +-160.156f,37.6823f,15.625f, +-156.25f,37.6204f,15.625f, +-152.344f,37.8037f,15.625f, +-148.438f,37.8555f,15.625f, +-144.531f,37.9638f,15.625f, +-140.625f,37.4821f,15.625f, +-136.719f,37.0202f,15.625f, +-132.813f,36.4604f,15.625f, +-128.906f,36.1575f,15.625f, +-125.0f,35.4218f,15.625f, +-121.094f,33.5202f,15.625f, +-117.188f,32.116f,15.625f, +-113.281f,30.9352f,15.625f, +-109.375f,29.8297f,15.625f, +-105.469f,29.9146f,15.625f, +-101.563f,28.7245f,15.625f, +-97.6563f,27.7205f,15.625f, +-93.75f,27.4217f,15.625f, +-89.8438f,25.8557f,15.625f, +-85.9375f,24.0609f,15.625f, +-82.0313f,22.7869f,15.625f, +-78.125f,20.4923f,15.625f, +-74.2188f,21.0025f,15.625f, +-70.3125f,21.2985f,15.625f, +-66.4063f,22.5717f,15.625f, +-62.5f,23.0569f,15.625f, +-58.5938f,23.2123f,15.625f, +-54.6875f,24.1861f,15.625f, +-50.7813f,24.5626f,15.625f, +-46.875f,25.1259f,15.625f, +-42.9688f,25.9995f,15.625f, +-39.0625f,26.8682f,15.625f, +-35.1563f,27.8593f,15.625f, +-31.25f,29.8924f,15.625f, +-27.3438f,32.8894f,15.625f, +-23.4375f,36.2901f,15.625f, +-19.5313f,38.2475f,15.625f, +-15.625f,40.593f,15.625f, +-11.7188f,42.2973f,15.625f, +-7.8125f,45.3308f,15.625f, +-3.90625f,47.345f,15.625f, +0.0f,48.9808f,15.625f, +3.90625f,49.2295f,15.625f, +-250.0f,1.16646f,11.7188f, +-246.094f,2.99331f,11.7188f, +-242.188f,4.37829f,11.7188f, +-238.281f,5.21593f,11.7188f, +-234.375f,6.84374f,11.7188f, +-230.469f,8.34616f,11.7188f, +-226.563f,9.2826f,11.7188f, +-222.656f,9.90104f,11.7188f, +-218.75f,10.9211f,11.7187f, +-214.844f,13.6881f,11.7187f, +-210.938f,15.7745f,11.7187f, +-207.031f,16.2325f,11.7187f, +-203.125f,17.2525f,11.7187f, +-199.219f,19.1108f,11.7187f, +-195.313f,21.4743f,11.7187f, +-191.406f,24.021f,11.7187f, +-187.5f,25.8676f,11.7187f, +-183.594f,27.021f,11.7187f, +-179.688f,28.254f,11.7187f, +-175.781f,31.6036f,11.7187f, +-171.875f,32.629f,11.7187f, +-167.969f,34.9526f,11.7187f, +-164.063f,36.8236f,11.7187f, +-160.156f,37.152f,11.7187f, +-156.25f,37.6659f,11.7187f, +-152.344f,37.4102f,11.7187f, +-148.438f,37.0806f,11.7187f, +-144.531f,37.6299f,11.7187f, +-140.625f,36.7269f,11.7187f, +-136.719f,36.4841f,11.7187f, +-132.813f,35.2557f,11.7187f, +-128.906f,34.7066f,11.7187f, +-125.0f,34.0947f,11.7187f, +-121.094f,32.7343f,11.7187f, +-117.188f,31.5605f,11.7187f, +-113.281f,30.7492f,11.7187f, +-109.375f,30.1608f,11.7187f, +-105.469f,29.9144f,11.7187f, +-101.563f,28.5532f,11.7187f, +-97.6563f,26.2051f,11.7187f, +-93.75f,26.0432f,11.7187f, +-89.8438f,25.1831f,11.7187f, +-85.9375f,23.7935f,11.7187f, +-82.0313f,22.6952f,11.7187f, +-78.125f,21.9812f,11.7187f, +-74.2188f,22.3423f,11.7187f, +-70.3125f,22.4959f,11.7187f, +-66.4063f,22.9438f,11.7187f, +-62.5f,23.6591f,11.7187f, +-58.5938f,24.1634f,11.7187f, +-54.6875f,24.8781f,11.7187f, +-50.7813f,25.3471f,11.7187f, +-46.875f,25.7599f,11.7187f, +-42.9688f,26.61f,11.7187f, +-39.0625f,27.5033f,11.7187f, +-35.1563f,29.2751f,11.7187f, +-31.25f,31.9147f,11.7187f, +-27.3438f,34.1964f,11.7187f, +-23.4375f,36.7734f,11.7187f, +-19.5313f,39.2441f,11.7187f, +-15.625f,41.3269f,11.7187f, +-11.7188f,44.2682f,11.7187f, +-7.8125f,47.2458f,11.7187f, +-3.90625f,49.2199f,11.7187f, +0.0f,50.2546f,11.7187f, +3.90625f,51.1233f,11.7187f, +-250.0f,1.52698f,7.8125f, +-246.094f,2.97227f,7.8125f, +-242.188f,3.77319f,7.8125f, +-238.281f,4.81095f,7.8125f, +-234.375f,5.94458f,7.8125f, +-230.469f,7.45352f,7.8125f, +-226.563f,8.9683f,7.8125f, +-222.656f,9.37348f,7.8125f, +-218.75f,10.3818f,7.8125f, +-214.844f,13.0632f,7.8125f, +-210.938f,15.5836f,7.8125f, +-207.031f,17.1532f,7.8125f, +-203.125f,19.3065f,7.8125f, +-199.219f,21.746f,7.8125f, +-195.313f,23.0026f,7.8125f, +-191.406f,25.1876f,7.8125f, +-187.5f,27.4911f,7.8125f, +-183.594f,28.651f,7.8125f, +-179.688f,28.9685f,7.8125f, +-175.781f,31.1275f,7.8125f, +-171.875f,32.457f,7.8125f, +-167.969f,34.4336f,7.8125f, +-164.063f,35.9124f,7.8125f, +-160.156f,36.5078f,7.8125f, +-156.25f,36.9999f,7.8125f, +-152.344f,36.9517f,7.8125f, +-148.438f,37.9713f,7.8125f, +-144.531f,37.929f,7.8125f, +-140.625f,37.5334f,7.8125f, +-136.719f,36.2798f,7.8125f, +-132.813f,35.1904f,7.8125f, +-128.906f,33.7356f,7.8125f, +-125.0f,34.0968f,7.8125f, +-121.094f,33.5838f,7.8125f, +-117.188f,32.9371f,7.8125f, +-113.281f,32.0353f,7.8125f, +-109.375f,31.4623f,7.8125f, +-105.469f,30.5184f,7.8125f, +-101.563f,28.7396f,7.8125f, +-97.6563f,27.2715f,7.8125f, +-93.75f,26.1242f,7.8125f, +-89.8438f,24.5691f,7.8125f, +-85.9375f,23.931f,7.8125f, +-82.0313f,23.7643f,7.8125f, +-78.125f,22.4588f,7.8125f, +-74.2188f,22.5395f,7.8125f, +-70.3125f,22.9322f,7.8125f, +-66.4063f,23.4361f,7.8125f, +-62.5f,24.2733f,7.8125f, +-58.5938f,24.1873f,7.8125f, +-54.6875f,24.2666f,7.8125f, +-50.7813f,25.2522f,7.8125f, +-46.875f,26.3494f,7.8125f, +-42.9688f,26.8365f,7.8125f, +-39.0625f,27.5515f,7.8125f, +-35.1563f,30.4441f,7.8125f, +-31.25f,33.5547f,7.8125f, +-27.3438f,36.1409f,7.8125f, +-23.4375f,38.1103f,7.8125f, +-19.5313f,39.8171f,7.8125f, +-15.625f,42.1146f,7.8125f, +-11.7188f,45.3603f,7.8125f, +-7.8125f,47.6602f,7.8125f, +-3.90625f,49.963f,7.8125f, +0.0f,51.8119f,7.8125f, +3.90625f,52.2527f,7.8125f, +-250.0f,0.139875f,3.90625f, +-246.094f,1.72995f,3.90625f, +-242.188f,2.60122f,3.90625f, +-238.281f,4.01346f,3.90625f, +-234.375f,5.13654f,3.90625f, +-230.469f,6.69665f,3.90625f, +-226.563f,8.43203f,3.90625f, +-222.656f,9.83442f,3.90625f, +-218.75f,11.3645f,3.90625f, +-214.844f,14.222f,3.90625f, +-210.938f,16.1758f,3.90625f, +-207.031f,18.9127f,3.90625f, +-203.125f,21.2478f,3.90625f, +-199.219f,23.0589f,3.90625f, +-195.313f,24.6025f,3.90625f, +-191.406f,25.8143f,3.90625f, +-187.5f,27.5696f,3.90625f, +-183.594f,29.2176f,3.90625f, +-179.688f,29.6835f,3.90625f, +-175.781f,30.7416f,3.90625f, +-171.875f,31.4405f,3.90625f, +-167.969f,33.0831f,3.90625f, +-164.063f,34.6225f,3.90625f, +-160.156f,35.4992f,3.90625f, +-156.25f,37.4126f,3.90625f, +-152.344f,38.453f,3.90625f, +-148.438f,38.9974f,3.90625f, +-144.531f,38.7871f,3.90625f, +-140.625f,37.6021f,3.90625f, +-136.719f,36.1797f,3.90625f, +-132.813f,34.9906f,3.90625f, +-128.906f,34.1304f,3.90625f, +-125.0f,34.3517f,3.90625f, +-121.094f,33.6612f,3.90625f, +-117.188f,32.7047f,3.90625f, +-113.281f,32.3958f,3.90625f, +-109.375f,31.0818f,3.90625f, +-105.469f,30.9536f,3.90625f, +-101.563f,29.8205f,3.90625f, +-97.6563f,28.4796f,3.90625f, +-93.75f,27.6494f,3.90625f, +-89.8438f,25.5721f,3.90625f, +-85.9375f,24.227f,3.90625f, +-82.0313f,23.2611f,3.90625f, +-78.125f,22.4589f,3.90625f, +-74.2188f,23.2261f,3.90625f, +-70.3125f,23.5025f,3.90625f, +-66.4063f,23.6913f,3.90625f, +-62.5f,24.6785f,3.90625f, +-58.5938f,25.4946f,3.90625f, +-54.6875f,25.9722f,3.90625f, +-50.7813f,26.1977f,3.90625f, +-46.875f,26.8539f,3.90625f, +-42.9688f,27.7268f,3.90625f, +-39.0625f,29.2046f,3.90625f, +-35.1563f,31.79f,3.90625f, +-31.25f,34.2658f,3.90625f, +-27.3438f,35.9914f,3.90625f, +-23.4375f,38.3776f,3.90625f, +-19.5313f,39.8852f,3.90625f, +-15.625f,43.1455f,3.90625f, +-11.7188f,45.5059f,3.90625f, +-7.8125f,47.4257f,3.90625f, +-3.90625f,49.9032f,3.90625f, +0.0f,52.0322f,3.90625f, +3.90625f,52.6186f,3.90625f, +}; + +btScalar Landscape02Nml[] = { +0.376889f,0.897995f,0.227068f, +0.251083f,0.961355f,0.112931f, +0.256071f,0.961946f,0.0953332f, +0.188246f,0.981544f,0.0336933f, +0.321782f,0.946812f,0.00191405f, +0.277829f,0.960055f,0.0332431f, +0.366908f,0.922321f,-0.121252f, +0.346681f,0.936118f,-0.0591191f, +0.34598f,0.936023f,-0.0644918f, +0.326882f,0.934733f,-0.139364f, +0.195537f,0.979014f,-0.0574119f, +0.208421f,0.974173f,-0.0868766f, +0.220158f,0.96963f,-0.106528f, +0.21764f,0.974169f,-0.0602246f, +0.194781f,0.966032f,-0.169831f, +0.137923f,0.97923f,-0.148611f, +-0.0890295f,0.968844f,-0.231118f, +-0.164208f,0.952108f,-0.257926f, +-0.299547f,0.905883f,-0.299413f, +-0.331781f,0.892916f,-0.304338f, +-0.275234f,0.921181f,-0.275086f, +-0.190055f,0.968186f,-0.162776f, +-0.191147f,0.964101f,-0.184313f, +-0.167051f,0.973656f,-0.155201f, +-0.260549f,0.956867f,-0.128527f, +-0.236175f,0.968373f,-0.080466f, +-0.305083f,0.942279f,-0.137969f, +-0.32302f,0.940678f,-0.103844f, +-0.376654f,0.91108f,-0.167524f, +-0.43665f,0.882087f,-0.176802f, +-0.404697f,0.87224f,-0.274621f, +-0.461396f,0.842558f,-0.277868f, +-0.340534f,0.861872f,-0.375783f, +-0.381498f,0.847049f,-0.370091f, +-0.349262f,0.83292f,-0.429255f, +-0.383821f,0.842401f,-0.378209f, +-0.350717f,0.827302f,-0.438826f, +-0.312636f,0.886963f,-0.339934f, +-0.202637f,0.921293f,-0.331899f, +-0.164853f,0.917655f,-0.361571f, +-0.320762f,0.929092f,-0.184116f, +-0.291289f,0.89543f,-0.336684f, +-0.523923f,0.850919f,-0.0379686f, +-0.415222f,0.907809f,-0.0589323f, +-0.464751f,0.884928f,0.030152f, +-0.464228f,0.885715f,0.00114487f, +-0.460666f,0.887573f,-0.00119475f, +-0.527574f,0.824073f,-0.206324f, +-0.569463f,0.819886f,-0.0591577f, +-0.624043f,0.739025f,-0.253797f, +-0.677912f,0.708815f,-0.19498f, +-0.654991f,0.737431f,-0.164874f, +-0.612102f,0.778841f,-0.136883f, +-0.555251f,0.829082f,-0.0657209f, +-0.466796f,0.884362f,-0.00238444f, +-0.393172f,0.917844f,0.0545768f, +-0.415266f,0.902781f,0.111985f, +-0.346174f,0.92512f,0.155936f, +-0.270143f,0.942251f,0.197955f, +-0.242693f,0.931939f,0.269424f, +-0.146828f,0.979561f,0.137484f, +-0.151815f,0.949716f,0.273847f, +-0.23746f,0.962635f,0.130183f, +-0.242269f,0.936807f,0.252385f, +-0.439066f,0.897439f,0.0427119f, +-0.506925f,0.859633f,0.0637107f, +-0.369534f,0.927612f,0.0545955f, +-0.266432f,0.921234f,0.283447f, +-0.0849634f,0.983229f,0.161377f, +-0.142422f,0.97399f,0.176238f, +0.059987f,0.992193f,0.109333f, +-0.00609097f,0.990503f,0.137353f, +0.218751f,0.975042f,-0.0379662f, +0.195675f,0.973574f,0.117747f, +0.412438f,0.903178f,-0.119012f, +0.389829f,0.920771f,0.01463f, +0.471887f,0.878868f,-0.0700914f, +0.512637f,0.843878f,0.158344f, +0.438398f,0.898776f,-0.0028899f, +0.463505f,0.872879f,0.152466f, +0.213581f,0.96879f,0.125817f, +0.217949f,0.966902f,0.132661f, +0.150053f,0.978231f,0.143348f, +0.183142f,0.954792f,0.234161f, +0.324547f,0.937949f,0.122152f, +0.305949f,0.944044f,0.123194f, +0.404781f,0.90011f,0.161105f, +0.386685f,0.917163f,0.0963685f, +0.43511f,0.894378f,0.103764f, +0.444378f,0.884165f,0.144156f, +0.485066f,0.871945f,0.0665013f, +0.480511f,0.864609f,0.146835f, +0.542329f,0.83784f,0.0624783f, +0.538258f,0.834152f,0.120286f, +0.497652f,0.86488f,0.0657686f, +0.471897f,0.881288f,0.0253797f, +0.368509f,0.927548f,0.0620863f, +0.391828f,0.918428f,0.0544149f, +0.284879f,0.953389f,0.0994662f, +0.359932f,0.902669f,0.235877f, +0.19297f,0.969614f,0.150374f, +0.198191f,0.923716f,0.327825f, +0.174784f,0.978101f,0.113003f, +0.121688f,0.95783f,0.260297f, +0.3291f,0.939598f,0.094074f, +0.241925f,0.967997f,0.066744f, +0.275982f,0.959352f,0.0589789f, +0.207349f,0.969048f,-0.133986f, +-0.048418f,0.997403f,0.0533214f, +-0.0214229f,0.995947f,-0.0873486f, +-0.224808f,0.97209f,0.0671032f, +-0.154526f,0.98721f,0.0392114f, +-0.0539424f,0.990401f,0.127262f, +0.0294265f,0.986864f,0.158851f, +0.115045f,0.967726f,0.224212f, +0.135755f,0.967813f,0.211917f, +-0.0987201f,0.976534f,0.191406f, +-0.208734f,0.974954f,0.0767793f, +-0.346094f,0.938088f,0.0144628f, +-0.364883f,0.930977f,0.0119327f, +-0.234075f,0.972082f,0.0162811f, +-0.216489f,0.973875f,0.0685516f, +-0.126585f,0.991898f,0.0107448f, +-0.188432f,0.981937f,-0.0171439f, +-0.186728f,0.980312f,-0.0641921f, +-0.243763f,0.959118f,-0.14378f, +-0.256453f,0.962392f,-0.0896326f, +-0.227009f,0.972481f,-0.0524148f, +-0.308642f,0.945388f,-0.104794f, +-0.322884f,0.94242f,-0.0871231f, +-0.32494f,0.940988f,-0.0946312f, +-0.365791f,0.920972f,-0.134189f, +0.507209f,0.830952f,0.228598f, +0.427157f,0.893788f,0.136676f, +0.390358f,0.920644f,0.00595094f, +0.357f,0.931227f,0.0732586f, +0.253669f,0.95455f,0.156478f, +0.247974f,0.954291f,0.166849f, +0.303694f,0.950352f,0.0678299f, +0.260247f,0.965246f,0.0238949f, +-0.0615746f,0.996768f,-0.0515863f, +-0.225111f,0.970921f,-0.0814727f, +-0.33579f,0.924057f,-0.18266f, +-0.286567f,0.949099f,-0.13073f, +-0.266283f,0.957101f,-0.114241f, +-0.297972f,0.942451f,-0.151651f, +-0.345158f,0.930403f,-0.123358f, +-0.323606f,0.933615f,-0.153759f, +-0.295216f,0.935234f,-0.195409f, +-0.294262f,0.935546f,-0.195355f, +-0.367877f,0.896699f,-0.246165f, +-0.460611f,0.856308f,-0.233612f, +-0.493615f,0.869663f,0.00556421f, +-0.56572f,0.819247f,0.0937815f, +-0.482796f,0.868728f,0.110547f, +-0.473443f,0.870107f,0.136985f, +-0.486628f,0.863931f,0.12968f, +-0.584612f,0.809918f,-0.0475519f, +-0.673803f,0.720247f,-0.165027f, +-0.584438f,0.811258f,-0.0171189f, +-0.49626f,0.855798f,0.146063f, +-0.266763f,0.927018f,0.26358f, +-0.000318467f,0.974136f,0.225963f, +-0.2098f,0.977621f,0.015525f, +-0.363964f,0.929076f,-0.0659462f, +-0.427799f,0.890708f,-0.153708f, +-0.226888f,0.973494f,-0.0288381f, +0.176474f,0.981f,0.080593f, +0.382766f,0.920418f,-0.0794987f, +0.4558f,0.874041f,-0.16822f, +0.44168f,0.87342f,-0.205075f, +0.269141f,0.944688f,-0.187422f, +0.0983269f,0.994746f,0.0285051f, +0.164874f,0.980231f,0.10938f, +0.300398f,0.949423f,0.0914149f, +0.370498f,0.925363f,0.0802133f, +0.51325f,0.857062f,0.0449297f, +0.515688f,0.85628f,-0.0291725f, +0.532902f,0.845818f,-0.0246416f, +0.470584f,0.882352f,0.00224652f, +0.358364f,0.932053f,0.0534101f, +0.299916f,0.948938f,0.0978121f, +0.234125f,0.96956f,0.0716857f, +0.201429f,0.97943f,0.0119968f, +0.257021f,0.965839f,0.0330825f, +0.205585f,0.966488f,0.153741f, +-0.0291083f,0.972977f,0.22906f, +-0.183781f,0.97216f,0.145362f, +-0.0880966f,0.991634f,0.0943445f, +0.0404056f,0.991359f,0.124796f, +-0.0259416f,0.986408f,0.162256f, +-0.213262f,0.97241f,0.0945471f, +-0.221976f,0.974645f,0.0281856f, +-0.137418f,0.990413f,0.014064f, +-0.147111f,0.988464f,0.0360112f, +-0.213681f,0.97687f,0.00813376f, +-0.286716f,0.957516f,-0.0309366f, +-0.362687f,0.929548f,-0.0663186f, +0.471826f,0.881687f,0.00273101f, +0.493844f,0.862721f,0.108764f, +0.305852f,0.940961f,0.145073f, +0.225186f,0.91763f,0.327484f, +0.255894f,0.905552f,0.33837f, +0.302798f,0.922674f,0.238719f, +0.353759f,0.914443f,0.196594f, +0.301669f,0.941039f,0.153105f, +0.00675732f,0.993813f,0.110864f, +-0.180673f,0.978312f,0.101302f, +-0.247784f,0.966857f,0.0615767f, +-0.309703f,0.949482f,-0.0506691f, +-0.243038f,0.969623f,-0.0276337f, +-0.257234f,0.966017f,-0.0253295f, +-0.381367f,0.920413f,-0.0860151f, +-0.354157f,0.93479f,-0.027217f, +-0.299485f,0.952671f,0.0522246f, +-0.356888f,0.9323f,0.0587106f, +-0.335176f,0.924244f,0.182839f, +-0.500593f,0.855036f,0.135351f, +-0.576428f,0.801243f,0.160441f, +-0.583679f,0.788168f,0.195218f, +-0.491918f,0.829821f,0.263465f, +-0.431671f,0.862042f,0.2656f, +-0.443518f,0.883408f,0.151265f, +-0.464317f,0.881859f,0.0820666f, +-0.652068f,0.753609f,-0.0829502f, +-0.681939f,0.728217f,-0.068254f, +-0.591161f,0.804152f,0.0621953f, +-0.352647f,0.921747f,0.161318f, +0.0545396f,0.95959f,0.276065f, +0.0694942f,0.971972f,0.224591f, +-0.253858f,0.964902f,-0.0672354f, +-0.408551f,0.900688f,-0.147807f, +-0.327666f,0.933936f,-0.142825f, +0.129878f,0.985787f,-0.106564f, +0.442239f,0.89421f,-0.0693695f, +0.506959f,0.860716f,-0.0464834f, +0.440087f,0.895465f,-0.0668225f, +0.226441f,0.974021f,0.00265329f, +-0.0272959f,0.999596f,0.00787303f, +0.0903893f,0.995643f,0.0228958f, +0.359925f,0.931179f,0.0579615f, +0.431266f,0.899788f,-0.0662666f, +0.53735f,0.839722f,-0.0782406f, +0.525898f,0.846474f,-0.0831443f, +0.503404f,0.859213f,-0.0913118f, +0.450901f,0.892319f,-0.0213084f, +0.278054f,0.959353f,0.048252f, +0.254295f,0.953824f,0.159853f, +0.246692f,0.953779f,0.171608f, +0.237766f,0.960301f,0.145908f, +0.249319f,0.965473f,0.0755121f, +0.140552f,0.989905f,0.0182753f, +-0.0589195f,0.996842f,0.0532477f, +-0.101426f,0.988847f,0.109061f, +-0.043669f,0.99706f,0.0629708f, +0.0474685f,0.998853f,-0.0063145f, +-0.0867729f,0.996136f,-0.0135299f, +-0.196161f,0.972844f,0.12286f, +-0.192413f,0.974994f,0.111196f, +-0.123107f,0.990318f,0.0641543f, +-0.164426f,0.985628f,0.0387435f, +-0.213922f,0.974633f,0.0657922f, +-0.241049f,0.968373f,0.0644173f, +-0.307154f,0.951627f,-0.00792363f, +0.280771f,0.958227f,-0.0544817f, +0.299035f,0.949091f,0.0990176f, +0.225174f,0.937279f,0.266091f, +0.201765f,0.945847f,0.254291f, +0.341377f,0.920786f,0.18872f, +0.3743f,0.913661f,0.158502f, +0.359138f,0.923211f,0.136755f, +0.36518f,0.919296f,0.146759f, +0.0046348f,0.996002f,0.0892048f, +-0.241229f,0.954179f,0.177061f, +-0.158349f,0.951157f,0.265002f, +-0.207545f,0.971279f,0.116375f, +-0.289845f,0.957072f,0.00156201f, +-0.257416f,0.96626f,0.00885102f, +-0.326801f,0.944936f,0.0172234f, +-0.439204f,0.898379f,-0.00377194f, +-0.336537f,0.936282f,0.100589f, +-0.407285f,0.907139f,0.105914f, +-0.44858f,0.865076f,0.224543f, +-0.454994f,0.838311f,0.300358f, +-0.578424f,0.785375f,0.220483f, +-0.613986f,0.761879f,0.206302f, +-0.509143f,0.819763f,0.262226f, +-0.364105f,0.879908f,0.30527f, +-0.344494f,0.905138f,0.249097f, +-0.369295f,0.913195f,0.172323f, +-0.574832f,0.817482f,0.0359178f, +-0.689125f,0.724332f,-0.0212343f, +-0.619919f,0.781232f,-0.0733212f, +-0.441345f,0.892835f,-0.0897783f, +-0.0649595f,0.996915f,0.0440505f, +0.146397f,0.977716f,0.150467f, +-0.0177868f,0.998167f,0.0578468f, +-0.37006f,0.91802f,-0.14246f, +-0.30849f,0.937533f,-0.160828f, +0.107382f,0.980696f,-0.163415f, +0.392635f,0.914926f,-0.093533f, +0.501877f,0.862749f,-0.0615151f, +0.381618f,0.912204f,-0.14917f, +0.160415f,0.986769f,-0.0235493f, +0.0253729f,0.99703f,0.0727145f, +0.144484f,0.989507f,0.000443305f, +0.379228f,0.922372f,-0.073601f, +0.493599f,0.867009f,-0.0682314f, +0.529895f,0.842151f,-0.099967f, +0.549367f,0.821638f,-0.152008f, +0.439412f,0.876451f,-0.196851f, +0.349224f,0.935858f,0.0470259f, +0.182079f,0.971589f,0.151205f, +0.194383f,0.962201f,0.190749f, +0.266182f,0.94835f,0.172569f, +0.284034f,0.949535f,0.133071f, +0.347472f,0.93345f,0.089069f, +0.226103f,0.974059f,0.00925465f, +-0.0773561f,0.993257f,-0.0863519f, +-0.200366f,0.974099f,-0.104811f, +-0.00292133f,0.99995f,-0.00953497f, +0.144264f,0.988303f,-0.0494442f, +-0.155865f,0.979469f,-0.127857f, +-0.286146f,0.957784f,-0.0277406f, +-0.165259f,0.985103f,-0.0475661f, +-0.069504f,0.996782f,-0.0399387f, +-0.139315f,0.988254f,-0.0628056f, +-0.230813f,0.967463f,-0.103639f, +-0.24543f,0.966984f,-0.0686046f, +-0.189537f,0.981091f,0.0391957f, +0.151487f,0.988375f,0.0128779f, +0.16936f,0.984329f,0.0491336f, +0.218781f,0.968894f,0.115672f, +0.279098f,0.952669f,0.120523f, +0.344688f,0.931221f,0.118397f, +0.359727f,0.914297f,0.186165f, +0.326371f,0.918389f,0.223703f, +0.361839f,0.886899f,0.287197f, +-0.000924981f,0.965442f,0.260617f, +-0.321168f,0.914653f,0.24548f, +-0.23578f,0.933549f,0.269988f, +-0.0519805f,0.910912f,0.409313f, +-0.120702f,0.947306f,0.296721f, +-0.257649f,0.956241f,0.138637f, +-0.340179f,0.924947f,0.169564f, +-0.415425f,0.90289f,0.110507f, +-0.41038f,0.91038f,0.0528755f, +-0.447459f,0.881081f,0.153222f, +-0.521314f,0.820871f,0.233245f, +-0.470597f,0.83806f,0.27603f, +-0.530303f,0.820989f,0.211554f, +-0.59428f,0.795918f,0.11552f, +-0.564828f,0.823165f,0.0580397f, +-0.435129f,0.882511f,0.17843f, +-0.320859f,0.891866f,0.318787f, +-0.272192f,0.902535f,0.33368f, +-0.476067f,0.856837f,0.197967f, +-0.671403f,0.739101f,0.0543033f, +-0.548598f,0.834125f,0.0572312f, +-0.459373f,0.883769f,-0.0890421f, +-0.194341f,0.977153f,-0.0860449f, +0.0638196f,0.997784f,0.0188364f, +0.119241f,0.989813f,0.0777976f, +-0.189205f,0.978439f,-0.0828203f, +-0.328042f,0.913868f,-0.239234f, +0.0439005f,0.976566f,-0.210694f, +0.345392f,0.929362f,-0.130351f, +0.531991f,0.841029f,-0.0982628f, +0.385958f,0.912021f,-0.13876f, +0.00996624f,0.998173f,-0.059598f, +-0.0397997f,0.999182f,0.00710574f, +0.22423f,0.974041f,-0.0310806f, +0.399529f,0.909843f,-0.112084f, +0.472825f,0.876316f,-0.0922302f, +0.567959f,0.818431f,-0.0871407f, +0.591097f,0.802347f,-0.0827227f, +0.294969f,0.954774f,-0.0374031f, +0.136562f,0.986139f,0.0942395f, +0.140836f,0.978895f,0.148089f, +0.208743f,0.962024f,0.175889f, +0.331657f,0.931412f,0.149918f, +0.32318f,0.945148f,0.0474422f, +0.378499f,0.925602f,0.000447487f, +0.240237f,0.969087f,-0.0561752f, +0.0676245f,0.996927f,-0.0395359f, +-0.154966f,0.962822f,-0.221268f, +-0.087338f,0.971663f,-0.219642f, +0.144581f,0.983839f,-0.105631f, +-0.0884322f,0.993076f,-0.0773351f, +-0.293638f,0.94457f,-0.146848f, +-0.135408f,0.983934f,-0.116358f, +-0.103543f,0.987494f,-0.11889f, +-0.104597f,0.98248f,-0.15425f, +-0.176622f,0.962045f,-0.208023f, +-0.325467f,0.923065f,-0.204992f, +-0.403927f,0.903415f,-0.143824f, +0.344389f,0.929213f,0.134014f, +0.233815f,0.972165f,0.0150206f, +0.162621f,0.985815f,-0.0415186f, +0.195602f,0.980526f,0.0175561f, +0.28987f,0.950331f,0.113346f, +0.255987f,0.942074f,0.216718f, +0.263495f,0.890351f,0.371275f, +0.315069f,0.864416f,0.391812f, +0.0646003f,0.916859f,0.39395f, +-0.213657f,0.9234f,0.318877f, +-0.307635f,0.926495f,0.216719f, +-0.201977f,0.923807f,0.325246f, +-0.0210673f,0.916391f,0.399731f, +-0.17042f,0.919713f,0.353674f, +-0.316748f,0.899919f,0.299695f, +-0.294061f,0.92391f,0.244781f, +-0.396636f,0.905857f,0.14867f, +-0.523471f,0.83043f,0.190696f, +-0.568887f,0.791598f,0.223024f, +-0.446362f,0.844948f,0.294659f, +-0.453253f,0.853996f,0.255447f, +-0.541011f,0.824142f,0.167623f, +-0.550736f,0.81694f,0.171169f, +-0.53915f,0.819657f,0.193597f, +-0.444412f,0.862352f,0.242584f, +-0.285315f,0.907749f,0.30755f, +-0.329395f,0.886574f,0.324786f, +-0.610599f,0.78547f,0.101022f, +-0.543486f,0.838015f,0.0485148f, +-0.319704f,0.945394f,0.0634074f, +-0.262212f,0.963421f,-0.055354f, +0.000253525f,0.995852f,0.0909893f, +0.105619f,0.991464f,0.0764441f, +0.0245363f,0.999682f,-0.00586488f, +-0.22917f,0.926966f,-0.29701f, +-0.0159754f,0.943632f,-0.33061f, +0.309925f,0.920539f,-0.237812f, +0.48714f,0.850311f,-0.199165f, +0.288684f,0.955866f,-0.0546085f, +-0.0787222f,0.994967f,0.0619939f, +0.0273777f,0.99772f,0.0616831f, +0.291481f,0.955243f,-0.0505022f, +0.438727f,0.89664f,-0.0596253f, +0.485213f,0.871546f,-0.0705428f, +0.5406f,0.839608f,-0.0530067f, +0.49511f,0.866937f,0.0573254f, +0.280189f,0.947413f,0.154605f, +0.158816f,0.979113f,0.126949f, +0.168625f,0.983554f,0.0647105f, +0.187616f,0.98216f,0.0127302f, +0.334023f,0.942557f,0.00379923f, +0.401318f,0.914355f,0.0538517f, +0.424638f,0.905172f,0.0185914f, +0.289448f,0.956081f,-0.0461475f, +0.0899479f,0.980871f,-0.172633f, +-0.00560791f,0.970967f,-0.23915f, +-0.153691f,0.938842f,-0.308149f, +-0.0450622f,0.984719f,-0.168219f, +-0.0818032f,0.994271f,0.0687937f, +-0.254478f,0.967062f,-0.0056871f, +-0.190127f,0.974114f,-0.122284f, +-0.0615121f,0.986397f,-0.152435f, +-0.0478084f,0.984317f,-0.169808f, +-0.157882f,0.979732f,-0.123284f, +-0.307356f,0.93941f,-0.151791f, +-0.432596f,0.869844f,-0.237133f, +0.35469f,0.923204f,0.147951f, +0.317903f,0.938384f,0.135547f, +0.209784f,0.976723f,0.0447562f, +0.188401f,0.980806f,-0.0502544f, +0.153267f,0.987748f,-0.0293859f, +0.102074f,0.966336f,0.236167f, +0.128463f,0.933972f,0.333456f, +0.308207f,0.882627f,0.354934f, +0.141883f,0.91146f,0.386148f, +-0.174863f,0.945456f,0.274837f, +-0.248524f,0.937312f,0.244299f, +-0.268339f,0.945888f,0.182456f, +-0.0843285f,0.960488f,0.265238f, +-0.151825f,0.934815f,0.321045f, +-0.286064f,0.900967f,0.326231f, +-0.240679f,0.904695f,0.351568f, +-0.362345f,0.88785f,0.2836f, +-0.538142f,0.813225f,0.221511f, +-0.57294f,0.797677f,0.188284f, +-0.51091f,0.838129f,0.191079f, +-0.412611f,0.865658f,0.283528f, +-0.528395f,0.821979f,0.212483f, +-0.579097f,0.792111f,0.192891f, +-0.502268f,0.843036f,0.192398f, +-0.402738f,0.896524f,0.184518f, +-0.323371f,0.930281f,0.173231f, +-0.341027f,0.92193f,0.183699f, +-0.49586f,0.861123f,0.112209f, +-0.562176f,0.82675f,-0.0210484f, +-0.29935f,0.952705f,0.0523715f, +-0.273263f,0.96182f,0.0151701f, +-0.127856f,0.984802f,0.117552f, +0.16681f,0.967622f,0.189425f, +0.219885f,0.966852f,0.1298f, +0.0444925f,0.994595f,-0.093817f, +-0.0559771f,0.948894f,-0.31059f, +0.229668f,0.93439f,-0.272337f, +0.391338f,0.907289f,-0.153889f, +0.215699f,0.975228f,0.0490428f, +-0.1202f,0.992098f,0.0359644f, +0.0568932f,0.997098f,0.0505773f, +0.369571f,0.928802f,0.0272646f, +0.435039f,0.898005f,-0.0657877f, +0.45866f,0.886154f,-0.0660444f, +0.484136f,0.874975f,0.00559808f, +0.464546f,0.884206f,0.0487577f, +0.311084f,0.947795f,0.0700806f, +0.215922f,0.975139f,0.0498078f, +0.229266f,0.973122f,-0.0216826f, +0.269391f,0.956816f,-0.109228f, +0.297276f,0.941247f,-0.160256f, +0.352506f,0.931874f,-0.0857318f, +0.363875f,0.92958f,-0.0589632f, +0.421372f,0.901903f,0.094954f, +0.220959f,0.972251f,-0.0768509f, +0.0552433f,0.994093f,-0.0934223f, +-0.134577f,0.980922f,-0.140288f, +-0.247593f,0.953903f,-0.169607f, +-0.238891f,0.96987f,-0.0477791f, +-0.130123f,0.990325f,-0.0482061f, +0.00814361f,0.986901f,-0.161119f, +-0.0740374f,0.970051f,-0.231345f, +-0.135238f,0.990526f,-0.0238593f, +-0.204897f,0.978574f,0.0202582f, +-0.205889f,0.977122f,-0.0533174f, +-0.236999f,0.963982f,-0.120711f, +0.399314f,0.905653f,0.142621f, +0.334882f,0.936094f,0.107618f, +0.310789f,0.943606f,0.114093f, +0.298988f,0.952609f,0.0560503f, +0.00373107f,0.999894f,-0.0140921f, +-0.127729f,0.983543f,0.12778f, +0.134365f,0.969696f,0.204046f, +0.250753f,0.938877f,0.235867f, +0.172971f,0.901933f,0.395725f, +-0.0661635f,0.938085f,0.340027f, +-0.190026f,0.944561f,0.267758f, +-0.246469f,0.952194f,0.180498f, +-0.199636f,0.962622f,0.183041f, +-0.204824f,0.924659f,0.321019f, +-0.345906f,0.869848f,0.351729f, +-0.272906f,0.86539f,0.420265f, +-0.23738f,0.86577f,0.44056f, +-0.476597f,0.838274f,0.264863f, +-0.549692f,0.815624f,0.180542f, +-0.521659f,0.837826f,0.160993f, +-0.461012f,0.874551f,0.150426f, +-0.498406f,0.858536f,0.120447f, +-0.538861f,0.837113f,0.0941878f, +-0.51696f,0.855065f,0.0401927f, +-0.464195f,0.882878f,0.0710582f, +-0.339798f,0.923706f,0.176929f, +-0.307071f,0.929998f,0.202016f, +-0.435636f,0.887155f,0.152245f, +-0.50925f,0.856289f,0.0862179f, +-0.352613f,0.935762f,-0.00363908f, +-0.24432f,0.969666f,0.0074465f, +-0.223693f,0.974193f,-0.0301471f, +0.0924619f,0.993171f,0.071143f, +0.248444f,0.955155f,0.161104f, +0.25541f,0.957577f,0.133462f, +0.152224f,0.983188f,-0.100846f, +0.175485f,0.954332f,-0.241774f, +0.229817f,0.96697f,-0.110245f, +0.104087f,0.990176f,0.0933667f, +-0.0251916f,0.99085f,0.132593f, +0.0299952f,0.999356f,-0.0197015f, +0.374506f,0.927216f,-0.00387803f, +0.523769f,0.851516f,-0.0242066f, +0.412003f,0.903869f,-0.115217f, +0.44751f,0.89427f,-0.00401492f, +0.502351f,0.864643f,-0.0060566f, +0.261187f,0.953407f,-0.150988f, +0.201827f,0.974066f,-0.102283f, +0.328474f,0.941424f,-0.0763319f, +0.327281f,0.932573f,-0.152297f, +0.312159f,0.927432f,-0.205977f, +0.304739f,0.922289f,-0.237734f, +0.291399f,0.941708f,-0.168142f, +0.325323f,0.94222f,-0.0799213f, +0.270502f,0.962573f,-0.0167793f, +-0.00135827f,0.998382f,0.0568385f, +-0.0464612f,0.993882f,0.100202f, +-0.163616f,0.983349f,-0.0790802f, +-0.219372f,0.956704f,-0.191292f, +-0.0798083f,0.976764f,-0.198904f, +-0.0362508f,0.993161f,-0.11098f, +-0.194493f,0.976824f,0.0893684f, +-0.303508f,0.929002f,0.211751f, +-0.120982f,0.967912f,0.220249f, +-0.126864f,0.979558f,0.156117f, +-0.190168f,0.969475f,0.154773f, +0.442277f,0.894635f,0.0633978f, +0.351901f,0.932017f,0.0866602f, +0.271089f,0.951246f,0.147111f, +0.263373f,0.940704f,0.2138f, +0.0780789f,0.961317f,0.264145f, +-0.165165f,0.972713f,0.162944f, +0.054241f,0.96435f,0.259011f, +0.119009f,0.928226f,0.352467f, +0.062551f,0.905107f,0.420558f, +-0.0376962f,0.903166f,0.427633f, +-0.119235f,0.864868f,0.487634f, +-0.107099f,0.89512f,0.43277f, +-0.228241f,0.933808f,0.275515f, +-0.34367f,0.891778f,0.294319f, +-0.360994f,0.863066f,0.353271f, +-0.329935f,0.870805f,0.364474f, +-0.225803f,0.873787f,0.430708f, +-0.324138f,0.85889f,0.396537f, +-0.511071f,0.812187f,0.281352f, +-0.475013f,0.824987f,0.306202f, +-0.392033f,0.887928f,0.240612f, +-0.45534f,0.876633f,0.155499f, +-0.547025f,0.829694f,0.111226f, +-0.496064f,0.862275f,0.101992f, +-0.479515f,0.87606f,0.0508306f, +-0.424535f,0.90465f,0.0371277f, +-0.362147f,0.919497f,0.152886f, +-0.412742f,0.878092f,0.24207f, +-0.402299f,0.893898f,0.197745f, +-0.26297f,0.963672f,0.0467231f, +-0.219075f,0.975598f,-0.0146319f, +-0.186267f,0.980099f,-0.0686323f, +-0.0357984f,0.992879f,-0.113625f, +0.180598f,0.983509f,0.00973344f, +0.28459f,0.957748f,0.0415635f, +0.350884f,0.934731f,0.0561944f, +0.201029f,0.975728f,-0.0868401f, +0.10163f,0.994331f,-0.0312587f, +-0.0498772f,0.998294f,0.0303674f, +0.0144565f,0.996475f,0.082632f, +0.17671f,0.984206f,0.0105968f, +0.384098f,0.921983f,-0.049144f, +0.526508f,0.848767f,-0.048829f, +0.451141f,0.890087f,-0.0649363f, +0.349978f,0.927792f,-0.129298f, +0.525028f,0.849511f,-0.051734f, +0.403316f,0.902994f,-0.148114f, +0.146493f,0.950082f,-0.275472f, +0.257494f,0.953663f,-0.155639f, +0.363336f,0.930153f,-0.0529431f, +0.407301f,0.911128f,-0.0628641f, +0.309341f,0.935596f,-0.170201f, +0.234661f,0.952473f,-0.194238f, +0.248922f,0.950735f,-0.18477f, +0.176271f,0.982701f,-0.0568089f, +-0.0817466f,0.996475f,0.0188703f, +-0.0390696f,0.99855f,0.0370285f, +0.0392849f,0.997614f,0.0567754f, +-0.165147f,0.985538f,-0.0379532f, +-0.216905f,0.97598f,0.020392f, +-0.25871f,0.942954f,0.209538f, +-0.318314f,0.87576f,0.362933f, +-0.238112f,0.92993f,0.280235f, +-0.11178f,0.963059f,0.244995f, +-0.156033f,0.939968f,0.303502f, +-0.219558f,0.904757f,0.364977f, +0.29059f,0.953077f,-0.0848643f, +0.282679f,0.959209f,-0.00326087f, +0.165956f,0.986031f,0.0141778f, +0.145774f,0.971701f,0.185869f, +0.0971539f,0.92606f,0.364656f, +-0.126893f,0.938591f,0.320851f, +-0.158756f,0.918948f,0.361014f, +0.0576791f,0.877286f,0.47649f, +0.151465f,0.884095f,0.442079f, +-0.0842052f,0.912347f,0.400665f, +-0.236928f,0.870703f,0.430978f, +-0.0173538f,0.858153f,0.513101f, +-0.0453547f,0.868839f,0.493013f, +-0.308698f,0.88215f,0.355692f, +-0.391959f,0.868398f,0.303732f, +-0.360504f,0.877037f,0.317558f, +-0.289644f,0.88703f,0.359561f, +-0.323579f,0.85156f,0.412484f, +-0.483914f,0.781191f,0.39442f, +-0.428744f,0.813324f,0.393297f, +-0.337017f,0.871068f,0.357294f, +-0.382215f,0.837599f,0.390306f, +-0.472752f,0.816976f,0.330237f, +-0.454132f,0.848356f,0.272131f, +-0.386129f,0.879637f,0.277745f, +-0.408175f,0.895196f,0.178931f, +-0.461039f,0.873474f,0.15648f, +-0.444429f,0.876284f,0.186035f, +-0.324725f,0.941951f,0.085336f, +-0.200261f,0.979518f,0.0209972f, +-0.146655f,0.98862f,0.0335086f, +-0.105669f,0.986512f,-0.125016f, +-0.0113758f,0.977088f,-0.21253f, +0.125756f,0.969156f,-0.211948f, +0.231535f,0.947003f,-0.222657f, +0.267937f,0.954488f,-0.131005f, +0.231299f,0.971277f,0.055871f, +0.0809071f,0.991774f,0.0991925f, +0.000207679f,0.999953f,0.00973996f, +0.0247831f,0.993578f,-0.110402f, +0.181304f,0.979201f,-0.0910725f, +0.390907f,0.919373f,-0.0441033f, +0.523664f,0.849877f,-0.0590321f, +0.487061f,0.873094f,-0.0218679f, +0.442794f,0.892691f,-0.0838822f, +0.486459f,0.850567f,-0.199735f, +0.449595f,0.886474f,-0.10967f, +0.172841f,0.979158f,-0.106661f, +0.134151f,0.987388f,-0.084069f, +0.292984f,0.955775f,-0.0255695f, +0.391346f,0.920229f,-0.00512785f, +0.418943f,0.907957f,0.00999318f, +0.324262f,0.936698f,-0.1321f, +0.190686f,0.957473f,-0.216527f, +0.0619887f,0.993289f,-0.097645f, +-0.0829846f,0.99633f,-0.0209901f, +-0.0646754f,0.997763f,-0.0169202f, +-0.0614217f,0.996217f,0.0614677f, +-0.189778f,0.963623f,0.188191f, +-0.363861f,0.896503f,0.25276f, +-0.348308f,0.859996f,0.372945f, +-0.264506f,0.906439f,0.329249f, +-0.140762f,0.939057f,0.31362f, +-0.154941f,0.944783f,0.288752f, +-0.237481f,0.904164f,0.355093f, +-0.314839f,0.867723f,0.38462f, +0.199283f,0.97456f,-0.102566f, +0.290362f,0.956152f,-0.0382605f, +0.163603f,0.98144f,-0.10005f, +-0.0845537f,0.992536f,-0.0878854f, +-0.0995819f,0.988025f,0.117859f, +-0.128698f,0.94862f,0.289062f, +-0.181988f,0.934999f,0.304396f, +0.0121717f,0.953274f,0.301863f, +0.15771f,0.909532f,0.384551f, +-0.030083f,0.904525f,0.425359f, +-0.262213f,0.918561f,0.295788f, +-0.150427f,0.932893f,0.327234f, +-0.0433771f,0.888915f,0.456013f, +-0.194904f,0.882492f,0.428042f, +-0.359771f,0.865678f,0.348089f, +-0.358104f,0.856009f,0.37284f, +-0.334766f,0.853069f,0.400257f, +-0.382047f,0.809514f,0.445788f, +-0.440041f,0.772384f,0.458024f, +-0.392897f,0.847233f,0.357532f, +-0.352962f,0.862399f,0.362885f, +-0.432462f,0.797784f,0.42014f, +-0.40741f,0.807767f,0.426063f, +-0.417686f,0.831448f,0.366378f, +-0.406533f,0.835025f,0.370761f, +-0.302917f,0.831265f,0.466089f, +-0.354465f,0.85583f,0.376708f, +-0.320875f,0.930472f,0.17681f, +-0.210666f,0.977556f,0.00208309f, +-0.202152f,0.976764f,-0.0711849f, +-0.0734606f,0.993473f,-0.0872598f, +0.0104554f,0.979699f,-0.2002f, +0.0812548f,0.981491f,-0.173417f, +0.133484f,0.953074f,-0.271721f, +0.239226f,0.941558f,-0.23715f, +0.0986638f,0.979162f,-0.177504f, +0.0167662f,0.999807f,0.0102821f, +0.0608252f,0.989728f,0.129377f, +0.193478f,0.976369f,0.0962839f, +0.105893f,0.986391f,-0.125774f, +0.159018f,0.972139f,-0.17222f, +0.348199f,0.916375f,-0.197521f, +0.506641f,0.853561f,-0.121441f, +0.438954f,0.895697f,-0.0710352f, +0.508211f,0.861156f,-0.0114456f, +0.538629f,0.837641f,-0.0907543f, +0.350973f,0.934296f,-0.0625226f, +0.130826f,0.991364f,0.00901604f, +0.142249f,0.989581f,0.0222434f, +0.314713f,0.948656f,-0.0317428f, +0.413134f,0.902882f,-0.118849f, +0.421178f,0.889709f,-0.176143f, +0.40304f,0.897538f,-0.178843f, +0.190553f,0.961133f,-0.199782f, +-0.0704956f,0.989551f,-0.125772f, +-0.145721f,0.988685f,0.035603f, +-0.158165f,0.979549f,0.124366f, +-0.141884f,0.945197f,0.294061f, +-0.282634f,0.89813f,0.336869f, +-0.398539f,0.847577f,0.350398f, +-0.326007f,0.891199f,0.31541f, +-0.257935f,0.930645f,0.259558f, +-0.189362f,0.933131f,0.305628f, +-0.181998f,0.908713f,0.375656f, +-0.284451f,0.857477f,0.428743f, +-0.324962f,0.834267f,0.445419f, +0.162722f,0.967013f,-0.19598f, +0.196801f,0.96943f,-0.146541f, +0.171798f,0.98444f,0.0369126f, +-0.0614366f,0.993745f,0.0932502f, +-0.263807f,0.962515f,0.063023f, +-0.262644f,0.943232f,0.203304f, +-0.183229f,0.945939f,0.267632f, +-0.0512022f,0.955564f,0.290302f, +0.0500709f,0.932925f,0.356571f, +-0.017607f,0.930336f,0.366286f, +-0.141345f,0.917863f,0.370876f, +-0.196664f,0.921785f,0.334121f, +-0.123639f,0.931227f,0.342826f, +-0.166673f,0.929929f,0.327799f, +-0.365314f,0.882118f,0.297345f, +-0.422119f,0.842584f,0.334465f, +-0.378137f,0.838603f,0.392119f, +-0.433991f,0.800503f,0.413336f, +-0.373446f,0.819157f,0.435339f, +-0.321191f,0.877582f,0.35593f, +-0.410179f,0.839146f,0.357194f, +-0.450466f,0.792998f,0.410164f, +-0.383405f,0.853385f,0.353178f, +-0.361072f,0.88078f,0.306355f, +-0.471517f,0.844691f,0.253315f, +-0.399349f,0.852332f,0.337713f, +-0.193735f,0.889811f,0.413163f, +-0.0964184f,0.953204f,0.28654f, +-0.0731968f,0.993583f,0.0862245f, +-0.107213f,0.990087f,-0.0907379f, +-0.0139207f,0.976637f,-0.214443f, +-0.00517032f,0.976967f,-0.213328f, +0.032564f,0.990278f,-0.135238f, +0.193406f,0.974103f,-0.117123f, +0.137302f,0.989014f,-0.0547632f, +0.0149454f,0.997504f,0.06901f, +-0.0673257f,0.995987f,0.0589639f, +0.00671915f,0.997834f,0.0654375f, +0.236496f,0.961793f,0.137925f, +0.296243f,0.953456f,0.0562338f, +0.227931f,0.966806f,-0.11547f, +0.392626f,0.909868f,-0.134105f, +0.455312f,0.880641f,-0.131003f, +0.402519f,0.906647f,-0.126375f, +0.459051f,0.879656f,-0.124406f, +0.531911f,0.846049f,-0.0356662f, +0.366681f,0.930218f,0.0155094f, +0.101768f,0.992829f,-0.0627213f, +0.169781f,0.984995f,-0.0309622f, +0.383193f,0.921183f,-0.0677109f, +0.483652f,0.86784f,-0.113728f, +0.481548f,0.864447f,-0.144373f, +0.322376f,0.925659f,-0.198063f, +0.121084f,0.992307f,-0.0257868f, +-0.189201f,0.97803f,0.0875253f, +-0.272481f,0.941614f,0.197779f, +-0.28107f,0.929157f,0.240138f, +-0.316277f,0.890261f,0.327726f, +-0.284096f,0.875896f,0.389994f, +-0.304764f,0.879665f,0.365114f, +-0.295018f,0.913863f,0.278959f, +-0.233864f,0.913909f,0.331779f, +-0.25276f,0.886942f,0.386584f, +-0.254968f,0.846261f,0.467797f, +-0.324913f,0.811645f,0.485452f, +-0.330966f,0.801562f,0.497956f, +0.166281f,0.984047f,-0.0632562f, +0.102172f,0.992786f,-0.0627485f, +-0.0446214f,0.999004f,-0.000325965f, +-0.137659f,0.980871f,0.13763f, +-0.270041f,0.94552f,0.18185f, +-0.300503f,0.932348f,0.201063f, +-0.224552f,0.960314f,0.165452f, +-0.109331f,0.978965f,0.17226f, +0.0684226f,0.972288f,0.223551f, +-0.0281009f,0.965962f,0.257154f, +-0.203983f,0.927334f,0.313757f, +-0.170837f,0.935943f,0.307937f, +-0.0844776f,0.951083f,0.29716f, +-0.140439f,0.935294f,0.32481f, +-0.360713f,0.879742f,0.309743f, +-0.466354f,0.845167f,0.261162f, +-0.425659f,0.859392f,0.283303f, +-0.470194f,0.836884f,0.280256f, +-0.410878f,0.856359f,0.312777f, +-0.293557f,0.864483f,0.408036f, +-0.429097f,0.81157f,0.396523f, +-0.438172f,0.837036f,0.327683f, +-0.303084f,0.911643f,0.277574f, +-0.346895f,0.902405f,0.255594f, +-0.444307f,0.857916f,0.258015f, +-0.440123f,0.885255f,0.150386f, +-0.246442f,0.965625f,0.0826743f, +-0.0242341f,0.995753f,0.0888192f, +0.128537f,0.987977f,0.085905f, +0.10291f,0.993755f,-0.0431449f, +0.0280177f,0.986869f,-0.159076f, +-0.0318503f,0.988236f,-0.149584f, +0.00777626f,0.97932f,-0.202168f, +0.111085f,0.970769f,-0.212762f, +-0.00220326f,0.997417f,-0.0718009f, +-0.0152092f,0.997571f,0.0679693f, +0.0100591f,0.998816f,0.0476033f, +-0.00783919f,0.999851f,-0.0153546f, +0.1632f,0.986482f,-0.0148045f, +0.356551f,0.93118f,0.0760001f, +0.33409f,0.940767f,0.0578066f, +0.378555f,0.924836f,-0.0370621f, +0.481573f,0.874509f,-0.0576253f, +0.443664f,0.890369f,-0.102011f, +0.449245f,0.88434f,-0.126968f, +0.449063f,0.892098f,-0.05003f, +0.400085f,0.916232f,0.0212355f, +0.189459f,0.975149f,-0.114846f, +0.154225f,0.96178f,-0.226258f, +0.36559f,0.902984f,-0.225751f, +0.443305f,0.891814f,-0.0902669f, +0.481296f,0.876165f,0.0262584f, +0.274557f,0.96003f,0.0544047f, +-0.0951468f,0.983236f,0.155547f, +-0.272231f,0.920302f,0.280953f, +-0.309095f,0.909629f,0.277553f, +-0.260629f,0.904898f,0.336501f, +-0.319906f,0.899874f,0.296456f, +-0.309019f,0.910231f,0.275658f, +-0.301457f,0.909911f,0.284931f, +-0.289244f,0.908198f,0.302514f, +-0.349317f,0.867088f,0.355157f, +-0.355035f,0.811266f,0.46454f, +-0.291879f,0.804435f,0.517388f, +-0.292737f,0.815956f,0.498519f, +-0.341117f,0.83204f,0.437434f, +0.012939f,0.999781f,0.0164623f, +0.101117f,0.986501f,0.12881f, +-0.0315137f,0.991787f,0.123953f, +-0.202813f,0.972667f,0.113078f, +-0.267039f,0.954882f,0.129964f, +-0.329248f,0.943109f,0.0462825f, +-0.158801f,0.981787f,0.104294f, +-0.0896983f,0.994441f,0.0551561f, +-0.03797f,0.996172f,0.0787436f, +-0.124773f,0.970658f,0.205561f, +-0.242396f,0.92942f,0.278248f, +-0.1236f,0.936757f,0.327428f, +-0.115597f,0.950099f,0.289742f, +-0.242269f,0.924532f,0.294187f, +-0.335063f,0.873272f,0.353736f, +-0.402827f,0.872268f,0.27727f, +-0.433494f,0.882428f,0.182769f, +-0.472347f,0.860126f,0.192541f, +-0.516304f,0.829671f,0.212311f, +-0.401557f,0.840095f,0.364681f, +-0.365647f,0.853697f,0.370816f, +-0.342203f,0.911984f,0.226234f, +-0.319568f,0.928553f,0.188855f, +-0.368607f,0.886665f,0.279203f, +-0.401013f,0.885839f,0.233406f, +-0.263462f,0.961384f,0.0795548f, +-0.119336f,0.983737f,-0.134243f, +-0.028348f,0.969034f,-0.245295f, +0.0404463f,0.983879f,-0.174201f, +0.11875f,0.992593f,0.0256534f, +0.0602272f,0.997166f,0.0450923f, +0.0340291f,0.999414f,-0.00366965f, +0.0708792f,0.992684f,-0.097743f, +0.0958935f,0.99395f,-0.0535485f, +-0.0943801f,0.993296f,-0.0667466f, +-0.119267f,0.988594f,-0.0919588f, +0.000759128f,0.999891f,-0.0147216f, +0.0724665f,0.997368f,-0.00256206f, +0.170906f,0.979948f,-0.10244f, +0.214916f,0.97339f,-0.079521f, +0.347938f,0.935698f,0.0583811f, +0.479062f,0.877734f,-0.00909944f, +0.517939f,0.850313f,-0.0933121f, +0.446396f,0.884197f,-0.137574f, +0.389313f,0.918353f,-0.0711587f, +0.410982f,0.908412f,0.0766878f, +0.41147f,0.910096f,0.0491837f, +0.356411f,0.933637f,-0.0359751f, +0.291892f,0.941315f,-0.169483f, +0.292525f,0.936947f,-0.191205f, +0.303478f,0.950202f,-0.0708325f, +0.350076f,0.936333f,0.0269695f, +0.186651f,0.94527f,0.26763f, +-0.145022f,0.9031f,0.404201f, +-0.257588f,0.88179f,0.395088f, +-0.316433f,0.892435f,0.321607f, +-0.301856f,0.895088f,0.328177f, +-0.311714f,0.888624f,0.336427f, +-0.275146f,0.879635f,0.387991f, +-0.320358f,0.874704f,0.363681f, +-0.312957f,0.856468f,0.410514f, +-0.417707f,0.826376f,0.377656f, +-0.402058f,0.821773f,0.403779f, +-0.299174f,0.86271f,0.407708f, +-0.252864f,0.886408f,0.387737f, +-0.266831f,0.899401f,0.346235f, +-0.121912f,0.980245f,-0.155747f, +-0.0467045f,0.996241f,-0.0729522f, +-0.0560423f,0.996609f,0.0602479f, +-0.253613f,0.959854f,0.119832f, +-0.17852f,0.958289f,0.223189f, +-0.25091f,0.965294f,0.0724672f, +-0.244405f,0.968888f,0.0390022f, +-0.111828f,0.978686f,0.172245f, +-0.104286f,0.963728f,0.245667f, +-0.172657f,0.941673f,0.288863f, +-0.302965f,0.917419f,0.257981f, +-0.21274f,0.929075f,0.302592f, +-0.0577232f,0.923128f,0.380136f, +-0.183983f,0.930078f,0.31797f, +-0.384056f,0.900387f,0.204463f, +-0.327378f,0.913703f,0.240771f, +-0.374063f,0.905896f,0.198566f, +-0.504219f,0.846296f,0.17189f, +-0.555467f,0.810974f,0.183786f, +-0.456478f,0.86757f,0.197356f, +-0.300554f,0.935674f,0.184881f, +-0.295051f,0.948068f,0.118792f, +-0.362387f,0.917821f,0.162113f, +-0.440667f,0.875232f,0.199453f, +-0.248631f,0.939944f,0.233854f, +-0.0966352f,0.995188f,0.0161918f, +0.0243217f,0.996259f,-0.0829196f, +0.0213875f,0.994057f,-0.106741f, +-0.13683f,0.98707f,-0.0834831f, +-0.0593385f,0.994125f,0.0905282f, +0.0836318f,0.990077f,0.112932f, +0.079675f,0.993049f,0.0866394f, +0.0726138f,0.990126f,0.119908f, +0.0468689f,0.990824f,0.126776f, +0.00048966f,0.99587f,0.0907856f, +-0.0299455f,0.998898f,-0.0361395f, +-0.0528047f,0.988171f,-0.143981f, +0.0771474f,0.992034f,-0.0995875f, +0.233f,0.968973f,-0.0824758f, +0.215078f,0.967265f,-0.134683f, +0.299646f,0.93128f,-0.207193f, +0.500666f,0.844143f,-0.191721f, +0.5316f,0.838001f,-0.123112f, +0.45137f,0.888237f,-0.0854371f, +0.26295f,0.958984f,-0.105862f, +0.297072f,0.954855f,-0.000735176f, +0.467586f,0.880091f,0.0824758f, +0.451683f,0.892137f,0.00862833f, +0.280097f,0.955995f,-0.0872873f, +0.27353f,0.961001f,0.0407195f, +0.263182f,0.963734f,0.044184f, +0.22357f,0.970136f,0.0940863f, +-0.055048f,0.955137f,0.291002f, +-0.267739f,0.863744f,0.426921f, +-0.199104f,0.857693f,0.474046f, +-0.21681f,0.879018f,0.424642f, +-0.270209f,0.885026f,0.379098f, +-0.341336f,0.865644f,0.366267f, +-0.32372f,0.861174f,0.391898f, +-0.34092f,0.838889f,0.42431f, +-0.295898f,0.818794f,0.491956f, +-0.331f,0.829823f,0.449258f, +-0.389842f,0.853312f,0.34624f, +-0.281201f,0.9123f,0.297716f, +-0.234572f,0.935622f,0.263795f, +-0.225355f,0.942001f,0.248696f, +-0.0486057f,0.996635f,-0.0660014f, +-0.101682f,0.988174f,-0.114771f, +-0.162649f,0.983215f,-0.0826606f, +-0.318288f,0.946728f,-0.048975f, +-0.258454f,0.965864f,-0.0175802f, +-0.136613f,0.987862f,0.0739351f, +-0.281595f,0.958211f,0.0503573f, +-0.28706f,0.943479f,0.165663f, +-0.148179f,0.930819f,0.334095f, +-0.182832f,0.931383f,0.314798f, +-0.242578f,0.923022f,0.298642f, +-0.204404f,0.955935f,0.21073f, +-0.142784f,0.976536f,0.161212f, +-0.136962f,0.950722f,0.278153f, +-0.274249f,0.920019f,0.279915f, +-0.389723f,0.904453f,0.173436f, +-0.370261f,0.901011f,0.226022f, +-0.50377f,0.847021f,0.169619f, +-0.52553f,0.835875f,0.158529f, +-0.435894f,0.894864f,0.0959897f, +-0.279872f,0.956869f,0.07793f, +-0.331658f,0.940229f,0.0772765f, +-0.372127f,0.91403f,0.161461f, +-0.456876f,0.888328f,0.0462339f, +-0.204408f,0.978272f,0.0346564f, +0.0554954f,0.998458f,-0.00157713f, +-0.0102256f,0.999947f,0.00149442f, +-0.0507499f,0.985345f,0.162848f, +-0.124313f,0.970082f,0.208536f, +-0.111836f,0.992788f,0.0431796f, +0.135986f,0.987999f,0.0732526f, +0.00980425f,0.997155f,0.0747439f, +0.00734776f,0.982792f,0.184568f, +0.0872171f,0.965097f,0.246944f, +0.0795152f,0.966423f,0.244345f, +0.106439f,0.984803f,0.137237f, +0.0584187f,0.998092f,-0.0199996f, +0.0370568f,0.991888f,-0.121591f, +0.199554f,0.972297f,-0.121727f, +0.308311f,0.945569f,-0.104131f, +0.399439f,0.904394f,-0.150064f, +0.468199f,0.870932f,-0.149223f, +0.412212f,0.907025f,-0.0859413f, +0.425915f,0.903304f,0.0513667f, +0.351639f,0.936099f,-0.00832492f, +0.20857f,0.966693f,-0.148333f, +0.395551f,0.918183f,0.0219088f, +0.538432f,0.838724f,0.0814483f, +0.24402f,0.966591f,-0.0784634f, +0.178953f,0.981938f,0.0614245f, +0.258979f,0.960241f,0.104243f, +0.0759782f,0.986383f,0.145865f, +-0.19655f,0.929601f,0.311786f, +-0.328358f,0.883678f,0.333607f, +-0.21216f,0.920721f,0.327507f, +-0.208125f,0.923292f,0.322823f, +-0.300181f,0.87973f,0.368737f, +-0.312111f,0.847974f,0.428401f, +-0.324858f,0.873038f,0.363693f, +-0.410275f,0.846963f,0.338124f, +-0.346514f,0.853308f,0.389607f, +-0.303825f,0.86928f,0.389926f, +-0.270707f,0.881074f,0.387848f, +-0.213937f,0.928705f,0.302885f, +-0.20202f,0.939889f,0.275312f, +-0.214102f,0.943299f,0.253667f, +-0.0402111f,0.999126f,0.011392f, +-0.0458289f,0.99894f,0.00442323f, +-0.170695f,0.984267f,-0.0456311f, +-0.29333f,0.955986f,-0.00691228f, +-0.274679f,0.961535f,-0.00118788f, +-0.240876f,0.970372f,-0.0188751f, +-0.335158f,0.942005f,0.0172014f, +-0.387782f,0.921031f,0.0364391f, +-0.254694f,0.964339f,0.0719752f, +-0.156383f,0.970864f,0.181569f, +-0.223749f,0.957301f,0.183063f, +-0.122594f,0.972034f,0.200303f, +-0.0910709f,0.976799f,0.193828f, +-0.28429f,0.950625f,0.124466f, +-0.315477f,0.924742f,0.212902f, +-0.305454f,0.925312f,0.224713f, +-0.365063f,0.920836f,0.137077f, +-0.474911f,0.873286f,0.108772f, +-0.523018f,0.843362f,0.123259f, +-0.405348f,0.903149f,0.141474f, +-0.272593f,0.953587f,0.127925f, +-0.342778f,0.935924f,0.0809316f, +-0.402631f,0.912044f,0.0778773f, +-0.324862f,0.935409f,0.139553f, +-0.213356f,0.97623f,0.0381383f, +0.0301299f,0.998064f,0.0544045f, +-0.104927f,0.992798f,0.0578138f, +-0.261101f,0.959724f,0.103713f, +-0.0217785f,0.964552f,0.262994f, +0.0803134f,0.988499f,0.128142f, +0.028164f,0.998669f,0.043203f, +-0.0183001f,0.984341f,0.175323f, +-0.0612635f,0.982917f,0.173556f, +-0.0331225f,0.977326f,0.209135f, +0.0728156f,0.957515f,0.279039f, +0.245559f,0.942697f,0.225881f, +0.183786f,0.974714f,0.127102f, +0.141547f,0.988409f,0.0548866f, +0.245636f,0.968932f,-0.0288843f, +0.304552f,0.94926f,-0.0784495f, +0.340339f,0.936344f,-0.0861948f, +0.460805f,0.886321f,0.0457651f, +0.380493f,0.924294f,0.030084f, +0.352595f,0.93478f,0.0431689f, +0.472573f,0.87479f,0.106851f, +0.264087f,0.962772f,-0.057695f, +0.234368f,0.968348f,-0.0858683f, +0.503248f,0.863251f,0.0392276f, +0.302957f,0.950423f,0.0700943f, +0.0199528f,0.999731f,0.0118377f, +0.239816f,0.960125f,0.143695f, +-0.0259597f,0.9852f,0.16943f, +-0.288371f,0.907451f,0.305574f, +-0.301113f,0.913287f,0.274296f, +-0.184882f,0.952263f,0.242927f, +-0.251998f,0.931999f,0.260528f, +-0.398011f,0.856633f,0.32828f, +-0.335641f,0.851294f,0.403292f, +-0.239383f,0.893387f,0.380205f, +-0.388171f,0.875539f,0.287671f, +-0.364652f,0.897686f,0.247364f, +-0.31107f,0.908317f,0.279636f, +-0.277708f,0.915298f,0.291733f, +-0.164862f,0.947448f,0.274159f, +-0.18884f,0.953184f,0.236178f, +-0.183001f,0.960107f,0.211435f, +-0.0382166f,0.998778f,0.0313295f, +-0.025601f,0.999566f,0.0145695f, +-0.151993f,0.98817f,-0.0204673f, +-0.361566f,0.932093f,-0.021731f, +-0.304279f,0.951825f,0.0379804f, +-0.164708f,0.984119f,0.0661845f, +-0.289794f,0.954555f,-0.0695987f, +-0.339732f,0.933497f,-0.114741f, +-0.304944f,0.945342f,-0.115492f, +-0.266385f,0.963249f,-0.0345067f, +-0.261205f,0.96511f,0.0183122f, +-0.220073f,0.973176f,0.06706f, +-0.108437f,0.981443f,0.158152f, +-0.188668f,0.971426f,0.143996f, +-0.373149f,0.923277f,0.0912126f, +-0.308957f,0.927563f,0.210174f, +-0.302984f,0.922237f,0.240167f, +-0.457665f,0.867903f,0.193102f, +-0.548023f,0.825328f,0.136032f, +-0.407198f,0.903776f,0.131829f, +-0.253292f,0.959077f,0.126545f, +-0.271541f,0.948088f,0.165511f, +-0.43428f,0.889355f,0.142997f, +-0.382973f,0.89965f,0.20967f, +-0.169509f,0.965022f,0.199998f, +0.00160887f,0.982078f,0.188467f, +-0.0137168f,0.977172f,0.212005f, +-0.230009f,0.971053f,0.0644371f, +-0.165502f,0.985539f,0.036359f, +0.129892f,0.967237f,0.218131f, +0.0422409f,0.973374f,0.225299f, +-0.105762f,0.968925f,0.223604f, +-0.0226547f,0.965849f,0.258115f, +0.0138374f,0.990856f,0.134211f, +0.0309349f,0.998739f,0.0395399f, +0.294589f,0.940971f,0.166706f, +0.248856f,0.959421f,0.132596f, +0.181153f,0.982002f,0.053445f, +0.283788f,0.958737f,0.0169453f, +0.366617f,0.930251f,-0.0149969f, +0.332578f,0.93839f,-0.0938972f, +0.358957f,0.931691f,-0.0557027f, +0.429022f,0.901938f,0.0494683f, +0.332897f,0.942781f,-0.0185381f, +0.429131f,0.903242f,-0.000810457f, +0.405301f,0.91403f,-0.0167607f, +0.256936f,0.958211f,-0.12576f, +0.354456f,0.935063f,-0.00433271f, +0.385431f,0.888673f,0.248403f, +0.0742527f,0.992531f,0.0967874f, +0.121836f,0.985927f,0.11447f, +-0.100545f,0.965192f,0.241444f, +-0.337975f,0.881899f,0.328674f, +-0.242866f,0.922974f,0.298555f, +-0.185171f,0.940279f,0.285633f, +-0.313033f,0.906226f,0.28419f, +-0.448562f,0.843983f,0.294082f, +-0.356046f,0.888609f,0.289144f, +-0.196811f,0.931399f,0.306206f, +-0.298585f,0.916744f,0.265384f, +-0.410663f,0.894937f,0.17448f, +-0.325435f,0.90586f,0.271126f, +-0.301755f,0.928362f,0.216998f, +-0.109278f,0.952007f,0.285903f, +-0.14523f,0.965578f,0.215795f, +-0.139372f,0.971047f,0.194018f, +0.00163448f,0.997617f,0.0689798f, +0.026224f,0.998835f,0.04051f, +-0.128032f,0.991559f,-0.0204567f, +-0.309968f,0.948873f,-0.0596736f, +-0.340105f,0.924291f,-0.173245f, +-0.190965f,0.977348f,-0.0912302f, +-0.146645f,0.988782f,-0.028384f, +-0.31072f,0.935549f,-0.167929f, +-0.380234f,0.90209f,-0.204096f, +-0.300275f,0.945729f,-0.124224f, +-0.302914f,0.945705f,-0.117837f, +-0.237161f,0.970049f,-0.0525309f, +-0.165718f,0.984724f,-0.0534418f, +-0.190643f,0.98063f,0.0449474f, +-0.411915f,0.909141f,0.0615588f, +-0.453396f,0.88136f,0.1328f, +-0.362905f,0.886473f,0.287169f, +-0.380477f,0.872742f,0.305874f, +-0.476636f,0.866585f,0.147809f, +-0.366115f,0.923073f,0.117878f, +-0.278065f,0.952821f,0.121709f, +-0.370509f,0.910147f,0.18535f, +-0.442894f,0.857435f,0.26201f, +-0.347292f,0.915122f,0.204794f, +-0.111317f,0.983727f,0.141034f, +-0.00583658f,0.989977f,0.14111f, +0.00293304f,0.989031f,0.147679f, +-0.0932614f,0.992658f,0.0770272f, +-0.209442f,0.977765f,-0.0104574f, +-0.0521744f,0.996134f,0.0706788f, +0.0111918f,0.977173f,0.21215f, +-0.0985288f,0.958328f,0.268141f, +0.0097532f,0.972945f,0.23083f, +0.214151f,0.960047f,0.180136f, +0.0316331f,0.999392f,0.014672f, +0.114623f,0.990459f,0.0765015f, +0.302992f,0.926463f,0.223298f, +0.283203f,0.948444f,0.142303f, +0.315435f,0.948621f,0.0248881f, +0.37741f,0.92565f,0.0270755f, +0.401819f,0.915069f,0.0345122f, +0.321768f,0.943567f,-0.0784028f, +0.371664f,0.926589f,-0.0574381f, +0.394659f,0.917373f,-0.0516908f, +0.434962f,0.894125f,-0.106531f, +0.447382f,0.892016f,-0.0644733f, +0.241542f,0.966428f,-0.0876093f, +0.127706f,0.991493f,-0.0251536f, +0.250404f,0.953051f,0.170269f, +0.250954f,0.937023f,0.242919f, +-0.000559693f,0.986358f,0.164614f, +-0.211006f,0.922632f,0.32284f, +-0.34675f,0.881023f,0.321811f, +-0.216454f,0.925604f,0.310492f, +-0.177379f,0.942447f,0.283426f, +-0.307121f,0.917748f,0.251824f, +-0.427987f,0.86998f,0.244872f, +-0.348579f,0.908707f,0.229659f, +-0.214211f,0.945769f,0.244201f, +-0.272299f,0.924949f,0.265184f, +-0.413173f,0.878684f,0.239168f, +-0.359354f,0.883418f,0.300728f, +-0.292273f,0.892332f,0.343978f, +-0.146355f,0.897543f,0.415929f, +-0.0984727f,0.903088f,0.418013f, +-0.114958f,0.888054f,0.445134f, +0.0486539f,0.997583f,-0.0496084f, +0.0486095f,0.995772f,-0.0779487f, +-0.0727955f,0.994312f,-0.0777426f, +-0.222675f,0.967501f,-0.119823f, +-0.286744f,0.93984f,-0.185682f, +-0.296641f,0.937378f,-0.182555f, +-0.219022f,0.967026f,-0.12996f, +-0.147314f,0.984117f,-0.0990538f, +-0.3428f,0.902622f,-0.26031f, +-0.347893f,0.908635f,-0.230983f, +-0.327008f,0.925901f,-0.189136f, +-0.254527f,0.952486f,-0.167289f, +-0.228332f,0.958887f,-0.168522f, +-0.287734f,0.955666f,-0.0625468f, +-0.451431f,0.892304f,0.00185963f, +-0.510909f,0.851571f,0.11747f, +-0.434919f,0.884052f,0.171166f, +-0.355658f,0.920763f,0.16032f, +-0.392075f,0.91242f,0.117331f, +-0.40418f,0.912194f,0.0673793f, +-0.347001f,0.925636f,0.15096f, +-0.406528f,0.883834f,0.231457f, +-0.406378f,0.897555f,0.171031f, +-0.271349f,0.960134f,0.0671726f, +-0.0926357f,0.994526f,0.0483373f, +-0.0156467f,0.998994f,0.0420269f, +0.00801384f,0.999533f,0.0295044f, +-0.0412004f,0.995482f,0.0855485f, +-0.171347f,0.982792f,0.068987f, +-0.142796f,0.988044f,0.0581328f, +-0.101871f,0.981247f,0.163632f, +-0.103189f,0.979569f,0.172615f, +0.0761964f,0.994828f,0.0671726f, +0.210538f,0.977574f,0.00485915f, +0.123577f,0.988892f,0.0825912f, +0.0553491f,0.995759f,0.0734865f, +0.223203f,0.966768f,0.124662f, +0.344575f,0.927512f,0.144881f, +0.388873f,0.91351f,0.119485f, +0.324349f,0.942843f,0.0764535f, +0.411999f,0.8978f,0.155603f, +0.440079f,0.892774f,0.0963553f, +0.378616f,0.925121f,-0.0283174f, +0.428515f,0.90345f,-0.0123871f, +0.429626f,0.902172f,-0.0388249f, +0.396609f,0.917987f,-0.000717735f, +0.233551f,0.972137f,-0.020091f, +0.111169f,0.993801f,0.000982701f, +0.115357f,0.993291f,0.00809163f, +0.164275f,0.973308f,0.160266f, +-0.0349159f,0.947849f,0.316803f, +-0.267423f,0.890391f,0.368361f, +-0.327503f,0.90805f,0.261125f, +-0.196107f,0.942247f,0.271499f, +-0.118776f,0.949723f,0.289686f, +-0.296931f,0.925681f,0.234405f, +-0.445051f,0.862967f,0.239201f, +-0.335704f,0.917243f,0.2144f, +-0.25181f,0.948438f,0.1925f, +-0.329983f,0.903347f,0.274f, +-0.391867f,0.838521f,0.378579f, +-0.417038f,0.817641f,0.396917f, +-0.341558f,0.812981f,0.471594f, +-0.188106f,0.834488f,0.517925f, +-0.137025f,0.804598f,0.577794f, +-0.18711f,0.76127f,0.620852f, +0.138194f,0.960364f,-0.242082f, +0.0401358f,0.96162f,-0.271434f, +-0.076195f,0.979732f,-0.185256f, +-0.203103f,0.960439f,-0.190543f, +-0.267864f,0.941416f,-0.2049f, +-0.261748f,0.936741f,-0.232388f, +-0.231434f,0.930091f,-0.285254f, +-0.126583f,0.962607f,-0.239509f, +-0.258776f,0.934905f,-0.242872f, +-0.430322f,0.876496f,-0.215819f, +-0.353956f,0.929119f,-0.107016f, +-0.27861f,0.956787f,-0.0832819f, +-0.250796f,0.967007f,-0.0447179f, +-0.348257f,0.937394f,-0.0030026f, +-0.497787f,0.866258f,0.0424905f, +-0.584411f,0.803193f,0.115522f, +-0.394257f,0.905213f,0.158588f, +-0.343138f,0.935038f,0.0892179f, +-0.380878f,0.917442f,0.115034f, +-0.389256f,0.914513f,0.11021f, +-0.431967f,0.895633f,0.10605f, +-0.414636f,0.893675f,0.171528f, +-0.300214f,0.948969f,0.0965901f, +-0.20281f,0.978452f,-0.0387339f, +-0.123855f,0.987388f,-0.098611f, +-0.0140563f,0.999899f,0.0019046f, +-0.052066f,0.991601f,0.118388f, +-0.0936165f,0.973604f,0.208163f, +-0.149626f,0.978491f,0.142013f, +-0.198198f,0.970011f,0.140699f, +-0.130637f,0.968649f,0.211313f, +0.013631f,0.991214f,0.131563f, +0.20118f,0.979295f,0.0225449f, +0.231889f,0.971935f,-0.0396138f, +0.0131145f,0.999014f,-0.0424166f, +0.0264969f,0.999403f,0.0221517f, +0.210411f,0.977103f,0.0315571f, +0.327081f,0.943965f,0.0441437f, +0.381166f,0.920813f,0.0825546f, +0.346088f,0.933621f,0.0925967f, +0.356105f,0.932513f,0.0600724f, +0.479238f,0.87232f,0.0968908f, +0.446186f,0.89276f,0.062428f, +0.391504f,0.920172f,-0.00287489f, +0.426134f,0.9041f,0.0318405f, +0.417296f,0.907685f,0.0444148f, +0.286592f,0.957965f,0.012947f, +0.07628f,0.996621f,-0.030475f, +0.0820652f,0.99629f,0.0259114f, +-0.0280556f,0.994071f,0.105053f, +-0.213977f,0.933546f,0.287585f, +-0.245374f,0.890565f,0.382995f, +-0.189692f,0.923736f,0.332759f, +-0.238316f,0.94737f,0.213765f, +-0.176209f,0.945132f,0.275092f, +-0.265622f,0.907592f,0.32515f, +-0.420635f,0.873046f,0.246691f, +-0.275407f,0.930254f,0.242441f, +-0.273955f,0.921146f,0.276474f, +-0.415501f,0.828882f,0.374585f, +-0.488833f,0.76092f,0.426664f, +-0.43149f,0.76785f,0.473522f, +-0.33634f,0.787599f,0.516297f, +-0.228347f,0.790629f,0.568123f, +-0.231089f,0.763668f,0.602835f, +-0.28515f,0.752352f,0.593849f, +0.109283f,0.926796f,-0.359314f, +-0.0105223f,0.944186f,-0.329244f, +-0.147017f,0.945286f,-0.29124f, +-0.202823f,0.935685f,-0.288714f, +-0.214861f,0.941374f,-0.260095f, +-0.2356f,0.926477f,-0.293483f, +-0.224333f,0.941495f,-0.251519f, +-0.230404f,0.948768f,-0.216226f, +-0.277442f,0.956386f,-0.0913908f, +-0.472179f,0.876647f,-0.0923929f, +-0.428177f,0.898465f,-0.0970806f, +-0.3387f,0.938243f,-0.0705803f, +-0.291725f,0.956079f,0.0284457f, +-0.399526f,0.915525f,0.0468393f, +-0.527082f,0.845186f,0.0885769f, +-0.577694f,0.815576f,0.0332458f, +-0.408723f,0.912647f,0.00457497f, +-0.331162f,0.938989f,0.0929031f, +-0.4185f,0.893481f,0.162938f, +-0.372755f,0.902119f,0.217335f, +-0.419905f,0.891761f,0.168648f, +-0.426162f,0.889671f,0.163929f, +-0.238048f,0.949403f,0.20486f, +-0.0631417f,0.981494f,0.180781f, +-0.0934621f,0.991987f,0.0850084f, +-0.209815f,0.971464f,0.110612f, +-0.239382f,0.928806f,0.282871f, +-0.0385152f,0.924665f,0.378829f, +-0.0229585f,0.976683f,0.213458f, +-0.204415f,0.977814f,0.0457583f, +-0.131276f,0.991302f,0.00937849f, +0.100844f,0.99484f,0.0110965f, +0.227419f,0.973508f,-0.0237273f, +0.22975f,0.97307f,0.0187244f, +0.0718328f,0.997222f,0.0197173f, +0.0214849f,0.994143f,-0.105917f, +0.174121f,0.982096f,-0.0718949f, +0.303053f,0.952921f,0.010044f, +0.38012f,0.924935f,0.00218727f, +0.364895f,0.929903f,-0.0461611f, +0.383009f,0.921386f,-0.0659776f, +0.441676f,0.895702f,-0.0513817f, +0.484548f,0.87476f,0.00284626f, +0.413676f,0.910113f,-0.0237944f, +0.449057f,0.893501f,-0.00212143f, +0.360983f,0.928147f,-0.090746f, +0.274993f,0.958661f,0.0731286f, +0.0881261f,0.984394f,0.15232f, +0.00584658f,0.984704f,0.174138f, +-0.113749f,0.971528f,0.207834f, +-0.320112f,0.923512f,0.211313f, +-0.308899f,0.921582f,0.23509f, +-0.147069f,0.956187f,0.253135f, +-0.14137f,0.959806f,0.242461f, +-0.277438f,0.935166f,0.220209f, +-0.254545f,0.906523f,0.336782f, +-0.385464f,0.89189f,0.236535f, +-0.346902f,0.887297f,0.303913f, +-0.404152f,0.809818f,0.425271f, +-0.45263f,0.705418f,0.545446f, +-0.436346f,0.733679f,0.520882f, +-0.40606f,0.758487f,0.509719f, +-0.399991f,0.76519f,0.504471f, +-0.29927f,0.789873f,0.535292f, +-0.216265f,0.823324f,0.524754f, +-0.25441f,0.854784f,0.452349f, +-0.0876585f,0.974972f,-0.204317f, +-0.064531f,0.993199f,-0.096908f, +-0.142906f,0.98657f,-0.0790982f, +-0.190225f,0.979959f,-0.0591132f, +-0.245075f,0.966633f,-0.0745641f, +-0.286525f,0.954682f,-0.0805399f, +-0.302328f,0.953201f,0.00253574f, +-0.315251f,0.947498f,0.0535207f, +-0.363913f,0.92013f,0.144666f, +-0.433014f,0.884677f,0.172759f, +-0.39903f,0.904384f,0.151207f, +-0.340877f,0.927749f,0.15194f, +-0.34367f,0.933336f,0.103799f, +-0.371228f,0.927804f,0.0370044f, +-0.540653f,0.838686f,-0.0655789f, +-0.541683f,0.840171f,-0.0263209f, +-0.443789f,0.895468f,-0.0344719f, +-0.446175f,0.894923f,0.00646964f, +-0.489716f,0.870366f,0.0513954f, +-0.393228f,0.91623f,0.0767741f, +-0.386844f,0.914535f,0.118231f, +-0.456614f,0.881467f,0.1205f, +-0.291641f,0.939064f,0.181947f, +-0.0983466f,0.949337f,0.298474f, +-0.0663966f,0.917799f,0.391455f, +-0.225097f,0.912905f,0.340494f, +-0.270333f,0.917625f,0.291349f, +-0.0378823f,0.963845f,0.263756f, +0.203246f,0.94956f,0.238803f, +-0.00658121f,0.998329f,0.057403f, +-0.104339f,0.991332f,-0.0798442f, +0.0714998f,0.99184f,-0.105548f, +0.229254f,0.968801f,-0.0941692f, +0.162963f,0.980447f,-0.110304f, +0.144794f,0.987619f,-0.0603599f, +0.1028f,0.982727f,-0.153883f, +0.103742f,0.981824f,-0.158931f, +0.242509f,0.962807f,-0.119129f, +0.409757f,0.908112f,-0.0862081f, +0.420763f,0.899369f,-0.118717f, +0.356993f,0.920491f,-0.158908f, +0.417923f,0.902816f,-0.101306f, +0.45294f,0.886743f,-0.0923743f, +0.388277f,0.919595f,-0.0598771f, +0.442705f,0.896663f,-0.00260706f, +0.330753f,0.943188f,0.0316099f, +0.0976556f,0.983098f,0.154858f, +-0.0408134f,0.964902f,0.259421f, +-0.0353778f,0.920067f,0.39016f, +-0.0336634f,0.909873f,0.413518f, +-0.27131f,0.928078f,0.255075f, +-0.276299f,0.942343f,0.188808f, +-0.178846f,0.97249f,0.149254f, +-0.173925f,0.95192f,0.252185f, +-0.312455f,0.905292f,0.287781f, +-0.299358f,0.905887f,0.299588f, +-0.361522f,0.88183f,0.302783f, +-0.474485f,0.805519f,0.35497f, +-0.514467f,0.728892f,0.451708f, +-0.495653f,0.729457f,0.471404f, +-0.395267f,0.75904f,0.517322f, +-0.414244f,0.765988f,0.491594f, +-0.375453f,0.800102f,0.467837f, +-0.23686f,0.857078f,0.457509f, +-0.153599f,0.897001f,0.414483f, +-0.139778f,0.900978f,0.410733f, +-0.246424f,0.968956f,-0.0200009f, +-0.187575f,0.975459f,0.115309f, +-0.169324f,0.958565f,0.229092f, +-0.227196f,0.942917f,0.243495f, +-0.216356f,0.935609f,0.278972f, +-0.279085f,0.916546f,0.286453f, +-0.337088f,0.885038f,0.32106f, +-0.317388f,0.891504f,0.323242f, +-0.400555f,0.875243f,0.271117f, +-0.420396f,0.865286f,0.273034f, +-0.438864f,0.863369f,0.248983f, +-0.296161f,0.903481f,0.309855f, +-0.22181f,0.945018f,0.240296f, +-0.217483f,0.959525f,0.178924f, +-0.432196f,0.899705f,0.0611361f, +-0.592514f,0.805005f,-0.029893f, +-0.445437f,0.89528f,0.00770123f, +-0.444106f,0.895735f,-0.0207082f, +-0.441178f,0.89658f,-0.0387967f, +-0.433316f,0.896401f,-0.0932815f, +-0.448061f,0.893999f,-0.00273746f, +-0.479681f,0.876222f,0.046264f, +-0.38049f,0.918735f,0.105607f, +-0.274091f,0.928692f,0.249812f, +-0.115693f,0.919238f,0.37632f, +-0.109076f,0.943601f,0.312601f, +-0.183297f,0.969532f,0.162513f, +-0.0200265f,0.998099f,0.0582807f, +0.217564f,0.969248f,0.114995f, +0.107422f,0.986137f,0.126469f, +-0.0101958f,0.999802f,0.0170616f, +0.0917708f,0.993871f,-0.0616322f, +0.259886f,0.964354f,-0.049807f, +0.22181f,0.965636f,-0.135454f, +0.11068f,0.965795f,-0.234499f, +0.156396f,0.962982f,-0.219561f, +0.0996902f,0.954613f,-0.28067f, +0.240821f,0.930419f,-0.276271f, +0.362585f,0.892287f,-0.268992f, +0.39828f,0.905306f,-0.147629f, +0.377219f,0.92249f,-0.0819651f, +0.379471f,0.918832f,-0.108391f, +0.428571f,0.902988f,-0.0306522f, +0.390587f,0.920304f,0.0219829f, +0.365451f,0.930816f,-0.00527733f, +0.226127f,0.963781f,0.141399f, +-0.014879f,0.969939f,0.242893f, +-0.0990439f,0.938525f,0.330697f, +-0.160986f,0.911469f,0.37856f, +-0.0311141f,0.900531f,0.433676f, +-0.0818559f,0.904519f,0.418503f, +-0.202897f,0.939947f,0.274469f, +-0.199596f,0.951915f,0.232421f, +-0.290928f,0.922977f,0.251942f, +-0.30301f,0.91121f,0.279072f, +-0.315746f,0.908229f,0.274635f, +-0.386173f,0.858884f,0.336435f, +-0.56045f,0.768828f,0.307894f, +-0.529456f,0.742805f,0.409776f, +-0.545227f,0.770059f,0.331265f, +-0.460487f,0.804404f,0.375346f, +-0.384041f,0.835484f,0.393038f, +-0.366328f,0.856374f,0.363907f, +-0.227066f,0.886912f,0.40228f, +-0.162423f,0.896635f,0.411903f, +-0.18398f,0.877261f,0.443356f, +-0.33059f,0.941987f,0.0580528f, +-0.349053f,0.930827f,0.108275f, +-0.250298f,0.937413f,0.242089f, +-0.231173f,0.921233f,0.312871f, +-0.267366f,0.883285f,0.385127f, +-0.300638f,0.858727f,0.414975f, +-0.348846f,0.869854f,0.348799f, +-0.262698f,0.902187f,0.342122f, +-0.319043f,0.887638f,0.33213f, +-0.407631f,0.874264f,0.263628f, +-0.391131f,0.891388f,0.229006f, +-0.306387f,0.939971f,0.150271f, +-0.172289f,0.969062f,0.176734f, +-0.280735f,0.939942f,0.194158f, +-0.35822f,0.876748f,0.320922f, +-0.540223f,0.822439f,0.178196f, +-0.415201f,0.897062f,0.151285f, +-0.398489f,0.913332f,0.0838552f, +-0.47388f,0.879024f,0.052479f, +-0.430994f,0.889287f,0.153011f, +-0.501585f,0.850518f,0.158213f, +-0.493115f,0.843586f,0.212601f, +-0.437044f,0.869936f,0.228482f, +-0.335665f,0.928238f,0.160321f, +-0.135997f,0.987913f,0.0743886f, +0.0115105f,0.995614f,0.0928467f, +-0.0367985f,0.999249f,0.0121783f, +0.0254956f,0.996874f,-0.0747791f, +0.107382f,0.991622f,-0.0717932f, +0.144184f,0.989518f,0.00810907f, +0.0943487f,0.994079f,-0.0539027f, +0.124876f,0.987862f,-0.0923827f, +0.25534f,0.960035f,-0.114602f, +0.339105f,0.927956f,-0.154613f, +0.200588f,0.937015f,-0.285951f, +0.184172f,0.917658f,-0.352115f, +0.137125f,0.909076f,-0.393417f, +0.231522f,0.90798f,-0.349242f, +0.299652f,0.902049f,-0.310671f, +0.23061f,0.944613f,-0.233507f, +0.336481f,0.938772f,-0.0740748f, +0.38792f,0.918977f,-0.070704f, +0.337723f,0.938393f,-0.073227f, +0.392706f,0.919584f,-0.012147f, +0.294051f,0.954956f,-0.0399037f, +0.173344f,0.964432f,0.199555f, +-0.108669f,0.967119f,0.22994f, +-0.18728f,0.925976f,0.327863f, +-0.156223f,0.937505f,0.310931f, +-0.0961609f,0.948752f,0.301037f, +-0.051031f,0.914222f,0.401987f, +-0.116652f,0.921592f,0.370216f, +-0.16747f,0.919727f,0.355044f, +-0.233888f,0.917713f,0.321092f, +-0.296558f,0.924646f,0.23892f, +-0.384099f,0.898594f,0.212122f, +-0.451252f,0.843433f,0.291535f, +-0.561019f,0.766309f,0.313095f, +-0.56702f,0.761029f,0.315156f, +-0.502958f,0.815049f,0.287624f, +-0.46769f,0.845823f,0.256612f, +-0.438846f,0.860082f,0.260142f, +-0.380472f,0.841841f,0.382812f, +-0.286801f,0.84573f,0.449984f, +-0.166497f,0.837941f,0.519744f, +-0.237954f,0.844014f,0.480644f, +-0.400938f,0.907575f,0.124721f, +-0.36178f,0.91645f,0.170983f, +-0.326178f,0.936068f,0.131852f, +-0.348093f,0.925471f,0.149445f, +-0.380521f,0.903785f,0.195901f, +-0.261965f,0.932138f,0.249988f, +-0.229009f,0.957451f,0.175621f, +-0.296226f,0.953377f,0.0576446f, +-0.385007f,0.916429f,0.109216f, +-0.396898f,0.895963f,0.199304f, +-0.30002f,0.927264f,0.223985f, +-0.290512f,0.953204f,0.083697f, +-0.240862f,0.959505f,0.146069f, +-0.368638f,0.900621f,0.230189f, +-0.437205f,0.833732f,0.337256f, +-0.435531f,0.825298f,0.359438f, +-0.382764f,0.869714f,0.311593f, +-0.302351f,0.902083f,0.307944f, +-0.504704f,0.84016f,0.198507f, +-0.44412f,0.839306f,0.313565f, +-0.494888f,0.841296f,0.217503f, +-0.530329f,0.827106f,0.186138f, +-0.314084f,0.933199f,0.174614f, +-0.124034f,0.990967f,0.050983f, +-0.0452003f,0.995178f,-0.0870557f, +-0.00182424f,0.990385f,-0.138326f, +-0.0388611f,0.986686f,-0.157927f, +0.0684221f,0.991564f,-0.11009f, +0.102533f,0.981475f,-0.161848f, +0.149983f,0.975213f,-0.162681f, +0.108711f,0.963953f,-0.24285f, +0.134579f,0.963238f,-0.232511f, +0.280754f,0.932346f,-0.227832f, +0.370391f,0.907723f,-0.197103f, +0.290987f,0.936165f,-0.197286f, +0.244643f,0.947659f,-0.205165f, +0.12819f,0.972148f,-0.196204f, +0.159014f,0.967422f,-0.197002f, +0.312607f,0.930748f,-0.189697f, +0.153027f,0.941997f,-0.298704f, +0.218578f,0.950985f,-0.218748f, +0.390534f,0.915543f,-0.0962525f, +0.350134f,0.933592f,-0.0762398f, +0.369694f,0.928637f,-0.030973f, +0.182224f,0.981373f,0.0608345f, +-0.0452136f,0.980467f,0.191416f, +-0.152401f,0.95767f,0.244216f, +-0.205784f,0.951891f,0.22706f, +-0.112228f,0.971017f,0.211022f, +-0.130106f,0.967854f,0.215247f, +-0.151633f,0.958079f,0.243087f, +-0.104162f,0.953804f,0.281796f, +-0.17561f,0.947845f,0.265989f, +-0.209606f,0.941523f,0.263816f, +-0.251275f,0.930745f,0.265659f, +-0.361f,0.884718f,0.294879f, +-0.50281f,0.813876f,0.291185f, +-0.583247f,0.763934f,0.276094f, +-0.556622f,0.802134f,0.216224f, +-0.473532f,0.851987f,0.223352f, +-0.473757f,0.85285f,0.219548f, +-0.491496f,0.823107f,0.284477f, +-0.477559f,0.793154f,0.377946f, +-0.368868f,0.830921f,0.416542f, +-0.202419f,0.861608f,0.465466f, +-0.095407f,0.855544f,0.508864f, +-0.40239f,0.909528f,0.104118f, +-0.357524f,0.930915f,0.0746555f, +-0.280797f,0.959558f,0.0200349f, +-0.296463f,0.954936f,-0.0143765f, +-0.381172f,0.918388f,-0.106166f, +-0.308734f,0.946435f,-0.094572f, +-0.184864f,0.981918f,-0.0407667f, +-0.211096f,0.97426f,-0.0790985f, +-0.431269f,0.892976f,-0.128847f, +-0.508723f,0.860224f,-0.0348507f, +-0.315588f,0.942693f,0.108326f, +-0.229963f,0.954167f,0.191527f, +-0.338476f,0.90391f,0.261495f, +-0.399866f,0.843393f,0.358882f, +-0.508212f,0.817205f,0.271838f, +-0.45663f,0.829465f,0.321678f, +-0.343829f,0.869846f,0.353765f, +-0.25214f,0.908629f,0.332893f, +-0.465924f,0.864347f,0.189262f, +-0.451321f,0.885092f,0.11367f, +-0.398038f,0.913426f,0.0849568f, +-0.473433f,0.880353f,-0.0289816f, +-0.282123f,0.951018f,-0.126376f, +-0.111297f,0.983512f,-0.142537f, +-0.0203568f,0.995748f,-0.089847f, +0.0177076f,0.998505f,-0.0517153f, +-0.0210973f,0.999746f,0.00787929f, +0.0422415f,0.999104f,-0.00245387f, +0.162083f,0.986673f,-0.0143034f, +0.184873f,0.978111f,-0.0954998f, +0.225836f,0.960454f,-0.162869f, +0.105652f,0.960265f,-0.25832f, +0.22096f,0.965567f,-0.137321f, +0.306187f,0.951906f,0.0111556f, +0.252563f,0.963728f,0.0862585f, +0.185211f,0.975091f,0.122044f, +0.141716f,0.976503f,0.162355f, +0.200688f,0.976886f,0.0736112f, +0.398894f,0.916482f,0.0307355f, +0.27456f,0.96012f,-0.0527967f, +0.152825f,0.971043f,-0.183632f, +0.271211f,0.950001f,-0.154736f, +0.286301f,0.958137f,0.00244849f, +0.246502f,0.96458f,0.0939299f, +0.102065f,0.977178f,0.186298f, +-0.0761105f,0.976837f,0.19999f, +-0.0810786f,0.974651f,0.208524f, +-0.174214f,0.975155f,0.136831f, +-0.127689f,0.983595f,0.127422f, +-0.123239f,0.988203f,0.0909257f, +-0.173027f,0.984333f,0.033919f, +-0.13019f,0.985916f,0.104975f, +-0.151236f,0.977557f,0.146665f, +-0.212082f,0.972216f,0.0990861f, +-0.346196f,0.93167f,0.110181f, +-0.461867f,0.845088f,0.269268f, +-0.491314f,0.790968f,0.364663f, +-0.499721f,0.798886f,0.334753f, +-0.533877f,0.823302f,0.192741f, +-0.489959f,0.855912f,0.165393f, +-0.540105f,0.823669f,0.172786f, +-0.55174f,0.789596f,0.268553f, +-0.518837f,0.818462f,0.246838f, +-0.35793f,0.879679f,0.31313f, +-0.226645f,0.914368f,0.335505f, +-0.174062f,0.93173f,0.31872f, +-0.352372f,0.928926f,-0.113715f, +-0.283164f,0.949292f,-0.13661f, +-0.253833f,0.949289f,-0.185523f, +-0.258433f,0.953837f,-0.152994f, +-0.329686f,0.925665f,-0.185613f, +-0.360482f,0.913899f,-0.186657f, +-0.246398f,0.964945f,-0.0903879f, +-0.197613f,0.98019f,0.013309f, +-0.409684f,0.910684f,0.0530475f, +-0.545574f,0.83677f,0.0465257f, +-0.477964f,0.876264f,0.060934f, +-0.386247f,0.882258f,0.269135f, +-0.437443f,0.816448f,0.376904f, +-0.381546f,0.830459f,0.405906f, +-0.378931f,0.857772f,0.347329f, +-0.484349f,0.854204f,0.189053f, +-0.391934f,0.899277f,0.194136f, +-0.180618f,0.947297f,0.264585f, +-0.285059f,0.943094f,0.171219f, +-0.41449f,0.905591f,-0.0900102f, +-0.367364f,0.916679f,-0.157298f, +-0.4046f,0.892318f,-0.200168f, +-0.265207f,0.933534f,-0.241204f, +-0.171437f,0.970625f,-0.168809f, +-0.091648f,0.995789f,0.00231266f, +-0.0988725f,0.989781f,0.102747f, +-0.0749525f,0.978356f,0.192877f, +0.0618361f,0.988236f,0.139875f, +0.222758f,0.971067f,0.0860673f, +0.260459f,0.965435f,-0.00983276f, +0.296216f,0.954928f,-0.0191894f, +0.108089f,0.992937f,-0.0489145f, +0.0559635f,0.998425f,-0.00391097f, +0.182072f,0.980129f,0.0787236f, +0.189029f,0.972269f,0.137697f, +0.20292f,0.962368f,0.180751f, +0.162611f,0.977583f,0.133749f, +0.283117f,0.944546f,0.166365f, +0.362781f,0.917623f,0.162352f, +0.322808f,0.912852f,0.249991f, +0.306817f,0.930382f,0.200629f, +0.265368f,0.963264f,0.0412725f, +0.150516f,0.988588f,0.00624705f, +0.192187f,0.980013f,0.0513622f, +0.111093f,0.98864f,0.101236f, +-0.0652663f,0.990994f,0.116922f, +-0.0960853f,0.989279f,0.109972f, +-0.171018f,0.980514f,0.0966674f, +-0.118023f,0.981194f,0.152737f, +-0.0297124f,0.980668f,0.19341f, +-0.130364f,0.983461f,0.125733f, +-0.228583f,0.970632f,0.0749913f, +-0.187681f,0.973906f,0.127608f, +-0.18184f,0.968481f,0.170233f, +-0.382626f,0.904754f,0.187128f, +-0.565004f,0.795638f,0.218473f, +-0.54964f,0.808473f,0.210397f, +-0.494188f,0.848001f,0.191501f, +-0.42417f,0.88632f,0.185785f, +-0.490729f,0.864039f,0.112346f, +-0.547278f,0.819965f,0.167765f, +-0.555649f,0.823683f,0.113141f, +-0.525063f,0.850181f,0.0387426f, +-0.465555f,0.881687f,0.0767294f, +-0.25104f,0.948586f,0.19278f, +-0.134177f,0.968986f,0.207515f, +-0.358148f,0.879839f,-0.31243f, +-0.281248f,0.911984f,-0.298639f, +-0.261128f,0.923339f,-0.281526f, +-0.281121f,0.935581f,-0.213678f, +-0.316696f,0.928992f,-0.191515f, +-0.378661f,0.908066f,-0.178974f, +-0.357733f,0.923356f,-0.139433f, +-0.295419f,0.953886f,0.0531873f, +-0.456379f,0.869265f,0.18999f, +-0.492836f,0.836159f,0.240731f, +-0.533039f,0.832034f,0.153586f, +-0.471339f,0.822176f,0.319166f, +-0.417097f,0.817012f,0.398149f, +-0.397475f,0.860419f,0.318894f, +-0.295585f,0.889222f,0.349162f, +-0.397825f,0.896297f,0.195927f, +-0.426121f,0.903442f,0.0470364f, +-0.225108f,0.967792f,0.11272f, +-0.180332f,0.969123f,0.168172f, +-0.283694f,0.958436f,-0.0303046f, +-0.31011f,0.929142f,-0.201316f, +-0.379988f,0.880118f,-0.284609f, +-0.280631f,0.91033f,-0.304213f, +-0.299273f,0.919298f,-0.255591f, +-0.271669f,0.962178f,0.0202533f, +-0.127278f,0.946024f,0.298058f, +-0.0668081f,0.957542f,0.280447f, +0.156177f,0.962373f,0.222366f, +0.269377f,0.960799f,0.0655824f, +0.307217f,0.951527f,-0.0146071f, +0.247019f,0.968029f,-0.0436127f, +0.117286f,0.99106f,0.0635867f, +0.0498813f,0.996011f,0.0739844f, +0.194956f,0.980335f,0.0305971f, +0.139483f,0.989424f,-0.0398183f, +0.235447f,0.970519f,0.0515568f, +0.132445f,0.989845f,-0.05162f, +0.206421f,0.976844f,0.0562743f, +0.330371f,0.919083f,0.214804f, +0.266375f,0.922982f,0.277756f, +0.331232f,0.885792f,0.325049f, +0.36267f,0.895106f,0.259337f, +0.240431f,0.963714f,0.115964f, +0.171746f,0.982113f,-0.0771883f, +0.0351621f,0.99889f,-0.0313443f, +-0.0882653f,0.987488f,0.130674f, +-0.0658856f,0.986287f,0.151318f, +-0.167193f,0.982329f,0.0841182f, +-0.21476f,0.97234f,0.0918338f, +-0.104496f,0.958461f,0.265392f, +-0.0605561f,0.923444f,0.378926f, +-0.152497f,0.949101f,0.275594f, +-0.216118f,0.964594f,0.151167f, +-0.26219f,0.945639f,0.192413f, +-0.408309f,0.854572f,0.320922f, +-0.530012f,0.797788f,0.28744f, +-0.48417f,0.855541f,0.183383f, +-0.504616f,0.863257f,0.012294f, +-0.421367f,0.905956f,0.0411587f, +-0.517653f,0.855189f,0.0262018f, +-0.533316f,0.826853f,0.178574f, +-0.514944f,0.854185f,0.0721125f, +-0.506113f,0.861889f,-0.0315744f, +-0.499639f,0.865958f,-0.0218358f, +-0.302149f,0.952465f,0.038937f, +-0.129933f,0.988738f,0.0742583f, +}; + +btScalar Landscape02Tex[] = { +0.0f,0.273438f, +0.0f,0.265625f, +0.0078125f,0.273438f, +0.0078125f,0.265625f, +0.015625f,0.273438f, +0.015625f,0.265625f, +0.0234375f,0.273438f, +0.0234375f,0.265625f, +0.03125f,0.273438f, +0.03125f,0.265625f, +0.0390625f,0.273438f, +0.0390625f,0.265625f, +0.046875f,0.273438f, +0.046875f,0.265625f, +0.0546875f,0.273438f, +0.0546875f,0.265625f, +0.0625f,0.273438f, +0.0625f,0.265625f, +0.0703125f,0.273438f, +0.0703125f,0.265625f, +0.078125f,0.273438f, +0.078125f,0.265625f, +0.0859375f,0.273438f, +0.0859375f,0.265625f, +0.09375f,0.273438f, +0.09375f,0.265625f, +0.101563f,0.273438f, +0.101563f,0.265625f, +0.109375f,0.273438f, +0.109375f,0.265625f, +0.117188f,0.273438f, +0.117188f,0.265625f, +0.125f,0.273438f, +0.125f,0.265625f, +0.132813f,0.273438f, +0.132813f,0.265625f, +0.140625f,0.273438f, +0.140625f,0.265625f, +0.148438f,0.273438f, +0.148438f,0.265625f, +0.15625f,0.273438f, +0.15625f,0.265625f, +0.164063f,0.273438f, +0.164063f,0.265625f, +0.171875f,0.273438f, +0.171875f,0.265625f, +0.179688f,0.273438f, +0.179688f,0.265625f, +0.1875f,0.273438f, +0.1875f,0.265625f, +0.195313f,0.273438f, +0.195313f,0.265625f, +0.203125f,0.273438f, +0.203125f,0.265625f, +0.210938f,0.273438f, +0.210938f,0.265625f, +0.21875f,0.273438f, +0.21875f,0.265625f, +0.226563f,0.273438f, +0.226563f,0.265625f, +0.234375f,0.273438f, +0.234375f,0.265625f, +0.242188f,0.273438f, +0.242188f,0.265625f, +0.25f,0.273438f, +0.25f,0.265625f, +0.257813f,0.273438f, +0.257813f,0.265625f, +0.265625f,0.273438f, +0.265625f,0.265625f, +0.273438f,0.273438f, +0.273438f,0.265625f, +0.28125f,0.273438f, +0.28125f,0.265625f, +0.289063f,0.273438f, +0.289063f,0.265625f, +0.296875f,0.273438f, +0.296875f,0.265625f, +0.304688f,0.273438f, +0.304688f,0.265625f, +0.3125f,0.273438f, +0.3125f,0.265625f, +0.320313f,0.273438f, +0.320313f,0.265625f, +0.328125f,0.273438f, +0.328125f,0.265625f, +0.335938f,0.273438f, +0.335938f,0.265625f, +0.34375f,0.273438f, +0.34375f,0.265625f, +0.351563f,0.273438f, +0.351563f,0.265625f, +0.359375f,0.273438f, +0.359375f,0.265625f, +0.367188f,0.273438f, +0.367188f,0.265625f, +0.375f,0.273438f, +0.375f,0.265625f, +0.382813f,0.273438f, +0.382813f,0.265625f, +0.390625f,0.273438f, +0.390625f,0.265625f, +0.398438f,0.273438f, +0.398438f,0.265625f, +0.40625f,0.273438f, +0.40625f,0.265625f, +0.414063f,0.273438f, +0.414063f,0.265625f, +0.421875f,0.273438f, +0.421875f,0.265625f, +0.429688f,0.273438f, +0.429688f,0.265625f, +0.4375f,0.273438f, +0.4375f,0.265625f, +0.445313f,0.273438f, +0.445313f,0.265625f, +0.453125f,0.273438f, +0.453125f,0.265625f, +0.460938f,0.273438f, +0.460938f,0.265625f, +0.46875f,0.273438f, +0.46875f,0.265625f, +0.476563f,0.273438f, +0.476563f,0.265625f, +0.484375f,0.273438f, +0.484375f,0.265625f, +0.492188f,0.273438f, +0.492188f,0.265625f, +0.5f,0.273438f, +0.5f,0.265625f, +0.507813f,0.273438f, +0.507813f,0.265625f, +0.0f,0.28125f, +0.0078125f,0.28125f, +0.015625f,0.28125f, +0.0234375f,0.28125f, +0.03125f,0.28125f, +0.0390625f,0.28125f, +0.046875f,0.28125f, +0.0546875f,0.28125f, +0.0625f,0.28125f, +0.0703125f,0.28125f, +0.078125f,0.28125f, +0.0859375f,0.28125f, +0.09375f,0.28125f, +0.101563f,0.28125f, +0.109375f,0.28125f, +0.117188f,0.28125f, +0.125f,0.28125f, +0.132813f,0.28125f, +0.140625f,0.28125f, +0.148438f,0.28125f, +0.15625f,0.28125f, +0.164063f,0.28125f, +0.171875f,0.28125f, +0.179688f,0.28125f, +0.1875f,0.28125f, +0.195313f,0.28125f, +0.203125f,0.28125f, +0.210938f,0.28125f, +0.21875f,0.28125f, +0.226563f,0.28125f, +0.234375f,0.28125f, +0.242188f,0.28125f, +0.25f,0.28125f, +0.257813f,0.28125f, +0.265625f,0.28125f, +0.273438f,0.28125f, +0.28125f,0.28125f, +0.289063f,0.28125f, +0.296875f,0.28125f, +0.304688f,0.28125f, +0.3125f,0.28125f, +0.320313f,0.28125f, +0.328125f,0.28125f, +0.335938f,0.28125f, +0.34375f,0.28125f, +0.351563f,0.28125f, +0.359375f,0.28125f, +0.367188f,0.28125f, +0.375f,0.28125f, +0.382813f,0.28125f, +0.390625f,0.28125f, +0.398438f,0.28125f, +0.40625f,0.28125f, +0.414063f,0.28125f, +0.421875f,0.28125f, +0.429688f,0.28125f, +0.4375f,0.28125f, +0.445313f,0.28125f, +0.453125f,0.28125f, +0.460938f,0.28125f, +0.46875f,0.28125f, +0.476563f,0.28125f, +0.484375f,0.28125f, +0.492188f,0.28125f, +0.5f,0.28125f, +0.507813f,0.28125f, +0.0f,0.289063f, +0.0078125f,0.289063f, +0.015625f,0.289063f, +0.0234375f,0.289063f, +0.03125f,0.289063f, +0.0390625f,0.289063f, +0.046875f,0.289063f, +0.0546875f,0.289063f, +0.0625f,0.289063f, +0.0703125f,0.289063f, +0.078125f,0.289063f, +0.0859375f,0.289063f, +0.09375f,0.289063f, +0.101563f,0.289063f, +0.109375f,0.289063f, +0.117188f,0.289063f, +0.125f,0.289063f, +0.132813f,0.289063f, +0.140625f,0.289063f, +0.148438f,0.289063f, +0.15625f,0.289063f, +0.164063f,0.289063f, +0.171875f,0.289063f, +0.179688f,0.289063f, +0.1875f,0.289063f, +0.195313f,0.289063f, +0.203125f,0.289063f, +0.210938f,0.289063f, +0.21875f,0.289063f, +0.226563f,0.289063f, +0.234375f,0.289063f, +0.242188f,0.289063f, +0.25f,0.289063f, +0.257813f,0.289063f, +0.265625f,0.289063f, +0.273438f,0.289063f, +0.28125f,0.289063f, +0.289063f,0.289063f, +0.296875f,0.289063f, +0.304688f,0.289063f, +0.3125f,0.289063f, +0.320313f,0.289063f, +0.328125f,0.289063f, +0.335938f,0.289063f, +0.34375f,0.289063f, +0.351563f,0.289063f, +0.359375f,0.289063f, +0.367188f,0.289063f, +0.375f,0.289063f, +0.382813f,0.289063f, +0.390625f,0.289063f, +0.398438f,0.289063f, +0.40625f,0.289063f, +0.414063f,0.289063f, +0.421875f,0.289063f, +0.429688f,0.289063f, +0.4375f,0.289063f, +0.445313f,0.289063f, +0.453125f,0.289063f, +0.460938f,0.289063f, +0.46875f,0.289063f, +0.476563f,0.289063f, +0.484375f,0.289063f, +0.492188f,0.289063f, +0.5f,0.289063f, +0.507813f,0.289063f, +0.0f,0.296875f, +0.0078125f,0.296875f, +0.015625f,0.296875f, +0.0234375f,0.296875f, +0.03125f,0.296875f, +0.0390625f,0.296875f, +0.046875f,0.296875f, +0.0546875f,0.296875f, +0.0625f,0.296875f, +0.0703125f,0.296875f, +0.078125f,0.296875f, +0.0859375f,0.296875f, +0.09375f,0.296875f, +0.101563f,0.296875f, +0.109375f,0.296875f, +0.117188f,0.296875f, +0.125f,0.296875f, +0.132813f,0.296875f, +0.140625f,0.296875f, +0.148438f,0.296875f, +0.15625f,0.296875f, +0.164063f,0.296875f, +0.171875f,0.296875f, +0.179688f,0.296875f, +0.1875f,0.296875f, +0.195313f,0.296875f, +0.203125f,0.296875f, +0.210938f,0.296875f, +0.21875f,0.296875f, +0.226563f,0.296875f, +0.234375f,0.296875f, +0.242188f,0.296875f, +0.25f,0.296875f, +0.257813f,0.296875f, +0.265625f,0.296875f, +0.273438f,0.296875f, +0.28125f,0.296875f, +0.289063f,0.296875f, +0.296875f,0.296875f, +0.304688f,0.296875f, +0.3125f,0.296875f, +0.320313f,0.296875f, +0.328125f,0.296875f, +0.335938f,0.296875f, +0.34375f,0.296875f, +0.351563f,0.296875f, +0.359375f,0.296875f, +0.367188f,0.296875f, +0.375f,0.296875f, +0.382813f,0.296875f, +0.390625f,0.296875f, +0.398438f,0.296875f, +0.40625f,0.296875f, +0.414063f,0.296875f, +0.421875f,0.296875f, +0.429688f,0.296875f, +0.4375f,0.296875f, +0.445313f,0.296875f, +0.453125f,0.296875f, +0.460938f,0.296875f, +0.46875f,0.296875f, +0.476563f,0.296875f, +0.484375f,0.296875f, +0.492188f,0.296875f, +0.5f,0.296875f, +0.507813f,0.296875f, +0.0f,0.304688f, +0.0078125f,0.304688f, +0.015625f,0.304688f, +0.0234375f,0.304688f, +0.03125f,0.304688f, +0.0390625f,0.304688f, +0.046875f,0.304688f, +0.0546875f,0.304688f, +0.0625f,0.304688f, +0.0703125f,0.304688f, +0.078125f,0.304688f, +0.0859375f,0.304688f, +0.09375f,0.304688f, +0.101563f,0.304688f, +0.109375f,0.304688f, +0.117188f,0.304688f, +0.125f,0.304688f, +0.132813f,0.304688f, +0.140625f,0.304688f, +0.148438f,0.304688f, +0.15625f,0.304688f, +0.164063f,0.304688f, +0.171875f,0.304688f, +0.179688f,0.304688f, +0.1875f,0.304688f, +0.195313f,0.304688f, +0.203125f,0.304688f, +0.210938f,0.304688f, +0.21875f,0.304688f, +0.226563f,0.304688f, +0.234375f,0.304688f, +0.242188f,0.304688f, +0.25f,0.304688f, +0.257813f,0.304688f, +0.265625f,0.304688f, +0.273438f,0.304688f, +0.28125f,0.304688f, +0.289063f,0.304688f, +0.296875f,0.304688f, +0.304688f,0.304688f, +0.3125f,0.304688f, +0.320313f,0.304688f, +0.328125f,0.304688f, +0.335938f,0.304688f, +0.34375f,0.304688f, +0.351563f,0.304688f, +0.359375f,0.304688f, +0.367188f,0.304688f, +0.375f,0.304688f, +0.382813f,0.304688f, +0.390625f,0.304688f, +0.398438f,0.304688f, +0.40625f,0.304688f, +0.414063f,0.304688f, +0.421875f,0.304688f, +0.429688f,0.304688f, +0.4375f,0.304688f, +0.445313f,0.304688f, +0.453125f,0.304688f, +0.460938f,0.304688f, +0.46875f,0.304688f, +0.476563f,0.304688f, +0.484375f,0.304688f, +0.492188f,0.304688f, +0.5f,0.304688f, +0.507813f,0.304688f, +0.0f,0.3125f, +0.0078125f,0.3125f, +0.015625f,0.3125f, +0.0234375f,0.3125f, +0.03125f,0.3125f, +0.0390625f,0.3125f, +0.046875f,0.3125f, +0.0546875f,0.3125f, +0.0625f,0.3125f, +0.0703125f,0.3125f, +0.078125f,0.3125f, +0.0859375f,0.3125f, +0.09375f,0.3125f, +0.101563f,0.3125f, +0.109375f,0.3125f, +0.117188f,0.3125f, +0.125f,0.3125f, +0.132813f,0.3125f, +0.140625f,0.3125f, +0.148438f,0.3125f, +0.15625f,0.3125f, +0.164063f,0.3125f, +0.171875f,0.3125f, +0.179688f,0.3125f, +0.1875f,0.3125f, +0.195313f,0.3125f, +0.203125f,0.3125f, +0.210938f,0.3125f, +0.21875f,0.3125f, +0.226563f,0.3125f, +0.234375f,0.3125f, +0.242188f,0.3125f, +0.25f,0.3125f, +0.257813f,0.3125f, +0.265625f,0.3125f, +0.273438f,0.3125f, +0.28125f,0.3125f, +0.289063f,0.3125f, +0.296875f,0.3125f, +0.304688f,0.3125f, +0.3125f,0.3125f, +0.320313f,0.3125f, +0.328125f,0.3125f, +0.335938f,0.3125f, +0.34375f,0.3125f, +0.351563f,0.3125f, +0.359375f,0.3125f, +0.367188f,0.3125f, +0.375f,0.3125f, +0.382813f,0.3125f, +0.390625f,0.3125f, +0.398438f,0.3125f, +0.40625f,0.3125f, +0.414063f,0.3125f, +0.421875f,0.3125f, +0.429688f,0.3125f, +0.4375f,0.3125f, +0.445313f,0.3125f, +0.453125f,0.3125f, +0.460938f,0.3125f, +0.46875f,0.3125f, +0.476563f,0.3125f, +0.484375f,0.3125f, +0.492188f,0.3125f, +0.5f,0.3125f, +0.507813f,0.3125f, +0.0f,0.320313f, +0.0078125f,0.320313f, +0.015625f,0.320313f, +0.0234375f,0.320313f, +0.03125f,0.320313f, +0.0390625f,0.320313f, +0.046875f,0.320313f, +0.0546875f,0.320313f, +0.0625f,0.320313f, +0.0703125f,0.320313f, +0.078125f,0.320313f, +0.0859375f,0.320313f, +0.09375f,0.320313f, +0.101563f,0.320313f, +0.109375f,0.320313f, +0.117188f,0.320313f, +0.125f,0.320313f, +0.132813f,0.320313f, +0.140625f,0.320313f, +0.148438f,0.320313f, +0.15625f,0.320313f, +0.164063f,0.320313f, +0.171875f,0.320313f, +0.179688f,0.320313f, +0.1875f,0.320313f, +0.195313f,0.320313f, +0.203125f,0.320313f, +0.210938f,0.320313f, +0.21875f,0.320313f, +0.226563f,0.320313f, +0.234375f,0.320313f, +0.242188f,0.320313f, +0.25f,0.320313f, +0.257813f,0.320313f, +0.265625f,0.320313f, +0.273438f,0.320313f, +0.28125f,0.320313f, +0.289063f,0.320313f, +0.296875f,0.320313f, +0.304688f,0.320313f, +0.3125f,0.320313f, +0.320313f,0.320313f, +0.328125f,0.320313f, +0.335938f,0.320313f, +0.34375f,0.320313f, +0.351563f,0.320313f, +0.359375f,0.320313f, +0.367188f,0.320313f, +0.375f,0.320313f, +0.382813f,0.320313f, +0.390625f,0.320313f, +0.398438f,0.320313f, +0.40625f,0.320313f, +0.414063f,0.320313f, +0.421875f,0.320313f, +0.429688f,0.320313f, +0.4375f,0.320313f, +0.445313f,0.320313f, +0.453125f,0.320313f, +0.460938f,0.320313f, +0.46875f,0.320313f, +0.476563f,0.320313f, +0.484375f,0.320313f, +0.492188f,0.320313f, +0.5f,0.320313f, +0.507813f,0.320313f, +0.0f,0.328125f, +0.0078125f,0.328125f, +0.015625f,0.328125f, +0.0234375f,0.328125f, +0.03125f,0.328125f, +0.0390625f,0.328125f, +0.046875f,0.328125f, +0.0546875f,0.328125f, +0.0625f,0.328125f, +0.0703125f,0.328125f, +0.078125f,0.328125f, +0.0859375f,0.328125f, +0.09375f,0.328125f, +0.101563f,0.328125f, +0.109375f,0.328125f, +0.117188f,0.328125f, +0.125f,0.328125f, +0.132813f,0.328125f, +0.140625f,0.328125f, +0.148438f,0.328125f, +0.15625f,0.328125f, +0.164063f,0.328125f, +0.171875f,0.328125f, +0.179688f,0.328125f, +0.1875f,0.328125f, +0.195313f,0.328125f, +0.203125f,0.328125f, +0.210938f,0.328125f, +0.21875f,0.328125f, +0.226563f,0.328125f, +0.234375f,0.328125f, +0.242188f,0.328125f, +0.25f,0.328125f, +0.257813f,0.328125f, +0.265625f,0.328125f, +0.273438f,0.328125f, +0.28125f,0.328125f, +0.289063f,0.328125f, +0.296875f,0.328125f, +0.304688f,0.328125f, +0.3125f,0.328125f, +0.320313f,0.328125f, +0.328125f,0.328125f, +0.335938f,0.328125f, +0.34375f,0.328125f, +0.351563f,0.328125f, +0.359375f,0.328125f, +0.367188f,0.328125f, +0.375f,0.328125f, +0.382813f,0.328125f, +0.390625f,0.328125f, +0.398438f,0.328125f, +0.40625f,0.328125f, +0.414063f,0.328125f, +0.421875f,0.328125f, +0.429688f,0.328125f, +0.4375f,0.328125f, +0.445313f,0.328125f, +0.453125f,0.328125f, +0.460938f,0.328125f, +0.46875f,0.328125f, +0.476563f,0.328125f, +0.484375f,0.328125f, +0.492188f,0.328125f, +0.5f,0.328125f, +0.507813f,0.328125f, +0.0f,0.335938f, +0.0078125f,0.335938f, +0.015625f,0.335938f, +0.0234375f,0.335938f, +0.03125f,0.335938f, +0.0390625f,0.335938f, +0.046875f,0.335938f, +0.0546875f,0.335938f, +0.0625f,0.335938f, +0.0703125f,0.335938f, +0.078125f,0.335938f, +0.0859375f,0.335938f, +0.09375f,0.335938f, +0.101563f,0.335938f, +0.109375f,0.335938f, +0.117188f,0.335938f, +0.125f,0.335938f, +0.132813f,0.335938f, +0.140625f,0.335938f, +0.148438f,0.335938f, +0.15625f,0.335938f, +0.164063f,0.335938f, +0.171875f,0.335938f, +0.179688f,0.335938f, +0.1875f,0.335938f, +0.195313f,0.335938f, +0.203125f,0.335938f, +0.210938f,0.335938f, +0.21875f,0.335938f, +0.226563f,0.335938f, +0.234375f,0.335938f, +0.242188f,0.335938f, +0.25f,0.335938f, +0.257813f,0.335938f, +0.265625f,0.335938f, +0.273438f,0.335938f, +0.28125f,0.335938f, +0.289063f,0.335938f, +0.296875f,0.335938f, +0.304688f,0.335938f, +0.3125f,0.335938f, +0.320313f,0.335938f, +0.328125f,0.335938f, +0.335938f,0.335938f, +0.34375f,0.335938f, +0.351563f,0.335938f, +0.359375f,0.335938f, +0.367188f,0.335938f, +0.375f,0.335938f, +0.382813f,0.335938f, +0.390625f,0.335938f, +0.398438f,0.335938f, +0.40625f,0.335938f, +0.414063f,0.335938f, +0.421875f,0.335938f, +0.429688f,0.335938f, +0.4375f,0.335938f, +0.445313f,0.335938f, +0.453125f,0.335938f, +0.460938f,0.335938f, +0.46875f,0.335938f, +0.476563f,0.335938f, +0.484375f,0.335938f, +0.492188f,0.335938f, +0.5f,0.335938f, +0.507813f,0.335938f, +0.0f,0.34375f, +0.0078125f,0.34375f, +0.015625f,0.34375f, +0.0234375f,0.34375f, +0.03125f,0.34375f, +0.0390625f,0.34375f, +0.046875f,0.34375f, +0.0546875f,0.34375f, +0.0625f,0.34375f, +0.0703125f,0.34375f, +0.078125f,0.34375f, +0.0859375f,0.34375f, +0.09375f,0.34375f, +0.101563f,0.34375f, +0.109375f,0.34375f, +0.117188f,0.34375f, +0.125f,0.34375f, +0.132813f,0.34375f, +0.140625f,0.34375f, +0.148438f,0.34375f, +0.15625f,0.34375f, +0.164063f,0.34375f, +0.171875f,0.34375f, +0.179688f,0.34375f, +0.1875f,0.34375f, +0.195313f,0.34375f, +0.203125f,0.34375f, +0.210938f,0.34375f, +0.21875f,0.34375f, +0.226563f,0.34375f, +0.234375f,0.34375f, +0.242188f,0.34375f, +0.25f,0.34375f, +0.257813f,0.34375f, +0.265625f,0.34375f, +0.273438f,0.34375f, +0.28125f,0.34375f, +0.289063f,0.34375f, +0.296875f,0.34375f, +0.304688f,0.34375f, +0.3125f,0.34375f, +0.320313f,0.34375f, +0.328125f,0.34375f, +0.335938f,0.34375f, +0.34375f,0.34375f, +0.351563f,0.34375f, +0.359375f,0.34375f, +0.367188f,0.34375f, +0.375f,0.34375f, +0.382813f,0.34375f, +0.390625f,0.34375f, +0.398438f,0.34375f, +0.40625f,0.34375f, +0.414063f,0.34375f, +0.421875f,0.34375f, +0.429688f,0.34375f, +0.4375f,0.34375f, +0.445313f,0.34375f, +0.453125f,0.34375f, +0.460938f,0.34375f, +0.46875f,0.34375f, +0.476563f,0.34375f, +0.484375f,0.34375f, +0.492188f,0.34375f, +0.5f,0.34375f, +0.507813f,0.34375f, +0.0f,0.351563f, +0.0078125f,0.351563f, +0.015625f,0.351563f, +0.0234375f,0.351563f, +0.03125f,0.351563f, +0.0390625f,0.351563f, +0.046875f,0.351563f, +0.0546875f,0.351563f, +0.0625f,0.351563f, +0.0703125f,0.351563f, +0.078125f,0.351563f, +0.0859375f,0.351563f, +0.09375f,0.351563f, +0.101563f,0.351563f, +0.109375f,0.351563f, +0.117188f,0.351563f, +0.125f,0.351563f, +0.132813f,0.351563f, +0.140625f,0.351563f, +0.148438f,0.351563f, +0.15625f,0.351563f, +0.164063f,0.351563f, +0.171875f,0.351563f, +0.179688f,0.351563f, +0.1875f,0.351563f, +0.195313f,0.351563f, +0.203125f,0.351563f, +0.210938f,0.351563f, +0.21875f,0.351563f, +0.226563f,0.351563f, +0.234375f,0.351563f, +0.242188f,0.351563f, +0.25f,0.351563f, +0.257813f,0.351563f, +0.265625f,0.351563f, +0.273438f,0.351563f, +0.28125f,0.351563f, +0.289063f,0.351563f, +0.296875f,0.351563f, +0.304688f,0.351563f, +0.3125f,0.351563f, +0.320313f,0.351563f, +0.328125f,0.351563f, +0.335938f,0.351563f, +0.34375f,0.351563f, +0.351563f,0.351563f, +0.359375f,0.351563f, +0.367188f,0.351563f, +0.375f,0.351563f, +0.382813f,0.351563f, +0.390625f,0.351563f, +0.398438f,0.351563f, +0.40625f,0.351563f, +0.414063f,0.351563f, +0.421875f,0.351563f, +0.429688f,0.351563f, +0.4375f,0.351563f, +0.445313f,0.351563f, +0.453125f,0.351563f, +0.460938f,0.351563f, +0.46875f,0.351563f, +0.476563f,0.351563f, +0.484375f,0.351563f, +0.492188f,0.351563f, +0.5f,0.351563f, +0.507813f,0.351563f, +0.0f,0.359375f, +0.0078125f,0.359375f, +0.015625f,0.359375f, +0.0234375f,0.359375f, +0.03125f,0.359375f, +0.0390625f,0.359375f, +0.046875f,0.359375f, +0.0546875f,0.359375f, +0.0625f,0.359375f, +0.0703125f,0.359375f, +0.078125f,0.359375f, +0.0859375f,0.359375f, +0.09375f,0.359375f, +0.101563f,0.359375f, +0.109375f,0.359375f, +0.117188f,0.359375f, +0.125f,0.359375f, +0.132813f,0.359375f, +0.140625f,0.359375f, +0.148438f,0.359375f, +0.15625f,0.359375f, +0.164063f,0.359375f, +0.171875f,0.359375f, +0.179688f,0.359375f, +0.1875f,0.359375f, +0.195313f,0.359375f, +0.203125f,0.359375f, +0.210938f,0.359375f, +0.21875f,0.359375f, +0.226563f,0.359375f, +0.234375f,0.359375f, +0.242188f,0.359375f, +0.25f,0.359375f, +0.257813f,0.359375f, +0.265625f,0.359375f, +0.273438f,0.359375f, +0.28125f,0.359375f, +0.289063f,0.359375f, +0.296875f,0.359375f, +0.304688f,0.359375f, +0.3125f,0.359375f, +0.320313f,0.359375f, +0.328125f,0.359375f, +0.335938f,0.359375f, +0.34375f,0.359375f, +0.351563f,0.359375f, +0.359375f,0.359375f, +0.367188f,0.359375f, +0.375f,0.359375f, +0.382813f,0.359375f, +0.390625f,0.359375f, +0.398438f,0.359375f, +0.40625f,0.359375f, +0.414063f,0.359375f, +0.421875f,0.359375f, +0.429688f,0.359375f, +0.4375f,0.359375f, +0.445313f,0.359375f, +0.453125f,0.359375f, +0.460938f,0.359375f, +0.46875f,0.359375f, +0.476563f,0.359375f, +0.484375f,0.359375f, +0.492188f,0.359375f, +0.5f,0.359375f, +0.507813f,0.359375f, +0.0f,0.367188f, +0.0078125f,0.367188f, +0.015625f,0.367188f, +0.0234375f,0.367188f, +0.03125f,0.367188f, +0.0390625f,0.367188f, +0.046875f,0.367188f, +0.0546875f,0.367188f, +0.0625f,0.367188f, +0.0703125f,0.367188f, +0.078125f,0.367188f, +0.0859375f,0.367188f, +0.09375f,0.367188f, +0.101563f,0.367188f, +0.109375f,0.367188f, +0.117188f,0.367188f, +0.125f,0.367188f, +0.132813f,0.367188f, +0.140625f,0.367188f, +0.148438f,0.367188f, +0.15625f,0.367188f, +0.164063f,0.367188f, +0.171875f,0.367188f, +0.179688f,0.367188f, +0.1875f,0.367188f, +0.195313f,0.367188f, +0.203125f,0.367188f, +0.210938f,0.367188f, +0.21875f,0.367188f, +0.226563f,0.367188f, +0.234375f,0.367188f, +0.242188f,0.367188f, +0.25f,0.367188f, +0.257813f,0.367188f, +0.265625f,0.367188f, +0.273438f,0.367188f, +0.28125f,0.367188f, +0.289063f,0.367188f, +0.296875f,0.367188f, +0.304688f,0.367188f, +0.3125f,0.367188f, +0.320313f,0.367188f, +0.328125f,0.367188f, +0.335938f,0.367188f, +0.34375f,0.367188f, +0.351563f,0.367188f, +0.359375f,0.367188f, +0.367188f,0.367188f, +0.375f,0.367188f, +0.382813f,0.367188f, +0.390625f,0.367188f, +0.398438f,0.367188f, +0.40625f,0.367188f, +0.414063f,0.367188f, +0.421875f,0.367188f, +0.429688f,0.367188f, +0.4375f,0.367188f, +0.445313f,0.367188f, +0.453125f,0.367188f, +0.460938f,0.367188f, +0.46875f,0.367188f, +0.476563f,0.367188f, +0.484375f,0.367188f, +0.492188f,0.367188f, +0.5f,0.367188f, +0.507813f,0.367188f, +0.0f,0.375f, +0.0078125f,0.375f, +0.015625f,0.375f, +0.0234375f,0.375f, +0.03125f,0.375f, +0.0390625f,0.375f, +0.046875f,0.375f, +0.0546875f,0.375f, +0.0625f,0.375f, +0.0703125f,0.375f, +0.078125f,0.375f, +0.0859375f,0.375f, +0.09375f,0.375f, +0.101563f,0.375f, +0.109375f,0.375f, +0.117188f,0.375f, +0.125f,0.375f, +0.132813f,0.375f, +0.140625f,0.375f, +0.148438f,0.375f, +0.15625f,0.375f, +0.164063f,0.375f, +0.171875f,0.375f, +0.179688f,0.375f, +0.1875f,0.375f, +0.195313f,0.375f, +0.203125f,0.375f, +0.210938f,0.375f, +0.21875f,0.375f, +0.226563f,0.375f, +0.234375f,0.375f, +0.242188f,0.375f, +0.25f,0.375f, +0.257813f,0.375f, +0.265625f,0.375f, +0.273438f,0.375f, +0.28125f,0.375f, +0.289063f,0.375f, +0.296875f,0.375f, +0.304688f,0.375f, +0.3125f,0.375f, +0.320313f,0.375f, +0.328125f,0.375f, +0.335938f,0.375f, +0.34375f,0.375f, +0.351563f,0.375f, +0.359375f,0.375f, +0.367188f,0.375f, +0.375f,0.375f, +0.382813f,0.375f, +0.390625f,0.375f, +0.398438f,0.375f, +0.40625f,0.375f, +0.414063f,0.375f, +0.421875f,0.375f, +0.429688f,0.375f, +0.4375f,0.375f, +0.445313f,0.375f, +0.453125f,0.375f, +0.460938f,0.375f, +0.46875f,0.375f, +0.476563f,0.375f, +0.484375f,0.375f, +0.492188f,0.375f, +0.5f,0.375f, +0.507813f,0.375f, +0.0f,0.382813f, +0.0078125f,0.382813f, +0.015625f,0.382813f, +0.0234375f,0.382813f, +0.03125f,0.382813f, +0.0390625f,0.382813f, +0.046875f,0.382813f, +0.0546875f,0.382813f, +0.0625f,0.382813f, +0.0703125f,0.382813f, +0.078125f,0.382813f, +0.0859375f,0.382813f, +0.09375f,0.382813f, +0.101563f,0.382813f, +0.109375f,0.382813f, +0.117188f,0.382813f, +0.125f,0.382813f, +0.132813f,0.382813f, +0.140625f,0.382813f, +0.148438f,0.382813f, +0.15625f,0.382813f, +0.164063f,0.382813f, +0.171875f,0.382813f, +0.179688f,0.382813f, +0.1875f,0.382813f, +0.195313f,0.382813f, +0.203125f,0.382813f, +0.210938f,0.382813f, +0.21875f,0.382813f, +0.226563f,0.382813f, +0.234375f,0.382813f, +0.242188f,0.382813f, +0.25f,0.382813f, +0.257813f,0.382813f, +0.265625f,0.382813f, +0.273438f,0.382813f, +0.28125f,0.382813f, +0.289063f,0.382813f, +0.296875f,0.382813f, +0.304688f,0.382813f, +0.3125f,0.382813f, +0.320313f,0.382813f, +0.328125f,0.382813f, +0.335938f,0.382813f, +0.34375f,0.382813f, +0.351563f,0.382813f, +0.359375f,0.382813f, +0.367188f,0.382813f, +0.375f,0.382813f, +0.382813f,0.382813f, +0.390625f,0.382813f, +0.398438f,0.382813f, +0.40625f,0.382813f, +0.414063f,0.382813f, +0.421875f,0.382813f, +0.429688f,0.382813f, +0.4375f,0.382813f, +0.445313f,0.382813f, +0.453125f,0.382813f, +0.460938f,0.382813f, +0.46875f,0.382813f, +0.476563f,0.382813f, +0.484375f,0.382813f, +0.492188f,0.382813f, +0.5f,0.382813f, +0.507813f,0.382813f, +0.0f,0.390625f, +0.0078125f,0.390625f, +0.015625f,0.390625f, +0.0234375f,0.390625f, +0.03125f,0.390625f, +0.0390625f,0.390625f, +0.046875f,0.390625f, +0.0546875f,0.390625f, +0.0625f,0.390625f, +0.0703125f,0.390625f, +0.078125f,0.390625f, +0.0859375f,0.390625f, +0.09375f,0.390625f, +0.101563f,0.390625f, +0.109375f,0.390625f, +0.117188f,0.390625f, +0.125f,0.390625f, +0.132813f,0.390625f, +0.140625f,0.390625f, +0.148438f,0.390625f, +0.15625f,0.390625f, +0.164063f,0.390625f, +0.171875f,0.390625f, +0.179688f,0.390625f, +0.1875f,0.390625f, +0.195313f,0.390625f, +0.203125f,0.390625f, +0.210938f,0.390625f, +0.21875f,0.390625f, +0.226563f,0.390625f, +0.234375f,0.390625f, +0.242188f,0.390625f, +0.25f,0.390625f, +0.257813f,0.390625f, +0.265625f,0.390625f, +0.273438f,0.390625f, +0.28125f,0.390625f, +0.289063f,0.390625f, +0.296875f,0.390625f, +0.304688f,0.390625f, +0.3125f,0.390625f, +0.320313f,0.390625f, +0.328125f,0.390625f, +0.335938f,0.390625f, +0.34375f,0.390625f, +0.351563f,0.390625f, +0.359375f,0.390625f, +0.367188f,0.390625f, +0.375f,0.390625f, +0.382813f,0.390625f, +0.390625f,0.390625f, +0.398438f,0.390625f, +0.40625f,0.390625f, +0.414063f,0.390625f, +0.421875f,0.390625f, +0.429688f,0.390625f, +0.4375f,0.390625f, +0.445313f,0.390625f, +0.453125f,0.390625f, +0.460938f,0.390625f, +0.46875f,0.390625f, +0.476563f,0.390625f, +0.484375f,0.390625f, +0.492188f,0.390625f, +0.5f,0.390625f, +0.507813f,0.390625f, +0.0f,0.398438f, +0.0078125f,0.398438f, +0.015625f,0.398438f, +0.0234375f,0.398438f, +0.03125f,0.398438f, +0.0390625f,0.398438f, +0.046875f,0.398438f, +0.0546875f,0.398438f, +0.0625f,0.398438f, +0.0703125f,0.398438f, +0.078125f,0.398438f, +0.0859375f,0.398438f, +0.09375f,0.398438f, +0.101563f,0.398438f, +0.109375f,0.398438f, +0.117188f,0.398438f, +0.125f,0.398438f, +0.132813f,0.398438f, +0.140625f,0.398438f, +0.148438f,0.398438f, +0.15625f,0.398438f, +0.164063f,0.398438f, +0.171875f,0.398438f, +0.179688f,0.398438f, +0.1875f,0.398438f, +0.195313f,0.398438f, +0.203125f,0.398438f, +0.210938f,0.398438f, +0.21875f,0.398438f, +0.226563f,0.398438f, +0.234375f,0.398438f, +0.242188f,0.398438f, +0.25f,0.398438f, +0.257813f,0.398438f, +0.265625f,0.398438f, +0.273438f,0.398438f, +0.28125f,0.398438f, +0.289063f,0.398438f, +0.296875f,0.398438f, +0.304688f,0.398438f, +0.3125f,0.398438f, +0.320313f,0.398438f, +0.328125f,0.398438f, +0.335938f,0.398438f, +0.34375f,0.398438f, +0.351563f,0.398438f, +0.359375f,0.398438f, +0.367188f,0.398438f, +0.375f,0.398438f, +0.382813f,0.398438f, +0.390625f,0.398438f, +0.398438f,0.398438f, +0.40625f,0.398438f, +0.414063f,0.398438f, +0.421875f,0.398438f, +0.429688f,0.398438f, +0.4375f,0.398438f, +0.445313f,0.398438f, +0.453125f,0.398438f, +0.460938f,0.398438f, +0.46875f,0.398438f, +0.476563f,0.398438f, +0.484375f,0.398438f, +0.492188f,0.398438f, +0.5f,0.398438f, +0.507813f,0.398438f, +0.0f,0.40625f, +0.0078125f,0.40625f, +0.015625f,0.40625f, +0.0234375f,0.40625f, +0.03125f,0.40625f, +0.0390625f,0.40625f, +0.046875f,0.40625f, +0.0546875f,0.40625f, +0.0625f,0.40625f, +0.0703125f,0.40625f, +0.078125f,0.40625f, +0.0859375f,0.40625f, +0.09375f,0.40625f, +0.101563f,0.40625f, +0.109375f,0.40625f, +0.117188f,0.40625f, +0.125f,0.40625f, +0.132813f,0.40625f, +0.140625f,0.40625f, +0.148438f,0.40625f, +0.15625f,0.40625f, +0.164063f,0.40625f, +0.171875f,0.40625f, +0.179688f,0.40625f, +0.1875f,0.40625f, +0.195313f,0.40625f, +0.203125f,0.40625f, +0.210938f,0.40625f, +0.21875f,0.40625f, +0.226563f,0.40625f, +0.234375f,0.40625f, +0.242188f,0.40625f, +0.25f,0.40625f, +0.257813f,0.40625f, +0.265625f,0.40625f, +0.273438f,0.40625f, +0.28125f,0.40625f, +0.289063f,0.40625f, +0.296875f,0.40625f, +0.304688f,0.40625f, +0.3125f,0.40625f, +0.320313f,0.40625f, +0.328125f,0.40625f, +0.335938f,0.40625f, +0.34375f,0.40625f, +0.351563f,0.40625f, +0.359375f,0.40625f, +0.367188f,0.40625f, +0.375f,0.40625f, +0.382813f,0.40625f, +0.390625f,0.40625f, +0.398438f,0.40625f, +0.40625f,0.40625f, +0.414063f,0.40625f, +0.421875f,0.40625f, +0.429688f,0.40625f, +0.4375f,0.40625f, +0.445313f,0.40625f, +0.453125f,0.40625f, +0.460938f,0.40625f, +0.46875f,0.40625f, +0.476563f,0.40625f, +0.484375f,0.40625f, +0.492188f,0.40625f, +0.5f,0.40625f, +0.507813f,0.40625f, +0.0f,0.414063f, +0.0078125f,0.414063f, +0.015625f,0.414063f, +0.0234375f,0.414063f, +0.03125f,0.414063f, +0.0390625f,0.414063f, +0.046875f,0.414063f, +0.0546875f,0.414063f, +0.0625f,0.414063f, +0.0703125f,0.414063f, +0.078125f,0.414063f, +0.0859375f,0.414063f, +0.09375f,0.414063f, +0.101563f,0.414063f, +0.109375f,0.414063f, +0.117188f,0.414063f, +0.125f,0.414063f, +0.132813f,0.414063f, +0.140625f,0.414063f, +0.148438f,0.414063f, +0.15625f,0.414063f, +0.164063f,0.414063f, +0.171875f,0.414063f, +0.179688f,0.414063f, +0.1875f,0.414063f, +0.195313f,0.414063f, +0.203125f,0.414063f, +0.210938f,0.414063f, +0.21875f,0.414063f, +0.226563f,0.414063f, +0.234375f,0.414063f, +0.242188f,0.414063f, +0.25f,0.414063f, +0.257813f,0.414063f, +0.265625f,0.414063f, +0.273438f,0.414063f, +0.28125f,0.414063f, +0.289063f,0.414063f, +0.296875f,0.414063f, +0.304688f,0.414063f, +0.3125f,0.414063f, +0.320313f,0.414063f, +0.328125f,0.414063f, +0.335938f,0.414063f, +0.34375f,0.414063f, +0.351563f,0.414063f, +0.359375f,0.414063f, +0.367188f,0.414063f, +0.375f,0.414063f, +0.382813f,0.414063f, +0.390625f,0.414063f, +0.398438f,0.414063f, +0.40625f,0.414063f, +0.414063f,0.414063f, +0.421875f,0.414063f, +0.429688f,0.414063f, +0.4375f,0.414063f, +0.445313f,0.414063f, +0.453125f,0.414063f, +0.460938f,0.414063f, +0.46875f,0.414063f, +0.476563f,0.414063f, +0.484375f,0.414063f, +0.492188f,0.414063f, +0.5f,0.414063f, +0.507813f,0.414063f, +0.0f,0.421875f, +0.0078125f,0.421875f, +0.015625f,0.421875f, +0.0234375f,0.421875f, +0.03125f,0.421875f, +0.0390625f,0.421875f, +0.046875f,0.421875f, +0.0546875f,0.421875f, +0.0625f,0.421875f, +0.0703125f,0.421875f, +0.078125f,0.421875f, +0.0859375f,0.421875f, +0.09375f,0.421875f, +0.101563f,0.421875f, +0.109375f,0.421875f, +0.117188f,0.421875f, +0.125f,0.421875f, +0.132813f,0.421875f, +0.140625f,0.421875f, +0.148438f,0.421875f, +0.15625f,0.421875f, +0.164063f,0.421875f, +0.171875f,0.421875f, +0.179688f,0.421875f, +0.1875f,0.421875f, +0.195313f,0.421875f, +0.203125f,0.421875f, +0.210938f,0.421875f, +0.21875f,0.421875f, +0.226563f,0.421875f, +0.234375f,0.421875f, +0.242188f,0.421875f, +0.25f,0.421875f, +0.257813f,0.421875f, +0.265625f,0.421875f, +0.273438f,0.421875f, +0.28125f,0.421875f, +0.289063f,0.421875f, +0.296875f,0.421875f, +0.304688f,0.421875f, +0.3125f,0.421875f, +0.320313f,0.421875f, +0.328125f,0.421875f, +0.335938f,0.421875f, +0.34375f,0.421875f, +0.351563f,0.421875f, +0.359375f,0.421875f, +0.367188f,0.421875f, +0.375f,0.421875f, +0.382813f,0.421875f, +0.390625f,0.421875f, +0.398438f,0.421875f, +0.40625f,0.421875f, +0.414063f,0.421875f, +0.421875f,0.421875f, +0.429688f,0.421875f, +0.4375f,0.421875f, +0.445313f,0.421875f, +0.453125f,0.421875f, +0.460938f,0.421875f, +0.46875f,0.421875f, +0.476563f,0.421875f, +0.484375f,0.421875f, +0.492188f,0.421875f, +0.5f,0.421875f, +0.507813f,0.421875f, +0.0f,0.429688f, +0.0078125f,0.429688f, +0.015625f,0.429688f, +0.0234375f,0.429688f, +0.03125f,0.429688f, +0.0390625f,0.429688f, +0.046875f,0.429688f, +0.0546875f,0.429688f, +0.0625f,0.429688f, +0.0703125f,0.429688f, +0.078125f,0.429688f, +0.0859375f,0.429688f, +0.09375f,0.429688f, +0.101563f,0.429688f, +0.109375f,0.429688f, +0.117188f,0.429688f, +0.125f,0.429688f, +0.132813f,0.429688f, +0.140625f,0.429688f, +0.148438f,0.429688f, +0.15625f,0.429688f, +0.164063f,0.429688f, +0.171875f,0.429688f, +0.179688f,0.429688f, +0.1875f,0.429688f, +0.195313f,0.429688f, +0.203125f,0.429688f, +0.210938f,0.429688f, +0.21875f,0.429688f, +0.226563f,0.429688f, +0.234375f,0.429688f, +0.242188f,0.429688f, +0.25f,0.429688f, +0.257813f,0.429688f, +0.265625f,0.429688f, +0.273438f,0.429688f, +0.28125f,0.429688f, +0.289063f,0.429688f, +0.296875f,0.429688f, +0.304688f,0.429688f, +0.3125f,0.429688f, +0.320313f,0.429688f, +0.328125f,0.429688f, +0.335938f,0.429688f, +0.34375f,0.429688f, +0.351563f,0.429688f, +0.359375f,0.429688f, +0.367188f,0.429688f, +0.375f,0.429688f, +0.382813f,0.429688f, +0.390625f,0.429688f, +0.398438f,0.429688f, +0.40625f,0.429688f, +0.414063f,0.429688f, +0.421875f,0.429688f, +0.429688f,0.429688f, +0.4375f,0.429688f, +0.445313f,0.429688f, +0.453125f,0.429688f, +0.460938f,0.429688f, +0.46875f,0.429688f, +0.476563f,0.429688f, +0.484375f,0.429688f, +0.492188f,0.429688f, +0.5f,0.429688f, +0.507813f,0.429688f, +0.0f,0.4375f, +0.0078125f,0.4375f, +0.015625f,0.4375f, +0.0234375f,0.4375f, +0.03125f,0.4375f, +0.0390625f,0.4375f, +0.046875f,0.4375f, +0.0546875f,0.4375f, +0.0625f,0.4375f, +0.0703125f,0.4375f, +0.078125f,0.4375f, +0.0859375f,0.4375f, +0.09375f,0.4375f, +0.101563f,0.4375f, +0.109375f,0.4375f, +0.117188f,0.4375f, +0.125f,0.4375f, +0.132813f,0.4375f, +0.140625f,0.4375f, +0.148438f,0.4375f, +0.15625f,0.4375f, +0.164063f,0.4375f, +0.171875f,0.4375f, +0.179688f,0.4375f, +0.1875f,0.4375f, +0.195313f,0.4375f, +0.203125f,0.4375f, +0.210938f,0.4375f, +0.21875f,0.4375f, +0.226563f,0.4375f, +0.234375f,0.4375f, +0.242188f,0.4375f, +0.25f,0.4375f, +0.257813f,0.4375f, +0.265625f,0.4375f, +0.273438f,0.4375f, +0.28125f,0.4375f, +0.289063f,0.4375f, +0.296875f,0.4375f, +0.304688f,0.4375f, +0.3125f,0.4375f, +0.320313f,0.4375f, +0.328125f,0.4375f, +0.335938f,0.4375f, +0.34375f,0.4375f, +0.351563f,0.4375f, +0.359375f,0.4375f, +0.367188f,0.4375f, +0.375f,0.4375f, +0.382813f,0.4375f, +0.390625f,0.4375f, +0.398438f,0.4375f, +0.40625f,0.4375f, +0.414063f,0.4375f, +0.421875f,0.4375f, +0.429688f,0.4375f, +0.4375f,0.4375f, +0.445313f,0.4375f, +0.453125f,0.4375f, +0.460938f,0.4375f, +0.46875f,0.4375f, +0.476563f,0.4375f, +0.484375f,0.4375f, +0.492188f,0.4375f, +0.5f,0.4375f, +0.507813f,0.4375f, +0.0f,0.445313f, +0.0078125f,0.445313f, +0.015625f,0.445313f, +0.0234375f,0.445313f, +0.03125f,0.445313f, +0.0390625f,0.445313f, +0.046875f,0.445313f, +0.0546875f,0.445313f, +0.0625f,0.445313f, +0.0703125f,0.445313f, +0.078125f,0.445313f, +0.0859375f,0.445313f, +0.09375f,0.445313f, +0.101563f,0.445313f, +0.109375f,0.445313f, +0.117188f,0.445313f, +0.125f,0.445313f, +0.132813f,0.445313f, +0.140625f,0.445313f, +0.148438f,0.445313f, +0.15625f,0.445313f, +0.164063f,0.445313f, +0.171875f,0.445313f, +0.179688f,0.445313f, +0.1875f,0.445313f, +0.195313f,0.445313f, +0.203125f,0.445313f, +0.210938f,0.445313f, +0.21875f,0.445313f, +0.226563f,0.445313f, +0.234375f,0.445313f, +0.242188f,0.445313f, +0.25f,0.445313f, +0.257813f,0.445313f, +0.265625f,0.445313f, +0.273438f,0.445313f, +0.28125f,0.445313f, +0.289063f,0.445313f, +0.296875f,0.445313f, +0.304688f,0.445313f, +0.3125f,0.445313f, +0.320313f,0.445313f, +0.328125f,0.445313f, +0.335938f,0.445313f, +0.34375f,0.445313f, +0.351563f,0.445313f, +0.359375f,0.445313f, +0.367188f,0.445313f, +0.375f,0.445313f, +0.382813f,0.445313f, +0.390625f,0.445313f, +0.398438f,0.445313f, +0.40625f,0.445313f, +0.414063f,0.445313f, +0.421875f,0.445313f, +0.429688f,0.445313f, +0.4375f,0.445313f, +0.445313f,0.445313f, +0.453125f,0.445313f, +0.460938f,0.445313f, +0.46875f,0.445313f, +0.476563f,0.445313f, +0.484375f,0.445313f, +0.492188f,0.445313f, +0.5f,0.445313f, +0.507813f,0.445313f, +0.0f,0.453125f, +0.0078125f,0.453125f, +0.015625f,0.453125f, +0.0234375f,0.453125f, +0.03125f,0.453125f, +0.0390625f,0.453125f, +0.046875f,0.453125f, +0.0546875f,0.453125f, +0.0625f,0.453125f, +0.0703125f,0.453125f, +0.078125f,0.453125f, +0.0859375f,0.453125f, +0.09375f,0.453125f, +0.101563f,0.453125f, +0.109375f,0.453125f, +0.117188f,0.453125f, +0.125f,0.453125f, +0.132813f,0.453125f, +0.140625f,0.453125f, +0.148438f,0.453125f, +0.15625f,0.453125f, +0.164063f,0.453125f, +0.171875f,0.453125f, +0.179688f,0.453125f, +0.1875f,0.453125f, +0.195313f,0.453125f, +0.203125f,0.453125f, +0.210938f,0.453125f, +0.21875f,0.453125f, +0.226563f,0.453125f, +0.234375f,0.453125f, +0.242188f,0.453125f, +0.25f,0.453125f, +0.257813f,0.453125f, +0.265625f,0.453125f, +0.273438f,0.453125f, +0.28125f,0.453125f, +0.289063f,0.453125f, +0.296875f,0.453125f, +0.304688f,0.453125f, +0.3125f,0.453125f, +0.320313f,0.453125f, +0.328125f,0.453125f, +0.335938f,0.453125f, +0.34375f,0.453125f, +0.351563f,0.453125f, +0.359375f,0.453125f, +0.367188f,0.453125f, +0.375f,0.453125f, +0.382813f,0.453125f, +0.390625f,0.453125f, +0.398438f,0.453125f, +0.40625f,0.453125f, +0.414063f,0.453125f, +0.421875f,0.453125f, +0.429688f,0.453125f, +0.4375f,0.453125f, +0.445313f,0.453125f, +0.453125f,0.453125f, +0.460938f,0.453125f, +0.46875f,0.453125f, +0.476563f,0.453125f, +0.484375f,0.453125f, +0.492188f,0.453125f, +0.5f,0.453125f, +0.507813f,0.453125f, +0.0f,0.460938f, +0.0078125f,0.460938f, +0.015625f,0.460938f, +0.0234375f,0.460938f, +0.03125f,0.460938f, +0.0390625f,0.460938f, +0.046875f,0.460938f, +0.0546875f,0.460938f, +0.0625f,0.460938f, +0.0703125f,0.460938f, +0.078125f,0.460938f, +0.0859375f,0.460938f, +0.09375f,0.460938f, +0.101563f,0.460938f, +0.109375f,0.460938f, +0.117188f,0.460938f, +0.125f,0.460938f, +0.132813f,0.460938f, +0.140625f,0.460938f, +0.148438f,0.460938f, +0.15625f,0.460938f, +0.164063f,0.460938f, +0.171875f,0.460938f, +0.179688f,0.460938f, +0.1875f,0.460938f, +0.195313f,0.460938f, +0.203125f,0.460938f, +0.210938f,0.460938f, +0.21875f,0.460938f, +0.226563f,0.460938f, +0.234375f,0.460938f, +0.242188f,0.460938f, +0.25f,0.460938f, +0.257813f,0.460938f, +0.265625f,0.460938f, +0.273438f,0.460938f, +0.28125f,0.460938f, +0.289063f,0.460938f, +0.296875f,0.460938f, +0.304688f,0.460938f, +0.3125f,0.460938f, +0.320313f,0.460938f, +0.328125f,0.460938f, +0.335938f,0.460938f, +0.34375f,0.460938f, +0.351563f,0.460938f, +0.359375f,0.460938f, +0.367188f,0.460938f, +0.375f,0.460938f, +0.382813f,0.460938f, +0.390625f,0.460938f, +0.398438f,0.460938f, +0.40625f,0.460938f, +0.414063f,0.460938f, +0.421875f,0.460938f, +0.429688f,0.460938f, +0.4375f,0.460938f, +0.445313f,0.460938f, +0.453125f,0.460938f, +0.460938f,0.460938f, +0.46875f,0.460938f, +0.476563f,0.460938f, +0.484375f,0.460938f, +0.492188f,0.460938f, +0.5f,0.460938f, +0.507813f,0.460938f, +0.0f,0.46875f, +0.0078125f,0.46875f, +0.015625f,0.46875f, +0.0234375f,0.46875f, +0.03125f,0.46875f, +0.0390625f,0.46875f, +0.046875f,0.46875f, +0.0546875f,0.46875f, +0.0625f,0.46875f, +0.0703125f,0.46875f, +0.078125f,0.46875f, +0.0859375f,0.46875f, +0.09375f,0.46875f, +0.101563f,0.46875f, +0.109375f,0.46875f, +0.117188f,0.46875f, +0.125f,0.46875f, +0.132813f,0.46875f, +0.140625f,0.46875f, +0.148438f,0.46875f, +0.15625f,0.46875f, +0.164063f,0.46875f, +0.171875f,0.46875f, +0.179688f,0.46875f, +0.1875f,0.46875f, +0.195313f,0.46875f, +0.203125f,0.46875f, +0.210938f,0.46875f, +0.21875f,0.46875f, +0.226563f,0.46875f, +0.234375f,0.46875f, +0.242188f,0.46875f, +0.25f,0.46875f, +0.257813f,0.46875f, +0.265625f,0.46875f, +0.273438f,0.46875f, +0.28125f,0.46875f, +0.289063f,0.46875f, +0.296875f,0.46875f, +0.304688f,0.46875f, +0.3125f,0.46875f, +0.320313f,0.46875f, +0.328125f,0.46875f, +0.335938f,0.46875f, +0.34375f,0.46875f, +0.351563f,0.46875f, +0.359375f,0.46875f, +0.367188f,0.46875f, +0.375f,0.46875f, +0.382813f,0.46875f, +0.390625f,0.46875f, +0.398438f,0.46875f, +0.40625f,0.46875f, +0.414063f,0.46875f, +0.421875f,0.46875f, +0.429688f,0.46875f, +0.4375f,0.46875f, +0.445313f,0.46875f, +0.453125f,0.46875f, +0.460938f,0.46875f, +0.46875f,0.46875f, +0.476563f,0.46875f, +0.484375f,0.46875f, +0.492188f,0.46875f, +0.5f,0.46875f, +0.507813f,0.46875f, +0.0f,0.476563f, +0.0078125f,0.476563f, +0.015625f,0.476563f, +0.0234375f,0.476563f, +0.03125f,0.476563f, +0.0390625f,0.476563f, +0.046875f,0.476563f, +0.0546875f,0.476563f, +0.0625f,0.476563f, +0.0703125f,0.476563f, +0.078125f,0.476563f, +0.0859375f,0.476563f, +0.09375f,0.476563f, +0.101563f,0.476563f, +0.109375f,0.476563f, +0.117188f,0.476563f, +0.125f,0.476563f, +0.132813f,0.476563f, +0.140625f,0.476563f, +0.148438f,0.476563f, +0.15625f,0.476563f, +0.164063f,0.476563f, +0.171875f,0.476563f, +0.179688f,0.476563f, +0.1875f,0.476563f, +0.195313f,0.476563f, +0.203125f,0.476563f, +0.210938f,0.476563f, +0.21875f,0.476563f, +0.226563f,0.476563f, +0.234375f,0.476563f, +0.242188f,0.476563f, +0.25f,0.476563f, +0.257813f,0.476563f, +0.265625f,0.476563f, +0.273438f,0.476563f, +0.28125f,0.476563f, +0.289063f,0.476563f, +0.296875f,0.476563f, +0.304688f,0.476563f, +0.3125f,0.476563f, +0.320313f,0.476563f, +0.328125f,0.476563f, +0.335938f,0.476563f, +0.34375f,0.476563f, +0.351563f,0.476563f, +0.359375f,0.476563f, +0.367188f,0.476563f, +0.375f,0.476563f, +0.382813f,0.476563f, +0.390625f,0.476563f, +0.398438f,0.476563f, +0.40625f,0.476563f, +0.414063f,0.476563f, +0.421875f,0.476563f, +0.429688f,0.476563f, +0.4375f,0.476563f, +0.445313f,0.476563f, +0.453125f,0.476563f, +0.460938f,0.476563f, +0.46875f,0.476563f, +0.476563f,0.476563f, +0.484375f,0.476563f, +0.492188f,0.476563f, +0.5f,0.476563f, +0.507813f,0.476563f, +0.0f,0.484375f, +0.0078125f,0.484375f, +0.015625f,0.484375f, +0.0234375f,0.484375f, +0.03125f,0.484375f, +0.0390625f,0.484375f, +0.046875f,0.484375f, +0.0546875f,0.484375f, +0.0625f,0.484375f, +0.0703125f,0.484375f, +0.078125f,0.484375f, +0.0859375f,0.484375f, +0.09375f,0.484375f, +0.101563f,0.484375f, +0.109375f,0.484375f, +0.117188f,0.484375f, +0.125f,0.484375f, +0.132813f,0.484375f, +0.140625f,0.484375f, +0.148438f,0.484375f, +0.15625f,0.484375f, +0.164063f,0.484375f, +0.171875f,0.484375f, +0.179688f,0.484375f, +0.1875f,0.484375f, +0.195313f,0.484375f, +0.203125f,0.484375f, +0.210938f,0.484375f, +0.21875f,0.484375f, +0.226563f,0.484375f, +0.234375f,0.484375f, +0.242188f,0.484375f, +0.25f,0.484375f, +0.257813f,0.484375f, +0.265625f,0.484375f, +0.273438f,0.484375f, +0.28125f,0.484375f, +0.289063f,0.484375f, +0.296875f,0.484375f, +0.304688f,0.484375f, +0.3125f,0.484375f, +0.320313f,0.484375f, +0.328125f,0.484375f, +0.335938f,0.484375f, +0.34375f,0.484375f, +0.351563f,0.484375f, +0.359375f,0.484375f, +0.367188f,0.484375f, +0.375f,0.484375f, +0.382813f,0.484375f, +0.390625f,0.484375f, +0.398438f,0.484375f, +0.40625f,0.484375f, +0.414063f,0.484375f, +0.421875f,0.484375f, +0.429688f,0.484375f, +0.4375f,0.484375f, +0.445313f,0.484375f, +0.453125f,0.484375f, +0.460938f,0.484375f, +0.46875f,0.484375f, +0.476563f,0.484375f, +0.484375f,0.484375f, +0.492188f,0.484375f, +0.5f,0.484375f, +0.507813f,0.484375f, +0.0f,0.492188f, +0.0078125f,0.492188f, +0.015625f,0.492188f, +0.0234375f,0.492188f, +0.03125f,0.492188f, +0.0390625f,0.492188f, +0.046875f,0.492188f, +0.0546875f,0.492188f, +0.0625f,0.492188f, +0.0703125f,0.492188f, +0.078125f,0.492188f, +0.0859375f,0.492188f, +0.09375f,0.492188f, +0.101563f,0.492188f, +0.109375f,0.492188f, +0.117188f,0.492188f, +0.125f,0.492188f, +0.132813f,0.492188f, +0.140625f,0.492188f, +0.148438f,0.492188f, +0.15625f,0.492188f, +0.164063f,0.492188f, +0.171875f,0.492188f, +0.179688f,0.492188f, +0.1875f,0.492188f, +0.195313f,0.492188f, +0.203125f,0.492188f, +0.210938f,0.492188f, +0.21875f,0.492188f, +0.226563f,0.492188f, +0.234375f,0.492188f, +0.242188f,0.492188f, +0.25f,0.492188f, +0.257813f,0.492188f, +0.265625f,0.492188f, +0.273438f,0.492188f, +0.28125f,0.492188f, +0.289063f,0.492188f, +0.296875f,0.492188f, +0.304688f,0.492188f, +0.3125f,0.492188f, +0.320313f,0.492188f, +0.328125f,0.492188f, +0.335938f,0.492188f, +0.34375f,0.492188f, +0.351563f,0.492188f, +0.359375f,0.492188f, +0.367188f,0.492188f, +0.375f,0.492188f, +0.382813f,0.492188f, +0.390625f,0.492188f, +0.398438f,0.492188f, +0.40625f,0.492188f, +0.414063f,0.492188f, +0.421875f,0.492188f, +0.429688f,0.492188f, +0.4375f,0.492188f, +0.445313f,0.492188f, +0.453125f,0.492188f, +0.460938f,0.492188f, +0.46875f,0.492188f, +0.476563f,0.492188f, +0.484375f,0.492188f, +0.492188f,0.492188f, +0.5f,0.492188f, +0.507813f,0.492188f, +}; + +unsigned short Landscape02Idx[] = { +0,1,2, +3,2,1, +2,3,4, +5,4,3, +4,5,6, +7,6,5, +6,7,8, +9,8,7, +8,9,10, +11,10,9, +10,11,12, +13,12,11, +12,13,14, +15,14,13, +14,15,16, +17,16,15, +16,17,18, +19,18,17, +18,19,20, +21,20,19, +20,21,22, +23,22,21, +22,23,24, +25,24,23, +24,25,26, +27,26,25, +26,27,28, +29,28,27, +28,29,30, +31,30,29, +30,31,32, +33,32,31, +32,33,34, +35,34,33, +34,35,36, +37,36,35, +36,37,38, +39,38,37, +38,39,40, +41,40,39, +40,41,42, +43,42,41, +42,43,44, +45,44,43, +44,45,46, +47,46,45, +46,47,48, +49,48,47, +48,49,50, +51,50,49, +50,51,52, +53,52,51, +52,53,54, +55,54,53, +54,55,56, +57,56,55, +56,57,58, +59,58,57, +58,59,60, +61,60,59, +60,61,62, +63,62,61, +62,63,64, +65,64,63, +64,65,66, +67,66,65, +66,67,68, +69,68,67, +68,69,70, +71,70,69, +70,71,72, +73,72,71, +72,73,74, +75,74,73, +74,75,76, +77,76,75, +76,77,78, +79,78,77, +78,79,80, +81,80,79, +80,81,82, +83,82,81, +82,83,84, +85,84,83, +84,85,86, +87,86,85, +86,87,88, +89,88,87, +88,89,90, +91,90,89, +90,91,92, +93,92,91, +92,93,94, +95,94,93, +94,95,96, +97,96,95, +96,97,98, +99,98,97, +98,99,100, +101,100,99, +100,101,102, +103,102,101, +102,103,104, +105,104,103, +104,105,106, +107,106,105, +106,107,108, +109,108,107, +108,109,110, +111,110,109, +110,111,112, +113,112,111, +112,113,114, +115,114,113, +114,115,116, +117,116,115, +116,117,118, +119,118,117, +118,119,120, +121,120,119, +120,121,122, +123,122,121, +122,123,124, +125,124,123, +124,125,126, +127,126,125, +126,127,128, +129,128,127, +128,129,130, +131,130,129, +132,0,133, +2,133,0, +133,2,134, +4,134,2, +134,4,135, +6,135,4, +135,6,136, +8,136,6, +136,8,137, +10,137,8, +137,10,138, +12,138,10, +138,12,139, +14,139,12, +139,14,140, +16,140,14, +140,16,141, +18,141,16, +141,18,142, +20,142,18, +142,20,143, +22,143,20, +143,22,144, +24,144,22, +144,24,145, +26,145,24, +145,26,146, +28,146,26, +146,28,147, +30,147,28, +147,30,148, +32,148,30, +148,32,149, +34,149,32, +149,34,150, +36,150,34, +150,36,151, +38,151,36, +151,38,152, +40,152,38, +152,40,153, +42,153,40, +153,42,154, +44,154,42, +154,44,155, +46,155,44, +155,46,156, +48,156,46, +156,48,157, +50,157,48, +157,50,158, +52,158,50, +158,52,159, +54,159,52, +159,54,160, +56,160,54, +160,56,161, +58,161,56, +161,58,162, +60,162,58, +162,60,163, +62,163,60, +163,62,164, +64,164,62, +164,64,165, +66,165,64, +165,66,166, +68,166,66, +166,68,167, +70,167,68, +167,70,168, +72,168,70, +168,72,169, +74,169,72, +169,74,170, +76,170,74, +170,76,171, +78,171,76, +171,78,172, +80,172,78, +172,80,173, +82,173,80, +173,82,174, +84,174,82, +174,84,175, +86,175,84, +175,86,176, +88,176,86, +176,88,177, +90,177,88, +177,90,178, +92,178,90, +178,92,179, +94,179,92, +179,94,180, +96,180,94, +180,96,181, +98,181,96, +181,98,182, +100,182,98, +182,100,183, +102,183,100, +183,102,184, +104,184,102, +184,104,185, +106,185,104, +185,106,186, +108,186,106, +186,108,187, +110,187,108, +187,110,188, +112,188,110, +188,112,189, +114,189,112, +189,114,190, +116,190,114, +190,116,191, +118,191,116, +191,118,192, +120,192,118, +192,120,193, +122,193,120, +193,122,194, +124,194,122, +194,124,195, +126,195,124, +195,126,196, +128,196,126, +196,128,197, +130,197,128, +198,132,199, +133,199,132, +199,133,200, +134,200,133, +200,134,201, +135,201,134, +201,135,202, +136,202,135, +202,136,203, +137,203,136, +203,137,204, +138,204,137, +204,138,205, +139,205,138, +205,139,206, +140,206,139, +206,140,207, +141,207,140, +207,141,208, +142,208,141, +208,142,209, +143,209,142, +209,143,210, +144,210,143, +210,144,211, +145,211,144, +211,145,212, +146,212,145, +212,146,213, +147,213,146, +213,147,214, +148,214,147, +214,148,215, +149,215,148, +215,149,216, +150,216,149, +216,150,217, +151,217,150, +217,151,218, +152,218,151, +218,152,219, +153,219,152, +219,153,220, +154,220,153, +220,154,221, +155,221,154, +221,155,222, +156,222,155, +222,156,223, +157,223,156, +223,157,224, +158,224,157, +224,158,225, +159,225,158, +225,159,226, +160,226,159, +226,160,227, +161,227,160, +227,161,228, +162,228,161, +228,162,229, +163,229,162, +229,163,230, +164,230,163, +230,164,231, +165,231,164, +231,165,232, +166,232,165, +232,166,233, +167,233,166, +233,167,234, +168,234,167, +234,168,235, +169,235,168, +235,169,236, +170,236,169, +236,170,237, +171,237,170, +237,171,238, +172,238,171, +238,172,239, +173,239,172, +239,173,240, +174,240,173, +240,174,241, +175,241,174, +241,175,242, +176,242,175, +242,176,243, +177,243,176, +243,177,244, +178,244,177, +244,178,245, +179,245,178, +245,179,246, +180,246,179, +246,180,247, +181,247,180, +247,181,248, +182,248,181, +248,182,249, +183,249,182, +249,183,250, +184,250,183, +250,184,251, +185,251,184, +251,185,252, +186,252,185, +252,186,253, +187,253,186, +253,187,254, +188,254,187, +254,188,255, +189,255,188, +255,189,256, +190,256,189, +256,190,257, +191,257,190, +257,191,258, +192,258,191, +258,192,259, +193,259,192, +259,193,260, +194,260,193, +260,194,261, +195,261,194, +261,195,262, +196,262,195, +262,196,263, +197,263,196, +264,198,265, +199,265,198, +265,199,266, +200,266,199, +266,200,267, +201,267,200, +267,201,268, +202,268,201, +268,202,269, +203,269,202, +269,203,270, +204,270,203, +270,204,271, +205,271,204, +271,205,272, +206,272,205, +272,206,273, +207,273,206, +273,207,274, +208,274,207, +274,208,275, +209,275,208, +275,209,276, +210,276,209, +276,210,277, +211,277,210, +277,211,278, +212,278,211, +278,212,279, +213,279,212, +279,213,280, +214,280,213, +280,214,281, +215,281,214, +281,215,282, +216,282,215, +282,216,283, +217,283,216, +283,217,284, +218,284,217, +284,218,285, +219,285,218, +285,219,286, +220,286,219, +286,220,287, +221,287,220, +287,221,288, +222,288,221, +288,222,289, +223,289,222, +289,223,290, +224,290,223, +290,224,291, +225,291,224, +291,225,292, +226,292,225, +292,226,293, +227,293,226, +293,227,294, +228,294,227, +294,228,295, +229,295,228, +295,229,296, +230,296,229, +296,230,297, +231,297,230, +297,231,298, +232,298,231, +298,232,299, +233,299,232, +299,233,300, +234,300,233, +300,234,301, +235,301,234, +301,235,302, +236,302,235, +302,236,303, +237,303,236, +303,237,304, +238,304,237, +304,238,305, +239,305,238, +305,239,306, +240,306,239, +306,240,307, +241,307,240, +307,241,308, +242,308,241, +308,242,309, +243,309,242, +309,243,310, +244,310,243, +310,244,311, +245,311,244, +311,245,312, +246,312,245, +312,246,313, +247,313,246, +313,247,314, +248,314,247, +314,248,315, +249,315,248, +315,249,316, +250,316,249, +316,250,317, +251,317,250, +317,251,318, +252,318,251, +318,252,319, +253,319,252, +319,253,320, +254,320,253, +320,254,321, +255,321,254, +321,255,322, +256,322,255, +322,256,323, +257,323,256, +323,257,324, +258,324,257, +324,258,325, +259,325,258, +325,259,326, +260,326,259, +326,260,327, +261,327,260, +327,261,328, +262,328,261, +328,262,329, +263,329,262, +330,264,331, +265,331,264, +331,265,332, +266,332,265, +332,266,333, +267,333,266, +333,267,334, +268,334,267, +334,268,335, +269,335,268, +335,269,336, +270,336,269, +336,270,337, +271,337,270, +337,271,338, +272,338,271, +338,272,339, +273,339,272, +339,273,340, +274,340,273, +340,274,341, +275,341,274, +341,275,342, +276,342,275, +342,276,343, +277,343,276, +343,277,344, +278,344,277, +344,278,345, +279,345,278, +345,279,346, +280,346,279, +346,280,347, +281,347,280, +347,281,348, +282,348,281, +348,282,349, +283,349,282, +349,283,350, +284,350,283, +350,284,351, +285,351,284, +351,285,352, +286,352,285, +352,286,353, +287,353,286, +353,287,354, +288,354,287, +354,288,355, +289,355,288, +355,289,356, +290,356,289, +356,290,357, +291,357,290, +357,291,358, +292,358,291, +358,292,359, +293,359,292, +359,293,360, +294,360,293, +360,294,361, +295,361,294, +361,295,362, +296,362,295, +362,296,363, +297,363,296, +363,297,364, +298,364,297, +364,298,365, +299,365,298, +365,299,366, +300,366,299, +366,300,367, +301,367,300, +367,301,368, +302,368,301, +368,302,369, +303,369,302, +369,303,370, +304,370,303, +370,304,371, +305,371,304, +371,305,372, +306,372,305, +372,306,373, +307,373,306, +373,307,374, +308,374,307, +374,308,375, +309,375,308, +375,309,376, +310,376,309, +376,310,377, +311,377,310, +377,311,378, +312,378,311, +378,312,379, +313,379,312, +379,313,380, +314,380,313, +380,314,381, +315,381,314, +381,315,382, +316,382,315, +382,316,383, +317,383,316, +383,317,384, +318,384,317, +384,318,385, +319,385,318, +385,319,386, +320,386,319, +386,320,387, +321,387,320, +387,321,388, +322,388,321, +388,322,389, +323,389,322, +389,323,390, +324,390,323, +390,324,391, +325,391,324, +391,325,392, +326,392,325, +392,326,393, +327,393,326, +393,327,394, +328,394,327, +394,328,395, +329,395,328, +396,330,397, +331,397,330, +397,331,398, +332,398,331, +398,332,399, +333,399,332, +399,333,400, +334,400,333, +400,334,401, +335,401,334, +401,335,402, +336,402,335, +402,336,403, +337,403,336, +403,337,404, +338,404,337, +404,338,405, +339,405,338, +405,339,406, +340,406,339, +406,340,407, +341,407,340, +407,341,408, +342,408,341, +408,342,409, +343,409,342, +409,343,410, +344,410,343, +410,344,411, +345,411,344, +411,345,412, +346,412,345, +412,346,413, +347,413,346, +413,347,414, +348,414,347, +414,348,415, +349,415,348, +415,349,416, +350,416,349, +416,350,417, +351,417,350, +417,351,418, +352,418,351, +418,352,419, +353,419,352, +419,353,420, +354,420,353, +420,354,421, +355,421,354, +421,355,422, +356,422,355, +422,356,423, +357,423,356, +423,357,424, +358,424,357, +424,358,425, +359,425,358, +425,359,426, +360,426,359, +426,360,427, +361,427,360, +427,361,428, +362,428,361, +428,362,429, +363,429,362, +429,363,430, +364,430,363, +430,364,431, +365,431,364, +431,365,432, +366,432,365, +432,366,433, +367,433,366, +433,367,434, +368,434,367, +434,368,435, +369,435,368, +435,369,436, +370,436,369, +436,370,437, +371,437,370, +437,371,438, +372,438,371, +438,372,439, +373,439,372, +439,373,440, +374,440,373, +440,374,441, +375,441,374, +441,375,442, +376,442,375, +442,376,443, +377,443,376, +443,377,444, +378,444,377, +444,378,445, +379,445,378, +445,379,446, +380,446,379, +446,380,447, +381,447,380, +447,381,448, +382,448,381, +448,382,449, +383,449,382, +449,383,450, +384,450,383, +450,384,451, +385,451,384, +451,385,452, +386,452,385, +452,386,453, +387,453,386, +453,387,454, +388,454,387, +454,388,455, +389,455,388, +455,389,456, +390,456,389, +456,390,457, +391,457,390, +457,391,458, +392,458,391, +458,392,459, +393,459,392, +459,393,460, +394,460,393, +460,394,461, +395,461,394, +462,396,463, +397,463,396, +463,397,464, +398,464,397, +464,398,465, +399,465,398, +465,399,466, +400,466,399, +466,400,467, +401,467,400, +467,401,468, +402,468,401, +468,402,469, +403,469,402, +469,403,470, +404,470,403, +470,404,471, +405,471,404, +471,405,472, +406,472,405, +472,406,473, +407,473,406, +473,407,474, +408,474,407, +474,408,475, +409,475,408, +475,409,476, +410,476,409, +476,410,477, +411,477,410, +477,411,478, +412,478,411, +478,412,479, +413,479,412, +479,413,480, +414,480,413, +480,414,481, +415,481,414, +481,415,482, +416,482,415, +482,416,483, +417,483,416, +483,417,484, +418,484,417, +484,418,485, +419,485,418, +485,419,486, +420,486,419, +486,420,487, +421,487,420, +487,421,488, +422,488,421, +488,422,489, +423,489,422, +489,423,490, +424,490,423, +490,424,491, +425,491,424, +491,425,492, +426,492,425, +492,426,493, +427,493,426, +493,427,494, +428,494,427, +494,428,495, +429,495,428, +495,429,496, +430,496,429, +496,430,497, +431,497,430, +497,431,498, +432,498,431, +498,432,499, +433,499,432, +499,433,500, +434,500,433, +500,434,501, +435,501,434, +501,435,502, +436,502,435, +502,436,503, +437,503,436, +503,437,504, +438,504,437, +504,438,505, +439,505,438, +505,439,506, +440,506,439, +506,440,507, +441,507,440, +507,441,508, +442,508,441, +508,442,509, +443,509,442, +509,443,510, +444,510,443, +510,444,511, +445,511,444, +511,445,512, +446,512,445, +512,446,513, +447,513,446, +513,447,514, +448,514,447, +514,448,515, +449,515,448, +515,449,516, +450,516,449, +516,450,517, +451,517,450, +517,451,518, +452,518,451, +518,452,519, +453,519,452, +519,453,520, +454,520,453, +520,454,521, +455,521,454, +521,455,522, +456,522,455, +522,456,523, +457,523,456, +523,457,524, +458,524,457, +524,458,525, +459,525,458, +525,459,526, +460,526,459, +526,460,527, +461,527,460, +528,462,529, +463,529,462, +529,463,530, +464,530,463, +530,464,531, +465,531,464, +531,465,532, +466,532,465, +532,466,533, +467,533,466, +533,467,534, +468,534,467, +534,468,535, +469,535,468, +535,469,536, +470,536,469, +536,470,537, +471,537,470, +537,471,538, +472,538,471, +538,472,539, +473,539,472, +539,473,540, +474,540,473, +540,474,541, +475,541,474, +541,475,542, +476,542,475, +542,476,543, +477,543,476, +543,477,544, +478,544,477, +544,478,545, +479,545,478, +545,479,546, +480,546,479, +546,480,547, +481,547,480, +547,481,548, +482,548,481, +548,482,549, +483,549,482, +549,483,550, +484,550,483, +550,484,551, +485,551,484, +551,485,552, +486,552,485, +552,486,553, +487,553,486, +553,487,554, +488,554,487, +554,488,555, +489,555,488, +555,489,556, +490,556,489, +556,490,557, +491,557,490, +557,491,558, +492,558,491, +558,492,559, +493,559,492, +559,493,560, +494,560,493, +560,494,561, +495,561,494, +561,495,562, +496,562,495, +562,496,563, +497,563,496, +563,497,564, +498,564,497, +564,498,565, +499,565,498, +565,499,566, +500,566,499, +566,500,567, +501,567,500, +567,501,568, +502,568,501, +568,502,569, +503,569,502, +569,503,570, +504,570,503, +570,504,571, +505,571,504, +571,505,572, +506,572,505, +572,506,573, +507,573,506, +573,507,574, +508,574,507, +574,508,575, +509,575,508, +575,509,576, +510,576,509, +576,510,577, +511,577,510, +577,511,578, +512,578,511, +578,512,579, +513,579,512, +579,513,580, +514,580,513, +580,514,581, +515,581,514, +581,515,582, +516,582,515, +582,516,583, +517,583,516, +583,517,584, +518,584,517, +584,518,585, +519,585,518, +585,519,586, +520,586,519, +586,520,587, +521,587,520, +587,521,588, +522,588,521, +588,522,589, +523,589,522, +589,523,590, +524,590,523, +590,524,591, +525,591,524, +591,525,592, +526,592,525, +592,526,593, +527,593,526, +594,528,595, +529,595,528, +595,529,596, +530,596,529, +596,530,597, +531,597,530, +597,531,598, +532,598,531, +598,532,599, +533,599,532, +599,533,600, +534,600,533, +600,534,601, +535,601,534, +601,535,602, +536,602,535, +602,536,603, +537,603,536, +603,537,604, +538,604,537, +604,538,605, +539,605,538, +605,539,606, +540,606,539, +606,540,607, +541,607,540, +607,541,608, +542,608,541, +608,542,609, +543,609,542, +609,543,610, +544,610,543, +610,544,611, +545,611,544, +611,545,612, +546,612,545, +612,546,613, +547,613,546, +613,547,614, +548,614,547, +614,548,615, +549,615,548, +615,549,616, +550,616,549, +616,550,617, +551,617,550, +617,551,618, +552,618,551, +618,552,619, +553,619,552, +619,553,620, +554,620,553, +620,554,621, +555,621,554, +621,555,622, +556,622,555, +622,556,623, +557,623,556, +623,557,624, +558,624,557, +624,558,625, +559,625,558, +625,559,626, +560,626,559, +626,560,627, +561,627,560, +627,561,628, +562,628,561, +628,562,629, +563,629,562, +629,563,630, +564,630,563, +630,564,631, +565,631,564, +631,565,632, +566,632,565, +632,566,633, +567,633,566, +633,567,634, +568,634,567, +634,568,635, +569,635,568, +635,569,636, +570,636,569, +636,570,637, +571,637,570, +637,571,638, +572,638,571, +638,572,639, +573,639,572, +639,573,640, +574,640,573, +640,574,641, +575,641,574, +641,575,642, +576,642,575, +642,576,643, +577,643,576, +643,577,644, +578,644,577, +644,578,645, +579,645,578, +645,579,646, +580,646,579, +646,580,647, +581,647,580, +647,581,648, +582,648,581, +648,582,649, +583,649,582, +649,583,650, +584,650,583, +650,584,651, +585,651,584, +651,585,652, +586,652,585, +652,586,653, +587,653,586, +653,587,654, +588,654,587, +654,588,655, +589,655,588, +655,589,656, +590,656,589, +656,590,657, +591,657,590, +657,591,658, +592,658,591, +658,592,659, +593,659,592, +660,594,661, +595,661,594, +661,595,662, +596,662,595, +662,596,663, +597,663,596, +663,597,664, +598,664,597, +664,598,665, +599,665,598, +665,599,666, +600,666,599, +666,600,667, +601,667,600, +667,601,668, +602,668,601, +668,602,669, +603,669,602, +669,603,670, +604,670,603, +670,604,671, +605,671,604, +671,605,672, +606,672,605, +672,606,673, +607,673,606, +673,607,674, +608,674,607, +674,608,675, +609,675,608, +675,609,676, +610,676,609, +676,610,677, +611,677,610, +677,611,678, +612,678,611, +678,612,679, +613,679,612, +679,613,680, +614,680,613, +680,614,681, +615,681,614, +681,615,682, +616,682,615, +682,616,683, +617,683,616, +683,617,684, +618,684,617, +684,618,685, +619,685,618, +685,619,686, +620,686,619, +686,620,687, +621,687,620, +687,621,688, +622,688,621, +688,622,689, +623,689,622, +689,623,690, +624,690,623, +690,624,691, +625,691,624, +691,625,692, +626,692,625, +692,626,693, +627,693,626, +693,627,694, +628,694,627, +694,628,695, +629,695,628, +695,629,696, +630,696,629, +696,630,697, +631,697,630, +697,631,698, +632,698,631, +698,632,699, +633,699,632, +699,633,700, +634,700,633, +700,634,701, +635,701,634, +701,635,702, +636,702,635, +702,636,703, +637,703,636, +703,637,704, +638,704,637, +704,638,705, +639,705,638, +705,639,706, +640,706,639, +706,640,707, +641,707,640, +707,641,708, +642,708,641, +708,642,709, +643,709,642, +709,643,710, +644,710,643, +710,644,711, +645,711,644, +711,645,712, +646,712,645, +712,646,713, +647,713,646, +713,647,714, +648,714,647, +714,648,715, +649,715,648, +715,649,716, +650,716,649, +716,650,717, +651,717,650, +717,651,718, +652,718,651, +718,652,719, +653,719,652, +719,653,720, +654,720,653, +720,654,721, +655,721,654, +721,655,722, +656,722,655, +722,656,723, +657,723,656, +723,657,724, +658,724,657, +724,658,725, +659,725,658, +726,660,727, +661,727,660, +727,661,728, +662,728,661, +728,662,729, +663,729,662, +729,663,730, +664,730,663, +730,664,731, +665,731,664, +731,665,732, +666,732,665, +732,666,733, +667,733,666, +733,667,734, +668,734,667, +734,668,735, +669,735,668, +735,669,736, +670,736,669, +736,670,737, +671,737,670, +737,671,738, +672,738,671, +738,672,739, +673,739,672, +739,673,740, +674,740,673, +740,674,741, +675,741,674, +741,675,742, +676,742,675, +742,676,743, +677,743,676, +743,677,744, +678,744,677, +744,678,745, +679,745,678, +745,679,746, +680,746,679, +746,680,747, +681,747,680, +747,681,748, +682,748,681, +748,682,749, +683,749,682, +749,683,750, +684,750,683, +750,684,751, +685,751,684, +751,685,752, +686,752,685, +752,686,753, +687,753,686, +753,687,754, +688,754,687, +754,688,755, +689,755,688, +755,689,756, +690,756,689, +756,690,757, +691,757,690, +757,691,758, +692,758,691, +758,692,759, +693,759,692, +759,693,760, +694,760,693, +760,694,761, +695,761,694, +761,695,762, +696,762,695, +762,696,763, +697,763,696, +763,697,764, +698,764,697, +764,698,765, +699,765,698, +765,699,766, +700,766,699, +766,700,767, +701,767,700, +767,701,768, +702,768,701, +768,702,769, +703,769,702, +769,703,770, +704,770,703, +770,704,771, +705,771,704, +771,705,772, +706,772,705, +772,706,773, +707,773,706, +773,707,774, +708,774,707, +774,708,775, +709,775,708, +775,709,776, +710,776,709, +776,710,777, +711,777,710, +777,711,778, +712,778,711, +778,712,779, +713,779,712, +779,713,780, +714,780,713, +780,714,781, +715,781,714, +781,715,782, +716,782,715, +782,716,783, +717,783,716, +783,717,784, +718,784,717, +784,718,785, +719,785,718, +785,719,786, +720,786,719, +786,720,787, +721,787,720, +787,721,788, +722,788,721, +788,722,789, +723,789,722, +789,723,790, +724,790,723, +790,724,791, +725,791,724, +792,726,793, +727,793,726, +793,727,794, +728,794,727, +794,728,795, +729,795,728, +795,729,796, +730,796,729, +796,730,797, +731,797,730, +797,731,798, +732,798,731, +798,732,799, +733,799,732, +799,733,800, +734,800,733, +800,734,801, +735,801,734, +801,735,802, +736,802,735, +802,736,803, +737,803,736, +803,737,804, +738,804,737, +804,738,805, +739,805,738, +805,739,806, +740,806,739, +806,740,807, +741,807,740, +807,741,808, +742,808,741, +808,742,809, +743,809,742, +809,743,810, +744,810,743, +810,744,811, +745,811,744, +811,745,812, +746,812,745, +812,746,813, +747,813,746, +813,747,814, +748,814,747, +814,748,815, +749,815,748, +815,749,816, +750,816,749, +816,750,817, +751,817,750, +817,751,818, +752,818,751, +818,752,819, +753,819,752, +819,753,820, +754,820,753, +820,754,821, +755,821,754, +821,755,822, +756,822,755, +822,756,823, +757,823,756, +823,757,824, +758,824,757, +824,758,825, +759,825,758, +825,759,826, +760,826,759, +826,760,827, +761,827,760, +827,761,828, +762,828,761, +828,762,829, +763,829,762, +829,763,830, +764,830,763, +830,764,831, +765,831,764, +831,765,832, +766,832,765, +832,766,833, +767,833,766, +833,767,834, +768,834,767, +834,768,835, +769,835,768, +835,769,836, +770,836,769, +836,770,837, +771,837,770, +837,771,838, +772,838,771, +838,772,839, +773,839,772, +839,773,840, +774,840,773, +840,774,841, +775,841,774, +841,775,842, +776,842,775, +842,776,843, +777,843,776, +843,777,844, +778,844,777, +844,778,845, +779,845,778, +845,779,846, +780,846,779, +846,780,847, +781,847,780, +847,781,848, +782,848,781, +848,782,849, +783,849,782, +849,783,850, +784,850,783, +850,784,851, +785,851,784, +851,785,852, +786,852,785, +852,786,853, +787,853,786, +853,787,854, +788,854,787, +854,788,855, +789,855,788, +855,789,856, +790,856,789, +856,790,857, +791,857,790, +858,792,859, +793,859,792, +859,793,860, +794,860,793, +860,794,861, +795,861,794, +861,795,862, +796,862,795, +862,796,863, +797,863,796, +863,797,864, +798,864,797, +864,798,865, +799,865,798, +865,799,866, +800,866,799, +866,800,867, +801,867,800, +867,801,868, +802,868,801, +868,802,869, +803,869,802, +869,803,870, +804,870,803, +870,804,871, +805,871,804, +871,805,872, +806,872,805, +872,806,873, +807,873,806, +873,807,874, +808,874,807, +874,808,875, +809,875,808, +875,809,876, +810,876,809, +876,810,877, +811,877,810, +877,811,878, +812,878,811, +878,812,879, +813,879,812, +879,813,880, +814,880,813, +880,814,881, +815,881,814, +881,815,882, +816,882,815, +882,816,883, +817,883,816, +883,817,884, +818,884,817, +884,818,885, +819,885,818, +885,819,886, +820,886,819, +886,820,887, +821,887,820, +887,821,888, +822,888,821, +888,822,889, +823,889,822, +889,823,890, +824,890,823, +890,824,891, +825,891,824, +891,825,892, +826,892,825, +892,826,893, +827,893,826, +893,827,894, +828,894,827, +894,828,895, +829,895,828, +895,829,896, +830,896,829, +896,830,897, +831,897,830, +897,831,898, +832,898,831, +898,832,899, +833,899,832, +899,833,900, +834,900,833, +900,834,901, +835,901,834, +901,835,902, +836,902,835, +902,836,903, +837,903,836, +903,837,904, +838,904,837, +904,838,905, +839,905,838, +905,839,906, +840,906,839, +906,840,907, +841,907,840, +907,841,908, +842,908,841, +908,842,909, +843,909,842, +909,843,910, +844,910,843, +910,844,911, +845,911,844, +911,845,912, +846,912,845, +912,846,913, +847,913,846, +913,847,914, +848,914,847, +914,848,915, +849,915,848, +915,849,916, +850,916,849, +916,850,917, +851,917,850, +917,851,918, +852,918,851, +918,852,919, +853,919,852, +919,853,920, +854,920,853, +920,854,921, +855,921,854, +921,855,922, +856,922,855, +922,856,923, +857,923,856, +924,858,925, +859,925,858, +925,859,926, +860,926,859, +926,860,927, +861,927,860, +927,861,928, +862,928,861, +928,862,929, +863,929,862, +929,863,930, +864,930,863, +930,864,931, +865,931,864, +931,865,932, +866,932,865, +932,866,933, +867,933,866, +933,867,934, +868,934,867, +934,868,935, +869,935,868, +935,869,936, +870,936,869, +936,870,937, +871,937,870, +937,871,938, +872,938,871, +938,872,939, +873,939,872, +939,873,940, +874,940,873, +940,874,941, +875,941,874, +941,875,942, +876,942,875, +942,876,943, +877,943,876, +943,877,944, +878,944,877, +944,878,945, +879,945,878, +945,879,946, +880,946,879, +946,880,947, +881,947,880, +947,881,948, +882,948,881, +948,882,949, +883,949,882, +949,883,950, +884,950,883, +950,884,951, +885,951,884, +951,885,952, +886,952,885, +952,886,953, +887,953,886, +953,887,954, +888,954,887, +954,888,955, +889,955,888, +955,889,956, +890,956,889, +956,890,957, +891,957,890, +957,891,958, +892,958,891, +958,892,959, +893,959,892, +959,893,960, +894,960,893, +960,894,961, +895,961,894, +961,895,962, +896,962,895, +962,896,963, +897,963,896, +963,897,964, +898,964,897, +964,898,965, +899,965,898, +965,899,966, +900,966,899, +966,900,967, +901,967,900, +967,901,968, +902,968,901, +968,902,969, +903,969,902, +969,903,970, +904,970,903, +970,904,971, +905,971,904, +971,905,972, +906,972,905, +972,906,973, +907,973,906, +973,907,974, +908,974,907, +974,908,975, +909,975,908, +975,909,976, +910,976,909, +976,910,977, +911,977,910, +977,911,978, +912,978,911, +978,912,979, +913,979,912, +979,913,980, +914,980,913, +980,914,981, +915,981,914, +981,915,982, +916,982,915, +982,916,983, +917,983,916, +983,917,984, +918,984,917, +984,918,985, +919,985,918, +985,919,986, +920,986,919, +986,920,987, +921,987,920, +987,921,988, +922,988,921, +988,922,989, +923,989,922, +990,924,991, +925,991,924, +991,925,992, +926,992,925, +992,926,993, +927,993,926, +993,927,994, +928,994,927, +994,928,995, +929,995,928, +995,929,996, +930,996,929, +996,930,997, +931,997,930, +997,931,998, +932,998,931, +998,932,999, +933,999,932, +999,933,1000, +934,1000,933, +1000,934,1001, +935,1001,934, +1001,935,1002, +936,1002,935, +1002,936,1003, +937,1003,936, +1003,937,1004, +938,1004,937, +1004,938,1005, +939,1005,938, +1005,939,1006, +940,1006,939, +1006,940,1007, +941,1007,940, +1007,941,1008, +942,1008,941, +1008,942,1009, +943,1009,942, +1009,943,1010, +944,1010,943, +1010,944,1011, +945,1011,944, +1011,945,1012, +946,1012,945, +1012,946,1013, +947,1013,946, +1013,947,1014, +948,1014,947, +1014,948,1015, +949,1015,948, +1015,949,1016, +950,1016,949, +1016,950,1017, +951,1017,950, +1017,951,1018, +952,1018,951, +1018,952,1019, +953,1019,952, +1019,953,1020, +954,1020,953, +1020,954,1021, +955,1021,954, +1021,955,1022, +956,1022,955, +1022,956,1023, +957,1023,956, +1023,957,1024, +958,1024,957, +1024,958,1025, +959,1025,958, +1025,959,1026, +960,1026,959, +1026,960,1027, +961,1027,960, +1027,961,1028, +962,1028,961, +1028,962,1029, +963,1029,962, +1029,963,1030, +964,1030,963, +1030,964,1031, +965,1031,964, +1031,965,1032, +966,1032,965, +1032,966,1033, +967,1033,966, +1033,967,1034, +968,1034,967, +1034,968,1035, +969,1035,968, +1035,969,1036, +970,1036,969, +1036,970,1037, +971,1037,970, +1037,971,1038, +972,1038,971, +1038,972,1039, +973,1039,972, +1039,973,1040, +974,1040,973, +1040,974,1041, +975,1041,974, +1041,975,1042, +976,1042,975, +1042,976,1043, +977,1043,976, +1043,977,1044, +978,1044,977, +1044,978,1045, +979,1045,978, +1045,979,1046, +980,1046,979, +1046,980,1047, +981,1047,980, +1047,981,1048, +982,1048,981, +1048,982,1049, +983,1049,982, +1049,983,1050, +984,1050,983, +1050,984,1051, +985,1051,984, +1051,985,1052, +986,1052,985, +1052,986,1053, +987,1053,986, +1053,987,1054, +988,1054,987, +1054,988,1055, +989,1055,988, +1056,990,1057, +991,1057,990, +1057,991,1058, +992,1058,991, +1058,992,1059, +993,1059,992, +1059,993,1060, +994,1060,993, +1060,994,1061, +995,1061,994, +1061,995,1062, +996,1062,995, +1062,996,1063, +997,1063,996, +1063,997,1064, +998,1064,997, +1064,998,1065, +999,1065,998, +1065,999,1066, +1000,1066,999, +1066,1000,1067, +1001,1067,1000, +1067,1001,1068, +1002,1068,1001, +1068,1002,1069, +1003,1069,1002, +1069,1003,1070, +1004,1070,1003, +1070,1004,1071, +1005,1071,1004, +1071,1005,1072, +1006,1072,1005, +1072,1006,1073, +1007,1073,1006, +1073,1007,1074, +1008,1074,1007, +1074,1008,1075, +1009,1075,1008, +1075,1009,1076, +1010,1076,1009, +1076,1010,1077, +1011,1077,1010, +1077,1011,1078, +1012,1078,1011, +1078,1012,1079, +1013,1079,1012, +1079,1013,1080, +1014,1080,1013, +1080,1014,1081, +1015,1081,1014, +1081,1015,1082, +1016,1082,1015, +1082,1016,1083, +1017,1083,1016, +1083,1017,1084, +1018,1084,1017, +1084,1018,1085, +1019,1085,1018, +1085,1019,1086, +1020,1086,1019, +1086,1020,1087, +1021,1087,1020, +1087,1021,1088, +1022,1088,1021, +1088,1022,1089, +1023,1089,1022, +1089,1023,1090, +1024,1090,1023, +1090,1024,1091, +1025,1091,1024, +1091,1025,1092, +1026,1092,1025, +1092,1026,1093, +1027,1093,1026, +1093,1027,1094, +1028,1094,1027, +1094,1028,1095, +1029,1095,1028, +1095,1029,1096, +1030,1096,1029, +1096,1030,1097, +1031,1097,1030, +1097,1031,1098, +1032,1098,1031, +1098,1032,1099, +1033,1099,1032, +1099,1033,1100, +1034,1100,1033, +1100,1034,1101, +1035,1101,1034, +1101,1035,1102, +1036,1102,1035, +1102,1036,1103, +1037,1103,1036, +1103,1037,1104, +1038,1104,1037, +1104,1038,1105, +1039,1105,1038, +1105,1039,1106, +1040,1106,1039, +1106,1040,1107, +1041,1107,1040, +1107,1041,1108, +1042,1108,1041, +1108,1042,1109, +1043,1109,1042, +1109,1043,1110, +1044,1110,1043, +1110,1044,1111, +1045,1111,1044, +1111,1045,1112, +1046,1112,1045, +1112,1046,1113, +1047,1113,1046, +1113,1047,1114, +1048,1114,1047, +1114,1048,1115, +1049,1115,1048, +1115,1049,1116, +1050,1116,1049, +1116,1050,1117, +1051,1117,1050, +1117,1051,1118, +1052,1118,1051, +1118,1052,1119, +1053,1119,1052, +1119,1053,1120, +1054,1120,1053, +1120,1054,1121, +1055,1121,1054, +1122,1056,1123, +1057,1123,1056, +1123,1057,1124, +1058,1124,1057, +1124,1058,1125, +1059,1125,1058, +1125,1059,1126, +1060,1126,1059, +1126,1060,1127, +1061,1127,1060, +1127,1061,1128, +1062,1128,1061, +1128,1062,1129, +1063,1129,1062, +1129,1063,1130, +1064,1130,1063, +1130,1064,1131, +1065,1131,1064, +1131,1065,1132, +1066,1132,1065, +1132,1066,1133, +1067,1133,1066, +1133,1067,1134, +1068,1134,1067, +1134,1068,1135, +1069,1135,1068, +1135,1069,1136, +1070,1136,1069, +1136,1070,1137, +1071,1137,1070, +1137,1071,1138, +1072,1138,1071, +1138,1072,1139, +1073,1139,1072, +1139,1073,1140, +1074,1140,1073, +1140,1074,1141, +1075,1141,1074, +1141,1075,1142, +1076,1142,1075, +1142,1076,1143, +1077,1143,1076, +1143,1077,1144, +1078,1144,1077, +1144,1078,1145, +1079,1145,1078, +1145,1079,1146, +1080,1146,1079, +1146,1080,1147, +1081,1147,1080, +1147,1081,1148, +1082,1148,1081, +1148,1082,1149, +1083,1149,1082, +1149,1083,1150, +1084,1150,1083, +1150,1084,1151, +1085,1151,1084, +1151,1085,1152, +1086,1152,1085, +1152,1086,1153, +1087,1153,1086, +1153,1087,1154, +1088,1154,1087, +1154,1088,1155, +1089,1155,1088, +1155,1089,1156, +1090,1156,1089, +1156,1090,1157, +1091,1157,1090, +1157,1091,1158, +1092,1158,1091, +1158,1092,1159, +1093,1159,1092, +1159,1093,1160, +1094,1160,1093, +1160,1094,1161, +1095,1161,1094, +1161,1095,1162, +1096,1162,1095, +1162,1096,1163, +1097,1163,1096, +1163,1097,1164, +1098,1164,1097, +1164,1098,1165, +1099,1165,1098, +1165,1099,1166, +1100,1166,1099, +1166,1100,1167, +1101,1167,1100, +1167,1101,1168, +1102,1168,1101, +1168,1102,1169, +1103,1169,1102, +1169,1103,1170, +1104,1170,1103, +1170,1104,1171, +1105,1171,1104, +1171,1105,1172, +1106,1172,1105, +1172,1106,1173, +1107,1173,1106, +1173,1107,1174, +1108,1174,1107, +1174,1108,1175, +1109,1175,1108, +1175,1109,1176, +1110,1176,1109, +1176,1110,1177, +1111,1177,1110, +1177,1111,1178, +1112,1178,1111, +1178,1112,1179, +1113,1179,1112, +1179,1113,1180, +1114,1180,1113, +1180,1114,1181, +1115,1181,1114, +1181,1115,1182, +1116,1182,1115, +1182,1116,1183, +1117,1183,1116, +1183,1117,1184, +1118,1184,1117, +1184,1118,1185, +1119,1185,1118, +1185,1119,1186, +1120,1186,1119, +1186,1120,1187, +1121,1187,1120, +1188,1122,1189, +1123,1189,1122, +1189,1123,1190, +1124,1190,1123, +1190,1124,1191, +1125,1191,1124, +1191,1125,1192, +1126,1192,1125, +1192,1126,1193, +1127,1193,1126, +1193,1127,1194, +1128,1194,1127, +1194,1128,1195, +1129,1195,1128, +1195,1129,1196, +1130,1196,1129, +1196,1130,1197, +1131,1197,1130, +1197,1131,1198, +1132,1198,1131, +1198,1132,1199, +1133,1199,1132, +1199,1133,1200, +1134,1200,1133, +1200,1134,1201, +1135,1201,1134, +1201,1135,1202, +1136,1202,1135, +1202,1136,1203, +1137,1203,1136, +1203,1137,1204, +1138,1204,1137, +1204,1138,1205, +1139,1205,1138, +1205,1139,1206, +1140,1206,1139, +1206,1140,1207, +1141,1207,1140, +1207,1141,1208, +1142,1208,1141, +1208,1142,1209, +1143,1209,1142, +1209,1143,1210, +1144,1210,1143, +1210,1144,1211, +1145,1211,1144, +1211,1145,1212, +1146,1212,1145, +1212,1146,1213, +1147,1213,1146, +1213,1147,1214, +1148,1214,1147, +1214,1148,1215, +1149,1215,1148, +1215,1149,1216, +1150,1216,1149, +1216,1150,1217, +1151,1217,1150, +1217,1151,1218, +1152,1218,1151, +1218,1152,1219, +1153,1219,1152, +1219,1153,1220, +1154,1220,1153, +1220,1154,1221, +1155,1221,1154, +1221,1155,1222, +1156,1222,1155, +1222,1156,1223, +1157,1223,1156, +1223,1157,1224, +1158,1224,1157, +1224,1158,1225, +1159,1225,1158, +1225,1159,1226, +1160,1226,1159, +1226,1160,1227, +1161,1227,1160, +1227,1161,1228, +1162,1228,1161, +1228,1162,1229, +1163,1229,1162, +1229,1163,1230, +1164,1230,1163, +1230,1164,1231, +1165,1231,1164, +1231,1165,1232, +1166,1232,1165, +1232,1166,1233, +1167,1233,1166, +1233,1167,1234, +1168,1234,1167, +1234,1168,1235, +1169,1235,1168, +1235,1169,1236, +1170,1236,1169, +1236,1170,1237, +1171,1237,1170, +1237,1171,1238, +1172,1238,1171, +1238,1172,1239, +1173,1239,1172, +1239,1173,1240, +1174,1240,1173, +1240,1174,1241, +1175,1241,1174, +1241,1175,1242, +1176,1242,1175, +1242,1176,1243, +1177,1243,1176, +1243,1177,1244, +1178,1244,1177, +1244,1178,1245, +1179,1245,1178, +1245,1179,1246, +1180,1246,1179, +1246,1180,1247, +1181,1247,1180, +1247,1181,1248, +1182,1248,1181, +1248,1182,1249, +1183,1249,1182, +1249,1183,1250, +1184,1250,1183, +1250,1184,1251, +1185,1251,1184, +1251,1185,1252, +1186,1252,1185, +1252,1186,1253, +1187,1253,1186, +1254,1188,1255, +1189,1255,1188, +1255,1189,1256, +1190,1256,1189, +1256,1190,1257, +1191,1257,1190, +1257,1191,1258, +1192,1258,1191, +1258,1192,1259, +1193,1259,1192, +1259,1193,1260, +1194,1260,1193, +1260,1194,1261, +1195,1261,1194, +1261,1195,1262, +1196,1262,1195, +1262,1196,1263, +1197,1263,1196, +1263,1197,1264, +1198,1264,1197, +1264,1198,1265, +1199,1265,1198, +1265,1199,1266, +1200,1266,1199, +1266,1200,1267, +1201,1267,1200, +1267,1201,1268, +1202,1268,1201, +1268,1202,1269, +1203,1269,1202, +1269,1203,1270, +1204,1270,1203, +1270,1204,1271, +1205,1271,1204, +1271,1205,1272, +1206,1272,1205, +1272,1206,1273, +1207,1273,1206, +1273,1207,1274, +1208,1274,1207, +1274,1208,1275, +1209,1275,1208, +1275,1209,1276, +1210,1276,1209, +1276,1210,1277, +1211,1277,1210, +1277,1211,1278, +1212,1278,1211, +1278,1212,1279, +1213,1279,1212, +1279,1213,1280, +1214,1280,1213, +1280,1214,1281, +1215,1281,1214, +1281,1215,1282, +1216,1282,1215, +1282,1216,1283, +1217,1283,1216, +1283,1217,1284, +1218,1284,1217, +1284,1218,1285, +1219,1285,1218, +1285,1219,1286, +1220,1286,1219, +1286,1220,1287, +1221,1287,1220, +1287,1221,1288, +1222,1288,1221, +1288,1222,1289, +1223,1289,1222, +1289,1223,1290, +1224,1290,1223, +1290,1224,1291, +1225,1291,1224, +1291,1225,1292, +1226,1292,1225, +1292,1226,1293, +1227,1293,1226, +1293,1227,1294, +1228,1294,1227, +1294,1228,1295, +1229,1295,1228, +1295,1229,1296, +1230,1296,1229, +1296,1230,1297, +1231,1297,1230, +1297,1231,1298, +1232,1298,1231, +1298,1232,1299, +1233,1299,1232, +1299,1233,1300, +1234,1300,1233, +1300,1234,1301, +1235,1301,1234, +1301,1235,1302, +1236,1302,1235, +1302,1236,1303, +1237,1303,1236, +1303,1237,1304, +1238,1304,1237, +1304,1238,1305, +1239,1305,1238, +1305,1239,1306, +1240,1306,1239, +1306,1240,1307, +1241,1307,1240, +1307,1241,1308, +1242,1308,1241, +1308,1242,1309, +1243,1309,1242, +1309,1243,1310, +1244,1310,1243, +1310,1244,1311, +1245,1311,1244, +1311,1245,1312, +1246,1312,1245, +1312,1246,1313, +1247,1313,1246, +1313,1247,1314, +1248,1314,1247, +1314,1248,1315, +1249,1315,1248, +1315,1249,1316, +1250,1316,1249, +1316,1250,1317, +1251,1317,1250, +1317,1251,1318, +1252,1318,1251, +1318,1252,1319, +1253,1319,1252, +1320,1254,1321, +1255,1321,1254, +1321,1255,1322, +1256,1322,1255, +1322,1256,1323, +1257,1323,1256, +1323,1257,1324, +1258,1324,1257, +1324,1258,1325, +1259,1325,1258, +1325,1259,1326, +1260,1326,1259, +1326,1260,1327, +1261,1327,1260, +1327,1261,1328, +1262,1328,1261, +1328,1262,1329, +1263,1329,1262, +1329,1263,1330, +1264,1330,1263, +1330,1264,1331, +1265,1331,1264, +1331,1265,1332, +1266,1332,1265, +1332,1266,1333, +1267,1333,1266, +1333,1267,1334, +1268,1334,1267, +1334,1268,1335, +1269,1335,1268, +1335,1269,1336, +1270,1336,1269, +1336,1270,1337, +1271,1337,1270, +1337,1271,1338, +1272,1338,1271, +1338,1272,1339, +1273,1339,1272, +1339,1273,1340, +1274,1340,1273, +1340,1274,1341, +1275,1341,1274, +1341,1275,1342, +1276,1342,1275, +1342,1276,1343, +1277,1343,1276, +1343,1277,1344, +1278,1344,1277, +1344,1278,1345, +1279,1345,1278, +1345,1279,1346, +1280,1346,1279, +1346,1280,1347, +1281,1347,1280, +1347,1281,1348, +1282,1348,1281, +1348,1282,1349, +1283,1349,1282, +1349,1283,1350, +1284,1350,1283, +1350,1284,1351, +1285,1351,1284, +1351,1285,1352, +1286,1352,1285, +1352,1286,1353, +1287,1353,1286, +1353,1287,1354, +1288,1354,1287, +1354,1288,1355, +1289,1355,1288, +1355,1289,1356, +1290,1356,1289, +1356,1290,1357, +1291,1357,1290, +1357,1291,1358, +1292,1358,1291, +1358,1292,1359, +1293,1359,1292, +1359,1293,1360, +1294,1360,1293, +1360,1294,1361, +1295,1361,1294, +1361,1295,1362, +1296,1362,1295, +1362,1296,1363, +1297,1363,1296, +1363,1297,1364, +1298,1364,1297, +1364,1298,1365, +1299,1365,1298, +1365,1299,1366, +1300,1366,1299, +1366,1300,1367, +1301,1367,1300, +1367,1301,1368, +1302,1368,1301, +1368,1302,1369, +1303,1369,1302, +1369,1303,1370, +1304,1370,1303, +1370,1304,1371, +1305,1371,1304, +1371,1305,1372, +1306,1372,1305, +1372,1306,1373, +1307,1373,1306, +1373,1307,1374, +1308,1374,1307, +1374,1308,1375, +1309,1375,1308, +1375,1309,1376, +1310,1376,1309, +1376,1310,1377, +1311,1377,1310, +1377,1311,1378, +1312,1378,1311, +1378,1312,1379, +1313,1379,1312, +1379,1313,1380, +1314,1380,1313, +1380,1314,1381, +1315,1381,1314, +1381,1315,1382, +1316,1382,1315, +1382,1316,1383, +1317,1383,1316, +1383,1317,1384, +1318,1384,1317, +1384,1318,1385, +1319,1385,1318, +1386,1320,1387, +1321,1387,1320, +1387,1321,1388, +1322,1388,1321, +1388,1322,1389, +1323,1389,1322, +1389,1323,1390, +1324,1390,1323, +1390,1324,1391, +1325,1391,1324, +1391,1325,1392, +1326,1392,1325, +1392,1326,1393, +1327,1393,1326, +1393,1327,1394, +1328,1394,1327, +1394,1328,1395, +1329,1395,1328, +1395,1329,1396, +1330,1396,1329, +1396,1330,1397, +1331,1397,1330, +1397,1331,1398, +1332,1398,1331, +1398,1332,1399, +1333,1399,1332, +1399,1333,1400, +1334,1400,1333, +1400,1334,1401, +1335,1401,1334, +1401,1335,1402, +1336,1402,1335, +1402,1336,1403, +1337,1403,1336, +1403,1337,1404, +1338,1404,1337, +1404,1338,1405, +1339,1405,1338, +1405,1339,1406, +1340,1406,1339, +1406,1340,1407, +1341,1407,1340, +1407,1341,1408, +1342,1408,1341, +1408,1342,1409, +1343,1409,1342, +1409,1343,1410, +1344,1410,1343, +1410,1344,1411, +1345,1411,1344, +1411,1345,1412, +1346,1412,1345, +1412,1346,1413, +1347,1413,1346, +1413,1347,1414, +1348,1414,1347, +1414,1348,1415, +1349,1415,1348, +1415,1349,1416, +1350,1416,1349, +1416,1350,1417, +1351,1417,1350, +1417,1351,1418, +1352,1418,1351, +1418,1352,1419, +1353,1419,1352, +1419,1353,1420, +1354,1420,1353, +1420,1354,1421, +1355,1421,1354, +1421,1355,1422, +1356,1422,1355, +1422,1356,1423, +1357,1423,1356, +1423,1357,1424, +1358,1424,1357, +1424,1358,1425, +1359,1425,1358, +1425,1359,1426, +1360,1426,1359, +1426,1360,1427, +1361,1427,1360, +1427,1361,1428, +1362,1428,1361, +1428,1362,1429, +1363,1429,1362, +1429,1363,1430, +1364,1430,1363, +1430,1364,1431, +1365,1431,1364, +1431,1365,1432, +1366,1432,1365, +1432,1366,1433, +1367,1433,1366, +1433,1367,1434, +1368,1434,1367, +1434,1368,1435, +1369,1435,1368, +1435,1369,1436, +1370,1436,1369, +1436,1370,1437, +1371,1437,1370, +1437,1371,1438, +1372,1438,1371, +1438,1372,1439, +1373,1439,1372, +1439,1373,1440, +1374,1440,1373, +1440,1374,1441, +1375,1441,1374, +1441,1375,1442, +1376,1442,1375, +1442,1376,1443, +1377,1443,1376, +1443,1377,1444, +1378,1444,1377, +1444,1378,1445, +1379,1445,1378, +1445,1379,1446, +1380,1446,1379, +1446,1380,1447, +1381,1447,1380, +1447,1381,1448, +1382,1448,1381, +1448,1382,1449, +1383,1449,1382, +1449,1383,1450, +1384,1450,1383, +1450,1384,1451, +1385,1451,1384, +1452,1386,1453, +1387,1453,1386, +1453,1387,1454, +1388,1454,1387, +1454,1388,1455, +1389,1455,1388, +1455,1389,1456, +1390,1456,1389, +1456,1390,1457, +1391,1457,1390, +1457,1391,1458, +1392,1458,1391, +1458,1392,1459, +1393,1459,1392, +1459,1393,1460, +1394,1460,1393, +1460,1394,1461, +1395,1461,1394, +1461,1395,1462, +1396,1462,1395, +1462,1396,1463, +1397,1463,1396, +1463,1397,1464, +1398,1464,1397, +1464,1398,1465, +1399,1465,1398, +1465,1399,1466, +1400,1466,1399, +1466,1400,1467, +1401,1467,1400, +1467,1401,1468, +1402,1468,1401, +1468,1402,1469, +1403,1469,1402, +1469,1403,1470, +1404,1470,1403, +1470,1404,1471, +1405,1471,1404, +1471,1405,1472, +1406,1472,1405, +1472,1406,1473, +1407,1473,1406, +1473,1407,1474, +1408,1474,1407, +1474,1408,1475, +1409,1475,1408, +1475,1409,1476, +1410,1476,1409, +1476,1410,1477, +1411,1477,1410, +1477,1411,1478, +1412,1478,1411, +1478,1412,1479, +1413,1479,1412, +1479,1413,1480, +1414,1480,1413, +1480,1414,1481, +1415,1481,1414, +1481,1415,1482, +1416,1482,1415, +1482,1416,1483, +1417,1483,1416, +1483,1417,1484, +1418,1484,1417, +1484,1418,1485, +1419,1485,1418, +1485,1419,1486, +1420,1486,1419, +1486,1420,1487, +1421,1487,1420, +1487,1421,1488, +1422,1488,1421, +1488,1422,1489, +1423,1489,1422, +1489,1423,1490, +1424,1490,1423, +1490,1424,1491, +1425,1491,1424, +1491,1425,1492, +1426,1492,1425, +1492,1426,1493, +1427,1493,1426, +1493,1427,1494, +1428,1494,1427, +1494,1428,1495, +1429,1495,1428, +1495,1429,1496, +1430,1496,1429, +1496,1430,1497, +1431,1497,1430, +1497,1431,1498, +1432,1498,1431, +1498,1432,1499, +1433,1499,1432, +1499,1433,1500, +1434,1500,1433, +1500,1434,1501, +1435,1501,1434, +1501,1435,1502, +1436,1502,1435, +1502,1436,1503, +1437,1503,1436, +1503,1437,1504, +1438,1504,1437, +1504,1438,1505, +1439,1505,1438, +1505,1439,1506, +1440,1506,1439, +1506,1440,1507, +1441,1507,1440, +1507,1441,1508, +1442,1508,1441, +1508,1442,1509, +1443,1509,1442, +1509,1443,1510, +1444,1510,1443, +1510,1444,1511, +1445,1511,1444, +1511,1445,1512, +1446,1512,1445, +1512,1446,1513, +1447,1513,1446, +1513,1447,1514, +1448,1514,1447, +1514,1448,1515, +1449,1515,1448, +1515,1449,1516, +1450,1516,1449, +1516,1450,1517, +1451,1517,1450, +1518,1452,1519, +1453,1519,1452, +1519,1453,1520, +1454,1520,1453, +1520,1454,1521, +1455,1521,1454, +1521,1455,1522, +1456,1522,1455, +1522,1456,1523, +1457,1523,1456, +1523,1457,1524, +1458,1524,1457, +1524,1458,1525, +1459,1525,1458, +1525,1459,1526, +1460,1526,1459, +1526,1460,1527, +1461,1527,1460, +1527,1461,1528, +1462,1528,1461, +1528,1462,1529, +1463,1529,1462, +1529,1463,1530, +1464,1530,1463, +1530,1464,1531, +1465,1531,1464, +1531,1465,1532, +1466,1532,1465, +1532,1466,1533, +1467,1533,1466, +1533,1467,1534, +1468,1534,1467, +1534,1468,1535, +1469,1535,1468, +1535,1469,1536, +1470,1536,1469, +1536,1470,1537, +1471,1537,1470, +1537,1471,1538, +1472,1538,1471, +1538,1472,1539, +1473,1539,1472, +1539,1473,1540, +1474,1540,1473, +1540,1474,1541, +1475,1541,1474, +1541,1475,1542, +1476,1542,1475, +1542,1476,1543, +1477,1543,1476, +1543,1477,1544, +1478,1544,1477, +1544,1478,1545, +1479,1545,1478, +1545,1479,1546, +1480,1546,1479, +1546,1480,1547, +1481,1547,1480, +1547,1481,1548, +1482,1548,1481, +1548,1482,1549, +1483,1549,1482, +1549,1483,1550, +1484,1550,1483, +1550,1484,1551, +1485,1551,1484, +1551,1485,1552, +1486,1552,1485, +1552,1486,1553, +1487,1553,1486, +1553,1487,1554, +1488,1554,1487, +1554,1488,1555, +1489,1555,1488, +1555,1489,1556, +1490,1556,1489, +1556,1490,1557, +1491,1557,1490, +1557,1491,1558, +1492,1558,1491, +1558,1492,1559, +1493,1559,1492, +1559,1493,1560, +1494,1560,1493, +1560,1494,1561, +1495,1561,1494, +1561,1495,1562, +1496,1562,1495, +1562,1496,1563, +1497,1563,1496, +1563,1497,1564, +1498,1564,1497, +1564,1498,1565, +1499,1565,1498, +1565,1499,1566, +1500,1566,1499, +1566,1500,1567, +1501,1567,1500, +1567,1501,1568, +1502,1568,1501, +1568,1502,1569, +1503,1569,1502, +1569,1503,1570, +1504,1570,1503, +1570,1504,1571, +1505,1571,1504, +1571,1505,1572, +1506,1572,1505, +1572,1506,1573, +1507,1573,1506, +1573,1507,1574, +1508,1574,1507, +1574,1508,1575, +1509,1575,1508, +1575,1509,1576, +1510,1576,1509, +1576,1510,1577, +1511,1577,1510, +1577,1511,1578, +1512,1578,1511, +1578,1512,1579, +1513,1579,1512, +1579,1513,1580, +1514,1580,1513, +1580,1514,1581, +1515,1581,1514, +1581,1515,1582, +1516,1582,1515, +1582,1516,1583, +1517,1583,1516, +1584,1518,1585, +1519,1585,1518, +1585,1519,1586, +1520,1586,1519, +1586,1520,1587, +1521,1587,1520, +1587,1521,1588, +1522,1588,1521, +1588,1522,1589, +1523,1589,1522, +1589,1523,1590, +1524,1590,1523, +1590,1524,1591, +1525,1591,1524, +1591,1525,1592, +1526,1592,1525, +1592,1526,1593, +1527,1593,1526, +1593,1527,1594, +1528,1594,1527, +1594,1528,1595, +1529,1595,1528, +1595,1529,1596, +1530,1596,1529, +1596,1530,1597, +1531,1597,1530, +1597,1531,1598, +1532,1598,1531, +1598,1532,1599, +1533,1599,1532, +1599,1533,1600, +1534,1600,1533, +1600,1534,1601, +1535,1601,1534, +1601,1535,1602, +1536,1602,1535, +1602,1536,1603, +1537,1603,1536, +1603,1537,1604, +1538,1604,1537, +1604,1538,1605, +1539,1605,1538, +1605,1539,1606, +1540,1606,1539, +1606,1540,1607, +1541,1607,1540, +1607,1541,1608, +1542,1608,1541, +1608,1542,1609, +1543,1609,1542, +1609,1543,1610, +1544,1610,1543, +1610,1544,1611, +1545,1611,1544, +1611,1545,1612, +1546,1612,1545, +1612,1546,1613, +1547,1613,1546, +1613,1547,1614, +1548,1614,1547, +1614,1548,1615, +1549,1615,1548, +1615,1549,1616, +1550,1616,1549, +1616,1550,1617, +1551,1617,1550, +1617,1551,1618, +1552,1618,1551, +1618,1552,1619, +1553,1619,1552, +1619,1553,1620, +1554,1620,1553, +1620,1554,1621, +1555,1621,1554, +1621,1555,1622, +1556,1622,1555, +1622,1556,1623, +1557,1623,1556, +1623,1557,1624, +1558,1624,1557, +1624,1558,1625, +1559,1625,1558, +1625,1559,1626, +1560,1626,1559, +1626,1560,1627, +1561,1627,1560, +1627,1561,1628, +1562,1628,1561, +1628,1562,1629, +1563,1629,1562, +1629,1563,1630, +1564,1630,1563, +1630,1564,1631, +1565,1631,1564, +1631,1565,1632, +1566,1632,1565, +1632,1566,1633, +1567,1633,1566, +1633,1567,1634, +1568,1634,1567, +1634,1568,1635, +1569,1635,1568, +1635,1569,1636, +1570,1636,1569, +1636,1570,1637, +1571,1637,1570, +1637,1571,1638, +1572,1638,1571, +1638,1572,1639, +1573,1639,1572, +1639,1573,1640, +1574,1640,1573, +1640,1574,1641, +1575,1641,1574, +1641,1575,1642, +1576,1642,1575, +1642,1576,1643, +1577,1643,1576, +1643,1577,1644, +1578,1644,1577, +1644,1578,1645, +1579,1645,1578, +1645,1579,1646, +1580,1646,1579, +1646,1580,1647, +1581,1647,1580, +1647,1581,1648, +1582,1648,1581, +1648,1582,1649, +1583,1649,1582, +1650,1584,1651, +1585,1651,1584, +1651,1585,1652, +1586,1652,1585, +1652,1586,1653, +1587,1653,1586, +1653,1587,1654, +1588,1654,1587, +1654,1588,1655, +1589,1655,1588, +1655,1589,1656, +1590,1656,1589, +1656,1590,1657, +1591,1657,1590, +1657,1591,1658, +1592,1658,1591, +1658,1592,1659, +1593,1659,1592, +1659,1593,1660, +1594,1660,1593, +1660,1594,1661, +1595,1661,1594, +1661,1595,1662, +1596,1662,1595, +1662,1596,1663, +1597,1663,1596, +1663,1597,1664, +1598,1664,1597, +1664,1598,1665, +1599,1665,1598, +1665,1599,1666, +1600,1666,1599, +1666,1600,1667, +1601,1667,1600, +1667,1601,1668, +1602,1668,1601, +1668,1602,1669, +1603,1669,1602, +1669,1603,1670, +1604,1670,1603, +1670,1604,1671, +1605,1671,1604, +1671,1605,1672, +1606,1672,1605, +1672,1606,1673, +1607,1673,1606, +1673,1607,1674, +1608,1674,1607, +1674,1608,1675, +1609,1675,1608, +1675,1609,1676, +1610,1676,1609, +1676,1610,1677, +1611,1677,1610, +1677,1611,1678, +1612,1678,1611, +1678,1612,1679, +1613,1679,1612, +1679,1613,1680, +1614,1680,1613, +1680,1614,1681, +1615,1681,1614, +1681,1615,1682, +1616,1682,1615, +1682,1616,1683, +1617,1683,1616, +1683,1617,1684, +1618,1684,1617, +1684,1618,1685, +1619,1685,1618, +1685,1619,1686, +1620,1686,1619, +1686,1620,1687, +1621,1687,1620, +1687,1621,1688, +1622,1688,1621, +1688,1622,1689, +1623,1689,1622, +1689,1623,1690, +1624,1690,1623, +1690,1624,1691, +1625,1691,1624, +1691,1625,1692, +1626,1692,1625, +1692,1626,1693, +1627,1693,1626, +1693,1627,1694, +1628,1694,1627, +1694,1628,1695, +1629,1695,1628, +1695,1629,1696, +1630,1696,1629, +1696,1630,1697, +1631,1697,1630, +1697,1631,1698, +1632,1698,1631, +1698,1632,1699, +1633,1699,1632, +1699,1633,1700, +1634,1700,1633, +1700,1634,1701, +1635,1701,1634, +1701,1635,1702, +1636,1702,1635, +1702,1636,1703, +1637,1703,1636, +1703,1637,1704, +1638,1704,1637, +1704,1638,1705, +1639,1705,1638, +1705,1639,1706, +1640,1706,1639, +1706,1640,1707, +1641,1707,1640, +1707,1641,1708, +1642,1708,1641, +1708,1642,1709, +1643,1709,1642, +1709,1643,1710, +1644,1710,1643, +1710,1644,1711, +1645,1711,1644, +1711,1645,1712, +1646,1712,1645, +1712,1646,1713, +1647,1713,1646, +1713,1647,1714, +1648,1714,1647, +1714,1648,1715, +1649,1715,1648, +1716,1650,1717, +1651,1717,1650, +1717,1651,1718, +1652,1718,1651, +1718,1652,1719, +1653,1719,1652, +1719,1653,1720, +1654,1720,1653, +1720,1654,1721, +1655,1721,1654, +1721,1655,1722, +1656,1722,1655, +1722,1656,1723, +1657,1723,1656, +1723,1657,1724, +1658,1724,1657, +1724,1658,1725, +1659,1725,1658, +1725,1659,1726, +1660,1726,1659, +1726,1660,1727, +1661,1727,1660, +1727,1661,1728, +1662,1728,1661, +1728,1662,1729, +1663,1729,1662, +1729,1663,1730, +1664,1730,1663, +1730,1664,1731, +1665,1731,1664, +1731,1665,1732, +1666,1732,1665, +1732,1666,1733, +1667,1733,1666, +1733,1667,1734, +1668,1734,1667, +1734,1668,1735, +1669,1735,1668, +1735,1669,1736, +1670,1736,1669, +1736,1670,1737, +1671,1737,1670, +1737,1671,1738, +1672,1738,1671, +1738,1672,1739, +1673,1739,1672, +1739,1673,1740, +1674,1740,1673, +1740,1674,1741, +1675,1741,1674, +1741,1675,1742, +1676,1742,1675, +1742,1676,1743, +1677,1743,1676, +1743,1677,1744, +1678,1744,1677, +1744,1678,1745, +1679,1745,1678, +1745,1679,1746, +1680,1746,1679, +1746,1680,1747, +1681,1747,1680, +1747,1681,1748, +1682,1748,1681, +1748,1682,1749, +1683,1749,1682, +1749,1683,1750, +1684,1750,1683, +1750,1684,1751, +1685,1751,1684, +1751,1685,1752, +1686,1752,1685, +1752,1686,1753, +1687,1753,1686, +1753,1687,1754, +1688,1754,1687, +1754,1688,1755, +1689,1755,1688, +1755,1689,1756, +1690,1756,1689, +1756,1690,1757, +1691,1757,1690, +1757,1691,1758, +1692,1758,1691, +1758,1692,1759, +1693,1759,1692, +1759,1693,1760, +1694,1760,1693, +1760,1694,1761, +1695,1761,1694, +1761,1695,1762, +1696,1762,1695, +1762,1696,1763, +1697,1763,1696, +1763,1697,1764, +1698,1764,1697, +1764,1698,1765, +1699,1765,1698, +1765,1699,1766, +1700,1766,1699, +1766,1700,1767, +1701,1767,1700, +1767,1701,1768, +1702,1768,1701, +1768,1702,1769, +1703,1769,1702, +1769,1703,1770, +1704,1770,1703, +1770,1704,1771, +1705,1771,1704, +1771,1705,1772, +1706,1772,1705, +1772,1706,1773, +1707,1773,1706, +1773,1707,1774, +1708,1774,1707, +1774,1708,1775, +1709,1775,1708, +1775,1709,1776, +1710,1776,1709, +1776,1710,1777, +1711,1777,1710, +1777,1711,1778, +1712,1778,1711, +1778,1712,1779, +1713,1779,1712, +1779,1713,1780, +1714,1780,1713, +1780,1714,1781, +1715,1781,1714, +1782,1716,1783, +1717,1783,1716, +1783,1717,1784, +1718,1784,1717, +1784,1718,1785, +1719,1785,1718, +1785,1719,1786, +1720,1786,1719, +1786,1720,1787, +1721,1787,1720, +1787,1721,1788, +1722,1788,1721, +1788,1722,1789, +1723,1789,1722, +1789,1723,1790, +1724,1790,1723, +1790,1724,1791, +1725,1791,1724, +1791,1725,1792, +1726,1792,1725, +1792,1726,1793, +1727,1793,1726, +1793,1727,1794, +1728,1794,1727, +1794,1728,1795, +1729,1795,1728, +1795,1729,1796, +1730,1796,1729, +1796,1730,1797, +1731,1797,1730, +1797,1731,1798, +1732,1798,1731, +1798,1732,1799, +1733,1799,1732, +1799,1733,1800, +1734,1800,1733, +1800,1734,1801, +1735,1801,1734, +1801,1735,1802, +1736,1802,1735, +1802,1736,1803, +1737,1803,1736, +1803,1737,1804, +1738,1804,1737, +1804,1738,1805, +1739,1805,1738, +1805,1739,1806, +1740,1806,1739, +1806,1740,1807, +1741,1807,1740, +1807,1741,1808, +1742,1808,1741, +1808,1742,1809, +1743,1809,1742, +1809,1743,1810, +1744,1810,1743, +1810,1744,1811, +1745,1811,1744, +1811,1745,1812, +1746,1812,1745, +1812,1746,1813, +1747,1813,1746, +1813,1747,1814, +1748,1814,1747, +1814,1748,1815, +1749,1815,1748, +1815,1749,1816, +1750,1816,1749, +1816,1750,1817, +1751,1817,1750, +1817,1751,1818, +1752,1818,1751, +1818,1752,1819, +1753,1819,1752, +1819,1753,1820, +1754,1820,1753, +1820,1754,1821, +1755,1821,1754, +1821,1755,1822, +1756,1822,1755, +1822,1756,1823, +1757,1823,1756, +1823,1757,1824, +1758,1824,1757, +1824,1758,1825, +1759,1825,1758, +1825,1759,1826, +1760,1826,1759, +1826,1760,1827, +1761,1827,1760, +1827,1761,1828, +1762,1828,1761, +1828,1762,1829, +1763,1829,1762, +1829,1763,1830, +1764,1830,1763, +1830,1764,1831, +1765,1831,1764, +1831,1765,1832, +1766,1832,1765, +1832,1766,1833, +1767,1833,1766, +1833,1767,1834, +1768,1834,1767, +1834,1768,1835, +1769,1835,1768, +1835,1769,1836, +1770,1836,1769, +1836,1770,1837, +1771,1837,1770, +1837,1771,1838, +1772,1838,1771, +1838,1772,1839, +1773,1839,1772, +1839,1773,1840, +1774,1840,1773, +1840,1774,1841, +1775,1841,1774, +1841,1775,1842, +1776,1842,1775, +1842,1776,1843, +1777,1843,1776, +1843,1777,1844, +1778,1844,1777, +1844,1778,1845, +1779,1845,1778, +1845,1779,1846, +1780,1846,1779, +1846,1780,1847, +1781,1847,1780, +1848,1782,1849, +1783,1849,1782, +1849,1783,1850, +1784,1850,1783, +1850,1784,1851, +1785,1851,1784, +1851,1785,1852, +1786,1852,1785, +1852,1786,1853, +1787,1853,1786, +1853,1787,1854, +1788,1854,1787, +1854,1788,1855, +1789,1855,1788, +1855,1789,1856, +1790,1856,1789, +1856,1790,1857, +1791,1857,1790, +1857,1791,1858, +1792,1858,1791, +1858,1792,1859, +1793,1859,1792, +1859,1793,1860, +1794,1860,1793, +1860,1794,1861, +1795,1861,1794, +1861,1795,1862, +1796,1862,1795, +1862,1796,1863, +1797,1863,1796, +1863,1797,1864, +1798,1864,1797, +1864,1798,1865, +1799,1865,1798, +1865,1799,1866, +1800,1866,1799, +1866,1800,1867, +1801,1867,1800, +1867,1801,1868, +1802,1868,1801, +1868,1802,1869, +1803,1869,1802, +1869,1803,1870, +1804,1870,1803, +1870,1804,1871, +1805,1871,1804, +1871,1805,1872, +1806,1872,1805, +1872,1806,1873, +1807,1873,1806, +1873,1807,1874, +1808,1874,1807, +1874,1808,1875, +1809,1875,1808, +1875,1809,1876, +1810,1876,1809, +1876,1810,1877, +1811,1877,1810, +1877,1811,1878, +1812,1878,1811, +1878,1812,1879, +1813,1879,1812, +1879,1813,1880, +1814,1880,1813, +1880,1814,1881, +1815,1881,1814, +1881,1815,1882, +1816,1882,1815, +1882,1816,1883, +1817,1883,1816, +1883,1817,1884, +1818,1884,1817, +1884,1818,1885, +1819,1885,1818, +1885,1819,1886, +1820,1886,1819, +1886,1820,1887, +1821,1887,1820, +1887,1821,1888, +1822,1888,1821, +1888,1822,1889, +1823,1889,1822, +1889,1823,1890, +1824,1890,1823, +1890,1824,1891, +1825,1891,1824, +1891,1825,1892, +1826,1892,1825, +1892,1826,1893, +1827,1893,1826, +1893,1827,1894, +1828,1894,1827, +1894,1828,1895, +1829,1895,1828, +1895,1829,1896, +1830,1896,1829, +1896,1830,1897, +1831,1897,1830, +1897,1831,1898, +1832,1898,1831, +1898,1832,1899, +1833,1899,1832, +1899,1833,1900, +1834,1900,1833, +1900,1834,1901, +1835,1901,1834, +1901,1835,1902, +1836,1902,1835, +1902,1836,1903, +1837,1903,1836, +1903,1837,1904, +1838,1904,1837, +1904,1838,1905, +1839,1905,1838, +1905,1839,1906, +1840,1906,1839, +1906,1840,1907, +1841,1907,1840, +1907,1841,1908, +1842,1908,1841, +1908,1842,1909, +1843,1909,1842, +1909,1843,1910, +1844,1910,1843, +1910,1844,1911, +1845,1911,1844, +1911,1845,1912, +1846,1912,1845, +1912,1846,1913, +1847,1913,1846, +1914,1848,1915, +1849,1915,1848, +1915,1849,1916, +1850,1916,1849, +1916,1850,1917, +1851,1917,1850, +1917,1851,1918, +1852,1918,1851, +1918,1852,1919, +1853,1919,1852, +1919,1853,1920, +1854,1920,1853, +1920,1854,1921, +1855,1921,1854, +1921,1855,1922, +1856,1922,1855, +1922,1856,1923, +1857,1923,1856, +1923,1857,1924, +1858,1924,1857, +1924,1858,1925, +1859,1925,1858, +1925,1859,1926, +1860,1926,1859, +1926,1860,1927, +1861,1927,1860, +1927,1861,1928, +1862,1928,1861, +1928,1862,1929, +1863,1929,1862, +1929,1863,1930, +1864,1930,1863, +1930,1864,1931, +1865,1931,1864, +1931,1865,1932, +1866,1932,1865, +1932,1866,1933, +1867,1933,1866, +1933,1867,1934, +1868,1934,1867, +1934,1868,1935, +1869,1935,1868, +1935,1869,1936, +1870,1936,1869, +1936,1870,1937, +1871,1937,1870, +1937,1871,1938, +1872,1938,1871, +1938,1872,1939, +1873,1939,1872, +1939,1873,1940, +1874,1940,1873, +1940,1874,1941, +1875,1941,1874, +1941,1875,1942, +1876,1942,1875, +1942,1876,1943, +1877,1943,1876, +1943,1877,1944, +1878,1944,1877, +1944,1878,1945, +1879,1945,1878, +1945,1879,1946, +1880,1946,1879, +1946,1880,1947, +1881,1947,1880, +1947,1881,1948, +1882,1948,1881, +1948,1882,1949, +1883,1949,1882, +1949,1883,1950, +1884,1950,1883, +1950,1884,1951, +1885,1951,1884, +1951,1885,1952, +1886,1952,1885, +1952,1886,1953, +1887,1953,1886, +1953,1887,1954, +1888,1954,1887, +1954,1888,1955, +1889,1955,1888, +1955,1889,1956, +1890,1956,1889, +1956,1890,1957, +1891,1957,1890, +1957,1891,1958, +1892,1958,1891, +1958,1892,1959, +1893,1959,1892, +1959,1893,1960, +1894,1960,1893, +1960,1894,1961, +1895,1961,1894, +1961,1895,1962, +1896,1962,1895, +1962,1896,1963, +1897,1963,1896, +1963,1897,1964, +1898,1964,1897, +1964,1898,1965, +1899,1965,1898, +1965,1899,1966, +1900,1966,1899, +1966,1900,1967, +1901,1967,1900, +1967,1901,1968, +1902,1968,1901, +1968,1902,1969, +1903,1969,1902, +1969,1903,1970, +1904,1970,1903, +1970,1904,1971, +1905,1971,1904, +1971,1905,1972, +1906,1972,1905, +1972,1906,1973, +1907,1973,1906, +1973,1907,1974, +1908,1974,1907, +1974,1908,1975, +1909,1975,1908, +1975,1909,1976, +1910,1976,1909, +1976,1910,1977, +1911,1977,1910, +1977,1911,1978, +1912,1978,1911, +1978,1912,1979, +1913,1979,1912, +}; + +#define Landscape03VtxCount 2048 +#define Landscape03IdxCount 11718 + +btScalar Landscape03Vtx[] = { +3.90625f,50.3865f,-2.20246e-006f, +3.90625f,52.6186f,3.90625f, +7.8125f,50.3905f,-2.20264e-006f, +7.8125f,51.8648f,3.90625f, +11.7188f,49.8171f,-2.17758e-006f, +11.7188f,51.1949f,3.90625f, +15.625f,50.595f,-2.21158e-006f, +15.625f,50.2102f,3.90625f, +19.5313f,50.405f,-2.20327e-006f, +19.5313f,50.6058f,3.90625f, +23.4375f,50.9679f,-2.22788e-006f, +23.4375f,50.7008f,3.90625f, +27.3438f,52.4635f,-2.29325e-006f, +27.3438f,51.2163f,3.90625f, +31.25f,53.1505f,-2.32328e-006f, +31.25f,51.4263f,3.90625f, +35.1563f,53.061f,-2.31937e-006f, +35.1563f,52.1968f,3.90625f, +39.0625f,53.6772f,-2.34631e-006f, +39.0625f,53.9783f,3.90625f, +42.9688f,54.3062f,-2.3738e-006f, +42.9688f,53.8927f,3.90625f, +46.875f,54.6795f,-2.39012e-006f, +46.875f,53.3266f,3.90625f, +50.7813f,55.3188f,-2.41806e-006f, +50.7813f,53.5901f,3.90625f, +54.6875f,56.913f,-2.48775e-006f, +54.6875f,55.5679f,3.90625f, +58.5938f,57.4575f,-2.51155e-006f, +58.5938f,55.1819f,3.90625f, +62.5f,56.5398f,-2.47143e-006f, +62.5f,53.6891f,3.90625f, +66.4063f,55.8786f,-2.44253e-006f, +66.4063f,53.0541f,3.90625f, +70.3125f,53.6497f,-2.3451e-006f, +70.3125f,51.6665f,3.90625f, +74.2188f,51.6447f,-2.25746e-006f, +74.2188f,51.4469f,3.90625f, +78.125f,51.8145f,-2.26488e-006f, +78.125f,51.9591f,3.90625f, +82.0313f,51.335f,-2.24392e-006f, +82.0313f,51.0418f,3.90625f, +85.9375f,50.1836f,-2.1936e-006f, +85.9375f,49.7513f,3.90625f, +89.8438f,49.0536f,-2.1442e-006f, +89.8438f,48.7329f,3.90625f, +93.75f,47.3968f,-2.07178e-006f, +93.75f,46.8713f,3.90625f, +97.6563f,45.8014f,-2.00204e-006f, +97.6563f,46.3905f,3.90625f, +101.563f,45.2347f,-1.97727e-006f, +101.563f,45.4241f,3.90625f, +105.469f,44.6501f,-1.95172e-006f, +105.469f,45.6811f,3.90625f, +109.375f,44.3569f,-1.9389e-006f, +109.375f,45.3238f,3.90625f, +113.281f,44.1147f,-1.92831e-006f, +113.281f,43.6112f,3.90625f, +117.188f,43.4037f,-1.89723e-006f, +117.188f,42.1291f,3.90625f, +121.094f,41.1606f,-1.79919e-006f, +121.094f,40.4747f,3.90625f, +125.0f,40.195f,-1.75698e-006f, +125.0f,39.3351f,3.90625f, +128.906f,39.5659f,-1.72948e-006f, +128.906f,38.0742f,3.90625f, +132.813f,38.2592f,-1.67236e-006f, +132.813f,36.7758f,3.90625f, +136.719f,36.4337f,-1.59257e-006f, +136.719f,34.9213f,3.90625f, +140.625f,34.1507f,-1.49277e-006f, +140.625f,32.3643f,3.90625f, +144.531f,31.5531f,-1.37923e-006f, +144.531f,31.7157f,3.90625f, +148.438f,29.9056f,-1.30722e-006f, +148.438f,30.6005f,3.90625f, +152.344f,30.5219f,-1.33416e-006f, +152.344f,31.6034f,3.90625f, +156.25f,31.1254f,-1.36053e-006f, +156.25f,32.6503f,3.90625f, +160.156f,31.8976f,-1.39429e-006f, +160.156f,33.3131f,3.90625f, +164.063f,31.5364f,-1.3785e-006f, +164.063f,32.5745f,3.90625f, +167.969f,30.5585f,-1.33575e-006f, +167.969f,31.5017f,3.90625f, +171.875f,30.0528f,-1.31365e-006f, +171.875f,30.6842f,3.90625f, +175.781f,29.2833f,-1.28002e-006f, +175.781f,29.8734f,3.90625f, +179.688f,28.3316f,-1.23841e-006f, +179.688f,28.6537f,3.90625f, +183.594f,27.0177f,-1.18098e-006f, +183.594f,27.2073f,3.90625f, +187.5f,24.7626f,-1.08241e-006f, +187.5f,25.4367f,3.90625f, +191.406f,22.7371f,-9.9387e-007f, +191.406f,24.1609f,3.90625f, +195.313f,21.6497f,-9.46338e-007f, +195.313f,23.9724f,3.90625f, +199.219f,21.3313f,-9.32422e-007f, +199.219f,23.7702f,3.90625f, +203.125f,20.9148f,-9.14215e-007f, +203.125f,22.4031f,3.90625f, +207.031f,19.4875f,-8.51826e-007f, +207.031f,22.1587f,3.90625f, +210.938f,19.0037f,-8.30679e-007f, +210.938f,21.6154f,3.90625f, +214.844f,18.408f,-8.0464e-007f, +214.844f,21.8202f,3.90625f, +218.75f,18.7855f,-8.2114e-007f, +218.75f,21.017f,3.90625f, +222.656f,18.1497f,-7.9335e-007f, +222.656f,19.3736f,3.90625f, +226.563f,17.6889f,-7.73205e-007f, +226.563f,18.2127f,3.90625f, +230.469f,16.8429f,-7.36228e-007f, +230.469f,17.2263f,3.90625f, +234.375f,16.3712f,-7.15609e-007f, +234.375f,16.2938f,3.90625f, +238.281f,14.3259f,-6.26204e-007f, +238.281f,14.4518f,3.90625f, +242.188f,12.4394f,-5.43742e-007f, +242.188f,13.6398f,3.90625f, +246.094f,12.3876f,-5.41479e-007f, +246.094f,13.2404f,3.90625f, +250.0f,11.9236f,-5.21196e-007f, +250.0f,12.7102f,3.90625f, +3.90625f,48.8559f,-3.90625f, +7.8125f,49.3575f,-3.90625f, +11.7188f,49.963f,-3.90625f, +15.625f,50.1126f,-3.90625f, +19.5313f,51.6247f,-3.90625f, +23.4375f,52.1716f,-3.90625f, +27.3438f,52.8679f,-3.90625f, +31.25f,53.978f,-3.90625f, +35.1563f,53.8948f,-3.90625f, +39.0625f,54.8492f,-3.90625f, +42.9688f,56.1714f,-3.90625f, +46.875f,56.4915f,-3.90625f, +50.7813f,56.5729f,-3.90625f, +54.6875f,57.9767f,-3.90625f, +58.5938f,58.6125f,-3.90625f, +62.5f,58.0023f,-3.90625f, +66.4063f,57.5742f,-3.90625f, +70.3125f,55.4949f,-3.90625f, +74.2188f,53.7219f,-3.90625f, +78.125f,53.233f,-3.90625f, +82.0313f,52.5499f,-3.90625f, +85.9375f,51.1842f,-3.90625f, +89.8438f,49.6534f,-3.90625f, +93.75f,47.6829f,-3.90625f, +97.6563f,45.813f,-3.90625f, +101.563f,44.7099f,-3.90625f, +105.469f,45.0932f,-3.90625f, +109.375f,44.8326f,-3.90625f, +113.281f,44.5197f,-3.90625f, +117.188f,43.7399f,-3.90625f, +121.094f,42.3088f,-3.90625f, +125.0f,40.4224f,-3.90625f, +128.906f,39.437f,-3.90625f, +132.813f,39.825f,-3.90625f, +136.719f,38.2979f,-3.90625f, +140.625f,35.2095f,-3.90625f, +144.531f,32.0692f,-3.90625f, +148.438f,31.1765f,-3.90625f, +152.344f,32.2065f,-3.90625f, +156.25f,31.4774f,-3.90625f, +160.156f,31.7166f,-3.90625f, +164.063f,31.7667f,-3.90625f, +167.969f,31.1742f,-3.90625f, +171.875f,29.6515f,-3.90625f, +175.781f,28.7845f,-3.90625f, +179.688f,28.3154f,-3.90625f, +183.594f,26.6187f,-3.90625f, +187.5f,24.7363f,-3.90625f, +191.406f,22.9162f,-3.90625f, +195.313f,21.5211f,-3.90625f, +199.219f,19.7693f,-3.90625f, +203.125f,18.9792f,-3.90625f, +207.031f,18.8399f,-3.90625f, +210.938f,18.8797f,-3.90625f, +214.844f,18.8123f,-3.90625f, +218.75f,18.5136f,-3.90625f, +222.656f,18.5607f,-3.90625f, +226.563f,17.5053f,-3.90625f, +230.469f,17.4838f,-3.90625f, +234.375f,16.6728f,-3.90625f, +238.281f,14.8594f,-3.90625f, +242.188f,12.9613f,-3.90625f, +246.094f,12.8624f,-3.90625f, +250.0f,11.5894f,-3.90625f, +3.90625f,48.7225f,-7.8125f, +7.8125f,49.1281f,-7.8125f, +11.7188f,50.0005f,-7.8125f, +15.625f,50.5896f,-7.8125f, +19.5313f,51.5499f,-7.8125f, +23.4375f,52.9511f,-7.8125f, +27.3438f,53.117f,-7.8125f, +31.25f,54.0682f,-7.8125f, +35.1563f,55.2353f,-7.8125f, +39.0625f,57.2741f,-7.8125f, +42.9688f,57.4338f,-7.8125f, +46.875f,57.766f,-7.8125f, +50.7813f,57.2724f,-7.8125f, +54.6875f,58.0147f,-7.8125f, +58.5938f,58.764f,-7.8125f, +62.5f,58.6375f,-7.8125f, +66.4063f,57.2699f,-7.8125f, +70.3125f,55.9883f,-7.8125f, +74.2188f,54.8767f,-7.8125f, +78.125f,54.5266f,-7.8125f, +82.0313f,53.7148f,-7.8125f, +85.9375f,52.3735f,-7.8125f, +89.8438f,50.9637f,-7.8125f, +93.75f,48.4983f,-7.8125f, +97.6563f,45.9034f,-7.8125f, +101.563f,45.0863f,-7.8125f, +105.469f,44.2432f,-7.8125f, +109.375f,43.9561f,-7.8125f, +113.281f,43.3015f,-7.8125f, +117.188f,43.254f,-7.8125f, +121.094f,42.7388f,-7.8125f, +125.0f,41.1851f,-7.8125f, +128.906f,39.7522f,-7.8125f, +132.813f,39.8116f,-7.8125f, +136.719f,38.7148f,-7.8125f, +140.625f,36.0845f,-7.8125f, +144.531f,34.0308f,-7.8125f, +148.438f,33.0368f,-7.8125f, +152.344f,32.5867f,-7.8125f, +156.25f,32.8758f,-7.8125f, +160.156f,32.65f,-7.8125f, +164.063f,32.6826f,-7.8125f, +167.969f,31.5243f,-7.8125f, +171.875f,30.4061f,-7.8125f, +175.781f,29.2721f,-7.8125f, +179.688f,28.0417f,-7.8125f, +183.594f,26.2041f,-7.8125f, +187.5f,24.2168f,-7.8125f, +191.406f,22.7847f,-7.8125f, +195.313f,20.5069f,-7.8125f, +199.219f,18.6189f,-7.8125f, +203.125f,17.5296f,-7.8125f, +207.031f,18.0846f,-7.8125f, +210.938f,18.4802f,-7.8125f, +214.844f,18.5436f,-7.8125f, +218.75f,18.3296f,-7.8125f, +222.656f,17.9158f,-7.8125f, +226.563f,17.0318f,-7.8125f, +230.469f,16.2818f,-7.8125f, +234.375f,15.4949f,-7.8125f, +238.281f,13.4891f,-7.8125f, +242.188f,13.3349f,-7.8125f, +246.094f,12.2716f,-7.8125f, +250.0f,10.9901f,-7.8125f, +3.90625f,49.6298f,-11.7188f, +7.8125f,50.0683f,-11.7188f, +11.7188f,50.6295f,-11.7188f, +15.625f,51.0495f,-11.7188f, +19.5313f,52.4884f,-11.7188f, +23.4375f,53.3147f,-11.7188f, +27.3438f,54.4311f,-11.7188f, +31.25f,55.2874f,-11.7188f, +35.1563f,56.5549f,-11.7188f, +39.0625f,57.9376f,-11.7188f, +42.9688f,58.2302f,-11.7188f, +46.875f,59.1419f,-11.7188f, +50.7813f,58.8724f,-11.7188f, +54.6875f,58.5393f,-11.7188f, +58.5938f,58.6416f,-11.7188f, +62.5f,58.1973f,-11.7188f, +66.4063f,57.9168f,-11.7188f, +70.3125f,56.4347f,-11.7188f, +74.2188f,55.7911f,-11.7188f, +78.125f,55.946f,-11.7188f, +82.0313f,54.9033f,-11.7188f, +85.9375f,53.0954f,-11.7188f, +89.8438f,51.7428f,-11.7188f, +93.75f,49.2198f,-11.7188f, +97.6563f,46.1127f,-11.7188f, +101.563f,43.9953f,-11.7188f, +105.469f,43.5777f,-11.7188f, +109.375f,43.3284f,-11.7188f, +113.281f,43.5152f,-11.7188f, +117.188f,43.6687f,-11.7188f, +121.094f,42.5477f,-11.7188f, +125.0f,41.4079f,-11.7188f, +128.906f,39.4512f,-11.7188f, +132.813f,39.5183f,-11.7188f, +136.719f,37.8068f,-11.7188f, +140.625f,36.5652f,-11.7188f, +144.531f,34.8202f,-11.7188f, +148.438f,34.0166f,-11.7188f, +152.344f,33.5311f,-11.7188f, +156.25f,34.1672f,-11.7188f, +160.156f,33.8602f,-11.7188f, +164.063f,33.8717f,-11.7188f, +167.969f,33.1703f,-11.7188f, +171.875f,31.0241f,-11.7188f, +175.781f,30.2798f,-11.7188f, +179.688f,28.3241f,-11.7188f, +183.594f,26.4432f,-11.7188f, +187.5f,24.9758f,-11.7188f, +191.406f,22.2834f,-11.7188f, +195.313f,19.3875f,-11.7188f, +199.219f,18.4079f,-11.7188f, +203.125f,16.6498f,-11.7188f, +207.031f,16.1235f,-11.7188f, +210.938f,16.9462f,-11.7188f, +214.844f,17.2638f,-11.7188f, +218.75f,17.0386f,-11.7188f, +222.656f,16.7666f,-11.7188f, +226.563f,15.3591f,-11.7188f, +230.469f,14.4048f,-11.7188f, +234.375f,13.3079f,-11.7188f, +238.281f,13.0895f,-11.7188f, +242.188f,12.8462f,-11.7188f, +246.094f,12.6287f,-11.7188f, +250.0f,11.4682f,-11.7188f, +3.90625f,50.6915f,-15.625f, +7.8125f,51.2382f,-15.625f, +11.7188f,52.3659f,-15.625f, +15.625f,52.3873f,-15.625f, +19.5313f,53.1083f,-15.625f, +23.4375f,54.652f,-15.625f, +27.3438f,56.0359f,-15.625f, +31.25f,56.4398f,-15.625f, +35.1563f,57.3156f,-15.625f, +39.0625f,58.2355f,-15.625f, +42.9688f,59.4547f,-15.625f, +46.875f,59.9176f,-15.625f, +50.7813f,60.0789f,-15.625f, +54.6875f,59.004f,-15.625f, +58.5938f,59.3361f,-15.625f, +62.5f,59.2681f,-15.625f, +66.4063f,58.5571f,-15.625f, +70.3125f,57.1801f,-15.625f, +74.2188f,56.2048f,-15.625f, +78.125f,56.9427f,-15.625f, +82.0313f,55.401f,-15.625f, +85.9375f,53.0457f,-15.625f, +89.8438f,51.6378f,-15.625f, +93.75f,49.1297f,-15.625f, +97.6563f,46.6267f,-15.625f, +101.563f,44.7255f,-15.625f, +105.469f,43.3819f,-15.625f, +109.375f,42.8703f,-15.625f, +113.281f,42.7636f,-15.625f, +117.188f,42.1897f,-15.625f, +121.094f,41.9269f,-15.625f, +125.0f,41.5365f,-15.625f, +128.906f,39.5408f,-15.625f, +132.813f,38.9178f,-15.625f, +136.719f,38.1447f,-15.625f, +140.625f,36.5145f,-15.625f, +144.531f,34.8696f,-15.625f, +148.438f,34.8203f,-15.625f, +152.344f,34.409f,-15.625f, +156.25f,35.1394f,-15.625f, +160.156f,35.619f,-15.625f, +164.063f,34.7784f,-15.625f, +167.969f,33.6548f,-15.625f, +171.875f,32.1822f,-15.625f, +175.781f,31.1666f,-15.625f, +179.688f,28.9574f,-15.625f, +183.594f,27.3989f,-15.625f, +187.5f,24.7201f,-15.625f, +191.406f,21.7859f,-15.625f, +195.313f,19.2508f,-15.625f, +199.219f,18.0209f,-15.625f, +203.125f,16.8441f,-15.625f, +207.031f,15.8846f,-15.625f, +210.938f,15.6902f,-15.625f, +214.844f,15.3143f,-15.625f, +218.75f,15.3862f,-15.625f, +222.656f,14.2743f,-15.625f, +226.563f,13.5791f,-15.625f, +230.469f,13.4953f,-15.625f, +234.375f,13.3484f,-15.625f, +238.281f,13.2722f,-15.625f, +242.188f,13.4455f,-15.625f, +246.094f,13.0725f,-15.625f, +250.0f,11.5558f,-15.625f, +3.90625f,52.1028f,-19.5313f, +7.8125f,52.877f,-19.5313f, +11.7188f,54.5397f,-19.5313f, +15.625f,54.8941f,-19.5313f, +19.5313f,54.9009f,-19.5313f, +23.4375f,56.1681f,-19.5313f, +27.3438f,56.5579f,-19.5313f, +31.25f,57.7962f,-19.5313f, +35.1563f,58.728f,-19.5313f, +39.0625f,59.4794f,-19.5313f, +42.9688f,60.2636f,-19.5313f, +46.875f,61.2139f,-19.5313f, +50.7813f,60.4636f,-19.5313f, +54.6875f,59.681f,-19.5313f, +58.5938f,60.2068f,-19.5313f, +62.5f,59.1055f,-19.5313f, +66.4063f,57.6126f,-19.5313f, +70.3125f,56.6416f,-19.5313f, +74.2188f,56.4864f,-19.5313f, +78.125f,56.1784f,-19.5313f, +82.0313f,54.8451f,-19.5313f, +85.9375f,53.4094f,-19.5313f, +89.8438f,51.7161f,-19.5313f, +93.75f,48.9933f,-19.5313f, +97.6563f,47.5116f,-19.5313f, +101.563f,45.7701f,-19.5313f, +105.469f,44.0377f,-19.5313f, +109.375f,43.0918f,-19.5313f, +113.281f,42.3992f,-19.5313f, +117.188f,42.0928f,-19.5313f, +121.094f,42.0543f,-19.5313f, +125.0f,41.793f,-19.5313f, +128.906f,39.3232f,-19.5313f, +132.813f,39.1149f,-19.5313f, +136.719f,38.2381f,-19.5313f, +140.625f,36.1019f,-19.5313f, +144.531f,36.4503f,-19.5313f, +148.438f,35.6809f,-19.5313f, +152.344f,35.8022f,-19.5313f, +156.25f,36.4955f,-19.5313f, +160.156f,36.3187f,-19.5313f, +164.063f,35.0268f,-19.5313f, +167.969f,34.0134f,-19.5313f, +171.875f,33.6455f,-19.5313f, +175.781f,31.5932f,-19.5313f, +179.688f,30.0326f,-19.5313f, +183.594f,28.3453f,-19.5313f, +187.5f,25.3719f,-19.5313f, +191.406f,22.0833f,-19.5313f, +195.313f,18.7475f,-19.5313f, +199.219f,17.5517f,-19.5313f, +203.125f,16.1528f,-19.5313f, +207.031f,15.6144f,-19.5313f, +210.938f,14.9281f,-19.5313f, +214.844f,14.5711f,-19.5313f, +218.75f,13.8446f,-19.5313f, +222.656f,13.6892f,-19.5313f, +226.563f,13.1595f,-19.5313f, +230.469f,13.2872f,-19.5313f, +234.375f,13.6153f,-19.5313f, +238.281f,12.8725f,-19.5313f, +242.188f,12.7128f,-19.5313f, +246.094f,13.0658f,-19.5313f, +250.0f,11.5414f,-19.5313f, +3.90625f,54.332f,-23.4375f, +7.8125f,55.636f,-23.4375f, +11.7188f,56.3899f,-23.4375f, +15.625f,56.3763f,-23.4375f, +19.5313f,56.9523f,-23.4375f, +23.4375f,57.5593f,-23.4375f, +27.3438f,57.8056f,-23.4375f, +31.25f,58.5489f,-23.4375f, +35.1563f,59.2321f,-23.4375f, +39.0625f,60.5971f,-23.4375f, +42.9688f,60.1728f,-23.4375f, +46.875f,60.9341f,-23.4375f, +50.7813f,59.5118f,-23.4375f, +54.6875f,59.7552f,-23.4375f, +58.5938f,59.9126f,-23.4375f, +62.5f,58.501f,-23.4375f, +66.4063f,57.8539f,-23.4375f, +70.3125f,56.8693f,-23.4375f, +74.2188f,56.0687f,-23.4375f, +78.125f,55.4392f,-23.4375f, +82.0313f,53.7167f,-23.4375f, +85.9375f,52.1078f,-23.4375f, +89.8438f,50.8869f,-23.4375f, +93.75f,49.9812f,-23.4375f, +97.6563f,47.9233f,-23.4375f, +101.563f,46.1166f,-23.4375f, +105.469f,44.4826f,-23.4375f, +109.375f,42.8924f,-23.4375f, +113.281f,41.9991f,-23.4375f, +117.188f,41.1759f,-23.4375f, +121.094f,41.1189f,-23.4375f, +125.0f,39.9128f,-23.4375f, +128.906f,39.8641f,-23.4375f, +132.813f,39.8777f,-23.4375f, +136.719f,38.3567f,-23.4375f, +140.625f,37.4926f,-23.4375f, +144.531f,37.0275f,-23.4375f, +148.438f,36.7211f,-23.4375f, +152.344f,36.9355f,-23.4375f, +156.25f,37.7455f,-23.4375f, +160.156f,37.3585f,-23.4375f, +164.063f,36.1837f,-23.4375f, +167.969f,34.768f,-23.4375f, +171.875f,33.2179f,-23.4375f, +175.781f,31.6883f,-23.4375f, +179.688f,30.1136f,-23.4375f, +183.594f,28.1155f,-23.4375f, +187.5f,25.4881f,-23.4375f, +191.406f,22.8498f,-23.4375f, +195.313f,19.4425f,-23.4375f, +199.219f,17.1253f,-23.4375f, +203.125f,14.8354f,-23.4375f, +207.031f,14.1771f,-23.4375f, +210.938f,13.9227f,-23.4375f, +214.844f,13.3404f,-23.4375f, +218.75f,13.0525f,-23.4375f, +222.656f,13.0744f,-23.4375f, +226.563f,13.0432f,-23.4375f, +230.469f,13.3341f,-23.4375f, +234.375f,13.6022f,-23.4375f, +238.281f,13.3878f,-23.4375f, +242.188f,12.5812f,-23.4375f, +246.094f,11.8699f,-23.4375f, +250.0f,11.3395f,-23.4375f, +3.90625f,57.5273f,-27.3438f, +7.8125f,57.8217f,-27.3438f, +11.7188f,57.5626f,-27.3438f, +15.625f,57.7794f,-27.3438f, +19.5313f,58.7949f,-27.3438f, +23.4375f,59.3547f,-27.3438f, +27.3438f,59.2359f,-27.3438f, +31.25f,58.8772f,-27.3438f, +35.1563f,58.7149f,-27.3438f, +39.0625f,59.7221f,-27.3438f, +42.9688f,60.0457f,-27.3438f, +46.875f,59.6559f,-27.3438f, +50.7813f,59.9346f,-27.3438f, +54.6875f,60.4095f,-27.3438f, +58.5938f,59.3107f,-27.3438f, +62.5f,57.9086f,-27.3438f, +66.4063f,57.3034f,-27.3438f, +70.3125f,55.5758f,-27.3438f, +74.2188f,54.7167f,-27.3438f, +78.125f,54.405f,-27.3438f, +82.0313f,53.0644f,-27.3438f, +85.9375f,50.9689f,-27.3438f, +89.8438f,49.5959f,-27.3438f, +93.75f,49.2817f,-27.3438f, +97.6563f,48.9188f,-27.3438f, +101.563f,47.0066f,-27.3438f, +105.469f,44.4266f,-27.3438f, +109.375f,42.4539f,-27.3438f, +113.281f,41.5486f,-27.3438f, +117.188f,41.4419f,-27.3438f, +121.094f,41.2039f,-27.3438f, +125.0f,40.188f,-27.3438f, +128.906f,40.4744f,-27.3438f, +132.813f,40.1187f,-27.3438f, +136.719f,38.8055f,-27.3438f, +140.625f,38.024f,-27.3438f, +144.531f,37.5255f,-27.3438f, +148.438f,36.8676f,-27.3438f, +152.344f,37.8967f,-27.3438f, +156.25f,38.4708f,-27.3438f, +160.156f,37.8284f,-27.3438f, +164.063f,36.6094f,-27.3438f, +167.969f,34.4523f,-27.3438f, +171.875f,32.2936f,-27.3438f, +175.781f,31.7467f,-27.3438f, +179.688f,29.9455f,-27.3438f, +183.594f,27.7546f,-27.3438f, +187.5f,25.1902f,-27.3438f, +191.406f,22.537f,-27.3438f, +195.313f,19.5657f,-27.3438f, +199.219f,17.4406f,-27.3438f, +203.125f,15.5459f,-27.3438f, +207.031f,14.92f,-27.3438f, +210.938f,13.472f,-27.3438f, +214.844f,12.9933f,-27.3438f, +218.75f,13.2849f,-27.3438f, +222.656f,12.3375f,-27.3438f, +226.563f,12.0553f,-27.3438f, +230.469f,12.4756f,-27.3438f, +234.375f,12.0857f,-27.3438f, +238.281f,12.1988f,-27.3438f, +242.188f,11.9091f,-27.3438f, +246.094f,10.7301f,-27.3438f, +250.0f,10.1068f,-27.3438f, +3.90625f,59.4204f,-31.25f, +7.8125f,59.5424f,-31.25f, +11.7188f,58.7785f,-31.25f, +15.625f,59.7851f,-31.25f, +19.5313f,60.4897f,-31.25f, +23.4375f,60.6095f,-31.25f, +27.3438f,60.3384f,-31.25f, +31.25f,59.5445f,-31.25f, +35.1563f,58.6838f,-31.25f, +39.0625f,58.847f,-31.25f, +42.9688f,59.3885f,-31.25f, +46.875f,59.447f,-31.25f, +50.7813f,59.5998f,-31.25f, +54.6875f,58.9947f,-31.25f, +58.5938f,58.7482f,-31.25f, +62.5f,56.5947f,-31.25f, +66.4063f,56.2941f,-31.25f, +70.3125f,54.6423f,-31.25f, +74.2188f,53.7392f,-31.25f, +78.125f,53.2955f,-31.25f, +82.0313f,52.8233f,-31.25f, +85.9375f,52.1194f,-31.25f, +89.8438f,51.3335f,-31.25f, +93.75f,49.9201f,-31.25f, +97.6563f,49.1642f,-31.25f, +101.563f,47.4466f,-31.25f, +105.469f,44.6086f,-31.25f, +109.375f,42.885f,-31.25f, +113.281f,42.947f,-31.25f, +117.188f,42.2436f,-31.25f, +121.094f,41.6479f,-31.25f, +125.0f,41.6151f,-31.25f, +128.906f,41.2079f,-31.25f, +132.813f,40.7975f,-31.25f, +136.719f,39.8341f,-31.25f, +140.625f,38.7649f,-31.25f, +144.531f,37.7387f,-31.25f, +148.438f,37.2112f,-31.25f, +152.344f,38.3278f,-31.25f, +156.25f,38.7659f,-31.25f, +160.156f,37.5608f,-31.25f, +164.063f,35.9966f,-31.25f, +167.969f,33.737f,-31.25f, +171.875f,32.0109f,-31.25f, +175.781f,31.1169f,-31.25f, +179.688f,30.0211f,-31.25f, +183.594f,27.5633f,-31.25f, +187.5f,25.0292f,-31.25f, +191.406f,22.8265f,-31.25f, +195.313f,19.8972f,-31.25f, +199.219f,17.6714f,-31.25f, +203.125f,16.2679f,-31.25f, +207.031f,15.0546f,-31.25f, +210.938f,14.037f,-31.25f, +214.844f,12.5501f,-31.25f, +218.75f,12.1528f,-31.25f, +222.656f,12.0576f,-31.25f, +226.563f,11.2847f,-31.25f, +230.469f,11.5946f,-31.25f, +234.375f,10.9216f,-31.25f, +238.281f,10.9182f,-31.25f, +242.188f,11.2826f,-31.25f, +246.094f,11.5781f,-31.25f, +250.0f,11.536f,-31.25f, +3.90625f,60.2212f,-35.1563f, +7.8125f,59.3731f,-35.1563f, +11.7188f,58.5327f,-35.1563f, +15.625f,59.5785f,-35.1563f, +19.5313f,60.1491f,-35.1563f, +23.4375f,60.5297f,-35.1563f, +27.3438f,60.5336f,-35.1563f, +31.25f,60.162f,-35.1563f, +35.1563f,58.5927f,-35.1563f, +39.0625f,57.9369f,-35.1563f, +42.9688f,58.4405f,-35.1563f, +46.875f,58.7374f,-35.1563f, +50.7813f,57.6198f,-35.1563f, +54.6875f,57.3277f,-35.1563f, +58.5938f,56.6423f,-35.1563f, +62.5f,56.2444f,-35.1563f, +66.4063f,56.132f,-35.1563f, +70.3125f,54.6673f,-35.1563f, +74.2188f,53.2924f,-35.1563f, +78.125f,53.2569f,-35.1563f, +82.0313f,52.0828f,-35.1563f, +85.9375f,51.9661f,-35.1563f, +89.8438f,50.9045f,-35.1563f, +93.75f,49.4997f,-35.1563f, +97.6563f,48.0748f,-35.1563f, +101.563f,46.3182f,-35.1563f, +105.469f,44.0878f,-35.1563f, +109.375f,42.863f,-35.1563f, +113.281f,42.8044f,-35.1563f, +117.188f,42.9648f,-35.1563f, +121.094f,42.3221f,-35.1563f, +125.0f,41.6576f,-35.1563f, +128.906f,41.1606f,-35.1563f, +132.813f,39.59f,-35.1563f, +136.719f,38.5602f,-35.1563f, +140.625f,37.9389f,-35.1563f, +144.531f,37.2602f,-35.1563f, +148.438f,37.3784f,-35.1563f, +152.344f,37.8906f,-35.1563f, +156.25f,37.8221f,-35.1563f, +160.156f,36.3088f,-35.1563f, +164.063f,35.1881f,-35.1563f, +167.969f,33.2601f,-35.1563f, +171.875f,31.8157f,-35.1563f, +175.781f,31.3416f,-35.1563f, +179.688f,30.0265f,-35.1563f, +183.594f,27.3943f,-35.1563f, +187.5f,24.641f,-35.1563f, +191.406f,22.2525f,-35.1563f, +195.313f,20.2011f,-35.1563f, +199.219f,18.7104f,-35.1563f, +203.125f,17.3459f,-35.1563f, +207.031f,15.2838f,-35.1563f, +210.938f,13.6157f,-35.1563f, +214.844f,13.3893f,-35.1563f, +218.75f,12.9319f,-35.1563f, +222.656f,11.5191f,-35.1563f, +226.563f,10.4878f,-35.1563f, +230.469f,9.83031f,-35.1563f, +234.375f,9.91945f,-35.1563f, +238.281f,10.9647f,-35.1563f, +242.188f,11.5866f,-35.1563f, +246.094f,11.8313f,-35.1563f, +250.0f,11.9419f,-35.1563f, +3.90625f,59.9094f,-39.0625f, +7.8125f,58.6207f,-39.0625f, +11.7188f,57.735f,-39.0625f, +15.625f,58.9909f,-39.0625f, +19.5313f,60.0678f,-39.0625f, +23.4375f,60.5419f,-39.0625f, +27.3438f,60.4672f,-39.0625f, +31.25f,59.5824f,-39.0625f, +35.1563f,58.4068f,-39.0625f, +39.0625f,57.5098f,-39.0625f, +42.9688f,57.6631f,-39.0625f, +46.875f,57.8211f,-39.0625f, +50.7813f,57.1897f,-39.0625f, +54.6875f,55.6789f,-39.0625f, +58.5938f,55.3212f,-39.0625f, +62.5f,55.2941f,-39.0625f, +66.4063f,55.8101f,-39.0625f, +70.3125f,54.309f,-39.0625f, +74.2188f,53.6313f,-39.0625f, +78.125f,52.7246f,-39.0625f, +82.0313f,51.5473f,-39.0625f, +85.9375f,51.5315f,-39.0625f, +89.8438f,50.6121f,-39.0625f, +93.75f,50.3734f,-39.0625f, +97.6563f,48.8877f,-39.0625f, +101.563f,47.0081f,-39.0625f, +105.469f,44.4827f,-39.0625f, +109.375f,43.5851f,-39.0625f, +113.281f,43.2668f,-39.0625f, +117.188f,43.4016f,-39.0625f, +121.094f,41.962f,-39.0625f, +125.0f,41.4641f,-39.0625f, +128.906f,40.2221f,-39.0625f, +132.813f,38.9234f,-39.0625f, +136.719f,37.7062f,-39.0625f, +140.625f,37.6455f,-39.0625f, +144.531f,37.8691f,-39.0625f, +148.438f,37.4139f,-39.0625f, +152.344f,37.204f,-39.0625f, +156.25f,36.7774f,-39.0625f, +160.156f,35.8962f,-39.0625f, +164.063f,34.5247f,-39.0625f, +167.969f,32.7322f,-39.0625f, +171.875f,32.1044f,-39.0625f, +175.781f,31.321f,-39.0625f, +179.688f,29.7775f,-39.0625f, +183.594f,26.7381f,-39.0625f, +187.5f,24.0216f,-39.0625f, +191.406f,22.277f,-39.0625f, +195.313f,21.2497f,-39.0625f, +199.219f,19.9529f,-39.0625f, +203.125f,18.3349f,-39.0625f, +207.031f,16.7961f,-39.0625f, +210.938f,15.071f,-39.0625f, +214.844f,13.5616f,-39.0625f, +218.75f,13.1679f,-39.0625f, +222.656f,11.2729f,-39.0625f, +226.563f,10.5025f,-39.0625f, +230.469f,9.72086f,-39.0625f, +234.375f,9.90489f,-39.0625f, +238.281f,10.7231f,-39.0625f, +242.188f,11.2573f,-39.0625f, +246.094f,12.0761f,-39.0625f, +250.0f,11.902f,-39.0625f, +3.90625f,59.5207f,-42.9688f, +7.8125f,58.2483f,-42.9688f, +11.7188f,58.069f,-42.9688f, +15.625f,59.4248f,-42.9688f, +19.5313f,60.5261f,-42.9688f, +23.4375f,60.668f,-42.9688f, +27.3438f,60.0252f,-42.9688f, +31.25f,58.0523f,-42.9688f, +35.1563f,56.7426f,-42.9688f, +39.0625f,57.2045f,-42.9688f, +42.9688f,57.166f,-42.9688f, +46.875f,56.9465f,-42.9688f, +50.7813f,55.7381f,-42.9688f, +54.6875f,55.2924f,-42.9688f, +58.5938f,54.6074f,-42.9688f, +62.5f,54.1882f,-42.9688f, +66.4063f,53.672f,-42.9688f, +70.3125f,53.3122f,-42.9688f, +74.2188f,53.0852f,-42.9688f, +78.125f,52.6173f,-42.9688f, +82.0313f,51.616f,-42.9688f, +85.9375f,50.148f,-42.9688f, +89.8438f,49.4823f,-42.9688f, +93.75f,50.0221f,-42.9688f, +97.6563f,48.9931f,-42.9688f, +101.563f,47.1045f,-42.9688f, +105.469f,44.442f,-42.9688f, +109.375f,44.5071f,-42.9688f, +113.281f,44.1005f,-42.9688f, +117.188f,42.8414f,-42.9688f, +121.094f,42.5419f,-42.9688f, +125.0f,41.5451f,-42.9688f, +128.906f,39.4272f,-42.9688f, +132.813f,39.8815f,-42.9688f, +136.719f,39.1366f,-42.9688f, +140.625f,38.7457f,-42.9688f, +144.531f,38.4257f,-42.9688f, +148.438f,37.9899f,-42.9688f, +152.344f,37.1716f,-42.9688f, +156.25f,36.0431f,-42.9688f, +160.156f,35.0784f,-42.9688f, +164.063f,33.3564f,-42.9688f, +167.969f,32.1522f,-42.9688f, +171.875f,30.9698f,-42.9688f, +175.781f,29.7186f,-42.9688f, +179.688f,28.0509f,-42.9688f, +183.594f,25.8254f,-42.9688f, +187.5f,24.8502f,-42.9688f, +191.406f,22.9031f,-42.9688f, +195.313f,20.8135f,-42.9688f, +199.219f,19.6651f,-42.9688f, +203.125f,18.4753f,-42.9688f, +207.031f,17.2259f,-42.9688f, +210.938f,15.6171f,-42.9688f, +214.844f,13.2953f,-42.9688f, +218.75f,13.1679f,-42.9688f, +222.656f,10.7772f,-42.9688f, +226.563f,9.62294f,-42.9688f, +230.469f,9.27609f,-42.9688f, +234.375f,9.47241f,-42.9688f, +238.281f,10.2411f,-42.9688f, +242.188f,11.3745f,-42.9688f, +246.094f,10.981f,-42.9688f, +250.0f,9.93179f,-42.9688f, +3.90625f,58.9086f,-46.875f, +7.8125f,58.895f,-46.875f, +11.7188f,59.1807f,-46.875f, +15.625f,60.2442f,-46.875f, +19.5313f,60.6114f,-46.875f, +23.4375f,59.9439f,-46.875f, +27.3438f,58.704f,-46.875f, +31.25f,58.3729f,-46.875f, +35.1563f,57.0256f,-46.875f, +39.0625f,57.069f,-46.875f, +42.9688f,57.0536f,-46.875f, +46.875f,55.7912f,-46.875f, +50.7813f,54.8674f,-46.875f, +54.6875f,53.8265f,-46.875f, +58.5938f,53.563f,-46.875f, +62.5f,52.5979f,-46.875f, +66.4063f,52.3986f,-46.875f, +70.3125f,52.1891f,-46.875f, +74.2188f,52.2468f,-46.875f, +78.125f,52.3398f,-46.875f, +82.0313f,50.9875f,-46.875f, +85.9375f,49.4072f,-46.875f, +89.8438f,48.3295f,-46.875f, +93.75f,48.9009f,-46.875f, +97.6563f,47.6633f,-46.875f, +101.563f,44.4101f,-46.875f, +105.469f,44.0249f,-46.875f, +109.375f,43.7395f,-46.875f, +113.281f,44.0967f,-46.875f, +117.188f,43.3593f,-46.875f, +121.094f,42.11f,-46.875f, +125.0f,40.8903f,-46.875f, +128.906f,40.3861f,-46.875f, +132.813f,40.075f,-46.875f, +136.719f,39.6347f,-46.875f, +140.625f,38.7369f,-46.875f, +144.531f,37.9042f,-46.875f, +148.438f,36.8546f,-46.875f, +152.344f,36.4012f,-46.875f, +156.25f,35.3977f,-46.875f, +160.156f,34.0947f,-46.875f, +164.063f,32.2545f,-46.875f, +167.969f,30.0086f,-46.875f, +171.875f,29.202f,-46.875f, +175.781f,28.0362f,-46.875f, +179.688f,26.7114f,-46.875f, +183.594f,25.9577f,-46.875f, +187.5f,25.3242f,-46.875f, +191.406f,23.8586f,-46.875f, +195.313f,20.6056f,-46.875f, +199.219f,19.3835f,-46.875f, +203.125f,17.4503f,-46.875f, +207.031f,16.5736f,-46.875f, +210.938f,14.945f,-46.875f, +214.844f,12.5914f,-46.875f, +218.75f,11.835f,-46.875f, +222.656f,10.1636f,-46.875f, +226.563f,9.71281f,-46.875f, +230.469f,9.27988f,-46.875f, +234.375f,8.50394f,-46.875f, +238.281f,9.20978f,-46.875f, +242.188f,9.21707f,-46.875f, +246.094f,9.40089f,-46.875f, +250.0f,8.55411f,-46.875f, +3.90625f,59.8509f,-50.7813f, +7.8125f,59.6141f,-50.7813f, +11.7188f,59.7453f,-50.7813f, +15.625f,60.4259f,-50.7813f, +19.5313f,59.4314f,-50.7813f, +23.4375f,59.033f,-50.7813f, +27.3438f,57.561f,-50.7813f, +31.25f,57.9511f,-50.7813f, +35.1563f,57.0088f,-50.7813f, +39.0625f,56.2469f,-50.7813f, +42.9688f,55.8604f,-50.7813f, +46.875f,55.2326f,-50.7813f, +50.7813f,54.8965f,-50.7813f, +54.6875f,53.1713f,-50.7813f, +58.5938f,52.6122f,-50.7813f, +62.5f,50.9097f,-50.7813f, +66.4063f,50.8144f,-50.7813f, +70.3125f,50.2702f,-50.7813f, +74.2188f,51.4962f,-50.7813f, +78.125f,50.7879f,-50.7813f, +82.0313f,49.5502f,-50.7813f, +85.9375f,48.3386f,-50.7813f, +89.8438f,48.0143f,-50.7813f, +93.75f,46.7527f,-50.7813f, +97.6563f,45.5374f,-50.7813f, +101.563f,44.3542f,-50.7813f, +105.469f,44.8366f,-50.7813f, +109.375f,45.0192f,-50.7813f, +113.281f,44.4763f,-50.7813f, +117.188f,43.4751f,-50.7813f, +121.094f,42.029f,-50.7813f, +125.0f,40.9708f,-50.7813f, +128.906f,40.3658f,-50.7813f, +132.813f,40.0768f,-50.7813f, +136.719f,40.0333f,-50.7813f, +140.625f,38.2667f,-50.7813f, +144.531f,36.5326f,-50.7813f, +148.438f,35.8183f,-50.7813f, +152.344f,35.3934f,-50.7813f, +156.25f,34.9787f,-50.7813f, +160.156f,33.4969f,-50.7813f, +164.063f,31.7517f,-50.7813f, +167.969f,29.499f,-50.7813f, +171.875f,27.1729f,-50.7813f, +175.781f,25.4931f,-50.7813f, +179.688f,25.2745f,-50.7813f, +183.594f,25.2315f,-50.7813f, +187.5f,24.531f,-50.7813f, +191.406f,23.4387f,-50.7813f, +195.313f,21.3665f,-50.7813f, +199.219f,19.2834f,-50.7813f, +203.125f,17.7694f,-50.7813f, +207.031f,16.0247f,-50.7813f, +210.938f,13.9451f,-50.7813f, +214.844f,12.3369f,-50.7813f, +218.75f,10.9033f,-50.7813f, +222.656f,10.0734f,-50.7813f, +226.563f,9.08212f,-50.7813f, +230.469f,9.04527f,-50.7813f, +234.375f,8.83458f,-50.7813f, +238.281f,9.03578f,-50.7813f, +242.188f,9.06782f,-50.7813f, +246.094f,9.03068f,-50.7813f, +250.0f,9.66685f,-50.7813f, +3.90625f,60.3928f,-54.6875f, +7.8125f,60.9235f,-54.6875f, +11.7188f,60.8946f,-54.6875f, +15.625f,60.5131f,-54.6875f, +19.5313f,58.455f,-54.6875f, +23.4375f,57.9712f,-54.6875f, +27.3438f,57.0716f,-54.6875f, +31.25f,56.9372f,-54.6875f, +35.1563f,57.5607f,-54.6875f, +39.0625f,56.6778f,-54.6875f, +42.9688f,56.24f,-54.6875f, +46.875f,55.0661f,-54.6875f, +50.7813f,54.3546f,-54.6875f, +54.6875f,52.1641f,-54.6875f, +58.5938f,51.2643f,-54.6875f, +62.5f,49.4484f,-54.6875f, +66.4063f,48.4401f,-54.6875f, +70.3125f,48.0181f,-54.6875f, +74.2188f,48.8036f,-54.6875f, +78.125f,48.2106f,-54.6875f, +82.0313f,47.8181f,-54.6875f, +85.9375f,47.3982f,-54.6875f, +89.8438f,46.4776f,-54.6875f, +93.75f,45.3848f,-54.6875f, +97.6563f,44.5336f,-54.6875f, +101.563f,45.1445f,-54.6875f, +105.469f,45.5775f,-54.6875f, +109.375f,45.4274f,-54.6875f, +113.281f,44.4184f,-54.6875f, +117.188f,43.6208f,-54.6875f, +121.094f,43.0133f,-54.6875f, +125.0f,41.2193f,-54.6875f, +128.906f,40.0465f,-54.6875f, +132.813f,40.3451f,-54.6875f, +136.719f,39.4272f,-54.6875f, +140.625f,37.2935f,-54.6875f, +144.531f,35.9597f,-54.6875f, +148.438f,34.766f,-54.6875f, +152.344f,33.3503f,-54.6875f, +156.25f,33.6732f,-54.6875f, +160.156f,32.5764f,-54.6875f, +164.063f,30.6942f,-54.6875f, +167.969f,28.8727f,-54.6875f, +171.875f,26.8203f,-54.6875f, +175.781f,24.7162f,-54.6875f, +179.688f,23.5533f,-54.6875f, +183.594f,23.5154f,-54.6875f, +187.5f,23.3554f,-54.6875f, +191.406f,22.7735f,-54.6875f, +195.313f,22.2741f,-54.6875f, +199.219f,20.9717f,-54.6875f, +203.125f,18.5469f,-54.6875f, +207.031f,16.0531f,-54.6875f, +210.938f,13.6058f,-54.6875f, +214.844f,11.0674f,-54.6875f, +218.75f,9.89862f,-54.6875f, +222.656f,9.6172f,-54.6875f, +226.563f,8.63026f,-54.6875f, +230.469f,8.95799f,-54.6875f, +234.375f,8.84522f,-54.6875f, +238.281f,8.9176f,-54.6875f, +242.188f,9.19248f,-54.6875f, +246.094f,9.16691f,-54.6875f, +250.0f,9.42022f,-54.6875f, +3.90625f,61.5747f,-58.5938f, +7.8125f,61.244f,-58.5938f, +11.7188f,60.3982f,-58.5938f, +15.625f,59.4267f,-58.5938f, +19.5313f,58.5294f,-58.5938f, +23.4375f,56.6412f,-58.5938f, +27.3438f,56.0648f,-58.5938f, +31.25f,56.4883f,-58.5938f, +35.1563f,56.5562f,-58.5938f, +39.0625f,56.745f,-58.5938f, +42.9688f,55.6505f,-58.5938f, +46.875f,54.6622f,-58.5938f, +50.7813f,53.7206f,-58.5938f, +54.6875f,51.9309f,-58.5938f, +58.5938f,50.4214f,-58.5938f, +62.5f,48.4353f,-58.5938f, +66.4063f,47.1373f,-58.5938f, +70.3125f,46.0037f,-58.5938f, +74.2188f,45.9795f,-58.5938f, +78.125f,45.2396f,-58.5938f, +82.0313f,45.264f,-58.5938f, +85.9375f,45.2603f,-58.5938f, +89.8438f,45.3076f,-58.5938f, +93.75f,44.8744f,-58.5938f, +97.6563f,44.3646f,-58.5938f, +101.563f,45.1043f,-58.5938f, +105.469f,45.6336f,-58.5938f, +109.375f,44.6129f,-58.5938f, +113.281f,44.3333f,-58.5938f, +117.188f,44.3267f,-58.5938f, +121.094f,42.9064f,-58.5938f, +125.0f,40.63f,-58.5938f, +128.906f,41.2828f,-58.5938f, +132.813f,40.2801f,-58.5938f, +136.719f,39.4089f,-58.5938f, +140.625f,37.0919f,-58.5938f, +144.531f,34.889f,-58.5938f, +148.438f,32.5161f,-58.5938f, +152.344f,31.9597f,-58.5938f, +156.25f,31.5986f,-58.5938f, +160.156f,31.1966f,-58.5938f, +164.063f,30.4149f,-58.5938f, +167.969f,29.0304f,-58.5938f, +171.875f,27.2929f,-58.5938f, +175.781f,26.0835f,-58.5938f, +179.688f,24.7373f,-58.5938f, +183.594f,23.6409f,-58.5938f, +187.5f,23.3059f,-58.5938f, +191.406f,22.8781f,-58.5938f, +195.313f,22.319f,-58.5938f, +199.219f,21.2986f,-58.5938f, +203.125f,19.8613f,-58.5938f, +207.031f,16.8941f,-58.5938f, +210.938f,13.7519f,-58.5938f, +214.844f,11.895f,-58.5938f, +218.75f,9.64673f,-58.5938f, +222.656f,9.27102f,-58.5938f, +226.563f,9.40316f,-58.5938f, +230.469f,8.90628f,-58.5938f, +234.375f,8.63691f,-58.5938f, +238.281f,9.10736f,-58.5938f, +242.188f,9.6506f,-58.5938f, +246.094f,9.20945f,-58.5938f, +250.0f,10.1973f,-58.5938f, +3.90625f,62.1111f,-62.5f, +7.8125f,60.6401f,-62.5f, +11.7188f,59.5734f,-62.5f, +15.625f,59.219f,-62.5f, +19.5313f,57.489f,-62.5f, +23.4375f,55.7813f,-62.5f, +27.3438f,55.9775f,-62.5f, +31.25f,55.9857f,-62.5f, +35.1563f,55.7053f,-62.5f, +39.0625f,55.9712f,-62.5f, +42.9688f,54.6904f,-62.5f, +46.875f,53.8065f,-62.5f, +50.7813f,52.4182f,-62.5f, +54.6875f,50.8531f,-62.5f, +58.5938f,49.1994f,-62.5f, +62.5f,47.7017f,-62.5f, +66.4063f,45.469f,-62.5f, +70.3125f,44.3384f,-62.5f, +74.2188f,43.2272f,-62.5f, +78.125f,43.8591f,-62.5f, +82.0313f,44.3452f,-62.5f, +85.9375f,44.3048f,-62.5f, +89.8438f,44.2242f,-62.5f, +93.75f,44.0587f,-62.5f, +97.6563f,43.7317f,-62.5f, +101.563f,44.5392f,-62.5f, +105.469f,44.5257f,-62.5f, +109.375f,43.5595f,-62.5f, +113.281f,44.5114f,-62.5f, +117.188f,43.2895f,-62.5f, +121.094f,41.6188f,-62.5f, +125.0f,39.9989f,-62.5f, +128.906f,40.9613f,-62.5f, +132.813f,39.8454f,-62.5f, +136.719f,38.9499f,-62.5f, +140.625f,36.7405f,-62.5f, +144.531f,34.8983f,-62.5f, +148.438f,33.5172f,-62.5f, +152.344f,31.5497f,-62.5f, +156.25f,31.3001f,-62.5f, +160.156f,30.8035f,-62.5f, +164.063f,30.3361f,-62.5f, +167.969f,29.7129f,-62.5f, +171.875f,28.9356f,-62.5f, +175.781f,27.3605f,-62.5f, +179.688f,26.5354f,-62.5f, +183.594f,25.1923f,-62.5f, +187.5f,23.8745f,-62.5f, +191.406f,22.6444f,-62.5f, +195.313f,22.0412f,-62.5f, +199.219f,20.9675f,-62.5f, +203.125f,18.5243f,-62.5f, +207.031f,15.5154f,-62.5f, +210.938f,13.2419f,-62.5f, +214.844f,11.0082f,-62.5f, +218.75f,9.92645f,-62.5f, +222.656f,9.66787f,-62.5f, +226.563f,10.141f,-62.5f, +230.469f,9.5559f,-62.5f, +234.375f,8.93799f,-62.5f, +238.281f,9.36179f,-62.5f, +242.188f,9.32325f,-62.5f, +246.094f,9.89448f,-62.5f, +250.0f,11.3062f,-62.5f, +3.90625f,60.8569f,-66.4063f, +7.8125f,59.3087f,-66.4063f, +11.7188f,58.6192f,-66.4063f, +15.625f,57.567f,-66.4063f, +19.5313f,54.6351f,-66.4063f, +23.4375f,53.6183f,-66.4063f, +27.3438f,54.0844f,-66.4063f, +31.25f,54.4962f,-66.4063f, +35.1563f,53.9539f,-66.4063f, +39.0625f,53.4324f,-66.4063f, +42.9688f,52.6655f,-66.4063f, +46.875f,51.9681f,-66.4063f, +50.7813f,51.1623f,-66.4063f, +54.6875f,50.0114f,-66.4063f, +58.5938f,47.9598f,-66.4063f, +62.5f,46.2999f,-66.4063f, +66.4063f,44.4466f,-66.4063f, +70.3125f,42.2001f,-66.4063f, +74.2188f,41.2192f,-66.4063f, +78.125f,41.7209f,-66.4063f, +82.0313f,42.7363f,-66.4063f, +85.9375f,42.9552f,-66.4063f, +89.8438f,43.0346f,-66.4063f, +93.75f,43.4604f,-66.4063f, +97.6563f,42.6437f,-66.4063f, +101.563f,42.6894f,-66.4063f, +105.469f,43.1054f,-66.4063f, +109.375f,42.7138f,-66.4063f, +113.281f,42.4744f,-66.4063f, +117.188f,42.2299f,-66.4063f, +121.094f,41.2421f,-66.4063f, +125.0f,40.3737f,-66.4063f, +128.906f,40.1758f,-66.4063f, +132.813f,39.5421f,-66.4063f, +136.719f,39.0437f,-66.4063f, +140.625f,37.1531f,-66.4063f, +144.531f,34.9841f,-66.4063f, +148.438f,33.2713f,-66.4063f, +152.344f,32.4185f,-66.4063f, +156.25f,31.779f,-66.4063f, +160.156f,30.7377f,-66.4063f, +164.063f,30.5524f,-66.4063f, +167.969f,29.5693f,-66.4063f, +171.875f,28.9756f,-66.4063f, +175.781f,27.4499f,-66.4063f, +179.688f,26.7907f,-66.4063f, +183.594f,25.5886f,-66.4063f, +187.5f,24.2807f,-66.4063f, +191.406f,22.1754f,-66.4063f, +195.313f,20.7766f,-66.4063f, +199.219f,19.914f,-66.4063f, +203.125f,17.149f,-66.4063f, +207.031f,14.0043f,-66.4063f, +210.938f,11.404f,-66.4063f, +214.844f,10.0012f,-66.4063f, +218.75f,8.65109f,-66.4063f, +222.656f,9.38897f,-66.4063f, +226.563f,9.4612f,-66.4063f, +230.469f,8.86613f,-66.4063f, +234.375f,8.68429f,-66.4063f, +238.281f,9.75985f,-66.4063f, +242.188f,10.3807f,-66.4063f, +246.094f,10.966f,-66.4063f, +250.0f,11.4354f,-66.4063f, +3.90625f,59.1482f,-70.3125f, +7.8125f,57.7892f,-70.3125f, +11.7188f,55.5839f,-70.3125f, +15.625f,54.3451f,-70.3125f, +19.5313f,52.0576f,-70.3125f, +23.4375f,50.5935f,-70.3125f, +27.3438f,50.8648f,-70.3125f, +31.25f,51.3182f,-70.3125f, +35.1563f,51.6726f,-70.3125f, +39.0625f,51.1264f,-70.3125f, +42.9688f,51.6239f,-70.3125f, +46.875f,49.728f,-70.3125f, +50.7813f,48.7924f,-70.3125f, +54.6875f,47.3884f,-70.3125f, +58.5938f,46.4477f,-70.3125f, +62.5f,45.2447f,-70.3125f, +66.4063f,42.8677f,-70.3125f, +70.3125f,40.9023f,-70.3125f, +74.2188f,39.5284f,-70.3125f, +78.125f,39.6524f,-70.3125f, +82.0313f,40.5173f,-70.3125f, +85.9375f,41.0204f,-70.3125f, +89.8438f,41.9366f,-70.3125f, +93.75f,42.1341f,-70.3125f, +97.6563f,41.4699f,-70.3125f, +101.563f,40.6754f,-70.3125f, +105.469f,41.2206f,-70.3125f, +109.375f,40.9668f,-70.3125f, +113.281f,41.1079f,-70.3125f, +117.188f,40.7056f,-70.3125f, +121.094f,39.8305f,-70.3125f, +125.0f,40.959f,-70.3125f, +128.906f,41.7481f,-70.3125f, +132.813f,41.1255f,-70.3125f, +136.719f,39.8634f,-70.3125f, +140.625f,37.8454f,-70.3125f, +144.531f,35.3914f,-70.3125f, +148.438f,33.8462f,-70.3125f, +152.344f,33.0994f,-70.3125f, +156.25f,32.4757f,-70.3125f, +160.156f,31.4779f,-70.3125f, +164.063f,29.4211f,-70.3125f, +167.969f,28.0779f,-70.3125f, +171.875f,27.802f,-70.3125f, +175.781f,26.7406f,-70.3125f, +179.688f,25.4777f,-70.3125f, +183.594f,24.7569f,-70.3125f, +187.5f,22.9331f,-70.3125f, +191.406f,21.2419f,-70.3125f, +195.313f,19.5082f,-70.3125f, +199.219f,17.6022f,-70.3125f, +203.125f,15.316f,-70.3125f, +207.031f,12.7546f,-70.3125f, +210.938f,10.3646f,-70.3125f, +214.844f,8.2502f,-70.3125f, +218.75f,8.14317f,-70.3125f, +222.656f,8.65089f,-70.3125f, +226.563f,8.60005f,-70.3125f, +230.469f,8.58165f,-70.3125f, +234.375f,9.40162f,-70.3125f, +238.281f,9.96281f,-70.3125f, +242.188f,9.81934f,-70.3125f, +246.094f,10.3078f,-70.3125f, +250.0f,10.4404f,-70.3125f, +3.90625f,56.5167f,-74.2188f, +7.8125f,55.7237f,-74.2188f, +11.7188f,53.4039f,-74.2188f, +15.625f,51.0313f,-74.2188f, +19.5313f,49.1141f,-74.2188f, +23.4375f,47.8398f,-74.2188f, +27.3438f,47.778f,-74.2188f, +31.25f,48.3917f,-74.2188f, +35.1563f,48.2503f,-74.2188f, +39.0625f,49.1497f,-74.2188f, +42.9688f,48.8224f,-74.2188f, +46.875f,47.4358f,-74.2188f, +50.7813f,47.051f,-74.2188f, +54.6875f,45.4218f,-74.2188f, +58.5938f,44.3385f,-74.2188f, +62.5f,42.9758f,-74.2188f, +66.4063f,41.4743f,-74.2188f, +70.3125f,39.4251f,-74.2188f, +74.2188f,37.5972f,-74.2188f, +78.125f,37.8246f,-74.2188f, +82.0313f,38.9578f,-74.2188f, +85.9375f,40.148f,-74.2188f, +89.8438f,41.1035f,-74.2188f, +93.75f,40.631f,-74.2188f, +97.6563f,40.0863f,-74.2188f, +101.563f,40.3273f,-74.2188f, +105.469f,40.0413f,-74.2188f, +109.375f,40.0514f,-74.2188f, +113.281f,39.4849f,-74.2188f, +117.188f,39.5903f,-74.2188f, +121.094f,40.1543f,-74.2188f, +125.0f,40.3424f,-74.2188f, +128.906f,41.779f,-74.2188f, +132.813f,41.4976f,-74.2188f, +136.719f,41.1475f,-74.2188f, +140.625f,38.8105f,-74.2188f, +144.531f,35.834f,-74.2188f, +148.438f,34.6385f,-74.2188f, +152.344f,33.7088f,-74.2188f, +156.25f,32.7137f,-74.2188f, +160.156f,30.7745f,-74.2188f, +164.063f,28.172f,-74.2188f, +167.969f,27.1433f,-74.2188f, +171.875f,26.7248f,-74.2188f, +175.781f,25.7807f,-74.2188f, +179.688f,24.8758f,-74.2188f, +183.594f,23.4994f,-74.2188f, +187.5f,23.3209f,-74.2188f, +191.406f,22.3523f,-74.2188f, +195.313f,20.3275f,-74.2188f, +199.219f,17.2927f,-74.2188f, +203.125f,15.0486f,-74.2188f, +207.031f,12.2721f,-74.2188f, +210.938f,9.60109f,-74.2188f, +214.844f,7.36411f,-74.2188f, +218.75f,7.27514f,-74.2188f, +222.656f,8.35951f,-74.2188f, +226.563f,8.18334f,-74.2188f, +230.469f,8.98708f,-74.2188f, +234.375f,8.98011f,-74.2188f, +238.281f,9.03329f,-74.2188f, +242.188f,8.88664f,-74.2188f, +246.094f,8.62938f,-74.2188f, +250.0f,9.6823f,-74.2188f, +3.90625f,54.4402f,-78.125f, +7.8125f,53.0525f,-78.125f, +11.7188f,51.2204f,-78.125f, +15.625f,48.7251f,-78.125f, +19.5313f,45.9841f,-78.125f, +23.4375f,45.0227f,-78.125f, +27.3438f,45.3099f,-78.125f, +31.25f,45.9225f,-78.125f, +35.1563f,46.8025f,-78.125f, +39.0625f,46.8434f,-78.125f, +42.9688f,46.0024f,-78.125f, +46.875f,45.6669f,-78.125f, +50.7813f,45.4624f,-78.125f, +54.6875f,43.4573f,-78.125f, +58.5938f,42.1273f,-78.125f, +62.5f,41.0088f,-78.125f, +66.4063f,38.8967f,-78.125f, +70.3125f,38.002f,-78.125f, +74.2188f,36.5282f,-78.125f, +78.125f,37.0499f,-78.125f, +82.0313f,37.3419f,-78.125f, +85.9375f,38.6056f,-78.125f, +89.8438f,39.7527f,-78.125f, +93.75f,40.3513f,-78.125f, +97.6563f,40.6919f,-78.125f, +101.563f,40.7736f,-78.125f, +105.469f,40.3007f,-78.125f, +109.375f,39.3023f,-78.125f, +113.281f,39.1369f,-78.125f, +117.188f,39.884f,-78.125f, +121.094f,40.5674f,-78.125f, +125.0f,40.8192f,-78.125f, +128.906f,41.893f,-78.125f, +132.813f,42.3647f,-78.125f, +136.719f,41.2455f,-78.125f, +140.625f,38.7064f,-78.125f, +144.531f,36.9679f,-78.125f, +148.438f,36.03f,-78.125f, +152.344f,33.9946f,-78.125f, +156.25f,32.2274f,-78.125f, +160.156f,30.474f,-78.125f, +164.063f,28.4739f,-78.125f, +167.969f,27.222f,-78.125f, +171.875f,26.6935f,-78.125f, +175.781f,25.0624f,-78.125f, +179.688f,24.162f,-78.125f, +183.594f,24.0176f,-78.125f, +187.5f,24.0379f,-78.125f, +191.406f,22.4301f,-78.125f, +195.313f,19.7078f,-78.125f, +199.219f,17.0911f,-78.125f, +203.125f,14.784f,-78.125f, +207.031f,11.8835f,-78.125f, +210.938f,9.34715f,-78.125f, +214.844f,7.23075f,-78.125f, +218.75f,7.91637f,-78.125f, +222.656f,8.69702f,-78.125f, +226.563f,8.56112f,-78.125f, +230.469f,9.86446f,-78.125f, +234.375f,9.26431f,-78.125f, +238.281f,8.47473f,-78.125f, +242.188f,7.8386f,-78.125f, +246.094f,7.82236f,-78.125f, +250.0f,8.68625f,-78.125f, +3.90625f,51.949f,-82.0313f, +7.8125f,50.1159f,-82.0313f, +11.7188f,48.9067f,-82.0313f, +15.625f,46.6417f,-82.0313f, +19.5313f,44.5725f,-82.0313f, +23.4375f,43.435f,-82.0313f, +27.3438f,43.6749f,-82.0313f, +31.25f,44.8399f,-82.0313f, +35.1563f,45.0253f,-82.0313f, +39.0625f,44.7335f,-82.0313f, +42.9688f,44.4485f,-82.0313f, +46.875f,44.8284f,-82.0313f, +50.7813f,43.5547f,-82.0313f, +54.6875f,41.2266f,-82.0313f, +58.5938f,40.4716f,-82.0313f, +62.5f,38.4361f,-82.0313f, +66.4063f,36.3554f,-82.0313f, +70.3125f,35.5722f,-82.0313f, +74.2188f,35.0069f,-82.0313f, +78.125f,35.8289f,-82.0313f, +82.0313f,37.0933f,-82.0313f, +85.9375f,38.1008f,-82.0313f, +89.8438f,38.9582f,-82.0313f, +93.75f,40.0751f,-82.0313f, +97.6563f,40.3989f,-82.0313f, +101.563f,40.2487f,-82.0313f, +105.469f,39.9234f,-82.0313f, +109.375f,40.0277f,-82.0313f, +113.281f,40.6647f,-82.0313f, +117.188f,40.69f,-82.0313f, +121.094f,40.7857f,-82.0313f, +125.0f,41.5688f,-82.0313f, +128.906f,41.836f,-82.0313f, +132.813f,41.6054f,-82.0313f, +136.719f,39.6237f,-82.0313f, +140.625f,38.6765f,-82.0313f, +144.531f,36.9959f,-82.0313f, +148.438f,35.8215f,-82.0313f, +152.344f,34.799f,-82.0313f, +156.25f,33.2398f,-82.0313f, +160.156f,30.7864f,-82.0313f, +164.063f,28.6776f,-82.0313f, +167.969f,26.6558f,-82.0313f, +171.875f,25.8282f,-82.0313f, +175.781f,24.7932f,-82.0313f, +179.688f,22.3283f,-82.0313f, +183.594f,23.1666f,-82.0313f, +187.5f,23.1721f,-82.0313f, +191.406f,21.3358f,-82.0313f, +195.313f,18.8226f,-82.0313f, +199.219f,16.5471f,-82.0313f, +203.125f,14.4667f,-82.0313f, +207.031f,11.1533f,-82.0313f, +210.938f,8.28389f,-82.0313f, +214.844f,8.02411f,-82.0313f, +218.75f,8.03784f,-82.0313f, +222.656f,8.27638f,-82.0313f, +226.563f,8.14824f,-82.0313f, +230.469f,8.45286f,-82.0313f, +234.375f,8.21959f,-82.0313f, +238.281f,8.25224f,-82.0313f, +242.188f,7.67129f,-82.0313f, +246.094f,8.04143f,-82.0313f, +250.0f,8.6199f,-82.0313f, +3.90625f,50.007f,-85.9375f, +7.8125f,48.4593f,-85.9375f, +11.7188f,46.0233f,-85.9375f, +15.625f,44.0556f,-85.9375f, +19.5313f,42.3324f,-85.9375f, +23.4375f,41.8982f,-85.9375f, +27.3438f,42.3931f,-85.9375f, +31.25f,43.1153f,-85.9375f, +35.1563f,43.1285f,-85.9375f, +39.0625f,43.422f,-85.9375f, +42.9688f,43.5417f,-85.9375f, +46.875f,42.2294f,-85.9375f, +50.7813f,40.9068f,-85.9375f, +54.6875f,39.4177f,-85.9375f, +58.5938f,37.2575f,-85.9375f, +62.5f,35.2254f,-85.9375f, +66.4063f,33.8821f,-85.9375f, +70.3125f,33.1531f,-85.9375f, +74.2188f,34.2747f,-85.9375f, +78.125f,35.599f,-85.9375f, +82.0313f,37.007f,-85.9375f, +85.9375f,37.5018f,-85.9375f, +89.8438f,38.1376f,-85.9375f, +93.75f,38.9449f,-85.9375f, +97.6563f,38.9221f,-85.9375f, +101.563f,38.8555f,-85.9375f, +105.469f,39.5572f,-85.9375f, +109.375f,40.1231f,-85.9375f, +113.281f,40.7416f,-85.9375f, +117.188f,40.3888f,-85.9375f, +121.094f,40.6715f,-85.9375f, +125.0f,40.7246f,-85.9375f, +128.906f,40.6124f,-85.9375f, +132.813f,39.685f,-85.9375f, +136.719f,39.2043f,-85.9375f, +140.625f,38.1816f,-85.9375f, +144.531f,36.598f,-85.9375f, +148.438f,36.2907f,-85.9375f, +152.344f,34.8832f,-85.9375f, +156.25f,33.4024f,-85.9375f, +160.156f,31.2463f,-85.9375f, +164.063f,29.1669f,-85.9375f, +167.969f,26.7298f,-85.9375f, +171.875f,24.3407f,-85.9375f, +175.781f,23.4854f,-85.9375f, +179.688f,21.3474f,-85.9375f, +183.594f,21.2953f,-85.9375f, +187.5f,21.7398f,-85.9375f, +191.406f,20.4218f,-85.9375f, +195.313f,17.9433f,-85.9375f, +199.219f,15.3133f,-85.9375f, +203.125f,13.0586f,-85.9375f, +207.031f,9.24996f,-85.9375f, +210.938f,7.18408f,-85.9375f, +214.844f,7.59758f,-85.9375f, +218.75f,8.04641f,-85.9375f, +222.656f,8.01634f,-85.9375f, +226.563f,7.95015f,-85.9375f, +230.469f,7.86343f,-85.9375f, +234.375f,6.21751f,-85.9375f, +238.281f,7.40112f,-85.9375f, +242.188f,7.60481f,-85.9375f, +246.094f,6.77129f,-85.9375f, +250.0f,7.87753f,-85.9375f, +3.90625f,47.6596f,-89.8438f, +7.8125f,45.9136f,-89.8438f, +11.7188f,44.0495f,-89.8438f, +15.625f,42.5127f,-89.8438f, +19.5313f,41.5996f,-89.8438f, +23.4375f,41.2638f,-89.8438f, +27.3438f,41.2672f,-89.8438f, +31.25f,41.5402f,-89.8438f, +35.1563f,42.558f,-89.8438f, +39.0625f,42.49f,-89.8438f, +42.9688f,42.2839f,-89.8438f, +46.875f,40.9401f,-89.8438f, +50.7813f,38.7346f,-89.8438f, +54.6875f,36.624f,-89.8438f, +58.5938f,35.1978f,-89.8438f, +62.5f,34.9272f,-89.8438f, +66.4063f,32.893f,-89.8438f, +70.3125f,32.4101f,-89.8438f, +74.2188f,33.9814f,-89.8438f, +78.125f,35.8825f,-89.8438f, +82.0313f,37.1245f,-89.8438f, +85.9375f,37.3954f,-89.8438f, +89.8438f,38.0118f,-89.8438f, +93.75f,37.5426f,-89.8438f, +97.6563f,38.0776f,-89.8438f, +101.563f,37.9785f,-89.8438f, +105.469f,38.6389f,-89.8438f, +109.375f,39.284f,-89.8438f, +113.281f,40.0027f,-89.8438f, +117.188f,41.2412f,-89.8438f, +121.094f,41.2301f,-89.8438f, +125.0f,40.7611f,-89.8438f, +128.906f,39.7426f,-89.8438f, +132.813f,39.1387f,-89.8438f, +136.719f,38.499f,-89.8438f, +140.625f,37.714f,-89.8438f, +144.531f,36.6379f,-89.8438f, +148.438f,36.1196f,-89.8438f, +152.344f,35.7001f,-89.8438f, +156.25f,33.9038f,-89.8438f, +160.156f,32.0706f,-89.8438f, +164.063f,29.746f,-89.8438f, +167.969f,26.4482f,-89.8438f, +171.875f,23.8046f,-89.8438f, +175.781f,21.9675f,-89.8438f, +179.688f,20.7011f,-89.8438f, +183.594f,20.6699f,-89.8438f, +187.5f,20.1508f,-89.8438f, +191.406f,17.8245f,-89.8438f, +195.313f,16.2785f,-89.8438f, +199.219f,13.4596f,-89.8438f, +203.125f,9.54647f,-89.8438f, +207.031f,6.02727f,-89.8438f, +210.938f,5.88903f,-89.8438f, +214.844f,6.47568f,-89.8438f, +218.75f,6.20004f,-89.8438f, +222.656f,6.0849f,-89.8438f, +226.563f,6.84648f,-89.8438f, +230.469f,6.3424f,-89.8438f, +234.375f,5.81853f,-89.8438f, +238.281f,5.89205f,-89.8438f, +242.188f,6.84078f,-89.8438f, +246.094f,6.32426f,-89.8438f, +250.0f,6.29368f,-89.8438f, +3.90625f,45.4182f,-93.75f, +7.8125f,44.5664f,-93.75f, +11.7188f,44.0207f,-93.75f, +15.625f,42.2553f,-93.75f, +19.5313f,40.8951f,-93.75f, +23.4375f,40.7665f,-93.75f, +27.3438f,40.5756f,-93.75f, +31.25f,41.2988f,-93.75f, +35.1563f,40.6862f,-93.75f, +39.0625f,40.6007f,-93.75f, +42.9688f,39.5329f,-93.75f, +46.875f,38.2364f,-93.75f, +50.7813f,36.1442f,-93.75f, +54.6875f,34.7353f,-93.75f, +58.5938f,34.4214f,-93.75f, +62.5f,33.9528f,-93.75f, +66.4063f,32.4931f,-93.75f, +70.3125f,32.5145f,-93.75f, +74.2188f,33.393f,-93.75f, +78.125f,34.9658f,-93.75f, +82.0313f,36.3611f,-93.75f, +85.9375f,37.568f,-93.75f, +89.8438f,37.012f,-93.75f, +93.75f,37.6392f,-93.75f, +97.6563f,38.4371f,-93.75f, +101.563f,38.3719f,-93.75f, +105.469f,39.1179f,-93.75f, +109.375f,38.5168f,-93.75f, +113.281f,40.0403f,-93.75f, +117.188f,40.2277f,-93.75f, +121.094f,40.8985f,-93.75f, +125.0f,40.189f,-93.75f, +128.906f,39.9435f,-93.75f, +132.813f,39.6824f,-93.75f, +136.719f,38.844f,-93.75f, +140.625f,37.4579f,-93.75f, +144.531f,36.8375f,-93.75f, +148.438f,36.2601f,-93.75f, +152.344f,35.6484f,-93.75f, +156.25f,34.179f,-93.75f, +160.156f,32.0651f,-93.75f, +164.063f,28.6431f,-93.75f, +167.969f,25.1239f,-93.75f, +171.875f,22.4459f,-93.75f, +175.781f,19.5301f,-93.75f, +179.688f,18.4371f,-93.75f, +183.594f,18.6076f,-93.75f, +187.5f,17.488f,-93.75f, +191.406f,15.1604f,-93.75f, +195.313f,13.0197f,-93.75f, +199.219f,9.4702f,-93.75f, +203.125f,5.597f,-93.75f, +207.031f,3.59409f,-93.75f, +210.938f,4.28966f,-93.75f, +214.844f,4.21811f,-93.75f, +218.75f,4.11546f,-93.75f, +222.656f,5.40815f,-93.75f, +226.563f,5.56249f,-93.75f, +230.469f,5.35075f,-93.75f, +234.375f,5.24306f,-93.75f, +238.281f,4.85548f,-93.75f, +242.188f,5.02825f,-93.75f, +246.094f,5.32318f,-93.75f, +250.0f,5.59512f,-93.75f, +3.90625f,44.9637f,-97.6563f, +7.8125f,44.7813f,-97.6563f, +11.7188f,43.457f,-97.6563f, +15.625f,42.5329f,-97.6563f, +19.5313f,40.506f,-97.6563f, +23.4375f,39.8146f,-97.6563f, +27.3438f,40.2245f,-97.6563f, +31.25f,39.497f,-97.6563f, +35.1563f,38.8152f,-97.6563f, +39.0625f,38.3406f,-97.6563f, +42.9688f,37.57f,-97.6563f, +46.875f,36.3128f,-97.6563f, +50.7813f,34.2277f,-97.6563f, +54.6875f,33.3395f,-97.6563f, +58.5938f,32.972f,-97.6563f, +62.5f,32.6315f,-97.6563f, +66.4063f,32.4796f,-97.6563f, +70.3125f,31.6472f,-97.6563f, +74.2188f,32.2256f,-97.6563f, +78.125f,33.8073f,-97.6563f, +82.0313f,35.7591f,-97.6563f, +85.9375f,36.5001f,-97.6563f, +89.8438f,36.9113f,-97.6563f, +93.75f,37.6902f,-97.6563f, +97.6563f,37.9643f,-97.6563f, +101.563f,38.9556f,-97.6563f, +105.469f,39.6823f,-97.6563f, +109.375f,38.9917f,-97.6563f, +113.281f,40.0872f,-97.6563f, +117.188f,40.44f,-97.6563f, +121.094f,39.6877f,-97.6563f, +125.0f,39.0011f,-97.6563f, +128.906f,39.8735f,-97.6563f, +132.813f,39.5503f,-97.6563f, +136.719f,37.743f,-97.6563f, +140.625f,36.4691f,-97.6563f, +144.531f,36.1765f,-97.6563f, +148.438f,35.9476f,-97.6563f, +152.344f,35.1141f,-97.6563f, +156.25f,33.2516f,-97.6563f, +160.156f,30.654f,-97.6563f, +164.063f,27.2318f,-97.6563f, +167.969f,23.3975f,-97.6563f, +171.875f,20.6722f,-97.6563f, +175.781f,18.394f,-97.6563f, +179.688f,17.6475f,-97.6563f, +183.594f,16.1037f,-97.6563f, +187.5f,14.761f,-97.6563f, +191.406f,12.2456f,-97.6563f, +195.313f,9.43327f,-97.6563f, +199.219f,6.9118f,-97.6563f, +203.125f,4.26334f,-97.6563f, +207.031f,3.47413f,-97.6563f, +210.938f,3.74872f,-97.6563f, +214.844f,3.7631f,-97.6563f, +218.75f,3.80513f,-97.6563f, +222.656f,4.23443f,-97.6563f, +226.563f,3.71016f,-97.6563f, +230.469f,3.772f,-97.6563f, +234.375f,3.80374f,-97.6563f, +238.281f,3.70762f,-97.6563f, +242.188f,4.23931f,-97.6563f, +246.094f,4.40519f,-97.6563f, +250.0f,4.5119f,-97.6563f, +3.90625f,44.5311f,-101.563f, +7.8125f,44.4181f,-101.563f, +11.7188f,43.4864f,-101.563f, +15.625f,42.259f,-101.563f, +19.5313f,41.0558f,-101.563f, +23.4375f,39.9996f,-101.563f, +27.3438f,39.3917f,-101.563f, +31.25f,39.5691f,-101.563f, +35.1563f,37.0889f,-101.563f, +39.0625f,36.4296f,-101.563f, +42.9688f,36.543f,-101.563f, +46.875f,35.4365f,-101.563f, +50.7813f,33.3641f,-101.563f, +54.6875f,32.0629f,-101.563f, +58.5938f,32.175f,-101.563f, +62.5f,32.775f,-101.563f, +66.4063f,31.6335f,-101.563f, +70.3125f,32.1001f,-101.563f, +74.2188f,32.5906f,-101.563f, +78.125f,33.1502f,-101.563f, +82.0313f,35.1972f,-101.563f, +85.9375f,36.0132f,-101.563f, +89.8438f,37.3442f,-101.563f, +93.75f,37.6109f,-101.563f, +97.6563f,38.1601f,-101.563f, +101.563f,39.77f,-101.563f, +105.469f,39.6862f,-101.563f, +109.375f,39.4829f,-101.563f, +113.281f,40.1383f,-101.563f, +117.188f,40.8908f,-101.563f, +121.094f,39.3517f,-101.563f, +125.0f,38.9321f,-101.563f, +128.906f,39.2537f,-101.563f, +132.813f,38.4876f,-101.563f, +136.719f,36.6755f,-101.563f, +140.625f,35.2803f,-101.563f, +144.531f,35.8754f,-101.563f, +148.438f,36.2761f,-101.563f, +152.344f,34.7815f,-101.563f, +156.25f,32.2662f,-101.563f, +160.156f,29.8191f,-101.563f, +164.063f,25.8929f,-101.563f, +167.969f,22.552f,-101.563f, +171.875f,20.3186f,-101.563f, +175.781f,17.2917f,-101.563f, +179.688f,16.8305f,-101.563f, +183.594f,14.7168f,-101.563f, +187.5f,12.0609f,-101.563f, +191.406f,9.91022f,-101.563f, +195.313f,7.22029f,-101.563f, +199.219f,5.48379f,-101.563f, +203.125f,3.03759f,-101.563f, +207.031f,3.02148f,-101.563f, +210.938f,2.88667f,-101.563f, +214.844f,3.08795f,-101.563f, +218.75f,3.43814f,-101.563f, +222.656f,3.58591f,-101.563f, +226.563f,3.17855f,-101.563f, +230.469f,2.48711f,-101.563f, +234.375f,2.66471f,-101.563f, +238.281f,2.06432f,-101.563f, +242.188f,2.49704f,-101.563f, +246.094f,3.05219f,-101.563f, +250.0f,3.69155f,-101.563f, +3.90625f,44.8466f,-105.469f, +7.8125f,44.3102f,-105.469f, +11.7188f,43.8936f,-105.469f, +15.625f,43.2285f,-105.469f, +19.5313f,42.7384f,-105.469f, +23.4375f,41.2954f,-105.469f, +27.3438f,39.4813f,-105.469f, +31.25f,38.4483f,-105.469f, +35.1563f,35.8264f,-105.469f, +39.0625f,35.0991f,-105.469f, +42.9688f,35.1929f,-105.469f, +46.875f,34.3044f,-105.469f, +50.7813f,31.4169f,-105.469f, +54.6875f,30.8206f,-105.469f, +58.5938f,31.2902f,-105.469f, +62.5f,32.2869f,-105.469f, +66.4063f,32.5121f,-105.469f, +70.3125f,32.772f,-105.469f, +74.2188f,32.5422f,-105.469f, +78.125f,34.0506f,-105.469f, +82.0313f,35.4894f,-105.469f, +85.9375f,36.753f,-105.469f, +89.8438f,37.6901f,-105.469f, +93.75f,37.848f,-105.469f, +97.6563f,38.9724f,-105.469f, +101.563f,40.0724f,-105.469f, +105.469f,39.7381f,-105.469f, +109.375f,39.3905f,-105.469f, +113.281f,39.8577f,-105.469f, +117.188f,40.4957f,-105.469f, +121.094f,39.554f,-105.469f, +125.0f,39.0384f,-105.469f, +128.906f,38.2112f,-105.469f, +132.813f,36.7141f,-105.469f, +136.719f,34.736f,-105.469f, +140.625f,34.2236f,-105.469f, +144.531f,35.4181f,-105.469f, +148.438f,35.4456f,-105.469f, +152.344f,33.4389f,-105.469f, +156.25f,29.9708f,-105.469f, +160.156f,27.2392f,-105.469f, +164.063f,24.3409f,-105.469f, +167.969f,22.4438f,-105.469f, +171.875f,19.5326f,-105.469f, +175.781f,16.9951f,-105.469f, +179.688f,14.77f,-105.469f, +183.594f,13.1816f,-105.469f, +187.5f,10.3711f,-105.469f, +191.406f,7.10511f,-105.469f, +195.313f,5.43711f,-105.469f, +199.219f,3.35463f,-105.469f, +203.125f,2.41276f,-105.469f, +207.031f,2.35357f,-105.469f, +210.938f,2.28627f,-105.469f, +214.844f,1.61561f,-105.469f, +218.75f,2.61087f,-105.469f, +222.656f,2.34638f,-105.469f, +226.563f,1.47074f,-105.469f, +230.469f,0.63025f,-105.469f, +234.375f,0.847991f,-105.469f, +238.281f,1.35199f,-105.469f, +242.188f,2.21032f,-105.469f, +246.094f,3.01323f,-105.469f, +250.0f,3.12713f,-105.469f, +3.90625f,45.3987f,-109.375f, +7.8125f,44.6273f,-109.375f, +11.7188f,44.5674f,-109.375f, +15.625f,44.2998f,-109.375f, +19.5313f,43.5383f,-109.375f, +23.4375f,42.0306f,-109.375f, +27.3438f,40.7068f,-109.375f, +31.25f,39.6497f,-109.375f, +35.1563f,36.2161f,-109.375f, +39.0625f,34.8769f,-109.375f, +42.9688f,35.1989f,-109.375f, +46.875f,33.9714f,-109.375f, +50.7813f,30.9979f,-109.375f, +54.6875f,31.9366f,-109.375f, +58.5938f,31.5755f,-109.375f, +62.5f,31.572f,-109.375f, +66.4063f,33.0668f,-109.375f, +70.3125f,33.6444f,-109.375f, +74.2188f,32.5467f,-109.375f, +78.125f,34.2686f,-109.375f, +82.0313f,36.0633f,-109.375f, +85.9375f,37.5569f,-109.375f, +89.8438f,38.5599f,-109.375f, +93.75f,38.6708f,-109.375f, +97.6563f,39.2558f,-109.375f, +101.563f,39.9111f,-109.375f, +105.469f,39.9236f,-109.375f, +109.375f,39.5666f,-109.375f, +113.281f,40.1532f,-109.375f, +117.188f,40.8773f,-109.375f, +121.094f,40.133f,-109.375f, +125.0f,38.348f,-109.375f, +128.906f,36.9174f,-109.375f, +132.813f,34.8975f,-109.375f, +136.719f,32.9097f,-109.375f, +140.625f,32.6666f,-109.375f, +144.531f,33.1207f,-109.375f, +148.438f,32.6024f,-109.375f, +152.344f,31.1149f,-109.375f, +156.25f,27.7885f,-109.375f, +160.156f,24.9665f,-109.375f, +164.063f,22.789f,-109.375f, +167.969f,20.4907f,-109.375f, +171.875f,18.2402f,-109.375f, +175.781f,15.9409f,-109.375f, +179.688f,12.7122f,-109.375f, +183.594f,10.9582f,-109.375f, +187.5f,7.47226f,-109.375f, +191.406f,4.87747f,-109.375f, +195.313f,2.78589f,-109.375f, +199.219f,1.53429f,-109.375f, +203.125f,1.61775f,-109.375f, +207.031f,1.772f,-109.375f, +210.938f,1.15444f,-109.375f, +214.844f,0.342505f,-109.375f, +218.75f,0.510183f,-109.375f, +222.656f,0.254977f,-109.375f, +226.563f,-0.22727f,-109.375f, +230.469f,-0.840625f,-109.375f, +234.375f,-0.282154f,-109.375f, +238.281f,0.424945f,-109.375f, +242.188f,1.73577f,-109.375f, +246.094f,1.80217f,-109.375f, +250.0f,1.60105f,-109.375f, +3.90625f,47.4869f,-113.281f, +7.8125f,46.3185f,-113.281f, +11.7188f,46.4911f,-113.281f, +15.625f,45.2506f,-113.281f, +19.5313f,43.7939f,-113.281f, +23.4375f,42.6062f,-113.281f, +27.3438f,41.6674f,-113.281f, +31.25f,39.5196f,-113.281f, +35.1563f,36.6784f,-113.281f, +39.0625f,35.8546f,-113.281f, +42.9688f,35.2647f,-113.281f, +46.875f,33.0882f,-113.281f, +50.7813f,31.1331f,-113.281f, +54.6875f,31.9095f,-113.281f, +58.5938f,31.5715f,-113.281f, +62.5f,32.3642f,-113.281f, +66.4063f,33.2578f,-113.281f, +70.3125f,33.1847f,-113.281f, +74.2188f,33.6624f,-113.281f, +78.125f,35.6582f,-113.281f, +82.0313f,36.7989f,-113.281f, +85.9375f,37.9951f,-113.281f, +89.8438f,38.7063f,-113.281f, +93.75f,39.9727f,-113.281f, +97.6563f,39.641f,-113.281f, +101.563f,40.1318f,-113.281f, +105.469f,40.117f,-113.281f, +109.375f,40.0678f,-113.281f, +113.281f,40.1534f,-113.281f, +117.188f,40.7841f,-113.281f, +121.094f,39.3312f,-113.281f, +125.0f,38.1823f,-113.281f, +128.906f,37.0921f,-113.281f, +132.813f,34.9687f,-113.281f, +136.719f,32.6631f,-113.281f, +140.625f,30.9601f,-113.281f, +144.531f,31.0644f,-113.281f, +148.438f,29.6495f,-113.281f, +152.344f,27.5095f,-113.281f, +156.25f,24.9361f,-113.281f, +160.156f,22.6206f,-113.281f, +164.063f,20.1136f,-113.281f, +167.969f,17.9862f,-113.281f, +171.875f,16.1252f,-113.281f, +175.781f,14.2991f,-113.281f, +179.688f,11.4262f,-113.281f, +183.594f,8.55749f,-113.281f, +187.5f,6.02067f,-113.281f, +191.406f,3.1883f,-113.281f, +195.313f,1.54808f,-113.281f, +199.219f,0.0223479f,-113.281f, +203.125f,-0.0807506f,-113.281f, +207.031f,-0.420855f,-113.281f, +210.938f,-0.531322f,-113.281f, +214.844f,-1.34393f,-113.281f, +218.75f,-2.28346f,-113.281f, +222.656f,-2.245f,-113.281f, +226.563f,-2.22932f,-113.281f, +230.469f,-1.47268f,-113.281f, +234.375f,-0.543695f,-113.281f, +238.281f,-0.391948f,-113.281f, +242.188f,-0.270077f,-113.281f, +246.094f,-0.650629f,-113.281f, +250.0f,0.111517f,-113.281f, +3.90625f,48.3887f,-117.188f, +7.8125f,48.004f,-117.188f, +11.7188f,46.8723f,-117.188f, +15.625f,45.5005f,-117.188f, +19.5313f,43.3644f,-117.188f, +23.4375f,42.3352f,-117.188f, +27.3438f,41.1562f,-117.188f, +31.25f,39.1736f,-117.188f, +35.1563f,38.0627f,-117.188f, +39.0625f,36.4728f,-117.188f, +42.9688f,34.8001f,-117.188f, +46.875f,32.5103f,-117.188f, +50.7813f,31.6328f,-117.188f, +54.6875f,31.6106f,-117.188f, +58.5938f,32.3004f,-117.188f, +62.5f,32.696f,-117.188f, +66.4063f,33.3795f,-117.188f, +70.3125f,33.9696f,-117.188f, +74.2188f,34.9211f,-117.188f, +78.125f,36.7686f,-117.188f, +82.0313f,37.7676f,-117.188f, +85.9375f,37.8174f,-117.188f, +89.8438f,38.2878f,-117.188f, +93.75f,39.6151f,-117.188f, +97.6563f,39.7422f,-117.188f, +101.563f,40.9611f,-117.188f, +105.469f,40.8932f,-117.188f, +109.375f,40.6603f,-117.188f, +113.281f,40.2935f,-117.188f, +117.188f,39.8681f,-117.188f, +121.094f,39.0965f,-117.188f, +125.0f,37.1333f,-117.188f, +128.906f,35.5222f,-117.188f, +132.813f,33.9068f,-117.188f, +136.719f,32.2618f,-117.188f, +140.625f,29.8657f,-117.188f, +144.531f,28.1704f,-117.188f, +148.438f,27.1495f,-117.188f, +152.344f,24.5217f,-117.188f, +156.25f,22.0419f,-117.188f, +160.156f,19.9238f,-117.188f, +164.063f,17.6875f,-117.188f, +167.969f,15.5636f,-117.188f, +171.875f,13.5497f,-117.188f, +175.781f,11.2761f,-117.188f, +179.688f,8.95864f,-117.188f, +183.594f,7.04623f,-117.188f, +187.5f,4.83635f,-117.188f, +191.406f,2.76046f,-117.188f, +195.313f,0.190119f,-117.188f, +199.219f,-0.558379f,-117.188f, +203.125f,-1.03303f,-117.188f, +207.031f,-2.17563f,-117.188f, +210.938f,-1.91155f,-117.188f, +214.844f,-3.00018f,-117.188f, +218.75f,-4.26691f,-117.188f, +222.656f,-5.15855f,-117.188f, +226.563f,-3.46348f,-117.188f, +230.469f,-2.16077f,-117.188f, +234.375f,-1.47785f,-117.188f, +238.281f,-1.78424f,-117.188f, +242.188f,-1.00317f,-117.188f, +246.094f,-1.97981f,-117.188f, +250.0f,-2.29372f,-117.188f, +}; + +btScalar Landscape03Nml[] = { +-0.0301669f,0.913898f,-0.404822f, +0.0925944f,0.901922f,-0.421856f, +0.0550338f,0.955133f,-0.291019f, +0.163554f,0.924847f,-0.343379f, +-0.00160556f,0.985516f,-0.169577f, +0.0975687f,0.967908f,-0.23159f, +-0.0718641f,0.997324f,-0.0134097f, +0.108884f,0.992259f,0.0597208f, +-0.0649193f,0.987727f,0.142057f, +-0.0923076f,0.995503f,-0.0212622f, +-0.212176f,0.966905f,0.141687f, +-0.135924f,0.982555f,0.126925f, +-0.248136f,0.950917f,0.184892f, +-0.114969f,0.937595f,0.328173f, +-0.0596382f,0.954355f,0.292661f, +-0.0673134f,0.931098f,0.358506f, +-0.100514f,0.963905f,0.246544f, +-0.237357f,0.960335f,0.146353f, +-0.210275f,0.964506f,0.159726f, +-0.243879f,0.969407f,-0.027797f, +-0.0995316f,0.963559f,0.248291f, +0.0232774f,0.986211f,0.163848f, +-0.0780955f,0.939808f,0.33266f, +0.0143543f,0.937354f,0.348083f, +-0.242603f,0.911487f,0.332166f, +-0.217791f,0.899583f,0.378572f, +-0.259297f,0.919695f,0.294833f, +-0.235372f,0.900382f,0.365939f, +0.0548314f,0.924698f,0.376733f, +0.17577f,0.83537f,0.520828f, +0.183628f,0.8685f,0.460423f, +0.206319f,0.791195f,0.57571f, +0.291585f,0.831097f,0.473557f, +0.258977f,0.806104f,0.532097f, +0.406441f,0.807616f,0.427274f, +0.279416f,0.89888f,0.337552f, +0.161449f,0.944511f,0.286064f, +-0.0153595f,0.999467f,0.0288015f, +0.0344442f,0.986316f,0.16123f, +0.0228147f,0.999694f,-0.00950936f, +0.221267f,0.961345f,0.163882f, +0.262982f,0.961437f,0.0804904f, +0.292545f,0.943495f,0.155677f, +0.287728f,0.952627f,0.0985627f, +0.338791f,0.935036f,0.104535f, +0.332042f,0.939101f,0.0885263f, +0.395865f,0.914692f,0.0814219f, +0.342439f,0.937891f,0.0556409f, +0.24643f,0.967531f,-0.0561722f, +0.155524f,0.980084f,-0.12348f, +0.12756f,0.989194f,-0.0722747f, +0.141529f,0.984734f,-0.10133f, +0.0842668f,0.99539f,-0.0458028f, +0.00840046f,0.967846f,-0.251403f, +0.0723924f,0.995277f,-0.0646756f, +0.161395f,0.974624f,-0.155111f, +0.168526f,0.983485f,0.0660013f, +0.32936f,0.929371f,0.166709f, +0.334018f,0.924548f,0.18342f, +0.39263f,0.883836f,0.254313f, +0.373683f,0.906029f,0.198675f, +0.318503f,0.931732f,0.174444f, +0.214891f,0.969497f,0.117891f, +0.248914f,0.936934f,0.245348f, +0.199074f,0.96113f,0.19131f, +0.293417f,0.893252f,0.340597f, +0.339667f,0.873015f,0.349959f, +0.354613f,0.873548f,0.333412f, +0.457963f,0.824157f,0.333219f, +0.455319f,0.825254f,0.334127f, +0.52695f,0.805593f,0.270821f, +0.439193f,0.858556f,0.264557f, +0.401282f,0.908751f,0.114652f, +0.249111f,0.965853f,-0.0712114f, +0.0897089f,0.991664f,0.0924929f, +0.0376765f,0.979393f,-0.19842f, +-0.126991f,0.990951f,0.0434627f, +-0.217753f,0.933113f,-0.286154f, +-0.167574f,0.97576f,-0.140749f, +-0.203937f,0.914317f,-0.349907f, +-0.0608955f,0.980207f,-0.188379f, +-0.0120075f,0.947447f,-0.319686f, +0.167601f,0.980952f,-0.0982003f, +0.212052f,0.945824f,-0.245868f, +0.218606f,0.972968f,-0.0744646f, +0.212851f,0.953898f,-0.211596f, +0.171647f,0.974969f,-0.141323f, +0.199197f,0.967793f,-0.153938f, +0.200412f,0.972091f,-0.121957f, +0.23265f,0.963849f,-0.129883f, +0.296235f,0.953212f,-0.060261f, +0.314311f,0.946698f,-0.0705058f, +0.404868f,0.912189f,-0.0631982f, +0.403087f,0.912504f,-0.0696997f, +0.463227f,0.884095f,-0.0616207f, +0.39479f,0.897802f,-0.195171f, +0.35121f,0.926619f,-0.13427f, +0.220773f,0.898508f,-0.379398f, +0.189824f,0.93595f,-0.296589f, +0.0483901f,0.855509f,-0.515522f, +0.0904515f,0.884685f,-0.457329f, +0.120283f,0.865017f,-0.487112f, +0.203986f,0.900002f,-0.385209f, +0.248454f,0.881227f,-0.402131f, +0.178575f,0.929214f,-0.323532f, +0.0792679f,0.824417f,-0.560404f, +0.115378f,0.950213f,-0.289454f, +0.0725597f,0.807744f,-0.585051f, +0.0327706f,0.953791f,-0.298679f, +0.0099385f,0.78612f,-0.617994f, +0.0403637f,0.952173f,-0.302881f, +0.215114f,0.87002f,-0.443611f, +0.182967f,0.972742f,-0.142465f, +0.292542f,0.923312f,-0.248827f, +0.159782f,0.983577f,-0.0839386f, +0.255356f,0.959339f,-0.120256f, +0.180088f,0.983508f,0.0167535f, +0.210595f,0.975243f,-0.0674566f, +0.305089f,0.951559f,0.0381592f, +0.342154f,0.939613f,0.00764387f, +0.44387f,0.894627f,0.0512048f, +0.377004f,0.921573f,-0.0925792f, +0.197535f,0.978807f,-0.0540106f, +0.128094f,0.953819f,-0.271702f, +0.10228f,0.991256f,-0.0833686f, +0.111348f,0.971755f,-0.208074f, +0.120727f,0.982203f,-0.143886f, +0.131919f,0.971754f,-0.195681f, +-0.118481f,0.971727f,-0.204228f, +-0.131824f,0.977685f,-0.163569f, +-0.0725384f,0.997366f,-0.000133281f, +-0.204047f,0.978951f,0.00446862f, +-0.227431f,0.966677f,0.117515f, +-0.137601f,0.963906f,0.227929f, +-0.242399f,0.965055f,0.0995586f, +-0.153062f,0.97808f,0.141178f, +-0.129415f,0.948353f,0.289617f, +-0.22442f,0.902886f,0.366649f, +-0.173979f,0.92147f,0.34731f, +-0.0318649f,0.93595f,0.350687f, +-0.176397f,0.955508f,0.236408f, +-0.254551f,0.956811f,0.140418f, +-0.0162894f,0.984782f,0.173032f, +0.167302f,0.961803f,0.216667f, +0.267797f,0.948626f,0.168505f, +0.412955f,0.869957f,0.269525f, +0.258065f,0.893814f,0.366742f, +0.124905f,0.932115f,0.339941f, +0.234805f,0.927845f,0.289777f, +0.325979f,0.90761f,0.264542f, +0.401458f,0.890435f,0.214374f, +0.44845f,0.886659f,0.112823f, +0.337292f,0.940965f,0.0286028f, +0.110729f,0.992952f,-0.0422648f, +0.0165495f,0.996512f,-0.0817925f, +0.0843804f,0.994583f,-0.0606957f, +0.1131f,0.990749f,-0.0749933f, +0.241223f,0.970417f,0.0100747f, +0.396578f,0.902933f,0.165644f, +0.324808f,0.936808f,0.129963f, +0.0728626f,0.997053f,0.0240034f, +0.167633f,0.975741f,0.140815f, +0.474631f,0.846984f,0.239465f, +0.567824f,0.786908f,0.24156f, +0.402496f,0.873451f,0.274008f, +0.0459982f,0.950641f,0.306865f, +-0.0582337f,0.962437f,0.265188f, +0.030037f,0.970181f,0.240514f, +-0.0533502f,0.992438f,0.110548f, +0.0995416f,0.988544f,0.11346f, +0.255626f,0.959556f,0.11793f, +0.26735f,0.961569f,0.0625254f, +0.18836f,0.981833f,-0.0228855f, +0.278864f,0.958778f,-0.0545789f, +0.407529f,0.909061f,-0.086769f, +0.427129f,0.902011f,-0.0627458f, +0.408272f,0.912551f,-0.0237565f, +0.36375f,0.922794f,-0.127037f, +0.266363f,0.919721f,-0.28838f, +0.0788795f,0.927162f,-0.366263f, +0.0391177f,0.978258f,-0.20367f, +0.0160429f,0.996725f,-0.0792609f, +0.0608773f,0.998141f,0.00292939f, +0.025245f,0.998361f,-0.0513526f, +0.140845f,0.988959f,-0.046063f, +0.138979f,0.986427f,-0.0874468f, +0.128983f,0.987322f,-0.0925141f, +0.303074f,0.948227f,-0.0949297f, +0.392011f,0.918105f,-0.0584085f, +0.26566f,0.960779f,0.0795528f, +0.166068f,0.98603f,-0.0129125f, +0.262845f,0.962536f,-0.0666132f, +-0.104783f,0.989703f,0.0975085f, +-0.153604f,0.984769f,0.0814646f, +-0.17021f,0.98292f,0.0699758f, +-0.192965f,0.974203f,0.117018f, +-0.286836f,0.952199f,0.105086f, +-0.195248f,0.969752f,0.146488f, +-0.150662f,0.967412f,0.203504f, +-0.264752f,0.950334f,0.163619f, +-0.315905f,0.913283f,0.257134f, +-0.224744f,0.91965f,0.322078f, +-0.108929f,0.947464f,0.300743f, +0.0128823f,0.944776f,0.327463f, +-0.0190359f,0.964202f,0.264485f, +-0.187346f,0.97974f,0.0707926f, +-0.0647113f,0.997854f,-0.0100069f, +0.163923f,0.98566f,0.0400324f, +0.299244f,0.952147f,0.0622031f, +0.300231f,0.948028f,0.105378f, +0.182306f,0.951449f,0.248009f, +0.15023f,0.937487f,0.313924f, +0.264855f,0.926023f,0.268948f, +0.322593f,0.919374f,0.225135f, +0.43093f,0.873406f,0.22685f, +0.536094f,0.828094f,0.163899f, +0.40435f,0.914491f,0.0144028f, +0.203744f,0.975451f,-0.0835749f, +0.102706f,0.983162f,-0.151145f, +0.0912494f,0.98262f,-0.161654f, +0.0714052f,0.991795f,-0.106042f, +0.113839f,0.992199f,-0.0508211f, +0.266818f,0.963676f,0.0116937f, +0.379059f,0.920849f,0.091386f, +0.155245f,0.98775f,0.0158058f, +0.135484f,0.989724f,-0.0457313f, +0.394833f,0.917954f,-0.0383045f, +0.510875f,0.847518f,0.143943f, +0.369724f,0.884704f,0.283906f, +0.16927f,0.926331f,0.336538f, +-0.0368298f,0.974452f,0.221557f, +0.0247064f,0.955492f,0.293981f, +0.0101397f,0.960739f,0.27727f, +0.120365f,0.954563f,0.272621f, +0.285189f,0.933274f,0.218327f, +0.27356f,0.947401f,0.16612f, +0.298803f,0.939862f,0.165455f, +0.344494f,0.938521f,0.0223999f, +0.423232f,0.90602f,-0.00171397f, +0.428479f,0.903517f,-0.00795118f, +0.445837f,0.889867f,-0.0967762f, +0.420806f,0.885752f,-0.195872f, +0.361482f,0.916002f,-0.173987f, +0.0888846f,0.94798f,-0.305668f, +-0.104291f,0.938663f,-0.328687f, +-0.0525896f,0.969771f,-0.238281f, +0.0233793f,0.980465f,-0.1953f, +0.0772242f,0.980658f,-0.179852f, +0.158397f,0.962723f,-0.219259f, +0.207852f,0.94171f,-0.264536f, +0.167471f,0.922973f,-0.346518f, +0.273321f,0.900673f,-0.337764f, +0.244245f,0.947327f,-0.207161f, +0.179974f,0.982676f,-0.0442354f, +0.256056f,0.966655f,0.00369743f, +0.311224f,0.950239f,-0.0136096f, +-0.114346f,0.96184f,0.248574f, +-0.136601f,0.952445f,0.272377f, +-0.118024f,0.9521f,0.282091f, +-0.208962f,0.956737f,0.20246f, +-0.278994f,0.940284f,0.195009f, +-0.257672f,0.939434f,0.225986f, +-0.195307f,0.931658f,0.306381f, +-0.244185f,0.930201f,0.274044f, +-0.297894f,0.926606f,0.229479f, +-0.247712f,0.954952f,0.163421f, +-0.130651f,0.964187f,0.230812f, +-0.0752954f,0.962878f,0.259223f, +0.102408f,0.945859f,0.308f, +-0.0116154f,0.986031f,0.166158f, +0.0110135f,0.994405f,0.105056f, +0.0951503f,0.992756f,0.0733669f, +0.243797f,0.961487f,0.12691f, +0.260872f,0.955085f,0.140567f, +0.0581113f,0.983556f,0.170998f, +0.136043f,0.955475f,0.261839f, +0.341254f,0.920705f,0.189336f, +0.362462f,0.927476f,0.0917096f, +0.434756f,0.897441f,0.0747436f, +0.56712f,0.819757f,0.0798336f, +0.532941f,0.840799f,0.0950342f, +0.285812f,0.957415f,-0.0408404f, +0.105292f,0.985973f,-0.129498f, +0.0183827f,0.988838f,-0.147857f, +0.00614806f,0.993133f,-0.116825f, +0.099955f,0.989102f,-0.108098f, +0.238003f,0.969438f,-0.0595305f, +0.37769f,0.925502f,0.0282058f, +0.22782f,0.973089f,-0.0345812f, +0.169707f,0.981804f,-0.085208f, +0.345833f,0.936168f,-0.0631539f, +0.390375f,0.920563f,0.0130624f, +0.292594f,0.949139f,0.116291f, +0.162356f,0.962761f,0.216174f, +-0.0222207f,0.972687f,0.231055f, +-0.0543181f,0.955402f,0.290271f, +0.0573363f,0.941579f,0.331875f, +0.0971816f,0.964596f,0.245172f, +0.31345f,0.917083f,0.246388f, +0.307384f,0.923753f,0.228463f, +0.331585f,0.921188f,0.203628f, +0.40966f,0.902178f,0.135106f, +0.421265f,0.901117f,0.102585f, +0.477285f,0.878068f,0.0345826f, +0.547818f,0.833857f,-0.0676607f, +0.41388f,0.899953f,-0.13707f, +0.336726f,0.938017f,-0.0820957f, +0.267129f,0.960427f,-0.0788775f, +-0.0301028f,0.966021f,-0.256704f, +-0.102361f,0.925067f,-0.36575f, +-0.0109209f,0.925593f,-0.378364f, +0.0802595f,0.925005f,-0.371381f, +0.178475f,0.901809f,-0.393558f, +0.234643f,0.9031f,-0.359657f, +0.21073f,0.932522f,-0.29325f, +0.145492f,0.962309f,-0.22977f, +0.0986234f,0.992893f,-0.0666048f, +0.0609779f,0.998071f,0.0116837f, +0.208222f,0.976086f,0.0624398f, +0.291247f,0.954621f,0.0622453f, +-0.144182f,0.940028f,0.309126f, +-0.205006f,0.91833f,0.33859f, +-0.12423f,0.88968f,0.43936f, +-0.080186f,0.900963f,0.426423f, +-0.276852f,0.915664f,0.291398f, +-0.294009f,0.912157f,0.285532f, +-0.229314f,0.935643f,0.268306f, +-0.167187f,0.934278f,0.314918f, +-0.22242f,0.937858f,0.266367f, +-0.260643f,0.947201f,0.186748f, +-0.191964f,0.952786f,0.235261f, +-0.0626162f,0.968356f,0.24159f, +0.113658f,0.975135f,0.190246f, +0.0609991f,0.983083f,0.172707f, +0.00661942f,0.987494f,0.157516f, +0.132957f,0.988179f,0.0763221f, +0.229975f,0.973129f,-0.011475f, +0.267568f,0.962445f,0.0458956f, +0.0512446f,0.996521f,0.0657221f, +0.10251f,0.994623f,0.0147167f, +0.405413f,0.913613f,0.0308412f, +0.422693f,0.905322f,0.0415123f, +0.446493f,0.894763f,-0.00665318f, +0.517619f,0.855611f,0.00103599f, +0.493254f,0.857934f,0.143698f, +0.391227f,0.901201f,0.186488f, +0.212519f,0.97466f,0.0698119f, +0.0889638f,0.99521f,-0.0405254f, +0.0684633f,0.989971f,-0.123576f, +0.0764325f,0.983592f,-0.163418f, +0.104882f,0.990961f,-0.0836475f, +0.31755f,0.948184f,0.0104726f, +0.297752f,0.954642f,-0.00148102f, +0.157954f,0.986909f,-0.0325777f, +0.331713f,0.943333f,0.00940707f, +0.320973f,0.946975f,0.014661f, +0.220471f,0.961455f,0.164306f, +0.0647366f,0.977455f,0.200976f, +-0.0349474f,0.961311f,0.273238f, +-0.125874f,0.956852f,0.261896f, +0.0785055f,0.963364f,0.256449f, +0.211427f,0.962249f,0.171395f, +0.267083f,0.952021f,0.149409f, +0.340455f,0.905998f,0.251512f, +0.343062f,0.921876f,0.180149f, +0.420249f,0.886024f,0.195835f, +0.477229f,0.85754f,0.192034f, +0.564804f,0.822942f,0.0613434f, +0.583206f,0.811559f,-0.0352364f, +0.433319f,0.897576f,-0.0811897f, +0.291913f,0.950865f,-0.103166f, +0.268144f,0.961121f,-0.065914f, +0.14681f,0.986926f,-0.0665068f, +0.0393351f,0.975019f,-0.218612f, +0.042722f,0.945279f,-0.323454f, +0.104892f,0.926937f,-0.360257f, +0.188153f,0.928382f,-0.320477f, +0.104479f,0.956869f,-0.271082f, +0.039684f,0.98773f,-0.151046f, +0.0798596f,0.996734f,-0.0120106f, +0.0027229f,0.999081f,-0.0427778f, +0.0156228f,0.999853f,-0.00700924f, +0.224664f,0.97266f,0.058815f, +0.342188f,0.939164f,0.029646f, +-0.199093f,0.881081f,0.429019f, +-0.240385f,0.861587f,0.447083f, +-0.200309f,0.881599f,0.427386f, +-0.0492643f,0.888913f,0.455419f, +-0.146605f,0.886582f,0.438724f, +-0.194932f,0.91844f,0.344193f, +-0.212452f,0.949737f,0.229922f, +-0.231229f,0.946978f,0.223083f, +-0.22018f,0.943947f,0.245937f, +-0.155384f,0.954263f,0.255419f, +-0.222552f,0.970336f,0.0944332f, +0.0103498f,0.996133f,0.0872447f, +0.133012f,0.991064f,-0.00997971f, +0.0530236f,0.995787f,0.0748093f, +0.0840279f,0.994917f,0.0554967f, +0.25995f,0.964887f,-0.0376792f, +0.277109f,0.958722f,-0.0637373f, +0.172083f,0.982525f,-0.0709421f, +0.0951551f,0.994032f,-0.0533466f, +0.177084f,0.970483f,-0.163718f, +0.336303f,0.91861f,-0.207499f, +0.381503f,0.916211f,-0.122527f, +0.437128f,0.898759f,-0.0339342f, +0.471093f,0.8784f,0.0805223f, +0.407138f,0.905658f,0.118413f, +0.402844f,0.901612f,0.157519f, +0.327464f,0.936685f,0.124046f, +0.19809f,0.980129f,0.0103207f, +0.123868f,0.987803f,-0.0943524f, +0.0527864f,0.989238f,-0.136459f, +0.072462f,0.988213f,-0.134849f, +0.248671f,0.959688f,-0.131005f, +0.280617f,0.958078f,0.0577984f, +0.169552f,0.981657f,0.0871871f, +0.315169f,0.946806f,0.0650122f, +0.205308f,0.973708f,0.0986977f, +0.0950386f,0.972165f,0.214158f, +0.053629f,0.964124f,0.259978f, +-0.0859535f,0.951705f,0.294738f, +-0.0564482f,0.948883f,0.31054f, +0.154105f,0.958817f,0.238582f, +0.276457f,0.946116f,0.168629f, +0.211552f,0.972531f,0.0971047f, +0.294402f,0.951062f,0.0938527f, +0.390766f,0.916003f,0.0907783f, +0.406836f,0.907458f,0.104904f, +0.487803f,0.868421f,0.0888414f, +0.60401f,0.790886f,0.0983406f, +0.637938f,0.762279f,0.109387f, +0.4874f,0.873178f,0.00117935f, +0.336067f,0.93258f,-0.131735f, +0.229766f,0.943375f,-0.239272f, +0.152224f,0.966237f,-0.207882f, +0.121199f,0.969969f,-0.210883f, +0.121425f,0.965511f,-0.230314f, +0.0800447f,0.963578f,-0.255166f, +0.0996944f,0.981315f,-0.164563f, +0.0506382f,0.996401f,-0.0679735f, +-0.049503f,0.998346f,-0.0292297f, +0.050214f,0.998168f,0.0337586f, +0.113307f,0.993459f,0.014176f, +-0.000723347f,0.991208f,-0.132313f, +0.134265f,0.980729f,-0.141929f, +0.363008f,0.931437f,-0.0254801f, +-0.23486f,0.827656f,0.509732f, +-0.18483f,0.851106f,0.491383f, +-0.113579f,0.917253f,0.381767f, +-0.0885467f,0.926234f,0.366401f, +-0.119506f,0.895756f,0.428181f, +-0.107176f,0.917761f,0.382398f, +-0.0925542f,0.950614f,0.296253f, +-0.166069f,0.978511f,0.12222f, +-0.250375f,0.968134f,-0.00545859f, +-0.116612f,0.99254f,0.0355817f, +-0.0441586f,0.99869f,-0.0258397f, +0.0237183f,0.990591f,-0.134786f, +0.114156f,0.992737f,-0.0379611f, +0.0216237f,0.999568f,0.0199155f, +0.13918f,0.98521f,-0.0999564f, +0.240654f,0.960885f,-0.137059f, +0.249305f,0.964708f,-0.0847689f, +0.222546f,0.966381f,-0.128771f, +0.148234f,0.971026f,-0.187443f, +0.258813f,0.946284f,-0.193812f, +0.386195f,0.898799f,-0.207397f, +0.325896f,0.902531f,-0.281478f, +0.250321f,0.93543f,-0.249621f, +0.351402f,0.936022f,0.01949f, +0.42413f,0.889134f,0.171914f, +0.422963f,0.898638f,0.116411f, +0.393976f,0.918547f,0.0324739f, +0.283361f,0.957155f,-0.0596804f, +0.186222f,0.979389f,-0.0782236f, +0.100294f,0.99243f,-0.0708823f, +0.151138f,0.983442f,-0.0999959f, +0.115742f,0.982035f,-0.149033f, +0.0920961f,0.993962f,0.0596489f, +0.180728f,0.97583f,0.122852f, +0.267575f,0.959234f,0.0909572f, +0.204025f,0.959594f,0.193785f, +0.0830398f,0.98516f,0.150214f, +0.000808908f,0.987078f,0.160239f, +-0.115905f,0.961815f,0.247948f, +-0.0397732f,0.972025f,0.231484f, +0.185186f,0.964166f,0.189976f, +0.333936f,0.928543f,0.162155f, +0.358439f,0.932281f,0.0487095f, +0.30639f,0.946624f,-0.100142f, +0.389119f,0.921183f,-0.00273847f, +0.418957f,0.907889f,-0.0145855f, +0.498018f,0.86538f,-0.05563f, +0.565975f,0.823958f,-0.0276542f, +0.61235f,0.789736f,0.0366549f, +0.580326f,0.809292f,0.0909313f, +0.472624f,0.880866f,0.0264734f, +0.31167f,0.948991f,-0.0477351f, +0.149242f,0.981946f,-0.116226f, +0.114121f,0.974963f,-0.190851f, +0.0836789f,0.981905f,-0.169884f, +0.0779767f,0.990421f,-0.113957f, +0.0144442f,0.982901f,-0.183565f, +-0.021091f,0.988398f,-0.150415f, +-0.0454971f,0.990828f,-0.127242f, +-0.0180398f,0.984723f,-0.173189f, +0.129331f,0.988095f,-0.0833159f, +0.183553f,0.978578f,-0.0932403f, +0.123107f,0.958699f,-0.256402f, +0.189949f,0.953063f,-0.235775f, +-0.0544616f,0.84489f,0.53216f, +-0.0113297f,0.890886f,0.454085f, +-0.0462225f,0.938549f,0.342038f, +-0.128436f,0.915911f,0.380277f, +-0.159132f,0.90887f,0.385529f, +-0.0486608f,0.932565f,0.357708f, +0.0612592f,0.9505f,0.304627f, +0.0533898f,0.988914f,0.138559f, +-0.104607f,0.992177f,-0.0681298f, +-0.180998f,0.963403f,-0.197725f, +0.0184775f,0.993878f,-0.108929f, +-0.0166014f,0.988229f,-0.152078f, +-0.0077365f,0.996975f,-0.0773314f, +0.0579939f,0.995726f,-0.071872f, +0.284878f,0.950639f,-0.123003f, +0.233331f,0.946766f,-0.221789f, +0.274724f,0.943287f,-0.186374f, +0.284827f,0.926731f,-0.245036f, +0.143673f,0.947988f,-0.284037f, +0.183874f,0.951741f,-0.245725f, +0.373811f,0.924384f,-0.0760214f, +0.370847f,0.928183f,0.0307872f, +0.230777f,0.972874f,0.0160428f, +0.116854f,0.992434f,-0.0376857f, +0.311514f,0.945104f,0.0986779f, +0.493623f,0.85792f,0.14251f, +0.47336f,0.879733f,0.0447334f, +0.299829f,0.953139f,0.0403417f, +0.142324f,0.985386f,0.0935816f, +0.0780161f,0.991843f,0.100799f, +0.120483f,0.987279f,0.10375f, +0.113666f,0.977351f,0.178507f, +0.020827f,0.987302f,0.157484f, +0.18308f,0.973453f,0.137371f, +0.268344f,0.949436f,0.162981f, +0.178652f,0.97403f,0.139099f, +0.140521f,0.985536f,0.0947243f, +-0.0588959f,0.995353f,0.0761881f, +-0.17043f,0.974748f,0.144293f, +0.0194468f,0.992819f,0.118038f, +0.23167f,0.972512f,0.0234243f, +0.390625f,0.920274f,-0.0225152f, +0.45457f,0.886543f,-0.086066f, +0.307368f,0.941264f,-0.13981f, +0.289942f,0.953608f,-0.0810322f, +0.455218f,0.890309f,-0.0112281f, +0.513837f,0.856124f,-0.0549855f, +0.546925f,0.836241f,-0.0396788f, +0.583367f,0.812208f,-0.00110721f, +0.552934f,0.832422f,0.0365798f, +0.448406f,0.891004f,0.0710176f, +0.325547f,0.934833f,0.141795f, +0.239603f,0.963586f,0.118709f, +0.230453f,0.97295f,0.0160981f, +0.0486317f,0.9909f,-0.125509f, +0.0743177f,0.991871f,-0.103291f, +0.139517f,0.9837f,-0.11344f, +-0.0210587f,0.976395f,-0.214963f, +0.00854959f,0.97326f,-0.229548f, +0.0184659f,0.95097f,-0.308733f, +0.0120962f,0.95636f,-0.291939f, +0.153044f,0.979201f,-0.1332f, +0.190748f,0.981634f,-0.00308124f, +0.151842f,0.988041f,0.0268087f, +0.0319983f,0.964154f,0.263409f, +0.0761375f,0.979983f,0.183946f, +-0.0471561f,0.98918f,0.13892f, +-0.184804f,0.965808f,0.181831f, +-0.118202f,0.977652f,0.173852f, +-0.00263192f,0.986244f,0.165277f, +0.113935f,0.977488f,0.177586f, +0.213178f,0.965311f,0.150764f, +0.0917926f,0.995582f,-0.0197448f, +-0.112968f,0.973922f,-0.196759f, +-0.0750323f,0.977001f,-0.199598f, +0.0257774f,0.985322f,-0.168747f, +0.042721f,0.964979f,-0.258825f, +0.0821835f,0.934135f,-0.34733f, +0.254423f,0.923351f,-0.287563f, +0.255965f,0.951062f,-0.173101f, +0.240055f,0.959513f,-0.147338f, +0.319995f,0.939284f,-0.123892f, +0.15271f,0.974885f,-0.162111f, +0.132954f,0.978157f,-0.159787f, +0.156062f,0.978958f,-0.131476f, +0.237325f,0.969005f,0.0685979f, +0.280555f,0.951122f,0.129056f, +0.254605f,0.966124f,0.0421956f, +0.282663f,0.955227f,-0.087427f, +0.484968f,0.871846f,-0.0684877f, +0.483506f,0.87515f,-0.0182894f, +0.210764f,0.97671f,0.0402119f, +0.0804806f,0.985666f,0.148275f, +0.143859f,0.967897f,0.206108f, +0.0874346f,0.987357f,0.132215f, +0.0878227f,0.985433f,0.145635f, +0.118466f,0.990277f,0.0729134f, +0.170426f,0.983396f,-0.0623508f, +0.249461f,0.967984f,-0.0278496f, +0.240586f,0.970589f,0.00866192f, +0.158755f,0.987312f,0.00339798f, +-0.0496588f,0.997869f,0.0423253f, +-0.174436f,0.984473f,-0.0196346f, +0.0953847f,0.991998f,-0.0827112f, +0.301757f,0.941321f,-0.151184f, +0.416386f,0.897492f,-0.145363f, +0.439988f,0.889223f,-0.125274f, +0.313047f,0.948071f,-0.0562344f, +0.243151f,0.96888f,-0.0463665f, +0.428373f,0.903467f,-0.0156432f, +0.536849f,0.842847f,-0.0374461f, +0.521753f,0.850621f,-0.0649361f, +0.537565f,0.842885f,-0.02384f, +0.530522f,0.843125f,0.087673f, +0.408082f,0.90082f,0.148295f, +0.350282f,0.920762f,0.171756f, +0.275878f,0.960222f,0.0431791f, +0.279727f,0.959242f,0.0400889f, +0.199403f,0.977085f,0.0744484f, +0.0837631f,0.994427f,-0.0640234f, +0.142714f,0.98022f,-0.137117f, +0.0724844f,0.974795f,-0.211f, +0.0199047f,0.956284f,-0.29176f, +0.0419923f,0.973015f,-0.226887f, +-0.0571486f,0.988577f,-0.139464f, +-0.0620153f,0.996095f,-0.0628396f, +0.00941635f,0.995205f,0.097359f, +0.0452536f,0.980521f,0.191132f, +0.238692f,0.970551f,0.032497f, +0.18188f,0.979621f,-0.0852148f, +-0.0338772f,0.991689f,-0.124115f, +-0.215207f,0.972977f,-0.0836781f, +-0.127875f,0.990711f,-0.0462653f, +-0.0382254f,0.999079f,-0.0194842f, +0.0717625f,0.997386f,-0.00848587f, +0.235337f,0.971913f,0.00129577f, +0.258073f,0.965901f,-0.0208375f, +0.00563659f,0.988134f,-0.153488f, +-0.0963466f,0.971245f,-0.217715f, +0.0933449f,0.976181f,-0.19585f, +0.172697f,0.943118f,-0.284084f, +0.114064f,0.91464f,-0.387844f, +0.105309f,0.920749f,-0.375675f, +0.0952503f,0.976152f,-0.195075f, +0.198665f,0.977736f,-0.0675672f, +0.327274f,0.944589f,-0.0253815f, +0.185125f,0.982311f,-0.0281882f, +0.161734f,0.983206f,-0.0845435f, +0.135269f,0.981463f,-0.135765f, +0.160555f,0.98307f,-0.0882893f, +0.258909f,0.96483f,-0.0454967f, +0.342126f,0.938267f,0.0510447f, +0.36458f,0.930989f,-0.0184394f, +0.461971f,0.885156f,-0.0555142f, +0.401049f,0.915892f,-0.0173601f, +0.179695f,0.981649f,0.0638365f, +-0.0160491f,0.998918f,0.0436388f, +0.112643f,0.989219f,0.093583f, +0.158223f,0.986353f,0.0455405f, +0.150051f,0.988439f,-0.0217303f, +0.238384f,0.964999f,-0.10932f, +0.283357f,0.938433f,-0.197616f, +0.1814f,0.953903f,-0.239086f, +0.147672f,0.981223f,-0.124073f, +0.0988803f,0.99502f,-0.0125399f, +-0.0367309f,0.999167f,-0.0177995f, +-0.0641669f,0.988893f,-0.134067f, +0.155868f,0.964972f,-0.211032f, +0.311449f,0.929937f,-0.195488f, +0.363438f,0.913854f,-0.181064f, +0.379108f,0.919625f,-0.102794f, +0.251516f,0.967833f,-0.00624272f, +0.239964f,0.970767f,0.0053561f, +0.444229f,0.895407f,-0.0301255f, +0.561208f,0.823627f,-0.0817525f, +0.529532f,0.843694f,-0.0881851f, +0.463417f,0.885698f,-0.0280076f, +0.42264f,0.895689f,0.138263f, +0.360725f,0.902736f,0.234403f, +0.374064f,0.893088f,0.249939f, +0.398158f,0.891769f,0.214982f, +0.241834f,0.965676f,0.0947983f, +0.124224f,0.988267f,0.0888664f, +0.239364f,0.964398f,0.112437f, +0.252174f,0.966402f,-0.0497516f, +0.205848f,0.974166f,-0.0928869f, +0.0402048f,0.980488f,-0.192421f, +-0.109787f,0.981783f,-0.155076f, +-0.172809f,0.983136f,-0.0598348f, +-0.119927f,0.992756f,0.00723519f, +-0.0378691f,0.997707f,0.0560999f, +-0.018583f,0.999146f,0.0369096f, +0.311296f,0.946614f,-0.0837655f, +0.23235f,0.967065f,-0.103921f, +-0.0472012f,0.997512f,-0.0523709f, +-0.280913f,0.95942f,-0.0245033f, +-0.168558f,0.985462f,0.0212842f, +-0.0297654f,0.999551f,-0.00345095f, +0.14783f,0.984722f,-0.0920209f, +0.234818f,0.942556f,-0.23759f, +0.226f,0.954601f,-0.194065f, +0.0915505f,0.991576f,-0.0916283f, +-0.0384295f,0.986109f,-0.161594f, +0.0699749f,0.969463f,-0.235043f, +0.242042f,0.947128f,-0.210628f, +0.200696f,0.954776f,-0.21937f, +0.0684629f,0.960296f,-0.270452f, +-0.0178037f,0.955193f,-0.295449f, +0.106419f,0.956511f,-0.271592f, +0.250177f,0.956337f,-0.151101f, +0.206468f,0.977841f,-0.0346042f, +0.226301f,0.972897f,-0.047521f, +0.19172f,0.975927f,-0.103973f, +0.110286f,0.969903f,-0.217085f, +0.124805f,0.979571f,-0.157684f, +0.230362f,0.972377f,0.0376307f, +0.390327f,0.9143f,0.108165f, +0.486088f,0.869528f,0.0874049f, +0.355552f,0.931184f,0.0804947f, +0.162837f,0.968115f,0.190362f, +0.0587916f,0.990094f,0.127507f, +0.122084f,0.99234f,0.0189101f, +0.227899f,0.973107f,0.0335246f, +0.245712f,0.968327f,-0.0443735f, +0.235392f,0.962107f,-0.137626f, +0.299512f,0.953154f,0.0423112f, +0.158421f,0.985528f,0.0603087f, +0.0139537f,0.99778f,0.0651181f, +0.05695f,0.991196f,0.119526f, +0.0853993f,0.993434f,0.0761332f, +0.0800124f,0.992698f,-0.0902652f, +0.152744f,0.965412f,-0.211303f, +0.298303f,0.938225f,-0.175354f, +0.346617f,0.918158f,-0.191946f, +0.306791f,0.939305f,-0.153575f, +0.213668f,0.966817f,-0.140039f, +0.269123f,0.94608f,-0.180294f, +0.462084f,0.866259f,-0.189928f, +0.547323f,0.828917f,-0.11547f, +0.492713f,0.870051f,0.0156307f, +0.377637f,0.925543f,0.0275792f, +0.309374f,0.94993f,0.0438272f, +0.339128f,0.933648f,0.115296f, +0.355844f,0.92275f,0.148012f, +0.387104f,0.898496f,0.207015f, +0.394935f,0.895155f,0.206698f, +0.187014f,0.981688f,0.0362499f, +0.286474f,0.957988f,0.0138101f, +0.315633f,0.944806f,-0.0878444f, +0.189054f,0.976628f,-0.102261f, +0.071001f,0.995263f,-0.066411f, +-0.121993f,0.990638f,-0.0612738f, +-0.195423f,0.978588f,-0.0646113f, +-0.134933f,0.988908f,-0.0620808f, +-0.0362027f,0.9885f,-0.146822f, +0.0247852f,0.975168f,-0.220074f, +0.236634f,0.970435f,-0.0475491f, +0.163622f,0.985347f,0.0481553f, +-0.110204f,0.98299f,0.146921f, +-0.274076f,0.953125f,0.128197f, +-0.127913f,0.990913f,0.0415925f, +0.0693505f,0.994264f,-0.081428f, +0.246728f,0.957329f,-0.15049f, +0.356012f,0.927656f,-0.112735f, +0.108926f,0.979602f,-0.168863f, +-0.0117435f,0.995074f,-0.0984399f, +0.0591802f,0.992813f,-0.104017f, +0.152983f,0.961405f,-0.228683f, +0.199436f,0.939216f,-0.279462f, +0.158919f,0.956661f,-0.244017f, +0.142246f,0.964436f,-0.222776f, +0.0928224f,0.948092f,-0.304146f, +0.072096f,0.927878f,-0.365849f, +0.0949024f,0.954182f,-0.28378f, +0.0839904f,0.981792f,-0.17038f, +0.207123f,0.975655f,-0.0720922f, +0.306863f,0.948734f,-0.075756f, +0.227677f,0.946857f,-0.22721f, +0.0209281f,0.957849f,-0.28651f, +0.0889558f,0.973432f,-0.210993f, +0.377519f,0.908654f,-0.178401f, +0.444767f,0.867771f,-0.22171f, +0.296477f,0.952876f,-0.0642486f, +0.049587f,0.998699f,0.0118749f, +0.185088f,0.975344f,0.120192f, +0.179316f,0.983776f,0.00553586f, +0.203508f,0.978758f,-0.0248474f, +0.30632f,0.951877f,-0.00993344f, +0.182507f,0.983075f,0.0159703f, +0.0804506f,0.991985f,0.0974322f, +0.170994f,0.963788f,0.204629f, +0.0962731f,0.986887f,0.12956f, +0.097797f,0.995201f,0.00337759f, +0.147003f,0.987459f,-0.0575677f, +0.218112f,0.972969f,-0.0758899f, +0.244949f,0.956598f,-0.157862f, +0.315584f,0.924587f,-0.213415f, +0.352441f,0.893692f,-0.277668f, +0.28482f,0.905458f,-0.31468f, +0.265138f,0.910445f,-0.317477f, +0.308383f,0.884493f,-0.350102f, +0.390084f,0.870652f,-0.299665f, +0.373263f,0.922794f,-0.0955261f, +0.378781f,0.918384f,0.114439f, +0.476669f,0.866105f,0.150494f, +0.353048f,0.93424f,-0.0505168f, +0.309942f,0.946077f,-0.0942048f, +0.298518f,0.948219f,-0.108479f, +0.350416f,0.935917f,-0.0356219f, +0.447907f,0.893892f,-0.0183155f, +0.280155f,0.95286f,-0.116492f, +0.270748f,0.951225f,-0.147871f, +0.374052f,0.922269f,-0.0974917f, +0.176754f,0.980223f,-0.0889943f, +0.0634799f,0.992926f,-0.100339f, +-0.11806f,0.977045f,-0.177329f, +-0.199746f,0.955239f,-0.218219f, +-0.0812223f,0.969857f,-0.229739f, +0.130179f,0.951543f,-0.278602f, +0.200559f,0.919086f,-0.339202f, +0.0174361f,0.999489f,0.0268061f, +0.0105554f,0.991703f,0.128113f, +-0.141198f,0.973013f,0.182506f, +-0.142313f,0.985833f,0.0887713f, +0.00597934f,0.99465f,-0.103131f, +0.213448f,0.959986f,-0.181295f, +0.150446f,0.953754f,-0.260228f, +0.244008f,0.968351f,-0.0525036f, +0.184758f,0.982743f,0.00893989f, +-0.00567918f,0.992902f,-0.118797f, +0.138037f,0.98016f,-0.142241f, +0.21929f,0.962205f,-0.16147f, +0.269703f,0.95408f,-0.13035f, +0.150911f,0.956731f,-0.24878f, +0.180021f,0.944452f,-0.27496f, +0.119147f,0.92214f,-0.368051f, +0.0669033f,0.930661f,-0.359714f, +-0.0113587f,0.942765f,-0.333265f, +0.0142182f,0.972628f,-0.231934f, +0.163413f,0.959027f,-0.231437f, +0.324001f,0.919871f,-0.221046f, +0.291919f,0.93701f,-0.19182f, +0.107512f,0.968299f,-0.225473f, +0.0749887f,0.923898f,-0.375218f, +0.415609f,0.849812f,-0.324172f, +0.314994f,0.92041f,-0.231569f, +0.136459f,0.990645f,0.000905767f, +0.00734966f,0.998995f,0.0442195f, +0.0805668f,0.996634f,0.0151596f, +0.266119f,0.962333f,0.0556322f, +0.269187f,0.962624f,-0.0298845f, +0.209195f,0.975524f,-0.0677535f, +0.153299f,0.985902f,0.0670637f, +0.0587395f,0.996349f,0.0619523f, +0.20348f,0.97612f,0.0760684f, +0.225978f,0.971688f,-0.0689656f, +0.204562f,0.957442f,-0.203617f, +0.164418f,0.955123f,-0.246386f, +0.1725f,0.961839f,-0.212392f, +0.288653f,0.947463f,-0.137816f, +0.355829f,0.918236f,-0.173863f, +0.453757f,0.873536f,-0.176182f, +0.355645f,0.881401f,-0.310884f, +0.238917f,0.864251f,-0.442706f, +0.251593f,0.863453f,-0.437206f, +0.231383f,0.92049f,-0.314896f, +0.219172f,0.968344f,-0.119471f, +0.254773f,0.966196f,-0.0394394f, +0.482542f,0.873342f,0.0665443f, +0.470019f,0.880685f,0.0589576f, +0.359563f,0.932576f,-0.0318683f, +0.336062f,0.937393f,-0.0914179f, +0.320744f,0.932455f,-0.166285f, +0.428106f,0.887361f,-0.171217f, +0.372336f,0.918652f,-0.132074f, +0.247289f,0.941171f,-0.230314f, +0.287477f,0.950239f,-0.120008f, +0.121799f,0.989487f,-0.0779795f, +0.132326f,0.991166f,-0.00888466f, +-0.00459516f,0.997934f,-0.0640824f, +-0.0924696f,0.984613f,-0.148277f, +-0.0479758f,0.968834f,-0.243019f, +0.052427f,0.976364f,-0.209677f, +0.223214f,0.97397f,-0.0394671f, +0.0112214f,0.972418f,0.232975f, +0.0106355f,0.967748f,0.251694f, +-0.0743183f,0.979789f,0.185717f, +0.0581795f,0.9982f,0.01459f, +0.133434f,0.964693f,-0.227076f, +0.215981f,0.948544f,-0.231554f, +0.137408f,0.968029f,-0.209856f, +0.0442022f,0.987042f,-0.154256f, +0.228305f,0.972284f,0.0504f, +0.121617f,0.992241f,-0.0258404f, +0.134527f,0.985242f,-0.105833f, +0.151618f,0.980953f,-0.121423f, +0.275183f,0.956894f,-0.092891f, +0.263324f,0.945384f,-0.192117f, +0.25647f,0.929449f,-0.26523f, +0.21073f,0.904026f,-0.371926f, +0.0728135f,0.89169f,-0.446751f, +-0.0691284f,0.877831f,-0.473955f, +-0.019884f,0.913569f,-0.406197f, +0.178205f,0.891525f,-0.416444f, +0.263993f,0.900279f,-0.34613f, +0.210305f,0.939702f,-0.269689f, +0.208408f,0.948624f,-0.238074f, +0.229275f,0.910156f,-0.345036f, +0.227512f,0.924458f,-0.305966f, +0.142229f,0.989234f,0.0344507f, +-0.0464441f,0.986357f,0.157934f, +0.073391f,0.981122f,0.178921f, +0.158555f,0.984472f,0.0753311f, +0.265489f,0.961878f,0.0656237f, +0.318063f,0.94383f,0.0895592f, +0.229589f,0.973115f,0.0183382f, +0.0918017f,0.995548f,-0.0213497f, +0.0710209f,0.997458f,0.00582691f, +0.234172f,0.971044f,-0.0473045f, +0.373198f,0.918081f,-0.133603f, +0.27855f,0.93462f,-0.221124f, +0.174681f,0.94082f,-0.290421f, +0.0816739f,0.936818f,-0.34015f, +0.233666f,0.948403f,-0.214319f, +0.373882f,0.91082f,-0.174984f, +0.44036f,0.88198f,-0.16791f, +0.496092f,0.86017f,-0.118324f, +0.420226f,0.875748f,-0.237645f, +0.228936f,0.896528f,-0.379243f, +0.0594423f,0.913794f,-0.401806f, +0.0971839f,0.949435f,-0.298544f, +0.201575f,0.953775f,-0.222894f, +0.339139f,0.935667f,-0.0975326f, +0.471026f,0.864094f,0.177416f, +0.409402f,0.896788f,0.167814f, +0.414181f,0.90532f,0.0940739f, +0.426161f,0.903473f,-0.0460849f, +0.431652f,0.886771f,-0.165266f, +0.36903f,0.909898f,-0.189479f, +0.237762f,0.950577f,-0.199683f, +0.250405f,0.963718f,-0.0924377f, +0.100123f,0.989034f,-0.108572f, +0.0410755f,0.997876f,-0.0505615f, +0.0233843f,0.999496f,0.0214792f, +-0.0536722f,0.998467f,-0.0135057f, +0.00107433f,0.999993f,-0.00356525f, +-0.0705196f,0.996911f,-0.0345704f, +-0.0688919f,0.997514f,0.0148223f, +-0.0812179f,0.983535f,0.161436f, +-0.0138011f,0.988231f,0.152344f, +0.0655184f,0.995642f,0.0663652f, +0.220598f,0.973784f,-0.0554998f, +0.309629f,0.942731f,-0.124049f, +0.155774f,0.947975f,-0.27763f, +0.127196f,0.974249f,-0.186174f, +-0.058769f,0.981296f,-0.183314f, +0.0497615f,0.99612f,-0.0725919f, +0.182926f,0.98205f,0.0460018f, +0.19209f,0.981195f,-0.0189005f, +0.224403f,0.972569f,-0.0612647f, +0.315645f,0.941316f,-0.119552f, +0.360736f,0.920207f,-0.151949f, +0.310465f,0.916626f,-0.251809f, +0.327403f,0.899549f,-0.28917f, +0.161725f,0.896729f,-0.411973f, +-0.0141039f,0.865769f,-0.500245f, +-0.0292484f,0.82172f,-0.56914f, +0.0961328f,0.815723f,-0.570398f, +0.101793f,0.868026f,-0.485972f, +0.156302f,0.922247f,-0.353597f, +0.205267f,0.935719f,-0.286871f, +0.229076f,0.948515f,-0.218729f, +0.0347356f,0.987904f,-0.151126f, +-0.079026f,0.996018f,0.0412683f, +-0.00943989f,0.997185f,0.0743796f, +0.111542f,0.993598f,-0.0179121f, +0.186771f,0.982172f,0.0213291f, +0.207496f,0.975443f,0.0738717f, +0.321818f,0.944637f,0.0639911f, +0.281397f,0.958917f,0.0359716f, +0.126766f,0.988281f,0.0850327f, +0.0940702f,0.995531f,0.0082479f, +0.338235f,0.93955f,-0.0533163f, +0.410978f,0.899199f,-0.150126f, +0.338008f,0.912085f,-0.232059f, +0.265939f,0.902685f,-0.338284f, +0.120839f,0.912428f,-0.39099f, +0.0943411f,0.91428f,-0.393944f, +0.326367f,0.911608f,-0.24991f, +0.410002f,0.90171f,-0.137175f, +0.446036f,0.89335f,-0.054576f, +0.453415f,0.890674f,0.0333893f, +0.369882f,0.926554f,0.0684487f, +0.15305f,0.985829f,-0.0686756f, +0.0307343f,0.980172f,-0.195752f, +0.104404f,0.981192f,-0.162361f, +0.153412f,0.984343f,-0.086793f, +0.259868f,0.962798f,0.0740869f, +0.405239f,0.886729f,0.222469f, +0.507863f,0.829218f,0.233395f, +0.530784f,0.842353f,0.0933228f, +0.515092f,0.857118f,0.0053912f, +0.421652f,0.904509f,-0.0638277f, +0.186762f,0.968676f,-0.16367f, +0.141357f,0.986443f,-0.0833539f, +0.10637f,0.994244f,0.0127965f, +-0.010764f,0.999348f,-0.0344492f, +-0.00443345f,0.999867f,-0.0156939f, +-0.0569297f,0.998142f,0.0217125f, +-0.0108274f,0.998516f,0.0533776f, +-0.0518054f,0.997615f,0.0456197f, +-0.08879f,0.991878f,0.0910736f, +0.15627f,0.9777f,0.14029f, +0.127078f,0.991794f,-0.0140045f, +0.182153f,0.975854f,-0.12054f, +0.236919f,0.957374f,-0.165238f, +0.354425f,0.924081f,-0.143031f, +0.22947f,0.95204f,-0.202395f, +0.0414456f,0.986576f,-0.157956f, +-0.0334694f,0.988237f,-0.149222f, +-0.0516418f,0.976013f,-0.2115f, +0.149794f,0.980531f,-0.126967f, +0.232135f,0.958309f,-0.166606f, +0.253821f,0.951991f,-0.171138f, +0.306434f,0.927336f,-0.214818f, +0.397399f,0.902704f,-0.164923f, +0.371523f,0.904625f,-0.208864f, +0.394746f,0.892045f,-0.220071f, +0.272791f,0.90211f,-0.334339f, +0.143123f,0.890975f,-0.430905f, +0.0302622f,0.843122f,-0.53687f, +0.0628652f,0.888185f,-0.455165f, +0.00848379f,0.914478f,-0.404546f, +0.009201f,0.926788f,-0.375473f, +0.0671766f,0.952807f,-0.296052f, +0.132209f,0.974746f,-0.179973f, +-0.0203291f,0.99362f,-0.110936f, +-0.138553f,0.985569f,-0.0972441f, +0.0605753f,0.989699f,-0.129717f, +0.0968295f,0.980926f,-0.168548f, +0.0979519f,0.993956f,-0.0495753f, +0.201443f,0.976928f,-0.0709446f, +0.381986f,0.916436f,-0.119294f, +0.157625f,0.97891f,-0.12996f, +0.10065f,0.993729f,0.0486956f, +0.194299f,0.980695f,-0.0220253f, +0.364962f,0.929379f,-0.0552881f, +0.487949f,0.871552f,-0.0479875f, +0.462417f,0.883871f,-0.0702998f, +0.341292f,0.927621f,-0.151788f, +0.13195f,0.962323f,-0.237746f, +0.0784249f,0.961522f,-0.263298f, +0.155522f,0.961843f,-0.225101f, +0.275269f,0.959916f,-0.0528088f, +0.354301f,0.927858f,0.116403f, +0.359914f,0.906647f,0.22012f, +0.307706f,0.904557f,0.295117f, +0.281691f,0.897787f,0.338569f, +0.169122f,0.964903f,0.200898f, +0.116857f,0.992098f,0.045666f, +0.131422f,0.991068f,-0.0226175f, +0.19688f,0.980005f,-0.0287978f, +0.332698f,0.942383f,-0.0350149f, +0.49437f,0.868541f,-0.0351363f, +0.591151f,0.806162f,-0.0253575f, +0.528595f,0.848271f,-0.0319893f, +0.452945f,0.891538f,3.96151e-005f, +0.269718f,0.962267f,0.0359679f, +0.0172075f,0.99965f,0.0201157f, +0.0836306f,0.98488f,0.151715f, +0.0817519f,0.992549f,0.0903531f, +-0.0289252f,0.999464f,0.015311f, +-0.0977995f,0.99488f,0.0254794f, +-0.0368101f,0.998502f,0.0404932f, +-0.0917396f,0.988968f,0.116306f, +-0.19824f,0.961924f,0.188156f, +0.355147f,0.931267f,-0.0813196f, +0.261709f,0.946669f,-0.187953f, +0.187089f,0.954576f,-0.23191f, +0.281523f,0.925027f,-0.255086f, +0.340665f,0.862289f,-0.374707f, +0.168991f,0.920317f,-0.352786f, +-0.0114217f,0.969014f,-0.246743f, +0.0275027f,0.971061f,-0.237244f, +0.0127748f,0.945787f,-0.324537f, +0.106685f,0.927276f,-0.358857f, +0.242554f,0.910981f,-0.333589f, +0.254201f,0.919334f,-0.300346f, +0.319051f,0.907348f,-0.273727f, +0.384836f,0.892504f,-0.235241f, +0.359386f,0.889916f,-0.280877f, +0.418755f,0.87516f,-0.242361f, +0.378513f,0.873068f,-0.307377f, +0.247447f,0.872868f,-0.420561f, +0.0334574f,0.868028f,-0.495387f, +-0.104393f,0.897693f,-0.428077f, +-0.0466408f,0.949283f,-0.310944f, +0.00907853f,0.960916f,-0.276691f, +0.00868667f,0.966036f,-0.258261f, +0.0845957f,0.976098f,-0.200192f, +-0.0296926f,0.969375f,-0.243785f, +-0.104852f,0.955765f,-0.274807f, +0.0855702f,0.957819f,-0.274336f, +0.0411396f,0.961225f,-0.272681f, +0.0481708f,0.973933f,-0.221661f, +0.28909f,0.93695f,-0.196346f, +0.356766f,0.919532f,-0.164859f, +0.126757f,0.9882f,-0.0859897f, +0.0144124f,0.990867f,-0.134068f, +0.233251f,0.969449f,-0.075909f, +0.354937f,0.93426f,-0.034317f, +0.469402f,0.882971f,-0.00493066f, +0.398385f,0.917184f,-0.00790304f, +0.386606f,0.918227f,0.0859925f, +0.228789f,0.970147f,0.0804364f, +0.115903f,0.993259f,0.0019484f, +0.110471f,0.992802f,-0.0462595f, +0.159257f,0.98723f,-0.00373461f, +0.193831f,0.979844f,0.0483161f, +0.304703f,0.938233f,0.163935f, +0.27363f,0.944953f,0.179417f, +0.268196f,0.936861f,0.224416f, +0.306571f,0.922686f,0.233806f, +0.304362f,0.944561f,0.123164f, +0.226364f,0.97021f,-0.0863264f, +0.198019f,0.963611f,-0.179562f, +0.39862f,0.902547f,-0.162819f, +0.534677f,0.804719f,-0.257967f, +0.537872f,0.788638f,-0.297899f, +0.486148f,0.837034f,-0.251066f, +0.374822f,0.901369f,-0.216893f, +0.171725f,0.976903f,-0.127168f, +-0.0108013f,0.999941f,-0.00151679f, +0.0247265f,0.999687f,-0.00377037f, +0.135958f,0.990654f,0.0109791f, +-0.00717425f,0.999252f,0.0379956f, +-0.0710711f,0.991911f,0.105175f, +-0.0859239f,0.990395f,0.108328f, +-0.18335f,0.97033f,0.157612f, +-0.315275f,0.941315f,0.120535f, +0.340669f,0.883831f,-0.320605f, +0.289176f,0.886429f,-0.361416f, +0.20883f,0.874721f,-0.437325f, +0.364068f,0.812937f,-0.454519f, +0.367133f,0.769647f,-0.522357f, +0.0748495f,0.818621f,-0.569436f, +-0.0872921f,0.835085f,-0.543151f, +0.00846427f,0.872897f,-0.48783f, +0.114223f,0.886407f,-0.448593f, +0.0920189f,0.872463f,-0.479939f, +0.2125f,0.893929f,-0.394633f, +0.175058f,0.869572f,-0.461735f, +0.23988f,0.874417f,-0.421725f, +0.3397f,0.869601f,-0.358326f, +0.392151f,0.874231f,-0.286248f, +0.401032f,0.871377f,-0.282622f, +0.447169f,0.847971f,-0.28458f, +0.337548f,0.868339f,-0.363386f, +0.0674983f,0.896564f,-0.437742f, +-0.167145f,0.867884f,-0.467804f, +-0.130341f,0.888597f,-0.43978f, +-0.0513088f,0.927515f,-0.370248f, +-0.0499693f,0.955154f,-0.291861f, +0.0619562f,0.966501f,-0.249073f, +0.104114f,0.952328f,-0.28676f, +-0.0782617f,0.904542f,-0.419141f, +0.00654125f,0.918336f,-0.395747f, +0.0825819f,0.944757f,-0.317199f, +0.028702f,0.9283f,-0.370722f, +0.170752f,0.927761f,-0.331819f, +0.188742f,0.965638f,-0.178664f, +0.126613f,0.983535f,0.12895f, +0.0677004f,0.989289f,0.129321f, +0.179931f,0.977134f,0.113286f, +0.301628f,0.94869f,0.0949132f, +0.473083f,0.874439f,0.107469f, +0.430087f,0.900068f,0.0700241f, +0.294529f,0.954232f,0.0519033f, +0.218538f,0.963065f,0.157309f, +0.194139f,0.967934f,0.159416f, +0.193754f,0.980213f,0.0405318f, +0.162395f,0.97825f,-0.129057f, +0.175319f,0.968352f,-0.177646f, +0.248014f,0.960103f,-0.129196f, +0.28568f,0.95369f,-0.0941428f, +0.21993f,0.968315f,-0.118312f, +0.322085f,0.944206f,-0.068818f, +0.382868f,0.918715f,-0.0968289f, +0.390317f,0.908769f,-0.147618f, +0.269935f,0.914207f,-0.30226f, +0.374262f,0.856519f,-0.355391f, +0.561588f,0.771614f,-0.298716f, +0.563679f,0.781086f,-0.268646f, +0.435393f,0.841674f,-0.319402f, +0.305805f,0.901875f,-0.305133f, +0.0714141f,0.973517f,-0.217175f, +-0.0655193f,0.984454f,-0.162963f, +0.0352485f,0.985949f,-0.163286f, +0.0657594f,0.9937f,-0.0907542f, +-0.080707f,0.996331f,0.0284757f, +-0.168129f,0.985261f,0.0315202f, +-0.129479f,0.990858f,0.0378905f, +-0.12231f,0.991737f,0.0387141f, +-0.178343f,0.98279f,-0.0481504f, +0.273318f,0.858026f,-0.434843f, +0.385091f,0.836836f,-0.389114f, +0.340339f,0.786413f,-0.515483f, +0.318221f,0.733035f,-0.601161f, +0.367621f,0.755443f,-0.542366f, +0.119455f,0.799665f,-0.588444f, +-0.0802011f,0.78091f,-0.619473f, +-0.0688818f,0.778398f,-0.623981f, +0.0140135f,0.818686f,-0.574071f, +0.0274992f,0.866697f,-0.498077f, +0.177071f,0.88196f,-0.436797f, +0.265217f,0.852958f,-0.449581f, +0.257768f,0.854407f,-0.45116f, +0.248846f,0.837431f,-0.486605f, +0.267639f,0.861569f,-0.431356f, +0.378672f,0.856274f,-0.351288f, +0.453357f,0.836299f,-0.308337f, +0.386424f,0.863215f,-0.324865f, +0.128686f,0.904609f,-0.406352f, +-0.130252f,0.895612f,-0.425338f, +-0.18148f,0.896143f,-0.40496f, +-0.161324f,0.928509f,-0.334435f, +-0.0897102f,0.95467f,-0.283825f, +0.0454642f,0.942898f,-0.329963f, +0.150896f,0.947175f,-0.283f, +0.0358472f,0.960013f,-0.277651f, +-0.0385071f,0.932002f,-0.360402f, +0.0386813f,0.938718f,-0.342507f, +0.0283698f,0.934985f,-0.353551f, +0.108122f,0.956069f,-0.272473f, +0.00374271f,0.987226f,-0.159284f, +-0.196358f,0.979545f,-0.0439957f, +-0.00408304f,0.984849f,0.173364f, +0.19648f,0.945984f,0.257896f, +0.360526f,0.896905f,0.256092f, +0.497904f,0.850304f,0.170515f, +0.432778f,0.894142f,0.114953f, +0.285493f,0.945844f,0.154508f, +0.185631f,0.971794f,0.145459f, +0.230083f,0.969236f,0.0874248f, +0.368311f,0.929659f,-0.00905859f, +0.334163f,0.916764f,-0.218814f, +0.186339f,0.940464f,-0.284262f, +0.166871f,0.945707f,-0.278912f, +0.282007f,0.937612f,-0.20336f, +0.24104f,0.942322f,-0.232226f, +0.269154f,0.937876f,-0.218962f, +0.376707f,0.923358f,-0.0741695f, +0.419282f,0.907855f,0.00132882f, +0.443207f,0.893334f,-0.0743096f, +0.437794f,0.862232f,-0.254741f, +0.526311f,0.818963f,-0.228685f, +0.539618f,0.818293f,-0.198015f, +0.495179f,0.844909f,-0.202303f, +0.231134f,0.928947f,-0.289195f, +-0.0315579f,0.980647f,-0.193222f, +-0.0610949f,0.990009f,-0.12708f, +-0.0213691f,0.991115f,-0.131279f, +-0.0564833f,0.997988f,-0.0288065f, +-0.126885f,0.991868f,-0.0099403f, +-0.0683923f,0.994887f,-0.0743097f, +-0.0443491f,0.981445f,-0.186542f, +-0.106156f,0.962217f,-0.250737f, +-0.0540242f,0.978674f,-0.198191f, +0.194886f,0.824241f,-0.531645f, +0.320074f,0.809438f,-0.492303f, +0.464438f,0.773143f,-0.431911f, +0.405677f,0.746051f,-0.528047f, +0.305674f,0.751501f,-0.584645f, +0.130892f,0.809782f,-0.571944f, +-0.0644176f,0.819769f,-0.56906f, +-0.0714323f,0.833301f,-0.548185f, +-0.0643631f,0.853923f,-0.516404f, +-0.0107306f,0.851684f,-0.523946f, +0.13746f,0.827954f,-0.543688f, +0.198685f,0.868523f,-0.454084f, +0.246871f,0.881894f,-0.401644f, +0.296117f,0.852853f,-0.430066f, +0.256816f,0.850031f,-0.459883f, +0.314177f,0.830121f,-0.460643f, +0.37334f,0.830673f,-0.413038f, +0.413553f,0.857071f,-0.30725f, +0.158679f,0.931259f,-0.327989f, +-0.130088f,0.933779f,-0.333368f, +-0.259668f,0.892475f,-0.368866f, +-0.237565f,0.924215f,-0.298981f, +-0.0871208f,0.968004f,-0.235327f, +0.0797031f,0.982117f,-0.17057f, +0.0461708f,0.99392f,-0.0999594f, +0.0445161f,0.998669f,-0.0260401f, +0.0420509f,0.9919f,-0.119856f, +0.0652827f,0.976809f,-0.203917f, +0.0163117f,0.980129f,-0.197692f, +-0.0727832f,0.991022f,-0.112154f, +-0.0519999f,0.997388f,0.0501216f, +-0.215497f,0.976498f,0.00360735f, +-0.144793f,0.989191f,0.023161f, +0.11495f,0.986032f,0.120527f, +0.332155f,0.934954f,0.124633f, +0.520936f,0.843883f,0.128405f, +0.426058f,0.883139f,0.196317f, +0.297882f,0.930389f,0.213643f, +0.255462f,0.962333f,0.0930293f, +0.330201f,0.94382f,-0.0130553f, +0.464814f,0.88236f,-0.0734001f, +0.396624f,0.912293f,-0.10203f, +0.190826f,0.974675f,-0.116592f, +0.186045f,0.970537f,-0.153119f, +0.228366f,0.951236f,-0.207361f, +0.252282f,0.958154f,-0.135261f, +0.163352f,0.984522f,-0.0635096f, +0.214627f,0.974395f,0.066997f, +0.385854f,0.917468f,0.096793f, +0.519216f,0.853803f,0.0378886f, +0.535665f,0.843867f,-0.0308472f, +0.541689f,0.838373f,-0.060851f, +0.563197f,0.822059f,-0.0838289f, +0.51966f,0.848391f,-0.100928f, +0.236369f,0.967062f,-0.0944536f, +-0.111969f,0.993037f,-0.0366171f, +-0.0968965f,0.995233f,-0.011032f, +-0.0970566f,0.995182f,0.013894f, +-0.0559363f,0.991458f,0.117821f, +-0.00538008f,0.999824f,-0.0179674f, +0.0108998f,0.982438f,-0.186268f, +0.0427996f,0.970253f,-0.238279f, +-0.10823f,0.95386f,-0.280066f, +-0.196538f,0.942983f,-0.26862f, +0.307908f,0.814842f,-0.491147f, +0.299308f,0.78907f,-0.536455f, +0.435133f,0.777699f,-0.453699f, +0.495126f,0.764316f,-0.413124f, +0.362871f,0.81835f,-0.445676f, +0.0803271f,0.871076f,-0.484534f, +-0.110099f,0.885293f,-0.451812f, +-0.149245f,0.895891f,-0.418456f, +-0.0670569f,0.907151f,-0.415428f, +0.0527044f,0.88691f,-0.458926f, +0.100471f,0.888224f,-0.448291f, +0.121208f,0.922825f,-0.365653f, +0.249787f,0.879883f,-0.404243f, +0.334334f,0.839973f,-0.427396f, +0.283757f,0.852792f,-0.438437f, +0.337422f,0.812854f,-0.474778f, +0.291967f,0.807546f,-0.512469f, +0.269633f,0.862064f,-0.429119f, +0.108203f,0.943068f,-0.314506f, +-0.121343f,0.966872f,-0.224575f, +-0.202731f,0.95836f,-0.201115f, +-0.275106f,0.928104f,-0.25088f, +-0.220959f,0.943196f,-0.248108f, +-0.0845259f,0.990859f,-0.105139f, +-0.0183112f,0.999824f,0.00404228f, +0.0398541f,0.999205f,-0.000234289f, +0.144105f,0.989245f,0.0250549f, +0.0887732f,0.994681f,0.052239f, +-0.0385311f,0.993554f,0.106613f, +-0.141743f,0.984863f,0.099766f, +-0.130913f,0.987043f,0.0927824f, +-0.138468f,0.982136f,0.12742f, +-0.181593f,0.983362f,-0.00473479f, +0.124018f,0.991703f,-0.0338209f, +0.350394f,0.929846f,-0.112294f, +0.471172f,0.881999f,-0.00866642f, +0.362692f,0.927143f,0.0941279f, +0.321547f,0.934446f,0.153031f, +0.39706f,0.903274f,0.162601f, +0.408629f,0.910814f,0.0586596f, +0.440544f,0.897708f,-0.00641084f, +0.417743f,0.90832f,0.0210971f, +0.223429f,0.972702f,-0.0626924f, +0.239878f,0.966667f,-0.0895152f, +0.326998f,0.934073f,-0.143454f, +0.0984577f,0.955256f,-0.278913f, +0.055814f,0.995135f,-0.081185f, +0.198837f,0.979583f,-0.0296926f, +0.452343f,0.887429f,-0.0886289f, +0.538988f,0.831253f,-0.136052f, +0.534759f,0.840783f,-0.084361f, +0.557911f,0.827063f,-0.0685738f, +0.570718f,0.812258f,-0.120488f, +0.469437f,0.877038f,-0.102147f, +0.179725f,0.982175f,0.0550563f, +-0.143773f,0.988083f,0.054972f, +-0.0900032f,0.995941f,-0.00107895f, +-0.112639f,0.992937f,-0.0372634f, +-0.0770822f,0.995012f,-0.0633234f, +0.131283f,0.990073f,-0.0501953f, +0.151552f,0.985928f,-0.0705498f, +0.0547644f,0.990744f,-0.124209f, +-0.0889999f,0.992043f,-0.0890439f, +-0.225525f,0.966809f,-0.120075f, +0.367815f,0.812209f,-0.4528f, +0.333749f,0.806687f,-0.487716f, +0.350467f,0.776679f,-0.523395f, +0.428661f,0.776887f,-0.461189f, +0.344028f,0.851962f,-0.394722f, +0.0917588f,0.929121f,-0.35821f, +-0.151193f,0.922445f,-0.355297f, +-0.135334f,0.926245f,-0.351788f, +-0.0236046f,0.919658f,-0.39201f, +0.0475929f,0.924342f,-0.378586f, +0.0534474f,0.931533f,-0.359707f, +0.122967f,0.908442f,-0.399514f, +0.333531f,0.836829f,-0.434137f, +0.345062f,0.821786f,-0.45343f, +0.298405f,0.81077f,-0.503594f, +0.369796f,0.765054f,-0.527202f, +0.289381f,0.806079f,-0.516232f, +0.106326f,0.866117f,-0.488402f, +-0.0247184f,0.959589f,-0.280318f, +-0.247885f,0.952117f,-0.178958f, +-0.233969f,0.968302f,-0.0874651f, +-0.230973f,0.963517f,-0.135224f, +-0.23946f,0.950685f,-0.197121f, +-0.148981f,0.968772f,-0.198205f, +-0.0244446f,0.976892f,-0.212332f, +0.0214143f,0.979888f,-0.198397f, +0.0179015f,0.996249f,-0.084666f, +-0.0584671f,0.995927f,0.0686411f, +-0.0472317f,0.986168f,0.158874f, +-0.0434315f,0.994906f,0.0909663f, +-0.106857f,0.994237f,0.00858694f, +-0.103595f,0.993848f,-0.0391609f, +-0.0110181f,0.988269f,-0.152323f, +0.194953f,0.947451f,-0.253632f, +0.318956f,0.92262f,-0.216885f, +0.355303f,0.928796f,-0.105349f, +0.319482f,0.947371f,-0.0204796f, +0.274811f,0.961125f,0.0267891f, +0.33758f,0.938163f,0.0767414f, +0.445225f,0.885597f,0.132261f, +0.483843f,0.868855f,0.104815f, +0.473616f,0.877987f,0.069475f, +0.358094f,0.929841f,-0.0846442f, +0.209896f,0.940516f,-0.267156f, +0.398687f,0.89746f,-0.188715f, +0.164362f,0.933368f,-0.319075f, +-0.0806345f,0.937721f,-0.337901f, +0.19678f,0.945117f,-0.26083f, +0.467829f,0.857531f,-0.213953f, +0.522616f,0.828828f,-0.199792f, +0.48751f,0.848849f,-0.204424f, +0.559553f,0.806974f,-0.18893f, +0.585339f,0.775984f,-0.235006f, +0.309037f,0.923705f,-0.22642f, +0.0763335f,0.997082f,0.00115348f, +-0.0450053f,0.998556f,0.0293498f, +-0.0333568f,0.997154f,-0.0676115f, +-0.00964185f,0.995848f,-0.0905243f, +0.000956175f,0.96601f,-0.258503f, +0.00169255f,0.940578f,-0.339574f, +0.0710047f,0.988076f,-0.136617f, +0.0666563f,0.995318f,-0.0699874f, +-0.123764f,0.98454f,-0.123946f, +-0.163961f,0.983022f,-0.0823738f, +0.335205f,0.824436f,-0.456008f, +0.40434f,0.809075f,-0.426506f, +0.410475f,0.791681f,-0.452494f, +0.374361f,0.829194f,-0.41508f, +0.245781f,0.909811f,-0.33442f, +0.0263815f,0.954919f,-0.295693f, +-0.125325f,0.941665f,-0.312348f, +-0.129375f,0.929134f,-0.346369f, +-0.0304152f,0.953686f,-0.299263f, +-0.0235504f,0.953092f,-0.301762f, +0.153775f,0.94901f,-0.275197f, +0.274986f,0.871191f,-0.406705f, +0.301999f,0.805469f,-0.509919f, +0.376419f,0.798039f,-0.470576f, +0.361388f,0.809968f,-0.461899f, +0.38255f,0.848875f,-0.364783f, +0.240129f,0.889938f,-0.387747f, +-0.0576931f,0.937865f,-0.342172f, +-0.263371f,0.95113f,-0.161204f, +-0.310954f,0.950327f,-0.0136276f, +-0.223147f,0.974756f,-0.00746382f, +-0.15809f,0.984734f,-0.0728478f, +-0.146587f,0.977645f,-0.150739f, +-0.120405f,0.952352f,-0.280228f, +0.00186508f,0.961595f,-0.274467f, +-0.0732237f,0.95724f,-0.279876f, +-0.12777f,0.973556f,-0.189377f, +-0.137722f,0.985013f,-0.103834f, +-0.0840689f,0.995964f,-0.0314252f, +0.00572333f,0.997438f,0.0713008f, +-0.0203309f,0.999218f,0.033924f, +0.0131655f,0.994107f,-0.107599f, +0.106442f,0.965608f,-0.237214f, +0.156613f,0.948157f,-0.276534f, +0.221784f,0.959186f,-0.175425f, +0.297839f,0.94933f,-0.100322f, +0.237415f,0.96993f,-0.0535752f, +0.206724f,0.977649f,0.0383141f, +0.342833f,0.933108f,0.108513f, +0.413098f,0.906827f,0.0837554f, +0.485601f,0.86482f,0.127586f, +0.517433f,0.850444f,0.0949105f, +0.521609f,0.853001f,-0.0177076f, +0.35462f,0.907818f,-0.223854f, +0.320255f,0.896065f,-0.307417f, +0.254422f,0.945666f,-0.202447f, +-0.0420832f,0.95285f,-0.300511f, +0.132146f,0.911038f,-0.390572f, +0.397135f,0.84337f,-0.361954f, +0.530962f,0.805014f,-0.264634f, +0.518015f,0.788476f,-0.331612f, +0.536794f,0.726368f,-0.429234f, +0.499189f,0.748129f,-0.437165f, +0.193048f,0.933972f,-0.300713f, +-0.0642143f,0.969885f,-0.234947f, +-0.0349143f,0.97216f,-0.231701f, +-0.020308f,0.973327f,-0.22852f, +0.0335645f,0.983758f,-0.176336f, +0.162495f,0.963807f,-0.211356f, +0.0549435f,0.960153f,-0.274021f, +-0.150243f,0.943756f,-0.294538f, +0.093877f,0.988384f,-0.119518f, +-0.0288967f,0.977445f,-0.209205f, +-0.228292f,0.925763f,-0.301406f, +0.329933f,0.832357f,-0.445339f, +0.354113f,0.855807f,-0.377092f, +0.402588f,0.885182f,-0.233185f, +0.310305f,0.922327f,-0.23027f, +0.169674f,0.966179f,-0.194188f, +0.0510686f,0.987038f,-0.152145f, +-0.0638218f,0.978386f,-0.196689f, +-0.116946f,0.960297f,-0.253286f, +-0.0788814f,0.945056f,-0.317249f, +0.0429532f,0.937478f,-0.345383f, +0.160798f,0.890341f,-0.425953f, +0.370061f,0.833359f,-0.410569f, +0.405144f,0.796477f,-0.448867f, +0.330775f,0.831238f,-0.446802f, +0.214187f,0.914592f,-0.342995f, +0.302956f,0.933789f,-0.190409f, +0.260411f,0.956162f,-0.13394f, +-0.0987797f,0.989363f,-0.106786f, +-0.381946f,0.915584f,-0.125788f, +-0.356892f,0.930397f,-0.0835967f, +-0.219462f,0.974624f,-0.0441002f, +-0.0826206f,0.996346f,-0.0216629f, +-0.0522166f,0.993096f,-0.10504f, +-0.0544454f,0.992373f,-0.110596f, +-0.0392289f,0.996233f,-0.0773398f, +-0.0738534f,0.995703f,-0.0558676f, +-0.126249f,0.987782f,-0.0913672f, +-0.191576f,0.965578f,-0.17595f, +-0.204819f,0.971278f,-0.121116f, +-0.121301f,0.991656f,-0.0436452f, +0.0591737f,0.997785f,0.0303762f, +0.146031f,0.988908f,-0.0271181f, +0.164489f,0.985353f,-0.0449734f, +0.1732f,0.984753f,-0.0162076f, +0.192999f,0.97944f,-0.0587201f, +0.224284f,0.970976f,-0.0830781f, +0.215597f,0.976395f,0.0130766f, +0.11857f,0.99294f,-0.00337615f, +0.283009f,0.956652f,0.0687283f, +0.418445f,0.903636f,0.0913547f, +0.498249f,0.865176f,0.0567366f, +0.572218f,0.818628f,-0.0491444f, +0.584595f,0.798602f,-0.143119f, +0.499999f,0.838004f,-0.218521f, +0.312173f,0.860973f,-0.401589f, +0.169015f,0.918853f,-0.356571f, +0.0805256f,0.94115f,-0.328258f, +0.268694f,0.864193f,-0.42541f, +0.373719f,0.773399f,-0.512044f, +0.442856f,0.749728f,-0.491717f, +0.564815f,0.671761f,-0.479293f, +0.549235f,0.627986f,-0.551338f, +0.305274f,0.788247f,-0.534298f, +0.0146963f,0.910216f,-0.413874f, +-0.0347141f,0.920746f,-0.388614f, +-0.0142092f,0.918584f,-0.394971f, +-0.0593092f,0.944757f,-0.32236f, +-0.0129026f,0.951456f,-0.307515f, +0.101136f,0.954598f,-0.280203f, +0.103786f,0.979836f,-0.170731f, +-0.130724f,0.946294f,-0.2957f, +-0.0475497f,0.951312f,-0.30454f, +0.068843f,0.980898f,-0.181933f, +-0.0601749f,0.975587f,-0.21121f, +0.164088f,0.946673f,-0.277283f, +0.219167f,0.958752f,-0.180996f, +0.292116f,0.952214f,-0.0892046f, +0.382294f,0.923975f,-0.0110254f, +0.185963f,0.972429f,-0.140709f, +0.0282036f,0.98507f,-0.16983f, +-0.0260978f,0.984942f,-0.170904f, +0.00347731f,0.966818f,-0.255444f, +0.046523f,0.915606f,-0.399376f, +0.121249f,0.881024f,-0.457269f, +0.234655f,0.843553f,-0.483069f, +0.349259f,0.806387f,-0.47724f, +0.352024f,0.817545f,-0.455741f, +0.21f,0.895765f,-0.391796f, +0.123731f,0.946466f,-0.298149f, +0.189246f,0.953263f,-0.235533f, +0.21574f,0.971887f,-0.0943018f, +-0.0878709f,0.988681f,-0.12161f, +-0.31365f,0.930831f,-0.187554f, +-0.370884f,0.90378f,-0.213602f, +-0.292833f,0.938489f,-0.182993f, +-0.076513f,0.991298f,-0.107116f, +-0.0492348f,0.994225f,-0.0953508f, +-0.128831f,0.991129f,-0.0326479f, +-0.117178f,0.99304f,0.0118732f, +-0.0834857f,0.989043f,0.12175f, +-0.0124631f,0.991817f,0.127061f, +-0.133134f,0.991073f,-0.00703918f, +-0.190067f,0.981738f,-0.00811131f, +-0.0950662f,0.989352f,-0.110206f, +0.0262188f,0.977376f,-0.209877f, +0.0774906f,0.981033f,-0.177679f, +0.0911686f,0.995787f,-0.00982619f, +0.177517f,0.984043f,0.0121696f, +0.260966f,0.962001f,-0.0803208f, +0.219093f,0.96759f,-0.12557f, +0.15488f,0.986019f,-0.06147f, +0.155325f,0.987507f,-0.0265508f, +0.257438f,0.9633f,-0.0760109f, +0.429699f,0.898131f,-0.0933795f, +0.553938f,0.821258f,-0.136702f, +0.635333f,0.740056f,-0.220611f, +0.590775f,0.752696f,-0.290577f, +0.544721f,0.782975f,-0.300381f, +0.386007f,0.854199f,-0.348343f, +0.159868f,0.903698f,-0.397205f, +0.111475f,0.854344f,-0.507613f, +0.32886f,0.783243f,-0.527619f, +0.428722f,0.729381f,-0.533105f, +0.463071f,0.680849f,-0.567459f, +0.578683f,0.643078f,-0.501575f, +0.498776f,0.750313f,-0.433881f, +0.172367f,0.935224f,-0.309265f, +-0.0549105f,0.957697f,-0.282492f, +-0.000989137f,0.955961f,-0.293491f, +-0.105185f,0.947134f,-0.303107f, +-0.108598f,0.951252f,-0.288662f, +-0.0192021f,0.937992f,-0.346125f, +0.0434621f,0.947915f,-0.315545f, +0.0658084f,0.965866f,-0.250542f, +0.00168367f,0.969468f,-0.245211f, +-0.0752902f,0.953259f,-0.292624f, +-0.0406571f,0.962797f,-0.267151f, +-0.0486067f,0.969651f,-0.239615f, +0.0419974f,0.993223f,-0.108371f, +0.194169f,0.980548f,-0.0286949f, +0.261981f,0.963651f,-0.0523696f, +0.349136f,0.937066f,-0.00343362f, +0.31121f,0.950026f,0.0244779f, +0.0510089f,0.992585f,-0.110335f, +0.0314098f,0.989653f,-0.140003f, +0.185979f,0.958236f,-0.217244f, +0.136104f,0.898638f,-0.417044f, +0.108771f,0.892335f,-0.438072f, +0.238757f,0.906785f,-0.34747f, +0.373646f,0.87379f,-0.311256f, +0.340425f,0.883999f,-0.320402f, +0.14853f,0.93597f,-0.319217f, +0.0564088f,0.968057f,-0.244304f, +0.0971116f,0.979187f,-0.17822f, +0.12449f,0.986246f,-0.108724f, +0.00791995f,0.999591f,-0.0274806f, +-0.236925f,0.964883f,-0.113439f, +-0.404549f,0.891486f,-0.203944f, +-0.302952f,0.940514f,-0.153798f, +-0.187243f,0.970939f,-0.149055f, +-0.103813f,0.994585f,-0.00480558f, +-0.136945f,0.990579f,0.00047278f, +-0.192386f,0.981319f,0.000301484f, +-0.157118f,0.980577f,0.117404f, +-0.0205849f,0.995936f,0.0876826f, +-0.0389376f,0.992928f,0.112147f, +-0.205589f,0.977918f,0.0375515f, +0.0799477f,0.995293f,0.0547661f, +0.128711f,0.981689f,-0.140426f, +-0.00377139f,0.985264f,-0.170999f, +-0.0186288f,0.990563f,-0.135788f, +0.247861f,0.95847f,-0.141069f, +0.335397f,0.913398f,-0.230679f, +0.164127f,0.956335f,-0.241837f, +0.0560549f,0.992155f,-0.111746f, +0.165621f,0.985752f,-0.0293729f, +0.329655f,0.93718f,-0.114108f, +0.47188f,0.859421f,-0.196784f, +0.593068f,0.774119f,-0.22138f, +0.65363f,0.716422f,-0.24394f, +0.606788f,0.760352f,-0.231675f, +0.536399f,0.810894f,-0.23394f, +0.343135f,0.901586f,-0.263439f, +0.295862f,0.930397f,-0.216396f, +0.307346f,0.85762f,-0.412342f, +0.36437f,0.770675f,-0.522776f, +0.48977f,0.726784f,-0.481571f, +0.467664f,0.727396f,-0.50218f, +0.516451f,0.759976f,-0.394608f, +0.369408f,0.883578f,-0.287798f, +0.11272f,0.986131f,-0.121821f, +-0.0556185f,0.985996f,-0.157218f, +-0.0141506f,0.99059f,-0.13613f, +-0.0462718f,0.993931f,-0.099801f, +-0.0190733f,0.9801f,-0.197584f, +0.0617351f,0.955747f,-0.287639f, +-0.00791345f,0.937814f,-0.347049f, +0.0263533f,0.943249f,-0.331038f, +-0.0408223f,0.937006f,-0.34692f, +-0.0840519f,0.9495f,-0.302299f, +-0.0536227f,0.964498f,-0.25859f, +-0.0366453f,0.973297f,-0.226607f, +0.0559372f,0.997556f,-0.0418806f, +0.117658f,0.99199f,-0.0459629f, +0.260816f,0.963552f,0.059517f, +0.265721f,0.95723f,0.114473f, +0.305022f,0.92568f,0.223781f, +0.229311f,0.961539f,0.151192f, +0.0614828f,0.993074f,-0.10012f, +0.279787f,0.947394f,-0.15545f, +0.307005f,0.902601f,-0.301762f, +0.0599313f,0.924785f,-0.375741f, +0.138459f,0.941623f,-0.306881f, +0.380474f,0.890209f,-0.250536f, +0.362157f,0.883362f,-0.297512f, +0.118666f,0.951617f,-0.283449f, +-0.0864913f,0.973386f,-0.212226f, +0.0535968f,0.99807f,-0.0313783f, +0.0571748f,0.998014f,0.026449f, +-0.0576417f,0.995225f,0.0787756f, +-0.164671f,0.983729f,0.0718444f, +-0.317398f,0.947117f,0.0472105f, +-0.350813f,0.936189f,-0.0219157f, +-0.249283f,0.968275f,0.0173648f, +-0.166219f,0.983818f,0.0668861f, +-0.137263f,0.989074f,0.0537794f, +-0.237615f,0.966132f,0.100634f, +-0.156805f,0.98112f,0.113207f, +0.0155394f,0.999476f,0.0283817f, +-0.0358194f,0.998926f,0.0293752f, +-0.187269f,0.982125f,-0.01898f, +0.0856923f,0.996255f,0.0114998f, +0.21812f,0.975918f,0.00295422f, +0.0575266f,0.997525f,-0.0404377f, +0.0557844f,0.976324f,-0.208997f, +0.282723f,0.906166f,-0.314533f, +0.34017f,0.885713f,-0.315906f, +0.0703654f,0.964786f,-0.253451f, +-0.0857039f,0.987005f,-0.135924f, +0.161068f,0.982423f,-0.0943491f, +0.439921f,0.879468f,-0.181673f, +0.499341f,0.805071f,-0.320185f, +0.581376f,0.752639f,-0.309089f, +0.634744f,0.735927f,-0.235609f, +0.590228f,0.797974f,-0.121932f, +0.552123f,0.824777f,-0.122079f, +0.403254f,0.893687f,-0.196749f, +0.282279f,0.904426f,-0.319896f, +0.487441f,0.821419f,-0.296095f, +0.471414f,0.771013f,-0.428146f, +0.452383f,0.750947f,-0.48107f, +0.453351f,0.789814f,-0.413117f, +0.426317f,0.829282f,-0.361311f, +0.274227f,0.935292f,-0.223671f, +0.0409647f,0.985686f,-0.16354f, +0.00611451f,0.980211f,-0.19786f, +-0.0818346f,0.965065f,-0.248905f, +-0.0402149f,0.984168f,-0.172615f, +0.0358772f,0.970818f,-0.237119f, +0.140843f,0.951316f,-0.274156f, +0.0386407f,0.935491f,-0.351232f, +0.02521f,0.945244f,-0.325388f, +-0.00704123f,0.966541f,-0.256414f, +-0.132543f,0.963814f,-0.231288f, +-0.120001f,0.972985f,-0.197233f, +-0.125856f,0.970406f,-0.20609f, +0.150068f,0.984139f,0.0946078f, +0.0962514f,0.994035f,0.0512922f, +0.139768f,0.98134f,0.132051f, +0.167943f,0.959948f,0.224265f, +0.248876f,0.931236f,0.266197f, +0.347088f,0.901338f,0.259075f, +0.298327f,0.935934f,0.187161f, +0.410224f,0.911771f,0.0197232f, +0.382392f,0.916875f,-0.11453f, +0.0687189f,0.981224f,-0.180215f, +0.109108f,0.978331f,-0.175964f, +0.423091f,0.889035f,-0.17496f, +0.308023f,0.9305f,-0.198221f, +0.0610242f,0.996399f,-0.0588678f, +-0.139679f,0.983461f,-0.1153f, +-0.178862f,0.976278f,-0.122024f, +-0.0279755f,0.98865f,0.147609f, +0.0175582f,0.984678f,0.173494f, +-0.182965f,0.982824f,0.0240987f, +-0.334982f,0.934918f,0.117109f, +-0.346361f,0.929574f,0.126201f, +-0.256073f,0.950373f,0.176686f, +-0.14622f,0.975847f,0.162306f, +-0.145894f,0.982033f,0.119692f, +-0.243091f,0.96438f,0.104295f, +-0.119399f,0.991881f,0.0437603f, +0.0792305f,0.996134f,0.0379462f, +-0.0234512f,0.999544f,0.0190445f, +-0.148416f,0.988869f,0.0105176f, +0.0279419f,0.999576f,0.00824062f, +0.239276f,0.970159f,0.0392311f, +0.182184f,0.979477f,-0.086222f, +0.251919f,0.933495f,-0.255194f, +0.359782f,0.855042f,-0.373444f, +0.260041f,0.87469f,-0.409017f, +-0.0332083f,0.931159f,-0.363099f, +-0.108678f,0.933514f,-0.341673f, +0.191287f,0.909011f,-0.370282f, +0.516055f,0.783319f,-0.346553f, +0.557568f,0.726461f,-0.401711f, +0.511814f,0.738467f,-0.438991f, +0.509794f,0.789775f,-0.341125f, +0.522098f,0.819729f,-0.235496f, +0.54438f,0.815602f,-0.196071f, +0.540927f,0.823066f,-0.173089f, +0.36892f,0.838043f,-0.401972f, +0.461826f,0.790802f,-0.401684f, +0.549439f,0.728653f,-0.408878f, +0.455853f,0.753497f,-0.473751f, +0.389397f,0.799772f,-0.456875f, +0.293181f,0.868874f,-0.398878f, +0.155589f,0.965139f,-0.210473f, +0.031565f,0.984349f,-0.173382f, +0.0970165f,0.970686f,-0.219901f, +-0.0352366f,0.943342f,-0.329946f, +-0.0636858f,0.931929f,-0.357006f, +0.111555f,0.924517f,-0.364451f, +0.180963f,0.908751f,-0.376064f, +0.0582409f,0.924666f,-0.376299f, +-0.091325f,0.934476f,-0.344113f, +-0.148498f,0.963415f,-0.223113f, +-0.170646f,0.976481f,-0.131776f, +-0.0961794f,0.980781f,-0.169761f, +-0.06221f,0.973089f,-0.221874f, +0.206636f,0.934831f,0.288777f, +0.0869406f,0.963592f,0.252847f, +0.0799701f,0.959241f,0.271038f, +0.160525f,0.963414f,0.21463f, +0.255681f,0.955661f,0.146082f, +0.323027f,0.93103f,0.169812f, +0.330118f,0.920313f,0.209873f, +0.447578f,0.884885f,0.12904f, +0.467368f,0.874534f,0.129448f, +0.130174f,0.988207f,0.0806387f, +0.145402f,0.989036f,-0.0258009f, +0.425216f,0.898822f,-0.106345f, +0.205136f,0.977985f,-0.0382811f, +-0.0258123f,0.995757f,0.0883314f, +-0.00518813f,0.996132f,0.0877124f, +-0.192412f,0.980974f,0.0258233f, +-0.196114f,0.979963f,0.0348015f, +0.0217983f,0.995754f,0.0894399f, +-0.10216f,0.980256f,0.169296f, +-0.384424f,0.908881f,0.161723f, +-0.367551f,0.91996f,0.136309f, +-0.285788f,0.948719f,0.135118f, +-0.171256f,0.972185f,0.159771f, +-0.0605854f,0.969905f,0.235826f, +-0.167372f,0.981266f,0.0954134f, +-0.0977838f,0.994994f,0.0206294f, +0.0451608f,0.997867f,0.0471292f, +-0.0136124f,0.997411f,0.0706177f, +-0.158818f,0.986831f,0.0306748f, +0.0267005f,0.99957f,0.0121357f, +0.289361f,0.957076f,-0.0166175f, +0.336393f,0.939976f,-0.0573177f, +0.390118f,0.913466f,-0.115702f, +0.445853f,0.875576f,-0.185959f, +0.293335f,0.914816f,-0.277609f, +-0.00739937f,0.915657f,-0.401893f, +0.00533725f,0.872492f,-0.488599f, +0.197734f,0.788261f,-0.582705f, +0.43334f,0.722538f,-0.53866f, +0.548408f,0.706281f,-0.447678f, +0.484095f,0.751007f,-0.449045f, +0.458828f,0.77804f,-0.429103f, +0.441245f,0.787203f,-0.430829f, +0.474553f,0.805707f,-0.354451f, +0.550933f,0.789486f,-0.270526f, +0.502032f,0.792798f,-0.345594f, +0.478273f,0.764634f,-0.43196f, +0.556872f,0.730832f,-0.394687f, +0.471855f,0.788619f,-0.394251f, +0.354943f,0.841801f,-0.406677f, +0.154029f,0.899791f,-0.40823f, +0.0155123f,0.938951f,-0.343701f, +0.0497714f,0.948037f,-0.314243f, +0.154285f,0.935402f,-0.31815f, +0.101927f,0.920411f,-0.377432f, +-0.0203862f,0.864666f,-0.501933f, +0.070179f,0.866621f,-0.494007f, +0.100294f,0.910674f,-0.400766f, +0.000402101f,0.968295f,-0.249809f, +-0.128961f,0.971456f,-0.199105f, +-0.199723f,0.946207f,-0.254564f, +-0.134113f,0.940975f,-0.310772f, +-0.0316747f,0.927512f,-0.372449f, +0.0302907f,0.938917f,-0.342807f, +0.218976f,0.899032f,0.379198f, +0.139079f,0.919337f,0.368072f, +0.135024f,0.957047f,0.256573f, +0.313512f,0.936875f,0.154838f, +0.29644f,0.95504f,0.00476296f, +0.279277f,0.959996f,0.0202722f, +0.3625f,0.931007f,0.0426625f, +0.472022f,0.881367f,0.0196857f, +0.429567f,0.887347f,0.167594f, +0.224991f,0.963227f,0.146879f, +0.296133f,0.954919f,-0.0208476f, +0.415966f,0.902166f,-0.114319f, +0.183129f,0.982743f,0.0260829f, +-0.0925135f,0.995706f,-0.00325499f, +-0.0437431f,0.995986f,0.0780946f, +-0.179713f,0.977607f,0.109486f, +-0.141385f,0.986823f,0.0786845f, +-0.085949f,0.993479f,0.0749198f, +-0.233157f,0.944593f,0.231044f, +-0.345216f,0.897121f,0.275681f, +-0.266518f,0.944857f,0.190296f, +-0.236509f,0.971079f,0.032684f, +-0.255527f,0.96653f,-0.0229239f, +-0.0941044f,0.991025f,0.0949427f, +-0.0715158f,0.990946f,0.113625f, +-0.0636481f,0.988651f,0.136079f, +0.0130078f,0.992968f,0.11767f, +0.0194535f,0.99321f,0.114698f, +-0.0733749f,0.997304f,0.000320173f, +0.0745089f,0.991949f,-0.102398f, +0.316045f,0.940065f,-0.128038f, +0.302503f,0.936628f,-0.176692f, +0.365578f,0.917629f,-0.155918f, +0.474055f,0.875706f,-0.091714f, +0.462666f,0.882661f,-0.0827679f, +0.197672f,0.918824f,-0.341598f, +0.1211f,0.851979f,-0.509379f, +0.340562f,0.776445f,-0.530237f, +0.411588f,0.704014f,-0.578756f, +0.454493f,0.713166f,-0.533695f, +0.463114f,0.742631f,-0.483761f, +0.44079f,0.754688f,-0.485953f, +0.400302f,0.772025f,-0.493696f, +0.38659f,0.783016f,-0.487272f, +0.457033f,0.766931f,-0.450487f, +0.547084f,0.759757f,-0.351382f, +0.508566f,0.782012f,-0.360303f, +0.54699f,0.792915f,-0.268492f, +0.489855f,0.837224f,-0.243102f, +0.350988f,0.891534f,-0.286312f, +0.195385f,0.947495f,-0.253137f, +0.0709694f,0.939176f,-0.336023f, +0.0288377f,0.903143f,-0.42837f, +0.128806f,0.91498f,-0.382389f, +0.209123f,0.895775f,-0.392243f, +0.0981301f,0.852621f,-0.513233f, +-0.0414306f,0.841347f,-0.538906f, +-0.0951984f,0.922571f,-0.373899f, +-0.157973f,0.963972f,-0.214014f, +-0.107909f,0.978829f,-0.173926f, +-0.0713291f,0.969594f,-0.234092f, +0.0141898f,0.950434f,-0.310602f, +-0.0202439f,0.895649f,-0.4443f, +-0.114151f,0.867225f,-0.484655f, +0.0955354f,0.969912f,0.223927f, +0.218114f,0.913651f,0.343028f, +0.223104f,0.958808f,0.175816f, +0.39761f,0.915149f,0.0663907f, +0.332649f,0.940641f,-0.0673772f, +0.280455f,0.956871f,-0.0757854f, +0.359446f,0.926985f,-0.107225f, +0.369482f,0.924827f,-0.0904272f, +0.410746f,0.887001f,0.210991f, +0.335823f,0.922126f,0.192112f, +0.395669f,0.917218f,-0.0464346f, +0.353697f,0.926083f,-0.131407f, +0.179534f,0.981887f,0.0605388f, +-0.13479f,0.99057f,-0.0245515f, +-0.0725996f,0.990136f,0.119831f, +-0.160567f,0.981095f,0.108036f, +-0.173547f,0.983858f,0.0436428f, +-0.151709f,0.976244f,0.154697f, +-0.302597f,0.914896f,0.267208f, +-0.328732f,0.906446f,0.265123f, +-0.132663f,0.960039f,0.246424f, +-0.138673f,0.989957f,0.0274833f, +-0.234284f,0.968151f,-0.0882923f, +-0.176173f,0.979923f,-0.0933525f, +-0.138089f,0.990412f,-0.00402308f, +-0.0957719f,0.981754f,0.164279f, +0.0343111f,0.979592f,0.198047f, +0.0638942f,0.984862f,0.161133f, +0.0719687f,0.995312f,0.0646062f, +0.0847007f,0.982914f,-0.163422f, +0.363247f,0.926697f,-0.0963506f, +0.36667f,0.908341f,-0.201173f, +0.337169f,0.882657f,-0.327465f, +0.394509f,0.879929f,-0.264742f, +0.48646f,0.864989f,-0.123088f, +0.417344f,0.883151f,-0.21417f, +0.20086f,0.830272f,-0.519907f, +0.38892f,0.767179f,-0.510077f, +0.449414f,0.718324f,-0.531072f, +0.423477f,0.726204f,-0.541567f, +0.422958f,0.74196f,-0.520194f, +0.433204f,0.760712f,-0.483374f, +0.409051f,0.775415f,-0.481049f, +0.416047f,0.762178f,-0.495973f, +0.412818f,0.728929f,-0.546117f, +0.422596f,0.756339f,-0.499363f, +0.473538f,0.806572f,-0.353841f, +0.474731f,0.838081f,-0.268794f, +0.539079f,0.832631f,-0.126962f, +0.311124f,0.910644f,-0.271898f, +0.195648f,0.962321f,-0.18884f, +0.177086f,0.961235f,-0.211349f, +0.0559264f,0.927874f,-0.368677f, +0.121016f,0.928529f,-0.350982f, +0.256538f,0.895264f,-0.364269f, +0.222607f,0.876269f,-0.427317f, +-0.106542f,0.82471f,-0.55543f, +-0.245122f,0.890501f,-0.383305f, +-0.209725f,0.956698f,-0.201855f, +-0.0624605f,0.97406f,-0.2175f, +-0.0812465f,0.947824f,-0.308266f, +0.0649824f,0.972455f,-0.223851f, +0.119957f,0.950206f,-0.287609f, +-0.0414767f,0.905483f,-0.422351f, +}; + +btScalar Landscape03Tex[] = { +0.507813f,0.5f, +0.507813f,0.492188f, +0.515625f,0.5f, +0.515625f,0.492188f, +0.523438f,0.5f, +0.523438f,0.492188f, +0.53125f,0.5f, +0.53125f,0.492188f, +0.539063f,0.5f, +0.539063f,0.492188f, +0.546875f,0.5f, +0.546875f,0.492188f, +0.554688f,0.5f, +0.554688f,0.492188f, +0.5625f,0.5f, +0.5625f,0.492188f, +0.570313f,0.5f, +0.570313f,0.492188f, +0.578125f,0.5f, +0.578125f,0.492188f, +0.585938f,0.5f, +0.585938f,0.492188f, +0.59375f,0.5f, +0.59375f,0.492188f, +0.601563f,0.5f, +0.601563f,0.492188f, +0.609375f,0.5f, +0.609375f,0.492188f, +0.617188f,0.5f, +0.617188f,0.492188f, +0.625f,0.5f, +0.625f,0.492188f, +0.632813f,0.5f, +0.632813f,0.492188f, +0.640625f,0.5f, +0.640625f,0.492188f, +0.648438f,0.5f, +0.648438f,0.492188f, +0.65625f,0.5f, +0.65625f,0.492188f, +0.664063f,0.5f, +0.664063f,0.492188f, +0.671875f,0.5f, +0.671875f,0.492188f, +0.679688f,0.5f, +0.679688f,0.492188f, +0.6875f,0.5f, +0.6875f,0.492188f, +0.695313f,0.5f, +0.695313f,0.492188f, +0.703125f,0.5f, +0.703125f,0.492188f, +0.710938f,0.5f, +0.710938f,0.492188f, +0.71875f,0.5f, +0.71875f,0.492188f, +0.726563f,0.5f, +0.726563f,0.492188f, +0.734375f,0.5f, +0.734375f,0.492188f, +0.742188f,0.5f, +0.742188f,0.492188f, +0.75f,0.5f, +0.75f,0.492188f, +0.757813f,0.5f, +0.757813f,0.492188f, +0.765625f,0.5f, +0.765625f,0.492188f, +0.773438f,0.5f, +0.773438f,0.492188f, +0.78125f,0.5f, +0.78125f,0.492188f, +0.789063f,0.5f, +0.789063f,0.492188f, +0.796875f,0.5f, +0.796875f,0.492188f, +0.804688f,0.5f, +0.804688f,0.492188f, +0.8125f,0.5f, +0.8125f,0.492188f, +0.820313f,0.5f, +0.820313f,0.492188f, +0.828125f,0.5f, +0.828125f,0.492188f, +0.835938f,0.5f, +0.835938f,0.492188f, +0.84375f,0.5f, +0.84375f,0.492188f, +0.851563f,0.5f, +0.851563f,0.492188f, +0.859375f,0.5f, +0.859375f,0.492188f, +0.867188f,0.5f, +0.867188f,0.492188f, +0.875f,0.5f, +0.875f,0.492188f, +0.882813f,0.5f, +0.882813f,0.492188f, +0.890625f,0.5f, +0.890625f,0.492188f, +0.898438f,0.5f, +0.898438f,0.492188f, +0.90625f,0.5f, +0.90625f,0.492188f, +0.914063f,0.5f, +0.914063f,0.492188f, +0.921875f,0.5f, +0.921875f,0.492188f, +0.929688f,0.5f, +0.929688f,0.492188f, +0.9375f,0.5f, +0.9375f,0.492188f, +0.945313f,0.5f, +0.945313f,0.492188f, +0.953125f,0.5f, +0.953125f,0.492188f, +0.960938f,0.5f, +0.960938f,0.492188f, +0.96875f,0.5f, +0.96875f,0.492188f, +0.976563f,0.5f, +0.976563f,0.492188f, +0.984375f,0.5f, +0.984375f,0.492188f, +0.992188f,0.5f, +0.992188f,0.492188f, +1.0f,0.5f, +1.0f,0.492188f, +0.507813f,0.507813f, +0.515625f,0.507813f, +0.523438f,0.507813f, +0.53125f,0.507813f, +0.539063f,0.507813f, +0.546875f,0.507813f, +0.554688f,0.507813f, +0.5625f,0.507813f, +0.570313f,0.507813f, +0.578125f,0.507813f, +0.585938f,0.507813f, +0.59375f,0.507813f, +0.601563f,0.507813f, +0.609375f,0.507813f, +0.617188f,0.507813f, +0.625f,0.507813f, +0.632813f,0.507813f, +0.640625f,0.507813f, +0.648438f,0.507813f, +0.65625f,0.507813f, +0.664063f,0.507813f, +0.671875f,0.507813f, +0.679688f,0.507813f, +0.6875f,0.507813f, +0.695313f,0.507813f, +0.703125f,0.507813f, +0.710938f,0.507813f, +0.71875f,0.507813f, +0.726563f,0.507813f, +0.734375f,0.507813f, +0.742188f,0.507813f, +0.75f,0.507813f, +0.757813f,0.507813f, +0.765625f,0.507813f, +0.773438f,0.507813f, +0.78125f,0.507813f, +0.789063f,0.507813f, +0.796875f,0.507813f, +0.804688f,0.507813f, +0.8125f,0.507813f, +0.820313f,0.507813f, +0.828125f,0.507813f, +0.835938f,0.507813f, +0.84375f,0.507813f, +0.851563f,0.507813f, +0.859375f,0.507813f, +0.867188f,0.507813f, +0.875f,0.507813f, +0.882813f,0.507813f, +0.890625f,0.507813f, +0.898438f,0.507813f, +0.90625f,0.507813f, +0.914063f,0.507813f, +0.921875f,0.507813f, +0.929688f,0.507813f, +0.9375f,0.507813f, +0.945313f,0.507813f, +0.953125f,0.507813f, +0.960938f,0.507813f, +0.96875f,0.507813f, +0.976563f,0.507813f, +0.984375f,0.507813f, +0.992188f,0.507813f, +1.0f,0.507813f, +0.507813f,0.515625f, +0.515625f,0.515625f, +0.523438f,0.515625f, +0.53125f,0.515625f, +0.539063f,0.515625f, +0.546875f,0.515625f, +0.554688f,0.515625f, +0.5625f,0.515625f, +0.570313f,0.515625f, +0.578125f,0.515625f, +0.585938f,0.515625f, +0.59375f,0.515625f, +0.601563f,0.515625f, +0.609375f,0.515625f, +0.617188f,0.515625f, +0.625f,0.515625f, +0.632813f,0.515625f, +0.640625f,0.515625f, +0.648438f,0.515625f, +0.65625f,0.515625f, +0.664063f,0.515625f, +0.671875f,0.515625f, +0.679688f,0.515625f, +0.6875f,0.515625f, +0.695313f,0.515625f, +0.703125f,0.515625f, +0.710938f,0.515625f, +0.71875f,0.515625f, +0.726563f,0.515625f, +0.734375f,0.515625f, +0.742188f,0.515625f, +0.75f,0.515625f, +0.757813f,0.515625f, +0.765625f,0.515625f, +0.773438f,0.515625f, +0.78125f,0.515625f, +0.789063f,0.515625f, +0.796875f,0.515625f, +0.804688f,0.515625f, +0.8125f,0.515625f, +0.820313f,0.515625f, +0.828125f,0.515625f, +0.835938f,0.515625f, +0.84375f,0.515625f, +0.851563f,0.515625f, +0.859375f,0.515625f, +0.867188f,0.515625f, +0.875f,0.515625f, +0.882813f,0.515625f, +0.890625f,0.515625f, +0.898438f,0.515625f, +0.90625f,0.515625f, +0.914063f,0.515625f, +0.921875f,0.515625f, +0.929688f,0.515625f, +0.9375f,0.515625f, +0.945313f,0.515625f, +0.953125f,0.515625f, +0.960938f,0.515625f, +0.96875f,0.515625f, +0.976563f,0.515625f, +0.984375f,0.515625f, +0.992188f,0.515625f, +1.0f,0.515625f, +0.507813f,0.523438f, +0.515625f,0.523438f, +0.523438f,0.523438f, +0.53125f,0.523438f, +0.539063f,0.523438f, +0.546875f,0.523438f, +0.554688f,0.523438f, +0.5625f,0.523438f, +0.570313f,0.523438f, +0.578125f,0.523438f, +0.585938f,0.523438f, +0.59375f,0.523438f, +0.601563f,0.523438f, +0.609375f,0.523438f, +0.617188f,0.523438f, +0.625f,0.523438f, +0.632813f,0.523438f, +0.640625f,0.523438f, +0.648438f,0.523438f, +0.65625f,0.523438f, +0.664063f,0.523438f, +0.671875f,0.523438f, +0.679688f,0.523438f, +0.6875f,0.523438f, +0.695313f,0.523438f, +0.703125f,0.523438f, +0.710938f,0.523438f, +0.71875f,0.523438f, +0.726563f,0.523438f, +0.734375f,0.523438f, +0.742188f,0.523438f, +0.75f,0.523438f, +0.757813f,0.523438f, +0.765625f,0.523438f, +0.773438f,0.523438f, +0.78125f,0.523438f, +0.789063f,0.523438f, +0.796875f,0.523438f, +0.804688f,0.523438f, +0.8125f,0.523438f, +0.820313f,0.523438f, +0.828125f,0.523438f, +0.835938f,0.523438f, +0.84375f,0.523438f, +0.851563f,0.523438f, +0.859375f,0.523438f, +0.867188f,0.523438f, +0.875f,0.523438f, +0.882813f,0.523438f, +0.890625f,0.523438f, +0.898438f,0.523438f, +0.90625f,0.523438f, +0.914063f,0.523438f, +0.921875f,0.523438f, +0.929688f,0.523438f, +0.9375f,0.523438f, +0.945313f,0.523438f, +0.953125f,0.523438f, +0.960938f,0.523438f, +0.96875f,0.523438f, +0.976563f,0.523438f, +0.984375f,0.523438f, +0.992188f,0.523438f, +1.0f,0.523438f, +0.507813f,0.53125f, +0.515625f,0.53125f, +0.523438f,0.53125f, +0.53125f,0.53125f, +0.539063f,0.53125f, +0.546875f,0.53125f, +0.554688f,0.53125f, +0.5625f,0.53125f, +0.570313f,0.53125f, +0.578125f,0.53125f, +0.585938f,0.53125f, +0.59375f,0.53125f, +0.601563f,0.53125f, +0.609375f,0.53125f, +0.617188f,0.53125f, +0.625f,0.53125f, +0.632813f,0.53125f, +0.640625f,0.53125f, +0.648438f,0.53125f, +0.65625f,0.53125f, +0.664063f,0.53125f, +0.671875f,0.53125f, +0.679688f,0.53125f, +0.6875f,0.53125f, +0.695313f,0.53125f, +0.703125f,0.53125f, +0.710938f,0.53125f, +0.71875f,0.53125f, +0.726563f,0.53125f, +0.734375f,0.53125f, +0.742188f,0.53125f, +0.75f,0.53125f, +0.757813f,0.53125f, +0.765625f,0.53125f, +0.773438f,0.53125f, +0.78125f,0.53125f, +0.789063f,0.53125f, +0.796875f,0.53125f, +0.804688f,0.53125f, +0.8125f,0.53125f, +0.820313f,0.53125f, +0.828125f,0.53125f, +0.835938f,0.53125f, +0.84375f,0.53125f, +0.851563f,0.53125f, +0.859375f,0.53125f, +0.867188f,0.53125f, +0.875f,0.53125f, +0.882813f,0.53125f, +0.890625f,0.53125f, +0.898438f,0.53125f, +0.90625f,0.53125f, +0.914063f,0.53125f, +0.921875f,0.53125f, +0.929688f,0.53125f, +0.9375f,0.53125f, +0.945313f,0.53125f, +0.953125f,0.53125f, +0.960938f,0.53125f, +0.96875f,0.53125f, +0.976563f,0.53125f, +0.984375f,0.53125f, +0.992188f,0.53125f, +1.0f,0.53125f, +0.507813f,0.539063f, +0.515625f,0.539063f, +0.523438f,0.539063f, +0.53125f,0.539063f, +0.539063f,0.539063f, +0.546875f,0.539063f, +0.554688f,0.539063f, +0.5625f,0.539063f, +0.570313f,0.539063f, +0.578125f,0.539063f, +0.585938f,0.539063f, +0.59375f,0.539063f, +0.601563f,0.539063f, +0.609375f,0.539063f, +0.617188f,0.539063f, +0.625f,0.539063f, +0.632813f,0.539063f, +0.640625f,0.539063f, +0.648438f,0.539063f, +0.65625f,0.539063f, +0.664063f,0.539063f, +0.671875f,0.539063f, +0.679688f,0.539063f, +0.6875f,0.539063f, +0.695313f,0.539063f, +0.703125f,0.539063f, +0.710938f,0.539063f, +0.71875f,0.539063f, +0.726563f,0.539063f, +0.734375f,0.539063f, +0.742188f,0.539063f, +0.75f,0.539063f, +0.757813f,0.539063f, +0.765625f,0.539063f, +0.773438f,0.539063f, +0.78125f,0.539063f, +0.789063f,0.539063f, +0.796875f,0.539063f, +0.804688f,0.539063f, +0.8125f,0.539063f, +0.820313f,0.539063f, +0.828125f,0.539063f, +0.835938f,0.539063f, +0.84375f,0.539063f, +0.851563f,0.539063f, +0.859375f,0.539063f, +0.867188f,0.539063f, +0.875f,0.539063f, +0.882813f,0.539063f, +0.890625f,0.539063f, +0.898438f,0.539063f, +0.90625f,0.539063f, +0.914063f,0.539063f, +0.921875f,0.539063f, +0.929688f,0.539063f, +0.9375f,0.539063f, +0.945313f,0.539063f, +0.953125f,0.539063f, +0.960938f,0.539063f, +0.96875f,0.539063f, +0.976563f,0.539063f, +0.984375f,0.539063f, +0.992188f,0.539063f, +1.0f,0.539063f, +0.507813f,0.546875f, +0.515625f,0.546875f, +0.523438f,0.546875f, +0.53125f,0.546875f, +0.539063f,0.546875f, +0.546875f,0.546875f, +0.554688f,0.546875f, +0.5625f,0.546875f, +0.570313f,0.546875f, +0.578125f,0.546875f, +0.585938f,0.546875f, +0.59375f,0.546875f, +0.601563f,0.546875f, +0.609375f,0.546875f, +0.617188f,0.546875f, +0.625f,0.546875f, +0.632813f,0.546875f, +0.640625f,0.546875f, +0.648438f,0.546875f, +0.65625f,0.546875f, +0.664063f,0.546875f, +0.671875f,0.546875f, +0.679688f,0.546875f, +0.6875f,0.546875f, +0.695313f,0.546875f, +0.703125f,0.546875f, +0.710938f,0.546875f, +0.71875f,0.546875f, +0.726563f,0.546875f, +0.734375f,0.546875f, +0.742188f,0.546875f, +0.75f,0.546875f, +0.757813f,0.546875f, +0.765625f,0.546875f, +0.773438f,0.546875f, +0.78125f,0.546875f, +0.789063f,0.546875f, +0.796875f,0.546875f, +0.804688f,0.546875f, +0.8125f,0.546875f, +0.820313f,0.546875f, +0.828125f,0.546875f, +0.835938f,0.546875f, +0.84375f,0.546875f, +0.851563f,0.546875f, +0.859375f,0.546875f, +0.867188f,0.546875f, +0.875f,0.546875f, +0.882813f,0.546875f, +0.890625f,0.546875f, +0.898438f,0.546875f, +0.90625f,0.546875f, +0.914063f,0.546875f, +0.921875f,0.546875f, +0.929688f,0.546875f, +0.9375f,0.546875f, +0.945313f,0.546875f, +0.953125f,0.546875f, +0.960938f,0.546875f, +0.96875f,0.546875f, +0.976563f,0.546875f, +0.984375f,0.546875f, +0.992188f,0.546875f, +1.0f,0.546875f, +0.507813f,0.554688f, +0.515625f,0.554688f, +0.523438f,0.554688f, +0.53125f,0.554688f, +0.539063f,0.554688f, +0.546875f,0.554688f, +0.554688f,0.554688f, +0.5625f,0.554688f, +0.570313f,0.554688f, +0.578125f,0.554688f, +0.585938f,0.554688f, +0.59375f,0.554688f, +0.601563f,0.554688f, +0.609375f,0.554688f, +0.617188f,0.554688f, +0.625f,0.554688f, +0.632813f,0.554688f, +0.640625f,0.554688f, +0.648438f,0.554688f, +0.65625f,0.554688f, +0.664063f,0.554688f, +0.671875f,0.554688f, +0.679688f,0.554688f, +0.6875f,0.554688f, +0.695313f,0.554688f, +0.703125f,0.554688f, +0.710938f,0.554688f, +0.71875f,0.554688f, +0.726563f,0.554688f, +0.734375f,0.554688f, +0.742188f,0.554688f, +0.75f,0.554688f, +0.757813f,0.554688f, +0.765625f,0.554688f, +0.773438f,0.554688f, +0.78125f,0.554688f, +0.789063f,0.554688f, +0.796875f,0.554688f, +0.804688f,0.554688f, +0.8125f,0.554688f, +0.820313f,0.554688f, +0.828125f,0.554688f, +0.835938f,0.554688f, +0.84375f,0.554688f, +0.851563f,0.554688f, +0.859375f,0.554688f, +0.867188f,0.554688f, +0.875f,0.554688f, +0.882813f,0.554688f, +0.890625f,0.554688f, +0.898438f,0.554688f, +0.90625f,0.554688f, +0.914063f,0.554688f, +0.921875f,0.554688f, +0.929688f,0.554688f, +0.9375f,0.554688f, +0.945313f,0.554688f, +0.953125f,0.554688f, +0.960938f,0.554688f, +0.96875f,0.554688f, +0.976563f,0.554688f, +0.984375f,0.554688f, +0.992188f,0.554688f, +1.0f,0.554688f, +0.507813f,0.5625f, +0.515625f,0.5625f, +0.523438f,0.5625f, +0.53125f,0.5625f, +0.539063f,0.5625f, +0.546875f,0.5625f, +0.554688f,0.5625f, +0.5625f,0.5625f, +0.570313f,0.5625f, +0.578125f,0.5625f, +0.585938f,0.5625f, +0.59375f,0.5625f, +0.601563f,0.5625f, +0.609375f,0.5625f, +0.617188f,0.5625f, +0.625f,0.5625f, +0.632813f,0.5625f, +0.640625f,0.5625f, +0.648438f,0.5625f, +0.65625f,0.5625f, +0.664063f,0.5625f, +0.671875f,0.5625f, +0.679688f,0.5625f, +0.6875f,0.5625f, +0.695313f,0.5625f, +0.703125f,0.5625f, +0.710938f,0.5625f, +0.71875f,0.5625f, +0.726563f,0.5625f, +0.734375f,0.5625f, +0.742188f,0.5625f, +0.75f,0.5625f, +0.757813f,0.5625f, +0.765625f,0.5625f, +0.773438f,0.5625f, +0.78125f,0.5625f, +0.789063f,0.5625f, +0.796875f,0.5625f, +0.804688f,0.5625f, +0.8125f,0.5625f, +0.820313f,0.5625f, +0.828125f,0.5625f, +0.835938f,0.5625f, +0.84375f,0.5625f, +0.851563f,0.5625f, +0.859375f,0.5625f, +0.867188f,0.5625f, +0.875f,0.5625f, +0.882813f,0.5625f, +0.890625f,0.5625f, +0.898438f,0.5625f, +0.90625f,0.5625f, +0.914063f,0.5625f, +0.921875f,0.5625f, +0.929688f,0.5625f, +0.9375f,0.5625f, +0.945313f,0.5625f, +0.953125f,0.5625f, +0.960938f,0.5625f, +0.96875f,0.5625f, +0.976563f,0.5625f, +0.984375f,0.5625f, +0.992188f,0.5625f, +1.0f,0.5625f, +0.507813f,0.570313f, +0.515625f,0.570313f, +0.523438f,0.570313f, +0.53125f,0.570313f, +0.539063f,0.570313f, +0.546875f,0.570313f, +0.554688f,0.570313f, +0.5625f,0.570313f, +0.570313f,0.570313f, +0.578125f,0.570313f, +0.585938f,0.570313f, +0.59375f,0.570313f, +0.601563f,0.570313f, +0.609375f,0.570313f, +0.617188f,0.570313f, +0.625f,0.570313f, +0.632813f,0.570313f, +0.640625f,0.570313f, +0.648438f,0.570313f, +0.65625f,0.570313f, +0.664063f,0.570313f, +0.671875f,0.570313f, +0.679688f,0.570313f, +0.6875f,0.570313f, +0.695313f,0.570313f, +0.703125f,0.570313f, +0.710938f,0.570313f, +0.71875f,0.570313f, +0.726563f,0.570313f, +0.734375f,0.570313f, +0.742188f,0.570313f, +0.75f,0.570313f, +0.757813f,0.570313f, +0.765625f,0.570313f, +0.773438f,0.570313f, +0.78125f,0.570313f, +0.789063f,0.570313f, +0.796875f,0.570313f, +0.804688f,0.570313f, +0.8125f,0.570313f, +0.820313f,0.570313f, +0.828125f,0.570313f, +0.835938f,0.570313f, +0.84375f,0.570313f, +0.851563f,0.570313f, +0.859375f,0.570313f, +0.867188f,0.570313f, +0.875f,0.570313f, +0.882813f,0.570313f, +0.890625f,0.570313f, +0.898438f,0.570313f, +0.90625f,0.570313f, +0.914063f,0.570313f, +0.921875f,0.570313f, +0.929688f,0.570313f, +0.9375f,0.570313f, +0.945313f,0.570313f, +0.953125f,0.570313f, +0.960938f,0.570313f, +0.96875f,0.570313f, +0.976563f,0.570313f, +0.984375f,0.570313f, +0.992188f,0.570313f, +1.0f,0.570313f, +0.507813f,0.578125f, +0.515625f,0.578125f, +0.523438f,0.578125f, +0.53125f,0.578125f, +0.539063f,0.578125f, +0.546875f,0.578125f, +0.554688f,0.578125f, +0.5625f,0.578125f, +0.570313f,0.578125f, +0.578125f,0.578125f, +0.585938f,0.578125f, +0.59375f,0.578125f, +0.601563f,0.578125f, +0.609375f,0.578125f, +0.617188f,0.578125f, +0.625f,0.578125f, +0.632813f,0.578125f, +0.640625f,0.578125f, +0.648438f,0.578125f, +0.65625f,0.578125f, +0.664063f,0.578125f, +0.671875f,0.578125f, +0.679688f,0.578125f, +0.6875f,0.578125f, +0.695313f,0.578125f, +0.703125f,0.578125f, +0.710938f,0.578125f, +0.71875f,0.578125f, +0.726563f,0.578125f, +0.734375f,0.578125f, +0.742188f,0.578125f, +0.75f,0.578125f, +0.757813f,0.578125f, +0.765625f,0.578125f, +0.773438f,0.578125f, +0.78125f,0.578125f, +0.789063f,0.578125f, +0.796875f,0.578125f, +0.804688f,0.578125f, +0.8125f,0.578125f, +0.820313f,0.578125f, +0.828125f,0.578125f, +0.835938f,0.578125f, +0.84375f,0.578125f, +0.851563f,0.578125f, +0.859375f,0.578125f, +0.867188f,0.578125f, +0.875f,0.578125f, +0.882813f,0.578125f, +0.890625f,0.578125f, +0.898438f,0.578125f, +0.90625f,0.578125f, +0.914063f,0.578125f, +0.921875f,0.578125f, +0.929688f,0.578125f, +0.9375f,0.578125f, +0.945313f,0.578125f, +0.953125f,0.578125f, +0.960938f,0.578125f, +0.96875f,0.578125f, +0.976563f,0.578125f, +0.984375f,0.578125f, +0.992188f,0.578125f, +1.0f,0.578125f, +0.507813f,0.585938f, +0.515625f,0.585938f, +0.523438f,0.585938f, +0.53125f,0.585938f, +0.539063f,0.585938f, +0.546875f,0.585938f, +0.554688f,0.585938f, +0.5625f,0.585938f, +0.570313f,0.585938f, +0.578125f,0.585938f, +0.585938f,0.585938f, +0.59375f,0.585938f, +0.601563f,0.585938f, +0.609375f,0.585938f, +0.617188f,0.585938f, +0.625f,0.585938f, +0.632813f,0.585938f, +0.640625f,0.585938f, +0.648438f,0.585938f, +0.65625f,0.585938f, +0.664063f,0.585938f, +0.671875f,0.585938f, +0.679688f,0.585938f, +0.6875f,0.585938f, +0.695313f,0.585938f, +0.703125f,0.585938f, +0.710938f,0.585938f, +0.71875f,0.585938f, +0.726563f,0.585938f, +0.734375f,0.585938f, +0.742188f,0.585938f, +0.75f,0.585938f, +0.757813f,0.585938f, +0.765625f,0.585938f, +0.773438f,0.585938f, +0.78125f,0.585938f, +0.789063f,0.585938f, +0.796875f,0.585938f, +0.804688f,0.585938f, +0.8125f,0.585938f, +0.820313f,0.585938f, +0.828125f,0.585938f, +0.835938f,0.585938f, +0.84375f,0.585938f, +0.851563f,0.585938f, +0.859375f,0.585938f, +0.867188f,0.585938f, +0.875f,0.585938f, +0.882813f,0.585938f, +0.890625f,0.585938f, +0.898438f,0.585938f, +0.90625f,0.585938f, +0.914063f,0.585938f, +0.921875f,0.585938f, +0.929688f,0.585938f, +0.9375f,0.585938f, +0.945313f,0.585938f, +0.953125f,0.585938f, +0.960938f,0.585938f, +0.96875f,0.585938f, +0.976563f,0.585938f, +0.984375f,0.585938f, +0.992188f,0.585938f, +1.0f,0.585938f, +0.507813f,0.59375f, +0.515625f,0.59375f, +0.523438f,0.59375f, +0.53125f,0.59375f, +0.539063f,0.59375f, +0.546875f,0.59375f, +0.554688f,0.59375f, +0.5625f,0.59375f, +0.570313f,0.59375f, +0.578125f,0.59375f, +0.585938f,0.59375f, +0.59375f,0.59375f, +0.601563f,0.59375f, +0.609375f,0.59375f, +0.617188f,0.59375f, +0.625f,0.59375f, +0.632813f,0.59375f, +0.640625f,0.59375f, +0.648438f,0.59375f, +0.65625f,0.59375f, +0.664063f,0.59375f, +0.671875f,0.59375f, +0.679688f,0.59375f, +0.6875f,0.59375f, +0.695313f,0.59375f, +0.703125f,0.59375f, +0.710938f,0.59375f, +0.71875f,0.59375f, +0.726563f,0.59375f, +0.734375f,0.59375f, +0.742188f,0.59375f, +0.75f,0.59375f, +0.757813f,0.59375f, +0.765625f,0.59375f, +0.773438f,0.59375f, +0.78125f,0.59375f, +0.789063f,0.59375f, +0.796875f,0.59375f, +0.804688f,0.59375f, +0.8125f,0.59375f, +0.820313f,0.59375f, +0.828125f,0.59375f, +0.835938f,0.59375f, +0.84375f,0.59375f, +0.851563f,0.59375f, +0.859375f,0.59375f, +0.867188f,0.59375f, +0.875f,0.59375f, +0.882813f,0.59375f, +0.890625f,0.59375f, +0.898438f,0.59375f, +0.90625f,0.59375f, +0.914063f,0.59375f, +0.921875f,0.59375f, +0.929688f,0.59375f, +0.9375f,0.59375f, +0.945313f,0.59375f, +0.953125f,0.59375f, +0.960938f,0.59375f, +0.96875f,0.59375f, +0.976563f,0.59375f, +0.984375f,0.59375f, +0.992188f,0.59375f, +1.0f,0.59375f, +0.507813f,0.601563f, +0.515625f,0.601563f, +0.523438f,0.601563f, +0.53125f,0.601563f, +0.539063f,0.601563f, +0.546875f,0.601563f, +0.554688f,0.601563f, +0.5625f,0.601563f, +0.570313f,0.601563f, +0.578125f,0.601563f, +0.585938f,0.601563f, +0.59375f,0.601563f, +0.601563f,0.601563f, +0.609375f,0.601563f, +0.617188f,0.601563f, +0.625f,0.601563f, +0.632813f,0.601563f, +0.640625f,0.601563f, +0.648438f,0.601563f, +0.65625f,0.601563f, +0.664063f,0.601563f, +0.671875f,0.601563f, +0.679688f,0.601563f, +0.6875f,0.601563f, +0.695313f,0.601563f, +0.703125f,0.601563f, +0.710938f,0.601563f, +0.71875f,0.601563f, +0.726563f,0.601563f, +0.734375f,0.601563f, +0.742188f,0.601563f, +0.75f,0.601563f, +0.757813f,0.601563f, +0.765625f,0.601563f, +0.773438f,0.601563f, +0.78125f,0.601563f, +0.789063f,0.601563f, +0.796875f,0.601563f, +0.804688f,0.601563f, +0.8125f,0.601563f, +0.820313f,0.601563f, +0.828125f,0.601563f, +0.835938f,0.601563f, +0.84375f,0.601563f, +0.851563f,0.601563f, +0.859375f,0.601563f, +0.867188f,0.601563f, +0.875f,0.601563f, +0.882813f,0.601563f, +0.890625f,0.601563f, +0.898438f,0.601563f, +0.90625f,0.601563f, +0.914063f,0.601563f, +0.921875f,0.601563f, +0.929688f,0.601563f, +0.9375f,0.601563f, +0.945313f,0.601563f, +0.953125f,0.601563f, +0.960938f,0.601563f, +0.96875f,0.601563f, +0.976563f,0.601563f, +0.984375f,0.601563f, +0.992188f,0.601563f, +1.0f,0.601563f, +0.507813f,0.609375f, +0.515625f,0.609375f, +0.523438f,0.609375f, +0.53125f,0.609375f, +0.539063f,0.609375f, +0.546875f,0.609375f, +0.554688f,0.609375f, +0.5625f,0.609375f, +0.570313f,0.609375f, +0.578125f,0.609375f, +0.585938f,0.609375f, +0.59375f,0.609375f, +0.601563f,0.609375f, +0.609375f,0.609375f, +0.617188f,0.609375f, +0.625f,0.609375f, +0.632813f,0.609375f, +0.640625f,0.609375f, +0.648438f,0.609375f, +0.65625f,0.609375f, +0.664063f,0.609375f, +0.671875f,0.609375f, +0.679688f,0.609375f, +0.6875f,0.609375f, +0.695313f,0.609375f, +0.703125f,0.609375f, +0.710938f,0.609375f, +0.71875f,0.609375f, +0.726563f,0.609375f, +0.734375f,0.609375f, +0.742188f,0.609375f, +0.75f,0.609375f, +0.757813f,0.609375f, +0.765625f,0.609375f, +0.773438f,0.609375f, +0.78125f,0.609375f, +0.789063f,0.609375f, +0.796875f,0.609375f, +0.804688f,0.609375f, +0.8125f,0.609375f, +0.820313f,0.609375f, +0.828125f,0.609375f, +0.835938f,0.609375f, +0.84375f,0.609375f, +0.851563f,0.609375f, +0.859375f,0.609375f, +0.867188f,0.609375f, +0.875f,0.609375f, +0.882813f,0.609375f, +0.890625f,0.609375f, +0.898438f,0.609375f, +0.90625f,0.609375f, +0.914063f,0.609375f, +0.921875f,0.609375f, +0.929688f,0.609375f, +0.9375f,0.609375f, +0.945313f,0.609375f, +0.953125f,0.609375f, +0.960938f,0.609375f, +0.96875f,0.609375f, +0.976563f,0.609375f, +0.984375f,0.609375f, +0.992188f,0.609375f, +1.0f,0.609375f, +0.507813f,0.617188f, +0.515625f,0.617188f, +0.523438f,0.617188f, +0.53125f,0.617188f, +0.539063f,0.617188f, +0.546875f,0.617188f, +0.554688f,0.617188f, +0.5625f,0.617188f, +0.570313f,0.617188f, +0.578125f,0.617188f, +0.585938f,0.617188f, +0.59375f,0.617188f, +0.601563f,0.617188f, +0.609375f,0.617188f, +0.617188f,0.617188f, +0.625f,0.617188f, +0.632813f,0.617188f, +0.640625f,0.617188f, +0.648438f,0.617188f, +0.65625f,0.617188f, +0.664063f,0.617188f, +0.671875f,0.617188f, +0.679688f,0.617188f, +0.6875f,0.617188f, +0.695313f,0.617188f, +0.703125f,0.617188f, +0.710938f,0.617188f, +0.71875f,0.617188f, +0.726563f,0.617188f, +0.734375f,0.617188f, +0.742188f,0.617188f, +0.75f,0.617188f, +0.757813f,0.617188f, +0.765625f,0.617188f, +0.773438f,0.617188f, +0.78125f,0.617188f, +0.789063f,0.617188f, +0.796875f,0.617188f, +0.804688f,0.617188f, +0.8125f,0.617188f, +0.820313f,0.617188f, +0.828125f,0.617188f, +0.835938f,0.617188f, +0.84375f,0.617188f, +0.851563f,0.617188f, +0.859375f,0.617188f, +0.867188f,0.617188f, +0.875f,0.617188f, +0.882813f,0.617188f, +0.890625f,0.617188f, +0.898438f,0.617188f, +0.90625f,0.617188f, +0.914063f,0.617188f, +0.921875f,0.617188f, +0.929688f,0.617188f, +0.9375f,0.617188f, +0.945313f,0.617188f, +0.953125f,0.617188f, +0.960938f,0.617188f, +0.96875f,0.617188f, +0.976563f,0.617188f, +0.984375f,0.617188f, +0.992188f,0.617188f, +1.0f,0.617188f, +0.507813f,0.625f, +0.515625f,0.625f, +0.523438f,0.625f, +0.53125f,0.625f, +0.539063f,0.625f, +0.546875f,0.625f, +0.554688f,0.625f, +0.5625f,0.625f, +0.570313f,0.625f, +0.578125f,0.625f, +0.585938f,0.625f, +0.59375f,0.625f, +0.601563f,0.625f, +0.609375f,0.625f, +0.617188f,0.625f, +0.625f,0.625f, +0.632813f,0.625f, +0.640625f,0.625f, +0.648438f,0.625f, +0.65625f,0.625f, +0.664063f,0.625f, +0.671875f,0.625f, +0.679688f,0.625f, +0.6875f,0.625f, +0.695313f,0.625f, +0.703125f,0.625f, +0.710938f,0.625f, +0.71875f,0.625f, +0.726563f,0.625f, +0.734375f,0.625f, +0.742188f,0.625f, +0.75f,0.625f, +0.757813f,0.625f, +0.765625f,0.625f, +0.773438f,0.625f, +0.78125f,0.625f, +0.789063f,0.625f, +0.796875f,0.625f, +0.804688f,0.625f, +0.8125f,0.625f, +0.820313f,0.625f, +0.828125f,0.625f, +0.835938f,0.625f, +0.84375f,0.625f, +0.851563f,0.625f, +0.859375f,0.625f, +0.867188f,0.625f, +0.875f,0.625f, +0.882813f,0.625f, +0.890625f,0.625f, +0.898438f,0.625f, +0.90625f,0.625f, +0.914063f,0.625f, +0.921875f,0.625f, +0.929688f,0.625f, +0.9375f,0.625f, +0.945313f,0.625f, +0.953125f,0.625f, +0.960938f,0.625f, +0.96875f,0.625f, +0.976563f,0.625f, +0.984375f,0.625f, +0.992188f,0.625f, +1.0f,0.625f, +0.507813f,0.632813f, +0.515625f,0.632813f, +0.523438f,0.632813f, +0.53125f,0.632813f, +0.539063f,0.632813f, +0.546875f,0.632813f, +0.554688f,0.632813f, +0.5625f,0.632813f, +0.570313f,0.632813f, +0.578125f,0.632813f, +0.585938f,0.632813f, +0.59375f,0.632813f, +0.601563f,0.632813f, +0.609375f,0.632813f, +0.617188f,0.632813f, +0.625f,0.632813f, +0.632813f,0.632813f, +0.640625f,0.632813f, +0.648438f,0.632813f, +0.65625f,0.632813f, +0.664063f,0.632813f, +0.671875f,0.632813f, +0.679688f,0.632813f, +0.6875f,0.632813f, +0.695313f,0.632813f, +0.703125f,0.632813f, +0.710938f,0.632813f, +0.71875f,0.632813f, +0.726563f,0.632813f, +0.734375f,0.632813f, +0.742188f,0.632813f, +0.75f,0.632813f, +0.757813f,0.632813f, +0.765625f,0.632813f, +0.773438f,0.632813f, +0.78125f,0.632813f, +0.789063f,0.632813f, +0.796875f,0.632813f, +0.804688f,0.632813f, +0.8125f,0.632813f, +0.820313f,0.632813f, +0.828125f,0.632813f, +0.835938f,0.632813f, +0.84375f,0.632813f, +0.851563f,0.632813f, +0.859375f,0.632813f, +0.867188f,0.632813f, +0.875f,0.632813f, +0.882813f,0.632813f, +0.890625f,0.632813f, +0.898438f,0.632813f, +0.90625f,0.632813f, +0.914063f,0.632813f, +0.921875f,0.632813f, +0.929688f,0.632813f, +0.9375f,0.632813f, +0.945313f,0.632813f, +0.953125f,0.632813f, +0.960938f,0.632813f, +0.96875f,0.632813f, +0.976563f,0.632813f, +0.984375f,0.632813f, +0.992188f,0.632813f, +1.0f,0.632813f, +0.507813f,0.640625f, +0.515625f,0.640625f, +0.523438f,0.640625f, +0.53125f,0.640625f, +0.539063f,0.640625f, +0.546875f,0.640625f, +0.554688f,0.640625f, +0.5625f,0.640625f, +0.570313f,0.640625f, +0.578125f,0.640625f, +0.585938f,0.640625f, +0.59375f,0.640625f, +0.601563f,0.640625f, +0.609375f,0.640625f, +0.617188f,0.640625f, +0.625f,0.640625f, +0.632813f,0.640625f, +0.640625f,0.640625f, +0.648438f,0.640625f, +0.65625f,0.640625f, +0.664063f,0.640625f, +0.671875f,0.640625f, +0.679688f,0.640625f, +0.6875f,0.640625f, +0.695313f,0.640625f, +0.703125f,0.640625f, +0.710938f,0.640625f, +0.71875f,0.640625f, +0.726563f,0.640625f, +0.734375f,0.640625f, +0.742188f,0.640625f, +0.75f,0.640625f, +0.757813f,0.640625f, +0.765625f,0.640625f, +0.773438f,0.640625f, +0.78125f,0.640625f, +0.789063f,0.640625f, +0.796875f,0.640625f, +0.804688f,0.640625f, +0.8125f,0.640625f, +0.820313f,0.640625f, +0.828125f,0.640625f, +0.835938f,0.640625f, +0.84375f,0.640625f, +0.851563f,0.640625f, +0.859375f,0.640625f, +0.867188f,0.640625f, +0.875f,0.640625f, +0.882813f,0.640625f, +0.890625f,0.640625f, +0.898438f,0.640625f, +0.90625f,0.640625f, +0.914063f,0.640625f, +0.921875f,0.640625f, +0.929688f,0.640625f, +0.9375f,0.640625f, +0.945313f,0.640625f, +0.953125f,0.640625f, +0.960938f,0.640625f, +0.96875f,0.640625f, +0.976563f,0.640625f, +0.984375f,0.640625f, +0.992188f,0.640625f, +1.0f,0.640625f, +0.507813f,0.648438f, +0.515625f,0.648438f, +0.523438f,0.648438f, +0.53125f,0.648438f, +0.539063f,0.648438f, +0.546875f,0.648438f, +0.554688f,0.648438f, +0.5625f,0.648438f, +0.570313f,0.648438f, +0.578125f,0.648438f, +0.585938f,0.648438f, +0.59375f,0.648438f, +0.601563f,0.648438f, +0.609375f,0.648438f, +0.617188f,0.648438f, +0.625f,0.648438f, +0.632813f,0.648438f, +0.640625f,0.648438f, +0.648438f,0.648438f, +0.65625f,0.648438f, +0.664063f,0.648438f, +0.671875f,0.648438f, +0.679688f,0.648438f, +0.6875f,0.648438f, +0.695313f,0.648438f, +0.703125f,0.648438f, +0.710938f,0.648438f, +0.71875f,0.648438f, +0.726563f,0.648438f, +0.734375f,0.648438f, +0.742188f,0.648438f, +0.75f,0.648438f, +0.757813f,0.648438f, +0.765625f,0.648438f, +0.773438f,0.648438f, +0.78125f,0.648438f, +0.789063f,0.648438f, +0.796875f,0.648438f, +0.804688f,0.648438f, +0.8125f,0.648438f, +0.820313f,0.648438f, +0.828125f,0.648438f, +0.835938f,0.648438f, +0.84375f,0.648438f, +0.851563f,0.648438f, +0.859375f,0.648438f, +0.867188f,0.648438f, +0.875f,0.648438f, +0.882813f,0.648438f, +0.890625f,0.648438f, +0.898438f,0.648438f, +0.90625f,0.648438f, +0.914063f,0.648438f, +0.921875f,0.648438f, +0.929688f,0.648438f, +0.9375f,0.648438f, +0.945313f,0.648438f, +0.953125f,0.648438f, +0.960938f,0.648438f, +0.96875f,0.648438f, +0.976563f,0.648438f, +0.984375f,0.648438f, +0.992188f,0.648438f, +1.0f,0.648438f, +0.507813f,0.65625f, +0.515625f,0.65625f, +0.523438f,0.65625f, +0.53125f,0.65625f, +0.539063f,0.65625f, +0.546875f,0.65625f, +0.554688f,0.65625f, +0.5625f,0.65625f, +0.570313f,0.65625f, +0.578125f,0.65625f, +0.585938f,0.65625f, +0.59375f,0.65625f, +0.601563f,0.65625f, +0.609375f,0.65625f, +0.617188f,0.65625f, +0.625f,0.65625f, +0.632813f,0.65625f, +0.640625f,0.65625f, +0.648438f,0.65625f, +0.65625f,0.65625f, +0.664063f,0.65625f, +0.671875f,0.65625f, +0.679688f,0.65625f, +0.6875f,0.65625f, +0.695313f,0.65625f, +0.703125f,0.65625f, +0.710938f,0.65625f, +0.71875f,0.65625f, +0.726563f,0.65625f, +0.734375f,0.65625f, +0.742188f,0.65625f, +0.75f,0.65625f, +0.757813f,0.65625f, +0.765625f,0.65625f, +0.773438f,0.65625f, +0.78125f,0.65625f, +0.789063f,0.65625f, +0.796875f,0.65625f, +0.804688f,0.65625f, +0.8125f,0.65625f, +0.820313f,0.65625f, +0.828125f,0.65625f, +0.835938f,0.65625f, +0.84375f,0.65625f, +0.851563f,0.65625f, +0.859375f,0.65625f, +0.867188f,0.65625f, +0.875f,0.65625f, +0.882813f,0.65625f, +0.890625f,0.65625f, +0.898438f,0.65625f, +0.90625f,0.65625f, +0.914063f,0.65625f, +0.921875f,0.65625f, +0.929688f,0.65625f, +0.9375f,0.65625f, +0.945313f,0.65625f, +0.953125f,0.65625f, +0.960938f,0.65625f, +0.96875f,0.65625f, +0.976563f,0.65625f, +0.984375f,0.65625f, +0.992188f,0.65625f, +1.0f,0.65625f, +0.507813f,0.664063f, +0.515625f,0.664063f, +0.523438f,0.664063f, +0.53125f,0.664063f, +0.539063f,0.664063f, +0.546875f,0.664063f, +0.554688f,0.664063f, +0.5625f,0.664063f, +0.570313f,0.664063f, +0.578125f,0.664063f, +0.585938f,0.664063f, +0.59375f,0.664063f, +0.601563f,0.664063f, +0.609375f,0.664063f, +0.617188f,0.664063f, +0.625f,0.664063f, +0.632813f,0.664063f, +0.640625f,0.664063f, +0.648438f,0.664063f, +0.65625f,0.664063f, +0.664063f,0.664063f, +0.671875f,0.664063f, +0.679688f,0.664063f, +0.6875f,0.664063f, +0.695313f,0.664063f, +0.703125f,0.664063f, +0.710938f,0.664063f, +0.71875f,0.664063f, +0.726563f,0.664063f, +0.734375f,0.664063f, +0.742188f,0.664063f, +0.75f,0.664063f, +0.757813f,0.664063f, +0.765625f,0.664063f, +0.773438f,0.664063f, +0.78125f,0.664063f, +0.789063f,0.664063f, +0.796875f,0.664063f, +0.804688f,0.664063f, +0.8125f,0.664063f, +0.820313f,0.664063f, +0.828125f,0.664063f, +0.835938f,0.664063f, +0.84375f,0.664063f, +0.851563f,0.664063f, +0.859375f,0.664063f, +0.867188f,0.664063f, +0.875f,0.664063f, +0.882813f,0.664063f, +0.890625f,0.664063f, +0.898438f,0.664063f, +0.90625f,0.664063f, +0.914063f,0.664063f, +0.921875f,0.664063f, +0.929688f,0.664063f, +0.9375f,0.664063f, +0.945313f,0.664063f, +0.953125f,0.664063f, +0.960938f,0.664063f, +0.96875f,0.664063f, +0.976563f,0.664063f, +0.984375f,0.664063f, +0.992188f,0.664063f, +1.0f,0.664063f, +0.507813f,0.671875f, +0.515625f,0.671875f, +0.523438f,0.671875f, +0.53125f,0.671875f, +0.539063f,0.671875f, +0.546875f,0.671875f, +0.554688f,0.671875f, +0.5625f,0.671875f, +0.570313f,0.671875f, +0.578125f,0.671875f, +0.585938f,0.671875f, +0.59375f,0.671875f, +0.601563f,0.671875f, +0.609375f,0.671875f, +0.617188f,0.671875f, +0.625f,0.671875f, +0.632813f,0.671875f, +0.640625f,0.671875f, +0.648438f,0.671875f, +0.65625f,0.671875f, +0.664063f,0.671875f, +0.671875f,0.671875f, +0.679688f,0.671875f, +0.6875f,0.671875f, +0.695313f,0.671875f, +0.703125f,0.671875f, +0.710938f,0.671875f, +0.71875f,0.671875f, +0.726563f,0.671875f, +0.734375f,0.671875f, +0.742188f,0.671875f, +0.75f,0.671875f, +0.757813f,0.671875f, +0.765625f,0.671875f, +0.773438f,0.671875f, +0.78125f,0.671875f, +0.789063f,0.671875f, +0.796875f,0.671875f, +0.804688f,0.671875f, +0.8125f,0.671875f, +0.820313f,0.671875f, +0.828125f,0.671875f, +0.835938f,0.671875f, +0.84375f,0.671875f, +0.851563f,0.671875f, +0.859375f,0.671875f, +0.867188f,0.671875f, +0.875f,0.671875f, +0.882813f,0.671875f, +0.890625f,0.671875f, +0.898438f,0.671875f, +0.90625f,0.671875f, +0.914063f,0.671875f, +0.921875f,0.671875f, +0.929688f,0.671875f, +0.9375f,0.671875f, +0.945313f,0.671875f, +0.953125f,0.671875f, +0.960938f,0.671875f, +0.96875f,0.671875f, +0.976563f,0.671875f, +0.984375f,0.671875f, +0.992188f,0.671875f, +1.0f,0.671875f, +0.507813f,0.679688f, +0.515625f,0.679688f, +0.523438f,0.679688f, +0.53125f,0.679688f, +0.539063f,0.679688f, +0.546875f,0.679688f, +0.554688f,0.679688f, +0.5625f,0.679688f, +0.570313f,0.679688f, +0.578125f,0.679688f, +0.585938f,0.679688f, +0.59375f,0.679688f, +0.601563f,0.679688f, +0.609375f,0.679688f, +0.617188f,0.679688f, +0.625f,0.679688f, +0.632813f,0.679688f, +0.640625f,0.679688f, +0.648438f,0.679688f, +0.65625f,0.679688f, +0.664063f,0.679688f, +0.671875f,0.679688f, +0.679688f,0.679688f, +0.6875f,0.679688f, +0.695313f,0.679688f, +0.703125f,0.679688f, +0.710938f,0.679688f, +0.71875f,0.679688f, +0.726563f,0.679688f, +0.734375f,0.679688f, +0.742188f,0.679688f, +0.75f,0.679688f, +0.757813f,0.679688f, +0.765625f,0.679688f, +0.773438f,0.679688f, +0.78125f,0.679688f, +0.789063f,0.679688f, +0.796875f,0.679688f, +0.804688f,0.679688f, +0.8125f,0.679688f, +0.820313f,0.679688f, +0.828125f,0.679688f, +0.835938f,0.679688f, +0.84375f,0.679688f, +0.851563f,0.679688f, +0.859375f,0.679688f, +0.867188f,0.679688f, +0.875f,0.679688f, +0.882813f,0.679688f, +0.890625f,0.679688f, +0.898438f,0.679688f, +0.90625f,0.679688f, +0.914063f,0.679688f, +0.921875f,0.679688f, +0.929688f,0.679688f, +0.9375f,0.679688f, +0.945313f,0.679688f, +0.953125f,0.679688f, +0.960938f,0.679688f, +0.96875f,0.679688f, +0.976563f,0.679688f, +0.984375f,0.679688f, +0.992188f,0.679688f, +1.0f,0.679688f, +0.507813f,0.6875f, +0.515625f,0.6875f, +0.523438f,0.6875f, +0.53125f,0.6875f, +0.539063f,0.6875f, +0.546875f,0.6875f, +0.554688f,0.6875f, +0.5625f,0.6875f, +0.570313f,0.6875f, +0.578125f,0.6875f, +0.585938f,0.6875f, +0.59375f,0.6875f, +0.601563f,0.6875f, +0.609375f,0.6875f, +0.617188f,0.6875f, +0.625f,0.6875f, +0.632813f,0.6875f, +0.640625f,0.6875f, +0.648438f,0.6875f, +0.65625f,0.6875f, +0.664063f,0.6875f, +0.671875f,0.6875f, +0.679688f,0.6875f, +0.6875f,0.6875f, +0.695313f,0.6875f, +0.703125f,0.6875f, +0.710938f,0.6875f, +0.71875f,0.6875f, +0.726563f,0.6875f, +0.734375f,0.6875f, +0.742188f,0.6875f, +0.75f,0.6875f, +0.757813f,0.6875f, +0.765625f,0.6875f, +0.773438f,0.6875f, +0.78125f,0.6875f, +0.789063f,0.6875f, +0.796875f,0.6875f, +0.804688f,0.6875f, +0.8125f,0.6875f, +0.820313f,0.6875f, +0.828125f,0.6875f, +0.835938f,0.6875f, +0.84375f,0.6875f, +0.851563f,0.6875f, +0.859375f,0.6875f, +0.867188f,0.6875f, +0.875f,0.6875f, +0.882813f,0.6875f, +0.890625f,0.6875f, +0.898438f,0.6875f, +0.90625f,0.6875f, +0.914063f,0.6875f, +0.921875f,0.6875f, +0.929688f,0.6875f, +0.9375f,0.6875f, +0.945313f,0.6875f, +0.953125f,0.6875f, +0.960938f,0.6875f, +0.96875f,0.6875f, +0.976563f,0.6875f, +0.984375f,0.6875f, +0.992188f,0.6875f, +1.0f,0.6875f, +0.507813f,0.695313f, +0.515625f,0.695313f, +0.523438f,0.695313f, +0.53125f,0.695313f, +0.539063f,0.695313f, +0.546875f,0.695313f, +0.554688f,0.695313f, +0.5625f,0.695313f, +0.570313f,0.695313f, +0.578125f,0.695313f, +0.585938f,0.695313f, +0.59375f,0.695313f, +0.601563f,0.695313f, +0.609375f,0.695313f, +0.617188f,0.695313f, +0.625f,0.695313f, +0.632813f,0.695313f, +0.640625f,0.695313f, +0.648438f,0.695313f, +0.65625f,0.695313f, +0.664063f,0.695313f, +0.671875f,0.695313f, +0.679688f,0.695313f, +0.6875f,0.695313f, +0.695313f,0.695313f, +0.703125f,0.695313f, +0.710938f,0.695313f, +0.71875f,0.695313f, +0.726563f,0.695313f, +0.734375f,0.695313f, +0.742188f,0.695313f, +0.75f,0.695313f, +0.757813f,0.695313f, +0.765625f,0.695313f, +0.773438f,0.695313f, +0.78125f,0.695313f, +0.789063f,0.695313f, +0.796875f,0.695313f, +0.804688f,0.695313f, +0.8125f,0.695313f, +0.820313f,0.695313f, +0.828125f,0.695313f, +0.835938f,0.695313f, +0.84375f,0.695313f, +0.851563f,0.695313f, +0.859375f,0.695313f, +0.867188f,0.695313f, +0.875f,0.695313f, +0.882813f,0.695313f, +0.890625f,0.695313f, +0.898438f,0.695313f, +0.90625f,0.695313f, +0.914063f,0.695313f, +0.921875f,0.695313f, +0.929688f,0.695313f, +0.9375f,0.695313f, +0.945313f,0.695313f, +0.953125f,0.695313f, +0.960938f,0.695313f, +0.96875f,0.695313f, +0.976563f,0.695313f, +0.984375f,0.695313f, +0.992188f,0.695313f, +1.0f,0.695313f, +0.507813f,0.703125f, +0.515625f,0.703125f, +0.523438f,0.703125f, +0.53125f,0.703125f, +0.539063f,0.703125f, +0.546875f,0.703125f, +0.554688f,0.703125f, +0.5625f,0.703125f, +0.570313f,0.703125f, +0.578125f,0.703125f, +0.585938f,0.703125f, +0.59375f,0.703125f, +0.601563f,0.703125f, +0.609375f,0.703125f, +0.617188f,0.703125f, +0.625f,0.703125f, +0.632813f,0.703125f, +0.640625f,0.703125f, +0.648438f,0.703125f, +0.65625f,0.703125f, +0.664063f,0.703125f, +0.671875f,0.703125f, +0.679688f,0.703125f, +0.6875f,0.703125f, +0.695313f,0.703125f, +0.703125f,0.703125f, +0.710938f,0.703125f, +0.71875f,0.703125f, +0.726563f,0.703125f, +0.734375f,0.703125f, +0.742188f,0.703125f, +0.75f,0.703125f, +0.757813f,0.703125f, +0.765625f,0.703125f, +0.773438f,0.703125f, +0.78125f,0.703125f, +0.789063f,0.703125f, +0.796875f,0.703125f, +0.804688f,0.703125f, +0.8125f,0.703125f, +0.820313f,0.703125f, +0.828125f,0.703125f, +0.835938f,0.703125f, +0.84375f,0.703125f, +0.851563f,0.703125f, +0.859375f,0.703125f, +0.867188f,0.703125f, +0.875f,0.703125f, +0.882813f,0.703125f, +0.890625f,0.703125f, +0.898438f,0.703125f, +0.90625f,0.703125f, +0.914063f,0.703125f, +0.921875f,0.703125f, +0.929688f,0.703125f, +0.9375f,0.703125f, +0.945313f,0.703125f, +0.953125f,0.703125f, +0.960938f,0.703125f, +0.96875f,0.703125f, +0.976563f,0.703125f, +0.984375f,0.703125f, +0.992188f,0.703125f, +1.0f,0.703125f, +0.507813f,0.710938f, +0.515625f,0.710938f, +0.523438f,0.710938f, +0.53125f,0.710938f, +0.539063f,0.710938f, +0.546875f,0.710938f, +0.554688f,0.710938f, +0.5625f,0.710938f, +0.570313f,0.710938f, +0.578125f,0.710938f, +0.585938f,0.710938f, +0.59375f,0.710938f, +0.601563f,0.710938f, +0.609375f,0.710938f, +0.617188f,0.710938f, +0.625f,0.710938f, +0.632813f,0.710938f, +0.640625f,0.710938f, +0.648438f,0.710938f, +0.65625f,0.710938f, +0.664063f,0.710938f, +0.671875f,0.710938f, +0.679688f,0.710938f, +0.6875f,0.710938f, +0.695313f,0.710938f, +0.703125f,0.710938f, +0.710938f,0.710938f, +0.71875f,0.710938f, +0.726563f,0.710938f, +0.734375f,0.710938f, +0.742188f,0.710938f, +0.75f,0.710938f, +0.757813f,0.710938f, +0.765625f,0.710938f, +0.773438f,0.710938f, +0.78125f,0.710938f, +0.789063f,0.710938f, +0.796875f,0.710938f, +0.804688f,0.710938f, +0.8125f,0.710938f, +0.820313f,0.710938f, +0.828125f,0.710938f, +0.835938f,0.710938f, +0.84375f,0.710938f, +0.851563f,0.710938f, +0.859375f,0.710938f, +0.867188f,0.710938f, +0.875f,0.710938f, +0.882813f,0.710938f, +0.890625f,0.710938f, +0.898438f,0.710938f, +0.90625f,0.710938f, +0.914063f,0.710938f, +0.921875f,0.710938f, +0.929688f,0.710938f, +0.9375f,0.710938f, +0.945313f,0.710938f, +0.953125f,0.710938f, +0.960938f,0.710938f, +0.96875f,0.710938f, +0.976563f,0.710938f, +0.984375f,0.710938f, +0.992188f,0.710938f, +1.0f,0.710938f, +0.507813f,0.71875f, +0.515625f,0.71875f, +0.523438f,0.71875f, +0.53125f,0.71875f, +0.539063f,0.71875f, +0.546875f,0.71875f, +0.554688f,0.71875f, +0.5625f,0.71875f, +0.570313f,0.71875f, +0.578125f,0.71875f, +0.585938f,0.71875f, +0.59375f,0.71875f, +0.601563f,0.71875f, +0.609375f,0.71875f, +0.617188f,0.71875f, +0.625f,0.71875f, +0.632813f,0.71875f, +0.640625f,0.71875f, +0.648438f,0.71875f, +0.65625f,0.71875f, +0.664063f,0.71875f, +0.671875f,0.71875f, +0.679688f,0.71875f, +0.6875f,0.71875f, +0.695313f,0.71875f, +0.703125f,0.71875f, +0.710938f,0.71875f, +0.71875f,0.71875f, +0.726563f,0.71875f, +0.734375f,0.71875f, +0.742188f,0.71875f, +0.75f,0.71875f, +0.757813f,0.71875f, +0.765625f,0.71875f, +0.773438f,0.71875f, +0.78125f,0.71875f, +0.789063f,0.71875f, +0.796875f,0.71875f, +0.804688f,0.71875f, +0.8125f,0.71875f, +0.820313f,0.71875f, +0.828125f,0.71875f, +0.835938f,0.71875f, +0.84375f,0.71875f, +0.851563f,0.71875f, +0.859375f,0.71875f, +0.867188f,0.71875f, +0.875f,0.71875f, +0.882813f,0.71875f, +0.890625f,0.71875f, +0.898438f,0.71875f, +0.90625f,0.71875f, +0.914063f,0.71875f, +0.921875f,0.71875f, +0.929688f,0.71875f, +0.9375f,0.71875f, +0.945313f,0.71875f, +0.953125f,0.71875f, +0.960938f,0.71875f, +0.96875f,0.71875f, +0.976563f,0.71875f, +0.984375f,0.71875f, +0.992188f,0.71875f, +1.0f,0.71875f, +0.507813f,0.726563f, +0.515625f,0.726563f, +0.523438f,0.726563f, +0.53125f,0.726563f, +0.539063f,0.726563f, +0.546875f,0.726563f, +0.554688f,0.726563f, +0.5625f,0.726563f, +0.570313f,0.726563f, +0.578125f,0.726563f, +0.585938f,0.726563f, +0.59375f,0.726563f, +0.601563f,0.726563f, +0.609375f,0.726563f, +0.617188f,0.726563f, +0.625f,0.726563f, +0.632813f,0.726563f, +0.640625f,0.726563f, +0.648438f,0.726563f, +0.65625f,0.726563f, +0.664063f,0.726563f, +0.671875f,0.726563f, +0.679688f,0.726563f, +0.6875f,0.726563f, +0.695313f,0.726563f, +0.703125f,0.726563f, +0.710938f,0.726563f, +0.71875f,0.726563f, +0.726563f,0.726563f, +0.734375f,0.726563f, +0.742188f,0.726563f, +0.75f,0.726563f, +0.757813f,0.726563f, +0.765625f,0.726563f, +0.773438f,0.726563f, +0.78125f,0.726563f, +0.789063f,0.726563f, +0.796875f,0.726563f, +0.804688f,0.726563f, +0.8125f,0.726563f, +0.820313f,0.726563f, +0.828125f,0.726563f, +0.835938f,0.726563f, +0.84375f,0.726563f, +0.851563f,0.726563f, +0.859375f,0.726563f, +0.867188f,0.726563f, +0.875f,0.726563f, +0.882813f,0.726563f, +0.890625f,0.726563f, +0.898438f,0.726563f, +0.90625f,0.726563f, +0.914063f,0.726563f, +0.921875f,0.726563f, +0.929688f,0.726563f, +0.9375f,0.726563f, +0.945313f,0.726563f, +0.953125f,0.726563f, +0.960938f,0.726563f, +0.96875f,0.726563f, +0.976563f,0.726563f, +0.984375f,0.726563f, +0.992188f,0.726563f, +1.0f,0.726563f, +0.507813f,0.734375f, +0.515625f,0.734375f, +0.523438f,0.734375f, +0.53125f,0.734375f, +0.539063f,0.734375f, +0.546875f,0.734375f, +0.554688f,0.734375f, +0.5625f,0.734375f, +0.570313f,0.734375f, +0.578125f,0.734375f, +0.585938f,0.734375f, +0.59375f,0.734375f, +0.601563f,0.734375f, +0.609375f,0.734375f, +0.617188f,0.734375f, +0.625f,0.734375f, +0.632813f,0.734375f, +0.640625f,0.734375f, +0.648438f,0.734375f, +0.65625f,0.734375f, +0.664063f,0.734375f, +0.671875f,0.734375f, +0.679688f,0.734375f, +0.6875f,0.734375f, +0.695313f,0.734375f, +0.703125f,0.734375f, +0.710938f,0.734375f, +0.71875f,0.734375f, +0.726563f,0.734375f, +0.734375f,0.734375f, +0.742188f,0.734375f, +0.75f,0.734375f, +0.757813f,0.734375f, +0.765625f,0.734375f, +0.773438f,0.734375f, +0.78125f,0.734375f, +0.789063f,0.734375f, +0.796875f,0.734375f, +0.804688f,0.734375f, +0.8125f,0.734375f, +0.820313f,0.734375f, +0.828125f,0.734375f, +0.835938f,0.734375f, +0.84375f,0.734375f, +0.851563f,0.734375f, +0.859375f,0.734375f, +0.867188f,0.734375f, +0.875f,0.734375f, +0.882813f,0.734375f, +0.890625f,0.734375f, +0.898438f,0.734375f, +0.90625f,0.734375f, +0.914063f,0.734375f, +0.921875f,0.734375f, +0.929688f,0.734375f, +0.9375f,0.734375f, +0.945313f,0.734375f, +0.953125f,0.734375f, +0.960938f,0.734375f, +0.96875f,0.734375f, +0.976563f,0.734375f, +0.984375f,0.734375f, +0.992188f,0.734375f, +1.0f,0.734375f, +}; + +unsigned short Landscape03Idx[] = { +0,1,2, +3,2,1, +2,3,4, +5,4,3, +4,5,6, +7,6,5, +6,7,8, +9,8,7, +8,9,10, +11,10,9, +10,11,12, +13,12,11, +12,13,14, +15,14,13, +14,15,16, +17,16,15, +16,17,18, +19,18,17, +18,19,20, +21,20,19, +20,21,22, +23,22,21, +22,23,24, +25,24,23, +24,25,26, +27,26,25, +26,27,28, +29,28,27, +28,29,30, +31,30,29, +30,31,32, +33,32,31, +32,33,34, +35,34,33, +34,35,36, +37,36,35, +36,37,38, +39,38,37, +38,39,40, +41,40,39, +40,41,42, +43,42,41, +42,43,44, +45,44,43, +44,45,46, +47,46,45, +46,47,48, +49,48,47, +48,49,50, +51,50,49, +50,51,52, +53,52,51, +52,53,54, +55,54,53, +54,55,56, +57,56,55, +56,57,58, +59,58,57, +58,59,60, +61,60,59, +60,61,62, +63,62,61, +62,63,64, +65,64,63, +64,65,66, +67,66,65, +66,67,68, +69,68,67, +68,69,70, +71,70,69, +70,71,72, +73,72,71, +72,73,74, +75,74,73, +74,75,76, +77,76,75, +76,77,78, +79,78,77, +78,79,80, +81,80,79, +80,81,82, +83,82,81, +82,83,84, +85,84,83, +84,85,86, +87,86,85, +86,87,88, +89,88,87, +88,89,90, +91,90,89, +90,91,92, +93,92,91, +92,93,94, +95,94,93, +94,95,96, +97,96,95, +96,97,98, +99,98,97, +98,99,100, +101,100,99, +100,101,102, +103,102,101, +102,103,104, +105,104,103, +104,105,106, +107,106,105, +106,107,108, +109,108,107, +108,109,110, +111,110,109, +110,111,112, +113,112,111, +112,113,114, +115,114,113, +114,115,116, +117,116,115, +116,117,118, +119,118,117, +118,119,120, +121,120,119, +120,121,122, +123,122,121, +122,123,124, +125,124,123, +124,125,126, +127,126,125, +128,0,129, +2,129,0, +129,2,130, +4,130,2, +130,4,131, +6,131,4, +131,6,132, +8,132,6, +132,8,133, +10,133,8, +133,10,134, +12,134,10, +134,12,135, +14,135,12, +135,14,136, +16,136,14, +136,16,137, +18,137,16, +137,18,138, +20,138,18, +138,20,139, +22,139,20, +139,22,140, +24,140,22, +140,24,141, +26,141,24, +141,26,142, +28,142,26, +142,28,143, +30,143,28, +143,30,144, +32,144,30, +144,32,145, +34,145,32, +145,34,146, +36,146,34, +146,36,147, +38,147,36, +147,38,148, +40,148,38, +148,40,149, +42,149,40, +149,42,150, +44,150,42, +150,44,151, +46,151,44, +151,46,152, +48,152,46, +152,48,153, +50,153,48, +153,50,154, +52,154,50, +154,52,155, +54,155,52, +155,54,156, +56,156,54, +156,56,157, +58,157,56, +157,58,158, +60,158,58, +158,60,159, +62,159,60, +159,62,160, +64,160,62, +160,64,161, +66,161,64, +161,66,162, +68,162,66, +162,68,163, +70,163,68, +163,70,164, +72,164,70, +164,72,165, +74,165,72, +165,74,166, +76,166,74, +166,76,167, +78,167,76, +167,78,168, +80,168,78, +168,80,169, +82,169,80, +169,82,170, +84,170,82, +170,84,171, +86,171,84, +171,86,172, +88,172,86, +172,88,173, +90,173,88, +173,90,174, +92,174,90, +174,92,175, +94,175,92, +175,94,176, +96,176,94, +176,96,177, +98,177,96, +177,98,178, +100,178,98, +178,100,179, +102,179,100, +179,102,180, +104,180,102, +180,104,181, +106,181,104, +181,106,182, +108,182,106, +182,108,183, +110,183,108, +183,110,184, +112,184,110, +184,112,185, +114,185,112, +185,114,186, +116,186,114, +186,116,187, +118,187,116, +187,118,188, +120,188,118, +188,120,189, +122,189,120, +189,122,190, +124,190,122, +190,124,191, +126,191,124, +192,128,193, +129,193,128, +193,129,194, +130,194,129, +194,130,195, +131,195,130, +195,131,196, +132,196,131, +196,132,197, +133,197,132, +197,133,198, +134,198,133, +198,134,199, +135,199,134, +199,135,200, +136,200,135, +200,136,201, +137,201,136, +201,137,202, +138,202,137, +202,138,203, +139,203,138, +203,139,204, +140,204,139, +204,140,205, +141,205,140, +205,141,206, +142,206,141, +206,142,207, +143,207,142, +207,143,208, +144,208,143, +208,144,209, +145,209,144, +209,145,210, +146,210,145, +210,146,211, +147,211,146, +211,147,212, +148,212,147, +212,148,213, +149,213,148, +213,149,214, +150,214,149, +214,150,215, +151,215,150, +215,151,216, +152,216,151, +216,152,217, +153,217,152, +217,153,218, +154,218,153, +218,154,219, +155,219,154, +219,155,220, +156,220,155, +220,156,221, +157,221,156, +221,157,222, +158,222,157, +222,158,223, +159,223,158, +223,159,224, +160,224,159, +224,160,225, +161,225,160, +225,161,226, +162,226,161, +226,162,227, +163,227,162, +227,163,228, +164,228,163, +228,164,229, +165,229,164, +229,165,230, +166,230,165, +230,166,231, +167,231,166, +231,167,232, +168,232,167, +232,168,233, +169,233,168, +233,169,234, +170,234,169, +234,170,235, +171,235,170, +235,171,236, +172,236,171, +236,172,237, +173,237,172, +237,173,238, +174,238,173, +238,174,239, +175,239,174, +239,175,240, +176,240,175, +240,176,241, +177,241,176, +241,177,242, +178,242,177, +242,178,243, +179,243,178, +243,179,244, +180,244,179, +244,180,245, +181,245,180, +245,181,246, +182,246,181, +246,182,247, +183,247,182, +247,183,248, +184,248,183, +248,184,249, +185,249,184, +249,185,250, +186,250,185, +250,186,251, +187,251,186, +251,187,252, +188,252,187, +252,188,253, +189,253,188, +253,189,254, +190,254,189, +254,190,255, +191,255,190, +256,192,257, +193,257,192, +257,193,258, +194,258,193, +258,194,259, +195,259,194, +259,195,260, +196,260,195, +260,196,261, +197,261,196, +261,197,262, +198,262,197, +262,198,263, +199,263,198, +263,199,264, +200,264,199, +264,200,265, +201,265,200, +265,201,266, +202,266,201, +266,202,267, +203,267,202, +267,203,268, +204,268,203, +268,204,269, +205,269,204, +269,205,270, +206,270,205, +270,206,271, +207,271,206, +271,207,272, +208,272,207, +272,208,273, +209,273,208, +273,209,274, +210,274,209, +274,210,275, +211,275,210, +275,211,276, +212,276,211, +276,212,277, +213,277,212, +277,213,278, +214,278,213, +278,214,279, +215,279,214, +279,215,280, +216,280,215, +280,216,281, +217,281,216, +281,217,282, +218,282,217, +282,218,283, +219,283,218, +283,219,284, +220,284,219, +284,220,285, +221,285,220, +285,221,286, +222,286,221, +286,222,287, +223,287,222, +287,223,288, +224,288,223, +288,224,289, +225,289,224, +289,225,290, +226,290,225, +290,226,291, +227,291,226, +291,227,292, +228,292,227, +292,228,293, +229,293,228, +293,229,294, +230,294,229, +294,230,295, +231,295,230, +295,231,296, +232,296,231, +296,232,297, +233,297,232, +297,233,298, +234,298,233, +298,234,299, +235,299,234, +299,235,300, +236,300,235, +300,236,301, +237,301,236, +301,237,302, +238,302,237, +302,238,303, +239,303,238, +303,239,304, +240,304,239, +304,240,305, +241,305,240, +305,241,306, +242,306,241, +306,242,307, +243,307,242, +307,243,308, +244,308,243, +308,244,309, +245,309,244, +309,245,310, +246,310,245, +310,246,311, +247,311,246, +311,247,312, +248,312,247, +312,248,313, +249,313,248, +313,249,314, +250,314,249, +314,250,315, +251,315,250, +315,251,316, +252,316,251, +316,252,317, +253,317,252, +317,253,318, +254,318,253, +318,254,319, +255,319,254, +320,256,321, +257,321,256, +321,257,322, +258,322,257, +322,258,323, +259,323,258, +323,259,324, +260,324,259, +324,260,325, +261,325,260, +325,261,326, +262,326,261, +326,262,327, +263,327,262, +327,263,328, +264,328,263, +328,264,329, +265,329,264, +329,265,330, +266,330,265, +330,266,331, +267,331,266, +331,267,332, +268,332,267, +332,268,333, +269,333,268, +333,269,334, +270,334,269, +334,270,335, +271,335,270, +335,271,336, +272,336,271, +336,272,337, +273,337,272, +337,273,338, +274,338,273, +338,274,339, +275,339,274, +339,275,340, +276,340,275, +340,276,341, +277,341,276, +341,277,342, +278,342,277, +342,278,343, +279,343,278, +343,279,344, +280,344,279, +344,280,345, +281,345,280, +345,281,346, +282,346,281, +346,282,347, +283,347,282, +347,283,348, +284,348,283, +348,284,349, +285,349,284, +349,285,350, +286,350,285, +350,286,351, +287,351,286, +351,287,352, +288,352,287, +352,288,353, +289,353,288, +353,289,354, +290,354,289, +354,290,355, +291,355,290, +355,291,356, +292,356,291, +356,292,357, +293,357,292, +357,293,358, +294,358,293, +358,294,359, +295,359,294, +359,295,360, +296,360,295, +360,296,361, +297,361,296, +361,297,362, +298,362,297, +362,298,363, +299,363,298, +363,299,364, +300,364,299, +364,300,365, +301,365,300, +365,301,366, +302,366,301, +366,302,367, +303,367,302, +367,303,368, +304,368,303, +368,304,369, +305,369,304, +369,305,370, +306,370,305, +370,306,371, +307,371,306, +371,307,372, +308,372,307, +372,308,373, +309,373,308, +373,309,374, +310,374,309, +374,310,375, +311,375,310, +375,311,376, +312,376,311, +376,312,377, +313,377,312, +377,313,378, +314,378,313, +378,314,379, +315,379,314, +379,315,380, +316,380,315, +380,316,381, +317,381,316, +381,317,382, +318,382,317, +382,318,383, +319,383,318, +384,320,385, +321,385,320, +385,321,386, +322,386,321, +386,322,387, +323,387,322, +387,323,388, +324,388,323, +388,324,389, +325,389,324, +389,325,390, +326,390,325, +390,326,391, +327,391,326, +391,327,392, +328,392,327, +392,328,393, +329,393,328, +393,329,394, +330,394,329, +394,330,395, +331,395,330, +395,331,396, +332,396,331, +396,332,397, +333,397,332, +397,333,398, +334,398,333, +398,334,399, +335,399,334, +399,335,400, +336,400,335, +400,336,401, +337,401,336, +401,337,402, +338,402,337, +402,338,403, +339,403,338, +403,339,404, +340,404,339, +404,340,405, +341,405,340, +405,341,406, +342,406,341, +406,342,407, +343,407,342, +407,343,408, +344,408,343, +408,344,409, +345,409,344, +409,345,410, +346,410,345, +410,346,411, +347,411,346, +411,347,412, +348,412,347, +412,348,413, +349,413,348, +413,349,414, +350,414,349, +414,350,415, +351,415,350, +415,351,416, +352,416,351, +416,352,417, +353,417,352, +417,353,418, +354,418,353, +418,354,419, +355,419,354, +419,355,420, +356,420,355, +420,356,421, +357,421,356, +421,357,422, +358,422,357, +422,358,423, +359,423,358, +423,359,424, +360,424,359, +424,360,425, +361,425,360, +425,361,426, +362,426,361, +426,362,427, +363,427,362, +427,363,428, +364,428,363, +428,364,429, +365,429,364, +429,365,430, +366,430,365, +430,366,431, +367,431,366, +431,367,432, +368,432,367, +432,368,433, +369,433,368, +433,369,434, +370,434,369, +434,370,435, +371,435,370, +435,371,436, +372,436,371, +436,372,437, +373,437,372, +437,373,438, +374,438,373, +438,374,439, +375,439,374, +439,375,440, +376,440,375, +440,376,441, +377,441,376, +441,377,442, +378,442,377, +442,378,443, +379,443,378, +443,379,444, +380,444,379, +444,380,445, +381,445,380, +445,381,446, +382,446,381, +446,382,447, +383,447,382, +448,384,449, +385,449,384, +449,385,450, +386,450,385, +450,386,451, +387,451,386, +451,387,452, +388,452,387, +452,388,453, +389,453,388, +453,389,454, +390,454,389, +454,390,455, +391,455,390, +455,391,456, +392,456,391, +456,392,457, +393,457,392, +457,393,458, +394,458,393, +458,394,459, +395,459,394, +459,395,460, +396,460,395, +460,396,461, +397,461,396, +461,397,462, +398,462,397, +462,398,463, +399,463,398, +463,399,464, +400,464,399, +464,400,465, +401,465,400, +465,401,466, +402,466,401, +466,402,467, +403,467,402, +467,403,468, +404,468,403, +468,404,469, +405,469,404, +469,405,470, +406,470,405, +470,406,471, +407,471,406, +471,407,472, +408,472,407, +472,408,473, +409,473,408, +473,409,474, +410,474,409, +474,410,475, +411,475,410, +475,411,476, +412,476,411, +476,412,477, +413,477,412, +477,413,478, +414,478,413, +478,414,479, +415,479,414, +479,415,480, +416,480,415, +480,416,481, +417,481,416, +481,417,482, +418,482,417, +482,418,483, +419,483,418, +483,419,484, +420,484,419, +484,420,485, +421,485,420, +485,421,486, +422,486,421, +486,422,487, +423,487,422, +487,423,488, +424,488,423, +488,424,489, +425,489,424, +489,425,490, +426,490,425, +490,426,491, +427,491,426, +491,427,492, +428,492,427, +492,428,493, +429,493,428, +493,429,494, +430,494,429, +494,430,495, +431,495,430, +495,431,496, +432,496,431, +496,432,497, +433,497,432, +497,433,498, +434,498,433, +498,434,499, +435,499,434, +499,435,500, +436,500,435, +500,436,501, +437,501,436, +501,437,502, +438,502,437, +502,438,503, +439,503,438, +503,439,504, +440,504,439, +504,440,505, +441,505,440, +505,441,506, +442,506,441, +506,442,507, +443,507,442, +507,443,508, +444,508,443, +508,444,509, +445,509,444, +509,445,510, +446,510,445, +510,446,511, +447,511,446, +512,448,513, +449,513,448, +513,449,514, +450,514,449, +514,450,515, +451,515,450, +515,451,516, +452,516,451, +516,452,517, +453,517,452, +517,453,518, +454,518,453, +518,454,519, +455,519,454, +519,455,520, +456,520,455, +520,456,521, +457,521,456, +521,457,522, +458,522,457, +522,458,523, +459,523,458, +523,459,524, +460,524,459, +524,460,525, +461,525,460, +525,461,526, +462,526,461, +526,462,527, +463,527,462, +527,463,528, +464,528,463, +528,464,529, +465,529,464, +529,465,530, +466,530,465, +530,466,531, +467,531,466, +531,467,532, +468,532,467, +532,468,533, +469,533,468, +533,469,534, +470,534,469, +534,470,535, +471,535,470, +535,471,536, +472,536,471, +536,472,537, +473,537,472, +537,473,538, +474,538,473, +538,474,539, +475,539,474, +539,475,540, +476,540,475, +540,476,541, +477,541,476, +541,477,542, +478,542,477, +542,478,543, +479,543,478, +543,479,544, +480,544,479, +544,480,545, +481,545,480, +545,481,546, +482,546,481, +546,482,547, +483,547,482, +547,483,548, +484,548,483, +548,484,549, +485,549,484, +549,485,550, +486,550,485, +550,486,551, +487,551,486, +551,487,552, +488,552,487, +552,488,553, +489,553,488, +553,489,554, +490,554,489, +554,490,555, +491,555,490, +555,491,556, +492,556,491, +556,492,557, +493,557,492, +557,493,558, +494,558,493, +558,494,559, +495,559,494, +559,495,560, +496,560,495, +560,496,561, +497,561,496, +561,497,562, +498,562,497, +562,498,563, +499,563,498, +563,499,564, +500,564,499, +564,500,565, +501,565,500, +565,501,566, +502,566,501, +566,502,567, +503,567,502, +567,503,568, +504,568,503, +568,504,569, +505,569,504, +569,505,570, +506,570,505, +570,506,571, +507,571,506, +571,507,572, +508,572,507, +572,508,573, +509,573,508, +573,509,574, +510,574,509, +574,510,575, +511,575,510, +576,512,577, +513,577,512, +577,513,578, +514,578,513, +578,514,579, +515,579,514, +579,515,580, +516,580,515, +580,516,581, +517,581,516, +581,517,582, +518,582,517, +582,518,583, +519,583,518, +583,519,584, +520,584,519, +584,520,585, +521,585,520, +585,521,586, +522,586,521, +586,522,587, +523,587,522, +587,523,588, +524,588,523, +588,524,589, +525,589,524, +589,525,590, +526,590,525, +590,526,591, +527,591,526, +591,527,592, +528,592,527, +592,528,593, +529,593,528, +593,529,594, +530,594,529, +594,530,595, +531,595,530, +595,531,596, +532,596,531, +596,532,597, +533,597,532, +597,533,598, +534,598,533, +598,534,599, +535,599,534, +599,535,600, +536,600,535, +600,536,601, +537,601,536, +601,537,602, +538,602,537, +602,538,603, +539,603,538, +603,539,604, +540,604,539, +604,540,605, +541,605,540, +605,541,606, +542,606,541, +606,542,607, +543,607,542, +607,543,608, +544,608,543, +608,544,609, +545,609,544, +609,545,610, +546,610,545, +610,546,611, +547,611,546, +611,547,612, +548,612,547, +612,548,613, +549,613,548, +613,549,614, +550,614,549, +614,550,615, +551,615,550, +615,551,616, +552,616,551, +616,552,617, +553,617,552, +617,553,618, +554,618,553, +618,554,619, +555,619,554, +619,555,620, +556,620,555, +620,556,621, +557,621,556, +621,557,622, +558,622,557, +622,558,623, +559,623,558, +623,559,624, +560,624,559, +624,560,625, +561,625,560, +625,561,626, +562,626,561, +626,562,627, +563,627,562, +627,563,628, +564,628,563, +628,564,629, +565,629,564, +629,565,630, +566,630,565, +630,566,631, +567,631,566, +631,567,632, +568,632,567, +632,568,633, +569,633,568, +633,569,634, +570,634,569, +634,570,635, +571,635,570, +635,571,636, +572,636,571, +636,572,637, +573,637,572, +637,573,638, +574,638,573, +638,574,639, +575,639,574, +640,576,641, +577,641,576, +641,577,642, +578,642,577, +642,578,643, +579,643,578, +643,579,644, +580,644,579, +644,580,645, +581,645,580, +645,581,646, +582,646,581, +646,582,647, +583,647,582, +647,583,648, +584,648,583, +648,584,649, +585,649,584, +649,585,650, +586,650,585, +650,586,651, +587,651,586, +651,587,652, +588,652,587, +652,588,653, +589,653,588, +653,589,654, +590,654,589, +654,590,655, +591,655,590, +655,591,656, +592,656,591, +656,592,657, +593,657,592, +657,593,658, +594,658,593, +658,594,659, +595,659,594, +659,595,660, +596,660,595, +660,596,661, +597,661,596, +661,597,662, +598,662,597, +662,598,663, +599,663,598, +663,599,664, +600,664,599, +664,600,665, +601,665,600, +665,601,666, +602,666,601, +666,602,667, +603,667,602, +667,603,668, +604,668,603, +668,604,669, +605,669,604, +669,605,670, +606,670,605, +670,606,671, +607,671,606, +671,607,672, +608,672,607, +672,608,673, +609,673,608, +673,609,674, +610,674,609, +674,610,675, +611,675,610, +675,611,676, +612,676,611, +676,612,677, +613,677,612, +677,613,678, +614,678,613, +678,614,679, +615,679,614, +679,615,680, +616,680,615, +680,616,681, +617,681,616, +681,617,682, +618,682,617, +682,618,683, +619,683,618, +683,619,684, +620,684,619, +684,620,685, +621,685,620, +685,621,686, +622,686,621, +686,622,687, +623,687,622, +687,623,688, +624,688,623, +688,624,689, +625,689,624, +689,625,690, +626,690,625, +690,626,691, +627,691,626, +691,627,692, +628,692,627, +692,628,693, +629,693,628, +693,629,694, +630,694,629, +694,630,695, +631,695,630, +695,631,696, +632,696,631, +696,632,697, +633,697,632, +697,633,698, +634,698,633, +698,634,699, +635,699,634, +699,635,700, +636,700,635, +700,636,701, +637,701,636, +701,637,702, +638,702,637, +702,638,703, +639,703,638, +704,640,705, +641,705,640, +705,641,706, +642,706,641, +706,642,707, +643,707,642, +707,643,708, +644,708,643, +708,644,709, +645,709,644, +709,645,710, +646,710,645, +710,646,711, +647,711,646, +711,647,712, +648,712,647, +712,648,713, +649,713,648, +713,649,714, +650,714,649, +714,650,715, +651,715,650, +715,651,716, +652,716,651, +716,652,717, +653,717,652, +717,653,718, +654,718,653, +718,654,719, +655,719,654, +719,655,720, +656,720,655, +720,656,721, +657,721,656, +721,657,722, +658,722,657, +722,658,723, +659,723,658, +723,659,724, +660,724,659, +724,660,725, +661,725,660, +725,661,726, +662,726,661, +726,662,727, +663,727,662, +727,663,728, +664,728,663, +728,664,729, +665,729,664, +729,665,730, +666,730,665, +730,666,731, +667,731,666, +731,667,732, +668,732,667, +732,668,733, +669,733,668, +733,669,734, +670,734,669, +734,670,735, +671,735,670, +735,671,736, +672,736,671, +736,672,737, +673,737,672, +737,673,738, +674,738,673, +738,674,739, +675,739,674, +739,675,740, +676,740,675, +740,676,741, +677,741,676, +741,677,742, +678,742,677, +742,678,743, +679,743,678, +743,679,744, +680,744,679, +744,680,745, +681,745,680, +745,681,746, +682,746,681, +746,682,747, +683,747,682, +747,683,748, +684,748,683, +748,684,749, +685,749,684, +749,685,750, +686,750,685, +750,686,751, +687,751,686, +751,687,752, +688,752,687, +752,688,753, +689,753,688, +753,689,754, +690,754,689, +754,690,755, +691,755,690, +755,691,756, +692,756,691, +756,692,757, +693,757,692, +757,693,758, +694,758,693, +758,694,759, +695,759,694, +759,695,760, +696,760,695, +760,696,761, +697,761,696, +761,697,762, +698,762,697, +762,698,763, +699,763,698, +763,699,764, +700,764,699, +764,700,765, +701,765,700, +765,701,766, +702,766,701, +766,702,767, +703,767,702, +768,704,769, +705,769,704, +769,705,770, +706,770,705, +770,706,771, +707,771,706, +771,707,772, +708,772,707, +772,708,773, +709,773,708, +773,709,774, +710,774,709, +774,710,775, +711,775,710, +775,711,776, +712,776,711, +776,712,777, +713,777,712, +777,713,778, +714,778,713, +778,714,779, +715,779,714, +779,715,780, +716,780,715, +780,716,781, +717,781,716, +781,717,782, +718,782,717, +782,718,783, +719,783,718, +783,719,784, +720,784,719, +784,720,785, +721,785,720, +785,721,786, +722,786,721, +786,722,787, +723,787,722, +787,723,788, +724,788,723, +788,724,789, +725,789,724, +789,725,790, +726,790,725, +790,726,791, +727,791,726, +791,727,792, +728,792,727, +792,728,793, +729,793,728, +793,729,794, +730,794,729, +794,730,795, +731,795,730, +795,731,796, +732,796,731, +796,732,797, +733,797,732, +797,733,798, +734,798,733, +798,734,799, +735,799,734, +799,735,800, +736,800,735, +800,736,801, +737,801,736, +801,737,802, +738,802,737, +802,738,803, +739,803,738, +803,739,804, +740,804,739, +804,740,805, +741,805,740, +805,741,806, +742,806,741, +806,742,807, +743,807,742, +807,743,808, +744,808,743, +808,744,809, +745,809,744, +809,745,810, +746,810,745, +810,746,811, +747,811,746, +811,747,812, +748,812,747, +812,748,813, +749,813,748, +813,749,814, +750,814,749, +814,750,815, +751,815,750, +815,751,816, +752,816,751, +816,752,817, +753,817,752, +817,753,818, +754,818,753, +818,754,819, +755,819,754, +819,755,820, +756,820,755, +820,756,821, +757,821,756, +821,757,822, +758,822,757, +822,758,823, +759,823,758, +823,759,824, +760,824,759, +824,760,825, +761,825,760, +825,761,826, +762,826,761, +826,762,827, +763,827,762, +827,763,828, +764,828,763, +828,764,829, +765,829,764, +829,765,830, +766,830,765, +830,766,831, +767,831,766, +832,768,833, +769,833,768, +833,769,834, +770,834,769, +834,770,835, +771,835,770, +835,771,836, +772,836,771, +836,772,837, +773,837,772, +837,773,838, +774,838,773, +838,774,839, +775,839,774, +839,775,840, +776,840,775, +840,776,841, +777,841,776, +841,777,842, +778,842,777, +842,778,843, +779,843,778, +843,779,844, +780,844,779, +844,780,845, +781,845,780, +845,781,846, +782,846,781, +846,782,847, +783,847,782, +847,783,848, +784,848,783, +848,784,849, +785,849,784, +849,785,850, +786,850,785, +850,786,851, +787,851,786, +851,787,852, +788,852,787, +852,788,853, +789,853,788, +853,789,854, +790,854,789, +854,790,855, +791,855,790, +855,791,856, +792,856,791, +856,792,857, +793,857,792, +857,793,858, +794,858,793, +858,794,859, +795,859,794, +859,795,860, +796,860,795, +860,796,861, +797,861,796, +861,797,862, +798,862,797, +862,798,863, +799,863,798, +863,799,864, +800,864,799, +864,800,865, +801,865,800, +865,801,866, +802,866,801, +866,802,867, +803,867,802, +867,803,868, +804,868,803, +868,804,869, +805,869,804, +869,805,870, +806,870,805, +870,806,871, +807,871,806, +871,807,872, +808,872,807, +872,808,873, +809,873,808, +873,809,874, +810,874,809, +874,810,875, +811,875,810, +875,811,876, +812,876,811, +876,812,877, +813,877,812, +877,813,878, +814,878,813, +878,814,879, +815,879,814, +879,815,880, +816,880,815, +880,816,881, +817,881,816, +881,817,882, +818,882,817, +882,818,883, +819,883,818, +883,819,884, +820,884,819, +884,820,885, +821,885,820, +885,821,886, +822,886,821, +886,822,887, +823,887,822, +887,823,888, +824,888,823, +888,824,889, +825,889,824, +889,825,890, +826,890,825, +890,826,891, +827,891,826, +891,827,892, +828,892,827, +892,828,893, +829,893,828, +893,829,894, +830,894,829, +894,830,895, +831,895,830, +896,832,897, +833,897,832, +897,833,898, +834,898,833, +898,834,899, +835,899,834, +899,835,900, +836,900,835, +900,836,901, +837,901,836, +901,837,902, +838,902,837, +902,838,903, +839,903,838, +903,839,904, +840,904,839, +904,840,905, +841,905,840, +905,841,906, +842,906,841, +906,842,907, +843,907,842, +907,843,908, +844,908,843, +908,844,909, +845,909,844, +909,845,910, +846,910,845, +910,846,911, +847,911,846, +911,847,912, +848,912,847, +912,848,913, +849,913,848, +913,849,914, +850,914,849, +914,850,915, +851,915,850, +915,851,916, +852,916,851, +916,852,917, +853,917,852, +917,853,918, +854,918,853, +918,854,919, +855,919,854, +919,855,920, +856,920,855, +920,856,921, +857,921,856, +921,857,922, +858,922,857, +922,858,923, +859,923,858, +923,859,924, +860,924,859, +924,860,925, +861,925,860, +925,861,926, +862,926,861, +926,862,927, +863,927,862, +927,863,928, +864,928,863, +928,864,929, +865,929,864, +929,865,930, +866,930,865, +930,866,931, +867,931,866, +931,867,932, +868,932,867, +932,868,933, +869,933,868, +933,869,934, +870,934,869, +934,870,935, +871,935,870, +935,871,936, +872,936,871, +936,872,937, +873,937,872, +937,873,938, +874,938,873, +938,874,939, +875,939,874, +939,875,940, +876,940,875, +940,876,941, +877,941,876, +941,877,942, +878,942,877, +942,878,943, +879,943,878, +943,879,944, +880,944,879, +944,880,945, +881,945,880, +945,881,946, +882,946,881, +946,882,947, +883,947,882, +947,883,948, +884,948,883, +948,884,949, +885,949,884, +949,885,950, +886,950,885, +950,886,951, +887,951,886, +951,887,952, +888,952,887, +952,888,953, +889,953,888, +953,889,954, +890,954,889, +954,890,955, +891,955,890, +955,891,956, +892,956,891, +956,892,957, +893,957,892, +957,893,958, +894,958,893, +958,894,959, +895,959,894, +960,896,961, +897,961,896, +961,897,962, +898,962,897, +962,898,963, +899,963,898, +963,899,964, +900,964,899, +964,900,965, +901,965,900, +965,901,966, +902,966,901, +966,902,967, +903,967,902, +967,903,968, +904,968,903, +968,904,969, +905,969,904, +969,905,970, +906,970,905, +970,906,971, +907,971,906, +971,907,972, +908,972,907, +972,908,973, +909,973,908, +973,909,974, +910,974,909, +974,910,975, +911,975,910, +975,911,976, +912,976,911, +976,912,977, +913,977,912, +977,913,978, +914,978,913, +978,914,979, +915,979,914, +979,915,980, +916,980,915, +980,916,981, +917,981,916, +981,917,982, +918,982,917, +982,918,983, +919,983,918, +983,919,984, +920,984,919, +984,920,985, +921,985,920, +985,921,986, +922,986,921, +986,922,987, +923,987,922, +987,923,988, +924,988,923, +988,924,989, +925,989,924, +989,925,990, +926,990,925, +990,926,991, +927,991,926, +991,927,992, +928,992,927, +992,928,993, +929,993,928, +993,929,994, +930,994,929, +994,930,995, +931,995,930, +995,931,996, +932,996,931, +996,932,997, +933,997,932, +997,933,998, +934,998,933, +998,934,999, +935,999,934, +999,935,1000, +936,1000,935, +1000,936,1001, +937,1001,936, +1001,937,1002, +938,1002,937, +1002,938,1003, +939,1003,938, +1003,939,1004, +940,1004,939, +1004,940,1005, +941,1005,940, +1005,941,1006, +942,1006,941, +1006,942,1007, +943,1007,942, +1007,943,1008, +944,1008,943, +1008,944,1009, +945,1009,944, +1009,945,1010, +946,1010,945, +1010,946,1011, +947,1011,946, +1011,947,1012, +948,1012,947, +1012,948,1013, +949,1013,948, +1013,949,1014, +950,1014,949, +1014,950,1015, +951,1015,950, +1015,951,1016, +952,1016,951, +1016,952,1017, +953,1017,952, +1017,953,1018, +954,1018,953, +1018,954,1019, +955,1019,954, +1019,955,1020, +956,1020,955, +1020,956,1021, +957,1021,956, +1021,957,1022, +958,1022,957, +1022,958,1023, +959,1023,958, +1024,960,1025, +961,1025,960, +1025,961,1026, +962,1026,961, +1026,962,1027, +963,1027,962, +1027,963,1028, +964,1028,963, +1028,964,1029, +965,1029,964, +1029,965,1030, +966,1030,965, +1030,966,1031, +967,1031,966, +1031,967,1032, +968,1032,967, +1032,968,1033, +969,1033,968, +1033,969,1034, +970,1034,969, +1034,970,1035, +971,1035,970, +1035,971,1036, +972,1036,971, +1036,972,1037, +973,1037,972, +1037,973,1038, +974,1038,973, +1038,974,1039, +975,1039,974, +1039,975,1040, +976,1040,975, +1040,976,1041, +977,1041,976, +1041,977,1042, +978,1042,977, +1042,978,1043, +979,1043,978, +1043,979,1044, +980,1044,979, +1044,980,1045, +981,1045,980, +1045,981,1046, +982,1046,981, +1046,982,1047, +983,1047,982, +1047,983,1048, +984,1048,983, +1048,984,1049, +985,1049,984, +1049,985,1050, +986,1050,985, +1050,986,1051, +987,1051,986, +1051,987,1052, +988,1052,987, +1052,988,1053, +989,1053,988, +1053,989,1054, +990,1054,989, +1054,990,1055, +991,1055,990, +1055,991,1056, +992,1056,991, +1056,992,1057, +993,1057,992, +1057,993,1058, +994,1058,993, +1058,994,1059, +995,1059,994, +1059,995,1060, +996,1060,995, +1060,996,1061, +997,1061,996, +1061,997,1062, +998,1062,997, +1062,998,1063, +999,1063,998, +1063,999,1064, +1000,1064,999, +1064,1000,1065, +1001,1065,1000, +1065,1001,1066, +1002,1066,1001, +1066,1002,1067, +1003,1067,1002, +1067,1003,1068, +1004,1068,1003, +1068,1004,1069, +1005,1069,1004, +1069,1005,1070, +1006,1070,1005, +1070,1006,1071, +1007,1071,1006, +1071,1007,1072, +1008,1072,1007, +1072,1008,1073, +1009,1073,1008, +1073,1009,1074, +1010,1074,1009, +1074,1010,1075, +1011,1075,1010, +1075,1011,1076, +1012,1076,1011, +1076,1012,1077, +1013,1077,1012, +1077,1013,1078, +1014,1078,1013, +1078,1014,1079, +1015,1079,1014, +1079,1015,1080, +1016,1080,1015, +1080,1016,1081, +1017,1081,1016, +1081,1017,1082, +1018,1082,1017, +1082,1018,1083, +1019,1083,1018, +1083,1019,1084, +1020,1084,1019, +1084,1020,1085, +1021,1085,1020, +1085,1021,1086, +1022,1086,1021, +1086,1022,1087, +1023,1087,1022, +1088,1024,1089, +1025,1089,1024, +1089,1025,1090, +1026,1090,1025, +1090,1026,1091, +1027,1091,1026, +1091,1027,1092, +1028,1092,1027, +1092,1028,1093, +1029,1093,1028, +1093,1029,1094, +1030,1094,1029, +1094,1030,1095, +1031,1095,1030, +1095,1031,1096, +1032,1096,1031, +1096,1032,1097, +1033,1097,1032, +1097,1033,1098, +1034,1098,1033, +1098,1034,1099, +1035,1099,1034, +1099,1035,1100, +1036,1100,1035, +1100,1036,1101, +1037,1101,1036, +1101,1037,1102, +1038,1102,1037, +1102,1038,1103, +1039,1103,1038, +1103,1039,1104, +1040,1104,1039, +1104,1040,1105, +1041,1105,1040, +1105,1041,1106, +1042,1106,1041, +1106,1042,1107, +1043,1107,1042, +1107,1043,1108, +1044,1108,1043, +1108,1044,1109, +1045,1109,1044, +1109,1045,1110, +1046,1110,1045, +1110,1046,1111, +1047,1111,1046, +1111,1047,1112, +1048,1112,1047, +1112,1048,1113, +1049,1113,1048, +1113,1049,1114, +1050,1114,1049, +1114,1050,1115, +1051,1115,1050, +1115,1051,1116, +1052,1116,1051, +1116,1052,1117, +1053,1117,1052, +1117,1053,1118, +1054,1118,1053, +1118,1054,1119, +1055,1119,1054, +1119,1055,1120, +1056,1120,1055, +1120,1056,1121, +1057,1121,1056, +1121,1057,1122, +1058,1122,1057, +1122,1058,1123, +1059,1123,1058, +1123,1059,1124, +1060,1124,1059, +1124,1060,1125, +1061,1125,1060, +1125,1061,1126, +1062,1126,1061, +1126,1062,1127, +1063,1127,1062, +1127,1063,1128, +1064,1128,1063, +1128,1064,1129, +1065,1129,1064, +1129,1065,1130, +1066,1130,1065, +1130,1066,1131, +1067,1131,1066, +1131,1067,1132, +1068,1132,1067, +1132,1068,1133, +1069,1133,1068, +1133,1069,1134, +1070,1134,1069, +1134,1070,1135, +1071,1135,1070, +1135,1071,1136, +1072,1136,1071, +1136,1072,1137, +1073,1137,1072, +1137,1073,1138, +1074,1138,1073, +1138,1074,1139, +1075,1139,1074, +1139,1075,1140, +1076,1140,1075, +1140,1076,1141, +1077,1141,1076, +1141,1077,1142, +1078,1142,1077, +1142,1078,1143, +1079,1143,1078, +1143,1079,1144, +1080,1144,1079, +1144,1080,1145, +1081,1145,1080, +1145,1081,1146, +1082,1146,1081, +1146,1082,1147, +1083,1147,1082, +1147,1083,1148, +1084,1148,1083, +1148,1084,1149, +1085,1149,1084, +1149,1085,1150, +1086,1150,1085, +1150,1086,1151, +1087,1151,1086, +1152,1088,1153, +1089,1153,1088, +1153,1089,1154, +1090,1154,1089, +1154,1090,1155, +1091,1155,1090, +1155,1091,1156, +1092,1156,1091, +1156,1092,1157, +1093,1157,1092, +1157,1093,1158, +1094,1158,1093, +1158,1094,1159, +1095,1159,1094, +1159,1095,1160, +1096,1160,1095, +1160,1096,1161, +1097,1161,1096, +1161,1097,1162, +1098,1162,1097, +1162,1098,1163, +1099,1163,1098, +1163,1099,1164, +1100,1164,1099, +1164,1100,1165, +1101,1165,1100, +1165,1101,1166, +1102,1166,1101, +1166,1102,1167, +1103,1167,1102, +1167,1103,1168, +1104,1168,1103, +1168,1104,1169, +1105,1169,1104, +1169,1105,1170, +1106,1170,1105, +1170,1106,1171, +1107,1171,1106, +1171,1107,1172, +1108,1172,1107, +1172,1108,1173, +1109,1173,1108, +1173,1109,1174, +1110,1174,1109, +1174,1110,1175, +1111,1175,1110, +1175,1111,1176, +1112,1176,1111, +1176,1112,1177, +1113,1177,1112, +1177,1113,1178, +1114,1178,1113, +1178,1114,1179, +1115,1179,1114, +1179,1115,1180, +1116,1180,1115, +1180,1116,1181, +1117,1181,1116, +1181,1117,1182, +1118,1182,1117, +1182,1118,1183, +1119,1183,1118, +1183,1119,1184, +1120,1184,1119, +1184,1120,1185, +1121,1185,1120, +1185,1121,1186, +1122,1186,1121, +1186,1122,1187, +1123,1187,1122, +1187,1123,1188, +1124,1188,1123, +1188,1124,1189, +1125,1189,1124, +1189,1125,1190, +1126,1190,1125, +1190,1126,1191, +1127,1191,1126, +1191,1127,1192, +1128,1192,1127, +1192,1128,1193, +1129,1193,1128, +1193,1129,1194, +1130,1194,1129, +1194,1130,1195, +1131,1195,1130, +1195,1131,1196, +1132,1196,1131, +1196,1132,1197, +1133,1197,1132, +1197,1133,1198, +1134,1198,1133, +1198,1134,1199, +1135,1199,1134, +1199,1135,1200, +1136,1200,1135, +1200,1136,1201, +1137,1201,1136, +1201,1137,1202, +1138,1202,1137, +1202,1138,1203, +1139,1203,1138, +1203,1139,1204, +1140,1204,1139, +1204,1140,1205, +1141,1205,1140, +1205,1141,1206, +1142,1206,1141, +1206,1142,1207, +1143,1207,1142, +1207,1143,1208, +1144,1208,1143, +1208,1144,1209, +1145,1209,1144, +1209,1145,1210, +1146,1210,1145, +1210,1146,1211, +1147,1211,1146, +1211,1147,1212, +1148,1212,1147, +1212,1148,1213, +1149,1213,1148, +1213,1149,1214, +1150,1214,1149, +1214,1150,1215, +1151,1215,1150, +1216,1152,1217, +1153,1217,1152, +1217,1153,1218, +1154,1218,1153, +1218,1154,1219, +1155,1219,1154, +1219,1155,1220, +1156,1220,1155, +1220,1156,1221, +1157,1221,1156, +1221,1157,1222, +1158,1222,1157, +1222,1158,1223, +1159,1223,1158, +1223,1159,1224, +1160,1224,1159, +1224,1160,1225, +1161,1225,1160, +1225,1161,1226, +1162,1226,1161, +1226,1162,1227, +1163,1227,1162, +1227,1163,1228, +1164,1228,1163, +1228,1164,1229, +1165,1229,1164, +1229,1165,1230, +1166,1230,1165, +1230,1166,1231, +1167,1231,1166, +1231,1167,1232, +1168,1232,1167, +1232,1168,1233, +1169,1233,1168, +1233,1169,1234, +1170,1234,1169, +1234,1170,1235, +1171,1235,1170, +1235,1171,1236, +1172,1236,1171, +1236,1172,1237, +1173,1237,1172, +1237,1173,1238, +1174,1238,1173, +1238,1174,1239, +1175,1239,1174, +1239,1175,1240, +1176,1240,1175, +1240,1176,1241, +1177,1241,1176, +1241,1177,1242, +1178,1242,1177, +1242,1178,1243, +1179,1243,1178, +1243,1179,1244, +1180,1244,1179, +1244,1180,1245, +1181,1245,1180, +1245,1181,1246, +1182,1246,1181, +1246,1182,1247, +1183,1247,1182, +1247,1183,1248, +1184,1248,1183, +1248,1184,1249, +1185,1249,1184, +1249,1185,1250, +1186,1250,1185, +1250,1186,1251, +1187,1251,1186, +1251,1187,1252, +1188,1252,1187, +1252,1188,1253, +1189,1253,1188, +1253,1189,1254, +1190,1254,1189, +1254,1190,1255, +1191,1255,1190, +1255,1191,1256, +1192,1256,1191, +1256,1192,1257, +1193,1257,1192, +1257,1193,1258, +1194,1258,1193, +1258,1194,1259, +1195,1259,1194, +1259,1195,1260, +1196,1260,1195, +1260,1196,1261, +1197,1261,1196, +1261,1197,1262, +1198,1262,1197, +1262,1198,1263, +1199,1263,1198, +1263,1199,1264, +1200,1264,1199, +1264,1200,1265, +1201,1265,1200, +1265,1201,1266, +1202,1266,1201, +1266,1202,1267, +1203,1267,1202, +1267,1203,1268, +1204,1268,1203, +1268,1204,1269, +1205,1269,1204, +1269,1205,1270, +1206,1270,1205, +1270,1206,1271, +1207,1271,1206, +1271,1207,1272, +1208,1272,1207, +1272,1208,1273, +1209,1273,1208, +1273,1209,1274, +1210,1274,1209, +1274,1210,1275, +1211,1275,1210, +1275,1211,1276, +1212,1276,1211, +1276,1212,1277, +1213,1277,1212, +1277,1213,1278, +1214,1278,1213, +1278,1214,1279, +1215,1279,1214, +1280,1216,1281, +1217,1281,1216, +1281,1217,1282, +1218,1282,1217, +1282,1218,1283, +1219,1283,1218, +1283,1219,1284, +1220,1284,1219, +1284,1220,1285, +1221,1285,1220, +1285,1221,1286, +1222,1286,1221, +1286,1222,1287, +1223,1287,1222, +1287,1223,1288, +1224,1288,1223, +1288,1224,1289, +1225,1289,1224, +1289,1225,1290, +1226,1290,1225, +1290,1226,1291, +1227,1291,1226, +1291,1227,1292, +1228,1292,1227, +1292,1228,1293, +1229,1293,1228, +1293,1229,1294, +1230,1294,1229, +1294,1230,1295, +1231,1295,1230, +1295,1231,1296, +1232,1296,1231, +1296,1232,1297, +1233,1297,1232, +1297,1233,1298, +1234,1298,1233, +1298,1234,1299, +1235,1299,1234, +1299,1235,1300, +1236,1300,1235, +1300,1236,1301, +1237,1301,1236, +1301,1237,1302, +1238,1302,1237, +1302,1238,1303, +1239,1303,1238, +1303,1239,1304, +1240,1304,1239, +1304,1240,1305, +1241,1305,1240, +1305,1241,1306, +1242,1306,1241, +1306,1242,1307, +1243,1307,1242, +1307,1243,1308, +1244,1308,1243, +1308,1244,1309, +1245,1309,1244, +1309,1245,1310, +1246,1310,1245, +1310,1246,1311, +1247,1311,1246, +1311,1247,1312, +1248,1312,1247, +1312,1248,1313, +1249,1313,1248, +1313,1249,1314, +1250,1314,1249, +1314,1250,1315, +1251,1315,1250, +1315,1251,1316, +1252,1316,1251, +1316,1252,1317, +1253,1317,1252, +1317,1253,1318, +1254,1318,1253, +1318,1254,1319, +1255,1319,1254, +1319,1255,1320, +1256,1320,1255, +1320,1256,1321, +1257,1321,1256, +1321,1257,1322, +1258,1322,1257, +1322,1258,1323, +1259,1323,1258, +1323,1259,1324, +1260,1324,1259, +1324,1260,1325, +1261,1325,1260, +1325,1261,1326, +1262,1326,1261, +1326,1262,1327, +1263,1327,1262, +1327,1263,1328, +1264,1328,1263, +1328,1264,1329, +1265,1329,1264, +1329,1265,1330, +1266,1330,1265, +1330,1266,1331, +1267,1331,1266, +1331,1267,1332, +1268,1332,1267, +1332,1268,1333, +1269,1333,1268, +1333,1269,1334, +1270,1334,1269, +1334,1270,1335, +1271,1335,1270, +1335,1271,1336, +1272,1336,1271, +1336,1272,1337, +1273,1337,1272, +1337,1273,1338, +1274,1338,1273, +1338,1274,1339, +1275,1339,1274, +1339,1275,1340, +1276,1340,1275, +1340,1276,1341, +1277,1341,1276, +1341,1277,1342, +1278,1342,1277, +1342,1278,1343, +1279,1343,1278, +1344,1280,1345, +1281,1345,1280, +1345,1281,1346, +1282,1346,1281, +1346,1282,1347, +1283,1347,1282, +1347,1283,1348, +1284,1348,1283, +1348,1284,1349, +1285,1349,1284, +1349,1285,1350, +1286,1350,1285, +1350,1286,1351, +1287,1351,1286, +1351,1287,1352, +1288,1352,1287, +1352,1288,1353, +1289,1353,1288, +1353,1289,1354, +1290,1354,1289, +1354,1290,1355, +1291,1355,1290, +1355,1291,1356, +1292,1356,1291, +1356,1292,1357, +1293,1357,1292, +1357,1293,1358, +1294,1358,1293, +1358,1294,1359, +1295,1359,1294, +1359,1295,1360, +1296,1360,1295, +1360,1296,1361, +1297,1361,1296, +1361,1297,1362, +1298,1362,1297, +1362,1298,1363, +1299,1363,1298, +1363,1299,1364, +1300,1364,1299, +1364,1300,1365, +1301,1365,1300, +1365,1301,1366, +1302,1366,1301, +1366,1302,1367, +1303,1367,1302, +1367,1303,1368, +1304,1368,1303, +1368,1304,1369, +1305,1369,1304, +1369,1305,1370, +1306,1370,1305, +1370,1306,1371, +1307,1371,1306, +1371,1307,1372, +1308,1372,1307, +1372,1308,1373, +1309,1373,1308, +1373,1309,1374, +1310,1374,1309, +1374,1310,1375, +1311,1375,1310, +1375,1311,1376, +1312,1376,1311, +1376,1312,1377, +1313,1377,1312, +1377,1313,1378, +1314,1378,1313, +1378,1314,1379, +1315,1379,1314, +1379,1315,1380, +1316,1380,1315, +1380,1316,1381, +1317,1381,1316, +1381,1317,1382, +1318,1382,1317, +1382,1318,1383, +1319,1383,1318, +1383,1319,1384, +1320,1384,1319, +1384,1320,1385, +1321,1385,1320, +1385,1321,1386, +1322,1386,1321, +1386,1322,1387, +1323,1387,1322, +1387,1323,1388, +1324,1388,1323, +1388,1324,1389, +1325,1389,1324, +1389,1325,1390, +1326,1390,1325, +1390,1326,1391, +1327,1391,1326, +1391,1327,1392, +1328,1392,1327, +1392,1328,1393, +1329,1393,1328, +1393,1329,1394, +1330,1394,1329, +1394,1330,1395, +1331,1395,1330, +1395,1331,1396, +1332,1396,1331, +1396,1332,1397, +1333,1397,1332, +1397,1333,1398, +1334,1398,1333, +1398,1334,1399, +1335,1399,1334, +1399,1335,1400, +1336,1400,1335, +1400,1336,1401, +1337,1401,1336, +1401,1337,1402, +1338,1402,1337, +1402,1338,1403, +1339,1403,1338, +1403,1339,1404, +1340,1404,1339, +1404,1340,1405, +1341,1405,1340, +1405,1341,1406, +1342,1406,1341, +1406,1342,1407, +1343,1407,1342, +1408,1344,1409, +1345,1409,1344, +1409,1345,1410, +1346,1410,1345, +1410,1346,1411, +1347,1411,1346, +1411,1347,1412, +1348,1412,1347, +1412,1348,1413, +1349,1413,1348, +1413,1349,1414, +1350,1414,1349, +1414,1350,1415, +1351,1415,1350, +1415,1351,1416, +1352,1416,1351, +1416,1352,1417, +1353,1417,1352, +1417,1353,1418, +1354,1418,1353, +1418,1354,1419, +1355,1419,1354, +1419,1355,1420, +1356,1420,1355, +1420,1356,1421, +1357,1421,1356, +1421,1357,1422, +1358,1422,1357, +1422,1358,1423, +1359,1423,1358, +1423,1359,1424, +1360,1424,1359, +1424,1360,1425, +1361,1425,1360, +1425,1361,1426, +1362,1426,1361, +1426,1362,1427, +1363,1427,1362, +1427,1363,1428, +1364,1428,1363, +1428,1364,1429, +1365,1429,1364, +1429,1365,1430, +1366,1430,1365, +1430,1366,1431, +1367,1431,1366, +1431,1367,1432, +1368,1432,1367, +1432,1368,1433, +1369,1433,1368, +1433,1369,1434, +1370,1434,1369, +1434,1370,1435, +1371,1435,1370, +1435,1371,1436, +1372,1436,1371, +1436,1372,1437, +1373,1437,1372, +1437,1373,1438, +1374,1438,1373, +1438,1374,1439, +1375,1439,1374, +1439,1375,1440, +1376,1440,1375, +1440,1376,1441, +1377,1441,1376, +1441,1377,1442, +1378,1442,1377, +1442,1378,1443, +1379,1443,1378, +1443,1379,1444, +1380,1444,1379, +1444,1380,1445, +1381,1445,1380, +1445,1381,1446, +1382,1446,1381, +1446,1382,1447, +1383,1447,1382, +1447,1383,1448, +1384,1448,1383, +1448,1384,1449, +1385,1449,1384, +1449,1385,1450, +1386,1450,1385, +1450,1386,1451, +1387,1451,1386, +1451,1387,1452, +1388,1452,1387, +1452,1388,1453, +1389,1453,1388, +1453,1389,1454, +1390,1454,1389, +1454,1390,1455, +1391,1455,1390, +1455,1391,1456, +1392,1456,1391, +1456,1392,1457, +1393,1457,1392, +1457,1393,1458, +1394,1458,1393, +1458,1394,1459, +1395,1459,1394, +1459,1395,1460, +1396,1460,1395, +1460,1396,1461, +1397,1461,1396, +1461,1397,1462, +1398,1462,1397, +1462,1398,1463, +1399,1463,1398, +1463,1399,1464, +1400,1464,1399, +1464,1400,1465, +1401,1465,1400, +1465,1401,1466, +1402,1466,1401, +1466,1402,1467, +1403,1467,1402, +1467,1403,1468, +1404,1468,1403, +1468,1404,1469, +1405,1469,1404, +1469,1405,1470, +1406,1470,1405, +1470,1406,1471, +1407,1471,1406, +1472,1408,1473, +1409,1473,1408, +1473,1409,1474, +1410,1474,1409, +1474,1410,1475, +1411,1475,1410, +1475,1411,1476, +1412,1476,1411, +1476,1412,1477, +1413,1477,1412, +1477,1413,1478, +1414,1478,1413, +1478,1414,1479, +1415,1479,1414, +1479,1415,1480, +1416,1480,1415, +1480,1416,1481, +1417,1481,1416, +1481,1417,1482, +1418,1482,1417, +1482,1418,1483, +1419,1483,1418, +1483,1419,1484, +1420,1484,1419, +1484,1420,1485, +1421,1485,1420, +1485,1421,1486, +1422,1486,1421, +1486,1422,1487, +1423,1487,1422, +1487,1423,1488, +1424,1488,1423, +1488,1424,1489, +1425,1489,1424, +1489,1425,1490, +1426,1490,1425, +1490,1426,1491, +1427,1491,1426, +1491,1427,1492, +1428,1492,1427, +1492,1428,1493, +1429,1493,1428, +1493,1429,1494, +1430,1494,1429, +1494,1430,1495, +1431,1495,1430, +1495,1431,1496, +1432,1496,1431, +1496,1432,1497, +1433,1497,1432, +1497,1433,1498, +1434,1498,1433, +1498,1434,1499, +1435,1499,1434, +1499,1435,1500, +1436,1500,1435, +1500,1436,1501, +1437,1501,1436, +1501,1437,1502, +1438,1502,1437, +1502,1438,1503, +1439,1503,1438, +1503,1439,1504, +1440,1504,1439, +1504,1440,1505, +1441,1505,1440, +1505,1441,1506, +1442,1506,1441, +1506,1442,1507, +1443,1507,1442, +1507,1443,1508, +1444,1508,1443, +1508,1444,1509, +1445,1509,1444, +1509,1445,1510, +1446,1510,1445, +1510,1446,1511, +1447,1511,1446, +1511,1447,1512, +1448,1512,1447, +1512,1448,1513, +1449,1513,1448, +1513,1449,1514, +1450,1514,1449, +1514,1450,1515, +1451,1515,1450, +1515,1451,1516, +1452,1516,1451, +1516,1452,1517, +1453,1517,1452, +1517,1453,1518, +1454,1518,1453, +1518,1454,1519, +1455,1519,1454, +1519,1455,1520, +1456,1520,1455, +1520,1456,1521, +1457,1521,1456, +1521,1457,1522, +1458,1522,1457, +1522,1458,1523, +1459,1523,1458, +1523,1459,1524, +1460,1524,1459, +1524,1460,1525, +1461,1525,1460, +1525,1461,1526, +1462,1526,1461, +1526,1462,1527, +1463,1527,1462, +1527,1463,1528, +1464,1528,1463, +1528,1464,1529, +1465,1529,1464, +1529,1465,1530, +1466,1530,1465, +1530,1466,1531, +1467,1531,1466, +1531,1467,1532, +1468,1532,1467, +1532,1468,1533, +1469,1533,1468, +1533,1469,1534, +1470,1534,1469, +1534,1470,1535, +1471,1535,1470, +1536,1472,1537, +1473,1537,1472, +1537,1473,1538, +1474,1538,1473, +1538,1474,1539, +1475,1539,1474, +1539,1475,1540, +1476,1540,1475, +1540,1476,1541, +1477,1541,1476, +1541,1477,1542, +1478,1542,1477, +1542,1478,1543, +1479,1543,1478, +1543,1479,1544, +1480,1544,1479, +1544,1480,1545, +1481,1545,1480, +1545,1481,1546, +1482,1546,1481, +1546,1482,1547, +1483,1547,1482, +1547,1483,1548, +1484,1548,1483, +1548,1484,1549, +1485,1549,1484, +1549,1485,1550, +1486,1550,1485, +1550,1486,1551, +1487,1551,1486, +1551,1487,1552, +1488,1552,1487, +1552,1488,1553, +1489,1553,1488, +1553,1489,1554, +1490,1554,1489, +1554,1490,1555, +1491,1555,1490, +1555,1491,1556, +1492,1556,1491, +1556,1492,1557, +1493,1557,1492, +1557,1493,1558, +1494,1558,1493, +1558,1494,1559, +1495,1559,1494, +1559,1495,1560, +1496,1560,1495, +1560,1496,1561, +1497,1561,1496, +1561,1497,1562, +1498,1562,1497, +1562,1498,1563, +1499,1563,1498, +1563,1499,1564, +1500,1564,1499, +1564,1500,1565, +1501,1565,1500, +1565,1501,1566, +1502,1566,1501, +1566,1502,1567, +1503,1567,1502, +1567,1503,1568, +1504,1568,1503, +1568,1504,1569, +1505,1569,1504, +1569,1505,1570, +1506,1570,1505, +1570,1506,1571, +1507,1571,1506, +1571,1507,1572, +1508,1572,1507, +1572,1508,1573, +1509,1573,1508, +1573,1509,1574, +1510,1574,1509, +1574,1510,1575, +1511,1575,1510, +1575,1511,1576, +1512,1576,1511, +1576,1512,1577, +1513,1577,1512, +1577,1513,1578, +1514,1578,1513, +1578,1514,1579, +1515,1579,1514, +1579,1515,1580, +1516,1580,1515, +1580,1516,1581, +1517,1581,1516, +1581,1517,1582, +1518,1582,1517, +1582,1518,1583, +1519,1583,1518, +1583,1519,1584, +1520,1584,1519, +1584,1520,1585, +1521,1585,1520, +1585,1521,1586, +1522,1586,1521, +1586,1522,1587, +1523,1587,1522, +1587,1523,1588, +1524,1588,1523, +1588,1524,1589, +1525,1589,1524, +1589,1525,1590, +1526,1590,1525, +1590,1526,1591, +1527,1591,1526, +1591,1527,1592, +1528,1592,1527, +1592,1528,1593, +1529,1593,1528, +1593,1529,1594, +1530,1594,1529, +1594,1530,1595, +1531,1595,1530, +1595,1531,1596, +1532,1596,1531, +1596,1532,1597, +1533,1597,1532, +1597,1533,1598, +1534,1598,1533, +1598,1534,1599, +1535,1599,1534, +1600,1536,1601, +1537,1601,1536, +1601,1537,1602, +1538,1602,1537, +1602,1538,1603, +1539,1603,1538, +1603,1539,1604, +1540,1604,1539, +1604,1540,1605, +1541,1605,1540, +1605,1541,1606, +1542,1606,1541, +1606,1542,1607, +1543,1607,1542, +1607,1543,1608, +1544,1608,1543, +1608,1544,1609, +1545,1609,1544, +1609,1545,1610, +1546,1610,1545, +1610,1546,1611, +1547,1611,1546, +1611,1547,1612, +1548,1612,1547, +1612,1548,1613, +1549,1613,1548, +1613,1549,1614, +1550,1614,1549, +1614,1550,1615, +1551,1615,1550, +1615,1551,1616, +1552,1616,1551, +1616,1552,1617, +1553,1617,1552, +1617,1553,1618, +1554,1618,1553, +1618,1554,1619, +1555,1619,1554, +1619,1555,1620, +1556,1620,1555, +1620,1556,1621, +1557,1621,1556, +1621,1557,1622, +1558,1622,1557, +1622,1558,1623, +1559,1623,1558, +1623,1559,1624, +1560,1624,1559, +1624,1560,1625, +1561,1625,1560, +1625,1561,1626, +1562,1626,1561, +1626,1562,1627, +1563,1627,1562, +1627,1563,1628, +1564,1628,1563, +1628,1564,1629, +1565,1629,1564, +1629,1565,1630, +1566,1630,1565, +1630,1566,1631, +1567,1631,1566, +1631,1567,1632, +1568,1632,1567, +1632,1568,1633, +1569,1633,1568, +1633,1569,1634, +1570,1634,1569, +1634,1570,1635, +1571,1635,1570, +1635,1571,1636, +1572,1636,1571, +1636,1572,1637, +1573,1637,1572, +1637,1573,1638, +1574,1638,1573, +1638,1574,1639, +1575,1639,1574, +1639,1575,1640, +1576,1640,1575, +1640,1576,1641, +1577,1641,1576, +1641,1577,1642, +1578,1642,1577, +1642,1578,1643, +1579,1643,1578, +1643,1579,1644, +1580,1644,1579, +1644,1580,1645, +1581,1645,1580, +1645,1581,1646, +1582,1646,1581, +1646,1582,1647, +1583,1647,1582, +1647,1583,1648, +1584,1648,1583, +1648,1584,1649, +1585,1649,1584, +1649,1585,1650, +1586,1650,1585, +1650,1586,1651, +1587,1651,1586, +1651,1587,1652, +1588,1652,1587, +1652,1588,1653, +1589,1653,1588, +1653,1589,1654, +1590,1654,1589, +1654,1590,1655, +1591,1655,1590, +1655,1591,1656, +1592,1656,1591, +1656,1592,1657, +1593,1657,1592, +1657,1593,1658, +1594,1658,1593, +1658,1594,1659, +1595,1659,1594, +1659,1595,1660, +1596,1660,1595, +1660,1596,1661, +1597,1661,1596, +1661,1597,1662, +1598,1662,1597, +1662,1598,1663, +1599,1663,1598, +1664,1600,1665, +1601,1665,1600, +1665,1601,1666, +1602,1666,1601, +1666,1602,1667, +1603,1667,1602, +1667,1603,1668, +1604,1668,1603, +1668,1604,1669, +1605,1669,1604, +1669,1605,1670, +1606,1670,1605, +1670,1606,1671, +1607,1671,1606, +1671,1607,1672, +1608,1672,1607, +1672,1608,1673, +1609,1673,1608, +1673,1609,1674, +1610,1674,1609, +1674,1610,1675, +1611,1675,1610, +1675,1611,1676, +1612,1676,1611, +1676,1612,1677, +1613,1677,1612, +1677,1613,1678, +1614,1678,1613, +1678,1614,1679, +1615,1679,1614, +1679,1615,1680, +1616,1680,1615, +1680,1616,1681, +1617,1681,1616, +1681,1617,1682, +1618,1682,1617, +1682,1618,1683, +1619,1683,1618, +1683,1619,1684, +1620,1684,1619, +1684,1620,1685, +1621,1685,1620, +1685,1621,1686, +1622,1686,1621, +1686,1622,1687, +1623,1687,1622, +1687,1623,1688, +1624,1688,1623, +1688,1624,1689, +1625,1689,1624, +1689,1625,1690, +1626,1690,1625, +1690,1626,1691, +1627,1691,1626, +1691,1627,1692, +1628,1692,1627, +1692,1628,1693, +1629,1693,1628, +1693,1629,1694, +1630,1694,1629, +1694,1630,1695, +1631,1695,1630, +1695,1631,1696, +1632,1696,1631, +1696,1632,1697, +1633,1697,1632, +1697,1633,1698, +1634,1698,1633, +1698,1634,1699, +1635,1699,1634, +1699,1635,1700, +1636,1700,1635, +1700,1636,1701, +1637,1701,1636, +1701,1637,1702, +1638,1702,1637, +1702,1638,1703, +1639,1703,1638, +1703,1639,1704, +1640,1704,1639, +1704,1640,1705, +1641,1705,1640, +1705,1641,1706, +1642,1706,1641, +1706,1642,1707, +1643,1707,1642, +1707,1643,1708, +1644,1708,1643, +1708,1644,1709, +1645,1709,1644, +1709,1645,1710, +1646,1710,1645, +1710,1646,1711, +1647,1711,1646, +1711,1647,1712, +1648,1712,1647, +1712,1648,1713, +1649,1713,1648, +1713,1649,1714, +1650,1714,1649, +1714,1650,1715, +1651,1715,1650, +1715,1651,1716, +1652,1716,1651, +1716,1652,1717, +1653,1717,1652, +1717,1653,1718, +1654,1718,1653, +1718,1654,1719, +1655,1719,1654, +1719,1655,1720, +1656,1720,1655, +1720,1656,1721, +1657,1721,1656, +1721,1657,1722, +1658,1722,1657, +1722,1658,1723, +1659,1723,1658, +1723,1659,1724, +1660,1724,1659, +1724,1660,1725, +1661,1725,1660, +1725,1661,1726, +1662,1726,1661, +1726,1662,1727, +1663,1727,1662, +1728,1664,1729, +1665,1729,1664, +1729,1665,1730, +1666,1730,1665, +1730,1666,1731, +1667,1731,1666, +1731,1667,1732, +1668,1732,1667, +1732,1668,1733, +1669,1733,1668, +1733,1669,1734, +1670,1734,1669, +1734,1670,1735, +1671,1735,1670, +1735,1671,1736, +1672,1736,1671, +1736,1672,1737, +1673,1737,1672, +1737,1673,1738, +1674,1738,1673, +1738,1674,1739, +1675,1739,1674, +1739,1675,1740, +1676,1740,1675, +1740,1676,1741, +1677,1741,1676, +1741,1677,1742, +1678,1742,1677, +1742,1678,1743, +1679,1743,1678, +1743,1679,1744, +1680,1744,1679, +1744,1680,1745, +1681,1745,1680, +1745,1681,1746, +1682,1746,1681, +1746,1682,1747, +1683,1747,1682, +1747,1683,1748, +1684,1748,1683, +1748,1684,1749, +1685,1749,1684, +1749,1685,1750, +1686,1750,1685, +1750,1686,1751, +1687,1751,1686, +1751,1687,1752, +1688,1752,1687, +1752,1688,1753, +1689,1753,1688, +1753,1689,1754, +1690,1754,1689, +1754,1690,1755, +1691,1755,1690, +1755,1691,1756, +1692,1756,1691, +1756,1692,1757, +1693,1757,1692, +1757,1693,1758, +1694,1758,1693, +1758,1694,1759, +1695,1759,1694, +1759,1695,1760, +1696,1760,1695, +1760,1696,1761, +1697,1761,1696, +1761,1697,1762, +1698,1762,1697, +1762,1698,1763, +1699,1763,1698, +1763,1699,1764, +1700,1764,1699, +1764,1700,1765, +1701,1765,1700, +1765,1701,1766, +1702,1766,1701, +1766,1702,1767, +1703,1767,1702, +1767,1703,1768, +1704,1768,1703, +1768,1704,1769, +1705,1769,1704, +1769,1705,1770, +1706,1770,1705, +1770,1706,1771, +1707,1771,1706, +1771,1707,1772, +1708,1772,1707, +1772,1708,1773, +1709,1773,1708, +1773,1709,1774, +1710,1774,1709, +1774,1710,1775, +1711,1775,1710, +1775,1711,1776, +1712,1776,1711, +1776,1712,1777, +1713,1777,1712, +1777,1713,1778, +1714,1778,1713, +1778,1714,1779, +1715,1779,1714, +1779,1715,1780, +1716,1780,1715, +1780,1716,1781, +1717,1781,1716, +1781,1717,1782, +1718,1782,1717, +1782,1718,1783, +1719,1783,1718, +1783,1719,1784, +1720,1784,1719, +1784,1720,1785, +1721,1785,1720, +1785,1721,1786, +1722,1786,1721, +1786,1722,1787, +1723,1787,1722, +1787,1723,1788, +1724,1788,1723, +1788,1724,1789, +1725,1789,1724, +1789,1725,1790, +1726,1790,1725, +1790,1726,1791, +1727,1791,1726, +1792,1728,1793, +1729,1793,1728, +1793,1729,1794, +1730,1794,1729, +1794,1730,1795, +1731,1795,1730, +1795,1731,1796, +1732,1796,1731, +1796,1732,1797, +1733,1797,1732, +1797,1733,1798, +1734,1798,1733, +1798,1734,1799, +1735,1799,1734, +1799,1735,1800, +1736,1800,1735, +1800,1736,1801, +1737,1801,1736, +1801,1737,1802, +1738,1802,1737, +1802,1738,1803, +1739,1803,1738, +1803,1739,1804, +1740,1804,1739, +1804,1740,1805, +1741,1805,1740, +1805,1741,1806, +1742,1806,1741, +1806,1742,1807, +1743,1807,1742, +1807,1743,1808, +1744,1808,1743, +1808,1744,1809, +1745,1809,1744, +1809,1745,1810, +1746,1810,1745, +1810,1746,1811, +1747,1811,1746, +1811,1747,1812, +1748,1812,1747, +1812,1748,1813, +1749,1813,1748, +1813,1749,1814, +1750,1814,1749, +1814,1750,1815, +1751,1815,1750, +1815,1751,1816, +1752,1816,1751, +1816,1752,1817, +1753,1817,1752, +1817,1753,1818, +1754,1818,1753, +1818,1754,1819, +1755,1819,1754, +1819,1755,1820, +1756,1820,1755, +1820,1756,1821, +1757,1821,1756, +1821,1757,1822, +1758,1822,1757, +1822,1758,1823, +1759,1823,1758, +1823,1759,1824, +1760,1824,1759, +1824,1760,1825, +1761,1825,1760, +1825,1761,1826, +1762,1826,1761, +1826,1762,1827, +1763,1827,1762, +1827,1763,1828, +1764,1828,1763, +1828,1764,1829, +1765,1829,1764, +1829,1765,1830, +1766,1830,1765, +1830,1766,1831, +1767,1831,1766, +1831,1767,1832, +1768,1832,1767, +1832,1768,1833, +1769,1833,1768, +1833,1769,1834, +1770,1834,1769, +1834,1770,1835, +1771,1835,1770, +1835,1771,1836, +1772,1836,1771, +1836,1772,1837, +1773,1837,1772, +1837,1773,1838, +1774,1838,1773, +1838,1774,1839, +1775,1839,1774, +1839,1775,1840, +1776,1840,1775, +1840,1776,1841, +1777,1841,1776, +1841,1777,1842, +1778,1842,1777, +1842,1778,1843, +1779,1843,1778, +1843,1779,1844, +1780,1844,1779, +1844,1780,1845, +1781,1845,1780, +1845,1781,1846, +1782,1846,1781, +1846,1782,1847, +1783,1847,1782, +1847,1783,1848, +1784,1848,1783, +1848,1784,1849, +1785,1849,1784, +1849,1785,1850, +1786,1850,1785, +1850,1786,1851, +1787,1851,1786, +1851,1787,1852, +1788,1852,1787, +1852,1788,1853, +1789,1853,1788, +1853,1789,1854, +1790,1854,1789, +1854,1790,1855, +1791,1855,1790, +1856,1792,1857, +1793,1857,1792, +1857,1793,1858, +1794,1858,1793, +1858,1794,1859, +1795,1859,1794, +1859,1795,1860, +1796,1860,1795, +1860,1796,1861, +1797,1861,1796, +1861,1797,1862, +1798,1862,1797, +1862,1798,1863, +1799,1863,1798, +1863,1799,1864, +1800,1864,1799, +1864,1800,1865, +1801,1865,1800, +1865,1801,1866, +1802,1866,1801, +1866,1802,1867, +1803,1867,1802, +1867,1803,1868, +1804,1868,1803, +1868,1804,1869, +1805,1869,1804, +1869,1805,1870, +1806,1870,1805, +1870,1806,1871, +1807,1871,1806, +1871,1807,1872, +1808,1872,1807, +1872,1808,1873, +1809,1873,1808, +1873,1809,1874, +1810,1874,1809, +1874,1810,1875, +1811,1875,1810, +1875,1811,1876, +1812,1876,1811, +1876,1812,1877, +1813,1877,1812, +1877,1813,1878, +1814,1878,1813, +1878,1814,1879, +1815,1879,1814, +1879,1815,1880, +1816,1880,1815, +1880,1816,1881, +1817,1881,1816, +1881,1817,1882, +1818,1882,1817, +1882,1818,1883, +1819,1883,1818, +1883,1819,1884, +1820,1884,1819, +1884,1820,1885, +1821,1885,1820, +1885,1821,1886, +1822,1886,1821, +1886,1822,1887, +1823,1887,1822, +1887,1823,1888, +1824,1888,1823, +1888,1824,1889, +1825,1889,1824, +1889,1825,1890, +1826,1890,1825, +1890,1826,1891, +1827,1891,1826, +1891,1827,1892, +1828,1892,1827, +1892,1828,1893, +1829,1893,1828, +1893,1829,1894, +1830,1894,1829, +1894,1830,1895, +1831,1895,1830, +1895,1831,1896, +1832,1896,1831, +1896,1832,1897, +1833,1897,1832, +1897,1833,1898, +1834,1898,1833, +1898,1834,1899, +1835,1899,1834, +1899,1835,1900, +1836,1900,1835, +1900,1836,1901, +1837,1901,1836, +1901,1837,1902, +1838,1902,1837, +1902,1838,1903, +1839,1903,1838, +1903,1839,1904, +1840,1904,1839, +1904,1840,1905, +1841,1905,1840, +1905,1841,1906, +1842,1906,1841, +1906,1842,1907, +1843,1907,1842, +1907,1843,1908, +1844,1908,1843, +1908,1844,1909, +1845,1909,1844, +1909,1845,1910, +1846,1910,1845, +1910,1846,1911, +1847,1911,1846, +1911,1847,1912, +1848,1912,1847, +1912,1848,1913, +1849,1913,1848, +1913,1849,1914, +1850,1914,1849, +1914,1850,1915, +1851,1915,1850, +1915,1851,1916, +1852,1916,1851, +1916,1852,1917, +1853,1917,1852, +1917,1853,1918, +1854,1918,1853, +1918,1854,1919, +1855,1919,1854, +1920,1856,1921, +1857,1921,1856, +1921,1857,1922, +1858,1922,1857, +1922,1858,1923, +1859,1923,1858, +1923,1859,1924, +1860,1924,1859, +1924,1860,1925, +1861,1925,1860, +1925,1861,1926, +1862,1926,1861, +1926,1862,1927, +1863,1927,1862, +1927,1863,1928, +1864,1928,1863, +1928,1864,1929, +1865,1929,1864, +1929,1865,1930, +1866,1930,1865, +1930,1866,1931, +1867,1931,1866, +1931,1867,1932, +1868,1932,1867, +1932,1868,1933, +1869,1933,1868, +1933,1869,1934, +1870,1934,1869, +1934,1870,1935, +1871,1935,1870, +1935,1871,1936, +1872,1936,1871, +1936,1872,1937, +1873,1937,1872, +1937,1873,1938, +1874,1938,1873, +1938,1874,1939, +1875,1939,1874, +1939,1875,1940, +1876,1940,1875, +1940,1876,1941, +1877,1941,1876, +1941,1877,1942, +1878,1942,1877, +1942,1878,1943, +1879,1943,1878, +1943,1879,1944, +1880,1944,1879, +1944,1880,1945, +1881,1945,1880, +1945,1881,1946, +1882,1946,1881, +1946,1882,1947, +1883,1947,1882, +1947,1883,1948, +1884,1948,1883, +1948,1884,1949, +1885,1949,1884, +1949,1885,1950, +1886,1950,1885, +1950,1886,1951, +1887,1951,1886, +1951,1887,1952, +1888,1952,1887, +1952,1888,1953, +1889,1953,1888, +1953,1889,1954, +1890,1954,1889, +1954,1890,1955, +1891,1955,1890, +1955,1891,1956, +1892,1956,1891, +1956,1892,1957, +1893,1957,1892, +1957,1893,1958, +1894,1958,1893, +1958,1894,1959, +1895,1959,1894, +1959,1895,1960, +1896,1960,1895, +1960,1896,1961, +1897,1961,1896, +1961,1897,1962, +1898,1962,1897, +1962,1898,1963, +1899,1963,1898, +1963,1899,1964, +1900,1964,1899, +1964,1900,1965, +1901,1965,1900, +1965,1901,1966, +1902,1966,1901, +1966,1902,1967, +1903,1967,1902, +1967,1903,1968, +1904,1968,1903, +1968,1904,1969, +1905,1969,1904, +1969,1905,1970, +1906,1970,1905, +1970,1906,1971, +1907,1971,1906, +1971,1907,1972, +1908,1972,1907, +1972,1908,1973, +1909,1973,1908, +1973,1909,1974, +1910,1974,1909, +1974,1910,1975, +1911,1975,1910, +1975,1911,1976, +1912,1976,1911, +1976,1912,1977, +1913,1977,1912, +1977,1913,1978, +1914,1978,1913, +1978,1914,1979, +1915,1979,1914, +1979,1915,1980, +1916,1980,1915, +1980,1916,1981, +1917,1981,1916, +1981,1917,1982, +1918,1982,1917, +1982,1918,1983, +1919,1983,1918, +1984,1920,1985, +1921,1985,1920, +1985,1921,1986, +1922,1986,1921, +1986,1922,1987, +1923,1987,1922, +1987,1923,1988, +1924,1988,1923, +1988,1924,1989, +1925,1989,1924, +1989,1925,1990, +1926,1990,1925, +1990,1926,1991, +1927,1991,1926, +1991,1927,1992, +1928,1992,1927, +1992,1928,1993, +1929,1993,1928, +1993,1929,1994, +1930,1994,1929, +1994,1930,1995, +1931,1995,1930, +1995,1931,1996, +1932,1996,1931, +1996,1932,1997, +1933,1997,1932, +1997,1933,1998, +1934,1998,1933, +1998,1934,1999, +1935,1999,1934, +1999,1935,2000, +1936,2000,1935, +2000,1936,2001, +1937,2001,1936, +2001,1937,2002, +1938,2002,1937, +2002,1938,2003, +1939,2003,1938, +2003,1939,2004, +1940,2004,1939, +2004,1940,2005, +1941,2005,1940, +2005,1941,2006, +1942,2006,1941, +2006,1942,2007, +1943,2007,1942, +2007,1943,2008, +1944,2008,1943, +2008,1944,2009, +1945,2009,1944, +2009,1945,2010, +1946,2010,1945, +2010,1946,2011, +1947,2011,1946, +2011,1947,2012, +1948,2012,1947, +2012,1948,2013, +1949,2013,1948, +2013,1949,2014, +1950,2014,1949, +2014,1950,2015, +1951,2015,1950, +2015,1951,2016, +1952,2016,1951, +2016,1952,2017, +1953,2017,1952, +2017,1953,2018, +1954,2018,1953, +2018,1954,2019, +1955,2019,1954, +2019,1955,2020, +1956,2020,1955, +2020,1956,2021, +1957,2021,1956, +2021,1957,2022, +1958,2022,1957, +2022,1958,2023, +1959,2023,1958, +2023,1959,2024, +1960,2024,1959, +2024,1960,2025, +1961,2025,1960, +2025,1961,2026, +1962,2026,1961, +2026,1962,2027, +1963,2027,1962, +2027,1963,2028, +1964,2028,1963, +2028,1964,2029, +1965,2029,1964, +2029,1965,2030, +1966,2030,1965, +2030,1966,2031, +1967,2031,1966, +2031,1967,2032, +1968,2032,1967, +2032,1968,2033, +1969,2033,1968, +2033,1969,2034, +1970,2034,1969, +2034,1970,2035, +1971,2035,1970, +2035,1971,2036, +1972,2036,1971, +2036,1972,2037, +1973,2037,1972, +2037,1973,2038, +1974,2038,1973, +2038,1974,2039, +1975,2039,1974, +2039,1975,2040, +1976,2040,1975, +2040,1976,2041, +1977,2041,1976, +2041,1977,2042, +1978,2042,1977, +2042,1978,2043, +1979,2043,1978, +2043,1979,2044, +1980,2044,1979, +2044,1980,2045, +1981,2045,1980, +2045,1981,2046, +1982,2046,1981, +2046,1982,2047, +1983,2047,1982, +}; + +#define Landscape04VtxCount 2112 +#define Landscape04IdxCount 12096 + +btScalar Landscape04Vtx[] = { +3.90625f,18.9654f,125.0f, +3.90625f,20.0876f,128.906f, +7.8125f,20.5764f,125.0f, +7.8125f,21.0764f,128.906f, +11.7188f,21.5489f,125.0f, +11.7188f,21.4076f,128.906f, +15.625f,22.4963f,125.0f, +15.625f,22.6299f,128.906f, +19.5313f,22.3264f,125.0f, +19.5313f,22.1174f,128.906f, +23.4375f,20.3987f,125.0f, +23.4375f,20.3977f,128.906f, +27.3438f,18.6622f,125.0f, +27.3438f,18.7343f,128.906f, +31.25f,17.4724f,125.0f, +31.25f,17.9144f,128.906f, +35.1563f,16.4832f,125.0f, +35.1563f,17.2941f,128.906f, +39.0625f,15.2653f,125.0f, +39.0625f,16.5386f,128.906f, +42.9688f,14.379f,125.0f, +42.9688f,15.6892f,128.906f, +46.875f,13.9872f,125.0f, +46.875f,14.6414f,128.906f, +50.7813f,14.7002f,125.0f, +50.7813f,14.3505f,128.906f, +54.6875f,15.1119f,125.0f, +54.6875f,14.1604f,128.906f, +58.5938f,14.6638f,125.0f, +58.5938f,14.517f,128.906f, +62.5f,14.668f,125.0f, +62.5f,15.1057f,128.906f, +66.4063f,14.9792f,125.0f, +66.4063f,16.0684f,128.906f, +70.3125f,15.4776f,125.0f, +70.3125f,16.6251f,128.906f, +74.2188f,15.0939f,125.0f, +74.2188f,15.9689f,128.906f, +78.125f,15.5318f,125.0f, +78.125f,16.0234f,128.906f, +82.0313f,16.0777f,125.0f, +82.0313f,16.205f,128.906f, +85.9375f,17.8753f,125.0f, +85.9375f,18.8167f,128.906f, +89.8438f,18.8786f,125.0f, +89.8438f,19.6433f,128.906f, +93.75f,19.8208f,125.0f, +93.75f,20.2916f,128.906f, +97.6563f,23.2578f,125.0f, +97.6563f,23.2308f,128.906f, +101.563f,25.3117f,125.0f, +101.563f,25.882f,128.906f, +105.469f,26.8718f,125.0f, +105.469f,27.5736f,128.906f, +109.375f,28.7414f,125.0f, +109.375f,28.9662f,128.906f, +113.281f,29.9339f,125.0f, +113.281f,30.5702f,128.906f, +117.188f,30.6849f,125.0f, +117.188f,31.8627f,128.906f, +121.094f,32.4202f,125.0f, +121.094f,32.5216f,128.906f, +125.0f,34.7495f,125.0f, +125.0f,34.1918f,128.906f, +128.906f,37.137f,125.0f, +128.906f,37.0161f,128.906f, +132.813f,38.4113f,125.0f, +132.813f,38.5084f,128.906f, +136.719f,38.1788f,125.0f, +136.719f,39.1631f,128.906f, +140.625f,38.7652f,125.0f, +140.625f,39.0529f,128.906f, +144.531f,37.9353f,125.0f, +144.531f,38.9229f,128.906f, +148.438f,38.5681f,125.0f, +148.438f,38.4312f,128.906f, +152.344f,38.6243f,125.0f, +152.344f,39.1086f,128.906f, +156.25f,39.6341f,125.0f, +156.25f,39.7022f,128.906f, +160.156f,39.762f,125.0f, +160.156f,39.3007f,128.906f, +164.063f,38.5385f,125.0f, +164.063f,38.2318f,128.906f, +167.969f,36.3551f,125.0f, +167.969f,36.7493f,128.906f, +171.875f,36.1936f,125.0f, +171.875f,35.9781f,128.906f, +175.781f,35.5636f,125.0f, +175.781f,35.7712f,128.906f, +179.688f,34.6544f,125.0f, +179.688f,35.6247f,128.906f, +183.594f,34.1597f,125.0f, +183.594f,35.4808f,128.906f, +187.5f,33.5567f,125.0f, +187.5f,35.6102f,128.906f, +191.406f,33.0138f,125.0f, +191.406f,34.0305f,128.906f, +195.313f,31.2722f,125.0f, +195.313f,32.0227f,128.906f, +199.219f,29.2529f,125.0f, +199.219f,29.7666f,128.906f, +203.125f,26.9435f,125.0f, +203.125f,27.3968f,128.906f, +207.031f,25.0844f,125.0f, +207.031f,25.1642f,128.906f, +210.938f,23.6605f,125.0f, +210.938f,24.279f,128.906f, +214.844f,22.0745f,125.0f, +214.844f,22.4357f,128.906f, +218.75f,20.3206f,125.0f, +218.75f,21.7754f,128.906f, +222.656f,20.0402f,125.0f, +222.656f,19.6381f,128.906f, +226.563f,20.1162f,125.0f, +226.563f,19.78f,128.906f, +230.469f,20.2399f,125.0f, +230.469f,20.0349f,128.906f, +234.375f,19.6142f,125.0f, +234.375f,19.1534f,128.906f, +238.281f,18.6118f,125.0f, +238.281f,17.863f,128.906f, +242.188f,17.3711f,125.0f, +242.188f,17.658f,128.906f, +246.094f,17.675f,125.0f, +246.094f,16.951f,128.906f, +250.0f,17.3999f,125.0f, +250.0f,16.2961f,128.906f, +3.90625f,18.5327f,121.094f, +7.8125f,19.7267f,121.094f, +11.7188f,20.9891f,121.094f, +15.625f,22.237f,121.094f, +19.5313f,22.3238f,121.094f, +23.4375f,20.1525f,121.094f, +27.3438f,17.9536f,121.094f, +31.25f,17.647f,121.094f, +35.1563f,16.241f,121.094f, +39.0625f,14.6821f,121.094f, +42.9688f,14.4948f,121.094f, +46.875f,15.0351f,121.094f, +50.7813f,15.3893f,121.094f, +54.6875f,15.1531f,121.094f, +58.5938f,14.9284f,121.094f, +62.5f,15.1197f,121.094f, +66.4063f,15.1561f,121.094f, +70.3125f,15.1593f,121.094f, +74.2188f,15.0707f,121.094f, +78.125f,16.0455f,121.094f, +82.0313f,16.6186f,121.094f, +85.9375f,17.4149f,121.094f, +89.8438f,18.746f,121.094f, +93.75f,18.8475f,121.094f, +97.6563f,21.6899f,121.094f, +101.563f,24.567f,121.094f, +105.469f,25.7581f,121.094f, +109.375f,27.437f,121.094f, +113.281f,29.1226f,121.094f, +117.188f,30.137f,121.094f, +121.094f,32.1062f,121.094f, +125.0f,34.674f,121.094f, +128.906f,37.1044f,121.094f, +132.813f,37.8111f,121.094f, +136.719f,37.7901f,121.094f, +140.625f,37.5727f,121.094f, +144.531f,37.1561f,121.094f, +148.438f,38.1976f,121.094f, +152.344f,38.9227f,121.094f, +156.25f,40.3124f,121.094f, +160.156f,40.6867f,121.094f, +164.063f,39.5374f,121.094f, +167.969f,38.019f,121.094f, +171.875f,36.4573f,121.094f, +175.781f,35.2509f,121.094f, +179.688f,34.6709f,121.094f, +183.594f,33.5584f,121.094f, +187.5f,33.2411f,121.094f, +191.406f,31.7588f,121.094f, +195.313f,30.3558f,121.094f, +199.219f,28.879f,121.094f, +203.125f,26.7589f,121.094f, +207.031f,25.0535f,121.094f, +210.938f,23.0477f,121.094f, +214.844f,20.6897f,121.094f, +218.75f,19.3676f,121.094f, +222.656f,19.2985f,121.094f, +226.563f,20.2312f,121.094f, +230.469f,20.317f,121.094f, +234.375f,20.2468f,121.094f, +238.281f,20.3734f,121.094f, +242.188f,18.3676f,121.094f, +246.094f,16.642f,121.094f, +250.0f,17.5995f,121.094f, +3.90625f,18.919f,117.188f, +7.8125f,19.2124f,117.188f, +11.7188f,20.7659f,117.188f, +15.625f,20.5809f,117.188f, +19.5313f,20.3134f,117.188f, +23.4375f,18.6669f,117.188f, +27.3438f,17.5145f,117.188f, +31.25f,17.0813f,117.188f, +35.1563f,15.6789f,117.188f, +39.0625f,14.7581f,117.188f, +42.9688f,14.4424f,117.188f, +46.875f,14.7991f,117.188f, +50.7813f,15.0726f,117.188f, +54.6875f,14.8056f,117.188f, +58.5938f,15.756f,117.188f, +62.5f,16.3024f,117.188f, +66.4063f,16.0449f,117.188f, +70.3125f,15.9115f,117.188f, +74.2188f,16.1633f,117.188f, +78.125f,17.3323f,117.188f, +82.0313f,17.2659f,117.188f, +85.9375f,17.987f,117.188f, +89.8438f,18.3044f,117.188f, +93.75f,18.2665f,117.188f, +97.6563f,19.5364f,117.188f, +101.563f,21.7536f,117.188f, +105.469f,23.6545f,117.188f, +109.375f,25.5212f,117.188f, +113.281f,28.1179f,117.188f, +117.188f,29.5931f,117.188f, +121.094f,31.8126f,117.188f, +125.0f,34.0227f,117.188f, +128.906f,36.3895f,117.188f, +132.813f,37.0423f,117.188f, +136.719f,36.8278f,117.188f, +140.625f,36.2349f,117.188f, +144.531f,36.8825f,117.188f, +148.438f,39.6492f,117.188f, +152.344f,41.6626f,117.188f, +156.25f,42.5091f,117.188f, +160.156f,43.0711f,117.188f, +164.063f,41.7733f,117.188f, +167.969f,40.5985f,117.188f, +171.875f,38.1852f,117.188f, +175.781f,37.023f,117.188f, +179.688f,35.8533f,117.188f, +183.594f,34.5754f,117.188f, +187.5f,33.6585f,117.188f, +191.406f,32.534f,117.188f, +195.313f,31.0632f,117.188f, +199.219f,29.0243f,117.188f, +203.125f,27.0248f,117.188f, +207.031f,25.1597f,117.188f, +210.938f,22.6282f,117.188f, +214.844f,20.6205f,117.188f, +218.75f,19.2556f,117.188f, +222.656f,18.8259f,117.188f, +226.563f,19.2235f,117.188f, +230.469f,20.4441f,117.188f, +234.375f,20.5373f,117.188f, +238.281f,20.3082f,117.188f, +242.188f,19.4397f,117.188f, +246.094f,17.9806f,117.188f, +250.0f,17.3395f,117.188f, +3.90625f,18.3498f,113.281f, +7.8125f,18.7009f,113.281f, +11.7188f,19.3704f,113.281f, +15.625f,19.5203f,113.281f, +19.5313f,18.5704f,113.281f, +23.4375f,17.6697f,113.281f, +27.3438f,16.8001f,113.281f, +31.25f,16.54f,113.281f, +35.1563f,15.8558f,113.281f, +39.0625f,15.1296f,113.281f, +42.9688f,15.8599f,113.281f, +46.875f,16.437f,113.281f, +50.7813f,16.2977f,113.281f, +54.6875f,16.7076f,113.281f, +58.5938f,16.8187f,113.281f, +62.5f,17.1513f,113.281f, +66.4063f,16.5296f,113.281f, +70.3125f,15.8782f,113.281f, +74.2188f,16.614f,113.281f, +78.125f,17.0474f,113.281f, +82.0313f,17.3371f,113.281f, +85.9375f,17.9565f,113.281f, +89.8438f,18.3918f,113.281f, +93.75f,19.0258f,113.281f, +97.6563f,19.2791f,113.281f, +101.563f,20.1533f,113.281f, +105.469f,22.2922f,113.281f, +109.375f,24.6835f,113.281f, +113.281f,25.7755f,113.281f, +117.188f,28.8805f,113.281f, +121.094f,31.2119f,113.281f, +125.0f,33.4657f,113.281f, +128.906f,35.1055f,113.281f, +132.813f,36.4197f,113.281f, +136.719f,37.3017f,113.281f, +140.625f,37.1796f,113.281f, +144.531f,38.2037f,113.281f, +148.438f,41.4383f,113.281f, +152.344f,43.9714f,113.281f, +156.25f,45.0067f,113.281f, +160.156f,45.1491f,113.281f, +164.063f,43.8042f,113.281f, +167.969f,42.5165f,113.281f, +171.875f,40.361f,113.281f, +175.781f,38.3494f,113.281f, +179.688f,37.4529f,113.281f, +183.594f,35.5766f,113.281f, +187.5f,34.2438f,113.281f, +191.406f,32.0218f,113.281f, +195.313f,30.2021f,113.281f, +199.219f,28.8256f,113.281f, +203.125f,27.2081f,113.281f, +207.031f,24.992f,113.281f, +210.938f,22.5332f,113.281f, +214.844f,19.7765f,113.281f, +218.75f,18.5573f,113.281f, +222.656f,18.1469f,113.281f, +226.563f,17.9659f,113.281f, +230.469f,19.2f,113.281f, +234.375f,20.0741f,113.281f, +238.281f,20.1159f,113.281f, +242.188f,19.0382f,113.281f, +246.094f,18.3417f,113.281f, +250.0f,18.7603f,113.281f, +3.90625f,18.0017f,109.375f, +7.8125f,18.1552f,109.375f, +11.7188f,18.2026f,109.375f, +15.625f,18.2042f,109.375f, +19.5313f,17.7806f,109.375f, +23.4375f,17.5378f,109.375f, +27.3438f,16.8627f,109.375f, +31.25f,15.9329f,109.375f, +35.1563f,15.192f,109.375f, +39.0625f,16.0796f,109.375f, +42.9688f,16.1895f,109.375f, +46.875f,15.9774f,109.375f, +50.7813f,16.9529f,109.375f, +54.6875f,17.0901f,109.375f, +58.5938f,17.3722f,109.375f, +62.5f,16.5809f,109.375f, +66.4063f,16.8111f,109.375f, +70.3125f,16.9238f,109.375f, +74.2188f,16.8422f,109.375f, +78.125f,17.0401f,109.375f, +82.0313f,16.8637f,109.375f, +85.9375f,17.4071f,109.375f, +89.8438f,17.944f,109.375f, +93.75f,18.5255f,109.375f, +97.6563f,18.2829f,109.375f, +101.563f,19.0975f,109.375f, +105.469f,20.4292f,109.375f, +109.375f,22.163f,109.375f, +113.281f,25.6773f,109.375f, +117.188f,27.8617f,109.375f, +121.094f,30.6543f,109.375f, +125.0f,33.4226f,109.375f, +128.906f,34.4263f,109.375f, +132.813f,36.8747f,109.375f, +136.719f,37.4551f,109.375f, +140.625f,37.4975f,109.375f, +144.531f,40.0751f,109.375f, +148.438f,42.7524f,109.375f, +152.344f,44.7756f,109.375f, +156.25f,46.1787f,109.375f, +160.156f,46.3753f,109.375f, +164.063f,45.2089f,109.375f, +167.969f,43.7487f,109.375f, +171.875f,41.6365f,109.375f, +175.781f,39.7459f,109.375f, +179.688f,36.9804f,109.375f, +183.594f,35.6688f,109.375f, +187.5f,35.0212f,109.375f, +191.406f,32.4383f,109.375f, +195.313f,29.6046f,109.375f, +199.219f,28.1822f,109.375f, +203.125f,26.2444f,109.375f, +207.031f,24.1442f,109.375f, +210.938f,22.1072f,109.375f, +214.844f,20.0401f,109.375f, +218.75f,18.0663f,109.375f, +222.656f,16.866f,109.375f, +226.563f,16.9372f,109.375f, +230.469f,16.9853f,109.375f, +234.375f,17.6761f,109.375f, +238.281f,18.3669f,109.375f, +242.188f,18.4156f,109.375f, +246.094f,18.2171f,109.375f, +250.0f,18.5941f,109.375f, +3.90625f,17.9608f,105.469f, +7.8125f,18.4369f,105.469f, +11.7188f,18.4406f,105.469f, +15.625f,17.8685f,105.469f, +19.5313f,17.7519f,105.469f, +23.4375f,17.5734f,105.469f, +27.3438f,16.3397f,105.469f, +31.25f,15.8618f,105.469f, +35.1563f,16.1194f,105.469f, +39.0625f,16.889f,105.469f, +42.9688f,16.2804f,105.469f, +46.875f,15.8474f,105.469f, +50.7813f,16.2892f,105.469f, +54.6875f,16.2854f,105.469f, +58.5938f,16.7368f,105.469f, +62.5f,17.4055f,105.469f, +66.4063f,16.8808f,105.469f, +70.3125f,17.3183f,105.469f, +74.2188f,17.7166f,105.469f, +78.125f,17.0657f,105.469f, +82.0313f,16.7305f,105.469f, +85.9375f,16.3929f,105.469f, +89.8438f,16.6475f,105.469f, +93.75f,17.7645f,105.469f, +97.6563f,18.4212f,105.469f, +101.563f,18.4107f,105.469f, +105.469f,19.3751f,105.469f, +109.375f,21.843f,105.469f, +113.281f,25.0143f,105.469f, +117.188f,26.9168f,105.469f, +121.094f,29.8403f,105.469f, +125.0f,32.4937f,105.469f, +128.906f,34.4076f,105.469f, +132.813f,35.2497f,105.469f, +136.719f,36.4785f,105.469f, +140.625f,37.7983f,105.469f, +144.531f,40.5712f,105.469f, +148.438f,43.3698f,105.469f, +152.344f,45.784f,105.469f, +156.25f,46.9835f,105.469f, +160.156f,47.2774f,105.469f, +164.063f,46.7695f,105.469f, +167.969f,45.0199f,105.469f, +171.875f,42.588f,105.469f, +175.781f,39.988f,105.469f, +179.688f,38.0653f,105.469f, +183.594f,37.5754f,105.469f, +187.5f,35.6316f,105.469f, +191.406f,32.4143f,105.469f, +195.313f,29.5342f,105.469f, +199.219f,27.2795f,105.469f, +203.125f,26.065f,105.469f, +207.031f,24.8633f,105.469f, +210.938f,23.0216f,105.469f, +214.844f,21.1684f,105.469f, +218.75f,18.9315f,105.469f, +222.656f,17.7013f,105.469f, +226.563f,16.9466f,105.469f, +230.469f,17.1437f,105.469f, +234.375f,17.6691f,105.469f, +238.281f,17.9243f,105.469f, +242.188f,18.0005f,105.469f, +246.094f,18.6179f,105.469f, +250.0f,19.2165f,105.469f, +3.90625f,17.7074f,101.563f, +7.8125f,18.411f,101.563f, +11.7188f,17.9916f,101.563f, +15.625f,18.5349f,101.563f, +19.5313f,18.6607f,101.563f, +23.4375f,17.406f,101.563f, +27.3438f,17.2356f,101.563f, +31.25f,17.0395f,101.563f, +35.1563f,17.9903f,101.563f, +39.0625f,18.2603f,101.563f, +42.9688f,17.9037f,101.563f, +46.875f,17.2358f,101.563f, +50.7813f,16.1089f,101.563f, +54.6875f,16.6043f,101.563f, +58.5938f,16.5656f,101.563f, +62.5f,16.8655f,101.563f, +66.4063f,17.0123f,101.563f, +70.3125f,17.4985f,101.563f, +74.2188f,18.0195f,101.563f, +78.125f,17.3417f,101.563f, +82.0313f,16.8477f,101.563f, +85.9375f,15.4602f,101.563f, +89.8438f,15.6001f,101.563f, +93.75f,16.8889f,101.563f, +97.6563f,17.2944f,101.563f, +101.563f,17.3431f,101.563f, +105.469f,18.2306f,101.563f, +109.375f,20.5556f,101.563f, +113.281f,22.5598f,101.563f, +117.188f,25.0997f,101.563f, +121.094f,28.2048f,101.563f, +125.0f,30.46f,101.563f, +128.906f,32.5729f,101.563f, +132.813f,34.5568f,101.563f, +136.719f,36.463f,101.563f, +140.625f,37.8259f,101.563f, +144.531f,40.4357f,101.563f, +148.438f,43.6544f,101.563f, +152.344f,46.204f,101.563f, +156.25f,47.3874f,101.563f, +160.156f,47.5222f,101.563f, +164.063f,46.8312f,101.563f, +167.969f,44.5065f,101.563f, +171.875f,43.7648f,101.563f, +175.781f,41.9789f,101.563f, +179.688f,40.785f,101.563f, +183.594f,38.7639f,101.563f, +187.5f,36.1589f,101.563f, +191.406f,33.4197f,101.563f, +195.313f,29.7568f,101.563f, +199.219f,27.2343f,101.563f, +203.125f,26.3845f,101.563f, +207.031f,25.3149f,101.563f, +210.938f,23.4896f,101.563f, +214.844f,22.229f,101.563f, +218.75f,20.0014f,101.563f, +222.656f,19.0955f,101.563f, +226.563f,17.971f,101.563f, +230.469f,16.9303f,101.563f, +234.375f,17.3619f,101.563f, +238.281f,17.0337f,101.563f, +242.188f,17.1424f,101.563f, +246.094f,18.334f,101.563f, +250.0f,19.2744f,101.563f, +3.90625f,18.0176f,97.6563f, +7.8125f,18.1916f,97.6563f, +11.7188f,17.72f,97.6563f, +15.625f,18.3444f,97.6563f, +19.5313f,18.7102f,97.6563f, +23.4375f,17.4143f,97.6563f, +27.3438f,18.0085f,97.6563f, +31.25f,18.4924f,97.6563f, +35.1563f,19.4324f,97.6563f, +39.0625f,19.7998f,97.6563f, +42.9688f,19.5444f,97.6563f, +46.875f,19.5513f,97.6563f, +50.7813f,17.9397f,97.6563f, +54.6875f,16.6383f,97.6563f, +58.5938f,16.0619f,97.6563f, +62.5f,16.7402f,97.6563f, +66.4063f,16.955f,97.6563f, +70.3125f,17.5912f,97.6563f, +74.2188f,17.1181f,97.6563f, +78.125f,16.9063f,97.6563f, +82.0313f,16.3988f,97.6563f, +85.9375f,15.935f,97.6563f, +89.8438f,16.0664f,97.6563f, +93.75f,16.1926f,97.6563f, +97.6563f,16.5004f,97.6563f, +101.563f,17.1185f,97.6563f, +105.469f,17.2859f,97.6563f, +109.375f,19.0026f,97.6563f, +113.281f,21.0018f,97.6563f, +117.188f,23.6336f,97.6563f, +121.094f,26.4831f,97.6563f, +125.0f,29.3075f,97.6563f, +128.906f,32.5702f,97.6563f, +132.813f,34.5711f,97.6563f, +136.719f,36.1666f,97.6563f, +140.625f,37.5909f,97.6563f, +144.531f,40.3232f,97.6563f, +148.438f,42.661f,97.6563f, +152.344f,45.5604f,97.6563f, +156.25f,47.6984f,97.6563f, +160.156f,47.4129f,97.6563f, +164.063f,47.1564f,97.6563f, +167.969f,45.3058f,97.6563f, +171.875f,44.8069f,97.6563f, +175.781f,43.6847f,97.6563f, +179.688f,41.6831f,97.6563f, +183.594f,39.4072f,97.6563f, +187.5f,36.6118f,97.6563f, +191.406f,33.396f,97.6563f, +195.313f,29.9372f,97.6563f, +199.219f,28.0616f,97.6563f, +203.125f,27.3957f,97.6563f, +207.031f,25.6934f,97.6563f, +210.938f,24.4412f,97.6563f, +214.844f,23.2356f,97.6563f, +218.75f,21.445f,97.6563f, +222.656f,19.5412f,97.6563f, +226.563f,18.4898f,97.6563f, +230.469f,17.727f,97.6563f, +234.375f,16.5139f,97.6563f, +238.281f,16.2579f,97.6563f, +242.188f,16.1539f,97.6563f, +246.094f,17.0856f,97.6563f, +250.0f,18.5151f,97.6563f, +3.90625f,17.1671f,93.75f, +7.8125f,16.817f,93.75f, +11.7188f,17.5293f,93.75f, +15.625f,18.7701f,93.75f, +19.5313f,18.3362f,93.75f, +23.4375f,19.0869f,93.75f, +27.3438f,19.7557f,93.75f, +31.25f,20.0113f,93.75f, +35.1563f,20.3441f,93.75f, +39.0625f,21.4434f,93.75f, +42.9688f,21.6008f,93.75f, +46.875f,21.5423f,93.75f, +50.7813f,20.7592f,93.75f, +54.6875f,18.9207f,93.75f, +58.5938f,17.6772f,93.75f, +62.5f,17.5409f,93.75f, +66.4063f,17.599f,93.75f, +70.3125f,18.2626f,93.75f, +74.2188f,18.4046f,93.75f, +78.125f,18.215f,93.75f, +82.0313f,18.4743f,93.75f, +85.9375f,17.6579f,93.75f, +89.8438f,17.732f,93.75f, +93.75f,18.4172f,93.75f, +97.6563f,19.0439f,93.75f, +101.563f,19.7437f,93.75f, +105.469f,19.8588f,93.75f, +109.375f,19.7414f,93.75f, +113.281f,21.4756f,93.75f, +117.188f,24.1862f,93.75f, +121.094f,26.8351f,93.75f, +125.0f,29.9621f,93.75f, +128.906f,32.8267f,93.75f, +132.813f,34.6779f,93.75f, +136.719f,36.0083f,93.75f, +140.625f,36.9812f,93.75f, +144.531f,39.6087f,93.75f, +148.438f,42.2269f,93.75f, +152.344f,44.492f,93.75f, +156.25f,47.1767f,93.75f, +160.156f,47.5667f,93.75f, +164.063f,46.9625f,93.75f, +167.969f,45.6865f,93.75f, +171.875f,45.7668f,93.75f, +175.781f,44.8303f,93.75f, +179.688f,42.5904f,93.75f, +183.594f,40.3536f,93.75f, +187.5f,37.9498f,93.75f, +191.406f,35.1415f,93.75f, +195.313f,31.5011f,93.75f, +199.219f,29.695f,93.75f, +203.125f,27.7988f,93.75f, +207.031f,26.3522f,93.75f, +210.938f,25.8544f,93.75f, +214.844f,24.7269f,93.75f, +218.75f,23.7697f,93.75f, +222.656f,20.9249f,93.75f, +226.563f,19.1368f,93.75f, +230.469f,18.5704f,93.75f, +234.375f,17.554f,93.75f, +238.281f,14.9004f,93.75f, +242.188f,16.3253f,93.75f, +246.094f,16.0037f,93.75f, +250.0f,15.9921f,93.75f, +3.90625f,15.6427f,89.8438f, +7.8125f,16.2722f,89.8438f, +11.7188f,17.6471f,89.8438f, +15.625f,18.8565f,89.8438f, +19.5313f,19.651f,89.8438f, +23.4375f,20.9243f,89.8438f, +27.3438f,20.8045f,89.8438f, +31.25f,20.2274f,89.8438f, +35.1563f,21.5768f,89.8438f, +39.0625f,22.566f,89.8438f, +42.9688f,23.4111f,89.8438f, +46.875f,23.5063f,89.8438f, +50.7813f,22.9631f,89.8438f, +54.6875f,21.5642f,89.8438f, +58.5938f,20.3649f,89.8438f, +62.5f,19.6177f,89.8438f, +66.4063f,18.6758f,89.8438f, +70.3125f,18.6837f,89.8438f, +74.2188f,19.7593f,89.8438f, +78.125f,20.4356f,89.8438f, +82.0313f,20.1806f,89.8438f, +85.9375f,19.4513f,89.8438f, +89.8438f,19.2942f,89.8438f, +93.75f,19.9864f,89.8438f, +97.6563f,20.6569f,89.8438f, +101.563f,20.8985f,89.8438f, +105.469f,20.8027f,89.8438f, +109.375f,21.5099f,89.8438f, +113.281f,22.7491f,89.8438f, +117.188f,24.1938f,89.8438f, +121.094f,27.3472f,89.8438f, +125.0f,29.9546f,89.8438f, +128.906f,32.3821f,89.8438f, +132.813f,34.2078f,89.8438f, +136.719f,35.7419f,89.8438f, +140.625f,36.6408f,89.8438f, +144.531f,39.1756f,89.8438f, +148.438f,42.1721f,89.8438f, +152.344f,43.7891f,89.8438f, +156.25f,45.9566f,89.8438f, +160.156f,47.5521f,89.8438f, +164.063f,47.0165f,89.8438f, +167.969f,46.0084f,89.8438f, +171.875f,46.0374f,89.8438f, +175.781f,45.9301f,89.8438f, +179.688f,43.5326f,89.8438f, +183.594f,40.5203f,89.8438f, +187.5f,38.133f,89.8438f, +191.406f,35.8688f,89.8438f, +195.313f,33.0648f,89.8438f, +199.219f,31.0451f,89.8438f, +203.125f,27.691f,89.8438f, +207.031f,26.7927f,89.8438f, +210.938f,26.334f,89.8438f, +214.844f,25.0669f,89.8438f, +218.75f,23.4149f,89.8438f, +222.656f,20.9786f,89.8438f, +226.563f,18.963f,89.8438f, +230.469f,18.7894f,89.8438f, +234.375f,17.2683f,89.8438f, +238.281f,14.98f,89.8438f, +242.188f,15.4163f,89.8438f, +246.094f,15.4238f,89.8438f, +250.0f,15.9208f,89.8438f, +3.90625f,15.5916f,85.9375f, +7.8125f,16.3916f,85.9375f, +11.7188f,18.2047f,85.9375f, +15.625f,19.1861f,85.9375f, +19.5313f,20.7525f,85.9375f, +23.4375f,21.6364f,85.9375f, +27.3438f,21.9262f,85.9375f, +31.25f,21.6225f,85.9375f, +35.1563f,22.4806f,85.9375f, +39.0625f,23.7973f,85.9375f, +42.9688f,24.6135f,85.9375f, +46.875f,24.8421f,85.9375f, +50.7813f,24.5451f,85.9375f, +54.6875f,23.688f,85.9375f, +58.5938f,22.221f,85.9375f, +62.5f,21.5009f,85.9375f, +66.4063f,21.2241f,85.9375f, +70.3125f,20.2058f,85.9375f, +74.2188f,20.3437f,85.9375f, +78.125f,21.8786f,85.9375f, +82.0313f,21.9425f,85.9375f, +85.9375f,20.6496f,85.9375f, +89.8438f,20.6855f,85.9375f, +93.75f,20.6495f,85.9375f, +97.6563f,21.0738f,85.9375f, +101.563f,21.7991f,85.9375f, +105.469f,22.3795f,85.9375f, +109.375f,22.4292f,85.9375f, +113.281f,23.6451f,85.9375f, +117.188f,24.8457f,85.9375f, +121.094f,26.7121f,85.9375f, +125.0f,29.2236f,85.9375f, +128.906f,31.5942f,85.9375f, +132.813f,33.8517f,85.9375f, +136.719f,35.7145f,85.9375f, +140.625f,36.6808f,85.9375f, +144.531f,38.8926f,85.9375f, +148.438f,41.6484f,85.9375f, +152.344f,44.2035f,85.9375f, +156.25f,45.1997f,85.9375f, +160.156f,46.1921f,85.9375f, +164.063f,47.2097f,85.9375f, +167.969f,47.0691f,85.9375f, +171.875f,45.5257f,85.9375f, +175.781f,44.6746f,85.9375f, +179.688f,43.6223f,85.9375f, +183.594f,40.2395f,85.9375f, +187.5f,38.445f,85.9375f, +191.406f,36.5002f,85.9375f, +195.313f,33.7977f,85.9375f, +199.219f,31.5943f,85.9375f, +203.125f,28.8305f,85.9375f, +207.031f,27.4922f,85.9375f, +210.938f,26.0386f,85.9375f, +214.844f,24.1792f,85.9375f, +218.75f,22.1567f,85.9375f, +222.656f,20.1169f,85.9375f, +226.563f,19.3603f,85.9375f, +230.469f,17.7703f,85.9375f, +234.375f,16.3147f,85.9375f, +238.281f,15.0886f,85.9375f, +242.188f,15.1332f,85.9375f, +246.094f,14.7802f,85.9375f, +250.0f,15.2259f,85.9375f, +3.90625f,16.9644f,82.0313f, +7.8125f,17.8f,82.0313f, +11.7188f,19.2943f,82.0313f, +15.625f,21.0269f,82.0313f, +19.5313f,22.3312f,82.0313f, +23.4375f,23.0871f,82.0313f, +27.3438f,23.1115f,82.0313f, +31.25f,23.5304f,82.0313f, +35.1563f,24.1493f,82.0313f, +39.0625f,25.0848f,82.0313f, +42.9688f,26.0789f,82.0313f, +46.875f,26.3399f,82.0313f, +50.7813f,25.4397f,82.0313f, +54.6875f,24.894f,82.0313f, +58.5938f,24.1026f,82.0313f, +62.5f,24.0749f,82.0313f, +66.4063f,23.5256f,82.0313f, +70.3125f,21.9612f,82.0313f, +74.2188f,21.932f,82.0313f, +78.125f,22.6241f,82.0313f, +82.0313f,22.672f,82.0313f, +85.9375f,21.4303f,82.0313f, +89.8438f,21.6964f,82.0313f, +93.75f,21.7198f,82.0313f, +97.6563f,22.4953f,82.0313f, +101.563f,23.0451f,82.0313f, +105.469f,23.0285f,82.0313f, +109.375f,23.24f,82.0313f, +113.281f,23.6861f,82.0313f, +117.188f,24.7685f,82.0313f, +121.094f,26.4466f,82.0313f, +125.0f,28.8315f,82.0313f, +128.906f,30.9624f,82.0313f, +132.813f,33.7991f,82.0313f, +136.719f,35.8079f,82.0313f, +140.625f,37.0254f,82.0313f, +144.531f,38.7479f,82.0313f, +148.438f,42.0473f,82.0313f, +152.344f,43.7879f,82.0313f, +156.25f,45.1826f,82.0313f, +160.156f,46.2454f,82.0313f, +164.063f,47.0196f,82.0313f, +167.969f,47.2872f,82.0313f, +171.875f,46.2496f,82.0313f, +175.781f,44.3338f,82.0313f, +179.688f,43.1095f,82.0313f, +183.594f,40.7857f,82.0313f, +187.5f,39.646f,82.0313f, +191.406f,37.5425f,82.0313f, +195.313f,35.2951f,82.0313f, +199.219f,33.6324f,82.0313f, +203.125f,30.8911f,82.0313f, +207.031f,27.2798f,82.0313f, +210.938f,25.4308f,82.0313f, +214.844f,23.8814f,82.0313f, +218.75f,22.4441f,82.0313f, +222.656f,20.3771f,82.0313f, +226.563f,19.2073f,82.0313f, +230.469f,19.0082f,82.0313f, +234.375f,17.769f,82.0313f, +238.281f,15.8302f,82.0313f, +242.188f,14.2967f,82.0313f, +246.094f,15.1365f,82.0313f, +250.0f,14.9159f,82.0313f, +3.90625f,18.8244f,78.125f, +7.8125f,19.5283f,78.125f, +11.7188f,20.9466f,78.125f, +15.625f,22.0951f,78.125f, +19.5313f,23.2483f,78.125f, +23.4375f,23.8238f,78.125f, +27.3438f,24.6236f,78.125f, +31.25f,24.0856f,78.125f, +35.1563f,25.6129f,78.125f, +39.0625f,26.8525f,78.125f, +42.9688f,26.9859f,78.125f, +46.875f,26.6403f,78.125f, +50.7813f,26.6419f,78.125f, +54.6875f,27.4236f,78.125f, +58.5938f,26.5989f,78.125f, +62.5f,26.137f,78.125f, +66.4063f,24.8717f,78.125f, +70.3125f,23.8694f,78.125f, +74.2188f,23.2668f,78.125f, +78.125f,23.1081f,78.125f, +82.0313f,23.3134f,78.125f, +85.9375f,23.0903f,78.125f, +89.8438f,23.2822f,78.125f, +93.75f,24.291f,78.125f, +97.6563f,24.5546f,78.125f, +101.563f,24.4216f,78.125f, +105.469f,24.6379f,78.125f, +109.375f,24.5235f,78.125f, +113.281f,24.88f,78.125f, +117.188f,25.6988f,78.125f, +121.094f,26.9155f,78.125f, +125.0f,29.7499f,78.125f, +128.906f,31.361f,78.125f, +132.813f,33.9367f,78.125f, +136.719f,35.4066f,78.125f, +140.625f,36.6153f,78.125f, +144.531f,38.6091f,78.125f, +148.438f,41.2276f,78.125f, +152.344f,43.2187f,78.125f, +156.25f,45.2494f,78.125f, +160.156f,46.5334f,78.125f, +164.063f,47.1659f,78.125f, +167.969f,47.5409f,78.125f, +171.875f,46.3778f,78.125f, +175.781f,44.8935f,78.125f, +179.688f,43.7429f,78.125f, +183.594f,42.4748f,78.125f, +187.5f,40.5234f,78.125f, +191.406f,38.2806f,78.125f, +195.313f,36.297f,78.125f, +199.219f,35.0641f,78.125f, +203.125f,32.4145f,78.125f, +207.031f,29.4539f,78.125f, +210.938f,25.7399f,78.125f, +214.844f,23.157f,78.125f, +218.75f,20.9425f,78.125f, +222.656f,19.2349f,78.125f, +226.563f,18.5576f,78.125f, +230.469f,18.8407f,78.125f, +234.375f,17.6562f,78.125f, +238.281f,15.7207f,78.125f, +242.188f,14.3385f,78.125f, +246.094f,13.9958f,78.125f, +250.0f,14.6888f,78.125f, +3.90625f,20.6829f,74.2188f, +7.8125f,22.7393f,74.2188f, +11.7188f,22.9007f,74.2188f, +15.625f,23.3717f,74.2188f, +19.5313f,23.7991f,74.2188f, +23.4375f,24.5576f,74.2188f, +27.3438f,25.3464f,74.2188f, +31.25f,25.8349f,74.2188f, +35.1563f,26.2326f,74.2188f, +39.0625f,27.8003f,74.2188f, +42.9688f,28.502f,74.2188f, +46.875f,28.7947f,74.2188f, +50.7813f,29.109f,74.2188f, +54.6875f,29.4315f,74.2188f, +58.5938f,29.1948f,74.2188f, +62.5f,28.241f,74.2188f, +66.4063f,26.6727f,74.2188f, +70.3125f,25.5496f,74.2188f, +74.2188f,24.2265f,74.2188f, +78.125f,24.8641f,74.2188f, +82.0313f,24.8692f,74.2188f, +85.9375f,23.8066f,74.2188f, +89.8438f,24.5827f,74.2188f, +93.75f,25.5885f,74.2188f, +97.6563f,25.005f,74.2188f, +101.563f,25.4768f,74.2188f, +105.469f,25.8326f,74.2188f, +109.375f,25.8587f,74.2188f, +113.281f,26.8029f,74.2188f, +117.188f,27.8764f,74.2188f, +121.094f,28.8835f,74.2188f, +125.0f,30.0077f,74.2188f, +128.906f,31.9776f,74.2188f, +132.813f,34.2008f,74.2188f, +136.719f,35.4023f,74.2188f, +140.625f,36.3754f,74.2188f, +144.531f,38.9991f,74.2188f, +148.438f,41.295f,74.2188f, +152.344f,44.1131f,74.2188f, +156.25f,46.2221f,74.2188f, +160.156f,46.7797f,74.2188f, +164.063f,47.446f,74.2188f, +167.969f,47.1396f,74.2188f, +171.875f,45.9937f,74.2188f, +175.781f,45.4284f,74.2188f, +179.688f,45.018f,74.2188f, +183.594f,43.1233f,74.2188f, +187.5f,41.2272f,74.2188f, +191.406f,37.8072f,74.2188f, +195.313f,36.5304f,74.2188f, +199.219f,35.1638f,74.2188f, +203.125f,33.1538f,74.2188f, +207.031f,30.2207f,74.2188f, +210.938f,26.1665f,74.2188f, +214.844f,22.1619f,74.2188f, +218.75f,18.452f,74.2188f, +222.656f,17.0925f,74.2188f, +226.563f,17.3468f,74.2188f, +230.469f,16.447f,74.2188f, +234.375f,15.7197f,74.2188f, +238.281f,14.7889f,74.2188f, +242.188f,13.641f,74.2188f, +246.094f,12.7728f,74.2188f, +250.0f,13.3875f,74.2188f, +3.90625f,22.948f,70.3125f, +7.8125f,24.3431f,70.3125f, +11.7188f,24.6307f,70.3125f, +15.625f,24.9963f,70.3125f, +19.5313f,25.2034f,70.3125f, +23.4375f,25.2791f,70.3125f, +27.3438f,25.8257f,70.3125f, +31.25f,27.1123f,70.3125f, +35.1563f,27.8795f,70.3125f, +39.0625f,28.8437f,70.3125f, +42.9688f,29.8883f,70.3125f, +46.875f,30.6548f,70.3125f, +50.7813f,31.0396f,70.3125f, +54.6875f,31.6324f,70.3125f, +58.5938f,31.5222f,70.3125f, +62.5f,30.4696f,70.3125f, +66.4063f,28.7208f,70.3125f, +70.3125f,26.8611f,70.3125f, +74.2188f,25.6776f,70.3125f, +78.125f,26.1193f,70.3125f, +82.0313f,25.1971f,70.3125f, +85.9375f,24.4814f,70.3125f, +89.8438f,25.1213f,70.3125f, +93.75f,26.1411f,70.3125f, +97.6563f,26.4276f,70.3125f, +101.563f,26.0728f,70.3125f, +105.469f,26.113f,70.3125f, +109.375f,27.5702f,70.3125f, +113.281f,28.6199f,70.3125f, +117.188f,30.054f,70.3125f, +121.094f,30.255f,70.3125f, +125.0f,30.9839f,70.3125f, +128.906f,32.4045f,70.3125f, +132.813f,33.9858f,70.3125f, +136.719f,35.8568f,70.3125f, +140.625f,37.5803f,70.3125f, +144.531f,40.2984f,70.3125f, +148.438f,41.9326f,70.3125f, +152.344f,44.1607f,70.3125f, +156.25f,45.6454f,70.3125f, +160.156f,47.3567f,70.3125f, +164.063f,48.1147f,70.3125f, +167.969f,47.7671f,70.3125f, +171.875f,46.1009f,70.3125f, +175.781f,45.3829f,70.3125f, +179.688f,44.3458f,70.3125f, +183.594f,42.818f,70.3125f, +187.5f,40.5253f,70.3125f, +191.406f,37.6731f,70.3125f, +195.313f,36.7234f,70.3125f, +199.219f,35.0848f,70.3125f, +203.125f,33.0857f,70.3125f, +207.031f,30.0508f,70.3125f, +210.938f,26.741f,70.3125f, +214.844f,22.7613f,70.3125f, +218.75f,18.5375f,70.3125f, +222.656f,15.6052f,70.3125f, +226.563f,14.6945f,70.3125f, +230.469f,15.0013f,70.3125f, +234.375f,13.9965f,70.3125f, +238.281f,12.4404f,70.3125f, +242.188f,12.4448f,70.3125f, +246.094f,11.7446f,70.3125f, +250.0f,11.7886f,70.3125f, +3.90625f,25.5564f,66.4063f, +7.8125f,26.1216f,66.4063f, +11.7188f,26.234f,66.4063f, +15.625f,26.4553f,66.4063f, +19.5313f,26.9827f,66.4063f, +23.4375f,27.0173f,66.4063f, +27.3438f,27.3577f,66.4063f, +31.25f,28.895f,66.4063f, +35.1563f,30.1057f,66.4063f, +39.0625f,30.249f,66.4063f, +42.9688f,31.1394f,66.4063f, +46.875f,31.7197f,66.4063f, +50.7813f,33.2905f,66.4063f, +54.6875f,33.6208f,66.4063f, +58.5938f,33.5152f,66.4063f, +62.5f,31.5128f,66.4063f, +66.4063f,30.1049f,66.4063f, +70.3125f,28.9139f,66.4063f, +74.2188f,27.093f,66.4063f, +78.125f,26.8272f,66.4063f, +82.0313f,25.8777f,66.4063f, +85.9375f,25.2597f,66.4063f, +89.8438f,25.8742f,66.4063f, +93.75f,27.4783f,66.4063f, +97.6563f,27.1897f,66.4063f, +101.563f,26.8406f,66.4063f, +105.469f,27.2889f,66.4063f, +109.375f,28.6616f,66.4063f, +113.281f,29.2852f,66.4063f, +117.188f,30.3362f,66.4063f, +121.094f,32.0648f,66.4063f, +125.0f,32.6693f,66.4063f, +128.906f,33.7239f,66.4063f, +132.813f,34.8193f,66.4063f, +136.719f,36.6878f,66.4063f, +140.625f,38.5422f,66.4063f, +144.531f,40.5193f,66.4063f, +148.438f,42.0434f,66.4063f, +152.344f,43.692f,66.4063f, +156.25f,46.2f,66.4063f, +160.156f,47.7247f,66.4063f, +164.063f,48.3486f,66.4063f, +167.969f,48.4057f,66.4063f, +171.875f,47.4141f,66.4063f, +175.781f,45.925f,66.4063f, +179.688f,44.0772f,66.4063f, +183.594f,42.0866f,66.4063f, +187.5f,40.2687f,66.4063f, +191.406f,38.0236f,66.4063f, +195.313f,36.9223f,66.4063f, +199.219f,35.6323f,66.4063f, +203.125f,33.0001f,66.4063f, +207.031f,30.1425f,66.4063f, +210.938f,26.4551f,66.4063f, +214.844f,22.4224f,66.4063f, +218.75f,18.5557f,66.4063f, +222.656f,16.1428f,66.4063f, +226.563f,14.9942f,66.4063f, +230.469f,14.9221f,66.4063f, +234.375f,13.3816f,66.4063f, +238.281f,10.9914f,66.4063f, +242.188f,10.6094f,66.4063f, +246.094f,9.77905f,66.4063f, +250.0f,9.99853f,66.4063f, +3.90625f,27.1929f,62.5f, +7.8125f,28.1411f,62.5f, +11.7188f,27.9312f,62.5f, +15.625f,27.692f,62.5f, +19.5313f,27.8511f,62.5f, +23.4375f,28.2162f,62.5f, +27.3438f,29.5518f,62.5f, +31.25f,30.2367f,62.5f, +35.1563f,31.1075f,62.5f, +39.0625f,31.6239f,62.5f, +42.9688f,32.8498f,62.5f, +46.875f,33.1521f,62.5f, +50.7813f,34.6411f,62.5f, +54.6875f,35.0063f,62.5f, +58.5938f,33.8006f,62.5f, +62.5f,33.1029f,62.5f, +66.4063f,32.1466f,62.5f, +70.3125f,30.2614f,62.5f, +74.2188f,28.2978f,62.5f, +78.125f,28.0764f,62.5f, +82.0313f,27.2473f,62.5f, +85.9375f,26.2769f,62.5f, +89.8438f,26.2922f,62.5f, +93.75f,27.1235f,62.5f, +97.6563f,27.498f,62.5f, +101.563f,27.2257f,62.5f, +105.469f,28.2897f,62.5f, +109.375f,28.8921f,62.5f, +113.281f,30.563f,62.5f, +117.188f,32.1298f,62.5f, +121.094f,32.8639f,62.5f, +125.0f,34.6537f,62.5f, +128.906f,35.4867f,62.5f, +132.813f,36.6181f,62.5f, +136.719f,37.6418f,62.5f, +140.625f,39.2228f,62.5f, +144.531f,40.5105f,62.5f, +148.438f,42.215f,62.5f, +152.344f,43.5394f,62.5f, +156.25f,45.1171f,62.5f, +160.156f,46.6711f,62.5f, +164.063f,47.4274f,62.5f, +167.969f,47.6821f,62.5f, +171.875f,48.0762f,62.5f, +175.781f,46.4607f,62.5f, +179.688f,44.7623f,62.5f, +183.594f,42.6372f,62.5f, +187.5f,40.3231f,62.5f, +191.406f,38.4371f,62.5f, +195.313f,36.1978f,62.5f, +199.219f,35.38f,62.5f, +203.125f,32.0325f,62.5f, +207.031f,29.2047f,62.5f, +210.938f,27.481f,62.5f, +214.844f,24.0627f,62.5f, +218.75f,20.6235f,62.5f, +222.656f,18.5468f,62.5f, +226.563f,17.2736f,62.5f, +230.469f,15.4125f,62.5f, +234.375f,13.6775f,62.5f, +238.281f,11.4407f,62.5f, +242.188f,9.73154f,62.5f, +246.094f,8.55197f,62.5f, +250.0f,8.43693f,62.5f, +3.90625f,28.3495f,58.5938f, +7.8125f,28.8832f,58.5938f, +11.7188f,28.5512f,58.5938f, +15.625f,28.8533f,58.5938f, +19.5313f,29.0576f,58.5938f, +23.4375f,30.3079f,58.5938f, +27.3438f,31.3861f,58.5938f, +31.25f,33.0252f,58.5938f, +35.1563f,33.4087f,58.5938f, +39.0625f,34.3736f,58.5938f, +42.9688f,34.6944f,58.5938f, +46.875f,34.1156f,58.5938f, +50.7813f,34.7246f,58.5938f, +54.6875f,35.3934f,58.5938f, +58.5938f,34.9508f,58.5938f, +62.5f,34.469f,58.5938f, +66.4063f,33.1584f,58.5938f, +70.3125f,30.5913f,58.5938f, +74.2188f,30.4147f,58.5938f, +78.125f,30.821f,58.5938f, +82.0313f,29.9244f,58.5938f, +85.9375f,28.365f,58.5938f, +89.8438f,27.8694f,58.5938f, +93.75f,27.7517f,58.5938f, +97.6563f,27.9188f,58.5938f, +101.563f,27.7605f,58.5938f, +105.469f,28.252f,58.5938f, +109.375f,29.4592f,58.5938f, +113.281f,31.2608f,58.5938f, +117.188f,33.5373f,58.5938f, +121.094f,34.4995f,58.5938f, +125.0f,35.1593f,58.5938f, +128.906f,36.6148f,58.5938f, +132.813f,37.1425f,58.5938f, +136.719f,38.2148f,58.5938f, +140.625f,38.9964f,58.5938f, +144.531f,40.3196f,58.5938f, +148.438f,42.4959f,58.5938f, +152.344f,43.37f,58.5938f, +156.25f,44.3488f,58.5938f, +160.156f,45.6441f,58.5937f, +164.063f,45.6597f,58.5937f, +167.969f,46.9631f,58.5938f, +171.875f,47.0933f,58.5938f, +175.781f,45.839f,58.5937f, +179.688f,44.0491f,58.5937f, +183.594f,41.6462f,58.5938f, +187.5f,39.9012f,58.5938f, +191.406f,37.8373f,58.5938f, +195.313f,35.0871f,58.5938f, +199.219f,34.6045f,58.5938f, +203.125f,32.4469f,58.5938f, +207.031f,30.5103f,58.5938f, +210.938f,28.7194f,58.5938f, +214.844f,26.3358f,58.5938f, +218.75f,24.3668f,58.5938f, +222.656f,22.1719f,58.5938f, +226.563f,20.1708f,58.5938f, +230.469f,18.1384f,58.5938f, +234.375f,15.6994f,58.5938f, +238.281f,12.6124f,58.5938f, +242.188f,11.2279f,58.5938f, +246.094f,10.4938f,58.5938f, +250.0f,9.45058f,58.5938f, +3.90625f,29.2057f,54.6875f, +7.8125f,29.4161f,54.6875f, +11.7188f,29.6274f,54.6875f, +15.625f,29.8747f,54.6875f, +19.5313f,31.3353f,54.6875f, +23.4375f,32.5261f,54.6875f, +27.3438f,34.3893f,54.6875f, +31.25f,34.9525f,54.6875f, +35.1563f,35.8992f,54.6875f, +39.0625f,36.2066f,54.6875f, +42.9688f,36.4212f,54.6875f, +46.875f,36.1377f,54.6875f, +50.7813f,35.4213f,54.6875f, +54.6875f,35.5045f,54.6875f, +58.5938f,36.0891f,54.6875f, +62.5f,36.0244f,54.6875f, +66.4063f,34.9086f,54.6875f, +70.3125f,32.8671f,54.6875f, +74.2188f,33.5578f,54.6875f, +78.125f,33.8468f,54.6875f, +82.0313f,32.868f,54.6875f, +85.9375f,31.2245f,54.6875f, +89.8438f,29.442f,54.6875f, +93.75f,28.9144f,54.6875f, +97.6563f,27.6797f,54.6875f, +101.563f,27.9585f,54.6875f, +105.469f,28.5492f,54.6875f, +109.375f,29.119f,54.6875f, +113.281f,30.7234f,54.6875f, +117.188f,32.402f,54.6875f, +121.094f,34.3605f,54.6875f, +125.0f,35.6614f,54.6875f, +128.906f,37.1814f,54.6875f, +132.813f,37.8509f,54.6875f, +136.719f,38.3282f,54.6875f, +140.625f,39.021f,54.6875f, +144.531f,39.8455f,54.6875f, +148.438f,41.3547f,54.6875f, +152.344f,42.0848f,54.6875f, +156.25f,42.4546f,54.6875f, +160.156f,43.3035f,54.6875f, +164.063f,44.2757f,54.6875f, +167.969f,45.0917f,54.6875f, +171.875f,44.9479f,54.6875f, +175.781f,44.386f,54.6875f, +179.688f,43.1031f,54.6875f, +183.594f,41.5243f,54.6875f, +187.5f,39.9976f,54.6875f, +191.406f,37.1931f,54.6875f, +195.313f,35.2297f,54.6875f, +199.219f,34.439f,54.6875f, +203.125f,32.7399f,54.6875f, +207.031f,31.4766f,54.6875f, +210.938f,29.9402f,54.6875f, +214.844f,28.6752f,54.6875f, +218.75f,27.0387f,54.6875f, +222.656f,24.4777f,54.6875f, +226.563f,21.7169f,54.6875f, +230.469f,20.0299f,54.6875f, +234.375f,17.3103f,54.6875f, +238.281f,14.1891f,54.6875f, +242.188f,12.1605f,54.6875f, +246.094f,10.9065f,54.6875f, +250.0f,10.6619f,54.6875f, +3.90625f,30.4306f,50.7813f, +7.8125f,30.9679f,50.7813f, +11.7188f,31.3065f,50.7813f, +15.625f,32.0527f,50.7813f, +19.5313f,33.9185f,50.7813f, +23.4375f,34.6834f,50.7813f, +27.3438f,35.8025f,50.7813f, +31.25f,36.824f,50.7813f, +35.1563f,37.9949f,50.7813f, +39.0625f,38.2428f,50.7813f, +42.9688f,37.3912f,50.7813f, +46.875f,37.2849f,50.7813f, +50.7813f,36.4441f,50.7813f, +54.6875f,36.5986f,50.7813f, +58.5938f,36.7371f,50.7813f, +62.5f,36.6154f,50.7813f, +66.4063f,35.9475f,50.7813f, +70.3125f,35.1832f,50.7813f, +74.2188f,35.7876f,50.7813f, +78.125f,35.9086f,50.7813f, +82.0313f,35.0048f,50.7813f, +85.9375f,33.7202f,50.7813f, +89.8438f,32.6473f,50.7813f, +93.75f,30.9552f,50.7813f, +97.6563f,28.7453f,50.7813f, +101.563f,29.1526f,50.7813f, +105.469f,29.9957f,50.7813f, +109.375f,30.5544f,50.7813f, +113.281f,31.6947f,50.7813f, +117.188f,32.7584f,50.7813f, +121.094f,34.2518f,50.7813f, +125.0f,36.3694f,50.7813f, +128.906f,36.9477f,50.7813f, +132.813f,37.2918f,50.7813f, +136.719f,37.8325f,50.7813f, +140.625f,38.0845f,50.7813f, +144.531f,40.0088f,50.7813f, +148.438f,40.8219f,50.7813f, +152.344f,42.4039f,50.7813f, +156.25f,42.6086f,50.7813f, +160.156f,43.5487f,50.7813f, +164.063f,43.5328f,50.7813f, +167.969f,44.212f,50.7812f, +171.875f,43.6744f,50.7813f, +175.781f,43.198f,50.7813f, +179.688f,42.957f,50.7813f, +183.594f,41.4993f,50.7813f, +187.5f,39.5101f,50.7813f, +191.406f,38.1729f,50.7813f, +195.313f,35.4881f,50.7813f, +199.219f,34.6384f,50.7813f, +203.125f,34.1873f,50.7813f, +207.031f,32.1155f,50.7813f, +210.938f,30.912f,50.7813f, +214.844f,30.3391f,50.7813f, +218.75f,28.1256f,50.7813f, +222.656f,24.902f,50.7813f, +226.563f,22.2443f,50.7813f, +230.469f,20.9172f,50.7813f, +234.375f,18.8508f,50.7813f, +238.281f,15.9912f,50.7813f, +242.188f,12.7716f,50.7813f, +246.094f,11.6189f,50.7813f, +250.0f,12.2688f,50.7813f, +3.90625f,30.8772f,46.875f, +7.8125f,32.4754f,46.875f, +11.7188f,33.6983f,46.875f, +15.625f,35.14f,46.875f, +19.5313f,37.0369f,46.875f, +23.4375f,38.369f,46.875f, +27.3438f,38.6134f,46.875f, +31.25f,38.9784f,46.875f, +35.1563f,39.9891f,46.875f, +39.0625f,40.3197f,46.875f, +42.9688f,39.9692f,46.875f, +46.875f,39.6994f,46.875f, +50.7813f,39.4183f,46.875f, +54.6875f,38.2948f,46.875f, +58.5938f,38.32f,46.875f, +62.5f,38.621f,46.875f, +66.4063f,38.2134f,46.875f, +70.3125f,36.9577f,46.875f, +74.2188f,37.2936f,46.875f, +78.125f,37.8653f,46.875f, +82.0313f,36.9058f,46.875f, +85.9375f,36.1841f,46.875f, +89.8438f,34.8143f,46.875f, +93.75f,33.0783f,46.875f, +97.6563f,30.9854f,46.875f, +101.563f,30.934f,46.875f, +105.469f,32.108f,46.875f, +109.375f,33.0462f,46.875f, +113.281f,32.9253f,46.875f, +117.188f,33.3377f,46.875f, +121.094f,34.2153f,46.875f, +125.0f,35.0739f,46.875f, +128.906f,36.8239f,46.875f, +132.813f,37.1463f,46.875f, +136.719f,37.5409f,46.875f, +140.625f,38.8265f,46.875f, +144.531f,40.7241f,46.875f, +148.438f,40.9349f,46.875f, +152.344f,42.4491f,46.875f, +156.25f,43.9695f,46.875f, +160.156f,44.2191f,46.875f, +164.063f,44.9265f,46.875f, +167.969f,43.9423f,46.875f, +171.875f,43.273f,46.875f, +175.781f,43.2543f,46.875f, +179.688f,42.5328f,46.875f, +183.594f,41.1777f,46.875f, +187.5f,39.3553f,46.875f, +191.406f,37.8242f,46.875f, +195.313f,36.4649f,46.875f, +199.219f,35.6955f,46.875f, +203.125f,35.1878f,46.875f, +207.031f,32.9438f,46.875f, +210.938f,31.3677f,46.875f, +214.844f,30.7282f,46.875f, +218.75f,28.3328f,46.875f, +222.656f,25.0599f,46.875f, +226.563f,24.1932f,46.875f, +230.469f,22.3853f,46.875f, +234.375f,19.4896f,46.875f, +238.281f,16.8753f,46.875f, +242.188f,13.9469f,46.875f, +246.094f,13.2975f,46.875f, +250.0f,13.2524f,46.875f, +3.90625f,31.8945f,42.9688f, +7.8125f,34.0117f,42.9688f, +11.7188f,36.2441f,42.9688f, +15.625f,37.3622f,42.9688f, +19.5313f,39.5877f,42.9688f, +23.4375f,41.0994f,42.9688f, +27.3438f,42.0864f,42.9688f, +31.25f,42.0849f,42.9688f, +35.1563f,42.2038f,42.9688f, +39.0625f,43.473f,42.9688f, +42.9688f,42.7754f,42.9688f, +46.875f,42.3177f,42.9688f, +50.7813f,42.209f,42.9688f, +54.6875f,41.3095f,42.9688f, +58.5938f,40.8629f,42.9688f, +62.5f,40.4776f,42.9688f, +66.4063f,40.1396f,42.9688f, +70.3125f,39.1169f,42.9688f, +74.2188f,39.1382f,42.9688f, +78.125f,39.1421f,42.9688f, +82.0313f,38.9022f,42.9688f, +85.9375f,37.5711f,42.9688f, +89.8438f,36.7924f,42.9688f, +93.75f,34.7734f,42.9688f, +97.6563f,33.167f,42.9688f, +101.563f,32.4173f,42.9688f, +105.469f,33.0466f,42.9688f, +109.375f,33.3882f,42.9688f, +113.281f,33.7538f,42.9688f, +117.188f,33.5661f,42.9688f, +121.094f,33.9051f,42.9688f, +125.0f,34.9181f,42.9688f, +128.906f,35.2925f,42.9688f, +132.813f,37.1741f,42.9688f, +136.719f,38.0993f,42.9688f, +140.625f,38.7621f,42.9688f, +144.531f,39.712f,42.9688f, +148.438f,40.7257f,42.9688f, +152.344f,42.2465f,42.9688f, +156.25f,43.5331f,42.9688f, +160.156f,44.6745f,42.9687f, +164.063f,44.564f,42.9688f, +167.969f,44.6075f,42.9688f, +171.875f,43.2227f,42.9688f, +175.781f,42.5688f,42.9688f, +179.688f,41.9742f,42.9688f, +183.594f,40.3484f,42.9688f, +187.5f,38.9109f,42.9688f, +191.406f,37.7273f,42.9688f, +195.313f,36.5287f,42.9688f, +199.219f,35.9361f,42.9688f, +203.125f,35.1638f,42.9688f, +207.031f,33.6615f,42.9688f, +210.938f,31.2785f,42.9688f, +214.844f,30.1259f,42.9688f, +218.75f,28.6143f,42.9688f, +222.656f,26.1162f,42.9688f, +226.563f,24.2882f,42.9688f, +230.469f,22.5195f,42.9688f, +234.375f,20.1462f,42.9688f, +238.281f,17.4811f,42.9688f, +242.188f,15.2736f,42.9688f, +246.094f,13.788f,42.9688f, +250.0f,13.1723f,42.9688f, +3.90625f,34.9171f,39.0625f, +7.8125f,36.7711f,39.0625f, +11.7188f,38.5677f,39.0625f, +15.625f,40.0524f,39.0625f, +19.5313f,42.2392f,39.0625f, +23.4375f,43.2332f,39.0625f, +27.3438f,44.8254f,39.0625f, +31.25f,45.1808f,39.0625f, +35.1563f,44.9684f,39.0625f, +39.0625f,45.0647f,39.0625f, +42.9688f,45.0888f,39.0625f, +46.875f,45.5266f,39.0625f, +50.7813f,45.2542f,39.0625f, +54.6875f,44.1797f,39.0625f, +58.5938f,43.2658f,39.0625f, +62.5f,42.7568f,39.0625f, +66.4063f,42.4159f,39.0625f, +70.3125f,41.3883f,39.0625f, +74.2188f,41.1975f,39.0625f, +78.125f,41.3073f,39.0625f, +82.0313f,41.0587f,39.0625f, +85.9375f,40.0611f,39.0625f, +89.8438f,38.7299f,39.0625f, +93.75f,37.2923f,39.0625f, +97.6563f,35.7971f,39.0625f, +101.563f,35.1982f,39.0625f, +105.469f,33.6408f,39.0625f, +109.375f,33.2619f,39.0625f, +113.281f,33.8387f,39.0625f, +117.188f,34.7554f,39.0625f, +121.094f,33.8569f,39.0625f, +125.0f,34.7741f,39.0625f, +128.906f,35.7319f,39.0625f, +132.813f,36.6023f,39.0625f, +136.719f,37.7084f,39.0625f, +140.625f,38.2513f,39.0625f, +144.531f,39.1992f,39.0625f, +148.438f,40.2336f,39.0625f, +152.344f,41.0883f,39.0625f, +156.25f,42.4004f,39.0625f, +160.156f,42.8753f,39.0625f, +164.063f,43.1631f,39.0625f, +167.969f,43.6378f,39.0625f, +171.875f,43.2113f,39.0625f, +175.781f,42.5474f,39.0625f, +179.688f,41.3413f,39.0625f, +183.594f,39.4383f,39.0625f, +187.5f,38.9723f,39.0625f, +191.406f,37.3549f,39.0625f, +195.313f,35.8615f,39.0625f, +199.219f,34.9243f,39.0625f, +203.125f,34.598f,39.0625f, +207.031f,33.6592f,39.0625f, +210.938f,32.2347f,39.0625f, +214.844f,30.4117f,39.0625f, +218.75f,28.4787f,39.0625f, +222.656f,26.6538f,39.0625f, +226.563f,24.4892f,39.0625f, +230.469f,22.9637f,39.0625f, +234.375f,20.6363f,39.0625f, +238.281f,18.4584f,39.0625f, +242.188f,16.293f,39.0625f, +246.094f,13.7473f,39.0625f, +250.0f,13.2449f,39.0625f, +3.90625f,38.5427f,35.1563f, +7.8125f,39.2771f,35.1563f, +11.7188f,40.4801f,35.1563f, +15.625f,42.2714f,35.1563f, +19.5313f,44.0743f,35.1562f, +23.4375f,45.9071f,35.1562f, +27.3438f,47.4425f,35.1563f, +31.25f,47.765f,35.1563f, +35.1563f,46.8453f,35.1562f, +39.0625f,47.1161f,35.1562f, +42.9688f,46.591f,35.1563f, +46.875f,47.4064f,35.1563f, +50.7813f,47.2001f,35.1562f, +54.6875f,47.2372f,35.1562f, +58.5938f,46.9666f,35.1563f, +62.5f,45.3322f,35.1563f, +66.4063f,44.4351f,35.1562f, +70.3125f,43.869f,35.1562f, +74.2188f,43.7604f,35.1563f, +78.125f,43.6414f,35.1563f, +82.0313f,43.6044f,35.1563f, +85.9375f,41.9765f,35.1563f, +89.8438f,40.597f,35.1563f, +93.75f,38.8088f,35.1563f, +97.6563f,37.4254f,35.1563f, +101.563f,36.4869f,35.1563f, +105.469f,34.7975f,35.1563f, +109.375f,32.6051f,35.1563f, +113.281f,32.3929f,35.1563f, +117.188f,33.3906f,35.1563f, +121.094f,33.728f,35.1563f, +125.0f,33.8089f,35.1563f, +128.906f,35.2443f,35.1563f, +132.813f,35.9877f,35.1563f, +136.719f,36.3747f,35.1563f, +140.625f,37.6045f,35.1563f, +144.531f,38.3698f,35.1563f, +148.438f,39.393f,35.1563f, +152.344f,40.0115f,35.1563f, +156.25f,40.8722f,35.1563f, +160.156f,40.7302f,35.1563f, +164.063f,41.6767f,35.1563f, +167.969f,42.1719f,35.1563f, +171.875f,41.924f,35.1563f, +175.781f,40.9628f,35.1563f, +179.688f,39.3209f,35.1563f, +183.594f,37.9615f,35.1563f, +187.5f,37.2902f,35.1563f, +191.406f,36.1521f,35.1563f, +195.313f,35.5697f,35.1563f, +199.219f,35.0547f,35.1563f, +203.125f,33.8422f,35.1563f, +207.031f,33.1699f,35.1563f, +210.938f,32.4197f,35.1563f, +214.844f,31.0723f,35.1563f, +218.75f,29.1069f,35.1563f, +222.656f,26.4015f,35.1563f, +226.563f,23.6862f,35.1563f, +230.469f,22.3142f,35.1563f, +234.375f,20.9225f,35.1563f, +238.281f,18.6533f,35.1563f, +242.188f,16.5438f,35.1563f, +246.094f,14.5457f,35.1563f, +250.0f,13.5112f,35.1563f, +3.90625f,41.4381f,31.25f, +7.8125f,41.4661f,31.25f, +11.7188f,42.5211f,31.25f, +15.625f,44.1517f,31.25f, +19.5313f,45.8301f,31.25f, +23.4375f,47.3213f,31.25f, +27.3438f,49.1504f,31.25f, +31.25f,49.1313f,31.25f, +35.1563f,48.4621f,31.25f, +39.0625f,48.0866f,31.25f, +42.9688f,47.5259f,31.25f, +46.875f,48.2042f,31.25f, +50.7813f,48.2678f,31.25f, +54.6875f,48.6796f,31.25f, +58.5938f,49.1508f,31.25f, +62.5f,48.5261f,31.25f, +66.4063f,47.2699f,31.25f, +70.3125f,46.3239f,31.25f, +74.2188f,45.9053f,31.25f, +78.125f,45.2948f,31.25f, +82.0313f,45.1222f,31.25f, +85.9375f,44.1773f,31.25f, +89.8438f,42.0751f,31.25f, +93.75f,39.8181f,31.25f, +97.6563f,38.1904f,31.25f, +101.563f,36.9029f,31.25f, +105.469f,35.9897f,31.25f, +109.375f,34.1082f,31.25f, +113.281f,33.9882f,31.25f, +117.188f,33.4544f,31.25f, +121.094f,32.7435f,31.25f, +125.0f,32.2982f,31.25f, +128.906f,33.2893f,31.25f, +132.813f,34.4302f,31.25f, +136.719f,35.501f,31.25f, +140.625f,36.4162f,31.25f, +144.531f,38.0795f,31.25f, +148.438f,38.4184f,31.25f, +152.344f,38.1695f,31.25f, +156.25f,39.1334f,31.25f, +160.156f,39.8018f,31.25f, +164.063f,40.4009f,31.25f, +167.969f,40.6662f,31.25f, +171.875f,40.6389f,31.25f, +175.781f,40.0005f,31.25f, +179.688f,38.1437f,31.25f, +183.594f,36.1677f,31.25f, +187.5f,35.7553f,31.25f, +191.406f,35.2539f,31.25f, +195.313f,34.5258f,31.25f, +199.219f,33.9511f,31.25f, +203.125f,33.8209f,31.25f, +207.031f,32.5194f,31.25f, +210.938f,31.6797f,31.25f, +214.844f,30.494f,31.25f, +218.75f,28.9089f,31.25f, +222.656f,27.096f,31.25f, +226.563f,23.5752f,31.25f, +230.469f,22.5423f,31.25f, +234.375f,20.8438f,31.25f, +238.281f,18.7938f,31.25f, +242.188f,16.7022f,31.25f, +246.094f,14.6115f,31.25f, +250.0f,12.7758f,31.25f, +3.90625f,42.7334f,27.3437f, +7.8125f,43.3658f,27.3438f, +11.7188f,44.93f,27.3437f, +15.625f,46.7113f,27.3438f, +19.5313f,48.1031f,27.3437f, +23.4375f,48.7173f,27.3438f, +27.3438f,49.0875f,27.3437f, +31.25f,50.1272f,27.3438f, +35.1563f,49.1784f,27.3437f, +39.0625f,50.4569f,27.3438f, +42.9688f,49.7216f,27.3437f, +46.875f,49.0563f,27.3438f, +50.7813f,48.7494f,27.3437f, +54.6875f,49.0519f,27.3438f, +58.5938f,49.8264f,27.3437f, +62.5f,49.8194f,27.3438f, +66.4063f,48.9033f,27.3437f, +70.3125f,47.5002f,27.3438f, +74.2188f,46.7308f,27.3437f, +78.125f,45.8132f,27.3438f, +82.0313f,45.4303f,27.3437f, +85.9375f,44.4837f,27.3438f, +89.8438f,42.6706f,27.3437f, +93.75f,40.5108f,27.3438f, +97.6563f,38.4748f,27.3437f, +101.563f,38.2458f,27.3438f, +105.469f,37.8191f,27.3437f, +109.375f,37.5503f,27.3438f, +113.281f,36.4883f,27.3437f, +117.188f,35.7025f,27.3438f, +121.094f,34.3569f,27.3437f, +125.0f,34.052f,27.3438f, +128.906f,34.3166f,27.3437f, +132.813f,33.9873f,27.3438f, +136.719f,33.8326f,27.3437f, +140.625f,35.5138f,27.3438f, +144.531f,35.9847f,27.3437f, +148.438f,36.3159f,27.3438f, +152.344f,38.1026f,27.3437f, +156.25f,39.0191f,27.3438f, +160.156f,39.0705f,27.3437f, +164.063f,38.9644f,27.3438f, +167.969f,38.0972f,27.3437f, +171.875f,38.277f,27.3438f, +175.781f,37.5686f,27.3437f, +179.688f,35.9897f,27.3438f, +183.594f,34.1554f,27.3437f, +187.5f,33.9646f,27.3438f, +191.406f,33.9556f,27.3437f, +195.313f,33.7374f,27.3438f, +199.219f,33.3736f,27.3437f, +203.125f,32.1967f,27.3438f, +207.031f,32.2131f,27.3437f, +210.938f,30.4757f,27.3438f, +214.844f,29.0495f,27.3437f, +218.75f,27.539f,27.3438f, +222.656f,25.7435f,27.3437f, +226.563f,23.5358f,27.3438f, +230.469f,22.5305f,27.3437f, +234.375f,20.3466f,27.3438f, +238.281f,18.5956f,27.3438f, +242.188f,16.6554f,27.3438f, +246.094f,14.7633f,27.3438f, +250.0f,12.979f,27.3438f, +3.90625f,44.6783f,23.4375f, +7.8125f,46.1279f,23.4375f, +11.7188f,47.9921f,23.4375f, +15.625f,48.593f,23.4375f, +19.5313f,49.826f,23.4375f, +23.4375f,50.0111f,23.4375f, +27.3438f,49.773f,23.4375f, +31.25f,50.6443f,23.4375f, +35.1563f,50.242f,23.4375f, +39.0625f,51.5289f,23.4375f, +42.9688f,51.3905f,23.4375f, +46.875f,50.5543f,23.4375f, +50.7813f,49.96f,23.4375f, +54.6875f,51.029f,23.4375f, +58.5938f,50.4996f,23.4375f, +62.5f,50.0508f,23.4375f, +66.4063f,49.4463f,23.4375f, +70.3125f,48.7613f,23.4375f, +74.2188f,48.0188f,23.4375f, +78.125f,48.0992f,23.4375f, +82.0313f,47.1947f,23.4375f, +85.9375f,45.1889f,23.4375f, +89.8438f,43.9247f,23.4375f, +93.75f,41.7965f,23.4375f, +97.6563f,40.363f,23.4375f, +101.563f,40.3201f,23.4375f, +105.469f,39.2422f,23.4375f, +109.375f,38.6318f,23.4375f, +113.281f,37.9263f,23.4375f, +117.188f,37.113f,23.4375f, +121.094f,35.4884f,23.4375f, +125.0f,35.8385f,23.4375f, +128.906f,35.4941f,23.4375f, +132.813f,34.1911f,23.4375f, +136.719f,33.6791f,23.4375f, +140.625f,33.4506f,23.4375f, +144.531f,35.4822f,23.4375f, +148.438f,36.0187f,23.4375f, +152.344f,38.231f,23.4375f, +156.25f,39.1197f,23.4375f, +160.156f,38.9095f,23.4375f, +164.063f,38.1737f,23.4375f, +167.969f,36.7498f,23.4375f, +171.875f,36.6113f,23.4375f, +175.781f,35.5895f,23.4375f, +179.688f,34.7415f,23.4375f, +183.594f,32.6574f,23.4375f, +187.5f,32.5837f,23.4375f, +191.406f,32.5272f,23.4375f, +195.313f,32.3611f,23.4375f, +199.219f,31.4784f,23.4375f, +203.125f,30.8078f,23.4375f, +207.031f,29.9524f,23.4375f, +210.938f,29.9998f,23.4375f, +214.844f,28.4828f,23.4375f, +218.75f,26.6709f,23.4375f, +222.656f,24.9874f,23.4375f, +226.563f,23.0213f,23.4375f, +230.469f,21.3587f,23.4375f, +234.375f,19.0527f,23.4375f, +238.281f,18.1056f,23.4375f, +242.188f,16.7916f,23.4375f, +246.094f,14.9561f,23.4375f, +250.0f,13.0063f,23.4375f, +3.90625f,46.9055f,19.5312f, +7.8125f,48.3769f,19.5312f, +11.7188f,50.0613f,19.5312f, +15.625f,50.9962f,19.5312f, +19.5313f,51.161f,19.5312f, +23.4375f,51.7721f,19.5312f, +27.3438f,51.5823f,19.5312f, +31.25f,51.5274f,19.5312f, +35.1563f,51.5913f,19.5312f, +39.0625f,52.4399f,19.5312f, +42.9688f,52.5999f,19.5312f, +46.875f,51.9309f,19.5312f, +50.7813f,51.6062f,19.5312f, +54.6875f,50.86f,19.5312f, +58.5938f,51.1496f,19.5312f, +62.5f,50.1957f,19.5312f, +66.4063f,49.8047f,19.5312f, +70.3125f,49.1838f,19.5312f, +74.2188f,48.7276f,19.5312f, +78.125f,48.4967f,19.5312f, +82.0313f,47.4515f,19.5312f, +85.9375f,46.2594f,19.5312f, +89.8438f,44.6756f,19.5312f, +93.75f,43.0377f,19.5312f, +97.6563f,41.3508f,19.5312f, +101.563f,40.8261f,19.5312f, +105.469f,40.5524f,19.5312f, +109.375f,39.7289f,19.5312f, +113.281f,38.9437f,19.5312f, +117.188f,38.3781f,19.5312f, +121.094f,36.9618f,19.5312f, +125.0f,35.9735f,19.5312f, +128.906f,35.3887f,19.5312f, +132.813f,34.5133f,19.5312f, +136.719f,34.7253f,19.5312f, +140.625f,33.9228f,19.5312f, +144.531f,34.2826f,19.5312f, +148.438f,35.5643f,19.5312f, +152.344f,37.7492f,19.5312f, +156.25f,38.7871f,19.5312f, +160.156f,38.6036f,19.5312f, +164.063f,38.2702f,19.5312f, +167.969f,35.931f,19.5312f, +171.875f,34.8252f,19.5312f, +175.781f,33.99f,19.5312f, +179.688f,33.664f,19.5312f, +183.594f,31.6973f,19.5312f, +187.5f,31.3559f,19.5312f, +191.406f,31.3589f,19.5312f, +195.313f,30.7614f,19.5312f, +199.219f,29.2596f,19.5312f, +203.125f,28.7711f,19.5312f, +207.031f,27.9455f,19.5312f, +210.938f,28.3339f,19.5312f, +214.844f,28.3863f,19.5312f, +218.75f,27.4513f,19.5312f, +222.656f,25.0652f,19.5312f, +226.563f,23.2291f,19.5312f, +230.469f,20.8477f,19.5313f, +234.375f,19.424f,19.5313f, +238.281f,17.7051f,19.5313f, +242.188f,16.5977f,19.5313f, +246.094f,14.7851f,19.5313f, +250.0f,12.8344f,19.5313f, +3.90625f,49.2295f,15.625f, +7.8125f,50.0754f,15.625f, +11.7188f,51.5873f,15.625f, +15.625f,52.0525f,15.625f, +19.5313f,51.4269f,15.625f, +23.4375f,51.8405f,15.625f, +27.3438f,52.3327f,15.625f, +31.25f,53.011f,15.625f, +35.1563f,52.7359f,15.625f, +39.0625f,53.2852f,15.625f, +42.9688f,53.6617f,15.625f, +46.875f,52.4883f,15.625f, +50.7813f,51.9362f,15.625f, +54.6875f,50.8372f,15.625f, +58.5938f,50.1782f,15.625f, +62.5f,49.0401f,15.625f, +66.4063f,49.1011f,15.625f, +70.3125f,48.7903f,15.625f, +74.2188f,48.6124f,15.625f, +78.125f,48.1259f,15.625f, +82.0313f,47.7267f,15.625f, +85.9375f,46.9214f,15.625f, +89.8438f,45.0939f,15.625f, +93.75f,43.6563f,15.625f, +97.6563f,42.5709f,15.625f, +101.563f,41.9572f,15.625f, +105.469f,40.973f,15.625f, +109.375f,40.7682f,15.625f, +113.281f,39.3641f,15.625f, +117.188f,39.2768f,15.625f, +121.094f,37.5977f,15.625f, +125.0f,36.0608f,15.625f, +128.906f,36.045f,15.625f, +132.813f,35.1379f,15.625f, +136.719f,34.9875f,15.625f, +140.625f,34.0482f,15.625f, +144.531f,33.8104f,15.625f, +148.438f,34.9994f,15.625f, +152.344f,36.2664f,15.625f, +156.25f,37.7694f,15.625f, +160.156f,37.6584f,15.625f, +164.063f,36.9226f,15.625f, +167.969f,34.7519f,15.625f, +171.875f,33.2827f,15.625f, +175.781f,32.8949f,15.625f, +179.688f,32.1339f,15.625f, +183.594f,30.407f,15.625f, +187.5f,28.996f,15.625f, +191.406f,29.3357f,15.625f, +195.313f,29.1098f,15.625f, +199.219f,27.8354f,15.625f, +203.125f,26.4739f,15.625f, +207.031f,26.1829f,15.625f, +210.938f,27.387f,15.625f, +214.844f,27.4944f,15.625f, +218.75f,26.4893f,15.625f, +222.656f,24.7764f,15.625f, +226.563f,22.9689f,15.625f, +230.469f,20.4237f,15.625f, +234.375f,18.8049f,15.625f, +238.281f,17.4547f,15.625f, +242.188f,16.2758f,15.625f, +246.094f,14.2192f,15.625f, +250.0f,11.8103f,15.625f, +3.90625f,51.1233f,11.7187f, +7.8125f,51.8127f,11.7187f, +11.7188f,52.0971f,11.7187f, +15.625f,51.8317f,11.7187f, +19.5313f,52.1213f,11.7187f, +23.4375f,51.7889f,11.7187f, +27.3438f,52.2065f,11.7187f, +31.25f,52.438f,11.7187f, +35.1563f,52.6021f,11.7187f, +39.0625f,53.2864f,11.7187f, +42.9688f,52.8882f,11.7187f, +46.875f,52.6009f,11.7187f, +50.7813f,52.8442f,11.7187f, +54.6875f,52.6512f,11.7187f, +58.5938f,51.6436f,11.7187f, +62.5f,50.4271f,11.7187f, +66.4063f,49.3264f,11.7187f, +70.3125f,48.6522f,11.7187f, +74.2188f,49.5854f,11.7187f, +78.125f,50.3492f,11.7187f, +82.0313f,49.035f,11.7187f, +85.9375f,47.6474f,11.7187f, +89.8438f,46.0472f,11.7187f, +93.75f,44.7337f,11.7187f, +97.6563f,44.3349f,11.7187f, +101.563f,43.475f,11.7187f, +105.469f,42.9461f,11.7187f, +109.375f,41.7731f,11.7187f, +113.281f,40.717f,11.7187f, +117.188f,39.399f,11.7187f, +121.094f,38.1327f,11.7187f, +125.0f,36.3286f,11.7187f, +128.906f,36.2512f,11.7187f, +132.813f,35.1997f,11.7187f, +136.719f,33.9406f,11.7187f, +140.625f,33.3109f,11.7187f, +144.531f,33.8153f,11.7187f, +148.438f,33.6823f,11.7187f, +152.344f,34.7077f,11.7187f, +156.25f,35.4472f,11.7187f, +160.156f,35.6332f,11.7187f, +164.063f,34.3651f,11.7187f, +167.969f,32.9876f,11.7187f, +171.875f,32.2858f,11.7187f, +175.781f,32.1374f,11.7187f, +179.688f,30.9575f,11.7187f, +183.594f,29.1111f,11.7187f, +187.5f,28.149f,11.7187f, +191.406f,27.4443f,11.7187f, +195.313f,27.3781f,11.7187f, +199.219f,26.4413f,11.7187f, +203.125f,24.9734f,11.7187f, +207.031f,25.0959f,11.7187f, +210.938f,26.2472f,11.7187f, +214.844f,26.1569f,11.7187f, +218.75f,24.8556f,11.7187f, +222.656f,22.8797f,11.7187f, +226.563f,21.8102f,11.7187f, +230.469f,19.294f,11.7187f, +234.375f,17.5291f,11.7187f, +238.281f,16.242f,11.7187f, +242.188f,15.2738f,11.7187f, +246.094f,13.8715f,11.7187f, +250.0f,12.3043f,11.7187f, +3.90625f,52.2527f,7.8125f, +7.8125f,52.7759f,7.8125f, +11.7188f,52.1635f,7.8125f, +15.625f,52.2016f,7.8125f, +19.5313f,51.9832f,7.8125f, +23.4375f,51.4669f,7.8125f, +27.3438f,51.0033f,7.8125f, +31.25f,50.7124f,7.8125f, +35.1563f,51.6427f,7.8125f, +39.0625f,52.5008f,7.8125f, +42.9688f,53.2834f,7.8125f, +46.875f,52.5339f,7.8125f, +50.7813f,52.627f,7.8125f, +54.6875f,52.9017f,7.8125f, +58.5938f,52.8616f,7.8125f, +62.5f,51.7566f,7.8125f, +66.4063f,51.3268f,7.8125f, +70.3125f,50.6108f,7.8125f, +74.2188f,50.9277f,7.8125f, +78.125f,51.701f,7.8125f, +82.0313f,50.5549f,7.8125f, +85.9375f,48.4345f,7.8125f, +89.8438f,47.3592f,7.8125f, +93.75f,45.7216f,7.8125f, +97.6563f,45.75f,7.8125f, +101.563f,44.4249f,7.8125f, +105.469f,44.7192f,7.8125f, +109.375f,44.4938f,7.8125f, +113.281f,43.252f,7.8125f, +117.188f,41.3735f,7.8125f, +121.094f,39.8664f,7.8125f, +125.0f,37.025f,7.8125f, +128.906f,36.5094f,7.8125f, +132.813f,35.3554f,7.8125f, +136.719f,33.9389f,7.8125f, +140.625f,32.7715f,7.8125f, +144.531f,32.8295f,7.8125f, +148.438f,32.4513f,7.8125f, +152.344f,33.4598f,7.8125f, +156.25f,34.3434f,7.8125f, +160.156f,34.8633f,7.8125f, +164.063f,33.7043f,7.8125f, +167.969f,32.5629f,7.8125f, +171.875f,31.5117f,7.8125f, +175.781f,30.9816f,7.8125f, +179.688f,30.2039f,7.8125f, +183.594f,28.5054f,7.8125f, +187.5f,26.8519f,7.8125f, +191.406f,25.6078f,7.8125f, +195.313f,26.0906f,7.8125f, +199.219f,25.313f,7.8125f, +203.125f,24.0014f,7.8125f, +207.031f,24.066f,7.8125f, +210.938f,24.4935f,7.8125f, +214.844f,24.3803f,7.8125f, +218.75f,23.0075f,7.8125f, +222.656f,21.1023f,7.8125f, +226.563f,19.0418f,7.8125f, +230.469f,17.9588f,7.8125f, +234.375f,16.5211f,7.8125f, +238.281f,15.4949f,7.8125f, +242.188f,14.0938f,7.8125f, +246.094f,13.3141f,7.8125f, +250.0f,12.9595f,7.8125f, +3.90625f,52.6186f,3.90625f, +7.8125f,51.8648f,3.90625f, +11.7188f,51.1949f,3.90625f, +15.625f,50.2102f,3.90625f, +19.5313f,50.6058f,3.90625f, +23.4375f,50.7008f,3.90625f, +27.3438f,51.2163f,3.90625f, +31.25f,51.4263f,3.90625f, +35.1563f,52.1968f,3.90625f, +39.0625f,53.9783f,3.90625f, +42.9688f,53.8927f,3.90625f, +46.875f,53.3266f,3.90625f, +50.7813f,53.5901f,3.90625f, +54.6875f,55.5679f,3.90625f, +58.5938f,55.1819f,3.90625f, +62.5f,53.6891f,3.90625f, +66.4063f,53.0541f,3.90625f, +70.3125f,51.6665f,3.90625f, +74.2188f,51.4469f,3.90625f, +78.125f,51.9591f,3.90625f, +82.0313f,51.0418f,3.90625f, +85.9375f,49.7513f,3.90625f, +89.8438f,48.7329f,3.90625f, +93.75f,46.8713f,3.90625f, +97.6563f,46.3905f,3.90625f, +101.563f,45.4241f,3.90625f, +105.469f,45.6811f,3.90625f, +109.375f,45.3238f,3.90625f, +113.281f,43.6112f,3.90625f, +117.188f,42.1291f,3.90625f, +121.094f,40.4747f,3.90625f, +125.0f,39.3351f,3.90625f, +128.906f,38.0742f,3.90625f, +132.813f,36.7758f,3.90625f, +136.719f,34.9213f,3.90625f, +140.625f,32.3643f,3.90625f, +144.531f,31.7157f,3.90625f, +148.438f,30.6005f,3.90625f, +152.344f,31.6034f,3.90625f, +156.25f,32.6503f,3.90625f, +160.156f,33.3131f,3.90625f, +164.063f,32.5745f,3.90625f, +167.969f,31.5017f,3.90625f, +171.875f,30.6842f,3.90625f, +175.781f,29.8734f,3.90625f, +179.688f,28.6537f,3.90625f, +183.594f,27.2073f,3.90625f, +187.5f,25.4367f,3.90625f, +191.406f,24.1609f,3.90625f, +195.313f,23.9724f,3.90625f, +199.219f,23.7702f,3.90625f, +203.125f,22.4031f,3.90625f, +207.031f,22.1587f,3.90625f, +210.938f,21.6154f,3.90625f, +214.844f,21.8202f,3.90625f, +218.75f,21.017f,3.90625f, +222.656f,19.3736f,3.90625f, +226.563f,18.2127f,3.90625f, +230.469f,17.2263f,3.90625f, +234.375f,16.2938f,3.90625f, +238.281f,14.4518f,3.90625f, +242.188f,13.6398f,3.90625f, +246.094f,13.2404f,3.90625f, +250.0f,12.7102f,3.90625f, +}; + +btScalar Landscape04Nml[] = { +-0.350125f,0.914758f,-0.201568f, +-0.310159f,0.930741f,-0.193707f, +-0.297809f,0.93918f,-0.171025f, +-0.203808f,0.975413f,-0.083855f, +-0.227869f,0.971729f,-0.0617958f, +-0.175976f,0.984209f,0.0190985f, +-0.113434f,0.992992f,-0.0331636f, +-0.10748f,0.994138f,-0.0117748f, +0.264437f,0.964372f,0.00769155f, +0.281666f,0.958691f,0.0397075f, +0.430486f,0.901936f,-0.0345351f, +0.401178f,0.915992f,-0.00383073f, +0.323069f,0.944057f,-0.0662002f, +0.321744f,0.945983f,-0.039967f, +0.269775f,0.962292f,-0.0348534f, +0.20193f,0.970428f,-0.132266f, +0.268889f,0.954681f,-0.127604f, +0.194635f,0.954618f,-0.225435f, +0.221506f,0.956393f,-0.190387f, +0.193103f,0.932235f,-0.306022f, +0.127904f,0.985279f,-0.113427f, +0.190082f,0.941797f,-0.277285f, +-0.00897869f,0.999816f,0.0169309f, +0.104995f,0.98929f,-0.101393f, +-0.0904331f,0.992726f,0.0794834f, +0.0230108f,0.991613f,0.127174f, +0.0155488f,0.993572f,0.11213f, +0.0288983f,0.981821f,0.187597f, +0.0247864f,0.996149f,0.0840949f, +-0.0831472f,0.996537f,0.000391199f, +-0.0501709f,0.99867f,0.0118531f, +-0.153f,0.976743f,-0.15021f, +-0.106591f,0.988499f,-0.107277f, +-0.178503f,0.946807f,-0.267757f, +-0.0254657f,0.984638f,-0.172739f, +-0.00387521f,0.963955f,-0.266035f, +-0.0158619f,0.994497f,-0.103554f, +0.0516719f,0.979433f,-0.195043f, +-0.113536f,0.993496f,-0.00869834f, +-0.0532458f,0.993386f,-0.101726f, +-0.240923f,0.970479f,0.0112676f, +-0.272825f,0.959264f,-0.0733371f, +-0.364171f,0.921854f,-0.132533f, +-0.38043f,0.901643f,-0.205699f, +-0.208475f,0.967633f,-0.142215f, +-0.200209f,0.964847f,-0.170257f, +-0.436593f,0.880066f,-0.186734f, +-0.420663f,0.90307f,-0.0866427f, +-0.564169f,0.813693f,-0.140058f, +-0.556718f,0.83037f,-0.0234562f, +-0.419122f,0.896066f,-0.146295f, +-0.466908f,0.873897f,-0.135282f, +-0.39151f,0.89596f,-0.209704f, +-0.388383f,0.911455f,-0.135677f, +-0.356022f,0.918213f,-0.173589f, +-0.334437f,0.939184f,-0.0780065f, +-0.257665f,0.953587f,-0.155824f, +-0.309301f,0.93272f,-0.185382f, +-0.315034f,0.931862f,-0.179961f, +-0.295926f,0.931298f,-0.212393f, +-0.436779f,0.896592f,-0.0731173f, +-0.317368f,0.948237f,0.0111289f, +-0.503169f,0.863334f,0.0383931f, +-0.468116f,0.877337f,0.105583f, +-0.41232f,0.911034f,0.00307775f, +-0.465256f,0.885053f,0.0147642f, +-0.139311f,0.987488f,-0.0738976f, +-0.20689f,0.974976f,-0.0813499f, +-0.0453849f,0.98457f,-0.169006f, +-0.109269f,0.973649f,-0.20017f, +0.0405907f,0.980595f,-0.191794f, +0.0742781f,0.990348f,-0.117022f, +-0.00934593f,0.982385f,-0.186633f, +0.00811898f,0.984163f,-0.177079f, +-0.0726933f,0.996391f,-0.043832f, +0.0160265f,0.999861f,-0.00453309f, +-0.163053f,0.986585f,0.00801872f, +-0.185529f,0.978031f,-0.0950467f, +-0.137829f,0.987875f,0.0714611f, +-0.0578854f,0.998186f,0.0165557f, +0.148249f,0.976119f,0.158788f, +0.193139f,0.975453f,0.10578f, +0.369772f,0.912299f,0.176006f, +0.348645f,0.936628f,0.0342667f, +0.282769f,0.952501f,0.113063f, +0.239504f,0.96906f,-0.059674f, +0.137712f,0.990197f,0.0233582f, +0.149987f,0.988306f,0.0274647f, +0.169834f,0.984573f,-0.0420991f, +0.0927723f,0.990592f,-0.100603f, +0.171676f,0.97845f,-0.114732f, +0.0567364f,0.963622f,-0.261179f, +0.117062f,0.969073f,-0.217242f, +0.0434058f,0.931949f,-0.359981f, +0.148347f,0.946865f,-0.285375f, +0.103327f,0.903437f,-0.416082f, +0.28421f,0.914779f,-0.287061f, +0.391793f,0.893555f,-0.21922f, +0.419866f,0.888994f,-0.182764f, +0.461528f,0.873246f,-0.156313f, +0.483081f,0.869853f,-0.099941f, +0.503438f,0.857022f,-0.109831f, +0.46584f,0.882166f,-0.0691099f, +0.489623f,0.868073f,-0.0819641f, +0.410796f,0.910896f,-0.0389227f, +0.393119f,0.918063f,-0.0511611f, +0.359627f,0.921042f,-0.1495f, +0.306646f,0.942147f,-0.135377f, +0.381773f,0.903228f,-0.196033f, +0.360002f,0.920948f,-0.149176f, +0.203221f,0.945872f,-0.253037f, +0.218471f,0.943498f,-0.249162f, +0.0567054f,0.995659f,-0.0738017f, +0.229305f,0.968679f,0.0952866f, +-0.0263963f,0.99794f,0.0584726f, +-0.0422212f,0.996107f,0.0773806f, +0.0415928f,0.997459f,0.0578396f, +0.0625406f,0.995706f,0.0682456f, +0.174866f,0.970931f,0.163448f, +0.248971f,0.959664f,0.13061f, +0.296526f,0.91909f,0.259511f, +0.244457f,0.962524f,0.117427f, +0.144028f,0.988219f,0.0517682f, +0.0516566f,0.998622f,-0.00921711f, +-0.0100473f,0.999479f,-0.0306849f, +0.144821f,0.968281f,0.203614f, +0.0927686f,0.985877f,0.139429f, +0.159268f,0.950036f,0.268448f, +-0.238265f,0.969366f,-0.0596594f, +-0.317162f,0.937667f,-0.14209f, +-0.252226f,0.956124f,-0.149026f, +-0.139275f,0.959516f,-0.244809f, +0.225678f,0.948782f,-0.221092f, +0.454598f,0.876109f,-0.160545f, +0.280777f,0.950726f,-0.131467f, +0.235562f,0.968875f,-0.076101f, +0.32523f,0.943278f,-0.0667146f, +0.204883f,0.977104f,-0.0573623f, +-0.016814f,0.999658f,-0.0200258f, +-0.0821474f,0.994185f,0.0696248f, +-0.0248008f,0.998098f,0.0564331f, +0.000698274f,0.999817f,0.0191283f, +0.0007523f,0.989994f,0.141106f, +-0.0137951f,0.98192f,0.188792f, +-0.00956379f,0.990301f,0.138609f, +-0.0156365f,0.996604f,0.0808513f, +-0.104293f,0.986463f,0.126542f, +-0.156424f,0.969975f,0.186228f, +-0.167617f,0.975111f,0.145129f, +-0.261339f,0.965118f,0.0157997f, +-0.160877f,0.9832f,-0.0862302f, +-0.296054f,0.934306f,-0.198555f, +-0.550185f,0.752769f,-0.361436f, +-0.408582f,0.840233f,-0.356467f, +-0.339245f,0.876729f,-0.340968f, +-0.402741f,0.85772f,-0.319556f, +-0.316164f,0.924069f,-0.214795f, +-0.348907f,0.927941f,-0.131109f, +-0.48502f,0.870548f,-0.0830789f, +-0.53006f,0.843646f,-0.085433f, +-0.352226f,0.931519f,-0.0906107f, +-0.0975811f,0.982258f,-0.160146f, +0.0477418f,0.981235f,-0.186812f, +0.0219054f,0.966987f,-0.253882f, +-0.115057f,0.988784f,-0.0952266f, +-0.238673f,0.960258f,0.144707f, +-0.213447f,0.931011f,0.296071f, +-0.201955f,0.923284f,0.326742f, +0.101325f,0.921693f,0.374453f, +0.294403f,0.882174f,0.367555f, +0.373397f,0.835094f,0.403971f, +0.278351f,0.921647f,0.270347f, +0.215461f,0.962466f,0.16503f, +0.225302f,0.965479f,0.13073f, +0.175997f,0.983214f,0.0481225f, +0.220124f,0.97536f,0.0147531f, +0.32343f,0.94566f,-0.0334783f, +0.369971f,0.927728f,-0.0494253f, +0.427777f,0.903113f,-0.037328f, +0.446874f,0.894597f,9.72625e-005f, +0.445338f,0.895316f,-0.00910111f, +0.463955f,0.88101f,-0.0925573f, +0.398143f,0.905258f,-0.148289f, +0.190091f,0.969836f,-0.152589f, +-0.0830374f,0.980972f,-0.175495f, +-0.1343f,0.985908f,-0.0997463f, +-0.00843053f,0.999434f,0.0325608f, +0.021819f,0.995847f,0.0883913f, +0.206682f,0.96009f,0.188439f, +0.388829f,0.882727f,0.263827f, +0.0707915f,0.996578f,0.0426701f, +-0.161491f,0.983232f,-0.0847068f, +-0.0785342f,0.996721f,-0.0194704f, +-0.224473f,0.966422f,-0.125062f, +-0.159666f,0.968511f,-0.191032f, +0.0318558f,0.951557f,-0.305817f, +0.187349f,0.896729f,-0.400972f, +0.324927f,0.900628f,-0.288602f, +0.217775f,0.961772f,-0.16604f, +0.20019f,0.973241f,-0.112807f, +0.277242f,0.959937f,-0.0407145f, +0.14204f,0.987332f,0.0707153f, +-0.0153938f,0.984428f,0.175114f, +-0.0735255f,0.984081f,0.161796f, +-0.0237909f,0.990594f,0.134749f, +-0.0614906f,0.985818f,0.156146f, +-0.143236f,0.970943f,0.191711f, +-0.0137498f,0.973243f,0.229369f, +0.0567477f,0.984597f,0.165372f, +-0.0347212f,0.993259f,0.110594f, +-0.143386f,0.976741f,0.159429f, +-0.139502f,0.982211f,0.125705f, +-0.0993842f,0.989216f,0.107588f, +-0.136731f,0.987843f,0.0739654f, +-0.0893069f,0.995969f,0.00840628f, +-0.123862f,0.992294f,-0.00315825f, +-0.391175f,0.886683f,-0.246529f, +-0.44403f,0.793263f,-0.41662f, +-0.399761f,0.83626f,-0.375315f, +-0.422675f,0.841058f,-0.33759f, +-0.445112f,0.835127f,-0.323168f, +-0.410733f,0.898417f,-0.155389f, +-0.485628f,0.867891f,-0.104549f, +-0.491383f,0.859111f,-0.143077f, +-0.358033f,0.910383f,-0.207399f, +-0.0910122f,0.986127f,-0.138818f, +0.0820594f,0.995842f,-0.039567f, +-0.0287013f,0.999312f,-0.0234726f, +-0.346268f,0.933835f,0.0897299f, +-0.471073f,0.825151f,0.311795f, +-0.27505f,0.819541f,0.502693f, +-0.154238f,0.84574f,0.510818f, +0.0836929f,0.869512f,0.48677f, +0.266688f,0.84547f,0.462663f, +0.365749f,0.809921f,0.458537f, +0.371864f,0.832105f,0.411483f, +0.260242f,0.895369f,0.361371f, +0.283389f,0.903576f,0.321311f, +0.269874f,0.934168f,0.233448f, +0.265321f,0.957928f,0.10945f, +0.333071f,0.942841f,0.0106961f, +0.387903f,0.9217f,0.000193271f, +0.435792f,0.899834f,0.0195967f, +0.454676f,0.88982f,0.0386129f, +0.482276f,0.876019f,-0.000723308f, +0.505259f,0.860654f,-0.0631586f, +0.398328f,0.910448f,-0.111444f, +0.21929f,0.970647f,-0.0987756f, +0.0111053f,0.988208f,-0.152714f, +-0.210805f,0.943357f,-0.256201f, +-0.146846f,0.978658f,-0.143755f, +0.0139602f,0.999731f,-0.0184963f, +0.133096f,0.990721f,-0.0275154f, +0.2933f,0.953875f,0.0640122f, +0.228393f,0.945969f,0.230173f, +0.0546169f,0.969859f,0.237467f, +-0.0762534f,0.988779f,-0.128459f, +-0.106647f,0.982213f,-0.154543f, +-0.122396f,0.949634f,-0.28847f, +0.0920652f,0.954226f,-0.284566f, +0.185259f,0.946785f,-0.263206f, +0.232314f,0.960849f,-0.150996f, +0.169992f,0.979263f,-0.110207f, +0.125326f,0.980516f,-0.151267f, +0.149673f,0.98818f,-0.0331477f, +0.0238199f,0.989878f,0.139909f, +-0.107594f,0.981438f,0.158754f, +-0.0846643f,0.982313f,0.167013f, +-0.0375415f,0.970751f,0.237134f, +-0.0510768f,0.964816f,0.257917f, +-0.0443365f,0.980593f,0.190977f, +0.00242513f,0.997744f,0.0670872f, +0.124335f,0.983389f,0.132238f, +-0.00301992f,0.993206f,0.116332f, +-0.125192f,0.990103f,0.0634287f, +-0.100487f,0.994519f,-0.0288746f, +-0.101663f,0.992712f,-0.0647098f, +-0.139647f,0.987963f,-0.0665471f, +-0.130136f,0.990189f,-0.0508981f, +-0.0756901f,0.997123f,-0.00415316f, +-0.171558f,0.977059f,-0.126185f, +-0.351855f,0.892529f,-0.282117f, +-0.447333f,0.817645f,-0.362422f, +-0.423851f,0.857249f,-0.29236f, +-0.448058f,0.866215f,-0.221171f, +-0.531086f,0.820738f,-0.210565f, +-0.511898f,0.851158f,-0.116153f, +-0.425868f,0.900461f,-0.0883553f, +-0.399025f,0.900598f,-0.172345f, +-0.24223f,0.968919f,-0.0502012f, +-0.0663613f,0.996507f,0.0506899f, +-0.138021f,0.972657f,0.186782f, +-0.4139f,0.851097f,0.322987f, +-0.550512f,0.782849f,0.289973f, +-0.380287f,0.863038f,0.332486f, +-0.131533f,0.903571f,0.407748f, +0.119586f,0.9109f,0.394918f, +0.299052f,0.87558f,0.379379f, +0.370047f,0.8611f,0.348671f, +0.442832f,0.822723f,0.356408f, +0.35885f,0.890772f,0.278839f, +0.314791f,0.940053f,0.131179f, +0.339464f,0.925728f,0.166711f, +0.403599f,0.900778f,0.160334f, +0.45653f,0.889636f,-0.0113152f, +0.365242f,0.916509f,-0.163124f, +0.379822f,0.91652f,-0.125407f, +0.442125f,0.891797f,-0.096041f, +0.493888f,0.864551f,-0.0928755f, +0.541781f,0.83947f,-0.041994f, +0.441424f,0.894377f,-0.0723577f, +0.226514f,0.958331f,-0.174048f, +0.0664964f,0.969681f,-0.235153f, +-0.103823f,0.949537f,-0.295973f, +-0.233692f,0.889012f,-0.39376f, +-0.0987171f,0.939339f,-0.328477f, +0.103986f,0.972613f,-0.207871f, +0.198802f,0.974287f,-0.106033f, +0.0601774f,0.998175f,0.00500958f, +-0.0421158f,0.995212f,0.0882012f, +-0.0598721f,0.997785f,-0.0289851f, +-0.030607f,0.999125f,-0.0285146f, +-0.00697633f,0.993471f,-0.113875f, +0.0388611f,0.980882f,-0.190686f, +0.0977483f,0.98843f,-0.115983f, +0.15403f,0.986798f,-0.0500538f, +0.193054f,0.979913f,-0.0500083f, +0.157678f,0.98694f,-0.0329733f, +-0.0158549f,0.999428f,0.0298765f, +-0.0525571f,0.987534f,0.14837f, +0.000720533f,0.997813f,0.0660913f, +-0.102677f,0.99254f,-0.0657426f, +-0.099341f,0.994285f,-0.0391091f, +-0.0676495f,0.996952f,-0.0388727f, +0.0225146f,0.999293f,0.0301014f, +0.0577235f,0.997453f,0.0418936f, +-0.0269869f,0.999243f,0.0280361f, +0.00446401f,0.985157f,0.171599f, +-0.0141502f,0.990326f,0.138035f, +-0.00518586f,0.999975f,0.00477817f, +-0.0328139f,0.995381f,-0.09022f, +-0.128063f,0.971338f,-0.200254f, +-0.151852f,0.967914f,-0.200209f, +-0.0720493f,0.989055f,-0.128759f, +-0.0591129f,0.991504f,-0.115868f, +-0.248059f,0.943661f,-0.219024f, +-0.389946f,0.877483f,-0.279225f, +-0.523332f,0.810744f,-0.262332f, +-0.51839f,0.842544f,-0.146256f, +-0.550368f,0.815716f,-0.178051f, +-0.560732f,0.813038f,-0.156683f, +-0.427123f,0.899415f,-0.0928351f, +-0.366593f,0.924495f,-0.104494f, +-0.322547f,0.93696f,-0.134426f, +-0.128035f,0.99042f,-0.0517317f, +-0.291376f,0.953688f,0.0746902f, +-0.520094f,0.826135f,0.216802f, +-0.516864f,0.826474f,0.22314f, +-0.396988f,0.892552f,0.213897f, +-0.184148f,0.954818f,0.233263f, +0.0957205f,0.95579f,0.278034f, +0.314018f,0.892294f,0.32435f, +0.401668f,0.873128f,0.276243f, +0.463054f,0.857596f,0.223851f, +0.480022f,0.855973f,0.192066f, +0.375927f,0.916106f,0.13939f, +0.288789f,0.941864f,0.171735f, +0.396643f,0.909563f,0.123974f, +0.561623f,0.825897f,0.0497286f, +0.465605f,0.881752f,-0.0756653f, +0.370044f,0.915005f,-0.160728f, +0.427822f,0.898624f,-0.0971747f, +0.465206f,0.885137f,-0.0107503f, +0.468824f,0.88183f,0.0507874f, +0.478143f,0.868746f,0.12907f, +0.351411f,0.934208f,0.0613665f, +0.140442f,0.98844f,-0.0571117f, +-0.0122878f,0.991421f,-0.130131f, +-0.117862f,0.972142f,-0.202603f, +-0.15815f,0.947613f,-0.27752f, +-0.0729629f,0.95654f,-0.282325f, +0.0272484f,0.989771f,-0.14004f, +-0.0137333f,0.999563f,0.0261849f, +-0.0985129f,0.993299f,0.0604412f, +-0.135233f,0.990548f,-0.0229695f, +-0.0373153f,0.999264f,0.00888433f, +0.0352261f,0.99933f,0.00994916f, +0.061219f,0.99588f,0.0668911f, +0.0815695f,0.99444f,0.0665983f, +0.144386f,0.989424f,0.0139045f, +0.184662f,0.980318f,0.0698361f, +0.0224217f,0.989677f,0.14155f, +-0.0794321f,0.954058f,0.288901f, +-0.0304562f,0.959461f,0.280192f, +0.112423f,0.968918f,0.220359f, +0.0390938f,0.993037f,0.111126f, +-0.0885962f,0.9933f,-0.0741985f, +-0.0453085f,0.996418f,-0.0714089f, +-0.123875f,0.985221f,-0.118298f, +0.00670832f,0.999925f,0.010273f, +-0.0146906f,0.998569f,0.0514303f, +-0.0998092f,0.992773f,0.0666264f, +0.0466126f,0.990197f,0.131669f, +0.103009f,0.992862f,0.0601126f, +0.113553f,0.993084f,-0.0298385f, +-0.0128779f,0.975704f,-0.218713f, +-0.177855f,0.94662f,-0.268846f, +-0.191482f,0.955424f,-0.224722f, +-0.0532043f,0.987628f,-0.147512f, +-0.140744f,0.970833f,-0.194099f, +-0.387395f,0.889373f,-0.242778f, +-0.531553f,0.818908f,-0.216427f, +-0.531571f,0.799354f,-0.280115f, +-0.51407f,0.81292f,-0.273666f, +-0.549112f,0.793924f,-0.261078f, +-0.484709f,0.822384f,-0.297895f, +-0.322663f,0.926066f,-0.195678f, +-0.315438f,0.927311f,-0.201479f, +-0.289702f,0.947148f,-0.13778f, +-0.417457f,0.908684f,-0.00477603f, +-0.584599f,0.810188f,0.0428868f, +-0.55194f,0.828316f,0.0962071f, +-0.397599f,0.904432f,0.154656f, +-0.183216f,0.971572f,0.149931f, +0.0355131f,0.990243f,0.134751f, +0.298837f,0.942288f,0.150964f, +0.413659f,0.900634f,0.133206f, +0.498073f,0.828388f,0.256313f, +0.444018f,0.853405f,0.273035f, +0.327561f,0.881897f,0.339061f, +0.313826f,0.898686f,0.306392f, +0.495157f,0.851292f,0.173556f, +0.614747f,0.78345f,0.0910662f, +0.55187f,0.833866f,0.0103585f, +0.367713f,0.926545f,-0.0793776f, +0.311567f,0.950223f,0.00108255f, +0.382947f,0.917094f,0.110859f, +0.410945f,0.895808f,0.169272f, +0.455231f,0.858878f,0.234721f, +0.373673f,0.896264f,0.238911f, +0.246571f,0.935158f,0.254328f, +0.0808975f,0.990111f,0.114608f, +-0.0843211f,0.99633f,-0.0147289f, +-0.0859474f,0.994869f,-0.0533687f, +-0.0567528f,0.986639f,-0.152718f, +-0.104487f,0.984189f,-0.143019f, +-0.139027f,0.990289f,8.5057e-005f, +-0.137547f,0.987918f,0.0714029f, +-0.144256f,0.989201f,-0.0259182f, +-0.026694f,0.998838f,-0.0401331f, +-0.0313342f,0.99664f,-0.0756769f, +-0.0574884f,0.99781f,0.0327011f, +0.145005f,0.983413f,0.108961f, +0.119257f,0.992151f,0.0376122f, +0.0587452f,0.978725f,0.196585f, +-0.0803833f,0.947865f,0.308369f, +-0.127827f,0.919581f,0.371526f, +-0.00616421f,0.930831f,0.365399f, +0.107639f,0.912609f,0.394409f, +0.210572f,0.88729f,0.410336f, +0.0740329f,0.980065f,0.184368f, +-0.0250926f,0.999613f,0.0120275f, +-0.0610433f,0.996433f,-0.05826f, +-0.0708404f,0.994984f,-0.0706271f, +-0.0640037f,0.997923f,-0.00726403f, +-0.0949547f,0.99548f,0.00148231f, +0.00929451f,0.997943f,-0.0634315f, +0.147986f,0.988795f,-0.0195964f, +0.19874f,0.98001f,-0.00909425f, +0.119683f,0.99247f,-0.0260466f, +-0.140841f,0.984951f,-0.10018f, +-0.197496f,0.959342f,-0.201637f, +-0.0821482f,0.973605f,-0.212945f, +-0.090387f,0.978841f,-0.18358f, +-0.34459f,0.903344f,-0.255395f, +-0.465169f,0.833236f,-0.29889f, +-0.493353f,0.789348f,-0.365421f, +-0.529455f,0.773394f,-0.348624f, +-0.541108f,0.776645f,-0.322528f, +-0.503238f,0.814279f,-0.289312f, +-0.451111f,0.869282f,-0.202106f, +-0.405307f,0.906179f,-0.120689f, +-0.367499f,0.92846f,-0.0539062f, +-0.448648f,0.893437f,-0.0220131f, +-0.582415f,0.811815f,-0.0418214f, +-0.587857f,0.805915f,-0.0701802f, +-0.440963f,0.897524f,0.00144435f, +-0.150082f,0.985674f,0.0769547f, +0.0512849f,0.998035f,0.0359923f, +0.331471f,0.9412f,0.0653422f, +0.327057f,0.943418f,0.0547333f, +0.325027f,0.917755f,0.228216f, +0.374201f,0.856118f,0.35642f, +0.374565f,0.858588f,0.350039f, +0.460817f,0.854058f,0.241312f, +0.556465f,0.823608f,0.109619f, +0.63153f,0.770458f,0.0869767f, +0.587056f,0.806123f,0.074369f, +0.365958f,0.924908f,0.10305f, +0.26636f,0.954918f,0.131089f, +0.330741f,0.937061f,0.111923f, +0.358992f,0.918233f,0.167249f, +0.397317f,0.888574f,0.229294f, +0.378918f,0.890078f,0.253343f, +0.252398f,0.944302f,0.211161f, +0.242388f,0.947895f,0.206744f, +0.0865865f,0.99456f,0.0579091f, +-0.0181168f,0.990006f,-0.139854f, +0.0162661f,0.98021f,-0.197289f, +-0.148111f,0.960303f,-0.236394f, +-0.255052f,0.949006f,-0.185302f, +-0.211751f,0.971559f,-0.105997f, +-0.0120621f,0.994912f,-0.100021f, +-0.015173f,0.98959f,-0.143115f, +-0.0401151f,0.99847f,-0.0380528f, +-0.0979763f,0.995187f,0.00194195f, +0.0571375f,0.998251f,0.0151643f, +0.0776787f,0.976915f,0.199006f, +-0.101892f,0.95655f,0.273185f, +-0.133768f,0.938598f,0.318024f, +-0.177801f,0.93623f,0.303084f, +-0.022321f,0.922329f,0.385761f, +0.0333931f,0.905943f,0.422081f, +0.163361f,0.862964f,0.478127f, +0.305267f,0.821497f,0.481617f, +0.18106f,0.939243f,0.291615f, +-0.00700511f,0.992472f,0.122275f, +-0.0966012f,0.992994f,0.068052f, +-0.106034f,0.991731f,0.0722919f, +-0.0353039f,0.993084f,0.11197f, +0.0541772f,0.995603f,0.0764134f, +0.08347f,0.989853f,0.114994f, +0.130868f,0.975887f,0.174696f, +0.0723356f,0.969665f,0.23349f, +-0.0470347f,0.960948f,0.272703f, +-0.10077f,0.971805f,0.213169f, +-0.119566f,0.974584f,0.189448f, +-0.0774738f,0.965859f,0.247214f, +-0.198029f,0.968836f,0.1488f, +-0.435505f,0.897132f,-0.0740912f, +-0.502708f,0.857298f,-0.111019f, +-0.564282f,0.819749f,-0.0979722f, +-0.594236f,0.795147f,-0.120937f, +-0.591492f,0.803058f,-0.0723546f, +-0.526826f,0.849968f,-0.0029614f, +-0.410127f,0.912007f,0.00617969f, +-0.355675f,0.932755f,-0.0588432f, +-0.457125f,0.883759f,-0.100032f, +-0.544765f,0.834451f,-0.0832032f, +-0.554858f,0.819866f,-0.141253f, +-0.535218f,0.826621f,-0.173894f, +-0.203549f,0.978635f,-0.0289948f, +0.0668755f,0.997729f,0.00799418f, +0.247034f,0.968844f,0.017759f, +0.275407f,0.949712f,0.148988f, +0.19759f,0.950103f,0.241375f, +0.374575f,0.880138f,0.291635f, +0.446827f,0.865948f,0.224675f, +0.519968f,0.833624f,0.186291f, +0.587008f,0.786117f,0.193499f, +0.636373f,0.75334f,0.165857f, +0.540728f,0.822377f,0.176944f, +0.345338f,0.910903f,0.225828f, +0.278322f,0.945193f,0.170723f, +0.30876f,0.936535f,0.166043f, +0.303863f,0.916063f,0.261719f, +0.319419f,0.895614f,0.309591f, +0.43277f,0.828092f,0.356332f, +0.333077f,0.917687f,0.216587f, +0.219655f,0.964319f,0.147787f, +0.242228f,0.95005f,0.196802f, +0.204875f,0.978767f,-0.00640881f, +-0.000192716f,0.97566f,-0.219288f, +-0.0681124f,0.988809f,-0.132732f, +-0.241144f,0.919453f,-0.310573f, +-0.290276f,0.882193f,-0.370776f, +0.0292627f,0.97223f,-0.232189f, +-0.0803803f,0.976804f,-0.198478f, +-0.203999f,0.977793f,-0.0480039f, +-0.118856f,0.989202f,0.0857425f, +-0.0783112f,0.985397f,0.151198f, +-0.0878718f,0.938803f,0.333059f, +-0.083435f,0.948159f,0.30665f, +-0.110585f,0.962509f,0.247682f, +-0.186686f,0.943514f,0.273733f, +-0.149516f,0.932553f,0.32862f, +-0.00475332f,0.899494f,0.436906f, +0.0862131f,0.885009f,0.457522f, +0.277459f,0.815555f,0.507825f, +0.298118f,0.799955f,0.520766f, +0.14455f,0.869997f,0.471392f, +0.0121492f,0.942115f,0.335071f, +-0.0752209f,0.977077f,0.199154f, +-0.128636f,0.97789f,0.164878f, +-0.000660482f,0.945164f,0.326595f, +0.00550592f,0.919316f,0.393482f, +0.0803772f,0.905979f,0.415621f, +0.0810259f,0.907487f,0.412192f, +-0.090779f,0.919652f,0.382099f, +-0.137864f,0.897436f,0.419048f, +-0.130404f,0.886486f,0.444001f, +-0.0852724f,0.906321f,0.413897f, +-0.0259127f,0.906615f,0.421163f, +-0.225351f,0.915922f,0.332119f, +-0.462548f,0.869686f,0.172323f, +-0.572668f,0.816922f,0.0684804f, +-0.585929f,0.806118f,0.0828267f, +-0.593406f,0.803366f,0.0497268f, +-0.516762f,0.856027f,-0.0132014f, +-0.38427f,0.922646f,-0.0325731f, +-0.287245f,0.956724f,-0.0465863f, +-0.413146f,0.905396f,-0.097823f, +-0.564236f,0.818421f,-0.108744f, +-0.507227f,0.858315f,-0.0775611f, +-0.527754f,0.82927f,-0.183811f, +-0.354765f,0.918321f,-0.175582f, +0.0463007f,0.998926f,-0.00175561f, +0.214268f,0.976774f,0.00151756f, +0.165544f,0.983729f,0.0698077f, +0.096445f,0.982342f,0.16032f, +0.366991f,0.896711f,0.24744f, +0.500788f,0.845195f,0.186699f, +0.507012f,0.85355f,0.119965f, +0.542994f,0.824496f,0.159261f, +0.605757f,0.757486f,0.243463f, +0.532123f,0.786802f,0.312711f, +0.44869f,0.847812f,0.282652f, +0.34333f,0.935092f,0.0879082f, +0.24319f,0.961353f,0.129073f, +0.223708f,0.954136f,0.198946f, +0.276144f,0.94134f,0.193965f, +0.41277f,0.892522f,0.181731f, +0.485836f,0.856185f,0.175815f, +0.251109f,0.963495f,0.0928509f, +0.217377f,0.969921f,0.109544f, +0.402023f,0.911537f,0.0864706f, +0.0930878f,0.988366f,-0.120284f, +-0.0926141f,0.987658f,-0.126311f, +-0.0129498f,0.988134f,-0.153049f, +-0.0752509f,0.973537f,-0.215783f, +-0.167591f,0.970187f,-0.175075f, +-0.227938f,0.971032f,-0.0717025f, +-0.288377f,0.95589f,0.0557925f, +-0.2706f,0.959797f,0.0746015f, +-0.201821f,0.948409f,0.244517f, +-0.135104f,0.944724f,0.298737f, +0.0536332f,0.953012f,0.298147f, +-0.104499f,0.972769f,0.206883f, +-0.26012f,0.936243f,0.236192f, +-0.221301f,0.933098f,0.283468f, +-0.0976008f,0.934678f,0.341835f, +0.0488135f,0.920165f,0.388475f, +0.20566f,0.878417f,0.431379f, +0.294052f,0.82595f,0.480979f, +0.211093f,0.846234f,0.489211f, +0.1526f,0.86506f,0.477897f, +0.100541f,0.907805f,0.407163f, +-0.126416f,0.965258f,0.228683f, +-0.211306f,0.949302f,0.232755f, +-0.037039f,0.912463f,0.40748f, +0.117233f,0.908378f,0.401379f, +0.101997f,0.928038f,0.35825f, +-0.0502775f,0.939056f,0.340069f, +-0.158243f,0.952358f,0.260718f, +-0.125329f,0.958222f,0.257106f, +-0.051336f,0.956723f,0.286436f, +-0.0625203f,0.954305f,0.29222f, +-0.207996f,0.932703f,0.294623f, +-0.319481f,0.91161f,0.258649f, +-0.495077f,0.865137f,0.0802322f, +-0.579132f,0.814857f,-0.0247929f, +-0.549115f,0.83292f,-0.0686783f, +-0.493373f,0.86244f,-0.113053f, +-0.402759f,0.911225f,-0.0863345f, +-0.292096f,0.955556f,-0.0399004f, +-0.382523f,0.923047f,-0.0407488f, +-0.572187f,0.816414f,-0.0779103f, +-0.512485f,0.857517f,-0.0449819f, +-0.420369f,0.906318f,-0.0433336f, +-0.419207f,0.879291f,-0.22608f, +-0.129012f,0.980121f,-0.150729f, +0.168538f,0.98409f,0.056222f, +0.177285f,0.97778f,0.111881f, +0.0313595f,0.998166f,-0.0517722f, +0.266622f,0.963684f,-0.0150476f, +0.566513f,0.817464f,0.103999f, +0.539244f,0.841888f,0.0209898f, +0.503392f,0.861782f,0.0626771f, +0.548011f,0.825978f,0.132075f, +0.53464f,0.817691f,0.213407f, +0.52656f,0.822061f,0.21668f, +0.418461f,0.898681f,0.131391f, +0.217077f,0.97168f,0.0933593f, +0.230073f,0.97316f,0.00512693f, +0.352039f,0.933499f,-0.0681773f, +0.427612f,0.891089f,-0.152014f, +0.47402f,0.877861f,-0.0682997f, +0.292505f,0.956178f,-0.0128375f, +0.212998f,0.971167f,-0.107084f, +0.394409f,0.913171f,-0.102761f, +0.229015f,0.973422f,0.000912976f, +-0.0760893f,0.988509f,-0.130618f, +-0.0515625f,0.984716f,-0.166362f, +-0.0928406f,0.987408f,-0.128086f, +-0.200115f,0.967117f,0.156969f, +-0.29324f,0.941681f,0.165066f, +-0.336305f,0.919935f,0.201539f, +-0.298108f,0.921775f,0.247915f, +-0.262609f,0.920325f,0.289892f, +-0.146209f,0.952657f,0.266586f, +-0.00778438f,0.956339f,0.292158f, +-0.050022f,0.92665f,0.372583f, +-0.258705f,0.916977f,0.303687f, +-0.247478f,0.923305f,0.293706f, +-0.126717f,0.938107f,0.322331f, +0.0303988f,0.946862f,0.320201f, +0.135735f,0.944675f,0.298606f, +0.25669f,0.889672f,0.377616f, +0.215508f,0.868916f,0.44558f, +0.117717f,0.868155f,0.482129f, +0.172493f,0.853951f,0.490931f, +0.0744588f,0.909987f,0.407897f, +-0.203499f,0.942765f,0.264163f, +-0.165852f,0.956441f,0.240237f, +0.150303f,0.946565f,0.285349f, +0.126121f,0.955231f,0.267632f, +0.00383767f,0.957166f,0.289515f, +-0.0803601f,0.965694f,0.246937f, +-0.14415f,0.963474f,0.225698f, +-0.128772f,0.964294f,0.231421f, +-0.0634991f,0.964707f,0.255554f, +-0.15178f,0.96554f,0.211412f, +-0.290877f,0.950446f,0.109737f, +-0.365587f,0.928197f,0.069257f, +-0.512709f,0.855901f,-0.0675528f, +-0.522587f,0.843414f,-0.12472f, +-0.519355f,0.843468f,-0.13723f, +-0.458617f,0.886978f,-0.054221f, +-0.335795f,0.941914f,0.00633015f, +-0.354719f,0.934449f,0.0312872f, +-0.552854f,0.83289f,-0.025441f, +-0.550469f,0.834453f,-0.0259307f, +-0.388185f,0.921529f,-0.00983026f, +-0.282899f,0.957493f,-0.056358f, +-0.256814f,0.955751f,-0.143483f, +-0.0731312f,0.996697f,-0.0353254f, +0.211397f,0.967055f,0.141832f, +0.27554f,0.960583f,0.0368595f, +0.217196f,0.959783f,-0.177882f, +0.479261f,0.875236f,-0.0653524f, +0.513664f,0.856169f,0.0558883f, +0.446145f,0.882397f,0.149434f, +0.498219f,0.84712f,0.184837f, +0.503236f,0.827823f,0.247916f, +0.51285f,0.815024f,0.269666f, +0.506381f,0.824734f,0.251778f, +0.333663f,0.940706f,0.0611746f, +0.353215f,0.932965f,-0.069389f, +0.414309f,0.904024f,-0.105298f, +0.451897f,0.886486f,-0.0996557f, +0.345824f,0.933767f,-0.0921138f, +0.280994f,0.95917f,0.0321915f, +0.317081f,0.945948f,0.0681282f, +0.344866f,0.938141f,0.0309596f, +0.224406f,0.974203f,0.0238892f, +-0.0108486f,0.995761f,-0.0913323f, +-0.00158176f,0.998953f,-0.0457292f, +-0.115676f,0.985559f,-0.123663f, +-0.188171f,0.911466f,0.365816f, +-0.262724f,0.896783f,0.356029f, +-0.358149f,0.883197f,0.302807f, +-0.323424f,0.894918f,0.307438f, +-0.242922f,0.924564f,0.293548f, +-0.121147f,0.94907f,0.290844f, +-0.0341414f,0.951299f,0.306374f, +-0.132493f,0.945016f,0.298983f, +-0.194216f,0.905093f,0.378268f, +-0.212944f,0.914784f,0.343257f, +-0.127802f,0.956235f,0.263215f, +0.0483659f,0.968777f,0.243172f, +0.117573f,0.942608f,0.312517f, +0.164225f,0.89741f,0.409494f, +0.122313f,0.88201f,0.455081f, +0.101965f,0.875392f,0.472537f, +0.209339f,0.879095f,0.428217f, +0.174899f,0.892224f,0.416349f, +-0.060088f,0.941634f,0.331231f, +-0.120508f,0.975773f,0.182606f, +0.112168f,0.972734f,0.202994f, +0.117253f,0.950933f,0.286318f, +-0.0544328f,0.941394f,0.332887f, +-0.0790068f,0.915303f,0.394942f, +-0.127609f,0.917525f,0.376648f, +-0.0756868f,0.941409f,0.328666f, +-0.0332439f,0.958716f,0.282415f, +-0.0735168f,0.965505f,0.249792f, +-0.203882f,0.964791f,0.166163f, +-0.320453f,0.94269f,0.0929826f, +-0.471247f,0.881185f,0.0379224f, +-0.492278f,0.869051f,0.0491152f, +-0.532259f,0.846256f,-0.0234739f, +-0.499446f,0.866138f,-0.0189645f, +-0.373407f,0.92679f,-0.0403466f, +-0.352534f,0.935772f,-0.00715155f, +-0.527726f,0.848793f,-0.0324855f, +-0.520812f,0.852354f,-0.0474108f, +-0.409147f,0.909436f,-0.0743255f, +-0.294722f,0.955583f,0.000817458f, +-0.222255f,0.974321f,0.0360744f, +-0.14278f,0.989739f,0.00545783f, +0.112175f,0.992761f,0.0429195f, +0.349968f,0.931754f,0.0967357f, +0.338116f,0.939385f,0.056869f, +0.379594f,0.923814f,0.0497667f, +0.434257f,0.879279f,0.195674f, +0.391146f,0.89525f,0.213383f, +0.465582f,0.860371f,0.207352f, +0.429826f,0.860017f,0.274991f, +0.465148f,0.815034f,0.34548f, +0.575943f,0.73808f,0.351465f, +0.535537f,0.824709f,0.181813f, +0.414278f,0.908562f,-0.0537569f, +0.380258f,0.913027f,-0.147599f, +0.408447f,0.90132f,-0.144197f, +0.367806f,0.925659f,-0.0887431f, +0.142987f,0.986995f,-0.073455f, +0.215691f,0.972786f,0.0846483f, +0.373384f,0.916381f,0.144331f, +0.381582f,0.918997f,0.0991966f, +0.0727073f,0.993287f,-0.0899678f, +-0.0658262f,0.992454f,-0.103446f, +0.0138596f,0.999564f,-0.0260736f, +-0.215981f,0.852322f,0.47634f, +-0.206677f,0.845053f,0.493123f, +-0.272991f,0.879681f,0.389406f, +-0.267376f,0.924267f,0.272471f, +-0.22026f,0.956955f,0.189003f, +-0.175208f,0.966589f,0.187106f, +-0.043064f,0.959071f,0.279872f, +-0.116589f,0.955061f,0.272519f, +-0.310776f,0.922421f,0.229257f, +-0.169995f,0.929299f,0.32788f, +-0.0175005f,0.941141f,0.337561f, +0.0138751f,0.95035f,0.310874f, +-0.0519487f,0.924056f,0.37871f, +0.0171204f,0.875115f,0.483613f, +0.148666f,0.835016f,0.529761f, +0.187668f,0.864969f,0.465412f, +0.241037f,0.89408f,0.377521f, +0.22255f,0.900707f,0.373093f, +0.0517034f,0.945752f,0.320749f, +-0.0271248f,0.957046f,0.288665f, +0.0325916f,0.970401f,0.239289f, +0.0171507f,0.960836f,0.276588f, +-0.143534f,0.9275f,0.345169f, +-0.0983366f,0.916766f,0.38713f, +-0.0476997f,0.944806f,0.32414f, +-0.0337303f,0.946895f,0.319767f, +-0.0100366f,0.942379f,0.334396f, +-0.0544901f,0.938102f,0.342046f, +-0.14598f,0.916868f,0.371541f, +-0.23743f,0.904478f,0.354324f, +-0.411826f,0.87795f,0.244136f, +-0.481531f,0.866693f,0.130273f, +-0.469337f,0.874903f,0.119446f, +-0.452816f,0.890509f,0.0441746f, +-0.332275f,0.942324f,-0.0402274f, +-0.391441f,0.91825f,-0.0599172f, +-0.492183f,0.870395f,0.0129854f, +-0.540952f,0.839903f,-0.0439814f, +-0.452633f,0.891182f,0.0302916f, +-0.353037f,0.931758f,0.0848037f, +-0.230998f,0.971043f,0.0609518f, +-0.110559f,0.993184f,0.0368984f, +0.0985994f,0.994896f,-0.0214387f, +0.290703f,0.956813f,-0.000841556f, +0.306742f,0.941069f,0.142471f, +0.309512f,0.928678f,0.20435f, +0.393276f,0.890035f,0.23059f, +0.472781f,0.864565f,0.170309f, +0.455511f,0.888755f,0.0512287f, +0.387199f,0.912459f,0.13227f, +0.420125f,0.891345f,0.170293f, +0.568557f,0.791084f,0.225676f, +0.642678f,0.725845f,0.245181f, +0.61301f,0.785525f,0.0846683f, +0.519083f,0.833826f,-0.187849f, +0.390386f,0.832025f,-0.394123f, +0.254733f,0.897839f,-0.359161f, +0.0968538f,0.955535f,-0.278518f, +0.110338f,0.951183f,-0.288231f, +0.337547f,0.917961f,-0.20835f, +0.382401f,0.916771f,-0.115327f, +0.232755f,0.967238f,-0.101374f, +-0.075544f,0.963631f,-0.256338f, +-0.111861f,0.963998f,-0.241238f, +-0.403631f,0.823611f,0.398431f, +-0.211285f,0.853176f,0.476917f, +-0.0996818f,0.887327f,0.450237f, +-0.119017f,0.926423f,0.357178f, +-0.147962f,0.959424f,0.240027f, +-0.17904f,0.969453f,0.167646f, +-0.182698f,0.967757f,0.173402f, +-0.0875162f,0.935774f,0.341566f, +-0.247354f,0.926662f,0.283043f, +-0.269706f,0.932828f,0.238937f, +-0.116046f,0.932011f,0.34335f, +-0.054572f,0.895119f,0.442474f, +-0.0702883f,0.870311f,0.487462f, +-0.0238769f,0.872685f,0.4877f, +0.145141f,0.847062f,0.511292f, +0.26226f,0.839585f,0.475728f, +0.307436f,0.859155f,0.409067f, +0.272452f,0.896089f,0.35042f, +0.0602872f,0.949936f,0.306572f, +-0.0269541f,0.950357f,0.309992f, +0.110161f,0.964193f,0.241239f, +0.0112822f,0.980274f,0.19732f, +-0.201697f,0.957263f,0.207282f, +-0.0780713f,0.964435f,0.252529f, +0.00973745f,0.973101f,0.230172f, +-0.0755968f,0.981149f,0.177855f, +-0.0876613f,0.97114f,0.221817f, +-0.111729f,0.927016f,0.357991f, +-0.221124f,0.882386f,0.41533f, +-0.204491f,0.867297f,0.45385f, +-0.238609f,0.89578f,0.375026f, +-0.38933f,0.904206f,0.175592f, +-0.447525f,0.889442f,0.0928077f, +-0.421271f,0.9063f,0.0339399f, +-0.295839f,0.951557f,0.0837779f, +-0.40469f,0.90695f,0.116906f, +-0.500893f,0.852054f,0.152018f, +-0.539765f,0.838827f,0.0708671f, +-0.497421f,0.864837f,0.068037f, +-0.338953f,0.937284f,0.0813017f, +-0.178116f,0.975677f,0.127782f, +-0.0428295f,0.992057f,0.118272f, +0.176596f,0.983706f,0.0336999f, +0.217356f,0.975284f,-0.0397137f, +0.172156f,0.984981f,0.0131952f, +0.279801f,0.958586f,0.0531518f, +0.429228f,0.901897f,0.0484305f, +0.537427f,0.843269f,0.00840869f, +0.461159f,0.886671f,-0.0338697f, +0.347666f,0.937337f,0.022966f, +0.390524f,0.920568f,0.00669632f, +0.544615f,0.837115f,0.0513162f, +0.64737f,0.75903f,0.0691749f, +0.709483f,0.698136f,0.0961199f, +0.69002f,0.723355f,-0.0250988f, +0.510759f,0.819636f,-0.259464f, +0.161066f,0.87948f,-0.447854f, +0.0742832f,0.901252f,-0.426881f, +0.164688f,0.896506f,-0.411284f, +0.211827f,0.873436f,-0.43845f, +0.238498f,0.898773f,-0.367868f, +0.244991f,0.941894f,-0.229815f, +0.0339169f,0.959887f,-0.278328f, +-0.150927f,0.928909f,-0.338156f, +-0.262269f,0.839002f,0.47675f, +-0.199453f,0.89484f,0.39935f, +-0.0695117f,0.920513f,0.384478f, +-0.0794509f,0.922822f,0.376943f, +-0.0384813f,0.923599f,0.381424f, +-0.0906334f,0.946866f,0.308593f, +-0.231342f,0.940055f,0.250554f, +-0.228342f,0.910605f,0.344468f, +-0.168052f,0.897027f,0.408779f, +-0.249241f,0.920512f,0.300892f, +-0.201125f,0.932701f,0.29936f, +-0.156169f,0.918655f,0.362882f, +-0.101964f,0.881359f,0.461314f, +-0.0479674f,0.88379f,0.465418f, +0.160937f,0.878499f,0.449821f, +0.298148f,0.878819f,0.372539f, +0.363972f,0.843945f,0.394059f, +0.330687f,0.867316f,0.372033f, +0.109951f,0.941418f,0.318814f, +0.0530775f,0.967978f,0.245361f, +0.171035f,0.972595f,0.157499f, +0.0211384f,0.985036f,0.171048f, +-0.223743f,0.958122f,0.178723f, +-0.143003f,0.966115f,0.214875f, +0.0335442f,0.969798f,0.24159f, +0.00108957f,0.977785f,0.209606f, +-0.185748f,0.96522f,0.183978f, +-0.245345f,0.928456f,0.278881f, +-0.278935f,0.920412f,0.273928f, +-0.227379f,0.922009f,0.313367f, +-0.127558f,0.911679f,0.390603f, +-0.252363f,0.916101f,0.311563f, +-0.353299f,0.912723f,0.205222f, +-0.418007f,0.90407f,0.089031f, +-0.400603f,0.906481f,0.133452f, +-0.448512f,0.870078f,0.204452f, +-0.467166f,0.869433f,0.160757f, +-0.442544f,0.892618f,0.0859534f, +-0.465336f,0.885122f,-0.00451183f, +-0.389888f,0.920791f,0.0114409f, +-0.26105f,0.96208f,0.079086f, +-0.0611649f,0.990413f,0.123862f, +0.218817f,0.959555f,0.177126f, +0.289447f,0.944291f,0.156638f, +0.238555f,0.970242f,0.0415028f, +0.303951f,0.946528f,-0.108164f, +0.431424f,0.894504f,-0.117199f, +0.527248f,0.845956f,-0.0797999f, +0.433918f,0.900916f,0.0081213f, +0.311993f,0.948885f,0.0477355f, +0.430547f,0.901487f,0.0441572f, +0.533619f,0.845624f,-0.013065f, +0.634808f,0.772557f,-0.013228f, +0.691864f,0.721963f,0.00965866f, +0.719067f,0.694383f,0.0278453f, +0.653183f,0.756562f,0.0310991f, +0.386363f,0.918778f,-0.0810638f, +0.0570874f,0.970389f,-0.234704f, +0.136394f,0.961794f,-0.237379f, +0.31236f,0.906525f,-0.283977f, +0.169471f,0.890916f,-0.421365f, +0.117142f,0.913195f,-0.390323f, +0.0777866f,0.931625f,-0.354998f, +-0.0437682f,0.92941f,-0.366443f, +-0.144429f,0.859889f,0.489623f, +-0.0880742f,0.890372f,0.446633f, +-0.0314378f,0.923882f,0.381384f, +-0.0838814f,0.944139f,0.318693f, +-0.0693885f,0.945887f,0.316991f, +-0.0723769f,0.923178f,0.377496f, +-0.19706f,0.892458f,0.405815f, +-0.297386f,0.892332f,0.339566f, +-0.156962f,0.91638f,0.368254f, +-0.15276f,0.919794f,0.361447f, +-0.17017f,0.922781f,0.345714f, +-0.253151f,0.920843f,0.296586f, +-0.189094f,0.905109f,0.380816f, +0.00126887f,0.929197f,0.369582f, +0.193396f,0.936415f,0.292787f, +0.338227f,0.878943f,0.336247f, +0.32269f,0.878938f,0.351198f, +0.355444f,0.867037f,0.34915f, +0.217316f,0.918786f,0.329554f, +0.123007f,0.956146f,0.265807f, +0.19987f,0.950731f,0.236986f, +0.0209731f,0.979076f,0.202411f, +-0.247784f,0.961065f,0.122302f, +-0.158935f,0.979718f,0.122036f, +0.0602949f,0.986043f,0.155188f, +-0.0308065f,0.985867f,0.164674f, +-0.185866f,0.954971f,0.231267f, +-0.272851f,0.942767f,0.191682f, +-0.226832f,0.938998f,0.258516f, +-0.311155f,0.923351f,0.224958f, +-0.264965f,0.917378f,0.297004f, +-0.186536f,0.890461f,0.41507f, +-0.257136f,0.895376f,0.363569f, +-0.330368f,0.897563f,0.291955f, +-0.415623f,0.888172f,0.19598f, +-0.414839f,0.89462f,0.166025f, +-0.429244f,0.901932f,0.0476213f, +-0.370358f,0.92848f,0.0275516f, +-0.456696f,0.886215f,-0.0777874f, +-0.424934f,0.901633f,-0.0805556f, +-0.26755f,0.960865f,-0.0718042f, +-0.0958709f,0.992595f,-0.0745981f, +0.0853594f,0.996177f,0.0185983f, +0.317006f,0.925486f,0.207323f, +0.362438f,0.919121f,0.154455f, +0.423147f,0.903697f,0.0654098f, +0.439077f,0.898135f,-0.0237805f, +0.463592f,0.885685f,-0.0253961f, +0.432904f,0.900567f,0.0396714f, +0.274262f,0.960561f,-0.0458644f, +0.460874f,0.887433f,0.00757752f, +0.557878f,0.824691f,-0.0930446f, +0.608392f,0.791916f,-0.0522232f, +0.68605f,0.722282f,0.0874302f, +0.697187f,0.705867f,0.125228f, +0.597474f,0.77589f,0.202532f, +0.400677f,0.868028f,0.293233f, +0.18602f,0.951589f,0.244694f, +0.190924f,0.979879f,0.0581851f, +0.431268f,0.902043f,-0.01807f, +0.329374f,0.934061f,-0.137997f, +0.144406f,0.935772f,-0.321679f, +0.0779514f,0.92222f,-0.378727f, +-0.0417532f,0.914206f,-0.403093f, +-0.201619f,0.929423f,0.309066f, +-0.0738258f,0.948242f,0.308847f, +0.0288118f,0.952024f,0.304665f, +-0.00526808f,0.951397f,0.307922f, +-0.0992485f,0.952014f,0.289515f, +-0.179425f,0.914994f,0.361376f, +-0.223397f,0.866943f,0.445538f, +-0.185005f,0.868122f,0.460584f, +-0.180405f,0.90051f,0.395646f, +-0.165976f,0.891215f,0.422122f, +-0.142635f,0.91411f,0.37955f, +-0.196593f,0.942079f,0.271733f, +-0.231892f,0.955708f,0.181242f, +0.0754625f,0.968764f,0.236224f, +0.189929f,0.95814f,0.214232f, +0.245783f,0.922809f,0.29667f, +0.350212f,0.885135f,0.30641f, +0.361791f,0.894635f,0.262174f, +0.218601f,0.892888f,0.393656f, +0.122578f,0.888731f,0.441737f, +0.221602f,0.877963f,0.42435f, +0.113111f,0.927784f,0.355561f, +-0.0962286f,0.967788f,0.232652f, +-0.169743f,0.984124f,0.0518298f, +0.00440837f,0.997134f,0.0755295f, +-0.0780505f,0.992255f,0.096638f, +-0.206915f,0.971074f,0.119173f, +-0.298261f,0.946469f,0.123437f, +-0.365054f,0.904843f,0.219077f, +-0.255666f,0.897337f,0.35975f, +-0.290965f,0.914197f,0.282104f, +-0.292271f,0.916518f,0.27308f, +-0.219619f,0.919339f,0.326472f, +-0.256286f,0.928086f,0.270137f, +-0.310598f,0.93305f,0.18151f, +-0.350728f,0.934452f,0.0615507f, +-0.388138f,0.92156f,0.00876308f, +-0.343471f,0.93847f,0.0360903f, +-0.339947f,0.939272f,-0.0469463f, +-0.382902f,0.903055f,-0.19462f, +-0.249239f,0.929446f,-0.272047f, +-0.147764f,0.944907f,-0.29209f, +-0.0668186f,0.978447f,-0.19539f, +0.17553f,0.981686f,-0.0740426f, +0.388973f,0.921211f,-0.00833323f, +0.44678f,0.894539f,-0.0136777f, +0.47739f,0.878112f,-0.0318964f, +0.465567f,0.884409f,-0.0326842f, +0.484387f,0.873859f,-0.0417148f, +0.315003f,0.932104f,-0.178762f, +0.426472f,0.898104f,-0.107381f, +0.587094f,0.80929f,-0.0192587f, +0.491946f,0.869904f,0.0354452f, +0.550379f,0.808299f,0.209131f, +0.597166f,0.706874f,0.379107f, +0.503286f,0.706664f,0.497322f, +0.349603f,0.761935f,0.545191f, +0.317931f,0.791281f,0.522298f, +0.357034f,0.859818f,0.365021f, +0.457671f,0.859336f,0.22821f, +0.436038f,0.880267f,0.187085f, +0.291237f,0.949467f,0.117016f, +0.172846f,0.983353f,0.0560389f, +0.00924155f,0.999014f,-0.043417f, +-0.112379f,0.966854f,0.22927f, +-0.0543436f,0.980353f,0.189616f, +0.0014105f,0.977032f,0.213089f, +-0.0810261f,0.954455f,0.287143f, +-0.162384f,0.905883f,0.391161f, +-0.248623f,0.850337f,0.463803f, +-0.272281f,0.829594f,0.48748f, +-0.210534f,0.842738f,0.495447f, +-0.142516f,0.845822f,0.514076f, +-0.128959f,0.864859f,0.485168f, +-0.000520612f,0.895905f,0.444245f, +0.00320439f,0.940529f,0.339698f, +-0.169376f,0.979765f,0.106637f, +-0.0517963f,0.994886f,0.0867084f, +0.124214f,0.955178f,0.268711f, +0.208945f,0.916166f,0.342027f, +0.39407f,0.858275f,0.328745f, +0.248342f,0.913565f,0.322063f, +0.031165f,0.861455f,0.506877f, +0.0654094f,0.812115f,0.57982f, +0.246891f,0.786687f,0.565834f, +0.230643f,0.834381f,0.500612f, +0.069509f,0.924157f,0.375637f, +0.0080049f,0.977951f,0.208681f, +-0.0216545f,0.998818f,0.043521f, +-0.0416834f,0.994806f,0.0928633f, +-0.209164f,0.977378f,0.0313447f, +-0.33727f,0.941399f,0.00405643f, +-0.445763f,0.895148f,-0.00236945f, +-0.379089f,0.924127f,0.0477591f, +-0.212534f,0.958583f,0.189598f, +-0.289703f,0.944216f,0.156615f, +-0.225857f,0.954875f,0.19288f, +-0.19812f,0.968114f,0.153308f, +-0.225491f,0.970896f,0.0807165f, +-0.268028f,0.963292f,-0.0151842f, +-0.386115f,0.917249f,-0.0978197f, +-0.332792f,0.935954f,-0.115065f, +-0.223332f,0.957817f,-0.180856f, +-0.272615f,0.913397f,-0.302304f, +-0.182015f,0.92061f,-0.345468f, +-0.156497f,0.91949f,-0.36062f, +-0.125465f,0.931751f,-0.340733f, +0.1054f,0.935905f,-0.336114f, +0.348771f,0.906917f,-0.236346f, +0.444797f,0.880373f,-0.164617f, +0.451025f,0.885434f,-0.112171f, +0.467976f,0.880983f,-0.0697667f, +0.499335f,0.858868f,-0.114062f, +0.349601f,0.930335f,-0.110707f, +0.307802f,0.944888f,-0.11156f, +0.473394f,0.878106f,0.0694821f, +0.43441f,0.869457f,0.23523f, +0.41901f,0.855868f,0.303184f, +0.452664f,0.775597f,0.439937f, +0.432369f,0.72522f,0.535829f, +0.415514f,0.737038f,0.533032f, +0.381011f,0.793693f,0.474217f, +0.445314f,0.773558f,0.450892f, +0.520117f,0.767192f,0.375359f, +0.457464f,0.838846f,0.295064f, +0.276432f,0.924946f,0.260884f, +0.199394f,0.937964f,0.283664f, +0.190897f,0.927436f,0.32159f, +-0.0705492f,0.959049f,0.274315f, +-0.0655623f,0.961527f,0.266772f, +-0.0518964f,0.943387f,0.32761f, +-0.202287f,0.906319f,0.371032f, +-0.245861f,0.842829f,0.478739f, +-0.310342f,0.836362f,0.451869f, +-0.256381f,0.850522f,0.459219f, +-0.198762f,0.867072f,0.456815f, +-0.12379f,0.863897f,0.48822f, +-0.0469651f,0.900623f,0.432056f, +-8.11553e-005f,0.943721f,0.330744f, +0.129628f,0.925055f,0.357028f, +0.0340614f,0.966037f,0.256151f, +-0.0890995f,0.983963f,0.154524f, +-0.0322587f,0.981394f,0.189278f, +0.138447f,0.956229f,0.257794f, +0.317932f,0.883665f,0.343592f, +0.154174f,0.859961f,0.486516f, +-0.0823702f,0.837125f,0.540774f, +0.067942f,0.838652f,0.540413f, +0.256779f,0.806501f,0.532561f, +0.317316f,0.771073f,0.552047f, +0.228943f,0.837474f,0.496208f, +0.221417f,0.908583f,0.354192f, +0.0661321f,0.986936f,0.146917f, +-0.101631f,0.981129f,0.164493f, +-0.140334f,0.967949f,0.20828f, +-0.26644f,0.954208f,0.136f, +-0.376833f,0.92539f,0.0406146f, +-0.423125f,0.902479f,-0.0805992f, +-0.378547f,0.924929f,-0.0347556f, +-0.294214f,0.950388f,0.101004f, +-0.253707f,0.966868f,0.0282789f, +-0.1425f,0.989661f,0.0162607f, +-0.152778f,0.987285f,-0.0438961f, +-0.226417f,0.971142f,-0.0749508f, +-0.278106f,0.959626f,-0.0421373f, +-0.315252f,0.936348f,-0.154492f, +-0.13807f,0.983353f,-0.118124f, +-0.169891f,0.968928f,-0.179762f, +-0.200272f,0.947942f,-0.247583f, +-0.182846f,0.93983f,-0.288594f, +-0.0836086f,0.941177f,-0.327408f, +0.0732417f,0.918516f,-0.388542f, +0.208177f,0.929929f,-0.303139f, +0.350352f,0.926406f,-0.137933f, +0.401951f,0.914196f,-0.0517823f, +0.448456f,0.893661f,-0.0160636f, +0.515556f,0.856358f,0.0291996f, +0.347689f,0.937245f,0.0261378f, +0.255909f,0.965329f,0.0514824f, +0.382053f,0.909938f,0.161395f, +0.340926f,0.922929f,0.178808f, +0.312845f,0.910786f,0.269439f, +0.364196f,0.849776f,0.381106f, +0.45928f,0.814969f,0.353394f, +0.52951f,0.800019f,0.282116f, +0.449914f,0.855375f,0.256731f, +0.454599f,0.838858f,0.299428f, +0.555327f,0.766362f,0.322957f, +0.54417f,0.781393f,0.305455f, +0.357615f,0.911759f,0.202005f, +0.139813f,0.972952f,0.183891f, +0.109083f,0.950848f,0.289808f, +-0.192892f,0.944314f,0.266579f, +-0.117537f,0.919218f,0.375796f, +-0.132138f,0.875254f,0.465263f, +-0.253971f,0.812679f,0.524453f, +-0.263136f,0.777105f,0.571723f, +-0.18663f,0.797568f,0.573633f, +-0.239071f,0.855961f,0.458449f, +-0.228946f,0.872463f,0.431732f, +-0.154745f,0.876861f,0.455159f, +0.0511929f,0.876307f,0.479025f, +0.079622f,0.902874f,0.422468f, +0.0999946f,0.903351f,0.417083f, +0.103272f,0.908778f,0.404299f, +-0.0300958f,0.943633f,0.329622f, +-0.0276233f,0.954592f,0.296632f, +0.0865379f,0.944508f,0.316884f, +0.19572f,0.915809f,0.350694f, +0.0629871f,0.902785f,0.425456f, +-0.0973105f,0.893058f,0.439293f, +0.0850344f,0.884912f,0.45793f, +0.226219f,0.859273f,0.458775f, +0.265876f,0.822998f,0.50198f, +0.299522f,0.800365f,0.519329f, +0.365936f,0.804413f,0.467986f, +0.167843f,0.908094f,0.383659f, +-0.151292f,0.923022f,0.353753f, +-0.16349f,0.897488f,0.409618f, +-0.164454f,0.89713f,0.410016f, +-0.256833f,0.931773f,0.256583f, +-0.308509f,0.944441f,0.11337f, +-0.397192f,0.916896f,-0.0392391f, +-0.321804f,0.945652f,-0.046751f, +-0.145617f,0.989197f,-0.0168656f, +-0.117605f,0.989571f,-0.083174f, +-0.131213f,0.988938f,-0.0691672f, +-0.264465f,0.964357f,-0.00857016f, +-0.279285f,0.95849f,0.0574115f, +-0.308064f,0.950873f,-0.0306128f, +-0.232189f,0.97071f,0.0617333f, +-0.126956f,0.977263f,0.169823f, +-0.134913f,0.981643f,0.134817f, +-0.0643092f,0.996192f,0.0588766f, +-0.0179518f,0.989177f,-0.145623f, +0.100718f,0.978365f,-0.180716f, +0.107842f,0.981772f,-0.156502f, +0.235537f,0.96668f,-0.100264f, +0.400696f,0.915349f,-0.0397433f, +0.382123f,0.921514f,-0.0692327f, +0.451191f,0.890657f,0.0561954f, +0.368356f,0.915308f,0.162865f, +0.16123f,0.974745f,0.154523f, +0.326647f,0.914341f,0.239337f, +0.365189f,0.91282f,0.182749f, +0.230086f,0.959458f,0.162792f, +0.336546f,0.918886f,0.205876f, +0.545838f,0.824177f,0.150977f, +0.544526f,0.829407f,0.124801f, +0.442013f,0.862414f,0.24671f, +0.417167f,0.87901f,0.230894f, +0.525918f,0.823184f,0.213956f, +0.591278f,0.763502f,0.259719f, +0.412761f,0.877728f,0.243355f, +0.079495f,0.961838f,0.261818f, +-0.108191f,0.959339f,0.260698f, +-0.395968f,0.898347f,0.190215f, +-0.315805f,0.885393f,0.341095f, +-0.255081f,0.831656f,0.493236f, +-0.32798f,0.786298f,0.523607f, +-0.31899f,0.766541f,0.557369f, +-0.160414f,0.763167f,0.625974f, +-0.0711111f,0.771377f,0.632393f, +-0.143173f,0.825852f,0.545409f, +-0.172278f,0.854223f,0.490534f, +0.0123154f,0.838365f,0.544971f, +0.0830743f,0.830631f,0.550592f, +0.0507686f,0.835031f,0.547855f, +0.149519f,0.800804f,0.579962f, +0.0893025f,0.847618f,0.523038f, +-0.0238205f,0.893087f,0.449253f, +0.0209713f,0.900623f,0.434095f, +0.182588f,0.867377f,0.462945f, +0.0933756f,0.88802f,0.450223f, +-0.0988317f,0.917919f,0.384262f, +0.0323919f,0.922001f,0.38583f, +0.205498f,0.882674f,0.422678f, +0.228981f,0.875897f,0.424702f, +0.330967f,0.833446f,0.442526f, +0.386545f,0.82285f,0.416534f, +0.244254f,0.85459f,0.458275f, +-0.128515f,0.915454f,0.381351f, +-0.221592f,0.919582f,0.324447f, +-0.103305f,0.941351f,0.321226f, +-0.0534104f,0.960954f,0.271504f, +-0.164863f,0.980806f,0.104112f, +-0.239884f,0.970598f,-0.0198681f, +-0.303213f,0.937604f,-0.170178f, +-0.252015f,0.951441f,-0.176773f, +-0.108694f,0.994072f,0.00232095f, +-0.192935f,0.981013f,0.0197642f, +-0.322908f,0.946132f,0.0237552f, +-0.269028f,0.963107f,-0.00704542f, +-0.230013f,0.973161f,0.00722315f, +-0.357365f,0.933662f,-0.0237822f, +-0.204315f,0.973479f,0.102922f, +-0.115797f,0.983778f,0.137007f, +0.0200406f,0.991033f,0.132107f, +0.176509f,0.981212f,0.0778953f, +0.102914f,0.991977f,-0.0734239f, +0.103634f,0.990563f,-0.0896973f, +0.246302f,0.962545f,-0.113327f, +0.365449f,0.921945f,-0.12831f, +0.388572f,0.919102f,-0.0652967f, +0.33675f,0.940592f,-0.0434361f, +0.294334f,0.951251f,0.0921318f, +0.170376f,0.973956f,0.149605f, +0.291052f,0.946977f,0.136102f, +0.448607f,0.879963f,0.156258f, +0.275208f,0.960522f,0.0407201f, +0.320727f,0.94717f,-0.00171267f, +0.563867f,0.822582f,0.0735748f, +0.458264f,0.882692f,0.104155f, +0.35932f,0.917336f,0.171414f, +0.473577f,0.85831f,0.197555f, +0.552768f,0.818756f,0.155195f, +0.56022f,0.811568f,0.165865f, +0.410483f,0.877955f,0.246373f, +0.119318f,0.965792f,0.230239f, +-0.0302464f,0.98755f,0.15437f, +-0.434902f,0.821345f,0.369123f, +-0.425801f,0.804682f,0.41374f, +-0.330648f,0.807018f,0.489278f, +-0.341863f,0.793213f,0.503928f, +-0.356504f,0.786512f,0.504286f, +-0.269874f,0.813284f,0.515498f, +-0.0937663f,0.786137f,0.610898f, +-0.0122488f,0.782782f,0.622176f, +-0.145176f,0.838097f,0.525849f, +-0.0659853f,0.863648f,0.499758f, +0.0911511f,0.81559f,0.571406f, +0.0567409f,0.801208f,0.59569f, +0.110855f,0.801019f,0.588286f, +0.153854f,0.799367f,0.580811f, +0.0810561f,0.837494f,0.540401f, +0.0627084f,0.873537f,0.482702f, +0.153028f,0.87118f,0.466506f, +0.121758f,0.869515f,0.478663f, +-0.0139367f,0.889364f,0.456987f, +0.0116753f,0.909652f,0.415206f, +0.182976f,0.873078f,0.451946f, +0.230254f,0.874104f,0.427698f, +0.299542f,0.853577f,0.42624f, +0.365816f,0.815944f,0.447677f, +0.258135f,0.828321f,0.497243f, +0.0438733f,0.899999f,0.433678f, +-0.113551f,0.976415f,0.183628f, +-0.115165f,0.991964f,0.0523877f, +-0.0427249f,0.989973f,0.134639f, +-0.000526251f,0.987641f,0.156735f, +-0.182878f,0.982656f,-0.0306907f, +-0.187196f,0.982029f,-0.0240342f, +-0.272847f,0.956238f,-0.105656f, +-0.292658f,0.95046f,-0.104775f, +-0.178909f,0.983865f,0.00116467f, +-0.22078f,0.973898f,-0.0527095f, +-0.269354f,0.950491f,-0.154966f, +-0.262457f,0.956005f,-0.131038f, +-0.333574f,0.929233f,-0.158915f, +-0.27846f,0.93913f,-0.201231f, +-0.105722f,0.98028f,-0.166954f, +-0.03086f,0.983393f,-0.178845f, +0.166296f,0.985117f,-0.0434662f, +0.22991f,0.973119f,0.0134671f, +0.156605f,0.983722f,-0.0881293f, +0.276714f,0.94824f,-0.155787f, +0.32696f,0.929339f,-0.171541f, +0.339039f,0.938238f,-0.0690071f, +0.308789f,0.948131f,-0.0754727f, +0.23717f,0.967343f,-0.0894326f, +0.163558f,0.982662f,-0.0873214f, +0.252735f,0.966333f,-0.0482272f, +0.434287f,0.896865f,0.0838305f, +0.398093f,0.912104f,0.0979158f, +0.320154f,0.94669f,-0.0357668f, +0.45783f,0.889003f,0.00810452f, +0.504235f,0.85135f,0.144742f, +0.385352f,0.920157f,0.0693918f, +0.466232f,0.882239f,0.0654287f, +0.538345f,0.833943f,0.121343f, +0.517827f,0.838051f,0.171829f, +0.46128f,0.862173f,0.209471f, +0.229103f,0.969676f,0.085091f, +0.119821f,0.992172f,0.0351865f, +-0.316654f,0.75101f,0.579409f, +-0.356062f,0.779142f,0.515904f, +-0.357471f,0.814286f,0.457331f, +-0.357809f,0.798452f,0.484198f, +-0.344344f,0.806376f,0.480818f, +-0.279175f,0.813317f,0.510467f, +-0.188283f,0.817533f,0.544233f, +0.0108927f,0.825394f,0.564451f, +0.000505664f,0.854739f,0.519058f, +-0.0291193f,0.899152f,0.436667f, +-0.043893f,0.902469f,0.428513f, +-0.00142614f,0.854428f,0.519568f, +0.10644f,0.82426f,0.556117f, +0.17821f,0.772022f,0.610101f, +0.155558f,0.792656f,0.58949f, +0.103298f,0.851042f,0.514837f, +0.136998f,0.86222f,0.487656f, +0.128814f,0.846529f,0.516522f, +0.0086465f,0.861582f,0.507544f, +0.0126115f,0.865086f,0.501464f, +0.152876f,0.854998f,0.495588f, +0.261992f,0.846686f,0.463122f, +0.298132f,0.855648f,0.423065f, +0.330245f,0.846388f,0.417811f, +0.241868f,0.85891f,0.451412f, +0.243399f,0.870337f,0.428102f, +0.218863f,0.950296f,0.221442f, +-0.0230145f,0.994562f,-0.101567f, +-0.18143f,0.968994f,-0.167732f, +-0.00536077f,0.999859f,-0.0158957f, +-0.0149312f,0.999841f,-0.00972481f, +-0.248945f,0.961384f,-0.11733f, +-0.206226f,0.978121f,-0.0273758f, +-0.251569f,0.958037f,-0.137399f, +-0.215501f,0.957565f,-0.191386f, +-0.183194f,0.972176f,-0.145991f, +-0.242363f,0.956164f,-0.164351f, +-0.223675f,0.959477f,-0.171387f, +-0.263678f,0.929229f,-0.25886f, +-0.190809f,0.923444f,-0.332932f, +-0.125476f,0.902264f,-0.412524f, +-0.0800599f,0.931052f,-0.355994f, +0.00289679f,0.952892f,-0.303297f, +0.173027f,0.965415f,-0.195025f, +0.23552f,0.951626f,-0.197328f, +0.324166f,0.90746f,-0.26727f, +0.272213f,0.920502f,-0.280314f, +0.263103f,0.942676f,-0.205278f, +0.331376f,0.931643f,-0.1491f, +0.273621f,0.957062f,-0.0957296f, +0.174678f,0.976512f,-0.126141f, +0.162465f,0.97193f,-0.170168f, +0.285207f,0.956722f,-0.0577913f, +0.392887f,0.912166f,0.116586f, +0.413213f,0.901715f,0.127138f, +0.444428f,0.894805f,0.0425078f, +0.482399f,0.875952f,0.000225918f, +0.414394f,0.908379f,-0.0559034f, +0.421361f,0.906852f,-0.00856344f, +0.501069f,0.86151f,0.0820434f, +0.492896f,0.86226f,0.116453f, +0.497628f,0.854344f,0.149874f, +0.327901f,0.939568f,0.0984569f, +0.134608f,0.990256f,0.0356963f, +-0.115732f,0.781457f,0.613132f, +-0.224646f,0.82464f,0.519137f, +-0.330602f,0.837584f,0.434919f, +-0.37055f,0.826801f,0.423193f, +-0.389755f,0.836631f,0.38489f, +-0.35019f,0.83732f,0.419835f, +-0.192063f,0.866433f,0.460875f, +0.0577661f,0.893053f,0.446228f, +0.0715028f,0.909685f,0.409097f, +0.0355467f,0.937027f,0.347443f, +-0.0473295f,0.949618f,0.309815f, +-0.0714543f,0.946618f,0.31434f, +0.0109848f,0.930588f,0.365903f, +0.0306039f,0.876434f,0.480548f, +0.171338f,0.790427f,0.588106f, +0.228263f,0.773415f,0.591376f, +0.15062f,0.839076f,0.522748f, +0.0933237f,0.852392f,0.514508f, +0.0403687f,0.864191f,0.501542f, +0.0159293f,0.89067f,0.454371f, +0.162582f,0.873944f,0.458028f, +0.324998f,0.838057f,0.438219f, +0.361417f,0.861814f,0.355886f, +0.357364f,0.88789f,0.289727f, +0.288052f,0.920034f,0.265637f, +0.274707f,0.932706f,0.233657f, +0.415911f,0.867317f,0.273456f, +0.214502f,0.965967f,0.144559f, +-0.0739208f,0.997262f,-0.00212715f, +-0.130316f,0.972201f,-0.194533f, +0.00262571f,0.981048f,-0.193747f, +-0.190851f,0.93935f,-0.284951f, +-0.250649f,0.92646f,-0.280798f, +-0.16238f,0.957944f,-0.236595f, +-0.204897f,0.9457f,-0.252327f, +-0.246487f,0.945291f,-0.213705f, +-0.204741f,0.966747f,-0.153234f, +-0.173965f,0.952924f,-0.248341f, +-0.185492f,0.924696f,-0.332461f, +-0.120486f,0.929748f,-0.347926f, +-0.0981061f,0.932335f,-0.348033f, +-0.143961f,0.923839f,-0.354678f, +-0.0348514f,0.936175f,-0.349804f, +0.141193f,0.941481f,-0.306069f, +0.298926f,0.908144f,-0.293117f, +0.339558f,0.869399f,-0.35895f, +0.236934f,0.893673f,-0.381064f, +0.188986f,0.916304f,-0.353088f, +0.222126f,0.937284f,-0.268624f, +0.165461f,0.966952f,-0.193976f, +0.194618f,0.975642f,-0.101229f, +0.225585f,0.970105f,-0.0894815f, +0.18757f,0.970367f,-0.152331f, +0.271776f,0.9587f,-0.0838549f, +0.390134f,0.920749f,0.00399703f, +0.487191f,0.870564f,0.0690114f, +0.567845f,0.821826f,0.0464111f, +0.430596f,0.898843f,-0.0816633f, +0.345462f,0.936301f,-0.063213f, +0.439054f,0.898457f,0.0025505f, +0.485886f,0.873093f,0.040301f, +0.468523f,0.882438f,0.0422951f, +0.395695f,0.916215f,0.0630502f, +0.224264f,0.974198f,-0.0253916f, +-0.04074f,0.869731f,0.491842f, +-0.147521f,0.861626f,0.485632f, +-0.290306f,0.828918f,0.47814f, +-0.344291f,0.81826f,0.460342f, +-0.325822f,0.848235f,0.417537f, +-0.347006f,0.892025f,0.289618f, +-0.23289f,0.9484f,0.215175f, +0.0826503f,0.953848f,0.288692f, +0.0849803f,0.942357f,0.323639f, +0.0946367f,0.912864f,0.397143f, +0.0188563f,0.944615f,0.327637f, +-0.0844647f,0.976435f,0.198596f, +-0.0480441f,0.982086f,0.182207f, +-0.108246f,0.969423f,0.220233f, +0.0163534f,0.944153f,0.329102f, +0.218936f,0.864112f,0.453186f, +0.243602f,0.846524f,0.473344f, +0.157715f,0.898021f,0.410713f, +0.124101f,0.930824f,0.343753f, +0.0887369f,0.958556f,0.270731f, +0.13199f,0.965856f,0.222935f, +0.34996f,0.900513f,0.258077f, +0.45204f,0.856515f,0.249081f, +0.434574f,0.879659f,0.19325f, +0.307812f,0.936972f,0.165332f, +0.238408f,0.942387f,0.234669f, +0.292411f,0.883524f,0.365897f, +0.235944f,0.851222f,0.468777f, +0.0834983f,0.888208f,0.45179f, +0.120252f,0.948234f,0.293925f, +0.107426f,0.988487f,0.106553f, +-0.0604958f,0.997925f,0.0220282f, +-0.22861f,0.965114f,-0.127644f, +-0.213845f,0.934088f,-0.285919f, +-0.236679f,0.925441f,-0.295876f, +-0.274282f,0.922231f,-0.272506f, +-0.200442f,0.934584f,-0.293896f, +-0.0905439f,0.955043f,-0.282301f, +-0.107977f,0.974204f,-0.198159f, +-0.176859f,0.954188f,-0.241343f, +-0.109412f,0.961464f,-0.252221f, +-0.0832631f,0.934053f,-0.347292f, +-0.0389646f,0.894623f,-0.44512f, +0.0844722f,0.90285f,-0.421576f, +0.278944f,0.884527f,-0.373902f, +0.405411f,0.845478f,-0.347577f, +0.241979f,0.880406f,-0.407837f, +0.10107f,0.917999f,-0.383487f, +0.153454f,0.950374f,-0.270631f, +0.150056f,0.964994f,-0.215103f, +0.116981f,0.964373f,-0.237277f, +0.171185f,0.966068f,-0.19341f, +0.269303f,0.954896f,-0.1251f, +0.246577f,0.939836f,-0.236448f, +0.325998f,0.915178f,-0.237011f, +0.400262f,0.89707f,-0.18723f, +0.540095f,0.838463f,-0.0726465f, +0.4591f,0.888384f,0.000734802f, +0.350121f,0.936701f,0.00262749f, +0.415959f,0.907987f,-0.0503785f, +0.469999f,0.882626f,-0.00849165f, +0.46759f,0.883776f,0.0172864f, +0.444948f,0.895095f,0.0287648f, +0.38429f,0.923043f,-0.0176926f, +-0.184131f,0.893945f,0.408605f, +-0.22256f,0.84592f,0.484651f, +-0.306803f,0.799127f,0.516979f, +-0.327467f,0.825975f,0.458836f, +-0.215523f,0.873324f,0.43687f, +-0.122358f,0.93676f,0.327886f, +-0.214245f,0.969738f,0.117081f, +0.00165628f,0.984816f,0.173596f, +-0.0471807f,0.97232f,0.228838f, +-0.042786f,0.929182f,0.367137f, +0.159108f,0.885534f,0.43648f, +0.0848362f,0.945025f,0.315803f, +-0.0323525f,0.969808f,0.241716f, +-0.0998895f,0.964402f,0.244849f, +-0.0727123f,0.986494f,0.146772f, +0.121392f,0.97688f,0.175982f, +0.260802f,0.928486f,0.264378f, +0.24004f,0.922405f,0.302572f, +0.162896f,0.94112f,0.296239f, +0.158069f,0.936377f,0.313389f, +0.18876f,0.956613f,0.221947f, +0.312407f,0.939867f,0.138025f, +0.450948f,0.870255f,0.198248f, +0.44762f,0.863366f,0.232885f, +0.235953f,0.935784f,0.261983f, +0.128819f,0.928252f,0.348933f, +0.106701f,0.927182f,0.359094f, +0.172918f,0.882203f,0.437968f, +0.183128f,0.868984f,0.459707f, +0.240959f,0.881259f,0.406597f, +0.154256f,0.918617f,0.363797f, +0.0253035f,0.919137f,0.393124f, +0.0182377f,0.964511f,0.263413f, +0.0263571f,0.99964f,0.00499089f, +-0.149002f,0.961331f,-0.231604f, +-0.264821f,0.912849f,-0.310769f, +-0.139498f,0.954507f,-0.263548f, +-0.253683f,0.93262f,-0.25664f, +-0.265231f,0.9626f,-0.0552561f, +-0.114883f,0.993341f,-0.00868247f, +0.0072742f,0.99351f,-0.113513f, +0.112563f,0.957036f,-0.26723f, +0.0621414f,0.905176f,-0.420469f, +0.0722297f,0.880288f,-0.468909f, +0.230329f,0.856327f,-0.462225f, +0.381575f,0.843927f,-0.377079f, +0.221134f,0.891315f,-0.395799f, +0.0308171f,0.923698f,-0.381879f, +0.0400222f,0.939112f,-0.341272f, +0.100477f,0.950816f,-0.293006f, +0.177047f,0.942783f,-0.282515f, +0.133298f,0.926135f,-0.352852f, +0.196525f,0.937661f,-0.286653f, +0.349249f,0.920399f,-0.17576f, +0.344233f,0.909171f,-0.234334f, +0.376056f,0.891226f,-0.25357f, +0.439076f,0.869021f,-0.228069f, +0.419906f,0.900431f,-0.113589f, +0.367672f,0.919513f,-0.13897f, +0.413581f,0.894358f,-0.170514f, +0.417856f,0.905717f,-0.0712231f, +0.442627f,0.896671f,0.00788109f, +0.434719f,0.900071f,0.0298519f, +0.417993f,0.908131f,0.0240916f, +-0.312333f,0.839022f,0.445522f, +-0.320499f,0.80841f,0.493714f, +-0.254519f,0.811123f,0.526593f, +-0.204612f,0.85744f,0.472156f, +-0.178862f,0.910868f,0.371925f, +-0.00702334f,0.926328f,0.376653f, +-0.0708828f,0.954444f,0.289847f, +-0.0771525f,0.977635f,0.195648f, +-0.0751036f,0.961343f,0.264914f, +-0.145577f,0.95681f,0.25164f, +0.127391f,0.9356f,0.329278f, +0.155803f,0.922417f,0.353372f, +-0.0158909f,0.953782f,0.300078f, +-0.071615f,0.974742f,0.211541f, +0.0985463f,0.976728f,0.190504f, +0.112633f,0.991267f,0.0685771f, +0.169574f,0.979892f,0.105153f, +0.189025f,0.96308f,0.191696f, +0.0919285f,0.967342f,0.236218f, +0.12853f,0.953507f,0.272588f, +0.291986f,0.918653f,0.266123f, +0.353363f,0.907675f,0.226407f, +0.385555f,0.89484f,0.224962f, +0.404454f,0.872627f,0.273752f, +0.205311f,0.929054f,0.307743f, +0.110161f,0.942272f,0.316208f, +0.185964f,0.923078f,0.336668f, +0.152054f,0.949861f,0.273212f, +0.185461f,0.938647f,0.290768f, +0.273329f,0.907935f,0.317718f, +0.1744f,0.944567f,0.278169f, +0.0252708f,0.979111f,0.20175f, +0.168508f,0.972599f,0.160178f, +0.171022f,0.978059f,0.118964f, +0.0998107f,0.989636f,0.103241f, +-0.201522f,0.966723f,-0.157591f, +-0.270475f,0.936595f,-0.222784f, +-0.312657f,0.944755f,-0.0984088f, +-0.352005f,0.934773f,-0.0478632f, +-0.0861214f,0.995901f,-0.0276381f, +0.0987576f,0.994369f,-0.0384345f, +0.271502f,0.95802f,-0.0921061f, +0.198786f,0.941001f,-0.273863f, +0.12025f,0.91375f,-0.388073f, +0.19318f,0.901312f,-0.38771f, +0.347672f,0.893681f,-0.283653f, +0.243349f,0.925421f,-0.290477f, +0.0173943f,0.947888f,-0.318129f, +0.037959f,0.944705f,-0.325718f, +0.138906f,0.919468f,-0.36781f, +0.157447f,0.882137f,-0.443897f, +0.187757f,0.895179f,-0.404229f, +0.0607904f,0.891083f,-0.44975f, +0.186006f,0.945946f,-0.265685f, +0.365887f,0.929282f,-0.0506235f, +0.41897f,0.907686f,-0.0238758f, +0.421784f,0.903427f,-0.0769231f, +0.443234f,0.894342f,-0.0608035f, +0.410975f,0.898831f,-0.152323f, +0.386797f,0.913648f,-0.125039f, +0.291947f,0.94823f,-0.125004f, +0.388472f,0.921139f,-0.0243475f, +0.43729f,0.89932f,0.000909095f, +0.438439f,0.898727f,-0.00777216f, +-0.28789f,0.841477f,0.457204f, +-0.335895f,0.843138f,0.419871f, +-0.2812f,0.876582f,0.390553f, +-0.0955224f,0.927302f,0.361922f, +-0.12003f,0.968207f,0.219473f, +-0.0624603f,0.972133f,0.225956f, +0.00876105f,0.944888f,0.327276f, +-0.0188296f,0.951986f,0.305562f, +-0.0880524f,0.955492f,0.28157f, +-0.14211f,0.96142f,0.235533f, +0.0867118f,0.963277f,0.254122f, +0.135173f,0.965034f,0.224584f, +0.150393f,0.96446f,0.217252f, +0.0301773f,0.99954f,0.00289386f, +0.112215f,0.991225f,-0.0698593f, +0.139936f,0.985559f,-0.0953439f, +0.125274f,0.991296f,-0.0404889f, +0.130003f,0.991461f,0.0102436f, +0.104702f,0.992835f,0.0575904f, +0.129192f,0.991077f,0.0328109f, +0.258743f,0.962487f,0.0816753f, +0.358319f,0.917773f,0.171175f, +0.362543f,0.919373f,0.152698f, +0.379026f,0.899795f,0.216122f, +0.252574f,0.930076f,0.266767f, +0.106065f,0.974915f,0.195683f, +0.13953f,0.968709f,0.205267f, +0.207814f,0.946678f,0.246198f, +0.149976f,0.969192f,0.195383f, +0.250422f,0.937237f,0.242644f, +0.308573f,0.924236f,0.224878f, +0.137327f,0.986571f,0.0884273f, +0.176869f,0.981357f,0.0752039f, +0.106914f,0.989761f,0.0945676f, +0.0990876f,0.985862f,0.135123f, +0.0562231f,0.995571f,0.0753513f, +-0.246892f,0.957072f,-0.15185f, +-0.351837f,0.92065f,-0.169157f, +-0.377614f,0.902561f,-0.206862f, +-0.10132f,0.980362f,-0.169188f, +0.0776454f,0.98254f,-0.169077f, +0.306304f,0.93954f,-0.153108f, +0.377181f,0.900422f,-0.216738f, +0.189257f,0.917577f,-0.349621f, +0.154953f,0.928643f,-0.337063f, +0.267717f,0.911458f,-0.312367f, +0.294676f,0.908518f,-0.296244f, +0.0231864f,0.917435f,-0.39721f, +0.0626224f,0.928776f,-0.365314f, +0.222796f,0.906686f,-0.358165f, +0.23143f,0.87959f,-0.415646f, +0.13808f,0.870415f,-0.472559f, +0.025291f,0.910796f,-0.412081f, +-0.0453254f,0.945277f,-0.323104f, +0.159501f,0.971914f,-0.17304f, +0.38445f,0.922508f,-0.0343154f, +0.457445f,0.889226f,-0.00452937f, +0.479545f,0.877417f,-0.0132742f, +0.420093f,0.902443f,-0.0954967f, +0.386091f,0.921349f,-0.0452663f, +0.319162f,0.945851f,-0.059174f, +0.358596f,0.930564f,-0.0738904f, +0.442653f,0.891593f,-0.0955061f, +0.442432f,0.88607f,-0.138327f, +-0.180108f,0.868506f,0.461799f, +-0.252344f,0.891893f,0.375298f, +-0.214515f,0.951228f,0.221693f, +-0.0232238f,0.989215f,0.144618f, +0.0240637f,0.992144f,0.122761f, +-0.119024f,0.992873f,0.00598183f, +-0.113037f,0.992656f,0.0430988f, +-0.0429691f,0.994091f,0.0996822f, +-0.0494378f,0.98881f,0.140751f, +-0.101045f,0.990831f,0.0896877f, +0.0748729f,0.995782f,0.0530223f, +0.173588f,0.976877f,0.124814f, +0.168744f,0.967443f,0.188628f, +0.211654f,0.955224f,0.206761f, +0.198232f,0.976689f,0.0823528f, +0.160641f,0.986993f,-0.00630407f, +0.0575905f,0.994633f,-0.0859521f, +0.0365841f,0.998447f,-0.0420043f, +0.0556411f,0.989086f,0.136432f, +0.127974f,0.973486f,0.1896f, +0.188609f,0.96964f,0.155643f, +0.316079f,0.935031f,0.16066f, +0.368833f,0.913789f,0.170151f, +0.28567f,0.933317f,0.217512f, +0.224877f,0.919424f,0.322631f, +0.173372f,0.927466f,0.331284f, +0.14641f,0.951279f,0.271352f, +0.199618f,0.950197f,0.239328f, +0.194716f,0.961761f,0.192616f, +0.211001f,0.970026f,0.12053f, +0.377145f,0.915922f,0.137289f, +0.173279f,0.983115f,0.0588147f, +0.137169f,0.986854f,0.085457f, +0.167124f,0.984519f,0.0528309f, +0.114693f,0.990538f,-0.0753596f, +0.120988f,0.991416f,-0.0495523f, +-0.0934722f,0.99234f,-0.0807704f, +-0.28812f,0.930265f,-0.227141f, +-0.319246f,0.884516f,-0.340167f, +-0.147049f,0.912977f,-0.380591f, +0.113837f,0.925954f,-0.360071f, +0.286328f,0.873071f,-0.394668f, +0.386305f,0.86841f,-0.310857f, +0.201568f,0.937185f,-0.284702f, +0.165365f,0.953527f,-0.251875f, +0.277218f,0.910704f,-0.306215f, +0.350715f,0.890932f,-0.288511f, +0.130261f,0.920935f,-0.367302f, +-0.00793534f,0.891743f,-0.452472f, +0.173424f,0.90309f,-0.392878f, +0.309572f,0.891597f,-0.330484f, +0.155483f,0.904383f,-0.397387f, +-0.0901615f,0.931774f,-0.351664f, +-0.12522f,0.950283f,-0.285102f, +0.116309f,0.952999f,-0.279758f, +0.314059f,0.900664f,-0.300285f, +0.399484f,0.884115f,-0.242388f, +0.476487f,0.865346f,-0.155359f, +0.461331f,0.87037f,-0.172132f, +0.340659f,0.915541f,-0.213858f, +0.307988f,0.934535f,-0.178292f, +0.356904f,0.924065f,-0.136833f, +0.470016f,0.879468f,-0.0749671f, +0.505067f,0.862447f,-0.0330571f, +-0.15355f,0.924768f,0.348175f, +-0.09321f,0.949622f,0.299215f, +-0.0484808f,0.991662f,0.1194f, +-0.0103305f,0.999605f,0.0261285f, +0.0401188f,0.998578f,0.0351042f, +-0.00661539f,0.998628f,-0.0519471f, +-0.0683745f,0.981776f,-0.177318f, +-0.0856989f,0.966825f,-0.240633f, +-0.0983519f,0.984458f,-0.145499f, +-0.0680709f,0.995572f,-0.0648268f, +0.0777629f,0.996246f,-0.0380386f, +0.0383267f,0.998901f,-0.0269619f, +0.00333347f,0.997094f,0.0761077f, +0.139217f,0.959624f,0.244419f, +0.245721f,0.912381f,0.327386f, +0.246821f,0.907772f,0.339159f, +0.175417f,0.940931f,0.289617f, +-0.027159f,0.9789f,0.202525f, +-0.173424f,0.953226f,0.247557f, +0.0844967f,0.921276f,0.37962f, +0.304261f,0.89366f,0.329845f, +0.31812f,0.923926f,0.21251f, +0.353311f,0.902952f,0.244642f, +0.195957f,0.945525f,0.25997f, +0.182247f,0.923305f,0.338075f, +0.134205f,0.934918f,0.328507f, +0.176553f,0.881734f,0.437463f, +0.22427f,0.87574f,0.42753f, +0.29074f,0.869795f,0.398657f, +0.272684f,0.924539f,0.266215f, +0.39631f,0.892935f,0.213556f, +0.227086f,0.96746f,0.111597f, +0.14196f,0.988195f,0.0576051f, +0.283679f,0.958555f,0.0264133f, +0.216474f,0.969698f,-0.113251f, +0.0386649f,0.982201f,-0.183812f, +-0.0151491f,0.988164f,-0.152652f, +-0.145516f,0.952277f,-0.268316f, +-0.219857f,0.921944f,-0.318875f, +-0.140821f,0.920717f,-0.363936f, +0.13255f,0.932146f,-0.33695f, +0.285156f,0.898104f,-0.334807f, +0.270867f,0.921389f,-0.278701f, +0.136545f,0.958362f,-0.250793f, +0.156889f,0.960437f,-0.230103f, +0.337521f,0.917391f,-0.210889f, +0.340375f,0.909959f,-0.236896f, +0.226521f,0.931852f,-0.283443f, +0.0467156f,0.919678f,-0.389885f, +0.11829f,0.926104f,-0.358244f, +0.284734f,0.910765f,-0.299055f, +0.155007f,0.943096f,-0.294183f, +-0.117772f,0.948884f,-0.29283f, +-0.124268f,0.932168f,-0.340029f, +0.155477f,0.92011f,-0.359477f, +0.348711f,0.859859f,-0.372885f, +0.344156f,0.842199f,-0.415039f, +0.367487f,0.839547f,-0.400142f, +0.45537f,0.851179f,-0.261021f, +0.340771f,0.905445f,-0.25307f, +0.281592f,0.927438f,-0.246101f, +0.270207f,0.930215f,-0.248371f, +0.337751f,0.936799f,-0.0912801f, +0.415821f,0.905383f,0.085868f, +-0.0508816f,0.992949f,0.107064f, +0.00772943f,0.999926f,0.0093874f, +0.0748585f,0.990585f,-0.114623f, +0.0155266f,0.983672f,-0.179298f, +0.0579395f,0.986738f,-0.15163f, +0.0876255f,0.991018f,-0.10102f, +0.0527296f,0.995461f,-0.0792264f, +-0.086898f,0.99085f,-0.103274f, +-0.226618f,0.972789f,-0.0482267f, +-0.175193f,0.983195f,0.0513344f, +0.0267808f,0.994997f,0.0962477f, +0.0618698f,0.991981f,0.110211f, +-0.098328f,0.984739f,0.143601f, +-0.00458312f,0.952299f,0.305132f, +0.173153f,0.913691f,0.367678f, +0.186464f,0.911194f,0.367365f, +0.171431f,0.905309f,0.388622f, +0.0620384f,0.93682f,0.344266f, +-0.143644f,0.960893f,0.23675f, +0.0362541f,0.97893f,0.200951f, +0.349667f,0.904284f,0.244957f, +0.338175f,0.903327f,0.26389f, +0.333852f,0.898218f,0.285914f, +0.192181f,0.948404f,0.252183f, +0.15408f,0.957234f,0.244873f, +0.108314f,0.961372f,0.253046f, +0.0186373f,0.953687f,0.300223f, +0.205839f,0.914416f,0.34853f, +0.331275f,0.886521f,0.323015f, +0.368345f,0.875165f,0.313702f, +0.405591f,0.862022f,0.303997f, +0.335644f,0.884308f,0.324566f, +0.194457f,0.953987f,0.228245f, +0.317589f,0.932139f,0.173936f, +0.34707f,0.93458f,0.0781131f, +0.1429f,0.981779f,-0.125256f, +0.0457434f,0.962864f,-0.266085f, +-0.0800896f,0.929514f,-0.359987f, +-0.224976f,0.908098f,-0.353191f, +-0.16594f,0.929111f,-0.330481f, +0.0749763f,0.957672f,-0.277928f, +0.277052f,0.936424f,-0.215295f, +0.266206f,0.947023f,-0.17967f, +0.192217f,0.96172f,-0.195315f, +0.159333f,0.947925f,-0.275775f, +0.291985f,0.916673f,-0.272864f, +0.390644f,0.893072f,-0.223205f, +0.316013f,0.901654f,-0.295223f, +0.0938304f,0.916417f,-0.38907f, +0.0371906f,0.918056f,-0.394702f, +0.249356f,0.914822f,-0.317682f, +0.159281f,0.933374f,-0.321625f, +-0.034507f,0.927426f,-0.372412f, +-0.0639276f,0.876921f,-0.476365f, +0.150154f,0.87361f,-0.462881f, +0.34577f,0.845394f,-0.407127f, +0.406017f,0.841234f,-0.357037f, +0.322181f,0.876026f,-0.358855f, +0.315882f,0.91236f,-0.260417f, +0.325378f,0.928704f,-0.177873f, +0.281437f,0.937288f,-0.205633f, +0.23991f,0.955112f,-0.173792f, +0.165717f,0.980838f,-0.102443f, +0.16591f,0.98582f,-0.0251575f, +0.188672f,0.97776f,0.0915829f, +0.0994257f,0.983812f,-0.14909f, +0.199087f,0.95198f,-0.232593f, +0.0121878f,0.914874f,-0.403556f, +-0.0234414f,0.930265f,-0.36614f, +-0.038124f,0.972539f,-0.229595f, +-0.0300917f,0.999515f,-0.00796094f, +-0.092201f,0.984658f,0.148144f, +-0.315366f,0.938181f,0.142688f, +-0.138968f,0.942311f,0.304528f, +0.0277459f,0.977812f,0.207641f, +0.0496201f,0.98101f,0.187502f, +-0.256039f,0.940975f,0.22138f, +-0.0796386f,0.864833f,0.495703f, +0.172206f,0.836979f,0.519434f, +0.218401f,0.8652f,0.451365f, +0.211231f,0.888948f,0.406391f, +0.153922f,0.942863f,0.295494f, +-0.0705923f,0.983817f,0.164685f, +0.0334153f,0.99603f,0.0825054f, +0.282635f,0.9535f,0.104667f, +0.322121f,0.91103f,0.257413f, +0.32296f,0.89395f,0.310726f, +0.263681f,0.921808f,0.284152f, +0.145976f,0.970498f,0.191897f, +0.110214f,0.967993f,0.225482f, +0.0100073f,0.970397f,0.241307f, +0.231259f,0.94984f,0.210532f, +0.350804f,0.929639f,0.112731f, +0.388908f,0.908557f,0.152559f, +0.325259f,0.933029f,0.153831f, +0.358244f,0.845843f,0.395235f, +0.245479f,0.88292f,0.400241f, +0.340078f,0.880829f,0.329372f, +0.448713f,0.860203f,0.242295f, +0.291253f,0.956268f,-0.0268833f, +0.174446f,0.957532f,-0.229565f, +-0.0246181f,0.920367f,-0.390281f, +-0.230596f,0.878986f,-0.417383f, +-0.188847f,0.897269f,-0.399054f, +0.0175328f,0.926292f,-0.376398f, +0.23985f,0.925856f,-0.291997f, +0.22945f,0.938275f,-0.258829f, +0.212396f,0.953082f,-0.21569f, +0.229329f,0.940641f,-0.250204f, +0.284501f,0.899212f,-0.33238f, +0.376241f,0.875275f,-0.30387f, +0.33476f,0.887829f,-0.315744f, +0.163808f,0.925647f,-0.341094f, +0.00890663f,0.895805f,-0.444357f, +0.214972f,0.896442f,-0.38753f, +0.17587f,0.912162f,-0.370177f, +0.075136f,0.903308f,-0.422362f, +-0.00910936f,0.832148f,-0.55448f, +0.080579f,0.825188f,-0.559082f, +0.296201f,0.838595f,-0.457191f, +0.316267f,0.8627f,-0.39462f, +0.301959f,0.9215f,-0.24425f, +0.239667f,0.953185f,-0.184387f, +0.359606f,0.929321f,-0.0839473f, +0.264487f,0.941897f,-0.207066f, +0.184815f,0.971569f,-0.147976f, +0.141833f,0.988976f,-0.0425335f, +0.112364f,0.992816f,-0.0411276f, +}; + +btScalar Landscape04Tex[] = { +0.507813f,0.25f, +0.507813f,0.242188f, +0.515625f,0.25f, +0.515625f,0.242188f, +0.523438f,0.25f, +0.523438f,0.242188f, +0.53125f,0.25f, +0.53125f,0.242188f, +0.539063f,0.25f, +0.539063f,0.242188f, +0.546875f,0.25f, +0.546875f,0.242188f, +0.554688f,0.25f, +0.554688f,0.242188f, +0.5625f,0.25f, +0.5625f,0.242188f, +0.570313f,0.25f, +0.570313f,0.242188f, +0.578125f,0.25f, +0.578125f,0.242188f, +0.585938f,0.25f, +0.585938f,0.242188f, +0.59375f,0.25f, +0.59375f,0.242188f, +0.601563f,0.25f, +0.601563f,0.242188f, +0.609375f,0.25f, +0.609375f,0.242188f, +0.617188f,0.25f, +0.617188f,0.242188f, +0.625f,0.25f, +0.625f,0.242188f, +0.632813f,0.25f, +0.632813f,0.242188f, +0.640625f,0.25f, +0.640625f,0.242188f, +0.648438f,0.25f, +0.648438f,0.242188f, +0.65625f,0.25f, +0.65625f,0.242188f, +0.664063f,0.25f, +0.664063f,0.242188f, +0.671875f,0.25f, +0.671875f,0.242188f, +0.679688f,0.25f, +0.679688f,0.242188f, +0.6875f,0.25f, +0.6875f,0.242188f, +0.695313f,0.25f, +0.695313f,0.242188f, +0.703125f,0.25f, +0.703125f,0.242188f, +0.710938f,0.25f, +0.710938f,0.242188f, +0.71875f,0.25f, +0.71875f,0.242188f, +0.726563f,0.25f, +0.726563f,0.242188f, +0.734375f,0.25f, +0.734375f,0.242188f, +0.742188f,0.25f, +0.742188f,0.242188f, +0.75f,0.25f, +0.75f,0.242188f, +0.757813f,0.25f, +0.757813f,0.242188f, +0.765625f,0.25f, +0.765625f,0.242188f, +0.773438f,0.25f, +0.773438f,0.242188f, +0.78125f,0.25f, +0.78125f,0.242188f, +0.789063f,0.25f, +0.789063f,0.242188f, +0.796875f,0.25f, +0.796875f,0.242188f, +0.804688f,0.25f, +0.804688f,0.242188f, +0.8125f,0.25f, +0.8125f,0.242188f, +0.820313f,0.25f, +0.820313f,0.242188f, +0.828125f,0.25f, +0.828125f,0.242188f, +0.835938f,0.25f, +0.835938f,0.242188f, +0.84375f,0.25f, +0.84375f,0.242188f, +0.851563f,0.25f, +0.851563f,0.242188f, +0.859375f,0.25f, +0.859375f,0.242188f, +0.867188f,0.25f, +0.867188f,0.242188f, +0.875f,0.25f, +0.875f,0.242188f, +0.882813f,0.25f, +0.882813f,0.242188f, +0.890625f,0.25f, +0.890625f,0.242188f, +0.898438f,0.25f, +0.898438f,0.242188f, +0.90625f,0.25f, +0.90625f,0.242188f, +0.914063f,0.25f, +0.914063f,0.242188f, +0.921875f,0.25f, +0.921875f,0.242188f, +0.929688f,0.25f, +0.929688f,0.242188f, +0.9375f,0.25f, +0.9375f,0.242188f, +0.945313f,0.25f, +0.945313f,0.242188f, +0.953125f,0.25f, +0.953125f,0.242188f, +0.960938f,0.25f, +0.960938f,0.242188f, +0.96875f,0.25f, +0.96875f,0.242188f, +0.976563f,0.25f, +0.976563f,0.242188f, +0.984375f,0.25f, +0.984375f,0.242188f, +0.992188f,0.25f, +0.992188f,0.242188f, +1.0f,0.25f, +1.0f,0.242188f, +0.507813f,0.257813f, +0.515625f,0.257813f, +0.523438f,0.257813f, +0.53125f,0.257813f, +0.539063f,0.257813f, +0.546875f,0.257813f, +0.554688f,0.257813f, +0.5625f,0.257813f, +0.570313f,0.257813f, +0.578125f,0.257813f, +0.585938f,0.257813f, +0.59375f,0.257813f, +0.601563f,0.257813f, +0.609375f,0.257813f, +0.617188f,0.257813f, +0.625f,0.257813f, +0.632813f,0.257813f, +0.640625f,0.257813f, +0.648438f,0.257813f, +0.65625f,0.257813f, +0.664063f,0.257813f, +0.671875f,0.257813f, +0.679688f,0.257813f, +0.6875f,0.257813f, +0.695313f,0.257813f, +0.703125f,0.257813f, +0.710938f,0.257813f, +0.71875f,0.257813f, +0.726563f,0.257813f, +0.734375f,0.257813f, +0.742188f,0.257813f, +0.75f,0.257813f, +0.757813f,0.257813f, +0.765625f,0.257813f, +0.773438f,0.257813f, +0.78125f,0.257813f, +0.789063f,0.257813f, +0.796875f,0.257813f, +0.804688f,0.257813f, +0.8125f,0.257813f, +0.820313f,0.257813f, +0.828125f,0.257813f, +0.835938f,0.257813f, +0.84375f,0.257813f, +0.851563f,0.257813f, +0.859375f,0.257813f, +0.867188f,0.257813f, +0.875f,0.257813f, +0.882813f,0.257813f, +0.890625f,0.257813f, +0.898438f,0.257813f, +0.90625f,0.257813f, +0.914063f,0.257813f, +0.921875f,0.257813f, +0.929688f,0.257813f, +0.9375f,0.257813f, +0.945313f,0.257813f, +0.953125f,0.257813f, +0.960938f,0.257813f, +0.96875f,0.257813f, +0.976563f,0.257813f, +0.984375f,0.257813f, +0.992188f,0.257813f, +1.0f,0.257813f, +0.507813f,0.265625f, +0.515625f,0.265625f, +0.523438f,0.265625f, +0.53125f,0.265625f, +0.539063f,0.265625f, +0.546875f,0.265625f, +0.554688f,0.265625f, +0.5625f,0.265625f, +0.570313f,0.265625f, +0.578125f,0.265625f, +0.585938f,0.265625f, +0.59375f,0.265625f, +0.601563f,0.265625f, +0.609375f,0.265625f, +0.617188f,0.265625f, +0.625f,0.265625f, +0.632813f,0.265625f, +0.640625f,0.265625f, +0.648438f,0.265625f, +0.65625f,0.265625f, +0.664063f,0.265625f, +0.671875f,0.265625f, +0.679688f,0.265625f, +0.6875f,0.265625f, +0.695313f,0.265625f, +0.703125f,0.265625f, +0.710938f,0.265625f, +0.71875f,0.265625f, +0.726563f,0.265625f, +0.734375f,0.265625f, +0.742188f,0.265625f, +0.75f,0.265625f, +0.757813f,0.265625f, +0.765625f,0.265625f, +0.773438f,0.265625f, +0.78125f,0.265625f, +0.789063f,0.265625f, +0.796875f,0.265625f, +0.804688f,0.265625f, +0.8125f,0.265625f, +0.820313f,0.265625f, +0.828125f,0.265625f, +0.835938f,0.265625f, +0.84375f,0.265625f, +0.851563f,0.265625f, +0.859375f,0.265625f, +0.867188f,0.265625f, +0.875f,0.265625f, +0.882813f,0.265625f, +0.890625f,0.265625f, +0.898438f,0.265625f, +0.90625f,0.265625f, +0.914063f,0.265625f, +0.921875f,0.265625f, +0.929688f,0.265625f, +0.9375f,0.265625f, +0.945313f,0.265625f, +0.953125f,0.265625f, +0.960938f,0.265625f, +0.96875f,0.265625f, +0.976563f,0.265625f, +0.984375f,0.265625f, +0.992188f,0.265625f, +1.0f,0.265625f, +0.507813f,0.273438f, +0.515625f,0.273438f, +0.523438f,0.273438f, +0.53125f,0.273438f, +0.539063f,0.273438f, +0.546875f,0.273438f, +0.554688f,0.273438f, +0.5625f,0.273438f, +0.570313f,0.273438f, +0.578125f,0.273438f, +0.585938f,0.273438f, +0.59375f,0.273438f, +0.601563f,0.273438f, +0.609375f,0.273438f, +0.617188f,0.273438f, +0.625f,0.273438f, +0.632813f,0.273438f, +0.640625f,0.273438f, +0.648438f,0.273438f, +0.65625f,0.273438f, +0.664063f,0.273438f, +0.671875f,0.273438f, +0.679688f,0.273438f, +0.6875f,0.273438f, +0.695313f,0.273438f, +0.703125f,0.273438f, +0.710938f,0.273438f, +0.71875f,0.273438f, +0.726563f,0.273438f, +0.734375f,0.273438f, +0.742188f,0.273438f, +0.75f,0.273438f, +0.757813f,0.273438f, +0.765625f,0.273438f, +0.773438f,0.273438f, +0.78125f,0.273438f, +0.789063f,0.273438f, +0.796875f,0.273438f, +0.804688f,0.273438f, +0.8125f,0.273438f, +0.820313f,0.273438f, +0.828125f,0.273438f, +0.835938f,0.273438f, +0.84375f,0.273438f, +0.851563f,0.273438f, +0.859375f,0.273438f, +0.867188f,0.273438f, +0.875f,0.273438f, +0.882813f,0.273438f, +0.890625f,0.273438f, +0.898438f,0.273438f, +0.90625f,0.273438f, +0.914063f,0.273438f, +0.921875f,0.273438f, +0.929688f,0.273438f, +0.9375f,0.273438f, +0.945313f,0.273438f, +0.953125f,0.273438f, +0.960938f,0.273438f, +0.96875f,0.273438f, +0.976563f,0.273438f, +0.984375f,0.273438f, +0.992188f,0.273438f, +1.0f,0.273438f, +0.507813f,0.28125f, +0.515625f,0.28125f, +0.523438f,0.28125f, +0.53125f,0.28125f, +0.539063f,0.28125f, +0.546875f,0.28125f, +0.554688f,0.28125f, +0.5625f,0.28125f, +0.570313f,0.28125f, +0.578125f,0.28125f, +0.585938f,0.28125f, +0.59375f,0.28125f, +0.601563f,0.28125f, +0.609375f,0.28125f, +0.617188f,0.28125f, +0.625f,0.28125f, +0.632813f,0.28125f, +0.640625f,0.28125f, +0.648438f,0.28125f, +0.65625f,0.28125f, +0.664063f,0.28125f, +0.671875f,0.28125f, +0.679688f,0.28125f, +0.6875f,0.28125f, +0.695313f,0.28125f, +0.703125f,0.28125f, +0.710938f,0.28125f, +0.71875f,0.28125f, +0.726563f,0.28125f, +0.734375f,0.28125f, +0.742188f,0.28125f, +0.75f,0.28125f, +0.757813f,0.28125f, +0.765625f,0.28125f, +0.773438f,0.28125f, +0.78125f,0.28125f, +0.789063f,0.28125f, +0.796875f,0.28125f, +0.804688f,0.28125f, +0.8125f,0.28125f, +0.820313f,0.28125f, +0.828125f,0.28125f, +0.835938f,0.28125f, +0.84375f,0.28125f, +0.851563f,0.28125f, +0.859375f,0.28125f, +0.867188f,0.28125f, +0.875f,0.28125f, +0.882813f,0.28125f, +0.890625f,0.28125f, +0.898438f,0.28125f, +0.90625f,0.28125f, +0.914063f,0.28125f, +0.921875f,0.28125f, +0.929688f,0.28125f, +0.9375f,0.28125f, +0.945313f,0.28125f, +0.953125f,0.28125f, +0.960938f,0.28125f, +0.96875f,0.28125f, +0.976563f,0.28125f, +0.984375f,0.28125f, +0.992188f,0.28125f, +1.0f,0.28125f, +0.507813f,0.289063f, +0.515625f,0.289063f, +0.523438f,0.289063f, +0.53125f,0.289063f, +0.539063f,0.289063f, +0.546875f,0.289063f, +0.554688f,0.289063f, +0.5625f,0.289063f, +0.570313f,0.289063f, +0.578125f,0.289063f, +0.585938f,0.289063f, +0.59375f,0.289063f, +0.601563f,0.289063f, +0.609375f,0.289063f, +0.617188f,0.289063f, +0.625f,0.289063f, +0.632813f,0.289063f, +0.640625f,0.289063f, +0.648438f,0.289063f, +0.65625f,0.289063f, +0.664063f,0.289063f, +0.671875f,0.289063f, +0.679688f,0.289063f, +0.6875f,0.289063f, +0.695313f,0.289063f, +0.703125f,0.289063f, +0.710938f,0.289063f, +0.71875f,0.289063f, +0.726563f,0.289063f, +0.734375f,0.289063f, +0.742188f,0.289063f, +0.75f,0.289063f, +0.757813f,0.289063f, +0.765625f,0.289063f, +0.773438f,0.289063f, +0.78125f,0.289063f, +0.789063f,0.289063f, +0.796875f,0.289063f, +0.804688f,0.289063f, +0.8125f,0.289063f, +0.820313f,0.289063f, +0.828125f,0.289063f, +0.835938f,0.289063f, +0.84375f,0.289063f, +0.851563f,0.289063f, +0.859375f,0.289063f, +0.867188f,0.289063f, +0.875f,0.289063f, +0.882813f,0.289063f, +0.890625f,0.289063f, +0.898438f,0.289063f, +0.90625f,0.289063f, +0.914063f,0.289063f, +0.921875f,0.289063f, +0.929688f,0.289063f, +0.9375f,0.289063f, +0.945313f,0.289063f, +0.953125f,0.289063f, +0.960938f,0.289063f, +0.96875f,0.289063f, +0.976563f,0.289063f, +0.984375f,0.289063f, +0.992188f,0.289063f, +1.0f,0.289063f, +0.507813f,0.296875f, +0.515625f,0.296875f, +0.523438f,0.296875f, +0.53125f,0.296875f, +0.539063f,0.296875f, +0.546875f,0.296875f, +0.554688f,0.296875f, +0.5625f,0.296875f, +0.570313f,0.296875f, +0.578125f,0.296875f, +0.585938f,0.296875f, +0.59375f,0.296875f, +0.601563f,0.296875f, +0.609375f,0.296875f, +0.617188f,0.296875f, +0.625f,0.296875f, +0.632813f,0.296875f, +0.640625f,0.296875f, +0.648438f,0.296875f, +0.65625f,0.296875f, +0.664063f,0.296875f, +0.671875f,0.296875f, +0.679688f,0.296875f, +0.6875f,0.296875f, +0.695313f,0.296875f, +0.703125f,0.296875f, +0.710938f,0.296875f, +0.71875f,0.296875f, +0.726563f,0.296875f, +0.734375f,0.296875f, +0.742188f,0.296875f, +0.75f,0.296875f, +0.757813f,0.296875f, +0.765625f,0.296875f, +0.773438f,0.296875f, +0.78125f,0.296875f, +0.789063f,0.296875f, +0.796875f,0.296875f, +0.804688f,0.296875f, +0.8125f,0.296875f, +0.820313f,0.296875f, +0.828125f,0.296875f, +0.835938f,0.296875f, +0.84375f,0.296875f, +0.851563f,0.296875f, +0.859375f,0.296875f, +0.867188f,0.296875f, +0.875f,0.296875f, +0.882813f,0.296875f, +0.890625f,0.296875f, +0.898438f,0.296875f, +0.90625f,0.296875f, +0.914063f,0.296875f, +0.921875f,0.296875f, +0.929688f,0.296875f, +0.9375f,0.296875f, +0.945313f,0.296875f, +0.953125f,0.296875f, +0.960938f,0.296875f, +0.96875f,0.296875f, +0.976563f,0.296875f, +0.984375f,0.296875f, +0.992188f,0.296875f, +1.0f,0.296875f, +0.507813f,0.304688f, +0.515625f,0.304688f, +0.523438f,0.304688f, +0.53125f,0.304688f, +0.539063f,0.304688f, +0.546875f,0.304688f, +0.554688f,0.304688f, +0.5625f,0.304688f, +0.570313f,0.304688f, +0.578125f,0.304688f, +0.585938f,0.304688f, +0.59375f,0.304688f, +0.601563f,0.304688f, +0.609375f,0.304688f, +0.617188f,0.304688f, +0.625f,0.304688f, +0.632813f,0.304688f, +0.640625f,0.304688f, +0.648438f,0.304688f, +0.65625f,0.304688f, +0.664063f,0.304688f, +0.671875f,0.304688f, +0.679688f,0.304688f, +0.6875f,0.304688f, +0.695313f,0.304688f, +0.703125f,0.304688f, +0.710938f,0.304688f, +0.71875f,0.304688f, +0.726563f,0.304688f, +0.734375f,0.304688f, +0.742188f,0.304688f, +0.75f,0.304688f, +0.757813f,0.304688f, +0.765625f,0.304688f, +0.773438f,0.304688f, +0.78125f,0.304688f, +0.789063f,0.304688f, +0.796875f,0.304688f, +0.804688f,0.304688f, +0.8125f,0.304688f, +0.820313f,0.304688f, +0.828125f,0.304688f, +0.835938f,0.304688f, +0.84375f,0.304688f, +0.851563f,0.304688f, +0.859375f,0.304688f, +0.867188f,0.304688f, +0.875f,0.304688f, +0.882813f,0.304688f, +0.890625f,0.304688f, +0.898438f,0.304688f, +0.90625f,0.304688f, +0.914063f,0.304688f, +0.921875f,0.304688f, +0.929688f,0.304688f, +0.9375f,0.304688f, +0.945313f,0.304688f, +0.953125f,0.304688f, +0.960938f,0.304688f, +0.96875f,0.304688f, +0.976563f,0.304688f, +0.984375f,0.304688f, +0.992188f,0.304688f, +1.0f,0.304688f, +0.507813f,0.3125f, +0.515625f,0.3125f, +0.523438f,0.3125f, +0.53125f,0.3125f, +0.539063f,0.3125f, +0.546875f,0.3125f, +0.554688f,0.3125f, +0.5625f,0.3125f, +0.570313f,0.3125f, +0.578125f,0.3125f, +0.585938f,0.3125f, +0.59375f,0.3125f, +0.601563f,0.3125f, +0.609375f,0.3125f, +0.617188f,0.3125f, +0.625f,0.3125f, +0.632813f,0.3125f, +0.640625f,0.3125f, +0.648438f,0.3125f, +0.65625f,0.3125f, +0.664063f,0.3125f, +0.671875f,0.3125f, +0.679688f,0.3125f, +0.6875f,0.3125f, +0.695313f,0.3125f, +0.703125f,0.3125f, +0.710938f,0.3125f, +0.71875f,0.3125f, +0.726563f,0.3125f, +0.734375f,0.3125f, +0.742188f,0.3125f, +0.75f,0.3125f, +0.757813f,0.3125f, +0.765625f,0.3125f, +0.773438f,0.3125f, +0.78125f,0.3125f, +0.789063f,0.3125f, +0.796875f,0.3125f, +0.804688f,0.3125f, +0.8125f,0.3125f, +0.820313f,0.3125f, +0.828125f,0.3125f, +0.835938f,0.3125f, +0.84375f,0.3125f, +0.851563f,0.3125f, +0.859375f,0.3125f, +0.867188f,0.3125f, +0.875f,0.3125f, +0.882813f,0.3125f, +0.890625f,0.3125f, +0.898438f,0.3125f, +0.90625f,0.3125f, +0.914063f,0.3125f, +0.921875f,0.3125f, +0.929688f,0.3125f, +0.9375f,0.3125f, +0.945313f,0.3125f, +0.953125f,0.3125f, +0.960938f,0.3125f, +0.96875f,0.3125f, +0.976563f,0.3125f, +0.984375f,0.3125f, +0.992188f,0.3125f, +1.0f,0.3125f, +0.507813f,0.320313f, +0.515625f,0.320313f, +0.523438f,0.320313f, +0.53125f,0.320313f, +0.539063f,0.320313f, +0.546875f,0.320313f, +0.554688f,0.320313f, +0.5625f,0.320313f, +0.570313f,0.320313f, +0.578125f,0.320313f, +0.585938f,0.320313f, +0.59375f,0.320313f, +0.601563f,0.320313f, +0.609375f,0.320313f, +0.617188f,0.320313f, +0.625f,0.320313f, +0.632813f,0.320313f, +0.640625f,0.320313f, +0.648438f,0.320313f, +0.65625f,0.320313f, +0.664063f,0.320313f, +0.671875f,0.320313f, +0.679688f,0.320313f, +0.6875f,0.320313f, +0.695313f,0.320313f, +0.703125f,0.320313f, +0.710938f,0.320313f, +0.71875f,0.320313f, +0.726563f,0.320313f, +0.734375f,0.320313f, +0.742188f,0.320313f, +0.75f,0.320313f, +0.757813f,0.320313f, +0.765625f,0.320313f, +0.773438f,0.320313f, +0.78125f,0.320313f, +0.789063f,0.320313f, +0.796875f,0.320313f, +0.804688f,0.320313f, +0.8125f,0.320313f, +0.820313f,0.320313f, +0.828125f,0.320313f, +0.835938f,0.320313f, +0.84375f,0.320313f, +0.851563f,0.320313f, +0.859375f,0.320313f, +0.867188f,0.320313f, +0.875f,0.320313f, +0.882813f,0.320313f, +0.890625f,0.320313f, +0.898438f,0.320313f, +0.90625f,0.320313f, +0.914063f,0.320313f, +0.921875f,0.320313f, +0.929688f,0.320313f, +0.9375f,0.320313f, +0.945313f,0.320313f, +0.953125f,0.320313f, +0.960938f,0.320313f, +0.96875f,0.320313f, +0.976563f,0.320313f, +0.984375f,0.320313f, +0.992188f,0.320313f, +1.0f,0.320313f, +0.507813f,0.328125f, +0.515625f,0.328125f, +0.523438f,0.328125f, +0.53125f,0.328125f, +0.539063f,0.328125f, +0.546875f,0.328125f, +0.554688f,0.328125f, +0.5625f,0.328125f, +0.570313f,0.328125f, +0.578125f,0.328125f, +0.585938f,0.328125f, +0.59375f,0.328125f, +0.601563f,0.328125f, +0.609375f,0.328125f, +0.617188f,0.328125f, +0.625f,0.328125f, +0.632813f,0.328125f, +0.640625f,0.328125f, +0.648438f,0.328125f, +0.65625f,0.328125f, +0.664063f,0.328125f, +0.671875f,0.328125f, +0.679688f,0.328125f, +0.6875f,0.328125f, +0.695313f,0.328125f, +0.703125f,0.328125f, +0.710938f,0.328125f, +0.71875f,0.328125f, +0.726563f,0.328125f, +0.734375f,0.328125f, +0.742188f,0.328125f, +0.75f,0.328125f, +0.757813f,0.328125f, +0.765625f,0.328125f, +0.773438f,0.328125f, +0.78125f,0.328125f, +0.789063f,0.328125f, +0.796875f,0.328125f, +0.804688f,0.328125f, +0.8125f,0.328125f, +0.820313f,0.328125f, +0.828125f,0.328125f, +0.835938f,0.328125f, +0.84375f,0.328125f, +0.851563f,0.328125f, +0.859375f,0.328125f, +0.867188f,0.328125f, +0.875f,0.328125f, +0.882813f,0.328125f, +0.890625f,0.328125f, +0.898438f,0.328125f, +0.90625f,0.328125f, +0.914063f,0.328125f, +0.921875f,0.328125f, +0.929688f,0.328125f, +0.9375f,0.328125f, +0.945313f,0.328125f, +0.953125f,0.328125f, +0.960938f,0.328125f, +0.96875f,0.328125f, +0.976563f,0.328125f, +0.984375f,0.328125f, +0.992188f,0.328125f, +1.0f,0.328125f, +0.507813f,0.335938f, +0.515625f,0.335938f, +0.523438f,0.335938f, +0.53125f,0.335938f, +0.539063f,0.335938f, +0.546875f,0.335938f, +0.554688f,0.335938f, +0.5625f,0.335938f, +0.570313f,0.335938f, +0.578125f,0.335938f, +0.585938f,0.335938f, +0.59375f,0.335938f, +0.601563f,0.335938f, +0.609375f,0.335938f, +0.617188f,0.335938f, +0.625f,0.335938f, +0.632813f,0.335938f, +0.640625f,0.335938f, +0.648438f,0.335938f, +0.65625f,0.335938f, +0.664063f,0.335938f, +0.671875f,0.335938f, +0.679688f,0.335938f, +0.6875f,0.335938f, +0.695313f,0.335938f, +0.703125f,0.335938f, +0.710938f,0.335938f, +0.71875f,0.335938f, +0.726563f,0.335938f, +0.734375f,0.335938f, +0.742188f,0.335938f, +0.75f,0.335938f, +0.757813f,0.335938f, +0.765625f,0.335938f, +0.773438f,0.335938f, +0.78125f,0.335938f, +0.789063f,0.335938f, +0.796875f,0.335938f, +0.804688f,0.335938f, +0.8125f,0.335938f, +0.820313f,0.335938f, +0.828125f,0.335938f, +0.835938f,0.335938f, +0.84375f,0.335938f, +0.851563f,0.335938f, +0.859375f,0.335938f, +0.867188f,0.335938f, +0.875f,0.335938f, +0.882813f,0.335938f, +0.890625f,0.335938f, +0.898438f,0.335938f, +0.90625f,0.335938f, +0.914063f,0.335938f, +0.921875f,0.335938f, +0.929688f,0.335938f, +0.9375f,0.335938f, +0.945313f,0.335938f, +0.953125f,0.335938f, +0.960938f,0.335938f, +0.96875f,0.335938f, +0.976563f,0.335938f, +0.984375f,0.335938f, +0.992188f,0.335938f, +1.0f,0.335938f, +0.507813f,0.34375f, +0.515625f,0.34375f, +0.523438f,0.34375f, +0.53125f,0.34375f, +0.539063f,0.34375f, +0.546875f,0.34375f, +0.554688f,0.34375f, +0.5625f,0.34375f, +0.570313f,0.34375f, +0.578125f,0.34375f, +0.585938f,0.34375f, +0.59375f,0.34375f, +0.601563f,0.34375f, +0.609375f,0.34375f, +0.617188f,0.34375f, +0.625f,0.34375f, +0.632813f,0.34375f, +0.640625f,0.34375f, +0.648438f,0.34375f, +0.65625f,0.34375f, +0.664063f,0.34375f, +0.671875f,0.34375f, +0.679688f,0.34375f, +0.6875f,0.34375f, +0.695313f,0.34375f, +0.703125f,0.34375f, +0.710938f,0.34375f, +0.71875f,0.34375f, +0.726563f,0.34375f, +0.734375f,0.34375f, +0.742188f,0.34375f, +0.75f,0.34375f, +0.757813f,0.34375f, +0.765625f,0.34375f, +0.773438f,0.34375f, +0.78125f,0.34375f, +0.789063f,0.34375f, +0.796875f,0.34375f, +0.804688f,0.34375f, +0.8125f,0.34375f, +0.820313f,0.34375f, +0.828125f,0.34375f, +0.835938f,0.34375f, +0.84375f,0.34375f, +0.851563f,0.34375f, +0.859375f,0.34375f, +0.867188f,0.34375f, +0.875f,0.34375f, +0.882813f,0.34375f, +0.890625f,0.34375f, +0.898438f,0.34375f, +0.90625f,0.34375f, +0.914063f,0.34375f, +0.921875f,0.34375f, +0.929688f,0.34375f, +0.9375f,0.34375f, +0.945313f,0.34375f, +0.953125f,0.34375f, +0.960938f,0.34375f, +0.96875f,0.34375f, +0.976563f,0.34375f, +0.984375f,0.34375f, +0.992188f,0.34375f, +1.0f,0.34375f, +0.507813f,0.351563f, +0.515625f,0.351563f, +0.523438f,0.351563f, +0.53125f,0.351563f, +0.539063f,0.351563f, +0.546875f,0.351563f, +0.554688f,0.351563f, +0.5625f,0.351563f, +0.570313f,0.351563f, +0.578125f,0.351563f, +0.585938f,0.351563f, +0.59375f,0.351563f, +0.601563f,0.351563f, +0.609375f,0.351563f, +0.617188f,0.351563f, +0.625f,0.351563f, +0.632813f,0.351563f, +0.640625f,0.351563f, +0.648438f,0.351563f, +0.65625f,0.351563f, +0.664063f,0.351563f, +0.671875f,0.351563f, +0.679688f,0.351563f, +0.6875f,0.351563f, +0.695313f,0.351563f, +0.703125f,0.351563f, +0.710938f,0.351563f, +0.71875f,0.351563f, +0.726563f,0.351563f, +0.734375f,0.351563f, +0.742188f,0.351563f, +0.75f,0.351563f, +0.757813f,0.351563f, +0.765625f,0.351563f, +0.773438f,0.351563f, +0.78125f,0.351563f, +0.789063f,0.351563f, +0.796875f,0.351563f, +0.804688f,0.351563f, +0.8125f,0.351563f, +0.820313f,0.351563f, +0.828125f,0.351563f, +0.835938f,0.351563f, +0.84375f,0.351563f, +0.851563f,0.351563f, +0.859375f,0.351563f, +0.867188f,0.351563f, +0.875f,0.351563f, +0.882813f,0.351563f, +0.890625f,0.351563f, +0.898438f,0.351563f, +0.90625f,0.351563f, +0.914063f,0.351563f, +0.921875f,0.351563f, +0.929688f,0.351563f, +0.9375f,0.351563f, +0.945313f,0.351563f, +0.953125f,0.351563f, +0.960938f,0.351563f, +0.96875f,0.351563f, +0.976563f,0.351563f, +0.984375f,0.351563f, +0.992188f,0.351563f, +1.0f,0.351563f, +0.507813f,0.359375f, +0.515625f,0.359375f, +0.523438f,0.359375f, +0.53125f,0.359375f, +0.539063f,0.359375f, +0.546875f,0.359375f, +0.554688f,0.359375f, +0.5625f,0.359375f, +0.570313f,0.359375f, +0.578125f,0.359375f, +0.585938f,0.359375f, +0.59375f,0.359375f, +0.601563f,0.359375f, +0.609375f,0.359375f, +0.617188f,0.359375f, +0.625f,0.359375f, +0.632813f,0.359375f, +0.640625f,0.359375f, +0.648438f,0.359375f, +0.65625f,0.359375f, +0.664063f,0.359375f, +0.671875f,0.359375f, +0.679688f,0.359375f, +0.6875f,0.359375f, +0.695313f,0.359375f, +0.703125f,0.359375f, +0.710938f,0.359375f, +0.71875f,0.359375f, +0.726563f,0.359375f, +0.734375f,0.359375f, +0.742188f,0.359375f, +0.75f,0.359375f, +0.757813f,0.359375f, +0.765625f,0.359375f, +0.773438f,0.359375f, +0.78125f,0.359375f, +0.789063f,0.359375f, +0.796875f,0.359375f, +0.804688f,0.359375f, +0.8125f,0.359375f, +0.820313f,0.359375f, +0.828125f,0.359375f, +0.835938f,0.359375f, +0.84375f,0.359375f, +0.851563f,0.359375f, +0.859375f,0.359375f, +0.867188f,0.359375f, +0.875f,0.359375f, +0.882813f,0.359375f, +0.890625f,0.359375f, +0.898438f,0.359375f, +0.90625f,0.359375f, +0.914063f,0.359375f, +0.921875f,0.359375f, +0.929688f,0.359375f, +0.9375f,0.359375f, +0.945313f,0.359375f, +0.953125f,0.359375f, +0.960938f,0.359375f, +0.96875f,0.359375f, +0.976563f,0.359375f, +0.984375f,0.359375f, +0.992188f,0.359375f, +1.0f,0.359375f, +0.507813f,0.367188f, +0.515625f,0.367188f, +0.523438f,0.367188f, +0.53125f,0.367188f, +0.539063f,0.367188f, +0.546875f,0.367188f, +0.554688f,0.367188f, +0.5625f,0.367188f, +0.570313f,0.367188f, +0.578125f,0.367188f, +0.585938f,0.367188f, +0.59375f,0.367188f, +0.601563f,0.367188f, +0.609375f,0.367188f, +0.617188f,0.367188f, +0.625f,0.367188f, +0.632813f,0.367188f, +0.640625f,0.367188f, +0.648438f,0.367188f, +0.65625f,0.367188f, +0.664063f,0.367188f, +0.671875f,0.367188f, +0.679688f,0.367188f, +0.6875f,0.367188f, +0.695313f,0.367188f, +0.703125f,0.367188f, +0.710938f,0.367188f, +0.71875f,0.367188f, +0.726563f,0.367188f, +0.734375f,0.367188f, +0.742188f,0.367188f, +0.75f,0.367188f, +0.757813f,0.367188f, +0.765625f,0.367188f, +0.773438f,0.367188f, +0.78125f,0.367188f, +0.789063f,0.367188f, +0.796875f,0.367188f, +0.804688f,0.367188f, +0.8125f,0.367188f, +0.820313f,0.367188f, +0.828125f,0.367188f, +0.835938f,0.367188f, +0.84375f,0.367188f, +0.851563f,0.367188f, +0.859375f,0.367188f, +0.867188f,0.367188f, +0.875f,0.367188f, +0.882813f,0.367188f, +0.890625f,0.367188f, +0.898438f,0.367188f, +0.90625f,0.367188f, +0.914063f,0.367188f, +0.921875f,0.367188f, +0.929688f,0.367188f, +0.9375f,0.367188f, +0.945313f,0.367188f, +0.953125f,0.367188f, +0.960938f,0.367188f, +0.96875f,0.367188f, +0.976563f,0.367188f, +0.984375f,0.367188f, +0.992188f,0.367188f, +1.0f,0.367188f, +0.507813f,0.375f, +0.515625f,0.375f, +0.523438f,0.375f, +0.53125f,0.375f, +0.539063f,0.375f, +0.546875f,0.375f, +0.554688f,0.375f, +0.5625f,0.375f, +0.570313f,0.375f, +0.578125f,0.375f, +0.585938f,0.375f, +0.59375f,0.375f, +0.601563f,0.375f, +0.609375f,0.375f, +0.617188f,0.375f, +0.625f,0.375f, +0.632813f,0.375f, +0.640625f,0.375f, +0.648438f,0.375f, +0.65625f,0.375f, +0.664063f,0.375f, +0.671875f,0.375f, +0.679688f,0.375f, +0.6875f,0.375f, +0.695313f,0.375f, +0.703125f,0.375f, +0.710938f,0.375f, +0.71875f,0.375f, +0.726563f,0.375f, +0.734375f,0.375f, +0.742188f,0.375f, +0.75f,0.375f, +0.757813f,0.375f, +0.765625f,0.375f, +0.773438f,0.375f, +0.78125f,0.375f, +0.789063f,0.375f, +0.796875f,0.375f, +0.804688f,0.375f, +0.8125f,0.375f, +0.820313f,0.375f, +0.828125f,0.375f, +0.835938f,0.375f, +0.84375f,0.375f, +0.851563f,0.375f, +0.859375f,0.375f, +0.867188f,0.375f, +0.875f,0.375f, +0.882813f,0.375f, +0.890625f,0.375f, +0.898438f,0.375f, +0.90625f,0.375f, +0.914063f,0.375f, +0.921875f,0.375f, +0.929688f,0.375f, +0.9375f,0.375f, +0.945313f,0.375f, +0.953125f,0.375f, +0.960938f,0.375f, +0.96875f,0.375f, +0.976563f,0.375f, +0.984375f,0.375f, +0.992188f,0.375f, +1.0f,0.375f, +0.507813f,0.382813f, +0.515625f,0.382813f, +0.523438f,0.382813f, +0.53125f,0.382813f, +0.539063f,0.382813f, +0.546875f,0.382813f, +0.554688f,0.382813f, +0.5625f,0.382813f, +0.570313f,0.382813f, +0.578125f,0.382813f, +0.585938f,0.382813f, +0.59375f,0.382813f, +0.601563f,0.382813f, +0.609375f,0.382813f, +0.617188f,0.382813f, +0.625f,0.382813f, +0.632813f,0.382813f, +0.640625f,0.382813f, +0.648438f,0.382813f, +0.65625f,0.382813f, +0.664063f,0.382813f, +0.671875f,0.382813f, +0.679688f,0.382813f, +0.6875f,0.382813f, +0.695313f,0.382813f, +0.703125f,0.382813f, +0.710938f,0.382813f, +0.71875f,0.382813f, +0.726563f,0.382813f, +0.734375f,0.382813f, +0.742188f,0.382813f, +0.75f,0.382813f, +0.757813f,0.382813f, +0.765625f,0.382813f, +0.773438f,0.382813f, +0.78125f,0.382813f, +0.789063f,0.382813f, +0.796875f,0.382813f, +0.804688f,0.382813f, +0.8125f,0.382813f, +0.820313f,0.382813f, +0.828125f,0.382813f, +0.835938f,0.382813f, +0.84375f,0.382813f, +0.851563f,0.382813f, +0.859375f,0.382813f, +0.867188f,0.382813f, +0.875f,0.382813f, +0.882813f,0.382813f, +0.890625f,0.382813f, +0.898438f,0.382813f, +0.90625f,0.382813f, +0.914063f,0.382813f, +0.921875f,0.382813f, +0.929688f,0.382813f, +0.9375f,0.382813f, +0.945313f,0.382813f, +0.953125f,0.382813f, +0.960938f,0.382813f, +0.96875f,0.382813f, +0.976563f,0.382813f, +0.984375f,0.382813f, +0.992188f,0.382813f, +1.0f,0.382813f, +0.507813f,0.390625f, +0.515625f,0.390625f, +0.523438f,0.390625f, +0.53125f,0.390625f, +0.539063f,0.390625f, +0.546875f,0.390625f, +0.554688f,0.390625f, +0.5625f,0.390625f, +0.570313f,0.390625f, +0.578125f,0.390625f, +0.585938f,0.390625f, +0.59375f,0.390625f, +0.601563f,0.390625f, +0.609375f,0.390625f, +0.617188f,0.390625f, +0.625f,0.390625f, +0.632813f,0.390625f, +0.640625f,0.390625f, +0.648438f,0.390625f, +0.65625f,0.390625f, +0.664063f,0.390625f, +0.671875f,0.390625f, +0.679688f,0.390625f, +0.6875f,0.390625f, +0.695313f,0.390625f, +0.703125f,0.390625f, +0.710938f,0.390625f, +0.71875f,0.390625f, +0.726563f,0.390625f, +0.734375f,0.390625f, +0.742188f,0.390625f, +0.75f,0.390625f, +0.757813f,0.390625f, +0.765625f,0.390625f, +0.773438f,0.390625f, +0.78125f,0.390625f, +0.789063f,0.390625f, +0.796875f,0.390625f, +0.804688f,0.390625f, +0.8125f,0.390625f, +0.820313f,0.390625f, +0.828125f,0.390625f, +0.835938f,0.390625f, +0.84375f,0.390625f, +0.851563f,0.390625f, +0.859375f,0.390625f, +0.867188f,0.390625f, +0.875f,0.390625f, +0.882813f,0.390625f, +0.890625f,0.390625f, +0.898438f,0.390625f, +0.90625f,0.390625f, +0.914063f,0.390625f, +0.921875f,0.390625f, +0.929688f,0.390625f, +0.9375f,0.390625f, +0.945313f,0.390625f, +0.953125f,0.390625f, +0.960938f,0.390625f, +0.96875f,0.390625f, +0.976563f,0.390625f, +0.984375f,0.390625f, +0.992188f,0.390625f, +1.0f,0.390625f, +0.507813f,0.398438f, +0.515625f,0.398438f, +0.523438f,0.398438f, +0.53125f,0.398438f, +0.539063f,0.398438f, +0.546875f,0.398438f, +0.554688f,0.398438f, +0.5625f,0.398438f, +0.570313f,0.398438f, +0.578125f,0.398438f, +0.585938f,0.398438f, +0.59375f,0.398438f, +0.601563f,0.398438f, +0.609375f,0.398438f, +0.617188f,0.398438f, +0.625f,0.398438f, +0.632813f,0.398438f, +0.640625f,0.398438f, +0.648438f,0.398438f, +0.65625f,0.398438f, +0.664063f,0.398438f, +0.671875f,0.398438f, +0.679688f,0.398438f, +0.6875f,0.398438f, +0.695313f,0.398438f, +0.703125f,0.398438f, +0.710938f,0.398438f, +0.71875f,0.398438f, +0.726563f,0.398438f, +0.734375f,0.398438f, +0.742188f,0.398438f, +0.75f,0.398438f, +0.757813f,0.398438f, +0.765625f,0.398438f, +0.773438f,0.398438f, +0.78125f,0.398438f, +0.789063f,0.398438f, +0.796875f,0.398438f, +0.804688f,0.398438f, +0.8125f,0.398438f, +0.820313f,0.398438f, +0.828125f,0.398438f, +0.835938f,0.398438f, +0.84375f,0.398438f, +0.851563f,0.398438f, +0.859375f,0.398438f, +0.867188f,0.398438f, +0.875f,0.398438f, +0.882813f,0.398438f, +0.890625f,0.398438f, +0.898438f,0.398438f, +0.90625f,0.398438f, +0.914063f,0.398438f, +0.921875f,0.398438f, +0.929688f,0.398438f, +0.9375f,0.398438f, +0.945313f,0.398438f, +0.953125f,0.398438f, +0.960938f,0.398438f, +0.96875f,0.398438f, +0.976563f,0.398438f, +0.984375f,0.398438f, +0.992188f,0.398438f, +1.0f,0.398438f, +0.507813f,0.40625f, +0.515625f,0.40625f, +0.523438f,0.40625f, +0.53125f,0.40625f, +0.539063f,0.40625f, +0.546875f,0.40625f, +0.554688f,0.40625f, +0.5625f,0.40625f, +0.570313f,0.40625f, +0.578125f,0.40625f, +0.585938f,0.40625f, +0.59375f,0.40625f, +0.601563f,0.40625f, +0.609375f,0.40625f, +0.617188f,0.40625f, +0.625f,0.40625f, +0.632813f,0.40625f, +0.640625f,0.40625f, +0.648438f,0.40625f, +0.65625f,0.40625f, +0.664063f,0.40625f, +0.671875f,0.40625f, +0.679688f,0.40625f, +0.6875f,0.40625f, +0.695313f,0.40625f, +0.703125f,0.40625f, +0.710938f,0.40625f, +0.71875f,0.40625f, +0.726563f,0.40625f, +0.734375f,0.40625f, +0.742188f,0.40625f, +0.75f,0.40625f, +0.757813f,0.40625f, +0.765625f,0.40625f, +0.773438f,0.40625f, +0.78125f,0.40625f, +0.789063f,0.40625f, +0.796875f,0.40625f, +0.804688f,0.40625f, +0.8125f,0.40625f, +0.820313f,0.40625f, +0.828125f,0.40625f, +0.835938f,0.40625f, +0.84375f,0.40625f, +0.851563f,0.40625f, +0.859375f,0.40625f, +0.867188f,0.40625f, +0.875f,0.40625f, +0.882813f,0.40625f, +0.890625f,0.40625f, +0.898438f,0.40625f, +0.90625f,0.40625f, +0.914063f,0.40625f, +0.921875f,0.40625f, +0.929688f,0.40625f, +0.9375f,0.40625f, +0.945313f,0.40625f, +0.953125f,0.40625f, +0.960938f,0.40625f, +0.96875f,0.40625f, +0.976563f,0.40625f, +0.984375f,0.40625f, +0.992188f,0.40625f, +1.0f,0.40625f, +0.507813f,0.414063f, +0.515625f,0.414063f, +0.523438f,0.414063f, +0.53125f,0.414063f, +0.539063f,0.414063f, +0.546875f,0.414063f, +0.554688f,0.414063f, +0.5625f,0.414063f, +0.570313f,0.414063f, +0.578125f,0.414063f, +0.585938f,0.414063f, +0.59375f,0.414063f, +0.601563f,0.414063f, +0.609375f,0.414063f, +0.617188f,0.414063f, +0.625f,0.414063f, +0.632813f,0.414063f, +0.640625f,0.414063f, +0.648438f,0.414063f, +0.65625f,0.414063f, +0.664063f,0.414063f, +0.671875f,0.414063f, +0.679688f,0.414063f, +0.6875f,0.414063f, +0.695313f,0.414063f, +0.703125f,0.414063f, +0.710938f,0.414063f, +0.71875f,0.414063f, +0.726563f,0.414063f, +0.734375f,0.414063f, +0.742188f,0.414063f, +0.75f,0.414063f, +0.757813f,0.414063f, +0.765625f,0.414063f, +0.773438f,0.414063f, +0.78125f,0.414063f, +0.789063f,0.414063f, +0.796875f,0.414063f, +0.804688f,0.414063f, +0.8125f,0.414063f, +0.820313f,0.414063f, +0.828125f,0.414063f, +0.835938f,0.414063f, +0.84375f,0.414063f, +0.851563f,0.414063f, +0.859375f,0.414063f, +0.867188f,0.414063f, +0.875f,0.414063f, +0.882813f,0.414063f, +0.890625f,0.414063f, +0.898438f,0.414063f, +0.90625f,0.414063f, +0.914063f,0.414063f, +0.921875f,0.414063f, +0.929688f,0.414063f, +0.9375f,0.414063f, +0.945313f,0.414063f, +0.953125f,0.414063f, +0.960938f,0.414063f, +0.96875f,0.414063f, +0.976563f,0.414063f, +0.984375f,0.414063f, +0.992188f,0.414063f, +1.0f,0.414063f, +0.507813f,0.421875f, +0.515625f,0.421875f, +0.523438f,0.421875f, +0.53125f,0.421875f, +0.539063f,0.421875f, +0.546875f,0.421875f, +0.554688f,0.421875f, +0.5625f,0.421875f, +0.570313f,0.421875f, +0.578125f,0.421875f, +0.585938f,0.421875f, +0.59375f,0.421875f, +0.601563f,0.421875f, +0.609375f,0.421875f, +0.617188f,0.421875f, +0.625f,0.421875f, +0.632813f,0.421875f, +0.640625f,0.421875f, +0.648438f,0.421875f, +0.65625f,0.421875f, +0.664063f,0.421875f, +0.671875f,0.421875f, +0.679688f,0.421875f, +0.6875f,0.421875f, +0.695313f,0.421875f, +0.703125f,0.421875f, +0.710938f,0.421875f, +0.71875f,0.421875f, +0.726563f,0.421875f, +0.734375f,0.421875f, +0.742188f,0.421875f, +0.75f,0.421875f, +0.757813f,0.421875f, +0.765625f,0.421875f, +0.773438f,0.421875f, +0.78125f,0.421875f, +0.789063f,0.421875f, +0.796875f,0.421875f, +0.804688f,0.421875f, +0.8125f,0.421875f, +0.820313f,0.421875f, +0.828125f,0.421875f, +0.835938f,0.421875f, +0.84375f,0.421875f, +0.851563f,0.421875f, +0.859375f,0.421875f, +0.867188f,0.421875f, +0.875f,0.421875f, +0.882813f,0.421875f, +0.890625f,0.421875f, +0.898438f,0.421875f, +0.90625f,0.421875f, +0.914063f,0.421875f, +0.921875f,0.421875f, +0.929688f,0.421875f, +0.9375f,0.421875f, +0.945313f,0.421875f, +0.953125f,0.421875f, +0.960938f,0.421875f, +0.96875f,0.421875f, +0.976563f,0.421875f, +0.984375f,0.421875f, +0.992188f,0.421875f, +1.0f,0.421875f, +0.507813f,0.429688f, +0.515625f,0.429688f, +0.523438f,0.429688f, +0.53125f,0.429688f, +0.539063f,0.429688f, +0.546875f,0.429688f, +0.554688f,0.429688f, +0.5625f,0.429688f, +0.570313f,0.429688f, +0.578125f,0.429688f, +0.585938f,0.429688f, +0.59375f,0.429688f, +0.601563f,0.429688f, +0.609375f,0.429688f, +0.617188f,0.429688f, +0.625f,0.429688f, +0.632813f,0.429688f, +0.640625f,0.429688f, +0.648438f,0.429688f, +0.65625f,0.429688f, +0.664063f,0.429688f, +0.671875f,0.429688f, +0.679688f,0.429688f, +0.6875f,0.429688f, +0.695313f,0.429688f, +0.703125f,0.429688f, +0.710938f,0.429688f, +0.71875f,0.429688f, +0.726563f,0.429688f, +0.734375f,0.429688f, +0.742188f,0.429688f, +0.75f,0.429688f, +0.757813f,0.429688f, +0.765625f,0.429688f, +0.773438f,0.429688f, +0.78125f,0.429688f, +0.789063f,0.429688f, +0.796875f,0.429688f, +0.804688f,0.429688f, +0.8125f,0.429688f, +0.820313f,0.429688f, +0.828125f,0.429688f, +0.835938f,0.429688f, +0.84375f,0.429688f, +0.851563f,0.429688f, +0.859375f,0.429688f, +0.867188f,0.429688f, +0.875f,0.429688f, +0.882813f,0.429688f, +0.890625f,0.429688f, +0.898438f,0.429688f, +0.90625f,0.429688f, +0.914063f,0.429688f, +0.921875f,0.429688f, +0.929688f,0.429688f, +0.9375f,0.429688f, +0.945313f,0.429688f, +0.953125f,0.429688f, +0.960938f,0.429688f, +0.96875f,0.429688f, +0.976563f,0.429688f, +0.984375f,0.429688f, +0.992188f,0.429688f, +1.0f,0.429688f, +0.507813f,0.4375f, +0.515625f,0.4375f, +0.523438f,0.4375f, +0.53125f,0.4375f, +0.539063f,0.4375f, +0.546875f,0.4375f, +0.554688f,0.4375f, +0.5625f,0.4375f, +0.570313f,0.4375f, +0.578125f,0.4375f, +0.585938f,0.4375f, +0.59375f,0.4375f, +0.601563f,0.4375f, +0.609375f,0.4375f, +0.617188f,0.4375f, +0.625f,0.4375f, +0.632813f,0.4375f, +0.640625f,0.4375f, +0.648438f,0.4375f, +0.65625f,0.4375f, +0.664063f,0.4375f, +0.671875f,0.4375f, +0.679688f,0.4375f, +0.6875f,0.4375f, +0.695313f,0.4375f, +0.703125f,0.4375f, +0.710938f,0.4375f, +0.71875f,0.4375f, +0.726563f,0.4375f, +0.734375f,0.4375f, +0.742188f,0.4375f, +0.75f,0.4375f, +0.757813f,0.4375f, +0.765625f,0.4375f, +0.773438f,0.4375f, +0.78125f,0.4375f, +0.789063f,0.4375f, +0.796875f,0.4375f, +0.804688f,0.4375f, +0.8125f,0.4375f, +0.820313f,0.4375f, +0.828125f,0.4375f, +0.835938f,0.4375f, +0.84375f,0.4375f, +0.851563f,0.4375f, +0.859375f,0.4375f, +0.867188f,0.4375f, +0.875f,0.4375f, +0.882813f,0.4375f, +0.890625f,0.4375f, +0.898438f,0.4375f, +0.90625f,0.4375f, +0.914063f,0.4375f, +0.921875f,0.4375f, +0.929688f,0.4375f, +0.9375f,0.4375f, +0.945313f,0.4375f, +0.953125f,0.4375f, +0.960938f,0.4375f, +0.96875f,0.4375f, +0.976563f,0.4375f, +0.984375f,0.4375f, +0.992188f,0.4375f, +1.0f,0.4375f, +0.507813f,0.445313f, +0.515625f,0.445313f, +0.523438f,0.445313f, +0.53125f,0.445313f, +0.539063f,0.445313f, +0.546875f,0.445313f, +0.554688f,0.445313f, +0.5625f,0.445313f, +0.570313f,0.445313f, +0.578125f,0.445313f, +0.585938f,0.445313f, +0.59375f,0.445313f, +0.601563f,0.445313f, +0.609375f,0.445313f, +0.617188f,0.445313f, +0.625f,0.445313f, +0.632813f,0.445313f, +0.640625f,0.445313f, +0.648438f,0.445313f, +0.65625f,0.445313f, +0.664063f,0.445313f, +0.671875f,0.445313f, +0.679688f,0.445313f, +0.6875f,0.445313f, +0.695313f,0.445313f, +0.703125f,0.445313f, +0.710938f,0.445313f, +0.71875f,0.445313f, +0.726563f,0.445313f, +0.734375f,0.445313f, +0.742188f,0.445313f, +0.75f,0.445313f, +0.757813f,0.445313f, +0.765625f,0.445313f, +0.773438f,0.445313f, +0.78125f,0.445313f, +0.789063f,0.445313f, +0.796875f,0.445313f, +0.804688f,0.445313f, +0.8125f,0.445313f, +0.820313f,0.445313f, +0.828125f,0.445313f, +0.835938f,0.445313f, +0.84375f,0.445313f, +0.851563f,0.445313f, +0.859375f,0.445313f, +0.867188f,0.445313f, +0.875f,0.445313f, +0.882813f,0.445313f, +0.890625f,0.445313f, +0.898438f,0.445313f, +0.90625f,0.445313f, +0.914063f,0.445313f, +0.921875f,0.445313f, +0.929688f,0.445313f, +0.9375f,0.445313f, +0.945313f,0.445313f, +0.953125f,0.445313f, +0.960938f,0.445313f, +0.96875f,0.445313f, +0.976563f,0.445313f, +0.984375f,0.445313f, +0.992188f,0.445313f, +1.0f,0.445313f, +0.507813f,0.453125f, +0.515625f,0.453125f, +0.523438f,0.453125f, +0.53125f,0.453125f, +0.539063f,0.453125f, +0.546875f,0.453125f, +0.554688f,0.453125f, +0.5625f,0.453125f, +0.570313f,0.453125f, +0.578125f,0.453125f, +0.585938f,0.453125f, +0.59375f,0.453125f, +0.601563f,0.453125f, +0.609375f,0.453125f, +0.617188f,0.453125f, +0.625f,0.453125f, +0.632813f,0.453125f, +0.640625f,0.453125f, +0.648438f,0.453125f, +0.65625f,0.453125f, +0.664063f,0.453125f, +0.671875f,0.453125f, +0.679688f,0.453125f, +0.6875f,0.453125f, +0.695313f,0.453125f, +0.703125f,0.453125f, +0.710938f,0.453125f, +0.71875f,0.453125f, +0.726563f,0.453125f, +0.734375f,0.453125f, +0.742188f,0.453125f, +0.75f,0.453125f, +0.757813f,0.453125f, +0.765625f,0.453125f, +0.773438f,0.453125f, +0.78125f,0.453125f, +0.789063f,0.453125f, +0.796875f,0.453125f, +0.804688f,0.453125f, +0.8125f,0.453125f, +0.820313f,0.453125f, +0.828125f,0.453125f, +0.835938f,0.453125f, +0.84375f,0.453125f, +0.851563f,0.453125f, +0.859375f,0.453125f, +0.867188f,0.453125f, +0.875f,0.453125f, +0.882813f,0.453125f, +0.890625f,0.453125f, +0.898438f,0.453125f, +0.90625f,0.453125f, +0.914063f,0.453125f, +0.921875f,0.453125f, +0.929688f,0.453125f, +0.9375f,0.453125f, +0.945313f,0.453125f, +0.953125f,0.453125f, +0.960938f,0.453125f, +0.96875f,0.453125f, +0.976563f,0.453125f, +0.984375f,0.453125f, +0.992188f,0.453125f, +1.0f,0.453125f, +0.507813f,0.460938f, +0.515625f,0.460938f, +0.523438f,0.460938f, +0.53125f,0.460938f, +0.539063f,0.460938f, +0.546875f,0.460938f, +0.554688f,0.460938f, +0.5625f,0.460938f, +0.570313f,0.460938f, +0.578125f,0.460938f, +0.585938f,0.460938f, +0.59375f,0.460938f, +0.601563f,0.460938f, +0.609375f,0.460938f, +0.617188f,0.460938f, +0.625f,0.460938f, +0.632813f,0.460938f, +0.640625f,0.460938f, +0.648438f,0.460938f, +0.65625f,0.460938f, +0.664063f,0.460938f, +0.671875f,0.460938f, +0.679688f,0.460938f, +0.6875f,0.460938f, +0.695313f,0.460938f, +0.703125f,0.460938f, +0.710938f,0.460938f, +0.71875f,0.460938f, +0.726563f,0.460938f, +0.734375f,0.460938f, +0.742188f,0.460938f, +0.75f,0.460938f, +0.757813f,0.460938f, +0.765625f,0.460938f, +0.773438f,0.460938f, +0.78125f,0.460938f, +0.789063f,0.460938f, +0.796875f,0.460938f, +0.804688f,0.460938f, +0.8125f,0.460938f, +0.820313f,0.460938f, +0.828125f,0.460938f, +0.835938f,0.460938f, +0.84375f,0.460938f, +0.851563f,0.460938f, +0.859375f,0.460938f, +0.867188f,0.460938f, +0.875f,0.460938f, +0.882813f,0.460938f, +0.890625f,0.460938f, +0.898438f,0.460938f, +0.90625f,0.460938f, +0.914063f,0.460938f, +0.921875f,0.460938f, +0.929688f,0.460938f, +0.9375f,0.460938f, +0.945313f,0.460938f, +0.953125f,0.460938f, +0.960938f,0.460938f, +0.96875f,0.460938f, +0.976563f,0.460938f, +0.984375f,0.460938f, +0.992188f,0.460938f, +1.0f,0.460938f, +0.507813f,0.46875f, +0.515625f,0.46875f, +0.523438f,0.46875f, +0.53125f,0.46875f, +0.539063f,0.46875f, +0.546875f,0.46875f, +0.554688f,0.46875f, +0.5625f,0.46875f, +0.570313f,0.46875f, +0.578125f,0.46875f, +0.585938f,0.46875f, +0.59375f,0.46875f, +0.601563f,0.46875f, +0.609375f,0.46875f, +0.617188f,0.46875f, +0.625f,0.46875f, +0.632813f,0.46875f, +0.640625f,0.46875f, +0.648438f,0.46875f, +0.65625f,0.46875f, +0.664063f,0.46875f, +0.671875f,0.46875f, +0.679688f,0.46875f, +0.6875f,0.46875f, +0.695313f,0.46875f, +0.703125f,0.46875f, +0.710938f,0.46875f, +0.71875f,0.46875f, +0.726563f,0.46875f, +0.734375f,0.46875f, +0.742188f,0.46875f, +0.75f,0.46875f, +0.757813f,0.46875f, +0.765625f,0.46875f, +0.773438f,0.46875f, +0.78125f,0.46875f, +0.789063f,0.46875f, +0.796875f,0.46875f, +0.804688f,0.46875f, +0.8125f,0.46875f, +0.820313f,0.46875f, +0.828125f,0.46875f, +0.835938f,0.46875f, +0.84375f,0.46875f, +0.851563f,0.46875f, +0.859375f,0.46875f, +0.867188f,0.46875f, +0.875f,0.46875f, +0.882813f,0.46875f, +0.890625f,0.46875f, +0.898438f,0.46875f, +0.90625f,0.46875f, +0.914063f,0.46875f, +0.921875f,0.46875f, +0.929688f,0.46875f, +0.9375f,0.46875f, +0.945313f,0.46875f, +0.953125f,0.46875f, +0.960938f,0.46875f, +0.96875f,0.46875f, +0.976563f,0.46875f, +0.984375f,0.46875f, +0.992188f,0.46875f, +1.0f,0.46875f, +0.507813f,0.476563f, +0.515625f,0.476563f, +0.523438f,0.476563f, +0.53125f,0.476563f, +0.539063f,0.476563f, +0.546875f,0.476563f, +0.554688f,0.476563f, +0.5625f,0.476563f, +0.570313f,0.476563f, +0.578125f,0.476563f, +0.585938f,0.476563f, +0.59375f,0.476563f, +0.601563f,0.476563f, +0.609375f,0.476563f, +0.617188f,0.476563f, +0.625f,0.476563f, +0.632813f,0.476563f, +0.640625f,0.476563f, +0.648438f,0.476563f, +0.65625f,0.476563f, +0.664063f,0.476563f, +0.671875f,0.476563f, +0.679688f,0.476563f, +0.6875f,0.476563f, +0.695313f,0.476563f, +0.703125f,0.476563f, +0.710938f,0.476563f, +0.71875f,0.476563f, +0.726563f,0.476563f, +0.734375f,0.476563f, +0.742188f,0.476563f, +0.75f,0.476563f, +0.757813f,0.476563f, +0.765625f,0.476563f, +0.773438f,0.476563f, +0.78125f,0.476563f, +0.789063f,0.476563f, +0.796875f,0.476563f, +0.804688f,0.476563f, +0.8125f,0.476563f, +0.820313f,0.476563f, +0.828125f,0.476563f, +0.835938f,0.476563f, +0.84375f,0.476563f, +0.851563f,0.476563f, +0.859375f,0.476563f, +0.867188f,0.476563f, +0.875f,0.476563f, +0.882813f,0.476563f, +0.890625f,0.476563f, +0.898438f,0.476563f, +0.90625f,0.476563f, +0.914063f,0.476563f, +0.921875f,0.476563f, +0.929688f,0.476563f, +0.9375f,0.476563f, +0.945313f,0.476563f, +0.953125f,0.476563f, +0.960938f,0.476563f, +0.96875f,0.476563f, +0.976563f,0.476563f, +0.984375f,0.476563f, +0.992188f,0.476563f, +1.0f,0.476563f, +0.507813f,0.484375f, +0.515625f,0.484375f, +0.523438f,0.484375f, +0.53125f,0.484375f, +0.539063f,0.484375f, +0.546875f,0.484375f, +0.554688f,0.484375f, +0.5625f,0.484375f, +0.570313f,0.484375f, +0.578125f,0.484375f, +0.585938f,0.484375f, +0.59375f,0.484375f, +0.601563f,0.484375f, +0.609375f,0.484375f, +0.617188f,0.484375f, +0.625f,0.484375f, +0.632813f,0.484375f, +0.640625f,0.484375f, +0.648438f,0.484375f, +0.65625f,0.484375f, +0.664063f,0.484375f, +0.671875f,0.484375f, +0.679688f,0.484375f, +0.6875f,0.484375f, +0.695313f,0.484375f, +0.703125f,0.484375f, +0.710938f,0.484375f, +0.71875f,0.484375f, +0.726563f,0.484375f, +0.734375f,0.484375f, +0.742188f,0.484375f, +0.75f,0.484375f, +0.757813f,0.484375f, +0.765625f,0.484375f, +0.773438f,0.484375f, +0.78125f,0.484375f, +0.789063f,0.484375f, +0.796875f,0.484375f, +0.804688f,0.484375f, +0.8125f,0.484375f, +0.820313f,0.484375f, +0.828125f,0.484375f, +0.835938f,0.484375f, +0.84375f,0.484375f, +0.851563f,0.484375f, +0.859375f,0.484375f, +0.867188f,0.484375f, +0.875f,0.484375f, +0.882813f,0.484375f, +0.890625f,0.484375f, +0.898438f,0.484375f, +0.90625f,0.484375f, +0.914063f,0.484375f, +0.921875f,0.484375f, +0.929688f,0.484375f, +0.9375f,0.484375f, +0.945313f,0.484375f, +0.953125f,0.484375f, +0.960938f,0.484375f, +0.96875f,0.484375f, +0.976563f,0.484375f, +0.984375f,0.484375f, +0.992188f,0.484375f, +1.0f,0.484375f, +0.507813f,0.492188f, +0.515625f,0.492188f, +0.523438f,0.492188f, +0.53125f,0.492188f, +0.539063f,0.492188f, +0.546875f,0.492188f, +0.554688f,0.492188f, +0.5625f,0.492188f, +0.570313f,0.492188f, +0.578125f,0.492188f, +0.585938f,0.492188f, +0.59375f,0.492188f, +0.601563f,0.492188f, +0.609375f,0.492188f, +0.617188f,0.492188f, +0.625f,0.492188f, +0.632813f,0.492188f, +0.640625f,0.492188f, +0.648438f,0.492188f, +0.65625f,0.492188f, +0.664063f,0.492188f, +0.671875f,0.492188f, +0.679688f,0.492188f, +0.6875f,0.492188f, +0.695313f,0.492188f, +0.703125f,0.492188f, +0.710938f,0.492188f, +0.71875f,0.492188f, +0.726563f,0.492188f, +0.734375f,0.492188f, +0.742188f,0.492188f, +0.75f,0.492188f, +0.757813f,0.492188f, +0.765625f,0.492188f, +0.773438f,0.492188f, +0.78125f,0.492188f, +0.789063f,0.492188f, +0.796875f,0.492188f, +0.804688f,0.492188f, +0.8125f,0.492188f, +0.820313f,0.492188f, +0.828125f,0.492188f, +0.835938f,0.492188f, +0.84375f,0.492188f, +0.851563f,0.492188f, +0.859375f,0.492188f, +0.867188f,0.492188f, +0.875f,0.492188f, +0.882813f,0.492188f, +0.890625f,0.492188f, +0.898438f,0.492188f, +0.90625f,0.492188f, +0.914063f,0.492188f, +0.921875f,0.492188f, +0.929688f,0.492188f, +0.9375f,0.492188f, +0.945313f,0.492188f, +0.953125f,0.492188f, +0.960938f,0.492188f, +0.96875f,0.492188f, +0.976563f,0.492188f, +0.984375f,0.492188f, +0.992188f,0.492188f, +1.0f,0.492188f, +}; + +unsigned short Landscape04Idx[] = { +0,1,2, +3,2,1, +2,3,4, +5,4,3, +4,5,6, +7,6,5, +6,7,8, +9,8,7, +8,9,10, +11,10,9, +10,11,12, +13,12,11, +12,13,14, +15,14,13, +14,15,16, +17,16,15, +16,17,18, +19,18,17, +18,19,20, +21,20,19, +20,21,22, +23,22,21, +22,23,24, +25,24,23, +24,25,26, +27,26,25, +26,27,28, +29,28,27, +28,29,30, +31,30,29, +30,31,32, +33,32,31, +32,33,34, +35,34,33, +34,35,36, +37,36,35, +36,37,38, +39,38,37, +38,39,40, +41,40,39, +40,41,42, +43,42,41, +42,43,44, +45,44,43, +44,45,46, +47,46,45, +46,47,48, +49,48,47, +48,49,50, +51,50,49, +50,51,52, +53,52,51, +52,53,54, +55,54,53, +54,55,56, +57,56,55, +56,57,58, +59,58,57, +58,59,60, +61,60,59, +60,61,62, +63,62,61, +62,63,64, +65,64,63, +64,65,66, +67,66,65, +66,67,68, +69,68,67, +68,69,70, +71,70,69, +70,71,72, +73,72,71, +72,73,74, +75,74,73, +74,75,76, +77,76,75, +76,77,78, +79,78,77, +78,79,80, +81,80,79, +80,81,82, +83,82,81, +82,83,84, +85,84,83, +84,85,86, +87,86,85, +86,87,88, +89,88,87, +88,89,90, +91,90,89, +90,91,92, +93,92,91, +92,93,94, +95,94,93, +94,95,96, +97,96,95, +96,97,98, +99,98,97, +98,99,100, +101,100,99, +100,101,102, +103,102,101, +102,103,104, +105,104,103, +104,105,106, +107,106,105, +106,107,108, +109,108,107, +108,109,110, +111,110,109, +110,111,112, +113,112,111, +112,113,114, +115,114,113, +114,115,116, +117,116,115, +116,117,118, +119,118,117, +118,119,120, +121,120,119, +120,121,122, +123,122,121, +122,123,124, +125,124,123, +124,125,126, +127,126,125, +128,0,129, +2,129,0, +129,2,130, +4,130,2, +130,4,131, +6,131,4, +131,6,132, +8,132,6, +132,8,133, +10,133,8, +133,10,134, +12,134,10, +134,12,135, +14,135,12, +135,14,136, +16,136,14, +136,16,137, +18,137,16, +137,18,138, +20,138,18, +138,20,139, +22,139,20, +139,22,140, +24,140,22, +140,24,141, +26,141,24, +141,26,142, +28,142,26, +142,28,143, +30,143,28, +143,30,144, +32,144,30, +144,32,145, +34,145,32, +145,34,146, +36,146,34, +146,36,147, +38,147,36, +147,38,148, +40,148,38, +148,40,149, +42,149,40, +149,42,150, +44,150,42, +150,44,151, +46,151,44, +151,46,152, +48,152,46, +152,48,153, +50,153,48, +153,50,154, +52,154,50, +154,52,155, +54,155,52, +155,54,156, +56,156,54, +156,56,157, +58,157,56, +157,58,158, +60,158,58, +158,60,159, +62,159,60, +159,62,160, +64,160,62, +160,64,161, +66,161,64, +161,66,162, +68,162,66, +162,68,163, +70,163,68, +163,70,164, +72,164,70, +164,72,165, +74,165,72, +165,74,166, +76,166,74, +166,76,167, +78,167,76, +167,78,168, +80,168,78, +168,80,169, +82,169,80, +169,82,170, +84,170,82, +170,84,171, +86,171,84, +171,86,172, +88,172,86, +172,88,173, +90,173,88, +173,90,174, +92,174,90, +174,92,175, +94,175,92, +175,94,176, +96,176,94, +176,96,177, +98,177,96, +177,98,178, +100,178,98, +178,100,179, +102,179,100, +179,102,180, +104,180,102, +180,104,181, +106,181,104, +181,106,182, +108,182,106, +182,108,183, +110,183,108, +183,110,184, +112,184,110, +184,112,185, +114,185,112, +185,114,186, +116,186,114, +186,116,187, +118,187,116, +187,118,188, +120,188,118, +188,120,189, +122,189,120, +189,122,190, +124,190,122, +190,124,191, +126,191,124, +192,128,193, +129,193,128, +193,129,194, +130,194,129, +194,130,195, +131,195,130, +195,131,196, +132,196,131, +196,132,197, +133,197,132, +197,133,198, +134,198,133, +198,134,199, +135,199,134, +199,135,200, +136,200,135, +200,136,201, +137,201,136, +201,137,202, +138,202,137, +202,138,203, +139,203,138, +203,139,204, +140,204,139, +204,140,205, +141,205,140, +205,141,206, +142,206,141, +206,142,207, +143,207,142, +207,143,208, +144,208,143, +208,144,209, +145,209,144, +209,145,210, +146,210,145, +210,146,211, +147,211,146, +211,147,212, +148,212,147, +212,148,213, +149,213,148, +213,149,214, +150,214,149, +214,150,215, +151,215,150, +215,151,216, +152,216,151, +216,152,217, +153,217,152, +217,153,218, +154,218,153, +218,154,219, +155,219,154, +219,155,220, +156,220,155, +220,156,221, +157,221,156, +221,157,222, +158,222,157, +222,158,223, +159,223,158, +223,159,224, +160,224,159, +224,160,225, +161,225,160, +225,161,226, +162,226,161, +226,162,227, +163,227,162, +227,163,228, +164,228,163, +228,164,229, +165,229,164, +229,165,230, +166,230,165, +230,166,231, +167,231,166, +231,167,232, +168,232,167, +232,168,233, +169,233,168, +233,169,234, +170,234,169, +234,170,235, +171,235,170, +235,171,236, +172,236,171, +236,172,237, +173,237,172, +237,173,238, +174,238,173, +238,174,239, +175,239,174, +239,175,240, +176,240,175, +240,176,241, +177,241,176, +241,177,242, +178,242,177, +242,178,243, +179,243,178, +243,179,244, +180,244,179, +244,180,245, +181,245,180, +245,181,246, +182,246,181, +246,182,247, +183,247,182, +247,183,248, +184,248,183, +248,184,249, +185,249,184, +249,185,250, +186,250,185, +250,186,251, +187,251,186, +251,187,252, +188,252,187, +252,188,253, +189,253,188, +253,189,254, +190,254,189, +254,190,255, +191,255,190, +256,192,257, +193,257,192, +257,193,258, +194,258,193, +258,194,259, +195,259,194, +259,195,260, +196,260,195, +260,196,261, +197,261,196, +261,197,262, +198,262,197, +262,198,263, +199,263,198, +263,199,264, +200,264,199, +264,200,265, +201,265,200, +265,201,266, +202,266,201, +266,202,267, +203,267,202, +267,203,268, +204,268,203, +268,204,269, +205,269,204, +269,205,270, +206,270,205, +270,206,271, +207,271,206, +271,207,272, +208,272,207, +272,208,273, +209,273,208, +273,209,274, +210,274,209, +274,210,275, +211,275,210, +275,211,276, +212,276,211, +276,212,277, +213,277,212, +277,213,278, +214,278,213, +278,214,279, +215,279,214, +279,215,280, +216,280,215, +280,216,281, +217,281,216, +281,217,282, +218,282,217, +282,218,283, +219,283,218, +283,219,284, +220,284,219, +284,220,285, +221,285,220, +285,221,286, +222,286,221, +286,222,287, +223,287,222, +287,223,288, +224,288,223, +288,224,289, +225,289,224, +289,225,290, +226,290,225, +290,226,291, +227,291,226, +291,227,292, +228,292,227, +292,228,293, +229,293,228, +293,229,294, +230,294,229, +294,230,295, +231,295,230, +295,231,296, +232,296,231, +296,232,297, +233,297,232, +297,233,298, +234,298,233, +298,234,299, +235,299,234, +299,235,300, +236,300,235, +300,236,301, +237,301,236, +301,237,302, +238,302,237, +302,238,303, +239,303,238, +303,239,304, +240,304,239, +304,240,305, +241,305,240, +305,241,306, +242,306,241, +306,242,307, +243,307,242, +307,243,308, +244,308,243, +308,244,309, +245,309,244, +309,245,310, +246,310,245, +310,246,311, +247,311,246, +311,247,312, +248,312,247, +312,248,313, +249,313,248, +313,249,314, +250,314,249, +314,250,315, +251,315,250, +315,251,316, +252,316,251, +316,252,317, +253,317,252, +317,253,318, +254,318,253, +318,254,319, +255,319,254, +320,256,321, +257,321,256, +321,257,322, +258,322,257, +322,258,323, +259,323,258, +323,259,324, +260,324,259, +324,260,325, +261,325,260, +325,261,326, +262,326,261, +326,262,327, +263,327,262, +327,263,328, +264,328,263, +328,264,329, +265,329,264, +329,265,330, +266,330,265, +330,266,331, +267,331,266, +331,267,332, +268,332,267, +332,268,333, +269,333,268, +333,269,334, +270,334,269, +334,270,335, +271,335,270, +335,271,336, +272,336,271, +336,272,337, +273,337,272, +337,273,338, +274,338,273, +338,274,339, +275,339,274, +339,275,340, +276,340,275, +340,276,341, +277,341,276, +341,277,342, +278,342,277, +342,278,343, +279,343,278, +343,279,344, +280,344,279, +344,280,345, +281,345,280, +345,281,346, +282,346,281, +346,282,347, +283,347,282, +347,283,348, +284,348,283, +348,284,349, +285,349,284, +349,285,350, +286,350,285, +350,286,351, +287,351,286, +351,287,352, +288,352,287, +352,288,353, +289,353,288, +353,289,354, +290,354,289, +354,290,355, +291,355,290, +355,291,356, +292,356,291, +356,292,357, +293,357,292, +357,293,358, +294,358,293, +358,294,359, +295,359,294, +359,295,360, +296,360,295, +360,296,361, +297,361,296, +361,297,362, +298,362,297, +362,298,363, +299,363,298, +363,299,364, +300,364,299, +364,300,365, +301,365,300, +365,301,366, +302,366,301, +366,302,367, +303,367,302, +367,303,368, +304,368,303, +368,304,369, +305,369,304, +369,305,370, +306,370,305, +370,306,371, +307,371,306, +371,307,372, +308,372,307, +372,308,373, +309,373,308, +373,309,374, +310,374,309, +374,310,375, +311,375,310, +375,311,376, +312,376,311, +376,312,377, +313,377,312, +377,313,378, +314,378,313, +378,314,379, +315,379,314, +379,315,380, +316,380,315, +380,316,381, +317,381,316, +381,317,382, +318,382,317, +382,318,383, +319,383,318, +384,320,385, +321,385,320, +385,321,386, +322,386,321, +386,322,387, +323,387,322, +387,323,388, +324,388,323, +388,324,389, +325,389,324, +389,325,390, +326,390,325, +390,326,391, +327,391,326, +391,327,392, +328,392,327, +392,328,393, +329,393,328, +393,329,394, +330,394,329, +394,330,395, +331,395,330, +395,331,396, +332,396,331, +396,332,397, +333,397,332, +397,333,398, +334,398,333, +398,334,399, +335,399,334, +399,335,400, +336,400,335, +400,336,401, +337,401,336, +401,337,402, +338,402,337, +402,338,403, +339,403,338, +403,339,404, +340,404,339, +404,340,405, +341,405,340, +405,341,406, +342,406,341, +406,342,407, +343,407,342, +407,343,408, +344,408,343, +408,344,409, +345,409,344, +409,345,410, +346,410,345, +410,346,411, +347,411,346, +411,347,412, +348,412,347, +412,348,413, +349,413,348, +413,349,414, +350,414,349, +414,350,415, +351,415,350, +415,351,416, +352,416,351, +416,352,417, +353,417,352, +417,353,418, +354,418,353, +418,354,419, +355,419,354, +419,355,420, +356,420,355, +420,356,421, +357,421,356, +421,357,422, +358,422,357, +422,358,423, +359,423,358, +423,359,424, +360,424,359, +424,360,425, +361,425,360, +425,361,426, +362,426,361, +426,362,427, +363,427,362, +427,363,428, +364,428,363, +428,364,429, +365,429,364, +429,365,430, +366,430,365, +430,366,431, +367,431,366, +431,367,432, +368,432,367, +432,368,433, +369,433,368, +433,369,434, +370,434,369, +434,370,435, +371,435,370, +435,371,436, +372,436,371, +436,372,437, +373,437,372, +437,373,438, +374,438,373, +438,374,439, +375,439,374, +439,375,440, +376,440,375, +440,376,441, +377,441,376, +441,377,442, +378,442,377, +442,378,443, +379,443,378, +443,379,444, +380,444,379, +444,380,445, +381,445,380, +445,381,446, +382,446,381, +446,382,447, +383,447,382, +448,384,449, +385,449,384, +449,385,450, +386,450,385, +450,386,451, +387,451,386, +451,387,452, +388,452,387, +452,388,453, +389,453,388, +453,389,454, +390,454,389, +454,390,455, +391,455,390, +455,391,456, +392,456,391, +456,392,457, +393,457,392, +457,393,458, +394,458,393, +458,394,459, +395,459,394, +459,395,460, +396,460,395, +460,396,461, +397,461,396, +461,397,462, +398,462,397, +462,398,463, +399,463,398, +463,399,464, +400,464,399, +464,400,465, +401,465,400, +465,401,466, +402,466,401, +466,402,467, +403,467,402, +467,403,468, +404,468,403, +468,404,469, +405,469,404, +469,405,470, +406,470,405, +470,406,471, +407,471,406, +471,407,472, +408,472,407, +472,408,473, +409,473,408, +473,409,474, +410,474,409, +474,410,475, +411,475,410, +475,411,476, +412,476,411, +476,412,477, +413,477,412, +477,413,478, +414,478,413, +478,414,479, +415,479,414, +479,415,480, +416,480,415, +480,416,481, +417,481,416, +481,417,482, +418,482,417, +482,418,483, +419,483,418, +483,419,484, +420,484,419, +484,420,485, +421,485,420, +485,421,486, +422,486,421, +486,422,487, +423,487,422, +487,423,488, +424,488,423, +488,424,489, +425,489,424, +489,425,490, +426,490,425, +490,426,491, +427,491,426, +491,427,492, +428,492,427, +492,428,493, +429,493,428, +493,429,494, +430,494,429, +494,430,495, +431,495,430, +495,431,496, +432,496,431, +496,432,497, +433,497,432, +497,433,498, +434,498,433, +498,434,499, +435,499,434, +499,435,500, +436,500,435, +500,436,501, +437,501,436, +501,437,502, +438,502,437, +502,438,503, +439,503,438, +503,439,504, +440,504,439, +504,440,505, +441,505,440, +505,441,506, +442,506,441, +506,442,507, +443,507,442, +507,443,508, +444,508,443, +508,444,509, +445,509,444, +509,445,510, +446,510,445, +510,446,511, +447,511,446, +512,448,513, +449,513,448, +513,449,514, +450,514,449, +514,450,515, +451,515,450, +515,451,516, +452,516,451, +516,452,517, +453,517,452, +517,453,518, +454,518,453, +518,454,519, +455,519,454, +519,455,520, +456,520,455, +520,456,521, +457,521,456, +521,457,522, +458,522,457, +522,458,523, +459,523,458, +523,459,524, +460,524,459, +524,460,525, +461,525,460, +525,461,526, +462,526,461, +526,462,527, +463,527,462, +527,463,528, +464,528,463, +528,464,529, +465,529,464, +529,465,530, +466,530,465, +530,466,531, +467,531,466, +531,467,532, +468,532,467, +532,468,533, +469,533,468, +533,469,534, +470,534,469, +534,470,535, +471,535,470, +535,471,536, +472,536,471, +536,472,537, +473,537,472, +537,473,538, +474,538,473, +538,474,539, +475,539,474, +539,475,540, +476,540,475, +540,476,541, +477,541,476, +541,477,542, +478,542,477, +542,478,543, +479,543,478, +543,479,544, +480,544,479, +544,480,545, +481,545,480, +545,481,546, +482,546,481, +546,482,547, +483,547,482, +547,483,548, +484,548,483, +548,484,549, +485,549,484, +549,485,550, +486,550,485, +550,486,551, +487,551,486, +551,487,552, +488,552,487, +552,488,553, +489,553,488, +553,489,554, +490,554,489, +554,490,555, +491,555,490, +555,491,556, +492,556,491, +556,492,557, +493,557,492, +557,493,558, +494,558,493, +558,494,559, +495,559,494, +559,495,560, +496,560,495, +560,496,561, +497,561,496, +561,497,562, +498,562,497, +562,498,563, +499,563,498, +563,499,564, +500,564,499, +564,500,565, +501,565,500, +565,501,566, +502,566,501, +566,502,567, +503,567,502, +567,503,568, +504,568,503, +568,504,569, +505,569,504, +569,505,570, +506,570,505, +570,506,571, +507,571,506, +571,507,572, +508,572,507, +572,508,573, +509,573,508, +573,509,574, +510,574,509, +574,510,575, +511,575,510, +576,512,577, +513,577,512, +577,513,578, +514,578,513, +578,514,579, +515,579,514, +579,515,580, +516,580,515, +580,516,581, +517,581,516, +581,517,582, +518,582,517, +582,518,583, +519,583,518, +583,519,584, +520,584,519, +584,520,585, +521,585,520, +585,521,586, +522,586,521, +586,522,587, +523,587,522, +587,523,588, +524,588,523, +588,524,589, +525,589,524, +589,525,590, +526,590,525, +590,526,591, +527,591,526, +591,527,592, +528,592,527, +592,528,593, +529,593,528, +593,529,594, +530,594,529, +594,530,595, +531,595,530, +595,531,596, +532,596,531, +596,532,597, +533,597,532, +597,533,598, +534,598,533, +598,534,599, +535,599,534, +599,535,600, +536,600,535, +600,536,601, +537,601,536, +601,537,602, +538,602,537, +602,538,603, +539,603,538, +603,539,604, +540,604,539, +604,540,605, +541,605,540, +605,541,606, +542,606,541, +606,542,607, +543,607,542, +607,543,608, +544,608,543, +608,544,609, +545,609,544, +609,545,610, +546,610,545, +610,546,611, +547,611,546, +611,547,612, +548,612,547, +612,548,613, +549,613,548, +613,549,614, +550,614,549, +614,550,615, +551,615,550, +615,551,616, +552,616,551, +616,552,617, +553,617,552, +617,553,618, +554,618,553, +618,554,619, +555,619,554, +619,555,620, +556,620,555, +620,556,621, +557,621,556, +621,557,622, +558,622,557, +622,558,623, +559,623,558, +623,559,624, +560,624,559, +624,560,625, +561,625,560, +625,561,626, +562,626,561, +626,562,627, +563,627,562, +627,563,628, +564,628,563, +628,564,629, +565,629,564, +629,565,630, +566,630,565, +630,566,631, +567,631,566, +631,567,632, +568,632,567, +632,568,633, +569,633,568, +633,569,634, +570,634,569, +634,570,635, +571,635,570, +635,571,636, +572,636,571, +636,572,637, +573,637,572, +637,573,638, +574,638,573, +638,574,639, +575,639,574, +640,576,641, +577,641,576, +641,577,642, +578,642,577, +642,578,643, +579,643,578, +643,579,644, +580,644,579, +644,580,645, +581,645,580, +645,581,646, +582,646,581, +646,582,647, +583,647,582, +647,583,648, +584,648,583, +648,584,649, +585,649,584, +649,585,650, +586,650,585, +650,586,651, +587,651,586, +651,587,652, +588,652,587, +652,588,653, +589,653,588, +653,589,654, +590,654,589, +654,590,655, +591,655,590, +655,591,656, +592,656,591, +656,592,657, +593,657,592, +657,593,658, +594,658,593, +658,594,659, +595,659,594, +659,595,660, +596,660,595, +660,596,661, +597,661,596, +661,597,662, +598,662,597, +662,598,663, +599,663,598, +663,599,664, +600,664,599, +664,600,665, +601,665,600, +665,601,666, +602,666,601, +666,602,667, +603,667,602, +667,603,668, +604,668,603, +668,604,669, +605,669,604, +669,605,670, +606,670,605, +670,606,671, +607,671,606, +671,607,672, +608,672,607, +672,608,673, +609,673,608, +673,609,674, +610,674,609, +674,610,675, +611,675,610, +675,611,676, +612,676,611, +676,612,677, +613,677,612, +677,613,678, +614,678,613, +678,614,679, +615,679,614, +679,615,680, +616,680,615, +680,616,681, +617,681,616, +681,617,682, +618,682,617, +682,618,683, +619,683,618, +683,619,684, +620,684,619, +684,620,685, +621,685,620, +685,621,686, +622,686,621, +686,622,687, +623,687,622, +687,623,688, +624,688,623, +688,624,689, +625,689,624, +689,625,690, +626,690,625, +690,626,691, +627,691,626, +691,627,692, +628,692,627, +692,628,693, +629,693,628, +693,629,694, +630,694,629, +694,630,695, +631,695,630, +695,631,696, +632,696,631, +696,632,697, +633,697,632, +697,633,698, +634,698,633, +698,634,699, +635,699,634, +699,635,700, +636,700,635, +700,636,701, +637,701,636, +701,637,702, +638,702,637, +702,638,703, +639,703,638, +704,640,705, +641,705,640, +705,641,706, +642,706,641, +706,642,707, +643,707,642, +707,643,708, +644,708,643, +708,644,709, +645,709,644, +709,645,710, +646,710,645, +710,646,711, +647,711,646, +711,647,712, +648,712,647, +712,648,713, +649,713,648, +713,649,714, +650,714,649, +714,650,715, +651,715,650, +715,651,716, +652,716,651, +716,652,717, +653,717,652, +717,653,718, +654,718,653, +718,654,719, +655,719,654, +719,655,720, +656,720,655, +720,656,721, +657,721,656, +721,657,722, +658,722,657, +722,658,723, +659,723,658, +723,659,724, +660,724,659, +724,660,725, +661,725,660, +725,661,726, +662,726,661, +726,662,727, +663,727,662, +727,663,728, +664,728,663, +728,664,729, +665,729,664, +729,665,730, +666,730,665, +730,666,731, +667,731,666, +731,667,732, +668,732,667, +732,668,733, +669,733,668, +733,669,734, +670,734,669, +734,670,735, +671,735,670, +735,671,736, +672,736,671, +736,672,737, +673,737,672, +737,673,738, +674,738,673, +738,674,739, +675,739,674, +739,675,740, +676,740,675, +740,676,741, +677,741,676, +741,677,742, +678,742,677, +742,678,743, +679,743,678, +743,679,744, +680,744,679, +744,680,745, +681,745,680, +745,681,746, +682,746,681, +746,682,747, +683,747,682, +747,683,748, +684,748,683, +748,684,749, +685,749,684, +749,685,750, +686,750,685, +750,686,751, +687,751,686, +751,687,752, +688,752,687, +752,688,753, +689,753,688, +753,689,754, +690,754,689, +754,690,755, +691,755,690, +755,691,756, +692,756,691, +756,692,757, +693,757,692, +757,693,758, +694,758,693, +758,694,759, +695,759,694, +759,695,760, +696,760,695, +760,696,761, +697,761,696, +761,697,762, +698,762,697, +762,698,763, +699,763,698, +763,699,764, +700,764,699, +764,700,765, +701,765,700, +765,701,766, +702,766,701, +766,702,767, +703,767,702, +768,704,769, +705,769,704, +769,705,770, +706,770,705, +770,706,771, +707,771,706, +771,707,772, +708,772,707, +772,708,773, +709,773,708, +773,709,774, +710,774,709, +774,710,775, +711,775,710, +775,711,776, +712,776,711, +776,712,777, +713,777,712, +777,713,778, +714,778,713, +778,714,779, +715,779,714, +779,715,780, +716,780,715, +780,716,781, +717,781,716, +781,717,782, +718,782,717, +782,718,783, +719,783,718, +783,719,784, +720,784,719, +784,720,785, +721,785,720, +785,721,786, +722,786,721, +786,722,787, +723,787,722, +787,723,788, +724,788,723, +788,724,789, +725,789,724, +789,725,790, +726,790,725, +790,726,791, +727,791,726, +791,727,792, +728,792,727, +792,728,793, +729,793,728, +793,729,794, +730,794,729, +794,730,795, +731,795,730, +795,731,796, +732,796,731, +796,732,797, +733,797,732, +797,733,798, +734,798,733, +798,734,799, +735,799,734, +799,735,800, +736,800,735, +800,736,801, +737,801,736, +801,737,802, +738,802,737, +802,738,803, +739,803,738, +803,739,804, +740,804,739, +804,740,805, +741,805,740, +805,741,806, +742,806,741, +806,742,807, +743,807,742, +807,743,808, +744,808,743, +808,744,809, +745,809,744, +809,745,810, +746,810,745, +810,746,811, +747,811,746, +811,747,812, +748,812,747, +812,748,813, +749,813,748, +813,749,814, +750,814,749, +814,750,815, +751,815,750, +815,751,816, +752,816,751, +816,752,817, +753,817,752, +817,753,818, +754,818,753, +818,754,819, +755,819,754, +819,755,820, +756,820,755, +820,756,821, +757,821,756, +821,757,822, +758,822,757, +822,758,823, +759,823,758, +823,759,824, +760,824,759, +824,760,825, +761,825,760, +825,761,826, +762,826,761, +826,762,827, +763,827,762, +827,763,828, +764,828,763, +828,764,829, +765,829,764, +829,765,830, +766,830,765, +830,766,831, +767,831,766, +832,768,833, +769,833,768, +833,769,834, +770,834,769, +834,770,835, +771,835,770, +835,771,836, +772,836,771, +836,772,837, +773,837,772, +837,773,838, +774,838,773, +838,774,839, +775,839,774, +839,775,840, +776,840,775, +840,776,841, +777,841,776, +841,777,842, +778,842,777, +842,778,843, +779,843,778, +843,779,844, +780,844,779, +844,780,845, +781,845,780, +845,781,846, +782,846,781, +846,782,847, +783,847,782, +847,783,848, +784,848,783, +848,784,849, +785,849,784, +849,785,850, +786,850,785, +850,786,851, +787,851,786, +851,787,852, +788,852,787, +852,788,853, +789,853,788, +853,789,854, +790,854,789, +854,790,855, +791,855,790, +855,791,856, +792,856,791, +856,792,857, +793,857,792, +857,793,858, +794,858,793, +858,794,859, +795,859,794, +859,795,860, +796,860,795, +860,796,861, +797,861,796, +861,797,862, +798,862,797, +862,798,863, +799,863,798, +863,799,864, +800,864,799, +864,800,865, +801,865,800, +865,801,866, +802,866,801, +866,802,867, +803,867,802, +867,803,868, +804,868,803, +868,804,869, +805,869,804, +869,805,870, +806,870,805, +870,806,871, +807,871,806, +871,807,872, +808,872,807, +872,808,873, +809,873,808, +873,809,874, +810,874,809, +874,810,875, +811,875,810, +875,811,876, +812,876,811, +876,812,877, +813,877,812, +877,813,878, +814,878,813, +878,814,879, +815,879,814, +879,815,880, +816,880,815, +880,816,881, +817,881,816, +881,817,882, +818,882,817, +882,818,883, +819,883,818, +883,819,884, +820,884,819, +884,820,885, +821,885,820, +885,821,886, +822,886,821, +886,822,887, +823,887,822, +887,823,888, +824,888,823, +888,824,889, +825,889,824, +889,825,890, +826,890,825, +890,826,891, +827,891,826, +891,827,892, +828,892,827, +892,828,893, +829,893,828, +893,829,894, +830,894,829, +894,830,895, +831,895,830, +896,832,897, +833,897,832, +897,833,898, +834,898,833, +898,834,899, +835,899,834, +899,835,900, +836,900,835, +900,836,901, +837,901,836, +901,837,902, +838,902,837, +902,838,903, +839,903,838, +903,839,904, +840,904,839, +904,840,905, +841,905,840, +905,841,906, +842,906,841, +906,842,907, +843,907,842, +907,843,908, +844,908,843, +908,844,909, +845,909,844, +909,845,910, +846,910,845, +910,846,911, +847,911,846, +911,847,912, +848,912,847, +912,848,913, +849,913,848, +913,849,914, +850,914,849, +914,850,915, +851,915,850, +915,851,916, +852,916,851, +916,852,917, +853,917,852, +917,853,918, +854,918,853, +918,854,919, +855,919,854, +919,855,920, +856,920,855, +920,856,921, +857,921,856, +921,857,922, +858,922,857, +922,858,923, +859,923,858, +923,859,924, +860,924,859, +924,860,925, +861,925,860, +925,861,926, +862,926,861, +926,862,927, +863,927,862, +927,863,928, +864,928,863, +928,864,929, +865,929,864, +929,865,930, +866,930,865, +930,866,931, +867,931,866, +931,867,932, +868,932,867, +932,868,933, +869,933,868, +933,869,934, +870,934,869, +934,870,935, +871,935,870, +935,871,936, +872,936,871, +936,872,937, +873,937,872, +937,873,938, +874,938,873, +938,874,939, +875,939,874, +939,875,940, +876,940,875, +940,876,941, +877,941,876, +941,877,942, +878,942,877, +942,878,943, +879,943,878, +943,879,944, +880,944,879, +944,880,945, +881,945,880, +945,881,946, +882,946,881, +946,882,947, +883,947,882, +947,883,948, +884,948,883, +948,884,949, +885,949,884, +949,885,950, +886,950,885, +950,886,951, +887,951,886, +951,887,952, +888,952,887, +952,888,953, +889,953,888, +953,889,954, +890,954,889, +954,890,955, +891,955,890, +955,891,956, +892,956,891, +956,892,957, +893,957,892, +957,893,958, +894,958,893, +958,894,959, +895,959,894, +960,896,961, +897,961,896, +961,897,962, +898,962,897, +962,898,963, +899,963,898, +963,899,964, +900,964,899, +964,900,965, +901,965,900, +965,901,966, +902,966,901, +966,902,967, +903,967,902, +967,903,968, +904,968,903, +968,904,969, +905,969,904, +969,905,970, +906,970,905, +970,906,971, +907,971,906, +971,907,972, +908,972,907, +972,908,973, +909,973,908, +973,909,974, +910,974,909, +974,910,975, +911,975,910, +975,911,976, +912,976,911, +976,912,977, +913,977,912, +977,913,978, +914,978,913, +978,914,979, +915,979,914, +979,915,980, +916,980,915, +980,916,981, +917,981,916, +981,917,982, +918,982,917, +982,918,983, +919,983,918, +983,919,984, +920,984,919, +984,920,985, +921,985,920, +985,921,986, +922,986,921, +986,922,987, +923,987,922, +987,923,988, +924,988,923, +988,924,989, +925,989,924, +989,925,990, +926,990,925, +990,926,991, +927,991,926, +991,927,992, +928,992,927, +992,928,993, +929,993,928, +993,929,994, +930,994,929, +994,930,995, +931,995,930, +995,931,996, +932,996,931, +996,932,997, +933,997,932, +997,933,998, +934,998,933, +998,934,999, +935,999,934, +999,935,1000, +936,1000,935, +1000,936,1001, +937,1001,936, +1001,937,1002, +938,1002,937, +1002,938,1003, +939,1003,938, +1003,939,1004, +940,1004,939, +1004,940,1005, +941,1005,940, +1005,941,1006, +942,1006,941, +1006,942,1007, +943,1007,942, +1007,943,1008, +944,1008,943, +1008,944,1009, +945,1009,944, +1009,945,1010, +946,1010,945, +1010,946,1011, +947,1011,946, +1011,947,1012, +948,1012,947, +1012,948,1013, +949,1013,948, +1013,949,1014, +950,1014,949, +1014,950,1015, +951,1015,950, +1015,951,1016, +952,1016,951, +1016,952,1017, +953,1017,952, +1017,953,1018, +954,1018,953, +1018,954,1019, +955,1019,954, +1019,955,1020, +956,1020,955, +1020,956,1021, +957,1021,956, +1021,957,1022, +958,1022,957, +1022,958,1023, +959,1023,958, +1024,960,1025, +961,1025,960, +1025,961,1026, +962,1026,961, +1026,962,1027, +963,1027,962, +1027,963,1028, +964,1028,963, +1028,964,1029, +965,1029,964, +1029,965,1030, +966,1030,965, +1030,966,1031, +967,1031,966, +1031,967,1032, +968,1032,967, +1032,968,1033, +969,1033,968, +1033,969,1034, +970,1034,969, +1034,970,1035, +971,1035,970, +1035,971,1036, +972,1036,971, +1036,972,1037, +973,1037,972, +1037,973,1038, +974,1038,973, +1038,974,1039, +975,1039,974, +1039,975,1040, +976,1040,975, +1040,976,1041, +977,1041,976, +1041,977,1042, +978,1042,977, +1042,978,1043, +979,1043,978, +1043,979,1044, +980,1044,979, +1044,980,1045, +981,1045,980, +1045,981,1046, +982,1046,981, +1046,982,1047, +983,1047,982, +1047,983,1048, +984,1048,983, +1048,984,1049, +985,1049,984, +1049,985,1050, +986,1050,985, +1050,986,1051, +987,1051,986, +1051,987,1052, +988,1052,987, +1052,988,1053, +989,1053,988, +1053,989,1054, +990,1054,989, +1054,990,1055, +991,1055,990, +1055,991,1056, +992,1056,991, +1056,992,1057, +993,1057,992, +1057,993,1058, +994,1058,993, +1058,994,1059, +995,1059,994, +1059,995,1060, +996,1060,995, +1060,996,1061, +997,1061,996, +1061,997,1062, +998,1062,997, +1062,998,1063, +999,1063,998, +1063,999,1064, +1000,1064,999, +1064,1000,1065, +1001,1065,1000, +1065,1001,1066, +1002,1066,1001, +1066,1002,1067, +1003,1067,1002, +1067,1003,1068, +1004,1068,1003, +1068,1004,1069, +1005,1069,1004, +1069,1005,1070, +1006,1070,1005, +1070,1006,1071, +1007,1071,1006, +1071,1007,1072, +1008,1072,1007, +1072,1008,1073, +1009,1073,1008, +1073,1009,1074, +1010,1074,1009, +1074,1010,1075, +1011,1075,1010, +1075,1011,1076, +1012,1076,1011, +1076,1012,1077, +1013,1077,1012, +1077,1013,1078, +1014,1078,1013, +1078,1014,1079, +1015,1079,1014, +1079,1015,1080, +1016,1080,1015, +1080,1016,1081, +1017,1081,1016, +1081,1017,1082, +1018,1082,1017, +1082,1018,1083, +1019,1083,1018, +1083,1019,1084, +1020,1084,1019, +1084,1020,1085, +1021,1085,1020, +1085,1021,1086, +1022,1086,1021, +1086,1022,1087, +1023,1087,1022, +1088,1024,1089, +1025,1089,1024, +1089,1025,1090, +1026,1090,1025, +1090,1026,1091, +1027,1091,1026, +1091,1027,1092, +1028,1092,1027, +1092,1028,1093, +1029,1093,1028, +1093,1029,1094, +1030,1094,1029, +1094,1030,1095, +1031,1095,1030, +1095,1031,1096, +1032,1096,1031, +1096,1032,1097, +1033,1097,1032, +1097,1033,1098, +1034,1098,1033, +1098,1034,1099, +1035,1099,1034, +1099,1035,1100, +1036,1100,1035, +1100,1036,1101, +1037,1101,1036, +1101,1037,1102, +1038,1102,1037, +1102,1038,1103, +1039,1103,1038, +1103,1039,1104, +1040,1104,1039, +1104,1040,1105, +1041,1105,1040, +1105,1041,1106, +1042,1106,1041, +1106,1042,1107, +1043,1107,1042, +1107,1043,1108, +1044,1108,1043, +1108,1044,1109, +1045,1109,1044, +1109,1045,1110, +1046,1110,1045, +1110,1046,1111, +1047,1111,1046, +1111,1047,1112, +1048,1112,1047, +1112,1048,1113, +1049,1113,1048, +1113,1049,1114, +1050,1114,1049, +1114,1050,1115, +1051,1115,1050, +1115,1051,1116, +1052,1116,1051, +1116,1052,1117, +1053,1117,1052, +1117,1053,1118, +1054,1118,1053, +1118,1054,1119, +1055,1119,1054, +1119,1055,1120, +1056,1120,1055, +1120,1056,1121, +1057,1121,1056, +1121,1057,1122, +1058,1122,1057, +1122,1058,1123, +1059,1123,1058, +1123,1059,1124, +1060,1124,1059, +1124,1060,1125, +1061,1125,1060, +1125,1061,1126, +1062,1126,1061, +1126,1062,1127, +1063,1127,1062, +1127,1063,1128, +1064,1128,1063, +1128,1064,1129, +1065,1129,1064, +1129,1065,1130, +1066,1130,1065, +1130,1066,1131, +1067,1131,1066, +1131,1067,1132, +1068,1132,1067, +1132,1068,1133, +1069,1133,1068, +1133,1069,1134, +1070,1134,1069, +1134,1070,1135, +1071,1135,1070, +1135,1071,1136, +1072,1136,1071, +1136,1072,1137, +1073,1137,1072, +1137,1073,1138, +1074,1138,1073, +1138,1074,1139, +1075,1139,1074, +1139,1075,1140, +1076,1140,1075, +1140,1076,1141, +1077,1141,1076, +1141,1077,1142, +1078,1142,1077, +1142,1078,1143, +1079,1143,1078, +1143,1079,1144, +1080,1144,1079, +1144,1080,1145, +1081,1145,1080, +1145,1081,1146, +1082,1146,1081, +1146,1082,1147, +1083,1147,1082, +1147,1083,1148, +1084,1148,1083, +1148,1084,1149, +1085,1149,1084, +1149,1085,1150, +1086,1150,1085, +1150,1086,1151, +1087,1151,1086, +1152,1088,1153, +1089,1153,1088, +1153,1089,1154, +1090,1154,1089, +1154,1090,1155, +1091,1155,1090, +1155,1091,1156, +1092,1156,1091, +1156,1092,1157, +1093,1157,1092, +1157,1093,1158, +1094,1158,1093, +1158,1094,1159, +1095,1159,1094, +1159,1095,1160, +1096,1160,1095, +1160,1096,1161, +1097,1161,1096, +1161,1097,1162, +1098,1162,1097, +1162,1098,1163, +1099,1163,1098, +1163,1099,1164, +1100,1164,1099, +1164,1100,1165, +1101,1165,1100, +1165,1101,1166, +1102,1166,1101, +1166,1102,1167, +1103,1167,1102, +1167,1103,1168, +1104,1168,1103, +1168,1104,1169, +1105,1169,1104, +1169,1105,1170, +1106,1170,1105, +1170,1106,1171, +1107,1171,1106, +1171,1107,1172, +1108,1172,1107, +1172,1108,1173, +1109,1173,1108, +1173,1109,1174, +1110,1174,1109, +1174,1110,1175, +1111,1175,1110, +1175,1111,1176, +1112,1176,1111, +1176,1112,1177, +1113,1177,1112, +1177,1113,1178, +1114,1178,1113, +1178,1114,1179, +1115,1179,1114, +1179,1115,1180, +1116,1180,1115, +1180,1116,1181, +1117,1181,1116, +1181,1117,1182, +1118,1182,1117, +1182,1118,1183, +1119,1183,1118, +1183,1119,1184, +1120,1184,1119, +1184,1120,1185, +1121,1185,1120, +1185,1121,1186, +1122,1186,1121, +1186,1122,1187, +1123,1187,1122, +1187,1123,1188, +1124,1188,1123, +1188,1124,1189, +1125,1189,1124, +1189,1125,1190, +1126,1190,1125, +1190,1126,1191, +1127,1191,1126, +1191,1127,1192, +1128,1192,1127, +1192,1128,1193, +1129,1193,1128, +1193,1129,1194, +1130,1194,1129, +1194,1130,1195, +1131,1195,1130, +1195,1131,1196, +1132,1196,1131, +1196,1132,1197, +1133,1197,1132, +1197,1133,1198, +1134,1198,1133, +1198,1134,1199, +1135,1199,1134, +1199,1135,1200, +1136,1200,1135, +1200,1136,1201, +1137,1201,1136, +1201,1137,1202, +1138,1202,1137, +1202,1138,1203, +1139,1203,1138, +1203,1139,1204, +1140,1204,1139, +1204,1140,1205, +1141,1205,1140, +1205,1141,1206, +1142,1206,1141, +1206,1142,1207, +1143,1207,1142, +1207,1143,1208, +1144,1208,1143, +1208,1144,1209, +1145,1209,1144, +1209,1145,1210, +1146,1210,1145, +1210,1146,1211, +1147,1211,1146, +1211,1147,1212, +1148,1212,1147, +1212,1148,1213, +1149,1213,1148, +1213,1149,1214, +1150,1214,1149, +1214,1150,1215, +1151,1215,1150, +1216,1152,1217, +1153,1217,1152, +1217,1153,1218, +1154,1218,1153, +1218,1154,1219, +1155,1219,1154, +1219,1155,1220, +1156,1220,1155, +1220,1156,1221, +1157,1221,1156, +1221,1157,1222, +1158,1222,1157, +1222,1158,1223, +1159,1223,1158, +1223,1159,1224, +1160,1224,1159, +1224,1160,1225, +1161,1225,1160, +1225,1161,1226, +1162,1226,1161, +1226,1162,1227, +1163,1227,1162, +1227,1163,1228, +1164,1228,1163, +1228,1164,1229, +1165,1229,1164, +1229,1165,1230, +1166,1230,1165, +1230,1166,1231, +1167,1231,1166, +1231,1167,1232, +1168,1232,1167, +1232,1168,1233, +1169,1233,1168, +1233,1169,1234, +1170,1234,1169, +1234,1170,1235, +1171,1235,1170, +1235,1171,1236, +1172,1236,1171, +1236,1172,1237, +1173,1237,1172, +1237,1173,1238, +1174,1238,1173, +1238,1174,1239, +1175,1239,1174, +1239,1175,1240, +1176,1240,1175, +1240,1176,1241, +1177,1241,1176, +1241,1177,1242, +1178,1242,1177, +1242,1178,1243, +1179,1243,1178, +1243,1179,1244, +1180,1244,1179, +1244,1180,1245, +1181,1245,1180, +1245,1181,1246, +1182,1246,1181, +1246,1182,1247, +1183,1247,1182, +1247,1183,1248, +1184,1248,1183, +1248,1184,1249, +1185,1249,1184, +1249,1185,1250, +1186,1250,1185, +1250,1186,1251, +1187,1251,1186, +1251,1187,1252, +1188,1252,1187, +1252,1188,1253, +1189,1253,1188, +1253,1189,1254, +1190,1254,1189, +1254,1190,1255, +1191,1255,1190, +1255,1191,1256, +1192,1256,1191, +1256,1192,1257, +1193,1257,1192, +1257,1193,1258, +1194,1258,1193, +1258,1194,1259, +1195,1259,1194, +1259,1195,1260, +1196,1260,1195, +1260,1196,1261, +1197,1261,1196, +1261,1197,1262, +1198,1262,1197, +1262,1198,1263, +1199,1263,1198, +1263,1199,1264, +1200,1264,1199, +1264,1200,1265, +1201,1265,1200, +1265,1201,1266, +1202,1266,1201, +1266,1202,1267, +1203,1267,1202, +1267,1203,1268, +1204,1268,1203, +1268,1204,1269, +1205,1269,1204, +1269,1205,1270, +1206,1270,1205, +1270,1206,1271, +1207,1271,1206, +1271,1207,1272, +1208,1272,1207, +1272,1208,1273, +1209,1273,1208, +1273,1209,1274, +1210,1274,1209, +1274,1210,1275, +1211,1275,1210, +1275,1211,1276, +1212,1276,1211, +1276,1212,1277, +1213,1277,1212, +1277,1213,1278, +1214,1278,1213, +1278,1214,1279, +1215,1279,1214, +1280,1216,1281, +1217,1281,1216, +1281,1217,1282, +1218,1282,1217, +1282,1218,1283, +1219,1283,1218, +1283,1219,1284, +1220,1284,1219, +1284,1220,1285, +1221,1285,1220, +1285,1221,1286, +1222,1286,1221, +1286,1222,1287, +1223,1287,1222, +1287,1223,1288, +1224,1288,1223, +1288,1224,1289, +1225,1289,1224, +1289,1225,1290, +1226,1290,1225, +1290,1226,1291, +1227,1291,1226, +1291,1227,1292, +1228,1292,1227, +1292,1228,1293, +1229,1293,1228, +1293,1229,1294, +1230,1294,1229, +1294,1230,1295, +1231,1295,1230, +1295,1231,1296, +1232,1296,1231, +1296,1232,1297, +1233,1297,1232, +1297,1233,1298, +1234,1298,1233, +1298,1234,1299, +1235,1299,1234, +1299,1235,1300, +1236,1300,1235, +1300,1236,1301, +1237,1301,1236, +1301,1237,1302, +1238,1302,1237, +1302,1238,1303, +1239,1303,1238, +1303,1239,1304, +1240,1304,1239, +1304,1240,1305, +1241,1305,1240, +1305,1241,1306, +1242,1306,1241, +1306,1242,1307, +1243,1307,1242, +1307,1243,1308, +1244,1308,1243, +1308,1244,1309, +1245,1309,1244, +1309,1245,1310, +1246,1310,1245, +1310,1246,1311, +1247,1311,1246, +1311,1247,1312, +1248,1312,1247, +1312,1248,1313, +1249,1313,1248, +1313,1249,1314, +1250,1314,1249, +1314,1250,1315, +1251,1315,1250, +1315,1251,1316, +1252,1316,1251, +1316,1252,1317, +1253,1317,1252, +1317,1253,1318, +1254,1318,1253, +1318,1254,1319, +1255,1319,1254, +1319,1255,1320, +1256,1320,1255, +1320,1256,1321, +1257,1321,1256, +1321,1257,1322, +1258,1322,1257, +1322,1258,1323, +1259,1323,1258, +1323,1259,1324, +1260,1324,1259, +1324,1260,1325, +1261,1325,1260, +1325,1261,1326, +1262,1326,1261, +1326,1262,1327, +1263,1327,1262, +1327,1263,1328, +1264,1328,1263, +1328,1264,1329, +1265,1329,1264, +1329,1265,1330, +1266,1330,1265, +1330,1266,1331, +1267,1331,1266, +1331,1267,1332, +1268,1332,1267, +1332,1268,1333, +1269,1333,1268, +1333,1269,1334, +1270,1334,1269, +1334,1270,1335, +1271,1335,1270, +1335,1271,1336, +1272,1336,1271, +1336,1272,1337, +1273,1337,1272, +1337,1273,1338, +1274,1338,1273, +1338,1274,1339, +1275,1339,1274, +1339,1275,1340, +1276,1340,1275, +1340,1276,1341, +1277,1341,1276, +1341,1277,1342, +1278,1342,1277, +1342,1278,1343, +1279,1343,1278, +1344,1280,1345, +1281,1345,1280, +1345,1281,1346, +1282,1346,1281, +1346,1282,1347, +1283,1347,1282, +1347,1283,1348, +1284,1348,1283, +1348,1284,1349, +1285,1349,1284, +1349,1285,1350, +1286,1350,1285, +1350,1286,1351, +1287,1351,1286, +1351,1287,1352, +1288,1352,1287, +1352,1288,1353, +1289,1353,1288, +1353,1289,1354, +1290,1354,1289, +1354,1290,1355, +1291,1355,1290, +1355,1291,1356, +1292,1356,1291, +1356,1292,1357, +1293,1357,1292, +1357,1293,1358, +1294,1358,1293, +1358,1294,1359, +1295,1359,1294, +1359,1295,1360, +1296,1360,1295, +1360,1296,1361, +1297,1361,1296, +1361,1297,1362, +1298,1362,1297, +1362,1298,1363, +1299,1363,1298, +1363,1299,1364, +1300,1364,1299, +1364,1300,1365, +1301,1365,1300, +1365,1301,1366, +1302,1366,1301, +1366,1302,1367, +1303,1367,1302, +1367,1303,1368, +1304,1368,1303, +1368,1304,1369, +1305,1369,1304, +1369,1305,1370, +1306,1370,1305, +1370,1306,1371, +1307,1371,1306, +1371,1307,1372, +1308,1372,1307, +1372,1308,1373, +1309,1373,1308, +1373,1309,1374, +1310,1374,1309, +1374,1310,1375, +1311,1375,1310, +1375,1311,1376, +1312,1376,1311, +1376,1312,1377, +1313,1377,1312, +1377,1313,1378, +1314,1378,1313, +1378,1314,1379, +1315,1379,1314, +1379,1315,1380, +1316,1380,1315, +1380,1316,1381, +1317,1381,1316, +1381,1317,1382, +1318,1382,1317, +1382,1318,1383, +1319,1383,1318, +1383,1319,1384, +1320,1384,1319, +1384,1320,1385, +1321,1385,1320, +1385,1321,1386, +1322,1386,1321, +1386,1322,1387, +1323,1387,1322, +1387,1323,1388, +1324,1388,1323, +1388,1324,1389, +1325,1389,1324, +1389,1325,1390, +1326,1390,1325, +1390,1326,1391, +1327,1391,1326, +1391,1327,1392, +1328,1392,1327, +1392,1328,1393, +1329,1393,1328, +1393,1329,1394, +1330,1394,1329, +1394,1330,1395, +1331,1395,1330, +1395,1331,1396, +1332,1396,1331, +1396,1332,1397, +1333,1397,1332, +1397,1333,1398, +1334,1398,1333, +1398,1334,1399, +1335,1399,1334, +1399,1335,1400, +1336,1400,1335, +1400,1336,1401, +1337,1401,1336, +1401,1337,1402, +1338,1402,1337, +1402,1338,1403, +1339,1403,1338, +1403,1339,1404, +1340,1404,1339, +1404,1340,1405, +1341,1405,1340, +1405,1341,1406, +1342,1406,1341, +1406,1342,1407, +1343,1407,1342, +1408,1344,1409, +1345,1409,1344, +1409,1345,1410, +1346,1410,1345, +1410,1346,1411, +1347,1411,1346, +1411,1347,1412, +1348,1412,1347, +1412,1348,1413, +1349,1413,1348, +1413,1349,1414, +1350,1414,1349, +1414,1350,1415, +1351,1415,1350, +1415,1351,1416, +1352,1416,1351, +1416,1352,1417, +1353,1417,1352, +1417,1353,1418, +1354,1418,1353, +1418,1354,1419, +1355,1419,1354, +1419,1355,1420, +1356,1420,1355, +1420,1356,1421, +1357,1421,1356, +1421,1357,1422, +1358,1422,1357, +1422,1358,1423, +1359,1423,1358, +1423,1359,1424, +1360,1424,1359, +1424,1360,1425, +1361,1425,1360, +1425,1361,1426, +1362,1426,1361, +1426,1362,1427, +1363,1427,1362, +1427,1363,1428, +1364,1428,1363, +1428,1364,1429, +1365,1429,1364, +1429,1365,1430, +1366,1430,1365, +1430,1366,1431, +1367,1431,1366, +1431,1367,1432, +1368,1432,1367, +1432,1368,1433, +1369,1433,1368, +1433,1369,1434, +1370,1434,1369, +1434,1370,1435, +1371,1435,1370, +1435,1371,1436, +1372,1436,1371, +1436,1372,1437, +1373,1437,1372, +1437,1373,1438, +1374,1438,1373, +1438,1374,1439, +1375,1439,1374, +1439,1375,1440, +1376,1440,1375, +1440,1376,1441, +1377,1441,1376, +1441,1377,1442, +1378,1442,1377, +1442,1378,1443, +1379,1443,1378, +1443,1379,1444, +1380,1444,1379, +1444,1380,1445, +1381,1445,1380, +1445,1381,1446, +1382,1446,1381, +1446,1382,1447, +1383,1447,1382, +1447,1383,1448, +1384,1448,1383, +1448,1384,1449, +1385,1449,1384, +1449,1385,1450, +1386,1450,1385, +1450,1386,1451, +1387,1451,1386, +1451,1387,1452, +1388,1452,1387, +1452,1388,1453, +1389,1453,1388, +1453,1389,1454, +1390,1454,1389, +1454,1390,1455, +1391,1455,1390, +1455,1391,1456, +1392,1456,1391, +1456,1392,1457, +1393,1457,1392, +1457,1393,1458, +1394,1458,1393, +1458,1394,1459, +1395,1459,1394, +1459,1395,1460, +1396,1460,1395, +1460,1396,1461, +1397,1461,1396, +1461,1397,1462, +1398,1462,1397, +1462,1398,1463, +1399,1463,1398, +1463,1399,1464, +1400,1464,1399, +1464,1400,1465, +1401,1465,1400, +1465,1401,1466, +1402,1466,1401, +1466,1402,1467, +1403,1467,1402, +1467,1403,1468, +1404,1468,1403, +1468,1404,1469, +1405,1469,1404, +1469,1405,1470, +1406,1470,1405, +1470,1406,1471, +1407,1471,1406, +1472,1408,1473, +1409,1473,1408, +1473,1409,1474, +1410,1474,1409, +1474,1410,1475, +1411,1475,1410, +1475,1411,1476, +1412,1476,1411, +1476,1412,1477, +1413,1477,1412, +1477,1413,1478, +1414,1478,1413, +1478,1414,1479, +1415,1479,1414, +1479,1415,1480, +1416,1480,1415, +1480,1416,1481, +1417,1481,1416, +1481,1417,1482, +1418,1482,1417, +1482,1418,1483, +1419,1483,1418, +1483,1419,1484, +1420,1484,1419, +1484,1420,1485, +1421,1485,1420, +1485,1421,1486, +1422,1486,1421, +1486,1422,1487, +1423,1487,1422, +1487,1423,1488, +1424,1488,1423, +1488,1424,1489, +1425,1489,1424, +1489,1425,1490, +1426,1490,1425, +1490,1426,1491, +1427,1491,1426, +1491,1427,1492, +1428,1492,1427, +1492,1428,1493, +1429,1493,1428, +1493,1429,1494, +1430,1494,1429, +1494,1430,1495, +1431,1495,1430, +1495,1431,1496, +1432,1496,1431, +1496,1432,1497, +1433,1497,1432, +1497,1433,1498, +1434,1498,1433, +1498,1434,1499, +1435,1499,1434, +1499,1435,1500, +1436,1500,1435, +1500,1436,1501, +1437,1501,1436, +1501,1437,1502, +1438,1502,1437, +1502,1438,1503, +1439,1503,1438, +1503,1439,1504, +1440,1504,1439, +1504,1440,1505, +1441,1505,1440, +1505,1441,1506, +1442,1506,1441, +1506,1442,1507, +1443,1507,1442, +1507,1443,1508, +1444,1508,1443, +1508,1444,1509, +1445,1509,1444, +1509,1445,1510, +1446,1510,1445, +1510,1446,1511, +1447,1511,1446, +1511,1447,1512, +1448,1512,1447, +1512,1448,1513, +1449,1513,1448, +1513,1449,1514, +1450,1514,1449, +1514,1450,1515, +1451,1515,1450, +1515,1451,1516, +1452,1516,1451, +1516,1452,1517, +1453,1517,1452, +1517,1453,1518, +1454,1518,1453, +1518,1454,1519, +1455,1519,1454, +1519,1455,1520, +1456,1520,1455, +1520,1456,1521, +1457,1521,1456, +1521,1457,1522, +1458,1522,1457, +1522,1458,1523, +1459,1523,1458, +1523,1459,1524, +1460,1524,1459, +1524,1460,1525, +1461,1525,1460, +1525,1461,1526, +1462,1526,1461, +1526,1462,1527, +1463,1527,1462, +1527,1463,1528, +1464,1528,1463, +1528,1464,1529, +1465,1529,1464, +1529,1465,1530, +1466,1530,1465, +1530,1466,1531, +1467,1531,1466, +1531,1467,1532, +1468,1532,1467, +1532,1468,1533, +1469,1533,1468, +1533,1469,1534, +1470,1534,1469, +1534,1470,1535, +1471,1535,1470, +1536,1472,1537, +1473,1537,1472, +1537,1473,1538, +1474,1538,1473, +1538,1474,1539, +1475,1539,1474, +1539,1475,1540, +1476,1540,1475, +1540,1476,1541, +1477,1541,1476, +1541,1477,1542, +1478,1542,1477, +1542,1478,1543, +1479,1543,1478, +1543,1479,1544, +1480,1544,1479, +1544,1480,1545, +1481,1545,1480, +1545,1481,1546, +1482,1546,1481, +1546,1482,1547, +1483,1547,1482, +1547,1483,1548, +1484,1548,1483, +1548,1484,1549, +1485,1549,1484, +1549,1485,1550, +1486,1550,1485, +1550,1486,1551, +1487,1551,1486, +1551,1487,1552, +1488,1552,1487, +1552,1488,1553, +1489,1553,1488, +1553,1489,1554, +1490,1554,1489, +1554,1490,1555, +1491,1555,1490, +1555,1491,1556, +1492,1556,1491, +1556,1492,1557, +1493,1557,1492, +1557,1493,1558, +1494,1558,1493, +1558,1494,1559, +1495,1559,1494, +1559,1495,1560, +1496,1560,1495, +1560,1496,1561, +1497,1561,1496, +1561,1497,1562, +1498,1562,1497, +1562,1498,1563, +1499,1563,1498, +1563,1499,1564, +1500,1564,1499, +1564,1500,1565, +1501,1565,1500, +1565,1501,1566, +1502,1566,1501, +1566,1502,1567, +1503,1567,1502, +1567,1503,1568, +1504,1568,1503, +1568,1504,1569, +1505,1569,1504, +1569,1505,1570, +1506,1570,1505, +1570,1506,1571, +1507,1571,1506, +1571,1507,1572, +1508,1572,1507, +1572,1508,1573, +1509,1573,1508, +1573,1509,1574, +1510,1574,1509, +1574,1510,1575, +1511,1575,1510, +1575,1511,1576, +1512,1576,1511, +1576,1512,1577, +1513,1577,1512, +1577,1513,1578, +1514,1578,1513, +1578,1514,1579, +1515,1579,1514, +1579,1515,1580, +1516,1580,1515, +1580,1516,1581, +1517,1581,1516, +1581,1517,1582, +1518,1582,1517, +1582,1518,1583, +1519,1583,1518, +1583,1519,1584, +1520,1584,1519, +1584,1520,1585, +1521,1585,1520, +1585,1521,1586, +1522,1586,1521, +1586,1522,1587, +1523,1587,1522, +1587,1523,1588, +1524,1588,1523, +1588,1524,1589, +1525,1589,1524, +1589,1525,1590, +1526,1590,1525, +1590,1526,1591, +1527,1591,1526, +1591,1527,1592, +1528,1592,1527, +1592,1528,1593, +1529,1593,1528, +1593,1529,1594, +1530,1594,1529, +1594,1530,1595, +1531,1595,1530, +1595,1531,1596, +1532,1596,1531, +1596,1532,1597, +1533,1597,1532, +1597,1533,1598, +1534,1598,1533, +1598,1534,1599, +1535,1599,1534, +1600,1536,1601, +1537,1601,1536, +1601,1537,1602, +1538,1602,1537, +1602,1538,1603, +1539,1603,1538, +1603,1539,1604, +1540,1604,1539, +1604,1540,1605, +1541,1605,1540, +1605,1541,1606, +1542,1606,1541, +1606,1542,1607, +1543,1607,1542, +1607,1543,1608, +1544,1608,1543, +1608,1544,1609, +1545,1609,1544, +1609,1545,1610, +1546,1610,1545, +1610,1546,1611, +1547,1611,1546, +1611,1547,1612, +1548,1612,1547, +1612,1548,1613, +1549,1613,1548, +1613,1549,1614, +1550,1614,1549, +1614,1550,1615, +1551,1615,1550, +1615,1551,1616, +1552,1616,1551, +1616,1552,1617, +1553,1617,1552, +1617,1553,1618, +1554,1618,1553, +1618,1554,1619, +1555,1619,1554, +1619,1555,1620, +1556,1620,1555, +1620,1556,1621, +1557,1621,1556, +1621,1557,1622, +1558,1622,1557, +1622,1558,1623, +1559,1623,1558, +1623,1559,1624, +1560,1624,1559, +1624,1560,1625, +1561,1625,1560, +1625,1561,1626, +1562,1626,1561, +1626,1562,1627, +1563,1627,1562, +1627,1563,1628, +1564,1628,1563, +1628,1564,1629, +1565,1629,1564, +1629,1565,1630, +1566,1630,1565, +1630,1566,1631, +1567,1631,1566, +1631,1567,1632, +1568,1632,1567, +1632,1568,1633, +1569,1633,1568, +1633,1569,1634, +1570,1634,1569, +1634,1570,1635, +1571,1635,1570, +1635,1571,1636, +1572,1636,1571, +1636,1572,1637, +1573,1637,1572, +1637,1573,1638, +1574,1638,1573, +1638,1574,1639, +1575,1639,1574, +1639,1575,1640, +1576,1640,1575, +1640,1576,1641, +1577,1641,1576, +1641,1577,1642, +1578,1642,1577, +1642,1578,1643, +1579,1643,1578, +1643,1579,1644, +1580,1644,1579, +1644,1580,1645, +1581,1645,1580, +1645,1581,1646, +1582,1646,1581, +1646,1582,1647, +1583,1647,1582, +1647,1583,1648, +1584,1648,1583, +1648,1584,1649, +1585,1649,1584, +1649,1585,1650, +1586,1650,1585, +1650,1586,1651, +1587,1651,1586, +1651,1587,1652, +1588,1652,1587, +1652,1588,1653, +1589,1653,1588, +1653,1589,1654, +1590,1654,1589, +1654,1590,1655, +1591,1655,1590, +1655,1591,1656, +1592,1656,1591, +1656,1592,1657, +1593,1657,1592, +1657,1593,1658, +1594,1658,1593, +1658,1594,1659, +1595,1659,1594, +1659,1595,1660, +1596,1660,1595, +1660,1596,1661, +1597,1661,1596, +1661,1597,1662, +1598,1662,1597, +1662,1598,1663, +1599,1663,1598, +1664,1600,1665, +1601,1665,1600, +1665,1601,1666, +1602,1666,1601, +1666,1602,1667, +1603,1667,1602, +1667,1603,1668, +1604,1668,1603, +1668,1604,1669, +1605,1669,1604, +1669,1605,1670, +1606,1670,1605, +1670,1606,1671, +1607,1671,1606, +1671,1607,1672, +1608,1672,1607, +1672,1608,1673, +1609,1673,1608, +1673,1609,1674, +1610,1674,1609, +1674,1610,1675, +1611,1675,1610, +1675,1611,1676, +1612,1676,1611, +1676,1612,1677, +1613,1677,1612, +1677,1613,1678, +1614,1678,1613, +1678,1614,1679, +1615,1679,1614, +1679,1615,1680, +1616,1680,1615, +1680,1616,1681, +1617,1681,1616, +1681,1617,1682, +1618,1682,1617, +1682,1618,1683, +1619,1683,1618, +1683,1619,1684, +1620,1684,1619, +1684,1620,1685, +1621,1685,1620, +1685,1621,1686, +1622,1686,1621, +1686,1622,1687, +1623,1687,1622, +1687,1623,1688, +1624,1688,1623, +1688,1624,1689, +1625,1689,1624, +1689,1625,1690, +1626,1690,1625, +1690,1626,1691, +1627,1691,1626, +1691,1627,1692, +1628,1692,1627, +1692,1628,1693, +1629,1693,1628, +1693,1629,1694, +1630,1694,1629, +1694,1630,1695, +1631,1695,1630, +1695,1631,1696, +1632,1696,1631, +1696,1632,1697, +1633,1697,1632, +1697,1633,1698, +1634,1698,1633, +1698,1634,1699, +1635,1699,1634, +1699,1635,1700, +1636,1700,1635, +1700,1636,1701, +1637,1701,1636, +1701,1637,1702, +1638,1702,1637, +1702,1638,1703, +1639,1703,1638, +1703,1639,1704, +1640,1704,1639, +1704,1640,1705, +1641,1705,1640, +1705,1641,1706, +1642,1706,1641, +1706,1642,1707, +1643,1707,1642, +1707,1643,1708, +1644,1708,1643, +1708,1644,1709, +1645,1709,1644, +1709,1645,1710, +1646,1710,1645, +1710,1646,1711, +1647,1711,1646, +1711,1647,1712, +1648,1712,1647, +1712,1648,1713, +1649,1713,1648, +1713,1649,1714, +1650,1714,1649, +1714,1650,1715, +1651,1715,1650, +1715,1651,1716, +1652,1716,1651, +1716,1652,1717, +1653,1717,1652, +1717,1653,1718, +1654,1718,1653, +1718,1654,1719, +1655,1719,1654, +1719,1655,1720, +1656,1720,1655, +1720,1656,1721, +1657,1721,1656, +1721,1657,1722, +1658,1722,1657, +1722,1658,1723, +1659,1723,1658, +1723,1659,1724, +1660,1724,1659, +1724,1660,1725, +1661,1725,1660, +1725,1661,1726, +1662,1726,1661, +1726,1662,1727, +1663,1727,1662, +1728,1664,1729, +1665,1729,1664, +1729,1665,1730, +1666,1730,1665, +1730,1666,1731, +1667,1731,1666, +1731,1667,1732, +1668,1732,1667, +1732,1668,1733, +1669,1733,1668, +1733,1669,1734, +1670,1734,1669, +1734,1670,1735, +1671,1735,1670, +1735,1671,1736, +1672,1736,1671, +1736,1672,1737, +1673,1737,1672, +1737,1673,1738, +1674,1738,1673, +1738,1674,1739, +1675,1739,1674, +1739,1675,1740, +1676,1740,1675, +1740,1676,1741, +1677,1741,1676, +1741,1677,1742, +1678,1742,1677, +1742,1678,1743, +1679,1743,1678, +1743,1679,1744, +1680,1744,1679, +1744,1680,1745, +1681,1745,1680, +1745,1681,1746, +1682,1746,1681, +1746,1682,1747, +1683,1747,1682, +1747,1683,1748, +1684,1748,1683, +1748,1684,1749, +1685,1749,1684, +1749,1685,1750, +1686,1750,1685, +1750,1686,1751, +1687,1751,1686, +1751,1687,1752, +1688,1752,1687, +1752,1688,1753, +1689,1753,1688, +1753,1689,1754, +1690,1754,1689, +1754,1690,1755, +1691,1755,1690, +1755,1691,1756, +1692,1756,1691, +1756,1692,1757, +1693,1757,1692, +1757,1693,1758, +1694,1758,1693, +1758,1694,1759, +1695,1759,1694, +1759,1695,1760, +1696,1760,1695, +1760,1696,1761, +1697,1761,1696, +1761,1697,1762, +1698,1762,1697, +1762,1698,1763, +1699,1763,1698, +1763,1699,1764, +1700,1764,1699, +1764,1700,1765, +1701,1765,1700, +1765,1701,1766, +1702,1766,1701, +1766,1702,1767, +1703,1767,1702, +1767,1703,1768, +1704,1768,1703, +1768,1704,1769, +1705,1769,1704, +1769,1705,1770, +1706,1770,1705, +1770,1706,1771, +1707,1771,1706, +1771,1707,1772, +1708,1772,1707, +1772,1708,1773, +1709,1773,1708, +1773,1709,1774, +1710,1774,1709, +1774,1710,1775, +1711,1775,1710, +1775,1711,1776, +1712,1776,1711, +1776,1712,1777, +1713,1777,1712, +1777,1713,1778, +1714,1778,1713, +1778,1714,1779, +1715,1779,1714, +1779,1715,1780, +1716,1780,1715, +1780,1716,1781, +1717,1781,1716, +1781,1717,1782, +1718,1782,1717, +1782,1718,1783, +1719,1783,1718, +1783,1719,1784, +1720,1784,1719, +1784,1720,1785, +1721,1785,1720, +1785,1721,1786, +1722,1786,1721, +1786,1722,1787, +1723,1787,1722, +1787,1723,1788, +1724,1788,1723, +1788,1724,1789, +1725,1789,1724, +1789,1725,1790, +1726,1790,1725, +1790,1726,1791, +1727,1791,1726, +1792,1728,1793, +1729,1793,1728, +1793,1729,1794, +1730,1794,1729, +1794,1730,1795, +1731,1795,1730, +1795,1731,1796, +1732,1796,1731, +1796,1732,1797, +1733,1797,1732, +1797,1733,1798, +1734,1798,1733, +1798,1734,1799, +1735,1799,1734, +1799,1735,1800, +1736,1800,1735, +1800,1736,1801, +1737,1801,1736, +1801,1737,1802, +1738,1802,1737, +1802,1738,1803, +1739,1803,1738, +1803,1739,1804, +1740,1804,1739, +1804,1740,1805, +1741,1805,1740, +1805,1741,1806, +1742,1806,1741, +1806,1742,1807, +1743,1807,1742, +1807,1743,1808, +1744,1808,1743, +1808,1744,1809, +1745,1809,1744, +1809,1745,1810, +1746,1810,1745, +1810,1746,1811, +1747,1811,1746, +1811,1747,1812, +1748,1812,1747, +1812,1748,1813, +1749,1813,1748, +1813,1749,1814, +1750,1814,1749, +1814,1750,1815, +1751,1815,1750, +1815,1751,1816, +1752,1816,1751, +1816,1752,1817, +1753,1817,1752, +1817,1753,1818, +1754,1818,1753, +1818,1754,1819, +1755,1819,1754, +1819,1755,1820, +1756,1820,1755, +1820,1756,1821, +1757,1821,1756, +1821,1757,1822, +1758,1822,1757, +1822,1758,1823, +1759,1823,1758, +1823,1759,1824, +1760,1824,1759, +1824,1760,1825, +1761,1825,1760, +1825,1761,1826, +1762,1826,1761, +1826,1762,1827, +1763,1827,1762, +1827,1763,1828, +1764,1828,1763, +1828,1764,1829, +1765,1829,1764, +1829,1765,1830, +1766,1830,1765, +1830,1766,1831, +1767,1831,1766, +1831,1767,1832, +1768,1832,1767, +1832,1768,1833, +1769,1833,1768, +1833,1769,1834, +1770,1834,1769, +1834,1770,1835, +1771,1835,1770, +1835,1771,1836, +1772,1836,1771, +1836,1772,1837, +1773,1837,1772, +1837,1773,1838, +1774,1838,1773, +1838,1774,1839, +1775,1839,1774, +1839,1775,1840, +1776,1840,1775, +1840,1776,1841, +1777,1841,1776, +1841,1777,1842, +1778,1842,1777, +1842,1778,1843, +1779,1843,1778, +1843,1779,1844, +1780,1844,1779, +1844,1780,1845, +1781,1845,1780, +1845,1781,1846, +1782,1846,1781, +1846,1782,1847, +1783,1847,1782, +1847,1783,1848, +1784,1848,1783, +1848,1784,1849, +1785,1849,1784, +1849,1785,1850, +1786,1850,1785, +1850,1786,1851, +1787,1851,1786, +1851,1787,1852, +1788,1852,1787, +1852,1788,1853, +1789,1853,1788, +1853,1789,1854, +1790,1854,1789, +1854,1790,1855, +1791,1855,1790, +1856,1792,1857, +1793,1857,1792, +1857,1793,1858, +1794,1858,1793, +1858,1794,1859, +1795,1859,1794, +1859,1795,1860, +1796,1860,1795, +1860,1796,1861, +1797,1861,1796, +1861,1797,1862, +1798,1862,1797, +1862,1798,1863, +1799,1863,1798, +1863,1799,1864, +1800,1864,1799, +1864,1800,1865, +1801,1865,1800, +1865,1801,1866, +1802,1866,1801, +1866,1802,1867, +1803,1867,1802, +1867,1803,1868, +1804,1868,1803, +1868,1804,1869, +1805,1869,1804, +1869,1805,1870, +1806,1870,1805, +1870,1806,1871, +1807,1871,1806, +1871,1807,1872, +1808,1872,1807, +1872,1808,1873, +1809,1873,1808, +1873,1809,1874, +1810,1874,1809, +1874,1810,1875, +1811,1875,1810, +1875,1811,1876, +1812,1876,1811, +1876,1812,1877, +1813,1877,1812, +1877,1813,1878, +1814,1878,1813, +1878,1814,1879, +1815,1879,1814, +1879,1815,1880, +1816,1880,1815, +1880,1816,1881, +1817,1881,1816, +1881,1817,1882, +1818,1882,1817, +1882,1818,1883, +1819,1883,1818, +1883,1819,1884, +1820,1884,1819, +1884,1820,1885, +1821,1885,1820, +1885,1821,1886, +1822,1886,1821, +1886,1822,1887, +1823,1887,1822, +1887,1823,1888, +1824,1888,1823, +1888,1824,1889, +1825,1889,1824, +1889,1825,1890, +1826,1890,1825, +1890,1826,1891, +1827,1891,1826, +1891,1827,1892, +1828,1892,1827, +1892,1828,1893, +1829,1893,1828, +1893,1829,1894, +1830,1894,1829, +1894,1830,1895, +1831,1895,1830, +1895,1831,1896, +1832,1896,1831, +1896,1832,1897, +1833,1897,1832, +1897,1833,1898, +1834,1898,1833, +1898,1834,1899, +1835,1899,1834, +1899,1835,1900, +1836,1900,1835, +1900,1836,1901, +1837,1901,1836, +1901,1837,1902, +1838,1902,1837, +1902,1838,1903, +1839,1903,1838, +1903,1839,1904, +1840,1904,1839, +1904,1840,1905, +1841,1905,1840, +1905,1841,1906, +1842,1906,1841, +1906,1842,1907, +1843,1907,1842, +1907,1843,1908, +1844,1908,1843, +1908,1844,1909, +1845,1909,1844, +1909,1845,1910, +1846,1910,1845, +1910,1846,1911, +1847,1911,1846, +1911,1847,1912, +1848,1912,1847, +1912,1848,1913, +1849,1913,1848, +1913,1849,1914, +1850,1914,1849, +1914,1850,1915, +1851,1915,1850, +1915,1851,1916, +1852,1916,1851, +1916,1852,1917, +1853,1917,1852, +1917,1853,1918, +1854,1918,1853, +1918,1854,1919, +1855,1919,1854, +1920,1856,1921, +1857,1921,1856, +1921,1857,1922, +1858,1922,1857, +1922,1858,1923, +1859,1923,1858, +1923,1859,1924, +1860,1924,1859, +1924,1860,1925, +1861,1925,1860, +1925,1861,1926, +1862,1926,1861, +1926,1862,1927, +1863,1927,1862, +1927,1863,1928, +1864,1928,1863, +1928,1864,1929, +1865,1929,1864, +1929,1865,1930, +1866,1930,1865, +1930,1866,1931, +1867,1931,1866, +1931,1867,1932, +1868,1932,1867, +1932,1868,1933, +1869,1933,1868, +1933,1869,1934, +1870,1934,1869, +1934,1870,1935, +1871,1935,1870, +1935,1871,1936, +1872,1936,1871, +1936,1872,1937, +1873,1937,1872, +1937,1873,1938, +1874,1938,1873, +1938,1874,1939, +1875,1939,1874, +1939,1875,1940, +1876,1940,1875, +1940,1876,1941, +1877,1941,1876, +1941,1877,1942, +1878,1942,1877, +1942,1878,1943, +1879,1943,1878, +1943,1879,1944, +1880,1944,1879, +1944,1880,1945, +1881,1945,1880, +1945,1881,1946, +1882,1946,1881, +1946,1882,1947, +1883,1947,1882, +1947,1883,1948, +1884,1948,1883, +1948,1884,1949, +1885,1949,1884, +1949,1885,1950, +1886,1950,1885, +1950,1886,1951, +1887,1951,1886, +1951,1887,1952, +1888,1952,1887, +1952,1888,1953, +1889,1953,1888, +1953,1889,1954, +1890,1954,1889, +1954,1890,1955, +1891,1955,1890, +1955,1891,1956, +1892,1956,1891, +1956,1892,1957, +1893,1957,1892, +1957,1893,1958, +1894,1958,1893, +1958,1894,1959, +1895,1959,1894, +1959,1895,1960, +1896,1960,1895, +1960,1896,1961, +1897,1961,1896, +1961,1897,1962, +1898,1962,1897, +1962,1898,1963, +1899,1963,1898, +1963,1899,1964, +1900,1964,1899, +1964,1900,1965, +1901,1965,1900, +1965,1901,1966, +1902,1966,1901, +1966,1902,1967, +1903,1967,1902, +1967,1903,1968, +1904,1968,1903, +1968,1904,1969, +1905,1969,1904, +1969,1905,1970, +1906,1970,1905, +1970,1906,1971, +1907,1971,1906, +1971,1907,1972, +1908,1972,1907, +1972,1908,1973, +1909,1973,1908, +1973,1909,1974, +1910,1974,1909, +1974,1910,1975, +1911,1975,1910, +1975,1911,1976, +1912,1976,1911, +1976,1912,1977, +1913,1977,1912, +1977,1913,1978, +1914,1978,1913, +1978,1914,1979, +1915,1979,1914, +1979,1915,1980, +1916,1980,1915, +1980,1916,1981, +1917,1981,1916, +1981,1917,1982, +1918,1982,1917, +1982,1918,1983, +1919,1983,1918, +1984,1920,1985, +1921,1985,1920, +1985,1921,1986, +1922,1986,1921, +1986,1922,1987, +1923,1987,1922, +1987,1923,1988, +1924,1988,1923, +1988,1924,1989, +1925,1989,1924, +1989,1925,1990, +1926,1990,1925, +1990,1926,1991, +1927,1991,1926, +1991,1927,1992, +1928,1992,1927, +1992,1928,1993, +1929,1993,1928, +1993,1929,1994, +1930,1994,1929, +1994,1930,1995, +1931,1995,1930, +1995,1931,1996, +1932,1996,1931, +1996,1932,1997, +1933,1997,1932, +1997,1933,1998, +1934,1998,1933, +1998,1934,1999, +1935,1999,1934, +1999,1935,2000, +1936,2000,1935, +2000,1936,2001, +1937,2001,1936, +2001,1937,2002, +1938,2002,1937, +2002,1938,2003, +1939,2003,1938, +2003,1939,2004, +1940,2004,1939, +2004,1940,2005, +1941,2005,1940, +2005,1941,2006, +1942,2006,1941, +2006,1942,2007, +1943,2007,1942, +2007,1943,2008, +1944,2008,1943, +2008,1944,2009, +1945,2009,1944, +2009,1945,2010, +1946,2010,1945, +2010,1946,2011, +1947,2011,1946, +2011,1947,2012, +1948,2012,1947, +2012,1948,2013, +1949,2013,1948, +2013,1949,2014, +1950,2014,1949, +2014,1950,2015, +1951,2015,1950, +2015,1951,2016, +1952,2016,1951, +2016,1952,2017, +1953,2017,1952, +2017,1953,2018, +1954,2018,1953, +2018,1954,2019, +1955,2019,1954, +2019,1955,2020, +1956,2020,1955, +2020,1956,2021, +1957,2021,1956, +2021,1957,2022, +1958,2022,1957, +2022,1958,2023, +1959,2023,1958, +2023,1959,2024, +1960,2024,1959, +2024,1960,2025, +1961,2025,1960, +2025,1961,2026, +1962,2026,1961, +2026,1962,2027, +1963,2027,1962, +2027,1963,2028, +1964,2028,1963, +2028,1964,2029, +1965,2029,1964, +2029,1965,2030, +1966,2030,1965, +2030,1966,2031, +1967,2031,1966, +2031,1967,2032, +1968,2032,1967, +2032,1968,2033, +1969,2033,1968, +2033,1969,2034, +1970,2034,1969, +2034,1970,2035, +1971,2035,1970, +2035,1971,2036, +1972,2036,1971, +2036,1972,2037, +1973,2037,1972, +2037,1973,2038, +1974,2038,1973, +2038,1974,2039, +1975,2039,1974, +2039,1975,2040, +1976,2040,1975, +2040,1976,2041, +1977,2041,1976, +2041,1977,2042, +1978,2042,1977, +2042,1978,2043, +1979,2043,1978, +2043,1979,2044, +1980,2044,1979, +2044,1980,2045, +1981,2045,1980, +2045,1981,2046, +1982,2046,1981, +2046,1982,2047, +1983,2047,1982, +2048,1984,2049, +1985,2049,1984, +2049,1985,2050, +1986,2050,1985, +2050,1986,2051, +1987,2051,1986, +2051,1987,2052, +1988,2052,1987, +2052,1988,2053, +1989,2053,1988, +2053,1989,2054, +1990,2054,1989, +2054,1990,2055, +1991,2055,1990, +2055,1991,2056, +1992,2056,1991, +2056,1992,2057, +1993,2057,1992, +2057,1993,2058, +1994,2058,1993, +2058,1994,2059, +1995,2059,1994, +2059,1995,2060, +1996,2060,1995, +2060,1996,2061, +1997,2061,1996, +2061,1997,2062, +1998,2062,1997, +2062,1998,2063, +1999,2063,1998, +2063,1999,2064, +2000,2064,1999, +2064,2000,2065, +2001,2065,2000, +2065,2001,2066, +2002,2066,2001, +2066,2002,2067, +2003,2067,2002, +2067,2003,2068, +2004,2068,2003, +2068,2004,2069, +2005,2069,2004, +2069,2005,2070, +2006,2070,2005, +2070,2006,2071, +2007,2071,2006, +2071,2007,2072, +2008,2072,2007, +2072,2008,2073, +2009,2073,2008, +2073,2009,2074, +2010,2074,2009, +2074,2010,2075, +2011,2075,2010, +2075,2011,2076, +2012,2076,2011, +2076,2012,2077, +2013,2077,2012, +2077,2013,2078, +2014,2078,2013, +2078,2014,2079, +2015,2079,2014, +2079,2015,2080, +2016,2080,2015, +2080,2016,2081, +2017,2081,2016, +2081,2017,2082, +2018,2082,2017, +2082,2018,2083, +2019,2083,2018, +2083,2019,2084, +2020,2084,2019, +2084,2020,2085, +2021,2085,2020, +2085,2021,2086, +2022,2086,2021, +2086,2022,2087, +2023,2087,2022, +2087,2023,2088, +2024,2088,2023, +2088,2024,2089, +2025,2089,2024, +2089,2025,2090, +2026,2090,2025, +2090,2026,2091, +2027,2091,2026, +2091,2027,2092, +2028,2092,2027, +2092,2028,2093, +2029,2093,2028, +2093,2029,2094, +2030,2094,2029, +2094,2030,2095, +2031,2095,2030, +2095,2031,2096, +2032,2096,2031, +2096,2032,2097, +2033,2097,2032, +2097,2033,2098, +2034,2098,2033, +2098,2034,2099, +2035,2099,2034, +2099,2035,2100, +2036,2100,2035, +2100,2036,2101, +2037,2101,2036, +2101,2037,2102, +2038,2102,2037, +2102,2038,2103, +2039,2103,2038, +2103,2039,2104, +2040,2104,2039, +2104,2040,2105, +2041,2105,2040, +2105,2041,2106, +2042,2106,2041, +2106,2042,2107, +2043,2107,2042, +2107,2043,2108, +2044,2108,2043, +2108,2044,2109, +2045,2109,2044, +2109,2045,2110, +2046,2110,2045, +2110,2046,2111, +2047,2111,2046, +}; + +#define Landscape05VtxCount 2244 +#define Landscape05IdxCount 12870 + +btScalar Landscape05Vtx[] = { +-250.0f,-0.990273f,0.0f, +-250.0f,0.139875f,3.90625f, +-246.094f,0.671004f,0.0f, +-246.094f,1.72995f,3.90625f, +-242.188f,1.84097f,0.0f, +-242.188f,2.60122f,3.90625f, +-238.281f,3.67319f,-1.6056e-007f, +-238.281f,4.01346f,3.90625f, +-234.375f,4.96849f,-2.1718e-007f, +-234.375f,5.13654f,3.90625f, +-230.469f,6.56215f,-2.86841e-007f, +-230.469f,6.69665f,3.90625f, +-226.563f,8.30102f,-3.62849e-007f, +-226.563f,8.43203f,3.90625f, +-222.656f,9.94385f,-4.3466e-007f, +-222.656f,9.83442f,3.90625f, +-218.75f,11.5986f,-5.06992e-007f, +-218.75f,11.3645f,3.90625f, +-214.844f,14.3141f,-6.2569e-007f, +-214.844f,14.222f,3.90625f, +-210.938f,16.5538f,-7.2359e-007f, +-210.938f,16.1758f,3.90625f, +-207.031f,18.852f,-8.24046e-007f, +-207.031f,18.9127f,3.90625f, +-203.125f,21.5344f,-9.41301e-007f, +-203.125f,21.2478f,3.90625f, +-199.219f,22.7337f,-9.93723e-007f, +-199.219f,23.0589f,3.90625f, +-195.313f,24.4712f,-1.06967e-006f, +-195.313f,24.6025f,3.90625f, +-191.406f,26.1169f,-1.14161e-006f, +-191.406f,25.8143f,3.90625f, +-187.5f,26.9988f,-1.18015e-006f, +-187.5f,27.5696f,3.90625f, +-183.594f,28.3854f,-1.24077e-006f, +-183.594f,29.2176f,3.90625f, +-179.688f,29.0457f,-1.26963e-006f, +-179.688f,29.6835f,3.90625f, +-175.781f,29.802f,-1.30269e-006f, +-175.781f,30.7416f,3.90625f, +-171.875f,30.1559f,-1.31816e-006f, +-171.875f,31.4405f,3.90625f, +-167.969f,32.3708f,-1.41497e-006f, +-167.969f,33.0831f,3.90625f, +-164.063f,34.9705f,-1.52861e-006f, +-164.063f,34.6225f,3.90625f, +-160.156f,36.396f,-1.59092e-006f, +-160.156f,35.4992f,3.90625f, +-156.25f,37.2947f,-1.6302e-006f, +-156.25f,37.4126f,3.90625f, +-152.344f,38.248f,-1.67187e-006f, +-152.344f,38.453f,3.90625f, +-148.438f,38.3176f,-1.67491e-006f, +-148.438f,38.9974f,3.90625f, +-144.531f,38.1589f,-1.66798e-006f, +-144.531f,38.7871f,3.90625f, +-140.625f,36.5895f,-1.59938e-006f, +-140.625f,37.6021f,3.90625f, +-136.719f,35.718f,-1.56128e-006f, +-136.719f,36.1797f,3.90625f, +-132.813f,33.7519f,-1.47534e-006f, +-132.813f,34.9906f,3.90625f, +-128.906f,33.2853f,-1.45495e-006f, +-128.906f,34.1304f,3.90625f, +-125.0f,33.4003f,-1.45997e-006f, +-125.0f,34.3517f,3.90625f, +-121.094f,33.1132f,-1.44742e-006f, +-121.094f,33.6612f,3.90625f, +-117.188f,32.7861f,-1.43313e-006f, +-117.188f,32.7047f,3.90625f, +-113.281f,33.0037f,-1.44264e-006f, +-113.281f,32.3958f,3.90625f, +-109.375f,32.508f,-1.42097e-006f, +-109.375f,31.0818f,3.90625f, +-105.469f,31.8384f,-1.3917e-006f, +-105.469f,30.9536f,3.90625f, +-101.563f,31.1858f,-1.36317e-006f, +-101.563f,29.8205f,3.90625f, +-97.6563f,29.6739f,-1.29709e-006f, +-97.6563f,28.4796f,3.90625f, +-93.75f,27.8258f,-1.2163e-006f, +-93.75f,27.6494f,3.90625f, +-89.8438f,25.9046f,-1.13232e-006f, +-89.8438f,25.5721f,3.90625f, +-85.9375f,23.4229f,-1.02385e-006f, +-85.9375f,24.227f,3.90625f, +-82.0313f,23.3671f,-1.02141e-006f, +-82.0313f,23.2611f,3.90625f, +-78.125f,23.0585f,-1.00792e-006f, +-78.125f,22.4589f,3.90625f, +-74.2188f,23.9226f,-1.04569e-006f, +-74.2188f,23.2261f,3.90625f, +-70.3125f,23.6449f,-1.03355e-006f, +-70.3125f,23.5025f,3.90625f, +-66.4063f,23.2789f,-1.01755e-006f, +-66.4063f,23.6913f,3.90625f, +-62.5f,24.5841f,-1.07461e-006f, +-62.5f,24.6785f,3.90625f, +-58.5938f,25.71f,-1.12382e-006f, +-58.5938f,25.4946f,3.90625f, +-54.6875f,26.9872f,-1.17965e-006f, +-54.6875f,25.9722f,3.90625f, +-50.7813f,27.8632f,-1.21794e-006f, +-50.7813f,26.1977f,3.90625f, +-46.875f,28.0326f,-1.22534e-006f, +-46.875f,26.8539f,3.90625f, +-42.9688f,28.0866f,-1.2277e-006f, +-42.9688f,27.7268f,3.90625f, +-39.0625f,30.1482f,-1.31782e-006f, +-39.0625f,29.2046f,3.90625f, +-35.1563f,32.4049f,-1.41646e-006f, +-35.1563f,31.79f,3.90625f, +-31.25f,34.4714f,-1.50679e-006f, +-31.25f,34.2658f,3.90625f, +-27.3438f,37.2668f,-1.62898e-006f, +-27.3438f,35.9914f,3.90625f, +-23.4375f,38.7934f,-1.69571e-006f, +-23.4375f,38.3776f,3.90625f, +-19.5313f,40.4024f,-1.76605e-006f, +-19.5313f,39.8852f,3.90625f, +-15.625f,42.8177f,-1.87162e-006f, +-15.625f,43.1455f,3.90625f, +-11.7188f,45.0198f,-1.96788e-006f, +-11.7188f,45.5059f,3.90625f, +-7.8125f,46.7349f,-2.04285e-006f, +-7.8125f,47.4257f,3.90625f, +-3.90625f,48.376f,-2.11458e-006f, +-3.90625f,49.9032f,3.90625f, +0.0f,49.9016f,-2.18127e-006f, +0.0f,52.0322f,3.90625f, +3.90625f,50.3865f,-2.20246e-006f, +3.90625f,52.6186f,3.90625f, +-250.0f,-0.818988f,-3.90625f, +-246.094f,0.671433f,-3.90625f, +-242.188f,2.83415f,-3.90625f, +-238.281f,4.19978f,-3.90625f, +-234.375f,5.59158f,-3.90625f, +-230.469f,6.94041f,-3.90625f, +-226.563f,8.34599f,-3.90625f, +-222.656f,9.85416f,-3.90625f, +-218.75f,10.8989f,-3.90625f, +-214.844f,13.6339f,-3.90625f, +-210.938f,16.5116f,-3.90625f, +-207.031f,17.7111f,-3.90625f, +-203.125f,20.7442f,-3.90625f, +-199.219f,22.5356f,-3.90625f, +-195.313f,24.3988f,-3.90625f, +-191.406f,25.8062f,-3.90625f, +-187.5f,26.9714f,-3.90625f, +-183.594f,27.7397f,-3.90625f, +-179.688f,28.8632f,-3.90625f, +-175.781f,29.9688f,-3.90625f, +-171.875f,32.154f,-3.90625f, +-167.969f,33.3799f,-3.90625f, +-164.063f,35.3882f,-3.90625f, +-160.156f,35.9765f,-3.90625f, +-156.25f,36.5306f,-3.90625f, +-152.344f,37.3214f,-3.90625f, +-148.438f,36.8126f,-3.90625f, +-144.531f,36.5407f,-3.90625f, +-140.625f,35.696f,-3.90625f, +-136.719f,35.1152f,-3.90625f, +-132.813f,34.1963f,-3.90625f, +-128.906f,34.0796f,-3.90625f, +-125.0f,34.2398f,-3.90625f, +-121.094f,34.1503f,-3.90625f, +-117.188f,33.7958f,-3.90625f, +-113.281f,33.856f,-3.90625f, +-109.375f,33.2705f,-3.90625f, +-105.469f,32.5804f,-3.90625f, +-101.563f,31.911f,-3.90625f, +-97.6563f,30.3705f,-3.90625f, +-93.75f,29.0627f,-3.90625f, +-89.8438f,26.6822f,-3.90625f, +-85.9375f,24.8309f,-3.90625f, +-82.0313f,23.8581f,-3.90625f, +-78.125f,23.3764f,-3.90625f, +-74.2188f,23.9582f,-3.90625f, +-70.3125f,24.13f,-3.90625f, +-66.4063f,24.4426f,-3.90625f, +-62.5f,25.5839f,-3.90625f, +-58.5938f,26.6899f,-3.90625f, +-54.6875f,27.9086f,-3.90625f, +-50.7813f,28.5131f,-3.90625f, +-46.875f,29.2612f,-3.90625f, +-42.9688f,29.4581f,-3.90625f, +-39.0625f,30.8972f,-3.90625f, +-35.1563f,32.9085f,-3.90625f, +-31.25f,34.9204f,-3.90625f, +-27.3438f,37.7223f,-3.90625f, +-23.4375f,38.921f,-3.90625f, +-19.5313f,40.2983f,-3.90625f, +-15.625f,41.7689f,-3.90625f, +-11.7188f,43.8388f,-3.90625f, +-7.8125f,44.7599f,-3.90625f, +-3.90625f,46.53f,-3.90625f, +0.0f,48.2498f,-3.90625f, +3.90625f,48.8559f,-3.90625f, +-250.0f,0.432867f,-7.8125f, +-246.094f,1.93096f,-7.8125f, +-242.188f,3.28774f,-7.8125f, +-238.281f,4.53112f,-7.8125f, +-234.375f,5.67699f,-7.8125f, +-230.469f,7.34068f,-7.8125f, +-226.563f,8.48553f,-7.8125f, +-222.656f,10.127f,-7.8125f, +-218.75f,11.3267f,-7.8125f, +-214.844f,13.3914f,-7.8125f, +-210.938f,15.5197f,-7.8125f, +-207.031f,17.9403f,-7.8125f, +-203.125f,20.5644f,-7.8125f, +-199.219f,22.8796f,-7.8125f, +-195.313f,23.715f,-7.8125f, +-191.406f,26.1312f,-7.8125f, +-187.5f,28.0754f,-7.8125f, +-183.594f,29.1199f,-7.8125f, +-179.688f,29.5774f,-7.8125f, +-175.781f,30.2676f,-7.8125f, +-171.875f,31.8275f,-7.8125f, +-167.969f,33.4969f,-7.8125f, +-164.063f,34.4445f,-7.8125f, +-160.156f,35.3881f,-7.8125f, +-156.25f,36.0267f,-7.8125f, +-152.344f,36.1221f,-7.8125f, +-148.438f,36.7707f,-7.8125f, +-144.531f,36.3067f,-7.8125f, +-140.625f,36.2295f,-7.8125f, +-136.719f,35.6858f,-7.8125f, +-132.813f,34.6232f,-7.8125f, +-128.906f,34.1675f,-7.8125f, +-125.0f,34.1756f,-7.8125f, +-121.094f,33.6453f,-7.8125f, +-117.188f,34.2516f,-7.8125f, +-113.281f,34.228f,-7.8125f, +-109.375f,34.253f,-7.8125f, +-105.469f,33.1798f,-7.8125f, +-101.563f,32.238f,-7.8125f, +-97.6563f,31.0377f,-7.8125f, +-93.75f,29.6795f,-7.8125f, +-89.8438f,27.5934f,-7.8125f, +-85.9375f,25.7426f,-7.8125f, +-82.0313f,24.4001f,-7.8125f, +-78.125f,24.4095f,-7.8125f, +-74.2188f,25.1494f,-7.8125f, +-70.3125f,25.0193f,-7.8125f, +-66.4063f,25.3902f,-7.8125f, +-62.5f,25.8612f,-7.8125f, +-58.5938f,26.8169f,-7.8125f, +-54.6875f,28.0698f,-7.8125f, +-50.7813f,28.978f,-7.8125f, +-46.875f,29.1063f,-7.8125f, +-42.9688f,30.6071f,-7.8125f, +-39.0625f,31.7015f,-7.8125f, +-35.1563f,32.6112f,-7.8125f, +-31.25f,34.6006f,-7.8125f, +-27.3438f,36.3005f,-7.8125f, +-23.4375f,38.4757f,-7.8125f, +-19.5313f,39.7014f,-7.8125f, +-15.625f,40.7762f,-7.8125f, +-11.7188f,42.6458f,-7.8125f, +-7.8125f,45.0307f,-7.8125f, +-3.90625f,47.2861f,-7.8125f, +0.0f,48.5591f,-7.8125f, +3.90625f,48.7225f,-7.8125f, +-250.0f,0.568294f,-11.7188f, +-246.094f,1.83097f,-11.7188f, +-242.188f,3.32037f,-11.7188f, +-238.281f,4.29184f,-11.7188f, +-234.375f,6.04113f,-11.7188f, +-230.469f,7.01872f,-11.7188f, +-226.563f,8.96731f,-11.7188f, +-222.656f,10.3749f,-11.7188f, +-218.75f,11.568f,-11.7188f, +-214.844f,13.9092f,-11.7188f, +-210.938f,15.6547f,-11.7188f, +-207.031f,18.2156f,-11.7188f, +-203.125f,20.0116f,-11.7188f, +-199.219f,21.5443f,-11.7188f, +-195.313f,23.4553f,-11.7188f, +-191.406f,26.2778f,-11.7188f, +-187.5f,28.0543f,-11.7188f, +-183.594f,29.2657f,-11.7188f, +-179.688f,29.6454f,-11.7188f, +-175.781f,30.699f,-11.7188f, +-171.875f,30.8229f,-11.7188f, +-167.969f,32.9874f,-11.7188f, +-164.063f,33.581f,-11.7188f, +-160.156f,34.6365f,-11.7188f, +-156.25f,35.6153f,-11.7188f, +-152.344f,36.2491f,-11.7188f, +-148.438f,36.2996f,-11.7188f, +-144.531f,36.5456f,-11.7188f, +-140.625f,36.3803f,-11.7188f, +-136.719f,35.2403f,-11.7188f, +-132.813f,34.0595f,-11.7188f, +-128.906f,34.1384f,-11.7188f, +-125.0f,33.59f,-11.7188f, +-121.094f,33.7745f,-11.7188f, +-117.188f,33.7284f,-11.7188f, +-113.281f,33.7013f,-11.7188f, +-109.375f,33.6335f,-11.7188f, +-105.469f,33.2451f,-11.7188f, +-101.563f,32.8691f,-11.7188f, +-97.6563f,31.1343f,-11.7188f, +-93.75f,29.5843f,-11.7188f, +-89.8438f,27.5891f,-11.7188f, +-85.9375f,25.75f,-11.7188f, +-82.0313f,25.4336f,-11.7188f, +-78.125f,25.6207f,-11.7188f, +-74.2188f,25.1627f,-11.7188f, +-70.3125f,25.542f,-11.7188f, +-66.4063f,25.5384f,-11.7188f, +-62.5f,25.9238f,-11.7188f, +-58.5938f,26.0718f,-11.7188f, +-54.6875f,27.4395f,-11.7188f, +-50.7813f,28.8032f,-11.7188f, +-46.875f,29.9667f,-11.7188f, +-42.9688f,31.7598f,-11.7188f, +-39.0625f,32.2636f,-11.7188f, +-35.1563f,32.5734f,-11.7188f, +-31.25f,33.543f,-11.7188f, +-27.3438f,35.1143f,-11.7188f, +-23.4375f,37.3147f,-11.7188f, +-19.5313f,39.2413f,-11.7188f, +-15.625f,41.8344f,-11.7188f, +-11.7188f,43.9992f,-11.7188f, +-7.8125f,46.8581f,-11.7188f, +-3.90625f,48.5977f,-11.7188f, +0.0f,48.7029f,-11.7188f, +3.90625f,49.6298f,-11.7188f, +-250.0f,1.50235f,-15.625f, +-246.094f,1.79115f,-15.625f, +-242.188f,2.52523f,-15.625f, +-238.281f,4.09278f,-15.625f, +-234.375f,6.21068f,-15.625f, +-230.469f,7.49819f,-15.625f, +-226.563f,8.56548f,-15.625f, +-222.656f,9.98954f,-15.625f, +-218.75f,12.3263f,-15.625f, +-214.844f,14.495f,-15.625f, +-210.938f,15.3551f,-15.625f, +-207.031f,17.6989f,-15.625f, +-203.125f,19.2847f,-15.625f, +-199.219f,21.1027f,-15.625f, +-195.313f,23.3408f,-15.625f, +-191.406f,25.3739f,-15.625f, +-187.5f,27.368f,-15.625f, +-183.594f,28.3731f,-15.625f, +-179.688f,29.5532f,-15.625f, +-175.781f,30.0011f,-15.625f, +-171.875f,31.0216f,-15.625f, +-167.969f,32.5546f,-15.625f, +-164.063f,32.6717f,-15.625f, +-160.156f,33.8465f,-15.625f, +-156.25f,35.1272f,-15.625f, +-152.344f,35.5572f,-15.625f, +-148.438f,36.643f,-15.625f, +-144.531f,36.4283f,-15.625f, +-140.625f,35.6122f,-15.625f, +-136.719f,35.358f,-15.625f, +-132.813f,34.1938f,-15.625f, +-128.906f,34.3913f,-15.625f, +-125.0f,33.2147f,-15.625f, +-121.094f,32.799f,-15.625f, +-117.188f,33.1385f,-15.625f, +-113.281f,33.1487f,-15.625f, +-109.375f,33.6564f,-15.625f, +-105.469f,33.2315f,-15.625f, +-101.563f,32.6066f,-15.625f, +-97.6563f,30.6926f,-15.625f, +-93.75f,28.534f,-15.625f, +-89.8438f,27.6738f,-15.625f, +-85.9375f,27.4216f,-15.625f, +-82.0313f,26.0324f,-15.625f, +-78.125f,25.775f,-15.625f, +-74.2188f,25.909f,-15.625f, +-70.3125f,25.0198f,-15.625f, +-66.4063f,25.9376f,-15.625f, +-62.5f,26.0382f,-15.625f, +-58.5938f,25.856f,-15.625f, +-54.6875f,27.3648f,-15.625f, +-50.7813f,28.9059f,-15.625f, +-46.875f,30.6601f,-15.625f, +-42.9688f,32.6996f,-15.625f, +-39.0625f,32.6909f,-15.625f, +-35.1563f,33.1697f,-15.625f, +-31.25f,34.6947f,-15.625f, +-27.3438f,35.6982f,-15.625f, +-23.4375f,38.2946f,-15.625f, +-19.5313f,40.6765f,-15.625f, +-15.625f,43.5894f,-15.625f, +-11.7188f,46.3071f,-15.625f, +-7.8125f,48.6578f,-15.625f, +-3.90625f,49.0003f,-15.625f, +0.0f,50.5123f,-15.625f, +3.90625f,50.6915f,-15.625f, +-250.0f,1.44302f,-19.5313f, +-246.094f,1.65093f,-19.5313f, +-242.188f,2.94233f,-19.5313f, +-238.281f,4.72065f,-19.5313f, +-234.375f,6.57861f,-19.5313f, +-230.469f,7.31849f,-19.5313f, +-226.563f,7.90567f,-19.5313f, +-222.656f,9.84414f,-19.5313f, +-218.75f,12.1574f,-19.5313f, +-214.844f,13.2825f,-19.5313f, +-210.938f,15.2284f,-19.5313f, +-207.031f,17.2765f,-19.5313f, +-203.125f,19.1565f,-19.5313f, +-199.219f,20.3098f,-19.5313f, +-195.313f,21.9346f,-19.5313f, +-191.406f,23.8549f,-19.5313f, +-187.5f,26.133f,-19.5313f, +-183.594f,27.5858f,-19.5313f, +-179.688f,28.557f,-19.5313f, +-175.781f,28.9754f,-19.5313f, +-171.875f,29.9709f,-19.5313f, +-167.969f,31.2632f,-19.5313f, +-164.063f,31.4957f,-19.5313f, +-160.156f,33.6753f,-19.5313f, +-156.25f,35.1342f,-19.5313f, +-152.344f,35.0617f,-19.5313f, +-148.438f,34.9467f,-19.5313f, +-144.531f,35.1042f,-19.5313f, +-140.625f,35.0842f,-19.5313f, +-136.719f,34.7766f,-19.5313f, +-132.813f,33.8305f,-19.5313f, +-128.906f,33.3013f,-19.5313f, +-125.0f,32.5726f,-19.5313f, +-121.094f,31.5139f,-19.5313f, +-117.188f,31.4576f,-19.5313f, +-113.281f,31.6546f,-19.5313f, +-109.375f,32.4663f,-19.5313f, +-105.469f,32.6148f,-19.5313f, +-101.563f,31.253f,-19.5313f, +-97.6563f,29.5875f,-19.5313f, +-93.75f,28.4866f,-19.5313f, +-89.8438f,29.106f,-19.5313f, +-85.9375f,28.7092f,-19.5313f, +-82.0313f,27.4567f,-19.5313f, +-78.125f,26.5225f,-19.5313f, +-74.2188f,26.7534f,-19.5313f, +-70.3125f,26.278f,-19.5313f, +-66.4063f,25.6949f,-19.5313f, +-62.5f,25.7385f,-19.5313f, +-58.5938f,25.8791f,-19.5313f, +-54.6875f,27.42f,-19.5313f, +-50.7813f,29.0777f,-19.5313f, +-46.875f,31.016f,-19.5313f, +-42.9688f,32.5331f,-19.5313f, +-39.0625f,33.213f,-19.5313f, +-35.1563f,33.9437f,-19.5313f, +-31.25f,35.6737f,-19.5313f, +-27.3438f,37.8841f,-19.5313f, +-23.4375f,40.5289f,-19.5313f, +-19.5313f,43.6786f,-19.5313f, +-15.625f,47.2945f,-19.5313f, +-11.7188f,49.7082f,-19.5313f, +-7.8125f,51.1285f,-19.5313f, +-3.90625f,51.5532f,-19.5313f, +0.0f,52.3342f,-19.5313f, +3.90625f,52.1028f,-19.5313f, +-250.0f,1.05337f,-23.4375f, +-246.094f,1.28315f,-23.4375f, +-242.188f,3.38102f,-23.4375f, +-238.281f,4.51357f,-23.4375f, +-234.375f,5.63288f,-23.4375f, +-230.469f,6.49498f,-23.4375f, +-226.563f,7.71248f,-23.4375f, +-222.656f,8.83716f,-23.4375f, +-218.75f,10.4002f,-23.4375f, +-214.844f,11.8049f,-23.4375f, +-210.938f,13.7948f,-23.4375f, +-207.031f,16.5066f,-23.4375f, +-203.125f,18.598f,-23.4375f, +-199.219f,20.3069f,-23.4375f, +-195.313f,21.6868f,-23.4375f, +-191.406f,22.5781f,-23.4375f, +-187.5f,25.0292f,-23.4375f, +-183.594f,26.5386f,-23.4375f, +-179.688f,27.1952f,-23.4375f, +-175.781f,28.4023f,-23.4375f, +-171.875f,29.0264f,-23.4375f, +-167.969f,29.9302f,-23.4375f, +-164.063f,31.7992f,-23.4375f, +-160.156f,33.4902f,-23.4375f, +-156.25f,34.4307f,-23.4375f, +-152.344f,34.1463f,-23.4375f, +-148.438f,33.5881f,-23.4375f, +-144.531f,34.0515f,-23.4375f, +-140.625f,33.7128f,-23.4375f, +-136.719f,33.2076f,-23.4375f, +-132.813f,32.0419f,-23.4375f, +-128.906f,31.3464f,-23.4375f, +-125.0f,31.3552f,-23.4375f, +-121.094f,30.6713f,-23.4375f, +-117.188f,30.1403f,-23.4375f, +-113.281f,30.1753f,-23.4375f, +-109.375f,30.6182f,-23.4375f, +-105.469f,31.2785f,-23.4375f, +-101.563f,30.4839f,-23.4375f, +-97.6563f,28.9907f,-23.4375f, +-93.75f,29.3427f,-23.4375f, +-89.8438f,29.5539f,-23.4375f, +-85.9375f,29.4313f,-23.4375f, +-82.0313f,28.0148f,-23.4375f, +-78.125f,27.3569f,-23.4375f, +-74.2188f,26.8569f,-23.4375f, +-70.3125f,25.6193f,-23.4375f, +-66.4063f,25.8188f,-23.4375f, +-62.5f,25.458f,-23.4375f, +-58.5938f,26.5128f,-23.4375f, +-54.6875f,27.2598f,-23.4375f, +-50.7813f,28.4912f,-23.4375f, +-46.875f,31.0376f,-23.4375f, +-42.9688f,33.0941f,-23.4375f, +-39.0625f,34.4933f,-23.4375f, +-35.1563f,37.1957f,-23.4375f, +-31.25f,39.4612f,-23.4375f, +-27.3438f,41.4598f,-23.4375f, +-23.4375f,43.5893f,-23.4375f, +-19.5313f,46.8054f,-23.4375f, +-15.625f,49.4177f,-23.4375f, +-11.7188f,51.7957f,-23.4375f, +-7.8125f,53.1306f,-23.4375f, +-3.90625f,53.4872f,-23.4375f, +0.0f,53.6348f,-23.4375f, +3.90625f,54.332f,-23.4375f, +-250.0f,1.05459f,-27.3438f, +-246.094f,2.15725f,-27.3438f, +-242.188f,3.16747f,-27.3438f, +-238.281f,4.17562f,-27.3438f, +-234.375f,5.17097f,-27.3438f, +-230.469f,6.61997f,-27.3438f, +-226.563f,7.25727f,-27.3438f, +-222.656f,9.26302f,-27.3438f, +-218.75f,10.7606f,-27.3438f, +-214.844f,11.6966f,-27.3438f, +-210.938f,13.0425f,-27.3438f, +-207.031f,15.0672f,-27.3438f, +-203.125f,17.5971f,-27.3438f, +-199.219f,19.3182f,-27.3438f, +-195.313f,20.4505f,-27.3438f, +-191.406f,20.7017f,-27.3438f, +-187.5f,22.8054f,-27.3438f, +-183.594f,24.7406f,-27.3438f, +-179.688f,25.7957f,-27.3438f, +-175.781f,28.4608f,-27.3438f, +-171.875f,29.5031f,-27.3438f, +-167.969f,29.8812f,-27.3438f, +-164.063f,31.4954f,-27.3438f, +-160.156f,32.6053f,-27.3438f, +-156.25f,32.9274f,-27.3438f, +-152.344f,32.6481f,-27.3438f, +-148.438f,32.4456f,-27.3438f, +-144.531f,32.0065f,-27.3438f, +-140.625f,31.7655f,-27.3438f, +-136.719f,31.6836f,-27.3438f, +-132.813f,30.9994f,-27.3438f, +-128.906f,30.4065f,-27.3438f, +-125.0f,29.7478f,-27.3438f, +-121.094f,29.3871f,-27.3438f, +-117.188f,28.6628f,-27.3438f, +-113.281f,28.88f,-27.3438f, +-109.375f,29.3757f,-27.3438f, +-105.469f,29.7372f,-27.3438f, +-101.563f,28.9035f,-27.3438f, +-97.6563f,29.0842f,-27.3438f, +-93.75f,28.969f,-27.3438f, +-89.8438f,29.282f,-27.3438f, +-85.9375f,29.4429f,-27.3438f, +-82.0313f,29.2385f,-27.3438f, +-78.125f,28.2845f,-27.3438f, +-74.2188f,26.9413f,-27.3438f, +-70.3125f,26.3888f,-27.3438f, +-66.4063f,26.4127f,-27.3438f, +-62.5f,27.4297f,-27.3438f, +-58.5938f,28.0301f,-27.3438f, +-54.6875f,28.3682f,-27.3438f, +-50.7813f,30.4624f,-27.3438f, +-46.875f,32.6469f,-27.3438f, +-42.9688f,34.7681f,-27.3438f, +-39.0625f,37.3677f,-27.3438f, +-35.1563f,40.0943f,-27.3438f, +-31.25f,42.4424f,-27.3438f, +-27.3438f,44.5954f,-27.3438f, +-23.4375f,48.1538f,-27.3438f, +-19.5313f,50.5809f,-27.3438f, +-15.625f,52.7959f,-27.3438f, +-11.7188f,53.9779f,-27.3438f, +-7.8125f,55.2657f,-27.3438f, +-3.90625f,55.7427f,-27.3438f, +0.0f,56.6047f,-27.3438f, +3.90625f,57.5273f,-27.3438f, +-250.0f,1.91243f,-31.25f, +-246.094f,1.77508f,-31.25f, +-242.188f,2.89721f,-31.25f, +-238.281f,4.82177f,-31.25f, +-234.375f,5.57483f,-31.25f, +-230.469f,6.15697f,-31.25f, +-226.563f,7.43219f,-31.25f, +-222.656f,9.10752f,-31.25f, +-218.75f,10.7345f,-31.25f, +-214.844f,11.7298f,-31.25f, +-210.938f,13.0008f,-31.25f, +-207.031f,14.4465f,-31.25f, +-203.125f,16.7635f,-31.25f, +-199.219f,18.7095f,-31.25f, +-195.313f,19.057f,-31.25f, +-191.406f,19.522f,-31.25f, +-187.5f,21.0252f,-31.25f, +-183.594f,22.477f,-31.25f, +-179.688f,24.9456f,-31.25f, +-175.781f,27.5579f,-31.25f, +-171.875f,28.9367f,-31.25f, +-167.969f,29.5938f,-31.25f, +-164.063f,29.9491f,-31.25f, +-160.156f,31.1043f,-31.25f, +-156.25f,31.898f,-31.25f, +-152.344f,32.025f,-31.25f, +-148.438f,32.2848f,-31.25f, +-144.531f,31.4433f,-31.25f, +-140.625f,29.9423f,-31.25f, +-136.719f,30.2535f,-31.25f, +-132.813f,30.4668f,-31.25f, +-128.906f,30.1261f,-31.25f, +-125.0f,29.2612f,-31.25f, +-121.094f,27.5496f,-31.25f, +-117.188f,27.0659f,-31.25f, +-113.281f,27.3359f,-31.25f, +-109.375f,27.8418f,-31.25f, +-105.469f,28.9814f,-31.25f, +-101.563f,28.4429f,-31.25f, +-97.6563f,28.5833f,-31.25f, +-93.75f,28.9986f,-31.25f, +-89.8438f,30.3273f,-31.25f, +-85.9375f,30.5898f,-31.25f, +-82.0313f,29.8768f,-31.25f, +-78.125f,28.7278f,-31.25f, +-74.2188f,28.2599f,-31.25f, +-70.3125f,27.5942f,-31.25f, +-66.4063f,28.2721f,-31.25f, +-62.5f,28.9526f,-31.25f, +-58.5938f,29.4527f,-31.25f, +-54.6875f,30.1605f,-31.25f, +-50.7813f,32.6242f,-31.25f, +-46.875f,35.2708f,-31.25f, +-42.9688f,37.6696f,-31.25f, +-39.0625f,40.1477f,-31.25f, +-35.1563f,42.5127f,-31.25f, +-31.25f,45.655f,-31.25f, +-27.3438f,48.5747f,-31.25f, +-23.4375f,51.2069f,-31.25f, +-19.5313f,53.5599f,-31.25f, +-15.625f,55.3726f,-31.25f, +-11.7188f,56.4687f,-31.25f, +-7.8125f,56.313f,-31.25f, +-3.90625f,58.0363f,-31.25f, +0.0f,59.422f,-31.25f, +3.90625f,59.4204f,-31.25f, +-250.0f,1.80637f,-35.1563f, +-246.094f,1.14243f,-35.1563f, +-242.188f,2.08309f,-35.1563f, +-238.281f,3.66548f,-35.1563f, +-234.375f,4.49251f,-35.1563f, +-230.469f,5.63985f,-35.1563f, +-226.563f,7.33778f,-35.1563f, +-222.656f,9.15183f,-35.1563f, +-218.75f,10.0463f,-35.1563f, +-214.844f,11.7521f,-35.1563f, +-210.938f,12.6919f,-35.1563f, +-207.031f,14.0216f,-35.1563f, +-203.125f,14.9825f,-35.1563f, +-199.219f,16.2286f,-35.1563f, +-195.313f,17.2153f,-35.1563f, +-191.406f,18.0692f,-35.1563f, +-187.5f,19.858f,-35.1563f, +-183.594f,22.2715f,-35.1563f, +-179.688f,25.6457f,-35.1563f, +-175.781f,27.6627f,-35.1563f, +-171.875f,28.6491f,-35.1563f, +-167.969f,29.5869f,-35.1563f, +-164.063f,29.5582f,-35.1563f, +-160.156f,30.7619f,-35.1563f, +-156.25f,31.372f,-35.1563f, +-152.344f,31.4423f,-35.1563f, +-148.438f,31.7578f,-35.1563f, +-144.531f,31.1339f,-35.1563f, +-140.625f,29.3454f,-35.1563f, +-136.719f,28.0675f,-35.1563f, +-132.813f,28.1828f,-35.1563f, +-128.906f,28.2649f,-35.1563f, +-125.0f,27.2326f,-35.1563f, +-121.094f,26.2567f,-35.1563f, +-117.188f,25.4914f,-35.1563f, +-113.281f,25.5444f,-35.1563f, +-109.375f,25.8703f,-35.1563f, +-105.469f,27.9373f,-35.1563f, +-101.563f,27.9306f,-35.1563f, +-97.6563f,27.9282f,-35.1563f, +-93.75f,28.9199f,-35.1563f, +-89.8438f,30.142f,-35.1563f, +-85.9375f,30.3479f,-35.1563f, +-82.0313f,29.749f,-35.1563f, +-78.125f,29.2656f,-35.1563f, +-74.2188f,28.8561f,-35.1563f, +-70.3125f,28.7144f,-35.1563f, +-66.4063f,29.3204f,-35.1563f, +-62.5f,29.6751f,-35.1563f, +-58.5938f,31.0647f,-35.1563f, +-54.6875f,32.3243f,-35.1563f, +-50.7813f,34.476f,-35.1563f, +-46.875f,37.0984f,-35.1563f, +-42.9688f,40.1281f,-35.1563f, +-39.0625f,42.4472f,-35.1563f, +-35.1563f,45.6772f,-35.1563f, +-31.25f,49.5655f,-35.1563f, +-27.3438f,51.5783f,-35.1563f, +-23.4375f,53.3f,-35.1563f, +-19.5313f,55.4127f,-35.1563f, +-15.625f,56.8152f,-35.1563f, +-11.7188f,56.8985f,-35.1563f, +-7.8125f,57.5886f,-35.1563f, +-3.90625f,58.9321f,-35.1563f, +0.0f,60.2297f,-35.1563f, +3.90625f,60.2212f,-35.1563f, +-250.0f,2.59935f,-39.0625f, +-246.094f,1.55278f,-39.0625f, +-242.188f,1.42243f,-39.0625f, +-238.281f,2.78238f,-39.0625f, +-234.375f,3.85918f,-39.0625f, +-230.469f,5.01321f,-39.0625f, +-226.563f,6.56707f,-39.0625f, +-222.656f,7.99762f,-39.0625f, +-218.75f,9.72642f,-39.0625f, +-214.844f,11.975f,-39.0625f, +-210.938f,12.8008f,-39.0625f, +-207.031f,13.6902f,-39.0625f, +-203.125f,14.2017f,-39.0625f, +-199.219f,14.8784f,-39.0625f, +-195.313f,16.6265f,-39.0625f, +-191.406f,17.066f,-39.0625f, +-187.5f,19.3153f,-39.0625f, +-183.594f,23.4017f,-39.0625f, +-179.688f,26.2073f,-39.0625f, +-175.781f,27.92f,-39.0625f, +-171.875f,29.0435f,-39.0625f, +-167.969f,28.8537f,-39.0625f, +-164.063f,29.6445f,-39.0625f, +-160.156f,30.2119f,-39.0625f, +-156.25f,30.4693f,-39.0625f, +-152.344f,30.6063f,-39.0625f, +-148.438f,30.8716f,-39.0625f, +-144.531f,30.3253f,-39.0625f, +-140.625f,29.3941f,-39.0625f, +-136.719f,27.7606f,-39.0625f, +-132.813f,26.806f,-39.0625f, +-128.906f,26.6501f,-39.0625f, +-125.0f,25.6992f,-39.0625f, +-121.094f,24.4674f,-39.0625f, +-117.188f,24.1124f,-39.0625f, +-113.281f,24.9142f,-39.0625f, +-109.375f,25.5696f,-39.0625f, +-105.469f,25.4691f,-39.0625f, +-101.563f,26.7147f,-39.0625f, +-97.6563f,26.7558f,-39.0625f, +-93.75f,27.9278f,-39.0625f, +-89.8438f,29.0149f,-39.0625f, +-85.9375f,29.3557f,-39.0625f, +-82.0313f,29.6134f,-39.0625f, +-78.125f,29.4742f,-39.0625f, +-74.2188f,29.3377f,-39.0625f, +-70.3125f,29.6082f,-39.0625f, +-66.4063f,29.4634f,-39.0625f, +-62.5f,31.1775f,-39.0625f, +-58.5938f,32.7227f,-39.0625f, +-54.6875f,34.2233f,-39.0625f, +-50.7813f,36.1862f,-39.0625f, +-46.875f,38.7123f,-39.0625f, +-42.9688f,41.2396f,-39.0625f, +-39.0625f,44.5857f,-39.0625f, +-35.1563f,47.0183f,-39.0625f, +-31.25f,50.9933f,-39.0625f, +-27.3438f,53.2967f,-39.0625f, +-23.4375f,55.2026f,-39.0625f, +-19.5313f,56.3858f,-39.0625f, +-15.625f,57.8615f,-39.0625f, +-11.7188f,57.7515f,-39.0625f, +-7.8125f,58.8071f,-39.0625f, +-3.90625f,59.73f,-39.0625f, +0.0f,59.8999f,-39.0625f, +3.90625f,59.9094f,-39.0625f, +-250.0f,2.73015f,-42.9688f, +-246.094f,1.9296f,-42.9688f, +-242.188f,2.00835f,-42.9688f, +-238.281f,3.16245f,-42.9688f, +-234.375f,3.35198f,-42.9688f, +-230.469f,4.50732f,-42.9688f, +-226.563f,6.28971f,-42.9688f, +-222.656f,7.89723f,-42.9688f, +-218.75f,9.28447f,-42.9688f, +-214.844f,11.4302f,-42.9688f, +-210.938f,12.7156f,-42.9688f, +-207.031f,13.6281f,-42.9688f, +-203.125f,14.5932f,-42.9688f, +-199.219f,14.8129f,-42.9688f, +-195.313f,15.7965f,-42.9688f, +-191.406f,16.3571f,-42.9688f, +-187.5f,20.257f,-42.9688f, +-183.594f,23.2993f,-42.9688f, +-179.688f,25.4583f,-42.9688f, +-175.781f,27.2887f,-42.9688f, +-171.875f,27.9862f,-42.9688f, +-167.969f,28.274f,-42.9688f, +-164.063f,28.9264f,-42.9688f, +-160.156f,29.1855f,-42.9688f, +-156.25f,29.8898f,-42.9688f, +-152.344f,29.4922f,-42.9688f, +-148.438f,29.257f,-42.9688f, +-144.531f,28.9137f,-42.9688f, +-140.625f,27.618f,-42.9688f, +-136.719f,26.8539f,-42.9688f, +-132.813f,26.2806f,-42.9688f, +-128.906f,25.1378f,-42.9688f, +-125.0f,24.508f,-42.9688f, +-121.094f,23.8458f,-42.9688f, +-117.188f,23.501f,-42.9688f, +-113.281f,24.0593f,-42.9688f, +-109.375f,24.1366f,-42.9688f, +-105.469f,24.075f,-42.9688f, +-101.563f,24.5025f,-42.9688f, +-97.6563f,24.8457f,-42.9688f, +-93.75f,26.5028f,-42.9688f, +-89.8438f,26.9842f,-42.9688f, +-85.9375f,28.5672f,-42.9688f, +-82.0313f,28.9848f,-42.9688f, +-78.125f,29.1484f,-42.9688f, +-74.2188f,28.8735f,-42.9688f, +-70.3125f,29.9085f,-42.9688f, +-66.4063f,31.647f,-42.9688f, +-62.5f,32.8553f,-42.9688f, +-58.5938f,34.4488f,-42.9688f, +-54.6875f,35.7724f,-42.9688f, +-50.7813f,38.5181f,-42.9688f, +-46.875f,40.619f,-42.9688f, +-42.9688f,42.6158f,-42.9688f, +-39.0625f,45.9557f,-42.9688f, +-35.1563f,48.8071f,-42.9688f, +-31.25f,51.5425f,-42.9688f, +-27.3438f,54.1461f,-42.9688f, +-23.4375f,56.6935f,-42.9688f, +-19.5313f,57.353f,-42.9688f, +-15.625f,58.289f,-42.9688f, +-11.7188f,58.4633f,-42.9688f, +-7.8125f,59.0033f,-42.9688f, +-3.90625f,59.61f,-42.9688f, +0.0f,59.6115f,-42.9688f, +3.90625f,59.5207f,-42.9688f, +-250.0f,2.05499f,-46.875f, +-246.094f,1.44228f,-46.875f, +-242.188f,1.95946f,-46.875f, +-238.281f,2.50642f,-46.875f, +-234.375f,3.23732f,-46.875f, +-230.469f,4.46051f,-46.875f, +-226.563f,6.17815f,-46.875f, +-222.656f,7.58101f,-46.875f, +-218.75f,9.4063f,-46.875f, +-214.844f,11.394f,-46.875f, +-210.938f,12.4493f,-46.875f, +-207.031f,13.1281f,-46.875f, +-203.125f,13.8316f,-46.875f, +-199.219f,14.1574f,-46.875f, +-195.313f,15.0289f,-46.875f, +-191.406f,17.2095f,-46.875f, +-187.5f,20.3326f,-46.875f, +-183.594f,22.5046f,-46.875f, +-179.688f,24.7998f,-46.875f, +-175.781f,26.3728f,-46.875f, +-171.875f,27.3394f,-46.875f, +-167.969f,27.2989f,-46.875f, +-164.063f,27.5191f,-46.875f, +-160.156f,28.1581f,-46.875f, +-156.25f,28.357f,-46.875f, +-152.344f,27.2465f,-46.875f, +-148.438f,27.6591f,-46.875f, +-144.531f,26.7196f,-46.875f, +-140.625f,25.3776f,-46.875f, +-136.719f,25.1174f,-46.875f, +-132.813f,24.6913f,-46.875f, +-128.906f,23.828f,-46.875f, +-125.0f,22.7885f,-46.875f, +-121.094f,23.6316f,-46.875f, +-117.188f,23.288f,-46.875f, +-113.281f,22.8849f,-46.875f, +-109.375f,22.6367f,-46.875f, +-105.469f,22.2282f,-46.875f, +-101.563f,22.7539f,-46.875f, +-97.6563f,23.4319f,-46.875f, +-93.75f,25.0494f,-46.875f, +-89.8438f,25.7759f,-46.875f, +-85.9375f,27.2287f,-46.875f, +-82.0313f,28.1554f,-46.875f, +-78.125f,28.6794f,-46.875f, +-74.2188f,30.4763f,-46.875f, +-70.3125f,32.23f,-46.875f, +-66.4063f,33.6868f,-46.875f, +-62.5f,34.7841f,-46.875f, +-58.5938f,36.2585f,-46.875f, +-54.6875f,38.2534f,-46.875f, +-50.7813f,39.5261f,-46.875f, +-46.875f,41.7676f,-46.875f, +-42.9688f,44.8849f,-46.875f, +-39.0625f,47.6394f,-46.875f, +-35.1563f,49.5783f,-46.875f, +-31.25f,52.3871f,-46.875f, +-27.3438f,54.9333f,-46.875f, +-23.4375f,56.6705f,-46.875f, +-19.5313f,56.898f,-46.875f, +-15.625f,58.678f,-46.875f, +-11.7188f,59.6595f,-46.875f, +-7.8125f,59.0163f,-46.875f, +-3.90625f,59.3587f,-46.875f, +0.0f,58.5405f,-46.875f, +3.90625f,58.9086f,-46.875f, +-250.0f,2.57742f,-50.7813f, +-246.094f,2.06275f,-50.7813f, +-242.188f,2.26453f,-50.7813f, +-238.281f,2.43527f,-50.7813f, +-234.375f,2.63858f,-50.7813f, +-230.469f,4.44964f,-50.7813f, +-226.563f,6.50192f,-50.7813f, +-222.656f,8.11006f,-50.7813f, +-218.75f,10.1023f,-50.7813f, +-214.844f,11.3708f,-50.7813f, +-210.938f,12.7395f,-50.7813f, +-207.031f,13.6541f,-50.7813f, +-203.125f,13.6317f,-50.7813f, +-199.219f,13.4823f,-50.7813f, +-195.313f,15.3032f,-50.7813f, +-191.406f,17.5085f,-50.7813f, +-187.5f,19.5731f,-50.7813f, +-183.594f,22.0894f,-50.7813f, +-179.688f,23.8927f,-50.7813f, +-175.781f,24.9335f,-50.7813f, +-171.875f,26.1125f,-50.7813f, +-167.969f,25.9034f,-50.7813f, +-164.063f,26.9549f,-50.7813f, +-160.156f,26.7939f,-50.7813f, +-156.25f,26.3447f,-50.7813f, +-152.344f,25.6085f,-50.7813f, +-148.438f,25.2823f,-50.7813f, +-144.531f,25.4854f,-50.7813f, +-140.625f,23.906f,-50.7813f, +-136.719f,23.7094f,-50.7813f, +-132.813f,22.9599f,-50.7813f, +-128.906f,22.3089f,-50.7813f, +-125.0f,22.302f,-50.7813f, +-121.094f,23.3289f,-50.7813f, +-117.188f,23.1804f,-50.7813f, +-113.281f,22.6693f,-50.7813f, +-109.375f,21.2587f,-50.7813f, +-105.469f,20.4638f,-50.7813f, +-101.563f,21.4819f,-50.7813f, +-97.6563f,22.0137f,-50.7813f, +-93.75f,23.4763f,-50.7813f, +-89.8438f,25.2125f,-50.7813f, +-85.9375f,26.446f,-50.7813f, +-82.0313f,27.5614f,-50.7813f, +-78.125f,29.5641f,-50.7813f, +-74.2188f,31.1552f,-50.7813f, +-70.3125f,33.5337f,-50.7813f, +-66.4063f,35.653f,-50.7813f, +-62.5f,36.2419f,-50.7813f, +-58.5938f,37.4297f,-50.7813f, +-54.6875f,39.7492f,-50.7813f, +-50.7813f,41.494f,-50.7813f, +-46.875f,44.5449f,-50.7813f, +-42.9688f,47.2689f,-50.7813f, +-39.0625f,49.6705f,-50.7813f, +-35.1563f,51.8942f,-50.7813f, +-31.25f,53.9483f,-50.7813f, +-27.3438f,55.2444f,-50.7813f, +-23.4375f,56.5482f,-50.7813f, +-19.5313f,58.5545f,-50.7813f, +-15.625f,59.5559f,-50.7813f, +-11.7188f,58.8699f,-50.7813f, +-7.8125f,59.0373f,-50.7813f, +-3.90625f,59.5884f,-50.7813f, +0.0f,59.6491f,-50.7813f, +3.90625f,59.8509f,-50.7813f, +-250.0f,2.04136f,-54.6875f, +-246.094f,2.5492f,-54.6875f, +-242.188f,2.70952f,-54.6875f, +-238.281f,3.00758f,-54.6875f, +-234.375f,3.54707f,-54.6875f, +-230.469f,5.09851f,-54.6875f, +-226.563f,7.09409f,-54.6875f, +-222.656f,8.40975f,-54.6875f, +-218.75f,10.0555f,-54.6875f, +-214.844f,11.4962f,-54.6875f, +-210.938f,12.1806f,-54.6875f, +-207.031f,12.7217f,-54.6875f, +-203.125f,12.6935f,-54.6875f, +-199.219f,14.0259f,-54.6875f, +-195.313f,16.1147f,-54.6875f, +-191.406f,18.3888f,-54.6875f, +-187.5f,19.3549f,-54.6875f, +-183.594f,21.6563f,-54.6875f, +-179.688f,22.9906f,-54.6875f, +-175.781f,23.7728f,-54.6875f, +-171.875f,25.2286f,-54.6875f, +-167.969f,26.0764f,-54.6875f, +-164.063f,26.746f,-54.6875f, +-160.156f,26.3029f,-54.6875f, +-156.25f,25.6172f,-54.6875f, +-152.344f,24.537f,-54.6875f, +-148.438f,23.8458f,-54.6875f, +-144.531f,23.3726f,-54.6875f, +-140.625f,22.8694f,-54.6875f, +-136.719f,22.5247f,-54.6875f, +-132.813f,21.436f,-54.6875f, +-128.906f,21.4712f,-54.6875f, +-125.0f,22.1621f,-54.6875f, +-121.094f,22.4599f,-54.6875f, +-117.188f,21.4148f,-54.6875f, +-113.281f,20.8237f,-54.6875f, +-109.375f,19.6257f,-54.6875f, +-105.469f,20.1462f,-54.6875f, +-101.563f,21.5895f,-54.6875f, +-97.6563f,22.2376f,-54.6875f, +-93.75f,23.679f,-54.6875f, +-89.8438f,24.9403f,-54.6875f, +-85.9375f,26.4205f,-54.6875f, +-82.0313f,27.9125f,-54.6875f, +-78.125f,30.0689f,-54.6875f, +-74.2188f,32.7388f,-54.6875f, +-70.3125f,34.3502f,-54.6875f, +-66.4063f,35.6763f,-54.6875f, +-62.5f,37.4625f,-54.6875f, +-58.5938f,38.3448f,-54.6875f, +-54.6875f,40.6027f,-54.6875f, +-50.7813f,44.4532f,-54.6875f, +-46.875f,47.6182f,-54.6875f, +-42.9688f,49.7683f,-54.6875f, +-39.0625f,52.1875f,-54.6875f, +-35.1563f,54.4951f,-54.6875f, +-31.25f,55.9437f,-54.6875f, +-27.3438f,57.1353f,-54.6875f, +-23.4375f,58.016f,-54.6875f, +-19.5313f,59.6013f,-54.6875f, +-15.625f,59.9872f,-54.6875f, +-11.7188f,59.8299f,-54.6875f, +-7.8125f,60.1035f,-54.6875f, +-3.90625f,60.8558f,-54.6875f, +0.0f,60.5619f,-54.6875f, +3.90625f,60.3928f,-54.6875f, +-250.0f,4.01167f,-58.5938f, +-246.094f,3.0694f,-58.5938f, +-242.188f,3.37661f,-58.5938f, +-238.281f,3.71931f,-58.5938f, +-234.375f,4.08816f,-58.5938f, +-230.469f,5.56386f,-58.5938f, +-226.563f,7.3314f,-58.5938f, +-222.656f,8.61323f,-58.5938f, +-218.75f,9.77849f,-58.5938f, +-214.844f,11.9744f,-58.5938f, +-210.938f,12.9366f,-58.5938f, +-207.031f,13.5175f,-58.5938f, +-203.125f,13.948f,-58.5938f, +-199.219f,14.4053f,-58.5938f, +-195.313f,16.1496f,-58.5938f, +-191.406f,17.8653f,-58.5938f, +-187.5f,18.9853f,-58.5938f, +-183.594f,21.2985f,-58.5938f, +-179.688f,23.4932f,-58.5938f, +-175.781f,25.3544f,-58.5938f, +-171.875f,26.1087f,-58.5938f, +-167.969f,26.5864f,-58.5938f, +-164.063f,25.8729f,-58.5938f, +-160.156f,25.0068f,-58.5938f, +-156.25f,25.2867f,-58.5938f, +-152.344f,23.9482f,-58.5938f, +-148.438f,23.23f,-58.5938f, +-144.531f,22.6171f,-58.5938f, +-140.625f,21.4991f,-58.5938f, +-136.719f,21.0822f,-58.5938f, +-132.813f,21.0037f,-58.5938f, +-128.906f,21.8362f,-58.5938f, +-125.0f,21.5985f,-58.5938f, +-121.094f,20.951f,-58.5938f, +-117.188f,21.2066f,-58.5938f, +-113.281f,19.7479f,-58.5938f, +-109.375f,18.5787f,-58.5938f, +-105.469f,20.3984f,-58.5938f, +-101.563f,22.257f,-58.5938f, +-97.6563f,23.3411f,-58.5938f, +-93.75f,24.362f,-58.5938f, +-89.8438f,25.7544f,-58.5938f, +-85.9375f,27.7522f,-58.5938f, +-82.0313f,28.9204f,-58.5938f, +-78.125f,30.8124f,-58.5938f, +-74.2188f,32.9097f,-58.5938f, +-70.3125f,34.8737f,-58.5938f, +-66.4063f,36.0518f,-58.5938f, +-62.5f,38.506f,-58.5938f, +-58.5938f,41.2951f,-58.5938f, +-54.6875f,43.3387f,-58.5938f, +-50.7813f,46.5457f,-58.5938f, +-46.875f,49.2409f,-58.5938f, +-42.9688f,51.3946f,-58.5938f, +-39.0625f,54.0957f,-58.5938f, +-35.1563f,55.8205f,-58.5938f, +-31.25f,57.094f,-58.5938f, +-27.3438f,58.0636f,-58.5938f, +-23.4375f,58.8159f,-58.5938f, +-19.5313f,59.9761f,-58.5938f, +-15.625f,60.2094f,-58.5938f, +-11.7188f,60.0275f,-58.5938f, +-7.8125f,61.0991f,-58.5938f, +-3.90625f,61.4786f,-58.5938f, +0.0f,61.4895f,-58.5938f, +3.90625f,61.5747f,-58.5938f, +-250.0f,5.54938f,-62.5f, +-246.094f,4.18374f,-62.5f, +-242.188f,3.90057f,-62.5f, +-238.281f,4.25951f,-62.5f, +-234.375f,4.82365f,-62.5f, +-230.469f,6.03197f,-62.5f, +-226.563f,7.69909f,-62.5f, +-222.656f,8.80826f,-62.5f, +-218.75f,10.8241f,-62.5f, +-214.844f,13.5771f,-62.5f, +-210.938f,14.456f,-62.5f, +-207.031f,15.0395f,-62.5f, +-203.125f,14.5505f,-62.5f, +-199.219f,16.1706f,-62.5f, +-195.313f,16.9508f,-62.5f, +-191.406f,18.2016f,-62.5f, +-187.5f,19.8694f,-62.5f, +-183.594f,22.6167f,-62.5f, +-179.688f,24.5727f,-62.5f, +-175.781f,26.0063f,-62.5f, +-171.875f,26.0399f,-62.5f, +-167.969f,26.6416f,-62.5f, +-164.063f,25.6476f,-62.5f, +-160.156f,24.4615f,-62.5f, +-156.25f,23.5295f,-62.5f, +-152.344f,23.7879f,-62.5f, +-148.438f,22.8826f,-62.5f, +-144.531f,21.6558f,-62.5f, +-140.625f,20.6405f,-62.5f, +-136.719f,20.1695f,-62.5f, +-132.813f,20.7715f,-62.5f, +-128.906f,20.5918f,-62.5f, +-125.0f,20.4476f,-62.5f, +-121.094f,19.9068f,-62.5f, +-117.188f,19.4838f,-62.5f, +-113.281f,17.843f,-62.5f, +-109.375f,18.5661f,-62.5f, +-105.469f,20.1106f,-62.5f, +-101.563f,21.3182f,-62.5f, +-97.6563f,23.2851f,-62.5f, +-93.75f,24.3601f,-62.5f, +-89.8438f,26.3742f,-62.5f, +-85.9375f,27.7409f,-62.5f, +-82.0313f,29.533f,-62.5f, +-78.125f,31.5622f,-62.5f, +-74.2188f,33.2773f,-62.5f, +-70.3125f,35.6025f,-62.5f, +-66.4063f,38.4255f,-62.5f, +-62.5f,40.916f,-62.5f, +-58.5938f,43.9378f,-62.5f, +-54.6875f,45.9116f,-62.5f, +-50.7813f,48.3177f,-62.5f, +-46.875f,50.1977f,-62.5f, +-42.9688f,52.4552f,-62.5f, +-39.0625f,54.6779f,-62.5f, +-35.1563f,56.1564f,-62.5f, +-31.25f,57.5665f,-62.5f, +-27.3438f,58.7762f,-62.5f, +-23.4375f,59.115f,-62.5f, +-19.5313f,58.5535f,-62.5f, +-15.625f,58.2117f,-62.5f, +-11.7188f,59.0863f,-62.5f, +-7.8125f,60.3775f,-62.5f, +-3.90625f,61.0192f,-62.5f, +0.0f,61.864f,-62.5f, +3.90625f,62.1111f,-62.5f, +-250.0f,6.08003f,-66.4063f, +-246.094f,5.13458f,-66.4063f, +-242.188f,5.0967f,-66.4063f, +-238.281f,5.36926f,-66.4063f, +-234.375f,5.21926f,-66.4063f, +-230.469f,6.37997f,-66.4063f, +-226.563f,7.85032f,-66.4063f, +-222.656f,9.36117f,-66.4063f, +-218.75f,11.896f,-66.4063f, +-214.844f,13.9549f,-66.4063f, +-210.938f,15.4673f,-66.4063f, +-207.031f,15.9885f,-66.4063f, +-203.125f,16.4425f,-66.4063f, +-199.219f,17.4253f,-66.4063f, +-195.313f,18.1385f,-66.4063f, +-191.406f,18.8676f,-66.4063f, +-187.5f,20.1316f,-66.4063f, +-183.594f,22.8534f,-66.4063f, +-179.688f,24.5364f,-66.4063f, +-175.781f,25.6234f,-66.4063f, +-171.875f,25.9362f,-66.4063f, +-167.969f,25.7735f,-66.4063f, +-164.063f,25.1524f,-66.4063f, +-160.156f,24.4245f,-66.4063f, +-156.25f,22.8769f,-66.4063f, +-152.344f,22.8762f,-66.4063f, +-148.438f,21.9008f,-66.4063f, +-144.531f,20.9242f,-66.4063f, +-140.625f,20.1022f,-66.4063f, +-136.719f,19.5823f,-66.4063f, +-132.813f,19.4415f,-66.4063f, +-128.906f,18.9513f,-66.4063f, +-125.0f,18.9264f,-66.4063f, +-121.094f,18.6878f,-66.4063f, +-117.188f,17.8998f,-66.4063f, +-113.281f,17.9815f,-66.4063f, +-109.375f,18.2652f,-66.4063f, +-105.469f,19.533f,-66.4063f, +-101.563f,21.0045f,-66.4063f, +-97.6563f,22.2461f,-66.4063f, +-93.75f,23.7189f,-66.4063f, +-89.8438f,25.574f,-66.4063f, +-85.9375f,27.55f,-66.4063f, +-82.0313f,29.733f,-66.4063f, +-78.125f,31.0763f,-66.4063f, +-74.2188f,33.9607f,-66.4063f, +-70.3125f,37.3595f,-66.4063f, +-66.4063f,41.019f,-66.4063f, +-62.5f,43.7286f,-66.4063f, +-58.5938f,46.5077f,-66.4063f, +-54.6875f,47.985f,-66.4063f, +-50.7813f,49.2623f,-66.4063f, +-46.875f,50.9465f,-66.4063f, +-42.9688f,52.912f,-66.4063f, +-39.0625f,55.0349f,-66.4063f, +-35.1563f,56.428f,-66.4063f, +-31.25f,57.3951f,-66.4063f, +-27.3438f,58.5332f,-66.4063f, +-23.4375f,58.3328f,-66.4063f, +-19.5313f,56.9549f,-66.4063f, +-15.625f,56.9387f,-66.4063f, +-11.7188f,58.3656f,-66.4063f, +-7.8125f,59.6577f,-66.4063f, +-3.90625f,59.8566f,-66.4063f, +0.0f,60.693f,-66.4063f, +3.90625f,60.8569f,-66.4063f, +-250.0f,6.38861f,-70.3125f, +-246.094f,6.37976f,-70.3125f, +-242.188f,6.52455f,-70.3125f, +-238.281f,6.93657f,-70.3125f, +-234.375f,6.77321f,-70.3125f, +-230.469f,7.26034f,-70.3125f, +-226.563f,8.99316f,-70.3125f, +-222.656f,10.5015f,-70.3125f, +-218.75f,11.631f,-70.3125f, +-214.844f,14.0548f,-70.3125f, +-210.938f,15.9163f,-70.3125f, +-207.031f,16.6824f,-70.3125f, +-203.125f,17.1063f,-70.3125f, +-199.219f,18.066f,-70.3125f, +-195.313f,18.5539f,-70.3125f, +-191.406f,18.8425f,-70.3125f, +-187.5f,20.7731f,-70.3125f, +-183.594f,22.8929f,-70.3125f, +-179.688f,24.2011f,-70.3125f, +-175.781f,24.5512f,-70.3125f, +-171.875f,24.651f,-70.3125f, +-167.969f,23.9906f,-70.3125f, +-164.063f,23.6279f,-70.3125f, +-160.156f,23.6162f,-70.3125f, +-156.25f,22.3196f,-70.3125f, +-152.344f,22.173f,-70.3125f, +-148.438f,20.6833f,-70.3125f, +-144.531f,19.6848f,-70.3125f, +-140.625f,18.4633f,-70.3125f, +-136.719f,18.2692f,-70.3125f, +-132.813f,18.0595f,-70.3125f, +-128.906f,17.2062f,-70.3125f, +-125.0f,17.0103f,-70.3125f, +-121.094f,17.1584f,-70.3125f, +-117.188f,17.5441f,-70.3125f, +-113.281f,17.5669f,-70.3125f, +-109.375f,17.7536f,-70.3125f, +-105.469f,18.3913f,-70.3125f, +-101.563f,19.7264f,-70.3125f, +-97.6563f,20.8943f,-70.3125f, +-93.75f,22.7517f,-70.3125f, +-89.8438f,25.1479f,-70.3125f, +-85.9375f,27.3953f,-70.3125f, +-82.0313f,29.5127f,-70.3125f, +-78.125f,31.2816f,-70.3125f, +-74.2188f,34.6589f,-70.3125f, +-70.3125f,38.2161f,-70.3125f, +-66.4063f,42.3872f,-70.3125f, +-62.5f,45.4363f,-70.3125f, +-58.5938f,47.0181f,-70.3125f, +-54.6875f,48.7348f,-70.3125f, +-50.7813f,49.8739f,-70.3125f, +-46.875f,51.2434f,-70.3125f, +-42.9688f,52.9444f,-70.3125f, +-39.0625f,54.8413f,-70.3125f, +-35.1563f,55.8776f,-70.3125f, +-31.25f,56.9088f,-70.3125f, +-27.3438f,56.8827f,-70.3125f, +-23.4375f,56.1649f,-70.3125f, +-19.5313f,54.9828f,-70.3125f, +-15.625f,56.5543f,-70.3125f, +-11.7188f,58.0071f,-70.3125f, +-7.8125f,58.1204f,-70.3125f, +-3.90625f,58.8019f,-70.3125f, +0.0f,59.3765f,-70.3125f, +3.90625f,59.1482f,-70.3125f, +-250.0f,7.29753f,-74.2188f, +-246.094f,6.9318f,-74.2188f, +-242.188f,7.9493f,-74.2188f, +-238.281f,7.61482f,-74.2188f, +-234.375f,8.38948f,-74.2188f, +-230.469f,8.85034f,-74.2188f, +-226.563f,10.783f,-74.2188f, +-222.656f,12.203f,-74.2188f, +-218.75f,12.7122f,-74.2188f, +-214.844f,14.2813f,-74.2188f, +-210.938f,16.1159f,-74.2188f, +-207.031f,16.8501f,-74.2188f, +-203.125f,17.728f,-74.2188f, +-199.219f,18.6948f,-74.2188f, +-195.313f,19.0254f,-74.2188f, +-191.406f,18.9874f,-74.2188f, +-187.5f,20.7575f,-74.2188f, +-183.594f,22.4682f,-74.2188f, +-179.688f,23.785f,-74.2188f, +-175.781f,23.136f,-74.2188f, +-171.875f,22.2872f,-74.2188f, +-167.969f,21.9381f,-74.2188f, +-164.063f,22.818f,-74.2188f, +-160.156f,21.8019f,-74.2188f, +-156.25f,21.3496f,-74.2188f, +-152.344f,19.9092f,-74.2188f, +-148.438f,19.5338f,-74.2188f, +-144.531f,19.2227f,-74.2188f, +-140.625f,17.2583f,-74.2188f, +-136.719f,15.7727f,-74.2188f, +-132.813f,15.2069f,-74.2188f, +-128.906f,15.0929f,-74.2188f, +-125.0f,15.3066f,-74.2188f, +-121.094f,15.1161f,-74.2188f, +-117.188f,16.1171f,-74.2188f, +-113.281f,17.2851f,-74.2188f, +-109.375f,16.8359f,-74.2188f, +-105.469f,17.6612f,-74.2188f, +-101.563f,18.1651f,-74.2188f, +-97.6563f,18.9354f,-74.2188f, +-93.75f,21.1152f,-74.2188f, +-89.8438f,23.9267f,-74.2188f, +-85.9375f,26.5361f,-74.2188f, +-82.0313f,29.6007f,-74.2188f, +-78.125f,31.8355f,-74.2188f, +-74.2188f,34.5711f,-74.2188f, +-70.3125f,37.6211f,-74.2188f, +-66.4063f,41.978f,-74.2188f, +-62.5f,44.757f,-74.2188f, +-58.5938f,47.2561f,-74.2188f, +-54.6875f,48.796f,-74.2188f, +-50.7813f,50.085f,-74.2188f, +-46.875f,51.427f,-74.2188f, +-42.9688f,52.9103f,-74.2188f, +-39.0625f,53.6345f,-74.2188f, +-35.1563f,55.5589f,-74.2188f, +-31.25f,56.4557f,-74.2188f, +-27.3438f,55.8259f,-74.2188f, +-23.4375f,55.2472f,-74.2188f, +-19.5313f,54.9161f,-74.2188f, +-15.625f,56.2403f,-74.2188f, +-11.7188f,57.7266f,-74.2188f, +-7.8125f,57.6855f,-74.2188f, +-3.90625f,57.4796f,-74.2188f, +0.0f,56.3955f,-74.2188f, +3.90625f,56.5167f,-74.2188f, +-250.0f,8.88618f,-78.125f, +-246.094f,8.31776f,-78.125f, +-242.188f,8.67289f,-78.125f, +-238.281f,9.52219f,-78.125f, +-234.375f,9.78196f,-78.125f, +-230.469f,11.3032f,-78.125f, +-226.563f,13.1558f,-78.125f, +-222.656f,14.4361f,-78.125f, +-218.75f,15.5721f,-78.125f, +-214.844f,14.3491f,-78.125f, +-210.938f,15.6393f,-78.125f, +-207.031f,16.9133f,-78.125f, +-203.125f,18.1402f,-78.125f, +-199.219f,19.179f,-78.125f, +-195.313f,18.9448f,-78.125f, +-191.406f,19.5289f,-78.125f, +-187.5f,20.8547f,-78.125f, +-183.594f,22.7611f,-78.125f, +-179.688f,22.8314f,-78.125f, +-175.781f,21.815f,-78.125f, +-171.875f,22.2112f,-78.125f, +-167.969f,21.9322f,-78.125f, +-164.063f,21.3024f,-78.125f, +-160.156f,20.354f,-78.125f, +-156.25f,19.8588f,-78.125f, +-152.344f,17.8458f,-78.125f, +-148.438f,18.0613f,-78.125f, +-144.531f,17.0664f,-78.125f, +-140.625f,16.2256f,-78.125f, +-136.719f,14.3082f,-78.125f, +-132.813f,13.3463f,-78.125f, +-128.906f,14.3881f,-78.125f, +-125.0f,14.6865f,-78.125f, +-121.094f,14.2011f,-78.125f, +-117.188f,15.4562f,-78.125f, +-113.281f,16.6171f,-78.125f, +-109.375f,16.2869f,-78.125f, +-105.469f,15.9406f,-78.125f, +-101.563f,17.5579f,-78.125f, +-97.6563f,19.157f,-78.125f, +-93.75f,21.0678f,-78.125f, +-89.8438f,23.1633f,-78.125f, +-85.9375f,25.2991f,-78.125f, +-82.0313f,28.9462f,-78.125f, +-78.125f,31.8594f,-78.125f, +-74.2188f,35.2294f,-78.125f, +-70.3125f,36.9557f,-78.125f, +-66.4063f,40.692f,-78.125f, +-62.5f,44.5904f,-78.125f, +-58.5938f,46.9805f,-78.125f, +-54.6875f,48.3073f,-78.125f, +-50.7813f,49.8001f,-78.125f, +-46.875f,51.4881f,-78.125f, +-42.9688f,52.7488f,-78.125f, +-39.0625f,53.0994f,-78.125f, +-35.1563f,54.6505f,-78.125f, +-31.25f,55.3393f,-78.125f, +-27.3438f,55.3608f,-78.125f, +-23.4375f,54.3833f,-78.125f, +-19.5313f,53.9595f,-78.125f, +-15.625f,55.0695f,-78.125f, +-11.7188f,56.423f,-78.125f, +-7.8125f,56.1568f,-78.125f, +-3.90625f,56.2841f,-78.125f, +0.0f,54.7508f,-78.125f, +3.90625f,54.4402f,-78.125f, +-250.0f,10.7839f,-82.0313f, +-246.094f,10.1255f,-82.0313f, +-242.188f,10.6621f,-82.0313f, +-238.281f,11.4172f,-82.0313f, +-234.375f,12.3063f,-82.0313f, +-230.469f,13.4915f,-82.0313f, +-226.563f,14.9113f,-82.0313f, +-222.656f,16.5463f,-82.0313f, +-218.75f,17.3752f,-82.0313f, +-214.844f,16.6701f,-82.0313f, +-210.938f,15.5847f,-82.0313f, +-207.031f,16.6988f,-82.0313f, +-203.125f,17.6449f,-82.0313f, +-199.219f,18.4976f,-82.0313f, +-195.313f,18.033f,-82.0313f, +-191.406f,19.1758f,-82.0313f, +-187.5f,20.7116f,-82.0313f, +-183.594f,21.5492f,-82.0313f, +-179.688f,20.7908f,-82.0313f, +-175.781f,20.6891f,-82.0313f, +-171.875f,21.6368f,-82.0313f, +-167.969f,21.6862f,-82.0313f, +-164.063f,20.4236f,-82.0313f, +-160.156f,19.4449f,-82.0313f, +-156.25f,17.8718f,-82.0313f, +-152.344f,16.0984f,-82.0313f, +-148.438f,16.1225f,-82.0313f, +-144.531f,15.3001f,-82.0313f, +-140.625f,14.0113f,-82.0313f, +-136.719f,12.7128f,-82.0313f, +-132.813f,13.1695f,-82.0313f, +-128.906f,14.1608f,-82.0313f, +-125.0f,14.006f,-82.0313f, +-121.094f,13.5671f,-82.0313f, +-117.188f,14.799f,-82.0313f, +-113.281f,15.6819f,-82.0313f, +-109.375f,15.1047f,-82.0313f, +-105.469f,15.4826f,-82.0313f, +-101.563f,17.2178f,-82.0313f, +-97.6563f,19.1794f,-82.0313f, +-93.75f,21.3021f,-82.0313f, +-89.8438f,21.9981f,-82.0313f, +-85.9375f,24.4031f,-82.0313f, +-82.0313f,28.8062f,-82.0313f, +-78.125f,31.7576f,-82.0313f, +-74.2188f,34.6198f,-82.0313f, +-70.3125f,37.0145f,-82.0313f, +-66.4063f,39.5952f,-82.0313f, +-62.5f,43.4294f,-82.0313f, +-58.5938f,45.9611f,-82.0313f, +-54.6875f,47.398f,-82.0313f, +-50.7813f,49.5672f,-82.0313f, +-46.875f,51.4863f,-82.0313f, +-42.9688f,52.3277f,-82.0313f, +-39.0625f,52.6736f,-82.0313f, +-35.1563f,53.5554f,-82.0313f, +-31.25f,54.4611f,-82.0313f, +-27.3438f,53.3151f,-82.0313f, +-23.4375f,52.9631f,-82.0313f, +-19.5313f,52.3147f,-82.0313f, +-15.625f,53.7891f,-82.0313f, +-11.7188f,54.3962f,-82.0313f, +-7.8125f,54.2326f,-82.0313f, +-3.90625f,53.6717f,-82.0313f, +0.0f,52.8681f,-82.0313f, +3.90625f,51.949f,-82.0313f, +-250.0f,12.2756f,-85.9375f, +-246.094f,11.9011f,-85.9375f, +-242.188f,13.4495f,-85.9375f, +-238.281f,14.3858f,-85.9375f, +-234.375f,14.855f,-85.9375f, +-230.469f,15.3384f,-85.9375f, +-226.563f,17.3357f,-85.9375f, +-222.656f,18.7108f,-85.9375f, +-218.75f,18.0095f,-85.9375f, +-214.844f,17.4308f,-85.9375f, +-210.938f,17.0565f,-85.9375f, +-207.031f,16.4039f,-85.9375f, +-203.125f,17.3449f,-85.9375f, +-199.219f,17.5816f,-85.9375f, +-195.313f,17.7511f,-85.9375f, +-191.406f,18.792f,-85.9375f, +-187.5f,19.7983f,-85.9375f, +-183.594f,19.6069f,-85.9375f, +-179.688f,19.1396f,-85.9375f, +-175.781f,19.0184f,-85.9375f, +-171.875f,19.7492f,-85.9375f, +-167.969f,19.6428f,-85.9375f, +-164.063f,18.6091f,-85.9375f, +-160.156f,18.1998f,-85.9375f, +-156.25f,16.6809f,-85.9375f, +-152.344f,15.0269f,-85.9375f, +-148.438f,13.3773f,-85.9375f, +-144.531f,12.7371f,-85.9375f, +-140.625f,12.2537f,-85.9375f, +-136.719f,12.6536f,-85.9375f, +-132.813f,12.7798f,-85.9375f, +-128.906f,13.2089f,-85.9375f, +-125.0f,12.8356f,-85.9375f, +-121.094f,12.5484f,-85.9375f, +-117.188f,13.5275f,-85.9375f, +-113.281f,13.5387f,-85.9375f, +-109.375f,13.6111f,-85.9375f, +-105.469f,14.7023f,-85.9375f, +-101.563f,16.6526f,-85.9375f, +-97.6563f,17.9729f,-85.9375f, +-93.75f,19.8258f,-85.9375f, +-89.8438f,21.7903f,-85.9375f, +-85.9375f,23.4003f,-85.9375f, +-82.0313f,27.4381f,-85.9375f, +-78.125f,30.1644f,-85.9375f, +-74.2188f,33.7682f,-85.9375f, +-70.3125f,36.1779f,-85.9375f, +-66.4063f,38.1368f,-85.9375f, +-62.5f,41.5768f,-85.9375f, +-58.5938f,43.7832f,-85.9375f, +-54.6875f,45.866f,-85.9375f, +-50.7813f,48.5751f,-85.9375f, +-46.875f,50.4188f,-85.9375f, +-42.9688f,51.0239f,-85.9375f, +-39.0625f,51.2389f,-85.9375f, +-35.1563f,51.8865f,-85.9375f, +-31.25f,52.9036f,-85.9375f, +-27.3438f,52.5405f,-85.9375f, +-23.4375f,52.3296f,-85.9375f, +-19.5313f,52.5889f,-85.9375f, +-15.625f,52.3033f,-85.9375f, +-11.7188f,52.1239f,-85.9375f, +-7.8125f,52.0608f,-85.9375f, +-3.90625f,51.0213f,-85.9375f, +0.0f,50.5601f,-85.9375f, +3.90625f,50.007f,-85.9375f, +-250.0f,13.6424f,-89.8438f, +-246.094f,14.2919f,-89.8438f, +-242.188f,15.9647f,-89.8438f, +-238.281f,17.1274f,-89.8438f, +-234.375f,17.9206f,-89.8438f, +-230.469f,17.9917f,-89.8438f, +-226.563f,19.3423f,-89.8438f, +-222.656f,20.1401f,-89.8438f, +-218.75f,19.295f,-89.8438f, +-214.844f,18.1101f,-89.8438f, +-210.938f,17.3485f,-89.8438f, +-207.031f,17.1077f,-89.8438f, +-203.125f,17.7413f,-89.8438f, +-199.219f,17.2325f,-89.8438f, +-195.313f,17.6696f,-89.8438f, +-191.406f,18.8437f,-89.8438f, +-187.5f,19.1808f,-89.8438f, +-183.594f,18.6366f,-89.8438f, +-179.688f,17.3251f,-89.8438f, +-175.781f,17.5752f,-89.8438f, +-171.875f,18.1005f,-89.8438f, +-167.969f,18.0907f,-89.8438f, +-164.063f,16.519f,-89.8438f, +-160.156f,15.5225f,-89.8438f, +-156.25f,14.3937f,-89.8438f, +-152.344f,13.4199f,-89.8438f, +-148.438f,12.8584f,-89.8438f, +-144.531f,12.8604f,-89.8438f, +-140.625f,12.2817f,-89.8438f, +-136.719f,12.4113f,-89.8438f, +-132.813f,12.9949f,-89.8438f, +-128.906f,11.9716f,-89.8438f, +-125.0f,11.8348f,-89.8438f, +-121.094f,12.2532f,-89.8438f, +-117.188f,12.5983f,-89.8438f, +-113.281f,13.2095f,-89.8438f, +-109.375f,13.7209f,-89.8438f, +-105.469f,13.8655f,-89.8438f, +-101.563f,14.8679f,-89.8438f, +-97.6563f,16.1039f,-89.8438f, +-93.75f,17.9997f,-89.8438f, +-89.8438f,20.0247f,-89.8438f, +-85.9375f,22.8012f,-89.8438f, +-82.0313f,25.8255f,-89.8438f, +-78.125f,29.0288f,-89.8438f, +-74.2188f,31.8325f,-89.8438f, +-70.3125f,34.2688f,-89.8438f, +-66.4063f,37.2576f,-89.8438f, +-62.5f,40.8036f,-89.8438f, +-58.5938f,43.0354f,-89.8438f, +-54.6875f,44.5176f,-89.8438f, +-50.7813f,47.4827f,-89.8438f, +-46.875f,48.9307f,-89.8438f, +-42.9688f,48.82f,-89.8438f, +-39.0625f,48.8887f,-89.8438f, +-35.1563f,50.05f,-89.8438f, +-31.25f,50.9253f,-89.8438f, +-27.3438f,52.3859f,-89.8438f, +-23.4375f,52.2702f,-89.8438f, +-19.5313f,52.0708f,-89.8438f, +-15.625f,51.2832f,-89.8438f, +-11.7188f,50.0989f,-89.8438f, +-7.8125f,49.6111f,-89.8438f, +-3.90625f,48.7785f,-89.8438f, +0.0f,48.7183f,-89.8438f, +3.90625f,47.6596f,-89.8438f, +-250.0f,15.247f,-93.75f, +-246.094f,17.6018f,-93.75f, +-242.188f,19.2494f,-93.75f, +-238.281f,20.8362f,-93.75f, +-234.375f,20.4345f,-93.75f, +-230.469f,21.1572f,-93.75f, +-226.563f,21.3131f,-93.75f, +-222.656f,20.8797f,-93.75f, +-218.75f,20.5347f,-93.75f, +-214.844f,19.3559f,-93.75f, +-210.938f,18.2443f,-93.75f, +-207.031f,17.5994f,-93.75f, +-203.125f,18.0336f,-93.75f, +-199.219f,18.0561f,-93.75f, +-195.313f,17.673f,-93.75f, +-191.406f,18.7132f,-93.75f, +-187.5f,18.4272f,-93.75f, +-183.594f,18.078f,-93.75f, +-179.688f,16.7984f,-93.75f, +-175.781f,16.1827f,-93.75f, +-171.875f,16.5937f,-93.75f, +-167.969f,16.0698f,-93.75f, +-164.063f,14.9813f,-93.75f, +-160.156f,13.1718f,-93.75f, +-156.25f,12.1738f,-93.75f, +-152.344f,12.229f,-93.75f, +-148.438f,12.2803f,-93.75f, +-144.531f,12.526f,-93.75f, +-140.625f,11.9028f,-93.75f, +-136.719f,12.3491f,-93.75f, +-132.813f,11.7412f,-93.75f, +-128.906f,11.5455f,-93.75f, +-125.0f,11.6285f,-93.75f, +-121.094f,11.478f,-93.75f, +-117.188f,11.536f,-93.75f, +-113.281f,11.8722f,-93.75f, +-109.375f,12.61f,-93.75f, +-105.469f,12.6899f,-93.75f, +-101.563f,13.1659f,-93.75f, +-97.6563f,14.5994f,-93.75f, +-93.75f,16.6015f,-93.75f, +-89.8438f,19.9429f,-93.75f, +-85.9375f,22.8876f,-93.75f, +-82.0313f,26.3209f,-93.75f, +-78.125f,28.8526f,-93.75f, +-74.2188f,30.2969f,-93.75f, +-70.3125f,33.1597f,-93.75f, +-66.4063f,36.2648f,-93.75f, +-62.5f,39.1918f,-93.75f, +-58.5938f,41.4171f,-93.75f, +-54.6875f,43.4299f,-93.75f, +-50.7813f,45.5438f,-93.75f, +-46.875f,46.6281f,-93.75f, +-42.9688f,46.784f,-93.75f, +-39.0625f,47.3415f,-93.75f, +-35.1563f,48.5539f,-93.75f, +-31.25f,50.5714f,-93.75f, +-27.3438f,51.0532f,-93.75f, +-23.4375f,51.7685f,-93.75f, +-19.5313f,51.3638f,-93.75f, +-15.625f,49.6289f,-93.75f, +-11.7188f,50.0322f,-93.75f, +-7.8125f,48.6289f,-93.75f, +-3.90625f,46.7733f,-93.75f, +0.0f,45.5993f,-93.75f, +3.90625f,45.4182f,-93.75f, +-250.0f,18.5038f,-97.6563f, +-246.094f,20.1199f,-97.6563f, +-242.188f,22.7365f,-97.6563f, +-238.281f,24.311f,-97.6563f, +-234.375f,24.2572f,-97.6563f, +-230.469f,24.3322f,-97.6563f, +-226.563f,24.3501f,-97.6563f, +-222.656f,23.3494f,-97.6563f, +-218.75f,21.7677f,-97.6563f, +-214.844f,20.6573f,-97.6563f, +-210.938f,18.8509f,-97.6563f, +-207.031f,18.1355f,-97.6563f, +-203.125f,18.5785f,-97.6563f, +-199.219f,18.2049f,-97.6563f, +-195.313f,17.4136f,-97.6563f, +-191.406f,18.6105f,-97.6563f, +-187.5f,18.0859f,-97.6563f, +-183.594f,17.3286f,-97.6563f, +-179.688f,16.66f,-97.6563f, +-175.781f,15.1619f,-97.6563f, +-171.875f,14.271f,-97.6563f, +-167.969f,13.4801f,-97.6563f, +-164.063f,12.6373f,-97.6563f, +-160.156f,11.4464f,-97.6563f, +-156.25f,11.5423f,-97.6563f, +-152.344f,11.795f,-97.6563f, +-148.438f,10.9108f,-97.6563f, +-144.531f,11.2217f,-97.6563f, +-140.625f,11.0533f,-97.6563f, +-136.719f,11.5512f,-97.6563f, +-132.813f,11.6628f,-97.6563f, +-128.906f,10.9589f,-97.6563f, +-125.0f,10.3779f,-97.6563f, +-121.094f,9.96294f,-97.6563f, +-117.188f,10.6728f,-97.6563f, +-113.281f,11.2587f,-97.6563f, +-109.375f,11.2512f,-97.6563f, +-105.469f,12.1215f,-97.6563f, +-101.563f,12.0908f,-97.6563f, +-97.6563f,13.5835f,-97.6563f, +-93.75f,16.6536f,-97.6563f, +-89.8438f,19.7104f,-97.6563f, +-85.9375f,22.8325f,-97.6563f, +-82.0313f,26.7422f,-97.6563f, +-78.125f,29.4762f,-97.6563f, +-74.2188f,30.148f,-97.6563f, +-70.3125f,33.5961f,-97.6563f, +-66.4063f,36.1685f,-97.6563f, +-62.5f,37.3648f,-97.6563f, +-58.5938f,39.4445f,-97.6563f, +-54.6875f,40.3698f,-97.6563f, +-50.7813f,43.2595f,-97.6563f, +-46.875f,43.8006f,-97.6563f, +-42.9688f,44.8371f,-97.6563f, +-39.0625f,46.8993f,-97.6563f, +-35.1563f,48.8152f,-97.6563f, +-31.25f,50.2801f,-97.6563f, +-27.3438f,49.7242f,-97.6563f, +-23.4375f,49.8502f,-97.6563f, +-19.5313f,49.8568f,-97.6563f, +-15.625f,48.3267f,-97.6563f, +-11.7188f,47.8521f,-97.6563f, +-7.8125f,47.3364f,-97.6563f, +-3.90625f,46.156f,-97.6563f, +0.0f,44.8966f,-97.6563f, +3.90625f,44.9637f,-97.6563f, +-250.0f,21.0334f,-101.563f, +-246.094f,23.093f,-101.563f, +-242.188f,25.4189f,-101.563f, +-238.281f,27.31f,-101.563f, +-234.375f,26.8223f,-101.563f, +-230.469f,26.375f,-101.563f, +-226.563f,26.7718f,-101.563f, +-222.656f,25.3642f,-101.563f, +-218.75f,23.7619f,-101.563f, +-214.844f,21.4458f,-101.563f, +-210.938f,19.7809f,-101.563f, +-207.031f,19.054f,-101.563f, +-203.125f,19.6087f,-101.563f, +-199.219f,19.2503f,-101.563f, +-195.313f,18.0809f,-101.563f, +-191.406f,17.75f,-101.563f, +-187.5f,17.1292f,-101.563f, +-183.594f,16.2151f,-101.563f, +-179.688f,15.8928f,-101.563f, +-175.781f,14.4866f,-101.563f, +-171.875f,13.9039f,-101.563f, +-167.969f,12.278f,-101.563f, +-164.063f,11.5804f,-101.563f, +-160.156f,12.0152f,-101.563f, +-156.25f,11.7113f,-101.563f, +-152.344f,10.7496f,-101.563f, +-148.438f,9.67121f,-101.563f, +-144.531f,9.72628f,-101.563f, +-140.625f,9.99849f,-101.563f, +-136.719f,10.504f,-101.563f, +-132.813f,11.0917f,-101.563f, +-128.906f,10.4997f,-101.563f, +-125.0f,9.12306f,-101.563f, +-121.094f,8.34841f,-101.563f, +-117.188f,8.92074f,-101.563f, +-113.281f,9.44857f,-101.563f, +-109.375f,10.5456f,-101.563f, +-105.469f,10.7435f,-101.563f, +-101.563f,11.6413f,-101.563f, +-97.6563f,14.2233f,-101.563f, +-93.75f,17.0641f,-101.563f, +-89.8438f,20.5963f,-101.563f, +-85.9375f,22.9601f,-101.563f, +-82.0313f,26.0881f,-101.563f, +-78.125f,28.3451f,-101.563f, +-74.2188f,30.4473f,-101.563f, +-70.3125f,33.7644f,-101.563f, +-66.4063f,36.3074f,-101.563f, +-62.5f,38.0683f,-101.563f, +-58.5938f,39.1597f,-101.563f, +-54.6875f,40.3396f,-101.563f, +-50.7813f,41.4946f,-101.563f, +-46.875f,43.0029f,-101.563f, +-42.9688f,44.8434f,-101.563f, +-39.0625f,47.2094f,-101.563f, +-35.1563f,47.3449f,-101.563f, +-31.25f,49.1989f,-101.563f, +-27.3438f,48.845f,-101.563f, +-23.4375f,47.635f,-101.563f, +-19.5313f,47.9355f,-101.563f, +-15.625f,47.1439f,-101.563f, +-11.7188f,45.929f,-101.563f, +-7.8125f,46.9058f,-101.563f, +-3.90625f,46.1235f,-101.563f, +0.0f,45.2655f,-101.563f, +3.90625f,44.5311f,-101.563f, +-250.0f,24.0006f,-105.469f, +-246.094f,26.733f,-105.469f, +-242.188f,28.4305f,-105.469f, +-238.281f,29.0431f,-105.469f, +-234.375f,28.1582f,-105.469f, +-230.469f,28.0178f,-105.469f, +-226.563f,27.4417f,-105.469f, +-222.656f,27.0081f,-105.469f, +-218.75f,24.9646f,-105.469f, +-214.844f,22.8713f,-105.469f, +-210.938f,21.4507f,-105.469f, +-207.031f,21.2058f,-105.469f, +-203.125f,20.8114f,-105.469f, +-199.219f,20.7281f,-105.469f, +-195.313f,19.7358f,-105.469f, +-191.406f,18.4733f,-105.469f, +-187.5f,17.1875f,-105.469f, +-183.594f,15.4383f,-105.469f, +-179.688f,14.151f,-105.469f, +-175.781f,13.882f,-105.469f, +-171.875f,12.9008f,-105.469f, +-167.969f,11.246f,-105.469f, +-164.063f,11.1287f,-105.469f, +-160.156f,10.748f,-105.469f, +-156.25f,11.5003f,-105.469f, +-152.344f,10.3683f,-105.469f, +-148.438f,9.87346f,-105.469f, +-144.531f,9.6524f,-105.469f, +-140.625f,8.36957f,-105.469f, +-136.719f,9.12242f,-105.469f, +-132.813f,9.41585f,-105.469f, +-128.906f,8.97735f,-105.469f, +-125.0f,7.89593f,-105.469f, +-121.094f,7.20155f,-105.469f, +-117.188f,6.63681f,-105.469f, +-113.281f,8.27572f,-105.469f, +-109.375f,8.39126f,-105.469f, +-105.469f,9.69363f,-105.469f, +-101.563f,12.2269f,-105.469f, +-97.6563f,15.3785f,-105.469f, +-93.75f,18.1643f,-105.469f, +-89.8438f,20.8715f,-105.469f, +-85.9375f,23.5096f,-105.469f, +-82.0313f,25.2072f,-105.469f, +-78.125f,27.8536f,-105.469f, +-74.2188f,30.8436f,-105.469f, +-70.3125f,33.8966f,-105.469f, +-66.4063f,36.3107f,-105.469f, +-62.5f,37.9291f,-105.469f, +-58.5938f,39.7963f,-105.469f, +-54.6875f,40.5554f,-105.469f, +-50.7813f,42.1374f,-105.469f, +-46.875f,42.7622f,-105.469f, +-42.9688f,44.5703f,-105.469f, +-39.0625f,46.4665f,-105.469f, +-35.1563f,46.6101f,-105.469f, +-31.25f,47.1188f,-105.469f, +-27.3438f,48.052f,-105.469f, +-23.4375f,47.7845f,-105.469f, +-19.5313f,47.8159f,-105.469f, +-15.625f,46.7772f,-105.469f, +-11.7188f,46.0033f,-105.469f, +-7.8125f,47.2861f,-105.469f, +-3.90625f,46.9832f,-105.469f, +0.0f,45.6472f,-105.469f, +3.90625f,44.8466f,-105.469f, +-250.0f,27.0053f,-109.375f, +-246.094f,28.4873f,-109.375f, +-242.188f,29.8219f,-109.375f, +-238.281f,30.0561f,-109.375f, +-234.375f,29.2892f,-109.375f, +-230.469f,29.5933f,-109.375f, +-226.563f,28.8697f,-109.375f, +-222.656f,27.4881f,-109.375f, +-218.75f,25.7165f,-109.375f, +-214.844f,23.9985f,-109.375f, +-210.938f,23.3958f,-109.375f, +-207.031f,23.3567f,-109.375f, +-203.125f,23.3311f,-109.375f, +-199.219f,22.2114f,-109.375f, +-195.313f,21.0452f,-109.375f, +-191.406f,20.2153f,-109.375f, +-187.5f,18.8202f,-109.375f, +-183.594f,16.7998f,-109.375f, +-179.688f,15.8942f,-109.375f, +-175.781f,14.8638f,-109.375f, +-171.875f,13.1475f,-109.375f, +-167.969f,12.7375f,-109.375f, +-164.063f,10.7456f,-109.375f, +-160.156f,10.2908f,-109.375f, +-156.25f,9.65347f,-109.375f, +-152.344f,10.1273f,-109.375f, +-148.438f,9.91826f,-109.375f, +-144.531f,8.92229f,-109.375f, +-140.625f,8.34112f,-109.375f, +-136.719f,7.82043f,-109.375f, +-132.813f,7.17703f,-109.375f, +-128.906f,7.28288f,-109.375f, +-125.0f,6.94364f,-109.375f, +-121.094f,6.57742f,-109.375f, +-117.188f,5.68794f,-109.375f, +-113.281f,5.66654f,-109.375f, +-109.375f,6.9457f,-109.375f, +-105.469f,9.81036f,-109.375f, +-101.563f,12.6651f,-109.375f, +-97.6563f,15.2246f,-109.375f, +-93.75f,18.3914f,-109.375f, +-89.8438f,21.0454f,-109.375f, +-85.9375f,23.3579f,-109.375f, +-82.0313f,25.0292f,-109.375f, +-78.125f,28.9637f,-109.375f, +-74.2188f,31.9858f,-109.375f, +-70.3125f,34.5815f,-109.375f, +-66.4063f,37.1495f,-109.375f, +-62.5f,38.5371f,-109.375f, +-58.5938f,39.6993f,-109.375f, +-54.6875f,41.3314f,-109.375f, +-50.7813f,42.3279f,-109.375f, +-46.875f,43.399f,-109.375f, +-42.9688f,44.8971f,-109.375f, +-39.0625f,46.4515f,-109.375f, +-35.1563f,46.6684f,-109.375f, +-31.25f,47.2696f,-109.375f, +-27.3438f,48.2082f,-109.375f, +-23.4375f,47.2707f,-109.375f, +-19.5313f,47.952f,-109.375f, +-15.625f,47.4088f,-109.375f, +-11.7188f,47.3981f,-109.375f, +-7.8125f,48.0766f,-109.375f, +-3.90625f,47.4974f,-109.375f, +0.0f,46.1817f,-109.375f, +3.90625f,45.3987f,-109.375f, +-250.0f,28.5243f,-113.281f, +-246.094f,30.3032f,-113.281f, +-242.188f,31.2443f,-113.281f, +-238.281f,30.733f,-113.281f, +-234.375f,31.2433f,-113.281f, +-230.469f,31.5829f,-113.281f, +-226.563f,30.3008f,-113.281f, +-222.656f,28.2348f,-113.281f, +-218.75f,25.8116f,-113.281f, +-214.844f,25.3702f,-113.281f, +-210.938f,24.8435f,-113.281f, +-207.031f,25.7524f,-113.281f, +-203.125f,26.0021f,-113.281f, +-199.219f,24.9024f,-113.281f, +-195.313f,23.7348f,-113.281f, +-191.406f,21.9608f,-113.281f, +-187.5f,20.2108f,-113.281f, +-183.594f,18.963f,-113.281f, +-179.688f,17.7929f,-113.281f, +-175.781f,16.3625f,-113.281f, +-171.875f,14.6525f,-113.281f, +-167.969f,13.4453f,-113.281f, +-164.063f,11.5352f,-113.281f, +-160.156f,10.457f,-113.281f, +-156.25f,9.86849f,-113.281f, +-152.344f,9.76379f,-113.281f, +-148.438f,9.40799f,-113.281f, +-144.531f,8.38098f,-113.281f, +-140.625f,8.03078f,-113.281f, +-136.719f,7.4536f,-113.281f, +-132.813f,6.32375f,-113.281f, +-128.906f,5.90846f,-113.281f, +-125.0f,5.44126f,-113.281f, +-121.094f,5.53385f,-113.281f, +-117.188f,5.35081f,-113.281f, +-113.281f,6.14244f,-113.281f, +-109.375f,7.72509f,-113.281f, +-105.469f,9.98969f,-113.281f, +-101.563f,12.8924f,-113.281f, +-97.6563f,15.6605f,-113.281f, +-93.75f,18.4427f,-113.281f, +-89.8438f,20.4633f,-113.281f, +-85.9375f,22.3484f,-113.281f, +-82.0313f,25.7434f,-113.281f, +-78.125f,29.5649f,-113.281f, +-74.2188f,32.7377f,-113.281f, +-70.3125f,34.4529f,-113.281f, +-66.4063f,37.0096f,-113.281f, +-62.5f,38.2565f,-113.281f, +-58.5938f,39.8951f,-113.281f, +-54.6875f,41.291f,-113.281f, +-50.7813f,42.6018f,-113.281f, +-46.875f,43.3624f,-113.281f, +-42.9688f,44.3449f,-113.281f, +-39.0625f,45.4446f,-113.281f, +-35.1563f,46.0157f,-113.281f, +-31.25f,47.6632f,-113.281f, +-27.3438f,47.6934f,-113.281f, +-23.4375f,46.4824f,-113.281f, +-19.5313f,48.2708f,-113.281f, +-15.625f,48.5036f,-113.281f, +-11.7188f,47.6795f,-113.281f, +-7.8125f,48.4742f,-113.281f, +-3.90625f,48.509f,-113.281f, +0.0f,47.4037f,-113.281f, +3.90625f,47.4869f,-113.281f, +-250.0f,30.7007f,-117.188f, +-246.094f,31.6625f,-117.188f, +-242.188f,31.8246f,-117.188f, +-238.281f,32.4951f,-117.188f, +-234.375f,33.3552f,-117.188f, +-230.469f,32.7471f,-117.188f, +-226.563f,30.8092f,-117.188f, +-222.656f,28.3135f,-117.188f, +-218.75f,27.0912f,-117.188f, +-214.844f,27.0184f,-117.188f, +-210.938f,27.5702f,-117.188f, +-207.031f,27.9311f,-117.188f, +-203.125f,28.0909f,-117.188f, +-199.219f,26.6916f,-117.188f, +-195.313f,25.6983f,-117.188f, +-191.406f,24.0617f,-117.188f, +-187.5f,22.1476f,-117.188f, +-183.594f,20.964f,-117.188f, +-179.688f,19.1417f,-117.188f, +-175.781f,18.0941f,-117.188f, +-171.875f,16.3483f,-117.188f, +-167.969f,13.8969f,-117.188f, +-164.063f,12.2065f,-117.188f, +-160.156f,10.4346f,-117.188f, +-156.25f,9.28283f,-117.188f, +-152.344f,8.20933f,-117.188f, +-148.438f,7.69157f,-117.188f, +-144.531f,7.05251f,-117.188f, +-140.625f,6.38685f,-117.188f, +-136.719f,5.88862f,-117.188f, +-132.813f,4.48007f,-117.188f, +-128.906f,4.03049f,-117.188f, +-125.0f,4.96603f,-117.188f, +-121.094f,6.08105f,-117.188f, +-117.188f,6.76315f,-117.188f, +-113.281f,7.41087f,-117.188f, +-109.375f,7.5353f,-117.188f, +-105.469f,9.88018f,-117.188f, +-101.563f,11.8887f,-117.188f, +-97.6563f,14.4702f,-117.188f, +-93.75f,17.2187f,-117.188f, +-89.8438f,20.2241f,-117.188f, +-85.9375f,22.2766f,-117.188f, +-82.0313f,25.968f,-117.188f, +-78.125f,29.2923f,-117.188f, +-74.2188f,31.9825f,-117.188f, +-70.3125f,34.0756f,-117.188f, +-66.4063f,35.9202f,-117.188f, +-62.5f,37.9131f,-117.188f, +-58.5938f,39.2288f,-117.188f, +-54.6875f,40.591f,-117.188f, +-50.7813f,42.5191f,-117.188f, +-46.875f,42.7237f,-117.188f, +-42.9688f,43.8388f,-117.188f, +-39.0625f,45.2151f,-117.188f, +-35.1563f,45.096f,-117.188f, +-31.25f,45.9904f,-117.188f, +-27.3438f,45.2594f,-117.188f, +-23.4375f,45.7333f,-117.188f, +-19.5313f,47.4248f,-117.188f, +-15.625f,48.122f,-117.188f, +-11.7188f,48.0312f,-117.188f, +-7.8125f,49.0431f,-117.188f, +-3.90625f,49.2804f,-117.188f, +0.0f,48.803f,-117.188f, +3.90625f,48.3887f,-117.188f, +-250.0f,31.7497f,-121.094f, +-246.094f,31.3973f,-121.094f, +-242.188f,32.0742f,-121.094f, +-238.281f,33.1521f,-121.094f, +-234.375f,33.6068f,-121.094f, +-230.469f,31.9815f,-121.094f, +-226.563f,30.2957f,-121.094f, +-222.656f,28.5699f,-121.094f, +-218.75f,28.3353f,-121.094f, +-214.844f,28.8422f,-121.094f, +-210.938f,29.4292f,-121.094f, +-207.031f,29.2833f,-121.094f, +-203.125f,28.4123f,-121.094f, +-199.219f,27.4455f,-121.094f, +-195.313f,26.9053f,-121.094f, +-191.406f,24.8164f,-121.094f, +-187.5f,22.4409f,-121.094f, +-183.594f,21.5447f,-121.094f, +-179.688f,20.6668f,-121.094f, +-175.781f,18.9757f,-121.094f, +-171.875f,16.8092f,-121.094f, +-167.969f,14.4997f,-121.094f, +-164.063f,13.0122f,-121.094f, +-160.156f,11.2904f,-121.094f, +-156.25f,9.63825f,-121.094f, +-152.344f,8.62771f,-121.094f, +-148.438f,7.36842f,-121.094f, +-144.531f,6.44275f,-121.094f, +-140.625f,5.50805f,-121.094f, +-136.719f,6.00349f,-121.094f, +-132.813f,4.67796f,-121.094f, +-128.906f,3.93081f,-121.094f, +-125.0f,5.39329f,-121.094f, +-121.094f,6.95361f,-121.094f, +-117.188f,8.00676f,-121.094f, +-113.281f,7.76936f,-121.094f, +-109.375f,8.598f,-121.094f, +-105.469f,9.71941f,-121.094f, +-101.563f,11.4789f,-121.094f, +-97.6563f,13.572f,-121.094f, +-93.75f,16.0296f,-121.094f, +-89.8438f,18.5079f,-121.094f, +-85.9375f,22.5232f,-121.094f, +-82.0313f,25.7298f,-121.094f, +-78.125f,29.0421f,-121.094f, +-74.2188f,31.8936f,-121.094f, +-70.3125f,33.6857f,-121.094f, +-66.4063f,35.8951f,-121.094f, +-62.5f,37.4244f,-121.094f, +-58.5938f,39.1337f,-121.094f, +-54.6875f,40.6842f,-121.094f, +-50.7813f,41.8829f,-121.094f, +-46.875f,42.9851f,-121.094f, +-42.9688f,42.3613f,-121.094f, +-39.0625f,44.0627f,-121.094f, +-35.1563f,43.3741f,-121.094f, +-31.25f,43.2393f,-121.094f, +-27.3438f,44.1982f,-121.094f, +-23.4375f,45.2747f,-121.094f, +-19.5313f,46.6461f,-121.094f, +-15.625f,47.338f,-121.094f, +-11.7188f,48.1318f,-121.094f, +-7.8125f,49.3601f,-121.094f, +-3.90625f,49.6752f,-121.094f, +0.0f,49.3611f,-121.094f, +3.90625f,49.6769f,-121.094f, +-250.0f,31.4025f,-125.0f, +-246.094f,31.4165f,-125.0f, +-242.188f,32.314f,-125.0f, +-238.281f,32.9822f,-125.0f, +-234.375f,32.6962f,-125.0f, +-230.469f,31.3632f,-125.0f, +-226.563f,29.4391f,-125.0f, +-222.656f,29.519f,-125.0f, +-218.75f,29.4481f,-125.0f, +-214.844f,29.8481f,-125.0f, +-210.938f,30.408f,-125.0f, +-207.031f,30.291f,-125.0f, +-203.125f,28.7473f,-125.0f, +-199.219f,28.1816f,-125.0f, +-195.313f,27.2839f,-125.0f, +-191.406f,25.7018f,-125.0f, +-187.5f,23.2882f,-125.0f, +-183.594f,22.1614f,-125.0f, +-179.688f,20.658f,-125.0f, +-175.781f,18.8433f,-125.0f, +-171.875f,16.364f,-125.0f, +-167.969f,14.7298f,-125.0f, +-164.063f,12.9859f,-125.0f, +-160.156f,11.3306f,-125.0f, +-156.25f,10.1916f,-125.0f, +-152.344f,8.3967f,-125.0f, +-148.438f,6.23292f,-125.0f, +-144.531f,5.48985f,-125.0f, +-140.625f,5.18276f,-125.0f, +-136.719f,5.56059f,-125.0f, +-132.813f,5.75157f,-125.0f, +-128.906f,5.32154f,-125.0f, +-125.0f,6.15672f,-125.0f, +-121.094f,7.53373f,-125.0f, +-117.188f,8.38676f,-125.0f, +-113.281f,8.64274f,-125.0f, +-109.375f,8.49941f,-125.0f, +-105.469f,9.24481f,-125.0f, +-101.563f,11.5178f,-125.0f, +-97.6563f,13.4113f,-125.0f, +-93.75f,15.4997f,-125.0f, +-89.8438f,17.3502f,-125.0f, +-85.9375f,20.8168f,-125.0f, +-82.0313f,24.9405f,-125.0f, +-78.125f,27.8681f,-125.0f, +-74.2188f,30.1495f,-125.0f, +-70.3125f,32.4402f,-125.0f, +-66.4063f,34.2537f,-125.0f, +-62.5f,36.5623f,-125.0f, +-58.5938f,38.9027f,-125.0f, +-54.6875f,40.1192f,-125.0f, +-50.7813f,41.9393f,-125.0f, +-46.875f,41.8765f,-125.0f, +-42.9688f,41.6371f,-125.0f, +-39.0625f,41.6432f,-125.0f, +-35.1563f,41.2852f,-125.0f, +-31.25f,41.5629f,-125.0f, +-27.3438f,42.2956f,-125.0f, +-23.4375f,43.9719f,-125.0f, +-19.5313f,46.2232f,-125.0f, +-15.625f,47.3104f,-125.0f, +-11.7188f,47.5943f,-125.0f, +-7.8125f,49.1192f,-125.0f, +-3.90625f,49.6341f,-125.0f, +0.0f,50.3481f,-125.0f, +3.90625f,50.3021f,-125.0f, +}; + +btScalar Landscape05Nml[] = { +-0.379368f,0.918093f,-0.114827f, +-0.372144f,0.893697f,-0.250627f, +-0.36483f,0.925769f,-0.0992527f, +-0.303739f,0.924201f,-0.231506f, +-0.333317f,0.942796f,0.0059764f, +-0.301915f,0.940094f,-0.158338f, +-0.363026f,0.931698f,0.0122604f, +-0.316966f,0.945703f,-0.0719588f, +-0.334188f,0.941548f,0.0424963f, +-0.326039f,0.944563f,-0.0387196f, +-0.382515f,0.923758f,0.0188291f, +-0.388659f,0.920843f,-0.0315106f, +-0.393577f,0.919186f,-0.013971f, +-0.384968f,0.922772f,-0.0170923f, +-0.36589f,0.930393f,-0.0222354f, +-0.357745f,0.933231f,0.0331438f, +-0.482959f,0.873942f,-0.0545559f, +-0.473203f,0.879732f,0.0463645f, +-0.550088f,0.834035f,-0.0423024f, +-0.534007f,0.844766f,0.0347315f, +-0.469703f,0.882824f,0.000376011f, +-0.490919f,0.868868f,0.0637728f, +-0.552202f,0.826862f,-0.106641f, +-0.558464f,0.829519f,0.00395409f, +-0.437742f,0.897949f,-0.0454837f, +-0.437659f,0.898576f,0.0318733f, +-0.370538f,0.927929f,-0.0406078f, +-0.403245f,0.912789f,-0.064878f, +-0.385648f,0.921933f,-0.0362754f, +-0.356223f,0.934382f,-0.00604283f, +-0.30076f,0.953691f,-0.00400305f, +-0.305622f,0.951852f,0.0239231f, +-0.284526f,0.956527f,-0.0640436f, +-0.380428f,0.91278f,-0.148684f, +-0.270228f,0.949845f,-0.157392f, +-0.258662f,0.947281f,-0.189085f, +-0.182234f,0.978377f,-0.0978241f, +-0.170558f,0.969333f,-0.176927f, +-0.205282f,0.978149f,-0.0329196f, +-0.190223f,0.949267f,-0.250415f, +-0.274135f,0.959498f,0.0649128f, +-0.310884f,0.912161f,-0.267046f, +-0.496348f,0.868119f,0.00275513f, +-0.43081f,0.896388f,-0.104358f, +-0.405094f,0.913485f,0.0380057f, +-0.324068f,0.9389f,0.115955f, +-0.25697f,0.965908f,0.0314342f, +-0.271227f,0.948776f,0.162051f, +-0.254963f,0.963309f,-0.0838379f, +-0.344475f,0.938191f,-0.03368f, +-0.111765f,0.981495f,-0.15549f, +-0.167507f,0.982459f,-0.0819529f, +-0.0010222f,0.966945f,-0.254984f, +-0.0444844f,0.98477f,-0.168075f, +0.186055f,0.950323f,-0.249537f, +0.1896f,0.965697f,-0.177427f, +0.271688f,0.939248f,-0.209761f, +0.279232f,0.936599f,-0.211687f, +0.322549f,0.939459f,-0.115666f, +0.354799f,0.922502f,-0.152013f, +0.252542f,0.965579f,-0.0622893f, +0.223889f,0.935481f,-0.273404f, +0.054661f,0.998373f,-0.0162575f, +0.0861707f,0.972348f,-0.217056f, +0.0124775f,0.999913f,-0.00421609f, +0.0330599f,0.976575f,-0.212621f, +0.0918366f,0.994675f,0.046771f, +0.166973f,0.980978f,-0.0990035f, +0.0387017f,0.993028f,0.111346f, +0.125297f,0.990619f,0.054541f, +0.0541059f,0.984899f,0.164456f, +0.149711f,0.968151f,0.200673f, +0.168008f,0.956272f,0.239411f, +0.195367f,0.93223f,0.304595f, +0.147118f,0.96491f,0.217497f, +0.125818f,0.960755f,0.247225f, +0.270517f,0.934497f,0.23138f, +0.29818f,0.904256f,0.305629f, +0.363841f,0.900609f,0.237745f, +0.316827f,0.923009f,0.218347f, +0.413166f,0.893779f,0.17451f, +0.334815f,0.940911f,0.0508378f, +0.474676f,0.869519f,0.136452f, +0.456974f,0.889396f,0.0122055f, +0.272216f,0.960219f,0.0622813f, +0.228855f,0.962963f,-0.142573f, +0.0810211f,0.995842f,0.0416494f, +0.189938f,0.980101f,0.0576713f, +-0.0449078f,0.994712f,0.0923629f, +-0.00155869f,0.98749f,0.157671f, +-0.0840704f,0.991095f,0.103263f, +-0.0968834f,0.985327f,0.140515f, +0.0427121f,0.991995f,0.118832f, +-0.0240058f,0.999711f,0.000939081f, +-0.124569f,0.986858f,0.10293f, +-0.167243f,0.982306f,-0.0842863f, +-0.286295f,0.953093f,0.0982316f, +-0.243406f,0.969914f,-0.00444377f, +-0.280466f,0.950626f,0.132851f, +-0.21091f,0.972115f,0.102516f, +-0.230061f,0.951476f,0.204368f, +-0.123921f,0.950092f,0.286301f, +-0.126792f,0.952499f,0.276893f, +-0.0764868f,0.927481f,0.365962f, +-0.0452811f,0.949055f,0.31184f, +-0.138647f,0.960819f,0.240008f, +-0.25036f,0.943892f,0.215377f, +-0.314158f,0.941939f,0.118561f, +-0.458647f,0.872527f,0.168342f, +-0.427047f,0.882261f,0.198106f, +-0.485467f,0.864542f,0.129958f, +-0.523912f,0.844181f,0.113461f, +-0.532843f,0.842328f,0.081008f, +-0.518838f,0.84918f,0.0984888f, +-0.439028f,0.883929f,0.16101f, +-0.409166f,0.878784f,0.245606f, +-0.386543f,0.918859f,0.0792661f, +-0.447749f,0.88853f,0.100178f, +-0.431191f,0.90206f,0.0190184f, +-0.467639f,0.880276f,0.0801789f, +-0.518882f,0.844495f,-0.132623f, +-0.570181f,0.817923f,-0.076789f, +-0.420368f,0.883342f,-0.207357f, +-0.464447f,0.877342f,-0.120667f, +-0.386958f,0.877414f,-0.283564f, +-0.442101f,0.874511f,-0.199442f, +-0.380012f,0.859996f,-0.340584f, +-0.442865f,0.822467f,-0.356959f, +-0.24551f,0.880879f,-0.404695f, +-0.263304f,0.844058f,-0.467159f, +-0.116714f,0.897206f,-0.425909f, +-0.129252f,0.860962f,-0.491974f, +-0.352237f,0.922053f,0.160457f, +-0.402553f,0.906198f,0.129446f, +-0.377478f,0.915341f,0.140219f, +-0.336315f,0.935519f,0.10815f, +-0.335675f,0.937548f,0.0912505f, +-0.330532f,0.939201f,0.0930086f, +-0.361761f,0.931606f,0.035208f, +-0.318172f,0.947538f,0.0306247f, +-0.418525f,0.907834f,-0.0259689f, +-0.56364f,0.818048f,-0.114485f, +-0.461029f,0.882661f,-0.0914388f, +-0.472492f,0.87835f,-0.0724725f, +-0.523319f,0.846244f,-0.100037f, +-0.381187f,0.924062f,-0.0283799f, +-0.407557f,0.911105f,-0.0615298f, +-0.340677f,0.939702f,0.0299913f, +-0.237849f,0.962659f,0.129291f, +-0.233755f,0.968303f,0.0880164f, +-0.248597f,0.967837f,0.0386268f, +-0.357032f,0.933656f,0.0285478f, +-0.359392f,0.919937f,0.156695f, +-0.375075f,0.918577f,0.12464f, +-0.326685f,0.944457f,-0.0357437f, +-0.172605f,0.980131f,-0.0977257f, +-0.156177f,0.9732f,-0.168789f, +-0.0732432f,0.97238f,-0.221612f, +0.0871915f,0.980367f,-0.176858f, +0.1118f,0.973873f,-0.197667f, +0.197176f,0.978426f,-0.0616824f, +0.202039f,0.979229f,-0.0170475f, +0.172249f,0.982761f,0.0671591f, +0.0103709f,0.995351f,0.095751f, +0.00657151f,0.996617f,0.0819183f, +0.0314022f,0.995508f,0.0893156f, +0.0387801f,0.982532f,0.182011f, +0.0412148f,0.983254f,0.177521f, +0.166642f,0.964252f,0.20603f, +0.177047f,0.971307f,0.1588f, +0.255603f,0.956785f,0.138671f, +0.338465f,0.927074f,0.161166f, +0.418264f,0.886168f,0.199401f, +0.454161f,0.868211f,0.199869f, +0.355471f,0.903694f,0.2387f, +0.136408f,0.975339f,0.173515f, +-0.0223692f,0.983821f,0.177753f, +-0.0947578f,0.983833f,0.151964f, +-0.0484831f,0.985895f,0.16019f, +-0.137652f,0.965784f,0.219802f, +-0.273035f,0.949633f,0.153782f, +-0.284296f,0.949219f,0.134753f, +-0.233616f,0.961781f,0.142834f, +-0.158293f,0.979011f,0.128376f, +-0.142079f,0.977628f,0.155106f, +-0.179667f,0.940095f,0.289726f, +-0.385363f,0.907468f,0.167324f, +-0.462662f,0.886082f,0.0283396f, +-0.500483f,0.865637f,-0.0137244f, +-0.459387f,0.885328f,-0.0718224f, +-0.318003f,0.947491f,-0.0336944f, +-0.336522f,0.937427f,-0.0893505f, +-0.421711f,0.882359f,-0.208814f, +-0.386976f,0.894588f,-0.223522f, +-0.348564f,0.925302f,-0.149395f, +-0.389936f,0.911457f,-0.131135f, +-0.262418f,0.94867f,-0.17653f, +-0.142966f,0.967048f,-0.210661f, +-0.341303f,0.927435f,0.152892f, +-0.342877f,0.929169f,0.138133f, +-0.327958f,0.941991f,0.0713955f, +-0.312837f,0.949244f,0.0326933f, +-0.32505f,0.944749f,0.0423311f, +-0.35038f,0.936272f,0.0250833f, +-0.334661f,0.939274f,0.0759313f, +-0.336592f,0.939816f,0.0587454f, +-0.383743f,0.919849f,0.0813597f, +-0.479391f,0.876726f,0.0391772f, +-0.521184f,0.850742f,-0.0678625f, +-0.496942f,0.867777f,0.00353465f, +-0.521763f,0.848113f,-0.0920201f, +-0.373289f,0.923494f,-0.0883984f, +-0.40896f,0.910065f,-0.067337f, +-0.458758f,0.888254f,0.0233657f, +-0.335137f,0.935384f,0.112868f, +-0.174079f,0.969266f,0.173839f, +-0.174994f,0.976179f,0.128265f, +-0.244694f,0.967717f,0.0603988f, +-0.409093f,0.90433f,-0.121779f, +-0.290803f,0.954139f,-0.0710763f, +-0.266076f,0.946406f,-0.183082f, +-0.19492f,0.966664f,-0.166031f, +-0.107014f,0.989078f,-0.101359f, +-0.0950037f,0.987234f,-0.127838f, +-0.0081899f,0.996807f,-0.0794301f, +0.0655685f,0.997841f,0.0038314f, +0.121704f,0.991617f,0.0433953f, +0.204125f,0.978885f,0.010797f, +0.169834f,0.985465f,0.00398161f, +0.0639966f,0.99795f,0.000581677f, +0.0389498f,0.997722f,-0.0550831f, +-0.00230315f,0.998522f,-0.0543072f, +-0.0428959f,0.99833f,-0.0386874f, +8.35518e-005f,0.999804f,-0.0198162f, +0.12638f,0.991004f,0.0440296f, +0.219728f,0.969155f,0.111616f, +0.270292f,0.956521f,0.109589f, +0.325159f,0.942616f,0.0758083f, +0.394886f,0.91647f,0.0644013f, +0.455483f,0.885289f,0.0937962f, +0.346134f,0.927862f,0.13879f, +0.142703f,0.967217f,0.210065f, +-0.0417806f,0.973195f,0.226154f, +-0.0873343f,0.983405f,0.159022f, +-0.027932f,0.984118f,0.175304f, +-0.101812f,0.985941f,0.132496f, +-0.174734f,0.983884f,0.037939f, +-0.279511f,0.957793f,-0.0671252f, +-0.277834f,0.959638f,-0.04362f, +-0.153076f,0.986374f,0.0602763f, +-0.221825f,0.968529f,0.112897f, +-0.256381f,0.940693f,0.222182f, +-0.236646f,0.958592f,0.158432f, +-0.345917f,0.937587f,-0.0356594f, +-0.417749f,0.894423f,-0.159665f, +-0.456832f,0.853011f,-0.252341f, +-0.379407f,0.905637f,-0.189399f, +-0.328991f,0.940983f,-0.0794707f, +-0.363362f,0.931271f,0.0264943f, +-0.48653f,0.873119f,0.0308429f, +-0.459174f,0.871133f,0.174033f, +-0.359639f,0.91236f,0.1956f, +-0.2127f,0.972657f,0.0932592f, +-0.0697188f,0.989689f,0.12512f, +-0.251887f,0.965064f,0.0721469f, +-0.317161f,0.947815f,-0.0324826f, +-0.311043f,0.947329f,-0.076288f, +-0.343705f,0.938452f,-0.0342691f, +-0.318958f,0.946045f,0.0571365f, +-0.341405f,0.939767f,0.0167816f, +-0.371963f,0.928183f,-0.0109617f, +-0.353511f,0.935132f,0.0236193f, +-0.398287f,0.910412f,0.111881f, +-0.43162f,0.897024f,0.0951448f, +-0.485116f,0.874338f,-0.0140269f, +-0.473699f,0.879939f,-0.03627f, +-0.417805f,0.900966f,-0.117046f, +-0.424936f,0.889519f,-0.167884f, +-0.467852f,0.878936f,-0.0926624f, +-0.493825f,0.865439f,-0.0845782f, +-0.351989f,0.932075f,-0.0856709f, +-0.214961f,0.974111f,-0.0700008f, +-0.163285f,0.986387f,-0.0194449f, +-0.162841f,0.986548f,-0.0143588f, +-0.285987f,0.956112f,-0.0637334f, +-0.292441f,0.94548f,-0.143341f, +-0.215932f,0.955314f,-0.201864f, +-0.253415f,0.950159f,-0.181603f, +-0.183417f,0.974504f,-0.129231f, +-0.101906f,0.993299f,-0.0545242f, +-0.042238f,0.99904f,-0.0116303f, +0.0329811f,0.99907f,-0.0277622f, +0.132201f,0.990073f,-0.0477429f, +0.267032f,0.963432f,-0.0221792f, +0.1278f,0.990718f,-0.0463084f, +0.0964891f,0.995299f,-0.00830296f, +0.0476853f,0.991211f,-0.123396f, +-0.00640997f,0.993203f,-0.116222f, +-0.0126443f,0.992773f,-0.119338f, +-0.00631822f,0.992917f,-0.118638f, +0.0563885f,0.995667f,-0.073943f, +0.12664f,0.991687f,-0.022778f, +0.273262f,0.961705f,0.021246f, +0.388375f,0.920615f,-0.0403992f, +0.37695f,0.920931f,-0.0989673f, +0.400211f,0.914808f,0.0543818f, +0.279689f,0.947142f,0.15715f, +0.0626591f,0.985325f,0.158772f, +0.0197159f,0.983213f,0.181391f, +0.0112307f,0.995546f,0.0936022f, +-0.0611233f,0.998037f,0.013638f, +-0.0515369f,0.996025f,0.0726543f, +-0.060221f,0.998076f,0.0147593f, +-0.21333f,0.972986f,-0.0882534f, +-0.330599f,0.94012f,-0.0829391f, +-0.311254f,0.950309f,-0.00575056f, +-0.324983f,0.931955f,0.160768f, +-0.245964f,0.942146f,0.227736f, +-0.125195f,0.981121f,0.147403f, +-0.193437f,0.975595f,0.103908f, +-0.319958f,0.946961f,0.029845f, +-0.440983f,0.895915f,-0.0535662f, +-0.477838f,0.878381f,-0.0108058f, +-0.480471f,0.872693f,0.0869201f, +-0.478968f,0.83494f,0.271043f, +-0.490257f,0.796981f,0.352803f, +-0.434277f,0.834185f,0.339909f, +-0.265882f,0.929328f,0.256236f, +-0.142385f,0.958793f,0.245852f, +-0.182126f,0.963412f,0.196642f, +-0.0681643f,0.992157f,0.104781f, +-0.176883f,0.983918f,0.024857f, +-0.305513f,0.952069f,-0.0150524f, +-0.401485f,0.91552f,0.0251517f, +-0.372509f,0.927256f,0.0378572f, +-0.265017f,0.964159f,0.0127972f, +-0.342134f,0.935688f,-0.0862078f, +-0.427338f,0.901948f,-0.062226f, +-0.447549f,0.894216f,0.00877894f, +-0.382185f,0.923573f,-0.0307708f, +-0.386509f,0.921774f,-0.0307138f, +-0.457766f,0.884255f,-0.0924303f, +-0.384262f,0.916404f,-0.11201f, +-0.431623f,0.886784f,-0.165273f, +-0.460575f,0.869789f,-0.177024f, +-0.471547f,0.850265f,-0.233865f, +-0.351048f,0.911491f,-0.214361f, +-0.263539f,0.9431f,-0.202755f, +-0.173283f,0.972074f,-0.158258f, +-0.19847f,0.960809f,-0.193536f, +-0.275034f,0.951707f,-0.136422f, +-0.217032f,0.958372f,-0.185526f, +-0.201987f,0.95666f,-0.209771f, +-0.299318f,0.94727f,-0.114406f, +-0.187056f,0.978613f,-0.0855959f, +-0.155621f,0.97153f,-0.178637f, +-0.0810385f,0.981009f,-0.176221f, +0.0905036f,0.986207f,-0.138581f, +0.115825f,0.982705f,-0.14448f, +0.19636f,0.97731f,-0.0794224f, +0.143519f,0.988245f,-0.0526749f, +0.109744f,0.989619f,-0.0927937f, +0.197571f,0.972036f,-0.12693f, +0.00332495f,0.962309f,-0.271939f, +-0.0356976f,0.959351f,-0.279948f, +-0.0721767f,0.96735f,-0.242948f, +-0.00843005f,0.989549f,-0.143952f, +0.152572f,0.983317f,-0.0990425f, +0.281378f,0.943362f,-0.175768f, +0.428891f,0.891683f,-0.144753f, +0.290445f,0.954517f,-0.0673633f, +0.176401f,0.973557f,0.145155f, +0.232983f,0.924473f,0.301776f, +0.181127f,0.950255f,0.253393f, +-0.00165339f,0.991402f,0.130837f, +0.0981935f,0.976268f,0.193027f, +0.000170743f,0.996657f,0.0816968f, +-0.0970384f,0.995225f,-0.0105345f, +-0.00895717f,0.999951f,-0.00426387f, +-0.170944f,0.985202f,-0.0124686f, +-0.362907f,0.93182f,-0.00317037f, +-0.388121f,0.921046f,0.0322033f, +-0.407598f,0.90852f,0.0919578f, +-0.247403f,0.962759f,0.109032f, +-0.0829823f,0.986114f,0.143848f, +-0.240859f,0.956011f,0.167424f, +-0.312142f,0.912012f,0.266086f, +-0.398269f,0.862926f,0.311032f, +-0.511957f,0.795091f,0.325161f, +-0.506846f,0.755093f,0.415864f, +-0.506747f,0.718735f,0.476054f, +-0.45002f,0.736589f,0.504895f, +-0.287855f,0.833759f,0.471153f, +-0.237765f,0.90713f,0.34725f, +-0.146865f,0.915961f,0.373425f, +-0.0859218f,0.935714f,0.342136f, +-0.054455f,0.996952f,-0.0558782f, +-0.211499f,0.976662f,-0.0374149f, +-0.331452f,0.940975f,0.0686022f, +-0.397421f,0.917381f,0.0216451f, +-0.316207f,0.946964f,-0.0572054f, +-0.202804f,0.975284f,-0.0877067f, +-0.28846f,0.951091f,-0.110532f, +-0.440756f,0.882415f,-0.164552f, +-0.391159f,0.897816f,-0.202288f, +-0.37945f,0.884355f,-0.27191f, +-0.436492f,0.880924f,-0.182888f, +-0.458204f,0.880643f,-0.12049f, +-0.365575f,0.927969f,-0.0723085f, +-0.344164f,0.93545f,-0.0805227f, +-0.392565f,0.898448f,-0.196683f, +-0.458844f,0.839155f,-0.292028f, +-0.406986f,0.873305f,-0.267769f, +-0.264536f,0.933458f,-0.242234f, +-0.197907f,0.946975f,-0.253123f, +-0.162416f,0.964761f,-0.207018f, +-0.261287f,0.932524f,-0.249254f, +-0.237723f,0.937266f,-0.25499f, +-0.255938f,0.959549f,-0.117312f, +-0.378394f,0.921703f,-0.0853291f, +-0.154569f,0.983106f,-0.098032f, +0.020864f,0.98441f,-0.174648f, +-0.0493076f,0.945704f,-0.321268f, +0.00354211f,0.950539f,-0.310586f, +0.0705741f,0.962405f,-0.262289f, +0.155003f,0.952815f,-0.260992f, +0.190084f,0.945182f,-0.265518f, +0.109466f,0.94166f,-0.318268f, +0.219465f,0.948713f,-0.227551f, +0.131592f,0.95776f,-0.255694f, +-0.023132f,0.936016f,-0.351196f, +-0.102398f,0.923738f,-0.369083f, +-0.11778f,0.928743f,-0.351518f, +0.14699f,0.959781f,-0.239196f, +0.329451f,0.917295f,-0.223678f, +0.290403f,0.942778f,-0.163815f, +0.10086f,0.993272f,0.056896f, +0.00690717f,0.980954f,0.194116f, +0.198478f,0.949829f,0.241726f, +0.257584f,0.935998f,0.239913f, +0.0870031f,0.976807f,0.195647f, +0.0578083f,0.994066f,0.0921449f, +0.121554f,0.989161f,0.0823711f, +0.0335983f,0.999242f,0.0196737f, +-0.0544848f,0.997579f,-0.0432265f, +-0.170331f,0.98419f,0.0485619f, +-0.366378f,0.930108f,-0.0258115f, +-0.430564f,0.901925f,-0.0338598f, +-0.412156f,0.909498f,0.0542308f, +-0.303685f,0.949097f,0.0836093f, +-0.198153f,0.949404f,0.243656f, +-0.267445f,0.871756f,0.410506f, +-0.393769f,0.805932f,0.442062f, +-0.427473f,0.750775f,0.50359f, +-0.522691f,0.707231f,0.476044f, +-0.550081f,0.670741f,0.497511f, +-0.518356f,0.695815f,0.49714f, +-0.372017f,0.764162f,0.526934f, +-0.210863f,0.841692f,0.497082f, +-0.116051f,0.87101f,0.477362f, +-0.106872f,0.906726f,0.407954f, +0.0295506f,0.897687f,0.439643f, +-0.11391f,0.993475f,0.00559176f, +-0.238885f,0.970513f,0.0322297f, +-0.352278f,0.935893f,0.00201985f, +-0.29155f,0.955165f,-0.0515582f, +-0.283012f,0.950207f,-0.130422f, +-0.233718f,0.966509f,-0.105997f, +-0.293314f,0.953293f,-0.0721f, +-0.344057f,0.937935f,-0.0436188f, +-0.359338f,0.921856f,-0.145114f, +-0.361988f,0.90939f,-0.204876f, +-0.478777f,0.840974f,-0.252063f, +-0.501126f,0.832032f,-0.237897f, +-0.42396f,0.887247f,-0.1818f, +-0.340692f,0.929815f,-0.13919f, +-0.261328f,0.946412f,-0.189766f, +-0.383135f,0.863856f,-0.327048f, +-0.4248f,0.838392f,-0.341533f, +-0.258907f,0.912327f,-0.317216f, +-0.273875f,0.922352f,-0.272505f, +-0.216284f,0.973372f,-0.0759435f, +-0.186061f,0.980681f,-0.0603919f, +-0.327344f,0.93227f,-0.15401f, +-0.354135f,0.933013f,-0.0638423f, +-0.30838f,0.94174f,-0.13427f, +-0.0952482f,0.963393f,-0.250602f, +0.0864929f,0.957116f,-0.276491f, +0.0265645f,0.947809f,-0.31773f, +-0.00743162f,0.929747f,-0.368124f, +0.0794584f,0.926075f,-0.368877f, +0.177698f,0.921503f,-0.345334f, +0.210118f,0.923104f,-0.322071f, +0.0972314f,0.929984f,-0.354507f, +0.0931107f,0.932401f,-0.349226f, +0.163846f,0.947557f,-0.274392f, +0.04099f,0.947023f,-0.318539f, +-0.0637185f,0.942657f,-0.327625f, +-0.131539f,0.923216f,-0.361068f, +0.0323928f,0.932437f,-0.359877f, +0.242794f,0.937436f,-0.249528f, +0.154647f,0.984538f,-0.0822692f, +-0.0290139f,0.999421f,0.0177744f, +-0.0330797f,0.998482f,0.0440283f, +0.157195f,0.980432f,0.118503f, +0.251646f,0.94505f,0.208697f, +0.178529f,0.966849f,0.182568f, +0.171641f,0.982807f,0.0680498f, +0.107902f,0.993714f,0.0298233f, +0.00302695f,0.994036f,0.109006f, +-0.0844358f,0.977656f,0.19251f, +-0.18119f,0.958323f,0.220878f, +-0.285317f,0.945377f,0.157659f, +-0.419121f,0.895183f,0.151606f, +-0.490039f,0.857134f,0.158693f, +-0.402244f,0.878123f,0.259038f, +-0.398659f,0.825161f,0.400226f, +-0.427626f,0.728675f,0.534948f, +-0.378859f,0.704334f,0.600316f, +-0.386613f,0.684959f,0.617545f, +-0.440363f,0.648556f,0.62085f, +-0.484249f,0.659981f,0.574394f, +-0.462576f,0.728741f,0.504936f, +-0.380875f,0.811463f,0.443241f, +-0.190303f,0.865049f,0.464193f, +-0.0749094f,0.86956f,0.488113f, +-0.11614f,0.868815f,0.481323f, +-0.102623f,0.843113f,0.527854f, +-0.198362f,0.979655f,0.0304707f, +-0.238942f,0.970277f,0.0383318f, +-0.308109f,0.951351f,-0.000213496f, +-0.245044f,0.968893f,0.0346459f, +-0.275786f,0.960816f,-0.0278198f, +-0.256726f,0.965729f,-0.0381932f, +-0.318964f,0.947473f,-0.0236049f, +-0.388409f,0.921405f,0.0123096f, +-0.298771f,0.953298f,0.0442638f, +-0.291187f,0.956662f,0.00282226f, +-0.39367f,0.915026f,-0.0880448f, +-0.501897f,0.840236f,-0.20519f, +-0.460271f,0.863055f,-0.208055f, +-0.311786f,0.925724f,-0.214066f, +-0.177876f,0.937081f,-0.300397f, +-0.256831f,0.902901f,-0.344683f, +-0.413909f,0.808626f,-0.418096f, +-0.347694f,0.845102f,-0.406092f, +-0.390269f,0.881564f,-0.265585f, +-0.38258f,0.915768f,-0.122479f, +-0.172737f,0.984864f,-0.0142896f, +-0.221138f,0.97315f,-0.0638528f, +-0.32806f,0.922266f,-0.204454f, +-0.20334f,0.945769f,-0.253326f, +-0.0362109f,0.959773f,-0.278433f, +0.0451082f,0.968522f,-0.244806f, +0.103574f,0.977375f,-0.184421f, +0.095607f,0.942862f,-0.319172f, +0.028855f,0.903939f,-0.426688f, +0.0781753f,0.937277f,-0.339707f, +0.163597f,0.966118f,-0.199631f, +0.165445f,0.973063f,-0.160553f, +0.145787f,0.95097f,-0.272767f, +0.130591f,0.92029f,-0.368799f, +0.0531207f,0.931628f,-0.35951f, +-0.0802666f,0.935074f,-0.345244f, +-0.124987f,0.942063f,-0.311281f, +0.0397165f,0.963525f,-0.264653f, +0.0790619f,0.96623f,-0.245254f, +0.0277086f,0.995754f,-0.0877838f, +-0.0718135f,0.997414f,0.00271225f, +-0.0601764f,0.993596f,0.0956336f, +0.0305316f,0.992338f,0.119724f, +0.184993f,0.96549f,0.183324f, +0.240982f,0.949316f,0.20181f, +0.205406f,0.960305f,0.188739f, +0.0685231f,0.967991f,0.241448f, +-0.121139f,0.95072f,0.285408f, +-0.150135f,0.918283f,0.366355f, +-0.132611f,0.919499f,0.370048f, +-0.285199f,0.893271f,0.34746f, +-0.428415f,0.803512f,0.413316f, +-0.445474f,0.783214f,0.433738f, +-0.459983f,0.771026f,0.44038f, +-0.467611f,0.730475f,0.497741f, +-0.48066f,0.718458f,0.502777f, +-0.417628f,0.706128f,0.571814f, +-0.464585f,0.665035f,0.584713f, +-0.472738f,0.646587f,0.598702f, +-0.412146f,0.689264f,0.595861f, +-0.326825f,0.752406f,0.5719f, +-0.254151f,0.834713f,0.48853f, +-0.235109f,0.888903f,0.39316f, +-0.153581f,0.849492f,0.504753f, +-0.150095f,0.815518f,0.558929f, +-0.18873f,0.837012f,0.513607f, +0.0689174f,0.995773f,0.0607139f, +-0.155258f,0.983404f,-0.0938683f, +-0.345692f,0.927547f,-0.141961f, +-0.289881f,0.953783f,-0.079168f, +-0.192407f,0.979661f,-0.0569578f, +-0.267677f,0.960104f,-0.0809323f, +-0.338627f,0.940905f,-0.0054102f, +-0.378143f,0.925406f,-0.0251327f, +-0.331689f,0.941021f,-0.0667991f, +-0.266964f,0.963694f,-0.00485284f, +-0.326986f,0.944023f,-0.0435962f, +-0.406544f,0.902607f,-0.141498f, +-0.445264f,0.84532f,-0.295253f, +-0.261882f,0.90946f,-0.322956f, +-0.131634f,0.928868f,-0.346231f, +-0.231876f,0.922232f,-0.30939f, +-0.381112f,0.87967f,-0.284489f, +-0.459513f,0.85999f,-0.22196f, +-0.498013f,0.864257f,-0.0710131f, +-0.440544f,0.89211f,-0.100303f, +-0.247938f,0.96287f,-0.106806f, +-0.10732f,0.992504f,-0.0584663f, +-0.221465f,0.956592f,-0.189431f, +-0.229248f,0.946541f,-0.22695f, +-0.0978243f,0.972744f,-0.210239f, +-0.0379465f,0.985853f,-0.163259f, +0.0806013f,0.992194f,-0.0951546f, +0.280296f,0.95443f,-0.102456f, +0.155799f,0.941292f,-0.299494f, +-0.0466248f,0.90184f,-0.429548f, +0.0333539f,0.93989f,-0.339845f, +0.15766f,0.95203f,-0.262264f, +0.275219f,0.92494f,-0.262186f, +0.226492f,0.914035f,-0.336513f, +0.0375497f,0.921004f,-0.387739f, +-0.0841489f,0.913809f,-0.39733f, +-0.216548f,0.901013f,-0.375874f, +-0.0617755f,0.971104f,-0.230524f, +0.0635289f,0.988552f,-0.136856f, +-0.0898172f,0.987883f,-0.126568f, +-0.195744f,0.9803f,-0.0263689f, +-0.163398f,0.98375f,0.0744142f, +0.0549941f,0.99236f,0.110438f, +0.19398f,0.975972f,0.0992507f, +0.191759f,0.972804f,0.129928f, +0.149866f,0.963222f,0.223034f, +-0.00306242f,0.957956f,0.286898f, +-0.13576f,0.938575f,0.317249f, +-0.176601f,0.936485f,0.303f, +-0.158083f,0.914215f,0.373122f, +-0.316693f,0.854194f,0.412381f, +-0.498069f,0.774619f,0.389733f, +-0.492142f,0.755365f,0.432688f, +-0.453311f,0.739293f,0.49795f, +-0.471661f,0.730931f,0.49323f, +-0.504596f,0.695479f,0.511558f, +-0.486075f,0.660592f,0.572145f, +-0.455536f,0.681017f,0.573326f, +-0.475459f,0.732851f,0.486691f, +-0.40679f,0.784517f,0.468032f, +-0.294511f,0.862991f,0.410499f, +-0.137096f,0.926626f,0.350098f, +-0.212171f,0.92693f,0.30949f, +-0.320702f,0.890591f,0.322488f, +-0.144781f,0.913051f,0.381284f, +-0.0467088f,0.929255f,0.366475f, +0.190524f,0.979715f,0.0621193f, +-0.0159571f,0.99888f,-0.0445494f, +-0.299493f,0.937414f,-0.177647f, +-0.30245f,0.926474f,-0.223986f, +-0.236991f,0.948637f,-0.209579f, +-0.316653f,0.935173f,-0.15869f, +-0.385652f,0.9143f,-0.123807f, +-0.33937f,0.934637f,-0.106213f, +-0.347064f,0.934195f,-0.0826249f, +-0.295744f,0.955249f,0.00583919f, +-0.275005f,0.961059f,-0.0271544f, +-0.269439f,0.957464f,-0.103275f, +-0.282112f,0.919833f,-0.272616f, +-0.294141f,0.877255f,-0.379347f, +-0.188084f,0.929949f,-0.315942f, +-0.305781f,0.908958f,-0.283361f, +-0.494244f,0.854771f,-0.158396f, +-0.556326f,0.828917f,0.0582992f, +-0.534005f,0.83843f,0.108964f, +-0.372194f,0.92607f,0.0621723f, +-0.216902f,0.97615f,-0.00922891f, +-0.129625f,0.988755f,-0.0745716f, +-0.137022f,0.98954f,-0.0451077f, +-0.210914f,0.969697f,-0.123297f, +-0.0927848f,0.980946f,-0.170691f, +-0.0487293f,0.98279f,-0.178186f, +0.0377154f,0.983594f,-0.176409f, +0.270827f,0.95519f,-0.119436f, +0.365037f,0.928517f,-0.0678507f, +0.131842f,0.951604f,-0.277612f, +-0.0185121f,0.905238f,-0.424502f, +0.118166f,0.903064f,-0.412931f, +0.230045f,0.8849f,-0.405008f, +0.2101f,0.906634f,-0.365886f, +0.0544702f,0.94453f,-0.323878f, +-0.0630069f,0.9598f,-0.273522f, +-0.203027f,0.928033f,-0.312304f, +-0.22235f,0.90002f,-0.374866f, +0.0164141f,0.973192f,-0.229407f, +-0.131299f,0.967472f,-0.216237f, +-0.248586f,0.95668f,-0.151553f, +-0.180678f,0.971697f,-0.152182f, +0.021506f,0.991774f,-0.126182f, +0.129882f,0.991187f,-0.0260519f, +0.125479f,0.988703f,0.0819803f, +0.0585413f,0.987325f,0.14752f, +-0.0186301f,0.977162f,0.211676f, +-0.162972f,0.968132f,0.19016f, +-0.218545f,0.935778f,0.276691f, +-0.284144f,0.890895f,0.354356f, +-0.345593f,0.839997f,0.418295f, +-0.488331f,0.792258f,0.36587f, +-0.545891f,0.770241f,0.329746f, +-0.533891f,0.766492f,0.357002f, +-0.51665f,0.749346f,0.414189f, +-0.616561f,0.690345f,0.37852f, +-0.519109f,0.719346f,0.461593f, +-0.392236f,0.782177f,0.484097f, +-0.398436f,0.817816f,0.415241f, +-0.392025f,0.864189f,0.315428f, +-0.176475f,0.937288f,0.300577f, +-0.137444f,0.969881f,0.201097f, +-0.206545f,0.942409f,0.263066f, +-0.293185f,0.938992f,0.179823f, +-0.159029f,0.985376f,0.0611911f, +0.00174953f,0.998094f,0.0616789f, +0.241821f,0.962041f,0.126492f, +0.127737f,0.984773f,0.117921f, +-0.17559f,0.984255f,0.0202494f, +-0.277772f,0.957333f,-0.0797282f, +-0.264237f,0.953214f,-0.146839f, +-0.330132f,0.935063f,-0.129113f, +-0.363469f,0.924563f,-0.114338f, +-0.371034f,0.917638f,-0.142388f, +-0.425424f,0.897691f,-0.114736f, +-0.353654f,0.934652f,-0.0368062f, +-0.218582f,0.975792f,0.007136f, +-0.203676f,0.978799f,-0.0216238f, +-0.149661f,0.987587f,-0.0476727f, +-0.278943f,0.945373f,-0.1687f, +-0.239375f,0.951961f,-0.190969f, +-0.360119f,0.921099f,-0.147955f, +-0.584157f,0.811569f,0.0107674f, +-0.61484f,0.786528f,0.0578414f, +-0.504089f,0.86363f,-0.00605437f, +-0.333455f,0.94143f,-0.0501755f, +-0.123418f,0.989972f,-0.0687344f, +-0.105519f,0.985418f,-0.133478f, +-0.134701f,0.9843f,-0.114061f, +-0.137014f,0.977235f,-0.161985f, +-0.0439551f,0.980481f,-0.191638f, +-0.0327274f,0.96544f,-0.258561f, +0.0268923f,0.955378f,-0.294159f, +0.189265f,0.941783f,-0.277892f, +0.306008f,0.930356f,-0.201982f, +0.2909f,0.948465f,-0.12566f, +0.135694f,0.963424f,-0.231086f, +0.114996f,0.92781f,-0.354886f, +0.243157f,0.920361f,-0.306286f, +0.181493f,0.943785f,-0.27628f, +-0.0348676f,0.964621f,-0.261325f, +-0.138397f,0.964431f,-0.225208f, +-0.0584572f,0.973863f,-0.219483f, +-0.160488f,0.904663f,-0.394751f, +-0.113572f,0.901558f,-0.417487f, +-0.155065f,0.923521f,-0.350803f, +-0.242307f,0.919914f,-0.308295f, +-0.206106f,0.923371f,-0.323891f, +-0.0753677f,0.972428f,-0.220691f, +0.00286078f,0.993423f,-0.114469f, +0.0506503f,0.998257f,-0.0302924f, +-0.0328546f,0.999299f,0.017926f, +-0.060813f,0.979003f,0.194565f, +-0.19049f,0.94338f,0.271567f, +-0.332962f,0.885593f,0.323821f, +-0.330466f,0.869145f,0.367938f, +-0.383415f,0.840587f,0.382632f, +-0.450848f,0.795155f,0.405542f, +-0.50223f,0.7918f,0.347589f, +-0.586371f,0.768822f,0.255112f, +-0.550176f,0.765625f,0.333355f, +-0.594581f,0.747662f,0.295761f, +-0.604774f,0.771025f,0.199423f, +-0.461798f,0.840354f,0.283809f, +-0.323989f,0.875237f,0.359155f, +-0.321766f,0.916629f,0.23719f, +-0.168943f,0.967667f,0.187293f, +-0.107108f,0.976625f,0.186366f, +-0.222921f,0.963011f,0.151379f, +-0.142187f,0.985732f,0.0900906f, +-0.0555822f,0.997373f,-0.0464466f, +-0.00128055f,0.995901f,-0.0904418f, +0.189226f,0.980362f,-0.0555288f, +0.085267f,0.996327f,-0.00782177f, +-0.128918f,0.990746f,0.042464f, +-0.188312f,0.982054f,-0.0104463f, +-0.196136f,0.979449f,-0.0470074f, +-0.346836f,0.935484f,-0.0676365f, +-0.385817f,0.920741f,-0.0581445f, +-0.364523f,0.930255f,-0.0418259f, +-0.413227f,0.910109f,-0.0307546f, +-0.395357f,0.915702f,-0.071985f, +-0.249105f,0.966325f,-0.0645241f, +-0.224404f,0.97132f,-0.0786097f, +-0.136636f,0.989057f,-0.0556425f, +-0.161967f,0.98357f,-0.0797312f, +-0.264069f,0.956689f,-0.122532f, +-0.415862f,0.909427f,-0.00117779f, +-0.618635f,0.784039f,0.0507281f, +-0.569525f,0.818988f,-0.0700017f, +-0.458442f,0.876243f,-0.148424f, +-0.301532f,0.936403f,-0.179521f, +-0.125352f,0.969963f,-0.208469f, +-0.0885456f,0.971015f,-0.222014f, +-0.127345f,0.96169f,-0.242765f, +-0.111865f,0.95953f,-0.258434f, +-0.00408963f,0.957803f,-0.287396f, +0.0423217f,0.932535f,-0.358592f, +0.0695614f,0.921939f,-0.381037f, +0.190852f,0.890613f,-0.412775f, +0.209386f,0.879353f,-0.427663f, +0.178912f,0.925963f,-0.332541f, +0.21012f,0.943847f,-0.254954f, +0.194248f,0.92787f,-0.318316f, +0.12116f,0.941808f,-0.313556f, +0.143074f,0.982238f,-0.121399f, +0.00445755f,0.990826f,-0.135068f, +-0.0763662f,0.964673f,-0.252139f, +-0.00960064f,0.938734f,-0.34451f, +-0.0448775f,0.923487f,-0.380997f, +-0.121038f,0.899958f,-0.418839f, +-0.214432f,0.896136f,-0.388536f, +-0.236628f,0.909444f,-0.341933f, +-0.245801f,0.902665f,-0.353239f, +-0.210816f,0.938091f,-0.274848f, +-0.0790665f,0.981118f,-0.17651f, +-0.0418777f,0.998086f,-0.0455073f, +-0.112513f,0.981903f,0.152339f, +-0.289647f,0.921573f,0.258473f, +-0.276284f,0.866929f,0.414851f, +-0.316808f,0.857367f,0.405653f, +-0.333206f,0.853137f,0.401412f, +-0.396081f,0.828088f,0.396725f, +-0.485909f,0.809843f,0.328705f, +-0.463328f,0.813789f,0.350819f, +-0.520203f,0.774122f,0.360725f, +-0.581754f,0.763678f,0.279925f, +-0.55781f,0.791203f,0.250691f, +-0.576356f,0.800103f,0.166282f, +-0.522214f,0.839566f,0.149738f, +-0.327667f,0.934488f,0.139166f, +-0.239893f,0.965369f,0.102537f, +-0.178401f,0.973537f,0.142826f, +-0.0446164f,0.980327f,0.192274f, +-0.152707f,0.98769f,0.0338934f, +-0.061376f,0.996098f,-0.0634113f, +-0.00816896f,0.988579f,-0.150483f, +0.0167009f,0.992551f,-0.120678f, +0.148875f,0.988771f,-0.0129578f, +0.0273451f,0.999626f,0.000950796f, +-0.109359f,0.99398f,0.00672756f, +-0.162948f,0.982686f,-0.0881845f, +-0.242271f,0.966262f,-0.0874275f, +-0.357996f,0.933723f,0.000140943f, +-0.377863f,0.925289f,0.0325572f, +-0.389424f,0.920391f,0.0350616f, +-0.408888f,0.910343f,0.0639282f, +-0.371945f,0.928232f,0.00649489f, +-0.230632f,0.97289f,0.0171594f, +-0.159091f,0.987197f,-0.0114848f, +-0.122759f,0.984183f,-0.127724f, +-0.175251f,0.974473f,-0.14032f, +-0.35571f,0.933079f,-0.0532364f, +-0.501387f,0.863164f,0.0596562f, +-0.575441f,0.816492f,-0.0470046f, +-0.501056f,0.856673f,-0.122698f, +-0.414992f,0.888139f,-0.19746f, +-0.309585f,0.914677f,-0.259854f, +-0.0986663f,0.965073f,-0.242693f, +-0.0576728f,0.965088f,-0.255499f, +-0.0928316f,0.963296f,-0.251879f, +-0.0710107f,0.944633f,-0.320352f, +0.0799711f,0.918771f,-0.386606f, +0.0834923f,0.89273f,-0.442789f, +0.0521243f,0.897343f,-0.438246f, +0.251171f,0.890827f,-0.378604f, +0.176541f,0.892631f,-0.414781f, +0.102505f,0.91423f,-0.392015f, +0.148543f,0.910792f,-0.385219f, +0.204336f,0.92739f,-0.313361f, +0.00672261f,0.969577f,-0.244696f, +-0.0203828f,0.994006f,-0.10741f, +0.0984818f,0.994155f,-0.0442492f, +0.0884297f,0.979853f,-0.179077f, +0.079756f,0.934869f,-0.345919f, +-0.0373135f,0.916973f,-0.3972f, +-0.13475f,0.922044f,-0.362873f, +-0.248554f,0.90561f,-0.343645f, +-0.298871f,0.900649f,-0.315447f, +-0.245556f,0.942684f,-0.225941f, +-0.29156f,0.92569f,-0.241018f, +-0.210251f,0.966564f,-0.146796f, +-0.258034f,0.965595f,0.0323199f, +-0.368176f,0.902709f,0.22263f, +-0.350064f,0.851117f,0.391223f, +-0.273287f,0.858969f,0.432996f, +-0.285306f,0.881397f,0.376483f, +-0.391023f,0.856564f,0.336748f, +-0.346592f,0.838969f,0.419529f, +-0.422742f,0.829366f,0.365295f, +-0.513303f,0.775065f,0.368504f, +-0.526999f,0.742246f,0.413935f, +-0.485934f,0.782442f,0.389426f, +-0.494091f,0.808005f,0.32094f, +-0.527377f,0.820007f,0.222402f, +-0.463863f,0.878834f,0.111725f, +-0.310302f,0.94881f,0.0589178f, +-0.228025f,0.964645f,0.132153f, +-0.25901f,0.96255f,0.080067f, +-0.0424596f,0.997867f,0.0495831f, +-0.00646979f,0.998786f,0.048831f, +0.0235108f,0.999153f,0.033786f, +0.0350773f,0.999112f,0.0233587f, +-0.06489f,0.99782f,0.0120079f, +0.0653571f,0.99589f,0.0626978f, +0.0437681f,0.989758f,0.13588f, +-0.0612591f,0.992124f,0.109253f, +-0.0700659f,0.993846f,0.085792f, +-0.245254f,0.968292f,0.0475526f, +-0.425333f,0.903383f,0.0546907f, +-0.406557f,0.90921f,0.0897132f, +-0.40303f,0.911526f,0.0817765f, +-0.380881f,0.92142f,0.0769048f, +-0.320213f,0.947262f,0.0126033f, +-0.2583f,0.964583f,-0.0534921f, +-0.102892f,0.993091f,-0.0564197f, +-0.0482689f,0.996133f,-0.0734163f, +-0.214829f,0.976629f,0.00662477f, +-0.431775f,0.896672f,0.0977224f, +-0.451215f,0.886255f,0.104672f, +-0.522087f,0.848838f,-0.0830587f, +-0.458286f,0.880944f,-0.117949f, +-0.338524f,0.917937f,-0.206865f, +-0.285281f,0.916752f,-0.279607f, +-0.142352f,0.962006f,-0.232982f, +-0.0943041f,0.983891f,-0.151875f, +-0.0753867f,0.988192f,-0.133394f, +0.0592214f,0.975378f,-0.212437f, +0.135178f,0.93923f,-0.315553f, +0.146098f,0.928461f,-0.34149f, +0.0154593f,0.901088f,-0.433361f, +0.163565f,0.906515f,-0.389201f, +0.204593f,0.933049f,-0.295907f, +0.124274f,0.938076f,-0.323371f, +0.137407f,0.92485f,-0.354642f, +0.063168f,0.960879f,-0.269671f, +-0.0720239f,0.98835f,-0.134077f, +-0.0757271f,0.981006f,-0.178587f, +0.0897227f,0.968994f,-0.23022f, +0.219073f,0.948381f,-0.229303f, +0.192275f,0.938149f,-0.287936f, +-0.0492263f,0.973953f,-0.221343f, +-0.181885f,0.971294f,-0.153316f, +-0.242476f,0.960686f,-0.135229f, +-0.363624f,0.917475f,-0.161301f, +-0.330978f,0.935565f,-0.12317f, +-0.30439f,0.949195f,-0.0798413f, +-0.362853f,0.931339f,-0.0307322f, +-0.401675f,0.903644f,0.148607f, +-0.425736f,0.872787f,0.238731f, +-0.458216f,0.866256f,0.199096f, +-0.325646f,0.913769f,0.242862f, +-0.214745f,0.922085f,0.321938f, +-0.398463f,0.884492f,0.242694f, +-0.475038f,0.830832f,0.289927f, +-0.448294f,0.764081f,0.463909f, +-0.497042f,0.7065f,0.503792f, +-0.489906f,0.735868f,0.467431f, +-0.460921f,0.76339f,0.452535f, +-0.40897f,0.781052f,0.471913f, +-0.371818f,0.839399f,0.396435f, +-0.326758f,0.904742f,0.27326f, +-0.383198f,0.91056f,0.155045f, +-0.284609f,0.924825f,0.252383f, +-0.0749114f,0.976737f,0.200932f, +0.00799324f,0.997093f,0.0757729f, +-0.0700844f,0.990942f,0.114551f, +-0.0596966f,0.983848f,0.168758f, +0.00586433f,0.977052f,0.212922f, +-0.0605914f,0.978841f,0.195443f, +-0.0438257f,0.995801f,0.0803703f, +-0.0570689f,0.993344f,0.100052f, +-0.0606116f,0.987839f,0.143177f, +-0.0960986f,0.983658f,0.152253f, +-0.240218f,0.956553f,0.16523f, +-0.410215f,0.902731f,0.129617f, +-0.38596f,0.917352f,0.0974681f, +-0.348531f,0.935694f,0.0547901f, +-0.396424f,0.918039f,-0.00721866f, +-0.26358f,0.961512f,0.0775866f, +-0.177577f,0.982975f,0.0471779f, +-0.0921077f,0.995708f,0.00907831f, +-0.131805f,0.991186f,0.0133294f, +-0.348565f,0.935587f,0.0563885f, +-0.467549f,0.880933f,0.0731775f, +-0.372581f,0.926945f,0.0442312f, +-0.408929f,0.911847f,-0.0362219f, +-0.445009f,0.893478f,-0.0605312f, +-0.306432f,0.951885f,-0.00384437f, +-0.259351f,0.965029f,0.0381644f, +-0.265204f,0.963994f,-0.0195798f, +-0.114808f,0.993343f,0.00942441f, +-0.0279481f,0.990324f,-0.135929f, +0.103339f,0.977655f,-0.18306f, +0.218767f,0.966894f,-0.131368f, +0.207579f,0.958824f,-0.193824f, +0.136905f,0.960239f,-0.243308f, +0.117272f,0.934734f,-0.335438f, +0.133403f,0.937193f,-0.322294f, +0.140113f,0.948531f,-0.284001f, +0.0924439f,0.975124f,-0.201463f, +-0.0405443f,0.993271f,-0.108481f, +-0.0729426f,0.987394f,-0.140474f, +0.0307633f,0.972795f,-0.229615f, +0.200951f,0.951021f,-0.2349f, +0.206873f,0.91785f,-0.338755f, +0.0409109f,0.957201f,-0.286518f, +-0.211311f,0.976629f,-0.0392802f, +-0.256735f,0.961768f,0.0953371f, +-0.237528f,0.960421f,0.145504f, +-0.329105f,0.937835f,0.110248f, +-0.355083f,0.930437f,0.0905737f, +-0.33751f,0.931415f,0.13621f, +-0.400013f,0.905919f,0.138928f, +-0.505595f,0.854442f,0.119596f, +-0.452675f,0.873473f,0.179247f, +-0.360085f,0.917004f,0.17159f, +-0.404496f,0.910531f,0.0855373f, +-0.324231f,0.903855f,0.279141f, +-0.336075f,0.852068f,0.40129f, +-0.562491f,0.75864f,0.328737f, +-0.580482f,0.703244f,0.410473f, +-0.499356f,0.747889f,0.437385f, +-0.47057f,0.77436f,0.423001f, +-0.457721f,0.780273f,0.426221f, +-0.387043f,0.830428f,0.400733f, +-0.304454f,0.882516f,0.358431f, +-0.240482f,0.915056f,0.323791f, +-0.289179f,0.919765f,0.265345f, +-0.239541f,0.954664f,0.176742f, +-0.0468358f,0.993768f,0.10115f, +-0.0227943f,0.987776f,0.154204f, +-0.112093f,0.964309f,0.239881f, +-0.0599845f,0.969963f,0.235741f, +0.0387578f,0.968143f,0.24738f, +0.0187191f,0.971458f,0.236471f, +0.242021f,0.896343f,0.371478f, +0.0480335f,0.972296f,0.228765f, +-0.0779729f,0.986176f,0.146206f, +-0.0941394f,0.982277f,0.16208f, +-0.22083f,0.962927f,0.154936f, +-0.380194f,0.918443f,0.109152f, +-0.362825f,0.928988f,0.0730715f, +-0.322334f,0.943799f,0.0731113f, +-0.408658f,0.905696f,0.112752f, +-0.342623f,0.91378f,0.218209f, +-0.178962f,0.947287f,0.265744f, +-0.0963031f,0.962264f,0.254507f, +-0.129686f,0.959928f,0.248434f, +-0.25861f,0.932715f,0.251325f, +-0.400538f,0.911394f,0.0944958f, +-0.371118f,0.928542f,0.00899351f, +-0.395096f,0.916517f,0.0624194f, +-0.492959f,0.864551f,0.097688f, +-0.425957f,0.892844f,0.146255f, +-0.256791f,0.9425f,0.213898f, +-0.177422f,0.976398f,0.123157f, +0.0269208f,0.996881f,0.0741829f, +0.164645f,0.980831f,-0.104223f, +0.0973784f,0.963273f,-0.250244f, +0.114359f,0.965463f,-0.234102f, +0.250084f,0.96398f,-0.0905583f, +0.183861f,0.973241f,-0.137829f, +0.203921f,0.957737f,-0.202868f, +0.170155f,0.95208f,-0.254149f, +0.0373443f,0.963666f,-0.264487f, +-0.0311132f,0.98854f,-0.147717f, +-0.0500681f,0.990616f,-0.127173f, +0.0774781f,0.980584f,-0.180143f, +0.0416659f,0.952342f,-0.302174f, +0.183971f,0.945491f,-0.268702f, +0.234504f,0.932825f,-0.27358f, +-0.0611848f,0.988685f,-0.13696f, +-0.37387f,0.925543f,-0.059925f, +-0.361069f,0.932447f,-0.0130774f, +-0.247932f,0.961796f,0.1161f, +-0.321909f,0.940217f,0.111206f, +-0.373794f,0.915694f,0.147587f, +-0.370927f,0.915202f,0.157537f, +-0.367344f,0.908177f,0.20068f, +-0.445687f,0.879826f,0.165134f, +-0.480845f,0.872838f,0.0833169f, +-0.396228f,0.900984f,0.176722f, +-0.39533f,0.870559f,0.292987f, +-0.514705f,0.791717f,0.329034f, +-0.426478f,0.754312f,0.49913f, +-0.476928f,0.731476f,0.487321f, +-0.555203f,0.748777f,0.362053f, +-0.513793f,0.811828f,0.277402f, +-0.498737f,0.823176f,0.271372f, +-0.459197f,0.851815f,0.252089f, +-0.364638f,0.907849f,0.207f, +-0.280535f,0.937686f,0.205051f, +-0.204645f,0.959273f,0.194721f, +-0.188424f,0.978285f,0.0863425f, +-0.16576f,0.97773f,-0.128717f, +-0.0413953f,0.984504f,-0.170405f, +-0.119175f,0.989154f,-0.0858603f, +-0.164393f,0.986215f,0.018821f, +-0.0876541f,0.994439f,0.0583851f, +-0.00781607f,0.987179f,0.159428f, +-0.00608226f,0.980142f,0.198203f, +0.294056f,0.919888f,0.259494f, +0.176099f,0.946212f,0.271426f, +-0.0256669f,0.973237f,0.228366f, +-0.0934761f,0.978631f,0.183149f, +-0.211202f,0.968374f,0.132837f, +-0.345036f,0.933287f,0.0996237f, +-0.346043f,0.935088f,0.0765773f, +-0.381385f,0.918419f,0.105127f, +-0.476923f,0.857096f,0.19476f, +-0.397907f,0.88874f,0.227622f, +-0.175271f,0.936954f,0.30232f, +-0.040477f,0.944541f,0.325889f, +-0.142418f,0.942444f,0.302518f, +-0.246569f,0.91514f,0.318938f, +-0.255277f,0.933873f,0.25043f, +-0.348488f,0.92941f,0.121466f, +-0.472178f,0.874219f,0.113089f, +-0.490306f,0.858256f,0.151645f, +-0.38804f,0.914553f,0.114097f, +-0.196584f,0.979051f,0.0530513f, +-0.0793551f,0.996572f,-0.0234008f, +0.0406197f,0.994776f,-0.0936505f, +0.24653f,0.966821f,-0.0669378f, +0.269235f,0.959692f,-0.0806517f, +0.0569112f,0.963296f,-0.26234f, +0.131503f,0.973945f,-0.184764f, +0.24729f,0.957434f,-0.148892f, +0.248779f,0.951221f,-0.18245f, +0.18718f,0.966303f,-0.176696f, +0.00607471f,0.977895f,-0.20901f, +-0.0210706f,0.975074f,-0.220878f, +0.00501251f,0.949574f,-0.313502f, +0.0771251f,0.945518f,-0.316304f, +0.130553f,0.948445f,-0.288805f, +0.175519f,0.929764f,-0.323623f, +0.111769f,0.971665f,-0.208266f, +-0.210844f,0.971563f,-0.107753f, +-0.345299f,0.9344f,-0.087551f, +-0.367127f,0.918607f,-0.146212f, +-0.340753f,0.929779f,-0.139279f, +-0.358585f,0.929839f,-0.0825605f, +-0.393886f,0.919008f,-0.0166963f, +-0.401193f,0.915983f,0.00451588f, +-0.406108f,0.91192f,0.0589777f, +-0.45609f,0.887954f,0.0593294f, +-0.481921f,0.86351f,0.148669f, +-0.533578f,0.80576f,0.256994f, +-0.480795f,0.753832f,0.447854f, +-0.502576f,0.721353f,0.476516f, +-0.457582f,0.746697f,0.482766f, +-0.419108f,0.791496f,0.44484f, +-0.465376f,0.834036f,0.296325f, +-0.468919f,0.860429f,0.199442f, +-0.486627f,0.858618f,0.161151f, +-0.430227f,0.89524f,0.115972f, +-0.34028f,0.937953f,0.066739f, +-0.311486f,0.949765f,0.0303886f, +-0.166884f,0.985403f,0.0336267f, +0.0381647f,0.996782f,-0.0704869f, +0.0486826f,0.951753f,-0.302979f, +-0.0940893f,0.932244f,-0.349383f, +-0.229015f,0.944857f,-0.234089f, +-0.214421f,0.956596f,-0.19735f, +-0.17466f,0.962579f,-0.207209f, +-0.106663f,0.986513f,-0.124157f, +-0.0523564f,0.993983f,-0.0962102f, +0.1751f,0.970986f,0.162867f, +0.126838f,0.957099f,0.260524f, +-0.0248407f,0.948904f,0.314587f, +-0.0169284f,0.94527f,0.325849f, +-0.126002f,0.963121f,0.237743f, +-0.322368f,0.933961f,0.154262f, +-0.357267f,0.920847f,0.156206f, +-0.40825f,0.900639f,0.148934f, +-0.500408f,0.86145f,0.0865774f, +-0.437173f,0.895731f,0.0809122f, +-0.234862f,0.957423f,0.167871f, +-0.122112f,0.971133f,0.204913f, +-0.146988f,0.949325f,0.277805f, +-0.214866f,0.947227f,0.237893f, +-0.166781f,0.968529f,0.184757f, +-0.279132f,0.953637f,0.112522f, +-0.438908f,0.892826f,0.101101f, +-0.476448f,0.878957f,0.0207741f, +-0.317496f,0.946313f,-0.0607282f, +-0.175675f,0.968847f,-0.174568f, +0.00443594f,0.981128f,-0.193308f, +0.0639918f,0.955901f,-0.286634f, +0.156615f,0.959233f,-0.235253f, +0.281138f,0.953388f,-0.109604f, +0.173642f,0.975105f,-0.137905f, +0.125725f,0.970112f,-0.207546f, +0.23259f,0.936622f,-0.261996f, +0.234534f,0.938208f,-0.25448f, +0.160485f,0.952598f,-0.258459f, +0.0824642f,0.968528f,-0.234849f, +0.0634583f,0.946763f,-0.315614f, +0.0567562f,0.917557f,-0.393532f, +0.0240187f,0.918352f,-0.395035f, +0.0995244f,0.946786f,-0.30609f, +0.0782245f,0.971194f,-0.225085f, +0.0104903f,0.995647f,-0.0926114f, +-0.185802f,0.976721f,-0.107212f, +-0.328502f,0.923412f,-0.198486f, +-0.311331f,0.92975f,-0.196566f, +-0.349149f,0.904891f,-0.24345f, +-0.388436f,0.90322f,-0.182515f, +-0.447323f,0.88531f,-0.126995f, +-0.452109f,0.890067f,-0.0581177f, +-0.409043f,0.912515f,0.000312055f, +-0.489105f,0.872225f,-0.000401423f, +-0.602394f,0.789815f,0.115381f, +-0.644891f,0.727938f,0.232857f, +-0.581256f,0.729671f,0.360168f, +-0.503025f,0.763549f,0.404917f, +-0.449741f,0.833702f,0.320428f, +-0.320295f,0.891402f,0.320645f, +-0.365897f,0.908793f,0.200535f, +-0.418513f,0.900509f,0.118029f, +-0.464312f,0.883882f,0.0562756f, +-0.399182f,0.916811f,0.0105308f, +-0.291715f,0.956056f,-0.0293054f, +-0.237447f,0.965751f,-0.104617f, +-0.100041f,0.966568f,-0.236091f, +0.160871f,0.934989f,-0.316096f, +0.093049f,0.931221f,-0.352375f, +-0.15859f,0.964926f,-0.209204f, +-0.273524f,0.944194f,-0.183526f, +-0.190425f,0.948278f,-0.253984f, +-0.130985f,0.95529f,-0.265074f, +-0.109109f,0.943759f,-0.312112f, +-0.0442587f,0.936376f,-0.348197f, +0.0244075f,0.991066f,0.131121f, +-0.0145509f,0.975134f,0.221137f, +-0.0404534f,0.947565f,0.316994f, +-0.0554847f,0.953641f,0.295787f, +-0.0378486f,0.926136f,0.375287f, +-0.276884f,0.909741f,0.309364f, +-0.35531f,0.878584f,0.319132f, +-0.28855f,0.905318f,0.311668f, +-0.418654f,0.900829f,0.115051f, +-0.470621f,0.881923f,0.0269622f, +-0.302456f,0.950707f,0.0683814f, +-0.155931f,0.981097f,0.114601f, +-0.172528f,0.971746f,0.161072f, +-0.175279f,0.972437f,0.153763f, +-0.0948884f,0.989506f,0.108971f, +-0.271832f,0.96203f,0.0246161f, +-0.434113f,0.899816f,0.0433328f, +-0.41192f,0.910729f,-0.0299284f, +-0.184465f,0.976107f,-0.114836f, +-0.0519711f,0.950434f,-0.306552f, +0.0510061f,0.914254f,-0.401918f, +0.0714878f,0.915457f,-0.396015f, +0.0823148f,0.944294f,-0.318643f, +0.154376f,0.938672f,-0.308322f, +0.218285f,0.948145f,-0.231024f, +0.158935f,0.938404f,-0.306818f, +0.261223f,0.9329f,-0.247912f, +0.285998f,0.932056f,-0.222434f, +0.190198f,0.913869f,-0.358703f, +0.0636773f,0.892218f,-0.447094f, +0.10205f,0.889697f,-0.445f, +0.100031f,0.900986f,-0.422159f, +0.0104969f,0.905423f,-0.424381f, +-0.0688464f,0.910262f,-0.408268f, +-0.0482237f,0.974352f,-0.219802f, +-0.0083558f,0.994225f,-0.106992f, +-0.112134f,0.979056f,-0.169927f, +-0.229912f,0.945374f,-0.231102f, +-0.280533f,0.899591f,-0.334719f, +-0.346884f,0.867971f,-0.355384f, +-0.459064f,0.843199f,-0.279779f, +-0.497889f,0.848119f,-0.181111f, +-0.501207f,0.860371f,-0.0924901f, +-0.458162f,0.888868f,-0.00122281f, +-0.514613f,0.855463f,0.0579275f, +-0.647763f,0.760835f,0.0391491f, +-0.704753f,0.709026f,0.0246046f, +-0.656653f,0.750377f,0.0757771f, +-0.504188f,0.854115f,0.127601f, +-0.41033f,0.905141f,0.111126f, +-0.337511f,0.936543f,0.0947305f, +-0.307169f,0.946112f,0.10256f, +-0.367429f,0.928128f,0.0597776f, +-0.393986f,0.91872f,-0.0269814f, +-0.373766f,0.918684f,-0.127743f, +-0.26114f,0.960116f,-0.0999132f, +-0.103927f,0.984722f,-0.139723f, +0.0511518f,0.955672f,-0.289956f, +0.187205f,0.928701f,-0.320109f, +-0.0295799f,0.970029f,-0.241182f, +-0.314429f,0.940081f,-0.13184f, +-0.185337f,0.978913f,-0.0859053f, +-0.104364f,0.967564f,-0.230061f, +-0.0895833f,0.932754f,-0.349206f, +-0.054587f,0.891296f,-0.450124f, +0.0297567f,0.885691f,-0.463321f, +0.100841f,0.951386f,0.291024f, +-0.0719364f,0.970866f,0.22857f, +-0.0950354f,0.957535f,0.272204f, +-0.063148f,0.9475f,0.313457f, +-0.147905f,0.922206f,0.357295f, +-0.255052f,0.862392f,0.437296f, +-0.348295f,0.831026f,0.433689f, +-0.228735f,0.861593f,0.453141f, +-0.189137f,0.904176f,0.383004f, +-0.40614f,0.912877f,0.041313f, +-0.322035f,0.946605f,-0.0152552f, +-0.213289f,0.976152f,0.0404333f, +-0.216957f,0.96919f,0.116619f, +-0.143471f,0.982181f,0.121395f, +-0.0619809f,0.995307f,0.0743149f, +-0.20303f,0.975599f,0.0835793f, +-0.415979f,0.909172f,0.0191678f, +-0.336954f,0.94062f,-0.0411873f, +-0.0679584f,0.981162f,-0.180839f, +0.116786f,0.956914f,-0.265849f, +0.119526f,0.96094f,-0.249616f, +-0.00488697f,0.95735f,-0.288889f, +0.0539017f,0.947486f,-0.315223f, +0.147321f,0.922615f,-0.35648f, +0.255572f,0.910786f,-0.324272f, +0.156463f,0.885962f,-0.436566f, +0.1301f,0.92297f,-0.362215f, +0.25276f,0.923086f,-0.289871f, +0.383737f,0.889757f,-0.247141f, +0.211205f,0.883014f,-0.419141f, +0.0342331f,0.879599f,-0.474482f, +0.00319575f,0.938694f,-0.344735f, +0.0177214f,0.953292f,-0.301529f, +-0.111253f,0.93857f,-0.326663f, +-0.240335f,0.933381f,-0.26653f, +-0.0538188f,0.987001f,-0.151433f, +-0.0274864f,0.979377f,-0.200162f, +-0.187631f,0.946384f,-0.262966f, +-0.206926f,0.955659f,-0.209519f, +-0.334901f,0.924406f,-0.182523f, +-0.500035f,0.842333f,-0.201099f, +-0.536058f,0.812568f,-0.228857f, +-0.57838f,0.789021f,-0.207176f, +-0.551453f,0.831854f,-0.0625953f, +-0.537806f,0.840551f,0.0651045f, +-0.581123f,0.812541f,0.0455343f, +-0.677773f,0.725811f,-0.117567f, +-0.674512f,0.726391f,-0.131871f, +-0.561194f,0.823313f,-0.0849523f, +-0.426155f,0.904036f,-0.0333265f, +-0.350057f,0.935877f,-0.0399208f, +-0.324764f,0.94579f,-0.0029281f, +-0.334572f,0.942069f,0.0238272f, +-0.264187f,0.96401f,-0.0298196f, +-0.331302f,0.926674f,-0.177522f, +-0.297768f,0.937944f,-0.177749f, +-0.0551409f,0.983889f,-0.170067f, +0.144484f,0.972505f,-0.182644f, +0.119335f,0.96645f,-0.227451f, +-0.0885992f,0.982619f,-0.163126f, +-0.33707f,0.92576f,-0.171324f, +-0.162854f,0.966557f,-0.198108f, +0.0162126f,0.974218f,-0.225026f, +0.138436f,0.947057f,-0.289688f, +0.0835536f,0.876982f,-0.473204f, +-0.010237f,0.848096f,-0.529743f, +0.136921f,0.906371f,0.399681f, +0.0140824f,0.922185f,0.386492f, +-0.160268f,0.929321f,0.33268f, +-0.112451f,0.900092f,0.420938f, +-0.203296f,0.876433f,0.436504f, +-0.322996f,0.829667f,0.455332f, +-0.340765f,0.827757f,0.445755f, +-0.257344f,0.84669f,0.465715f, +0.00366351f,0.865541f,0.500825f, +-0.0425812f,0.956742f,0.287804f, +-0.322344f,0.945159f,-0.052618f, +-0.280797f,0.958795f,-0.0431994f, +-0.262333f,0.964629f,-0.0259446f, +-0.0891831f,0.995449f,-0.0335709f, +-0.0801038f,0.992742f,-0.0896982f, +-0.224206f,0.974484f,0.0105758f, +-0.364477f,0.9309f,-0.0241328f, +-0.198506f,0.970273f,-0.138443f, +0.0492304f,0.955815f,-0.289816f, +0.0465241f,0.961334f,-0.271428f, +0.0147498f,0.993644f,-0.111598f, +0.136409f,0.989222f,-0.0532271f, +0.148553f,0.957532f,-0.247113f, +0.203722f,0.927854f,-0.312384f, +0.268253f,0.883803f,-0.383317f, +0.18614f,0.887058f,-0.422469f, +0.10218f,0.907566f,-0.407286f, +0.200645f,0.878358f,-0.433854f, +0.320433f,0.870875f,-0.372692f, +0.278243f,0.911383f,-0.303252f, +-0.0169368f,0.97379f,-0.226818f, +-0.116502f,0.978925f,-0.16773f, +0.0246686f,0.985931f,-0.165321f, +-0.099417f,0.977857f,-0.184152f, +-0.275352f,0.945128f,-0.175824f, +-0.0928967f,0.974055f,-0.206368f, +0.0664566f,0.97817f,-0.196893f, +-0.180659f,0.959555f,-0.21591f, +-0.356529f,0.924348f,-0.135896f, +-0.392702f,0.919607f,0.0104344f, +-0.427591f,0.903919f,-0.00980201f, +-0.491673f,0.851131f,-0.183941f, +-0.597871f,0.779934f,-0.185076f, +-0.630214f,0.771159f,-0.0902474f, +-0.603795f,0.796392f,-0.0345128f, +-0.532942f,0.846043f,0.013577f, +-0.560658f,0.826581f,-0.049261f, +-0.693149f,0.692482f,-0.200033f, +-0.591049f,0.792583f,-0.14991f, +-0.423413f,0.894971f,-0.14053f, +-0.360923f,0.922234f,-0.138633f, +-0.376728f,0.924323f,-0.0608465f, +-0.330964f,0.94352f,-0.0152562f, +-0.205049f,0.976512f,-0.0661789f, +-0.221147f,0.966952f,-0.126878f, +-0.282753f,0.933366f,-0.221083f, +-0.0599842f,0.959615f,-0.274846f, +0.119046f,0.947951f,-0.295324f, +0.164559f,0.948383f,-0.27109f, +-0.0951076f,0.948417f,-0.302424f, +-0.271887f,0.913351f,-0.303098f, +-0.128933f,0.917201f,-0.376985f, +0.0280066f,0.909443f,-0.414885f, +0.150608f,0.898143f,-0.413106f, +0.212115f,0.88838f,-0.407172f, +0.0467869f,0.87371f,-0.484191f, +0.135605f,0.903203f,0.407228f, +-0.01172f,0.896648f,0.44259f, +-0.138887f,0.847422f,0.512432f, +-0.170991f,0.843044f,0.50994f, +-0.191878f,0.839246f,0.508772f, +-0.300268f,0.838171f,0.455311f, +-0.32966f,0.831286f,0.447535f, +-0.223175f,0.877254f,0.424992f, +-0.0256774f,0.953915f,0.298977f, +0.199545f,0.913698f,0.354031f, +-0.0319727f,0.980881f,0.191963f, +-0.258985f,0.964126f,-0.0582107f, +-0.212788f,0.970943f,-0.109502f, +-0.0721792f,0.982085f,-0.174064f, +-0.0849627f,0.985898f,-0.144175f, +-0.290021f,0.949136f,-0.122591f, +-0.248272f,0.954348f,-0.166075f, +-0.0507313f,0.942327f,-0.330828f, +0.0792104f,0.910775f,-0.405234f, +-0.0679775f,0.927432f,-0.367762f, +-0.0963141f,0.945938f,-0.309718f, +0.147422f,0.952479f,-0.266555f, +0.232988f,0.930423f,-0.282895f, +0.296671f,0.921407f,-0.250989f, +0.346023f,0.880014f,-0.325337f, +0.246011f,0.893818f,-0.374924f, +0.0779935f,0.862828f,-0.499444f, +0.218748f,0.861753f,-0.457746f, +0.236169f,0.890523f,-0.388836f, +0.122215f,0.968128f,-0.218613f, +-0.119249f,0.983741f,-0.134288f, +-0.0975043f,0.983669f,-0.151287f, +0.0551556f,0.975975f,-0.210786f, +-0.0858442f,0.972611f,-0.216008f, +-0.228301f,0.939116f,-0.256789f, +-0.0600278f,0.94195f,-0.330342f, +-0.00498162f,0.954835f,-0.297095f, +-0.236752f,0.956732f,-0.169151f, +-0.404481f,0.905728f,-0.126698f, +-0.442956f,0.884106f,-0.148815f, +-0.353117f,0.929811f,-0.103732f, +-0.367684f,0.920274f,-0.133808f, +-0.620195f,0.758926f,-0.19847f, +-0.650875f,0.742352f,-0.158981f, +-0.60395f,0.783223f,-0.147668f, +-0.562027f,0.815077f,-0.140626f, +-0.504739f,0.855197f,-0.117796f, +-0.629314f,0.743816f,-0.22517f, +-0.590837f,0.750634f,-0.295736f, +-0.432954f,0.842346f,-0.320942f, +-0.414184f,0.8722f,-0.260227f, +-0.438355f,0.884876f,-0.157606f, +-0.309198f,0.940747f,-0.13925f, +-0.155389f,0.967122f,-0.20132f, +-0.14424f,0.961525f,-0.233805f, +-0.235758f,0.924f,-0.301067f, +0.0151186f,0.960375f,-0.278299f, +0.144315f,0.944571f,-0.294888f, +0.112415f,0.964242f,-0.239999f, +-0.0426025f,0.977992f,-0.204249f, +-0.206795f,0.910666f,-0.357663f, +-0.0742651f,0.885367f,-0.458922f, +0.0946583f,0.875247f,-0.474324f, +0.121834f,0.836586f,-0.534117f, +0.198513f,0.859849f,-0.470374f, +0.17646f,0.872184f,-0.456242f, +0.0304109f,0.916616f,0.39861f, +-0.119037f,0.881644f,0.456655f, +-0.241587f,0.81204f,0.53125f, +-0.146676f,0.796898f,0.586037f, +-0.0991089f,0.808485f,0.580111f, +-0.265015f,0.835696f,0.481019f, +-0.330941f,0.833473f,0.442495f, +-0.0736129f,0.908742f,0.410816f, +0.128357f,0.956244f,0.26291f, +0.135386f,0.977167f,0.163754f, +0.135126f,0.969499f,0.204482f, +-0.0826833f,0.991706f,0.0984031f, +-0.125203f,0.992066f,-0.0113628f, +-0.0793175f,0.988189f,-0.131112f, +-0.135148f,0.988869f,-0.0622353f, +-0.236045f,0.96998f,-0.0584937f, +-0.106098f,0.976702f,-0.186536f, +0.0734477f,0.937214f,-0.340932f, +0.0657813f,0.913127f,-0.402333f, +-0.0656411f,0.925185f,-0.373797f, +-0.0812155f,0.911514f,-0.403169f, +0.138018f,0.895606f,-0.422895f, +0.180346f,0.87052f,-0.457898f, +0.220345f,0.874256f,-0.43258f, +0.337626f,0.867122f,-0.366208f, +0.351448f,0.893332f,-0.280076f, +0.206919f,0.931373f,-0.299548f, +0.143612f,0.950749f,-0.274684f, +0.0388897f,0.972032f,-0.231606f, +-0.0281782f,0.996586f,-0.077599f, +-0.0348963f,0.997716f,-0.0578427f, +-0.0315338f,0.968969f,-0.245163f, +0.0536322f,0.969299f,-0.239965f, +-0.0592746f,0.980608f,-0.186802f, +-0.146447f,0.958871f,-0.243144f, +-0.0489008f,0.966653f,-0.251379f, +-0.0921771f,0.973026f,-0.211482f, +-0.303489f,0.921788f,-0.24125f, +-0.360359f,0.892722f,-0.270533f, +-0.374413f,0.86994f,-0.320965f, +-0.420297f,0.839321f,-0.344805f, +-0.400389f,0.890168f,-0.217463f, +-0.5519f,0.817694f,-0.163655f, +-0.641175f,0.723209f,-0.25664f, +-0.591295f,0.757829f,-0.275801f, +-0.562781f,0.775127f,-0.287152f, +-0.492934f,0.830818f,-0.258375f, +-0.559738f,0.799568f,-0.21768f, +-0.572862f,0.78051f,-0.250266f, +-0.449965f,0.836305f,-0.31325f, +-0.485973f,0.815927f,-0.313197f, +-0.461831f,0.850292f,-0.252418f, +-0.261301f,0.911823f,-0.316702f, +-0.0988633f,0.911184f,-0.399961f, +-0.117544f,0.902602f,-0.414118f, +-0.193385f,0.896249f,-0.399173f, +-0.121448f,0.924471f,-0.361392f, +0.0924319f,0.986306f,-0.136592f, +0.0129691f,0.994218f,-0.106593f, +0.0478938f,0.996018f,-0.0752017f, +0.0322924f,0.95892f,-0.281832f, +0.0176709f,0.880909f,-0.472956f, +0.117774f,0.85642f,-0.502666f, +0.141956f,0.850649f,-0.506206f, +0.133057f,0.865588f,-0.482757f, +0.139695f,0.858438f,-0.493528f, +-0.227309f,0.878161f,0.420907f, +-0.208802f,0.809453f,0.548805f, +-0.283627f,0.767885f,0.574377f, +-0.166581f,0.77975f,0.603523f, +-0.0979994f,0.806409f,0.583181f, +-0.132228f,0.805326f,0.577898f, +-0.219374f,0.878043f,0.425342f, +-0.024745f,0.955845f,0.292828f, +0.235018f,0.923494f,0.303193f, +0.225806f,0.944421f,0.238915f, +0.125193f,0.981151f,0.147203f, +-0.0300197f,0.990754f,0.132305f, +-0.0418198f,0.992604f,0.113964f, +0.010498f,0.998335f,0.0567192f, +-0.187859f,0.981941f,-0.0223995f, +-0.164152f,0.985849f,-0.0340039f, +-0.00148231f,0.989313f,-0.145799f, +0.214865f,0.96059f,-0.176353f, +0.130927f,0.950976f,-0.280185f, +-0.0784848f,0.932131f,-0.353513f, +-0.05291f,0.922588f,-0.382142f, +0.16861f,0.90111f,-0.399463f, +0.291627f,0.864919f,-0.408495f, +0.209787f,0.830907f,-0.515347f, +0.211969f,0.855025f,-0.473287f, +0.179371f,0.927145f,-0.328982f, +0.0938016f,0.98223f,-0.162562f, +0.0948278f,0.994302f,-0.0487031f, +0.0439203f,0.998532f,-0.0316906f, +-0.0612398f,0.9958f,-0.0680553f, +0.0442323f,0.992295f,-0.115732f, +0.0938163f,0.983362f,-0.155559f, +-0.00984882f,0.984434f,-0.175479f, +-0.064778f,0.984002f,-0.165961f, +-0.129271f,0.96358f,-0.234101f, +-0.126642f,0.968315f,-0.215238f, +-0.066296f,0.988071f,-0.138997f, +-0.153283f,0.960153f,-0.233691f, +-0.288259f,0.887225f,-0.360193f, +-0.349196f,0.862768f,-0.365641f, +-0.457337f,0.833523f,-0.309971f, +-0.510223f,0.838902f,-0.189514f, +-0.576482f,0.813491f,-0.0768136f, +-0.627022f,0.773599f,-0.0915885f, +-0.562811f,0.806938f,-0.179152f, +-0.554556f,0.77173f,-0.31129f, +-0.544029f,0.784112f,-0.298665f, +-0.593089f,0.773019f,-0.225135f, +-0.565758f,0.788678f,-0.240633f, +-0.424914f,0.871459f,-0.244963f, +-0.461935f,0.845882f,-0.266647f, +-0.437432f,0.833935f,-0.336461f, +-0.166572f,0.89804f,-0.407159f, +-0.027465f,0.893903f,-0.447419f, +-0.142495f,0.890824f,-0.431426f, +-0.254187f,0.896659f,-0.36248f, +-0.245781f,0.925153f,-0.289282f, +-0.124728f,0.970098f,-0.208211f, +0.0496061f,0.995502f,-0.0807218f, +0.134453f,0.977049f,-0.165221f, +0.178593f,0.948688f,-0.260952f, +0.203783f,0.948389f,-0.242962f, +0.169172f,0.89845f,-0.405178f, +0.129822f,0.855112f,-0.501925f, +0.114157f,0.849198f,-0.515587f, +0.207913f,0.855521f,-0.47419f, +-0.447508f,0.787815f,0.423184f, +-0.372189f,0.752087f,0.543911f, +-0.298757f,0.721076f,0.625135f, +-0.109779f,0.732409f,0.671956f, +-0.05023f,0.773443f,0.631872f, +-0.0721375f,0.784971f,0.615319f, +0.0161123f,0.834678f,0.550503f, +0.0881584f,0.925537f,0.368252f, +0.194291f,0.939133f,0.283338f, +0.290284f,0.915951f,0.277072f, +0.206501f,0.959193f,0.193147f, +0.0129994f,0.989588f,0.143339f, +-0.0515539f,0.993638f,0.100126f, +0.0752528f,0.992857f,0.0925807f, +-0.11243f,0.993659f,-0.00132253f, +-0.0900456f,0.995381f,-0.0332891f, +0.0735618f,0.988585f,-0.131483f, +0.187914f,0.97058f,-0.150539f, +0.259537f,0.959521f,-0.109363f, +0.039582f,0.950958f,-0.306778f, +0.0151247f,0.899216f,-0.437243f, +0.157602f,0.861329f,-0.482984f, +0.313265f,0.852495f,-0.41847f, +0.26241f,0.877515f,-0.401384f, +0.106606f,0.940488f,-0.322671f, +0.0451106f,0.964729f,-0.259351f, +-0.0198008f,0.966294f,-0.256677f, +0.0415355f,0.979836f,-0.195439f, +0.019077f,0.98811f,-0.15256f, +0.00843283f,0.995377f,-0.095676f, +0.0813095f,0.98616f,-0.14449f, +0.0601215f,0.98288f,-0.174159f, +0.0231889f,0.98066f,-0.194342f, +-0.0257967f,0.969536f,-0.243588f, +-0.0655874f,0.972755f,-0.222364f, +-0.116074f,0.960607f,-0.252509f, +-0.11539f,0.952331f,-0.282402f, +-0.0547002f,0.971779f,-0.229464f, +-0.238443f,0.921749f,-0.305817f, +-0.409013f,0.87493f,-0.259242f, +-0.537403f,0.830349f,-0.147369f, +-0.604026f,0.794872f,-0.0577237f, +-0.636334f,0.771366f,0.00856593f, +-0.598176f,0.796287f,0.0900769f, +-0.445184f,0.894265f,0.0458439f, +-0.510078f,0.851049f,-0.124644f, +-0.584904f,0.80616f,-0.0894032f, +-0.566358f,0.809139f,-0.156631f, +-0.526778f,0.78194f,-0.333278f, +-0.411595f,0.815587f,-0.406703f, +-0.430581f,0.806825f,-0.404517f, +-0.346574f,0.828739f,-0.439406f, +-0.163187f,0.84355f,-0.511658f, +-0.120565f,0.900123f,-0.41862f, +-0.22033f,0.94784f,-0.230335f, +-0.354954f,0.922144f,-0.15381f, +-0.229701f,0.962171f,-0.146509f, +-0.156358f,0.938689f,-0.30727f, +-0.0202846f,0.954287f,-0.298202f, +0.237025f,0.938874f,-0.24967f, +0.153523f,0.923965f,-0.350312f, +0.146234f,0.948682f,-0.280389f, +0.334575f,0.915861f,-0.221942f, +0.32488f,0.905199f,-0.273985f, +0.124349f,0.918374f,-0.375668f, +0.0853809f,0.932635f,-0.350575f, +-0.326098f,0.745953f,0.580702f, +-0.408924f,0.742079f,0.53113f, +-0.380928f,0.732802f,0.563822f, +-0.135265f,0.771831f,0.621274f, +0.0172939f,0.791015f,0.611552f, +-0.0321407f,0.821651f,0.569084f, +0.110827f,0.821493f,0.559345f, +0.260047f,0.831043f,0.491674f, +0.30077f,0.882298f,0.362061f, +0.33436f,0.910333f,0.243922f, +0.27591f,0.939307f,0.203903f, +0.0278945f,0.981912f,0.18727f, +-0.00885636f,0.980185f,0.197887f, +0.145141f,0.978135f,0.148949f, +-0.0144219f,0.999761f,0.0164012f, +-0.0725846f,0.989236f,-0.127057f, +0.156537f,0.975005f,-0.157677f, +0.153594f,0.966224f,-0.206929f, +0.277291f,0.95249f,-0.125986f, +0.254121f,0.951784f,-0.171844f, +0.192884f,0.934802f,-0.298229f, +0.176671f,0.893747f,-0.412315f, +0.195208f,0.917965f,-0.345303f, +0.157451f,0.974963f,-0.157023f, +0.0279983f,0.991052f,-0.13051f, +0.088609f,0.976865f,-0.194637f, +0.0507072f,0.953301f,-0.297735f, +-0.0277167f,0.944799f,-0.326477f, +-0.027462f,0.967827f,-0.250115f, +-0.0885824f,0.972427f,-0.215728f, +0.0938124f,0.990405f,-0.101477f, +0.168783f,0.975825f,-0.138845f, +0.111665f,0.949064f,-0.294633f, +-0.0373777f,0.928827f,-0.368623f, +-0.132876f,0.934016f,-0.3316f, +-0.0938993f,0.959978f,-0.263865f, +-0.105226f,0.962669f,-0.249392f, +-0.104341f,0.966883f,-0.232916f, +-0.220802f,0.965347f,-0.13911f, +-0.478375f,0.876928f,-0.0464122f, +-0.604444f,0.796064f,0.0305022f, +-0.611643f,0.789038f,0.0575453f, +-0.651561f,0.758511f,-0.0113831f, +-0.622019f,0.781788f,-0.0435906f, +-0.406862f,0.913403f,-0.012587f, +-0.447294f,0.893518f,0.0394196f, +-0.595605f,0.801728f,0.049859f, +-0.453119f,0.890822f,0.0334497f, +-0.397535f,0.913376f,-0.0878049f, +-0.358743f,0.901381f,-0.242521f, +-0.368468f,0.876571f,-0.309604f, +-0.3524f,0.834147f,-0.42428f, +-0.221095f,0.907887f,-0.356171f, +-0.336012f,0.912731f,-0.232418f, +-0.365521f,0.924164f,-0.110978f, +-0.381997f,0.913352f,-0.140951f, +-0.128103f,0.980976f,-0.145863f, +0.0620369f,0.958271f,-0.279048f, +-0.0393717f,0.894694f,-0.44494f, +0.166576f,0.906235f,-0.388576f, +0.257306f,0.912784f,-0.317204f, +0.0500832f,0.912737f,-0.405466f, +0.219062f,0.950498f,-0.220374f, +0.303476f,0.949102f,-0.0843104f, +0.167756f,0.983709f,-0.0646101f, +-0.00137806f,0.991718f,-0.128423f, +-0.411803f,0.737245f,0.535619f, +-0.383529f,0.716567f,0.582612f, +-0.385829f,0.756694f,0.527779f, +-0.125894f,0.866623f,0.482821f, +0.0864817f,0.885592f,0.456341f, +0.0185611f,0.909875f,0.414467f, +0.0890012f,0.92755f,0.362947f, +0.3312f,0.85507f,0.39895f, +0.411118f,0.842585f,0.347898f, +0.395768f,0.87253f,0.286458f, +0.265631f,0.912624f,0.310738f, +0.0432866f,0.942781f,0.330591f, +-0.0291247f,0.959608f,0.279829f, +0.17674f,0.935093f,0.307187f, +0.194038f,0.946511f,0.25781f, +0.0938941f,0.995535f,0.00965941f, +0.2133f,0.967919f,-0.132802f, +0.174202f,0.951285f,-0.254382f, +0.185706f,0.942688f,-0.277223f, +0.254853f,0.951817f,-0.170569f, +0.272452f,0.946195f,-0.174599f, +0.236374f,0.944357f,-0.228728f, +0.0622104f,0.974295f,-0.216517f, +0.00421412f,0.994674f,-0.102989f, +0.150974f,0.988535f,0.00252771f, +0.198367f,0.972494f,-0.122094f, +0.128147f,0.983415f,-0.128347f, +0.00128047f,0.972843f,-0.231463f, +-0.0877992f,0.94046f,-0.328368f, +-0.123322f,0.945018f,-0.302876f, +0.0120775f,0.960206f,-0.279033f, +0.230563f,0.945381f,-0.230424f, +0.231597f,0.934072f,-0.271795f, +0.0492688f,0.934225f,-0.353265f, +-0.160672f,0.892999f,-0.4204f, +-0.160391f,0.913064f,-0.374951f, +-0.146451f,0.932705f,-0.329565f, +-0.203905f,0.952995f,-0.224107f, +-0.374034f,0.927408f,-0.00361175f, +-0.538909f,0.826945f,0.160435f, +-0.614792f,0.776175f,0.139939f, +-0.589081f,0.79961f,0.116649f, +-0.558852f,0.827241f,0.0579274f, +-0.582196f,0.802416f,-0.131063f, +-0.51435f,0.846005f,-0.140428f, +-0.52517f,0.850476f,0.0297862f, +-0.596917f,0.80173f,0.0303285f, +-0.476386f,0.879145f,0.0126877f, +-0.346071f,0.935165f,0.0755073f, +-0.29506f,0.953573f,0.0603189f, +-0.290873f,0.956376f,0.0271545f, +-0.342792f,0.934849f,-0.0924672f, +-0.36131f,0.919889f,-0.152511f, +-0.440677f,0.895263f,-0.0656364f, +-0.27224f,0.960453f,-0.0584458f, +-0.239345f,0.939791f,-0.243941f, +-0.184322f,0.924268f,-0.334296f, +0.170265f,0.967851f,-0.185131f, +0.0831722f,0.975078f,-0.205681f, +0.0764752f,0.962386f,-0.2607f, +0.25092f,0.948574f,-0.192995f, +-0.000511184f,0.983325f,-0.181855f, +0.00805518f,0.99922f,-0.0386666f, +0.231558f,0.969957f,0.0745867f, +0.213284f,0.97378f,0.0791335f, +0.134707f,0.990255f,0.0353415f, +-0.461887f,0.727903f,0.506772f, +-0.409704f,0.769768f,0.48949f, +-0.245031f,0.85373f,0.459461f, +-0.000652498f,0.933053f,0.359739f, +0.0977619f,0.940993f,0.323999f, +0.0976539f,0.925223f,0.366641f, +0.122528f,0.958779f,0.256377f, +0.300256f,0.92807f,0.220301f, +0.434057f,0.868364f,0.239872f, +0.373936f,0.875783f,0.305249f, +0.188752f,0.892291f,0.41011f, +0.0749298f,0.875078f,0.478146f, +0.0539526f,0.905587f,0.420716f, +0.139771f,0.930537f,0.338475f, +0.252071f,0.902374f,0.349544f, +0.271241f,0.91149f,0.309214f, +0.343876f,0.91657f,0.204082f, +0.324141f,0.940857f,0.098591f, +0.18373f,0.982977f,-0.000581414f, +0.215424f,0.976468f,-0.0101277f, +0.272942f,0.961141f,-0.0413737f, +0.263192f,0.964688f,-0.010384f, +0.0834313f,0.988492f,-0.126183f, +-0.0244777f,0.972824f,-0.230248f, +0.037395f,0.972598f,-0.229465f, +0.188221f,0.98005f,-0.0638298f, +0.133895f,0.99093f,-0.0113778f, +0.15553f,0.985289f,-0.0708293f, +0.062154f,0.97927f,-0.19279f, +-0.0906565f,0.929896f,-0.356476f, +-0.00537849f,0.905315f,-0.424706f, +0.162604f,0.918237f,-0.361109f, +0.211297f,0.942163f,-0.260159f, +0.166674f,0.959094f,-0.22882f, +-0.0900843f,0.919646f,-0.382278f, +-0.185542f,0.891522f,-0.413234f, +-0.236454f,0.911319f,-0.337026f, +-0.404129f,0.904849f,-0.133894f, +-0.540771f,0.839361f,0.0551279f, +-0.598434f,0.794978f,0.0994372f, +-0.56944f,0.810652f,0.136315f, +-0.572323f,0.818089f,0.0563579f, +-0.472334f,0.880613f,0.0376913f, +-0.539685f,0.840552f,-0.0470301f, +-0.574258f,0.816988f,0.0525225f, +-0.582793f,0.802613f,0.127141f, +-0.577964f,0.810669f,0.0936681f, +-0.453297f,0.886551f,0.0924669f, +-0.392456f,0.918879f,0.0405067f, +-0.316387f,0.94595f,0.0712573f, +-0.278453f,0.953269f,0.117224f, +-0.268053f,0.957793f,0.103824f, +-0.307148f,0.94927f,0.0674248f, +-0.42059f,0.907249f,-0.00173726f, +-0.259446f,0.962613f,-0.0778756f, +-0.0851837f,0.992966f,-0.082236f, +-0.215247f,0.960313f,-0.177393f, +-0.0219544f,0.989556f,-0.14247f, +0.0391647f,0.99769f,-0.0555004f, +0.102045f,0.994433f,0.0262785f, +0.194292f,0.978837f,0.0642512f, +-0.0292693f,0.988875f,0.145839f, +-0.101853f,0.986247f,0.130166f, +0.212882f,0.964861f,0.15403f, +0.245798f,0.960888f,0.127587f, +0.195444f,0.974318f,0.111832f, +-0.321858f,0.809731f,0.490656f, +-0.324834f,0.8531f,0.408293f, +-0.169338f,0.931652f,0.321478f, +0.0137661f,0.965459f,0.260189f, +0.0568655f,0.931751f,0.358619f, +0.0773718f,0.91837f,0.388084f, +0.261047f,0.911575f,0.317625f, +0.360487f,0.919759f,0.155217f, +0.377368f,0.917164f,0.128078f, +0.276887f,0.917903f,0.284232f, +0.0739314f,0.913495f,0.400076f, +0.00592871f,0.863726f,0.503926f, +0.12818f,0.830694f,0.541773f, +0.218813f,0.849726f,0.479673f, +0.242686f,0.877276f,0.414115f, +0.274843f,0.886896f,0.371318f, +0.349234f,0.864992f,0.360313f, +0.316807f,0.866747f,0.385206f, +0.243026f,0.8884f,0.389467f, +0.293176f,0.904042f,0.311057f, +0.24905f,0.947495f,0.200568f, +0.307601f,0.926121f,0.21836f, +0.250581f,0.964737f,0.0805682f, +0.134636f,0.99035f,-0.0328548f, +0.000251354f,0.985828f,-0.167762f, +0.0218107f,0.990992f,-0.132131f, +0.159951f,0.984761f,-0.068279f, +0.165852f,0.977778f,-0.128229f, +0.162621f,0.98447f,-0.06613f, +0.121502f,0.975682f,-0.182435f, +0.0565286f,0.935574f,-0.348576f, +0.0461029f,0.9227f,-0.382752f, +0.0939341f,0.947555f,-0.305477f, +0.144515f,0.970016f,-0.195409f, +0.0775217f,0.989125f,-0.124991f, +-0.200827f,0.965332f,-0.16674f, +-0.401609f,0.907839f,-0.120577f, +-0.559375f,0.828885f,-0.00699655f, +-0.565805f,0.821746f,0.0678162f, +-0.593147f,0.804311f,0.0354918f, +-0.576294f,0.817225f,0.00543077f, +-0.525544f,0.848999f,-0.0548173f, +-0.499547f,0.863338f,-0.0714126f, +-0.553806f,0.830814f,0.0551944f, +-0.639015f,0.755184f,0.146141f, +-0.555848f,0.812796f,0.174341f, +-0.558245f,0.826947f,0.0672363f, +-0.433561f,0.898303f,0.0712505f, +-0.328723f,0.942541f,0.0596481f, +-0.348698f,0.936876f,0.0259581f, +-0.301092f,0.95068f,0.0745005f, +-0.263015f,0.962594f,0.0650869f, +-0.284818f,0.957539f,0.0446894f, +-0.359379f,0.932627f,-0.032449f, +-0.231945f,0.967322f,-0.102417f, +-0.134462f,0.989922f,-0.0444264f, +-0.162306f,0.986023f,0.0376183f, +0.00794699f,0.998548f,-0.0532871f, +-0.0239448f,0.993657f,-0.109874f, +-0.0216422f,0.99782f,0.0623378f, +0.109723f,0.978713f,0.173443f, +-0.0637399f,0.980084f,0.188075f, +-0.0488189f,0.981371f,0.185814f, +0.215314f,0.95546f,0.201833f, +0.226954f,0.944659f,0.236876f, +0.18874f,0.93582f,0.297688f, +-0.35388f,0.863488f,0.359384f, +-0.279389f,0.900607f,0.332938f, +-0.0980507f,0.952584f,0.288043f, +-0.0324622f,0.946395f,0.321377f, +-0.0380375f,0.913004f,0.406173f, +0.128955f,0.929408f,0.345792f, +0.375928f,0.898621f,0.226181f, +0.446257f,0.883274f,0.143813f, +0.289683f,0.938589f,0.187442f, +0.125289f,0.928145f,0.350499f, +-0.0288389f,0.895239f,0.444652f, +-0.103894f,0.871209f,0.479793f, +0.105997f,0.859294f,0.500378f, +0.239743f,0.842088f,0.483127f, +0.302444f,0.818919f,0.48775f, +0.351983f,0.830309f,0.432082f, +0.318807f,0.868172f,0.380315f, +0.306771f,0.857612f,0.412787f, +0.273726f,0.881543f,0.384651f, +0.337032f,0.866043f,0.369295f, +0.363605f,0.874829f,0.320103f, +0.334634f,0.927168f,0.168463f, +0.372292f,0.916204f,0.148217f, +0.206342f,0.978274f,0.0200943f, +0.119354f,0.989819f,-0.077546f, +0.042858f,0.974765f,-0.21908f, +0.15227f,0.956258f,-0.24977f, +0.17642f,0.955622f,-0.235928f, +0.119264f,0.963567f,-0.239406f, +0.210452f,0.949288f,-0.233584f, +0.171674f,0.93622f,-0.306626f, +0.0511268f,0.942128f,-0.331333f, +0.00960037f,0.978635f,-0.205381f, +-0.00181509f,0.99884f,-0.048118f, +-0.0483779f,0.993619f,0.101885f, +-0.221067f,0.964285f,0.145887f, +-0.435375f,0.898142f,0.0615596f, +-0.544434f,0.838804f,-0.00062539f, +-0.579913f,0.810216f,-0.0851529f, +-0.5726f,0.815766f,-0.0815813f, +-0.546649f,0.832873f,-0.0865884f, +-0.465735f,0.88205f,-0.071268f, +-0.55864f,0.824018f,-0.0944285f, +-0.642115f,0.765228f,0.0459774f, +-0.656804f,0.753752f,0.0216163f, +-0.520592f,0.853762f,0.00863503f, +-0.481258f,0.875004f,-0.0525228f, +-0.443379f,0.889071f,-0.113874f, +-0.339817f,0.937077f,-0.0800719f, +-0.346478f,0.935462f,-0.0697409f, +-0.350474f,0.934462f,-0.0628307f, +-0.228751f,0.97348f,-0.00313391f, +-0.230759f,0.970493f,-0.0699589f, +-0.279469f,0.954379f,-0.105155f, +-0.198889f,0.96686f,-0.16008f, +-0.230529f,0.946681f,-0.225058f, +-0.14204f,0.970201f,-0.196301f, +0.0687794f,0.962113f,-0.263834f, +-0.0677159f,0.979986f,-0.187196f, +-0.220027f,0.972288f,-0.0790245f, +0.07326f,0.993712f,0.0846721f, +-0.0289367f,0.993146f,0.113239f, +-0.106822f,0.986395f,0.124957f, +0.128381f,0.967004f,0.22005f, +0.141757f,0.945235f,0.293998f, +0.0274083f,0.95189f,0.30521f, +-0.150915f,0.940582f,0.304189f, +-0.174369f,0.970549f,0.166222f, +-0.140821f,0.979995f,0.140639f, +-0.141606f,0.959082f,0.245171f, +0.011894f,0.972798f,0.23135f, +0.262326f,0.961504f,0.0818187f, +0.456393f,0.889018f,0.036791f, +0.382632f,0.920315f,0.0813253f, +0.174752f,0.942069f,0.286301f, +-0.045852f,0.917014f,0.396211f, +-0.0633233f,0.882412f,0.466197f, +-0.0422981f,0.919143f,0.391647f, +0.126089f,0.949054f,0.288786f, +0.256733f,0.912921f,0.317275f, +0.315104f,0.887032f,0.337468f, +0.409846f,0.864148f,0.292018f, +0.343944f,0.901166f,0.263823f, +0.312798f,0.897029f,0.312244f, +0.323227f,0.888441f,0.325879f, +0.342446f,0.89904f,0.272869f, +0.451059f,0.860524f,0.236736f, +0.423682f,0.891569f,0.159992f, +0.404089f,0.899665f,0.165275f, +0.34072f,0.934631f,0.101855f, +0.255675f,0.966712f,-0.00994645f, +0.192495f,0.972523f,-0.130939f, +0.146493f,0.95759f,-0.248115f, +0.177747f,0.950895f,-0.253387f, +0.10258f,0.958737f,-0.265144f, +0.233714f,0.956929f,-0.172236f, +0.223818f,0.95591f,-0.190111f, +-0.0753718f,0.974181f,-0.212814f, +-0.223858f,0.97386f,-0.0385406f, +-0.201603f,0.967155f,0.154817f, +-0.110966f,0.95618f,0.270934f, +-0.121146f,0.966863f,0.224722f, +-0.291476f,0.94891f,0.120877f, +-0.477923f,0.877529f,-0.0391374f, +-0.509066f,0.849204f,-0.140369f, +-0.547573f,0.807834f,-0.218101f, +-0.563212f,0.785973f,-0.255028f, +-0.550783f,0.817799f,-0.166865f, +-0.567941f,0.823056f,0.00472398f, +-0.662541f,0.748994f,-0.00687841f, +-0.61971f,0.78387f,-0.03883f, +-0.523314f,0.847679f,-0.0870804f, +-0.447797f,0.889814f,-0.0877948f, +-0.443749f,0.888577f,-0.116264f, +-0.376466f,0.920201f,-0.107257f, +-0.337652f,0.938208f,-0.0758775f, +-0.365552f,0.926461f,-0.0896778f, +-0.259904f,0.962681f,-0.0754604f, +-0.126151f,0.988548f,-0.0828222f, +-0.30144f,0.926166f,-0.226606f, +-0.124801f,0.973148f,-0.193411f, +-0.0842547f,0.941418f,-0.326548f, +-0.0799027f,0.902475f,-0.423267f, +-0.00736616f,0.932864f,-0.360152f, +-0.199402f,0.957181f,-0.209865f, +-0.285967f,0.938676f,-0.192641f, +-0.0884894f,0.987166f,-0.132941f, +-0.0982017f,0.994337f,0.0406204f, +-0.151395f,0.982648f,0.107153f, +0.0310104f,0.988838f,0.14573f, +0.106405f,0.964191f,0.242925f, +0.070474f,0.952157f,0.297374f, +0.0656706f,0.9919f,0.108725f, +-0.0894851f,0.995828f,0.0178395f, +-0.190523f,0.981135f,0.0327999f, +-0.155304f,0.987556f,0.0247798f, +0.115224f,0.991572f,-0.0592235f, +0.36579f,0.920032f,-0.140496f, +0.356271f,0.926984f,-0.117348f, +0.248335f,0.959842f,0.130508f, +0.000801886f,0.966476f,0.256755f, +-0.114974f,0.940419f,0.319989f, +-0.0524682f,0.940494f,0.335734f, +0.129742f,0.951002f,0.280646f, +0.183656f,0.974747f,0.127042f, +0.210533f,0.964529f,0.159247f, +0.299776f,0.935816f,0.185429f, +0.476652f,0.857927f,0.191739f, +0.365421f,0.920615f,0.137608f, +0.247354f,0.961561f,0.119232f, +0.333488f,0.932256f,0.140299f, +0.428629f,0.898219f,0.0973634f, +0.470887f,0.881687f,0.0298847f, +0.443595f,0.892268f,0.0841461f, +0.38152f,0.920309f,0.0864469f, +0.381462f,0.916941f,0.117074f, +0.327497f,0.93955f,0.099957f, +0.304803f,0.952409f,-0.00357992f, +0.239937f,0.959204f,-0.149528f, +0.202117f,0.965308f,-0.165315f, +0.0495866f,0.988011f,-0.146203f, +0.0854477f,0.995976f,-0.027023f, +0.244078f,0.956317f,0.160886f, +-0.0753613f,0.986424f,0.145905f, +-0.339089f,0.932874f,0.12151f, +-0.294837f,0.942606f,0.15673f, +-0.104304f,0.973462f,0.203698f, +-0.0723227f,0.985619f,0.152724f, +-0.210009f,0.973927f,0.0858055f, +-0.391811f,0.919671f,-0.0262484f, +-0.442429f,0.895892f,-0.0404195f, +-0.501975f,0.857758f,-0.11078f, +-0.516547f,0.834688f,-0.190982f, +-0.606461f,0.747704f,-0.270451f, +-0.650373f,0.745527f,-0.145618f, +-0.638901f,0.762805f,-0.0996673f, +-0.598555f,0.785548f,-0.156994f, +-0.501024f,0.846694f,-0.179123f, +-0.446137f,0.875545f,-0.185426f, +-0.431282f,0.886668f,-0.16678f, +-0.409115f,0.903871f,-0.125073f, +-0.364534f,0.929271f,-0.0597475f, +-0.342967f,0.93838f,-0.0426101f, +-0.26831f,0.95962f,-0.0844963f, +-0.0393852f,0.992201f,-0.118264f, +-0.116204f,0.958118f,-0.261737f, +-0.10396f,0.911216f,-0.398596f, +0.0690263f,0.90803f,-0.41318f, +-0.107766f,0.879323f,-0.463872f, +-0.204112f,0.904181f,-0.375227f, +-0.300499f,0.93243f,-0.200683f, +-0.27347f,0.953749f,-0.124807f, +-0.169754f,0.978593f,-0.116359f, +-0.231778f,0.970053f,-0.072634f, +-0.190395f,0.98166f,0.00964305f, +-0.0305984f,0.996687f,0.0753532f, +0.015862f,0.984083f,0.177002f, +-0.0353434f,0.980638f,0.192612f, +-0.00358253f,0.996067f,-0.0885361f, +-0.091201f,0.995656f,-0.0187243f, +-0.182622f,0.982071f,0.0467509f, +-0.0739202f,0.997106f,-0.017751f, +0.154438f,0.971547f,-0.179571f, +0.395535f,0.904532f,-0.159291f, +0.194508f,0.960754f,-0.197781f, +0.113269f,0.98581f,0.123894f, +-0.030891f,0.963944f,0.264306f, +-0.124571f,0.959262f,0.253572f, +-0.0553429f,0.968125f,0.244277f, +0.192328f,0.950681f,0.243343f, +0.217769f,0.968216f,0.123025f, +0.205296f,0.966103f,0.156522f, +0.276023f,0.954237f,0.11508f, +0.467224f,0.868183f,0.167212f, +0.402263f,0.894308f,0.195955f, +0.299601f,0.940084f,0.162733f, +0.355906f,0.933872f,0.0348486f, +0.474044f,0.880198f,-0.0230946f, +0.444725f,0.891474f,-0.0865651f, +0.431452f,0.901988f,0.0163334f, +0.385491f,0.922676f,0.00810292f, +0.339313f,0.940655f,0.00595024f, +0.37483f,0.92173f,0.099581f, +0.41171f,0.911266f,-0.00949356f, +0.281208f,0.933096f,-0.224175f, +0.138066f,0.959634f,-0.245031f, +0.0299217f,0.992057f,-0.122182f, +-0.0797424f,0.99128f,-0.104905f, +0.124146f,0.977522f,0.170405f, +-0.0302976f,0.947743f,0.317594f, +-0.301142f,0.928457f,0.21744f, +-0.278579f,0.94845f,0.151119f, +-0.150217f,0.982764f,0.107745f, +0.0163995f,0.982022f,0.188052f, +-0.137431f,0.989816f,0.0370977f, +-0.36652f,0.926186f,-0.0885568f, +-0.445397f,0.895157f,-0.0177851f, +-0.463397f,0.885777f,-0.0257252f, +-0.466469f,0.878885f,-0.099842f, +-0.557948f,0.804805f,-0.202443f, +-0.681509f,0.679149f,-0.272587f, +-0.629296f,0.753928f,-0.188625f, +-0.5596f,0.798482f,-0.221976f, +-0.503025f,0.800303f,-0.326313f, +-0.422254f,0.855253f,-0.300408f, +-0.454716f,0.829192f,-0.325075f, +-0.46025f,0.856807f,-0.232488f, +-0.37729f,0.921922f,-0.0878209f, +-0.375084f,0.920087f,-0.112928f, +-0.173161f,0.984659f,-0.0214944f, +-0.0348229f,0.978528f,-0.20315f, +0.0523603f,0.977312f,-0.205229f, +-0.0533357f,0.893335f,-0.446215f, +0.0246713f,0.873256f,-0.486637f, +-0.0923807f,0.905308f,-0.414587f, +-0.269958f,0.871402f,-0.409612f, +-0.388686f,0.862358f,-0.324442f, +-0.340148f,0.928537f,-0.148722f, +-0.147166f,0.988619f,-0.0312327f, +-0.248059f,0.963625f,-0.099463f, +-0.232297f,0.969578f,-0.0771772f, +-0.142695f,0.989498f,-0.02308f, +-0.0198137f,0.98287f,0.18323f, +-0.0333475f,0.978727f,0.202438f, +}; + +btScalar Landscape05Tex[] = { +0.0f,0.5f, +0.0f,0.492188f, +0.0078125f,0.5f, +0.0078125f,0.492188f, +0.015625f,0.5f, +0.015625f,0.492188f, +0.0234375f,0.5f, +0.0234375f,0.492188f, +0.03125f,0.5f, +0.03125f,0.492188f, +0.0390625f,0.5f, +0.0390625f,0.492188f, +0.046875f,0.5f, +0.046875f,0.492188f, +0.0546875f,0.5f, +0.0546875f,0.492188f, +0.0625f,0.5f, +0.0625f,0.492188f, +0.0703125f,0.5f, +0.0703125f,0.492188f, +0.078125f,0.5f, +0.078125f,0.492188f, +0.0859375f,0.5f, +0.0859375f,0.492188f, +0.09375f,0.5f, +0.09375f,0.492188f, +0.101563f,0.5f, +0.101563f,0.492188f, +0.109375f,0.5f, +0.109375f,0.492188f, +0.117188f,0.5f, +0.117188f,0.492188f, +0.125f,0.5f, +0.125f,0.492188f, +0.132813f,0.5f, +0.132813f,0.492188f, +0.140625f,0.5f, +0.140625f,0.492188f, +0.148438f,0.5f, +0.148438f,0.492188f, +0.15625f,0.5f, +0.15625f,0.492188f, +0.164063f,0.5f, +0.164063f,0.492188f, +0.171875f,0.5f, +0.171875f,0.492188f, +0.179688f,0.5f, +0.179688f,0.492188f, +0.1875f,0.5f, +0.1875f,0.492188f, +0.195313f,0.5f, +0.195313f,0.492188f, +0.203125f,0.5f, +0.203125f,0.492188f, +0.210938f,0.5f, +0.210938f,0.492188f, +0.21875f,0.5f, +0.21875f,0.492188f, +0.226563f,0.5f, +0.226563f,0.492188f, +0.234375f,0.5f, +0.234375f,0.492188f, +0.242188f,0.5f, +0.242188f,0.492188f, +0.25f,0.5f, +0.25f,0.492188f, +0.257813f,0.5f, +0.257813f,0.492188f, +0.265625f,0.5f, +0.265625f,0.492188f, +0.273438f,0.5f, +0.273438f,0.492188f, +0.28125f,0.5f, +0.28125f,0.492188f, +0.289063f,0.5f, +0.289063f,0.492188f, +0.296875f,0.5f, +0.296875f,0.492188f, +0.304688f,0.5f, +0.304688f,0.492188f, +0.3125f,0.5f, +0.3125f,0.492188f, +0.320313f,0.5f, +0.320313f,0.492188f, +0.328125f,0.5f, +0.328125f,0.492188f, +0.335938f,0.5f, +0.335938f,0.492188f, +0.34375f,0.5f, +0.34375f,0.492188f, +0.351563f,0.5f, +0.351563f,0.492188f, +0.359375f,0.5f, +0.359375f,0.492188f, +0.367188f,0.5f, +0.367188f,0.492188f, +0.375f,0.5f, +0.375f,0.492188f, +0.382813f,0.5f, +0.382813f,0.492188f, +0.390625f,0.5f, +0.390625f,0.492188f, +0.398438f,0.5f, +0.398438f,0.492188f, +0.40625f,0.5f, +0.40625f,0.492188f, +0.414063f,0.5f, +0.414063f,0.492188f, +0.421875f,0.5f, +0.421875f,0.492188f, +0.429688f,0.5f, +0.429688f,0.492188f, +0.4375f,0.5f, +0.4375f,0.492188f, +0.445313f,0.5f, +0.445313f,0.492188f, +0.453125f,0.5f, +0.453125f,0.492188f, +0.460938f,0.5f, +0.460938f,0.492188f, +0.46875f,0.5f, +0.46875f,0.492188f, +0.476563f,0.5f, +0.476563f,0.492188f, +0.484375f,0.5f, +0.484375f,0.492188f, +0.492188f,0.5f, +0.492188f,0.492188f, +0.5f,0.5f, +0.5f,0.492188f, +0.507813f,0.5f, +0.507813f,0.492188f, +0.0f,0.507813f, +0.0078125f,0.507813f, +0.015625f,0.507813f, +0.0234375f,0.507813f, +0.03125f,0.507813f, +0.0390625f,0.507813f, +0.046875f,0.507813f, +0.0546875f,0.507813f, +0.0625f,0.507813f, +0.0703125f,0.507813f, +0.078125f,0.507813f, +0.0859375f,0.507813f, +0.09375f,0.507813f, +0.101563f,0.507813f, +0.109375f,0.507813f, +0.117188f,0.507813f, +0.125f,0.507813f, +0.132813f,0.507813f, +0.140625f,0.507813f, +0.148438f,0.507813f, +0.15625f,0.507813f, +0.164063f,0.507813f, +0.171875f,0.507813f, +0.179688f,0.507813f, +0.1875f,0.507813f, +0.195313f,0.507813f, +0.203125f,0.507813f, +0.210938f,0.507813f, +0.21875f,0.507813f, +0.226563f,0.507813f, +0.234375f,0.507813f, +0.242188f,0.507813f, +0.25f,0.507813f, +0.257813f,0.507813f, +0.265625f,0.507813f, +0.273438f,0.507813f, +0.28125f,0.507813f, +0.289063f,0.507813f, +0.296875f,0.507813f, +0.304688f,0.507813f, +0.3125f,0.507813f, +0.320313f,0.507813f, +0.328125f,0.507813f, +0.335938f,0.507813f, +0.34375f,0.507813f, +0.351563f,0.507813f, +0.359375f,0.507813f, +0.367188f,0.507813f, +0.375f,0.507813f, +0.382813f,0.507813f, +0.390625f,0.507813f, +0.398438f,0.507813f, +0.40625f,0.507813f, +0.414063f,0.507813f, +0.421875f,0.507813f, +0.429688f,0.507813f, +0.4375f,0.507813f, +0.445313f,0.507813f, +0.453125f,0.507813f, +0.460938f,0.507813f, +0.46875f,0.507813f, +0.476563f,0.507813f, +0.484375f,0.507813f, +0.492188f,0.507813f, +0.5f,0.507813f, +0.507813f,0.507813f, +0.0f,0.515625f, +0.0078125f,0.515625f, +0.015625f,0.515625f, +0.0234375f,0.515625f, +0.03125f,0.515625f, +0.0390625f,0.515625f, +0.046875f,0.515625f, +0.0546875f,0.515625f, +0.0625f,0.515625f, +0.0703125f,0.515625f, +0.078125f,0.515625f, +0.0859375f,0.515625f, +0.09375f,0.515625f, +0.101563f,0.515625f, +0.109375f,0.515625f, +0.117188f,0.515625f, +0.125f,0.515625f, +0.132813f,0.515625f, +0.140625f,0.515625f, +0.148438f,0.515625f, +0.15625f,0.515625f, +0.164063f,0.515625f, +0.171875f,0.515625f, +0.179688f,0.515625f, +0.1875f,0.515625f, +0.195313f,0.515625f, +0.203125f,0.515625f, +0.210938f,0.515625f, +0.21875f,0.515625f, +0.226563f,0.515625f, +0.234375f,0.515625f, +0.242188f,0.515625f, +0.25f,0.515625f, +0.257813f,0.515625f, +0.265625f,0.515625f, +0.273438f,0.515625f, +0.28125f,0.515625f, +0.289063f,0.515625f, +0.296875f,0.515625f, +0.304688f,0.515625f, +0.3125f,0.515625f, +0.320313f,0.515625f, +0.328125f,0.515625f, +0.335938f,0.515625f, +0.34375f,0.515625f, +0.351563f,0.515625f, +0.359375f,0.515625f, +0.367188f,0.515625f, +0.375f,0.515625f, +0.382813f,0.515625f, +0.390625f,0.515625f, +0.398438f,0.515625f, +0.40625f,0.515625f, +0.414063f,0.515625f, +0.421875f,0.515625f, +0.429688f,0.515625f, +0.4375f,0.515625f, +0.445313f,0.515625f, +0.453125f,0.515625f, +0.460938f,0.515625f, +0.46875f,0.515625f, +0.476563f,0.515625f, +0.484375f,0.515625f, +0.492188f,0.515625f, +0.5f,0.515625f, +0.507813f,0.515625f, +0.0f,0.523438f, +0.0078125f,0.523438f, +0.015625f,0.523438f, +0.0234375f,0.523438f, +0.03125f,0.523438f, +0.0390625f,0.523438f, +0.046875f,0.523438f, +0.0546875f,0.523438f, +0.0625f,0.523438f, +0.0703125f,0.523438f, +0.078125f,0.523438f, +0.0859375f,0.523438f, +0.09375f,0.523438f, +0.101563f,0.523438f, +0.109375f,0.523438f, +0.117188f,0.523438f, +0.125f,0.523438f, +0.132813f,0.523438f, +0.140625f,0.523438f, +0.148438f,0.523438f, +0.15625f,0.523438f, +0.164063f,0.523438f, +0.171875f,0.523438f, +0.179688f,0.523438f, +0.1875f,0.523438f, +0.195313f,0.523438f, +0.203125f,0.523438f, +0.210938f,0.523438f, +0.21875f,0.523438f, +0.226563f,0.523438f, +0.234375f,0.523438f, +0.242188f,0.523438f, +0.25f,0.523438f, +0.257813f,0.523438f, +0.265625f,0.523438f, +0.273438f,0.523438f, +0.28125f,0.523438f, +0.289063f,0.523438f, +0.296875f,0.523438f, +0.304688f,0.523438f, +0.3125f,0.523438f, +0.320313f,0.523438f, +0.328125f,0.523438f, +0.335938f,0.523438f, +0.34375f,0.523438f, +0.351563f,0.523438f, +0.359375f,0.523438f, +0.367188f,0.523438f, +0.375f,0.523438f, +0.382813f,0.523438f, +0.390625f,0.523438f, +0.398438f,0.523438f, +0.40625f,0.523438f, +0.414063f,0.523438f, +0.421875f,0.523438f, +0.429688f,0.523438f, +0.4375f,0.523438f, +0.445313f,0.523438f, +0.453125f,0.523438f, +0.460938f,0.523438f, +0.46875f,0.523438f, +0.476563f,0.523438f, +0.484375f,0.523438f, +0.492188f,0.523438f, +0.5f,0.523438f, +0.507813f,0.523438f, +0.0f,0.53125f, +0.0078125f,0.53125f, +0.015625f,0.53125f, +0.0234375f,0.53125f, +0.03125f,0.53125f, +0.0390625f,0.53125f, +0.046875f,0.53125f, +0.0546875f,0.53125f, +0.0625f,0.53125f, +0.0703125f,0.53125f, +0.078125f,0.53125f, +0.0859375f,0.53125f, +0.09375f,0.53125f, +0.101563f,0.53125f, +0.109375f,0.53125f, +0.117188f,0.53125f, +0.125f,0.53125f, +0.132813f,0.53125f, +0.140625f,0.53125f, +0.148438f,0.53125f, +0.15625f,0.53125f, +0.164063f,0.53125f, +0.171875f,0.53125f, +0.179688f,0.53125f, +0.1875f,0.53125f, +0.195313f,0.53125f, +0.203125f,0.53125f, +0.210938f,0.53125f, +0.21875f,0.53125f, +0.226563f,0.53125f, +0.234375f,0.53125f, +0.242188f,0.53125f, +0.25f,0.53125f, +0.257813f,0.53125f, +0.265625f,0.53125f, +0.273438f,0.53125f, +0.28125f,0.53125f, +0.289063f,0.53125f, +0.296875f,0.53125f, +0.304688f,0.53125f, +0.3125f,0.53125f, +0.320313f,0.53125f, +0.328125f,0.53125f, +0.335938f,0.53125f, +0.34375f,0.53125f, +0.351563f,0.53125f, +0.359375f,0.53125f, +0.367188f,0.53125f, +0.375f,0.53125f, +0.382813f,0.53125f, +0.390625f,0.53125f, +0.398438f,0.53125f, +0.40625f,0.53125f, +0.414063f,0.53125f, +0.421875f,0.53125f, +0.429688f,0.53125f, +0.4375f,0.53125f, +0.445313f,0.53125f, +0.453125f,0.53125f, +0.460938f,0.53125f, +0.46875f,0.53125f, +0.476563f,0.53125f, +0.484375f,0.53125f, +0.492188f,0.53125f, +0.5f,0.53125f, +0.507813f,0.53125f, +0.0f,0.539063f, +0.0078125f,0.539063f, +0.015625f,0.539063f, +0.0234375f,0.539063f, +0.03125f,0.539063f, +0.0390625f,0.539063f, +0.046875f,0.539063f, +0.0546875f,0.539063f, +0.0625f,0.539063f, +0.0703125f,0.539063f, +0.078125f,0.539063f, +0.0859375f,0.539063f, +0.09375f,0.539063f, +0.101563f,0.539063f, +0.109375f,0.539063f, +0.117188f,0.539063f, +0.125f,0.539063f, +0.132813f,0.539063f, +0.140625f,0.539063f, +0.148438f,0.539063f, +0.15625f,0.539063f, +0.164063f,0.539063f, +0.171875f,0.539063f, +0.179688f,0.539063f, +0.1875f,0.539063f, +0.195313f,0.539063f, +0.203125f,0.539063f, +0.210938f,0.539063f, +0.21875f,0.539063f, +0.226563f,0.539063f, +0.234375f,0.539063f, +0.242188f,0.539063f, +0.25f,0.539063f, +0.257813f,0.539063f, +0.265625f,0.539063f, +0.273438f,0.539063f, +0.28125f,0.539063f, +0.289063f,0.539063f, +0.296875f,0.539063f, +0.304688f,0.539063f, +0.3125f,0.539063f, +0.320313f,0.539063f, +0.328125f,0.539063f, +0.335938f,0.539063f, +0.34375f,0.539063f, +0.351563f,0.539063f, +0.359375f,0.539063f, +0.367188f,0.539063f, +0.375f,0.539063f, +0.382813f,0.539063f, +0.390625f,0.539063f, +0.398438f,0.539063f, +0.40625f,0.539063f, +0.414063f,0.539063f, +0.421875f,0.539063f, +0.429688f,0.539063f, +0.4375f,0.539063f, +0.445313f,0.539063f, +0.453125f,0.539063f, +0.460938f,0.539063f, +0.46875f,0.539063f, +0.476563f,0.539063f, +0.484375f,0.539063f, +0.492188f,0.539063f, +0.5f,0.539063f, +0.507813f,0.539063f, +0.0f,0.546875f, +0.0078125f,0.546875f, +0.015625f,0.546875f, +0.0234375f,0.546875f, +0.03125f,0.546875f, +0.0390625f,0.546875f, +0.046875f,0.546875f, +0.0546875f,0.546875f, +0.0625f,0.546875f, +0.0703125f,0.546875f, +0.078125f,0.546875f, +0.0859375f,0.546875f, +0.09375f,0.546875f, +0.101563f,0.546875f, +0.109375f,0.546875f, +0.117188f,0.546875f, +0.125f,0.546875f, +0.132813f,0.546875f, +0.140625f,0.546875f, +0.148438f,0.546875f, +0.15625f,0.546875f, +0.164063f,0.546875f, +0.171875f,0.546875f, +0.179688f,0.546875f, +0.1875f,0.546875f, +0.195313f,0.546875f, +0.203125f,0.546875f, +0.210938f,0.546875f, +0.21875f,0.546875f, +0.226563f,0.546875f, +0.234375f,0.546875f, +0.242188f,0.546875f, +0.25f,0.546875f, +0.257813f,0.546875f, +0.265625f,0.546875f, +0.273438f,0.546875f, +0.28125f,0.546875f, +0.289063f,0.546875f, +0.296875f,0.546875f, +0.304688f,0.546875f, +0.3125f,0.546875f, +0.320313f,0.546875f, +0.328125f,0.546875f, +0.335938f,0.546875f, +0.34375f,0.546875f, +0.351563f,0.546875f, +0.359375f,0.546875f, +0.367188f,0.546875f, +0.375f,0.546875f, +0.382813f,0.546875f, +0.390625f,0.546875f, +0.398438f,0.546875f, +0.40625f,0.546875f, +0.414063f,0.546875f, +0.421875f,0.546875f, +0.429688f,0.546875f, +0.4375f,0.546875f, +0.445313f,0.546875f, +0.453125f,0.546875f, +0.460938f,0.546875f, +0.46875f,0.546875f, +0.476563f,0.546875f, +0.484375f,0.546875f, +0.492188f,0.546875f, +0.5f,0.546875f, +0.507813f,0.546875f, +0.0f,0.554688f, +0.0078125f,0.554688f, +0.015625f,0.554688f, +0.0234375f,0.554688f, +0.03125f,0.554688f, +0.0390625f,0.554688f, +0.046875f,0.554688f, +0.0546875f,0.554688f, +0.0625f,0.554688f, +0.0703125f,0.554688f, +0.078125f,0.554688f, +0.0859375f,0.554688f, +0.09375f,0.554688f, +0.101563f,0.554688f, +0.109375f,0.554688f, +0.117188f,0.554688f, +0.125f,0.554688f, +0.132813f,0.554688f, +0.140625f,0.554688f, +0.148438f,0.554688f, +0.15625f,0.554688f, +0.164063f,0.554688f, +0.171875f,0.554688f, +0.179688f,0.554688f, +0.1875f,0.554688f, +0.195313f,0.554688f, +0.203125f,0.554688f, +0.210938f,0.554688f, +0.21875f,0.554688f, +0.226563f,0.554688f, +0.234375f,0.554688f, +0.242188f,0.554688f, +0.25f,0.554688f, +0.257813f,0.554688f, +0.265625f,0.554688f, +0.273438f,0.554688f, +0.28125f,0.554688f, +0.289063f,0.554688f, +0.296875f,0.554688f, +0.304688f,0.554688f, +0.3125f,0.554688f, +0.320313f,0.554688f, +0.328125f,0.554688f, +0.335938f,0.554688f, +0.34375f,0.554688f, +0.351563f,0.554688f, +0.359375f,0.554688f, +0.367188f,0.554688f, +0.375f,0.554688f, +0.382813f,0.554688f, +0.390625f,0.554688f, +0.398438f,0.554688f, +0.40625f,0.554688f, +0.414063f,0.554688f, +0.421875f,0.554688f, +0.429688f,0.554688f, +0.4375f,0.554688f, +0.445313f,0.554688f, +0.453125f,0.554688f, +0.460938f,0.554688f, +0.46875f,0.554688f, +0.476563f,0.554688f, +0.484375f,0.554688f, +0.492188f,0.554688f, +0.5f,0.554688f, +0.507813f,0.554688f, +0.0f,0.5625f, +0.0078125f,0.5625f, +0.015625f,0.5625f, +0.0234375f,0.5625f, +0.03125f,0.5625f, +0.0390625f,0.5625f, +0.046875f,0.5625f, +0.0546875f,0.5625f, +0.0625f,0.5625f, +0.0703125f,0.5625f, +0.078125f,0.5625f, +0.0859375f,0.5625f, +0.09375f,0.5625f, +0.101563f,0.5625f, +0.109375f,0.5625f, +0.117188f,0.5625f, +0.125f,0.5625f, +0.132813f,0.5625f, +0.140625f,0.5625f, +0.148438f,0.5625f, +0.15625f,0.5625f, +0.164063f,0.5625f, +0.171875f,0.5625f, +0.179688f,0.5625f, +0.1875f,0.5625f, +0.195313f,0.5625f, +0.203125f,0.5625f, +0.210938f,0.5625f, +0.21875f,0.5625f, +0.226563f,0.5625f, +0.234375f,0.5625f, +0.242188f,0.5625f, +0.25f,0.5625f, +0.257813f,0.5625f, +0.265625f,0.5625f, +0.273438f,0.5625f, +0.28125f,0.5625f, +0.289063f,0.5625f, +0.296875f,0.5625f, +0.304688f,0.5625f, +0.3125f,0.5625f, +0.320313f,0.5625f, +0.328125f,0.5625f, +0.335938f,0.5625f, +0.34375f,0.5625f, +0.351563f,0.5625f, +0.359375f,0.5625f, +0.367188f,0.5625f, +0.375f,0.5625f, +0.382813f,0.5625f, +0.390625f,0.5625f, +0.398438f,0.5625f, +0.40625f,0.5625f, +0.414063f,0.5625f, +0.421875f,0.5625f, +0.429688f,0.5625f, +0.4375f,0.5625f, +0.445313f,0.5625f, +0.453125f,0.5625f, +0.460938f,0.5625f, +0.46875f,0.5625f, +0.476563f,0.5625f, +0.484375f,0.5625f, +0.492188f,0.5625f, +0.5f,0.5625f, +0.507813f,0.5625f, +0.0f,0.570313f, +0.0078125f,0.570313f, +0.015625f,0.570313f, +0.0234375f,0.570313f, +0.03125f,0.570313f, +0.0390625f,0.570313f, +0.046875f,0.570313f, +0.0546875f,0.570313f, +0.0625f,0.570313f, +0.0703125f,0.570313f, +0.078125f,0.570313f, +0.0859375f,0.570313f, +0.09375f,0.570313f, +0.101563f,0.570313f, +0.109375f,0.570313f, +0.117188f,0.570313f, +0.125f,0.570313f, +0.132813f,0.570313f, +0.140625f,0.570313f, +0.148438f,0.570313f, +0.15625f,0.570313f, +0.164063f,0.570313f, +0.171875f,0.570313f, +0.179688f,0.570313f, +0.1875f,0.570313f, +0.195313f,0.570313f, +0.203125f,0.570313f, +0.210938f,0.570313f, +0.21875f,0.570313f, +0.226563f,0.570313f, +0.234375f,0.570313f, +0.242188f,0.570313f, +0.25f,0.570313f, +0.257813f,0.570313f, +0.265625f,0.570313f, +0.273438f,0.570313f, +0.28125f,0.570313f, +0.289063f,0.570313f, +0.296875f,0.570313f, +0.304688f,0.570313f, +0.3125f,0.570313f, +0.320313f,0.570313f, +0.328125f,0.570313f, +0.335938f,0.570313f, +0.34375f,0.570313f, +0.351563f,0.570313f, +0.359375f,0.570313f, +0.367188f,0.570313f, +0.375f,0.570313f, +0.382813f,0.570313f, +0.390625f,0.570313f, +0.398438f,0.570313f, +0.40625f,0.570313f, +0.414063f,0.570313f, +0.421875f,0.570313f, +0.429688f,0.570313f, +0.4375f,0.570313f, +0.445313f,0.570313f, +0.453125f,0.570313f, +0.460938f,0.570313f, +0.46875f,0.570313f, +0.476563f,0.570313f, +0.484375f,0.570313f, +0.492188f,0.570313f, +0.5f,0.570313f, +0.507813f,0.570313f, +0.0f,0.578125f, +0.0078125f,0.578125f, +0.015625f,0.578125f, +0.0234375f,0.578125f, +0.03125f,0.578125f, +0.0390625f,0.578125f, +0.046875f,0.578125f, +0.0546875f,0.578125f, +0.0625f,0.578125f, +0.0703125f,0.578125f, +0.078125f,0.578125f, +0.0859375f,0.578125f, +0.09375f,0.578125f, +0.101563f,0.578125f, +0.109375f,0.578125f, +0.117188f,0.578125f, +0.125f,0.578125f, +0.132813f,0.578125f, +0.140625f,0.578125f, +0.148438f,0.578125f, +0.15625f,0.578125f, +0.164063f,0.578125f, +0.171875f,0.578125f, +0.179688f,0.578125f, +0.1875f,0.578125f, +0.195313f,0.578125f, +0.203125f,0.578125f, +0.210938f,0.578125f, +0.21875f,0.578125f, +0.226563f,0.578125f, +0.234375f,0.578125f, +0.242188f,0.578125f, +0.25f,0.578125f, +0.257813f,0.578125f, +0.265625f,0.578125f, +0.273438f,0.578125f, +0.28125f,0.578125f, +0.289063f,0.578125f, +0.296875f,0.578125f, +0.304688f,0.578125f, +0.3125f,0.578125f, +0.320313f,0.578125f, +0.328125f,0.578125f, +0.335938f,0.578125f, +0.34375f,0.578125f, +0.351563f,0.578125f, +0.359375f,0.578125f, +0.367188f,0.578125f, +0.375f,0.578125f, +0.382813f,0.578125f, +0.390625f,0.578125f, +0.398438f,0.578125f, +0.40625f,0.578125f, +0.414063f,0.578125f, +0.421875f,0.578125f, +0.429688f,0.578125f, +0.4375f,0.578125f, +0.445313f,0.578125f, +0.453125f,0.578125f, +0.460938f,0.578125f, +0.46875f,0.578125f, +0.476563f,0.578125f, +0.484375f,0.578125f, +0.492188f,0.578125f, +0.5f,0.578125f, +0.507813f,0.578125f, +0.0f,0.585938f, +0.0078125f,0.585938f, +0.015625f,0.585938f, +0.0234375f,0.585938f, +0.03125f,0.585938f, +0.0390625f,0.585938f, +0.046875f,0.585938f, +0.0546875f,0.585938f, +0.0625f,0.585938f, +0.0703125f,0.585938f, +0.078125f,0.585938f, +0.0859375f,0.585938f, +0.09375f,0.585938f, +0.101563f,0.585938f, +0.109375f,0.585938f, +0.117188f,0.585938f, +0.125f,0.585938f, +0.132813f,0.585938f, +0.140625f,0.585938f, +0.148438f,0.585938f, +0.15625f,0.585938f, +0.164063f,0.585938f, +0.171875f,0.585938f, +0.179688f,0.585938f, +0.1875f,0.585938f, +0.195313f,0.585938f, +0.203125f,0.585938f, +0.210938f,0.585938f, +0.21875f,0.585938f, +0.226563f,0.585938f, +0.234375f,0.585938f, +0.242188f,0.585938f, +0.25f,0.585938f, +0.257813f,0.585938f, +0.265625f,0.585938f, +0.273438f,0.585938f, +0.28125f,0.585938f, +0.289063f,0.585938f, +0.296875f,0.585938f, +0.304688f,0.585938f, +0.3125f,0.585938f, +0.320313f,0.585938f, +0.328125f,0.585938f, +0.335938f,0.585938f, +0.34375f,0.585938f, +0.351563f,0.585938f, +0.359375f,0.585938f, +0.367188f,0.585938f, +0.375f,0.585938f, +0.382813f,0.585938f, +0.390625f,0.585938f, +0.398438f,0.585938f, +0.40625f,0.585938f, +0.414063f,0.585938f, +0.421875f,0.585938f, +0.429688f,0.585938f, +0.4375f,0.585938f, +0.445313f,0.585938f, +0.453125f,0.585938f, +0.460938f,0.585938f, +0.46875f,0.585938f, +0.476563f,0.585938f, +0.484375f,0.585938f, +0.492188f,0.585938f, +0.5f,0.585938f, +0.507813f,0.585938f, +0.0f,0.59375f, +0.0078125f,0.59375f, +0.015625f,0.59375f, +0.0234375f,0.59375f, +0.03125f,0.59375f, +0.0390625f,0.59375f, +0.046875f,0.59375f, +0.0546875f,0.59375f, +0.0625f,0.59375f, +0.0703125f,0.59375f, +0.078125f,0.59375f, +0.0859375f,0.59375f, +0.09375f,0.59375f, +0.101563f,0.59375f, +0.109375f,0.59375f, +0.117188f,0.59375f, +0.125f,0.59375f, +0.132813f,0.59375f, +0.140625f,0.59375f, +0.148438f,0.59375f, +0.15625f,0.59375f, +0.164063f,0.59375f, +0.171875f,0.59375f, +0.179688f,0.59375f, +0.1875f,0.59375f, +0.195313f,0.59375f, +0.203125f,0.59375f, +0.210938f,0.59375f, +0.21875f,0.59375f, +0.226563f,0.59375f, +0.234375f,0.59375f, +0.242188f,0.59375f, +0.25f,0.59375f, +0.257813f,0.59375f, +0.265625f,0.59375f, +0.273438f,0.59375f, +0.28125f,0.59375f, +0.289063f,0.59375f, +0.296875f,0.59375f, +0.304688f,0.59375f, +0.3125f,0.59375f, +0.320313f,0.59375f, +0.328125f,0.59375f, +0.335938f,0.59375f, +0.34375f,0.59375f, +0.351563f,0.59375f, +0.359375f,0.59375f, +0.367188f,0.59375f, +0.375f,0.59375f, +0.382813f,0.59375f, +0.390625f,0.59375f, +0.398438f,0.59375f, +0.40625f,0.59375f, +0.414063f,0.59375f, +0.421875f,0.59375f, +0.429688f,0.59375f, +0.4375f,0.59375f, +0.445313f,0.59375f, +0.453125f,0.59375f, +0.460938f,0.59375f, +0.46875f,0.59375f, +0.476563f,0.59375f, +0.484375f,0.59375f, +0.492188f,0.59375f, +0.5f,0.59375f, +0.507813f,0.59375f, +0.0f,0.601563f, +0.0078125f,0.601563f, +0.015625f,0.601563f, +0.0234375f,0.601563f, +0.03125f,0.601563f, +0.0390625f,0.601563f, +0.046875f,0.601563f, +0.0546875f,0.601563f, +0.0625f,0.601563f, +0.0703125f,0.601563f, +0.078125f,0.601563f, +0.0859375f,0.601563f, +0.09375f,0.601563f, +0.101563f,0.601563f, +0.109375f,0.601563f, +0.117188f,0.601563f, +0.125f,0.601563f, +0.132813f,0.601563f, +0.140625f,0.601563f, +0.148438f,0.601563f, +0.15625f,0.601563f, +0.164063f,0.601563f, +0.171875f,0.601563f, +0.179688f,0.601563f, +0.1875f,0.601563f, +0.195313f,0.601563f, +0.203125f,0.601563f, +0.210938f,0.601563f, +0.21875f,0.601563f, +0.226563f,0.601563f, +0.234375f,0.601563f, +0.242188f,0.601563f, +0.25f,0.601563f, +0.257813f,0.601563f, +0.265625f,0.601563f, +0.273438f,0.601563f, +0.28125f,0.601563f, +0.289063f,0.601563f, +0.296875f,0.601563f, +0.304688f,0.601563f, +0.3125f,0.601563f, +0.320313f,0.601563f, +0.328125f,0.601563f, +0.335938f,0.601563f, +0.34375f,0.601563f, +0.351563f,0.601563f, +0.359375f,0.601563f, +0.367188f,0.601563f, +0.375f,0.601563f, +0.382813f,0.601563f, +0.390625f,0.601563f, +0.398438f,0.601563f, +0.40625f,0.601563f, +0.414063f,0.601563f, +0.421875f,0.601563f, +0.429688f,0.601563f, +0.4375f,0.601563f, +0.445313f,0.601563f, +0.453125f,0.601563f, +0.460938f,0.601563f, +0.46875f,0.601563f, +0.476563f,0.601563f, +0.484375f,0.601563f, +0.492188f,0.601563f, +0.5f,0.601563f, +0.507813f,0.601563f, +0.0f,0.609375f, +0.0078125f,0.609375f, +0.015625f,0.609375f, +0.0234375f,0.609375f, +0.03125f,0.609375f, +0.0390625f,0.609375f, +0.046875f,0.609375f, +0.0546875f,0.609375f, +0.0625f,0.609375f, +0.0703125f,0.609375f, +0.078125f,0.609375f, +0.0859375f,0.609375f, +0.09375f,0.609375f, +0.101563f,0.609375f, +0.109375f,0.609375f, +0.117188f,0.609375f, +0.125f,0.609375f, +0.132813f,0.609375f, +0.140625f,0.609375f, +0.148438f,0.609375f, +0.15625f,0.609375f, +0.164063f,0.609375f, +0.171875f,0.609375f, +0.179688f,0.609375f, +0.1875f,0.609375f, +0.195313f,0.609375f, +0.203125f,0.609375f, +0.210938f,0.609375f, +0.21875f,0.609375f, +0.226563f,0.609375f, +0.234375f,0.609375f, +0.242188f,0.609375f, +0.25f,0.609375f, +0.257813f,0.609375f, +0.265625f,0.609375f, +0.273438f,0.609375f, +0.28125f,0.609375f, +0.289063f,0.609375f, +0.296875f,0.609375f, +0.304688f,0.609375f, +0.3125f,0.609375f, +0.320313f,0.609375f, +0.328125f,0.609375f, +0.335938f,0.609375f, +0.34375f,0.609375f, +0.351563f,0.609375f, +0.359375f,0.609375f, +0.367188f,0.609375f, +0.375f,0.609375f, +0.382813f,0.609375f, +0.390625f,0.609375f, +0.398438f,0.609375f, +0.40625f,0.609375f, +0.414063f,0.609375f, +0.421875f,0.609375f, +0.429688f,0.609375f, +0.4375f,0.609375f, +0.445313f,0.609375f, +0.453125f,0.609375f, +0.460938f,0.609375f, +0.46875f,0.609375f, +0.476563f,0.609375f, +0.484375f,0.609375f, +0.492188f,0.609375f, +0.5f,0.609375f, +0.507813f,0.609375f, +0.0f,0.617188f, +0.0078125f,0.617188f, +0.015625f,0.617188f, +0.0234375f,0.617188f, +0.03125f,0.617188f, +0.0390625f,0.617188f, +0.046875f,0.617188f, +0.0546875f,0.617188f, +0.0625f,0.617188f, +0.0703125f,0.617188f, +0.078125f,0.617188f, +0.0859375f,0.617188f, +0.09375f,0.617188f, +0.101563f,0.617188f, +0.109375f,0.617188f, +0.117188f,0.617188f, +0.125f,0.617188f, +0.132813f,0.617188f, +0.140625f,0.617188f, +0.148438f,0.617188f, +0.15625f,0.617188f, +0.164063f,0.617188f, +0.171875f,0.617188f, +0.179688f,0.617188f, +0.1875f,0.617188f, +0.195313f,0.617188f, +0.203125f,0.617188f, +0.210938f,0.617188f, +0.21875f,0.617188f, +0.226563f,0.617188f, +0.234375f,0.617188f, +0.242188f,0.617188f, +0.25f,0.617188f, +0.257813f,0.617188f, +0.265625f,0.617188f, +0.273438f,0.617188f, +0.28125f,0.617188f, +0.289063f,0.617188f, +0.296875f,0.617188f, +0.304688f,0.617188f, +0.3125f,0.617188f, +0.320313f,0.617188f, +0.328125f,0.617188f, +0.335938f,0.617188f, +0.34375f,0.617188f, +0.351563f,0.617188f, +0.359375f,0.617188f, +0.367188f,0.617188f, +0.375f,0.617188f, +0.382813f,0.617188f, +0.390625f,0.617188f, +0.398438f,0.617188f, +0.40625f,0.617188f, +0.414063f,0.617188f, +0.421875f,0.617188f, +0.429688f,0.617188f, +0.4375f,0.617188f, +0.445313f,0.617188f, +0.453125f,0.617188f, +0.460938f,0.617188f, +0.46875f,0.617188f, +0.476563f,0.617188f, +0.484375f,0.617188f, +0.492188f,0.617188f, +0.5f,0.617188f, +0.507813f,0.617188f, +0.0f,0.625f, +0.0078125f,0.625f, +0.015625f,0.625f, +0.0234375f,0.625f, +0.03125f,0.625f, +0.0390625f,0.625f, +0.046875f,0.625f, +0.0546875f,0.625f, +0.0625f,0.625f, +0.0703125f,0.625f, +0.078125f,0.625f, +0.0859375f,0.625f, +0.09375f,0.625f, +0.101563f,0.625f, +0.109375f,0.625f, +0.117188f,0.625f, +0.125f,0.625f, +0.132813f,0.625f, +0.140625f,0.625f, +0.148438f,0.625f, +0.15625f,0.625f, +0.164063f,0.625f, +0.171875f,0.625f, +0.179688f,0.625f, +0.1875f,0.625f, +0.195313f,0.625f, +0.203125f,0.625f, +0.210938f,0.625f, +0.21875f,0.625f, +0.226563f,0.625f, +0.234375f,0.625f, +0.242188f,0.625f, +0.25f,0.625f, +0.257813f,0.625f, +0.265625f,0.625f, +0.273438f,0.625f, +0.28125f,0.625f, +0.289063f,0.625f, +0.296875f,0.625f, +0.304688f,0.625f, +0.3125f,0.625f, +0.320313f,0.625f, +0.328125f,0.625f, +0.335938f,0.625f, +0.34375f,0.625f, +0.351563f,0.625f, +0.359375f,0.625f, +0.367188f,0.625f, +0.375f,0.625f, +0.382813f,0.625f, +0.390625f,0.625f, +0.398438f,0.625f, +0.40625f,0.625f, +0.414063f,0.625f, +0.421875f,0.625f, +0.429688f,0.625f, +0.4375f,0.625f, +0.445313f,0.625f, +0.453125f,0.625f, +0.460938f,0.625f, +0.46875f,0.625f, +0.476563f,0.625f, +0.484375f,0.625f, +0.492188f,0.625f, +0.5f,0.625f, +0.507813f,0.625f, +0.0f,0.632813f, +0.0078125f,0.632813f, +0.015625f,0.632813f, +0.0234375f,0.632813f, +0.03125f,0.632813f, +0.0390625f,0.632813f, +0.046875f,0.632813f, +0.0546875f,0.632813f, +0.0625f,0.632813f, +0.0703125f,0.632813f, +0.078125f,0.632813f, +0.0859375f,0.632813f, +0.09375f,0.632813f, +0.101563f,0.632813f, +0.109375f,0.632813f, +0.117188f,0.632813f, +0.125f,0.632813f, +0.132813f,0.632813f, +0.140625f,0.632813f, +0.148438f,0.632813f, +0.15625f,0.632813f, +0.164063f,0.632813f, +0.171875f,0.632813f, +0.179688f,0.632813f, +0.1875f,0.632813f, +0.195313f,0.632813f, +0.203125f,0.632813f, +0.210938f,0.632813f, +0.21875f,0.632813f, +0.226563f,0.632813f, +0.234375f,0.632813f, +0.242188f,0.632813f, +0.25f,0.632813f, +0.257813f,0.632813f, +0.265625f,0.632813f, +0.273438f,0.632813f, +0.28125f,0.632813f, +0.289063f,0.632813f, +0.296875f,0.632813f, +0.304688f,0.632813f, +0.3125f,0.632813f, +0.320313f,0.632813f, +0.328125f,0.632813f, +0.335938f,0.632813f, +0.34375f,0.632813f, +0.351563f,0.632813f, +0.359375f,0.632813f, +0.367188f,0.632813f, +0.375f,0.632813f, +0.382813f,0.632813f, +0.390625f,0.632813f, +0.398438f,0.632813f, +0.40625f,0.632813f, +0.414063f,0.632813f, +0.421875f,0.632813f, +0.429688f,0.632813f, +0.4375f,0.632813f, +0.445313f,0.632813f, +0.453125f,0.632813f, +0.460938f,0.632813f, +0.46875f,0.632813f, +0.476563f,0.632813f, +0.484375f,0.632813f, +0.492188f,0.632813f, +0.5f,0.632813f, +0.507813f,0.632813f, +0.0f,0.640625f, +0.0078125f,0.640625f, +0.015625f,0.640625f, +0.0234375f,0.640625f, +0.03125f,0.640625f, +0.0390625f,0.640625f, +0.046875f,0.640625f, +0.0546875f,0.640625f, +0.0625f,0.640625f, +0.0703125f,0.640625f, +0.078125f,0.640625f, +0.0859375f,0.640625f, +0.09375f,0.640625f, +0.101563f,0.640625f, +0.109375f,0.640625f, +0.117188f,0.640625f, +0.125f,0.640625f, +0.132813f,0.640625f, +0.140625f,0.640625f, +0.148438f,0.640625f, +0.15625f,0.640625f, +0.164063f,0.640625f, +0.171875f,0.640625f, +0.179688f,0.640625f, +0.1875f,0.640625f, +0.195313f,0.640625f, +0.203125f,0.640625f, +0.210938f,0.640625f, +0.21875f,0.640625f, +0.226563f,0.640625f, +0.234375f,0.640625f, +0.242188f,0.640625f, +0.25f,0.640625f, +0.257813f,0.640625f, +0.265625f,0.640625f, +0.273438f,0.640625f, +0.28125f,0.640625f, +0.289063f,0.640625f, +0.296875f,0.640625f, +0.304688f,0.640625f, +0.3125f,0.640625f, +0.320313f,0.640625f, +0.328125f,0.640625f, +0.335938f,0.640625f, +0.34375f,0.640625f, +0.351563f,0.640625f, +0.359375f,0.640625f, +0.367188f,0.640625f, +0.375f,0.640625f, +0.382813f,0.640625f, +0.390625f,0.640625f, +0.398438f,0.640625f, +0.40625f,0.640625f, +0.414063f,0.640625f, +0.421875f,0.640625f, +0.429688f,0.640625f, +0.4375f,0.640625f, +0.445313f,0.640625f, +0.453125f,0.640625f, +0.460938f,0.640625f, +0.46875f,0.640625f, +0.476563f,0.640625f, +0.484375f,0.640625f, +0.492188f,0.640625f, +0.5f,0.640625f, +0.507813f,0.640625f, +0.0f,0.648438f, +0.0078125f,0.648438f, +0.015625f,0.648438f, +0.0234375f,0.648438f, +0.03125f,0.648438f, +0.0390625f,0.648438f, +0.046875f,0.648438f, +0.0546875f,0.648438f, +0.0625f,0.648438f, +0.0703125f,0.648438f, +0.078125f,0.648438f, +0.0859375f,0.648438f, +0.09375f,0.648438f, +0.101563f,0.648438f, +0.109375f,0.648438f, +0.117188f,0.648438f, +0.125f,0.648438f, +0.132813f,0.648438f, +0.140625f,0.648438f, +0.148438f,0.648438f, +0.15625f,0.648438f, +0.164063f,0.648438f, +0.171875f,0.648438f, +0.179688f,0.648438f, +0.1875f,0.648438f, +0.195313f,0.648438f, +0.203125f,0.648438f, +0.210938f,0.648438f, +0.21875f,0.648438f, +0.226563f,0.648438f, +0.234375f,0.648438f, +0.242188f,0.648438f, +0.25f,0.648438f, +0.257813f,0.648438f, +0.265625f,0.648438f, +0.273438f,0.648438f, +0.28125f,0.648438f, +0.289063f,0.648438f, +0.296875f,0.648438f, +0.304688f,0.648438f, +0.3125f,0.648438f, +0.320313f,0.648438f, +0.328125f,0.648438f, +0.335938f,0.648438f, +0.34375f,0.648438f, +0.351563f,0.648438f, +0.359375f,0.648438f, +0.367188f,0.648438f, +0.375f,0.648438f, +0.382813f,0.648438f, +0.390625f,0.648438f, +0.398438f,0.648438f, +0.40625f,0.648438f, +0.414063f,0.648438f, +0.421875f,0.648438f, +0.429688f,0.648438f, +0.4375f,0.648438f, +0.445313f,0.648438f, +0.453125f,0.648438f, +0.460938f,0.648438f, +0.46875f,0.648438f, +0.476563f,0.648438f, +0.484375f,0.648438f, +0.492188f,0.648438f, +0.5f,0.648438f, +0.507813f,0.648438f, +0.0f,0.65625f, +0.0078125f,0.65625f, +0.015625f,0.65625f, +0.0234375f,0.65625f, +0.03125f,0.65625f, +0.0390625f,0.65625f, +0.046875f,0.65625f, +0.0546875f,0.65625f, +0.0625f,0.65625f, +0.0703125f,0.65625f, +0.078125f,0.65625f, +0.0859375f,0.65625f, +0.09375f,0.65625f, +0.101563f,0.65625f, +0.109375f,0.65625f, +0.117188f,0.65625f, +0.125f,0.65625f, +0.132813f,0.65625f, +0.140625f,0.65625f, +0.148438f,0.65625f, +0.15625f,0.65625f, +0.164063f,0.65625f, +0.171875f,0.65625f, +0.179688f,0.65625f, +0.1875f,0.65625f, +0.195313f,0.65625f, +0.203125f,0.65625f, +0.210938f,0.65625f, +0.21875f,0.65625f, +0.226563f,0.65625f, +0.234375f,0.65625f, +0.242188f,0.65625f, +0.25f,0.65625f, +0.257813f,0.65625f, +0.265625f,0.65625f, +0.273438f,0.65625f, +0.28125f,0.65625f, +0.289063f,0.65625f, +0.296875f,0.65625f, +0.304688f,0.65625f, +0.3125f,0.65625f, +0.320313f,0.65625f, +0.328125f,0.65625f, +0.335938f,0.65625f, +0.34375f,0.65625f, +0.351563f,0.65625f, +0.359375f,0.65625f, +0.367188f,0.65625f, +0.375f,0.65625f, +0.382813f,0.65625f, +0.390625f,0.65625f, +0.398438f,0.65625f, +0.40625f,0.65625f, +0.414063f,0.65625f, +0.421875f,0.65625f, +0.429688f,0.65625f, +0.4375f,0.65625f, +0.445313f,0.65625f, +0.453125f,0.65625f, +0.460938f,0.65625f, +0.46875f,0.65625f, +0.476563f,0.65625f, +0.484375f,0.65625f, +0.492188f,0.65625f, +0.5f,0.65625f, +0.507813f,0.65625f, +0.0f,0.664063f, +0.0078125f,0.664063f, +0.015625f,0.664063f, +0.0234375f,0.664063f, +0.03125f,0.664063f, +0.0390625f,0.664063f, +0.046875f,0.664063f, +0.0546875f,0.664063f, +0.0625f,0.664063f, +0.0703125f,0.664063f, +0.078125f,0.664063f, +0.0859375f,0.664063f, +0.09375f,0.664063f, +0.101563f,0.664063f, +0.109375f,0.664063f, +0.117188f,0.664063f, +0.125f,0.664063f, +0.132813f,0.664063f, +0.140625f,0.664063f, +0.148438f,0.664063f, +0.15625f,0.664063f, +0.164063f,0.664063f, +0.171875f,0.664063f, +0.179688f,0.664063f, +0.1875f,0.664063f, +0.195313f,0.664063f, +0.203125f,0.664063f, +0.210938f,0.664063f, +0.21875f,0.664063f, +0.226563f,0.664063f, +0.234375f,0.664063f, +0.242188f,0.664063f, +0.25f,0.664063f, +0.257813f,0.664063f, +0.265625f,0.664063f, +0.273438f,0.664063f, +0.28125f,0.664063f, +0.289063f,0.664063f, +0.296875f,0.664063f, +0.304688f,0.664063f, +0.3125f,0.664063f, +0.320313f,0.664063f, +0.328125f,0.664063f, +0.335938f,0.664063f, +0.34375f,0.664063f, +0.351563f,0.664063f, +0.359375f,0.664063f, +0.367188f,0.664063f, +0.375f,0.664063f, +0.382813f,0.664063f, +0.390625f,0.664063f, +0.398438f,0.664063f, +0.40625f,0.664063f, +0.414063f,0.664063f, +0.421875f,0.664063f, +0.429688f,0.664063f, +0.4375f,0.664063f, +0.445313f,0.664063f, +0.453125f,0.664063f, +0.460938f,0.664063f, +0.46875f,0.664063f, +0.476563f,0.664063f, +0.484375f,0.664063f, +0.492188f,0.664063f, +0.5f,0.664063f, +0.507813f,0.664063f, +0.0f,0.671875f, +0.0078125f,0.671875f, +0.015625f,0.671875f, +0.0234375f,0.671875f, +0.03125f,0.671875f, +0.0390625f,0.671875f, +0.046875f,0.671875f, +0.0546875f,0.671875f, +0.0625f,0.671875f, +0.0703125f,0.671875f, +0.078125f,0.671875f, +0.0859375f,0.671875f, +0.09375f,0.671875f, +0.101563f,0.671875f, +0.109375f,0.671875f, +0.117188f,0.671875f, +0.125f,0.671875f, +0.132813f,0.671875f, +0.140625f,0.671875f, +0.148438f,0.671875f, +0.15625f,0.671875f, +0.164063f,0.671875f, +0.171875f,0.671875f, +0.179688f,0.671875f, +0.1875f,0.671875f, +0.195313f,0.671875f, +0.203125f,0.671875f, +0.210938f,0.671875f, +0.21875f,0.671875f, +0.226563f,0.671875f, +0.234375f,0.671875f, +0.242188f,0.671875f, +0.25f,0.671875f, +0.257813f,0.671875f, +0.265625f,0.671875f, +0.273438f,0.671875f, +0.28125f,0.671875f, +0.289063f,0.671875f, +0.296875f,0.671875f, +0.304688f,0.671875f, +0.3125f,0.671875f, +0.320313f,0.671875f, +0.328125f,0.671875f, +0.335938f,0.671875f, +0.34375f,0.671875f, +0.351563f,0.671875f, +0.359375f,0.671875f, +0.367188f,0.671875f, +0.375f,0.671875f, +0.382813f,0.671875f, +0.390625f,0.671875f, +0.398438f,0.671875f, +0.40625f,0.671875f, +0.414063f,0.671875f, +0.421875f,0.671875f, +0.429688f,0.671875f, +0.4375f,0.671875f, +0.445313f,0.671875f, +0.453125f,0.671875f, +0.460938f,0.671875f, +0.46875f,0.671875f, +0.476563f,0.671875f, +0.484375f,0.671875f, +0.492188f,0.671875f, +0.5f,0.671875f, +0.507813f,0.671875f, +0.0f,0.679688f, +0.0078125f,0.679688f, +0.015625f,0.679688f, +0.0234375f,0.679688f, +0.03125f,0.679688f, +0.0390625f,0.679688f, +0.046875f,0.679688f, +0.0546875f,0.679688f, +0.0625f,0.679688f, +0.0703125f,0.679688f, +0.078125f,0.679688f, +0.0859375f,0.679688f, +0.09375f,0.679688f, +0.101563f,0.679688f, +0.109375f,0.679688f, +0.117188f,0.679688f, +0.125f,0.679688f, +0.132813f,0.679688f, +0.140625f,0.679688f, +0.148438f,0.679688f, +0.15625f,0.679688f, +0.164063f,0.679688f, +0.171875f,0.679688f, +0.179688f,0.679688f, +0.1875f,0.679688f, +0.195313f,0.679688f, +0.203125f,0.679688f, +0.210938f,0.679688f, +0.21875f,0.679688f, +0.226563f,0.679688f, +0.234375f,0.679688f, +0.242188f,0.679688f, +0.25f,0.679688f, +0.257813f,0.679688f, +0.265625f,0.679688f, +0.273438f,0.679688f, +0.28125f,0.679688f, +0.289063f,0.679688f, +0.296875f,0.679688f, +0.304688f,0.679688f, +0.3125f,0.679688f, +0.320313f,0.679688f, +0.328125f,0.679688f, +0.335938f,0.679688f, +0.34375f,0.679688f, +0.351563f,0.679688f, +0.359375f,0.679688f, +0.367188f,0.679688f, +0.375f,0.679688f, +0.382813f,0.679688f, +0.390625f,0.679688f, +0.398438f,0.679688f, +0.40625f,0.679688f, +0.414063f,0.679688f, +0.421875f,0.679688f, +0.429688f,0.679688f, +0.4375f,0.679688f, +0.445313f,0.679688f, +0.453125f,0.679688f, +0.460938f,0.679688f, +0.46875f,0.679688f, +0.476563f,0.679688f, +0.484375f,0.679688f, +0.492188f,0.679688f, +0.5f,0.679688f, +0.507813f,0.679688f, +0.0f,0.6875f, +0.0078125f,0.6875f, +0.015625f,0.6875f, +0.0234375f,0.6875f, +0.03125f,0.6875f, +0.0390625f,0.6875f, +0.046875f,0.6875f, +0.0546875f,0.6875f, +0.0625f,0.6875f, +0.0703125f,0.6875f, +0.078125f,0.6875f, +0.0859375f,0.6875f, +0.09375f,0.6875f, +0.101563f,0.6875f, +0.109375f,0.6875f, +0.117188f,0.6875f, +0.125f,0.6875f, +0.132813f,0.6875f, +0.140625f,0.6875f, +0.148438f,0.6875f, +0.15625f,0.6875f, +0.164063f,0.6875f, +0.171875f,0.6875f, +0.179688f,0.6875f, +0.1875f,0.6875f, +0.195313f,0.6875f, +0.203125f,0.6875f, +0.210938f,0.6875f, +0.21875f,0.6875f, +0.226563f,0.6875f, +0.234375f,0.6875f, +0.242188f,0.6875f, +0.25f,0.6875f, +0.257813f,0.6875f, +0.265625f,0.6875f, +0.273438f,0.6875f, +0.28125f,0.6875f, +0.289063f,0.6875f, +0.296875f,0.6875f, +0.304688f,0.6875f, +0.3125f,0.6875f, +0.320313f,0.6875f, +0.328125f,0.6875f, +0.335938f,0.6875f, +0.34375f,0.6875f, +0.351563f,0.6875f, +0.359375f,0.6875f, +0.367188f,0.6875f, +0.375f,0.6875f, +0.382813f,0.6875f, +0.390625f,0.6875f, +0.398438f,0.6875f, +0.40625f,0.6875f, +0.414063f,0.6875f, +0.421875f,0.6875f, +0.429688f,0.6875f, +0.4375f,0.6875f, +0.445313f,0.6875f, +0.453125f,0.6875f, +0.460938f,0.6875f, +0.46875f,0.6875f, +0.476563f,0.6875f, +0.484375f,0.6875f, +0.492188f,0.6875f, +0.5f,0.6875f, +0.507813f,0.6875f, +0.0f,0.695313f, +0.0078125f,0.695313f, +0.015625f,0.695313f, +0.0234375f,0.695313f, +0.03125f,0.695313f, +0.0390625f,0.695313f, +0.046875f,0.695313f, +0.0546875f,0.695313f, +0.0625f,0.695313f, +0.0703125f,0.695313f, +0.078125f,0.695313f, +0.0859375f,0.695313f, +0.09375f,0.695313f, +0.101563f,0.695313f, +0.109375f,0.695313f, +0.117188f,0.695313f, +0.125f,0.695313f, +0.132813f,0.695313f, +0.140625f,0.695313f, +0.148438f,0.695313f, +0.15625f,0.695313f, +0.164063f,0.695313f, +0.171875f,0.695313f, +0.179688f,0.695313f, +0.1875f,0.695313f, +0.195313f,0.695313f, +0.203125f,0.695313f, +0.210938f,0.695313f, +0.21875f,0.695313f, +0.226563f,0.695313f, +0.234375f,0.695313f, +0.242188f,0.695313f, +0.25f,0.695313f, +0.257813f,0.695313f, +0.265625f,0.695313f, +0.273438f,0.695313f, +0.28125f,0.695313f, +0.289063f,0.695313f, +0.296875f,0.695313f, +0.304688f,0.695313f, +0.3125f,0.695313f, +0.320313f,0.695313f, +0.328125f,0.695313f, +0.335938f,0.695313f, +0.34375f,0.695313f, +0.351563f,0.695313f, +0.359375f,0.695313f, +0.367188f,0.695313f, +0.375f,0.695313f, +0.382813f,0.695313f, +0.390625f,0.695313f, +0.398438f,0.695313f, +0.40625f,0.695313f, +0.414063f,0.695313f, +0.421875f,0.695313f, +0.429688f,0.695313f, +0.4375f,0.695313f, +0.445313f,0.695313f, +0.453125f,0.695313f, +0.460938f,0.695313f, +0.46875f,0.695313f, +0.476563f,0.695313f, +0.484375f,0.695313f, +0.492188f,0.695313f, +0.5f,0.695313f, +0.507813f,0.695313f, +0.0f,0.703125f, +0.0078125f,0.703125f, +0.015625f,0.703125f, +0.0234375f,0.703125f, +0.03125f,0.703125f, +0.0390625f,0.703125f, +0.046875f,0.703125f, +0.0546875f,0.703125f, +0.0625f,0.703125f, +0.0703125f,0.703125f, +0.078125f,0.703125f, +0.0859375f,0.703125f, +0.09375f,0.703125f, +0.101563f,0.703125f, +0.109375f,0.703125f, +0.117188f,0.703125f, +0.125f,0.703125f, +0.132813f,0.703125f, +0.140625f,0.703125f, +0.148438f,0.703125f, +0.15625f,0.703125f, +0.164063f,0.703125f, +0.171875f,0.703125f, +0.179688f,0.703125f, +0.1875f,0.703125f, +0.195313f,0.703125f, +0.203125f,0.703125f, +0.210938f,0.703125f, +0.21875f,0.703125f, +0.226563f,0.703125f, +0.234375f,0.703125f, +0.242188f,0.703125f, +0.25f,0.703125f, +0.257813f,0.703125f, +0.265625f,0.703125f, +0.273438f,0.703125f, +0.28125f,0.703125f, +0.289063f,0.703125f, +0.296875f,0.703125f, +0.304688f,0.703125f, +0.3125f,0.703125f, +0.320313f,0.703125f, +0.328125f,0.703125f, +0.335938f,0.703125f, +0.34375f,0.703125f, +0.351563f,0.703125f, +0.359375f,0.703125f, +0.367188f,0.703125f, +0.375f,0.703125f, +0.382813f,0.703125f, +0.390625f,0.703125f, +0.398438f,0.703125f, +0.40625f,0.703125f, +0.414063f,0.703125f, +0.421875f,0.703125f, +0.429688f,0.703125f, +0.4375f,0.703125f, +0.445313f,0.703125f, +0.453125f,0.703125f, +0.460938f,0.703125f, +0.46875f,0.703125f, +0.476563f,0.703125f, +0.484375f,0.703125f, +0.492188f,0.703125f, +0.5f,0.703125f, +0.507813f,0.703125f, +0.0f,0.710938f, +0.0078125f,0.710938f, +0.015625f,0.710938f, +0.0234375f,0.710938f, +0.03125f,0.710938f, +0.0390625f,0.710938f, +0.046875f,0.710938f, +0.0546875f,0.710938f, +0.0625f,0.710938f, +0.0703125f,0.710938f, +0.078125f,0.710938f, +0.0859375f,0.710938f, +0.09375f,0.710938f, +0.101563f,0.710938f, +0.109375f,0.710938f, +0.117188f,0.710938f, +0.125f,0.710938f, +0.132813f,0.710938f, +0.140625f,0.710938f, +0.148438f,0.710938f, +0.15625f,0.710938f, +0.164063f,0.710938f, +0.171875f,0.710938f, +0.179688f,0.710938f, +0.1875f,0.710938f, +0.195313f,0.710938f, +0.203125f,0.710938f, +0.210938f,0.710938f, +0.21875f,0.710938f, +0.226563f,0.710938f, +0.234375f,0.710938f, +0.242188f,0.710938f, +0.25f,0.710938f, +0.257813f,0.710938f, +0.265625f,0.710938f, +0.273438f,0.710938f, +0.28125f,0.710938f, +0.289063f,0.710938f, +0.296875f,0.710938f, +0.304688f,0.710938f, +0.3125f,0.710938f, +0.320313f,0.710938f, +0.328125f,0.710938f, +0.335938f,0.710938f, +0.34375f,0.710938f, +0.351563f,0.710938f, +0.359375f,0.710938f, +0.367188f,0.710938f, +0.375f,0.710938f, +0.382813f,0.710938f, +0.390625f,0.710938f, +0.398438f,0.710938f, +0.40625f,0.710938f, +0.414063f,0.710938f, +0.421875f,0.710938f, +0.429688f,0.710938f, +0.4375f,0.710938f, +0.445313f,0.710938f, +0.453125f,0.710938f, +0.460938f,0.710938f, +0.46875f,0.710938f, +0.476563f,0.710938f, +0.484375f,0.710938f, +0.492188f,0.710938f, +0.5f,0.710938f, +0.507813f,0.710938f, +0.0f,0.71875f, +0.0078125f,0.71875f, +0.015625f,0.71875f, +0.0234375f,0.71875f, +0.03125f,0.71875f, +0.0390625f,0.71875f, +0.046875f,0.71875f, +0.0546875f,0.71875f, +0.0625f,0.71875f, +0.0703125f,0.71875f, +0.078125f,0.71875f, +0.0859375f,0.71875f, +0.09375f,0.71875f, +0.101563f,0.71875f, +0.109375f,0.71875f, +0.117188f,0.71875f, +0.125f,0.71875f, +0.132813f,0.71875f, +0.140625f,0.71875f, +0.148438f,0.71875f, +0.15625f,0.71875f, +0.164063f,0.71875f, +0.171875f,0.71875f, +0.179688f,0.71875f, +0.1875f,0.71875f, +0.195313f,0.71875f, +0.203125f,0.71875f, +0.210938f,0.71875f, +0.21875f,0.71875f, +0.226563f,0.71875f, +0.234375f,0.71875f, +0.242188f,0.71875f, +0.25f,0.71875f, +0.257813f,0.71875f, +0.265625f,0.71875f, +0.273438f,0.71875f, +0.28125f,0.71875f, +0.289063f,0.71875f, +0.296875f,0.71875f, +0.304688f,0.71875f, +0.3125f,0.71875f, +0.320313f,0.71875f, +0.328125f,0.71875f, +0.335938f,0.71875f, +0.34375f,0.71875f, +0.351563f,0.71875f, +0.359375f,0.71875f, +0.367188f,0.71875f, +0.375f,0.71875f, +0.382813f,0.71875f, +0.390625f,0.71875f, +0.398438f,0.71875f, +0.40625f,0.71875f, +0.414063f,0.71875f, +0.421875f,0.71875f, +0.429688f,0.71875f, +0.4375f,0.71875f, +0.445313f,0.71875f, +0.453125f,0.71875f, +0.460938f,0.71875f, +0.46875f,0.71875f, +0.476563f,0.71875f, +0.484375f,0.71875f, +0.492188f,0.71875f, +0.5f,0.71875f, +0.507813f,0.71875f, +0.0f,0.726563f, +0.0078125f,0.726563f, +0.015625f,0.726563f, +0.0234375f,0.726563f, +0.03125f,0.726563f, +0.0390625f,0.726563f, +0.046875f,0.726563f, +0.0546875f,0.726563f, +0.0625f,0.726563f, +0.0703125f,0.726563f, +0.078125f,0.726563f, +0.0859375f,0.726563f, +0.09375f,0.726563f, +0.101563f,0.726563f, +0.109375f,0.726563f, +0.117188f,0.726563f, +0.125f,0.726563f, +0.132813f,0.726563f, +0.140625f,0.726563f, +0.148438f,0.726563f, +0.15625f,0.726563f, +0.164063f,0.726563f, +0.171875f,0.726563f, +0.179688f,0.726563f, +0.1875f,0.726563f, +0.195313f,0.726563f, +0.203125f,0.726563f, +0.210938f,0.726563f, +0.21875f,0.726563f, +0.226563f,0.726563f, +0.234375f,0.726563f, +0.242188f,0.726563f, +0.25f,0.726563f, +0.257813f,0.726563f, +0.265625f,0.726563f, +0.273438f,0.726563f, +0.28125f,0.726563f, +0.289063f,0.726563f, +0.296875f,0.726563f, +0.304688f,0.726563f, +0.3125f,0.726563f, +0.320313f,0.726563f, +0.328125f,0.726563f, +0.335938f,0.726563f, +0.34375f,0.726563f, +0.351563f,0.726563f, +0.359375f,0.726563f, +0.367188f,0.726563f, +0.375f,0.726563f, +0.382813f,0.726563f, +0.390625f,0.726563f, +0.398438f,0.726563f, +0.40625f,0.726563f, +0.414063f,0.726563f, +0.421875f,0.726563f, +0.429688f,0.726563f, +0.4375f,0.726563f, +0.445313f,0.726563f, +0.453125f,0.726563f, +0.460938f,0.726563f, +0.46875f,0.726563f, +0.476563f,0.726563f, +0.484375f,0.726563f, +0.492188f,0.726563f, +0.5f,0.726563f, +0.507813f,0.726563f, +0.0f,0.734375f, +0.0078125f,0.734375f, +0.015625f,0.734375f, +0.0234375f,0.734375f, +0.03125f,0.734375f, +0.0390625f,0.734375f, +0.046875f,0.734375f, +0.0546875f,0.734375f, +0.0625f,0.734375f, +0.0703125f,0.734375f, +0.078125f,0.734375f, +0.0859375f,0.734375f, +0.09375f,0.734375f, +0.101563f,0.734375f, +0.109375f,0.734375f, +0.117188f,0.734375f, +0.125f,0.734375f, +0.132813f,0.734375f, +0.140625f,0.734375f, +0.148438f,0.734375f, +0.15625f,0.734375f, +0.164063f,0.734375f, +0.171875f,0.734375f, +0.179688f,0.734375f, +0.1875f,0.734375f, +0.195313f,0.734375f, +0.203125f,0.734375f, +0.210938f,0.734375f, +0.21875f,0.734375f, +0.226563f,0.734375f, +0.234375f,0.734375f, +0.242188f,0.734375f, +0.25f,0.734375f, +0.257813f,0.734375f, +0.265625f,0.734375f, +0.273438f,0.734375f, +0.28125f,0.734375f, +0.289063f,0.734375f, +0.296875f,0.734375f, +0.304688f,0.734375f, +0.3125f,0.734375f, +0.320313f,0.734375f, +0.328125f,0.734375f, +0.335938f,0.734375f, +0.34375f,0.734375f, +0.351563f,0.734375f, +0.359375f,0.734375f, +0.367188f,0.734375f, +0.375f,0.734375f, +0.382813f,0.734375f, +0.390625f,0.734375f, +0.398438f,0.734375f, +0.40625f,0.734375f, +0.414063f,0.734375f, +0.421875f,0.734375f, +0.429688f,0.734375f, +0.4375f,0.734375f, +0.445313f,0.734375f, +0.453125f,0.734375f, +0.460938f,0.734375f, +0.46875f,0.734375f, +0.476563f,0.734375f, +0.484375f,0.734375f, +0.492188f,0.734375f, +0.5f,0.734375f, +0.507813f,0.734375f, +0.0f,0.742188f, +0.0078125f,0.742188f, +0.015625f,0.742188f, +0.0234375f,0.742188f, +0.03125f,0.742188f, +0.0390625f,0.742188f, +0.046875f,0.742188f, +0.0546875f,0.742188f, +0.0625f,0.742188f, +0.0703125f,0.742188f, +0.078125f,0.742188f, +0.0859375f,0.742188f, +0.09375f,0.742188f, +0.101563f,0.742188f, +0.109375f,0.742188f, +0.117188f,0.742188f, +0.125f,0.742188f, +0.132813f,0.742188f, +0.140625f,0.742188f, +0.148438f,0.742188f, +0.15625f,0.742188f, +0.164063f,0.742188f, +0.171875f,0.742188f, +0.179688f,0.742188f, +0.1875f,0.742188f, +0.195313f,0.742188f, +0.203125f,0.742188f, +0.210938f,0.742188f, +0.21875f,0.742188f, +0.226563f,0.742188f, +0.234375f,0.742188f, +0.242188f,0.742188f, +0.25f,0.742188f, +0.257813f,0.742188f, +0.265625f,0.742188f, +0.273438f,0.742188f, +0.28125f,0.742188f, +0.289063f,0.742188f, +0.296875f,0.742188f, +0.304688f,0.742188f, +0.3125f,0.742188f, +0.320313f,0.742188f, +0.328125f,0.742188f, +0.335938f,0.742188f, +0.34375f,0.742188f, +0.351563f,0.742188f, +0.359375f,0.742188f, +0.367188f,0.742188f, +0.375f,0.742188f, +0.382813f,0.742188f, +0.390625f,0.742188f, +0.398438f,0.742188f, +0.40625f,0.742188f, +0.414063f,0.742188f, +0.421875f,0.742188f, +0.429688f,0.742188f, +0.4375f,0.742188f, +0.445313f,0.742188f, +0.453125f,0.742188f, +0.460938f,0.742188f, +0.46875f,0.742188f, +0.476563f,0.742188f, +0.484375f,0.742188f, +0.492188f,0.742188f, +0.5f,0.742188f, +0.507813f,0.742188f, +0.0f,0.75f, +0.0078125f,0.75f, +0.015625f,0.75f, +0.0234375f,0.75f, +0.03125f,0.75f, +0.0390625f,0.75f, +0.046875f,0.75f, +0.0546875f,0.75f, +0.0625f,0.75f, +0.0703125f,0.75f, +0.078125f,0.75f, +0.0859375f,0.75f, +0.09375f,0.75f, +0.101563f,0.75f, +0.109375f,0.75f, +0.117188f,0.75f, +0.125f,0.75f, +0.132813f,0.75f, +0.140625f,0.75f, +0.148438f,0.75f, +0.15625f,0.75f, +0.164063f,0.75f, +0.171875f,0.75f, +0.179688f,0.75f, +0.1875f,0.75f, +0.195313f,0.75f, +0.203125f,0.75f, +0.210938f,0.75f, +0.21875f,0.75f, +0.226563f,0.75f, +0.234375f,0.75f, +0.242188f,0.75f, +0.25f,0.75f, +0.257813f,0.75f, +0.265625f,0.75f, +0.273438f,0.75f, +0.28125f,0.75f, +0.289063f,0.75f, +0.296875f,0.75f, +0.304688f,0.75f, +0.3125f,0.75f, +0.320313f,0.75f, +0.328125f,0.75f, +0.335938f,0.75f, +0.34375f,0.75f, +0.351563f,0.75f, +0.359375f,0.75f, +0.367188f,0.75f, +0.375f,0.75f, +0.382813f,0.75f, +0.390625f,0.75f, +0.398438f,0.75f, +0.40625f,0.75f, +0.414063f,0.75f, +0.421875f,0.75f, +0.429688f,0.75f, +0.4375f,0.75f, +0.445313f,0.75f, +0.453125f,0.75f, +0.460938f,0.75f, +0.46875f,0.75f, +0.476563f,0.75f, +0.484375f,0.75f, +0.492188f,0.75f, +0.5f,0.75f, +0.507813f,0.75f, +}; + +unsigned short Landscape05Idx[] = { +0,1,2, +3,2,1, +2,3,4, +5,4,3, +4,5,6, +7,6,5, +6,7,8, +9,8,7, +8,9,10, +11,10,9, +10,11,12, +13,12,11, +12,13,14, +15,14,13, +14,15,16, +17,16,15, +16,17,18, +19,18,17, +18,19,20, +21,20,19, +20,21,22, +23,22,21, +22,23,24, +25,24,23, +24,25,26, +27,26,25, +26,27,28, +29,28,27, +28,29,30, +31,30,29, +30,31,32, +33,32,31, +32,33,34, +35,34,33, +34,35,36, +37,36,35, +36,37,38, +39,38,37, +38,39,40, +41,40,39, +40,41,42, +43,42,41, +42,43,44, +45,44,43, +44,45,46, +47,46,45, +46,47,48, +49,48,47, +48,49,50, +51,50,49, +50,51,52, +53,52,51, +52,53,54, +55,54,53, +54,55,56, +57,56,55, +56,57,58, +59,58,57, +58,59,60, +61,60,59, +60,61,62, +63,62,61, +62,63,64, +65,64,63, +64,65,66, +67,66,65, +66,67,68, +69,68,67, +68,69,70, +71,70,69, +70,71,72, +73,72,71, +72,73,74, +75,74,73, +74,75,76, +77,76,75, +76,77,78, +79,78,77, +78,79,80, +81,80,79, +80,81,82, +83,82,81, +82,83,84, +85,84,83, +84,85,86, +87,86,85, +86,87,88, +89,88,87, +88,89,90, +91,90,89, +90,91,92, +93,92,91, +92,93,94, +95,94,93, +94,95,96, +97,96,95, +96,97,98, +99,98,97, +98,99,100, +101,100,99, +100,101,102, +103,102,101, +102,103,104, +105,104,103, +104,105,106, +107,106,105, +106,107,108, +109,108,107, +108,109,110, +111,110,109, +110,111,112, +113,112,111, +112,113,114, +115,114,113, +114,115,116, +117,116,115, +116,117,118, +119,118,117, +118,119,120, +121,120,119, +120,121,122, +123,122,121, +122,123,124, +125,124,123, +124,125,126, +127,126,125, +126,127,128, +129,128,127, +128,129,130, +131,130,129, +132,0,133, +2,133,0, +133,2,134, +4,134,2, +134,4,135, +6,135,4, +135,6,136, +8,136,6, +136,8,137, +10,137,8, +137,10,138, +12,138,10, +138,12,139, +14,139,12, +139,14,140, +16,140,14, +140,16,141, +18,141,16, +141,18,142, +20,142,18, +142,20,143, +22,143,20, +143,22,144, +24,144,22, +144,24,145, +26,145,24, +145,26,146, +28,146,26, +146,28,147, +30,147,28, +147,30,148, +32,148,30, +148,32,149, +34,149,32, +149,34,150, +36,150,34, +150,36,151, +38,151,36, +151,38,152, +40,152,38, +152,40,153, +42,153,40, +153,42,154, +44,154,42, +154,44,155, +46,155,44, +155,46,156, +48,156,46, +156,48,157, +50,157,48, +157,50,158, +52,158,50, +158,52,159, +54,159,52, +159,54,160, +56,160,54, +160,56,161, +58,161,56, +161,58,162, +60,162,58, +162,60,163, +62,163,60, +163,62,164, +64,164,62, +164,64,165, +66,165,64, +165,66,166, +68,166,66, +166,68,167, +70,167,68, +167,70,168, +72,168,70, +168,72,169, +74,169,72, +169,74,170, +76,170,74, +170,76,171, +78,171,76, +171,78,172, +80,172,78, +172,80,173, +82,173,80, +173,82,174, +84,174,82, +174,84,175, +86,175,84, +175,86,176, +88,176,86, +176,88,177, +90,177,88, +177,90,178, +92,178,90, +178,92,179, +94,179,92, +179,94,180, +96,180,94, +180,96,181, +98,181,96, +181,98,182, +100,182,98, +182,100,183, +102,183,100, +183,102,184, +104,184,102, +184,104,185, +106,185,104, +185,106,186, +108,186,106, +186,108,187, +110,187,108, +187,110,188, +112,188,110, +188,112,189, +114,189,112, +189,114,190, +116,190,114, +190,116,191, +118,191,116, +191,118,192, +120,192,118, +192,120,193, +122,193,120, +193,122,194, +124,194,122, +194,124,195, +126,195,124, +195,126,196, +128,196,126, +196,128,197, +130,197,128, +198,132,199, +133,199,132, +199,133,200, +134,200,133, +200,134,201, +135,201,134, +201,135,202, +136,202,135, +202,136,203, +137,203,136, +203,137,204, +138,204,137, +204,138,205, +139,205,138, +205,139,206, +140,206,139, +206,140,207, +141,207,140, +207,141,208, +142,208,141, +208,142,209, +143,209,142, +209,143,210, +144,210,143, +210,144,211, +145,211,144, +211,145,212, +146,212,145, +212,146,213, +147,213,146, +213,147,214, +148,214,147, +214,148,215, +149,215,148, +215,149,216, +150,216,149, +216,150,217, +151,217,150, +217,151,218, +152,218,151, +218,152,219, +153,219,152, +219,153,220, +154,220,153, +220,154,221, +155,221,154, +221,155,222, +156,222,155, +222,156,223, +157,223,156, +223,157,224, +158,224,157, +224,158,225, +159,225,158, +225,159,226, +160,226,159, +226,160,227, +161,227,160, +227,161,228, +162,228,161, +228,162,229, +163,229,162, +229,163,230, +164,230,163, +230,164,231, +165,231,164, +231,165,232, +166,232,165, +232,166,233, +167,233,166, +233,167,234, +168,234,167, +234,168,235, +169,235,168, +235,169,236, +170,236,169, +236,170,237, +171,237,170, +237,171,238, +172,238,171, +238,172,239, +173,239,172, +239,173,240, +174,240,173, +240,174,241, +175,241,174, +241,175,242, +176,242,175, +242,176,243, +177,243,176, +243,177,244, +178,244,177, +244,178,245, +179,245,178, +245,179,246, +180,246,179, +246,180,247, +181,247,180, +247,181,248, +182,248,181, +248,182,249, +183,249,182, +249,183,250, +184,250,183, +250,184,251, +185,251,184, +251,185,252, +186,252,185, +252,186,253, +187,253,186, +253,187,254, +188,254,187, +254,188,255, +189,255,188, +255,189,256, +190,256,189, +256,190,257, +191,257,190, +257,191,258, +192,258,191, +258,192,259, +193,259,192, +259,193,260, +194,260,193, +260,194,261, +195,261,194, +261,195,262, +196,262,195, +262,196,263, +197,263,196, +264,198,265, +199,265,198, +265,199,266, +200,266,199, +266,200,267, +201,267,200, +267,201,268, +202,268,201, +268,202,269, +203,269,202, +269,203,270, +204,270,203, +270,204,271, +205,271,204, +271,205,272, +206,272,205, +272,206,273, +207,273,206, +273,207,274, +208,274,207, +274,208,275, +209,275,208, +275,209,276, +210,276,209, +276,210,277, +211,277,210, +277,211,278, +212,278,211, +278,212,279, +213,279,212, +279,213,280, +214,280,213, +280,214,281, +215,281,214, +281,215,282, +216,282,215, +282,216,283, +217,283,216, +283,217,284, +218,284,217, +284,218,285, +219,285,218, +285,219,286, +220,286,219, +286,220,287, +221,287,220, +287,221,288, +222,288,221, +288,222,289, +223,289,222, +289,223,290, +224,290,223, +290,224,291, +225,291,224, +291,225,292, +226,292,225, +292,226,293, +227,293,226, +293,227,294, +228,294,227, +294,228,295, +229,295,228, +295,229,296, +230,296,229, +296,230,297, +231,297,230, +297,231,298, +232,298,231, +298,232,299, +233,299,232, +299,233,300, +234,300,233, +300,234,301, +235,301,234, +301,235,302, +236,302,235, +302,236,303, +237,303,236, +303,237,304, +238,304,237, +304,238,305, +239,305,238, +305,239,306, +240,306,239, +306,240,307, +241,307,240, +307,241,308, +242,308,241, +308,242,309, +243,309,242, +309,243,310, +244,310,243, +310,244,311, +245,311,244, +311,245,312, +246,312,245, +312,246,313, +247,313,246, +313,247,314, +248,314,247, +314,248,315, +249,315,248, +315,249,316, +250,316,249, +316,250,317, +251,317,250, +317,251,318, +252,318,251, +318,252,319, +253,319,252, +319,253,320, +254,320,253, +320,254,321, +255,321,254, +321,255,322, +256,322,255, +322,256,323, +257,323,256, +323,257,324, +258,324,257, +324,258,325, +259,325,258, +325,259,326, +260,326,259, +326,260,327, +261,327,260, +327,261,328, +262,328,261, +328,262,329, +263,329,262, +330,264,331, +265,331,264, +331,265,332, +266,332,265, +332,266,333, +267,333,266, +333,267,334, +268,334,267, +334,268,335, +269,335,268, +335,269,336, +270,336,269, +336,270,337, +271,337,270, +337,271,338, +272,338,271, +338,272,339, +273,339,272, +339,273,340, +274,340,273, +340,274,341, +275,341,274, +341,275,342, +276,342,275, +342,276,343, +277,343,276, +343,277,344, +278,344,277, +344,278,345, +279,345,278, +345,279,346, +280,346,279, +346,280,347, +281,347,280, +347,281,348, +282,348,281, +348,282,349, +283,349,282, +349,283,350, +284,350,283, +350,284,351, +285,351,284, +351,285,352, +286,352,285, +352,286,353, +287,353,286, +353,287,354, +288,354,287, +354,288,355, +289,355,288, +355,289,356, +290,356,289, +356,290,357, +291,357,290, +357,291,358, +292,358,291, +358,292,359, +293,359,292, +359,293,360, +294,360,293, +360,294,361, +295,361,294, +361,295,362, +296,362,295, +362,296,363, +297,363,296, +363,297,364, +298,364,297, +364,298,365, +299,365,298, +365,299,366, +300,366,299, +366,300,367, +301,367,300, +367,301,368, +302,368,301, +368,302,369, +303,369,302, +369,303,370, +304,370,303, +370,304,371, +305,371,304, +371,305,372, +306,372,305, +372,306,373, +307,373,306, +373,307,374, +308,374,307, +374,308,375, +309,375,308, +375,309,376, +310,376,309, +376,310,377, +311,377,310, +377,311,378, +312,378,311, +378,312,379, +313,379,312, +379,313,380, +314,380,313, +380,314,381, +315,381,314, +381,315,382, +316,382,315, +382,316,383, +317,383,316, +383,317,384, +318,384,317, +384,318,385, +319,385,318, +385,319,386, +320,386,319, +386,320,387, +321,387,320, +387,321,388, +322,388,321, +388,322,389, +323,389,322, +389,323,390, +324,390,323, +390,324,391, +325,391,324, +391,325,392, +326,392,325, +392,326,393, +327,393,326, +393,327,394, +328,394,327, +394,328,395, +329,395,328, +396,330,397, +331,397,330, +397,331,398, +332,398,331, +398,332,399, +333,399,332, +399,333,400, +334,400,333, +400,334,401, +335,401,334, +401,335,402, +336,402,335, +402,336,403, +337,403,336, +403,337,404, +338,404,337, +404,338,405, +339,405,338, +405,339,406, +340,406,339, +406,340,407, +341,407,340, +407,341,408, +342,408,341, +408,342,409, +343,409,342, +409,343,410, +344,410,343, +410,344,411, +345,411,344, +411,345,412, +346,412,345, +412,346,413, +347,413,346, +413,347,414, +348,414,347, +414,348,415, +349,415,348, +415,349,416, +350,416,349, +416,350,417, +351,417,350, +417,351,418, +352,418,351, +418,352,419, +353,419,352, +419,353,420, +354,420,353, +420,354,421, +355,421,354, +421,355,422, +356,422,355, +422,356,423, +357,423,356, +423,357,424, +358,424,357, +424,358,425, +359,425,358, +425,359,426, +360,426,359, +426,360,427, +361,427,360, +427,361,428, +362,428,361, +428,362,429, +363,429,362, +429,363,430, +364,430,363, +430,364,431, +365,431,364, +431,365,432, +366,432,365, +432,366,433, +367,433,366, +433,367,434, +368,434,367, +434,368,435, +369,435,368, +435,369,436, +370,436,369, +436,370,437, +371,437,370, +437,371,438, +372,438,371, +438,372,439, +373,439,372, +439,373,440, +374,440,373, +440,374,441, +375,441,374, +441,375,442, +376,442,375, +442,376,443, +377,443,376, +443,377,444, +378,444,377, +444,378,445, +379,445,378, +445,379,446, +380,446,379, +446,380,447, +381,447,380, +447,381,448, +382,448,381, +448,382,449, +383,449,382, +449,383,450, +384,450,383, +450,384,451, +385,451,384, +451,385,452, +386,452,385, +452,386,453, +387,453,386, +453,387,454, +388,454,387, +454,388,455, +389,455,388, +455,389,456, +390,456,389, +456,390,457, +391,457,390, +457,391,458, +392,458,391, +458,392,459, +393,459,392, +459,393,460, +394,460,393, +460,394,461, +395,461,394, +462,396,463, +397,463,396, +463,397,464, +398,464,397, +464,398,465, +399,465,398, +465,399,466, +400,466,399, +466,400,467, +401,467,400, +467,401,468, +402,468,401, +468,402,469, +403,469,402, +469,403,470, +404,470,403, +470,404,471, +405,471,404, +471,405,472, +406,472,405, +472,406,473, +407,473,406, +473,407,474, +408,474,407, +474,408,475, +409,475,408, +475,409,476, +410,476,409, +476,410,477, +411,477,410, +477,411,478, +412,478,411, +478,412,479, +413,479,412, +479,413,480, +414,480,413, +480,414,481, +415,481,414, +481,415,482, +416,482,415, +482,416,483, +417,483,416, +483,417,484, +418,484,417, +484,418,485, +419,485,418, +485,419,486, +420,486,419, +486,420,487, +421,487,420, +487,421,488, +422,488,421, +488,422,489, +423,489,422, +489,423,490, +424,490,423, +490,424,491, +425,491,424, +491,425,492, +426,492,425, +492,426,493, +427,493,426, +493,427,494, +428,494,427, +494,428,495, +429,495,428, +495,429,496, +430,496,429, +496,430,497, +431,497,430, +497,431,498, +432,498,431, +498,432,499, +433,499,432, +499,433,500, +434,500,433, +500,434,501, +435,501,434, +501,435,502, +436,502,435, +502,436,503, +437,503,436, +503,437,504, +438,504,437, +504,438,505, +439,505,438, +505,439,506, +440,506,439, +506,440,507, +441,507,440, +507,441,508, +442,508,441, +508,442,509, +443,509,442, +509,443,510, +444,510,443, +510,444,511, +445,511,444, +511,445,512, +446,512,445, +512,446,513, +447,513,446, +513,447,514, +448,514,447, +514,448,515, +449,515,448, +515,449,516, +450,516,449, +516,450,517, +451,517,450, +517,451,518, +452,518,451, +518,452,519, +453,519,452, +519,453,520, +454,520,453, +520,454,521, +455,521,454, +521,455,522, +456,522,455, +522,456,523, +457,523,456, +523,457,524, +458,524,457, +524,458,525, +459,525,458, +525,459,526, +460,526,459, +526,460,527, +461,527,460, +528,462,529, +463,529,462, +529,463,530, +464,530,463, +530,464,531, +465,531,464, +531,465,532, +466,532,465, +532,466,533, +467,533,466, +533,467,534, +468,534,467, +534,468,535, +469,535,468, +535,469,536, +470,536,469, +536,470,537, +471,537,470, +537,471,538, +472,538,471, +538,472,539, +473,539,472, +539,473,540, +474,540,473, +540,474,541, +475,541,474, +541,475,542, +476,542,475, +542,476,543, +477,543,476, +543,477,544, +478,544,477, +544,478,545, +479,545,478, +545,479,546, +480,546,479, +546,480,547, +481,547,480, +547,481,548, +482,548,481, +548,482,549, +483,549,482, +549,483,550, +484,550,483, +550,484,551, +485,551,484, +551,485,552, +486,552,485, +552,486,553, +487,553,486, +553,487,554, +488,554,487, +554,488,555, +489,555,488, +555,489,556, +490,556,489, +556,490,557, +491,557,490, +557,491,558, +492,558,491, +558,492,559, +493,559,492, +559,493,560, +494,560,493, +560,494,561, +495,561,494, +561,495,562, +496,562,495, +562,496,563, +497,563,496, +563,497,564, +498,564,497, +564,498,565, +499,565,498, +565,499,566, +500,566,499, +566,500,567, +501,567,500, +567,501,568, +502,568,501, +568,502,569, +503,569,502, +569,503,570, +504,570,503, +570,504,571, +505,571,504, +571,505,572, +506,572,505, +572,506,573, +507,573,506, +573,507,574, +508,574,507, +574,508,575, +509,575,508, +575,509,576, +510,576,509, +576,510,577, +511,577,510, +577,511,578, +512,578,511, +578,512,579, +513,579,512, +579,513,580, +514,580,513, +580,514,581, +515,581,514, +581,515,582, +516,582,515, +582,516,583, +517,583,516, +583,517,584, +518,584,517, +584,518,585, +519,585,518, +585,519,586, +520,586,519, +586,520,587, +521,587,520, +587,521,588, +522,588,521, +588,522,589, +523,589,522, +589,523,590, +524,590,523, +590,524,591, +525,591,524, +591,525,592, +526,592,525, +592,526,593, +527,593,526, +594,528,595, +529,595,528, +595,529,596, +530,596,529, +596,530,597, +531,597,530, +597,531,598, +532,598,531, +598,532,599, +533,599,532, +599,533,600, +534,600,533, +600,534,601, +535,601,534, +601,535,602, +536,602,535, +602,536,603, +537,603,536, +603,537,604, +538,604,537, +604,538,605, +539,605,538, +605,539,606, +540,606,539, +606,540,607, +541,607,540, +607,541,608, +542,608,541, +608,542,609, +543,609,542, +609,543,610, +544,610,543, +610,544,611, +545,611,544, +611,545,612, +546,612,545, +612,546,613, +547,613,546, +613,547,614, +548,614,547, +614,548,615, +549,615,548, +615,549,616, +550,616,549, +616,550,617, +551,617,550, +617,551,618, +552,618,551, +618,552,619, +553,619,552, +619,553,620, +554,620,553, +620,554,621, +555,621,554, +621,555,622, +556,622,555, +622,556,623, +557,623,556, +623,557,624, +558,624,557, +624,558,625, +559,625,558, +625,559,626, +560,626,559, +626,560,627, +561,627,560, +627,561,628, +562,628,561, +628,562,629, +563,629,562, +629,563,630, +564,630,563, +630,564,631, +565,631,564, +631,565,632, +566,632,565, +632,566,633, +567,633,566, +633,567,634, +568,634,567, +634,568,635, +569,635,568, +635,569,636, +570,636,569, +636,570,637, +571,637,570, +637,571,638, +572,638,571, +638,572,639, +573,639,572, +639,573,640, +574,640,573, +640,574,641, +575,641,574, +641,575,642, +576,642,575, +642,576,643, +577,643,576, +643,577,644, +578,644,577, +644,578,645, +579,645,578, +645,579,646, +580,646,579, +646,580,647, +581,647,580, +647,581,648, +582,648,581, +648,582,649, +583,649,582, +649,583,650, +584,650,583, +650,584,651, +585,651,584, +651,585,652, +586,652,585, +652,586,653, +587,653,586, +653,587,654, +588,654,587, +654,588,655, +589,655,588, +655,589,656, +590,656,589, +656,590,657, +591,657,590, +657,591,658, +592,658,591, +658,592,659, +593,659,592, +660,594,661, +595,661,594, +661,595,662, +596,662,595, +662,596,663, +597,663,596, +663,597,664, +598,664,597, +664,598,665, +599,665,598, +665,599,666, +600,666,599, +666,600,667, +601,667,600, +667,601,668, +602,668,601, +668,602,669, +603,669,602, +669,603,670, +604,670,603, +670,604,671, +605,671,604, +671,605,672, +606,672,605, +672,606,673, +607,673,606, +673,607,674, +608,674,607, +674,608,675, +609,675,608, +675,609,676, +610,676,609, +676,610,677, +611,677,610, +677,611,678, +612,678,611, +678,612,679, +613,679,612, +679,613,680, +614,680,613, +680,614,681, +615,681,614, +681,615,682, +616,682,615, +682,616,683, +617,683,616, +683,617,684, +618,684,617, +684,618,685, +619,685,618, +685,619,686, +620,686,619, +686,620,687, +621,687,620, +687,621,688, +622,688,621, +688,622,689, +623,689,622, +689,623,690, +624,690,623, +690,624,691, +625,691,624, +691,625,692, +626,692,625, +692,626,693, +627,693,626, +693,627,694, +628,694,627, +694,628,695, +629,695,628, +695,629,696, +630,696,629, +696,630,697, +631,697,630, +697,631,698, +632,698,631, +698,632,699, +633,699,632, +699,633,700, +634,700,633, +700,634,701, +635,701,634, +701,635,702, +636,702,635, +702,636,703, +637,703,636, +703,637,704, +638,704,637, +704,638,705, +639,705,638, +705,639,706, +640,706,639, +706,640,707, +641,707,640, +707,641,708, +642,708,641, +708,642,709, +643,709,642, +709,643,710, +644,710,643, +710,644,711, +645,711,644, +711,645,712, +646,712,645, +712,646,713, +647,713,646, +713,647,714, +648,714,647, +714,648,715, +649,715,648, +715,649,716, +650,716,649, +716,650,717, +651,717,650, +717,651,718, +652,718,651, +718,652,719, +653,719,652, +719,653,720, +654,720,653, +720,654,721, +655,721,654, +721,655,722, +656,722,655, +722,656,723, +657,723,656, +723,657,724, +658,724,657, +724,658,725, +659,725,658, +726,660,727, +661,727,660, +727,661,728, +662,728,661, +728,662,729, +663,729,662, +729,663,730, +664,730,663, +730,664,731, +665,731,664, +731,665,732, +666,732,665, +732,666,733, +667,733,666, +733,667,734, +668,734,667, +734,668,735, +669,735,668, +735,669,736, +670,736,669, +736,670,737, +671,737,670, +737,671,738, +672,738,671, +738,672,739, +673,739,672, +739,673,740, +674,740,673, +740,674,741, +675,741,674, +741,675,742, +676,742,675, +742,676,743, +677,743,676, +743,677,744, +678,744,677, +744,678,745, +679,745,678, +745,679,746, +680,746,679, +746,680,747, +681,747,680, +747,681,748, +682,748,681, +748,682,749, +683,749,682, +749,683,750, +684,750,683, +750,684,751, +685,751,684, +751,685,752, +686,752,685, +752,686,753, +687,753,686, +753,687,754, +688,754,687, +754,688,755, +689,755,688, +755,689,756, +690,756,689, +756,690,757, +691,757,690, +757,691,758, +692,758,691, +758,692,759, +693,759,692, +759,693,760, +694,760,693, +760,694,761, +695,761,694, +761,695,762, +696,762,695, +762,696,763, +697,763,696, +763,697,764, +698,764,697, +764,698,765, +699,765,698, +765,699,766, +700,766,699, +766,700,767, +701,767,700, +767,701,768, +702,768,701, +768,702,769, +703,769,702, +769,703,770, +704,770,703, +770,704,771, +705,771,704, +771,705,772, +706,772,705, +772,706,773, +707,773,706, +773,707,774, +708,774,707, +774,708,775, +709,775,708, +775,709,776, +710,776,709, +776,710,777, +711,777,710, +777,711,778, +712,778,711, +778,712,779, +713,779,712, +779,713,780, +714,780,713, +780,714,781, +715,781,714, +781,715,782, +716,782,715, +782,716,783, +717,783,716, +783,717,784, +718,784,717, +784,718,785, +719,785,718, +785,719,786, +720,786,719, +786,720,787, +721,787,720, +787,721,788, +722,788,721, +788,722,789, +723,789,722, +789,723,790, +724,790,723, +790,724,791, +725,791,724, +792,726,793, +727,793,726, +793,727,794, +728,794,727, +794,728,795, +729,795,728, +795,729,796, +730,796,729, +796,730,797, +731,797,730, +797,731,798, +732,798,731, +798,732,799, +733,799,732, +799,733,800, +734,800,733, +800,734,801, +735,801,734, +801,735,802, +736,802,735, +802,736,803, +737,803,736, +803,737,804, +738,804,737, +804,738,805, +739,805,738, +805,739,806, +740,806,739, +806,740,807, +741,807,740, +807,741,808, +742,808,741, +808,742,809, +743,809,742, +809,743,810, +744,810,743, +810,744,811, +745,811,744, +811,745,812, +746,812,745, +812,746,813, +747,813,746, +813,747,814, +748,814,747, +814,748,815, +749,815,748, +815,749,816, +750,816,749, +816,750,817, +751,817,750, +817,751,818, +752,818,751, +818,752,819, +753,819,752, +819,753,820, +754,820,753, +820,754,821, +755,821,754, +821,755,822, +756,822,755, +822,756,823, +757,823,756, +823,757,824, +758,824,757, +824,758,825, +759,825,758, +825,759,826, +760,826,759, +826,760,827, +761,827,760, +827,761,828, +762,828,761, +828,762,829, +763,829,762, +829,763,830, +764,830,763, +830,764,831, +765,831,764, +831,765,832, +766,832,765, +832,766,833, +767,833,766, +833,767,834, +768,834,767, +834,768,835, +769,835,768, +835,769,836, +770,836,769, +836,770,837, +771,837,770, +837,771,838, +772,838,771, +838,772,839, +773,839,772, +839,773,840, +774,840,773, +840,774,841, +775,841,774, +841,775,842, +776,842,775, +842,776,843, +777,843,776, +843,777,844, +778,844,777, +844,778,845, +779,845,778, +845,779,846, +780,846,779, +846,780,847, +781,847,780, +847,781,848, +782,848,781, +848,782,849, +783,849,782, +849,783,850, +784,850,783, +850,784,851, +785,851,784, +851,785,852, +786,852,785, +852,786,853, +787,853,786, +853,787,854, +788,854,787, +854,788,855, +789,855,788, +855,789,856, +790,856,789, +856,790,857, +791,857,790, +858,792,859, +793,859,792, +859,793,860, +794,860,793, +860,794,861, +795,861,794, +861,795,862, +796,862,795, +862,796,863, +797,863,796, +863,797,864, +798,864,797, +864,798,865, +799,865,798, +865,799,866, +800,866,799, +866,800,867, +801,867,800, +867,801,868, +802,868,801, +868,802,869, +803,869,802, +869,803,870, +804,870,803, +870,804,871, +805,871,804, +871,805,872, +806,872,805, +872,806,873, +807,873,806, +873,807,874, +808,874,807, +874,808,875, +809,875,808, +875,809,876, +810,876,809, +876,810,877, +811,877,810, +877,811,878, +812,878,811, +878,812,879, +813,879,812, +879,813,880, +814,880,813, +880,814,881, +815,881,814, +881,815,882, +816,882,815, +882,816,883, +817,883,816, +883,817,884, +818,884,817, +884,818,885, +819,885,818, +885,819,886, +820,886,819, +886,820,887, +821,887,820, +887,821,888, +822,888,821, +888,822,889, +823,889,822, +889,823,890, +824,890,823, +890,824,891, +825,891,824, +891,825,892, +826,892,825, +892,826,893, +827,893,826, +893,827,894, +828,894,827, +894,828,895, +829,895,828, +895,829,896, +830,896,829, +896,830,897, +831,897,830, +897,831,898, +832,898,831, +898,832,899, +833,899,832, +899,833,900, +834,900,833, +900,834,901, +835,901,834, +901,835,902, +836,902,835, +902,836,903, +837,903,836, +903,837,904, +838,904,837, +904,838,905, +839,905,838, +905,839,906, +840,906,839, +906,840,907, +841,907,840, +907,841,908, +842,908,841, +908,842,909, +843,909,842, +909,843,910, +844,910,843, +910,844,911, +845,911,844, +911,845,912, +846,912,845, +912,846,913, +847,913,846, +913,847,914, +848,914,847, +914,848,915, +849,915,848, +915,849,916, +850,916,849, +916,850,917, +851,917,850, +917,851,918, +852,918,851, +918,852,919, +853,919,852, +919,853,920, +854,920,853, +920,854,921, +855,921,854, +921,855,922, +856,922,855, +922,856,923, +857,923,856, +924,858,925, +859,925,858, +925,859,926, +860,926,859, +926,860,927, +861,927,860, +927,861,928, +862,928,861, +928,862,929, +863,929,862, +929,863,930, +864,930,863, +930,864,931, +865,931,864, +931,865,932, +866,932,865, +932,866,933, +867,933,866, +933,867,934, +868,934,867, +934,868,935, +869,935,868, +935,869,936, +870,936,869, +936,870,937, +871,937,870, +937,871,938, +872,938,871, +938,872,939, +873,939,872, +939,873,940, +874,940,873, +940,874,941, +875,941,874, +941,875,942, +876,942,875, +942,876,943, +877,943,876, +943,877,944, +878,944,877, +944,878,945, +879,945,878, +945,879,946, +880,946,879, +946,880,947, +881,947,880, +947,881,948, +882,948,881, +948,882,949, +883,949,882, +949,883,950, +884,950,883, +950,884,951, +885,951,884, +951,885,952, +886,952,885, +952,886,953, +887,953,886, +953,887,954, +888,954,887, +954,888,955, +889,955,888, +955,889,956, +890,956,889, +956,890,957, +891,957,890, +957,891,958, +892,958,891, +958,892,959, +893,959,892, +959,893,960, +894,960,893, +960,894,961, +895,961,894, +961,895,962, +896,962,895, +962,896,963, +897,963,896, +963,897,964, +898,964,897, +964,898,965, +899,965,898, +965,899,966, +900,966,899, +966,900,967, +901,967,900, +967,901,968, +902,968,901, +968,902,969, +903,969,902, +969,903,970, +904,970,903, +970,904,971, +905,971,904, +971,905,972, +906,972,905, +972,906,973, +907,973,906, +973,907,974, +908,974,907, +974,908,975, +909,975,908, +975,909,976, +910,976,909, +976,910,977, +911,977,910, +977,911,978, +912,978,911, +978,912,979, +913,979,912, +979,913,980, +914,980,913, +980,914,981, +915,981,914, +981,915,982, +916,982,915, +982,916,983, +917,983,916, +983,917,984, +918,984,917, +984,918,985, +919,985,918, +985,919,986, +920,986,919, +986,920,987, +921,987,920, +987,921,988, +922,988,921, +988,922,989, +923,989,922, +990,924,991, +925,991,924, +991,925,992, +926,992,925, +992,926,993, +927,993,926, +993,927,994, +928,994,927, +994,928,995, +929,995,928, +995,929,996, +930,996,929, +996,930,997, +931,997,930, +997,931,998, +932,998,931, +998,932,999, +933,999,932, +999,933,1000, +934,1000,933, +1000,934,1001, +935,1001,934, +1001,935,1002, +936,1002,935, +1002,936,1003, +937,1003,936, +1003,937,1004, +938,1004,937, +1004,938,1005, +939,1005,938, +1005,939,1006, +940,1006,939, +1006,940,1007, +941,1007,940, +1007,941,1008, +942,1008,941, +1008,942,1009, +943,1009,942, +1009,943,1010, +944,1010,943, +1010,944,1011, +945,1011,944, +1011,945,1012, +946,1012,945, +1012,946,1013, +947,1013,946, +1013,947,1014, +948,1014,947, +1014,948,1015, +949,1015,948, +1015,949,1016, +950,1016,949, +1016,950,1017, +951,1017,950, +1017,951,1018, +952,1018,951, +1018,952,1019, +953,1019,952, +1019,953,1020, +954,1020,953, +1020,954,1021, +955,1021,954, +1021,955,1022, +956,1022,955, +1022,956,1023, +957,1023,956, +1023,957,1024, +958,1024,957, +1024,958,1025, +959,1025,958, +1025,959,1026, +960,1026,959, +1026,960,1027, +961,1027,960, +1027,961,1028, +962,1028,961, +1028,962,1029, +963,1029,962, +1029,963,1030, +964,1030,963, +1030,964,1031, +965,1031,964, +1031,965,1032, +966,1032,965, +1032,966,1033, +967,1033,966, +1033,967,1034, +968,1034,967, +1034,968,1035, +969,1035,968, +1035,969,1036, +970,1036,969, +1036,970,1037, +971,1037,970, +1037,971,1038, +972,1038,971, +1038,972,1039, +973,1039,972, +1039,973,1040, +974,1040,973, +1040,974,1041, +975,1041,974, +1041,975,1042, +976,1042,975, +1042,976,1043, +977,1043,976, +1043,977,1044, +978,1044,977, +1044,978,1045, +979,1045,978, +1045,979,1046, +980,1046,979, +1046,980,1047, +981,1047,980, +1047,981,1048, +982,1048,981, +1048,982,1049, +983,1049,982, +1049,983,1050, +984,1050,983, +1050,984,1051, +985,1051,984, +1051,985,1052, +986,1052,985, +1052,986,1053, +987,1053,986, +1053,987,1054, +988,1054,987, +1054,988,1055, +989,1055,988, +1056,990,1057, +991,1057,990, +1057,991,1058, +992,1058,991, +1058,992,1059, +993,1059,992, +1059,993,1060, +994,1060,993, +1060,994,1061, +995,1061,994, +1061,995,1062, +996,1062,995, +1062,996,1063, +997,1063,996, +1063,997,1064, +998,1064,997, +1064,998,1065, +999,1065,998, +1065,999,1066, +1000,1066,999, +1066,1000,1067, +1001,1067,1000, +1067,1001,1068, +1002,1068,1001, +1068,1002,1069, +1003,1069,1002, +1069,1003,1070, +1004,1070,1003, +1070,1004,1071, +1005,1071,1004, +1071,1005,1072, +1006,1072,1005, +1072,1006,1073, +1007,1073,1006, +1073,1007,1074, +1008,1074,1007, +1074,1008,1075, +1009,1075,1008, +1075,1009,1076, +1010,1076,1009, +1076,1010,1077, +1011,1077,1010, +1077,1011,1078, +1012,1078,1011, +1078,1012,1079, +1013,1079,1012, +1079,1013,1080, +1014,1080,1013, +1080,1014,1081, +1015,1081,1014, +1081,1015,1082, +1016,1082,1015, +1082,1016,1083, +1017,1083,1016, +1083,1017,1084, +1018,1084,1017, +1084,1018,1085, +1019,1085,1018, +1085,1019,1086, +1020,1086,1019, +1086,1020,1087, +1021,1087,1020, +1087,1021,1088, +1022,1088,1021, +1088,1022,1089, +1023,1089,1022, +1089,1023,1090, +1024,1090,1023, +1090,1024,1091, +1025,1091,1024, +1091,1025,1092, +1026,1092,1025, +1092,1026,1093, +1027,1093,1026, +1093,1027,1094, +1028,1094,1027, +1094,1028,1095, +1029,1095,1028, +1095,1029,1096, +1030,1096,1029, +1096,1030,1097, +1031,1097,1030, +1097,1031,1098, +1032,1098,1031, +1098,1032,1099, +1033,1099,1032, +1099,1033,1100, +1034,1100,1033, +1100,1034,1101, +1035,1101,1034, +1101,1035,1102, +1036,1102,1035, +1102,1036,1103, +1037,1103,1036, +1103,1037,1104, +1038,1104,1037, +1104,1038,1105, +1039,1105,1038, +1105,1039,1106, +1040,1106,1039, +1106,1040,1107, +1041,1107,1040, +1107,1041,1108, +1042,1108,1041, +1108,1042,1109, +1043,1109,1042, +1109,1043,1110, +1044,1110,1043, +1110,1044,1111, +1045,1111,1044, +1111,1045,1112, +1046,1112,1045, +1112,1046,1113, +1047,1113,1046, +1113,1047,1114, +1048,1114,1047, +1114,1048,1115, +1049,1115,1048, +1115,1049,1116, +1050,1116,1049, +1116,1050,1117, +1051,1117,1050, +1117,1051,1118, +1052,1118,1051, +1118,1052,1119, +1053,1119,1052, +1119,1053,1120, +1054,1120,1053, +1120,1054,1121, +1055,1121,1054, +1122,1056,1123, +1057,1123,1056, +1123,1057,1124, +1058,1124,1057, +1124,1058,1125, +1059,1125,1058, +1125,1059,1126, +1060,1126,1059, +1126,1060,1127, +1061,1127,1060, +1127,1061,1128, +1062,1128,1061, +1128,1062,1129, +1063,1129,1062, +1129,1063,1130, +1064,1130,1063, +1130,1064,1131, +1065,1131,1064, +1131,1065,1132, +1066,1132,1065, +1132,1066,1133, +1067,1133,1066, +1133,1067,1134, +1068,1134,1067, +1134,1068,1135, +1069,1135,1068, +1135,1069,1136, +1070,1136,1069, +1136,1070,1137, +1071,1137,1070, +1137,1071,1138, +1072,1138,1071, +1138,1072,1139, +1073,1139,1072, +1139,1073,1140, +1074,1140,1073, +1140,1074,1141, +1075,1141,1074, +1141,1075,1142, +1076,1142,1075, +1142,1076,1143, +1077,1143,1076, +1143,1077,1144, +1078,1144,1077, +1144,1078,1145, +1079,1145,1078, +1145,1079,1146, +1080,1146,1079, +1146,1080,1147, +1081,1147,1080, +1147,1081,1148, +1082,1148,1081, +1148,1082,1149, +1083,1149,1082, +1149,1083,1150, +1084,1150,1083, +1150,1084,1151, +1085,1151,1084, +1151,1085,1152, +1086,1152,1085, +1152,1086,1153, +1087,1153,1086, +1153,1087,1154, +1088,1154,1087, +1154,1088,1155, +1089,1155,1088, +1155,1089,1156, +1090,1156,1089, +1156,1090,1157, +1091,1157,1090, +1157,1091,1158, +1092,1158,1091, +1158,1092,1159, +1093,1159,1092, +1159,1093,1160, +1094,1160,1093, +1160,1094,1161, +1095,1161,1094, +1161,1095,1162, +1096,1162,1095, +1162,1096,1163, +1097,1163,1096, +1163,1097,1164, +1098,1164,1097, +1164,1098,1165, +1099,1165,1098, +1165,1099,1166, +1100,1166,1099, +1166,1100,1167, +1101,1167,1100, +1167,1101,1168, +1102,1168,1101, +1168,1102,1169, +1103,1169,1102, +1169,1103,1170, +1104,1170,1103, +1170,1104,1171, +1105,1171,1104, +1171,1105,1172, +1106,1172,1105, +1172,1106,1173, +1107,1173,1106, +1173,1107,1174, +1108,1174,1107, +1174,1108,1175, +1109,1175,1108, +1175,1109,1176, +1110,1176,1109, +1176,1110,1177, +1111,1177,1110, +1177,1111,1178, +1112,1178,1111, +1178,1112,1179, +1113,1179,1112, +1179,1113,1180, +1114,1180,1113, +1180,1114,1181, +1115,1181,1114, +1181,1115,1182, +1116,1182,1115, +1182,1116,1183, +1117,1183,1116, +1183,1117,1184, +1118,1184,1117, +1184,1118,1185, +1119,1185,1118, +1185,1119,1186, +1120,1186,1119, +1186,1120,1187, +1121,1187,1120, +1188,1122,1189, +1123,1189,1122, +1189,1123,1190, +1124,1190,1123, +1190,1124,1191, +1125,1191,1124, +1191,1125,1192, +1126,1192,1125, +1192,1126,1193, +1127,1193,1126, +1193,1127,1194, +1128,1194,1127, +1194,1128,1195, +1129,1195,1128, +1195,1129,1196, +1130,1196,1129, +1196,1130,1197, +1131,1197,1130, +1197,1131,1198, +1132,1198,1131, +1198,1132,1199, +1133,1199,1132, +1199,1133,1200, +1134,1200,1133, +1200,1134,1201, +1135,1201,1134, +1201,1135,1202, +1136,1202,1135, +1202,1136,1203, +1137,1203,1136, +1203,1137,1204, +1138,1204,1137, +1204,1138,1205, +1139,1205,1138, +1205,1139,1206, +1140,1206,1139, +1206,1140,1207, +1141,1207,1140, +1207,1141,1208, +1142,1208,1141, +1208,1142,1209, +1143,1209,1142, +1209,1143,1210, +1144,1210,1143, +1210,1144,1211, +1145,1211,1144, +1211,1145,1212, +1146,1212,1145, +1212,1146,1213, +1147,1213,1146, +1213,1147,1214, +1148,1214,1147, +1214,1148,1215, +1149,1215,1148, +1215,1149,1216, +1150,1216,1149, +1216,1150,1217, +1151,1217,1150, +1217,1151,1218, +1152,1218,1151, +1218,1152,1219, +1153,1219,1152, +1219,1153,1220, +1154,1220,1153, +1220,1154,1221, +1155,1221,1154, +1221,1155,1222, +1156,1222,1155, +1222,1156,1223, +1157,1223,1156, +1223,1157,1224, +1158,1224,1157, +1224,1158,1225, +1159,1225,1158, +1225,1159,1226, +1160,1226,1159, +1226,1160,1227, +1161,1227,1160, +1227,1161,1228, +1162,1228,1161, +1228,1162,1229, +1163,1229,1162, +1229,1163,1230, +1164,1230,1163, +1230,1164,1231, +1165,1231,1164, +1231,1165,1232, +1166,1232,1165, +1232,1166,1233, +1167,1233,1166, +1233,1167,1234, +1168,1234,1167, +1234,1168,1235, +1169,1235,1168, +1235,1169,1236, +1170,1236,1169, +1236,1170,1237, +1171,1237,1170, +1237,1171,1238, +1172,1238,1171, +1238,1172,1239, +1173,1239,1172, +1239,1173,1240, +1174,1240,1173, +1240,1174,1241, +1175,1241,1174, +1241,1175,1242, +1176,1242,1175, +1242,1176,1243, +1177,1243,1176, +1243,1177,1244, +1178,1244,1177, +1244,1178,1245, +1179,1245,1178, +1245,1179,1246, +1180,1246,1179, +1246,1180,1247, +1181,1247,1180, +1247,1181,1248, +1182,1248,1181, +1248,1182,1249, +1183,1249,1182, +1249,1183,1250, +1184,1250,1183, +1250,1184,1251, +1185,1251,1184, +1251,1185,1252, +1186,1252,1185, +1252,1186,1253, +1187,1253,1186, +1254,1188,1255, +1189,1255,1188, +1255,1189,1256, +1190,1256,1189, +1256,1190,1257, +1191,1257,1190, +1257,1191,1258, +1192,1258,1191, +1258,1192,1259, +1193,1259,1192, +1259,1193,1260, +1194,1260,1193, +1260,1194,1261, +1195,1261,1194, +1261,1195,1262, +1196,1262,1195, +1262,1196,1263, +1197,1263,1196, +1263,1197,1264, +1198,1264,1197, +1264,1198,1265, +1199,1265,1198, +1265,1199,1266, +1200,1266,1199, +1266,1200,1267, +1201,1267,1200, +1267,1201,1268, +1202,1268,1201, +1268,1202,1269, +1203,1269,1202, +1269,1203,1270, +1204,1270,1203, +1270,1204,1271, +1205,1271,1204, +1271,1205,1272, +1206,1272,1205, +1272,1206,1273, +1207,1273,1206, +1273,1207,1274, +1208,1274,1207, +1274,1208,1275, +1209,1275,1208, +1275,1209,1276, +1210,1276,1209, +1276,1210,1277, +1211,1277,1210, +1277,1211,1278, +1212,1278,1211, +1278,1212,1279, +1213,1279,1212, +1279,1213,1280, +1214,1280,1213, +1280,1214,1281, +1215,1281,1214, +1281,1215,1282, +1216,1282,1215, +1282,1216,1283, +1217,1283,1216, +1283,1217,1284, +1218,1284,1217, +1284,1218,1285, +1219,1285,1218, +1285,1219,1286, +1220,1286,1219, +1286,1220,1287, +1221,1287,1220, +1287,1221,1288, +1222,1288,1221, +1288,1222,1289, +1223,1289,1222, +1289,1223,1290, +1224,1290,1223, +1290,1224,1291, +1225,1291,1224, +1291,1225,1292, +1226,1292,1225, +1292,1226,1293, +1227,1293,1226, +1293,1227,1294, +1228,1294,1227, +1294,1228,1295, +1229,1295,1228, +1295,1229,1296, +1230,1296,1229, +1296,1230,1297, +1231,1297,1230, +1297,1231,1298, +1232,1298,1231, +1298,1232,1299, +1233,1299,1232, +1299,1233,1300, +1234,1300,1233, +1300,1234,1301, +1235,1301,1234, +1301,1235,1302, +1236,1302,1235, +1302,1236,1303, +1237,1303,1236, +1303,1237,1304, +1238,1304,1237, +1304,1238,1305, +1239,1305,1238, +1305,1239,1306, +1240,1306,1239, +1306,1240,1307, +1241,1307,1240, +1307,1241,1308, +1242,1308,1241, +1308,1242,1309, +1243,1309,1242, +1309,1243,1310, +1244,1310,1243, +1310,1244,1311, +1245,1311,1244, +1311,1245,1312, +1246,1312,1245, +1312,1246,1313, +1247,1313,1246, +1313,1247,1314, +1248,1314,1247, +1314,1248,1315, +1249,1315,1248, +1315,1249,1316, +1250,1316,1249, +1316,1250,1317, +1251,1317,1250, +1317,1251,1318, +1252,1318,1251, +1318,1252,1319, +1253,1319,1252, +1320,1254,1321, +1255,1321,1254, +1321,1255,1322, +1256,1322,1255, +1322,1256,1323, +1257,1323,1256, +1323,1257,1324, +1258,1324,1257, +1324,1258,1325, +1259,1325,1258, +1325,1259,1326, +1260,1326,1259, +1326,1260,1327, +1261,1327,1260, +1327,1261,1328, +1262,1328,1261, +1328,1262,1329, +1263,1329,1262, +1329,1263,1330, +1264,1330,1263, +1330,1264,1331, +1265,1331,1264, +1331,1265,1332, +1266,1332,1265, +1332,1266,1333, +1267,1333,1266, +1333,1267,1334, +1268,1334,1267, +1334,1268,1335, +1269,1335,1268, +1335,1269,1336, +1270,1336,1269, +1336,1270,1337, +1271,1337,1270, +1337,1271,1338, +1272,1338,1271, +1338,1272,1339, +1273,1339,1272, +1339,1273,1340, +1274,1340,1273, +1340,1274,1341, +1275,1341,1274, +1341,1275,1342, +1276,1342,1275, +1342,1276,1343, +1277,1343,1276, +1343,1277,1344, +1278,1344,1277, +1344,1278,1345, +1279,1345,1278, +1345,1279,1346, +1280,1346,1279, +1346,1280,1347, +1281,1347,1280, +1347,1281,1348, +1282,1348,1281, +1348,1282,1349, +1283,1349,1282, +1349,1283,1350, +1284,1350,1283, +1350,1284,1351, +1285,1351,1284, +1351,1285,1352, +1286,1352,1285, +1352,1286,1353, +1287,1353,1286, +1353,1287,1354, +1288,1354,1287, +1354,1288,1355, +1289,1355,1288, +1355,1289,1356, +1290,1356,1289, +1356,1290,1357, +1291,1357,1290, +1357,1291,1358, +1292,1358,1291, +1358,1292,1359, +1293,1359,1292, +1359,1293,1360, +1294,1360,1293, +1360,1294,1361, +1295,1361,1294, +1361,1295,1362, +1296,1362,1295, +1362,1296,1363, +1297,1363,1296, +1363,1297,1364, +1298,1364,1297, +1364,1298,1365, +1299,1365,1298, +1365,1299,1366, +1300,1366,1299, +1366,1300,1367, +1301,1367,1300, +1367,1301,1368, +1302,1368,1301, +1368,1302,1369, +1303,1369,1302, +1369,1303,1370, +1304,1370,1303, +1370,1304,1371, +1305,1371,1304, +1371,1305,1372, +1306,1372,1305, +1372,1306,1373, +1307,1373,1306, +1373,1307,1374, +1308,1374,1307, +1374,1308,1375, +1309,1375,1308, +1375,1309,1376, +1310,1376,1309, +1376,1310,1377, +1311,1377,1310, +1377,1311,1378, +1312,1378,1311, +1378,1312,1379, +1313,1379,1312, +1379,1313,1380, +1314,1380,1313, +1380,1314,1381, +1315,1381,1314, +1381,1315,1382, +1316,1382,1315, +1382,1316,1383, +1317,1383,1316, +1383,1317,1384, +1318,1384,1317, +1384,1318,1385, +1319,1385,1318, +1386,1320,1387, +1321,1387,1320, +1387,1321,1388, +1322,1388,1321, +1388,1322,1389, +1323,1389,1322, +1389,1323,1390, +1324,1390,1323, +1390,1324,1391, +1325,1391,1324, +1391,1325,1392, +1326,1392,1325, +1392,1326,1393, +1327,1393,1326, +1393,1327,1394, +1328,1394,1327, +1394,1328,1395, +1329,1395,1328, +1395,1329,1396, +1330,1396,1329, +1396,1330,1397, +1331,1397,1330, +1397,1331,1398, +1332,1398,1331, +1398,1332,1399, +1333,1399,1332, +1399,1333,1400, +1334,1400,1333, +1400,1334,1401, +1335,1401,1334, +1401,1335,1402, +1336,1402,1335, +1402,1336,1403, +1337,1403,1336, +1403,1337,1404, +1338,1404,1337, +1404,1338,1405, +1339,1405,1338, +1405,1339,1406, +1340,1406,1339, +1406,1340,1407, +1341,1407,1340, +1407,1341,1408, +1342,1408,1341, +1408,1342,1409, +1343,1409,1342, +1409,1343,1410, +1344,1410,1343, +1410,1344,1411, +1345,1411,1344, +1411,1345,1412, +1346,1412,1345, +1412,1346,1413, +1347,1413,1346, +1413,1347,1414, +1348,1414,1347, +1414,1348,1415, +1349,1415,1348, +1415,1349,1416, +1350,1416,1349, +1416,1350,1417, +1351,1417,1350, +1417,1351,1418, +1352,1418,1351, +1418,1352,1419, +1353,1419,1352, +1419,1353,1420, +1354,1420,1353, +1420,1354,1421, +1355,1421,1354, +1421,1355,1422, +1356,1422,1355, +1422,1356,1423, +1357,1423,1356, +1423,1357,1424, +1358,1424,1357, +1424,1358,1425, +1359,1425,1358, +1425,1359,1426, +1360,1426,1359, +1426,1360,1427, +1361,1427,1360, +1427,1361,1428, +1362,1428,1361, +1428,1362,1429, +1363,1429,1362, +1429,1363,1430, +1364,1430,1363, +1430,1364,1431, +1365,1431,1364, +1431,1365,1432, +1366,1432,1365, +1432,1366,1433, +1367,1433,1366, +1433,1367,1434, +1368,1434,1367, +1434,1368,1435, +1369,1435,1368, +1435,1369,1436, +1370,1436,1369, +1436,1370,1437, +1371,1437,1370, +1437,1371,1438, +1372,1438,1371, +1438,1372,1439, +1373,1439,1372, +1439,1373,1440, +1374,1440,1373, +1440,1374,1441, +1375,1441,1374, +1441,1375,1442, +1376,1442,1375, +1442,1376,1443, +1377,1443,1376, +1443,1377,1444, +1378,1444,1377, +1444,1378,1445, +1379,1445,1378, +1445,1379,1446, +1380,1446,1379, +1446,1380,1447, +1381,1447,1380, +1447,1381,1448, +1382,1448,1381, +1448,1382,1449, +1383,1449,1382, +1449,1383,1450, +1384,1450,1383, +1450,1384,1451, +1385,1451,1384, +1452,1386,1453, +1387,1453,1386, +1453,1387,1454, +1388,1454,1387, +1454,1388,1455, +1389,1455,1388, +1455,1389,1456, +1390,1456,1389, +1456,1390,1457, +1391,1457,1390, +1457,1391,1458, +1392,1458,1391, +1458,1392,1459, +1393,1459,1392, +1459,1393,1460, +1394,1460,1393, +1460,1394,1461, +1395,1461,1394, +1461,1395,1462, +1396,1462,1395, +1462,1396,1463, +1397,1463,1396, +1463,1397,1464, +1398,1464,1397, +1464,1398,1465, +1399,1465,1398, +1465,1399,1466, +1400,1466,1399, +1466,1400,1467, +1401,1467,1400, +1467,1401,1468, +1402,1468,1401, +1468,1402,1469, +1403,1469,1402, +1469,1403,1470, +1404,1470,1403, +1470,1404,1471, +1405,1471,1404, +1471,1405,1472, +1406,1472,1405, +1472,1406,1473, +1407,1473,1406, +1473,1407,1474, +1408,1474,1407, +1474,1408,1475, +1409,1475,1408, +1475,1409,1476, +1410,1476,1409, +1476,1410,1477, +1411,1477,1410, +1477,1411,1478, +1412,1478,1411, +1478,1412,1479, +1413,1479,1412, +1479,1413,1480, +1414,1480,1413, +1480,1414,1481, +1415,1481,1414, +1481,1415,1482, +1416,1482,1415, +1482,1416,1483, +1417,1483,1416, +1483,1417,1484, +1418,1484,1417, +1484,1418,1485, +1419,1485,1418, +1485,1419,1486, +1420,1486,1419, +1486,1420,1487, +1421,1487,1420, +1487,1421,1488, +1422,1488,1421, +1488,1422,1489, +1423,1489,1422, +1489,1423,1490, +1424,1490,1423, +1490,1424,1491, +1425,1491,1424, +1491,1425,1492, +1426,1492,1425, +1492,1426,1493, +1427,1493,1426, +1493,1427,1494, +1428,1494,1427, +1494,1428,1495, +1429,1495,1428, +1495,1429,1496, +1430,1496,1429, +1496,1430,1497, +1431,1497,1430, +1497,1431,1498, +1432,1498,1431, +1498,1432,1499, +1433,1499,1432, +1499,1433,1500, +1434,1500,1433, +1500,1434,1501, +1435,1501,1434, +1501,1435,1502, +1436,1502,1435, +1502,1436,1503, +1437,1503,1436, +1503,1437,1504, +1438,1504,1437, +1504,1438,1505, +1439,1505,1438, +1505,1439,1506, +1440,1506,1439, +1506,1440,1507, +1441,1507,1440, +1507,1441,1508, +1442,1508,1441, +1508,1442,1509, +1443,1509,1442, +1509,1443,1510, +1444,1510,1443, +1510,1444,1511, +1445,1511,1444, +1511,1445,1512, +1446,1512,1445, +1512,1446,1513, +1447,1513,1446, +1513,1447,1514, +1448,1514,1447, +1514,1448,1515, +1449,1515,1448, +1515,1449,1516, +1450,1516,1449, +1516,1450,1517, +1451,1517,1450, +1518,1452,1519, +1453,1519,1452, +1519,1453,1520, +1454,1520,1453, +1520,1454,1521, +1455,1521,1454, +1521,1455,1522, +1456,1522,1455, +1522,1456,1523, +1457,1523,1456, +1523,1457,1524, +1458,1524,1457, +1524,1458,1525, +1459,1525,1458, +1525,1459,1526, +1460,1526,1459, +1526,1460,1527, +1461,1527,1460, +1527,1461,1528, +1462,1528,1461, +1528,1462,1529, +1463,1529,1462, +1529,1463,1530, +1464,1530,1463, +1530,1464,1531, +1465,1531,1464, +1531,1465,1532, +1466,1532,1465, +1532,1466,1533, +1467,1533,1466, +1533,1467,1534, +1468,1534,1467, +1534,1468,1535, +1469,1535,1468, +1535,1469,1536, +1470,1536,1469, +1536,1470,1537, +1471,1537,1470, +1537,1471,1538, +1472,1538,1471, +1538,1472,1539, +1473,1539,1472, +1539,1473,1540, +1474,1540,1473, +1540,1474,1541, +1475,1541,1474, +1541,1475,1542, +1476,1542,1475, +1542,1476,1543, +1477,1543,1476, +1543,1477,1544, +1478,1544,1477, +1544,1478,1545, +1479,1545,1478, +1545,1479,1546, +1480,1546,1479, +1546,1480,1547, +1481,1547,1480, +1547,1481,1548, +1482,1548,1481, +1548,1482,1549, +1483,1549,1482, +1549,1483,1550, +1484,1550,1483, +1550,1484,1551, +1485,1551,1484, +1551,1485,1552, +1486,1552,1485, +1552,1486,1553, +1487,1553,1486, +1553,1487,1554, +1488,1554,1487, +1554,1488,1555, +1489,1555,1488, +1555,1489,1556, +1490,1556,1489, +1556,1490,1557, +1491,1557,1490, +1557,1491,1558, +1492,1558,1491, +1558,1492,1559, +1493,1559,1492, +1559,1493,1560, +1494,1560,1493, +1560,1494,1561, +1495,1561,1494, +1561,1495,1562, +1496,1562,1495, +1562,1496,1563, +1497,1563,1496, +1563,1497,1564, +1498,1564,1497, +1564,1498,1565, +1499,1565,1498, +1565,1499,1566, +1500,1566,1499, +1566,1500,1567, +1501,1567,1500, +1567,1501,1568, +1502,1568,1501, +1568,1502,1569, +1503,1569,1502, +1569,1503,1570, +1504,1570,1503, +1570,1504,1571, +1505,1571,1504, +1571,1505,1572, +1506,1572,1505, +1572,1506,1573, +1507,1573,1506, +1573,1507,1574, +1508,1574,1507, +1574,1508,1575, +1509,1575,1508, +1575,1509,1576, +1510,1576,1509, +1576,1510,1577, +1511,1577,1510, +1577,1511,1578, +1512,1578,1511, +1578,1512,1579, +1513,1579,1512, +1579,1513,1580, +1514,1580,1513, +1580,1514,1581, +1515,1581,1514, +1581,1515,1582, +1516,1582,1515, +1582,1516,1583, +1517,1583,1516, +1584,1518,1585, +1519,1585,1518, +1585,1519,1586, +1520,1586,1519, +1586,1520,1587, +1521,1587,1520, +1587,1521,1588, +1522,1588,1521, +1588,1522,1589, +1523,1589,1522, +1589,1523,1590, +1524,1590,1523, +1590,1524,1591, +1525,1591,1524, +1591,1525,1592, +1526,1592,1525, +1592,1526,1593, +1527,1593,1526, +1593,1527,1594, +1528,1594,1527, +1594,1528,1595, +1529,1595,1528, +1595,1529,1596, +1530,1596,1529, +1596,1530,1597, +1531,1597,1530, +1597,1531,1598, +1532,1598,1531, +1598,1532,1599, +1533,1599,1532, +1599,1533,1600, +1534,1600,1533, +1600,1534,1601, +1535,1601,1534, +1601,1535,1602, +1536,1602,1535, +1602,1536,1603, +1537,1603,1536, +1603,1537,1604, +1538,1604,1537, +1604,1538,1605, +1539,1605,1538, +1605,1539,1606, +1540,1606,1539, +1606,1540,1607, +1541,1607,1540, +1607,1541,1608, +1542,1608,1541, +1608,1542,1609, +1543,1609,1542, +1609,1543,1610, +1544,1610,1543, +1610,1544,1611, +1545,1611,1544, +1611,1545,1612, +1546,1612,1545, +1612,1546,1613, +1547,1613,1546, +1613,1547,1614, +1548,1614,1547, +1614,1548,1615, +1549,1615,1548, +1615,1549,1616, +1550,1616,1549, +1616,1550,1617, +1551,1617,1550, +1617,1551,1618, +1552,1618,1551, +1618,1552,1619, +1553,1619,1552, +1619,1553,1620, +1554,1620,1553, +1620,1554,1621, +1555,1621,1554, +1621,1555,1622, +1556,1622,1555, +1622,1556,1623, +1557,1623,1556, +1623,1557,1624, +1558,1624,1557, +1624,1558,1625, +1559,1625,1558, +1625,1559,1626, +1560,1626,1559, +1626,1560,1627, +1561,1627,1560, +1627,1561,1628, +1562,1628,1561, +1628,1562,1629, +1563,1629,1562, +1629,1563,1630, +1564,1630,1563, +1630,1564,1631, +1565,1631,1564, +1631,1565,1632, +1566,1632,1565, +1632,1566,1633, +1567,1633,1566, +1633,1567,1634, +1568,1634,1567, +1634,1568,1635, +1569,1635,1568, +1635,1569,1636, +1570,1636,1569, +1636,1570,1637, +1571,1637,1570, +1637,1571,1638, +1572,1638,1571, +1638,1572,1639, +1573,1639,1572, +1639,1573,1640, +1574,1640,1573, +1640,1574,1641, +1575,1641,1574, +1641,1575,1642, +1576,1642,1575, +1642,1576,1643, +1577,1643,1576, +1643,1577,1644, +1578,1644,1577, +1644,1578,1645, +1579,1645,1578, +1645,1579,1646, +1580,1646,1579, +1646,1580,1647, +1581,1647,1580, +1647,1581,1648, +1582,1648,1581, +1648,1582,1649, +1583,1649,1582, +1650,1584,1651, +1585,1651,1584, +1651,1585,1652, +1586,1652,1585, +1652,1586,1653, +1587,1653,1586, +1653,1587,1654, +1588,1654,1587, +1654,1588,1655, +1589,1655,1588, +1655,1589,1656, +1590,1656,1589, +1656,1590,1657, +1591,1657,1590, +1657,1591,1658, +1592,1658,1591, +1658,1592,1659, +1593,1659,1592, +1659,1593,1660, +1594,1660,1593, +1660,1594,1661, +1595,1661,1594, +1661,1595,1662, +1596,1662,1595, +1662,1596,1663, +1597,1663,1596, +1663,1597,1664, +1598,1664,1597, +1664,1598,1665, +1599,1665,1598, +1665,1599,1666, +1600,1666,1599, +1666,1600,1667, +1601,1667,1600, +1667,1601,1668, +1602,1668,1601, +1668,1602,1669, +1603,1669,1602, +1669,1603,1670, +1604,1670,1603, +1670,1604,1671, +1605,1671,1604, +1671,1605,1672, +1606,1672,1605, +1672,1606,1673, +1607,1673,1606, +1673,1607,1674, +1608,1674,1607, +1674,1608,1675, +1609,1675,1608, +1675,1609,1676, +1610,1676,1609, +1676,1610,1677, +1611,1677,1610, +1677,1611,1678, +1612,1678,1611, +1678,1612,1679, +1613,1679,1612, +1679,1613,1680, +1614,1680,1613, +1680,1614,1681, +1615,1681,1614, +1681,1615,1682, +1616,1682,1615, +1682,1616,1683, +1617,1683,1616, +1683,1617,1684, +1618,1684,1617, +1684,1618,1685, +1619,1685,1618, +1685,1619,1686, +1620,1686,1619, +1686,1620,1687, +1621,1687,1620, +1687,1621,1688, +1622,1688,1621, +1688,1622,1689, +1623,1689,1622, +1689,1623,1690, +1624,1690,1623, +1690,1624,1691, +1625,1691,1624, +1691,1625,1692, +1626,1692,1625, +1692,1626,1693, +1627,1693,1626, +1693,1627,1694, +1628,1694,1627, +1694,1628,1695, +1629,1695,1628, +1695,1629,1696, +1630,1696,1629, +1696,1630,1697, +1631,1697,1630, +1697,1631,1698, +1632,1698,1631, +1698,1632,1699, +1633,1699,1632, +1699,1633,1700, +1634,1700,1633, +1700,1634,1701, +1635,1701,1634, +1701,1635,1702, +1636,1702,1635, +1702,1636,1703, +1637,1703,1636, +1703,1637,1704, +1638,1704,1637, +1704,1638,1705, +1639,1705,1638, +1705,1639,1706, +1640,1706,1639, +1706,1640,1707, +1641,1707,1640, +1707,1641,1708, +1642,1708,1641, +1708,1642,1709, +1643,1709,1642, +1709,1643,1710, +1644,1710,1643, +1710,1644,1711, +1645,1711,1644, +1711,1645,1712, +1646,1712,1645, +1712,1646,1713, +1647,1713,1646, +1713,1647,1714, +1648,1714,1647, +1714,1648,1715, +1649,1715,1648, +1716,1650,1717, +1651,1717,1650, +1717,1651,1718, +1652,1718,1651, +1718,1652,1719, +1653,1719,1652, +1719,1653,1720, +1654,1720,1653, +1720,1654,1721, +1655,1721,1654, +1721,1655,1722, +1656,1722,1655, +1722,1656,1723, +1657,1723,1656, +1723,1657,1724, +1658,1724,1657, +1724,1658,1725, +1659,1725,1658, +1725,1659,1726, +1660,1726,1659, +1726,1660,1727, +1661,1727,1660, +1727,1661,1728, +1662,1728,1661, +1728,1662,1729, +1663,1729,1662, +1729,1663,1730, +1664,1730,1663, +1730,1664,1731, +1665,1731,1664, +1731,1665,1732, +1666,1732,1665, +1732,1666,1733, +1667,1733,1666, +1733,1667,1734, +1668,1734,1667, +1734,1668,1735, +1669,1735,1668, +1735,1669,1736, +1670,1736,1669, +1736,1670,1737, +1671,1737,1670, +1737,1671,1738, +1672,1738,1671, +1738,1672,1739, +1673,1739,1672, +1739,1673,1740, +1674,1740,1673, +1740,1674,1741, +1675,1741,1674, +1741,1675,1742, +1676,1742,1675, +1742,1676,1743, +1677,1743,1676, +1743,1677,1744, +1678,1744,1677, +1744,1678,1745, +1679,1745,1678, +1745,1679,1746, +1680,1746,1679, +1746,1680,1747, +1681,1747,1680, +1747,1681,1748, +1682,1748,1681, +1748,1682,1749, +1683,1749,1682, +1749,1683,1750, +1684,1750,1683, +1750,1684,1751, +1685,1751,1684, +1751,1685,1752, +1686,1752,1685, +1752,1686,1753, +1687,1753,1686, +1753,1687,1754, +1688,1754,1687, +1754,1688,1755, +1689,1755,1688, +1755,1689,1756, +1690,1756,1689, +1756,1690,1757, +1691,1757,1690, +1757,1691,1758, +1692,1758,1691, +1758,1692,1759, +1693,1759,1692, +1759,1693,1760, +1694,1760,1693, +1760,1694,1761, +1695,1761,1694, +1761,1695,1762, +1696,1762,1695, +1762,1696,1763, +1697,1763,1696, +1763,1697,1764, +1698,1764,1697, +1764,1698,1765, +1699,1765,1698, +1765,1699,1766, +1700,1766,1699, +1766,1700,1767, +1701,1767,1700, +1767,1701,1768, +1702,1768,1701, +1768,1702,1769, +1703,1769,1702, +1769,1703,1770, +1704,1770,1703, +1770,1704,1771, +1705,1771,1704, +1771,1705,1772, +1706,1772,1705, +1772,1706,1773, +1707,1773,1706, +1773,1707,1774, +1708,1774,1707, +1774,1708,1775, +1709,1775,1708, +1775,1709,1776, +1710,1776,1709, +1776,1710,1777, +1711,1777,1710, +1777,1711,1778, +1712,1778,1711, +1778,1712,1779, +1713,1779,1712, +1779,1713,1780, +1714,1780,1713, +1780,1714,1781, +1715,1781,1714, +1782,1716,1783, +1717,1783,1716, +1783,1717,1784, +1718,1784,1717, +1784,1718,1785, +1719,1785,1718, +1785,1719,1786, +1720,1786,1719, +1786,1720,1787, +1721,1787,1720, +1787,1721,1788, +1722,1788,1721, +1788,1722,1789, +1723,1789,1722, +1789,1723,1790, +1724,1790,1723, +1790,1724,1791, +1725,1791,1724, +1791,1725,1792, +1726,1792,1725, +1792,1726,1793, +1727,1793,1726, +1793,1727,1794, +1728,1794,1727, +1794,1728,1795, +1729,1795,1728, +1795,1729,1796, +1730,1796,1729, +1796,1730,1797, +1731,1797,1730, +1797,1731,1798, +1732,1798,1731, +1798,1732,1799, +1733,1799,1732, +1799,1733,1800, +1734,1800,1733, +1800,1734,1801, +1735,1801,1734, +1801,1735,1802, +1736,1802,1735, +1802,1736,1803, +1737,1803,1736, +1803,1737,1804, +1738,1804,1737, +1804,1738,1805, +1739,1805,1738, +1805,1739,1806, +1740,1806,1739, +1806,1740,1807, +1741,1807,1740, +1807,1741,1808, +1742,1808,1741, +1808,1742,1809, +1743,1809,1742, +1809,1743,1810, +1744,1810,1743, +1810,1744,1811, +1745,1811,1744, +1811,1745,1812, +1746,1812,1745, +1812,1746,1813, +1747,1813,1746, +1813,1747,1814, +1748,1814,1747, +1814,1748,1815, +1749,1815,1748, +1815,1749,1816, +1750,1816,1749, +1816,1750,1817, +1751,1817,1750, +1817,1751,1818, +1752,1818,1751, +1818,1752,1819, +1753,1819,1752, +1819,1753,1820, +1754,1820,1753, +1820,1754,1821, +1755,1821,1754, +1821,1755,1822, +1756,1822,1755, +1822,1756,1823, +1757,1823,1756, +1823,1757,1824, +1758,1824,1757, +1824,1758,1825, +1759,1825,1758, +1825,1759,1826, +1760,1826,1759, +1826,1760,1827, +1761,1827,1760, +1827,1761,1828, +1762,1828,1761, +1828,1762,1829, +1763,1829,1762, +1829,1763,1830, +1764,1830,1763, +1830,1764,1831, +1765,1831,1764, +1831,1765,1832, +1766,1832,1765, +1832,1766,1833, +1767,1833,1766, +1833,1767,1834, +1768,1834,1767, +1834,1768,1835, +1769,1835,1768, +1835,1769,1836, +1770,1836,1769, +1836,1770,1837, +1771,1837,1770, +1837,1771,1838, +1772,1838,1771, +1838,1772,1839, +1773,1839,1772, +1839,1773,1840, +1774,1840,1773, +1840,1774,1841, +1775,1841,1774, +1841,1775,1842, +1776,1842,1775, +1842,1776,1843, +1777,1843,1776, +1843,1777,1844, +1778,1844,1777, +1844,1778,1845, +1779,1845,1778, +1845,1779,1846, +1780,1846,1779, +1846,1780,1847, +1781,1847,1780, +1848,1782,1849, +1783,1849,1782, +1849,1783,1850, +1784,1850,1783, +1850,1784,1851, +1785,1851,1784, +1851,1785,1852, +1786,1852,1785, +1852,1786,1853, +1787,1853,1786, +1853,1787,1854, +1788,1854,1787, +1854,1788,1855, +1789,1855,1788, +1855,1789,1856, +1790,1856,1789, +1856,1790,1857, +1791,1857,1790, +1857,1791,1858, +1792,1858,1791, +1858,1792,1859, +1793,1859,1792, +1859,1793,1860, +1794,1860,1793, +1860,1794,1861, +1795,1861,1794, +1861,1795,1862, +1796,1862,1795, +1862,1796,1863, +1797,1863,1796, +1863,1797,1864, +1798,1864,1797, +1864,1798,1865, +1799,1865,1798, +1865,1799,1866, +1800,1866,1799, +1866,1800,1867, +1801,1867,1800, +1867,1801,1868, +1802,1868,1801, +1868,1802,1869, +1803,1869,1802, +1869,1803,1870, +1804,1870,1803, +1870,1804,1871, +1805,1871,1804, +1871,1805,1872, +1806,1872,1805, +1872,1806,1873, +1807,1873,1806, +1873,1807,1874, +1808,1874,1807, +1874,1808,1875, +1809,1875,1808, +1875,1809,1876, +1810,1876,1809, +1876,1810,1877, +1811,1877,1810, +1877,1811,1878, +1812,1878,1811, +1878,1812,1879, +1813,1879,1812, +1879,1813,1880, +1814,1880,1813, +1880,1814,1881, +1815,1881,1814, +1881,1815,1882, +1816,1882,1815, +1882,1816,1883, +1817,1883,1816, +1883,1817,1884, +1818,1884,1817, +1884,1818,1885, +1819,1885,1818, +1885,1819,1886, +1820,1886,1819, +1886,1820,1887, +1821,1887,1820, +1887,1821,1888, +1822,1888,1821, +1888,1822,1889, +1823,1889,1822, +1889,1823,1890, +1824,1890,1823, +1890,1824,1891, +1825,1891,1824, +1891,1825,1892, +1826,1892,1825, +1892,1826,1893, +1827,1893,1826, +1893,1827,1894, +1828,1894,1827, +1894,1828,1895, +1829,1895,1828, +1895,1829,1896, +1830,1896,1829, +1896,1830,1897, +1831,1897,1830, +1897,1831,1898, +1832,1898,1831, +1898,1832,1899, +1833,1899,1832, +1899,1833,1900, +1834,1900,1833, +1900,1834,1901, +1835,1901,1834, +1901,1835,1902, +1836,1902,1835, +1902,1836,1903, +1837,1903,1836, +1903,1837,1904, +1838,1904,1837, +1904,1838,1905, +1839,1905,1838, +1905,1839,1906, +1840,1906,1839, +1906,1840,1907, +1841,1907,1840, +1907,1841,1908, +1842,1908,1841, +1908,1842,1909, +1843,1909,1842, +1909,1843,1910, +1844,1910,1843, +1910,1844,1911, +1845,1911,1844, +1911,1845,1912, +1846,1912,1845, +1912,1846,1913, +1847,1913,1846, +1914,1848,1915, +1849,1915,1848, +1915,1849,1916, +1850,1916,1849, +1916,1850,1917, +1851,1917,1850, +1917,1851,1918, +1852,1918,1851, +1918,1852,1919, +1853,1919,1852, +1919,1853,1920, +1854,1920,1853, +1920,1854,1921, +1855,1921,1854, +1921,1855,1922, +1856,1922,1855, +1922,1856,1923, +1857,1923,1856, +1923,1857,1924, +1858,1924,1857, +1924,1858,1925, +1859,1925,1858, +1925,1859,1926, +1860,1926,1859, +1926,1860,1927, +1861,1927,1860, +1927,1861,1928, +1862,1928,1861, +1928,1862,1929, +1863,1929,1862, +1929,1863,1930, +1864,1930,1863, +1930,1864,1931, +1865,1931,1864, +1931,1865,1932, +1866,1932,1865, +1932,1866,1933, +1867,1933,1866, +1933,1867,1934, +1868,1934,1867, +1934,1868,1935, +1869,1935,1868, +1935,1869,1936, +1870,1936,1869, +1936,1870,1937, +1871,1937,1870, +1937,1871,1938, +1872,1938,1871, +1938,1872,1939, +1873,1939,1872, +1939,1873,1940, +1874,1940,1873, +1940,1874,1941, +1875,1941,1874, +1941,1875,1942, +1876,1942,1875, +1942,1876,1943, +1877,1943,1876, +1943,1877,1944, +1878,1944,1877, +1944,1878,1945, +1879,1945,1878, +1945,1879,1946, +1880,1946,1879, +1946,1880,1947, +1881,1947,1880, +1947,1881,1948, +1882,1948,1881, +1948,1882,1949, +1883,1949,1882, +1949,1883,1950, +1884,1950,1883, +1950,1884,1951, +1885,1951,1884, +1951,1885,1952, +1886,1952,1885, +1952,1886,1953, +1887,1953,1886, +1953,1887,1954, +1888,1954,1887, +1954,1888,1955, +1889,1955,1888, +1955,1889,1956, +1890,1956,1889, +1956,1890,1957, +1891,1957,1890, +1957,1891,1958, +1892,1958,1891, +1958,1892,1959, +1893,1959,1892, +1959,1893,1960, +1894,1960,1893, +1960,1894,1961, +1895,1961,1894, +1961,1895,1962, +1896,1962,1895, +1962,1896,1963, +1897,1963,1896, +1963,1897,1964, +1898,1964,1897, +1964,1898,1965, +1899,1965,1898, +1965,1899,1966, +1900,1966,1899, +1966,1900,1967, +1901,1967,1900, +1967,1901,1968, +1902,1968,1901, +1968,1902,1969, +1903,1969,1902, +1969,1903,1970, +1904,1970,1903, +1970,1904,1971, +1905,1971,1904, +1971,1905,1972, +1906,1972,1905, +1972,1906,1973, +1907,1973,1906, +1973,1907,1974, +1908,1974,1907, +1974,1908,1975, +1909,1975,1908, +1975,1909,1976, +1910,1976,1909, +1976,1910,1977, +1911,1977,1910, +1977,1911,1978, +1912,1978,1911, +1978,1912,1979, +1913,1979,1912, +1980,1914,1981, +1915,1981,1914, +1981,1915,1982, +1916,1982,1915, +1982,1916,1983, +1917,1983,1916, +1983,1917,1984, +1918,1984,1917, +1984,1918,1985, +1919,1985,1918, +1985,1919,1986, +1920,1986,1919, +1986,1920,1987, +1921,1987,1920, +1987,1921,1988, +1922,1988,1921, +1988,1922,1989, +1923,1989,1922, +1989,1923,1990, +1924,1990,1923, +1990,1924,1991, +1925,1991,1924, +1991,1925,1992, +1926,1992,1925, +1992,1926,1993, +1927,1993,1926, +1993,1927,1994, +1928,1994,1927, +1994,1928,1995, +1929,1995,1928, +1995,1929,1996, +1930,1996,1929, +1996,1930,1997, +1931,1997,1930, +1997,1931,1998, +1932,1998,1931, +1998,1932,1999, +1933,1999,1932, +1999,1933,2000, +1934,2000,1933, +2000,1934,2001, +1935,2001,1934, +2001,1935,2002, +1936,2002,1935, +2002,1936,2003, +1937,2003,1936, +2003,1937,2004, +1938,2004,1937, +2004,1938,2005, +1939,2005,1938, +2005,1939,2006, +1940,2006,1939, +2006,1940,2007, +1941,2007,1940, +2007,1941,2008, +1942,2008,1941, +2008,1942,2009, +1943,2009,1942, +2009,1943,2010, +1944,2010,1943, +2010,1944,2011, +1945,2011,1944, +2011,1945,2012, +1946,2012,1945, +2012,1946,2013, +1947,2013,1946, +2013,1947,2014, +1948,2014,1947, +2014,1948,2015, +1949,2015,1948, +2015,1949,2016, +1950,2016,1949, +2016,1950,2017, +1951,2017,1950, +2017,1951,2018, +1952,2018,1951, +2018,1952,2019, +1953,2019,1952, +2019,1953,2020, +1954,2020,1953, +2020,1954,2021, +1955,2021,1954, +2021,1955,2022, +1956,2022,1955, +2022,1956,2023, +1957,2023,1956, +2023,1957,2024, +1958,2024,1957, +2024,1958,2025, +1959,2025,1958, +2025,1959,2026, +1960,2026,1959, +2026,1960,2027, +1961,2027,1960, +2027,1961,2028, +1962,2028,1961, +2028,1962,2029, +1963,2029,1962, +2029,1963,2030, +1964,2030,1963, +2030,1964,2031, +1965,2031,1964, +2031,1965,2032, +1966,2032,1965, +2032,1966,2033, +1967,2033,1966, +2033,1967,2034, +1968,2034,1967, +2034,1968,2035, +1969,2035,1968, +2035,1969,2036, +1970,2036,1969, +2036,1970,2037, +1971,2037,1970, +2037,1971,2038, +1972,2038,1971, +2038,1972,2039, +1973,2039,1972, +2039,1973,2040, +1974,2040,1973, +2040,1974,2041, +1975,2041,1974, +2041,1975,2042, +1976,2042,1975, +2042,1976,2043, +1977,2043,1976, +2043,1977,2044, +1978,2044,1977, +2044,1978,2045, +1979,2045,1978, +2046,1980,2047, +1981,2047,1980, +2047,1981,2048, +1982,2048,1981, +2048,1982,2049, +1983,2049,1982, +2049,1983,2050, +1984,2050,1983, +2050,1984,2051, +1985,2051,1984, +2051,1985,2052, +1986,2052,1985, +2052,1986,2053, +1987,2053,1986, +2053,1987,2054, +1988,2054,1987, +2054,1988,2055, +1989,2055,1988, +2055,1989,2056, +1990,2056,1989, +2056,1990,2057, +1991,2057,1990, +2057,1991,2058, +1992,2058,1991, +2058,1992,2059, +1993,2059,1992, +2059,1993,2060, +1994,2060,1993, +2060,1994,2061, +1995,2061,1994, +2061,1995,2062, +1996,2062,1995, +2062,1996,2063, +1997,2063,1996, +2063,1997,2064, +1998,2064,1997, +2064,1998,2065, +1999,2065,1998, +2065,1999,2066, +2000,2066,1999, +2066,2000,2067, +2001,2067,2000, +2067,2001,2068, +2002,2068,2001, +2068,2002,2069, +2003,2069,2002, +2069,2003,2070, +2004,2070,2003, +2070,2004,2071, +2005,2071,2004, +2071,2005,2072, +2006,2072,2005, +2072,2006,2073, +2007,2073,2006, +2073,2007,2074, +2008,2074,2007, +2074,2008,2075, +2009,2075,2008, +2075,2009,2076, +2010,2076,2009, +2076,2010,2077, +2011,2077,2010, +2077,2011,2078, +2012,2078,2011, +2078,2012,2079, +2013,2079,2012, +2079,2013,2080, +2014,2080,2013, +2080,2014,2081, +2015,2081,2014, +2081,2015,2082, +2016,2082,2015, +2082,2016,2083, +2017,2083,2016, +2083,2017,2084, +2018,2084,2017, +2084,2018,2085, +2019,2085,2018, +2085,2019,2086, +2020,2086,2019, +2086,2020,2087, +2021,2087,2020, +2087,2021,2088, +2022,2088,2021, +2088,2022,2089, +2023,2089,2022, +2089,2023,2090, +2024,2090,2023, +2090,2024,2091, +2025,2091,2024, +2091,2025,2092, +2026,2092,2025, +2092,2026,2093, +2027,2093,2026, +2093,2027,2094, +2028,2094,2027, +2094,2028,2095, +2029,2095,2028, +2095,2029,2096, +2030,2096,2029, +2096,2030,2097, +2031,2097,2030, +2097,2031,2098, +2032,2098,2031, +2098,2032,2099, +2033,2099,2032, +2099,2033,2100, +2034,2100,2033, +2100,2034,2101, +2035,2101,2034, +2101,2035,2102, +2036,2102,2035, +2102,2036,2103, +2037,2103,2036, +2103,2037,2104, +2038,2104,2037, +2104,2038,2105, +2039,2105,2038, +2105,2039,2106, +2040,2106,2039, +2106,2040,2107, +2041,2107,2040, +2107,2041,2108, +2042,2108,2041, +2108,2042,2109, +2043,2109,2042, +2109,2043,2110, +2044,2110,2043, +2110,2044,2111, +2045,2111,2044, +2112,2046,2113, +2047,2113,2046, +2113,2047,2114, +2048,2114,2047, +2114,2048,2115, +2049,2115,2048, +2115,2049,2116, +2050,2116,2049, +2116,2050,2117, +2051,2117,2050, +2117,2051,2118, +2052,2118,2051, +2118,2052,2119, +2053,2119,2052, +2119,2053,2120, +2054,2120,2053, +2120,2054,2121, +2055,2121,2054, +2121,2055,2122, +2056,2122,2055, +2122,2056,2123, +2057,2123,2056, +2123,2057,2124, +2058,2124,2057, +2124,2058,2125, +2059,2125,2058, +2125,2059,2126, +2060,2126,2059, +2126,2060,2127, +2061,2127,2060, +2127,2061,2128, +2062,2128,2061, +2128,2062,2129, +2063,2129,2062, +2129,2063,2130, +2064,2130,2063, +2130,2064,2131, +2065,2131,2064, +2131,2065,2132, +2066,2132,2065, +2132,2066,2133, +2067,2133,2066, +2133,2067,2134, +2068,2134,2067, +2134,2068,2135, +2069,2135,2068, +2135,2069,2136, +2070,2136,2069, +2136,2070,2137, +2071,2137,2070, +2137,2071,2138, +2072,2138,2071, +2138,2072,2139, +2073,2139,2072, +2139,2073,2140, +2074,2140,2073, +2140,2074,2141, +2075,2141,2074, +2141,2075,2142, +2076,2142,2075, +2142,2076,2143, +2077,2143,2076, +2143,2077,2144, +2078,2144,2077, +2144,2078,2145, +2079,2145,2078, +2145,2079,2146, +2080,2146,2079, +2146,2080,2147, +2081,2147,2080, +2147,2081,2148, +2082,2148,2081, +2148,2082,2149, +2083,2149,2082, +2149,2083,2150, +2084,2150,2083, +2150,2084,2151, +2085,2151,2084, +2151,2085,2152, +2086,2152,2085, +2152,2086,2153, +2087,2153,2086, +2153,2087,2154, +2088,2154,2087, +2154,2088,2155, +2089,2155,2088, +2155,2089,2156, +2090,2156,2089, +2156,2090,2157, +2091,2157,2090, +2157,2091,2158, +2092,2158,2091, +2158,2092,2159, +2093,2159,2092, +2159,2093,2160, +2094,2160,2093, +2160,2094,2161, +2095,2161,2094, +2161,2095,2162, +2096,2162,2095, +2162,2096,2163, +2097,2163,2096, +2163,2097,2164, +2098,2164,2097, +2164,2098,2165, +2099,2165,2098, +2165,2099,2166, +2100,2166,2099, +2166,2100,2167, +2101,2167,2100, +2167,2101,2168, +2102,2168,2101, +2168,2102,2169, +2103,2169,2102, +2169,2103,2170, +2104,2170,2103, +2170,2104,2171, +2105,2171,2104, +2171,2105,2172, +2106,2172,2105, +2172,2106,2173, +2107,2173,2106, +2173,2107,2174, +2108,2174,2107, +2174,2108,2175, +2109,2175,2108, +2175,2109,2176, +2110,2176,2109, +2176,2110,2177, +2111,2177,2110, +2178,2112,2179, +2113,2179,2112, +2179,2113,2180, +2114,2180,2113, +2180,2114,2181, +2115,2181,2114, +2181,2115,2182, +2116,2182,2115, +2182,2116,2183, +2117,2183,2116, +2183,2117,2184, +2118,2184,2117, +2184,2118,2185, +2119,2185,2118, +2185,2119,2186, +2120,2186,2119, +2186,2120,2187, +2121,2187,2120, +2187,2121,2188, +2122,2188,2121, +2188,2122,2189, +2123,2189,2122, +2189,2123,2190, +2124,2190,2123, +2190,2124,2191, +2125,2191,2124, +2191,2125,2192, +2126,2192,2125, +2192,2126,2193, +2127,2193,2126, +2193,2127,2194, +2128,2194,2127, +2194,2128,2195, +2129,2195,2128, +2195,2129,2196, +2130,2196,2129, +2196,2130,2197, +2131,2197,2130, +2197,2131,2198, +2132,2198,2131, +2198,2132,2199, +2133,2199,2132, +2199,2133,2200, +2134,2200,2133, +2200,2134,2201, +2135,2201,2134, +2201,2135,2202, +2136,2202,2135, +2202,2136,2203, +2137,2203,2136, +2203,2137,2204, +2138,2204,2137, +2204,2138,2205, +2139,2205,2138, +2205,2139,2206, +2140,2206,2139, +2206,2140,2207, +2141,2207,2140, +2207,2141,2208, +2142,2208,2141, +2208,2142,2209, +2143,2209,2142, +2209,2143,2210, +2144,2210,2143, +2210,2144,2211, +2145,2211,2144, +2211,2145,2212, +2146,2212,2145, +2212,2146,2213, +2147,2213,2146, +2213,2147,2214, +2148,2214,2147, +2214,2148,2215, +2149,2215,2148, +2215,2149,2216, +2150,2216,2149, +2216,2150,2217, +2151,2217,2150, +2217,2151,2218, +2152,2218,2151, +2218,2152,2219, +2153,2219,2152, +2219,2153,2220, +2154,2220,2153, +2220,2154,2221, +2155,2221,2154, +2221,2155,2222, +2156,2222,2155, +2222,2156,2223, +2157,2223,2156, +2223,2157,2224, +2158,2224,2157, +2224,2158,2225, +2159,2225,2158, +2225,2159,2226, +2160,2226,2159, +2226,2160,2227, +2161,2227,2160, +2227,2161,2228, +2162,2228,2161, +2228,2162,2229, +2163,2229,2162, +2229,2163,2230, +2164,2230,2163, +2230,2164,2231, +2165,2231,2164, +2231,2165,2232, +2166,2232,2165, +2232,2166,2233, +2167,2233,2166, +2233,2167,2234, +2168,2234,2167, +2234,2168,2235, +2169,2235,2168, +2235,2169,2236, +2170,2236,2169, +2236,2170,2237, +2171,2237,2170, +2237,2171,2238, +2172,2238,2171, +2238,2172,2239, +2173,2239,2172, +2239,2173,2240, +2174,2240,2173, +2240,2174,2241, +2175,2241,2174, +2241,2175,2242, +2176,2242,2175, +2242,2176,2243, +2177,2243,2176, +}; + +#define Landscape06VtxCount 2310 +#define Landscape06IdxCount 13260 + +btScalar Landscape06Vtx[] = { +-250.0f,5.63631f,246.094f, +-250.0f,8.1152f,250.0f, +-246.094f,7.06461f,246.094f, +-246.094f,9.72778f,250.0f, +-242.188f,9.8471f,246.094f, +-242.188f,11.659f,250.0f, +-238.281f,12.8404f,246.094f, +-238.281f,12.5619f,250.0f, +-234.375f,13.9879f,246.094f, +-234.375f,12.9518f,250.0f, +-230.469f,15.7239f,246.094f, +-230.469f,15.1373f,250.0f, +-226.563f,17.5095f,246.094f, +-226.563f,17.0421f,250.0f, +-222.656f,18.4322f,246.094f, +-222.656f,17.9919f,250.0f, +-218.75f,19.0755f,246.094f, +-218.75f,18.7918f,250.0f, +-214.844f,19.9271f,246.094f, +-214.844f,19.5719f,250.0f, +-210.938f,19.7244f,246.094f, +-210.938f,20.0866f,250.0f, +-207.031f,18.9716f,246.094f, +-207.031f,19.7869f,250.0f, +-203.125f,19.1922f,246.094f, +-203.125f,20.0264f,250.0f, +-199.219f,17.8506f,246.094f, +-199.219f,19.3207f,250.0f, +-195.313f,15.238f,246.094f, +-195.313f,18.0244f,250.0f, +-191.406f,14.6904f,246.094f, +-191.406f,16.2939f,250.0f, +-187.5f,12.9803f,246.094f, +-187.5f,14.9619f,250.0f, +-183.594f,11.6545f,246.094f, +-183.594f,12.6676f,250.0f, +-179.688f,12.4631f,246.094f, +-179.688f,13.6712f,250.0f, +-175.781f,13.1206f,246.094f, +-175.781f,14.5417f,250.0f, +-171.875f,13.3105f,246.094f, +-171.875f,15.8974f,250.0f, +-167.969f,13.4543f,246.094f, +-167.969f,15.9641f,250.0f, +-164.063f,13.4505f,246.094f, +-164.063f,15.4826f,250.0f, +-160.156f,14.6873f,246.094f, +-160.156f,15.1093f,250.0f, +-156.25f,14.1623f,246.094f, +-156.25f,14.8119f,250.0f, +-152.344f,14.0111f,246.094f, +-152.344f,14.4017f,250.0f, +-148.438f,13.2014f,246.094f, +-148.438f,14.2916f,250.0f, +-144.531f,12.8662f,246.094f, +-144.531f,13.5685f,250.0f, +-140.625f,13.1721f,246.094f, +-140.625f,14.2972f,250.0f, +-136.719f,12.9479f,246.094f, +-136.719f,15.0727f,250.0f, +-132.813f,13.4221f,246.094f, +-132.813f,14.5344f,250.0f, +-128.906f,14.0862f,246.094f, +-128.906f,15.7145f,250.0f, +-125.0f,13.481f,246.094f, +-125.0f,15.4608f,250.0f, +-121.094f,12.6228f,246.094f, +-121.094f,15.1857f,250.0f, +-117.188f,12.0584f,246.094f, +-117.188f,15.444f,250.0f, +-113.281f,12.7173f,246.094f, +-113.281f,15.8882f,250.0f, +-109.375f,12.3498f,246.094f, +-109.375f,15.2023f,250.0f, +-105.469f,13.0125f,246.094f, +-105.469f,15.1747f,250.0f, +-101.563f,13.7023f,246.094f, +-101.563f,14.7499f,250.0f, +-97.6563f,14.0674f,246.094f, +-97.6563f,15.0991f,250.0f, +-93.75f,13.8437f,246.094f, +-93.75f,14.6676f,250.0f, +-89.8438f,14.6327f,246.094f, +-89.8438f,14.1527f,250.0f, +-85.9375f,13.2966f,246.094f, +-85.9375f,14.0388f,250.0f, +-82.0313f,12.8094f,246.094f, +-82.0313f,13.7786f,250.0f, +-78.125f,11.8006f,246.094f, +-78.125f,13.0685f,250.0f, +-74.2188f,11.6837f,246.094f, +-74.2188f,12.8361f,250.0f, +-70.3125f,11.0326f,246.094f, +-70.3125f,12.3629f,250.0f, +-66.4063f,11.893f,246.094f, +-66.4063f,11.1909f,250.0f, +-62.5f,10.6469f,246.094f, +-62.5f,9.92966f,250.0f, +-58.5938f,8.55287f,246.094f, +-58.5938f,8.8871f,250.0f, +-54.6875f,7.1029f,246.094f, +-54.6875f,7.4963f,250.0f, +-50.7813f,6.9758f,246.094f, +-50.7813f,6.23897f,250.0f, +-46.875f,7.98262f,246.094f, +-46.875f,6.88918f,250.0f, +-42.9688f,9.11554f,246.094f, +-42.9688f,7.29319f,250.0f, +-39.0625f,8.74373f,246.094f, +-39.0625f,6.89167f,250.0f, +-35.1563f,7.46275f,246.094f, +-35.1563f,6.659f,250.0f, +-31.25f,7.67626f,246.094f, +-31.25f,6.75404f,250.0f, +-27.3438f,7.00511f,246.094f, +-27.3438f,6.15573f,250.0f, +-23.4375f,5.63813f,246.094f, +-23.4375f,5.72737f,250.0f, +-19.5313f,5.11885f,246.094f, +-19.5313f,4.00822f,250.0f, +-15.625f,3.60038f,246.094f, +-15.625f,3.50471f,250.0f, +-11.7188f,3.05357f,246.094f, +-11.7188f,3.0992f,250.0f, +-7.8125f,2.48195f,246.094f, +-7.8125f,2.46052f,250.0f, +-3.90625f,1.69136f,246.094f, +-3.90625f,2.5505f,250.0f, +0.0f,1.14548f,246.094f, +0.0f,2.18079f,250.0f, +3.90625f,0.45291f,246.094f, +3.90625f,1.52302f,250.0f, +-250.0f,5.2159f,242.188f, +-246.094f,7.35218f,242.188f, +-242.188f,10.2284f,242.188f, +-238.281f,12.7552f,242.188f, +-234.375f,14.3317f,242.188f, +-230.469f,16.3594f,242.188f, +-226.563f,17.8216f,242.188f, +-222.656f,18.5321f,242.188f, +-218.75f,18.7578f,242.188f, +-214.844f,19.504f,242.188f, +-210.938f,18.9422f,242.188f, +-207.031f,17.9771f,242.188f, +-203.125f,17.2798f,242.188f, +-199.219f,15.2252f,242.188f, +-195.313f,13.8769f,242.188f, +-191.406f,12.8727f,242.188f, +-187.5f,11.7858f,242.188f, +-183.594f,12.4886f,242.188f, +-179.688f,12.9814f,242.188f, +-175.781f,13.5265f,242.188f, +-171.875f,13.8082f,242.188f, +-167.969f,13.8407f,242.188f, +-164.063f,13.5872f,242.188f, +-160.156f,13.8287f,242.188f, +-156.25f,13.5778f,242.188f, +-152.344f,13.0026f,242.188f, +-148.438f,12.6259f,242.188f, +-144.531f,12.4666f,242.188f, +-140.625f,12.634f,242.188f, +-136.719f,12.1746f,242.188f, +-132.813f,11.7885f,242.188f, +-128.906f,11.4539f,242.188f, +-125.0f,11.0084f,242.188f, +-121.094f,10.1521f,242.188f, +-117.188f,10.6008f,242.188f, +-113.281f,10.2088f,242.188f, +-109.375f,11.0344f,242.188f, +-105.469f,11.1441f,242.188f, +-101.563f,12.3959f,242.188f, +-97.6563f,13.3587f,242.188f, +-93.75f,14.2415f,242.188f, +-89.8438f,13.9809f,242.188f, +-85.9375f,13.3276f,242.188f, +-82.0313f,11.9639f,242.188f, +-78.125f,11.5863f,242.188f, +-74.2188f,11.7327f,242.188f, +-70.3125f,11.5527f,242.188f, +-66.4063f,12.3699f,242.188f, +-62.5f,11.1959f,242.188f, +-58.5938f,9.59967f,242.188f, +-54.6875f,8.38887f,242.188f, +-50.7813f,7.42613f,242.188f, +-46.875f,8.34697f,242.188f, +-42.9688f,9.7013f,242.188f, +-39.0625f,9.10668f,242.188f, +-35.1563f,8.24657f,242.188f, +-31.25f,8.06656f,242.188f, +-27.3438f,6.98555f,242.188f, +-23.4375f,6.88836f,242.188f, +-19.5313f,5.88079f,242.188f, +-15.625f,4.43148f,242.188f, +-11.7188f,3.65843f,242.188f, +-7.8125f,2.85687f,242.188f, +-3.90625f,1.8332f,242.188f, +0.0f,2.03971f,242.188f, +3.90625f,2.21488f,242.188f, +-250.0f,5.44463f,238.281f, +-246.094f,7.90885f,238.281f, +-242.188f,10.3908f,238.281f, +-238.281f,12.875f,238.281f, +-234.375f,14.8255f,238.281f, +-230.469f,16.5404f,238.281f, +-226.563f,17.8109f,238.281f, +-222.656f,19.0205f,238.281f, +-218.75f,18.7565f,238.281f, +-214.844f,18.9852f,238.281f, +-210.938f,18.3753f,238.281f, +-207.031f,16.6829f,238.281f, +-203.125f,15.8099f,238.281f, +-199.219f,13.2915f,238.281f, +-195.313f,13.447f,238.281f, +-191.406f,13.5971f,238.281f, +-187.5f,12.1473f,238.281f, +-183.594f,13.3531f,238.281f, +-179.688f,14.4732f,238.281f, +-175.781f,15.0267f,238.281f, +-171.875f,14.7852f,238.281f, +-167.969f,15.5706f,238.281f, +-164.063f,14.267f,238.281f, +-160.156f,14.0772f,238.281f, +-156.25f,12.4965f,238.281f, +-152.344f,12.1473f,238.281f, +-148.438f,11.8693f,238.281f, +-144.531f,11.2795f,238.281f, +-140.625f,10.8173f,238.281f, +-136.719f,10.792f,238.281f, +-132.813f,10.8481f,238.281f, +-128.906f,9.95928f,238.281f, +-125.0f,10.0976f,238.281f, +-121.094f,8.74444f,238.281f, +-117.188f,9.1761f,238.281f, +-113.281f,10.2354f,238.281f, +-109.375f,10.7023f,238.281f, +-105.469f,11.6386f,238.281f, +-101.563f,12.7789f,238.281f, +-97.6563f,13.956f,238.281f, +-93.75f,14.1101f,238.281f, +-89.8438f,13.2653f,238.281f, +-85.9375f,12.1604f,238.281f, +-82.0313f,11.6914f,238.281f, +-78.125f,11.3706f,238.281f, +-74.2188f,12.1449f,238.281f, +-70.3125f,12.4512f,238.281f, +-66.4063f,12.6436f,238.281f, +-62.5f,11.6692f,238.281f, +-58.5938f,10.8304f,238.281f, +-54.6875f,8.88158f,238.281f, +-50.7813f,7.94904f,238.281f, +-46.875f,8.47525f,238.281f, +-42.9688f,9.08763f,238.281f, +-39.0625f,9.21095f,238.281f, +-35.1563f,9.12926f,238.281f, +-31.25f,8.5517f,238.281f, +-27.3438f,7.86146f,238.281f, +-23.4375f,7.33662f,238.281f, +-19.5313f,6.37551f,238.281f, +-15.625f,5.59324f,238.281f, +-11.7188f,4.81831f,238.281f, +-7.8125f,4.35695f,238.281f, +-3.90625f,3.64159f,238.281f, +0.0f,3.70314f,238.281f, +3.90625f,3.04396f,238.281f, +-250.0f,5.92848f,234.375f, +-246.094f,8.10446f,234.375f, +-242.188f,10.3516f,234.375f, +-238.281f,12.4984f,234.375f, +-234.375f,15.0991f,234.375f, +-230.469f,16.0002f,234.375f, +-226.563f,17.2585f,234.375f, +-222.656f,18.1852f,234.375f, +-218.75f,18.7811f,234.375f, +-214.844f,18.4638f,234.375f, +-210.938f,18.3171f,234.375f, +-207.031f,16.1085f,234.375f, +-203.125f,15.1926f,234.375f, +-199.219f,14.1792f,234.375f, +-195.313f,13.5589f,234.375f, +-191.406f,13.9362f,234.375f, +-187.5f,13.303f,234.375f, +-183.594f,13.6602f,234.375f, +-179.688f,15.1086f,234.375f, +-175.781f,15.5943f,234.375f, +-171.875f,15.3663f,234.375f, +-167.969f,14.9609f,234.375f, +-164.063f,14.4285f,234.375f, +-160.156f,14.1532f,234.375f, +-156.25f,13.0139f,234.375f, +-152.344f,11.6503f,234.375f, +-148.438f,11.6112f,234.375f, +-144.531f,11.1097f,234.375f, +-140.625f,10.8763f,234.375f, +-136.719f,10.2321f,234.375f, +-132.813f,9.71321f,234.375f, +-128.906f,9.04388f,234.375f, +-125.0f,9.53542f,234.375f, +-121.094f,8.10006f,234.375f, +-117.188f,9.16948f,234.375f, +-113.281f,9.67824f,234.375f, +-109.375f,10.2679f,234.375f, +-105.469f,10.9669f,234.375f, +-101.563f,12.2942f,234.375f, +-97.6563f,13.2952f,234.375f, +-93.75f,13.0932f,234.375f, +-89.8438f,12.4514f,234.375f, +-85.9375f,12.2395f,234.375f, +-82.0313f,11.7622f,234.375f, +-78.125f,11.9666f,234.375f, +-74.2188f,12.2346f,234.375f, +-70.3125f,13.1648f,234.375f, +-66.4063f,13.506f,234.375f, +-62.5f,13.1773f,234.375f, +-58.5938f,11.9168f,234.375f, +-54.6875f,10.0208f,234.375f, +-50.7813f,9.08267f,234.375f, +-46.875f,8.4406f,234.375f, +-42.9688f,9.27515f,234.375f, +-39.0625f,10.2228f,234.375f, +-35.1563f,9.77624f,234.375f, +-31.25f,9.17943f,234.375f, +-27.3438f,8.83272f,234.375f, +-23.4375f,8.00355f,234.375f, +-19.5313f,7.37167f,234.375f, +-15.625f,6.87424f,234.375f, +-11.7188f,6.23994f,234.375f, +-7.8125f,5.50641f,234.375f, +-3.90625f,5.06839f,234.375f, +0.0f,5.06846f,234.375f, +3.90625f,5.19166f,234.375f, +-250.0f,4.98265f,230.469f, +-246.094f,7.878f,230.469f, +-242.188f,10.9188f,230.469f, +-238.281f,12.8549f,230.469f, +-234.375f,14.5578f,230.469f, +-230.469f,16.067f,230.469f, +-226.563f,17.9938f,230.469f, +-222.656f,18.3449f,230.469f, +-218.75f,18.4423f,230.469f, +-214.844f,18.9411f,230.469f, +-210.938f,17.3131f,230.469f, +-207.031f,15.3292f,230.469f, +-203.125f,15.5278f,230.469f, +-199.219f,14.9451f,230.469f, +-195.313f,13.8026f,230.469f, +-191.406f,13.1586f,230.469f, +-187.5f,13.4388f,230.469f, +-183.594f,14.2213f,230.469f, +-179.688f,14.907f,230.469f, +-175.781f,15.2295f,230.469f, +-171.875f,14.8701f,230.469f, +-167.969f,14.1393f,230.469f, +-164.063f,13.7829f,230.469f, +-160.156f,13.0614f,230.469f, +-156.25f,12.3416f,230.469f, +-152.344f,11.5366f,230.469f, +-148.438f,11.5201f,230.469f, +-144.531f,11.0918f,230.469f, +-140.625f,11.139f,230.469f, +-136.719f,10.0387f,230.469f, +-132.813f,8.59099f,230.469f, +-128.906f,7.71771f,230.469f, +-125.0f,7.44273f,230.469f, +-121.094f,8.17087f,230.469f, +-117.188f,8.34002f,230.469f, +-113.281f,9.22169f,230.469f, +-109.375f,10.2195f,230.469f, +-105.469f,11.523f,230.469f, +-101.563f,12.7411f,230.469f, +-97.6563f,12.7429f,230.469f, +-93.75f,12.3959f,230.469f, +-89.8438f,11.7559f,230.469f, +-85.9375f,10.3669f,230.469f, +-82.0313f,10.0825f,230.469f, +-78.125f,11.4451f,230.469f, +-74.2188f,12.235f,230.469f, +-70.3125f,13.6016f,230.469f, +-66.4063f,14.377f,230.469f, +-62.5f,13.967f,230.469f, +-58.5938f,12.862f,230.469f, +-54.6875f,11.4719f,230.469f, +-50.7813f,9.99381f,230.469f, +-46.875f,8.68857f,230.469f, +-42.9688f,9.43448f,230.469f, +-39.0625f,10.4708f,230.469f, +-35.1563f,11.0521f,230.469f, +-31.25f,10.5864f,230.469f, +-27.3438f,10.8331f,230.469f, +-23.4375f,9.96112f,230.469f, +-19.5313f,8.61029f,230.469f, +-15.625f,7.42407f,230.469f, +-11.7188f,6.43202f,230.469f, +-7.8125f,6.36726f,230.469f, +-3.90625f,6.52581f,230.469f, +0.0f,6.18686f,230.469f, +3.90625f,5.885f,230.469f, +-250.0f,4.92227f,226.563f, +-246.094f,8.66811f,226.563f, +-242.188f,11.7599f,226.563f, +-238.281f,13.6581f,226.563f, +-234.375f,15.6409f,226.563f, +-230.469f,16.7907f,226.563f, +-226.563f,17.4606f,226.563f, +-222.656f,18.4841f,226.563f, +-218.75f,18.4506f,226.563f, +-214.844f,17.5936f,226.563f, +-210.938f,16.5941f,226.563f, +-207.031f,14.8805f,226.563f, +-203.125f,15.3743f,226.563f, +-199.219f,15.4493f,226.563f, +-195.313f,14.5184f,226.563f, +-191.406f,12.9285f,226.563f, +-187.5f,13.3898f,226.563f, +-183.594f,14.0358f,226.563f, +-179.688f,15.2884f,226.563f, +-175.781f,14.972f,226.563f, +-171.875f,14.2355f,226.563f, +-167.969f,13.6786f,226.563f, +-164.063f,13.0771f,226.563f, +-160.156f,12.7879f,226.563f, +-156.25f,12.4767f,226.563f, +-152.344f,11.5156f,226.563f, +-148.438f,11.1725f,226.563f, +-144.531f,10.8869f,226.563f, +-140.625f,9.77232f,226.563f, +-136.719f,8.75728f,226.563f, +-132.813f,6.77705f,226.563f, +-128.906f,6.35083f,226.563f, +-125.0f,6.59888f,226.563f, +-121.094f,7.81295f,226.563f, +-117.188f,8.10078f,226.563f, +-113.281f,9.07634f,226.563f, +-109.375f,10.2289f,226.563f, +-105.469f,11.5342f,226.563f, +-101.563f,12.9142f,226.563f, +-97.6563f,12.8729f,226.563f, +-93.75f,12.8149f,226.563f, +-89.8438f,10.9671f,226.563f, +-85.9375f,10.0649f,226.563f, +-82.0313f,9.28012f,226.563f, +-78.125f,10.1324f,226.563f, +-74.2188f,11.8638f,226.563f, +-70.3125f,12.6141f,226.563f, +-66.4063f,13.6851f,226.563f, +-62.5f,13.9389f,226.563f, +-58.5938f,13.5413f,226.563f, +-54.6875f,12.4869f,226.563f, +-50.7813f,11.2774f,226.563f, +-46.875f,10.6009f,226.563f, +-42.9688f,11.4839f,226.563f, +-39.0625f,12.5408f,226.563f, +-35.1563f,12.8694f,226.563f, +-31.25f,12.5253f,226.563f, +-27.3438f,12.1887f,226.563f, +-23.4375f,11.5356f,226.563f, +-19.5313f,9.53151f,226.563f, +-15.625f,8.29811f,226.563f, +-11.7188f,7.38375f,226.563f, +-7.8125f,7.57607f,226.563f, +-3.90625f,7.41156f,226.563f, +0.0f,6.9836f,226.563f, +3.90625f,6.89682f,226.563f, +-250.0f,4.66781f,222.656f, +-246.094f,7.89882f,222.656f, +-242.188f,10.8629f,222.656f, +-238.281f,14.1235f,222.656f, +-234.375f,15.6001f,222.656f, +-230.469f,17.0347f,222.656f, +-226.563f,17.4872f,222.656f, +-222.656f,17.6157f,222.656f, +-218.75f,16.8213f,222.656f, +-214.844f,16.4076f,222.656f, +-210.938f,15.0745f,222.656f, +-207.031f,14.2914f,222.656f, +-203.125f,14.6094f,222.656f, +-199.219f,14.4637f,222.656f, +-195.313f,14.0807f,222.656f, +-191.406f,12.4559f,222.656f, +-187.5f,13.0367f,222.656f, +-183.594f,13.975f,222.656f, +-179.688f,14.802f,222.656f, +-175.781f,14.6145f,222.656f, +-171.875f,13.4733f,222.656f, +-167.969f,13.3385f,222.656f, +-164.063f,13.721f,222.656f, +-160.156f,12.5775f,222.656f, +-156.25f,11.962f,222.656f, +-152.344f,11.2422f,222.656f, +-148.438f,10.827f,222.656f, +-144.531f,10.2848f,222.656f, +-140.625f,8.45922f,222.656f, +-136.719f,7.72182f,222.656f, +-132.813f,6.23545f,222.656f, +-128.906f,5.69752f,222.656f, +-125.0f,6.29925f,222.656f, +-121.094f,7.1991f,222.656f, +-117.188f,7.56788f,222.656f, +-113.281f,8.87895f,222.656f, +-109.375f,9.92302f,222.656f, +-105.469f,10.2628f,222.656f, +-101.563f,11.427f,222.656f, +-97.6563f,12.2929f,222.656f, +-93.75f,11.6083f,222.656f, +-89.8438f,11.594f,222.656f, +-85.9375f,10.1683f,222.656f, +-82.0313f,10.4152f,222.656f, +-78.125f,10.765f,222.656f, +-74.2188f,11.5311f,222.656f, +-70.3125f,12.8761f,222.656f, +-66.4063f,14.8794f,222.656f, +-62.5f,15.7341f,222.656f, +-58.5938f,15.0851f,222.656f, +-54.6875f,14.4719f,222.656f, +-50.7813f,13.6899f,222.656f, +-46.875f,13.0842f,222.656f, +-42.9688f,13.1059f,222.656f, +-39.0625f,13.9942f,222.656f, +-35.1563f,13.8877f,222.656f, +-31.25f,14.1293f,222.656f, +-27.3438f,13.6276f,222.656f, +-23.4375f,12.2206f,222.656f, +-19.5313f,10.8481f,222.656f, +-15.625f,9.71168f,222.656f, +-11.7188f,8.51834f,222.656f, +-7.8125f,9.04274f,222.656f, +-3.90625f,8.46981f,222.656f, +0.0f,8.26045f,222.656f, +3.90625f,6.81349f,222.656f, +-250.0f,5.16984f,218.75f, +-246.094f,6.64731f,218.75f, +-242.188f,9.50207f,218.75f, +-238.281f,12.5115f,218.75f, +-234.375f,15.8009f,218.75f, +-230.469f,17.6139f,218.75f, +-226.563f,18.128f,218.75f, +-222.656f,17.3111f,218.75f, +-218.75f,16.3962f,218.75f, +-214.844f,16.0245f,218.75f, +-210.938f,14.5344f,218.75f, +-207.031f,13.4459f,218.75f, +-203.125f,13.3987f,218.75f, +-199.219f,13.5444f,218.75f, +-195.313f,12.1973f,218.75f, +-191.406f,11.8337f,218.75f, +-187.5f,13.3027f,218.75f, +-183.594f,13.2862f,218.75f, +-179.688f,14.577f,218.75f, +-175.781f,14.4312f,218.75f, +-171.875f,13.3065f,218.75f, +-167.969f,14.2726f,218.75f, +-164.063f,14.5522f,218.75f, +-160.156f,13.8269f,218.75f, +-156.25f,12.4234f,218.75f, +-152.344f,10.5035f,218.75f, +-148.438f,9.65297f,218.75f, +-144.531f,8.3692f,218.75f, +-140.625f,7.39811f,218.75f, +-136.719f,6.29024f,218.75f, +-132.813f,5.37103f,218.75f, +-128.906f,5.29069f,218.75f, +-125.0f,5.59696f,218.75f, +-121.094f,6.15404f,218.75f, +-117.188f,7.15855f,218.75f, +-113.281f,8.08243f,218.75f, +-109.375f,8.97937f,218.75f, +-105.469f,9.67177f,218.75f, +-101.563f,10.7738f,218.75f, +-97.6563f,11.4256f,218.75f, +-93.75f,11.6906f,218.75f, +-89.8438f,11.4527f,218.75f, +-85.9375f,11.5445f,218.75f, +-82.0313f,11.9384f,218.75f, +-78.125f,12.452f,218.75f, +-74.2188f,13.3202f,218.75f, +-70.3125f,14.2351f,218.75f, +-66.4063f,15.021f,218.75f, +-62.5f,16.1053f,218.75f, +-58.5938f,16.0633f,218.75f, +-54.6875f,15.6154f,218.75f, +-50.7813f,15.3347f,218.75f, +-46.875f,14.8984f,218.75f, +-42.9688f,14.1541f,218.75f, +-39.0625f,14.8343f,218.75f, +-35.1563f,14.8393f,218.75f, +-31.25f,14.865f,218.75f, +-27.3438f,13.9913f,218.75f, +-23.4375f,13.7749f,218.75f, +-19.5313f,12.6247f,218.75f, +-15.625f,11.3466f,218.75f, +-11.7188f,10.5048f,218.75f, +-7.8125f,9.94742f,218.75f, +-3.90625f,8.79577f,218.75f, +0.0f,8.31646f,218.75f, +3.90625f,8.02546f,218.75f, +-250.0f,4.42455f,214.844f, +-246.094f,6.15686f,214.844f, +-242.188f,8.4919f,214.844f, +-238.281f,12.2627f,214.844f, +-234.375f,15.9215f,214.844f, +-230.469f,17.6896f,214.844f, +-226.563f,18.1835f,214.844f, +-222.656f,17.9341f,214.844f, +-218.75f,16.9803f,214.844f, +-214.844f,15.6617f,214.844f, +-210.938f,14.3989f,214.844f, +-207.031f,12.7777f,214.844f, +-203.125f,12.7635f,214.844f, +-199.219f,12.8533f,214.844f, +-195.313f,12.1672f,214.844f, +-191.406f,12.2357f,214.844f, +-187.5f,12.5806f,214.844f, +-183.594f,12.5597f,214.844f, +-179.688f,13.6296f,214.844f, +-175.781f,13.8382f,214.844f, +-171.875f,14.4001f,214.844f, +-167.969f,14.3002f,214.844f, +-164.063f,14.3353f,214.844f, +-160.156f,14.0346f,214.844f, +-156.25f,12.9823f,214.844f, +-152.344f,10.8141f,214.844f, +-148.438f,9.57028f,214.844f, +-144.531f,8.18427f,214.844f, +-140.625f,6.89938f,214.844f, +-136.719f,5.79227f,214.844f, +-132.813f,4.60172f,214.844f, +-128.906f,4.59969f,214.844f, +-125.0f,5.20294f,214.844f, +-121.094f,6.17542f,214.844f, +-117.188f,7.13347f,214.844f, +-113.281f,8.1045f,214.844f, +-109.375f,8.73005f,214.844f, +-105.469f,9.96489f,214.844f, +-101.563f,11.1039f,214.844f, +-97.6563f,11.6791f,214.844f, +-93.75f,11.9246f,214.844f, +-89.8438f,12.0071f,214.844f, +-85.9375f,12.8099f,214.844f, +-82.0313f,13.3672f,214.844f, +-78.125f,13.5811f,214.844f, +-74.2188f,14.7559f,214.844f, +-70.3125f,15.4274f,214.844f, +-66.4063f,15.487f,214.844f, +-62.5f,16.3346f,214.844f, +-58.5938f,16.424f,214.844f, +-54.6875f,17.1014f,214.844f, +-50.7813f,17.634f,214.844f, +-46.875f,16.5132f,214.844f, +-42.9688f,15.1728f,214.844f, +-39.0625f,15.4699f,214.844f, +-35.1563f,16.154f,214.844f, +-31.25f,15.8527f,214.844f, +-27.3438f,15.4057f,214.844f, +-23.4375f,14.6476f,214.844f, +-19.5313f,13.1705f,214.844f, +-15.625f,11.9754f,214.844f, +-11.7188f,11.7453f,214.844f, +-7.8125f,10.8384f,214.844f, +-3.90625f,10.1259f,214.844f, +0.0f,9.49925f,214.844f, +3.90625f,9.25513f,214.844f, +-250.0f,3.60269f,210.938f, +-246.094f,5.37638f,210.938f, +-242.188f,7.66914f,210.938f, +-238.281f,11.9863f,210.938f, +-234.375f,14.9525f,210.938f, +-230.469f,16.5034f,210.938f, +-226.563f,17.8663f,210.938f, +-222.656f,17.1002f,210.938f, +-218.75f,16.0413f,210.938f, +-214.844f,14.8516f,210.938f, +-210.938f,13.8904f,210.938f, +-207.031f,11.9929f,210.938f, +-203.125f,11.8171f,210.938f, +-199.219f,11.6849f,210.938f, +-195.313f,11.056f,210.938f, +-191.406f,11.6318f,210.938f, +-187.5f,11.9333f,210.938f, +-183.594f,12.599f,210.938f, +-179.688f,14.0437f,210.938f, +-175.781f,14.7937f,210.938f, +-171.875f,14.8844f,210.938f, +-167.969f,14.3312f,210.938f, +-164.063f,13.2879f,210.938f, +-160.156f,12.3423f,210.938f, +-156.25f,11.4768f,210.938f, +-152.344f,9.94481f,210.938f, +-148.438f,7.76655f,210.938f, +-144.531f,6.59218f,210.938f, +-140.625f,6.49848f,210.938f, +-136.719f,5.2458f,210.938f, +-132.813f,4.27164f,210.938f, +-128.906f,4.68484f,210.938f, +-125.0f,5.2746f,210.938f, +-121.094f,6.12822f,210.938f, +-117.188f,8.02215f,210.938f, +-113.281f,8.95036f,210.938f, +-109.375f,9.92538f,210.938f, +-105.469f,10.4058f,210.938f, +-101.563f,11.2862f,210.938f, +-97.6563f,11.7274f,210.938f, +-93.75f,12.3175f,210.938f, +-89.8438f,12.6423f,210.938f, +-85.9375f,13.2212f,210.938f, +-82.0313f,13.9379f,210.938f, +-78.125f,15.3332f,210.938f, +-74.2188f,16.2893f,210.938f, +-70.3125f,16.1032f,210.938f, +-66.4063f,16.7786f,210.938f, +-62.5f,16.8038f,210.938f, +-58.5938f,16.1537f,210.938f, +-54.6875f,17.4306f,210.938f, +-50.7813f,17.313f,210.938f, +-46.875f,16.2568f,210.938f, +-42.9688f,16.0266f,210.938f, +-39.0625f,16.9569f,210.938f, +-35.1563f,18.0733f,210.938f, +-31.25f,17.4779f,210.938f, +-27.3438f,17.2939f,210.938f, +-23.4375f,16.1477f,210.938f, +-19.5313f,15.409f,210.938f, +-15.625f,14.0019f,210.938f, +-11.7188f,13.3531f,210.938f, +-7.8125f,12.4823f,210.938f, +-3.90625f,11.7842f,210.938f, +0.0f,11.0776f,210.938f, +3.90625f,10.5728f,210.938f, +-250.0f,3.49901f,207.031f, +-246.094f,4.00092f,207.031f, +-242.188f,7.06194f,207.031f, +-238.281f,10.1502f,207.031f, +-234.375f,13.0262f,207.031f, +-230.469f,15.541f,207.031f, +-226.563f,16.4029f,207.031f, +-222.656f,16.0741f,207.031f, +-218.75f,15.3706f,207.031f, +-214.844f,14.3529f,207.031f, +-210.938f,13.1351f,207.031f, +-207.031f,11.2939f,207.031f, +-203.125f,11.4337f,207.031f, +-199.219f,11.43f,207.031f, +-195.313f,10.6048f,207.031f, +-191.406f,10.859f,207.031f, +-187.5f,11.8447f,207.031f, +-183.594f,12.8305f,207.031f, +-179.688f,14.9116f,207.031f, +-175.781f,15.0225f,207.031f, +-171.875f,14.847f,207.031f, +-167.969f,13.7464f,207.031f, +-164.063f,12.6716f,207.031f, +-160.156f,10.4028f,207.031f, +-156.25f,9.61156f,207.031f, +-152.344f,9.08545f,207.031f, +-148.438f,6.96088f,207.031f, +-144.531f,6.6794f,207.031f, +-140.625f,6.08012f,207.031f, +-136.719f,5.02964f,207.031f, +-132.813f,4.93996f,207.031f, +-128.906f,4.955f,207.031f, +-125.0f,5.23446f,207.031f, +-121.094f,7.14164f,207.031f, +-117.188f,9.21655f,207.031f, +-113.281f,10.8802f,207.031f, +-109.375f,11.0518f,207.031f, +-105.469f,11.5707f,207.031f, +-101.563f,12.2834f,207.031f, +-97.6563f,12.7498f,207.031f, +-93.75f,12.6608f,207.031f, +-89.8438f,12.3649f,207.031f, +-85.9375f,13.1678f,207.031f, +-82.0313f,13.541f,207.031f, +-78.125f,14.3448f,207.031f, +-74.2188f,15.6006f,207.031f, +-70.3125f,17.0141f,207.031f, +-66.4063f,17.4107f,207.031f, +-62.5f,18.0045f,207.031f, +-58.5938f,17.6582f,207.031f, +-54.6875f,17.0297f,207.031f, +-50.7813f,16.6619f,207.031f, +-46.875f,17.1267f,207.031f, +-42.9688f,18.0618f,207.031f, +-39.0625f,18.7698f,207.031f, +-35.1563f,19.3034f,207.031f, +-31.25f,19.1566f,207.031f, +-27.3438f,19.1107f,207.031f, +-23.4375f,17.3298f,207.031f, +-19.5313f,15.7204f,207.031f, +-15.625f,14.7827f,207.031f, +-11.7188f,14.2027f,207.031f, +-7.8125f,13.5758f,207.031f, +-3.90625f,13.1935f,207.031f, +0.0f,11.8526f,207.031f, +3.90625f,10.4539f,207.031f, +-250.0f,3.85941f,203.125f, +-246.094f,3.80391f,203.125f, +-242.188f,6.8342f,203.125f, +-238.281f,10.0313f,203.125f, +-234.375f,12.9894f,203.125f, +-230.469f,15.1588f,203.125f, +-226.563f,15.6234f,203.125f, +-222.656f,15.112f,203.125f, +-218.75f,14.5577f,203.125f, +-214.844f,14.0703f,203.125f, +-210.938f,13.3523f,203.125f, +-207.031f,12.1264f,203.125f, +-203.125f,11.037f,203.125f, +-199.219f,10.3379f,203.125f, +-195.313f,11.3f,203.125f, +-191.406f,10.6845f,203.125f, +-187.5f,11.7023f,203.125f, +-183.594f,13.2057f,203.125f, +-179.688f,13.976f,203.125f, +-175.781f,14.994f,203.125f, +-171.875f,14.6465f,203.125f, +-167.969f,13.4879f,203.125f, +-164.063f,12.0617f,203.125f, +-160.156f,10.6454f,203.125f, +-156.25f,10.2693f,203.125f, +-152.344f,8.33279f,203.125f, +-148.438f,7.60557f,203.125f, +-144.531f,6.19774f,203.125f, +-140.625f,5.7751f,203.125f, +-136.719f,5.28903f,203.125f, +-132.813f,5.10696f,203.125f, +-128.906f,5.61944f,203.125f, +-125.0f,7.32929f,203.125f, +-121.094f,9.09158f,203.125f, +-117.188f,10.6952f,203.125f, +-113.281f,11.555f,203.125f, +-109.375f,12.5837f,203.125f, +-105.469f,13.4444f,203.125f, +-101.563f,14.3191f,203.125f, +-97.6563f,14.5546f,203.125f, +-93.75f,13.9216f,203.125f, +-89.8438f,13.07f,203.125f, +-85.9375f,13.0497f,203.125f, +-82.0313f,13.8884f,203.125f, +-78.125f,14.2048f,203.125f, +-74.2188f,16.2809f,203.125f, +-70.3125f,17.1518f,203.125f, +-66.4063f,18.4883f,203.125f, +-62.5f,19.2231f,203.125f, +-58.5938f,19.0199f,203.125f, +-54.6875f,18.4606f,203.125f, +-50.7813f,17.3076f,203.125f, +-46.875f,17.0012f,203.125f, +-42.9688f,18.4311f,203.125f, +-39.0625f,19.9758f,203.125f, +-35.1563f,20.1252f,203.125f, +-31.25f,20.126f,203.125f, +-27.3438f,18.9276f,203.125f, +-23.4375f,18.3938f,203.125f, +-19.5313f,16.6811f,203.125f, +-15.625f,15.7398f,203.125f, +-11.7188f,14.6978f,203.125f, +-7.8125f,14.7567f,203.125f, +-3.90625f,14.377f,203.125f, +0.0f,13.0029f,203.125f, +3.90625f,11.4706f,203.125f, +-250.0f,4.68355f,199.219f, +-246.094f,4.65569f,199.219f, +-242.188f,6.34925f,199.219f, +-238.281f,9.03665f,199.219f, +-234.375f,11.4587f,199.219f, +-230.469f,13.9932f,199.219f, +-226.563f,14.8268f,199.219f, +-222.656f,14.0552f,199.219f, +-218.75f,14.4455f,199.219f, +-214.844f,14.3053f,199.219f, +-210.938f,12.5781f,199.219f, +-207.031f,11.5778f,199.219f, +-203.125f,9.91652f,199.219f, +-199.219f,9.20832f,199.219f, +-195.313f,10.1078f,199.219f, +-191.406f,10.5638f,199.219f, +-187.5f,11.6649f,199.219f, +-183.594f,13.3758f,199.219f, +-179.688f,15.2035f,199.219f, +-175.781f,14.6909f,199.219f, +-171.875f,14.0312f,199.219f, +-167.969f,12.6808f,199.219f, +-164.063f,12.649f,199.219f, +-160.156f,11.6333f,199.219f, +-156.25f,10.8896f,199.219f, +-152.344f,8.72848f,199.219f, +-148.438f,7.55753f,199.219f, +-144.531f,6.70035f,199.219f, +-140.625f,5.28209f,199.219f, +-136.719f,5.47347f,199.219f, +-132.813f,7.25678f,199.219f, +-128.906f,9.06223f,199.219f, +-125.0f,9.91604f,199.219f, +-121.094f,10.882f,199.219f, +-117.188f,11.8314f,199.219f, +-113.281f,12.9729f,199.219f, +-109.375f,14.1144f,199.219f, +-105.469f,15.0374f,199.219f, +-101.563f,15.4321f,199.219f, +-97.6563f,15.9823f,199.219f, +-93.75f,15.4663f,199.219f, +-89.8438f,14.4094f,199.219f, +-85.9375f,14.1599f,199.219f, +-82.0313f,14.4239f,199.219f, +-78.125f,14.7717f,199.219f, +-74.2188f,15.3979f,199.219f, +-70.3125f,16.4014f,199.219f, +-66.4063f,17.9486f,199.219f, +-62.5f,19.3767f,199.219f, +-58.5938f,19.7322f,199.219f, +-54.6875f,19.0648f,199.219f, +-50.7813f,18.2481f,199.219f, +-46.875f,17.1507f,199.219f, +-42.9688f,18.6306f,199.219f, +-39.0625f,19.2486f,199.219f, +-35.1563f,20.3158f,199.219f, +-31.25f,19.6441f,199.219f, +-27.3438f,18.7294f,199.219f, +-23.4375f,17.9051f,199.219f, +-19.5313f,17.278f,199.219f, +-15.625f,16.1912f,199.219f, +-11.7188f,15.3685f,199.219f, +-7.8125f,14.8376f,199.219f, +-3.90625f,13.8988f,199.219f, +0.0f,12.5645f,199.219f, +3.90625f,12.1184f,199.219f, +-250.0f,5.71048f,195.313f, +-246.094f,4.68298f,195.313f, +-242.188f,5.30012f,195.313f, +-238.281f,7.72299f,195.313f, +-234.375f,10.9797f,195.313f, +-230.469f,12.6343f,195.313f, +-226.563f,13.8962f,195.313f, +-222.656f,13.2189f,195.313f, +-218.75f,14.0254f,195.313f, +-214.844f,14.5903f,195.313f, +-210.938f,12.6794f,195.313f, +-207.031f,9.8479f,195.313f, +-203.125f,8.05763f,195.313f, +-199.219f,7.68254f,195.313f, +-195.313f,9.0324f,195.313f, +-191.406f,10.7973f,195.313f, +-187.5f,12.1516f,195.313f, +-183.594f,13.1888f,195.313f, +-179.688f,14.2559f,195.313f, +-175.781f,14.0455f,195.313f, +-171.875f,13.2785f,195.313f, +-167.969f,12.7724f,195.313f, +-164.063f,12.56f,195.313f, +-160.156f,11.4647f,195.313f, +-156.25f,10.6463f,195.313f, +-152.344f,9.36927f,195.313f, +-148.438f,7.87862f,195.313f, +-144.531f,6.78168f,195.313f, +-140.625f,5.32688f,195.313f, +-136.719f,6.62928f,195.313f, +-132.813f,8.97871f,195.313f, +-128.906f,10.3174f,195.313f, +-125.0f,11.2136f,195.313f, +-121.094f,12.2822f,195.313f, +-117.188f,13.7351f,195.313f, +-113.281f,14.0196f,195.313f, +-109.375f,15.5457f,195.313f, +-105.469f,16.1402f,195.313f, +-101.563f,16.6719f,195.313f, +-97.6563f,16.2658f,195.313f, +-93.75f,16.5379f,195.313f, +-89.8438f,15.1289f,195.313f, +-85.9375f,14.7687f,195.313f, +-82.0313f,15.4638f,195.313f, +-78.125f,15.3391f,195.313f, +-74.2188f,14.8602f,195.313f, +-70.3125f,16.2701f,195.313f, +-66.4063f,17.9511f,195.313f, +-62.5f,19.108f,195.313f, +-58.5938f,19.5253f,195.313f, +-54.6875f,19.1648f,195.313f, +-50.7813f,18.0624f,195.313f, +-46.875f,17.2201f,195.313f, +-42.9688f,19.4165f,195.313f, +-39.0625f,20.3781f,195.313f, +-35.1563f,19.796f,195.313f, +-31.25f,18.9841f,195.313f, +-27.3438f,18.3143f,195.313f, +-23.4375f,18.1973f,195.313f, +-19.5313f,17.5121f,195.313f, +-15.625f,16.5969f,195.313f, +-11.7188f,15.3539f,195.313f, +-7.8125f,14.4654f,195.313f, +-3.90625f,13.8161f,195.313f, +0.0f,12.4727f,195.313f, +3.90625f,13.8013f,195.313f, +-250.0f,6.07831f,191.406f, +-246.094f,5.46721f,191.406f, +-242.188f,4.48351f,191.406f, +-238.281f,6.74031f,191.406f, +-234.375f,9.75661f,191.406f, +-230.469f,11.5382f,191.406f, +-226.563f,12.9559f,191.406f, +-222.656f,12.6196f,191.406f, +-218.75f,12.4516f,191.406f, +-214.844f,13.5738f,191.406f, +-210.938f,12.2334f,191.406f, +-207.031f,9.36284f,191.406f, +-203.125f,7.56119f,191.406f, +-199.219f,8.2975f,191.406f, +-195.313f,10.0432f,191.406f, +-191.406f,11.528f,191.406f, +-187.5f,12.9338f,191.406f, +-183.594f,13.9397f,191.406f, +-179.688f,14.1423f,191.406f, +-175.781f,13.7637f,191.406f, +-171.875f,12.7983f,191.406f, +-167.969f,12.6132f,191.406f, +-164.063f,12.07f,191.406f, +-160.156f,11.7037f,191.406f, +-156.25f,10.3692f,191.406f, +-152.344f,9.29784f,191.406f, +-148.438f,7.91508f,191.406f, +-144.531f,6.85636f,191.406f, +-140.625f,8.06021f,191.406f, +-136.719f,8.86078f,191.406f, +-132.813f,11.0565f,191.406f, +-128.906f,12.4031f,191.406f, +-125.0f,13.4308f,191.406f, +-121.094f,13.8732f,191.406f, +-117.188f,15.0555f,191.406f, +-113.281f,16.0219f,191.406f, +-109.375f,16.8646f,191.406f, +-105.469f,16.9156f,191.406f, +-101.563f,16.9811f,191.406f, +-97.6563f,17.1773f,191.406f, +-93.75f,16.9233f,191.406f, +-89.8438f,15.3563f,191.406f, +-85.9375f,14.4936f,191.406f, +-82.0313f,15.6108f,191.406f, +-78.125f,15.9615f,191.406f, +-74.2188f,14.6365f,191.406f, +-70.3125f,15.5344f,191.406f, +-66.4063f,17.4295f,191.406f, +-62.5f,18.2646f,191.406f, +-58.5938f,19.0205f,191.406f, +-54.6875f,19.0503f,191.406f, +-50.7813f,17.6912f,191.406f, +-46.875f,17.6816f,191.406f, +-42.9688f,18.8066f,191.406f, +-39.0625f,19.8444f,191.406f, +-35.1563f,18.7929f,191.406f, +-31.25f,18.6865f,191.406f, +-27.3438f,19.0671f,191.406f, +-23.4375f,18.6708f,191.406f, +-19.5313f,17.7215f,191.406f, +-15.625f,16.4711f,191.406f, +-11.7188f,15.4735f,191.406f, +-7.8125f,14.6316f,191.406f, +-3.90625f,13.8779f,191.406f, +0.0f,13.7777f,191.406f, +3.90625f,14.3936f,191.406f, +-250.0f,6.25219f,187.5f, +-246.094f,5.98752f,187.5f, +-242.188f,5.50108f,187.5f, +-238.281f,5.52049f,187.5f, +-234.375f,7.87236f,187.5f, +-230.469f,10.0244f,187.5f, +-226.563f,10.9579f,187.5f, +-222.656f,11.4176f,187.5f, +-218.75f,11.1583f,187.5f, +-214.844f,12.0797f,187.5f, +-210.938f,10.8226f,187.5f, +-207.031f,8.91363f,187.5f, +-203.125f,7.71952f,187.5f, +-199.219f,8.97116f,187.5f, +-195.313f,10.8813f,187.5f, +-191.406f,12.5874f,187.5f, +-187.5f,13.3418f,187.5f, +-183.594f,13.6407f,187.5f, +-179.688f,13.8787f,187.5f, +-175.781f,13.7918f,187.5f, +-171.875f,12.965f,187.5f, +-167.969f,12.2732f,187.5f, +-164.063f,11.6063f,187.5f, +-160.156f,10.9159f,187.5f, +-156.25f,10.2447f,187.5f, +-152.344f,9.32757f,187.5f, +-148.438f,9.17721f,187.5f, +-144.531f,9.53961f,187.5f, +-140.625f,10.4339f,187.5f, +-136.719f,11.8144f,187.5f, +-132.813f,13.3081f,187.5f, +-128.906f,13.571f,187.5f, +-125.0f,13.9242f,187.5f, +-121.094f,15.4069f,187.5f, +-117.188f,16.9689f,187.5f, +-113.281f,17.987f,187.5f, +-109.375f,18.7838f,187.5f, +-105.469f,18.7737f,187.5f, +-101.563f,18.6666f,187.5f, +-97.6563f,18.4809f,187.5f, +-93.75f,18.3562f,187.5f, +-89.8438f,16.3715f,187.5f, +-85.9375f,14.5483f,187.5f, +-82.0313f,14.9648f,187.5f, +-78.125f,16.1061f,187.5f, +-74.2188f,14.4715f,187.5f, +-70.3125f,14.8322f,187.5f, +-66.4063f,16.3093f,187.5f, +-62.5f,17.3305f,187.5f, +-58.5938f,18.3312f,187.5f, +-54.6875f,18.2865f,187.5f, +-50.7813f,17.4373f,187.5f, +-46.875f,17.9803f,187.5f, +-42.9688f,18.679f,187.5f, +-39.0625f,19.2363f,187.5f, +-35.1563f,19.9926f,187.5f, +-31.25f,19.8827f,187.5f, +-27.3438f,19.283f,187.5f, +-23.4375f,19.0081f,187.5f, +-19.5313f,17.5129f,187.5f, +-15.625f,16.6754f,187.5f, +-11.7188f,15.6685f,187.5f, +-7.8125f,14.6133f,187.5f, +-3.90625f,13.9468f,187.5f, +0.0f,14.2206f,187.5f, +3.90625f,14.1738f,187.5f, +-250.0f,7.10023f,183.594f, +-246.094f,6.39376f,183.594f, +-242.188f,5.78017f,183.594f, +-238.281f,5.07235f,183.594f, +-234.375f,5.98564f,183.594f, +-230.469f,7.6542f,183.594f, +-226.563f,8.75539f,183.594f, +-222.656f,9.90845f,183.594f, +-218.75f,10.2067f,183.594f, +-214.844f,10.2019f,183.594f, +-210.938f,9.2327f,183.594f, +-207.031f,7.67088f,183.594f, +-203.125f,8.15546f,183.594f, +-199.219f,9.42269f,183.594f, +-195.313f,10.8046f,183.594f, +-191.406f,13.3042f,183.594f, +-187.5f,13.9971f,183.594f, +-183.594f,13.621f,183.594f, +-179.688f,13.5612f,183.594f, +-175.781f,13.5357f,183.594f, +-171.875f,12.8778f,183.594f, +-167.969f,12.0385f,183.594f, +-164.063f,11.4391f,183.594f, +-160.156f,10.4255f,183.594f, +-156.25f,10.5692f,183.594f, +-152.344f,10.5452f,183.594f, +-148.438f,11.506f,183.594f, +-144.531f,12.1591f,183.594f, +-140.625f,12.6212f,183.594f, +-136.719f,13.5025f,183.594f, +-132.813f,14.3363f,183.594f, +-128.906f,14.5206f,183.594f, +-125.0f,15.4902f,183.594f, +-121.094f,17.4029f,183.594f, +-117.188f,17.9537f,183.594f, +-113.281f,18.5532f,183.594f, +-109.375f,19.2939f,183.594f, +-105.469f,19.2503f,183.594f, +-101.563f,19.8772f,183.594f, +-97.6563f,19.6753f,183.594f, +-93.75f,18.6744f,183.594f, +-89.8438f,17.7905f,183.594f, +-85.9375f,16.1613f,183.594f, +-82.0313f,15.7839f,183.594f, +-78.125f,15.657f,183.594f, +-74.2188f,14.4171f,183.594f, +-70.3125f,14.6083f,183.594f, +-66.4063f,15.5594f,183.594f, +-62.5f,16.1338f,183.594f, +-58.5938f,17.1134f,183.594f, +-54.6875f,16.8192f,183.594f, +-50.7813f,17.6885f,183.594f, +-46.875f,18.5331f,183.594f, +-42.9688f,19.7359f,183.594f, +-39.0625f,20.7966f,183.594f, +-35.1563f,20.414f,183.594f, +-31.25f,20.1587f,183.594f, +-27.3438f,19.9385f,183.594f, +-23.4375f,18.4694f,183.594f, +-19.5313f,16.9742f,183.594f, +-15.625f,16.0698f,183.594f, +-11.7188f,15.4466f,183.594f, +-7.8125f,15.0614f,183.594f, +-3.90625f,15.2165f,183.594f, +0.0f,14.2632f,183.594f, +3.90625f,13.9878f,183.594f, +-250.0f,8.16978f,179.688f, +-246.094f,7.02044f,179.688f, +-242.188f,6.49336f,179.688f, +-238.281f,6.17674f,179.688f, +-234.375f,4.65977f,179.688f, +-230.469f,5.28977f,179.688f, +-226.563f,7.10711f,179.688f, +-222.656f,8.03062f,179.688f, +-218.75f,9.32719f,179.688f, +-214.844f,9.22926f,179.688f, +-210.938f,8.64588f,179.688f, +-207.031f,7.76534f,179.688f, +-203.125f,8.37552f,179.688f, +-199.219f,8.61402f,179.688f, +-195.313f,10.7567f,179.688f, +-191.406f,12.1961f,179.688f, +-187.5f,13.5076f,179.688f, +-183.594f,13.5739f,179.688f, +-179.688f,13.6032f,179.688f, +-175.781f,13.5388f,179.688f, +-171.875f,13.0425f,179.688f, +-167.969f,13.5885f,179.688f, +-164.063f,13.2666f,179.688f, +-160.156f,11.7827f,179.688f, +-156.25f,12.3517f,179.688f, +-152.344f,13.1307f,179.688f, +-148.438f,13.6688f,179.688f, +-144.531f,13.758f,179.688f, +-140.625f,14.023f,179.688f, +-136.719f,15.1514f,179.688f, +-132.813f,16.004f,179.688f, +-128.906f,16.8991f,179.688f, +-125.0f,17.3616f,179.688f, +-121.094f,18.6059f,179.688f, +-117.188f,19.3263f,179.688f, +-113.281f,19.1956f,179.688f, +-109.375f,19.7991f,179.688f, +-105.469f,20.6907f,179.688f, +-101.563f,21.7059f,179.688f, +-97.6563f,21.5595f,179.688f, +-93.75f,20.4072f,179.688f, +-89.8438f,19.1786f,179.688f, +-85.9375f,18.2895f,179.688f, +-82.0313f,17.1568f,179.688f, +-78.125f,15.2991f,179.688f, +-74.2188f,14.0951f,179.688f, +-70.3125f,14.2935f,179.688f, +-66.4063f,15.0579f,179.688f, +-62.5f,15.3497f,179.688f, +-58.5938f,15.4148f,179.688f, +-54.6875f,17.2528f,179.688f, +-50.7813f,18.38f,179.688f, +-46.875f,19.343f,179.688f, +-42.9688f,20.2151f,179.688f, +-39.0625f,21.1482f,179.688f, +-35.1563f,20.8113f,179.688f, +-31.25f,19.3685f,179.688f, +-27.3438f,18.4966f,179.688f, +-23.4375f,17.1162f,179.688f, +-19.5313f,16.1739f,179.688f, +-15.625f,15.1081f,179.688f, +-11.7188f,15.5766f,179.688f, +-7.8125f,16.3649f,179.688f, +-3.90625f,16.3198f,179.688f, +0.0f,15.6844f,179.688f, +3.90625f,14.6785f,179.688f, +-250.0f,9.32456f,175.781f, +-246.094f,8.37571f,175.781f, +-242.188f,7.57502f,175.781f, +-238.281f,7.01497f,175.781f, +-234.375f,5.67261f,175.781f, +-230.469f,4.32895f,175.781f, +-226.563f,5.20027f,175.781f, +-222.656f,6.31061f,175.781f, +-218.75f,7.56464f,175.781f, +-214.844f,8.35874f,175.781f, +-210.938f,8.24556f,175.781f, +-207.031f,7.58905f,175.781f, +-203.125f,8.23662f,175.781f, +-199.219f,8.64236f,175.781f, +-195.313f,10.4842f,175.781f, +-191.406f,11.8296f,175.781f, +-187.5f,13.5307f,175.781f, +-183.594f,14.3422f,175.781f, +-179.688f,14.0725f,175.781f, +-175.781f,14.6f,175.781f, +-171.875f,13.9877f,175.781f, +-167.969f,13.7556f,175.781f, +-164.063f,13.4564f,175.781f, +-160.156f,13.6823f,175.781f, +-156.25f,14.2643f,175.781f, +-152.344f,14.5034f,175.781f, +-148.438f,14.905f,175.781f, +-144.531f,15.0207f,175.781f, +-140.625f,15.2745f,175.781f, +-136.719f,16.7553f,175.781f, +-132.813f,17.9777f,175.781f, +-128.906f,18.5468f,175.781f, +-125.0f,19.2067f,175.781f, +-121.094f,19.2384f,175.781f, +-117.188f,19.4993f,175.781f, +-113.281f,20.2276f,175.781f, +-109.375f,21.3946f,175.781f, +-105.469f,22.0598f,175.781f, +-101.563f,23.2713f,175.781f, +-97.6563f,22.6691f,175.781f, +-93.75f,21.3119f,175.781f, +-89.8438f,20.6083f,175.781f, +-85.9375f,19.4937f,175.781f, +-82.0313f,18.1998f,175.781f, +-78.125f,15.7716f,175.781f, +-74.2188f,14.2438f,175.781f, +-70.3125f,14.4105f,175.781f, +-66.4063f,15.1879f,175.781f, +-62.5f,15.7946f,175.781f, +-58.5938f,16.2302f,175.781f, +-54.6875f,17.1058f,175.781f, +-50.7813f,18.9688f,175.781f, +-46.875f,19.3102f,175.781f, +-42.9688f,19.3902f,175.781f, +-39.0625f,19.6545f,175.781f, +-35.1563f,19.2909f,175.781f, +-31.25f,18.5385f,175.781f, +-27.3438f,16.4388f,175.781f, +-23.4375f,15.5576f,175.781f, +-19.5313f,15.7726f,175.781f, +-15.625f,16.3756f,175.781f, +-11.7188f,16.9626f,175.781f, +-7.8125f,17.219f,175.781f, +-3.90625f,17.063f,175.781f, +0.0f,16.3609f,175.781f, +3.90625f,15.2963f,175.781f, +-250.0f,10.0329f,171.875f, +-246.094f,8.57258f,171.875f, +-242.188f,7.81755f,171.875f, +-238.281f,6.9951f,171.875f, +-234.375f,5.59199f,171.875f, +-230.469f,4.81205f,171.875f, +-226.563f,4.7432f,171.875f, +-222.656f,5.42683f,171.875f, +-218.75f,6.16332f,171.875f, +-214.844f,6.63573f,171.875f, +-210.938f,6.97578f,171.875f, +-207.031f,7.49804f,171.875f, +-203.125f,8.51155f,171.875f, +-199.219f,7.94356f,171.875f, +-195.313f,9.50881f,171.875f, +-191.406f,10.9726f,171.875f, +-187.5f,13.1622f,171.875f, +-183.594f,13.8249f,171.875f, +-179.688f,15.1925f,171.875f, +-175.781f,14.9284f,171.875f, +-171.875f,13.915f,171.875f, +-167.969f,14.2258f,171.875f, +-164.063f,13.435f,171.875f, +-160.156f,13.9359f,171.875f, +-156.25f,14.8963f,171.875f, +-152.344f,15.2933f,171.875f, +-148.438f,15.0124f,171.875f, +-144.531f,15.0787f,171.875f, +-140.625f,15.1958f,171.875f, +-136.719f,17.151f,171.875f, +-132.813f,18.8799f,171.875f, +-128.906f,19.5273f,171.875f, +-125.0f,19.6894f,171.875f, +-121.094f,19.6466f,171.875f, +-117.188f,20.5941f,171.875f, +-113.281f,21.5237f,171.875f, +-109.375f,22.5435f,171.875f, +-105.469f,23.0706f,171.875f, +-101.563f,23.614f,171.875f, +-97.6563f,22.4198f,171.875f, +-93.75f,21.9598f,171.875f, +-89.8438f,22.3051f,171.875f, +-85.9375f,21.7459f,171.875f, +-82.0313f,20.1308f,171.875f, +-78.125f,17.6018f,171.875f, +-74.2188f,15.106f,171.875f, +-70.3125f,16.0838f,171.875f, +-66.4063f,16.4153f,171.875f, +-62.5f,16.9093f,171.875f, +-58.5938f,16.7439f,171.875f, +-54.6875f,16.4659f,171.875f, +-50.7813f,18.0893f,171.875f, +-46.875f,18.8298f,171.875f, +-42.9688f,18.459f,171.875f, +-39.0625f,18.0953f,171.875f, +-35.1563f,18.2461f,171.875f, +-31.25f,17.0625f,171.875f, +-27.3438f,15.3181f,171.875f, +-23.4375f,15.1837f,171.875f, +-19.5313f,17.2025f,171.875f, +-15.625f,18.3144f,171.875f, +-11.7188f,18.4161f,171.875f, +-7.8125f,18.3279f,171.875f, +-3.90625f,17.5657f,171.875f, +0.0f,16.2057f,171.875f, +3.90625f,16.0791f,171.875f, +-250.0f,9.46368f,167.969f, +-246.094f,8.91851f,167.969f, +-242.188f,7.83383f,167.969f, +-238.281f,7.4147f,167.969f, +-234.375f,6.33692f,167.969f, +-230.469f,5.44334f,167.969f, +-226.563f,4.39369f,167.969f, +-222.656f,3.44146f,167.969f, +-218.75f,4.44651f,167.969f, +-214.844f,5.36701f,167.969f, +-210.938f,6.2915f,167.969f, +-207.031f,6.3588f,167.969f, +-203.125f,7.36203f,167.969f, +-199.219f,7.7957f,167.969f, +-195.313f,9.3926f,167.969f, +-191.406f,11.2699f,167.969f, +-187.5f,12.3727f,167.969f, +-183.594f,14.7022f,167.969f, +-179.688f,15.4324f,167.969f, +-175.781f,15.226f,167.969f, +-171.875f,13.6658f,167.969f, +-167.969f,14.0361f,167.969f, +-164.063f,13.5871f,167.969f, +-160.156f,14.725f,167.969f, +-156.25f,15.5452f,167.969f, +-152.344f,16.3685f,167.969f, +-148.438f,17.0213f,167.969f, +-144.531f,16.2228f,167.969f, +-140.625f,15.1123f,167.969f, +-136.719f,16.9339f,167.969f, +-132.813f,18.4025f,167.969f, +-128.906f,19.9945f,167.969f, +-125.0f,20.4069f,167.969f, +-121.094f,21.447f,167.969f, +-117.188f,22.384f,167.969f, +-113.281f,22.4822f,167.969f, +-109.375f,22.9018f,167.969f, +-105.469f,23.4936f,167.969f, +-101.563f,23.0085f,167.969f, +-97.6563f,22.8398f,167.969f, +-93.75f,23.2939f,167.969f, +-89.8438f,23.3336f,167.969f, +-85.9375f,22.6883f,167.969f, +-82.0313f,21.8752f,167.969f, +-78.125f,18.7456f,167.969f, +-74.2188f,16.5685f,167.969f, +-70.3125f,17.179f,167.969f, +-66.4063f,18.1074f,167.969f, +-62.5f,18.9865f,167.969f, +-58.5938f,17.4851f,167.969f, +-54.6875f,17.2795f,167.969f, +-50.7813f,16.9142f,167.969f, +-46.875f,17.1532f,167.969f, +-42.9688f,17.796f,167.969f, +-39.0625f,17.6868f,167.969f, +-35.1563f,16.7998f,167.969f, +-31.25f,16.0556f,167.969f, +-27.3438f,14.7864f,167.969f, +-23.4375f,16.8386f,167.969f, +-19.5313f,17.9676f,167.969f, +-15.625f,18.4144f,167.969f, +-11.7188f,18.9248f,167.969f, +-7.8125f,18.4614f,167.969f, +-3.90625f,17.2197f,167.969f, +0.0f,16.7097f,167.969f, +3.90625f,17.1455f,167.969f, +-250.0f,9.27861f,164.063f, +-246.094f,8.67875f,164.063f, +-242.188f,8.39269f,164.063f, +-238.281f,7.54041f,164.063f, +-234.375f,6.37361f,164.063f, +-230.469f,5.0066f,164.063f, +-226.563f,3.63142f,164.063f, +-222.656f,2.77898f,164.063f, +-218.75f,2.89032f,164.063f, +-214.844f,4.01591f,164.063f, +-210.938f,4.52151f,164.063f, +-207.031f,4.85596f,164.063f, +-203.125f,6.21759f,164.063f, +-199.219f,8.25574f,164.063f, +-195.313f,10.3856f,164.063f, +-191.406f,11.6593f,164.063f, +-187.5f,12.5334f,164.063f, +-183.594f,14.1044f,164.063f, +-179.688f,14.8149f,164.063f, +-175.781f,14.9916f,164.063f, +-171.875f,14.6218f,164.063f, +-167.969f,14.5374f,164.063f, +-164.063f,13.7748f,164.063f, +-160.156f,15.1069f,164.063f, +-156.25f,16.5225f,164.063f, +-152.344f,17.8264f,164.063f, +-148.438f,18.5076f,164.063f, +-144.531f,17.6099f,164.063f, +-140.625f,16.4656f,164.063f, +-136.719f,16.7761f,164.063f, +-132.813f,19.1652f,164.063f, +-128.906f,20.565f,164.063f, +-125.0f,21.7781f,164.063f, +-121.094f,22.7613f,164.063f, +-117.188f,23.5743f,164.063f, +-113.281f,23.3567f,164.063f, +-109.375f,24.4075f,164.063f, +-105.469f,24.4502f,164.063f, +-101.563f,24.044f,164.063f, +-97.6563f,24.669f,164.063f, +-93.75f,24.7946f,164.063f, +-89.8438f,23.9722f,164.063f, +-85.9375f,23.2481f,164.063f, +-82.0313f,22.4202f,164.063f, +-78.125f,19.4816f,164.063f, +-74.2188f,18.3571f,164.063f, +-70.3125f,19.3195f,164.063f, +-66.4063f,19.6276f,164.063f, +-62.5f,19.775f,164.063f, +-58.5938f,18.4049f,164.063f, +-54.6875f,17.6998f,164.063f, +-50.7813f,16.7989f,164.063f, +-46.875f,16.5351f,164.063f, +-42.9688f,16.0836f,164.063f, +-39.0625f,16.4446f,164.063f, +-35.1563f,15.0322f,164.063f, +-31.25f,14.1679f,164.063f, +-27.3438f,16.0461f,164.063f, +-23.4375f,16.985f,164.063f, +-19.5313f,17.3286f,164.063f, +-15.625f,18.477f,164.063f, +-11.7188f,17.8736f,164.063f, +-7.8125f,17.8059f,164.063f, +-3.90625f,17.2079f,164.063f, +0.0f,16.7726f,164.063f, +3.90625f,16.4621f,164.063f, +-250.0f,8.56359f,160.156f, +-246.094f,8.04536f,160.156f, +-242.188f,7.71795f,160.156f, +-238.281f,7.20369f,160.156f, +-234.375f,5.51432f,160.156f, +-230.469f,5.00541f,160.156f, +-226.563f,4.36899f,160.156f, +-222.656f,3.03865f,160.156f, +-218.75f,2.92915f,160.156f, +-214.844f,2.63693f,160.156f, +-210.938f,2.69254f,160.156f, +-207.031f,3.5578f,160.156f, +-203.125f,5.61634f,160.156f, +-199.219f,7.61065f,160.156f, +-195.313f,9.64763f,160.156f, +-191.406f,11.2848f,160.156f, +-187.5f,12.7624f,160.156f, +-183.594f,13.2875f,160.156f, +-179.688f,15.2776f,160.156f, +-175.781f,15.3268f,160.156f, +-171.875f,15.211f,160.156f, +-167.969f,14.343f,160.156f, +-164.063f,14.8683f,160.156f, +-160.156f,16.1659f,160.156f, +-156.25f,16.4538f,160.156f, +-152.344f,18.5601f,160.156f, +-148.438f,19.2615f,160.156f, +-144.531f,18.8155f,160.156f, +-140.625f,17.4377f,160.156f, +-136.719f,17.6478f,160.156f, +-132.813f,19.7168f,160.156f, +-128.906f,21.4745f,160.156f, +-125.0f,23.0596f,160.156f, +-121.094f,24.6069f,160.156f, +-117.188f,25.9676f,160.156f, +-113.281f,26.2865f,160.156f, +-109.375f,27.1441f,160.156f, +-105.469f,27.0334f,160.156f, +-101.563f,26.0567f,160.156f, +-97.6563f,26.2584f,160.156f, +-93.75f,26.2751f,160.156f, +-89.8438f,25.6929f,160.156f, +-85.9375f,24.0275f,160.156f, +-82.0313f,22.2346f,160.156f, +-78.125f,20.4728f,160.156f, +-74.2188f,19.6229f,160.156f, +-70.3125f,20.0997f,160.156f, +-66.4063f,21.118f,160.156f, +-62.5f,20.4515f,160.156f, +-58.5938f,19.4599f,160.156f, +-54.6875f,18.2081f,160.156f, +-50.7813f,16.8263f,160.156f, +-46.875f,16.3719f,160.156f, +-42.9688f,15.1416f,160.156f, +-39.0625f,14.5969f,160.156f, +-35.1563f,14.7039f,160.156f, +-31.25f,14.8314f,160.156f, +-27.3438f,16.4129f,160.156f, +-23.4375f,16.144f,160.156f, +-19.5313f,17.5764f,160.156f, +-15.625f,17.9247f,160.156f, +-11.7188f,17.0582f,160.156f, +-7.8125f,17.1554f,160.156f, +-3.90625f,16.8369f,160.156f, +0.0f,16.4316f,160.156f, +3.90625f,16.628f,160.156f, +-250.0f,7.51933f,156.25f, +-246.094f,7.63381f,156.25f, +-242.188f,7.57378f,156.25f, +-238.281f,6.94606f,156.25f, +-234.375f,4.79198f,156.25f, +-230.469f,4.43262f,156.25f, +-226.563f,4.13314f,156.25f, +-222.656f,2.75517f,156.25f, +-218.75f,2.67631f,156.25f, +-214.844f,3.321f,156.25f, +-210.938f,3.33063f,156.25f, +-207.031f,3.60719f,156.25f, +-203.125f,4.44636f,156.25f, +-199.219f,6.02108f,156.25f, +-195.313f,8.25702f,156.25f, +-191.406f,10.5762f,156.25f, +-187.5f,11.4514f,156.25f, +-183.594f,12.7361f,156.25f, +-179.688f,15.4206f,156.25f, +-175.781f,16.1997f,156.25f, +-171.875f,14.8996f,156.25f, +-167.969f,14.1118f,156.25f, +-164.063f,16.0576f,156.25f, +-160.156f,17.6078f,156.25f, +-156.25f,17.7518f,156.25f, +-152.344f,18.4278f,156.25f, +-148.438f,19.5827f,156.25f, +-144.531f,19.2756f,156.25f, +-140.625f,18.2888f,156.25f, +-136.719f,18.7157f,156.25f, +-132.813f,20.4669f,156.25f, +-128.906f,22.5748f,156.25f, +-125.0f,24.648f,156.25f, +-121.094f,27.1223f,156.25f, +-117.188f,28.0709f,156.25f, +-113.281f,28.4982f,156.25f, +-109.375f,29.0927f,156.25f, +-105.469f,29.2755f,156.25f, +-101.563f,28.9208f,156.25f, +-97.6563f,28.3829f,156.25f, +-93.75f,26.8508f,156.25f, +-89.8438f,25.9621f,156.25f, +-85.9375f,24.2707f,156.25f, +-82.0313f,22.6235f,156.25f, +-78.125f,21.9368f,156.25f, +-74.2188f,21.0831f,156.25f, +-70.3125f,21.368f,156.25f, +-66.4063f,21.3333f,156.25f, +-62.5f,20.5296f,156.25f, +-58.5938f,19.98f,156.25f, +-54.6875f,18.5818f,156.25f, +-50.7813f,17.2025f,156.25f, +-46.875f,16.1859f,156.25f, +-42.9688f,14.4559f,156.25f, +-39.0625f,13.7597f,156.25f, +-35.1563f,14.6354f,156.25f, +-31.25f,15.6213f,156.25f, +-27.3438f,15.683f,156.25f, +-23.4375f,16.5331f,156.25f, +-19.5313f,16.8272f,156.25f, +-15.625f,16.551f,156.25f, +-11.7188f,16.34f,156.25f, +-7.8125f,16.4067f,156.25f, +-3.90625f,15.8725f,156.25f, +0.0f,16.3451f,156.25f, +3.90625f,16.9346f,156.25f, +-250.0f,6.48899f,152.344f, +-246.094f,6.4047f,152.344f, +-242.188f,6.57203f,152.344f, +-238.281f,5.4628f,152.344f, +-234.375f,4.20753f,152.344f, +-230.469f,2.81156f,152.344f, +-226.563f,1.88132f,152.344f, +-222.656f,1.57153f,152.344f, +-218.75f,2.48106f,152.344f, +-214.844f,2.88884f,152.344f, +-210.938f,2.63578f,152.344f, +-207.031f,2.9717f,152.344f, +-203.125f,3.6084f,152.344f, +-199.219f,3.99032f,152.344f, +-195.313f,7.36858f,152.344f, +-191.406f,9.54951f,152.344f, +-187.5f,10.6254f,152.344f, +-183.594f,12.3317f,152.344f, +-179.688f,14.015f,152.344f, +-175.781f,14.8857f,152.344f, +-171.875f,14.9944f,152.344f, +-167.969f,14.7547f,152.344f, +-164.063f,16.7748f,152.344f, +-160.156f,18.5461f,152.344f, +-156.25f,19.5932f,152.344f, +-152.344f,19.1033f,152.344f, +-148.438f,19.012f,152.344f, +-144.531f,19.4428f,152.344f, +-140.625f,19.3453f,152.344f, +-136.719f,20.6611f,152.344f, +-132.813f,22.2914f,152.344f, +-128.906f,24.3802f,152.344f, +-125.0f,26.4048f,152.344f, +-121.094f,28.3525f,152.344f, +-117.188f,30.0561f,152.344f, +-113.281f,30.1155f,152.344f, +-109.375f,30.9005f,152.344f, +-105.469f,30.8767f,152.344f, +-101.563f,30.9056f,152.344f, +-97.6563f,30.3635f,152.344f, +-93.75f,28.3996f,152.344f, +-89.8438f,25.8081f,152.344f, +-85.9375f,24.3731f,152.344f, +-82.0313f,22.7783f,152.344f, +-78.125f,22.5973f,152.344f, +-74.2188f,21.8359f,152.344f, +-70.3125f,21.4903f,152.344f, +-66.4063f,21.0461f,152.344f, +-62.5f,19.9934f,152.344f, +-58.5938f,19.4729f,152.344f, +-54.6875f,18.1265f,152.344f, +-50.7813f,16.4684f,152.344f, +-46.875f,15.0104f,152.344f, +-42.9688f,13.8642f,152.344f, +-39.0625f,14.8875f,152.344f, +-35.1563f,15.117f,152.344f, +-31.25f,15.0707f,152.344f, +-27.3438f,15.3829f,152.344f, +-23.4375f,15.5218f,152.344f, +-19.5313f,15.215f,152.344f, +-15.625f,15.2099f,152.344f, +-11.7188f,15.5383f,152.344f, +-7.8125f,15.6462f,152.344f, +-3.90625f,15.3096f,152.344f, +0.0f,16.3854f,152.344f, +3.90625f,17.6952f,152.344f, +-250.0f,5.17712f,148.438f, +-246.094f,4.67214f,148.438f, +-242.188f,4.31659f,148.438f, +-238.281f,3.2191f,148.438f, +-234.375f,2.13365f,148.438f, +-230.469f,1.19555f,148.438f, +-226.563f,0.110638f,148.438f, +-222.656f,0.945025f,148.438f, +-218.75f,1.43378f,148.438f, +-214.844f,2.06915f,148.438f, +-210.938f,2.27715f,148.438f, +-207.031f,2.23051f,148.438f, +-203.125f,2.64045f,148.438f, +-199.219f,2.99575f,148.438f, +-195.313f,5.40402f,148.438f, +-191.406f,8.03643f,148.438f, +-187.5f,10.0212f,148.438f, +-183.594f,12.2205f,148.438f, +-179.688f,14.1884f,148.438f, +-175.781f,14.5505f,148.438f, +-171.875f,15.188f,148.438f, +-167.969f,15.2222f,148.438f, +-164.063f,17.4791f,148.438f, +-160.156f,19.6158f,148.438f, +-156.25f,20.2107f,148.438f, +-152.344f,20.552f,148.438f, +-148.438f,20.2463f,148.438f, +-144.531f,20.4526f,148.438f, +-140.625f,20.9426f,148.438f, +-136.719f,22.6331f,148.438f, +-132.813f,25.1345f,148.438f, +-128.906f,27.0299f,148.438f, +-125.0f,29.381f,148.438f, +-121.094f,31.0494f,148.438f, +-117.188f,31.7246f,148.438f, +-113.281f,31.9331f,148.438f, +-109.375f,31.9517f,148.438f, +-105.469f,32.217f,148.438f, +-101.563f,31.9001f,148.438f, +-97.6563f,30.471f,148.438f, +-93.75f,28.6143f,148.438f, +-89.8438f,26.5696f,148.438f, +-85.9375f,24.7785f,148.438f, +-82.0313f,23.3248f,148.438f, +-78.125f,22.2737f,148.438f, +-74.2188f,22.0395f,148.438f, +-70.3125f,21.4879f,148.438f, +-66.4063f,20.5539f,148.438f, +-62.5f,19.3981f,148.438f, +-58.5938f,18.0902f,148.438f, +-54.6875f,16.6154f,148.438f, +-50.7813f,15.8338f,148.438f, +-46.875f,14.0809f,148.438f, +-42.9688f,12.8188f,148.438f, +-39.0625f,14.0819f,148.438f, +-35.1563f,14.3673f,148.438f, +-31.25f,14.2973f,148.438f, +-27.3438f,15.1616f,148.438f, +-23.4375f,13.9458f,148.438f, +-19.5313f,14.9412f,148.438f, +-15.625f,15.4488f,148.438f, +-11.7188f,15.3397f,148.438f, +-7.8125f,15.0356f,148.438f, +-3.90625f,15.6431f,148.438f, +0.0f,16.6218f,148.438f, +3.90625f,18.4109f,148.438f, +-250.0f,5.38918f,144.531f, +-246.094f,4.29322f,144.531f, +-242.188f,2.99843f,144.531f, +-238.281f,2.80561f,144.531f, +-234.375f,1.65282f,144.531f, +-230.469f,-0.268879f,144.531f, +-226.563f,-0.474469f,144.531f, +-222.656f,-0.0607398f,144.531f, +-218.75f,0.859532f,144.531f, +-214.844f,1.28455f,144.531f, +-210.938f,1.69755f,144.531f, +-207.031f,2.1277f,144.531f, +-203.125f,2.92014f,144.531f, +-199.219f,3.85473f,144.531f, +-195.313f,4.38999f,144.531f, +-191.406f,6.72101f,144.531f, +-187.5f,9.24433f,144.531f, +-183.594f,11.6027f,144.531f, +-179.688f,13.2042f,144.531f, +-175.781f,14.6647f,144.531f, +-171.875f,14.7252f,144.531f, +-167.969f,16.1425f,144.531f, +-164.063f,18.1823f,144.531f, +-160.156f,19.9802f,144.531f, +-156.25f,22.2009f,144.531f, +-152.344f,21.9313f,144.531f, +-148.438f,22.3421f,144.531f, +-144.531f,21.6393f,144.531f, +-140.625f,23.0621f,144.531f, +-136.719f,24.695f,144.531f, +-132.813f,26.6159f,144.531f, +-128.906f,29.9912f,144.531f, +-125.0f,31.6471f,144.531f, +-121.094f,32.4919f,144.531f, +-117.188f,32.9775f,144.531f, +-113.281f,33.1587f,144.531f, +-109.375f,33.0247f,144.531f, +-105.469f,32.4654f,144.531f, +-101.563f,31.5009f,144.531f, +-97.6563f,30.2211f,144.531f, +-93.75f,28.3655f,144.531f, +-89.8438f,26.6696f,144.531f, +-85.9375f,25.6101f,144.531f, +-82.0313f,23.5563f,144.531f, +-78.125f,21.8779f,144.531f, +-74.2188f,21.4789f,144.531f, +-70.3125f,21.2134f,144.531f, +-66.4063f,20.0494f,144.531f, +-62.5f,19.4674f,144.531f, +-58.5938f,17.3288f,144.531f, +-54.6875f,16.7337f,144.531f, +-50.7813f,15.9259f,144.531f, +-46.875f,14.3007f,144.531f, +-42.9688f,13.3631f,144.531f, +-39.0625f,12.7904f,144.531f, +-35.1563f,13.6627f,144.531f, +-31.25f,13.6872f,144.531f, +-27.3438f,14.0818f,144.531f, +-23.4375f,13.953f,144.531f, +-19.5313f,14.0386f,144.531f, +-15.625f,14.1249f,144.531f, +-11.7188f,14.1069f,144.531f, +-7.8125f,14.4968f,144.531f, +-3.90625f,15.4283f,144.531f, +0.0f,16.5593f,144.531f, +3.90625f,17.8758f,144.531f, +-250.0f,5.32443f,140.625f, +-246.094f,4.53202f,140.625f, +-242.188f,2.85351f,140.625f, +-238.281f,1.48443f,140.625f, +-234.375f,0.193579f,140.625f, +-230.469f,-0.0240196f,140.625f, +-226.563f,-0.195521f,140.625f, +-222.656f,-0.525286f,140.625f, +-218.75f,0.255241f,140.625f, +-214.844f,0.505993f,140.625f, +-210.938f,1.2501f,140.625f, +-207.031f,2.77282f,140.625f, +-203.125f,3.23678f,140.625f, +-199.219f,3.81665f,140.625f, +-195.313f,4.45749f,140.625f, +-191.406f,6.57237f,140.625f, +-187.5f,8.78049f,140.625f, +-183.594f,10.653f,140.625f, +-179.688f,12.1762f,140.625f, +-175.781f,13.836f,140.625f, +-171.875f,14.4421f,140.625f, +-167.969f,16.2272f,140.625f, +-164.063f,17.8194f,140.625f, +-160.156f,20.3268f,140.625f, +-156.25f,21.6942f,140.625f, +-152.344f,21.8506f,140.625f, +-148.438f,22.857f,140.625f, +-144.531f,23.0189f,140.625f, +-140.625f,24.7041f,140.625f, +-136.719f,26.468f,140.625f, +-132.813f,28.6459f,140.625f, +-128.906f,30.9708f,140.625f, +-125.0f,33.2917f,140.625f, +-121.094f,34.9879f,140.625f, +-117.188f,34.5936f,140.625f, +-113.281f,34.2431f,140.625f, +-109.375f,33.7219f,140.625f, +-105.469f,32.9679f,140.625f, +-101.563f,31.3296f,140.625f, +-97.6563f,30.0001f,140.625f, +-93.75f,28.0182f,140.625f, +-89.8438f,26.2542f,140.625f, +-85.9375f,24.9632f,140.625f, +-82.0313f,23.5598f,140.625f, +-78.125f,21.3613f,140.625f, +-74.2188f,20.8425f,140.625f, +-70.3125f,20.6976f,140.625f, +-66.4063f,19.4459f,140.625f, +-62.5f,17.9969f,140.625f, +-58.5938f,17.2754f,140.625f, +-54.6875f,16.763f,140.625f, +-50.7813f,15.8668f,140.625f, +-46.875f,15.2278f,140.625f, +-42.9688f,14.0988f,140.625f, +-39.0625f,13.4132f,140.625f, +-35.1563f,12.9004f,140.625f, +-31.25f,12.6267f,140.625f, +-27.3438f,12.7032f,140.625f, +-23.4375f,12.0508f,140.625f, +-19.5313f,12.8332f,140.625f, +-15.625f,12.2269f,140.625f, +-11.7188f,12.2256f,140.625f, +-7.8125f,13.9086f,140.625f, +-3.90625f,15.559f,140.625f, +0.0f,16.8086f,140.625f, +3.90625f,18.5798f,140.625f, +-250.0f,4.69677f,136.719f, +-246.094f,3.45683f,136.719f, +-242.188f,1.81964f,136.719f, +-238.281f,1.13059f,136.719f, +-234.375f,0.535221f,136.719f, +-230.469f,0.868904f,136.719f, +-226.563f,0.574251f,136.719f, +-222.656f,0.279368f,136.719f, +-218.75f,-1.1876f,136.719f, +-214.844f,-0.688708f,136.719f, +-210.938f,0.470686f,136.719f, +-207.031f,2.00488f,136.719f, +-203.125f,3.42644f,136.719f, +-199.219f,4.20503f,136.719f, +-195.313f,5.23588f,136.719f, +-191.406f,6.02424f,136.719f, +-187.5f,7.96541f,136.719f, +-183.594f,10.5299f,136.719f, +-179.688f,12.0941f,136.719f, +-175.781f,13.5058f,136.719f, +-171.875f,14.8816f,136.719f, +-167.969f,16.551f,136.719f, +-164.063f,17.712f,136.719f, +-160.156f,19.6536f,136.719f, +-156.25f,21.4322f,136.719f, +-152.344f,22.672f,136.719f, +-148.438f,23.3463f,136.719f, +-144.531f,24.5334f,136.719f, +-140.625f,26.061f,136.719f, +-136.719f,27.7423f,136.719f, +-132.813f,30.1692f,136.719f, +-128.906f,33.3739f,136.719f, +-125.0f,34.9742f,136.719f, +-121.094f,35.9387f,136.719f, +-117.188f,36.0925f,136.719f, +-113.281f,35.6549f,136.719f, +-109.375f,34.5646f,136.719f, +-105.469f,34.6062f,136.719f, +-101.563f,32.8375f,136.719f, +-97.6563f,30.2678f,136.719f, +-93.75f,27.2213f,136.719f, +-89.8438f,26.1126f,136.719f, +-85.9375f,24.9965f,136.719f, +-82.0313f,22.5841f,136.719f, +-78.125f,21.7213f,136.719f, +-74.2188f,21.534f,136.719f, +-70.3125f,20.5652f,136.719f, +-66.4063f,19.032f,136.719f, +-62.5f,17.4252f,136.719f, +-58.5938f,16.7783f,136.719f, +-54.6875f,15.9619f,136.719f, +-50.7813f,14.8707f,136.719f, +-46.875f,14.3143f,136.719f, +-42.9688f,13.8793f,136.719f, +-39.0625f,12.6352f,136.719f, +-35.1563f,12.0433f,136.719f, +-31.25f,11.8551f,136.719f, +-27.3438f,12.0193f,136.719f, +-23.4375f,11.2795f,136.719f, +-19.5313f,11.6002f,136.719f, +-15.625f,10.9143f,136.719f, +-11.7188f,12.1473f,136.719f, +-7.8125f,14.3093f,136.719f, +-3.90625f,16.245f,136.719f, +0.0f,17.3141f,136.719f, +3.90625f,19.7224f,136.719f, +-250.0f,3.94613f,132.813f, +-246.094f,2.33247f,132.813f, +-242.188f,1.96569f,132.813f, +-238.281f,1.1741f,132.813f, +-234.375f,0.606142f,132.813f, +-230.469f,0.00901447f,132.813f, +-226.563f,0.143339f,132.813f, +-222.656f,-0.356031f,132.813f, +-218.75f,-1.55439f,132.813f, +-214.844f,-1.22801f,132.813f, +-210.938f,-0.390443f,132.813f, +-207.031f,1.15349f,132.813f, +-203.125f,2.6275f,132.813f, +-199.219f,3.55895f,132.813f, +-195.313f,4.99281f,132.813f, +-191.406f,4.99673f,132.813f, +-187.5f,6.96468f,132.813f, +-183.594f,10.0691f,132.813f, +-179.688f,12.3783f,132.813f, +-175.781f,13.2459f,132.813f, +-171.875f,14.3637f,132.813f, +-167.969f,16.3222f,132.813f, +-164.063f,17.6984f,132.813f, +-160.156f,19.3295f,132.813f, +-156.25f,20.9768f,132.813f, +-152.344f,23.1452f,132.813f, +-148.438f,23.885f,132.813f, +-144.531f,24.7169f,132.813f, +-140.625f,27.1655f,132.813f, +-136.719f,29.0232f,132.813f, +-132.813f,30.2573f,132.813f, +-128.906f,33.5563f,132.813f, +-125.0f,35.1858f,132.813f, +-121.094f,36.4332f,132.813f, +-117.188f,36.6359f,132.813f, +-113.281f,36.0253f,132.813f, +-109.375f,34.7127f,132.813f, +-105.469f,34.6833f,132.813f, +-101.563f,33.7208f,132.813f, +-97.6563f,30.9809f,132.813f, +-93.75f,27.9091f,132.813f, +-89.8438f,25.709f,132.813f, +-85.9375f,24.452f,132.813f, +-82.0313f,22.4897f,132.813f, +-78.125f,22.0485f,132.813f, +-74.2188f,22.1517f,132.813f, +-70.3125f,20.4874f,132.813f, +-66.4063f,19.0482f,132.813f, +-62.5f,17.1019f,132.813f, +-58.5938f,16.7815f,132.813f, +-54.6875f,15.1253f,132.813f, +-50.7813f,14.5074f,132.813f, +-46.875f,12.7631f,132.813f, +-42.9688f,12.6595f,132.813f, +-39.0625f,11.9406f,132.813f, +-35.1563f,11.7459f,132.813f, +-31.25f,10.8406f,132.813f, +-27.3438f,11.0393f,132.813f, +-23.4375f,10.4798f,132.813f, +-19.5313f,10.8165f,132.813f, +-15.625f,12.4368f,132.813f, +-11.7188f,13.2405f,132.813f, +-7.8125f,14.9282f,132.813f, +-3.90625f,16.4449f,132.813f, +0.0f,17.8238f,132.813f, +3.90625f,19.9574f,132.813f, +-250.0f,2.5744f,128.906f, +-246.094f,2.12474f,128.906f, +-242.188f,0.674823f,128.906f, +-238.281f,-0.305135f,128.906f, +-234.375f,-0.948647f,128.906f, +-230.469f,-0.982836f,128.906f, +-226.563f,-1.17369f,128.906f, +-222.656f,-1.48697f,128.906f, +-218.75f,-2.23137f,128.906f, +-214.844f,-2.13825f,128.906f, +-210.938f,-1.06826f,128.906f, +-207.031f,0.0666403f,128.906f, +-203.125f,1.15717f,128.906f, +-199.219f,3.14762f,128.906f, +-195.313f,4.08858f,128.906f, +-191.406f,5.07728f,128.906f, +-187.5f,8.06699f,128.906f, +-183.594f,10.7473f,128.906f, +-179.688f,12.0801f,128.906f, +-175.781f,13.1617f,128.906f, +-171.875f,14.5283f,128.906f, +-167.969f,15.8148f,128.906f, +-164.063f,16.9067f,128.906f, +-160.156f,18.6293f,128.906f, +-156.25f,20.8869f,128.906f, +-152.344f,22.6168f,128.906f, +-148.438f,23.9359f,128.906f, +-144.531f,26.521f,128.906f, +-140.625f,27.4381f,128.906f, +-136.719f,29.5698f,128.906f, +-132.813f,30.681f,128.906f, +-128.906f,33.28f,128.906f, +-125.0f,35.3433f,128.906f, +-121.094f,36.3509f,128.906f, +-117.188f,36.2098f,128.906f, +-113.281f,35.157f,128.906f, +-109.375f,35.3884f,128.906f, +-105.469f,35.7158f,128.906f, +-101.563f,34.3449f,128.906f, +-97.6563f,32.5198f,128.906f, +-93.75f,29.0611f,128.906f, +-89.8438f,25.9945f,128.906f, +-85.9375f,24.2624f,128.906f, +-82.0313f,23.0248f,128.906f, +-78.125f,21.6012f,128.906f, +-74.2188f,21.0399f,128.906f, +-70.3125f,20.1719f,128.906f, +-66.4063f,18.6862f,128.906f, +-62.5f,17.3287f,128.906f, +-58.5938f,16.0916f,128.906f, +-54.6875f,14.1153f,128.906f, +-50.7813f,12.6292f,128.906f, +-46.875f,12.0431f,128.906f, +-42.9688f,11.4785f,128.906f, +-39.0625f,11.911f,128.906f, +-35.1563f,11.6609f,128.906f, +-31.25f,10.4332f,128.906f, +-27.3438f,9.68026f,128.906f, +-23.4375f,9.84506f,128.906f, +-19.5313f,11.6097f,128.906f, +-15.625f,13.2944f,128.906f, +-11.7188f,14.0518f,128.906f, +-7.8125f,15.2998f,128.906f, +-3.90625f,16.8731f,128.906f, +0.0f,18.0594f,128.906f, +3.90625f,20.0876f,128.906f, +-250.0f,2.47782f,125.0f, +-246.094f,1.27263f,125.0f, +-242.188f,-0.535855f,125.0f, +-238.281f,-1.33089f,125.0f, +-234.375f,-1.63273f,125.0f, +-230.469f,-2.30607f,125.0f, +-226.563f,-2.13647f,125.0f, +-222.656f,-2.95807f,125.0f, +-218.75f,-2.92133f,125.0f, +-214.844f,-3.33811f,125.0f, +-210.938f,-2.29807f,125.0f, +-207.031f,-0.860766f,125.0f, +-203.125f,0.507027f,125.0f, +-199.219f,1.54044f,125.0f, +-195.313f,3.32139f,125.0f, +-191.406f,5.76593f,125.0f, +-187.5f,8.17548f,125.0f, +-183.594f,10.5223f,125.0f, +-179.688f,11.4741f,125.0f, +-175.781f,12.3545f,125.0f, +-171.875f,13.5542f,125.0f, +-167.969f,14.4358f,125.0f, +-164.063f,16.6197f,125.0f, +-160.156f,18.7561f,125.0f, +-156.25f,21.2618f,125.0f, +-152.344f,22.9541f,125.0f, +-148.438f,24.7574f,125.0f, +-144.531f,26.8375f,125.0f, +-140.625f,28.3307f,125.0f, +-136.719f,29.2598f,125.0f, +-132.813f,31.2334f,125.0f, +-128.906f,32.9236f,125.0f, +-125.0f,34.4853f,125.0f, +-121.094f,35.1589f,125.0f, +-117.188f,34.4655f,125.0f, +-113.281f,35.7692f,125.0f, +-109.375f,35.9985f,125.0f, +-105.469f,35.7974f,125.0f, +-101.563f,34.6099f,125.0f, +-97.6563f,32.4066f,125.0f, +-93.75f,28.8398f,125.0f, +-89.8438f,26.014f,125.0f, +-85.9375f,25.0319f,125.0f, +-82.0313f,23.7685f,125.0f, +-78.125f,22.4099f,125.0f, +-74.2188f,20.9166f,125.0f, +-70.3125f,19.1502f,125.0f, +-66.4063f,17.8355f,125.0f, +-62.5f,16.5146f,125.0f, +-58.5938f,14.9189f,125.0f, +-54.6875f,13.2423f,125.0f, +-50.7813f,12.2568f,125.0f, +-46.875f,11.4853f,125.0f, +-42.9688f,10.7795f,125.0f, +-39.0625f,10.3251f,125.0f, +-35.1563f,10.4077f,125.0f, +-31.25f,9.96202f,125.0f, +-27.3438f,9.77658f,125.0f, +-23.4375f,10.6703f,125.0f, +-19.5313f,12.2058f,125.0f, +-15.625f,13.8385f,125.0f, +-11.7188f,15.1556f,125.0f, +-7.8125f,15.7626f,125.0f, +-3.90625f,16.911f,125.0f, +0.0f,18.0803f,125.0f, +3.90625f,18.9654f,125.0f, +-250.0f,1.97449f,121.094f, +-246.094f,1.28169f,121.094f, +-242.188f,0.0699786f,121.094f, +-238.281f,-1.31551f,121.094f, +-234.375f,-2.33115f,121.094f, +-230.469f,-3.19445f,121.094f, +-226.563f,-3.91693f,121.094f, +-222.656f,-4.0298f,121.094f, +-218.75f,-4.334f,121.094f, +-214.844f,-3.5405f,121.094f, +-210.938f,-2.70043f,121.094f, +-207.031f,-2.86125f,121.094f, +-203.125f,-1.24727f,121.094f, +-199.219f,0.20797f,121.094f, +-195.313f,2.52573f,121.094f, +-191.406f,4.8544f,121.094f, +-187.5f,7.37504f,121.094f, +-183.594f,9.40828f,121.094f, +-179.688f,11.0747f,121.094f, +-175.781f,11.9892f,121.094f, +-171.875f,12.3358f,121.094f, +-167.969f,13.2084f,121.094f, +-164.063f,15.8626f,121.094f, +-160.156f,18.1098f,121.094f, +-156.25f,20.2905f,121.094f, +-152.344f,22.8183f,121.094f, +-148.438f,25.3439f,121.094f, +-144.531f,26.7908f,121.094f, +-140.625f,29.0959f,121.094f, +-136.719f,29.9478f,121.094f, +-132.813f,30.8054f,121.094f, +-128.906f,31.9545f,121.094f, +-125.0f,33.8025f,121.094f, +-121.094f,35.2826f,121.094f, +-117.188f,36.2373f,121.094f, +-113.281f,36.7861f,121.094f, +-109.375f,36.509f,121.094f, +-105.469f,35.7461f,121.094f, +-101.563f,33.7802f,121.094f, +-97.6563f,30.788f,121.094f, +-93.75f,28.1422f,121.094f, +-89.8438f,26.6316f,121.094f, +-85.9375f,26.0349f,121.094f, +-82.0313f,24.8022f,121.094f, +-78.125f,23.5217f,121.094f, +-74.2188f,21.74f,121.094f, +-70.3125f,20.0101f,121.094f, +-66.4063f,17.8705f,121.094f, +-62.5f,15.6785f,121.094f, +-58.5938f,13.74f,121.094f, +-54.6875f,12.3387f,121.094f, +-50.7813f,11.9457f,121.094f, +-46.875f,12.0102f,121.094f, +-42.9688f,11.0065f,121.094f, +-39.0625f,9.84571f,121.094f, +-35.1563f,10.0894f,121.094f, +-31.25f,10.5366f,121.094f, +-27.3438f,9.94957f,121.094f, +-23.4375f,11.0038f,121.094f, +-19.5313f,12.8084f,121.094f, +-15.625f,13.8969f,121.094f, +-11.7188f,14.9146f,121.094f, +-7.8125f,15.4187f,121.094f, +-3.90625f,16.094f,121.094f, +0.0f,17.0612f,121.094f, +3.90625f,18.5327f,121.094f, +-250.0f,2.18397f,117.188f, +-246.094f,1.51628f,117.188f, +-242.188f,0.628327f,117.188f, +-238.281f,-0.567933f,117.188f, +-234.375f,-2.01568f,117.188f, +-230.469f,-3.41089f,117.188f, +-226.563f,-3.82758f,117.188f, +-222.656f,-5.01586f,117.188f, +-218.75f,-4.74822f,117.188f, +-214.844f,-3.30853f,117.188f, +-210.938f,-2.32499f,117.188f, +-207.031f,-1.71509f,117.188f, +-203.125f,-1.19203f,117.188f, +-199.219f,0.219498f,117.188f, +-195.313f,1.66304f,117.188f, +-191.406f,4.35105f,117.188f, +-187.5f,6.33228f,117.188f, +-183.594f,8.00972f,117.188f, +-179.688f,9.71486f,117.188f, +-175.781f,10.7727f,117.188f, +-171.875f,11.358f,117.188f, +-167.969f,12.5239f,117.188f, +-164.063f,14.6278f,117.188f, +-160.156f,17.2069f,117.188f, +-156.25f,19.9779f,117.188f, +-152.344f,23.4607f,117.188f, +-148.438f,26.6108f,117.188f, +-144.531f,28.4635f,117.188f, +-140.625f,29.7705f,117.188f, +-136.719f,31.0684f,117.188f, +-132.813f,31.8395f,117.188f, +-128.906f,32.1658f,117.188f, +-125.0f,34.7478f,117.188f, +-121.094f,36.0624f,117.188f, +-117.188f,37.2702f,117.188f, +-113.281f,37.3474f,117.188f, +-109.375f,37.242f,117.188f, +-105.469f,36.1544f,117.188f, +-101.563f,33.403f,117.188f, +-97.6563f,31.294f,117.188f, +-93.75f,29.4961f,117.188f, +-89.8438f,29.0556f,117.188f, +-85.9375f,28.2757f,117.188f, +-82.0313f,26.6322f,117.188f, +-78.125f,24.8286f,117.188f, +-74.2188f,22.7019f,117.188f, +-70.3125f,20.4725f,117.188f, +-66.4063f,17.984f,117.188f, +-62.5f,16.3033f,117.188f, +-58.5938f,14.2087f,117.188f, +-54.6875f,12.8086f,117.188f, +-50.7813f,12.5463f,117.188f, +-46.875f,12.1781f,117.188f, +-42.9688f,11.1391f,117.188f, +-39.0625f,10.4623f,117.188f, +-35.1563f,11.0528f,117.188f, +-31.25f,11.454f,117.188f, +-27.3438f,10.5577f,117.188f, +-23.4375f,10.6328f,117.188f, +-19.5313f,12.5569f,117.188f, +-15.625f,13.5389f,117.188f, +-11.7188f,14.3792f,117.188f, +-7.8125f,15.4809f,117.188f, +-3.90625f,16.1008f,117.188f, +0.0f,17.3675f,117.188f, +3.90625f,18.919f,117.188f, +}; + +btScalar Landscape06Nml[] = { +-0.373915f,0.891474f,-0.255855f, +-0.31015f,0.793525f,-0.52357f, +-0.450332f,0.86393f,-0.225447f, +-0.404472f,0.777981f,-0.480778f, +-0.557629f,0.811458f,-0.174885f, +-0.428564f,0.86234f,-0.269633f, +-0.414608f,0.909847f,-0.0166634f, +-0.208047f,0.971233f,0.115854f, +-0.328757f,0.932331f,0.150588f, +-0.263029f,0.937991f,0.225808f, +-0.409412f,0.900937f,0.143853f, +-0.455309f,0.881347f,0.126178f, +-0.31951f,0.943247f,0.0905511f, +-0.33825f,0.934582f,0.1102f, +-0.183669f,0.981438f,0.0551769f, +-0.208308f,0.97293f,0.100072f, +-0.189578f,0.981862f,-0.00282566f, +-0.201983f,0.97649f,0.0752952f, +-0.0672914f,0.99749f,-0.0220572f, +-0.118523f,0.991949f,0.0446084f, +0.102757f,0.986595f,-0.126773f, +0.00122687f,0.992675f,-0.120808f, +0.0798054f,0.967751f,-0.238933f, +0.00875196f,0.978629f,-0.205448f, +0.141554f,0.932155f,-0.333242f, +0.0918343f,0.965319f,-0.244387f, +0.372959f,0.842559f,-0.388582f, +0.280191f,0.875069f,-0.394647f, +0.314921f,0.849656f,-0.422977f, +0.258676f,0.813335f,-0.521127f, +0.266443f,0.876708f,-0.400489f, +0.358307f,0.856764f,-0.370907f, +0.280512f,0.913716f,-0.293999f, +0.337561f,0.857178f,-0.388971f, +0.0927666f,0.994197f,-0.0544758f, +0.155544f,0.953116f,-0.259567f, +-0.18671f,0.979157f,-0.0799463f, +-0.20939f,0.930283f,-0.301212f, +-0.117108f,0.986639f,-0.113269f, +-0.190516f,0.897405f,-0.397956f, +-0.0703231f,0.977433f,-0.199199f, +-0.142735f,0.82748f,-0.54305f, +-0.00706444f,0.969596f,-0.244609f, +0.0216131f,0.85384f,-0.520087f, +-0.100606f,0.961424f,-0.256011f, +0.00977565f,0.925054f,-0.379709f, +-0.0412166f,0.978641f,-0.201403f, +0.099113f,0.987693f,-0.12099f, +0.0911178f,0.982669f,-0.16143f, +0.0730708f,0.986329f,-0.147703f, +0.114859f,0.978874f,-0.169152f, +0.109302f,0.983788f,-0.142175f, +0.116167f,0.976713f,-0.180378f, +0.0784892f,0.966143f,-0.24578f, +0.0196949f,0.987682f,-0.155232f, +0.0258077f,0.978923f,-0.202593f, +-0.0161862f,0.979217f,-0.202168f, +-0.120896f,0.935381f,-0.332336f, +-0.0291128f,0.941335f,-0.336215f, +-0.0776893f,0.901631f,-0.425472f, +-0.0768763f,0.919716f,-0.384983f, +-0.0462705f,0.951989f,-0.302615f, +-0.0260847f,0.891121f,-0.453016f, +-0.0818404f,0.911776f,-0.40245f, +0.152271f,0.86407f,-0.479789f, +0.0880729f,0.874485f,-0.476991f, +0.11644f,0.855496f,-0.504548f, +0.0395982f,0.813262f,-0.580548f, +0.00631598f,0.857568f,-0.514332f, +-0.0780909f,0.759651f,-0.645626f, +-0.0538158f,0.822232f,-0.566603f, +0.0102932f,0.785194f,-0.619165f, +-0.00905015f,0.879608f,-0.475613f, +0.0439442f,0.825793f,-0.562259f, +-0.15058f,0.877556f,-0.455216f, +-0.0080088f,0.902753f,-0.430085f, +-0.112334f,0.946952f,-0.301104f, +0.00843129f,0.966084f,-0.258092f, +-0.0520095f,0.981628f,-0.183579f, +-0.0023169f,0.970009f,-0.243057f, +-0.0302799f,0.995335f,-0.0916051f, +0.0376961f,0.991328f,-0.125888f, +0.0852061f,0.995425f,-0.0432221f, +0.156966f,0.986644f,0.0435404f, +0.21491f,0.973384f,-0.079613f, +0.060548f,0.977921f,-0.200013f, +0.158822f,0.967125f,-0.198606f, +0.134591f,0.957423f,-0.255396f, +0.121293f,0.978974f,-0.164008f, +0.108432f,0.947609f,-0.300465f, +0.0857608f,0.988377f,-0.125519f, +0.0956294f,0.951748f,-0.291599f, +-0.0286686f,0.995404f,-0.0913747f, +0.0793846f,0.975448f,-0.205424f, +0.106071f,0.990697f,0.085251f, +0.292453f,0.941038f,0.170056f, +0.371746f,0.914213f,0.161306f, +0.341006f,0.933768f,0.108596f, +0.372402f,0.920827f,0.115737f, +0.298439f,0.950662f,-0.0847083f, +0.211549f,0.974139f,0.0793788f, +0.255698f,0.96634f,-0.0283838f, +-0.0706076f,0.991212f,0.111867f, +0.0490836f,0.977096f,0.207063f, +-0.256838f,0.950876f,0.172827f, +-0.168627f,0.937168f,0.30542f, +-0.0642391f,0.963856f,0.258562f, +-0.00196823f,0.905532f,0.424274f, +0.182795f,0.945782f,0.268481f, +0.13515f,0.919671f,0.368699f, +0.107184f,0.970151f,0.217528f, +0.00985613f,0.977921f,0.208742f, +0.0734564f,0.98632f,0.147572f, +0.067487f,0.972043f,0.224896f, +0.20672f,0.968081f,0.141727f, +0.186648f,0.970679f,0.151478f, +0.213561f,0.965286f,0.150383f, +0.189498f,0.980689f,0.0483704f, +0.277013f,0.94213f,0.188824f, +0.316429f,0.927757f,0.197839f, +0.225121f,0.964838f,0.135677f, +0.124434f,0.992109f,0.0153398f, +0.14416f,0.987262f,0.0673169f, +0.128154f,0.991727f,-0.0073791f, +0.1809f,0.982671f,0.0404037f, +0.125271f,0.99083f,-0.0506329f, +0.117639f,0.992303f,-0.0386759f, +0.0449726f,0.973305f,-0.225068f, +0.124809f,0.992058f,0.0156083f, +0.127135f,0.958258f,-0.256082f, +0.171896f,0.982167f,0.0761593f, +0.160304f,0.951991f,-0.260798f, +-0.494953f,0.868907f,-0.00477061f, +-0.512017f,0.856533f,0.0647248f, +-0.564588f,0.823588f,0.0542513f, +-0.480746f,0.876502f,0.0250513f, +-0.397786f,0.91419f,0.0776024f, +-0.3922f,0.916181f,0.0824136f, +-0.288362f,0.955571f,0.0610852f, +-0.109541f,0.991807f,0.0657195f, +-0.119597f,0.99188f,-0.0432477f, +-0.0246849f,0.992746f,-0.117673f, +0.197846f,0.964215f,-0.176481f, +0.198977f,0.940868f,-0.274182f, +0.288209f,0.884317f,-0.367314f, +0.309487f,0.847917f,-0.430411f, +0.274335f,0.939851f,-0.20352f, +0.256503f,0.958634f,-0.123399f, +0.0454718f,0.993939f,-0.100084f, +-0.104233f,0.980418f,0.167081f, +-0.137204f,0.957647f,0.253153f, +-0.0909923f,0.97094f,0.221352f, +-0.0588081f,0.977218f,0.203928f, +0.0555628f,0.971956f,0.228506f, +0.00693538f,0.995197f,0.0976442f, +0.0112691f,0.996103f,-0.0874744f, +0.104487f,0.972486f,-0.208215f, +0.102504f,0.971128f,-0.215412f, +0.0933319f,0.976682f,-0.193342f, +0.023135f,0.974909f,-0.221399f, +0.0195254f,0.964185f,-0.264511f, +0.0843961f,0.966003f,-0.244368f, +0.0791804f,0.94997f,-0.30214f, +0.048562f,0.904645f,-0.423391f, +0.168302f,0.901104f,-0.399607f, +0.0460994f,0.899241f,-0.435018f, +-0.0201301f,0.942734f,-0.332937f, +-0.0651933f,0.964794f,-0.254799f, +-0.107417f,0.971064f,-0.213298f, +-0.17484f,0.97454f,-0.140369f, +-0.26177f,0.957564f,-0.120611f, +-0.18964f,0.980348f,-0.0543506f, +-0.0244255f,0.999511f,-0.0195208f, +0.0943164f,0.983888f,-0.151887f, +0.241216f,0.961222f,-0.133665f, +0.186016f,0.976207f,-0.111437f, +0.0288865f,0.998091f,-0.0545842f, +-0.00269516f,0.997826f,0.0658428f, +-0.0454406f,0.988515f,0.144131f, +0.0349744f,0.994103f,0.102646f, +0.310638f,0.939659f,0.143339f, +0.362637f,0.904005f,0.226428f, +0.268459f,0.940968f,0.206177f, +-0.0101438f,0.990408f,0.137803f, +-0.259956f,0.964753f,0.0409231f, +-0.105214f,0.99436f,0.0133734f, +0.151003f,0.984401f,0.0902917f, +0.153972f,0.971331f,0.181133f, +0.131893f,0.982033f,0.134962f, +0.145326f,0.983866f,0.104346f, +0.172165f,0.970545f,0.16853f, +0.260168f,0.947172f,0.18756f, +0.265906f,0.934787f,0.235514f, +0.175251f,0.956563f,0.232968f, +0.205308f,0.948623f,0.240753f, +0.093567f,0.968565f,0.230493f, +0.000708259f,0.964766f,0.263107f, +0.00657781f,0.964909f,0.262504f, +-0.520396f,0.851586f,0.063156f, +-0.521936f,0.850242f,0.0683468f, +-0.537166f,0.843365f,0.0137284f, +-0.507784f,0.86143f,-0.00972442f, +-0.393238f,0.917684f,0.0567504f, +-0.362634f,0.931285f,-0.0347048f, +-0.298916f,0.951591f,-0.0715749f, +-0.125797f,0.991634f,-0.0289454f, +0.00629701f,0.999979f,0.00117199f, +0.0170902f,0.994718f,-0.101214f, +0.290594f,0.952688f,-0.0891078f, +0.285259f,0.936469f,-0.20409f, +0.342737f,0.918097f,-0.199071f, +0.262981f,0.956466f,-0.126547f, +-0.000199178f,0.996828f,-0.0795833f, +0.16652f,0.978742f,0.119733f, +0.0382843f,0.984413f,0.171653f, +-0.277981f,0.950703f,0.137441f, +-0.18354f,0.954113f,0.236605f, +-0.0382213f,0.967232f,0.251001f, +-0.0471282f,0.983482f,0.174763f, +0.05509f,0.990469f,0.126237f, +0.154415f,0.97865f,0.135647f, +0.187824f,0.979878f,0.0675348f, +0.226039f,0.971999f,-0.0642243f, +0.0780765f,0.982532f,-0.168921f, +0.109774f,0.985685f,-0.127961f, +0.112009f,0.982676f,-0.147653f, +0.0632751f,0.975786f,-0.209375f, +0.0264674f,0.962968f,-0.268312f, +0.10845f,0.959018f,-0.261771f, +0.0643921f,0.961817f,-0.266009f, +0.166593f,0.964859f,-0.203209f, +0.0747121f,0.973608f,-0.215653f, +-0.165051f,0.968419f,-0.186874f, +-0.148108f,0.983106f,-0.10755f, +-0.179372f,0.979451f,-0.0922022f, +-0.237948f,0.970437f,-0.0404116f, +-0.2824f,0.959184f,-0.014723f, +-0.146028f,0.988959f,-0.0252228f, +0.05616f,0.991975f,-0.113275f, +0.196359f,0.969761f,-0.144935f, +0.181455f,0.976082f,-0.119739f, +0.110973f,0.993178f,-0.035804f, +-0.0390828f,0.998775f,0.0303582f, +-0.136356f,0.988616f,0.0636122f, +-0.0521843f,0.980102f,0.191512f, +0.0572854f,0.981374f,0.183367f, +0.238568f,0.946616f,0.216801f, +0.340107f,0.907515f,0.246464f, +0.312043f,0.926088f,0.212108f, +0.0846085f,0.98223f,0.167527f, +-0.163231f,0.986101f,0.0309937f, +-0.143013f,0.98971f,-0.00457425f, +0.0291614f,0.993948f,0.105909f, +0.107232f,0.980268f,0.16606f, +0.13514f,0.977368f,0.162754f, +0.171582f,0.963454f,0.205708f, +0.160805f,0.97344f,0.162963f, +0.206565f,0.959827f,0.189905f, +0.203733f,0.939018f,0.277016f, +0.156541f,0.940477f,0.30166f, +0.14264f,0.938158f,0.315457f, +0.0877292f,0.924317f,0.371405f, +0.0427952f,0.921735f,0.385453f, +0.102307f,0.915297f,0.389569f, +-0.518725f,0.854828f,-0.0138881f, +-0.516652f,0.85588f,0.023226f, +-0.490153f,0.869598f,0.0595683f, +-0.505693f,0.862598f,-0.0140982f, +-0.393758f,0.918824f,-0.0267811f, +-0.308114f,0.951253f,-0.0135724f, +-0.25353f,0.967309f,0.00592796f, +-0.183935f,0.978787f,-0.0902442f, +-0.0335384f,0.998587f,-0.0412272f, +0.0888831f,0.995408f,-0.0355216f, +0.275528f,0.951614f,-0.136073f, +0.317879f,0.941106f,-0.115209f, +0.22556f,0.974028f,-0.0197739f, +0.262726f,0.954534f,0.140851f, +0.0383338f,0.998565f,0.0373963f, +0.0108706f,0.999386f,-0.0333096f, +0.0472758f,0.987524f,0.150202f, +-0.22401f,0.968166f,0.111686f, +-0.221122f,0.974472f,0.0388438f, +-0.0303833f,0.999266f,0.0233175f, +0.0911048f,0.995841f,0.000284795f, +0.0750561f,0.987717f,-0.137044f, +0.140099f,0.985231f,-0.098447f, +0.159287f,0.981153f,-0.10939f, +0.301657f,0.953265f,-0.0169985f, +0.140836f,0.988971f,-0.0458453f, +0.074059f,0.996008f,-0.0498236f, +0.0873182f,0.996023f,-0.0176849f, +0.132872f,0.990946f,0.019257f, +0.15553f,0.982355f,-0.103875f, +0.133638f,0.955183f,-0.264135f, +0.0505536f,0.951293f,-0.304114f, +0.0663471f,0.962897f,-0.261588f, +0.0679148f,0.992885f,-0.0978063f, +-0.186921f,0.976146f,-0.110452f, +-0.16844f,0.980926f,-0.0970201f, +-0.17716f,0.9831f,-0.0461376f, +-0.252028f,0.967676f,-0.00920485f, +-0.25063f,0.967236f,-0.0404965f, +-0.0995772f,0.983353f,-0.151991f, +0.0940064f,0.974734f,-0.202626f, +0.146102f,0.962693f,-0.227766f, +0.10874f,0.966405f,-0.232891f, +-0.0013416f,0.987029f,-0.160533f, +-0.0603915f,0.998129f,0.00954783f, +-0.17946f,0.98293f,0.040526f, +-0.153066f,0.978461f,0.138509f, +0.00546813f,0.977756f,0.209673f, +0.202775f,0.944505f,0.258443f, +0.334531f,0.904949f,0.262976f, +0.339399f,0.898505f,0.278385f, +0.212792f,0.950144f,0.227917f, +-0.0583572f,0.996371f,0.0619671f, +-0.218128f,0.975136f,0.0391184f, +-0.0703437f,0.983861f,0.16453f, +0.113041f,0.961301f,0.25124f, +0.0979771f,0.959037f,0.265798f, +0.151767f,0.929082f,0.337302f, +0.185905f,0.937423f,0.294409f, +0.169611f,0.955662f,0.240713f, +0.159864f,0.96582f,0.204047f, +0.151538f,0.965571f,0.211446f, +0.11661f,0.954852f,0.273241f, +0.0708035f,0.941966f,0.328158f, +-0.00402057f,0.956357f,0.292174f, +0.0123647f,0.956622f,0.291069f, +-0.626234f,0.777268f,-0.0607036f, +-0.590408f,0.806122f,0.0398278f, +-0.512253f,0.84829f,0.134171f, +-0.429387f,0.891471f,0.144588f, +-0.394702f,0.915407f,0.0789917f, +-0.352114f,0.935018f,0.0419128f, +-0.269358f,0.962596f,0.0292454f, +-0.0709514f,0.996127f,0.0519312f, +-0.0485279f,0.996417f,-0.069268f, +0.139101f,0.983953f,-0.111751f, +0.369972f,0.916386f,-0.152833f, +0.200502f,0.96864f,-0.146752f, +0.063154f,0.997971f,0.00814434f, +0.218613f,0.964332f,0.149236f, +0.233367f,0.966768f,0.104401f, +0.00832713f,0.995958f,-0.0894382f, +-0.101235f,0.994608f,-0.0224841f, +-0.188929f,0.980627f,0.051742f, +-0.131276f,0.990999f,0.026226f, +0.0111642f,0.996226f,-0.0860703f, +0.127344f,0.982944f,-0.132683f, +0.133649f,0.978353f,-0.157998f, +0.127047f,0.978674f,-0.161419f, +0.154013f,0.97768f,-0.142902f, +0.207952f,0.974577f,-0.0833996f, +0.130584f,0.99044f,-0.0444555f, +0.0527996f,0.997244f,-0.0521173f, +0.0873033f,0.993919f,-0.0671111f, +0.134372f,0.9813f,-0.137819f, +0.302979f,0.937443f,-0.171475f, +0.235087f,0.922651f,-0.305694f, +0.116878f,0.945593f,-0.303632f, +-0.0892912f,0.947762f,-0.306226f, +-0.0487728f,0.993685f,-0.101049f, +-0.161853f,0.9816f,-0.101314f, +-0.226351f,0.97061f,-0.0817454f, +-0.270044f,0.962691f,-0.0173905f, +-0.294262f,0.954053f,0.0565031f, +-0.151555f,0.985239f,0.0795882f, +0.00297078f,0.999916f,-0.0126498f, +0.158118f,0.985077f,-0.067991f, +0.232676f,0.957923f,-0.168067f, +0.184787f,0.953241f,-0.239135f, +-0.102652f,0.943763f,-0.314284f, +-0.249925f,0.941897f,-0.224429f, +-0.230538f,0.969668f,-0.0812203f, +-0.256878f,0.964046f,-0.0680376f, +-0.0528332f,0.99816f,0.0297627f, +0.16253f,0.979605f,0.118148f, +0.292443f,0.935246f,0.199479f, +0.337448f,0.899957f,0.276054f, +0.288581f,0.911989f,0.291541f, +0.0381605f,0.961598f,0.271797f, +-0.217082f,0.942133f,0.25546f, +-0.187341f,0.947099f,0.26059f, +0.0122725f,0.939216f,0.343107f, +0.0450967f,0.927047f,0.372224f, +0.0805118f,0.921403f,0.380178f, +0.269621f,0.884781f,0.380089f, +0.278457f,0.920235f,0.275007f, +0.240432f,0.950543f,0.19662f, +0.110916f,0.980787f,0.160482f, +0.0190768f,0.974013f,0.225685f, +0.0421661f,0.96323f,0.26535f, +0.0623149f,0.965243f,0.253816f, +0.0484827f,0.970002f,0.238214f, +-0.675447f,0.735679f,-0.050474f, +-0.639324f,0.768795f,-0.0148056f, +-0.556082f,0.830482f,0.0327513f, +-0.42972f,0.893254f,0.132053f, +-0.365389f,0.922739f,0.122653f, +-0.226979f,0.966229f,0.121993f, +-0.221717f,0.973751f,-0.051483f, +-0.0779728f,0.987923f,-0.133899f, +0.0930073f,0.979917f,-0.176386f, +0.192144f,0.942491f,-0.27348f, +0.309496f,0.916222f,-0.254459f, +0.155051f,0.977443f,-0.143405f, +-0.0554135f,0.989739f,-0.131708f, +0.110672f,0.991805f,-0.0638304f, +0.310319f,0.950296f,0.0252996f, +0.103349f,0.993006f,-0.0570824f, +-0.143599f,0.988502f,-0.0473533f, +-0.226116f,0.973312f,-0.0391734f, +-0.100068f,0.994649f,-0.0257001f, +0.124656f,0.989757f,-0.0695779f, +0.137305f,0.97907f,-0.150231f, +0.12072f,0.989818f,-0.075415f, +0.132256f,0.990827f,-0.0277589f, +0.0994133f,0.991446f,-0.0845708f, +0.16457f,0.984921f,-0.0533595f, +0.161357f,0.986289f,-0.034624f, +0.0776395f,0.993281f,-0.0858198f, +0.196429f,0.972629f,-0.124127f, +0.213597f,0.93634f,-0.278645f, +0.333587f,0.906552f,-0.258619f, +0.264447f,0.928271f,-0.261499f, +0.0224352f,0.968338f,-0.248633f, +-0.153007f,0.973949f,-0.167368f, +-0.171971f,0.976037f,-0.133332f, +-0.164739f,0.982172f,-0.0905542f, +-0.256427f,0.965345f,-0.0485236f, +-0.266685f,0.961164f,-0.0710119f, +-0.315314f,0.936338f,-0.154429f, +-0.180509f,0.974939f,-0.130043f, +0.0306802f,0.996715f,-0.0749509f, +0.181216f,0.981966f,-0.0538862f, +0.308423f,0.951239f,-0.0044789f, +0.193412f,0.981099f,-0.00609358f, +-0.00883535f,0.999181f,0.039479f, +-0.293629f,0.95203f,-0.0861418f, +-0.288511f,0.952707f,-0.0954526f, +-0.270635f,0.961763f,-0.0420598f, +-0.176015f,0.982039f,0.0679556f, +0.0472003f,0.981703f,0.184478f, +0.185293f,0.947852f,0.259313f, +0.26012f,0.901797f,0.345109f, +0.219376f,0.887657f,0.404894f, +0.015248f,0.892187f,0.451408f, +-0.212632f,0.887876f,0.407999f, +-0.145904f,0.908525f,0.391529f, +-0.0226457f,0.932703f,0.359933f, +0.0874951f,0.910834f,0.403393f, +0.125007f,0.935932f,0.329249f, +0.288568f,0.918223f,0.271284f, +0.34457f,0.896771f,0.277619f, +0.261558f,0.928634f,0.263108f, +0.0802026f,0.961218f,0.26387f, +0.0163948f,0.952196f,0.305047f, +0.0566148f,0.964684f,0.257253f, +0.102872f,0.970943f,0.216073f, +0.0353576f,0.994079f,0.102749f, +-0.569322f,0.820332f,-0.0541097f, +-0.616679f,0.764093f,-0.18939f, +-0.605157f,0.764062f,-0.223597f, +-0.50856f,0.856476f,-0.0884048f, +-0.372491f,0.927008f,0.0436669f, +-0.225048f,0.969626f,0.0958063f, +-0.0508165f,0.996801f,0.0616925f, +0.0586358f,0.990558f,-0.123919f, +0.126111f,0.966195f,-0.224862f, +0.229194f,0.950926f,-0.207869f, +0.252375f,0.936474f,-0.243564f, +0.0944308f,0.971404f,-0.217846f, +-0.0355117f,0.972557f,-0.229939f, +0.0856503f,0.962722f,-0.256575f, +0.220711f,0.941477f,-0.254769f, +0.0934053f,0.989629f,-0.109133f, +-0.156897f,0.986627f,-0.0441527f, +-0.224564f,0.970579f,-0.0868729f, +-0.0948813f,0.992594f,-0.0758608f, +0.168753f,0.983045f,-0.0717275f, +0.110894f,0.991432f,-0.0690319f, +-0.0147158f,0.998265f,0.0570193f, +0.10964f,0.979883f,0.16676f, +0.213201f,0.96906f,0.124368f, +0.195873f,0.980015f,-0.0346975f, +0.162476f,0.975738f,-0.146751f, +0.136902f,0.9692f,-0.204718f, +0.244929f,0.933568f,-0.26165f, +0.288988f,0.918188f,-0.270954f, +0.254175f,0.924529f,-0.283974f, +0.243695f,0.954587f,-0.171397f, +-0.00175415f,0.99017f,-0.13986f, +-0.165264f,0.975245f,-0.146916f, +-0.185767f,0.967008f,-0.174319f, +-0.191354f,0.972667f,-0.131541f, +-0.271241f,0.952999f,-0.134987f, +-0.1847f,0.972855f,-0.139424f, +-0.209304f,0.957842f,-0.1968f, +-0.243194f,0.936f,-0.254482f, +-0.0210884f,0.983365f,-0.18041f, +0.0761402f,0.989042f,-0.126486f, +0.185372f,0.981538f,0.047127f, +0.117606f,0.973445f,0.196404f, +-0.0453061f,0.954332f,0.295292f, +-0.152267f,0.943756f,0.293495f, +-0.272105f,0.944288f,0.185149f, +-0.341417f,0.929337f,0.140592f, +-0.316477f,0.938022f,0.141266f, +-0.0291064f,0.965694f,0.258045f, +0.139271f,0.938861f,0.31487f, +0.16066f,0.916793f,0.36562f, +0.163005f,0.879828f,0.446466f, +0.088987f,0.884248f,0.458461f, +-0.126118f,0.932849f,0.337472f, +-0.101381f,0.953175f,0.284919f, +-0.0233764f,0.967738f,0.250872f, +0.0600962f,0.965273f,0.254236f, +0.184472f,0.94915f,0.255117f, +0.293565f,0.911429f,0.288301f, +0.309916f,0.89217f,0.328611f, +0.260108f,0.896879f,0.357704f, +0.0945809f,0.935133f,0.341439f, +0.0335311f,0.964748f,0.261032f, +0.0942492f,0.979731f,0.176762f, +0.167685f,0.967918f,0.187127f, +0.258869f,0.942682f,0.210564f, +-0.367443f,0.929937f,-0.0142236f, +-0.499723f,0.853143f,-0.149749f, +-0.60287f,0.768676f,-0.213739f, +-0.628893f,0.759885f,-0.164524f, +-0.498958f,0.866588f,-0.00814533f, +-0.266358f,0.961387f,0.0691948f, +0.0209306f,0.994406f,0.103533f, +0.18825f,0.979809f,0.0673512f, +0.186929f,0.982347f,-0.00722501f, +0.221871f,0.971137f,-0.0875532f, +0.321849f,0.94224f,-0.0927163f, +0.129468f,0.975377f,-0.178544f, +-0.0214597f,0.975387f,-0.219454f, +0.135606f,0.972282f,-0.19047f, +0.166947f,0.968719f,-0.18361f, +-0.0604962f,0.993281f,-0.0986602f, +-0.147333f,0.985679f,-0.0820398f, +-0.177745f,0.972235f,-0.152201f, +-0.13389f,0.979994f,-0.147259f, +0.107621f,0.993068f,-0.0472599f, +0.0496354f,0.9956f,0.0794756f, +-0.114638f,0.990271f,0.0788811f, +0.0386746f,0.994961f,0.0924988f, +0.257639f,0.951075f,0.170521f, +0.371556f,0.918219f,0.137186f, +0.306734f,0.951256f,-0.0320228f, +0.251981f,0.957147f,-0.142743f, +0.259956f,0.937158f,-0.232721f, +0.273432f,0.938847f,-0.209289f, +0.242378f,0.942977f,-0.228139f, +0.135357f,0.967026f,-0.21573f, +-0.0237633f,0.989278f,-0.144096f, +-0.131198f,0.984621f,-0.11536f, +-0.202181f,0.972555f,-0.115152f, +-0.221308f,0.9725f,-0.0725642f, +-0.229514f,0.969023f,-0.0912046f, +-0.218972f,0.967608f,-0.125639f, +-0.212632f,0.976006f,-0.0469096f, +-0.218674f,0.974967f,-0.0402565f, +-0.122558f,0.989962f,-0.0703905f, +0.0166378f,0.999654f,0.0203946f, +-0.0104674f,0.996634f,0.0813074f, +-0.0169459f,0.959611f,0.28082f, +-0.0960206f,0.935549f,0.339894f, +-0.167668f,0.926307f,0.337405f, +-0.198261f,0.909687f,0.364915f, +-0.193335f,0.935754f,0.294935f, +-0.259424f,0.960196f,0.103554f, +-0.126539f,0.989254f,0.073239f, +0.0445245f,0.981975f,0.183692f, +0.070195f,0.9396f,0.334999f, +0.116045f,0.901991f,0.415867f, +0.160437f,0.912696f,0.375828f, +-0.00552585f,0.963507f,0.267627f, +-0.111729f,0.971129f,0.210774f, +0.00935468f,0.964114f,0.265323f, +0.084172f,0.968508f,0.234323f, +0.13752f,0.967988f,0.209968f, +0.208575f,0.947382f,0.242826f, +0.289545f,0.920265f,0.263203f, +0.228797f,0.929214f,0.290195f, +0.185013f,0.916649f,0.354295f, +0.160823f,0.950358f,0.266374f, +0.183734f,0.959776f,0.212302f, +0.0865279f,0.982909f,0.162492f, +0.143782f,0.963199f,0.227098f, +-0.40108f,0.898526f,-0.178287f, +-0.447805f,0.881163f,-0.15173f, +-0.619629f,0.769135f,-0.156501f, +-0.663764f,0.743697f,-0.0795752f, +-0.534645f,0.83883f,-0.102567f, +-0.293541f,0.950588f,-0.101077f, +-0.0154638f,0.998684f,-0.048892f, +0.170364f,0.984269f,-0.0468065f, +0.272586f,0.961403f,-0.0374194f, +0.276742f,0.955139f,-0.105472f, +0.3572f,0.929651f,-0.0903144f, +0.185848f,0.967712f,-0.170277f, +-0.00167559f,0.978573f,-0.205892f, +0.0698456f,0.971595f,-0.226108f, +0.0821889f,0.985623f,-0.147624f, +-0.0376538f,0.998466f,-0.0405822f, +-0.0983702f,0.988409f,-0.115634f, +-0.140633f,0.987279f,-0.0741791f, +-0.185061f,0.981813f,-0.0423742f, +-0.0718387f,0.997236f,0.0189748f, +0.00846681f,0.991398f,0.130611f, +0.00870324f,0.999937f,0.00714861f, +0.043927f,0.984772f,-0.168207f, +0.173423f,0.967972f,-0.181535f, +0.363952f,0.925731f,-0.10277f, +0.415083f,0.906279f,-0.0797799f, +0.295656f,0.934439f,-0.198525f, +0.285411f,0.94244f,-0.174208f, +0.286359f,0.952372f,-0.104818f, +0.274f,0.954057f,-0.121243f, +0.125082f,0.985323f,-0.116157f, +-0.0728358f,0.994219f,-0.0788892f, +-0.183935f,0.981488f,-0.0533801f, +-0.254614f,0.966975f,0.0114848f, +-0.238556f,0.965368f,0.105624f, +-0.207746f,0.971319f,0.115674f, +-0.215469f,0.971204f,0.101667f, +-0.267107f,0.96138f,0.0663435f, +-0.207576f,0.97646f,0.0586408f, +-0.117358f,0.991748f,0.0516096f, +-0.0500459f,0.994852f,0.0881198f, +-0.093813f,0.986665f,0.133006f, +-0.152698f,0.969858f,0.18989f, +-0.1251f,0.953778f,0.273236f, +-0.165614f,0.925222f,0.341373f, +-0.185498f,0.929562f,0.3186f, +-0.115032f,0.960173f,0.254626f, +-0.110794f,0.97049f,0.214181f, +-0.10146f,0.992209f,0.072301f, +-0.111958f,0.99337f,0.026117f, +-0.0975457f,0.980844f,0.168611f, +0.086247f,0.976994f,0.195051f, +0.241113f,0.947591f,0.20961f, +0.0868755f,0.959222f,0.268972f, +-0.141994f,0.949853f,0.278599f, +-0.0178282f,0.934163f,0.356401f, +0.0726972f,0.940594f,0.331659f, +0.165529f,0.917627f,0.361333f, +0.223743f,0.920886f,0.319231f, +0.302189f,0.900958f,0.311378f, +0.181249f,0.939198f,0.291642f, +0.15269f,0.934294f,0.32215f, +0.181639f,0.932767f,0.311371f, +0.174351f,0.925291f,0.336805f, +0.107261f,0.938861f,0.327163f, +0.0621733f,0.949825f,0.306542f, +-0.336425f,0.924181f,-0.180852f, +-0.467727f,0.856958f,-0.216458f, +-0.602238f,0.781026f,-0.165251f, +-0.647361f,0.734151f,-0.204809f, +-0.50962f,0.821617f,-0.255407f, +-0.329682f,0.908003f,-0.258533f, +-0.0514578f,0.97257f,-0.226846f, +0.197411f,0.959315f,-0.201849f, +0.264136f,0.946231f,-0.186758f, +0.271989f,0.947232f,-0.169627f, +0.342182f,0.926412f,-0.157076f, +0.226068f,0.960114f,-0.164544f, +0.0298714f,0.986995f,-0.157954f, +0.0947848f,0.979734f,-0.176458f, +0.0184686f,0.978597f,-0.204958f, +-0.115417f,0.979217f,-0.166771f, +-0.133289f,0.987752f,-0.0811202f, +-0.254272f,0.966705f,0.0287551f, +-0.238007f,0.962858f,0.127508f, +-0.0805244f,0.989118f,0.123135f, +0.0609568f,0.996652f,0.0544921f, +0.185345f,0.981121f,-0.0552078f, +0.246025f,0.947034f,-0.206392f, +0.188933f,0.898455f,-0.396338f, +0.253355f,0.896162f,-0.364288f, +0.431339f,0.877591f,-0.209237f, +0.33179f,0.90994f,-0.248847f, +0.173449f,0.964884f,-0.197267f, +0.195848f,0.971573f,-0.133f, +0.242458f,0.968164f,-0.0622215f, +0.0872514f,0.995924f,0.0228468f, +-0.104392f,0.994289f,0.0221861f, +-0.212909f,0.976423f,0.0355982f, +-0.329497f,0.936369f,0.121017f, +-0.322708f,0.91595f,0.238528f, +-0.206447f,0.929806f,0.304697f, +-0.167225f,0.947523f,0.272462f, +-0.184928f,0.959175f,0.213976f, +-0.173343f,0.972643f,0.154651f, +-0.113658f,0.986612f,0.116951f, +-0.0855668f,0.994338f,0.0630098f, +-0.114452f,0.992427f,0.0446133f, +-0.159653f,0.986324f,0.0409453f, +-0.238644f,0.971105f,-0.00174015f, +-0.263001f,0.962569f,0.0655076f, +-0.150786f,0.97653f,0.153794f, +-0.0789227f,0.973225f,0.21588f, +-0.0862836f,0.967962f,0.235807f, +0.0429765f,0.969236f,0.242351f, +-0.0440941f,0.992467f,0.114305f, +-0.115348f,0.992717f,-0.0347649f, +0.0790257f,0.995351f,-0.0550642f, +0.126473f,0.98592f,0.109395f, +-0.0409487f,0.953557f,0.298417f, +-0.206016f,0.913735f,0.350208f, +-0.0633912f,0.92675f,0.370293f, +0.0785739f,0.913264f,0.399719f, +0.177609f,0.899902f,0.398285f, +0.238034f,0.923241f,0.301604f, +0.255943f,0.926508f,0.27582f, +0.232022f,0.914012f,0.332787f, +0.162081f,0.936068f,0.312259f, +0.177513f,0.926269f,0.332437f, +0.185532f,0.921601f,0.340924f, +0.173632f,0.950356f,0.258214f, +0.111166f,0.980225f,0.163712f, +-0.0923042f,0.995727f,-0.00270435f, +-0.408896f,0.902709f,-0.133863f, +-0.602302f,0.79183f,-0.10118f, +-0.624884f,0.765307f,-0.154352f, +-0.552184f,0.809036f,-0.201379f, +-0.343811f,0.917937f,-0.197956f, +-0.0748905f,0.960991f,-0.266248f, +0.134998f,0.958099f,-0.252631f, +0.206547f,0.962195f,-0.177534f, +0.264489f,0.960553f,-0.0859237f, +0.340814f,0.939333f,-0.0387315f, +0.235136f,0.971602f,-0.0264814f, +0.0144037f,0.991275f,-0.131023f, +0.053242f,0.991683f,-0.117173f, +0.0920982f,0.995717f,0.00816044f, +-0.164789f,0.980567f,-0.106454f, +-0.239234f,0.97035f,-0.0344802f, +-0.316227f,0.948287f,0.0274269f, +-0.260328f,0.965493f,0.00728909f, +-0.00635978f,0.999169f,0.0402508f, +0.152101f,0.988094f,-0.023159f, +0.261272f,0.960304f,-0.0977355f, +0.363311f,0.923635f,-0.122082f, +0.303719f,0.94151f,-0.145994f, +0.209258f,0.960639f,-0.182713f, +0.299827f,0.935978f,-0.184526f, +0.310225f,0.948937f,-0.0572597f, +0.134013f,0.988326f,-0.0724722f, +0.173294f,0.983169f,-0.0578515f, +0.150596f,0.988589f,-0.00352276f, +0.0218728f,0.99535f,0.093809f, +-0.090936f,0.980927f,0.171796f, +-0.253868f,0.938693f,0.233251f, +-0.400767f,0.870372f,0.286074f, +-0.392418f,0.877786f,0.274773f, +-0.219224f,0.925755f,0.308089f, +-0.114269f,0.92983f,0.349798f, +-0.147993f,0.921652f,0.358685f, +-0.138523f,0.925121f,0.353501f, +-0.0290531f,0.945854f,0.32329f, +0.0440242f,0.978167f,0.203106f, +-0.0576599f,0.997178f,0.0480716f, +-0.156038f,0.987653f,-0.0139414f, +-0.143901f,0.989541f,-0.0100722f, +-0.293059f,0.951458f,-0.0940478f, +-0.298958f,0.953936f,-0.0251005f, +-0.203233f,0.972711f,0.111937f, +-0.134891f,0.965356f,0.223367f, +-0.0182075f,0.958686f,0.283884f, +0.123188f,0.934113f,0.33505f, +0.0872404f,0.983488f,0.15856f, +0.00440122f,0.999845f,-0.0170726f, +-0.143813f,0.987727f,0.0609306f, +-0.192356f,0.942318f,0.273927f, +-0.141157f,0.926207f,0.349593f, +-0.0674076f,0.959831f,0.272363f, +0.0730938f,0.959591f,0.27174f, +0.173541f,0.961002f,0.215311f, +0.369237f,0.888798f,0.271483f, +0.277281f,0.944196f,0.177789f, +0.215184f,0.95909f,0.183961f, +0.13088f,0.973624f,0.186887f, +0.130607f,0.953976f,0.269946f, +0.212637f,0.930888f,0.297042f, +0.306976f,0.920481f,0.241829f, +0.280289f,0.947029f,0.156763f, +0.0123331f,0.988431f,0.151171f, +-0.297868f,0.952288f,0.0664969f, +-0.612229f,0.786332f,-0.0828155f, +-0.600387f,0.789438f,-0.127758f, +-0.542733f,0.826042f,-0.151972f, +-0.320126f,0.93364f,-0.160733f, +0.000589343f,0.981171f,-0.193142f, +0.0980808f,0.971507f,-0.215763f, +0.124748f,0.986178f,-0.109047f, +0.199191f,0.978521f,-0.0531043f, +0.247764f,0.965734f,-0.0772702f, +0.318214f,0.948019f,-0.000766246f, +0.183917f,0.97162f,-0.148756f, +-0.0488566f,0.965709f,-0.25499f, +-0.0165518f,0.99654f,-0.0814512f, +-0.0793375f,0.996823f,-0.00696945f, +-0.310737f,0.950344f,-0.0169863f, +-0.292329f,0.952706f,0.0830406f, +-0.217409f,0.975529f,0.0328f, +-0.044323f,0.995765f,-0.0805443f, +0.185778f,0.977354f,-0.101323f, +0.271832f,0.958328f,-0.0878372f, +0.32088f,0.946924f,0.019279f, +0.252443f,0.960909f,0.113697f, +0.290552f,0.947257f,0.135217f, +0.289238f,0.957058f,-0.0195476f, +0.286171f,0.957114f,0.0451517f, +0.220997f,0.975269f,0.00320969f, +0.0994052f,0.991378f,-0.0853655f, +0.0429034f,0.994069f,0.099932f, +-0.0709962f,0.952332f,0.296687f, +-0.214284f,0.897012f,0.38659f, +-0.318505f,0.838002f,0.443066f, +-0.352211f,0.849573f,0.392649f, +-0.30013f,0.898851f,0.319356f, +-0.250783f,0.928599f,0.273517f, +-0.200191f,0.919896f,0.337217f, +-0.179596f,0.907951f,0.378643f, +-0.135043f,0.919145f,0.370049f, +0.0368434f,0.920312f,0.389447f, +0.16581f,0.924682f,0.34274f, +0.0946402f,0.961136f,0.259346f, +-0.111217f,0.985094f,0.131228f, +-0.13188f,0.98641f,0.0979915f, +-0.254562f,0.966634f,0.028585f, +-0.324299f,0.94515f,-0.0390035f, +-0.293729f,0.954471f,-0.0520494f, +-0.247862f,0.966889f,0.0607495f, +-0.0794894f,0.980131f,0.181727f, +0.101373f,0.964007f,0.245794f, +0.197084f,0.947574f,0.251517f, +0.177833f,0.964662f,0.194431f, +-0.161149f,0.986485f,0.0296539f, +-0.316387f,0.94824f,0.02721f, +-0.207789f,0.976057f,0.0643106f, +-0.00905536f,0.99298f,0.117933f, +0.141544f,0.987983f,0.062088f, +0.189336f,0.98168f,-0.0213574f, +0.273454f,0.960225f,0.0564811f, +0.315806f,0.930776f,0.184181f, +0.235283f,0.955417f,0.17838f, +0.124851f,0.982004f,0.141708f, +0.0792257f,0.989953f,0.117114f, +0.210835f,0.9739f,0.0840678f, +0.31429f,0.942479f,0.113817f, +0.350241f,0.914076f,0.20444f, +0.0694749f,0.983151f,0.169077f, +-0.169784f,0.982476f,0.076909f, +-0.507716f,0.850133f,-0.139637f, +-0.564212f,0.800379f,-0.202629f, +-0.514428f,0.829332f,-0.218112f, +-0.369417f,0.885582f,-0.28156f, +0.00180169f,0.974596f,-0.223965f, +0.0258344f,0.976386f,-0.214484f, +-0.024f,0.996868f,-0.0753534f, +0.239975f,0.969587f,0.0481022f, +0.34797f,0.931588f,-0.105173f, +0.316295f,0.909782f,-0.268803f, +0.250422f,0.912989f,-0.322087f, +-0.0369252f,0.950156f,-0.30958f, +-0.207502f,0.950188f,-0.232562f, +-0.167975f,0.985706f,-0.0129903f, +-0.315712f,0.948273f,0.0332206f, +-0.386969f,0.921609f,-0.0298463f, +-0.12805f,0.991662f,0.0144567f, +0.102711f,0.991948f,-0.0740863f, +0.21217f,0.967879f,-0.134884f, +0.167738f,0.98185f,-0.0885116f, +0.176293f,0.984226f,0.0148055f, +0.233609f,0.968608f,0.0850021f, +0.30166f,0.950058f,0.0799509f, +0.387591f,0.914349f,0.117215f, +0.244561f,0.968825f,0.0395933f, +0.294792f,0.954101f,0.0528114f, +0.0843374f,0.996399f,0.00873819f, +-0.221704f,0.963341f,0.151067f, +-0.335663f,0.86809f,0.365719f, +-0.262618f,0.850841f,0.455085f, +-0.222709f,0.867235f,0.445313f, +-0.24917f,0.884312f,0.39485f, +-0.238336f,0.907466f,0.345978f, +-0.270997f,0.917236f,0.291956f, +-0.229194f,0.914337f,0.333853f, +-0.15897f,0.933059f,0.322692f, +-0.100911f,0.956766f,0.272794f, +-0.0211523f,0.974532f,0.223248f, +0.201297f,0.933635f,0.29632f, +0.155914f,0.954519f,0.254134f, +-0.0218294f,0.971898f,0.234389f, +-0.079809f,0.976613f,0.199646f, +-0.0874479f,0.990326f,0.10774f, +-0.258167f,0.959037f,-0.116608f, +-0.306401f,0.945943f,-0.106352f, +-0.341562f,0.936596f,-0.0782577f, +-0.199458f,0.979359f,-0.0327519f, +0.0464294f,0.997405f,0.0550308f, +0.191208f,0.978076f,0.0825056f, +0.238583f,0.96711f,0.0881811f, +-0.0888379f,0.993271f,0.0743033f, +-0.264236f,0.955782f,0.129075f, +-0.188913f,0.981529f,0.0302016f, +-0.0145673f,0.997134f,-0.0742444f, +0.169633f,0.978852f,-0.114338f, +0.20381f,0.976959f,-0.0633407f, +0.175314f,0.984354f,-0.0176521f, +0.240514f,0.967819f,0.0740208f, +0.244396f,0.964775f,0.0973589f, +0.18832f,0.980026f,0.0639107f, +0.156937f,0.987568f,-0.00896143f, +0.262584f,0.963481f,-0.0524761f, +0.165405f,0.986171f,-0.0103631f, +0.180443f,0.960877f,0.210132f, +0.22428f,0.955199f,0.193116f, +0.0674282f,0.994387f,0.0815297f, +-0.367623f,0.911009f,-0.186858f, +-0.569756f,0.78903f,-0.229805f, +-0.492917f,0.847419f,-0.197265f, +-0.366141f,0.895981f,-0.251313f, +-0.0646011f,0.969824f,-0.235091f, +0.018291f,0.976889f,-0.212961f, +-0.170757f,0.95698f,-0.234588f, +0.158661f,0.98264f,-0.0961541f, +0.509439f,0.859861f,-0.0333235f, +0.45757f,0.865797f,-0.202548f, +0.211042f,0.949174f,-0.233516f, +-0.116125f,0.987892f,-0.102876f, +-0.347298f,0.937329f,-0.028262f, +-0.3353f,0.938887f,0.0778782f, +-0.281604f,0.948411f,0.145656f, +-0.254278f,0.964997f,0.0642133f, +-0.124948f,0.985399f,-0.115656f, +0.137997f,0.981596f,-0.132006f, +0.145883f,0.979226f,-0.140833f, +0.128056f,0.990732f,-0.0452937f, +0.135002f,0.989818f,-0.0451192f, +0.250583f,0.968082f,-0.00493589f, +0.249752f,0.966686f,-0.056052f, +0.354812f,0.933896f,0.0441336f, +0.303438f,0.951308f,0.0542095f, +0.224177f,0.96836f,0.10965f, +0.0241424f,0.959753f,0.279804f, +-0.360787f,0.871516f,0.332105f, +-0.379082f,0.837086f,0.394442f, +-0.267154f,0.880877f,0.390749f, +-0.209592f,0.899886f,0.382462f, +-0.280017f,0.899934f,0.33423f, +-0.205094f,0.90311f,0.377265f, +-0.215487f,0.908768f,0.35736f, +-0.222303f,0.927919f,0.299247f, +-0.133955f,0.964793f,0.226343f, +-0.0310722f,0.978213f,0.205265f, +0.00222901f,0.986522f,0.163613f, +0.163026f,0.975343f,0.148754f, +0.222032f,0.968535f,0.112436f, +-0.0591592f,0.996482f,0.0593585f, +-0.0736093f,0.986012f,0.149538f, +0.0883465f,0.986402f,0.138585f, +-0.129755f,0.988677f,-0.0753772f, +-0.360418f,0.926521f,-0.10797f, +-0.325602f,0.942448f,-0.0759939f, +-0.212184f,0.970083f,-0.117968f, +-0.0173686f,0.99664f,-0.0800487f, +0.199307f,0.979749f,-0.0191744f, +0.207601f,0.977585f,-0.0350739f, +-0.111673f,0.993337f,0.0284751f, +-0.348081f,0.937445f,0.00599776f, +-0.0214784f,0.998661f,0.0470579f, +0.101424f,0.987937f,-0.11702f, +0.14864f,0.985437f,-0.0825872f, +0.115279f,0.993006f,0.0255073f, +0.132171f,0.98902f,0.0661133f, +0.208651f,0.976857f,0.0470664f, +0.263292f,0.96404f,0.0361305f, +0.248825f,0.968171f,0.0270552f, +0.185161f,0.982538f,-0.018271f, +0.217415f,0.97571f,0.0268649f, +0.0197241f,0.992022f,0.124516f, +-0.222642f,0.960275f,0.168234f, +0.132211f,0.987109f,0.0902005f, +0.194249f,0.96722f,0.163561f, +-0.121192f,0.992517f,0.0149198f, +-0.530811f,0.812343f,-0.241533f, +-0.504434f,0.808747f,-0.302447f, +-0.34313f,0.885425f,-0.313504f, +-0.137778f,0.93664f,-0.322061f, +0.0757018f,0.968813f,-0.235947f, +-0.132891f,0.938587f,-0.318425f, +0.0404124f,0.947798f,-0.316301f, +0.44786f,0.871235f,-0.200923f, +0.490699f,0.867082f,-0.0859319f, +0.104719f,0.99418f,-0.0252995f, +-0.266739f,0.955461f,0.126271f, +-0.36926f,0.905342f,0.209771f, +-0.330235f,0.922316f,0.200695f, +-0.269586f,0.955277f,0.121531f, +-0.151874f,0.986716f,0.0576671f, +-0.0142621f,0.999832f,-0.0115305f, +0.159425f,0.986955f,-0.0224599f, +0.153623f,0.986882f,-0.0496328f, +0.106278f,0.991325f,-0.0773283f, +0.114508f,0.986134f,-0.120113f, +0.21169f,0.974687f,-0.0719165f, +0.274634f,0.961096f,-0.0295159f, +0.269382f,0.962666f,0.0266079f, +0.255851f,0.94689f,0.19478f, +-0.00861224f,0.958716f,0.284234f, +-0.164949f,0.853283f,0.494671f, +-0.299895f,0.797641f,0.523289f, +-0.348319f,0.830543f,0.434595f, +-0.252787f,0.902204f,0.349467f, +-0.200686f,0.920719f,0.334665f, +-0.211731f,0.897332f,0.387253f, +-0.253565f,0.89104f,0.376502f, +-0.186105f,0.884245f,0.42834f, +-0.119153f,0.910802f,0.395274f, +-0.0259565f,0.945107f,0.325728f, +-0.0365208f,0.969055f,0.244127f, +0.0217438f,0.965814f,0.258322f, +0.21499f,0.950394f,0.224789f, +0.314831f,0.941255f,0.12215f, +-0.024099f,0.99913f,-0.0340298f, +-0.193558f,0.979871f,-0.0488714f, +0.141024f,0.987427f,0.0714227f, +0.042141f,0.998281f,-0.0407328f, +-0.330902f,0.928766f,-0.167024f, +-0.316891f,0.928564f,-0.193256f, +-0.212611f,0.956496f,-0.199781f, +-0.0848317f,0.98296f,-0.163073f, +0.159095f,0.98144f,-0.107074f, +0.142493f,0.988352f,-0.0534431f, +-0.0993206f,0.99343f,0.0568515f, +-0.282995f,0.956355f,-0.0727984f, +-0.0511781f,0.994657f,-0.0896605f, +0.128118f,0.991123f,0.0355009f, +0.0178584f,0.998165f,0.057865f, +0.0308308f,0.995199f,0.0928875f, +0.176093f,0.979878f,0.0939732f, +0.250441f,0.967914f,0.0205173f, +0.266597f,0.963616f,0.0192599f, +0.242746f,0.969766f,0.0250589f, +0.198829f,0.979834f,0.0197961f, +0.092758f,0.995177f,0.031931f, +-0.00514037f,0.987257f,0.15905f, +-0.197401f,0.976423f,0.0873538f, +0.0947848f,0.990346f,0.101148f, +0.11003f,0.98867f,0.102099f, +0.0979659f,0.987432f,0.124019f, +-0.288467f,0.943192f,-0.16485f, +-0.465875f,0.798355f,-0.381562f, +-0.320527f,0.848593f,-0.420894f, +-0.189264f,0.880141f,-0.435352f, +-0.0157309f,0.942454f,-0.333965f, +-0.0523924f,0.9528f,-0.299042f, +0.0243535f,0.924362f,-0.38074f, +0.347438f,0.877508f,-0.330555f, +0.339023f,0.92439f,-0.174834f, +0.0111821f,0.998297f,0.0572478f, +-0.344224f,0.932997f,0.105009f, +-0.433099f,0.895278f,0.104414f, +-0.282796f,0.937116f,0.204547f, +-0.130039f,0.982692f,0.131936f, +-0.0814764f,0.996291f,-0.027691f, +-0.0200688f,0.997106f,-0.0733289f, +0.118984f,0.992345f,-0.0330638f, +0.199561f,0.979885f,0.00110984f, +0.153394f,0.986654f,-0.0546216f, +0.176634f,0.980572f,-0.0853107f, +0.13548f,0.982889f,-0.124795f, +0.191838f,0.980855f,0.0334985f, +0.104996f,0.978045f,0.180009f, +0.00782433f,0.923816f,0.382758f, +-0.0895214f,0.848914f,0.520894f, +-0.239967f,0.84054f,0.485703f, +-0.280756f,0.842357f,0.460011f, +-0.207606f,0.901917f,0.378742f, +-0.122486f,0.94404f,0.306245f, +-0.244402f,0.93107f,0.270881f, +-0.292773f,0.891472f,0.345777f, +-0.276286f,0.909624f,0.310243f, +-0.213016f,0.932947f,0.290231f, +-0.0942691f,0.953854f,0.28509f, +-0.0105057f,0.953135f,0.302364f, +0.0307865f,0.936068f,0.35047f, +0.0538732f,0.955717f,0.289315f, +0.209391f,0.949668f,0.232994f, +0.403861f,0.868428f,0.287628f, +0.149382f,0.968969f,0.196936f, +-0.176548f,0.984269f,0.00674917f, +0.0687777f,0.996274f,-0.0520396f, +0.147821f,0.988716f,-0.0242998f, +-0.223164f,0.968308f,-0.112148f, +-0.295488f,0.928787f,-0.2237f, +-0.23574f,0.935973f,-0.261496f, +-0.100501f,0.963432f,-0.248392f, +0.0576299f,0.973773f,-0.220102f, +0.0436147f,0.999029f,-0.00621142f, +-0.153496f,0.982634f,0.104254f, +-0.184805f,0.972589f,0.141133f, +-0.14696f,0.984535f,0.0953571f, +-0.0211774f,0.989717f,0.141466f, +0.0758245f,0.9782f,0.193326f, +0.117048f,0.987762f,0.103083f, +0.217731f,0.97559f,-0.0285914f, +0.270726f,0.959521f,-0.0776314f, +0.230415f,0.971747f,-0.0511441f, +0.234903f,0.971865f,0.0172727f, +0.182122f,0.97948f,0.0863184f, +0.0884364f,0.988499f,0.122674f, +-0.00977715f,0.999042f,0.0426606f, +-0.0304096f,0.999492f,-0.00954367f, +0.200711f,0.957383f,0.207686f, +0.148405f,0.978101f,0.145929f, +0.14921f,0.978785f,0.140417f, +0.0273685f,0.999287f,0.0260052f, +-0.3017f,0.88706f,-0.349431f, +-0.32483f,0.824834f,-0.462746f, +-0.238736f,0.866733f,-0.437926f, +-0.174101f,0.907603f,-0.382029f, +-0.0165261f,0.968715f,-0.247625f, +0.078914f,0.949167f,-0.30472f, +0.287731f,0.926482f,-0.242571f, +0.12793f,0.981688f,-0.141147f, +-0.134026f,0.990975f,-0.00233563f, +-0.342476f,0.939327f,-0.0193419f, +-0.427311f,0.903697f,-0.027138f, +-0.353742f,0.934457f,-0.0407041f, +-0.055135f,0.997815f,0.0363915f, +0.0312575f,0.999385f,0.0158812f, +0.00264454f,0.999634f,-0.0269175f, +0.0835808f,0.996075f,-0.0291308f, +0.150499f,0.987413f,0.0486412f, +0.165157f,0.971811f,0.168246f, +0.215634f,0.960222f,0.177413f, +0.0835282f,0.988765f,0.123967f, +-0.00975779f,0.968408f,0.249181f, +-0.06977f,0.918125f,0.3901f, +-0.139283f,0.878718f,0.456569f, +-0.11373f,0.882765f,0.455842f, +-0.169944f,0.889011f,0.42518f, +-0.209287f,0.894084f,0.395996f, +-0.156853f,0.920873f,0.356917f, +-0.124966f,0.921391f,0.367997f, +-0.29021f,0.888579f,0.355255f, +-0.269725f,0.894676f,0.356094f, +-0.146199f,0.945073f,0.292342f, +-0.175209f,0.971632f,0.15885f, +-0.117718f,0.980316f,0.158504f, +-0.0825429f,0.966227f,0.244116f, +-0.0312586f,0.938703f,0.343308f, +0.145253f,0.922109f,0.358632f, +0.209296f,0.943478f,0.256992f, +0.299421f,0.901575f,0.312265f, +0.248395f,0.88619f,0.39111f, +0.0914055f,0.966416f,0.240179f, +0.127765f,0.989974f,-0.0602251f, +0.140331f,0.988333f,-0.0592086f, +-0.14269f,0.987394f,-0.0685058f, +-0.196659f,0.96924f,-0.147981f, +-0.173702f,0.951221f,-0.254961f, +-0.143754f,0.948468f,-0.282389f, +-0.0849965f,0.99069f,-0.106347f, +-0.164159f,0.984178f,0.0666661f, +-0.232036f,0.961292f,0.148586f, +-0.256871f,0.951713f,0.168109f, +-0.0692891f,0.973705f,0.217018f, +0.083167f,0.991239f,0.102607f, +0.0755656f,0.994003f,-0.07904f, +0.210733f,0.972404f,-0.100116f, +0.30249f,0.937213f,-0.173582f, +0.293071f,0.941554f,-0.166086f, +0.154342f,0.975072f,-0.159414f, +0.102764f,0.994605f,0.0141294f, +0.056079f,0.980415f,0.188792f, +0.109909f,0.955557f,0.273554f, +0.133139f,0.972499f,0.191102f, +0.0554464f,0.995429f,0.0777578f, +0.259868f,0.925249f,0.276374f, +0.196037f,0.949951f,0.243232f, +0.114869f,0.970528f,0.21185f, +0.223665f,0.947755f,0.227452f, +0.0930818f,0.995219f,-0.0295687f, +-0.269847f,0.892223f,-0.362106f, +-0.284642f,0.866853f,-0.409321f, +-0.255009f,0.880625f,-0.399336f, +-0.131932f,0.93993f,-0.314842f, +0.0677192f,0.974824f,-0.212442f, +0.187299f,0.973952f,-0.127815f, +0.0529524f,0.998138f,-0.0302806f, +-0.109006f,0.993972f,0.0117426f, +-0.296161f,0.95278f,-0.067077f, +-0.391399f,0.918205f,-0.0608803f, +-0.369652f,0.920023f,-0.130056f, +-0.175066f,0.983052f,-0.0544101f, +0.0114037f,0.997649f,0.0675687f, +-0.0112147f,0.996664f,0.0808418f, +0.0734363f,0.988721f,0.130533f, +0.0224625f,0.993745f,0.109391f, +0.0118323f,0.985875f,0.167063f, +0.164185f,0.947186f,0.275466f, +0.0854603f,0.916044f,0.391867f, +-0.130673f,0.906994f,0.400358f, +-0.128332f,0.898319f,0.420183f, +-0.0833752f,0.911617f,0.402496f, +-0.0573327f,0.932174f,0.357442f, +-0.17852f,0.926686f,0.330734f, +-0.230606f,0.897072f,0.376939f, +-0.191094f,0.893503f,0.406369f, +-0.142227f,0.886795f,0.439733f, +-0.17679f,0.896492f,0.40626f, +-0.238548f,0.945234f,0.222772f, +-0.0952672f,0.973092f,0.209801f, +-0.096256f,0.964628f,0.245412f, +-0.179685f,0.951666f,0.249087f, +-0.204503f,0.928081f,0.311197f, +-0.0772696f,0.924068f,0.374336f, +0.158946f,0.926358f,0.341463f, +0.256333f,0.910209f,0.325291f, +0.24298f,0.91134f,0.332296f, +0.258464f,0.899993f,0.351011f, +0.335956f,0.897826f,0.28468f, +0.32299f,0.94494f,0.0525965f, +0.125001f,0.99187f,-0.0238687f, +-0.121525f,0.992278f,-0.0248174f, +-0.149564f,0.988264f,-0.0310731f, +-0.0664528f,0.99755f,-0.021853f, +-0.216702f,0.971886f,-0.0920818f, +-0.313688f,0.949511f,-0.0053432f, +-0.230579f,0.964148f,0.131349f, +-0.200205f,0.977444f,0.06724f, +-0.214561f,0.975215f,-0.0540219f, +-0.0751922f,0.988525f,-0.131015f, +0.196994f,0.973692f,-0.114533f, +0.277294f,0.941009f,-0.193932f, +0.227557f,0.901482f,-0.368168f, +0.240964f,0.919471f,-0.31066f, +0.212207f,0.970864f,-0.111317f, +0.0629816f,0.997092f,0.0428958f, +-0.106678f,0.985091f,0.134967f, +-0.0538645f,0.972292f,0.227481f, +0.0800601f,0.969345f,0.232295f, +0.209708f,0.947853f,0.239995f, +0.200719f,0.957631f,0.206531f, +0.262538f,0.945755f,0.191366f, +0.219609f,0.958448f,0.182068f, +0.16942f,0.971857f,0.163679f, +0.226298f,0.968297f,0.105781f, +0.311569f,0.942438f,0.12139f, +0.0252626f,0.999298f,-0.0276703f, +-0.250271f,0.93337f,-0.257262f, +-0.253906f,0.911858f,-0.322563f, +-0.227242f,0.899531f,-0.373102f, +-0.0651757f,0.944171f,-0.322945f, +0.0757455f,0.97969f,-0.185662f, +-0.00346825f,0.999555f,-0.0296364f, +-0.101674f,0.994706f,-0.0148914f, +-0.257112f,0.961591f,-0.0961018f, +-0.383381f,0.91395f,-0.133094f, +-0.376104f,0.917884f,-0.12663f, +-0.286338f,0.956389f,-0.0577212f, +-0.0969792f,0.993405f,0.061176f, +-0.0181638f,0.982944f,0.183006f, +0.0407231f,0.989025f,0.142023f, +0.0858284f,0.987795f,0.129982f, +0.0586048f,0.994197f,0.0902062f, +0.00131743f,0.999561f,0.0296072f, +-0.0615813f,0.973472f,0.220363f, +-0.103673f,0.946783f,0.304719f, +-0.0728984f,0.963065f,0.259214f, +-0.0671535f,0.98356f,0.16763f, +-0.0415144f,0.986558f,0.158053f, +-0.226194f,0.961315f,0.157196f, +-0.322442f,0.916637f,0.236235f, +-0.20303f,0.923357f,0.32587f, +-0.141662f,0.940817f,0.307889f, +-0.0764267f,0.960304f,0.268283f, +-0.0942789f,0.977491f,0.188741f, +-0.142883f,0.973984f,0.175899f, +-0.198273f,0.947542f,0.250702f, +-0.198314f,0.931193f,0.305861f, +-0.212116f,0.938506f,0.272421f, +-0.0469422f,0.977819f,0.204126f, +0.196637f,0.969918f,0.1435f, +0.210661f,0.950426f,0.228718f, +0.210629f,0.90739f,0.363701f, +0.274296f,0.882172f,0.382799f, +0.402024f,0.855402f,0.326595f, +0.442462f,0.866019f,0.232889f, +0.128104f,0.97894f,0.158954f, +-0.10509f,0.973708f,0.202109f, +-0.168744f,0.972176f,0.162479f, +-0.102712f,0.980722f,0.166234f, +-0.117365f,0.985855f,0.119644f, +-0.348177f,0.934585f,-0.0729569f, +-0.249993f,0.967414f,-0.040164f, +-0.059218f,0.996444f,-0.0599467f, +-0.0488698f,0.975685f,-0.21366f, +-0.0228314f,0.943327f,-0.331077f, +0.144917f,0.936565f,-0.319132f, +0.332603f,0.901794f,-0.275938f, +0.285592f,0.906866f,-0.309889f, +0.0349917f,0.981145f,-0.190079f, +-0.0795345f,0.991829f,0.0997459f, +-0.0793233f,0.9451f,0.317009f, +-0.0879959f,0.940679f,0.327688f, +-0.00912821f,0.970457f,0.241099f, +0.124716f,0.982357f,0.13936f, +0.187981f,0.977561f,0.0950669f, +0.255482f,0.951122f,0.173483f, +0.297001f,0.952441f,0.0681659f, +0.265042f,0.961574f,0.0716068f, +0.186715f,0.981446f,0.0436002f, +0.255349f,0.964505f,0.0672885f, +0.267248f,0.96042f,0.078566f, +0.154901f,0.983709f,0.0912232f, +-0.0558054f,0.990723f,-0.123913f, +-0.190326f,0.930089f,-0.314182f, +-0.171804f,0.925365f,-0.337911f, +-0.124574f,0.93618f,-0.328706f, +-0.0782933f,0.960403f,-0.267387f, +-0.15298f,0.970001f,-0.188931f, +-0.0717491f,0.993745f,-0.0855706f, +-0.147047f,0.986451f,-0.0727437f, +-0.378361f,0.919377f,-0.107652f, +-0.386168f,0.917464f,-0.0955771f, +-0.364818f,0.925918f,-0.097894f, +-0.234461f,0.971639f,0.0307667f, +-0.0876095f,0.988677f,0.121826f, +0.151616f,0.984538f,0.0877402f, +0.0730881f,0.996968f,-0.0267174f, +0.0661066f,0.997404f,0.0285557f, +0.00089126f,0.998637f,0.052186f, +-0.169004f,0.978667f,0.116824f, +-0.169994f,0.972188f,0.161096f, +-0.0375438f,0.966292f,0.254695f, +0.0282607f,0.96926f,0.244409f, +0.0134123f,0.993493f,0.113096f, +-0.245106f,0.969303f,-0.0193377f, +-0.4073f,0.913294f,0.000911808f, +-0.297873f,0.952205f,0.0676567f, +-0.106293f,0.976869f,0.185552f, +-0.0629676f,0.97793f,0.199217f, +-0.110366f,0.958688f,0.262177f, +-0.181956f,0.936769f,0.298926f, +-0.212233f,0.945122f,0.248398f, +-0.195256f,0.962306f,0.189318f, +-0.105775f,0.982974f,0.150248f, +0.0268617f,0.999457f,0.0191026f, +0.158413f,0.985011f,0.068261f, +0.0517671f,0.977028f,0.206729f, +0.0576574f,0.95413f,0.293788f, +0.234396f,0.901434f,0.363971f, +0.437391f,0.816127f,0.377659f, +0.504071f,0.803908f,0.315666f, +0.133347f,0.946928f,0.292483f, +-0.151412f,0.933905f,0.323877f, +-0.120106f,0.92207f,0.367915f, +-0.00325057f,0.939171f,0.343435f, +0.0348166f,0.983178f,0.179299f, +-0.135523f,0.990774f,0.00106677f, +-0.269937f,0.929173f,-0.252528f, +-0.0598233f,0.968739f,-0.240761f, +0.0705133f,0.981516f,-0.177915f, +0.0411605f,0.966746f,-0.252403f, +0.126252f,0.944488f,-0.30332f, +0.315542f,0.911296f,-0.264523f, +0.160596f,0.976989f,-0.140362f, +-0.167382f,0.98071f,0.100946f, +-0.298691f,0.934743f,0.192454f, +-0.145935f,0.9608f,0.235724f, +-0.00307512f,0.970287f,0.241936f, +0.110563f,0.982642f,0.148964f, +0.216043f,0.97432f,0.0634533f, +0.143964f,0.986263f,0.0809867f, +0.0914437f,0.980957f,0.17135f, +0.140934f,0.985084f,-0.0987321f, +0.206841f,0.978337f,0.00859891f, +0.190086f,0.979435f,0.0676362f, +0.201515f,0.978077f,0.0525072f, +0.267937f,0.960786f,0.0714189f, +0.246755f,0.968907f,0.0182169f, +0.214715f,0.971106f,-0.104168f, +-0.0180649f,0.956568f,-0.290949f, +-0.219959f,0.899081f,-0.378512f, +-0.191729f,0.921961f,-0.336494f, +-0.106738f,0.947718f,-0.300729f, +-0.152636f,0.943663f,-0.293602f, +-0.224106f,0.947646f,-0.227472f, +-0.228203f,0.973419f,0.019469f, +-0.388401f,0.917519f,0.0854554f, +-0.336148f,0.939599f,0.0644837f, +-0.402605f,0.913568f,-0.0574625f, +-0.305232f,0.952235f,-0.00907982f, +-0.096739f,0.995183f,-0.0159156f, +0.180076f,0.982792f,0.0411394f, +0.136148f,0.986894f,0.0866302f, +0.0219341f,0.999371f,0.0278606f, +-0.0791566f,0.996134f,0.0381004f, +-0.239326f,0.960376f,0.142833f, +-0.218166f,0.951783f,0.215666f, +-0.166214f,0.94168f,0.292596f, +0.0428911f,0.92465f,0.378394f, +0.200943f,0.923885f,0.325667f, +-0.0783125f,0.985711f,0.149132f, +-0.415101f,0.909654f,-0.0148509f, +-0.366356f,0.929766f,0.0363078f, +-0.239727f,0.962799f,0.124698f, +-0.166496f,0.955565f,0.243259f, +-0.200219f,0.921854f,0.331809f, +-0.112297f,0.932828f,0.342375f, +-0.106223f,0.957221f,0.269154f, +-0.127872f,0.96503f,0.228835f, +-0.0138049f,0.984551f,0.174552f, +0.0256733f,0.993774f,0.108417f, +0.00728748f,0.973829f,0.227164f, +-0.00741294f,0.956693f,0.291004f, +0.0683597f,0.974464f,0.213887f, +0.177941f,0.966015f,0.187489f, +0.424978f,0.876377f,0.226619f, +0.505816f,0.827485f,0.243758f, +0.166361f,0.911198f,0.376885f, +-0.17476f,0.913668f,0.366973f, +-0.176728f,0.923512f,0.340431f, +0.0722139f,0.943797f,0.322541f, +0.177366f,0.957288f,0.228344f, +0.0913959f,0.986484f,0.136004f, +-0.0297265f,0.993047f,-0.113903f, +-0.0869422f,0.951911f,-0.293781f, +-0.0450316f,0.952406f,-0.301489f, +0.143119f,0.964298f,-0.222813f, +0.165675f,0.921893f,-0.350237f, +0.164354f,0.949667f,-0.266682f, +-0.039757f,0.998354f,0.0413462f, +-0.291683f,0.947651f,0.12992f, +-0.239728f,0.968947f,0.0605947f, +-0.107127f,0.994229f,0.00574708f, +-0.00468879f,0.997776f,-0.0664969f, +0.179786f,0.983119f,-0.033983f, +0.200209f,0.979349f,-0.0281487f, +0.0601426f,0.997956f,0.0216006f, +-0.0759803f,0.997037f,0.0120005f, +0.14599f,0.98347f,-0.107112f, +0.111543f,0.987674f,-0.109808f, +0.157618f,0.987042f,-0.0300797f, +0.250909f,0.967637f,-0.026879f, +0.281043f,0.956928f,-0.0728269f, +0.296885f,0.954758f,-0.0172396f, +0.276747f,0.960894f,-0.00969537f, +0.102049f,0.992961f,-0.0601211f, +-0.130111f,0.972079f,-0.195279f, +-0.17254f,0.923261f,-0.343248f, +-0.125309f,0.912244f,-0.390012f, +-0.211743f,0.924189f,-0.317868f, +-0.376287f,0.901788f,-0.212569f, +-0.427638f,0.901509f,-0.0663888f, +-0.389415f,0.920624f,0.0283935f, +-0.297925f,0.953877f,0.0368632f, +-0.273734f,0.961504f,0.0240644f, +-0.334113f,0.936286f,-0.108341f, +-0.109536f,0.993721f,-0.0228029f, +0.0288145f,0.999546f,0.00876748f, +0.119784f,0.984043f,0.131571f, +0.0511538f,0.994284f,0.0937163f, +-0.0752276f,0.983313f,0.165639f, +-0.293078f,0.946365f,0.136011f, +-0.332793f,0.935954f,0.115063f, +-0.225106f,0.941939f,0.249154f, +0.0114661f,0.958888f,0.283552f, +0.24485f,0.921506f,0.301455f, +0.100987f,0.953885f,0.282675f, +-0.340266f,0.932035f,0.124616f, +-0.415762f,0.898895f,0.138312f, +-0.325966f,0.925955f,0.190664f, +-0.250966f,0.918836f,0.304559f, +-0.221816f,0.898675f,0.378392f, +-0.0852583f,0.899614f,0.428282f, +-0.0998073f,0.904564f,0.41449f, +-0.102816f,0.885513f,0.453096f, +0.0414724f,0.91382f,0.403996f, +-0.0128006f,0.939036f,0.343581f, +-0.0641104f,0.924175f,0.376551f, +0.0655361f,0.926269f,0.37112f, +0.187467f,0.942186f,0.277743f, +0.21985f,0.965692f,0.138218f, +0.3812f,0.921864f,0.0696633f, +0.433954f,0.878909f,0.197998f, +0.0643484f,0.944154f,0.32316f, +-0.162002f,0.923385f,0.348016f, +-0.0466746f,0.93461f,0.352597f, +0.113297f,0.96975f,0.216212f, +0.268791f,0.938715f,0.215791f, +0.199257f,0.972974f,0.116695f, +0.13591f,0.990721f,-0.000598755f, +0.098836f,0.989317f,-0.107165f, +0.00840194f,0.94937f,-0.314049f, +0.0977197f,0.93606f,-0.337997f, +0.228369f,0.952655f,-0.20074f, +-0.102319f,0.98537f,-0.136295f, +-0.210478f,0.975126f,0.0694824f, +-0.226245f,0.97389f,-0.0187694f, +-0.184535f,0.981701f,-0.0470082f, +-0.0356904f,0.995184f,-0.0912977f, +0.0448449f,0.980059f,-0.193583f, +0.0871766f,0.981936f,-0.167935f, +0.149691f,0.986438f,-0.0673319f, +0.081336f,0.996451f,-0.021693f, +0.0320348f,0.999323f,-0.0181162f, +0.0913657f,0.979354f,-0.180329f, +0.100696f,0.986931f,-0.125808f, +0.108832f,0.988438f,-0.105573f, +0.287509f,0.953f,-0.0955498f, +0.243655f,0.954139f,-0.173927f, +0.160509f,0.983073f,-0.0883436f, +0.264497f,0.963724f,0.0357424f, +0.162998f,0.986545f,0.0127154f, +0.0143391f,0.999851f,0.00965394f, +-0.0125406f,0.999093f,-0.0406807f, +-0.106874f,0.984584f,-0.138462f, +-0.285824f,0.938351f,-0.194429f, +-0.419998f,0.877928f,-0.22988f, +-0.451562f,0.860313f,-0.236545f, +-0.434075f,0.875052f,-0.214154f, +-0.338822f,0.927615f,-0.157258f, +-0.245036f,0.962096f,-0.119701f, +-0.344114f,0.932339f,-0.111035f, +-0.226404f,0.972006f,0.0628119f, +0.0419787f,0.991974f,0.119273f, +0.128473f,0.991295f,0.0288037f, +-0.0257017f,0.999564f,0.0145347f, +-0.185301f,0.952066f,0.243378f, +-0.184541f,0.936895f,0.29694f, +-0.273419f,0.950852f,0.145334f, +-0.319783f,0.945196f,0.0659039f, +-0.035432f,0.98966f,0.138987f, +0.220222f,0.955124f,0.19809f, +0.125192f,0.96286f,0.239224f, +-0.256002f,0.939458f,0.227776f, +-0.448892f,0.878586f,0.163043f, +-0.385115f,0.893165f,0.232256f, +-0.361248f,0.871706f,0.331103f, +-0.291851f,0.846516f,0.445235f, +-0.17348f,0.85884f,0.481973f, +-0.107775f,0.841326f,0.529675f, +-0.0921307f,0.850827f,0.517306f, +0.0950699f,0.836893f,0.539048f, +0.0822562f,0.850572f,0.519385f, +0.00749303f,0.916802f,0.399272f, +0.0761143f,0.966912f,0.243491f, +0.269493f,0.937399f,0.220582f, +0.37073f,0.916186f,0.152194f, +0.358083f,0.929944f,0.083549f, +0.335187f,0.907961f,0.251509f, +0.0578141f,0.947361f,0.314904f, +-0.166707f,0.957873f,0.233855f, +-0.0184246f,0.983369f,0.180682f, +0.167068f,0.976917f,0.13312f, +0.286534f,0.942354f,0.172822f, +0.301062f,0.945554f,0.123648f, +0.228175f,0.972518f,0.0463188f, +0.216797f,0.97484f,-0.0518194f, +0.199106f,0.962895f,-0.18218f, +0.00394531f,0.962307f,-0.271937f, +-0.0105699f,0.99745f,-0.0705888f, +-0.131705f,0.985651f,0.105578f, +-0.19725f,0.980353f,0.00065076f, +-0.141436f,0.988723f,-0.0492296f, +-0.163841f,0.979948f,-0.113394f, +0.0189882f,0.981225f,-0.191928f, +0.0882705f,0.978772f,-0.18497f, +0.0393937f,0.981447f,-0.187645f, +0.0729287f,0.986122f,-0.149146f, +0.0148824f,0.998969f,-0.0428982f, +-0.0177962f,0.999449f,0.0279995f, +-0.0162323f,0.963189f,-0.268333f, +0.00641467f,0.976357f,-0.216067f, +0.107749f,0.98057f,-0.16393f, +0.293413f,0.939289f,-0.177892f, +0.308304f,0.934826f,-0.17621f, +0.101903f,0.952869f,-0.285755f, +0.182917f,0.946528f,-0.265755f, +0.146405f,0.977668f,-0.15077f, +-0.0629734f,0.995858f,-0.0655825f, +-0.0448201f,0.998977f,-0.00597126f, +-0.0400505f,0.999191f,-0.00375744f, +-0.153158f,0.98627f,-0.0617534f, +-0.285484f,0.92871f,-0.236637f, +-0.448842f,0.826713f,-0.339243f, +-0.479202f,0.840256f,-0.253646f, +-0.347296f,0.912974f,-0.214157f, +-0.288381f,0.931416f,-0.222037f, +-0.393139f,0.905395f,-0.160316f, +-0.362299f,0.919254f,-0.153982f, +0.042344f,0.998556f,-0.0330675f, +0.205011f,0.978411f,0.0261187f, +-0.127573f,0.99058f,0.0497635f, +-0.371574f,0.908811f,0.189723f, +-0.216831f,0.928294f,0.302084f, +-0.0703165f,0.93644f,0.343708f, +-0.232099f,0.969924f,0.0733245f, +-0.112472f,0.99344f,-0.0206566f, +0.137846f,0.985164f,0.102232f, +0.0558694f,0.966778f,0.249437f, +-0.236804f,0.911959f,0.335045f, +-0.429918f,0.856338f,0.286105f, +-0.441526f,0.844766f,0.302366f, +-0.455345f,0.82665f,0.330622f, +-0.361376f,0.843549f,0.397281f, +-0.152799f,0.875871f,0.457714f, +-0.118894f,0.891156f,0.437842f, +-0.0896442f,0.897342f,0.432135f, +0.0157836f,0.897193f,0.441356f, +0.112602f,0.854856f,0.5065f, +0.219938f,0.859901f,0.460648f, +0.288065f,0.92641f,0.242451f, +0.293811f,0.955367f,0.0308066f, +0.390529f,0.919592f,0.0428713f, +0.271277f,0.959279f,0.0786938f, +0.217133f,0.949907f,0.22479f, +0.0884504f,0.963513f,0.252624f, +-0.0236259f,0.986232f,0.163669f, +0.0800779f,0.996646f,0.0168362f, +0.165418f,0.984838f,-0.0522657f, +0.249596f,0.968284f,-0.0113122f, +0.338274f,0.940962f,-0.0126639f, +0.305431f,0.950632f,-0.0548703f, +0.294152f,0.946987f,-0.12919f, +0.225417f,0.970184f,-0.0890507f, +-0.00713906f,0.99978f,0.0197001f, +-0.176932f,0.984214f,-0.00420403f, +-0.111846f,0.993652f,0.0120569f, +-0.1391f,0.984895f,-0.103119f, +-0.088794f,0.987668f,-0.128949f, +-0.0465185f,0.96883f,-0.243321f, +0.0250763f,0.955082f,-0.295277f, +0.0363238f,0.977208f,-0.209152f, +0.0515148f,0.981849f,-0.182534f, +-0.0181f,0.986039f,-0.165529f, +-0.1292f,0.991547f,-0.0118974f, +-0.123925f,0.986172f,0.110035f, +0.0445182f,0.949745f,-0.309843f, +-0.00147152f,0.93224f,-0.361838f, +0.114309f,0.919114f,-0.377045f, +0.249456f,0.882365f,-0.399004f, +0.318339f,0.895336f,-0.311503f, +0.245085f,0.904168f,-0.349877f, +0.0939131f,0.907167f,-0.410156f, +-0.0302879f,0.963667f,-0.265383f, +-0.13844f,0.974516f,-0.176503f, +-0.0411687f,0.989896f,-0.135687f, +-0.00628724f,0.990542f,-0.137063f, +-0.112489f,0.976976f,-0.181283f, +-0.1315f,0.967086f,-0.217836f, +-0.376506f,0.872387f,-0.311743f, +-0.531305f,0.793042f,-0.297992f, +-0.39351f,0.883689f,-0.253462f, +-0.336847f,0.927504f,-0.162083f, +-0.393317f,0.917094f,-0.0651222f, +-0.321501f,0.93797f,-0.129808f, +-0.135804f,0.972419f,-0.189625f, +0.0526632f,0.998612f,0.00112608f, +-0.194024f,0.972777f,0.126724f, +-0.436845f,0.883669f,0.168215f, +-0.311688f,0.924669f,0.218719f, +-0.0696464f,0.953993f,0.291628f, +0.0409792f,0.956788f,0.287884f, +-0.0764775f,0.990645f,0.113025f, +-0.0364568f,0.989186f,0.142066f, +-0.121833f,0.946798f,0.297877f, +-0.315082f,0.850341f,0.421476f, +-0.377714f,0.797842f,0.469873f, +-0.420842f,0.786479f,0.452043f, +-0.397492f,0.78965f,0.467389f, +-0.380055f,0.83336f,0.401334f, +-0.183142f,0.896787f,0.402781f, +-0.0888282f,0.916137f,0.3909f, +-0.0940934f,0.935116f,0.34162f, +0.00386799f,0.937503f,0.347956f, +0.10018f,0.944394f,0.313183f, +0.280679f,0.93056f,0.235113f, +0.465087f,0.85876f,0.215002f, +0.41466f,0.904302f,0.101461f, +0.364139f,0.929581f,0.0572809f, +0.242065f,0.968602f,0.0566915f, +0.117842f,0.992149f,0.0418746f, +0.148716f,0.982681f,0.110551f, +0.0959266f,0.995185f,0.0201233f, +0.176327f,0.980433f,-0.0875236f, +0.210189f,0.965141f,-0.155959f, +0.226725f,0.946611f,-0.229181f, +0.330781f,0.920607f,-0.207526f, +0.365923f,0.916599f,-0.161081f, +0.298516f,0.923753f,-0.239936f, +0.0221976f,0.976238f,-0.215559f, +-0.104515f,0.994469f,-0.0104162f, +-0.0427336f,0.998984f,-0.0143091f, +-0.0839971f,0.989572f,-0.117013f, +-0.00725244f,0.993108f,-0.116977f, +-0.0399839f,0.966361f,-0.254064f, +0.00504893f,0.980798f,-0.194961f, +-0.018473f,0.987693f,-0.155309f, +-0.0253738f,0.987423f,-0.15605f, +0.000452807f,0.989468f,-0.144748f, +-0.0811148f,0.995994f,-0.0376225f, +-0.286969f,0.957515f,0.0285449f, +-0.27524f,0.951495f,0.137481f, +0.163018f,0.971572f,-0.171676f, +0.122581f,0.955248f,-0.269212f, +0.130974f,0.917919f,-0.374527f, +0.258812f,0.917892f,-0.300816f, +0.268244f,0.908354f,-0.320839f, +0.223034f,0.911459f,-0.345686f, +0.0389184f,0.957275f,-0.28655f, +-0.140597f,0.964524f,-0.223439f, +-0.145862f,0.970122f,-0.193875f, +-0.104111f,0.974098f,-0.200733f, +-0.0208986f,0.992723f,-0.118595f, +-0.0701237f,0.994147f,-0.08218f, +-0.122604f,0.99062f,-0.0603304f, +-0.259222f,0.963912f,-0.0606481f, +-0.533518f,0.797325f,-0.282189f, +-0.48726f,0.821939f,-0.294948f, +-0.445665f,0.877532f,-0.176975f, +-0.446224f,0.888631f,-0.105925f, +-0.296073f,0.952805f,-0.0671049f, +-0.124475f,0.991773f,-0.0298685f, +-0.112069f,0.99368f,-0.00632266f, +-0.24484f,0.957295f,0.15375f, +-0.472578f,0.869701f,0.142444f, +-0.348902f,0.914252f,0.205937f, +-0.110311f,0.945787f,0.30548f, +-0.00134709f,0.941519f,0.336957f, +0.0293716f,0.928574f,0.369983f, +-0.116225f,0.946895f,0.299803f, +-0.223618f,0.889099f,0.399372f, +-0.413824f,0.817577f,0.400396f, +-0.452277f,0.775981f,0.439658f, +-0.398113f,0.749968f,0.528257f, +-0.374899f,0.784234f,0.494397f, +-0.25264f,0.860337f,0.442712f, +-0.127446f,0.920564f,0.369215f, +-0.018556f,0.935495f,0.352851f, +-0.0323754f,0.965116f,0.259814f, +0.0357851f,0.98547f,0.166039f, +0.195904f,0.976812f,0.0863732f, +0.361612f,0.932271f,0.0103395f, +0.440593f,0.897705f,0.00204446f, +0.433278f,0.895277f,0.103679f, +0.385805f,0.912456f,0.136304f, +0.326244f,0.9426f,0.0712044f, +0.139247f,0.987833f,-0.0692571f, +0.107504f,0.992792f,-0.0529845f, +0.186477f,0.981836f,-0.0349818f, +0.2261f,0.969793f,-0.0915407f, +0.319918f,0.94368f,-0.0843796f, +0.284455f,0.935881f,-0.207877f, +0.26738f,0.950319f,-0.159379f, +0.326413f,0.941309f,-0.085975f, +0.340028f,0.93811f,-0.0657985f, +0.0548427f,0.991972f,-0.113944f, +-0.195067f,0.950504f,-0.241849f, +-0.0282147f,0.982936f,-0.181769f, +-0.0838232f,0.97875f,-0.187144f, +0.0287357f,0.988886f,-0.145871f, +0.0192345f,0.984318f,-0.175351f, +-0.131262f,0.971109f,-0.199292f, +-0.0357158f,0.988874f,-0.144408f, +0.0171216f,0.989641f,-0.142542f, +-0.0610371f,0.990627f,-0.122202f, +-0.174272f,0.984646f,-0.0100664f, +-0.321779f,0.946758f,0.0104107f, +-0.391721f,0.920071f,-0.0049163f, +0.251962f,0.967049f,0.0364793f, +0.286588f,0.95799f,-0.0110494f, +0.190653f,0.96361f,-0.187371f, +0.192921f,0.95146f,-0.239803f, +0.313234f,0.932132f,-0.181696f, +0.220402f,0.968379f,-0.116899f, +0.0241557f,0.995754f,-0.0888337f, +-0.173138f,0.969731f,-0.172177f, +-0.148056f,0.974915f,-0.166191f, +-0.121802f,0.976444f,-0.178104f, +-0.134617f,0.985638f,-0.10196f, +-0.12881f,0.990748f,0.0427476f, +-0.193234f,0.979772f,0.0520324f, +-0.169584f,0.981577f,0.0880205f, +-0.37404f,0.925821f,-0.0543154f, +-0.520547f,0.83989f,-0.153672f, +-0.499517f,0.851003f,-0.162103f, +-0.4353f,0.881523f,-0.182841f, +-0.371568f,0.902946f,-0.21593f, +-0.165948f,0.980792f,-0.10251f, +-0.208618f,0.975931f,-0.0635357f, +-0.355123f,0.932394f,0.0673039f, +-0.461506f,0.884901f,0.0629418f, +-0.443442f,0.893747f,0.0676439f, +-0.18907f,0.971969f,0.139742f, +-0.0546977f,0.978989f,0.19644f, +0.0244551f,0.950588f,0.309492f, +-0.115369f,0.932748f,0.341572f, +-0.31704f,0.862788f,0.393805f, +-0.382907f,0.826411f,0.412829f, +-0.514077f,0.784716f,0.346333f, +-0.482563f,0.790781f,0.37656f, +-0.301253f,0.838125f,0.454745f, +-0.149029f,0.885064f,0.440966f, +-0.0699981f,0.93986f,0.33431f, +0.00541731f,0.96209f,0.272677f, +0.0875381f,0.972016f,0.217994f, +0.185287f,0.977612f,0.0997159f, +0.257792f,0.964794f,-0.0521163f, +0.377486f,0.923846f,-0.0633437f, +0.414459f,0.907288f,-0.071082f, +0.347034f,0.936287f,-0.0541691f, +0.366281f,0.930406f,0.0134975f, +0.42839f,0.903092f,0.0301138f, +0.236883f,0.966501f,-0.0988031f, +0.0750179f,0.986987f,-0.142226f, +0.187793f,0.976018f,-0.110108f, +0.233114f,0.960011f,-0.155038f, +0.295131f,0.944107f,-0.146833f, +0.293935f,0.952937f,-0.0742579f, +0.206131f,0.978459f,-0.0112805f, +0.26541f,0.963541f,0.0338617f, +0.315062f,0.940538f,0.126983f, +0.200639f,0.96888f,0.144968f, +-0.0482349f,0.996749f,-0.0645292f, +-0.0829471f,0.973987f,-0.210875f, +-0.0395681f,0.974449f,-0.221097f, +-0.0327152f,0.953444f,-0.299791f, +0.0198675f,0.970814f,-0.23901f, +-0.0300308f,0.967142f,-0.252456f, +-0.0212823f,0.929856f,-0.367308f, +-0.0806959f,0.938686f,-0.335198f, +-0.165388f,0.976093f,-0.141032f, +-0.248602f,0.968455f,-0.0171025f, +-0.306518f,0.951371f,0.0306604f, +-0.345042f,0.93733f,0.04856f, +0.223548f,0.968386f,-0.110699f, +0.301936f,0.947319f,-0.106873f, +0.333496f,0.936283f,-0.110248f, +0.267715f,0.952143f,-0.147486f, +0.160925f,0.980864f,-0.109589f, +0.106924f,0.990465f,0.086874f, +0.0634847f,0.989163f,0.132389f, +-0.00868593f,0.99995f,-0.00503069f, +-0.137697f,0.961899f,-0.236198f, +-0.140914f,0.964191f,-0.224676f, +-0.263955f,0.951239f,-0.159597f, +-0.23775f,0.971227f,-0.0138849f, +-0.148246f,0.985689f,0.0802536f, +-0.176705f,0.981995f,0.0667941f, +-0.283636f,0.956796f,0.0639697f, +-0.481368f,0.872896f,-0.0796102f, +-0.48359f,0.86775f,-0.114673f, +-0.410361f,0.90546f,-0.10838f, +-0.368916f,0.919839f,-0.133408f, +-0.290849f,0.948818f,-0.123086f, +-0.265473f,0.964116f,-0.001833f, +-0.375668f,0.926391f,0.025952f, +-0.457607f,0.88747f,-0.0547004f, +-0.428989f,0.902388f,-0.0407983f, +-0.246051f,0.968578f,-0.0362744f, +-0.121016f,0.990282f,0.0685327f, +-0.158606f,0.977484f,0.139173f, +-0.181659f,0.932387f,0.312498f, +-0.374645f,0.868516f,0.324533f, +-0.427131f,0.84162f,0.330508f, +-0.473189f,0.797198f,0.374923f, +-0.486417f,0.800363f,0.350452f, +-0.401778f,0.85438f,0.329557f, +-0.142919f,0.913903f,0.379941f, +0.0660554f,0.918312f,0.390308f, +0.107243f,0.947465f,0.301346f, +0.120927f,0.966132f,0.227959f, +0.280478f,0.92581f,0.253394f, +0.365712f,0.921405f,0.131406f, +0.413772f,0.910147f,-0.0206163f, +0.410674f,0.90493f,-0.111572f, +0.355567f,0.932765f,-0.0593443f, +0.345425f,0.933621f,-0.0950402f, +0.397628f,0.912297f,-0.0980078f, +0.290063f,0.956994f,0.00506036f, +0.106586f,0.994174f,-0.016042f, +0.184529f,0.978373f,-0.093465f, +0.32595f,0.937225f,-0.12396f, +0.234333f,0.947332f,-0.218287f, +0.205568f,0.971289f,-0.119751f, +0.183661f,0.977533f,-0.103434f, +0.18646f,0.974485f,-0.124944f, +0.228632f,0.97345f,-0.0111031f, +0.2372f,0.970015f,0.0529807f, +0.150741f,0.988413f,-0.0177775f, +0.0529111f,0.986113f,-0.15742f, +0.0129012f,0.976239f,-0.216311f, +0.0638914f,0.966774f,-0.247521f, +-0.013106f,0.949224f,-0.314329f, +0.00301657f,0.947335f,-0.320229f, +0.0158116f,0.945699f,-0.32466f, +-0.206362f,0.955554f,-0.21055f, +-0.363868f,0.929813f,-0.0551994f, +-0.322459f,0.943841f,0.0720059f, +-0.369143f,0.923823f,0.101411f, +-0.383217f,0.903675f,0.191093f, +0.316947f,0.930379f,-0.184227f, +0.292606f,0.932053f,-0.213681f, +0.281637f,0.95325f,-0.109518f, +0.181192f,0.981727f,-0.0581435f, +0.0846872f,0.996407f,0.000962506f, +-0.00109762f,0.999999f,0.000234158f, +0.0777708f,0.996176f,0.0398008f, +0.205791f,0.978243f,0.0262708f, +0.0568816f,0.985436f,-0.160253f, +-0.183235f,0.956309f,-0.227811f, +-0.306851f,0.928821f,-0.207686f, +-0.348537f,0.918038f,-0.189017f, +-0.243342f,0.965099f,-0.0967916f, +-0.232072f,0.972378f,-0.0249578f, +-0.190489f,0.981246f,0.0294989f, +-0.361119f,0.921084f,-0.145596f, +-0.509056f,0.842731f,-0.175118f, +-0.463553f,0.883903f,-0.0619248f, +-0.339892f,0.940435f,0.00741701f, +-0.334839f,0.939566f,-0.0714062f, +-0.350156f,0.936419f,-0.0225887f, +-0.347741f,0.937357f,0.020947f, +-0.370099f,0.928938f,-0.0100614f, +-0.438593f,0.892875f,-0.102033f, +-0.372504f,0.925425f,-0.0694955f, +-0.205666f,0.969919f,0.130228f, +-0.228734f,0.96522f,0.126612f, +-0.319826f,0.92691f,0.196338f, +-0.371568f,0.883063f,0.286595f, +-0.42486f,0.867995f,0.257059f, +-0.575514f,0.802019f,0.159839f, +-0.477155f,0.843037f,0.248216f, +-0.322215f,0.91617f,0.238347f, +-0.15776f,0.967147f,0.199344f, +0.0563134f,0.972277f,0.226949f, +0.189774f,0.959109f,0.209989f, +0.114773f,0.983426f,0.140357f, +0.195319f,0.960799f,0.196765f, +0.466014f,0.846607f,0.257076f, +0.551779f,0.823036f,0.13473f, +0.451922f,0.891695f,-0.0254353f, +0.295217f,0.951228f,-0.0895088f, +0.39575f,0.916754f,-0.0542532f, +0.335629f,0.937827f,-0.0885088f, +0.163272f,0.984979f,0.0561951f, +0.175225f,0.975709f,0.131485f, +0.276736f,0.960943f,0.00255915f, +0.374077f,0.92611f,-0.0488528f, +0.257806f,0.961501f,-0.0951409f, +0.210674f,0.973483f,-0.0891523f, +0.210996f,0.9611f,-0.178234f, +0.230566f,0.953272f,-0.195223f, +0.113631f,0.949966f,-0.290949f, +0.210906f,0.960561f,-0.181223f, +0.197018f,0.968285f,-0.153646f, +0.117662f,0.979392f,-0.164157f, +0.00452083f,0.974487f,-0.224398f, +0.0685234f,0.976453f,-0.20456f, +0.0486196f,0.979817f,-0.193895f, +-0.041249f,0.985341f,-0.165533f, +-0.0536621f,0.998462f,0.0138937f, +-0.34438f,0.936413f,0.0673216f, +-0.441342f,0.892502f,0.0930463f, +-0.35428f,0.929013f,0.106864f, +-0.394607f,0.91136f,0.117083f, +-0.495153f,0.861045f,0.115868f, +0.317163f,0.930357f,-0.183965f, +0.258032f,0.948579f,-0.183348f, +0.18786f,0.965135f,-0.182274f, +0.168177f,0.970722f,-0.171508f, +0.130487f,0.977884f,-0.163448f, +0.0391868f,0.976408f,-0.212349f, +0.0535243f,0.973465f,-0.222489f, +0.187797f,0.962281f,-0.196843f, +0.12136f,0.981658f,-0.147035f, +-0.157459f,0.973185f,-0.167681f, +-0.281843f,0.941023f,-0.18719f, +-0.339259f,0.910185f,-0.237625f, +-0.312535f,0.920718f,-0.233666f, +-0.266508f,0.952365f,-0.148237f, +-0.190534f,0.974186f,-0.121073f, +-0.276015f,0.959165f,-0.0617859f, +-0.523368f,0.852103f,0.00254573f, +-0.538f,0.84284f,-0.0133122f, +-0.352764f,0.935613f,-0.0136594f, +-0.269435f,0.962844f,-0.0183539f, +-0.350798f,0.93502f,-0.0517468f, +-0.373067f,0.922044f,-0.103225f, +-0.354323f,0.929911f,-0.0985928f, +-0.409705f,0.907488f,-0.0927797f, +-0.42852f,0.900791f,-0.070324f, +-0.329659f,0.944032f,-0.0113329f, +-0.243515f,0.962301f,0.121152f, +-0.341781f,0.918017f,0.201073f, +-0.462572f,0.875527f,0.139571f, +-0.350168f,0.914262f,0.203733f, +-0.49611f,0.864935f,0.0759072f, +-0.527565f,0.849514f,0.000485091f, +-0.337106f,0.940759f,0.0364912f, +-0.159402f,0.986691f,0.0321325f, +0.0661572f,0.997809f,-0.000201698f, +0.185343f,0.982618f,-0.0104608f, +0.145499f,0.981994f,0.120491f, +0.134704f,0.982549f,0.128264f, +0.406275f,0.89759f,0.17109f, +0.586902f,0.779785f,0.217901f, +0.565709f,0.807524f,0.166967f, +0.384632f,0.92307f,-3.36604e-005f, +0.35623f,0.932256f,-0.0632309f, +0.323525f,0.94617f,0.00968274f, +0.0775419f,0.995759f,-0.0495083f, +0.170196f,0.984289f,-0.0470022f, +0.351353f,0.935822f,-0.0280704f, +0.38341f,0.923157f,-0.0278874f, +0.285688f,0.957776f,-0.0323514f, +0.254076f,0.961785f,-0.102057f, +0.271137f,0.936424f,-0.222698f, +0.261266f,0.933845f,-0.24428f, +0.199017f,0.946563f,-0.253793f, +0.0763778f,0.960008f,-0.269355f, +0.131471f,0.985485f,-0.107402f, +0.160318f,0.984539f,-0.0705758f, +0.0961684f,0.977977f,-0.185235f, +0.0245162f,0.963631f,-0.26611f, +-0.0125968f,0.989853f,-0.141538f, +-0.234149f,0.972198f,0.00219358f, +-0.224015f,0.949544f,0.219506f, +-0.294091f,0.928539f,0.226551f, +-0.388903f,0.912184f,0.129128f, +-0.352208f,0.9324f,0.0811158f, +-0.3962f,0.915032f,0.0757807f, +-0.491066f,0.869445f,0.0540404f, +0.157697f,0.961233f,-0.226193f, +0.272083f,0.946677f,-0.172551f, +0.25297f,0.931319f,-0.262015f, +0.179666f,0.941632f,-0.284691f, +0.0998509f,0.952676f,-0.287122f, +0.0337305f,0.95661f,-0.289412f, +0.0669213f,0.956372f,-0.284383f, +0.111493f,0.948222f,-0.297395f, +0.109434f,0.973643f,-0.200107f, +-0.146896f,0.95648f,-0.252126f, +-0.266533f,0.937028f,-0.225695f, +-0.287184f,0.932451f,-0.219226f, +-0.333493f,0.906758f,-0.258015f, +-0.32756f,0.915563f,-0.233343f, +-0.294553f,0.94475f,-0.143827f, +-0.391872f,0.91893f,0.0447686f, +-0.558682f,0.823628f,0.0975275f, +-0.441987f,0.895769f,0.0473795f, +-0.31507f,0.944961f,-0.0882052f, +-0.286026f,0.950757f,-0.119373f, +-0.300544f,0.946699f,-0.115905f, +-0.336723f,0.926445f,-0.168278f, +-0.353572f,0.929204f,-0.107543f, +-0.453641f,0.88906f,-0.0615028f, +-0.438343f,0.898681f,0.0151213f, +-0.388424f,0.921475f,0.00321393f, +-0.409039f,0.909757f,0.0709235f, +-0.363684f,0.905932f,0.216843f, +-0.363969f,0.919331f,0.149522f, +-0.393196f,0.918247f,0.0470974f, +-0.399628f,0.911703f,0.0953624f, +-0.51262f,0.855967f,-0.0673815f, +-0.335242f,0.936382f,-0.103929f, +-0.0973696f,0.981557f,-0.164516f, +0.067792f,0.980923f,-0.182192f, +0.0872383f,0.996018f,-0.0183907f, +-0.00523703f,0.995218f,0.0975357f, +0.128581f,0.983098f,0.130327f, +0.373617f,0.921384f,0.107058f, +0.560261f,0.820373f,0.114439f, +0.627317f,0.771722f,0.104494f, +0.477878f,0.875076f,0.0766505f, +0.339671f,0.937101f,0.080413f, +0.338185f,0.931593f,0.133286f, +0.241006f,0.969638f,0.0414564f, +0.184566f,0.96984f,-0.159206f, +0.299844f,0.937156f,-0.178416f, +0.33645f,0.93097f,-0.14176f, +0.33978f,0.935566f,-0.0962638f, +0.338458f,0.922961f,-0.183273f, +0.376116f,0.905613f,-0.195964f, +0.229101f,0.942068f,-0.244989f, +0.179681f,0.964126f,-0.195387f, +0.0309568f,0.968834f,-0.245768f, +0.00573259f,0.975463f,-0.220088f, +0.156849f,0.977783f,-0.139061f, +0.21782f,0.972525f,-0.0821593f, +0.0218621f,0.99451f,-0.102332f, +-0.198564f,0.980065f,-0.00663249f, +-0.36267f,0.923836f,0.122463f, +-0.30382f,0.935102f,0.182419f, +-0.225949f,0.949998f,0.215522f, +-0.338005f,0.935768f,0.100459f, +-0.329518f,0.942604f,0.0540005f, +-0.353044f,0.9356f,0.00366832f, +-0.46383f,0.880375f,-0.0990046f, +0.265153f,0.963251f,-0.0429098f, +0.322279f,0.944597f,-0.0622248f, +0.315505f,0.945542f,-0.0800488f, +0.163962f,0.974749f,-0.151597f, +0.137337f,0.972433f,-0.188448f, +0.0704319f,0.957822f,-0.278599f, +0.0704671f,0.945462f,-0.318019f, +0.0908986f,0.948607f,-0.303121f, +0.035224f,0.968727f,-0.245614f, +-0.0832465f,0.983302f,-0.161824f, +-0.246429f,0.938519f,-0.241773f, +-0.316726f,0.889326f,-0.329823f, +-0.284897f,0.918994f,-0.272549f, +-0.362325f,0.886545f,-0.287677f, +-0.440048f,0.874713f,-0.203063f, +-0.497142f,0.865956f,-0.0544999f, +-0.523445f,0.849121f,-0.0707108f, +-0.401725f,0.907593f,-0.122034f, +-0.239401f,0.964528f,-0.111235f, +-0.233733f,0.958501f,-0.163231f, +-0.252964f,0.932836f,-0.256566f, +-0.367645f,0.889692f,-0.270713f, +-0.454692f,0.878935f,-0.143978f, +-0.492544f,0.866924f,-0.0764391f, +-0.481959f,0.875013f,-0.0454739f, +-0.427088f,0.903155f,0.0436767f, +-0.414523f,0.900313f,0.132691f, +-0.445145f,0.893064f,0.0654368f, +-0.272596f,0.94477f,0.181937f, +-0.346295f,0.936658f,0.0524542f, +-0.387211f,0.921676f,-0.0241059f, +-0.412405f,0.90305f,-0.120098f, +-0.307707f,0.940243f,-0.145806f, +-0.0608418f,0.995582f,-0.0715164f, +-0.0645131f,0.997917f,-0.000435129f, +-0.102008f,0.988043f,0.115607f, +0.0143588f,0.992143f,0.12428f, +0.177967f,0.984035f,-0.00139713f, +0.41001f,0.908001f,-0.0861781f, +0.552955f,0.819416f,-0.150989f, +0.604866f,0.793986f,-0.061019f, +0.412532f,0.907382f,0.080473f, +0.292095f,0.937176f,0.190737f, +0.30791f,0.927063f,0.213882f, +0.344775f,0.913992f,0.21389f, +0.356481f,0.927786f,0.110156f, +0.364153f,0.931072f,-0.0223179f, +0.345291f,0.930006f,-0.125944f, +0.351321f,0.913987f,-0.20298f, +0.3587f,0.898336f,-0.253627f, +0.30452f,0.930923f,-0.201617f, +0.2074f,0.975489f,-0.0735288f, +0.18932f,0.981882f,-0.00809888f, +0.163933f,0.983471f,-0.0768774f, +0.0155138f,0.975385f,-0.219964f, +0.0271837f,0.983796f,-0.177221f, +0.116676f,0.992898f,-0.0232359f, +-0.0753728f,0.996934f,0.0209924f, +-0.279745f,0.951672f,0.12674f, +-0.364174f,0.921867f,0.132433f, +-0.344523f,0.936581f,0.0641857f, +-0.216332f,0.972578f,0.0853902f, +-0.223892f,0.974436f,0.0186366f, +-0.28965f,0.953049f,-0.0883156f, +-0.269918f,0.95756f,-0.101108f, +-0.286201f,0.950564f,-0.120491f, +0.172976f,0.984286f,-0.0355076f, +0.24194f,0.969981f,0.0245291f, +0.324379f,0.937283f,0.127591f, +0.286811f,0.953171f,0.0959428f, +0.228455f,0.972614f,-0.0427886f, +0.182359f,0.97568f,-0.121631f, +0.113036f,0.971479f,-0.208452f, +0.0547152f,0.964701f,-0.257601f, +-0.089806f,0.977237f,-0.192205f, +-0.171631f,0.984685f,-0.0306458f, +-0.116586f,0.992809f,0.0271681f, +-0.181607f,0.981068f,-0.0672723f, +-0.351307f,0.914748f,-0.199546f, +-0.388005f,0.90325f,-0.183278f, +-0.498044f,0.847159f,-0.185132f, +-0.510366f,0.84434f,-0.163145f, +-0.479522f,0.851128f,-0.213636f, +-0.42037f,0.86671f,-0.268518f, +-0.285469f,0.932257f,-0.22227f, +-0.161107f,0.969121f,-0.186679f, +-0.183754f,0.955302f,-0.231585f, +-0.370817f,0.89935f,-0.231654f, +-0.514998f,0.83014f,-0.213645f, +-0.498206f,0.85286f,-0.156273f, +-0.539513f,0.835182f,-0.106757f, +-0.535773f,0.843208f,0.0441435f, +-0.434698f,0.878206f,0.19948f, +-0.415775f,0.89222f,0.176277f, +-0.35414f,0.920981f,0.162413f, +-0.208366f,0.953013f,0.219884f, +-0.257177f,0.962661f,0.0845243f, +-0.386488f,0.920792f,-0.0526133f, +-0.381213f,0.924327f,0.0172227f, +-0.280093f,0.955497f,0.0925905f, +-0.1219f,0.953555f,0.275451f, +-0.0595691f,0.973079f,0.222641f, +0.124431f,0.978938f,0.161854f, +0.328706f,0.943592f,0.0398269f, +0.495224f,0.863825f,-0.0925162f, +0.549494f,0.832161f,-0.0745945f, +0.445758f,0.890738f,0.0887957f, +0.286029f,0.911685f,0.294987f, +0.236342f,0.90766f,0.346837f, +0.306156f,0.900003f,0.310262f, +0.362522f,0.893707f,0.264322f, +0.407318f,0.891604f,0.197826f, +0.447705f,0.883296f,0.139101f, +0.451832f,0.890524f,0.0530504f, +0.450032f,0.892977f,-0.00796524f, +0.380264f,0.922022f,-0.0726326f, +0.220431f,0.973877f,-0.0545382f, +0.073814f,0.997262f,0.00436123f, +0.143916f,0.987825f,0.059083f, +0.242994f,0.967605f,0.068523f, +0.0793826f,0.995647f,0.0488496f, +-0.0810126f,0.994023f,0.0731786f, +0.0550609f,0.987118f,0.150223f, +-0.0403249f,0.995863f,0.0814341f, +-0.341404f,0.939899f,-0.00574405f, +-0.333197f,0.942331f,0.0315063f, +-0.270492f,0.962353f,-0.0266656f, +-0.217149f,0.973729f,-0.0685481f, +-0.150518f,0.988024f,-0.0339529f, +-0.227799f,0.970772f,-0.0755549f, +-0.30247f,0.950166f,-0.0754703f, +-0.319718f,0.946617f,-0.0411916f, +0.16825f,0.98433f,0.0527868f, +0.196178f,0.978898f,0.0572086f, +0.274186f,0.954613f,0.116347f, +0.32563f,0.930709f,0.166568f, +0.315871f,0.943308f,0.101959f, +0.191037f,0.981318f,-0.0227958f, +0.218135f,0.975914f,0.0029357f, +0.0466483f,0.982299f,-0.18142f, +-0.170175f,0.975305f,-0.140788f, +-0.258133f,0.965917f,0.0192531f, +-0.189679f,0.978131f,0.0853348f, +-0.0936377f,0.967266f,0.235858f, +-0.301926f,0.950003f,0.0795937f, +-0.345647f,0.93835f,0.00528925f, +-0.494118f,0.858314f,-0.138363f, +-0.492927f,0.860507f,-0.128646f, +-0.443878f,0.87267f,-0.203517f, +-0.398442f,0.869961f,-0.290537f, +-0.31747f,0.894846f,-0.313789f, +-0.189431f,0.934926f,-0.300049f, +-0.194231f,0.947861f,-0.252654f, +-0.355627f,0.917296f,-0.179159f, +-0.521351f,0.821848f,-0.229692f, +-0.537173f,0.817848f,-0.206322f, +-0.595314f,0.798098f,-0.0929575f, +-0.612312f,0.785394f,0.0907203f, +-0.484809f,0.839064f,0.246843f, +-0.327417f,0.875762f,0.354737f, +-0.358949f,0.909479f,0.20977f, +-0.221142f,0.943893f,0.245282f, +-0.137619f,0.956208f,0.258316f, +-0.37682f,0.920718f,0.101416f, +-0.393482f,0.900899f,0.183174f, +-0.309483f,0.930699f,0.194988f, +-0.137506f,0.96116f,0.2393f, +-0.0256175f,0.984881f,0.171327f, +0.155024f,0.972933f,0.171372f, +0.40312f,0.907825f,0.115531f, +0.491485f,0.869632f,-0.0467184f, +0.488586f,0.869843f,0.0682392f, +0.313615f,0.910806f,0.268473f, +0.190736f,0.863506f,0.466881f, +0.238952f,0.837112f,0.492083f, +0.344695f,0.840122f,0.418784f, +0.396648f,0.860615f,0.319393f, +0.456384f,0.85928f,0.230981f, +0.487857f,0.863295f,0.129295f, +0.451906f,0.891012f,0.043332f, +0.456211f,0.882737f,0.112455f, +0.397431f,0.910062f,0.117622f, +0.204941f,0.971778f,0.116821f, +0.0877111f,0.985798f,0.143208f, +0.14813f,0.986469f,0.0702648f, +0.212033f,0.976625f,0.035296f, +0.0413914f,0.99116f,0.126047f, +-0.10186f,0.970634f,0.217932f, +0.0558102f,0.971334f,0.231076f, +0.0834757f,0.981533f,0.172117f, +-0.293392f,0.955612f,-0.0269471f, +-0.339064f,0.938377f,-0.0669636f, +-0.232942f,0.969004f,-0.0822698f, +-0.249298f,0.960887f,-0.120613f, +-0.178309f,0.98375f,-0.0210319f, +-0.23671f,0.971566f,0.00516088f, +-0.322203f,0.944986f,0.0564443f, +-0.359276f,0.929551f,0.0827968f, +}; + +btScalar Landscape06Tex[] = { +0.0f,0.0078125f, +0.0f,0.0f, +0.0078125f,0.0078125f, +0.0078125f,0.0f, +0.015625f,0.0078125f, +0.015625f,0.0f, +0.0234375f,0.0078125f, +0.0234375f,0.0f, +0.03125f,0.0078125f, +0.03125f,0.0f, +0.0390625f,0.0078125f, +0.0390625f,0.0f, +0.046875f,0.0078125f, +0.046875f,0.0f, +0.0546875f,0.0078125f, +0.0546875f,0.0f, +0.0625f,0.0078125f, +0.0625f,0.0f, +0.0703125f,0.0078125f, +0.0703125f,0.0f, +0.078125f,0.0078125f, +0.078125f,0.0f, +0.0859375f,0.0078125f, +0.0859375f,0.0f, +0.09375f,0.0078125f, +0.09375f,0.0f, +0.101563f,0.0078125f, +0.101563f,0.0f, +0.109375f,0.0078125f, +0.109375f,0.0f, +0.117188f,0.0078125f, +0.117188f,0.0f, +0.125f,0.0078125f, +0.125f,0.0f, +0.132813f,0.0078125f, +0.132813f,0.0f, +0.140625f,0.0078125f, +0.140625f,0.0f, +0.148438f,0.0078125f, +0.148438f,0.0f, +0.15625f,0.0078125f, +0.15625f,0.0f, +0.164063f,0.0078125f, +0.164063f,0.0f, +0.171875f,0.0078125f, +0.171875f,0.0f, +0.179688f,0.0078125f, +0.179688f,0.0f, +0.1875f,0.0078125f, +0.1875f,0.0f, +0.195313f,0.0078125f, +0.195313f,0.0f, +0.203125f,0.0078125f, +0.203125f,0.0f, +0.210938f,0.0078125f, +0.210938f,0.0f, +0.21875f,0.0078125f, +0.21875f,0.0f, +0.226563f,0.0078125f, +0.226563f,0.0f, +0.234375f,0.0078125f, +0.234375f,0.0f, +0.242188f,0.0078125f, +0.242188f,0.0f, +0.25f,0.0078125f, +0.25f,0.0f, +0.257813f,0.0078125f, +0.257813f,0.0f, +0.265625f,0.0078125f, +0.265625f,0.0f, +0.273438f,0.0078125f, +0.273438f,0.0f, +0.28125f,0.0078125f, +0.28125f,0.0f, +0.289063f,0.0078125f, +0.289063f,0.0f, +0.296875f,0.0078125f, +0.296875f,0.0f, +0.304688f,0.0078125f, +0.304688f,0.0f, +0.3125f,0.0078125f, +0.3125f,0.0f, +0.320313f,0.0078125f, +0.320313f,0.0f, +0.328125f,0.0078125f, +0.328125f,0.0f, +0.335938f,0.0078125f, +0.335938f,0.0f, +0.34375f,0.0078125f, +0.34375f,0.0f, +0.351563f,0.0078125f, +0.351563f,0.0f, +0.359375f,0.0078125f, +0.359375f,0.0f, +0.367188f,0.0078125f, +0.367188f,0.0f, +0.375f,0.0078125f, +0.375f,0.0f, +0.382813f,0.0078125f, +0.382813f,0.0f, +0.390625f,0.0078125f, +0.390625f,0.0f, +0.398438f,0.0078125f, +0.398438f,0.0f, +0.40625f,0.0078125f, +0.40625f,0.0f, +0.414063f,0.0078125f, +0.414063f,0.0f, +0.421875f,0.0078125f, +0.421875f,0.0f, +0.429688f,0.0078125f, +0.429688f,0.0f, +0.4375f,0.0078125f, +0.4375f,0.0f, +0.445313f,0.0078125f, +0.445313f,0.0f, +0.453125f,0.0078125f, +0.453125f,0.0f, +0.460938f,0.0078125f, +0.460938f,0.0f, +0.46875f,0.0078125f, +0.46875f,0.0f, +0.476563f,0.0078125f, +0.476563f,0.0f, +0.484375f,0.0078125f, +0.484375f,0.0f, +0.492188f,0.0078125f, +0.492188f,0.0f, +0.5f,0.0078125f, +0.5f,0.0f, +0.507813f,0.0078125f, +0.507813f,0.0f, +0.0f,0.015625f, +0.0078125f,0.015625f, +0.015625f,0.015625f, +0.0234375f,0.015625f, +0.03125f,0.015625f, +0.0390625f,0.015625f, +0.046875f,0.015625f, +0.0546875f,0.015625f, +0.0625f,0.015625f, +0.0703125f,0.015625f, +0.078125f,0.015625f, +0.0859375f,0.015625f, +0.09375f,0.015625f, +0.101563f,0.015625f, +0.109375f,0.015625f, +0.117188f,0.015625f, +0.125f,0.015625f, +0.132813f,0.015625f, +0.140625f,0.015625f, +0.148438f,0.015625f, +0.15625f,0.015625f, +0.164063f,0.015625f, +0.171875f,0.015625f, +0.179688f,0.015625f, +0.1875f,0.015625f, +0.195313f,0.015625f, +0.203125f,0.015625f, +0.210938f,0.015625f, +0.21875f,0.015625f, +0.226563f,0.015625f, +0.234375f,0.015625f, +0.242188f,0.015625f, +0.25f,0.015625f, +0.257813f,0.015625f, +0.265625f,0.015625f, +0.273438f,0.015625f, +0.28125f,0.015625f, +0.289063f,0.015625f, +0.296875f,0.015625f, +0.304688f,0.015625f, +0.3125f,0.015625f, +0.320313f,0.015625f, +0.328125f,0.015625f, +0.335938f,0.015625f, +0.34375f,0.015625f, +0.351563f,0.015625f, +0.359375f,0.015625f, +0.367188f,0.015625f, +0.375f,0.015625f, +0.382813f,0.015625f, +0.390625f,0.015625f, +0.398438f,0.015625f, +0.40625f,0.015625f, +0.414063f,0.015625f, +0.421875f,0.015625f, +0.429688f,0.015625f, +0.4375f,0.015625f, +0.445313f,0.015625f, +0.453125f,0.015625f, +0.460938f,0.015625f, +0.46875f,0.015625f, +0.476563f,0.015625f, +0.484375f,0.015625f, +0.492188f,0.015625f, +0.5f,0.015625f, +0.507813f,0.015625f, +0.0f,0.0234375f, +0.0078125f,0.0234375f, +0.015625f,0.0234375f, +0.0234375f,0.0234375f, +0.03125f,0.0234375f, +0.0390625f,0.0234375f, +0.046875f,0.0234375f, +0.0546875f,0.0234375f, +0.0625f,0.0234375f, +0.0703125f,0.0234375f, +0.078125f,0.0234375f, +0.0859375f,0.0234375f, +0.09375f,0.0234375f, +0.101563f,0.0234375f, +0.109375f,0.0234375f, +0.117188f,0.0234375f, +0.125f,0.0234375f, +0.132813f,0.0234375f, +0.140625f,0.0234375f, +0.148438f,0.0234375f, +0.15625f,0.0234375f, +0.164063f,0.0234375f, +0.171875f,0.0234375f, +0.179688f,0.0234375f, +0.1875f,0.0234375f, +0.195313f,0.0234375f, +0.203125f,0.0234375f, +0.210938f,0.0234375f, +0.21875f,0.0234375f, +0.226563f,0.0234375f, +0.234375f,0.0234375f, +0.242188f,0.0234375f, +0.25f,0.0234375f, +0.257813f,0.0234375f, +0.265625f,0.0234375f, +0.273438f,0.0234375f, +0.28125f,0.0234375f, +0.289063f,0.0234375f, +0.296875f,0.0234375f, +0.304688f,0.0234375f, +0.3125f,0.0234375f, +0.320313f,0.0234375f, +0.328125f,0.0234375f, +0.335938f,0.0234375f, +0.34375f,0.0234375f, +0.351563f,0.0234375f, +0.359375f,0.0234375f, +0.367188f,0.0234375f, +0.375f,0.0234375f, +0.382813f,0.0234375f, +0.390625f,0.0234375f, +0.398438f,0.0234375f, +0.40625f,0.0234375f, +0.414063f,0.0234375f, +0.421875f,0.0234375f, +0.429688f,0.0234375f, +0.4375f,0.0234375f, +0.445313f,0.0234375f, +0.453125f,0.0234375f, +0.460938f,0.0234375f, +0.46875f,0.0234375f, +0.476563f,0.0234375f, +0.484375f,0.0234375f, +0.492188f,0.0234375f, +0.5f,0.0234375f, +0.507813f,0.0234375f, +0.0f,0.03125f, +0.0078125f,0.03125f, +0.015625f,0.03125f, +0.0234375f,0.03125f, +0.03125f,0.03125f, +0.0390625f,0.03125f, +0.046875f,0.03125f, +0.0546875f,0.03125f, +0.0625f,0.03125f, +0.0703125f,0.03125f, +0.078125f,0.03125f, +0.0859375f,0.03125f, +0.09375f,0.03125f, +0.101563f,0.03125f, +0.109375f,0.03125f, +0.117188f,0.03125f, +0.125f,0.03125f, +0.132813f,0.03125f, +0.140625f,0.03125f, +0.148438f,0.03125f, +0.15625f,0.03125f, +0.164063f,0.03125f, +0.171875f,0.03125f, +0.179688f,0.03125f, +0.1875f,0.03125f, +0.195313f,0.03125f, +0.203125f,0.03125f, +0.210938f,0.03125f, +0.21875f,0.03125f, +0.226563f,0.03125f, +0.234375f,0.03125f, +0.242188f,0.03125f, +0.25f,0.03125f, +0.257813f,0.03125f, +0.265625f,0.03125f, +0.273438f,0.03125f, +0.28125f,0.03125f, +0.289063f,0.03125f, +0.296875f,0.03125f, +0.304688f,0.03125f, +0.3125f,0.03125f, +0.320313f,0.03125f, +0.328125f,0.03125f, +0.335938f,0.03125f, +0.34375f,0.03125f, +0.351563f,0.03125f, +0.359375f,0.03125f, +0.367188f,0.03125f, +0.375f,0.03125f, +0.382813f,0.03125f, +0.390625f,0.03125f, +0.398438f,0.03125f, +0.40625f,0.03125f, +0.414063f,0.03125f, +0.421875f,0.03125f, +0.429688f,0.03125f, +0.4375f,0.03125f, +0.445313f,0.03125f, +0.453125f,0.03125f, +0.460938f,0.03125f, +0.46875f,0.03125f, +0.476563f,0.03125f, +0.484375f,0.03125f, +0.492188f,0.03125f, +0.5f,0.03125f, +0.507813f,0.03125f, +0.0f,0.0390625f, +0.0078125f,0.0390625f, +0.015625f,0.0390625f, +0.0234375f,0.0390625f, +0.03125f,0.0390625f, +0.0390625f,0.0390625f, +0.046875f,0.0390625f, +0.0546875f,0.0390625f, +0.0625f,0.0390625f, +0.0703125f,0.0390625f, +0.078125f,0.0390625f, +0.0859375f,0.0390625f, +0.09375f,0.0390625f, +0.101563f,0.0390625f, +0.109375f,0.0390625f, +0.117188f,0.0390625f, +0.125f,0.0390625f, +0.132813f,0.0390625f, +0.140625f,0.0390625f, +0.148438f,0.0390625f, +0.15625f,0.0390625f, +0.164063f,0.0390625f, +0.171875f,0.0390625f, +0.179688f,0.0390625f, +0.1875f,0.0390625f, +0.195313f,0.0390625f, +0.203125f,0.0390625f, +0.210938f,0.0390625f, +0.21875f,0.0390625f, +0.226563f,0.0390625f, +0.234375f,0.0390625f, +0.242188f,0.0390625f, +0.25f,0.0390625f, +0.257813f,0.0390625f, +0.265625f,0.0390625f, +0.273438f,0.0390625f, +0.28125f,0.0390625f, +0.289063f,0.0390625f, +0.296875f,0.0390625f, +0.304688f,0.0390625f, +0.3125f,0.0390625f, +0.320313f,0.0390625f, +0.328125f,0.0390625f, +0.335938f,0.0390625f, +0.34375f,0.0390625f, +0.351563f,0.0390625f, +0.359375f,0.0390625f, +0.367188f,0.0390625f, +0.375f,0.0390625f, +0.382813f,0.0390625f, +0.390625f,0.0390625f, +0.398438f,0.0390625f, +0.40625f,0.0390625f, +0.414063f,0.0390625f, +0.421875f,0.0390625f, +0.429688f,0.0390625f, +0.4375f,0.0390625f, +0.445313f,0.0390625f, +0.453125f,0.0390625f, +0.460938f,0.0390625f, +0.46875f,0.0390625f, +0.476563f,0.0390625f, +0.484375f,0.0390625f, +0.492188f,0.0390625f, +0.5f,0.0390625f, +0.507813f,0.0390625f, +0.0f,0.046875f, +0.0078125f,0.046875f, +0.015625f,0.046875f, +0.0234375f,0.046875f, +0.03125f,0.046875f, +0.0390625f,0.046875f, +0.046875f,0.046875f, +0.0546875f,0.046875f, +0.0625f,0.046875f, +0.0703125f,0.046875f, +0.078125f,0.046875f, +0.0859375f,0.046875f, +0.09375f,0.046875f, +0.101563f,0.046875f, +0.109375f,0.046875f, +0.117188f,0.046875f, +0.125f,0.046875f, +0.132813f,0.046875f, +0.140625f,0.046875f, +0.148438f,0.046875f, +0.15625f,0.046875f, +0.164063f,0.046875f, +0.171875f,0.046875f, +0.179688f,0.046875f, +0.1875f,0.046875f, +0.195313f,0.046875f, +0.203125f,0.046875f, +0.210938f,0.046875f, +0.21875f,0.046875f, +0.226563f,0.046875f, +0.234375f,0.046875f, +0.242188f,0.046875f, +0.25f,0.046875f, +0.257813f,0.046875f, +0.265625f,0.046875f, +0.273438f,0.046875f, +0.28125f,0.046875f, +0.289063f,0.046875f, +0.296875f,0.046875f, +0.304688f,0.046875f, +0.3125f,0.046875f, +0.320313f,0.046875f, +0.328125f,0.046875f, +0.335938f,0.046875f, +0.34375f,0.046875f, +0.351563f,0.046875f, +0.359375f,0.046875f, +0.367188f,0.046875f, +0.375f,0.046875f, +0.382813f,0.046875f, +0.390625f,0.046875f, +0.398438f,0.046875f, +0.40625f,0.046875f, +0.414063f,0.046875f, +0.421875f,0.046875f, +0.429688f,0.046875f, +0.4375f,0.046875f, +0.445313f,0.046875f, +0.453125f,0.046875f, +0.460938f,0.046875f, +0.46875f,0.046875f, +0.476563f,0.046875f, +0.484375f,0.046875f, +0.492188f,0.046875f, +0.5f,0.046875f, +0.507813f,0.046875f, +0.0f,0.0546875f, +0.0078125f,0.0546875f, +0.015625f,0.0546875f, +0.0234375f,0.0546875f, +0.03125f,0.0546875f, +0.0390625f,0.0546875f, +0.046875f,0.0546875f, +0.0546875f,0.0546875f, +0.0625f,0.0546875f, +0.0703125f,0.0546875f, +0.078125f,0.0546875f, +0.0859375f,0.0546875f, +0.09375f,0.0546875f, +0.101563f,0.0546875f, +0.109375f,0.0546875f, +0.117188f,0.0546875f, +0.125f,0.0546875f, +0.132813f,0.0546875f, +0.140625f,0.0546875f, +0.148438f,0.0546875f, +0.15625f,0.0546875f, +0.164063f,0.0546875f, +0.171875f,0.0546875f, +0.179688f,0.0546875f, +0.1875f,0.0546875f, +0.195313f,0.0546875f, +0.203125f,0.0546875f, +0.210938f,0.0546875f, +0.21875f,0.0546875f, +0.226563f,0.0546875f, +0.234375f,0.0546875f, +0.242188f,0.0546875f, +0.25f,0.0546875f, +0.257813f,0.0546875f, +0.265625f,0.0546875f, +0.273438f,0.0546875f, +0.28125f,0.0546875f, +0.289063f,0.0546875f, +0.296875f,0.0546875f, +0.304688f,0.0546875f, +0.3125f,0.0546875f, +0.320313f,0.0546875f, +0.328125f,0.0546875f, +0.335938f,0.0546875f, +0.34375f,0.0546875f, +0.351563f,0.0546875f, +0.359375f,0.0546875f, +0.367188f,0.0546875f, +0.375f,0.0546875f, +0.382813f,0.0546875f, +0.390625f,0.0546875f, +0.398438f,0.0546875f, +0.40625f,0.0546875f, +0.414063f,0.0546875f, +0.421875f,0.0546875f, +0.429688f,0.0546875f, +0.4375f,0.0546875f, +0.445313f,0.0546875f, +0.453125f,0.0546875f, +0.460938f,0.0546875f, +0.46875f,0.0546875f, +0.476563f,0.0546875f, +0.484375f,0.0546875f, +0.492188f,0.0546875f, +0.5f,0.0546875f, +0.507813f,0.0546875f, +0.0f,0.0625f, +0.0078125f,0.0625f, +0.015625f,0.0625f, +0.0234375f,0.0625f, +0.03125f,0.0625f, +0.0390625f,0.0625f, +0.046875f,0.0625f, +0.0546875f,0.0625f, +0.0625f,0.0625f, +0.0703125f,0.0625f, +0.078125f,0.0625f, +0.0859375f,0.0625f, +0.09375f,0.0625f, +0.101563f,0.0625f, +0.109375f,0.0625f, +0.117188f,0.0625f, +0.125f,0.0625f, +0.132813f,0.0625f, +0.140625f,0.0625f, +0.148438f,0.0625f, +0.15625f,0.0625f, +0.164063f,0.0625f, +0.171875f,0.0625f, +0.179688f,0.0625f, +0.1875f,0.0625f, +0.195313f,0.0625f, +0.203125f,0.0625f, +0.210938f,0.0625f, +0.21875f,0.0625f, +0.226563f,0.0625f, +0.234375f,0.0625f, +0.242188f,0.0625f, +0.25f,0.0625f, +0.257813f,0.0625f, +0.265625f,0.0625f, +0.273438f,0.0625f, +0.28125f,0.0625f, +0.289063f,0.0625f, +0.296875f,0.0625f, +0.304688f,0.0625f, +0.3125f,0.0625f, +0.320313f,0.0625f, +0.328125f,0.0625f, +0.335938f,0.0625f, +0.34375f,0.0625f, +0.351563f,0.0625f, +0.359375f,0.0625f, +0.367188f,0.0625f, +0.375f,0.0625f, +0.382813f,0.0625f, +0.390625f,0.0625f, +0.398438f,0.0625f, +0.40625f,0.0625f, +0.414063f,0.0625f, +0.421875f,0.0625f, +0.429688f,0.0625f, +0.4375f,0.0625f, +0.445313f,0.0625f, +0.453125f,0.0625f, +0.460938f,0.0625f, +0.46875f,0.0625f, +0.476563f,0.0625f, +0.484375f,0.0625f, +0.492188f,0.0625f, +0.5f,0.0625f, +0.507813f,0.0625f, +0.0f,0.0703125f, +0.0078125f,0.0703125f, +0.015625f,0.0703125f, +0.0234375f,0.0703125f, +0.03125f,0.0703125f, +0.0390625f,0.0703125f, +0.046875f,0.0703125f, +0.0546875f,0.0703125f, +0.0625f,0.0703125f, +0.0703125f,0.0703125f, +0.078125f,0.0703125f, +0.0859375f,0.0703125f, +0.09375f,0.0703125f, +0.101563f,0.0703125f, +0.109375f,0.0703125f, +0.117188f,0.0703125f, +0.125f,0.0703125f, +0.132813f,0.0703125f, +0.140625f,0.0703125f, +0.148438f,0.0703125f, +0.15625f,0.0703125f, +0.164063f,0.0703125f, +0.171875f,0.0703125f, +0.179688f,0.0703125f, +0.1875f,0.0703125f, +0.195313f,0.0703125f, +0.203125f,0.0703125f, +0.210938f,0.0703125f, +0.21875f,0.0703125f, +0.226563f,0.0703125f, +0.234375f,0.0703125f, +0.242188f,0.0703125f, +0.25f,0.0703125f, +0.257813f,0.0703125f, +0.265625f,0.0703125f, +0.273438f,0.0703125f, +0.28125f,0.0703125f, +0.289063f,0.0703125f, +0.296875f,0.0703125f, +0.304688f,0.0703125f, +0.3125f,0.0703125f, +0.320313f,0.0703125f, +0.328125f,0.0703125f, +0.335938f,0.0703125f, +0.34375f,0.0703125f, +0.351563f,0.0703125f, +0.359375f,0.0703125f, +0.367188f,0.0703125f, +0.375f,0.0703125f, +0.382813f,0.0703125f, +0.390625f,0.0703125f, +0.398438f,0.0703125f, +0.40625f,0.0703125f, +0.414063f,0.0703125f, +0.421875f,0.0703125f, +0.429688f,0.0703125f, +0.4375f,0.0703125f, +0.445313f,0.0703125f, +0.453125f,0.0703125f, +0.460938f,0.0703125f, +0.46875f,0.0703125f, +0.476563f,0.0703125f, +0.484375f,0.0703125f, +0.492188f,0.0703125f, +0.5f,0.0703125f, +0.507813f,0.0703125f, +0.0f,0.078125f, +0.0078125f,0.078125f, +0.015625f,0.078125f, +0.0234375f,0.078125f, +0.03125f,0.078125f, +0.0390625f,0.078125f, +0.046875f,0.078125f, +0.0546875f,0.078125f, +0.0625f,0.078125f, +0.0703125f,0.078125f, +0.078125f,0.078125f, +0.0859375f,0.078125f, +0.09375f,0.078125f, +0.101563f,0.078125f, +0.109375f,0.078125f, +0.117188f,0.078125f, +0.125f,0.078125f, +0.132813f,0.078125f, +0.140625f,0.078125f, +0.148438f,0.078125f, +0.15625f,0.078125f, +0.164063f,0.078125f, +0.171875f,0.078125f, +0.179688f,0.078125f, +0.1875f,0.078125f, +0.195313f,0.078125f, +0.203125f,0.078125f, +0.210938f,0.078125f, +0.21875f,0.078125f, +0.226563f,0.078125f, +0.234375f,0.078125f, +0.242188f,0.078125f, +0.25f,0.078125f, +0.257813f,0.078125f, +0.265625f,0.078125f, +0.273438f,0.078125f, +0.28125f,0.078125f, +0.289063f,0.078125f, +0.296875f,0.078125f, +0.304688f,0.078125f, +0.3125f,0.078125f, +0.320313f,0.078125f, +0.328125f,0.078125f, +0.335938f,0.078125f, +0.34375f,0.078125f, +0.351563f,0.078125f, +0.359375f,0.078125f, +0.367188f,0.078125f, +0.375f,0.078125f, +0.382813f,0.078125f, +0.390625f,0.078125f, +0.398438f,0.078125f, +0.40625f,0.078125f, +0.414063f,0.078125f, +0.421875f,0.078125f, +0.429688f,0.078125f, +0.4375f,0.078125f, +0.445313f,0.078125f, +0.453125f,0.078125f, +0.460938f,0.078125f, +0.46875f,0.078125f, +0.476563f,0.078125f, +0.484375f,0.078125f, +0.492188f,0.078125f, +0.5f,0.078125f, +0.507813f,0.078125f, +0.0f,0.0859375f, +0.0078125f,0.0859375f, +0.015625f,0.0859375f, +0.0234375f,0.0859375f, +0.03125f,0.0859375f, +0.0390625f,0.0859375f, +0.046875f,0.0859375f, +0.0546875f,0.0859375f, +0.0625f,0.0859375f, +0.0703125f,0.0859375f, +0.078125f,0.0859375f, +0.0859375f,0.0859375f, +0.09375f,0.0859375f, +0.101563f,0.0859375f, +0.109375f,0.0859375f, +0.117188f,0.0859375f, +0.125f,0.0859375f, +0.132813f,0.0859375f, +0.140625f,0.0859375f, +0.148438f,0.0859375f, +0.15625f,0.0859375f, +0.164063f,0.0859375f, +0.171875f,0.0859375f, +0.179688f,0.0859375f, +0.1875f,0.0859375f, +0.195313f,0.0859375f, +0.203125f,0.0859375f, +0.210938f,0.0859375f, +0.21875f,0.0859375f, +0.226563f,0.0859375f, +0.234375f,0.0859375f, +0.242188f,0.0859375f, +0.25f,0.0859375f, +0.257813f,0.0859375f, +0.265625f,0.0859375f, +0.273438f,0.0859375f, +0.28125f,0.0859375f, +0.289063f,0.0859375f, +0.296875f,0.0859375f, +0.304688f,0.0859375f, +0.3125f,0.0859375f, +0.320313f,0.0859375f, +0.328125f,0.0859375f, +0.335938f,0.0859375f, +0.34375f,0.0859375f, +0.351563f,0.0859375f, +0.359375f,0.0859375f, +0.367188f,0.0859375f, +0.375f,0.0859375f, +0.382813f,0.0859375f, +0.390625f,0.0859375f, +0.398438f,0.0859375f, +0.40625f,0.0859375f, +0.414063f,0.0859375f, +0.421875f,0.0859375f, +0.429688f,0.0859375f, +0.4375f,0.0859375f, +0.445313f,0.0859375f, +0.453125f,0.0859375f, +0.460938f,0.0859375f, +0.46875f,0.0859375f, +0.476563f,0.0859375f, +0.484375f,0.0859375f, +0.492188f,0.0859375f, +0.5f,0.0859375f, +0.507813f,0.0859375f, +0.0f,0.09375f, +0.0078125f,0.09375f, +0.015625f,0.09375f, +0.0234375f,0.09375f, +0.03125f,0.09375f, +0.0390625f,0.09375f, +0.046875f,0.09375f, +0.0546875f,0.09375f, +0.0625f,0.09375f, +0.0703125f,0.09375f, +0.078125f,0.09375f, +0.0859375f,0.09375f, +0.09375f,0.09375f, +0.101563f,0.09375f, +0.109375f,0.09375f, +0.117188f,0.09375f, +0.125f,0.09375f, +0.132813f,0.09375f, +0.140625f,0.09375f, +0.148438f,0.09375f, +0.15625f,0.09375f, +0.164063f,0.09375f, +0.171875f,0.09375f, +0.179688f,0.09375f, +0.1875f,0.09375f, +0.195313f,0.09375f, +0.203125f,0.09375f, +0.210938f,0.09375f, +0.21875f,0.09375f, +0.226563f,0.09375f, +0.234375f,0.09375f, +0.242188f,0.09375f, +0.25f,0.09375f, +0.257813f,0.09375f, +0.265625f,0.09375f, +0.273438f,0.09375f, +0.28125f,0.09375f, +0.289063f,0.09375f, +0.296875f,0.09375f, +0.304688f,0.09375f, +0.3125f,0.09375f, +0.320313f,0.09375f, +0.328125f,0.09375f, +0.335938f,0.09375f, +0.34375f,0.09375f, +0.351563f,0.09375f, +0.359375f,0.09375f, +0.367188f,0.09375f, +0.375f,0.09375f, +0.382813f,0.09375f, +0.390625f,0.09375f, +0.398438f,0.09375f, +0.40625f,0.09375f, +0.414063f,0.09375f, +0.421875f,0.09375f, +0.429688f,0.09375f, +0.4375f,0.09375f, +0.445313f,0.09375f, +0.453125f,0.09375f, +0.460938f,0.09375f, +0.46875f,0.09375f, +0.476563f,0.09375f, +0.484375f,0.09375f, +0.492188f,0.09375f, +0.5f,0.09375f, +0.507813f,0.09375f, +0.0f,0.101563f, +0.0078125f,0.101563f, +0.015625f,0.101563f, +0.0234375f,0.101563f, +0.03125f,0.101563f, +0.0390625f,0.101563f, +0.046875f,0.101563f, +0.0546875f,0.101563f, +0.0625f,0.101563f, +0.0703125f,0.101563f, +0.078125f,0.101563f, +0.0859375f,0.101563f, +0.09375f,0.101563f, +0.101563f,0.101563f, +0.109375f,0.101563f, +0.117188f,0.101563f, +0.125f,0.101563f, +0.132813f,0.101563f, +0.140625f,0.101563f, +0.148438f,0.101563f, +0.15625f,0.101563f, +0.164063f,0.101563f, +0.171875f,0.101563f, +0.179688f,0.101563f, +0.1875f,0.101563f, +0.195313f,0.101563f, +0.203125f,0.101563f, +0.210938f,0.101563f, +0.21875f,0.101563f, +0.226563f,0.101563f, +0.234375f,0.101563f, +0.242188f,0.101563f, +0.25f,0.101563f, +0.257813f,0.101563f, +0.265625f,0.101563f, +0.273438f,0.101563f, +0.28125f,0.101563f, +0.289063f,0.101563f, +0.296875f,0.101563f, +0.304688f,0.101563f, +0.3125f,0.101563f, +0.320313f,0.101563f, +0.328125f,0.101563f, +0.335938f,0.101563f, +0.34375f,0.101563f, +0.351563f,0.101563f, +0.359375f,0.101563f, +0.367188f,0.101563f, +0.375f,0.101563f, +0.382813f,0.101563f, +0.390625f,0.101563f, +0.398438f,0.101563f, +0.40625f,0.101563f, +0.414063f,0.101563f, +0.421875f,0.101563f, +0.429688f,0.101563f, +0.4375f,0.101563f, +0.445313f,0.101563f, +0.453125f,0.101563f, +0.460938f,0.101563f, +0.46875f,0.101563f, +0.476563f,0.101563f, +0.484375f,0.101563f, +0.492188f,0.101563f, +0.5f,0.101563f, +0.507813f,0.101563f, +0.0f,0.109375f, +0.0078125f,0.109375f, +0.015625f,0.109375f, +0.0234375f,0.109375f, +0.03125f,0.109375f, +0.0390625f,0.109375f, +0.046875f,0.109375f, +0.0546875f,0.109375f, +0.0625f,0.109375f, +0.0703125f,0.109375f, +0.078125f,0.109375f, +0.0859375f,0.109375f, +0.09375f,0.109375f, +0.101563f,0.109375f, +0.109375f,0.109375f, +0.117188f,0.109375f, +0.125f,0.109375f, +0.132813f,0.109375f, +0.140625f,0.109375f, +0.148438f,0.109375f, +0.15625f,0.109375f, +0.164063f,0.109375f, +0.171875f,0.109375f, +0.179688f,0.109375f, +0.1875f,0.109375f, +0.195313f,0.109375f, +0.203125f,0.109375f, +0.210938f,0.109375f, +0.21875f,0.109375f, +0.226563f,0.109375f, +0.234375f,0.109375f, +0.242188f,0.109375f, +0.25f,0.109375f, +0.257813f,0.109375f, +0.265625f,0.109375f, +0.273438f,0.109375f, +0.28125f,0.109375f, +0.289063f,0.109375f, +0.296875f,0.109375f, +0.304688f,0.109375f, +0.3125f,0.109375f, +0.320313f,0.109375f, +0.328125f,0.109375f, +0.335938f,0.109375f, +0.34375f,0.109375f, +0.351563f,0.109375f, +0.359375f,0.109375f, +0.367188f,0.109375f, +0.375f,0.109375f, +0.382813f,0.109375f, +0.390625f,0.109375f, +0.398438f,0.109375f, +0.40625f,0.109375f, +0.414063f,0.109375f, +0.421875f,0.109375f, +0.429688f,0.109375f, +0.4375f,0.109375f, +0.445313f,0.109375f, +0.453125f,0.109375f, +0.460938f,0.109375f, +0.46875f,0.109375f, +0.476563f,0.109375f, +0.484375f,0.109375f, +0.492188f,0.109375f, +0.5f,0.109375f, +0.507813f,0.109375f, +0.0f,0.117188f, +0.0078125f,0.117188f, +0.015625f,0.117188f, +0.0234375f,0.117188f, +0.03125f,0.117188f, +0.0390625f,0.117188f, +0.046875f,0.117188f, +0.0546875f,0.117188f, +0.0625f,0.117188f, +0.0703125f,0.117188f, +0.078125f,0.117188f, +0.0859375f,0.117188f, +0.09375f,0.117188f, +0.101563f,0.117188f, +0.109375f,0.117188f, +0.117188f,0.117188f, +0.125f,0.117188f, +0.132813f,0.117188f, +0.140625f,0.117188f, +0.148438f,0.117188f, +0.15625f,0.117188f, +0.164063f,0.117188f, +0.171875f,0.117188f, +0.179688f,0.117188f, +0.1875f,0.117188f, +0.195313f,0.117188f, +0.203125f,0.117188f, +0.210938f,0.117188f, +0.21875f,0.117188f, +0.226563f,0.117188f, +0.234375f,0.117188f, +0.242188f,0.117188f, +0.25f,0.117188f, +0.257813f,0.117188f, +0.265625f,0.117188f, +0.273438f,0.117188f, +0.28125f,0.117188f, +0.289063f,0.117188f, +0.296875f,0.117188f, +0.304688f,0.117188f, +0.3125f,0.117188f, +0.320313f,0.117188f, +0.328125f,0.117188f, +0.335938f,0.117188f, +0.34375f,0.117188f, +0.351563f,0.117188f, +0.359375f,0.117188f, +0.367188f,0.117188f, +0.375f,0.117188f, +0.382813f,0.117188f, +0.390625f,0.117188f, +0.398438f,0.117188f, +0.40625f,0.117188f, +0.414063f,0.117188f, +0.421875f,0.117188f, +0.429688f,0.117188f, +0.4375f,0.117188f, +0.445313f,0.117188f, +0.453125f,0.117188f, +0.460938f,0.117188f, +0.46875f,0.117188f, +0.476563f,0.117188f, +0.484375f,0.117188f, +0.492188f,0.117188f, +0.5f,0.117188f, +0.507813f,0.117188f, +0.0f,0.125f, +0.0078125f,0.125f, +0.015625f,0.125f, +0.0234375f,0.125f, +0.03125f,0.125f, +0.0390625f,0.125f, +0.046875f,0.125f, +0.0546875f,0.125f, +0.0625f,0.125f, +0.0703125f,0.125f, +0.078125f,0.125f, +0.0859375f,0.125f, +0.09375f,0.125f, +0.101563f,0.125f, +0.109375f,0.125f, +0.117188f,0.125f, +0.125f,0.125f, +0.132813f,0.125f, +0.140625f,0.125f, +0.148438f,0.125f, +0.15625f,0.125f, +0.164063f,0.125f, +0.171875f,0.125f, +0.179688f,0.125f, +0.1875f,0.125f, +0.195313f,0.125f, +0.203125f,0.125f, +0.210938f,0.125f, +0.21875f,0.125f, +0.226563f,0.125f, +0.234375f,0.125f, +0.242188f,0.125f, +0.25f,0.125f, +0.257813f,0.125f, +0.265625f,0.125f, +0.273438f,0.125f, +0.28125f,0.125f, +0.289063f,0.125f, +0.296875f,0.125f, +0.304688f,0.125f, +0.3125f,0.125f, +0.320313f,0.125f, +0.328125f,0.125f, +0.335938f,0.125f, +0.34375f,0.125f, +0.351563f,0.125f, +0.359375f,0.125f, +0.367188f,0.125f, +0.375f,0.125f, +0.382813f,0.125f, +0.390625f,0.125f, +0.398438f,0.125f, +0.40625f,0.125f, +0.414063f,0.125f, +0.421875f,0.125f, +0.429688f,0.125f, +0.4375f,0.125f, +0.445313f,0.125f, +0.453125f,0.125f, +0.460938f,0.125f, +0.46875f,0.125f, +0.476563f,0.125f, +0.484375f,0.125f, +0.492188f,0.125f, +0.5f,0.125f, +0.507813f,0.125f, +0.0f,0.132813f, +0.0078125f,0.132813f, +0.015625f,0.132813f, +0.0234375f,0.132813f, +0.03125f,0.132813f, +0.0390625f,0.132813f, +0.046875f,0.132813f, +0.0546875f,0.132813f, +0.0625f,0.132813f, +0.0703125f,0.132813f, +0.078125f,0.132813f, +0.0859375f,0.132813f, +0.09375f,0.132813f, +0.101563f,0.132813f, +0.109375f,0.132813f, +0.117188f,0.132813f, +0.125f,0.132813f, +0.132813f,0.132813f, +0.140625f,0.132813f, +0.148438f,0.132813f, +0.15625f,0.132813f, +0.164063f,0.132813f, +0.171875f,0.132813f, +0.179688f,0.132813f, +0.1875f,0.132813f, +0.195313f,0.132813f, +0.203125f,0.132813f, +0.210938f,0.132813f, +0.21875f,0.132813f, +0.226563f,0.132813f, +0.234375f,0.132813f, +0.242188f,0.132813f, +0.25f,0.132813f, +0.257813f,0.132813f, +0.265625f,0.132813f, +0.273438f,0.132813f, +0.28125f,0.132813f, +0.289063f,0.132813f, +0.296875f,0.132813f, +0.304688f,0.132813f, +0.3125f,0.132813f, +0.320313f,0.132813f, +0.328125f,0.132813f, +0.335938f,0.132813f, +0.34375f,0.132813f, +0.351563f,0.132813f, +0.359375f,0.132813f, +0.367188f,0.132813f, +0.375f,0.132813f, +0.382813f,0.132813f, +0.390625f,0.132813f, +0.398438f,0.132813f, +0.40625f,0.132813f, +0.414063f,0.132813f, +0.421875f,0.132813f, +0.429688f,0.132813f, +0.4375f,0.132813f, +0.445313f,0.132813f, +0.453125f,0.132813f, +0.460938f,0.132813f, +0.46875f,0.132813f, +0.476563f,0.132813f, +0.484375f,0.132813f, +0.492188f,0.132813f, +0.5f,0.132813f, +0.507813f,0.132813f, +0.0f,0.140625f, +0.0078125f,0.140625f, +0.015625f,0.140625f, +0.0234375f,0.140625f, +0.03125f,0.140625f, +0.0390625f,0.140625f, +0.046875f,0.140625f, +0.0546875f,0.140625f, +0.0625f,0.140625f, +0.0703125f,0.140625f, +0.078125f,0.140625f, +0.0859375f,0.140625f, +0.09375f,0.140625f, +0.101563f,0.140625f, +0.109375f,0.140625f, +0.117188f,0.140625f, +0.125f,0.140625f, +0.132813f,0.140625f, +0.140625f,0.140625f, +0.148438f,0.140625f, +0.15625f,0.140625f, +0.164063f,0.140625f, +0.171875f,0.140625f, +0.179688f,0.140625f, +0.1875f,0.140625f, +0.195313f,0.140625f, +0.203125f,0.140625f, +0.210938f,0.140625f, +0.21875f,0.140625f, +0.226563f,0.140625f, +0.234375f,0.140625f, +0.242188f,0.140625f, +0.25f,0.140625f, +0.257813f,0.140625f, +0.265625f,0.140625f, +0.273438f,0.140625f, +0.28125f,0.140625f, +0.289063f,0.140625f, +0.296875f,0.140625f, +0.304688f,0.140625f, +0.3125f,0.140625f, +0.320313f,0.140625f, +0.328125f,0.140625f, +0.335938f,0.140625f, +0.34375f,0.140625f, +0.351563f,0.140625f, +0.359375f,0.140625f, +0.367188f,0.140625f, +0.375f,0.140625f, +0.382813f,0.140625f, +0.390625f,0.140625f, +0.398438f,0.140625f, +0.40625f,0.140625f, +0.414063f,0.140625f, +0.421875f,0.140625f, +0.429688f,0.140625f, +0.4375f,0.140625f, +0.445313f,0.140625f, +0.453125f,0.140625f, +0.460938f,0.140625f, +0.46875f,0.140625f, +0.476563f,0.140625f, +0.484375f,0.140625f, +0.492188f,0.140625f, +0.5f,0.140625f, +0.507813f,0.140625f, +0.0f,0.148438f, +0.0078125f,0.148438f, +0.015625f,0.148438f, +0.0234375f,0.148438f, +0.03125f,0.148438f, +0.0390625f,0.148438f, +0.046875f,0.148438f, +0.0546875f,0.148438f, +0.0625f,0.148438f, +0.0703125f,0.148438f, +0.078125f,0.148438f, +0.0859375f,0.148438f, +0.09375f,0.148438f, +0.101563f,0.148438f, +0.109375f,0.148438f, +0.117188f,0.148438f, +0.125f,0.148438f, +0.132813f,0.148438f, +0.140625f,0.148438f, +0.148438f,0.148438f, +0.15625f,0.148438f, +0.164063f,0.148438f, +0.171875f,0.148438f, +0.179688f,0.148438f, +0.1875f,0.148438f, +0.195313f,0.148438f, +0.203125f,0.148438f, +0.210938f,0.148438f, +0.21875f,0.148438f, +0.226563f,0.148438f, +0.234375f,0.148438f, +0.242188f,0.148438f, +0.25f,0.148438f, +0.257813f,0.148438f, +0.265625f,0.148438f, +0.273438f,0.148438f, +0.28125f,0.148438f, +0.289063f,0.148438f, +0.296875f,0.148438f, +0.304688f,0.148438f, +0.3125f,0.148438f, +0.320313f,0.148438f, +0.328125f,0.148438f, +0.335938f,0.148438f, +0.34375f,0.148438f, +0.351563f,0.148438f, +0.359375f,0.148438f, +0.367188f,0.148438f, +0.375f,0.148438f, +0.382813f,0.148438f, +0.390625f,0.148438f, +0.398438f,0.148438f, +0.40625f,0.148438f, +0.414063f,0.148438f, +0.421875f,0.148438f, +0.429688f,0.148438f, +0.4375f,0.148438f, +0.445313f,0.148438f, +0.453125f,0.148438f, +0.460938f,0.148438f, +0.46875f,0.148438f, +0.476563f,0.148438f, +0.484375f,0.148438f, +0.492188f,0.148438f, +0.5f,0.148438f, +0.507813f,0.148438f, +0.0f,0.15625f, +0.0078125f,0.15625f, +0.015625f,0.15625f, +0.0234375f,0.15625f, +0.03125f,0.15625f, +0.0390625f,0.15625f, +0.046875f,0.15625f, +0.0546875f,0.15625f, +0.0625f,0.15625f, +0.0703125f,0.15625f, +0.078125f,0.15625f, +0.0859375f,0.15625f, +0.09375f,0.15625f, +0.101563f,0.15625f, +0.109375f,0.15625f, +0.117188f,0.15625f, +0.125f,0.15625f, +0.132813f,0.15625f, +0.140625f,0.15625f, +0.148438f,0.15625f, +0.15625f,0.15625f, +0.164063f,0.15625f, +0.171875f,0.15625f, +0.179688f,0.15625f, +0.1875f,0.15625f, +0.195313f,0.15625f, +0.203125f,0.15625f, +0.210938f,0.15625f, +0.21875f,0.15625f, +0.226563f,0.15625f, +0.234375f,0.15625f, +0.242188f,0.15625f, +0.25f,0.15625f, +0.257813f,0.15625f, +0.265625f,0.15625f, +0.273438f,0.15625f, +0.28125f,0.15625f, +0.289063f,0.15625f, +0.296875f,0.15625f, +0.304688f,0.15625f, +0.3125f,0.15625f, +0.320313f,0.15625f, +0.328125f,0.15625f, +0.335938f,0.15625f, +0.34375f,0.15625f, +0.351563f,0.15625f, +0.359375f,0.15625f, +0.367188f,0.15625f, +0.375f,0.15625f, +0.382813f,0.15625f, +0.390625f,0.15625f, +0.398438f,0.15625f, +0.40625f,0.15625f, +0.414063f,0.15625f, +0.421875f,0.15625f, +0.429688f,0.15625f, +0.4375f,0.15625f, +0.445313f,0.15625f, +0.453125f,0.15625f, +0.460938f,0.15625f, +0.46875f,0.15625f, +0.476563f,0.15625f, +0.484375f,0.15625f, +0.492188f,0.15625f, +0.5f,0.15625f, +0.507813f,0.15625f, +0.0f,0.164063f, +0.0078125f,0.164063f, +0.015625f,0.164063f, +0.0234375f,0.164063f, +0.03125f,0.164063f, +0.0390625f,0.164063f, +0.046875f,0.164063f, +0.0546875f,0.164063f, +0.0625f,0.164063f, +0.0703125f,0.164063f, +0.078125f,0.164063f, +0.0859375f,0.164063f, +0.09375f,0.164063f, +0.101563f,0.164063f, +0.109375f,0.164063f, +0.117188f,0.164063f, +0.125f,0.164063f, +0.132813f,0.164063f, +0.140625f,0.164063f, +0.148438f,0.164063f, +0.15625f,0.164063f, +0.164063f,0.164063f, +0.171875f,0.164063f, +0.179688f,0.164063f, +0.1875f,0.164063f, +0.195313f,0.164063f, +0.203125f,0.164063f, +0.210938f,0.164063f, +0.21875f,0.164063f, +0.226563f,0.164063f, +0.234375f,0.164063f, +0.242188f,0.164063f, +0.25f,0.164063f, +0.257813f,0.164063f, +0.265625f,0.164063f, +0.273438f,0.164063f, +0.28125f,0.164063f, +0.289063f,0.164063f, +0.296875f,0.164063f, +0.304688f,0.164063f, +0.3125f,0.164063f, +0.320313f,0.164063f, +0.328125f,0.164063f, +0.335938f,0.164063f, +0.34375f,0.164063f, +0.351563f,0.164063f, +0.359375f,0.164063f, +0.367188f,0.164063f, +0.375f,0.164063f, +0.382813f,0.164063f, +0.390625f,0.164063f, +0.398438f,0.164063f, +0.40625f,0.164063f, +0.414063f,0.164063f, +0.421875f,0.164063f, +0.429688f,0.164063f, +0.4375f,0.164063f, +0.445313f,0.164063f, +0.453125f,0.164063f, +0.460938f,0.164063f, +0.46875f,0.164063f, +0.476563f,0.164063f, +0.484375f,0.164063f, +0.492188f,0.164063f, +0.5f,0.164063f, +0.507813f,0.164063f, +0.0f,0.171875f, +0.0078125f,0.171875f, +0.015625f,0.171875f, +0.0234375f,0.171875f, +0.03125f,0.171875f, +0.0390625f,0.171875f, +0.046875f,0.171875f, +0.0546875f,0.171875f, +0.0625f,0.171875f, +0.0703125f,0.171875f, +0.078125f,0.171875f, +0.0859375f,0.171875f, +0.09375f,0.171875f, +0.101563f,0.171875f, +0.109375f,0.171875f, +0.117188f,0.171875f, +0.125f,0.171875f, +0.132813f,0.171875f, +0.140625f,0.171875f, +0.148438f,0.171875f, +0.15625f,0.171875f, +0.164063f,0.171875f, +0.171875f,0.171875f, +0.179688f,0.171875f, +0.1875f,0.171875f, +0.195313f,0.171875f, +0.203125f,0.171875f, +0.210938f,0.171875f, +0.21875f,0.171875f, +0.226563f,0.171875f, +0.234375f,0.171875f, +0.242188f,0.171875f, +0.25f,0.171875f, +0.257813f,0.171875f, +0.265625f,0.171875f, +0.273438f,0.171875f, +0.28125f,0.171875f, +0.289063f,0.171875f, +0.296875f,0.171875f, +0.304688f,0.171875f, +0.3125f,0.171875f, +0.320313f,0.171875f, +0.328125f,0.171875f, +0.335938f,0.171875f, +0.34375f,0.171875f, +0.351563f,0.171875f, +0.359375f,0.171875f, +0.367188f,0.171875f, +0.375f,0.171875f, +0.382813f,0.171875f, +0.390625f,0.171875f, +0.398438f,0.171875f, +0.40625f,0.171875f, +0.414063f,0.171875f, +0.421875f,0.171875f, +0.429688f,0.171875f, +0.4375f,0.171875f, +0.445313f,0.171875f, +0.453125f,0.171875f, +0.460938f,0.171875f, +0.46875f,0.171875f, +0.476563f,0.171875f, +0.484375f,0.171875f, +0.492188f,0.171875f, +0.5f,0.171875f, +0.507813f,0.171875f, +0.0f,0.179688f, +0.0078125f,0.179688f, +0.015625f,0.179688f, +0.0234375f,0.179688f, +0.03125f,0.179688f, +0.0390625f,0.179688f, +0.046875f,0.179688f, +0.0546875f,0.179688f, +0.0625f,0.179688f, +0.0703125f,0.179688f, +0.078125f,0.179688f, +0.0859375f,0.179688f, +0.09375f,0.179688f, +0.101563f,0.179688f, +0.109375f,0.179688f, +0.117188f,0.179688f, +0.125f,0.179688f, +0.132813f,0.179688f, +0.140625f,0.179688f, +0.148438f,0.179688f, +0.15625f,0.179688f, +0.164063f,0.179688f, +0.171875f,0.179688f, +0.179688f,0.179688f, +0.1875f,0.179688f, +0.195313f,0.179688f, +0.203125f,0.179688f, +0.210938f,0.179688f, +0.21875f,0.179688f, +0.226563f,0.179688f, +0.234375f,0.179688f, +0.242188f,0.179688f, +0.25f,0.179688f, +0.257813f,0.179688f, +0.265625f,0.179688f, +0.273438f,0.179688f, +0.28125f,0.179688f, +0.289063f,0.179688f, +0.296875f,0.179688f, +0.304688f,0.179688f, +0.3125f,0.179688f, +0.320313f,0.179688f, +0.328125f,0.179688f, +0.335938f,0.179688f, +0.34375f,0.179688f, +0.351563f,0.179688f, +0.359375f,0.179688f, +0.367188f,0.179688f, +0.375f,0.179688f, +0.382813f,0.179688f, +0.390625f,0.179688f, +0.398438f,0.179688f, +0.40625f,0.179688f, +0.414063f,0.179688f, +0.421875f,0.179688f, +0.429688f,0.179688f, +0.4375f,0.179688f, +0.445313f,0.179688f, +0.453125f,0.179688f, +0.460938f,0.179688f, +0.46875f,0.179688f, +0.476563f,0.179688f, +0.484375f,0.179688f, +0.492188f,0.179688f, +0.5f,0.179688f, +0.507813f,0.179688f, +0.0f,0.1875f, +0.0078125f,0.1875f, +0.015625f,0.1875f, +0.0234375f,0.1875f, +0.03125f,0.1875f, +0.0390625f,0.1875f, +0.046875f,0.1875f, +0.0546875f,0.1875f, +0.0625f,0.1875f, +0.0703125f,0.1875f, +0.078125f,0.1875f, +0.0859375f,0.1875f, +0.09375f,0.1875f, +0.101563f,0.1875f, +0.109375f,0.1875f, +0.117188f,0.1875f, +0.125f,0.1875f, +0.132813f,0.1875f, +0.140625f,0.1875f, +0.148438f,0.1875f, +0.15625f,0.1875f, +0.164063f,0.1875f, +0.171875f,0.1875f, +0.179688f,0.1875f, +0.1875f,0.1875f, +0.195313f,0.1875f, +0.203125f,0.1875f, +0.210938f,0.1875f, +0.21875f,0.1875f, +0.226563f,0.1875f, +0.234375f,0.1875f, +0.242188f,0.1875f, +0.25f,0.1875f, +0.257813f,0.1875f, +0.265625f,0.1875f, +0.273438f,0.1875f, +0.28125f,0.1875f, +0.289063f,0.1875f, +0.296875f,0.1875f, +0.304688f,0.1875f, +0.3125f,0.1875f, +0.320313f,0.1875f, +0.328125f,0.1875f, +0.335938f,0.1875f, +0.34375f,0.1875f, +0.351563f,0.1875f, +0.359375f,0.1875f, +0.367188f,0.1875f, +0.375f,0.1875f, +0.382813f,0.1875f, +0.390625f,0.1875f, +0.398438f,0.1875f, +0.40625f,0.1875f, +0.414063f,0.1875f, +0.421875f,0.1875f, +0.429688f,0.1875f, +0.4375f,0.1875f, +0.445313f,0.1875f, +0.453125f,0.1875f, +0.460938f,0.1875f, +0.46875f,0.1875f, +0.476563f,0.1875f, +0.484375f,0.1875f, +0.492188f,0.1875f, +0.5f,0.1875f, +0.507813f,0.1875f, +0.0f,0.195313f, +0.0078125f,0.195313f, +0.015625f,0.195313f, +0.0234375f,0.195313f, +0.03125f,0.195313f, +0.0390625f,0.195313f, +0.046875f,0.195313f, +0.0546875f,0.195313f, +0.0625f,0.195313f, +0.0703125f,0.195313f, +0.078125f,0.195313f, +0.0859375f,0.195313f, +0.09375f,0.195313f, +0.101563f,0.195313f, +0.109375f,0.195313f, +0.117188f,0.195313f, +0.125f,0.195313f, +0.132813f,0.195313f, +0.140625f,0.195313f, +0.148438f,0.195313f, +0.15625f,0.195313f, +0.164063f,0.195313f, +0.171875f,0.195313f, +0.179688f,0.195313f, +0.1875f,0.195313f, +0.195313f,0.195313f, +0.203125f,0.195313f, +0.210938f,0.195313f, +0.21875f,0.195313f, +0.226563f,0.195313f, +0.234375f,0.195313f, +0.242188f,0.195313f, +0.25f,0.195313f, +0.257813f,0.195313f, +0.265625f,0.195313f, +0.273438f,0.195313f, +0.28125f,0.195313f, +0.289063f,0.195313f, +0.296875f,0.195313f, +0.304688f,0.195313f, +0.3125f,0.195313f, +0.320313f,0.195313f, +0.328125f,0.195313f, +0.335938f,0.195313f, +0.34375f,0.195313f, +0.351563f,0.195313f, +0.359375f,0.195313f, +0.367188f,0.195313f, +0.375f,0.195313f, +0.382813f,0.195313f, +0.390625f,0.195313f, +0.398438f,0.195313f, +0.40625f,0.195313f, +0.414063f,0.195313f, +0.421875f,0.195313f, +0.429688f,0.195313f, +0.4375f,0.195313f, +0.445313f,0.195313f, +0.453125f,0.195313f, +0.460938f,0.195313f, +0.46875f,0.195313f, +0.476563f,0.195313f, +0.484375f,0.195313f, +0.492188f,0.195313f, +0.5f,0.195313f, +0.507813f,0.195313f, +0.0f,0.203125f, +0.0078125f,0.203125f, +0.015625f,0.203125f, +0.0234375f,0.203125f, +0.03125f,0.203125f, +0.0390625f,0.203125f, +0.046875f,0.203125f, +0.0546875f,0.203125f, +0.0625f,0.203125f, +0.0703125f,0.203125f, +0.078125f,0.203125f, +0.0859375f,0.203125f, +0.09375f,0.203125f, +0.101563f,0.203125f, +0.109375f,0.203125f, +0.117188f,0.203125f, +0.125f,0.203125f, +0.132813f,0.203125f, +0.140625f,0.203125f, +0.148438f,0.203125f, +0.15625f,0.203125f, +0.164063f,0.203125f, +0.171875f,0.203125f, +0.179688f,0.203125f, +0.1875f,0.203125f, +0.195313f,0.203125f, +0.203125f,0.203125f, +0.210938f,0.203125f, +0.21875f,0.203125f, +0.226563f,0.203125f, +0.234375f,0.203125f, +0.242188f,0.203125f, +0.25f,0.203125f, +0.257813f,0.203125f, +0.265625f,0.203125f, +0.273438f,0.203125f, +0.28125f,0.203125f, +0.289063f,0.203125f, +0.296875f,0.203125f, +0.304688f,0.203125f, +0.3125f,0.203125f, +0.320313f,0.203125f, +0.328125f,0.203125f, +0.335938f,0.203125f, +0.34375f,0.203125f, +0.351563f,0.203125f, +0.359375f,0.203125f, +0.367188f,0.203125f, +0.375f,0.203125f, +0.382813f,0.203125f, +0.390625f,0.203125f, +0.398438f,0.203125f, +0.40625f,0.203125f, +0.414063f,0.203125f, +0.421875f,0.203125f, +0.429688f,0.203125f, +0.4375f,0.203125f, +0.445313f,0.203125f, +0.453125f,0.203125f, +0.460938f,0.203125f, +0.46875f,0.203125f, +0.476563f,0.203125f, +0.484375f,0.203125f, +0.492188f,0.203125f, +0.5f,0.203125f, +0.507813f,0.203125f, +0.0f,0.210938f, +0.0078125f,0.210938f, +0.015625f,0.210938f, +0.0234375f,0.210938f, +0.03125f,0.210938f, +0.0390625f,0.210938f, +0.046875f,0.210938f, +0.0546875f,0.210938f, +0.0625f,0.210938f, +0.0703125f,0.210938f, +0.078125f,0.210938f, +0.0859375f,0.210938f, +0.09375f,0.210938f, +0.101563f,0.210938f, +0.109375f,0.210938f, +0.117188f,0.210938f, +0.125f,0.210938f, +0.132813f,0.210938f, +0.140625f,0.210938f, +0.148438f,0.210938f, +0.15625f,0.210938f, +0.164063f,0.210938f, +0.171875f,0.210938f, +0.179688f,0.210938f, +0.1875f,0.210938f, +0.195313f,0.210938f, +0.203125f,0.210938f, +0.210938f,0.210938f, +0.21875f,0.210938f, +0.226563f,0.210938f, +0.234375f,0.210938f, +0.242188f,0.210938f, +0.25f,0.210938f, +0.257813f,0.210938f, +0.265625f,0.210938f, +0.273438f,0.210938f, +0.28125f,0.210938f, +0.289063f,0.210938f, +0.296875f,0.210938f, +0.304688f,0.210938f, +0.3125f,0.210938f, +0.320313f,0.210938f, +0.328125f,0.210938f, +0.335938f,0.210938f, +0.34375f,0.210938f, +0.351563f,0.210938f, +0.359375f,0.210938f, +0.367188f,0.210938f, +0.375f,0.210938f, +0.382813f,0.210938f, +0.390625f,0.210938f, +0.398438f,0.210938f, +0.40625f,0.210938f, +0.414063f,0.210938f, +0.421875f,0.210938f, +0.429688f,0.210938f, +0.4375f,0.210938f, +0.445313f,0.210938f, +0.453125f,0.210938f, +0.460938f,0.210938f, +0.46875f,0.210938f, +0.476563f,0.210938f, +0.484375f,0.210938f, +0.492188f,0.210938f, +0.5f,0.210938f, +0.507813f,0.210938f, +0.0f,0.21875f, +0.0078125f,0.21875f, +0.015625f,0.21875f, +0.0234375f,0.21875f, +0.03125f,0.21875f, +0.0390625f,0.21875f, +0.046875f,0.21875f, +0.0546875f,0.21875f, +0.0625f,0.21875f, +0.0703125f,0.21875f, +0.078125f,0.21875f, +0.0859375f,0.21875f, +0.09375f,0.21875f, +0.101563f,0.21875f, +0.109375f,0.21875f, +0.117188f,0.21875f, +0.125f,0.21875f, +0.132813f,0.21875f, +0.140625f,0.21875f, +0.148438f,0.21875f, +0.15625f,0.21875f, +0.164063f,0.21875f, +0.171875f,0.21875f, +0.179688f,0.21875f, +0.1875f,0.21875f, +0.195313f,0.21875f, +0.203125f,0.21875f, +0.210938f,0.21875f, +0.21875f,0.21875f, +0.226563f,0.21875f, +0.234375f,0.21875f, +0.242188f,0.21875f, +0.25f,0.21875f, +0.257813f,0.21875f, +0.265625f,0.21875f, +0.273438f,0.21875f, +0.28125f,0.21875f, +0.289063f,0.21875f, +0.296875f,0.21875f, +0.304688f,0.21875f, +0.3125f,0.21875f, +0.320313f,0.21875f, +0.328125f,0.21875f, +0.335938f,0.21875f, +0.34375f,0.21875f, +0.351563f,0.21875f, +0.359375f,0.21875f, +0.367188f,0.21875f, +0.375f,0.21875f, +0.382813f,0.21875f, +0.390625f,0.21875f, +0.398438f,0.21875f, +0.40625f,0.21875f, +0.414063f,0.21875f, +0.421875f,0.21875f, +0.429688f,0.21875f, +0.4375f,0.21875f, +0.445313f,0.21875f, +0.453125f,0.21875f, +0.460938f,0.21875f, +0.46875f,0.21875f, +0.476563f,0.21875f, +0.484375f,0.21875f, +0.492188f,0.21875f, +0.5f,0.21875f, +0.507813f,0.21875f, +0.0f,0.226563f, +0.0078125f,0.226563f, +0.015625f,0.226563f, +0.0234375f,0.226563f, +0.03125f,0.226563f, +0.0390625f,0.226563f, +0.046875f,0.226563f, +0.0546875f,0.226563f, +0.0625f,0.226563f, +0.0703125f,0.226563f, +0.078125f,0.226563f, +0.0859375f,0.226563f, +0.09375f,0.226563f, +0.101563f,0.226563f, +0.109375f,0.226563f, +0.117188f,0.226563f, +0.125f,0.226563f, +0.132813f,0.226563f, +0.140625f,0.226563f, +0.148438f,0.226563f, +0.15625f,0.226563f, +0.164063f,0.226563f, +0.171875f,0.226563f, +0.179688f,0.226563f, +0.1875f,0.226563f, +0.195313f,0.226563f, +0.203125f,0.226563f, +0.210938f,0.226563f, +0.21875f,0.226563f, +0.226563f,0.226563f, +0.234375f,0.226563f, +0.242188f,0.226563f, +0.25f,0.226563f, +0.257813f,0.226563f, +0.265625f,0.226563f, +0.273438f,0.226563f, +0.28125f,0.226563f, +0.289063f,0.226563f, +0.296875f,0.226563f, +0.304688f,0.226563f, +0.3125f,0.226563f, +0.320313f,0.226563f, +0.328125f,0.226563f, +0.335938f,0.226563f, +0.34375f,0.226563f, +0.351563f,0.226563f, +0.359375f,0.226563f, +0.367188f,0.226563f, +0.375f,0.226563f, +0.382813f,0.226563f, +0.390625f,0.226563f, +0.398438f,0.226563f, +0.40625f,0.226563f, +0.414063f,0.226563f, +0.421875f,0.226563f, +0.429688f,0.226563f, +0.4375f,0.226563f, +0.445313f,0.226563f, +0.453125f,0.226563f, +0.460938f,0.226563f, +0.46875f,0.226563f, +0.476563f,0.226563f, +0.484375f,0.226563f, +0.492188f,0.226563f, +0.5f,0.226563f, +0.507813f,0.226563f, +0.0f,0.234375f, +0.0078125f,0.234375f, +0.015625f,0.234375f, +0.0234375f,0.234375f, +0.03125f,0.234375f, +0.0390625f,0.234375f, +0.046875f,0.234375f, +0.0546875f,0.234375f, +0.0625f,0.234375f, +0.0703125f,0.234375f, +0.078125f,0.234375f, +0.0859375f,0.234375f, +0.09375f,0.234375f, +0.101563f,0.234375f, +0.109375f,0.234375f, +0.117188f,0.234375f, +0.125f,0.234375f, +0.132813f,0.234375f, +0.140625f,0.234375f, +0.148438f,0.234375f, +0.15625f,0.234375f, +0.164063f,0.234375f, +0.171875f,0.234375f, +0.179688f,0.234375f, +0.1875f,0.234375f, +0.195313f,0.234375f, +0.203125f,0.234375f, +0.210938f,0.234375f, +0.21875f,0.234375f, +0.226563f,0.234375f, +0.234375f,0.234375f, +0.242188f,0.234375f, +0.25f,0.234375f, +0.257813f,0.234375f, +0.265625f,0.234375f, +0.273438f,0.234375f, +0.28125f,0.234375f, +0.289063f,0.234375f, +0.296875f,0.234375f, +0.304688f,0.234375f, +0.3125f,0.234375f, +0.320313f,0.234375f, +0.328125f,0.234375f, +0.335938f,0.234375f, +0.34375f,0.234375f, +0.351563f,0.234375f, +0.359375f,0.234375f, +0.367188f,0.234375f, +0.375f,0.234375f, +0.382813f,0.234375f, +0.390625f,0.234375f, +0.398438f,0.234375f, +0.40625f,0.234375f, +0.414063f,0.234375f, +0.421875f,0.234375f, +0.429688f,0.234375f, +0.4375f,0.234375f, +0.445313f,0.234375f, +0.453125f,0.234375f, +0.460938f,0.234375f, +0.46875f,0.234375f, +0.476563f,0.234375f, +0.484375f,0.234375f, +0.492188f,0.234375f, +0.5f,0.234375f, +0.507813f,0.234375f, +0.0f,0.242188f, +0.0078125f,0.242188f, +0.015625f,0.242188f, +0.0234375f,0.242188f, +0.03125f,0.242188f, +0.0390625f,0.242188f, +0.046875f,0.242188f, +0.0546875f,0.242188f, +0.0625f,0.242188f, +0.0703125f,0.242188f, +0.078125f,0.242188f, +0.0859375f,0.242188f, +0.09375f,0.242188f, +0.101563f,0.242188f, +0.109375f,0.242188f, +0.117188f,0.242188f, +0.125f,0.242188f, +0.132813f,0.242188f, +0.140625f,0.242188f, +0.148438f,0.242188f, +0.15625f,0.242188f, +0.164063f,0.242188f, +0.171875f,0.242188f, +0.179688f,0.242188f, +0.1875f,0.242188f, +0.195313f,0.242188f, +0.203125f,0.242188f, +0.210938f,0.242188f, +0.21875f,0.242188f, +0.226563f,0.242188f, +0.234375f,0.242188f, +0.242188f,0.242188f, +0.25f,0.242188f, +0.257813f,0.242188f, +0.265625f,0.242188f, +0.273438f,0.242188f, +0.28125f,0.242188f, +0.289063f,0.242188f, +0.296875f,0.242188f, +0.304688f,0.242188f, +0.3125f,0.242188f, +0.320313f,0.242188f, +0.328125f,0.242188f, +0.335938f,0.242188f, +0.34375f,0.242188f, +0.351563f,0.242188f, +0.359375f,0.242188f, +0.367188f,0.242188f, +0.375f,0.242188f, +0.382813f,0.242188f, +0.390625f,0.242188f, +0.398438f,0.242188f, +0.40625f,0.242188f, +0.414063f,0.242188f, +0.421875f,0.242188f, +0.429688f,0.242188f, +0.4375f,0.242188f, +0.445313f,0.242188f, +0.453125f,0.242188f, +0.460938f,0.242188f, +0.46875f,0.242188f, +0.476563f,0.242188f, +0.484375f,0.242188f, +0.492188f,0.242188f, +0.5f,0.242188f, +0.507813f,0.242188f, +0.0f,0.25f, +0.0078125f,0.25f, +0.015625f,0.25f, +0.0234375f,0.25f, +0.03125f,0.25f, +0.0390625f,0.25f, +0.046875f,0.25f, +0.0546875f,0.25f, +0.0625f,0.25f, +0.0703125f,0.25f, +0.078125f,0.25f, +0.0859375f,0.25f, +0.09375f,0.25f, +0.101563f,0.25f, +0.109375f,0.25f, +0.117188f,0.25f, +0.125f,0.25f, +0.132813f,0.25f, +0.140625f,0.25f, +0.148438f,0.25f, +0.15625f,0.25f, +0.164063f,0.25f, +0.171875f,0.25f, +0.179688f,0.25f, +0.1875f,0.25f, +0.195313f,0.25f, +0.203125f,0.25f, +0.210938f,0.25f, +0.21875f,0.25f, +0.226563f,0.25f, +0.234375f,0.25f, +0.242188f,0.25f, +0.25f,0.25f, +0.257813f,0.25f, +0.265625f,0.25f, +0.273438f,0.25f, +0.28125f,0.25f, +0.289063f,0.25f, +0.296875f,0.25f, +0.304688f,0.25f, +0.3125f,0.25f, +0.320313f,0.25f, +0.328125f,0.25f, +0.335938f,0.25f, +0.34375f,0.25f, +0.351563f,0.25f, +0.359375f,0.25f, +0.367188f,0.25f, +0.375f,0.25f, +0.382813f,0.25f, +0.390625f,0.25f, +0.398438f,0.25f, +0.40625f,0.25f, +0.414063f,0.25f, +0.421875f,0.25f, +0.429688f,0.25f, +0.4375f,0.25f, +0.445313f,0.25f, +0.453125f,0.25f, +0.460938f,0.25f, +0.46875f,0.25f, +0.476563f,0.25f, +0.484375f,0.25f, +0.492188f,0.25f, +0.5f,0.25f, +0.507813f,0.25f, +0.0f,0.257813f, +0.0078125f,0.257813f, +0.015625f,0.257813f, +0.0234375f,0.257813f, +0.03125f,0.257813f, +0.0390625f,0.257813f, +0.046875f,0.257813f, +0.0546875f,0.257813f, +0.0625f,0.257813f, +0.0703125f,0.257813f, +0.078125f,0.257813f, +0.0859375f,0.257813f, +0.09375f,0.257813f, +0.101563f,0.257813f, +0.109375f,0.257813f, +0.117188f,0.257813f, +0.125f,0.257813f, +0.132813f,0.257813f, +0.140625f,0.257813f, +0.148438f,0.257813f, +0.15625f,0.257813f, +0.164063f,0.257813f, +0.171875f,0.257813f, +0.179688f,0.257813f, +0.1875f,0.257813f, +0.195313f,0.257813f, +0.203125f,0.257813f, +0.210938f,0.257813f, +0.21875f,0.257813f, +0.226563f,0.257813f, +0.234375f,0.257813f, +0.242188f,0.257813f, +0.25f,0.257813f, +0.257813f,0.257813f, +0.265625f,0.257813f, +0.273438f,0.257813f, +0.28125f,0.257813f, +0.289063f,0.257813f, +0.296875f,0.257813f, +0.304688f,0.257813f, +0.3125f,0.257813f, +0.320313f,0.257813f, +0.328125f,0.257813f, +0.335938f,0.257813f, +0.34375f,0.257813f, +0.351563f,0.257813f, +0.359375f,0.257813f, +0.367188f,0.257813f, +0.375f,0.257813f, +0.382813f,0.257813f, +0.390625f,0.257813f, +0.398438f,0.257813f, +0.40625f,0.257813f, +0.414063f,0.257813f, +0.421875f,0.257813f, +0.429688f,0.257813f, +0.4375f,0.257813f, +0.445313f,0.257813f, +0.453125f,0.257813f, +0.460938f,0.257813f, +0.46875f,0.257813f, +0.476563f,0.257813f, +0.484375f,0.257813f, +0.492188f,0.257813f, +0.5f,0.257813f, +0.507813f,0.257813f, +0.0f,0.265625f, +0.0078125f,0.265625f, +0.015625f,0.265625f, +0.0234375f,0.265625f, +0.03125f,0.265625f, +0.0390625f,0.265625f, +0.046875f,0.265625f, +0.0546875f,0.265625f, +0.0625f,0.265625f, +0.0703125f,0.265625f, +0.078125f,0.265625f, +0.0859375f,0.265625f, +0.09375f,0.265625f, +0.101563f,0.265625f, +0.109375f,0.265625f, +0.117188f,0.265625f, +0.125f,0.265625f, +0.132813f,0.265625f, +0.140625f,0.265625f, +0.148438f,0.265625f, +0.15625f,0.265625f, +0.164063f,0.265625f, +0.171875f,0.265625f, +0.179688f,0.265625f, +0.1875f,0.265625f, +0.195313f,0.265625f, +0.203125f,0.265625f, +0.210938f,0.265625f, +0.21875f,0.265625f, +0.226563f,0.265625f, +0.234375f,0.265625f, +0.242188f,0.265625f, +0.25f,0.265625f, +0.257813f,0.265625f, +0.265625f,0.265625f, +0.273438f,0.265625f, +0.28125f,0.265625f, +0.289063f,0.265625f, +0.296875f,0.265625f, +0.304688f,0.265625f, +0.3125f,0.265625f, +0.320313f,0.265625f, +0.328125f,0.265625f, +0.335938f,0.265625f, +0.34375f,0.265625f, +0.351563f,0.265625f, +0.359375f,0.265625f, +0.367188f,0.265625f, +0.375f,0.265625f, +0.382813f,0.265625f, +0.390625f,0.265625f, +0.398438f,0.265625f, +0.40625f,0.265625f, +0.414063f,0.265625f, +0.421875f,0.265625f, +0.429688f,0.265625f, +0.4375f,0.265625f, +0.445313f,0.265625f, +0.453125f,0.265625f, +0.460938f,0.265625f, +0.46875f,0.265625f, +0.476563f,0.265625f, +0.484375f,0.265625f, +0.492188f,0.265625f, +0.5f,0.265625f, +0.507813f,0.265625f, +}; + +unsigned short Landscape06Idx[] = { +0,1,2, +3,2,1, +2,3,4, +5,4,3, +4,5,6, +7,6,5, +6,7,8, +9,8,7, +8,9,10, +11,10,9, +10,11,12, +13,12,11, +12,13,14, +15,14,13, +14,15,16, +17,16,15, +16,17,18, +19,18,17, +18,19,20, +21,20,19, +20,21,22, +23,22,21, +22,23,24, +25,24,23, +24,25,26, +27,26,25, +26,27,28, +29,28,27, +28,29,30, +31,30,29, +30,31,32, +33,32,31, +32,33,34, +35,34,33, +34,35,36, +37,36,35, +36,37,38, +39,38,37, +38,39,40, +41,40,39, +40,41,42, +43,42,41, +42,43,44, +45,44,43, +44,45,46, +47,46,45, +46,47,48, +49,48,47, +48,49,50, +51,50,49, +50,51,52, +53,52,51, +52,53,54, +55,54,53, +54,55,56, +57,56,55, +56,57,58, +59,58,57, +58,59,60, +61,60,59, +60,61,62, +63,62,61, +62,63,64, +65,64,63, +64,65,66, +67,66,65, +66,67,68, +69,68,67, +68,69,70, +71,70,69, +70,71,72, +73,72,71, +72,73,74, +75,74,73, +74,75,76, +77,76,75, +76,77,78, +79,78,77, +78,79,80, +81,80,79, +80,81,82, +83,82,81, +82,83,84, +85,84,83, +84,85,86, +87,86,85, +86,87,88, +89,88,87, +88,89,90, +91,90,89, +90,91,92, +93,92,91, +92,93,94, +95,94,93, +94,95,96, +97,96,95, +96,97,98, +99,98,97, +98,99,100, +101,100,99, +100,101,102, +103,102,101, +102,103,104, +105,104,103, +104,105,106, +107,106,105, +106,107,108, +109,108,107, +108,109,110, +111,110,109, +110,111,112, +113,112,111, +112,113,114, +115,114,113, +114,115,116, +117,116,115, +116,117,118, +119,118,117, +118,119,120, +121,120,119, +120,121,122, +123,122,121, +122,123,124, +125,124,123, +124,125,126, +127,126,125, +126,127,128, +129,128,127, +128,129,130, +131,130,129, +132,0,133, +2,133,0, +133,2,134, +4,134,2, +134,4,135, +6,135,4, +135,6,136, +8,136,6, +136,8,137, +10,137,8, +137,10,138, +12,138,10, +138,12,139, +14,139,12, +139,14,140, +16,140,14, +140,16,141, +18,141,16, +141,18,142, +20,142,18, +142,20,143, +22,143,20, +143,22,144, +24,144,22, +144,24,145, +26,145,24, +145,26,146, +28,146,26, +146,28,147, +30,147,28, +147,30,148, +32,148,30, +148,32,149, +34,149,32, +149,34,150, +36,150,34, +150,36,151, +38,151,36, +151,38,152, +40,152,38, +152,40,153, +42,153,40, +153,42,154, +44,154,42, +154,44,155, +46,155,44, +155,46,156, +48,156,46, +156,48,157, +50,157,48, +157,50,158, +52,158,50, +158,52,159, +54,159,52, +159,54,160, +56,160,54, +160,56,161, +58,161,56, +161,58,162, +60,162,58, +162,60,163, +62,163,60, +163,62,164, +64,164,62, +164,64,165, +66,165,64, +165,66,166, +68,166,66, +166,68,167, +70,167,68, +167,70,168, +72,168,70, +168,72,169, +74,169,72, +169,74,170, +76,170,74, +170,76,171, +78,171,76, +171,78,172, +80,172,78, +172,80,173, +82,173,80, +173,82,174, +84,174,82, +174,84,175, +86,175,84, +175,86,176, +88,176,86, +176,88,177, +90,177,88, +177,90,178, +92,178,90, +178,92,179, +94,179,92, +179,94,180, +96,180,94, +180,96,181, +98,181,96, +181,98,182, +100,182,98, +182,100,183, +102,183,100, +183,102,184, +104,184,102, +184,104,185, +106,185,104, +185,106,186, +108,186,106, +186,108,187, +110,187,108, +187,110,188, +112,188,110, +188,112,189, +114,189,112, +189,114,190, +116,190,114, +190,116,191, +118,191,116, +191,118,192, +120,192,118, +192,120,193, +122,193,120, +193,122,194, +124,194,122, +194,124,195, +126,195,124, +195,126,196, +128,196,126, +196,128,197, +130,197,128, +198,132,199, +133,199,132, +199,133,200, +134,200,133, +200,134,201, +135,201,134, +201,135,202, +136,202,135, +202,136,203, +137,203,136, +203,137,204, +138,204,137, +204,138,205, +139,205,138, +205,139,206, +140,206,139, +206,140,207, +141,207,140, +207,141,208, +142,208,141, +208,142,209, +143,209,142, +209,143,210, +144,210,143, +210,144,211, +145,211,144, +211,145,212, +146,212,145, +212,146,213, +147,213,146, +213,147,214, +148,214,147, +214,148,215, +149,215,148, +215,149,216, +150,216,149, +216,150,217, +151,217,150, +217,151,218, +152,218,151, +218,152,219, +153,219,152, +219,153,220, +154,220,153, +220,154,221, +155,221,154, +221,155,222, +156,222,155, +222,156,223, +157,223,156, +223,157,224, +158,224,157, +224,158,225, +159,225,158, +225,159,226, +160,226,159, +226,160,227, +161,227,160, +227,161,228, +162,228,161, +228,162,229, +163,229,162, +229,163,230, +164,230,163, +230,164,231, +165,231,164, +231,165,232, +166,232,165, +232,166,233, +167,233,166, +233,167,234, +168,234,167, +234,168,235, +169,235,168, +235,169,236, +170,236,169, +236,170,237, +171,237,170, +237,171,238, +172,238,171, +238,172,239, +173,239,172, +239,173,240, +174,240,173, +240,174,241, +175,241,174, +241,175,242, +176,242,175, +242,176,243, +177,243,176, +243,177,244, +178,244,177, +244,178,245, +179,245,178, +245,179,246, +180,246,179, +246,180,247, +181,247,180, +247,181,248, +182,248,181, +248,182,249, +183,249,182, +249,183,250, +184,250,183, +250,184,251, +185,251,184, +251,185,252, +186,252,185, +252,186,253, +187,253,186, +253,187,254, +188,254,187, +254,188,255, +189,255,188, +255,189,256, +190,256,189, +256,190,257, +191,257,190, +257,191,258, +192,258,191, +258,192,259, +193,259,192, +259,193,260, +194,260,193, +260,194,261, +195,261,194, +261,195,262, +196,262,195, +262,196,263, +197,263,196, +264,198,265, +199,265,198, +265,199,266, +200,266,199, +266,200,267, +201,267,200, +267,201,268, +202,268,201, +268,202,269, +203,269,202, +269,203,270, +204,270,203, +270,204,271, +205,271,204, +271,205,272, +206,272,205, +272,206,273, +207,273,206, +273,207,274, +208,274,207, +274,208,275, +209,275,208, +275,209,276, +210,276,209, +276,210,277, +211,277,210, +277,211,278, +212,278,211, +278,212,279, +213,279,212, +279,213,280, +214,280,213, +280,214,281, +215,281,214, +281,215,282, +216,282,215, +282,216,283, +217,283,216, +283,217,284, +218,284,217, +284,218,285, +219,285,218, +285,219,286, +220,286,219, +286,220,287, +221,287,220, +287,221,288, +222,288,221, +288,222,289, +223,289,222, +289,223,290, +224,290,223, +290,224,291, +225,291,224, +291,225,292, +226,292,225, +292,226,293, +227,293,226, +293,227,294, +228,294,227, +294,228,295, +229,295,228, +295,229,296, +230,296,229, +296,230,297, +231,297,230, +297,231,298, +232,298,231, +298,232,299, +233,299,232, +299,233,300, +234,300,233, +300,234,301, +235,301,234, +301,235,302, +236,302,235, +302,236,303, +237,303,236, +303,237,304, +238,304,237, +304,238,305, +239,305,238, +305,239,306, +240,306,239, +306,240,307, +241,307,240, +307,241,308, +242,308,241, +308,242,309, +243,309,242, +309,243,310, +244,310,243, +310,244,311, +245,311,244, +311,245,312, +246,312,245, +312,246,313, +247,313,246, +313,247,314, +248,314,247, +314,248,315, +249,315,248, +315,249,316, +250,316,249, +316,250,317, +251,317,250, +317,251,318, +252,318,251, +318,252,319, +253,319,252, +319,253,320, +254,320,253, +320,254,321, +255,321,254, +321,255,322, +256,322,255, +322,256,323, +257,323,256, +323,257,324, +258,324,257, +324,258,325, +259,325,258, +325,259,326, +260,326,259, +326,260,327, +261,327,260, +327,261,328, +262,328,261, +328,262,329, +263,329,262, +330,264,331, +265,331,264, +331,265,332, +266,332,265, +332,266,333, +267,333,266, +333,267,334, +268,334,267, +334,268,335, +269,335,268, +335,269,336, +270,336,269, +336,270,337, +271,337,270, +337,271,338, +272,338,271, +338,272,339, +273,339,272, +339,273,340, +274,340,273, +340,274,341, +275,341,274, +341,275,342, +276,342,275, +342,276,343, +277,343,276, +343,277,344, +278,344,277, +344,278,345, +279,345,278, +345,279,346, +280,346,279, +346,280,347, +281,347,280, +347,281,348, +282,348,281, +348,282,349, +283,349,282, +349,283,350, +284,350,283, +350,284,351, +285,351,284, +351,285,352, +286,352,285, +352,286,353, +287,353,286, +353,287,354, +288,354,287, +354,288,355, +289,355,288, +355,289,356, +290,356,289, +356,290,357, +291,357,290, +357,291,358, +292,358,291, +358,292,359, +293,359,292, +359,293,360, +294,360,293, +360,294,361, +295,361,294, +361,295,362, +296,362,295, +362,296,363, +297,363,296, +363,297,364, +298,364,297, +364,298,365, +299,365,298, +365,299,366, +300,366,299, +366,300,367, +301,367,300, +367,301,368, +302,368,301, +368,302,369, +303,369,302, +369,303,370, +304,370,303, +370,304,371, +305,371,304, +371,305,372, +306,372,305, +372,306,373, +307,373,306, +373,307,374, +308,374,307, +374,308,375, +309,375,308, +375,309,376, +310,376,309, +376,310,377, +311,377,310, +377,311,378, +312,378,311, +378,312,379, +313,379,312, +379,313,380, +314,380,313, +380,314,381, +315,381,314, +381,315,382, +316,382,315, +382,316,383, +317,383,316, +383,317,384, +318,384,317, +384,318,385, +319,385,318, +385,319,386, +320,386,319, +386,320,387, +321,387,320, +387,321,388, +322,388,321, +388,322,389, +323,389,322, +389,323,390, +324,390,323, +390,324,391, +325,391,324, +391,325,392, +326,392,325, +392,326,393, +327,393,326, +393,327,394, +328,394,327, +394,328,395, +329,395,328, +396,330,397, +331,397,330, +397,331,398, +332,398,331, +398,332,399, +333,399,332, +399,333,400, +334,400,333, +400,334,401, +335,401,334, +401,335,402, +336,402,335, +402,336,403, +337,403,336, +403,337,404, +338,404,337, +404,338,405, +339,405,338, +405,339,406, +340,406,339, +406,340,407, +341,407,340, +407,341,408, +342,408,341, +408,342,409, +343,409,342, +409,343,410, +344,410,343, +410,344,411, +345,411,344, +411,345,412, +346,412,345, +412,346,413, +347,413,346, +413,347,414, +348,414,347, +414,348,415, +349,415,348, +415,349,416, +350,416,349, +416,350,417, +351,417,350, +417,351,418, +352,418,351, +418,352,419, +353,419,352, +419,353,420, +354,420,353, +420,354,421, +355,421,354, +421,355,422, +356,422,355, +422,356,423, +357,423,356, +423,357,424, +358,424,357, +424,358,425, +359,425,358, +425,359,426, +360,426,359, +426,360,427, +361,427,360, +427,361,428, +362,428,361, +428,362,429, +363,429,362, +429,363,430, +364,430,363, +430,364,431, +365,431,364, +431,365,432, +366,432,365, +432,366,433, +367,433,366, +433,367,434, +368,434,367, +434,368,435, +369,435,368, +435,369,436, +370,436,369, +436,370,437, +371,437,370, +437,371,438, +372,438,371, +438,372,439, +373,439,372, +439,373,440, +374,440,373, +440,374,441, +375,441,374, +441,375,442, +376,442,375, +442,376,443, +377,443,376, +443,377,444, +378,444,377, +444,378,445, +379,445,378, +445,379,446, +380,446,379, +446,380,447, +381,447,380, +447,381,448, +382,448,381, +448,382,449, +383,449,382, +449,383,450, +384,450,383, +450,384,451, +385,451,384, +451,385,452, +386,452,385, +452,386,453, +387,453,386, +453,387,454, +388,454,387, +454,388,455, +389,455,388, +455,389,456, +390,456,389, +456,390,457, +391,457,390, +457,391,458, +392,458,391, +458,392,459, +393,459,392, +459,393,460, +394,460,393, +460,394,461, +395,461,394, +462,396,463, +397,463,396, +463,397,464, +398,464,397, +464,398,465, +399,465,398, +465,399,466, +400,466,399, +466,400,467, +401,467,400, +467,401,468, +402,468,401, +468,402,469, +403,469,402, +469,403,470, +404,470,403, +470,404,471, +405,471,404, +471,405,472, +406,472,405, +472,406,473, +407,473,406, +473,407,474, +408,474,407, +474,408,475, +409,475,408, +475,409,476, +410,476,409, +476,410,477, +411,477,410, +477,411,478, +412,478,411, +478,412,479, +413,479,412, +479,413,480, +414,480,413, +480,414,481, +415,481,414, +481,415,482, +416,482,415, +482,416,483, +417,483,416, +483,417,484, +418,484,417, +484,418,485, +419,485,418, +485,419,486, +420,486,419, +486,420,487, +421,487,420, +487,421,488, +422,488,421, +488,422,489, +423,489,422, +489,423,490, +424,490,423, +490,424,491, +425,491,424, +491,425,492, +426,492,425, +492,426,493, +427,493,426, +493,427,494, +428,494,427, +494,428,495, +429,495,428, +495,429,496, +430,496,429, +496,430,497, +431,497,430, +497,431,498, +432,498,431, +498,432,499, +433,499,432, +499,433,500, +434,500,433, +500,434,501, +435,501,434, +501,435,502, +436,502,435, +502,436,503, +437,503,436, +503,437,504, +438,504,437, +504,438,505, +439,505,438, +505,439,506, +440,506,439, +506,440,507, +441,507,440, +507,441,508, +442,508,441, +508,442,509, +443,509,442, +509,443,510, +444,510,443, +510,444,511, +445,511,444, +511,445,512, +446,512,445, +512,446,513, +447,513,446, +513,447,514, +448,514,447, +514,448,515, +449,515,448, +515,449,516, +450,516,449, +516,450,517, +451,517,450, +517,451,518, +452,518,451, +518,452,519, +453,519,452, +519,453,520, +454,520,453, +520,454,521, +455,521,454, +521,455,522, +456,522,455, +522,456,523, +457,523,456, +523,457,524, +458,524,457, +524,458,525, +459,525,458, +525,459,526, +460,526,459, +526,460,527, +461,527,460, +528,462,529, +463,529,462, +529,463,530, +464,530,463, +530,464,531, +465,531,464, +531,465,532, +466,532,465, +532,466,533, +467,533,466, +533,467,534, +468,534,467, +534,468,535, +469,535,468, +535,469,536, +470,536,469, +536,470,537, +471,537,470, +537,471,538, +472,538,471, +538,472,539, +473,539,472, +539,473,540, +474,540,473, +540,474,541, +475,541,474, +541,475,542, +476,542,475, +542,476,543, +477,543,476, +543,477,544, +478,544,477, +544,478,545, +479,545,478, +545,479,546, +480,546,479, +546,480,547, +481,547,480, +547,481,548, +482,548,481, +548,482,549, +483,549,482, +549,483,550, +484,550,483, +550,484,551, +485,551,484, +551,485,552, +486,552,485, +552,486,553, +487,553,486, +553,487,554, +488,554,487, +554,488,555, +489,555,488, +555,489,556, +490,556,489, +556,490,557, +491,557,490, +557,491,558, +492,558,491, +558,492,559, +493,559,492, +559,493,560, +494,560,493, +560,494,561, +495,561,494, +561,495,562, +496,562,495, +562,496,563, +497,563,496, +563,497,564, +498,564,497, +564,498,565, +499,565,498, +565,499,566, +500,566,499, +566,500,567, +501,567,500, +567,501,568, +502,568,501, +568,502,569, +503,569,502, +569,503,570, +504,570,503, +570,504,571, +505,571,504, +571,505,572, +506,572,505, +572,506,573, +507,573,506, +573,507,574, +508,574,507, +574,508,575, +509,575,508, +575,509,576, +510,576,509, +576,510,577, +511,577,510, +577,511,578, +512,578,511, +578,512,579, +513,579,512, +579,513,580, +514,580,513, +580,514,581, +515,581,514, +581,515,582, +516,582,515, +582,516,583, +517,583,516, +583,517,584, +518,584,517, +584,518,585, +519,585,518, +585,519,586, +520,586,519, +586,520,587, +521,587,520, +587,521,588, +522,588,521, +588,522,589, +523,589,522, +589,523,590, +524,590,523, +590,524,591, +525,591,524, +591,525,592, +526,592,525, +592,526,593, +527,593,526, +594,528,595, +529,595,528, +595,529,596, +530,596,529, +596,530,597, +531,597,530, +597,531,598, +532,598,531, +598,532,599, +533,599,532, +599,533,600, +534,600,533, +600,534,601, +535,601,534, +601,535,602, +536,602,535, +602,536,603, +537,603,536, +603,537,604, +538,604,537, +604,538,605, +539,605,538, +605,539,606, +540,606,539, +606,540,607, +541,607,540, +607,541,608, +542,608,541, +608,542,609, +543,609,542, +609,543,610, +544,610,543, +610,544,611, +545,611,544, +611,545,612, +546,612,545, +612,546,613, +547,613,546, +613,547,614, +548,614,547, +614,548,615, +549,615,548, +615,549,616, +550,616,549, +616,550,617, +551,617,550, +617,551,618, +552,618,551, +618,552,619, +553,619,552, +619,553,620, +554,620,553, +620,554,621, +555,621,554, +621,555,622, +556,622,555, +622,556,623, +557,623,556, +623,557,624, +558,624,557, +624,558,625, +559,625,558, +625,559,626, +560,626,559, +626,560,627, +561,627,560, +627,561,628, +562,628,561, +628,562,629, +563,629,562, +629,563,630, +564,630,563, +630,564,631, +565,631,564, +631,565,632, +566,632,565, +632,566,633, +567,633,566, +633,567,634, +568,634,567, +634,568,635, +569,635,568, +635,569,636, +570,636,569, +636,570,637, +571,637,570, +637,571,638, +572,638,571, +638,572,639, +573,639,572, +639,573,640, +574,640,573, +640,574,641, +575,641,574, +641,575,642, +576,642,575, +642,576,643, +577,643,576, +643,577,644, +578,644,577, +644,578,645, +579,645,578, +645,579,646, +580,646,579, +646,580,647, +581,647,580, +647,581,648, +582,648,581, +648,582,649, +583,649,582, +649,583,650, +584,650,583, +650,584,651, +585,651,584, +651,585,652, +586,652,585, +652,586,653, +587,653,586, +653,587,654, +588,654,587, +654,588,655, +589,655,588, +655,589,656, +590,656,589, +656,590,657, +591,657,590, +657,591,658, +592,658,591, +658,592,659, +593,659,592, +660,594,661, +595,661,594, +661,595,662, +596,662,595, +662,596,663, +597,663,596, +663,597,664, +598,664,597, +664,598,665, +599,665,598, +665,599,666, +600,666,599, +666,600,667, +601,667,600, +667,601,668, +602,668,601, +668,602,669, +603,669,602, +669,603,670, +604,670,603, +670,604,671, +605,671,604, +671,605,672, +606,672,605, +672,606,673, +607,673,606, +673,607,674, +608,674,607, +674,608,675, +609,675,608, +675,609,676, +610,676,609, +676,610,677, +611,677,610, +677,611,678, +612,678,611, +678,612,679, +613,679,612, +679,613,680, +614,680,613, +680,614,681, +615,681,614, +681,615,682, +616,682,615, +682,616,683, +617,683,616, +683,617,684, +618,684,617, +684,618,685, +619,685,618, +685,619,686, +620,686,619, +686,620,687, +621,687,620, +687,621,688, +622,688,621, +688,622,689, +623,689,622, +689,623,690, +624,690,623, +690,624,691, +625,691,624, +691,625,692, +626,692,625, +692,626,693, +627,693,626, +693,627,694, +628,694,627, +694,628,695, +629,695,628, +695,629,696, +630,696,629, +696,630,697, +631,697,630, +697,631,698, +632,698,631, +698,632,699, +633,699,632, +699,633,700, +634,700,633, +700,634,701, +635,701,634, +701,635,702, +636,702,635, +702,636,703, +637,703,636, +703,637,704, +638,704,637, +704,638,705, +639,705,638, +705,639,706, +640,706,639, +706,640,707, +641,707,640, +707,641,708, +642,708,641, +708,642,709, +643,709,642, +709,643,710, +644,710,643, +710,644,711, +645,711,644, +711,645,712, +646,712,645, +712,646,713, +647,713,646, +713,647,714, +648,714,647, +714,648,715, +649,715,648, +715,649,716, +650,716,649, +716,650,717, +651,717,650, +717,651,718, +652,718,651, +718,652,719, +653,719,652, +719,653,720, +654,720,653, +720,654,721, +655,721,654, +721,655,722, +656,722,655, +722,656,723, +657,723,656, +723,657,724, +658,724,657, +724,658,725, +659,725,658, +726,660,727, +661,727,660, +727,661,728, +662,728,661, +728,662,729, +663,729,662, +729,663,730, +664,730,663, +730,664,731, +665,731,664, +731,665,732, +666,732,665, +732,666,733, +667,733,666, +733,667,734, +668,734,667, +734,668,735, +669,735,668, +735,669,736, +670,736,669, +736,670,737, +671,737,670, +737,671,738, +672,738,671, +738,672,739, +673,739,672, +739,673,740, +674,740,673, +740,674,741, +675,741,674, +741,675,742, +676,742,675, +742,676,743, +677,743,676, +743,677,744, +678,744,677, +744,678,745, +679,745,678, +745,679,746, +680,746,679, +746,680,747, +681,747,680, +747,681,748, +682,748,681, +748,682,749, +683,749,682, +749,683,750, +684,750,683, +750,684,751, +685,751,684, +751,685,752, +686,752,685, +752,686,753, +687,753,686, +753,687,754, +688,754,687, +754,688,755, +689,755,688, +755,689,756, +690,756,689, +756,690,757, +691,757,690, +757,691,758, +692,758,691, +758,692,759, +693,759,692, +759,693,760, +694,760,693, +760,694,761, +695,761,694, +761,695,762, +696,762,695, +762,696,763, +697,763,696, +763,697,764, +698,764,697, +764,698,765, +699,765,698, +765,699,766, +700,766,699, +766,700,767, +701,767,700, +767,701,768, +702,768,701, +768,702,769, +703,769,702, +769,703,770, +704,770,703, +770,704,771, +705,771,704, +771,705,772, +706,772,705, +772,706,773, +707,773,706, +773,707,774, +708,774,707, +774,708,775, +709,775,708, +775,709,776, +710,776,709, +776,710,777, +711,777,710, +777,711,778, +712,778,711, +778,712,779, +713,779,712, +779,713,780, +714,780,713, +780,714,781, +715,781,714, +781,715,782, +716,782,715, +782,716,783, +717,783,716, +783,717,784, +718,784,717, +784,718,785, +719,785,718, +785,719,786, +720,786,719, +786,720,787, +721,787,720, +787,721,788, +722,788,721, +788,722,789, +723,789,722, +789,723,790, +724,790,723, +790,724,791, +725,791,724, +792,726,793, +727,793,726, +793,727,794, +728,794,727, +794,728,795, +729,795,728, +795,729,796, +730,796,729, +796,730,797, +731,797,730, +797,731,798, +732,798,731, +798,732,799, +733,799,732, +799,733,800, +734,800,733, +800,734,801, +735,801,734, +801,735,802, +736,802,735, +802,736,803, +737,803,736, +803,737,804, +738,804,737, +804,738,805, +739,805,738, +805,739,806, +740,806,739, +806,740,807, +741,807,740, +807,741,808, +742,808,741, +808,742,809, +743,809,742, +809,743,810, +744,810,743, +810,744,811, +745,811,744, +811,745,812, +746,812,745, +812,746,813, +747,813,746, +813,747,814, +748,814,747, +814,748,815, +749,815,748, +815,749,816, +750,816,749, +816,750,817, +751,817,750, +817,751,818, +752,818,751, +818,752,819, +753,819,752, +819,753,820, +754,820,753, +820,754,821, +755,821,754, +821,755,822, +756,822,755, +822,756,823, +757,823,756, +823,757,824, +758,824,757, +824,758,825, +759,825,758, +825,759,826, +760,826,759, +826,760,827, +761,827,760, +827,761,828, +762,828,761, +828,762,829, +763,829,762, +829,763,830, +764,830,763, +830,764,831, +765,831,764, +831,765,832, +766,832,765, +832,766,833, +767,833,766, +833,767,834, +768,834,767, +834,768,835, +769,835,768, +835,769,836, +770,836,769, +836,770,837, +771,837,770, +837,771,838, +772,838,771, +838,772,839, +773,839,772, +839,773,840, +774,840,773, +840,774,841, +775,841,774, +841,775,842, +776,842,775, +842,776,843, +777,843,776, +843,777,844, +778,844,777, +844,778,845, +779,845,778, +845,779,846, +780,846,779, +846,780,847, +781,847,780, +847,781,848, +782,848,781, +848,782,849, +783,849,782, +849,783,850, +784,850,783, +850,784,851, +785,851,784, +851,785,852, +786,852,785, +852,786,853, +787,853,786, +853,787,854, +788,854,787, +854,788,855, +789,855,788, +855,789,856, +790,856,789, +856,790,857, +791,857,790, +858,792,859, +793,859,792, +859,793,860, +794,860,793, +860,794,861, +795,861,794, +861,795,862, +796,862,795, +862,796,863, +797,863,796, +863,797,864, +798,864,797, +864,798,865, +799,865,798, +865,799,866, +800,866,799, +866,800,867, +801,867,800, +867,801,868, +802,868,801, +868,802,869, +803,869,802, +869,803,870, +804,870,803, +870,804,871, +805,871,804, +871,805,872, +806,872,805, +872,806,873, +807,873,806, +873,807,874, +808,874,807, +874,808,875, +809,875,808, +875,809,876, +810,876,809, +876,810,877, +811,877,810, +877,811,878, +812,878,811, +878,812,879, +813,879,812, +879,813,880, +814,880,813, +880,814,881, +815,881,814, +881,815,882, +816,882,815, +882,816,883, +817,883,816, +883,817,884, +818,884,817, +884,818,885, +819,885,818, +885,819,886, +820,886,819, +886,820,887, +821,887,820, +887,821,888, +822,888,821, +888,822,889, +823,889,822, +889,823,890, +824,890,823, +890,824,891, +825,891,824, +891,825,892, +826,892,825, +892,826,893, +827,893,826, +893,827,894, +828,894,827, +894,828,895, +829,895,828, +895,829,896, +830,896,829, +896,830,897, +831,897,830, +897,831,898, +832,898,831, +898,832,899, +833,899,832, +899,833,900, +834,900,833, +900,834,901, +835,901,834, +901,835,902, +836,902,835, +902,836,903, +837,903,836, +903,837,904, +838,904,837, +904,838,905, +839,905,838, +905,839,906, +840,906,839, +906,840,907, +841,907,840, +907,841,908, +842,908,841, +908,842,909, +843,909,842, +909,843,910, +844,910,843, +910,844,911, +845,911,844, +911,845,912, +846,912,845, +912,846,913, +847,913,846, +913,847,914, +848,914,847, +914,848,915, +849,915,848, +915,849,916, +850,916,849, +916,850,917, +851,917,850, +917,851,918, +852,918,851, +918,852,919, +853,919,852, +919,853,920, +854,920,853, +920,854,921, +855,921,854, +921,855,922, +856,922,855, +922,856,923, +857,923,856, +924,858,925, +859,925,858, +925,859,926, +860,926,859, +926,860,927, +861,927,860, +927,861,928, +862,928,861, +928,862,929, +863,929,862, +929,863,930, +864,930,863, +930,864,931, +865,931,864, +931,865,932, +866,932,865, +932,866,933, +867,933,866, +933,867,934, +868,934,867, +934,868,935, +869,935,868, +935,869,936, +870,936,869, +936,870,937, +871,937,870, +937,871,938, +872,938,871, +938,872,939, +873,939,872, +939,873,940, +874,940,873, +940,874,941, +875,941,874, +941,875,942, +876,942,875, +942,876,943, +877,943,876, +943,877,944, +878,944,877, +944,878,945, +879,945,878, +945,879,946, +880,946,879, +946,880,947, +881,947,880, +947,881,948, +882,948,881, +948,882,949, +883,949,882, +949,883,950, +884,950,883, +950,884,951, +885,951,884, +951,885,952, +886,952,885, +952,886,953, +887,953,886, +953,887,954, +888,954,887, +954,888,955, +889,955,888, +955,889,956, +890,956,889, +956,890,957, +891,957,890, +957,891,958, +892,958,891, +958,892,959, +893,959,892, +959,893,960, +894,960,893, +960,894,961, +895,961,894, +961,895,962, +896,962,895, +962,896,963, +897,963,896, +963,897,964, +898,964,897, +964,898,965, +899,965,898, +965,899,966, +900,966,899, +966,900,967, +901,967,900, +967,901,968, +902,968,901, +968,902,969, +903,969,902, +969,903,970, +904,970,903, +970,904,971, +905,971,904, +971,905,972, +906,972,905, +972,906,973, +907,973,906, +973,907,974, +908,974,907, +974,908,975, +909,975,908, +975,909,976, +910,976,909, +976,910,977, +911,977,910, +977,911,978, +912,978,911, +978,912,979, +913,979,912, +979,913,980, +914,980,913, +980,914,981, +915,981,914, +981,915,982, +916,982,915, +982,916,983, +917,983,916, +983,917,984, +918,984,917, +984,918,985, +919,985,918, +985,919,986, +920,986,919, +986,920,987, +921,987,920, +987,921,988, +922,988,921, +988,922,989, +923,989,922, +990,924,991, +925,991,924, +991,925,992, +926,992,925, +992,926,993, +927,993,926, +993,927,994, +928,994,927, +994,928,995, +929,995,928, +995,929,996, +930,996,929, +996,930,997, +931,997,930, +997,931,998, +932,998,931, +998,932,999, +933,999,932, +999,933,1000, +934,1000,933, +1000,934,1001, +935,1001,934, +1001,935,1002, +936,1002,935, +1002,936,1003, +937,1003,936, +1003,937,1004, +938,1004,937, +1004,938,1005, +939,1005,938, +1005,939,1006, +940,1006,939, +1006,940,1007, +941,1007,940, +1007,941,1008, +942,1008,941, +1008,942,1009, +943,1009,942, +1009,943,1010, +944,1010,943, +1010,944,1011, +945,1011,944, +1011,945,1012, +946,1012,945, +1012,946,1013, +947,1013,946, +1013,947,1014, +948,1014,947, +1014,948,1015, +949,1015,948, +1015,949,1016, +950,1016,949, +1016,950,1017, +951,1017,950, +1017,951,1018, +952,1018,951, +1018,952,1019, +953,1019,952, +1019,953,1020, +954,1020,953, +1020,954,1021, +955,1021,954, +1021,955,1022, +956,1022,955, +1022,956,1023, +957,1023,956, +1023,957,1024, +958,1024,957, +1024,958,1025, +959,1025,958, +1025,959,1026, +960,1026,959, +1026,960,1027, +961,1027,960, +1027,961,1028, +962,1028,961, +1028,962,1029, +963,1029,962, +1029,963,1030, +964,1030,963, +1030,964,1031, +965,1031,964, +1031,965,1032, +966,1032,965, +1032,966,1033, +967,1033,966, +1033,967,1034, +968,1034,967, +1034,968,1035, +969,1035,968, +1035,969,1036, +970,1036,969, +1036,970,1037, +971,1037,970, +1037,971,1038, +972,1038,971, +1038,972,1039, +973,1039,972, +1039,973,1040, +974,1040,973, +1040,974,1041, +975,1041,974, +1041,975,1042, +976,1042,975, +1042,976,1043, +977,1043,976, +1043,977,1044, +978,1044,977, +1044,978,1045, +979,1045,978, +1045,979,1046, +980,1046,979, +1046,980,1047, +981,1047,980, +1047,981,1048, +982,1048,981, +1048,982,1049, +983,1049,982, +1049,983,1050, +984,1050,983, +1050,984,1051, +985,1051,984, +1051,985,1052, +986,1052,985, +1052,986,1053, +987,1053,986, +1053,987,1054, +988,1054,987, +1054,988,1055, +989,1055,988, +1056,990,1057, +991,1057,990, +1057,991,1058, +992,1058,991, +1058,992,1059, +993,1059,992, +1059,993,1060, +994,1060,993, +1060,994,1061, +995,1061,994, +1061,995,1062, +996,1062,995, +1062,996,1063, +997,1063,996, +1063,997,1064, +998,1064,997, +1064,998,1065, +999,1065,998, +1065,999,1066, +1000,1066,999, +1066,1000,1067, +1001,1067,1000, +1067,1001,1068, +1002,1068,1001, +1068,1002,1069, +1003,1069,1002, +1069,1003,1070, +1004,1070,1003, +1070,1004,1071, +1005,1071,1004, +1071,1005,1072, +1006,1072,1005, +1072,1006,1073, +1007,1073,1006, +1073,1007,1074, +1008,1074,1007, +1074,1008,1075, +1009,1075,1008, +1075,1009,1076, +1010,1076,1009, +1076,1010,1077, +1011,1077,1010, +1077,1011,1078, +1012,1078,1011, +1078,1012,1079, +1013,1079,1012, +1079,1013,1080, +1014,1080,1013, +1080,1014,1081, +1015,1081,1014, +1081,1015,1082, +1016,1082,1015, +1082,1016,1083, +1017,1083,1016, +1083,1017,1084, +1018,1084,1017, +1084,1018,1085, +1019,1085,1018, +1085,1019,1086, +1020,1086,1019, +1086,1020,1087, +1021,1087,1020, +1087,1021,1088, +1022,1088,1021, +1088,1022,1089, +1023,1089,1022, +1089,1023,1090, +1024,1090,1023, +1090,1024,1091, +1025,1091,1024, +1091,1025,1092, +1026,1092,1025, +1092,1026,1093, +1027,1093,1026, +1093,1027,1094, +1028,1094,1027, +1094,1028,1095, +1029,1095,1028, +1095,1029,1096, +1030,1096,1029, +1096,1030,1097, +1031,1097,1030, +1097,1031,1098, +1032,1098,1031, +1098,1032,1099, +1033,1099,1032, +1099,1033,1100, +1034,1100,1033, +1100,1034,1101, +1035,1101,1034, +1101,1035,1102, +1036,1102,1035, +1102,1036,1103, +1037,1103,1036, +1103,1037,1104, +1038,1104,1037, +1104,1038,1105, +1039,1105,1038, +1105,1039,1106, +1040,1106,1039, +1106,1040,1107, +1041,1107,1040, +1107,1041,1108, +1042,1108,1041, +1108,1042,1109, +1043,1109,1042, +1109,1043,1110, +1044,1110,1043, +1110,1044,1111, +1045,1111,1044, +1111,1045,1112, +1046,1112,1045, +1112,1046,1113, +1047,1113,1046, +1113,1047,1114, +1048,1114,1047, +1114,1048,1115, +1049,1115,1048, +1115,1049,1116, +1050,1116,1049, +1116,1050,1117, +1051,1117,1050, +1117,1051,1118, +1052,1118,1051, +1118,1052,1119, +1053,1119,1052, +1119,1053,1120, +1054,1120,1053, +1120,1054,1121, +1055,1121,1054, +1122,1056,1123, +1057,1123,1056, +1123,1057,1124, +1058,1124,1057, +1124,1058,1125, +1059,1125,1058, +1125,1059,1126, +1060,1126,1059, +1126,1060,1127, +1061,1127,1060, +1127,1061,1128, +1062,1128,1061, +1128,1062,1129, +1063,1129,1062, +1129,1063,1130, +1064,1130,1063, +1130,1064,1131, +1065,1131,1064, +1131,1065,1132, +1066,1132,1065, +1132,1066,1133, +1067,1133,1066, +1133,1067,1134, +1068,1134,1067, +1134,1068,1135, +1069,1135,1068, +1135,1069,1136, +1070,1136,1069, +1136,1070,1137, +1071,1137,1070, +1137,1071,1138, +1072,1138,1071, +1138,1072,1139, +1073,1139,1072, +1139,1073,1140, +1074,1140,1073, +1140,1074,1141, +1075,1141,1074, +1141,1075,1142, +1076,1142,1075, +1142,1076,1143, +1077,1143,1076, +1143,1077,1144, +1078,1144,1077, +1144,1078,1145, +1079,1145,1078, +1145,1079,1146, +1080,1146,1079, +1146,1080,1147, +1081,1147,1080, +1147,1081,1148, +1082,1148,1081, +1148,1082,1149, +1083,1149,1082, +1149,1083,1150, +1084,1150,1083, +1150,1084,1151, +1085,1151,1084, +1151,1085,1152, +1086,1152,1085, +1152,1086,1153, +1087,1153,1086, +1153,1087,1154, +1088,1154,1087, +1154,1088,1155, +1089,1155,1088, +1155,1089,1156, +1090,1156,1089, +1156,1090,1157, +1091,1157,1090, +1157,1091,1158, +1092,1158,1091, +1158,1092,1159, +1093,1159,1092, +1159,1093,1160, +1094,1160,1093, +1160,1094,1161, +1095,1161,1094, +1161,1095,1162, +1096,1162,1095, +1162,1096,1163, +1097,1163,1096, +1163,1097,1164, +1098,1164,1097, +1164,1098,1165, +1099,1165,1098, +1165,1099,1166, +1100,1166,1099, +1166,1100,1167, +1101,1167,1100, +1167,1101,1168, +1102,1168,1101, +1168,1102,1169, +1103,1169,1102, +1169,1103,1170, +1104,1170,1103, +1170,1104,1171, +1105,1171,1104, +1171,1105,1172, +1106,1172,1105, +1172,1106,1173, +1107,1173,1106, +1173,1107,1174, +1108,1174,1107, +1174,1108,1175, +1109,1175,1108, +1175,1109,1176, +1110,1176,1109, +1176,1110,1177, +1111,1177,1110, +1177,1111,1178, +1112,1178,1111, +1178,1112,1179, +1113,1179,1112, +1179,1113,1180, +1114,1180,1113, +1180,1114,1181, +1115,1181,1114, +1181,1115,1182, +1116,1182,1115, +1182,1116,1183, +1117,1183,1116, +1183,1117,1184, +1118,1184,1117, +1184,1118,1185, +1119,1185,1118, +1185,1119,1186, +1120,1186,1119, +1186,1120,1187, +1121,1187,1120, +1188,1122,1189, +1123,1189,1122, +1189,1123,1190, +1124,1190,1123, +1190,1124,1191, +1125,1191,1124, +1191,1125,1192, +1126,1192,1125, +1192,1126,1193, +1127,1193,1126, +1193,1127,1194, +1128,1194,1127, +1194,1128,1195, +1129,1195,1128, +1195,1129,1196, +1130,1196,1129, +1196,1130,1197, +1131,1197,1130, +1197,1131,1198, +1132,1198,1131, +1198,1132,1199, +1133,1199,1132, +1199,1133,1200, +1134,1200,1133, +1200,1134,1201, +1135,1201,1134, +1201,1135,1202, +1136,1202,1135, +1202,1136,1203, +1137,1203,1136, +1203,1137,1204, +1138,1204,1137, +1204,1138,1205, +1139,1205,1138, +1205,1139,1206, +1140,1206,1139, +1206,1140,1207, +1141,1207,1140, +1207,1141,1208, +1142,1208,1141, +1208,1142,1209, +1143,1209,1142, +1209,1143,1210, +1144,1210,1143, +1210,1144,1211, +1145,1211,1144, +1211,1145,1212, +1146,1212,1145, +1212,1146,1213, +1147,1213,1146, +1213,1147,1214, +1148,1214,1147, +1214,1148,1215, +1149,1215,1148, +1215,1149,1216, +1150,1216,1149, +1216,1150,1217, +1151,1217,1150, +1217,1151,1218, +1152,1218,1151, +1218,1152,1219, +1153,1219,1152, +1219,1153,1220, +1154,1220,1153, +1220,1154,1221, +1155,1221,1154, +1221,1155,1222, +1156,1222,1155, +1222,1156,1223, +1157,1223,1156, +1223,1157,1224, +1158,1224,1157, +1224,1158,1225, +1159,1225,1158, +1225,1159,1226, +1160,1226,1159, +1226,1160,1227, +1161,1227,1160, +1227,1161,1228, +1162,1228,1161, +1228,1162,1229, +1163,1229,1162, +1229,1163,1230, +1164,1230,1163, +1230,1164,1231, +1165,1231,1164, +1231,1165,1232, +1166,1232,1165, +1232,1166,1233, +1167,1233,1166, +1233,1167,1234, +1168,1234,1167, +1234,1168,1235, +1169,1235,1168, +1235,1169,1236, +1170,1236,1169, +1236,1170,1237, +1171,1237,1170, +1237,1171,1238, +1172,1238,1171, +1238,1172,1239, +1173,1239,1172, +1239,1173,1240, +1174,1240,1173, +1240,1174,1241, +1175,1241,1174, +1241,1175,1242, +1176,1242,1175, +1242,1176,1243, +1177,1243,1176, +1243,1177,1244, +1178,1244,1177, +1244,1178,1245, +1179,1245,1178, +1245,1179,1246, +1180,1246,1179, +1246,1180,1247, +1181,1247,1180, +1247,1181,1248, +1182,1248,1181, +1248,1182,1249, +1183,1249,1182, +1249,1183,1250, +1184,1250,1183, +1250,1184,1251, +1185,1251,1184, +1251,1185,1252, +1186,1252,1185, +1252,1186,1253, +1187,1253,1186, +1254,1188,1255, +1189,1255,1188, +1255,1189,1256, +1190,1256,1189, +1256,1190,1257, +1191,1257,1190, +1257,1191,1258, +1192,1258,1191, +1258,1192,1259, +1193,1259,1192, +1259,1193,1260, +1194,1260,1193, +1260,1194,1261, +1195,1261,1194, +1261,1195,1262, +1196,1262,1195, +1262,1196,1263, +1197,1263,1196, +1263,1197,1264, +1198,1264,1197, +1264,1198,1265, +1199,1265,1198, +1265,1199,1266, +1200,1266,1199, +1266,1200,1267, +1201,1267,1200, +1267,1201,1268, +1202,1268,1201, +1268,1202,1269, +1203,1269,1202, +1269,1203,1270, +1204,1270,1203, +1270,1204,1271, +1205,1271,1204, +1271,1205,1272, +1206,1272,1205, +1272,1206,1273, +1207,1273,1206, +1273,1207,1274, +1208,1274,1207, +1274,1208,1275, +1209,1275,1208, +1275,1209,1276, +1210,1276,1209, +1276,1210,1277, +1211,1277,1210, +1277,1211,1278, +1212,1278,1211, +1278,1212,1279, +1213,1279,1212, +1279,1213,1280, +1214,1280,1213, +1280,1214,1281, +1215,1281,1214, +1281,1215,1282, +1216,1282,1215, +1282,1216,1283, +1217,1283,1216, +1283,1217,1284, +1218,1284,1217, +1284,1218,1285, +1219,1285,1218, +1285,1219,1286, +1220,1286,1219, +1286,1220,1287, +1221,1287,1220, +1287,1221,1288, +1222,1288,1221, +1288,1222,1289, +1223,1289,1222, +1289,1223,1290, +1224,1290,1223, +1290,1224,1291, +1225,1291,1224, +1291,1225,1292, +1226,1292,1225, +1292,1226,1293, +1227,1293,1226, +1293,1227,1294, +1228,1294,1227, +1294,1228,1295, +1229,1295,1228, +1295,1229,1296, +1230,1296,1229, +1296,1230,1297, +1231,1297,1230, +1297,1231,1298, +1232,1298,1231, +1298,1232,1299, +1233,1299,1232, +1299,1233,1300, +1234,1300,1233, +1300,1234,1301, +1235,1301,1234, +1301,1235,1302, +1236,1302,1235, +1302,1236,1303, +1237,1303,1236, +1303,1237,1304, +1238,1304,1237, +1304,1238,1305, +1239,1305,1238, +1305,1239,1306, +1240,1306,1239, +1306,1240,1307, +1241,1307,1240, +1307,1241,1308, +1242,1308,1241, +1308,1242,1309, +1243,1309,1242, +1309,1243,1310, +1244,1310,1243, +1310,1244,1311, +1245,1311,1244, +1311,1245,1312, +1246,1312,1245, +1312,1246,1313, +1247,1313,1246, +1313,1247,1314, +1248,1314,1247, +1314,1248,1315, +1249,1315,1248, +1315,1249,1316, +1250,1316,1249, +1316,1250,1317, +1251,1317,1250, +1317,1251,1318, +1252,1318,1251, +1318,1252,1319, +1253,1319,1252, +1320,1254,1321, +1255,1321,1254, +1321,1255,1322, +1256,1322,1255, +1322,1256,1323, +1257,1323,1256, +1323,1257,1324, +1258,1324,1257, +1324,1258,1325, +1259,1325,1258, +1325,1259,1326, +1260,1326,1259, +1326,1260,1327, +1261,1327,1260, +1327,1261,1328, +1262,1328,1261, +1328,1262,1329, +1263,1329,1262, +1329,1263,1330, +1264,1330,1263, +1330,1264,1331, +1265,1331,1264, +1331,1265,1332, +1266,1332,1265, +1332,1266,1333, +1267,1333,1266, +1333,1267,1334, +1268,1334,1267, +1334,1268,1335, +1269,1335,1268, +1335,1269,1336, +1270,1336,1269, +1336,1270,1337, +1271,1337,1270, +1337,1271,1338, +1272,1338,1271, +1338,1272,1339, +1273,1339,1272, +1339,1273,1340, +1274,1340,1273, +1340,1274,1341, +1275,1341,1274, +1341,1275,1342, +1276,1342,1275, +1342,1276,1343, +1277,1343,1276, +1343,1277,1344, +1278,1344,1277, +1344,1278,1345, +1279,1345,1278, +1345,1279,1346, +1280,1346,1279, +1346,1280,1347, +1281,1347,1280, +1347,1281,1348, +1282,1348,1281, +1348,1282,1349, +1283,1349,1282, +1349,1283,1350, +1284,1350,1283, +1350,1284,1351, +1285,1351,1284, +1351,1285,1352, +1286,1352,1285, +1352,1286,1353, +1287,1353,1286, +1353,1287,1354, +1288,1354,1287, +1354,1288,1355, +1289,1355,1288, +1355,1289,1356, +1290,1356,1289, +1356,1290,1357, +1291,1357,1290, +1357,1291,1358, +1292,1358,1291, +1358,1292,1359, +1293,1359,1292, +1359,1293,1360, +1294,1360,1293, +1360,1294,1361, +1295,1361,1294, +1361,1295,1362, +1296,1362,1295, +1362,1296,1363, +1297,1363,1296, +1363,1297,1364, +1298,1364,1297, +1364,1298,1365, +1299,1365,1298, +1365,1299,1366, +1300,1366,1299, +1366,1300,1367, +1301,1367,1300, +1367,1301,1368, +1302,1368,1301, +1368,1302,1369, +1303,1369,1302, +1369,1303,1370, +1304,1370,1303, +1370,1304,1371, +1305,1371,1304, +1371,1305,1372, +1306,1372,1305, +1372,1306,1373, +1307,1373,1306, +1373,1307,1374, +1308,1374,1307, +1374,1308,1375, +1309,1375,1308, +1375,1309,1376, +1310,1376,1309, +1376,1310,1377, +1311,1377,1310, +1377,1311,1378, +1312,1378,1311, +1378,1312,1379, +1313,1379,1312, +1379,1313,1380, +1314,1380,1313, +1380,1314,1381, +1315,1381,1314, +1381,1315,1382, +1316,1382,1315, +1382,1316,1383, +1317,1383,1316, +1383,1317,1384, +1318,1384,1317, +1384,1318,1385, +1319,1385,1318, +1386,1320,1387, +1321,1387,1320, +1387,1321,1388, +1322,1388,1321, +1388,1322,1389, +1323,1389,1322, +1389,1323,1390, +1324,1390,1323, +1390,1324,1391, +1325,1391,1324, +1391,1325,1392, +1326,1392,1325, +1392,1326,1393, +1327,1393,1326, +1393,1327,1394, +1328,1394,1327, +1394,1328,1395, +1329,1395,1328, +1395,1329,1396, +1330,1396,1329, +1396,1330,1397, +1331,1397,1330, +1397,1331,1398, +1332,1398,1331, +1398,1332,1399, +1333,1399,1332, +1399,1333,1400, +1334,1400,1333, +1400,1334,1401, +1335,1401,1334, +1401,1335,1402, +1336,1402,1335, +1402,1336,1403, +1337,1403,1336, +1403,1337,1404, +1338,1404,1337, +1404,1338,1405, +1339,1405,1338, +1405,1339,1406, +1340,1406,1339, +1406,1340,1407, +1341,1407,1340, +1407,1341,1408, +1342,1408,1341, +1408,1342,1409, +1343,1409,1342, +1409,1343,1410, +1344,1410,1343, +1410,1344,1411, +1345,1411,1344, +1411,1345,1412, +1346,1412,1345, +1412,1346,1413, +1347,1413,1346, +1413,1347,1414, +1348,1414,1347, +1414,1348,1415, +1349,1415,1348, +1415,1349,1416, +1350,1416,1349, +1416,1350,1417, +1351,1417,1350, +1417,1351,1418, +1352,1418,1351, +1418,1352,1419, +1353,1419,1352, +1419,1353,1420, +1354,1420,1353, +1420,1354,1421, +1355,1421,1354, +1421,1355,1422, +1356,1422,1355, +1422,1356,1423, +1357,1423,1356, +1423,1357,1424, +1358,1424,1357, +1424,1358,1425, +1359,1425,1358, +1425,1359,1426, +1360,1426,1359, +1426,1360,1427, +1361,1427,1360, +1427,1361,1428, +1362,1428,1361, +1428,1362,1429, +1363,1429,1362, +1429,1363,1430, +1364,1430,1363, +1430,1364,1431, +1365,1431,1364, +1431,1365,1432, +1366,1432,1365, +1432,1366,1433, +1367,1433,1366, +1433,1367,1434, +1368,1434,1367, +1434,1368,1435, +1369,1435,1368, +1435,1369,1436, +1370,1436,1369, +1436,1370,1437, +1371,1437,1370, +1437,1371,1438, +1372,1438,1371, +1438,1372,1439, +1373,1439,1372, +1439,1373,1440, +1374,1440,1373, +1440,1374,1441, +1375,1441,1374, +1441,1375,1442, +1376,1442,1375, +1442,1376,1443, +1377,1443,1376, +1443,1377,1444, +1378,1444,1377, +1444,1378,1445, +1379,1445,1378, +1445,1379,1446, +1380,1446,1379, +1446,1380,1447, +1381,1447,1380, +1447,1381,1448, +1382,1448,1381, +1448,1382,1449, +1383,1449,1382, +1449,1383,1450, +1384,1450,1383, +1450,1384,1451, +1385,1451,1384, +1452,1386,1453, +1387,1453,1386, +1453,1387,1454, +1388,1454,1387, +1454,1388,1455, +1389,1455,1388, +1455,1389,1456, +1390,1456,1389, +1456,1390,1457, +1391,1457,1390, +1457,1391,1458, +1392,1458,1391, +1458,1392,1459, +1393,1459,1392, +1459,1393,1460, +1394,1460,1393, +1460,1394,1461, +1395,1461,1394, +1461,1395,1462, +1396,1462,1395, +1462,1396,1463, +1397,1463,1396, +1463,1397,1464, +1398,1464,1397, +1464,1398,1465, +1399,1465,1398, +1465,1399,1466, +1400,1466,1399, +1466,1400,1467, +1401,1467,1400, +1467,1401,1468, +1402,1468,1401, +1468,1402,1469, +1403,1469,1402, +1469,1403,1470, +1404,1470,1403, +1470,1404,1471, +1405,1471,1404, +1471,1405,1472, +1406,1472,1405, +1472,1406,1473, +1407,1473,1406, +1473,1407,1474, +1408,1474,1407, +1474,1408,1475, +1409,1475,1408, +1475,1409,1476, +1410,1476,1409, +1476,1410,1477, +1411,1477,1410, +1477,1411,1478, +1412,1478,1411, +1478,1412,1479, +1413,1479,1412, +1479,1413,1480, +1414,1480,1413, +1480,1414,1481, +1415,1481,1414, +1481,1415,1482, +1416,1482,1415, +1482,1416,1483, +1417,1483,1416, +1483,1417,1484, +1418,1484,1417, +1484,1418,1485, +1419,1485,1418, +1485,1419,1486, +1420,1486,1419, +1486,1420,1487, +1421,1487,1420, +1487,1421,1488, +1422,1488,1421, +1488,1422,1489, +1423,1489,1422, +1489,1423,1490, +1424,1490,1423, +1490,1424,1491, +1425,1491,1424, +1491,1425,1492, +1426,1492,1425, +1492,1426,1493, +1427,1493,1426, +1493,1427,1494, +1428,1494,1427, +1494,1428,1495, +1429,1495,1428, +1495,1429,1496, +1430,1496,1429, +1496,1430,1497, +1431,1497,1430, +1497,1431,1498, +1432,1498,1431, +1498,1432,1499, +1433,1499,1432, +1499,1433,1500, +1434,1500,1433, +1500,1434,1501, +1435,1501,1434, +1501,1435,1502, +1436,1502,1435, +1502,1436,1503, +1437,1503,1436, +1503,1437,1504, +1438,1504,1437, +1504,1438,1505, +1439,1505,1438, +1505,1439,1506, +1440,1506,1439, +1506,1440,1507, +1441,1507,1440, +1507,1441,1508, +1442,1508,1441, +1508,1442,1509, +1443,1509,1442, +1509,1443,1510, +1444,1510,1443, +1510,1444,1511, +1445,1511,1444, +1511,1445,1512, +1446,1512,1445, +1512,1446,1513, +1447,1513,1446, +1513,1447,1514, +1448,1514,1447, +1514,1448,1515, +1449,1515,1448, +1515,1449,1516, +1450,1516,1449, +1516,1450,1517, +1451,1517,1450, +1518,1452,1519, +1453,1519,1452, +1519,1453,1520, +1454,1520,1453, +1520,1454,1521, +1455,1521,1454, +1521,1455,1522, +1456,1522,1455, +1522,1456,1523, +1457,1523,1456, +1523,1457,1524, +1458,1524,1457, +1524,1458,1525, +1459,1525,1458, +1525,1459,1526, +1460,1526,1459, +1526,1460,1527, +1461,1527,1460, +1527,1461,1528, +1462,1528,1461, +1528,1462,1529, +1463,1529,1462, +1529,1463,1530, +1464,1530,1463, +1530,1464,1531, +1465,1531,1464, +1531,1465,1532, +1466,1532,1465, +1532,1466,1533, +1467,1533,1466, +1533,1467,1534, +1468,1534,1467, +1534,1468,1535, +1469,1535,1468, +1535,1469,1536, +1470,1536,1469, +1536,1470,1537, +1471,1537,1470, +1537,1471,1538, +1472,1538,1471, +1538,1472,1539, +1473,1539,1472, +1539,1473,1540, +1474,1540,1473, +1540,1474,1541, +1475,1541,1474, +1541,1475,1542, +1476,1542,1475, +1542,1476,1543, +1477,1543,1476, +1543,1477,1544, +1478,1544,1477, +1544,1478,1545, +1479,1545,1478, +1545,1479,1546, +1480,1546,1479, +1546,1480,1547, +1481,1547,1480, +1547,1481,1548, +1482,1548,1481, +1548,1482,1549, +1483,1549,1482, +1549,1483,1550, +1484,1550,1483, +1550,1484,1551, +1485,1551,1484, +1551,1485,1552, +1486,1552,1485, +1552,1486,1553, +1487,1553,1486, +1553,1487,1554, +1488,1554,1487, +1554,1488,1555, +1489,1555,1488, +1555,1489,1556, +1490,1556,1489, +1556,1490,1557, +1491,1557,1490, +1557,1491,1558, +1492,1558,1491, +1558,1492,1559, +1493,1559,1492, +1559,1493,1560, +1494,1560,1493, +1560,1494,1561, +1495,1561,1494, +1561,1495,1562, +1496,1562,1495, +1562,1496,1563, +1497,1563,1496, +1563,1497,1564, +1498,1564,1497, +1564,1498,1565, +1499,1565,1498, +1565,1499,1566, +1500,1566,1499, +1566,1500,1567, +1501,1567,1500, +1567,1501,1568, +1502,1568,1501, +1568,1502,1569, +1503,1569,1502, +1569,1503,1570, +1504,1570,1503, +1570,1504,1571, +1505,1571,1504, +1571,1505,1572, +1506,1572,1505, +1572,1506,1573, +1507,1573,1506, +1573,1507,1574, +1508,1574,1507, +1574,1508,1575, +1509,1575,1508, +1575,1509,1576, +1510,1576,1509, +1576,1510,1577, +1511,1577,1510, +1577,1511,1578, +1512,1578,1511, +1578,1512,1579, +1513,1579,1512, +1579,1513,1580, +1514,1580,1513, +1580,1514,1581, +1515,1581,1514, +1581,1515,1582, +1516,1582,1515, +1582,1516,1583, +1517,1583,1516, +1584,1518,1585, +1519,1585,1518, +1585,1519,1586, +1520,1586,1519, +1586,1520,1587, +1521,1587,1520, +1587,1521,1588, +1522,1588,1521, +1588,1522,1589, +1523,1589,1522, +1589,1523,1590, +1524,1590,1523, +1590,1524,1591, +1525,1591,1524, +1591,1525,1592, +1526,1592,1525, +1592,1526,1593, +1527,1593,1526, +1593,1527,1594, +1528,1594,1527, +1594,1528,1595, +1529,1595,1528, +1595,1529,1596, +1530,1596,1529, +1596,1530,1597, +1531,1597,1530, +1597,1531,1598, +1532,1598,1531, +1598,1532,1599, +1533,1599,1532, +1599,1533,1600, +1534,1600,1533, +1600,1534,1601, +1535,1601,1534, +1601,1535,1602, +1536,1602,1535, +1602,1536,1603, +1537,1603,1536, +1603,1537,1604, +1538,1604,1537, +1604,1538,1605, +1539,1605,1538, +1605,1539,1606, +1540,1606,1539, +1606,1540,1607, +1541,1607,1540, +1607,1541,1608, +1542,1608,1541, +1608,1542,1609, +1543,1609,1542, +1609,1543,1610, +1544,1610,1543, +1610,1544,1611, +1545,1611,1544, +1611,1545,1612, +1546,1612,1545, +1612,1546,1613, +1547,1613,1546, +1613,1547,1614, +1548,1614,1547, +1614,1548,1615, +1549,1615,1548, +1615,1549,1616, +1550,1616,1549, +1616,1550,1617, +1551,1617,1550, +1617,1551,1618, +1552,1618,1551, +1618,1552,1619, +1553,1619,1552, +1619,1553,1620, +1554,1620,1553, +1620,1554,1621, +1555,1621,1554, +1621,1555,1622, +1556,1622,1555, +1622,1556,1623, +1557,1623,1556, +1623,1557,1624, +1558,1624,1557, +1624,1558,1625, +1559,1625,1558, +1625,1559,1626, +1560,1626,1559, +1626,1560,1627, +1561,1627,1560, +1627,1561,1628, +1562,1628,1561, +1628,1562,1629, +1563,1629,1562, +1629,1563,1630, +1564,1630,1563, +1630,1564,1631, +1565,1631,1564, +1631,1565,1632, +1566,1632,1565, +1632,1566,1633, +1567,1633,1566, +1633,1567,1634, +1568,1634,1567, +1634,1568,1635, +1569,1635,1568, +1635,1569,1636, +1570,1636,1569, +1636,1570,1637, +1571,1637,1570, +1637,1571,1638, +1572,1638,1571, +1638,1572,1639, +1573,1639,1572, +1639,1573,1640, +1574,1640,1573, +1640,1574,1641, +1575,1641,1574, +1641,1575,1642, +1576,1642,1575, +1642,1576,1643, +1577,1643,1576, +1643,1577,1644, +1578,1644,1577, +1644,1578,1645, +1579,1645,1578, +1645,1579,1646, +1580,1646,1579, +1646,1580,1647, +1581,1647,1580, +1647,1581,1648, +1582,1648,1581, +1648,1582,1649, +1583,1649,1582, +1650,1584,1651, +1585,1651,1584, +1651,1585,1652, +1586,1652,1585, +1652,1586,1653, +1587,1653,1586, +1653,1587,1654, +1588,1654,1587, +1654,1588,1655, +1589,1655,1588, +1655,1589,1656, +1590,1656,1589, +1656,1590,1657, +1591,1657,1590, +1657,1591,1658, +1592,1658,1591, +1658,1592,1659, +1593,1659,1592, +1659,1593,1660, +1594,1660,1593, +1660,1594,1661, +1595,1661,1594, +1661,1595,1662, +1596,1662,1595, +1662,1596,1663, +1597,1663,1596, +1663,1597,1664, +1598,1664,1597, +1664,1598,1665, +1599,1665,1598, +1665,1599,1666, +1600,1666,1599, +1666,1600,1667, +1601,1667,1600, +1667,1601,1668, +1602,1668,1601, +1668,1602,1669, +1603,1669,1602, +1669,1603,1670, +1604,1670,1603, +1670,1604,1671, +1605,1671,1604, +1671,1605,1672, +1606,1672,1605, +1672,1606,1673, +1607,1673,1606, +1673,1607,1674, +1608,1674,1607, +1674,1608,1675, +1609,1675,1608, +1675,1609,1676, +1610,1676,1609, +1676,1610,1677, +1611,1677,1610, +1677,1611,1678, +1612,1678,1611, +1678,1612,1679, +1613,1679,1612, +1679,1613,1680, +1614,1680,1613, +1680,1614,1681, +1615,1681,1614, +1681,1615,1682, +1616,1682,1615, +1682,1616,1683, +1617,1683,1616, +1683,1617,1684, +1618,1684,1617, +1684,1618,1685, +1619,1685,1618, +1685,1619,1686, +1620,1686,1619, +1686,1620,1687, +1621,1687,1620, +1687,1621,1688, +1622,1688,1621, +1688,1622,1689, +1623,1689,1622, +1689,1623,1690, +1624,1690,1623, +1690,1624,1691, +1625,1691,1624, +1691,1625,1692, +1626,1692,1625, +1692,1626,1693, +1627,1693,1626, +1693,1627,1694, +1628,1694,1627, +1694,1628,1695, +1629,1695,1628, +1695,1629,1696, +1630,1696,1629, +1696,1630,1697, +1631,1697,1630, +1697,1631,1698, +1632,1698,1631, +1698,1632,1699, +1633,1699,1632, +1699,1633,1700, +1634,1700,1633, +1700,1634,1701, +1635,1701,1634, +1701,1635,1702, +1636,1702,1635, +1702,1636,1703, +1637,1703,1636, +1703,1637,1704, +1638,1704,1637, +1704,1638,1705, +1639,1705,1638, +1705,1639,1706, +1640,1706,1639, +1706,1640,1707, +1641,1707,1640, +1707,1641,1708, +1642,1708,1641, +1708,1642,1709, +1643,1709,1642, +1709,1643,1710, +1644,1710,1643, +1710,1644,1711, +1645,1711,1644, +1711,1645,1712, +1646,1712,1645, +1712,1646,1713, +1647,1713,1646, +1713,1647,1714, +1648,1714,1647, +1714,1648,1715, +1649,1715,1648, +1716,1650,1717, +1651,1717,1650, +1717,1651,1718, +1652,1718,1651, +1718,1652,1719, +1653,1719,1652, +1719,1653,1720, +1654,1720,1653, +1720,1654,1721, +1655,1721,1654, +1721,1655,1722, +1656,1722,1655, +1722,1656,1723, +1657,1723,1656, +1723,1657,1724, +1658,1724,1657, +1724,1658,1725, +1659,1725,1658, +1725,1659,1726, +1660,1726,1659, +1726,1660,1727, +1661,1727,1660, +1727,1661,1728, +1662,1728,1661, +1728,1662,1729, +1663,1729,1662, +1729,1663,1730, +1664,1730,1663, +1730,1664,1731, +1665,1731,1664, +1731,1665,1732, +1666,1732,1665, +1732,1666,1733, +1667,1733,1666, +1733,1667,1734, +1668,1734,1667, +1734,1668,1735, +1669,1735,1668, +1735,1669,1736, +1670,1736,1669, +1736,1670,1737, +1671,1737,1670, +1737,1671,1738, +1672,1738,1671, +1738,1672,1739, +1673,1739,1672, +1739,1673,1740, +1674,1740,1673, +1740,1674,1741, +1675,1741,1674, +1741,1675,1742, +1676,1742,1675, +1742,1676,1743, +1677,1743,1676, +1743,1677,1744, +1678,1744,1677, +1744,1678,1745, +1679,1745,1678, +1745,1679,1746, +1680,1746,1679, +1746,1680,1747, +1681,1747,1680, +1747,1681,1748, +1682,1748,1681, +1748,1682,1749, +1683,1749,1682, +1749,1683,1750, +1684,1750,1683, +1750,1684,1751, +1685,1751,1684, +1751,1685,1752, +1686,1752,1685, +1752,1686,1753, +1687,1753,1686, +1753,1687,1754, +1688,1754,1687, +1754,1688,1755, +1689,1755,1688, +1755,1689,1756, +1690,1756,1689, +1756,1690,1757, +1691,1757,1690, +1757,1691,1758, +1692,1758,1691, +1758,1692,1759, +1693,1759,1692, +1759,1693,1760, +1694,1760,1693, +1760,1694,1761, +1695,1761,1694, +1761,1695,1762, +1696,1762,1695, +1762,1696,1763, +1697,1763,1696, +1763,1697,1764, +1698,1764,1697, +1764,1698,1765, +1699,1765,1698, +1765,1699,1766, +1700,1766,1699, +1766,1700,1767, +1701,1767,1700, +1767,1701,1768, +1702,1768,1701, +1768,1702,1769, +1703,1769,1702, +1769,1703,1770, +1704,1770,1703, +1770,1704,1771, +1705,1771,1704, +1771,1705,1772, +1706,1772,1705, +1772,1706,1773, +1707,1773,1706, +1773,1707,1774, +1708,1774,1707, +1774,1708,1775, +1709,1775,1708, +1775,1709,1776, +1710,1776,1709, +1776,1710,1777, +1711,1777,1710, +1777,1711,1778, +1712,1778,1711, +1778,1712,1779, +1713,1779,1712, +1779,1713,1780, +1714,1780,1713, +1780,1714,1781, +1715,1781,1714, +1782,1716,1783, +1717,1783,1716, +1783,1717,1784, +1718,1784,1717, +1784,1718,1785, +1719,1785,1718, +1785,1719,1786, +1720,1786,1719, +1786,1720,1787, +1721,1787,1720, +1787,1721,1788, +1722,1788,1721, +1788,1722,1789, +1723,1789,1722, +1789,1723,1790, +1724,1790,1723, +1790,1724,1791, +1725,1791,1724, +1791,1725,1792, +1726,1792,1725, +1792,1726,1793, +1727,1793,1726, +1793,1727,1794, +1728,1794,1727, +1794,1728,1795, +1729,1795,1728, +1795,1729,1796, +1730,1796,1729, +1796,1730,1797, +1731,1797,1730, +1797,1731,1798, +1732,1798,1731, +1798,1732,1799, +1733,1799,1732, +1799,1733,1800, +1734,1800,1733, +1800,1734,1801, +1735,1801,1734, +1801,1735,1802, +1736,1802,1735, +1802,1736,1803, +1737,1803,1736, +1803,1737,1804, +1738,1804,1737, +1804,1738,1805, +1739,1805,1738, +1805,1739,1806, +1740,1806,1739, +1806,1740,1807, +1741,1807,1740, +1807,1741,1808, +1742,1808,1741, +1808,1742,1809, +1743,1809,1742, +1809,1743,1810, +1744,1810,1743, +1810,1744,1811, +1745,1811,1744, +1811,1745,1812, +1746,1812,1745, +1812,1746,1813, +1747,1813,1746, +1813,1747,1814, +1748,1814,1747, +1814,1748,1815, +1749,1815,1748, +1815,1749,1816, +1750,1816,1749, +1816,1750,1817, +1751,1817,1750, +1817,1751,1818, +1752,1818,1751, +1818,1752,1819, +1753,1819,1752, +1819,1753,1820, +1754,1820,1753, +1820,1754,1821, +1755,1821,1754, +1821,1755,1822, +1756,1822,1755, +1822,1756,1823, +1757,1823,1756, +1823,1757,1824, +1758,1824,1757, +1824,1758,1825, +1759,1825,1758, +1825,1759,1826, +1760,1826,1759, +1826,1760,1827, +1761,1827,1760, +1827,1761,1828, +1762,1828,1761, +1828,1762,1829, +1763,1829,1762, +1829,1763,1830, +1764,1830,1763, +1830,1764,1831, +1765,1831,1764, +1831,1765,1832, +1766,1832,1765, +1832,1766,1833, +1767,1833,1766, +1833,1767,1834, +1768,1834,1767, +1834,1768,1835, +1769,1835,1768, +1835,1769,1836, +1770,1836,1769, +1836,1770,1837, +1771,1837,1770, +1837,1771,1838, +1772,1838,1771, +1838,1772,1839, +1773,1839,1772, +1839,1773,1840, +1774,1840,1773, +1840,1774,1841, +1775,1841,1774, +1841,1775,1842, +1776,1842,1775, +1842,1776,1843, +1777,1843,1776, +1843,1777,1844, +1778,1844,1777, +1844,1778,1845, +1779,1845,1778, +1845,1779,1846, +1780,1846,1779, +1846,1780,1847, +1781,1847,1780, +1848,1782,1849, +1783,1849,1782, +1849,1783,1850, +1784,1850,1783, +1850,1784,1851, +1785,1851,1784, +1851,1785,1852, +1786,1852,1785, +1852,1786,1853, +1787,1853,1786, +1853,1787,1854, +1788,1854,1787, +1854,1788,1855, +1789,1855,1788, +1855,1789,1856, +1790,1856,1789, +1856,1790,1857, +1791,1857,1790, +1857,1791,1858, +1792,1858,1791, +1858,1792,1859, +1793,1859,1792, +1859,1793,1860, +1794,1860,1793, +1860,1794,1861, +1795,1861,1794, +1861,1795,1862, +1796,1862,1795, +1862,1796,1863, +1797,1863,1796, +1863,1797,1864, +1798,1864,1797, +1864,1798,1865, +1799,1865,1798, +1865,1799,1866, +1800,1866,1799, +1866,1800,1867, +1801,1867,1800, +1867,1801,1868, +1802,1868,1801, +1868,1802,1869, +1803,1869,1802, +1869,1803,1870, +1804,1870,1803, +1870,1804,1871, +1805,1871,1804, +1871,1805,1872, +1806,1872,1805, +1872,1806,1873, +1807,1873,1806, +1873,1807,1874, +1808,1874,1807, +1874,1808,1875, +1809,1875,1808, +1875,1809,1876, +1810,1876,1809, +1876,1810,1877, +1811,1877,1810, +1877,1811,1878, +1812,1878,1811, +1878,1812,1879, +1813,1879,1812, +1879,1813,1880, +1814,1880,1813, +1880,1814,1881, +1815,1881,1814, +1881,1815,1882, +1816,1882,1815, +1882,1816,1883, +1817,1883,1816, +1883,1817,1884, +1818,1884,1817, +1884,1818,1885, +1819,1885,1818, +1885,1819,1886, +1820,1886,1819, +1886,1820,1887, +1821,1887,1820, +1887,1821,1888, +1822,1888,1821, +1888,1822,1889, +1823,1889,1822, +1889,1823,1890, +1824,1890,1823, +1890,1824,1891, +1825,1891,1824, +1891,1825,1892, +1826,1892,1825, +1892,1826,1893, +1827,1893,1826, +1893,1827,1894, +1828,1894,1827, +1894,1828,1895, +1829,1895,1828, +1895,1829,1896, +1830,1896,1829, +1896,1830,1897, +1831,1897,1830, +1897,1831,1898, +1832,1898,1831, +1898,1832,1899, +1833,1899,1832, +1899,1833,1900, +1834,1900,1833, +1900,1834,1901, +1835,1901,1834, +1901,1835,1902, +1836,1902,1835, +1902,1836,1903, +1837,1903,1836, +1903,1837,1904, +1838,1904,1837, +1904,1838,1905, +1839,1905,1838, +1905,1839,1906, +1840,1906,1839, +1906,1840,1907, +1841,1907,1840, +1907,1841,1908, +1842,1908,1841, +1908,1842,1909, +1843,1909,1842, +1909,1843,1910, +1844,1910,1843, +1910,1844,1911, +1845,1911,1844, +1911,1845,1912, +1846,1912,1845, +1912,1846,1913, +1847,1913,1846, +1914,1848,1915, +1849,1915,1848, +1915,1849,1916, +1850,1916,1849, +1916,1850,1917, +1851,1917,1850, +1917,1851,1918, +1852,1918,1851, +1918,1852,1919, +1853,1919,1852, +1919,1853,1920, +1854,1920,1853, +1920,1854,1921, +1855,1921,1854, +1921,1855,1922, +1856,1922,1855, +1922,1856,1923, +1857,1923,1856, +1923,1857,1924, +1858,1924,1857, +1924,1858,1925, +1859,1925,1858, +1925,1859,1926, +1860,1926,1859, +1926,1860,1927, +1861,1927,1860, +1927,1861,1928, +1862,1928,1861, +1928,1862,1929, +1863,1929,1862, +1929,1863,1930, +1864,1930,1863, +1930,1864,1931, +1865,1931,1864, +1931,1865,1932, +1866,1932,1865, +1932,1866,1933, +1867,1933,1866, +1933,1867,1934, +1868,1934,1867, +1934,1868,1935, +1869,1935,1868, +1935,1869,1936, +1870,1936,1869, +1936,1870,1937, +1871,1937,1870, +1937,1871,1938, +1872,1938,1871, +1938,1872,1939, +1873,1939,1872, +1939,1873,1940, +1874,1940,1873, +1940,1874,1941, +1875,1941,1874, +1941,1875,1942, +1876,1942,1875, +1942,1876,1943, +1877,1943,1876, +1943,1877,1944, +1878,1944,1877, +1944,1878,1945, +1879,1945,1878, +1945,1879,1946, +1880,1946,1879, +1946,1880,1947, +1881,1947,1880, +1947,1881,1948, +1882,1948,1881, +1948,1882,1949, +1883,1949,1882, +1949,1883,1950, +1884,1950,1883, +1950,1884,1951, +1885,1951,1884, +1951,1885,1952, +1886,1952,1885, +1952,1886,1953, +1887,1953,1886, +1953,1887,1954, +1888,1954,1887, +1954,1888,1955, +1889,1955,1888, +1955,1889,1956, +1890,1956,1889, +1956,1890,1957, +1891,1957,1890, +1957,1891,1958, +1892,1958,1891, +1958,1892,1959, +1893,1959,1892, +1959,1893,1960, +1894,1960,1893, +1960,1894,1961, +1895,1961,1894, +1961,1895,1962, +1896,1962,1895, +1962,1896,1963, +1897,1963,1896, +1963,1897,1964, +1898,1964,1897, +1964,1898,1965, +1899,1965,1898, +1965,1899,1966, +1900,1966,1899, +1966,1900,1967, +1901,1967,1900, +1967,1901,1968, +1902,1968,1901, +1968,1902,1969, +1903,1969,1902, +1969,1903,1970, +1904,1970,1903, +1970,1904,1971, +1905,1971,1904, +1971,1905,1972, +1906,1972,1905, +1972,1906,1973, +1907,1973,1906, +1973,1907,1974, +1908,1974,1907, +1974,1908,1975, +1909,1975,1908, +1975,1909,1976, +1910,1976,1909, +1976,1910,1977, +1911,1977,1910, +1977,1911,1978, +1912,1978,1911, +1978,1912,1979, +1913,1979,1912, +1980,1914,1981, +1915,1981,1914, +1981,1915,1982, +1916,1982,1915, +1982,1916,1983, +1917,1983,1916, +1983,1917,1984, +1918,1984,1917, +1984,1918,1985, +1919,1985,1918, +1985,1919,1986, +1920,1986,1919, +1986,1920,1987, +1921,1987,1920, +1987,1921,1988, +1922,1988,1921, +1988,1922,1989, +1923,1989,1922, +1989,1923,1990, +1924,1990,1923, +1990,1924,1991, +1925,1991,1924, +1991,1925,1992, +1926,1992,1925, +1992,1926,1993, +1927,1993,1926, +1993,1927,1994, +1928,1994,1927, +1994,1928,1995, +1929,1995,1928, +1995,1929,1996, +1930,1996,1929, +1996,1930,1997, +1931,1997,1930, +1997,1931,1998, +1932,1998,1931, +1998,1932,1999, +1933,1999,1932, +1999,1933,2000, +1934,2000,1933, +2000,1934,2001, +1935,2001,1934, +2001,1935,2002, +1936,2002,1935, +2002,1936,2003, +1937,2003,1936, +2003,1937,2004, +1938,2004,1937, +2004,1938,2005, +1939,2005,1938, +2005,1939,2006, +1940,2006,1939, +2006,1940,2007, +1941,2007,1940, +2007,1941,2008, +1942,2008,1941, +2008,1942,2009, +1943,2009,1942, +2009,1943,2010, +1944,2010,1943, +2010,1944,2011, +1945,2011,1944, +2011,1945,2012, +1946,2012,1945, +2012,1946,2013, +1947,2013,1946, +2013,1947,2014, +1948,2014,1947, +2014,1948,2015, +1949,2015,1948, +2015,1949,2016, +1950,2016,1949, +2016,1950,2017, +1951,2017,1950, +2017,1951,2018, +1952,2018,1951, +2018,1952,2019, +1953,2019,1952, +2019,1953,2020, +1954,2020,1953, +2020,1954,2021, +1955,2021,1954, +2021,1955,2022, +1956,2022,1955, +2022,1956,2023, +1957,2023,1956, +2023,1957,2024, +1958,2024,1957, +2024,1958,2025, +1959,2025,1958, +2025,1959,2026, +1960,2026,1959, +2026,1960,2027, +1961,2027,1960, +2027,1961,2028, +1962,2028,1961, +2028,1962,2029, +1963,2029,1962, +2029,1963,2030, +1964,2030,1963, +2030,1964,2031, +1965,2031,1964, +2031,1965,2032, +1966,2032,1965, +2032,1966,2033, +1967,2033,1966, +2033,1967,2034, +1968,2034,1967, +2034,1968,2035, +1969,2035,1968, +2035,1969,2036, +1970,2036,1969, +2036,1970,2037, +1971,2037,1970, +2037,1971,2038, +1972,2038,1971, +2038,1972,2039, +1973,2039,1972, +2039,1973,2040, +1974,2040,1973, +2040,1974,2041, +1975,2041,1974, +2041,1975,2042, +1976,2042,1975, +2042,1976,2043, +1977,2043,1976, +2043,1977,2044, +1978,2044,1977, +2044,1978,2045, +1979,2045,1978, +2046,1980,2047, +1981,2047,1980, +2047,1981,2048, +1982,2048,1981, +2048,1982,2049, +1983,2049,1982, +2049,1983,2050, +1984,2050,1983, +2050,1984,2051, +1985,2051,1984, +2051,1985,2052, +1986,2052,1985, +2052,1986,2053, +1987,2053,1986, +2053,1987,2054, +1988,2054,1987, +2054,1988,2055, +1989,2055,1988, +2055,1989,2056, +1990,2056,1989, +2056,1990,2057, +1991,2057,1990, +2057,1991,2058, +1992,2058,1991, +2058,1992,2059, +1993,2059,1992, +2059,1993,2060, +1994,2060,1993, +2060,1994,2061, +1995,2061,1994, +2061,1995,2062, +1996,2062,1995, +2062,1996,2063, +1997,2063,1996, +2063,1997,2064, +1998,2064,1997, +2064,1998,2065, +1999,2065,1998, +2065,1999,2066, +2000,2066,1999, +2066,2000,2067, +2001,2067,2000, +2067,2001,2068, +2002,2068,2001, +2068,2002,2069, +2003,2069,2002, +2069,2003,2070, +2004,2070,2003, +2070,2004,2071, +2005,2071,2004, +2071,2005,2072, +2006,2072,2005, +2072,2006,2073, +2007,2073,2006, +2073,2007,2074, +2008,2074,2007, +2074,2008,2075, +2009,2075,2008, +2075,2009,2076, +2010,2076,2009, +2076,2010,2077, +2011,2077,2010, +2077,2011,2078, +2012,2078,2011, +2078,2012,2079, +2013,2079,2012, +2079,2013,2080, +2014,2080,2013, +2080,2014,2081, +2015,2081,2014, +2081,2015,2082, +2016,2082,2015, +2082,2016,2083, +2017,2083,2016, +2083,2017,2084, +2018,2084,2017, +2084,2018,2085, +2019,2085,2018, +2085,2019,2086, +2020,2086,2019, +2086,2020,2087, +2021,2087,2020, +2087,2021,2088, +2022,2088,2021, +2088,2022,2089, +2023,2089,2022, +2089,2023,2090, +2024,2090,2023, +2090,2024,2091, +2025,2091,2024, +2091,2025,2092, +2026,2092,2025, +2092,2026,2093, +2027,2093,2026, +2093,2027,2094, +2028,2094,2027, +2094,2028,2095, +2029,2095,2028, +2095,2029,2096, +2030,2096,2029, +2096,2030,2097, +2031,2097,2030, +2097,2031,2098, +2032,2098,2031, +2098,2032,2099, +2033,2099,2032, +2099,2033,2100, +2034,2100,2033, +2100,2034,2101, +2035,2101,2034, +2101,2035,2102, +2036,2102,2035, +2102,2036,2103, +2037,2103,2036, +2103,2037,2104, +2038,2104,2037, +2104,2038,2105, +2039,2105,2038, +2105,2039,2106, +2040,2106,2039, +2106,2040,2107, +2041,2107,2040, +2107,2041,2108, +2042,2108,2041, +2108,2042,2109, +2043,2109,2042, +2109,2043,2110, +2044,2110,2043, +2110,2044,2111, +2045,2111,2044, +2112,2046,2113, +2047,2113,2046, +2113,2047,2114, +2048,2114,2047, +2114,2048,2115, +2049,2115,2048, +2115,2049,2116, +2050,2116,2049, +2116,2050,2117, +2051,2117,2050, +2117,2051,2118, +2052,2118,2051, +2118,2052,2119, +2053,2119,2052, +2119,2053,2120, +2054,2120,2053, +2120,2054,2121, +2055,2121,2054, +2121,2055,2122, +2056,2122,2055, +2122,2056,2123, +2057,2123,2056, +2123,2057,2124, +2058,2124,2057, +2124,2058,2125, +2059,2125,2058, +2125,2059,2126, +2060,2126,2059, +2126,2060,2127, +2061,2127,2060, +2127,2061,2128, +2062,2128,2061, +2128,2062,2129, +2063,2129,2062, +2129,2063,2130, +2064,2130,2063, +2130,2064,2131, +2065,2131,2064, +2131,2065,2132, +2066,2132,2065, +2132,2066,2133, +2067,2133,2066, +2133,2067,2134, +2068,2134,2067, +2134,2068,2135, +2069,2135,2068, +2135,2069,2136, +2070,2136,2069, +2136,2070,2137, +2071,2137,2070, +2137,2071,2138, +2072,2138,2071, +2138,2072,2139, +2073,2139,2072, +2139,2073,2140, +2074,2140,2073, +2140,2074,2141, +2075,2141,2074, +2141,2075,2142, +2076,2142,2075, +2142,2076,2143, +2077,2143,2076, +2143,2077,2144, +2078,2144,2077, +2144,2078,2145, +2079,2145,2078, +2145,2079,2146, +2080,2146,2079, +2146,2080,2147, +2081,2147,2080, +2147,2081,2148, +2082,2148,2081, +2148,2082,2149, +2083,2149,2082, +2149,2083,2150, +2084,2150,2083, +2150,2084,2151, +2085,2151,2084, +2151,2085,2152, +2086,2152,2085, +2152,2086,2153, +2087,2153,2086, +2153,2087,2154, +2088,2154,2087, +2154,2088,2155, +2089,2155,2088, +2155,2089,2156, +2090,2156,2089, +2156,2090,2157, +2091,2157,2090, +2157,2091,2158, +2092,2158,2091, +2158,2092,2159, +2093,2159,2092, +2159,2093,2160, +2094,2160,2093, +2160,2094,2161, +2095,2161,2094, +2161,2095,2162, +2096,2162,2095, +2162,2096,2163, +2097,2163,2096, +2163,2097,2164, +2098,2164,2097, +2164,2098,2165, +2099,2165,2098, +2165,2099,2166, +2100,2166,2099, +2166,2100,2167, +2101,2167,2100, +2167,2101,2168, +2102,2168,2101, +2168,2102,2169, +2103,2169,2102, +2169,2103,2170, +2104,2170,2103, +2170,2104,2171, +2105,2171,2104, +2171,2105,2172, +2106,2172,2105, +2172,2106,2173, +2107,2173,2106, +2173,2107,2174, +2108,2174,2107, +2174,2108,2175, +2109,2175,2108, +2175,2109,2176, +2110,2176,2109, +2176,2110,2177, +2111,2177,2110, +2178,2112,2179, +2113,2179,2112, +2179,2113,2180, +2114,2180,2113, +2180,2114,2181, +2115,2181,2114, +2181,2115,2182, +2116,2182,2115, +2182,2116,2183, +2117,2183,2116, +2183,2117,2184, +2118,2184,2117, +2184,2118,2185, +2119,2185,2118, +2185,2119,2186, +2120,2186,2119, +2186,2120,2187, +2121,2187,2120, +2187,2121,2188, +2122,2188,2121, +2188,2122,2189, +2123,2189,2122, +2189,2123,2190, +2124,2190,2123, +2190,2124,2191, +2125,2191,2124, +2191,2125,2192, +2126,2192,2125, +2192,2126,2193, +2127,2193,2126, +2193,2127,2194, +2128,2194,2127, +2194,2128,2195, +2129,2195,2128, +2195,2129,2196, +2130,2196,2129, +2196,2130,2197, +2131,2197,2130, +2197,2131,2198, +2132,2198,2131, +2198,2132,2199, +2133,2199,2132, +2199,2133,2200, +2134,2200,2133, +2200,2134,2201, +2135,2201,2134, +2201,2135,2202, +2136,2202,2135, +2202,2136,2203, +2137,2203,2136, +2203,2137,2204, +2138,2204,2137, +2204,2138,2205, +2139,2205,2138, +2205,2139,2206, +2140,2206,2139, +2206,2140,2207, +2141,2207,2140, +2207,2141,2208, +2142,2208,2141, +2208,2142,2209, +2143,2209,2142, +2209,2143,2210, +2144,2210,2143, +2210,2144,2211, +2145,2211,2144, +2211,2145,2212, +2146,2212,2145, +2212,2146,2213, +2147,2213,2146, +2213,2147,2214, +2148,2214,2147, +2214,2148,2215, +2149,2215,2148, +2215,2149,2216, +2150,2216,2149, +2216,2150,2217, +2151,2217,2150, +2217,2151,2218, +2152,2218,2151, +2218,2152,2219, +2153,2219,2152, +2219,2153,2220, +2154,2220,2153, +2220,2154,2221, +2155,2221,2154, +2221,2155,2222, +2156,2222,2155, +2222,2156,2223, +2157,2223,2156, +2223,2157,2224, +2158,2224,2157, +2224,2158,2225, +2159,2225,2158, +2225,2159,2226, +2160,2226,2159, +2226,2160,2227, +2161,2227,2160, +2227,2161,2228, +2162,2228,2161, +2228,2162,2229, +2163,2229,2162, +2229,2163,2230, +2164,2230,2163, +2230,2164,2231, +2165,2231,2164, +2231,2165,2232, +2166,2232,2165, +2232,2166,2233, +2167,2233,2166, +2233,2167,2234, +2168,2234,2167, +2234,2168,2235, +2169,2235,2168, +2235,2169,2236, +2170,2236,2169, +2236,2170,2237, +2171,2237,2170, +2237,2171,2238, +2172,2238,2171, +2238,2172,2239, +2173,2239,2172, +2239,2173,2240, +2174,2240,2173, +2240,2174,2241, +2175,2241,2174, +2241,2175,2242, +2176,2242,2175, +2242,2176,2243, +2177,2243,2176, +2244,2178,2245, +2179,2245,2178, +2245,2179,2246, +2180,2246,2179, +2246,2180,2247, +2181,2247,2180, +2247,2181,2248, +2182,2248,2181, +2248,2182,2249, +2183,2249,2182, +2249,2183,2250, +2184,2250,2183, +2250,2184,2251, +2185,2251,2184, +2251,2185,2252, +2186,2252,2185, +2252,2186,2253, +2187,2253,2186, +2253,2187,2254, +2188,2254,2187, +2254,2188,2255, +2189,2255,2188, +2255,2189,2256, +2190,2256,2189, +2256,2190,2257, +2191,2257,2190, +2257,2191,2258, +2192,2258,2191, +2258,2192,2259, +2193,2259,2192, +2259,2193,2260, +2194,2260,2193, +2260,2194,2261, +2195,2261,2194, +2261,2195,2262, +2196,2262,2195, +2262,2196,2263, +2197,2263,2196, +2263,2197,2264, +2198,2264,2197, +2264,2198,2265, +2199,2265,2198, +2265,2199,2266, +2200,2266,2199, +2266,2200,2267, +2201,2267,2200, +2267,2201,2268, +2202,2268,2201, +2268,2202,2269, +2203,2269,2202, +2269,2203,2270, +2204,2270,2203, +2270,2204,2271, +2205,2271,2204, +2271,2205,2272, +2206,2272,2205, +2272,2206,2273, +2207,2273,2206, +2273,2207,2274, +2208,2274,2207, +2274,2208,2275, +2209,2275,2208, +2275,2209,2276, +2210,2276,2209, +2276,2210,2277, +2211,2277,2210, +2277,2211,2278, +2212,2278,2211, +2278,2212,2279, +2213,2279,2212, +2279,2213,2280, +2214,2280,2213, +2280,2214,2281, +2215,2281,2214, +2281,2215,2282, +2216,2282,2215, +2282,2216,2283, +2217,2283,2216, +2283,2217,2284, +2218,2284,2217, +2284,2218,2285, +2219,2285,2218, +2285,2219,2286, +2220,2286,2219, +2286,2220,2287, +2221,2287,2220, +2287,2221,2288, +2222,2288,2221, +2288,2222,2289, +2223,2289,2222, +2289,2223,2290, +2224,2290,2223, +2290,2224,2291, +2225,2291,2224, +2291,2225,2292, +2226,2292,2225, +2292,2226,2293, +2227,2293,2226, +2293,2227,2294, +2228,2294,2227, +2294,2228,2295, +2229,2295,2228, +2295,2229,2296, +2230,2296,2229, +2296,2230,2297, +2231,2297,2230, +2297,2231,2298, +2232,2298,2231, +2298,2232,2299, +2233,2299,2232, +2299,2233,2300, +2234,2300,2233, +2300,2234,2301, +2235,2301,2234, +2301,2235,2302, +2236,2302,2235, +2302,2236,2303, +2237,2303,2236, +2303,2237,2304, +2238,2304,2237, +2304,2238,2305, +2239,2305,2238, +2305,2239,2306, +2240,2306,2239, +2306,2240,2307, +2241,2307,2240, +2307,2241,2308, +2242,2308,2241, +2308,2242,2309, +2243,2309,2242, +}; + +#define Landscape07VtxCount 2240 +#define Landscape07IdxCount 12852 + +btScalar Landscape07Vtx[] = { +3.90625f,49.6769f,-121.094f, +3.90625f,48.3887f,-117.188f, +7.8125f,48.8687f,-121.094f, +7.8125f,48.004f,-117.188f, +11.7188f,47.3453f,-121.094f, +11.7188f,46.8723f,-117.188f, +15.625f,44.9132f,-121.094f, +15.625f,45.5005f,-117.188f, +19.5313f,43.1526f,-121.094f, +19.5313f,43.3644f,-117.188f, +23.4375f,41.3946f,-121.094f, +23.4375f,42.3352f,-117.188f, +27.3438f,40.1349f,-121.094f, +27.3438f,41.1562f,-117.188f, +31.25f,39.2733f,-121.094f, +31.25f,39.1736f,-117.188f, +35.1563f,38.3718f,-121.094f, +35.1563f,38.0627f,-117.188f, +39.0625f,37.16f,-121.094f, +39.0625f,36.4728f,-117.188f, +42.9688f,35.2678f,-121.094f, +42.9688f,34.8001f,-117.188f, +46.875f,32.8529f,-121.094f, +46.875f,32.5103f,-117.188f, +50.7813f,32.0924f,-121.094f, +50.7813f,31.6328f,-117.188f, +54.6875f,33.2013f,-121.094f, +54.6875f,31.6106f,-117.188f, +58.5938f,34.1499f,-121.094f, +58.5938f,32.3004f,-117.188f, +62.5f,33.7675f,-121.094f, +62.5f,32.696f,-117.188f, +66.4063f,34.4892f,-121.094f, +66.4063f,33.3795f,-117.188f, +70.3125f,34.7441f,-121.094f, +70.3125f,33.9696f,-117.188f, +74.2188f,35.4435f,-121.094f, +74.2188f,34.9211f,-117.188f, +78.125f,36.6876f,-121.094f, +78.125f,36.7686f,-117.188f, +82.0313f,37.8831f,-121.094f, +82.0313f,37.7676f,-117.188f, +85.9375f,37.8533f,-121.094f, +85.9375f,37.8174f,-117.188f, +89.8438f,38.2467f,-121.094f, +89.8438f,38.2878f,-117.188f, +93.75f,39.5884f,-121.094f, +93.75f,39.6151f,-117.188f, +97.6563f,39.7164f,-121.094f, +97.6563f,39.7422f,-117.188f, +101.563f,40.296f,-121.094f, +101.563f,40.9611f,-117.188f, +105.469f,40.7222f,-121.094f, +105.469f,40.8932f,-117.188f, +109.375f,40.1304f,-121.094f, +109.375f,40.6603f,-117.188f, +113.281f,39.4566f,-121.094f, +113.281f,40.2935f,-117.188f, +117.188f,39.003f,-121.094f, +117.188f,39.8681f,-117.188f, +121.094f,38.091f,-121.094f, +121.094f,39.0965f,-117.188f, +125.0f,37.216f,-121.094f, +125.0f,37.1333f,-117.188f, +128.906f,35.4631f,-121.094f, +128.906f,35.5222f,-117.188f, +132.813f,33.4698f,-121.094f, +132.813f,33.9068f,-117.188f, +136.719f,31.5516f,-121.094f, +136.719f,32.2618f,-117.188f, +140.625f,28.6676f,-121.094f, +140.625f,29.8657f,-117.188f, +144.531f,26.5656f,-121.094f, +144.531f,28.1704f,-117.188f, +148.438f,24.1962f,-121.094f, +148.438f,27.1495f,-117.188f, +152.344f,22.2193f,-121.094f, +152.344f,24.5217f,-117.188f, +156.25f,20.1818f,-121.094f, +156.25f,22.0419f,-117.188f, +160.156f,17.6116f,-121.094f, +160.156f,19.9238f,-117.188f, +164.063f,15.5398f,-121.094f, +164.063f,17.6875f,-117.188f, +167.969f,13.7972f,-121.094f, +167.969f,15.5636f,-117.188f, +171.875f,11.7291f,-121.094f, +171.875f,13.5497f,-117.188f, +175.781f,9.31738f,-121.094f, +175.781f,11.2761f,-117.188f, +179.688f,6.60425f,-121.094f, +179.688f,8.95864f,-117.188f, +183.594f,4.50127f,-121.094f, +183.594f,7.04623f,-117.188f, +187.5f,2.77579f,-121.094f, +187.5f,4.83635f,-117.188f, +191.406f,1.39292f,-121.094f, +191.406f,2.76046f,-117.188f, +195.313f,-1.41093f,-121.094f, +195.313f,0.190119f,-117.188f, +199.219f,-2.1383f,-121.094f, +199.219f,-0.558379f,-117.188f, +203.125f,-2.43203f,-121.094f, +203.125f,-1.03303f,-117.188f, +207.031f,-3.74398f,-121.094f, +207.031f,-2.17563f,-117.188f, +210.938f,-4.31531f,-121.094f, +210.938f,-1.91155f,-117.188f, +214.844f,-5.42965f,-121.094f, +214.844f,-3.00018f,-117.188f, +218.75f,-6.70056f,-121.094f, +218.75f,-4.26691f,-117.188f, +222.656f,-6.19564f,-121.094f, +222.656f,-5.15855f,-117.188f, +226.563f,-4.68254f,-121.094f, +226.563f,-3.46348f,-117.188f, +230.469f,-3.31858f,-121.094f, +230.469f,-2.16077f,-117.188f, +234.375f,-3.88428f,-121.094f, +234.375f,-1.47785f,-117.188f, +238.281f,-3.80321f,-121.094f, +238.281f,-1.78424f,-117.188f, +242.188f,-3.43571f,-121.094f, +242.188f,-1.00317f,-117.188f, +246.094f,-3.77556f,-121.094f, +246.094f,-1.97981f,-117.188f, +250.0f,-3.83169f,-121.094f, +250.0f,-2.29372f,-117.188f, +3.90625f,50.3021f,-125.0f, +7.8125f,50.0186f,-125.0f, +11.7188f,47.8026f,-125.0f, +15.625f,45.4122f,-125.0f, +19.5313f,42.7204f,-125.0f, +23.4375f,42.1093f,-125.0f, +27.3438f,41.0672f,-125.0f, +31.25f,40.3016f,-125.0f, +35.1563f,38.401f,-125.0f, +39.0625f,36.5811f,-125.0f, +42.9688f,35.0771f,-125.0f, +46.875f,32.9255f,-125.0f, +50.7813f,31.2736f,-125.0f, +54.6875f,33.4622f,-125.0f, +58.5938f,34.314f,-125.0f, +62.5f,34.4185f,-125.0f, +66.4063f,34.621f,-125.0f, +70.3125f,34.9532f,-125.0f, +74.2188f,35.7305f,-125.0f, +78.125f,37.4446f,-125.0f, +82.0313f,37.6824f,-125.0f, +85.9375f,37.9835f,-125.0f, +89.8438f,38.5713f,-125.0f, +93.75f,39.56f,-125.0f, +97.6563f,40.0645f,-125.0f, +101.563f,39.9237f,-125.0f, +105.469f,39.8912f,-125.0f, +109.375f,39.9678f,-125.0f, +113.281f,39.7665f,-125.0f, +117.188f,38.758f,-125.0f, +121.094f,37.6738f,-125.0f, +125.0f,36.834f,-125.0f, +128.906f,34.7637f,-125.0f, +132.813f,31.9691f,-125.0f, +136.719f,30.7311f,-125.0f, +140.625f,27.9768f,-125.0f, +144.531f,25.22f,-125.0f, +148.438f,22.2616f,-125.0f, +152.344f,20.6399f,-125.0f, +156.25f,18.9363f,-125.0f, +160.156f,16.8778f,-125.0f, +164.063f,14.7425f,-125.0f, +167.969f,12.4299f,-125.0f, +171.875f,10.1017f,-125.0f, +175.781f,7.82169f,-125.0f, +179.688f,5.46502f,-125.0f, +183.594f,2.71076f,-125.0f, +187.5f,1.07736f,-125.0f, +191.406f,-0.592638f,-125.0f, +195.313f,-2.99173f,-125.0f, +199.219f,-4.30517f,-125.0f, +203.125f,-4.79591f,-125.0f, +207.031f,-6.32671f,-125.0f, +210.938f,-6.6914f,-125.0f, +214.844f,-8.34188f,-125.0f, +218.75f,-8.94371f,-125.0f, +222.656f,-7.16417f,-125.0f, +226.563f,-5.53904f,-125.0f, +230.469f,-5.10207f,-125.0f, +234.375f,-5.77507f,-125.0f, +238.281f,-5.5948f,-125.0f, +242.188f,-5.81224f,-125.0f, +246.094f,-5.48291f,-125.0f, +250.0f,-5.3221f,-125.0f, +3.90625f,50.4716f,-128.906f, +7.8125f,50.3922f,-128.906f, +11.7188f,48.0997f,-128.906f, +15.625f,44.9895f,-128.906f, +19.5313f,43.3038f,-128.906f, +23.4375f,42.8795f,-128.906f, +27.3438f,42.0905f,-128.906f, +31.25f,40.0566f,-128.906f, +35.1563f,37.7024f,-128.906f, +39.0625f,35.7533f,-128.906f, +42.9688f,32.9949f,-128.906f, +46.875f,31.7476f,-128.906f, +50.7813f,30.9413f,-128.906f, +54.6875f,31.9364f,-128.906f, +58.5938f,33.2028f,-128.906f, +62.5f,34.0103f,-128.906f, +66.4063f,34.3126f,-128.906f, +70.3125f,34.6096f,-128.906f, +74.2188f,35.8861f,-128.906f, +78.125f,36.5754f,-128.906f, +82.0313f,36.9009f,-128.906f, +85.9375f,37.369f,-128.906f, +89.8438f,38.2734f,-128.906f, +93.75f,38.7518f,-128.906f, +97.6563f,39.7576f,-128.906f, +101.563f,39.3413f,-128.906f, +105.469f,40.4224f,-128.906f, +109.375f,40.506f,-128.906f, +113.281f,39.7509f,-128.906f, +117.188f,38.6208f,-128.906f, +121.094f,37.1513f,-128.906f, +125.0f,36.003f,-128.906f, +128.906f,34.1307f,-128.906f, +132.813f,31.5523f,-128.906f, +136.719f,29.2003f,-128.906f, +140.625f,26.3718f,-128.906f, +144.531f,24.0851f,-128.906f, +148.438f,21.0492f,-128.906f, +152.344f,18.9709f,-128.906f, +156.25f,16.5536f,-128.906f, +160.156f,14.5588f,-128.906f, +164.063f,12.8386f,-128.906f, +167.969f,11.3092f,-128.906f, +171.875f,9.19396f,-128.906f, +175.781f,6.84617f,-128.906f, +179.688f,3.80062f,-128.906f, +183.594f,0.734751f,-128.906f, +187.5f,0.121523f,-128.906f, +191.406f,-1.9203f,-128.906f, +195.313f,-5.35291f,-128.906f, +199.219f,-7.06575f,-128.906f, +203.125f,-8.27325f,-128.906f, +207.031f,-8.82541f,-128.906f, +210.938f,-9.36185f,-128.906f, +214.844f,-10.8597f,-128.906f, +218.75f,-10.695f,-128.906f, +222.656f,-8.91012f,-128.906f, +226.563f,-8.24825f,-128.906f, +230.469f,-7.79624f,-128.906f, +234.375f,-6.74578f,-128.906f, +238.281f,-7.41285f,-128.906f, +242.188f,-7.01421f,-128.906f, +246.094f,-6.91669f,-128.906f, +250.0f,-6.09876f,-128.906f, +3.90625f,49.1054f,-132.813f, +7.8125f,48.771f,-132.813f, +11.7188f,46.9765f,-132.813f, +15.625f,44.4736f,-132.813f, +19.5313f,43.2026f,-132.813f, +23.4375f,42.2898f,-132.813f, +27.3438f,41.7492f,-132.813f, +31.25f,39.5792f,-132.813f, +35.1563f,36.5653f,-132.813f, +39.0625f,33.5612f,-132.813f, +42.9688f,31.9604f,-132.813f, +46.875f,30.953f,-132.813f, +50.7813f,30.5912f,-132.813f, +54.6875f,31.76f,-132.813f, +58.5938f,33.0843f,-132.813f, +62.5f,33.4323f,-132.813f, +66.4063f,33.9264f,-132.813f, +70.3125f,33.9268f,-132.813f, +74.2188f,33.8122f,-132.813f, +78.125f,34.9456f,-132.813f, +82.0313f,35.6308f,-132.813f, +85.9375f,35.8317f,-132.813f, +89.8438f,36.8255f,-132.813f, +93.75f,37.5781f,-132.813f, +97.6563f,39.0469f,-132.813f, +101.563f,38.905f,-132.813f, +105.469f,39.3656f,-132.813f, +109.375f,39.9706f,-132.813f, +113.281f,38.8077f,-132.813f, +117.188f,37.8378f,-132.813f, +121.094f,36.8368f,-132.813f, +125.0f,35.8474f,-132.813f, +128.906f,33.8502f,-132.813f, +132.813f,31.6251f,-132.813f, +136.719f,28.2781f,-132.813f, +140.625f,24.9841f,-132.813f, +144.531f,22.2281f,-132.813f, +148.438f,19.2974f,-132.813f, +152.344f,17.1516f,-132.813f, +156.25f,14.7654f,-132.813f, +160.156f,13.1833f,-132.813f, +164.063f,11.0184f,-132.813f, +167.969f,9.1589f,-132.813f, +171.875f,6.82631f,-132.813f, +175.781f,4.30633f,-132.813f, +179.688f,2.04751f,-132.813f, +183.594f,-0.74554f,-132.813f, +187.5f,-1.24688f,-132.813f, +191.406f,-3.70884f,-132.813f, +195.313f,-7.20423f,-132.813f, +199.219f,-9.63057f,-132.813f, +203.125f,-10.6411f,-132.813f, +207.031f,-11.1561f,-132.813f, +210.938f,-11.9998f,-132.813f, +214.844f,-13.1369f,-132.813f, +218.75f,-12.4543f,-132.813f, +222.656f,-11.5031f,-132.813f, +226.563f,-11.4632f,-132.813f, +230.469f,-10.5609f,-132.813f, +234.375f,-9.96017f,-132.813f, +238.281f,-9.64047f,-132.813f, +242.188f,-8.79112f,-132.813f, +246.094f,-8.33514f,-132.813f, +250.0f,-6.32649f,-132.813f, +3.90625f,47.9f,-136.719f, +7.8125f,47.0423f,-136.719f, +11.7188f,46.1087f,-136.719f, +15.625f,42.8209f,-136.719f, +19.5313f,41.8846f,-136.719f, +23.4375f,41.4071f,-136.719f, +27.3438f,39.6798f,-136.719f, +31.25f,38.1881f,-136.719f, +35.1563f,35.3952f,-136.719f, +39.0625f,31.8297f,-136.719f, +42.9688f,31.014f,-136.719f, +46.875f,29.29f,-136.719f, +50.7813f,29.4455f,-136.719f, +54.6875f,30.368f,-136.719f, +58.5938f,31.6261f,-136.719f, +62.5f,31.8803f,-136.719f, +66.4063f,32.8102f,-136.719f, +70.3125f,33.4331f,-136.719f, +74.2188f,33.19f,-136.719f, +78.125f,33.74f,-136.719f, +82.0313f,35.1047f,-136.719f, +85.9375f,36.2436f,-136.719f, +89.8438f,36.4928f,-136.719f, +93.75f,36.192f,-136.719f, +97.6563f,37.547f,-136.719f, +101.563f,38.0632f,-136.719f, +105.469f,38.6551f,-136.719f, +109.375f,38.4484f,-136.719f, +113.281f,37.8421f,-136.719f, +117.188f,37.5588f,-136.719f, +121.094f,37.278f,-136.719f, +125.0f,35.3541f,-136.719f, +128.906f,33.0939f,-136.719f, +132.813f,30.522f,-136.719f, +136.719f,27.5957f,-136.719f, +140.625f,24.4595f,-136.719f, +144.531f,21.0335f,-136.719f, +148.438f,18.0163f,-136.719f, +152.344f,15.3659f,-136.719f, +156.25f,13.4036f,-136.719f, +160.156f,11.6819f,-136.719f, +164.063f,9.68686f,-136.719f, +167.969f,7.56782f,-136.719f, +171.875f,4.49435f,-136.719f, +175.781f,1.55284f,-136.719f, +179.688f,0.275057f,-136.719f, +183.594f,-2.20168f,-136.719f, +187.5f,-3.16842f,-136.719f, +191.406f,-5.74212f,-136.719f, +195.313f,-8.33918f,-136.719f, +199.219f,-11.9926f,-136.719f, +203.125f,-13.7382f,-136.719f, +207.031f,-14.2163f,-136.719f, +210.938f,-14.76f,-136.719f, +214.844f,-14.7917f,-136.719f, +218.75f,-15.4594f,-136.719f, +222.656f,-14.7722f,-136.719f, +226.563f,-14.7687f,-136.719f, +230.469f,-13.0502f,-136.719f, +234.375f,-12.7522f,-136.719f, +238.281f,-12.1277f,-136.719f, +242.188f,-11.9805f,-136.719f, +246.094f,-9.26664f,-136.719f, +250.0f,-6.42671f,-136.719f, +3.90625f,47.2681f,-140.625f, +7.8125f,46.3513f,-140.625f, +11.7188f,45.1181f,-140.625f, +15.625f,42.9593f,-140.625f, +19.5313f,40.04f,-140.625f, +23.4375f,38.1657f,-140.625f, +27.3438f,37.2537f,-140.625f, +31.25f,35.6767f,-140.625f, +35.1563f,33.3413f,-140.625f, +39.0625f,30.7556f,-140.625f, +42.9688f,29.0258f,-140.625f, +46.875f,27.8122f,-140.625f, +50.7813f,27.4512f,-140.625f, +54.6875f,28.1912f,-140.625f, +58.5938f,29.8142f,-140.625f, +62.5f,30.1394f,-140.625f, +66.4063f,30.7105f,-140.625f, +70.3125f,31.9295f,-140.625f, +74.2188f,32.6689f,-140.625f, +78.125f,32.9232f,-140.625f, +82.0313f,35.5221f,-140.625f, +85.9375f,36.1785f,-140.625f, +89.8438f,35.864f,-140.625f, +93.75f,35.2473f,-140.625f, +97.6563f,35.6334f,-140.625f, +101.563f,36.5759f,-140.625f, +105.469f,37.2506f,-140.625f, +109.375f,36.7249f,-140.625f, +113.281f,36.4287f,-140.625f, +117.188f,36.6819f,-140.625f, +121.094f,36.4294f,-140.625f, +125.0f,35.2358f,-140.625f, +128.906f,32.9869f,-140.625f, +132.813f,30.156f,-140.625f, +136.719f,27.0471f,-140.625f, +140.625f,23.8554f,-140.625f, +144.531f,20.3993f,-140.625f, +148.438f,16.6224f,-140.625f, +152.344f,13.058f,-140.625f, +156.25f,11.1345f,-140.625f, +160.156f,9.35133f,-140.625f, +164.063f,7.36194f,-140.625f, +167.969f,5.31819f,-140.625f, +171.875f,2.78652f,-140.625f, +175.781f,0.868982f,-140.625f, +179.688f,-1.31465f,-140.625f, +183.594f,-3.64199f,-140.625f, +187.5f,-5.38333f,-140.625f, +191.406f,-8.08251f,-140.625f, +195.313f,-10.9184f,-140.625f, +199.219f,-14.2737f,-140.625f, +203.125f,-16.1495f,-140.625f, +207.031f,-16.9134f,-140.625f, +210.938f,-16.9575f,-140.625f, +214.844f,-17.6023f,-140.625f, +218.75f,-17.6633f,-140.625f, +222.656f,-17.159f,-140.625f, +226.563f,-16.2062f,-140.625f, +230.469f,-15.7685f,-140.625f, +234.375f,-15.0547f,-140.625f, +238.281f,-14.7858f,-140.625f, +242.188f,-12.8534f,-140.625f, +246.094f,-9.20599f,-140.625f, +250.0f,-5.60644f,-140.625f, +3.90625f,45.2398f,-144.531f, +7.8125f,45.0428f,-144.531f, +11.7188f,44.1179f,-144.531f, +15.625f,42.444f,-144.531f, +19.5313f,39.732f,-144.531f, +23.4375f,37.0479f,-144.531f, +27.3438f,34.3624f,-144.531f, +31.25f,33.2513f,-144.531f, +35.1563f,31.1146f,-144.531f, +39.0625f,29.2726f,-144.531f, +42.9688f,27.3159f,-144.531f, +46.875f,27.1241f,-144.531f, +50.7813f,26.6524f,-144.531f, +54.6875f,26.3337f,-144.531f, +58.5938f,27.8201f,-144.531f, +62.5f,27.8456f,-144.531f, +66.4063f,27.8306f,-144.531f, +70.3125f,29.8911f,-144.531f, +74.2188f,31.0667f,-144.531f, +78.125f,32.5778f,-144.531f, +82.0313f,34.5337f,-144.531f, +85.9375f,35.1457f,-144.531f, +89.8438f,34.7649f,-144.531f, +93.75f,34.0929f,-144.531f, +97.6563f,34.2934f,-144.531f, +101.563f,34.8046f,-144.531f, +105.469f,36.2496f,-144.531f, +109.375f,35.8351f,-144.531f, +113.281f,35.8228f,-144.531f, +117.188f,35.7495f,-144.531f, +121.094f,34.832f,-144.531f, +125.0f,34.3351f,-144.531f, +128.906f,32.4744f,-144.531f, +132.813f,29.6967f,-144.531f, +136.719f,26.263f,-144.531f, +140.625f,23.3556f,-144.531f, +144.531f,19.3517f,-144.531f, +148.438f,14.458f,-144.531f, +152.344f,11.2423f,-144.531f, +156.25f,9.75514f,-144.531f, +160.156f,7.96146f,-144.531f, +164.063f,5.67024f,-144.531f, +167.969f,4.08006f,-144.531f, +171.875f,1.71102f,-144.531f, +175.781f,-0.915369f,-144.531f, +179.688f,-2.66343f,-144.531f, +183.594f,-5.5816f,-144.531f, +187.5f,-7.79353f,-144.531f, +191.406f,-10.1772f,-144.531f, +195.313f,-13.5463f,-144.531f, +199.219f,-16.0692f,-144.531f, +203.125f,-17.2505f,-144.531f, +207.031f,-18.7241f,-144.531f, +210.938f,-18.7295f,-144.531f, +214.844f,-19.3f,-144.531f, +218.75f,-20.3181f,-144.531f, +222.656f,-19.4871f,-144.531f, +226.563f,-18.5465f,-144.531f, +230.469f,-17.525f,-144.531f, +234.375f,-16.5076f,-144.531f, +238.281f,-15.0993f,-144.531f, +242.188f,-13.0716f,-144.531f, +246.094f,-9.99063f,-144.531f, +250.0f,-5.64288f,-144.531f, +3.90625f,43.4167f,-148.438f, +7.8125f,43.0193f,-148.438f, +11.7188f,42.6242f,-148.438f, +15.625f,40.8831f,-148.438f, +19.5313f,38.6824f,-148.438f, +23.4375f,36.0177f,-148.438f, +27.3438f,32.9654f,-148.438f, +31.25f,31.3995f,-148.438f, +35.1563f,29.5101f,-148.438f, +39.0625f,27.4588f,-148.438f, +42.9688f,25.129f,-148.438f, +46.875f,25.4533f,-148.438f, +50.7813f,25.7106f,-148.438f, +54.6875f,25.737f,-148.438f, +58.5938f,26.1608f,-148.438f, +62.5f,27.2373f,-148.438f, +66.4063f,27.3635f,-148.438f, +70.3125f,27.7787f,-148.438f, +74.2188f,29.0906f,-148.438f, +78.125f,31.3992f,-148.438f, +82.0313f,32.9373f,-148.438f, +85.9375f,33.743f,-148.438f, +89.8438f,34.4265f,-148.438f, +93.75f,33.525f,-148.438f, +97.6563f,33.8231f,-148.438f, +101.563f,34.6826f,-148.438f, +105.469f,35.0275f,-148.438f, +109.375f,34.4667f,-148.438f, +113.281f,34.7266f,-148.438f, +117.188f,34.0788f,-148.438f, +121.094f,33.2521f,-148.438f, +125.0f,32.1914f,-148.438f, +128.906f,30.7782f,-148.438f, +132.813f,28.8615f,-148.438f, +136.719f,25.3691f,-148.438f, +140.625f,21.5786f,-148.438f, +144.531f,17.2969f,-148.438f, +148.438f,13.1925f,-148.438f, +152.344f,10.0632f,-148.438f, +156.25f,8.32421f,-148.438f, +160.156f,6.57856f,-148.438f, +164.063f,4.18522f,-148.438f, +167.969f,2.25091f,-148.438f, +171.875f,0.445952f,-148.438f, +175.781f,-1.73703f,-148.438f, +179.688f,-3.44886f,-148.438f, +183.594f,-6.77108f,-148.438f, +187.5f,-9.26031f,-148.438f, +191.406f,-12.38f,-148.438f, +195.313f,-14.6453f,-148.438f, +199.219f,-15.8435f,-148.438f, +203.125f,-17.3242f,-148.438f, +207.031f,-19.3932f,-148.438f, +210.938f,-19.7735f,-148.438f, +214.844f,-20.1293f,-148.438f, +218.75f,-20.5777f,-148.438f, +222.656f,-20.7145f,-148.438f, +226.563f,-20.64f,-148.438f, +230.469f,-19.6971f,-148.438f, +234.375f,-17.5016f,-148.438f, +238.281f,-14.644f,-148.438f, +242.188f,-12.3094f,-148.438f, +246.094f,-10.1634f,-148.438f, +250.0f,-6.79503f,-148.438f, +3.90625f,42.7212f,-152.344f, +7.8125f,41.7463f,-152.344f, +11.7188f,40.5249f,-152.344f, +15.625f,39.5225f,-152.344f, +19.5313f,36.6967f,-152.344f, +23.4375f,34.0075f,-152.344f, +27.3438f,31.2054f,-152.344f, +31.25f,28.8502f,-152.344f, +35.1563f,27.2625f,-152.344f, +39.0625f,24.9496f,-152.344f, +42.9688f,23.5897f,-152.344f, +46.875f,23.4709f,-152.344f, +50.7813f,24.179f,-152.344f, +54.6875f,25.021f,-152.344f, +58.5938f,25.6664f,-152.344f, +62.5f,25.7063f,-152.344f, +66.4063f,26.6928f,-152.344f, +70.3125f,26.8261f,-152.344f, +74.2188f,28.2549f,-152.344f, +78.125f,30.3373f,-152.344f, +82.0313f,31.6194f,-152.344f, +85.9375f,32.9189f,-152.344f, +89.8438f,32.7162f,-152.344f, +93.75f,33.0001f,-152.344f, +97.6563f,34.4407f,-152.344f, +101.563f,35.0813f,-152.344f, +105.469f,34.4143f,-152.344f, +109.375f,33.5195f,-152.344f, +113.281f,32.927f,-152.344f, +117.188f,32.6509f,-152.344f, +121.094f,32.6775f,-152.344f, +125.0f,30.887f,-152.344f, +128.906f,28.4296f,-152.344f, +132.813f,26.5539f,-152.344f, +136.719f,24.0803f,-152.344f, +140.625f,20.196f,-152.344f, +144.531f,16.4293f,-152.344f, +148.438f,12.8243f,-152.344f, +152.344f,9.76479f,-152.344f, +156.25f,7.14206f,-152.344f, +160.156f,4.74684f,-152.344f, +164.063f,2.30008f,-152.344f, +167.969f,1.49801f,-152.344f, +171.875f,-0.62719f,-152.344f, +175.781f,-1.99004f,-152.344f, +179.688f,-4.80775f,-152.344f, +183.594f,-8.00986f,-152.344f, +187.5f,-11.4771f,-152.344f, +191.406f,-12.8743f,-152.344f, +195.313f,-13.8733f,-152.344f, +199.219f,-15.0749f,-152.344f, +203.125f,-16.9234f,-152.344f, +207.031f,-18.3258f,-152.344f, +210.938f,-19.6583f,-152.344f, +214.844f,-20.9396f,-152.344f, +218.75f,-21.8071f,-152.344f, +222.656f,-21.4908f,-152.344f, +226.563f,-21.4698f,-152.344f, +230.469f,-19.3773f,-152.344f, +234.375f,-17.0448f,-152.344f, +238.281f,-14.0123f,-152.344f, +242.188f,-11.2372f,-152.344f, +246.094f,-9.11286f,-152.344f, +250.0f,-6.76792f,-152.344f, +3.90625f,41.7368f,-156.25f, +7.8125f,40.8494f,-156.25f, +11.7188f,39.2286f,-156.25f, +15.625f,37.4784f,-156.25f, +19.5313f,36.0345f,-156.25f, +23.4375f,33.9716f,-156.25f, +27.3438f,31.3041f,-156.25f, +31.25f,28.9777f,-156.25f, +35.1563f,26.0934f,-156.25f, +39.0625f,23.7421f,-156.25f, +42.9688f,22.4401f,-156.25f, +46.875f,22.1238f,-156.25f, +50.7813f,22.6669f,-156.25f, +54.6875f,23.7702f,-156.25f, +58.5938f,24.63f,-156.25f, +62.5f,25.2145f,-156.25f, +66.4063f,26.6101f,-156.25f, +70.3125f,27.3664f,-156.25f, +74.2188f,28.121f,-156.25f, +78.125f,29.5305f,-156.25f, +82.0313f,30.4367f,-156.25f, +85.9375f,30.627f,-156.25f, +89.8438f,30.4079f,-156.25f, +93.75f,32.2186f,-156.25f, +97.6563f,33.2916f,-156.25f, +101.563f,33.8066f,-156.25f, +105.469f,32.5269f,-156.25f, +109.375f,32.0751f,-156.25f, +113.281f,31.0298f,-156.25f, +117.188f,30.9869f,-156.25f, +121.094f,30.9826f,-156.25f, +125.0f,29.0676f,-156.25f, +128.906f,26.8988f,-156.25f, +132.813f,24.0771f,-156.25f, +136.719f,21.8087f,-156.25f, +140.625f,18.8179f,-156.25f, +144.531f,14.2483f,-156.25f, +148.438f,10.9236f,-156.25f, +152.344f,9.05948f,-156.25f, +156.25f,6.86087f,-156.25f, +160.156f,3.50699f,-156.25f, +164.063f,1.14903f,-156.25f, +167.969f,-0.639847f,-156.25f, +171.875f,-2.73828f,-156.25f, +175.781f,-4.02372f,-156.25f, +179.688f,-6.15141f,-156.25f, +183.594f,-8.81231f,-156.25f, +187.5f,-10.3417f,-156.25f, +191.406f,-11.1895f,-156.25f, +195.313f,-13.1464f,-156.25f, +199.219f,-14.5401f,-156.25f, +203.125f,-15.9427f,-156.25f, +207.031f,-17.492f,-156.25f, +210.938f,-19.0599f,-156.25f, +214.844f,-21.1101f,-156.25f, +218.75f,-21.3872f,-156.25f, +222.656f,-21.1481f,-156.25f, +226.563f,-20.2836f,-156.25f, +230.469f,-18.1679f,-156.25f, +234.375f,-15.72f,-156.25f, +238.281f,-13.4579f,-156.25f, +242.188f,-10.1453f,-156.25f, +246.094f,-8.09411f,-156.25f, +250.0f,-5.46467f,-156.25f, +3.90625f,40.4755f,-160.156f, +7.8125f,39.299f,-160.156f, +11.7188f,37.3972f,-160.156f, +15.625f,36.1894f,-160.156f, +19.5313f,34.3138f,-160.156f, +23.4375f,32.893f,-160.156f, +27.3438f,30.4515f,-160.156f, +31.25f,28.5808f,-160.156f, +35.1563f,25.8839f,-160.156f, +39.0625f,23.8505f,-160.156f, +42.9688f,22.3057f,-160.156f, +46.875f,21.4418f,-160.156f, +50.7813f,21.9709f,-160.156f, +54.6875f,23.0083f,-160.156f, +58.5938f,24.899f,-160.156f, +62.5f,25.213f,-160.156f, +66.4063f,26.1428f,-160.156f, +70.3125f,27.2675f,-160.156f, +74.2188f,28.0843f,-160.156f, +78.125f,28.9474f,-160.156f, +82.0313f,29.5078f,-160.156f, +85.9375f,29.7468f,-160.156f, +89.8438f,30.8621f,-160.156f, +93.75f,31.5001f,-160.156f, +97.6563f,32.1184f,-160.156f, +101.563f,31.2692f,-160.156f, +105.469f,30.4985f,-160.156f, +109.375f,29.4368f,-160.156f, +113.281f,30.6889f,-160.156f, +117.188f,29.6238f,-160.156f, +121.094f,28.6487f,-160.156f, +125.0f,26.3174f,-160.156f, +128.906f,24.6125f,-160.156f, +132.813f,22.1993f,-160.156f, +136.719f,19.3934f,-160.156f, +140.625f,16.5457f,-160.156f, +144.531f,13.4024f,-160.156f, +148.438f,9.69887f,-160.156f, +152.344f,8.13305f,-160.156f, +156.25f,6.48921f,-160.156f, +160.156f,2.56153f,-160.156f, +164.063f,0.0733139f,-160.156f, +167.969f,-1.11414f,-160.156f, +171.875f,-3.04708f,-160.156f, +175.781f,-6.18654f,-160.156f, +179.688f,-7.4188f,-160.156f, +183.594f,-9.1718f,-160.156f, +187.5f,-9.78027f,-160.156f, +191.406f,-10.5496f,-160.156f, +195.313f,-12.7259f,-160.156f, +199.219f,-13.9068f,-160.156f, +203.125f,-15.4772f,-160.156f, +207.031f,-17.6287f,-160.156f, +210.938f,-19.2502f,-160.156f, +214.844f,-19.5824f,-160.156f, +218.75f,-19.3114f,-160.156f, +222.656f,-19.5266f,-160.156f, +226.563f,-17.8446f,-160.156f, +230.469f,-16.3027f,-160.156f, +234.375f,-14.5015f,-160.156f, +238.281f,-11.9891f,-160.156f, +242.188f,-9.40017f,-160.156f, +246.094f,-6.63794f,-160.156f, +250.0f,-3.71573f,-160.156f, +3.90625f,38.8633f,-164.063f, +7.8125f,37.4382f,-164.063f, +11.7188f,35.7214f,-164.063f, +15.625f,34.0614f,-164.063f, +19.5313f,33.0957f,-164.063f, +23.4375f,32.0369f,-164.063f, +27.3438f,29.7096f,-164.063f, +31.25f,27.3216f,-164.063f, +35.1563f,25.2446f,-164.063f, +39.0625f,23.6071f,-164.063f, +42.9688f,22.2443f,-164.063f, +46.875f,21.2807f,-164.063f, +50.7813f,21.0358f,-164.063f, +54.6875f,22.8177f,-164.063f, +58.5938f,24.4434f,-164.063f, +62.5f,25.1375f,-164.063f, +66.4063f,25.3266f,-164.063f, +70.3125f,26.6102f,-164.063f, +74.2188f,27.6569f,-164.063f, +78.125f,27.8248f,-164.063f, +82.0313f,28.0421f,-164.063f, +85.9375f,29.1719f,-164.063f, +89.8438f,29.9529f,-164.063f, +93.75f,30.947f,-164.063f, +97.6563f,30.6189f,-164.063f, +101.563f,29.7913f,-164.063f, +105.469f,27.6858f,-164.063f, +109.375f,27.3234f,-164.063f, +113.281f,27.8148f,-164.063f, +117.188f,27.3571f,-164.063f, +121.094f,26.1572f,-164.063f, +125.0f,23.8557f,-164.063f, +128.906f,21.6383f,-164.063f, +132.813f,19.0681f,-164.063f, +136.719f,16.7352f,-164.063f, +140.625f,14.4004f,-164.063f, +144.531f,11.082f,-164.063f, +148.438f,8.38754f,-164.063f, +152.344f,7.0054f,-164.063f, +156.25f,4.95122f,-164.063f, +160.156f,2.47298f,-164.063f, +164.063f,0.777691f,-164.063f, +167.969f,-1.44055f,-164.063f, +171.875f,-3.57218f,-164.063f, +175.781f,-6.3396f,-164.063f, +179.688f,-7.49937f,-164.063f, +183.594f,-9.17485f,-164.063f, +187.5f,-9.92705f,-164.063f, +191.406f,-11.0737f,-164.063f, +195.313f,-12.8264f,-164.063f, +199.219f,-14.9306f,-164.063f, +203.125f,-15.9553f,-164.063f, +207.031f,-17.0898f,-164.063f, +210.938f,-18.5283f,-164.063f, +214.844f,-18.545f,-164.063f, +218.75f,-18.553f,-164.063f, +222.656f,-17.5725f,-164.063f, +226.563f,-15.6444f,-164.063f, +230.469f,-14.565f,-164.063f, +234.375f,-12.5578f,-164.063f, +238.281f,-10.6498f,-164.063f, +242.188f,-8.28284f,-164.063f, +246.094f,-5.87682f,-164.063f, +250.0f,-2.5339f,-164.063f, +3.90625f,37.2199f,-167.969f, +7.8125f,36.6782f,-167.969f, +11.7188f,36.2393f,-167.969f, +15.625f,33.4745f,-167.969f, +19.5313f,32.0928f,-167.969f, +23.4375f,30.5662f,-167.969f, +27.3438f,28.5968f,-167.969f, +31.25f,26.4298f,-167.969f, +35.1563f,23.9469f,-167.969f, +39.0625f,22.5415f,-167.969f, +42.9688f,21.8267f,-167.969f, +46.875f,21.2097f,-167.969f, +50.7813f,21.0841f,-167.969f, +54.6875f,21.7877f,-167.969f, +58.5938f,22.9351f,-167.969f, +62.5f,24.0641f,-167.969f, +66.4063f,24.42f,-167.969f, +70.3125f,24.8355f,-167.969f, +74.2188f,25.2701f,-167.969f, +78.125f,26.0252f,-167.969f, +82.0313f,26.8612f,-167.969f, +85.9375f,27.4256f,-167.969f, +89.8438f,28.994f,-167.969f, +93.75f,29.1766f,-167.969f, +97.6563f,27.8964f,-167.969f, +101.563f,26.6384f,-167.969f, +105.469f,24.9844f,-167.969f, +109.375f,25.0669f,-167.969f, +113.281f,24.572f,-167.969f, +117.188f,23.7817f,-167.969f, +121.094f,22.2089f,-167.969f, +125.0f,19.7633f,-167.969f, +128.906f,17.7618f,-167.969f, +132.813f,15.7339f,-167.969f, +136.719f,13.4975f,-167.969f, +140.625f,11.7364f,-167.969f, +144.531f,9.85351f,-167.969f, +148.438f,8.05282f,-167.969f, +152.344f,6.97463f,-167.969f, +156.25f,5.11511f,-167.969f, +160.156f,3.12954f,-167.969f, +164.063f,1.56555f,-167.969f, +167.969f,-1.77415f,-167.969f, +171.875f,-4.16322f,-167.969f, +175.781f,-5.85214f,-167.969f, +179.688f,-7.97892f,-167.969f, +183.594f,-9.87953f,-167.969f, +187.5f,-10.2762f,-167.969f, +191.406f,-11.5319f,-167.969f, +195.313f,-13.3612f,-167.969f, +199.219f,-15.3709f,-167.969f, +203.125f,-16.5674f,-167.969f, +207.031f,-17.6903f,-167.969f, +210.938f,-17.6736f,-167.969f, +214.844f,-16.8207f,-167.969f, +218.75f,-17.0254f,-167.969f, +222.656f,-16.3676f,-167.969f, +226.563f,-14.2816f,-167.969f, +230.469f,-13.3488f,-167.969f, +234.375f,-12.0136f,-167.969f, +238.281f,-9.90116f,-167.969f, +242.188f,-7.92295f,-167.969f, +246.094f,-5.41594f,-167.969f, +250.0f,-1.87299f,-167.969f, +3.90625f,35.3898f,-171.875f, +7.8125f,35.2527f,-171.875f, +11.7188f,34.3178f,-171.875f, +15.625f,33.0736f,-171.875f, +19.5313f,31.4013f,-171.875f, +23.4375f,28.9174f,-171.875f, +27.3438f,26.607f,-171.875f, +31.25f,24.7766f,-171.875f, +35.1563f,23.21f,-171.875f, +39.0625f,21.903f,-171.875f, +42.9688f,20.775f,-171.875f, +46.875f,20.114f,-171.875f, +50.7813f,19.6974f,-171.875f, +54.6875f,20.6726f,-171.875f, +58.5938f,22.241f,-171.875f, +62.5f,22.075f,-171.875f, +66.4063f,22.6771f,-171.875f, +70.3125f,22.4456f,-171.875f, +74.2188f,22.8643f,-171.875f, +78.125f,24.7268f,-171.875f, +82.0313f,25.7019f,-171.875f, +85.9375f,26.1196f,-171.875f, +89.8438f,25.6156f,-171.875f, +93.75f,24.7881f,-171.875f, +97.6563f,24.0074f,-171.875f, +101.563f,23.4739f,-171.875f, +105.469f,23.362f,-171.875f, +109.375f,22.2604f,-171.875f, +113.281f,21.2772f,-171.875f, +117.188f,19.7815f,-171.875f, +121.094f,17.9686f,-171.875f, +125.0f,16.3211f,-171.875f, +128.906f,14.2631f,-171.875f, +132.813f,12.4914f,-171.875f, +136.719f,10.3941f,-171.875f, +140.625f,8.91613f,-171.875f, +144.531f,9.17409f,-171.875f, +148.438f,7.34154f,-171.875f, +152.344f,6.13056f,-171.875f, +156.25f,4.58272f,-171.875f, +160.156f,2.77083f,-171.875f, +164.063f,1.11181f,-171.875f, +167.969f,-2.00034f,-171.875f, +171.875f,-3.64525f,-171.875f, +175.781f,-5.12602f,-171.875f, +179.688f,-8.3325f,-171.875f, +183.594f,-10.0807f,-171.875f, +187.5f,-10.8974f,-171.875f, +191.406f,-11.9623f,-171.875f, +195.313f,-14.5041f,-171.875f, +199.219f,-15.8629f,-171.875f, +203.125f,-17.2342f,-171.875f, +207.031f,-18.2786f,-171.875f, +210.938f,-16.9405f,-171.875f, +214.844f,-16.1592f,-171.875f, +218.75f,-15.9928f,-171.875f, +222.656f,-14.9179f,-171.875f, +226.563f,-13.6308f,-171.875f, +230.469f,-12.822f,-171.875f, +234.375f,-11.0168f,-171.875f, +238.281f,-8.54191f,-171.875f, +242.188f,-6.16464f,-171.875f, +246.094f,-4.35579f,-171.875f, +250.0f,-1.83408f,-171.875f, +3.90625f,34.823f,-175.781f, +7.8125f,33.9621f,-175.781f, +11.7188f,33.7226f,-175.781f, +15.625f,31.9821f,-175.781f, +19.5313f,29.6933f,-175.781f, +23.4375f,27.247f,-175.781f, +27.3438f,25.1394f,-175.781f, +31.25f,23.3125f,-175.781f, +35.1563f,21.288f,-175.781f, +39.0625f,21.2432f,-175.781f, +42.9688f,19.7041f,-175.781f, +46.875f,19.3043f,-175.781f, +50.7813f,18.5669f,-175.781f, +54.6875f,19.5408f,-175.781f, +58.5938f,20.3028f,-175.781f, +62.5f,20.573f,-175.781f, +66.4063f,20.7874f,-175.781f, +70.3125f,21.4507f,-175.781f, +74.2188f,22.9166f,-175.781f, +78.125f,23.6886f,-175.781f, +82.0313f,24.4139f,-175.781f, +85.9375f,25.1097f,-175.781f, +89.8438f,24.1395f,-175.781f, +93.75f,23.5282f,-175.781f, +97.6563f,22.7881f,-175.781f, +101.563f,21.2087f,-175.781f, +105.469f,20.6461f,-175.781f, +109.375f,19.7212f,-175.781f, +113.281f,17.9239f,-175.781f, +117.188f,16.9142f,-175.781f, +121.094f,16.1581f,-175.781f, +125.0f,15.1171f,-175.781f, +128.906f,13.1305f,-175.781f, +132.813f,10.3035f,-175.781f, +136.719f,7.95438f,-175.781f, +140.625f,7.49768f,-175.781f, +144.531f,7.76486f,-175.781f, +148.438f,6.84318f,-175.781f, +152.344f,6.0204f,-175.781f, +156.25f,4.83875f,-175.781f, +160.156f,2.59906f,-175.781f, +164.063f,1.35973f,-175.781f, +167.969f,-1.40345f,-175.781f, +171.875f,-3.6985f,-175.781f, +175.781f,-5.60686f,-175.781f, +179.688f,-8.15914f,-175.781f, +183.594f,-9.0389f,-175.781f, +187.5f,-11.2771f,-175.781f, +191.406f,-13.1363f,-175.781f, +195.313f,-14.845f,-175.781f, +199.219f,-15.885f,-175.781f, +203.125f,-17.6421f,-175.781f, +207.031f,-18.1972f,-175.781f, +210.938f,-16.4052f,-175.781f, +214.844f,-16.4522f,-175.781f, +218.75f,-15.8261f,-175.781f, +222.656f,-13.6816f,-175.781f, +226.563f,-12.8394f,-175.781f, +230.469f,-11.638f,-175.781f, +234.375f,-8.87545f,-175.781f, +238.281f,-6.82071f,-175.781f, +242.188f,-3.82988f,-175.781f, +246.094f,-2.34543f,-175.781f, +250.0f,-0.72787f,-175.781f, +3.90625f,32.9461f,-179.688f, +7.8125f,32.0951f,-179.688f, +11.7188f,31.1161f,-179.688f, +15.625f,29.4f,-179.688f, +19.5313f,27.5196f,-179.688f, +23.4375f,26.3351f,-179.688f, +27.3438f,24.0706f,-179.688f, +31.25f,21.9677f,-179.688f, +35.1563f,20.1582f,-179.688f, +39.0625f,19.3604f,-179.688f, +42.9688f,18.5912f,-179.688f, +46.875f,18.0845f,-179.688f, +50.7813f,18.0311f,-179.688f, +54.6875f,17.5412f,-179.688f, +58.5938f,17.724f,-179.688f, +62.5f,18.1752f,-179.688f, +66.4063f,18.8435f,-179.688f, +70.3125f,20.8887f,-179.688f, +74.2188f,21.9179f,-179.688f, +78.125f,22.3044f,-179.688f, +82.0313f,22.1491f,-179.688f, +85.9375f,23.261f,-179.688f, +89.8438f,22.4285f,-179.688f, +93.75f,21.5354f,-179.688f, +97.6563f,19.6399f,-179.688f, +101.563f,18.1312f,-179.688f, +105.469f,17.0655f,-179.688f, +109.375f,16.1471f,-179.688f, +113.281f,15.8256f,-179.688f, +117.188f,14.9609f,-179.688f, +121.094f,15.4508f,-179.688f, +125.0f,14.9122f,-179.688f, +128.906f,12.3324f,-179.688f, +132.813f,9.95184f,-179.688f, +136.719f,7.31755f,-179.688f, +140.625f,6.91109f,-179.688f, +144.531f,7.29489f,-179.688f, +148.438f,6.73968f,-179.688f, +152.344f,6.0555f,-179.688f, +156.25f,5.42266f,-179.688f, +160.156f,3.84651f,-179.688f, +164.063f,2.44552f,-179.688f, +167.969f,-0.187962f,-179.688f, +171.875f,-3.00626f,-179.688f, +175.781f,-5.38527f,-179.688f, +179.688f,-6.48806f,-179.688f, +183.594f,-9.24275f,-179.688f, +187.5f,-11.5122f,-179.688f, +191.406f,-12.6735f,-179.688f, +195.313f,-14.1843f,-179.688f, +199.219f,-15.4787f,-179.688f, +203.125f,-16.6061f,-179.688f, +207.031f,-17.1175f,-179.688f, +210.938f,-16.022f,-179.688f, +214.844f,-15.9349f,-179.688f, +218.75f,-14.6169f,-179.688f, +222.656f,-13.0146f,-179.688f, +226.563f,-12.2f,-179.688f, +230.469f,-9.81169f,-179.688f, +234.375f,-6.72224f,-179.688f, +238.281f,-4.11664f,-179.688f, +242.188f,-2.18066f,-179.688f, +246.094f,-0.510192f,-179.688f, +250.0f,1.48603f,-179.688f, +3.90625f,30.0027f,-183.594f, +7.8125f,29.6114f,-183.594f, +11.7188f,28.342f,-183.594f, +15.625f,26.9383f,-183.594f, +19.5313f,26.0219f,-183.594f, +23.4375f,25.017f,-183.594f, +27.3438f,22.7851f,-183.594f, +31.25f,20.6488f,-183.594f, +35.1563f,18.7107f,-183.594f, +39.0625f,17.0893f,-183.594f, +42.9688f,17.4316f,-183.594f, +46.875f,17.3211f,-183.594f, +50.7813f,16.5318f,-183.594f, +54.6875f,16.2012f,-183.594f, +58.5938f,17.0855f,-183.594f, +62.5f,17.2472f,-183.594f, +66.4063f,18.0123f,-183.594f, +70.3125f,18.684f,-183.594f, +74.2188f,19.625f,-183.594f, +78.125f,19.9442f,-183.594f, +82.0313f,19.9236f,-183.594f, +85.9375f,19.2286f,-183.594f, +89.8438f,19.5358f,-183.594f, +93.75f,18.429f,-183.594f, +97.6563f,16.1318f,-183.594f, +101.563f,14.371f,-183.594f, +105.469f,13.894f,-183.594f, +109.375f,13.5457f,-183.594f, +113.281f,13.7348f,-183.594f, +117.188f,14.0078f,-183.594f, +121.094f,14.2652f,-183.594f, +125.0f,13.5964f,-183.594f, +128.906f,11.3529f,-183.594f, +132.813f,8.43645f,-183.594f, +136.719f,6.95213f,-183.594f, +140.625f,7.16061f,-183.594f, +144.531f,6.71961f,-183.594f, +148.438f,5.35597f,-183.594f, +152.344f,5.22708f,-183.594f, +156.25f,5.07045f,-183.594f, +160.156f,3.44698f,-183.594f, +164.063f,2.33212f,-183.594f, +167.969f,0.462143f,-183.594f, +171.875f,-2.31458f,-183.594f, +175.781f,-4.89712f,-183.594f, +179.688f,-6.66797f,-183.594f, +183.594f,-9.25909f,-183.594f, +187.5f,-9.93472f,-183.594f, +191.406f,-12.0357f,-183.594f, +195.313f,-13.4286f,-183.594f, +199.219f,-14.4671f,-183.594f, +203.125f,-15.0102f,-183.594f, +207.031f,-14.8104f,-183.594f, +210.938f,-13.4733f,-183.594f, +214.844f,-14.0715f,-183.594f, +218.75f,-14.2416f,-183.594f, +222.656f,-12.2774f,-183.594f, +226.563f,-11.1048f,-183.594f, +230.469f,-8.72548f,-183.594f, +234.375f,-5.50563f,-183.594f, +238.281f,-2.81853f,-183.594f, +242.188f,-0.555239f,-183.594f, +246.094f,1.07177f,-183.594f, +250.0f,3.1022f,-183.594f, +3.90625f,27.6405f,-187.5f, +7.8125f,27.1266f,-187.5f, +11.7188f,26.0941f,-187.5f, +15.625f,25.1443f,-187.5f, +19.5313f,24.6236f,-187.5f, +23.4375f,23.7274f,-187.5f, +27.3438f,22.5792f,-187.5f, +31.25f,19.7482f,-187.5f, +35.1563f,17.6829f,-187.5f, +39.0625f,16.5577f,-187.5f, +42.9688f,15.8636f,-187.5f, +46.875f,16.0968f,-187.5f, +50.7813f,15.5614f,-187.5f, +54.6875f,15.4655f,-187.5f, +58.5938f,16.304f,-187.5f, +62.5f,16.7706f,-187.5f, +66.4063f,16.3947f,-187.5f, +70.3125f,16.6761f,-187.5f, +74.2188f,16.7627f,-187.5f, +78.125f,17.2579f,-187.5f, +82.0313f,16.7208f,-187.5f, +85.9375f,16.5278f,-187.5f, +89.8438f,16.2251f,-187.5f, +93.75f,15.0741f,-187.5f, +97.6563f,14.2628f,-187.5f, +101.563f,12.432f,-187.5f, +105.469f,10.8877f,-187.5f, +109.375f,11.903f,-187.5f, +113.281f,12.5606f,-187.5f, +117.188f,13.2652f,-187.5f, +121.094f,13.6914f,-187.5f, +125.0f,12.7849f,-187.5f, +128.906f,10.4802f,-187.5f, +132.813f,8.75276f,-187.5f, +136.719f,6.90392f,-187.5f, +140.625f,6.91636f,-187.5f, +144.531f,6.78271f,-187.5f, +148.438f,5.25436f,-187.5f, +152.344f,4.14458f,-187.5f, +156.25f,3.58445f,-187.5f, +160.156f,3.67538f,-187.5f, +164.063f,1.88171f,-187.5f, +167.969f,1.16358f,-187.5f, +171.875f,-0.909335f,-187.5f, +175.781f,-4.00056f,-187.5f, +179.688f,-6.532f,-187.5f, +183.594f,-8.29174f,-187.5f, +187.5f,-9.0196f,-187.5f, +191.406f,-10.1189f,-187.5f, +195.313f,-11.1349f,-187.5f, +199.219f,-12.4853f,-187.5f, +203.125f,-12.7324f,-187.5f, +207.031f,-12.949f,-187.5f, +210.938f,-11.8708f,-187.5f, +214.844f,-12.2515f,-187.5f, +218.75f,-12.8455f,-187.5f, +222.656f,-10.7923f,-187.5f, +226.563f,-8.82819f,-187.5f, +230.469f,-7.36721f,-187.5f, +234.375f,-5.23714f,-187.5f, +238.281f,-2.63334f,-187.5f, +242.188f,0.485313f,-187.5f, +246.094f,2.78278f,-187.5f, +250.0f,3.96313f,-187.5f, +3.90625f,25.3652f,-191.406f, +7.8125f,24.7195f,-191.406f, +11.7188f,25.004f,-191.406f, +15.625f,24.1773f,-191.406f, +19.5313f,22.7395f,-191.406f, +23.4375f,21.4739f,-191.406f, +27.3438f,21.0405f,-191.406f, +31.25f,18.3321f,-191.406f, +35.1563f,16.9491f,-191.406f, +39.0625f,15.1898f,-191.406f, +42.9688f,14.5842f,-191.406f, +46.875f,14.234f,-191.406f, +50.7813f,14.0689f,-191.406f, +54.6875f,15.4103f,-191.406f, +58.5938f,15.0749f,-191.406f, +62.5f,14.6893f,-191.406f, +66.4063f,14.8987f,-191.406f, +70.3125f,14.4416f,-191.406f, +74.2188f,14.3436f,-191.406f, +78.125f,13.5844f,-191.406f, +82.0313f,13.3989f,-191.406f, +85.9375f,14.3892f,-191.406f, +89.8438f,13.3595f,-191.406f, +93.75f,13.3004f,-191.406f, +97.6563f,11.8557f,-191.406f, +101.563f,9.50387f,-191.406f, +105.469f,9.09049f,-191.406f, +109.375f,10.2607f,-191.406f, +113.281f,11.3275f,-191.406f, +117.188f,11.8898f,-191.406f, +121.094f,11.9585f,-191.406f, +125.0f,11.0034f,-191.406f, +128.906f,10.0704f,-191.406f, +132.813f,8.84472f,-191.406f, +136.719f,7.56972f,-191.406f, +140.625f,6.66467f,-191.406f, +144.531f,5.57509f,-191.406f, +148.438f,4.43943f,-191.406f, +152.344f,3.51469f,-191.406f, +156.25f,2.91572f,-191.406f, +160.156f,3.43161f,-191.406f, +164.063f,1.97664f,-191.406f, +167.969f,1.37279f,-191.406f, +171.875f,-0.545961f,-191.406f, +175.781f,-3.78517f,-191.406f, +179.688f,-6.09483f,-191.406f, +183.594f,-6.45627f,-191.406f, +187.5f,-7.27376f,-191.406f, +191.406f,-8.99215f,-191.406f, +195.313f,-9.89915f,-191.406f, +199.219f,-10.9608f,-191.406f, +203.125f,-10.8387f,-191.406f, +207.031f,-10.5261f,-191.406f, +210.938f,-10.1365f,-191.406f, +214.844f,-10.631f,-191.406f, +218.75f,-10.8413f,-191.406f, +222.656f,-9.03823f,-191.406f, +226.563f,-7.39571f,-191.406f, +230.469f,-4.8409f,-191.406f, +234.375f,-3.47756f,-191.406f, +238.281f,-1.63291f,-191.406f, +242.188f,1.44814f,-191.406f, +246.094f,2.93141f,-191.406f, +250.0f,4.03991f,-191.406f, +3.90625f,23.0993f,-195.313f, +7.8125f,23.2309f,-195.313f, +11.7188f,23.4293f,-195.313f, +15.625f,22.4425f,-195.313f, +19.5313f,21.4905f,-195.313f, +23.4375f,19.6567f,-195.313f, +27.3438f,18.1324f,-195.313f, +31.25f,17.3872f,-195.313f, +35.1563f,16.265f,-195.313f, +39.0625f,13.8338f,-195.313f, +42.9688f,12.7629f,-195.313f, +46.875f,13.1006f,-195.313f, +50.7813f,13.3481f,-195.313f, +54.6875f,13.8039f,-195.313f, +58.5938f,13.0621f,-195.313f, +62.5f,12.4363f,-195.313f, +66.4063f,12.748f,-195.313f, +70.3125f,12.2979f,-195.313f, +74.2188f,11.3997f,-195.313f, +78.125f,12.1637f,-195.313f, +82.0313f,12.2143f,-195.313f, +85.9375f,12.0963f,-195.313f, +89.8438f,11.3468f,-195.313f, +93.75f,11.1939f,-195.313f, +97.6563f,9.31577f,-195.313f, +101.563f,9.0203f,-195.313f, +105.469f,8.39154f,-195.313f, +109.375f,8.72501f,-195.313f, +113.281f,9.3763f,-195.313f, +117.188f,9.56963f,-195.313f, +121.094f,9.54203f,-195.313f, +125.0f,9.30859f,-195.313f, +128.906f,9.02325f,-195.313f, +132.813f,8.54457f,-195.313f, +136.719f,7.91487f,-195.313f, +140.625f,5.8935f,-195.313f, +144.531f,4.77605f,-195.313f, +148.438f,3.03324f,-195.313f, +152.344f,2.63999f,-195.313f, +156.25f,1.85254f,-195.313f, +160.156f,2.58504f,-195.313f, +164.063f,1.86646f,-195.313f, +167.969f,0.472293f,-195.313f, +171.875f,-0.819486f,-195.313f, +175.781f,-3.28005f,-195.313f, +179.688f,-4.07223f,-195.313f, +183.594f,-5.23099f,-195.313f, +187.5f,-5.93446f,-195.313f, +191.406f,-7.40083f,-195.313f, +195.313f,-9.52595f,-195.313f, +199.219f,-9.06593f,-195.313f, +203.125f,-8.64632f,-195.313f, +207.031f,-8.71126f,-195.313f, +210.938f,-7.66946f,-195.313f, +214.844f,-8.22025f,-195.313f, +218.75f,-8.77434f,-195.313f, +222.656f,-7.8003f,-195.313f, +226.563f,-5.29317f,-195.313f, +230.469f,-3.13421f,-195.313f, +234.375f,-1.47978f,-195.313f, +238.281f,0.0436352f,-195.313f, +242.188f,1.56763f,-195.313f, +246.094f,3.2707f,-195.313f, +250.0f,5.38332f,-195.313f, +3.90625f,21.5827f,-199.219f, +7.8125f,21.5884f,-199.219f, +11.7188f,22.0551f,-199.219f, +15.625f,21.1895f,-199.219f, +19.5313f,19.9629f,-199.219f, +23.4375f,18.1891f,-199.219f, +27.3438f,17.3914f,-199.219f, +31.25f,15.7832f,-199.219f, +35.1563f,13.9537f,-199.219f, +39.0625f,11.7784f,-199.219f, +42.9688f,12.6473f,-199.219f, +46.875f,12.1685f,-199.219f, +50.7813f,12.2586f,-199.219f, +54.6875f,12.032f,-199.219f, +58.5938f,12.5025f,-199.219f, +62.5f,12.2207f,-199.219f, +66.4063f,10.4332f,-199.219f, +70.3125f,10.2093f,-199.219f, +74.2188f,9.56536f,-199.219f, +78.125f,10.5041f,-199.219f, +82.0313f,10.9136f,-199.219f, +85.9375f,10.6303f,-199.219f, +89.8438f,11.148f,-199.219f, +93.75f,10.2169f,-199.219f, +97.6563f,8.56966f,-199.219f, +101.563f,8.81808f,-199.219f, +105.469f,7.92638f,-199.219f, +109.375f,7.988f,-199.219f, +113.281f,8.07342f,-199.219f, +117.188f,8.41463f,-199.219f, +121.094f,8.44317f,-199.219f, +125.0f,8.93315f,-199.219f, +128.906f,8.02242f,-199.219f, +132.813f,7.78977f,-199.219f, +136.719f,7.24422f,-199.219f, +140.625f,6.65469f,-199.219f, +144.531f,5.63698f,-199.219f, +148.438f,3.71906f,-199.219f, +152.344f,1.94989f,-199.219f, +156.25f,1.5781f,-199.219f, +160.156f,2.54367f,-199.219f, +164.063f,2.24455f,-199.219f, +167.969f,0.172967f,-199.219f, +171.875f,-1.24076f,-199.219f, +175.781f,-2.09517f,-199.219f, +179.688f,-2.60068f,-199.219f, +183.594f,-3.35838f,-199.219f, +187.5f,-5.02796f,-199.219f, +191.406f,-6.75939f,-199.219f, +195.313f,-7.86176f,-199.219f, +199.219f,-7.60703f,-199.219f, +203.125f,-7.1176f,-199.219f, +207.031f,-7.21926f,-199.219f, +210.938f,-6.354f,-199.219f, +214.844f,-6.26146f,-199.219f, +218.75f,-7.39202f,-199.219f, +222.656f,-6.10132f,-199.219f, +226.563f,-4.15677f,-199.219f, +230.469f,-1.72339f,-199.219f, +234.375f,0.220408f,-199.219f, +238.281f,1.71501f,-199.219f, +242.188f,2.32136f,-199.219f, +246.094f,3.9302f,-199.219f, +250.0f,6.99831f,-199.219f, +3.90625f,20.3179f,-203.125f, +7.8125f,19.0038f,-203.125f, +11.7188f,19.8795f,-203.125f, +15.625f,18.863f,-203.125f, +19.5313f,17.2513f,-203.125f, +23.4375f,16.7786f,-203.125f, +27.3438f,16.4605f,-203.125f, +31.25f,14.0944f,-203.125f, +35.1563f,12.6715f,-203.125f, +39.0625f,12.2869f,-203.125f, +42.9688f,12.0256f,-203.125f, +46.875f,11.4308f,-203.125f, +50.7813f,11.5543f,-203.125f, +54.6875f,10.8247f,-203.125f, +58.5938f,12.5385f,-203.125f, +62.5f,12.1754f,-203.125f, +66.4063f,10.0857f,-203.125f, +70.3125f,8.73654f,-203.125f, +74.2188f,8.35323f,-203.125f, +78.125f,8.75049f,-203.125f, +82.0313f,9.69714f,-203.125f, +85.9375f,9.93848f,-203.125f, +89.8438f,9.99533f,-203.125f, +93.75f,9.28937f,-203.125f, +97.6563f,8.19048f,-203.125f, +101.563f,7.82659f,-203.125f, +105.469f,6.70152f,-203.125f, +109.375f,6.35245f,-203.125f, +113.281f,6.80811f,-203.125f, +117.188f,7.88474f,-203.125f, +121.094f,8.76964f,-203.125f, +125.0f,9.33913f,-203.125f, +128.906f,9.12843f,-203.125f, +132.813f,7.62144f,-203.125f, +136.719f,6.32841f,-203.125f, +140.625f,6.30299f,-203.125f, +144.531f,5.78467f,-203.125f, +148.438f,4.2404f,-203.125f, +152.344f,2.7611f,-203.125f, +156.25f,1.95904f,-203.125f, +160.156f,2.27166f,-203.125f, +164.063f,2.22405f,-203.125f, +167.969f,1.12279f,-203.125f, +171.875f,-0.169061f,-203.125f, +175.781f,-0.887647f,-203.125f, +179.688f,-0.896535f,-203.125f, +183.594f,-2.41604f,-203.125f, +187.5f,-3.63423f,-203.125f, +191.406f,-6.00826f,-203.125f, +195.313f,-5.87316f,-203.125f, +199.219f,-5.18767f,-203.125f, +203.125f,-4.23762f,-203.125f, +207.031f,-4.7338f,-203.125f, +210.938f,-4.88225f,-203.125f, +214.844f,-4.82274f,-203.125f, +218.75f,-5.06338f,-203.125f, +222.656f,-5.13737f,-203.125f, +226.563f,-2.74217f,-203.125f, +230.469f,0.0831564f,-203.125f, +234.375f,2.00986f,-203.125f, +238.281f,2.89937f,-203.125f, +242.188f,3.79442f,-203.125f, +246.094f,5.43821f,-203.125f, +250.0f,8.47222f,-203.125f, +3.90625f,18.3149f,-207.031f, +7.8125f,16.9318f,-207.031f, +11.7188f,16.7123f,-207.031f, +15.625f,16.066f,-207.031f, +19.5313f,15.8401f,-207.031f, +23.4375f,14.9793f,-207.031f, +27.3438f,13.5136f,-207.031f, +31.25f,12.316f,-207.031f, +35.1563f,12.4286f,-207.031f, +39.0625f,12.5926f,-207.031f, +42.9688f,12.419f,-207.031f, +46.875f,11.7087f,-207.031f, +50.7813f,10.9033f,-207.031f, +54.6875f,10.2175f,-207.031f, +58.5938f,10.7307f,-207.031f, +62.5f,9.9283f,-207.031f, +66.4063f,9.11458f,-207.031f, +70.3125f,6.81804f,-207.031f, +74.2188f,6.85559f,-207.031f, +78.125f,6.98146f,-207.031f, +82.0313f,8.41059f,-207.031f, +85.9375f,8.81018f,-207.031f, +89.8438f,9.25882f,-207.031f, +93.75f,8.4973f,-207.031f, +97.6563f,7.11312f,-207.031f, +101.563f,6.11367f,-207.031f, +105.469f,4.54171f,-207.031f, +109.375f,3.984f,-207.031f, +113.281f,6.23536f,-207.031f, +117.188f,7.41972f,-207.031f, +121.094f,8.40005f,-207.031f, +125.0f,9.21009f,-207.031f, +128.906f,9.10113f,-207.031f, +132.813f,8.69785f,-207.031f, +136.719f,7.08314f,-207.031f, +140.625f,6.14113f,-207.031f, +144.531f,4.85123f,-207.031f, +148.438f,4.53013f,-207.031f, +152.344f,4.73052f,-207.031f, +156.25f,3.50435f,-207.031f, +160.156f,3.02093f,-207.031f, +164.063f,2.65317f,-207.031f, +167.969f,1.91936f,-207.031f, +171.875f,1.31638f,-207.031f, +175.781f,0.631767f,-207.031f, +179.688f,-0.185018f,-207.031f, +183.594f,-1.04617f,-207.031f, +187.5f,-2.59594f,-207.031f, +191.406f,-3.62219f,-207.031f, +195.313f,-3.17366f,-207.031f, +199.219f,-3.0812f,-207.031f, +203.125f,-2.21365f,-207.031f, +207.031f,-3.02851f,-207.031f, +210.938f,-4.12823f,-207.031f, +214.844f,-3.42208f,-207.031f, +218.75f,-3.83284f,-207.031f, +222.656f,-3.83483f,-207.031f, +226.563f,-1.81388f,-207.031f, +230.469f,1.06182f,-207.031f, +234.375f,3.0063f,-207.031f, +238.281f,3.97581f,-207.031f, +242.188f,5.25584f,-207.031f, +246.094f,6.1092f,-207.031f, +250.0f,9.89458f,-207.031f, +3.90625f,16.2147f,-210.938f, +7.8125f,15.8155f,-210.938f, +11.7188f,14.9704f,-210.938f, +15.625f,14.6853f,-210.938f, +19.5313f,14.3326f,-210.938f, +23.4375f,14.0488f,-210.938f, +27.3438f,12.2057f,-210.938f, +31.25f,12.7526f,-210.938f, +35.1563f,13.1468f,-210.938f, +39.0625f,12.959f,-210.938f, +42.9688f,12.3931f,-210.938f, +46.875f,11.9578f,-210.938f, +50.7813f,10.5381f,-210.938f, +54.6875f,9.28222f,-210.938f, +58.5938f,9.20117f,-210.938f, +62.5f,8.74359f,-210.938f, +66.4063f,7.58308f,-210.938f, +70.3125f,5.98903f,-210.938f, +74.2188f,5.92315f,-210.938f, +78.125f,6.30208f,-210.938f, +82.0313f,7.35787f,-210.938f, +85.9375f,7.64729f,-210.938f, +89.8438f,7.89394f,-210.938f, +93.75f,7.64523f,-210.938f, +97.6563f,5.66526f,-210.938f, +101.563f,4.1348f,-210.938f, +105.469f,2.65548f,-210.938f, +109.375f,4.20615f,-210.938f, +113.281f,5.82801f,-210.938f, +117.188f,6.92681f,-210.938f, +121.094f,8.52107f,-210.938f, +125.0f,9.29929f,-210.938f, +128.906f,10.1454f,-210.938f, +132.813f,9.39782f,-210.938f, +136.719f,8.72704f,-210.938f, +140.625f,7.91058f,-210.938f, +144.531f,5.32835f,-210.938f, +148.438f,5.30143f,-210.938f, +152.344f,4.98294f,-210.938f, +156.25f,5.27331f,-210.938f, +160.156f,4.054f,-210.938f, +164.063f,4.25352f,-210.938f, +167.969f,3.60791f,-210.938f, +171.875f,2.94898f,-210.938f, +175.781f,1.97064f,-210.938f, +179.688f,1.21275f,-210.938f, +183.594f,-0.419751f,-210.938f, +187.5f,-1.77221f,-210.938f, +191.406f,-1.94763f,-210.938f, +195.313f,-1.32172f,-210.938f, +199.219f,-1.74453f,-210.938f, +203.125f,-0.694964f,-210.938f, +207.031f,-1.77277f,-210.938f, +210.938f,-2.39571f,-210.938f, +214.844f,-2.61021f,-210.938f, +218.75f,-3.16f,-210.938f, +222.656f,-2.46606f,-210.938f, +226.563f,-0.862086f,-210.938f, +230.469f,1.4487f,-210.938f, +234.375f,3.44239f,-210.938f, +238.281f,5.41949f,-210.938f, +242.188f,6.28416f,-210.938f, +246.094f,7.24993f,-210.938f, +250.0f,10.7227f,-210.938f, +3.90625f,14.284f,-214.844f, +7.8125f,14.031f,-214.844f, +11.7188f,12.8153f,-214.844f, +15.625f,12.2914f,-214.844f, +19.5313f,12.0657f,-214.844f, +23.4375f,12.4452f,-214.844f, +27.3438f,12.703f,-214.844f, +31.25f,12.3401f,-214.844f, +35.1563f,13.2219f,-214.844f, +39.0625f,12.9074f,-214.844f, +42.9688f,12.5934f,-214.844f, +46.875f,11.4717f,-214.844f, +50.7813f,10.548f,-214.844f, +54.6875f,9.43614f,-214.844f, +58.5938f,10.0982f,-214.844f, +62.5f,9.36536f,-214.844f, +66.4063f,8.07196f,-214.844f, +70.3125f,6.4483f,-214.844f, +74.2188f,5.80499f,-214.844f, +78.125f,5.60605f,-214.844f, +82.0313f,6.64906f,-214.844f, +85.9375f,7.64402f,-214.844f, +89.8438f,8.31151f,-214.844f, +93.75f,7.97344f,-214.844f, +97.6563f,5.39549f,-214.844f, +101.563f,3.66809f,-214.844f, +105.469f,3.2001f,-214.844f, +109.375f,5.91373f,-214.844f, +113.281f,7.40339f,-214.844f, +117.188f,8.30807f,-214.844f, +121.094f,9.75774f,-214.844f, +125.0f,10.2383f,-214.844f, +128.906f,10.3408f,-214.844f, +132.813f,10.6262f,-214.844f, +136.719f,10.8818f,-214.844f, +140.625f,9.09087f,-214.844f, +144.531f,6.48291f,-214.844f, +148.438f,5.02116f,-214.844f, +152.344f,5.97543f,-214.844f, +156.25f,6.33053f,-214.844f, +160.156f,5.91049f,-214.844f, +164.063f,5.03025f,-214.844f, +167.969f,5.01201f,-214.844f, +171.875f,4.36222f,-214.844f, +175.781f,3.69208f,-214.844f, +179.688f,2.96539f,-214.844f, +183.594f,1.43789f,-214.844f, +187.5f,-0.374301f,-214.844f, +191.406f,-0.955695f,-214.844f, +195.313f,-0.123769f,-214.844f, +199.219f,-0.113436f,-214.844f, +203.125f,-0.0171993f,-214.844f, +207.031f,-1.0984f,-214.844f, +210.938f,-1.10949f,-214.844f, +214.844f,-1.92471f,-214.844f, +218.75f,-2.26183f,-214.844f, +222.656f,-1.32064f,-214.844f, +226.563f,0.209158f,-214.844f, +230.469f,2.41199f,-214.844f, +234.375f,4.66871f,-214.844f, +238.281f,6.29773f,-214.844f, +242.188f,7.20184f,-214.844f, +246.094f,8.08018f,-214.844f, +250.0f,10.3057f,-214.844f, +3.90625f,13.272f,-218.75f, +7.8125f,12.8218f,-218.75f, +11.7188f,11.8102f,-218.75f, +15.625f,11.7105f,-218.75f, +19.5313f,11.5191f,-218.75f, +23.4375f,12.1253f,-218.75f, +27.3438f,12.0266f,-218.75f, +31.25f,12.3549f,-218.75f, +35.1563f,12.3822f,-218.75f, +39.0625f,12.268f,-218.75f, +42.9688f,12.5022f,-218.75f, +46.875f,11.2878f,-218.75f, +50.7813f,10.1823f,-218.75f, +54.6875f,10.4244f,-218.75f, +58.5938f,10.0047f,-218.75f, +62.5f,9.96061f,-218.75f, +66.4063f,8.64873f,-218.75f, +70.3125f,6.45636f,-218.75f, +74.2188f,5.30254f,-218.75f, +78.125f,5.2915f,-218.75f, +82.0313f,7.2575f,-218.75f, +85.9375f,8.1568f,-218.75f, +89.8438f,8.97514f,-218.75f, +93.75f,7.72908f,-218.75f, +97.6563f,5.41501f,-218.75f, +101.563f,4.24025f,-218.75f, +105.469f,5.39134f,-218.75f, +109.375f,7.69518f,-218.75f, +113.281f,8.87616f,-218.75f, +117.188f,9.44758f,-218.75f, +121.094f,9.21473f,-218.75f, +125.0f,10.1366f,-218.75f, +128.906f,11.6088f,-218.75f, +132.813f,12.0083f,-218.75f, +136.719f,12.3184f,-218.75f, +140.625f,10.8438f,-218.75f, +144.531f,7.65837f,-218.75f, +148.438f,6.07316f,-218.75f, +152.344f,6.4613f,-218.75f, +156.25f,7.01972f,-218.75f, +160.156f,7.25454f,-218.75f, +164.063f,6.31416f,-218.75f, +167.969f,6.48096f,-218.75f, +171.875f,5.89274f,-218.75f, +175.781f,5.71289f,-218.75f, +179.688f,4.3046f,-218.75f, +183.594f,2.49719f,-218.75f, +187.5f,1.16956f,-218.75f, +191.406f,1.21673f,-218.75f, +195.313f,1.19652f,-218.75f, +199.219f,1.27819f,-218.75f, +203.125f,1.06325f,-218.75f, +207.031f,0.133118f,-218.75f, +210.938f,-0.283675f,-218.75f, +214.844f,-0.471323f,-218.75f, +218.75f,-0.941533f,-218.75f, +222.656f,-0.953851f,-218.75f, +226.563f,0.751216f,-218.75f, +230.469f,2.54245f,-218.75f, +234.375f,5.17863f,-218.75f, +238.281f,7.22669f,-218.75f, +242.188f,8.44723f,-218.75f, +246.094f,8.59229f,-218.75f, +250.0f,10.4333f,-218.75f, +3.90625f,13.0199f,-222.656f, +7.8125f,13.1789f,-222.656f, +11.7188f,12.4614f,-222.656f, +15.625f,10.8521f,-222.656f, +19.5313f,11.2552f,-222.656f, +23.4375f,12.1618f,-222.656f, +27.3438f,12.6207f,-222.656f, +31.25f,12.7195f,-222.656f, +35.1563f,12.6379f,-222.656f, +39.0625f,12.5247f,-222.656f, +42.9688f,11.5493f,-222.656f, +46.875f,11.1218f,-222.656f, +50.7813f,11.1036f,-222.656f, +54.6875f,11.2909f,-222.656f, +58.5938f,9.99718f,-222.656f, +62.5f,9.07075f,-222.656f, +66.4063f,7.85904f,-222.656f, +70.3125f,6.00034f,-222.656f, +74.2188f,6.20222f,-222.656f, +78.125f,6.90091f,-222.656f, +82.0313f,8.15724f,-222.656f, +85.9375f,8.92624f,-222.656f, +89.8438f,9.54135f,-222.656f, +93.75f,8.05473f,-222.656f, +97.6563f,5.80654f,-222.656f, +101.563f,5.02178f,-222.656f, +105.469f,7.15584f,-222.656f, +109.375f,8.94755f,-222.656f, +113.281f,9.86631f,-222.656f, +117.188f,10.6421f,-222.656f, +121.094f,10.7891f,-222.656f, +125.0f,11.0716f,-222.656f, +128.906f,12.6376f,-222.656f, +132.813f,12.4373f,-222.656f, +136.719f,12.1143f,-222.656f, +140.625f,11.4028f,-222.656f, +144.531f,8.95242f,-222.656f, +148.438f,6.83012f,-222.656f, +152.344f,7.65217f,-222.656f, +156.25f,8.26579f,-222.656f, +160.156f,7.9665f,-222.656f, +164.063f,7.5217f,-222.656f, +167.969f,7.17758f,-222.656f, +171.875f,5.9966f,-222.656f, +175.781f,5.77514f,-222.656f, +179.688f,4.77675f,-222.656f, +183.594f,3.39545f,-222.656f, +187.5f,2.95911f,-222.656f, +191.406f,1.85368f,-222.656f, +195.313f,1.31365f,-222.656f, +199.219f,1.12622f,-222.656f, +203.125f,1.47676f,-222.656f, +207.031f,1.89446f,-222.656f, +210.938f,0.63056f,-222.656f, +214.844f,0.297565f,-222.656f, +218.75f,-0.0109998f,-222.656f, +222.656f,-0.225082f,-222.656f, +226.563f,0.63258f,-222.656f, +230.469f,2.89831f,-222.656f, +234.375f,5.64839f,-222.656f, +238.281f,7.22414f,-222.656f, +242.188f,7.89951f,-222.656f, +246.094f,8.80151f,-222.656f, +250.0f,10.9602f,-222.656f, +3.90625f,11.9733f,-226.563f, +7.8125f,12.8862f,-226.563f, +11.7188f,12.1283f,-226.563f, +15.625f,10.7234f,-226.563f, +19.5313f,11.6866f,-226.563f, +23.4375f,12.6552f,-226.563f, +27.3438f,12.7353f,-226.563f, +31.25f,11.7992f,-226.563f, +35.1563f,11.2006f,-226.563f, +39.0625f,10.9699f,-226.563f, +42.9688f,10.7653f,-226.563f, +46.875f,10.9947f,-226.563f, +50.7813f,11.2791f,-226.563f, +54.6875f,11.0716f,-226.563f, +58.5938f,10.7092f,-226.563f, +62.5f,9.16355f,-226.563f, +66.4063f,7.59431f,-226.563f, +70.3125f,6.68502f,-226.563f, +74.2188f,6.98133f,-226.563f, +78.125f,7.72239f,-226.563f, +82.0313f,9.00293f,-226.563f, +85.9375f,9.47866f,-226.563f, +89.8438f,8.94458f,-226.563f, +93.75f,7.79648f,-226.563f, +97.6563f,6.07787f,-226.563f, +101.563f,6.60546f,-226.563f, +105.469f,8.5652f,-226.563f, +109.375f,10.2869f,-226.563f, +113.281f,11.4751f,-226.563f, +117.188f,11.6224f,-226.563f, +121.094f,12.0803f,-226.563f, +125.0f,12.5335f,-226.563f, +128.906f,13.5918f,-226.563f, +132.813f,12.9198f,-226.563f, +136.719f,11.521f,-226.563f, +140.625f,10.6418f,-226.563f, +144.531f,8.8393f,-226.563f, +148.438f,8.79941f,-226.563f, +152.344f,9.4929f,-226.563f, +156.25f,9.96206f,-226.563f, +160.156f,8.75524f,-226.563f, +164.063f,7.64157f,-226.563f, +167.969f,7.1963f,-226.563f, +171.875f,6.83929f,-226.563f, +175.781f,6.10665f,-226.563f, +179.688f,4.70473f,-226.563f, +183.594f,4.54758f,-226.563f, +187.5f,3.58616f,-226.563f, +191.406f,2.97998f,-226.563f, +195.313f,1.49179f,-226.563f, +199.219f,1.85834f,-226.563f, +203.125f,1.49089f,-226.563f, +207.031f,1.39949f,-226.563f, +210.938f,0.863002f,-226.563f, +214.844f,1.15546f,-226.563f, +218.75f,0.609373f,-226.563f, +222.656f,1.04332f,-226.563f, +226.563f,1.58038f,-226.563f, +230.469f,4.11549f,-226.563f, +234.375f,5.64696f,-226.563f, +238.281f,6.61687f,-226.563f, +242.188f,7.3113f,-226.563f, +246.094f,8.56955f,-226.563f, +250.0f,10.7891f,-226.563f, +3.90625f,10.4619f,-230.469f, +7.8125f,11.4179f,-230.469f, +11.7188f,10.7841f,-230.469f, +15.625f,10.597f,-230.469f, +19.5313f,10.9999f,-230.469f, +23.4375f,11.5972f,-230.469f, +27.3438f,11.4553f,-230.469f, +31.25f,10.1015f,-230.469f, +35.1563f,10.412f,-230.469f, +39.0625f,9.72694f,-230.469f, +42.9688f,9.71973f,-230.469f, +46.875f,10.7767f,-230.469f, +50.7813f,10.8775f,-230.469f, +54.6875f,10.3186f,-230.469f, +58.5938f,10.4188f,-230.469f, +62.5f,8.94879f,-230.469f, +66.4063f,7.92103f,-230.469f, +70.3125f,8.48295f,-230.469f, +74.2188f,8.74782f,-230.469f, +78.125f,8.87976f,-230.469f, +82.0313f,9.68632f,-230.469f, +85.9375f,9.54993f,-230.469f, +89.8438f,9.04624f,-230.469f, +93.75f,8.49407f,-230.469f, +97.6563f,7.90008f,-230.469f, +101.563f,9.20657f,-230.469f, +105.469f,10.5114f,-230.469f, +109.375f,11.5284f,-230.469f, +113.281f,12.0378f,-230.469f, +117.188f,12.9398f,-230.469f, +121.094f,13.1489f,-230.469f, +125.0f,13.8974f,-230.469f, +128.906f,14.5048f,-230.469f, +132.813f,13.1823f,-230.469f, +136.719f,11.6226f,-230.469f, +140.625f,11.1108f,-230.469f, +144.531f,10.0418f,-230.469f, +148.438f,10.2026f,-230.469f, +152.344f,10.9585f,-230.469f, +156.25f,11.0258f,-230.469f, +160.156f,9.88552f,-230.469f, +164.063f,8.92538f,-230.469f, +167.969f,7.90306f,-230.469f, +171.875f,7.23733f,-230.469f, +175.781f,6.09503f,-230.469f, +179.688f,5.15065f,-230.469f, +183.594f,4.73006f,-230.469f, +187.5f,4.05091f,-230.469f, +191.406f,3.01834f,-230.469f, +195.313f,1.83317f,-230.469f, +199.219f,2.77945f,-230.469f, +203.125f,3.05633f,-230.469f, +207.031f,2.07007f,-230.469f, +210.938f,2.01993f,-230.469f, +214.844f,2.13491f,-230.469f, +218.75f,1.65812f,-230.469f, +222.656f,1.8404f,-230.469f, +226.563f,2.78297f,-230.469f, +230.469f,3.94561f,-230.469f, +234.375f,5.83019f,-230.469f, +238.281f,6.9093f,-230.469f, +242.188f,7.96229f,-230.469f, +246.094f,7.63052f,-230.469f, +250.0f,10.2449f,-230.469f, +3.90625f,8.85224f,-234.375f, +7.8125f,9.40139f,-234.375f, +11.7188f,9.62814f,-234.375f, +15.625f,9.97075f,-234.375f, +19.5313f,9.96073f,-234.375f, +23.4375f,9.70541f,-234.375f, +27.3438f,10.0435f,-234.375f, +31.25f,9.85879f,-234.375f, +35.1563f,9.52681f,-234.375f, +39.0625f,8.75341f,-234.375f, +42.9688f,8.99686f,-234.375f, +46.875f,9.56309f,-234.375f, +50.7813f,9.54486f,-234.375f, +54.6875f,10.0225f,-234.375f, +58.5938f,9.56394f,-234.375f, +62.5f,9.18474f,-234.375f, +66.4063f,9.29208f,-234.375f, +70.3125f,10.4881f,-234.375f, +74.2188f,10.8865f,-234.375f, +78.125f,11.0201f,-234.375f, +82.0313f,11.7722f,-234.375f, +85.9375f,11.1624f,-234.375f, +89.8438f,10.602f,-234.375f, +93.75f,9.93284f,-234.375f, +97.6563f,10.2532f,-234.375f, +101.563f,11.0848f,-234.375f, +105.469f,12.6576f,-234.375f, +109.375f,13.4783f,-234.375f, +113.281f,14.7992f,-234.375f, +117.188f,15.3803f,-234.375f, +121.094f,15.9985f,-234.375f, +125.0f,14.9035f,-234.375f, +128.906f,14.2715f,-234.375f, +132.813f,14.0098f,-234.375f, +136.719f,13.1141f,-234.375f, +140.625f,12.5809f,-234.375f, +144.531f,11.8546f,-234.375f, +148.438f,11.5219f,-234.375f, +152.344f,11.8842f,-234.375f, +156.25f,11.6581f,-234.375f, +160.156f,10.8307f,-234.375f, +164.063f,10.2712f,-234.375f, +167.969f,8.58443f,-234.375f, +171.875f,7.00592f,-234.375f, +175.781f,5.65553f,-234.375f, +179.688f,5.07429f,-234.375f, +183.594f,4.41004f,-234.375f, +187.5f,3.95516f,-234.375f, +191.406f,3.42243f,-234.375f, +195.313f,2.54334f,-234.375f, +199.219f,3.95931f,-234.375f, +203.125f,3.9139f,-234.375f, +207.031f,2.90644f,-234.375f, +210.938f,3.11525f,-234.375f, +214.844f,3.33135f,-234.375f, +218.75f,2.64229f,-234.375f, +222.656f,2.64397f,-234.375f, +226.563f,3.186f,-234.375f, +230.469f,4.46201f,-234.375f, +234.375f,5.92783f,-234.375f, +238.281f,6.79968f,-234.375f, +242.188f,8.7067f,-234.375f, +246.094f,8.47322f,-234.375f, +250.0f,10.3839f,-234.375f, +3.90625f,7.99527f,-238.281f, +7.8125f,8.62199f,-238.281f, +11.7188f,9.06695f,-238.281f, +15.625f,9.12589f,-238.281f, +19.5313f,8.97926f,-238.281f, +23.4375f,9.75152f,-238.281f, +27.3438f,9.58038f,-238.281f, +31.25f,9.30169f,-238.281f, +35.1563f,8.63599f,-238.281f, +39.0625f,8.72973f,-238.281f, +42.9688f,8.49513f,-238.281f, +46.875f,8.78362f,-238.281f, +50.7813f,8.75045f,-238.281f, +54.6875f,8.96186f,-238.281f, +58.5938f,10.0611f,-238.281f, +62.5f,11.1275f,-238.281f, +66.4063f,10.8209f,-238.281f, +70.3125f,12.0108f,-238.281f, +74.2188f,13.2126f,-238.281f, +78.125f,14.1323f,-238.281f, +82.0313f,14.3575f,-238.281f, +85.9375f,13.2781f,-238.281f, +89.8438f,12.8024f,-238.281f, +93.75f,12.0484f,-238.281f, +97.6563f,12.7657f,-238.281f, +101.563f,14.0307f,-238.281f, +105.469f,15.9567f,-238.281f, +109.375f,17.7803f,-238.281f, +113.281f,19.0777f,-238.281f, +117.188f,18.7555f,-238.281f, +121.094f,18.8129f,-238.281f, +125.0f,17.4807f,-238.281f, +128.906f,16.4022f,-238.281f, +132.813f,16.01f,-238.281f, +136.719f,15.1852f,-238.281f, +140.625f,13.9301f,-238.281f, +144.531f,12.8841f,-238.281f, +148.438f,11.7108f,-238.281f, +152.344f,11.414f,-238.281f, +156.25f,11.056f,-238.281f, +160.156f,10.8688f,-238.281f, +164.063f,10.5672f,-238.281f, +167.969f,10.0938f,-238.281f, +171.875f,7.73603f,-238.281f, +175.781f,5.94931f,-238.281f, +179.688f,5.51512f,-238.281f, +183.594f,5.27449f,-238.281f, +187.5f,4.94763f,-238.281f, +191.406f,4.13161f,-238.281f, +195.313f,3.59426f,-238.281f, +199.219f,4.03163f,-238.281f, +203.125f,4.38188f,-238.281f, +207.031f,3.09959f,-238.281f, +210.938f,3.1766f,-238.281f, +214.844f,3.05715f,-238.281f, +218.75f,3.20329f,-238.281f, +222.656f,2.53565f,-238.281f, +226.563f,3.1275f,-238.281f, +230.469f,4.54736f,-238.281f, +234.375f,5.9361f,-238.281f, +238.281f,6.99977f,-238.281f, +242.188f,8.20813f,-238.281f, +246.094f,9.56614f,-238.281f, +250.0f,11.4751f,-238.281f, +3.90625f,6.40337f,-242.188f, +7.8125f,7.88741f,-242.188f, +11.7188f,8.60661f,-242.188f, +15.625f,8.56923f,-242.188f, +19.5313f,8.60588f,-242.188f, +23.4375f,8.63232f,-242.188f, +27.3438f,8.3446f,-242.188f, +31.25f,7.50857f,-242.188f, +35.1563f,7.64026f,-242.188f, +39.0625f,7.75851f,-242.188f, +42.9688f,7.56672f,-242.188f, +46.875f,7.98994f,-242.188f, +50.7813f,9.62391f,-242.188f, +54.6875f,9.28711f,-242.188f, +58.5938f,10.3792f,-242.188f, +62.5f,11.2793f,-242.188f, +66.4063f,12.3048f,-242.188f, +70.3125f,13.5272f,-242.188f, +74.2188f,14.5101f,-242.188f, +78.125f,15.2091f,-242.188f, +82.0313f,15.9007f,-242.188f, +85.9375f,15.4601f,-242.188f, +89.8438f,14.5171f,-242.188f, +93.75f,14.2266f,-242.188f, +97.6563f,13.9558f,-242.188f, +101.563f,15.8234f,-242.188f, +105.469f,18.6741f,-242.188f, +109.375f,20.7296f,-242.188f, +113.281f,21.5353f,-242.188f, +117.188f,20.9821f,-242.188f, +121.094f,20.2232f,-242.188f, +125.0f,18.5423f,-242.188f, +128.906f,17.8591f,-242.188f, +132.813f,17.6716f,-242.188f, +136.719f,16.8982f,-242.188f, +140.625f,14.8574f,-242.188f, +144.531f,13.0736f,-242.188f, +148.438f,12.4847f,-242.188f, +152.344f,11.8101f,-242.188f, +156.25f,11.7863f,-242.188f, +160.156f,11.4288f,-242.188f, +164.063f,10.8653f,-242.188f, +167.969f,9.75951f,-242.188f, +171.875f,8.13212f,-242.188f, +175.781f,6.91851f,-242.188f, +179.688f,5.93418f,-242.188f, +183.594f,5.79732f,-242.188f, +187.5f,5.8082f,-242.188f, +191.406f,4.85116f,-242.188f, +195.313f,4.2744f,-242.188f, +199.219f,4.23009f,-242.188f, +203.125f,3.99841f,-242.188f, +207.031f,3.48205f,-242.188f, +210.938f,3.71102f,-242.188f, +214.844f,3.52803f,-242.188f, +218.75f,3.41263f,-242.188f, +222.656f,2.40768f,-242.188f, +226.563f,3.40111f,-242.188f, +230.469f,4.51594f,-242.188f, +234.375f,5.96131f,-242.188f, +238.281f,7.68646f,-242.188f, +242.188f,8.54536f,-242.188f, +246.094f,9.49379f,-242.188f, +250.0f,12.0532f,-242.188f, +3.90625f,6.09425f,-246.094f, +7.8125f,7.62532f,-246.094f, +11.7188f,8.33141f,-246.094f, +15.625f,8.6172f,-246.094f, +19.5313f,8.7607f,-246.094f, +23.4375f,7.89699f,-246.094f, +27.3438f,7.77868f,-246.094f, +31.25f,7.41037f,-246.094f, +35.1563f,6.57203f,-246.094f, +39.0625f,6.31554f,-246.094f, +42.9688f,7.72481f,-246.094f, +46.875f,8.88325f,-246.094f, +50.7813f,10.0433f,-246.094f, +54.6875f,10.7945f,-246.094f, +58.5938f,11.7506f,-246.094f, +62.5f,13.1397f,-246.094f, +66.4063f,13.1294f,-246.094f, +70.3125f,14.8885f,-246.094f, +74.2188f,15.5444f,-246.094f, +78.125f,16.4867f,-246.094f, +82.0313f,17.0601f,-246.094f, +85.9375f,17.2351f,-246.094f, +89.8438f,16.4292f,-246.094f, +93.75f,16.32f,-246.094f, +97.6563f,17.0323f,-246.094f, +101.563f,17.5524f,-246.094f, +105.469f,20.0544f,-246.094f, +109.375f,21.7596f,-246.094f, +113.281f,22.3401f,-246.094f, +117.188f,22.7891f,-246.094f, +121.094f,21.705f,-246.094f, +125.0f,20.4875f,-246.094f, +128.906f,19.3013f,-246.094f, +132.813f,18.5254f,-246.094f, +136.719f,17.4179f,-246.094f, +140.625f,14.7663f,-246.094f, +144.531f,13.8915f,-246.094f, +148.438f,12.0594f,-246.094f, +152.344f,11.8343f,-246.094f, +156.25f,12.3176f,-246.094f, +160.156f,12.7287f,-246.094f, +164.063f,10.9779f,-246.094f, +167.969f,10.1928f,-246.094f, +171.875f,8.20833f,-246.094f, +175.781f,7.71383f,-246.094f, +179.688f,7.59678f,-246.094f, +183.594f,6.98083f,-246.094f, +187.5f,6.81055f,-246.094f, +191.406f,6.13881f,-246.094f, +195.313f,4.42472f,-246.094f, +199.219f,3.97044f,-246.094f, +203.125f,4.06157f,-246.094f, +207.031f,3.73524f,-246.094f, +210.938f,4.45121f,-246.094f, +214.844f,3.42347f,-246.094f, +218.75f,2.70444f,-246.094f, +222.656f,3.88027f,-246.094f, +226.563f,4.53456f,-246.094f, +230.469f,5.69259f,-246.094f, +234.375f,6.23366f,-246.094f, +238.281f,7.38965f,-246.094f, +242.188f,8.96481f,-246.094f, +246.094f,10.9805f,-246.094f, +250.0f,13.0168f,-246.094f, +3.90625f,6.31953f,-250.0f, +7.8125f,6.89279f,-250.0f, +11.7188f,8.63362f,-250.0f, +15.625f,9.28278f,-250.0f, +19.5313f,9.05374f,-250.0f, +23.4375f,8.51295f,-250.0f, +27.3438f,8.2676f,-250.0f, +31.25f,7.86717f,-250.0f, +35.1563f,6.56073f,-250.0f, +39.0625f,6.77605f,-250.0f, +42.9688f,8.67577f,-250.0f, +46.875f,10.2384f,-250.0f, +50.7813f,11.5086f,-250.0f, +54.6875f,12.7259f,-250.0f, +58.5938f,14.4625f,-250.0f, +62.5f,15.7352f,-250.0f, +66.4063f,15.1953f,-250.0f, +70.3125f,16.1585f,-250.0f, +74.2188f,17.1058f,-250.0f, +78.125f,17.3014f,-250.0f, +82.0313f,18.6932f,-250.0f, +85.9375f,18.6138f,-250.0f, +89.8438f,18.0431f,-250.0f, +93.75f,18.293f,-250.0f, +97.6563f,18.5338f,-250.0f, +101.563f,18.8033f,-250.0f, +105.469f,22.2037f,-250.0f, +109.375f,24.04f,-250.0f, +113.281f,24.711f,-250.0f, +117.188f,24.2801f,-250.0f, +121.094f,23.1052f,-250.0f, +125.0f,21.9886f,-250.0f, +128.906f,21.2657f,-250.0f, +132.813f,19.5364f,-250.0f, +136.719f,18.5278f,-250.0f, +140.625f,15.9806f,-250.0f, +144.531f,14.8577f,-250.0f, +148.438f,13.3645f,-250.0f, +152.344f,12.8082f,-250.0f, +156.25f,13.3689f,-250.0f, +160.156f,12.7449f,-250.0f, +164.063f,11.1108f,-250.0f, +167.969f,9.59991f,-250.0f, +171.875f,8.88472f,-250.0f, +175.781f,8.39035f,-250.0f, +179.688f,7.9163f,-250.0f, +183.594f,7.4118f,-250.0f, +187.5f,6.98082f,-250.0f, +191.406f,7.20793f,-250.0f, +195.313f,6.19875f,-250.0f, +199.219f,4.05745f,-250.0f, +203.125f,4.65884f,-250.0f, +207.031f,3.75824f,-250.0f, +210.938f,4.17504f,-250.0f, +214.844f,4.37516f,-250.0f, +218.75f,4.69345f,-250.0f, +222.656f,5.87678f,-250.0f, +226.563f,6.28295f,-250.0f, +230.469f,7.2125f,-250.0f, +234.375f,7.55925f,-250.0f, +238.281f,7.93922f,-250.0f, +242.188f,9.87332f,-250.0f, +246.094f,11.5957f,-250.0f, +250.0f,13.3418f,-250.0f, +}; + +btScalar Landscape07Nml[] = { +0.163295f,0.951018f,0.262487f, +0.144468f,0.954269f,0.261724f, +0.284339f,0.929979f,0.233003f, +0.211332f,0.959058f,0.188537f, +0.433374f,0.893306f,0.11913f, +0.363648f,0.930033f,0.052906f, +0.467682f,0.883824f,-0.0113249f, +0.383618f,0.915858f,-0.118494f, +0.389479f,0.919494f,-0.0532637f, +0.409514f,0.907723f,-0.0913076f, +0.332107f,0.943241f,-0.00112667f, +0.268223f,0.935541f,-0.229827f, +0.254548f,0.967046f,-0.0051751f, +0.306606f,0.933957f,-0.183623f, +0.282468f,0.956486f,0.073117f, +0.352033f,0.935268f,0.0366899f, +0.28404f,0.958651f,0.0175868f, +0.303901f,0.947745f,0.0970751f, +0.36555f,0.930735f,0.0102418f, +0.393208f,0.907605f,0.147107f, +0.468517f,0.882377f,0.0436299f, +0.45621f,0.884295f,0.0994741f, +0.387946f,0.921329f,0.0254982f, +0.35572f,0.93034f,0.0890492f, +-0.0727074f,0.997226f,-0.0159048f, +0.0416391f,0.981376f,0.187527f, +-0.216733f,0.958137f,0.187084f, +-0.0894435f,0.917028f,0.388664f, +-0.0768893f,0.966885f,0.243356f, +-0.0850782f,0.918088f,0.387139f, +-0.0500426f,0.973558f,0.222893f, +-0.133165f,0.955198f,0.264319f, +-0.123001f,0.980349f,0.154228f, +-0.136539f,0.958129f,0.251685f, +-0.132627f,0.981796f,0.135965f, +-0.174651f,0.968606f,0.176918f, +-0.259357f,0.958248f,0.120395f, +-0.298496f,0.949786f,0.0938444f, +-0.287382f,0.955091f,0.0721996f, +-0.350088f,0.936687f,-0.00747904f, +-0.148232f,0.988935f,-0.00587251f, +-0.126386f,0.991686f,0.0242043f, +-0.0549856f,0.99804f,0.0298927f, +-0.061356f,0.998107f,0.00430538f, +-0.205447f,0.97828f,0.0275574f, +-0.222811f,0.974816f,-0.00939735f, +-0.192208f,0.981343f,0.00477232f, +-0.179009f,0.983825f,-0.00666687f, +-0.0670729f,0.997581f,0.0182672f, +-0.127994f,0.990724f,-0.0456448f, +-0.132352f,0.983294f,-0.124961f, +-0.16906f,0.976471f,-0.133875f, +0.0163433f,0.992538f,-0.120836f, +0.061026f,0.995929f,-0.0663405f, +0.133906f,0.98909f,-0.0613958f, +0.0943148f,0.983776f,-0.152607f, +0.150352f,0.985874f,-0.0738065f, +0.100217f,0.972528f,-0.210109f, +0.174622f,0.974275f,-0.142462f, +0.154561f,0.962801f,-0.221644f, +0.214773f,0.96191f,-0.169122f, +0.258606f,0.948184f,-0.184582f, +0.352689f,0.932616f,-0.0764078f, +0.422646f,0.906225f,0.0112396f, +0.443105f,0.890896f,-0.0998108f, +0.401063f,0.915401f,-0.0344995f, +0.415945f,0.889086f,-0.19109f, +0.396075f,0.910803f,-0.116459f, +0.504361f,0.849207f,-0.15642f, +0.465554f,0.866637f,-0.179442f, +0.527872f,0.824305f,-0.204628f, +0.465951f,0.840148f,-0.277561f, +0.474007f,0.822715f,-0.31378f, +0.361245f,0.837173f,-0.410663f, +0.405138f,0.793126f,-0.454769f, +0.304965f,0.772294f,-0.557277f, +0.421648f,0.811214f,-0.405148f, +0.482203f,0.762506f,-0.431353f, +0.478963f,0.817038f,-0.321005f, +0.485062f,0.781955f,-0.391486f, +0.478205f,0.82345f,-0.305368f, +0.426707f,0.781297f,-0.455518f, +0.428677f,0.841565f,-0.32864f, +0.430024f,0.798188f,-0.421871f, +0.423016f,0.835924f,-0.349699f, +0.437416f,0.818455f,-0.372557f, +0.461522f,0.813116f,-0.354739f, +0.446182f,0.808887f,-0.382915f, +0.507869f,0.791896f,-0.339072f, +0.474665f,0.780232f,-0.407346f, +0.494125f,0.792543f,-0.357373f, +0.430265f,0.769469f,-0.472006f, +0.389469f,0.809375f,-0.439574f, +0.38782f,0.781711f,-0.488389f, +0.349938f,0.837293f,-0.4201f, +0.417236f,0.816738f,-0.398564f, +0.440298f,0.822173f,-0.360789f, +0.490994f,0.819158f,-0.296487f, +0.379279f,0.852728f,-0.359169f, +0.3675f,0.860963f,-0.351692f, +0.122152f,0.892865f,-0.433442f, +0.135293f,0.922235f,-0.362185f, +0.188083f,0.883941f,-0.428104f, +0.194653f,0.9204f,-0.339078f, +0.200053f,0.870677f,-0.449332f, +0.149584f,0.899445f,-0.410639f, +0.170948f,0.845446f,-0.505962f, +0.0834541f,0.848059f,-0.523289f, +0.233208f,0.811352f,-0.536024f, +0.246347f,0.822898f,-0.512008f, +0.0429626f,0.875995f,-0.480403f, +0.171623f,0.870482f,-0.461311f, +-0.202408f,0.938053f,-0.281226f, +-0.0831604f,0.960463f,-0.265698f, +-0.312635f,0.912112f,-0.265162f, +-0.344362f,0.89728f,-0.276231f, +-0.0852182f,0.932714f,-0.350403f, +-0.156991f,0.922287f,-0.353185f, +0.0213728f,0.893503f,-0.448548f, +-0.0577934f,0.860578f,-0.506029f, +-0.0250381f,0.886654f,-0.461755f, +-0.0319956f,0.87749f,-0.478526f, +-0.0302913f,0.865602f,-0.499816f, +-0.00892741f,0.865625f,-0.500613f, +0.0556557f,0.906734f,-0.418015f, +0.137632f,0.905698f,-0.400959f, +0.0276894f,0.926625f,-0.374965f, +0.074566f,0.927887f,-0.365329f, +0.0588963f,0.991806f,0.113367f, +0.300045f,0.940314f,0.160571f, +0.505162f,0.858812f,0.0851652f, +0.523651f,0.851407f,0.0299276f, +0.336751f,0.940492f,0.0455315f, +0.231254f,0.960478f,0.15493f, +0.265257f,0.945144f,0.190637f, +0.327138f,0.941822f,0.0771526f, +0.406507f,0.912216f,-0.0511354f, +0.398687f,0.900126f,-0.17556f, +0.399875f,0.884983f,-0.238547f, +0.421808f,0.899838f,-0.11122f, +-0.041369f,0.987502f,-0.152078f, +-0.327111f,0.932019f,-0.156008f, +-0.143307f,0.985559f,-0.0902006f, +-0.0270205f,0.999466f,0.0183744f, +-0.0836031f,0.996473f,-0.00727851f, +-0.153499f,0.988141f,-0.00380883f, +-0.269657f,0.962702f,0.0221269f, +-0.220011f,0.975241f,-0.0223422f, +-0.104184f,0.990611f,-0.0885198f, +-0.112376f,0.99176f,-0.0615135f, +-0.176142f,0.984186f,-0.0187604f, +-0.211815f,0.974306f,-0.076572f, +-0.0254097f,0.999559f,-0.0153608f, +-0.0364109f,0.99734f,-0.0631393f, +-0.0203648f,0.999538f,-0.0225481f, +0.0549873f,0.998448f,0.00884961f, +0.169599f,0.985346f,0.0181241f, +0.253148f,0.96653f,-0.0416731f, +0.241207f,0.963047f,-0.119834f, +0.334221f,0.932038f,-0.140004f, +0.510774f,0.849501f,-0.132124f, +0.446103f,0.866333f,-0.224633f, +0.443332f,0.853241f,-0.274658f, +0.556199f,0.799442f,-0.227011f, +0.56349f,0.790862f,-0.238781f, +0.469847f,0.819465f,-0.32821f, +0.384148f,0.843359f,-0.375735f, +0.405196f,0.828658f,-0.386189f, +0.451519f,0.832227f,-0.321758f, +0.460293f,0.845627f,-0.27027f, +0.479361f,0.841341f,-0.249716f, +0.486527f,0.832565f,-0.264815f, +0.505678f,0.817374f,-0.276024f, +0.532701f,0.792427f,-0.297134f, +0.419998f,0.832504f,-0.361301f, +0.381252f,0.872209f,-0.306428f, +0.441269f,0.820876f,-0.362552f, +0.40003f,0.811169f,-0.426593f, +0.192925f,0.829083f,-0.524786f, +0.183969f,0.805942f,-0.562684f, +0.196671f,0.822252f,-0.534063f, +0.210296f,0.820946f,-0.530871f, +0.203797f,0.82129f,-0.532869f, +-0.110131f,0.879911f,-0.462199f, +-0.313522f,0.874849f,-0.369247f, +-0.225349f,0.894153f,-0.386922f, +-0.0425073f,0.90311f,-0.4273f, +0.0811921f,0.929959f,-0.358587f, +-0.0097083f,0.913772f,-0.406111f, +-0.0203212f,0.916094f,-0.400448f, +-0.0594319f,0.92652f,-0.371521f, +-0.0269889f,0.956838f,-0.289365f, +0.0349749f,0.98646f,-0.160231f, +0.256968f,0.956769f,-0.13624f, +0.548943f,0.832681f,-0.0728256f, +0.489119f,0.868806f,-0.0770563f, +0.299363f,0.954014f,0.0154449f, +0.150669f,0.988307f,0.0233966f, +0.338483f,0.938561f,0.0673226f, +0.470525f,0.880363f,-0.0597344f, +0.482272f,0.850276f,-0.210818f, +0.467725f,0.834993f,-0.289861f, +0.394888f,0.866151f,-0.306343f, +0.253937f,0.935832f,-0.244407f, +-0.00400266f,0.994244f,-0.107062f, +-0.309146f,0.937501f,-0.15975f, +-0.226806f,0.957844f,-0.176334f, +-0.122632f,0.982531f,-0.139981f, +-0.0635605f,0.992861f,-0.10093f, +-0.151586f,0.973622f,-0.170534f, +-0.231525f,0.948656f,-0.215516f, +-0.166237f,0.951792f,-0.257795f, +-0.0869197f,0.960928f,-0.262798f, +-0.164573f,0.950876f,-0.262203f, +-0.167249f,0.963013f,-0.211268f, +-0.211402f,0.954271f,-0.211366f, +-0.0642089f,0.988782f,-0.134861f, +-0.0696806f,0.987799f,-0.139279f, +-0.124243f,0.98904f,-0.0797755f, +0.0962393f,0.995288f,-0.0118021f, +0.210783f,0.972894f,-0.0951158f, +0.297355f,0.950074f,-0.0945467f, +0.301001f,0.949737f,-0.0860135f, +0.352321f,0.929179f,-0.111785f, +0.488103f,0.867307f,-0.0976422f, +0.556803f,0.828121f,-0.0646904f, +0.522997f,0.817722f,-0.240427f, +0.526158f,0.791225f,-0.311642f, +0.539548f,0.783883f,-0.30727f, +0.519736f,0.798926f,-0.302643f, +0.456854f,0.816569f,-0.352845f, +0.429557f,0.807438f,-0.404381f, +0.403588f,0.823842f,-0.397997f, +0.363835f,0.833866f,-0.415079f, +0.411515f,0.83345f,-0.368804f, +0.472303f,0.812756f,-0.341113f, +0.520866f,0.78709f,-0.330436f, +0.571303f,0.758641f,-0.313172f, +0.364947f,0.85616f,-0.365791f, +0.334117f,0.892356f,-0.303424f, +0.531373f,0.790182f,-0.305376f, +0.490437f,0.768139f,-0.411624f, +0.28549f,0.798709f,-0.529679f, +0.166173f,0.802828f,-0.572585f, +0.142862f,0.826392f,-0.544671f, +0.199443f,0.816751f,-0.541424f, +0.128075f,0.851947f,-0.507724f, +-0.168704f,0.879688f,-0.444621f, +-0.244755f,0.842741f,-0.479461f, +-0.150804f,0.809643f,-0.567218f, +-0.142654f,0.804501f,-0.576565f, +-0.00468689f,0.885234f,-0.465123f, +-0.00403137f,0.903548f,-0.428468f, +-0.0506207f,0.931001f,-0.361489f, +-0.153442f,0.941817f,-0.299058f, +-0.162811f,0.972443f,-0.166875f, +0.109587f,0.934225f,-0.339431f, +0.212963f,0.908729f,-0.358967f, +0.490721f,0.837065f,-0.2419f, +0.423339f,0.87185f,-0.246298f, +0.265687f,0.948953f,-0.169996f, +0.19754f,0.959782f,-0.199488f, +0.295591f,0.918793f,-0.261622f, +0.531499f,0.826018f,-0.187622f, +0.59212f,0.773761f,-0.225139f, +0.430882f,0.823206f,-0.369692f, +0.346812f,0.896722f,-0.274977f, +0.157001f,0.944818f,-0.287523f, +-0.0770972f,0.974843f,-0.209133f, +-0.291803f,0.93708f,-0.191656f, +-0.196019f,0.961744f,-0.191378f, +-0.131765f,0.96396f,-0.231124f, +-0.0745388f,0.982069f,-0.173159f, +0.00914064f,0.98959f,-0.143621f, +-0.138284f,0.94748f,-0.288373f, +-0.221669f,0.91917f,-0.325561f, +-0.129149f,0.970549f,-0.203358f, +-0.130482f,0.980721f,-0.145466f, +-0.176902f,0.951987f,-0.249854f, +-0.247465f,0.916992f,-0.31287f, +-0.158128f,0.953184f,-0.25775f, +-0.0356987f,0.985511f,-0.165812f, +-0.125849f,0.96636f,-0.224301f, +0.0681695f,0.96619f,-0.248655f, +0.227225f,0.953018f,-0.200315f, +0.225952f,0.967572f,-0.112919f, +0.287704f,0.957355f,-0.0264129f, +0.36102f,0.928385f,-0.0881278f, +0.475672f,0.87145f,-0.119627f, +0.569214f,0.81507f,-0.107964f, +0.623663f,0.769908f,-0.13523f, +0.603105f,0.773542f,-0.19467f, +0.556766f,0.776509f,-0.295034f, +0.523993f,0.789717f,-0.319025f, +0.458736f,0.810878f,-0.36337f, +0.42608f,0.838013f,-0.340867f, +0.413816f,0.852215f,-0.320134f, +0.428047f,0.839676f,-0.334247f, +0.440545f,0.806668f,-0.393963f, +0.471664f,0.754066f,-0.457075f, +0.438131f,0.75533f,-0.487358f, +0.513035f,0.778713f,-0.361111f, +0.362236f,0.865985f,-0.344753f, +0.319311f,0.872794f,-0.36915f, +0.546544f,0.761872f,-0.347621f, +0.587841f,0.74763f,-0.309017f, +0.346001f,0.792234f,-0.502642f, +0.160837f,0.807416f,-0.567637f, +0.137348f,0.82025f,-0.555271f, +0.177955f,0.827144f,-0.533071f, +0.0951091f,0.870125f,-0.483567f, +-0.154432f,0.835911f,-0.526691f, +-0.124368f,0.808763f,-0.574834f, +-0.126819f,0.782715f,-0.609323f, +-0.137751f,0.811099f,-0.568456f, +-0.111652f,0.799108f,-0.590729f, +-0.083265f,0.829705f,-0.551957f, +-0.187386f,0.858237f,-0.477825f, +-0.293723f,0.918982f,-0.263055f, +-0.393626f,0.913021f,-0.107009f, +0.212209f,0.950224f,-0.228125f, +0.209499f,0.936607f,-0.280851f, +0.442676f,0.872148f,-0.208317f, +0.471617f,0.857429f,-0.205893f, +0.203873f,0.890799f,-0.406094f, +0.238352f,0.874506f,-0.422408f, +0.316589f,0.834877f,-0.45028f, +0.439788f,0.802413f,-0.403384f, +0.591147f,0.75018f,-0.29627f, +0.446858f,0.837414f,-0.314732f, +0.297014f,0.892204f,-0.340228f, +0.174626f,0.914769f,-0.364286f, +-0.105816f,0.915255f,-0.388731f, +-0.264967f,0.884964f,-0.382925f, +-0.17731f,0.909999f,-0.374785f, +-0.129483f,0.910653f,-0.39236f, +-0.183919f,0.912509f,-0.365379f, +-0.0547605f,0.971103f,-0.232295f, +-0.0329197f,0.988161f,-0.149845f, +-0.283679f,0.94023f,-0.188398f, +-0.271484f,0.961222f,-0.0484715f, +-0.126156f,0.992006f,-0.00297784f, +-0.0077445f,0.99412f,-0.10801f, +-0.122479f,0.952558f,-0.278626f, +-0.22816f,0.898995f,-0.373834f, +-0.116624f,0.94701f,-0.299285f, +-0.0338322f,0.962019f,-0.270876f, +0.0643125f,0.93366f,-0.352339f, +0.108033f,0.951056f,-0.28952f, +0.0914872f,0.981979f,-0.165373f, +0.260441f,0.963994f,-0.0537291f, +0.448443f,0.892711f,-0.0443492f, +0.523825f,0.846692f,-0.0933822f, +0.566469f,0.810587f,-0.148532f, +0.615421f,0.777098f,-0.131818f, +0.641634f,0.7586f,-0.11328f, +0.626845f,0.758026f,-0.180172f, +0.575952f,0.768546f,-0.278596f, +0.455289f,0.793648f,-0.403527f, +0.401888f,0.827012f,-0.393113f, +0.390072f,0.829628f,-0.399451f, +0.432707f,0.817098f,-0.380939f, +0.498394f,0.785084f,-0.367759f, +0.54453f,0.759415f,-0.356056f, +0.443321f,0.820621f,-0.360621f, +0.413861f,0.828476f,-0.377289f, +0.394054f,0.852433f,-0.343626f, +0.354186f,0.831754f,-0.427477f, +0.501406f,0.754246f,-0.423916f, +0.58911f,0.726277f,-0.354219f, +0.489087f,0.757568f,-0.432301f, +0.219144f,0.803913f,-0.552901f, +0.0950257f,0.808184f,-0.581213f, +0.0824554f,0.830823f,-0.550395f, +0.0933748f,0.860985f,-0.499987f, +-0.0248456f,0.850125f,-0.525994f, +-0.102917f,0.824622f,-0.556243f, +-0.137975f,0.843048f,-0.519839f, +-0.191841f,0.811585f,-0.551839f, +-0.0960986f,0.833755f,-0.543707f, +-0.122745f,0.850064f,-0.512177f, +-0.326981f,0.870361f,-0.368177f, +-0.538824f,0.830097f,-0.143558f, +-0.554748f,0.831168f,0.0375988f, +0.183636f,0.945911f,-0.267453f, +0.248003f,0.941284f,-0.229083f, +0.367193f,0.90606f,-0.210295f, +0.559963f,0.826078f,-0.0635307f, +0.486301f,0.848236f,-0.209779f, +0.313552f,0.830527f,-0.460336f, +0.26103f,0.794184f,-0.548758f, +0.384376f,0.78311f,-0.488869f, +0.479781f,0.77201f,-0.416905f, +0.481011f,0.825397f,-0.295547f, +0.281884f,0.886831f,-0.366158f, +0.202383f,0.940438f,-0.273162f, +-0.0238314f,0.938511f,-0.344426f, +-0.257973f,0.859678f,-0.440913f, +-0.194719f,0.873936f,-0.445332f, +-0.0838372f,0.877697f,-0.471825f, +-0.223876f,0.839024f,-0.495901f, +-0.216019f,0.888182f,-0.405548f, +-0.127765f,0.960438f,-0.247457f, +-0.306436f,0.940762f,-0.145138f, +-0.327317f,0.939981f,-0.096429f, +-0.0557083f,0.990847f,-0.122959f, +0.0995056f,0.975129f,-0.198043f, +0.0247654f,0.966343f,-0.256062f, +-0.1694f,0.916546f,-0.362281f, +-0.197841f,0.908709f,-0.367568f, +-0.0185126f,0.95561f,-0.294052f, +0.0824185f,0.951583f,-0.296138f, +0.0241627f,0.96387f,-0.265277f, +0.0355962f,0.964767f,-0.260688f, +0.155357f,0.948871f,-0.274788f, +0.403654f,0.905713f,-0.129414f, +0.540931f,0.838513f,-0.0654957f, +0.603296f,0.79305f,-0.0842943f, +0.615316f,0.778563f,-0.123395f, +0.650635f,0.750663f,-0.114799f, +0.681129f,0.712532f,-0.16841f, +0.640077f,0.706799f,-0.301225f, +0.501905f,0.776085f,-0.381816f, +0.395956f,0.833034f,-0.386359f, +0.40448f,0.824611f,-0.39549f, +0.410354f,0.816219f,-0.406689f, +0.470853f,0.807605f,-0.355065f, +0.489936f,0.812779f,-0.315203f, +0.459069f,0.843316f,-0.279417f, +0.469145f,0.829489f,-0.303069f, +0.440235f,0.819159f,-0.367657f, +0.420347f,0.792019f,-0.442734f, +0.528602f,0.735131f,-0.424456f, +0.540602f,0.708419f,-0.453752f, +0.493287f,0.777492f,-0.390095f, +0.304413f,0.86604f,-0.396619f, +0.0820709f,0.870144f,-0.485916f, +0.0884612f,0.883073f,-0.460823f, +0.0898563f,0.860973f,-0.500651f, +-0.0421635f,0.844727f,-0.533535f, +-0.161922f,0.847271f,-0.505878f, +-0.14449f,0.888235f,-0.436074f, +-0.171293f,0.877903f,-0.447153f, +-0.137238f,0.90321f,-0.406666f, +-0.254069f,0.918554f,-0.302831f, +-0.505168f,0.843216f,-0.183829f, +-0.675277f,0.734237f,-0.069976f, +-0.653992f,0.755215f,0.0440947f, +0.0555085f,0.890635f,-0.451319f, +0.137334f,0.909799f,-0.39167f, +0.308301f,0.903589f,-0.297451f, +0.471952f,0.852104f,-0.226231f, +0.566013f,0.811602f,-0.144679f, +0.544915f,0.811135f,-0.212433f, +0.36963f,0.829124f,-0.419437f, +0.344038f,0.821377f,-0.454948f, +0.421617f,0.811326f,-0.404955f, +0.42674f,0.823996f,-0.372724f, +0.214619f,0.881696f,-0.42018f, +0.0910032f,0.951585f,-0.293606f, +0.0846967f,0.975495f,-0.203065f, +-0.12731f,0.949549f,-0.286616f, +-0.203708f,0.900619f,-0.383912f, +-0.0136138f,0.94578f,-0.324521f, +-0.1774f,0.907831f,-0.379963f, +-0.319591f,0.828051f,-0.460644f, +-0.309551f,0.868477f,-0.387202f, +-0.350068f,0.908991f,-0.226245f, +-0.314996f,0.908797f,-0.273615f, +-0.0601423f,0.962735f,-0.263674f, +0.136393f,0.973573f,-0.183175f, +0.0532739f,0.976623f,-0.208255f, +-0.105007f,0.973025f,-0.205419f, +-0.20872f,0.948662f,-0.237649f, +-0.0905915f,0.950284f,-0.297915f, +0.0475864f,0.961005f,-0.272405f, +0.0362517f,0.97079f,-0.237174f, +0.105725f,0.948531f,-0.298516f, +0.162566f,0.915122f,-0.368949f, +0.273546f,0.895769f,-0.350385f, +0.484941f,0.844255f,-0.228179f, +0.616479f,0.776457f,-0.130645f, +0.628311f,0.758456f,-0.173119f, +0.646758f,0.730427f,-0.2195f, +0.713832f,0.657703f,-0.240564f, +0.670883f,0.685042f,-0.283959f, +0.484582f,0.813502f,-0.32155f, +0.374759f,0.869215f,-0.322522f, +0.442437f,0.844514f,-0.301738f, +0.417442f,0.841211f,-0.343666f, +0.423405f,0.844004f,-0.329219f, +0.51768f,0.821209f,-0.240049f, +0.452859f,0.851327f,-0.264878f, +0.509187f,0.825405f,-0.243796f, +0.514747f,0.798114f,-0.313129f, +0.470791f,0.788824f,-0.395111f, +0.531455f,0.747848f,-0.397843f, +0.533283f,0.783064f,-0.32003f, +0.426956f,0.884256f,-0.18921f, +0.350467f,0.920762f,-0.171379f, +0.166727f,0.944055f,-0.284537f, +0.0641204f,0.940994f,-0.332292f, +0.176576f,0.941646f,-0.286573f, +0.033479f,0.945913f,-0.322688f, +-0.166217f,0.885456f,-0.433982f, +-0.211415f,0.849321f,-0.483692f, +-0.245686f,0.873508f,-0.420264f, +-0.318583f,0.913339f,-0.253606f, +-0.37482f,0.927017f,-0.0122188f, +-0.519112f,0.853899f,0.0371293f, +-0.674751f,0.732141f,-0.0931649f, +-0.717847f,0.685588f,-0.121095f, +0.129526f,0.933398f,-0.33465f, +0.109756f,0.909727f,-0.400439f, +0.235187f,0.88528f,-0.401206f, +0.43527f,0.839228f,-0.32594f, +0.509145f,0.799028f,-0.319883f, +0.559944f,0.774395f,-0.294577f, +0.481154f,0.808934f,-0.337812f, +0.346903f,0.826321f,-0.443681f, +0.419785f,0.810323f,-0.408849f, +0.424579f,0.803602f,-0.417081f, +0.213763f,0.882039f,-0.419896f, +-0.065439f,0.903315f,-0.423958f, +-0.0365788f,0.953894f,-0.297908f, +-0.052968f,0.984136f,-0.169324f, +-0.178873f,0.950393f,-0.254476f, +-0.13588f,0.955299f,-0.262566f, +-0.0549577f,0.986053f,-0.157096f, +-0.250853f,0.921347f,-0.296972f, +-0.383387f,0.86801f,-0.31555f, +-0.39517f,0.874494f,-0.281248f, +-0.297344f,0.903399f,-0.308961f, +-0.146671f,0.942034f,-0.301762f, +0.0292749f,0.969498f,-0.243343f, +0.0315554f,0.994938f,-0.0954108f, +-0.135353f,0.99076f,0.00864549f, +-0.109362f,0.993969f,-0.00807889f, +0.00178341f,0.978683f,-0.205368f, +0.0583577f,0.951175f,-0.303086f, +0.0448944f,0.938747f,-0.341671f, +0.135893f,0.935013f,-0.327543f, +0.248098f,0.92828f,-0.277025f, +0.287291f,0.872499f,-0.395234f, +0.360517f,0.825037f,-0.435134f, +0.531263f,0.786524f,-0.314864f, +0.667801f,0.716872f,-0.200342f, +0.67932f,0.687853f,-0.2557f, +0.702261f,0.671608f,-0.236161f, +0.672702f,0.722764f,-0.15838f, +0.529805f,0.828764f,-0.180158f, +0.396956f,0.86756f,-0.29961f, +0.439447f,0.830334f,-0.342683f, +0.431898f,0.838796f,-0.33149f, +0.414335f,0.865026f,-0.282941f, +0.433505f,0.865399f,-0.251314f, +0.473777f,0.866492f,-0.157252f, +0.513796f,0.828002f,-0.224559f, +0.584841f,0.771201f,-0.251417f, +0.518412f,0.788719f,-0.330412f, +0.507007f,0.831445f,-0.227253f, +0.414775f,0.908203f,-0.0559478f, +0.370241f,0.92627f,0.07033f, +0.386742f,0.919823f,0.0659988f, +0.294152f,0.955333f,0.0285335f, +0.1108f,0.9849f,-0.133022f, +0.118551f,0.967697f,-0.222506f, +0.0772752f,0.978981f,-0.188747f, +-0.0200413f,0.97522f,-0.220327f, +-0.18076f,0.942791f,-0.280125f, +-0.356914f,0.914544f,-0.190318f, +-0.511643f,0.854464f,-0.0900754f, +-0.529301f,0.843485f,0.0915077f, +-0.481356f,0.855106f,0.192586f, +-0.566596f,0.818312f,0.0966086f, +-0.682392f,0.727753f,-0.0686784f, +0.232504f,0.952167f,-0.198291f, +0.256414f,0.932781f,-0.253323f, +0.252094f,0.888895f,-0.38251f, +0.391259f,0.847753f,-0.358095f, +0.537533f,0.80784f,-0.241771f, +0.561137f,0.803605f,-0.198354f, +0.542606f,0.822395f,-0.171013f, +0.447025f,0.853524f,-0.267703f, +0.421457f,0.829331f,-0.366857f, +0.381949f,0.841011f,-0.383165f, +0.196905f,0.918187f,-0.343745f, +-0.0750719f,0.92165f,-0.380691f, +-0.176435f,0.915143f,-0.362469f, +-0.162121f,0.952528f,-0.257698f, +-0.094717f,0.979068f,-0.180149f, +-0.167752f,0.965606f,-0.198655f, +-0.133367f,0.985758f,-0.102438f, +-0.176519f,0.982527f,-0.0590077f, +-0.382392f,0.914243f,-0.133925f, +-0.379354f,0.898635f,-0.220329f, +-0.2745f,0.907747f,-0.317246f, +-0.107475f,0.924008f,-0.366959f, +-0.0783766f,0.915897f,-0.393688f, +-0.161723f,0.964079f,-0.210708f, +-0.213776f,0.971922f,-0.0983248f, +0.0126393f,0.993361f,-0.114343f, +0.146279f,0.956353f,-0.252963f, +0.181548f,0.939791f,-0.289541f, +0.0719106f,0.91394f,-0.399427f, +0.0405362f,0.92481f,-0.378262f, +0.227996f,0.9289f,-0.291825f, +0.430007f,0.847434f,-0.311368f, +0.444003f,0.803436f,-0.396676f, +0.425815f,0.77314f,-0.470039f, +0.591393f,0.731624f,-0.339089f, +0.68448f,0.684033f,-0.252165f, +0.663878f,0.696032f,-0.273504f, +0.62681f,0.752096f,-0.203619f, +0.578478f,0.810023f,-0.0960529f, +0.535256f,0.829774f,-0.158038f, +0.488949f,0.817442f,-0.304496f, +0.370902f,0.857519f,-0.356501f, +0.349699f,0.870975f,-0.345126f, +0.374514f,0.863134f,-0.338731f, +0.45144f,0.856074f,-0.251673f, +0.565254f,0.789722f,-0.238384f, +0.610208f,0.775791f,-0.160605f, +0.460354f,0.88479f,-0.0722568f, +0.360414f,0.930663f,0.0629891f, +0.310809f,0.940565f,0.136874f, +0.344153f,0.923997f,0.166701f, +0.371378f,0.913473f,0.166271f, +0.349168f,0.916329f,0.196019f, +0.310264f,0.946182f,0.0920588f, +0.219218f,0.972739f,-0.075642f, +0.0579784f,0.994476f,-0.087501f, +-0.0556996f,0.997544f,-0.0424565f, +-0.239345f,0.970003f,0.0425244f, +-0.461388f,0.876311f,0.138566f, +-0.538726f,0.825514f,0.168229f, +-0.597717f,0.791468f,0.127721f, +-0.507215f,0.833365f,0.219627f, +-0.488959f,0.84151f,0.229738f, +-0.545304f,0.815937f,0.192066f, +0.227692f,0.931856f,-0.282489f, +0.297935f,0.90904f,-0.291343f, +0.353719f,0.876832f,-0.325652f, +0.346915f,0.865884f,-0.36041f, +0.409305f,0.867351f,-0.283145f, +0.519851f,0.844165f,-0.130922f, +0.531147f,0.844051f,-0.0738934f, +0.549452f,0.835136f,-0.0255055f, +0.519598f,0.847001f,-0.112281f, +0.416821f,0.899711f,-0.12954f, +0.213877f,0.961324f,-0.173531f, +-0.0327967f,0.969436f,-0.243141f, +-0.200151f,0.944585f,-0.26019f, +-0.261086f,0.940261f,-0.218503f, +-0.16617f,0.980036f,-0.109163f, +-0.211362f,0.973049f,-0.0922088f, +-0.262019f,0.96267f,-0.0679153f, +-0.172722f,0.984229f,0.0382049f, +-0.269464f,0.962867f,-0.0166155f, +-0.289017f,0.944015f,-0.159073f, +-0.146887f,0.958128f,-0.245795f, +-0.0700562f,0.951312f,-0.300164f, +-0.140619f,0.963564f,-0.227533f, +-0.278995f,0.930049f,-0.239105f, +-0.16269f,0.936868f,-0.309531f, +0.070144f,0.909561f,-0.409607f, +0.193776f,0.876857f,-0.43997f, +0.127038f,0.902686f,-0.411121f, +0.150617f,0.947884f,-0.280767f, +0.0386496f,0.919015f,-0.392324f, +0.208973f,0.868713f,-0.449075f, +0.403894f,0.796876f,-0.449287f, +0.495348f,0.781817f,-0.378673f, +0.489779f,0.764879f,-0.418421f, +0.499102f,0.742417f,-0.446893f, +0.648968f,0.690613f,-0.319208f, +0.677239f,0.687846f,-0.26118f, +0.512369f,0.799495f,-0.313506f, +0.465181f,0.863456f,-0.195064f, +0.589095f,0.803266f,-0.0879238f, +0.56026f,0.801619f,-0.208601f, +0.442292f,0.866151f,-0.232723f, +0.407485f,0.876049f,-0.257867f, +0.41887f,0.854839f,-0.306264f, +0.344336f,0.834896f,-0.429397f, +0.497957f,0.824163f,-0.269804f, +0.448098f,0.886678f,-0.114058f, +0.337837f,0.929162f,0.150081f, +0.341034f,0.908641f,0.240972f, +0.356163f,0.918925f,0.169481f, +0.332963f,0.932465f,0.140159f, +0.378366f,0.915215f,0.13864f, +0.366597f,0.926522f,0.0846395f, +0.364364f,0.925578f,0.102688f, +0.226565f,0.954799f,0.192424f, +0.0359845f,0.964557f,0.261408f, +-0.155471f,0.954274f,0.255321f, +-0.290268f,0.886689f,0.359898f, +-0.467017f,0.828082f,0.31012f, +-0.499403f,0.82291f,0.270953f, +-0.565258f,0.797609f,0.210482f, +-0.553063f,0.809532f,0.196925f, +-0.499446f,0.823964f,0.267652f, +-0.522286f,0.796771f,0.30393f, +0.282895f,0.896955f,-0.339766f, +0.328074f,0.870604f,-0.366628f, +0.343521f,0.854938f,-0.388683f, +0.333693f,0.867418f,-0.369101f, +0.350459f,0.883644f,-0.310405f, +0.440013f,0.868347f,-0.228826f, +0.488334f,0.85139f,-0.191483f, +0.49066f,0.852892f,-0.178404f, +0.509846f,0.855822f,-0.0873222f, +0.418823f,0.907869f,-0.0190138f, +0.288806f,0.957176f,-0.0201137f, +0.0497186f,0.992214f,-0.114191f, +-0.215841f,0.960205f,-0.177253f, +-0.338759f,0.933444f,-0.118004f, +-0.242696f,0.969321f,-0.0389388f, +-0.141909f,0.989578f,-0.0244358f, +-0.270493f,0.952883f,-0.137288f, +-0.235245f,0.967095f,-0.0968818f, +-0.186427f,0.979041f,-0.0819931f, +-0.181825f,0.962183f,-0.20284f, +-0.135402f,0.958028f,-0.252681f, +-0.153581f,0.96935f,-0.191767f, +-0.186528f,0.978878f,-0.0837011f, +-0.164286f,0.974581f,-0.152324f, +0.0119477f,0.951315f,-0.307988f, +0.181241f,0.876938f,-0.44512f, +0.193514f,0.837326f,-0.51131f, +-0.00806995f,0.853668f,-0.520756f, +0.0461085f,0.918292f,-0.393209f, +0.210027f,0.898011f,-0.386606f, +0.313179f,0.820953f,-0.477447f, +0.395672f,0.762863f,-0.511355f, +0.407119f,0.752829f,-0.517206f, +0.491283f,0.735772f,-0.466133f, +0.508563f,0.731088f,-0.454835f, +0.557969f,0.720001f,-0.412637f, +0.635268f,0.712821f,-0.297187f, +0.514275f,0.818992f,-0.254505f, +0.384017f,0.888427f,-0.251454f, +0.535431f,0.823023f,-0.189597f, +0.597396f,0.79853f,-0.0739445f, +0.435766f,0.897283f,-0.0706489f, +0.387025f,0.91478f,-0.115713f, +0.532369f,0.842082f,-0.0864959f, +0.42055f,0.882636f,-0.209979f, +0.370951f,0.912219f,-0.173928f, +0.309089f,0.948381f,-0.0709704f, +0.21321f,0.976943f,0.0111471f, +0.331446f,0.943237f,0.0211533f, +0.410945f,0.911483f,0.0179772f, +0.321726f,0.946051f,-0.0384626f, +0.397145f,0.917286f,0.0293659f, +0.411757f,0.908804f,0.0673213f, +0.22276f,0.971882f,0.0763077f, +0.069501f,0.964908f,0.253224f, +-0.028986f,0.93542f,0.352349f, +-0.1774f,0.888082f,0.424074f, +-0.313309f,0.830284f,0.460941f, +-0.375142f,0.83463f,0.403313f, +-0.455516f,0.824707f,0.335207f, +-0.516585f,0.80896f,0.280577f, +-0.560057f,0.80406f,0.199559f, +-0.56953f,0.792393f,0.218515f, +-0.567769f,0.776958f,0.271984f, +0.281384f,0.90217f,-0.326974f, +0.32181f,0.911348f,-0.256676f, +0.424167f,0.891125f,-0.16118f, +0.302129f,0.903121f,-0.305108f, +0.274213f,0.914554f,-0.297318f, +0.377666f,0.887315f,-0.264651f, +0.50458f,0.840574f,-0.197063f, +0.48044f,0.846134f,-0.230726f, +0.426379f,0.87586f,-0.225987f, +0.348305f,0.925694f,-0.147563f, +0.27972f,0.958581f,-0.053649f, +0.144728f,0.989215f,-0.0225097f, +-0.168728f,0.979072f,-0.113791f, +-0.360157f,0.915919f,-0.177143f, +-0.292774f,0.933287f,-0.207987f, +-0.10309f,0.983541f,-0.148387f, +-0.174215f,0.960869f,-0.215359f, +-0.250891f,0.918965f,-0.304233f, +-0.150246f,0.940005f,-0.306294f, +-0.0860686f,0.946791f,-0.310127f, +-0.15131f,0.934427f,-0.322415f, +-0.22276f,0.935306f,-0.27492f, +-0.201088f,0.949203f,-0.242028f, +-0.0437143f,0.949864f,-0.309592f, +0.109977f,0.887847f,-0.446802f, +0.297781f,0.833674f,-0.465096f, +0.214775f,0.818536f,-0.532795f, +0.0269455f,0.850361f,-0.52551f, +-0.017632f,0.796129f,-0.60487f, +0.185146f,0.781388f,-0.595948f, +0.323386f,0.740218f,-0.589491f, +0.406653f,0.707179f,-0.578387f, +0.409551f,0.698057f,-0.587354f, +0.432954f,0.696782f,-0.57188f, +0.429959f,0.722053f,-0.54201f, +0.513634f,0.737641f,-0.438254f, +0.557438f,0.766448f,-0.319093f, +0.451237f,0.872287f,-0.188415f, +0.398866f,0.907449f,-0.132071f, +0.479702f,0.868398f,-0.125579f, +0.492136f,0.869715f,0.0373829f, +0.490052f,0.864036f,0.115287f, +0.467195f,0.882543f,-0.0533554f, +0.500676f,0.860686f,-0.092427f, +0.467521f,0.883982f,0.000254135f, +0.346172f,0.935182f,-0.0748316f, +0.285844f,0.955101f,-0.0779434f, +0.233788f,0.970423f,-0.0601792f, +0.33578f,0.93567f,-0.108509f, +0.44843f,0.890103f,-0.0814045f, +0.344049f,0.926181f,-0.154332f, +0.278254f,0.949058f,-0.147866f, +0.299653f,0.954043f,0.00333978f, +0.154533f,0.964067f,0.21609f, +0.0182142f,0.948347f,0.316711f, +-0.116946f,0.954294f,0.275039f, +-0.30019f,0.894483f,0.33134f, +-0.320232f,0.867471f,0.380717f, +-0.340655f,0.881399f,0.327246f, +-0.432069f,0.860755f,0.269105f, +-0.470649f,0.851696f,0.23044f, +-0.520568f,0.837827f,0.164485f, +-0.594362f,0.792684f,0.135598f, +-0.629645f,0.760492f,0.15874f, +0.105475f,0.917668f,-0.383094f, +0.157333f,0.940076f,-0.302494f, +0.34936f,0.922619f,-0.163471f, +0.441147f,0.892415f,-0.0947875f, +0.353266f,0.911437f,-0.210916f, +0.379048f,0.861228f,-0.33854f, +0.442622f,0.833751f,-0.330068f, +0.481137f,0.838111f,-0.257053f, +0.418048f,0.882249f,-0.216499f, +0.270753f,0.936711f,-0.221958f, +0.184979f,0.961951f,-0.201082f, +0.112903f,0.979904f,-0.164442f, +-0.0774318f,0.983977f,-0.160602f, +-0.269214f,0.939575f,-0.211477f, +-0.244405f,0.926884f,-0.284872f, +-0.16522f,0.91825f,-0.359887f, +-0.0697709f,0.937892f,-0.339838f, +-0.121807f,0.888033f,-0.443351f, +-0.178259f,0.862094f,-0.474361f, +-0.173573f,0.911189f,-0.373641f, +-0.145335f,0.940854f,-0.30606f, +-0.196672f,0.897435f,-0.394881f, +-0.142648f,0.86312f,-0.484434f, +0.079713f,0.828378f,-0.554469f, +0.216417f,0.76965f,-0.600668f, +0.249468f,0.776353f,-0.578828f, +0.204058f,0.841867f,-0.499621f, +0.0644049f,0.826788f,-0.558814f, +0.116412f,0.767322f,-0.630607f, +0.208898f,0.705315f,-0.677416f, +0.323537f,0.664792f,-0.673332f, +0.378749f,0.668133f,-0.640428f, +0.350681f,0.681998f,-0.641795f, +0.388988f,0.701053f,-0.597673f, +0.366172f,0.724838f,-0.583548f, +0.331191f,0.791609f,-0.513486f, +0.441902f,0.864123f,-0.240861f, +0.365381f,0.918735f,-0.149742f, +0.346761f,0.932102f,-0.104611f, +0.441617f,0.896164f,-0.0431763f, +0.429069f,0.903098f,0.0177174f, +0.509493f,0.859732f,0.035759f, +0.550737f,0.834518f,-0.0163997f, +0.446836f,0.894607f,0.00385291f, +0.489488f,0.868437f,0.0788584f, +0.430014f,0.900385f,-0.0662903f, +0.277285f,0.953602f,-0.117285f, +0.208284f,0.969937f,-0.12586f, +0.377184f,0.918436f,-0.119197f, +0.417651f,0.892053f,-0.172653f, +0.381197f,0.917074f,-0.116891f, +0.274507f,0.95009f,-0.148238f, +0.0946799f,0.989623f,-0.108088f, +-0.059654f,0.986641f,0.151597f, +-0.0667871f,0.959734f,0.272857f, +-0.0714815f,0.942101f,0.327622f, +-0.300084f,0.906469f,0.297092f, +-0.336918f,0.914203f,0.225209f, +-0.288002f,0.930996f,0.224278f, +-0.416386f,0.886687f,0.201018f, +-0.454428f,0.859405f,0.234346f, +-0.478891f,0.849426f,0.221671f, +-0.583336f,0.801078f,0.13414f, +-0.664795f,0.744846f,0.0570272f, +0.0774054f,0.9409f,-0.329722f, +0.120466f,0.940242f,-0.318486f, +0.258377f,0.92069f,-0.292526f, +0.391172f,0.892344f,-0.225179f, +0.441921f,0.861239f,-0.250944f, +0.474164f,0.819484f,-0.321892f, +0.430001f,0.828794f,-0.358051f, +0.388327f,0.849227f,-0.357794f, +0.321794f,0.900086f,-0.293759f, +0.306798f,0.936469f,-0.170002f, +0.197413f,0.950888f,-0.238412f, +0.140677f,0.959941f,-0.242328f, +-0.0738732f,0.952166f,-0.296516f, +-0.264161f,0.917561f,-0.297155f, +-0.156821f,0.939785f,-0.303665f, +-0.074827f,0.921443f,-0.381239f, +-0.0597443f,0.912887f,-0.403816f, +-0.0722702f,0.937805f,-0.339556f, +-0.223343f,0.933173f,-0.281613f, +-0.284993f,0.906137f,-0.31256f, +-0.17102f,0.941557f,-0.290212f, +0.0188228f,0.955829f,-0.29332f, +0.0949729f,0.880183f,-0.465036f, +0.154174f,0.836833f,-0.525301f, +0.175395f,0.823625f,-0.539331f, +0.0906162f,0.806123f,-0.584769f, +0.167569f,0.848038f,-0.502744f, +0.206981f,0.812951f,-0.544306f, +0.220466f,0.75453f,-0.618126f, +0.281661f,0.74367f,-0.606318f, +0.323085f,0.773947f,-0.544631f, +0.389827f,0.796004f,-0.463047f, +0.409468f,0.784217f,-0.466197f, +0.383754f,0.755374f,-0.531172f, +0.333252f,0.782449f,-0.526039f, +0.13472f,0.877229f,-0.460782f, +0.220453f,0.931705f,-0.288664f, +0.346271f,0.928921f,-0.131156f, +0.317872f,0.942854f,-0.0999207f, +0.41364f,0.908959f,-0.0519229f, +0.398453f,0.915561f,-0.0546188f, +0.505703f,0.862625f,-0.0119489f, +0.526627f,0.849939f,0.0163649f, +0.402553f,0.915142f,0.0215902f, +0.486926f,0.872826f,0.0328415f, +0.480317f,0.876602f,0.0293992f, +0.350224f,0.935385f,0.0489656f, +0.241613f,0.961192f,-0.13317f, +0.388714f,0.905381f,-0.170843f, +0.410083f,0.900693f,-0.14347f, +0.356005f,0.930194f,-0.0894385f, +0.273996f,0.955273f,-0.111267f, +-0.044831f,0.997624f,-0.0523075f, +-0.196423f,0.976135f,0.0926162f, +-0.135564f,0.988784f,0.0626771f, +-0.172489f,0.970476f,0.168594f, +-0.254529f,0.9218f,0.292405f, +-0.284378f,0.936305f,0.206065f, +-0.327372f,0.917976f,0.223935f, +-0.435353f,0.844597f,0.311647f, +-0.503149f,0.802852f,0.319796f, +-0.41775f,0.811758f,0.408086f, +-0.454925f,0.830308f,0.321918f, +-0.572823f,0.802298f,0.167904f, +0.20617f,0.937765f,-0.279448f, +0.12824f,0.920264f,-0.369687f, +0.239724f,0.89965f,-0.364914f, +0.406692f,0.839091f,-0.361286f, +0.450018f,0.81612f,-0.362535f, +0.486709f,0.828644f,-0.276522f, +0.440087f,0.85086f,-0.286985f, +0.416932f,0.85696f,-0.302962f, +0.239451f,0.901982f,-0.359293f, +0.202502f,0.927776f,-0.313409f, +0.221835f,0.941111f,-0.255147f, +0.127859f,0.963075f,-0.236935f, +0.0102396f,0.970361f,-0.241441f, +-0.185811f,0.907396f,-0.376969f, +-0.143f,0.87175f,-0.468618f, +-0.054802f,0.895065f,-0.442557f, +-0.153942f,0.908075f,-0.389489f, +-0.214862f,0.949277f,-0.22958f, +-0.226443f,0.961303f,-0.156909f, +-0.189142f,0.939849f,-0.284446f, +-0.183498f,0.904381f,-0.385258f, +0.0372666f,0.939229f,-0.341264f, +0.17942f,0.912891f,-0.366659f, +0.186987f,0.89504f,-0.404894f, +0.249987f,0.855827f,-0.452843f, +0.209164f,0.815071f,-0.540287f, +0.137636f,0.780743f,-0.609506f, +0.248264f,0.780183f,-0.574177f, +0.268876f,0.805155f,-0.528613f, +0.166884f,0.854291f,-0.492277f, +0.223895f,0.925944f,-0.304136f, +0.382591f,0.903499f,-0.193167f, +0.505015f,0.839819f,-0.199159f, +0.522375f,0.816711f,-0.245169f, +0.295143f,0.898426f,-0.32515f, +0.045309f,0.962545f,-0.26731f, +0.0698554f,0.972543f,-0.221991f, +0.23803f,0.966556f,-0.0954522f, +0.24345f,0.969904f,-0.00421011f, +0.387893f,0.915554f,0.106303f, +0.388608f,0.912695f,0.126382f, +0.452964f,0.880246f,0.141388f, +0.553021f,0.816379f,0.166411f, +0.46714f,0.881043f,0.0744546f, +0.450683f,0.892414f,0.0219511f, +0.444978f,0.886482f,0.127064f, +0.382178f,0.921652f,0.0670691f, +0.411319f,0.911388f,-0.0137033f, +0.389838f,0.919191f,-0.0558004f, +0.35617f,0.934375f,0.0092699f, +0.326889f,0.943423f,0.0556465f, +0.261297f,0.961477f,0.0853544f, +-0.107365f,0.988428f,0.107158f, +-0.198313f,0.974378f,0.106114f, +-0.119767f,0.989964f,0.0750203f, +-0.291683f,0.947022f,0.134427f, +-0.31644f,0.92799f,0.196723f, +-0.289311f,0.932636f,0.215615f, +-0.411791f,0.85345f,0.319455f, +-0.469106f,0.777331f,0.419161f, +-0.481552f,0.76826f,0.421765f, +-0.441444f,0.803246f,0.399904f, +-0.347505f,0.834501f,0.427607f, +-0.388172f,0.828163f,0.404313f, +0.166663f,0.855647f,-0.489991f, +0.206118f,0.852788f,-0.479863f, +0.253643f,0.809648f,-0.529278f, +0.34663f,0.798296f,-0.492515f, +0.334799f,0.852879f,-0.400633f, +0.411503f,0.867459f,-0.279608f, +0.469719f,0.846111f,-0.251912f, +0.425418f,0.857617f,-0.288986f, +0.321984f,0.890401f,-0.321733f, +0.13105f,0.897315f,-0.421487f, +0.163065f,0.944711f,-0.284482f, +0.0880681f,0.960841f,-0.262734f, +0.0835185f,0.96106f,-0.263417f, +-0.0250069f,0.943064f,-0.33167f, +-0.080502f,0.931121f,-0.355714f, +-0.129429f,0.916002f,-0.379721f, +-0.246145f,0.898013f,-0.36467f, +-0.295885f,0.891242f,-0.343715f, +-0.176282f,0.915144f,-0.362541f, +-0.0418985f,0.91018f,-0.412089f, +-0.0774111f,0.852502f,-0.51696f, +-0.0321668f,0.826692f,-0.561735f, +0.194406f,0.844754f,-0.498595f, +0.282885f,0.80862f,-0.515859f, +0.302949f,0.736294f,-0.605056f, +0.233445f,0.738314f,-0.632768f, +0.172128f,0.759349f,-0.627504f, +0.112225f,0.79134f,-0.600988f, +0.137255f,0.870359f,-0.472902f, +0.0541041f,0.935131f,-0.350147f, +0.048453f,0.960354f,-0.274541f, +0.350102f,0.918679f,-0.182913f, +0.524752f,0.830609f,-0.186344f, +0.518158f,0.835225f,-0.184147f, +0.313736f,0.944893f,-0.0935296f, +0.0308812f,0.997052f,-0.070238f, +0.048477f,0.985949f,-0.159858f, +0.14972f,0.972865f,-0.1764f, +0.155626f,0.983809f,-0.0888849f, +0.284416f,0.958659f,0.0089454f, +0.3659f,0.926807f,0.0845335f, +0.421454f,0.897257f,0.131556f, +0.563402f,0.804293f,0.188919f, +0.539736f,0.827553f,0.154408f, +0.404327f,0.91158f,0.0744378f, +0.452914f,0.883943f,0.116249f, +0.458215f,0.8862f,0.0684684f, +0.412404f,0.90336f,0.117745f, +0.337667f,0.93426f,0.114626f, +0.331072f,0.928113f,0.170285f, +0.265924f,0.943818f,0.196193f, +0.193837f,0.929607f,0.313462f, +-0.0688814f,0.919176f,0.387776f, +-0.142537f,0.930406f,0.33768f, +-0.12463f,0.963373f,0.237444f, +-0.336333f,0.924835f,0.17765f, +-0.311125f,0.930755f,0.192081f, +-0.359893f,0.911001f,0.201382f, +-0.532454f,0.800855f,0.274086f, +-0.552598f,0.767696f,0.324466f, +-0.457025f,0.795874f,0.39713f, +-0.406778f,0.834647f,0.371344f, +-0.39211f,0.844207f,0.365466f, +-0.407171f,0.83024f,0.380675f, +0.088004f,0.820624f,-0.564651f, +0.180508f,0.82686f,-0.532654f, +0.264125f,0.820464f,-0.507027f, +0.247967f,0.854234f,-0.456943f, +0.24322f,0.902001f,-0.356704f, +0.342999f,0.897422f,-0.277462f, +0.495739f,0.849894f,-0.178668f, +0.449958f,0.858561f,-0.245787f, +0.384562f,0.884942f,-0.262659f, +0.158931f,0.931299f,-0.327755f, +-0.00482349f,0.936712f,-0.350067f, +0.115045f,0.961792f,-0.248435f, +0.108639f,0.956333f,-0.271339f, +-0.0605962f,0.963938f,-0.259135f, +-0.116693f,0.974935f,-0.189434f, +-0.0876965f,0.975552f,-0.201512f, +-0.158272f,0.938607f,-0.30654f, +-0.195709f,0.870225f,-0.452113f, +-0.139804f,0.831767f,-0.537233f, +-0.0224753f,0.834621f,-0.550366f, +0.0691358f,0.82738f,-0.557371f, +0.021368f,0.778901f,-0.626782f, +0.103745f,0.763834f,-0.637021f, +0.295282f,0.754578f,-0.586021f, +0.391718f,0.767187f,-0.507919f, +0.243831f,0.78308f,-0.57213f, +0.0624167f,0.795727f,-0.60243f, +0.0157622f,0.882125f,-0.470752f, +-0.0549233f,0.922741f,-0.381487f, +-0.0376875f,0.97f,-0.240167f, +0.0506221f,0.974297f,-0.219507f, +0.328414f,0.911788f,-0.246548f, +0.524714f,0.832523f,-0.177709f, +0.470173f,0.873047f,-0.12933f, +0.188699f,0.978079f,-0.0880599f, +0.0393835f,0.999181f,-0.00932192f, +0.202516f,0.978334f,-0.0430044f, +0.188361f,0.964087f,-0.187232f, +0.0636833f,0.962187f,-0.264841f, +0.180234f,0.965248f,-0.18924f, +0.346543f,0.937198f,-0.0395955f, +0.331037f,0.942573f,-0.0443968f, +0.504726f,0.851052f,0.144785f, +0.565376f,0.80039f,0.199312f, +0.492317f,0.859822f,0.135391f, +0.448961f,0.892857f,0.0352157f, +0.367625f,0.92412f,0.104186f, +0.329385f,0.906428f,0.264373f, +0.348699f,0.881448f,0.318526f, +0.290794f,0.899496f,0.326107f, +0.185082f,0.919339f,0.347219f, +0.0676347f,0.907778f,0.413962f, +-0.145808f,0.884054f,0.444059f, +-0.0815232f,0.884669f,0.459037f, +0.0810938f,0.898461f,0.431499f, +-0.248842f,0.934053f,0.256168f, +-0.367995f,0.892045f,0.262364f, +-0.356163f,0.871443f,0.337246f, +-0.546503f,0.805165f,0.230312f, +-0.590616f,0.793807f,0.145063f, +-0.541291f,0.82267f,0.173836f, +-0.431572f,0.851071f,0.299038f, +-0.381298f,0.858781f,0.342208f, +-0.443875f,0.85724f,0.260987f, +0.118157f,0.850415f,-0.512673f, +0.134653f,0.857894f,-0.49587f, +0.229214f,0.896945f,-0.378087f, +0.208074f,0.910502f,-0.35734f, +0.182505f,0.899208f,-0.397639f, +0.219865f,0.895989f,-0.385828f, +0.451196f,0.865461f,-0.217713f, +0.490084f,0.844039f,-0.217752f, +0.378309f,0.899823f,-0.217259f, +0.231483f,0.942802f,-0.239876f, +0.0439163f,0.94313f,-0.329511f, +0.0365981f,0.93055f,-0.364332f, +0.0406622f,0.963235f,-0.265566f, +-0.0474005f,0.988537f,-0.143342f, +-0.135564f,0.953464f,-0.269312f, +-0.0159099f,0.95648f,-0.291363f, +6.71815e-006f,0.933398f,-0.358843f, +-0.0477574f,0.880875f,-0.470933f, +-0.0515582f,0.822668f,-0.56618f, +0.00280332f,0.78244f,-0.62272f, +0.0365076f,0.790824f,-0.610954f, +0.0809221f,0.832084f,-0.548715f, +0.112086f,0.801748f,-0.587057f, +0.219407f,0.814817f,-0.536594f, +0.31647f,0.811557f,-0.491143f, +0.326532f,0.816359f,-0.476376f, +0.0311646f,0.874097f,-0.484751f, +-0.166146f,0.898216f,-0.406943f, +-0.145486f,0.939877f,-0.308975f, +-0.113562f,0.952885f,-0.281273f, +0.0633693f,0.957888f,-0.280063f, +0.322061f,0.911056f,-0.257398f, +0.438519f,0.889327f,-0.12961f, +0.430695f,0.901938f,0.0317863f, +0.232727f,0.970972f,0.0552405f, +0.0388751f,0.995464f,-0.0868351f, +0.197289f,0.970749f,-0.136837f, +0.308804f,0.945817f,-0.100347f, +0.177873f,0.966831f,-0.183299f, +0.0327621f,0.970738f,-0.237896f, +0.244781f,0.968393f,-0.0479323f, +0.27827f,0.960269f,-0.0211936f, +0.355239f,0.931705f,0.0757045f, +0.555707f,0.816071f,0.158801f, +0.563884f,0.814994f,0.133487f, +0.420142f,0.89843f,0.127685f, +0.31027f,0.90429f,0.293243f, +0.233723f,0.926208f,0.295826f, +0.272016f,0.906457f,0.323021f, +0.267428f,0.881549f,0.389042f, +0.161017f,0.891985f,0.422417f, +0.0459966f,0.878435f,0.475642f, +-0.0917474f,0.877231f,0.47122f, +-0.0819927f,0.91503f,0.394964f, +0.108269f,0.907964f,0.40482f, +-0.16221f,0.904236f,0.395026f, +-0.422279f,0.840786f,0.338761f, +-0.374364f,0.835182f,0.402893f, +-0.384829f,0.826017f,0.411828f, +-0.512379f,0.829197f,0.223383f, +-0.585197f,0.801652f,0.122056f, +-0.526709f,0.831787f,0.175237f, +-0.374079f,0.907515f,0.191003f, +-0.329797f,0.931547f,0.153144f, +0.105779f,0.878895f,-0.465138f, +0.0405535f,0.897741f,-0.438654f, +0.106545f,0.927041f,-0.359504f, +0.255352f,0.917446f,-0.305103f, +0.298997f,0.88918f,-0.346352f, +0.205215f,0.859845f,-0.467497f, +0.304244f,0.842016f,-0.445471f, +0.435228f,0.863678f,-0.254238f, +0.39753f,0.896082f,-0.197502f, +0.268558f,0.910516f,-0.314385f, +0.0970216f,0.931439f,-0.350727f, +0.0336528f,0.944013f,-0.328188f, +-0.0988412f,0.948055f,-0.302362f, +-0.0597673f,0.966409f,-0.249964f, +0.0558923f,0.934228f,-0.352269f, +-0.00489276f,0.88655f,-0.462606f, +0.0451038f,0.899627f,-0.434323f, +0.0627933f,0.870215f,-0.488654f, +0.0536848f,0.846805f,-0.529187f, +0.0729181f,0.867797f,-0.491539f, +-0.0450251f,0.86132f,-0.506063f, +0.0321391f,0.857039f,-0.514249f, +0.105366f,0.853869f,-0.509711f, +0.20021f,0.860626f,-0.468229f, +0.336826f,0.823703f,-0.456137f, +0.291163f,0.890761f,-0.348954f, +-0.0337704f,0.937324f,-0.34682f, +-0.238938f,0.893089f,-0.381184f, +-0.1654f,0.905926f,-0.389797f, +-0.0746684f,0.904792f,-0.419256f, +0.0731105f,0.895556f,-0.438901f, +0.199233f,0.902713f,-0.381334f, +0.277877f,0.941082f,-0.192742f, +0.300522f,0.95354f,-0.0211427f, +0.316945f,0.945681f,0.0723468f, +0.218722f,0.970853f,-0.0980014f, +0.256356f,0.93882f,-0.229999f, +0.242436f,0.93442f,-0.26093f, +0.1983f,0.960329f,-0.196077f, +0.00223103f,0.977894f,-0.209089f, +0.104164f,0.98625f,-0.128296f, +0.285507f,0.957716f,-0.0355725f, +0.283907f,0.956269f,-0.0703361f, +0.529334f,0.848145f,0.0213636f, +0.533064f,0.836918f,0.124145f, +0.319483f,0.916151f,0.242069f, +0.17728f,0.930248f,0.321263f, +0.27524f,0.891192f,0.360581f, +0.317681f,0.901882f,0.292724f, +0.194688f,0.951543f,0.23804f, +0.108971f,0.911619f,0.396329f, +-0.0300123f,0.895185f,0.444683f, +-0.0818392f,0.875146f,0.476887f, +-0.0034355f,0.872809f,0.48805f, +0.0854438f,0.889906f,0.448069f, +-0.143928f,0.891079f,0.430422f, +-0.400827f,0.846578f,0.350204f, +-0.436121f,0.820693f,0.369135f, +-0.389169f,0.817738f,0.42409f, +-0.354493f,0.838309f,0.414212f, +-0.495629f,0.825913f,0.268736f, +-0.491187f,0.862049f,0.124928f, +-0.360891f,0.926358f,0.107794f, +-0.272797f,0.945677f,0.17685f, +-0.0230447f,0.8982f,-0.438983f, +-0.0253824f,0.922509f,-0.38514f, +0.0868314f,0.93389f,-0.346856f, +0.228815f,0.908408f,-0.349913f, +0.325232f,0.887343f,-0.326875f, +0.342601f,0.877959f,-0.334385f, +0.256841f,0.884237f,-0.390073f, +0.281416f,0.889548f,-0.359874f, +0.383834f,0.865745f,-0.321181f, +0.3194f,0.893039f,-0.316962f, +0.102059f,0.965529f,-0.239452f, +-0.0466698f,0.958891f,-0.279912f, +-0.0536344f,0.964707f,-0.257804f, +-0.0261637f,0.940106f,-0.339875f, +0.144391f,0.948897f,-0.280616f, +0.0981473f,0.936323f,-0.337144f, +0.012852f,0.869861f,-0.493129f, +0.144402f,0.872896f,-0.466049f, +-0.00636809f,0.871363f,-0.490597f, +-0.0613187f,0.915967f,-0.396541f, +0.0199429f,0.949099f,-0.314346f, +0.0355652f,0.92816f,-0.370479f, +0.140076f,0.947915f,-0.286071f, +0.222188f,0.910114f,-0.349749f, +0.215543f,0.917499f,-0.33427f, +0.183013f,0.971215f,-0.152469f, +0.0390344f,0.988083f,-0.14889f, +-0.127226f,0.955382f,-0.266569f, +-0.116102f,0.92344f,-0.365757f, +-0.0309649f,0.920225f,-0.390164f, +0.00625843f,0.924708f,-0.380627f, +0.101949f,0.952725f,-0.286221f, +0.10526f,0.958946f,-0.263332f, +0.1589f,0.975537f,-0.151918f, +0.291601f,0.956292f,-0.0217678f, +0.33385f,0.942155f,0.0297851f, +0.349208f,0.937042f,0.00260008f, +0.278057f,0.953965f,-0.112407f, +0.149531f,0.968881f,-0.197256f, +-0.00612536f,0.988275f,-0.152563f, +-0.00797921f,0.994274f,-0.106558f, +0.301027f,0.953574f,-0.00894642f, +0.304582f,0.944145f,-0.125778f, +0.403446f,0.913254f,-0.0565483f, +0.37426f,0.908704f,0.184893f, +0.255667f,0.895707f,0.363791f, +0.219787f,0.909558f,0.352701f, +0.267099f,0.929513f,0.254289f, +0.378434f,0.885367f,0.270025f, +0.147409f,0.95291f,0.265015f, +-0.0634097f,0.932842f,0.354663f, +-0.0326192f,0.907501f,0.418782f, +-0.118713f,0.911859f,0.392963f, +-0.0609125f,0.902157f,0.427087f, +0.138333f,0.871993f,0.469567f, +-0.0649916f,0.904886f,0.420664f, +-0.383734f,0.861279f,0.333085f, +-0.474942f,0.817835f,0.324924f, +-0.422908f,0.836367f,0.348768f, +-0.339416f,0.853379f,0.395651f, +-0.324702f,0.875389f,0.358137f, +-0.41353f,0.899847f,0.138815f, +-0.448451f,0.884614f,0.12787f, +-0.414049f,0.866279f,0.279505f, +0.070634f,0.912028f,-0.404001f, +-0.0676482f,0.885638f,-0.459422f, +0.0565435f,0.906984f,-0.417353f, +0.246119f,0.879096f,-0.408185f, +0.292529f,0.859337f,-0.419485f, +0.280896f,0.904751f,-0.320192f, +0.320721f,0.917291f,-0.23604f, +0.350916f,0.874365f,-0.335178f, +0.376904f,0.866371f,-0.327636f, +0.17512f,0.962866f,-0.205478f, +0.0176642f,0.987314f,-0.157793f, +0.0227212f,0.982851f,-0.182998f, +0.0272561f,0.971904f,-0.233795f, +-0.0877209f,0.950392f,-0.298429f, +0.0166276f,0.994097f,-0.107211f, +0.266845f,0.962366f,-0.0514236f, +0.216132f,0.934464f,-0.282956f, +0.0993362f,0.906446f,-0.410472f, +-0.0104212f,0.924877f,-0.380123f, +-0.166185f,0.907878f,-0.384889f, +-0.0197905f,0.953108f,-0.301983f, +-0.0183125f,0.962192f,-0.271757f, +0.0845408f,0.976284f,-0.199307f, +0.269635f,0.943751f,-0.191394f, +0.189274f,0.968047f,-0.164501f, +0.102539f,0.979864f,-0.171327f, +0.106979f,0.970988f,-0.213865f, +-0.0373949f,0.962501f,-0.268688f, +-0.0919497f,0.957563f,-0.273163f, +-0.0692205f,0.979823f,-0.187497f, +-0.0661107f,0.993399f,-0.093741f, +0.0537161f,0.998551f,0.00311785f, +0.163558f,0.98647f,-0.0111964f, +0.128373f,0.980868f,-0.146347f, +0.126964f,0.974881f,-0.182993f, +0.228868f,0.973261f,0.0195364f, +0.336464f,0.933228f,0.126005f, +0.409696f,0.899435f,0.152205f, +0.227221f,0.973118f,0.0375761f, +-0.0400449f,0.999001f,-0.0198394f, +-0.0832424f,0.995769f,-0.0389306f, +0.262425f,0.963268f,0.0569854f, +0.380638f,0.919787f,0.0954299f, +0.267185f,0.959941f,0.0844166f, +0.200067f,0.945675f,0.256267f, +0.180437f,0.922348f,0.341639f, +0.274022f,0.906356f,0.321607f, +0.375587f,0.88639f,0.270641f, +0.289567f,0.933145f,0.213051f, +0.118001f,0.9078f,0.402461f, +-0.100351f,0.886215f,0.452275f, +-0.0321373f,0.879207f,0.475355f, +-0.064732f,0.903306f,0.424085f, +-0.117284f,0.933968f,0.337563f, +0.107835f,0.909874f,0.400625f, +-0.00684675f,0.915037f,0.403311f, +-0.3665f,0.879987f,0.302161f, +-0.484488f,0.825175f,0.290444f, +-0.455029f,0.825809f,0.33315f, +-0.355514f,0.861697f,0.362061f, +-0.249905f,0.90704f,0.338859f, +-0.283441f,0.915216f,0.286426f, +-0.489082f,0.840765f,0.232193f, +-0.566036f,0.779585f,0.26805f, +0.300059f,0.882066f,-0.363212f, +0.0511478f,0.860745f,-0.506461f, +0.0202137f,0.82997f,-0.557442f, +0.244641f,0.828925f,-0.503024f, +0.229733f,0.86489f,-0.446306f, +0.151553f,0.888421f,-0.433289f, +0.276054f,0.875076f,-0.397538f, +0.35746f,0.874812f,-0.326997f, +0.20869f,0.962246f,-0.174729f, +0.135202f,0.98952f,0.050694f, +0.0768682f,0.997036f,0.00329808f, +0.0854955f,0.992826f,-0.08359f, +0.0751533f,0.982531f,-0.170249f, +-0.0858423f,0.966447f,-0.242097f, +-0.101218f,0.962967f,-0.2499f, +0.245897f,0.943422f,-0.222463f, +0.411229f,0.896277f,-0.166064f, +0.160383f,0.921177f,-0.354556f, +0.0135902f,0.93936f,-0.342662f, +-0.185366f,0.907574f,-0.37676f, +-0.130182f,0.940725f,-0.313191f, +-0.0326676f,0.972591f,-0.230215f, +0.0675199f,0.972602f,-0.222457f, +0.233107f,0.94649f,-0.2232f, +0.212831f,0.95378f,-0.212148f, +0.167019f,0.9356f,-0.311059f, +0.16946f,0.90555f,-0.388925f, +-0.0763448f,0.914067f,-0.398312f, +-0.178349f,0.9565f,-0.230865f, +-0.221816f,0.964561f,-0.142896f, +-0.163528f,0.986246f,-0.0240246f, +-0.0459992f,0.998297f,0.0358721f, +0.192503f,0.971257f,0.140008f, +0.306262f,0.942491f,0.133843f, +0.166989f,0.985549f,-0.0284312f, +0.110164f,0.988175f,-0.106645f, +0.230491f,0.969982f,-0.0775155f, +0.320779f,0.937031f,0.138109f, +0.2844f,0.912116f,0.295231f, +0.0676957f,0.97278f,0.221621f, +-0.0445371f,0.996486f,0.0709375f, +0.140086f,0.988598f,0.0552233f, +0.294951f,0.934183f,0.200765f, +0.239076f,0.923996f,0.298453f, +0.115077f,0.947116f,0.299546f, +0.169084f,0.942486f,0.288323f, +0.304609f,0.90997f,0.281369f, +0.369662f,0.880322f,0.297294f, +0.206677f,0.906857f,0.36728f, +-0.0427609f,0.882729f,0.467933f, +-0.167345f,0.859324f,0.483279f, +-0.0302574f,0.860894f,0.507884f, +0.0910322f,0.886636f,0.453421f, +-0.0366606f,0.947171f,0.318627f, +0.025939f,0.94095f,0.337552f, +0.0591946f,0.91956f,0.388466f, +-0.284221f,0.911546f,0.297158f, +-0.532586f,0.813173f,0.234739f, +-0.487487f,0.825499f,0.284445f, +-0.31853f,0.893358f,0.316938f, +-0.238637f,0.92505f,0.295524f, +-0.265409f,0.911937f,0.312937f, +-0.505062f,0.827653f,0.244749f, +-0.589625f,0.757122f,0.281262f, +0.260545f,0.875981f,-0.405923f, +0.198469f,0.90372f,-0.379342f, +0.0608985f,0.867502f,-0.493691f, +0.108599f,0.877043f,-0.467977f, +0.149016f,0.918586f,-0.366053f, +0.269933f,0.909568f,-0.315946f, +0.225091f,0.894351f,-0.386613f, +0.14483f,0.975181f,-0.16747f, +0.0237141f,0.999718f,0.00125985f, +0.0312597f,0.997955f,0.0557504f, +0.105656f,0.993029f,0.0522575f, +0.205288f,0.977382f,0.0508146f, +0.175007f,0.977751f,-0.115656f, +0.0411408f,0.976103f,-0.213378f, +-0.0123853f,0.935985f,-0.351821f, +0.185506f,0.902134f,-0.38954f, +0.361594f,0.882471f,-0.300824f, +0.229178f,0.926898f,-0.297216f, +-0.016076f,0.953923f,-0.299621f, +-0.176229f,0.940869f,-0.289326f, +-0.197595f,0.933757f,-0.298419f, +-0.0925101f,0.952321f,-0.290735f, +0.0363018f,0.966473f,-0.254189f, +0.27059f,0.939141f,-0.211649f, +0.283887f,0.910685f,-0.300101f, +0.267987f,0.87929f,-0.39374f, +0.167837f,0.906306f,-0.387866f, +-0.162045f,0.958045f,-0.236411f, +-0.34242f,0.923851f,-0.171018f, +-0.280408f,0.954479f,-0.101693f, +-0.219474f,0.974995f,-0.0348799f, +-0.111179f,0.993643f,0.0176973f, +0.0791225f,0.990452f,0.112896f, +0.243665f,0.947394f,0.207537f, +0.282223f,0.914505f,0.289882f, +0.280685f,0.943977f,0.173563f, +0.165641f,0.985889f,-0.0242044f, +0.0702016f,0.994363f,0.0794649f, +0.118053f,0.960325f,0.252664f, +0.204772f,0.904931f,0.373051f, +0.0632983f,0.962848f,0.262521f, +0.122554f,0.958346f,0.257978f, +0.174517f,0.943136f,0.28291f, +0.181765f,0.923678f,0.337315f, +0.176745f,0.924152f,0.338681f, +0.201711f,0.945597f,0.255262f, +0.29766f,0.929054f,0.219676f, +0.268359f,0.928086f,0.258147f, +0.100906f,0.896734f,0.430912f, +-0.0388415f,0.876619f,0.479615f, +-0.130193f,0.899332f,0.417434f, +0.000668505f,0.914851f,0.403791f, +0.198601f,0.908384f,0.367961f, +0.0382447f,0.953766f,0.298106f, +-0.0134843f,0.968824f,0.247384f, +0.0247843f,0.964757f,0.261972f, +-0.214942f,0.928034f,0.304224f, +-0.51491f,0.834181f,0.197508f, +-0.514132f,0.845f,0.147116f, +-0.364403f,0.910649f,0.194754f, +-0.252308f,0.925047f,0.283953f, +-0.245043f,0.926077f,0.286941f, +-0.475784f,0.852889f,0.214964f, +-0.66621f,0.724577f,0.176499f, +0.0831836f,0.888999f,-0.45029f, +0.181271f,0.909397f,-0.374349f, +0.118635f,0.893305f,-0.433511f, +0.0803087f,0.896743f,-0.435204f, +0.0532614f,0.909245f,-0.41284f, +0.209897f,0.941844f,-0.262435f, +0.164344f,0.979747f,-0.114402f, +-0.0796744f,0.996148f,-0.0366233f, +-0.0133458f,0.996096f,0.0872637f, +0.0764545f,0.99532f,0.0590999f, +0.136206f,0.990597f,0.0128964f, +0.22076f,0.975032f,-0.0240476f, +0.302428f,0.952936f,-0.021205f, +0.123508f,0.990766f,-0.0559322f, +0.0598433f,0.996046f,-0.06566f, +0.217088f,0.972764f,-0.0812636f, +0.324106f,0.93941f,-0.111642f, +0.231973f,0.969426f,-0.0800149f, +-0.0239272f,0.988929f,-0.146448f, +-0.168479f,0.969286f,-0.179165f, +-0.198758f,0.9628f,-0.183064f, +-0.0847832f,0.988177f,-0.12774f, +-0.00304443f,0.993662f,-0.112364f, +0.297886f,0.949812f,-0.0955022f, +0.392699f,0.900627f,-0.186169f, +0.309254f,0.921444f,-0.235165f, +-0.0368216f,0.992281f,-0.118418f, +-0.30784f,0.939111f,0.152661f, +-0.339391f,0.929078f,0.147065f, +-0.31987f,0.942094f,0.100706f, +-0.261939f,0.955297f,0.137099f, +-0.18149f,0.977639f,0.106224f, +-0.0176854f,0.987381f,0.157371f, +0.134774f,0.952305f,0.273773f, +0.227558f,0.898637f,0.375058f, +0.367312f,0.872839f,0.3213f, +0.289472f,0.940027f,0.180432f, +0.0121921f,0.995617f,0.0927227f, +-0.0151053f,0.984704f,0.173582f, +0.12465f,0.941586f,0.312855f, +0.123765f,0.936041f,0.329407f, +0.0496474f,0.956015f,0.289087f, +0.155803f,0.919433f,0.361065f, +0.180039f,0.912678f,0.366885f, +0.192318f,0.910529f,0.365993f, +0.269572f,0.892548f,0.361509f, +0.331198f,0.898525f,0.288029f, +0.198758f,0.948186f,0.247866f, +-0.0345441f,0.951973f,0.304226f, +-0.0327497f,0.929484f,0.367404f, +-0.0643392f,0.937143f,0.342962f, +0.00774044f,0.965859f,0.258952f, +0.179174f,0.948429f,0.261495f, +0.132443f,0.935778f,0.32677f, +0.0607758f,0.973146f,0.222018f, +-0.0289622f,0.977742f,0.2078f, +-0.247283f,0.928769f,0.276114f, +-0.440694f,0.866976f,0.232681f, +-0.493254f,0.853754f,0.166745f, +-0.437376f,0.881741f,0.176734f, +-0.303558f,0.920161f,0.247297f, +-0.230002f,0.942128f,0.243914f, +-0.435382f,0.879414f,0.192544f, +-0.672886f,0.738322f,0.045878f, +0.0719528f,0.93004f,-0.360345f, +0.170321f,0.920666f,-0.351232f, +0.181011f,0.922477f,-0.340985f, +0.0828362f,0.939404f,-0.332654f, +-0.0227994f,0.947238f,-0.31972f, +-0.0485785f,0.963562f,-0.263036f, +0.0586424f,0.995988f,-0.0676002f, +-0.0660447f,0.996659f,-0.0480482f, +-0.0602898f,0.992772f,-0.103773f, +0.058767f,0.996066f,-0.0663303f, +0.189158f,0.981943f,0.00282556f, +0.237805f,0.968932f,-0.0679702f, +0.226076f,0.973949f,-0.0176966f, +0.0903031f,0.990597f,0.102775f, +0.00876316f,0.995102f,0.0984623f, +0.239141f,0.958139f,0.157419f, +0.358816f,0.926379f,0.11434f, +0.290281f,0.955997f,0.0425008f, +0.0827916f,0.995067f,-0.054651f, +-0.14974f,0.985436f,-0.0805802f, +-0.250148f,0.9681f,-0.0144092f, +-0.190918f,0.980525f,0.0460446f, +0.000678111f,0.99542f,0.0955933f, +0.316233f,0.948486f,0.019255f, +0.451155f,0.892443f,0.00187563f, +0.20864f,0.975493f,0.0698802f, +-0.187263f,0.946264f,0.263661f, +-0.412354f,0.843904f,0.343207f, +-0.267988f,0.899756f,0.344414f, +-0.237384f,0.936767f,0.25713f, +-0.24929f,0.96341f,0.0984657f, +-0.12508f,0.979898f,0.155419f, +-0.075281f,0.975532f,0.206567f, +-0.0362475f,0.956877f,0.288223f, +0.179598f,0.903623f,0.388856f, +0.452503f,0.830262f,0.325433f, +0.44384f,0.859576f,0.253251f, +0.0283124f,0.992393f,0.119807f, +-0.131018f,0.979645f,0.152082f, +-0.0108162f,0.971878f,0.235238f, +0.177243f,0.920605f,0.347953f, +0.0690998f,0.954542f,0.289956f, +0.0964158f,0.939858f,0.327675f, +0.141817f,0.921257f,0.362178f, +0.189018f,0.897606f,0.398216f, +0.266469f,0.899974f,0.345024f, +0.359545f,0.871551f,0.333357f, +0.237931f,0.897592f,0.371104f, +-0.0217966f,0.934365f,0.355651f, +-0.0978092f,0.948287f,0.30197f, +0.00875447f,0.940305f,0.340221f, +0.0870369f,0.963741f,0.252246f, +0.143744f,0.964801f,0.220218f, +0.0987042f,0.960888f,0.25875f, +0.124661f,0.953903f,0.273f, +-0.0397023f,0.970451f,0.238011f, +-0.294392f,0.938787f,0.17892f, +-0.415783f,0.892445f,0.175119f, +-0.502145f,0.854833f,0.130809f, +-0.438287f,0.876552f,0.198899f, +-0.315043f,0.920499f,0.231147f, +-0.194294f,0.951114f,0.240065f, +-0.351808f,0.923717f,0.151587f, +-0.54821f,0.835857f,0.0284484f, +0.0750917f,0.989867f,-0.120519f, +0.16891f,0.981624f,-0.0887941f, +0.190217f,0.976992f,-0.0964579f, +0.031324f,0.983953f,-0.175657f, +-0.0605958f,0.993695f,-0.0943344f, +-0.0750681f,0.99685f,-0.025582f, +-0.0331924f,0.999431f,-0.00606515f, +-0.0198899f,0.99954f,0.0228873f, +-0.0160511f,0.998799f,-0.0462827f, +0.0298246f,0.995221f,-0.092978f, +0.113995f,0.985706f,-0.124048f, +0.249662f,0.968309f,-0.00683024f, +0.100872f,0.992347f,0.0712218f, +0.0920036f,0.982533f,0.161755f, +0.0527146f,0.998589f,-0.00636128f, +0.182827f,0.9816f,-0.0550969f, +0.393766f,0.919069f,-0.0161334f, +0.337394f,0.941358f,0.00313128f, +0.105574f,0.990777f,0.0849468f, +-0.199161f,0.971911f,0.125398f, +-0.309481f,0.93868f,0.151989f, +-0.20903f,0.965522f,0.15516f, +0.0624223f,0.987754f,0.142987f, +0.384312f,0.922399f,0.0385395f, +0.395292f,0.916973f,0.0539f, +-0.00445825f,0.983693f,0.179798f, +-0.32103f,0.866957f,0.381215f, +-0.378167f,0.863609f,0.33342f, +-0.220175f,0.926633f,0.304752f, +-0.0614943f,0.950074f,0.305906f, +-0.12116f,0.98024f,0.156364f, +-0.278268f,0.956461f,0.0880323f, +-0.168756f,0.960122f,0.222908f, +-0.0650574f,0.977781f,0.199281f, +0.11325f,0.979757f,0.165078f, +0.469769f,0.846474f,0.250598f, +0.492575f,0.830428f,0.260305f, +0.123756f,0.962501f,0.241404f, +-0.13585f,0.964887f,0.224807f, +-0.0763658f,0.97309f,0.217403f, +0.0878568f,0.965257f,0.246088f, +0.105594f,0.951417f,0.289233f, +0.0757959f,0.967864f,0.239781f, +0.0993833f,0.975608f,0.195732f, +0.186309f,0.954458f,0.23302f, +0.338273f,0.909543f,0.241458f, +0.326788f,0.907649f,0.263405f, +0.193788f,0.920444f,0.339454f, +0.0304147f,0.954662f,0.296135f, +-0.0232537f,0.980981f,0.192706f, +0.000389577f,0.986091f,0.166207f, +0.0882095f,0.967853f,0.235542f, +0.188357f,0.927906f,0.321731f, +0.0670292f,0.972109f,0.224745f, +0.0943312f,0.961869f,0.256728f, +0.0613113f,0.959756f,0.274061f, +-0.207348f,0.967924f,0.141881f, +-0.415608f,0.907723f,0.0575284f, +-0.500123f,0.863342f,0.0672098f, +-0.492039f,0.866172f,0.0874256f, +-0.354073f,0.931677f,0.0813054f, +-0.181316f,0.978479f,0.0985071f, +-0.266622f,0.956284f,0.120138f, +-0.442863f,0.891447f,0.0958846f, +-0.0871303f,0.98944f,-0.115829f, +0.0906659f,0.9958f,-0.0127409f, +0.283182f,0.958456f,0.0342056f, +0.0813038f,0.994836f,-0.0607581f, +-0.14732f,0.989082f,0.00362058f, +-0.15085f,0.987502f,0.0456442f, +-0.0204288f,0.99901f,0.039516f, +0.00607957f,0.996993f,-0.0772516f, +0.0245166f,0.989435f,-0.142892f, +0.112542f,0.984768f,-0.132539f, +0.117701f,0.980135f,-0.159633f, +0.0712861f,0.996099f,-0.0520052f, +0.0255235f,0.995475f,0.0915291f, +0.102558f,0.988742f,0.10895f, +0.263691f,0.960156f,0.0925667f, +0.248163f,0.965214f,-0.0823197f, +0.340591f,0.934756f,-0.101139f, +0.19652f,0.980248f,0.0222232f, +-0.0707824f,0.98306f,0.169067f, +-0.214629f,0.938414f,0.270766f, +-0.253216f,0.94197f,0.220395f, +-0.140751f,0.981088f,0.132876f, +0.0855474f,0.99626f,0.0121329f, +0.407822f,0.912623f,0.0283097f, +0.314806f,0.941456f,0.120654f, +-0.127318f,0.956166f,0.263699f, +-0.403379f,0.856412f,0.322248f, +-0.326125f,0.89105f,0.315709f, +-0.192548f,0.934549f,0.29924f, +-0.115959f,0.956033f,0.26936f, +-0.0455884f,0.940005f,0.3381f, +-0.221624f,0.931041f,0.289905f, +-0.142796f,0.963558f,0.226198f, +0.0818112f,0.991531f,0.100865f, +0.115133f,0.989689f,-0.0852087f, +0.362891f,0.931224f,-0.0336289f, +0.464909f,0.869676f,0.1659f, +0.12135f,0.938462f,0.323362f, +-0.154102f,0.92745f,0.340718f, +-0.00840056f,0.94535f,0.325948f, +0.0978542f,0.97811f,0.183647f, +0.11792f,0.982347f,0.145222f, +0.146369f,0.980631f,0.130149f, +0.169334f,0.978423f,0.118383f, +0.164013f,0.985699f,0.0386944f, +0.265906f,0.961228f,0.0730397f, +0.245913f,0.944548f,0.217615f, +0.193695f,0.94265f,0.271832f, +0.193351f,0.95598f,0.22072f, +0.0582845f,0.995708f,0.0718875f, +-0.00685416f,0.998237f,0.0589609f, +-0.0637908f,0.997757f,0.0202719f, +0.11477f,0.985697f,0.123411f, +0.150647f,0.970382f,0.188848f, +0.0830539f,0.976206f,0.200309f, +0.0503424f,0.976583f,0.20917f, +-0.0756986f,0.967299f,0.242081f, +-0.38538f,0.913963f,0.127097f, +-0.499709f,0.856093f,0.131896f, +-0.457912f,0.888414f,0.0322019f, +-0.285439f,0.956482f,-0.0605596f, +-0.224005f,0.968049f,-0.112706f, +-0.33892f,0.940492f,-0.0246551f, +-0.468811f,0.882994f,0.0231736f, +-0.219323f,0.927554f,-0.302556f, +0.0032435f,0.972826f,-0.231515f, +0.227016f,0.959392f,-0.167423f, +0.0751831f,0.995555f,-0.0567285f, +-0.21163f,0.975526f,-0.0596754f, +-0.120787f,0.989714f,-0.0766664f, +0.103292f,0.984862f,-0.139202f, +0.130327f,0.957045f,-0.258998f, +0.100597f,0.957666f,-0.269734f, +0.0434385f,0.943793f,-0.327671f, +-0.00659457f,0.974177f,-0.225689f, +-0.0387678f,0.996731f,-0.0708824f, +0.0108947f,0.998722f,-0.049343f, +0.045379f,0.994354f,-0.0959194f, +0.256328f,0.966322f,0.0227405f, +0.338426f,0.940797f,0.0191927f, +0.245639f,0.967185f,0.0649251f, +0.104201f,0.958601f,0.265004f, +-0.106481f,0.952706f,0.284628f, +-0.229215f,0.947098f,0.224647f, +-0.194403f,0.966329f,0.168569f, +-0.00252669f,0.996043f,0.0888332f, +0.156392f,0.987666f,-0.00755935f, +0.321695f,0.943636f,0.0778705f, +0.130492f,0.960095f,0.247363f, +-0.218806f,0.887212f,0.406175f, +-0.387978f,0.851763f,0.352097f, +-0.317465f,0.905687f,0.280974f, +-0.175202f,0.945708f,0.273753f, +-0.0852507f,0.952748f,0.291554f, +-0.110501f,0.951599f,0.28679f, +-0.162568f,0.933525f,0.319534f, +-0.0379096f,0.973407f,0.225923f, +0.243134f,0.964593f,0.102203f, +0.236277f,0.971524f,-0.017745f, +0.298887f,0.954255f,-0.00800205f, +0.225509f,0.966982f,0.118704f, +-0.0160588f,0.939828f,0.341271f, +-0.127862f,0.916925f,0.378021f, +0.078893f,0.93958f,0.333116f, +0.244086f,0.933689f,0.262004f, +0.186692f,0.967385f,0.17121f, +0.108188f,0.990525f,0.0845894f, +0.174941f,0.977766f,0.115627f, +0.231991f,0.970242f,0.0693606f, +0.186114f,0.981267f,0.0497696f, +0.166608f,0.977012f,0.133002f, +0.191728f,0.971565f,0.138929f, +0.25765f,0.957218f,0.131718f, +0.087274f,0.989729f,0.113225f, +-0.00280678f,0.977756f,0.209725f, +0.0607703f,0.980671f,0.185986f, +0.0485237f,0.997381f,0.053629f, +0.0587736f,0.987863f,0.14378f, +0.0482407f,0.976088f,0.211956f, +0.0134663f,0.978159f,0.20742f, +-0.112292f,0.962623f,0.246469f, +-0.319272f,0.919627f,0.228803f, +-0.453582f,0.883075f,0.120176f, +-0.338159f,0.939324f,0.0576029f, +-0.23768f,0.971299f,-0.0092623f, +-0.191895f,0.980604f,-0.0399f, +-0.401044f,0.906011f,-0.135303f, +-0.489506f,0.868205f,-0.081269f, +-0.196977f,0.901169f,-0.386128f, +-0.0562291f,0.922285f,-0.382399f, +0.0867548f,0.952728f,-0.291176f, +0.0232316f,0.988917f,-0.146644f, +-0.11605f,0.968007f,-0.222475f, +-0.0789033f,0.942785f,-0.323929f, +0.139529f,0.948189f,-0.285427f, +0.132434f,0.962288f,-0.23762f, +0.0765905f,0.96807f,-0.238692f, +0.0641003f,0.96574f,-0.251472f, +-0.105766f,0.965216f,-0.239106f, +-0.110895f,0.972771f,-0.203515f, +0.0206339f,0.984024f,-0.176838f, +0.0647147f,0.988173f,-0.139018f, +0.148599f,0.980872f,-0.125734f, +0.271512f,0.961735f,0.0367049f, +0.0561912f,0.976773f,0.206777f, +-0.0583132f,0.913697f,0.402191f, +-0.0462589f,0.893353f,0.446968f, +-0.125152f,0.910112f,0.39501f, +-0.0803843f,0.940756f,0.329418f, +0.0619859f,0.973174f,0.221562f, +0.135828f,0.971328f,0.195124f, +0.132962f,0.954202f,0.267992f, +-0.0325488f,0.903596f,0.427147f, +-0.270164f,0.841605f,0.467668f, +-0.262238f,0.850223f,0.456456f, +-0.212116f,0.889937f,0.403757f, +-0.177521f,0.909486f,0.375929f, +-0.116828f,0.901627f,0.416436f, +-0.0747169f,0.915103f,0.396238f, +-0.119776f,0.962629f,0.242896f, +0.0380452f,0.99097f,0.128572f, +0.304108f,0.937317f,0.17016f, +0.240764f,0.951762f,0.190215f, +0.194326f,0.952804f,0.233243f, +0.142453f,0.936947f,0.31912f, +-0.0935081f,0.945618f,0.31155f, +-0.0887705f,0.956167f,0.27904f, +0.107828f,0.967058f,0.230592f, +0.241042f,0.935322f,0.258984f, +0.259409f,0.922717f,0.285133f, +0.218487f,0.962504f,0.160778f, +0.220571f,0.975062f,0.0245473f, +0.235132f,0.971421f,-0.0324531f, +0.193322f,0.980828f,0.0245576f, +0.123827f,0.992302f,-0.00201728f, +0.206505f,0.97706f,0.0520531f, +0.250594f,0.965023f,0.0770254f, +0.0246334f,0.99033f,0.136524f, +-0.123437f,0.964871f,0.231923f, +0.10276f,0.956911f,0.271591f, +0.090829f,0.970486f,0.223397f, +0.00393218f,0.964068f,0.265627f, +0.045739f,0.962581f,0.267105f, +0.0438394f,0.968724f,0.244235f, +-0.1348f,0.971521f,0.194876f, +-0.247965f,0.950768f,0.185883f, +-0.385563f,0.920067f,0.0694089f, +-0.33646f,0.941527f,0.0179056f, +-0.284408f,0.957673f,0.0444463f, +-0.0809611f,0.98246f,0.167982f, +-0.272195f,0.961849f,0.0275091f, +-0.538305f,0.840251f,-0.0648443f, +-0.138085f,0.947265f,-0.289173f, +-0.112292f,0.943405f,-0.312055f, +-0.0366032f,0.968339f,-0.246942f, +-0.0207584f,0.978499f,-0.205204f, +-0.0114432f,0.978269f,-0.207024f, +-0.017206f,0.978017f,-0.207814f, +-0.00196221f,0.968739f,-0.248075f, +0.111459f,0.982805f,-0.147209f, +0.0917515f,0.980196f,-0.175495f, +0.0783409f,0.987595f,-0.136083f, +-0.0849004f,0.981698f,-0.170473f, +-0.0826208f,0.969176f,-0.232103f, +-0.0513296f,0.962825f,-0.265205f, +-0.0169212f,0.988046f,-0.153227f, +0.0442536f,0.99886f,0.017891f, +0.0803284f,0.974024f,0.211719f, +-0.118041f,0.942704f,0.312052f, +-0.187621f,0.893485f,0.408023f, +-0.0735772f,0.857937f,0.508459f, +-0.0838693f,0.837024f,0.5407f, +-0.00356882f,0.863268f,0.504733f, +0.117551f,0.889838f,0.440874f, +0.141271f,0.893306f,0.426669f, +0.0270129f,0.906148f,0.422097f, +-0.109486f,0.851548f,0.512717f, +-0.266831f,0.814637f,0.514944f, +-0.253628f,0.788787f,0.559899f, +-0.216685f,0.776961f,0.591083f, +-0.15137f,0.760068f,0.631968f, +-0.119157f,0.801398f,0.586143f, +0.0626697f,0.817134f,0.573031f, +0.150716f,0.886392f,0.437714f, +0.0719955f,0.965525f,0.250157f, +0.170594f,0.93758f,0.303054f, +0.205981f,0.906978f,0.367374f, +0.159242f,0.93166f,0.326575f, +0.163686f,0.939188f,0.301881f, +0.00255834f,0.983457f,0.181126f, +-0.0246414f,0.997684f,0.063397f, +0.103068f,0.994148f,0.0323463f, +0.175261f,0.977189f,0.119941f, +0.238397f,0.946614f,0.216998f, +0.376211f,0.893689f,0.244508f, +0.336321f,0.93903f,0.0714918f, +0.22632f,0.974025f,-0.00733613f, +0.155366f,0.98668f,0.0481989f, +0.129371f,0.988467f,0.0787169f, +0.140766f,0.985457f,0.095182f, +0.181141f,0.974304f,0.133867f, +-0.0259321f,0.983166f,0.180868f, +-0.16382f,0.974748f,0.151756f, +0.12842f,0.977623f,0.166619f, +0.102805f,0.986615f,0.12658f, +-0.0352231f,0.991461f,0.125559f, +0.0344472f,0.990276f,0.134782f, +0.100258f,0.97877f,0.178768f, +-0.0763414f,0.992566f,0.0947915f, +-0.24142f,0.968616f,0.059149f, +-0.325267f,0.943242f,0.06705f, +-0.302069f,0.9528f,0.0304413f, +-0.317187f,0.948361f,-0.0017587f, +-0.219267f,0.973832f,0.059775f, +-0.187608f,0.954493f,0.231832f, +-0.46452f,0.867868f,0.176143f, +-0.203418f,0.948131f,-0.244273f, +-0.139664f,0.973265f,-0.182342f, +-0.0536959f,0.988785f,-0.139361f, +-0.00355604f,0.986781f,-0.162022f, +-0.0572809f,0.980561f,-0.187669f, +-0.0374007f,0.985205f,-0.167247f, +0.0555765f,0.976159f,-0.209822f, +0.0908927f,0.962348f,-0.256173f, +0.0600715f,0.972748f,-0.223946f, +0.0442581f,0.987652f,-0.150282f, +-0.0260568f,0.986636f,-0.160841f, +-0.0937884f,0.986183f,-0.136552f, +-0.00585357f,0.999959f,-0.00691373f, +-0.168872f,0.982349f,-0.0804476f, +-0.215485f,0.975309f,0.0483622f, +-0.0961691f,0.964354f,0.246521f, +-0.114487f,0.922048f,0.369757f, +-0.269656f,0.899414f,0.344007f, +-0.21772f,0.897789f,0.382849f, +-0.126818f,0.886934f,0.444145f, +0.0624514f,0.872607f,0.484415f, +0.170504f,0.863439f,0.474764f, +0.127681f,0.882519f,0.452612f, +0.0249418f,0.887332f,0.460457f, +-0.228952f,0.87943f,0.417354f, +-0.336679f,0.801754f,0.493799f, +-0.354676f,0.742594f,0.568119f, +-0.265358f,0.728648f,0.631393f, +-0.0874663f,0.774696f,0.626255f, +0.0313715f,0.816845f,0.576004f, +0.138491f,0.877406f,0.459325f, +0.251487f,0.873743f,0.416325f, +0.149012f,0.891076f,0.428695f, +0.134082f,0.895567f,0.424244f, +0.259356f,0.879751f,0.398462f, +0.273738f,0.923515f,0.268677f, +0.242075f,0.954352f,0.174962f, +0.166067f,0.977105f,0.132992f, +0.0519593f,0.998404f,0.022142f, +0.0706628f,0.997395f,0.0145074f, +0.0910476f,0.994722f,0.0473141f, +0.126598f,0.990827f,0.0472679f, +0.33108f,0.937289f,0.108974f, +0.427456f,0.888646f,0.166103f, +0.265492f,0.95292f,0.14648f, +0.0868945f,0.990384f,0.10765f, +0.0739344f,0.98242f,0.171417f, +0.14882f,0.964095f,0.219937f, +0.160065f,0.969614f,0.185009f, +0.0379065f,0.980794f,0.191328f, +-0.111879f,0.992654f,0.0460448f, +0.101571f,0.994616f,0.0205655f, +0.134276f,0.987226f,0.0857599f, +0.00322228f,0.996946f,0.0780295f, +-0.00585508f,0.99961f,0.0273218f, +0.102527f,0.992913f,0.0601057f, +-0.0243337f,0.999696f,0.00385478f, +-0.236106f,0.971591f,0.0163038f, +-0.335881f,0.941896f,0.00400261f, +-0.319925f,0.947097f,0.0255887f, +-0.262465f,0.960477f,0.0927118f, +-0.320184f,0.947305f,-0.00973767f, +-0.358146f,0.929034f,0.0928862f, +-0.431591f,0.882961f,0.184686f, +-0.350194f,0.913588f,-0.20669f, +-0.241714f,0.958821f,-0.149118f, +-0.0874799f,0.991928f,-0.0917931f, +-0.00637736f,0.998289f,-0.0581162f, +0.0261719f,0.997729f,-0.0620574f, +0.00430678f,0.979141f,-0.203135f, +0.121705f,0.971178f,-0.20494f, +0.10219f,0.965909f,-0.237861f, +0.00407698f,0.957171f,-0.289495f, +-0.0386862f,0.968014f,-0.247897f, +-0.0509849f,0.995926f,-0.0743816f, +-0.228245f,0.973592f,-0.00474817f, +-0.140696f,0.979081f,0.146984f, +-0.104046f,0.966867f,0.233113f, +-0.254332f,0.94315f,0.213969f, +-0.211685f,0.953746f,0.213442f, +-0.245201f,0.93619f,0.251844f, +-0.247199f,0.912647f,0.325527f, +-0.213426f,0.932543f,0.291228f, +-0.170741f,0.942588f,0.28701f, +-0.0363946f,0.943193f,0.330245f, +0.169433f,0.88607f,0.431478f, +0.12169f,0.89261f,0.434096f, +0.0508642f,0.869951f,0.490509f, +-0.175065f,0.875657f,0.450086f, +-0.464211f,0.815419f,0.345833f, +-0.467728f,0.796275f,0.383635f, +-0.295863f,0.865688f,0.403795f, +-0.0706376f,0.91172f,0.404693f, +0.151265f,0.880258f,0.449738f, +0.239887f,0.896678f,0.372052f, +0.270966f,0.902061f,0.335952f, +0.133682f,0.938928f,0.317085f, +0.132181f,0.949509f,0.284538f, +0.337234f,0.911457f,0.235624f, +0.391568f,0.908725f,0.144547f, +0.297707f,0.949115f,0.10272f, +0.163642f,0.985787f,0.038011f, +0.0603665f,0.994817f,0.0818182f, +0.0342529f,0.984393f,0.172617f, +0.146f,0.969394f,0.197379f, +0.189586f,0.979398f,0.0695505f, +0.32179f,0.946595f,0.0202369f, +0.339913f,0.938655f,0.0581868f, +0.255631f,0.940824f,0.222493f, +0.130905f,0.959362f,0.249975f, +0.0245005f,0.97884f,0.203155f, +0.116898f,0.96642f,0.228839f, +0.217161f,0.952887f,0.211771f, +0.0905814f,0.991503f,0.0933592f, +0.00963547f,0.999795f,0.0178162f, +0.0707892f,0.997359f,-0.0162393f, +0.0454623f,0.996335f,0.0724521f, +0.025845f,0.99119f,0.129903f, +0.0553395f,0.998031f,0.0295398f, +0.0632528f,0.997901f,0.0138837f, +-0.000723073f,0.987186f,0.159572f, +-0.246121f,0.956173f,0.158611f, +-0.292993f,0.948379f,0.121377f, +-0.358856f,0.933219f,0.0180357f, +-0.312153f,0.948631f,0.0515794f, +-0.263061f,0.955548f,0.133141f, +-0.387996f,0.907685f,0.159898f, +-0.516559f,0.845117f,0.137638f, +-0.310178f,0.948377f,-0.0661154f, +-0.300026f,0.949757f,-0.0891454f, +-0.137668f,0.990363f,0.0151269f, +-0.0326899f,0.997118f,0.0684562f, +0.0835016f,0.994462f,0.0638203f, +0.0992766f,0.995028f,0.00796582f, +0.068628f,0.997514f,-0.0159775f, +0.181484f,0.983266f,0.0158879f, +0.0929905f,0.991619f,-0.0896955f, +-0.159863f,0.9831f,-0.0892104f, +-0.274969f,0.956779f,0.094689f, +-0.2578f,0.933703f,0.248472f, +-0.255563f,0.934109f,0.249254f, +-0.183445f,0.905456f,0.382751f, +-0.258353f,0.860148f,0.439771f, +-0.12588f,0.873686f,0.469923f, +-0.210169f,0.916013f,0.341684f, +-0.272883f,0.91339f,0.302083f, +-0.180317f,0.937251f,0.298406f, +-0.199625f,0.942232f,0.268977f, +-0.0859427f,0.9396f,0.33131f, +0.0831524f,0.928739f,0.361288f, +0.0997333f,0.904186f,0.415333f, +-0.0517762f,0.893569f,0.445931f, +-0.109718f,0.87826f,0.465426f, +-0.369685f,0.848108f,0.379534f, +-0.446603f,0.811841f,0.376112f, +-0.267849f,0.883969f,0.383218f, +-0.10672f,0.930725f,0.349801f, +0.10205f,0.92892f,0.355941f, +0.253281f,0.903219f,0.346475f, +0.270898f,0.880967f,0.387957f, +0.236849f,0.896348f,0.374784f, +0.206634f,0.946539f,0.247723f, +0.405577f,0.89206f,0.199342f, +0.379351f,0.915673f,0.1328f, +0.334598f,0.922412f,0.192872f, +0.211991f,0.969195f,0.125385f, +-0.0201216f,0.993487f,0.112152f, +-0.0648495f,0.986484f,0.150479f, +0.170924f,0.975936f,0.135405f, +0.29249f,0.9553f,0.0430209f, +0.300918f,0.953641f,0.00421578f, +0.280252f,0.954656f,0.100457f, +0.110799f,0.982326f,0.150862f, +0.111953f,0.970209f,0.214852f, +0.0917898f,0.974074f,0.206772f, +0.0706157f,0.981239f,0.179398f, +0.263217f,0.920389f,0.289137f, +0.266708f,0.942871f,0.199653f, +0.0169344f,0.99983f,0.00724636f, +0.0586405f,0.99674f,0.0554216f, +-0.0335948f,0.99924f,0.0197934f, +0.0130139f,0.996641f,0.0808552f, +0.158081f,0.974057f,0.161934f, +-0.0718701f,0.984912f,0.157428f, +-0.146615f,0.930223f,0.336437f, +-0.215441f,0.915614f,0.339465f, +-0.194576f,0.929319f,0.313857f, +-0.21244f,0.956751f,0.198736f, +-0.353032f,0.933914f,0.0563254f, +-0.387138f,0.913346f,0.126188f, +-0.421226f,0.884098f,0.202334f, +-0.478159f,0.863227f,0.161871f, +-0.144962f,0.987796f,0.0569687f, +-0.329752f,0.937067f,-0.114758f, +-0.228627f,0.973393f,0.0153452f, +-0.0297707f,0.988896f,0.1456f, +0.0737235f,0.992418f,0.0983429f, +0.119683f,0.983634f,0.134687f, +0.0735029f,0.988539f,0.131863f, +0.205816f,0.971725f,0.115713f, +0.105316f,0.994111f,0.0255379f, +-0.224655f,0.970814f,0.0839657f, +-0.371877f,0.9075f,0.195325f, +-0.304303f,0.906448f,0.292833f, +-0.280483f,0.900657f,0.331883f, +-0.306628f,0.862929f,0.401664f, +-0.272078f,0.807801f,0.522907f, +-0.0728986f,0.827771f,0.55631f, +-0.0766844f,0.868115f,0.490404f, +-0.262952f,0.903979f,0.337163f, +-0.116268f,0.92805f,0.353844f, +-0.236581f,0.941122f,0.241494f, +-0.103825f,0.933685f,0.342713f, +0.0620174f,0.936003f,0.346485f, +0.0525461f,0.928042f,0.368751f, +-0.037371f,0.900626f,0.432986f, +-0.0859425f,0.920181f,0.381944f, +-0.402084f,0.867474f,0.292945f, +-0.458834f,0.792013f,0.402725f, +-0.247545f,0.839465f,0.483756f, +-0.0206347f,0.857039f,0.514838f, +0.131938f,0.906082f,0.402004f, +0.260907f,0.906936f,0.330749f, +0.222736f,0.912076f,0.344246f, +0.286017f,0.867948f,0.406029f, +0.265664f,0.918021f,0.29438f, +0.386646f,0.888781f,0.246116f, +0.416594f,0.869611f,0.265003f, +0.291338f,0.924889f,0.244341f, +0.264598f,0.920497f,0.287528f, +-0.0209737f,0.965015f,0.261353f, +0.011928f,0.966786f,0.255307f, +0.209759f,0.975171f,0.0710066f, +0.379568f,0.924828f,0.0249204f, +0.227757f,0.968062f,-0.104795f, +0.230276f,0.968937f,0.0901831f, +0.121279f,0.97806f,0.169381f, +0.101139f,0.989453f,0.103701f, +0.125341f,0.986876f,0.101809f, +0.00931107f,0.998148f,0.0601183f, +0.147262f,0.96746f,0.205755f, +0.372526f,0.861294f,0.34554f, +0.0770606f,0.989688f,0.120749f, +0.0673416f,0.990666f,0.11852f, +0.0242126f,0.998823f,0.0420167f, +-0.0975945f,0.993903f,-0.0513095f, +0.0117629f,0.986762f,0.16175f, +-0.119035f,0.908985f,0.399472f, +-0.171696f,0.877378f,0.448027f, +-0.168225f,0.894295f,0.414653f, +-0.158105f,0.915758f,0.369311f, +-0.0984338f,0.938718f,0.330333f, +-0.319812f,0.930617f,0.177966f, +-0.398204f,0.897351f,0.190248f, +-0.414882f,0.896338f,0.156369f, +-0.434877f,0.894265f,0.105701f, +}; + +btScalar Landscape07Tex[] = { +0.507813f,0.742188f, +0.507813f,0.734375f, +0.515625f,0.742188f, +0.515625f,0.734375f, +0.523438f,0.742188f, +0.523438f,0.734375f, +0.53125f,0.742188f, +0.53125f,0.734375f, +0.539063f,0.742188f, +0.539063f,0.734375f, +0.546875f,0.742188f, +0.546875f,0.734375f, +0.554688f,0.742188f, +0.554688f,0.734375f, +0.5625f,0.742188f, +0.5625f,0.734375f, +0.570313f,0.742188f, +0.570313f,0.734375f, +0.578125f,0.742188f, +0.578125f,0.734375f, +0.585938f,0.742188f, +0.585938f,0.734375f, +0.59375f,0.742188f, +0.59375f,0.734375f, +0.601563f,0.742188f, +0.601563f,0.734375f, +0.609375f,0.742188f, +0.609375f,0.734375f, +0.617188f,0.742188f, +0.617188f,0.734375f, +0.625f,0.742188f, +0.625f,0.734375f, +0.632813f,0.742188f, +0.632813f,0.734375f, +0.640625f,0.742188f, +0.640625f,0.734375f, +0.648438f,0.742188f, +0.648438f,0.734375f, +0.65625f,0.742188f, +0.65625f,0.734375f, +0.664063f,0.742188f, +0.664063f,0.734375f, +0.671875f,0.742188f, +0.671875f,0.734375f, +0.679688f,0.742188f, +0.679688f,0.734375f, +0.6875f,0.742188f, +0.6875f,0.734375f, +0.695313f,0.742188f, +0.695313f,0.734375f, +0.703125f,0.742188f, +0.703125f,0.734375f, +0.710938f,0.742188f, +0.710938f,0.734375f, +0.71875f,0.742188f, +0.71875f,0.734375f, +0.726563f,0.742188f, +0.726563f,0.734375f, +0.734375f,0.742188f, +0.734375f,0.734375f, +0.742188f,0.742188f, +0.742188f,0.734375f, +0.75f,0.742188f, +0.75f,0.734375f, +0.757813f,0.742188f, +0.757813f,0.734375f, +0.765625f,0.742188f, +0.765625f,0.734375f, +0.773438f,0.742188f, +0.773438f,0.734375f, +0.78125f,0.742188f, +0.78125f,0.734375f, +0.789063f,0.742188f, +0.789063f,0.734375f, +0.796875f,0.742188f, +0.796875f,0.734375f, +0.804688f,0.742188f, +0.804688f,0.734375f, +0.8125f,0.742188f, +0.8125f,0.734375f, +0.820313f,0.742188f, +0.820313f,0.734375f, +0.828125f,0.742188f, +0.828125f,0.734375f, +0.835938f,0.742188f, +0.835938f,0.734375f, +0.84375f,0.742188f, +0.84375f,0.734375f, +0.851563f,0.742188f, +0.851563f,0.734375f, +0.859375f,0.742188f, +0.859375f,0.734375f, +0.867188f,0.742188f, +0.867188f,0.734375f, +0.875f,0.742188f, +0.875f,0.734375f, +0.882813f,0.742188f, +0.882813f,0.734375f, +0.890625f,0.742188f, +0.890625f,0.734375f, +0.898438f,0.742188f, +0.898438f,0.734375f, +0.90625f,0.742188f, +0.90625f,0.734375f, +0.914063f,0.742188f, +0.914063f,0.734375f, +0.921875f,0.742188f, +0.921875f,0.734375f, +0.929688f,0.742188f, +0.929688f,0.734375f, +0.9375f,0.742188f, +0.9375f,0.734375f, +0.945313f,0.742188f, +0.945313f,0.734375f, +0.953125f,0.742188f, +0.953125f,0.734375f, +0.960938f,0.742188f, +0.960938f,0.734375f, +0.96875f,0.742188f, +0.96875f,0.734375f, +0.976563f,0.742188f, +0.976563f,0.734375f, +0.984375f,0.742188f, +0.984375f,0.734375f, +0.992188f,0.742188f, +0.992188f,0.734375f, +1.0f,0.742188f, +1.0f,0.734375f, +0.507813f,0.75f, +0.515625f,0.75f, +0.523438f,0.75f, +0.53125f,0.75f, +0.539063f,0.75f, +0.546875f,0.75f, +0.554688f,0.75f, +0.5625f,0.75f, +0.570313f,0.75f, +0.578125f,0.75f, +0.585938f,0.75f, +0.59375f,0.75f, +0.601563f,0.75f, +0.609375f,0.75f, +0.617188f,0.75f, +0.625f,0.75f, +0.632813f,0.75f, +0.640625f,0.75f, +0.648438f,0.75f, +0.65625f,0.75f, +0.664063f,0.75f, +0.671875f,0.75f, +0.679688f,0.75f, +0.6875f,0.75f, +0.695313f,0.75f, +0.703125f,0.75f, +0.710938f,0.75f, +0.71875f,0.75f, +0.726563f,0.75f, +0.734375f,0.75f, +0.742188f,0.75f, +0.75f,0.75f, +0.757813f,0.75f, +0.765625f,0.75f, +0.773438f,0.75f, +0.78125f,0.75f, +0.789063f,0.75f, +0.796875f,0.75f, +0.804688f,0.75f, +0.8125f,0.75f, +0.820313f,0.75f, +0.828125f,0.75f, +0.835938f,0.75f, +0.84375f,0.75f, +0.851563f,0.75f, +0.859375f,0.75f, +0.867188f,0.75f, +0.875f,0.75f, +0.882813f,0.75f, +0.890625f,0.75f, +0.898438f,0.75f, +0.90625f,0.75f, +0.914063f,0.75f, +0.921875f,0.75f, +0.929688f,0.75f, +0.9375f,0.75f, +0.945313f,0.75f, +0.953125f,0.75f, +0.960938f,0.75f, +0.96875f,0.75f, +0.976563f,0.75f, +0.984375f,0.75f, +0.992188f,0.75f, +1.0f,0.75f, +0.507813f,0.757813f, +0.515625f,0.757813f, +0.523438f,0.757813f, +0.53125f,0.757813f, +0.539063f,0.757813f, +0.546875f,0.757813f, +0.554688f,0.757813f, +0.5625f,0.757813f, +0.570313f,0.757813f, +0.578125f,0.757813f, +0.585938f,0.757813f, +0.59375f,0.757813f, +0.601563f,0.757813f, +0.609375f,0.757813f, +0.617188f,0.757813f, +0.625f,0.757813f, +0.632813f,0.757813f, +0.640625f,0.757813f, +0.648438f,0.757813f, +0.65625f,0.757813f, +0.664063f,0.757813f, +0.671875f,0.757813f, +0.679688f,0.757813f, +0.6875f,0.757813f, +0.695313f,0.757813f, +0.703125f,0.757813f, +0.710938f,0.757813f, +0.71875f,0.757813f, +0.726563f,0.757813f, +0.734375f,0.757813f, +0.742188f,0.757813f, +0.75f,0.757813f, +0.757813f,0.757813f, +0.765625f,0.757813f, +0.773438f,0.757813f, +0.78125f,0.757813f, +0.789063f,0.757813f, +0.796875f,0.757813f, +0.804688f,0.757813f, +0.8125f,0.757813f, +0.820313f,0.757813f, +0.828125f,0.757813f, +0.835938f,0.757813f, +0.84375f,0.757813f, +0.851563f,0.757813f, +0.859375f,0.757813f, +0.867188f,0.757813f, +0.875f,0.757813f, +0.882813f,0.757813f, +0.890625f,0.757813f, +0.898438f,0.757813f, +0.90625f,0.757813f, +0.914063f,0.757813f, +0.921875f,0.757813f, +0.929688f,0.757813f, +0.9375f,0.757813f, +0.945313f,0.757813f, +0.953125f,0.757813f, +0.960938f,0.757813f, +0.96875f,0.757813f, +0.976563f,0.757813f, +0.984375f,0.757813f, +0.992188f,0.757813f, +1.0f,0.757813f, +0.507813f,0.765625f, +0.515625f,0.765625f, +0.523438f,0.765625f, +0.53125f,0.765625f, +0.539063f,0.765625f, +0.546875f,0.765625f, +0.554688f,0.765625f, +0.5625f,0.765625f, +0.570313f,0.765625f, +0.578125f,0.765625f, +0.585938f,0.765625f, +0.59375f,0.765625f, +0.601563f,0.765625f, +0.609375f,0.765625f, +0.617188f,0.765625f, +0.625f,0.765625f, +0.632813f,0.765625f, +0.640625f,0.765625f, +0.648438f,0.765625f, +0.65625f,0.765625f, +0.664063f,0.765625f, +0.671875f,0.765625f, +0.679688f,0.765625f, +0.6875f,0.765625f, +0.695313f,0.765625f, +0.703125f,0.765625f, +0.710938f,0.765625f, +0.71875f,0.765625f, +0.726563f,0.765625f, +0.734375f,0.765625f, +0.742188f,0.765625f, +0.75f,0.765625f, +0.757813f,0.765625f, +0.765625f,0.765625f, +0.773438f,0.765625f, +0.78125f,0.765625f, +0.789063f,0.765625f, +0.796875f,0.765625f, +0.804688f,0.765625f, +0.8125f,0.765625f, +0.820313f,0.765625f, +0.828125f,0.765625f, +0.835938f,0.765625f, +0.84375f,0.765625f, +0.851563f,0.765625f, +0.859375f,0.765625f, +0.867188f,0.765625f, +0.875f,0.765625f, +0.882813f,0.765625f, +0.890625f,0.765625f, +0.898438f,0.765625f, +0.90625f,0.765625f, +0.914063f,0.765625f, +0.921875f,0.765625f, +0.929688f,0.765625f, +0.9375f,0.765625f, +0.945313f,0.765625f, +0.953125f,0.765625f, +0.960938f,0.765625f, +0.96875f,0.765625f, +0.976563f,0.765625f, +0.984375f,0.765625f, +0.992188f,0.765625f, +1.0f,0.765625f, +0.507813f,0.773438f, +0.515625f,0.773438f, +0.523438f,0.773438f, +0.53125f,0.773438f, +0.539063f,0.773438f, +0.546875f,0.773438f, +0.554688f,0.773438f, +0.5625f,0.773438f, +0.570313f,0.773438f, +0.578125f,0.773438f, +0.585938f,0.773438f, +0.59375f,0.773438f, +0.601563f,0.773438f, +0.609375f,0.773438f, +0.617188f,0.773438f, +0.625f,0.773438f, +0.632813f,0.773438f, +0.640625f,0.773438f, +0.648438f,0.773438f, +0.65625f,0.773438f, +0.664063f,0.773438f, +0.671875f,0.773438f, +0.679688f,0.773438f, +0.6875f,0.773438f, +0.695313f,0.773438f, +0.703125f,0.773438f, +0.710938f,0.773438f, +0.71875f,0.773438f, +0.726563f,0.773438f, +0.734375f,0.773438f, +0.742188f,0.773438f, +0.75f,0.773438f, +0.757813f,0.773438f, +0.765625f,0.773438f, +0.773438f,0.773438f, +0.78125f,0.773438f, +0.789063f,0.773438f, +0.796875f,0.773438f, +0.804688f,0.773438f, +0.8125f,0.773438f, +0.820313f,0.773438f, +0.828125f,0.773438f, +0.835938f,0.773438f, +0.84375f,0.773438f, +0.851563f,0.773438f, +0.859375f,0.773438f, +0.867188f,0.773438f, +0.875f,0.773438f, +0.882813f,0.773438f, +0.890625f,0.773438f, +0.898438f,0.773438f, +0.90625f,0.773438f, +0.914063f,0.773438f, +0.921875f,0.773438f, +0.929688f,0.773438f, +0.9375f,0.773438f, +0.945313f,0.773438f, +0.953125f,0.773438f, +0.960938f,0.773438f, +0.96875f,0.773438f, +0.976563f,0.773438f, +0.984375f,0.773438f, +0.992188f,0.773438f, +1.0f,0.773438f, +0.507813f,0.78125f, +0.515625f,0.78125f, +0.523438f,0.78125f, +0.53125f,0.78125f, +0.539063f,0.78125f, +0.546875f,0.78125f, +0.554688f,0.78125f, +0.5625f,0.78125f, +0.570313f,0.78125f, +0.578125f,0.78125f, +0.585938f,0.78125f, +0.59375f,0.78125f, +0.601563f,0.78125f, +0.609375f,0.78125f, +0.617188f,0.78125f, +0.625f,0.78125f, +0.632813f,0.78125f, +0.640625f,0.78125f, +0.648438f,0.78125f, +0.65625f,0.78125f, +0.664063f,0.78125f, +0.671875f,0.78125f, +0.679688f,0.78125f, +0.6875f,0.78125f, +0.695313f,0.78125f, +0.703125f,0.78125f, +0.710938f,0.78125f, +0.71875f,0.78125f, +0.726563f,0.78125f, +0.734375f,0.78125f, +0.742188f,0.78125f, +0.75f,0.78125f, +0.757813f,0.78125f, +0.765625f,0.78125f, +0.773438f,0.78125f, +0.78125f,0.78125f, +0.789063f,0.78125f, +0.796875f,0.78125f, +0.804688f,0.78125f, +0.8125f,0.78125f, +0.820313f,0.78125f, +0.828125f,0.78125f, +0.835938f,0.78125f, +0.84375f,0.78125f, +0.851563f,0.78125f, +0.859375f,0.78125f, +0.867188f,0.78125f, +0.875f,0.78125f, +0.882813f,0.78125f, +0.890625f,0.78125f, +0.898438f,0.78125f, +0.90625f,0.78125f, +0.914063f,0.78125f, +0.921875f,0.78125f, +0.929688f,0.78125f, +0.9375f,0.78125f, +0.945313f,0.78125f, +0.953125f,0.78125f, +0.960938f,0.78125f, +0.96875f,0.78125f, +0.976563f,0.78125f, +0.984375f,0.78125f, +0.992188f,0.78125f, +1.0f,0.78125f, +0.507813f,0.789063f, +0.515625f,0.789063f, +0.523438f,0.789063f, +0.53125f,0.789063f, +0.539063f,0.789063f, +0.546875f,0.789063f, +0.554688f,0.789063f, +0.5625f,0.789063f, +0.570313f,0.789063f, +0.578125f,0.789063f, +0.585938f,0.789063f, +0.59375f,0.789063f, +0.601563f,0.789063f, +0.609375f,0.789063f, +0.617188f,0.789063f, +0.625f,0.789063f, +0.632813f,0.789063f, +0.640625f,0.789063f, +0.648438f,0.789063f, +0.65625f,0.789063f, +0.664063f,0.789063f, +0.671875f,0.789063f, +0.679688f,0.789063f, +0.6875f,0.789063f, +0.695313f,0.789063f, +0.703125f,0.789063f, +0.710938f,0.789063f, +0.71875f,0.789063f, +0.726563f,0.789063f, +0.734375f,0.789063f, +0.742188f,0.789063f, +0.75f,0.789063f, +0.757813f,0.789063f, +0.765625f,0.789063f, +0.773438f,0.789063f, +0.78125f,0.789063f, +0.789063f,0.789063f, +0.796875f,0.789063f, +0.804688f,0.789063f, +0.8125f,0.789063f, +0.820313f,0.789063f, +0.828125f,0.789063f, +0.835938f,0.789063f, +0.84375f,0.789063f, +0.851563f,0.789063f, +0.859375f,0.789063f, +0.867188f,0.789063f, +0.875f,0.789063f, +0.882813f,0.789063f, +0.890625f,0.789063f, +0.898438f,0.789063f, +0.90625f,0.789063f, +0.914063f,0.789063f, +0.921875f,0.789063f, +0.929688f,0.789063f, +0.9375f,0.789063f, +0.945313f,0.789063f, +0.953125f,0.789063f, +0.960938f,0.789063f, +0.96875f,0.789063f, +0.976563f,0.789063f, +0.984375f,0.789063f, +0.992188f,0.789063f, +1.0f,0.789063f, +0.507813f,0.796875f, +0.515625f,0.796875f, +0.523438f,0.796875f, +0.53125f,0.796875f, +0.539063f,0.796875f, +0.546875f,0.796875f, +0.554688f,0.796875f, +0.5625f,0.796875f, +0.570313f,0.796875f, +0.578125f,0.796875f, +0.585938f,0.796875f, +0.59375f,0.796875f, +0.601563f,0.796875f, +0.609375f,0.796875f, +0.617188f,0.796875f, +0.625f,0.796875f, +0.632813f,0.796875f, +0.640625f,0.796875f, +0.648438f,0.796875f, +0.65625f,0.796875f, +0.664063f,0.796875f, +0.671875f,0.796875f, +0.679688f,0.796875f, +0.6875f,0.796875f, +0.695313f,0.796875f, +0.703125f,0.796875f, +0.710938f,0.796875f, +0.71875f,0.796875f, +0.726563f,0.796875f, +0.734375f,0.796875f, +0.742188f,0.796875f, +0.75f,0.796875f, +0.757813f,0.796875f, +0.765625f,0.796875f, +0.773438f,0.796875f, +0.78125f,0.796875f, +0.789063f,0.796875f, +0.796875f,0.796875f, +0.804688f,0.796875f, +0.8125f,0.796875f, +0.820313f,0.796875f, +0.828125f,0.796875f, +0.835938f,0.796875f, +0.84375f,0.796875f, +0.851563f,0.796875f, +0.859375f,0.796875f, +0.867188f,0.796875f, +0.875f,0.796875f, +0.882813f,0.796875f, +0.890625f,0.796875f, +0.898438f,0.796875f, +0.90625f,0.796875f, +0.914063f,0.796875f, +0.921875f,0.796875f, +0.929688f,0.796875f, +0.9375f,0.796875f, +0.945313f,0.796875f, +0.953125f,0.796875f, +0.960938f,0.796875f, +0.96875f,0.796875f, +0.976563f,0.796875f, +0.984375f,0.796875f, +0.992188f,0.796875f, +1.0f,0.796875f, +0.507813f,0.804688f, +0.515625f,0.804688f, +0.523438f,0.804688f, +0.53125f,0.804688f, +0.539063f,0.804688f, +0.546875f,0.804688f, +0.554688f,0.804688f, +0.5625f,0.804688f, +0.570313f,0.804688f, +0.578125f,0.804688f, +0.585938f,0.804688f, +0.59375f,0.804688f, +0.601563f,0.804688f, +0.609375f,0.804688f, +0.617188f,0.804688f, +0.625f,0.804688f, +0.632813f,0.804688f, +0.640625f,0.804688f, +0.648438f,0.804688f, +0.65625f,0.804688f, +0.664063f,0.804688f, +0.671875f,0.804688f, +0.679688f,0.804688f, +0.6875f,0.804688f, +0.695313f,0.804688f, +0.703125f,0.804688f, +0.710938f,0.804688f, +0.71875f,0.804688f, +0.726563f,0.804688f, +0.734375f,0.804688f, +0.742188f,0.804688f, +0.75f,0.804688f, +0.757813f,0.804688f, +0.765625f,0.804688f, +0.773438f,0.804688f, +0.78125f,0.804688f, +0.789063f,0.804688f, +0.796875f,0.804688f, +0.804688f,0.804688f, +0.8125f,0.804688f, +0.820313f,0.804688f, +0.828125f,0.804688f, +0.835938f,0.804688f, +0.84375f,0.804688f, +0.851563f,0.804688f, +0.859375f,0.804688f, +0.867188f,0.804688f, +0.875f,0.804688f, +0.882813f,0.804688f, +0.890625f,0.804688f, +0.898438f,0.804688f, +0.90625f,0.804688f, +0.914063f,0.804688f, +0.921875f,0.804688f, +0.929688f,0.804688f, +0.9375f,0.804688f, +0.945313f,0.804688f, +0.953125f,0.804688f, +0.960938f,0.804688f, +0.96875f,0.804688f, +0.976563f,0.804688f, +0.984375f,0.804688f, +0.992188f,0.804688f, +1.0f,0.804688f, +0.507813f,0.8125f, +0.515625f,0.8125f, +0.523438f,0.8125f, +0.53125f,0.8125f, +0.539063f,0.8125f, +0.546875f,0.8125f, +0.554688f,0.8125f, +0.5625f,0.8125f, +0.570313f,0.8125f, +0.578125f,0.8125f, +0.585938f,0.8125f, +0.59375f,0.8125f, +0.601563f,0.8125f, +0.609375f,0.8125f, +0.617188f,0.8125f, +0.625f,0.8125f, +0.632813f,0.8125f, +0.640625f,0.8125f, +0.648438f,0.8125f, +0.65625f,0.8125f, +0.664063f,0.8125f, +0.671875f,0.8125f, +0.679688f,0.8125f, +0.6875f,0.8125f, +0.695313f,0.8125f, +0.703125f,0.8125f, +0.710938f,0.8125f, +0.71875f,0.8125f, +0.726563f,0.8125f, +0.734375f,0.8125f, +0.742188f,0.8125f, +0.75f,0.8125f, +0.757813f,0.8125f, +0.765625f,0.8125f, +0.773438f,0.8125f, +0.78125f,0.8125f, +0.789063f,0.8125f, +0.796875f,0.8125f, +0.804688f,0.8125f, +0.8125f,0.8125f, +0.820313f,0.8125f, +0.828125f,0.8125f, +0.835938f,0.8125f, +0.84375f,0.8125f, +0.851563f,0.8125f, +0.859375f,0.8125f, +0.867188f,0.8125f, +0.875f,0.8125f, +0.882813f,0.8125f, +0.890625f,0.8125f, +0.898438f,0.8125f, +0.90625f,0.8125f, +0.914063f,0.8125f, +0.921875f,0.8125f, +0.929688f,0.8125f, +0.9375f,0.8125f, +0.945313f,0.8125f, +0.953125f,0.8125f, +0.960938f,0.8125f, +0.96875f,0.8125f, +0.976563f,0.8125f, +0.984375f,0.8125f, +0.992188f,0.8125f, +1.0f,0.8125f, +0.507813f,0.820313f, +0.515625f,0.820313f, +0.523438f,0.820313f, +0.53125f,0.820313f, +0.539063f,0.820313f, +0.546875f,0.820313f, +0.554688f,0.820313f, +0.5625f,0.820313f, +0.570313f,0.820313f, +0.578125f,0.820313f, +0.585938f,0.820313f, +0.59375f,0.820313f, +0.601563f,0.820313f, +0.609375f,0.820313f, +0.617188f,0.820313f, +0.625f,0.820313f, +0.632813f,0.820313f, +0.640625f,0.820313f, +0.648438f,0.820313f, +0.65625f,0.820313f, +0.664063f,0.820313f, +0.671875f,0.820313f, +0.679688f,0.820313f, +0.6875f,0.820313f, +0.695313f,0.820313f, +0.703125f,0.820313f, +0.710938f,0.820313f, +0.71875f,0.820313f, +0.726563f,0.820313f, +0.734375f,0.820313f, +0.742188f,0.820313f, +0.75f,0.820313f, +0.757813f,0.820313f, +0.765625f,0.820313f, +0.773438f,0.820313f, +0.78125f,0.820313f, +0.789063f,0.820313f, +0.796875f,0.820313f, +0.804688f,0.820313f, +0.8125f,0.820313f, +0.820313f,0.820313f, +0.828125f,0.820313f, +0.835938f,0.820313f, +0.84375f,0.820313f, +0.851563f,0.820313f, +0.859375f,0.820313f, +0.867188f,0.820313f, +0.875f,0.820313f, +0.882813f,0.820313f, +0.890625f,0.820313f, +0.898438f,0.820313f, +0.90625f,0.820313f, +0.914063f,0.820313f, +0.921875f,0.820313f, +0.929688f,0.820313f, +0.9375f,0.820313f, +0.945313f,0.820313f, +0.953125f,0.820313f, +0.960938f,0.820313f, +0.96875f,0.820313f, +0.976563f,0.820313f, +0.984375f,0.820313f, +0.992188f,0.820313f, +1.0f,0.820313f, +0.507813f,0.828125f, +0.515625f,0.828125f, +0.523438f,0.828125f, +0.53125f,0.828125f, +0.539063f,0.828125f, +0.546875f,0.828125f, +0.554688f,0.828125f, +0.5625f,0.828125f, +0.570313f,0.828125f, +0.578125f,0.828125f, +0.585938f,0.828125f, +0.59375f,0.828125f, +0.601563f,0.828125f, +0.609375f,0.828125f, +0.617188f,0.828125f, +0.625f,0.828125f, +0.632813f,0.828125f, +0.640625f,0.828125f, +0.648438f,0.828125f, +0.65625f,0.828125f, +0.664063f,0.828125f, +0.671875f,0.828125f, +0.679688f,0.828125f, +0.6875f,0.828125f, +0.695313f,0.828125f, +0.703125f,0.828125f, +0.710938f,0.828125f, +0.71875f,0.828125f, +0.726563f,0.828125f, +0.734375f,0.828125f, +0.742188f,0.828125f, +0.75f,0.828125f, +0.757813f,0.828125f, +0.765625f,0.828125f, +0.773438f,0.828125f, +0.78125f,0.828125f, +0.789063f,0.828125f, +0.796875f,0.828125f, +0.804688f,0.828125f, +0.8125f,0.828125f, +0.820313f,0.828125f, +0.828125f,0.828125f, +0.835938f,0.828125f, +0.84375f,0.828125f, +0.851563f,0.828125f, +0.859375f,0.828125f, +0.867188f,0.828125f, +0.875f,0.828125f, +0.882813f,0.828125f, +0.890625f,0.828125f, +0.898438f,0.828125f, +0.90625f,0.828125f, +0.914063f,0.828125f, +0.921875f,0.828125f, +0.929688f,0.828125f, +0.9375f,0.828125f, +0.945313f,0.828125f, +0.953125f,0.828125f, +0.960938f,0.828125f, +0.96875f,0.828125f, +0.976563f,0.828125f, +0.984375f,0.828125f, +0.992188f,0.828125f, +1.0f,0.828125f, +0.507813f,0.835938f, +0.515625f,0.835938f, +0.523438f,0.835938f, +0.53125f,0.835938f, +0.539063f,0.835938f, +0.546875f,0.835938f, +0.554688f,0.835938f, +0.5625f,0.835938f, +0.570313f,0.835938f, +0.578125f,0.835938f, +0.585938f,0.835938f, +0.59375f,0.835938f, +0.601563f,0.835938f, +0.609375f,0.835938f, +0.617188f,0.835938f, +0.625f,0.835938f, +0.632813f,0.835938f, +0.640625f,0.835938f, +0.648438f,0.835938f, +0.65625f,0.835938f, +0.664063f,0.835938f, +0.671875f,0.835938f, +0.679688f,0.835938f, +0.6875f,0.835938f, +0.695313f,0.835938f, +0.703125f,0.835938f, +0.710938f,0.835938f, +0.71875f,0.835938f, +0.726563f,0.835938f, +0.734375f,0.835938f, +0.742188f,0.835938f, +0.75f,0.835938f, +0.757813f,0.835938f, +0.765625f,0.835938f, +0.773438f,0.835938f, +0.78125f,0.835938f, +0.789063f,0.835938f, +0.796875f,0.835938f, +0.804688f,0.835938f, +0.8125f,0.835938f, +0.820313f,0.835938f, +0.828125f,0.835938f, +0.835938f,0.835938f, +0.84375f,0.835938f, +0.851563f,0.835938f, +0.859375f,0.835938f, +0.867188f,0.835938f, +0.875f,0.835938f, +0.882813f,0.835938f, +0.890625f,0.835938f, +0.898438f,0.835938f, +0.90625f,0.835938f, +0.914063f,0.835938f, +0.921875f,0.835938f, +0.929688f,0.835938f, +0.9375f,0.835938f, +0.945313f,0.835938f, +0.953125f,0.835938f, +0.960938f,0.835938f, +0.96875f,0.835938f, +0.976563f,0.835938f, +0.984375f,0.835938f, +0.992188f,0.835938f, +1.0f,0.835938f, +0.507813f,0.84375f, +0.515625f,0.84375f, +0.523438f,0.84375f, +0.53125f,0.84375f, +0.539063f,0.84375f, +0.546875f,0.84375f, +0.554688f,0.84375f, +0.5625f,0.84375f, +0.570313f,0.84375f, +0.578125f,0.84375f, +0.585938f,0.84375f, +0.59375f,0.84375f, +0.601563f,0.84375f, +0.609375f,0.84375f, +0.617188f,0.84375f, +0.625f,0.84375f, +0.632813f,0.84375f, +0.640625f,0.84375f, +0.648438f,0.84375f, +0.65625f,0.84375f, +0.664063f,0.84375f, +0.671875f,0.84375f, +0.679688f,0.84375f, +0.6875f,0.84375f, +0.695313f,0.84375f, +0.703125f,0.84375f, +0.710938f,0.84375f, +0.71875f,0.84375f, +0.726563f,0.84375f, +0.734375f,0.84375f, +0.742188f,0.84375f, +0.75f,0.84375f, +0.757813f,0.84375f, +0.765625f,0.84375f, +0.773438f,0.84375f, +0.78125f,0.84375f, +0.789063f,0.84375f, +0.796875f,0.84375f, +0.804688f,0.84375f, +0.8125f,0.84375f, +0.820313f,0.84375f, +0.828125f,0.84375f, +0.835938f,0.84375f, +0.84375f,0.84375f, +0.851563f,0.84375f, +0.859375f,0.84375f, +0.867188f,0.84375f, +0.875f,0.84375f, +0.882813f,0.84375f, +0.890625f,0.84375f, +0.898438f,0.84375f, +0.90625f,0.84375f, +0.914063f,0.84375f, +0.921875f,0.84375f, +0.929688f,0.84375f, +0.9375f,0.84375f, +0.945313f,0.84375f, +0.953125f,0.84375f, +0.960938f,0.84375f, +0.96875f,0.84375f, +0.976563f,0.84375f, +0.984375f,0.84375f, +0.992188f,0.84375f, +1.0f,0.84375f, +0.507813f,0.851563f, +0.515625f,0.851563f, +0.523438f,0.851563f, +0.53125f,0.851563f, +0.539063f,0.851563f, +0.546875f,0.851563f, +0.554688f,0.851563f, +0.5625f,0.851563f, +0.570313f,0.851563f, +0.578125f,0.851563f, +0.585938f,0.851563f, +0.59375f,0.851563f, +0.601563f,0.851563f, +0.609375f,0.851563f, +0.617188f,0.851563f, +0.625f,0.851563f, +0.632813f,0.851563f, +0.640625f,0.851563f, +0.648438f,0.851563f, +0.65625f,0.851563f, +0.664063f,0.851563f, +0.671875f,0.851563f, +0.679688f,0.851563f, +0.6875f,0.851563f, +0.695313f,0.851563f, +0.703125f,0.851563f, +0.710938f,0.851563f, +0.71875f,0.851563f, +0.726563f,0.851563f, +0.734375f,0.851563f, +0.742188f,0.851563f, +0.75f,0.851563f, +0.757813f,0.851563f, +0.765625f,0.851563f, +0.773438f,0.851563f, +0.78125f,0.851563f, +0.789063f,0.851563f, +0.796875f,0.851563f, +0.804688f,0.851563f, +0.8125f,0.851563f, +0.820313f,0.851563f, +0.828125f,0.851563f, +0.835938f,0.851563f, +0.84375f,0.851563f, +0.851563f,0.851563f, +0.859375f,0.851563f, +0.867188f,0.851563f, +0.875f,0.851563f, +0.882813f,0.851563f, +0.890625f,0.851563f, +0.898438f,0.851563f, +0.90625f,0.851563f, +0.914063f,0.851563f, +0.921875f,0.851563f, +0.929688f,0.851563f, +0.9375f,0.851563f, +0.945313f,0.851563f, +0.953125f,0.851563f, +0.960938f,0.851563f, +0.96875f,0.851563f, +0.976563f,0.851563f, +0.984375f,0.851563f, +0.992188f,0.851563f, +1.0f,0.851563f, +0.507813f,0.859375f, +0.515625f,0.859375f, +0.523438f,0.859375f, +0.53125f,0.859375f, +0.539063f,0.859375f, +0.546875f,0.859375f, +0.554688f,0.859375f, +0.5625f,0.859375f, +0.570313f,0.859375f, +0.578125f,0.859375f, +0.585938f,0.859375f, +0.59375f,0.859375f, +0.601563f,0.859375f, +0.609375f,0.859375f, +0.617188f,0.859375f, +0.625f,0.859375f, +0.632813f,0.859375f, +0.640625f,0.859375f, +0.648438f,0.859375f, +0.65625f,0.859375f, +0.664063f,0.859375f, +0.671875f,0.859375f, +0.679688f,0.859375f, +0.6875f,0.859375f, +0.695313f,0.859375f, +0.703125f,0.859375f, +0.710938f,0.859375f, +0.71875f,0.859375f, +0.726563f,0.859375f, +0.734375f,0.859375f, +0.742188f,0.859375f, +0.75f,0.859375f, +0.757813f,0.859375f, +0.765625f,0.859375f, +0.773438f,0.859375f, +0.78125f,0.859375f, +0.789063f,0.859375f, +0.796875f,0.859375f, +0.804688f,0.859375f, +0.8125f,0.859375f, +0.820313f,0.859375f, +0.828125f,0.859375f, +0.835938f,0.859375f, +0.84375f,0.859375f, +0.851563f,0.859375f, +0.859375f,0.859375f, +0.867188f,0.859375f, +0.875f,0.859375f, +0.882813f,0.859375f, +0.890625f,0.859375f, +0.898438f,0.859375f, +0.90625f,0.859375f, +0.914063f,0.859375f, +0.921875f,0.859375f, +0.929688f,0.859375f, +0.9375f,0.859375f, +0.945313f,0.859375f, +0.953125f,0.859375f, +0.960938f,0.859375f, +0.96875f,0.859375f, +0.976563f,0.859375f, +0.984375f,0.859375f, +0.992188f,0.859375f, +1.0f,0.859375f, +0.507813f,0.867188f, +0.515625f,0.867188f, +0.523438f,0.867188f, +0.53125f,0.867188f, +0.539063f,0.867188f, +0.546875f,0.867188f, +0.554688f,0.867188f, +0.5625f,0.867188f, +0.570313f,0.867188f, +0.578125f,0.867188f, +0.585938f,0.867188f, +0.59375f,0.867188f, +0.601563f,0.867188f, +0.609375f,0.867188f, +0.617188f,0.867188f, +0.625f,0.867188f, +0.632813f,0.867188f, +0.640625f,0.867188f, +0.648438f,0.867188f, +0.65625f,0.867188f, +0.664063f,0.867188f, +0.671875f,0.867188f, +0.679688f,0.867188f, +0.6875f,0.867188f, +0.695313f,0.867188f, +0.703125f,0.867188f, +0.710938f,0.867188f, +0.71875f,0.867188f, +0.726563f,0.867188f, +0.734375f,0.867188f, +0.742188f,0.867188f, +0.75f,0.867188f, +0.757813f,0.867188f, +0.765625f,0.867188f, +0.773438f,0.867188f, +0.78125f,0.867188f, +0.789063f,0.867188f, +0.796875f,0.867188f, +0.804688f,0.867188f, +0.8125f,0.867188f, +0.820313f,0.867188f, +0.828125f,0.867188f, +0.835938f,0.867188f, +0.84375f,0.867188f, +0.851563f,0.867188f, +0.859375f,0.867188f, +0.867188f,0.867188f, +0.875f,0.867188f, +0.882813f,0.867188f, +0.890625f,0.867188f, +0.898438f,0.867188f, +0.90625f,0.867188f, +0.914063f,0.867188f, +0.921875f,0.867188f, +0.929688f,0.867188f, +0.9375f,0.867188f, +0.945313f,0.867188f, +0.953125f,0.867188f, +0.960938f,0.867188f, +0.96875f,0.867188f, +0.976563f,0.867188f, +0.984375f,0.867188f, +0.992188f,0.867188f, +1.0f,0.867188f, +0.507813f,0.875f, +0.515625f,0.875f, +0.523438f,0.875f, +0.53125f,0.875f, +0.539063f,0.875f, +0.546875f,0.875f, +0.554688f,0.875f, +0.5625f,0.875f, +0.570313f,0.875f, +0.578125f,0.875f, +0.585938f,0.875f, +0.59375f,0.875f, +0.601563f,0.875f, +0.609375f,0.875f, +0.617188f,0.875f, +0.625f,0.875f, +0.632813f,0.875f, +0.640625f,0.875f, +0.648438f,0.875f, +0.65625f,0.875f, +0.664063f,0.875f, +0.671875f,0.875f, +0.679688f,0.875f, +0.6875f,0.875f, +0.695313f,0.875f, +0.703125f,0.875f, +0.710938f,0.875f, +0.71875f,0.875f, +0.726563f,0.875f, +0.734375f,0.875f, +0.742188f,0.875f, +0.75f,0.875f, +0.757813f,0.875f, +0.765625f,0.875f, +0.773438f,0.875f, +0.78125f,0.875f, +0.789063f,0.875f, +0.796875f,0.875f, +0.804688f,0.875f, +0.8125f,0.875f, +0.820313f,0.875f, +0.828125f,0.875f, +0.835938f,0.875f, +0.84375f,0.875f, +0.851563f,0.875f, +0.859375f,0.875f, +0.867188f,0.875f, +0.875f,0.875f, +0.882813f,0.875f, +0.890625f,0.875f, +0.898438f,0.875f, +0.90625f,0.875f, +0.914063f,0.875f, +0.921875f,0.875f, +0.929688f,0.875f, +0.9375f,0.875f, +0.945313f,0.875f, +0.953125f,0.875f, +0.960938f,0.875f, +0.96875f,0.875f, +0.976563f,0.875f, +0.984375f,0.875f, +0.992188f,0.875f, +1.0f,0.875f, +0.507813f,0.882813f, +0.515625f,0.882813f, +0.523438f,0.882813f, +0.53125f,0.882813f, +0.539063f,0.882813f, +0.546875f,0.882813f, +0.554688f,0.882813f, +0.5625f,0.882813f, +0.570313f,0.882813f, +0.578125f,0.882813f, +0.585938f,0.882813f, +0.59375f,0.882813f, +0.601563f,0.882813f, +0.609375f,0.882813f, +0.617188f,0.882813f, +0.625f,0.882813f, +0.632813f,0.882813f, +0.640625f,0.882813f, +0.648438f,0.882813f, +0.65625f,0.882813f, +0.664063f,0.882813f, +0.671875f,0.882813f, +0.679688f,0.882813f, +0.6875f,0.882813f, +0.695313f,0.882813f, +0.703125f,0.882813f, +0.710938f,0.882813f, +0.71875f,0.882813f, +0.726563f,0.882813f, +0.734375f,0.882813f, +0.742188f,0.882813f, +0.75f,0.882813f, +0.757813f,0.882813f, +0.765625f,0.882813f, +0.773438f,0.882813f, +0.78125f,0.882813f, +0.789063f,0.882813f, +0.796875f,0.882813f, +0.804688f,0.882813f, +0.8125f,0.882813f, +0.820313f,0.882813f, +0.828125f,0.882813f, +0.835938f,0.882813f, +0.84375f,0.882813f, +0.851563f,0.882813f, +0.859375f,0.882813f, +0.867188f,0.882813f, +0.875f,0.882813f, +0.882813f,0.882813f, +0.890625f,0.882813f, +0.898438f,0.882813f, +0.90625f,0.882813f, +0.914063f,0.882813f, +0.921875f,0.882813f, +0.929688f,0.882813f, +0.9375f,0.882813f, +0.945313f,0.882813f, +0.953125f,0.882813f, +0.960938f,0.882813f, +0.96875f,0.882813f, +0.976563f,0.882813f, +0.984375f,0.882813f, +0.992188f,0.882813f, +1.0f,0.882813f, +0.507813f,0.890625f, +0.515625f,0.890625f, +0.523438f,0.890625f, +0.53125f,0.890625f, +0.539063f,0.890625f, +0.546875f,0.890625f, +0.554688f,0.890625f, +0.5625f,0.890625f, +0.570313f,0.890625f, +0.578125f,0.890625f, +0.585938f,0.890625f, +0.59375f,0.890625f, +0.601563f,0.890625f, +0.609375f,0.890625f, +0.617188f,0.890625f, +0.625f,0.890625f, +0.632813f,0.890625f, +0.640625f,0.890625f, +0.648438f,0.890625f, +0.65625f,0.890625f, +0.664063f,0.890625f, +0.671875f,0.890625f, +0.679688f,0.890625f, +0.6875f,0.890625f, +0.695313f,0.890625f, +0.703125f,0.890625f, +0.710938f,0.890625f, +0.71875f,0.890625f, +0.726563f,0.890625f, +0.734375f,0.890625f, +0.742188f,0.890625f, +0.75f,0.890625f, +0.757813f,0.890625f, +0.765625f,0.890625f, +0.773438f,0.890625f, +0.78125f,0.890625f, +0.789063f,0.890625f, +0.796875f,0.890625f, +0.804688f,0.890625f, +0.8125f,0.890625f, +0.820313f,0.890625f, +0.828125f,0.890625f, +0.835938f,0.890625f, +0.84375f,0.890625f, +0.851563f,0.890625f, +0.859375f,0.890625f, +0.867188f,0.890625f, +0.875f,0.890625f, +0.882813f,0.890625f, +0.890625f,0.890625f, +0.898438f,0.890625f, +0.90625f,0.890625f, +0.914063f,0.890625f, +0.921875f,0.890625f, +0.929688f,0.890625f, +0.9375f,0.890625f, +0.945313f,0.890625f, +0.953125f,0.890625f, +0.960938f,0.890625f, +0.96875f,0.890625f, +0.976563f,0.890625f, +0.984375f,0.890625f, +0.992188f,0.890625f, +1.0f,0.890625f, +0.507813f,0.898438f, +0.515625f,0.898438f, +0.523438f,0.898438f, +0.53125f,0.898438f, +0.539063f,0.898438f, +0.546875f,0.898438f, +0.554688f,0.898438f, +0.5625f,0.898438f, +0.570313f,0.898438f, +0.578125f,0.898438f, +0.585938f,0.898438f, +0.59375f,0.898438f, +0.601563f,0.898438f, +0.609375f,0.898438f, +0.617188f,0.898438f, +0.625f,0.898438f, +0.632813f,0.898438f, +0.640625f,0.898438f, +0.648438f,0.898438f, +0.65625f,0.898438f, +0.664063f,0.898438f, +0.671875f,0.898438f, +0.679688f,0.898438f, +0.6875f,0.898438f, +0.695313f,0.898438f, +0.703125f,0.898438f, +0.710938f,0.898438f, +0.71875f,0.898438f, +0.726563f,0.898438f, +0.734375f,0.898438f, +0.742188f,0.898438f, +0.75f,0.898438f, +0.757813f,0.898438f, +0.765625f,0.898438f, +0.773438f,0.898438f, +0.78125f,0.898438f, +0.789063f,0.898438f, +0.796875f,0.898438f, +0.804688f,0.898438f, +0.8125f,0.898438f, +0.820313f,0.898438f, +0.828125f,0.898438f, +0.835938f,0.898438f, +0.84375f,0.898438f, +0.851563f,0.898438f, +0.859375f,0.898438f, +0.867188f,0.898438f, +0.875f,0.898438f, +0.882813f,0.898438f, +0.890625f,0.898438f, +0.898438f,0.898438f, +0.90625f,0.898438f, +0.914063f,0.898438f, +0.921875f,0.898438f, +0.929688f,0.898438f, +0.9375f,0.898438f, +0.945313f,0.898438f, +0.953125f,0.898438f, +0.960938f,0.898438f, +0.96875f,0.898438f, +0.976563f,0.898438f, +0.984375f,0.898438f, +0.992188f,0.898438f, +1.0f,0.898438f, +0.507813f,0.90625f, +0.515625f,0.90625f, +0.523438f,0.90625f, +0.53125f,0.90625f, +0.539063f,0.90625f, +0.546875f,0.90625f, +0.554688f,0.90625f, +0.5625f,0.90625f, +0.570313f,0.90625f, +0.578125f,0.90625f, +0.585938f,0.90625f, +0.59375f,0.90625f, +0.601563f,0.90625f, +0.609375f,0.90625f, +0.617188f,0.90625f, +0.625f,0.90625f, +0.632813f,0.90625f, +0.640625f,0.90625f, +0.648438f,0.90625f, +0.65625f,0.90625f, +0.664063f,0.90625f, +0.671875f,0.90625f, +0.679688f,0.90625f, +0.6875f,0.90625f, +0.695313f,0.90625f, +0.703125f,0.90625f, +0.710938f,0.90625f, +0.71875f,0.90625f, +0.726563f,0.90625f, +0.734375f,0.90625f, +0.742188f,0.90625f, +0.75f,0.90625f, +0.757813f,0.90625f, +0.765625f,0.90625f, +0.773438f,0.90625f, +0.78125f,0.90625f, +0.789063f,0.90625f, +0.796875f,0.90625f, +0.804688f,0.90625f, +0.8125f,0.90625f, +0.820313f,0.90625f, +0.828125f,0.90625f, +0.835938f,0.90625f, +0.84375f,0.90625f, +0.851563f,0.90625f, +0.859375f,0.90625f, +0.867188f,0.90625f, +0.875f,0.90625f, +0.882813f,0.90625f, +0.890625f,0.90625f, +0.898438f,0.90625f, +0.90625f,0.90625f, +0.914063f,0.90625f, +0.921875f,0.90625f, +0.929688f,0.90625f, +0.9375f,0.90625f, +0.945313f,0.90625f, +0.953125f,0.90625f, +0.960938f,0.90625f, +0.96875f,0.90625f, +0.976563f,0.90625f, +0.984375f,0.90625f, +0.992188f,0.90625f, +1.0f,0.90625f, +0.507813f,0.914063f, +0.515625f,0.914063f, +0.523438f,0.914063f, +0.53125f,0.914063f, +0.539063f,0.914063f, +0.546875f,0.914063f, +0.554688f,0.914063f, +0.5625f,0.914063f, +0.570313f,0.914063f, +0.578125f,0.914063f, +0.585938f,0.914063f, +0.59375f,0.914063f, +0.601563f,0.914063f, +0.609375f,0.914063f, +0.617188f,0.914063f, +0.625f,0.914063f, +0.632813f,0.914063f, +0.640625f,0.914063f, +0.648438f,0.914063f, +0.65625f,0.914063f, +0.664063f,0.914063f, +0.671875f,0.914063f, +0.679688f,0.914063f, +0.6875f,0.914063f, +0.695313f,0.914063f, +0.703125f,0.914063f, +0.710938f,0.914063f, +0.71875f,0.914063f, +0.726563f,0.914063f, +0.734375f,0.914063f, +0.742188f,0.914063f, +0.75f,0.914063f, +0.757813f,0.914063f, +0.765625f,0.914063f, +0.773438f,0.914063f, +0.78125f,0.914063f, +0.789063f,0.914063f, +0.796875f,0.914063f, +0.804688f,0.914063f, +0.8125f,0.914063f, +0.820313f,0.914063f, +0.828125f,0.914063f, +0.835938f,0.914063f, +0.84375f,0.914063f, +0.851563f,0.914063f, +0.859375f,0.914063f, +0.867188f,0.914063f, +0.875f,0.914063f, +0.882813f,0.914063f, +0.890625f,0.914063f, +0.898438f,0.914063f, +0.90625f,0.914063f, +0.914063f,0.914063f, +0.921875f,0.914063f, +0.929688f,0.914063f, +0.9375f,0.914063f, +0.945313f,0.914063f, +0.953125f,0.914063f, +0.960938f,0.914063f, +0.96875f,0.914063f, +0.976563f,0.914063f, +0.984375f,0.914063f, +0.992188f,0.914063f, +1.0f,0.914063f, +0.507813f,0.921875f, +0.515625f,0.921875f, +0.523438f,0.921875f, +0.53125f,0.921875f, +0.539063f,0.921875f, +0.546875f,0.921875f, +0.554688f,0.921875f, +0.5625f,0.921875f, +0.570313f,0.921875f, +0.578125f,0.921875f, +0.585938f,0.921875f, +0.59375f,0.921875f, +0.601563f,0.921875f, +0.609375f,0.921875f, +0.617188f,0.921875f, +0.625f,0.921875f, +0.632813f,0.921875f, +0.640625f,0.921875f, +0.648438f,0.921875f, +0.65625f,0.921875f, +0.664063f,0.921875f, +0.671875f,0.921875f, +0.679688f,0.921875f, +0.6875f,0.921875f, +0.695313f,0.921875f, +0.703125f,0.921875f, +0.710938f,0.921875f, +0.71875f,0.921875f, +0.726563f,0.921875f, +0.734375f,0.921875f, +0.742188f,0.921875f, +0.75f,0.921875f, +0.757813f,0.921875f, +0.765625f,0.921875f, +0.773438f,0.921875f, +0.78125f,0.921875f, +0.789063f,0.921875f, +0.796875f,0.921875f, +0.804688f,0.921875f, +0.8125f,0.921875f, +0.820313f,0.921875f, +0.828125f,0.921875f, +0.835938f,0.921875f, +0.84375f,0.921875f, +0.851563f,0.921875f, +0.859375f,0.921875f, +0.867188f,0.921875f, +0.875f,0.921875f, +0.882813f,0.921875f, +0.890625f,0.921875f, +0.898438f,0.921875f, +0.90625f,0.921875f, +0.914063f,0.921875f, +0.921875f,0.921875f, +0.929688f,0.921875f, +0.9375f,0.921875f, +0.945313f,0.921875f, +0.953125f,0.921875f, +0.960938f,0.921875f, +0.96875f,0.921875f, +0.976563f,0.921875f, +0.984375f,0.921875f, +0.992188f,0.921875f, +1.0f,0.921875f, +0.507813f,0.929688f, +0.515625f,0.929688f, +0.523438f,0.929688f, +0.53125f,0.929688f, +0.539063f,0.929688f, +0.546875f,0.929688f, +0.554688f,0.929688f, +0.5625f,0.929688f, +0.570313f,0.929688f, +0.578125f,0.929688f, +0.585938f,0.929688f, +0.59375f,0.929688f, +0.601563f,0.929688f, +0.609375f,0.929688f, +0.617188f,0.929688f, +0.625f,0.929688f, +0.632813f,0.929688f, +0.640625f,0.929688f, +0.648438f,0.929688f, +0.65625f,0.929688f, +0.664063f,0.929688f, +0.671875f,0.929688f, +0.679688f,0.929688f, +0.6875f,0.929688f, +0.695313f,0.929688f, +0.703125f,0.929688f, +0.710938f,0.929688f, +0.71875f,0.929688f, +0.726563f,0.929688f, +0.734375f,0.929688f, +0.742188f,0.929688f, +0.75f,0.929688f, +0.757813f,0.929688f, +0.765625f,0.929688f, +0.773438f,0.929688f, +0.78125f,0.929688f, +0.789063f,0.929688f, +0.796875f,0.929688f, +0.804688f,0.929688f, +0.8125f,0.929688f, +0.820313f,0.929688f, +0.828125f,0.929688f, +0.835938f,0.929688f, +0.84375f,0.929688f, +0.851563f,0.929688f, +0.859375f,0.929688f, +0.867188f,0.929688f, +0.875f,0.929688f, +0.882813f,0.929688f, +0.890625f,0.929688f, +0.898438f,0.929688f, +0.90625f,0.929688f, +0.914063f,0.929688f, +0.921875f,0.929688f, +0.929688f,0.929688f, +0.9375f,0.929688f, +0.945313f,0.929688f, +0.953125f,0.929688f, +0.960938f,0.929688f, +0.96875f,0.929688f, +0.976563f,0.929688f, +0.984375f,0.929688f, +0.992188f,0.929688f, +1.0f,0.929688f, +0.507813f,0.9375f, +0.515625f,0.9375f, +0.523438f,0.9375f, +0.53125f,0.9375f, +0.539063f,0.9375f, +0.546875f,0.9375f, +0.554688f,0.9375f, +0.5625f,0.9375f, +0.570313f,0.9375f, +0.578125f,0.9375f, +0.585938f,0.9375f, +0.59375f,0.9375f, +0.601563f,0.9375f, +0.609375f,0.9375f, +0.617188f,0.9375f, +0.625f,0.9375f, +0.632813f,0.9375f, +0.640625f,0.9375f, +0.648438f,0.9375f, +0.65625f,0.9375f, +0.664063f,0.9375f, +0.671875f,0.9375f, +0.679688f,0.9375f, +0.6875f,0.9375f, +0.695313f,0.9375f, +0.703125f,0.9375f, +0.710938f,0.9375f, +0.71875f,0.9375f, +0.726563f,0.9375f, +0.734375f,0.9375f, +0.742188f,0.9375f, +0.75f,0.9375f, +0.757813f,0.9375f, +0.765625f,0.9375f, +0.773438f,0.9375f, +0.78125f,0.9375f, +0.789063f,0.9375f, +0.796875f,0.9375f, +0.804688f,0.9375f, +0.8125f,0.9375f, +0.820313f,0.9375f, +0.828125f,0.9375f, +0.835938f,0.9375f, +0.84375f,0.9375f, +0.851563f,0.9375f, +0.859375f,0.9375f, +0.867188f,0.9375f, +0.875f,0.9375f, +0.882813f,0.9375f, +0.890625f,0.9375f, +0.898438f,0.9375f, +0.90625f,0.9375f, +0.914063f,0.9375f, +0.921875f,0.9375f, +0.929688f,0.9375f, +0.9375f,0.9375f, +0.945313f,0.9375f, +0.953125f,0.9375f, +0.960938f,0.9375f, +0.96875f,0.9375f, +0.976563f,0.9375f, +0.984375f,0.9375f, +0.992188f,0.9375f, +1.0f,0.9375f, +0.507813f,0.945313f, +0.515625f,0.945313f, +0.523438f,0.945313f, +0.53125f,0.945313f, +0.539063f,0.945313f, +0.546875f,0.945313f, +0.554688f,0.945313f, +0.5625f,0.945313f, +0.570313f,0.945313f, +0.578125f,0.945313f, +0.585938f,0.945313f, +0.59375f,0.945313f, +0.601563f,0.945313f, +0.609375f,0.945313f, +0.617188f,0.945313f, +0.625f,0.945313f, +0.632813f,0.945313f, +0.640625f,0.945313f, +0.648438f,0.945313f, +0.65625f,0.945313f, +0.664063f,0.945313f, +0.671875f,0.945313f, +0.679688f,0.945313f, +0.6875f,0.945313f, +0.695313f,0.945313f, +0.703125f,0.945313f, +0.710938f,0.945313f, +0.71875f,0.945313f, +0.726563f,0.945313f, +0.734375f,0.945313f, +0.742188f,0.945313f, +0.75f,0.945313f, +0.757813f,0.945313f, +0.765625f,0.945313f, +0.773438f,0.945313f, +0.78125f,0.945313f, +0.789063f,0.945313f, +0.796875f,0.945313f, +0.804688f,0.945313f, +0.8125f,0.945313f, +0.820313f,0.945313f, +0.828125f,0.945313f, +0.835938f,0.945313f, +0.84375f,0.945313f, +0.851563f,0.945313f, +0.859375f,0.945313f, +0.867188f,0.945313f, +0.875f,0.945313f, +0.882813f,0.945313f, +0.890625f,0.945313f, +0.898438f,0.945313f, +0.90625f,0.945313f, +0.914063f,0.945313f, +0.921875f,0.945313f, +0.929688f,0.945313f, +0.9375f,0.945313f, +0.945313f,0.945313f, +0.953125f,0.945313f, +0.960938f,0.945313f, +0.96875f,0.945313f, +0.976563f,0.945313f, +0.984375f,0.945313f, +0.992188f,0.945313f, +1.0f,0.945313f, +0.507813f,0.953125f, +0.515625f,0.953125f, +0.523438f,0.953125f, +0.53125f,0.953125f, +0.539063f,0.953125f, +0.546875f,0.953125f, +0.554688f,0.953125f, +0.5625f,0.953125f, +0.570313f,0.953125f, +0.578125f,0.953125f, +0.585938f,0.953125f, +0.59375f,0.953125f, +0.601563f,0.953125f, +0.609375f,0.953125f, +0.617188f,0.953125f, +0.625f,0.953125f, +0.632813f,0.953125f, +0.640625f,0.953125f, +0.648438f,0.953125f, +0.65625f,0.953125f, +0.664063f,0.953125f, +0.671875f,0.953125f, +0.679688f,0.953125f, +0.6875f,0.953125f, +0.695313f,0.953125f, +0.703125f,0.953125f, +0.710938f,0.953125f, +0.71875f,0.953125f, +0.726563f,0.953125f, +0.734375f,0.953125f, +0.742188f,0.953125f, +0.75f,0.953125f, +0.757813f,0.953125f, +0.765625f,0.953125f, +0.773438f,0.953125f, +0.78125f,0.953125f, +0.789063f,0.953125f, +0.796875f,0.953125f, +0.804688f,0.953125f, +0.8125f,0.953125f, +0.820313f,0.953125f, +0.828125f,0.953125f, +0.835938f,0.953125f, +0.84375f,0.953125f, +0.851563f,0.953125f, +0.859375f,0.953125f, +0.867188f,0.953125f, +0.875f,0.953125f, +0.882813f,0.953125f, +0.890625f,0.953125f, +0.898438f,0.953125f, +0.90625f,0.953125f, +0.914063f,0.953125f, +0.921875f,0.953125f, +0.929688f,0.953125f, +0.9375f,0.953125f, +0.945313f,0.953125f, +0.953125f,0.953125f, +0.960938f,0.953125f, +0.96875f,0.953125f, +0.976563f,0.953125f, +0.984375f,0.953125f, +0.992188f,0.953125f, +1.0f,0.953125f, +0.507813f,0.960938f, +0.515625f,0.960938f, +0.523438f,0.960938f, +0.53125f,0.960938f, +0.539063f,0.960938f, +0.546875f,0.960938f, +0.554688f,0.960938f, +0.5625f,0.960938f, +0.570313f,0.960938f, +0.578125f,0.960938f, +0.585938f,0.960938f, +0.59375f,0.960938f, +0.601563f,0.960938f, +0.609375f,0.960938f, +0.617188f,0.960938f, +0.625f,0.960938f, +0.632813f,0.960938f, +0.640625f,0.960938f, +0.648438f,0.960938f, +0.65625f,0.960938f, +0.664063f,0.960938f, +0.671875f,0.960938f, +0.679688f,0.960938f, +0.6875f,0.960938f, +0.695313f,0.960938f, +0.703125f,0.960938f, +0.710938f,0.960938f, +0.71875f,0.960938f, +0.726563f,0.960938f, +0.734375f,0.960938f, +0.742188f,0.960938f, +0.75f,0.960938f, +0.757813f,0.960938f, +0.765625f,0.960938f, +0.773438f,0.960938f, +0.78125f,0.960938f, +0.789063f,0.960938f, +0.796875f,0.960938f, +0.804688f,0.960938f, +0.8125f,0.960938f, +0.820313f,0.960938f, +0.828125f,0.960938f, +0.835938f,0.960938f, +0.84375f,0.960938f, +0.851563f,0.960938f, +0.859375f,0.960938f, +0.867188f,0.960938f, +0.875f,0.960938f, +0.882813f,0.960938f, +0.890625f,0.960938f, +0.898438f,0.960938f, +0.90625f,0.960938f, +0.914063f,0.960938f, +0.921875f,0.960938f, +0.929688f,0.960938f, +0.9375f,0.960938f, +0.945313f,0.960938f, +0.953125f,0.960938f, +0.960938f,0.960938f, +0.96875f,0.960938f, +0.976563f,0.960938f, +0.984375f,0.960938f, +0.992188f,0.960938f, +1.0f,0.960938f, +0.507813f,0.96875f, +0.515625f,0.96875f, +0.523438f,0.96875f, +0.53125f,0.96875f, +0.539063f,0.96875f, +0.546875f,0.96875f, +0.554688f,0.96875f, +0.5625f,0.96875f, +0.570313f,0.96875f, +0.578125f,0.96875f, +0.585938f,0.96875f, +0.59375f,0.96875f, +0.601563f,0.96875f, +0.609375f,0.96875f, +0.617188f,0.96875f, +0.625f,0.96875f, +0.632813f,0.96875f, +0.640625f,0.96875f, +0.648438f,0.96875f, +0.65625f,0.96875f, +0.664063f,0.96875f, +0.671875f,0.96875f, +0.679688f,0.96875f, +0.6875f,0.96875f, +0.695313f,0.96875f, +0.703125f,0.96875f, +0.710938f,0.96875f, +0.71875f,0.96875f, +0.726563f,0.96875f, +0.734375f,0.96875f, +0.742188f,0.96875f, +0.75f,0.96875f, +0.757813f,0.96875f, +0.765625f,0.96875f, +0.773438f,0.96875f, +0.78125f,0.96875f, +0.789063f,0.96875f, +0.796875f,0.96875f, +0.804688f,0.96875f, +0.8125f,0.96875f, +0.820313f,0.96875f, +0.828125f,0.96875f, +0.835938f,0.96875f, +0.84375f,0.96875f, +0.851563f,0.96875f, +0.859375f,0.96875f, +0.867188f,0.96875f, +0.875f,0.96875f, +0.882813f,0.96875f, +0.890625f,0.96875f, +0.898438f,0.96875f, +0.90625f,0.96875f, +0.914063f,0.96875f, +0.921875f,0.96875f, +0.929688f,0.96875f, +0.9375f,0.96875f, +0.945313f,0.96875f, +0.953125f,0.96875f, +0.960938f,0.96875f, +0.96875f,0.96875f, +0.976563f,0.96875f, +0.984375f,0.96875f, +0.992188f,0.96875f, +1.0f,0.96875f, +0.507813f,0.976563f, +0.515625f,0.976563f, +0.523438f,0.976563f, +0.53125f,0.976563f, +0.539063f,0.976563f, +0.546875f,0.976563f, +0.554688f,0.976563f, +0.5625f,0.976563f, +0.570313f,0.976563f, +0.578125f,0.976563f, +0.585938f,0.976563f, +0.59375f,0.976563f, +0.601563f,0.976563f, +0.609375f,0.976563f, +0.617188f,0.976563f, +0.625f,0.976563f, +0.632813f,0.976563f, +0.640625f,0.976563f, +0.648438f,0.976563f, +0.65625f,0.976563f, +0.664063f,0.976563f, +0.671875f,0.976563f, +0.679688f,0.976563f, +0.6875f,0.976563f, +0.695313f,0.976563f, +0.703125f,0.976563f, +0.710938f,0.976563f, +0.71875f,0.976563f, +0.726563f,0.976563f, +0.734375f,0.976563f, +0.742188f,0.976563f, +0.75f,0.976563f, +0.757813f,0.976563f, +0.765625f,0.976563f, +0.773438f,0.976563f, +0.78125f,0.976563f, +0.789063f,0.976563f, +0.796875f,0.976563f, +0.804688f,0.976563f, +0.8125f,0.976563f, +0.820313f,0.976563f, +0.828125f,0.976563f, +0.835938f,0.976563f, +0.84375f,0.976563f, +0.851563f,0.976563f, +0.859375f,0.976563f, +0.867188f,0.976563f, +0.875f,0.976563f, +0.882813f,0.976563f, +0.890625f,0.976563f, +0.898438f,0.976563f, +0.90625f,0.976563f, +0.914063f,0.976563f, +0.921875f,0.976563f, +0.929688f,0.976563f, +0.9375f,0.976563f, +0.945313f,0.976563f, +0.953125f,0.976563f, +0.960938f,0.976563f, +0.96875f,0.976563f, +0.976563f,0.976563f, +0.984375f,0.976563f, +0.992188f,0.976563f, +1.0f,0.976563f, +0.507813f,0.984375f, +0.515625f,0.984375f, +0.523438f,0.984375f, +0.53125f,0.984375f, +0.539063f,0.984375f, +0.546875f,0.984375f, +0.554688f,0.984375f, +0.5625f,0.984375f, +0.570313f,0.984375f, +0.578125f,0.984375f, +0.585938f,0.984375f, +0.59375f,0.984375f, +0.601563f,0.984375f, +0.609375f,0.984375f, +0.617188f,0.984375f, +0.625f,0.984375f, +0.632813f,0.984375f, +0.640625f,0.984375f, +0.648438f,0.984375f, +0.65625f,0.984375f, +0.664063f,0.984375f, +0.671875f,0.984375f, +0.679688f,0.984375f, +0.6875f,0.984375f, +0.695313f,0.984375f, +0.703125f,0.984375f, +0.710938f,0.984375f, +0.71875f,0.984375f, +0.726563f,0.984375f, +0.734375f,0.984375f, +0.742188f,0.984375f, +0.75f,0.984375f, +0.757813f,0.984375f, +0.765625f,0.984375f, +0.773438f,0.984375f, +0.78125f,0.984375f, +0.789063f,0.984375f, +0.796875f,0.984375f, +0.804688f,0.984375f, +0.8125f,0.984375f, +0.820313f,0.984375f, +0.828125f,0.984375f, +0.835938f,0.984375f, +0.84375f,0.984375f, +0.851563f,0.984375f, +0.859375f,0.984375f, +0.867188f,0.984375f, +0.875f,0.984375f, +0.882813f,0.984375f, +0.890625f,0.984375f, +0.898438f,0.984375f, +0.90625f,0.984375f, +0.914063f,0.984375f, +0.921875f,0.984375f, +0.929688f,0.984375f, +0.9375f,0.984375f, +0.945313f,0.984375f, +0.953125f,0.984375f, +0.960938f,0.984375f, +0.96875f,0.984375f, +0.976563f,0.984375f, +0.984375f,0.984375f, +0.992188f,0.984375f, +1.0f,0.984375f, +0.507813f,0.992188f, +0.515625f,0.992188f, +0.523438f,0.992188f, +0.53125f,0.992188f, +0.539063f,0.992188f, +0.546875f,0.992188f, +0.554688f,0.992188f, +0.5625f,0.992188f, +0.570313f,0.992188f, +0.578125f,0.992188f, +0.585938f,0.992188f, +0.59375f,0.992188f, +0.601563f,0.992188f, +0.609375f,0.992188f, +0.617188f,0.992188f, +0.625f,0.992188f, +0.632813f,0.992188f, +0.640625f,0.992188f, +0.648438f,0.992188f, +0.65625f,0.992188f, +0.664063f,0.992188f, +0.671875f,0.992188f, +0.679688f,0.992188f, +0.6875f,0.992188f, +0.695313f,0.992188f, +0.703125f,0.992188f, +0.710938f,0.992188f, +0.71875f,0.992188f, +0.726563f,0.992188f, +0.734375f,0.992188f, +0.742188f,0.992188f, +0.75f,0.992188f, +0.757813f,0.992188f, +0.765625f,0.992188f, +0.773438f,0.992188f, +0.78125f,0.992188f, +0.789063f,0.992188f, +0.796875f,0.992188f, +0.804688f,0.992188f, +0.8125f,0.992188f, +0.820313f,0.992188f, +0.828125f,0.992188f, +0.835938f,0.992188f, +0.84375f,0.992188f, +0.851563f,0.992188f, +0.859375f,0.992188f, +0.867188f,0.992188f, +0.875f,0.992188f, +0.882813f,0.992188f, +0.890625f,0.992188f, +0.898438f,0.992188f, +0.90625f,0.992188f, +0.914063f,0.992188f, +0.921875f,0.992188f, +0.929688f,0.992188f, +0.9375f,0.992188f, +0.945313f,0.992188f, +0.953125f,0.992188f, +0.960938f,0.992188f, +0.96875f,0.992188f, +0.976563f,0.992188f, +0.984375f,0.992188f, +0.992188f,0.992188f, +1.0f,0.992188f, +0.507813f,1.0f, +0.515625f,1.0f, +0.523438f,1.0f, +0.53125f,1.0f, +0.539063f,1.0f, +0.546875f,1.0f, +0.554688f,1.0f, +0.5625f,1.0f, +0.570313f,1.0f, +0.578125f,1.0f, +0.585938f,1.0f, +0.59375f,1.0f, +0.601563f,1.0f, +0.609375f,1.0f, +0.617188f,1.0f, +0.625f,1.0f, +0.632813f,1.0f, +0.640625f,1.0f, +0.648438f,1.0f, +0.65625f,1.0f, +0.664063f,1.0f, +0.671875f,1.0f, +0.679688f,1.0f, +0.6875f,1.0f, +0.695313f,1.0f, +0.703125f,1.0f, +0.710938f,1.0f, +0.71875f,1.0f, +0.726563f,1.0f, +0.734375f,1.0f, +0.742188f,1.0f, +0.75f,1.0f, +0.757813f,1.0f, +0.765625f,1.0f, +0.773438f,1.0f, +0.78125f,1.0f, +0.789063f,1.0f, +0.796875f,1.0f, +0.804688f,1.0f, +0.8125f,1.0f, +0.820313f,1.0f, +0.828125f,1.0f, +0.835938f,1.0f, +0.84375f,1.0f, +0.851563f,1.0f, +0.859375f,1.0f, +0.867188f,1.0f, +0.875f,1.0f, +0.882813f,1.0f, +0.890625f,1.0f, +0.898438f,1.0f, +0.90625f,1.0f, +0.914063f,1.0f, +0.921875f,1.0f, +0.929688f,1.0f, +0.9375f,1.0f, +0.945313f,1.0f, +0.953125f,1.0f, +0.960938f,1.0f, +0.96875f,1.0f, +0.976563f,1.0f, +0.984375f,1.0f, +0.992188f,1.0f, +1.0f,1.0f, +}; + +unsigned short Landscape07Idx[] = { +0,1,2, +3,2,1, +2,3,4, +5,4,3, +4,5,6, +7,6,5, +6,7,8, +9,8,7, +8,9,10, +11,10,9, +10,11,12, +13,12,11, +12,13,14, +15,14,13, +14,15,16, +17,16,15, +16,17,18, +19,18,17, +18,19,20, +21,20,19, +20,21,22, +23,22,21, +22,23,24, +25,24,23, +24,25,26, +27,26,25, +26,27,28, +29,28,27, +28,29,30, +31,30,29, +30,31,32, +33,32,31, +32,33,34, +35,34,33, +34,35,36, +37,36,35, +36,37,38, +39,38,37, +38,39,40, +41,40,39, +40,41,42, +43,42,41, +42,43,44, +45,44,43, +44,45,46, +47,46,45, +46,47,48, +49,48,47, +48,49,50, +51,50,49, +50,51,52, +53,52,51, +52,53,54, +55,54,53, +54,55,56, +57,56,55, +56,57,58, +59,58,57, +58,59,60, +61,60,59, +60,61,62, +63,62,61, +62,63,64, +65,64,63, +64,65,66, +67,66,65, +66,67,68, +69,68,67, +68,69,70, +71,70,69, +70,71,72, +73,72,71, +72,73,74, +75,74,73, +74,75,76, +77,76,75, +76,77,78, +79,78,77, +78,79,80, +81,80,79, +80,81,82, +83,82,81, +82,83,84, +85,84,83, +84,85,86, +87,86,85, +86,87,88, +89,88,87, +88,89,90, +91,90,89, +90,91,92, +93,92,91, +92,93,94, +95,94,93, +94,95,96, +97,96,95, +96,97,98, +99,98,97, +98,99,100, +101,100,99, +100,101,102, +103,102,101, +102,103,104, +105,104,103, +104,105,106, +107,106,105, +106,107,108, +109,108,107, +108,109,110, +111,110,109, +110,111,112, +113,112,111, +112,113,114, +115,114,113, +114,115,116, +117,116,115, +116,117,118, +119,118,117, +118,119,120, +121,120,119, +120,121,122, +123,122,121, +122,123,124, +125,124,123, +124,125,126, +127,126,125, +128,0,129, +2,129,0, +129,2,130, +4,130,2, +130,4,131, +6,131,4, +131,6,132, +8,132,6, +132,8,133, +10,133,8, +133,10,134, +12,134,10, +134,12,135, +14,135,12, +135,14,136, +16,136,14, +136,16,137, +18,137,16, +137,18,138, +20,138,18, +138,20,139, +22,139,20, +139,22,140, +24,140,22, +140,24,141, +26,141,24, +141,26,142, +28,142,26, +142,28,143, +30,143,28, +143,30,144, +32,144,30, +144,32,145, +34,145,32, +145,34,146, +36,146,34, +146,36,147, +38,147,36, +147,38,148, +40,148,38, +148,40,149, +42,149,40, +149,42,150, +44,150,42, +150,44,151, +46,151,44, +151,46,152, +48,152,46, +152,48,153, +50,153,48, +153,50,154, +52,154,50, +154,52,155, +54,155,52, +155,54,156, +56,156,54, +156,56,157, +58,157,56, +157,58,158, +60,158,58, +158,60,159, +62,159,60, +159,62,160, +64,160,62, +160,64,161, +66,161,64, +161,66,162, +68,162,66, +162,68,163, +70,163,68, +163,70,164, +72,164,70, +164,72,165, +74,165,72, +165,74,166, +76,166,74, +166,76,167, +78,167,76, +167,78,168, +80,168,78, +168,80,169, +82,169,80, +169,82,170, +84,170,82, +170,84,171, +86,171,84, +171,86,172, +88,172,86, +172,88,173, +90,173,88, +173,90,174, +92,174,90, +174,92,175, +94,175,92, +175,94,176, +96,176,94, +176,96,177, +98,177,96, +177,98,178, +100,178,98, +178,100,179, +102,179,100, +179,102,180, +104,180,102, +180,104,181, +106,181,104, +181,106,182, +108,182,106, +182,108,183, +110,183,108, +183,110,184, +112,184,110, +184,112,185, +114,185,112, +185,114,186, +116,186,114, +186,116,187, +118,187,116, +187,118,188, +120,188,118, +188,120,189, +122,189,120, +189,122,190, +124,190,122, +190,124,191, +126,191,124, +192,128,193, +129,193,128, +193,129,194, +130,194,129, +194,130,195, +131,195,130, +195,131,196, +132,196,131, +196,132,197, +133,197,132, +197,133,198, +134,198,133, +198,134,199, +135,199,134, +199,135,200, +136,200,135, +200,136,201, +137,201,136, +201,137,202, +138,202,137, +202,138,203, +139,203,138, +203,139,204, +140,204,139, +204,140,205, +141,205,140, +205,141,206, +142,206,141, +206,142,207, +143,207,142, +207,143,208, +144,208,143, +208,144,209, +145,209,144, +209,145,210, +146,210,145, +210,146,211, +147,211,146, +211,147,212, +148,212,147, +212,148,213, +149,213,148, +213,149,214, +150,214,149, +214,150,215, +151,215,150, +215,151,216, +152,216,151, +216,152,217, +153,217,152, +217,153,218, +154,218,153, +218,154,219, +155,219,154, +219,155,220, +156,220,155, +220,156,221, +157,221,156, +221,157,222, +158,222,157, +222,158,223, +159,223,158, +223,159,224, +160,224,159, +224,160,225, +161,225,160, +225,161,226, +162,226,161, +226,162,227, +163,227,162, +227,163,228, +164,228,163, +228,164,229, +165,229,164, +229,165,230, +166,230,165, +230,166,231, +167,231,166, +231,167,232, +168,232,167, +232,168,233, +169,233,168, +233,169,234, +170,234,169, +234,170,235, +171,235,170, +235,171,236, +172,236,171, +236,172,237, +173,237,172, +237,173,238, +174,238,173, +238,174,239, +175,239,174, +239,175,240, +176,240,175, +240,176,241, +177,241,176, +241,177,242, +178,242,177, +242,178,243, +179,243,178, +243,179,244, +180,244,179, +244,180,245, +181,245,180, +245,181,246, +182,246,181, +246,182,247, +183,247,182, +247,183,248, +184,248,183, +248,184,249, +185,249,184, +249,185,250, +186,250,185, +250,186,251, +187,251,186, +251,187,252, +188,252,187, +252,188,253, +189,253,188, +253,189,254, +190,254,189, +254,190,255, +191,255,190, +256,192,257, +193,257,192, +257,193,258, +194,258,193, +258,194,259, +195,259,194, +259,195,260, +196,260,195, +260,196,261, +197,261,196, +261,197,262, +198,262,197, +262,198,263, +199,263,198, +263,199,264, +200,264,199, +264,200,265, +201,265,200, +265,201,266, +202,266,201, +266,202,267, +203,267,202, +267,203,268, +204,268,203, +268,204,269, +205,269,204, +269,205,270, +206,270,205, +270,206,271, +207,271,206, +271,207,272, +208,272,207, +272,208,273, +209,273,208, +273,209,274, +210,274,209, +274,210,275, +211,275,210, +275,211,276, +212,276,211, +276,212,277, +213,277,212, +277,213,278, +214,278,213, +278,214,279, +215,279,214, +279,215,280, +216,280,215, +280,216,281, +217,281,216, +281,217,282, +218,282,217, +282,218,283, +219,283,218, +283,219,284, +220,284,219, +284,220,285, +221,285,220, +285,221,286, +222,286,221, +286,222,287, +223,287,222, +287,223,288, +224,288,223, +288,224,289, +225,289,224, +289,225,290, +226,290,225, +290,226,291, +227,291,226, +291,227,292, +228,292,227, +292,228,293, +229,293,228, +293,229,294, +230,294,229, +294,230,295, +231,295,230, +295,231,296, +232,296,231, +296,232,297, +233,297,232, +297,233,298, +234,298,233, +298,234,299, +235,299,234, +299,235,300, +236,300,235, +300,236,301, +237,301,236, +301,237,302, +238,302,237, +302,238,303, +239,303,238, +303,239,304, +240,304,239, +304,240,305, +241,305,240, +305,241,306, +242,306,241, +306,242,307, +243,307,242, +307,243,308, +244,308,243, +308,244,309, +245,309,244, +309,245,310, +246,310,245, +310,246,311, +247,311,246, +311,247,312, +248,312,247, +312,248,313, +249,313,248, +313,249,314, +250,314,249, +314,250,315, +251,315,250, +315,251,316, +252,316,251, +316,252,317, +253,317,252, +317,253,318, +254,318,253, +318,254,319, +255,319,254, +320,256,321, +257,321,256, +321,257,322, +258,322,257, +322,258,323, +259,323,258, +323,259,324, +260,324,259, +324,260,325, +261,325,260, +325,261,326, +262,326,261, +326,262,327, +263,327,262, +327,263,328, +264,328,263, +328,264,329, +265,329,264, +329,265,330, +266,330,265, +330,266,331, +267,331,266, +331,267,332, +268,332,267, +332,268,333, +269,333,268, +333,269,334, +270,334,269, +334,270,335, +271,335,270, +335,271,336, +272,336,271, +336,272,337, +273,337,272, +337,273,338, +274,338,273, +338,274,339, +275,339,274, +339,275,340, +276,340,275, +340,276,341, +277,341,276, +341,277,342, +278,342,277, +342,278,343, +279,343,278, +343,279,344, +280,344,279, +344,280,345, +281,345,280, +345,281,346, +282,346,281, +346,282,347, +283,347,282, +347,283,348, +284,348,283, +348,284,349, +285,349,284, +349,285,350, +286,350,285, +350,286,351, +287,351,286, +351,287,352, +288,352,287, +352,288,353, +289,353,288, +353,289,354, +290,354,289, +354,290,355, +291,355,290, +355,291,356, +292,356,291, +356,292,357, +293,357,292, +357,293,358, +294,358,293, +358,294,359, +295,359,294, +359,295,360, +296,360,295, +360,296,361, +297,361,296, +361,297,362, +298,362,297, +362,298,363, +299,363,298, +363,299,364, +300,364,299, +364,300,365, +301,365,300, +365,301,366, +302,366,301, +366,302,367, +303,367,302, +367,303,368, +304,368,303, +368,304,369, +305,369,304, +369,305,370, +306,370,305, +370,306,371, +307,371,306, +371,307,372, +308,372,307, +372,308,373, +309,373,308, +373,309,374, +310,374,309, +374,310,375, +311,375,310, +375,311,376, +312,376,311, +376,312,377, +313,377,312, +377,313,378, +314,378,313, +378,314,379, +315,379,314, +379,315,380, +316,380,315, +380,316,381, +317,381,316, +381,317,382, +318,382,317, +382,318,383, +319,383,318, +384,320,385, +321,385,320, +385,321,386, +322,386,321, +386,322,387, +323,387,322, +387,323,388, +324,388,323, +388,324,389, +325,389,324, +389,325,390, +326,390,325, +390,326,391, +327,391,326, +391,327,392, +328,392,327, +392,328,393, +329,393,328, +393,329,394, +330,394,329, +394,330,395, +331,395,330, +395,331,396, +332,396,331, +396,332,397, +333,397,332, +397,333,398, +334,398,333, +398,334,399, +335,399,334, +399,335,400, +336,400,335, +400,336,401, +337,401,336, +401,337,402, +338,402,337, +402,338,403, +339,403,338, +403,339,404, +340,404,339, +404,340,405, +341,405,340, +405,341,406, +342,406,341, +406,342,407, +343,407,342, +407,343,408, +344,408,343, +408,344,409, +345,409,344, +409,345,410, +346,410,345, +410,346,411, +347,411,346, +411,347,412, +348,412,347, +412,348,413, +349,413,348, +413,349,414, +350,414,349, +414,350,415, +351,415,350, +415,351,416, +352,416,351, +416,352,417, +353,417,352, +417,353,418, +354,418,353, +418,354,419, +355,419,354, +419,355,420, +356,420,355, +420,356,421, +357,421,356, +421,357,422, +358,422,357, +422,358,423, +359,423,358, +423,359,424, +360,424,359, +424,360,425, +361,425,360, +425,361,426, +362,426,361, +426,362,427, +363,427,362, +427,363,428, +364,428,363, +428,364,429, +365,429,364, +429,365,430, +366,430,365, +430,366,431, +367,431,366, +431,367,432, +368,432,367, +432,368,433, +369,433,368, +433,369,434, +370,434,369, +434,370,435, +371,435,370, +435,371,436, +372,436,371, +436,372,437, +373,437,372, +437,373,438, +374,438,373, +438,374,439, +375,439,374, +439,375,440, +376,440,375, +440,376,441, +377,441,376, +441,377,442, +378,442,377, +442,378,443, +379,443,378, +443,379,444, +380,444,379, +444,380,445, +381,445,380, +445,381,446, +382,446,381, +446,382,447, +383,447,382, +448,384,449, +385,449,384, +449,385,450, +386,450,385, +450,386,451, +387,451,386, +451,387,452, +388,452,387, +452,388,453, +389,453,388, +453,389,454, +390,454,389, +454,390,455, +391,455,390, +455,391,456, +392,456,391, +456,392,457, +393,457,392, +457,393,458, +394,458,393, +458,394,459, +395,459,394, +459,395,460, +396,460,395, +460,396,461, +397,461,396, +461,397,462, +398,462,397, +462,398,463, +399,463,398, +463,399,464, +400,464,399, +464,400,465, +401,465,400, +465,401,466, +402,466,401, +466,402,467, +403,467,402, +467,403,468, +404,468,403, +468,404,469, +405,469,404, +469,405,470, +406,470,405, +470,406,471, +407,471,406, +471,407,472, +408,472,407, +472,408,473, +409,473,408, +473,409,474, +410,474,409, +474,410,475, +411,475,410, +475,411,476, +412,476,411, +476,412,477, +413,477,412, +477,413,478, +414,478,413, +478,414,479, +415,479,414, +479,415,480, +416,480,415, +480,416,481, +417,481,416, +481,417,482, +418,482,417, +482,418,483, +419,483,418, +483,419,484, +420,484,419, +484,420,485, +421,485,420, +485,421,486, +422,486,421, +486,422,487, +423,487,422, +487,423,488, +424,488,423, +488,424,489, +425,489,424, +489,425,490, +426,490,425, +490,426,491, +427,491,426, +491,427,492, +428,492,427, +492,428,493, +429,493,428, +493,429,494, +430,494,429, +494,430,495, +431,495,430, +495,431,496, +432,496,431, +496,432,497, +433,497,432, +497,433,498, +434,498,433, +498,434,499, +435,499,434, +499,435,500, +436,500,435, +500,436,501, +437,501,436, +501,437,502, +438,502,437, +502,438,503, +439,503,438, +503,439,504, +440,504,439, +504,440,505, +441,505,440, +505,441,506, +442,506,441, +506,442,507, +443,507,442, +507,443,508, +444,508,443, +508,444,509, +445,509,444, +509,445,510, +446,510,445, +510,446,511, +447,511,446, +512,448,513, +449,513,448, +513,449,514, +450,514,449, +514,450,515, +451,515,450, +515,451,516, +452,516,451, +516,452,517, +453,517,452, +517,453,518, +454,518,453, +518,454,519, +455,519,454, +519,455,520, +456,520,455, +520,456,521, +457,521,456, +521,457,522, +458,522,457, +522,458,523, +459,523,458, +523,459,524, +460,524,459, +524,460,525, +461,525,460, +525,461,526, +462,526,461, +526,462,527, +463,527,462, +527,463,528, +464,528,463, +528,464,529, +465,529,464, +529,465,530, +466,530,465, +530,466,531, +467,531,466, +531,467,532, +468,532,467, +532,468,533, +469,533,468, +533,469,534, +470,534,469, +534,470,535, +471,535,470, +535,471,536, +472,536,471, +536,472,537, +473,537,472, +537,473,538, +474,538,473, +538,474,539, +475,539,474, +539,475,540, +476,540,475, +540,476,541, +477,541,476, +541,477,542, +478,542,477, +542,478,543, +479,543,478, +543,479,544, +480,544,479, +544,480,545, +481,545,480, +545,481,546, +482,546,481, +546,482,547, +483,547,482, +547,483,548, +484,548,483, +548,484,549, +485,549,484, +549,485,550, +486,550,485, +550,486,551, +487,551,486, +551,487,552, +488,552,487, +552,488,553, +489,553,488, +553,489,554, +490,554,489, +554,490,555, +491,555,490, +555,491,556, +492,556,491, +556,492,557, +493,557,492, +557,493,558, +494,558,493, +558,494,559, +495,559,494, +559,495,560, +496,560,495, +560,496,561, +497,561,496, +561,497,562, +498,562,497, +562,498,563, +499,563,498, +563,499,564, +500,564,499, +564,500,565, +501,565,500, +565,501,566, +502,566,501, +566,502,567, +503,567,502, +567,503,568, +504,568,503, +568,504,569, +505,569,504, +569,505,570, +506,570,505, +570,506,571, +507,571,506, +571,507,572, +508,572,507, +572,508,573, +509,573,508, +573,509,574, +510,574,509, +574,510,575, +511,575,510, +576,512,577, +513,577,512, +577,513,578, +514,578,513, +578,514,579, +515,579,514, +579,515,580, +516,580,515, +580,516,581, +517,581,516, +581,517,582, +518,582,517, +582,518,583, +519,583,518, +583,519,584, +520,584,519, +584,520,585, +521,585,520, +585,521,586, +522,586,521, +586,522,587, +523,587,522, +587,523,588, +524,588,523, +588,524,589, +525,589,524, +589,525,590, +526,590,525, +590,526,591, +527,591,526, +591,527,592, +528,592,527, +592,528,593, +529,593,528, +593,529,594, +530,594,529, +594,530,595, +531,595,530, +595,531,596, +532,596,531, +596,532,597, +533,597,532, +597,533,598, +534,598,533, +598,534,599, +535,599,534, +599,535,600, +536,600,535, +600,536,601, +537,601,536, +601,537,602, +538,602,537, +602,538,603, +539,603,538, +603,539,604, +540,604,539, +604,540,605, +541,605,540, +605,541,606, +542,606,541, +606,542,607, +543,607,542, +607,543,608, +544,608,543, +608,544,609, +545,609,544, +609,545,610, +546,610,545, +610,546,611, +547,611,546, +611,547,612, +548,612,547, +612,548,613, +549,613,548, +613,549,614, +550,614,549, +614,550,615, +551,615,550, +615,551,616, +552,616,551, +616,552,617, +553,617,552, +617,553,618, +554,618,553, +618,554,619, +555,619,554, +619,555,620, +556,620,555, +620,556,621, +557,621,556, +621,557,622, +558,622,557, +622,558,623, +559,623,558, +623,559,624, +560,624,559, +624,560,625, +561,625,560, +625,561,626, +562,626,561, +626,562,627, +563,627,562, +627,563,628, +564,628,563, +628,564,629, +565,629,564, +629,565,630, +566,630,565, +630,566,631, +567,631,566, +631,567,632, +568,632,567, +632,568,633, +569,633,568, +633,569,634, +570,634,569, +634,570,635, +571,635,570, +635,571,636, +572,636,571, +636,572,637, +573,637,572, +637,573,638, +574,638,573, +638,574,639, +575,639,574, +640,576,641, +577,641,576, +641,577,642, +578,642,577, +642,578,643, +579,643,578, +643,579,644, +580,644,579, +644,580,645, +581,645,580, +645,581,646, +582,646,581, +646,582,647, +583,647,582, +647,583,648, +584,648,583, +648,584,649, +585,649,584, +649,585,650, +586,650,585, +650,586,651, +587,651,586, +651,587,652, +588,652,587, +652,588,653, +589,653,588, +653,589,654, +590,654,589, +654,590,655, +591,655,590, +655,591,656, +592,656,591, +656,592,657, +593,657,592, +657,593,658, +594,658,593, +658,594,659, +595,659,594, +659,595,660, +596,660,595, +660,596,661, +597,661,596, +661,597,662, +598,662,597, +662,598,663, +599,663,598, +663,599,664, +600,664,599, +664,600,665, +601,665,600, +665,601,666, +602,666,601, +666,602,667, +603,667,602, +667,603,668, +604,668,603, +668,604,669, +605,669,604, +669,605,670, +606,670,605, +670,606,671, +607,671,606, +671,607,672, +608,672,607, +672,608,673, +609,673,608, +673,609,674, +610,674,609, +674,610,675, +611,675,610, +675,611,676, +612,676,611, +676,612,677, +613,677,612, +677,613,678, +614,678,613, +678,614,679, +615,679,614, +679,615,680, +616,680,615, +680,616,681, +617,681,616, +681,617,682, +618,682,617, +682,618,683, +619,683,618, +683,619,684, +620,684,619, +684,620,685, +621,685,620, +685,621,686, +622,686,621, +686,622,687, +623,687,622, +687,623,688, +624,688,623, +688,624,689, +625,689,624, +689,625,690, +626,690,625, +690,626,691, +627,691,626, +691,627,692, +628,692,627, +692,628,693, +629,693,628, +693,629,694, +630,694,629, +694,630,695, +631,695,630, +695,631,696, +632,696,631, +696,632,697, +633,697,632, +697,633,698, +634,698,633, +698,634,699, +635,699,634, +699,635,700, +636,700,635, +700,636,701, +637,701,636, +701,637,702, +638,702,637, +702,638,703, +639,703,638, +704,640,705, +641,705,640, +705,641,706, +642,706,641, +706,642,707, +643,707,642, +707,643,708, +644,708,643, +708,644,709, +645,709,644, +709,645,710, +646,710,645, +710,646,711, +647,711,646, +711,647,712, +648,712,647, +712,648,713, +649,713,648, +713,649,714, +650,714,649, +714,650,715, +651,715,650, +715,651,716, +652,716,651, +716,652,717, +653,717,652, +717,653,718, +654,718,653, +718,654,719, +655,719,654, +719,655,720, +656,720,655, +720,656,721, +657,721,656, +721,657,722, +658,722,657, +722,658,723, +659,723,658, +723,659,724, +660,724,659, +724,660,725, +661,725,660, +725,661,726, +662,726,661, +726,662,727, +663,727,662, +727,663,728, +664,728,663, +728,664,729, +665,729,664, +729,665,730, +666,730,665, +730,666,731, +667,731,666, +731,667,732, +668,732,667, +732,668,733, +669,733,668, +733,669,734, +670,734,669, +734,670,735, +671,735,670, +735,671,736, +672,736,671, +736,672,737, +673,737,672, +737,673,738, +674,738,673, +738,674,739, +675,739,674, +739,675,740, +676,740,675, +740,676,741, +677,741,676, +741,677,742, +678,742,677, +742,678,743, +679,743,678, +743,679,744, +680,744,679, +744,680,745, +681,745,680, +745,681,746, +682,746,681, +746,682,747, +683,747,682, +747,683,748, +684,748,683, +748,684,749, +685,749,684, +749,685,750, +686,750,685, +750,686,751, +687,751,686, +751,687,752, +688,752,687, +752,688,753, +689,753,688, +753,689,754, +690,754,689, +754,690,755, +691,755,690, +755,691,756, +692,756,691, +756,692,757, +693,757,692, +757,693,758, +694,758,693, +758,694,759, +695,759,694, +759,695,760, +696,760,695, +760,696,761, +697,761,696, +761,697,762, +698,762,697, +762,698,763, +699,763,698, +763,699,764, +700,764,699, +764,700,765, +701,765,700, +765,701,766, +702,766,701, +766,702,767, +703,767,702, +768,704,769, +705,769,704, +769,705,770, +706,770,705, +770,706,771, +707,771,706, +771,707,772, +708,772,707, +772,708,773, +709,773,708, +773,709,774, +710,774,709, +774,710,775, +711,775,710, +775,711,776, +712,776,711, +776,712,777, +713,777,712, +777,713,778, +714,778,713, +778,714,779, +715,779,714, +779,715,780, +716,780,715, +780,716,781, +717,781,716, +781,717,782, +718,782,717, +782,718,783, +719,783,718, +783,719,784, +720,784,719, +784,720,785, +721,785,720, +785,721,786, +722,786,721, +786,722,787, +723,787,722, +787,723,788, +724,788,723, +788,724,789, +725,789,724, +789,725,790, +726,790,725, +790,726,791, +727,791,726, +791,727,792, +728,792,727, +792,728,793, +729,793,728, +793,729,794, +730,794,729, +794,730,795, +731,795,730, +795,731,796, +732,796,731, +796,732,797, +733,797,732, +797,733,798, +734,798,733, +798,734,799, +735,799,734, +799,735,800, +736,800,735, +800,736,801, +737,801,736, +801,737,802, +738,802,737, +802,738,803, +739,803,738, +803,739,804, +740,804,739, +804,740,805, +741,805,740, +805,741,806, +742,806,741, +806,742,807, +743,807,742, +807,743,808, +744,808,743, +808,744,809, +745,809,744, +809,745,810, +746,810,745, +810,746,811, +747,811,746, +811,747,812, +748,812,747, +812,748,813, +749,813,748, +813,749,814, +750,814,749, +814,750,815, +751,815,750, +815,751,816, +752,816,751, +816,752,817, +753,817,752, +817,753,818, +754,818,753, +818,754,819, +755,819,754, +819,755,820, +756,820,755, +820,756,821, +757,821,756, +821,757,822, +758,822,757, +822,758,823, +759,823,758, +823,759,824, +760,824,759, +824,760,825, +761,825,760, +825,761,826, +762,826,761, +826,762,827, +763,827,762, +827,763,828, +764,828,763, +828,764,829, +765,829,764, +829,765,830, +766,830,765, +830,766,831, +767,831,766, +832,768,833, +769,833,768, +833,769,834, +770,834,769, +834,770,835, +771,835,770, +835,771,836, +772,836,771, +836,772,837, +773,837,772, +837,773,838, +774,838,773, +838,774,839, +775,839,774, +839,775,840, +776,840,775, +840,776,841, +777,841,776, +841,777,842, +778,842,777, +842,778,843, +779,843,778, +843,779,844, +780,844,779, +844,780,845, +781,845,780, +845,781,846, +782,846,781, +846,782,847, +783,847,782, +847,783,848, +784,848,783, +848,784,849, +785,849,784, +849,785,850, +786,850,785, +850,786,851, +787,851,786, +851,787,852, +788,852,787, +852,788,853, +789,853,788, +853,789,854, +790,854,789, +854,790,855, +791,855,790, +855,791,856, +792,856,791, +856,792,857, +793,857,792, +857,793,858, +794,858,793, +858,794,859, +795,859,794, +859,795,860, +796,860,795, +860,796,861, +797,861,796, +861,797,862, +798,862,797, +862,798,863, +799,863,798, +863,799,864, +800,864,799, +864,800,865, +801,865,800, +865,801,866, +802,866,801, +866,802,867, +803,867,802, +867,803,868, +804,868,803, +868,804,869, +805,869,804, +869,805,870, +806,870,805, +870,806,871, +807,871,806, +871,807,872, +808,872,807, +872,808,873, +809,873,808, +873,809,874, +810,874,809, +874,810,875, +811,875,810, +875,811,876, +812,876,811, +876,812,877, +813,877,812, +877,813,878, +814,878,813, +878,814,879, +815,879,814, +879,815,880, +816,880,815, +880,816,881, +817,881,816, +881,817,882, +818,882,817, +882,818,883, +819,883,818, +883,819,884, +820,884,819, +884,820,885, +821,885,820, +885,821,886, +822,886,821, +886,822,887, +823,887,822, +887,823,888, +824,888,823, +888,824,889, +825,889,824, +889,825,890, +826,890,825, +890,826,891, +827,891,826, +891,827,892, +828,892,827, +892,828,893, +829,893,828, +893,829,894, +830,894,829, +894,830,895, +831,895,830, +896,832,897, +833,897,832, +897,833,898, +834,898,833, +898,834,899, +835,899,834, +899,835,900, +836,900,835, +900,836,901, +837,901,836, +901,837,902, +838,902,837, +902,838,903, +839,903,838, +903,839,904, +840,904,839, +904,840,905, +841,905,840, +905,841,906, +842,906,841, +906,842,907, +843,907,842, +907,843,908, +844,908,843, +908,844,909, +845,909,844, +909,845,910, +846,910,845, +910,846,911, +847,911,846, +911,847,912, +848,912,847, +912,848,913, +849,913,848, +913,849,914, +850,914,849, +914,850,915, +851,915,850, +915,851,916, +852,916,851, +916,852,917, +853,917,852, +917,853,918, +854,918,853, +918,854,919, +855,919,854, +919,855,920, +856,920,855, +920,856,921, +857,921,856, +921,857,922, +858,922,857, +922,858,923, +859,923,858, +923,859,924, +860,924,859, +924,860,925, +861,925,860, +925,861,926, +862,926,861, +926,862,927, +863,927,862, +927,863,928, +864,928,863, +928,864,929, +865,929,864, +929,865,930, +866,930,865, +930,866,931, +867,931,866, +931,867,932, +868,932,867, +932,868,933, +869,933,868, +933,869,934, +870,934,869, +934,870,935, +871,935,870, +935,871,936, +872,936,871, +936,872,937, +873,937,872, +937,873,938, +874,938,873, +938,874,939, +875,939,874, +939,875,940, +876,940,875, +940,876,941, +877,941,876, +941,877,942, +878,942,877, +942,878,943, +879,943,878, +943,879,944, +880,944,879, +944,880,945, +881,945,880, +945,881,946, +882,946,881, +946,882,947, +883,947,882, +947,883,948, +884,948,883, +948,884,949, +885,949,884, +949,885,950, +886,950,885, +950,886,951, +887,951,886, +951,887,952, +888,952,887, +952,888,953, +889,953,888, +953,889,954, +890,954,889, +954,890,955, +891,955,890, +955,891,956, +892,956,891, +956,892,957, +893,957,892, +957,893,958, +894,958,893, +958,894,959, +895,959,894, +960,896,961, +897,961,896, +961,897,962, +898,962,897, +962,898,963, +899,963,898, +963,899,964, +900,964,899, +964,900,965, +901,965,900, +965,901,966, +902,966,901, +966,902,967, +903,967,902, +967,903,968, +904,968,903, +968,904,969, +905,969,904, +969,905,970, +906,970,905, +970,906,971, +907,971,906, +971,907,972, +908,972,907, +972,908,973, +909,973,908, +973,909,974, +910,974,909, +974,910,975, +911,975,910, +975,911,976, +912,976,911, +976,912,977, +913,977,912, +977,913,978, +914,978,913, +978,914,979, +915,979,914, +979,915,980, +916,980,915, +980,916,981, +917,981,916, +981,917,982, +918,982,917, +982,918,983, +919,983,918, +983,919,984, +920,984,919, +984,920,985, +921,985,920, +985,921,986, +922,986,921, +986,922,987, +923,987,922, +987,923,988, +924,988,923, +988,924,989, +925,989,924, +989,925,990, +926,990,925, +990,926,991, +927,991,926, +991,927,992, +928,992,927, +992,928,993, +929,993,928, +993,929,994, +930,994,929, +994,930,995, +931,995,930, +995,931,996, +932,996,931, +996,932,997, +933,997,932, +997,933,998, +934,998,933, +998,934,999, +935,999,934, +999,935,1000, +936,1000,935, +1000,936,1001, +937,1001,936, +1001,937,1002, +938,1002,937, +1002,938,1003, +939,1003,938, +1003,939,1004, +940,1004,939, +1004,940,1005, +941,1005,940, +1005,941,1006, +942,1006,941, +1006,942,1007, +943,1007,942, +1007,943,1008, +944,1008,943, +1008,944,1009, +945,1009,944, +1009,945,1010, +946,1010,945, +1010,946,1011, +947,1011,946, +1011,947,1012, +948,1012,947, +1012,948,1013, +949,1013,948, +1013,949,1014, +950,1014,949, +1014,950,1015, +951,1015,950, +1015,951,1016, +952,1016,951, +1016,952,1017, +953,1017,952, +1017,953,1018, +954,1018,953, +1018,954,1019, +955,1019,954, +1019,955,1020, +956,1020,955, +1020,956,1021, +957,1021,956, +1021,957,1022, +958,1022,957, +1022,958,1023, +959,1023,958, +1024,960,1025, +961,1025,960, +1025,961,1026, +962,1026,961, +1026,962,1027, +963,1027,962, +1027,963,1028, +964,1028,963, +1028,964,1029, +965,1029,964, +1029,965,1030, +966,1030,965, +1030,966,1031, +967,1031,966, +1031,967,1032, +968,1032,967, +1032,968,1033, +969,1033,968, +1033,969,1034, +970,1034,969, +1034,970,1035, +971,1035,970, +1035,971,1036, +972,1036,971, +1036,972,1037, +973,1037,972, +1037,973,1038, +974,1038,973, +1038,974,1039, +975,1039,974, +1039,975,1040, +976,1040,975, +1040,976,1041, +977,1041,976, +1041,977,1042, +978,1042,977, +1042,978,1043, +979,1043,978, +1043,979,1044, +980,1044,979, +1044,980,1045, +981,1045,980, +1045,981,1046, +982,1046,981, +1046,982,1047, +983,1047,982, +1047,983,1048, +984,1048,983, +1048,984,1049, +985,1049,984, +1049,985,1050, +986,1050,985, +1050,986,1051, +987,1051,986, +1051,987,1052, +988,1052,987, +1052,988,1053, +989,1053,988, +1053,989,1054, +990,1054,989, +1054,990,1055, +991,1055,990, +1055,991,1056, +992,1056,991, +1056,992,1057, +993,1057,992, +1057,993,1058, +994,1058,993, +1058,994,1059, +995,1059,994, +1059,995,1060, +996,1060,995, +1060,996,1061, +997,1061,996, +1061,997,1062, +998,1062,997, +1062,998,1063, +999,1063,998, +1063,999,1064, +1000,1064,999, +1064,1000,1065, +1001,1065,1000, +1065,1001,1066, +1002,1066,1001, +1066,1002,1067, +1003,1067,1002, +1067,1003,1068, +1004,1068,1003, +1068,1004,1069, +1005,1069,1004, +1069,1005,1070, +1006,1070,1005, +1070,1006,1071, +1007,1071,1006, +1071,1007,1072, +1008,1072,1007, +1072,1008,1073, +1009,1073,1008, +1073,1009,1074, +1010,1074,1009, +1074,1010,1075, +1011,1075,1010, +1075,1011,1076, +1012,1076,1011, +1076,1012,1077, +1013,1077,1012, +1077,1013,1078, +1014,1078,1013, +1078,1014,1079, +1015,1079,1014, +1079,1015,1080, +1016,1080,1015, +1080,1016,1081, +1017,1081,1016, +1081,1017,1082, +1018,1082,1017, +1082,1018,1083, +1019,1083,1018, +1083,1019,1084, +1020,1084,1019, +1084,1020,1085, +1021,1085,1020, +1085,1021,1086, +1022,1086,1021, +1086,1022,1087, +1023,1087,1022, +1088,1024,1089, +1025,1089,1024, +1089,1025,1090, +1026,1090,1025, +1090,1026,1091, +1027,1091,1026, +1091,1027,1092, +1028,1092,1027, +1092,1028,1093, +1029,1093,1028, +1093,1029,1094, +1030,1094,1029, +1094,1030,1095, +1031,1095,1030, +1095,1031,1096, +1032,1096,1031, +1096,1032,1097, +1033,1097,1032, +1097,1033,1098, +1034,1098,1033, +1098,1034,1099, +1035,1099,1034, +1099,1035,1100, +1036,1100,1035, +1100,1036,1101, +1037,1101,1036, +1101,1037,1102, +1038,1102,1037, +1102,1038,1103, +1039,1103,1038, +1103,1039,1104, +1040,1104,1039, +1104,1040,1105, +1041,1105,1040, +1105,1041,1106, +1042,1106,1041, +1106,1042,1107, +1043,1107,1042, +1107,1043,1108, +1044,1108,1043, +1108,1044,1109, +1045,1109,1044, +1109,1045,1110, +1046,1110,1045, +1110,1046,1111, +1047,1111,1046, +1111,1047,1112, +1048,1112,1047, +1112,1048,1113, +1049,1113,1048, +1113,1049,1114, +1050,1114,1049, +1114,1050,1115, +1051,1115,1050, +1115,1051,1116, +1052,1116,1051, +1116,1052,1117, +1053,1117,1052, +1117,1053,1118, +1054,1118,1053, +1118,1054,1119, +1055,1119,1054, +1119,1055,1120, +1056,1120,1055, +1120,1056,1121, +1057,1121,1056, +1121,1057,1122, +1058,1122,1057, +1122,1058,1123, +1059,1123,1058, +1123,1059,1124, +1060,1124,1059, +1124,1060,1125, +1061,1125,1060, +1125,1061,1126, +1062,1126,1061, +1126,1062,1127, +1063,1127,1062, +1127,1063,1128, +1064,1128,1063, +1128,1064,1129, +1065,1129,1064, +1129,1065,1130, +1066,1130,1065, +1130,1066,1131, +1067,1131,1066, +1131,1067,1132, +1068,1132,1067, +1132,1068,1133, +1069,1133,1068, +1133,1069,1134, +1070,1134,1069, +1134,1070,1135, +1071,1135,1070, +1135,1071,1136, +1072,1136,1071, +1136,1072,1137, +1073,1137,1072, +1137,1073,1138, +1074,1138,1073, +1138,1074,1139, +1075,1139,1074, +1139,1075,1140, +1076,1140,1075, +1140,1076,1141, +1077,1141,1076, +1141,1077,1142, +1078,1142,1077, +1142,1078,1143, +1079,1143,1078, +1143,1079,1144, +1080,1144,1079, +1144,1080,1145, +1081,1145,1080, +1145,1081,1146, +1082,1146,1081, +1146,1082,1147, +1083,1147,1082, +1147,1083,1148, +1084,1148,1083, +1148,1084,1149, +1085,1149,1084, +1149,1085,1150, +1086,1150,1085, +1150,1086,1151, +1087,1151,1086, +1152,1088,1153, +1089,1153,1088, +1153,1089,1154, +1090,1154,1089, +1154,1090,1155, +1091,1155,1090, +1155,1091,1156, +1092,1156,1091, +1156,1092,1157, +1093,1157,1092, +1157,1093,1158, +1094,1158,1093, +1158,1094,1159, +1095,1159,1094, +1159,1095,1160, +1096,1160,1095, +1160,1096,1161, +1097,1161,1096, +1161,1097,1162, +1098,1162,1097, +1162,1098,1163, +1099,1163,1098, +1163,1099,1164, +1100,1164,1099, +1164,1100,1165, +1101,1165,1100, +1165,1101,1166, +1102,1166,1101, +1166,1102,1167, +1103,1167,1102, +1167,1103,1168, +1104,1168,1103, +1168,1104,1169, +1105,1169,1104, +1169,1105,1170, +1106,1170,1105, +1170,1106,1171, +1107,1171,1106, +1171,1107,1172, +1108,1172,1107, +1172,1108,1173, +1109,1173,1108, +1173,1109,1174, +1110,1174,1109, +1174,1110,1175, +1111,1175,1110, +1175,1111,1176, +1112,1176,1111, +1176,1112,1177, +1113,1177,1112, +1177,1113,1178, +1114,1178,1113, +1178,1114,1179, +1115,1179,1114, +1179,1115,1180, +1116,1180,1115, +1180,1116,1181, +1117,1181,1116, +1181,1117,1182, +1118,1182,1117, +1182,1118,1183, +1119,1183,1118, +1183,1119,1184, +1120,1184,1119, +1184,1120,1185, +1121,1185,1120, +1185,1121,1186, +1122,1186,1121, +1186,1122,1187, +1123,1187,1122, +1187,1123,1188, +1124,1188,1123, +1188,1124,1189, +1125,1189,1124, +1189,1125,1190, +1126,1190,1125, +1190,1126,1191, +1127,1191,1126, +1191,1127,1192, +1128,1192,1127, +1192,1128,1193, +1129,1193,1128, +1193,1129,1194, +1130,1194,1129, +1194,1130,1195, +1131,1195,1130, +1195,1131,1196, +1132,1196,1131, +1196,1132,1197, +1133,1197,1132, +1197,1133,1198, +1134,1198,1133, +1198,1134,1199, +1135,1199,1134, +1199,1135,1200, +1136,1200,1135, +1200,1136,1201, +1137,1201,1136, +1201,1137,1202, +1138,1202,1137, +1202,1138,1203, +1139,1203,1138, +1203,1139,1204, +1140,1204,1139, +1204,1140,1205, +1141,1205,1140, +1205,1141,1206, +1142,1206,1141, +1206,1142,1207, +1143,1207,1142, +1207,1143,1208, +1144,1208,1143, +1208,1144,1209, +1145,1209,1144, +1209,1145,1210, +1146,1210,1145, +1210,1146,1211, +1147,1211,1146, +1211,1147,1212, +1148,1212,1147, +1212,1148,1213, +1149,1213,1148, +1213,1149,1214, +1150,1214,1149, +1214,1150,1215, +1151,1215,1150, +1216,1152,1217, +1153,1217,1152, +1217,1153,1218, +1154,1218,1153, +1218,1154,1219, +1155,1219,1154, +1219,1155,1220, +1156,1220,1155, +1220,1156,1221, +1157,1221,1156, +1221,1157,1222, +1158,1222,1157, +1222,1158,1223, +1159,1223,1158, +1223,1159,1224, +1160,1224,1159, +1224,1160,1225, +1161,1225,1160, +1225,1161,1226, +1162,1226,1161, +1226,1162,1227, +1163,1227,1162, +1227,1163,1228, +1164,1228,1163, +1228,1164,1229, +1165,1229,1164, +1229,1165,1230, +1166,1230,1165, +1230,1166,1231, +1167,1231,1166, +1231,1167,1232, +1168,1232,1167, +1232,1168,1233, +1169,1233,1168, +1233,1169,1234, +1170,1234,1169, +1234,1170,1235, +1171,1235,1170, +1235,1171,1236, +1172,1236,1171, +1236,1172,1237, +1173,1237,1172, +1237,1173,1238, +1174,1238,1173, +1238,1174,1239, +1175,1239,1174, +1239,1175,1240, +1176,1240,1175, +1240,1176,1241, +1177,1241,1176, +1241,1177,1242, +1178,1242,1177, +1242,1178,1243, +1179,1243,1178, +1243,1179,1244, +1180,1244,1179, +1244,1180,1245, +1181,1245,1180, +1245,1181,1246, +1182,1246,1181, +1246,1182,1247, +1183,1247,1182, +1247,1183,1248, +1184,1248,1183, +1248,1184,1249, +1185,1249,1184, +1249,1185,1250, +1186,1250,1185, +1250,1186,1251, +1187,1251,1186, +1251,1187,1252, +1188,1252,1187, +1252,1188,1253, +1189,1253,1188, +1253,1189,1254, +1190,1254,1189, +1254,1190,1255, +1191,1255,1190, +1255,1191,1256, +1192,1256,1191, +1256,1192,1257, +1193,1257,1192, +1257,1193,1258, +1194,1258,1193, +1258,1194,1259, +1195,1259,1194, +1259,1195,1260, +1196,1260,1195, +1260,1196,1261, +1197,1261,1196, +1261,1197,1262, +1198,1262,1197, +1262,1198,1263, +1199,1263,1198, +1263,1199,1264, +1200,1264,1199, +1264,1200,1265, +1201,1265,1200, +1265,1201,1266, +1202,1266,1201, +1266,1202,1267, +1203,1267,1202, +1267,1203,1268, +1204,1268,1203, +1268,1204,1269, +1205,1269,1204, +1269,1205,1270, +1206,1270,1205, +1270,1206,1271, +1207,1271,1206, +1271,1207,1272, +1208,1272,1207, +1272,1208,1273, +1209,1273,1208, +1273,1209,1274, +1210,1274,1209, +1274,1210,1275, +1211,1275,1210, +1275,1211,1276, +1212,1276,1211, +1276,1212,1277, +1213,1277,1212, +1277,1213,1278, +1214,1278,1213, +1278,1214,1279, +1215,1279,1214, +1280,1216,1281, +1217,1281,1216, +1281,1217,1282, +1218,1282,1217, +1282,1218,1283, +1219,1283,1218, +1283,1219,1284, +1220,1284,1219, +1284,1220,1285, +1221,1285,1220, +1285,1221,1286, +1222,1286,1221, +1286,1222,1287, +1223,1287,1222, +1287,1223,1288, +1224,1288,1223, +1288,1224,1289, +1225,1289,1224, +1289,1225,1290, +1226,1290,1225, +1290,1226,1291, +1227,1291,1226, +1291,1227,1292, +1228,1292,1227, +1292,1228,1293, +1229,1293,1228, +1293,1229,1294, +1230,1294,1229, +1294,1230,1295, +1231,1295,1230, +1295,1231,1296, +1232,1296,1231, +1296,1232,1297, +1233,1297,1232, +1297,1233,1298, +1234,1298,1233, +1298,1234,1299, +1235,1299,1234, +1299,1235,1300, +1236,1300,1235, +1300,1236,1301, +1237,1301,1236, +1301,1237,1302, +1238,1302,1237, +1302,1238,1303, +1239,1303,1238, +1303,1239,1304, +1240,1304,1239, +1304,1240,1305, +1241,1305,1240, +1305,1241,1306, +1242,1306,1241, +1306,1242,1307, +1243,1307,1242, +1307,1243,1308, +1244,1308,1243, +1308,1244,1309, +1245,1309,1244, +1309,1245,1310, +1246,1310,1245, +1310,1246,1311, +1247,1311,1246, +1311,1247,1312, +1248,1312,1247, +1312,1248,1313, +1249,1313,1248, +1313,1249,1314, +1250,1314,1249, +1314,1250,1315, +1251,1315,1250, +1315,1251,1316, +1252,1316,1251, +1316,1252,1317, +1253,1317,1252, +1317,1253,1318, +1254,1318,1253, +1318,1254,1319, +1255,1319,1254, +1319,1255,1320, +1256,1320,1255, +1320,1256,1321, +1257,1321,1256, +1321,1257,1322, +1258,1322,1257, +1322,1258,1323, +1259,1323,1258, +1323,1259,1324, +1260,1324,1259, +1324,1260,1325, +1261,1325,1260, +1325,1261,1326, +1262,1326,1261, +1326,1262,1327, +1263,1327,1262, +1327,1263,1328, +1264,1328,1263, +1328,1264,1329, +1265,1329,1264, +1329,1265,1330, +1266,1330,1265, +1330,1266,1331, +1267,1331,1266, +1331,1267,1332, +1268,1332,1267, +1332,1268,1333, +1269,1333,1268, +1333,1269,1334, +1270,1334,1269, +1334,1270,1335, +1271,1335,1270, +1335,1271,1336, +1272,1336,1271, +1336,1272,1337, +1273,1337,1272, +1337,1273,1338, +1274,1338,1273, +1338,1274,1339, +1275,1339,1274, +1339,1275,1340, +1276,1340,1275, +1340,1276,1341, +1277,1341,1276, +1341,1277,1342, +1278,1342,1277, +1342,1278,1343, +1279,1343,1278, +1344,1280,1345, +1281,1345,1280, +1345,1281,1346, +1282,1346,1281, +1346,1282,1347, +1283,1347,1282, +1347,1283,1348, +1284,1348,1283, +1348,1284,1349, +1285,1349,1284, +1349,1285,1350, +1286,1350,1285, +1350,1286,1351, +1287,1351,1286, +1351,1287,1352, +1288,1352,1287, +1352,1288,1353, +1289,1353,1288, +1353,1289,1354, +1290,1354,1289, +1354,1290,1355, +1291,1355,1290, +1355,1291,1356, +1292,1356,1291, +1356,1292,1357, +1293,1357,1292, +1357,1293,1358, +1294,1358,1293, +1358,1294,1359, +1295,1359,1294, +1359,1295,1360, +1296,1360,1295, +1360,1296,1361, +1297,1361,1296, +1361,1297,1362, +1298,1362,1297, +1362,1298,1363, +1299,1363,1298, +1363,1299,1364, +1300,1364,1299, +1364,1300,1365, +1301,1365,1300, +1365,1301,1366, +1302,1366,1301, +1366,1302,1367, +1303,1367,1302, +1367,1303,1368, +1304,1368,1303, +1368,1304,1369, +1305,1369,1304, +1369,1305,1370, +1306,1370,1305, +1370,1306,1371, +1307,1371,1306, +1371,1307,1372, +1308,1372,1307, +1372,1308,1373, +1309,1373,1308, +1373,1309,1374, +1310,1374,1309, +1374,1310,1375, +1311,1375,1310, +1375,1311,1376, +1312,1376,1311, +1376,1312,1377, +1313,1377,1312, +1377,1313,1378, +1314,1378,1313, +1378,1314,1379, +1315,1379,1314, +1379,1315,1380, +1316,1380,1315, +1380,1316,1381, +1317,1381,1316, +1381,1317,1382, +1318,1382,1317, +1382,1318,1383, +1319,1383,1318, +1383,1319,1384, +1320,1384,1319, +1384,1320,1385, +1321,1385,1320, +1385,1321,1386, +1322,1386,1321, +1386,1322,1387, +1323,1387,1322, +1387,1323,1388, +1324,1388,1323, +1388,1324,1389, +1325,1389,1324, +1389,1325,1390, +1326,1390,1325, +1390,1326,1391, +1327,1391,1326, +1391,1327,1392, +1328,1392,1327, +1392,1328,1393, +1329,1393,1328, +1393,1329,1394, +1330,1394,1329, +1394,1330,1395, +1331,1395,1330, +1395,1331,1396, +1332,1396,1331, +1396,1332,1397, +1333,1397,1332, +1397,1333,1398, +1334,1398,1333, +1398,1334,1399, +1335,1399,1334, +1399,1335,1400, +1336,1400,1335, +1400,1336,1401, +1337,1401,1336, +1401,1337,1402, +1338,1402,1337, +1402,1338,1403, +1339,1403,1338, +1403,1339,1404, +1340,1404,1339, +1404,1340,1405, +1341,1405,1340, +1405,1341,1406, +1342,1406,1341, +1406,1342,1407, +1343,1407,1342, +1408,1344,1409, +1345,1409,1344, +1409,1345,1410, +1346,1410,1345, +1410,1346,1411, +1347,1411,1346, +1411,1347,1412, +1348,1412,1347, +1412,1348,1413, +1349,1413,1348, +1413,1349,1414, +1350,1414,1349, +1414,1350,1415, +1351,1415,1350, +1415,1351,1416, +1352,1416,1351, +1416,1352,1417, +1353,1417,1352, +1417,1353,1418, +1354,1418,1353, +1418,1354,1419, +1355,1419,1354, +1419,1355,1420, +1356,1420,1355, +1420,1356,1421, +1357,1421,1356, +1421,1357,1422, +1358,1422,1357, +1422,1358,1423, +1359,1423,1358, +1423,1359,1424, +1360,1424,1359, +1424,1360,1425, +1361,1425,1360, +1425,1361,1426, +1362,1426,1361, +1426,1362,1427, +1363,1427,1362, +1427,1363,1428, +1364,1428,1363, +1428,1364,1429, +1365,1429,1364, +1429,1365,1430, +1366,1430,1365, +1430,1366,1431, +1367,1431,1366, +1431,1367,1432, +1368,1432,1367, +1432,1368,1433, +1369,1433,1368, +1433,1369,1434, +1370,1434,1369, +1434,1370,1435, +1371,1435,1370, +1435,1371,1436, +1372,1436,1371, +1436,1372,1437, +1373,1437,1372, +1437,1373,1438, +1374,1438,1373, +1438,1374,1439, +1375,1439,1374, +1439,1375,1440, +1376,1440,1375, +1440,1376,1441, +1377,1441,1376, +1441,1377,1442, +1378,1442,1377, +1442,1378,1443, +1379,1443,1378, +1443,1379,1444, +1380,1444,1379, +1444,1380,1445, +1381,1445,1380, +1445,1381,1446, +1382,1446,1381, +1446,1382,1447, +1383,1447,1382, +1447,1383,1448, +1384,1448,1383, +1448,1384,1449, +1385,1449,1384, +1449,1385,1450, +1386,1450,1385, +1450,1386,1451, +1387,1451,1386, +1451,1387,1452, +1388,1452,1387, +1452,1388,1453, +1389,1453,1388, +1453,1389,1454, +1390,1454,1389, +1454,1390,1455, +1391,1455,1390, +1455,1391,1456, +1392,1456,1391, +1456,1392,1457, +1393,1457,1392, +1457,1393,1458, +1394,1458,1393, +1458,1394,1459, +1395,1459,1394, +1459,1395,1460, +1396,1460,1395, +1460,1396,1461, +1397,1461,1396, +1461,1397,1462, +1398,1462,1397, +1462,1398,1463, +1399,1463,1398, +1463,1399,1464, +1400,1464,1399, +1464,1400,1465, +1401,1465,1400, +1465,1401,1466, +1402,1466,1401, +1466,1402,1467, +1403,1467,1402, +1467,1403,1468, +1404,1468,1403, +1468,1404,1469, +1405,1469,1404, +1469,1405,1470, +1406,1470,1405, +1470,1406,1471, +1407,1471,1406, +1472,1408,1473, +1409,1473,1408, +1473,1409,1474, +1410,1474,1409, +1474,1410,1475, +1411,1475,1410, +1475,1411,1476, +1412,1476,1411, +1476,1412,1477, +1413,1477,1412, +1477,1413,1478, +1414,1478,1413, +1478,1414,1479, +1415,1479,1414, +1479,1415,1480, +1416,1480,1415, +1480,1416,1481, +1417,1481,1416, +1481,1417,1482, +1418,1482,1417, +1482,1418,1483, +1419,1483,1418, +1483,1419,1484, +1420,1484,1419, +1484,1420,1485, +1421,1485,1420, +1485,1421,1486, +1422,1486,1421, +1486,1422,1487, +1423,1487,1422, +1487,1423,1488, +1424,1488,1423, +1488,1424,1489, +1425,1489,1424, +1489,1425,1490, +1426,1490,1425, +1490,1426,1491, +1427,1491,1426, +1491,1427,1492, +1428,1492,1427, +1492,1428,1493, +1429,1493,1428, +1493,1429,1494, +1430,1494,1429, +1494,1430,1495, +1431,1495,1430, +1495,1431,1496, +1432,1496,1431, +1496,1432,1497, +1433,1497,1432, +1497,1433,1498, +1434,1498,1433, +1498,1434,1499, +1435,1499,1434, +1499,1435,1500, +1436,1500,1435, +1500,1436,1501, +1437,1501,1436, +1501,1437,1502, +1438,1502,1437, +1502,1438,1503, +1439,1503,1438, +1503,1439,1504, +1440,1504,1439, +1504,1440,1505, +1441,1505,1440, +1505,1441,1506, +1442,1506,1441, +1506,1442,1507, +1443,1507,1442, +1507,1443,1508, +1444,1508,1443, +1508,1444,1509, +1445,1509,1444, +1509,1445,1510, +1446,1510,1445, +1510,1446,1511, +1447,1511,1446, +1511,1447,1512, +1448,1512,1447, +1512,1448,1513, +1449,1513,1448, +1513,1449,1514, +1450,1514,1449, +1514,1450,1515, +1451,1515,1450, +1515,1451,1516, +1452,1516,1451, +1516,1452,1517, +1453,1517,1452, +1517,1453,1518, +1454,1518,1453, +1518,1454,1519, +1455,1519,1454, +1519,1455,1520, +1456,1520,1455, +1520,1456,1521, +1457,1521,1456, +1521,1457,1522, +1458,1522,1457, +1522,1458,1523, +1459,1523,1458, +1523,1459,1524, +1460,1524,1459, +1524,1460,1525, +1461,1525,1460, +1525,1461,1526, +1462,1526,1461, +1526,1462,1527, +1463,1527,1462, +1527,1463,1528, +1464,1528,1463, +1528,1464,1529, +1465,1529,1464, +1529,1465,1530, +1466,1530,1465, +1530,1466,1531, +1467,1531,1466, +1531,1467,1532, +1468,1532,1467, +1532,1468,1533, +1469,1533,1468, +1533,1469,1534, +1470,1534,1469, +1534,1470,1535, +1471,1535,1470, +1536,1472,1537, +1473,1537,1472, +1537,1473,1538, +1474,1538,1473, +1538,1474,1539, +1475,1539,1474, +1539,1475,1540, +1476,1540,1475, +1540,1476,1541, +1477,1541,1476, +1541,1477,1542, +1478,1542,1477, +1542,1478,1543, +1479,1543,1478, +1543,1479,1544, +1480,1544,1479, +1544,1480,1545, +1481,1545,1480, +1545,1481,1546, +1482,1546,1481, +1546,1482,1547, +1483,1547,1482, +1547,1483,1548, +1484,1548,1483, +1548,1484,1549, +1485,1549,1484, +1549,1485,1550, +1486,1550,1485, +1550,1486,1551, +1487,1551,1486, +1551,1487,1552, +1488,1552,1487, +1552,1488,1553, +1489,1553,1488, +1553,1489,1554, +1490,1554,1489, +1554,1490,1555, +1491,1555,1490, +1555,1491,1556, +1492,1556,1491, +1556,1492,1557, +1493,1557,1492, +1557,1493,1558, +1494,1558,1493, +1558,1494,1559, +1495,1559,1494, +1559,1495,1560, +1496,1560,1495, +1560,1496,1561, +1497,1561,1496, +1561,1497,1562, +1498,1562,1497, +1562,1498,1563, +1499,1563,1498, +1563,1499,1564, +1500,1564,1499, +1564,1500,1565, +1501,1565,1500, +1565,1501,1566, +1502,1566,1501, +1566,1502,1567, +1503,1567,1502, +1567,1503,1568, +1504,1568,1503, +1568,1504,1569, +1505,1569,1504, +1569,1505,1570, +1506,1570,1505, +1570,1506,1571, +1507,1571,1506, +1571,1507,1572, +1508,1572,1507, +1572,1508,1573, +1509,1573,1508, +1573,1509,1574, +1510,1574,1509, +1574,1510,1575, +1511,1575,1510, +1575,1511,1576, +1512,1576,1511, +1576,1512,1577, +1513,1577,1512, +1577,1513,1578, +1514,1578,1513, +1578,1514,1579, +1515,1579,1514, +1579,1515,1580, +1516,1580,1515, +1580,1516,1581, +1517,1581,1516, +1581,1517,1582, +1518,1582,1517, +1582,1518,1583, +1519,1583,1518, +1583,1519,1584, +1520,1584,1519, +1584,1520,1585, +1521,1585,1520, +1585,1521,1586, +1522,1586,1521, +1586,1522,1587, +1523,1587,1522, +1587,1523,1588, +1524,1588,1523, +1588,1524,1589, +1525,1589,1524, +1589,1525,1590, +1526,1590,1525, +1590,1526,1591, +1527,1591,1526, +1591,1527,1592, +1528,1592,1527, +1592,1528,1593, +1529,1593,1528, +1593,1529,1594, +1530,1594,1529, +1594,1530,1595, +1531,1595,1530, +1595,1531,1596, +1532,1596,1531, +1596,1532,1597, +1533,1597,1532, +1597,1533,1598, +1534,1598,1533, +1598,1534,1599, +1535,1599,1534, +1600,1536,1601, +1537,1601,1536, +1601,1537,1602, +1538,1602,1537, +1602,1538,1603, +1539,1603,1538, +1603,1539,1604, +1540,1604,1539, +1604,1540,1605, +1541,1605,1540, +1605,1541,1606, +1542,1606,1541, +1606,1542,1607, +1543,1607,1542, +1607,1543,1608, +1544,1608,1543, +1608,1544,1609, +1545,1609,1544, +1609,1545,1610, +1546,1610,1545, +1610,1546,1611, +1547,1611,1546, +1611,1547,1612, +1548,1612,1547, +1612,1548,1613, +1549,1613,1548, +1613,1549,1614, +1550,1614,1549, +1614,1550,1615, +1551,1615,1550, +1615,1551,1616, +1552,1616,1551, +1616,1552,1617, +1553,1617,1552, +1617,1553,1618, +1554,1618,1553, +1618,1554,1619, +1555,1619,1554, +1619,1555,1620, +1556,1620,1555, +1620,1556,1621, +1557,1621,1556, +1621,1557,1622, +1558,1622,1557, +1622,1558,1623, +1559,1623,1558, +1623,1559,1624, +1560,1624,1559, +1624,1560,1625, +1561,1625,1560, +1625,1561,1626, +1562,1626,1561, +1626,1562,1627, +1563,1627,1562, +1627,1563,1628, +1564,1628,1563, +1628,1564,1629, +1565,1629,1564, +1629,1565,1630, +1566,1630,1565, +1630,1566,1631, +1567,1631,1566, +1631,1567,1632, +1568,1632,1567, +1632,1568,1633, +1569,1633,1568, +1633,1569,1634, +1570,1634,1569, +1634,1570,1635, +1571,1635,1570, +1635,1571,1636, +1572,1636,1571, +1636,1572,1637, +1573,1637,1572, +1637,1573,1638, +1574,1638,1573, +1638,1574,1639, +1575,1639,1574, +1639,1575,1640, +1576,1640,1575, +1640,1576,1641, +1577,1641,1576, +1641,1577,1642, +1578,1642,1577, +1642,1578,1643, +1579,1643,1578, +1643,1579,1644, +1580,1644,1579, +1644,1580,1645, +1581,1645,1580, +1645,1581,1646, +1582,1646,1581, +1646,1582,1647, +1583,1647,1582, +1647,1583,1648, +1584,1648,1583, +1648,1584,1649, +1585,1649,1584, +1649,1585,1650, +1586,1650,1585, +1650,1586,1651, +1587,1651,1586, +1651,1587,1652, +1588,1652,1587, +1652,1588,1653, +1589,1653,1588, +1653,1589,1654, +1590,1654,1589, +1654,1590,1655, +1591,1655,1590, +1655,1591,1656, +1592,1656,1591, +1656,1592,1657, +1593,1657,1592, +1657,1593,1658, +1594,1658,1593, +1658,1594,1659, +1595,1659,1594, +1659,1595,1660, +1596,1660,1595, +1660,1596,1661, +1597,1661,1596, +1661,1597,1662, +1598,1662,1597, +1662,1598,1663, +1599,1663,1598, +1664,1600,1665, +1601,1665,1600, +1665,1601,1666, +1602,1666,1601, +1666,1602,1667, +1603,1667,1602, +1667,1603,1668, +1604,1668,1603, +1668,1604,1669, +1605,1669,1604, +1669,1605,1670, +1606,1670,1605, +1670,1606,1671, +1607,1671,1606, +1671,1607,1672, +1608,1672,1607, +1672,1608,1673, +1609,1673,1608, +1673,1609,1674, +1610,1674,1609, +1674,1610,1675, +1611,1675,1610, +1675,1611,1676, +1612,1676,1611, +1676,1612,1677, +1613,1677,1612, +1677,1613,1678, +1614,1678,1613, +1678,1614,1679, +1615,1679,1614, +1679,1615,1680, +1616,1680,1615, +1680,1616,1681, +1617,1681,1616, +1681,1617,1682, +1618,1682,1617, +1682,1618,1683, +1619,1683,1618, +1683,1619,1684, +1620,1684,1619, +1684,1620,1685, +1621,1685,1620, +1685,1621,1686, +1622,1686,1621, +1686,1622,1687, +1623,1687,1622, +1687,1623,1688, +1624,1688,1623, +1688,1624,1689, +1625,1689,1624, +1689,1625,1690, +1626,1690,1625, +1690,1626,1691, +1627,1691,1626, +1691,1627,1692, +1628,1692,1627, +1692,1628,1693, +1629,1693,1628, +1693,1629,1694, +1630,1694,1629, +1694,1630,1695, +1631,1695,1630, +1695,1631,1696, +1632,1696,1631, +1696,1632,1697, +1633,1697,1632, +1697,1633,1698, +1634,1698,1633, +1698,1634,1699, +1635,1699,1634, +1699,1635,1700, +1636,1700,1635, +1700,1636,1701, +1637,1701,1636, +1701,1637,1702, +1638,1702,1637, +1702,1638,1703, +1639,1703,1638, +1703,1639,1704, +1640,1704,1639, +1704,1640,1705, +1641,1705,1640, +1705,1641,1706, +1642,1706,1641, +1706,1642,1707, +1643,1707,1642, +1707,1643,1708, +1644,1708,1643, +1708,1644,1709, +1645,1709,1644, +1709,1645,1710, +1646,1710,1645, +1710,1646,1711, +1647,1711,1646, +1711,1647,1712, +1648,1712,1647, +1712,1648,1713, +1649,1713,1648, +1713,1649,1714, +1650,1714,1649, +1714,1650,1715, +1651,1715,1650, +1715,1651,1716, +1652,1716,1651, +1716,1652,1717, +1653,1717,1652, +1717,1653,1718, +1654,1718,1653, +1718,1654,1719, +1655,1719,1654, +1719,1655,1720, +1656,1720,1655, +1720,1656,1721, +1657,1721,1656, +1721,1657,1722, +1658,1722,1657, +1722,1658,1723, +1659,1723,1658, +1723,1659,1724, +1660,1724,1659, +1724,1660,1725, +1661,1725,1660, +1725,1661,1726, +1662,1726,1661, +1726,1662,1727, +1663,1727,1662, +1728,1664,1729, +1665,1729,1664, +1729,1665,1730, +1666,1730,1665, +1730,1666,1731, +1667,1731,1666, +1731,1667,1732, +1668,1732,1667, +1732,1668,1733, +1669,1733,1668, +1733,1669,1734, +1670,1734,1669, +1734,1670,1735, +1671,1735,1670, +1735,1671,1736, +1672,1736,1671, +1736,1672,1737, +1673,1737,1672, +1737,1673,1738, +1674,1738,1673, +1738,1674,1739, +1675,1739,1674, +1739,1675,1740, +1676,1740,1675, +1740,1676,1741, +1677,1741,1676, +1741,1677,1742, +1678,1742,1677, +1742,1678,1743, +1679,1743,1678, +1743,1679,1744, +1680,1744,1679, +1744,1680,1745, +1681,1745,1680, +1745,1681,1746, +1682,1746,1681, +1746,1682,1747, +1683,1747,1682, +1747,1683,1748, +1684,1748,1683, +1748,1684,1749, +1685,1749,1684, +1749,1685,1750, +1686,1750,1685, +1750,1686,1751, +1687,1751,1686, +1751,1687,1752, +1688,1752,1687, +1752,1688,1753, +1689,1753,1688, +1753,1689,1754, +1690,1754,1689, +1754,1690,1755, +1691,1755,1690, +1755,1691,1756, +1692,1756,1691, +1756,1692,1757, +1693,1757,1692, +1757,1693,1758, +1694,1758,1693, +1758,1694,1759, +1695,1759,1694, +1759,1695,1760, +1696,1760,1695, +1760,1696,1761, +1697,1761,1696, +1761,1697,1762, +1698,1762,1697, +1762,1698,1763, +1699,1763,1698, +1763,1699,1764, +1700,1764,1699, +1764,1700,1765, +1701,1765,1700, +1765,1701,1766, +1702,1766,1701, +1766,1702,1767, +1703,1767,1702, +1767,1703,1768, +1704,1768,1703, +1768,1704,1769, +1705,1769,1704, +1769,1705,1770, +1706,1770,1705, +1770,1706,1771, +1707,1771,1706, +1771,1707,1772, +1708,1772,1707, +1772,1708,1773, +1709,1773,1708, +1773,1709,1774, +1710,1774,1709, +1774,1710,1775, +1711,1775,1710, +1775,1711,1776, +1712,1776,1711, +1776,1712,1777, +1713,1777,1712, +1777,1713,1778, +1714,1778,1713, +1778,1714,1779, +1715,1779,1714, +1779,1715,1780, +1716,1780,1715, +1780,1716,1781, +1717,1781,1716, +1781,1717,1782, +1718,1782,1717, +1782,1718,1783, +1719,1783,1718, +1783,1719,1784, +1720,1784,1719, +1784,1720,1785, +1721,1785,1720, +1785,1721,1786, +1722,1786,1721, +1786,1722,1787, +1723,1787,1722, +1787,1723,1788, +1724,1788,1723, +1788,1724,1789, +1725,1789,1724, +1789,1725,1790, +1726,1790,1725, +1790,1726,1791, +1727,1791,1726, +1792,1728,1793, +1729,1793,1728, +1793,1729,1794, +1730,1794,1729, +1794,1730,1795, +1731,1795,1730, +1795,1731,1796, +1732,1796,1731, +1796,1732,1797, +1733,1797,1732, +1797,1733,1798, +1734,1798,1733, +1798,1734,1799, +1735,1799,1734, +1799,1735,1800, +1736,1800,1735, +1800,1736,1801, +1737,1801,1736, +1801,1737,1802, +1738,1802,1737, +1802,1738,1803, +1739,1803,1738, +1803,1739,1804, +1740,1804,1739, +1804,1740,1805, +1741,1805,1740, +1805,1741,1806, +1742,1806,1741, +1806,1742,1807, +1743,1807,1742, +1807,1743,1808, +1744,1808,1743, +1808,1744,1809, +1745,1809,1744, +1809,1745,1810, +1746,1810,1745, +1810,1746,1811, +1747,1811,1746, +1811,1747,1812, +1748,1812,1747, +1812,1748,1813, +1749,1813,1748, +1813,1749,1814, +1750,1814,1749, +1814,1750,1815, +1751,1815,1750, +1815,1751,1816, +1752,1816,1751, +1816,1752,1817, +1753,1817,1752, +1817,1753,1818, +1754,1818,1753, +1818,1754,1819, +1755,1819,1754, +1819,1755,1820, +1756,1820,1755, +1820,1756,1821, +1757,1821,1756, +1821,1757,1822, +1758,1822,1757, +1822,1758,1823, +1759,1823,1758, +1823,1759,1824, +1760,1824,1759, +1824,1760,1825, +1761,1825,1760, +1825,1761,1826, +1762,1826,1761, +1826,1762,1827, +1763,1827,1762, +1827,1763,1828, +1764,1828,1763, +1828,1764,1829, +1765,1829,1764, +1829,1765,1830, +1766,1830,1765, +1830,1766,1831, +1767,1831,1766, +1831,1767,1832, +1768,1832,1767, +1832,1768,1833, +1769,1833,1768, +1833,1769,1834, +1770,1834,1769, +1834,1770,1835, +1771,1835,1770, +1835,1771,1836, +1772,1836,1771, +1836,1772,1837, +1773,1837,1772, +1837,1773,1838, +1774,1838,1773, +1838,1774,1839, +1775,1839,1774, +1839,1775,1840, +1776,1840,1775, +1840,1776,1841, +1777,1841,1776, +1841,1777,1842, +1778,1842,1777, +1842,1778,1843, +1779,1843,1778, +1843,1779,1844, +1780,1844,1779, +1844,1780,1845, +1781,1845,1780, +1845,1781,1846, +1782,1846,1781, +1846,1782,1847, +1783,1847,1782, +1847,1783,1848, +1784,1848,1783, +1848,1784,1849, +1785,1849,1784, +1849,1785,1850, +1786,1850,1785, +1850,1786,1851, +1787,1851,1786, +1851,1787,1852, +1788,1852,1787, +1852,1788,1853, +1789,1853,1788, +1853,1789,1854, +1790,1854,1789, +1854,1790,1855, +1791,1855,1790, +1856,1792,1857, +1793,1857,1792, +1857,1793,1858, +1794,1858,1793, +1858,1794,1859, +1795,1859,1794, +1859,1795,1860, +1796,1860,1795, +1860,1796,1861, +1797,1861,1796, +1861,1797,1862, +1798,1862,1797, +1862,1798,1863, +1799,1863,1798, +1863,1799,1864, +1800,1864,1799, +1864,1800,1865, +1801,1865,1800, +1865,1801,1866, +1802,1866,1801, +1866,1802,1867, +1803,1867,1802, +1867,1803,1868, +1804,1868,1803, +1868,1804,1869, +1805,1869,1804, +1869,1805,1870, +1806,1870,1805, +1870,1806,1871, +1807,1871,1806, +1871,1807,1872, +1808,1872,1807, +1872,1808,1873, +1809,1873,1808, +1873,1809,1874, +1810,1874,1809, +1874,1810,1875, +1811,1875,1810, +1875,1811,1876, +1812,1876,1811, +1876,1812,1877, +1813,1877,1812, +1877,1813,1878, +1814,1878,1813, +1878,1814,1879, +1815,1879,1814, +1879,1815,1880, +1816,1880,1815, +1880,1816,1881, +1817,1881,1816, +1881,1817,1882, +1818,1882,1817, +1882,1818,1883, +1819,1883,1818, +1883,1819,1884, +1820,1884,1819, +1884,1820,1885, +1821,1885,1820, +1885,1821,1886, +1822,1886,1821, +1886,1822,1887, +1823,1887,1822, +1887,1823,1888, +1824,1888,1823, +1888,1824,1889, +1825,1889,1824, +1889,1825,1890, +1826,1890,1825, +1890,1826,1891, +1827,1891,1826, +1891,1827,1892, +1828,1892,1827, +1892,1828,1893, +1829,1893,1828, +1893,1829,1894, +1830,1894,1829, +1894,1830,1895, +1831,1895,1830, +1895,1831,1896, +1832,1896,1831, +1896,1832,1897, +1833,1897,1832, +1897,1833,1898, +1834,1898,1833, +1898,1834,1899, +1835,1899,1834, +1899,1835,1900, +1836,1900,1835, +1900,1836,1901, +1837,1901,1836, +1901,1837,1902, +1838,1902,1837, +1902,1838,1903, +1839,1903,1838, +1903,1839,1904, +1840,1904,1839, +1904,1840,1905, +1841,1905,1840, +1905,1841,1906, +1842,1906,1841, +1906,1842,1907, +1843,1907,1842, +1907,1843,1908, +1844,1908,1843, +1908,1844,1909, +1845,1909,1844, +1909,1845,1910, +1846,1910,1845, +1910,1846,1911, +1847,1911,1846, +1911,1847,1912, +1848,1912,1847, +1912,1848,1913, +1849,1913,1848, +1913,1849,1914, +1850,1914,1849, +1914,1850,1915, +1851,1915,1850, +1915,1851,1916, +1852,1916,1851, +1916,1852,1917, +1853,1917,1852, +1917,1853,1918, +1854,1918,1853, +1918,1854,1919, +1855,1919,1854, +1920,1856,1921, +1857,1921,1856, +1921,1857,1922, +1858,1922,1857, +1922,1858,1923, +1859,1923,1858, +1923,1859,1924, +1860,1924,1859, +1924,1860,1925, +1861,1925,1860, +1925,1861,1926, +1862,1926,1861, +1926,1862,1927, +1863,1927,1862, +1927,1863,1928, +1864,1928,1863, +1928,1864,1929, +1865,1929,1864, +1929,1865,1930, +1866,1930,1865, +1930,1866,1931, +1867,1931,1866, +1931,1867,1932, +1868,1932,1867, +1932,1868,1933, +1869,1933,1868, +1933,1869,1934, +1870,1934,1869, +1934,1870,1935, +1871,1935,1870, +1935,1871,1936, +1872,1936,1871, +1936,1872,1937, +1873,1937,1872, +1937,1873,1938, +1874,1938,1873, +1938,1874,1939, +1875,1939,1874, +1939,1875,1940, +1876,1940,1875, +1940,1876,1941, +1877,1941,1876, +1941,1877,1942, +1878,1942,1877, +1942,1878,1943, +1879,1943,1878, +1943,1879,1944, +1880,1944,1879, +1944,1880,1945, +1881,1945,1880, +1945,1881,1946, +1882,1946,1881, +1946,1882,1947, +1883,1947,1882, +1947,1883,1948, +1884,1948,1883, +1948,1884,1949, +1885,1949,1884, +1949,1885,1950, +1886,1950,1885, +1950,1886,1951, +1887,1951,1886, +1951,1887,1952, +1888,1952,1887, +1952,1888,1953, +1889,1953,1888, +1953,1889,1954, +1890,1954,1889, +1954,1890,1955, +1891,1955,1890, +1955,1891,1956, +1892,1956,1891, +1956,1892,1957, +1893,1957,1892, +1957,1893,1958, +1894,1958,1893, +1958,1894,1959, +1895,1959,1894, +1959,1895,1960, +1896,1960,1895, +1960,1896,1961, +1897,1961,1896, +1961,1897,1962, +1898,1962,1897, +1962,1898,1963, +1899,1963,1898, +1963,1899,1964, +1900,1964,1899, +1964,1900,1965, +1901,1965,1900, +1965,1901,1966, +1902,1966,1901, +1966,1902,1967, +1903,1967,1902, +1967,1903,1968, +1904,1968,1903, +1968,1904,1969, +1905,1969,1904, +1969,1905,1970, +1906,1970,1905, +1970,1906,1971, +1907,1971,1906, +1971,1907,1972, +1908,1972,1907, +1972,1908,1973, +1909,1973,1908, +1973,1909,1974, +1910,1974,1909, +1974,1910,1975, +1911,1975,1910, +1975,1911,1976, +1912,1976,1911, +1976,1912,1977, +1913,1977,1912, +1977,1913,1978, +1914,1978,1913, +1978,1914,1979, +1915,1979,1914, +1979,1915,1980, +1916,1980,1915, +1980,1916,1981, +1917,1981,1916, +1981,1917,1982, +1918,1982,1917, +1982,1918,1983, +1919,1983,1918, +1984,1920,1985, +1921,1985,1920, +1985,1921,1986, +1922,1986,1921, +1986,1922,1987, +1923,1987,1922, +1987,1923,1988, +1924,1988,1923, +1988,1924,1989, +1925,1989,1924, +1989,1925,1990, +1926,1990,1925, +1990,1926,1991, +1927,1991,1926, +1991,1927,1992, +1928,1992,1927, +1992,1928,1993, +1929,1993,1928, +1993,1929,1994, +1930,1994,1929, +1994,1930,1995, +1931,1995,1930, +1995,1931,1996, +1932,1996,1931, +1996,1932,1997, +1933,1997,1932, +1997,1933,1998, +1934,1998,1933, +1998,1934,1999, +1935,1999,1934, +1999,1935,2000, +1936,2000,1935, +2000,1936,2001, +1937,2001,1936, +2001,1937,2002, +1938,2002,1937, +2002,1938,2003, +1939,2003,1938, +2003,1939,2004, +1940,2004,1939, +2004,1940,2005, +1941,2005,1940, +2005,1941,2006, +1942,2006,1941, +2006,1942,2007, +1943,2007,1942, +2007,1943,2008, +1944,2008,1943, +2008,1944,2009, +1945,2009,1944, +2009,1945,2010, +1946,2010,1945, +2010,1946,2011, +1947,2011,1946, +2011,1947,2012, +1948,2012,1947, +2012,1948,2013, +1949,2013,1948, +2013,1949,2014, +1950,2014,1949, +2014,1950,2015, +1951,2015,1950, +2015,1951,2016, +1952,2016,1951, +2016,1952,2017, +1953,2017,1952, +2017,1953,2018, +1954,2018,1953, +2018,1954,2019, +1955,2019,1954, +2019,1955,2020, +1956,2020,1955, +2020,1956,2021, +1957,2021,1956, +2021,1957,2022, +1958,2022,1957, +2022,1958,2023, +1959,2023,1958, +2023,1959,2024, +1960,2024,1959, +2024,1960,2025, +1961,2025,1960, +2025,1961,2026, +1962,2026,1961, +2026,1962,2027, +1963,2027,1962, +2027,1963,2028, +1964,2028,1963, +2028,1964,2029, +1965,2029,1964, +2029,1965,2030, +1966,2030,1965, +2030,1966,2031, +1967,2031,1966, +2031,1967,2032, +1968,2032,1967, +2032,1968,2033, +1969,2033,1968, +2033,1969,2034, +1970,2034,1969, +2034,1970,2035, +1971,2035,1970, +2035,1971,2036, +1972,2036,1971, +2036,1972,2037, +1973,2037,1972, +2037,1973,2038, +1974,2038,1973, +2038,1974,2039, +1975,2039,1974, +2039,1975,2040, +1976,2040,1975, +2040,1976,2041, +1977,2041,1976, +2041,1977,2042, +1978,2042,1977, +2042,1978,2043, +1979,2043,1978, +2043,1979,2044, +1980,2044,1979, +2044,1980,2045, +1981,2045,1980, +2045,1981,2046, +1982,2046,1981, +2046,1982,2047, +1983,2047,1982, +2048,1984,2049, +1985,2049,1984, +2049,1985,2050, +1986,2050,1985, +2050,1986,2051, +1987,2051,1986, +2051,1987,2052, +1988,2052,1987, +2052,1988,2053, +1989,2053,1988, +2053,1989,2054, +1990,2054,1989, +2054,1990,2055, +1991,2055,1990, +2055,1991,2056, +1992,2056,1991, +2056,1992,2057, +1993,2057,1992, +2057,1993,2058, +1994,2058,1993, +2058,1994,2059, +1995,2059,1994, +2059,1995,2060, +1996,2060,1995, +2060,1996,2061, +1997,2061,1996, +2061,1997,2062, +1998,2062,1997, +2062,1998,2063, +1999,2063,1998, +2063,1999,2064, +2000,2064,1999, +2064,2000,2065, +2001,2065,2000, +2065,2001,2066, +2002,2066,2001, +2066,2002,2067, +2003,2067,2002, +2067,2003,2068, +2004,2068,2003, +2068,2004,2069, +2005,2069,2004, +2069,2005,2070, +2006,2070,2005, +2070,2006,2071, +2007,2071,2006, +2071,2007,2072, +2008,2072,2007, +2072,2008,2073, +2009,2073,2008, +2073,2009,2074, +2010,2074,2009, +2074,2010,2075, +2011,2075,2010, +2075,2011,2076, +2012,2076,2011, +2076,2012,2077, +2013,2077,2012, +2077,2013,2078, +2014,2078,2013, +2078,2014,2079, +2015,2079,2014, +2079,2015,2080, +2016,2080,2015, +2080,2016,2081, +2017,2081,2016, +2081,2017,2082, +2018,2082,2017, +2082,2018,2083, +2019,2083,2018, +2083,2019,2084, +2020,2084,2019, +2084,2020,2085, +2021,2085,2020, +2085,2021,2086, +2022,2086,2021, +2086,2022,2087, +2023,2087,2022, +2087,2023,2088, +2024,2088,2023, +2088,2024,2089, +2025,2089,2024, +2089,2025,2090, +2026,2090,2025, +2090,2026,2091, +2027,2091,2026, +2091,2027,2092, +2028,2092,2027, +2092,2028,2093, +2029,2093,2028, +2093,2029,2094, +2030,2094,2029, +2094,2030,2095, +2031,2095,2030, +2095,2031,2096, +2032,2096,2031, +2096,2032,2097, +2033,2097,2032, +2097,2033,2098, +2034,2098,2033, +2098,2034,2099, +2035,2099,2034, +2099,2035,2100, +2036,2100,2035, +2100,2036,2101, +2037,2101,2036, +2101,2037,2102, +2038,2102,2037, +2102,2038,2103, +2039,2103,2038, +2103,2039,2104, +2040,2104,2039, +2104,2040,2105, +2041,2105,2040, +2105,2041,2106, +2042,2106,2041, +2106,2042,2107, +2043,2107,2042, +2107,2043,2108, +2044,2108,2043, +2108,2044,2109, +2045,2109,2044, +2109,2045,2110, +2046,2110,2045, +2110,2046,2111, +2047,2111,2046, +2112,2048,2113, +2049,2113,2048, +2113,2049,2114, +2050,2114,2049, +2114,2050,2115, +2051,2115,2050, +2115,2051,2116, +2052,2116,2051, +2116,2052,2117, +2053,2117,2052, +2117,2053,2118, +2054,2118,2053, +2118,2054,2119, +2055,2119,2054, +2119,2055,2120, +2056,2120,2055, +2120,2056,2121, +2057,2121,2056, +2121,2057,2122, +2058,2122,2057, +2122,2058,2123, +2059,2123,2058, +2123,2059,2124, +2060,2124,2059, +2124,2060,2125, +2061,2125,2060, +2125,2061,2126, +2062,2126,2061, +2126,2062,2127, +2063,2127,2062, +2127,2063,2128, +2064,2128,2063, +2128,2064,2129, +2065,2129,2064, +2129,2065,2130, +2066,2130,2065, +2130,2066,2131, +2067,2131,2066, +2131,2067,2132, +2068,2132,2067, +2132,2068,2133, +2069,2133,2068, +2133,2069,2134, +2070,2134,2069, +2134,2070,2135, +2071,2135,2070, +2135,2071,2136, +2072,2136,2071, +2136,2072,2137, +2073,2137,2072, +2137,2073,2138, +2074,2138,2073, +2138,2074,2139, +2075,2139,2074, +2139,2075,2140, +2076,2140,2075, +2140,2076,2141, +2077,2141,2076, +2141,2077,2142, +2078,2142,2077, +2142,2078,2143, +2079,2143,2078, +2143,2079,2144, +2080,2144,2079, +2144,2080,2145, +2081,2145,2080, +2145,2081,2146, +2082,2146,2081, +2146,2082,2147, +2083,2147,2082, +2147,2083,2148, +2084,2148,2083, +2148,2084,2149, +2085,2149,2084, +2149,2085,2150, +2086,2150,2085, +2150,2086,2151, +2087,2151,2086, +2151,2087,2152, +2088,2152,2087, +2152,2088,2153, +2089,2153,2088, +2153,2089,2154, +2090,2154,2089, +2154,2090,2155, +2091,2155,2090, +2155,2091,2156, +2092,2156,2091, +2156,2092,2157, +2093,2157,2092, +2157,2093,2158, +2094,2158,2093, +2158,2094,2159, +2095,2159,2094, +2159,2095,2160, +2096,2160,2095, +2160,2096,2161, +2097,2161,2096, +2161,2097,2162, +2098,2162,2097, +2162,2098,2163, +2099,2163,2098, +2163,2099,2164, +2100,2164,2099, +2164,2100,2165, +2101,2165,2100, +2165,2101,2166, +2102,2166,2101, +2166,2102,2167, +2103,2167,2102, +2167,2103,2168, +2104,2168,2103, +2168,2104,2169, +2105,2169,2104, +2169,2105,2170, +2106,2170,2105, +2170,2106,2171, +2107,2171,2106, +2171,2107,2172, +2108,2172,2107, +2172,2108,2173, +2109,2173,2108, +2173,2109,2174, +2110,2174,2109, +2174,2110,2175, +2111,2175,2110, +2176,2112,2177, +2113,2177,2112, +2177,2113,2178, +2114,2178,2113, +2178,2114,2179, +2115,2179,2114, +2179,2115,2180, +2116,2180,2115, +2180,2116,2181, +2117,2181,2116, +2181,2117,2182, +2118,2182,2117, +2182,2118,2183, +2119,2183,2118, +2183,2119,2184, +2120,2184,2119, +2184,2120,2185, +2121,2185,2120, +2185,2121,2186, +2122,2186,2121, +2186,2122,2187, +2123,2187,2122, +2187,2123,2188, +2124,2188,2123, +2188,2124,2189, +2125,2189,2124, +2189,2125,2190, +2126,2190,2125, +2190,2126,2191, +2127,2191,2126, +2191,2127,2192, +2128,2192,2127, +2192,2128,2193, +2129,2193,2128, +2193,2129,2194, +2130,2194,2129, +2194,2130,2195, +2131,2195,2130, +2195,2131,2196, +2132,2196,2131, +2196,2132,2197, +2133,2197,2132, +2197,2133,2198, +2134,2198,2133, +2198,2134,2199, +2135,2199,2134, +2199,2135,2200, +2136,2200,2135, +2200,2136,2201, +2137,2201,2136, +2201,2137,2202, +2138,2202,2137, +2202,2138,2203, +2139,2203,2138, +2203,2139,2204, +2140,2204,2139, +2204,2140,2205, +2141,2205,2140, +2205,2141,2206, +2142,2206,2141, +2206,2142,2207, +2143,2207,2142, +2207,2143,2208, +2144,2208,2143, +2208,2144,2209, +2145,2209,2144, +2209,2145,2210, +2146,2210,2145, +2210,2146,2211, +2147,2211,2146, +2211,2147,2212, +2148,2212,2147, +2212,2148,2213, +2149,2213,2148, +2213,2149,2214, +2150,2214,2149, +2214,2150,2215, +2151,2215,2150, +2215,2151,2216, +2152,2216,2151, +2216,2152,2217, +2153,2217,2152, +2217,2153,2218, +2154,2218,2153, +2218,2154,2219, +2155,2219,2154, +2219,2155,2220, +2156,2220,2155, +2220,2156,2221, +2157,2221,2156, +2221,2157,2222, +2158,2222,2157, +2222,2158,2223, +2159,2223,2158, +2223,2159,2224, +2160,2224,2159, +2224,2160,2225, +2161,2225,2160, +2225,2161,2226, +2162,2226,2161, +2226,2162,2227, +2163,2227,2162, +2227,2163,2228, +2164,2228,2163, +2228,2164,2229, +2165,2229,2164, +2229,2165,2230, +2166,2230,2165, +2230,2166,2231, +2167,2231,2166, +2231,2167,2232, +2168,2232,2167, +2232,2168,2233, +2169,2233,2168, +2233,2169,2234, +2170,2234,2169, +2234,2170,2235, +2171,2235,2170, +2235,2171,2236, +2172,2236,2171, +2236,2172,2237, +2173,2237,2172, +2237,2173,2238, +2174,2238,2173, +2238,2174,2239, +2175,2239,2174, +}; + +#define Landscape08VtxCount 2178 +#define Landscape08IdxCount 12480 + +btScalar Landscape08Vtx[] = { +-250.0f,30.98f,-128.906f, +-250.0f,31.4025f,-125.0f, +-246.094f,31.7629f,-128.906f, +-246.094f,31.4165f,-125.0f, +-242.188f,32.5689f,-128.906f, +-242.188f,32.314f,-125.0f, +-238.281f,32.9125f,-128.906f, +-238.281f,32.9822f,-125.0f, +-234.375f,32.5915f,-128.906f, +-234.375f,32.6962f,-125.0f, +-230.469f,31.2708f,-128.906f, +-230.469f,31.3632f,-125.0f, +-226.563f,30.5212f,-128.906f, +-226.563f,29.4391f,-125.0f, +-222.656f,30.2031f,-128.906f, +-222.656f,29.519f,-125.0f, +-218.75f,30.4582f,-128.906f, +-218.75f,29.4481f,-125.0f, +-214.844f,30.6941f,-128.906f, +-214.844f,29.8481f,-125.0f, +-210.938f,30.5035f,-128.906f, +-210.938f,30.408f,-125.0f, +-207.031f,30.2726f,-128.906f, +-207.031f,30.291f,-125.0f, +-203.125f,29.38f,-128.906f, +-203.125f,28.7473f,-125.0f, +-199.219f,28.6973f,-128.906f, +-199.219f,28.1816f,-125.0f, +-195.313f,27.9768f,-128.906f, +-195.313f,27.2839f,-125.0f, +-191.406f,26.1169f,-128.906f, +-191.406f,25.7018f,-125.0f, +-187.5f,23.8648f,-128.906f, +-187.5f,23.2882f,-125.0f, +-183.594f,21.95f,-128.906f, +-183.594f,22.1614f,-125.0f, +-179.688f,19.6798f,-128.906f, +-179.688f,20.658f,-125.0f, +-175.781f,17.3507f,-128.906f, +-175.781f,18.8433f,-125.0f, +-171.875f,15.7914f,-128.906f, +-171.875f,16.364f,-125.0f, +-167.969f,14.3745f,-128.906f, +-167.969f,14.7298f,-125.0f, +-164.063f,12.4911f,-128.906f, +-164.063f,12.9859f,-125.0f, +-160.156f,11.0533f,-128.906f, +-160.156f,11.3306f,-125.0f, +-156.25f,9.15062f,-128.906f, +-156.25f,10.1916f,-125.0f, +-152.344f,6.68059f,-128.906f, +-152.344f,8.3967f,-125.0f, +-148.438f,5.57112f,-128.906f, +-148.438f,6.23292f,-125.0f, +-144.531f,5.2271f,-128.906f, +-144.531f,5.48985f,-125.0f, +-140.625f,5.87576f,-128.906f, +-140.625f,5.18276f,-125.0f, +-136.719f,6.85614f,-128.906f, +-136.719f,5.56059f,-125.0f, +-132.813f,6.86087f,-128.906f, +-132.813f,5.75157f,-125.0f, +-128.906f,7.10341f,-128.906f, +-128.906f,5.32154f,-125.0f, +-125.0f,7.54727f,-128.906f, +-125.0f,6.15672f,-125.0f, +-121.094f,8.02225f,-128.906f, +-121.094f,7.53373f,-125.0f, +-117.188f,8.70065f,-128.906f, +-117.188f,8.38676f,-125.0f, +-113.281f,9.39689f,-128.906f, +-113.281f,8.64274f,-125.0f, +-109.375f,8.80449f,-128.906f, +-109.375f,8.49941f,-125.0f, +-105.469f,9.43366f,-128.906f, +-105.469f,9.24481f,-125.0f, +-101.563f,10.868f,-128.906f, +-101.563f,11.5178f,-125.0f, +-97.6563f,12.8404f,-128.906f, +-97.6563f,13.4113f,-125.0f, +-93.75f,14.8214f,-128.906f, +-93.75f,15.4997f,-125.0f, +-89.8438f,16.618f,-128.906f, +-89.8438f,17.3502f,-125.0f, +-85.9375f,20.2496f,-128.906f, +-85.9375f,20.8168f,-125.0f, +-82.0313f,23.697f,-128.906f, +-82.0313f,24.9405f,-125.0f, +-78.125f,26.4451f,-128.906f, +-78.125f,27.8681f,-125.0f, +-74.2188f,28.7901f,-128.906f, +-74.2188f,30.1495f,-125.0f, +-70.3125f,31.4052f,-128.906f, +-70.3125f,32.4402f,-125.0f, +-66.4063f,33.3106f,-128.906f, +-66.4063f,34.2537f,-125.0f, +-62.5f,35.8538f,-128.906f, +-62.5f,36.5623f,-125.0f, +-58.5938f,37.9798f,-128.906f, +-58.5938f,38.9027f,-125.0f, +-54.6875f,39.4006f,-128.906f, +-54.6875f,40.1192f,-125.0f, +-50.7813f,40.6584f,-128.906f, +-50.7813f,41.9393f,-125.0f, +-46.875f,40.8896f,-128.906f, +-46.875f,41.8765f,-125.0f, +-42.9688f,39.9544f,-128.906f, +-42.9688f,41.6371f,-125.0f, +-39.0625f,40.0893f,-128.906f, +-39.0625f,41.6432f,-125.0f, +-35.1563f,39.3183f,-128.906f, +-35.1563f,41.2852f,-125.0f, +-31.25f,39.8575f,-128.906f, +-31.25f,41.5629f,-125.0f, +-27.3438f,41.5378f,-128.906f, +-27.3438f,42.2956f,-125.0f, +-23.4375f,44.0561f,-128.906f, +-23.4375f,43.9719f,-125.0f, +-19.5313f,45.4298f,-128.906f, +-19.5313f,46.2232f,-125.0f, +-15.625f,47.4474f,-128.906f, +-15.625f,47.3104f,-125.0f, +-11.7188f,48.0018f,-128.906f, +-11.7188f,47.5943f,-125.0f, +-7.8125f,48.0717f,-128.906f, +-7.8125f,49.1192f,-125.0f, +-3.90625f,48.7253f,-128.906f, +-3.90625f,49.6341f,-125.0f, +0.0f,49.8f,-128.906f, +0.0f,50.3481f,-125.0f, +3.90625f,50.4716f,-128.906f, +3.90625f,50.3021f,-125.0f, +-250.0f,31.1145f,-132.813f, +-246.094f,31.857f,-132.813f, +-242.188f,32.7446f,-132.813f, +-238.281f,33.1734f,-132.813f, +-234.375f,32.1952f,-132.813f, +-230.469f,31.8959f,-132.813f, +-226.563f,32.1326f,-132.813f, +-222.656f,32.1631f,-132.813f, +-218.75f,31.3795f,-132.813f, +-214.844f,30.9888f,-132.813f, +-210.938f,30.5577f,-132.813f, +-207.031f,30.1392f,-132.813f, +-203.125f,29.8482f,-132.813f, +-199.219f,28.5903f,-132.813f, +-195.313f,27.4671f,-132.813f, +-191.406f,25.5032f,-132.813f, +-187.5f,23.2799f,-132.813f, +-183.594f,21.2846f,-132.813f, +-179.688f,19.3954f,-132.813f, +-175.781f,18.1112f,-132.813f, +-171.875f,16.3831f,-132.813f, +-167.969f,14.5038f,-132.813f, +-164.063f,12.8109f,-132.813f, +-160.156f,10.386f,-132.813f, +-156.25f,7.93486f,-132.813f, +-152.344f,7.25449f,-132.813f, +-148.438f,6.19974f,-132.813f, +-144.531f,5.89578f,-132.813f, +-140.625f,6.61884f,-132.813f, +-136.719f,7.53382f,-132.813f, +-132.813f,8.21024f,-132.813f, +-128.906f,8.74115f,-132.813f, +-125.0f,8.97047f,-132.813f, +-121.094f,9.41307f,-132.813f, +-117.188f,10.0468f,-132.813f, +-113.281f,9.47404f,-132.813f, +-109.375f,9.418f,-132.813f, +-105.469f,10.3176f,-132.813f, +-101.563f,11.3001f,-132.813f, +-97.6563f,12.5318f,-132.813f, +-93.75f,14.6986f,-132.813f, +-89.8438f,16.6495f,-132.813f, +-85.9375f,19.1906f,-132.813f, +-82.0313f,23.4349f,-132.813f, +-78.125f,26.1629f,-132.813f, +-74.2188f,28.739f,-132.813f, +-70.3125f,31.1271f,-132.813f, +-66.4063f,32.2452f,-132.813f, +-62.5f,34.0303f,-132.813f, +-58.5938f,36.1234f,-132.813f, +-54.6875f,38.3054f,-132.813f, +-50.7813f,38.7936f,-132.813f, +-46.875f,39.1319f,-132.813f, +-42.9688f,39.1462f,-132.813f, +-39.0625f,38.4732f,-132.813f, +-35.1563f,38.3061f,-132.813f, +-31.25f,39.4999f,-132.813f, +-27.3438f,41.8953f,-132.813f, +-23.4375f,43.2645f,-132.813f, +-19.5313f,44.7736f,-132.813f, +-15.625f,46.2491f,-132.813f, +-11.7188f,47.4527f,-132.813f, +-7.8125f,47.1407f,-132.813f, +-3.90625f,48.0628f,-132.813f, +0.0f,48.5651f,-132.813f, +3.90625f,49.1054f,-132.813f, +-250.0f,30.7461f,-136.719f, +-246.094f,30.8483f,-136.719f, +-242.188f,32.188f,-136.719f, +-238.281f,33.149f,-136.719f, +-234.375f,32.3165f,-136.719f, +-230.469f,32.613f,-136.719f, +-226.563f,33.3246f,-136.719f, +-222.656f,32.6429f,-136.719f, +-218.75f,31.8882f,-136.719f, +-214.844f,31.5125f,-136.719f, +-210.938f,30.2065f,-136.719f, +-207.031f,30.0024f,-136.719f, +-203.125f,29.5699f,-136.719f, +-199.219f,28.1245f,-136.719f, +-195.313f,26.764f,-136.719f, +-191.406f,24.8025f,-136.719f, +-187.5f,22.7863f,-136.719f, +-183.594f,21.0979f,-136.719f, +-179.688f,19.5742f,-136.719f, +-175.781f,17.9263f,-136.719f, +-171.875f,16.0908f,-136.719f, +-167.969f,14.6542f,-136.719f, +-164.063f,12.4534f,-136.719f, +-160.156f,9.93763f,-136.719f, +-156.25f,7.87486f,-136.719f, +-152.344f,7.06627f,-136.719f, +-148.438f,6.22453f,-136.719f, +-144.531f,6.39864f,-136.719f, +-140.625f,7.02103f,-136.719f, +-136.719f,7.85488f,-136.719f, +-132.813f,9.33235f,-136.719f, +-128.906f,10.546f,-136.719f, +-125.0f,10.1958f,-136.719f, +-121.094f,9.85385f,-136.719f, +-117.188f,10.2437f,-136.719f, +-113.281f,9.95341f,-136.719f, +-109.375f,9.05387f,-136.719f, +-105.469f,10.3384f,-136.719f, +-101.563f,11.2859f,-136.719f, +-97.6563f,12.3544f,-136.719f, +-93.75f,14.0582f,-136.719f, +-89.8438f,15.9772f,-136.719f, +-85.9375f,18.8673f,-136.719f, +-82.0313f,22.2278f,-136.719f, +-78.125f,25.0468f,-136.719f, +-74.2188f,27.6452f,-136.719f, +-70.3125f,29.155f,-136.719f, +-66.4063f,30.7457f,-136.719f, +-62.5f,32.6722f,-136.719f, +-58.5938f,34.5222f,-136.719f, +-54.6875f,36.3904f,-136.719f, +-50.7813f,36.1946f,-136.719f, +-46.875f,36.5194f,-136.719f, +-42.9688f,36.2715f,-136.719f, +-39.0625f,36.4185f,-136.719f, +-35.1563f,37.1668f,-136.719f, +-31.25f,38.3933f,-136.719f, +-27.3438f,40.8416f,-136.719f, +-23.4375f,42.7243f,-136.719f, +-19.5313f,43.7567f,-136.719f, +-15.625f,44.7705f,-136.719f, +-11.7188f,45.3267f,-136.719f, +-7.8125f,46.433f,-136.719f, +-3.90625f,47.3134f,-136.719f, +0.0f,48.4146f,-136.719f, +3.90625f,47.9f,-136.719f, +-250.0f,29.1575f,-140.625f, +-246.094f,30.5173f,-140.625f, +-242.188f,31.576f,-140.625f, +-238.281f,31.6992f,-140.625f, +-234.375f,32.9063f,-140.625f, +-230.469f,33.2752f,-140.625f, +-226.563f,32.8003f,-140.625f, +-222.656f,33.133f,-140.625f, +-218.75f,32.0543f,-140.625f, +-214.844f,31.2672f,-140.625f, +-210.938f,30.2378f,-140.625f, +-207.031f,29.601f,-140.625f, +-203.125f,28.4643f,-140.625f, +-199.219f,26.8711f,-140.625f, +-195.313f,24.936f,-140.625f, +-191.406f,22.9115f,-140.625f, +-187.5f,21.8507f,-140.625f, +-183.594f,20.4435f,-140.625f, +-179.688f,18.4455f,-140.625f, +-175.781f,17.1667f,-140.625f, +-171.875f,15.2077f,-140.625f, +-167.969f,13.4799f,-140.625f, +-164.063f,11.7723f,-140.625f, +-160.156f,9.26955f,-140.625f, +-156.25f,7.56528f,-140.625f, +-152.344f,6.4244f,-140.625f, +-148.438f,6.60539f,-140.625f, +-144.531f,6.44163f,-140.625f, +-140.625f,6.55017f,-140.625f, +-136.719f,7.62805f,-140.625f, +-132.813f,9.20726f,-140.625f, +-128.906f,10.5063f,-140.625f, +-125.0f,10.6867f,-140.625f, +-121.094f,9.3702f,-140.625f, +-117.188f,9.53484f,-140.625f, +-113.281f,8.855f,-140.625f, +-109.375f,9.3082f,-140.625f, +-105.469f,9.67718f,-140.625f, +-101.563f,10.5233f,-140.625f, +-97.6563f,11.8026f,-140.625f, +-93.75f,13.1675f,-140.625f, +-89.8438f,15.253f,-140.625f, +-85.9375f,18.1074f,-140.625f, +-82.0313f,20.8004f,-140.625f, +-78.125f,23.7651f,-140.625f, +-74.2188f,25.7067f,-140.625f, +-70.3125f,27.5126f,-140.625f, +-66.4063f,29.8191f,-140.625f, +-62.5f,31.7367f,-140.625f, +-58.5938f,32.8891f,-140.625f, +-54.6875f,34.0989f,-140.625f, +-50.7813f,34.6645f,-140.625f, +-46.875f,34.0325f,-140.625f, +-42.9688f,33.7773f,-140.625f, +-39.0625f,34.1723f,-140.625f, +-35.1563f,36.0861f,-140.625f, +-31.25f,38.8562f,-140.625f, +-27.3438f,40.5684f,-140.625f, +-23.4375f,42.6832f,-140.625f, +-19.5313f,43.505f,-140.625f, +-15.625f,43.7197f,-140.625f, +-11.7188f,43.8656f,-140.625f, +-7.8125f,45.6272f,-140.625f, +-3.90625f,46.7713f,-140.625f, +0.0f,47.1255f,-140.625f, +3.90625f,47.2681f,-140.625f, +-250.0f,28.3388f,-144.531f, +-246.094f,29.5689f,-144.531f, +-242.188f,30.0422f,-144.531f, +-238.281f,30.6319f,-144.531f, +-234.375f,32.5914f,-144.531f, +-230.469f,33.306f,-144.531f, +-226.563f,32.9265f,-144.531f, +-222.656f,32.5363f,-144.531f, +-218.75f,31.8845f,-144.531f, +-214.844f,31.7429f,-144.531f, +-210.938f,29.6521f,-144.531f, +-207.031f,28.3301f,-144.531f, +-203.125f,26.8166f,-144.531f, +-199.219f,25.0756f,-144.531f, +-195.313f,23.0988f,-144.531f, +-191.406f,21.2037f,-144.531f, +-187.5f,20.271f,-144.531f, +-183.594f,18.4189f,-144.531f, +-179.688f,16.2352f,-144.531f, +-175.781f,14.734f,-144.531f, +-171.875f,13.9522f,-144.531f, +-167.969f,12.543f,-144.531f, +-164.063f,10.6335f,-144.531f, +-160.156f,8.53885f,-144.531f, +-156.25f,7.32299f,-144.531f, +-152.344f,6.69849f,-144.531f, +-148.438f,5.37792f,-144.531f, +-144.531f,5.52557f,-144.531f, +-140.625f,5.94721f,-144.531f, +-136.719f,7.15949f,-144.531f, +-132.813f,8.5533f,-144.531f, +-128.906f,9.68048f,-144.531f, +-125.0f,9.80421f,-144.531f, +-121.094f,9.67052f,-144.531f, +-117.188f,9.82889f,-144.531f, +-113.281f,9.40895f,-144.531f, +-109.375f,9.53728f,-144.531f, +-105.469f,9.89567f,-144.531f, +-101.563f,10.4472f,-144.531f, +-97.6563f,11.3813f,-144.531f, +-93.75f,13.6687f,-144.531f, +-89.8438f,15.6897f,-144.531f, +-85.9375f,17.6694f,-144.531f, +-82.0313f,20.0542f,-144.531f, +-78.125f,22.2881f,-144.531f, +-74.2188f,24.021f,-144.531f, +-70.3125f,26.6221f,-144.531f, +-66.4063f,28.7647f,-144.531f, +-62.5f,31.0025f,-144.531f, +-58.5938f,31.9212f,-144.531f, +-54.6875f,32.1124f,-144.531f, +-50.7813f,33.4656f,-144.531f, +-46.875f,33.5412f,-144.531f, +-42.9688f,33.5562f,-144.531f, +-39.0625f,34.3563f,-144.531f, +-35.1563f,36.2482f,-144.531f, +-31.25f,37.99f,-144.531f, +-27.3438f,40.3527f,-144.531f, +-23.4375f,42.4204f,-144.531f, +-19.5313f,44.0f,-144.531f, +-15.625f,44.183f,-144.531f, +-11.7188f,44.0185f,-144.531f, +-7.8125f,45.08f,-144.531f, +-3.90625f,45.5784f,-144.531f, +0.0f,44.8122f,-144.531f, +3.90625f,45.2398f,-144.531f, +-250.0f,27.5165f,-148.438f, +-246.094f,28.4707f,-148.438f, +-242.188f,28.8693f,-148.438f, +-238.281f,29.8936f,-148.438f, +-234.375f,30.9982f,-148.438f, +-230.469f,31.9158f,-148.438f, +-226.563f,33.0887f,-148.438f, +-222.656f,32.141f,-148.438f, +-218.75f,31.0388f,-148.438f, +-214.844f,30.5599f,-148.438f, +-210.938f,29.1269f,-148.438f, +-207.031f,26.6179f,-148.438f, +-203.125f,25.2859f,-148.438f, +-199.219f,23.1182f,-148.438f, +-195.313f,21.139f,-148.438f, +-191.406f,19.7044f,-148.438f, +-187.5f,18.4387f,-148.438f, +-183.594f,17.6363f,-148.438f, +-179.688f,15.8724f,-148.438f, +-175.781f,14.454f,-148.438f, +-171.875f,13.2052f,-148.438f, +-167.969f,11.7702f,-148.438f, +-164.063f,10.4965f,-148.438f, +-160.156f,8.29165f,-148.438f, +-156.25f,7.24803f,-148.438f, +-152.344f,6.79621f,-148.438f, +-148.438f,5.48372f,-148.438f, +-144.531f,4.11362f,-148.438f, +-140.625f,4.6586f,-148.438f, +-136.719f,6.20081f,-148.438f, +-132.813f,7.67687f,-148.438f, +-128.906f,9.0742f,-148.438f, +-125.0f,8.8028f,-148.438f, +-121.094f,9.309f,-148.438f, +-117.188f,9.26616f,-148.438f, +-113.281f,9.88711f,-148.438f, +-109.375f,9.19023f,-148.438f, +-105.469f,9.46828f,-148.438f, +-101.563f,10.1584f,-148.438f, +-97.6563f,11.2649f,-148.438f, +-93.75f,13.476f,-148.438f, +-89.8438f,15.8318f,-148.438f, +-85.9375f,17.6136f,-148.438f, +-82.0313f,18.7495f,-148.438f, +-78.125f,20.5385f,-148.438f, +-74.2188f,23.5666f,-148.438f, +-70.3125f,26.2836f,-148.438f, +-66.4063f,28.729f,-148.438f, +-62.5f,30.3854f,-148.438f, +-58.5938f,30.9909f,-148.438f, +-54.6875f,31.4288f,-148.438f, +-50.7813f,31.916f,-148.438f, +-46.875f,32.4745f,-148.438f, +-42.9688f,32.0881f,-148.438f, +-39.0625f,34.0231f,-148.438f, +-35.1563f,35.6432f,-148.438f, +-31.25f,37.6278f,-148.438f, +-27.3438f,39.652f,-148.438f, +-23.4375f,42.3336f,-148.438f, +-19.5313f,43.3336f,-148.438f, +-15.625f,43.9329f,-148.438f, +-11.7188f,43.8742f,-148.438f, +-7.8125f,44.336f,-148.438f, +-3.90625f,44.2738f,-148.438f, +0.0f,42.6429f,-148.438f, +3.90625f,43.4167f,-148.438f, +-250.0f,27.7654f,-152.344f, +-246.094f,28.2588f,-152.344f, +-242.188f,28.0365f,-152.344f, +-238.281f,29.4531f,-152.344f, +-234.375f,31.8507f,-152.344f, +-230.469f,31.9987f,-152.344f, +-226.563f,32.2635f,-152.344f, +-222.656f,32.4573f,-152.344f, +-218.75f,30.3791f,-152.344f, +-214.844f,29.1133f,-152.344f, +-210.938f,27.6466f,-152.344f, +-207.031f,25.5524f,-152.344f, +-203.125f,23.857f,-152.344f, +-199.219f,21.724f,-152.344f, +-195.313f,19.9592f,-152.344f, +-191.406f,18.6648f,-152.344f, +-187.5f,17.3913f,-152.344f, +-183.594f,17.3113f,-152.344f, +-179.688f,15.8776f,-152.344f, +-175.781f,13.7968f,-152.344f, +-171.875f,11.9961f,-152.344f, +-167.969f,10.9315f,-152.344f, +-164.063f,9.24337f,-152.344f, +-160.156f,7.95749f,-152.344f, +-156.25f,6.95525f,-152.344f, +-152.344f,6.523f,-152.344f, +-148.438f,5.62313f,-152.344f, +-144.531f,4.31939f,-152.344f, +-140.625f,3.1203f,-152.344f, +-136.719f,4.98713f,-152.344f, +-132.813f,6.64544f,-152.344f, +-128.906f,7.48658f,-152.344f, +-125.0f,8.08424f,-152.344f, +-121.094f,8.96562f,-152.344f, +-117.188f,9.10159f,-152.344f, +-113.281f,9.38004f,-152.344f, +-109.375f,8.97581f,-152.344f, +-105.469f,8.78511f,-152.344f, +-101.563f,9.76846f,-152.344f, +-97.6563f,10.4299f,-152.344f, +-93.75f,13.6059f,-152.344f, +-89.8438f,16.3193f,-152.344f, +-85.9375f,17.6959f,-152.344f, +-82.0313f,18.5545f,-152.344f, +-78.125f,20.1179f,-152.344f, +-74.2188f,22.929f,-152.344f, +-70.3125f,25.8413f,-152.344f, +-66.4063f,28.4214f,-152.344f, +-62.5f,30.0187f,-152.344f, +-58.5938f,30.4285f,-152.344f, +-54.6875f,30.9236f,-152.344f, +-50.7813f,31.3519f,-152.344f, +-46.875f,31.0939f,-152.344f, +-42.9688f,30.2517f,-152.344f, +-39.0625f,32.8953f,-152.344f, +-35.1563f,34.6998f,-152.344f, +-31.25f,36.8107f,-152.344f, +-27.3438f,38.8491f,-152.344f, +-23.4375f,41.3749f,-152.344f, +-19.5313f,42.0838f,-152.344f, +-15.625f,42.3106f,-152.344f, +-11.7188f,43.9654f,-152.344f, +-7.8125f,44.3642f,-152.344f, +-3.90625f,43.1787f,-152.344f, +0.0f,41.875f,-152.344f, +3.90625f,42.7212f,-152.344f, +-250.0f,27.3076f,-156.25f, +-246.094f,27.8739f,-156.25f, +-242.188f,27.7337f,-156.25f, +-238.281f,28.4499f,-156.25f, +-234.375f,30.5068f,-156.25f, +-230.469f,31.1326f,-156.25f, +-226.563f,32.3149f,-156.25f, +-222.656f,31.2724f,-156.25f, +-218.75f,29.5487f,-156.25f, +-214.844f,26.8408f,-156.25f, +-210.938f,25.2503f,-156.25f, +-207.031f,24.2811f,-156.25f, +-203.125f,23.8635f,-156.25f, +-199.219f,22.2573f,-156.25f, +-195.313f,20.6368f,-156.25f, +-191.406f,19.4922f,-156.25f, +-187.5f,18.0281f,-156.25f, +-183.594f,15.4098f,-156.25f, +-179.688f,13.9176f,-156.25f, +-175.781f,11.8192f,-156.25f, +-171.875f,9.31112f,-156.25f, +-167.969f,8.81167f,-156.25f, +-164.063f,8.04908f,-156.25f, +-160.156f,6.4764f,-156.25f, +-156.25f,5.83656f,-156.25f, +-152.344f,5.70173f,-156.25f, +-148.438f,6.05686f,-156.25f, +-144.531f,3.98364f,-156.25f, +-140.625f,2.80636f,-156.25f, +-136.719f,3.53326f,-156.25f, +-132.813f,4.97177f,-156.25f, +-128.906f,6.71319f,-156.25f, +-125.0f,8.26478f,-156.25f, +-121.094f,9.00909f,-156.25f, +-117.188f,8.8849f,-156.25f, +-113.281f,9.50654f,-156.25f, +-109.375f,9.16878f,-156.25f, +-105.469f,8.84796f,-156.25f, +-101.563f,9.78015f,-156.25f, +-97.6563f,11.1536f,-156.25f, +-93.75f,13.416f,-156.25f, +-89.8438f,15.8674f,-156.25f, +-85.9375f,17.2814f,-156.25f, +-82.0313f,18.1958f,-156.25f, +-78.125f,19.5037f,-156.25f, +-74.2188f,22.0147f,-156.25f, +-70.3125f,24.3288f,-156.25f, +-66.4063f,26.5193f,-156.25f, +-62.5f,27.9571f,-156.25f, +-58.5938f,28.8524f,-156.25f, +-54.6875f,30.6249f,-156.25f, +-50.7813f,30.9824f,-156.25f, +-46.875f,31.0372f,-156.25f, +-42.9688f,30.2189f,-156.25f, +-39.0625f,32.0632f,-156.25f, +-35.1563f,34.0061f,-156.25f, +-31.25f,35.3975f,-156.25f, +-27.3438f,37.8006f,-156.25f, +-23.4375f,40.1384f,-156.25f, +-19.5313f,40.5455f,-156.25f, +-15.625f,41.6044f,-156.25f, +-11.7188f,43.1078f,-156.25f, +-7.8125f,43.5927f,-156.25f, +-3.90625f,43.0245f,-156.25f, +0.0f,41.3824f,-156.25f, +3.90625f,41.7368f,-156.25f, +-250.0f,27.1128f,-160.156f, +-246.094f,26.9845f,-160.156f, +-242.188f,26.7433f,-160.156f, +-238.281f,27.3777f,-160.156f, +-234.375f,29.1743f,-160.156f, +-230.469f,31.0712f,-160.156f, +-226.563f,31.3707f,-160.156f, +-222.656f,30.2327f,-160.156f, +-218.75f,27.897f,-160.156f, +-214.844f,26.4218f,-160.156f, +-210.938f,24.0007f,-160.156f, +-207.031f,23.6445f,-160.156f, +-203.125f,23.6467f,-160.156f, +-199.219f,22.8576f,-160.156f, +-195.313f,20.6778f,-160.156f, +-191.406f,19.3331f,-160.156f, +-187.5f,17.8893f,-160.156f, +-183.594f,14.3376f,-160.156f, +-179.688f,11.9084f,-160.156f, +-175.781f,9.60285f,-160.156f, +-171.875f,7.78231f,-160.156f, +-167.969f,8.15369f,-160.156f, +-164.063f,7.46984f,-160.156f, +-160.156f,6.48522f,-160.156f, +-156.25f,5.27847f,-160.156f, +-152.344f,4.69473f,-160.156f, +-148.438f,5.14018f,-160.156f, +-144.531f,3.26777f,-160.156f, +-140.625f,3.33507f,-160.156f, +-136.719f,2.47156f,-160.156f, +-132.813f,4.15824f,-160.156f, +-128.906f,6.45432f,-160.156f, +-125.0f,7.99373f,-160.156f, +-121.094f,8.38925f,-160.156f, +-117.188f,8.59802f,-160.156f, +-113.281f,9.4891f,-160.156f, +-109.375f,9.20323f,-160.156f, +-105.469f,8.27038f,-160.156f, +-101.563f,9.71848f,-160.156f, +-97.6563f,11.8577f,-160.156f, +-93.75f,14.596f,-160.156f, +-89.8438f,16.1058f,-160.156f, +-85.9375f,17.6531f,-160.156f, +-82.0313f,18.2123f,-160.156f, +-78.125f,18.7175f,-160.156f, +-74.2188f,20.7283f,-160.156f, +-70.3125f,23.5217f,-160.156f, +-66.4063f,26.4239f,-160.156f, +-62.5f,27.757f,-160.156f, +-58.5938f,28.1862f,-160.156f, +-54.6875f,28.9075f,-160.156f, +-50.7813f,29.5287f,-160.156f, +-46.875f,29.3972f,-160.156f, +-42.9688f,29.568f,-160.156f, +-39.0625f,30.605f,-160.156f, +-35.1563f,33.0369f,-160.156f, +-31.25f,34.749f,-160.156f, +-27.3438f,37.4864f,-160.156f, +-23.4375f,39.2291f,-160.156f, +-19.5313f,39.6275f,-160.156f, +-15.625f,39.865f,-160.156f, +-11.7188f,41.1833f,-160.156f, +-7.8125f,41.7789f,-160.156f, +-3.90625f,41.6972f,-160.156f, +0.0f,40.379f,-160.156f, +3.90625f,40.4755f,-160.156f, +-250.0f,26.3982f,-164.063f, +-246.094f,26.3606f,-164.063f, +-242.188f,26.6508f,-164.063f, +-238.281f,27.2228f,-164.063f, +-234.375f,29.1682f,-164.063f, +-230.469f,30.116f,-164.063f, +-226.563f,30.3591f,-164.063f, +-222.656f,28.8713f,-164.063f, +-218.75f,26.8459f,-164.063f, +-214.844f,24.9771f,-164.063f, +-210.938f,24.4581f,-164.063f, +-207.031f,23.6584f,-164.063f, +-203.125f,22.7316f,-164.063f, +-199.219f,21.1836f,-164.063f, +-195.313f,19.6131f,-164.063f, +-191.406f,18.5182f,-164.063f, +-187.5f,16.824f,-164.063f, +-183.594f,13.8772f,-164.063f, +-179.688f,10.3923f,-164.063f, +-175.781f,7.50643f,-164.063f, +-171.875f,6.58466f,-164.063f, +-167.969f,6.81413f,-164.063f, +-164.063f,6.88249f,-164.063f, +-160.156f,6.78655f,-164.063f, +-156.25f,5.18348f,-164.063f, +-152.344f,4.44173f,-164.063f, +-148.438f,4.56392f,-164.063f, +-144.531f,3.00722f,-164.063f, +-140.625f,2.88808f,-164.063f, +-136.719f,2.58477f,-164.063f, +-132.813f,3.20911f,-164.063f, +-128.906f,5.33043f,-164.063f, +-125.0f,6.73698f,-164.063f, +-121.094f,7.71971f,-164.063f, +-117.188f,8.44689f,-164.063f, +-113.281f,9.05366f,-164.063f, +-109.375f,8.81111f,-164.063f, +-105.469f,7.75706f,-164.063f, +-101.563f,11.1131f,-164.063f, +-97.6563f,12.8283f,-164.063f, +-93.75f,14.7771f,-164.063f, +-89.8438f,16.181f,-164.063f, +-85.9375f,17.4228f,-164.063f, +-82.0313f,18.5185f,-164.063f, +-78.125f,19.3122f,-164.063f, +-74.2188f,20.1572f,-164.063f, +-70.3125f,22.741f,-164.063f, +-66.4063f,24.5911f,-164.063f, +-62.5f,26.3846f,-164.063f, +-58.5938f,26.7315f,-164.063f, +-54.6875f,27.0842f,-164.063f, +-50.7813f,28.7654f,-164.063f, +-46.875f,28.7233f,-164.063f, +-42.9688f,29.2872f,-164.063f, +-39.0625f,29.4838f,-164.063f, +-35.1563f,32.7848f,-164.063f, +-31.25f,34.771f,-164.063f, +-27.3438f,36.568f,-164.063f, +-23.4375f,37.5518f,-164.063f, +-19.5313f,38.4106f,-164.063f, +-15.625f,39.2979f,-164.063f, +-11.7188f,39.3573f,-164.063f, +-7.8125f,40.0034f,-164.063f, +-3.90625f,39.5971f,-164.063f, +0.0f,38.8676f,-164.063f, +3.90625f,38.8633f,-164.063f, +-250.0f,25.2893f,-167.969f, +-246.094f,25.108f,-167.969f, +-242.188f,25.5028f,-167.969f, +-238.281f,26.6095f,-167.969f, +-234.375f,28.3221f,-167.969f, +-230.469f,28.5453f,-167.969f, +-226.563f,28.2595f,-167.969f, +-222.656f,26.8423f,-167.969f, +-218.75f,25.0092f,-167.969f, +-214.844f,24.2925f,-167.969f, +-210.938f,23.8404f,-167.969f, +-207.031f,22.7515f,-167.969f, +-203.125f,22.5332f,-167.969f, +-199.219f,20.3284f,-167.969f, +-195.313f,18.8238f,-167.969f, +-191.406f,17.0096f,-167.969f, +-187.5f,14.7741f,-167.969f, +-183.594f,12.4233f,-167.969f, +-179.688f,9.35872f,-167.969f, +-175.781f,6.39156f,-167.969f, +-171.875f,4.97533f,-167.969f, +-167.969f,4.85484f,-167.969f, +-164.063f,5.54727f,-167.969f, +-160.156f,5.08595f,-167.969f, +-156.25f,3.82379f,-167.969f, +-152.344f,3.95751f,-167.969f, +-148.438f,4.60866f,-167.969f, +-144.531f,3.48771f,-167.969f, +-140.625f,3.26748f,-167.969f, +-136.719f,1.87672f,-167.969f, +-132.813f,2.70232f,-167.969f, +-128.906f,4.51339f,-167.969f, +-125.0f,6.0309f,-167.969f, +-121.094f,7.41076f,-167.969f, +-117.188f,7.44121f,-167.969f, +-113.281f,7.50774f,-167.969f, +-109.375f,6.89121f,-167.969f, +-105.469f,8.13035f,-167.969f, +-101.563f,11.7503f,-167.969f, +-97.6563f,14.1358f,-167.969f, +-93.75f,15.4553f,-167.969f, +-89.8438f,16.6233f,-167.969f, +-85.9375f,16.9002f,-167.969f, +-82.0313f,18.4951f,-167.969f, +-78.125f,19.0947f,-167.969f, +-74.2188f,20.0506f,-167.969f, +-70.3125f,20.9426f,-167.969f, +-66.4063f,22.9738f,-167.969f, +-62.5f,24.6229f,-167.969f, +-58.5938f,26.446f,-167.969f, +-54.6875f,26.6448f,-167.969f, +-50.7813f,26.7349f,-167.969f, +-46.875f,28.1266f,-167.969f, +-42.9688f,29.6034f,-167.969f, +-39.0625f,30.3572f,-167.969f, +-35.1563f,31.5467f,-167.969f, +-31.25f,33.6878f,-167.969f, +-27.3438f,35.587f,-167.969f, +-23.4375f,36.0939f,-167.969f, +-19.5313f,37.5008f,-167.969f, +-15.625f,38.2137f,-167.969f, +-11.7188f,38.0843f,-167.969f, +-7.8125f,38.5726f,-167.969f, +-3.90625f,38.3565f,-167.969f, +0.0f,37.8848f,-167.969f, +3.90625f,37.2199f,-167.969f, +-250.0f,24.1398f,-171.875f, +-246.094f,23.8227f,-171.875f, +-242.188f,24.7818f,-171.875f, +-238.281f,26.1053f,-171.875f, +-234.375f,26.9542f,-171.875f, +-230.469f,26.4956f,-171.875f, +-226.563f,25.4866f,-171.875f, +-222.656f,24.7397f,-171.875f, +-218.75f,23.4337f,-171.875f, +-214.844f,23.2342f,-171.875f, +-210.938f,22.1055f,-171.875f, +-207.031f,20.7279f,-171.875f, +-203.125f,20.7273f,-171.875f, +-199.219f,19.1302f,-171.875f, +-195.313f,16.3679f,-171.875f, +-191.406f,14.4548f,-171.875f, +-187.5f,12.5085f,-171.875f, +-183.594f,10.0081f,-171.875f, +-179.688f,7.8572f,-171.875f, +-175.781f,4.38151f,-171.875f, +-171.875f,3.2342f,-171.875f, +-167.969f,3.37553f,-171.875f, +-164.063f,3.90509f,-171.875f, +-160.156f,3.26335f,-171.875f, +-156.25f,2.88438f,-171.875f, +-152.344f,4.22045f,-171.875f, +-148.438f,3.83297f,-171.875f, +-144.531f,2.98648f,-171.875f, +-140.625f,2.83916f,-171.875f, +-136.719f,1.97368f,-171.875f, +-132.813f,1.85909f,-171.875f, +-128.906f,3.2051f,-171.875f, +-125.0f,5.12684f,-171.875f, +-121.094f,5.86909f,-171.875f, +-117.188f,6.45429f,-171.875f, +-113.281f,6.28889f,-171.875f, +-109.375f,7.53536f,-171.875f, +-105.469f,9.44844f,-171.875f, +-101.563f,11.4162f,-171.875f, +-97.6563f,13.7412f,-171.875f, +-93.75f,14.8315f,-171.875f, +-89.8438f,15.4968f,-171.875f, +-85.9375f,16.3468f,-171.875f, +-82.0313f,18.2605f,-171.875f, +-78.125f,18.0829f,-171.875f, +-74.2188f,18.1489f,-171.875f, +-70.3125f,20.6678f,-171.875f, +-66.4063f,23.1234f,-171.875f, +-62.5f,24.4247f,-171.875f, +-58.5938f,26.5223f,-171.875f, +-54.6875f,26.4286f,-171.875f, +-50.7813f,26.7163f,-171.875f, +-46.875f,28.0436f,-171.875f, +-42.9688f,29.6821f,-171.875f, +-39.0625f,30.721f,-171.875f, +-35.1563f,31.1869f,-171.875f, +-31.25f,32.2507f,-171.875f, +-27.3438f,33.3898f,-171.875f, +-23.4375f,33.9008f,-171.875f, +-19.5313f,34.8028f,-171.875f, +-15.625f,35.7178f,-171.875f, +-11.7188f,35.7796f,-171.875f, +-7.8125f,35.6384f,-171.875f, +-3.90625f,35.5122f,-171.875f, +0.0f,35.5973f,-171.875f, +3.90625f,35.3898f,-171.875f, +-250.0f,23.4472f,-175.781f, +-246.094f,24.0295f,-175.781f, +-242.188f,25.0451f,-175.781f, +-238.281f,25.8985f,-175.781f, +-234.375f,26.561f,-175.781f, +-230.469f,25.8342f,-175.781f, +-226.563f,24.8466f,-175.781f, +-222.656f,24.9204f,-175.781f, +-218.75f,23.1933f,-175.781f, +-214.844f,22.3916f,-175.781f, +-210.938f,20.9595f,-175.781f, +-207.031f,19.4013f,-175.781f, +-203.125f,18.3359f,-175.781f, +-199.219f,16.2135f,-175.781f, +-195.313f,14.3022f,-175.781f, +-191.406f,12.4792f,-175.781f, +-187.5f,10.1621f,-175.781f, +-183.594f,7.8368f,-175.781f, +-179.688f,5.59407f,-175.781f, +-175.781f,3.47332f,-175.781f, +-171.875f,2.4167f,-175.781f, +-167.969f,2.13794f,-175.781f, +-164.063f,2.36632f,-175.781f, +-160.156f,2.44955f,-175.781f, +-156.25f,2.40042f,-175.781f, +-152.344f,3.0142f,-175.781f, +-148.438f,2.58304f,-175.781f, +-144.531f,3.06221f,-175.781f, +-140.625f,2.8937f,-175.781f, +-136.719f,2.59115f,-175.781f, +-132.813f,2.27806f,-175.781f, +-128.906f,3.67695f,-175.781f, +-125.0f,5.23254f,-175.781f, +-121.094f,6.12339f,-175.781f, +-117.188f,6.24689f,-175.781f, +-113.281f,6.79282f,-175.781f, +-109.375f,7.83542f,-175.781f, +-105.469f,9.33972f,-175.781f, +-101.563f,11.2701f,-175.781f, +-97.6563f,13.0689f,-175.781f, +-93.75f,13.927f,-175.781f, +-89.8438f,14.9788f,-175.781f, +-85.9375f,15.6647f,-175.781f, +-82.0313f,16.3833f,-175.781f, +-78.125f,16.1061f,-175.781f, +-74.2188f,17.7393f,-175.781f, +-70.3125f,19.8808f,-175.781f, +-66.4063f,22.2751f,-175.781f, +-62.5f,23.8491f,-175.781f, +-58.5938f,25.3344f,-175.781f, +-54.6875f,26.6818f,-175.781f, +-50.7813f,27.9151f,-175.781f, +-46.875f,28.5054f,-175.781f, +-42.9688f,29.7057f,-175.781f, +-39.0625f,30.623f,-175.781f, +-35.1563f,31.5341f,-175.781f, +-31.25f,31.663f,-175.781f, +-27.3438f,31.1886f,-175.781f, +-23.4375f,31.5377f,-175.781f, +-19.5313f,31.9508f,-175.781f, +-15.625f,32.9549f,-175.781f, +-11.7188f,33.7731f,-175.781f, +-7.8125f,33.8023f,-175.781f, +-3.90625f,34.5283f,-175.781f, +0.0f,34.7929f,-175.781f, +3.90625f,34.823f,-175.781f, +-250.0f,22.2698f,-179.688f, +-246.094f,23.7669f,-179.688f, +-242.188f,24.59f,-179.688f, +-238.281f,26.1637f,-179.688f, +-234.375f,25.5266f,-179.688f, +-230.469f,24.4911f,-179.688f, +-226.563f,24.894f,-179.688f, +-222.656f,23.7469f,-179.688f, +-218.75f,22.9663f,-179.688f, +-214.844f,20.6574f,-179.688f, +-210.938f,19.2502f,-179.688f, +-207.031f,17.3967f,-179.688f, +-203.125f,15.9684f,-179.688f, +-199.219f,13.2948f,-179.688f, +-195.313f,11.9318f,-179.688f, +-191.406f,9.64213f,-179.688f, +-187.5f,7.9435f,-179.688f, +-183.594f,6.1917f,-179.688f, +-179.688f,4.0394f,-179.688f, +-175.781f,1.9267f,-179.688f, +-171.875f,1.73477f,-179.688f, +-167.969f,0.994442f,-179.688f, +-164.063f,0.99617f,-179.688f, +-160.156f,1.00048f,-179.688f, +-156.25f,1.54446f,-179.688f, +-152.344f,0.849521f,-179.688f, +-148.438f,1.3046f,-179.688f, +-144.531f,1.38519f,-179.688f, +-140.625f,0.916628f,-179.688f, +-136.719f,1.39685f,-179.688f, +-132.813f,2.17945f,-179.688f, +-128.906f,4.01973f,-179.688f, +-125.0f,5.72989f,-179.688f, +-121.094f,7.24268f,-179.688f, +-117.188f,7.06199f,-179.688f, +-113.281f,7.91292f,-179.688f, +-109.375f,7.8138f,-179.688f, +-105.469f,10.102f,-179.688f, +-101.563f,11.8106f,-179.688f, +-97.6563f,12.9642f,-179.688f, +-93.75f,13.5879f,-179.688f, +-89.8438f,13.4552f,-179.688f, +-85.9375f,14.1844f,-179.688f, +-82.0313f,14.3802f,-179.688f, +-78.125f,15.3847f,-179.688f, +-74.2188f,17.2288f,-179.688f, +-70.3125f,18.9285f,-179.688f, +-66.4063f,20.0035f,-179.688f, +-62.5f,22.2672f,-179.688f, +-58.5938f,25.1262f,-179.688f, +-54.6875f,27.2745f,-179.688f, +-50.7813f,28.2648f,-179.688f, +-46.875f,29.3825f,-179.688f, +-42.9688f,30.2137f,-179.688f, +-39.0625f,31.3826f,-179.688f, +-35.1563f,31.25f,-179.688f, +-31.25f,31.0392f,-179.688f, +-27.3438f,30.3369f,-179.688f, +-23.4375f,30.5503f,-179.688f, +-19.5313f,30.9715f,-179.688f, +-15.625f,31.8287f,-179.688f, +-11.7188f,32.1393f,-179.688f, +-7.8125f,32.0725f,-179.688f, +-3.90625f,32.6574f,-179.688f, +0.0f,32.8889f,-179.688f, +3.90625f,32.9461f,-179.688f, +-250.0f,22.3874f,-183.594f, +-246.094f,22.8072f,-183.594f, +-242.188f,23.1353f,-183.594f, +-238.281f,24.0949f,-183.594f, +-234.375f,24.0026f,-183.594f, +-230.469f,23.458f,-183.594f, +-226.563f,23.872f,-183.594f, +-222.656f,22.969f,-183.594f, +-218.75f,21.8375f,-183.594f, +-214.844f,19.9316f,-183.594f, +-210.938f,16.812f,-183.594f, +-207.031f,15.1789f,-183.594f, +-203.125f,13.7876f,-183.594f, +-199.219f,11.6818f,-183.594f, +-195.313f,9.75291f,-183.594f, +-191.406f,7.08878f,-183.594f, +-187.5f,6.43001f,-183.594f, +-183.594f,5.15238f,-183.594f, +-179.688f,3.77653f,-183.594f, +-175.781f,3.01737f,-183.594f, +-171.875f,1.46355f,-183.594f, +-167.969f,0.767798f,-183.594f, +-164.063f,1.98474f,-183.594f, +-160.156f,1.09473f,-183.594f, +-156.25f,1.29857f,-183.594f, +-152.344f,-0.203491f,-183.594f, +-148.438f,-0.506199f,-183.594f, +-144.531f,-0.678603f,-183.594f, +-140.625f,0.165814f,-183.594f, +-136.719f,1.44759f,-183.594f, +-132.813f,1.43337f,-183.594f, +-128.906f,3.23614f,-183.594f, +-125.0f,4.8541f,-183.594f, +-121.094f,6.64038f,-183.594f, +-117.188f,7.96432f,-183.594f, +-113.281f,8.52594f,-183.594f, +-109.375f,7.78399f,-183.594f, +-105.469f,9.45422f,-183.594f, +-101.563f,11.3198f,-183.594f, +-97.6563f,12.2369f,-183.594f, +-93.75f,12.7733f,-183.594f, +-89.8438f,12.9184f,-183.594f, +-85.9375f,12.958f,-183.594f, +-82.0313f,13.3326f,-183.594f, +-78.125f,14.3984f,-183.594f, +-74.2188f,16.2737f,-183.594f, +-70.3125f,17.9981f,-183.594f, +-66.4063f,19.5314f,-183.594f, +-62.5f,21.4039f,-183.594f, +-58.5938f,24.8945f,-183.594f, +-54.6875f,26.9904f,-183.594f, +-50.7813f,28.6222f,-183.594f, +-46.875f,30.2128f,-183.594f, +-42.9688f,30.5142f,-183.594f, +-39.0625f,30.7026f,-183.594f, +-35.1563f,30.6413f,-183.594f, +-31.25f,29.7659f,-183.594f, +-27.3438f,30.2613f,-183.594f, +-23.4375f,31.0694f,-183.594f, +-19.5313f,31.0437f,-183.594f, +-15.625f,30.9824f,-183.594f, +-11.7188f,30.4648f,-183.594f, +-7.8125f,30.0916f,-183.594f, +-3.90625f,30.0801f,-183.594f, +0.0f,29.9992f,-183.594f, +3.90625f,30.0027f,-183.594f, +-250.0f,22.2829f,-187.5f, +-246.094f,23.1567f,-187.5f, +-242.188f,23.2229f,-187.5f, +-238.281f,23.6644f,-187.5f, +-234.375f,23.5148f,-187.5f, +-230.469f,22.8756f,-187.5f, +-226.563f,22.2471f,-187.5f, +-222.656f,21.4292f,-187.5f, +-218.75f,20.4108f,-187.5f, +-214.844f,18.2601f,-187.5f, +-210.938f,16.3575f,-187.5f, +-207.031f,13.0762f,-187.5f, +-203.125f,11.5916f,-187.5f, +-199.219f,9.81885f,-187.5f, +-195.313f,8.57193f,-187.5f, +-191.406f,5.93865f,-187.5f, +-187.5f,5.15801f,-187.5f, +-183.594f,3.89597f,-187.5f, +-179.688f,4.52236f,-187.5f, +-175.781f,4.21162f,-187.5f, +-171.875f,2.62521f,-187.5f, +-167.969f,1.85733f,-187.5f, +-164.063f,2.14119f,-187.5f, +-160.156f,2.60992f,-187.5f, +-156.25f,1.99742f,-187.5f, +-152.344f,0.836315f,-187.5f, +-148.438f,-0.122141f,-187.5f, +-144.531f,-1.21041f,-187.5f, +-140.625f,0.620409f,-187.5f, +-136.719f,2.20372f,-187.5f, +-132.813f,2.55457f,-187.5f, +-128.906f,3.09944f,-187.5f, +-125.0f,4.76219f,-187.5f, +-121.094f,6.5939f,-187.5f, +-117.188f,7.40657f,-187.5f, +-113.281f,8.17096f,-187.5f, +-109.375f,8.8965f,-187.5f, +-105.469f,9.54116f,-187.5f, +-101.563f,10.8183f,-187.5f, +-97.6563f,12.2345f,-187.5f, +-93.75f,11.945f,-187.5f, +-89.8438f,12.3063f,-187.5f, +-85.9375f,12.7736f,-187.5f, +-82.0313f,13.2581f,-187.5f, +-78.125f,14.2241f,-187.5f, +-74.2188f,15.1957f,-187.5f, +-70.3125f,17.7241f,-187.5f, +-66.4063f,21.0931f,-187.5f, +-62.5f,23.7741f,-187.5f, +-58.5938f,24.8775f,-187.5f, +-54.6875f,26.5924f,-187.5f, +-50.7813f,28.0699f,-187.5f, +-46.875f,30.1552f,-187.5f, +-42.9688f,30.8508f,-187.5f, +-39.0625f,30.7935f,-187.5f, +-35.1563f,30.3224f,-187.5f, +-31.25f,28.8455f,-187.5f, +-27.3438f,30.2059f,-187.5f, +-23.4375f,31.5456f,-187.5f, +-19.5313f,31.0657f,-187.5f, +-15.625f,30.5686f,-187.5f, +-11.7188f,29.9754f,-187.5f, +-7.8125f,28.7754f,-187.5f, +-3.90625f,28.2457f,-187.5f, +0.0f,27.4045f,-187.5f, +3.90625f,27.6405f,-187.5f, +-250.0f,21.5096f,-191.406f, +-246.094f,22.1931f,-191.406f, +-242.188f,22.416f,-191.406f, +-238.281f,22.619f,-191.406f, +-234.375f,22.9242f,-191.406f, +-230.469f,22.6042f,-191.406f, +-226.563f,21.5344f,-191.406f, +-222.656f,20.226f,-191.406f, +-218.75f,19.6198f,-191.406f, +-214.844f,18.0849f,-191.406f, +-210.938f,15.9896f,-191.406f, +-207.031f,12.7402f,-191.406f, +-203.125f,9.98899f,-191.406f, +-199.219f,7.38602f,-191.406f, +-195.313f,6.23078f,-191.406f, +-191.406f,4.8714f,-191.406f, +-187.5f,4.87792f,-191.406f, +-183.594f,4.53381f,-191.406f, +-179.688f,5.23517f,-191.406f, +-175.781f,4.22349f,-191.406f, +-171.875f,3.46214f,-191.406f, +-167.969f,3.62202f,-191.406f, +-164.063f,3.07142f,-191.406f, +-160.156f,3.69893f,-191.406f, +-156.25f,4.20827f,-191.406f, +-152.344f,2.23654f,-191.406f, +-148.438f,0.582121f,-191.406f, +-144.531f,0.44941f,-191.406f, +-140.625f,2.42446f,-191.406f, +-136.719f,3.54807f,-191.406f, +-132.813f,3.58143f,-191.406f, +-128.906f,4.42162f,-191.406f, +-125.0f,5.24153f,-191.406f, +-121.094f,6.55792f,-191.406f, +-117.188f,6.93471f,-191.406f, +-113.281f,7.73309f,-191.406f, +-109.375f,8.04468f,-191.406f, +-105.469f,9.15528f,-191.406f, +-101.563f,10.9583f,-191.406f, +-97.6563f,12.1897f,-191.406f, +-93.75f,11.6481f,-191.406f, +-89.8438f,11.6514f,-191.406f, +-85.9375f,12.4326f,-191.406f, +-82.0313f,13.3808f,-191.406f, +-78.125f,14.386f,-191.406f, +-74.2188f,16.182f,-191.406f, +-70.3125f,18.9931f,-191.406f, +-66.4063f,22.8308f,-191.406f, +-62.5f,25.3868f,-191.406f, +-58.5938f,26.1484f,-191.406f, +-54.6875f,25.6258f,-191.406f, +-50.7813f,26.9464f,-191.406f, +-46.875f,29.0075f,-191.406f, +-42.9688f,29.8523f,-191.406f, +-39.0625f,30.1236f,-191.406f, +-35.1563f,29.7557f,-191.406f, +-31.25f,28.4913f,-191.406f, +-27.3438f,29.5389f,-191.406f, +-23.4375f,30.4685f,-191.406f, +-19.5313f,30.3743f,-191.406f, +-15.625f,30.3762f,-191.406f, +-11.7188f,29.0099f,-191.406f, +-7.8125f,28.1952f,-191.406f, +-3.90625f,26.135f,-191.406f, +0.0f,25.2418f,-191.406f, +3.90625f,25.3652f,-191.406f, +-250.0f,20.78f,-195.313f, +-246.094f,20.8279f,-195.313f, +-242.188f,21.2199f,-195.313f, +-238.281f,22.0652f,-195.313f, +-234.375f,22.2095f,-195.313f, +-230.469f,22.1372f,-195.313f, +-226.563f,21.0165f,-195.313f, +-222.656f,19.4174f,-195.313f, +-218.75f,17.7927f,-195.313f, +-214.844f,16.6172f,-195.313f, +-210.938f,14.7065f,-195.313f, +-207.031f,11.8095f,-195.313f, +-203.125f,9.63824f,-195.313f, +-199.219f,6.4991f,-195.313f, +-195.313f,6.23707f,-195.313f, +-191.406f,6.60374f,-195.313f, +-187.5f,6.22557f,-195.313f, +-183.594f,5.47951f,-195.313f, +-179.688f,5.16851f,-195.313f, +-175.781f,4.83538f,-195.313f, +-171.875f,4.16992f,-195.313f, +-167.969f,5.40533f,-195.313f, +-164.063f,5.01562f,-195.313f, +-160.156f,4.58978f,-195.313f, +-156.25f,4.73252f,-195.313f, +-152.344f,3.14586f,-195.313f, +-148.438f,1.16894f,-195.313f, +-144.531f,2.4916f,-195.313f, +-140.625f,3.98933f,-195.313f, +-136.719f,5.16861f,-195.313f, +-132.813f,5.68931f,-195.313f, +-128.906f,5.45815f,-195.313f, +-125.0f,5.15506f,-195.313f, +-121.094f,6.46153f,-195.313f, +-117.188f,7.36577f,-195.313f, +-113.281f,8.13491f,-195.313f, +-109.375f,7.50896f,-195.313f, +-105.469f,8.93662f,-195.313f, +-101.563f,10.6513f,-195.313f, +-97.6563f,10.6255f,-195.313f, +-93.75f,10.5332f,-195.313f, +-89.8438f,11.5758f,-195.313f, +-85.9375f,11.568f,-195.313f, +-82.0313f,14.2419f,-195.313f, +-78.125f,16.1272f,-195.313f, +-74.2188f,17.0994f,-195.313f, +-70.3125f,20.4651f,-195.313f, +-66.4063f,23.534f,-195.313f, +-62.5f,25.1181f,-195.313f, +-58.5938f,25.9427f,-195.313f, +-54.6875f,25.5166f,-195.313f, +-50.7813f,25.1027f,-195.313f, +-46.875f,27.2281f,-195.313f, +-42.9688f,28.7319f,-195.313f, +-39.0625f,28.8984f,-195.313f, +-35.1563f,28.3307f,-195.313f, +-31.25f,27.4754f,-195.313f, +-27.3438f,27.8763f,-195.313f, +-23.4375f,28.1023f,-195.313f, +-19.5313f,28.9815f,-195.313f, +-15.625f,28.5849f,-195.313f, +-11.7188f,27.2687f,-195.313f, +-7.8125f,26.8112f,-195.313f, +-3.90625f,25.3636f,-195.313f, +0.0f,23.2134f,-195.313f, +3.90625f,23.0993f,-195.313f, +-250.0f,20.2026f,-199.219f, +-246.094f,19.5895f,-199.219f, +-242.188f,20.3489f,-199.219f, +-238.281f,21.0293f,-199.219f, +-234.375f,21.5343f,-199.219f, +-230.469f,20.6859f,-199.219f, +-226.563f,19.9279f,-199.219f, +-222.656f,18.7217f,-199.219f, +-218.75f,17.4818f,-199.219f, +-214.844f,15.0438f,-199.219f, +-210.938f,13.4082f,-199.219f, +-207.031f,10.7188f,-199.219f, +-203.125f,8.32176f,-199.219f, +-199.219f,7.30407f,-199.219f, +-195.313f,7.02569f,-199.219f, +-191.406f,7.38826f,-199.219f, +-187.5f,6.94954f,-199.219f, +-183.594f,6.62067f,-199.219f, +-179.688f,6.55308f,-199.219f, +-175.781f,6.3403f,-199.219f, +-171.875f,5.0001f,-199.219f, +-167.969f,6.51564f,-199.219f, +-164.063f,6.69774f,-199.219f, +-160.156f,5.67189f,-199.219f, +-156.25f,4.8973f,-199.219f, +-152.344f,3.43798f,-199.219f, +-148.438f,2.08531f,-199.219f, +-144.531f,3.86643f,-199.219f, +-140.625f,6.0862f,-199.219f, +-136.719f,6.99995f,-199.219f, +-132.813f,8.32808f,-199.219f, +-128.906f,8.55809f,-199.219f, +-125.0f,8.26904f,-199.219f, +-121.094f,8.63733f,-199.219f, +-117.188f,9.11106f,-199.219f, +-113.281f,9.73154f,-199.219f, +-109.375f,9.14108f,-199.219f, +-105.469f,9.3525f,-199.219f, +-101.563f,9.56281f,-199.219f, +-97.6563f,9.74866f,-199.219f, +-93.75f,10.9852f,-199.219f, +-89.8438f,12.3926f,-199.219f, +-85.9375f,13.6407f,-199.219f, +-82.0313f,15.9886f,-199.219f, +-78.125f,17.7913f,-199.219f, +-74.2188f,18.8352f,-199.219f, +-70.3125f,20.2718f,-199.219f, +-66.4063f,23.501f,-199.219f, +-62.5f,24.6073f,-199.219f, +-58.5938f,25.3028f,-199.219f, +-54.6875f,25.2244f,-199.219f, +-50.7813f,23.9922f,-199.219f, +-46.875f,24.6425f,-199.219f, +-42.9688f,26.6199f,-199.219f, +-39.0625f,27.5474f,-199.219f, +-35.1563f,27.4672f,-199.219f, +-31.25f,27.2906f,-199.219f, +-27.3438f,26.489f,-199.219f, +-23.4375f,26.3554f,-199.219f, +-19.5313f,26.1787f,-199.219f, +-15.625f,26.2538f,-199.219f, +-11.7188f,25.7694f,-199.219f, +-7.8125f,25.2691f,-199.219f, +-3.90625f,23.3867f,-199.219f, +0.0f,22.5717f,-199.219f, +3.90625f,21.5827f,-199.219f, +-250.0f,19.3526f,-203.125f, +-246.094f,19.2964f,-203.125f, +-242.188f,19.226f,-203.125f, +-238.281f,19.4274f,-203.125f, +-234.375f,19.4317f,-203.125f, +-230.469f,19.3079f,-203.125f, +-226.563f,18.212f,-203.125f, +-222.656f,17.8371f,-203.125f, +-218.75f,16.8642f,-203.125f, +-214.844f,14.8539f,-203.125f, +-210.938f,12.425f,-203.125f, +-207.031f,10.0369f,-203.125f, +-203.125f,9.00151f,-203.125f, +-199.219f,8.61334f,-203.125f, +-195.313f,8.09586f,-203.125f, +-191.406f,8.18143f,-203.125f, +-187.5f,7.75345f,-203.125f, +-183.594f,7.72772f,-203.125f, +-179.688f,7.71649f,-203.125f, +-175.781f,7.72935f,-203.125f, +-171.875f,6.70116f,-203.125f, +-167.969f,6.58828f,-203.125f, +-164.063f,6.47975f,-203.125f, +-160.156f,5.96451f,-203.125f, +-156.25f,5.85253f,-203.125f, +-152.344f,5.14982f,-203.125f, +-148.438f,4.60646f,-203.125f, +-144.531f,6.3659f,-203.125f, +-140.625f,7.66587f,-203.125f, +-136.719f,8.68095f,-203.125f, +-132.813f,9.86922f,-203.125f, +-128.906f,9.93481f,-203.125f, +-125.0f,10.9585f,-203.125f, +-121.094f,10.9271f,-203.125f, +-117.188f,11.4348f,-203.125f, +-113.281f,11.0548f,-203.125f, +-109.375f,11.2501f,-203.125f, +-105.469f,11.7673f,-203.125f, +-101.563f,10.8899f,-203.125f, +-97.6563f,11.3791f,-203.125f, +-93.75f,12.168f,-203.125f, +-89.8438f,12.7667f,-203.125f, +-85.9375f,15.2415f,-203.125f, +-82.0313f,17.9783f,-203.125f, +-78.125f,19.6193f,-203.125f, +-74.2188f,19.6343f,-203.125f, +-70.3125f,19.7814f,-203.125f, +-66.4063f,21.45f,-203.125f, +-62.5f,24.1224f,-203.125f, +-58.5938f,24.9145f,-203.125f, +-54.6875f,24.2614f,-203.125f, +-50.7813f,24.025f,-203.125f, +-46.875f,23.1092f,-203.125f, +-42.9688f,24.0294f,-203.125f, +-39.0625f,25.4744f,-203.125f, +-35.1563f,25.9477f,-203.125f, +-31.25f,25.5895f,-203.125f, +-27.3438f,25.0752f,-203.125f, +-23.4375f,24.6537f,-203.125f, +-19.5313f,25.0025f,-203.125f, +-15.625f,25.211f,-203.125f, +-11.7188f,24.2103f,-203.125f, +-7.8125f,23.1363f,-203.125f, +-3.90625f,21.4314f,-203.125f, +0.0f,20.8784f,-203.125f, +3.90625f,20.3179f,-203.125f, +-250.0f,18.4857f,-207.031f, +-246.094f,18.9103f,-207.031f, +-242.188f,17.7666f,-207.031f, +-238.281f,18.3803f,-207.031f, +-234.375f,17.7746f,-207.031f, +-230.469f,18.1956f,-207.031f, +-226.563f,17.4596f,-207.031f, +-222.656f,16.5346f,-207.031f, +-218.75f,15.3933f,-207.031f, +-214.844f,14.0342f,-207.031f, +-210.938f,11.5492f,-207.031f, +-207.031f,10.8526f,-207.031f, +-203.125f,10.5164f,-207.031f, +-199.219f,10.4957f,-207.031f, +-195.313f,9.57889f,-207.031f, +-191.406f,9.42031f,-207.031f, +-187.5f,9.08544f,-207.031f, +-183.594f,8.10082f,-207.031f, +-179.688f,8.5632f,-207.031f, +-175.781f,8.74392f,-207.031f, +-171.875f,8.56175f,-207.031f, +-167.969f,7.13665f,-207.031f, +-164.063f,6.99003f,-207.031f, +-160.156f,7.1192f,-207.031f, +-156.25f,6.173f,-207.031f, +-152.344f,6.44193f,-207.031f, +-148.438f,7.15583f,-207.031f, +-144.531f,7.74526f,-207.031f, +-140.625f,9.38846f,-207.031f, +-136.719f,10.1943f,-207.031f, +-132.813f,10.5195f,-207.031f, +-128.906f,11.4457f,-207.031f, +-125.0f,12.4233f,-207.031f, +-121.094f,12.8633f,-207.031f, +-117.188f,13.4045f,-207.031f, +-113.281f,12.9134f,-207.031f, +-109.375f,12.9203f,-207.031f, +-105.469f,13.2173f,-207.031f, +-101.563f,12.9065f,-207.031f, +-97.6563f,12.9327f,-207.031f, +-93.75f,13.5926f,-207.031f, +-89.8438f,14.5472f,-207.031f, +-85.9375f,16.41f,-207.031f, +-82.0313f,19.1484f,-207.031f, +-78.125f,20.5688f,-207.031f, +-74.2188f,20.1464f,-207.031f, +-70.3125f,19.9352f,-207.031f, +-66.4063f,20.4543f,-207.031f, +-62.5f,22.0083f,-207.031f, +-58.5938f,23.2866f,-207.031f, +-54.6875f,23.3242f,-207.031f, +-50.7813f,23.0127f,-207.031f, +-46.875f,23.4455f,-207.031f, +-42.9688f,23.4808f,-207.031f, +-39.0625f,24.4622f,-207.031f, +-35.1563f,25.1122f,-207.031f, +-31.25f,25.3818f,-207.031f, +-27.3438f,24.0051f,-207.031f, +-23.4375f,22.3971f,-207.031f, +-19.5313f,23.4811f,-207.031f, +-15.625f,23.8447f,-207.031f, +-11.7188f,22.3912f,-207.031f, +-7.8125f,21.7286f,-207.031f, +-3.90625f,20.1632f,-207.031f, +0.0f,18.6587f,-207.031f, +3.90625f,18.3149f,-207.031f, +-250.0f,17.6517f,-210.938f, +-246.094f,17.8132f,-210.938f, +-242.188f,17.4894f,-210.938f, +-238.281f,16.7087f,-210.938f, +-234.375f,15.9111f,-210.938f, +-230.469f,16.6733f,-210.938f, +-226.563f,16.6911f,-210.938f, +-222.656f,14.6177f,-210.938f, +-218.75f,13.6959f,-210.938f, +-214.844f,12.227f,-210.938f, +-210.938f,11.5376f,-210.938f, +-207.031f,11.7259f,-210.938f, +-203.125f,11.4804f,-210.938f, +-199.219f,11.8728f,-210.938f, +-195.313f,11.7357f,-210.938f, +-191.406f,10.6319f,-210.938f, +-187.5f,10.7016f,-210.938f, +-183.594f,9.53811f,-210.938f, +-179.688f,9.65149f,-210.938f, +-175.781f,9.45993f,-210.938f, +-171.875f,9.4427f,-210.938f, +-167.969f,8.02525f,-210.938f, +-164.063f,6.71089f,-210.938f, +-160.156f,7.22567f,-210.938f, +-156.25f,7.52391f,-210.938f, +-152.344f,8.46765f,-210.938f, +-148.438f,8.60801f,-210.938f, +-144.531f,9.89046f,-210.938f, +-140.625f,10.9163f,-210.938f, +-136.719f,11.445f,-210.938f, +-132.813f,12.6949f,-210.938f, +-128.906f,13.3645f,-210.938f, +-125.0f,14.5389f,-210.938f, +-121.094f,14.7689f,-210.938f, +-117.188f,15.8285f,-210.938f, +-113.281f,15.5058f,-210.938f, +-109.375f,14.3542f,-210.938f, +-105.469f,14.9928f,-210.938f, +-101.563f,14.9601f,-210.938f, +-97.6563f,15.1602f,-210.938f, +-93.75f,15.1589f,-210.938f, +-89.8438f,16.5401f,-210.938f, +-85.9375f,18.2407f,-210.938f, +-82.0313f,19.8006f,-210.938f, +-78.125f,20.9223f,-210.938f, +-74.2188f,20.5615f,-210.938f, +-70.3125f,21.0505f,-210.938f, +-66.4063f,21.024f,-210.938f, +-62.5f,21.7216f,-210.938f, +-58.5938f,22.8737f,-210.938f, +-54.6875f,23.631f,-210.938f, +-50.7813f,23.6265f,-210.938f, +-46.875f,23.5636f,-210.938f, +-42.9688f,24.1299f,-210.938f, +-39.0625f,24.6395f,-210.938f, +-35.1563f,25.3237f,-210.938f, +-31.25f,24.7459f,-210.938f, +-27.3438f,22.2327f,-210.938f, +-23.4375f,21.6309f,-210.938f, +-19.5313f,22.3059f,-210.938f, +-15.625f,22.1894f,-210.938f, +-11.7188f,21.2088f,-210.938f, +-7.8125f,20.3383f,-210.938f, +-3.90625f,18.4799f,-210.938f, +0.0f,17.18f,-210.938f, +3.90625f,16.2147f,-210.938f, +-250.0f,17.6547f,-214.844f, +-246.094f,17.1845f,-214.844f, +-242.188f,17.6913f,-214.844f, +-238.281f,16.8842f,-214.844f, +-234.375f,14.7169f,-214.844f, +-230.469f,15.4287f,-214.844f, +-226.563f,14.5659f,-214.844f, +-222.656f,13.1756f,-214.844f, +-218.75f,12.021f,-214.844f, +-214.844f,11.9663f,-214.844f, +-210.938f,12.535f,-214.844f, +-207.031f,12.5802f,-214.844f, +-203.125f,12.7437f,-214.844f, +-199.219f,12.9859f,-214.844f, +-195.313f,12.7714f,-214.844f, +-191.406f,11.9783f,-214.844f, +-187.5f,11.9282f,-214.844f, +-183.594f,10.7633f,-214.844f, +-179.688f,10.3463f,-214.844f, +-175.781f,10.1867f,-214.844f, +-171.875f,10.378f,-214.844f, +-167.969f,8.81572f,-214.844f, +-164.063f,7.29133f,-214.844f, +-160.156f,8.45242f,-214.844f, +-156.25f,9.77224f,-214.844f, +-152.344f,10.4567f,-214.844f, +-148.438f,11.0484f,-214.844f, +-144.531f,12.1985f,-214.844f, +-140.625f,13.766f,-214.844f, +-136.719f,14.9123f,-214.844f, +-132.813f,15.4577f,-214.844f, +-128.906f,16.3401f,-214.844f, +-125.0f,16.5963f,-214.844f, +-121.094f,16.9605f,-214.844f, +-117.188f,16.548f,-214.844f, +-113.281f,16.701f,-214.844f, +-109.375f,16.6987f,-214.844f, +-105.469f,16.1393f,-214.844f, +-101.563f,15.4379f,-214.844f, +-97.6563f,15.9931f,-214.844f, +-93.75f,16.7962f,-214.844f, +-89.8438f,18.5464f,-214.844f, +-85.9375f,20.2834f,-214.844f, +-82.0313f,20.8463f,-214.844f, +-78.125f,21.263f,-214.844f, +-74.2188f,22.137f,-214.844f, +-70.3125f,22.1614f,-214.844f, +-66.4063f,21.7706f,-214.844f, +-62.5f,23.0496f,-214.844f, +-58.5938f,23.0762f,-214.844f, +-54.6875f,24.2163f,-214.844f, +-50.7813f,23.9415f,-214.844f, +-46.875f,23.115f,-214.844f, +-42.9688f,24.4371f,-214.844f, +-39.0625f,25.7433f,-214.844f, +-35.1563f,24.6385f,-214.844f, +-31.25f,23.2822f,-214.844f, +-27.3438f,21.8583f,-214.844f, +-23.4375f,21.2352f,-214.844f, +-19.5313f,21.3084f,-214.844f, +-15.625f,20.7264f,-214.844f, +-11.7188f,19.67f,-214.844f, +-7.8125f,18.8192f,-214.844f, +-3.90625f,16.6504f,-214.844f, +0.0f,14.8779f,-214.844f, +3.90625f,14.284f,-214.844f, +-250.0f,17.1549f,-218.75f, +-246.094f,16.6295f,-218.75f, +-242.188f,17.7459f,-218.75f, +-238.281f,17.3894f,-218.75f, +-234.375f,15.2738f,-218.75f, +-230.469f,13.3984f,-218.75f, +-226.563f,12.8639f,-218.75f, +-222.656f,12.3225f,-218.75f, +-218.75f,12.1914f,-218.75f, +-214.844f,12.4104f,-218.75f, +-210.938f,12.9278f,-218.75f, +-207.031f,13.387f,-218.75f, +-203.125f,13.4342f,-218.75f, +-199.219f,12.7445f,-218.75f, +-195.313f,12.543f,-218.75f, +-191.406f,12.1437f,-218.75f, +-187.5f,12.3491f,-218.75f, +-183.594f,11.2334f,-218.75f, +-179.688f,11.4016f,-218.75f, +-175.781f,11.2455f,-218.75f, +-171.875f,10.3681f,-218.75f, +-167.969f,9.23056f,-218.75f, +-164.063f,8.35869f,-218.75f, +-160.156f,10.3612f,-218.75f, +-156.25f,11.8429f,-218.75f, +-152.344f,13.2154f,-218.75f, +-148.438f,13.6238f,-218.75f, +-144.531f,14.8343f,-218.75f, +-140.625f,15.5549f,-218.75f, +-136.719f,16.9496f,-218.75f, +-132.813f,17.9187f,-218.75f, +-128.906f,17.7467f,-218.75f, +-125.0f,17.8229f,-218.75f, +-121.094f,17.4408f,-218.75f, +-117.188f,17.3929f,-218.75f, +-113.281f,17.9861f,-218.75f, +-109.375f,18.0206f,-218.75f, +-105.469f,17.6787f,-218.75f, +-101.563f,17.3769f,-218.75f, +-97.6563f,17.5683f,-218.75f, +-93.75f,18.0067f,-218.75f, +-89.8438f,18.9639f,-218.75f, +-85.9375f,20.8377f,-218.75f, +-82.0313f,22.207f,-218.75f, +-78.125f,23.1239f,-218.75f, +-74.2188f,22.384f,-218.75f, +-70.3125f,22.2939f,-218.75f, +-66.4063f,21.8208f,-218.75f, +-62.5f,22.9458f,-218.75f, +-58.5938f,24.2547f,-218.75f, +-54.6875f,24.5855f,-218.75f, +-50.7813f,23.9529f,-218.75f, +-46.875f,22.9226f,-218.75f, +-42.9688f,25.1015f,-218.75f, +-39.0625f,25.1591f,-218.75f, +-35.1563f,23.6146f,-218.75f, +-31.25f,21.7924f,-218.75f, +-27.3438f,20.3147f,-218.75f, +-23.4375f,19.9227f,-218.75f, +-19.5313f,20.3267f,-218.75f, +-15.625f,19.1903f,-218.75f, +-11.7188f,17.3132f,-218.75f, +-7.8125f,16.5145f,-218.75f, +-3.90625f,15.5991f,-218.75f, +0.0f,13.7865f,-218.75f, +3.90625f,13.272f,-218.75f, +-250.0f,16.7536f,-222.656f, +-246.094f,16.7692f,-222.656f, +-242.188f,17.6216f,-222.656f, +-238.281f,17.7524f,-222.656f, +-234.375f,15.7102f,-222.656f, +-230.469f,13.9934f,-222.656f, +-226.563f,13.1311f,-222.656f, +-222.656f,13.6218f,-222.656f, +-218.75f,13.8812f,-222.656f, +-214.844f,13.6928f,-222.656f, +-210.938f,13.2498f,-222.656f, +-207.031f,13.9199f,-222.656f, +-203.125f,14.8224f,-222.656f, +-199.219f,14.7821f,-222.656f, +-195.313f,14.4118f,-222.656f, +-191.406f,13.2421f,-222.656f, +-187.5f,13.1953f,-222.656f, +-183.594f,11.9441f,-222.656f, +-179.688f,11.8006f,-222.656f, +-175.781f,11.2509f,-222.656f, +-171.875f,9.7863f,-222.656f, +-167.969f,8.85086f,-222.656f, +-164.063f,10.6896f,-222.656f, +-160.156f,12.9132f,-222.656f, +-156.25f,13.602f,-222.656f, +-152.344f,15.3711f,-222.656f, +-148.438f,16.1768f,-222.656f, +-144.531f,16.9203f,-222.656f, +-140.625f,17.0404f,-222.656f, +-136.719f,18.4968f,-222.656f, +-132.813f,18.8222f,-222.656f, +-128.906f,19.2736f,-222.656f, +-125.0f,19.1956f,-222.656f, +-121.094f,18.5998f,-222.656f, +-117.188f,18.5054f,-222.656f, +-113.281f,19.68f,-222.656f, +-109.375f,19.5038f,-222.656f, +-105.469f,19.4749f,-222.656f, +-101.563f,18.7504f,-222.656f, +-97.6563f,18.6121f,-222.656f, +-93.75f,19.1119f,-222.656f, +-89.8438f,20.5347f,-222.656f, +-85.9375f,21.4412f,-222.656f, +-82.0313f,22.187f,-222.656f, +-78.125f,22.9384f,-222.656f, +-74.2188f,22.5226f,-222.656f, +-70.3125f,22.7323f,-222.656f, +-66.4063f,23.4931f,-222.656f, +-62.5f,24.6895f,-222.656f, +-58.5938f,24.9745f,-222.656f, +-54.6875f,24.801f,-222.656f, +-50.7813f,23.2235f,-222.656f, +-46.875f,22.4973f,-222.656f, +-42.9688f,23.9826f,-222.656f, +-39.0625f,23.4458f,-222.656f, +-35.1563f,22.66f,-222.656f, +-31.25f,20.8011f,-222.656f, +-27.3438f,18.877f,-222.656f, +-23.4375f,17.9999f,-222.656f, +-19.5313f,18.2206f,-222.656f, +-15.625f,17.8501f,-222.656f, +-11.7188f,16.2125f,-222.656f, +-7.8125f,15.4897f,-222.656f, +-3.90625f,14.2048f,-222.656f, +0.0f,13.1443f,-222.656f, +3.90625f,13.0199f,-222.656f, +-250.0f,15.9959f,-226.563f, +-246.094f,16.3902f,-226.563f, +-242.188f,17.2433f,-226.563f, +-238.281f,16.8903f,-226.563f, +-234.375f,16.2616f,-226.563f, +-230.469f,16.3335f,-226.563f, +-226.563f,15.3662f,-226.563f, +-222.656f,14.6429f,-226.563f, +-218.75f,15.2987f,-226.563f, +-214.844f,15.1249f,-226.563f, +-210.938f,14.6321f,-226.563f, +-207.031f,15.402f,-226.563f, +-203.125f,15.5803f,-226.563f, +-199.219f,15.8024f,-226.563f, +-195.313f,14.9564f,-226.563f, +-191.406f,14.7272f,-226.563f, +-187.5f,14.0749f,-226.563f, +-183.594f,12.2838f,-226.563f, +-179.688f,12.0268f,-226.563f, +-175.781f,10.904f,-226.563f, +-171.875f,10.0049f,-226.563f, +-167.969f,9.85558f,-226.563f, +-164.063f,11.873f,-226.563f, +-160.156f,14.0684f,-226.563f, +-156.25f,15.4765f,-226.563f, +-152.344f,16.7458f,-226.563f, +-148.438f,17.9359f,-226.563f, +-144.531f,18.4507f,-226.563f, +-140.625f,18.3457f,-226.563f, +-136.719f,20.0059f,-226.563f, +-132.813f,20.3125f,-226.563f, +-128.906f,19.751f,-226.563f, +-125.0f,19.8084f,-226.563f, +-121.094f,19.9091f,-226.563f, +-117.188f,20.3401f,-226.563f, +-113.281f,20.8121f,-226.563f, +-109.375f,20.5705f,-226.563f, +-105.469f,20.9909f,-226.563f, +-101.563f,20.4171f,-226.563f, +-97.6563f,19.834f,-226.563f, +-93.75f,19.9289f,-226.563f, +-89.8438f,20.4305f,-226.563f, +-85.9375f,21.4097f,-226.563f, +-82.0313f,21.9666f,-226.563f, +-78.125f,22.5232f,-226.563f, +-74.2188f,22.2049f,-226.563f, +-70.3125f,22.7045f,-226.563f, +-66.4063f,23.7933f,-226.563f, +-62.5f,24.5938f,-226.563f, +-58.5938f,24.6161f,-226.563f, +-54.6875f,23.6008f,-226.563f, +-50.7813f,21.9411f,-226.563f, +-46.875f,21.6164f,-226.563f, +-42.9688f,22.5551f,-226.563f, +-39.0625f,22.5032f,-226.563f, +-35.1563f,21.5165f,-226.563f, +-31.25f,19.8362f,-226.563f, +-27.3438f,17.5967f,-226.563f, +-23.4375f,15.6932f,-226.563f, +-19.5313f,15.7774f,-226.563f, +-15.625f,15.6405f,-226.563f, +-11.7188f,14.7549f,-226.563f, +-7.8125f,14.3205f,-226.563f, +-3.90625f,13.2947f,-226.563f, +0.0f,11.9266f,-226.563f, +3.90625f,11.9733f,-226.563f, +-250.0f,15.2423f,-230.469f, +-246.094f,16.2143f,-230.469f, +-242.188f,17.2462f,-230.469f, +-238.281f,17.7941f,-230.469f, +-234.375f,18.4029f,-230.469f, +-230.469f,18.5726f,-230.469f, +-226.563f,17.4729f,-230.469f, +-222.656f,15.9467f,-230.469f, +-218.75f,15.5021f,-230.469f, +-214.844f,15.7096f,-230.469f, +-210.938f,15.6276f,-230.469f, +-207.031f,15.7025f,-230.469f, +-203.125f,14.8851f,-230.469f, +-199.219f,14.87f,-230.469f, +-195.313f,14.3971f,-230.469f, +-191.406f,14.5771f,-230.469f, +-187.5f,13.8163f,-230.469f, +-183.594f,12.7605f,-230.469f, +-179.688f,12.587f,-230.469f, +-175.781f,11.0727f,-230.469f, +-171.875f,10.0166f,-230.469f, +-167.969f,12.5787f,-230.469f, +-164.063f,13.3613f,-230.469f, +-160.156f,14.7537f,-230.469f, +-156.25f,15.9879f,-230.469f, +-152.344f,17.6792f,-230.469f, +-148.438f,18.5224f,-230.469f, +-144.531f,18.5026f,-230.469f, +-140.625f,19.4852f,-230.469f, +-136.719f,20.3222f,-230.469f, +-132.813f,20.2809f,-230.469f, +-128.906f,21.0408f,-230.469f, +-125.0f,20.4729f,-230.469f, +-121.094f,20.8829f,-230.469f, +-117.188f,21.532f,-230.469f, +-113.281f,21.3373f,-230.469f, +-109.375f,22.0014f,-230.469f, +-105.469f,22.1484f,-230.469f, +-101.563f,21.7053f,-230.469f, +-97.6563f,20.5255f,-230.469f, +-93.75f,19.6269f,-230.469f, +-89.8438f,20.0012f,-230.469f, +-85.9375f,21.0697f,-230.469f, +-82.0313f,21.8192f,-230.469f, +-78.125f,22.7525f,-230.469f, +-74.2188f,22.3932f,-230.469f, +-70.3125f,22.0383f,-230.469f, +-66.4063f,22.5989f,-230.469f, +-62.5f,23.0428f,-230.469f, +-58.5938f,22.4512f,-230.469f, +-54.6875f,21.5848f,-230.469f, +-50.7813f,20.085f,-230.469f, +-46.875f,19.9106f,-230.469f, +-42.9688f,20.5256f,-230.469f, +-39.0625f,20.2072f,-230.469f, +-35.1563f,18.9414f,-230.469f, +-31.25f,17.9342f,-230.469f, +-27.3438f,15.3472f,-230.469f, +-23.4375f,13.2173f,-230.469f, +-19.5313f,13.1448f,-230.469f, +-15.625f,13.7506f,-230.469f, +-11.7188f,12.7439f,-230.469f, +-7.8125f,12.5338f,-230.469f, +-3.90625f,12.0435f,-230.469f, +0.0f,11.0483f,-230.469f, +3.90625f,10.4619f,-230.469f, +-250.0f,15.6879f,-234.375f, +-246.094f,17.6667f,-234.375f, +-242.188f,18.8427f,-234.375f, +-238.281f,19.6527f,-234.375f, +-234.375f,19.7979f,-234.375f, +-230.469f,19.8698f,-234.375f, +-226.563f,19.1736f,-234.375f, +-222.656f,16.9995f,-234.375f, +-218.75f,15.4573f,-234.375f, +-214.844f,15.6294f,-234.375f, +-210.938f,15.4315f,-234.375f, +-207.031f,15.1239f,-234.375f, +-203.125f,14.669f,-234.375f, +-199.219f,14.4586f,-234.375f, +-195.313f,14.1329f,-234.375f, +-191.406f,14.0558f,-234.375f, +-187.5f,13.3746f,-234.375f, +-183.594f,13.2348f,-234.375f, +-179.688f,13.3354f,-234.375f, +-175.781f,12.1532f,-234.375f, +-171.875f,11.4785f,-234.375f, +-167.969f,12.7174f,-234.375f, +-164.063f,14.0617f,-234.375f, +-160.156f,15.3367f,-234.375f, +-156.25f,16.6196f,-234.375f, +-152.344f,17.6677f,-234.375f, +-148.438f,18.475f,-234.375f, +-144.531f,19.8205f,-234.375f, +-140.625f,19.6973f,-234.375f, +-136.719f,20.5952f,-234.375f, +-132.813f,20.3507f,-234.375f, +-128.906f,20.8729f,-234.375f, +-125.0f,21.9377f,-234.375f, +-121.094f,21.8916f,-234.375f, +-117.188f,21.9614f,-234.375f, +-113.281f,22.1752f,-234.375f, +-109.375f,22.2881f,-234.375f, +-105.469f,23.1063f,-234.375f, +-101.563f,23.4826f,-234.375f, +-97.6563f,22.5968f,-234.375f, +-93.75f,21.3142f,-234.375f, +-89.8438f,19.9609f,-234.375f, +-85.9375f,21.4353f,-234.375f, +-82.0313f,21.9716f,-234.375f, +-78.125f,22.6918f,-234.375f, +-74.2188f,21.9561f,-234.375f, +-70.3125f,21.3085f,-234.375f, +-66.4063f,21.4104f,-234.375f, +-62.5f,21.4904f,-234.375f, +-58.5938f,20.2467f,-234.375f, +-54.6875f,19.1535f,-234.375f, +-50.7813f,17.9598f,-234.375f, +-46.875f,18.0449f,-234.375f, +-42.9688f,18.3612f,-234.375f, +-39.0625f,17.5008f,-234.375f, +-35.1563f,16.7819f,-234.375f, +-31.25f,15.4328f,-234.375f, +-27.3438f,13.9747f,-234.375f, +-23.4375f,12.1868f,-234.375f, +-19.5313f,12.0847f,-234.375f, +-15.625f,11.926f,-234.375f, +-11.7188f,11.3058f,-234.375f, +-7.8125f,11.0187f,-234.375f, +-3.90625f,10.1275f,-234.375f, +0.0f,9.73133f,-234.375f, +3.90625f,8.85224f,-234.375f, +-250.0f,16.6463f,-238.281f, +-246.094f,18.8582f,-238.281f, +-242.188f,19.6269f,-238.281f, +-238.281f,20.3222f,-238.281f, +-234.375f,20.8316f,-238.281f, +-230.469f,20.6072f,-238.281f, +-226.563f,19.2331f,-238.281f, +-222.656f,18.0021f,-238.281f, +-218.75f,16.4891f,-238.281f, +-214.844f,15.7845f,-238.281f, +-210.938f,15.4622f,-238.281f, +-207.031f,14.3459f,-238.281f, +-203.125f,14.6544f,-238.281f, +-199.219f,13.7779f,-238.281f, +-195.313f,13.4199f,-238.281f, +-191.406f,13.2089f,-238.281f, +-187.5f,12.5036f,-238.281f, +-183.594f,12.6398f,-238.281f, +-179.688f,13.015f,-238.281f, +-175.781f,12.659f,-238.281f, +-171.875f,13.2801f,-238.281f, +-167.969f,13.9547f,-238.281f, +-164.063f,14.8792f,-238.281f, +-160.156f,16.4144f,-238.281f, +-156.25f,17.1062f,-238.281f, +-152.344f,17.9028f,-238.281f, +-148.438f,19.1823f,-238.281f, +-144.531f,20.6903f,-238.281f, +-140.625f,19.9053f,-238.281f, +-136.719f,20.8795f,-238.281f, +-132.813f,21.7034f,-238.281f, +-128.906f,21.8373f,-238.281f, +-125.0f,22.5134f,-238.281f, +-121.094f,22.7918f,-238.281f, +-117.188f,23.1126f,-238.281f, +-113.281f,23.0308f,-238.281f, +-109.375f,23.7212f,-238.281f, +-105.469f,24.6127f,-238.281f, +-101.563f,24.5942f,-238.281f, +-97.6563f,24.0315f,-238.281f, +-93.75f,23.2191f,-238.281f, +-89.8438f,21.3372f,-238.281f, +-85.9375f,20.6395f,-238.281f, +-82.0313f,22.2808f,-238.281f, +-78.125f,22.2977f,-238.281f, +-74.2188f,21.5802f,-238.281f, +-70.3125f,20.5131f,-238.281f, +-66.4063f,20.0882f,-238.281f, +-62.5f,19.9865f,-238.281f, +-58.5938f,19.1423f,-238.281f, +-54.6875f,16.917f,-238.281f, +-50.7813f,16.0256f,-238.281f, +-46.875f,15.4122f,-238.281f, +-42.9688f,15.0531f,-238.281f, +-39.0625f,15.8819f,-238.281f, +-35.1563f,14.3724f,-238.281f, +-31.25f,12.993f,-238.281f, +-27.3438f,11.8948f,-238.281f, +-23.4375f,10.1339f,-238.281f, +-19.5313f,10.4205f,-238.281f, +-15.625f,10.7339f,-238.281f, +-11.7188f,9.86852f,-238.281f, +-7.8125f,8.89818f,-238.281f, +-3.90625f,8.20848f,-238.281f, +0.0f,7.89095f,-238.281f, +3.90625f,7.99527f,-238.281f, +-250.0f,16.461f,-242.188f, +-246.094f,18.8623f,-242.188f, +-242.188f,19.6097f,-242.188f, +-238.281f,20.8167f,-242.188f, +-234.375f,21.0667f,-242.188f, +-230.469f,20.3337f,-242.188f, +-226.563f,18.9993f,-242.188f, +-222.656f,17.8141f,-242.188f, +-218.75f,17.3651f,-242.188f, +-214.844f,16.1703f,-242.188f, +-210.938f,15.3612f,-242.188f, +-207.031f,14.5062f,-242.188f, +-203.125f,14.0333f,-242.188f, +-199.219f,13.0731f,-242.188f, +-195.313f,13.0716f,-242.188f, +-191.406f,12.2773f,-242.188f, +-187.5f,12.1599f,-242.188f, +-183.594f,12.0841f,-242.188f, +-179.688f,11.1979f,-242.188f, +-175.781f,11.7767f,-242.188f, +-171.875f,13.5192f,-242.188f, +-167.969f,13.6117f,-242.188f, +-164.063f,14.5377f,-242.188f, +-160.156f,16.1128f,-242.188f, +-156.25f,17.0591f,-242.188f, +-152.344f,18.0547f,-242.188f, +-148.438f,19.9927f,-242.188f, +-144.531f,20.5592f,-242.188f, +-140.625f,20.5602f,-242.188f, +-136.719f,20.6585f,-242.188f, +-132.813f,22.6924f,-242.188f, +-128.906f,23.4786f,-242.188f, +-125.0f,23.9921f,-242.188f, +-121.094f,24.3221f,-242.188f, +-117.188f,24.7845f,-242.188f, +-113.281f,24.0995f,-242.188f, +-109.375f,25.5836f,-242.188f, +-105.469f,25.1932f,-242.188f, +-101.563f,25.0022f,-242.188f, +-97.6563f,24.569f,-242.188f, +-93.75f,24.5749f,-242.188f, +-89.8438f,22.6678f,-242.188f, +-85.9375f,20.6652f,-242.188f, +-82.0313f,21.1719f,-242.188f, +-78.125f,21.9102f,-242.188f, +-74.2188f,20.9512f,-242.188f, +-70.3125f,19.1099f,-242.188f, +-66.4063f,18.2366f,-242.188f, +-62.5f,16.9751f,-242.188f, +-58.5938f,16.938f,-242.188f, +-54.6875f,16.3692f,-242.188f, +-50.7813f,14.5702f,-242.188f, +-46.875f,13.5527f,-242.188f, +-42.9688f,13.0169f,-242.188f, +-39.0625f,11.9599f,-242.188f, +-35.1563f,11.4675f,-242.188f, +-31.25f,10.1264f,-242.188f, +-27.3438f,9.05124f,-242.188f, +-23.4375f,8.17722f,-242.188f, +-19.5313f,8.42066f,-242.188f, +-15.625f,8.13199f,-242.188f, +-11.7188f,7.70744f,-242.188f, +-7.8125f,7.06448f,-242.188f, +-3.90625f,6.2428f,-242.188f, +0.0f,6.35893f,-242.188f, +3.90625f,6.40337f,-242.188f, +-250.0f,16.6546f,-246.094f, +-246.094f,17.6689f,-246.094f, +-242.188f,18.7575f,-246.094f, +-238.281f,20.3967f,-246.094f, +-234.375f,20.3065f,-246.094f, +-230.469f,20.2082f,-246.094f, +-226.563f,19.5383f,-246.094f, +-222.656f,17.7409f,-246.094f, +-218.75f,16.6708f,-246.094f, +-214.844f,15.9584f,-246.094f, +-210.938f,14.8412f,-246.094f, +-207.031f,14.5591f,-246.094f, +-203.125f,13.9049f,-246.094f, +-199.219f,12.4723f,-246.094f, +-195.313f,11.7361f,-246.094f, +-191.406f,11.5463f,-246.094f, +-187.5f,10.9687f,-246.094f, +-183.594f,10.6795f,-246.094f, +-179.688f,10.6856f,-246.094f, +-175.781f,10.6342f,-246.094f, +-171.875f,12.061f,-246.094f, +-167.969f,12.3131f,-246.094f, +-164.063f,13.8453f,-246.094f, +-160.156f,15.3522f,-246.094f, +-156.25f,16.575f,-246.094f, +-152.344f,17.953f,-246.094f, +-148.438f,18.9271f,-246.094f, +-144.531f,19.6463f,-246.094f, +-140.625f,20.0348f,-246.094f, +-136.719f,20.8966f,-246.094f, +-132.813f,22.7081f,-246.094f, +-128.906f,24.2289f,-246.094f, +-125.0f,24.3296f,-246.094f, +-121.094f,25.513f,-246.094f, +-117.188f,26.0616f,-246.094f, +-113.281f,25.9026f,-246.094f, +-109.375f,25.3793f,-246.094f, +-105.469f,26.0086f,-246.094f, +-101.563f,25.9668f,-246.094f, +-97.6563f,25.4377f,-246.094f, +-93.75f,24.6398f,-246.094f, +-89.8438f,22.6277f,-246.094f, +-85.9375f,20.9377f,-246.094f, +-82.0313f,20.5815f,-246.094f, +-78.125f,20.2521f,-246.094f, +-74.2188f,19.1439f,-246.094f, +-70.3125f,17.8492f,-246.094f, +-66.4063f,16.6347f,-246.094f, +-62.5f,15.9154f,-246.094f, +-58.5938f,14.2098f,-246.094f, +-54.6875f,13.5957f,-246.094f, +-50.7813f,12.5676f,-246.094f, +-46.875f,11.2422f,-246.094f, +-42.9688f,10.426f,-246.094f, +-39.0625f,10.1665f,-246.094f, +-35.1563f,9.19605f,-246.094f, +-31.25f,7.36042f,-246.094f, +-27.3438f,5.74959f,-246.094f, +-23.4375f,5.41512f,-246.094f, +-19.5313f,6.03312f,-246.094f, +-15.625f,5.93285f,-246.094f, +-11.7188f,5.3331f,-246.094f, +-7.8125f,5.48059f,-246.094f, +-3.90625f,4.92566f,-246.094f, +0.0f,5.05645f,-246.094f, +3.90625f,6.09425f,-246.094f, +-250.0f,17.2418f,-250.0f, +-246.094f,17.9679f,-250.0f, +-242.188f,19.359f,-250.0f, +-238.281f,19.3277f,-250.0f, +-234.375f,20.1575f,-250.0f, +-230.469f,19.8999f,-250.0f, +-226.563f,18.9681f,-250.0f, +-222.656f,17.7696f,-250.0f, +-218.75f,15.6199f,-250.0f, +-214.844f,14.6555f,-250.0f, +-210.938f,13.0514f,-250.0f, +-207.031f,13.6029f,-250.0f, +-203.125f,13.1455f,-250.0f, +-199.219f,12.0056f,-250.0f, +-195.313f,11.1773f,-250.0f, +-191.406f,10.7263f,-250.0f, +-187.5f,10.2543f,-250.0f, +-183.594f,9.76389f,-250.0f, +-179.688f,9.00623f,-250.0f, +-175.781f,9.47424f,-250.0f, +-171.875f,10.8011f,-250.0f, +-167.969f,12.4395f,-250.0f, +-164.063f,13.7736f,-250.0f, +-160.156f,14.0938f,-250.0f, +-156.25f,15.8447f,-250.0f, +-152.344f,17.1975f,-250.0f, +-148.438f,17.963f,-250.0f, +-144.531f,19.3662f,-250.0f, +-140.625f,20.309f,-250.0f, +-136.719f,21.9063f,-250.0f, +-132.813f,22.8363f,-250.0f, +-128.906f,24.0073f,-250.0f, +-125.0f,25.2989f,-250.0f, +-121.094f,26.2944f,-250.0f, +-117.188f,27.4482f,-250.0f, +-113.281f,27.4823f,-250.0f, +-109.375f,27.2835f,-250.0f, +-105.469f,27.4754f,-250.0f, +-101.563f,27.7731f,-250.0f, +-97.6563f,26.6981f,-250.0f, +-93.75f,24.4699f,-250.0f, +-89.8438f,22.81f,-250.0f, +-85.9375f,21.6739f,-250.0f, +-82.0313f,19.8713f,-250.0f, +-78.125f,18.5848f,-250.0f, +-74.2188f,17.7134f,-250.0f, +-70.3125f,15.5276f,-250.0f, +-66.4063f,14.6805f,-250.0f, +-62.5f,14.0332f,-250.0f, +-58.5938f,12.1429f,-250.0f, +-54.6875f,10.3027f,-250.0f, +-50.7813f,9.68001f,-250.0f, +-46.875f,8.12561f,-250.0f, +-42.9688f,8.26581f,-250.0f, +-39.0625f,7.98056f,-250.0f, +-35.1563f,7.43215f,-250.0f, +-31.25f,6.33038f,-250.0f, +-27.3438f,4.62549f,-250.0f, +-23.4375f,3.83616f,-250.0f, +-19.5313f,4.24597f,-250.0f, +-15.625f,3.79997f,-250.0f, +-11.7188f,3.74461f,-250.0f, +-7.8125f,3.79853f,-250.0f, +-3.90625f,3.95418f,-250.0f, +0.0f,5.70623f,-250.0f, +3.90625f,6.31953f,-250.0f, +}; + +btScalar Landscape08Nml[] = { +-0.193879f,0.980285f,-0.0381128f, +-0.101407f,0.994799f,-0.00961843f, +-0.17812f,0.983422f,0.0339701f, +-0.107869f,0.990758f,0.0822321f, +-0.150224f,0.986838f,0.0598614f, +-0.176421f,0.983338f,0.0438458f, +0.00771709f,0.999873f,0.0139132f, +-0.0458501f,0.998747f,-0.0200731f, +0.170866f,0.984802f,-0.0311488f, +0.198428f,0.979783f,-0.0255296f, +0.223966f,0.969797f,0.0966125f, +0.319719f,0.946459f,0.0446654f, +0.155788f,0.942148f,0.296794f, +0.226142f,0.945324f,0.234996f, +0.0234229f,0.954977f,0.295752f, +-0.0213542f,0.981077f,0.192434f, +-0.0320299f,0.976907f,0.211248f, +-0.0305686f,0.97015f,0.240572f, +-0.00290395f,0.990031f,0.14082f, +-0.0740282f,0.98339f,0.165723f, +0.0359831f,0.998663f,0.0371117f, +-0.048977f,0.998654f,0.0171003f, +0.119085f,0.992879f,0.00312204f, +0.163687f,0.985928f,0.0339365f, +0.233927f,0.967265f,0.0983717f, +0.258555f,0.954734f,0.147076f, +0.185228f,0.98177f,0.0426319f, +0.171781f,0.975163f,0.139813f, +0.312497f,0.949826f,0.0132586f, +0.315278f,0.937034f,0.150223f, +0.455936f,0.889912f,-0.0133666f, +0.444363f,0.88993f,0.102789f, +0.477095f,0.878821f,-0.00729384f, +0.442265f,0.892911f,0.0843273f, +0.441901f,0.89445f,-0.0684218f, +0.356563f,0.929766f,-0.091634f, +0.46452f,0.88048f,-0.0947459f, +0.399286f,0.883106f,-0.246362f, +0.430625f,0.899506f,-0.073831f, +0.418125f,0.862027f,-0.286498f, +0.390492f,0.919986f,-0.0337736f, +0.451928f,0.884249f,-0.117748f, +0.389473f,0.920638f,-0.0271218f, +0.401911f,0.911214f,-0.0903147f, +0.411594f,0.910246f,-0.0451926f, +0.385985f,0.916603f,-0.104187f, +0.406515f,0.904587f,-0.128329f, +0.375686f,0.920382f,-0.108425f, +0.421893f,0.886378f,-0.190632f, +0.362475f,0.891842f,-0.270609f, +0.382406f,0.917607f,-0.108459f, +0.380095f,0.864773f,-0.32817f, +0.206545f,0.977978f,-0.0299668f, +0.319336f,0.938074f,-0.134321f, +-0.0276167f,0.998803f,0.0403598f, +0.0724517f,0.997355f,-0.00577643f, +-0.170399f,0.974366f,0.146884f, +-0.0444923f,0.976538f,0.210699f, +-0.123713f,0.961736f,0.244457f, +-0.0585476f,0.950932f,0.303809f, +-0.0436638f,0.948824f,0.312774f, +-0.0108452f,0.950133f,0.311655f, +-0.0562151f,0.924389f,0.377285f, +-0.024656f,0.918307f,0.3951f, +-0.11936f,0.930674f,0.345831f, +-0.21058f,0.936144f,0.281584f, +-0.166672f,0.952976f,0.253095f, +-0.262868f,0.958623f,0.109278f, +-0.138859f,0.97532f,0.171667f, +-0.166823f,0.980233f,0.106364f, +-0.016911f,0.994026f,0.107828f, +0.014088f,0.986713f,0.161858f, +-0.0269312f,0.989998f,0.138489f, +-0.0681193f,0.995186f,0.0704648f, +-0.241507f,0.962694f,0.122045f, +-0.306148f,0.951983f,0.00131283f, +-0.400562f,0.916076f,-0.0188573f, +-0.46755f,0.872686f,-0.140772f, +-0.451983f,0.886731f,-0.0970551f, +-0.445163f,0.885181f,-0.135217f, +-0.440559f,0.893764f,-0.0842181f, +-0.44058f,0.883958f,-0.156548f, +-0.530573f,0.842324f,-0.094771f, +-0.559377f,0.815929f,-0.14614f, +-0.675146f,0.724837f,-0.137074f, +-0.671227f,0.729467f,-0.131655f, +-0.627673f,0.767191f,-0.132076f, +-0.630683f,0.736819f,-0.243592f, +-0.548071f,0.819689f,-0.166518f, +-0.526895f,0.799727f,-0.287781f, +-0.521779f,0.83885f,-0.155167f, +-0.501504f,0.822365f,-0.268719f, +-0.465479f,0.867433f,-0.175756f, +-0.453816f,0.862676f,-0.223251f, +-0.458424f,0.854844f,-0.243083f, +-0.470698f,0.860374f,-0.195446f, +-0.485669f,0.830839f,-0.27172f, +-0.494445f,0.85319f,-0.166102f, +-0.418394f,0.865747f,-0.274642f, +-0.405345f,0.892443f,-0.198093f, +-0.287108f,0.926134f,-0.244631f, +-0.325256f,0.923685f,-0.202519f, +-0.192384f,0.91848f,-0.345518f, +-0.208186f,0.935081f,-0.28685f, +0.0681073f,0.948251f,-0.310131f, +0.077158f,0.955715f,-0.283998f, +0.102278f,0.947499f,-0.302962f, +0.02043f,0.921087f,-0.388821f, +0.0627177f,0.929646f,-0.363077f, +0.0629047f,0.918578f,-0.390202f, +-0.00415691f,0.947597f,-0.31944f, +-0.00512929f,0.899538f,-0.436812f, +-0.271944f,0.935195f,-0.226842f, +-0.177509f,0.92231f,-0.343271f, +-0.413186f,0.904845f,-0.102632f, +-0.338265f,0.931446f,-0.13411f, +-0.418276f,0.90315f,-0.0967731f, +-0.404177f,0.914278f,-0.0271442f, +-0.400569f,0.902696f,-0.157112f, +-0.429625f,0.894308f,-0.125039f, +-0.29004f,0.948484f,-0.127491f, +-0.188203f,0.980777f,0.0515283f, +-0.0585039f,0.997556f,-0.0381961f, +-0.133431f,0.99094f,0.0152943f, +-0.143343f,0.971126f,-0.1907f, +-0.24516f,0.938627f,-0.242644f, +-0.188833f,0.958258f,-0.214673f, +-0.174705f,0.963776f,-0.201528f, +-0.196517f,0.95296f,-0.230756f, +-0.128653f,0.987396f,-0.0921772f, +-0.120365f,0.975049f,-0.186527f, +0.0117596f,0.998991f,0.0433545f, +-0.146882f,0.98666f,-0.0701983f, +-0.218442f,0.971087f,-0.0962923f, +-0.179096f,0.983284f,-0.0328244f, +0.0658277f,0.997324f,0.0318063f, +0.120963f,0.992647f,0.00454206f, +0.0263542f,0.988052f,0.151849f, +0.0179305f,0.957276f,0.288619f, +0.0987151f,0.955923f,0.276526f, +0.113577f,0.970939f,0.210662f, +0.111989f,0.989066f,0.0959572f, +0.0937332f,0.995324f,-0.0233266f, +0.0889156f,0.995493f,-0.0329669f, +0.214527f,0.976717f,-0.0013568f, +0.281036f,0.957864f,-0.0592866f, +0.349427f,0.927689f,-0.131507f, +0.460507f,0.876585f,-0.139754f, +0.465208f,0.877856f,-0.1138f, +0.432422f,0.897621f,-0.0853653f, +0.392928f,0.918987f,-0.032723f, +0.389134f,0.920603f,0.0326418f, +0.40247f,0.914003f,0.0511488f, +0.41651f,0.90858f,0.031652f, +0.468908f,0.883168f,-0.0118055f, +0.497957f,0.862594f,-0.0892785f, +0.342146f,0.929254f,-0.139366f, +0.262957f,0.964807f,-0.00115352f, +0.156573f,0.98302f,0.095691f, +-0.0479214f,0.988417f,0.143995f, +-0.198695f,0.970386f,0.13737f, +-0.222539f,0.963461f,0.14906f, +-0.145574f,0.943362f,0.298121f, +-0.065459f,0.922659f,0.380021f, +-0.0644219f,0.950539f,0.303852f, +-0.126762f,0.967843f,0.217283f, +-0.017815f,0.980142f,0.197496f, +0.0660407f,0.994277f,0.0839804f, +-0.101583f,0.994471f,0.0266049f, +-0.224345f,0.969139f,0.102176f, +-0.280297f,0.958092f,0.0591033f, +-0.402555f,0.91416f,-0.047541f, +-0.458467f,0.883974f,-0.0916445f, +-0.50134f,0.862765f,-0.0655406f, +-0.644808f,0.754744f,-0.12077f, +-0.636358f,0.756299f,-0.151855f, +-0.556238f,0.818404f,-0.144268f, +-0.504016f,0.849904f,-0.153725f, +-0.404172f,0.887071f,-0.223046f, +-0.360363f,0.894242f,-0.265463f, +-0.432057f,0.840836f,-0.326069f, +-0.4393f,0.818603f,-0.370006f, +-0.249988f,0.890718f,-0.379642f, +-0.114697f,0.874572f,-0.471135f, +-0.0301956f,0.870113f,-0.491927f, +0.0871874f,0.907337f,-0.411263f, +0.0509325f,0.923392f,-0.380464f, +-0.106299f,0.953821f,-0.280938f, +-0.389809f,0.901657f,-0.187255f, +-0.420279f,0.904001f,-0.0784108f, +-0.360569f,0.922439f,-0.138186f, +-0.332116f,0.91853f,-0.214478f, +-0.305854f,0.899541f,-0.311896f, +-0.11957f,0.95083f,-0.285701f, +-0.0843961f,0.977455f,-0.193542f, +-0.186555f,0.968589f,-0.164414f, +-0.1142f,0.975963f,-0.185618f, +-0.138309f,0.943055f,-0.30252f, +-0.101226f,0.981339f,-0.163482f, +-0.184633f,0.97099f,-0.151951f, +-0.239394f,0.95355f,-0.182845f, +-0.0575173f,0.989733f,-0.130847f, +0.0688205f,0.993792f,0.0874178f, +-0.0714424f,0.990397f,0.118361f, +-0.0225247f,0.994972f,0.0975878f, +0.167362f,0.976776f,0.133786f, +0.156506f,0.98511f,0.0711603f, +0.198564f,0.979194f,0.0418473f, +0.173408f,0.984455f,-0.0278778f, +0.108869f,0.989375f,-0.0963545f, +0.224679f,0.96015f,-0.166226f, +0.339104f,0.91731f,-0.208688f, +0.367935f,0.88797f,-0.275922f, +0.418707f,0.869398f,-0.262357f, +0.420889f,0.892687f,-0.161129f, +0.397172f,0.910077f,-0.118378f, +0.374326f,0.920598f,-0.11126f, +0.397932f,0.911721f,-0.102056f, +0.386888f,0.911258f,-0.141166f, +0.41482f,0.902273f,-0.117593f, +0.501715f,0.859192f,-0.100356f, +0.491949f,0.863362f,-0.112214f, +0.357466f,0.931719f,-0.0641779f, +0.171333f,0.982821f,-0.068616f, +0.100623f,0.994346f,0.0339287f, +-0.0698557f,0.996834f,0.0379692f, +-0.194026f,0.980994f,0.00220452f, +-0.288205f,0.957419f,0.0169548f, +-0.304635f,0.947239f,0.0996808f, +-0.10216f,0.973655f,0.20386f, +0.100532f,0.974742f,0.199427f, +-0.0238908f,0.99964f,0.0121747f, +-0.00850096f,0.997624f,-0.0683673f, +0.116859f,0.992157f,-0.044359f, +-0.0433286f,0.998946f,-0.0151181f, +-0.258294f,0.961617f,-0.0926162f, +-0.256378f,0.96262f,-0.0873673f, +-0.327211f,0.940376f,-0.0928767f, +-0.431734f,0.888327f,-0.15646f, +-0.514253f,0.844258f,-0.150905f, +-0.599748f,0.789083f,-0.132858f, +-0.620824f,0.749219f,-0.230756f, +-0.533018f,0.803035f,-0.266508f, +-0.441513f,0.840682f,-0.313561f, +-0.38701f,0.854241f,-0.347124f, +-0.380219f,0.879441f,-0.286385f, +-0.39628f,0.874175f,-0.280679f, +-0.390488f,0.846052f,-0.362926f, +-0.205032f,0.876667f,-0.435221f, +-0.00372872f,0.883142f,-0.46909f, +-0.0083869f,0.837348f,-0.546606f, +-0.00127167f,0.831923f,-0.55489f, +-0.11424f,0.875282f,-0.469926f, +-0.256213f,0.933918f,-0.249305f, +-0.393049f,0.915109f,-0.0899313f, +-0.484342f,0.863396f,-0.141282f, +-0.32612f,0.940905f,-0.0913441f, +-0.240051f,0.956808f,-0.163992f, +-0.189326f,0.934609f,-0.301099f, +-0.228613f,0.900757f,-0.369288f, +-0.206601f,0.953154f,-0.220936f, +-0.220523f,0.958575f,-0.180285f, +-0.0691943f,0.98249f,-0.172992f, +0.0652464f,0.984331f,-0.163816f, +-0.308082f,0.909128f,-0.280306f, +-0.234588f,0.948864f,-0.211249f, +-0.164432f,0.95809f,-0.234578f, +-0.206026f,0.945244f,-0.253116f, +-0.143287f,0.989535f,-0.0170174f, +0.0124441f,0.996035f,0.0880878f, +0.00356068f,0.999352f,-0.0358152f, +0.110457f,0.993318f,-0.0334531f, +0.202646f,0.978802f,0.0296789f, +0.245502f,0.969355f,0.00893075f, +0.235742f,0.966989f,-0.096741f, +0.211469f,0.957228f,-0.197474f, +0.297424f,0.906479f,-0.299724f, +0.384843f,0.8614f,-0.331489f, +0.405425f,0.833969f,-0.374335f, +0.330388f,0.8594f,-0.390224f, +0.318232f,0.891429f,-0.32262f, +0.388106f,0.870631f,-0.302284f, +0.354731f,0.863719f,-0.357989f, +0.344798f,0.878386f,-0.330988f, +0.405293f,0.884611f,-0.230654f, +0.388923f,0.889959f,-0.23814f, +0.464087f,0.861962f,-0.20407f, +0.454884f,0.878774f,-0.144348f, +0.334448f,0.940492f,-0.0601651f, +0.155367f,0.984248f,-0.0843604f, +0.0216917f,0.991768f,-0.126198f, +-0.0136477f,0.995915f,-0.089255f, +-0.167328f,0.979282f,-0.114052f, +-0.307453f,0.946588f,-0.0971837f, +-0.335506f,0.9366f,-0.101072f, +-0.175739f,0.978185f,-0.110768f, +0.119064f,0.992411f,-0.0307238f, +0.11077f,0.993829f,0.00590121f, +0.0501349f,0.998052f,-0.0371321f, +0.0267572f,0.997581f,-0.0641572f, +-0.0614311f,0.997945f,0.0181992f, +-0.171984f,0.984492f,-0.0345973f, +-0.25243f,0.961435f,-0.109187f, +-0.338599f,0.935923f,-0.0969507f, +-0.406007f,0.913202f,-0.0349361f, +-0.506218f,0.860674f,-0.0546185f, +-0.568342f,0.8123f,-0.130983f, +-0.570141f,0.791669f,-0.219544f, +-0.495272f,0.816181f,-0.297581f, +-0.441753f,0.829099f,-0.342707f, +-0.433015f,0.854206f,-0.287802f, +-0.452692f,0.8617f,-0.229223f, +-0.349843f,0.914647f,-0.202562f, +-0.26556f,0.912134f,-0.312233f, +-0.238012f,0.870367f,-0.431058f, +0.0104117f,0.943359f,-0.331612f, +0.0744935f,0.949145f,-0.305899f, +-0.0305186f,0.956187f,-0.291161f, +-0.253914f,0.939488f,-0.229978f, +-0.449831f,0.878563f,-0.160557f, +-0.46937f,0.880955f,-0.0600792f, +-0.456075f,0.88917f,-0.0370459f, +-0.35963f,0.932902f,-0.0189682f, +-0.136797f,0.989932f,0.0363352f, +-0.0613131f,0.996495f,-0.0569106f, +-0.21207f,0.964351f,-0.158282f, +-0.303853f,0.931291f,-0.200924f, +-0.14101f,0.957182f,-0.252823f, +-0.0888984f,0.919027f,-0.384041f, +0.0067746f,0.936029f,-0.351857f, +-0.277531f,0.936633f,-0.213766f, +-0.206375f,0.947006f,-0.246148f, +-0.159145f,0.94264f,-0.293433f, +-0.254895f,0.932893f,-0.254437f, +-0.289527f,0.928279f,-0.233391f, +-0.0765713f,0.988951f,-0.126934f, +0.118605f,0.992812f,0.0160497f, +0.122094f,0.985714f,-0.116021f, +0.123131f,0.980876f,-0.150734f, +0.257926f,0.962137f,-0.0881221f, +0.397575f,0.90803f,-0.131971f, +0.301628f,0.898949f,-0.317666f, +0.360055f,0.863992f,-0.351962f, +0.391486f,0.830925f,-0.39535f, +0.399022f,0.829333f,-0.391136f, +0.323505f,0.871183f,-0.369302f, +0.290418f,0.885393f,-0.362955f, +0.422788f,0.860776f,-0.283398f, +0.400499f,0.876008f,-0.26872f, +0.272367f,0.912425f,-0.305444f, +0.289824f,0.919053f,-0.267101f, +0.375469f,0.907173f,-0.189898f, +0.450189f,0.881784f,-0.140667f, +0.386895f,0.914552f,-0.117932f, +0.236065f,0.970562f,-0.0477698f, +0.25497f,0.966484f,0.0299776f, +0.147152f,0.978905f,-0.141747f, +-0.0638684f,0.954892f,-0.290005f, +-0.198781f,0.952653f,-0.230082f, +-0.310279f,0.934977f,-0.171888f, +-0.315284f,0.933842f,-0.168923f, +-0.14676f,0.971582f,-0.185715f, +-0.0201641f,0.976785f,-0.213271f, +0.0408109f,0.997823f,-0.0518006f, +-0.000100141f,1.0f,-0.000656924f, +0.0713875f,0.992775f,0.096444f, +-0.0699693f,0.997522f,-0.0073179f, +-0.120441f,0.992484f,-0.0216487f, +-0.200799f,0.979135f,-0.0312183f, +-0.379156f,0.923729f,-0.0544518f, +-0.468756f,0.883079f,0.0209709f, +-0.451556f,0.890079f,0.0621062f, +-0.476504f,0.87674f,-0.0653536f, +-0.492274f,0.840855f,-0.22501f, +-0.481358f,0.828756f,-0.285409f, +-0.474733f,0.852404f,-0.219173f, +-0.502016f,0.852123f,-0.147874f, +-0.474734f,0.870513f,-0.12975f, +-0.344408f,0.92173f,-0.178317f, +-0.150823f,0.963991f,-0.21903f, +-0.180013f,0.935609f,-0.303696f, +-0.154788f,0.929555f,-0.334617f, +0.0226749f,0.973389f,-0.228036f, +-0.128469f,0.975007f,-0.181264f, +-0.302747f,0.952293f,-0.0385077f, +-0.427741f,0.902872f,-0.0431169f, +-0.47673f,0.871329f,-0.116249f, +-0.489254f,0.866227f,-0.101399f, +-0.407231f,0.911582f,-0.0564075f, +-0.202058f,0.978968f,-0.0281862f, +-0.00674228f,0.999486f,0.0313481f, +-0.103136f,0.994637f,-0.00773474f, +-0.196734f,0.967877f,-0.156554f, +0.0323675f,0.951182f,-0.306928f, +0.00132526f,0.886111f,-0.463472f, +-0.0819618f,0.88666f,-0.4551f, +-0.207835f,0.973361f,-0.0968142f, +-0.157163f,0.972283f,-0.173105f, +-0.187284f,0.955049f,-0.229797f, +-0.285445f,0.950862f,-0.119931f, +-0.25293f,0.964263f,-0.078892f, +-0.219599f,0.957265f,-0.188204f, +-0.0108412f,0.995374f,-0.0954668f, +0.265678f,0.963807f,-0.0221529f, +0.203794f,0.959343f,-0.195266f, +0.214345f,0.928921f,-0.301932f, +0.439386f,0.868442f,-0.22967f, +0.401404f,0.868685f,-0.290278f, +0.386804f,0.861005f,-0.330232f, +0.428054f,0.836263f,-0.342686f, +0.371108f,0.864198f,-0.339765f, +0.321515f,0.897421f,-0.302098f, +0.213518f,0.927633f,-0.306443f, +0.325579f,0.933219f,-0.151988f, +0.403183f,0.912352f,-0.0711129f, +0.337076f,0.932606f,-0.128942f, +0.295377f,0.932293f,-0.208765f, +0.330751f,0.922115f,-0.200767f, +0.392168f,0.906602f,-0.155808f, +0.373592f,0.925323f,-0.0648487f, +0.191498f,0.98018f,-0.0507507f, +0.210624f,0.977447f,-0.015309f, +0.322948f,0.945895f,0.0314047f, +0.111956f,0.981203f,-0.157186f, +-0.247376f,0.91284f,-0.32485f, +-0.344293f,0.903462f,-0.255381f, +-0.317143f,0.916625f,-0.243348f, +-0.146502f,0.958945f,-0.242819f, +-0.0529375f,0.980235f,-0.19062f, +-0.0439655f,0.993569f,-0.104344f, +-0.0681441f,0.993007f,-0.0964036f, +0.0333119f,0.999062f,-0.0276811f, +0.0418264f,0.997289f,-0.0605344f, +-0.133447f,0.982771f,-0.127878f, +-0.204776f,0.9734f,-0.102754f, +-0.405337f,0.909688f,-0.0903804f, +-0.513852f,0.857872f,0.00340788f, +-0.448907f,0.892038f,0.0524446f, +-0.345596f,0.938383f,0.000245611f, +-0.371875f,0.917654f,-0.14007f, +-0.507047f,0.834221f,-0.216744f, +-0.563482f,0.814021f,-0.140919f, +-0.549501f,0.831415f,-0.0824446f, +-0.452205f,0.89061f,-0.0482179f, +-0.283377f,0.952701f,-0.109812f, +-0.141817f,0.97445f,-0.174169f, +-0.1066f,0.981505f,-0.159008f, +-0.128743f,0.958435f,-0.254611f, +0.00656601f,0.946015f,-0.324056f, +-0.2018f,0.913066f,-0.354384f, +-0.37997f,0.904414f,-0.19406f, +-0.423353f,0.890783f,-0.165163f, +-0.446411f,0.883929f,-0.139235f, +-0.512365f,0.844229f,-0.157352f, +-0.38243f,0.91272f,-0.143839f, +-0.20154f,0.953013f,-0.226157f, +-0.104673f,0.977037f,-0.185586f, +-0.0458745f,0.998873f,-0.0121567f, +-0.0345945f,0.993617f,-0.107371f, +0.172752f,0.948616f,-0.265111f, +0.0733608f,0.946968f,-0.312842f, +-0.16546f,0.93251f,-0.321012f, +-0.129843f,0.991294f,-0.0218587f, +-0.0514732f,0.996939f,-0.0588533f, +-0.139666f,0.979954f,-0.142066f, +-0.409538f,0.893138f,-0.185964f, +-0.25948f,0.963277f,-0.0690542f, +-0.106228f,0.993322f,-0.0450175f, +-0.047863f,0.993002f,-0.107966f, +0.238746f,0.962198f,-0.131057f, +0.395076f,0.900486f,-0.181771f, +0.285693f,0.874669f,-0.391577f, +0.358513f,0.848133f,-0.39005f, +0.400938f,0.884343f,-0.239137f, +0.415724f,0.899223f,-0.136277f, +0.438653f,0.894164f,-0.0897495f, +0.361082f,0.930821f,-0.0565009f, +0.321158f,0.946416f,-0.0339725f, +0.242073f,0.961641f,-0.129024f, +0.199607f,0.93926f,-0.279192f, +0.404284f,0.887623f,-0.220636f, +0.424881f,0.860893f,-0.279892f, +0.291182f,0.870529f,-0.396727f, +0.302468f,0.897545f,-0.320822f, +0.33835f,0.898885f,-0.278433f, +0.289098f,0.929341f,-0.229667f, +0.170367f,0.971163f,-0.166783f, +0.129237f,0.986609f,-0.0995005f, +0.305057f,0.951694f,0.0349234f, +0.306439f,0.951736f,-0.0171507f, +-0.0808802f,0.976235f,-0.201056f, +-0.37625f,0.871862f,-0.313516f, +-0.307717f,0.906797f,-0.28815f, +-0.221648f,0.946026f,-0.236446f, +-0.153972f,0.983161f,-0.0984244f, +-0.108206f,0.992418f,-0.0582996f, +-0.0581427f,0.997361f,-0.0434687f, +0.00296039f,0.999365f,-0.0355116f, +0.0891034f,0.995894f,-0.0160169f, +-0.110645f,0.991801f,-0.0639364f, +-0.218461f,0.975223f,-0.0348525f, +-0.395365f,0.918398f,-0.0152307f, +-0.576836f,0.816159f,-0.0338453f, +-0.444941f,0.895556f,-0.00249309f, +-0.286239f,0.957764f,-0.0274641f, +-0.294715f,0.953259f,-0.0666355f, +-0.477956f,0.87064f,-0.116377f, +-0.574643f,0.800737f,-0.169131f, +-0.54804f,0.808388f,-0.214852f, +-0.442187f,0.863382f,-0.242986f, +-0.246722f,0.934143f,-0.257887f, +-0.157124f,0.964153f,-0.213827f, +-0.112706f,0.987993f,-0.10568f, +-0.0332674f,0.993709f,-0.106936f, +0.112688f,0.981964f,-0.151814f, +-0.167f,0.962022f,-0.215928f, +-0.466198f,0.854366f,-0.229606f, +-0.414399f,0.885329f,-0.210869f, +-0.461383f,0.855213f,-0.236084f, +-0.488245f,0.847976f,-0.206287f, +-0.351309f,0.900136f,-0.257559f, +-0.14601f,0.942734f,-0.29989f, +-0.222931f,0.937875f,-0.265879f, +-0.195469f,0.970505f,-0.141106f, +0.07525f,0.994532f,-0.0724173f, +0.279727f,0.951429f,-0.128592f, +0.077712f,0.980159f,-0.182341f, +-0.20264f,0.956685f,-0.209022f, +-0.0986596f,0.987061f,-0.126403f, +-0.0477559f,0.985147f,-0.164941f, +-0.0669351f,0.983547f,-0.167793f, +-0.331517f,0.915331f,-0.228616f, +-0.350669f,0.900109f,-0.258526f, +-0.179805f,0.971282f,-0.155824f, +0.0156578f,0.989915f,-0.140797f, +0.301547f,0.9226f,-0.240579f, +0.457383f,0.852861f,-0.25185f, +0.449776f,0.84917f,-0.276789f, +0.26609f,0.885033f,-0.381984f, +0.182331f,0.952085f,-0.245538f, +0.260541f,0.964562f,-0.0416928f, +0.408684f,0.907067f,0.101033f, +0.342263f,0.936545f,0.0757594f, +0.318298f,0.944991f,0.0753604f, +0.467785f,0.882822f,0.0424513f, +0.409568f,0.864687f,-0.290809f, +0.379738f,0.82358f,-0.421325f, +0.451329f,0.792384f,-0.410402f, +0.275091f,0.868881f,-0.411547f, +0.161796f,0.92881f,-0.333367f, +0.286521f,0.932696f,-0.219053f, +0.272475f,0.944744f,-0.182252f, +0.119383f,0.965719f,-0.230508f, +-0.0212448f,0.971989f,-0.234063f, +0.226311f,0.969491f,-0.094178f, +0.326176f,0.942844f,-0.068215f, +0.104404f,0.994209f,-0.0254499f, +-0.295807f,0.921372f,-0.252133f, +-0.383855f,0.886842f,-0.257228f, +-0.359597f,0.921141f,-0.148961f, +-0.240318f,0.969399f,-0.0501282f, +-0.0922578f,0.994071f,-0.0575481f, +-0.0797027f,0.995693f,-0.047355f, +-0.026569f,0.999636f,0.00472767f, +0.105393f,0.994402f,0.00758912f, +-0.0968377f,0.99427f,-0.0452707f, +-0.304918f,0.952227f,0.0169656f, +-0.404524f,0.901318f,0.154875f, +-0.513873f,0.850873f,0.109318f, +-0.450348f,0.892744f,-0.0139455f, +-0.274075f,0.961559f,-0.0169546f, +-0.246789f,0.966677f,-0.068048f, +-0.421796f,0.89143f,-0.165651f, +-0.530762f,0.820949f,-0.210556f, +-0.518596f,0.828643f,-0.210734f, +-0.419929f,0.882924f,-0.210013f, +-0.267086f,0.925885f,-0.26721f, +-0.260528f,0.916111f,-0.304739f, +-0.212437f,0.941505f,-0.261606f, +-0.048105f,0.973033f,-0.225594f, +0.0765563f,0.979806f,-0.184712f, +-0.093108f,0.98921f,-0.113109f, +-0.45825f,0.862094f,-0.216335f, +-0.388948f,0.902314f,-0.185873f, +-0.448149f,0.871913f,-0.197307f, +-0.488741f,0.854988f,-0.173574f, +-0.313337f,0.916762f,-0.247724f, +-0.157546f,0.938004f,-0.308753f, +-0.267357f,0.911027f,-0.313926f, +-0.236818f,0.920159f,-0.311809f, +0.000164176f,0.954985f,-0.296656f, +0.271822f,0.944232f,-0.185848f, +0.151331f,0.970946f,-0.185371f, +-0.118147f,0.962507f,-0.244174f, +0.026977f,0.993643f,-0.109301f, +0.00824696f,0.988318f,-0.152184f, +-0.049843f,0.98983f,-0.133236f, +-0.292853f,0.946012f,-0.138915f, +-0.402779f,0.899681f,-0.168355f, +-0.216565f,0.962959f,-0.160656f, +0.0811851f,0.971223f,-0.223909f, +0.376654f,0.888442f,-0.262304f, +0.412611f,0.862287f,-0.293621f, +0.420494f,0.885689f,-0.196825f, +0.303261f,0.948914f,-0.0871512f, +0.0927021f,0.987654f,-0.12628f, +0.131263f,0.975894f,-0.174359f, +0.34789f,0.928255f,-0.131586f, +0.388684f,0.916314f,-0.0964015f, +0.334363f,0.935247f,-0.116251f, +0.500896f,0.857152f,-0.119971f, +0.598542f,0.784881f,-0.160341f, +0.47847f,0.803478f,-0.354245f, +0.40143f,0.813052f,-0.421663f, +0.177917f,0.923323f,-0.340324f, +0.0444056f,0.967329f,-0.249605f, +0.182957f,0.975679f,-0.12074f, +0.298547f,0.954355f,0.00877178f, +0.20958f,0.975318f,-0.0695111f, +0.014388f,0.988042f,-0.153512f, +0.159715f,0.970499f,-0.180618f, +0.22067f,0.966546f,-0.130745f, +0.121564f,0.992499f,-0.0129668f, +-0.106928f,0.989668f,-0.0955226f, +-0.432009f,0.877086f,-0.209972f, +-0.412195f,0.894243f,-0.174429f, +-0.247992f,0.954923f,-0.163162f, +-0.103668f,0.985418f,-0.134925f, +-0.118626f,0.990103f,-0.0749928f, +-0.0679366f,0.995617f,-0.0642786f, +0.157737f,0.986207f,-0.0501565f, +-0.132086f,0.989105f,-0.064997f, +-0.385668f,0.914108f,0.125169f, +-0.489653f,0.859555f,0.146305f, +-0.451033f,0.881762f,0.138074f, +-0.379544f,0.923663f,0.0528468f, +-0.267976f,0.962936f,0.0307148f, +-0.154653f,0.986101f,0.0607174f, +-0.285519f,0.958009f,-0.0264139f, +-0.517333f,0.83498f,-0.187551f, +-0.544673f,0.81339f,-0.204273f, +-0.443255f,0.872475f,-0.205697f, +-0.212541f,0.959106f,-0.18693f, +-0.144834f,0.956217f,-0.254307f, +-0.219765f,0.912031f,-0.346271f, +-0.054698f,0.959311f,-0.277002f, +-0.0226538f,0.964658f,-0.262528f, +-0.09277f,0.980401f,-0.173803f, +-0.427129f,0.87184f,-0.2397f, +-0.458168f,0.877303f,-0.142906f, +-0.456008f,0.884075f,-0.102317f, +-0.457836f,0.873049f,-0.167843f, +-0.276231f,0.922652f,-0.269091f, +-0.0986428f,0.965162f,-0.242345f, +-0.166497f,0.944239f,-0.284061f, +-0.221568f,0.881867f,-0.416194f, +-0.047486f,0.902488f,-0.428089f, +0.159799f,0.906084f,-0.391761f, +0.154437f,0.936571f,-0.314616f, +-0.0388024f,0.943344f,-0.329539f, +0.0179311f,0.971802f,-0.235116f, +-0.0317957f,0.972144f,-0.232219f, +-0.108238f,0.982139f,-0.153906f, +-0.294778f,0.950488f,-0.098378f, +-0.31352f,0.940894f,-0.128155f, +-0.158161f,0.944104f,-0.289226f, +0.136392f,0.925587f,-0.353108f, +0.369725f,0.858345f,-0.355736f, +0.408427f,0.863142f,-0.296941f, +0.264495f,0.934318f,-0.238939f, +0.231394f,0.968992f,-0.0866717f, +0.180537f,0.980662f,-0.0755592f, +0.289728f,0.94884f,-0.125539f, +0.338081f,0.901985f,-0.268559f, +0.344111f,0.905129f,-0.249658f, +0.337921f,0.897299f,-0.284014f, +0.46242f,0.831252f,-0.308526f, +0.625979f,0.756355f,-0.18994f, +0.59942f,0.766009f,-0.232218f, +0.396651f,0.850096f,-0.346416f, +0.113051f,0.922761f,-0.368417f, +-0.0568672f,0.928859f,-0.366041f, +0.0370994f,0.962262f,-0.269583f, +0.21844f,0.959083f,-0.180121f, +0.248457f,0.958661f,-0.138705f, +0.0562715f,0.995806f,-0.072134f, +0.151796f,0.987439f,-0.0438309f, +0.213126f,0.976907f,0.0151789f, +0.0825188f,0.995896f,-0.0371849f, +-0.0293603f,0.995761f,-0.0871655f, +-0.339382f,0.929166f,-0.146528f, +-0.407976f,0.887929f,-0.212458f, +-0.300706f,0.928797f,-0.216592f, +-0.171876f,0.971688f,-0.162117f, +-0.133134f,0.975354f,-0.175954f, +-0.0436112f,0.969589f,-0.240823f, +0.0955252f,0.97277f,-0.211171f, +-0.222971f,0.974797f,-0.00733171f, +-0.502187f,0.842082f,0.19674f, +-0.406382f,0.878535f,0.251057f, +-0.403841f,0.907763f,0.113486f, +-0.295941f,0.954472f,0.0374491f, +-0.309098f,0.948653f,-0.0672074f, +-0.212726f,0.977025f,0.0130525f, +-0.199979f,0.978912f,0.0417118f, +-0.374584f,0.922961f,-0.0884893f, +-0.481248f,0.836641f,-0.261597f, +-0.419239f,0.839768f,-0.345005f, +-0.269419f,0.905569f,-0.327654f, +-0.084614f,0.973021f,-0.214643f, +-0.193736f,0.935164f,-0.296537f, +-0.190273f,0.932167f,-0.307995f, +-0.0917672f,0.986648f,-0.134552f, +-0.101923f,0.994749f,0.009248f, +-0.329353f,0.943234f,-0.0428565f, +-0.527408f,0.832391f,-0.170191f, +-0.427451f,0.895563f,-0.123505f, +-0.337252f,0.917187f,-0.212202f, +-0.254472f,0.911026f,-0.324462f, +-0.191138f,0.941948f,-0.276043f, +-0.0895186f,0.969134f,-0.229708f, +-0.115141f,0.935532f,-0.33395f, +-0.0316994f,0.925937f,-0.376346f, +0.117945f,0.920189f,-0.373285f, +0.121803f,0.934924f,-0.333287f, +-0.0046923f,0.925271f,-0.379279f, +0.0524128f,0.95708f,-0.285046f, +-0.0476851f,0.956392f,-0.288167f, +-0.185718f,0.956668f,-0.224263f, +-0.292875f,0.939689f,-0.176661f, +-0.212138f,0.937073f,-0.277295f, +0.00215598f,0.9095f,-0.415698f, +0.155074f,0.855231f,-0.494501f, +0.3372f,0.836708f,-0.431528f, +0.272726f,0.886233f,-0.374449f, +0.193484f,0.944931f,-0.263949f, +0.192169f,0.938969f,-0.285322f, +0.141281f,0.932743f,-0.331708f, +0.278032f,0.931044f,-0.236339f, +0.426985f,0.871432f,-0.241434f, +0.368362f,0.861689f,-0.349f, +0.400587f,0.825418f,-0.397762f, +0.451323f,0.785144f,-0.424095f, +0.523643f,0.765884f,-0.373121f, +0.603289f,0.753586f,-0.261056f, +0.44978f,0.832328f,-0.323928f, +0.156509f,0.915232f,-0.371289f, +-0.0704135f,0.915939f,-0.395092f, +-0.00319557f,0.926331f,-0.376696f, +0.166676f,0.911893f,-0.37506f, +0.102989f,0.962696f,-0.250219f, +-0.0387958f,0.995347f,-0.0881961f, +0.0653507f,0.992864f,-0.0997527f, +0.179449f,0.98367f,-0.0138117f, +0.177828f,0.983985f,0.012264f, +0.0645076f,0.995168f,-0.0740203f, +-0.292502f,0.938695f,-0.182468f, +-0.400433f,0.889464f,-0.220243f, +-0.318802f,0.923541f,-0.213161f, +-0.169897f,0.961934f,-0.214052f, +-0.0267051f,0.972116f,-0.232975f, +-0.00536052f,0.964395f,-0.264412f, +-0.100769f,0.988596f,-0.111905f, +-0.404303f,0.910751f,0.0840968f, +-0.594207f,0.803932f,0.0247338f, +-0.396136f,0.914658f,0.0804795f, +-0.304433f,0.952514f,0.00620435f, +-0.201276f,0.977901f,-0.0565476f, +-0.264949f,0.959844f,-0.0922019f, +-0.227773f,0.971084f,-0.0715179f, +-0.172114f,0.969698f,-0.173387f, +-0.26936f,0.945102f,-0.185006f, +-0.392685f,0.904465f,-0.166556f, +-0.407044f,0.896103f,-0.176958f, +-0.40747f,0.889993f,-0.204647f, +-0.189782f,0.978511f,-0.0806113f, +-0.0480587f,0.996223f,-0.0723184f, +-0.217275f,0.958525f,-0.184451f, +-0.306094f,0.944116f,-0.122276f, +-0.254593f,0.966558f,0.0308049f, +-0.20196f,0.972664f,0.114613f, +-0.409794f,0.899925f,-0.14901f, +-0.415034f,0.857771f,-0.303274f, +-0.263165f,0.89665f,-0.356039f, +-0.215387f,0.884962f,-0.412857f, +-0.225079f,0.887943f,-0.401119f, +-0.0773061f,0.916142f,-0.393328f, +-0.0308036f,0.905486f,-0.423257f, +-0.0371917f,0.883129f,-0.467653f, +0.0716369f,0.893813f,-0.442681f, +0.12997f,0.919319f,-0.371429f, +0.119867f,0.921216f,-0.370126f, +0.0228827f,0.984493f,-0.173923f, +-0.0834452f,0.988816f,-0.123614f, +-0.247718f,0.964917f,-0.0870125f, +-0.254118f,0.961997f,-0.0999321f, +-0.0671834f,0.977202f,-0.201403f, +0.157483f,0.940773f,-0.300243f, +0.164503f,0.92764f,-0.335294f, +0.27582f,0.929794f,-0.243733f, +0.209142f,0.946949f,-0.244024f, +0.183638f,0.949161f,-0.255677f, +0.277174f,0.906106f,-0.319605f, +0.178788f,0.896597f,-0.405153f, +0.185529f,0.860132f,-0.475134f, +0.438868f,0.800307f,-0.408538f, +0.441024f,0.788796f,-0.428135f, +0.397261f,0.791714f,-0.464083f, +0.440809f,0.77176f,-0.458338f, +0.455755f,0.768172f,-0.449666f, +0.535299f,0.762932f,-0.362477f, +0.450448f,0.842352f,-0.295872f, +0.136515f,0.937333f,-0.320579f, +-0.0637901f,0.937145f,-0.343061f, +-0.0112309f,0.935306f,-0.353662f, +0.108413f,0.948157f,-0.298738f, +-0.0660356f,0.972239f,-0.224477f, +-0.07256f,0.985988f,-0.150208f, +0.0814078f,0.980504f,-0.178842f, +0.133209f,0.989139f,-0.0621265f, +0.112681f,0.993117f,-0.0319677f, +0.144875f,0.987157f,0.0673239f, +-0.178705f,0.983714f,-0.0192655f, +-0.383305f,0.919432f,-0.0878717f, +-0.311703f,0.944518f,-0.103569f, +-0.170547f,0.974222f,-0.147663f, +-0.0584686f,0.987712f,-0.144938f, +-0.130239f,0.988008f,-0.0829397f, +-0.30957f,0.949755f,0.0461837f, +-0.426068f,0.896859f,0.118784f, +-0.505712f,0.862298f,-0.0263905f, +-0.384432f,0.913927f,-0.130189f, +-0.233817f,0.957708f,-0.167708f, +-0.196686f,0.961804f,-0.190386f, +-0.272431f,0.94059f,-0.202662f, +-0.180772f,0.950727f,-0.251872f, +-0.0565853f,0.956064f,-0.287647f, +-0.288561f,0.926858f,-0.240141f, +-0.491099f,0.856076f,-0.161104f, +-0.419638f,0.904096f,-0.0807095f, +-0.388583f,0.916169f,-0.0981701f, +-0.261262f,0.961028f,-0.0903754f, +-0.0632456f,0.997064f,0.0431658f, +-0.169715f,0.97859f,0.116442f, +-0.344027f,0.938297f,0.0352825f, +-0.314669f,0.949192f,0.00417096f, +-0.192981f,0.980434f,0.0388389f, +-0.184602f,0.98279f,-0.00683269f, +-0.246496f,0.934378f,-0.25725f, +-0.19921f,0.861846f,-0.466409f, +-0.140436f,0.848535f,-0.510163f, +-0.20288f,0.807079f,-0.554493f, +-0.11519f,0.832336f,-0.542169f, +0.00924053f,0.875455f,-0.483211f, +-0.00888073f,0.876341f,-0.48161f, +0.00107193f,0.907613f,-0.419807f, +0.021101f,0.930448f,-0.365817f, +0.0745313f,0.948396f,-0.308205f, +-0.200438f,0.964136f,-0.17397f, +-0.166231f,0.985214f,-0.0414839f, +-0.252324f,0.967639f,-0.00281073f, +-0.16447f,0.986195f,-0.0192238f, +0.0101706f,0.983613f,-0.180006f, +0.16229f,0.966979f,-0.196502f, +0.152128f,0.981833f,-0.113406f, +0.194455f,0.973444f,-0.120809f, +0.334057f,0.938492f,-0.0874058f, +0.243016f,0.928299f,-0.281434f, +0.337071f,0.885295f,-0.320369f, +0.298461f,0.876938f,-0.376698f, +0.311828f,0.819683f,-0.480502f, +0.369257f,0.755567f,-0.54108f, +0.401798f,0.784012f,-0.473163f, +0.404891f,0.784738f,-0.469309f, +0.444437f,0.782155f,-0.436702f, +0.466084f,0.794919f,-0.388419f, +0.447341f,0.805216f,-0.389247f, +0.362297f,0.887389f,-0.285098f, +0.179937f,0.962799f,-0.201595f, +0.000795301f,0.958246f,-0.285946f, +-0.0439986f,0.938528f,-0.342389f, +0.000314903f,0.959745f,-0.280871f, +-0.0200826f,0.975564f,-0.218794f, +-0.0669112f,0.936012f,-0.345551f, +0.0051897f,0.948012f,-0.318192f, +0.0134178f,0.970832f,-0.239387f, +0.036317f,0.978504f,-0.203005f, +0.0625457f,0.996542f,-0.0547064f, +-0.151505f,0.986626f,0.0601296f, +-0.354535f,0.929709f,0.0997293f, +-0.323458f,0.940866f,0.100727f, +-0.112965f,0.981029f,0.157548f, +-0.108156f,0.989168f,0.0992381f, +-0.141093f,0.979303f,0.145114f, +-0.335564f,0.940028f,0.061184f, +-0.404784f,0.910739f,0.081883f, +-0.415621f,0.909054f,0.0296628f, +-0.326024f,0.941449f,-0.0859172f, +-0.204455f,0.961807f,-0.182004f, +-0.198427f,0.946732f,-0.253624f, +-0.160629f,0.949f,-0.27129f, +-0.122223f,0.918206f,-0.376775f, +-0.161284f,0.939678f,-0.301651f, +-0.374966f,0.911783f,-0.167489f, +-0.467696f,0.856498f,-0.218336f, +-0.443475f,0.843003f,-0.304427f, +-0.385194f,0.898165f,-0.211955f, +-0.377418f,0.917998f,-0.121804f, +-0.264639f,0.962925f,0.0523651f, +-0.211739f,0.961017f,0.177801f, +-0.229995f,0.957255f,0.175401f, +-0.280377f,0.956102f,0.0851875f, +-0.20016f,0.97825f,0.0544282f, +-0.10573f,0.994257f,-0.0165441f, +0.0203896f,0.991211f,-0.130708f, +-0.0236073f,0.94884f,-0.314873f, +-0.0941765f,0.92043f,-0.379394f, +-0.167941f,0.897458f,-0.407879f, +-0.187085f,0.877031f,-0.442511f, +-0.0729267f,0.89358f,-0.44294f, +-0.0781669f,0.903365f,-0.421688f, +-0.0898224f,0.927661f,-0.362461f, +-0.0306254f,0.944826f,-0.326139f, +0.00767666f,0.952077f,-0.305762f, +-0.288656f,0.939633f,-0.183761f, +-0.235623f,0.952993f,-0.190489f, +-0.273085f,0.931861f,-0.238874f, +-0.0949222f,0.974332f,-0.204123f, +0.149266f,0.955245f,-0.255397f, +0.0666117f,0.957576f,-0.280376f, +0.127398f,0.979355f,-0.156952f, +0.209457f,0.954497f,-0.21228f, +0.367092f,0.913409f,-0.175864f, +0.415953f,0.865553f,-0.278928f, +0.34245f,0.832959f,-0.434635f, +0.340781f,0.830404f,-0.440793f, +0.395293f,0.802521f,-0.446882f, +0.405952f,0.792834f,-0.454552f, +0.385024f,0.788348f,-0.479858f, +0.365166f,0.783008f,-0.503539f, +0.371074f,0.838688f,-0.39863f, +0.42233f,0.859897f,-0.286732f, +0.440629f,0.882917f,-0.162183f, +0.299827f,0.949298f,-0.0945333f, +0.141695f,0.979344f,-0.144247f, +0.039666f,0.992248f,-0.117771f, +0.021245f,0.997585f,-0.0661304f, +-0.0594041f,0.983411f,-0.17139f, +0.0611812f,0.981318f,-0.182404f, +0.0186916f,0.932529f,-0.360611f, +-0.0300853f,0.91754f,-0.396504f, +-0.00135599f,0.922081f,-0.386995f, +-0.0351954f,0.956784f,-0.28866f, +-0.108108f,0.976189f,-0.188065f, +-0.279221f,0.950183f,-0.13852f, +-0.398641f,0.914814f,-0.0648175f, +-0.383626f,0.922668f,-0.0389249f, +-0.188191f,0.977628f,0.0939533f, +-0.083441f,0.973103f,0.21473f, +-0.0631642f,0.980575f,0.185698f, +-0.269017f,0.963031f,0.0141438f, +-0.4376f,0.89917f,-0.000301879f, +-0.339736f,0.940513f,0.00384959f, +-0.235638f,0.967987f,-0.0864624f, +-0.0773761f,0.988655f,-0.128744f, +-0.0852549f,0.968269f,-0.234917f, +-0.114948f,0.939941f,-0.3214f, +-0.156571f,0.928217f,-0.337488f, +-0.29563f,0.924155f,-0.241951f, +-0.401682f,0.899225f,-0.173337f, +-0.351799f,0.915761f,-0.193956f, +-0.391021f,0.882077f,-0.262761f, +-0.525453f,0.810665f,-0.258305f, +-0.504092f,0.859496f,-0.0846014f, +-0.362403f,0.931317f,0.0362275f, +-0.27912f,0.954258f,0.107159f, +-0.207619f,0.961802f,0.178414f, +-0.228638f,0.970139f,0.0809669f, +-0.12077f,0.992669f,0.00484841f, +0.0304882f,0.99448f,-0.100401f, +0.0674392f,0.979801f,-0.18826f, +0.0351304f,0.9953f,-0.090241f, +-0.0704736f,0.995263f,-0.0669708f, +-0.129706f,0.981562f,-0.1404f, +-0.122442f,0.956888f,-0.263387f, +-0.0356665f,0.922731f,-0.38379f, +-0.0454106f,0.896226f,-0.441267f, +-0.0870705f,0.865568f,-0.493164f, +-0.0312927f,0.854755f,-0.518087f, +-0.0110302f,0.85359f,-0.520829f, +-0.135251f,0.990349f,0.0302781f, +-0.120846f,0.991438f,-0.049458f, +-0.156404f,0.974115f,-0.163209f, +-0.121903f,0.951948f,-0.280952f, +0.0966131f,0.959924f,-0.263082f, +0.0624341f,0.96714f,-0.24646f, +0.0557469f,0.94749f,-0.31489f, +0.245712f,0.928812f,-0.27737f, +0.339947f,0.895451f,-0.28741f, +0.505833f,0.828917f,-0.238808f, +0.492153f,0.815708f,-0.303985f, +0.325713f,0.824266f,-0.463138f, +0.357884f,0.8174f,-0.451416f, +0.423911f,0.828952f,-0.364879f, +0.465983f,0.818349f,-0.3364f, +0.340136f,0.856815f,-0.387524f, +0.250037f,0.902839f,-0.349804f, +0.270063f,0.93551f,-0.227788f, +0.268197f,0.961943f,0.0523086f, +0.314452f,0.921737f,0.226982f, +0.230483f,0.962611f,0.142328f, +-0.0337231f,0.996519f,0.0762456f, +-0.0478467f,0.987694f,0.1489f, +0.0777224f,0.977564f,0.195776f, +0.137813f,0.987309f,0.0789204f, +0.213773f,0.976881f,-0.00209812f, +0.0678985f,0.982243f,-0.174896f, +-0.118448f,0.956882f,-0.26523f, +-0.229961f,0.9707f,-0.0697049f, +-0.144208f,0.98561f,0.0881926f, +-0.198479f,0.979386f,0.0375393f, +-0.401292f,0.909987f,-0.104347f, +-0.400254f,0.91005f,-0.107726f, +-0.346067f,0.932825f,-0.100374f, +-0.193125f,0.981161f,0.00517742f, +-0.0334943f,0.995589f,0.0876359f, +-0.09901f,0.987334f,0.12397f, +-0.411919f,0.909058f,-0.0627387f, +-0.33988f,0.934279f,-0.107727f, +-0.163445f,0.980417f,-0.109859f, +-0.094399f,0.976137f,-0.195566f, +-0.0281723f,0.98965f,-0.140708f, +-0.0765865f,0.985816f,-0.149338f, +-0.168645f,0.974838f,-0.145776f, +-0.316363f,0.934327f,-0.164156f, +-0.429172f,0.879196f,-0.206943f, +-0.428946f,0.898522f,-0.0930795f, +-0.397223f,0.909843f,0.12f, +-0.511164f,0.850782f,0.12199f, +-0.553545f,0.831305f,-0.0501975f, +-0.425265f,0.901367f,-0.0817687f, +-0.377377f,0.925701f,-0.0257517f, +-0.226427f,0.969468f,0.0941363f, +-0.0709665f,0.993431f,0.0897693f, +-0.0343935f,0.997803f,-0.0566276f, +0.136725f,0.981098f,-0.136942f, +-0.000388307f,0.974615f,-0.223888f, +-0.143125f,0.988947f,-0.0387096f, +-0.0654844f,0.993475f,0.0933713f, +0.0107967f,0.999865f,0.0124207f, +0.0463655f,0.990074f,-0.132676f, +0.111072f,0.958636f,-0.262069f, +0.052211f,0.918497f,-0.391967f, +0.014765f,0.869476f,-0.493754f, +-0.00446669f,0.826302f,-0.56321f, +-0.00312167f,0.829643f,-0.558286f, +-0.205328f,0.971118f,-0.121531f, +-0.107279f,0.990692f,-0.0837913f, +-0.0655817f,0.993795f,-0.089834f, +-0.0669083f,0.985851f,-0.15369f, +0.0877486f,0.98832f,-0.124596f, +0.169572f,0.978484f,-0.117533f, +0.160152f,0.950603f,-0.265903f, +0.208233f,0.926f,-0.314903f, +0.349792f,0.904675f,-0.243329f, +0.449891f,0.870303f,-0.200426f, +0.566229f,0.816333f,-0.113956f, +0.48817f,0.833849f,-0.257655f, +0.363235f,0.831342f,-0.420631f, +0.324206f,0.826771f,-0.459718f, +0.3997f,0.840833f,-0.365021f, +0.353025f,0.906211f,-0.232714f, +0.219616f,0.962891f,-0.156874f, +0.0720827f,0.994934f,-0.0700696f, +0.045678f,0.994046f,0.0989266f, +0.213575f,0.964796f,0.153475f, +0.24905f,0.930442f,0.268798f, +0.0777133f,0.945053f,0.317546f, +-0.128028f,0.977296f,0.168824f, +0.0217263f,0.951068f,0.308215f, +0.207313f,0.918764f,0.335998f, +0.282654f,0.924456f,0.255906f, +0.201157f,0.96204f,0.184429f, +-0.110233f,0.981395f,0.157205f, +-0.355659f,0.909169f,0.216606f, +-0.21295f,0.947904f,0.236917f, +-0.107393f,0.959263f,0.261306f, +-0.278087f,0.947596f,0.157257f, +-0.393558f,0.918794f,0.0304824f, +-0.302068f,0.952957f,-0.0250724f, +-0.213276f,0.970666f,-0.110997f, +-0.166999f,0.978773f,-0.118807f, +-0.142246f,0.989828f,0.00258048f, +-0.283745f,0.958854f,0.0093455f, +-0.336957f,0.941016f,-0.0308147f, +-0.113565f,0.9931f,-0.02925f, +-0.0231129f,0.991621f,-0.127093f, +-0.107284f,0.981887f,-0.156166f, +-0.121783f,0.990389f,-0.0655664f, +-0.179469f,0.983757f,0.00373427f, +-0.267261f,0.963295f,0.0251965f, +-0.419417f,0.907445f,0.0251735f, +-0.582729f,0.80835f,0.0836507f, +-0.554692f,0.78035f,0.288741f, +-0.368624f,0.840437f,0.397218f, +-0.336016f,0.929619f,0.151335f, +-0.379048f,0.912637f,-0.153022f, +-0.410461f,0.89244f,-0.187275f, +-0.310698f,0.938768f,-0.148932f, +-0.0772428f,0.993562f,-0.0828798f, +0.0559112f,0.996518f,-0.0618564f, +0.218481f,0.971621f,-0.090653f, +0.0070055f,0.988587f,-0.150488f, +-0.287385f,0.949521f,-0.125778f, +-0.0963797f,0.992515f,-0.0749989f, +0.0940601f,0.994076f,-0.0544632f, +0.147534f,0.985277f,-0.0863886f, +0.20617f,0.964455f,-0.165287f, +0.228919f,0.941159f,-0.248628f, +0.142687f,0.889558f,-0.433967f, +0.0525074f,0.86193f,-0.5043f, +-0.0400559f,0.852931f,-0.520485f, +-0.12929f,0.965503f,-0.226025f, +-0.12119f,0.954637f,-0.271994f, +-0.0677494f,0.970158f,-0.232815f, +-0.0658176f,0.978188f,-0.197017f, +0.00868199f,0.985201f,-0.171183f, +0.183883f,0.977449f,-0.103828f, +0.283397f,0.948052f,-0.144513f, +0.244002f,0.935244f,-0.256481f, +0.251457f,0.918413f,-0.305429f, +0.421894f,0.885288f,-0.195626f, +0.539016f,0.82675f,-0.161076f, +0.595125f,0.795068f,-0.117014f, +0.542945f,0.81823f,-0.188971f, +0.36087f,0.878337f,-0.313523f, +0.249934f,0.94591f,-0.206849f, +0.203095f,0.978645f,0.0317209f, +0.0808087f,0.992314f,0.0937131f, +0.015528f,0.990219f,0.138653f, +0.01799f,0.994881f,0.09944f, +0.195411f,0.975412f,0.101915f, +0.0694818f,0.977162f,0.200816f, +0.0667035f,0.917371f,0.392404f, +-0.00815505f,0.942331f,0.334582f, +-0.124548f,0.965608f,0.228228f, +0.172601f,0.943034f,0.284421f, +0.392995f,0.877789f,0.273937f, +0.148864f,0.962548f,0.226586f, +-0.160978f,0.90924f,0.383887f, +-0.338041f,0.865118f,0.370538f, +-0.158685f,0.913484f,0.374654f, +-0.085827f,0.934088f,0.346573f, +-0.160284f,0.956319f,0.244467f, +-0.286424f,0.955431f,0.0715057f, +-0.239888f,0.970684f,0.0150701f, +-0.160609f,0.986985f,0.00807186f, +-0.109896f,0.993313f,-0.0353894f, +-0.197211f,0.969041f,-0.148551f, +-0.329877f,0.939761f,-0.0896172f, +-0.308832f,0.948199f,-0.0744408f, +-0.098416f,0.980296f,-0.171271f, +0.0274733f,0.990192f,-0.136989f, +-0.0841565f,0.99088f,-0.105235f, +-0.256459f,0.960709f,-0.106143f, +-0.249667f,0.95978f,0.128406f, +-0.305999f,0.931391f,0.197168f, +-0.484241f,0.852569f,0.196565f, +-0.610379f,0.753144f,0.245383f, +-0.585787f,0.783089f,0.208867f, +-0.367515f,0.91758f,0.151588f, +-0.0411995f,0.989239f,0.140389f, +-0.109078f,0.987353f,-0.115051f, +-0.380949f,0.866858f,-0.321615f, +-0.342318f,0.88779f,-0.307647f, +-0.12792f,0.955198f,-0.266896f, +0.0278952f,0.967981f,-0.249469f, +0.188442f,0.9544f,-0.231539f, +0.052008f,0.978364f,-0.200246f, +-0.225418f,0.931417f,-0.285742f, +-0.134566f,0.926089f,-0.352493f, +0.0345745f,0.959769f,-0.278653f, +0.174695f,0.953806f,-0.24441f, +0.227273f,0.930386f,-0.287627f, +0.325716f,0.918321f,-0.224934f, +0.329407f,0.888239f,-0.32019f, +0.0905336f,0.875389f,-0.474867f, +-0.0331275f,0.86706f,-0.497102f, +0.0288126f,0.978255f,-0.205394f, +-0.0838329f,0.954569f,-0.285956f, +-0.140323f,0.954698f,-0.262415f, +-0.112432f,0.972197f,-0.205408f, +0.0092799f,0.981035f,-0.193608f, +0.142017f,0.962963f,-0.229203f, +0.310781f,0.933484f,-0.17895f, +0.359578f,0.919553f,-0.158514f, +0.334745f,0.907674f,-0.253129f, +0.345814f,0.873436f,-0.342815f, +0.500723f,0.821828f,-0.271799f, +0.538977f,0.812424f,-0.22242f, +0.523422f,0.839245f,-0.147303f, +0.340441f,0.940266f,0.000412888f, +0.0152874f,0.997305f,0.0717554f, +0.0533145f,0.966764f,0.250049f, +0.112464f,0.954457f,0.276338f, +0.109039f,0.955163f,0.275271f, +0.0445431f,0.979533f,0.196291f, +0.165433f,0.962373f,0.21557f, +-0.0715535f,0.977821f,0.196841f, +-0.0891149f,0.939351f,0.331178f, +0.117094f,0.910023f,0.397676f, +0.030807f,0.968216f,0.248212f, +0.157233f,0.982334f,0.101481f, +0.403254f,0.903723f,0.143774f, +0.0482774f,0.97679f,0.208689f, +-0.297552f,0.88274f,0.363639f, +-0.30014f,0.861944f,0.408619f, +-0.211374f,0.886111f,0.412466f, +-0.03076f,0.854928f,0.517834f, +0.0282722f,0.878122f,0.477601f, +-0.13332f,0.93673f,0.32367f, +-0.256519f,0.940042f,0.224764f, +-0.183801f,0.953616f,0.238397f, +-0.0194462f,0.968434f,0.24851f, +-0.0907191f,0.988269f,0.122863f, +-0.322189f,0.946234f,-0.028899f, +-0.20601f,0.965456f,-0.159543f, +-0.0654489f,0.973414f,-0.219504f, +-0.113732f,0.990052f,-0.0828341f, +-0.135223f,0.986029f,0.0972711f, +-0.295266f,0.944373f,0.144834f, +-0.450404f,0.860579f,0.237781f, +-0.30004f,0.881766f,0.363958f, +-0.429075f,0.860577f,0.274411f, +-0.624789f,0.771784f,0.118272f, +-0.497638f,0.864372f,0.0722275f, +-0.313601f,0.946808f,-0.0721819f, +-0.057809f,0.993544f,-0.0976184f, +0.13458f,0.987765f,-0.078798f, +-0.184662f,0.92514f,-0.331688f, +-0.385787f,0.812528f,-0.436996f, +-0.187957f,0.911737f,-0.36525f, +0.0316981f,0.954599f,-0.296202f, +0.147926f,0.956328f,-0.252101f, +0.104858f,0.974711f,-0.197342f, +-0.0836115f,0.931387f,-0.354298f, +-0.111379f,0.87594f,-0.469386f, +-0.0328315f,0.880204f,-0.473458f, +0.162025f,0.887756f,-0.430856f, +0.205253f,0.903446f,-0.376373f, +0.237481f,0.902569f,-0.359125f, +0.385116f,0.876359f,-0.289276f, +0.249914f,0.920198f,-0.301294f, +0.0143883f,0.906805f,-0.421304f, +0.1198f,0.98226f,-0.14427f, +-0.009516f,0.980934f,-0.194106f, +-0.149357f,0.951394f,-0.269335f, +-0.133007f,0.936454f,-0.324597f, +0.034566f,0.948692f,-0.314306f, +0.178184f,0.929444f,-0.323086f, +0.219637f,0.922638f,-0.317015f, +0.296463f,0.935411f,-0.192652f, +0.416664f,0.902617f,-0.108048f, +0.442812f,0.876638f,-0.188209f, +0.465688f,0.849444f,-0.248152f, +0.511879f,0.84424f,-0.158868f, +0.360617f,0.931627f,-0.0450278f, +0.228988f,0.955033f,0.188354f, +-0.00280316f,0.974776f,0.223168f, +0.00899431f,0.980078f,0.198407f, +0.0845579f,0.975657f,0.202347f, +0.0600237f,0.962271f,0.265389f, +0.0344627f,0.950379f,0.309181f, +0.173636f,0.921696f,0.346881f, +-0.00190385f,0.960894f,0.276909f, +-0.186383f,0.97431f,0.126416f, +0.101162f,0.98048f,0.168596f, +0.181976f,0.961147f,0.207559f, +0.220019f,0.957024f,0.188939f, +0.310192f,0.917199f,0.250053f, +-0.02225f,0.932984f,0.359229f, +-0.395015f,0.837639f,0.377259f, +-0.325443f,0.861588f,0.389554f, +-0.255559f,0.880464f,0.39934f, +-0.151471f,0.886274f,0.437693f, +-0.0211154f,0.863177f,0.50446f, +0.00094362f,0.808505f,0.588488f, +-0.114242f,0.850647f,0.513176f, +-0.11027f,0.888828f,0.444776f, +-0.0310984f,0.926772f,0.374335f, +0.036991f,0.899416f,0.435525f, +-0.0593828f,0.941327f,0.33223f, +-0.108182f,0.990534f,0.0844942f, +-0.153469f,0.985899f,0.066708f, +-0.257292f,0.956946f,0.134368f, +-0.339432f,0.926138f,0.164482f, +-0.361227f,0.853531f,0.3755f, +-0.433268f,0.811828f,0.391425f, +-0.292152f,0.883075f,0.367186f, +-0.254971f,0.931997f,0.257627f, +-0.51111f,0.857028f,-0.0653379f, +-0.482419f,0.859823f,-0.167263f, +-0.240122f,0.964988f,-0.105544f, +-0.0637549f,0.987476f,-0.144314f, +0.14266f,0.980144f,-0.137714f, +0.096896f,0.982614f,-0.158371f, +-0.287298f,0.856944f,-0.42791f, +-0.299829f,0.819408f,-0.488542f, +-0.0881013f,0.911449f,-0.40187f, +0.0509938f,0.949808f,-0.308649f, +0.13334f,0.962273f,-0.237174f, +0.0865622f,0.946427f,-0.311099f, +0.0118172f,0.924665f,-0.380599f, +-0.0178448f,0.910652f,-0.412789f, +0.073892f,0.906856f,-0.414913f, +0.15114f,0.90612f,-0.395099f, +0.255577f,0.878518f,-0.403593f, +0.278013f,0.865146f,-0.417411f, +0.239832f,0.923443f,-0.299555f, +0.188412f,0.940744f,-0.281961f, +-0.0158305f,0.982567f,-0.185231f, +0.0666038f,0.988337f,-0.136945f, +-0.0538402f,0.959334f,-0.277092f, +-0.0212127f,0.945816f,-0.324009f, +-0.0150833f,0.913689f,-0.406133f, +0.15601f,0.93774f,-0.310331f, +0.182702f,0.936618f,-0.298942f, +0.189924f,0.93758f,-0.29133f, +0.333869f,0.91329f,-0.233307f, +0.499532f,0.857573f,-0.122619f, +0.46551f,0.873216f,-0.144201f, +0.373694f,0.926999f,0.0320189f, +0.203779f,0.950539f,0.234414f, +0.13831f,0.928366f,0.344974f, +0.0515931f,0.949665f,0.30899f, +0.0310079f,0.96445f,0.262439f, +0.0853119f,0.968829f,0.232577f, +-0.00103764f,0.981733f,0.190261f, +-0.00365072f,0.967667f,0.252206f, +0.10066f,0.945677f,0.309134f, +0.178572f,0.914026f,0.364237f, +-0.0213985f,0.991455f,0.128684f, +0.0498313f,0.996519f,0.0668339f, +0.120586f,0.983203f,0.137006f, +0.0910496f,0.981472f,0.16859f, +0.13401f,0.919805f,0.368783f, +-0.0801133f,0.861028f,0.502208f, +-0.337717f,0.841946f,0.420801f, +-0.27627f,0.878916f,0.388821f, +-0.2301f,0.91025f,0.344237f, +-0.177792f,0.940411f,0.289857f, +-0.131507f,0.928729f,0.346652f, +-0.0961971f,0.892019f,0.441642f, +-0.0639687f,0.872394f,0.4846f, +-0.0102449f,0.879124f,0.476482f, +-0.00257342f,0.917704f,0.397258f, +-0.0554909f,0.910659f,0.409416f, +0.0291401f,0.896118f,0.442858f, +0.0220451f,0.91331f,0.406668f, +-0.138595f,0.921526f,0.362741f, +-0.186305f,0.924786f,0.331755f, +-0.347011f,0.903153f,0.25278f, +-0.513046f,0.817508f,0.261656f, +-0.445268f,0.835978f,0.320745f, +-0.177443f,0.933005f,0.313074f, +-0.0397144f,0.982015f,0.184579f, +-0.223543f,0.974128f,-0.0332155f, +-0.4666f,0.831165f,-0.302406f, +-0.335541f,0.890675f,-0.306773f, +-0.0318096f,0.973987f,-0.224358f, +0.0953506f,0.970682f,-0.220646f, +0.134482f,0.984534f,-0.112281f, +-0.0162953f,0.992479f,-0.121323f, +-0.284204f,0.902721f,-0.322992f, +-0.211997f,0.906314f,-0.365585f, +-0.016875f,0.958349f,-0.285101f, +0.129044f,0.959618f,-0.24996f, +0.151996f,0.928771f,-0.338057f, +-0.0199776f,0.904327f,-0.426372f, +-0.0559071f,0.940256f,-0.335846f, +0.108952f,0.945546f,-0.306712f, +0.215589f,0.905767f,-0.364838f, +0.293281f,0.878158f,-0.377921f, +0.279356f,0.877367f,-0.390112f, +0.127912f,0.886694f,-0.444312f, +0.153161f,0.902051f,-0.403541f, +-0.0890667f,0.969622f,-0.227816f, +0.0791521f,0.98141f,-0.174841f, +0.0791423f,0.971591f,-0.22304f, +0.0168825f,0.939671f,-0.341662f, +-0.00465273f,0.922224f,-0.386629f, +0.0341103f,0.949158f,-0.312946f, +0.243022f,0.94331f,-0.226069f, +0.218985f,0.910646f,-0.350386f, +0.282576f,0.88974f,-0.358487f, +0.398347f,0.877162f,-0.268155f, +0.330147f,0.941044f,-0.073754f, +0.178397f,0.970659f,0.16123f, +0.0525065f,0.954596f,0.293241f, +0.0945297f,0.914894f,0.392472f, +0.13661f,0.905749f,0.401193f, +0.0406243f,0.947359f,0.317587f, +0.163762f,0.925717f,0.340926f, +0.040504f,0.970394f,0.238108f, +-0.0543453f,0.975142f,0.214812f, +2.68223e-005f,0.976435f,0.215812f, +0.209407f,0.932778f,0.293383f, +0.184464f,0.966229f,0.179928f, +-0.0113387f,0.999016f,0.0428878f, +0.079177f,0.981677f,0.173323f, +0.0362262f,0.968187f,0.24759f, +-0.0723427f,0.93572f,0.345245f, +-0.135834f,0.890086f,0.435082f, +-0.264248f,0.873681f,0.408479f, +-0.262216f,0.89706f,0.355706f, +-0.164052f,0.919196f,0.358002f, +-0.167176f,0.924403f,0.342829f, +-0.200682f,0.904947f,0.375229f, +-0.158624f,0.899685f,0.406701f, +-0.112022f,0.891533f,0.438886f, +-0.00921475f,0.869473f,0.493894f, +0.0802624f,0.881225f,0.465833f, +-0.0504548f,0.922517f,0.382645f, +-0.0121989f,0.918687f,0.394797f, +0.0440736f,0.891185f,0.451494f, +-0.0756766f,0.900734f,0.427728f, +-0.202037f,0.909488f,0.363335f, +-0.295423f,0.866009f,0.403428f, +-0.471319f,0.827048f,0.30635f, +-0.443758f,0.874939f,0.193806f, +-0.125026f,0.977756f,0.168412f, +0.0442668f,0.987172f,0.153403f, +-0.0338798f,0.987768f,0.152205f, +-0.259589f,0.965039f,-0.0362462f, +-0.35784f,0.903258f,-0.236805f, +-0.167942f,0.956248f,-0.239554f, +0.0460995f,0.994911f,-0.0895878f, +-0.00166787f,0.99811f,-0.0614342f, +-0.0336402f,0.998923f,0.0319432f, +-0.139942f,0.989786f,0.0271849f, +-0.21913f,0.971861f,-0.0864193f, +-0.083914f,0.990307f,-0.110685f, +0.180721f,0.971397f,-0.154041f, +0.29639f,0.913592f,-0.278393f, +0.0452233f,0.94418f,-0.326312f, +-0.13463f,0.924181f,-0.357441f, +0.11753f,0.929423f,-0.349798f, +0.238754f,0.909243f,-0.340989f, +0.272577f,0.899491f,-0.341494f, +0.343945f,0.879082f,-0.330025f, +0.202726f,0.889055f,-0.410468f, +0.0880936f,0.876474f,-0.473321f, +-0.000386659f,0.989518f,-0.144407f, +-0.0138532f,0.983228f,-0.181856f, +0.165824f,0.98552f,-0.0353913f, +0.196669f,0.963831f,-0.179867f, +0.00115533f,0.93443f,-0.356144f, +-0.0579019f,0.928374f,-0.36711f, +0.234096f,0.913194f,-0.333581f, +0.311749f,0.881031f,-0.355805f, +0.243154f,0.902483f,-0.355529f, +0.214274f,0.956658f,-0.197209f, +0.120355f,0.990537f,0.0659672f, +0.0219689f,0.979298f,0.201227f, +-0.0108785f,0.963809f,0.266373f, +-0.016985f,0.957116f,0.289205f, +0.15437f,0.922679f,0.353316f, +0.0959731f,0.93811f,0.332776f, +0.138832f,0.935317f,0.325434f, +0.133758f,0.941295f,0.309956f, +-0.00148525f,0.972503f,0.232885f, +0.00817406f,0.979885f,0.199396f, +0.180862f,0.960033f,0.213602f, +0.330054f,0.924212f,0.192085f, +0.039978f,0.994865f,0.0929833f, +-0.118088f,0.976595f,0.179768f, +-0.100092f,0.923425f,0.370498f, +-0.117559f,0.88568f,0.449166f, +-0.170937f,0.879572f,0.443997f, +-0.244838f,0.844603f,0.47613f, +-0.196312f,0.844324f,0.498577f, +-0.188529f,0.85759f,0.478535f, +-0.188501f,0.839785f,0.509145f, +-0.185899f,0.842964f,0.50483f, +-0.154293f,0.872091f,0.464382f, +-0.115474f,0.894542f,0.431811f, +-0.0887035f,0.930393f,0.35567f, +0.133188f,0.884773f,0.446583f, +0.0484666f,0.90226f,0.42846f, +-0.0427135f,0.946807f,0.318954f, +-0.0239721f,0.952831f,0.302554f, +-0.0435714f,0.926502f,0.373759f, +-0.182333f,0.899048f,0.398079f, +-0.323546f,0.846433f,0.422929f, +-0.334412f,0.852971f,0.40076f, +-0.325744f,0.921829f,0.210052f, +-0.140593f,0.980752f,0.135497f, +-0.000911154f,0.974293f,0.225285f, +-0.0250989f,0.969759f,0.242771f, +-0.116671f,0.973198f,0.198177f, +-0.222025f,0.967605f,0.12019f, +-0.252573f,0.967519f,-0.0106675f, +-0.0639595f,0.99456f,0.0822198f, +0.0427289f,0.995551f,0.0839736f, +-0.103724f,0.994603f,-0.00239601f, +-0.143088f,0.981404f,0.127957f, +-0.10974f,0.986771f,0.119333f, +0.0104156f,0.996494f,-0.083017f, +0.293943f,0.936018f,-0.193565f, +0.319276f,0.921897f,-0.219472f, +0.0381885f,0.98033f,-0.193638f, +-0.0675527f,0.960756f,-0.269042f, +0.11652f,0.926645f,-0.357425f, +0.2292f,0.915276f,-0.331265f, +0.30797f,0.891339f,-0.33267f, +0.348546f,0.853103f,-0.38824f, +0.249601f,0.874176f,-0.416553f, +0.18778f,0.887174f,-0.421499f, +0.122671f,0.990262f,-0.0658213f, +-0.0435566f,0.992887f,-0.11081f, +0.0494387f,0.998572f,0.0202637f, +0.34574f,0.93458f,0.0838063f, +0.205482f,0.970541f,-0.125808f, +0.00807532f,0.928646f,-0.370879f, +0.212354f,0.896105f,-0.389746f, +0.285287f,0.924061f,-0.254407f, +0.130923f,0.978283f,-0.160691f, +-0.0198715f,0.999555f,-0.0222427f, +-0.0516664f,0.987583f,0.148362f, +-0.0269196f,0.97761f,0.208697f, +-0.00903021f,0.979554f,0.200976f, +-0.00834551f,0.993685f,0.111894f, +0.110842f,0.987362f,0.113269f, +0.106874f,0.976878f,0.185167f, +0.141547f,0.968321f,0.205716f, +0.174972f,0.958256f,0.22612f, +0.054828f,0.97071f,0.233913f, +0.0299952f,0.981566f,0.188753f, +0.154988f,0.980787f,0.118472f, +0.340268f,0.925521f,0.166219f, +0.0136729f,0.972695f,0.231683f, +-0.270301f,0.899629f,0.342937f, +-0.212226f,0.859098f,0.465736f, +-0.140535f,0.846284f,0.513861f, +-0.175101f,0.833937f,0.523345f, +-0.270288f,0.821688f,0.501769f, +-0.282918f,0.830124f,0.48047f, +-0.174774f,0.812594f,0.556008f, +-0.140913f,0.828898f,0.541361f, +-0.117146f,0.878471f,0.463211f, +-0.0728003f,0.920501f,0.383899f, +-0.00293246f,0.948861f,0.315679f, +-0.025836f,0.967046f,0.253289f, +-0.00528251f,0.957042f,0.289901f, +0.088837f,0.914901f,0.393781f, +0.103014f,0.924276f,0.367561f, +0.00437406f,0.95596f,0.293464f, +-0.1442f,0.952275f,0.269032f, +-0.25396f,0.922416f,0.290951f, +-0.3894f,0.883133f,0.261618f, +-0.283615f,0.906122f,0.313857f, +-0.158058f,0.930594f,0.330171f, +-0.134893f,0.961854f,0.237993f, +-0.0720522f,0.980808f,0.181173f, +0.0349752f,0.985618f,0.16533f, +-0.115886f,0.987377f,0.107965f, +-0.182211f,0.968171f,0.171592f, +-0.154769f,0.971197f,0.181169f, +-0.0833304f,0.991727f,0.0976435f, +0.136344f,0.989699f,0.0436644f, +-0.106946f,0.993768f,-0.0314277f, +-0.261215f,0.963441f,0.0595659f, +0.0120329f,0.999596f,0.0257635f, +0.254582f,0.953185f,-0.163178f, +0.299581f,0.899014f,-0.319413f, +0.266729f,0.9307f,-0.250307f, +0.0579078f,0.977779f,-0.201483f, +0.0590491f,0.968354f,-0.242494f, +0.196887f,0.912909f,-0.357536f, +0.211047f,0.877381f,-0.430885f, +0.301745f,0.869054f,-0.39204f, +0.422629f,0.852977f,-0.306291f, +0.252055f,0.896241f,-0.364994f, +0.158615f,0.91987f,-0.35872f, +0.099088f,0.991841f,-0.0802016f, +-0.0649468f,0.996188f,-0.0582405f, +-0.09006f,0.995865f,-0.0119566f, +0.299186f,0.949686f,0.0926523f, +0.448961f,0.886032f,0.115674f, +0.225408f,0.968479f,-0.106019f, +0.110364f,0.983262f,-0.144965f, +0.0982296f,0.994337f,0.0405443f, +0.03386f,0.98307f,0.180072f, +-0.0548904f,0.982813f,0.176255f, +-0.131535f,0.986412f,0.0984329f, +-0.0772354f,0.9803f,0.181787f, +0.0556449f,0.958844f,0.278429f, +0.08308f,0.969903f,0.228882f, +0.0990101f,0.980512f,0.169685f, +0.044494f,0.989611f,0.136713f, +0.124145f,0.981303f,0.14708f, +0.126925f,0.98249f,0.136391f, +0.0289993f,0.988064f,0.151292f, +0.146433f,0.982737f,0.113073f, +0.210582f,0.977005f,-0.0334257f, +0.179552f,0.980748f,0.0767724f, +-0.0986728f,0.925956f,0.364513f, +-0.333893f,0.835984f,0.435484f, +-0.316161f,0.849609f,0.422146f, +-0.184942f,0.836066f,0.516517f, +-0.165011f,0.827696f,0.536368f, +-0.1919f,0.849729f,0.491054f, +-0.260791f,0.881445f,0.393754f, +-0.244518f,0.891442f,0.3815f, +-0.101674f,0.91665f,0.386543f, +-0.0135975f,0.926806f,0.375295f, +0.0383624f,0.948469f,0.31454f, +0.0311937f,0.973858f,0.225008f, +-0.0712105f,0.966505f,0.24657f, +-0.0567001f,0.939446f,0.337973f, +0.028793f,0.937988f,0.345471f, +0.0944493f,0.922855f,0.373388f, +0.0339618f,0.928396f,0.370037f, +-0.0877384f,0.940895f,0.327137f, +-0.18953f,0.934542f,0.301182f, +-0.32638f,0.91712f,0.22884f, +-0.359606f,0.925931f,0.115484f, +-0.250341f,0.958991f,0.132911f, +-0.0188851f,0.981881f,0.188556f, +0.0444017f,0.992958f,0.109832f, +0.0292244f,0.992914f,0.115188f, +-0.0809364f,0.975181f,0.206087f, +-0.271318f,0.947628f,0.168488f, +-0.147667f,0.972329f,0.181027f, +0.0428511f,0.996597f,0.0704105f, +0.186761f,0.979997f,-0.0687482f, +-0.111624f,0.989428f,-0.0925828f, +-0.210799f,0.973161f,-0.0923101f, +0.115063f,0.969975f,-0.214262f, +0.376036f,0.900817f,-0.217086f, +0.373114f,0.884398f,-0.280403f, +0.226074f,0.905778f,-0.358407f, +0.0100432f,0.919347f,-0.393319f, +0.0770135f,0.93428f,-0.348124f, +0.321395f,0.895396f,-0.308175f, +0.278274f,0.88968f,-0.361984f, +0.208857f,0.897848f,-0.387619f, +0.325776f,0.898072f,-0.295527f, +0.259741f,0.94586f,-0.194637f, +0.133572f,0.977992f,-0.160282f, +-0.0277257f,0.992037f,-0.122857f, +-0.0924217f,0.994571f,-0.0478129f, +-0.116438f,0.990661f,-0.0709396f, +0.19557f,0.979919f,-0.0388625f, +0.381806f,0.908869f,0.167871f, +0.299282f,0.900933f,0.314247f, +0.0638964f,0.963274f,0.260808f, +-0.0731879f,0.961388f,0.265284f, +0.00180295f,0.933351f,0.35896f, +0.0655899f,0.939022f,0.337544f, +-0.0612046f,0.96894f,0.239602f, +-0.166052f,0.961913f,0.217141f, +-0.0893118f,0.965245f,0.245614f, +0.0820047f,0.941494f,0.326902f, +0.146932f,0.937808f,0.314527f, +0.136588f,0.939539f,0.314023f, +0.166222f,0.964584f,0.204811f, +0.17109f,0.976368f,0.132039f, +0.0961069f,0.992806f,0.0714098f, +0.21778f,0.975905f,-0.013487f, +0.251597f,0.967828f,-0.00281592f, +-0.0966896f,0.992674f,0.0724564f, +-0.377842f,0.87018f,0.316262f, +-0.323773f,0.853386f,0.408537f, +-0.278729f,0.867238f,0.412564f, +-0.286188f,0.874143f,0.392391f, +-0.157911f,0.873337f,0.46081f, +-0.102832f,0.901917f,0.419488f, +-0.202979f,0.914239f,0.350665f, +-0.202531f,0.912766f,0.354739f, +-0.0843061f,0.956165f,0.28043f, +-0.032801f,0.972626f,0.23005f, +0.0558474f,0.961664f,0.268485f, +0.0617913f,0.944956f,0.321309f, +-0.110343f,0.937288f,0.330629f, +-0.100375f,0.942449f,0.318927f, +0.00551388f,0.94452f,0.328408f, +0.0918462f,0.918926f,0.383587f, +0.101653f,0.927592f,0.3595f, +-0.0426308f,0.960188f,0.276083f, +-0.204594f,0.956809f,0.206539f, +-0.269971f,0.94929f,0.161132f, +-0.226691f,0.969699f,0.0910768f, +-0.201053f,0.979426f,-0.0173973f, +-0.0500104f,0.996428f,-0.0680439f, +0.0272717f,0.999341f,-0.0239459f, +-0.123434f,0.99095f,0.0527561f, +-0.192945f,0.962627f,0.190054f, +-0.168165f,0.969015f,0.180916f, +-0.018086f,0.998622f,0.0492547f, +0.193647f,0.975713f,-0.102395f, +0.238523f,0.949336f,-0.204618f, +-0.0631885f,0.979427f,-0.191649f, +-0.143153f,0.951631f,-0.271858f, +0.148284f,0.940281f,-0.306403f, +0.321113f,0.91022f,-0.261508f, +0.430557f,0.873923f,-0.225566f, +0.33081f,0.885978f,-0.324974f, +0.0651303f,0.881392f,-0.467874f, +0.0061581f,0.870221f,-0.492623f, +0.228459f,0.886891f,-0.401535f, +0.271547f,0.915184f,-0.297827f, +0.234822f,0.937165f,-0.258033f, +0.27549f,0.92259f,-0.270061f, +0.15924f,0.956523f,-0.244348f, +0.0559303f,0.980799f,-0.186831f, +-0.135424f,0.978967f,-0.152593f, +-0.15029f,0.985676f,-0.0765294f, +-0.0914165f,0.995631f,-0.0190383f, +0.0718608f,0.995714f,0.0582141f, +0.110439f,0.955564f,0.273313f, +0.150494f,0.878589f,0.453246f, +0.206788f,0.864483f,0.458157f, +0.00161058f,0.957582f,0.288156f, +-0.0606597f,0.978401f,0.197616f, +0.0692656f,0.9636f,0.25822f, +-0.0150286f,0.961837f,0.273212f, +-0.0821089f,0.979895f,0.181835f, +-0.0658015f,0.997594f,0.0218166f, +0.0735253f,0.997209f,0.0129617f, +0.108564f,0.993746f,0.0261473f, +0.141903f,0.981669f,0.127241f, +0.25029f,0.961471f,0.113707f, +0.225135f,0.967003f,0.119246f, +0.180078f,0.979492f,0.0903737f, +0.237995f,0.971216f,-0.00990333f, +0.0690008f,0.993039f,0.0954582f, +-0.15301f,0.921345f,0.357369f, +-0.436898f,0.858127f,0.2697f, +-0.402318f,0.892319f,0.204714f, +-0.306797f,0.913547f,0.267033f, +-0.291188f,0.917032f,0.272509f, +-0.177835f,0.951614f,0.250608f, +-0.0915363f,0.968867f,0.230039f, +-0.166531f,0.945303f,0.280483f, +-0.214524f,0.956179f,0.199251f, +-0.012479f,0.976094f,0.216991f, +0.0485598f,0.972045f,0.22972f, +-0.0252191f,0.985709f,0.166561f, +-0.0505751f,0.962642f,0.266012f, +-0.0744793f,0.942362f,0.3262f, +-0.0759606f,0.964725f,0.252062f, +-0.0161104f,0.954528f,0.297687f, +0.0264811f,0.949176f,0.313631f, +0.160628f,0.931063f,0.327597f, +0.0783265f,0.972396f,0.219798f, +-0.0844827f,0.993769f,0.0727062f, +-0.216702f,0.975588f,-0.035603f, +-0.195742f,0.979732f,-0.0425419f, +-0.158684f,0.986912f,-0.0287187f, +-0.0351752f,0.999203f,-0.0188605f, +0.0075235f,0.998877f,-0.0467686f, +-0.172586f,0.978556f,-0.112436f, +-0.211691f,0.968971f,-0.127601f, +-0.0966389f,0.974492f,-0.202552f, +0.105494f,0.955113f,-0.276822f, +0.276059f,0.900517f,-0.335947f, +0.219894f,0.907239f,-0.358557f, +-0.0517693f,0.940977f,-0.334489f, +-0.112634f,0.913693f,-0.390485f, +0.139923f,0.91136f,-0.387097f, +0.277005f,0.880398f,-0.384926f, +0.432717f,0.843875f,-0.317222f, +0.433921f,0.823502f,-0.365455f, +0.17364f,0.848637f,-0.499665f, +-0.015678f,0.850557f,-0.525649f, +0.122709f,0.874405f,-0.469423f, +0.164019f,0.896294f,-0.412014f, +0.166557f,0.925047f,-0.34139f, +0.280426f,0.925939f,-0.25298f, +0.167623f,0.949542f,-0.265088f, +-0.00102675f,0.947405f,-0.320035f, +-0.299103f,0.954018f,0.0196808f, +-0.231787f,0.963234f,0.135851f, +-0.196753f,0.961454f,0.192081f, +-0.100151f,0.951932f,0.289472f, +-0.0563981f,0.925245f,0.375154f, +0.0944709f,0.906549f,0.411394f, +0.305132f,0.862547f,0.403618f, +0.241596f,0.931691f,0.271261f, +-0.00370494f,0.998524f,0.0541932f, +-0.000261525f,0.998839f,0.0481646f, +0.0260826f,0.996855f,0.0748309f, +0.0599122f,0.998202f,-0.00179631f, +0.0800977f,0.992669f,-0.0905174f, +0.0495455f,0.986325f,-0.157186f, +0.0563113f,0.99071f,-0.123787f, +0.0832843f,0.991933f,-0.095561f, +0.195142f,0.979158f,-0.0563024f, +0.166634f,0.980307f,0.105976f, +0.195862f,0.965878f,0.169461f, +0.284001f,0.943304f,0.171815f, +-0.127388f,0.981047f,0.146008f, +-0.325222f,0.907949f,0.264311f, +-0.283635f,0.916157f,0.28321f, +-0.335047f,0.926228f,0.17276f, +-0.335005f,0.934046f,0.123816f, +-0.290471f,0.951826f,0.098256f, +-0.155538f,0.980437f,0.120632f, +-0.103955f,0.982905f,0.151957f, +-0.195165f,0.971298f,0.135979f, +-0.117017f,0.988828f,0.0923353f, +-0.0942839f,0.995508f,0.00860997f, +-0.0378307f,0.988218f,0.148301f, +0.011735f,0.964206f,0.264893f, +-0.104568f,0.970188f,0.218634f, +-0.0628876f,0.976435f,0.206445f, +-0.0629747f,0.98253f,0.175127f, +-0.0956593f,0.974263f,0.204109f, +0.00313264f,0.95614f,0.292895f, +0.184054f,0.913334f,0.363241f, +0.234886f,0.917194f,0.321843f, +0.0818984f,0.986888f,0.139086f, +-0.195667f,0.979747f,-0.0425424f, +-0.217661f,0.976006f,-0.00606019f, +-0.197993f,0.980131f,-0.011927f, +-0.0476541f,0.998861f,-0.00224411f, +0.0987461f,0.994341f,-0.039179f, +-0.0376594f,0.985822f,-0.163515f, +-0.127665f,0.950129f,-0.284528f, +0.022229f,0.926621f,-0.37534f, +0.1509f,0.867911f,-0.473243f, +0.251356f,0.84329f,-0.475061f, +0.180391f,0.877498f,-0.44436f, +-0.0381311f,0.903323f,-0.427263f, +-0.0302687f,0.878817f,-0.476199f, +0.151045f,0.843437f,-0.515557f, +0.243043f,0.829132f,-0.503459f, +0.361214f,0.815934f,-0.451416f, +0.469501f,0.80804f,-0.355866f, +0.232058f,0.89573f,-0.379233f, +-0.0406313f,0.902008f,-0.429803f, +0.0570971f,0.896722f,-0.438895f, +0.139199f,0.907425f,-0.396488f, +0.0981956f,0.909915f,-0.403003f, +0.173099f,0.913856f,-0.367293f, +0.208242f,0.936494f,-0.28216f, +0.104323f,0.936228f,-0.335549f, +-0.455877f,0.874672f,0.164697f, +-0.324643f,0.906811f,0.268889f, +-0.22917f,0.934048f,0.273927f, +-0.11917f,0.945648f,0.302569f, +-0.0303449f,0.953424f,0.300104f, +0.0953211f,0.968161f,0.231468f, +0.307551f,0.928088f,0.209914f, +0.396906f,0.882705f,0.251588f, +0.154339f,0.98019f,0.124127f, +0.00614755f,0.999958f,0.00674104f, +0.0862143f,0.995356f,-0.0428297f, +0.0605751f,0.988948f,-0.135323f, +0.116851f,0.991236f,-0.0616197f, +0.0626175f,0.989161f,-0.132815f, +0.0598334f,0.989391f,-0.132381f, +0.0870904f,0.982628f,-0.163882f, +0.0967617f,0.982554f,-0.15882f, +0.0255981f,0.999032f,-0.0357718f, +0.114826f,0.99101f,0.0686587f, +0.196799f,0.954402f,0.22447f, +-0.0385546f,0.932725f,0.358521f, +-0.332784f,0.924223f,0.18726f, +-0.304588f,0.936692f,0.172726f, +-0.293315f,0.937819f,0.185638f, +-0.274742f,0.953043f,0.127381f, +-0.263119f,0.962853f,0.0606766f, +-0.268024f,0.959606f,0.0855591f, +-0.0879001f,0.973995f,0.208824f, +-0.133948f,0.986848f,0.0904876f, +-0.113332f,0.988235f,0.102703f, +-0.0299834f,0.985262f,0.168402f, +-0.19277f,0.976736f,0.0939502f, +-0.0881002f,0.973369f,0.211639f, +-0.024161f,0.965814f,0.258109f, +-0.0447814f,0.977625f,0.205534f, +-0.0454862f,0.975256f,0.216349f, +-0.133105f,0.964838f,0.22665f, +-0.114579f,0.956534f,0.268169f, +0.0712671f,0.941693f,0.328841f, +0.238728f,0.884921f,0.399904f, +0.297664f,0.869038f,0.395183f, +-0.00961778f,0.988677f,0.149748f, +-0.265709f,0.963666f,-0.0273077f, +-0.143358f,0.988736f,0.0430136f, +-0.00534208f,0.998711f,-0.0504723f, +0.174549f,0.979244f,-0.103024f, +0.0753759f,0.97722f,-0.198391f, +-0.0309169f,0.954209f,-0.297538f, +0.114484f,0.932628f,-0.342197f, +0.277629f,0.881086f,-0.382896f, +0.233881f,0.840787f,-0.488238f, +0.145974f,0.866169f,-0.477957f, +-0.0214889f,0.855591f,-0.517207f, +0.015747f,0.850281f,-0.526094f, +0.181736f,0.859322f,-0.478056f, +0.233268f,0.832868f,-0.501913f, +0.278912f,0.819449f,-0.500711f, +0.37496f,0.838284f,-0.395834f, +0.211098f,0.909912f,-0.357069f, +0.0173895f,0.949305f,-0.313875f, +0.0778513f,0.935569f,-0.344455f, +0.13573f,0.919161f,-0.369756f, +0.128317f,0.903382f,-0.40919f, +0.134873f,0.894846f,-0.425512f, +0.140765f,0.922098f,-0.360446f, +0.195779f,0.941368f,-0.274766f, +-0.498792f,0.861228f,0.0974355f, +-0.334273f,0.933116f,0.132498f, +-0.209899f,0.97009f,0.121936f, +-0.146122f,0.979163f,0.141027f, +-0.00844043f,0.991347f,0.130997f, +0.183871f,0.98064f,0.0673491f, +0.295623f,0.955305f,0.000649681f, +0.325261f,0.940591f,0.0974362f, +0.279972f,0.936209f,0.212435f, +0.117319f,0.989809f,0.0807136f, +0.167452f,0.985876f,0.00303625f, +0.0997326f,0.991951f,-0.0780129f, +0.0970545f,0.989541f,-0.106723f, +0.122983f,0.982138f,-0.14241f, +0.0889416f,0.984545f,-0.150867f, +0.0922265f,0.975522f,-0.199627f, +0.0767647f,0.98447f,-0.15788f, +-0.0166949f,0.981051f,-0.193027f, +-0.0192651f,0.97159f,-0.235885f, +-0.0430007f,0.99834f,-0.038322f, +-0.1057f,0.976121f,0.189775f, +-0.21501f,0.968939f,0.122177f, +-0.312622f,0.947332f,0.0695023f, +-0.268759f,0.958656f,0.0935212f, +-0.210053f,0.974561f,0.0781578f, +-0.280996f,0.956877f,0.0736733f, +-0.29425f,0.945004f,0.142776f, +-0.103752f,0.988352f,0.111339f, +-0.0179991f,0.994529f,0.102897f, +-0.257355f,0.965403f,0.0420096f, +-0.105403f,0.956057f,0.273578f, +-0.10459f,0.942017f,0.318851f, +-0.129983f,0.956026f,0.262903f, +-0.0671262f,0.95499f,0.288944f, +-0.00387184f,0.948915f,0.315508f, +-0.104327f,0.957897f,0.267486f, +-0.136557f,0.931775f,0.336375f, +-0.0981417f,0.964639f,0.24462f, +0.0564237f,0.977306f,0.204178f, +0.151449f,0.955346f,0.253725f, +0.313069f,0.882901f,0.349962f, +0.317375f,0.903515f,0.287983f, +-0.14146f,0.988238f,-0.0580959f, +-0.183704f,0.977531f,-0.10337f, +0.0729777f,0.993775f,-0.0841813f, +0.241185f,0.959561f,-0.145165f, +0.180872f,0.946861f,-0.26597f, +0.0759246f,0.918564f,-0.387911f, +0.0834031f,0.881426f,-0.4649f, +0.312989f,0.886301f,-0.341334f, +0.345782f,0.8869f,-0.306339f, +0.190174f,0.893803f,-0.40614f, +0.0967003f,0.870562f,-0.482463f, +-0.011292f,0.813313f,-0.581716f, +0.104307f,0.818569f,-0.564858f, +0.278742f,0.804599f,-0.524332f, +0.252871f,0.80123f,-0.542298f, +0.288393f,0.816691f,-0.499846f, +0.158986f,0.877853f,-0.451771f, +-0.0422089f,0.892803f,-0.448466f, +0.0676213f,0.902423f,-0.425511f, +0.196008f,0.897779f,-0.394428f, +0.174291f,0.88488f,-0.431984f, +0.107973f,0.893114f,-0.43668f, +0.0286973f,0.916566f,-0.398853f, +0.0334026f,0.935074f,-0.352875f, +-0.456752f,0.886621f,-0.0726759f, +-0.35821f,0.92461f,-0.129546f, +-0.255187f,0.962466f,-0.0924034f, +-0.153659f,0.987984f,-0.0166497f, +0.0326193f,0.998752f,-0.0378261f, +0.219848f,0.975435f,-0.0138776f, +0.325192f,0.945498f,0.0168406f, +0.223054f,0.973348f,-0.0532875f, +0.221049f,0.975263f,0.000679153f, +0.242907f,0.969656f,0.0276409f, +0.175892f,0.983375f,-0.0451076f, +0.180873f,0.98342f,0.0130764f, +0.169259f,0.981997f,-0.0838673f, +0.138819f,0.973225f,-0.183198f, +0.0923263f,0.975478f,-0.199795f, +0.109785f,0.97291f,-0.203452f, +0.048887f,0.975403f,-0.214938f, +0.0862303f,0.974446f,-0.207409f, +0.0239822f,0.965181f,-0.260482f, +-0.234299f,0.93066f,-0.281028f, +-0.183154f,0.968628f,-0.167974f, +-0.163946f,0.9725f,-0.165423f, +-0.29935f,0.945623f,-0.127226f, +-0.309491f,0.943295f,-0.120043f, +-0.244588f,0.967669f,-0.0615978f, +-0.316375f,0.948228f,-0.0277512f, +-0.278706f,0.959538f,-0.0401272f, +-0.112855f,0.98959f,-0.0893067f, +-0.0120823f,0.999804f,0.015665f, +-0.269265f,0.962743f,0.0249422f, +-0.319779f,0.940968f,0.110998f, +-0.127925f,0.957822f,0.257316f, +-0.134411f,0.958853f,0.250069f, +-0.0963489f,0.939739f,0.328035f, +0.013379f,0.931979f,0.362265f, +-0.059723f,0.950577f,0.304692f, +-0.140375f,0.96932f,0.201776f, +0.0285405f,0.975242f,0.219289f, +0.0759984f,0.981739f,0.174395f, +0.082912f,0.985645f,0.14707f, +0.244118f,0.959921f,0.137686f, +0.433469f,0.888297f,0.151764f, +0.159753f,0.986026f,0.0472448f, +-0.155828f,0.965805f,-0.207217f, +0.0529598f,0.961817f,-0.268522f, +0.302231f,0.91749f,-0.258588f, +0.300969f,0.905771f,-0.298324f, +0.219954f,0.902269f,-0.370851f, +0.168125f,0.874674f,-0.45462f, +0.0852064f,0.832228f,-0.547846f, +0.293285f,0.876411f,-0.381953f, +0.299707f,0.878674f,-0.371628f, +0.169625f,0.87124f,-0.460618f, +0.152784f,0.862886f,-0.481751f, +0.140952f,0.826781f,-0.544578f, +0.216806f,0.796193f,-0.564865f, +0.252088f,0.778347f,-0.575003f, +0.184028f,0.779276f,-0.599052f, +0.07662f,0.847353f,-0.525474f, +-0.000576164f,0.875581f,-0.483072f, +0.0676453f,0.855821f,-0.51283f, +0.10935f,0.864233f,-0.491064f, +0.170357f,0.902391f,-0.395814f, +0.0783522f,0.922085f,-0.378973f, +-0.0376769f,0.945309f,-0.323992f, +-0.0145087f,0.973617f,-0.227725f, +-0.23379f,0.969091f,0.0787691f, +-0.308611f,0.949667f,-0.0537712f, +-0.26795f,0.959457f,-0.087437f, +-0.196118f,0.96672f,-0.16429f, +0.0184009f,0.993828f,-0.109391f, +0.124962f,0.988681f,-0.0830367f, +0.297057f,0.954812f,-0.00955538f, +0.355506f,0.934478f,-0.0191401f, +0.206845f,0.957298f,-0.201981f, +0.24827f,0.946264f,-0.207234f, +0.137685f,0.959548f,-0.245584f, +0.129837f,0.983718f,-0.124261f, +0.240211f,0.966075f,-0.0948542f, +0.253383f,0.959847f,-0.120381f, +0.101386f,0.970431f,-0.219056f, +0.110568f,0.971775f,-0.208395f, +0.09998f,0.968593f,-0.227667f, +0.051279f,0.9528f,-0.299236f, +0.0182953f,0.960636f,-0.277207f, +-0.177379f,0.948528f,-0.262356f, +-0.248744f,0.930203f,-0.269905f, +-0.201336f,0.9681f,-0.14915f, +-0.308378f,0.940105f,-0.145279f, +-0.337871f,0.915739f,-0.217407f, +-0.303349f,0.940151f,-0.155226f, +-0.267648f,0.955794f,-0.121746f, +-0.256838f,0.946595f,-0.194914f, +-0.151848f,0.978969f,-0.136244f, +-0.166527f,0.98578f,-0.0225025f, +-0.271416f,0.956933f,0.103014f, +-0.388293f,0.921445f,0.0129329f, +-0.211649f,0.973838f,0.0827345f, +-0.164151f,0.971899f,0.168719f, +-0.20343f,0.950968f,0.232971f, +-0.0501604f,0.944198f,0.325535f, +0.0851988f,0.916779f,0.390203f, +-0.0675238f,0.966737f,0.246698f, +-0.050967f,0.964665f,0.258503f, +0.0897532f,0.945965f,0.311599f, +0.203817f,0.954291f,0.218604f, +0.298323f,0.9542f,0.0224806f, +0.409994f,0.911395f,0.0355409f, +0.297451f,0.952362f,0.0673044f, +0.087158f,0.982486f,-0.164695f, +0.130693f,0.926163f,-0.353753f, +0.287973f,0.877932f,-0.3825f, +0.285473f,0.870692f,-0.400501f, +0.210236f,0.894171f,-0.395297f, +0.291478f,0.889926f,-0.350816f, +0.238796f,0.833f,-0.499086f, +0.156519f,0.786723f,-0.597134f, +0.265294f,0.807831f,-0.526334f, +0.196683f,0.821511f,-0.535197f, +0.111545f,0.852981f,-0.509883f, +0.148451f,0.876975f,-0.457031f, +0.27925f,0.865803f,-0.415216f, +0.364812f,0.845771f,-0.389337f, +0.213362f,0.862896f,-0.458135f, +-0.014091f,0.870788f,-0.491456f, +-0.0389733f,0.872117f,-0.487742f, +0.0697073f,0.876793f,-0.475789f, +0.0500075f,0.893805f,-0.445659f, +0.0507492f,0.920605f,-0.387184f, +0.00717016f,0.971083f,-0.238636f, +-0.12982f,0.987525f,-0.0891113f, +-0.196671f,0.977747f,-0.0730188f, +-0.180786f,0.972597f,0.146192f, +-0.276836f,0.956623f,0.0907445f, +-0.145247f,0.980389f,0.133193f, +-0.201228f,0.967008f,-0.156214f, +-0.0137179f,0.995281f,-0.0960578f, +0.139707f,0.987867f,-0.0678349f, +0.246306f,0.96116f,-0.124516f, +0.421865f,0.906227f,-0.0279788f, +0.299255f,0.934152f,-0.194439f, +0.288356f,0.912569f,-0.289945f, +0.0853497f,0.915952f,-0.392106f, +0.039019f,0.957394f,-0.286136f, +0.208597f,0.95771f,-0.198188f, +0.25753f,0.95731f,-0.131287f, +0.153643f,0.978938f,-0.134439f, +0.0994252f,0.976974f,-0.188775f, +0.12654f,0.974603f,-0.184759f, +0.142684f,0.966335f,-0.214099f, +-0.00843645f,0.93512f,-0.354231f, +-0.17704f,0.933769f,-0.311017f, +-0.343277f,0.895674f,-0.282717f, +-0.276715f,0.959562f,-0.0516624f, +-0.215753f,0.976427f,-0.00633257f, +-0.305134f,0.926522f,-0.220112f, +-0.33388f,0.920497f,-0.203001f, +-0.259644f,0.948413f,-0.181927f, +-0.268974f,0.938104f,-0.218205f, +-0.245938f,0.962991f,-0.110289f, +-0.275564f,0.96071f,0.0331654f, +-0.258271f,0.944524f,0.202903f, +-0.309053f,0.947461f,0.0824847f, +-0.320335f,0.94673f,-0.0329778f, +-0.208609f,0.963472f,0.167941f, +-0.270763f,0.941796f,0.199269f, +-0.104692f,0.947993f,0.30058f, +0.0304241f,0.930802f,0.364255f, +0.0189457f,0.906511f,0.421757f, +-0.0823065f,0.924037f,0.373337f, +0.102263f,0.911082f,0.39934f, +0.325851f,0.888801f,0.322263f, +0.371159f,0.927767f,0.0385981f, +0.355076f,0.934525f,0.0241533f, +0.375158f,0.916478f,0.139015f, +0.286108f,0.953917f,-0.0904664f, +0.199009f,0.919897f,-0.337913f, +0.358636f,0.872243f,-0.332523f, +0.268543f,0.846175f,-0.460296f, +0.182977f,0.871041f,-0.455858f, +0.289295f,0.860781f,-0.418765f, +0.382576f,0.820168f,-0.425393f, +0.183794f,0.780369f,-0.597699f, +0.239111f,0.770893f,-0.590381f, +0.11759f,0.781853f,-0.612273f, +0.0625615f,0.849006f,-0.524666f, +0.09237f,0.869569f,-0.485096f, +0.210947f,0.881757f,-0.421908f, +0.36331f,0.890409f,-0.274185f, +0.280816f,0.923638f,-0.260836f, +0.0186632f,0.936387f,-0.350473f, +-0.00764646f,0.914133f,-0.405343f, +0.0383964f,0.885647f,-0.462769f, +0.0296537f,0.913944f,-0.404755f, +-0.02984f,0.920171f,-0.390377f, +-0.172982f,0.943792f,-0.281663f, +-0.19032f,0.979403f,0.0674393f, +-0.205961f,0.972526f,0.108505f, +}; + +btScalar Landscape08Tex[] = { +0.0f,0.757813f, +0.0f,0.75f, +0.0078125f,0.757813f, +0.0078125f,0.75f, +0.015625f,0.757813f, +0.015625f,0.75f, +0.0234375f,0.757813f, +0.0234375f,0.75f, +0.03125f,0.757813f, +0.03125f,0.75f, +0.0390625f,0.757813f, +0.0390625f,0.75f, +0.046875f,0.757813f, +0.046875f,0.75f, +0.0546875f,0.757813f, +0.0546875f,0.75f, +0.0625f,0.757813f, +0.0625f,0.75f, +0.0703125f,0.757813f, +0.0703125f,0.75f, +0.078125f,0.757813f, +0.078125f,0.75f, +0.0859375f,0.757813f, +0.0859375f,0.75f, +0.09375f,0.757813f, +0.09375f,0.75f, +0.101563f,0.757813f, +0.101563f,0.75f, +0.109375f,0.757813f, +0.109375f,0.75f, +0.117188f,0.757813f, +0.117188f,0.75f, +0.125f,0.757813f, +0.125f,0.75f, +0.132813f,0.757813f, +0.132813f,0.75f, +0.140625f,0.757813f, +0.140625f,0.75f, +0.148438f,0.757813f, +0.148438f,0.75f, +0.15625f,0.757813f, +0.15625f,0.75f, +0.164063f,0.757813f, +0.164063f,0.75f, +0.171875f,0.757813f, +0.171875f,0.75f, +0.179688f,0.757813f, +0.179688f,0.75f, +0.1875f,0.757813f, +0.1875f,0.75f, +0.195313f,0.757813f, +0.195313f,0.75f, +0.203125f,0.757813f, +0.203125f,0.75f, +0.210938f,0.757813f, +0.210938f,0.75f, +0.21875f,0.757813f, +0.21875f,0.75f, +0.226563f,0.757813f, +0.226563f,0.75f, +0.234375f,0.757813f, +0.234375f,0.75f, +0.242188f,0.757813f, +0.242188f,0.75f, +0.25f,0.757813f, +0.25f,0.75f, +0.257813f,0.757813f, +0.257813f,0.75f, +0.265625f,0.757813f, +0.265625f,0.75f, +0.273438f,0.757813f, +0.273438f,0.75f, +0.28125f,0.757813f, +0.28125f,0.75f, +0.289063f,0.757813f, +0.289063f,0.75f, +0.296875f,0.757813f, +0.296875f,0.75f, +0.304688f,0.757813f, +0.304688f,0.75f, +0.3125f,0.757813f, +0.3125f,0.75f, +0.320313f,0.757813f, +0.320313f,0.75f, +0.328125f,0.757813f, +0.328125f,0.75f, +0.335938f,0.757813f, +0.335938f,0.75f, +0.34375f,0.757813f, +0.34375f,0.75f, +0.351563f,0.757813f, +0.351563f,0.75f, +0.359375f,0.757813f, +0.359375f,0.75f, +0.367188f,0.757813f, +0.367188f,0.75f, +0.375f,0.757813f, +0.375f,0.75f, +0.382813f,0.757813f, +0.382813f,0.75f, +0.390625f,0.757813f, +0.390625f,0.75f, +0.398438f,0.757813f, +0.398438f,0.75f, +0.40625f,0.757813f, +0.40625f,0.75f, +0.414063f,0.757813f, +0.414063f,0.75f, +0.421875f,0.757813f, +0.421875f,0.75f, +0.429688f,0.757813f, +0.429688f,0.75f, +0.4375f,0.757813f, +0.4375f,0.75f, +0.445313f,0.757813f, +0.445313f,0.75f, +0.453125f,0.757813f, +0.453125f,0.75f, +0.460938f,0.757813f, +0.460938f,0.75f, +0.46875f,0.757813f, +0.46875f,0.75f, +0.476563f,0.757813f, +0.476563f,0.75f, +0.484375f,0.757813f, +0.484375f,0.75f, +0.492188f,0.757813f, +0.492188f,0.75f, +0.5f,0.757813f, +0.5f,0.75f, +0.507813f,0.757813f, +0.507813f,0.75f, +0.0f,0.765625f, +0.0078125f,0.765625f, +0.015625f,0.765625f, +0.0234375f,0.765625f, +0.03125f,0.765625f, +0.0390625f,0.765625f, +0.046875f,0.765625f, +0.0546875f,0.765625f, +0.0625f,0.765625f, +0.0703125f,0.765625f, +0.078125f,0.765625f, +0.0859375f,0.765625f, +0.09375f,0.765625f, +0.101563f,0.765625f, +0.109375f,0.765625f, +0.117188f,0.765625f, +0.125f,0.765625f, +0.132813f,0.765625f, +0.140625f,0.765625f, +0.148438f,0.765625f, +0.15625f,0.765625f, +0.164063f,0.765625f, +0.171875f,0.765625f, +0.179688f,0.765625f, +0.1875f,0.765625f, +0.195313f,0.765625f, +0.203125f,0.765625f, +0.210938f,0.765625f, +0.21875f,0.765625f, +0.226563f,0.765625f, +0.234375f,0.765625f, +0.242188f,0.765625f, +0.25f,0.765625f, +0.257813f,0.765625f, +0.265625f,0.765625f, +0.273438f,0.765625f, +0.28125f,0.765625f, +0.289063f,0.765625f, +0.296875f,0.765625f, +0.304688f,0.765625f, +0.3125f,0.765625f, +0.320313f,0.765625f, +0.328125f,0.765625f, +0.335938f,0.765625f, +0.34375f,0.765625f, +0.351563f,0.765625f, +0.359375f,0.765625f, +0.367188f,0.765625f, +0.375f,0.765625f, +0.382813f,0.765625f, +0.390625f,0.765625f, +0.398438f,0.765625f, +0.40625f,0.765625f, +0.414063f,0.765625f, +0.421875f,0.765625f, +0.429688f,0.765625f, +0.4375f,0.765625f, +0.445313f,0.765625f, +0.453125f,0.765625f, +0.460938f,0.765625f, +0.46875f,0.765625f, +0.476563f,0.765625f, +0.484375f,0.765625f, +0.492188f,0.765625f, +0.5f,0.765625f, +0.507813f,0.765625f, +0.0f,0.773438f, +0.0078125f,0.773438f, +0.015625f,0.773438f, +0.0234375f,0.773438f, +0.03125f,0.773438f, +0.0390625f,0.773438f, +0.046875f,0.773438f, +0.0546875f,0.773438f, +0.0625f,0.773438f, +0.0703125f,0.773438f, +0.078125f,0.773438f, +0.0859375f,0.773438f, +0.09375f,0.773438f, +0.101563f,0.773438f, +0.109375f,0.773438f, +0.117188f,0.773438f, +0.125f,0.773438f, +0.132813f,0.773438f, +0.140625f,0.773438f, +0.148438f,0.773438f, +0.15625f,0.773438f, +0.164063f,0.773438f, +0.171875f,0.773438f, +0.179688f,0.773438f, +0.1875f,0.773438f, +0.195313f,0.773438f, +0.203125f,0.773438f, +0.210938f,0.773438f, +0.21875f,0.773438f, +0.226563f,0.773438f, +0.234375f,0.773438f, +0.242188f,0.773438f, +0.25f,0.773438f, +0.257813f,0.773438f, +0.265625f,0.773438f, +0.273438f,0.773438f, +0.28125f,0.773438f, +0.289063f,0.773438f, +0.296875f,0.773438f, +0.304688f,0.773438f, +0.3125f,0.773438f, +0.320313f,0.773438f, +0.328125f,0.773438f, +0.335938f,0.773438f, +0.34375f,0.773438f, +0.351563f,0.773438f, +0.359375f,0.773438f, +0.367188f,0.773438f, +0.375f,0.773438f, +0.382813f,0.773438f, +0.390625f,0.773438f, +0.398438f,0.773438f, +0.40625f,0.773438f, +0.414063f,0.773438f, +0.421875f,0.773438f, +0.429688f,0.773438f, +0.4375f,0.773438f, +0.445313f,0.773438f, +0.453125f,0.773438f, +0.460938f,0.773438f, +0.46875f,0.773438f, +0.476563f,0.773438f, +0.484375f,0.773438f, +0.492188f,0.773438f, +0.5f,0.773438f, +0.507813f,0.773438f, +0.0f,0.78125f, +0.0078125f,0.78125f, +0.015625f,0.78125f, +0.0234375f,0.78125f, +0.03125f,0.78125f, +0.0390625f,0.78125f, +0.046875f,0.78125f, +0.0546875f,0.78125f, +0.0625f,0.78125f, +0.0703125f,0.78125f, +0.078125f,0.78125f, +0.0859375f,0.78125f, +0.09375f,0.78125f, +0.101563f,0.78125f, +0.109375f,0.78125f, +0.117188f,0.78125f, +0.125f,0.78125f, +0.132813f,0.78125f, +0.140625f,0.78125f, +0.148438f,0.78125f, +0.15625f,0.78125f, +0.164063f,0.78125f, +0.171875f,0.78125f, +0.179688f,0.78125f, +0.1875f,0.78125f, +0.195313f,0.78125f, +0.203125f,0.78125f, +0.210938f,0.78125f, +0.21875f,0.78125f, +0.226563f,0.78125f, +0.234375f,0.78125f, +0.242188f,0.78125f, +0.25f,0.78125f, +0.257813f,0.78125f, +0.265625f,0.78125f, +0.273438f,0.78125f, +0.28125f,0.78125f, +0.289063f,0.78125f, +0.296875f,0.78125f, +0.304688f,0.78125f, +0.3125f,0.78125f, +0.320313f,0.78125f, +0.328125f,0.78125f, +0.335938f,0.78125f, +0.34375f,0.78125f, +0.351563f,0.78125f, +0.359375f,0.78125f, +0.367188f,0.78125f, +0.375f,0.78125f, +0.382813f,0.78125f, +0.390625f,0.78125f, +0.398438f,0.78125f, +0.40625f,0.78125f, +0.414063f,0.78125f, +0.421875f,0.78125f, +0.429688f,0.78125f, +0.4375f,0.78125f, +0.445313f,0.78125f, +0.453125f,0.78125f, +0.460938f,0.78125f, +0.46875f,0.78125f, +0.476563f,0.78125f, +0.484375f,0.78125f, +0.492188f,0.78125f, +0.5f,0.78125f, +0.507813f,0.78125f, +0.0f,0.789063f, +0.0078125f,0.789063f, +0.015625f,0.789063f, +0.0234375f,0.789063f, +0.03125f,0.789063f, +0.0390625f,0.789063f, +0.046875f,0.789063f, +0.0546875f,0.789063f, +0.0625f,0.789063f, +0.0703125f,0.789063f, +0.078125f,0.789063f, +0.0859375f,0.789063f, +0.09375f,0.789063f, +0.101563f,0.789063f, +0.109375f,0.789063f, +0.117188f,0.789063f, +0.125f,0.789063f, +0.132813f,0.789063f, +0.140625f,0.789063f, +0.148438f,0.789063f, +0.15625f,0.789063f, +0.164063f,0.789063f, +0.171875f,0.789063f, +0.179688f,0.789063f, +0.1875f,0.789063f, +0.195313f,0.789063f, +0.203125f,0.789063f, +0.210938f,0.789063f, +0.21875f,0.789063f, +0.226563f,0.789063f, +0.234375f,0.789063f, +0.242188f,0.789063f, +0.25f,0.789063f, +0.257813f,0.789063f, +0.265625f,0.789063f, +0.273438f,0.789063f, +0.28125f,0.789063f, +0.289063f,0.789063f, +0.296875f,0.789063f, +0.304688f,0.789063f, +0.3125f,0.789063f, +0.320313f,0.789063f, +0.328125f,0.789063f, +0.335938f,0.789063f, +0.34375f,0.789063f, +0.351563f,0.789063f, +0.359375f,0.789063f, +0.367188f,0.789063f, +0.375f,0.789063f, +0.382813f,0.789063f, +0.390625f,0.789063f, +0.398438f,0.789063f, +0.40625f,0.789063f, +0.414063f,0.789063f, +0.421875f,0.789063f, +0.429688f,0.789063f, +0.4375f,0.789063f, +0.445313f,0.789063f, +0.453125f,0.789063f, +0.460938f,0.789063f, +0.46875f,0.789063f, +0.476563f,0.789063f, +0.484375f,0.789063f, +0.492188f,0.789063f, +0.5f,0.789063f, +0.507813f,0.789063f, +0.0f,0.796875f, +0.0078125f,0.796875f, +0.015625f,0.796875f, +0.0234375f,0.796875f, +0.03125f,0.796875f, +0.0390625f,0.796875f, +0.046875f,0.796875f, +0.0546875f,0.796875f, +0.0625f,0.796875f, +0.0703125f,0.796875f, +0.078125f,0.796875f, +0.0859375f,0.796875f, +0.09375f,0.796875f, +0.101563f,0.796875f, +0.109375f,0.796875f, +0.117188f,0.796875f, +0.125f,0.796875f, +0.132813f,0.796875f, +0.140625f,0.796875f, +0.148438f,0.796875f, +0.15625f,0.796875f, +0.164063f,0.796875f, +0.171875f,0.796875f, +0.179688f,0.796875f, +0.1875f,0.796875f, +0.195313f,0.796875f, +0.203125f,0.796875f, +0.210938f,0.796875f, +0.21875f,0.796875f, +0.226563f,0.796875f, +0.234375f,0.796875f, +0.242188f,0.796875f, +0.25f,0.796875f, +0.257813f,0.796875f, +0.265625f,0.796875f, +0.273438f,0.796875f, +0.28125f,0.796875f, +0.289063f,0.796875f, +0.296875f,0.796875f, +0.304688f,0.796875f, +0.3125f,0.796875f, +0.320313f,0.796875f, +0.328125f,0.796875f, +0.335938f,0.796875f, +0.34375f,0.796875f, +0.351563f,0.796875f, +0.359375f,0.796875f, +0.367188f,0.796875f, +0.375f,0.796875f, +0.382813f,0.796875f, +0.390625f,0.796875f, +0.398438f,0.796875f, +0.40625f,0.796875f, +0.414063f,0.796875f, +0.421875f,0.796875f, +0.429688f,0.796875f, +0.4375f,0.796875f, +0.445313f,0.796875f, +0.453125f,0.796875f, +0.460938f,0.796875f, +0.46875f,0.796875f, +0.476563f,0.796875f, +0.484375f,0.796875f, +0.492188f,0.796875f, +0.5f,0.796875f, +0.507813f,0.796875f, +0.0f,0.804688f, +0.0078125f,0.804688f, +0.015625f,0.804688f, +0.0234375f,0.804688f, +0.03125f,0.804688f, +0.0390625f,0.804688f, +0.046875f,0.804688f, +0.0546875f,0.804688f, +0.0625f,0.804688f, +0.0703125f,0.804688f, +0.078125f,0.804688f, +0.0859375f,0.804688f, +0.09375f,0.804688f, +0.101563f,0.804688f, +0.109375f,0.804688f, +0.117188f,0.804688f, +0.125f,0.804688f, +0.132813f,0.804688f, +0.140625f,0.804688f, +0.148438f,0.804688f, +0.15625f,0.804688f, +0.164063f,0.804688f, +0.171875f,0.804688f, +0.179688f,0.804688f, +0.1875f,0.804688f, +0.195313f,0.804688f, +0.203125f,0.804688f, +0.210938f,0.804688f, +0.21875f,0.804688f, +0.226563f,0.804688f, +0.234375f,0.804688f, +0.242188f,0.804688f, +0.25f,0.804688f, +0.257813f,0.804688f, +0.265625f,0.804688f, +0.273438f,0.804688f, +0.28125f,0.804688f, +0.289063f,0.804688f, +0.296875f,0.804688f, +0.304688f,0.804688f, +0.3125f,0.804688f, +0.320313f,0.804688f, +0.328125f,0.804688f, +0.335938f,0.804688f, +0.34375f,0.804688f, +0.351563f,0.804688f, +0.359375f,0.804688f, +0.367188f,0.804688f, +0.375f,0.804688f, +0.382813f,0.804688f, +0.390625f,0.804688f, +0.398438f,0.804688f, +0.40625f,0.804688f, +0.414063f,0.804688f, +0.421875f,0.804688f, +0.429688f,0.804688f, +0.4375f,0.804688f, +0.445313f,0.804688f, +0.453125f,0.804688f, +0.460938f,0.804688f, +0.46875f,0.804688f, +0.476563f,0.804688f, +0.484375f,0.804688f, +0.492188f,0.804688f, +0.5f,0.804688f, +0.507813f,0.804688f, +0.0f,0.8125f, +0.0078125f,0.8125f, +0.015625f,0.8125f, +0.0234375f,0.8125f, +0.03125f,0.8125f, +0.0390625f,0.8125f, +0.046875f,0.8125f, +0.0546875f,0.8125f, +0.0625f,0.8125f, +0.0703125f,0.8125f, +0.078125f,0.8125f, +0.0859375f,0.8125f, +0.09375f,0.8125f, +0.101563f,0.8125f, +0.109375f,0.8125f, +0.117188f,0.8125f, +0.125f,0.8125f, +0.132813f,0.8125f, +0.140625f,0.8125f, +0.148438f,0.8125f, +0.15625f,0.8125f, +0.164063f,0.8125f, +0.171875f,0.8125f, +0.179688f,0.8125f, +0.1875f,0.8125f, +0.195313f,0.8125f, +0.203125f,0.8125f, +0.210938f,0.8125f, +0.21875f,0.8125f, +0.226563f,0.8125f, +0.234375f,0.8125f, +0.242188f,0.8125f, +0.25f,0.8125f, +0.257813f,0.8125f, +0.265625f,0.8125f, +0.273438f,0.8125f, +0.28125f,0.8125f, +0.289063f,0.8125f, +0.296875f,0.8125f, +0.304688f,0.8125f, +0.3125f,0.8125f, +0.320313f,0.8125f, +0.328125f,0.8125f, +0.335938f,0.8125f, +0.34375f,0.8125f, +0.351563f,0.8125f, +0.359375f,0.8125f, +0.367188f,0.8125f, +0.375f,0.8125f, +0.382813f,0.8125f, +0.390625f,0.8125f, +0.398438f,0.8125f, +0.40625f,0.8125f, +0.414063f,0.8125f, +0.421875f,0.8125f, +0.429688f,0.8125f, +0.4375f,0.8125f, +0.445313f,0.8125f, +0.453125f,0.8125f, +0.460938f,0.8125f, +0.46875f,0.8125f, +0.476563f,0.8125f, +0.484375f,0.8125f, +0.492188f,0.8125f, +0.5f,0.8125f, +0.507813f,0.8125f, +0.0f,0.820313f, +0.0078125f,0.820313f, +0.015625f,0.820313f, +0.0234375f,0.820313f, +0.03125f,0.820313f, +0.0390625f,0.820313f, +0.046875f,0.820313f, +0.0546875f,0.820313f, +0.0625f,0.820313f, +0.0703125f,0.820313f, +0.078125f,0.820313f, +0.0859375f,0.820313f, +0.09375f,0.820313f, +0.101563f,0.820313f, +0.109375f,0.820313f, +0.117188f,0.820313f, +0.125f,0.820313f, +0.132813f,0.820313f, +0.140625f,0.820313f, +0.148438f,0.820313f, +0.15625f,0.820313f, +0.164063f,0.820313f, +0.171875f,0.820313f, +0.179688f,0.820313f, +0.1875f,0.820313f, +0.195313f,0.820313f, +0.203125f,0.820313f, +0.210938f,0.820313f, +0.21875f,0.820313f, +0.226563f,0.820313f, +0.234375f,0.820313f, +0.242188f,0.820313f, +0.25f,0.820313f, +0.257813f,0.820313f, +0.265625f,0.820313f, +0.273438f,0.820313f, +0.28125f,0.820313f, +0.289063f,0.820313f, +0.296875f,0.820313f, +0.304688f,0.820313f, +0.3125f,0.820313f, +0.320313f,0.820313f, +0.328125f,0.820313f, +0.335938f,0.820313f, +0.34375f,0.820313f, +0.351563f,0.820313f, +0.359375f,0.820313f, +0.367188f,0.820313f, +0.375f,0.820313f, +0.382813f,0.820313f, +0.390625f,0.820313f, +0.398438f,0.820313f, +0.40625f,0.820313f, +0.414063f,0.820313f, +0.421875f,0.820313f, +0.429688f,0.820313f, +0.4375f,0.820313f, +0.445313f,0.820313f, +0.453125f,0.820313f, +0.460938f,0.820313f, +0.46875f,0.820313f, +0.476563f,0.820313f, +0.484375f,0.820313f, +0.492188f,0.820313f, +0.5f,0.820313f, +0.507813f,0.820313f, +0.0f,0.828125f, +0.0078125f,0.828125f, +0.015625f,0.828125f, +0.0234375f,0.828125f, +0.03125f,0.828125f, +0.0390625f,0.828125f, +0.046875f,0.828125f, +0.0546875f,0.828125f, +0.0625f,0.828125f, +0.0703125f,0.828125f, +0.078125f,0.828125f, +0.0859375f,0.828125f, +0.09375f,0.828125f, +0.101563f,0.828125f, +0.109375f,0.828125f, +0.117188f,0.828125f, +0.125f,0.828125f, +0.132813f,0.828125f, +0.140625f,0.828125f, +0.148438f,0.828125f, +0.15625f,0.828125f, +0.164063f,0.828125f, +0.171875f,0.828125f, +0.179688f,0.828125f, +0.1875f,0.828125f, +0.195313f,0.828125f, +0.203125f,0.828125f, +0.210938f,0.828125f, +0.21875f,0.828125f, +0.226563f,0.828125f, +0.234375f,0.828125f, +0.242188f,0.828125f, +0.25f,0.828125f, +0.257813f,0.828125f, +0.265625f,0.828125f, +0.273438f,0.828125f, +0.28125f,0.828125f, +0.289063f,0.828125f, +0.296875f,0.828125f, +0.304688f,0.828125f, +0.3125f,0.828125f, +0.320313f,0.828125f, +0.328125f,0.828125f, +0.335938f,0.828125f, +0.34375f,0.828125f, +0.351563f,0.828125f, +0.359375f,0.828125f, +0.367188f,0.828125f, +0.375f,0.828125f, +0.382813f,0.828125f, +0.390625f,0.828125f, +0.398438f,0.828125f, +0.40625f,0.828125f, +0.414063f,0.828125f, +0.421875f,0.828125f, +0.429688f,0.828125f, +0.4375f,0.828125f, +0.445313f,0.828125f, +0.453125f,0.828125f, +0.460938f,0.828125f, +0.46875f,0.828125f, +0.476563f,0.828125f, +0.484375f,0.828125f, +0.492188f,0.828125f, +0.5f,0.828125f, +0.507813f,0.828125f, +0.0f,0.835938f, +0.0078125f,0.835938f, +0.015625f,0.835938f, +0.0234375f,0.835938f, +0.03125f,0.835938f, +0.0390625f,0.835938f, +0.046875f,0.835938f, +0.0546875f,0.835938f, +0.0625f,0.835938f, +0.0703125f,0.835938f, +0.078125f,0.835938f, +0.0859375f,0.835938f, +0.09375f,0.835938f, +0.101563f,0.835938f, +0.109375f,0.835938f, +0.117188f,0.835938f, +0.125f,0.835938f, +0.132813f,0.835938f, +0.140625f,0.835938f, +0.148438f,0.835938f, +0.15625f,0.835938f, +0.164063f,0.835938f, +0.171875f,0.835938f, +0.179688f,0.835938f, +0.1875f,0.835938f, +0.195313f,0.835938f, +0.203125f,0.835938f, +0.210938f,0.835938f, +0.21875f,0.835938f, +0.226563f,0.835938f, +0.234375f,0.835938f, +0.242188f,0.835938f, +0.25f,0.835938f, +0.257813f,0.835938f, +0.265625f,0.835938f, +0.273438f,0.835938f, +0.28125f,0.835938f, +0.289063f,0.835938f, +0.296875f,0.835938f, +0.304688f,0.835938f, +0.3125f,0.835938f, +0.320313f,0.835938f, +0.328125f,0.835938f, +0.335938f,0.835938f, +0.34375f,0.835938f, +0.351563f,0.835938f, +0.359375f,0.835938f, +0.367188f,0.835938f, +0.375f,0.835938f, +0.382813f,0.835938f, +0.390625f,0.835938f, +0.398438f,0.835938f, +0.40625f,0.835938f, +0.414063f,0.835938f, +0.421875f,0.835938f, +0.429688f,0.835938f, +0.4375f,0.835938f, +0.445313f,0.835938f, +0.453125f,0.835938f, +0.460938f,0.835938f, +0.46875f,0.835938f, +0.476563f,0.835938f, +0.484375f,0.835938f, +0.492188f,0.835938f, +0.5f,0.835938f, +0.507813f,0.835938f, +0.0f,0.84375f, +0.0078125f,0.84375f, +0.015625f,0.84375f, +0.0234375f,0.84375f, +0.03125f,0.84375f, +0.0390625f,0.84375f, +0.046875f,0.84375f, +0.0546875f,0.84375f, +0.0625f,0.84375f, +0.0703125f,0.84375f, +0.078125f,0.84375f, +0.0859375f,0.84375f, +0.09375f,0.84375f, +0.101563f,0.84375f, +0.109375f,0.84375f, +0.117188f,0.84375f, +0.125f,0.84375f, +0.132813f,0.84375f, +0.140625f,0.84375f, +0.148438f,0.84375f, +0.15625f,0.84375f, +0.164063f,0.84375f, +0.171875f,0.84375f, +0.179688f,0.84375f, +0.1875f,0.84375f, +0.195313f,0.84375f, +0.203125f,0.84375f, +0.210938f,0.84375f, +0.21875f,0.84375f, +0.226563f,0.84375f, +0.234375f,0.84375f, +0.242188f,0.84375f, +0.25f,0.84375f, +0.257813f,0.84375f, +0.265625f,0.84375f, +0.273438f,0.84375f, +0.28125f,0.84375f, +0.289063f,0.84375f, +0.296875f,0.84375f, +0.304688f,0.84375f, +0.3125f,0.84375f, +0.320313f,0.84375f, +0.328125f,0.84375f, +0.335938f,0.84375f, +0.34375f,0.84375f, +0.351563f,0.84375f, +0.359375f,0.84375f, +0.367188f,0.84375f, +0.375f,0.84375f, +0.382813f,0.84375f, +0.390625f,0.84375f, +0.398438f,0.84375f, +0.40625f,0.84375f, +0.414063f,0.84375f, +0.421875f,0.84375f, +0.429688f,0.84375f, +0.4375f,0.84375f, +0.445313f,0.84375f, +0.453125f,0.84375f, +0.460938f,0.84375f, +0.46875f,0.84375f, +0.476563f,0.84375f, +0.484375f,0.84375f, +0.492188f,0.84375f, +0.5f,0.84375f, +0.507813f,0.84375f, +0.0f,0.851563f, +0.0078125f,0.851563f, +0.015625f,0.851563f, +0.0234375f,0.851563f, +0.03125f,0.851563f, +0.0390625f,0.851563f, +0.046875f,0.851563f, +0.0546875f,0.851563f, +0.0625f,0.851563f, +0.0703125f,0.851563f, +0.078125f,0.851563f, +0.0859375f,0.851563f, +0.09375f,0.851563f, +0.101563f,0.851563f, +0.109375f,0.851563f, +0.117188f,0.851563f, +0.125f,0.851563f, +0.132813f,0.851563f, +0.140625f,0.851563f, +0.148438f,0.851563f, +0.15625f,0.851563f, +0.164063f,0.851563f, +0.171875f,0.851563f, +0.179688f,0.851563f, +0.1875f,0.851563f, +0.195313f,0.851563f, +0.203125f,0.851563f, +0.210938f,0.851563f, +0.21875f,0.851563f, +0.226563f,0.851563f, +0.234375f,0.851563f, +0.242188f,0.851563f, +0.25f,0.851563f, +0.257813f,0.851563f, +0.265625f,0.851563f, +0.273438f,0.851563f, +0.28125f,0.851563f, +0.289063f,0.851563f, +0.296875f,0.851563f, +0.304688f,0.851563f, +0.3125f,0.851563f, +0.320313f,0.851563f, +0.328125f,0.851563f, +0.335938f,0.851563f, +0.34375f,0.851563f, +0.351563f,0.851563f, +0.359375f,0.851563f, +0.367188f,0.851563f, +0.375f,0.851563f, +0.382813f,0.851563f, +0.390625f,0.851563f, +0.398438f,0.851563f, +0.40625f,0.851563f, +0.414063f,0.851563f, +0.421875f,0.851563f, +0.429688f,0.851563f, +0.4375f,0.851563f, +0.445313f,0.851563f, +0.453125f,0.851563f, +0.460938f,0.851563f, +0.46875f,0.851563f, +0.476563f,0.851563f, +0.484375f,0.851563f, +0.492188f,0.851563f, +0.5f,0.851563f, +0.507813f,0.851563f, +0.0f,0.859375f, +0.0078125f,0.859375f, +0.015625f,0.859375f, +0.0234375f,0.859375f, +0.03125f,0.859375f, +0.0390625f,0.859375f, +0.046875f,0.859375f, +0.0546875f,0.859375f, +0.0625f,0.859375f, +0.0703125f,0.859375f, +0.078125f,0.859375f, +0.0859375f,0.859375f, +0.09375f,0.859375f, +0.101563f,0.859375f, +0.109375f,0.859375f, +0.117188f,0.859375f, +0.125f,0.859375f, +0.132813f,0.859375f, +0.140625f,0.859375f, +0.148438f,0.859375f, +0.15625f,0.859375f, +0.164063f,0.859375f, +0.171875f,0.859375f, +0.179688f,0.859375f, +0.1875f,0.859375f, +0.195313f,0.859375f, +0.203125f,0.859375f, +0.210938f,0.859375f, +0.21875f,0.859375f, +0.226563f,0.859375f, +0.234375f,0.859375f, +0.242188f,0.859375f, +0.25f,0.859375f, +0.257813f,0.859375f, +0.265625f,0.859375f, +0.273438f,0.859375f, +0.28125f,0.859375f, +0.289063f,0.859375f, +0.296875f,0.859375f, +0.304688f,0.859375f, +0.3125f,0.859375f, +0.320313f,0.859375f, +0.328125f,0.859375f, +0.335938f,0.859375f, +0.34375f,0.859375f, +0.351563f,0.859375f, +0.359375f,0.859375f, +0.367188f,0.859375f, +0.375f,0.859375f, +0.382813f,0.859375f, +0.390625f,0.859375f, +0.398438f,0.859375f, +0.40625f,0.859375f, +0.414063f,0.859375f, +0.421875f,0.859375f, +0.429688f,0.859375f, +0.4375f,0.859375f, +0.445313f,0.859375f, +0.453125f,0.859375f, +0.460938f,0.859375f, +0.46875f,0.859375f, +0.476563f,0.859375f, +0.484375f,0.859375f, +0.492188f,0.859375f, +0.5f,0.859375f, +0.507813f,0.859375f, +0.0f,0.867188f, +0.0078125f,0.867188f, +0.015625f,0.867188f, +0.0234375f,0.867188f, +0.03125f,0.867188f, +0.0390625f,0.867188f, +0.046875f,0.867188f, +0.0546875f,0.867188f, +0.0625f,0.867188f, +0.0703125f,0.867188f, +0.078125f,0.867188f, +0.0859375f,0.867188f, +0.09375f,0.867188f, +0.101563f,0.867188f, +0.109375f,0.867188f, +0.117188f,0.867188f, +0.125f,0.867188f, +0.132813f,0.867188f, +0.140625f,0.867188f, +0.148438f,0.867188f, +0.15625f,0.867188f, +0.164063f,0.867188f, +0.171875f,0.867188f, +0.179688f,0.867188f, +0.1875f,0.867188f, +0.195313f,0.867188f, +0.203125f,0.867188f, +0.210938f,0.867188f, +0.21875f,0.867188f, +0.226563f,0.867188f, +0.234375f,0.867188f, +0.242188f,0.867188f, +0.25f,0.867188f, +0.257813f,0.867188f, +0.265625f,0.867188f, +0.273438f,0.867188f, +0.28125f,0.867188f, +0.289063f,0.867188f, +0.296875f,0.867188f, +0.304688f,0.867188f, +0.3125f,0.867188f, +0.320313f,0.867188f, +0.328125f,0.867188f, +0.335938f,0.867188f, +0.34375f,0.867188f, +0.351563f,0.867188f, +0.359375f,0.867188f, +0.367188f,0.867188f, +0.375f,0.867188f, +0.382813f,0.867188f, +0.390625f,0.867188f, +0.398438f,0.867188f, +0.40625f,0.867188f, +0.414063f,0.867188f, +0.421875f,0.867188f, +0.429688f,0.867188f, +0.4375f,0.867188f, +0.445313f,0.867188f, +0.453125f,0.867188f, +0.460938f,0.867188f, +0.46875f,0.867188f, +0.476563f,0.867188f, +0.484375f,0.867188f, +0.492188f,0.867188f, +0.5f,0.867188f, +0.507813f,0.867188f, +0.0f,0.875f, +0.0078125f,0.875f, +0.015625f,0.875f, +0.0234375f,0.875f, +0.03125f,0.875f, +0.0390625f,0.875f, +0.046875f,0.875f, +0.0546875f,0.875f, +0.0625f,0.875f, +0.0703125f,0.875f, +0.078125f,0.875f, +0.0859375f,0.875f, +0.09375f,0.875f, +0.101563f,0.875f, +0.109375f,0.875f, +0.117188f,0.875f, +0.125f,0.875f, +0.132813f,0.875f, +0.140625f,0.875f, +0.148438f,0.875f, +0.15625f,0.875f, +0.164063f,0.875f, +0.171875f,0.875f, +0.179688f,0.875f, +0.1875f,0.875f, +0.195313f,0.875f, +0.203125f,0.875f, +0.210938f,0.875f, +0.21875f,0.875f, +0.226563f,0.875f, +0.234375f,0.875f, +0.242188f,0.875f, +0.25f,0.875f, +0.257813f,0.875f, +0.265625f,0.875f, +0.273438f,0.875f, +0.28125f,0.875f, +0.289063f,0.875f, +0.296875f,0.875f, +0.304688f,0.875f, +0.3125f,0.875f, +0.320313f,0.875f, +0.328125f,0.875f, +0.335938f,0.875f, +0.34375f,0.875f, +0.351563f,0.875f, +0.359375f,0.875f, +0.367188f,0.875f, +0.375f,0.875f, +0.382813f,0.875f, +0.390625f,0.875f, +0.398438f,0.875f, +0.40625f,0.875f, +0.414063f,0.875f, +0.421875f,0.875f, +0.429688f,0.875f, +0.4375f,0.875f, +0.445313f,0.875f, +0.453125f,0.875f, +0.460938f,0.875f, +0.46875f,0.875f, +0.476563f,0.875f, +0.484375f,0.875f, +0.492188f,0.875f, +0.5f,0.875f, +0.507813f,0.875f, +0.0f,0.882813f, +0.0078125f,0.882813f, +0.015625f,0.882813f, +0.0234375f,0.882813f, +0.03125f,0.882813f, +0.0390625f,0.882813f, +0.046875f,0.882813f, +0.0546875f,0.882813f, +0.0625f,0.882813f, +0.0703125f,0.882813f, +0.078125f,0.882813f, +0.0859375f,0.882813f, +0.09375f,0.882813f, +0.101563f,0.882813f, +0.109375f,0.882813f, +0.117188f,0.882813f, +0.125f,0.882813f, +0.132813f,0.882813f, +0.140625f,0.882813f, +0.148438f,0.882813f, +0.15625f,0.882813f, +0.164063f,0.882813f, +0.171875f,0.882813f, +0.179688f,0.882813f, +0.1875f,0.882813f, +0.195313f,0.882813f, +0.203125f,0.882813f, +0.210938f,0.882813f, +0.21875f,0.882813f, +0.226563f,0.882813f, +0.234375f,0.882813f, +0.242188f,0.882813f, +0.25f,0.882813f, +0.257813f,0.882813f, +0.265625f,0.882813f, +0.273438f,0.882813f, +0.28125f,0.882813f, +0.289063f,0.882813f, +0.296875f,0.882813f, +0.304688f,0.882813f, +0.3125f,0.882813f, +0.320313f,0.882813f, +0.328125f,0.882813f, +0.335938f,0.882813f, +0.34375f,0.882813f, +0.351563f,0.882813f, +0.359375f,0.882813f, +0.367188f,0.882813f, +0.375f,0.882813f, +0.382813f,0.882813f, +0.390625f,0.882813f, +0.398438f,0.882813f, +0.40625f,0.882813f, +0.414063f,0.882813f, +0.421875f,0.882813f, +0.429688f,0.882813f, +0.4375f,0.882813f, +0.445313f,0.882813f, +0.453125f,0.882813f, +0.460938f,0.882813f, +0.46875f,0.882813f, +0.476563f,0.882813f, +0.484375f,0.882813f, +0.492188f,0.882813f, +0.5f,0.882813f, +0.507813f,0.882813f, +0.0f,0.890625f, +0.0078125f,0.890625f, +0.015625f,0.890625f, +0.0234375f,0.890625f, +0.03125f,0.890625f, +0.0390625f,0.890625f, +0.046875f,0.890625f, +0.0546875f,0.890625f, +0.0625f,0.890625f, +0.0703125f,0.890625f, +0.078125f,0.890625f, +0.0859375f,0.890625f, +0.09375f,0.890625f, +0.101563f,0.890625f, +0.109375f,0.890625f, +0.117188f,0.890625f, +0.125f,0.890625f, +0.132813f,0.890625f, +0.140625f,0.890625f, +0.148438f,0.890625f, +0.15625f,0.890625f, +0.164063f,0.890625f, +0.171875f,0.890625f, +0.179688f,0.890625f, +0.1875f,0.890625f, +0.195313f,0.890625f, +0.203125f,0.890625f, +0.210938f,0.890625f, +0.21875f,0.890625f, +0.226563f,0.890625f, +0.234375f,0.890625f, +0.242188f,0.890625f, +0.25f,0.890625f, +0.257813f,0.890625f, +0.265625f,0.890625f, +0.273438f,0.890625f, +0.28125f,0.890625f, +0.289063f,0.890625f, +0.296875f,0.890625f, +0.304688f,0.890625f, +0.3125f,0.890625f, +0.320313f,0.890625f, +0.328125f,0.890625f, +0.335938f,0.890625f, +0.34375f,0.890625f, +0.351563f,0.890625f, +0.359375f,0.890625f, +0.367188f,0.890625f, +0.375f,0.890625f, +0.382813f,0.890625f, +0.390625f,0.890625f, +0.398438f,0.890625f, +0.40625f,0.890625f, +0.414063f,0.890625f, +0.421875f,0.890625f, +0.429688f,0.890625f, +0.4375f,0.890625f, +0.445313f,0.890625f, +0.453125f,0.890625f, +0.460938f,0.890625f, +0.46875f,0.890625f, +0.476563f,0.890625f, +0.484375f,0.890625f, +0.492188f,0.890625f, +0.5f,0.890625f, +0.507813f,0.890625f, +0.0f,0.898438f, +0.0078125f,0.898438f, +0.015625f,0.898438f, +0.0234375f,0.898438f, +0.03125f,0.898438f, +0.0390625f,0.898438f, +0.046875f,0.898438f, +0.0546875f,0.898438f, +0.0625f,0.898438f, +0.0703125f,0.898438f, +0.078125f,0.898438f, +0.0859375f,0.898438f, +0.09375f,0.898438f, +0.101563f,0.898438f, +0.109375f,0.898438f, +0.117188f,0.898438f, +0.125f,0.898438f, +0.132813f,0.898438f, +0.140625f,0.898438f, +0.148438f,0.898438f, +0.15625f,0.898438f, +0.164063f,0.898438f, +0.171875f,0.898438f, +0.179688f,0.898438f, +0.1875f,0.898438f, +0.195313f,0.898438f, +0.203125f,0.898438f, +0.210938f,0.898438f, +0.21875f,0.898438f, +0.226563f,0.898438f, +0.234375f,0.898438f, +0.242188f,0.898438f, +0.25f,0.898438f, +0.257813f,0.898438f, +0.265625f,0.898438f, +0.273438f,0.898438f, +0.28125f,0.898438f, +0.289063f,0.898438f, +0.296875f,0.898438f, +0.304688f,0.898438f, +0.3125f,0.898438f, +0.320313f,0.898438f, +0.328125f,0.898438f, +0.335938f,0.898438f, +0.34375f,0.898438f, +0.351563f,0.898438f, +0.359375f,0.898438f, +0.367188f,0.898438f, +0.375f,0.898438f, +0.382813f,0.898438f, +0.390625f,0.898438f, +0.398438f,0.898438f, +0.40625f,0.898438f, +0.414063f,0.898438f, +0.421875f,0.898438f, +0.429688f,0.898438f, +0.4375f,0.898438f, +0.445313f,0.898438f, +0.453125f,0.898438f, +0.460938f,0.898438f, +0.46875f,0.898438f, +0.476563f,0.898438f, +0.484375f,0.898438f, +0.492188f,0.898438f, +0.5f,0.898438f, +0.507813f,0.898438f, +0.0f,0.90625f, +0.0078125f,0.90625f, +0.015625f,0.90625f, +0.0234375f,0.90625f, +0.03125f,0.90625f, +0.0390625f,0.90625f, +0.046875f,0.90625f, +0.0546875f,0.90625f, +0.0625f,0.90625f, +0.0703125f,0.90625f, +0.078125f,0.90625f, +0.0859375f,0.90625f, +0.09375f,0.90625f, +0.101563f,0.90625f, +0.109375f,0.90625f, +0.117188f,0.90625f, +0.125f,0.90625f, +0.132813f,0.90625f, +0.140625f,0.90625f, +0.148438f,0.90625f, +0.15625f,0.90625f, +0.164063f,0.90625f, +0.171875f,0.90625f, +0.179688f,0.90625f, +0.1875f,0.90625f, +0.195313f,0.90625f, +0.203125f,0.90625f, +0.210938f,0.90625f, +0.21875f,0.90625f, +0.226563f,0.90625f, +0.234375f,0.90625f, +0.242188f,0.90625f, +0.25f,0.90625f, +0.257813f,0.90625f, +0.265625f,0.90625f, +0.273438f,0.90625f, +0.28125f,0.90625f, +0.289063f,0.90625f, +0.296875f,0.90625f, +0.304688f,0.90625f, +0.3125f,0.90625f, +0.320313f,0.90625f, +0.328125f,0.90625f, +0.335938f,0.90625f, +0.34375f,0.90625f, +0.351563f,0.90625f, +0.359375f,0.90625f, +0.367188f,0.90625f, +0.375f,0.90625f, +0.382813f,0.90625f, +0.390625f,0.90625f, +0.398438f,0.90625f, +0.40625f,0.90625f, +0.414063f,0.90625f, +0.421875f,0.90625f, +0.429688f,0.90625f, +0.4375f,0.90625f, +0.445313f,0.90625f, +0.453125f,0.90625f, +0.460938f,0.90625f, +0.46875f,0.90625f, +0.476563f,0.90625f, +0.484375f,0.90625f, +0.492188f,0.90625f, +0.5f,0.90625f, +0.507813f,0.90625f, +0.0f,0.914063f, +0.0078125f,0.914063f, +0.015625f,0.914063f, +0.0234375f,0.914063f, +0.03125f,0.914063f, +0.0390625f,0.914063f, +0.046875f,0.914063f, +0.0546875f,0.914063f, +0.0625f,0.914063f, +0.0703125f,0.914063f, +0.078125f,0.914063f, +0.0859375f,0.914063f, +0.09375f,0.914063f, +0.101563f,0.914063f, +0.109375f,0.914063f, +0.117188f,0.914063f, +0.125f,0.914063f, +0.132813f,0.914063f, +0.140625f,0.914063f, +0.148438f,0.914063f, +0.15625f,0.914063f, +0.164063f,0.914063f, +0.171875f,0.914063f, +0.179688f,0.914063f, +0.1875f,0.914063f, +0.195313f,0.914063f, +0.203125f,0.914063f, +0.210938f,0.914063f, +0.21875f,0.914063f, +0.226563f,0.914063f, +0.234375f,0.914063f, +0.242188f,0.914063f, +0.25f,0.914063f, +0.257813f,0.914063f, +0.265625f,0.914063f, +0.273438f,0.914063f, +0.28125f,0.914063f, +0.289063f,0.914063f, +0.296875f,0.914063f, +0.304688f,0.914063f, +0.3125f,0.914063f, +0.320313f,0.914063f, +0.328125f,0.914063f, +0.335938f,0.914063f, +0.34375f,0.914063f, +0.351563f,0.914063f, +0.359375f,0.914063f, +0.367188f,0.914063f, +0.375f,0.914063f, +0.382813f,0.914063f, +0.390625f,0.914063f, +0.398438f,0.914063f, +0.40625f,0.914063f, +0.414063f,0.914063f, +0.421875f,0.914063f, +0.429688f,0.914063f, +0.4375f,0.914063f, +0.445313f,0.914063f, +0.453125f,0.914063f, +0.460938f,0.914063f, +0.46875f,0.914063f, +0.476563f,0.914063f, +0.484375f,0.914063f, +0.492188f,0.914063f, +0.5f,0.914063f, +0.507813f,0.914063f, +0.0f,0.921875f, +0.0078125f,0.921875f, +0.015625f,0.921875f, +0.0234375f,0.921875f, +0.03125f,0.921875f, +0.0390625f,0.921875f, +0.046875f,0.921875f, +0.0546875f,0.921875f, +0.0625f,0.921875f, +0.0703125f,0.921875f, +0.078125f,0.921875f, +0.0859375f,0.921875f, +0.09375f,0.921875f, +0.101563f,0.921875f, +0.109375f,0.921875f, +0.117188f,0.921875f, +0.125f,0.921875f, +0.132813f,0.921875f, +0.140625f,0.921875f, +0.148438f,0.921875f, +0.15625f,0.921875f, +0.164063f,0.921875f, +0.171875f,0.921875f, +0.179688f,0.921875f, +0.1875f,0.921875f, +0.195313f,0.921875f, +0.203125f,0.921875f, +0.210938f,0.921875f, +0.21875f,0.921875f, +0.226563f,0.921875f, +0.234375f,0.921875f, +0.242188f,0.921875f, +0.25f,0.921875f, +0.257813f,0.921875f, +0.265625f,0.921875f, +0.273438f,0.921875f, +0.28125f,0.921875f, +0.289063f,0.921875f, +0.296875f,0.921875f, +0.304688f,0.921875f, +0.3125f,0.921875f, +0.320313f,0.921875f, +0.328125f,0.921875f, +0.335938f,0.921875f, +0.34375f,0.921875f, +0.351563f,0.921875f, +0.359375f,0.921875f, +0.367188f,0.921875f, +0.375f,0.921875f, +0.382813f,0.921875f, +0.390625f,0.921875f, +0.398438f,0.921875f, +0.40625f,0.921875f, +0.414063f,0.921875f, +0.421875f,0.921875f, +0.429688f,0.921875f, +0.4375f,0.921875f, +0.445313f,0.921875f, +0.453125f,0.921875f, +0.460938f,0.921875f, +0.46875f,0.921875f, +0.476563f,0.921875f, +0.484375f,0.921875f, +0.492188f,0.921875f, +0.5f,0.921875f, +0.507813f,0.921875f, +0.0f,0.929688f, +0.0078125f,0.929688f, +0.015625f,0.929688f, +0.0234375f,0.929688f, +0.03125f,0.929688f, +0.0390625f,0.929688f, +0.046875f,0.929688f, +0.0546875f,0.929688f, +0.0625f,0.929688f, +0.0703125f,0.929688f, +0.078125f,0.929688f, +0.0859375f,0.929688f, +0.09375f,0.929688f, +0.101563f,0.929688f, +0.109375f,0.929688f, +0.117188f,0.929688f, +0.125f,0.929688f, +0.132813f,0.929688f, +0.140625f,0.929688f, +0.148438f,0.929688f, +0.15625f,0.929688f, +0.164063f,0.929688f, +0.171875f,0.929688f, +0.179688f,0.929688f, +0.1875f,0.929688f, +0.195313f,0.929688f, +0.203125f,0.929688f, +0.210938f,0.929688f, +0.21875f,0.929688f, +0.226563f,0.929688f, +0.234375f,0.929688f, +0.242188f,0.929688f, +0.25f,0.929688f, +0.257813f,0.929688f, +0.265625f,0.929688f, +0.273438f,0.929688f, +0.28125f,0.929688f, +0.289063f,0.929688f, +0.296875f,0.929688f, +0.304688f,0.929688f, +0.3125f,0.929688f, +0.320313f,0.929688f, +0.328125f,0.929688f, +0.335938f,0.929688f, +0.34375f,0.929688f, +0.351563f,0.929688f, +0.359375f,0.929688f, +0.367188f,0.929688f, +0.375f,0.929688f, +0.382813f,0.929688f, +0.390625f,0.929688f, +0.398438f,0.929688f, +0.40625f,0.929688f, +0.414063f,0.929688f, +0.421875f,0.929688f, +0.429688f,0.929688f, +0.4375f,0.929688f, +0.445313f,0.929688f, +0.453125f,0.929688f, +0.460938f,0.929688f, +0.46875f,0.929688f, +0.476563f,0.929688f, +0.484375f,0.929688f, +0.492188f,0.929688f, +0.5f,0.929688f, +0.507813f,0.929688f, +0.0f,0.9375f, +0.0078125f,0.9375f, +0.015625f,0.9375f, +0.0234375f,0.9375f, +0.03125f,0.9375f, +0.0390625f,0.9375f, +0.046875f,0.9375f, +0.0546875f,0.9375f, +0.0625f,0.9375f, +0.0703125f,0.9375f, +0.078125f,0.9375f, +0.0859375f,0.9375f, +0.09375f,0.9375f, +0.101563f,0.9375f, +0.109375f,0.9375f, +0.117188f,0.9375f, +0.125f,0.9375f, +0.132813f,0.9375f, +0.140625f,0.9375f, +0.148438f,0.9375f, +0.15625f,0.9375f, +0.164063f,0.9375f, +0.171875f,0.9375f, +0.179688f,0.9375f, +0.1875f,0.9375f, +0.195313f,0.9375f, +0.203125f,0.9375f, +0.210938f,0.9375f, +0.21875f,0.9375f, +0.226563f,0.9375f, +0.234375f,0.9375f, +0.242188f,0.9375f, +0.25f,0.9375f, +0.257813f,0.9375f, +0.265625f,0.9375f, +0.273438f,0.9375f, +0.28125f,0.9375f, +0.289063f,0.9375f, +0.296875f,0.9375f, +0.304688f,0.9375f, +0.3125f,0.9375f, +0.320313f,0.9375f, +0.328125f,0.9375f, +0.335938f,0.9375f, +0.34375f,0.9375f, +0.351563f,0.9375f, +0.359375f,0.9375f, +0.367188f,0.9375f, +0.375f,0.9375f, +0.382813f,0.9375f, +0.390625f,0.9375f, +0.398438f,0.9375f, +0.40625f,0.9375f, +0.414063f,0.9375f, +0.421875f,0.9375f, +0.429688f,0.9375f, +0.4375f,0.9375f, +0.445313f,0.9375f, +0.453125f,0.9375f, +0.460938f,0.9375f, +0.46875f,0.9375f, +0.476563f,0.9375f, +0.484375f,0.9375f, +0.492188f,0.9375f, +0.5f,0.9375f, +0.507813f,0.9375f, +0.0f,0.945313f, +0.0078125f,0.945313f, +0.015625f,0.945313f, +0.0234375f,0.945313f, +0.03125f,0.945313f, +0.0390625f,0.945313f, +0.046875f,0.945313f, +0.0546875f,0.945313f, +0.0625f,0.945313f, +0.0703125f,0.945313f, +0.078125f,0.945313f, +0.0859375f,0.945313f, +0.09375f,0.945313f, +0.101563f,0.945313f, +0.109375f,0.945313f, +0.117188f,0.945313f, +0.125f,0.945313f, +0.132813f,0.945313f, +0.140625f,0.945313f, +0.148438f,0.945313f, +0.15625f,0.945313f, +0.164063f,0.945313f, +0.171875f,0.945313f, +0.179688f,0.945313f, +0.1875f,0.945313f, +0.195313f,0.945313f, +0.203125f,0.945313f, +0.210938f,0.945313f, +0.21875f,0.945313f, +0.226563f,0.945313f, +0.234375f,0.945313f, +0.242188f,0.945313f, +0.25f,0.945313f, +0.257813f,0.945313f, +0.265625f,0.945313f, +0.273438f,0.945313f, +0.28125f,0.945313f, +0.289063f,0.945313f, +0.296875f,0.945313f, +0.304688f,0.945313f, +0.3125f,0.945313f, +0.320313f,0.945313f, +0.328125f,0.945313f, +0.335938f,0.945313f, +0.34375f,0.945313f, +0.351563f,0.945313f, +0.359375f,0.945313f, +0.367188f,0.945313f, +0.375f,0.945313f, +0.382813f,0.945313f, +0.390625f,0.945313f, +0.398438f,0.945313f, +0.40625f,0.945313f, +0.414063f,0.945313f, +0.421875f,0.945313f, +0.429688f,0.945313f, +0.4375f,0.945313f, +0.445313f,0.945313f, +0.453125f,0.945313f, +0.460938f,0.945313f, +0.46875f,0.945313f, +0.476563f,0.945313f, +0.484375f,0.945313f, +0.492188f,0.945313f, +0.5f,0.945313f, +0.507813f,0.945313f, +0.0f,0.953125f, +0.0078125f,0.953125f, +0.015625f,0.953125f, +0.0234375f,0.953125f, +0.03125f,0.953125f, +0.0390625f,0.953125f, +0.046875f,0.953125f, +0.0546875f,0.953125f, +0.0625f,0.953125f, +0.0703125f,0.953125f, +0.078125f,0.953125f, +0.0859375f,0.953125f, +0.09375f,0.953125f, +0.101563f,0.953125f, +0.109375f,0.953125f, +0.117188f,0.953125f, +0.125f,0.953125f, +0.132813f,0.953125f, +0.140625f,0.953125f, +0.148438f,0.953125f, +0.15625f,0.953125f, +0.164063f,0.953125f, +0.171875f,0.953125f, +0.179688f,0.953125f, +0.1875f,0.953125f, +0.195313f,0.953125f, +0.203125f,0.953125f, +0.210938f,0.953125f, +0.21875f,0.953125f, +0.226563f,0.953125f, +0.234375f,0.953125f, +0.242188f,0.953125f, +0.25f,0.953125f, +0.257813f,0.953125f, +0.265625f,0.953125f, +0.273438f,0.953125f, +0.28125f,0.953125f, +0.289063f,0.953125f, +0.296875f,0.953125f, +0.304688f,0.953125f, +0.3125f,0.953125f, +0.320313f,0.953125f, +0.328125f,0.953125f, +0.335938f,0.953125f, +0.34375f,0.953125f, +0.351563f,0.953125f, +0.359375f,0.953125f, +0.367188f,0.953125f, +0.375f,0.953125f, +0.382813f,0.953125f, +0.390625f,0.953125f, +0.398438f,0.953125f, +0.40625f,0.953125f, +0.414063f,0.953125f, +0.421875f,0.953125f, +0.429688f,0.953125f, +0.4375f,0.953125f, +0.445313f,0.953125f, +0.453125f,0.953125f, +0.460938f,0.953125f, +0.46875f,0.953125f, +0.476563f,0.953125f, +0.484375f,0.953125f, +0.492188f,0.953125f, +0.5f,0.953125f, +0.507813f,0.953125f, +0.0f,0.960938f, +0.0078125f,0.960938f, +0.015625f,0.960938f, +0.0234375f,0.960938f, +0.03125f,0.960938f, +0.0390625f,0.960938f, +0.046875f,0.960938f, +0.0546875f,0.960938f, +0.0625f,0.960938f, +0.0703125f,0.960938f, +0.078125f,0.960938f, +0.0859375f,0.960938f, +0.09375f,0.960938f, +0.101563f,0.960938f, +0.109375f,0.960938f, +0.117188f,0.960938f, +0.125f,0.960938f, +0.132813f,0.960938f, +0.140625f,0.960938f, +0.148438f,0.960938f, +0.15625f,0.960938f, +0.164063f,0.960938f, +0.171875f,0.960938f, +0.179688f,0.960938f, +0.1875f,0.960938f, +0.195313f,0.960938f, +0.203125f,0.960938f, +0.210938f,0.960938f, +0.21875f,0.960938f, +0.226563f,0.960938f, +0.234375f,0.960938f, +0.242188f,0.960938f, +0.25f,0.960938f, +0.257813f,0.960938f, +0.265625f,0.960938f, +0.273438f,0.960938f, +0.28125f,0.960938f, +0.289063f,0.960938f, +0.296875f,0.960938f, +0.304688f,0.960938f, +0.3125f,0.960938f, +0.320313f,0.960938f, +0.328125f,0.960938f, +0.335938f,0.960938f, +0.34375f,0.960938f, +0.351563f,0.960938f, +0.359375f,0.960938f, +0.367188f,0.960938f, +0.375f,0.960938f, +0.382813f,0.960938f, +0.390625f,0.960938f, +0.398438f,0.960938f, +0.40625f,0.960938f, +0.414063f,0.960938f, +0.421875f,0.960938f, +0.429688f,0.960938f, +0.4375f,0.960938f, +0.445313f,0.960938f, +0.453125f,0.960938f, +0.460938f,0.960938f, +0.46875f,0.960938f, +0.476563f,0.960938f, +0.484375f,0.960938f, +0.492188f,0.960938f, +0.5f,0.960938f, +0.507813f,0.960938f, +0.0f,0.96875f, +0.0078125f,0.96875f, +0.015625f,0.96875f, +0.0234375f,0.96875f, +0.03125f,0.96875f, +0.0390625f,0.96875f, +0.046875f,0.96875f, +0.0546875f,0.96875f, +0.0625f,0.96875f, +0.0703125f,0.96875f, +0.078125f,0.96875f, +0.0859375f,0.96875f, +0.09375f,0.96875f, +0.101563f,0.96875f, +0.109375f,0.96875f, +0.117188f,0.96875f, +0.125f,0.96875f, +0.132813f,0.96875f, +0.140625f,0.96875f, +0.148438f,0.96875f, +0.15625f,0.96875f, +0.164063f,0.96875f, +0.171875f,0.96875f, +0.179688f,0.96875f, +0.1875f,0.96875f, +0.195313f,0.96875f, +0.203125f,0.96875f, +0.210938f,0.96875f, +0.21875f,0.96875f, +0.226563f,0.96875f, +0.234375f,0.96875f, +0.242188f,0.96875f, +0.25f,0.96875f, +0.257813f,0.96875f, +0.265625f,0.96875f, +0.273438f,0.96875f, +0.28125f,0.96875f, +0.289063f,0.96875f, +0.296875f,0.96875f, +0.304688f,0.96875f, +0.3125f,0.96875f, +0.320313f,0.96875f, +0.328125f,0.96875f, +0.335938f,0.96875f, +0.34375f,0.96875f, +0.351563f,0.96875f, +0.359375f,0.96875f, +0.367188f,0.96875f, +0.375f,0.96875f, +0.382813f,0.96875f, +0.390625f,0.96875f, +0.398438f,0.96875f, +0.40625f,0.96875f, +0.414063f,0.96875f, +0.421875f,0.96875f, +0.429688f,0.96875f, +0.4375f,0.96875f, +0.445313f,0.96875f, +0.453125f,0.96875f, +0.460938f,0.96875f, +0.46875f,0.96875f, +0.476563f,0.96875f, +0.484375f,0.96875f, +0.492188f,0.96875f, +0.5f,0.96875f, +0.507813f,0.96875f, +0.0f,0.976563f, +0.0078125f,0.976563f, +0.015625f,0.976563f, +0.0234375f,0.976563f, +0.03125f,0.976563f, +0.0390625f,0.976563f, +0.046875f,0.976563f, +0.0546875f,0.976563f, +0.0625f,0.976563f, +0.0703125f,0.976563f, +0.078125f,0.976563f, +0.0859375f,0.976563f, +0.09375f,0.976563f, +0.101563f,0.976563f, +0.109375f,0.976563f, +0.117188f,0.976563f, +0.125f,0.976563f, +0.132813f,0.976563f, +0.140625f,0.976563f, +0.148438f,0.976563f, +0.15625f,0.976563f, +0.164063f,0.976563f, +0.171875f,0.976563f, +0.179688f,0.976563f, +0.1875f,0.976563f, +0.195313f,0.976563f, +0.203125f,0.976563f, +0.210938f,0.976563f, +0.21875f,0.976563f, +0.226563f,0.976563f, +0.234375f,0.976563f, +0.242188f,0.976563f, +0.25f,0.976563f, +0.257813f,0.976563f, +0.265625f,0.976563f, +0.273438f,0.976563f, +0.28125f,0.976563f, +0.289063f,0.976563f, +0.296875f,0.976563f, +0.304688f,0.976563f, +0.3125f,0.976563f, +0.320313f,0.976563f, +0.328125f,0.976563f, +0.335938f,0.976563f, +0.34375f,0.976563f, +0.351563f,0.976563f, +0.359375f,0.976563f, +0.367188f,0.976563f, +0.375f,0.976563f, +0.382813f,0.976563f, +0.390625f,0.976563f, +0.398438f,0.976563f, +0.40625f,0.976563f, +0.414063f,0.976563f, +0.421875f,0.976563f, +0.429688f,0.976563f, +0.4375f,0.976563f, +0.445313f,0.976563f, +0.453125f,0.976563f, +0.460938f,0.976563f, +0.46875f,0.976563f, +0.476563f,0.976563f, +0.484375f,0.976563f, +0.492188f,0.976563f, +0.5f,0.976563f, +0.507813f,0.976563f, +0.0f,0.984375f, +0.0078125f,0.984375f, +0.015625f,0.984375f, +0.0234375f,0.984375f, +0.03125f,0.984375f, +0.0390625f,0.984375f, +0.046875f,0.984375f, +0.0546875f,0.984375f, +0.0625f,0.984375f, +0.0703125f,0.984375f, +0.078125f,0.984375f, +0.0859375f,0.984375f, +0.09375f,0.984375f, +0.101563f,0.984375f, +0.109375f,0.984375f, +0.117188f,0.984375f, +0.125f,0.984375f, +0.132813f,0.984375f, +0.140625f,0.984375f, +0.148438f,0.984375f, +0.15625f,0.984375f, +0.164063f,0.984375f, +0.171875f,0.984375f, +0.179688f,0.984375f, +0.1875f,0.984375f, +0.195313f,0.984375f, +0.203125f,0.984375f, +0.210938f,0.984375f, +0.21875f,0.984375f, +0.226563f,0.984375f, +0.234375f,0.984375f, +0.242188f,0.984375f, +0.25f,0.984375f, +0.257813f,0.984375f, +0.265625f,0.984375f, +0.273438f,0.984375f, +0.28125f,0.984375f, +0.289063f,0.984375f, +0.296875f,0.984375f, +0.304688f,0.984375f, +0.3125f,0.984375f, +0.320313f,0.984375f, +0.328125f,0.984375f, +0.335938f,0.984375f, +0.34375f,0.984375f, +0.351563f,0.984375f, +0.359375f,0.984375f, +0.367188f,0.984375f, +0.375f,0.984375f, +0.382813f,0.984375f, +0.390625f,0.984375f, +0.398438f,0.984375f, +0.40625f,0.984375f, +0.414063f,0.984375f, +0.421875f,0.984375f, +0.429688f,0.984375f, +0.4375f,0.984375f, +0.445313f,0.984375f, +0.453125f,0.984375f, +0.460938f,0.984375f, +0.46875f,0.984375f, +0.476563f,0.984375f, +0.484375f,0.984375f, +0.492188f,0.984375f, +0.5f,0.984375f, +0.507813f,0.984375f, +0.0f,0.992188f, +0.0078125f,0.992188f, +0.015625f,0.992188f, +0.0234375f,0.992188f, +0.03125f,0.992188f, +0.0390625f,0.992188f, +0.046875f,0.992188f, +0.0546875f,0.992188f, +0.0625f,0.992188f, +0.0703125f,0.992188f, +0.078125f,0.992188f, +0.0859375f,0.992188f, +0.09375f,0.992188f, +0.101563f,0.992188f, +0.109375f,0.992188f, +0.117188f,0.992188f, +0.125f,0.992188f, +0.132813f,0.992188f, +0.140625f,0.992188f, +0.148438f,0.992188f, +0.15625f,0.992188f, +0.164063f,0.992188f, +0.171875f,0.992188f, +0.179688f,0.992188f, +0.1875f,0.992188f, +0.195313f,0.992188f, +0.203125f,0.992188f, +0.210938f,0.992188f, +0.21875f,0.992188f, +0.226563f,0.992188f, +0.234375f,0.992188f, +0.242188f,0.992188f, +0.25f,0.992188f, +0.257813f,0.992188f, +0.265625f,0.992188f, +0.273438f,0.992188f, +0.28125f,0.992188f, +0.289063f,0.992188f, +0.296875f,0.992188f, +0.304688f,0.992188f, +0.3125f,0.992188f, +0.320313f,0.992188f, +0.328125f,0.992188f, +0.335938f,0.992188f, +0.34375f,0.992188f, +0.351563f,0.992188f, +0.359375f,0.992188f, +0.367188f,0.992188f, +0.375f,0.992188f, +0.382813f,0.992188f, +0.390625f,0.992188f, +0.398438f,0.992188f, +0.40625f,0.992188f, +0.414063f,0.992188f, +0.421875f,0.992188f, +0.429688f,0.992188f, +0.4375f,0.992188f, +0.445313f,0.992188f, +0.453125f,0.992188f, +0.460938f,0.992188f, +0.46875f,0.992188f, +0.476563f,0.992188f, +0.484375f,0.992188f, +0.492188f,0.992188f, +0.5f,0.992188f, +0.507813f,0.992188f, +0.0f,1.0f, +0.0078125f,1.0f, +0.015625f,1.0f, +0.0234375f,1.0f, +0.03125f,1.0f, +0.0390625f,1.0f, +0.046875f,1.0f, +0.0546875f,1.0f, +0.0625f,1.0f, +0.0703125f,1.0f, +0.078125f,1.0f, +0.0859375f,1.0f, +0.09375f,1.0f, +0.101563f,1.0f, +0.109375f,1.0f, +0.117188f,1.0f, +0.125f,1.0f, +0.132813f,1.0f, +0.140625f,1.0f, +0.148438f,1.0f, +0.15625f,1.0f, +0.164063f,1.0f, +0.171875f,1.0f, +0.179688f,1.0f, +0.1875f,1.0f, +0.195313f,1.0f, +0.203125f,1.0f, +0.210938f,1.0f, +0.21875f,1.0f, +0.226563f,1.0f, +0.234375f,1.0f, +0.242188f,1.0f, +0.25f,1.0f, +0.257813f,1.0f, +0.265625f,1.0f, +0.273438f,1.0f, +0.28125f,1.0f, +0.289063f,1.0f, +0.296875f,1.0f, +0.304688f,1.0f, +0.3125f,1.0f, +0.320313f,1.0f, +0.328125f,1.0f, +0.335938f,1.0f, +0.34375f,1.0f, +0.351563f,1.0f, +0.359375f,1.0f, +0.367188f,1.0f, +0.375f,1.0f, +0.382813f,1.0f, +0.390625f,1.0f, +0.398438f,1.0f, +0.40625f,1.0f, +0.414063f,1.0f, +0.421875f,1.0f, +0.429688f,1.0f, +0.4375f,1.0f, +0.445313f,1.0f, +0.453125f,1.0f, +0.460938f,1.0f, +0.46875f,1.0f, +0.476563f,1.0f, +0.484375f,1.0f, +0.492188f,1.0f, +0.5f,1.0f, +0.507813f,1.0f, +}; + +unsigned short Landscape08Idx[] = { +0,1,2, +3,2,1, +2,3,4, +5,4,3, +4,5,6, +7,6,5, +6,7,8, +9,8,7, +8,9,10, +11,10,9, +10,11,12, +13,12,11, +12,13,14, +15,14,13, +14,15,16, +17,16,15, +16,17,18, +19,18,17, +18,19,20, +21,20,19, +20,21,22, +23,22,21, +22,23,24, +25,24,23, +24,25,26, +27,26,25, +26,27,28, +29,28,27, +28,29,30, +31,30,29, +30,31,32, +33,32,31, +32,33,34, +35,34,33, +34,35,36, +37,36,35, +36,37,38, +39,38,37, +38,39,40, +41,40,39, +40,41,42, +43,42,41, +42,43,44, +45,44,43, +44,45,46, +47,46,45, +46,47,48, +49,48,47, +48,49,50, +51,50,49, +50,51,52, +53,52,51, +52,53,54, +55,54,53, +54,55,56, +57,56,55, +56,57,58, +59,58,57, +58,59,60, +61,60,59, +60,61,62, +63,62,61, +62,63,64, +65,64,63, +64,65,66, +67,66,65, +66,67,68, +69,68,67, +68,69,70, +71,70,69, +70,71,72, +73,72,71, +72,73,74, +75,74,73, +74,75,76, +77,76,75, +76,77,78, +79,78,77, +78,79,80, +81,80,79, +80,81,82, +83,82,81, +82,83,84, +85,84,83, +84,85,86, +87,86,85, +86,87,88, +89,88,87, +88,89,90, +91,90,89, +90,91,92, +93,92,91, +92,93,94, +95,94,93, +94,95,96, +97,96,95, +96,97,98, +99,98,97, +98,99,100, +101,100,99, +100,101,102, +103,102,101, +102,103,104, +105,104,103, +104,105,106, +107,106,105, +106,107,108, +109,108,107, +108,109,110, +111,110,109, +110,111,112, +113,112,111, +112,113,114, +115,114,113, +114,115,116, +117,116,115, +116,117,118, +119,118,117, +118,119,120, +121,120,119, +120,121,122, +123,122,121, +122,123,124, +125,124,123, +124,125,126, +127,126,125, +126,127,128, +129,128,127, +128,129,130, +131,130,129, +132,0,133, +2,133,0, +133,2,134, +4,134,2, +134,4,135, +6,135,4, +135,6,136, +8,136,6, +136,8,137, +10,137,8, +137,10,138, +12,138,10, +138,12,139, +14,139,12, +139,14,140, +16,140,14, +140,16,141, +18,141,16, +141,18,142, +20,142,18, +142,20,143, +22,143,20, +143,22,144, +24,144,22, +144,24,145, +26,145,24, +145,26,146, +28,146,26, +146,28,147, +30,147,28, +147,30,148, +32,148,30, +148,32,149, +34,149,32, +149,34,150, +36,150,34, +150,36,151, +38,151,36, +151,38,152, +40,152,38, +152,40,153, +42,153,40, +153,42,154, +44,154,42, +154,44,155, +46,155,44, +155,46,156, +48,156,46, +156,48,157, +50,157,48, +157,50,158, +52,158,50, +158,52,159, +54,159,52, +159,54,160, +56,160,54, +160,56,161, +58,161,56, +161,58,162, +60,162,58, +162,60,163, +62,163,60, +163,62,164, +64,164,62, +164,64,165, +66,165,64, +165,66,166, +68,166,66, +166,68,167, +70,167,68, +167,70,168, +72,168,70, +168,72,169, +74,169,72, +169,74,170, +76,170,74, +170,76,171, +78,171,76, +171,78,172, +80,172,78, +172,80,173, +82,173,80, +173,82,174, +84,174,82, +174,84,175, +86,175,84, +175,86,176, +88,176,86, +176,88,177, +90,177,88, +177,90,178, +92,178,90, +178,92,179, +94,179,92, +179,94,180, +96,180,94, +180,96,181, +98,181,96, +181,98,182, +100,182,98, +182,100,183, +102,183,100, +183,102,184, +104,184,102, +184,104,185, +106,185,104, +185,106,186, +108,186,106, +186,108,187, +110,187,108, +187,110,188, +112,188,110, +188,112,189, +114,189,112, +189,114,190, +116,190,114, +190,116,191, +118,191,116, +191,118,192, +120,192,118, +192,120,193, +122,193,120, +193,122,194, +124,194,122, +194,124,195, +126,195,124, +195,126,196, +128,196,126, +196,128,197, +130,197,128, +198,132,199, +133,199,132, +199,133,200, +134,200,133, +200,134,201, +135,201,134, +201,135,202, +136,202,135, +202,136,203, +137,203,136, +203,137,204, +138,204,137, +204,138,205, +139,205,138, +205,139,206, +140,206,139, +206,140,207, +141,207,140, +207,141,208, +142,208,141, +208,142,209, +143,209,142, +209,143,210, +144,210,143, +210,144,211, +145,211,144, +211,145,212, +146,212,145, +212,146,213, +147,213,146, +213,147,214, +148,214,147, +214,148,215, +149,215,148, +215,149,216, +150,216,149, +216,150,217, +151,217,150, +217,151,218, +152,218,151, +218,152,219, +153,219,152, +219,153,220, +154,220,153, +220,154,221, +155,221,154, +221,155,222, +156,222,155, +222,156,223, +157,223,156, +223,157,224, +158,224,157, +224,158,225, +159,225,158, +225,159,226, +160,226,159, +226,160,227, +161,227,160, +227,161,228, +162,228,161, +228,162,229, +163,229,162, +229,163,230, +164,230,163, +230,164,231, +165,231,164, +231,165,232, +166,232,165, +232,166,233, +167,233,166, +233,167,234, +168,234,167, +234,168,235, +169,235,168, +235,169,236, +170,236,169, +236,170,237, +171,237,170, +237,171,238, +172,238,171, +238,172,239, +173,239,172, +239,173,240, +174,240,173, +240,174,241, +175,241,174, +241,175,242, +176,242,175, +242,176,243, +177,243,176, +243,177,244, +178,244,177, +244,178,245, +179,245,178, +245,179,246, +180,246,179, +246,180,247, +181,247,180, +247,181,248, +182,248,181, +248,182,249, +183,249,182, +249,183,250, +184,250,183, +250,184,251, +185,251,184, +251,185,252, +186,252,185, +252,186,253, +187,253,186, +253,187,254, +188,254,187, +254,188,255, +189,255,188, +255,189,256, +190,256,189, +256,190,257, +191,257,190, +257,191,258, +192,258,191, +258,192,259, +193,259,192, +259,193,260, +194,260,193, +260,194,261, +195,261,194, +261,195,262, +196,262,195, +262,196,263, +197,263,196, +264,198,265, +199,265,198, +265,199,266, +200,266,199, +266,200,267, +201,267,200, +267,201,268, +202,268,201, +268,202,269, +203,269,202, +269,203,270, +204,270,203, +270,204,271, +205,271,204, +271,205,272, +206,272,205, +272,206,273, +207,273,206, +273,207,274, +208,274,207, +274,208,275, +209,275,208, +275,209,276, +210,276,209, +276,210,277, +211,277,210, +277,211,278, +212,278,211, +278,212,279, +213,279,212, +279,213,280, +214,280,213, +280,214,281, +215,281,214, +281,215,282, +216,282,215, +282,216,283, +217,283,216, +283,217,284, +218,284,217, +284,218,285, +219,285,218, +285,219,286, +220,286,219, +286,220,287, +221,287,220, +287,221,288, +222,288,221, +288,222,289, +223,289,222, +289,223,290, +224,290,223, +290,224,291, +225,291,224, +291,225,292, +226,292,225, +292,226,293, +227,293,226, +293,227,294, +228,294,227, +294,228,295, +229,295,228, +295,229,296, +230,296,229, +296,230,297, +231,297,230, +297,231,298, +232,298,231, +298,232,299, +233,299,232, +299,233,300, +234,300,233, +300,234,301, +235,301,234, +301,235,302, +236,302,235, +302,236,303, +237,303,236, +303,237,304, +238,304,237, +304,238,305, +239,305,238, +305,239,306, +240,306,239, +306,240,307, +241,307,240, +307,241,308, +242,308,241, +308,242,309, +243,309,242, +309,243,310, +244,310,243, +310,244,311, +245,311,244, +311,245,312, +246,312,245, +312,246,313, +247,313,246, +313,247,314, +248,314,247, +314,248,315, +249,315,248, +315,249,316, +250,316,249, +316,250,317, +251,317,250, +317,251,318, +252,318,251, +318,252,319, +253,319,252, +319,253,320, +254,320,253, +320,254,321, +255,321,254, +321,255,322, +256,322,255, +322,256,323, +257,323,256, +323,257,324, +258,324,257, +324,258,325, +259,325,258, +325,259,326, +260,326,259, +326,260,327, +261,327,260, +327,261,328, +262,328,261, +328,262,329, +263,329,262, +330,264,331, +265,331,264, +331,265,332, +266,332,265, +332,266,333, +267,333,266, +333,267,334, +268,334,267, +334,268,335, +269,335,268, +335,269,336, +270,336,269, +336,270,337, +271,337,270, +337,271,338, +272,338,271, +338,272,339, +273,339,272, +339,273,340, +274,340,273, +340,274,341, +275,341,274, +341,275,342, +276,342,275, +342,276,343, +277,343,276, +343,277,344, +278,344,277, +344,278,345, +279,345,278, +345,279,346, +280,346,279, +346,280,347, +281,347,280, +347,281,348, +282,348,281, +348,282,349, +283,349,282, +349,283,350, +284,350,283, +350,284,351, +285,351,284, +351,285,352, +286,352,285, +352,286,353, +287,353,286, +353,287,354, +288,354,287, +354,288,355, +289,355,288, +355,289,356, +290,356,289, +356,290,357, +291,357,290, +357,291,358, +292,358,291, +358,292,359, +293,359,292, +359,293,360, +294,360,293, +360,294,361, +295,361,294, +361,295,362, +296,362,295, +362,296,363, +297,363,296, +363,297,364, +298,364,297, +364,298,365, +299,365,298, +365,299,366, +300,366,299, +366,300,367, +301,367,300, +367,301,368, +302,368,301, +368,302,369, +303,369,302, +369,303,370, +304,370,303, +370,304,371, +305,371,304, +371,305,372, +306,372,305, +372,306,373, +307,373,306, +373,307,374, +308,374,307, +374,308,375, +309,375,308, +375,309,376, +310,376,309, +376,310,377, +311,377,310, +377,311,378, +312,378,311, +378,312,379, +313,379,312, +379,313,380, +314,380,313, +380,314,381, +315,381,314, +381,315,382, +316,382,315, +382,316,383, +317,383,316, +383,317,384, +318,384,317, +384,318,385, +319,385,318, +385,319,386, +320,386,319, +386,320,387, +321,387,320, +387,321,388, +322,388,321, +388,322,389, +323,389,322, +389,323,390, +324,390,323, +390,324,391, +325,391,324, +391,325,392, +326,392,325, +392,326,393, +327,393,326, +393,327,394, +328,394,327, +394,328,395, +329,395,328, +396,330,397, +331,397,330, +397,331,398, +332,398,331, +398,332,399, +333,399,332, +399,333,400, +334,400,333, +400,334,401, +335,401,334, +401,335,402, +336,402,335, +402,336,403, +337,403,336, +403,337,404, +338,404,337, +404,338,405, +339,405,338, +405,339,406, +340,406,339, +406,340,407, +341,407,340, +407,341,408, +342,408,341, +408,342,409, +343,409,342, +409,343,410, +344,410,343, +410,344,411, +345,411,344, +411,345,412, +346,412,345, +412,346,413, +347,413,346, +413,347,414, +348,414,347, +414,348,415, +349,415,348, +415,349,416, +350,416,349, +416,350,417, +351,417,350, +417,351,418, +352,418,351, +418,352,419, +353,419,352, +419,353,420, +354,420,353, +420,354,421, +355,421,354, +421,355,422, +356,422,355, +422,356,423, +357,423,356, +423,357,424, +358,424,357, +424,358,425, +359,425,358, +425,359,426, +360,426,359, +426,360,427, +361,427,360, +427,361,428, +362,428,361, +428,362,429, +363,429,362, +429,363,430, +364,430,363, +430,364,431, +365,431,364, +431,365,432, +366,432,365, +432,366,433, +367,433,366, +433,367,434, +368,434,367, +434,368,435, +369,435,368, +435,369,436, +370,436,369, +436,370,437, +371,437,370, +437,371,438, +372,438,371, +438,372,439, +373,439,372, +439,373,440, +374,440,373, +440,374,441, +375,441,374, +441,375,442, +376,442,375, +442,376,443, +377,443,376, +443,377,444, +378,444,377, +444,378,445, +379,445,378, +445,379,446, +380,446,379, +446,380,447, +381,447,380, +447,381,448, +382,448,381, +448,382,449, +383,449,382, +449,383,450, +384,450,383, +450,384,451, +385,451,384, +451,385,452, +386,452,385, +452,386,453, +387,453,386, +453,387,454, +388,454,387, +454,388,455, +389,455,388, +455,389,456, +390,456,389, +456,390,457, +391,457,390, +457,391,458, +392,458,391, +458,392,459, +393,459,392, +459,393,460, +394,460,393, +460,394,461, +395,461,394, +462,396,463, +397,463,396, +463,397,464, +398,464,397, +464,398,465, +399,465,398, +465,399,466, +400,466,399, +466,400,467, +401,467,400, +467,401,468, +402,468,401, +468,402,469, +403,469,402, +469,403,470, +404,470,403, +470,404,471, +405,471,404, +471,405,472, +406,472,405, +472,406,473, +407,473,406, +473,407,474, +408,474,407, +474,408,475, +409,475,408, +475,409,476, +410,476,409, +476,410,477, +411,477,410, +477,411,478, +412,478,411, +478,412,479, +413,479,412, +479,413,480, +414,480,413, +480,414,481, +415,481,414, +481,415,482, +416,482,415, +482,416,483, +417,483,416, +483,417,484, +418,484,417, +484,418,485, +419,485,418, +485,419,486, +420,486,419, +486,420,487, +421,487,420, +487,421,488, +422,488,421, +488,422,489, +423,489,422, +489,423,490, +424,490,423, +490,424,491, +425,491,424, +491,425,492, +426,492,425, +492,426,493, +427,493,426, +493,427,494, +428,494,427, +494,428,495, +429,495,428, +495,429,496, +430,496,429, +496,430,497, +431,497,430, +497,431,498, +432,498,431, +498,432,499, +433,499,432, +499,433,500, +434,500,433, +500,434,501, +435,501,434, +501,435,502, +436,502,435, +502,436,503, +437,503,436, +503,437,504, +438,504,437, +504,438,505, +439,505,438, +505,439,506, +440,506,439, +506,440,507, +441,507,440, +507,441,508, +442,508,441, +508,442,509, +443,509,442, +509,443,510, +444,510,443, +510,444,511, +445,511,444, +511,445,512, +446,512,445, +512,446,513, +447,513,446, +513,447,514, +448,514,447, +514,448,515, +449,515,448, +515,449,516, +450,516,449, +516,450,517, +451,517,450, +517,451,518, +452,518,451, +518,452,519, +453,519,452, +519,453,520, +454,520,453, +520,454,521, +455,521,454, +521,455,522, +456,522,455, +522,456,523, +457,523,456, +523,457,524, +458,524,457, +524,458,525, +459,525,458, +525,459,526, +460,526,459, +526,460,527, +461,527,460, +528,462,529, +463,529,462, +529,463,530, +464,530,463, +530,464,531, +465,531,464, +531,465,532, +466,532,465, +532,466,533, +467,533,466, +533,467,534, +468,534,467, +534,468,535, +469,535,468, +535,469,536, +470,536,469, +536,470,537, +471,537,470, +537,471,538, +472,538,471, +538,472,539, +473,539,472, +539,473,540, +474,540,473, +540,474,541, +475,541,474, +541,475,542, +476,542,475, +542,476,543, +477,543,476, +543,477,544, +478,544,477, +544,478,545, +479,545,478, +545,479,546, +480,546,479, +546,480,547, +481,547,480, +547,481,548, +482,548,481, +548,482,549, +483,549,482, +549,483,550, +484,550,483, +550,484,551, +485,551,484, +551,485,552, +486,552,485, +552,486,553, +487,553,486, +553,487,554, +488,554,487, +554,488,555, +489,555,488, +555,489,556, +490,556,489, +556,490,557, +491,557,490, +557,491,558, +492,558,491, +558,492,559, +493,559,492, +559,493,560, +494,560,493, +560,494,561, +495,561,494, +561,495,562, +496,562,495, +562,496,563, +497,563,496, +563,497,564, +498,564,497, +564,498,565, +499,565,498, +565,499,566, +500,566,499, +566,500,567, +501,567,500, +567,501,568, +502,568,501, +568,502,569, +503,569,502, +569,503,570, +504,570,503, +570,504,571, +505,571,504, +571,505,572, +506,572,505, +572,506,573, +507,573,506, +573,507,574, +508,574,507, +574,508,575, +509,575,508, +575,509,576, +510,576,509, +576,510,577, +511,577,510, +577,511,578, +512,578,511, +578,512,579, +513,579,512, +579,513,580, +514,580,513, +580,514,581, +515,581,514, +581,515,582, +516,582,515, +582,516,583, +517,583,516, +583,517,584, +518,584,517, +584,518,585, +519,585,518, +585,519,586, +520,586,519, +586,520,587, +521,587,520, +587,521,588, +522,588,521, +588,522,589, +523,589,522, +589,523,590, +524,590,523, +590,524,591, +525,591,524, +591,525,592, +526,592,525, +592,526,593, +527,593,526, +594,528,595, +529,595,528, +595,529,596, +530,596,529, +596,530,597, +531,597,530, +597,531,598, +532,598,531, +598,532,599, +533,599,532, +599,533,600, +534,600,533, +600,534,601, +535,601,534, +601,535,602, +536,602,535, +602,536,603, +537,603,536, +603,537,604, +538,604,537, +604,538,605, +539,605,538, +605,539,606, +540,606,539, +606,540,607, +541,607,540, +607,541,608, +542,608,541, +608,542,609, +543,609,542, +609,543,610, +544,610,543, +610,544,611, +545,611,544, +611,545,612, +546,612,545, +612,546,613, +547,613,546, +613,547,614, +548,614,547, +614,548,615, +549,615,548, +615,549,616, +550,616,549, +616,550,617, +551,617,550, +617,551,618, +552,618,551, +618,552,619, +553,619,552, +619,553,620, +554,620,553, +620,554,621, +555,621,554, +621,555,622, +556,622,555, +622,556,623, +557,623,556, +623,557,624, +558,624,557, +624,558,625, +559,625,558, +625,559,626, +560,626,559, +626,560,627, +561,627,560, +627,561,628, +562,628,561, +628,562,629, +563,629,562, +629,563,630, +564,630,563, +630,564,631, +565,631,564, +631,565,632, +566,632,565, +632,566,633, +567,633,566, +633,567,634, +568,634,567, +634,568,635, +569,635,568, +635,569,636, +570,636,569, +636,570,637, +571,637,570, +637,571,638, +572,638,571, +638,572,639, +573,639,572, +639,573,640, +574,640,573, +640,574,641, +575,641,574, +641,575,642, +576,642,575, +642,576,643, +577,643,576, +643,577,644, +578,644,577, +644,578,645, +579,645,578, +645,579,646, +580,646,579, +646,580,647, +581,647,580, +647,581,648, +582,648,581, +648,582,649, +583,649,582, +649,583,650, +584,650,583, +650,584,651, +585,651,584, +651,585,652, +586,652,585, +652,586,653, +587,653,586, +653,587,654, +588,654,587, +654,588,655, +589,655,588, +655,589,656, +590,656,589, +656,590,657, +591,657,590, +657,591,658, +592,658,591, +658,592,659, +593,659,592, +660,594,661, +595,661,594, +661,595,662, +596,662,595, +662,596,663, +597,663,596, +663,597,664, +598,664,597, +664,598,665, +599,665,598, +665,599,666, +600,666,599, +666,600,667, +601,667,600, +667,601,668, +602,668,601, +668,602,669, +603,669,602, +669,603,670, +604,670,603, +670,604,671, +605,671,604, +671,605,672, +606,672,605, +672,606,673, +607,673,606, +673,607,674, +608,674,607, +674,608,675, +609,675,608, +675,609,676, +610,676,609, +676,610,677, +611,677,610, +677,611,678, +612,678,611, +678,612,679, +613,679,612, +679,613,680, +614,680,613, +680,614,681, +615,681,614, +681,615,682, +616,682,615, +682,616,683, +617,683,616, +683,617,684, +618,684,617, +684,618,685, +619,685,618, +685,619,686, +620,686,619, +686,620,687, +621,687,620, +687,621,688, +622,688,621, +688,622,689, +623,689,622, +689,623,690, +624,690,623, +690,624,691, +625,691,624, +691,625,692, +626,692,625, +692,626,693, +627,693,626, +693,627,694, +628,694,627, +694,628,695, +629,695,628, +695,629,696, +630,696,629, +696,630,697, +631,697,630, +697,631,698, +632,698,631, +698,632,699, +633,699,632, +699,633,700, +634,700,633, +700,634,701, +635,701,634, +701,635,702, +636,702,635, +702,636,703, +637,703,636, +703,637,704, +638,704,637, +704,638,705, +639,705,638, +705,639,706, +640,706,639, +706,640,707, +641,707,640, +707,641,708, +642,708,641, +708,642,709, +643,709,642, +709,643,710, +644,710,643, +710,644,711, +645,711,644, +711,645,712, +646,712,645, +712,646,713, +647,713,646, +713,647,714, +648,714,647, +714,648,715, +649,715,648, +715,649,716, +650,716,649, +716,650,717, +651,717,650, +717,651,718, +652,718,651, +718,652,719, +653,719,652, +719,653,720, +654,720,653, +720,654,721, +655,721,654, +721,655,722, +656,722,655, +722,656,723, +657,723,656, +723,657,724, +658,724,657, +724,658,725, +659,725,658, +726,660,727, +661,727,660, +727,661,728, +662,728,661, +728,662,729, +663,729,662, +729,663,730, +664,730,663, +730,664,731, +665,731,664, +731,665,732, +666,732,665, +732,666,733, +667,733,666, +733,667,734, +668,734,667, +734,668,735, +669,735,668, +735,669,736, +670,736,669, +736,670,737, +671,737,670, +737,671,738, +672,738,671, +738,672,739, +673,739,672, +739,673,740, +674,740,673, +740,674,741, +675,741,674, +741,675,742, +676,742,675, +742,676,743, +677,743,676, +743,677,744, +678,744,677, +744,678,745, +679,745,678, +745,679,746, +680,746,679, +746,680,747, +681,747,680, +747,681,748, +682,748,681, +748,682,749, +683,749,682, +749,683,750, +684,750,683, +750,684,751, +685,751,684, +751,685,752, +686,752,685, +752,686,753, +687,753,686, +753,687,754, +688,754,687, +754,688,755, +689,755,688, +755,689,756, +690,756,689, +756,690,757, +691,757,690, +757,691,758, +692,758,691, +758,692,759, +693,759,692, +759,693,760, +694,760,693, +760,694,761, +695,761,694, +761,695,762, +696,762,695, +762,696,763, +697,763,696, +763,697,764, +698,764,697, +764,698,765, +699,765,698, +765,699,766, +700,766,699, +766,700,767, +701,767,700, +767,701,768, +702,768,701, +768,702,769, +703,769,702, +769,703,770, +704,770,703, +770,704,771, +705,771,704, +771,705,772, +706,772,705, +772,706,773, +707,773,706, +773,707,774, +708,774,707, +774,708,775, +709,775,708, +775,709,776, +710,776,709, +776,710,777, +711,777,710, +777,711,778, +712,778,711, +778,712,779, +713,779,712, +779,713,780, +714,780,713, +780,714,781, +715,781,714, +781,715,782, +716,782,715, +782,716,783, +717,783,716, +783,717,784, +718,784,717, +784,718,785, +719,785,718, +785,719,786, +720,786,719, +786,720,787, +721,787,720, +787,721,788, +722,788,721, +788,722,789, +723,789,722, +789,723,790, +724,790,723, +790,724,791, +725,791,724, +792,726,793, +727,793,726, +793,727,794, +728,794,727, +794,728,795, +729,795,728, +795,729,796, +730,796,729, +796,730,797, +731,797,730, +797,731,798, +732,798,731, +798,732,799, +733,799,732, +799,733,800, +734,800,733, +800,734,801, +735,801,734, +801,735,802, +736,802,735, +802,736,803, +737,803,736, +803,737,804, +738,804,737, +804,738,805, +739,805,738, +805,739,806, +740,806,739, +806,740,807, +741,807,740, +807,741,808, +742,808,741, +808,742,809, +743,809,742, +809,743,810, +744,810,743, +810,744,811, +745,811,744, +811,745,812, +746,812,745, +812,746,813, +747,813,746, +813,747,814, +748,814,747, +814,748,815, +749,815,748, +815,749,816, +750,816,749, +816,750,817, +751,817,750, +817,751,818, +752,818,751, +818,752,819, +753,819,752, +819,753,820, +754,820,753, +820,754,821, +755,821,754, +821,755,822, +756,822,755, +822,756,823, +757,823,756, +823,757,824, +758,824,757, +824,758,825, +759,825,758, +825,759,826, +760,826,759, +826,760,827, +761,827,760, +827,761,828, +762,828,761, +828,762,829, +763,829,762, +829,763,830, +764,830,763, +830,764,831, +765,831,764, +831,765,832, +766,832,765, +832,766,833, +767,833,766, +833,767,834, +768,834,767, +834,768,835, +769,835,768, +835,769,836, +770,836,769, +836,770,837, +771,837,770, +837,771,838, +772,838,771, +838,772,839, +773,839,772, +839,773,840, +774,840,773, +840,774,841, +775,841,774, +841,775,842, +776,842,775, +842,776,843, +777,843,776, +843,777,844, +778,844,777, +844,778,845, +779,845,778, +845,779,846, +780,846,779, +846,780,847, +781,847,780, +847,781,848, +782,848,781, +848,782,849, +783,849,782, +849,783,850, +784,850,783, +850,784,851, +785,851,784, +851,785,852, +786,852,785, +852,786,853, +787,853,786, +853,787,854, +788,854,787, +854,788,855, +789,855,788, +855,789,856, +790,856,789, +856,790,857, +791,857,790, +858,792,859, +793,859,792, +859,793,860, +794,860,793, +860,794,861, +795,861,794, +861,795,862, +796,862,795, +862,796,863, +797,863,796, +863,797,864, +798,864,797, +864,798,865, +799,865,798, +865,799,866, +800,866,799, +866,800,867, +801,867,800, +867,801,868, +802,868,801, +868,802,869, +803,869,802, +869,803,870, +804,870,803, +870,804,871, +805,871,804, +871,805,872, +806,872,805, +872,806,873, +807,873,806, +873,807,874, +808,874,807, +874,808,875, +809,875,808, +875,809,876, +810,876,809, +876,810,877, +811,877,810, +877,811,878, +812,878,811, +878,812,879, +813,879,812, +879,813,880, +814,880,813, +880,814,881, +815,881,814, +881,815,882, +816,882,815, +882,816,883, +817,883,816, +883,817,884, +818,884,817, +884,818,885, +819,885,818, +885,819,886, +820,886,819, +886,820,887, +821,887,820, +887,821,888, +822,888,821, +888,822,889, +823,889,822, +889,823,890, +824,890,823, +890,824,891, +825,891,824, +891,825,892, +826,892,825, +892,826,893, +827,893,826, +893,827,894, +828,894,827, +894,828,895, +829,895,828, +895,829,896, +830,896,829, +896,830,897, +831,897,830, +897,831,898, +832,898,831, +898,832,899, +833,899,832, +899,833,900, +834,900,833, +900,834,901, +835,901,834, +901,835,902, +836,902,835, +902,836,903, +837,903,836, +903,837,904, +838,904,837, +904,838,905, +839,905,838, +905,839,906, +840,906,839, +906,840,907, +841,907,840, +907,841,908, +842,908,841, +908,842,909, +843,909,842, +909,843,910, +844,910,843, +910,844,911, +845,911,844, +911,845,912, +846,912,845, +912,846,913, +847,913,846, +913,847,914, +848,914,847, +914,848,915, +849,915,848, +915,849,916, +850,916,849, +916,850,917, +851,917,850, +917,851,918, +852,918,851, +918,852,919, +853,919,852, +919,853,920, +854,920,853, +920,854,921, +855,921,854, +921,855,922, +856,922,855, +922,856,923, +857,923,856, +924,858,925, +859,925,858, +925,859,926, +860,926,859, +926,860,927, +861,927,860, +927,861,928, +862,928,861, +928,862,929, +863,929,862, +929,863,930, +864,930,863, +930,864,931, +865,931,864, +931,865,932, +866,932,865, +932,866,933, +867,933,866, +933,867,934, +868,934,867, +934,868,935, +869,935,868, +935,869,936, +870,936,869, +936,870,937, +871,937,870, +937,871,938, +872,938,871, +938,872,939, +873,939,872, +939,873,940, +874,940,873, +940,874,941, +875,941,874, +941,875,942, +876,942,875, +942,876,943, +877,943,876, +943,877,944, +878,944,877, +944,878,945, +879,945,878, +945,879,946, +880,946,879, +946,880,947, +881,947,880, +947,881,948, +882,948,881, +948,882,949, +883,949,882, +949,883,950, +884,950,883, +950,884,951, +885,951,884, +951,885,952, +886,952,885, +952,886,953, +887,953,886, +953,887,954, +888,954,887, +954,888,955, +889,955,888, +955,889,956, +890,956,889, +956,890,957, +891,957,890, +957,891,958, +892,958,891, +958,892,959, +893,959,892, +959,893,960, +894,960,893, +960,894,961, +895,961,894, +961,895,962, +896,962,895, +962,896,963, +897,963,896, +963,897,964, +898,964,897, +964,898,965, +899,965,898, +965,899,966, +900,966,899, +966,900,967, +901,967,900, +967,901,968, +902,968,901, +968,902,969, +903,969,902, +969,903,970, +904,970,903, +970,904,971, +905,971,904, +971,905,972, +906,972,905, +972,906,973, +907,973,906, +973,907,974, +908,974,907, +974,908,975, +909,975,908, +975,909,976, +910,976,909, +976,910,977, +911,977,910, +977,911,978, +912,978,911, +978,912,979, +913,979,912, +979,913,980, +914,980,913, +980,914,981, +915,981,914, +981,915,982, +916,982,915, +982,916,983, +917,983,916, +983,917,984, +918,984,917, +984,918,985, +919,985,918, +985,919,986, +920,986,919, +986,920,987, +921,987,920, +987,921,988, +922,988,921, +988,922,989, +923,989,922, +990,924,991, +925,991,924, +991,925,992, +926,992,925, +992,926,993, +927,993,926, +993,927,994, +928,994,927, +994,928,995, +929,995,928, +995,929,996, +930,996,929, +996,930,997, +931,997,930, +997,931,998, +932,998,931, +998,932,999, +933,999,932, +999,933,1000, +934,1000,933, +1000,934,1001, +935,1001,934, +1001,935,1002, +936,1002,935, +1002,936,1003, +937,1003,936, +1003,937,1004, +938,1004,937, +1004,938,1005, +939,1005,938, +1005,939,1006, +940,1006,939, +1006,940,1007, +941,1007,940, +1007,941,1008, +942,1008,941, +1008,942,1009, +943,1009,942, +1009,943,1010, +944,1010,943, +1010,944,1011, +945,1011,944, +1011,945,1012, +946,1012,945, +1012,946,1013, +947,1013,946, +1013,947,1014, +948,1014,947, +1014,948,1015, +949,1015,948, +1015,949,1016, +950,1016,949, +1016,950,1017, +951,1017,950, +1017,951,1018, +952,1018,951, +1018,952,1019, +953,1019,952, +1019,953,1020, +954,1020,953, +1020,954,1021, +955,1021,954, +1021,955,1022, +956,1022,955, +1022,956,1023, +957,1023,956, +1023,957,1024, +958,1024,957, +1024,958,1025, +959,1025,958, +1025,959,1026, +960,1026,959, +1026,960,1027, +961,1027,960, +1027,961,1028, +962,1028,961, +1028,962,1029, +963,1029,962, +1029,963,1030, +964,1030,963, +1030,964,1031, +965,1031,964, +1031,965,1032, +966,1032,965, +1032,966,1033, +967,1033,966, +1033,967,1034, +968,1034,967, +1034,968,1035, +969,1035,968, +1035,969,1036, +970,1036,969, +1036,970,1037, +971,1037,970, +1037,971,1038, +972,1038,971, +1038,972,1039, +973,1039,972, +1039,973,1040, +974,1040,973, +1040,974,1041, +975,1041,974, +1041,975,1042, +976,1042,975, +1042,976,1043, +977,1043,976, +1043,977,1044, +978,1044,977, +1044,978,1045, +979,1045,978, +1045,979,1046, +980,1046,979, +1046,980,1047, +981,1047,980, +1047,981,1048, +982,1048,981, +1048,982,1049, +983,1049,982, +1049,983,1050, +984,1050,983, +1050,984,1051, +985,1051,984, +1051,985,1052, +986,1052,985, +1052,986,1053, +987,1053,986, +1053,987,1054, +988,1054,987, +1054,988,1055, +989,1055,988, +1056,990,1057, +991,1057,990, +1057,991,1058, +992,1058,991, +1058,992,1059, +993,1059,992, +1059,993,1060, +994,1060,993, +1060,994,1061, +995,1061,994, +1061,995,1062, +996,1062,995, +1062,996,1063, +997,1063,996, +1063,997,1064, +998,1064,997, +1064,998,1065, +999,1065,998, +1065,999,1066, +1000,1066,999, +1066,1000,1067, +1001,1067,1000, +1067,1001,1068, +1002,1068,1001, +1068,1002,1069, +1003,1069,1002, +1069,1003,1070, +1004,1070,1003, +1070,1004,1071, +1005,1071,1004, +1071,1005,1072, +1006,1072,1005, +1072,1006,1073, +1007,1073,1006, +1073,1007,1074, +1008,1074,1007, +1074,1008,1075, +1009,1075,1008, +1075,1009,1076, +1010,1076,1009, +1076,1010,1077, +1011,1077,1010, +1077,1011,1078, +1012,1078,1011, +1078,1012,1079, +1013,1079,1012, +1079,1013,1080, +1014,1080,1013, +1080,1014,1081, +1015,1081,1014, +1081,1015,1082, +1016,1082,1015, +1082,1016,1083, +1017,1083,1016, +1083,1017,1084, +1018,1084,1017, +1084,1018,1085, +1019,1085,1018, +1085,1019,1086, +1020,1086,1019, +1086,1020,1087, +1021,1087,1020, +1087,1021,1088, +1022,1088,1021, +1088,1022,1089, +1023,1089,1022, +1089,1023,1090, +1024,1090,1023, +1090,1024,1091, +1025,1091,1024, +1091,1025,1092, +1026,1092,1025, +1092,1026,1093, +1027,1093,1026, +1093,1027,1094, +1028,1094,1027, +1094,1028,1095, +1029,1095,1028, +1095,1029,1096, +1030,1096,1029, +1096,1030,1097, +1031,1097,1030, +1097,1031,1098, +1032,1098,1031, +1098,1032,1099, +1033,1099,1032, +1099,1033,1100, +1034,1100,1033, +1100,1034,1101, +1035,1101,1034, +1101,1035,1102, +1036,1102,1035, +1102,1036,1103, +1037,1103,1036, +1103,1037,1104, +1038,1104,1037, +1104,1038,1105, +1039,1105,1038, +1105,1039,1106, +1040,1106,1039, +1106,1040,1107, +1041,1107,1040, +1107,1041,1108, +1042,1108,1041, +1108,1042,1109, +1043,1109,1042, +1109,1043,1110, +1044,1110,1043, +1110,1044,1111, +1045,1111,1044, +1111,1045,1112, +1046,1112,1045, +1112,1046,1113, +1047,1113,1046, +1113,1047,1114, +1048,1114,1047, +1114,1048,1115, +1049,1115,1048, +1115,1049,1116, +1050,1116,1049, +1116,1050,1117, +1051,1117,1050, +1117,1051,1118, +1052,1118,1051, +1118,1052,1119, +1053,1119,1052, +1119,1053,1120, +1054,1120,1053, +1120,1054,1121, +1055,1121,1054, +1122,1056,1123, +1057,1123,1056, +1123,1057,1124, +1058,1124,1057, +1124,1058,1125, +1059,1125,1058, +1125,1059,1126, +1060,1126,1059, +1126,1060,1127, +1061,1127,1060, +1127,1061,1128, +1062,1128,1061, +1128,1062,1129, +1063,1129,1062, +1129,1063,1130, +1064,1130,1063, +1130,1064,1131, +1065,1131,1064, +1131,1065,1132, +1066,1132,1065, +1132,1066,1133, +1067,1133,1066, +1133,1067,1134, +1068,1134,1067, +1134,1068,1135, +1069,1135,1068, +1135,1069,1136, +1070,1136,1069, +1136,1070,1137, +1071,1137,1070, +1137,1071,1138, +1072,1138,1071, +1138,1072,1139, +1073,1139,1072, +1139,1073,1140, +1074,1140,1073, +1140,1074,1141, +1075,1141,1074, +1141,1075,1142, +1076,1142,1075, +1142,1076,1143, +1077,1143,1076, +1143,1077,1144, +1078,1144,1077, +1144,1078,1145, +1079,1145,1078, +1145,1079,1146, +1080,1146,1079, +1146,1080,1147, +1081,1147,1080, +1147,1081,1148, +1082,1148,1081, +1148,1082,1149, +1083,1149,1082, +1149,1083,1150, +1084,1150,1083, +1150,1084,1151, +1085,1151,1084, +1151,1085,1152, +1086,1152,1085, +1152,1086,1153, +1087,1153,1086, +1153,1087,1154, +1088,1154,1087, +1154,1088,1155, +1089,1155,1088, +1155,1089,1156, +1090,1156,1089, +1156,1090,1157, +1091,1157,1090, +1157,1091,1158, +1092,1158,1091, +1158,1092,1159, +1093,1159,1092, +1159,1093,1160, +1094,1160,1093, +1160,1094,1161, +1095,1161,1094, +1161,1095,1162, +1096,1162,1095, +1162,1096,1163, +1097,1163,1096, +1163,1097,1164, +1098,1164,1097, +1164,1098,1165, +1099,1165,1098, +1165,1099,1166, +1100,1166,1099, +1166,1100,1167, +1101,1167,1100, +1167,1101,1168, +1102,1168,1101, +1168,1102,1169, +1103,1169,1102, +1169,1103,1170, +1104,1170,1103, +1170,1104,1171, +1105,1171,1104, +1171,1105,1172, +1106,1172,1105, +1172,1106,1173, +1107,1173,1106, +1173,1107,1174, +1108,1174,1107, +1174,1108,1175, +1109,1175,1108, +1175,1109,1176, +1110,1176,1109, +1176,1110,1177, +1111,1177,1110, +1177,1111,1178, +1112,1178,1111, +1178,1112,1179, +1113,1179,1112, +1179,1113,1180, +1114,1180,1113, +1180,1114,1181, +1115,1181,1114, +1181,1115,1182, +1116,1182,1115, +1182,1116,1183, +1117,1183,1116, +1183,1117,1184, +1118,1184,1117, +1184,1118,1185, +1119,1185,1118, +1185,1119,1186, +1120,1186,1119, +1186,1120,1187, +1121,1187,1120, +1188,1122,1189, +1123,1189,1122, +1189,1123,1190, +1124,1190,1123, +1190,1124,1191, +1125,1191,1124, +1191,1125,1192, +1126,1192,1125, +1192,1126,1193, +1127,1193,1126, +1193,1127,1194, +1128,1194,1127, +1194,1128,1195, +1129,1195,1128, +1195,1129,1196, +1130,1196,1129, +1196,1130,1197, +1131,1197,1130, +1197,1131,1198, +1132,1198,1131, +1198,1132,1199, +1133,1199,1132, +1199,1133,1200, +1134,1200,1133, +1200,1134,1201, +1135,1201,1134, +1201,1135,1202, +1136,1202,1135, +1202,1136,1203, +1137,1203,1136, +1203,1137,1204, +1138,1204,1137, +1204,1138,1205, +1139,1205,1138, +1205,1139,1206, +1140,1206,1139, +1206,1140,1207, +1141,1207,1140, +1207,1141,1208, +1142,1208,1141, +1208,1142,1209, +1143,1209,1142, +1209,1143,1210, +1144,1210,1143, +1210,1144,1211, +1145,1211,1144, +1211,1145,1212, +1146,1212,1145, +1212,1146,1213, +1147,1213,1146, +1213,1147,1214, +1148,1214,1147, +1214,1148,1215, +1149,1215,1148, +1215,1149,1216, +1150,1216,1149, +1216,1150,1217, +1151,1217,1150, +1217,1151,1218, +1152,1218,1151, +1218,1152,1219, +1153,1219,1152, +1219,1153,1220, +1154,1220,1153, +1220,1154,1221, +1155,1221,1154, +1221,1155,1222, +1156,1222,1155, +1222,1156,1223, +1157,1223,1156, +1223,1157,1224, +1158,1224,1157, +1224,1158,1225, +1159,1225,1158, +1225,1159,1226, +1160,1226,1159, +1226,1160,1227, +1161,1227,1160, +1227,1161,1228, +1162,1228,1161, +1228,1162,1229, +1163,1229,1162, +1229,1163,1230, +1164,1230,1163, +1230,1164,1231, +1165,1231,1164, +1231,1165,1232, +1166,1232,1165, +1232,1166,1233, +1167,1233,1166, +1233,1167,1234, +1168,1234,1167, +1234,1168,1235, +1169,1235,1168, +1235,1169,1236, +1170,1236,1169, +1236,1170,1237, +1171,1237,1170, +1237,1171,1238, +1172,1238,1171, +1238,1172,1239, +1173,1239,1172, +1239,1173,1240, +1174,1240,1173, +1240,1174,1241, +1175,1241,1174, +1241,1175,1242, +1176,1242,1175, +1242,1176,1243, +1177,1243,1176, +1243,1177,1244, +1178,1244,1177, +1244,1178,1245, +1179,1245,1178, +1245,1179,1246, +1180,1246,1179, +1246,1180,1247, +1181,1247,1180, +1247,1181,1248, +1182,1248,1181, +1248,1182,1249, +1183,1249,1182, +1249,1183,1250, +1184,1250,1183, +1250,1184,1251, +1185,1251,1184, +1251,1185,1252, +1186,1252,1185, +1252,1186,1253, +1187,1253,1186, +1254,1188,1255, +1189,1255,1188, +1255,1189,1256, +1190,1256,1189, +1256,1190,1257, +1191,1257,1190, +1257,1191,1258, +1192,1258,1191, +1258,1192,1259, +1193,1259,1192, +1259,1193,1260, +1194,1260,1193, +1260,1194,1261, +1195,1261,1194, +1261,1195,1262, +1196,1262,1195, +1262,1196,1263, +1197,1263,1196, +1263,1197,1264, +1198,1264,1197, +1264,1198,1265, +1199,1265,1198, +1265,1199,1266, +1200,1266,1199, +1266,1200,1267, +1201,1267,1200, +1267,1201,1268, +1202,1268,1201, +1268,1202,1269, +1203,1269,1202, +1269,1203,1270, +1204,1270,1203, +1270,1204,1271, +1205,1271,1204, +1271,1205,1272, +1206,1272,1205, +1272,1206,1273, +1207,1273,1206, +1273,1207,1274, +1208,1274,1207, +1274,1208,1275, +1209,1275,1208, +1275,1209,1276, +1210,1276,1209, +1276,1210,1277, +1211,1277,1210, +1277,1211,1278, +1212,1278,1211, +1278,1212,1279, +1213,1279,1212, +1279,1213,1280, +1214,1280,1213, +1280,1214,1281, +1215,1281,1214, +1281,1215,1282, +1216,1282,1215, +1282,1216,1283, +1217,1283,1216, +1283,1217,1284, +1218,1284,1217, +1284,1218,1285, +1219,1285,1218, +1285,1219,1286, +1220,1286,1219, +1286,1220,1287, +1221,1287,1220, +1287,1221,1288, +1222,1288,1221, +1288,1222,1289, +1223,1289,1222, +1289,1223,1290, +1224,1290,1223, +1290,1224,1291, +1225,1291,1224, +1291,1225,1292, +1226,1292,1225, +1292,1226,1293, +1227,1293,1226, +1293,1227,1294, +1228,1294,1227, +1294,1228,1295, +1229,1295,1228, +1295,1229,1296, +1230,1296,1229, +1296,1230,1297, +1231,1297,1230, +1297,1231,1298, +1232,1298,1231, +1298,1232,1299, +1233,1299,1232, +1299,1233,1300, +1234,1300,1233, +1300,1234,1301, +1235,1301,1234, +1301,1235,1302, +1236,1302,1235, +1302,1236,1303, +1237,1303,1236, +1303,1237,1304, +1238,1304,1237, +1304,1238,1305, +1239,1305,1238, +1305,1239,1306, +1240,1306,1239, +1306,1240,1307, +1241,1307,1240, +1307,1241,1308, +1242,1308,1241, +1308,1242,1309, +1243,1309,1242, +1309,1243,1310, +1244,1310,1243, +1310,1244,1311, +1245,1311,1244, +1311,1245,1312, +1246,1312,1245, +1312,1246,1313, +1247,1313,1246, +1313,1247,1314, +1248,1314,1247, +1314,1248,1315, +1249,1315,1248, +1315,1249,1316, +1250,1316,1249, +1316,1250,1317, +1251,1317,1250, +1317,1251,1318, +1252,1318,1251, +1318,1252,1319, +1253,1319,1252, +1320,1254,1321, +1255,1321,1254, +1321,1255,1322, +1256,1322,1255, +1322,1256,1323, +1257,1323,1256, +1323,1257,1324, +1258,1324,1257, +1324,1258,1325, +1259,1325,1258, +1325,1259,1326, +1260,1326,1259, +1326,1260,1327, +1261,1327,1260, +1327,1261,1328, +1262,1328,1261, +1328,1262,1329, +1263,1329,1262, +1329,1263,1330, +1264,1330,1263, +1330,1264,1331, +1265,1331,1264, +1331,1265,1332, +1266,1332,1265, +1332,1266,1333, +1267,1333,1266, +1333,1267,1334, +1268,1334,1267, +1334,1268,1335, +1269,1335,1268, +1335,1269,1336, +1270,1336,1269, +1336,1270,1337, +1271,1337,1270, +1337,1271,1338, +1272,1338,1271, +1338,1272,1339, +1273,1339,1272, +1339,1273,1340, +1274,1340,1273, +1340,1274,1341, +1275,1341,1274, +1341,1275,1342, +1276,1342,1275, +1342,1276,1343, +1277,1343,1276, +1343,1277,1344, +1278,1344,1277, +1344,1278,1345, +1279,1345,1278, +1345,1279,1346, +1280,1346,1279, +1346,1280,1347, +1281,1347,1280, +1347,1281,1348, +1282,1348,1281, +1348,1282,1349, +1283,1349,1282, +1349,1283,1350, +1284,1350,1283, +1350,1284,1351, +1285,1351,1284, +1351,1285,1352, +1286,1352,1285, +1352,1286,1353, +1287,1353,1286, +1353,1287,1354, +1288,1354,1287, +1354,1288,1355, +1289,1355,1288, +1355,1289,1356, +1290,1356,1289, +1356,1290,1357, +1291,1357,1290, +1357,1291,1358, +1292,1358,1291, +1358,1292,1359, +1293,1359,1292, +1359,1293,1360, +1294,1360,1293, +1360,1294,1361, +1295,1361,1294, +1361,1295,1362, +1296,1362,1295, +1362,1296,1363, +1297,1363,1296, +1363,1297,1364, +1298,1364,1297, +1364,1298,1365, +1299,1365,1298, +1365,1299,1366, +1300,1366,1299, +1366,1300,1367, +1301,1367,1300, +1367,1301,1368, +1302,1368,1301, +1368,1302,1369, +1303,1369,1302, +1369,1303,1370, +1304,1370,1303, +1370,1304,1371, +1305,1371,1304, +1371,1305,1372, +1306,1372,1305, +1372,1306,1373, +1307,1373,1306, +1373,1307,1374, +1308,1374,1307, +1374,1308,1375, +1309,1375,1308, +1375,1309,1376, +1310,1376,1309, +1376,1310,1377, +1311,1377,1310, +1377,1311,1378, +1312,1378,1311, +1378,1312,1379, +1313,1379,1312, +1379,1313,1380, +1314,1380,1313, +1380,1314,1381, +1315,1381,1314, +1381,1315,1382, +1316,1382,1315, +1382,1316,1383, +1317,1383,1316, +1383,1317,1384, +1318,1384,1317, +1384,1318,1385, +1319,1385,1318, +1386,1320,1387, +1321,1387,1320, +1387,1321,1388, +1322,1388,1321, +1388,1322,1389, +1323,1389,1322, +1389,1323,1390, +1324,1390,1323, +1390,1324,1391, +1325,1391,1324, +1391,1325,1392, +1326,1392,1325, +1392,1326,1393, +1327,1393,1326, +1393,1327,1394, +1328,1394,1327, +1394,1328,1395, +1329,1395,1328, +1395,1329,1396, +1330,1396,1329, +1396,1330,1397, +1331,1397,1330, +1397,1331,1398, +1332,1398,1331, +1398,1332,1399, +1333,1399,1332, +1399,1333,1400, +1334,1400,1333, +1400,1334,1401, +1335,1401,1334, +1401,1335,1402, +1336,1402,1335, +1402,1336,1403, +1337,1403,1336, +1403,1337,1404, +1338,1404,1337, +1404,1338,1405, +1339,1405,1338, +1405,1339,1406, +1340,1406,1339, +1406,1340,1407, +1341,1407,1340, +1407,1341,1408, +1342,1408,1341, +1408,1342,1409, +1343,1409,1342, +1409,1343,1410, +1344,1410,1343, +1410,1344,1411, +1345,1411,1344, +1411,1345,1412, +1346,1412,1345, +1412,1346,1413, +1347,1413,1346, +1413,1347,1414, +1348,1414,1347, +1414,1348,1415, +1349,1415,1348, +1415,1349,1416, +1350,1416,1349, +1416,1350,1417, +1351,1417,1350, +1417,1351,1418, +1352,1418,1351, +1418,1352,1419, +1353,1419,1352, +1419,1353,1420, +1354,1420,1353, +1420,1354,1421, +1355,1421,1354, +1421,1355,1422, +1356,1422,1355, +1422,1356,1423, +1357,1423,1356, +1423,1357,1424, +1358,1424,1357, +1424,1358,1425, +1359,1425,1358, +1425,1359,1426, +1360,1426,1359, +1426,1360,1427, +1361,1427,1360, +1427,1361,1428, +1362,1428,1361, +1428,1362,1429, +1363,1429,1362, +1429,1363,1430, +1364,1430,1363, +1430,1364,1431, +1365,1431,1364, +1431,1365,1432, +1366,1432,1365, +1432,1366,1433, +1367,1433,1366, +1433,1367,1434, +1368,1434,1367, +1434,1368,1435, +1369,1435,1368, +1435,1369,1436, +1370,1436,1369, +1436,1370,1437, +1371,1437,1370, +1437,1371,1438, +1372,1438,1371, +1438,1372,1439, +1373,1439,1372, +1439,1373,1440, +1374,1440,1373, +1440,1374,1441, +1375,1441,1374, +1441,1375,1442, +1376,1442,1375, +1442,1376,1443, +1377,1443,1376, +1443,1377,1444, +1378,1444,1377, +1444,1378,1445, +1379,1445,1378, +1445,1379,1446, +1380,1446,1379, +1446,1380,1447, +1381,1447,1380, +1447,1381,1448, +1382,1448,1381, +1448,1382,1449, +1383,1449,1382, +1449,1383,1450, +1384,1450,1383, +1450,1384,1451, +1385,1451,1384, +1452,1386,1453, +1387,1453,1386, +1453,1387,1454, +1388,1454,1387, +1454,1388,1455, +1389,1455,1388, +1455,1389,1456, +1390,1456,1389, +1456,1390,1457, +1391,1457,1390, +1457,1391,1458, +1392,1458,1391, +1458,1392,1459, +1393,1459,1392, +1459,1393,1460, +1394,1460,1393, +1460,1394,1461, +1395,1461,1394, +1461,1395,1462, +1396,1462,1395, +1462,1396,1463, +1397,1463,1396, +1463,1397,1464, +1398,1464,1397, +1464,1398,1465, +1399,1465,1398, +1465,1399,1466, +1400,1466,1399, +1466,1400,1467, +1401,1467,1400, +1467,1401,1468, +1402,1468,1401, +1468,1402,1469, +1403,1469,1402, +1469,1403,1470, +1404,1470,1403, +1470,1404,1471, +1405,1471,1404, +1471,1405,1472, +1406,1472,1405, +1472,1406,1473, +1407,1473,1406, +1473,1407,1474, +1408,1474,1407, +1474,1408,1475, +1409,1475,1408, +1475,1409,1476, +1410,1476,1409, +1476,1410,1477, +1411,1477,1410, +1477,1411,1478, +1412,1478,1411, +1478,1412,1479, +1413,1479,1412, +1479,1413,1480, +1414,1480,1413, +1480,1414,1481, +1415,1481,1414, +1481,1415,1482, +1416,1482,1415, +1482,1416,1483, +1417,1483,1416, +1483,1417,1484, +1418,1484,1417, +1484,1418,1485, +1419,1485,1418, +1485,1419,1486, +1420,1486,1419, +1486,1420,1487, +1421,1487,1420, +1487,1421,1488, +1422,1488,1421, +1488,1422,1489, +1423,1489,1422, +1489,1423,1490, +1424,1490,1423, +1490,1424,1491, +1425,1491,1424, +1491,1425,1492, +1426,1492,1425, +1492,1426,1493, +1427,1493,1426, +1493,1427,1494, +1428,1494,1427, +1494,1428,1495, +1429,1495,1428, +1495,1429,1496, +1430,1496,1429, +1496,1430,1497, +1431,1497,1430, +1497,1431,1498, +1432,1498,1431, +1498,1432,1499, +1433,1499,1432, +1499,1433,1500, +1434,1500,1433, +1500,1434,1501, +1435,1501,1434, +1501,1435,1502, +1436,1502,1435, +1502,1436,1503, +1437,1503,1436, +1503,1437,1504, +1438,1504,1437, +1504,1438,1505, +1439,1505,1438, +1505,1439,1506, +1440,1506,1439, +1506,1440,1507, +1441,1507,1440, +1507,1441,1508, +1442,1508,1441, +1508,1442,1509, +1443,1509,1442, +1509,1443,1510, +1444,1510,1443, +1510,1444,1511, +1445,1511,1444, +1511,1445,1512, +1446,1512,1445, +1512,1446,1513, +1447,1513,1446, +1513,1447,1514, +1448,1514,1447, +1514,1448,1515, +1449,1515,1448, +1515,1449,1516, +1450,1516,1449, +1516,1450,1517, +1451,1517,1450, +1518,1452,1519, +1453,1519,1452, +1519,1453,1520, +1454,1520,1453, +1520,1454,1521, +1455,1521,1454, +1521,1455,1522, +1456,1522,1455, +1522,1456,1523, +1457,1523,1456, +1523,1457,1524, +1458,1524,1457, +1524,1458,1525, +1459,1525,1458, +1525,1459,1526, +1460,1526,1459, +1526,1460,1527, +1461,1527,1460, +1527,1461,1528, +1462,1528,1461, +1528,1462,1529, +1463,1529,1462, +1529,1463,1530, +1464,1530,1463, +1530,1464,1531, +1465,1531,1464, +1531,1465,1532, +1466,1532,1465, +1532,1466,1533, +1467,1533,1466, +1533,1467,1534, +1468,1534,1467, +1534,1468,1535, +1469,1535,1468, +1535,1469,1536, +1470,1536,1469, +1536,1470,1537, +1471,1537,1470, +1537,1471,1538, +1472,1538,1471, +1538,1472,1539, +1473,1539,1472, +1539,1473,1540, +1474,1540,1473, +1540,1474,1541, +1475,1541,1474, +1541,1475,1542, +1476,1542,1475, +1542,1476,1543, +1477,1543,1476, +1543,1477,1544, +1478,1544,1477, +1544,1478,1545, +1479,1545,1478, +1545,1479,1546, +1480,1546,1479, +1546,1480,1547, +1481,1547,1480, +1547,1481,1548, +1482,1548,1481, +1548,1482,1549, +1483,1549,1482, +1549,1483,1550, +1484,1550,1483, +1550,1484,1551, +1485,1551,1484, +1551,1485,1552, +1486,1552,1485, +1552,1486,1553, +1487,1553,1486, +1553,1487,1554, +1488,1554,1487, +1554,1488,1555, +1489,1555,1488, +1555,1489,1556, +1490,1556,1489, +1556,1490,1557, +1491,1557,1490, +1557,1491,1558, +1492,1558,1491, +1558,1492,1559, +1493,1559,1492, +1559,1493,1560, +1494,1560,1493, +1560,1494,1561, +1495,1561,1494, +1561,1495,1562, +1496,1562,1495, +1562,1496,1563, +1497,1563,1496, +1563,1497,1564, +1498,1564,1497, +1564,1498,1565, +1499,1565,1498, +1565,1499,1566, +1500,1566,1499, +1566,1500,1567, +1501,1567,1500, +1567,1501,1568, +1502,1568,1501, +1568,1502,1569, +1503,1569,1502, +1569,1503,1570, +1504,1570,1503, +1570,1504,1571, +1505,1571,1504, +1571,1505,1572, +1506,1572,1505, +1572,1506,1573, +1507,1573,1506, +1573,1507,1574, +1508,1574,1507, +1574,1508,1575, +1509,1575,1508, +1575,1509,1576, +1510,1576,1509, +1576,1510,1577, +1511,1577,1510, +1577,1511,1578, +1512,1578,1511, +1578,1512,1579, +1513,1579,1512, +1579,1513,1580, +1514,1580,1513, +1580,1514,1581, +1515,1581,1514, +1581,1515,1582, +1516,1582,1515, +1582,1516,1583, +1517,1583,1516, +1584,1518,1585, +1519,1585,1518, +1585,1519,1586, +1520,1586,1519, +1586,1520,1587, +1521,1587,1520, +1587,1521,1588, +1522,1588,1521, +1588,1522,1589, +1523,1589,1522, +1589,1523,1590, +1524,1590,1523, +1590,1524,1591, +1525,1591,1524, +1591,1525,1592, +1526,1592,1525, +1592,1526,1593, +1527,1593,1526, +1593,1527,1594, +1528,1594,1527, +1594,1528,1595, +1529,1595,1528, +1595,1529,1596, +1530,1596,1529, +1596,1530,1597, +1531,1597,1530, +1597,1531,1598, +1532,1598,1531, +1598,1532,1599, +1533,1599,1532, +1599,1533,1600, +1534,1600,1533, +1600,1534,1601, +1535,1601,1534, +1601,1535,1602, +1536,1602,1535, +1602,1536,1603, +1537,1603,1536, +1603,1537,1604, +1538,1604,1537, +1604,1538,1605, +1539,1605,1538, +1605,1539,1606, +1540,1606,1539, +1606,1540,1607, +1541,1607,1540, +1607,1541,1608, +1542,1608,1541, +1608,1542,1609, +1543,1609,1542, +1609,1543,1610, +1544,1610,1543, +1610,1544,1611, +1545,1611,1544, +1611,1545,1612, +1546,1612,1545, +1612,1546,1613, +1547,1613,1546, +1613,1547,1614, +1548,1614,1547, +1614,1548,1615, +1549,1615,1548, +1615,1549,1616, +1550,1616,1549, +1616,1550,1617, +1551,1617,1550, +1617,1551,1618, +1552,1618,1551, +1618,1552,1619, +1553,1619,1552, +1619,1553,1620, +1554,1620,1553, +1620,1554,1621, +1555,1621,1554, +1621,1555,1622, +1556,1622,1555, +1622,1556,1623, +1557,1623,1556, +1623,1557,1624, +1558,1624,1557, +1624,1558,1625, +1559,1625,1558, +1625,1559,1626, +1560,1626,1559, +1626,1560,1627, +1561,1627,1560, +1627,1561,1628, +1562,1628,1561, +1628,1562,1629, +1563,1629,1562, +1629,1563,1630, +1564,1630,1563, +1630,1564,1631, +1565,1631,1564, +1631,1565,1632, +1566,1632,1565, +1632,1566,1633, +1567,1633,1566, +1633,1567,1634, +1568,1634,1567, +1634,1568,1635, +1569,1635,1568, +1635,1569,1636, +1570,1636,1569, +1636,1570,1637, +1571,1637,1570, +1637,1571,1638, +1572,1638,1571, +1638,1572,1639, +1573,1639,1572, +1639,1573,1640, +1574,1640,1573, +1640,1574,1641, +1575,1641,1574, +1641,1575,1642, +1576,1642,1575, +1642,1576,1643, +1577,1643,1576, +1643,1577,1644, +1578,1644,1577, +1644,1578,1645, +1579,1645,1578, +1645,1579,1646, +1580,1646,1579, +1646,1580,1647, +1581,1647,1580, +1647,1581,1648, +1582,1648,1581, +1648,1582,1649, +1583,1649,1582, +1650,1584,1651, +1585,1651,1584, +1651,1585,1652, +1586,1652,1585, +1652,1586,1653, +1587,1653,1586, +1653,1587,1654, +1588,1654,1587, +1654,1588,1655, +1589,1655,1588, +1655,1589,1656, +1590,1656,1589, +1656,1590,1657, +1591,1657,1590, +1657,1591,1658, +1592,1658,1591, +1658,1592,1659, +1593,1659,1592, +1659,1593,1660, +1594,1660,1593, +1660,1594,1661, +1595,1661,1594, +1661,1595,1662, +1596,1662,1595, +1662,1596,1663, +1597,1663,1596, +1663,1597,1664, +1598,1664,1597, +1664,1598,1665, +1599,1665,1598, +1665,1599,1666, +1600,1666,1599, +1666,1600,1667, +1601,1667,1600, +1667,1601,1668, +1602,1668,1601, +1668,1602,1669, +1603,1669,1602, +1669,1603,1670, +1604,1670,1603, +1670,1604,1671, +1605,1671,1604, +1671,1605,1672, +1606,1672,1605, +1672,1606,1673, +1607,1673,1606, +1673,1607,1674, +1608,1674,1607, +1674,1608,1675, +1609,1675,1608, +1675,1609,1676, +1610,1676,1609, +1676,1610,1677, +1611,1677,1610, +1677,1611,1678, +1612,1678,1611, +1678,1612,1679, +1613,1679,1612, +1679,1613,1680, +1614,1680,1613, +1680,1614,1681, +1615,1681,1614, +1681,1615,1682, +1616,1682,1615, +1682,1616,1683, +1617,1683,1616, +1683,1617,1684, +1618,1684,1617, +1684,1618,1685, +1619,1685,1618, +1685,1619,1686, +1620,1686,1619, +1686,1620,1687, +1621,1687,1620, +1687,1621,1688, +1622,1688,1621, +1688,1622,1689, +1623,1689,1622, +1689,1623,1690, +1624,1690,1623, +1690,1624,1691, +1625,1691,1624, +1691,1625,1692, +1626,1692,1625, +1692,1626,1693, +1627,1693,1626, +1693,1627,1694, +1628,1694,1627, +1694,1628,1695, +1629,1695,1628, +1695,1629,1696, +1630,1696,1629, +1696,1630,1697, +1631,1697,1630, +1697,1631,1698, +1632,1698,1631, +1698,1632,1699, +1633,1699,1632, +1699,1633,1700, +1634,1700,1633, +1700,1634,1701, +1635,1701,1634, +1701,1635,1702, +1636,1702,1635, +1702,1636,1703, +1637,1703,1636, +1703,1637,1704, +1638,1704,1637, +1704,1638,1705, +1639,1705,1638, +1705,1639,1706, +1640,1706,1639, +1706,1640,1707, +1641,1707,1640, +1707,1641,1708, +1642,1708,1641, +1708,1642,1709, +1643,1709,1642, +1709,1643,1710, +1644,1710,1643, +1710,1644,1711, +1645,1711,1644, +1711,1645,1712, +1646,1712,1645, +1712,1646,1713, +1647,1713,1646, +1713,1647,1714, +1648,1714,1647, +1714,1648,1715, +1649,1715,1648, +1716,1650,1717, +1651,1717,1650, +1717,1651,1718, +1652,1718,1651, +1718,1652,1719, +1653,1719,1652, +1719,1653,1720, +1654,1720,1653, +1720,1654,1721, +1655,1721,1654, +1721,1655,1722, +1656,1722,1655, +1722,1656,1723, +1657,1723,1656, +1723,1657,1724, +1658,1724,1657, +1724,1658,1725, +1659,1725,1658, +1725,1659,1726, +1660,1726,1659, +1726,1660,1727, +1661,1727,1660, +1727,1661,1728, +1662,1728,1661, +1728,1662,1729, +1663,1729,1662, +1729,1663,1730, +1664,1730,1663, +1730,1664,1731, +1665,1731,1664, +1731,1665,1732, +1666,1732,1665, +1732,1666,1733, +1667,1733,1666, +1733,1667,1734, +1668,1734,1667, +1734,1668,1735, +1669,1735,1668, +1735,1669,1736, +1670,1736,1669, +1736,1670,1737, +1671,1737,1670, +1737,1671,1738, +1672,1738,1671, +1738,1672,1739, +1673,1739,1672, +1739,1673,1740, +1674,1740,1673, +1740,1674,1741, +1675,1741,1674, +1741,1675,1742, +1676,1742,1675, +1742,1676,1743, +1677,1743,1676, +1743,1677,1744, +1678,1744,1677, +1744,1678,1745, +1679,1745,1678, +1745,1679,1746, +1680,1746,1679, +1746,1680,1747, +1681,1747,1680, +1747,1681,1748, +1682,1748,1681, +1748,1682,1749, +1683,1749,1682, +1749,1683,1750, +1684,1750,1683, +1750,1684,1751, +1685,1751,1684, +1751,1685,1752, +1686,1752,1685, +1752,1686,1753, +1687,1753,1686, +1753,1687,1754, +1688,1754,1687, +1754,1688,1755, +1689,1755,1688, +1755,1689,1756, +1690,1756,1689, +1756,1690,1757, +1691,1757,1690, +1757,1691,1758, +1692,1758,1691, +1758,1692,1759, +1693,1759,1692, +1759,1693,1760, +1694,1760,1693, +1760,1694,1761, +1695,1761,1694, +1761,1695,1762, +1696,1762,1695, +1762,1696,1763, +1697,1763,1696, +1763,1697,1764, +1698,1764,1697, +1764,1698,1765, +1699,1765,1698, +1765,1699,1766, +1700,1766,1699, +1766,1700,1767, +1701,1767,1700, +1767,1701,1768, +1702,1768,1701, +1768,1702,1769, +1703,1769,1702, +1769,1703,1770, +1704,1770,1703, +1770,1704,1771, +1705,1771,1704, +1771,1705,1772, +1706,1772,1705, +1772,1706,1773, +1707,1773,1706, +1773,1707,1774, +1708,1774,1707, +1774,1708,1775, +1709,1775,1708, +1775,1709,1776, +1710,1776,1709, +1776,1710,1777, +1711,1777,1710, +1777,1711,1778, +1712,1778,1711, +1778,1712,1779, +1713,1779,1712, +1779,1713,1780, +1714,1780,1713, +1780,1714,1781, +1715,1781,1714, +1782,1716,1783, +1717,1783,1716, +1783,1717,1784, +1718,1784,1717, +1784,1718,1785, +1719,1785,1718, +1785,1719,1786, +1720,1786,1719, +1786,1720,1787, +1721,1787,1720, +1787,1721,1788, +1722,1788,1721, +1788,1722,1789, +1723,1789,1722, +1789,1723,1790, +1724,1790,1723, +1790,1724,1791, +1725,1791,1724, +1791,1725,1792, +1726,1792,1725, +1792,1726,1793, +1727,1793,1726, +1793,1727,1794, +1728,1794,1727, +1794,1728,1795, +1729,1795,1728, +1795,1729,1796, +1730,1796,1729, +1796,1730,1797, +1731,1797,1730, +1797,1731,1798, +1732,1798,1731, +1798,1732,1799, +1733,1799,1732, +1799,1733,1800, +1734,1800,1733, +1800,1734,1801, +1735,1801,1734, +1801,1735,1802, +1736,1802,1735, +1802,1736,1803, +1737,1803,1736, +1803,1737,1804, +1738,1804,1737, +1804,1738,1805, +1739,1805,1738, +1805,1739,1806, +1740,1806,1739, +1806,1740,1807, +1741,1807,1740, +1807,1741,1808, +1742,1808,1741, +1808,1742,1809, +1743,1809,1742, +1809,1743,1810, +1744,1810,1743, +1810,1744,1811, +1745,1811,1744, +1811,1745,1812, +1746,1812,1745, +1812,1746,1813, +1747,1813,1746, +1813,1747,1814, +1748,1814,1747, +1814,1748,1815, +1749,1815,1748, +1815,1749,1816, +1750,1816,1749, +1816,1750,1817, +1751,1817,1750, +1817,1751,1818, +1752,1818,1751, +1818,1752,1819, +1753,1819,1752, +1819,1753,1820, +1754,1820,1753, +1820,1754,1821, +1755,1821,1754, +1821,1755,1822, +1756,1822,1755, +1822,1756,1823, +1757,1823,1756, +1823,1757,1824, +1758,1824,1757, +1824,1758,1825, +1759,1825,1758, +1825,1759,1826, +1760,1826,1759, +1826,1760,1827, +1761,1827,1760, +1827,1761,1828, +1762,1828,1761, +1828,1762,1829, +1763,1829,1762, +1829,1763,1830, +1764,1830,1763, +1830,1764,1831, +1765,1831,1764, +1831,1765,1832, +1766,1832,1765, +1832,1766,1833, +1767,1833,1766, +1833,1767,1834, +1768,1834,1767, +1834,1768,1835, +1769,1835,1768, +1835,1769,1836, +1770,1836,1769, +1836,1770,1837, +1771,1837,1770, +1837,1771,1838, +1772,1838,1771, +1838,1772,1839, +1773,1839,1772, +1839,1773,1840, +1774,1840,1773, +1840,1774,1841, +1775,1841,1774, +1841,1775,1842, +1776,1842,1775, +1842,1776,1843, +1777,1843,1776, +1843,1777,1844, +1778,1844,1777, +1844,1778,1845, +1779,1845,1778, +1845,1779,1846, +1780,1846,1779, +1846,1780,1847, +1781,1847,1780, +1848,1782,1849, +1783,1849,1782, +1849,1783,1850, +1784,1850,1783, +1850,1784,1851, +1785,1851,1784, +1851,1785,1852, +1786,1852,1785, +1852,1786,1853, +1787,1853,1786, +1853,1787,1854, +1788,1854,1787, +1854,1788,1855, +1789,1855,1788, +1855,1789,1856, +1790,1856,1789, +1856,1790,1857, +1791,1857,1790, +1857,1791,1858, +1792,1858,1791, +1858,1792,1859, +1793,1859,1792, +1859,1793,1860, +1794,1860,1793, +1860,1794,1861, +1795,1861,1794, +1861,1795,1862, +1796,1862,1795, +1862,1796,1863, +1797,1863,1796, +1863,1797,1864, +1798,1864,1797, +1864,1798,1865, +1799,1865,1798, +1865,1799,1866, +1800,1866,1799, +1866,1800,1867, +1801,1867,1800, +1867,1801,1868, +1802,1868,1801, +1868,1802,1869, +1803,1869,1802, +1869,1803,1870, +1804,1870,1803, +1870,1804,1871, +1805,1871,1804, +1871,1805,1872, +1806,1872,1805, +1872,1806,1873, +1807,1873,1806, +1873,1807,1874, +1808,1874,1807, +1874,1808,1875, +1809,1875,1808, +1875,1809,1876, +1810,1876,1809, +1876,1810,1877, +1811,1877,1810, +1877,1811,1878, +1812,1878,1811, +1878,1812,1879, +1813,1879,1812, +1879,1813,1880, +1814,1880,1813, +1880,1814,1881, +1815,1881,1814, +1881,1815,1882, +1816,1882,1815, +1882,1816,1883, +1817,1883,1816, +1883,1817,1884, +1818,1884,1817, +1884,1818,1885, +1819,1885,1818, +1885,1819,1886, +1820,1886,1819, +1886,1820,1887, +1821,1887,1820, +1887,1821,1888, +1822,1888,1821, +1888,1822,1889, +1823,1889,1822, +1889,1823,1890, +1824,1890,1823, +1890,1824,1891, +1825,1891,1824, +1891,1825,1892, +1826,1892,1825, +1892,1826,1893, +1827,1893,1826, +1893,1827,1894, +1828,1894,1827, +1894,1828,1895, +1829,1895,1828, +1895,1829,1896, +1830,1896,1829, +1896,1830,1897, +1831,1897,1830, +1897,1831,1898, +1832,1898,1831, +1898,1832,1899, +1833,1899,1832, +1899,1833,1900, +1834,1900,1833, +1900,1834,1901, +1835,1901,1834, +1901,1835,1902, +1836,1902,1835, +1902,1836,1903, +1837,1903,1836, +1903,1837,1904, +1838,1904,1837, +1904,1838,1905, +1839,1905,1838, +1905,1839,1906, +1840,1906,1839, +1906,1840,1907, +1841,1907,1840, +1907,1841,1908, +1842,1908,1841, +1908,1842,1909, +1843,1909,1842, +1909,1843,1910, +1844,1910,1843, +1910,1844,1911, +1845,1911,1844, +1911,1845,1912, +1846,1912,1845, +1912,1846,1913, +1847,1913,1846, +1914,1848,1915, +1849,1915,1848, +1915,1849,1916, +1850,1916,1849, +1916,1850,1917, +1851,1917,1850, +1917,1851,1918, +1852,1918,1851, +1918,1852,1919, +1853,1919,1852, +1919,1853,1920, +1854,1920,1853, +1920,1854,1921, +1855,1921,1854, +1921,1855,1922, +1856,1922,1855, +1922,1856,1923, +1857,1923,1856, +1923,1857,1924, +1858,1924,1857, +1924,1858,1925, +1859,1925,1858, +1925,1859,1926, +1860,1926,1859, +1926,1860,1927, +1861,1927,1860, +1927,1861,1928, +1862,1928,1861, +1928,1862,1929, +1863,1929,1862, +1929,1863,1930, +1864,1930,1863, +1930,1864,1931, +1865,1931,1864, +1931,1865,1932, +1866,1932,1865, +1932,1866,1933, +1867,1933,1866, +1933,1867,1934, +1868,1934,1867, +1934,1868,1935, +1869,1935,1868, +1935,1869,1936, +1870,1936,1869, +1936,1870,1937, +1871,1937,1870, +1937,1871,1938, +1872,1938,1871, +1938,1872,1939, +1873,1939,1872, +1939,1873,1940, +1874,1940,1873, +1940,1874,1941, +1875,1941,1874, +1941,1875,1942, +1876,1942,1875, +1942,1876,1943, +1877,1943,1876, +1943,1877,1944, +1878,1944,1877, +1944,1878,1945, +1879,1945,1878, +1945,1879,1946, +1880,1946,1879, +1946,1880,1947, +1881,1947,1880, +1947,1881,1948, +1882,1948,1881, +1948,1882,1949, +1883,1949,1882, +1949,1883,1950, +1884,1950,1883, +1950,1884,1951, +1885,1951,1884, +1951,1885,1952, +1886,1952,1885, +1952,1886,1953, +1887,1953,1886, +1953,1887,1954, +1888,1954,1887, +1954,1888,1955, +1889,1955,1888, +1955,1889,1956, +1890,1956,1889, +1956,1890,1957, +1891,1957,1890, +1957,1891,1958, +1892,1958,1891, +1958,1892,1959, +1893,1959,1892, +1959,1893,1960, +1894,1960,1893, +1960,1894,1961, +1895,1961,1894, +1961,1895,1962, +1896,1962,1895, +1962,1896,1963, +1897,1963,1896, +1963,1897,1964, +1898,1964,1897, +1964,1898,1965, +1899,1965,1898, +1965,1899,1966, +1900,1966,1899, +1966,1900,1967, +1901,1967,1900, +1967,1901,1968, +1902,1968,1901, +1968,1902,1969, +1903,1969,1902, +1969,1903,1970, +1904,1970,1903, +1970,1904,1971, +1905,1971,1904, +1971,1905,1972, +1906,1972,1905, +1972,1906,1973, +1907,1973,1906, +1973,1907,1974, +1908,1974,1907, +1974,1908,1975, +1909,1975,1908, +1975,1909,1976, +1910,1976,1909, +1976,1910,1977, +1911,1977,1910, +1977,1911,1978, +1912,1978,1911, +1978,1912,1979, +1913,1979,1912, +1980,1914,1981, +1915,1981,1914, +1981,1915,1982, +1916,1982,1915, +1982,1916,1983, +1917,1983,1916, +1983,1917,1984, +1918,1984,1917, +1984,1918,1985, +1919,1985,1918, +1985,1919,1986, +1920,1986,1919, +1986,1920,1987, +1921,1987,1920, +1987,1921,1988, +1922,1988,1921, +1988,1922,1989, +1923,1989,1922, +1989,1923,1990, +1924,1990,1923, +1990,1924,1991, +1925,1991,1924, +1991,1925,1992, +1926,1992,1925, +1992,1926,1993, +1927,1993,1926, +1993,1927,1994, +1928,1994,1927, +1994,1928,1995, +1929,1995,1928, +1995,1929,1996, +1930,1996,1929, +1996,1930,1997, +1931,1997,1930, +1997,1931,1998, +1932,1998,1931, +1998,1932,1999, +1933,1999,1932, +1999,1933,2000, +1934,2000,1933, +2000,1934,2001, +1935,2001,1934, +2001,1935,2002, +1936,2002,1935, +2002,1936,2003, +1937,2003,1936, +2003,1937,2004, +1938,2004,1937, +2004,1938,2005, +1939,2005,1938, +2005,1939,2006, +1940,2006,1939, +2006,1940,2007, +1941,2007,1940, +2007,1941,2008, +1942,2008,1941, +2008,1942,2009, +1943,2009,1942, +2009,1943,2010, +1944,2010,1943, +2010,1944,2011, +1945,2011,1944, +2011,1945,2012, +1946,2012,1945, +2012,1946,2013, +1947,2013,1946, +2013,1947,2014, +1948,2014,1947, +2014,1948,2015, +1949,2015,1948, +2015,1949,2016, +1950,2016,1949, +2016,1950,2017, +1951,2017,1950, +2017,1951,2018, +1952,2018,1951, +2018,1952,2019, +1953,2019,1952, +2019,1953,2020, +1954,2020,1953, +2020,1954,2021, +1955,2021,1954, +2021,1955,2022, +1956,2022,1955, +2022,1956,2023, +1957,2023,1956, +2023,1957,2024, +1958,2024,1957, +2024,1958,2025, +1959,2025,1958, +2025,1959,2026, +1960,2026,1959, +2026,1960,2027, +1961,2027,1960, +2027,1961,2028, +1962,2028,1961, +2028,1962,2029, +1963,2029,1962, +2029,1963,2030, +1964,2030,1963, +2030,1964,2031, +1965,2031,1964, +2031,1965,2032, +1966,2032,1965, +2032,1966,2033, +1967,2033,1966, +2033,1967,2034, +1968,2034,1967, +2034,1968,2035, +1969,2035,1968, +2035,1969,2036, +1970,2036,1969, +2036,1970,2037, +1971,2037,1970, +2037,1971,2038, +1972,2038,1971, +2038,1972,2039, +1973,2039,1972, +2039,1973,2040, +1974,2040,1973, +2040,1974,2041, +1975,2041,1974, +2041,1975,2042, +1976,2042,1975, +2042,1976,2043, +1977,2043,1976, +2043,1977,2044, +1978,2044,1977, +2044,1978,2045, +1979,2045,1978, +2046,1980,2047, +1981,2047,1980, +2047,1981,2048, +1982,2048,1981, +2048,1982,2049, +1983,2049,1982, +2049,1983,2050, +1984,2050,1983, +2050,1984,2051, +1985,2051,1984, +2051,1985,2052, +1986,2052,1985, +2052,1986,2053, +1987,2053,1986, +2053,1987,2054, +1988,2054,1987, +2054,1988,2055, +1989,2055,1988, +2055,1989,2056, +1990,2056,1989, +2056,1990,2057, +1991,2057,1990, +2057,1991,2058, +1992,2058,1991, +2058,1992,2059, +1993,2059,1992, +2059,1993,2060, +1994,2060,1993, +2060,1994,2061, +1995,2061,1994, +2061,1995,2062, +1996,2062,1995, +2062,1996,2063, +1997,2063,1996, +2063,1997,2064, +1998,2064,1997, +2064,1998,2065, +1999,2065,1998, +2065,1999,2066, +2000,2066,1999, +2066,2000,2067, +2001,2067,2000, +2067,2001,2068, +2002,2068,2001, +2068,2002,2069, +2003,2069,2002, +2069,2003,2070, +2004,2070,2003, +2070,2004,2071, +2005,2071,2004, +2071,2005,2072, +2006,2072,2005, +2072,2006,2073, +2007,2073,2006, +2073,2007,2074, +2008,2074,2007, +2074,2008,2075, +2009,2075,2008, +2075,2009,2076, +2010,2076,2009, +2076,2010,2077, +2011,2077,2010, +2077,2011,2078, +2012,2078,2011, +2078,2012,2079, +2013,2079,2012, +2079,2013,2080, +2014,2080,2013, +2080,2014,2081, +2015,2081,2014, +2081,2015,2082, +2016,2082,2015, +2082,2016,2083, +2017,2083,2016, +2083,2017,2084, +2018,2084,2017, +2084,2018,2085, +2019,2085,2018, +2085,2019,2086, +2020,2086,2019, +2086,2020,2087, +2021,2087,2020, +2087,2021,2088, +2022,2088,2021, +2088,2022,2089, +2023,2089,2022, +2089,2023,2090, +2024,2090,2023, +2090,2024,2091, +2025,2091,2024, +2091,2025,2092, +2026,2092,2025, +2092,2026,2093, +2027,2093,2026, +2093,2027,2094, +2028,2094,2027, +2094,2028,2095, +2029,2095,2028, +2095,2029,2096, +2030,2096,2029, +2096,2030,2097, +2031,2097,2030, +2097,2031,2098, +2032,2098,2031, +2098,2032,2099, +2033,2099,2032, +2099,2033,2100, +2034,2100,2033, +2100,2034,2101, +2035,2101,2034, +2101,2035,2102, +2036,2102,2035, +2102,2036,2103, +2037,2103,2036, +2103,2037,2104, +2038,2104,2037, +2104,2038,2105, +2039,2105,2038, +2105,2039,2106, +2040,2106,2039, +2106,2040,2107, +2041,2107,2040, +2107,2041,2108, +2042,2108,2041, +2108,2042,2109, +2043,2109,2042, +2109,2043,2110, +2044,2110,2043, +2110,2044,2111, +2045,2111,2044, +2112,2046,2113, +2047,2113,2046, +2113,2047,2114, +2048,2114,2047, +2114,2048,2115, +2049,2115,2048, +2115,2049,2116, +2050,2116,2049, +2116,2050,2117, +2051,2117,2050, +2117,2051,2118, +2052,2118,2051, +2118,2052,2119, +2053,2119,2052, +2119,2053,2120, +2054,2120,2053, +2120,2054,2121, +2055,2121,2054, +2121,2055,2122, +2056,2122,2055, +2122,2056,2123, +2057,2123,2056, +2123,2057,2124, +2058,2124,2057, +2124,2058,2125, +2059,2125,2058, +2125,2059,2126, +2060,2126,2059, +2126,2060,2127, +2061,2127,2060, +2127,2061,2128, +2062,2128,2061, +2128,2062,2129, +2063,2129,2062, +2129,2063,2130, +2064,2130,2063, +2130,2064,2131, +2065,2131,2064, +2131,2065,2132, +2066,2132,2065, +2132,2066,2133, +2067,2133,2066, +2133,2067,2134, +2068,2134,2067, +2134,2068,2135, +2069,2135,2068, +2135,2069,2136, +2070,2136,2069, +2136,2070,2137, +2071,2137,2070, +2137,2071,2138, +2072,2138,2071, +2138,2072,2139, +2073,2139,2072, +2139,2073,2140, +2074,2140,2073, +2140,2074,2141, +2075,2141,2074, +2141,2075,2142, +2076,2142,2075, +2142,2076,2143, +2077,2143,2076, +2143,2077,2144, +2078,2144,2077, +2144,2078,2145, +2079,2145,2078, +2145,2079,2146, +2080,2146,2079, +2146,2080,2147, +2081,2147,2080, +2147,2081,2148, +2082,2148,2081, +2148,2082,2149, +2083,2149,2082, +2149,2083,2150, +2084,2150,2083, +2150,2084,2151, +2085,2151,2084, +2151,2085,2152, +2086,2152,2085, +2152,2086,2153, +2087,2153,2086, +2153,2087,2154, +2088,2154,2087, +2154,2088,2155, +2089,2155,2088, +2155,2089,2156, +2090,2156,2089, +2156,2090,2157, +2091,2157,2090, +2157,2091,2158, +2092,2158,2091, +2158,2092,2159, +2093,2159,2092, +2159,2093,2160, +2094,2160,2093, +2160,2094,2161, +2095,2161,2094, +2161,2095,2162, +2096,2162,2095, +2162,2096,2163, +2097,2163,2096, +2163,2097,2164, +2098,2164,2097, +2164,2098,2165, +2099,2165,2098, +2165,2099,2166, +2100,2166,2099, +2166,2100,2167, +2101,2167,2100, +2167,2101,2168, +2102,2168,2101, +2168,2102,2169, +2103,2169,2102, +2169,2103,2170, +2104,2170,2103, +2170,2104,2171, +2105,2171,2104, +2171,2105,2172, +2106,2172,2105, +2172,2106,2173, +2107,2173,2106, +2173,2107,2174, +2108,2174,2107, +2174,2108,2175, +2109,2175,2108, +2175,2109,2176, +2110,2176,2109, +2176,2110,2177, +2111,2177,2110, +}; + +#define Landscape01VtxCount 2048 +#define Landscape01IdxCount 11718 + +btScalar Landscape01Vtx[] = { +3.90626f,0.452911f,246.094f, +3.90626f,1.52302f,250.0f, +7.8125f,1.18238f,246.094f, +7.81251f,1.7549f,250.0f, +11.7188f,2.12911f,246.094f, +11.7188f,2.62454f,250.0f, +15.625f,3.01456f,246.094f, +15.625f,3.22814f,250.0f, +19.5313f,3.97431f,246.094f, +19.5313f,3.63231f,250.0f, +23.4375f,4.08741f,246.094f, +23.4375f,4.24097f,250.0f, +27.3438f,5.8163f,246.094f, +27.3438f,5.93409f,250.0f, +31.25f,6.86809f,246.094f, +31.25f,7.34105f,250.0f, +35.1563f,8.25405f,246.094f, +35.1563f,8.62507f,250.0f, +39.0625f,8.38601f,246.094f, +39.0625f,8.68483f,250.0f, +42.9688f,6.94797f,246.094f, +42.9688f,7.71847f,250.0f, +46.875f,4.60698f,246.094f, +46.875f,6.12159f,250.0f, +50.7813f,3.6429f,246.094f, +50.7813f,5.13002f,250.0f, +54.6875f,4.01945f,246.094f, +54.6875f,5.50476f,250.0f, +58.5938f,4.05996f,246.094f, +58.5938f,5.31917f,250.0f, +62.5f,3.98995f,246.094f, +62.5f,5.51823f,250.0f, +66.4063f,5.44402f,246.094f, +66.4063f,6.80029f,250.0f, +70.3125f,6.03873f,246.094f, +70.3125f,7.41783f,250.0f, +74.2188f,6.37187f,246.094f, +74.2188f,8.16051f,250.0f, +78.125f,6.74414f,246.094f, +78.125f,8.72099f,250.0f, +82.0313f,7.37958f,246.094f, +82.0313f,10.1125f,250.0f, +85.9375f,8.97782f,246.094f, +85.9375f,10.4624f,250.0f, +89.8438f,11.0829f,246.094f, +89.8438f,11.6403f,250.0f, +93.75f,12.3286f,246.094f, +93.75f,13.1378f,250.0f, +97.6563f,13.5966f,246.094f, +97.6563f,14.2949f,250.0f, +101.563f,15.5602f,246.094f, +101.563f,16.9487f,250.0f, +105.469f,16.9944f,246.094f, +105.469f,18.1946f,250.0f, +109.375f,17.886f,246.094f, +109.375f,19.5101f,250.0f, +113.281f,18.9289f,246.094f, +113.281f,20.9286f,250.0f, +117.188f,18.9873f,246.094f, +117.188f,20.0636f,250.0f, +121.094f,18.4954f,246.094f, +121.094f,20.5657f,250.0f, +125.0f,20.1484f,246.094f, +125.0f,21.1466f,250.0f, +128.906f,20.5032f,246.094f, +128.906f,22.3026f,250.0f, +132.813f,21.212f,246.094f, +132.813f,22.9139f,250.0f, +136.719f,22.289f,246.094f, +136.719f,24.4671f,250.0f, +140.625f,23.2441f,246.094f, +140.625f,24.3276f,250.0f, +144.531f,22.4971f,246.094f, +144.531f,24.3128f,250.0f, +148.438f,22.6347f,246.094f, +148.438f,23.8291f,250.0f, +152.344f,23.5767f,246.094f, +152.344f,24.1369f,250.0f, +156.25f,25.193f,246.094f, +156.25f,24.9132f,250.0f, +160.156f,25.2521f,246.094f, +160.156f,24.7251f,250.0f, +164.063f,25.7424f,246.094f, +164.063f,24.1169f,250.0f, +167.969f,24.3269f,246.094f, +167.969f,24.6092f,250.0f, +171.875f,25.0479f,246.094f, +171.875f,24.967f,250.0f, +175.781f,25.0107f,246.094f, +175.781f,24.7879f,250.0f, +179.688f,23.583f,246.094f, +179.688f,22.6841f,250.0f, +183.594f,20.958f,246.094f, +183.594f,20.6584f,250.0f, +187.5f,19.7535f,246.094f, +187.5f,20.0313f,250.0f, +191.406f,20.4707f,246.094f, +191.406f,20.3896f,250.0f, +195.313f,19.7551f,246.094f, +195.313f,21.5643f,250.0f, +199.219f,19.698f,246.094f, +199.219f,21.5733f,250.0f, +203.125f,20.0732f,246.094f, +203.125f,20.38f,250.0f, +207.031f,19.8667f,246.094f, +207.031f,19.3779f,250.0f, +210.938f,19.4501f,246.094f, +210.938f,19.5994f,250.0f, +214.844f,19.2918f,246.094f, +214.844f,19.0966f,250.0f, +218.75f,18.7652f,246.094f, +218.75f,19.9256f,250.0f, +222.656f,18.8129f,246.094f, +222.656f,19.8704f,250.0f, +226.563f,18.3547f,246.094f, +226.563f,18.8671f,250.0f, +230.469f,16.9801f,246.094f, +230.469f,17.4931f,250.0f, +234.375f,15.6173f,246.094f, +234.375f,16.1699f,250.0f, +238.281f,15.549f,246.094f, +238.281f,15.3704f,250.0f, +242.188f,15.2468f,246.094f, +242.188f,15.0306f,250.0f, +246.094f,14.1325f,246.094f, +246.094f,14.2622f,250.0f, +250.0f,14.4063f,246.094f, +250.0f,14.3657f,250.0f, +3.90626f,2.21488f,242.188f, +7.81252f,2.28606f,242.188f, +11.7188f,3.88428f,242.188f, +15.625f,3.39117f,242.188f, +19.5313f,3.64824f,242.188f, +23.4375f,4.14072f,242.188f, +27.3438f,5.74104f,242.188f, +31.25f,6.66142f,242.188f, +35.1563f,7.31371f,242.188f, +39.0625f,7.68371f,242.188f, +42.9688f,6.99041f,242.188f, +46.875f,4.89778f,242.188f, +50.7813f,2.64913f,242.188f, +54.6875f,2.76175f,242.188f, +58.5938f,3.10499f,242.188f, +62.5f,4.61915f,242.188f, +66.4063f,5.36769f,242.188f, +70.3125f,5.41759f,242.188f, +74.2188f,5.42279f,242.188f, +78.125f,5.53934f,242.188f, +82.0313f,5.38421f,242.188f, +85.9375f,7.77227f,242.188f, +89.8438f,9.40622f,242.188f, +93.75f,11.2904f,242.188f, +97.6563f,12.0748f,242.188f, +101.563f,14.1058f,242.188f, +105.469f,15.1513f,242.188f, +109.375f,15.9477f,242.188f, +113.281f,16.843f,242.188f, +117.188f,17.2117f,242.188f, +121.094f,18.2641f,242.188f, +125.0f,18.8672f,242.188f, +128.906f,19.3239f,242.188f, +132.813f,20.1067f,242.188f, +136.719f,20.8307f,242.188f, +140.625f,21.3646f,242.188f, +144.531f,21.6047f,242.188f, +148.438f,22.2456f,242.188f, +152.344f,23.5103f,242.188f, +156.25f,24.8533f,242.188f, +160.156f,25.4504f,242.188f, +164.063f,25.9357f,242.188f, +167.969f,24.8535f,242.188f, +171.875f,25.3099f,242.188f, +175.781f,25.3494f,242.188f, +179.688f,24.2229f,242.188f, +183.594f,21.0829f,242.188f, +187.5f,19.574f,242.188f, +191.406f,19.9835f,242.188f, +195.313f,19.6061f,242.188f, +199.219f,18.9509f,242.188f, +203.125f,20.1818f,242.188f, +207.031f,19.2962f,242.188f, +210.938f,18.8908f,242.188f, +214.844f,18.7996f,242.188f, +218.75f,18.7982f,242.188f, +222.656f,18.3283f,242.188f, +226.563f,17.7287f,242.188f, +230.469f,15.6882f,242.188f, +234.375f,15.2468f,242.188f, +238.281f,15.2703f,242.188f, +242.188f,14.4812f,242.188f, +246.094f,14.5597f,242.188f, +250.0f,14.178f,242.188f, +3.90626f,3.04396f,238.281f, +7.81252f,3.88428f,238.281f, +11.7188f,4.51367f,238.281f, +15.625f,4.1993f,238.281f, +19.5313f,4.48585f,238.281f, +23.4375f,5.11452f,238.281f, +27.3438f,4.98441f,238.281f, +31.25f,5.77536f,238.281f, +35.1563f,5.42743f,238.281f, +39.0625f,6.4581f,238.281f, +42.9688f,5.55272f,238.281f, +46.875f,3.69555f,238.281f, +50.7813f,3.08321f,238.281f, +54.6875f,2.96664f,238.281f, +58.5938f,3.94595f,238.281f, +62.5f,4.71605f,238.281f, +66.4063f,5.07906f,238.281f, +70.3125f,5.39291f,238.281f, +74.2188f,4.29289f,238.281f, +78.125f,4.20855f,238.281f, +82.0313f,5.10829f,238.281f, +85.9375f,5.48654f,238.281f, +89.8438f,7.06082f,238.281f, +93.75f,8.6827f,238.281f, +97.6563f,9.99779f,238.281f, +101.563f,11.9757f,238.281f, +105.469f,12.9031f,238.281f, +109.375f,13.7947f,238.281f, +113.281f,13.6154f,238.281f, +117.188f,15.9897f,238.281f, +121.094f,18.0884f,238.281f, +125.0f,18.714f,238.281f, +128.906f,19.1457f,238.281f, +132.813f,20.0791f,238.281f, +136.719f,20.3929f,238.281f, +140.625f,20.8277f,238.281f, +144.531f,21.2111f,238.281f, +148.438f,22.5091f,238.281f, +152.344f,23.9188f,238.281f, +156.25f,25.0278f,238.281f, +160.156f,25.8335f,238.281f, +164.063f,25.6558f,238.281f, +167.969f,24.3663f,238.281f, +171.875f,30.6775f,238.281f, +175.781f,30.89f,238.281f, +179.688f,29.2543f,238.281f, +183.594f,26.6241f,238.281f, +187.5f,24.7124f,238.281f, +191.406f,23.7048f,238.281f, +195.313f,23.3839f,238.281f, +199.219f,23.312f,238.281f, +203.125f,17.5221f,238.281f, +207.031f,17.418f,238.281f, +210.938f,17.5259f,238.281f, +214.844f,18.2392f,238.281f, +218.75f,18.6793f,238.281f, +222.656f,18.3701f,238.281f, +226.563f,17.2487f,238.281f, +230.469f,16.4f,238.281f, +234.375f,15.4998f,238.281f, +238.281f,14.6207f,238.281f, +242.188f,14.3055f,238.281f, +246.094f,14.2255f,238.281f, +250.0f,14.1326f,238.281f, +3.90626f,5.19166f,234.375f, +7.81252f,4.93292f,234.375f, +11.7188f,4.03413f,234.375f, +15.625f,3.70957f,234.375f, +19.5313f,4.44484f,234.375f, +23.4375f,5.12277f,234.375f, +27.3438f,4.60029f,234.375f, +31.25f,4.55048f,234.375f, +35.1563f,4.78512f,234.375f, +39.0625f,4.94627f,234.375f, +42.9688f,5.03351f,234.375f, +46.875f,3.08166f,234.375f, +50.7813f,2.57752f,234.375f, +54.6875f,3.08533f,234.375f, +58.5938f,4.0254f,234.375f, +62.5f,4.57575f,234.375f, +66.4063f,4.67125f,234.375f, +70.3125f,4.5612f,234.375f, +74.2188f,4.232f,234.375f, +78.125f,4.1571f,234.375f, +82.0313f,4.20157f,234.375f, +85.9375f,4.29102f,234.375f, +89.8438f,5.54826f,234.375f, +93.75f,7.06094f,234.375f, +97.6563f,8.27366f,234.375f, +101.563f,9.83852f,234.375f, +105.469f,10.9262f,234.375f, +109.375f,11.7812f,234.375f, +113.281f,13.8453f,234.375f, +117.188f,15.5538f,234.375f, +121.094f,16.8977f,234.375f, +125.0f,18.2996f,234.375f, +128.906f,19.6512f,234.375f, +132.813f,19.411f,234.375f, +136.719f,19.3317f,234.375f, +140.625f,20.656f,234.375f, +144.531f,21.6048f,234.375f, +148.438f,22.2246f,234.375f, +152.344f,23.6649f,234.375f, +156.25f,24.8772f,234.375f, +160.156f,27.6423f,234.375f, +164.063f,29.4442f,234.375f, +167.969f,29.6691f,234.375f, +171.875f,30.0772f,234.375f, +175.781f,30.3189f,234.375f, +179.688f,28.7319f,234.375f, +183.594f,26.6952f,234.375f, +187.5f,25.3375f,234.375f, +191.406f,24.1666f,234.375f, +195.313f,22.5458f,234.375f, +199.219f,22.2182f,234.375f, +203.125f,22.2413f,234.375f, +207.031f,21.8533f,234.375f, +210.938f,17.4596f,234.375f, +214.844f,17.2677f,234.375f, +218.75f,16.9584f,234.375f, +222.656f,16.6188f,234.375f, +226.563f,17.4388f,234.375f, +230.469f,16.936f,234.375f, +234.375f,15.6181f,234.375f, +238.281f,15.8373f,234.375f, +242.188f,15.0881f,234.375f, +246.094f,14.2247f,234.375f, +250.0f,14.111f,234.375f, +3.90626f,5.885f,230.469f, +7.81251f,5.4786f,230.469f, +11.7188f,5.0584f,230.469f, +15.625f,4.10283f,230.469f, +19.5313f,4.10569f,230.469f, +23.4375f,4.42202f,230.469f, +27.3438f,4.27849f,230.469f, +31.25f,4.25612f,230.469f, +35.1563f,3.83542f,230.469f, +39.0625f,3.37515f,230.469f, +42.9688f,4.16288f,230.469f, +46.875f,2.84197f,230.469f, +50.7813f,2.83467f,230.469f, +54.6875f,3.07874f,230.469f, +58.5938f,3.37745f,230.469f, +62.5f,4.09612f,230.469f, +66.4063f,4.65777f,230.469f, +70.3125f,4.45712f,230.469f, +74.2188f,3.89296f,230.469f, +78.125f,3.87471f,230.469f, +82.0313f,4.64568f,230.469f, +85.9375f,5.82987f,230.469f, +89.8438f,6.40084f,230.469f, +93.75f,7.65914f,230.469f, +97.6563f,8.07052f,230.469f, +101.563f,9.86632f,230.469f, +105.469f,11.8636f,230.469f, +109.375f,12.9547f,230.469f, +113.281f,14.2745f,230.469f, +117.188f,15.6876f,230.469f, +121.094f,17.2089f,230.469f, +125.0f,18.1267f,230.469f, +128.906f,19.379f,230.469f, +132.813f,19.2097f,230.469f, +136.719f,18.9335f,230.469f, +140.625f,19.9763f,230.469f, +144.531f,21.5401f,230.469f, +148.438f,21.7302f,230.469f, +152.344f,23.0108f,230.469f, +156.25f,28.7387f,230.469f, +160.156f,28.4179f,230.469f, +164.063f,28.6483f,230.469f, +167.969f,29.5567f,230.469f, +171.875f,29.589f,230.469f, +175.781f,29.7943f,230.469f, +179.688f,28.0587f,230.469f, +183.594f,27.6387f,230.469f, +187.5f,26.92f,230.469f, +191.406f,25.7995f,230.469f, +195.313f,23.8573f,230.469f, +199.219f,22.1543f,230.469f, +203.125f,21.8606f,230.469f, +207.031f,21.7644f,230.469f, +210.938f,22.284f,230.469f, +214.844f,22.465f,230.469f, +218.75f,16.4018f,230.469f, +222.656f,16.1053f,230.469f, +226.563f,16.9553f,230.469f, +230.469f,16.9851f,230.469f, +234.375f,16.0967f,230.469f, +238.281f,15.9758f,230.469f, +242.188f,15.3258f,230.469f, +246.094f,15.2909f,230.469f, +250.0f,14.7208f,230.469f, +3.90626f,6.89682f,226.563f, +7.81251f,6.58742f,226.563f, +11.7188f,6.03516f,226.563f, +15.625f,4.72243f,226.563f, +19.5313f,3.6445f,226.563f, +23.4375f,4.35761f,226.563f, +27.3438f,4.11714f,226.563f, +31.25f,4.31125f,226.563f, +35.1563f,3.42415f,226.563f, +39.0625f,2.29216f,226.563f, +42.9688f,2.47915f,226.563f, +46.875f,2.26767f,226.563f, +50.7813f,1.11914f,226.563f, +54.6875f,2.43266f,226.563f, +58.5938f,3.88718f,226.563f, +62.5f,3.9963f,226.563f, +66.4063f,4.30547f,226.563f, +70.3125f,4.43739f,226.563f, +74.2188f,3.89069f,226.563f, +78.125f,4.12082f,226.563f, +82.0313f,5.53252f,226.563f, +85.9375f,6.38493f,226.563f, +89.8438f,6.79959f,226.563f, +93.75f,8.29598f,226.563f, +97.6563f,8.48723f,226.563f, +101.563f,9.93554f,226.563f, +105.469f,11.5657f,226.563f, +109.375f,13.0486f,226.563f, +113.281f,13.8621f,226.563f, +117.188f,14.9688f,226.563f, +121.094f,16.3799f,226.563f, +125.0f,17.1973f,226.563f, +128.906f,17.376f,226.563f, +132.813f,18.1073f,226.563f, +136.719f,18.6844f,226.563f, +140.625f,18.5161f,226.563f, +144.531f,20.7617f,226.563f, +148.438f,21.0578f,226.563f, +152.344f,26.44f,226.563f, +156.25f,27.1807f,226.563f, +160.156f,27.2962f,226.563f, +164.063f,28.0507f,226.563f, +167.969f,28.6572f,226.563f, +171.875f,28.3487f,226.563f, +175.781f,23.7294f,226.563f, +179.688f,23.1113f,226.563f, +183.594f,22.5708f,226.563f, +187.5f,22.6165f,226.563f, +191.406f,21.8697f,226.563f, +195.313f,19.9841f,226.563f, +199.219f,22.9835f,226.563f, +203.125f,22.0743f,226.563f, +207.031f,22.4886f,226.563f, +210.938f,22.2516f,226.563f, +214.844f,22.3739f,226.563f, +218.75f,22.7815f,226.563f, +222.656f,17.0366f,226.563f, +226.563f,16.1334f,226.563f, +230.469f,16.9265f,226.563f, +234.375f,17.1793f,226.563f, +238.281f,17.3365f,226.563f, +242.188f,16.1971f,226.563f, +246.094f,15.2775f,226.563f, +250.0f,15.1313f,226.563f, +3.90626f,6.81349f,222.656f, +7.81251f,7.23848f,222.656f, +11.7188f,6.09864f,222.656f, +15.625f,4.9545f,222.656f, +19.5313f,3.88133f,222.656f, +23.4375f,4.06964f,222.656f, +27.3438f,3.90589f,222.656f, +31.25f,4.08304f,222.656f, +35.1563f,3.26204f,222.656f, +39.0625f,1.53457f,222.656f, +42.9688f,1.90835f,222.656f, +46.875f,1.98509f,222.656f, +50.7813f,2.14652f,222.656f, +54.6875f,2.7418f,222.656f, +58.5938f,3.74695f,222.656f, +62.5f,4.00354f,222.656f, +66.4063f,4.38792f,222.656f, +70.3125f,3.93121f,222.656f, +74.2188f,3.42647f,222.656f, +78.125f,5.0562f,222.656f, +82.0313f,5.98572f,222.656f, +85.9375f,6.52919f,222.656f, +89.8438f,6.83394f,222.656f, +93.75f,7.48974f,222.656f, +97.6563f,8.19267f,222.656f, +101.563f,9.33438f,222.656f, +105.469f,11.8423f,222.656f, +109.375f,13.1158f,222.656f, +113.281f,13.8944f,222.656f, +117.188f,14.8014f,222.656f, +121.094f,15.4129f,222.656f, +125.0f,15.6942f,222.656f, +128.906f,16.2049f,222.656f, +132.813f,17.0318f,222.656f, +136.719f,18.5423f,222.656f, +140.625f,18.8685f,222.656f, +144.531f,19.4529f,222.656f, +148.438f,25.9153f,222.656f, +152.344f,25.6773f,222.656f, +156.25f,26.0432f,222.656f, +160.156f,26.3016f,222.656f, +164.063f,27.084f,222.656f, +167.969f,27.1073f,222.656f, +171.875f,22.7536f,222.656f, +175.781f,23.3785f,222.656f, +179.688f,23.0862f,222.656f, +183.594f,22.5993f,222.656f, +187.5f,22.0197f,222.656f, +191.406f,21.8352f,222.656f, +195.313f,20.0501f,222.656f, +199.219f,18.5797f,222.656f, +203.125f,18.2905f,222.656f, +207.031f,22.7876f,222.656f, +210.938f,21.9787f,222.656f, +214.844f,21.4782f,222.656f, +218.75f,21.5786f,222.656f, +222.656f,21.6231f,222.656f, +226.563f,17.8058f,222.656f, +230.469f,17.6169f,222.656f, +234.375f,18.3242f,222.656f, +238.281f,18.4847f,222.656f, +242.188f,17.3189f,222.656f, +246.094f,16.7726f,222.656f, +250.0f,16.587f,222.656f, +3.90627f,8.02546f,218.75f, +7.81251f,8.24803f,218.75f, +11.7188f,6.92174f,218.75f, +15.625f,5.86085f,218.75f, +19.5313f,4.56603f,218.75f, +23.4375f,3.6909f,218.75f, +27.3438f,4.26522f,218.75f, +31.25f,3.37783f,218.75f, +35.1563f,1.72339f,218.75f, +39.0625f,2.22205f,218.75f, +42.9688f,2.71848f,218.75f, +46.875f,3.1467f,218.75f, +50.7813f,3.05327f,218.75f, +54.6875f,3.19537f,218.75f, +58.5938f,3.68243f,218.75f, +62.5f,3.35279f,218.75f, +66.4063f,4.00402f,218.75f, +70.3125f,2.9244f,218.75f, +74.2188f,4.39027f,218.75f, +78.125f,5.55878f,218.75f, +82.0313f,6.38772f,218.75f, +85.9375f,6.34964f,218.75f, +89.8438f,6.80441f,218.75f, +93.75f,6.5829f,218.75f, +97.6563f,7.27657f,218.75f, +101.563f,9.67388f,218.75f, +105.469f,10.833f,218.75f, +109.375f,12.1666f,218.75f, +113.281f,13.2095f,218.75f, +117.188f,14.2491f,218.75f, +121.094f,14.6953f,218.75f, +125.0f,14.2707f,218.75f, +128.906f,15.9556f,218.75f, +132.813f,16.7068f,218.75f, +136.719f,17.6679f,218.75f, +140.625f,18.8257f,218.75f, +144.531f,24.2255f,218.75f, +148.438f,25.0749f,218.75f, +152.344f,25.9271f,218.75f, +156.25f,26.2032f,218.75f, +160.156f,24.5168f,218.75f, +164.063f,26.2403f,218.75f, +167.969f,26.6223f,218.75f, +171.875f,22.4271f,218.75f, +175.781f,23.7925f,218.75f, +179.688f,23.3478f,218.75f, +183.594f,22.2279f,218.75f, +187.5f,22.2148f,218.75f, +191.406f,20.7538f,218.75f, +195.313f,19.5131f,218.75f, +199.219f,19.4834f,218.75f, +203.125f,18.3756f,218.75f, +207.031f,18.1034f,218.75f, +210.938f,20.0003f,218.75f, +214.844f,22.2111f,218.75f, +218.75f,21.6123f,218.75f, +222.656f,22.5943f,218.75f, +226.563f,24.3115f,218.75f, +230.469f,19.0536f,218.75f, +234.375f,18.6613f,218.75f, +238.281f,18.7675f,218.75f, +242.188f,18.3163f,218.75f, +246.094f,16.7013f,218.75f, +250.0f,17.0786f,218.75f, +3.90627f,9.25513f,214.844f, +7.81251f,9.67426f,214.844f, +11.7188f,8.92139f,214.844f, +15.625f,6.90738f,214.844f, +19.5313f,6.12616f,214.844f, +23.4375f,4.98302f,214.844f, +27.3438f,3.63786f,214.844f, +31.25f,2.52097f,214.844f, +35.1563f,3.30816f,214.844f, +39.0625f,4.04406f,214.844f, +42.9688f,4.48446f,214.844f, +46.875f,4.40695f,214.844f, +50.7813f,3.7693f,214.844f, +54.6875f,2.85523f,214.844f, +58.5938f,2.56849f,214.844f, +62.5f,2.56561f,214.844f, +66.4063f,2.82937f,214.844f, +70.3125f,2.75221f,214.844f, +74.2188f,5.02974f,214.844f, +78.125f,5.7988f,214.844f, +82.0313f,6.03219f,214.844f, +85.9375f,6.27423f,214.844f, +89.8438f,6.1671f,214.844f, +93.75f,6.86893f,214.844f, +97.6563f,7.94747f,214.844f, +101.563f,9.13548f,214.844f, +105.469f,9.63636f,214.844f, +109.375f,10.3351f,214.844f, +113.281f,12.4028f,214.844f, +117.188f,13.0321f,214.844f, +121.094f,13.6284f,214.844f, +125.0f,14.3167f,214.844f, +128.906f,15.0573f,214.844f, +132.813f,16.2022f,214.844f, +136.719f,17.7526f,214.844f, +140.625f,23.7093f,214.844f, +144.531f,24.3603f,214.844f, +148.438f,24.9195f,214.844f, +152.344f,25.198f,214.844f, +156.25f,20.8225f,214.844f, +160.156f,24.5918f,214.844f, +164.063f,25.1404f,214.844f, +167.969f,26.0659f,214.844f, +171.875f,22.1485f,214.844f, +175.781f,27.7236f,214.844f, +179.688f,27.4914f,214.844f, +183.594f,26.6606f,214.844f, +187.5f,26.623f,214.844f, +191.406f,26.3244f,214.844f, +195.313f,24.8535f,214.844f, +199.219f,23.6373f,214.844f, +203.125f,21.1881f,214.844f, +207.031f,19.7509f,214.844f, +210.938f,22.3046f,214.844f, +214.844f,22.5297f,214.844f, +218.75f,22.9498f,214.844f, +222.656f,23.2271f,214.844f, +226.563f,24.89f,214.844f, +230.469f,23.5226f,214.844f, +234.375f,19.0463f,214.844f, +238.281f,17.96f,214.844f, +242.188f,18.8106f,214.844f, +246.094f,17.3168f,214.844f, +250.0f,16.7955f,214.844f, +3.90627f,10.5728f,210.938f, +7.81251f,9.81018f,210.938f, +11.7188f,9.69715f,210.938f, +15.625f,8.42137f,210.938f, +19.5313f,7.09174f,210.938f, +23.4375f,6.45357f,210.938f, +27.3438f,4.58257f,210.938f, +31.25f,4.31044f,210.938f, +35.1563f,4.23584f,210.938f, +39.0625f,4.77527f,210.938f, +42.9688f,5.51217f,210.938f, +46.875f,5.48962f,210.938f, +50.7813f,4.50211f,210.938f, +54.6875f,4.06287f,210.938f, +58.5938f,3.43161f,210.938f, +62.5f,3.43195f,210.938f, +66.4063f,3.64204f,210.938f, +70.3125f,5.16151f,210.938f, +74.2188f,6.72853f,210.938f, +78.125f,7.43878f,210.938f, +82.0313f,7.30716f,210.938f, +85.9375f,6.54327f,210.938f, +89.8438f,5.96003f,210.938f, +93.75f,6.45099f,210.938f, +97.6563f,8.32748f,210.938f, +101.563f,8.85186f,210.938f, +105.469f,9.64058f,210.938f, +109.375f,10.4181f,210.938f, +113.281f,11.6911f,210.938f, +117.188f,12.0508f,210.938f, +121.094f,13.1004f,210.938f, +125.0f,14.4899f,210.938f, +128.906f,15.1295f,210.938f, +132.813f,15.6195f,210.938f, +136.719f,16.9219f,210.938f, +140.625f,23.4614f,210.938f, +144.531f,24.6763f,210.938f, +148.438f,26.12f,210.938f, +152.344f,21.7533f,210.938f, +156.25f,20.7448f,210.938f, +160.156f,24.1481f,210.938f, +164.063f,26.0464f,210.938f, +167.969f,25.1633f,210.938f, +171.875f,20.8056f,210.938f, +175.781f,26.3651f,210.938f, +179.688f,25.5322f,210.938f, +183.594f,26.3828f,210.938f, +187.5f,26.3586f,210.938f, +191.406f,26.1714f,210.938f, +195.313f,25.9695f,210.938f, +199.219f,24.3505f,210.938f, +203.125f,23.872f,210.938f, +207.031f,23.0401f,210.938f, +210.938f,22.3904f,210.938f, +214.844f,22.7647f,210.938f, +218.75f,23.266f,210.938f, +222.656f,23.8563f,210.938f, +226.563f,24.6635f,210.938f, +230.469f,24.3846f,210.938f, +234.375f,18.3213f,210.938f, +238.281f,17.6531f,210.938f, +242.188f,17.8854f,210.938f, +246.094f,17.1692f,210.938f, +250.0f,16.127f,210.938f, +3.90626f,10.4539f,207.031f, +7.81251f,10.0241f,207.031f, +11.7188f,10.3861f,207.031f, +15.625f,8.84417f,207.031f, +19.5313f,8.35477f,207.031f, +23.4375f,6.48112f,207.031f, +27.3438f,6.10753f,207.031f, +31.25f,6.13796f,207.031f, +35.1563f,6.51045f,207.031f, +39.0625f,6.65278f,207.031f, +42.9688f,6.27698f,207.031f, +46.875f,5.80577f,207.031f, +50.7813f,5.90354f,207.031f, +54.6875f,5.66137f,207.031f, +58.5938f,4.67472f,207.031f, +62.5f,4.81103f,207.031f, +66.4063f,6.06764f,207.031f, +70.3125f,7.61387f,207.031f, +74.2188f,8.72682f,207.031f, +78.125f,9.33231f,207.031f, +82.0313f,8.49751f,207.031f, +85.9375f,7.85293f,207.031f, +89.8438f,7.37573f,207.031f, +93.75f,7.4561f,207.031f, +97.6563f,7.76623f,207.031f, +101.563f,8.68264f,207.031f, +105.469f,10.4373f,207.031f, +109.375f,10.4722f,207.031f, +113.281f,11.4418f,207.031f, +117.188f,12.3081f,207.031f, +121.094f,12.9224f,207.031f, +125.0f,14.3204f,207.031f, +128.906f,15.1746f,207.031f, +132.813f,14.4847f,207.031f, +136.719f,20.974f,207.031f, +140.625f,23.4669f,207.031f, +144.531f,24.9918f,207.031f, +148.438f,25.7345f,207.031f, +152.344f,21.4943f,207.031f, +156.25f,22.169f,207.031f, +160.156f,24.9739f,207.031f, +164.063f,26.4423f,207.031f, +167.969f,25.8928f,207.031f, +171.875f,20.5408f,207.031f, +175.781f,24.2294f,207.031f, +179.688f,24.4008f,207.031f, +183.594f,25.2809f,207.031f, +187.5f,25.8589f,207.031f, +191.406f,26.3716f,207.031f, +195.313f,26.0525f,207.031f, +199.219f,24.6109f,207.031f, +203.125f,24.1128f,207.031f, +207.031f,23.4731f,207.031f, +210.938f,22.6487f,207.031f, +214.844f,22.7977f,207.031f, +218.75f,18.4754f,207.031f, +222.656f,23.1848f,207.031f, +226.563f,23.1818f,207.031f, +230.469f,22.9194f,207.031f, +234.375f,19.8052f,207.031f, +238.281f,16.8602f,207.031f, +242.188f,17.1047f,207.031f, +246.094f,16.1145f,207.031f, +250.0f,15.0049f,207.031f, +3.90626f,11.4706f,203.125f, +7.81251f,11.0922f,203.125f, +11.7188f,11.454f,203.125f, +15.625f,10.399f,203.125f, +19.5313f,8.89365f,203.125f, +23.4375f,7.52605f,203.125f, +27.3438f,7.07779f,203.125f, +31.25f,7.98082f,203.125f, +35.1563f,8.78342f,203.125f, +39.0625f,8.87165f,203.125f, +42.9688f,8.39122f,203.125f, +46.875f,7.48032f,203.125f, +50.7813f,6.77944f,203.125f, +54.6875f,7.14862f,203.125f, +58.5938f,6.46173f,203.125f, +62.5f,6.73824f,203.125f, +66.4063f,7.64505f,203.125f, +70.3125f,9.22763f,203.125f, +74.2188f,9.87781f,203.125f, +78.125f,10.1574f,203.125f, +82.0313f,9.81606f,203.125f, +85.9375f,9.8669f,203.125f, +89.8438f,10.0032f,203.125f, +93.75f,9.76597f,203.125f, +97.6563f,9.2129f,203.125f, +101.563f,8.89917f,203.125f, +105.469f,9.85112f,203.125f, +109.375f,11.4827f,203.125f, +113.281f,11.8911f,203.125f, +117.188f,12.3305f,203.125f, +121.094f,13.6098f,203.125f, +125.0f,14.1477f,203.125f, +128.906f,14.7928f,203.125f, +132.813f,16.3422f,203.125f, +136.719f,22.7583f,203.125f, +140.625f,24.5881f,203.125f, +144.531f,25.3565f,203.125f, +148.438f,21.7799f,203.125f, +152.344f,24.1222f,203.125f, +156.25f,26.6774f,203.125f, +160.156f,25.7031f,203.125f, +164.063f,26.9766f,203.125f, +167.969f,25.936f,203.125f, +171.875f,19.7727f,203.125f, +175.781f,19.3015f,203.125f, +179.688f,19.2421f,203.125f, +183.594f,24.8014f,203.125f, +187.5f,25.3041f,203.125f, +191.406f,25.3226f,203.125f, +195.313f,20.0369f,203.125f, +199.219f,19.4927f,203.125f, +203.125f,23.4349f,203.125f, +207.031f,22.748f,203.125f, +210.938f,22.4583f,203.125f, +214.844f,18.8936f,203.125f, +218.75f,17.4565f,203.125f, +222.656f,18.8235f,203.125f, +226.563f,21.4749f,203.125f, +230.469f,21.7691f,203.125f, +234.375f,21.1398f,203.125f, +238.281f,15.9012f,203.125f, +242.188f,15.9735f,203.125f, +246.094f,15.2287f,203.125f, +250.0f,13.5655f,203.125f, +3.90626f,12.1184f,199.219f, +7.81251f,12.3652f,199.219f, +11.7188f,12.1177f,199.219f, +15.625f,11.107f,199.219f, +19.5313f,9.91183f,199.219f, +23.4375f,8.6581f,199.219f, +27.3438f,7.98212f,199.219f, +31.25f,9.14995f,199.219f, +35.1563f,10.2879f,199.219f, +39.0625f,10.2569f,199.219f, +42.9688f,9.58908f,199.219f, +46.875f,8.1296f,199.219f, +50.7813f,7.81944f,199.219f, +54.6875f,8.54521f,199.219f, +58.5938f,8.14627f,199.219f, +62.5f,8.60974f,199.219f, +66.4063f,9.63518f,199.219f, +70.3125f,10.5321f,199.219f, +74.2188f,10.3348f,199.219f, +78.125f,11.2806f,199.219f, +82.0313f,11.3874f,199.219f, +85.9375f,11.6949f,199.219f, +89.8438f,12.3833f,199.219f, +93.75f,12.4654f,199.219f, +97.6563f,11.369f,199.219f, +101.563f,10.2737f,199.219f, +105.469f,10.4291f,199.219f, +109.375f,11.0962f,199.219f, +113.281f,12.1388f,199.219f, +117.188f,12.5535f,199.219f, +121.094f,13.2826f,199.219f, +125.0f,15.1899f,199.219f, +128.906f,16.3486f,199.219f, +132.813f,17.6147f,199.219f, +136.719f,23.878f,199.219f, +140.625f,24.5901f,199.219f, +144.531f,26.2181f,199.219f, +148.438f,21.847f,199.219f, +152.344f,26.5018f,199.219f, +156.25f,26.2772f,199.219f, +160.156f,26.4621f,199.219f, +164.063f,26.1902f,199.219f, +167.969f,26.1086f,199.219f, +171.875f,20.7414f,199.219f, +175.781f,20.393f,199.219f, +179.688f,19.7885f,199.219f, +183.594f,20.9687f,199.219f, +187.5f,23.8625f,199.219f, +191.406f,24.0825f,199.219f, +195.313f,19.4921f,199.219f, +199.219f,20.8763f,199.219f, +203.125f,21.987f,199.219f, +207.031f,21.9212f,199.219f, +210.938f,20.0341f,199.219f, +214.844f,15.7998f,199.219f, +218.75f,15.7759f,199.219f, +222.656f,15.8963f,199.219f, +226.563f,19.8168f,199.219f, +230.469f,19.9894f,199.219f, +234.375f,19.4382f,199.219f, +238.281f,14.2335f,199.219f, +242.188f,14.9225f,199.219f, +246.094f,13.5857f,199.219f, +250.0f,11.7225f,199.219f, +3.90626f,13.8013f,195.313f, +7.81251f,13.8046f,195.313f, +11.7188f,13.1462f,195.313f, +15.625f,12.2626f,195.313f, +19.5313f,10.67f,195.313f, +23.4375f,10.0372f,195.313f, +27.3438f,9.3255f,195.313f, +31.25f,10.5057f,195.313f, +35.1563f,11.0615f,195.313f, +39.0625f,11.2421f,195.313f, +42.9688f,10.4767f,195.313f, +46.875f,9.03042f,195.313f, +50.7813f,9.47397f,195.313f, +54.6875f,9.65703f,195.313f, +58.5938f,9.6345f,195.313f, +62.5f,9.9552f,195.313f, +66.4063f,10.8427f,195.313f, +70.3125f,11.7912f,195.313f, +74.2188f,11.5822f,195.313f, +78.125f,13.07f,195.313f, +82.0313f,13.803f,195.313f, +85.9375f,12.9764f,195.313f, +89.8438f,14.639f,195.313f, +93.75f,14.6139f,195.313f, +97.6563f,13.3162f,195.313f, +101.563f,12.7402f,195.313f, +105.469f,12.8061f,195.313f, +109.375f,12.1167f,195.313f, +113.281f,12.705f,195.313f, +117.188f,12.4568f,195.313f, +121.094f,13.5698f,195.313f, +125.0f,15.1843f,195.313f, +128.906f,16.7529f,195.313f, +132.813f,19.1744f,195.313f, +136.719f,23.9261f,195.313f, +140.625f,25.9824f,195.313f, +144.531f,26.1631f,195.313f, +148.438f,21.4735f,195.313f, +152.344f,25.5313f,195.313f, +156.25f,27.0098f,195.313f, +160.156f,27.5776f,195.313f, +164.063f,27.0858f,195.313f, +167.969f,26.3007f,195.313f, +171.875f,23.4599f,195.313f, +175.781f,26.4252f,195.313f, +179.688f,21.1453f,195.313f, +183.594f,21.1021f,195.313f, +187.5f,25.1644f,195.313f, +191.406f,24.8681f,195.313f, +195.313f,24.1757f,195.313f, +199.219f,20.0013f,195.313f, +203.125f,23.6085f,195.313f, +207.031f,22.7043f,195.313f, +210.938f,17.4097f,195.313f, +214.844f,16.8216f,195.313f, +218.75f,16.2595f,195.313f, +222.656f,15.547f,195.313f, +226.563f,20.5074f,195.313f, +230.469f,20.0296f,195.313f, +234.375f,19.4594f,195.313f, +238.281f,14.3376f,195.313f, +242.188f,13.8667f,195.313f, +246.094f,12.7786f,195.313f, +250.0f,12.669f,195.313f, +3.90626f,14.3936f,191.406f, +7.81251f,14.3324f,191.406f, +11.7188f,13.5165f,191.406f, +15.625f,12.3486f,191.406f, +19.5313f,10.8996f,191.406f, +23.4375f,10.767f,191.406f, +27.3438f,12.0663f,191.406f, +31.25f,12.0032f,191.406f, +35.1563f,12.6763f,191.406f, +39.0625f,12.4746f,191.406f, +42.9688f,10.9305f,191.406f, +46.875f,11.0794f,191.406f, +50.7813f,11.2588f,191.406f, +54.6875f,11.0855f,191.406f, +58.5938f,10.1448f,191.406f, +62.5f,11.1184f,191.406f, +66.4063f,12.2266f,191.406f, +70.3125f,12.3132f,191.406f, +74.2188f,13.6918f,191.406f, +78.125f,14.4314f,191.406f, +82.0313f,14.6924f,191.406f, +85.9375f,15.6669f,191.406f, +89.8438f,16.085f,191.406f, +93.75f,16.2697f,191.406f, +97.6563f,16.3584f,191.406f, +101.563f,15.6226f,191.406f, +105.469f,14.7096f,191.406f, +109.375f,14.172f,191.406f, +113.281f,13.6538f,191.406f, +117.188f,14.6791f,191.406f, +121.094f,15.1835f,191.406f, +125.0f,16.4947f,191.406f, +128.906f,17.5173f,191.406f, +132.813f,22.4657f,191.406f, +136.719f,25.2206f,191.406f, +140.625f,26.6814f,191.406f, +144.531f,27.4657f,191.406f, +148.438f,22.8092f,191.406f, +152.344f,22.336f,191.406f, +156.25f,29.0833f,191.406f, +160.156f,29.5204f,191.406f, +164.063f,29.4008f,191.406f, +167.969f,28.5038f,191.406f, +171.875f,27.7213f,191.406f, +175.781f,27.6884f,191.406f, +179.688f,25.8434f,191.406f, +183.594f,23.3048f,191.406f, +187.5f,27.635f,191.406f, +191.406f,26.1341f,191.406f, +195.313f,26.6792f,191.406f, +199.219f,22.747f,191.406f, +203.125f,22.8472f,191.406f, +207.031f,21.8628f,191.406f, +210.938f,20.5896f,191.406f, +214.844f,20.683f,191.406f, +218.75f,15.9904f,191.406f, +222.656f,16.3766f,191.406f, +226.563f,21.611f,191.406f, +230.469f,20.8727f,191.406f, +234.375f,20.2044f,191.406f, +238.281f,15.3358f,191.406f, +242.188f,14.7065f,191.406f, +246.094f,14.4372f,191.406f, +250.0f,14.1124f,191.406f, +3.90626f,14.1738f,187.5f, +7.81252f,14.5502f,187.5f, +11.7188f,13.6083f,187.5f, +15.625f,12.2654f,187.5f, +19.5313f,11.7405f,187.5f, +23.4375f,12.3756f,187.5f, +27.3438f,14.0775f,187.5f, +31.25f,13.9675f,187.5f, +35.1563f,14.3286f,187.5f, +39.0625f,13.1055f,187.5f, +42.9688f,13.0413f,187.5f, +46.875f,13.318f,187.5f, +50.7813f,12.9383f,187.5f, +54.6875f,12.9366f,187.5f, +58.5938f,12.1308f,187.5f, +62.5f,12.8501f,187.5f, +66.4063f,13.0312f,187.5f, +70.3125f,13.1657f,187.5f, +74.2188f,14.6177f,187.5f, +78.125f,16.1865f,187.5f, +82.0313f,16.3194f,187.5f, +85.9375f,16.9023f,187.5f, +89.8438f,17.5469f,187.5f, +93.75f,18.1166f,187.5f, +97.6563f,18.7398f,187.5f, +101.563f,18.2643f,187.5f, +105.469f,17.5115f,187.5f, +109.375f,16.8559f,187.5f, +113.281f,15.8332f,187.5f, +117.188f,16.4429f,187.5f, +121.094f,17.0698f,187.5f, +125.0f,18.0389f,187.5f, +128.906f,19.8697f,187.5f, +132.813f,24.8511f,187.5f, +136.719f,26.6838f,187.5f, +140.625f,28.5323f,187.5f, +144.531f,28.756f,187.5f, +148.438f,25.5762f,187.5f, +152.344f,25.8993f,187.5f, +156.25f,29.0469f,187.5f, +160.156f,32.1254f,187.5f, +164.063f,32.1318f,187.5f, +167.969f,31.7887f,187.5f, +171.875f,30.3727f,187.5f, +175.781f,30.1222f,187.5f, +179.688f,30.3556f,187.5f, +183.594f,30.49f,187.5f, +187.5f,29.3956f,187.5f, +191.406f,30.6569f,187.5f, +195.313f,30.8632f,187.5f, +199.219f,26.1118f,187.5f, +203.125f,25.5008f,187.5f, +207.031f,24.7878f,187.5f, +210.938f,27.5453f,187.5f, +214.844f,25.5271f,187.5f, +218.75f,20.2295f,187.5f, +222.656f,17.2785f,187.5f, +226.563f,22.0337f,187.5f, +230.469f,22.1938f,187.5f, +234.375f,21.6646f,187.5f, +238.281f,16.8654f,187.5f, +242.188f,15.704f,187.5f, +246.094f,15.9973f,187.5f, +250.0f,15.209f,187.5f, +3.90626f,13.9878f,183.594f, +7.81252f,14.3413f,183.594f, +11.7188f,13.1779f,183.594f, +15.625f,12.8538f,183.594f, +19.5313f,13.9436f,183.594f, +23.4375f,14.716f,183.594f, +27.3438f,14.991f,183.594f, +31.25f,15.4235f,183.594f, +35.1563f,15.3865f,183.594f, +39.0625f,14.2459f,183.594f, +42.9688f,15.2992f,183.594f, +46.875f,16.0599f,183.594f, +50.7813f,14.8603f,183.594f, +54.6875f,14.9726f,183.594f, +58.5938f,13.6053f,183.594f, +62.5f,13.057f,183.594f, +66.4063f,13.4201f,183.594f, +70.3125f,14.0782f,183.594f, +74.2188f,15.3178f,183.594f, +78.125f,16.3995f,183.594f, +82.0313f,17.4379f,183.594f, +85.9375f,17.9502f,183.594f, +89.8438f,18.4811f,183.594f, +93.75f,19.4227f,183.594f, +97.6563f,20.1694f,183.594f, +101.563f,20.1609f,183.594f, +105.469f,19.5537f,183.594f, +109.375f,19.039f,183.594f, +113.281f,18.2247f,183.594f, +117.188f,18.6643f,183.594f, +121.094f,19.2334f,183.594f, +125.0f,20.4158f,183.594f, +128.906f,21.1136f,183.594f, +132.813f,25.6638f,183.594f, +136.719f,27.4642f,183.594f, +140.625f,29.0749f,183.594f, +144.531f,30.6966f,183.594f, +148.438f,26.933f,183.594f, +152.344f,27.9984f,183.594f, +156.25f,28.4094f,183.594f, +160.156f,33.857f,183.594f, +164.063f,34.6528f,183.594f, +167.969f,33.405f,183.594f, +171.875f,31.8412f,183.594f, +175.781f,31.8788f,183.594f, +179.688f,32.395f,183.594f, +183.594f,32.8498f,183.594f, +187.5f,28.7385f,183.594f, +191.406f,33.6253f,183.594f, +195.313f,32.9673f,183.594f, +199.219f,31.8413f,183.594f, +203.125f,26.491f,183.594f, +207.031f,29.4589f,183.594f, +210.938f,28.7843f,183.594f, +214.844f,26.577f,183.594f, +218.75f,25.0304f,183.594f, +222.656f,18.7948f,183.594f, +226.563f,23.1467f,183.594f, +230.469f,22.3329f,183.594f, +234.375f,21.6877f,183.594f, +238.281f,16.4114f,183.594f, +242.188f,16.4672f,183.594f, +246.094f,16.3324f,183.594f, +250.0f,16.0497f,183.594f, +3.90626f,14.6785f,179.688f, +7.81252f,14.4582f,179.688f, +11.7188f,13.7379f,179.688f, +15.625f,13.9816f,179.688f, +19.5313f,14.9647f,179.688f, +23.4375f,15.3633f,179.688f, +27.3438f,16.1346f,179.688f, +31.25f,16.4088f,179.688f, +35.1563f,16.195f,179.688f, +39.0625f,16.1785f,179.688f, +42.9688f,17.2534f,179.688f, +46.875f,17.329f,179.688f, +50.7813f,16.0096f,179.688f, +54.6875f,15.4766f,179.688f, +58.5938f,14.0828f,179.688f, +62.5f,12.8927f,179.688f, +66.4063f,14.1195f,179.688f, +70.3125f,14.9421f,179.688f, +74.2188f,15.9015f,179.688f, +78.125f,17.3756f,179.688f, +82.0313f,18.6339f,179.688f, +85.9375f,19.7602f,179.688f, +89.8438f,19.8522f,179.688f, +93.75f,20.5838f,179.688f, +97.6563f,21.2938f,179.688f, +101.563f,21.1808f,179.688f, +105.469f,21.4575f,179.688f, +109.375f,21.1629f,179.688f, +113.281f,20.4789f,179.688f, +117.188f,20.5729f,179.688f, +121.094f,20.3917f,179.688f, +125.0f,21.8501f,179.688f, +128.906f,22.6846f,179.688f, +132.813f,23.4145f,179.688f, +136.719f,28.3033f,179.688f, +140.625f,30.5638f,179.688f, +144.531f,32.761f,179.688f, +148.438f,29.4434f,179.688f, +152.344f,30.346f,179.688f, +156.25f,31.7037f,179.688f, +160.156f,36.287f,179.688f, +164.063f,36.7423f,179.688f, +167.969f,35.7482f,179.688f, +171.875f,30.0008f,179.688f, +175.781f,29.6748f,179.688f, +179.688f,34.5316f,179.688f, +183.594f,34.4476f,179.688f, +187.5f,34.3489f,179.688f, +191.406f,33.4208f,179.688f, +195.313f,29.5511f,179.688f, +199.219f,28.9653f,179.688f, +203.125f,28.1749f,179.688f, +207.031f,30.5574f,179.688f, +210.938f,28.6513f,179.688f, +214.844f,27.1867f,179.688f, +218.75f,20.8455f,179.688f, +222.656f,20.3256f,179.688f, +226.563f,24.3717f,179.688f, +230.469f,23.2197f,179.688f, +234.375f,21.6566f,179.688f, +238.281f,16.2487f,179.688f, +242.188f,16.7759f,179.688f, +246.094f,16.5259f,179.688f, +250.0f,15.8782f,179.688f, +3.90626f,15.2963f,175.781f, +7.81252f,15.075f,175.781f, +11.7188f,14.8069f,175.781f, +15.625f,14.4469f,175.781f, +19.5313f,15.8073f,175.781f, +23.4375f,16.5419f,175.781f, +27.3438f,16.7791f,175.781f, +31.25f,17.1945f,175.781f, +35.1563f,16.9974f,175.781f, +39.0625f,16.9655f,175.781f, +42.9688f,17.7583f,175.781f, +46.875f,18.115f,175.781f, +50.7813f,16.6524f,175.781f, +54.6875f,15.897f,175.781f, +58.5938f,15.4613f,175.781f, +62.5f,14.3684f,175.781f, +66.4063f,15.0403f,175.781f, +70.3125f,15.9604f,175.781f, +74.2188f,16.9477f,175.781f, +78.125f,18.0563f,175.781f, +82.0313f,18.8971f,175.781f, +85.9375f,20.1037f,175.781f, +89.8438f,20.3627f,175.781f, +93.75f,20.0215f,175.781f, +97.6563f,20.8917f,175.781f, +101.563f,21.8702f,175.781f, +105.469f,22.7304f,175.781f, +109.375f,22.6873f,175.781f, +113.281f,21.4896f,175.781f, +117.188f,21.3864f,175.781f, +121.094f,22.4194f,175.781f, +125.0f,23.5751f,175.781f, +128.906f,23.9616f,175.781f, +132.813f,24.6066f,175.781f, +136.719f,30.8792f,175.781f, +140.625f,31.6572f,175.781f, +144.531f,34.2264f,175.781f, +148.438f,30.9611f,175.781f, +152.344f,35.8851f,175.781f, +156.25f,38.6379f,175.781f, +160.156f,39.1098f,175.781f, +164.063f,39.046f,175.781f, +167.969f,38.0327f,175.781f, +171.875f,36.6611f,175.781f, +175.781f,36.0664f,175.781f, +179.688f,36.1227f,175.781f, +183.594f,36.0705f,175.781f, +187.5f,35.9099f,175.781f, +191.406f,30.4106f,175.781f, +195.313f,30.0475f,175.781f, +199.219f,28.9213f,175.781f, +203.125f,32.8995f,175.781f, +207.031f,31.2376f,175.781f, +210.938f,30.0194f,175.781f, +214.844f,23.402f,175.781f, +218.75f,21.7271f,175.781f, +222.656f,20.0594f,175.781f, +226.563f,25.2266f,175.781f, +230.469f,24.1549f,175.781f, +234.375f,22.0418f,175.781f, +238.281f,15.6301f,175.781f, +242.188f,15.4767f,175.781f, +246.094f,15.8876f,175.781f, +250.0f,15.1339f,175.781f, +3.90626f,16.0791f,171.875f, +7.81251f,16.012f,171.875f, +11.7188f,15.027f,171.875f, +15.625f,15.1362f,171.875f, +19.5313f,16.3622f,171.875f, +23.4375f,16.7304f,171.875f, +27.3438f,17.228f,171.875f, +31.25f,16.4882f,171.875f, +35.1563f,16.5399f,171.875f, +39.0625f,17.5505f,171.875f, +42.9688f,17.6944f,171.875f, +46.875f,17.7481f,171.875f, +50.7813f,17.4568f,171.875f, +54.6875f,16.5655f,171.875f, +58.5938f,15.4313f,171.875f, +62.5f,14.962f,171.875f, +66.4063f,15.2516f,171.875f, +70.3125f,16.3088f,171.875f, +74.2188f,17.5354f,171.875f, +78.125f,18.5759f,171.875f, +82.0313f,19.1666f,171.875f, +85.9375f,19.8244f,171.875f, +89.8438f,20.6303f,171.875f, +93.75f,20.5635f,171.875f, +97.6563f,20.5768f,171.875f, +101.563f,21.542f,171.875f, +105.469f,22.5605f,171.875f, +109.375f,23.0118f,171.875f, +113.281f,22.6086f,171.875f, +117.188f,22.8502f,171.875f, +121.094f,23.2278f,171.875f, +125.0f,24.368f,171.875f, +128.906f,25.5759f,171.875f, +132.813f,27.7217f,171.875f, +136.719f,33.4581f,171.875f, +140.625f,33.4128f,171.875f, +144.531f,34.9465f,171.875f, +148.438f,31.4923f,171.875f, +152.344f,38.6707f,171.875f, +156.25f,40.2713f,171.875f, +160.156f,40.4155f,171.875f, +164.063f,41.0232f,171.875f, +167.969f,39.781f,171.875f, +171.875f,37.8376f,171.875f, +175.781f,38.0559f,171.875f, +179.688f,32.0147f,171.875f, +183.594f,35.2298f,171.875f, +187.5f,34.7221f,171.875f, +191.406f,31.5516f,171.875f, +195.313f,28.9984f,171.875f, +199.219f,29.8767f,171.875f, +203.125f,32.6404f,171.875f, +207.031f,31.3413f,171.875f, +210.938f,28.4132f,171.875f, +214.844f,22.9909f,171.875f, +218.75f,21.3955f,171.875f, +222.656f,25.3135f,171.875f, +226.563f,25.1463f,171.875f, +230.469f,23.4716f,171.875f, +234.375f,22.494f,171.875f, +238.281f,15.9351f,171.875f, +242.188f,15.2882f,171.875f, +246.094f,14.8463f,171.875f, +250.0f,14.5269f,171.875f, +3.90626f,17.1455f,167.969f, +7.81251f,16.6981f,167.969f, +11.7188f,16.5681f,167.969f, +15.625f,16.1667f,167.969f, +19.5313f,16.3523f,167.969f, +23.4375f,16.5389f,167.969f, +27.3438f,16.8075f,167.969f, +31.25f,17.1987f,167.969f, +35.1563f,17.86f,167.969f, +39.0625f,18.5438f,167.969f, +42.9688f,18.6718f,167.969f, +46.875f,17.9387f,167.969f, +50.7813f,17.5403f,167.969f, +54.6875f,17.4895f,167.969f, +58.5938f,16.9679f,167.969f, +62.5f,16.2192f,167.969f, +66.4063f,15.5699f,167.969f, +70.3125f,17.0017f,167.969f, +74.2188f,18.0147f,167.969f, +78.125f,18.9836f,167.969f, +82.0313f,19.8197f,167.969f, +85.9375f,19.8969f,167.969f, +89.8438f,20.6411f,167.969f, +93.75f,20.9768f,167.969f, +97.6563f,21.1498f,167.969f, +101.563f,21.3269f,167.969f, +105.469f,22.1153f,167.969f, +109.375f,22.208f,167.969f, +113.281f,23.2278f,167.969f, +117.188f,24.5722f,167.969f, +121.094f,25.3921f,167.969f, +125.0f,26.2683f,167.969f, +128.906f,28.138f,167.969f, +132.813f,29.9483f,167.969f, +136.719f,34.7607f,167.969f, +140.625f,35.3745f,167.969f, +144.531f,36.1401f,167.969f, +148.438f,38.0587f,167.969f, +152.344f,40.0092f,167.969f, +156.25f,40.9205f,167.969f, +160.156f,41.4664f,167.969f, +164.063f,41.8834f,167.969f, +167.969f,40.2863f,167.969f, +171.875f,38.4111f,167.969f, +175.781f,37.4971f,167.969f, +179.688f,32.0995f,167.969f, +183.594f,36.4852f,167.969f, +187.5f,34.5523f,167.969f, +191.406f,34.4101f,167.969f, +195.313f,29.577f,167.969f, +199.219f,33.7462f,167.969f, +203.125f,33.0191f,167.969f, +207.031f,31.6651f,167.969f, +210.938f,24.6623f,167.969f, +214.844f,22.6532f,167.969f, +218.75f,21.898f,167.969f, +222.656f,26.1764f,167.969f, +226.563f,24.7619f,167.969f, +230.469f,22.6772f,167.969f, +234.375f,17.6202f,167.969f, +238.281f,16.1581f,167.969f, +242.188f,14.7308f,167.969f, +246.094f,14.294f,167.969f, +250.0f,13.1169f,167.969f, +3.90627f,16.4621f,164.063f, +7.81251f,17.581f,164.063f, +11.7188f,17.7296f,164.063f, +15.625f,17.126f,164.063f, +19.5313f,17.3484f,164.063f, +23.4375f,17.9863f,164.063f, +27.3438f,18.6623f,164.063f, +31.25f,18.7934f,164.063f, +35.1563f,18.8245f,164.063f, +39.0625f,18.9554f,164.063f, +42.9688f,19.3152f,164.063f, +46.875f,18.5996f,164.063f, +50.7813f,18.0094f,164.063f, +54.6875f,17.5702f,164.063f, +58.5938f,17.5846f,164.063f, +62.5f,17.3718f,164.063f, +66.4063f,17.7189f,164.063f, +70.3125f,17.9805f,164.063f, +74.2188f,18.2986f,164.063f, +78.125f,18.9566f,164.063f, +82.0313f,20.4142f,164.063f, +85.9375f,20.5066f,164.063f, +89.8438f,20.7654f,164.063f, +93.75f,20.9457f,164.063f, +97.6563f,21.1078f,164.063f, +101.563f,20.7505f,164.063f, +105.469f,21.4615f,164.063f, +109.375f,22.8061f,164.063f, +113.281f,24.2655f,164.063f, +117.188f,24.815f,164.063f, +121.094f,26.3141f,164.063f, +125.0f,28.393f,164.063f, +128.906f,30.0565f,164.063f, +132.813f,31.4858f,164.063f, +136.719f,31.6549f,164.063f, +140.625f,37.0597f,164.063f, +144.531f,37.7613f,164.063f, +148.438f,38.9888f,164.063f, +152.344f,39.1482f,164.063f, +156.25f,36.6367f,164.063f, +160.156f,41.2606f,164.063f, +164.063f,42.2366f,164.063f, +167.969f,40.9757f,164.063f, +171.875f,33.9016f,164.063f, +175.781f,34.1798f,164.063f, +179.688f,33.0682f,164.063f, +183.594f,35.2269f,164.063f, +187.5f,35.1129f,164.063f, +191.406f,34.7006f,164.063f, +195.313f,30.1221f,164.063f, +199.219f,34.6592f,164.063f, +203.125f,33.6195f,164.063f, +207.031f,30.0546f,164.063f, +210.938f,24.8295f,164.063f, +214.844f,23.0298f,164.063f, +218.75f,26.5636f,164.063f, +222.656f,25.7973f,164.063f, +226.563f,23.7612f,164.063f, +230.469f,22.3646f,164.063f, +234.375f,16.1956f,164.063f, +238.281f,14.863f,164.063f, +242.188f,13.95f,164.063f, +246.094f,14.1968f,164.063f, +250.0f,13.2951f,164.063f, +3.90627f,16.628f,160.156f, +7.81251f,17.4268f,160.156f, +11.7188f,18.0363f,160.156f, +15.625f,18.1287f,160.156f, +19.5313f,18.6222f,160.156f, +23.4375f,18.2801f,160.156f, +27.3438f,18.5912f,160.156f, +31.25f,18.8635f,160.156f, +35.1563f,19.2193f,160.156f, +39.0625f,18.8821f,160.156f, +42.9688f,19.0078f,160.156f, +46.875f,19.3506f,160.156f, +50.7813f,17.8504f,160.156f, +54.6875f,18.5322f,160.156f, +58.5938f,18.2223f,160.156f, +62.5f,18.032f,160.156f, +66.4063f,18.574f,160.156f, +70.3125f,18.3835f,160.156f, +74.2188f,18.0842f,160.156f, +78.125f,19.8632f,160.156f, +82.0313f,20.9487f,160.156f, +85.9375f,20.6197f,160.156f, +89.8438f,20.5117f,160.156f, +93.75f,20.4182f,160.156f, +97.6563f,19.8654f,160.156f, +101.563f,20.1971f,160.156f, +105.469f,22.0419f,160.156f, +109.375f,23.4698f,160.156f, +113.281f,24.6461f,160.156f, +117.188f,26.2207f,160.156f, +121.094f,28.1249f,160.156f, +125.0f,29.8102f,160.156f, +128.906f,31.7349f,160.156f, +132.813f,32.4376f,160.156f, +136.719f,33.2795f,160.156f, +140.625f,37.4588f,160.156f, +144.531f,38.8195f,160.156f, +148.438f,39.9622f,160.156f, +152.344f,41.6752f,160.156f, +156.25f,37.6576f,160.156f, +160.156f,41.4722f,160.156f, +164.063f,41.8372f,160.156f, +167.969f,40.7289f,160.156f, +171.875f,35.5243f,160.156f, +175.781f,34.1726f,160.156f, +179.688f,33.9628f,160.156f, +183.594f,33.3012f,160.156f, +187.5f,37.6064f,160.156f, +191.406f,36.2987f,160.156f, +195.313f,32.9836f,160.156f, +199.219f,34.2771f,160.156f, +203.125f,33.5607f,160.156f, +207.031f,26.9351f,160.156f, +210.938f,24.3584f,160.156f, +214.844f,25.5428f,160.156f, +218.75f,26.0054f,160.156f, +222.656f,24.092f,160.156f, +226.563f,22.8948f,160.156f, +230.469f,17.1899f,160.156f, +234.375f,15.0552f,160.156f, +238.281f,14.2468f,160.156f, +242.188f,13.7862f,160.156f, +246.094f,14.5132f,160.156f, +250.0f,14.3684f,160.156f, +3.90627f,16.9346f,156.25f, +7.81251f,18.2437f,156.25f, +11.7188f,18.3869f,156.25f, +15.625f,18.1055f,156.25f, +19.5313f,18.7445f,156.25f, +23.4375f,18.9235f,156.25f, +27.3438f,18.455f,156.25f, +31.25f,18.6644f,156.25f, +35.1563f,18.9448f,156.25f, +39.0625f,18.9971f,156.25f, +42.9688f,18.8628f,156.25f, +46.875f,18.6886f,156.25f, +50.7813f,18.8494f,156.25f, +54.6875f,19.4408f,156.25f, +58.5938f,18.7384f,156.25f, +62.5f,17.473f,156.25f, +66.4063f,18.5906f,156.25f, +70.3125f,18.7252f,156.25f, +74.2188f,19.5013f,156.25f, +78.125f,19.8221f,156.25f, +82.0313f,19.8648f,156.25f, +85.9375f,19.8955f,156.25f, +89.8438f,19.4401f,156.25f, +93.75f,18.7973f,156.25f, +97.6563f,18.8923f,156.25f, +101.563f,20.6151f,156.25f, +105.469f,22.9824f,156.25f, +109.375f,25.2251f,156.25f, +113.281f,26.7829f,156.25f, +117.188f,27.8131f,156.25f, +121.094f,29.6707f,156.25f, +125.0f,31.4614f,156.25f, +128.906f,32.8387f,156.25f, +132.813f,33.7834f,156.25f, +136.719f,34.3986f,156.25f, +140.625f,35.1609f,156.25f, +144.531f,40.0963f,156.25f, +148.438f,41.0412f,156.25f, +152.344f,42.0325f,156.25f, +156.25f,42.1696f,156.25f, +160.156f,41.9265f,156.25f, +164.063f,43.279f,156.25f, +167.969f,42.5995f,156.25f, +171.875f,36.6937f,156.25f, +175.781f,34.8393f,156.25f, +179.688f,34.7157f,156.25f, +183.594f,34.0579f,156.25f, +187.5f,33.7647f,156.25f, +191.406f,33.2242f,156.25f, +195.313f,32.1053f,156.25f, +199.219f,30.6563f,156.25f, +203.125f,33.623f,156.25f, +207.031f,28.0199f,156.25f, +210.938f,30.5092f,156.25f, +214.844f,29.3828f,156.25f, +218.75f,27.3486f,156.25f, +222.656f,25.8671f,156.25f, +226.563f,24.1209f,156.25f, +230.469f,17.9979f,156.25f, +234.375f,16.1304f,156.25f, +238.281f,14.8281f,156.25f, +242.188f,13.097f,156.25f, +246.094f,13.3642f,156.25f, +250.0f,13.6085f,156.25f, +3.90627f,17.6952f,152.344f, +7.81251f,19.1063f,152.344f, +11.7188f,19.6398f,152.344f, +15.625f,19.8626f,152.344f, +19.5313f,19.1453f,152.344f, +23.4375f,19.4932f,152.344f, +27.3438f,19.3908f,152.344f, +31.25f,18.6492f,152.344f, +35.1563f,18.3861f,152.344f, +39.0625f,18.198f,152.344f, +42.9688f,18.4497f,152.344f, +46.875f,17.8083f,152.344f, +50.7813f,18.5296f,152.344f, +54.6875f,19.8096f,152.344f, +58.5938f,19.3324f,152.344f, +62.5f,18.1507f,152.344f, +66.4063f,17.7998f,152.344f, +70.3125f,17.9266f,152.344f, +74.2188f,18.569f,152.344f, +78.125f,19.5043f,152.344f, +82.0313f,20.0768f,152.344f, +85.9375f,19.5187f,152.344f, +89.8438f,20.2592f,152.344f, +93.75f,19.2159f,152.344f, +97.6563f,20.1174f,152.344f, +101.563f,21.9257f,152.344f, +105.469f,23.9219f,152.344f, +109.375f,25.8476f,152.344f, +113.281f,27.9183f,152.344f, +117.188f,29.2798f,152.344f, +121.094f,30.2289f,152.344f, +125.0f,31.7495f,152.344f, +128.906f,33.1684f,152.344f, +132.813f,34.4626f,152.344f, +136.719f,35.9981f,152.344f, +140.625f,36.5168f,152.344f, +144.531f,35.9325f,152.344f, +148.438f,41.231f,152.344f, +152.344f,42.7257f,152.344f, +156.25f,43.5162f,152.344f, +160.156f,44.357f,152.344f, +164.063f,44.2347f,152.344f, +167.969f,40.2679f,152.344f, +171.875f,36.2109f,152.344f, +175.781f,36.3906f,152.344f, +179.688f,35.227f,152.344f, +183.594f,34.7006f,152.344f, +187.5f,34.7763f,152.344f, +191.406f,34.0912f,152.344f, +195.313f,32.201f,152.344f, +199.219f,30.6601f,152.344f, +203.125f,28.7526f,152.344f, +207.031f,33.0587f,152.344f, +210.938f,31.7955f,152.344f, +214.844f,29.893f,152.344f, +218.75f,27.5989f,152.344f, +222.656f,26.1347f,152.344f, +226.563f,19.6378f,152.344f, +230.469f,18.6596f,152.344f, +234.375f,17.3965f,152.344f, +238.281f,15.5807f,152.344f, +242.188f,13.4071f,152.344f, +246.094f,12.7989f,152.344f, +250.0f,12.5897f,152.344f, +3.90626f,18.4109f,148.438f, +7.81251f,18.8163f,148.438f, +11.7188f,20.7396f,148.438f, +15.625f,21.7833f,148.438f, +19.5313f,20.6586f,148.438f, +23.4375f,19.8597f,148.438f, +27.3438f,20.0951f,148.438f, +31.25f,18.7811f,148.438f, +35.1563f,18.123f,148.438f, +39.0625f,17.773f,148.438f, +42.9688f,18.0095f,148.438f, +46.875f,17.694f,148.438f, +50.7813f,17.1666f,148.438f, +54.6875f,18.3484f,148.438f, +58.5938f,18.5612f,148.438f, +62.5f,18.1324f,148.438f, +66.4063f,17.4119f,148.438f, +70.3125f,17.2873f,148.438f, +74.2188f,17.6855f,148.438f, +78.125f,18.6618f,148.438f, +82.0313f,19.6447f,148.438f, +85.9375f,19.4743f,148.438f, +89.8438f,20.2887f,148.438f, +93.75f,20.2469f,148.438f, +97.6563f,21.1802f,148.438f, +101.563f,23.2002f,148.438f, +105.469f,24.8874f,148.438f, +109.375f,26.5433f,148.438f, +113.281f,28.653f,148.438f, +117.188f,30.2347f,148.438f, +121.094f,31.6949f,148.438f, +125.0f,33.2452f,148.438f, +128.906f,34.3964f,148.438f, +132.813f,35.2835f,148.438f, +136.719f,36.7099f,148.438f, +140.625f,37.1893f,148.438f, +144.531f,36.5212f,148.438f, +148.438f,36.7413f,148.438f, +152.344f,43.9965f,148.438f, +156.25f,44.9543f,148.438f, +160.156f,44.8078f,148.438f, +164.063f,45.09f,148.438f, +167.969f,43.0871f,148.438f, +171.875f,42.2067f,148.438f, +175.781f,40.5399f,148.438f, +179.688f,35.9902f,148.438f, +183.594f,34.4093f,148.438f, +187.5f,35.1087f,148.438f, +191.406f,34.3372f,148.438f, +195.313f,35.6724f,148.438f, +199.219f,34.961f,148.438f, +203.125f,34.4106f,148.438f, +207.031f,32.0028f,148.438f, +210.938f,31.3925f,148.438f, +214.844f,29.3539f,148.438f, +218.75f,27.6213f,148.438f, +222.656f,21.6694f,148.438f, +226.563f,20.356f,148.438f, +230.469f,19.6202f,148.438f, +234.375f,17.6247f,148.438f, +238.281f,16.5152f,148.438f, +242.188f,14.901f,148.438f, +246.094f,12.7994f,148.438f, +250.0f,12.2743f,148.438f, +3.90626f,17.8758f,144.531f, +7.81251f,19.3177f,144.531f, +11.7188f,20.9214f,144.531f, +15.625f,21.8589f,144.531f, +19.5313f,21.2904f,144.531f, +23.4375f,19.9784f,144.531f, +27.3438f,19.6359f,144.531f, +31.25f,19.4398f,144.531f, +35.1563f,18.6596f,144.531f, +39.0625f,17.1967f,144.531f, +42.9688f,16.797f,144.531f, +46.875f,16.4099f,144.531f, +50.7813f,16.54f,144.531f, +54.6875f,16.811f,144.531f, +58.5938f,17.31f,144.531f, +62.5f,17.5358f,144.531f, +66.4063f,16.8495f,144.531f, +70.3125f,17.2148f,144.531f, +74.2188f,16.6285f,144.531f, +78.125f,17.7911f,144.531f, +82.0313f,18.6054f,144.531f, +85.9375f,18.787f,144.531f, +89.8438f,20.4804f,144.531f, +93.75f,21.0544f,144.531f, +97.6563f,20.9487f,144.531f, +101.563f,23.1098f,144.531f, +105.469f,25.2196f,144.531f, +109.375f,27.0389f,144.531f, +113.281f,29.4971f,144.531f, +117.188f,31.0049f,144.531f, +121.094f,33.086f,144.531f, +125.0f,34.6611f,144.531f, +128.906f,35.8626f,144.531f, +132.813f,36.8672f,144.531f, +136.719f,37.5515f,144.531f, +140.625f,37.6433f,144.531f, +144.531f,37.8923f,144.531f, +148.438f,37.1277f,144.531f, +152.344f,40.0287f,144.531f, +156.25f,44.9863f,144.531f, +160.156f,45.0845f,144.531f, +164.063f,44.7823f,144.531f, +167.969f,42.5338f,144.531f, +171.875f,41.7912f,144.531f, +175.781f,41.5762f,144.531f, +179.688f,41.3242f,144.531f, +183.594f,39.6796f,144.531f, +187.5f,39.4704f,144.531f, +191.406f,38.5401f,144.531f, +195.313f,37.3853f,144.531f, +199.219f,35.4345f,144.531f, +203.125f,34.2437f,144.531f, +207.031f,31.8218f,144.531f, +210.938f,30.6041f,144.531f, +214.844f,26.9001f,144.531f, +218.75f,22.3094f,144.531f, +222.656f,21.4446f,144.531f, +226.563f,20.6643f,144.531f, +230.469f,20.3246f,144.531f, +234.375f,18.0382f,144.531f, +238.281f,15.7854f,144.531f, +242.188f,14.3314f,144.531f, +246.094f,12.4723f,144.531f, +250.0f,12.5491f,144.531f, +3.90626f,18.5798f,140.625f, +7.81251f,19.7271f,140.625f, +11.7188f,20.8566f,140.625f, +15.625f,21.6914f,140.625f, +19.5313f,20.9288f,140.625f, +23.4375f,20.0531f,140.625f, +27.3438f,19.1655f,140.625f, +31.25f,18.7947f,140.625f, +35.1563f,18.2984f,140.625f, +39.0625f,17.3295f,140.625f, +42.9688f,16.5557f,140.625f, +46.875f,16.1679f,140.625f, +50.7813f,16.0262f,140.625f, +54.6875f,16.1659f,140.625f, +58.5938f,16.459f,140.625f, +62.5f,17.0307f,140.625f, +66.4063f,17.6303f,140.625f, +70.3125f,16.7576f,140.625f, +74.2188f,16.9614f,140.625f, +78.125f,17.3439f,140.625f, +82.0313f,17.7742f,140.625f, +85.9375f,19.0774f,140.625f, +89.8438f,20.0724f,140.625f, +93.75f,21.5734f,140.625f, +97.6563f,21.4923f,140.625f, +101.563f,24.2474f,140.625f, +105.469f,25.9666f,140.625f, +109.375f,27.8803f,140.625f, +113.281f,29.6397f,140.625f, +117.188f,32.0374f,140.625f, +121.094f,34.014f,140.625f, +125.0f,35.1589f,140.625f, +128.906f,36.2526f,140.625f, +132.813f,37.5386f,140.625f, +136.719f,38.1647f,140.625f, +140.625f,37.9014f,140.625f, +144.531f,39.0558f,140.625f, +148.438f,38.1493f,140.625f, +152.344f,39.5967f,140.625f, +156.25f,40.3409f,140.625f, +160.156f,39.4778f,140.625f, +164.063f,43.7911f,140.625f, +167.969f,42.7467f,140.625f, +171.875f,41.4394f,140.625f, +175.781f,41.222f,140.625f, +179.688f,40.9501f,140.625f, +183.594f,40.2741f,140.625f, +187.5f,40.5011f,140.625f, +191.406f,39.8634f,140.625f, +195.313f,37.8944f,140.625f, +199.219f,35.6917f,140.625f, +203.125f,33.0921f,140.625f, +207.031f,30.7497f,140.625f, +210.938f,24.355f,140.625f, +214.844f,23.6102f,140.625f, +218.75f,23.2298f,140.625f, +222.656f,21.8035f,140.625f, +226.563f,21.0813f,140.625f, +230.469f,20.4423f,140.625f, +234.375f,19.372f,140.625f, +238.281f,16.9074f,140.625f, +242.188f,15.6931f,140.625f, +246.094f,14.0046f,140.625f, +250.0f,12.7719f,140.625f, +3.90626f,19.7224f,136.719f, +7.81251f,20.3645f,136.719f, +11.7188f,20.1938f,136.719f, +15.625f,20.0122f,136.719f, +19.5313f,20.9204f,136.719f, +23.4375f,20.2208f,136.719f, +27.3438f,19.3419f,136.719f, +31.25f,18.2059f,136.719f, +35.1563f,17.6089f,136.719f, +39.0625f,17.131f,136.719f, +42.9688f,16.8349f,136.719f, +46.875f,16.3462f,136.719f, +50.7813f,15.4488f,136.719f, +54.6875f,15.7887f,136.719f, +58.5938f,16.431f,136.719f, +62.5f,16.3378f,136.719f, +66.4063f,17.4585f,136.719f, +70.3125f,17.5113f,136.719f, +74.2188f,17.6407f,136.719f, +78.125f,17.0887f,136.719f, +82.0313f,17.2555f,136.719f, +85.9375f,18.6283f,136.719f, +89.8438f,19.6874f,136.719f, +93.75f,21.0963f,136.719f, +97.6563f,21.5582f,136.719f, +101.563f,24.9129f,136.719f, +105.469f,27.5761f,136.719f, +109.375f,28.7426f,136.719f, +113.281f,31.0958f,136.719f, +117.188f,33.7564f,136.719f, +121.094f,34.6927f,136.719f, +125.0f,35.0503f,136.719f, +128.906f,36.0657f,136.719f, +132.813f,37.2001f,136.719f, +136.719f,38.5625f,136.719f, +140.625f,38.8809f,136.719f, +144.531f,39.3646f,136.719f, +148.438f,38.919f,136.719f, +152.344f,39.5251f,136.719f, +156.25f,39.5392f,136.719f, +160.156f,39.7011f,136.719f, +164.063f,38.4043f,136.719f, +167.969f,37.7232f,136.719f, +171.875f,37.8418f,136.719f, +175.781f,41.0576f,136.719f, +179.688f,40.6804f,136.719f, +183.594f,40.6431f,136.719f, +187.5f,41.2286f,136.719f, +191.406f,40.221f,136.719f, +195.313f,37.9197f,136.719f, +199.219f,30.9591f,136.719f, +203.125f,28.2027f,136.719f, +207.031f,25.2338f,136.719f, +210.938f,24.1525f,136.719f, +214.844f,23.6344f,136.719f, +218.75f,22.6246f,136.719f, +222.656f,21.3675f,136.719f, +226.563f,21.0207f,136.719f, +230.469f,20.2558f,136.719f, +234.375f,18.3661f,136.719f, +238.281f,16.7584f,136.719f, +242.188f,16.2723f,136.719f, +246.094f,14.7268f,136.719f, +250.0f,13.5973f,136.719f, +3.90626f,19.9574f,132.813f, +7.8125f,21.126f,132.813f, +11.7188f,20.9977f,132.813f, +15.625f,21.2478f,132.813f, +19.5313f,21.5981f,132.813f, +23.4375f,20.0536f,132.813f, +27.3438f,18.6025f,132.813f, +31.25f,18.166f,132.813f, +35.1563f,17.207f,132.813f, +39.0625f,17.3703f,132.813f, +42.9688f,16.3317f,132.813f, +46.875f,15.4769f,132.813f, +50.7813f,14.7771f,132.813f, +54.6875f,14.8038f,132.813f, +58.5938f,15.7291f,132.813f, +62.5f,16.2292f,132.813f, +66.4063f,17.1488f,132.813f, +70.3125f,17.5027f,132.813f, +74.2188f,16.9736f,132.813f, +78.125f,16.4014f,132.813f, +82.0313f,16.7581f,132.813f, +85.9375f,18.1894f,132.813f, +89.8438f,20.0178f,132.813f, +93.75f,20.5813f,132.813f, +97.6563f,22.5893f,132.813f, +101.563f,25.6741f,132.813f, +105.469f,28.0908f,132.813f, +109.375f,29.1124f,132.813f, +113.281f,31.4752f,132.813f, +117.188f,33.2328f,132.813f, +121.094f,34.3747f,132.813f, +125.0f,34.8849f,132.813f, +128.906f,36.3771f,132.813f, +132.813f,37.3154f,132.813f, +136.719f,38.6196f,132.813f, +140.625f,39.1474f,132.813f, +144.531f,39.5395f,132.813f, +148.438f,38.9241f,132.813f, +152.344f,39.6801f,132.813f, +156.25f,39.7675f,132.813f, +160.156f,39.4464f,132.813f, +164.063f,38.2967f,132.813f, +167.969f,37.3679f,132.813f, +171.875f,36.5147f,132.813f, +175.781f,35.9217f,132.813f, +179.688f,35.6874f,132.813f, +183.594f,36.0348f,132.813f, +187.5f,36.167f,132.813f, +191.406f,34.7462f,132.813f, +195.313f,32.5911f,132.813f, +199.219f,30.8509f,132.813f, +203.125f,27.889f,132.813f, +207.031f,25.0869f,132.813f, +210.938f,23.713f,132.813f, +214.844f,23.4714f,132.813f, +218.75f,22.2633f,132.813f, +222.656f,21.1409f,132.813f, +226.563f,20.2725f,132.813f, +230.469f,19.4678f,132.813f, +234.375f,18.4511f,132.813f, +238.281f,18.0306f,132.813f, +242.188f,17.5677f,132.813f, +246.094f,16.403f,132.813f, +250.0f,14.7316f,132.813f, +3.90626f,20.0876f,128.906f, +7.81252f,21.0764f,128.906f, +11.7188f,21.4076f,128.906f, +15.625f,22.6299f,128.906f, +19.5313f,22.1174f,128.906f, +23.4375f,20.3977f,128.906f, +27.3438f,18.7343f,128.906f, +31.25f,17.9144f,128.906f, +35.1563f,17.2941f,128.906f, +39.0625f,16.5386f,128.906f, +42.9688f,15.6892f,128.906f, +46.875f,14.6414f,128.906f, +50.7813f,14.3505f,128.906f, +54.6875f,14.1604f,128.906f, +58.5938f,14.517f,128.906f, +62.5f,15.1057f,128.906f, +66.4063f,16.0684f,128.906f, +70.3125f,16.6251f,128.906f, +74.2188f,15.9689f,128.906f, +78.125f,16.0234f,128.906f, +82.0313f,16.205f,128.906f, +85.9375f,18.8167f,128.906f, +89.8438f,19.6433f,128.906f, +93.75f,20.2916f,128.906f, +97.6563f,23.2308f,128.906f, +101.563f,25.882f,128.906f, +105.469f,27.5736f,128.906f, +109.375f,28.9662f,128.906f, +113.281f,30.5702f,128.906f, +117.188f,31.8627f,128.906f, +121.094f,32.5216f,128.906f, +125.0f,34.1918f,128.906f, +128.906f,37.0161f,128.906f, +132.813f,38.5084f,128.906f, +136.719f,39.1631f,128.906f, +140.625f,39.0529f,128.906f, +144.531f,38.9229f,128.906f, +148.438f,38.4312f,128.906f, +152.344f,39.1086f,128.906f, +156.25f,39.7022f,128.906f, +160.156f,39.3007f,128.906f, +164.063f,38.2318f,128.906f, +167.969f,36.7493f,128.906f, +171.875f,35.9781f,128.906f, +175.781f,35.7712f,128.906f, +179.688f,35.6247f,128.906f, +183.594f,35.4808f,128.906f, +187.5f,35.6102f,128.906f, +191.406f,34.0305f,128.906f, +195.313f,32.0227f,128.906f, +199.219f,29.7666f,128.906f, +203.125f,27.3968f,128.906f, +207.031f,25.1642f,128.906f, +210.938f,24.279f,128.906f, +214.844f,22.4357f,128.906f, +218.75f,21.7754f,128.906f, +222.656f,19.6381f,128.906f, +226.563f,19.78f,128.906f, +230.469f,20.0349f,128.906f, +234.375f,19.1534f,128.906f, +238.281f,17.863f,128.906f, +242.188f,17.658f,128.906f, +246.094f,16.951f,128.906f, +250.0f,16.2961f,128.906f, +}; + +btScalar Landscape01Nml[] = { +-0.145347f,0.988603f,0.0392193f, +-0.118578f,0.971903f,-0.203332f, +-0.210348f,0.975548f,0.0637181f, +-0.143154f,0.979915f,-0.138828f, +-0.186466f,0.976661f,0.106602f, +-0.200996f,0.973874f,-0.105691f, +-0.200019f,0.979742f,-0.00987837f, +-0.162567f,0.986516f,-0.0189093f, +-0.128872f,0.991658f,-0.00262187f, +-0.0972065f,0.993702f,0.0557464f, +-0.232168f,0.972676f,8.39761e-005f, +-0.280715f,0.959127f,-0.0356947f, +-0.328537f,0.944066f,-0.0283446f, +-0.348021f,0.936189f,-0.0493126f, +-0.28502f,0.953899f,-0.0940249f, +-0.329197f,0.938125f,-0.107479f, +-0.186873f,0.969867f,-0.15632f, +-0.168074f,0.98179f,-0.088542f, +0.138723f,0.984643f,-0.105994f, +0.139713f,0.984758f,-0.103594f, +0.415149f,0.907443f,-0.0647914f, +0.335594f,0.916204f,-0.218967f, +0.391251f,0.906316f,-0.159731f, +0.297117f,0.890775f,-0.343864f, +0.0782406f,0.948307f,-0.307558f, +0.0742546f,0.932023f,-0.354711f, +-0.0593029f,0.94484f,-0.322118f, +-0.035102f,0.9388f,-0.342668f, +-0.0398386f,0.972105f,-0.231139f, +0.0142535f,0.946652f,-0.321942f, +-0.149407f,0.982239f,-0.113505f, +-0.186817f,0.918353f,-0.348895f, +-0.227035f,0.95418f,-0.194923f, +-0.217455f,0.921613f,-0.32147f, +-0.104683f,0.961425f,-0.254368f, +-0.137473f,0.92562f,-0.352602f, +-0.0889131f,0.942391f,-0.322479f, +-0.137942f,0.895959f,-0.422173f, +-0.0994313f,0.915873f,-0.38896f, +-0.177412f,0.858967f,-0.480312f, +-0.28046f,0.843765f,-0.457605f, +-0.23875f,0.832625f,-0.499733f, +-0.35769f,0.865922f,-0.349624f, +-0.239679f,0.924761f,-0.295585f, +-0.367472f,0.894137f,-0.255898f, +-0.306721f,0.940051f,-0.149083f, +-0.29191f,0.929123f,-0.226977f, +-0.3205f,0.928892f,-0.185579f, +-0.367832f,0.894452f,-0.254274f, +-0.393375f,0.898238f,-0.196023f, +-0.386104f,0.869165f,-0.308993f, +-0.416765f,0.860247f,-0.293737f, +-0.257238f,0.898443f,-0.355849f, +-0.273377f,0.911812f,-0.306372f, +-0.228654f,0.889208f,-0.396265f, +-0.28545f,0.876522f,-0.387592f, +-0.142316f,0.885962f,-0.441381f, +-0.101084f,0.908701f,-0.405025f, +0.035618f,0.945519f,-0.323614f, +0.103277f,0.941647f,-0.320368f, +-0.120589f,0.957422f,-0.262302f, +-0.186114f,0.894712f,-0.40602f, +-0.202962f,0.931974f,-0.300385f, +-0.162074f,0.943023f,-0.290584f, +-0.152017f,0.933176f,-0.325688f, +-0.202811f,0.891764f,-0.404505f, +-0.195614f,0.919053f,-0.342165f, +-0.221332f,0.883262f,-0.413352f, +-0.230949f,0.883479f,-0.407587f, +-0.202664f,0.884798f,-0.419595f, +-0.013827f,0.935183f,-0.353894f, +0.0613953f,0.949306f,-0.308299f, +0.0379666f,0.956996f,-0.287605f, +0.0239474f,0.920688f,-0.389564f, +-0.124568f,0.971246f,-0.20289f, +-0.0173673f,0.966674f,-0.255421f, +-0.280608f,0.954174f,-0.103981f, +-0.188825f,0.978003f,-0.0886339f, +-0.193278f,0.981044f,-0.0139968f, +-0.089832f,0.992161f,0.0868734f, +-0.0617809f,0.994525f,0.0842802f, +0.0316335f,0.979002f,0.20138f, +0.126601f,0.973442f,0.190743f, +0.126356f,0.954056f,0.271683f, +0.0296197f,0.996225f,0.0816031f, +-0.130879f,0.990212f,-0.0484936f, +-0.0775613f,0.996382f,0.0347567f, +-0.0318445f,0.999049f,0.0297665f, +0.174213f,0.981835f,0.0751658f, +0.230898f,0.968544f,0.0927823f, +0.477724f,0.867555f,0.138304f, +0.489512f,0.856269f,0.164868f, +0.425011f,0.903484f,0.0555235f, +0.345126f,0.937885f,0.0355011f, +0.051136f,0.997417f,-0.0504465f, +0.0111243f,0.99878f,-0.0481145f, +0.00085351f,0.998643f,-0.0520782f, +-0.0736129f,0.992491f,-0.0976874f, +0.0605446f,0.978416f,-0.197578f, +-0.1248f,0.898669f,-0.420499f, +-0.068151f,0.956411f,-0.28396f, +0.0502596f,0.934397f,-0.35267f, +0.0492358f,0.99416f,-0.096025f, +0.22311f,0.97441f,-0.0273246f, +0.104257f,0.993921f,-0.0353788f, +0.135731f,0.987345f,0.0820234f, +0.0508084f,0.996415f,-0.0676404f, +0.013783f,0.999772f,-0.0162859f, +0.0814861f,0.996154f,-0.0322044f, +0.0451487f,0.998313f,-0.0365194f, +0.035547f,0.992801f,-0.114375f, +-0.0977551f,0.955799f,-0.277294f, +0.0588118f,0.977967f,-0.200303f, +0.0956551f,0.968682f,-0.229142f, +0.255494f,0.951171f,-0.173197f, +0.287347f,0.949686f,-0.124613f, +0.300983f,0.934694f,-0.189092f, +0.326044f,0.937015f,-0.125296f, +0.170234f,0.979103f,-0.111255f, +0.217643f,0.971688f,-0.0919459f, +0.0857423f,0.995f,-0.0512173f, +0.141055f,0.988855f,0.0476293f, +0.141065f,0.98942f,-0.0338874f, +0.161562f,0.986303f,0.0332183f, +0.113059f,0.993231f,0.0266602f, +0.073071f,0.997081f,-0.0221543f, +-0.0590251f,0.997651f,-0.034775f, +-0.0264959f,0.999595f,0.0103962f, +-0.0628475f,0.932757f,0.354985f, +-0.188464f,0.930547f,0.31395f, +-0.11595f,0.95582f,0.270118f, +-0.0150745f,0.981122f,0.192801f, +-0.121292f,0.98854f,0.0898753f, +-0.191875f,0.979293f,0.0645635f, +-0.302211f,0.947932f,-0.100469f, +-0.168835f,0.972187f,-0.162321f, +-0.165107f,0.942083f,-0.291925f, +0.0524842f,0.966783f,-0.250151f, +0.334898f,0.925425f,-0.177288f, +0.453352f,0.888614f,-0.0695481f, +0.212879f,0.976177f,-0.0419751f, +-0.0859137f,0.991174f,-0.100958f, +-0.19247f,0.980365f,-0.0428897f, +-0.217979f,0.975456f,0.0311624f, +-0.130678f,0.991292f,-0.0162531f, +0.0105625f,0.994964f,-0.0996785f, +-0.0191557f,0.967247f,-0.253114f, +-0.034833f,0.962122f,-0.270385f, +-0.195874f,0.937997f,-0.285996f, +-0.397161f,0.831379f,-0.388681f, +-0.379064f,0.825916f,-0.417342f, +-0.284483f,0.874083f,-0.393762f, +-0.320157f,0.86551f,-0.385217f, +-0.327447f,0.85814f,-0.395442f, +-0.219114f,0.871062f,-0.439592f, +-0.161876f,0.861769f,-0.480781f, +-0.18946f,0.845726f,-0.498852f, +-0.191307f,0.924603f,-0.32941f, +-0.159365f,0.982225f,-0.0991764f, +-0.164558f,0.975832f,-0.143777f, +-0.155521f,0.974006f,-0.164699f, +-0.172244f,0.972979f,-0.153766f, +-0.162541f,0.961346f,-0.222247f, +-0.11171f,0.955927f,-0.271523f, +-0.101714f,0.980079f,-0.170586f, +-0.223397f,0.974336f,-0.0276274f, +-0.300622f,0.953413f,0.0251167f, +-0.254202f,0.967133f,-0.00586307f, +-0.0994566f,0.994394f,0.0359007f, +0.078652f,0.996758f,-0.0169243f, +-0.0552979f,0.987555f,0.147234f, +-0.0666628f,0.864508f,0.498179f, +0.131082f,0.854494f,0.502651f, +0.414695f,0.764646f,0.4933f, +0.432926f,0.790826f,0.432632f, +0.126593f,0.91514f,0.382744f, +-0.0157552f,0.943082f,0.332186f, +0.122694f,0.924647f,0.36052f, +0.0975822f,0.984244f,0.147447f, +-0.026294f,0.960938f,-0.275512f, +0.1231f,0.958251f,-0.258072f, +0.037902f,0.976085f,-0.214059f, +-0.000148888f,0.992562f,-0.121742f, +0.0716429f,0.997173f,-0.0226693f, +0.135484f,0.989193f,-0.0560393f, +0.275603f,0.956281f,-0.0978236f, +0.283097f,0.956822f,-0.0659346f, +0.109624f,0.991403f,-0.0714361f, +0.084436f,0.990816f,-0.105609f, +0.0791881f,0.990931f,-0.108558f, +0.0674956f,0.997569f,-0.0173508f, +0.0556006f,0.998429f,0.00688119f, +-0.144974f,0.947519f,0.28494f, +-0.110826f,0.961365f,0.251981f, +-0.0669451f,0.996693f,0.0460586f, +-0.00516145f,0.998802f,0.0486696f, +-0.116537f,0.988089f,0.100498f, +-0.0456605f,0.993379f,0.105422f, +-0.110131f,0.987256f,-0.114879f, +-0.0746162f,0.968429f,-0.237861f, +-0.0785155f,0.952358f,-0.294703f, +-0.0192369f,0.946876f,-0.321024f, +0.320056f,0.920022f,-0.226108f, +0.288692f,0.932613f,-0.216541f, +0.123147f,0.991593f,-0.0397145f, +-0.113817f,0.992375f,0.0473138f, +-0.192042f,0.9774f,0.0883642f, +-0.156949f,0.987573f,0.00819321f, +-0.0848586f,0.992344f,-0.0897344f, +0.0818673f,0.992357f,-0.0923282f, +0.113464f,0.986976f,-0.114035f, +-0.0777263f,0.979155f,-0.187653f, +-0.11587f,0.975173f,-0.188711f, +-0.26618f,0.902421f,-0.338799f, +-0.343104f,0.842974f,-0.414336f, +-0.318919f,0.837107f,-0.444457f, +-0.324821f,0.839352f,-0.435867f, +-0.312979f,0.836318f,-0.45013f, +-0.203015f,0.862499f,-0.463553f, +-0.14187f,0.900483f,-0.411101f, +-0.22968f,0.933243f,-0.276233f, +-0.413973f,0.871187f,-0.263932f, +-0.305656f,0.93798f,-0.163607f, +-0.161875f,0.985861f,-0.0433003f, +-0.135788f,0.990721f,0.00582442f, +-0.138617f,0.984876f,-0.103942f, +-0.135024f,0.980056f,-0.145806f, +-0.124871f,0.989793f,-0.068687f, +-0.182018f,0.982992f,-0.024403f, +-0.309743f,0.950592f,-0.0208625f, +-0.30492f,0.95221f,0.0178823f, +-0.299424f,0.951826f,0.066125f, +-0.120448f,0.944431f,0.305848f, +0.118213f,0.907792f,0.402418f, +-0.261318f,0.917154f,0.300902f, +-0.411401f,0.860866f,0.299431f, +0.15139f,0.91772f,0.367249f, +0.409879f,0.832051f,0.373752f, +0.446772f,0.77668f,0.44403f, +0.301572f,0.80653f,0.508491f, +0.168293f,0.89172f,0.420135f, +0.0587854f,0.961406f,0.26878f, +0.30067f,0.896979f,0.324077f, +0.282217f,0.935284f,0.213535f, +0.148185f,0.986837f,0.0647602f, +-0.0572401f,0.974528f,-0.216838f, +-0.0945497f,0.96665f,-0.238009f, +-0.000668496f,0.9725f,-0.232902f, +0.125989f,0.980136f,-0.15317f, +0.218059f,0.975888f,-0.00959987f, +0.265461f,0.958501f,0.103951f, +0.173443f,0.98019f,0.0956349f, +0.133691f,0.987754f,0.0804258f, +0.0900836f,0.995272f,0.0363034f, +0.0177237f,0.999106f,-0.0383914f, +0.042211f,0.998744f,-0.0269875f, +0.0720539f,0.94434f,0.320982f, +0.0948772f,0.964987f,0.244537f, +0.123635f,0.987961f,0.0929884f, +-0.0283728f,0.998997f,-0.0346279f, +-0.152337f,0.985597f,-0.0734363f, +-0.0291778f,0.996634f,-0.0766092f, +0.0594392f,0.995285f,-0.0766423f, +-0.027888f,0.982723f,-0.182971f, +-0.0125244f,0.971758f,-0.235647f, +-0.0767296f,0.943557f,-0.322201f, +0.2299f,0.955601f,-0.184318f, +0.271645f,0.9586f,-0.0854157f, +0.0112173f,0.999015f,-0.0429278f, +-0.142475f,0.989464f,-0.02574f, +-0.192441f,0.979224f,-0.0639254f, +-0.103523f,0.99301f,-0.0567016f, +-0.00378459f,0.998834f,-0.0481324f, +0.0499927f,0.992415f,-0.112309f, +0.0737699f,0.994576f,-0.0733206f, +-0.0190206f,0.999623f,-0.0197948f, +-0.0783652f,0.99692f,0.00307073f, +-0.152226f,0.987897f,0.0297819f, +-0.333638f,0.940154f,-0.069252f, +-0.307736f,0.941909f,-0.134557f, +-0.334924f,0.918699f,-0.209327f, +-0.35357f,0.914459f,-0.19686f, +-0.243406f,0.963329f,-0.112917f, +-0.31479f,0.943784f,-0.100892f, +-0.368184f,0.929745f,0.00391099f, +-0.386308f,0.922293f,-0.0119138f, +-0.337617f,0.936762f,-0.0921568f, +-0.305867f,0.947033f,-0.0978487f, +-0.109063f,0.994026f,0.00418869f, +0.00976093f,0.996792f,-0.0794369f, +-0.152053f,0.972765f,-0.17495f, +-0.268682f,0.956747f,-0.111559f, +-0.16583f,0.986099f,0.0104333f, +-0.26795f,0.960138f,-0.0796053f, +-0.428361f,0.903607f,0.000904858f, +-0.364896f,0.884093f,0.291943f, +-0.411739f,0.889329f,0.19891f, +-0.213918f,0.942658f,0.256194f, +-0.0353818f,0.912316f,0.407955f, +-0.234679f,0.972031f,0.0090071f, +0.164799f,0.976041f,-0.142074f, +0.378329f,0.920537f,-0.0973577f, +0.389048f,0.913009f,0.122701f, +0.312785f,0.918579f,0.241617f, +0.331426f,0.913352f,0.236529f, +0.235473f,0.970893f,0.043811f, +0.0409183f,0.988429f,-0.14606f, +0.183882f,0.951979f,0.244794f, +0.256685f,0.844334f,0.470333f, +0.243297f,0.84406f,0.47788f, +0.178194f,0.957255f,0.227835f, +0.0574376f,0.965885f,-0.252523f, +-0.0590426f,0.961892f,-0.266977f, +0.0063288f,0.996614f,-0.081983f, +0.221194f,0.97242f,0.0739783f, +0.131016f,0.988415f,0.0766141f, +0.0953963f,0.986256f,0.134901f, +0.160579f,0.972927f,0.166216f, +0.109946f,0.983906f,0.14086f, +0.027673f,0.996741f,0.0757784f, +0.095102f,0.971229f,0.218334f, +0.102357f,0.973251f,0.205684f, +0.193741f,0.956416f,0.218477f, +0.132416f,0.984788f,0.112512f, +-0.0766537f,0.99488f,-0.0658589f, +-0.0304197f,0.995587f,-0.0887742f, +0.0261631f,0.997431f,-0.0666789f, +0.0720508f,0.996334f,-0.0461268f, +0.110802f,0.979106f,-0.170512f, +-0.036534f,0.946972f,-0.319234f, +0.0562543f,0.953438f,-0.296297f, +0.21433f,0.964539f,-0.154036f, +-0.0463138f,0.986383f,-0.157808f, +-0.114222f,0.99275f,-0.0374399f, +-0.129535f,0.99146f,-0.0150624f, +-0.148036f,0.985214f,-0.0862475f, +-0.0412316f,0.997863f,-0.050697f, +0.0938182f,0.995513f,-0.0123356f, +0.0585542f,0.997889f,-0.0281043f, +-0.11195f,0.993633f,0.0126653f, +-0.208443f,0.969116f,0.131782f, +-0.178284f,0.959747f,0.217024f, +-0.249524f,0.951637f,0.179236f, +-0.204568f,0.966799f,0.153139f, +-0.277831f,0.959694f,0.042405f, +-0.421523f,0.906804f,-0.00501147f, +-0.349246f,0.93481f,0.0644755f, +-0.271825f,0.953501f,0.130185f, +-0.341243f,0.939899f,0.0119564f, +-0.356048f,0.93224f,-0.0644791f, +-0.286188f,0.955628f,-0.0697892f, +-0.248084f,0.956522f,-0.153364f, +-0.154022f,0.960443f,-0.232007f, +0.032406f,0.989794f,-0.138774f, +-0.0622078f,0.991529f,-0.114016f, +-0.335467f,0.915845f,-0.220659f, +-0.194821f,0.973732f,-0.117857f, +-0.29903f,0.953799f,-0.0291431f, +-0.514277f,0.834668f,0.197101f, +-0.344769f,0.927072f,0.147212f, +-0.0936834f,0.993837f,0.0592615f, +-0.181141f,0.974379f,-0.133321f, +-0.0841805f,0.983933f,-0.157447f, +0.0661375f,0.94785f,-0.31178f, +0.143104f,0.856028f,-0.496726f, +0.226417f,0.827547f,-0.513714f, +0.178899f,0.912784f,-0.367179f, +0.234616f,0.943911f,-0.232351f, +0.346693f,0.91935f,-0.186008f, +0.307074f,0.943627f,-0.123586f, +0.214863f,0.970065f,0.113171f, +0.0234555f,0.999712f,0.00506759f, +-0.0206358f,0.99868f,0.047041f, +0.0320247f,0.946177f,0.322062f, +0.23638f,0.837444f,0.492759f, +0.410368f,0.848265f,0.33473f, +-0.0124285f,0.999913f,-0.00451951f, +-0.13197f,0.981357f,-0.139724f, +0.0888915f,0.995883f,0.0177605f, +0.12955f,0.973581f,0.188033f, +0.100974f,0.97841f,0.18033f, +0.116628f,0.987352f,0.107396f, +0.0879041f,0.989191f,0.117361f, +0.114472f,0.980893f,0.157306f, +0.0306685f,0.986407f,0.161431f, +0.128704f,0.972047f,0.196366f, +0.21783f,0.966546f,0.135421f, +0.280184f,0.953049f,0.114866f, +0.0272615f,0.999564f,-0.0113551f, +-0.0491486f,0.997279f,-0.0549472f, +0.00337261f,0.998977f,-0.0450999f, +0.0913253f,0.995457f,-0.0269266f, +0.252481f,0.964775f,-0.0739122f, +0.0897947f,0.975122f,-0.202665f, +-0.0238258f,0.968534f,-0.247739f, +0.162662f,0.981573f,-0.10028f, +-0.0276113f,0.997652f,-0.0626774f, +-0.289082f,0.95335f,-0.0869268f, +-0.160594f,0.986876f,0.0169191f, +-0.0752137f,0.997117f,0.00999502f, +-0.0455931f,0.997939f,-0.0451647f, +0.0616976f,0.995202f,-0.0759372f, +-0.00353073f,0.999867f,-0.0159004f, +-0.177748f,0.976224f,0.124065f, +-0.247702f,0.959217f,0.136188f, +-0.164797f,0.981869f,0.0936766f, +-0.214718f,0.976098f,0.0335935f, +-0.211552f,0.977318f,-0.00980662f, +-0.200169f,0.979677f,0.0128577f, +-0.39928f,0.916411f,-0.027687f, +-0.374531f,0.927212f,0.0022105f, +-0.268102f,0.963363f,0.00736207f, +-0.247283f,0.968232f,-0.0371081f, +-0.289483f,0.949449f,-0.121432f, +-0.253482f,0.93971f,-0.229547f, +-0.132892f,0.950758f,-0.279997f, +-0.140676f,0.931036f,-0.336723f, +-0.161496f,0.9509f,-0.264023f, +-0.0403886f,0.9973f,-0.0613364f, +-0.215095f,0.96767f,-0.131717f, +-0.434628f,0.895597f,-0.0948964f, +-0.381939f,0.886142f,0.262442f, +-0.43994f,0.880276f,0.177672f, +-0.252792f,0.948954f,-0.188633f, +-0.0941535f,0.957693f,-0.271953f, +-0.13352f,0.964535f,-0.227692f, +0.0341173f,0.927935f,-0.371176f, +0.348577f,0.799586f,-0.489036f, +0.387188f,0.819484f,-0.42253f, +0.14352f,0.883544f,-0.445815f, +0.0762879f,0.891752f,-0.446047f, +0.0742711f,0.875908f,-0.476728f, +0.300515f,0.871535f,-0.38745f, +0.0625809f,0.886656f,-0.458175f, +-0.0365474f,0.9191f,-0.392325f, +-0.0762363f,0.966891f,-0.243538f, +0.0117284f,0.995382f,0.0952715f, +0.0102532f,0.999347f,-0.0346391f, +-0.059511f,0.989492f,-0.131776f, +0.349383f,0.904972f,0.24281f, +0.425179f,0.763732f,0.485732f, +-0.0166138f,0.992406f,0.121875f, +-0.122272f,0.990094f,0.0690156f, +-0.015652f,0.970579f,0.240273f, +0.124649f,0.94771f,0.293785f, +0.220282f,0.938434f,0.266116f, +0.102745f,0.973801f,0.202865f, +0.0640356f,0.977435f,0.201297f, +-0.0952943f,0.987515f,0.125435f, +0.114947f,0.977151f,0.178783f, +0.258472f,0.957495f,0.128042f, +0.282157f,0.951094f,0.125728f, +0.142066f,0.986542f,0.0809464f, +-0.0434313f,0.998053f,-0.0447576f, +0.0347776f,0.999239f,-0.0176595f, +0.102204f,0.984881f,-0.139871f, +0.245582f,0.958619f,-0.144014f, +0.135608f,0.990697f,0.0113886f, +-0.0626335f,0.997441f,0.0344788f, +-0.0132478f,0.995736f,0.0912912f, +-0.039638f,0.981575f,0.186922f, +-0.205229f,0.973473f,0.10115f, +-0.153245f,0.987696f,-0.0311751f, +-0.0852914f,0.993336f,-0.0775215f, +0.0304281f,0.997751f,-0.0597208f, +0.0412582f,0.993049f,-0.110237f, +-0.115798f,0.992196f,0.0462328f, +-0.265664f,0.954942f,0.132323f, +-0.179634f,0.978355f,0.102729f, +-0.122093f,0.992469f,0.00988423f, +-0.0976525f,0.994936f,-0.0237989f, +-0.19391f,0.963376f,-0.185219f, +-0.249328f,0.960076f,-0.126845f, +-0.386054f,0.920896f,-0.0539736f, +-0.40236f,0.909842f,-0.101455f, +-0.264839f,0.959901f,-0.091928f, +-0.215529f,0.973573f,-0.0755211f, +-0.190591f,0.977631f,-0.0889496f, +-0.114636f,0.971653f,-0.20676f, +-0.147698f,0.942871f,-0.29863f, +-0.153003f,0.970479f,-0.186443f, +-0.259911f,0.94737f,-0.186912f, +-0.218176f,0.967871f,-0.124997f, +-0.218418f,0.965394f,0.142507f, +-0.497944f,0.825767f,0.264878f, +-0.394522f,0.874216f,0.283017f, +-0.174161f,0.980284f,0.0933364f, +-0.0291225f,0.984908f,-0.170609f, +-0.149188f,0.939649f,-0.307902f, +-0.109448f,0.970586f,-0.214438f, +0.391051f,0.895182f,-0.213842f, +0.237246f,0.888641f,-0.392468f, +0.104812f,0.984981f,-0.137213f, +0.1294f,0.991592f,-0.000205693f, +0.119158f,0.992497f,-0.0274125f, +0.117487f,0.990494f,-0.071548f, +0.234708f,0.962187f,-0.138234f, +0.347721f,0.937443f,-0.017023f, +0.135989f,0.962379f,-0.235229f, +-0.193384f,0.875532f,-0.442772f, +-0.209357f,0.905544f,-0.368998f, +0.0641865f,0.982942f,-0.172352f, +0.0534516f,0.998302f,-0.023133f, +-0.0579793f,0.992675f,-0.105989f, +0.299444f,0.827258f,0.475371f, +0.320901f,0.752799f,0.574731f, +-0.0625162f,0.964286f,0.257381f, +-0.0931157f,0.981324f,0.168322f, +0.0981691f,0.975509f,0.19684f, +0.238911f,0.944952f,0.223577f, +0.0852945f,0.980047f,0.179533f, +0.0437708f,0.96942f,0.241474f, +-0.0654565f,0.948925f,0.308637f, +0.105877f,0.941798f,0.319071f, +0.298409f,0.90697f,0.29725f, +0.267454f,0.931587f,0.246198f, +0.257873f,0.930012f,0.261877f, +0.0608152f,0.99476f,0.0821851f, +0.0682325f,0.995644f,-0.0635329f, +0.204976f,0.974836f,-0.0876375f, +0.100643f,0.994422f,0.031559f, +-0.0498971f,0.971595f,0.231328f, +-0.0948982f,0.951903f,0.291332f, +-0.0140779f,0.962693f,0.270229f, +0.0194699f,0.983768f,0.178386f, +-0.0700516f,0.997536f,0.00373294f, +-0.0458738f,0.991776f,-0.119485f, +-0.0457685f,0.983541f,-0.17479f, +0.031836f,0.984739f,-0.171101f, +-0.0846163f,0.991107f,-0.102703f, +-0.250146f,0.959975f,0.125993f, +-0.240823f,0.966766f,0.0858408f, +-0.110771f,0.993685f,0.0178603f, +-0.0536647f,0.99805f,-0.0318645f, +-0.0537905f,0.996775f,-0.0595505f, +-0.0979926f,0.994498f,-0.0370296f, +-0.317761f,0.946482f,-0.0565711f, +-0.353331f,0.932392f,-0.0761719f, +-0.315921f,0.918114f,-0.23929f, +-0.304095f,0.907663f,-0.289264f, +-0.232301f,0.951296f,-0.202665f, +-0.181242f,0.959764f,-0.214488f, +-0.0415921f,0.982269f,-0.182804f, +-0.134113f,0.976644f,-0.16787f, +-0.266673f,0.950383f,-0.160182f, +-0.233335f,0.968889f,-0.0825141f, +-0.383896f,0.923094f,0.0228394f, +-0.46523f,0.826401f,0.317211f, +-0.448022f,0.824389f,0.345917f, +-0.335673f,0.941977f,-0.00160348f, +0.00939714f,0.9768f,-0.213948f, +0.0525806f,0.945774f,-0.320541f, +-0.0139338f,0.984205f,-0.176483f, +-0.233879f,0.941098f,-0.244203f, +0.35813f,0.924476f,-0.13072f, +0.148621f,0.988076f,0.040214f, +-0.0873945f,0.896884f,0.433546f, +0.16715f,0.882598f,0.43941f, +0.105867f,0.92276f,0.370549f, +0.162793f,0.877156f,0.451769f, +0.26606f,0.895485f,0.356818f, +0.178343f,0.923603f,0.339339f, +0.205659f,0.876785f,0.434686f, +0.164046f,0.939287f,0.301379f, +-0.304778f,0.94913f,-0.0791393f, +-0.351721f,0.931897f,-0.088655f, +-0.137155f,0.986834f,0.0857151f, +-0.0493791f,0.984585f,0.167793f, +-0.29261f,0.942092f,0.163834f, +0.175576f,0.863797f,0.472257f, +0.388427f,0.769345f,0.507181f, +0.0396361f,0.995255f,0.0888612f, +0.000897162f,0.999738f,-0.022857f, +0.263974f,0.951061f,0.160623f, +0.140984f,0.987533f,0.0700142f, +-0.0604349f,0.998129f,-0.00925637f, +-0.0323604f,0.969904f,0.241328f, +0.0249905f,0.978924f,0.202689f, +0.301944f,0.900385f,0.313268f, +0.302439f,0.903212f,0.304531f, +0.227241f,0.927301f,0.297445f, +0.295557f,0.903047f,0.311692f, +0.215996f,0.968849f,0.121149f, +0.0543993f,0.994951f,0.0843384f, +-0.108272f,0.967731f,0.227539f, +-0.144218f,0.941468f,0.304694f, +-0.0465574f,0.94074f,0.335917f, +0.0834793f,0.95338f,0.289996f, +0.159412f,0.96437f,0.211135f, +0.125672f,0.984055f,0.125864f, +0.0125305f,0.999902f,-0.00630946f, +-0.0213081f,0.999771f,-0.00209364f, +-0.0845682f,0.99631f,0.014661f, +-0.191644f,0.962461f,0.192203f, +-0.326186f,0.912172f,0.248084f, +-0.125723f,0.965189f,0.229357f, +-0.0487346f,0.993706f,0.100859f, +0.0069351f,0.999976f,0.00057427f, +-0.0853775f,0.991791f,-0.0951918f, +-0.217561f,0.97582f,-0.0210368f, +-0.247132f,0.964013f,0.0979986f, +-0.253847f,0.965546f,-0.0573009f, +-0.17269f,0.977352f,-0.122318f, +-0.308873f,0.930936f,-0.19482f, +-0.274273f,0.935966f,-0.220775f, +-0.176582f,0.954344f,-0.240926f, +-0.17678f,0.967725f,-0.179601f, +-0.142126f,0.989789f,-0.0108556f, +-0.241082f,0.966299f,-0.0902532f, +-0.303483f,0.94088f,-0.150476f, +-0.634535f,0.768468f,-0.082594f, +-0.47113f,0.814002f,0.339761f, +-0.289984f,0.937003f,0.194769f, +0.025067f,0.999685f,-0.000862102f, +0.289006f,0.893747f,-0.343064f, +0.00615404f,0.935866f,-0.352301f, +-0.338901f,0.929111f,-0.147984f, +-0.164518f,0.985591f,-0.0393034f, +0.290961f,0.935697f,-0.199533f, +-0.0876053f,0.971539f,-0.220083f, +-0.32548f,0.935239f,0.139248f, +0.0766933f,0.974848f,0.20926f, +0.108828f,0.917507f,0.382541f, +0.0350786f,0.924503f,0.379557f, +0.162845f,0.883516f,0.439183f, +0.280718f,0.786151f,0.550603f, +0.282161f,0.80649f,0.519575f, +0.319525f,0.746566f,0.583561f, +-0.0912168f,0.872752f,0.479567f, +-0.288082f,0.924626f,0.249148f, +-0.142667f,0.981082f,0.130856f, +-0.066753f,0.9808f,0.183236f, +-0.230244f,0.961075f,0.152718f, +-0.067082f,0.99457f,0.0795691f, +0.611911f,0.730537f,0.303119f, +0.451199f,0.889041f,0.077617f, +0.0130284f,0.992329f,-0.12294f, +0.0930856f,0.993052f,-0.0719959f, +0.26722f,0.962884f,0.0380388f, +0.075301f,0.995117f,-0.0638176f, +0.167918f,0.972374f,0.162147f, +0.0578882f,0.993576f,0.0972437f, +0.196869f,0.968468f,0.152684f, +0.304163f,0.924874f,0.228237f, +0.255006f,0.935584f,0.244244f, +0.260728f,0.944471f,0.199987f, +0.218361f,0.924111f,0.313587f, +0.0535174f,0.911234f,0.408398f, +-0.0710624f,0.921034f,0.382946f, +-0.130246f,0.949543f,0.285314f, +-0.0655027f,0.977569f,0.200169f, +0.0903252f,0.974724f,0.204338f, +0.155207f,0.949154f,0.273892f, +0.153701f,0.938218f,0.310037f, +0.0621551f,0.960028f,0.272917f, +-0.0534301f,0.951765f,0.30214f, +-0.196733f,0.911558f,0.361052f, +-0.281614f,0.838193f,0.46704f, +-0.263195f,0.866235f,0.424694f, +-0.0481024f,0.917426f,0.394989f, +0.0935627f,0.945047f,0.31326f, +0.130693f,0.965135f,0.226792f, +0.00742185f,0.989033f,0.14751f, +-0.243053f,0.969364f,0.0354789f, +-0.273599f,0.961363f,-0.0304179f, +-0.215123f,0.976563f,-0.00682047f, +-0.164989f,0.983922f,0.068385f, +-0.241802f,0.97031f,0.00552545f, +-0.241315f,0.967202f,-0.0792945f, +-0.169018f,0.981272f,-0.0923975f, +-0.282714f,0.953981f,-0.0999632f, +-0.234963f,0.971912f,-0.0134244f, +-0.109087f,0.993838f,-0.0196489f, +-0.369236f,0.9273f,-0.0614783f, +-0.551241f,0.800465f,0.235349f, +-0.62344f,0.781571f,-0.0216512f, +-0.285923f,0.957424f,0.0398505f, +0.246101f,0.967083f,0.064696f, +0.379822f,0.894837f,-0.234526f, +-0.124179f,0.991035f,0.0492959f, +-0.55499f,0.830986f,0.0380685f, +-0.0883601f,0.986961f,0.13454f, +0.492332f,0.870217f,0.0182045f, +-0.0249785f,0.975709f,-0.217643f, +-0.368665f,0.864796f,-0.340902f, +-0.0172444f,0.938433f,-0.345031f, +-0.0663306f,0.97669f,-0.204147f, +0.00514992f,0.997132f,-0.0755029f, +0.0570337f,0.998371f,-0.00125828f, +0.249285f,0.962439f,0.107557f, +0.242481f,0.961206f,0.131476f, +0.205153f,0.940815f,0.269776f, +0.193253f,0.908579f,0.370322f, +-0.0564604f,0.989265f,0.134783f, +0.0286103f,0.993761f,-0.107795f, +-0.22802f,0.927614f,-0.29587f, +-0.141654f,0.989087f,-0.0405023f, +-0.0918591f,0.979413f,-0.179757f, +0.474817f,0.877478f,-0.067685f, +0.562064f,0.827022f,0.0108876f, +0.0667731f,0.98619f,-0.151561f, +0.0478258f,0.978171f,-0.202223f, +0.240461f,0.955483f,-0.170967f, +0.22331f,0.956303f,-0.188725f, +0.105513f,0.987685f,0.115519f, +0.0191904f,0.988704f,0.148645f, +0.138326f,0.966121f,0.217888f, +0.261136f,0.942738f,0.207491f, +0.283954f,0.937656f,0.20043f, +0.227821f,0.960294f,0.161036f, +0.0632997f,0.956465f,0.284901f, +-0.0487147f,0.902832f,0.427225f, +-0.0448066f,0.869805f,0.491357f, +0.0191513f,0.881775f,0.471282f, +0.0794772f,0.93047f,0.357644f, +0.0542875f,0.971817f,0.2294f, +0.0315472f,0.963796f,0.264769f, +0.140004f,0.919916f,0.36627f, +0.0838185f,0.924915f,0.370818f, +-0.147814f,0.916849f,0.370861f, +-0.285354f,0.864307f,0.414182f, +-0.277978f,0.859855f,0.428226f, +-0.199243f,0.910371f,0.362666f, +0.00801534f,0.941586f,0.336678f, +0.134574f,0.9298f,0.342582f, +0.118153f,0.909557f,0.398429f, +0.0557977f,0.896269f,0.439987f, +-0.0363608f,0.927402f,0.372294f, +-0.166377f,0.978738f,0.119962f, +-0.285966f,0.957794f,-0.0292047f, +-0.233552f,0.97096f,0.0518564f, +-0.131443f,0.981568f,0.138735f, +-0.225195f,0.974079f,0.0213645f, +-0.190643f,0.980844f,0.0400016f, +-0.234677f,0.970688f,0.051878f, +-0.269033f,0.961888f,-0.0489107f, +-0.0845976f,0.996159f,0.0225919f, +-0.404645f,0.907558f,0.112255f, +-0.609864f,0.674076f,0.416758f, +-0.498816f,0.848126f,0.178504f, +-0.144072f,0.987953f,-0.0565038f, +0.166758f,0.948601f,-0.268974f, +0.264567f,0.924612f,0.274038f, +-0.242512f,0.859891f,0.449195f, +-0.469649f,0.864648f,0.178364f, +-0.10506f,0.987899f,0.114094f, +0.522959f,0.850167f,0.0610757f, +0.207342f,0.943984f,-0.256717f, +-0.370985f,0.736513f,-0.565613f, +-0.196204f,0.840957f,-0.504277f, +-0.176697f,0.964208f,-0.197689f, +-0.102305f,0.980589f,-0.167266f, +0.103476f,0.966902f,-0.233225f, +0.176136f,0.882185f,-0.436721f, +0.1356f,0.926363f,-0.351374f, +0.144454f,0.987968f,-0.0552396f, +0.173673f,0.98445f,-0.0263929f, +0.186245f,0.978364f,-0.0900963f, +0.313839f,0.899877f,-0.302865f, +0.0432774f,0.865555f,-0.498941f, +-0.311487f,0.833772f,-0.45585f, +-0.00804547f,0.940342f,-0.340136f, +0.304128f,0.919914f,-0.247515f, +0.693924f,0.703662f,0.152743f, +0.239861f,0.957303f,-0.161363f, +0.0838446f,0.969769f,-0.229169f, +0.258925f,0.935636f,-0.239881f, +0.257223f,0.918931f,-0.299002f, +0.0548176f,0.967903f,0.245271f, +0.0212885f,0.963347f,0.267412f, +0.0818858f,0.973102f,0.215332f, +0.303912f,0.917546f,0.25641f, +0.304793f,0.927062f,0.218307f, +0.238677f,0.941098f,0.239517f, +-0.064428f,0.967965f,0.242677f, +-0.187169f,0.922119f,0.338622f, +-0.088608f,0.904799f,0.416518f, +0.0498324f,0.910793f,0.409846f, +0.176362f,0.913248f,0.367253f, +0.168717f,0.938419f,0.301504f, +0.00502329f,0.962305f,0.271928f, +0.0457173f,0.940418f,0.336934f, +0.0516487f,0.913931f,0.402569f, +-0.133343f,0.891616f,0.432713f, +-0.271457f,0.878825f,0.392399f, +-0.232052f,0.920355f,0.3148f, +-0.147635f,0.961854f,0.230305f, +-0.0156622f,0.96416f,0.264858f, +0.0430262f,0.93984f,0.338894f, +-0.0165403f,0.899263f,0.437095f, +0.0174547f,0.845985f,0.53292f, +0.0913065f,0.841589f,0.532345f, +0.0967863f,0.903784f,0.416901f, +-0.0948439f,0.973273f,0.209153f, +-0.30724f,0.95163f,-0.00197291f, +-0.219507f,0.974242f,0.051671f, +-0.123616f,0.986822f,0.104414f, +-0.209302f,0.977457f,0.0277521f, +-0.245642f,0.966973f,0.0679884f, +-0.189013f,0.970874f,0.147233f, +-0.260969f,0.955926f,0.134541f, +-0.586593f,0.772947f,0.241789f, +-0.622505f,0.744412f,0.241534f, +-0.343069f,0.923585f,0.171158f, +0.270136f,0.949637f,0.158794f, +-0.0270125f,0.976583f,-0.213437f, +-0.293688f,0.905533f,0.306199f, +-0.165876f,0.923469f,0.345963f, +-0.101353f,0.963266f,0.248689f, +-0.0607966f,0.998139f,0.00473307f, +0.571806f,0.81892f,0.04908f, +0.496821f,0.86721f,0.0334054f, +-0.0103979f,0.971297f,-0.237642f, +-0.296903f,0.868994f,-0.395851f, +-0.405401f,0.821757f,-0.400457f, +-0.0724266f,0.96927f,-0.235097f, +0.416989f,0.879556f,-0.229132f, +0.361436f,0.845922f,-0.392148f, +-0.194841f,0.930819f,-0.309213f, +-0.180426f,0.920987f,-0.345297f, +0.16396f,0.957989f,-0.235318f, +0.390246f,0.873397f,-0.291351f, +0.368832f,0.745912f,-0.554597f, +0.0989123f,0.900328f,-0.423823f, +-0.474178f,0.712544f,-0.517143f, +-0.225662f,0.862106f,-0.453707f, +0.0544551f,0.930953f,-0.361055f, +0.547706f,0.827837f,-0.121263f, +0.394416f,0.886974f,-0.240235f, +0.0920684f,0.955894f,-0.278909f, +0.287609f,0.908713f,-0.302524f, +0.34308f,0.875033f,-0.341487f, +-0.0471282f,0.962572f,0.266897f, +0.0309198f,0.953932f,0.298424f, +0.131633f,0.963671f,0.232402f, +0.278528f,0.937297f,0.209515f, +0.282669f,0.933258f,0.221646f, +0.232384f,0.927485f,0.292863f, +-0.0647083f,0.957687f,0.280443f, +-0.249973f,0.928177f,0.275683f, +-0.129841f,0.953629f,0.271538f, +0.0843284f,0.953748f,0.288536f, +0.245794f,0.935145f,0.255127f, +0.172562f,0.957759f,0.230042f, +-0.0230052f,0.954645f,0.296857f, +-0.041189f,0.951248f,0.305663f, +0.00483043f,0.930995f,0.364999f, +-0.165245f,0.915404f,0.367054f, +-0.220878f,0.904299f,0.365316f, +-0.0993279f,0.939818f,0.326919f, +-0.130653f,0.959943f,0.247869f, +-0.122986f,0.930904f,0.343936f, +-0.00592517f,0.911134f,0.412068f, +-0.1345f,0.9137f,0.383488f, +-0.0693903f,0.866333f,0.494623f, +0.121472f,0.852483f,0.508447f, +0.210048f,0.85163f,0.480215f, +0.0819942f,0.889969f,0.448588f, +-0.0885916f,0.940837f,0.327072f, +-0.228328f,0.96901f,0.0942702f, +-0.142437f,0.987843f,0.0622738f, +-0.157298f,0.987135f,0.0286638f, +-0.320718f,0.947161f,0.00499032f, +-0.336449f,0.936473f,0.0990975f, +-0.304779f,0.919932f,0.246646f, +-0.589969f,0.761912f,0.267259f, +-0.577652f,0.799842f,0.163009f, +-0.2738f,0.948238f,0.160868f, +0.240449f,0.968762f,0.0607085f, +-0.0196269f,0.999224f,-0.0341484f, +-0.384279f,0.908117f,0.166292f, +-0.0937293f,0.985711f,0.139963f, +0.0542133f,0.980144f,0.190731f, +0.0177665f,0.999043f,0.039964f, +0.448192f,0.892243f,0.0550135f, +0.417622f,0.800327f,0.430197f, +0.199972f,0.838529f,0.506833f, +-0.0526069f,0.975321f,0.214434f, +-0.547935f,0.818163f,-0.174291f, +-0.280437f,0.954205f,-0.10415f, +0.341739f,0.938698f,0.0453871f, +0.346269f,0.925369f,0.15424f, +-0.319444f,0.944119f,0.0812127f, +-0.192857f,0.977783f,0.0821343f, +0.335818f,0.935599f,-0.108997f, +0.474712f,0.785031f,-0.397964f, +0.373974f,0.907089f,-0.193218f, +0.0523306f,0.977738f,-0.203201f, +-0.41385f,0.870502f,-0.266372f, +-0.377073f,0.911356f,-0.165066f, +0.0445989f,0.977381f,-0.206731f, +0.525837f,0.831576f,-0.178819f, +0.378975f,0.901633f,-0.208411f, +0.088353f,0.958416f,-0.271353f, +0.309469f,0.925076f,-0.220144f, +0.420279f,0.904173f,-0.0763995f, +0.00329705f,0.962532f,0.271149f, +0.0784063f,0.967252f,0.241403f, +0.186812f,0.966508f,0.175965f, +0.294591f,0.944303f,0.146656f, +0.242144f,0.958708f,0.149151f, +0.122249f,0.946777f,0.297772f, +-0.0273117f,0.906407f,0.421521f, +-0.206066f,0.9181f,0.338568f, +-0.0954796f,0.950658f,0.295183f, +0.102184f,0.964671f,0.242834f, +0.213961f,0.952875f,0.215059f, +0.119187f,0.935673f,0.33213f, +-0.0431159f,0.926594f,0.373584f, +-0.0072858f,0.954565f,0.297913f, +-0.0455381f,0.966183f,0.253806f, +-0.154593f,0.937454f,0.311898f, +-0.199077f,0.936411f,0.288969f, +-0.136466f,0.95497f,0.263457f, +-0.127877f,0.920831f,0.3684f, +-0.229636f,0.912787f,0.337767f, +-0.0324452f,0.91205f,0.408794f, +-0.100812f,0.892675f,0.439282f, +-0.166782f,0.900555f,0.401477f, +0.102011f,0.876619f,0.470247f, +0.195025f,0.830402f,0.521918f, +0.0914158f,0.843587f,0.529154f, +0.0626366f,0.873316f,0.48311f, +-0.00226622f,0.929744f,0.3682f, +-0.0934177f,0.966149f,0.240479f, +-0.109555f,0.963702f,0.243468f, +-0.302241f,0.931855f,0.200739f, +-0.368178f,0.918352f,0.145171f, +-0.476623f,0.864028f,0.162128f, +-0.569304f,0.726984f,0.383911f, +-0.64096f,0.755201f,0.137264f, +-0.241026f,0.942011f,0.233501f, +0.376487f,0.905115f,0.197547f, +0.13011f,0.991259f,-0.0218225f, +-0.643013f,0.733979f,-0.218653f, +-0.19089f,0.942227f,0.275264f, +-0.00867818f,0.931663f,0.363219f, +0.146287f,0.916711f,0.371809f, +0.32054f,0.88208f,0.345239f, +0.0976689f,0.827123f,0.55347f, +0.0475977f,0.818583f,0.572413f, +0.312042f,0.775215f,0.549246f, +-0.398647f,0.872033f,0.283969f, +-0.297551f,0.880657f,0.368657f, +0.0684096f,0.950263f,0.303844f, +0.473417f,0.718991f,0.50885f, +-0.0712795f,0.964076f,0.255885f, +-0.187608f,0.981414f,0.0403824f, +0.441688f,0.892595f,0.090477f, +0.402228f,0.910874f,0.0923076f, +0.356001f,0.889285f,0.287114f, +0.109119f,0.990916f,0.0786044f, +-0.366364f,0.926283f,0.0881909f, +-0.361407f,0.913864f,0.185034f, +0.114451f,0.98516f,0.127909f, +0.511212f,0.854805f,0.0892759f, +0.488262f,0.865451f,0.112231f, +0.135362f,0.990178f,0.0350016f, +0.158924f,0.983832f,0.0825671f, +0.139428f,0.973099f,0.183407f, +-0.0124598f,0.997106f,0.0750005f, +0.111778f,0.989445f,0.0922193f, +0.245419f,0.967744f,0.0569325f, +0.2823f,0.95863f,0.0365395f, +0.172017f,0.973333f,0.151766f, +-0.129296f,0.953534f,0.27213f, +-0.0899396f,0.877846f,0.470422f, +-0.0963581f,0.899855f,0.425413f, +-0.0212856f,0.934761f,0.354638f, +0.147549f,0.94824f,0.281195f, +0.129526f,0.93959f,0.316849f, +0.0223606f,0.903767f,0.427441f, +-0.0124316f,0.909175f,0.41623f, +0.115235f,0.910193f,0.397831f, +-0.0283739f,0.950232f,0.310248f, +-0.203804f,0.932573f,0.297946f, +-0.13899f,0.955458f,0.260347f, +-0.204301f,0.958838f,0.197208f, +-0.229868f,0.915186f,0.331053f, +-0.132513f,0.91447f,0.38234f, +-0.151493f,0.940711f,0.3035f, +-0.124022f,0.907796f,0.400656f, +-0.112999f,0.914934f,0.387462f, +-0.039891f,0.908327f,0.416355f, +0.0930682f,0.835427f,0.541664f, +0.161351f,0.801381f,0.575981f, +0.131487f,0.83942f,0.527339f, +0.132693f,0.857332f,0.497367f, +-0.0832448f,0.920852f,0.380923f, +-0.145993f,0.894645f,0.422252f, +-0.213236f,0.888697f,0.405893f, +-0.293641f,0.888131f,0.353551f, +-0.525155f,0.788991f,0.318912f, +-0.588027f,0.679363f,0.438964f, +-0.478637f,0.812929f,0.331743f, +-0.264049f,0.917426f,0.297671f, +0.302963f,0.900818f,0.31103f, +0.420369f,0.80167f,0.424988f, +-0.470879f,0.867699f,0.159284f, +-0.530406f,0.817263f,0.225279f, +-0.0411983f,0.860627f,0.507566f, +0.103255f,0.833118f,0.543372f, +0.186539f,0.814428f,0.549463f, +0.132619f,0.779192f,0.612594f, +0.0761138f,0.83531f,0.544485f, +0.378863f,0.611781f,0.694397f, +-0.172003f,0.719417f,0.672944f, +-0.295852f,0.804769f,0.514605f, +0.0593285f,0.827842f,0.557814f, +0.323809f,0.743921f,0.584575f, +0.339913f,0.758357f,0.556197f, +-0.00694706f,0.946602f,0.322331f, +0.188872f,0.934445f,0.301895f, +0.251044f,0.713229f,0.654432f, +0.351195f,0.638214f,0.685087f, +0.295602f,0.899369f,0.322109f, +-0.450583f,0.880167f,0.14927f, +-0.375985f,0.904392f,0.201769f, +0.158376f,0.94847f,0.274448f, +0.500024f,0.831884f,0.240719f, +0.503159f,0.8293f,0.243089f, +0.0889199f,0.964326f,0.249335f, +0.108789f,0.932871f,0.34339f, +0.066105f,0.944864f,0.320722f, +-0.09433f,0.994124f,-0.0530892f, +0.0903529f,0.995715f,-0.0196726f, +0.246451f,0.969124f,-0.00783612f, +0.17532f,0.977334f,0.118663f, +0.0145033f,0.945036f,0.326645f, +-0.208385f,0.89773f,0.388145f, +-0.186403f,0.920929f,0.342264f, +-0.0196042f,0.920127f,0.391129f, +0.088861f,0.938743f,0.332966f, +0.0904885f,0.955513f,0.280725f, +0.00776342f,0.887041f,0.461625f, +0.0357997f,0.855618f,0.516368f, +0.0251977f,0.899984f,0.435195f, +0.113155f,0.898436f,0.424273f, +0.0488401f,0.928538f,0.36801f, +-0.122117f,0.962671f,0.241562f, +-0.0832756f,0.977563f,0.193483f, +-0.182752f,0.960599f,0.209407f, +-0.340533f,0.923546f,0.176353f, +-0.207225f,0.949201f,0.236801f, +-0.0875863f,0.939463f,0.331268f, +-0.156293f,0.945917f,0.284277f, +-0.15128f,0.944026f,0.293135f, +-0.133917f,0.921967f,0.363377f, +-0.0187779f,0.901995f,0.431337f, +0.137151f,0.859664f,0.492105f, +0.151864f,0.841546f,0.518398f, +0.169983f,0.832825f,0.526791f, +0.0329472f,0.8585f,0.511754f, +-0.148058f,0.877168f,0.456787f, +-0.179554f,0.872912f,0.453636f, +-0.29061f,0.863835f,0.411502f, +-0.582219f,0.748049f,0.318501f, +-0.586418f,0.753548f,0.297117f, +-0.423744f,0.867437f,0.260755f, +-0.266814f,0.914007f,0.305617f, +0.297036f,0.879751f,0.371224f, +0.301464f,0.846429f,0.438951f, +-0.267915f,0.8201f,0.505626f, +-0.708126f,0.705156f,0.0362171f, +-0.280503f,0.856013f,0.434234f, +0.0634361f,0.843315f,0.533662f, +0.203328f,0.848496f,0.488581f, +0.157757f,0.86266f,0.480552f, +-0.0108627f,0.875364f,0.483343f, +-0.00732908f,0.804113f,0.594431f, +0.217513f,0.756413f,0.616869f, +-0.242879f,0.903897f,0.352108f, +-0.0770731f,0.775477f,0.626654f, +0.238061f,0.731126f,0.639361f, +0.459013f,0.658034f,0.596908f, +0.0332364f,0.855326f,0.517022f, +-0.132848f,0.766918f,0.627844f, +-0.0252308f,0.840734f,0.54086f, +0.442735f,0.688282f,0.574677f, +0.624206f,0.545029f,0.559742f, +-0.216833f,0.89857f,0.381516f, +-0.428783f,0.890698f,0.151005f, +0.076598f,0.986116f,0.147334f, +0.479671f,0.865386f,0.144994f, +0.542246f,0.827427f,0.146065f, +0.100899f,0.969794f,0.222079f, +0.0591096f,0.972132f,0.226859f, +0.163564f,0.950136f,0.265495f, +-0.0539816f,0.998166f,0.0273959f, +0.085626f,0.996323f,0.00278248f, +0.159482f,0.986364f,0.0406345f, +-0.0565903f,0.982572f,0.177057f, +-0.167853f,0.932231f,0.320579f, +-0.135579f,0.92648f,0.351075f, +-0.12175f,0.950039f,0.287407f, +-0.0275f,0.960651f,0.276393f, +0.0945575f,0.956567f,0.27575f, +0.0118837f,0.934274f,0.356358f, +-0.160104f,0.889888f,0.42716f, +0.0609856f,0.903744f,0.423707f, +0.121664f,0.922268f,0.366906f, +0.148425f,0.946235f,0.287418f, +0.23463f,0.944122f,0.231479f, +-0.0440541f,0.996345f,0.0731815f, +-0.127251f,0.98255f,0.135658f, +-0.207412f,0.958865f,0.1938f, +-0.296871f,0.939382f,0.171549f, +-0.278192f,0.946498f,0.163558f, +-0.178451f,0.945897f,0.270988f, +-0.115294f,0.937073f,0.329548f, +-0.175206f,0.945254f,0.275312f, +-0.191323f,0.939359f,0.284604f, +-0.0822793f,0.949627f,0.302389f, +0.0583847f,0.93226f,0.357046f, +0.125066f,0.884667f,0.449136f, +0.147347f,0.866347f,0.477213f, +0.0545541f,0.865292f,0.49829f, +-0.098516f,0.887377f,0.450395f, +-0.209769f,0.897417f,0.388122f, +-0.210182f,0.881546f,0.422729f, +-0.451263f,0.852365f,0.264264f, +-0.650724f,0.758775f,-0.0286192f, +-0.407582f,0.890583f,0.201838f, +-0.388367f,0.887583f,0.247725f, +0.193188f,0.884808f,0.424019f, +0.215311f,0.880386f,0.422566f, +-0.165147f,0.855262f,0.491176f, +-0.520864f,0.795129f,0.310596f, +-0.488998f,0.786967f,0.37625f, +0.0562235f,0.868104f,0.493187f, +0.400928f,0.84731f,0.348313f, +0.199813f,0.978725f,-0.0465961f, +-0.198621f,0.97682f,0.0798329f, +-0.0891351f,0.888352f,0.450429f, +0.204835f,0.834736f,0.511135f, +-0.0720813f,0.941881f,0.328121f, +-0.196291f,0.972713f,0.123691f, +0.179787f,0.980826f,-0.0752149f, +0.511674f,0.853811f,0.0958982f, +0.0191479f,0.909767f,0.414677f, +-0.125562f,0.89333f,0.431505f, +0.22305f,0.943278f,0.245918f, +0.527748f,0.84488f,0.0875187f, +0.598212f,0.799615f,-0.0525252f, +0.0107332f,0.903361f,0.428747f, +-0.300811f,0.914951f,0.269032f, +0.179787f,0.975264f,0.128593f, +0.519301f,0.854591f,0.00126655f, +0.419398f,0.906587f,-0.0469514f, +0.0522982f,0.994257f,0.0933686f, +0.0513278f,0.996267f,0.0694112f, +0.103651f,0.993237f,0.0523089f, +0.0555975f,0.984758f,0.164805f, +0.0862163f,0.988349f,0.12543f, +0.0909734f,0.981273f,0.169784f, +-0.14512f,0.970727f,0.191388f, +-0.180918f,0.953611f,0.240612f, +-0.140102f,0.96533f,0.22025f, +-0.119189f,0.970295f,0.210526f, +-0.0126783f,0.974075f,0.225869f, +0.0237961f,0.97809f,0.20682f, +-0.0862872f,0.95413f,0.286688f, +-0.14433f,0.944949f,0.293667f, +0.132869f,0.954959f,0.265329f, +0.22733f,0.94991f,0.214458f, +0.185536f,0.968744f,0.164655f, +0.30218f,0.927213f,0.221277f, +-0.010566f,0.987352f,0.158194f, +-0.227641f,0.957817f,0.175404f, +-0.212635f,0.950922f,0.224799f, +-0.288872f,0.93765f,0.193302f, +-0.303211f,0.936666f,0.175273f, +-0.283958f,0.943546f,0.170553f, +-0.13575f,0.960553f,0.242714f, +-0.0816944f,0.973992f,0.211345f, +-0.191701f,0.977982f,0.0824724f, +-0.110352f,0.986199f,0.123427f, +-0.0409453f,0.971384f,0.233958f, +0.0185038f,0.933683f,0.357621f, +0.13477f,0.907601f,0.397615f, +0.0792432f,0.925049f,0.371489f, +-0.0350852f,0.929789f,0.366418f, +-0.159548f,0.910971f,0.380363f, +-0.245138f,0.905643f,0.346003f, +-0.179352f,0.926492f,0.330825f, +-0.589052f,0.80668f,0.0478056f, +-0.578625f,0.779472f,0.240033f, +-0.471687f,0.839166f,0.270762f, +0.0987404f,0.916105f,0.388589f, +0.173592f,0.831445f,0.527792f, +-0.220086f,0.704489f,0.674728f, +-0.395802f,0.62503f,0.672813f, +-0.417304f,0.755058f,0.505712f, +0.0513487f,0.865997f,0.497406f, +0.431689f,0.734124f,0.524124f, +0.359032f,0.884637f,0.297512f, +-0.308259f,0.930686f,0.196975f, +-0.34698f,0.877125f,0.332049f, +0.00851592f,0.919266f,0.393545f, +0.326193f,0.840272f,0.433061f, +0.261231f,0.960149f,-0.0993615f, +0.388612f,0.889039f,-0.242053f, +0.0354931f,0.979528f,-0.198152f, +0.0485316f,0.907873f,0.416427f, +-0.0781845f,0.964592f,0.251892f, +0.47974f,0.876345f,0.0432286f, +0.568817f,0.783907f,-0.248873f, +0.483889f,0.834837f,-0.262485f, +-0.220496f,0.975376f,0.00471288f, +-0.25449f,0.933474f,0.252706f, +0.326168f,0.921789f,0.209569f, +0.609761f,0.790958f,0.0507595f, +0.419183f,0.900774f,-0.11354f, +-0.0389936f,0.992704f,-0.114095f, +0.112818f,0.992086f,-0.0551048f, +0.140261f,0.98577f,-0.0926471f, +0.0460285f,0.981507f,0.185811f, +0.0839854f,0.981486f,0.172137f, +0.0780195f,0.983837f,0.161178f, +-0.135272f,0.977846f,0.159743f, +-0.233239f,0.960885f,0.149328f, +-0.119476f,0.978748f,0.166665f, +-0.0623017f,0.991047f,0.118089f, +-0.0310067f,0.999432f,0.0132292f, +-0.0037253f,0.997112f,0.0758502f, +-0.0758016f,0.98526f,0.153355f, +-0.143296f,0.988211f,0.0539015f, +0.103486f,0.991653f,0.076914f, +0.266632f,0.947722f,0.175298f, +0.164045f,0.978994f,0.121078f, +0.196418f,0.969063f,0.149458f, +0.0648458f,0.968138f,0.241876f, +-0.21695f,0.963194f,0.158716f, +-0.238014f,0.956133f,0.17076f, +-0.251543f,0.948014f,0.194926f, +-0.241597f,0.958745f,0.149794f, +-0.248822f,0.966568f,0.0619263f, +-0.195635f,0.9804f,0.0233089f, +0.00681016f,0.994726f,0.102342f, +-0.0728308f,0.997328f,0.00570638f, +-0.223928f,0.970021f,-0.0944255f, +-0.201047f,0.979434f,0.0169867f, +-0.100278f,0.986057f,0.132801f, +0.129703f,0.962794f,0.237074f, +0.129196f,0.949613f,0.28556f, +-0.100355f,0.959332f,0.263838f, +-0.226831f,0.927446f,0.297306f, +-0.211803f,0.921673f,0.325051f, +-0.16781f,0.90652f,0.387378f, +-0.507141f,0.76624f,0.394569f, +-0.499456f,0.740703f,0.449336f, +-0.375574f,0.865361f,0.331805f, +0.0665425f,0.96722f,0.245068f, +-0.127974f,0.946728f,0.295513f, +-0.531445f,0.627941f,0.568557f, +-0.268657f,0.746051f,0.609287f, +-0.123398f,0.84105f,0.526695f, +0.113268f,0.868801f,0.482033f, +0.278975f,0.860996f,0.425274f, +0.256512f,0.783766f,0.565608f, +0.24637f,0.788587f,0.563411f, +-0.207735f,0.977522f,-0.036006f, +0.0390118f,0.996098f,0.0791601f, +0.408253f,0.910351f,0.0677493f, +0.466297f,0.863647f,-0.191525f, +0.226125f,0.967725f,-0.111247f, +-0.24034f,0.965221f,0.102887f, +-0.130757f,0.944853f,0.300258f, +0.283435f,0.943407f,0.172188f, +0.590839f,0.8059f,-0.0378747f, +0.573782f,0.756596f,-0.313587f, +0.355206f,0.926281f,0.12583f, +-0.219704f,0.910923f,0.349212f, +-0.277723f,0.959254f,0.051969f, +0.340807f,0.938572f,0.0541606f, +0.677372f,0.729826f,0.0923128f, +0.49544f,0.867668f,-0.0411347f, +-0.024834f,0.981688f,-0.188872f, +0.050519f,0.974996f,-0.216403f, +0.180767f,0.970256f,-0.161015f, +0.0401148f,0.977494f,0.207113f, +0.106256f,0.969045f,0.222848f, +0.0969035f,0.97128f,0.217314f, +-0.118574f,0.978564f,0.16838f, +-0.194437f,0.978726f,0.0655019f, +-0.11441f,0.993427f,0.0037257f, +0.00229181f,0.999514f,0.0311045f, +0.0309142f,0.998007f,0.0550047f, +-0.113357f,0.989867f,0.085516f, +-0.111292f,0.980012f,0.164894f, +-0.0212066f,0.993646f,0.110539f, +0.0241257f,0.999577f,-0.0162417f, +0.157698f,0.982481f,0.0993122f, +0.222931f,0.950361f,0.21706f, +0.18078f,0.964986f,0.190052f, +0.0702985f,0.98108f,0.180387f, +-0.190259f,0.977665f,0.089291f, +-0.268574f,0.956136f,0.116926f, +-0.267756f,0.955804f,0.121429f, +-0.211446f,0.969418f,0.124579f, +-0.14687f,0.983484f,0.105776f, +-0.198985f,0.979945f,-0.0106117f, +-0.0887412f,0.995564f,0.0312775f, +0.0104704f,0.992989f,0.117739f, +-0.125001f,0.9915f,0.0360868f, +-0.238906f,0.968221f,-0.0739686f, +-0.167029f,0.981518f,-0.0933989f, +-0.0351406f,0.998931f,-0.030045f, +0.0130186f,0.974123f,0.225643f, +-0.0745329f,0.922898f,0.377762f, +-0.18971f,0.916591f,0.351953f, +-0.286917f,0.902381f,0.321538f, +-0.328487f,0.84853f,0.414841f, +-0.591704f,0.685127f,0.424839f, +-0.448564f,0.796089f,0.406241f, +-0.170353f,0.888356f,0.426384f, +-0.00830475f,0.908708f,0.417349f, +-0.140027f,0.883683f,0.446651f, +-0.599598f,0.727182f,0.334197f, +-0.234879f,0.924162f,0.301258f, +-0.0954672f,0.951872f,0.291248f, +0.100155f,0.948228f,0.301383f, +0.352663f,0.898478f,0.261471f, +0.217902f,0.956165f,0.19562f, +0.428441f,0.89557f,0.119967f, +0.0504867f,0.972497f,-0.227379f, +-0.160086f,0.98254f,-0.0948013f, +0.319131f,0.945228f,-0.0685555f, +0.64992f,0.715088f,0.257397f, +0.0361031f,0.995429f,0.0884124f, +-0.2599f,0.897768f,0.355618f, +-0.17567f,0.983498f,0.0432638f, +0.53944f,0.841427f,-0.0317039f, +0.60742f,0.697232f,-0.380669f, +0.609044f,0.790595f,-0.063438f, +-0.195234f,0.980448f,0.0245981f, +-0.224173f,0.885759f,0.406419f, +0.0964403f,0.992198f,0.0790071f, +0.380926f,0.892571f,-0.241272f, +0.532566f,0.777301f,-0.334927f, +0.58332f,0.811668f,0.0305478f, +0.122052f,0.989417f,-0.0784701f, +0.094933f,0.975516f,-0.198385f, +0.104703f,0.956209f,-0.273317f, +0.0116109f,0.989434f,0.144515f, +0.0514824f,0.974923f,0.216505f, +0.096067f,0.950842f,0.294399f, +0.00976988f,0.964716f,0.263111f, +-0.0931121f,0.98126f,0.168699f, +-0.0745948f,0.982842f,0.168693f, +-0.083139f,0.982475f,0.166825f, +-0.0763046f,0.97088f,0.22709f, +-0.130809f,0.960701f,0.244832f, +-0.117161f,0.974629f,0.190711f, +0.0735371f,0.976475f,0.202706f, +0.123062f,0.984428f,0.125529f, +0.0660058f,0.995943f,0.0611663f, +0.0811078f,0.98996f,0.115763f, +0.156048f,0.953727f,0.257008f, +0.12971f,0.935453f,0.32879f, +-0.0928149f,0.955298f,0.280698f, +-0.264252f,0.949049f,0.171686f, +-0.241724f,0.966072f,0.0909662f, +-0.244999f,0.96713f,0.0680795f, +-0.106995f,0.982895f,0.149898f, +-0.106861f,0.990227f,0.089616f, +-0.133621f,0.990932f,0.0141138f, +-0.0517957f,0.998024f,0.0355675f, +-0.0225779f,0.998718f,0.0453005f, +-0.144281f,0.986502f,-0.0774439f, +-0.157036f,0.983398f,-0.0909287f, +-0.161108f,0.986936f,-0.00118469f, +-0.22235f,0.965394f,0.136287f, +-0.250578f,0.942366f,0.221715f, +-0.217658f,0.901831f,0.373264f, +-0.29708f,0.848133f,0.438651f, +-0.36269f,0.819581f,0.443558f, +-0.534096f,0.793842f,0.290785f, +-0.584404f,0.811192f,0.0209707f, +-0.1404f,0.905222f,0.401075f, +-0.307079f,0.89418f,0.325797f, +-0.27164f,0.834087f,0.480115f, +-0.322843f,0.946322f,0.0157466f, +-0.301281f,0.933652f,-0.193713f, +-0.127165f,0.985755f,0.11007f, +0.121812f,0.97858f,0.165962f, +0.500139f,0.864928f,0.0419482f, +0.30357f,0.892132f,-0.334582f, +0.443241f,0.85073f,-0.282481f, +0.0967978f,0.993781f,0.0550442f, +-0.201565f,0.978713f,0.0386423f, +0.209591f,0.974539f,0.0796601f, +0.481917f,0.851558f,0.20641f, +-0.0224044f,0.977009f,0.212016f, +-0.238315f,0.88567f,0.398491f, +0.220358f,0.960844f,0.167992f, +0.601263f,0.791797f,-0.107428f, +0.618362f,0.741713f,-0.25979f, +0.284452f,0.956119f,0.0701626f, +-0.201478f,0.913131f,0.3544f, +-0.20526f,0.978252f,0.0298624f, +0.352634f,0.929538f,-0.107737f, +0.649062f,0.752634f,-0.110725f, +0.490387f,0.729272f,-0.477162f, +0.431974f,0.874843f,-0.219197f, +0.184608f,0.975155f,-0.122446f, +0.192786f,0.978517f,-0.0730681f, +0.240097f,0.966116f,-0.094733f, +-0.255309f,0.963455f,-0.0810722f, +-0.124334f,0.990531f,0.0582188f, +0.042075f,0.979967f,0.194667f, +0.0324324f,0.965776f,0.25734f, +-0.0760147f,0.965606f,0.248649f, +-0.138926f,0.972343f,0.187746f, +-0.0932442f,0.974882f,0.202264f, +-0.0380092f,0.975147f,0.218276f, +-0.0242537f,0.984345f,0.174576f, +-0.0724602f,0.995976f,0.0527463f, +0.0175716f,0.997526f,0.068069f, +0.191598f,0.97051f,0.146287f, +0.0888492f,0.992747f,0.0809944f, +0.0509079f,0.989914f,0.132209f, +0.0413152f,0.988953f,0.142354f, +-0.00590782f,0.97647f,0.215574f, +-0.0327876f,0.94937f,0.312443f, +-0.0862721f,0.978712f,0.186225f, +-0.179337f,0.981669f,0.0645377f, +-0.255621f,0.960924f,0.106226f, +-0.157413f,0.981394f,0.109943f, +-0.0325878f,0.996293f,0.0796149f, +-0.0627116f,0.997982f,-0.00999288f, +-0.0263234f,0.995733f,-0.0884504f, +0.00359159f,0.990572f,-0.136946f, +-0.0963f,0.991181f,-0.0910356f, +-0.255814f,0.966717f,-0.00409974f, +-0.292954f,0.950051f,0.107618f, +-0.259513f,0.946888f,0.189886f, +-0.274998f,0.934354f,0.226623f, +-0.37248f,0.885745f,0.276974f, +-0.384203f,0.849481f,0.361622f, +-0.326853f,0.86434f,0.382208f, +-0.213332f,0.922586f,0.321442f, +-0.528611f,0.848285f,0.0313709f, +-0.466119f,0.869006f,0.166018f, +-0.226659f,0.921685f,0.314837f, +-0.225942f,0.929604f,0.291181f, +0.262979f,0.943638f,0.200972f, +-0.158823f,0.970135f,-0.183342f, +-0.433654f,0.893597f,-0.115884f, +0.0458639f,0.99877f,-0.0188405f, +0.612149f,0.789064f,0.0514904f, +0.423383f,0.878106f,-0.222881f, +0.0967751f,0.930754f,-0.352606f, +0.0811144f,0.996202f,0.0316668f, +-0.413686f,0.895072f,-0.166465f, +0.148131f,0.951189f,0.270735f, +0.436798f,0.864787f,0.247692f, +0.0437864f,0.959427f,0.278536f, +-0.28501f,0.956226f,0.0663364f, +0.510274f,0.859616f,0.0260981f, +0.648806f,0.686419f,-0.328451f, +0.586912f,0.808674f,0.0397475f, +-0.0852935f,0.966768f,0.241009f, +-0.148057f,0.961052f,0.233361f, +0.164136f,0.983527f,-0.0757203f, +0.450314f,0.849987f,-0.273386f, +0.550526f,0.728504f,-0.407679f, +0.58281f,0.780161f,-0.227338f, +0.258267f,0.941325f,-0.21727f, +0.0807909f,0.98982f,-0.117172f, +0.0801488f,0.996327f,0.0301511f, +0.239863f,0.961671f,0.132871f, +-0.229647f,0.969202f,0.0889415f, +-0.172859f,0.981826f,0.0783421f, +-0.0626565f,0.996388f,0.0573105f, +-0.0572909f,0.992727f,0.105883f, +-0.0279351f,0.983375f,0.179427f, +-0.00285096f,0.99214f,0.125102f, +-0.084025f,0.99632f,-0.0168937f, +-0.0732377f,0.997041f,-0.0233556f, +-0.0045065f,0.999839f,0.0173404f, +0.0203121f,0.999722f,0.0119547f, +-0.0506539f,0.996487f,-0.0666886f, +0.119651f,0.992498f,0.0251293f, +0.0686084f,0.989615f,0.126312f, +0.000108814f,0.982339f,0.187109f, +0.0874025f,0.98865f,0.122196f, +-0.0625717f,0.997577f,0.0304034f, +-0.0486926f,0.992353f,0.113426f, +0.0140738f,0.989644f,0.142855f, +-0.151919f,0.980609f,0.123804f, +-0.280176f,0.959074f,0.0409668f, +-0.112828f,0.992642f,-0.0439511f, +0.0530002f,0.995827f,-0.0742939f, +0.0297885f,0.985001f,-0.169959f, +0.0528437f,0.970999f,-0.233169f, +-0.0380639f,0.977109f,-0.209305f, +-0.249056f,0.968138f,-0.0260696f, +-0.370842f,0.913812f,0.165599f, +-0.310025f,0.907402f,0.283736f, +-0.313659f,0.908343f,0.276641f, +-0.360766f,0.88042f,0.307747f, +-0.383668f,0.851108f,0.358349f, +-0.392242f,0.857478f,0.332984f, +-0.296931f,0.900087f,0.318865f, +-0.199402f,0.936164f,0.289543f, +-0.412291f,0.885214f,0.215434f, +-0.62242f,0.781068f,-0.0502514f, +-0.272781f,0.928261f,0.252828f, +-0.317665f,0.921151f,0.224876f, +0.0813846f,0.925309f,0.370378f, +0.00278871f,0.889899f,0.45615f, +-0.460626f,0.879338f,0.120782f, +0.0601251f,0.985077f,0.161272f, +0.599887f,0.787248f,0.142742f, +0.617017f,0.753279f,0.227729f, +0.13665f,0.981422f,0.134675f, +0.136502f,0.974756f,0.176687f, +-0.27066f,0.954113f,-0.128105f, +-0.13295f,0.980241f,-0.146465f, +0.409773f,0.909514f,-0.0697851f, +0.339811f,0.93455f,0.10557f, +-0.243979f,0.943604f,-0.223798f, +0.572252f,0.820076f,0.00181093f, +0.58136f,0.813444f,0.0181706f, +0.213313f,0.927464f,0.307095f, +-0.0427767f,0.853854f,0.518751f, +0.0717407f,0.97577f,0.206702f, +0.349298f,0.936925f,0.0127626f, +0.643074f,0.765767f,0.00757208f, +0.584117f,0.763349f,-0.275872f, +0.414478f,0.906497f,-0.0804466f, +0.213842f,0.975055f,-0.0594842f, +-0.00469446f,0.990505f,-0.137399f, +-0.0685672f,0.992236f,-0.103764f, +0.0844774f,0.996384f,-0.00904741f, +-0.320391f,0.938064f,0.131853f, +-0.173519f,0.96335f,0.204565f, +-0.0123366f,0.973468f,0.228492f, +-0.018009f,0.983892f,0.177855f, +-0.10447f,0.992257f,0.0671745f, +0.0409931f,0.988078f,0.148399f, +0.0370075f,0.994865f,0.0941976f, +-0.0471895f,0.997972f,-0.0427132f, +-0.0371271f,0.993135f,-0.110921f, +0.0109117f,0.996203f,-0.0863686f, +0.0455917f,0.995961f,-0.0773449f, +-0.0321894f,0.986545f,-0.160288f, +-0.0649603f,0.996397f,0.0545189f, +0.00369488f,0.985567f,0.169244f, +0.226168f,0.962189f,0.151787f, +0.029392f,0.999567f,0.00117257f, +-0.13579f,0.984206f,-0.113581f, +-0.10103f,0.992288f,-0.0718192f, +-0.125171f,0.991084f,0.0456533f, +-0.108309f,0.993989f,0.015999f, +-0.0231464f,0.995269f,-0.0943563f, +0.0270486f,0.99325f,-0.112795f, +0.141677f,0.989359f,-0.0331051f, +0.0268575f,0.994547f,-0.100767f, +-0.194101f,0.980932f,0.009818f, +-0.41139f,0.899763f,0.145547f, +-0.482013f,0.8562f,0.185973f, +-0.415606f,0.872343f,0.257468f, +-0.291757f,0.884021f,0.365218f, +-0.316561f,0.886381f,0.337814f, +-0.406f,0.884827f,0.22857f, +-0.363525f,0.905831f,0.217534f, +-0.301242f,0.93366f,0.193734f, +-0.208193f,0.941974f,0.263325f, +-0.164184f,0.932027f,0.323063f, +-0.4694f,0.88027f,-0.0691917f, +-0.525104f,0.840943f,-0.130688f, +-0.256903f,0.950739f,0.17348f, +-0.180022f,0.968548f,0.171775f, +0.0734506f,0.860739f,0.50372f, +-0.205317f,0.895889f,0.393991f, +0.0472127f,0.984089f,0.171289f, +0.492639f,0.869295f,-0.040419f, +0.615313f,0.776504f,0.135761f, +0.240143f,0.940103f,0.241946f, +0.0961855f,0.982412f,0.160044f, +0.107308f,0.976554f,0.186622f, +-0.0192621f,0.988216f,-0.151846f, +0.243819f,0.934285f,-0.260122f, +0.363158f,0.92047f,-0.144401f, +-0.0181857f,0.911833f,-0.410158f, +0.13216f,0.935755f,-0.326948f, +0.234069f,0.876493f,0.42068f, +-0.0429998f,0.864233f,0.501251f, +0.30178f,0.838678f,0.453374f, +0.334916f,0.905993f,0.258858f, +0.486799f,0.865003f,0.121641f, +0.551114f,0.813232f,-0.186886f, +0.639118f,0.75121f,0.164956f, +0.383938f,0.890692f,0.243432f, +0.354878f,0.921145f,0.159855f, +0.162961f,0.98584f,-0.0395363f, +-0.0637937f,0.974986f,-0.212914f, +-0.0365262f,0.968846f,-0.244954f, +-0.281965f,0.951785f,0.120834f, +-0.274882f,0.955225f,0.109473f, +-0.104135f,0.948711f,0.298502f, +0.0826411f,0.912269f,0.401168f, +0.0342531f,0.97031f,0.239425f, +-0.0365634f,0.991589f,0.124154f, +0.134024f,0.975461f,0.174679f, +0.109589f,0.99345f,0.032348f, +0.0453955f,0.994687f,-0.0923934f, +-0.0149079f,0.988982f,-0.147281f, +0.0512217f,0.992549f,-0.110554f, +0.0167819f,0.988638f,-0.149377f, +-0.222271f,0.949144f,-0.222982f, +-0.0921327f,0.987637f,-0.126823f, +0.189567f,0.98184f,-0.00744372f, +0.205171f,0.976356f,0.0680753f, +-0.00982996f,0.993812f,-0.110639f, +-0.0883427f,0.978311f,-0.18736f, +-0.198236f,0.955921f,-0.216604f, +-0.180283f,0.972159f,-0.149685f, +0.0029493f,0.99947f,-0.0324137f, +-0.0433514f,0.998534f,-0.0324142f, +0.0405175f,0.99421f,0.0995223f, +0.00286263f,0.981263f,0.19265f, +-0.296663f,0.921382f,0.251091f, +-0.412123f,0.867858f,0.277446f, +-0.439996f,0.871969f,0.214648f, +-0.457669f,0.875232f,0.156552f, +-0.384822f,0.899193f,0.208242f, +-0.276213f,0.916653f,0.288882f, +-0.314226f,0.91283f,0.260774f, +-0.345662f,0.91535f,0.206522f, +-0.311859f,0.934366f,0.17235f, +-0.323293f,0.931681f,0.165688f, +-0.218081f,0.943645f,0.248946f, +0.00414662f,0.967721f,0.251991f, +-0.350612f,0.910773f,-0.218092f, +-0.590427f,0.768592f,-0.246296f, +-0.263693f,0.937904f,0.225393f, +-0.149885f,0.945975f,0.287518f, +-0.0723712f,0.947676f,0.310922f, +0.303995f,0.902765f,0.304306f, +0.615729f,0.768916f,0.172179f, +0.376573f,0.870472f,0.316971f, +0.258103f,0.862435f,0.435417f, +0.208037f,0.965523f,0.156476f, +0.041711f,0.997309f,0.0602974f, +0.0896451f,0.984172f,0.152868f, +0.200861f,0.950569f,0.236798f, +0.331115f,0.861074f,0.385894f, +0.343908f,0.839357f,0.420961f, +-0.162885f,0.985003f,0.0568977f, +-0.0608521f,0.991774f,0.112611f, +0.279417f,0.937386f,0.207929f, +0.438178f,0.898268f,0.033396f, +0.516016f,0.854846f,-0.0544561f, +0.550254f,0.781096f,-0.295143f, +0.499018f,0.830127f,-0.248738f, +0.421585f,0.905472f,0.0488414f, +0.355515f,0.918443f,0.173411f, +0.416018f,0.882036f,0.221226f, +0.346021f,0.922667f,0.170161f, +0.0862406f,0.994799f,-0.0542001f, +0.0251294f,0.989963f,-0.139071f, +-0.167311f,0.982002f,0.0876306f, +-0.296088f,0.953872f,0.0496014f, +-0.309819f,0.944071f,0.112878f, +0.0107419f,0.974593f,0.223724f, +0.235566f,0.938548f,0.252263f, +0.0528759f,0.995406f,0.0798236f, +0.106055f,0.992977f,0.0524375f, +0.227694f,0.967451f,0.110427f, +0.15013f,0.988604f,0.0110517f, +0.0292872f,0.989448f,-0.141897f, +0.0113647f,0.978518f,-0.205848f, +0.0966514f,0.981912f,-0.162811f, +-0.0834695f,0.969158f,-0.231875f, +-0.173766f,0.92349f,-0.34201f, +0.0289323f,0.967596f,-0.250839f, +0.166759f,0.980973f,-0.0994165f, +0.0796755f,0.992423f,-0.0935347f, +-0.0109031f,0.993494f,-0.113363f, +-0.181202f,0.957527f,-0.224295f, +-0.231371f,0.948894f,-0.214636f, +-0.0963906f,0.978232f,-0.183771f, +-0.0964169f,0.992283f,-0.0779687f, +-0.114591f,0.992373f,0.045429f, +-0.0476997f,0.984744f,0.167343f, +-0.353531f,0.929974f,0.100818f, +-0.42903f,0.892447f,0.139543f, +-0.399459f,0.902474f,0.161164f, +-0.44275f,0.883954f,0.150326f, +-0.416721f,0.891582f,0.177271f, +-0.364313f,0.907101f,0.210818f, +-0.329954f,0.890729f,0.312622f, +-0.308128f,0.891277f,0.33269f, +-0.248313f,0.912421f,0.325314f, +-0.264673f,0.92449f,0.274348f, +-0.221501f,0.958108f,0.181568f, +-0.00722143f,0.985032f,0.17222f, +0.0811419f,0.973825f,0.212324f, +-0.519461f,0.82914f,-0.206608f, +-0.561212f,0.816969f,-0.132674f, +-0.10198f,0.978452f,0.179533f, +-0.0294922f,0.994047f,0.104885f, +0.212965f,0.975972f,0.0461033f, +0.39072f,0.902699f,0.180202f, +0.284816f,0.877828f,0.385096f, +0.371584f,0.726424f,0.578129f, +0.415725f,0.734903f,0.535809f, +0.0647658f,0.913533f,0.401575f, +0.0316961f,0.895539f,0.443852f, +-0.0215836f,0.930013f,0.366891f, +0.0389377f,0.900411f,0.433293f, +0.182398f,0.888094f,0.421923f, +0.319795f,0.864372f,0.388061f, +0.179682f,0.983355f,0.0269752f, +0.358016f,0.913314f,-0.19412f, +0.445422f,0.82688f,-0.343321f, +0.564533f,0.736553f,-0.372547f, +0.511683f,0.792162f,-0.332656f, +0.362215f,0.931906f,0.0187495f, +0.332114f,0.925718f,0.180958f, +0.376936f,0.924108f,0.0628019f, +0.34207f,0.939661f,0.00505146f, +0.432513f,0.89733f,0.0879243f, +0.250624f,0.96783f,0.022189f, +0.113333f,0.993448f,0.0146943f, +-0.330108f,0.943938f,0.00323688f, +-0.32108f,0.944743f,0.0660874f, +-0.312445f,0.949733f,0.0196284f, +-0.0425447f,0.998988f,-0.0145795f, +0.234895f,0.971633f,0.0274452f, +0.205978f,0.978297f,0.0225396f, +0.0556133f,0.99289f,-0.10525f, +0.149272f,0.988455f,-0.0259672f, +0.25486f,0.966188f,0.0390683f, +0.206371f,0.977859f,-0.0346908f, +0.0798975f,0.983688f,-0.161166f, +0.0387149f,0.980238f,-0.193996f, +-0.0261652f,0.985317f,-0.168719f, +-0.115457f,0.963019f,-0.243441f, +-0.0914394f,0.962229f,-0.256427f, +0.0382488f,0.992063f,-0.119784f, +0.0800161f,0.996698f,-0.0137989f, +0.0187475f,0.998138f,-0.0580508f, +-0.073595f,0.994051f,-0.0802936f, +-0.224165f,0.957926f,-0.179241f, +-0.16346f,0.967941f,-0.190711f, +-0.19173f,0.978244f,-0.0792358f, +-0.275576f,0.961029f,-0.0219235f, +-0.0407932f,0.98802f,0.148838f, +-0.278629f,0.956556f,0.085827f, +-0.465684f,0.878931f,0.103047f, +-0.438529f,0.89146f,0.11398f, +-0.455089f,0.880964f,0.129601f, +-0.457802f,0.879895f,0.127287f, +-0.406331f,0.89051f,0.204664f, +-0.386395f,0.891456f,0.236654f, +-0.321818f,0.921226f,0.218577f, +-0.271011f,0.935727f,0.22576f, +-0.198383f,0.944022f,0.263564f, +-0.105727f,0.975806f,0.191373f, +-0.0832756f,0.987941f,0.130528f, +0.0931562f,0.956641f,0.27597f, +-0.216408f,0.96162f,0.168686f, +-0.648586f,0.688743f,-0.323988f, +-0.276841f,0.843915f,-0.459527f, +-0.060911f,0.935148f,-0.348981f, +0.243821f,0.963831f,-0.107611f, +0.35478f,0.93349f,-0.0522288f, +0.124674f,0.987025f,-0.101179f, +0.106145f,0.993646f,0.0374371f, +0.264307f,0.911176f,0.316069f, +0.180037f,0.821936f,0.540378f, +0.0976487f,0.839888f,0.533903f, +0.242869f,0.82432f,0.511381f, +0.296956f,0.900742f,0.316987f, +0.37446f,0.92343f,0.0840066f, +0.38614f,0.913414f,-0.128727f, +0.497691f,0.838063f,-0.223505f, +0.399217f,0.778523f,-0.484281f, +0.607215f,0.684189f,-0.403949f, +0.455879f,0.835157f,-0.307715f, +0.317815f,0.943806f,-0.0906903f, +0.166917f,0.983806f,0.0653043f, +0.277188f,0.953387f,0.119249f, +0.491287f,0.85011f,0.189606f, +0.3858f,0.919271f,0.0780984f, +0.390109f,0.91635f,0.0900968f, +0.247947f,0.964668f,0.0890966f, +0.0188396f,0.999506f,0.0251451f, +-0.249227f,0.949063f,0.192782f, +-0.24873f,0.963608f,0.0979465f, +-0.225537f,0.968208f,-0.108193f, +-0.0586638f,0.984304f,-0.166448f, +0.193919f,0.980395f,-0.0349386f, +0.232927f,0.972341f,0.0172453f, +0.165218f,0.985248f,-0.0445953f, +0.10666f,0.982482f,-0.152814f, +0.176402f,0.976328f,-0.125164f, +0.217875f,0.975941f,-0.00837002f, +0.138055f,0.990338f,0.0130638f, +0.0914598f,0.995289f,-0.0321788f, +-0.014672f,0.992233f,-0.123523f, +-0.0701479f,0.990985f,-0.114142f, +-0.0940689f,0.987781f,-0.124254f, +-0.152176f,0.977744f,-0.144426f, +0.043676f,0.996991f,0.0640382f, +0.0457416f,0.996307f,0.07266f, +-0.0198973f,0.997072f,0.0738311f, +-0.119455f,0.990174f,-0.0727032f, +-0.224875f,0.962572f,-0.151282f, +-0.250045f,0.966903f,-0.0507448f, +-0.319974f,0.944248f,-0.0775328f, +-0.16005f,0.987102f,-0.00365841f, +-0.307005f,0.947659f,0.0876954f, +-0.490256f,0.846833f,0.206209f, +-0.400386f,0.879926f,0.255778f, +-0.427515f,0.880624f,0.204282f, +-0.477897f,0.856347f,0.195663f, +-0.43217f,0.864768f,0.255745f, +-0.342474f,0.92438f,0.16803f, +-0.284468f,0.956998f,0.0568588f, +-0.290121f,0.956708f,0.023234f, +-0.249156f,0.966838f,0.0560771f, +-0.0655515f,0.986836f,0.147842f, +-0.100568f,0.984251f,0.145384f, +-0.0191778f,0.985445f,0.168911f, +-0.0443403f,0.97787f,0.204462f, +-0.28653f,0.957033f,-0.044587f, +-0.127864f,0.901634f,-0.413166f, +-0.0930849f,0.861283f,-0.499526f, +-0.10032f,0.791759f,-0.60254f, +0.277857f,0.863349f,-0.421218f, +0.0733471f,0.944573f,-0.320003f, +0.0656198f,0.995434f,-0.0693225f, +0.0994234f,0.993172f,-0.0610351f, +0.0758799f,0.991718f,0.103618f, +0.0755546f,0.978148f,0.193698f, +0.318521f,0.931105f,0.177731f, +0.532035f,0.846717f,0.00302226f, +0.479952f,0.801468f,-0.356785f, +0.444207f,0.753204f,-0.485143f, +0.599635f,0.661874f,-0.449845f, +0.467802f,0.782561f,-0.410805f, +0.194572f,0.899472f,-0.391269f, +0.334078f,0.938895f,-0.0828733f, +0.236858f,0.971355f,0.0191963f, +0.177255f,0.983392f,0.0389945f, +0.22691f,0.973661f,-0.0222777f, +0.408661f,0.912593f,0.013075f, +0.394434f,0.908333f,0.139114f, +0.34039f,0.913901f,0.221176f, +0.340162f,0.904445f,0.257428f, +0.21637f,0.954077f,0.207173f, +-0.190356f,0.960699f,0.202044f, +-0.0745122f,0.978557f,0.192026f, +-0.0103556f,0.997337f,0.0721953f, +-0.102208f,0.994222f,-0.0328074f, +0.0538732f,0.998534f,0.00527007f, +0.220064f,0.97523f,-0.0223306f, +0.22889f,0.972208f,-0.0492086f, +0.203387f,0.976813f,-0.0668524f, +0.112155f,0.987122f,-0.114071f, +0.137033f,0.989998f,-0.0335468f, +0.125928f,0.990544f,-0.0544465f, +0.164164f,0.983484f,-0.0762248f, +0.056178f,0.987899f,-0.14457f, +-0.125491f,0.977887f,-0.167299f, +-0.0763702f,0.993552f,-0.0837951f, +-0.140516f,0.986451f,-0.0846751f, +-0.138825f,0.988035f,-0.0671838f, +0.0272382f,0.998662f,0.0439583f, +0.051406f,0.998673f,0.00322772f, +0.0131796f,0.996364f,-0.0841692f, +-0.197723f,0.973335f,-0.116299f, +-0.315939f,0.94482f,-0.0865842f, +-0.273936f,0.961179f,-0.0330844f, +-0.278588f,0.957771f,-0.0711653f, +-0.371629f,0.922753f,0.102078f, +-0.589295f,0.797687f,0.128167f, +-0.394808f,0.893641f,0.213383f, +-0.419749f,0.89327f,0.160869f, +-0.503386f,0.848953f,0.160878f, +-0.392151f,0.910681f,0.129912f, +-0.194389f,0.97789f,0.0771005f, +-0.210697f,0.97754f,0.00473511f, +-0.261758f,0.965059f,0.0120029f, +-0.306606f,0.951531f,-0.0240962f, +-0.191391f,0.98062f,0.0418887f, +-0.0805366f,0.9875f,0.135492f, +-0.0197042f,0.996843f,0.0769187f, +-0.0102082f,0.996001f,0.0887568f, +-0.106967f,0.993499f,0.0389638f, +-0.0299932f,0.997488f,-0.0641764f, +0.166392f,0.98551f,-0.0329295f, +0.122834f,0.919366f,-0.373736f, +0.0989442f,0.860803f,-0.499228f, +-0.16483f,0.786842f,-0.594736f, +-0.139994f,0.854441f,-0.500331f, +0.037386f,0.884593f,-0.464864f, +-0.0340706f,0.910599f,-0.411885f, +0.0643546f,0.934103f,-0.351155f, +0.330549f,0.864687f,-0.378225f, +0.61879f,0.706641f,-0.343158f, +0.664468f,0.668218f,-0.334614f, +0.535603f,0.737564f,-0.411252f, +0.392926f,0.807647f,-0.439677f, +0.299634f,0.936543f,-0.181953f, +0.20385f,0.978529f,-0.030423f, +0.255219f,0.962099f,-0.0960637f, +0.218057f,0.97044f,-0.103423f, +0.152183f,0.981776f,-0.113823f, +0.287579f,0.953452f,-0.0907011f, +0.354102f,0.933846f,-0.0504376f, +0.271766f,0.955964f,0.110796f, +0.254566f,0.942907f,0.214762f, +0.330431f,0.909031f,0.253925f, +0.276649f,0.934017f,0.226003f, +-0.276078f,0.960525f,0.0342386f, +-0.126608f,0.988039f,0.088024f, +-0.0433883f,0.982429f,0.181523f, +-0.0351658f,0.95918f,0.280603f, +0.130316f,0.978179f,0.161815f, +0.34012f,0.939563f,0.0392436f, +0.225269f,0.971719f,-0.0708295f, +0.186144f,0.981343f,-0.0481244f, +0.117145f,0.991402f,-0.0582961f, +0.122374f,0.988553f,-0.0882497f, +0.217284f,0.968092f,-0.124844f, +0.168939f,0.967628f,-0.1875f, +0.0966952f,0.983818f,-0.150838f, +-0.108071f,0.971789f,-0.209635f, +-0.167419f,0.956466f,-0.239047f, +-0.15925f,0.972646f,-0.169115f, +-0.169755f,0.972705f,-0.158205f, +0.0352685f,0.991682f,-0.123784f, +0.0984439f,0.980655f,-0.169186f, +0.0318934f,0.989724f,-0.139387f, +-0.246309f,0.963763f,-0.102435f, +-0.355567f,0.934631f,-0.00599911f, +-0.265814f,0.963735f,-0.0236194f, +-0.351588f,0.935043f,-0.0456126f, +-0.494494f,0.858936f,0.133056f, +-0.559402f,0.824266f,0.0874941f, +-0.405326f,0.914016f,0.0169127f, +-0.376559f,0.926338f,0.010028f, +-0.448864f,0.890609f,-0.0730511f, +-0.3487f,0.913403f,-0.210007f, +-0.225518f,0.948441f,-0.222713f, +-0.278172f,0.957801f,-0.0723737f, +-0.296428f,0.947861f,0.117f, +-0.260326f,0.954501f,0.14546f, +-0.208806f,0.976306f,0.0568064f, +-0.0937503f,0.995595f,-0.00141652f, +0.0211825f,0.998587f,-0.0487327f, +-0.0203898f,0.998016f,-0.0595622f, +-0.117256f,0.992273f,-0.0405676f, +0.0346735f,0.999272f,0.0158994f, +0.165596f,0.985653f,-0.0326431f, +0.277068f,0.959929f,-0.0420538f, +0.211278f,0.971116f,-0.110882f, +0.138826f,0.972226f,-0.188423f, +0.0186164f,0.920791f,-0.389612f, +0.00693313f,0.891348f,-0.453267f, +-0.0471378f,0.869656f,-0.491403f, +0.135484f,0.84445f,-0.518217f, +0.351566f,0.784405f,-0.510988f, +0.399468f,0.772299f,-0.493943f, +0.574953f,0.790421f,-0.211338f, +0.577809f,0.813449f,-0.0666111f, +0.451377f,0.892327f,0.00336233f, +0.237932f,0.970883f,-0.0278435f, +0.170635f,0.975266f,-0.140498f, +0.305065f,0.94416f,-0.124487f, +0.219111f,0.958291f,-0.183492f, +0.160317f,0.981326f,-0.106286f, +0.222178f,0.974771f,-0.021419f, +0.23168f,0.971792f,0.0441002f, +0.140177f,0.984507f,0.105338f, +0.184383f,0.966339f,0.179422f, +0.307531f,0.911743f,0.272303f, +0.342083f,0.879118f,0.331859f, +-0.245266f,0.968917f,0.0323163f, +-0.176433f,0.984311f,-0.00156667f, +-0.164847f,0.983548f,0.0738887f, +-0.0271087f,0.959686f,0.279762f, +0.210185f,0.960158f,0.18417f, +0.386525f,0.917795f,0.0908302f, +0.288585f,0.956426f,0.04436f, +0.157424f,0.986731f,-0.0397454f, +0.194229f,0.980956f,0.000793421f, +0.143953f,0.978f,-0.150974f, +0.243865f,0.955091f,-0.168319f, +0.151307f,0.968911f,-0.195749f, +0.0861511f,0.987302f,-0.133462f, +-0.0343302f,0.988258f,-0.148887f, +-0.149683f,0.954065f,-0.259529f, +-0.180054f,0.943807f,-0.277143f, +-0.182632f,0.946912f,-0.26458f, +0.0250152f,0.97257f,-0.23126f, +0.0655433f,0.96826f,-0.241197f, +0.00940225f,0.990707f,-0.135685f, +-0.313822f,0.94168f,-0.121471f, +-0.325919f,0.940955f,0.0915474f, +-0.245857f,0.968763f,-0.0324418f, +-0.38384f,0.920444f,-0.0738245f, +-0.542624f,0.834584f,0.0950211f, +-0.496894f,0.865347f,0.0653522f, +-0.40471f,0.910862f,-0.0808731f, +-0.336326f,0.940002f,-0.0572751f, +-0.384947f,0.90765f,-0.167296f, +-0.26052f,0.919475f,-0.294439f, +-0.278076f,0.879766f,-0.385599f, +-0.415096f,0.880667f,-0.2283f, +-0.411169f,0.907675f,0.0840562f, +-0.22106f,0.940981f,0.256296f, +-0.105371f,0.978797f,0.175653f, +-0.0100537f,0.999811f,0.0166273f, +0.0459065f,0.991326f,-0.123151f, +-0.0151969f,0.991011f,-0.132912f, +-0.164041f,0.976761f,-0.137947f, +0.00793599f,0.998771f,-0.0489272f, +0.178958f,0.98335f,-0.031577f, +0.314466f,0.949045f,-0.0206086f, +0.240757f,0.963062f,-0.120617f, +0.126531f,0.982046f,-0.139911f, +0.0695074f,0.9956f,-0.062839f, +0.0427419f,0.998852f,-0.02164f, +-0.0292495f,0.993565f,-0.109419f, +0.176081f,0.974549f,-0.138744f, +0.405406f,0.900659f,-0.156393f, +0.48202f,0.865956f,-0.133334f, +0.477566f,0.852664f,-0.211881f, +0.526274f,0.839922f,-0.132537f, +0.390331f,0.920621f,-0.0098857f, +0.349443f,0.931118f,0.104442f, +0.205374f,0.96487f,-0.163851f, +0.359411f,0.921384f,-0.147904f, +0.161592f,0.938137f,-0.306246f, +0.0124614f,0.982178f,-0.187542f, +0.143914f,0.986786f,0.0744463f, +0.270333f,0.949018f,0.162126f, +0.132f,0.991194f,0.0105184f, +0.131712f,0.991267f,0.00644011f, +0.199003f,0.974024f,0.108048f, +0.274163f,0.928953f,0.248757f, +}; + +btScalar Landscape01Tex[] = { +0.507813f,0.0078125f, +0.507813f,0.0f, +0.515625f,0.0078125f, +0.515625f,0.0f, +0.523438f,0.0078125f, +0.523438f,0.0f, +0.53125f,0.0078125f, +0.53125f,0.0f, +0.539063f,0.0078125f, +0.539063f,0.0f, +0.546875f,0.0078125f, +0.546875f,0.0f, +0.554688f,0.0078125f, +0.554688f,0.0f, +0.5625f,0.0078125f, +0.5625f,0.0f, +0.570313f,0.0078125f, +0.570313f,0.0f, +0.578125f,0.0078125f, +0.578125f,0.0f, +0.585938f,0.0078125f, +0.585938f,0.0f, +0.59375f,0.0078125f, +0.59375f,0.0f, +0.601563f,0.0078125f, +0.601563f,0.0f, +0.609375f,0.0078125f, +0.609375f,0.0f, +0.617188f,0.0078125f, +0.617188f,0.0f, +0.625f,0.0078125f, +0.625f,0.0f, +0.632813f,0.0078125f, +0.632813f,0.0f, +0.640625f,0.0078125f, +0.640625f,0.0f, +0.648438f,0.0078125f, +0.648438f,0.0f, +0.65625f,0.0078125f, +0.65625f,0.0f, +0.664063f,0.0078125f, +0.664063f,0.0f, +0.671875f,0.0078125f, +0.671875f,0.0f, +0.679688f,0.0078125f, +0.679688f,0.0f, +0.6875f,0.0078125f, +0.6875f,0.0f, +0.695313f,0.0078125f, +0.695313f,0.0f, +0.703125f,0.0078125f, +0.703125f,0.0f, +0.710938f,0.0078125f, +0.710938f,0.0f, +0.71875f,0.0078125f, +0.71875f,0.0f, +0.726563f,0.0078125f, +0.726563f,0.0f, +0.734375f,0.0078125f, +0.734375f,0.0f, +0.742188f,0.0078125f, +0.742188f,0.0f, +0.75f,0.0078125f, +0.75f,0.0f, +0.757813f,0.0078125f, +0.757813f,0.0f, +0.765625f,0.0078125f, +0.765625f,0.0f, +0.773438f,0.0078125f, +0.773438f,0.0f, +0.78125f,0.0078125f, +0.78125f,0.0f, +0.789063f,0.0078125f, +0.789063f,0.0f, +0.796875f,0.0078125f, +0.796875f,0.0f, +0.804688f,0.0078125f, +0.804688f,0.0f, +0.8125f,0.0078125f, +0.8125f,0.0f, +0.820313f,0.0078125f, +0.820313f,0.0f, +0.828125f,0.0078125f, +0.828125f,0.0f, +0.835938f,0.0078125f, +0.835938f,0.0f, +0.84375f,0.0078125f, +0.84375f,0.0f, +0.851563f,0.0078125f, +0.851563f,0.0f, +0.859375f,0.0078125f, +0.859375f,0.0f, +0.867188f,0.0078125f, +0.867188f,0.0f, +0.875f,0.0078125f, +0.875f,0.0f, +0.882813f,0.0078125f, +0.882813f,0.0f, +0.890625f,0.0078125f, +0.890625f,0.0f, +0.898438f,0.0078125f, +0.898438f,0.0f, +0.90625f,0.0078125f, +0.90625f,0.0f, +0.914063f,0.0078125f, +0.914063f,0.0f, +0.921875f,0.0078125f, +0.921875f,0.0f, +0.929688f,0.0078125f, +0.929688f,0.0f, +0.9375f,0.0078125f, +0.9375f,0.0f, +0.945313f,0.0078125f, +0.945313f,0.0f, +0.953125f,0.0078125f, +0.953125f,0.0f, +0.960938f,0.0078125f, +0.960938f,0.0f, +0.96875f,0.0078125f, +0.96875f,0.0f, +0.976563f,0.0078125f, +0.976563f,0.0f, +0.984375f,0.0078125f, +0.984375f,0.0f, +0.992188f,0.0078125f, +0.992188f,0.0f, +1.0f,0.0078125f, +1.0f,0.0f, +0.507813f,0.015625f, +0.515625f,0.015625f, +0.523438f,0.015625f, +0.53125f,0.015625f, +0.539063f,0.015625f, +0.546875f,0.015625f, +0.554688f,0.015625f, +0.5625f,0.015625f, +0.570313f,0.015625f, +0.578125f,0.015625f, +0.585938f,0.015625f, +0.59375f,0.015625f, +0.601563f,0.015625f, +0.609375f,0.015625f, +0.617188f,0.015625f, +0.625f,0.015625f, +0.632813f,0.015625f, +0.640625f,0.015625f, +0.648438f,0.015625f, +0.65625f,0.015625f, +0.664063f,0.015625f, +0.671875f,0.015625f, +0.679688f,0.015625f, +0.6875f,0.015625f, +0.695313f,0.015625f, +0.703125f,0.015625f, +0.710938f,0.015625f, +0.71875f,0.015625f, +0.726563f,0.015625f, +0.734375f,0.015625f, +0.742188f,0.015625f, +0.75f,0.015625f, +0.757813f,0.015625f, +0.765625f,0.015625f, +0.773438f,0.015625f, +0.78125f,0.015625f, +0.789063f,0.015625f, +0.796875f,0.015625f, +0.804688f,0.015625f, +0.8125f,0.015625f, +0.820313f,0.015625f, +0.828125f,0.015625f, +0.835938f,0.015625f, +0.84375f,0.015625f, +0.851563f,0.015625f, +0.859375f,0.015625f, +0.867188f,0.015625f, +0.875f,0.015625f, +0.882813f,0.015625f, +0.890625f,0.015625f, +0.898438f,0.015625f, +0.90625f,0.015625f, +0.914063f,0.015625f, +0.921875f,0.015625f, +0.929688f,0.015625f, +0.9375f,0.015625f, +0.945313f,0.015625f, +0.953125f,0.015625f, +0.960938f,0.015625f, +0.96875f,0.015625f, +0.976563f,0.015625f, +0.984375f,0.015625f, +0.992188f,0.015625f, +1.0f,0.015625f, +0.507813f,0.0234375f, +0.515625f,0.0234375f, +0.523438f,0.0234375f, +0.53125f,0.0234375f, +0.539063f,0.0234375f, +0.546875f,0.0234375f, +0.554688f,0.0234375f, +0.5625f,0.0234375f, +0.570313f,0.0234375f, +0.578125f,0.0234375f, +0.585938f,0.0234375f, +0.59375f,0.0234375f, +0.601563f,0.0234375f, +0.609375f,0.0234375f, +0.617188f,0.0234375f, +0.625f,0.0234375f, +0.632813f,0.0234375f, +0.640625f,0.0234375f, +0.648438f,0.0234375f, +0.65625f,0.0234375f, +0.664063f,0.0234375f, +0.671875f,0.0234375f, +0.679688f,0.0234375f, +0.6875f,0.0234375f, +0.695313f,0.0234375f, +0.703125f,0.0234375f, +0.710938f,0.0234375f, +0.71875f,0.0234375f, +0.726563f,0.0234375f, +0.734375f,0.0234375f, +0.742188f,0.0234375f, +0.75f,0.0234375f, +0.757813f,0.0234375f, +0.765625f,0.0234375f, +0.773438f,0.0234375f, +0.78125f,0.0234375f, +0.789063f,0.0234375f, +0.796875f,0.0234375f, +0.804688f,0.0234375f, +0.8125f,0.0234375f, +0.820313f,0.0234375f, +0.828125f,0.0234375f, +0.835938f,0.0234375f, +0.84375f,0.0234375f, +0.851563f,0.0234375f, +0.859375f,0.0234375f, +0.867188f,0.0234375f, +0.875f,0.0234375f, +0.882813f,0.0234375f, +0.890625f,0.0234375f, +0.898438f,0.0234375f, +0.90625f,0.0234375f, +0.914063f,0.0234375f, +0.921875f,0.0234375f, +0.929688f,0.0234375f, +0.9375f,0.0234375f, +0.945313f,0.0234375f, +0.953125f,0.0234375f, +0.960938f,0.0234375f, +0.96875f,0.0234375f, +0.976563f,0.0234375f, +0.984375f,0.0234375f, +0.992188f,0.0234375f, +1.0f,0.0234375f, +0.507813f,0.03125f, +0.515625f,0.03125f, +0.523438f,0.03125f, +0.53125f,0.03125f, +0.539063f,0.03125f, +0.546875f,0.03125f, +0.554688f,0.03125f, +0.5625f,0.03125f, +0.570313f,0.03125f, +0.578125f,0.03125f, +0.585938f,0.03125f, +0.59375f,0.03125f, +0.601563f,0.03125f, +0.609375f,0.03125f, +0.617188f,0.03125f, +0.625f,0.03125f, +0.632813f,0.03125f, +0.640625f,0.03125f, +0.648438f,0.03125f, +0.65625f,0.03125f, +0.664063f,0.03125f, +0.671875f,0.03125f, +0.679688f,0.03125f, +0.6875f,0.03125f, +0.695313f,0.03125f, +0.703125f,0.03125f, +0.710938f,0.03125f, +0.71875f,0.03125f, +0.726563f,0.03125f, +0.734375f,0.03125f, +0.742188f,0.03125f, +0.75f,0.03125f, +0.757813f,0.03125f, +0.765625f,0.03125f, +0.773438f,0.03125f, +0.78125f,0.03125f, +0.789063f,0.03125f, +0.796875f,0.03125f, +0.804688f,0.03125f, +0.8125f,0.03125f, +0.820313f,0.03125f, +0.828125f,0.03125f, +0.835938f,0.03125f, +0.84375f,0.03125f, +0.851563f,0.03125f, +0.859375f,0.03125f, +0.867188f,0.03125f, +0.875f,0.03125f, +0.882813f,0.03125f, +0.890625f,0.03125f, +0.898438f,0.03125f, +0.90625f,0.03125f, +0.914063f,0.03125f, +0.921875f,0.03125f, +0.929688f,0.03125f, +0.9375f,0.03125f, +0.945313f,0.03125f, +0.953125f,0.03125f, +0.960938f,0.03125f, +0.96875f,0.03125f, +0.976563f,0.03125f, +0.984375f,0.03125f, +0.992188f,0.03125f, +1.0f,0.03125f, +0.507813f,0.0390625f, +0.515625f,0.0390625f, +0.523438f,0.0390625f, +0.53125f,0.0390625f, +0.539063f,0.0390625f, +0.546875f,0.0390625f, +0.554688f,0.0390625f, +0.5625f,0.0390625f, +0.570313f,0.0390625f, +0.578125f,0.0390625f, +0.585938f,0.0390625f, +0.59375f,0.0390625f, +0.601563f,0.0390625f, +0.609375f,0.0390625f, +0.617188f,0.0390625f, +0.625f,0.0390625f, +0.632813f,0.0390625f, +0.640625f,0.0390625f, +0.648438f,0.0390625f, +0.65625f,0.0390625f, +0.664063f,0.0390625f, +0.671875f,0.0390625f, +0.679688f,0.0390625f, +0.6875f,0.0390625f, +0.695313f,0.0390625f, +0.703125f,0.0390625f, +0.710938f,0.0390625f, +0.71875f,0.0390625f, +0.726563f,0.0390625f, +0.734375f,0.0390625f, +0.742188f,0.0390625f, +0.75f,0.0390625f, +0.757813f,0.0390625f, +0.765625f,0.0390625f, +0.773438f,0.0390625f, +0.78125f,0.0390625f, +0.789063f,0.0390625f, +0.796875f,0.0390625f, +0.804688f,0.0390625f, +0.8125f,0.0390625f, +0.820313f,0.0390625f, +0.828125f,0.0390625f, +0.835938f,0.0390625f, +0.84375f,0.0390625f, +0.851563f,0.0390625f, +0.859375f,0.0390625f, +0.867188f,0.0390625f, +0.875f,0.0390625f, +0.882813f,0.0390625f, +0.890625f,0.0390625f, +0.898438f,0.0390625f, +0.90625f,0.0390625f, +0.914063f,0.0390625f, +0.921875f,0.0390625f, +0.929688f,0.0390625f, +0.9375f,0.0390625f, +0.945313f,0.0390625f, +0.953125f,0.0390625f, +0.960938f,0.0390625f, +0.96875f,0.0390625f, +0.976563f,0.0390625f, +0.984375f,0.0390625f, +0.992188f,0.0390625f, +1.0f,0.0390625f, +0.507813f,0.046875f, +0.515625f,0.046875f, +0.523438f,0.046875f, +0.53125f,0.046875f, +0.539063f,0.046875f, +0.546875f,0.046875f, +0.554688f,0.046875f, +0.5625f,0.046875f, +0.570313f,0.046875f, +0.578125f,0.046875f, +0.585938f,0.046875f, +0.59375f,0.046875f, +0.601563f,0.046875f, +0.609375f,0.046875f, +0.617188f,0.046875f, +0.625f,0.046875f, +0.632813f,0.046875f, +0.640625f,0.046875f, +0.648438f,0.046875f, +0.65625f,0.046875f, +0.664063f,0.046875f, +0.671875f,0.046875f, +0.679688f,0.046875f, +0.6875f,0.046875f, +0.695313f,0.046875f, +0.703125f,0.046875f, +0.710938f,0.046875f, +0.71875f,0.046875f, +0.726563f,0.046875f, +0.734375f,0.046875f, +0.742188f,0.046875f, +0.75f,0.046875f, +0.757813f,0.046875f, +0.765625f,0.046875f, +0.773438f,0.046875f, +0.78125f,0.046875f, +0.789063f,0.046875f, +0.796875f,0.046875f, +0.804688f,0.046875f, +0.8125f,0.046875f, +0.820313f,0.046875f, +0.828125f,0.046875f, +0.835938f,0.046875f, +0.84375f,0.046875f, +0.851563f,0.046875f, +0.859375f,0.046875f, +0.867188f,0.046875f, +0.875f,0.046875f, +0.882813f,0.046875f, +0.890625f,0.046875f, +0.898438f,0.046875f, +0.90625f,0.046875f, +0.914063f,0.046875f, +0.921875f,0.046875f, +0.929688f,0.046875f, +0.9375f,0.046875f, +0.945313f,0.046875f, +0.953125f,0.046875f, +0.960938f,0.046875f, +0.96875f,0.046875f, +0.976563f,0.046875f, +0.984375f,0.046875f, +0.992188f,0.046875f, +1.0f,0.046875f, +0.507813f,0.0546875f, +0.515625f,0.0546875f, +0.523438f,0.0546875f, +0.53125f,0.0546875f, +0.539063f,0.0546875f, +0.546875f,0.0546875f, +0.554688f,0.0546875f, +0.5625f,0.0546875f, +0.570313f,0.0546875f, +0.578125f,0.0546875f, +0.585938f,0.0546875f, +0.59375f,0.0546875f, +0.601563f,0.0546875f, +0.609375f,0.0546875f, +0.617188f,0.0546875f, +0.625f,0.0546875f, +0.632813f,0.0546875f, +0.640625f,0.0546875f, +0.648438f,0.0546875f, +0.65625f,0.0546875f, +0.664063f,0.0546875f, +0.671875f,0.0546875f, +0.679688f,0.0546875f, +0.6875f,0.0546875f, +0.695313f,0.0546875f, +0.703125f,0.0546875f, +0.710938f,0.0546875f, +0.71875f,0.0546875f, +0.726563f,0.0546875f, +0.734375f,0.0546875f, +0.742188f,0.0546875f, +0.75f,0.0546875f, +0.757813f,0.0546875f, +0.765625f,0.0546875f, +0.773438f,0.0546875f, +0.78125f,0.0546875f, +0.789063f,0.0546875f, +0.796875f,0.0546875f, +0.804688f,0.0546875f, +0.8125f,0.0546875f, +0.820313f,0.0546875f, +0.828125f,0.0546875f, +0.835938f,0.0546875f, +0.84375f,0.0546875f, +0.851563f,0.0546875f, +0.859375f,0.0546875f, +0.867188f,0.0546875f, +0.875f,0.0546875f, +0.882813f,0.0546875f, +0.890625f,0.0546875f, +0.898438f,0.0546875f, +0.90625f,0.0546875f, +0.914063f,0.0546875f, +0.921875f,0.0546875f, +0.929688f,0.0546875f, +0.9375f,0.0546875f, +0.945313f,0.0546875f, +0.953125f,0.0546875f, +0.960938f,0.0546875f, +0.96875f,0.0546875f, +0.976563f,0.0546875f, +0.984375f,0.0546875f, +0.992188f,0.0546875f, +1.0f,0.0546875f, +0.507813f,0.0625f, +0.515625f,0.0625f, +0.523438f,0.0625f, +0.53125f,0.0625f, +0.539063f,0.0625f, +0.546875f,0.0625f, +0.554688f,0.0625f, +0.5625f,0.0625f, +0.570313f,0.0625f, +0.578125f,0.0625f, +0.585938f,0.0625f, +0.59375f,0.0625f, +0.601563f,0.0625f, +0.609375f,0.0625f, +0.617188f,0.0625f, +0.625f,0.0625f, +0.632813f,0.0625f, +0.640625f,0.0625f, +0.648438f,0.0625f, +0.65625f,0.0625f, +0.664063f,0.0625f, +0.671875f,0.0625f, +0.679688f,0.0625f, +0.6875f,0.0625f, +0.695313f,0.0625f, +0.703125f,0.0625f, +0.710938f,0.0625f, +0.71875f,0.0625f, +0.726563f,0.0625f, +0.734375f,0.0625f, +0.742188f,0.0625f, +0.75f,0.0625f, +0.757813f,0.0625f, +0.765625f,0.0625f, +0.773438f,0.0625f, +0.78125f,0.0625f, +0.789063f,0.0625f, +0.796875f,0.0625f, +0.804688f,0.0625f, +0.8125f,0.0625f, +0.820313f,0.0625f, +0.828125f,0.0625f, +0.835938f,0.0625f, +0.84375f,0.0625f, +0.851563f,0.0625f, +0.859375f,0.0625f, +0.867188f,0.0625f, +0.875f,0.0625f, +0.882813f,0.0625f, +0.890625f,0.0625f, +0.898438f,0.0625f, +0.90625f,0.0625f, +0.914063f,0.0625f, +0.921875f,0.0625f, +0.929688f,0.0625f, +0.9375f,0.0625f, +0.945313f,0.0625f, +0.953125f,0.0625f, +0.960938f,0.0625f, +0.96875f,0.0625f, +0.976563f,0.0625f, +0.984375f,0.0625f, +0.992188f,0.0625f, +1.0f,0.0625f, +0.507813f,0.0703125f, +0.515625f,0.0703125f, +0.523438f,0.0703125f, +0.53125f,0.0703125f, +0.539063f,0.0703125f, +0.546875f,0.0703125f, +0.554688f,0.0703125f, +0.5625f,0.0703125f, +0.570313f,0.0703125f, +0.578125f,0.0703125f, +0.585938f,0.0703125f, +0.59375f,0.0703125f, +0.601563f,0.0703125f, +0.609375f,0.0703125f, +0.617188f,0.0703125f, +0.625f,0.0703125f, +0.632813f,0.0703125f, +0.640625f,0.0703125f, +0.648438f,0.0703125f, +0.65625f,0.0703125f, +0.664063f,0.0703125f, +0.671875f,0.0703125f, +0.679688f,0.0703125f, +0.6875f,0.0703125f, +0.695313f,0.0703125f, +0.703125f,0.0703125f, +0.710938f,0.0703125f, +0.71875f,0.0703125f, +0.726563f,0.0703125f, +0.734375f,0.0703125f, +0.742188f,0.0703125f, +0.75f,0.0703125f, +0.757813f,0.0703125f, +0.765625f,0.0703125f, +0.773438f,0.0703125f, +0.78125f,0.0703125f, +0.789063f,0.0703125f, +0.796875f,0.0703125f, +0.804688f,0.0703125f, +0.8125f,0.0703125f, +0.820313f,0.0703125f, +0.828125f,0.0703125f, +0.835938f,0.0703125f, +0.84375f,0.0703125f, +0.851563f,0.0703125f, +0.859375f,0.0703125f, +0.867188f,0.0703125f, +0.875f,0.0703125f, +0.882813f,0.0703125f, +0.890625f,0.0703125f, +0.898438f,0.0703125f, +0.90625f,0.0703125f, +0.914063f,0.0703125f, +0.921875f,0.0703125f, +0.929688f,0.0703125f, +0.9375f,0.0703125f, +0.945313f,0.0703125f, +0.953125f,0.0703125f, +0.960938f,0.0703125f, +0.96875f,0.0703125f, +0.976563f,0.0703125f, +0.984375f,0.0703125f, +0.992188f,0.0703125f, +1.0f,0.0703125f, +0.507813f,0.078125f, +0.515625f,0.078125f, +0.523438f,0.078125f, +0.53125f,0.078125f, +0.539063f,0.078125f, +0.546875f,0.078125f, +0.554688f,0.078125f, +0.5625f,0.078125f, +0.570313f,0.078125f, +0.578125f,0.078125f, +0.585938f,0.078125f, +0.59375f,0.078125f, +0.601563f,0.078125f, +0.609375f,0.078125f, +0.617188f,0.078125f, +0.625f,0.078125f, +0.632813f,0.078125f, +0.640625f,0.078125f, +0.648438f,0.078125f, +0.65625f,0.078125f, +0.664063f,0.078125f, +0.671875f,0.078125f, +0.679688f,0.078125f, +0.6875f,0.078125f, +0.695313f,0.078125f, +0.703125f,0.078125f, +0.710938f,0.078125f, +0.71875f,0.078125f, +0.726563f,0.078125f, +0.734375f,0.078125f, +0.742188f,0.078125f, +0.75f,0.078125f, +0.757813f,0.078125f, +0.765625f,0.078125f, +0.773438f,0.078125f, +0.78125f,0.078125f, +0.789063f,0.078125f, +0.796875f,0.078125f, +0.804688f,0.078125f, +0.8125f,0.078125f, +0.820313f,0.078125f, +0.828125f,0.078125f, +0.835938f,0.078125f, +0.84375f,0.078125f, +0.851563f,0.078125f, +0.859375f,0.078125f, +0.867188f,0.078125f, +0.875f,0.078125f, +0.882813f,0.078125f, +0.890625f,0.078125f, +0.898438f,0.078125f, +0.90625f,0.078125f, +0.914063f,0.078125f, +0.921875f,0.078125f, +0.929688f,0.078125f, +0.9375f,0.078125f, +0.945313f,0.078125f, +0.953125f,0.078125f, +0.960938f,0.078125f, +0.96875f,0.078125f, +0.976563f,0.078125f, +0.984375f,0.078125f, +0.992188f,0.078125f, +1.0f,0.078125f, +0.507813f,0.0859375f, +0.515625f,0.0859375f, +0.523438f,0.0859375f, +0.53125f,0.0859375f, +0.539063f,0.0859375f, +0.546875f,0.0859375f, +0.554688f,0.0859375f, +0.5625f,0.0859375f, +0.570313f,0.0859375f, +0.578125f,0.0859375f, +0.585938f,0.0859375f, +0.59375f,0.0859375f, +0.601563f,0.0859375f, +0.609375f,0.0859375f, +0.617188f,0.0859375f, +0.625f,0.0859375f, +0.632813f,0.0859375f, +0.640625f,0.0859375f, +0.648438f,0.0859375f, +0.65625f,0.0859375f, +0.664063f,0.0859375f, +0.671875f,0.0859375f, +0.679688f,0.0859375f, +0.6875f,0.0859375f, +0.695313f,0.0859375f, +0.703125f,0.0859375f, +0.710938f,0.0859375f, +0.71875f,0.0859375f, +0.726563f,0.0859375f, +0.734375f,0.0859375f, +0.742188f,0.0859375f, +0.75f,0.0859375f, +0.757813f,0.0859375f, +0.765625f,0.0859375f, +0.773438f,0.0859375f, +0.78125f,0.0859375f, +0.789063f,0.0859375f, +0.796875f,0.0859375f, +0.804688f,0.0859375f, +0.8125f,0.0859375f, +0.820313f,0.0859375f, +0.828125f,0.0859375f, +0.835938f,0.0859375f, +0.84375f,0.0859375f, +0.851563f,0.0859375f, +0.859375f,0.0859375f, +0.867188f,0.0859375f, +0.875f,0.0859375f, +0.882813f,0.0859375f, +0.890625f,0.0859375f, +0.898438f,0.0859375f, +0.90625f,0.0859375f, +0.914063f,0.0859375f, +0.921875f,0.0859375f, +0.929688f,0.0859375f, +0.9375f,0.0859375f, +0.945313f,0.0859375f, +0.953125f,0.0859375f, +0.960938f,0.0859375f, +0.96875f,0.0859375f, +0.976563f,0.0859375f, +0.984375f,0.0859375f, +0.992188f,0.0859375f, +1.0f,0.0859375f, +0.507813f,0.09375f, +0.515625f,0.09375f, +0.523438f,0.09375f, +0.53125f,0.09375f, +0.539063f,0.09375f, +0.546875f,0.09375f, +0.554688f,0.09375f, +0.5625f,0.09375f, +0.570313f,0.09375f, +0.578125f,0.09375f, +0.585938f,0.09375f, +0.59375f,0.09375f, +0.601563f,0.09375f, +0.609375f,0.09375f, +0.617188f,0.09375f, +0.625f,0.09375f, +0.632813f,0.09375f, +0.640625f,0.09375f, +0.648438f,0.09375f, +0.65625f,0.09375f, +0.664063f,0.09375f, +0.671875f,0.09375f, +0.679688f,0.09375f, +0.6875f,0.09375f, +0.695313f,0.09375f, +0.703125f,0.09375f, +0.710938f,0.09375f, +0.71875f,0.09375f, +0.726563f,0.09375f, +0.734375f,0.09375f, +0.742188f,0.09375f, +0.75f,0.09375f, +0.757813f,0.09375f, +0.765625f,0.09375f, +0.773438f,0.09375f, +0.78125f,0.09375f, +0.789063f,0.09375f, +0.796875f,0.09375f, +0.804688f,0.09375f, +0.8125f,0.09375f, +0.820313f,0.09375f, +0.828125f,0.09375f, +0.835938f,0.09375f, +0.84375f,0.09375f, +0.851563f,0.09375f, +0.859375f,0.09375f, +0.867188f,0.09375f, +0.875f,0.09375f, +0.882813f,0.09375f, +0.890625f,0.09375f, +0.898438f,0.09375f, +0.90625f,0.09375f, +0.914063f,0.09375f, +0.921875f,0.09375f, +0.929688f,0.09375f, +0.9375f,0.09375f, +0.945313f,0.09375f, +0.953125f,0.09375f, +0.960938f,0.09375f, +0.96875f,0.09375f, +0.976563f,0.09375f, +0.984375f,0.09375f, +0.992188f,0.09375f, +1.0f,0.09375f, +0.507813f,0.101563f, +0.515625f,0.101563f, +0.523438f,0.101563f, +0.53125f,0.101563f, +0.539063f,0.101563f, +0.546875f,0.101563f, +0.554688f,0.101563f, +0.5625f,0.101563f, +0.570313f,0.101563f, +0.578125f,0.101563f, +0.585938f,0.101563f, +0.59375f,0.101563f, +0.601563f,0.101563f, +0.609375f,0.101563f, +0.617188f,0.101563f, +0.625f,0.101563f, +0.632813f,0.101563f, +0.640625f,0.101563f, +0.648438f,0.101563f, +0.65625f,0.101563f, +0.664063f,0.101563f, +0.671875f,0.101563f, +0.679688f,0.101563f, +0.6875f,0.101563f, +0.695313f,0.101563f, +0.703125f,0.101563f, +0.710938f,0.101563f, +0.71875f,0.101563f, +0.726563f,0.101563f, +0.734375f,0.101563f, +0.742188f,0.101563f, +0.75f,0.101563f, +0.757813f,0.101563f, +0.765625f,0.101563f, +0.773438f,0.101563f, +0.78125f,0.101563f, +0.789063f,0.101563f, +0.796875f,0.101563f, +0.804688f,0.101563f, +0.8125f,0.101563f, +0.820313f,0.101563f, +0.828125f,0.101563f, +0.835938f,0.101563f, +0.84375f,0.101563f, +0.851563f,0.101563f, +0.859375f,0.101563f, +0.867188f,0.101563f, +0.875f,0.101563f, +0.882813f,0.101563f, +0.890625f,0.101563f, +0.898438f,0.101563f, +0.90625f,0.101563f, +0.914063f,0.101563f, +0.921875f,0.101563f, +0.929688f,0.101563f, +0.9375f,0.101563f, +0.945313f,0.101563f, +0.953125f,0.101563f, +0.960938f,0.101563f, +0.96875f,0.101563f, +0.976563f,0.101563f, +0.984375f,0.101563f, +0.992188f,0.101563f, +1.0f,0.101563f, +0.507813f,0.109375f, +0.515625f,0.109375f, +0.523438f,0.109375f, +0.53125f,0.109375f, +0.539063f,0.109375f, +0.546875f,0.109375f, +0.554688f,0.109375f, +0.5625f,0.109375f, +0.570313f,0.109375f, +0.578125f,0.109375f, +0.585938f,0.109375f, +0.59375f,0.109375f, +0.601563f,0.109375f, +0.609375f,0.109375f, +0.617188f,0.109375f, +0.625f,0.109375f, +0.632813f,0.109375f, +0.640625f,0.109375f, +0.648438f,0.109375f, +0.65625f,0.109375f, +0.664063f,0.109375f, +0.671875f,0.109375f, +0.679688f,0.109375f, +0.6875f,0.109375f, +0.695313f,0.109375f, +0.703125f,0.109375f, +0.710938f,0.109375f, +0.71875f,0.109375f, +0.726563f,0.109375f, +0.734375f,0.109375f, +0.742188f,0.109375f, +0.75f,0.109375f, +0.757813f,0.109375f, +0.765625f,0.109375f, +0.773438f,0.109375f, +0.78125f,0.109375f, +0.789063f,0.109375f, +0.796875f,0.109375f, +0.804688f,0.109375f, +0.8125f,0.109375f, +0.820313f,0.109375f, +0.828125f,0.109375f, +0.835938f,0.109375f, +0.84375f,0.109375f, +0.851563f,0.109375f, +0.859375f,0.109375f, +0.867188f,0.109375f, +0.875f,0.109375f, +0.882813f,0.109375f, +0.890625f,0.109375f, +0.898438f,0.109375f, +0.90625f,0.109375f, +0.914063f,0.109375f, +0.921875f,0.109375f, +0.929688f,0.109375f, +0.9375f,0.109375f, +0.945313f,0.109375f, +0.953125f,0.109375f, +0.960938f,0.109375f, +0.96875f,0.109375f, +0.976563f,0.109375f, +0.984375f,0.109375f, +0.992188f,0.109375f, +1.0f,0.109375f, +0.507813f,0.117188f, +0.515625f,0.117188f, +0.523438f,0.117188f, +0.53125f,0.117188f, +0.539063f,0.117188f, +0.546875f,0.117188f, +0.554688f,0.117188f, +0.5625f,0.117188f, +0.570313f,0.117188f, +0.578125f,0.117188f, +0.585938f,0.117188f, +0.59375f,0.117188f, +0.601563f,0.117188f, +0.609375f,0.117188f, +0.617188f,0.117188f, +0.625f,0.117188f, +0.632813f,0.117188f, +0.640625f,0.117188f, +0.648438f,0.117188f, +0.65625f,0.117188f, +0.664063f,0.117188f, +0.671875f,0.117188f, +0.679688f,0.117188f, +0.6875f,0.117188f, +0.695313f,0.117188f, +0.703125f,0.117188f, +0.710938f,0.117188f, +0.71875f,0.117188f, +0.726563f,0.117188f, +0.734375f,0.117188f, +0.742188f,0.117188f, +0.75f,0.117188f, +0.757813f,0.117188f, +0.765625f,0.117188f, +0.773438f,0.117188f, +0.78125f,0.117188f, +0.789063f,0.117188f, +0.796875f,0.117188f, +0.804688f,0.117188f, +0.8125f,0.117188f, +0.820313f,0.117188f, +0.828125f,0.117188f, +0.835938f,0.117188f, +0.84375f,0.117188f, +0.851563f,0.117188f, +0.859375f,0.117188f, +0.867188f,0.117188f, +0.875f,0.117188f, +0.882813f,0.117188f, +0.890625f,0.117188f, +0.898438f,0.117188f, +0.90625f,0.117188f, +0.914063f,0.117188f, +0.921875f,0.117188f, +0.929688f,0.117188f, +0.9375f,0.117188f, +0.945313f,0.117188f, +0.953125f,0.117188f, +0.960938f,0.117188f, +0.96875f,0.117188f, +0.976563f,0.117188f, +0.984375f,0.117188f, +0.992188f,0.117188f, +1.0f,0.117188f, +0.507813f,0.125f, +0.515625f,0.125f, +0.523438f,0.125f, +0.53125f,0.125f, +0.539063f,0.125f, +0.546875f,0.125f, +0.554688f,0.125f, +0.5625f,0.125f, +0.570313f,0.125f, +0.578125f,0.125f, +0.585938f,0.125f, +0.59375f,0.125f, +0.601563f,0.125f, +0.609375f,0.125f, +0.617188f,0.125f, +0.625f,0.125f, +0.632813f,0.125f, +0.640625f,0.125f, +0.648438f,0.125f, +0.65625f,0.125f, +0.664063f,0.125f, +0.671875f,0.125f, +0.679688f,0.125f, +0.6875f,0.125f, +0.695313f,0.125f, +0.703125f,0.125f, +0.710938f,0.125f, +0.71875f,0.125f, +0.726563f,0.125f, +0.734375f,0.125f, +0.742188f,0.125f, +0.75f,0.125f, +0.757813f,0.125f, +0.765625f,0.125f, +0.773438f,0.125f, +0.78125f,0.125f, +0.789063f,0.125f, +0.796875f,0.125f, +0.804688f,0.125f, +0.8125f,0.125f, +0.820313f,0.125f, +0.828125f,0.125f, +0.835938f,0.125f, +0.84375f,0.125f, +0.851563f,0.125f, +0.859375f,0.125f, +0.867188f,0.125f, +0.875f,0.125f, +0.882813f,0.125f, +0.890625f,0.125f, +0.898438f,0.125f, +0.90625f,0.125f, +0.914063f,0.125f, +0.921875f,0.125f, +0.929688f,0.125f, +0.9375f,0.125f, +0.945313f,0.125f, +0.953125f,0.125f, +0.960938f,0.125f, +0.96875f,0.125f, +0.976563f,0.125f, +0.984375f,0.125f, +0.992188f,0.125f, +1.0f,0.125f, +0.507813f,0.132813f, +0.515625f,0.132813f, +0.523438f,0.132813f, +0.53125f,0.132813f, +0.539063f,0.132813f, +0.546875f,0.132813f, +0.554688f,0.132813f, +0.5625f,0.132813f, +0.570313f,0.132813f, +0.578125f,0.132813f, +0.585938f,0.132813f, +0.59375f,0.132813f, +0.601563f,0.132813f, +0.609375f,0.132813f, +0.617188f,0.132813f, +0.625f,0.132813f, +0.632813f,0.132813f, +0.640625f,0.132813f, +0.648438f,0.132813f, +0.65625f,0.132813f, +0.664063f,0.132813f, +0.671875f,0.132813f, +0.679688f,0.132813f, +0.6875f,0.132813f, +0.695313f,0.132813f, +0.703125f,0.132813f, +0.710938f,0.132813f, +0.71875f,0.132813f, +0.726563f,0.132813f, +0.734375f,0.132813f, +0.742188f,0.132813f, +0.75f,0.132813f, +0.757813f,0.132813f, +0.765625f,0.132813f, +0.773438f,0.132813f, +0.78125f,0.132813f, +0.789063f,0.132813f, +0.796875f,0.132813f, +0.804688f,0.132813f, +0.8125f,0.132813f, +0.820313f,0.132813f, +0.828125f,0.132813f, +0.835938f,0.132813f, +0.84375f,0.132813f, +0.851563f,0.132813f, +0.859375f,0.132813f, +0.867188f,0.132813f, +0.875f,0.132813f, +0.882813f,0.132813f, +0.890625f,0.132813f, +0.898438f,0.132813f, +0.90625f,0.132813f, +0.914063f,0.132813f, +0.921875f,0.132813f, +0.929688f,0.132813f, +0.9375f,0.132813f, +0.945313f,0.132813f, +0.953125f,0.132813f, +0.960938f,0.132813f, +0.96875f,0.132813f, +0.976563f,0.132813f, +0.984375f,0.132813f, +0.992188f,0.132813f, +1.0f,0.132813f, +0.507813f,0.140625f, +0.515625f,0.140625f, +0.523438f,0.140625f, +0.53125f,0.140625f, +0.539063f,0.140625f, +0.546875f,0.140625f, +0.554688f,0.140625f, +0.5625f,0.140625f, +0.570313f,0.140625f, +0.578125f,0.140625f, +0.585938f,0.140625f, +0.59375f,0.140625f, +0.601563f,0.140625f, +0.609375f,0.140625f, +0.617188f,0.140625f, +0.625f,0.140625f, +0.632813f,0.140625f, +0.640625f,0.140625f, +0.648438f,0.140625f, +0.65625f,0.140625f, +0.664063f,0.140625f, +0.671875f,0.140625f, +0.679688f,0.140625f, +0.6875f,0.140625f, +0.695313f,0.140625f, +0.703125f,0.140625f, +0.710938f,0.140625f, +0.71875f,0.140625f, +0.726563f,0.140625f, +0.734375f,0.140625f, +0.742188f,0.140625f, +0.75f,0.140625f, +0.757813f,0.140625f, +0.765625f,0.140625f, +0.773438f,0.140625f, +0.78125f,0.140625f, +0.789063f,0.140625f, +0.796875f,0.140625f, +0.804688f,0.140625f, +0.8125f,0.140625f, +0.820313f,0.140625f, +0.828125f,0.140625f, +0.835938f,0.140625f, +0.84375f,0.140625f, +0.851563f,0.140625f, +0.859375f,0.140625f, +0.867188f,0.140625f, +0.875f,0.140625f, +0.882813f,0.140625f, +0.890625f,0.140625f, +0.898438f,0.140625f, +0.90625f,0.140625f, +0.914063f,0.140625f, +0.921875f,0.140625f, +0.929688f,0.140625f, +0.9375f,0.140625f, +0.945313f,0.140625f, +0.953125f,0.140625f, +0.960938f,0.140625f, +0.96875f,0.140625f, +0.976563f,0.140625f, +0.984375f,0.140625f, +0.992188f,0.140625f, +1.0f,0.140625f, +0.507813f,0.148438f, +0.515625f,0.148438f, +0.523438f,0.148438f, +0.53125f,0.148438f, +0.539063f,0.148438f, +0.546875f,0.148438f, +0.554688f,0.148438f, +0.5625f,0.148438f, +0.570313f,0.148438f, +0.578125f,0.148438f, +0.585938f,0.148438f, +0.59375f,0.148438f, +0.601563f,0.148438f, +0.609375f,0.148438f, +0.617188f,0.148438f, +0.625f,0.148438f, +0.632813f,0.148438f, +0.640625f,0.148438f, +0.648438f,0.148438f, +0.65625f,0.148438f, +0.664063f,0.148438f, +0.671875f,0.148438f, +0.679688f,0.148438f, +0.6875f,0.148438f, +0.695313f,0.148438f, +0.703125f,0.148438f, +0.710938f,0.148438f, +0.71875f,0.148438f, +0.726563f,0.148438f, +0.734375f,0.148438f, +0.742188f,0.148438f, +0.75f,0.148438f, +0.757813f,0.148438f, +0.765625f,0.148438f, +0.773438f,0.148438f, +0.78125f,0.148438f, +0.789063f,0.148438f, +0.796875f,0.148438f, +0.804688f,0.148438f, +0.8125f,0.148438f, +0.820313f,0.148438f, +0.828125f,0.148438f, +0.835938f,0.148438f, +0.84375f,0.148438f, +0.851563f,0.148438f, +0.859375f,0.148438f, +0.867188f,0.148438f, +0.875f,0.148438f, +0.882813f,0.148438f, +0.890625f,0.148438f, +0.898438f,0.148438f, +0.90625f,0.148438f, +0.914063f,0.148438f, +0.921875f,0.148438f, +0.929688f,0.148438f, +0.9375f,0.148438f, +0.945313f,0.148438f, +0.953125f,0.148438f, +0.960938f,0.148438f, +0.96875f,0.148438f, +0.976563f,0.148438f, +0.984375f,0.148438f, +0.992188f,0.148438f, +1.0f,0.148438f, +0.507813f,0.15625f, +0.515625f,0.15625f, +0.523438f,0.15625f, +0.53125f,0.15625f, +0.539063f,0.15625f, +0.546875f,0.15625f, +0.554688f,0.15625f, +0.5625f,0.15625f, +0.570313f,0.15625f, +0.578125f,0.15625f, +0.585938f,0.15625f, +0.59375f,0.15625f, +0.601563f,0.15625f, +0.609375f,0.15625f, +0.617188f,0.15625f, +0.625f,0.15625f, +0.632813f,0.15625f, +0.640625f,0.15625f, +0.648438f,0.15625f, +0.65625f,0.15625f, +0.664063f,0.15625f, +0.671875f,0.15625f, +0.679688f,0.15625f, +0.6875f,0.15625f, +0.695313f,0.15625f, +0.703125f,0.15625f, +0.710938f,0.15625f, +0.71875f,0.15625f, +0.726563f,0.15625f, +0.734375f,0.15625f, +0.742188f,0.15625f, +0.75f,0.15625f, +0.757813f,0.15625f, +0.765625f,0.15625f, +0.773438f,0.15625f, +0.78125f,0.15625f, +0.789063f,0.15625f, +0.796875f,0.15625f, +0.804688f,0.15625f, +0.8125f,0.15625f, +0.820313f,0.15625f, +0.828125f,0.15625f, +0.835938f,0.15625f, +0.84375f,0.15625f, +0.851563f,0.15625f, +0.859375f,0.15625f, +0.867188f,0.15625f, +0.875f,0.15625f, +0.882813f,0.15625f, +0.890625f,0.15625f, +0.898438f,0.15625f, +0.90625f,0.15625f, +0.914063f,0.15625f, +0.921875f,0.15625f, +0.929688f,0.15625f, +0.9375f,0.15625f, +0.945313f,0.15625f, +0.953125f,0.15625f, +0.960938f,0.15625f, +0.96875f,0.15625f, +0.976563f,0.15625f, +0.984375f,0.15625f, +0.992188f,0.15625f, +1.0f,0.15625f, +0.507813f,0.164063f, +0.515625f,0.164063f, +0.523438f,0.164063f, +0.53125f,0.164063f, +0.539063f,0.164063f, +0.546875f,0.164063f, +0.554688f,0.164063f, +0.5625f,0.164063f, +0.570313f,0.164063f, +0.578125f,0.164063f, +0.585938f,0.164063f, +0.59375f,0.164063f, +0.601563f,0.164063f, +0.609375f,0.164063f, +0.617188f,0.164063f, +0.625f,0.164063f, +0.632813f,0.164063f, +0.640625f,0.164063f, +0.648438f,0.164063f, +0.65625f,0.164063f, +0.664063f,0.164063f, +0.671875f,0.164063f, +0.679688f,0.164063f, +0.6875f,0.164063f, +0.695313f,0.164063f, +0.703125f,0.164063f, +0.710938f,0.164063f, +0.71875f,0.164063f, +0.726563f,0.164063f, +0.734375f,0.164063f, +0.742188f,0.164063f, +0.75f,0.164063f, +0.757813f,0.164063f, +0.765625f,0.164063f, +0.773438f,0.164063f, +0.78125f,0.164063f, +0.789063f,0.164063f, +0.796875f,0.164063f, +0.804688f,0.164063f, +0.8125f,0.164063f, +0.820313f,0.164063f, +0.828125f,0.164063f, +0.835938f,0.164063f, +0.84375f,0.164063f, +0.851563f,0.164063f, +0.859375f,0.164063f, +0.867188f,0.164063f, +0.875f,0.164063f, +0.882813f,0.164063f, +0.890625f,0.164063f, +0.898438f,0.164063f, +0.90625f,0.164063f, +0.914063f,0.164063f, +0.921875f,0.164063f, +0.929688f,0.164063f, +0.9375f,0.164063f, +0.945313f,0.164063f, +0.953125f,0.164063f, +0.960938f,0.164063f, +0.96875f,0.164063f, +0.976563f,0.164063f, +0.984375f,0.164063f, +0.992188f,0.164063f, +1.0f,0.164063f, +0.507813f,0.171875f, +0.515625f,0.171875f, +0.523438f,0.171875f, +0.53125f,0.171875f, +0.539063f,0.171875f, +0.546875f,0.171875f, +0.554688f,0.171875f, +0.5625f,0.171875f, +0.570313f,0.171875f, +0.578125f,0.171875f, +0.585938f,0.171875f, +0.59375f,0.171875f, +0.601563f,0.171875f, +0.609375f,0.171875f, +0.617188f,0.171875f, +0.625f,0.171875f, +0.632813f,0.171875f, +0.640625f,0.171875f, +0.648438f,0.171875f, +0.65625f,0.171875f, +0.664063f,0.171875f, +0.671875f,0.171875f, +0.679688f,0.171875f, +0.6875f,0.171875f, +0.695313f,0.171875f, +0.703125f,0.171875f, +0.710938f,0.171875f, +0.71875f,0.171875f, +0.726563f,0.171875f, +0.734375f,0.171875f, +0.742188f,0.171875f, +0.75f,0.171875f, +0.757813f,0.171875f, +0.765625f,0.171875f, +0.773438f,0.171875f, +0.78125f,0.171875f, +0.789063f,0.171875f, +0.796875f,0.171875f, +0.804688f,0.171875f, +0.8125f,0.171875f, +0.820313f,0.171875f, +0.828125f,0.171875f, +0.835938f,0.171875f, +0.84375f,0.171875f, +0.851563f,0.171875f, +0.859375f,0.171875f, +0.867188f,0.171875f, +0.875f,0.171875f, +0.882813f,0.171875f, +0.890625f,0.171875f, +0.898438f,0.171875f, +0.90625f,0.171875f, +0.914063f,0.171875f, +0.921875f,0.171875f, +0.929688f,0.171875f, +0.9375f,0.171875f, +0.945313f,0.171875f, +0.953125f,0.171875f, +0.960938f,0.171875f, +0.96875f,0.171875f, +0.976563f,0.171875f, +0.984375f,0.171875f, +0.992188f,0.171875f, +1.0f,0.171875f, +0.507813f,0.179688f, +0.515625f,0.179688f, +0.523438f,0.179688f, +0.53125f,0.179688f, +0.539063f,0.179688f, +0.546875f,0.179688f, +0.554688f,0.179688f, +0.5625f,0.179688f, +0.570313f,0.179688f, +0.578125f,0.179688f, +0.585938f,0.179688f, +0.59375f,0.179688f, +0.601563f,0.179688f, +0.609375f,0.179688f, +0.617188f,0.179688f, +0.625f,0.179688f, +0.632813f,0.179688f, +0.640625f,0.179688f, +0.648438f,0.179688f, +0.65625f,0.179688f, +0.664063f,0.179688f, +0.671875f,0.179688f, +0.679688f,0.179688f, +0.6875f,0.179688f, +0.695313f,0.179688f, +0.703125f,0.179688f, +0.710938f,0.179688f, +0.71875f,0.179688f, +0.726563f,0.179688f, +0.734375f,0.179688f, +0.742188f,0.179688f, +0.75f,0.179688f, +0.757813f,0.179688f, +0.765625f,0.179688f, +0.773438f,0.179688f, +0.78125f,0.179688f, +0.789063f,0.179688f, +0.796875f,0.179688f, +0.804688f,0.179688f, +0.8125f,0.179688f, +0.820313f,0.179688f, +0.828125f,0.179688f, +0.835938f,0.179688f, +0.84375f,0.179688f, +0.851563f,0.179688f, +0.859375f,0.179688f, +0.867188f,0.179688f, +0.875f,0.179688f, +0.882813f,0.179688f, +0.890625f,0.179688f, +0.898438f,0.179688f, +0.90625f,0.179688f, +0.914063f,0.179688f, +0.921875f,0.179688f, +0.929688f,0.179688f, +0.9375f,0.179688f, +0.945313f,0.179688f, +0.953125f,0.179688f, +0.960938f,0.179688f, +0.96875f,0.179688f, +0.976563f,0.179688f, +0.984375f,0.179688f, +0.992188f,0.179688f, +1.0f,0.179688f, +0.507813f,0.1875f, +0.515625f,0.1875f, +0.523438f,0.1875f, +0.53125f,0.1875f, +0.539063f,0.1875f, +0.546875f,0.1875f, +0.554688f,0.1875f, +0.5625f,0.1875f, +0.570313f,0.1875f, +0.578125f,0.1875f, +0.585938f,0.1875f, +0.59375f,0.1875f, +0.601563f,0.1875f, +0.609375f,0.1875f, +0.617188f,0.1875f, +0.625f,0.1875f, +0.632813f,0.1875f, +0.640625f,0.1875f, +0.648438f,0.1875f, +0.65625f,0.1875f, +0.664063f,0.1875f, +0.671875f,0.1875f, +0.679688f,0.1875f, +0.6875f,0.1875f, +0.695313f,0.1875f, +0.703125f,0.1875f, +0.710938f,0.1875f, +0.71875f,0.1875f, +0.726563f,0.1875f, +0.734375f,0.1875f, +0.742188f,0.1875f, +0.75f,0.1875f, +0.757813f,0.1875f, +0.765625f,0.1875f, +0.773438f,0.1875f, +0.78125f,0.1875f, +0.789063f,0.1875f, +0.796875f,0.1875f, +0.804688f,0.1875f, +0.8125f,0.1875f, +0.820313f,0.1875f, +0.828125f,0.1875f, +0.835938f,0.1875f, +0.84375f,0.1875f, +0.851563f,0.1875f, +0.859375f,0.1875f, +0.867188f,0.1875f, +0.875f,0.1875f, +0.882813f,0.1875f, +0.890625f,0.1875f, +0.898438f,0.1875f, +0.90625f,0.1875f, +0.914063f,0.1875f, +0.921875f,0.1875f, +0.929688f,0.1875f, +0.9375f,0.1875f, +0.945313f,0.1875f, +0.953125f,0.1875f, +0.960938f,0.1875f, +0.96875f,0.1875f, +0.976563f,0.1875f, +0.984375f,0.1875f, +0.992188f,0.1875f, +1.0f,0.1875f, +0.507813f,0.195313f, +0.515625f,0.195313f, +0.523438f,0.195313f, +0.53125f,0.195313f, +0.539063f,0.195313f, +0.546875f,0.195313f, +0.554688f,0.195313f, +0.5625f,0.195313f, +0.570313f,0.195313f, +0.578125f,0.195313f, +0.585938f,0.195313f, +0.59375f,0.195313f, +0.601563f,0.195313f, +0.609375f,0.195313f, +0.617188f,0.195313f, +0.625f,0.195313f, +0.632813f,0.195313f, +0.640625f,0.195313f, +0.648438f,0.195313f, +0.65625f,0.195313f, +0.664063f,0.195313f, +0.671875f,0.195313f, +0.679688f,0.195313f, +0.6875f,0.195313f, +0.695313f,0.195313f, +0.703125f,0.195313f, +0.710938f,0.195313f, +0.71875f,0.195313f, +0.726563f,0.195313f, +0.734375f,0.195313f, +0.742188f,0.195313f, +0.75f,0.195313f, +0.757813f,0.195313f, +0.765625f,0.195313f, +0.773438f,0.195313f, +0.78125f,0.195313f, +0.789063f,0.195313f, +0.796875f,0.195313f, +0.804688f,0.195313f, +0.8125f,0.195313f, +0.820313f,0.195313f, +0.828125f,0.195313f, +0.835938f,0.195313f, +0.84375f,0.195313f, +0.851563f,0.195313f, +0.859375f,0.195313f, +0.867188f,0.195313f, +0.875f,0.195313f, +0.882813f,0.195313f, +0.890625f,0.195313f, +0.898438f,0.195313f, +0.90625f,0.195313f, +0.914063f,0.195313f, +0.921875f,0.195313f, +0.929688f,0.195313f, +0.9375f,0.195313f, +0.945313f,0.195313f, +0.953125f,0.195313f, +0.960938f,0.195313f, +0.96875f,0.195313f, +0.976563f,0.195313f, +0.984375f,0.195313f, +0.992188f,0.195313f, +1.0f,0.195313f, +0.507813f,0.203125f, +0.515625f,0.203125f, +0.523438f,0.203125f, +0.53125f,0.203125f, +0.539063f,0.203125f, +0.546875f,0.203125f, +0.554688f,0.203125f, +0.5625f,0.203125f, +0.570313f,0.203125f, +0.578125f,0.203125f, +0.585938f,0.203125f, +0.59375f,0.203125f, +0.601563f,0.203125f, +0.609375f,0.203125f, +0.617188f,0.203125f, +0.625f,0.203125f, +0.632813f,0.203125f, +0.640625f,0.203125f, +0.648438f,0.203125f, +0.65625f,0.203125f, +0.664063f,0.203125f, +0.671875f,0.203125f, +0.679688f,0.203125f, +0.6875f,0.203125f, +0.695313f,0.203125f, +0.703125f,0.203125f, +0.710938f,0.203125f, +0.71875f,0.203125f, +0.726563f,0.203125f, +0.734375f,0.203125f, +0.742188f,0.203125f, +0.75f,0.203125f, +0.757813f,0.203125f, +0.765625f,0.203125f, +0.773438f,0.203125f, +0.78125f,0.203125f, +0.789063f,0.203125f, +0.796875f,0.203125f, +0.804688f,0.203125f, +0.8125f,0.203125f, +0.820313f,0.203125f, +0.828125f,0.203125f, +0.835938f,0.203125f, +0.84375f,0.203125f, +0.851563f,0.203125f, +0.859375f,0.203125f, +0.867188f,0.203125f, +0.875f,0.203125f, +0.882813f,0.203125f, +0.890625f,0.203125f, +0.898438f,0.203125f, +0.90625f,0.203125f, +0.914063f,0.203125f, +0.921875f,0.203125f, +0.929688f,0.203125f, +0.9375f,0.203125f, +0.945313f,0.203125f, +0.953125f,0.203125f, +0.960938f,0.203125f, +0.96875f,0.203125f, +0.976563f,0.203125f, +0.984375f,0.203125f, +0.992188f,0.203125f, +1.0f,0.203125f, +0.507813f,0.210938f, +0.515625f,0.210938f, +0.523438f,0.210938f, +0.53125f,0.210938f, +0.539063f,0.210938f, +0.546875f,0.210938f, +0.554688f,0.210938f, +0.5625f,0.210938f, +0.570313f,0.210938f, +0.578125f,0.210938f, +0.585938f,0.210938f, +0.59375f,0.210938f, +0.601563f,0.210938f, +0.609375f,0.210938f, +0.617188f,0.210938f, +0.625f,0.210938f, +0.632813f,0.210938f, +0.640625f,0.210938f, +0.648438f,0.210938f, +0.65625f,0.210938f, +0.664063f,0.210938f, +0.671875f,0.210938f, +0.679688f,0.210938f, +0.6875f,0.210938f, +0.695313f,0.210938f, +0.703125f,0.210938f, +0.710938f,0.210938f, +0.71875f,0.210938f, +0.726563f,0.210938f, +0.734375f,0.210938f, +0.742188f,0.210938f, +0.75f,0.210938f, +0.757813f,0.210938f, +0.765625f,0.210938f, +0.773438f,0.210938f, +0.78125f,0.210938f, +0.789063f,0.210938f, +0.796875f,0.210938f, +0.804688f,0.210938f, +0.8125f,0.210938f, +0.820313f,0.210938f, +0.828125f,0.210938f, +0.835938f,0.210938f, +0.84375f,0.210938f, +0.851563f,0.210938f, +0.859375f,0.210938f, +0.867188f,0.210938f, +0.875f,0.210938f, +0.882813f,0.210938f, +0.890625f,0.210938f, +0.898438f,0.210938f, +0.90625f,0.210938f, +0.914063f,0.210938f, +0.921875f,0.210938f, +0.929688f,0.210938f, +0.9375f,0.210938f, +0.945313f,0.210938f, +0.953125f,0.210938f, +0.960938f,0.210938f, +0.96875f,0.210938f, +0.976563f,0.210938f, +0.984375f,0.210938f, +0.992188f,0.210938f, +1.0f,0.210938f, +0.507813f,0.21875f, +0.515625f,0.21875f, +0.523438f,0.21875f, +0.53125f,0.21875f, +0.539063f,0.21875f, +0.546875f,0.21875f, +0.554688f,0.21875f, +0.5625f,0.21875f, +0.570313f,0.21875f, +0.578125f,0.21875f, +0.585938f,0.21875f, +0.59375f,0.21875f, +0.601563f,0.21875f, +0.609375f,0.21875f, +0.617188f,0.21875f, +0.625f,0.21875f, +0.632813f,0.21875f, +0.640625f,0.21875f, +0.648438f,0.21875f, +0.65625f,0.21875f, +0.664063f,0.21875f, +0.671875f,0.21875f, +0.679688f,0.21875f, +0.6875f,0.21875f, +0.695313f,0.21875f, +0.703125f,0.21875f, +0.710938f,0.21875f, +0.71875f,0.21875f, +0.726563f,0.21875f, +0.734375f,0.21875f, +0.742188f,0.21875f, +0.75f,0.21875f, +0.757813f,0.21875f, +0.765625f,0.21875f, +0.773438f,0.21875f, +0.78125f,0.21875f, +0.789063f,0.21875f, +0.796875f,0.21875f, +0.804688f,0.21875f, +0.8125f,0.21875f, +0.820313f,0.21875f, +0.828125f,0.21875f, +0.835938f,0.21875f, +0.84375f,0.21875f, +0.851563f,0.21875f, +0.859375f,0.21875f, +0.867188f,0.21875f, +0.875f,0.21875f, +0.882813f,0.21875f, +0.890625f,0.21875f, +0.898438f,0.21875f, +0.90625f,0.21875f, +0.914063f,0.21875f, +0.921875f,0.21875f, +0.929688f,0.21875f, +0.9375f,0.21875f, +0.945313f,0.21875f, +0.953125f,0.21875f, +0.960938f,0.21875f, +0.96875f,0.21875f, +0.976563f,0.21875f, +0.984375f,0.21875f, +0.992188f,0.21875f, +1.0f,0.21875f, +0.507813f,0.226563f, +0.515625f,0.226563f, +0.523438f,0.226563f, +0.53125f,0.226563f, +0.539063f,0.226563f, +0.546875f,0.226563f, +0.554688f,0.226563f, +0.5625f,0.226563f, +0.570313f,0.226563f, +0.578125f,0.226563f, +0.585938f,0.226563f, +0.59375f,0.226563f, +0.601563f,0.226563f, +0.609375f,0.226563f, +0.617188f,0.226563f, +0.625f,0.226563f, +0.632813f,0.226563f, +0.640625f,0.226563f, +0.648438f,0.226563f, +0.65625f,0.226563f, +0.664063f,0.226563f, +0.671875f,0.226563f, +0.679688f,0.226563f, +0.6875f,0.226563f, +0.695313f,0.226563f, +0.703125f,0.226563f, +0.710938f,0.226563f, +0.71875f,0.226563f, +0.726563f,0.226563f, +0.734375f,0.226563f, +0.742188f,0.226563f, +0.75f,0.226563f, +0.757813f,0.226563f, +0.765625f,0.226563f, +0.773438f,0.226563f, +0.78125f,0.226563f, +0.789063f,0.226563f, +0.796875f,0.226563f, +0.804688f,0.226563f, +0.8125f,0.226563f, +0.820313f,0.226563f, +0.828125f,0.226563f, +0.835938f,0.226563f, +0.84375f,0.226563f, +0.851563f,0.226563f, +0.859375f,0.226563f, +0.867188f,0.226563f, +0.875f,0.226563f, +0.882813f,0.226563f, +0.890625f,0.226563f, +0.898438f,0.226563f, +0.90625f,0.226563f, +0.914063f,0.226563f, +0.921875f,0.226563f, +0.929688f,0.226563f, +0.9375f,0.226563f, +0.945313f,0.226563f, +0.953125f,0.226563f, +0.960938f,0.226563f, +0.96875f,0.226563f, +0.976563f,0.226563f, +0.984375f,0.226563f, +0.992188f,0.226563f, +1.0f,0.226563f, +0.507813f,0.234375f, +0.515625f,0.234375f, +0.523438f,0.234375f, +0.53125f,0.234375f, +0.539063f,0.234375f, +0.546875f,0.234375f, +0.554688f,0.234375f, +0.5625f,0.234375f, +0.570313f,0.234375f, +0.578125f,0.234375f, +0.585938f,0.234375f, +0.59375f,0.234375f, +0.601563f,0.234375f, +0.609375f,0.234375f, +0.617188f,0.234375f, +0.625f,0.234375f, +0.632813f,0.234375f, +0.640625f,0.234375f, +0.648438f,0.234375f, +0.65625f,0.234375f, +0.664063f,0.234375f, +0.671875f,0.234375f, +0.679688f,0.234375f, +0.6875f,0.234375f, +0.695313f,0.234375f, +0.703125f,0.234375f, +0.710938f,0.234375f, +0.71875f,0.234375f, +0.726563f,0.234375f, +0.734375f,0.234375f, +0.742188f,0.234375f, +0.75f,0.234375f, +0.757813f,0.234375f, +0.765625f,0.234375f, +0.773438f,0.234375f, +0.78125f,0.234375f, +0.789063f,0.234375f, +0.796875f,0.234375f, +0.804688f,0.234375f, +0.8125f,0.234375f, +0.820313f,0.234375f, +0.828125f,0.234375f, +0.835938f,0.234375f, +0.84375f,0.234375f, +0.851563f,0.234375f, +0.859375f,0.234375f, +0.867188f,0.234375f, +0.875f,0.234375f, +0.882813f,0.234375f, +0.890625f,0.234375f, +0.898438f,0.234375f, +0.90625f,0.234375f, +0.914063f,0.234375f, +0.921875f,0.234375f, +0.929688f,0.234375f, +0.9375f,0.234375f, +0.945313f,0.234375f, +0.953125f,0.234375f, +0.960938f,0.234375f, +0.96875f,0.234375f, +0.976563f,0.234375f, +0.984375f,0.234375f, +0.992188f,0.234375f, +1.0f,0.234375f, +0.507813f,0.242188f, +0.515625f,0.242188f, +0.523438f,0.242188f, +0.53125f,0.242188f, +0.539063f,0.242188f, +0.546875f,0.242188f, +0.554688f,0.242188f, +0.5625f,0.242188f, +0.570313f,0.242188f, +0.578125f,0.242188f, +0.585938f,0.242188f, +0.59375f,0.242188f, +0.601563f,0.242188f, +0.609375f,0.242188f, +0.617188f,0.242188f, +0.625f,0.242188f, +0.632813f,0.242188f, +0.640625f,0.242188f, +0.648438f,0.242188f, +0.65625f,0.242188f, +0.664063f,0.242188f, +0.671875f,0.242188f, +0.679688f,0.242188f, +0.6875f,0.242188f, +0.695313f,0.242188f, +0.703125f,0.242188f, +0.710938f,0.242188f, +0.71875f,0.242188f, +0.726563f,0.242188f, +0.734375f,0.242188f, +0.742188f,0.242188f, +0.75f,0.242188f, +0.757813f,0.242188f, +0.765625f,0.242188f, +0.773438f,0.242188f, +0.78125f,0.242188f, +0.789063f,0.242188f, +0.796875f,0.242188f, +0.804688f,0.242188f, +0.8125f,0.242188f, +0.820313f,0.242188f, +0.828125f,0.242188f, +0.835938f,0.242188f, +0.84375f,0.242188f, +0.851563f,0.242188f, +0.859375f,0.242188f, +0.867188f,0.242188f, +0.875f,0.242188f, +0.882813f,0.242188f, +0.890625f,0.242188f, +0.898438f,0.242188f, +0.90625f,0.242188f, +0.914063f,0.242188f, +0.921875f,0.242188f, +0.929688f,0.242188f, +0.9375f,0.242188f, +0.945313f,0.242188f, +0.953125f,0.242188f, +0.960938f,0.242188f, +0.96875f,0.242188f, +0.976563f,0.242188f, +0.984375f,0.242188f, +0.992188f,0.242188f, +1.0f,0.242188f, +}; + +unsigned short Landscape01Idx[] = { +0,1,2, +3,2,1, +2,3,4, +5,4,3, +4,5,6, +7,6,5, +6,7,8, +9,8,7, +8,9,10, +11,10,9, +10,11,12, +13,12,11, +12,13,14, +15,14,13, +14,15,16, +17,16,15, +16,17,18, +19,18,17, +18,19,20, +21,20,19, +20,21,22, +23,22,21, +22,23,24, +25,24,23, +24,25,26, +27,26,25, +26,27,28, +29,28,27, +28,29,30, +31,30,29, +30,31,32, +33,32,31, +32,33,34, +35,34,33, +34,35,36, +37,36,35, +36,37,38, +39,38,37, +38,39,40, +41,40,39, +40,41,42, +43,42,41, +42,43,44, +45,44,43, +44,45,46, +47,46,45, +46,47,48, +49,48,47, +48,49,50, +51,50,49, +50,51,52, +53,52,51, +52,53,54, +55,54,53, +54,55,56, +57,56,55, +56,57,58, +59,58,57, +58,59,60, +61,60,59, +60,61,62, +63,62,61, +62,63,64, +65,64,63, +64,65,66, +67,66,65, +66,67,68, +69,68,67, +68,69,70, +71,70,69, +70,71,72, +73,72,71, +72,73,74, +75,74,73, +74,75,76, +77,76,75, +76,77,78, +79,78,77, +78,79,80, +81,80,79, +80,81,82, +83,82,81, +82,83,84, +85,84,83, +84,85,86, +87,86,85, +86,87,88, +89,88,87, +88,89,90, +91,90,89, +90,91,92, +93,92,91, +92,93,94, +95,94,93, +94,95,96, +97,96,95, +96,97,98, +99,98,97, +98,99,100, +101,100,99, +100,101,102, +103,102,101, +102,103,104, +105,104,103, +104,105,106, +107,106,105, +106,107,108, +109,108,107, +108,109,110, +111,110,109, +110,111,112, +113,112,111, +112,113,114, +115,114,113, +114,115,116, +117,116,115, +116,117,118, +119,118,117, +118,119,120, +121,120,119, +120,121,122, +123,122,121, +122,123,124, +125,124,123, +124,125,126, +127,126,125, +128,0,129, +2,129,0, +129,2,130, +4,130,2, +130,4,131, +6,131,4, +131,6,132, +8,132,6, +132,8,133, +10,133,8, +133,10,134, +12,134,10, +134,12,135, +14,135,12, +135,14,136, +16,136,14, +136,16,137, +18,137,16, +137,18,138, +20,138,18, +138,20,139, +22,139,20, +139,22,140, +24,140,22, +140,24,141, +26,141,24, +141,26,142, +28,142,26, +142,28,143, +30,143,28, +143,30,144, +32,144,30, +144,32,145, +34,145,32, +145,34,146, +36,146,34, +146,36,147, +38,147,36, +147,38,148, +40,148,38, +148,40,149, +42,149,40, +149,42,150, +44,150,42, +150,44,151, +46,151,44, +151,46,152, +48,152,46, +152,48,153, +50,153,48, +153,50,154, +52,154,50, +154,52,155, +54,155,52, +155,54,156, +56,156,54, +156,56,157, +58,157,56, +157,58,158, +60,158,58, +158,60,159, +62,159,60, +159,62,160, +64,160,62, +160,64,161, +66,161,64, +161,66,162, +68,162,66, +162,68,163, +70,163,68, +163,70,164, +72,164,70, +164,72,165, +74,165,72, +165,74,166, +76,166,74, +166,76,167, +78,167,76, +167,78,168, +80,168,78, +168,80,169, +82,169,80, +169,82,170, +84,170,82, +170,84,171, +86,171,84, +171,86,172, +88,172,86, +172,88,173, +90,173,88, +173,90,174, +92,174,90, +174,92,175, +94,175,92, +175,94,176, +96,176,94, +176,96,177, +98,177,96, +177,98,178, +100,178,98, +178,100,179, +102,179,100, +179,102,180, +104,180,102, +180,104,181, +106,181,104, +181,106,182, +108,182,106, +182,108,183, +110,183,108, +183,110,184, +112,184,110, +184,112,185, +114,185,112, +185,114,186, +116,186,114, +186,116,187, +118,187,116, +187,118,188, +120,188,118, +188,120,189, +122,189,120, +189,122,190, +124,190,122, +190,124,191, +126,191,124, +192,128,193, +129,193,128, +193,129,194, +130,194,129, +194,130,195, +131,195,130, +195,131,196, +132,196,131, +196,132,197, +133,197,132, +197,133,198, +134,198,133, +198,134,199, +135,199,134, +199,135,200, +136,200,135, +200,136,201, +137,201,136, +201,137,202, +138,202,137, +202,138,203, +139,203,138, +203,139,204, +140,204,139, +204,140,205, +141,205,140, +205,141,206, +142,206,141, +206,142,207, +143,207,142, +207,143,208, +144,208,143, +208,144,209, +145,209,144, +209,145,210, +146,210,145, +210,146,211, +147,211,146, +211,147,212, +148,212,147, +212,148,213, +149,213,148, +213,149,214, +150,214,149, +214,150,215, +151,215,150, +215,151,216, +152,216,151, +216,152,217, +153,217,152, +217,153,218, +154,218,153, +218,154,219, +155,219,154, +219,155,220, +156,220,155, +220,156,221, +157,221,156, +221,157,222, +158,222,157, +222,158,223, +159,223,158, +223,159,224, +160,224,159, +224,160,225, +161,225,160, +225,161,226, +162,226,161, +226,162,227, +163,227,162, +227,163,228, +164,228,163, +228,164,229, +165,229,164, +229,165,230, +166,230,165, +230,166,231, +167,231,166, +231,167,232, +168,232,167, +232,168,233, +169,233,168, +233,169,234, +170,234,169, +234,170,235, +171,235,170, +235,171,236, +172,236,171, +236,172,237, +173,237,172, +237,173,238, +174,238,173, +238,174,239, +175,239,174, +239,175,240, +176,240,175, +240,176,241, +177,241,176, +241,177,242, +178,242,177, +242,178,243, +179,243,178, +243,179,244, +180,244,179, +244,180,245, +181,245,180, +245,181,246, +182,246,181, +246,182,247, +183,247,182, +247,183,248, +184,248,183, +248,184,249, +185,249,184, +249,185,250, +186,250,185, +250,186,251, +187,251,186, +251,187,252, +188,252,187, +252,188,253, +189,253,188, +253,189,254, +190,254,189, +254,190,255, +191,255,190, +256,192,257, +193,257,192, +257,193,258, +194,258,193, +258,194,259, +195,259,194, +259,195,260, +196,260,195, +260,196,261, +197,261,196, +261,197,262, +198,262,197, +262,198,263, +199,263,198, +263,199,264, +200,264,199, +264,200,265, +201,265,200, +265,201,266, +202,266,201, +266,202,267, +203,267,202, +267,203,268, +204,268,203, +268,204,269, +205,269,204, +269,205,270, +206,270,205, +270,206,271, +207,271,206, +271,207,272, +208,272,207, +272,208,273, +209,273,208, +273,209,274, +210,274,209, +274,210,275, +211,275,210, +275,211,276, +212,276,211, +276,212,277, +213,277,212, +277,213,278, +214,278,213, +278,214,279, +215,279,214, +279,215,280, +216,280,215, +280,216,281, +217,281,216, +281,217,282, +218,282,217, +282,218,283, +219,283,218, +283,219,284, +220,284,219, +284,220,285, +221,285,220, +285,221,286, +222,286,221, +286,222,287, +223,287,222, +287,223,288, +224,288,223, +288,224,289, +225,289,224, +289,225,290, +226,290,225, +290,226,291, +227,291,226, +291,227,292, +228,292,227, +292,228,293, +229,293,228, +293,229,294, +230,294,229, +294,230,295, +231,295,230, +295,231,296, +232,296,231, +296,232,297, +233,297,232, +297,233,298, +234,298,233, +298,234,299, +235,299,234, +299,235,300, +236,300,235, +300,236,301, +237,301,236, +301,237,302, +238,302,237, +302,238,303, +239,303,238, +303,239,304, +240,304,239, +304,240,305, +241,305,240, +305,241,306, +242,306,241, +306,242,307, +243,307,242, +307,243,308, +244,308,243, +308,244,309, +245,309,244, +309,245,310, +246,310,245, +310,246,311, +247,311,246, +311,247,312, +248,312,247, +312,248,313, +249,313,248, +313,249,314, +250,314,249, +314,250,315, +251,315,250, +315,251,316, +252,316,251, +316,252,317, +253,317,252, +317,253,318, +254,318,253, +318,254,319, +255,319,254, +320,256,321, +257,321,256, +321,257,322, +258,322,257, +322,258,323, +259,323,258, +323,259,324, +260,324,259, +324,260,325, +261,325,260, +325,261,326, +262,326,261, +326,262,327, +263,327,262, +327,263,328, +264,328,263, +328,264,329, +265,329,264, +329,265,330, +266,330,265, +330,266,331, +267,331,266, +331,267,332, +268,332,267, +332,268,333, +269,333,268, +333,269,334, +270,334,269, +334,270,335, +271,335,270, +335,271,336, +272,336,271, +336,272,337, +273,337,272, +337,273,338, +274,338,273, +338,274,339, +275,339,274, +339,275,340, +276,340,275, +340,276,341, +277,341,276, +341,277,342, +278,342,277, +342,278,343, +279,343,278, +343,279,344, +280,344,279, +344,280,345, +281,345,280, +345,281,346, +282,346,281, +346,282,347, +283,347,282, +347,283,348, +284,348,283, +348,284,349, +285,349,284, +349,285,350, +286,350,285, +350,286,351, +287,351,286, +351,287,352, +288,352,287, +352,288,353, +289,353,288, +353,289,354, +290,354,289, +354,290,355, +291,355,290, +355,291,356, +292,356,291, +356,292,357, +293,357,292, +357,293,358, +294,358,293, +358,294,359, +295,359,294, +359,295,360, +296,360,295, +360,296,361, +297,361,296, +361,297,362, +298,362,297, +362,298,363, +299,363,298, +363,299,364, +300,364,299, +364,300,365, +301,365,300, +365,301,366, +302,366,301, +366,302,367, +303,367,302, +367,303,368, +304,368,303, +368,304,369, +305,369,304, +369,305,370, +306,370,305, +370,306,371, +307,371,306, +371,307,372, +308,372,307, +372,308,373, +309,373,308, +373,309,374, +310,374,309, +374,310,375, +311,375,310, +375,311,376, +312,376,311, +376,312,377, +313,377,312, +377,313,378, +314,378,313, +378,314,379, +315,379,314, +379,315,380, +316,380,315, +380,316,381, +317,381,316, +381,317,382, +318,382,317, +382,318,383, +319,383,318, +384,320,385, +321,385,320, +385,321,386, +322,386,321, +386,322,387, +323,387,322, +387,323,388, +324,388,323, +388,324,389, +325,389,324, +389,325,390, +326,390,325, +390,326,391, +327,391,326, +391,327,392, +328,392,327, +392,328,393, +329,393,328, +393,329,394, +330,394,329, +394,330,395, +331,395,330, +395,331,396, +332,396,331, +396,332,397, +333,397,332, +397,333,398, +334,398,333, +398,334,399, +335,399,334, +399,335,400, +336,400,335, +400,336,401, +337,401,336, +401,337,402, +338,402,337, +402,338,403, +339,403,338, +403,339,404, +340,404,339, +404,340,405, +341,405,340, +405,341,406, +342,406,341, +406,342,407, +343,407,342, +407,343,408, +344,408,343, +408,344,409, +345,409,344, +409,345,410, +346,410,345, +410,346,411, +347,411,346, +411,347,412, +348,412,347, +412,348,413, +349,413,348, +413,349,414, +350,414,349, +414,350,415, +351,415,350, +415,351,416, +352,416,351, +416,352,417, +353,417,352, +417,353,418, +354,418,353, +418,354,419, +355,419,354, +419,355,420, +356,420,355, +420,356,421, +357,421,356, +421,357,422, +358,422,357, +422,358,423, +359,423,358, +423,359,424, +360,424,359, +424,360,425, +361,425,360, +425,361,426, +362,426,361, +426,362,427, +363,427,362, +427,363,428, +364,428,363, +428,364,429, +365,429,364, +429,365,430, +366,430,365, +430,366,431, +367,431,366, +431,367,432, +368,432,367, +432,368,433, +369,433,368, +433,369,434, +370,434,369, +434,370,435, +371,435,370, +435,371,436, +372,436,371, +436,372,437, +373,437,372, +437,373,438, +374,438,373, +438,374,439, +375,439,374, +439,375,440, +376,440,375, +440,376,441, +377,441,376, +441,377,442, +378,442,377, +442,378,443, +379,443,378, +443,379,444, +380,444,379, +444,380,445, +381,445,380, +445,381,446, +382,446,381, +446,382,447, +383,447,382, +448,384,449, +385,449,384, +449,385,450, +386,450,385, +450,386,451, +387,451,386, +451,387,452, +388,452,387, +452,388,453, +389,453,388, +453,389,454, +390,454,389, +454,390,455, +391,455,390, +455,391,456, +392,456,391, +456,392,457, +393,457,392, +457,393,458, +394,458,393, +458,394,459, +395,459,394, +459,395,460, +396,460,395, +460,396,461, +397,461,396, +461,397,462, +398,462,397, +462,398,463, +399,463,398, +463,399,464, +400,464,399, +464,400,465, +401,465,400, +465,401,466, +402,466,401, +466,402,467, +403,467,402, +467,403,468, +404,468,403, +468,404,469, +405,469,404, +469,405,470, +406,470,405, +470,406,471, +407,471,406, +471,407,472, +408,472,407, +472,408,473, +409,473,408, +473,409,474, +410,474,409, +474,410,475, +411,475,410, +475,411,476, +412,476,411, +476,412,477, +413,477,412, +477,413,478, +414,478,413, +478,414,479, +415,479,414, +479,415,480, +416,480,415, +480,416,481, +417,481,416, +481,417,482, +418,482,417, +482,418,483, +419,483,418, +483,419,484, +420,484,419, +484,420,485, +421,485,420, +485,421,486, +422,486,421, +486,422,487, +423,487,422, +487,423,488, +424,488,423, +488,424,489, +425,489,424, +489,425,490, +426,490,425, +490,426,491, +427,491,426, +491,427,492, +428,492,427, +492,428,493, +429,493,428, +493,429,494, +430,494,429, +494,430,495, +431,495,430, +495,431,496, +432,496,431, +496,432,497, +433,497,432, +497,433,498, +434,498,433, +498,434,499, +435,499,434, +499,435,500, +436,500,435, +500,436,501, +437,501,436, +501,437,502, +438,502,437, +502,438,503, +439,503,438, +503,439,504, +440,504,439, +504,440,505, +441,505,440, +505,441,506, +442,506,441, +506,442,507, +443,507,442, +507,443,508, +444,508,443, +508,444,509, +445,509,444, +509,445,510, +446,510,445, +510,446,511, +447,511,446, +512,448,513, +449,513,448, +513,449,514, +450,514,449, +514,450,515, +451,515,450, +515,451,516, +452,516,451, +516,452,517, +453,517,452, +517,453,518, +454,518,453, +518,454,519, +455,519,454, +519,455,520, +456,520,455, +520,456,521, +457,521,456, +521,457,522, +458,522,457, +522,458,523, +459,523,458, +523,459,524, +460,524,459, +524,460,525, +461,525,460, +525,461,526, +462,526,461, +526,462,527, +463,527,462, +527,463,528, +464,528,463, +528,464,529, +465,529,464, +529,465,530, +466,530,465, +530,466,531, +467,531,466, +531,467,532, +468,532,467, +532,468,533, +469,533,468, +533,469,534, +470,534,469, +534,470,535, +471,535,470, +535,471,536, +472,536,471, +536,472,537, +473,537,472, +537,473,538, +474,538,473, +538,474,539, +475,539,474, +539,475,540, +476,540,475, +540,476,541, +477,541,476, +541,477,542, +478,542,477, +542,478,543, +479,543,478, +543,479,544, +480,544,479, +544,480,545, +481,545,480, +545,481,546, +482,546,481, +546,482,547, +483,547,482, +547,483,548, +484,548,483, +548,484,549, +485,549,484, +549,485,550, +486,550,485, +550,486,551, +487,551,486, +551,487,552, +488,552,487, +552,488,553, +489,553,488, +553,489,554, +490,554,489, +554,490,555, +491,555,490, +555,491,556, +492,556,491, +556,492,557, +493,557,492, +557,493,558, +494,558,493, +558,494,559, +495,559,494, +559,495,560, +496,560,495, +560,496,561, +497,561,496, +561,497,562, +498,562,497, +562,498,563, +499,563,498, +563,499,564, +500,564,499, +564,500,565, +501,565,500, +565,501,566, +502,566,501, +566,502,567, +503,567,502, +567,503,568, +504,568,503, +568,504,569, +505,569,504, +569,505,570, +506,570,505, +570,506,571, +507,571,506, +571,507,572, +508,572,507, +572,508,573, +509,573,508, +573,509,574, +510,574,509, +574,510,575, +511,575,510, +576,512,577, +513,577,512, +577,513,578, +514,578,513, +578,514,579, +515,579,514, +579,515,580, +516,580,515, +580,516,581, +517,581,516, +581,517,582, +518,582,517, +582,518,583, +519,583,518, +583,519,584, +520,584,519, +584,520,585, +521,585,520, +585,521,586, +522,586,521, +586,522,587, +523,587,522, +587,523,588, +524,588,523, +588,524,589, +525,589,524, +589,525,590, +526,590,525, +590,526,591, +527,591,526, +591,527,592, +528,592,527, +592,528,593, +529,593,528, +593,529,594, +530,594,529, +594,530,595, +531,595,530, +595,531,596, +532,596,531, +596,532,597, +533,597,532, +597,533,598, +534,598,533, +598,534,599, +535,599,534, +599,535,600, +536,600,535, +600,536,601, +537,601,536, +601,537,602, +538,602,537, +602,538,603, +539,603,538, +603,539,604, +540,604,539, +604,540,605, +541,605,540, +605,541,606, +542,606,541, +606,542,607, +543,607,542, +607,543,608, +544,608,543, +608,544,609, +545,609,544, +609,545,610, +546,610,545, +610,546,611, +547,611,546, +611,547,612, +548,612,547, +612,548,613, +549,613,548, +613,549,614, +550,614,549, +614,550,615, +551,615,550, +615,551,616, +552,616,551, +616,552,617, +553,617,552, +617,553,618, +554,618,553, +618,554,619, +555,619,554, +619,555,620, +556,620,555, +620,556,621, +557,621,556, +621,557,622, +558,622,557, +622,558,623, +559,623,558, +623,559,624, +560,624,559, +624,560,625, +561,625,560, +625,561,626, +562,626,561, +626,562,627, +563,627,562, +627,563,628, +564,628,563, +628,564,629, +565,629,564, +629,565,630, +566,630,565, +630,566,631, +567,631,566, +631,567,632, +568,632,567, +632,568,633, +569,633,568, +633,569,634, +570,634,569, +634,570,635, +571,635,570, +635,571,636, +572,636,571, +636,572,637, +573,637,572, +637,573,638, +574,638,573, +638,574,639, +575,639,574, +640,576,641, +577,641,576, +641,577,642, +578,642,577, +642,578,643, +579,643,578, +643,579,644, +580,644,579, +644,580,645, +581,645,580, +645,581,646, +582,646,581, +646,582,647, +583,647,582, +647,583,648, +584,648,583, +648,584,649, +585,649,584, +649,585,650, +586,650,585, +650,586,651, +587,651,586, +651,587,652, +588,652,587, +652,588,653, +589,653,588, +653,589,654, +590,654,589, +654,590,655, +591,655,590, +655,591,656, +592,656,591, +656,592,657, +593,657,592, +657,593,658, +594,658,593, +658,594,659, +595,659,594, +659,595,660, +596,660,595, +660,596,661, +597,661,596, +661,597,662, +598,662,597, +662,598,663, +599,663,598, +663,599,664, +600,664,599, +664,600,665, +601,665,600, +665,601,666, +602,666,601, +666,602,667, +603,667,602, +667,603,668, +604,668,603, +668,604,669, +605,669,604, +669,605,670, +606,670,605, +670,606,671, +607,671,606, +671,607,672, +608,672,607, +672,608,673, +609,673,608, +673,609,674, +610,674,609, +674,610,675, +611,675,610, +675,611,676, +612,676,611, +676,612,677, +613,677,612, +677,613,678, +614,678,613, +678,614,679, +615,679,614, +679,615,680, +616,680,615, +680,616,681, +617,681,616, +681,617,682, +618,682,617, +682,618,683, +619,683,618, +683,619,684, +620,684,619, +684,620,685, +621,685,620, +685,621,686, +622,686,621, +686,622,687, +623,687,622, +687,623,688, +624,688,623, +688,624,689, +625,689,624, +689,625,690, +626,690,625, +690,626,691, +627,691,626, +691,627,692, +628,692,627, +692,628,693, +629,693,628, +693,629,694, +630,694,629, +694,630,695, +631,695,630, +695,631,696, +632,696,631, +696,632,697, +633,697,632, +697,633,698, +634,698,633, +698,634,699, +635,699,634, +699,635,700, +636,700,635, +700,636,701, +637,701,636, +701,637,702, +638,702,637, +702,638,703, +639,703,638, +704,640,705, +641,705,640, +705,641,706, +642,706,641, +706,642,707, +643,707,642, +707,643,708, +644,708,643, +708,644,709, +645,709,644, +709,645,710, +646,710,645, +710,646,711, +647,711,646, +711,647,712, +648,712,647, +712,648,713, +649,713,648, +713,649,714, +650,714,649, +714,650,715, +651,715,650, +715,651,716, +652,716,651, +716,652,717, +653,717,652, +717,653,718, +654,718,653, +718,654,719, +655,719,654, +719,655,720, +656,720,655, +720,656,721, +657,721,656, +721,657,722, +658,722,657, +722,658,723, +659,723,658, +723,659,724, +660,724,659, +724,660,725, +661,725,660, +725,661,726, +662,726,661, +726,662,727, +663,727,662, +727,663,728, +664,728,663, +728,664,729, +665,729,664, +729,665,730, +666,730,665, +730,666,731, +667,731,666, +731,667,732, +668,732,667, +732,668,733, +669,733,668, +733,669,734, +670,734,669, +734,670,735, +671,735,670, +735,671,736, +672,736,671, +736,672,737, +673,737,672, +737,673,738, +674,738,673, +738,674,739, +675,739,674, +739,675,740, +676,740,675, +740,676,741, +677,741,676, +741,677,742, +678,742,677, +742,678,743, +679,743,678, +743,679,744, +680,744,679, +744,680,745, +681,745,680, +745,681,746, +682,746,681, +746,682,747, +683,747,682, +747,683,748, +684,748,683, +748,684,749, +685,749,684, +749,685,750, +686,750,685, +750,686,751, +687,751,686, +751,687,752, +688,752,687, +752,688,753, +689,753,688, +753,689,754, +690,754,689, +754,690,755, +691,755,690, +755,691,756, +692,756,691, +756,692,757, +693,757,692, +757,693,758, +694,758,693, +758,694,759, +695,759,694, +759,695,760, +696,760,695, +760,696,761, +697,761,696, +761,697,762, +698,762,697, +762,698,763, +699,763,698, +763,699,764, +700,764,699, +764,700,765, +701,765,700, +765,701,766, +702,766,701, +766,702,767, +703,767,702, +768,704,769, +705,769,704, +769,705,770, +706,770,705, +770,706,771, +707,771,706, +771,707,772, +708,772,707, +772,708,773, +709,773,708, +773,709,774, +710,774,709, +774,710,775, +711,775,710, +775,711,776, +712,776,711, +776,712,777, +713,777,712, +777,713,778, +714,778,713, +778,714,779, +715,779,714, +779,715,780, +716,780,715, +780,716,781, +717,781,716, +781,717,782, +718,782,717, +782,718,783, +719,783,718, +783,719,784, +720,784,719, +784,720,785, +721,785,720, +785,721,786, +722,786,721, +786,722,787, +723,787,722, +787,723,788, +724,788,723, +788,724,789, +725,789,724, +789,725,790, +726,790,725, +790,726,791, +727,791,726, +791,727,792, +728,792,727, +792,728,793, +729,793,728, +793,729,794, +730,794,729, +794,730,795, +731,795,730, +795,731,796, +732,796,731, +796,732,797, +733,797,732, +797,733,798, +734,798,733, +798,734,799, +735,799,734, +799,735,800, +736,800,735, +800,736,801, +737,801,736, +801,737,802, +738,802,737, +802,738,803, +739,803,738, +803,739,804, +740,804,739, +804,740,805, +741,805,740, +805,741,806, +742,806,741, +806,742,807, +743,807,742, +807,743,808, +744,808,743, +808,744,809, +745,809,744, +809,745,810, +746,810,745, +810,746,811, +747,811,746, +811,747,812, +748,812,747, +812,748,813, +749,813,748, +813,749,814, +750,814,749, +814,750,815, +751,815,750, +815,751,816, +752,816,751, +816,752,817, +753,817,752, +817,753,818, +754,818,753, +818,754,819, +755,819,754, +819,755,820, +756,820,755, +820,756,821, +757,821,756, +821,757,822, +758,822,757, +822,758,823, +759,823,758, +823,759,824, +760,824,759, +824,760,825, +761,825,760, +825,761,826, +762,826,761, +826,762,827, +763,827,762, +827,763,828, +764,828,763, +828,764,829, +765,829,764, +829,765,830, +766,830,765, +830,766,831, +767,831,766, +832,768,833, +769,833,768, +833,769,834, +770,834,769, +834,770,835, +771,835,770, +835,771,836, +772,836,771, +836,772,837, +773,837,772, +837,773,838, +774,838,773, +838,774,839, +775,839,774, +839,775,840, +776,840,775, +840,776,841, +777,841,776, +841,777,842, +778,842,777, +842,778,843, +779,843,778, +843,779,844, +780,844,779, +844,780,845, +781,845,780, +845,781,846, +782,846,781, +846,782,847, +783,847,782, +847,783,848, +784,848,783, +848,784,849, +785,849,784, +849,785,850, +786,850,785, +850,786,851, +787,851,786, +851,787,852, +788,852,787, +852,788,853, +789,853,788, +853,789,854, +790,854,789, +854,790,855, +791,855,790, +855,791,856, +792,856,791, +856,792,857, +793,857,792, +857,793,858, +794,858,793, +858,794,859, +795,859,794, +859,795,860, +796,860,795, +860,796,861, +797,861,796, +861,797,862, +798,862,797, +862,798,863, +799,863,798, +863,799,864, +800,864,799, +864,800,865, +801,865,800, +865,801,866, +802,866,801, +866,802,867, +803,867,802, +867,803,868, +804,868,803, +868,804,869, +805,869,804, +869,805,870, +806,870,805, +870,806,871, +807,871,806, +871,807,872, +808,872,807, +872,808,873, +809,873,808, +873,809,874, +810,874,809, +874,810,875, +811,875,810, +875,811,876, +812,876,811, +876,812,877, +813,877,812, +877,813,878, +814,878,813, +878,814,879, +815,879,814, +879,815,880, +816,880,815, +880,816,881, +817,881,816, +881,817,882, +818,882,817, +882,818,883, +819,883,818, +883,819,884, +820,884,819, +884,820,885, +821,885,820, +885,821,886, +822,886,821, +886,822,887, +823,887,822, +887,823,888, +824,888,823, +888,824,889, +825,889,824, +889,825,890, +826,890,825, +890,826,891, +827,891,826, +891,827,892, +828,892,827, +892,828,893, +829,893,828, +893,829,894, +830,894,829, +894,830,895, +831,895,830, +896,832,897, +833,897,832, +897,833,898, +834,898,833, +898,834,899, +835,899,834, +899,835,900, +836,900,835, +900,836,901, +837,901,836, +901,837,902, +838,902,837, +902,838,903, +839,903,838, +903,839,904, +840,904,839, +904,840,905, +841,905,840, +905,841,906, +842,906,841, +906,842,907, +843,907,842, +907,843,908, +844,908,843, +908,844,909, +845,909,844, +909,845,910, +846,910,845, +910,846,911, +847,911,846, +911,847,912, +848,912,847, +912,848,913, +849,913,848, +913,849,914, +850,914,849, +914,850,915, +851,915,850, +915,851,916, +852,916,851, +916,852,917, +853,917,852, +917,853,918, +854,918,853, +918,854,919, +855,919,854, +919,855,920, +856,920,855, +920,856,921, +857,921,856, +921,857,922, +858,922,857, +922,858,923, +859,923,858, +923,859,924, +860,924,859, +924,860,925, +861,925,860, +925,861,926, +862,926,861, +926,862,927, +863,927,862, +927,863,928, +864,928,863, +928,864,929, +865,929,864, +929,865,930, +866,930,865, +930,866,931, +867,931,866, +931,867,932, +868,932,867, +932,868,933, +869,933,868, +933,869,934, +870,934,869, +934,870,935, +871,935,870, +935,871,936, +872,936,871, +936,872,937, +873,937,872, +937,873,938, +874,938,873, +938,874,939, +875,939,874, +939,875,940, +876,940,875, +940,876,941, +877,941,876, +941,877,942, +878,942,877, +942,878,943, +879,943,878, +943,879,944, +880,944,879, +944,880,945, +881,945,880, +945,881,946, +882,946,881, +946,882,947, +883,947,882, +947,883,948, +884,948,883, +948,884,949, +885,949,884, +949,885,950, +886,950,885, +950,886,951, +887,951,886, +951,887,952, +888,952,887, +952,888,953, +889,953,888, +953,889,954, +890,954,889, +954,890,955, +891,955,890, +955,891,956, +892,956,891, +956,892,957, +893,957,892, +957,893,958, +894,958,893, +958,894,959, +895,959,894, +960,896,961, +897,961,896, +961,897,962, +898,962,897, +962,898,963, +899,963,898, +963,899,964, +900,964,899, +964,900,965, +901,965,900, +965,901,966, +902,966,901, +966,902,967, +903,967,902, +967,903,968, +904,968,903, +968,904,969, +905,969,904, +969,905,970, +906,970,905, +970,906,971, +907,971,906, +971,907,972, +908,972,907, +972,908,973, +909,973,908, +973,909,974, +910,974,909, +974,910,975, +911,975,910, +975,911,976, +912,976,911, +976,912,977, +913,977,912, +977,913,978, +914,978,913, +978,914,979, +915,979,914, +979,915,980, +916,980,915, +980,916,981, +917,981,916, +981,917,982, +918,982,917, +982,918,983, +919,983,918, +983,919,984, +920,984,919, +984,920,985, +921,985,920, +985,921,986, +922,986,921, +986,922,987, +923,987,922, +987,923,988, +924,988,923, +988,924,989, +925,989,924, +989,925,990, +926,990,925, +990,926,991, +927,991,926, +991,927,992, +928,992,927, +992,928,993, +929,993,928, +993,929,994, +930,994,929, +994,930,995, +931,995,930, +995,931,996, +932,996,931, +996,932,997, +933,997,932, +997,933,998, +934,998,933, +998,934,999, +935,999,934, +999,935,1000, +936,1000,935, +1000,936,1001, +937,1001,936, +1001,937,1002, +938,1002,937, +1002,938,1003, +939,1003,938, +1003,939,1004, +940,1004,939, +1004,940,1005, +941,1005,940, +1005,941,1006, +942,1006,941, +1006,942,1007, +943,1007,942, +1007,943,1008, +944,1008,943, +1008,944,1009, +945,1009,944, +1009,945,1010, +946,1010,945, +1010,946,1011, +947,1011,946, +1011,947,1012, +948,1012,947, +1012,948,1013, +949,1013,948, +1013,949,1014, +950,1014,949, +1014,950,1015, +951,1015,950, +1015,951,1016, +952,1016,951, +1016,952,1017, +953,1017,952, +1017,953,1018, +954,1018,953, +1018,954,1019, +955,1019,954, +1019,955,1020, +956,1020,955, +1020,956,1021, +957,1021,956, +1021,957,1022, +958,1022,957, +1022,958,1023, +959,1023,958, +1024,960,1025, +961,1025,960, +1025,961,1026, +962,1026,961, +1026,962,1027, +963,1027,962, +1027,963,1028, +964,1028,963, +1028,964,1029, +965,1029,964, +1029,965,1030, +966,1030,965, +1030,966,1031, +967,1031,966, +1031,967,1032, +968,1032,967, +1032,968,1033, +969,1033,968, +1033,969,1034, +970,1034,969, +1034,970,1035, +971,1035,970, +1035,971,1036, +972,1036,971, +1036,972,1037, +973,1037,972, +1037,973,1038, +974,1038,973, +1038,974,1039, +975,1039,974, +1039,975,1040, +976,1040,975, +1040,976,1041, +977,1041,976, +1041,977,1042, +978,1042,977, +1042,978,1043, +979,1043,978, +1043,979,1044, +980,1044,979, +1044,980,1045, +981,1045,980, +1045,981,1046, +982,1046,981, +1046,982,1047, +983,1047,982, +1047,983,1048, +984,1048,983, +1048,984,1049, +985,1049,984, +1049,985,1050, +986,1050,985, +1050,986,1051, +987,1051,986, +1051,987,1052, +988,1052,987, +1052,988,1053, +989,1053,988, +1053,989,1054, +990,1054,989, +1054,990,1055, +991,1055,990, +1055,991,1056, +992,1056,991, +1056,992,1057, +993,1057,992, +1057,993,1058, +994,1058,993, +1058,994,1059, +995,1059,994, +1059,995,1060, +996,1060,995, +1060,996,1061, +997,1061,996, +1061,997,1062, +998,1062,997, +1062,998,1063, +999,1063,998, +1063,999,1064, +1000,1064,999, +1064,1000,1065, +1001,1065,1000, +1065,1001,1066, +1002,1066,1001, +1066,1002,1067, +1003,1067,1002, +1067,1003,1068, +1004,1068,1003, +1068,1004,1069, +1005,1069,1004, +1069,1005,1070, +1006,1070,1005, +1070,1006,1071, +1007,1071,1006, +1071,1007,1072, +1008,1072,1007, +1072,1008,1073, +1009,1073,1008, +1073,1009,1074, +1010,1074,1009, +1074,1010,1075, +1011,1075,1010, +1075,1011,1076, +1012,1076,1011, +1076,1012,1077, +1013,1077,1012, +1077,1013,1078, +1014,1078,1013, +1078,1014,1079, +1015,1079,1014, +1079,1015,1080, +1016,1080,1015, +1080,1016,1081, +1017,1081,1016, +1081,1017,1082, +1018,1082,1017, +1082,1018,1083, +1019,1083,1018, +1083,1019,1084, +1020,1084,1019, +1084,1020,1085, +1021,1085,1020, +1085,1021,1086, +1022,1086,1021, +1086,1022,1087, +1023,1087,1022, +1088,1024,1089, +1025,1089,1024, +1089,1025,1090, +1026,1090,1025, +1090,1026,1091, +1027,1091,1026, +1091,1027,1092, +1028,1092,1027, +1092,1028,1093, +1029,1093,1028, +1093,1029,1094, +1030,1094,1029, +1094,1030,1095, +1031,1095,1030, +1095,1031,1096, +1032,1096,1031, +1096,1032,1097, +1033,1097,1032, +1097,1033,1098, +1034,1098,1033, +1098,1034,1099, +1035,1099,1034, +1099,1035,1100, +1036,1100,1035, +1100,1036,1101, +1037,1101,1036, +1101,1037,1102, +1038,1102,1037, +1102,1038,1103, +1039,1103,1038, +1103,1039,1104, +1040,1104,1039, +1104,1040,1105, +1041,1105,1040, +1105,1041,1106, +1042,1106,1041, +1106,1042,1107, +1043,1107,1042, +1107,1043,1108, +1044,1108,1043, +1108,1044,1109, +1045,1109,1044, +1109,1045,1110, +1046,1110,1045, +1110,1046,1111, +1047,1111,1046, +1111,1047,1112, +1048,1112,1047, +1112,1048,1113, +1049,1113,1048, +1113,1049,1114, +1050,1114,1049, +1114,1050,1115, +1051,1115,1050, +1115,1051,1116, +1052,1116,1051, +1116,1052,1117, +1053,1117,1052, +1117,1053,1118, +1054,1118,1053, +1118,1054,1119, +1055,1119,1054, +1119,1055,1120, +1056,1120,1055, +1120,1056,1121, +1057,1121,1056, +1121,1057,1122, +1058,1122,1057, +1122,1058,1123, +1059,1123,1058, +1123,1059,1124, +1060,1124,1059, +1124,1060,1125, +1061,1125,1060, +1125,1061,1126, +1062,1126,1061, +1126,1062,1127, +1063,1127,1062, +1127,1063,1128, +1064,1128,1063, +1128,1064,1129, +1065,1129,1064, +1129,1065,1130, +1066,1130,1065, +1130,1066,1131, +1067,1131,1066, +1131,1067,1132, +1068,1132,1067, +1132,1068,1133, +1069,1133,1068, +1133,1069,1134, +1070,1134,1069, +1134,1070,1135, +1071,1135,1070, +1135,1071,1136, +1072,1136,1071, +1136,1072,1137, +1073,1137,1072, +1137,1073,1138, +1074,1138,1073, +1138,1074,1139, +1075,1139,1074, +1139,1075,1140, +1076,1140,1075, +1140,1076,1141, +1077,1141,1076, +1141,1077,1142, +1078,1142,1077, +1142,1078,1143, +1079,1143,1078, +1143,1079,1144, +1080,1144,1079, +1144,1080,1145, +1081,1145,1080, +1145,1081,1146, +1082,1146,1081, +1146,1082,1147, +1083,1147,1082, +1147,1083,1148, +1084,1148,1083, +1148,1084,1149, +1085,1149,1084, +1149,1085,1150, +1086,1150,1085, +1150,1086,1151, +1087,1151,1086, +1152,1088,1153, +1089,1153,1088, +1153,1089,1154, +1090,1154,1089, +1154,1090,1155, +1091,1155,1090, +1155,1091,1156, +1092,1156,1091, +1156,1092,1157, +1093,1157,1092, +1157,1093,1158, +1094,1158,1093, +1158,1094,1159, +1095,1159,1094, +1159,1095,1160, +1096,1160,1095, +1160,1096,1161, +1097,1161,1096, +1161,1097,1162, +1098,1162,1097, +1162,1098,1163, +1099,1163,1098, +1163,1099,1164, +1100,1164,1099, +1164,1100,1165, +1101,1165,1100, +1165,1101,1166, +1102,1166,1101, +1166,1102,1167, +1103,1167,1102, +1167,1103,1168, +1104,1168,1103, +1168,1104,1169, +1105,1169,1104, +1169,1105,1170, +1106,1170,1105, +1170,1106,1171, +1107,1171,1106, +1171,1107,1172, +1108,1172,1107, +1172,1108,1173, +1109,1173,1108, +1173,1109,1174, +1110,1174,1109, +1174,1110,1175, +1111,1175,1110, +1175,1111,1176, +1112,1176,1111, +1176,1112,1177, +1113,1177,1112, +1177,1113,1178, +1114,1178,1113, +1178,1114,1179, +1115,1179,1114, +1179,1115,1180, +1116,1180,1115, +1180,1116,1181, +1117,1181,1116, +1181,1117,1182, +1118,1182,1117, +1182,1118,1183, +1119,1183,1118, +1183,1119,1184, +1120,1184,1119, +1184,1120,1185, +1121,1185,1120, +1185,1121,1186, +1122,1186,1121, +1186,1122,1187, +1123,1187,1122, +1187,1123,1188, +1124,1188,1123, +1188,1124,1189, +1125,1189,1124, +1189,1125,1190, +1126,1190,1125, +1190,1126,1191, +1127,1191,1126, +1191,1127,1192, +1128,1192,1127, +1192,1128,1193, +1129,1193,1128, +1193,1129,1194, +1130,1194,1129, +1194,1130,1195, +1131,1195,1130, +1195,1131,1196, +1132,1196,1131, +1196,1132,1197, +1133,1197,1132, +1197,1133,1198, +1134,1198,1133, +1198,1134,1199, +1135,1199,1134, +1199,1135,1200, +1136,1200,1135, +1200,1136,1201, +1137,1201,1136, +1201,1137,1202, +1138,1202,1137, +1202,1138,1203, +1139,1203,1138, +1203,1139,1204, +1140,1204,1139, +1204,1140,1205, +1141,1205,1140, +1205,1141,1206, +1142,1206,1141, +1206,1142,1207, +1143,1207,1142, +1207,1143,1208, +1144,1208,1143, +1208,1144,1209, +1145,1209,1144, +1209,1145,1210, +1146,1210,1145, +1210,1146,1211, +1147,1211,1146, +1211,1147,1212, +1148,1212,1147, +1212,1148,1213, +1149,1213,1148, +1213,1149,1214, +1150,1214,1149, +1214,1150,1215, +1151,1215,1150, +1216,1152,1217, +1153,1217,1152, +1217,1153,1218, +1154,1218,1153, +1218,1154,1219, +1155,1219,1154, +1219,1155,1220, +1156,1220,1155, +1220,1156,1221, +1157,1221,1156, +1221,1157,1222, +1158,1222,1157, +1222,1158,1223, +1159,1223,1158, +1223,1159,1224, +1160,1224,1159, +1224,1160,1225, +1161,1225,1160, +1225,1161,1226, +1162,1226,1161, +1226,1162,1227, +1163,1227,1162, +1227,1163,1228, +1164,1228,1163, +1228,1164,1229, +1165,1229,1164, +1229,1165,1230, +1166,1230,1165, +1230,1166,1231, +1167,1231,1166, +1231,1167,1232, +1168,1232,1167, +1232,1168,1233, +1169,1233,1168, +1233,1169,1234, +1170,1234,1169, +1234,1170,1235, +1171,1235,1170, +1235,1171,1236, +1172,1236,1171, +1236,1172,1237, +1173,1237,1172, +1237,1173,1238, +1174,1238,1173, +1238,1174,1239, +1175,1239,1174, +1239,1175,1240, +1176,1240,1175, +1240,1176,1241, +1177,1241,1176, +1241,1177,1242, +1178,1242,1177, +1242,1178,1243, +1179,1243,1178, +1243,1179,1244, +1180,1244,1179, +1244,1180,1245, +1181,1245,1180, +1245,1181,1246, +1182,1246,1181, +1246,1182,1247, +1183,1247,1182, +1247,1183,1248, +1184,1248,1183, +1248,1184,1249, +1185,1249,1184, +1249,1185,1250, +1186,1250,1185, +1250,1186,1251, +1187,1251,1186, +1251,1187,1252, +1188,1252,1187, +1252,1188,1253, +1189,1253,1188, +1253,1189,1254, +1190,1254,1189, +1254,1190,1255, +1191,1255,1190, +1255,1191,1256, +1192,1256,1191, +1256,1192,1257, +1193,1257,1192, +1257,1193,1258, +1194,1258,1193, +1258,1194,1259, +1195,1259,1194, +1259,1195,1260, +1196,1260,1195, +1260,1196,1261, +1197,1261,1196, +1261,1197,1262, +1198,1262,1197, +1262,1198,1263, +1199,1263,1198, +1263,1199,1264, +1200,1264,1199, +1264,1200,1265, +1201,1265,1200, +1265,1201,1266, +1202,1266,1201, +1266,1202,1267, +1203,1267,1202, +1267,1203,1268, +1204,1268,1203, +1268,1204,1269, +1205,1269,1204, +1269,1205,1270, +1206,1270,1205, +1270,1206,1271, +1207,1271,1206, +1271,1207,1272, +1208,1272,1207, +1272,1208,1273, +1209,1273,1208, +1273,1209,1274, +1210,1274,1209, +1274,1210,1275, +1211,1275,1210, +1275,1211,1276, +1212,1276,1211, +1276,1212,1277, +1213,1277,1212, +1277,1213,1278, +1214,1278,1213, +1278,1214,1279, +1215,1279,1214, +1280,1216,1281, +1217,1281,1216, +1281,1217,1282, +1218,1282,1217, +1282,1218,1283, +1219,1283,1218, +1283,1219,1284, +1220,1284,1219, +1284,1220,1285, +1221,1285,1220, +1285,1221,1286, +1222,1286,1221, +1286,1222,1287, +1223,1287,1222, +1287,1223,1288, +1224,1288,1223, +1288,1224,1289, +1225,1289,1224, +1289,1225,1290, +1226,1290,1225, +1290,1226,1291, +1227,1291,1226, +1291,1227,1292, +1228,1292,1227, +1292,1228,1293, +1229,1293,1228, +1293,1229,1294, +1230,1294,1229, +1294,1230,1295, +1231,1295,1230, +1295,1231,1296, +1232,1296,1231, +1296,1232,1297, +1233,1297,1232, +1297,1233,1298, +1234,1298,1233, +1298,1234,1299, +1235,1299,1234, +1299,1235,1300, +1236,1300,1235, +1300,1236,1301, +1237,1301,1236, +1301,1237,1302, +1238,1302,1237, +1302,1238,1303, +1239,1303,1238, +1303,1239,1304, +1240,1304,1239, +1304,1240,1305, +1241,1305,1240, +1305,1241,1306, +1242,1306,1241, +1306,1242,1307, +1243,1307,1242, +1307,1243,1308, +1244,1308,1243, +1308,1244,1309, +1245,1309,1244, +1309,1245,1310, +1246,1310,1245, +1310,1246,1311, +1247,1311,1246, +1311,1247,1312, +1248,1312,1247, +1312,1248,1313, +1249,1313,1248, +1313,1249,1314, +1250,1314,1249, +1314,1250,1315, +1251,1315,1250, +1315,1251,1316, +1252,1316,1251, +1316,1252,1317, +1253,1317,1252, +1317,1253,1318, +1254,1318,1253, +1318,1254,1319, +1255,1319,1254, +1319,1255,1320, +1256,1320,1255, +1320,1256,1321, +1257,1321,1256, +1321,1257,1322, +1258,1322,1257, +1322,1258,1323, +1259,1323,1258, +1323,1259,1324, +1260,1324,1259, +1324,1260,1325, +1261,1325,1260, +1325,1261,1326, +1262,1326,1261, +1326,1262,1327, +1263,1327,1262, +1327,1263,1328, +1264,1328,1263, +1328,1264,1329, +1265,1329,1264, +1329,1265,1330, +1266,1330,1265, +1330,1266,1331, +1267,1331,1266, +1331,1267,1332, +1268,1332,1267, +1332,1268,1333, +1269,1333,1268, +1333,1269,1334, +1270,1334,1269, +1334,1270,1335, +1271,1335,1270, +1335,1271,1336, +1272,1336,1271, +1336,1272,1337, +1273,1337,1272, +1337,1273,1338, +1274,1338,1273, +1338,1274,1339, +1275,1339,1274, +1339,1275,1340, +1276,1340,1275, +1340,1276,1341, +1277,1341,1276, +1341,1277,1342, +1278,1342,1277, +1342,1278,1343, +1279,1343,1278, +1344,1280,1345, +1281,1345,1280, +1345,1281,1346, +1282,1346,1281, +1346,1282,1347, +1283,1347,1282, +1347,1283,1348, +1284,1348,1283, +1348,1284,1349, +1285,1349,1284, +1349,1285,1350, +1286,1350,1285, +1350,1286,1351, +1287,1351,1286, +1351,1287,1352, +1288,1352,1287, +1352,1288,1353, +1289,1353,1288, +1353,1289,1354, +1290,1354,1289, +1354,1290,1355, +1291,1355,1290, +1355,1291,1356, +1292,1356,1291, +1356,1292,1357, +1293,1357,1292, +1357,1293,1358, +1294,1358,1293, +1358,1294,1359, +1295,1359,1294, +1359,1295,1360, +1296,1360,1295, +1360,1296,1361, +1297,1361,1296, +1361,1297,1362, +1298,1362,1297, +1362,1298,1363, +1299,1363,1298, +1363,1299,1364, +1300,1364,1299, +1364,1300,1365, +1301,1365,1300, +1365,1301,1366, +1302,1366,1301, +1366,1302,1367, +1303,1367,1302, +1367,1303,1368, +1304,1368,1303, +1368,1304,1369, +1305,1369,1304, +1369,1305,1370, +1306,1370,1305, +1370,1306,1371, +1307,1371,1306, +1371,1307,1372, +1308,1372,1307, +1372,1308,1373, +1309,1373,1308, +1373,1309,1374, +1310,1374,1309, +1374,1310,1375, +1311,1375,1310, +1375,1311,1376, +1312,1376,1311, +1376,1312,1377, +1313,1377,1312, +1377,1313,1378, +1314,1378,1313, +1378,1314,1379, +1315,1379,1314, +1379,1315,1380, +1316,1380,1315, +1380,1316,1381, +1317,1381,1316, +1381,1317,1382, +1318,1382,1317, +1382,1318,1383, +1319,1383,1318, +1383,1319,1384, +1320,1384,1319, +1384,1320,1385, +1321,1385,1320, +1385,1321,1386, +1322,1386,1321, +1386,1322,1387, +1323,1387,1322, +1387,1323,1388, +1324,1388,1323, +1388,1324,1389, +1325,1389,1324, +1389,1325,1390, +1326,1390,1325, +1390,1326,1391, +1327,1391,1326, +1391,1327,1392, +1328,1392,1327, +1392,1328,1393, +1329,1393,1328, +1393,1329,1394, +1330,1394,1329, +1394,1330,1395, +1331,1395,1330, +1395,1331,1396, +1332,1396,1331, +1396,1332,1397, +1333,1397,1332, +1397,1333,1398, +1334,1398,1333, +1398,1334,1399, +1335,1399,1334, +1399,1335,1400, +1336,1400,1335, +1400,1336,1401, +1337,1401,1336, +1401,1337,1402, +1338,1402,1337, +1402,1338,1403, +1339,1403,1338, +1403,1339,1404, +1340,1404,1339, +1404,1340,1405, +1341,1405,1340, +1405,1341,1406, +1342,1406,1341, +1406,1342,1407, +1343,1407,1342, +1408,1344,1409, +1345,1409,1344, +1409,1345,1410, +1346,1410,1345, +1410,1346,1411, +1347,1411,1346, +1411,1347,1412, +1348,1412,1347, +1412,1348,1413, +1349,1413,1348, +1413,1349,1414, +1350,1414,1349, +1414,1350,1415, +1351,1415,1350, +1415,1351,1416, +1352,1416,1351, +1416,1352,1417, +1353,1417,1352, +1417,1353,1418, +1354,1418,1353, +1418,1354,1419, +1355,1419,1354, +1419,1355,1420, +1356,1420,1355, +1420,1356,1421, +1357,1421,1356, +1421,1357,1422, +1358,1422,1357, +1422,1358,1423, +1359,1423,1358, +1423,1359,1424, +1360,1424,1359, +1424,1360,1425, +1361,1425,1360, +1425,1361,1426, +1362,1426,1361, +1426,1362,1427, +1363,1427,1362, +1427,1363,1428, +1364,1428,1363, +1428,1364,1429, +1365,1429,1364, +1429,1365,1430, +1366,1430,1365, +1430,1366,1431, +1367,1431,1366, +1431,1367,1432, +1368,1432,1367, +1432,1368,1433, +1369,1433,1368, +1433,1369,1434, +1370,1434,1369, +1434,1370,1435, +1371,1435,1370, +1435,1371,1436, +1372,1436,1371, +1436,1372,1437, +1373,1437,1372, +1437,1373,1438, +1374,1438,1373, +1438,1374,1439, +1375,1439,1374, +1439,1375,1440, +1376,1440,1375, +1440,1376,1441, +1377,1441,1376, +1441,1377,1442, +1378,1442,1377, +1442,1378,1443, +1379,1443,1378, +1443,1379,1444, +1380,1444,1379, +1444,1380,1445, +1381,1445,1380, +1445,1381,1446, +1382,1446,1381, +1446,1382,1447, +1383,1447,1382, +1447,1383,1448, +1384,1448,1383, +1448,1384,1449, +1385,1449,1384, +1449,1385,1450, +1386,1450,1385, +1450,1386,1451, +1387,1451,1386, +1451,1387,1452, +1388,1452,1387, +1452,1388,1453, +1389,1453,1388, +1453,1389,1454, +1390,1454,1389, +1454,1390,1455, +1391,1455,1390, +1455,1391,1456, +1392,1456,1391, +1456,1392,1457, +1393,1457,1392, +1457,1393,1458, +1394,1458,1393, +1458,1394,1459, +1395,1459,1394, +1459,1395,1460, +1396,1460,1395, +1460,1396,1461, +1397,1461,1396, +1461,1397,1462, +1398,1462,1397, +1462,1398,1463, +1399,1463,1398, +1463,1399,1464, +1400,1464,1399, +1464,1400,1465, +1401,1465,1400, +1465,1401,1466, +1402,1466,1401, +1466,1402,1467, +1403,1467,1402, +1467,1403,1468, +1404,1468,1403, +1468,1404,1469, +1405,1469,1404, +1469,1405,1470, +1406,1470,1405, +1470,1406,1471, +1407,1471,1406, +1472,1408,1473, +1409,1473,1408, +1473,1409,1474, +1410,1474,1409, +1474,1410,1475, +1411,1475,1410, +1475,1411,1476, +1412,1476,1411, +1476,1412,1477, +1413,1477,1412, +1477,1413,1478, +1414,1478,1413, +1478,1414,1479, +1415,1479,1414, +1479,1415,1480, +1416,1480,1415, +1480,1416,1481, +1417,1481,1416, +1481,1417,1482, +1418,1482,1417, +1482,1418,1483, +1419,1483,1418, +1483,1419,1484, +1420,1484,1419, +1484,1420,1485, +1421,1485,1420, +1485,1421,1486, +1422,1486,1421, +1486,1422,1487, +1423,1487,1422, +1487,1423,1488, +1424,1488,1423, +1488,1424,1489, +1425,1489,1424, +1489,1425,1490, +1426,1490,1425, +1490,1426,1491, +1427,1491,1426, +1491,1427,1492, +1428,1492,1427, +1492,1428,1493, +1429,1493,1428, +1493,1429,1494, +1430,1494,1429, +1494,1430,1495, +1431,1495,1430, +1495,1431,1496, +1432,1496,1431, +1496,1432,1497, +1433,1497,1432, +1497,1433,1498, +1434,1498,1433, +1498,1434,1499, +1435,1499,1434, +1499,1435,1500, +1436,1500,1435, +1500,1436,1501, +1437,1501,1436, +1501,1437,1502, +1438,1502,1437, +1502,1438,1503, +1439,1503,1438, +1503,1439,1504, +1440,1504,1439, +1504,1440,1505, +1441,1505,1440, +1505,1441,1506, +1442,1506,1441, +1506,1442,1507, +1443,1507,1442, +1507,1443,1508, +1444,1508,1443, +1508,1444,1509, +1445,1509,1444, +1509,1445,1510, +1446,1510,1445, +1510,1446,1511, +1447,1511,1446, +1511,1447,1512, +1448,1512,1447, +1512,1448,1513, +1449,1513,1448, +1513,1449,1514, +1450,1514,1449, +1514,1450,1515, +1451,1515,1450, +1515,1451,1516, +1452,1516,1451, +1516,1452,1517, +1453,1517,1452, +1517,1453,1518, +1454,1518,1453, +1518,1454,1519, +1455,1519,1454, +1519,1455,1520, +1456,1520,1455, +1520,1456,1521, +1457,1521,1456, +1521,1457,1522, +1458,1522,1457, +1522,1458,1523, +1459,1523,1458, +1523,1459,1524, +1460,1524,1459, +1524,1460,1525, +1461,1525,1460, +1525,1461,1526, +1462,1526,1461, +1526,1462,1527, +1463,1527,1462, +1527,1463,1528, +1464,1528,1463, +1528,1464,1529, +1465,1529,1464, +1529,1465,1530, +1466,1530,1465, +1530,1466,1531, +1467,1531,1466, +1531,1467,1532, +1468,1532,1467, +1532,1468,1533, +1469,1533,1468, +1533,1469,1534, +1470,1534,1469, +1534,1470,1535, +1471,1535,1470, +1536,1472,1537, +1473,1537,1472, +1537,1473,1538, +1474,1538,1473, +1538,1474,1539, +1475,1539,1474, +1539,1475,1540, +1476,1540,1475, +1540,1476,1541, +1477,1541,1476, +1541,1477,1542, +1478,1542,1477, +1542,1478,1543, +1479,1543,1478, +1543,1479,1544, +1480,1544,1479, +1544,1480,1545, +1481,1545,1480, +1545,1481,1546, +1482,1546,1481, +1546,1482,1547, +1483,1547,1482, +1547,1483,1548, +1484,1548,1483, +1548,1484,1549, +1485,1549,1484, +1549,1485,1550, +1486,1550,1485, +1550,1486,1551, +1487,1551,1486, +1551,1487,1552, +1488,1552,1487, +1552,1488,1553, +1489,1553,1488, +1553,1489,1554, +1490,1554,1489, +1554,1490,1555, +1491,1555,1490, +1555,1491,1556, +1492,1556,1491, +1556,1492,1557, +1493,1557,1492, +1557,1493,1558, +1494,1558,1493, +1558,1494,1559, +1495,1559,1494, +1559,1495,1560, +1496,1560,1495, +1560,1496,1561, +1497,1561,1496, +1561,1497,1562, +1498,1562,1497, +1562,1498,1563, +1499,1563,1498, +1563,1499,1564, +1500,1564,1499, +1564,1500,1565, +1501,1565,1500, +1565,1501,1566, +1502,1566,1501, +1566,1502,1567, +1503,1567,1502, +1567,1503,1568, +1504,1568,1503, +1568,1504,1569, +1505,1569,1504, +1569,1505,1570, +1506,1570,1505, +1570,1506,1571, +1507,1571,1506, +1571,1507,1572, +1508,1572,1507, +1572,1508,1573, +1509,1573,1508, +1573,1509,1574, +1510,1574,1509, +1574,1510,1575, +1511,1575,1510, +1575,1511,1576, +1512,1576,1511, +1576,1512,1577, +1513,1577,1512, +1577,1513,1578, +1514,1578,1513, +1578,1514,1579, +1515,1579,1514, +1579,1515,1580, +1516,1580,1515, +1580,1516,1581, +1517,1581,1516, +1581,1517,1582, +1518,1582,1517, +1582,1518,1583, +1519,1583,1518, +1583,1519,1584, +1520,1584,1519, +1584,1520,1585, +1521,1585,1520, +1585,1521,1586, +1522,1586,1521, +1586,1522,1587, +1523,1587,1522, +1587,1523,1588, +1524,1588,1523, +1588,1524,1589, +1525,1589,1524, +1589,1525,1590, +1526,1590,1525, +1590,1526,1591, +1527,1591,1526, +1591,1527,1592, +1528,1592,1527, +1592,1528,1593, +1529,1593,1528, +1593,1529,1594, +1530,1594,1529, +1594,1530,1595, +1531,1595,1530, +1595,1531,1596, +1532,1596,1531, +1596,1532,1597, +1533,1597,1532, +1597,1533,1598, +1534,1598,1533, +1598,1534,1599, +1535,1599,1534, +1600,1536,1601, +1537,1601,1536, +1601,1537,1602, +1538,1602,1537, +1602,1538,1603, +1539,1603,1538, +1603,1539,1604, +1540,1604,1539, +1604,1540,1605, +1541,1605,1540, +1605,1541,1606, +1542,1606,1541, +1606,1542,1607, +1543,1607,1542, +1607,1543,1608, +1544,1608,1543, +1608,1544,1609, +1545,1609,1544, +1609,1545,1610, +1546,1610,1545, +1610,1546,1611, +1547,1611,1546, +1611,1547,1612, +1548,1612,1547, +1612,1548,1613, +1549,1613,1548, +1613,1549,1614, +1550,1614,1549, +1614,1550,1615, +1551,1615,1550, +1615,1551,1616, +1552,1616,1551, +1616,1552,1617, +1553,1617,1552, +1617,1553,1618, +1554,1618,1553, +1618,1554,1619, +1555,1619,1554, +1619,1555,1620, +1556,1620,1555, +1620,1556,1621, +1557,1621,1556, +1621,1557,1622, +1558,1622,1557, +1622,1558,1623, +1559,1623,1558, +1623,1559,1624, +1560,1624,1559, +1624,1560,1625, +1561,1625,1560, +1625,1561,1626, +1562,1626,1561, +1626,1562,1627, +1563,1627,1562, +1627,1563,1628, +1564,1628,1563, +1628,1564,1629, +1565,1629,1564, +1629,1565,1630, +1566,1630,1565, +1630,1566,1631, +1567,1631,1566, +1631,1567,1632, +1568,1632,1567, +1632,1568,1633, +1569,1633,1568, +1633,1569,1634, +1570,1634,1569, +1634,1570,1635, +1571,1635,1570, +1635,1571,1636, +1572,1636,1571, +1636,1572,1637, +1573,1637,1572, +1637,1573,1638, +1574,1638,1573, +1638,1574,1639, +1575,1639,1574, +1639,1575,1640, +1576,1640,1575, +1640,1576,1641, +1577,1641,1576, +1641,1577,1642, +1578,1642,1577, +1642,1578,1643, +1579,1643,1578, +1643,1579,1644, +1580,1644,1579, +1644,1580,1645, +1581,1645,1580, +1645,1581,1646, +1582,1646,1581, +1646,1582,1647, +1583,1647,1582, +1647,1583,1648, +1584,1648,1583, +1648,1584,1649, +1585,1649,1584, +1649,1585,1650, +1586,1650,1585, +1650,1586,1651, +1587,1651,1586, +1651,1587,1652, +1588,1652,1587, +1652,1588,1653, +1589,1653,1588, +1653,1589,1654, +1590,1654,1589, +1654,1590,1655, +1591,1655,1590, +1655,1591,1656, +1592,1656,1591, +1656,1592,1657, +1593,1657,1592, +1657,1593,1658, +1594,1658,1593, +1658,1594,1659, +1595,1659,1594, +1659,1595,1660, +1596,1660,1595, +1660,1596,1661, +1597,1661,1596, +1661,1597,1662, +1598,1662,1597, +1662,1598,1663, +1599,1663,1598, +1664,1600,1665, +1601,1665,1600, +1665,1601,1666, +1602,1666,1601, +1666,1602,1667, +1603,1667,1602, +1667,1603,1668, +1604,1668,1603, +1668,1604,1669, +1605,1669,1604, +1669,1605,1670, +1606,1670,1605, +1670,1606,1671, +1607,1671,1606, +1671,1607,1672, +1608,1672,1607, +1672,1608,1673, +1609,1673,1608, +1673,1609,1674, +1610,1674,1609, +1674,1610,1675, +1611,1675,1610, +1675,1611,1676, +1612,1676,1611, +1676,1612,1677, +1613,1677,1612, +1677,1613,1678, +1614,1678,1613, +1678,1614,1679, +1615,1679,1614, +1679,1615,1680, +1616,1680,1615, +1680,1616,1681, +1617,1681,1616, +1681,1617,1682, +1618,1682,1617, +1682,1618,1683, +1619,1683,1618, +1683,1619,1684, +1620,1684,1619, +1684,1620,1685, +1621,1685,1620, +1685,1621,1686, +1622,1686,1621, +1686,1622,1687, +1623,1687,1622, +1687,1623,1688, +1624,1688,1623, +1688,1624,1689, +1625,1689,1624, +1689,1625,1690, +1626,1690,1625, +1690,1626,1691, +1627,1691,1626, +1691,1627,1692, +1628,1692,1627, +1692,1628,1693, +1629,1693,1628, +1693,1629,1694, +1630,1694,1629, +1694,1630,1695, +1631,1695,1630, +1695,1631,1696, +1632,1696,1631, +1696,1632,1697, +1633,1697,1632, +1697,1633,1698, +1634,1698,1633, +1698,1634,1699, +1635,1699,1634, +1699,1635,1700, +1636,1700,1635, +1700,1636,1701, +1637,1701,1636, +1701,1637,1702, +1638,1702,1637, +1702,1638,1703, +1639,1703,1638, +1703,1639,1704, +1640,1704,1639, +1704,1640,1705, +1641,1705,1640, +1705,1641,1706, +1642,1706,1641, +1706,1642,1707, +1643,1707,1642, +1707,1643,1708, +1644,1708,1643, +1708,1644,1709, +1645,1709,1644, +1709,1645,1710, +1646,1710,1645, +1710,1646,1711, +1647,1711,1646, +1711,1647,1712, +1648,1712,1647, +1712,1648,1713, +1649,1713,1648, +1713,1649,1714, +1650,1714,1649, +1714,1650,1715, +1651,1715,1650, +1715,1651,1716, +1652,1716,1651, +1716,1652,1717, +1653,1717,1652, +1717,1653,1718, +1654,1718,1653, +1718,1654,1719, +1655,1719,1654, +1719,1655,1720, +1656,1720,1655, +1720,1656,1721, +1657,1721,1656, +1721,1657,1722, +1658,1722,1657, +1722,1658,1723, +1659,1723,1658, +1723,1659,1724, +1660,1724,1659, +1724,1660,1725, +1661,1725,1660, +1725,1661,1726, +1662,1726,1661, +1726,1662,1727, +1663,1727,1662, +1728,1664,1729, +1665,1729,1664, +1729,1665,1730, +1666,1730,1665, +1730,1666,1731, +1667,1731,1666, +1731,1667,1732, +1668,1732,1667, +1732,1668,1733, +1669,1733,1668, +1733,1669,1734, +1670,1734,1669, +1734,1670,1735, +1671,1735,1670, +1735,1671,1736, +1672,1736,1671, +1736,1672,1737, +1673,1737,1672, +1737,1673,1738, +1674,1738,1673, +1738,1674,1739, +1675,1739,1674, +1739,1675,1740, +1676,1740,1675, +1740,1676,1741, +1677,1741,1676, +1741,1677,1742, +1678,1742,1677, +1742,1678,1743, +1679,1743,1678, +1743,1679,1744, +1680,1744,1679, +1744,1680,1745, +1681,1745,1680, +1745,1681,1746, +1682,1746,1681, +1746,1682,1747, +1683,1747,1682, +1747,1683,1748, +1684,1748,1683, +1748,1684,1749, +1685,1749,1684, +1749,1685,1750, +1686,1750,1685, +1750,1686,1751, +1687,1751,1686, +1751,1687,1752, +1688,1752,1687, +1752,1688,1753, +1689,1753,1688, +1753,1689,1754, +1690,1754,1689, +1754,1690,1755, +1691,1755,1690, +1755,1691,1756, +1692,1756,1691, +1756,1692,1757, +1693,1757,1692, +1757,1693,1758, +1694,1758,1693, +1758,1694,1759, +1695,1759,1694, +1759,1695,1760, +1696,1760,1695, +1760,1696,1761, +1697,1761,1696, +1761,1697,1762, +1698,1762,1697, +1762,1698,1763, +1699,1763,1698, +1763,1699,1764, +1700,1764,1699, +1764,1700,1765, +1701,1765,1700, +1765,1701,1766, +1702,1766,1701, +1766,1702,1767, +1703,1767,1702, +1767,1703,1768, +1704,1768,1703, +1768,1704,1769, +1705,1769,1704, +1769,1705,1770, +1706,1770,1705, +1770,1706,1771, +1707,1771,1706, +1771,1707,1772, +1708,1772,1707, +1772,1708,1773, +1709,1773,1708, +1773,1709,1774, +1710,1774,1709, +1774,1710,1775, +1711,1775,1710, +1775,1711,1776, +1712,1776,1711, +1776,1712,1777, +1713,1777,1712, +1777,1713,1778, +1714,1778,1713, +1778,1714,1779, +1715,1779,1714, +1779,1715,1780, +1716,1780,1715, +1780,1716,1781, +1717,1781,1716, +1781,1717,1782, +1718,1782,1717, +1782,1718,1783, +1719,1783,1718, +1783,1719,1784, +1720,1784,1719, +1784,1720,1785, +1721,1785,1720, +1785,1721,1786, +1722,1786,1721, +1786,1722,1787, +1723,1787,1722, +1787,1723,1788, +1724,1788,1723, +1788,1724,1789, +1725,1789,1724, +1789,1725,1790, +1726,1790,1725, +1790,1726,1791, +1727,1791,1726, +1792,1728,1793, +1729,1793,1728, +1793,1729,1794, +1730,1794,1729, +1794,1730,1795, +1731,1795,1730, +1795,1731,1796, +1732,1796,1731, +1796,1732,1797, +1733,1797,1732, +1797,1733,1798, +1734,1798,1733, +1798,1734,1799, +1735,1799,1734, +1799,1735,1800, +1736,1800,1735, +1800,1736,1801, +1737,1801,1736, +1801,1737,1802, +1738,1802,1737, +1802,1738,1803, +1739,1803,1738, +1803,1739,1804, +1740,1804,1739, +1804,1740,1805, +1741,1805,1740, +1805,1741,1806, +1742,1806,1741, +1806,1742,1807, +1743,1807,1742, +1807,1743,1808, +1744,1808,1743, +1808,1744,1809, +1745,1809,1744, +1809,1745,1810, +1746,1810,1745, +1810,1746,1811, +1747,1811,1746, +1811,1747,1812, +1748,1812,1747, +1812,1748,1813, +1749,1813,1748, +1813,1749,1814, +1750,1814,1749, +1814,1750,1815, +1751,1815,1750, +1815,1751,1816, +1752,1816,1751, +1816,1752,1817, +1753,1817,1752, +1817,1753,1818, +1754,1818,1753, +1818,1754,1819, +1755,1819,1754, +1819,1755,1820, +1756,1820,1755, +1820,1756,1821, +1757,1821,1756, +1821,1757,1822, +1758,1822,1757, +1822,1758,1823, +1759,1823,1758, +1823,1759,1824, +1760,1824,1759, +1824,1760,1825, +1761,1825,1760, +1825,1761,1826, +1762,1826,1761, +1826,1762,1827, +1763,1827,1762, +1827,1763,1828, +1764,1828,1763, +1828,1764,1829, +1765,1829,1764, +1829,1765,1830, +1766,1830,1765, +1830,1766,1831, +1767,1831,1766, +1831,1767,1832, +1768,1832,1767, +1832,1768,1833, +1769,1833,1768, +1833,1769,1834, +1770,1834,1769, +1834,1770,1835, +1771,1835,1770, +1835,1771,1836, +1772,1836,1771, +1836,1772,1837, +1773,1837,1772, +1837,1773,1838, +1774,1838,1773, +1838,1774,1839, +1775,1839,1774, +1839,1775,1840, +1776,1840,1775, +1840,1776,1841, +1777,1841,1776, +1841,1777,1842, +1778,1842,1777, +1842,1778,1843, +1779,1843,1778, +1843,1779,1844, +1780,1844,1779, +1844,1780,1845, +1781,1845,1780, +1845,1781,1846, +1782,1846,1781, +1846,1782,1847, +1783,1847,1782, +1847,1783,1848, +1784,1848,1783, +1848,1784,1849, +1785,1849,1784, +1849,1785,1850, +1786,1850,1785, +1850,1786,1851, +1787,1851,1786, +1851,1787,1852, +1788,1852,1787, +1852,1788,1853, +1789,1853,1788, +1853,1789,1854, +1790,1854,1789, +1854,1790,1855, +1791,1855,1790, +1856,1792,1857, +1793,1857,1792, +1857,1793,1858, +1794,1858,1793, +1858,1794,1859, +1795,1859,1794, +1859,1795,1860, +1796,1860,1795, +1860,1796,1861, +1797,1861,1796, +1861,1797,1862, +1798,1862,1797, +1862,1798,1863, +1799,1863,1798, +1863,1799,1864, +1800,1864,1799, +1864,1800,1865, +1801,1865,1800, +1865,1801,1866, +1802,1866,1801, +1866,1802,1867, +1803,1867,1802, +1867,1803,1868, +1804,1868,1803, +1868,1804,1869, +1805,1869,1804, +1869,1805,1870, +1806,1870,1805, +1870,1806,1871, +1807,1871,1806, +1871,1807,1872, +1808,1872,1807, +1872,1808,1873, +1809,1873,1808, +1873,1809,1874, +1810,1874,1809, +1874,1810,1875, +1811,1875,1810, +1875,1811,1876, +1812,1876,1811, +1876,1812,1877, +1813,1877,1812, +1877,1813,1878, +1814,1878,1813, +1878,1814,1879, +1815,1879,1814, +1879,1815,1880, +1816,1880,1815, +1880,1816,1881, +1817,1881,1816, +1881,1817,1882, +1818,1882,1817, +1882,1818,1883, +1819,1883,1818, +1883,1819,1884, +1820,1884,1819, +1884,1820,1885, +1821,1885,1820, +1885,1821,1886, +1822,1886,1821, +1886,1822,1887, +1823,1887,1822, +1887,1823,1888, +1824,1888,1823, +1888,1824,1889, +1825,1889,1824, +1889,1825,1890, +1826,1890,1825, +1890,1826,1891, +1827,1891,1826, +1891,1827,1892, +1828,1892,1827, +1892,1828,1893, +1829,1893,1828, +1893,1829,1894, +1830,1894,1829, +1894,1830,1895, +1831,1895,1830, +1895,1831,1896, +1832,1896,1831, +1896,1832,1897, +1833,1897,1832, +1897,1833,1898, +1834,1898,1833, +1898,1834,1899, +1835,1899,1834, +1899,1835,1900, +1836,1900,1835, +1900,1836,1901, +1837,1901,1836, +1901,1837,1902, +1838,1902,1837, +1902,1838,1903, +1839,1903,1838, +1903,1839,1904, +1840,1904,1839, +1904,1840,1905, +1841,1905,1840, +1905,1841,1906, +1842,1906,1841, +1906,1842,1907, +1843,1907,1842, +1907,1843,1908, +1844,1908,1843, +1908,1844,1909, +1845,1909,1844, +1909,1845,1910, +1846,1910,1845, +1910,1846,1911, +1847,1911,1846, +1911,1847,1912, +1848,1912,1847, +1912,1848,1913, +1849,1913,1848, +1913,1849,1914, +1850,1914,1849, +1914,1850,1915, +1851,1915,1850, +1915,1851,1916, +1852,1916,1851, +1916,1852,1917, +1853,1917,1852, +1917,1853,1918, +1854,1918,1853, +1918,1854,1919, +1855,1919,1854, +1920,1856,1921, +1857,1921,1856, +1921,1857,1922, +1858,1922,1857, +1922,1858,1923, +1859,1923,1858, +1923,1859,1924, +1860,1924,1859, +1924,1860,1925, +1861,1925,1860, +1925,1861,1926, +1862,1926,1861, +1926,1862,1927, +1863,1927,1862, +1927,1863,1928, +1864,1928,1863, +1928,1864,1929, +1865,1929,1864, +1929,1865,1930, +1866,1930,1865, +1930,1866,1931, +1867,1931,1866, +1931,1867,1932, +1868,1932,1867, +1932,1868,1933, +1869,1933,1868, +1933,1869,1934, +1870,1934,1869, +1934,1870,1935, +1871,1935,1870, +1935,1871,1936, +1872,1936,1871, +1936,1872,1937, +1873,1937,1872, +1937,1873,1938, +1874,1938,1873, +1938,1874,1939, +1875,1939,1874, +1939,1875,1940, +1876,1940,1875, +1940,1876,1941, +1877,1941,1876, +1941,1877,1942, +1878,1942,1877, +1942,1878,1943, +1879,1943,1878, +1943,1879,1944, +1880,1944,1879, +1944,1880,1945, +1881,1945,1880, +1945,1881,1946, +1882,1946,1881, +1946,1882,1947, +1883,1947,1882, +1947,1883,1948, +1884,1948,1883, +1948,1884,1949, +1885,1949,1884, +1949,1885,1950, +1886,1950,1885, +1950,1886,1951, +1887,1951,1886, +1951,1887,1952, +1888,1952,1887, +1952,1888,1953, +1889,1953,1888, +1953,1889,1954, +1890,1954,1889, +1954,1890,1955, +1891,1955,1890, +1955,1891,1956, +1892,1956,1891, +1956,1892,1957, +1893,1957,1892, +1957,1893,1958, +1894,1958,1893, +1958,1894,1959, +1895,1959,1894, +1959,1895,1960, +1896,1960,1895, +1960,1896,1961, +1897,1961,1896, +1961,1897,1962, +1898,1962,1897, +1962,1898,1963, +1899,1963,1898, +1963,1899,1964, +1900,1964,1899, +1964,1900,1965, +1901,1965,1900, +1965,1901,1966, +1902,1966,1901, +1966,1902,1967, +1903,1967,1902, +1967,1903,1968, +1904,1968,1903, +1968,1904,1969, +1905,1969,1904, +1969,1905,1970, +1906,1970,1905, +1970,1906,1971, +1907,1971,1906, +1971,1907,1972, +1908,1972,1907, +1972,1908,1973, +1909,1973,1908, +1973,1909,1974, +1910,1974,1909, +1974,1910,1975, +1911,1975,1910, +1975,1911,1976, +1912,1976,1911, +1976,1912,1977, +1913,1977,1912, +1977,1913,1978, +1914,1978,1913, +1978,1914,1979, +1915,1979,1914, +1979,1915,1980, +1916,1980,1915, +1980,1916,1981, +1917,1981,1916, +1981,1917,1982, +1918,1982,1917, +1982,1918,1983, +1919,1983,1918, +1984,1920,1985, +1921,1985,1920, +1985,1921,1986, +1922,1986,1921, +1986,1922,1987, +1923,1987,1922, +1987,1923,1988, +1924,1988,1923, +1988,1924,1989, +1925,1989,1924, +1989,1925,1990, +1926,1990,1925, +1990,1926,1991, +1927,1991,1926, +1991,1927,1992, +1928,1992,1927, +1992,1928,1993, +1929,1993,1928, +1993,1929,1994, +1930,1994,1929, +1994,1930,1995, +1931,1995,1930, +1995,1931,1996, +1932,1996,1931, +1996,1932,1997, +1933,1997,1932, +1997,1933,1998, +1934,1998,1933, +1998,1934,1999, +1935,1999,1934, +1999,1935,2000, +1936,2000,1935, +2000,1936,2001, +1937,2001,1936, +2001,1937,2002, +1938,2002,1937, +2002,1938,2003, +1939,2003,1938, +2003,1939,2004, +1940,2004,1939, +2004,1940,2005, +1941,2005,1940, +2005,1941,2006, +1942,2006,1941, +2006,1942,2007, +1943,2007,1942, +2007,1943,2008, +1944,2008,1943, +2008,1944,2009, +1945,2009,1944, +2009,1945,2010, +1946,2010,1945, +2010,1946,2011, +1947,2011,1946, +2011,1947,2012, +1948,2012,1947, +2012,1948,2013, +1949,2013,1948, +2013,1949,2014, +1950,2014,1949, +2014,1950,2015, +1951,2015,1950, +2015,1951,2016, +1952,2016,1951, +2016,1952,2017, +1953,2017,1952, +2017,1953,2018, +1954,2018,1953, +2018,1954,2019, +1955,2019,1954, +2019,1955,2020, +1956,2020,1955, +2020,1956,2021, +1957,2021,1956, +2021,1957,2022, +1958,2022,1957, +2022,1958,2023, +1959,2023,1958, +2023,1959,2024, +1960,2024,1959, +2024,1960,2025, +1961,2025,1960, +2025,1961,2026, +1962,2026,1961, +2026,1962,2027, +1963,2027,1962, +2027,1963,2028, +1964,2028,1963, +2028,1964,2029, +1965,2029,1964, +2029,1965,2030, +1966,2030,1965, +2030,1966,2031, +1967,2031,1966, +2031,1967,2032, +1968,2032,1967, +2032,1968,2033, +1969,2033,1968, +2033,1969,2034, +1970,2034,1969, +2034,1970,2035, +1971,2035,1970, +2035,1971,2036, +1972,2036,1971, +2036,1972,2037, +1973,2037,1972, +2037,1973,2038, +1974,2038,1973, +2038,1974,2039, +1975,2039,1974, +2039,1975,2040, +1976,2040,1975, +2040,1976,2041, +1977,2041,1976, +2041,1977,2042, +1978,2042,1977, +2042,1978,2043, +1979,2043,1978, +2043,1979,2044, +1980,2044,1979, +2044,1980,2045, +1981,2045,1980, +2045,1981,2046, +1982,2046,1981, +2046,1982,2047, +1983,2047,1982, +}; + diff --git a/Demos/Benchmarks/main.cpp b/Demos/Benchmarks/main.cpp new file mode 100644 index 0000000..48e23bb --- /dev/null +++ b/Demos/Benchmarks/main.cpp @@ -0,0 +1,88 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "BenchmarkDemo.h" +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btHashMap.h" +#include + +#ifdef USE_GRAPHICAL_BENCHMARK + #include "GlutStuff.h" + #include "GLDebugDrawer.h" + GLDebugDrawer gDebugDrawer; +#define benchmarkDemo benchmarkDemo4 +#endif //USE_GRAPHICAL_BENCHMARK + + +#define NUM_DEMOS 7 +#define NUM_TESTS 650 + +extern bool gDisableDeactivation; + +int main(int argc,char** argv) +{ + gDisableDeactivation = true; + + BenchmarkDemo1 benchmarkDemo1; + BenchmarkDemo2 benchmarkDemo2; + BenchmarkDemo3 benchmarkDemo3; + BenchmarkDemo4 benchmarkDemo4; + BenchmarkDemo5 benchmarkDemo5; + BenchmarkDemo6 benchmarkDemo6; + BenchmarkDemo7 benchmarkDemo7; + + BenchmarkDemo* demoArray[NUM_DEMOS] = {&benchmarkDemo1,&benchmarkDemo2,&benchmarkDemo3,&benchmarkDemo4,&benchmarkDemo5,&benchmarkDemo6,&benchmarkDemo7}; + const char* demoNames[NUM_DEMOS] = {"3000 fall", "1000 stack", "136 ragdolls","1000 convex", "prim-trimesh", "convex-trimesh","raytests"}; + float totalTime[NUM_DEMOS] = {0.f,0.f,0.f,0.f,0.f,0.f,0.f}; + +#ifdef USE_GRAPHICAL_BENCHMARK + benchmarkDemo.initPhysics(); + benchmarkDemo.getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + benchmarkDemo.setDebugMode(benchmarkDemo.getDebugMode() | btIDebugDraw::DBG_NoDeactivation); + return glutmain(argc, argv,640,480,"Bullet Physics Demo. http://bulletphysics.com",&benchmarkDemo); + +#else //USE_GRAPHICAL_BENCHMARK + int d; + + for (d=0;dinitPhysics(); + + + for (int i=0;iclientMoveAndDisplay(); + float frameTime = CProfileManager::Get_Time_Since_Reset(); + if ((i % 25)==0) + { + printf("BenchmarkDemo: %s, Frame %d, Duration (ms): %f\n",demoNames[d],i,frameTime); + } + totalTime[d] += frameTime; + if (i==NUM_TESTS-1) + CProfileManager::dumpAll(); + + + } + } + + for (d=0;d //printf debugging + + +void Box2dDemo::clientMoveAndDisplay() +{ + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //simple dynamics world doesn't handle fixed-time-stepping + float ms = getDeltaTimeMicroseconds(); + + ///step the simulation + if (m_dynamicsWorld) + { + m_dynamicsWorld->stepSimulation(ms / 1000000.f); + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + } + + renderme(); + + if (m_dialogDynamicsWorld) + m_dialogDynamicsWorld->draw(ms / 1000000.f); + + glFlush(); + + swapBuffers(); + +} + + + +void Box2dDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + //optional but useful: debug drawing to detect problems + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + if (m_dialogDynamicsWorld) + m_dialogDynamicsWorld->draw(0.f); + + glFlush(); + swapBuffers(); +} + + + +void Box2dDemo::reshape(int w, int h) +{ + if (m_dialogDynamicsWorld) + m_dialogDynamicsWorld->setScreenSize(w,h); + PlatformDemoApplication::reshape(w,h); +} + +void Box2dDemo::initPhysics() +{ + + m_dialogDynamicsWorld = new GL_DialogDynamicsWorld(); + + //m_dialogDynamicsWorld->createDialog(100,110,200,50); + //m_dialogDynamicsWorld->createDialog(100,00,100,100); + //m_dialogDynamicsWorld->createDialog(0,0,100,100); + GL_DialogWindow* settings = m_dialogDynamicsWorld->createDialog(50,0,200,120,"Settings"); + GL_ToggleControl* toggle = m_dialogDynamicsWorld->createToggle(settings,"Toggle 1"); + toggle = m_dialogDynamicsWorld->createToggle(settings,"Toggle 2"); + toggle ->m_active = true; + toggle = m_dialogDynamicsWorld->createToggle(settings,"Toggle 3"); + GL_SliderControl* slider = m_dialogDynamicsWorld->createSlider(settings,"Slider"); + + GL_DialogWindow* dialog = m_dialogDynamicsWorld->createDialog(0,200,420,300,"Help"); + GL_TextControl* txt = new GL_TextControl; + dialog->addControl(txt); + txt->m_textLines.push_back("Mouse to move"); + txt->m_textLines.push_back("Test 2"); + txt->m_textLines.push_back("mouse to interact"); + txt->m_textLines.push_back("ALT + mouse to move camera"); + txt->m_textLines.push_back("space to reset"); + txt->m_textLines.push_back("cursor keys and z,x to navigate"); + txt->m_textLines.push_back("i to toggle simulation, s single step"); + txt->m_textLines.push_back("q to quit"); + txt->m_textLines.push_back(". to shoot box"); + txt->m_textLines.push_back("d to toggle deactivation"); + txt->m_textLines.push_back("g to toggle mesh animation (ConcaveDemo)"); + txt->m_textLines.push_back("h to toggle help text"); + txt->m_textLines.push_back("o to toggle orthogonal/perspective view"); + //txt->m_textLines.push_back("+- shooting speed = %10.2f",m_ShootBoxInitialSpeed); + + + + setTexturing(true); + setShadows(true); + + setCameraDistance(btScalar(SCALING*50.)); + m_cameraTargetPosition.setValue(0,0,0);//0, ARRAY_SIZE_Y, 0); + + ///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); + + btVoronoiSimplexSolver* simplex = new btVoronoiSimplexSolver(); + btMinkowskiPenetrationDepthSolver* pdSolver = new btMinkowskiPenetrationDepthSolver(); + + + btConvex2dConvex2dAlgorithm::CreateFunc* convexAlgo2d = new btConvex2dConvex2dAlgorithm::CreateFunc(simplex,pdSolver); + + m_dispatcher->registerCollisionCreateFunc(CONVEX_2D_SHAPE_PROXYTYPE,CONVEX_2D_SHAPE_PROXYTYPE,convexAlgo2d); + m_dispatcher->registerCollisionCreateFunc(BOX_2D_SHAPE_PROXYTYPE,CONVEX_2D_SHAPE_PROXYTYPE,convexAlgo2d); + m_dispatcher->registerCollisionCreateFunc(CONVEX_2D_SHAPE_PROXYTYPE,BOX_2D_SHAPE_PROXYTYPE,convexAlgo2d); + m_dispatcher->registerCollisionCreateFunc(BOX_2D_SHAPE_PROXYTYPE,BOX_2D_SHAPE_PROXYTYPE,new btBox2dBox2dCollisionAlgorithm::CreateFunc()); + + m_broadphase = new btDbvtBroadphase(); + //m_broadphase = new btSimpleBroadphase(); + + ///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->getSolverInfo().m_erp = 1.f; + //m_dynamicsWorld->getSolverInfo().m_numIterations = 4; + + + + m_dynamicsWorld->setGravity(btVector3(0,-10,0)); + + ///create a few basic rigid bodies + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(150.),btScalar(50.),btScalar(150.))); +// btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); + + m_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-43,0)); + + //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here: + { + btScalar mass(0.); + + //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) + groundShape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + //add the body to the dynamics world + m_dynamicsWorld->addRigidBody(body); + } + + + { + //create a few dynamic rigidbodies + // Re-using the same collision is better for memory usage and performance + + btScalar u= btScalar(1*SCALING-0.04); + btVector3 points[3] = {btVector3(0,u,0),btVector3(-u,-u,0),btVector3(u,-u,0)}; + btConvexShape* colShape= new btConvex2dShape(new btBoxShape(btVector3(btScalar(SCALING*1),btScalar(SCALING*1),btScalar(0.04)))); + //btCollisionShape* colShape = new btBox2dShape(btVector3(SCALING*1,SCALING*1,0.04)); + + btConvexShape* colShape2= new btConvex2dShape(new btConvexHullShape(&points[0].getX(),3)); + btConvexShape* colShape3= new btConvex2dShape(new btCylinderShapeZ(btVector3(btScalar(SCALING*1),btScalar(SCALING*1),btScalar(0.04)))); + + + + + + //btUniformScalingShape* colShape = new btUniformScalingShape(convexColShape,1.f); + colShape->setMargin(btScalar(0.03)); + //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); + m_collisionShapes.push_back(colShape); + m_collisionShapes.push_back(colShape2); + + + /// Create Dynamic Objects + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + + //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) + colShape->calculateLocalInertia(mass,localInertia); + +// float start_x = START_POS_X - ARRAY_SIZE_X/2; +// float start_y = START_POS_Y; +// float start_z = START_POS_Z - ARRAY_SIZE_Z/2; + + btVector3 x(-ARRAY_SIZE_X, 8.0f,-20.f); + btVector3 y; + btVector3 deltaX(SCALING*1, SCALING*2,0.f); + btVector3 deltaY(SCALING*2, 0.0f,0.f); + + for (int i = 0; i < ARRAY_SIZE_X; ++i) + { + y = x; + + for (int j = i; j < ARRAY_SIZE_Y; ++j) + { + startTransform.setOrigin(y-btVector3(-10,0,0)); + + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(0,0,0); + switch (j%3) + { +#if 1 + case 0: + rbInfo = btRigidBody::btRigidBodyConstructionInfo(mass,myMotionState,colShape,localInertia); + break; + case 1: + rbInfo = btRigidBody::btRigidBodyConstructionInfo(mass,myMotionState,colShape3,localInertia); + break; +#endif + default: + rbInfo = btRigidBody::btRigidBodyConstructionInfo(mass,myMotionState,colShape2,localInertia); + } + btRigidBody* body = new btRigidBody(rbInfo); + //body->setContactProcessingThreshold(colShape->getContactBreakingThreshold()); + body->setActivationState(ISLAND_SLEEPING); + body->setLinearFactor(btVector3(1,1,0)); + body->setAngularFactor(btVector3(0,0,1)); + + m_dynamicsWorld->addRigidBody(body); + body->setActivationState(ISLAND_SLEEPING); + + + // y += -0.8*deltaY; + y += deltaY; + } + + x += deltaX; + } + + } + + + clientResetScene(); +} + + +void Box2dDemo::exitPhysics() +{ + delete m_dialogDynamicsWorld; + m_dialogDynamicsWorld = 0; + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;jmouseFunc(button,state,x,y)) + { + DemoApplication::mouseFunc(button,state,x,y); + } +} + +void Box2dDemo::mouseMotionFunc(int x,int y) +{ + m_dialogDynamicsWorld->mouseMotionFunc(x,y); + DemoApplication::mouseMotionFunc(x,y); +} + diff --git a/Demos/Box2dDemo/Box2dDemo.h b/Demos/Box2dDemo/Box2dDemo.h new file mode 100644 index 0000000..02d4cc6 --- /dev/null +++ b/Demos/Box2dDemo/Box2dDemo.h @@ -0,0 +1,89 @@ +/* +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 BOX2D_DEMO_H +#define BOX2D_DEMO_H + +#ifdef _WINDOWS +#include "Win32DemoApplication.h" +#define PlatformDemoApplication Win32DemoApplication +#else +#include "GlutDemoApplication.h" +#define PlatformDemoApplication GlutDemoApplication +#endif + +#include "LinearMath/btAlignedObjectArray.h" + +class btBroadphaseInterface; +class btCollisionShape; +class btOverlappingPairCache; +class btCollisionDispatcher; +class btConstraintSolver; +struct btCollisionAlgorithmCreateFunc; +class btDefaultCollisionConfiguration; +class GL_DialogDynamicsWorld; + +///Box2dDemo is good starting point for learning the code base and porting. +class Box2dDemo : public PlatformDemoApplication +{ + + //keep the collision shapes, for deletion/cleanup + btAlignedObjectArray m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + GL_DialogDynamicsWorld* m_dialogDynamicsWorld; + + public: + + Box2dDemo() : m_dialogDynamicsWorld(0) + { + } + virtual ~Box2dDemo() + { + exitPhysics(); + } + + virtual void reshape(int w, int h); + + void initPhysics(); + + void exitPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + static DemoApplication* Create() + { + Box2dDemo* demo = new Box2dDemo; + demo->myinit(); + demo->initPhysics(); + return demo; + } + + virtual void mouseFunc(int button, int state, int x, int y); + virtual void mouseMotionFunc(int x,int y); + + +}; + +#endif //BOX2D_DEMO_H + diff --git a/Demos/Box2dDemo/CMakeLists.txt b/Demos/Box2dDemo/CMakeLists.txt new file mode 100644 index 0000000..0b434f6 --- /dev/null +++ b/Demos/Box2dDemo/CMakeLists.txt @@ -0,0 +1,75 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# This is the variable for Windows. I use this to define the root of my directory structure. +SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/Glut) + +# You shouldn't have to modify anything below this line +######################################################## + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + IF (WIN32) + ADD_EXECUTABLE(AppBox2dDemo + main.cpp + Box2dDemo.cpp + Box2dDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) + ELSE() + ADD_EXECUTABLE(AppBox2dDemo + main.cpp + Box2dDemo.cpp + Box2dDemo.h + ) + ENDIF() + IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppBox2dDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppBox2dDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + + ENDIF(WIN32) +ELSE (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + ADD_EXECUTABLE(AppBox2dDemo + WIN32 + ../OpenGL/Win32AppMain.cpp + Win32Box2dDemo.cpp + Box2dDemo.cpp + Box2dDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) +ENDIF (USE_GLUT) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppBox2dDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppBox2dDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppBox2dDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + diff --git a/Demos/Box2dDemo/Win32Box2dDemo.cpp b/Demos/Box2dDemo/Win32Box2dDemo.cpp new file mode 100644 index 0000000..fb43906 --- /dev/null +++ b/Demos/Box2dDemo/Win32Box2dDemo.cpp @@ -0,0 +1,25 @@ +#ifdef _WINDOWS +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "Box2dDemo.h" + +///The 'createDemo' function is called from Bullet/Demos/OpenGL/Win32AppMain.cpp to instantiate this particular demo +DemoApplication* createDemo() +{ + return new Box2dDemo(); +} + +#endif diff --git a/Demos/Box2dDemo/main.cpp b/Demos/Box2dDemo/main.cpp new file mode 100644 index 0000000..1b0651c --- /dev/null +++ b/Demos/Box2dDemo/main.cpp @@ -0,0 +1,61 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "Box2dDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btHashMap.h" + +class OurValue + { + int m_uid; + + public: + OurValue(const btVector3& initialPos) + :m_position(initialPos) + { + static int gUid=0; + m_uid=gUid; + gUid++; + } + + btVector3 m_position; + int getUid() const + { + return m_uid; + } + }; + + +int main(int argc,char** argv) +{ + GLDebugDrawer gDebugDrawer; + + Box2dDemo ccdDemo; + ccdDemo.initPhysics(); + ccdDemo.getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + +#ifdef CHECK_MEMORY_LEAKS + ccdDemo.exitPhysics(); +#else + return glutmain(argc, argv,640,480,"Bullet Physics Demo. http://bulletphysics.com",&ccdDemo); +#endif + + //default glut doesn't return from mainloop + return 0; +} + diff --git a/Demos/BspDemo/BspConverter.cpp b/Demos/BspDemo/BspConverter.cpp new file mode 100644 index 0000000..8d750c3 --- /dev/null +++ b/Demos/BspDemo/BspConverter.cpp @@ -0,0 +1,207 @@ +/* +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 "BspConverter.h" +#include "BspLoader.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btGeometryUtil.h" +#include +#include + + +void BspConverter::convertBsp(BspLoader& bspLoader,float scaling) +{ + { + + float playstartf[3] = {0,0,100}; + + if (bspLoader.findVectorByName(&playstartf[0],"info_player_start")) + { + printf("found playerstart\n"); + } + else + { + if (bspLoader.findVectorByName(&playstartf[0],"info_player_deathmatch")) + { + printf("found deatchmatch start\n"); + } + } + + btVector3 playerStart (playstartf[0],playstartf[1],playstartf[2]); + + + playerStart[2] += 20.f; //start a bit higher + + playerStart *= scaling; + + + + //progressBegin("Loading bsp"); + + for (int i=0;i planeEquations; + + int brushid = bspLoader.m_dleafbrushes[leaf.firstLeafBrush+b]; + + BSPBrush& brush = bspLoader.m_dbrushes[brushid]; + if (brush.shaderNum!=-1) + { + if (bspLoader.m_dshaders[ brush.shaderNum ].contentFlags & BSPCONTENTS_SOLID) + { + brush.shaderNum = -1; + + for (int p=0;p vertices; + btGeometryUtil::getVerticesFromPlaneEquations(planeEquations,vertices); + + bool isEntity = false; + btVector3 entityTarget(0.f,0.f,0.f); + addConvexVerticesCollider(vertices,isEntity,entityTarget); + + } + } + } + } + } + +#define USE_ENTITIES +#ifdef USE_ENTITIES + + + { + int i; + for (i=0;i=0) && (modelnr < bspLoader.m_nummodels)) + { + const BSPModel& model = bspLoader.m_dmodels[modelnr]; + for (int n=0;n planeEquations; + bool isValidBrush = false; + + //convert brush + const BSPBrush& brush = bspLoader.m_dbrushes[model.firstBrush+n]; + { + for (int p=0;p vertices; + btGeometryUtil::getVerticesFromPlaneEquations(planeEquations,vertices); + + bool isEntity=true; + addConvexVerticesCollider(vertices,isEntity,targetLocation); + + } + } + + } + } + } + else + { + printf("unsupported trigger_push model, md3 ?\n"); + } + } + + } + } + } + } + +#endif //USE_ENTITIES + + + + //progressEnd(); + } + + } + + + + + + diff --git a/Demos/BspDemo/BspConverter.h b/Demos/BspDemo/BspConverter.h new file mode 100644 index 0000000..aca44db --- /dev/null +++ b/Demos/BspDemo/BspConverter.h @@ -0,0 +1,39 @@ +/* +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 BSP_CONVERTER_H +#define BSP_CONVERTER_H + +class BspLoader; +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" + +///BspConverter turns a loaded bsp level into convex parts (vertices) +class BspConverter +{ + public: + + void convertBsp(BspLoader& bspLoader,float scaling); + virtual ~BspConverter() + { + } + + ///this callback is called for each brush that succesfully converted into vertices + virtual void addConvexVerticesCollider(btAlignedObjectArray& vertices, bool isEntity, const btVector3& entityTargetLocation) = 0; + +}; + +#endif //BSP_CONVERTER_H + diff --git a/Demos/BspDemo/BspDemo.cpp b/Demos/BspDemo/BspDemo.cpp new file mode 100644 index 0000000..8301eac --- /dev/null +++ b/Demos/BspDemo/BspDemo.cpp @@ -0,0 +1,321 @@ +/* +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 "GLDebugDrawer.h" + + +#define QUAKE_BSP_IMPORTING 1 + +#ifdef QUAKE_BSP_IMPORTING +#include "BspLoader.h" +#include "BspConverter.h" +#endif //QUAKE_BSP_IMPORTING + + +#include //printf debugging + + +#include "BspDemo.h" +#include "GL_ShapeDrawer.h" +#include "GlutStuff.h" + + + + +#define CUBE_HALF_EXTENTS 1 +#define EXTRA_HEIGHT -20.f + + + +///BspToBulletConverter extends the BspConverter to convert to Bullet datastructures +class BspToBulletConverter : public BspConverter +{ + BspDemo* m_demoApp; + +public: + + BspToBulletConverter(BspDemo* demoApp) + :m_demoApp(demoApp) + { + } + + virtual void addConvexVerticesCollider(btAlignedObjectArray& vertices, bool isEntity, const btVector3& entityTargetLocation) + { + ///perhaps we can do something special with entities (isEntity) + ///like adding a collision Triggering (as example) + + if (vertices.size() > 0) + { + float mass = 0.f; + btTransform startTransform; + //can use a shift + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(0,0,-10.f)); + //this create an internal copy of the vertices + + btCollisionShape* shape = new btConvexHullShape(&(vertices[0].getX()),vertices.size()); + m_demoApp->m_collisionShapes.push_back(shape); + + //btRigidBody* body = m_demoApp->localCreateRigidBody(mass, startTransform,shape); + m_demoApp->localCreateRigidBody(mass, startTransform,shape); + } + } +}; + + + + + +//////////////////////////////////// + + + + + + + +BspDemo::~BspDemo() +{ + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;jsetGravity(-m_cameraUp * 10); + + +#ifdef QUAKE_BSP_IMPORTING + + void* memoryBuffer = 0; + + FILE* file = fopen(bspfilename,"r"); + if (!file) + { + //try again other path, + //sight... visual studio leaves the current working directory in the projectfiles folder + //instead of executable folder. who wants this default behaviour?!? + bspfilename = "../../BspDemo.bsp"; + file = fopen(bspfilename,"r"); + } + if (!file) + { + + //try again other path, cmake needs 4 levels deep back... + bspfilename = "../../../../BspDemo.bsp"; + file = fopen(bspfilename,"r"); + } + if (!file) + { + //try again other path, + //sight... visual studio leaves the current working directory in the projectfiles folder + //instead of executable folder. who wants this default behaviour?!? + bspfilename = "BspDemo.bsp"; + file = fopen(bspfilename,"r"); + } + + if (file) + { + BspLoader bspLoader; + int size=0; + if (fseek(file, 0, SEEK_END) || (size = ftell(file)) == EOF || fseek(file, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */ + printf("Error: cannot get filesize from %s\n", bspfilename); + } else + { + //how to detect file size? + memoryBuffer = malloc(size+1); + fread(memoryBuffer,1,size,file); + bspLoader.loadBSPFile( memoryBuffer); + + BspToBulletConverter bsp2bullet(this); + float bspScaling = 0.1f; + bsp2bullet.convertBsp(bspLoader,bspScaling); + + } + fclose(file); + } + +#endif + + + + + clientResetScene(); + +} + + +void BspDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + float dt = getDeltaTimeMicroseconds() * 0.000001f; + + m_dynamicsWorld->stepSimulation(dt); + + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + + renderme(); + + glFlush(); + glutSwapBuffers(); + +} + + + +void BspDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + + renderme(); + + //optional but useful: debug drawing + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + glFlush(); + glutSwapBuffers(); +} + + + + + + +//some code that de-mangles the windows filename passed in as argument +char cleaned_filename[512]; +char* getLastFileName() +{ + return cleaned_filename; +} +char* makeExeToBspFilename(const char* lpCmdLine) +{ + + + // We might get a windows-style path on the command line, this can mess up the DOM which expects + // all paths to be URI's. This block of code does some conversion to try and make the input + // compliant without breaking the ability to accept a properly formatted URI. Right now this only + // displays the first filename + const char *in = lpCmdLine; + char* out = cleaned_filename; + *out = '\0'; + // If the first character is a ", skip it (filenames with spaces in them are quoted) + if(*in == '\"') + { + in++; + } + int i; + for(i =0; i<512; i++) + { + //if we get '.' we stop as well, unless it's the first character. Then we add .bsp as extension + // If we hit a null or a quote, stop copying. This will get just the first filename. + if(i && (in[0] == '.') && (in[1] == 'e') && (in[2] == 'x') && (in[3] == 'e')) + break; + + // If we hit a null or a quote, stop copying. This will get just the first filename. + if(*in == '\0' || *in == '\"') + break; + // Copy while swapping backslashes for forward ones + if(*in == '\\') + { + *out = '/'; + } + else + { + *out = *in; + } + in++; + out++; + } + *(out++) = '.'; + *(out++) = 'b'; + *(out++) = 's'; + *(out++) = 'p'; + *(out++) = 0; + + return cleaned_filename; +} diff --git a/Demos/BspDemo/BspDemo.h b/Demos/BspDemo/BspDemo.h new file mode 100644 index 0000000..d2f5d7a --- /dev/null +++ b/Demos/BspDemo/BspDemo.h @@ -0,0 +1,71 @@ +/* +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 BSP_DEMO_H +#define BSP_DEMO_H + +#include "GlutDemoApplication.h" +#include "LinearMath/btAlignedObjectArray.h" + +class btBroadphaseInterface; +class btCollisionShape; +class btOverlappingPairCache; +class btCollisionDispatcher; +class btConstraintSolver; +struct btCollisionAlgorithmCreateFunc; +class btDefaultCollisionConfiguration; + + +///BspDemo shows the convex collision detection, by converting a Quake BSP file into convex objects and allowing interaction with boxes. +class BspDemo : public GlutDemoApplication +{ + public: + + //keep the collision shapes, for deletion/cleanup + btAlignedObjectArray m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + + + + virtual ~BspDemo(); + + virtual void initPhysics(); + + void initPhysics(const char* bspfilename); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + static DemoApplication* Create() + { + BspDemo* demo = new BspDemo; + demo->myinit(); + demo->initPhysics("BspDemo.bsp"); + return demo; + } + +}; + +#endif //BSP_DEMO_H + + diff --git a/Demos/BspDemo/BspLoader.cpp b/Demos/BspDemo/BspLoader.cpp new file mode 100644 index 0000000..0572463 --- /dev/null +++ b/Demos/BspDemo/BspLoader.cpp @@ -0,0 +1,730 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU bteral Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU bteral Public License for more details. + +You should have received a copy of the GNU bteral Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + + +#include "BspLoader.h" +#include +#include + +typedef struct +{ + char filename[1024]; + char *buffer,*script_p,*end_p; + int line; +} BSPScript; + +#define MAX_INCLUDES 8 +BSPScript scriptstack[MAX_INCLUDES]; +BSPScript *script; +int scriptline; + +char token[BSPMAXTOKEN]; +bool endofscript; +bool tokenready; // only true if UnGetToken was just called + +// +//loadBSPFile +// + +int extrasize = 100; + +BspLoader::BspLoader() + :m_num_entities(0) +{ + m_Endianness = getMachineEndianness(); + if (m_Endianness == BSP_BIG_ENDIAN) + { + printf("Machine is BIG_ENDIAN\n"); + } else + { + printf("Machine is Little Endian\n"); + } +} + + +bool BspLoader::loadBSPFile( void* memoryBuffer) { + + BSPHeader *header = (BSPHeader*) memoryBuffer; + + // load the file header + if (header) + { + // swap the header + swapBlock( (int *)header, sizeof(*header) ); + + int length = (header->lumps[BSPLUMP_SHADERS].filelen) / sizeof(BSPShader); + m_dshaders.resize(length+extrasize); + m_numShaders = copyLump( header, BSPLUMP_SHADERS, &m_dshaders[0], sizeof(BSPShader) ); + + length = (header->lumps[LUMP_MODELS].filelen) / sizeof(BSPModel); + m_dmodels.resize(length+extrasize); + m_nummodels = copyLump( header, LUMP_MODELS, &m_dmodels[0], sizeof(BSPModel) ); + + length = (header->lumps[BSPLUMP_PLANES].filelen) / sizeof(BSPPlane); + m_dplanes.resize(length+extrasize); + m_numplanes = copyLump( header, BSPLUMP_PLANES, &m_dplanes[0], sizeof(BSPPlane) ); + + length = (header->lumps[BSPLUMP_LEAFS].filelen) / sizeof(BSPLeaf); + m_dleafs.resize(length+extrasize); + m_numleafs = copyLump( header, BSPLUMP_LEAFS, &m_dleafs[0], sizeof(BSPLeaf) ); + + length = (header->lumps[BSPLUMP_NODES].filelen) / sizeof(BSPNode); + m_dnodes.resize(length+extrasize); + m_numnodes = copyLump( header, BSPLUMP_NODES, &m_dnodes[0], sizeof(BSPNode) ); + + length = (header->lumps[BSPLUMP_LEAFSURFACES].filelen) / sizeof(m_dleafsurfaces[0]); + m_dleafsurfaces.resize(length+extrasize); + m_numleafsurfaces = copyLump( header, BSPLUMP_LEAFSURFACES, &m_dleafsurfaces[0], sizeof(m_dleafsurfaces[0]) ); + + length = (header->lumps[BSPLUMP_LEAFBRUSHES].filelen) / sizeof(m_dleafbrushes[0]) ; + m_dleafbrushes.resize(length+extrasize); + m_numleafbrushes = copyLump( header, BSPLUMP_LEAFBRUSHES, &m_dleafbrushes[0], sizeof(m_dleafbrushes[0]) ); + + length = (header->lumps[LUMP_BRUSHES].filelen) / sizeof(BSPBrush); + m_dbrushes.resize(length+extrasize); + m_numbrushes = copyLump( header, LUMP_BRUSHES, &m_dbrushes[0], sizeof(BSPBrush) ); + + + length = (header->lumps[LUMP_BRUSHSIDES].filelen) / sizeof(BSPBrushSide); + m_dbrushsides.resize(length+extrasize); + m_numbrushsides = copyLump( header, LUMP_BRUSHSIDES, &m_dbrushsides[0], sizeof(BSPBrushSide) ); + + + length = (header->lumps[LUMP_SURFACES].filelen) / sizeof(BSPSurface); + m_drawSurfaces.resize(length+extrasize); + m_numDrawSurfaces = copyLump( header, LUMP_SURFACES, &m_drawSurfaces[0], sizeof(BSPSurface) ); + + + length = (header->lumps[LUMP_DRAWINDEXES].filelen) / sizeof(m_drawIndexes[0]); + m_drawIndexes.resize(length+extrasize); + m_numDrawIndexes = copyLump( header, LUMP_DRAWINDEXES, &m_drawIndexes[0], sizeof(m_drawIndexes[0]) ); + + length = (header->lumps[LUMP_VISIBILITY].filelen) / 1; + m_visBytes.resize(length+extrasize); + m_numVisBytes = copyLump( header, LUMP_VISIBILITY, &m_visBytes[0], 1 ); + + length = (header->lumps[LUMP_LIGHTMAPS].filelen) / 1; + m_lightBytes.resize(length+extrasize); + m_numLightBytes = copyLump( header, LUMP_LIGHTMAPS, &m_lightBytes[0], 1 ); + + length = (header->lumps[BSPLUMP_ENTITIES].filelen) / 1; + m_dentdata.resize(length+extrasize); + m_entdatasize = copyLump( header, BSPLUMP_ENTITIES, &m_dentdata[0], 1); + + length = (header->lumps[LUMP_LIGHTGRID].filelen) / 1; + m_gridData.resize(length+extrasize); + m_numGridPoints = copyLump( header, LUMP_LIGHTGRID, &m_gridData[0], 8 ); + + // swap everything + swapBSPFile(); + + return true; + + } + return false; +} + + + +const char* BspLoader::getValueForKey( const BSPEntity* ent, const char* key ) const { + + const BSPKeyValuePair* ep; + + for (ep=ent->epairs ; ep ; ep=ep->next) { + if (!strcmp(ep->key, key) ) { + return ep->value; + } + } + return ""; +} + +float BspLoader::getFloatForKey( const BSPEntity *ent, const char *key ) { + const char *k; + + k = getValueForKey( ent, key ); + return float(atof(k)); +} + +bool BspLoader::getVectorForKey( const BSPEntity *ent, const char *key, BSPVector3 vec ) { + + const char *k; + k = getValueForKey (ent, key); + if (strcmp(k, "")) + { + sscanf (k, "%f %f %f", &vec[0], &vec[1], &vec[2]); + return true; + } + return false; +} + + + + +/* +============== +parseFromMemory +============== +*/ +void BspLoader::parseFromMemory (char *buffer, int size) +{ + script = scriptstack; + script++; + if (script == &scriptstack[MAX_INCLUDES]) + { + //printf("script file exceeded MAX_INCLUDES"); + } + strcpy (script->filename, "memory buffer" ); + + script->buffer = buffer; + script->line = 1; + script->script_p = script->buffer; + script->end_p = script->buffer + size; + + endofscript = false; + tokenready = false; +} + + +bool BspLoader::isEndOfScript (bool crossline) +{ + if (!crossline) + //printf("Line %i is incomplete\n",scriptline); + + if (!strcmp (script->filename, "memory buffer")) + { + endofscript = true; + return false; + } + + //free (script->buffer); + if (script == scriptstack+1) + { + endofscript = true; + return false; + } + script--; + scriptline = script->line; + //printf ("returning to %s\n", script->filename); + return getToken (crossline); +} + +/* + +============== +getToken +============== +*/ +bool BspLoader::getToken (bool crossline) +{ + char *token_p; + + if (tokenready) // is a token allready waiting? + { + tokenready = false; + return true; + } + + if (script->script_p >= script->end_p) + return isEndOfScript (crossline); + +// +// skip space +// +skipspace: + while (*script->script_p <= 32) + { + if (script->script_p >= script->end_p) + return isEndOfScript (crossline); + if (*script->script_p++ == '\n') + { + if (!crossline) + { + //printf("Line %i is incomplete\n",scriptline); + } + scriptline = script->line++; + } + } + + if (script->script_p >= script->end_p) + return isEndOfScript (crossline); + + // ; # // comments + if (*script->script_p == ';' || *script->script_p == '#' + || ( script->script_p[0] == '/' && script->script_p[1] == '/') ) + { + if (!crossline) + { + //printf("Line %i is incomplete\n",scriptline); + } + while (*script->script_p++ != '\n') + if (script->script_p >= script->end_p) + return isEndOfScript (crossline); + scriptline = script->line++; + goto skipspace; + } + + // /* */ comments + if (script->script_p[0] == '/' && script->script_p[1] == '*') + { + if (!crossline) + { + //printf("Line %i is incomplete\n",scriptline); + } + script->script_p+=2; + while (script->script_p[0] != '*' && script->script_p[1] != '/') + { + if ( *script->script_p == '\n' ) { + scriptline = script->line++; + } + script->script_p++; + if (script->script_p >= script->end_p) + return isEndOfScript (crossline); + } + script->script_p += 2; + goto skipspace; + } + +// +// copy token +// + token_p = token; + + if (*script->script_p == '"') + { + // quoted token + script->script_p++; + while (*script->script_p != '"') + { + *token_p++ = *script->script_p++; + if (script->script_p == script->end_p) + break; + if (token_p == &token[BSPMAXTOKEN]) + { + //printf ("Token too large on line %i\n",scriptline); + } + } + script->script_p++; + } + else // regular token + while ( *script->script_p > 32 && *script->script_p != ';') + { + *token_p++ = *script->script_p++; + if (script->script_p == script->end_p) + break; + if (token_p == &token[BSPMAXTOKEN]) + { + //printf ("Token too large on line %i\n",scriptline); + } + } + + *token_p = 0; + + if (!strcmp (token, "$include")) + { + //getToken (false); + //AddScriptToStack (token); + return false;//getToken (crossline); + } + + return true; +} + +char *BspLoader::copystring(const char *s) +{ + char *b; + b = (char*) malloc( strlen(s)+1); + strcpy (b, s); + return b; +} + +void BspLoader::stripTrailing( char *e ) { + char *s; + + s = e + strlen(e)-1; + while (s >= e && *s <= 32) + { + *s = 0; + s--; + } +} +/* +================= +parseEpair +================= +*/ +BSPKeyValuePair *BspLoader::parseEpair( void ) { + BSPKeyValuePair *e; + + e = (struct BSPPair*) malloc( sizeof(BSPKeyValuePair)); + memset( e, 0, sizeof(BSPKeyValuePair) ); + + if ( strlen(token) >= BSPMAX_KEY-1 ) { + //printf ("ParseEpar: token too long"); + } + e->key = copystring( token ); + getToken( false ); + if ( strlen(token) >= BSPMAX_VALUE-1 ) { + + //printf ("ParseEpar: token too long"); + } + e->value = copystring( token ); + + // strip trailing spaces that sometimes get accidentally + // added in the editor + stripTrailing( e->key ); + stripTrailing( e->value ); + + return e; +} + + +/* +================ +parseEntity +================ +*/ +bool BspLoader::parseEntity( void ) { + BSPKeyValuePair *e; + BSPEntity *mapent; + + if ( !getToken (true) ) { + return false; + } + + if ( strcmp (token, "{") ) { + + //printf ("parseEntity: { not found"); + } + + BSPEntity bla; + bla.brushes = 0; + bla.epairs = 0; + bla.firstDrawSurf = 0; + bla.origin[0] = 0.f; + bla.origin[1] = 0.f; + bla.origin[2] = 0.f; + bla.patches = 0; + + m_entities.push_back(bla); + mapent = &m_entities[m_entities.size()-1]; + m_num_entities++; + + do { + if ( !getToken (true) ) { + //printf("parseEntity: EOF without closing brace"); + } + if ( !strcmp (token, "}") ) { + break; + } + e = (struct BSPPair*)parseEpair (); + e->next = mapent->epairs; + mapent->epairs = e; + } while (1); + + return true; +} + +/* +================ +parseEntities + +Parses the dentdata string into entities +================ +*/ +void BspLoader::parseEntities( void ) { + m_num_entities = 0; + m_entities.clear(); + + parseFromMemory( &m_dentdata[0], m_entdatasize ); + + while ( parseEntity () ) { + } +} + + + +int BspLoader::getMachineEndianness() +{ + long int i = 1; + const char *p = (const char *) &i; + if (p[0] == 1) // Lowest address contains the least significant byte + return BSP_LITTLE_ENDIAN; + else + return BSP_BIG_ENDIAN; +} + +short BspLoader::isLittleShort (short l) +{ + if (machineEndianness() == BSP_BIG_ENDIAN) + { + unsigned char b1,b2; + + b1 = l&255; + b2 = (l>>8)&255; + + return (b1<<8) + b2; + } + //little endian + return l; +} + +short BspLoader::isBigShort (short l) +{ + if (machineEndianness() == BSP_BIG_ENDIAN) + { + return l; + } + + unsigned char b1,b2; + + b1 = l&255; + b2 = (l>>8)&255; + + return (b1<<8) + b2; + + + +} + + +int BspLoader::isLittleLong (int l) +{ + if (machineEndianness() == BSP_BIG_ENDIAN) + { + unsigned char b1,b2,b3,b4; + + b1 = l&255; + b2 = (l>>8)&255; + b3 = (l>>16)&255; + b4 = (l>>24)&255; + + return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; + } + + //little endian + return l; + +} + +int BspLoader::isBigLong (int l) +{ + if (machineEndianness() == BSP_BIG_ENDIAN) + { + return l; + } + + + unsigned char b1,b2,b3,b4; + + b1 = l&255; + b2 = (l>>8)&255; + b3 = (l>>16)&255; + b4 = (l>>24)&255; + + return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; + +} + + +float BspLoader::isLittleFloat (float l) +{ + if (machineEndianness() == BSP_BIG_ENDIAN) + { + union {unsigned char b[4]; float f;} in, out; + + in.f = l; + out.b[0] = in.b[3]; + out.b[1] = in.b[2]; + out.b[2] = in.b[1]; + out.b[3] = in.b[0]; + + return out.f; + } + + //little endian + return l; +} + +float BspLoader::isBigFloat (float l) +{ + if (machineEndianness() == BSP_BIG_ENDIAN) + { + return l; + } + //little endian + union {unsigned char b[4]; float f;} in, out; + + in.f = l; + out.b[0] = in.b[3]; + out.b[1] = in.b[2]; + out.b[2] = in.b[1]; + out.b[3] = in.b[0]; + + return out.f; +} + + + + + + +// +// swapBlock +// If all values are 32 bits, this can be used to swap everything +// + +void BspLoader::swapBlock( int *block, int sizeOfBlock ) { + int i; + + sizeOfBlock >>= 2; + for ( i = 0 ; i < sizeOfBlock ; i++ ) { + block[i] = isLittleLong( block[i] ); + } +} + +// +// copyLump +// + +int BspLoader::copyLump( BSPHeader *header, int lump, void *dest, int size ) { + int length, ofs; + + length = header->lumps[lump].filelen; + ofs = header->lumps[lump].fileofs; + + //if ( length % size ) { + // printf ("loadBSPFile: odd lump size"); + //} + + memcpy( dest, (unsigned char *)header + ofs, length ); + + return length / size; +} + + + + +// +// swapBSPFile +// + +void BspLoader::swapBSPFile( void ) { + int i; + + // models + swapBlock( (int *) &m_dmodels[0], m_nummodels * sizeof( m_dmodels[0] ) ); + + // shaders (don't swap the name) + for ( i = 0 ; i < m_numShaders ; i++ ) { + m_dshaders[i].contentFlags = isLittleLong( m_dshaders[i].contentFlags ); + m_dshaders[i].surfaceFlags = isLittleLong( m_dshaders[i].surfaceFlags ); + } + + // planes + swapBlock( (int *)&m_dplanes[0], m_numplanes * sizeof( m_dplanes[0] ) ); + + // nodes + swapBlock( (int *)&m_dnodes[0], m_numnodes * sizeof( m_dnodes[0] ) ); + + // leafs + swapBlock( (int *)&m_dleafs[0], m_numleafs * sizeof( m_dleafs[0] ) ); + + // leaffaces + swapBlock( (int *)&m_dleafsurfaces[0], m_numleafsurfaces * sizeof( m_dleafsurfaces[0] ) ); + + // leafbrushes + swapBlock( (int *)&m_dleafbrushes[0], m_numleafbrushes * sizeof( m_dleafbrushes[0] ) ); + + // brushes + swapBlock( (int *)&m_dbrushes[0], m_numbrushes * sizeof( m_dbrushes[0] ) ); + + // brushsides + swapBlock( (int *)&m_dbrushsides[0], m_numbrushsides * sizeof( m_dbrushsides[0] ) ); + + // vis + ((int *)&m_visBytes)[0] = isLittleLong( ((int *)&m_visBytes)[0] ); + ((int *)&m_visBytes)[1] = isLittleLong( ((int *)&m_visBytes)[1] ); + + + // drawindexes + swapBlock( (int *)&m_drawIndexes[0], m_numDrawIndexes * sizeof( m_drawIndexes[0] ) ); + + // drawsurfs + swapBlock( (int *)&m_drawSurfaces[0], m_numDrawSurfaces * sizeof( m_drawSurfaces[0] ) ); + +} + + + + + +bool BspLoader::findVectorByName(float* outvec,const char* name) +{ + const char *cl; + BSPVector3 origin; + + bool found = false; + + parseEntities(); + + for ( int i = 1; i < m_num_entities; i++ ) { + cl = getValueForKey (&m_entities[i], "classname"); + if ( !strcmp( cl, "info_player_start" ) ) { + getVectorForKey( &m_entities[i], "origin", origin ); + found = true; + break; + } + if ( !strcmp( cl, "info_player_deathmatch" ) ) { + getVectorForKey( &m_entities[i], "origin", origin ); + found = true; + break; + } + } + + if (found) + { + outvec[0] = origin[0]; + outvec[1] = origin[1]; + outvec[2] = origin[2]; + } + return found; +} + + + +const BSPEntity * BspLoader::getEntityByValue( const char* name, const char* value) +{ + const BSPEntity* entity = NULL; + + for ( int i = 1; i < m_num_entities; i++ ) { + + const BSPEntity& ent = m_entities[i]; + + const char* cl = getValueForKey (&m_entities[i], name); + if ( !strcmp( cl, value ) ) { + entity = &ent; + break; + } + } + return entity; +} + diff --git a/Demos/BspDemo/BspLoader.h b/Demos/BspDemo/BspLoader.h new file mode 100644 index 0000000..b7fc302 --- /dev/null +++ b/Demos/BspDemo/BspLoader.h @@ -0,0 +1,295 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU bteral Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU bteral Public License for more details. + +You should have received a copy of the GNU bteral Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + + + +#ifndef BSP_LOADER_H +#define BSP_LOADER_H + +#include "LinearMath/btAlignedObjectArray.h" + +#define BSPMAXTOKEN 1024 +#define BSPMAX_KEY 32 +#define BSPMAX_VALUE 1024 +#define BSPCONTENTS_SOLID 1 +#define BSPCONTENTS_AREAPORTAL 0x8000 +#define BSPLUMP_ENTITIES 0 +#define BSPLUMP_SHADERS 1 +#define BSPLUMP_PLANES 2 +#define BSPLUMP_NODES 3 +#define BSPLUMP_LEAFS 4 +#define BSPLUMP_LEAFSURFACES 5 +#define BSPLUMP_LEAFBRUSHES 6 +#define LUMP_MODELS 7 +#define LUMP_BRUSHES 8 +#define LUMP_BRUSHSIDES 9 +#define LUMP_DRAWVERTS 10 +#define LUMP_DRAWINDEXES 11 +#define LUMP_SURFACES 13 +#define LUMP_LIGHTMAPS 14 +#define LUMP_LIGHTGRID 15 +#define LUMP_VISIBILITY 16 +#define HEADER_LUMPS 17 +#define MAX_QPATH 64 + + + +typedef struct { + int fileofs, filelen; +} BSPLump; + +typedef float BSPVector3[3]; + +typedef struct { + int ident; + int version; + + BSPLump lumps[HEADER_LUMPS]; +} BSPHeader; + + +typedef struct { + float mins[3], maxs[3]; + int firstSurface, numSurfaces; + int firstBrush, numBrushes; +} BSPModel; + +typedef struct { + char shader[MAX_QPATH]; + int surfaceFlags; + int contentFlags; +} BSPShader; + +typedef struct { + float normal[3]; + float dist; +} BSPPlane; + +typedef struct { + int planeNum; + int children[2]; + int mins[3]; + int maxs[3]; +} BSPNode; + +typedef struct { + int cluster; + int area; + + int mins[3]; + int maxs[3]; + + int firstLeafSurface; + int numLeafSurfaces; + + int firstLeafBrush; + int numLeafBrushes; +} BSPLeaf; + +typedef struct { + int planeNum; + int shaderNum; +} BSPBrushSide; + +typedef struct { + int firstSide; + int numSides; + int shaderNum; +} BSPBrush; + + + + +typedef struct BSPPair { + struct BSPPair *next; + char *key; + char *value; +} BSPKeyValuePair; + +typedef struct { + BSPVector3 origin; + struct bspbrush_s *brushes; + struct parseMesh_s *patches; + int firstDrawSurf; + BSPKeyValuePair *epairs; +} BSPEntity; + +typedef enum { + MST_BAD, + MST_PLANAR, + MST_PATCH, + MST_TRIANGLE_SOUP, + MST_FLARE +} BSPMapSurface; + +typedef struct { + int shaderNum; + int fogNum; + int surfaceType; + + int firstVert; + int numVerts; + + int firstIndex; + int numIndexes; + + int lightmapNum; + int lightmapX, lightmapY; + int lightmapWidth, lightmapHeight; + + BSPVector3 lightmapOrigin; + BSPVector3 lightmapVecs[3]; + + int patchWidth; + int patchHeight; +} BSPSurface; + + + +///GPL code from IdSofware to parse a Quake 3 BSP file +///check that your platform define __BIG_ENDIAN__ correctly (in BspLoader.cpp) +class BspLoader +{ + int m_Endianness; + + public: + + BspLoader(); + + bool loadBSPFile( void* memoryBuffer); + + const char* getValueForKey( const BSPEntity *ent, const char *key ) const; + + bool getVectorForKey( const BSPEntity *ent, const char *key, BSPVector3 vec ); + + float getFloatForKey( const BSPEntity *ent, const char *key ); + + void parseEntities( void ); + + bool findVectorByName(float* outvec,const char* name); + + const BSPEntity * getEntityByValue( const char* name, const char* value); + + + protected: + + void parseFromMemory (char *buffer, int size); + + + + bool isEndOfScript (bool crossline); + + bool getToken (bool crossline); + + char *copystring(const char *s); + + void stripTrailing( char *e ); + + BSPKeyValuePair * parseEpair( void ); + + bool parseEntity( void ); + + short isLittleShort (short l); + int isLittleLong (int l); + float isLittleFloat (float l); + + int isBigLong (int l); + short isBigShort (short l); + float isBigFloat (float l); + + void swapBlock( int *block, int sizeOfBlock ); + + int copyLump( BSPHeader *header, int lump, void *dest, int size ); + + void swapBSPFile( void ); + + + + + public: //easier for conversion + int m_num_entities; + btAlignedObjectArray m_entities; + + int m_nummodels; + btAlignedObjectArray m_dmodels; + + int m_numShaders; + btAlignedObjectArray m_dshaders; + + int m_entdatasize; + btAlignedObjectArray m_dentdata; + + int m_numleafs; + btAlignedObjectArray m_dleafs; + + int m_numplanes; + btAlignedObjectArray m_dplanes; + + int m_numnodes; + btAlignedObjectArray m_dnodes; + + int m_numleafsurfaces; + btAlignedObjectArray m_dleafsurfaces; + + int m_numleafbrushes; + btAlignedObjectArray m_dleafbrushes; + + int m_numbrushes; + btAlignedObjectArray m_dbrushes; + + int m_numbrushsides; + btAlignedObjectArray m_dbrushsides; + + int m_numLightBytes; + btAlignedObjectArray m_lightBytes; + + int m_numGridPoints; + btAlignedObjectArray m_gridData; + + int m_numVisBytes; + btAlignedObjectArray m_visBytes; + + + int m_numDrawIndexes; + btAlignedObjectArray m_drawIndexes; + + int m_numDrawSurfaces; + btAlignedObjectArray m_drawSurfaces; + + enum + { + BSP_LITTLE_ENDIAN = 0, + BSP_BIG_ENDIAN = 1 + }; + + //returns machines big endian / little endian + // + int getMachineEndianness(); + + inline int machineEndianness() + { + return m_Endianness; + } + +}; + +#endif //BSP_LOADER_H diff --git a/Demos/BspDemo/CMakeLists.txt b/Demos/BspDemo/CMakeLists.txt new file mode 100644 index 0000000..6105a18 --- /dev/null +++ b/Demos/BspDemo/CMakeLists.txt @@ -0,0 +1,60 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# You shouldn't have to modify anything below this line +######################################################## + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppBspPhysicsDemo + main.cpp + BspDemo.cpp + BspLoader.cpp + BspConverter.cpp +) + + +IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppBspPhysicsDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppBspPhysicsDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF(WIN32) + + + +IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( + TARGET AppBspPhysicsDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/BspDemo.bsp ${CMAKE_CURRENT_BINARY_DIR} + ) +ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppBspPhysicsDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppBspPhysicsDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppBspPhysicsDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/BspDemo/main.cpp b/Demos/BspDemo/main.cpp new file mode 100644 index 0000000..e957fa1 --- /dev/null +++ b/Demos/BspDemo/main.cpp @@ -0,0 +1,59 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "BspDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" + +char* makeExeToBspFilename(const char* lpCmdLine); +char* getLastFileName(); + + +int main(int argc,char** argv) +{ + + BspDemo* bspDemo = new BspDemo(); + + const char* bspfilename = "BspDemo.bsp"; + + printf("argc=%i\n",argc); + { + for (int i=0;i1) + { + bspfilename = argv[1]; + } + + GLDebugDrawer gDebugDrawer; + + // Enrico: TODO: Should change parameter type of initPhysics() to std::string or at least const char * + bspDemo->initPhysics((char*)bspfilename); + + bspDemo->getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + + + return glutmain(argc, argv,640,480,"Bullet Quake BSP Physics Viewer http://bulletphysics.org",bspDemo); +} + diff --git a/Demos/BulletDinoDemo/BulletDino.c b/Demos/BulletDinoDemo/BulletDino.c new file mode 100644 index 0000000..146f28d --- /dev/null +++ b/Demos/BulletDinoDemo/BulletDino.c @@ -0,0 +1,996 @@ + +/* This demo has been modified to use the Bullet C-API. + The C-API is minimal, and will develop based on developer feedback. + The C++ API is recommended, and compatible with the C-API. +*/ + +/* Copyright (c) Mark J. Kilgard, 1994, 1997. */ + +/* This program is freely distributable without licensing fees + and is provided without guarantee or warrantee expressed or + implied. This program is -not- in the public domain. */ + +/* Example for PC game developers to show how to *combine* texturing, + reflections, and projected shadows all in real-time with OpenGL. + Robust reflections use stenciling. Robust projected shadows + use both stenciling and polygon offset. PC game programmers + should realize that neither stenciling nor polygon offset are + supported by Direct3D, so these real-time rendering algorithms + are only really viable with OpenGL. + + The program has modes for disabling the stenciling and polygon + offset uses. It is worth running this example with these features + toggled off so you can see the sort of artifacts that result. + + Notice that the floor texturing, reflections, and shadowing + all co-exist properly. */ + +/* When you run this program: Left mouse button controls the + view. Middle mouse button controls light position (left & + right rotates light around dino; up & down moves light + position up and down). Right mouse button pops up menu. */ + +/* Check out the comments in the "redraw" routine to see how the + reflection blending and surface stenciling is done. You can + also see in "redraw" how the projected shadows are rendered, + including the use of stenciling and polygon offset. */ + +/* This program is derived from glutdino.c */ + +/* Compile: cc -o dinoshade dinoshade.c -lglut -lGLU -lGL -lXmu -lXext -lX11 -lm */ + +#include +#include +#include +#include /* for cos(), sin(), and sqrt() */ +#ifdef WIN32//for glut.h +#include +#endif + +#ifndef WIN32 +#ifndef CALLBACK +#define CALLBACK +#endif +#endif + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#define GLVOIDPTR GLvoid(*)() +#else +#include +#include +#define GLVOIDPTR void(CALLBACK*)() +#endif + +/* Some files do not define M_PI... */ +#ifndef M_PI +#define M_PI 3.14159265 +#endif + + +//#include "../../include/Bullet-C-Api.h" +#include "Bullet-C-Api.h" + + + +plPhysicsSdkHandle physicsSdk=0; +plDynamicsWorldHandle dynamicsWorld=0; +plRigidBodyHandle floorRigidBody; +plRigidBodyHandle dinoRigidBody; + +/* Variable controlling various rendering modes. */ +static int stencilReflection = 1, stencilShadow = 1, offsetShadow = 1; +static int renderShadow = 1, renderDinosaur = 1, renderReflection = 1; +static int linearFiltering = 0, useMipmaps = 0, useTexture = 1; +static int reportSpeed = 0; +static int animation = 1; +static GLboolean lightSwitch = GL_TRUE; +static int directionalLight = 1; +static int forceExtension = 0; + +/* Time varying or user-controled variables. */ +static float jump = 0.0; +static float lightAngle = 0.0, lightHeight = 20; +GLfloat angle = -150; /* in degrees */ +GLfloat angle2 = 30; /* in degrees */ + +int moving, startx, starty; +int lightMoving = 0, lightStartX, lightStartY; + +enum { + MISSING, EXTENSION, ONE_DOT_ONE +}; +int polygonOffsetVersion; + +static GLdouble bodyWidth = 3.0; +/* *INDENT-OFF* */ +static GLfloat body[][2] = { {0, 3}, {1, 1}, {5, 1}, {8, 4}, {10, 4}, {11, 5}, + {11, 11.5}, {13, 12}, {13, 13}, {10, 13.5}, {13, 14}, {13, 15}, {11, 16}, + {8, 16}, {7, 15}, {7, 13}, {8, 12}, {7, 11}, {6, 6}, {4, 3}, {3, 2}, + {1, 2} }; +static GLfloat arm[][2] = { {8, 10}, {9, 9}, {10, 9}, {13, 8}, {14, 9}, {16, 9}, + {15, 9.5}, {16, 10}, {15, 10}, {15.5, 11}, {14.5, 10}, {14, 11}, {14, 10}, + {13, 9}, {11, 11}, {9, 11} }; +static GLfloat leg[][2] = { {8, 6}, {8, 4}, {9, 3}, {9, 2}, {8, 1}, {8, 0.5}, {9, 0}, + {12, 0}, {10, 1}, {10, 2}, {12, 4}, {11, 6}, {10, 7}, {9, 7} }; +static GLfloat eye[][2] = { {8.75, 15}, {9, 14.7}, {9.6, 14.7}, {10.1, 15}, + {9.6, 15.25}, {9, 15.25} }; +static GLfloat lightPosition[4]; +static GLfloat lightColor[] = {0.8, 1.0, 0.8, 1.0}; /* green-tinted */ +static GLfloat skinColor[] = {0.1, 1.0, 0.1, 1.0}, eyeColor[] = {1.0, 0.2, 0.2, 1.0}; +/* *INDENT-ON* */ + +/* Nice floor texture tiling pattern. */ +static char *circles[] = { + "....xxxx........", + "..xxxxxxxx......", + ".xxxxxxxxxx.....", + ".xxx....xxx.....", + "xxx......xxx....", + "xxx......xxx....", + "xxx......xxx....", + "xxx......xxx....", + ".xxx....xxx.....", + ".xxxxxxxxxx.....", + "..xxxxxxxx......", + "....xxxx........", + "................", + "................", + "................", + "................", +}; + +static void +makeFloorTexture(void) +{ + GLubyte floorTexture[16][16][3]; + GLubyte *loc; + int s, t; + loc=0; + + /* Setup RGB image for the texture. */ + loc = (GLubyte*) floorTexture; + for (t = 0; t < 16; t++) { + for (s = 0; s < 16; s++) { + if (circles[t][s] == 'x') { + /* Nice green. */ + loc[0] = 0x1f; + loc[1] = 0x8f; + loc[2] = 0x1f; + } else { + /* Light gray. */ + loc[0] = 0xaa; + loc[1] = 0xaa; + loc[2] = 0xaa; + } + loc += 3; + } + } + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + if (useMipmaps) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_LINEAR); + gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 16, 16, + GL_RGB, GL_UNSIGNED_BYTE, floorTexture); + } else { + if (linearFiltering) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + glTexImage2D(GL_TEXTURE_2D, 0, 3, 16, 16, 0, + GL_RGB, GL_UNSIGNED_BYTE, floorTexture); + } +} + +enum { + X, Y, Z, W +}; +enum { + A, B, C, D +}; + +/* Create a matrix that will project the desired shadow. */ +void +shadowMatrix(GLfloat shadowMat[4][4], + GLfloat groundplane[4], + GLfloat lightpos[4]) +{ + GLfloat dot; + + /* Find dot product between light position vector and ground plane normal. */ + dot = groundplane[X] * lightpos[X] + + groundplane[Y] * lightpos[Y] + + groundplane[Z] * lightpos[Z] + + groundplane[W] * lightpos[W]; + + shadowMat[0][0] = dot - lightpos[X] * groundplane[X]; + shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y]; + shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z]; + shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W]; + + shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X]; + shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y]; + shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z]; + shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W]; + + shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X]; + shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y]; + shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z]; + shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W]; + + shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X]; + shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y]; + shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z]; + shadowMat[3][3] = dot - lightpos[W] * groundplane[W]; + +} + +/* Find the plane equation given 3 points. */ +void +findPlane(GLfloat plane[4], + GLfloat v0[3], GLfloat v1[3], GLfloat v2[3]) +{ + GLfloat vec0[3], vec1[3]; + + /* Need 2 vectors to find cross product. */ + vec0[X] = v1[X] - v0[X]; + vec0[Y] = v1[Y] - v0[Y]; + vec0[Z] = v1[Z] - v0[Z]; + + vec1[X] = v2[X] - v0[X]; + vec1[Y] = v2[Y] - v0[Y]; + vec1[Z] = v2[Z] - v0[Z]; + + /* find cross product to get A, B, and C of plane equation */ + plane[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y]; + plane[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]); + plane[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X]; + + plane[D] = -(plane[A] * v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]); +} + +void +extrudeSolidFromPolygon(GLfloat data[][2], unsigned int dataSize, + GLdouble thickness, GLuint side, GLuint edge, GLuint whole) +{ + static GLUtriangulatorObj *tobj = NULL; + GLdouble vertex[3], dx, dy, len; + int i; + int count = dataSize / (2 * sizeof(GLfloat)); + + if (tobj == NULL) { + tobj = gluNewTess(); /* create and initialize a GLU + polygon * * tesselation object */ + gluTessCallback(tobj, (GLenum)GLU_BEGIN, (GLVOIDPTR)glBegin); + gluTessCallback(tobj, (GLenum)GLU_VERTEX, (GLVOIDPTR)glVertex2fv); /* semi-tricky */ + gluTessCallback(tobj, (GLenum)GLU_END, (GLVOIDPTR)glEnd); + } + glNewList(side, GL_COMPILE); + glShadeModel(GL_SMOOTH); /* smooth minimizes seeing + tessellation */ + gluBeginPolygon(tobj); + for (i = 0; i < count; i++) { + vertex[0] = data[i][0]; + vertex[1] = data[i][1]; + vertex[2] = 0; + gluTessVertex(tobj, vertex, data[i]); + } + gluEndPolygon(tobj); + glEndList(); + glNewList(edge, GL_COMPILE); + glShadeModel(GL_FLAT); /* flat shade keeps angular hands + from being "smoothed" */ + glBegin(GL_QUAD_STRIP); + for (i = 0; i <= count; i++) { + /* mod function handles closing the edge */ + glVertex3f(data[i % count][0], data[i % count][1], 0.0); + glVertex3f(data[i % count][0], data[i % count][1], thickness); + /* Calculate a unit normal by dividing by Euclidean + distance. We * could be lazy and use + glEnable(GL_NORMALIZE) so we could pass in * arbitrary + normals for a very slight performance hit. */ + dx = data[(i + 1) % count][1] - data[i % count][1]; + dy = data[i % count][0] - data[(i + 1) % count][0]; + len = sqrt(dx * dx + dy * dy); + glNormal3f(dx / len, dy / len, 0.0); + } + glEnd(); + glEndList(); + glNewList(whole, GL_COMPILE); + glFrontFace(GL_CW); + glCallList(edge); + glNormal3f(0.0, 0.0, -1.0); /* constant normal for side */ + glCallList(side); + glPushMatrix(); + glTranslatef(0.0, 0.0, thickness); + glFrontFace(GL_CCW); + glNormal3f(0.0, 0.0, 1.0); /* opposite normal for other side */ + glCallList(side); + glPopMatrix(); + glEndList(); +} + +/* Enumerants for refering to display lists. */ +typedef enum { + RESERVED, BODY_SIDE, BODY_EDGE, BODY_WHOLE, ARM_SIDE, ARM_EDGE, ARM_WHOLE, + LEG_SIDE, LEG_EDGE, LEG_WHOLE, EYE_SIDE, EYE_EDGE, EYE_WHOLE +} displayLists; + +static void +makeDinosaur(void) +{ + extrudeSolidFromPolygon(body, sizeof(body), bodyWidth, + BODY_SIDE, BODY_EDGE, BODY_WHOLE); + extrudeSolidFromPolygon(arm, sizeof(arm), bodyWidth / 4, + ARM_SIDE, ARM_EDGE, ARM_WHOLE); + extrudeSolidFromPolygon(leg, sizeof(leg), bodyWidth / 2, + LEG_SIDE, LEG_EDGE, LEG_WHOLE); + extrudeSolidFromPolygon(eye, sizeof(eye), bodyWidth + 0.2, + EYE_SIDE, EYE_EDGE, EYE_WHOLE); +} + +static void +drawDinosaur(void) + +{ + plReal matrix[16]; + + glPushMatrix(); + /* Translate the dinosaur to be at (0,8,0). */ + + plGetOpenGLMatrix(dinoRigidBody,matrix); +// plGetPosition(dinoRigidBody,dinoWorldPos); + // glTranslatef(-8, 0, -bodyWidth / 2); + //glTranslatef(0.0, jump, 0.0); +// glTranslatef(dinoWorldPos[0],dinoWorldPos[1],dinoWorldPos[2]); + +#ifdef BT_USE_DOUBLE_PRECISION + glMultMatrixd(matrix); +#else + glMultMatrixf(matrix); +#endif +// glutSolidCube(15); + glTranslatef(-8.5, -8.5, 0); + + glMaterialfv(GL_FRONT, GL_DIFFUSE, skinColor); + glCallList(BODY_WHOLE); + glTranslatef(0.0, 0.0, bodyWidth); + glCallList(ARM_WHOLE); + glCallList(LEG_WHOLE); + glTranslatef(0.0, 0.0, -bodyWidth - bodyWidth / 4); + glCallList(ARM_WHOLE); + glTranslatef(0.0, 0.0, -bodyWidth / 4); + glCallList(LEG_WHOLE); + glTranslatef(0.0, 0.0, bodyWidth / 2 - 0.1); + glMaterialfv(GL_FRONT, GL_DIFFUSE, eyeColor); + glCallList(EYE_WHOLE); + + + glPopMatrix(); +} + +static GLfloat floorVertices[4][3] = { + { -20.0, 0.0, 20.0 }, + { 20.0, 0.0, 20.0 }, + { 20.0, 0.0, -20.0 }, + { -20.0, 0.0, -20.0 }, +}; + +/* Draw a floor (possibly textured). */ +static void +drawFloor(void) +{ + glDisable(GL_LIGHTING); + + if (useTexture) { + glEnable(GL_TEXTURE_2D); + } + + glBegin(GL_QUADS); + glTexCoord2f(0.0, 0.0); + glVertex3fv(floorVertices[0]); + glTexCoord2f(0.0, 16.0); + glVertex3fv(floorVertices[1]); + glTexCoord2f(16.0, 16.0); + glVertex3fv(floorVertices[2]); + glTexCoord2f(16.0, 0.0); + glVertex3fv(floorVertices[3]); + glEnd(); + + if (useTexture) { + glDisable(GL_TEXTURE_2D); + } + + glEnable(GL_LIGHTING); +} + +static GLfloat floorPlane[4]; +static GLfloat floorShadow[4][4]; + +static void +redraw(void) +{ + int start = 0, end = 0 ; + + if (reportSpeed) { + start = glutGet(GLUT_ELAPSED_TIME); + } + + /* Clear; default stencil clears to zero. */ + if ((stencilReflection && renderReflection) || (stencilShadow && renderShadow)) { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + } else { + /* Avoid clearing stencil when not using it. */ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + + /* Reposition the light source. */ + lightPosition[0] = 12*cos(lightAngle); + lightPosition[1] = lightHeight; + lightPosition[2] = 12*sin(lightAngle); + if (directionalLight) { + lightPosition[3] = 0.0; + } else { + lightPosition[3] = 1.0; + } + + shadowMatrix(floorShadow, floorPlane, lightPosition); + + glPushMatrix(); + /* Perform scene rotations based on user mouse input. */ + glRotatef(angle2, 1.0, 0.0, 0.0); + glRotatef(angle, 0.0, 1.0, 0.0); + + /* Tell GL new light source position. */ + glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); + + if (renderReflection) { + if (stencilReflection) { + /* We can eliminate the visual "artifact" of seeing the "flipped" + dinosaur underneath the floor by using stencil. The idea is + draw the floor without color or depth update but so that + a stencil value of one is where the floor will be. Later when + rendering the dinosaur reflection, we will only update pixels + with a stencil value of 1 to make sure the reflection only + lives on the floor, not below the floor. */ + + /* Don't update color or depth. */ + glDisable(GL_DEPTH_TEST); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + /* Draw 1 into the stencil buffer. */ + glEnable(GL_STENCIL_TEST); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + glStencilFunc(GL_ALWAYS, 1, 0xffffffff); + + /* Now render floor; floor pixels just get their stencil set to 1. */ + drawFloor(); + + /* Re-enable update of color and depth. */ + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glEnable(GL_DEPTH_TEST); + + /* Now, only render where stencil is set to 1. */ + glStencilFunc(GL_EQUAL, 1, 0xffffffff); /* draw if ==1 */ + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + } + + glPushMatrix(); + + /* The critical reflection step: Reflect dinosaur through the floor + (the Y=0 plane) to make a relection. */ + glScalef(1.0, -1.0, 1.0); + + /* Reflect the light position. */ + glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); + + /* To avoid our normals getting reversed and hence botched lighting + on the reflection, turn on normalize. */ + glEnable(GL_NORMALIZE); + glCullFace(GL_FRONT); + + /* Draw the reflected dinosaur. */ + drawDinosaur(); + + /* Disable noramlize again and re-enable back face culling. */ + glDisable(GL_NORMALIZE); + glCullFace(GL_BACK); + + glPopMatrix(); + + /* Switch back to the unreflected light position. */ + glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); + + if (stencilReflection) { + glDisable(GL_STENCIL_TEST); + } + } + + /* Back face culling will get used to only draw either the top or the + bottom floor. This let's us get a floor with two distinct + appearances. The top floor surface is reflective and kind of red. + The bottom floor surface is not reflective and blue. */ + + /* Draw "bottom" of floor in blue. */ + glFrontFace(GL_CW); /* Switch face orientation. */ + glColor4f(0.1, 0.1, 0.7, 1.0); + drawFloor(); + glFrontFace(GL_CCW); + + if (renderShadow) { + if (stencilShadow) { + /* Draw the floor with stencil value 3. This helps us only + draw the shadow once per floor pixel (and only on the + floor pixels). */ + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 3, 0xffffffff); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + } + } + + /* Draw "top" of floor. Use blending to blend in reflection. */ + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4f(0.7, 0.0, 0.0, 0.3); + glColor4f(1.0, 1.0, 1.0, 0.3); + drawFloor(); + glDisable(GL_BLEND); + + if (renderDinosaur) { + /* Draw "actual" dinosaur, not its reflection. */ + drawDinosaur(); + } + + if (renderShadow) { + + /* Render the projected shadow. */ + + if (stencilShadow) { + + /* Now, only render where stencil is set above 2 (ie, 3 where + the top floor is). Update stencil with 2 where the shadow + gets drawn so we don't redraw (and accidently reblend) the + shadow). */ + glStencilFunc(GL_LESS, 2, 0xffffffff); /* draw if ==1 */ + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + } + + /* To eliminate depth buffer artifacts, we use polygon offset + to raise the depth of the projected shadow slightly so + that it does not depth buffer alias with the floor. */ + if (offsetShadow) { + switch (polygonOffsetVersion) { + case EXTENSION: +#ifdef GL_VERSION_1_1 + case ONE_DOT_ONE: + glEnable(GL_POLYGON_OFFSET_FILL); + break; +#endif + case MISSING: + /* Oh well. */ + break; + } + } + + /* Render 50% black shadow color on top of whatever the + floor appareance is. */ + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_LIGHTING); /* Force the 50% black. */ + glColor4f(0.0, 0.0, 0.0, 0.5); + + glPushMatrix(); + /* Project the shadow. */ + glMultMatrixf((GLfloat *) floorShadow); + drawDinosaur(); + glPopMatrix(); + + glDisable(GL_BLEND); + glEnable(GL_LIGHTING); + + if (offsetShadow) { + switch (polygonOffsetVersion) { +#ifdef GL_VERSION_1_1 + case ONE_DOT_ONE: + glDisable(GL_POLYGON_OFFSET_FILL); + break; +#endif + case MISSING: + /* Oh well. */ + break; + } + } + if (stencilShadow) { + glDisable(GL_STENCIL_TEST); + } + } + + glPushMatrix(); + glDisable(GL_LIGHTING); + glColor3f(1.0, 1.0, 0.0); + if (directionalLight) { + /* Draw an arrowhead. */ + glDisable(GL_CULL_FACE); + glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]); + glRotatef(lightAngle * -180.0 / M_PI, 0, 1, 0); + glRotatef(atan(lightHeight/12) * 180.0 / M_PI, 0, 0, 1); + glBegin(GL_TRIANGLE_FAN); + glVertex3f(0, 0, 0); + glVertex3f(2, 1, 1); + glVertex3f(2, -1, 1); + glVertex3f(2, -1, -1); + glVertex3f(2, 1, -1); + glVertex3f(2, 1, 1); + glEnd(); + /* Draw a white line from light direction. */ + glColor3f(1.0, 1.0, 1.0); + glBegin(GL_LINES); + glVertex3f(0, 0, 0); + glVertex3f(5, 0, 0); + glEnd(); + glEnable(GL_CULL_FACE); + } else { + /* Draw a yellow ball at the light source. */ + glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]); + glutSolidSphere(1.0, 5, 5); + } + glEnable(GL_LIGHTING); + glPopMatrix(); + + glPopMatrix(); + + if (reportSpeed) { + glFinish(); + end = glutGet(GLUT_ELAPSED_TIME); + printf("Speed %.3g frames/sec (%d ms)\n", 1000.0/(end-start), end-start); + } + + glutSwapBuffers(); +} + +/* ARGSUSED2 */ +static void +mouse(int button, int state, int x, int y) +{ + if (button == GLUT_LEFT_BUTTON) { + if (state == GLUT_DOWN) { + moving = 1; + startx = x; + starty = y; + } + if (state == GLUT_UP) { + moving = 0; + } + } + if (button == GLUT_MIDDLE_BUTTON) { + if (state == GLUT_DOWN) { + lightMoving = 1; + lightStartX = x; + lightStartY = y; + } + if (state == GLUT_UP) { + lightMoving = 0; + } + } +} + +/* ARGSUSED1 */ +static void +motion(int x, int y) +{ + if (moving) { + angle = angle + (x - startx); + angle2 = angle2 + (y - starty); + startx = x; + starty = y; + glutPostRedisplay(); + } + if (0){//lightMoving) { + lightAngle += (x - lightStartX)/40.0; + lightHeight += (lightStartY - y)/20.0; + lightStartX = x; + lightStartY = y; + glutPostRedisplay(); + } +} + +/* Advance time varying state when idle callback registered. */ +static void +idle(void) +{ + static float time = 0.0; + static float prevtime = 0.0; + float dtime; + prevtime = time; + + time = glutGet(GLUT_ELAPSED_TIME) / 500.0; + dtime = time - prevtime; + + jump = 4.0 * fabs(sin(time)*0.5); + if (!lightMoving) { + lightAngle = time; + } + + if (dynamicsWorld) + plStepSimulation(dynamicsWorld,dtime); + + glutPostRedisplay(); +} + +enum { + M_NONE, M_MOTION, M_LIGHT, M_TEXTURE, M_SHADOWS, M_REFLECTION, M_DINOSAUR, + M_STENCIL_REFLECTION, M_STENCIL_SHADOW, M_OFFSET_SHADOW, + M_POSITIONAL, M_DIRECTIONAL, M_PERFORMANCE +}; + +static void +controlLights(int value) +{ + switch (value) { + case M_NONE: + return; + case M_MOTION: + animation = 1 - animation; + if (animation) { + glutIdleFunc(idle); + } else { + glutIdleFunc(NULL); + } + break; + case M_LIGHT: + lightSwitch = !lightSwitch; + if (lightSwitch) { + glEnable(GL_LIGHT0); + } else { + glDisable(GL_LIGHT0); + } + break; + case M_TEXTURE: + useTexture = !useTexture; + break; + case M_SHADOWS: + renderShadow = 1 - renderShadow; + break; + case M_REFLECTION: + renderReflection = 1 - renderReflection; + break; + case M_DINOSAUR: + renderDinosaur = 1 - renderDinosaur; + break; + case M_STENCIL_REFLECTION: + stencilReflection = 1 - stencilReflection; + break; + case M_STENCIL_SHADOW: + stencilShadow = 1 - stencilShadow; + break; + case M_OFFSET_SHADOW: + offsetShadow = 1 - offsetShadow; + break; + case M_POSITIONAL: + directionalLight = 0; + break; + case M_DIRECTIONAL: + directionalLight = 1; + break; + case M_PERFORMANCE: + reportSpeed = 1 - reportSpeed; + break; + } + glutPostRedisplay(); +} + +/* When not visible, stop animating. Restart when visible again. */ +static void +visible(int vis) +{ + if (vis == GLUT_VISIBLE) { + if (animation) + glutIdleFunc(idle); + } else { + if (!animation) + glutIdleFunc(NULL); + } +} + +/* Press any key to redraw; good when motion stopped and + performance reporting on. */ +/* ARGSUSED */ +static void +key(unsigned char c, int x, int y) +{ + if (c == 27) { + exit(0); /* IRIS GLism, Escape quits. */ + } + glutPostRedisplay(); +} + +/* Press any key to redraw; good when motion stopped and + performance reporting on. */ +/* ARGSUSED */ +static void +special(int k, int x, int y) +{ + glutPostRedisplay(); +} + +static int +supportsOneDotOne(void) +{ + const char *version; + int major, minor; + + version = (char *) glGetString(GL_VERSION); + if (sscanf(version, "%d.%d", &major, &minor) == 2) + return ((major > 1) || (major >= 1 && minor >= 1)); + return 0; /* OpenGL version string malformed! */ +} + + +int +main(int argc, char **argv) +{ + int i; + plCollisionShapeHandle floorShape; + plCollisionShapeHandle dinoShape,dinoChildShape; + plVector3 floorPos,childPos; + plVector3 dinoPos; + plQuaternion childOrn,dinoOrient; + + void* user_data=NULL; + + physicsSdk = plNewBulletSdk(); + dynamicsWorld = plCreateDynamicsWorld(physicsSdk); + + //create ground plane + + floorShape = plNewConvexHullShape(); + + for (i=0;i<4;i++) + { +// floorVertices + plAddVertex(floorShape,floorVertices[i][0],floorVertices[i][1],floorVertices[i][2]); + } + + + floorShape = plNewBoxShape(120,0,120); + + floorRigidBody = plCreateRigidBody(user_data,0.f,floorShape); + floorPos[0] = 0; + floorPos[1] = 0; + floorPos[2] = 0; + + plSetPosition(floorRigidBody,floorPos); + plAddRigidBody(dynamicsWorld,floorRigidBody); + + //create dino rigidbody + dinoChildShape = plNewBoxShape(8.5,8.5,8.5); + dinoShape = plNewCompoundShape(); + childPos[0] = 0; + childPos[1] = 0; + childPos[2] = 0; + childOrn[0] = 0; + childOrn[1] = 0; + childOrn[2] = 0; + childOrn[3] = 1; + + plAddChildShape(dinoShape,dinoChildShape,childPos,childOrn); + + dinoPos[0] = -10; dinoPos[1] = 28; dinoPos[2] = 0; + dinoRigidBody = plCreateRigidBody(0,1.0,dinoShape); + plSetPosition(dinoRigidBody,dinoPos); + plSetEuler(0,0,3.15*0.20,dinoOrient); + plSetOrientation(dinoRigidBody,dinoOrient); + + plAddRigidBody(dynamicsWorld,dinoRigidBody); + + printf("BulletDino\n"); + glutInit(&argc, argv); + + for (i=1; i=2 rgb double depth"); +#endif + + glutCreateWindow("Shadowy Leapin' Lizards"); + + if (glutGet(GLUT_WINDOW_STENCIL_SIZE) <= 1) { + printf("dinoshade: Sorry, I need at least 2 bits of stencil.\n"); + exit(1); + } + + /* Register GLUT callbacks. */ + glutDisplayFunc(redraw); + glutMouseFunc(mouse); + glutMotionFunc(motion); + glutVisibilityFunc(visible); + glutKeyboardFunc(key); + glutSpecialFunc(special); + + glutCreateMenu(controlLights); + + glutAddMenuEntry("Toggle motion", M_MOTION); + glutAddMenuEntry("-----------------------", M_NONE); + glutAddMenuEntry("Toggle light", M_LIGHT); + glutAddMenuEntry("Toggle texture", M_TEXTURE); + glutAddMenuEntry("Toggle shadows", M_SHADOWS); + glutAddMenuEntry("Toggle reflection", M_REFLECTION); + glutAddMenuEntry("Toggle dinosaur", M_DINOSAUR); + glutAddMenuEntry("-----------------------", M_NONE); + glutAddMenuEntry("Toggle reflection stenciling", M_STENCIL_REFLECTION); + glutAddMenuEntry("Toggle shadow stenciling", M_STENCIL_SHADOW); + glutAddMenuEntry("Toggle shadow offset", M_OFFSET_SHADOW); + glutAddMenuEntry("----------------------", M_NONE); + glutAddMenuEntry("Positional light", M_POSITIONAL); + glutAddMenuEntry("Directional light", M_DIRECTIONAL); + glutAddMenuEntry("-----------------------", M_NONE); + glutAddMenuEntry("Toggle performance", M_PERFORMANCE); + glutAttachMenu(GLUT_RIGHT_BUTTON); + makeDinosaur(); + +#ifdef GL_VERSION_1_1 + if (supportsOneDotOne() && !forceExtension) { + polygonOffsetVersion = ONE_DOT_ONE; + glPolygonOffset(-2.0, -1.0); + } else +#endif + { + { + polygonOffsetVersion = MISSING; + printf("\ndinoshine: Missing polygon offset.\n"); + printf(" Expect shadow depth aliasing artifacts.\n\n"); + } + } + + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + glLineWidth(3.0); + + glMatrixMode(GL_PROJECTION); + gluPerspective( /* field of view in degree */ 40.0, + /* aspect ratio */ 1.0, + /* Z near */ 20.0, /* Z far */ 100.0); + glMatrixMode(GL_MODELVIEW); + gluLookAt(0.0, 8.0, 60.0, /* eye is at (0,0,30) */ + 0.0, 8.0, 0.0, /* center is at (0,0,0) */ + 0.0, 1.0, 0.); /* up is in postivie Y direction */ + + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); + glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor); + glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1); + glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHTING); + + makeFloorTexture(); + + /* Setup floor plane for projected shadow calculations. */ + findPlane(floorPlane, floorVertices[1], floorVertices[2], floorVertices[3]); + + glutMainLoop(); + + plDeleteDynamicsWorld(dynamicsWorld); + plDeletePhysicsSdk(physicsSdk); + + + return 0; /* ANSI C requires main to return int. */ +} diff --git a/Demos/BulletDinoDemo/CMakeLists.txt b/Demos/BulletDinoDemo/CMakeLists.txt new file mode 100644 index 0000000..3923081 --- /dev/null +++ b/Demos/BulletDinoDemo/CMakeLists.txt @@ -0,0 +1,61 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# This is the variable for Windows. I use this to define the root of my directory structure. +SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/Glut) + +# You shouldn't have to modify anything below this line +######################################################## + + +# This is the shortcut to finding GLU, GLUT and OpenGL if they are properly installed on your system +# This should be the case. +INCLUDE (${CMAKE_ROOT}/Modules/FindGLU.cmake) +INCLUDE (${CMAKE_ROOT}/Modules/FindGLUT.cmake) +INCLUDE (${CMAKE_ROOT}/Modules/FindOpenGL.cmake) + + +IF (WIN32) + # This is the Windows code for which Opengl, and Glut are not properly installed + # since I can't install them I must cheat and copy libraries around + INCLUDE_DIRECTORIES(${GLUT_ROOT}) + # LINK_DIRECTORIES(${GLUT_ROOT}\\lib) + IF (${GLUT_glut_LIBRARY} MATCHES "GLUT_glut_LIBRARY-NOTFOUND") + SET(GLUT_glut_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glut32.lib) + # LINK_LIBRARIES(${GLUT_ROOT}\\lib\\glut32 ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY}) + # TARGET_LINK_LIBRARIES(table ${GLUT_ROOT}\\lib\\glut32) +# +# ADD_CUSTOM_COMMAND(TARGET table POST_BUILD COMMAND copy ${GLUT_ROOT}\\lib\\glut32.dll ${GLUT_ROOT}\\bin\\vs2005\\Debug +# COMMAND copy ${GLUT_ROOT}\\lib\\glut32.dll ${GLUT_ROOT}\\bin\\vs2003\\Debug +# COMMAND copy ${GLUT_ROOT}\\lib\\glut32.dll ${GLUT_ROOT}\\bin\\vs6\\Debug) + ELSE (${GLUT_glut_LIBRARY} MATCHES "GLUT_glut_LIBRARY-NOTFOUND") +# LINK_LIBRARIES(${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY}) +# TARGET_LINK_LIBRARIES(table ${GLUT_glut_LIBRARY}) + ENDIF(${GLUT_glut_LIBRARY} MATCHES "GLUT_glut_LIBRARY-NOTFOUND") +# TARGET_LINK_LIBRARIES(table ${OPENGL_gl_LIBRARY}) +# TARGET_LINK_LIBRARIES(table ${OPENGL_glu_LIBRARY}) +ELSE (WIN32) + # This is the lines for linux. This should always work if everything is installed and working fine. +# SET(CMAKE_BUILD_TYPE Debug) +# SET(CMAKE_CXX_FLAGS_DEBUG "-g") + INCLUDE_DIRECTORIES(/usr/include /usr/local/include ${GLUT_INCLUDE_DIR}) +# TARGET_LINK_LIBRARIES(table ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY}) +# TARGET_LINK_LIBRARIES(checker ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY}) +ENDIF (WIN32) + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( + LibOpenGLSupport LibBulletDynamics LibBulletCollision LibLinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY} +) + +ADD_EXECUTABLE(BulletDino + BulletDino.c +) + diff --git a/Demos/CMakeLists.txt b/Demos/CMakeLists.txt new file mode 100644 index 0000000..e50595d --- /dev/null +++ b/Demos/CMakeLists.txt @@ -0,0 +1,61 @@ + +IF (USE_DX11) + SUBDIRS(DX11ClothDemo) +ENDIF() + +SUBDIRS( HelloWorld ) + + +IF (USE_GLUT) + IF (GLUT_FOUND) + IF(BUILD_CPU_DEMOS) + SET(SharedDemoSubdirs + OpenGL AllBulletDemos ConvexDecompositionDemo + CcdPhysicsDemo ConstraintDemo SliderConstraintDemo GenericJointDemo Raytracer + RagdollDemo ForkLiftDemo BasicDemo VoronoiFractureDemo FractureDemo Box2dDemo BspDemo MovingConcaveDemo VehicleDemo + UserCollisionAlgorithm CharacterDemo SoftDemo HeightFieldFluidDemo + CollisionInterfaceDemo ConcaveConvexcastDemo SimplexDemo DynamicControlDemo + ConvexHullDistance + DoublePrecisionDemo ConcaveDemo CollisionDemo + ContinuousConvexCollision ConcaveRaycastDemo GjkConvexCastDemo + MultiMaterialDemo SerializeDemo InternalEdgeDemo + MultiThreadedDemo + ParticlesOpenCL + OpenCLClothDemo + ) + ELSE() + SET(SharedDemoSubdirs + OpenGL + ) + ENDIF() + + SUBDIRS( + ${SharedDemoSubdirs} + Benchmarks + ThreadingDemo + VectorAdd_OpenCL + ) + ENDIF(GLUT_FOUND) +ELSE (USE_GLUT) + IF (WIN32) + SUBDIRS( + OpenGL + BasicDemo + FractureDemo + Benchmarks + Box2dDemo + CollisionInterfaceDemo + ConcaveDemo + ConstraintDemo + ConvexDecompositionDemo + InternalEdgeDemo + GimpactTestDemo + GenericJointDemo + SerializeDemo + SoftDemo + VectorAdd_OpenCL + VoronoiFractureDemo + ) + ENDIF(WIN32) +ENDIF (USE_GLUT) + diff --git a/Demos/CcdPhysicsDemo/CMakeLists.txt b/Demos/CcdPhysicsDemo/CMakeLists.txt new file mode 100644 index 0000000..515d83c --- /dev/null +++ b/Demos/CcdPhysicsDemo/CMakeLists.txt @@ -0,0 +1,57 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +IF (WIN32) + ADD_EXECUTABLE(AppCcdPhysicsDemo + main.cpp + CcdPhysicsDemo.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) +ELSE() + ADD_EXECUTABLE(AppCcdPhysicsDemo + main.cpp + CcdPhysicsDemo.cpp + ) +ENDIF() + +IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppCcdPhysicsDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppCcdPhysicsDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF(WIN32) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppCcdPhysicsDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppCcdPhysicsDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppCcdPhysicsDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp b/Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp new file mode 100644 index 0000000..4bdfc16 --- /dev/null +++ b/Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp @@ -0,0 +1,413 @@ +/* +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. +*/ + + + +#define CUBE_HALF_EXTENTS 0.5 +#define EXTRA_HEIGHT 1.f + +#include "CcdPhysicsDemo.h" +#include "GlutStuff.h" +#include "GLDebugFont.h" + +///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files. +#include "btBulletDynamicsCommon.h" + +#include //printf debugging +#include "GLDebugDrawer.h" + +#if 0 +extern btAlignedObjectArray debugContacts; +extern btAlignedObjectArray debugNormals; +#endif + +static GLDebugDrawer sDebugDrawer; + + +CcdPhysicsDemo::CcdPhysicsDemo() +:m_ccdMode(USE_CCD) +{ + setDebugMode(btIDebugDraw::DBG_DrawText+btIDebugDraw::DBG_NoHelpText); + setCameraDistance(btScalar(20.)); +} + + +void CcdPhysicsDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //simple dynamics world doesn't handle fixed-time-stepping + float ms = getDeltaTimeMicroseconds(); + + ///step the simulation + if (m_dynamicsWorld) + { + m_dynamicsWorld->stepSimulation(1./60.);//ms / 1000000.f); + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + } + + renderme(); + + displayText(); +#if 0 + for (int i=0;igetDebugDrawer()->drawContactPoint(debugContacts[i],debugNormals[i],0,0,btVector3(1,0,0)); + } +#endif + + glFlush(); + + swapBuffers(); + +} + + +void CcdPhysicsDemo::displayText() +{ + int lineWidth=440; + int xStart = m_glutScreenWidth - lineWidth; + int yStart = 20; + + if((getDebugMode() & btIDebugDraw::DBG_DrawText)!=0) + { + setOrthographicProjection(); + glDisable(GL_LIGHTING); + glColor3f(0, 0, 0); + char buf[124]; + + glRasterPos3f(xStart, yStart, 0); + switch (m_ccdMode) + { + case USE_CCD: + { + sprintf(buf,"Predictive contacts and motion clamping"); + break; + } + case USE_NO_CCD: + { + sprintf(buf,"CCD handling disabled"); + break; + } + default: + { + sprintf(buf,"unknown CCD setting"); + }; + }; + + GLDebugDrawString(xStart,20,buf); + glRasterPos3f(xStart, yStart, 0); + sprintf(buf,"Press 'p' to change CCD mode"); + yStart+=20; + GLDebugDrawString(xStart,yStart,buf); + glRasterPos3f(xStart, yStart, 0); + sprintf(buf,"Press '.' or right mouse to shoot bullets"); + yStart+=20; + GLDebugDrawString(xStart,yStart,buf); + glRasterPos3f(xStart, yStart, 0); + sprintf(buf,"space to restart, h(elp), t(ext), w(ire)"); + yStart+=20; + GLDebugDrawString(xStart,yStart,buf); + + resetPerspectiveProjection(); + glEnable(GL_LIGHTING); + } + +} + + + +void CcdPhysicsDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + displayText(); + + //optional but useful: debug drawing to detect problems + if (m_dynamicsWorld) + { + m_dynamicsWorld->debugDrawWorld(); + } +#if 0 + for (int i=0;igetDebugDrawer()->drawContactPoint(debugContacts[i],debugNormals[i],0,0,btVector3(1,0,0)); + } +#endif + + glFlush(); + swapBuffers(); +} + + + + + +void CcdPhysicsDemo::initPhysics() +{ + setTexturing(true); + setShadows(true); + + m_ShootBoxInitialSpeed = 4000.f; + + + ///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_dispatcher->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE,BOX_SHAPE_PROXYTYPE,m_collisionConfiguration->getCollisionAlgorithmCreateFunc(CONVEX_SHAPE_PROXYTYPE,CONVEX_SHAPE_PROXYTYPE)); + + 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 ->setDebugDrawer(&sDebugDrawer); + m_dynamicsWorld->getSolverInfo().m_splitImpulse=true; + m_dynamicsWorld->getSolverInfo().m_numIterations = 20; + + + if (m_ccdMode==USE_CCD) + { + m_dynamicsWorld->getDispatchInfo().m_useContinuous=true; + } else + { + m_dynamicsWorld->getDispatchInfo().m_useContinuous=false; + } + + m_dynamicsWorld->setGravity(btVector3(0,-10,0)); + + ///create a few basic rigid bodies + btBoxShape* box = new btBoxShape(btVector3(btScalar(110.),btScalar(1.),btScalar(110.))); +// box->initializePolyhedralFeatures(); + btCollisionShape* groundShape = box; + +// btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); + + m_collisionShapes.push_back(groundShape); + m_collisionShapes.push_back(new btCylinderShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS))); + + btTransform groundTransform; + groundTransform.setIdentity(); + //groundTransform.setOrigin(btVector3(5,5,5)); + + //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here: + { + btScalar mass(0.); + + //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) + groundShape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + //add the body to the dynamics world + m_dynamicsWorld->addRigidBody(body); + } + + + { + //create a few dynamic rigidbodies + // Re-using the same collision is better for memory usage and performance + + btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1)); + + //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); + m_collisionShapes.push_back(colShape); + + /// Create Dynamic Objects + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + + //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) + colShape->calculateLocalInertia(mass,localInertia); + + int gNumObjects = 120; + int i; + for (i=0;i3) + { + col=11; + row2 |=1; + } + + btVector3 pos(col*2*CUBE_HALF_EXTENTS + (row2%2)*CUBE_HALF_EXTENTS, + row*2*CUBE_HALF_EXTENTS+CUBE_HALF_EXTENTS+EXTRA_HEIGHT,0); + + trans.setOrigin(pos); + + float mass = 1.f; + + btRigidBody* body = localCreateRigidBody(mass,trans,shape); + + + ///when using m_ccdMode + if (m_ccdMode==USE_CCD) + { + body->setCcdMotionThreshold(CUBE_HALF_EXTENTS); + body->setCcdSweptSphereRadius(0.9*CUBE_HALF_EXTENTS); + } + } + } + +} + +void CcdPhysicsDemo::clientResetScene() +{ + exitPhysics(); + initPhysics(); +} + +void CcdPhysicsDemo::keyboardCallback(unsigned char key, int x, int y) +{ + if (key=='p') + { + switch (m_ccdMode) + { + case USE_CCD: + { + m_ccdMode = USE_NO_CCD; + break; + } + case USE_NO_CCD: + default: + { + m_ccdMode = USE_CCD; + } + }; + clientResetScene(); + } else + { + DemoApplication::keyboardCallback(key,x,y); + } +} + + +void CcdPhysicsDemo::shootBox(const btVector3& destination) +{ + + if (m_dynamicsWorld) + { + float mass = 1.f; + btTransform startTransform; + startTransform.setIdentity(); + btVector3 camPos = getCameraPosition(); + startTransform.setOrigin(camPos); + + setShootBoxShape (); + + + btRigidBody* body = this->localCreateRigidBody(mass, startTransform,m_shootBoxShape); + body->setLinearFactor(btVector3(1,1,1)); + //body->setRestitution(1); + + btVector3 linVel(destination[0]-camPos[0],destination[1]-camPos[1],destination[2]-camPos[2]); + linVel.normalize(); + linVel*=m_ShootBoxInitialSpeed; + + body->getWorldTransform().setOrigin(camPos); + body->getWorldTransform().setRotation(btQuaternion(0,0,0,1)); + body->setLinearVelocity(linVel); + body->setAngularVelocity(btVector3(0,0,0)); + body->setContactProcessingThreshold(1e30); + + ///when using m_ccdMode, disable regular CCD + if (m_ccdMode==USE_CCD) + { + body->setCcdMotionThreshold(CUBE_HALF_EXTENTS); + body->setCcdSweptSphereRadius(0.4f); + } + + } +} + + + + +void CcdPhysicsDemo::exitPhysics() +{ + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;j m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + enum + { + USE_CCD=1, + USE_NO_CCD + }; + int m_ccdMode; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + public: + + CcdPhysicsDemo(); + + virtual ~CcdPhysicsDemo() + { + exitPhysics(); + } + void initPhysics(); + + void exitPhysics(); + + virtual void clientMoveAndDisplay(); + + void displayText(); + + virtual void keyboardCallback(unsigned char key, int x, int y); + + virtual void displayCallback(); + virtual void shootBox(const btVector3& destination); + virtual void clientResetScene(); + + + static DemoApplication* Create() + { + CcdPhysicsDemo* demo = new CcdPhysicsDemo; + demo->myinit(); + demo->initPhysics(); + return demo; + } + + +}; + +#endif //BT_CCD_PHYSICS_DEMO_H + diff --git a/Demos/CcdPhysicsDemo/Makefile.am b/Demos/CcdPhysicsDemo/Makefile.am new file mode 100644 index 0000000..b7c6968 --- /dev/null +++ b/Demos/CcdPhysicsDemo/Makefile.am @@ -0,0 +1,5 @@ +noinst_PROGRAMS=CcdPhysicsDemo + +CcdPhysicsDemo_SOURCES=CcdPhysicsDemo.cpp CcdPhysicsDemo.h main.cpp +CcdPhysicsDemo_CXXFLAGS=-I@top_builddir@/src -I@top_builddir@/Demos/OpenGL $(CXXFLAGS) +CcdPhysicsDemo_LDADD=-L../OpenGL -lbulletopenglsupport -L../../src -lBulletDynamics -lBulletCollision -lLinearMath @opengl_LIBS@ diff --git a/Demos/CcdPhysicsDemo/main.cpp b/Demos/CcdPhysicsDemo/main.cpp new file mode 100644 index 0000000..3d0955a --- /dev/null +++ b/Demos/CcdPhysicsDemo/main.cpp @@ -0,0 +1,49 @@ +/* +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 "CcdPhysicsDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" +#ifdef __DEBUG_FPU_ISSUES +#define _GNU_SOURCE +#include +#endif + +GLDebugDrawer gDebugDrawer; + +int main(int argc,char** argv) +{ + + CcdPhysicsDemo* ccdDemo = new CcdPhysicsDemo(); + +#ifdef __DEBUG_FPU_ISSUES +// feenableexcept (FE_DIVBYZERO); +// feenableexcept (FE_INEXACT); +// feenableexcept (FE_INVALID); +// feenableexcept (FE_OVERFLOW|FE_DIVBYZERO|FE_UNDERFLOW); +// feenableexcept (FE_UNDERFLOW); +#endif + + ccdDemo->initPhysics(); + ccdDemo->getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + + glutmain(argc, argv,640,480,"Bullet Physics Demo. http://bulletphysics.com",ccdDemo); + + delete ccdDemo; + return 0; + +} diff --git a/Demos/CellSpuDemo/BasicDemo2.cpp b/Demos/CellSpuDemo/BasicDemo2.cpp new file mode 100644 index 0000000..2af2b80 --- /dev/null +++ b/Demos/CellSpuDemo/BasicDemo2.cpp @@ -0,0 +1,277 @@ +/* +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. +*/ + + +//#define USE_GROUND_BOX 1 +#define PRINT_CONTACT_STATISTICS 1 +#define USE_PARALLEL_DISPATCHER 1 + + +//#define USE_SIMPLE_DYNAMICS_WORLD 1 + +int gNumObjects = 5; +#define HALF_EXTENTS btScalar(1.) +#include "btBulletDynamicsCommon.h" +#include "BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h" +#include "LinearMath/btIDebugDraw.h" +#include //printf debugging +btScalar deltaTime = btScalar(1./60.); +btScalar gCollisionMargin = btScalar(0.05); +#include "BasicDemo2.h" + +#ifdef USE_PARALLEL_DISPATCHER +#include "BulletMultiThreaded/SpuGatheringCollisionDispatcher.h" +#include "BulletMultiThreaded/Win32ThreadSupport.h" +#include "BulletMultiThreaded/SpuLibspe2Support.h" +#include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" +#endif//USE_PARALLEL_DISPATCHER + + +#include + +//////////////////////////////////// + + + + +int main(int argc,char** argv) +{ + + BasicDemo ccdDemo; + ccdDemo.initPhysics(); + + int i; + for (i=0;i<5;i++) + ccdDemo.clientMoveAndDisplay(); + ccdDemo.exitPhysics(); + + return 0; +} + + + +extern int gNumManifold; + +void BasicDemo::clientMoveAndDisplay() +{ + + //simple dynamics world doesn't handle fixed-time-stepping + float ms = m_clock.getTimeMicroseconds(); + m_clock.reset(); + float minFPS = 1000000.f/60.f; + if (ms > minFPS) + ms = minFPS; + + if (m_dynamicsWorld) + m_dynamicsWorld->stepSimulation(ms / 1000000.f); + + //some additional debugging info +#ifdef PRINT_CONTACT_STATISTICS + printf("num contact manifolds: %i\n",gNumManifold); + int numManifolds = m_dynamicsWorld->getDispatcher()->getNumManifolds(); + for (int i=0;igetDispatcher()->getManifoldByIndexInternal(i); + btCollisionObject* obA = static_cast(contactManifold->getBody0()); + btCollisionObject* obB = static_cast(contactManifold->getBody1()); + + int numContacts = contactManifold->getNumContacts(); + for (int j=0;jgetContactPoint(j); + btVector3 ptA = pt.getPositionWorldOnA(); + btVector3 ptB = pt.getPositionWorldOnB(); + printf("contact manifold[%d],pointA[%d]=(%f,%f,%f)\n",i,j,ptA[0],ptA[1],ptA[2]); + } + } +#endif //PRINT_CONTACT_STATISTICS + + +} + + + + + +void BasicDemo::initPhysics() +{ + + btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration(); + +#ifdef USE_PARALLEL_DISPATCHER + + int maxNumOutstandingTasks = 1;//number of maximum outstanding tasks +#ifdef USE_WIN32_THREADING + + Win32ThreadSupport* threadSupport = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo( + "collision", + processCollisionTask, + createCollisionLocalStoreMemory, + maxNumOutstandingTasks)); +#else + + spe_program_handle_t * program_handle; +#ifndef USE_CESOF + char* spuFileName = "../../../src/BulletMultiThreaded/out/spuCollision.elf"; + + program_handle = spe_image_open (spuFileName); + if (program_handle == NULL) + { + printf( "SPU OPEN IMAGE ERROR:%s\n",spuFileName); + exit(0); + } + else + { + printf( "IMAGE OPENED:%s\n",spuFileName); + } +#else + extern spe_program_handle_t spu_program; + program_handle = &spu_program; +#endif + SpuLibspe2Support* threadSupport = new SpuLibspe2Support( program_handle, maxNumOutstandingTasks); + +#endif // WIN32 + + + m_dispatcher = new SpuGatheringCollisionDispatcher(threadSupport,maxNumOutstandingTasks,collisionConfiguration); +#else + m_dispatcher = new btCollisionDispatcher(collisionConfiguration); +#endif //USE_PARALLEL_DISPATCHER + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + + +#define USE_SWEEP_AND_PRUNE 1 +#ifdef USE_SWEEP_AND_PRUNE +#define maxProxies 8192 + btVector3 worldAabbMin(-10000,-10000,-10000); + btVector3 worldAabbMax(10000,10000,10000); + m_overlappingPairCache = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies); + //m_overlappingPairCache = new btMultiSapBroadphase(); + + +#else + m_overlappingPairCache = new btSimpleBroadphase; +#endif //USE_SWEEP_AND_PRUNE + + + + btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; + m_solver = sol; + + + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_solver,m_collisionConfiguration); + m_dynamicsWorld->getDispatchInfo().m_enableSPU = true; + + m_dynamicsWorld->setGravity(btVector3(0,-10,0)); + + + ///create a few basic rigid bodies + + + //static ground +#ifdef USE_GROUND_BOX + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); +#else + btCollisionShape* groundShape = new btSphereShape(btScalar(50.)); +#endif//USE_GROUND_BOX + + m_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + localCreateRigidBody(btScalar(0.),groundTransform,groundShape); + + //create a few dynamic sphere rigidbodies (re-using the same sphere shape) + //btCollisionShape* sphereShape = new btBoxShape(btVector3(1,1,1)); + btCollisionShape* sphereShape = new btSphereShape(btScalar(1.)); + m_collisionShapes.push_back(sphereShape); + + int i; + for (i=0;isetMargin(gCollisionMargin); + btTransform trans; + trans.setIdentity(); + //stack them + int colsize = 2; + int row = (int)((i*HALF_EXTENTS*2)/(colsize*2*HALF_EXTENTS)); + int row2 = row; + int col = (i)%(colsize)-colsize/2; + btVector3 pos(col*2*HALF_EXTENTS + (row2%2)*HALF_EXTENTS, + row*2*HALF_EXTENTS+HALF_EXTENTS,0); + + trans.setOrigin(pos); + //btRigidBody* body = localCreateRigidBody(btScalar(1.),trans,sphereShape); + localCreateRigidBody(btScalar(1.),trans,sphereShape); + } + + //clientResetScene(); +} + +btRigidBody* BasicDemo::localCreateRigidBody(btScalar mass,const btTransform& startTrans,btCollisionShape* colShape) +{ +btVector3 inertia(0,0,0); +if (mass) + colShape->calculateLocalInertia(mass,inertia); + btRigidBody::btRigidBodyConstructionInfo rbci(mass,0,colShape,inertia); + rbci.m_startWorldTransform = startTrans; + +btRigidBody* body = new btRigidBody(rbci); + m_dynamicsWorld->addRigidBody(body); +return body; + +} +void BasicDemo::exitPhysics() +{ + + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int i; + for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--) + { + btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i]; + m_dynamicsWorld->removeCollisionObject( obj ); + delete obj; + } + + //delete collision shapes + for (int j=0;j m_collisionShapes; + + btBroadphaseInterface* m_overlappingPairCache; + + btCollisionDispatcher* m_dispatcher; + btDefaultCollisionConfiguration* m_collisionConfiguration; + btConstraintSolver* m_solver; + btDiscreteDynamicsWorld* m_dynamicsWorld; + + btCollisionAlgorithmCreateFunc* m_sphereSphereCF; + btCollisionAlgorithmCreateFunc* m_sphereBoxCF; + btCollisionAlgorithmCreateFunc* m_boxSphereCF; + + btRigidBody* localCreateRigidBody(btScalar mass,const btTransform& startTrans,btCollisionShape* colShape); + + + public: + + void initPhysics(); + + void exitPhysics(); + + virtual void clientMoveAndDisplay(); + + + +}; + +#endif //BASIC_DEMO_H + diff --git a/Demos/CellSpuDemo/ibmsdk/Makefile b/Demos/CellSpuDemo/ibmsdk/Makefile new file mode 100755 index 0000000..9777906 --- /dev/null +++ b/Demos/CellSpuDemo/ibmsdk/Makefile @@ -0,0 +1,69 @@ +# --------------------------------------------------------------- +# PLEASE DO NOT MODIFY THIS SECTION +# This prolog section is automatically generated. +# +# (C) Copyright 2001,2006, +# International Business Machines Corporation, +# +# All Rights Reserved. +# --------------------------------------------------------------- +# -------------------------------------------------------------- +# PROLOG END TAG zYx + +######################################################################## +# Source Code +######################################################################## +VPATH = ../ +######################################################################## +# Target +######################################################################## +ROOT = ../../.. +HOSTINC = /usr/include +PROGRAM_ppu := BasicDemo2 + +####################################################################### +# Objs +###################################################################### +OBJS = BasicDemo2.o + +######################################################################## +# Libraries, Include paths, Defines +######################################################################## +INCLUDE = -DUSE_LIBSPE2 \ + -I../ \ + -I$(ROOT)/src \ + -I$(ROOT)/Demos/OpenGL \ + -I$(HOSTINC) +SYS_LIBS := -lspe2 -lm + +IMPORTS = $(ROOT)/lib/ibmsdk/bulletmultithreaded.a \ + $(ROOT)/lib/ibmsdk/bulletdynamics.a \ + $(ROOT)/lib/ibmsdk/bulletcollision.a \ + $(ROOT)/lib/ibmsdk/bulletmath.a + +####################################################################### +# Install files/dirs +####################################################################### +INSTALL_DIR = $(ROOT)/ibmsdk +INSTALL_FILES = $(PROGRAM_ppu) +######################################################################## +# make.footer +######################################################################## + + +IBM_CELLSDK_VERSION := $(shell if [ -d /opt/cell ]; then echo "3.0"; fi) + +ifeq ("$(IBM_CELLSDK_VERSION)","3.0") + CELL_TOP ?= /opt/cell/sdk + include $(CELL_TOP)/buildutils/make.footer +else + CELL_TOP ?= /opt/ibm/cell-sdk/prototype + include $(CELL_TOP)/make.footer +endif + + +$(PPMS): + cp textures/$@ . + +cleanlocal: + rm -f $(PPMS) diff --git a/Demos/CharacterDemo/CMakeLists.txt b/Demos/CharacterDemo/CMakeLists.txt new file mode 100644 index 0000000..175e11b --- /dev/null +++ b/Demos/CharacterDemo/CMakeLists.txt @@ -0,0 +1,75 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# You shouldn't have to modify anything below this line +######################################################## + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) +SET(CharacterDemo_SRCS + + DynamicCharacterController.cpp + DynamicCharacterController.h + CharacterDemo.cpp + CharacterDemo.h + ../BspDemo/BspConverter.cpp + ../BspDemo/BspConverter.h + ../BspDemo/BspLoader.cpp + ../BspDemo/BspLoader.h + main.cpp +) + +IF (WIN32) + ADD_EXECUTABLE(AppCharacterDemo + ${CharacterDemo_SRCS} + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) +ELSE() + ADD_EXECUTABLE(AppCharacterDemo + ${CharacterDemo_SRCS} + ) +ENDIF() + +IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppCharacterDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppCharacterDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF(WIN32) + +IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( + TARGET AppCharacterDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/BspDemo.bsp ${CMAKE_CURRENT_BINARY_DIR} + ) +ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppCharacterDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppCharacterDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppCharacterDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) diff --git a/Demos/CharacterDemo/CharacterDemo.cpp b/Demos/CharacterDemo/CharacterDemo.cpp new file mode 100644 index 0000000..5445249 --- /dev/null +++ b/Demos/CharacterDemo/CharacterDemo.cpp @@ -0,0 +1,531 @@ +/* +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 "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h" +#include "BulletCollision/CollisionDispatch/btGhostObject.h" + +#include "GLDebugDrawer.h" +#include //printf debugging + +#include "GL_ShapeDrawer.h" + +#include "GlutStuff.h" +#include "CharacterDemo.h" +#ifdef DYNAMIC_CHARACTER_CONTROLLER +#include "DynamicCharacterController.h" +#else +#include "BulletDynamics/Character/btKinematicCharacterController.h" +#endif + +const int maxProxies = 32766; +const int maxOverlap = 65535; + +static int gForward = 0; +static int gBackward = 0; +static int gLeft = 0; +static int gRight = 0; +static int gJump = 0; + + + + +CharacterDemo::CharacterDemo() +: +m_cameraHeight(4.f), +m_minCameraDistance(3.f), +m_maxCameraDistance(10.f), +m_indexVertexArrays(0), +m_vertices(0) +{ + m_character = 0; + m_cameraPosition = btVector3(30,30,30); +} + + +void CharacterDemo::initPhysics() +{ + btCollisionShape* groundShape = new btBoxShape(btVector3(50,3,50)); + m_collisionShapes.push_back(groundShape); + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + btVector3 worldMin(-1000,-1000,-1000); + btVector3 worldMax(1000,1000,1000); + btAxisSweep3* sweepBP = new btAxisSweep3(worldMin,worldMax); + m_overlappingPairCache = sweepBP; + + m_constraintSolver = new btSequentialImpulseConstraintSolver(); + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_constraintSolver,m_collisionConfiguration); + m_dynamicsWorld->getDispatchInfo().m_allowedCcdPenetration=0.0001f; + +#ifdef DYNAMIC_CHARACTER_CONTROLLER + m_character = new DynamicCharacterController (); +#else + + btTransform startTransform; + startTransform.setIdentity (); + //startTransform.setOrigin (btVector3(0.0, 4.0, 0.0)); + startTransform.setOrigin (btVector3(10.210098,-1.6433364,16.453260)); + + + m_ghostObject = new btPairCachingGhostObject(); + m_ghostObject->setWorldTransform(startTransform); + sweepBP->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback()); + btScalar characterHeight=1.75; + btScalar characterWidth =1.75; + btConvexShape* capsule = new btCapsuleShape(characterWidth,characterHeight); + m_ghostObject->setCollisionShape (capsule); + m_ghostObject->setCollisionFlags (btCollisionObject::CF_CHARACTER_OBJECT); + + btScalar stepHeight = btScalar(0.35); + m_character = new btKinematicCharacterController (m_ghostObject,capsule,stepHeight); +#endif + + //////////////// + + /// Create some basic environment from a Quake level + + //m_dynamicsWorld->setGravity(btVector3(0,0,0)); + btTransform tr; + tr.setIdentity(); + + const char* bspfilename = "BspDemo.bsp"; + void* memoryBuffer = 0; + + FILE* file = fopen(bspfilename,"r"); + if (!file) + { + //cmake generated visual studio projects need 4 levels back + bspfilename = "../../../../BspDemo.bsp"; + file = fopen(bspfilename,"r"); + } + if (!file) + { + //visual studio leaves the current working directory in the projectfiles folder + bspfilename = "../../BspDemo.bsp"; + file = fopen(bspfilename,"r"); + } + if (!file) + { + //visual studio leaves the current working directory in the projectfiles folder + bspfilename = "BspDemo.bsp"; + file = fopen(bspfilename,"r"); + } + + if (file) + { + BspLoader bspLoader; + int size=0; + if (fseek(file, 0, SEEK_END) || (size = ftell(file)) == EOF || fseek(file, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */ + printf("Error: cannot get filesize from %s\n", bspfilename); + } else + { + //how to detect file size? + memoryBuffer = malloc(size+1); + fread(memoryBuffer,1,size,file); + bspLoader.loadBSPFile( memoryBuffer); + + BspToBulletConverter bsp2bullet(this); + float bspScaling = 0.1f; + bsp2bullet.convertBsp(bspLoader,bspScaling); + + } + fclose(file); + } + + ///only collide with static for now (no interaction with dynamic objects) + m_dynamicsWorld->addCollisionObject(m_ghostObject,btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter); + + m_dynamicsWorld->addAction(m_character); + + + /////////////// + + clientResetScene(); + + setCameraDistance(56.f); + +} + + +//to be implemented by the demo +void CharacterDemo::renderme() +{ + updateCamera(); + + DemoApplication::renderme(); +} + + + +void CharacterDemo::debugDrawContacts() +{ +// printf("numPairs = %d\n",m_customPairCallback->getOverlappingPairArray().size()); + { + btManifoldArray manifoldArray; + btBroadphasePairArray& pairArray = m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray(); + int numPairs = pairArray.size(); + + for (int i=0;igetOverlappingPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1); + if (!collisionPair) + continue; + + if (collisionPair->m_algorithm) + collisionPair->m_algorithm->getAllContactManifolds(manifoldArray); + + for (int j=0;jgetNumContacts();p++) + { + const btManifoldPoint&pt = manifold->getContactPoint(p); + + btVector3 color(255,255,255); + m_dynamicsWorld->getDebugDrawer()->drawContactPoint(pt.getPositionWorldOnB(),pt.m_normalWorldOnB,pt.getDistance(),pt.getLifeTime(),color); + } + } + } + } + +} + +void CharacterDemo::clientMoveAndDisplay() +{ + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + float dt = getDeltaTimeMicroseconds() * 0.000001f; + + /* Character stuff &*/ + if (m_character) + { + + } + + debugDrawContacts(); + + + if (m_dynamicsWorld) + { + //during idle mode, just run 1 simulation step maximum + int maxSimSubSteps = m_idle ? 1 : 2; + if (m_idle) + dt = 1.0/420.f; + + ///set walkDirection for our character + btTransform xform; + xform = m_ghostObject->getWorldTransform (); + + btVector3 forwardDir = xform.getBasis()[2]; + // printf("forwardDir=%f,%f,%f\n",forwardDir[0],forwardDir[1],forwardDir[2]); + btVector3 upDir = xform.getBasis()[1]; + btVector3 strafeDir = xform.getBasis()[0]; + forwardDir.normalize (); + upDir.normalize (); + strafeDir.normalize (); + + btVector3 walkDirection = btVector3(0.0, 0.0, 0.0); + btScalar walkVelocity = btScalar(1.1) * 4.0; // 4 km/h -> 1.1 m/s + btScalar walkSpeed = walkVelocity * dt; + + //rotate view + if (gLeft) + { + btMatrix3x3 orn = m_ghostObject->getWorldTransform().getBasis(); + orn *= btMatrix3x3(btQuaternion(btVector3(0,1,0),0.01)); + m_ghostObject->getWorldTransform ().setBasis(orn); + } + + if (gRight) + { + btMatrix3x3 orn = m_ghostObject->getWorldTransform().getBasis(); + orn *= btMatrix3x3(btQuaternion(btVector3(0,1,0),-0.01)); + m_ghostObject->getWorldTransform ().setBasis(orn); + } + + if (gForward) + walkDirection += forwardDir; + + if (gBackward) + walkDirection -= forwardDir; + + + m_character->setWalkDirection(walkDirection*walkSpeed); + + + int numSimSteps = m_dynamicsWorld->stepSimulation(dt,maxSimSubSteps); + + //optional but useful: debug drawing + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + +//#define VERBOSE_FEEDBACK +#ifdef VERBOSE_FEEDBACK + if (!numSimSteps) + printf("Interpolated transforms\n"); + else + { + if (numSimSteps > maxSimSubSteps) + { + //detect dropping frames + printf("Dropped (%i) simulation steps out of %i\n",numSimSteps - maxSimSubSteps,numSimSteps); + } else + { + printf("Simulated (%i) steps\n",numSimSteps); + } + } +#endif //VERBOSE_FEEDBACK + + } + + + + + + + +#ifdef USE_QUICKPROF + btProfiler::beginBlock("render"); +#endif //USE_QUICKPROF + + + renderme(); + +#ifdef USE_QUICKPROF + btProfiler::endBlock("render"); +#endif + + + glFlush(); + glutSwapBuffers(); + +} + + + +void CharacterDemo::displayCallback(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + //optional but useful: debug drawing + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + debugDrawContacts(); + + glFlush(); + glutSwapBuffers(); +} + +void CharacterDemo::clientResetScene() +{ + m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_ghostObject->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher()); + + m_character->reset (); + ///WTF + m_character->warp (btVector3(10.210001,-2.0306311,16.576973)); + +} + +void CharacterDemo::specialKeyboardUp(int key, int x, int y) +{ + switch (key) + { + case GLUT_KEY_UP: + { + gForward = 0; + } + break; + case GLUT_KEY_DOWN: + { + gBackward = 0; + } + break; + case GLUT_KEY_LEFT: + { + gLeft = 0; + } + break; + case GLUT_KEY_RIGHT: + { + gRight = 0; + } + break; + default: + DemoApplication::specialKeyboardUp(key,x,y); + break; + } +} + + +void CharacterDemo::specialKeyboard(int key, int x, int y) +{ + +// printf("key = %i x=%i y=%i\n",key,x,y); + + switch (key) + { + case GLUT_KEY_UP: + { + gForward = 1; + } + break; + case GLUT_KEY_DOWN: + { + gBackward = 1; + } + break; + case GLUT_KEY_LEFT: + { + gLeft = 1; + } + break; + case GLUT_KEY_RIGHT: + { + gRight = 1; + } + break; + case GLUT_KEY_F1: + { + if (m_character && m_character->canJump()) + gJump = 1; + } + break; + default: + DemoApplication::specialKeyboard(key,x,y); + break; + } + +// glutPostRedisplay(); + + +} + +void CharacterDemo::updateCamera() +{ + +//#define DISABLE_CAMERA 1 +#ifdef DISABLE_CAMERA + DemoApplication::updateCamera(); + return; +#endif //DISABLE_CAMERA + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + btTransform characterWorldTrans; + + //look at the vehicle + characterWorldTrans = m_ghostObject->getWorldTransform(); + btVector3 up = characterWorldTrans.getBasis()[1]; + btVector3 backward = -characterWorldTrans.getBasis()[2]; + up.normalize (); + backward.normalize (); + + m_cameraTargetPosition = characterWorldTrans.getOrigin(); + m_cameraPosition = m_cameraTargetPosition + up * 10.0 + backward * 12.0; + + //use the convex sweep test to find a safe position for the camera (not blocked by static geometry) + btSphereShape cameraSphere(0.2f); + btTransform cameraFrom,cameraTo; + cameraFrom.setIdentity(); + cameraFrom.setOrigin(characterWorldTrans.getOrigin()); + cameraTo.setIdentity(); + cameraTo.setOrigin(m_cameraPosition); + + btCollisionWorld::ClosestConvexResultCallback cb( characterWorldTrans.getOrigin(), cameraTo.getOrigin() ); + cb.m_collisionFilterMask = btBroadphaseProxy::StaticFilter; + + m_dynamicsWorld->convexSweepTest(&cameraSphere,cameraFrom,cameraTo,cb); + if (cb.hasHit()) + { + + btScalar minFraction = cb.m_closestHitFraction;//btMax(btScalar(0.3),cb.m_closestHitFraction); + m_cameraPosition.setInterpolate3(cameraFrom.getOrigin(),cameraTo.getOrigin(),minFraction); + } + + + + + //update OpenGL camera settings + glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10000.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + gluLookAt(m_cameraPosition[0],m_cameraPosition[1],m_cameraPosition[2], + m_cameraTargetPosition[0],m_cameraTargetPosition[1], m_cameraTargetPosition[2], + m_cameraUp.getX(),m_cameraUp.getY(),m_cameraUp.getZ()); + + + +} + + +CharacterDemo::~CharacterDemo() +{ + //cleanup in the reverse order of creation/initialization + if (m_character) + { + m_dynamicsWorld->removeCollisionObject(m_ghostObject); + } + //remove the rigidbodies from the dynamics world and delete them + int 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;j m_collisionShapes; + + class btBroadphaseInterface* m_overlappingPairCache; + + class btCollisionDispatcher* m_dispatcher; + + class btConstraintSolver* m_constraintSolver; + + class btDefaultCollisionConfiguration* m_collisionConfiguration; + + class btTriangleIndexVertexArray* m_indexVertexArrays; + + btVector3* m_vertices; + + void debugDrawContacts(); + + float m_cameraHeight; + + float m_minCameraDistance; + float m_maxCameraDistance; + + + CharacterDemo(); + + virtual ~CharacterDemo(); + + virtual void clientMoveAndDisplay(); + + virtual void clientResetScene(); + + virtual void displayCallback(); + + ///a very basic camera following the character + virtual void updateCamera(); + + virtual void specialKeyboard(int key, int x, int y); + + virtual void specialKeyboardUp(int key, int x, int y); + + void renderme(); + + void initPhysics(); + + static DemoApplication* Create() + { + CharacterDemo* demo = new CharacterDemo(); + demo->myinit(); + demo->initPhysics(); + return demo; + } +}; + + + +#define QUAKE_BSP_IMPORTING 1 +#ifdef QUAKE_BSP_IMPORTING +#include "../BspDemo/BspLoader.h" +#include "../BspDemo/BspConverter.h" + + + + +class BspToBulletConverter : public BspConverter +{ + CharacterDemo* m_demoApp; + +public: + + BspToBulletConverter(CharacterDemo* demoApp) + :m_demoApp(demoApp) + { + } + + virtual void addConvexVerticesCollider(btAlignedObjectArray& vertices, bool isEntity, const btVector3& entityTargetLocation) + { + ///perhaps we can do something special with entities (isEntity) + ///like adding a collision Triggering (as example) + + if (vertices.size() > 0) + { + float mass = 0.f; + btTransform startTransform; + //can use a shift + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(0,-10.0f,0.0f)); + //this create an internal copy of the vertices + for (int i = 0; i < vertices.size(); i++) + { + vertices[i] *= btScalar(0.5); + float t = vertices[i].getZ() * btScalar(0.75); + vertices[i].setZ(-vertices[i].getY()); + vertices[i].setY(t); + } + + btCollisionShape* shape = new btConvexHullShape(&(vertices[0].getX()),vertices.size()); + m_demoApp->m_collisionShapes.push_back(shape); + + //btRigidBody* body = m_demoApp->localCreateRigidBody(mass, startTransform,shape); + m_demoApp->localCreateRigidBody(mass, startTransform,shape); + } + } +}; +#endif //QUAKE_BSP_IMPORTING + + +#endif //CHARACTER_DEMO_H + + diff --git a/Demos/CharacterDemo/DynamicCharacterController.cpp b/Demos/CharacterDemo/DynamicCharacterController.cpp new file mode 100644 index 0000000..452d86b --- /dev/null +++ b/Demos/CharacterDemo/DynamicCharacterController.cpp @@ -0,0 +1,204 @@ +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "LinearMath/btDefaultMotionState.h" +#include "DynamicCharacterController.h" + +DynamicCharacterController::DynamicCharacterController () +{ + m_rayLambda[0] = 1.0; + m_rayLambda[1] = 1.0; + m_halfHeight = 1.0; + m_turnAngle = 0.0; + m_maxLinearVelocity = 10.0; + m_walkVelocity = 8.0; // meters/sec + m_turnVelocity = 1.0; // radians/sec + m_shape = NULL; + m_rigidBody = NULL; +} + +DynamicCharacterController::~DynamicCharacterController () +{ +} + +void DynamicCharacterController::setup (btScalar height, btScalar width, btScalar stepHeight) +{ + btVector3 spherePositions[2]; + btScalar sphereRadii[2]; + + sphereRadii[0] = width; + sphereRadii[1] = width; + spherePositions[0] = btVector3 (0.0, (height/btScalar(2.0) - width), 0.0); + spherePositions[1] = btVector3 (0.0, (-height/btScalar(2.0) + width), 0.0); + + m_halfHeight = height/btScalar(2.0); + + m_shape = new btMultiSphereShape (&spherePositions[0], &sphereRadii[0], 2); + + btTransform startTransform; + startTransform.setIdentity (); + startTransform.setOrigin (btVector3(0.0, 2.0, 0.0)); + btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + btRigidBody::btRigidBodyConstructionInfo cInfo(1.0, myMotionState, m_shape); + m_rigidBody = new btRigidBody(cInfo); + // kinematic vs. static doesn't work + //m_rigidBody->setCollisionFlags( m_rigidBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_rigidBody->setSleepingThresholds (0.0, 0.0); + m_rigidBody->setAngularFactor (0.0); + +} + +void DynamicCharacterController::destroy () +{ + if (m_shape) + { + delete m_shape; + } + + if (m_rigidBody) + { + delete m_rigidBody; + m_rigidBody = 0; + } +} + +btCollisionObject* DynamicCharacterController::getCollisionObject () +{ + return m_rigidBody; +} + +void DynamicCharacterController::preStep (const btCollisionWorld* collisionWorld) +{ + btTransform xform; + m_rigidBody->getMotionState()->getWorldTransform (xform); + btVector3 down = -xform.getBasis()[1]; + btVector3 forward = xform.getBasis()[2]; + down.normalize (); + forward.normalize(); + + m_raySource[0] = xform.getOrigin(); + m_raySource[1] = xform.getOrigin(); + + m_rayTarget[0] = m_raySource[0] + down * m_halfHeight * btScalar(1.1); + m_rayTarget[1] = m_raySource[1] + forward * m_halfHeight * btScalar(1.1); + + class ClosestNotMe : public btCollisionWorld::ClosestRayResultCallback + { + public: + ClosestNotMe (btRigidBody* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)) + { + m_me = me; + } + + virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) + { + if (rayResult.m_collisionObject == m_me) + return 1.0; + + return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace + ); + } + protected: + btRigidBody* m_me; + }; + + ClosestNotMe rayCallback(m_rigidBody); + + int i = 0; + for (i = 0; i < 2; i++) + { + rayCallback.m_closestHitFraction = 1.0; + collisionWorld->rayTest (m_raySource[i], m_rayTarget[i], rayCallback); + if (rayCallback.hasHit()) + { + m_rayLambda[i] = rayCallback.m_closestHitFraction; + } else { + m_rayLambda[i] = 1.0; + } + } +} + +void DynamicCharacterController::playerStep (const btCollisionWorld* dynaWorld,btScalar dt, + int forward, + int backward, + int left, + int right, + int jump) +{ + btTransform xform; + m_rigidBody->getMotionState()->getWorldTransform (xform); + + /* Handle turning */ + if (left) + m_turnAngle -= dt * m_turnVelocity; + if (right) + m_turnAngle += dt * m_turnVelocity; + + xform.setRotation (btQuaternion (btVector3(0.0, 1.0, 0.0), m_turnAngle)); + + btVector3 linearVelocity = m_rigidBody->getLinearVelocity(); + btScalar speed = m_rigidBody->getLinearVelocity().length(); + + btVector3 forwardDir = xform.getBasis()[2]; + forwardDir.normalize (); + btVector3 walkDirection = btVector3(0.0, 0.0, 0.0); + btScalar walkSpeed = m_walkVelocity * dt; + + if (forward) + walkDirection += forwardDir; + if (backward) + walkDirection -= forwardDir; + + + + if (!forward && !backward && onGround()) + { + /* Dampen when on the ground and not being moved by the player */ + linearVelocity *= btScalar(0.2); + m_rigidBody->setLinearVelocity (linearVelocity); + } else { + if (speed < m_maxLinearVelocity) + { + btVector3 velocity = linearVelocity + walkDirection * walkSpeed; + m_rigidBody->setLinearVelocity (velocity); + } + } + + m_rigidBody->getMotionState()->setWorldTransform (xform); + m_rigidBody->setCenterOfMassTransform (xform); +} + +bool DynamicCharacterController::canJump () const +{ + return onGround(); +} + +void DynamicCharacterController::jump () +{ + if (!canJump()) + return; + + btTransform xform; + m_rigidBody->getMotionState()->getWorldTransform (xform); + btVector3 up = xform.getBasis()[1]; + up.normalize (); + btScalar magnitude = (btScalar(1.0)/m_rigidBody->getInvMass()) * btScalar(8.0); + m_rigidBody->applyCentralImpulse (up * magnitude); +} + +bool DynamicCharacterController::onGround () const +{ + return m_rayLambda[0] < btScalar(1.0); +} + +void DynamicCharacterController::reset () +{ +} +void DynamicCharacterController::warp (const btVector3& origin) +{ +} +void DynamicCharacterController::registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher) +{ + +} + diff --git a/Demos/CharacterDemo/DynamicCharacterController.h b/Demos/CharacterDemo/DynamicCharacterController.h new file mode 100644 index 0000000..241aaea --- /dev/null +++ b/Demos/CharacterDemo/DynamicCharacterController.h @@ -0,0 +1,55 @@ +#ifndef CHARACTER_CONTROLLER_H +#define CHARACTER_CONTROLLER_H + +#include "LinearMath/btVector3.h" + +#include "BulletDynamics/Character/btCharacterControllerInterface.h" + +class btCollisionShape; +class btRigidBody; +class btCollisionWorld; + +///DynamicCharacterController is obsolete/unsupported at the moment +class DynamicCharacterController : public btCharacterControllerInterface +{ +protected: + btScalar m_halfHeight; + btCollisionShape* m_shape; + btRigidBody* m_rigidBody; + + btVector3 m_raySource[2]; + btVector3 m_rayTarget[2]; + btScalar m_rayLambda[2]; + btVector3 m_rayNormal[2]; + + btScalar m_turnAngle; + + btScalar m_maxLinearVelocity; + btScalar m_walkVelocity; + btScalar m_turnVelocity; +public: + DynamicCharacterController (); + ~DynamicCharacterController (); + void setup (btScalar height = 2.0, btScalar width = 0.25, btScalar stepHeight = 0.25); + void destroy (); + + virtual void reset (); + virtual void warp (const btVector3& origin); + virtual void registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher); + + btCollisionObject* getCollisionObject (); + + void preStep (const btCollisionWorld* collisionWorld); + void playerStep (const btCollisionWorld* collisionWorld,btScalar dt, + int forward, + int backward, + int left, + int right, + int jump); + bool canJump () const; + void jump (); + + bool onGround () const; +}; + +#endif diff --git a/Demos/CharacterDemo/main.cpp b/Demos/CharacterDemo/main.cpp new file mode 100644 index 0000000..080eb86 --- /dev/null +++ b/Demos/CharacterDemo/main.cpp @@ -0,0 +1,19 @@ + +#include "CharacterDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" + +GLDebugDrawer gDebugDrawer; + +int main(int argc,char** argv) +{ + + CharacterDemo* characterDemo = new CharacterDemo; + + characterDemo->initPhysics(); + characterDemo->getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + return glutmain(argc, argv,640,480,"Bullet Character Demo. http://www.continuousphysics.com/Bullet/phpBB2/", characterDemo); +} + diff --git a/Demos/CollisionDemo/CMakeLists.txt b/Demos/CollisionDemo/CMakeLists.txt new file mode 100644 index 0000000..6fbc03c --- /dev/null +++ b/Demos/CollisionDemo/CMakeLists.txt @@ -0,0 +1,54 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +IF (WIN32) + ADD_EXECUTABLE(AppCollisionDemo + CollisionDemo.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) +ELSE() + ADD_EXECUTABLE(AppCollisionDemo + CollisionDemo.cpp + ) +ENDIF() + +IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppCollisionDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppCollisionDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF(WIN32) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppCollisionDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppCollisionDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppCollisionDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/CollisionDemo/CollisionDemo.cpp b/Demos/CollisionDemo/CollisionDemo.cpp new file mode 100644 index 0000000..124cba3 --- /dev/null +++ b/Demos/CollisionDemo/CollisionDemo.cpp @@ -0,0 +1,380 @@ +/* +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. +*/ + + +/// +/// Collision Demo shows a degenerate case, where the Simplex solver has to deal with near-affine dependent cases +/// See the define CATCH_DEGENERATE_TETRAHEDRON in Bullet's btVoronoiSimplexSolver.cpp +/// + + +//#define CHECK_GENSHER_TRIANGLE_CASE 1 + + +///This low-level internal demo does intentionally NOT use the btBulletCollisionCommon.h header +///It needs internal access +#include "GL_Simplex1to4.h" +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btTransform.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btPointCollector.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "LinearMath/btTransformUtil.h" + +#include "CollisionDemo.h" +#include "GL_ShapeDrawer.h" +#include "GlutStuff.h" +#include "LinearMath/btIDebugDraw.h" +#include "../OpenGL/GLDebugDrawer.h" +GLDebugDrawer debugDrawer; + + +float yaw=0.f,pitch=0.f,roll=0.f; +const int maxNumObjects = 4; +const int numObjects = 2; + +GL_Simplex1to4 simplex; + +btPolyhedralConvexShape* shapePtr[maxNumObjects]; + +btTransform tr[numObjects]; +int screenWidth = 640; +int screenHeight = 480; + +void DrawRasterizerLine(float const* , float const*, int) +{ + +} + +int main(int argc,char** argv) +{ + CollisionDemo* colDemo = new CollisionDemo(); + +#ifdef CHECK_GENSHER_TRIANGLE_CASE + colDemo->setCameraDistance(8.f); +#else + colDemo->setCameraDistance(4.f); + +#endif // + colDemo->initPhysics(); + + + + return glutmain(argc, argv,screenWidth,screenHeight,"Collision Demo",colDemo); +} + +void CollisionDemo::initPhysics() +{ + setTexturing(false); + setShadows(false); + + //m_debugMode |= btIDebugDraw::DBG_DrawWireframe; +#ifdef CHECK_GENSHER_TRIANGLE_CASE + m_azi = 140.f; +#else + m_azi = 250.f; +#endif + m_ele = 25.f; + + m_azi = 0; + m_ele = 0; + m_cameraTargetPosition.setValue(8.12,0.39,0); + + tr[0].setIdentity(); + tr[0].setOrigin(btVector3(10,0,0)); + tr[1].setIdentity(); + tr[1].setOrigin(btVector3(0,0,0)); + + +#ifdef CHECK_GENSHER_TRIANGLE_CASE + tr[0].setIdentity(); + tr[1].setIdentity(); +#endif //CHECK_GENSHER_TRIANGLE_CASE + + btVector3 boxHalfExtentsA(1,1,1);//1.0000004768371582f,1.0000004768371582f,1.0000001192092896f); + btVector3 boxHalfExtentsB(4,4,4);//3.2836332321166992f,3.2836332321166992f,3.2836320400238037f); + +#ifndef CHECK_GENSHER_TRIANGLE_CASE + btBoxShape* boxA = new btBoxShape(boxHalfExtentsA); + btBoxShape* boxB = new btBoxShape(boxHalfExtentsB); +#endif + + + + + + +#ifdef CHECK_GENSHER_TRIANGLE_CASE + shapePtr[0] = trishapeA; + shapePtr[1] = trishapeB; +#else + shapePtr[0] = boxA; + shapePtr[1] = boxB; +#endif + +} + +void CollisionDemo::clientMoveAndDisplay() +{ + + displayCallback(); +} + + +static btVoronoiSimplexSolver sGjkSimplexSolver; +btSimplexSolverInterface& gGjkSimplexSolver = sGjkSimplexSolver; + +static btScalar gContactBreakingThreshold=.02f; +int myiter = 1; +int mystate = 2; + +int checkPerturbation = 1; +int numPerturbationIterations = 20; +void CollisionDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glDisable(GL_LIGHTING); + + btVoronoiSimplexSolver sGjkSimplexSolver; + btGjkEpaPenetrationDepthSolver epaSolver; + btPointCollector gjkOutput; + btVector3 worldBoundsMin(-1000,-1000,-1000); + btVector3 worldBoundsMax(1000,1000,1000); + { + btGjkPairDetector convexConvex(shapePtr[0],shapePtr[1],&sGjkSimplexSolver,&epaSolver); + + btGjkPairDetector::ClosestPointInput input; + input.m_transformA = tr[0]; + input.m_transformB = tr[1]; + + + convexConvex.getClosestPoints(input, gjkOutput, 0); + } + + btScalar m[16]; + int i; + + //m_ele = 21.2; + //m_azi = -56.6; + + + + + for (i=0;idrawOpenGL(m,shapePtr[i],btVector3(119./255.,147./255.,60./255.),btIDebugDraw::DBG_FastWireframe,worldBoundsMin,worldBoundsMax); + m_shapeDrawer->drawOpenGL(m,shapePtr[i],btVector3(0.6,0.6,0.6),btIDebugDraw::DBG_FastWireframe,worldBoundsMin,worldBoundsMax); + } + + if (gjkOutput.m_hasResult) + { + printf("original distance: %10.4f\n", gjkOutput.m_distance); + btVector3 endPt = gjkOutput.m_pointInWorld + + gjkOutput.m_normalOnBInWorld*gjkOutput.m_distance; + + debugDrawer.drawLine(gjkOutput.m_pointInWorld,endPt,btVector3(0,0,0)); + debugDrawer.drawSphere(gjkOutput.m_pointInWorld,0.05,btVector3(0,0,0)); + debugDrawer.drawSphere(endPt,0.05,btVector3(0,0,0)); + + bool perturbeA = false;//true; + const btScalar angleLimit = 0.125f * SIMD_PI; + btScalar perturbeAngle; + btScalar radiusA = shapePtr[0]->getAngularMotionDisc(); + btScalar radiusB = shapePtr[1]->getAngularMotionDisc(); + + if (radiusA < radiusB) + { + perturbeAngle = gContactBreakingThreshold /radiusA; + perturbeA = true; + } else + { + perturbeAngle = gContactBreakingThreshold / radiusB; + perturbeA = false; + } + if ( perturbeAngle > angleLimit ) + perturbeAngle = angleLimit; + + perturbeAngle*=5; + + btVector3 v0,v1; + btPlaneSpace1(gjkOutput.m_normalOnBInWorld,v0,v1); + + glLineWidth(5); + int i; + i=0; + if (myiter>=numPerturbationIterations) + myiter=0; + if (mystate<2) + { + i= myiter; + } + + for ( ;idrawOpenGL(m,shapePtr[0],btVector3(108./255.,131./255.,158./255),btIDebugDraw::DBG_FastWireframe,worldBoundsMin,worldBoundsMax); + m_shapeDrawer->drawOpenGL(m,shapePtr[0],btVector3(0.3,0.3,1),btIDebugDraw::DBG_FastWireframe,worldBoundsMin,worldBoundsMax); + + } + + if (1)//gjkOutput.m_hasResult) + { + + printf("perturbed distance: %10.4f\n", gjkOutput.m_distance); + btVector3 startPt,endPt; + btScalar depth = 0; + if (perturbeA) + { + btVector3 endPtOrg = gjkOutput.m_pointInWorld + gjkOutput.m_normalOnBInWorld*gjkOutput.m_distance; + endPt = (tr[0]*input.m_transformA.inverse())(endPtOrg); + depth = (endPt - gjkOutput.m_pointInWorld).dot(gjkOutput.m_normalOnBInWorld); + startPt = endPt-gjkOutput.m_normalOnBInWorld*depth; + } else + { + endPt = gjkOutput.m_pointInWorld + gjkOutput.m_normalOnBInWorld*gjkOutput.m_distance; + startPt = (tr[1]*input.m_transformB.inverse())(gjkOutput.m_pointInWorld); + depth = (endPt - startPt).dot(gjkOutput.m_normalOnBInWorld); + } + + printf("corrected distance: %10.4f\n", depth); + + + + debugDrawer.drawLine(startPt,endPt,btVector3(1,0,0)); + debugDrawer.drawSphere(startPt,0.05,btVector3(0,1,0)); + debugDrawer.drawSphere(endPt,0.05,btVector3(0,0,1)); + } + if (mystate<2) + break; + if (mystate==2 && i>myiter) + break; + } + + + } + + static int looper = 0; + if (looper++>10) + { + looper =0; + checkPerturbation++; + if (checkPerturbation>numPerturbationIterations) + checkPerturbation=0; + } + + GL_ShapeDrawer::drawCoordSystem(); + + + + if (mystate==1 || mystate==2) + { + static int count = 10; + count--; + if (count<0) + { + count=10; + myiter++; + } + } + + btQuaternion orn; + orn.setEuler(yaw,pitch,roll); + //let it rotate + //tr[0].setRotation(orn); + + pitch += 0.005f; + yaw += 0.01f; + + glFlush(); + glutSwapBuffers(); +} + + +void CollisionDemo::specialKeyboard(int key, int x, int y) +{ + switch (key) + { + case GLUT_KEY_DOWN: + case GLUT_KEY_UP: + { + break; + } + default: + DemoApplication::specialKeyboard(key,x,y); + break; + } + +} + +void CollisionDemo::specialKeyboardUp(int key, int x, int y) +{ + switch (key) + { + case GLUT_KEY_UP : + { + myiter++; + break; + } + + case GLUT_KEY_DOWN: + { + mystate++; + if (mystate>1) + myiter=0; + if (mystate>=4) + mystate = 0; + break; + } + default: + DemoApplication::specialKeyboardUp(key,x,y); + break; + } +} diff --git a/Demos/CollisionDemo/CollisionDemo.h b/Demos/CollisionDemo/CollisionDemo.h new file mode 100644 index 0000000..487250a --- /dev/null +++ b/Demos/CollisionDemo/CollisionDemo.h @@ -0,0 +1,38 @@ +/* +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 COLLISION_DEMO_H +#define COLLISION_DEMO_H + +#include "GlutDemoApplication.h" + +///CollisionDemo shows the low-level direct access to GJK +class CollisionDemo : public GlutDemoApplication +{ + public: + + void initPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + virtual void specialKeyboardUp(int key, int x, int y); + + virtual void specialKeyboard(int key, int x, int y); + +}; + +#endif //COLLISION_DEMO_H + diff --git a/Demos/CollisionInterfaceDemo/CMakeLists.txt b/Demos/CollisionInterfaceDemo/CMakeLists.txt new file mode 100644 index 0000000..2848f52 --- /dev/null +++ b/Demos/CollisionInterfaceDemo/CMakeLists.txt @@ -0,0 +1,77 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + +IF (USE_GLUT) + INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL + ) + + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + IF (WIN32) + ADD_EXECUTABLE(AppCollisionInterfaceDemo + CollisionInterfaceDemo.cpp + CollisionInterfaceDemo.h + main.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) + ELSE() + ADD_EXECUTABLE(AppCollisionInterfaceDemo + CollisionInterfaceDemo.cpp + CollisionInterfaceDemo.h + main.cpp + ) + ENDIF() + IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppCollisionInterfaceDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppCollisionInterfaceDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ENDIF(WIN32) +ELSE (USE_GLUT) + INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL + ) + + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + ADD_EXECUTABLE(AppCollisionInterfaceDemo + WIN32 + CollisionInterfaceDemo.cpp + CollisionInterfaceDemo.h + Win32CollisionInterfaceDemo.cpp + ../OpenGL/Win32AppMain.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) +ENDIF (USE_GLUT) + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppCollisionInterfaceDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppCollisionInterfaceDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppCollisionInterfaceDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/CollisionInterfaceDemo/CollisionInterfaceDemo.cpp b/Demos/CollisionInterfaceDemo/CollisionInterfaceDemo.cpp new file mode 100644 index 0000000..c21ebdf --- /dev/null +++ b/Demos/CollisionInterfaceDemo/CollisionInterfaceDemo.cpp @@ -0,0 +1,292 @@ +/* +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. +*/ + + +/// +/// CollisionInterfaceDemo shows high level usage of the Collision Detection. +/// +#define TEST_NOT_ADDING_OBJECTS_TO_WORLD + +#include "GL_Simplex1to4.h" + +//include common Bullet Collision Detection headerfiles +#include "btBulletCollisionCommon.h" + +#include "LinearMath/btIDebugDraw.h" +#include "GL_ShapeDrawer.h" +#include "CollisionInterfaceDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" + +btScalar yaw=0.f,pitch=0.f,roll=0.f; +const int maxNumObjects = 4; +const int numObjects = 2; + +GL_Simplex1to4 simplex; + +btCollisionObject objects[maxNumObjects]; +btCollisionWorld* collisionWorld = 0; + +GLDebugDrawer debugDrawer; + + +void CollisionInterfaceDemo::initPhysics() +{ + + m_debugMode |= btIDebugDraw::DBG_DrawWireframe; + + btMatrix3x3 basisA; + basisA.setIdentity(); + + btMatrix3x3 basisB; + basisB.setIdentity(); + + objects[0].getWorldTransform().setBasis(basisA); + objects[1].getWorldTransform().setBasis(basisB); + + btBoxShape* boxA = new btBoxShape(btVector3(1,1,1)); + boxA->setMargin(0.f); + + btBoxShape* boxB = new btBoxShape(btVector3(0.5,0.5,0.5)); + boxB->setMargin(0.f); + //ConvexHullShape hullA(points0,3); + //hullA.setLocalScaling(btVector3(3,3,3)); + //ConvexHullShape hullB(points1,4); + //hullB.setLocalScaling(btVector3(4,4,4)); + + objects[0].setCollisionShape(boxA);//&hullA; + objects[1].setCollisionShape(boxB);//&hullB; + + btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration(); + btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration); + btVector3 worldAabbMin(-1000,-1000,-1000); + btVector3 worldAabbMax(1000,1000,1000); + + btAxisSweep3* broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax); + + //SimpleBroadphase is a brute force alternative, performing N^2 aabb overlap tests + //SimpleBroadphase* broadphase = new btSimpleBroadphase; + + collisionWorld = new btCollisionWorld(dispatcher,broadphase,collisionConfiguration); + collisionWorld->setDebugDrawer(&debugDrawer); + +#ifdef TEST_NOT_ADDING_OBJECTS_TO_WORLD +// collisionWorld->addCollisionObject(&objects[0]); + collisionWorld->addCollisionObject(&objects[1]); +#endif //TEST_NOT_ADDING_OBJECTS_TO_WORLD + +} + + +//to be implemented by the demo + +void CollisionInterfaceDemo::clientMoveAndDisplay() +{ + + displayCallback(); +} + + +static btVoronoiSimplexSolver sGjkSimplexSolver; +btSimplexSolverInterface& gGjkSimplexSolver = sGjkSimplexSolver; + +struct btDrawingResult : public btCollisionWorld::ContactResultCallback +{ + virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1) + { + + glBegin(GL_LINES); + glColor3f(0, 0, 0); + + btVector3 ptA = cp.getPositionWorldOnA(); + btVector3 ptB = cp.getPositionWorldOnB(); + + glVertex3d(ptA.x(),ptA.y(),ptA.z()); + glVertex3d(ptB.x(),ptB.y(),ptB.z()); + glEnd(); + + return 0; + } +}; + +void CollisionInterfaceDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glDisable(GL_LIGHTING); + + btScalar m[16]; + + btVector3 worldBoundsMin,worldBoundsMax; + collisionWorld->getBroadphase()->getBroadphaseAabb(worldBoundsMin,worldBoundsMax); + + + int i; + for (i=0;idrawOpenGL(m,objects[i].getCollisionShape(),btVector3(1,1,1),getDebugMode(),worldBoundsMin,worldBoundsMax); + } + + collisionWorld->getDispatchInfo().m_debugDraw = &debugDrawer; + + if (collisionWorld) + collisionWorld->performDiscreteCollisionDetection(); + + + + + +#ifndef TEST_NOT_ADDING_OBJECTS_TO_WORLD + + collisionWorld->debugDrawWorld(); + ///one way to draw all the contact points is iterating over contact manifolds in the dispatcher: + + int numManifolds = collisionWorld->getDispatcher()->getNumManifolds(); + for (i=0;igetDispatcher()->getManifoldByIndexInternal(i); + btCollisionObject* obA = static_cast(contactManifold->getBody0()); + btCollisionObject* obB = static_cast(contactManifold->getBody1()); + + int numContacts = contactManifold->getNumContacts(); + for (int j=0;jgetContactPoint(j); + + glBegin(GL_LINES); + glColor3f(0, 0, 0); + + btVector3 ptA = pt.getPositionWorldOnA(); + btVector3 ptB = pt.getPositionWorldOnB(); + + glVertex3d(ptA.x(),ptA.y(),ptA.z()); + glVertex3d(ptB.x(),ptB.y(),ptB.z()); + glEnd(); + } + + //you can un-comment out this line, and then all points are removed + //contactManifold->clearManifold(); + } +#else + + + glDisable(GL_TEXTURE_2D); + for (i=0;idebugDrawObject(objects[i].getWorldTransform(),objects[i].getCollisionShape(), btVector3(1,1,0)); + } + + btDrawingResult renderCallback; + + //collisionWorld->contactPairTest(&objects[0],&objects[1], renderCallback); + collisionWorld->contactTest(&objects[0],renderCallback); + +#if 0 + + //another way is to directly query the dispatcher for both objects. The objects don't need to be inserted into the world + + btCollisionAlgorithm* algo = collisionWorld->getDispatcher()->findAlgorithm(&objects[0],&objects[1]); + btManifoldResult contactPointResult(&objects[0],&objects[1]); + algo->processCollision(&objects[0],&objects[1],collisionWorld->getDispatchInfo(),&contactPointResult); + + btManifoldArray manifoldArray; + algo->getAllContactManifolds(manifoldArray); + + int numManifolds = manifoldArray.size(); + for (i=0;i(contactManifold->getBody0()); + // btCollisionObject* obB = static_cast(contactManifold->getBody1()); + + glDisable(GL_DEPTH_TEST); + int numContacts = contactManifold->getNumContacts(); + bool swap = obA == &objects[0]; + + for (int j=0;jgetContactPoint(j); + + glBegin(GL_LINES); + glColor3f(0, 0, 0); + + btVector3 ptA = swap ?pt.getPositionWorldOnA():pt.getPositionWorldOnB(); + btVector3 ptB = swap ? pt.getPositionWorldOnB():pt.getPositionWorldOnA(); + + glVertex3d(ptA.x(),ptA.y(),ptA.z()); + glVertex3d(ptB.x(),ptB.y(),ptB.z()); + glEnd(); + } + + //you can un-comment out this line, and then all points are removed + //contactManifold->clearManifold(); + } +#endif + + +#endif + + + + + + //GL_ShapeDrawer::drawCoordSystem(); + + + btQuaternion qA = objects[0].getWorldTransform().getRotation(); + btQuaternion qB = objects[1].getWorldTransform().getRotation(); + + + if (!m_idle) + { + + + btScalar timeInSeconds = getDeltaTimeMicroseconds()/1000.f; + + btQuaternion orn; + + objects[0].getWorldTransform().getBasis().getEulerYPR(yaw,pitch,roll); + pitch += 0.00005f*timeInSeconds; + yaw += 0.0001f*timeInSeconds; + objects[0].getWorldTransform().getBasis().setEulerYPR(yaw,pitch,roll); + + orn.setEuler(yaw,pitch,roll); + objects[1].getWorldTransform().setOrigin(objects[1].getWorldTransform().getOrigin()+btVector3(0,-0.00001*timeInSeconds,0)); + + //objects[0].getWorldTransform().setRotation(orn); + + + + } + + glFlush(); + swapBuffers(); +} + +void CollisionInterfaceDemo::clientResetScene() +{ + objects[0].getWorldTransform().setOrigin(btVector3(0.0f,3.f,0.f)); + + btQuaternion rotA(0.739f,-0.204f,0.587f,0.257f); + rotA.normalize(); + + objects[0].getWorldTransform().setRotation(rotA); + + objects[1].getWorldTransform().setOrigin(btVector3(0.0f,4.248f,0.f)); + +} + + diff --git a/Demos/CollisionInterfaceDemo/CollisionInterfaceDemo.h b/Demos/CollisionInterfaceDemo/CollisionInterfaceDemo.h new file mode 100644 index 0000000..9c0d611 --- /dev/null +++ b/Demos/CollisionInterfaceDemo/CollisionInterfaceDemo.h @@ -0,0 +1,42 @@ +/* +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 COLLISION_INTERFACE_DEMO_H +#define COLLISION_INTERFACE_DEMO_H + +#ifdef _WINDOWS +#include "Win32DemoApplication.h" +#define PlatformDemoApplication Win32DemoApplication +#else +#include "GlutDemoApplication.h" +#define PlatformDemoApplication GlutDemoApplication +#endif + +///CollisionInterfaceDemo shows how to use the collision detection without dynamics (btCollisionWorld/CollisionObject) +class CollisionInterfaceDemo : public PlatformDemoApplication +{ + public: + + void initPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + virtual void clientResetScene(); + +}; + +#endif //COLLISION_INTERFACE_DEMO_H + diff --git a/Demos/CollisionInterfaceDemo/Win32CollisionInterfaceDemo.cpp b/Demos/CollisionInterfaceDemo/Win32CollisionInterfaceDemo.cpp new file mode 100644 index 0000000..c2f5906 --- /dev/null +++ b/Demos/CollisionInterfaceDemo/Win32CollisionInterfaceDemo.cpp @@ -0,0 +1,25 @@ +#ifdef _WINDOWS +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "CollisionInterfaceDemo.h" + +///The 'createDemo' function is called from Bullet/Demos/OpenGL/Win32AppMain.cpp to instantiate this particular demo +DemoApplication* createDemo() +{ + return new CollisionInterfaceDemo(); +} + +#endif diff --git a/Demos/CollisionInterfaceDemo/main.cpp b/Demos/CollisionInterfaceDemo/main.cpp new file mode 100644 index 0000000..f8cbb77 --- /dev/null +++ b/Demos/CollisionInterfaceDemo/main.cpp @@ -0,0 +1,19 @@ + +#include "CollisionInterfaceDemo.h" +#include "GlutStuff.h" +#include "btBulletDynamicsCommon.h" + +int screenWidth = 640; +int screenHeight = 480; + + +int main(int argc,char** argv) +{ + CollisionInterfaceDemo* collisionInterfaceDemo = new CollisionInterfaceDemo(); + + collisionInterfaceDemo->initPhysics(); + + collisionInterfaceDemo->clientResetScene(); + + return glutmain(argc, argv,screenWidth,screenHeight,"Collision Interface Demo",collisionInterfaceDemo); +} diff --git a/Demos/ConcaveConvexcastDemo/CMakeLists.txt b/Demos/ConcaveConvexcastDemo/CMakeLists.txt new file mode 100644 index 0000000..bf0c2bc --- /dev/null +++ b/Demos/ConcaveConvexcastDemo/CMakeLists.txt @@ -0,0 +1,48 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppConcaveConvexCastDemo + ConcaveConvexcastDemo.cpp + main.cpp +) + +IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppConcaveConvexCastDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppConcaveConvexCastDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF(WIN32) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppConcaveConvexCastDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppConcaveConvexCastDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppConcaveConvexCastDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/ConcaveConvexcastDemo/ConcaveConvexcastDemo.cpp b/Demos/ConcaveConvexcastDemo/ConcaveConvexcastDemo.cpp new file mode 100644 index 0000000..9509482 --- /dev/null +++ b/Demos/ConcaveConvexcastDemo/ConcaveConvexcastDemo.cpp @@ -0,0 +1,516 @@ +/* +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 "BulletCollision/CollisionShapes/btBoxShape.h" +#include "GLDebugDrawer.h" +#include "ConcaveConvexcastDemo.h" +#include "GL_ShapeDrawer.h" +#include "GlutStuff.h" + +#define NUM_DYNAMIC_BOXES_X 30 +#define NUM_DYNAMIC_BOXES_Y 30 + +static btVector3* gVertices=0; +static int* gIndices=0; +static btBvhTriangleMeshShape* trimeshShape =0; +static btRigidBody* staticBody = 0; +static float waveheight = 5.f; + +const float TRIANGLE_SIZE=8.f; + + +/* Scrolls back and forth over terrain */ +#define NUMRAYS_IN_BAR 100 +class btConvexcastBatch +{ +public: + btVector3 source[NUMRAYS_IN_BAR]; + btVector3 dest[NUMRAYS_IN_BAR]; + btVector3 direction[NUMRAYS_IN_BAR]; + btVector3 hit_com[NUMRAYS_IN_BAR]; + btVector3 hit_surface[NUMRAYS_IN_BAR]; + btScalar hit_fraction[NUMRAYS_IN_BAR]; + btVector3 normal[NUMRAYS_IN_BAR]; + + int frame_counter; + int ms; + int sum_ms; + int sum_ms_samples; + int min_ms; + int max_ms; + +#ifdef USE_BT_CLOCK + btClock frame_timer; +#endif //USE_BT_CLOCK + + btScalar dx; + btScalar min_x; + btScalar max_x; + btScalar min_y; + btScalar max_y; + btScalar sign; + + btVector3 boxShapeHalfExtents; + btBoxShape boxShape; + + btConvexcastBatch () : boxShape(btVector3(0.0, 0.0, 0.0)) + { + ms = 0; + max_ms = 0; + min_ms = 9999.0; + sum_ms_samples = 0; + sum_ms = 0; + } + + btConvexcastBatch (bool unused, btScalar ray_length, btScalar min_z, btScalar max_z, btScalar min_y , btScalar max_y ) : boxShape(btVector3(0.0, 0.0, 0.0)) + { + boxShapeHalfExtents = btVector3(1.0, 1.0, 1.0); + boxShape = btBoxShape(boxShapeHalfExtents); + frame_counter = 0; + ms = 0; + max_ms = 0; + min_ms = 9999.0; + sum_ms_samples = 0; + sum_ms = 0; + dx = 10.0; + min_x = -40; + max_x = 20; + this->min_y = min_y; + this->max_y = max_y; + sign = 1.0; + btScalar dalpha = 2*SIMD_2_PI/NUMRAYS_IN_BAR; + for (int i = 0; i < NUMRAYS_IN_BAR; i++) + { + btScalar z = (max_z-min_z)/NUMRAYS_IN_BAR * i + min_z; + source[i] = btVector3(min_x, max_y, z); + dest[i] = btVector3(min_x + ray_length, min_y, z); + normal[i] = btVector3(1.0, 0.0, 0.0); + } + } + + btConvexcastBatch (btScalar ray_length, btScalar z, btScalar min_y = -1000, btScalar max_y = 10) : boxShape(btVector3(0.0, 0.0, 0.0)) + { + boxShapeHalfExtents = btVector3(1.0, 1.0, 1.0); + boxShape = btBoxShape(boxShapeHalfExtents); + frame_counter = 0; + ms = 0; + max_ms = 0; + min_ms = 9999.0; + sum_ms_samples = 0; + sum_ms = 0; + dx = 10.0; + min_x = -40; + max_x = 20; + this->min_y = min_y; + this->max_y = max_y; + sign = 1.0; + btScalar dalpha = btScalar(2)*SIMD_2_PI/btScalar(NUMRAYS_IN_BAR); + for (int i = 0; i < NUMRAYS_IN_BAR; i++) + { + btScalar alpha = dalpha * btScalar(i); + // rotate around by alpha degrees y + btTransform tr(btQuaternion(btVector3(0.0, 1.0, 0.0), alpha)); + direction[i] = btVector3(1.0, 0.0, 0.0); + direction[i] = tr * direction[i]; + source[i] = btVector3(min_x, max_y, z); + dest[i] = source[i] + direction[i] * ray_length; + dest[i][1] = min_y; + normal[i] = btVector3(1.0, 0.0, 0.0); + } + } + + void move (btScalar dt) + { + if (dt > (1.0/60.0)) + dt = 1.0/60.0; + for (int i = 0; i < NUMRAYS_IN_BAR; i++) + { + source[i][0] += dx * dt * sign; + dest[i][0] += dx * dt * sign; + } + if (source[0][0] < min_x) + sign = 1.0; + else if (source[0][0] > max_x) + sign = -1.0; + } + + void cast (btCollisionWorld* cw) + { +#ifdef USE_BT_CLOCK + frame_timer.reset (); +#endif //USE_BT_CLOCK + for (int i = 0; i < NUMRAYS_IN_BAR; i++) + { + btCollisionWorld::ClosestConvexResultCallback cb(source[i], dest[i]); + btQuaternion qFrom; + btQuaternion qTo; + qFrom.setRotation (btVector3(1.0, 0.0, 0.0), 0.0); + qTo.setRotation (btVector3(1.0, 0.0, 0.0), 0.7); + btTransform from(qFrom, source[i]); + btTransform to(qTo, dest[i]); + cw->convexSweepTest (&boxShape, from, to, cb); + if (cb.hasHit ()) + { + hit_surface[i] = cb.m_hitPointWorld; + hit_com[i].setInterpolate3(source[i], dest[i], cb.m_closestHitFraction); + hit_fraction[i] = cb.m_closestHitFraction; + normal[i] = cb.m_hitNormalWorld; + normal[i].normalize (); + } else { + hit_com[i] = dest[i]; + hit_surface[i] = dest[i]; + hit_fraction[i] = 1.0f; + normal[i] = btVector3(1.0, 0.0, 0.0); + } + + } +#ifdef USE_BT_CLOCK + ms += frame_timer.getTimeMilliseconds (); +#endif //USE_BT_CLOCK + frame_counter++; + if (frame_counter > 50) + { + min_ms = ms < min_ms ? ms : min_ms; + max_ms = ms > max_ms ? ms : max_ms; + sum_ms += ms; + sum_ms_samples++; + btScalar mean_ms = (btScalar)sum_ms/(btScalar)sum_ms_samples; + printf("%d rays in %d ms %d %d %f\n", NUMRAYS_IN_BAR * frame_counter, ms, min_ms, max_ms, mean_ms); + ms = 0; + frame_counter = 0; + } + } + + + void drawCube (const btTransform& T) + { + btScalar m[16]; + T.getOpenGLMatrix (&m[0]); + glPushMatrix (); +#ifdef BT_USE_DOUBLE_PRECISION + glMultMatrixd (&m[0]); + glScaled (2.0 * boxShapeHalfExtents[0], 2.0 * boxShapeHalfExtents[1], 2.0 * boxShapeHalfExtents[2]); +#else + glMultMatrixf (&m[0]); + glScalef (2.0 * boxShapeHalfExtents[0], 2.0 * boxShapeHalfExtents[1], 2.0 * boxShapeHalfExtents[2]); +#endif //BT_USE_DOUBLE_PRECISION + glutSolidCube (1.0); + glPopMatrix (); + } + + void draw () + { + glDisable (GL_LIGHTING); + glColor3f (0.0, 1.0, 0.0); + glBegin (GL_LINES); + int i; + for (i = 0; i < NUMRAYS_IN_BAR; i++) + { + glVertex3f (source[i][0], source[i][1], source[i][2]); + glVertex3f (hit_com[i][0], hit_com[i][1], hit_com[i][2]); + } + glColor3f (1.0, 1.0, 1.0); + glBegin (GL_LINES); + btScalar normal_scale = 10.0; // easier to see if this is big + for (i = 0; i < NUMRAYS_IN_BAR; i++) + { + glVertex3f (hit_surface[i][0], hit_surface[i][1], hit_surface[i][2]); + glVertex3f (hit_surface[i][0] + normal_scale * normal[i][0], hit_surface[i][1] + normal_scale * normal[i][1], hit_surface[i][2] + normal_scale * normal[i][2]); + } + glEnd (); + glColor3f (0.0, 1.0, 1.0); + btQuaternion qFrom; + btQuaternion qTo; + qFrom.setRotation (btVector3(1.0, 0.0, 0.0), 0.0); + qTo.setRotation (btVector3(1.0, 0.0, 0.0), 0.7); + for ( i = 0; i < NUMRAYS_IN_BAR; i++) + { + btTransform from(qFrom, source[i]); + btTransform to(qTo, dest[i]); + btVector3 linVel, angVel; + btTransformUtil::calculateVelocity (from, to, 1.0, linVel, angVel); + btTransform T; + btTransformUtil::integrateTransform (from, linVel, angVel, hit_fraction[i], T); + drawCube (T); + } + glEnable (GL_LIGHTING); + } +}; + + +static btConvexcastBatch convexcastBatch; + + + + + +const int NUM_VERTS_X = 30; +const int NUM_VERTS_Y = 30; +const int totalVerts = NUM_VERTS_X*NUM_VERTS_Y; + +void ConcaveConvexcastDemo::setVertexPositions(float waveheight, float offset) +{ + int i; + int j; + + for ( i=0;isetCollisionFlags( staticBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + staticBody->setActivationState(DISABLE_DEACTIVATION); + } else + { + staticBody->setCollisionFlags( staticBody->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT); + staticBody->forceActivationState(ACTIVE_TAG); + } + } + + DemoApplication::keyboardCallback(key,x,y); + +} + +void ConcaveConvexcastDemo::initPhysics() +{ + #define TRISIZE 10.f + + setCameraDistance(100.f); + + + int vertStride = sizeof(btVector3); + int indexStride = 3*sizeof(int); + + + const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1); + + gVertices = new btVector3[totalVerts]; + gIndices = new int[totalTriangles*3]; + + int i; + + + setVertexPositions(waveheight,0.f); + + int index=0; + for ( i=0;isetCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT); + + //enable custom material callback + staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + + convexcastBatch = btConvexcastBatch (40.0, 0.0, -10.0,80.0); + //convexcastBatch = btConvexcastBatch (true, 40.0, -50.0, 50.0); +} + +void ConcaveConvexcastDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + float dt = getDeltaTimeMicroseconds() * 0.000001f; + + if (m_animatedMesh) + { + static float offset=0.f; + offset+=0.01f; + + + + int i; + int j; + btVector3 aabbMin(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); + btVector3 aabbMax(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT); + + for ( i=NUM_VERTS_X/2-3;ipartialRefitTree(aabbMin,aabbMax); + + + //clear all contact points involving mesh proxy. Note: this is a slow/unoptimized operation. + m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(staticBody->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher()); + } + + m_dynamicsWorld->stepSimulation(dt); + + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + + convexcastBatch.move (dt); + convexcastBatch.cast (m_dynamicsWorld); + renderme(); + convexcastBatch.draw (); + glFlush(); + glutSwapBuffers(); + +} + + + + +void ConcaveConvexcastDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + convexcastBatch.draw (); + glFlush(); + glutSwapBuffers(); +} + + + +void ConcaveConvexcastDemo::exitPhysics() +{ + + + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;j m_collisionShapes; + + btTriangleIndexVertexArray* m_indexVertexArrays; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + bool m_animatedMesh; + + public: + + ConcaveConvexcastDemo() : m_animatedMesh(true) + { + + } + void initPhysics(); + + void exitPhysics(); + + virtual ~ConcaveConvexcastDemo() + { + exitPhysics(); + } + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + //to show refit works + void setVertexPositions(float waveheight, float offset); + + virtual void keyboardCallback(unsigned char key, int x, int y); + + static DemoApplication* Create() + { + ConcaveConvexcastDemo* demo = new ConcaveConvexcastDemo(); + demo->myinit(); + demo->initPhysics(); + return demo; + }; +}; + +#endif //CONCAVE_CONVEXCAST_DEMO_H + diff --git a/Demos/ConcaveConvexcastDemo/main.cpp b/Demos/ConcaveConvexcastDemo/main.cpp new file mode 100644 index 0000000..6f405b6 --- /dev/null +++ b/Demos/ConcaveConvexcastDemo/main.cpp @@ -0,0 +1,15 @@ + +#include "ConcaveConvexcastDemo.h" +#include "GlutStuff.h" + + +int main(int argc,char** argv) +{ + + ConcaveConvexcastDemo* concaveConvexcastDemo = new ConcaveConvexcastDemo(); + concaveConvexcastDemo->initPhysics(); + concaveConvexcastDemo->setCameraDistance(30.f); + + return glutmain(argc, argv,640,480,"Concave Convexcast Demo",concaveConvexcastDemo); +} + diff --git a/Demos/ConcaveDemo/CMakeLists.txt b/Demos/ConcaveDemo/CMakeLists.txt new file mode 100644 index 0000000..4de3e42 --- /dev/null +++ b/Demos/ConcaveDemo/CMakeLists.txt @@ -0,0 +1,80 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + + +# You shouldn't have to modify anything below this line +######################################################## + +IF (USE_GLUT) + INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL + ${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletFileLoader + ${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletWorldImporter + ) + + LINK_LIBRARIES( + OpenGLSupport BulletWorldImporter BulletDynamics BulletCollision BulletFileLoader LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + IF (WIN32) + ADD_EXECUTABLE(AppConcaveDemo + ConcavePhysicsDemo.cpp + main.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) + ELSE() + ADD_EXECUTABLE(AppConcaveDemo + ConcavePhysicsDemo.cpp + main.cpp + ) + ENDIF() + IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppConcaveDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppConcaveDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ENDIF(WIN32) +ELSE (USE_GLUT) + + INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL + ${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletFileLoader + ${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletWorldImporter + ) + + LINK_LIBRARIES( + OpenGLSupport BulletWorldImporter BulletDynamics BulletCollision BulletFileLoader LinearMath ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + ADD_EXECUTABLE(AppConcaveDemo + WIN32 + ../OpenGL/Win32AppMain.cpp + ConcavePhysicsDemo.cpp + ConcaveDemo.h + Win32ConcaveDemo.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) + +ENDIF (USE_GLUT) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppConcaveDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppConcaveDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppConcaveDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/ConcaveDemo/ConcaveDemo.h b/Demos/ConcaveDemo/ConcaveDemo.h new file mode 100644 index 0000000..86144c7 --- /dev/null +++ b/Demos/ConcaveDemo/ConcaveDemo.h @@ -0,0 +1,91 @@ +/* +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 CONCAVE_DEMO_H +#define CONCAVE_DEMO_H + +#ifdef _WINDOWS +#include "Win32DemoApplication.h" +#define PlatformDemoApplication Win32DemoApplication +#else +#include "GlutDemoApplication.h" +#define PlatformDemoApplication GlutDemoApplication +#endif + +#include "LinearMath/btAlignedObjectArray.h" + +class btBroadphaseInterface; +class btCollisionShape; +class btOverlappingPairCache; +class btCollisionDispatcher; +class btConstraintSolver; +struct btCollisionAlgorithmCreateFunc; +class btDefaultCollisionConfiguration; +class btTriangleIndexVertexArray; + +///ConcaveDemo shows usage of static concave triangle meshes +///It also shows per-triangle material (friction/restitution) through CustomMaterialCombinerCallback +class ConcaveDemo : public PlatformDemoApplication +{ + + //keep the collision shapes, for deletion/cleanup + btAlignedObjectArray m_collisionShapes; + + btTriangleIndexVertexArray* m_indexVertexArrays; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + bool m_animatedMesh; + + public: + + ConcaveDemo() : m_animatedMesh(true) + { + + } + void initPhysics(); + + void exitPhysics(); + + virtual ~ConcaveDemo() + { + exitPhysics(); + } + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + //to show refit works + void setVertexPositions(float waveheight, float offset); + + virtual void keyboardCallback(unsigned char key, int x, int y); + + static DemoApplication* Create() + { + ConcaveDemo* demo = new ConcaveDemo(); + demo->myinit(); + demo->initPhysics(); + return demo; + }; +}; + +#endif //CONCAVE_DEMO_H + diff --git a/Demos/ConcaveDemo/ConcavePhysicsDemo.cpp b/Demos/ConcaveDemo/ConcavePhysicsDemo.cpp new file mode 100644 index 0000000..d4f40df --- /dev/null +++ b/Demos/ConcaveDemo/ConcavePhysicsDemo.cpp @@ -0,0 +1,474 @@ +/* +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 "GLDebugDrawer.h" +#include "ConcaveDemo.h" +#include "GL_ShapeDrawer.h" +#include "GlutStuff.h" + +#define SERIALIZE_TO_DISK 1 + +#ifndef SERIALIZE_TO_DISK +#include "btBulletWorldImporter.h" +#endif //SERIALIZE_TO_DISK + +//by default, the sample only (de)serializes the BVH to disk. +//If you enable the SERIALIZE_SHAPE define then it will serialize the entire collision shape +//then the animation will not play, because it is using the deserialized vertices +//#define SERIALIZE_SHAPE + + + + +//#define USE_PARALLEL_DISPATCHER 1 +#ifdef USE_PARALLEL_DISPATCHER +#include "../../Extras/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h" +#include "../../Extras/BulletMultiThreaded/Win32ThreadSupport.h" +#include "../../Extras/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" +#endif//USE_PARALLEL_DISPATCHER + + + + +static btVector3* gVertices=0; +static int* gIndices=0; +static btBvhTriangleMeshShape* trimeshShape =0; +static btRigidBody* staticBody = 0; +static float waveheight = 5.f; + +const float TRIANGLE_SIZE=8.f; + + + +///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; +inline btScalar calculateCombinedFriction(float friction0,float friction1) +{ + btScalar friction = friction0 * friction1; + + const btScalar MAX_FRICTION = 10.f; + if (friction < -MAX_FRICTION) + friction = -MAX_FRICTION; + if (friction > MAX_FRICTION) + friction = MAX_FRICTION; + return friction; + +} + +inline btScalar calculateCombinedRestitution(float restitution0,float restitution1) +{ + return restitution0 * restitution1; +} + + + +static bool CustomMaterialCombinerCallback(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1) +{ + + float friction0 = colObj0->getFriction(); + float friction1 = colObj1->getFriction(); + float restitution0 = colObj0->getRestitution(); + float restitution1 = colObj1->getRestitution(); + + if (colObj0->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) + { + friction0 = 1.0;//partId0,index0 + restitution0 = 0.f; + } + if (colObj1->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) + { + if (index1&1) + { + friction1 = 1.0f;//partId1,index1 + } else + { + friction1 = 0.f; + } + restitution1 = 0.f; + } + + cp.m_combinedFriction = calculateCombinedFriction(friction0,friction1); + cp.m_combinedRestitution = calculateCombinedRestitution(restitution0,restitution1); + + //this return value is currently ignored, but to be on the safe side: return false if you don't calculate friction + return true; +} + +extern ContactAddedCallback gContactAddedCallback; + + const int NUM_VERTS_X = 30; + const int NUM_VERTS_Y = 30; + const int totalVerts = NUM_VERTS_X*NUM_VERTS_Y; + +void ConcaveDemo::setVertexPositions(float waveheight, float offset) +{ + int i; + int j; + + for ( i=0;isetCollisionFlags( staticBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + staticBody->setActivationState(DISABLE_DEACTIVATION); + } else + { + staticBody->setCollisionFlags( staticBody->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT); + staticBody->forceActivationState(ACTIVE_TAG); + } + } + + DemoApplication::keyboardCallback(key,x,y); + +} + +void ConcaveDemo::initPhysics() +{ + + setTexturing(true); + setShadows(false);//true); + + #define TRISIZE 10.f + + gContactAddedCallback = CustomMaterialCombinerCallback; + +#define USE_TRIMESH_SHAPE 1 +#ifdef USE_TRIMESH_SHAPE + + int vertStride = sizeof(btVector3); + int indexStride = 3*sizeof(int); + + + const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1); + + gVertices = new btVector3[totalVerts]; + gIndices = new int[totalTriangles*3]; + + int i; + + + setVertexPositions(waveheight,0.f); + + int index=0; + for ( i=0;isetSerializationFlags(BT_SERIALIZE_NO_BVH);// or BT_SERIALIZE_NO_TRIANGLEINFOMAP + serializer->startSerialization(); + //registering a name is optional, it allows you to retrieve the shape by name + //serializer->registerNameForPointer(trimeshShape,"mymesh"); +#ifdef SERIALIZE_SHAPE + trimeshShape->serializeSingleShape(serializer); +#else + trimeshShape->serializeSingleBvh(serializer); +#endif + serializer->finishSerialization(); + FILE* f2 = fopen("myShape.bullet","wb"); + fwrite(serializer->getBufferPointer(),serializer->getCurrentBufferSize(),1,f2); + fclose(f2); + +#else + btBulletWorldImporter import(0);//don't store info into the world + if (import.loadFile("myShape.bullet")) + { + int numBvh = import.getNumBvhs(); + if (numBvh) + { + btOptimizedBvh* bvh = import.getBvhByIndex(0); + btVector3 aabbMin(-1000,-1000,-1000),aabbMax(1000,1000,1000); + + trimeshShape = new btBvhTriangleMeshShape(m_indexVertexArrays,useQuantizedAabbCompression,aabbMin,aabbMax,false); + trimeshShape->setOptimizedBvh(bvh); + //trimeshShape = new btBvhTriangleMeshShape(m_indexVertexArrays,useQuantizedAabbCompression,aabbMin,aabbMax); + //trimeshShape->setOptimizedBvh(bvh); + + } + int numShape = import.getNumCollisionShapes(); + if (numShape) + { + trimeshShape = (btBvhTriangleMeshShape*)import.getCollisionShapeByIndex(0); + + //if you know the name, you can also try to get the shape by name: + const char* meshName = import.getNameForPointer(trimeshShape); + if (meshName) + trimeshShape = (btBvhTriangleMeshShape*)import.getCollisionShapeByName(meshName); + + } + } + + +#endif + + btCollisionShape* groundShape = trimeshShape; + +#else + btCollisionShape* groundShape = new btBoxShape(btVector3(50,3,50)); + m_collisionShapes.push_back(groundShape); + +#endif //USE_TRIMESH_SHAPE + + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + +#ifdef USE_PARALLEL_DISPATCHER + +#ifdef USE_WIN32_THREADING + + int maxNumOutstandingTasks = 4;//number of maximum outstanding tasks + Win32ThreadSupport* threadSupport = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo( + "collision", + processCollisionTask, + createCollisionLocalStoreMemory, + maxNumOutstandingTasks)); +#else +///@todo show other platform threading +///Playstation 3 SPU (SPURS) version is available through PS3 Devnet +///Libspe2 SPU support will be available soon +///pthreads version +///you can hook it up to your custom task scheduler by deriving from btThreadSupportInterface +#endif + + m_dispatcher = new SpuGatheringCollisionDispatcher(threadSupport,maxNumOutstandingTasks,m_collisionConfiguration); +#else + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); +#endif//USE_PARALLEL_DISPATCHER + + + btVector3 worldMin(-1000,-1000,-1000); + btVector3 worldMax(1000,1000,1000); + m_broadphase = new btAxisSweep3(worldMin,worldMax); + m_solver = new btSequentialImpulseConstraintSolver(); + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); +#ifdef USE_PARALLEL_DISPATCHER + m_dynamicsWorld->getDispatchInfo().m_enableSPU=true; +#endif //USE_PARALLEL_DISPATCHER + + float mass = 0.f; + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(0,-2,0)); + +#ifdef USE_BOX_SHAPE + btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1)); +#else + + btCompoundShape* colShape = new btCompoundShape; + btCollisionShape* cylinderShape = new btCylinderShapeX(btVector3(4,1,1)); + btCollisionShape* boxShape = new btBoxShape(btVector3(4,1,1)); + btTransform localTransform; + localTransform.setIdentity(); + colShape->addChildShape(localTransform,boxShape); + btQuaternion orn(SIMD_HALF_PI,0,0); + localTransform.setRotation(orn); + colShape->addChildShape(localTransform,cylinderShape); + +#endif //USE_BOX_SHAPE + + + m_collisionShapes.push_back(colShape); + + { + for (int i=0;i<10;i++) + { + startTransform.setOrigin(btVector3(2,10+i*2,1)); + localCreateRigidBody(1, startTransform,colShape); + } + } + + startTransform.setIdentity(); + staticBody = localCreateRigidBody(mass, startTransform,groundShape); + + staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);//STATIC_OBJECT); + + //enable custom material callback + staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + + + + +} + +void ConcaveDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + float dt = getDeltaTimeMicroseconds() * 0.000001f; + + if (m_animatedMesh) + { + static float offset=0.f; + offset+=dt; + + // setVertexPositions(waveheight,offset); + + int i; + int j; + btVector3 aabbMin(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); + btVector3 aabbMax(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT); + + for ( i=NUM_VERTS_X/2-3;ipartialRefitTree(aabbMin,aabbMax); + + //clear all contact points involving mesh proxy. Note: this is a slow/unoptimized operation. + m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(staticBody->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher()); + } + + m_dynamicsWorld->stepSimulation(dt); + + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + + + renderme(); + + glFlush(); + swapBuffers(); + +} + + + + +void ConcaveDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + //optional but useful: debug drawing + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + + glFlush(); + swapBuffers(); +} + + + +void ConcaveDemo::exitPhysics() +{ + + + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;jinitPhysics(); + concaveDemo->setCameraDistance(30.f); + concaveDemo->getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + return glutmain(argc, argv,640,480,"Static Concave Mesh Demo",concaveDemo); +} + diff --git a/Demos/ConcaveRaycastDemo/CMakeLists.txt b/Demos/ConcaveRaycastDemo/CMakeLists.txt new file mode 100644 index 0000000..71bb8ce --- /dev/null +++ b/Demos/ConcaveRaycastDemo/CMakeLists.txt @@ -0,0 +1,57 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +IF (WIN32) + ADD_EXECUTABLE(AppConcaveRayCastDemo + ConcaveRaycastDemo.cpp + main.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) +ELSE() + ADD_EXECUTABLE(AppConcaveRayCastDemo + ConcaveRaycastDemo.cpp + main.cpp + ) +ENDIF() + +IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppConcaveRayCastDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppConcaveRayCastDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF(WIN32) + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppConcaveRayCastDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppConcaveRayCastDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppConcaveRayCastDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/ConcaveRaycastDemo/ConcaveRaycastDemo.cpp b/Demos/ConcaveRaycastDemo/ConcaveRaycastDemo.cpp new file mode 100644 index 0000000..9f0e1d6 --- /dev/null +++ b/Demos/ConcaveRaycastDemo/ConcaveRaycastDemo.cpp @@ -0,0 +1,490 @@ +/* +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 "GLDebugDrawer.h" +#include "ConcaveRaycastDemo.h" +#include "GL_ShapeDrawer.h" +#include "GlutStuff.h" + +static GLDebugDrawer sDebugDraw; + +static btVector3* gVertices=0; +static int* gIndices=0; +static btBvhTriangleMeshShape* trimeshShape =0; +static btRigidBody* staticBody = 0; +static float waveheight = 5.f; + +const float TRIANGLE_SIZE=8.f; + + +/* Scrolls back and forth over terrain */ +#define NUMRAYS_IN_BAR 100 +class btRaycastBar +{ +public: + btVector3 source[NUMRAYS_IN_BAR]; + btVector3 dest[NUMRAYS_IN_BAR]; + btVector3 direction[NUMRAYS_IN_BAR]; + btVector3 hit[NUMRAYS_IN_BAR]; + btVector3 normal[NUMRAYS_IN_BAR]; + + int frame_counter; + int ms; + int sum_ms; + int sum_ms_samples; + int min_ms; + int max_ms; + +#ifdef USE_BT_CLOCK + btClock frame_timer; +#endif //USE_BT_CLOCK + + btScalar dx; + btScalar min_x; + btScalar max_x; + btScalar min_y; + btScalar max_y; + btScalar sign; + + btRaycastBar () + { + ms = 0; + max_ms = 0; + min_ms = 9999.0; + sum_ms_samples = 0; + sum_ms = 0; + } + + btRaycastBar (bool unused, btScalar ray_length, btScalar min_z, btScalar max_z, btScalar min_y = -10, btScalar max_y = 10) + { + frame_counter = 0; + ms = 0; + max_ms = 0; + min_ms = 9999.0; + sum_ms_samples = 0; + sum_ms = 0; + dx = 10.0; + min_x = -40; + max_x = 20; + this->min_y = min_y; + this->max_y = max_y; + sign = 1.0; + btScalar dalpha = 2*SIMD_2_PI/NUMRAYS_IN_BAR; + for (int i = 0; i < NUMRAYS_IN_BAR; i++) + { + btScalar z = (max_z-min_z)/btScalar(NUMRAYS_IN_BAR) * btScalar(i) + min_z; + source[i] = btVector3(min_x, max_y, z); + dest[i] = btVector3(min_x + ray_length, min_y, z); + normal[i] = btVector3(1.0, 0.0, 0.0); + } + } + + btRaycastBar (btScalar ray_length, btScalar z, btScalar min_y = -1000, btScalar max_y = 10) + { + frame_counter = 0; + ms = 0; + max_ms = 0; + min_ms = 9999.0; + sum_ms_samples = 0; + sum_ms = 0; + dx = 10.0; + min_x = -40; + max_x = 20; + this->min_y = min_y; + this->max_y = max_y; + sign = 1.0; + btScalar dalpha = 2*SIMD_2_PI/NUMRAYS_IN_BAR; + for (int i = 0; i < NUMRAYS_IN_BAR; i++) + { + btScalar alpha = dalpha * i; + // rotate around by alpha degrees y + btTransform tr (btQuaternion (btVector3(0.0, 1.0, 0.0), alpha)); + direction[i] = btVector3(1.0, 0.0, 0.0); + direction[i] = tr* direction[i]; + direction[i] = direction[i] * ray_length; + source[i] = btVector3(min_x, max_y, z); + dest[i] = source[i] + direction[i]; + dest[i][1] = min_y; + normal[i] = btVector3(1.0, 0.0, 0.0); + } + } + + void move (btScalar dt) + { + if (dt > (1.0/60.0)) + dt = 1.0/60.0; + for (int i = 0; i < NUMRAYS_IN_BAR; i++) + { + source[i][0] += dx * dt * sign; + dest[i][0] += dx * dt * sign; + } + if (source[0][0] < min_x) + sign = 1.0; + else if (source[0][0] > max_x) + sign = -1.0; + } + + void cast (btCollisionWorld* cw) + { +#ifdef USE_BT_CLOCK + frame_timer.reset (); +#endif //USE_BT_CLOCK + +#ifdef BATCH_RAYCASTER + if (!gBatchRaycaster) + return; + + gBatchRaycaster->clearRays (); + for (int i = 0; i < NUMRAYS_IN_BAR; i++) + { + gBatchRaycaster->addRay (source[i], dest[i]); + } + gBatchRaycaster->performBatchRaycast (); + for (int i = 0; i < gBatchRaycaster->getNumRays (); i++) + { + const SpuRaycastTaskWorkUnitOut& out = (*gBatchRaycaster)[i]; + hit[i].setInterpolate3(source[i],dest[i],out.hitFraction); + normal[i] = out.hitNormal; + normal[i].normalize (); + } +#else + for (int i = 0; i < NUMRAYS_IN_BAR; 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); + } + + } +#ifdef USE_BT_CLOCK + ms += frame_timer.getTimeMilliseconds (); +#endif //USE_BT_CLOCK + frame_counter++; + if (frame_counter > 50) + { + min_ms = ms < min_ms ? ms : min_ms; + max_ms = ms > max_ms ? ms : max_ms; + sum_ms += ms; + sum_ms_samples++; + btScalar mean_ms = (btScalar)sum_ms/(btScalar)sum_ms_samples; + printf("%d rays in %d ms %d %d %f\n", NUMRAYS_IN_BAR * frame_counter, ms, min_ms, max_ms, mean_ms); + ms = 0; + frame_counter = 0; + } +#endif + } + + void draw () + { + glDisable (GL_LIGHTING); + glColor3f (0.0, 1.0, 0.0); + glBegin (GL_LINES); + int i; + + for (i = 0; i < NUMRAYS_IN_BAR; i++) + { + glVertex3f (source[i][0], source[i][1], source[i][2]); + glVertex3f (hit[i][0], hit[i][1], hit[i][2]); + } + glEnd (); + glColor3f (1.0, 1.0, 1.0); + glBegin (GL_LINES); + for (i = 0; i < NUMRAYS_IN_BAR; i++) + { + glVertex3f (hit[i][0], hit[i][1], hit[i][2]); + glVertex3f (hit[i][0] + normal[i][0], hit[i][1] + normal[i][1], hit[i][2] + normal[i][2]); + } + glEnd (); + glColor3f (0.0, 1.0, 1.0); + glBegin (GL_POINTS); + for ( i = 0; i < NUMRAYS_IN_BAR; i++) + { + glVertex3f (hit[i][0], hit[i][1], hit[i][2]); + } + glEnd (); + glEnable (GL_LIGHTING); + } +}; + + +static btRaycastBar raycastBar; + + +const int NUM_VERTS_X = 30; +const int NUM_VERTS_Y = 30; +const int totalVerts = NUM_VERTS_X*NUM_VERTS_Y; + +void ConcaveRaycastDemo::setVertexPositions(float waveheight, float offset) +{ + int i; + int j; + + for ( i=0;isetCollisionFlags( staticBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + staticBody->setActivationState(DISABLE_DEACTIVATION); + } else + { + staticBody->setCollisionFlags( staticBody->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT); + staticBody->forceActivationState(ACTIVE_TAG); + } + } + + DemoApplication::keyboardCallback(key,x,y); + +} + +void ConcaveRaycastDemo::initPhysics() +{ + + #define TRISIZE 10.f + + + + int vertStride = sizeof(btVector3); + int indexStride = 3*sizeof(int); + + + const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1); + + gVertices = new btVector3[totalVerts]; + gIndices = new int[totalTriangles*3]; + + int i; + + + setVertexPositions(waveheight,0.f); + + int index=0; + for ( i=0;igetSolverInfo().m_splitImpulse=true; + m_dynamicsWorld->setDebugDrawer(&sDebugDraw); + + float mass = 0.f; + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(0,-2,0)); + + btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1)); + m_collisionShapes.push_back(colShape); + + { + for (int i=0;i<10;i++) + { + //btCollisionShape* colShape = new btCapsuleShape(0.5,2.0);//boxShape = new btSphereShape(1.f); + startTransform.setOrigin(btVector3(2*i,10,1)); + localCreateRigidBody(1, startTransform,colShape); + } + } + + startTransform.setIdentity(); + staticBody = localCreateRigidBody(mass, startTransform,groundShape); + + staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT); + +#ifdef BATCH_RAYCASTER +int maxNumOutstandingTasks = 4; + +#ifdef USE_WIN32_THREADING + Win32ThreadSupport::Win32ThreadConstructionInfo tci("batch raycast", + processRaycastTask, + createRaycastLocalStoreMemory, + maxNumOutstandingTasks); + m_threadSupportRaycast = new Win32ThreadSupport(tci); + printf("m_threadSupportRaycast = %p\n", m_threadSupportRaycast); +#endif + + gBatchRaycaster = new SpuBatchRaycaster (m_threadSupportRaycast, maxNumOutstandingTasks, m_dynamicsWorld->getCollisionObjectArray(), m_dynamicsWorld->getNumCollisionObjects()); +#endif + + raycastBar = btRaycastBar (4000.0, 0.0); + //raycastBar = btRaycastBar (true, 40.0, -50.0, 50.0); + + + + + +} + +void ConcaveRaycastDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + float dt = getDeltaTimeMicroseconds() * 0.000001f; + + if (m_animatedMesh) + { + static float offset=0.f; + offset+=0.01f; + + setVertexPositions(waveheight,offset); + + btVector3 worldMin(-1000,-1000,-1000); + btVector3 worldMax(1000,1000,1000); + + trimeshShape->refitTree(worldMin,worldMax); + + //clear all contact points involving mesh proxy. Note: this is a slow/unoptimized operation. + m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(staticBody->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher()); + } + + m_dynamicsWorld->stepSimulation(1./60.,0); + + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + + raycastBar.move (dt); + raycastBar.cast (m_dynamicsWorld); + renderme(); + raycastBar.draw (); + glFlush(); + glutSwapBuffers(); + +} + + + + +void ConcaveRaycastDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //optional but useful: debug drawing + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + renderme(); + raycastBar.draw (); + glFlush(); + glutSwapBuffers(); +} + + + +void ConcaveRaycastDemo::exitPhysics() +{ + + + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;j m_collisionShapes; + + btTriangleIndexVertexArray* m_indexVertexArrays; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + class btThreadSupportInterface* m_threadSupportRaycast; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + bool m_animatedMesh; + + public: + + ConcaveRaycastDemo() : m_animatedMesh(false) + { + + } + void initPhysics(); + + void exitPhysics(); + + virtual ~ConcaveRaycastDemo() + { + exitPhysics(); + } + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + //to show refit works + void setVertexPositions(float waveheight, float offset); + + virtual void keyboardCallback(unsigned char key, int x, int y); + + static DemoApplication* Create() + { + ConcaveRaycastDemo* demo = new ConcaveRaycastDemo(); + demo->myinit(); + demo->initPhysics(); + return demo; + }; +}; + +#endif //CONCAVE_RAYCAST_DEMO_H + diff --git a/Demos/ConcaveRaycastDemo/main.cpp b/Demos/ConcaveRaycastDemo/main.cpp new file mode 100644 index 0000000..03fe36f --- /dev/null +++ b/Demos/ConcaveRaycastDemo/main.cpp @@ -0,0 +1,15 @@ + +#include "ConcaveRaycastDemo.h" +#include "GlutStuff.h" + + +int main(int argc,char** argv) +{ + + ConcaveRaycastDemo* concaveRaycastDemo = new ConcaveRaycastDemo(); + concaveRaycastDemo->initPhysics(); + concaveRaycastDemo->setCameraDistance(30.f); + + return glutmain(argc, argv,640,480,"Concave Raycast Demo",concaveRaycastDemo); +} + diff --git a/Demos/ConstraintDemo/CMakeLists.txt b/Demos/ConstraintDemo/CMakeLists.txt new file mode 100644 index 0000000..ad920d8 --- /dev/null +++ b/Demos/ConstraintDemo/CMakeLists.txt @@ -0,0 +1,69 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletFileLoader +${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletWorldImporter +) + + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport BulletWorldImporter BulletDynamics BulletCollision LinearMath BulletFileLoader ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + ADD_EXECUTABLE(AppConstraintDemo + ConstraintDemo.cpp + ConstraintDemo.h + main.cpp + ) + IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppConstraintDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppConstraintDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ENDIF(WIN32) +ELSE (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport BulletWorldImporter BulletDynamics BulletCollision LinearMath BulletFileLoader ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + ADD_EXECUTABLE(AppConstraintDemo + WIN32 + ../OpenGL/Win32AppMain.cpp + Win32ConstraintDemo.cpp + ConstraintDemo.cpp + ConstraintDemo.h + ) +ENDIF (USE_GLUT) + + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppConstraintDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppConstraintDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppConstraintDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/ConstraintDemo/ConstraintDemo.cpp b/Demos/ConstraintDemo/ConstraintDemo.cpp new file mode 100644 index 0000000..a35faa7 --- /dev/null +++ b/Demos/ConstraintDemo/ConstraintDemo.cpp @@ -0,0 +1,738 @@ +/* +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 "GLDebugDrawer.h" + +#include "GLDebugFont.h" +#include //printf debugging + +#include "ConstraintDemo.h" +#include "GL_ShapeDrawer.h" +#include "GlutStuff.h" + + +const int numObjects = 3; + +#define ENABLE_ALL_DEMOS 1 + +#define CUBE_HALF_EXTENTS 1.f + +#define SIMD_PI_2 ((SIMD_PI)*0.5f) +#define SIMD_PI_4 ((SIMD_PI)*0.25f) + + + + +btTransform sliderTransform; +btVector3 lowerSliderLimit = btVector3(-10,0,0); +btVector3 hiSliderLimit = btVector3(10,0,0); + +btRigidBody* d6body0 =0; + +btHingeConstraint* spDoorHinge = NULL; +btHingeConstraint* spHingeDynAB = NULL; +btGeneric6DofConstraint* spSlider6Dof = NULL; + +static bool s_bTestConeTwistMotor = false; + + + +void drawLimit() +{ + btVector3 from = sliderTransform*lowerSliderLimit; + btVector3 to = sliderTransform*hiSliderLimit; + btVector3 color(255,0,0); + glBegin(GL_LINES); + glColor3f(color.getX(), color.getY(), color.getZ()); + glVertex3d(from.getX(), from.getY(), from.getZ()); + glVertex3d(to.getX(), to.getY(), to.getZ()); + if (d6body0) + { + from = d6body0->getWorldTransform().getOrigin(); + to = from + d6body0->getWorldTransform().getBasis() * btVector3(0,0,10); + glVertex3d(from.getX(), from.getY(), from.getZ()); + glVertex3d(to.getX(), to.getY(), to.getZ()); + } + glEnd(); +} + + +void ConstraintDemo::setupEmptyDynamicsWorld() +{ + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + m_overlappingPairCache = new btDbvtBroadphase(); + m_constraintSolver = new btSequentialImpulseConstraintSolver(); + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_constraintSolver,m_collisionConfiguration); + +} + +void ConstraintDemo::initPhysics() +{ + setTexturing(true); + setShadows(true); + + setCameraDistance(26.f); + m_Time = 0; + + setupEmptyDynamicsWorld(); + + //btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(40.),btScalar(50.))); + btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),40); + + m_collisionShapes.push_back(groundShape); + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-56,0)); + btRigidBody* groundBody; + groundBody= localCreateRigidBody(0, groundTransform, groundShape); + + + + btCollisionShape* shape = new btBoxShape(btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS)); + m_collisionShapes.push_back(shape); + btTransform trans; + trans.setIdentity(); + trans.setOrigin(btVector3(0,20,0)); + + float mass = 1.f; + + +#if ENABLE_ALL_DEMOS + //point to point constraint with a breaking threshold + { + trans.setIdentity(); + trans.setOrigin(btVector3(1,30,-5)); + localCreateRigidBody( mass,trans,shape); + trans.setOrigin(btVector3(0,0,-5)); + + btRigidBody* body0 = localCreateRigidBody( mass,trans,shape); + trans.setOrigin(btVector3(2*CUBE_HALF_EXTENTS,20,0)); + mass = 1.f; + btRigidBody* body1 = 0;//localCreateRigidBody( mass,trans,shape); + btVector3 pivotInA(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,0); + btTypedConstraint* p2p = new btPoint2PointConstraint(*body0,pivotInA); + m_dynamicsWorld->addConstraint(p2p); + p2p ->setBreakingImpulseThreshold(10.2); + p2p->setDbgDrawSize(btScalar(5.f)); + } +#endif + + + +#if ENABLE_ALL_DEMOS + //point to point constraint (ball socket) + { + btRigidBody* body0 = localCreateRigidBody( mass,trans,shape); + trans.setOrigin(btVector3(2*CUBE_HALF_EXTENTS,20,0)); + + mass = 1.f; + btRigidBody* body1 = 0;//localCreateRigidBody( mass,trans,shape); +// btRigidBody* body1 = localCreateRigidBody( 0.0,trans,0); + //body1->setActivationState(DISABLE_DEACTIVATION); + //body1->setDamping(0.3,0.3); + + btVector3 pivotInA(CUBE_HALF_EXTENTS,-CUBE_HALF_EXTENTS,-CUBE_HALF_EXTENTS); + btVector3 axisInA(0,0,1); + + btVector3 pivotInB = body1 ? body1->getCenterOfMassTransform().inverse()(body0->getCenterOfMassTransform()(pivotInA)) : pivotInA; + btVector3 axisInB = body1? + (body1->getCenterOfMassTransform().getBasis().inverse()*(body1->getCenterOfMassTransform().getBasis() * axisInA)) : + body0->getCenterOfMassTransform().getBasis() * axisInA; + +#define P2P +#ifdef P2P + btTypedConstraint* p2p = new btPoint2PointConstraint(*body0,pivotInA); + //btTypedConstraint* p2p = new btPoint2PointConstraint(*body0,*body1,pivotInA,pivotInB); + //btTypedConstraint* hinge = new btHingeConstraint(*body0,*body1,pivotInA,pivotInB,axisInA,axisInB); + m_dynamicsWorld->addConstraint(p2p); + p2p->setDbgDrawSize(btScalar(5.f)); +#else + btHingeConstraint* hinge = new btHingeConstraint(*body0,pivotInA,axisInA); + + //use zero targetVelocity and a small maxMotorImpulse to simulate joint friction + //float targetVelocity = 0.f; + //float maxMotorImpulse = 0.01; + float targetVelocity = 1.f; + float maxMotorImpulse = 1.0f; + hinge->enableAngularMotor(true,targetVelocity,maxMotorImpulse); + m_dynamicsWorld->addConstraint(hinge); + hinge->setDbgDrawSize(btScalar(5.f)); +#endif //P2P + + + + + } +#endif + +#if ENABLE_ALL_DEMOS + //create a slider, using the generic D6 constraint + { + mass = 1.f; + btVector3 sliderWorldPos(0,10,0); + btVector3 sliderAxis(1,0,0); + btScalar angle=0.f;//SIMD_RADS_PER_DEG * 10.f; + btMatrix3x3 sliderOrientation(btQuaternion(sliderAxis ,angle)); + trans.setIdentity(); + trans.setOrigin(sliderWorldPos); + //trans.setBasis(sliderOrientation); + sliderTransform = trans; + + d6body0 = localCreateRigidBody( mass,trans,shape); + d6body0->setActivationState(DISABLE_DEACTIVATION); + btRigidBody* fixedBody1 = localCreateRigidBody(0,trans,0); + m_dynamicsWorld->addRigidBody(fixedBody1); + + btTransform frameInA, frameInB; + frameInA = btTransform::getIdentity(); + frameInB = btTransform::getIdentity(); + frameInA.setOrigin(btVector3(0., 5., 0.)); + frameInB.setOrigin(btVector3(0., 5., 0.)); + +// bool useLinearReferenceFrameA = false;//use fixed frame B for linear llimits + bool useLinearReferenceFrameA = true;//use fixed frame A for linear llimits + spSlider6Dof = new btGeneric6DofConstraint(*fixedBody1, *d6body0,frameInA,frameInB,useLinearReferenceFrameA); + spSlider6Dof->setLinearLowerLimit(lowerSliderLimit); + spSlider6Dof->setLinearUpperLimit(hiSliderLimit); + + //range should be small, otherwise singularities will 'explode' the constraint +// spSlider6Dof->setAngularLowerLimit(btVector3(-1.5,0,0)); +// spSlider6Dof->setAngularUpperLimit(btVector3(1.5,0,0)); +// spSlider6Dof->setAngularLowerLimit(btVector3(0,0,0)); +// spSlider6Dof->setAngularUpperLimit(btVector3(0,0,0)); + spSlider6Dof->setAngularLowerLimit(btVector3(-SIMD_PI,0,0)); + spSlider6Dof->setAngularUpperLimit(btVector3(1.5,0,0)); + + spSlider6Dof->getTranslationalLimitMotor()->m_enableMotor[0] = true; + spSlider6Dof->getTranslationalLimitMotor()->m_targetVelocity[0] = -5.0f; + spSlider6Dof->getTranslationalLimitMotor()->m_maxMotorForce[0] = 0.1f; + + + m_dynamicsWorld->addConstraint(spSlider6Dof); + spSlider6Dof->setDbgDrawSize(btScalar(5.f)); + + } +#endif +#if ENABLE_ALL_DEMOS + { // create a door using hinge constraint attached to the world + btCollisionShape* pDoorShape = new btBoxShape(btVector3(2.0f, 5.0f, 0.2f)); + m_collisionShapes.push_back(pDoorShape); + btTransform doorTrans; + doorTrans.setIdentity(); + doorTrans.setOrigin(btVector3(-5.0f, -2.0f, 0.0f)); + btRigidBody* pDoorBody = localCreateRigidBody( 1.0, doorTrans, pDoorShape); + pDoorBody->setActivationState(DISABLE_DEACTIVATION); + const btVector3 btPivotA(10.f + 2.1f, -2.0f, 0.0f ); // right next to the door slightly outside + btVector3 btAxisA( 0.0f, 1.0f, 0.0f ); // pointing upwards, aka Y-axis + + spDoorHinge = new btHingeConstraint( *pDoorBody, btPivotA, btAxisA ); + +// spDoorHinge->setLimit( 0.0f, SIMD_PI_2 ); + // test problem values +// spDoorHinge->setLimit( -SIMD_PI, SIMD_PI*0.8f); + +// spDoorHinge->setLimit( 1.f, -1.f); +// spDoorHinge->setLimit( -SIMD_PI*0.8f, SIMD_PI); +// spDoorHinge->setLimit( -SIMD_PI*0.8f, SIMD_PI, 0.9f, 0.3f, 0.0f); +// spDoorHinge->setLimit( -SIMD_PI*0.8f, SIMD_PI, 0.9f, 0.01f, 0.0f); // "sticky limits" + spDoorHinge->setLimit( -SIMD_PI * 0.25f, SIMD_PI * 0.25f ); +// spDoorHinge->setLimit( 0.0f, 0.0f ); + m_dynamicsWorld->addConstraint(spDoorHinge); + spDoorHinge->setDbgDrawSize(btScalar(5.f)); + + //doorTrans.setOrigin(btVector3(-5.0f, 2.0f, 0.0f)); + //btRigidBody* pDropBody = localCreateRigidBody( 10.0, doorTrans, shape); + } +#endif +#if ENABLE_ALL_DEMOS + { // create a generic 6DOF constraint + + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(10.), btScalar(6.), btScalar(0.))); + tr.getBasis().setEulerZYX(0,0,0); +// btRigidBody* pBodyA = localCreateRigidBody( mass, tr, shape); + btRigidBody* pBodyA = localCreateRigidBody( 0.0, tr, shape); +// btRigidBody* pBodyA = localCreateRigidBody( 0.0, tr, 0); + pBodyA->setActivationState(DISABLE_DEACTIVATION); + + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(0.), btScalar(6.), btScalar(0.))); + tr.getBasis().setEulerZYX(0,0,0); + btRigidBody* pBodyB = localCreateRigidBody(mass, tr, shape); +// btRigidBody* pBodyB = localCreateRigidBody(0.f, tr, shape); + pBodyB->setActivationState(DISABLE_DEACTIVATION); + + btTransform frameInA, frameInB; + frameInA = btTransform::getIdentity(); + frameInA.setOrigin(btVector3(btScalar(-5.), btScalar(0.), btScalar(0.))); + frameInB = btTransform::getIdentity(); + frameInB.setOrigin(btVector3(btScalar(5.), btScalar(0.), btScalar(0.))); + + btGeneric6DofConstraint* pGen6DOF = new btGeneric6DofConstraint(*pBodyA, *pBodyB, frameInA, frameInB, true); +// btGeneric6DofConstraint* pGen6DOF = new btGeneric6DofConstraint(*pBodyA, *pBodyB, frameInA, frameInB, false); + pGen6DOF->setLinearLowerLimit(btVector3(-10., -2., -1.)); + pGen6DOF->setLinearUpperLimit(btVector3(10., 2., 1.)); +// pGen6DOF->setLinearLowerLimit(btVector3(-10., 0., 0.)); +// pGen6DOF->setLinearUpperLimit(btVector3(10., 0., 0.)); +// pGen6DOF->setLinearLowerLimit(btVector3(0., 0., 0.)); +// pGen6DOF->setLinearUpperLimit(btVector3(0., 0., 0.)); + +// pGen6DOF->getTranslationalLimitMotor()->m_enableMotor[0] = true; +// pGen6DOF->getTranslationalLimitMotor()->m_targetVelocity[0] = 5.0f; +// pGen6DOF->getTranslationalLimitMotor()->m_maxMotorForce[0] = 0.1f; + + +// pGen6DOF->setAngularLowerLimit(btVector3(0., SIMD_HALF_PI*0.9, 0.)); +// pGen6DOF->setAngularUpperLimit(btVector3(0., -SIMD_HALF_PI*0.9, 0.)); +// pGen6DOF->setAngularLowerLimit(btVector3(0., 0., -SIMD_HALF_PI)); +// pGen6DOF->setAngularUpperLimit(btVector3(0., 0., SIMD_HALF_PI)); + + pGen6DOF->setAngularLowerLimit(btVector3(-SIMD_HALF_PI * 0.5f, -0.75, -SIMD_HALF_PI * 0.8f)); + pGen6DOF->setAngularUpperLimit(btVector3(SIMD_HALF_PI * 0.5f, 0.75, SIMD_HALF_PI * 0.8f)); +// pGen6DOF->setAngularLowerLimit(btVector3(0.f, -0.75, SIMD_HALF_PI * 0.8f)); +// pGen6DOF->setAngularUpperLimit(btVector3(0.f, 0.75, -SIMD_HALF_PI * 0.8f)); +// pGen6DOF->setAngularLowerLimit(btVector3(0.f, -SIMD_HALF_PI * 0.8f, SIMD_HALF_PI * 1.98f)); +// pGen6DOF->setAngularUpperLimit(btVector3(0.f, SIMD_HALF_PI * 0.8f, -SIMD_HALF_PI * 1.98f)); + + + +// pGen6DOF->setAngularLowerLimit(btVector3(-0.75,-0.5, -0.5)); +// pGen6DOF->setAngularUpperLimit(btVector3(0.75,0.5, 0.5)); +// pGen6DOF->setAngularLowerLimit(btVector3(-0.75,0., 0.)); +// pGen6DOF->setAngularUpperLimit(btVector3(0.75,0., 0.)); +// pGen6DOF->setAngularLowerLimit(btVector3(0., -0.7,0.)); +// pGen6DOF->setAngularUpperLimit(btVector3(0., 0.7, 0.)); +// pGen6DOF->setAngularLowerLimit(btVector3(-1., 0.,0.)); +// pGen6DOF->setAngularUpperLimit(btVector3(1., 0., 0.)); + + m_dynamicsWorld->addConstraint(pGen6DOF, true); + pGen6DOF->setDbgDrawSize(btScalar(5.f)); + } +#endif +#if ENABLE_ALL_DEMOS + { // create a ConeTwist constraint + + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(-10.), btScalar(5.), btScalar(0.))); + tr.getBasis().setEulerZYX(0,0,0); + btRigidBody* pBodyA = localCreateRigidBody( 1.0, tr, shape); +// btRigidBody* pBodyA = localCreateRigidBody( 0.0, tr, shape); + pBodyA->setActivationState(DISABLE_DEACTIVATION); + + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(-10.), btScalar(-5.), btScalar(0.))); + tr.getBasis().setEulerZYX(0,0,0); + btRigidBody* pBodyB = localCreateRigidBody(0.0, tr, shape); +// btRigidBody* pBodyB = localCreateRigidBody(1.0, tr, shape); + + btTransform frameInA, frameInB; + frameInA = btTransform::getIdentity(); + frameInA.getBasis().setEulerZYX(0, 0, SIMD_PI_2); + frameInA.setOrigin(btVector3(btScalar(0.), btScalar(-5.), btScalar(0.))); + frameInB = btTransform::getIdentity(); + frameInB.getBasis().setEulerZYX(0,0, SIMD_PI_2); + frameInB.setOrigin(btVector3(btScalar(0.), btScalar(5.), btScalar(0.))); + + m_ctc = new btConeTwistConstraint(*pBodyA, *pBodyB, frameInA, frameInB); +// m_ctc->setLimit(btScalar(SIMD_PI_4), btScalar(SIMD_PI_4), btScalar(SIMD_PI) * 0.8f); +// m_ctc->setLimit(btScalar(SIMD_PI_4*0.6f), btScalar(SIMD_PI_4), btScalar(SIMD_PI) * 0.8f, 1.0f); // soft limit == hard limit + m_ctc->setLimit(btScalar(SIMD_PI_4*0.6f), btScalar(SIMD_PI_4), btScalar(SIMD_PI) * 0.8f, 0.5f); + m_dynamicsWorld->addConstraint(m_ctc, true); + m_ctc->setDbgDrawSize(btScalar(5.f)); + // s_bTestConeTwistMotor = true; // use only with old solver for now + s_bTestConeTwistMotor = false; + } +#endif +#if ENABLE_ALL_DEMOS + { // Hinge connected to the world, with motor (to hinge motor with new and old constraint solver) + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(0.), btScalar(0.), btScalar(0.))); + btRigidBody* pBody = localCreateRigidBody( 1.0, tr, shape); + pBody->setActivationState(DISABLE_DEACTIVATION); + const btVector3 btPivotA( 10.0f, 0.0f, 0.0f ); + btVector3 btAxisA( 0.0f, 0.0f, 1.0f ); + + btHingeConstraint* pHinge = new btHingeConstraint( *pBody, btPivotA, btAxisA ); +// pHinge->enableAngularMotor(true, -1.0, 0.165); // use for the old solver + pHinge->enableAngularMotor(true, -1.0f, 1.65f); // use for the new SIMD solver + m_dynamicsWorld->addConstraint(pHinge); + pHinge->setDbgDrawSize(btScalar(5.f)); + } +#endif + +#if ENABLE_ALL_DEMOS + { + // create a universal joint using generic 6DOF constraint + // create two rigid bodies + // static bodyA (parent) on top: + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(20.), btScalar(4.), btScalar(0.))); + btRigidBody* pBodyA = localCreateRigidBody( 0.0, tr, shape); + pBodyA->setActivationState(DISABLE_DEACTIVATION); + // dynamic bodyB (child) below it : + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(20.), btScalar(0.), btScalar(0.))); + btRigidBody* pBodyB = localCreateRigidBody(1.0, tr, shape); + pBodyB->setActivationState(DISABLE_DEACTIVATION); + // add some (arbitrary) data to build constraint frames + btVector3 parentAxis(1.f, 0.f, 0.f); + btVector3 childAxis(0.f, 0.f, 1.f); + btVector3 anchor(20.f, 2.f, 0.f); + + btUniversalConstraint* pUniv = new btUniversalConstraint(*pBodyA, *pBodyB, anchor, parentAxis, childAxis); + pUniv->setLowerLimit(-SIMD_HALF_PI * 0.5f, -SIMD_HALF_PI * 0.5f); + pUniv->setUpperLimit(SIMD_HALF_PI * 0.5f, SIMD_HALF_PI * 0.5f); + // add constraint to world + m_dynamicsWorld->addConstraint(pUniv, true); + // draw constraint frames and limits for debugging + pUniv->setDbgDrawSize(btScalar(5.f)); + } +#endif + +#if ENABLE_ALL_DEMOS + { // create a generic 6DOF constraint with springs + + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(-20.), btScalar(16.), btScalar(0.))); + tr.getBasis().setEulerZYX(0,0,0); + btRigidBody* pBodyA = localCreateRigidBody( 0.0, tr, shape); + pBodyA->setActivationState(DISABLE_DEACTIVATION); + + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(-10.), btScalar(16.), btScalar(0.))); + tr.getBasis().setEulerZYX(0,0,0); + btRigidBody* pBodyB = localCreateRigidBody(1.0, tr, shape); + pBodyB->setActivationState(DISABLE_DEACTIVATION); + + btTransform frameInA, frameInB; + frameInA = btTransform::getIdentity(); + frameInA.setOrigin(btVector3(btScalar(10.), btScalar(0.), btScalar(0.))); + frameInB = btTransform::getIdentity(); + frameInB.setOrigin(btVector3(btScalar(0.), btScalar(0.), btScalar(0.))); + + btGeneric6DofSpringConstraint* pGen6DOFSpring = new btGeneric6DofSpringConstraint(*pBodyA, *pBodyB, frameInA, frameInB, true); + pGen6DOFSpring->setLinearUpperLimit(btVector3(5., 0., 0.)); + pGen6DOFSpring->setLinearLowerLimit(btVector3(-5., 0., 0.)); + + pGen6DOFSpring->setAngularLowerLimit(btVector3(0.f, 0.f, -1.5f)); + pGen6DOFSpring->setAngularUpperLimit(btVector3(0.f, 0.f, 1.5f)); + + m_dynamicsWorld->addConstraint(pGen6DOFSpring, true); + pGen6DOFSpring->setDbgDrawSize(btScalar(5.f)); + + pGen6DOFSpring->enableSpring(0, true); + pGen6DOFSpring->setStiffness(0, 39.478f); + pGen6DOFSpring->setDamping(0, 0.5f); + pGen6DOFSpring->enableSpring(5, true); + pGen6DOFSpring->setStiffness(5, 39.478f); + pGen6DOFSpring->setDamping(0, 0.3f); + pGen6DOFSpring->setEquilibriumPoint(); + } +#endif +#if ENABLE_ALL_DEMOS + { + // create a Hinge2 joint + // create two rigid bodies + // static bodyA (parent) on top: + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(-20.), btScalar(4.), btScalar(0.))); + btRigidBody* pBodyA = localCreateRigidBody( 0.0, tr, shape); + pBodyA->setActivationState(DISABLE_DEACTIVATION); + // dynamic bodyB (child) below it : + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(-20.), btScalar(0.), btScalar(0.))); + btRigidBody* pBodyB = localCreateRigidBody(1.0, tr, shape); + pBodyB->setActivationState(DISABLE_DEACTIVATION); + // add some data to build constraint frames + btVector3 parentAxis(0.f, 1.f, 0.f); + btVector3 childAxis(1.f, 0.f, 0.f); + btVector3 anchor(-20.f, 0.f, 0.f); + btHinge2Constraint* pHinge2 = new btHinge2Constraint(*pBodyA, *pBodyB, anchor, parentAxis, childAxis); + pHinge2->setLowerLimit(-SIMD_HALF_PI * 0.5f); + pHinge2->setUpperLimit( SIMD_HALF_PI * 0.5f); + // add constraint to world + m_dynamicsWorld->addConstraint(pHinge2, true); + // draw constraint frames and limits for debugging + pHinge2->setDbgDrawSize(btScalar(5.f)); + } +#endif +#if ENABLE_ALL_DEMOS + { + // create a Hinge joint between two dynamic bodies + // create two rigid bodies + // static bodyA (parent) on top: + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(-20.), btScalar(-2.), btScalar(0.))); + btRigidBody* pBodyA = localCreateRigidBody( 1.0f, tr, shape); + pBodyA->setActivationState(DISABLE_DEACTIVATION); + // dynamic bodyB: + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(-30.), btScalar(-2.), btScalar(0.))); + btRigidBody* pBodyB = localCreateRigidBody(10.0, tr, shape); + pBodyB->setActivationState(DISABLE_DEACTIVATION); + // add some data to build constraint frames + btVector3 axisA(0.f, 1.f, 0.f); + btVector3 axisB(0.f, 1.f, 0.f); + btVector3 pivotA(-5.f, 0.f, 0.f); + btVector3 pivotB( 5.f, 0.f, 0.f); + spHingeDynAB = new btHingeConstraint(*pBodyA, *pBodyB, pivotA, pivotB, axisA, axisB); + spHingeDynAB->setLimit(-SIMD_HALF_PI * 0.5f, SIMD_HALF_PI * 0.5f); + // add constraint to world + m_dynamicsWorld->addConstraint(spHingeDynAB, true); + // draw constraint frames and limits for debugging + spHingeDynAB->setDbgDrawSize(btScalar(5.f)); + } +#endif + +#if ENABLE_ALL_DEMOS + { // 6DOF connected to the world, with motor + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(10.), btScalar(-15.), btScalar(0.))); + btRigidBody* pBody = localCreateRigidBody( 1.0, tr, shape); + pBody->setActivationState(DISABLE_DEACTIVATION); + btTransform frameB; + frameB.setIdentity(); + btGeneric6DofConstraint* pGen6Dof = new btGeneric6DofConstraint( *pBody, frameB, false ); + m_dynamicsWorld->addConstraint(pGen6Dof); + pGen6Dof->setDbgDrawSize(btScalar(5.f)); + + pGen6Dof->setAngularLowerLimit(btVector3(0,0,0)); + pGen6Dof->setAngularUpperLimit(btVector3(0,0,0)); + pGen6Dof->setLinearLowerLimit(btVector3(-10., 0, 0)); + pGen6Dof->setLinearUpperLimit(btVector3(10., 0, 0)); + + pGen6Dof->getTranslationalLimitMotor()->m_enableMotor[0] = true; + pGen6Dof->getTranslationalLimitMotor()->m_targetVelocity[0] = 5.0f; + pGen6Dof->getTranslationalLimitMotor()->m_maxMotorForce[0] = 0.1f; + } +#endif + + + +} + +void ConstraintDemo::exitPhysics() +{ + + int i; + + //removed/delete constraints + for (i=m_dynamicsWorld->getNumConstraints()-1; i>=0 ;i--) + { + btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i); + m_dynamicsWorld->removeConstraint(constraint); + delete constraint; + } + m_ctc = NULL; + + //remove the rigidbodies from the dynamics world and delete them + 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;jenableMotor(true); + m_ctc->setMotorTargetInConstraintSpace(q1); + } + + { + static bool once = true; + if ( m_dynamicsWorld->getDebugDrawer() && once) + { + m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawConstraints+btIDebugDraw::DBG_DrawConstraintLimits); + once=false; + } + } + + + { + //during idle mode, just run 1 simulation step maximum + int maxSimSubSteps = m_idle ? 1 : 1; + if (m_idle) + dt = 1.0f/420.f; + + int numSimSteps = m_dynamicsWorld->stepSimulation(dt,maxSimSubSteps); + + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + + bool verbose = false; + if (verbose) + { + if (!numSimSteps) + printf("Interpolated transforms\n"); + else + { + if (numSimSteps > maxSimSubSteps) + { + //detect dropping frames + printf("Dropped (%i) simulation steps out of %i\n",numSimSteps - maxSimSubSteps,numSimSteps); + } else + { + printf("Simulated (%i) steps\n",numSimSteps); + } + } + } + } + renderme(); + +// drawLimit(); + + glFlush(); + swapBuffers(); +} + + + + +void ConstraintDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + +// drawLimit(); + + renderme(); + + glFlush(); + swapBuffers(); +} + + +void ConstraintDemo::keyboardCallback(unsigned char key, int x, int y) +{ + (void)x; + (void)y; + switch (key) + { + case 'O' : + { + bool offectOnOff; + if(spDoorHinge) + { + offectOnOff = spDoorHinge->getUseFrameOffset(); + offectOnOff = !offectOnOff; + spDoorHinge->setUseFrameOffset(offectOnOff); + printf("DoorHinge %s frame offset\n", offectOnOff ? "uses" : "does not use"); + } + if(spHingeDynAB) + { + offectOnOff = spHingeDynAB->getUseFrameOffset(); + offectOnOff = !offectOnOff; + spHingeDynAB->setUseFrameOffset(offectOnOff); + printf("HingeDynAB %s frame offset\n", offectOnOff ? "uses" : "does not use"); + } + if(spSlider6Dof) + { + offectOnOff = spSlider6Dof->getUseFrameOffset(); + offectOnOff = !offectOnOff; + spSlider6Dof->setUseFrameOffset(offectOnOff); + printf("Slider6Dof %s frame offset\n", offectOnOff ? "uses" : "does not use"); + } + } + break; + default : + { + DemoApplication::keyboardCallback(key, x, y); + } + break; + } +} diff --git a/Demos/ConstraintDemo/ConstraintDemo.h b/Demos/ConstraintDemo/ConstraintDemo.h new file mode 100644 index 0000000..6b73e07 --- /dev/null +++ b/Demos/ConstraintDemo/ConstraintDemo.h @@ -0,0 +1,72 @@ +/* +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 CONSTRAINT_DEMO_H +#define CONSTRAINT_DEMO_H + +#ifdef _WINDOWS +#include "Win32DemoApplication.h" +#define PlatformDemoApplication Win32DemoApplication +#else +#include "GlutDemoApplication.h" +#define PlatformDemoApplication GlutDemoApplication +#endif + +///ConstraintDemo shows how to create a constraint, like Hinge or btGenericD6constraint +class ConstraintDemo : public PlatformDemoApplication +{ + //keep track of variables to delete memory at the end + btAlignedObjectArray m_collisionShapes; + + class btBroadphaseInterface* m_overlappingPairCache; + + class btCollisionDispatcher* m_dispatcher; + + class btConstraintSolver* m_constraintSolver; + + class btDefaultCollisionConfiguration* m_collisionConfiguration; + + void setupEmptyDynamicsWorld(); + + public: + + + virtual ~ConstraintDemo(); + + void initPhysics(); + + void exitPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + static DemoApplication* Create() + { + ConstraintDemo* demo = new ConstraintDemo(); + demo->myinit(); + demo->initPhysics(); + return demo; + } + + virtual void keyboardCallback(unsigned char key, int x, int y); + + // for cone-twist motor driving + float m_Time; + class btConeTwistConstraint* m_ctc; + +}; + +#endif //CONSTRAINT_DEMO_H + diff --git a/Demos/ConstraintDemo/Win32ConstraintDemo.cpp b/Demos/ConstraintDemo/Win32ConstraintDemo.cpp new file mode 100644 index 0000000..552c263 --- /dev/null +++ b/Demos/ConstraintDemo/Win32ConstraintDemo.cpp @@ -0,0 +1,25 @@ +#ifdef _WINDOWS +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "ConstraintDemo.h" + +///The 'createDemo' function is called from Bullet/Demos/OpenGL/Win32AppMain.cpp to instantiate this particular demo +DemoApplication* createDemo() +{ + return new ConstraintDemo(); +} + +#endif diff --git a/Demos/ConstraintDemo/main.cpp b/Demos/ConstraintDemo/main.cpp new file mode 100644 index 0000000..c5e8538 --- /dev/null +++ b/Demos/ConstraintDemo/main.cpp @@ -0,0 +1,20 @@ +#include "ConstraintDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" + +int main(int argc,char** argv) +{ + + GLDebugDrawer gDebugDrawer; + + ConstraintDemo* constraintDemo = new ConstraintDemo(); + + + constraintDemo->initPhysics(); + constraintDemo->getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + constraintDemo->setDebugMode(btIDebugDraw::DBG_DrawConstraints+btIDebugDraw::DBG_DrawConstraintLimits); + + return glutmain(argc, argv,640,480,"Constraint Demo. http://www.continuousphysics.com/Bullet/phpBB2/",constraintDemo); +} + diff --git a/Demos/ContinuousConvexCollision/CMakeLists.txt b/Demos/ContinuousConvexCollision/CMakeLists.txt new file mode 100644 index 0000000..bca9750 --- /dev/null +++ b/Demos/ContinuousConvexCollision/CMakeLists.txt @@ -0,0 +1,47 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppContinuousConvexCollisionDemo + ContinuousConvexCollisionDemo.cpp +) + +IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppContinuousConvexCollisionDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppContinuousConvexCollisionDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF(WIN32) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppContinuousConvexCollisionDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppContinuousConvexCollisionDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppContinuousConvexCollisionDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/ContinuousConvexCollision/ContinuousConvexCollision.h b/Demos/ContinuousConvexCollision/ContinuousConvexCollision.h new file mode 100644 index 0000000..3f08900 --- /dev/null +++ b/Demos/ContinuousConvexCollision/ContinuousConvexCollision.h @@ -0,0 +1,36 @@ +/* +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 CONTINUOUS_CONVEX_COLLISION_DEMO_H +#define CONTINUOUS_CONVEX_COLLISION_DEMO_H + + + +///ContinuousConvexCollisionDemo shows the working of the continuous collision detection, including linear and angular motion +#include "GlutDemoApplication.h" +class btContinuousConvexCollisionDemo : public GlutDemoApplication +{ + public: + + void initPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + +}; + +#endif //CONTINUOUS_CONVEX_COLLISION_DEMO_H + diff --git a/Demos/ContinuousConvexCollision/ContinuousConvexCollisionDemo.cpp b/Demos/ContinuousConvexCollision/ContinuousConvexCollisionDemo.cpp new file mode 100644 index 0000000..9324845 --- /dev/null +++ b/Demos/ContinuousConvexCollision/ContinuousConvexCollisionDemo.cpp @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. + */ + + +/* + Continuous Convex Collision Demo demonstrates an efficient continuous collision detection algorithm. + Both linear and angular velocities are supported. Convex Objects are sampled using Supporting Vertex. + Motion using Exponential Map. + Future ideas: Comparison with Screwing Motion. + Also comparision with Algebraic CCD and Interval Arithmetic methods (Stephane Redon) +*/ + + +///This low level demo need internal access, and intentionally doesn't include the btBulletCollisionCommon.h headerfile +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btTransform.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" + +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" + +#include "LinearMath/btTransformUtil.h" +#include "DebugCastResult.h" + +#include "BulletCollision/CollisionShapes/btSphereShape.h" + +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" + +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" + +#include "GL_ShapeDrawer.h" +#include "ContinuousConvexCollision.h" +#include "GlutStuff.h" + + +float yaw=0.f,pitch=0.f,roll=0.f; +const int maxNumObjects = 4; +const int numObjects = 2; + +btVector3 angVels[numObjects]; +btVector3 linVels[numObjects]; + +btPolyhedralConvexShape* shapePtr[maxNumObjects]; + + +btTransform fromTrans[maxNumObjects]; +btTransform toTrans[maxNumObjects]; + + +int screenWidth = 640; +int screenHeight = 480; + + +int main(int argc,char** argv) +{ + btContinuousConvexCollisionDemo* ccdDemo = new btContinuousConvexCollisionDemo(); + + ccdDemo->setCameraDistance(40.f); + + ccdDemo->initPhysics(); + + return glutmain(argc, argv,screenWidth,screenHeight,"Continuous Convex Collision Demo",ccdDemo); +} + + +void btContinuousConvexCollisionDemo::initPhysics() +{ + fromTrans[0].setOrigin(btVector3(0,10,20)); + toTrans[0].setOrigin(btVector3(0,10,-20)); + fromTrans[1].setOrigin(btVector3(-2,7,0)); + toTrans[1].setOrigin(btVector3(-2,10,0)); + + btMatrix3x3 identBasis; + identBasis.setIdentity(); + + btMatrix3x3 basisA; + basisA.setIdentity(); + basisA.setEulerZYX(0.f,-SIMD_HALF_PI,0.f); + + fromTrans[0].setBasis(identBasis); + toTrans[0].setBasis(basisA); + + fromTrans[1].setBasis(identBasis); + toTrans[1].setBasis(identBasis); + + toTrans[1].setBasis(identBasis); + btVector3 boxHalfExtentsA(10,1,1); + btVector3 boxHalfExtentsB(1.1f,1.1f,1.1f); + btBoxShape* boxA = new btBoxShape(boxHalfExtentsA); +// btBU_Simplex1to4* boxA = new btBU_Simplex1to4(btVector3(-2,0,-2),btVector3(2,0,-2),btVector3(0,0,2),btVector3(0,2,0)); +// btBU_Simplex1to4* boxA = new btBU_Simplex1to4(btVector3(-12,0,0),btVector3(12,0,0)); + + + btBoxShape* boxB = new btBoxShape(boxHalfExtentsB); + + shapePtr[0] = boxA; + shapePtr[1] = boxB; + + shapePtr[0]->setMargin(0.01f); + shapePtr[1]->setMargin(0.01f); + + for (int i=0;idrawOpenGL(m,shapePtr[i],btVector3(1,0,1),getDebugMode(),worldBoundsMin,worldBoundsMax); + } + } + } + + + btMatrix3x3 mat; + mat.setEulerZYX(yaw,pitch,roll); + btQuaternion orn; + mat.getRotation(orn); + orn.setEuler(yaw,pitch,roll); + fromTrans[1].setRotation(orn); + toTrans[1].setRotation(orn); + + + if (m_stepping || m_singleStep) + { + m_singleStep = false; + pitch += 0.005f; +// yaw += 0.01f; + } +// btVector3 fromA(-25,11,0); +// btVector3 toA(-15,11,0); + +// btQuaternion ornFromA(0.f,0.f,0.f,1.f); +// btQuaternion ornToA(0.f,0.f,0.f,1.f); + +// btTransform rayFromWorld(ornFromA,fromA); +// btTransform rayToWorld(ornToA,toA); + + btTransform rayFromWorld = fromTrans[0]; + btTransform rayToWorld = toTrans[0]; + + + if (drawLine) + { + glBegin(GL_LINES); + glColor3f(0, 0, 1); + glVertex3d(rayFromWorld.getOrigin().x(), rayFromWorld.getOrigin().y(),rayFromWorld.getOrigin().z()); + glVertex3d(rayToWorld.getOrigin().x(),rayToWorld.getOrigin().y(),rayToWorld.getOrigin().z()); + glEnd(); + } + + //now perform a raycast on the shapes, in local (shape) space + gGjkSimplexSolver.reset(); + + //choose one of the following lines + + + for (i=0;idrawOpenGL(m,shapePtr[i],btVector3(1,1,1),getDebugMode(),worldBoundsMin,worldBoundsMax); + } + + btDebugCastResult rayResult1(fromTrans[0],shapePtr[0],linVels[0],angVels[0],m_shapeDrawer); + + + for (i=1;im_fraction,hitTrans); + + hitTrans.getOpenGLMatrix(m); + m_shapeDrawer->drawOpenGL(m,shapePtr[0],btVector3(0,1,0),getDebugMode(),worldBoundsMin,worldBoundsMax); + + btTransformUtil::integrateTransform(fromTrans[i],linVels[i],angVels[i],rayResultPtr->m_fraction,hitTrans); + + hitTrans.getOpenGLMatrix(m); + m_shapeDrawer->drawOpenGL(m,shapePtr[i],btVector3(0,1,1),getDebugMode(),worldBoundsMin,worldBoundsMax); + + + } + } + + swapBuffers(); +} + + diff --git a/Demos/ConvexDecompositionDemo/CMakeLists.txt b/Demos/ConvexDecompositionDemo/CMakeLists.txt new file mode 100644 index 0000000..5297949 --- /dev/null +++ b/Demos/ConvexDecompositionDemo/CMakeLists.txt @@ -0,0 +1,83 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# This is the variable for Windows. I use this to define the root of my directory structure. +SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/Glut) + +# You shouldn't have to modify anything below this line +######################################################## + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +${BULLET_PHYSICS_SOURCE_DIR}/Extras/HACD +${BULLET_PHYSICS_SOURCE_DIR}/Extras/ConvexDecomposition +${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletFileLoader +${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletWorldImporter +) + +IF (USE_GLUT) + + LINK_LIBRARIES( + OpenGLSupport BulletWorldImporter BulletDynamics BulletCollision LinearMath BulletFileLoader HACD ConvexDecomposition ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + ADD_EXECUTABLE(AppConvexDecompositionDemo + main.cpp + ConvexDecompositionDemo.cpp + ConvexDecompositionDemo.h + ) + IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppConvexDecompositionDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppConvexDecompositionDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ENDIF(WIN32) +ELSE (USE_GLUT) + +LINK_LIBRARIES( + OpenGLSupport BulletWorldImporter BulletDynamics BulletCollision LinearMath BulletFileLoader HACD ConvexDecomposition ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + ADD_EXECUTABLE(AppConvexDecompositionDemo + WIN32 + ../OpenGL/Win32AppMain.cpp + ConvexDecompositionDemo.cpp + ConvexDecompositionDemo.h + Win32ConvexDecompositionDemo.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) + +ENDIF (USE_GLUT) + +IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( + TARGET AppConvexDecompositionDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SerializeDemo/testFile.bullet ${CMAKE_CURRENT_BINARY_DIR}/testFile.bullet + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/file.obj ${CMAKE_CURRENT_BINARY_DIR} + ) +ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppConvexDecompositionDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppConvexDecompositionDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppConvexDecompositionDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) diff --git a/Demos/ConvexDecompositionDemo/ConvexDecompositionDemo.cpp b/Demos/ConvexDecompositionDemo/ConvexDecompositionDemo.cpp new file mode 100644 index 0000000..f62b945 --- /dev/null +++ b/Demos/ConvexDecompositionDemo/ConvexDecompositionDemo.cpp @@ -0,0 +1,741 @@ +/* +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 "hacdCircularList.h" +#include "hacdVector.h" +#include "hacdICHull.h" +#include "hacdGraph.h" +#include "hacdHACD.h" + +#include "cd_wavefront.h" +#include "ConvexBuilder.h" + +#include "btBulletDynamicsCommon.h" + +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btIDebugDraw.h" +#include "LinearMath/btGeometryUtil.h" +#include "BulletCollision/CollisionShapes/btShapeHull.h" + +//#define TEST_SERIALIZATION +//#define NO_OBJ_TO_BULLET + +#ifdef TEST_SERIALIZATION +#include "LinearMath/btSerializer.h" +#include "btBulletFile.h" +#include "btBulletWorldImporter.h" +#endif + +//#define USE_PARALLEL_DISPATCHER 1 +#ifdef USE_PARALLEL_DISPATCHER +#include "../../Extras/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h" +#include "../../Extras/BulletMultiThreaded/Win32ThreadSupport.h" +#include "../../Extras/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" +#endif//USE_PARALLEL_DISPATCHER + + + + + +#include "GLDebugFont.h" +#include //printf debugging + + +#include "ConvexDecompositionDemo.h" +#include "GL_ShapeDrawer.h" + +#include "GlutStuff.h" + + +btVector3 centroid=btVector3(0,0,0); +btVector3 convexDecompositionObjectOffset(10,0,0); + +#define CUBE_HALF_EXTENTS 4 + + +//////////////////////////////////// + +unsigned int tcount = 0; + + +void ConvexDecompositionDemo::initPhysics() +{ + initPhysics("file.obj"); +} + + + +///MyContactCallback is just an example to show how to get access to the child shape that collided +bool MyContactCallback ( + btManifoldPoint& cp, + const btCollisionObject* colObj0, + int partId0, + int index0, + const btCollisionObject* colObj1, + int partId1, + int index1) +{ + + if (colObj0->getRootCollisionShape()->getShapeType()==COMPOUND_SHAPE_PROXYTYPE) + { + btCompoundShape* compound = (btCompoundShape*)colObj0->getRootCollisionShape(); + btCollisionShape* childShape; + childShape = compound->getChildShape(index0); + } + + if (colObj1->getRootCollisionShape()->getShapeType()==COMPOUND_SHAPE_PROXYTYPE) + { + btCompoundShape* compound = (btCompoundShape*)colObj1->getRootCollisionShape(); + btCollisionShape* childShape; + childShape = compound->getChildShape(index1); + } + + return true; +} + + +void ConvexDecompositionDemo::setupEmptyDynamicsWorld() +{ +m_collisionConfiguration = new btDefaultCollisionConfiguration(); + +#ifdef USE_PARALLEL_DISPATCHER +#ifdef USE_WIN32_THREADING + + int maxNumOutstandingTasks = 4;//number of maximum outstanding tasks + Win32ThreadSupport* threadSupport = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo( + "collision", + processCollisionTask, + createCollisionLocalStoreMemory, + maxNumOutstandingTasks)); +#else +///@todo other platform threading +///Playstation 3 SPU (SPURS) version is available through PS3 Devnet +///Libspe2 SPU support will be available soon +///pthreads version +///you can hook it up to your custom task scheduler by deriving from btThreadSupportInterface +#endif + + m_dispatcher = new SpuGatheringCollisionDispatcher(threadSupport,maxNumOutstandingTasks,m_collisionConfiguration); +#else + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); +#endif//USE_PARALLEL_DISPATCHER + + + convexDecompositionObjectOffset.setValue(10,0,0); + + btVector3 worldAabbMin(-10000,-10000,-10000); + btVector3 worldAabbMax(10000,10000,10000); + + m_broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax); + //m_broadphase = new btSimpleBroadphase(); + + m_solver = new btSequentialImpulseConstraintSolver(); + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + +#ifdef USE_PARALLEL_DISPATCHER + m_dynamicsWorld->getDispatchInfo().m_enableSPU = true; +#endif //USE_PARALLEL_DISPATCHER + +} + +void ConvexDecompositionDemo::initPhysics(const char* filename) +{ + + + gContactAddedCallback = &MyContactCallback; + + setupEmptyDynamicsWorld(); + + setTexturing(true); + setShadows(true); + + setCameraDistance(26.f); + + +#ifndef NO_OBJ_TO_BULLET + + ConvexDecomposition::WavefrontObj wo; + + tcount = wo.loadObj(filename); + + if (!tcount) + { + //when running this app from visual studio, the default starting folder is different, so make a second attempt... + tcount = wo.loadObj("../../file.obj"); + } + if (!tcount) + { + //cmake generated msvc files need 4 levels deep back... so make a 3rd attempt... + tcount = wo.loadObj("../../../../file.obj"); + } + + + + + + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(0,-4.5,0)); + + btCollisionShape* boxShape = new btBoxShape(btVector3(30,2,30)); + m_collisionShapes.push_back(boxShape); + localCreateRigidBody(0.f,startTransform,boxShape); + + class MyConvexDecomposition : public ConvexDecomposition::ConvexDecompInterface + { + ConvexDecompositionDemo* m_convexDemo; + + public: + + btAlignedObjectArray m_convexShapes; + btAlignedObjectArray m_convexCentroids; + + MyConvexDecomposition (FILE* outputFile,ConvexDecompositionDemo* demo) + :m_convexDemo(demo), + mBaseCount(0), + mHullCount(0), + mOutputFile(outputFile) + + { + } + + virtual void ConvexDecompResult(ConvexDecomposition::ConvexResult &result) + { + + btTriangleMesh* trimesh = new btTriangleMesh(); + m_convexDemo->m_trimeshes.push_back(trimesh); + + btVector3 localScaling(6.f,6.f,6.f); + + //export data to .obj + printf("ConvexResult. "); + if (mOutputFile) + { + fprintf(mOutputFile,"## Hull Piece %d with %d vertices and %d triangles.\r\n", mHullCount, result.mHullVcount, result.mHullTcount ); + + fprintf(mOutputFile,"usemtl Material%i\r\n",mBaseCount); + fprintf(mOutputFile,"o Object%i\r\n",mBaseCount); + + for (unsigned int i=0; i vertices; + if ( 1 ) + { + //const unsigned int *src = result.mHullIndices; + for (unsigned int i=0; iaddTriangle(vertex0,vertex1,vertex2); + + index0+=mBaseCount; + index1+=mBaseCount; + index2+=mBaseCount; + + fprintf(mOutputFile,"f %d %d %d\r\n", index0+1, index1+1, index2+1 ); + } + } + + // float mass = 1.f; + + +//this is a tools issue: due to collision margin, convex objects overlap, compensate for it here: +//#define SHRINK_OBJECT_INWARDS 1 +#ifdef SHRINK_OBJECT_INWARDS + + float collisionMargin = 0.01f; + + btAlignedObjectArray planeEquations; + btGeometryUtil::getPlaneEquationsFromVertices(vertices,planeEquations); + + btAlignedObjectArray shiftedPlaneEquations; + for (int p=0;p shiftedVertices; + btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,shiftedVertices); + + + btConvexHullShape* convexShape = new btConvexHullShape(&(shiftedVertices[0].getX()),shiftedVertices.size()); + +#else //SHRINK_OBJECT_INWARDS + + btConvexHullShape* convexShape = new btConvexHullShape(&(vertices[0].getX()),vertices.size()); +#endif + + convexShape->setMargin(0.01f); + m_convexShapes.push_back(convexShape); + m_convexCentroids.push_back(centroid); + m_convexDemo->m_collisionShapes.push_back(convexShape); + mBaseCount+=result.mHullVcount; // advance the 'base index' counter. + + + } + } + + int mBaseCount; + int mHullCount; + FILE* mOutputFile; + + }; + + if (tcount) + { + btTriangleMesh* trimesh = new btTriangleMesh(); + m_trimeshes.push_back(trimesh); + + btVector3 localScaling(6.f,6.f,6.f); + + int i; + for ( i=0;iaddTriangle(vertex0,vertex1,vertex2); + } + + + btConvexShape* tmpConvexShape = new btConvexTriangleMeshShape(trimesh); + + printf("old numTriangles= %d\n",wo.mTriCount); + printf("old numIndices = %d\n",wo.mTriCount*3); + printf("old numVertices = %d\n",wo.mVertexCount); + + printf("reducing vertices by creating a convex hull\n"); + + //create a hull approximation + btShapeHull* hull = new btShapeHull(tmpConvexShape); + btScalar margin = tmpConvexShape->getMargin(); + hull->buildHull(margin); + tmpConvexShape->setUserPointer(hull); + + + printf("new numTriangles = %d\n", hull->numTriangles ()); + printf("new numIndices = %d\n", hull->numIndices ()); + printf("new numVertices = %d\n", hull->numVertices ()); + + btConvexHullShape* convexShape = new btConvexHullShape(); + for (i=0;inumVertices();i++) + { + convexShape->addPoint(hull->getVertexPointer()[i]); + } + + delete tmpConvexShape; + delete hull; + + + + m_collisionShapes.push_back(convexShape); + + float mass = 1.f; + + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(0,2,14)); + + localCreateRigidBody(mass, startTransform,convexShape); + + bool useQuantization = true; + btCollisionShape* concaveShape = new btBvhTriangleMeshShape(trimesh,useQuantization); + startTransform.setOrigin(convexDecompositionObjectOffset); + localCreateRigidBody(0.f,startTransform,concaveShape); + + m_collisionShapes.push_back (concaveShape); + + } + + + if (tcount) + { + //----------------------------------- + // Bullet Convex Decomposition + //----------------------------------- + + char outputFileName[512]; + strcpy(outputFileName,filename); + char *dot = strstr(outputFileName,"."); + if ( dot ) + *dot = 0; + strcat(outputFileName,"_convex.obj"); + FILE* outputFile = fopen(outputFileName,"wb"); + + unsigned int depth = 5; + float cpercent = 5; + float ppercent = 15; + unsigned int maxv = 16; + float skinWidth = 0.0; + + printf("WavefrontObj num triangles read %i\n",tcount); + ConvexDecomposition::DecompDesc desc; + desc.mVcount = wo.mVertexCount; + desc.mVertices = wo.mVertices; + desc.mTcount = wo.mTriCount; + desc.mIndices = (unsigned int *)wo.mIndices; + desc.mDepth = depth; + desc.mCpercent = cpercent; + desc.mPpercent = ppercent; + desc.mMaxVertices = maxv; + desc.mSkinWidth = skinWidth; + + MyConvexDecomposition convexDecomposition(outputFile,this); + desc.mCallback = &convexDecomposition; + + + //----------------------------------------------- + // HACD + //----------------------------------------------- + + std::vector< HACD::Vec3 > points; + std::vector< HACD::Vec3 > triangles; + + for(int i=0; i vertex(wo.mVertices[index], wo.mVertices[index+1],wo.mVertices[index+2]); + points.push_back(vertex); + } + + for(int i=0;i triangle(wo.mIndices[index], wo.mIndices[index+1], wo.mIndices[index+2]); + triangles.push_back(triangle); + } + + + HACD::HACD myHACD; + myHACD.SetPoints(&points[0]); + myHACD.SetNPoints(points.size()); + myHACD.SetTriangles(&triangles[0]); + myHACD.SetNTriangles(triangles.size()); + myHACD.SetCompacityWeight(0.1); + myHACD.SetVolumeWeight(0.0); + + // HACD parameters + // Recommended parameters: 2 100 0 0 0 0 + size_t nClusters = 2; + double concavity = 100; + bool invert = false; + bool addExtraDistPoints = false; + bool addNeighboursDistPoints = false; + bool addFacesPoints = false; + + myHACD.SetNClusters(nClusters); // minimum number of clusters + myHACD.SetNVerticesPerCH(100); // max of 100 vertices per convex-hull + myHACD.SetConcavity(concavity); // maximum concavity + myHACD.SetAddExtraDistPoints(addExtraDistPoints); + myHACD.SetAddNeighboursDistPoints(addNeighboursDistPoints); + myHACD.SetAddFacesPoints(addFacesPoints); + + myHACD.Compute(); + nClusters = myHACD.GetNClusters(); + + myHACD.Save("output.wrl", false); + + + //convexDecomposition.performConvexDecomposition(desc); + +// ConvexBuilder cb(desc.mCallback); +// cb.process(desc); + //now create some bodies + + if (1) + { + btCompoundShape* compound = new btCompoundShape(); + m_collisionShapes.push_back (compound); + + btTransform trans; + trans.setIdentity(); + + for (int c=0;c * pointsCH = new HACD::Vec3[nPoints]; + HACD::Vec3 * trianglesCH = new HACD::Vec3[nTriangles]; + myHACD.GetCH(c, pointsCH, trianglesCH); + + // points + for(size_t v = 0; v < nPoints; v++) + { + vertices[3*v] = pointsCH[v].X(); + vertices[3*v+1] = pointsCH[v].Y(); + vertices[3*v+2] = pointsCH[v].Z(); + } + // triangles + for(size_t f = 0; f < nTriangles; f++) + { + triangles[3*f] = trianglesCH[f].X(); + triangles[3*f+1] = trianglesCH[f].Y(); + triangles[3*f+2] = trianglesCH[f].Z(); + } + + delete [] pointsCH; + delete [] trianglesCH; + + ConvexResult r(nPoints, vertices, nTriangles, triangles); + convexDecomposition.ConvexDecompResult(r); + } + + for (int i=0;iaddChildShape(trans,convexShape); + + btRigidBody* body; + body = localCreateRigidBody( 1.0, trans,convexShape); + } +/* for (int i=0;iaddChildShape(trans,convexShape); + + btRigidBody* body; + body = localCreateRigidBody( 1.0, trans,convexShape); + }*/ + +#if 1 + btScalar mass=10.f; + trans.setOrigin(-convexDecompositionObjectOffset); + btRigidBody* body = localCreateRigidBody( mass, trans,compound); + body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + + convexDecompositionObjectOffset.setZ(6); + trans.setOrigin(-convexDecompositionObjectOffset); + body = localCreateRigidBody( mass, trans,compound); + body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + + convexDecompositionObjectOffset.setZ(-6); + trans.setOrigin(-convexDecompositionObjectOffset); + body = localCreateRigidBody( mass, trans,compound); + body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); +#endif + } + + + if (outputFile) + fclose(outputFile); + + + } + + + +#ifdef TEST_SERIALIZATION + //test serializing this + + int maxSerializeBufferSize = 1024*1024*5; + + btDefaultSerializer* serializer = new btDefaultSerializer(maxSerializeBufferSize); + m_dynamicsWorld->serialize(serializer); + + FILE* f2 = fopen("testFile.bullet","wb"); + fwrite(serializer->getBufferPointer(),serializer->getCurrentBufferSize(),1,f2); + fclose(f2); + + exitPhysics(); + + //now try again from the loaded file + setupEmptyDynamicsWorld(); +#endif //TEST_SERIALIZATION + +#endif //NO_OBJ_TO_BULLET + +#ifdef TEST_SERIALIZATION + + btBulletWorldImporter* fileLoader = new btBulletWorldImporter(m_dynamicsWorld); + //fileLoader->setVerboseMode(true); + + fileLoader->loadFile("testFile.bullet"); + //fileLoader->loadFile("testFile64Double.bullet"); + //fileLoader->loadFile("testFile64Single.bullet"); + //fileLoader->loadFile("testFile32Single.bullet"); + + + + +#endif //TEST_SERIALIZATION + +} + +void ConvexDecompositionDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + float dt = getDeltaTimeMicroseconds() * 0.000001f; + + m_dynamicsWorld->stepSimulation(dt); + + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + + renderme(); + + glFlush(); + swapBuffers(); + +} + + + +void ConvexDecompositionDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + renderme(); + + + glFlush(); + swapBuffers(); +} + + + + +void ConvexDecompositionDemo::exitPhysics() +{ + + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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 (i=0;i m_collisionShapes; + + btAlignedObjectArray m_trimeshes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + + virtual void initPhysics(); + + void initPhysics(const char* filename); + + void exitPhysics(); + + virtual ~ConvexDecompositionDemo() + { + exitPhysics(); + } + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + static DemoApplication* Create() + { + ConvexDecompositionDemo* demo = new ConvexDecompositionDemo(); + demo->myinit(); + demo->initPhysics("file.obj"); + return demo; + } + + +}; + +#endif //CONVEX_DECOMPOSITION_DEMO_H + + diff --git a/Demos/ConvexDecompositionDemo/Win32ConvexDecompositionDemo.cpp b/Demos/ConvexDecompositionDemo/Win32ConvexDecompositionDemo.cpp new file mode 100644 index 0000000..d04e1d3 --- /dev/null +++ b/Demos/ConvexDecompositionDemo/Win32ConvexDecompositionDemo.cpp @@ -0,0 +1,25 @@ +#ifdef _WINDOWS +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2010 Erwin Coumans http://bulletphysics.org + +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 "ConvexDecompositionDemo.h" + +///The 'createDemo' function is called from Bullet/Demos/OpenGL/Win32AppMain.cpp to instantiate this particular demo +DemoApplication* createDemo() +{ + return new ConvexDecompositionDemo(); +} + +#endif diff --git a/Demos/ConvexDecompositionDemo/main.cpp b/Demos/ConvexDecompositionDemo/main.cpp new file mode 100644 index 0000000..b8f3a65 --- /dev/null +++ b/Demos/ConvexDecompositionDemo/main.cpp @@ -0,0 +1,32 @@ + + +#include "ConvexDecompositionDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" + + +GLDebugDrawer gDebugDrawer; + +int main(int argc,char** argv) +{ + const char* filename = "file.obj"; + + + ConvexDecompositionDemo* convexDecompDemo = new ConvexDecompositionDemo(); + + convexDecompDemo->initPhysics(filename); + + convexDecompDemo->getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + + convexDecompDemo->clientResetScene(); + + + + glutmain(argc, argv,640,480,"Bullet Physics Demo. http://www.continuousphysics.com/Bullet/phpBB2/",convexDecompDemo); + + delete convexDecompDemo; + + return 0; +} diff --git a/Demos/ConvexDecompositionDemo/testFile32Single.bullet b/Demos/ConvexDecompositionDemo/testFile32Single.bullet new file mode 100644 index 0000000000000000000000000000000000000000..b946379739fca1bcdbd185eb00d3a423fe5e86e8 GIT binary patch literal 67844 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 +#endif +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#else +#include +#endif +#include "GlutStuff.h" + + +float yaw=0.f,pitch=0.f,roll=0.f; +const int maxNumObjects = 4; +const int numObjects = 2; + +GL_Simplex1to4 simplex; + +btConvexShape* shapePtr[maxNumObjects]; + +btTransform tr[numObjects]; +int screenWidth = 640.f; +int screenHeight = 480.f; + +void clientResetScene() +{ + tr[0].setOrigin(btVector3(0.0f,3.f,7.f)); + tr[1].setOrigin(btVector3(0.0f,9.f,2.f)); +} + +int debugMode = btIDebugDraw::DBG_DrawWireframe; +GL_ShapeDrawer shapeDrawer; +int m_glutScreenWidth=0; +int m_glutScreenHeight=0; +float m_frustumZNear = 1.f; +float m_frustumZFar = 10000.f; +bool m_ortho = false; + +int myglutmain(int argc, char **argv,int width,int height,const char* title); + + +void updateCamera() { + + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + btScalar rele = 0; + btScalar razi = 0; + btVector3 m_cameraUp(0,1,0); + btScalar m_cameraDistance = 10.f; + btVector3 m_cameraPosition; + + + btVector3 m_cameraTargetPosition = (tr[0].getOrigin()+tr[1].getOrigin())*0.5; + + + btQuaternion rot(m_cameraUp,razi); + + + int m_forwardAxis = 2; + + btVector3 eyePos(0,0,0); + eyePos[m_forwardAxis] = -m_cameraDistance; + + btVector3 forward(eyePos[0],eyePos[1],eyePos[2]); + if (forward.length2() < SIMD_EPSILON) + { + forward.setValue(1.f,0.f,0.f); + } + btVector3 right = m_cameraUp.cross(forward); + btQuaternion roll(right,-rele); + + eyePos = btMatrix3x3(rot) * btMatrix3x3(roll) * eyePos; + + m_cameraPosition[0] = eyePos.getX(); + m_cameraPosition[1] = eyePos.getY(); + m_cameraPosition[2] = eyePos.getZ(); + m_cameraPosition += m_cameraTargetPosition; + + if (m_glutScreenWidth == 0 && m_glutScreenHeight == 0) + return; + + btScalar aspect; + btVector3 extents; + + if (m_glutScreenWidth > m_glutScreenHeight) + { + aspect = m_glutScreenWidth / (btScalar)m_glutScreenHeight; + extents.setValue(aspect * 1.0f, 1.0f,0); + } else + { + aspect = m_glutScreenHeight / (btScalar)m_glutScreenWidth; + extents.setValue(1.0f, aspect*1.f,0); + } + + + if (m_ortho) + { + // reset matrix + glLoadIdentity(); + + + extents *= m_cameraDistance; + btVector3 lower = m_cameraTargetPosition - extents; + btVector3 upper = m_cameraTargetPosition + extents; + //gluOrtho2D(lower.x, upper.x, lower.y, upper.y); + glOrtho(lower.getX(), upper.getX(), lower.getY(), upper.getY(),-1000,1000); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + //glTranslatef(100,210,0); + } else + { + if (m_glutScreenWidth > m_glutScreenHeight) + { +// glFrustum (-aspect, aspect, -1.0, 1.0, 1.0, 10000.0); + glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar); + } else + { +// glFrustum (-1.0, 1.0, -aspect, aspect, 1.0, 10000.0); + glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar); + } + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(m_cameraPosition[0], m_cameraPosition[1], m_cameraPosition[2], + m_cameraTargetPosition[0], m_cameraTargetPosition[1], m_cameraTargetPosition[2], + m_cameraUp.getX(),m_cameraUp.getY(),m_cameraUp.getZ()); + } + +} + + +int main(int argc,char** argv) +{ + clientResetScene(); + + btMatrix3x3 basisA; + basisA.setIdentity(); + + btMatrix3x3 basisB; + basisB.setIdentity(); + + tr[0].setBasis(basisA); + tr[1].setBasis(basisB); + + btVector3 points0[3]={btVector3(1,0,0),btVector3(0,1,0),btVector3(0,0,1)}; + //btVector3 points1[5]={btVector3(1,0,0),btVector3(0,1,0),btVector3(0,0,1),btVector3(0,0,-1),btVector3(-1,-1,0)}; + + btConvexHullShape hullA(&points0[0].getX(),3); + btConvexHullShape hullB(TaruVtx,TaruVtxCount,3*sizeof(btScalar)); + + shapePtr[0] = &hullA; + shapePtr[1] = &hullB; + + + btTransform tr; + tr.setIdentity(); + + + return myglutmain(argc, argv,screenWidth,screenHeight,"Convex Hull Distance Demo"); +} + + +static btVoronoiSimplexSolver sGjkSimplexSolver; +btSimplexSolverInterface& gGjkSimplexSolver = sGjkSimplexSolver; + +#include + + +void clientDisplay(void) { + + + updateCamera(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glDisable(GL_LIGHTING); + + //GL_ShapeDrawer::drawCoordSystem(); + + btScalar m[16]; + int i; +#ifdef USE_GJK + btGjkEpaPenetrationDepthSolver epa; + btGjkPairDetector convexConvex(shapePtr[0],shapePtr[1],&sGjkSimplexSolver,&epa); + + btVector3 seperatingAxis(0.00000000f,0.059727669f,0.29259586f); + convexConvex.setCachedSeperatingAxis(seperatingAxis); + + btPointCollector gjkOutput; + btGjkPairDetector::ClosestPointInput input; + input.m_transformA = tr[0]; + input.m_transformB = tr[1]; + + convexConvex.getClosestPoints(input ,gjkOutput,0); + + if (gjkOutput.m_hasResult) + { + btVector3 endPt = gjkOutput.m_pointInWorld + + gjkOutput.m_normalOnBInWorld*gjkOutput.m_distance; + + glBegin(GL_LINES); + glColor3f(1, 0, 0); + glVertex3d(gjkOutput.m_pointInWorld.x(), gjkOutput.m_pointInWorld.y(),gjkOutput.m_pointInWorld.z()); + glVertex3d(endPt.x(),endPt.y(),endPt.z()); + glEnd(); + + } +#else //USE_GJK + + + struct MyContactResultCallback : public btCollisionWorld::ContactResultCallback + { + virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1) + { + glBegin(GL_LINES); + glColor3f(1, 0, 0); + + glVertex3d(cp.m_positionWorldOnA.getX(),cp.m_positionWorldOnA.getY(),cp.m_positionWorldOnA.getZ()); + glVertex3d(cp.m_positionWorldOnB.getX(),cp.m_positionWorldOnB.getY(),cp.m_positionWorldOnB.getZ()); + glEnd(); + + return 1.f; + } + }; + + btDefaultCollisionConfiguration collisionConfiguration; + btCollisionDispatcher dispatcher(&collisionConfiguration); + btDbvtBroadphase pairCache; + btCollisionWorld world (&dispatcher,&pairCache,&collisionConfiguration); + world.getDispatchInfo().m_convexMaxDistanceUseCPT = true; + MyContactResultCallback result; + btCollisionObject obA; + obA.setCollisionShape(shapePtr[0]); + obA.setWorldTransform(tr[0]); + btCollisionObject obB; + obB.setCollisionShape(shapePtr[1]); + obB.setWorldTransform(tr[1]); + world.contactPairTest(&obA,&obB,result); + +#endif//USE_GJK + + btVector3 worldMin(-1000,-1000,-1000); + btVector3 worldMax(1000,1000,1000); + + for (i=0;iisPolyhedral()) + { + if (!shapePtr[i]->getUserPointer()) + { + btConvexHullComputer* convexUtil = new btConvexHullComputer(); + shapePtr[i]->setUserPointer(convexUtil); + + btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shapePtr[i]; + + btAlignedObjectArray vertices; + vertices.resize(polyshape->getNumVertices()); + for (int i=0;igetNumVertices();i++) + { + polyshape->getVertex(i,vertices[i]); + } + + bool useDoublePrecision = false; + convexUtil->compute(&vertices[0].getX(),sizeof(btVector3), polyshape->getNumVertices(),0,0); + } + + if (shapePtr[i]->getUserPointer()) + { + btConvexHullComputer* convexUtil = (btConvexHullComputer*)shapePtr[i]->getUserPointer(); + //printf("num faces = %d\n",convexUtil->faces.size()); + for (int j=0;jfaces.size();j++) + { + int face = convexUtil->faces[j]; + //printf("face=%d\n",face); + const btConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face]; + const btConvexHullComputer::Edge* edge = firstEdge; + + do + { + int src = edge->getSourceVertex(); + int targ = edge->getTargetVertex(); + //printf("src=%d target = %d\n", src,targ); + + btVector3 wa = tr[i] * convexUtil->vertices[src]; + btVector3 wb = tr[i] * convexUtil->vertices[targ]; + + glBegin(GL_LINES); + glColor3f(1, 1, 1); + glVertex3f(wa.getX(),wa.getY(),wa.getZ()); + glVertex3f(wb.getX(),wb.getY(),wb.getZ()); + glEnd(); + + edge = edge->getNextEdgeOfFace(); + } while (edge!=firstEdge); + + } + } + } + } else + { + shapeDrawer.drawOpenGL(m,shapePtr[i],btVector3(1,1,1),debugMode, worldMin, worldMax); + } + + + } + + simplex.setSimplexSolver(&sGjkSimplexSolver); + btVector3 ybuf[4],pbuf[4],qbuf[4]; + int numpoints = sGjkSimplexSolver.getSimplex(pbuf,qbuf,ybuf); + simplex.reset(); + + for (i=0;i +char (*RtlpNumberOf( UNALIGNED T (&)[N] ))[N]; + +#define RTL_NUMBER_OF_V2(A) (sizeof(*RtlpNumberOf(A))) +#define ARRAYSIZE(A) RTL_NUMBER_OF_V2(A) +#endif + +//-------------------------------------------------------------------------------------- +// Thread safety +//-------------------------------------------------------------------------------------- +CRITICAL_SECTION g_cs; +bool g_bThreadSafe = true; + + +//-------------------------------------------------------------------------------------- +// Automatically enters & leaves the CS upon object creation/deletion +//-------------------------------------------------------------------------------------- +class DXUTLock +{ +public: + inline DXUTLock() { if( g_bThreadSafe ) EnterCriticalSection( &g_cs ); } + inline ~DXUTLock() { if( g_bThreadSafe ) LeaveCriticalSection( &g_cs ); } +}; + +//-------------------------------------------------------------------------------------- +// Helper macros to build member functions that access member variables with thread safety +//-------------------------------------------------------------------------------------- +#define SET_ACCESSOR( x, y ) inline void Set##y( x t ) { DXUTLock l; m_state.m_##y = t; }; +#define GET_ACCESSOR( x, y ) inline x Get##y() { DXUTLock l; return m_state.m_##y; }; +#define GET_SET_ACCESSOR( x, y ) SET_ACCESSOR( x, y ) GET_ACCESSOR( x, y ) + +#define SETP_ACCESSOR( x, y ) inline void Set##y( x* t ) { DXUTLock l; m_state.m_##y = *t; }; +#define GETP_ACCESSOR( x, y ) inline x* Get##y() { DXUTLock l; return &m_state.m_##y; }; +#define GETP_SETP_ACCESSOR( x, y ) SETP_ACCESSOR( x, y ) GETP_ACCESSOR( x, y ) + + +//-------------------------------------------------------------------------------------- +// Stores timer callback info +//-------------------------------------------------------------------------------------- +struct DXUT_TIMER +{ + LPDXUTCALLBACKTIMER pCallbackTimer; + void* pCallbackUserContext; + float fTimeoutInSecs; + float fCountdown; + bool bEnabled; + UINT nID; +}; + + + +//-------------------------------------------------------------------------------------- +// Stores DXUT state and data access is done with thread safety (if g_bThreadSafe==true) +//-------------------------------------------------------------------------------------- +class DXUTState +{ +protected: + struct STATE + { + // D3D9 specific + IDirect3D9* m_D3D9; // the main D3D9 object + IDirect3DDevice9* m_D3D9Device; // the D3D9 rendering device + DXUTDeviceSettings* m_CurrentDeviceSettings; // current device settings + D3DSURFACE_DESC m_BackBufferSurfaceDesc9; // D3D9 back buffer surface description + D3DCAPS9 m_Caps; // D3D caps for current device + + // D3D11 specific + IDXGIFactory1* m_DXGIFactory; // DXGI Factory object + IDXGIAdapter1* m_DXGIAdapter; // The DXGI adapter object for the D3D11 device + IDXGIOutput** m_DXGIOutputArray; // The array of output obj for the D3D11 adapter obj + UINT m_DXGIOutputArraySize; // Number of elements in m_D3D11OutputArray + IDXGISwapChain* m_DXGISwapChain; // the D3D11 swapchain + DXGI_SURFACE_DESC m_BackBufferSurfaceDescDXGI; // D3D11 back buffer surface description + bool m_RenderingOccluded; // Rendering is occluded by another window + bool m_DoNotStoreBufferSize; // Do not store the buffer size on WM_SIZE messages + + // D3D11 specific + bool m_D3D11Available; // if true, then D3D11 is available + ID3D11Device* m_D3D11Device; // the D3D11 rendering device + ID3D11DeviceContext* m_D3D11DeviceContext; // the D3D11 immediate device context + D3D_FEATURE_LEVEL m_D3D11FeatureLevel; // the D3D11 feature level that this device supports + ID3D11Texture2D* m_D3D11DepthStencil; // the D3D11 depth stencil texture (optional) + ID3D11DepthStencilView* m_D3D11DepthStencilView; // the D3D11 depth stencil view (optional) + ID3D11RenderTargetView* m_D3D11RenderTargetView; // the D3D11 render target view + ID3D11RasterizerState* m_D3D11RasterizerState; // the D3D11 Rasterizer state + + // General + HWND m_HWNDFocus; // the main app focus window + HWND m_HWNDDeviceFullScreen; // the main app device window in fullscreen mode + HWND m_HWNDDeviceWindowed; // the main app device window in windowed mode + HMONITOR m_AdapterMonitor; // the monitor of the adapter + HMENU m_Menu; // handle to menu + + UINT m_FullScreenBackBufferWidthAtModeChange; // back buffer size of fullscreen mode right before switching to windowed mode. Used to restore to same resolution when toggling back to fullscreen + UINT m_FullScreenBackBufferHeightAtModeChange; // back buffer size of fullscreen mode right before switching to windowed mode. Used to restore to same resolution when toggling back to fullscreen + UINT m_WindowBackBufferWidthAtModeChange; // back buffer size of windowed mode right before switching to fullscreen mode. Used to restore to same resolution when toggling back to windowed mode + UINT m_WindowBackBufferHeightAtModeChange; // back buffer size of windowed mode right before switching to fullscreen mode. Used to restore to same resolution when toggling back to windowed mode + DWORD m_WindowedStyleAtModeChange; // window style + WINDOWPLACEMENT m_WindowedPlacement;// record of windowed HWND position/show state/etc + bool m_TopmostWhileWindowed; // if true, the windowed HWND is topmost + bool m_Minimized; // if true, the HWND is minimized + bool m_Maximized; // if true, the HWND is maximized + bool m_MinimizedWhileFullscreen; // if true, the HWND is minimized due to a focus switch away when fullscreen mode + bool m_IgnoreSizeChange; // if true, DXUT won't reset the device upon HWND size change + + double m_Time; // current time in seconds + double m_AbsoluteTime; // absolute time in seconds + float m_ElapsedTime; // time elapsed since last frame + + HINSTANCE m_HInstance; // handle to the app instance + double m_LastStatsUpdateTime; // last time the stats were updated + DWORD m_LastStatsUpdateFrames; // frames count since last time the stats were updated + float m_FPS; // frames per second + int m_CurrentFrameNumber; // the current frame number + HHOOK m_KeyboardHook; // handle to keyboard hook + bool m_AllowShortcutKeysWhenFullscreen; // if true, when fullscreen enable shortcut keys (Windows keys, StickyKeys shortcut, ToggleKeys shortcut, FilterKeys shortcut) + bool m_AllowShortcutKeysWhenWindowed; // if true, when windowed enable shortcut keys (Windows keys, StickyKeys shortcut, ToggleKeys shortcut, FilterKeys shortcut) + bool m_AllowShortcutKeys; // if true, then shortcut keys are currently disabled (Windows key, etc) + bool m_CallDefWindowProc; // if true, DXUTStaticWndProc will call DefWindowProc for unhandled messages. Applications rendering to a dialog may need to set this to false. + STICKYKEYS m_StartupStickyKeys; // StickyKey settings upon startup so they can be restored later + TOGGLEKEYS m_StartupToggleKeys; // ToggleKey settings upon startup so they can be restored later + FILTERKEYS m_StartupFilterKeys; // FilterKey settings upon startup so they can be restored later + + bool m_AppSupportsD3D9Override; // true if app sets via DXUTSetD3DVersionSupport() + bool m_AppSupportsD3D11Override; // true if app sets via DXUTSetD3DVersionSupport() + bool m_UseD3DVersionOverride; // true if the app ever calls DXUTSetD3DVersionSupport() + + bool m_HandleEscape; // if true, then DXUT will handle escape to quit + bool m_HandleAltEnter; // if true, then DXUT will handle alt-enter to toggle fullscreen + bool m_HandlePause; // if true, then DXUT will handle pause to toggle time pausing + bool m_ShowMsgBoxOnError; // if true, then msgboxes are displayed upon errors + bool m_NoStats; // if true, then DXUTGetFrameStats() and DXUTGetDeviceStats() will return blank strings + bool m_ClipCursorWhenFullScreen; // if true, then DXUT will keep the cursor from going outside the window when full screen + bool m_ShowCursorWhenFullScreen; // if true, then DXUT will show a cursor when full screen + bool m_ConstantFrameTime; // if true, then elapsed frame time will always be 0.05f seconds which is good for debugging or automated capture + float m_TimePerFrame; // the constant time per frame in seconds, only valid if m_ConstantFrameTime==true + bool m_WireframeMode; // if true, then D3DRS_FILLMODE==D3DFILL_WIREFRAME else D3DRS_FILLMODE==D3DFILL_SOLID + bool m_AutoChangeAdapter; // if true, then the adapter will automatically change if the window is different monitor + bool m_WindowCreatedWithDefaultPositions; // if true, then CW_USEDEFAULT was used and the window should be moved to the right adapter + int m_ExitCode; // the exit code to be returned to the command line + + bool m_DXUTInited; // if true, then DXUTInit() has succeeded + bool m_WindowCreated; // if true, then DXUTCreateWindow() or DXUTSetWindow() has succeeded + bool m_DeviceCreated; // if true, then DXUTCreateDevice() or DXUTSetD3D*Device() has succeeded + + bool m_DXUTInitCalled; // if true, then DXUTInit() was called + bool m_WindowCreateCalled; // if true, then DXUTCreateWindow() or DXUTSetWindow() was called + bool m_DeviceCreateCalled; // if true, then DXUTCreateDevice() or DXUTSetD3D*Device() was called + + bool m_DeviceObjectsCreated; // if true, then DeviceCreated callback has been called (if non-NULL) + bool m_DeviceObjectsReset; // if true, then DeviceReset callback has been called (if non-NULL) + bool m_InsideDeviceCallback; // if true, then the framework is inside an app device callback + bool m_InsideMainloop; // if true, then the framework is inside the main loop + bool m_Active; // if true, then the app is the active top level window + bool m_TimePaused; // if true, then time is paused + bool m_RenderingPaused; // if true, then rendering is paused + int m_PauseRenderingCount; // pause rendering ref count + int m_PauseTimeCount; // pause time ref count + bool m_DeviceLost; // if true, then the device is lost and needs to be reset + bool m_NotifyOnMouseMove; // if true, include WM_MOUSEMOVE in mousecallback + bool m_Automation; // if true, automation is enabled + bool m_InSizeMove; // if true, app is inside a WM_ENTERSIZEMOVE + UINT m_TimerLastID; // last ID of the DXUT timer + bool m_MessageWhenD3D11NotAvailable; + + D3D_FEATURE_LEVEL m_OverrideForceFeatureLevel; // if != -1, then overrid to use a featurelevel + WCHAR m_ScreenShotName[256]; // command line screen shot name + bool m_SaveScreenShot; // command line save screen shot + bool m_ExitAfterScreenShot; // command line exit after screen shot + + int m_OverrideForceAPI; // if != -1, then override to use this Direct3D API version + int m_OverrideAdapterOrdinal; // if != -1, then override to use this adapter ordinal + bool m_OverrideWindowed; // if true, then force to start windowed + int m_OverrideOutput; // if != -1, then override to use the particular output on the adapter + bool m_OverrideFullScreen; // if true, then force to start full screen + int m_OverrideStartX; // if != -1, then override to this X position of the window + int m_OverrideStartY; // if != -1, then override to this Y position of the window + int m_OverrideWidth; // if != 0, then override to this width + int m_OverrideHeight; // if != 0, then override to this height + bool m_OverrideForceHAL; // if true, then force to HAL device (failing if one doesn't exist) + bool m_OverrideForceREF; // if true, then force to REF device (failing if one doesn't exist) + bool m_OverrideConstantFrameTime; // if true, then force to constant frame time + float m_OverrideConstantTimePerFrame; // the constant time per frame in seconds if m_OverrideConstantFrameTime==true + int m_OverrideQuitAfterFrame; // if != 0, then it will force the app to quit after that frame + int m_OverrideForceVsync; // if == 0, then it will force the app to use D3DPRESENT_INTERVAL_IMMEDIATE, if == 1 force use of D3DPRESENT_INTERVAL_DEFAULT + bool m_OverrideRelaunchMCE; // if true, then force relaunch of MCE at exit + bool m_AppCalledWasKeyPressed; // true if the app ever calls DXUTWasKeyPressed(). Allows for optimzation + bool m_ReleasingSwapChain; // if true, the app is releasing its swapchain + bool m_IsInGammaCorrectMode; // Tell DXUTRes and DXUTMisc that we are in gamma correct mode + + LPDXUTCALLBACKMODIFYDEVICESETTINGS m_ModifyDeviceSettingsFunc; // modify Direct3D device settings callback + LPDXUTCALLBACKDEVICEREMOVED m_DeviceRemovedFunc; // Direct3D device removed callback + LPDXUTCALLBACKFRAMEMOVE m_FrameMoveFunc; // frame move callback + LPDXUTCALLBACKKEYBOARD m_KeyboardFunc; // keyboard callback + LPDXUTCALLBACKMOUSE m_MouseFunc; // mouse callback + LPDXUTCALLBACKMSGPROC m_WindowMsgFunc; // window messages callback + + LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE m_IsD3D9DeviceAcceptableFunc; // D3D9 is device acceptable callback + LPDXUTCALLBACKD3D9DEVICECREATED m_D3D9DeviceCreatedFunc; // D3D9 device created callback + LPDXUTCALLBACKD3D9DEVICERESET m_D3D9DeviceResetFunc; // D3D9 device reset callback + LPDXUTCALLBACKD3D9DEVICELOST m_D3D9DeviceLostFunc; // D3D9 device lost callback + LPDXUTCALLBACKD3D9DEVICEDESTROYED m_D3D9DeviceDestroyedFunc; // D3D9 device destroyed callback + LPDXUTCALLBACKD3D9FRAMERENDER m_D3D9FrameRenderFunc; // D3D9 frame render callback + + LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE m_IsD3D11DeviceAcceptableFunc; // D3D11 is device acceptable callback + LPDXUTCALLBACKD3D11DEVICECREATED m_D3D11DeviceCreatedFunc; // D3D11 device created callback + LPDXUTCALLBACKD3D11SWAPCHAINRESIZED m_D3D11SwapChainResizedFunc; // D3D11 SwapChain reset callback + LPDXUTCALLBACKD3D11SWAPCHAINRELEASING m_D3D11SwapChainReleasingFunc; // D3D11 SwapChain lost callback + LPDXUTCALLBACKD3D11DEVICEDESTROYED m_D3D11DeviceDestroyedFunc; // D3D11 device destroyed callback + LPDXUTCALLBACKD3D11FRAMERENDER m_D3D11FrameRenderFunc; // D3D11 frame render callback + + + void* m_ModifyDeviceSettingsFuncUserContext; // user context for modify Direct3D device settings callback + void* m_DeviceRemovedFuncUserContext; // user context for Direct3D device removed callback + void* m_FrameMoveFuncUserContext; // user context for frame move callback + void* m_KeyboardFuncUserContext; // user context for keyboard callback + void* m_MouseFuncUserContext; // user context for mouse callback + void* m_WindowMsgFuncUserContext; // user context for window messages callback + + void* m_IsD3D9DeviceAcceptableFuncUserContext; // user context for is D3D9 device acceptable callback + void* m_D3D9DeviceCreatedFuncUserContext; // user context for D3D9 device created callback + void* m_D3D9DeviceResetFuncUserContext; // user context for D3D9 device reset callback + void* m_D3D9DeviceLostFuncUserContext; // user context for D3D9 device lost callback + void* m_D3D9DeviceDestroyedFuncUserContext; // user context for D3D9 device destroyed callback + void* m_D3D9FrameRenderFuncUserContext; // user context for D3D9 frame render callback + + void* m_IsD3D11DeviceAcceptableFuncUserContext; // user context for is D3D11 device acceptable callback + void* m_D3D11DeviceCreatedFuncUserContext; // user context for D3D11 device created callback + void* m_D3D11SwapChainResizedFuncUserContext; // user context for D3D11 SwapChain resized callback + void* m_D3D11SwapChainReleasingFuncUserContext; // user context for D3D11 SwapChain releasing callback + void* m_D3D11DeviceDestroyedFuncUserContext; // user context for D3D11 device destroyed callback + void* m_D3D11FrameRenderFuncUserContext; // user context for D3D11 frame render callback + + bool m_Keys[256]; // array of key state + bool m_LastKeys[256]; // array of last key state + bool m_MouseButtons[5]; // array of mouse states + + CGrowableArray* m_TimerList; // list of DXUT_TIMER structs + WCHAR m_StaticFrameStats[256]; // static part of frames stats + WCHAR m_FPSStats[64]; // fps stats + WCHAR m_FrameStats[256]; // frame stats (fps, width, etc) + WCHAR m_DeviceStats[256]; // device stats (description, device type, etc) + WCHAR m_WindowTitle[256]; // window title + }; + + STATE m_state; + +public: + DXUTState() { Create(); } + ~DXUTState() { Destroy(); } + + void Create() + { + g_bThreadSafe = true; + InitializeCriticalSectionAndSpinCount( &g_cs, 1000 ); + + ZeroMemory( &m_state, sizeof( STATE ) ); + m_state.m_OverrideStartX = -1; + m_state.m_OverrideStartY = -1; + m_state.m_OverrideForceFeatureLevel = (D3D_FEATURE_LEVEL)0; + m_state.m_ScreenShotName[0] = 0; + m_state.m_SaveScreenShot = false; + m_state.m_ExitAfterScreenShot = false; + m_state.m_OverrideForceAPI = -1; + m_state.m_OverrideAdapterOrdinal = -1; + m_state.m_OverrideOutput = -1; + m_state.m_OverrideForceVsync = -1; + m_state.m_AutoChangeAdapter = true; + m_state.m_ShowMsgBoxOnError = true; + m_state.m_AllowShortcutKeysWhenWindowed = true; + m_state.m_Active = true; + m_state.m_CallDefWindowProc = true; + m_state.m_HandleEscape = true; + m_state.m_HandleAltEnter = true; + m_state.m_HandlePause = true; + m_state.m_IsInGammaCorrectMode = true; + m_state.m_FPS = 1.0f; + m_state.m_MessageWhenD3D11NotAvailable = true; + } + + void Destroy() + { + SAFE_DELETE( m_state.m_TimerList ); + DXUTShutdown(); + DeleteCriticalSection( &g_cs ); + } + + // Macros to define access functions for thread safe access into m_state + GET_SET_ACCESSOR( DXUTDeviceSettings*, CurrentDeviceSettings ); + + // D3D9 specific + GET_SET_ACCESSOR( IDirect3D9*, D3D9 ); + GET_SET_ACCESSOR( IDirect3DDevice9*, D3D9Device ); + GETP_SETP_ACCESSOR( D3DSURFACE_DESC, BackBufferSurfaceDesc9 ); + GETP_SETP_ACCESSOR( D3DCAPS9, Caps ); + + // D3D11 specific + GET_SET_ACCESSOR( IDXGIFactory1*, DXGIFactory ); + GET_SET_ACCESSOR( IDXGIAdapter1*, DXGIAdapter ); + GET_SET_ACCESSOR( IDXGIOutput**, DXGIOutputArray ); + GET_SET_ACCESSOR( UINT, DXGIOutputArraySize ); + GET_SET_ACCESSOR( IDXGISwapChain*, DXGISwapChain ); + GETP_SETP_ACCESSOR( DXGI_SURFACE_DESC, BackBufferSurfaceDescDXGI ); + GET_SET_ACCESSOR( bool, RenderingOccluded ); + GET_SET_ACCESSOR( bool, DoNotStoreBufferSize ); + + // D3D11 specific + GET_SET_ACCESSOR( bool, D3D11Available ); + GET_SET_ACCESSOR( ID3D11Device*, D3D11Device ); + GET_SET_ACCESSOR( ID3D11DeviceContext*, D3D11DeviceContext ); + GET_SET_ACCESSOR( D3D_FEATURE_LEVEL, D3D11FeatureLevel ); + GET_SET_ACCESSOR( ID3D11Texture2D*, D3D11DepthStencil ); + GET_SET_ACCESSOR( ID3D11DepthStencilView*, D3D11DepthStencilView ); + GET_SET_ACCESSOR( ID3D11RenderTargetView*, D3D11RenderTargetView ); + GET_SET_ACCESSOR( ID3D11RasterizerState*, D3D11RasterizerState ); + + + GET_SET_ACCESSOR( HWND, HWNDFocus ); + GET_SET_ACCESSOR( HWND, HWNDDeviceFullScreen ); + GET_SET_ACCESSOR( HWND, HWNDDeviceWindowed ); + GET_SET_ACCESSOR( HMONITOR, AdapterMonitor ); + GET_SET_ACCESSOR( HMENU, Menu ); + + + GET_SET_ACCESSOR( UINT, FullScreenBackBufferWidthAtModeChange ); + GET_SET_ACCESSOR( UINT, FullScreenBackBufferHeightAtModeChange ); + GET_SET_ACCESSOR( UINT, WindowBackBufferWidthAtModeChange ); + GET_SET_ACCESSOR( UINT, WindowBackBufferHeightAtModeChange ); + GETP_SETP_ACCESSOR( WINDOWPLACEMENT, WindowedPlacement ); + GET_SET_ACCESSOR( DWORD, WindowedStyleAtModeChange ); + GET_SET_ACCESSOR( bool, TopmostWhileWindowed ); + GET_SET_ACCESSOR( bool, Minimized ); + GET_SET_ACCESSOR( bool, Maximized ); + GET_SET_ACCESSOR( bool, MinimizedWhileFullscreen ); + GET_SET_ACCESSOR( bool, IgnoreSizeChange ); + + GET_SET_ACCESSOR( double, Time ); + GET_SET_ACCESSOR( double, AbsoluteTime ); + GET_SET_ACCESSOR( float, ElapsedTime ); + + GET_SET_ACCESSOR( HINSTANCE, HInstance ); + GET_SET_ACCESSOR( double, LastStatsUpdateTime ); + GET_SET_ACCESSOR( DWORD, LastStatsUpdateFrames ); + GET_SET_ACCESSOR( float, FPS ); + GET_SET_ACCESSOR( int, CurrentFrameNumber ); + GET_SET_ACCESSOR( HHOOK, KeyboardHook ); + GET_SET_ACCESSOR( bool, AllowShortcutKeysWhenFullscreen ); + GET_SET_ACCESSOR( bool, AllowShortcutKeysWhenWindowed ); + GET_SET_ACCESSOR( bool, AllowShortcutKeys ); + GET_SET_ACCESSOR( bool, CallDefWindowProc ); + GET_SET_ACCESSOR( STICKYKEYS, StartupStickyKeys ); + GET_SET_ACCESSOR( TOGGLEKEYS, StartupToggleKeys ); + GET_SET_ACCESSOR( FILTERKEYS, StartupFilterKeys ); + + GET_SET_ACCESSOR( bool, AppSupportsD3D9Override ); + GET_SET_ACCESSOR( bool, AppSupportsD3D11Override ); + GET_SET_ACCESSOR( bool, UseD3DVersionOverride ); + + GET_SET_ACCESSOR( bool, HandleEscape ); + GET_SET_ACCESSOR( bool, HandleAltEnter ); + GET_SET_ACCESSOR( bool, HandlePause ); + GET_SET_ACCESSOR( bool, ShowMsgBoxOnError ); + GET_SET_ACCESSOR( bool, NoStats ); + GET_SET_ACCESSOR( bool, ClipCursorWhenFullScreen ); + GET_SET_ACCESSOR( bool, ShowCursorWhenFullScreen ); + GET_SET_ACCESSOR( bool, ConstantFrameTime ); + GET_SET_ACCESSOR( float, TimePerFrame ); + GET_SET_ACCESSOR( bool, WireframeMode ); + GET_SET_ACCESSOR( bool, AutoChangeAdapter ); + GET_SET_ACCESSOR( bool, WindowCreatedWithDefaultPositions ); + GET_SET_ACCESSOR( int, ExitCode ); + + GET_SET_ACCESSOR( bool, DXUTInited ); + GET_SET_ACCESSOR( bool, WindowCreated ); + GET_SET_ACCESSOR( bool, DeviceCreated ); + GET_SET_ACCESSOR( bool, DXUTInitCalled ); + GET_SET_ACCESSOR( bool, WindowCreateCalled ); + GET_SET_ACCESSOR( bool, DeviceCreateCalled ); + GET_SET_ACCESSOR( bool, InsideDeviceCallback ); + GET_SET_ACCESSOR( bool, InsideMainloop ); + GET_SET_ACCESSOR( bool, DeviceObjectsCreated ); + GET_SET_ACCESSOR( bool, DeviceObjectsReset ); + GET_SET_ACCESSOR( bool, Active ); + GET_SET_ACCESSOR( bool, RenderingPaused ); + GET_SET_ACCESSOR( bool, TimePaused ); + GET_SET_ACCESSOR( int, PauseRenderingCount ); + GET_SET_ACCESSOR( int, PauseTimeCount ); + GET_SET_ACCESSOR( bool, DeviceLost ); + GET_SET_ACCESSOR( bool, NotifyOnMouseMove ); + GET_SET_ACCESSOR( bool, Automation ); + GET_SET_ACCESSOR( bool, InSizeMove ); + GET_SET_ACCESSOR( UINT, TimerLastID ); + GET_SET_ACCESSOR( bool, MessageWhenD3D11NotAvailable ); + GET_SET_ACCESSOR( bool, AppCalledWasKeyPressed ); + + GET_SET_ACCESSOR( D3D_FEATURE_LEVEL, OverrideForceFeatureLevel ); + GET_ACCESSOR( WCHAR*, ScreenShotName ); + GET_SET_ACCESSOR( bool, SaveScreenShot ); + GET_SET_ACCESSOR( bool, ExitAfterScreenShot ); + + + GET_SET_ACCESSOR( int, OverrideForceAPI ); + GET_SET_ACCESSOR( int, OverrideAdapterOrdinal ); + GET_SET_ACCESSOR( bool, OverrideWindowed ); + GET_SET_ACCESSOR( int, OverrideOutput ); + GET_SET_ACCESSOR( bool, OverrideFullScreen ); + GET_SET_ACCESSOR( int, OverrideStartX ); + GET_SET_ACCESSOR( int, OverrideStartY ); + GET_SET_ACCESSOR( int, OverrideWidth ); + GET_SET_ACCESSOR( int, OverrideHeight ); + GET_SET_ACCESSOR( bool, OverrideForceHAL ); + GET_SET_ACCESSOR( bool, OverrideForceREF ); + GET_SET_ACCESSOR( bool, OverrideConstantFrameTime ); + GET_SET_ACCESSOR( float, OverrideConstantTimePerFrame ); + GET_SET_ACCESSOR( int, OverrideQuitAfterFrame ); + GET_SET_ACCESSOR( int, OverrideForceVsync ); + GET_SET_ACCESSOR( bool, OverrideRelaunchMCE ); + GET_SET_ACCESSOR( bool, ReleasingSwapChain ); + GET_SET_ACCESSOR( bool, IsInGammaCorrectMode ); + + GET_SET_ACCESSOR( LPDXUTCALLBACKMODIFYDEVICESETTINGS, ModifyDeviceSettingsFunc ); + GET_SET_ACCESSOR( LPDXUTCALLBACKDEVICEREMOVED, DeviceRemovedFunc ); + GET_SET_ACCESSOR( LPDXUTCALLBACKFRAMEMOVE, FrameMoveFunc ); + GET_SET_ACCESSOR( LPDXUTCALLBACKKEYBOARD, KeyboardFunc ); + GET_SET_ACCESSOR( LPDXUTCALLBACKMOUSE, MouseFunc ); + GET_SET_ACCESSOR( LPDXUTCALLBACKMSGPROC, WindowMsgFunc ); + + GET_SET_ACCESSOR( LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE, IsD3D9DeviceAcceptableFunc ); + GET_SET_ACCESSOR( LPDXUTCALLBACKD3D9DEVICECREATED, D3D9DeviceCreatedFunc ); + GET_SET_ACCESSOR( LPDXUTCALLBACKD3D9DEVICERESET, D3D9DeviceResetFunc ); + GET_SET_ACCESSOR( LPDXUTCALLBACKD3D9DEVICELOST, D3D9DeviceLostFunc ); + GET_SET_ACCESSOR( LPDXUTCALLBACKD3D9DEVICEDESTROYED, D3D9DeviceDestroyedFunc ); + GET_SET_ACCESSOR( LPDXUTCALLBACKD3D9FRAMERENDER, D3D9FrameRenderFunc ); + + GET_SET_ACCESSOR( LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE, IsD3D11DeviceAcceptableFunc ); + GET_SET_ACCESSOR( LPDXUTCALLBACKD3D11DEVICECREATED, D3D11DeviceCreatedFunc ); + GET_SET_ACCESSOR( LPDXUTCALLBACKD3D11SWAPCHAINRESIZED, D3D11SwapChainResizedFunc ); + GET_SET_ACCESSOR( LPDXUTCALLBACKD3D11SWAPCHAINRELEASING, D3D11SwapChainReleasingFunc ); + GET_SET_ACCESSOR( LPDXUTCALLBACKD3D11DEVICEDESTROYED, D3D11DeviceDestroyedFunc ); + GET_SET_ACCESSOR( LPDXUTCALLBACKD3D11FRAMERENDER, D3D11FrameRenderFunc ); + + GET_SET_ACCESSOR( void*, ModifyDeviceSettingsFuncUserContext ); + GET_SET_ACCESSOR( void*, DeviceRemovedFuncUserContext ); + GET_SET_ACCESSOR( void*, FrameMoveFuncUserContext ); + GET_SET_ACCESSOR( void*, KeyboardFuncUserContext ); + GET_SET_ACCESSOR( void*, MouseFuncUserContext ); + GET_SET_ACCESSOR( void*, WindowMsgFuncUserContext ); + + GET_SET_ACCESSOR( void*, IsD3D9DeviceAcceptableFuncUserContext ); + GET_SET_ACCESSOR( void*, D3D9DeviceCreatedFuncUserContext ); + GET_SET_ACCESSOR( void*, D3D9DeviceResetFuncUserContext ); + GET_SET_ACCESSOR( void*, D3D9DeviceLostFuncUserContext ); + GET_SET_ACCESSOR( void*, D3D9DeviceDestroyedFuncUserContext ); + GET_SET_ACCESSOR( void*, D3D9FrameRenderFuncUserContext ); + + GET_SET_ACCESSOR( void*, IsD3D11DeviceAcceptableFuncUserContext ); + GET_SET_ACCESSOR( void*, D3D11DeviceCreatedFuncUserContext ); + GET_SET_ACCESSOR( void*, D3D11DeviceDestroyedFuncUserContext ); + GET_SET_ACCESSOR( void*, D3D11SwapChainResizedFuncUserContext ); + GET_SET_ACCESSOR( void*, D3D11SwapChainReleasingFuncUserContext ); + GET_SET_ACCESSOR( void*, D3D11FrameRenderFuncUserContext ); + + GET_SET_ACCESSOR( CGrowableArray*, TimerList ); + GET_ACCESSOR( bool*, Keys ); + GET_ACCESSOR( bool*, LastKeys ); + GET_ACCESSOR( bool*, MouseButtons ); + GET_ACCESSOR( WCHAR*, StaticFrameStats ); + GET_ACCESSOR( WCHAR*, FPSStats ); + GET_ACCESSOR( WCHAR*, FrameStats ); + GET_ACCESSOR( WCHAR*, DeviceStats ); + GET_ACCESSOR( WCHAR*, WindowTitle ); +}; + + +//-------------------------------------------------------------------------------------- +// Global state +//-------------------------------------------------------------------------------------- +DXUTState* g_pDXUTState = NULL; + +HRESULT WINAPI DXUTCreateState() +{ + if( g_pDXUTState == NULL ) + { + g_pDXUTState = new DXUTState; + if( NULL == g_pDXUTState ) + return E_OUTOFMEMORY; + } + return S_OK; +} + +void WINAPI DXUTDestroyState() +{ + SAFE_DELETE( g_pDXUTState ); +} + +class DXUTMemoryHelper +{ +public: + DXUTMemoryHelper() { DXUTCreateState(); } + ~DXUTMemoryHelper() { DXUTDestroyState(); } +}; + + +DXUTState& GetDXUTState() +{ + // This class will auto create the memory when its first accessed and delete it after the program exits WinMain. + // However the application can also call DXUTCreateState() & DXUTDestroyState() independantly if its wants + static DXUTMemoryHelper memory; + + return *g_pDXUTState; +} + + +//-------------------------------------------------------------------------------------- +// Internal functions forward declarations +//-------------------------------------------------------------------------------------- +void DXUTParseCommandLine( __inout WCHAR* strCommandLine, + bool bIgnoreFirstCommand = true ); +bool DXUTIsNextArg( __inout WCHAR*& strCmdLine, + __inout WCHAR* strArg ); +bool DXUTGetCmdParam( __inout WCHAR*& strCmdLine, + __inout_ecount(MAX_PATH) WCHAR* strFlag ); +void DXUTAllowShortcutKeys( bool bAllowKeys ); +void DXUTUpdateStaticFrameStats(); +void DXUTUpdateFrameStats(); + +LRESULT CALLBACK DXUTStaticWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); +void DXUTHandleTimers(); +void DXUTDisplayErrorMessage( HRESULT hr ); +int DXUTMapButtonToArrayIndex( BYTE vButton ); + +HRESULT DXUTChangeDevice( DXUTDeviceSettings* pNewDeviceSettings, + IDirect3DDevice9* pd3d9DeviceFromApp, + ID3D11Device* pd3d11DeviceFromApp, + bool bForceRecreate, + bool bClipWindowToSingleAdapter ); + +bool DXUTCanDeviceBeReset( DXUTDeviceSettings* pOldDeviceSettings, + DXUTDeviceSettings* pNewDeviceSettings, + IDirect3DDevice9* pd3d9DeviceFromApp, + ID3D11Device* pd3d11DeviceFromApp ); + + +HRESULT DXUTDelayLoadDXGI(); +HRESULT DXUTDelayLoadD3D9(); +HRESULT DXUTSnapDeviceSettingsToEnumDevice( DXUTDeviceSettings* pDeviceSettings, bool forceEnum, D3D_FEATURE_LEVEL forceFL = D3D_FEATURE_LEVEL(0) ); +void DXUTUpdateDeviceSettingsWithOverrides( DXUTDeviceSettings* pDeviceSettings ); +void DXUTCheckForDXGIFullScreenSwitch(); +void DXUTResizeDXGIBuffers( UINT Width, UINT Height, BOOL bFullscreen ); +void DXUTCheckForDXGIBufferChange(); +void DXUTCheckForWindowSizeChange(); +void DXUTCheckForWindowChangingMonitors(); +void DXUTCleanup3DEnvironment( bool bReleaseSettings ); +HMONITOR DXUTGetMonitorFromAdapter( DXUTDeviceSettings* pDeviceSettings ); +HRESULT DXUTGetAdapterOrdinalFromMonitor( HMONITOR hMonitor, UINT* pAdapterOrdinal ); +HRESULT DXUTGetOutputOrdinalFromMonitor( HMONITOR hMonitor, UINT* pOutputOrdinal ); +HRESULT DXUTHandleDeviceRemoved(); +void DXUTUpdateBackBufferDesc(); +void DXUTSetupCursor(); + +// Direct3D 9 +HRESULT DXUTCreate3DEnvironment9( IDirect3DDevice9* pd3dDeviceFromApp ); +HRESULT DXUTReset3DEnvironment9(); +void DXUTRender3DEnvironment9(); +void DXUTCleanup3DEnvironment9( bool bReleaseSettings = true ); +HRESULT DXUTSetD3D9DeviceCursor( IDirect3DDevice9* pd3dDevice, HCURSOR hCursor, bool bAddWatermark ); +void DXUTUpdateD3D9DeviceStats( D3DDEVTYPE DeviceType, DWORD BehaviorFlags, + D3DADAPTER_IDENTIFIER9* pAdapterIdentifier ); +HRESULT DXUTFindD3D9AdapterFormat( UINT AdapterOrdinal, D3DDEVTYPE DeviceType, D3DFORMAT BackBufferFormat, + BOOL Windowed, D3DFORMAT* pAdapterFormat ); + +// Direct3D 11 +HRESULT DXUTCreateD3D11Views( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dDeviceContext, DXUTDeviceSettings* pDeviceSettings ); +HRESULT DXUTCreate3DEnvironment11( ID3D11Device* pd3dDeviceFromApp ); +HRESULT DXUTReset3DEnvironment11(); +void DXUTRender3DEnvironment11(); +void DXUTCleanup3DEnvironment11( bool bReleaseSettings = true ); +void DXUTUpdateD3D11DeviceStats( D3D_DRIVER_TYPE DeviceType, DXGI_ADAPTER_DESC* pAdapterDesc ); + + +//-------------------------------------------------------------------------------------- +// Internal helper functions +//-------------------------------------------------------------------------------------- +bool DXUTIsD3D9( DXUTDeviceSettings* pDeviceSettings ) { return (pDeviceSettings && pDeviceSettings->ver == DXUT_D3D9_DEVICE ); }; +bool DXUTIsCurrentDeviceD3D9() { DXUTDeviceSettings* pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); return DXUTIsD3D9(pDeviceSettings); }; +UINT DXUTGetBackBufferWidthFromDS( DXUTDeviceSettings* pNewDeviceSettings ) +{ + if( DXUTIsD3D9( pNewDeviceSettings ) ) + return pNewDeviceSettings->d3d9.pp.BackBufferWidth; + else + return pNewDeviceSettings->d3d11.sd.BufferDesc.Width; +} +UINT DXUTGetBackBufferHeightFromDS( DXUTDeviceSettings* pNewDeviceSettings ) +{ + if( DXUTIsD3D9(pNewDeviceSettings) ) + return pNewDeviceSettings->d3d9.pp.BackBufferHeight; + else + return pNewDeviceSettings->d3d11.sd.BufferDesc.Height; +} +bool DXUTGetIsWindowedFromDS( DXUTDeviceSettings* pNewDeviceSettings ) +{ + if (!pNewDeviceSettings) + return true; + + if( DXUTIsD3D9(pNewDeviceSettings) ) + return pNewDeviceSettings->d3d9.pp.Windowed ? true : false; + else + return pNewDeviceSettings->d3d11.sd.Windowed ? true : false; +} + + +//-------------------------------------------------------------------------------------- +// External state access functions +//-------------------------------------------------------------------------------------- +BOOL WINAPI DXUTGetMSAASwapChainCreated() { + DXUTDeviceSettings *psettings = GetDXUTState().GetCurrentDeviceSettings(); + if (psettings->ver == DXUT_D3D11_DEVICE) { + return psettings->d3d11.sd.SampleDesc.Count > 1; + }else if (psettings->ver == DXUT_D3D9_DEVICE) { + return (psettings->d3d9.pp.MultiSampleType >= D3DMULTISAMPLE_2_SAMPLES); + } + else return false; +} +IDirect3DDevice9* WINAPI DXUTGetD3D9Device() { return GetDXUTState().GetD3D9Device(); } +const D3DSURFACE_DESC* WINAPI DXUTGetD3D9BackBufferSurfaceDesc() { return GetDXUTState().GetBackBufferSurfaceDesc9(); } +const D3DCAPS9* WINAPI DXUTGetD3D9DeviceCaps() { return GetDXUTState().GetCaps(); } +ID3D11Device* WINAPI DXUTGetD3D11Device() { return GetDXUTState().GetD3D11Device(); } +D3D_FEATURE_LEVEL WINAPI DXUTGetD3D11DeviceFeatureLevel() { return GetDXUTState().GetD3D11FeatureLevel(); } +ID3D11DeviceContext* WINAPI DXUTGetD3D11DeviceContext() { return GetDXUTState().GetD3D11DeviceContext(); } +IDXGISwapChain* WINAPI DXUTGetDXGISwapChain() { return GetDXUTState().GetDXGISwapChain(); } +ID3D11RenderTargetView* WINAPI DXUTGetD3D11RenderTargetView() { return GetDXUTState().GetD3D11RenderTargetView(); } +ID3D11DepthStencilView* WINAPI DXUTGetD3D11DepthStencilView() { return GetDXUTState().GetD3D11DepthStencilView(); } +const DXGI_SURFACE_DESC* WINAPI DXUTGetDXGIBackBufferSurfaceDesc() { return GetDXUTState().GetBackBufferSurfaceDescDXGI(); } +HINSTANCE WINAPI DXUTGetHINSTANCE() { return GetDXUTState().GetHInstance(); } +HWND WINAPI DXUTGetHWND() { return DXUTIsWindowed() ? GetDXUTState().GetHWNDDeviceWindowed() : GetDXUTState().GetHWNDDeviceFullScreen(); } +HWND WINAPI DXUTGetHWNDFocus() { return GetDXUTState().GetHWNDFocus(); } +HWND WINAPI DXUTGetHWNDDeviceFullScreen() { return GetDXUTState().GetHWNDDeviceFullScreen(); } +HWND WINAPI DXUTGetHWNDDeviceWindowed() { return GetDXUTState().GetHWNDDeviceWindowed(); } +RECT WINAPI DXUTGetWindowClientRect() { RECT rc; GetClientRect( DXUTGetHWND(), &rc ); return rc; } +LONG WINAPI DXUTGetWindowWidth() { RECT rc = DXUTGetWindowClientRect(); return ((LONG)rc.right - rc.left); } +LONG WINAPI DXUTGetWindowHeight() { RECT rc = DXUTGetWindowClientRect(); return ((LONG)rc.bottom - rc.top); } +RECT WINAPI DXUTGetWindowClientRectAtModeChange() { RECT rc = { 0, 0, GetDXUTState().GetWindowBackBufferWidthAtModeChange(), GetDXUTState().GetWindowBackBufferHeightAtModeChange() }; return rc; } +RECT WINAPI DXUTGetFullsceenClientRectAtModeChange() { RECT rc = { 0, 0, GetDXUTState().GetFullScreenBackBufferWidthAtModeChange(), GetDXUTState().GetFullScreenBackBufferHeightAtModeChange() }; return rc; } +double WINAPI DXUTGetTime() { return GetDXUTState().GetTime(); } +float WINAPI DXUTGetElapsedTime() { return GetDXUTState().GetElapsedTime(); } +float WINAPI DXUTGetFPS() { return GetDXUTState().GetFPS(); } +LPCWSTR WINAPI DXUTGetWindowTitle() { return GetDXUTState().GetWindowTitle(); } +LPCWSTR WINAPI DXUTGetDeviceStats() { return GetDXUTState().GetDeviceStats(); } +bool WINAPI DXUTIsRenderingPaused() { return GetDXUTState().GetPauseRenderingCount() > 0; } +bool WINAPI DXUTIsTimePaused() { return GetDXUTState().GetPauseTimeCount() > 0; } +bool WINAPI DXUTIsActive() { return GetDXUTState().GetActive(); } +int WINAPI DXUTGetExitCode() { return GetDXUTState().GetExitCode(); } +bool WINAPI DXUTGetShowMsgBoxOnError() { return GetDXUTState().GetShowMsgBoxOnError(); } +bool WINAPI DXUTGetAutomation() { return GetDXUTState().GetAutomation(); } +bool WINAPI DXUTIsWindowed() { return DXUTGetIsWindowedFromDS( GetDXUTState().GetCurrentDeviceSettings() ); } +bool WINAPI DXUTIsInGammaCorrectMode() { return GetDXUTState().GetIsInGammaCorrectMode(); } +IDirect3D9* WINAPI DXUTGetD3D9Object() { DXUTDelayLoadD3D9(); return GetDXUTState().GetD3D9(); } +IDXGIFactory1* WINAPI DXUTGetDXGIFactory() { DXUTDelayLoadDXGI(); return GetDXUTState().GetDXGIFactory(); } +bool WINAPI DXUTIsD3D11Available() { DXUTDelayLoadDXGI(); return GetDXUTState().GetD3D11Available(); } +bool WINAPI DXUTIsAppRenderingWithD3D9() { return (GetDXUTState().GetD3D9Device() != NULL); } +bool WINAPI DXUTIsAppRenderingWithD3D11() { return (GetDXUTState().GetD3D11Device() != NULL); } + +//-------------------------------------------------------------------------------------- +// External callback setup functions +//-------------------------------------------------------------------------------------- + +// General callbacks +void WINAPI DXUTSetCallbackDeviceChanging( LPDXUTCALLBACKMODIFYDEVICESETTINGS pCallback, void* pUserContext ) { GetDXUTState().SetModifyDeviceSettingsFunc( pCallback ); GetDXUTState().SetModifyDeviceSettingsFuncUserContext( pUserContext ); } +void WINAPI DXUTSetCallbackDeviceRemoved( LPDXUTCALLBACKDEVICEREMOVED pCallback, void* pUserContext ) { GetDXUTState().SetDeviceRemovedFunc( pCallback ); GetDXUTState().SetDeviceRemovedFuncUserContext( pUserContext ); } +void WINAPI DXUTSetCallbackFrameMove( LPDXUTCALLBACKFRAMEMOVE pCallback, void* pUserContext ) { GetDXUTState().SetFrameMoveFunc( pCallback ); GetDXUTState().SetFrameMoveFuncUserContext( pUserContext ); } +void WINAPI DXUTSetCallbackKeyboard( LPDXUTCALLBACKKEYBOARD pCallback, void* pUserContext ) { GetDXUTState().SetKeyboardFunc( pCallback ); GetDXUTState().SetKeyboardFuncUserContext( pUserContext ); } +void WINAPI DXUTSetCallbackMouse( LPDXUTCALLBACKMOUSE pCallback, bool bIncludeMouseMove, void* pUserContext ) { GetDXUTState().SetMouseFunc( pCallback ); GetDXUTState().SetNotifyOnMouseMove( bIncludeMouseMove ); GetDXUTState().SetMouseFuncUserContext( pUserContext ); } +void WINAPI DXUTSetCallbackMsgProc( LPDXUTCALLBACKMSGPROC pCallback, void* pUserContext ) { GetDXUTState().SetWindowMsgFunc( pCallback ); GetDXUTState().SetWindowMsgFuncUserContext( pUserContext ); } + +// Direct3D 9 callbacks +void WINAPI DXUTSetCallbackD3D9DeviceAcceptable( LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE pCallback, void* pUserContext ) { GetDXUTState().SetIsD3D9DeviceAcceptableFunc( pCallback ); GetDXUTState().SetIsD3D9DeviceAcceptableFuncUserContext( pUserContext ); } +void WINAPI DXUTSetCallbackD3D9DeviceCreated( LPDXUTCALLBACKD3D9DEVICECREATED pCallback, void* pUserContext ) { GetDXUTState().SetD3D9DeviceCreatedFunc( pCallback ); GetDXUTState().SetD3D9DeviceCreatedFuncUserContext( pUserContext ); } +void WINAPI DXUTSetCallbackD3D9DeviceReset( LPDXUTCALLBACKD3D9DEVICERESET pCallback, void* pUserContext ) { GetDXUTState().SetD3D9DeviceResetFunc( pCallback ); GetDXUTState().SetD3D9DeviceResetFuncUserContext( pUserContext ); } +void WINAPI DXUTSetCallbackD3D9DeviceLost( LPDXUTCALLBACKD3D9DEVICELOST pCallback, void* pUserContext ) { GetDXUTState().SetD3D9DeviceLostFunc( pCallback ); GetDXUTState().SetD3D9DeviceLostFuncUserContext( pUserContext ); } +void WINAPI DXUTSetCallbackD3D9DeviceDestroyed( LPDXUTCALLBACKD3D9DEVICEDESTROYED pCallback, void* pUserContext ) { GetDXUTState().SetD3D9DeviceDestroyedFunc( pCallback ); GetDXUTState().SetD3D9DeviceDestroyedFuncUserContext( pUserContext ); } +void WINAPI DXUTSetCallbackD3D9FrameRender( LPDXUTCALLBACKD3D9FRAMERENDER pCallback, void* pUserContext ) { GetDXUTState().SetD3D9FrameRenderFunc( pCallback ); GetDXUTState().SetD3D9FrameRenderFuncUserContext( pUserContext ); } +void DXUTGetCallbackD3D9DeviceAcceptable( LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE* ppCallback, void** ppUserContext ) { *ppCallback = GetDXUTState().GetIsD3D9DeviceAcceptableFunc(); *ppUserContext = GetDXUTState().GetIsD3D9DeviceAcceptableFuncUserContext(); } + +// Direct3D 11 callbacks +void WINAPI DXUTSetCallbackD3D11DeviceAcceptable( LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE pCallback, void* pUserContext ) { GetDXUTState().SetIsD3D11DeviceAcceptableFunc( pCallback ); GetDXUTState().SetIsD3D11DeviceAcceptableFuncUserContext( pUserContext ); } +void WINAPI DXUTSetCallbackD3D11DeviceCreated( LPDXUTCALLBACKD3D11DEVICECREATED pCallback, void* pUserContext ) { GetDXUTState().SetD3D11DeviceCreatedFunc( pCallback ); GetDXUTState().SetD3D11DeviceCreatedFuncUserContext( pUserContext ); } +void WINAPI DXUTSetCallbackD3D11SwapChainResized( LPDXUTCALLBACKD3D11SWAPCHAINRESIZED pCallback, void* pUserContext ) { GetDXUTState().SetD3D11SwapChainResizedFunc( pCallback ); GetDXUTState().SetD3D11SwapChainResizedFuncUserContext( pUserContext ); } +void WINAPI DXUTSetCallbackD3D11FrameRender( LPDXUTCALLBACKD3D11FRAMERENDER pCallback, void* pUserContext ) { GetDXUTState().SetD3D11FrameRenderFunc( pCallback ); GetDXUTState().SetD3D11FrameRenderFuncUserContext( pUserContext ); } +void WINAPI DXUTSetCallbackD3D11SwapChainReleasing( LPDXUTCALLBACKD3D11SWAPCHAINRELEASING pCallback, void* pUserContext ) { GetDXUTState().SetD3D11SwapChainReleasingFunc( pCallback ); GetDXUTState().SetD3D11SwapChainReleasingFuncUserContext( pUserContext ); } +void WINAPI DXUTSetCallbackD3D11DeviceDestroyed( LPDXUTCALLBACKD3D11DEVICEDESTROYED pCallback, void* pUserContext ) { GetDXUTState().SetD3D11DeviceDestroyedFunc( pCallback ); GetDXUTState().SetD3D11DeviceDestroyedFuncUserContext( pUserContext ); } +void DXUTGetCallbackD3D11DeviceAcceptable( LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE* ppCallback, void** ppUserContext ) { *ppCallback = GetDXUTState().GetIsD3D11DeviceAcceptableFunc(); *ppUserContext = GetDXUTState().GetIsD3D11DeviceAcceptableFuncUserContext(); } + + +//-------------------------------------------------------------------------------------- +// Optionally parses the command line and sets if default hotkeys are handled +// +// Possible command line parameters are: +// -forcefeaturelevel:fl forces app to use a specified direct3D11 feature level +// -screenshotexit:filename save a screenshot to the filename.bmp and exit. +// -forceapi:# forces app to use specified Direct3D API version (fails if the application doesn't support this API or if no device is found) +// -adapter:# forces app to use this adapter # (fails if the adapter doesn't exist) +// -output:# [D3D11 only] forces app to use a particular output on the adapter (fails if the output doesn't exist) +// -windowed forces app to start windowed +// -fullscreen forces app to start full screen +// -forcehal forces app to use HAL (fails if HAL doesn't exist) +// -forceref forces app to use REF (fails if REF doesn't exist) +// -forcepurehwvp [D3D9 only] forces app to use pure HWVP (fails if device doesn't support it) +// -forcehwvp [D3D9 only] forces app to use HWVP (fails if device doesn't support it) +// -forceswvp [D3D9 only] forces app to use SWVP +// -forcevsync:# if # is 0, then vsync is disabled +// -width:# forces app to use # for width. for full screen, it will pick the closest possible supported mode +// -height:# forces app to use # for height. for full screen, it will pick the closest possible supported mode +// -startx:# forces app to use # for the x coord of the window position for windowed mode +// -starty:# forces app to use # for the y coord of the window position for windowed mode +// -constantframetime:# forces app to use constant frame time, where # is the time/frame in seconds +// -quitafterframe:x forces app to quit after # frames +// -noerrormsgboxes prevents the display of message boxes generated by the framework so the application can be run without user interaction +// -nostats prevents the display of the stats +// -relaunchmce re-launches the MCE UI after the app exits +// -automation a hint to other components that automation is active +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTInit( bool bParseCommandLine, + bool bShowMsgBoxOnError, + __in_opt WCHAR* strExtraCommandLineParams, + bool bThreadSafeDXUT ) +{ + g_bThreadSafe = bThreadSafeDXUT; + + GetDXUTState().SetDXUTInitCalled( true ); + + // Not always needed, but lets the app create GDI dialogs + InitCommonControls(); + + // Save the current sticky/toggle/filter key settings so DXUT can restore them later + STICKYKEYS sk = {sizeof(STICKYKEYS), 0}; + SystemParametersInfo(SPI_GETSTICKYKEYS, sizeof(STICKYKEYS), &sk, 0); + GetDXUTState().SetStartupStickyKeys( sk ); + + TOGGLEKEYS tk = {sizeof(TOGGLEKEYS), 0}; + SystemParametersInfo(SPI_GETTOGGLEKEYS, sizeof(TOGGLEKEYS), &tk, 0); + GetDXUTState().SetStartupToggleKeys( tk ); + + FILTERKEYS fk = {sizeof(FILTERKEYS), 0}; + SystemParametersInfo(SPI_GETFILTERKEYS, sizeof(FILTERKEYS), &fk, 0); + GetDXUTState().SetStartupFilterKeys( fk ); + + GetDXUTState().SetShowMsgBoxOnError( bShowMsgBoxOnError ); + + if( bParseCommandLine ) + DXUTParseCommandLine( GetCommandLine() ); + if( strExtraCommandLineParams ) + DXUTParseCommandLine( strExtraCommandLineParams, false ); + + // Reset the timer + DXUTGetGlobalTimer()->Reset(); + + GetDXUTState().SetDXUTInited( true ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Parses the command line for parameters. See DXUTInit() for list +//-------------------------------------------------------------------------------------- +void DXUTParseCommandLine(__inout WCHAR* strCommandLine, + bool bIgnoreFirstCommand ) +{ + WCHAR* strCmdLine; + WCHAR strFlag[MAX_PATH]; + + int nNumArgs; + LPWSTR* pstrArgList = CommandLineToArgvW( strCommandLine, &nNumArgs ); + int iArgStart = 0; + if( bIgnoreFirstCommand ) + iArgStart = 1; + for( int iArg = iArgStart; iArg < nNumArgs; iArg++ ) + { + strCmdLine = pstrArgList[iArg]; + + // Handle flag args + if( *strCmdLine == L'/' || *strCmdLine == L'-' ) + { + strCmdLine++; + + if( DXUTIsNextArg( strCmdLine, L"forcefeaturelevel" ) ) + { + if( DXUTGetCmdParam( strCmdLine, strFlag ) ) + { + if (_wcsnicmp( strFlag, L"D3D_FEATURE_LEVEL_11_0", MAX_PATH) == 0 ) { + GetDXUTState().SetOverrideForceFeatureLevel(D3D_FEATURE_LEVEL_11_0); + }else if (_wcsnicmp( strFlag, L"D3D_FEATURE_LEVEL_10_1", MAX_PATH) == 0 ) { + GetDXUTState().SetOverrideForceFeatureLevel(D3D_FEATURE_LEVEL_10_1); + }else if (_wcsnicmp( strFlag, L"D3D_FEATURE_LEVEL_10_0", MAX_PATH) == 0 ) { + GetDXUTState().SetOverrideForceFeatureLevel(D3D_FEATURE_LEVEL_10_0); + }else if (_wcsnicmp( strFlag, L"D3D_FEATURE_LEVEL_9_3", MAX_PATH) == 0 ) { + GetDXUTState().SetOverrideForceFeatureLevel(D3D_FEATURE_LEVEL_9_3); + }else if (_wcsnicmp( strFlag, L"D3D_FEATURE_LEVEL_9_2", MAX_PATH) == 0 ) { + GetDXUTState().SetOverrideForceFeatureLevel(D3D_FEATURE_LEVEL_9_2); + }else if (_wcsnicmp( strFlag, L"D3D_FEATURE_LEVEL_9_1", MAX_PATH) == 0 ) { + GetDXUTState().SetOverrideForceFeatureLevel(D3D_FEATURE_LEVEL_9_1); + } + + + continue; + } + } + + if( DXUTIsNextArg( strCmdLine, L"forceapi" ) ) + { + if( DXUTGetCmdParam( strCmdLine, strFlag ) ) + { + int nAPIVersion = _wtoi( strFlag ); + GetDXUTState().SetOverrideForceAPI( nAPIVersion ); + continue; + } + } + + if( DXUTIsNextArg( strCmdLine, L"adapter" ) ) + { + if( DXUTGetCmdParam( strCmdLine, strFlag ) ) + { + int nAdapter = _wtoi( strFlag ); + GetDXUTState().SetOverrideAdapterOrdinal( nAdapter ); + continue; + } + } + + if( DXUTIsNextArg( strCmdLine, L"windowed" ) ) + { + GetDXUTState().SetOverrideWindowed( true ); + continue; + } + + if( DXUTIsNextArg( strCmdLine, L"output" ) ) + { + if( DXUTGetCmdParam( strCmdLine, strFlag ) ) + { + int Output = _wtoi( strFlag ); + GetDXUTState().SetOverrideOutput( Output ); + continue; + } + } + + if( DXUTIsNextArg( strCmdLine, L"fullscreen" ) ) + { + GetDXUTState().SetOverrideFullScreen( true ); + continue; + } + + if( DXUTIsNextArg( strCmdLine, L"forcehal" ) ) + { + GetDXUTState().SetOverrideForceHAL( true ); + continue; + } + if( DXUTIsNextArg( strCmdLine, L"screenshotexit" ) ) { + if( DXUTGetCmdParam( strCmdLine, strFlag ) ) + { + GetDXUTState().SetExitAfterScreenShot( true ); + GetDXUTState().SetSaveScreenShot( true ); + swprintf_s( GetDXUTState().GetScreenShotName(), 256, L"%s.bmp", strFlag ); + continue; + } + } + if( DXUTIsNextArg( strCmdLine, L"forceref" ) ) + { + GetDXUTState().SetOverrideForceREF( true ); + continue; + } + + if( DXUTIsNextArg( strCmdLine, L"forcevsync" ) ) + { + if( DXUTGetCmdParam( strCmdLine, strFlag ) ) + { + int nOn = _wtoi( strFlag ); + GetDXUTState().SetOverrideForceVsync( nOn ); + continue; + } + } + + if( DXUTIsNextArg( strCmdLine, L"width" ) ) + { + if( DXUTGetCmdParam( strCmdLine, strFlag ) ) + { + int nWidth = _wtoi( strFlag ); + GetDXUTState().SetOverrideWidth( nWidth ); + continue; + } + } + + if( DXUTIsNextArg( strCmdLine, L"height" ) ) + { + if( DXUTGetCmdParam( strCmdLine, strFlag ) ) + { + int nHeight = _wtoi( strFlag ); + GetDXUTState().SetOverrideHeight( nHeight ); + continue; + } + } + + if( DXUTIsNextArg( strCmdLine, L"startx" ) ) + { + if( DXUTGetCmdParam( strCmdLine, strFlag ) ) + { + int nX = _wtoi( strFlag ); + GetDXUTState().SetOverrideStartX( nX ); + continue; + } + } + + if( DXUTIsNextArg( strCmdLine, L"starty" ) ) + { + if( DXUTGetCmdParam( strCmdLine, strFlag ) ) + { + int nY = _wtoi( strFlag ); + GetDXUTState().SetOverrideStartY( nY ); + continue; + } + } + + if( DXUTIsNextArg( strCmdLine, L"constantframetime" ) ) + { + float fTimePerFrame; + if( DXUTGetCmdParam( strCmdLine, strFlag ) ) + fTimePerFrame = ( float )wcstod( strFlag, NULL ); + else + fTimePerFrame = 0.0333f; + GetDXUTState().SetOverrideConstantFrameTime( true ); + GetDXUTState().SetOverrideConstantTimePerFrame( fTimePerFrame ); + DXUTSetConstantFrameTime( true, fTimePerFrame ); + continue; + } + + if( DXUTIsNextArg( strCmdLine, L"quitafterframe" ) ) + { + if( DXUTGetCmdParam( strCmdLine, strFlag ) ) + { + int nFrame = _wtoi( strFlag ); + GetDXUTState().SetOverrideQuitAfterFrame( nFrame ); + continue; + } + } + + if( DXUTIsNextArg( strCmdLine, L"noerrormsgboxes" ) ) + { + GetDXUTState().SetShowMsgBoxOnError( false ); + continue; + } + + if( DXUTIsNextArg( strCmdLine, L"nostats" ) ) + { + GetDXUTState().SetNoStats( true ); + continue; + } + + if( DXUTIsNextArg( strCmdLine, L"relaunchmce" ) ) + { + GetDXUTState().SetOverrideRelaunchMCE( true ); + continue; + } + + if( DXUTIsNextArg( strCmdLine, L"automation" ) ) + { + GetDXUTState().SetAutomation( true ); + continue; + } + } + + // Unrecognized flag + wcscpy_s( strFlag, 256, strCmdLine ); + WCHAR* strSpace = strFlag; + while( *strSpace && ( *strSpace > L' ' ) ) + strSpace++; + *strSpace = 0; + + DXUTOutputDebugString( L"Unrecognized flag: %s", strFlag ); + strCmdLine += wcslen( strFlag ); + } + + LocalFree( pstrArgList ); +} + + +//-------------------------------------------------------------------------------------- +// Helper function for DXUTParseCommandLine +//-------------------------------------------------------------------------------------- +bool DXUTIsNextArg( __inout WCHAR*& strCmdLine, + __inout WCHAR* strArg ) +{ + int nArgLen = ( int )wcslen( strArg ); + int nCmdLen = ( int )wcslen( strCmdLine ); + + if( nCmdLen >= nArgLen && + _wcsnicmp( strCmdLine, strArg, nArgLen ) == 0 && + ( strCmdLine[nArgLen] == 0 || strCmdLine[nArgLen] == L':' ) ) + { + strCmdLine += nArgLen; + return true; + } + + return false; +} + + +//-------------------------------------------------------------------------------------- +// Helper function for DXUTParseCommandLine. Updates strCmdLine and strFlag +// Example: if strCmdLine=="-width:1024 -forceref" +// then after: strCmdLine==" -forceref" and strFlag=="1024" +//-------------------------------------------------------------------------------------- +bool DXUTGetCmdParam( __inout WCHAR*& strCmdLine, + __inout_ecount(MAX_PATH) WCHAR* strFlag ) +{ + if( *strCmdLine == L':' ) + { + strCmdLine++; // Skip ':' + + // Place NULL terminator in strFlag after current token + wcscpy_s( strFlag, 256, strCmdLine ); + WCHAR* strSpace = strFlag; + while( *strSpace && ( *strSpace > L' ' ) ) + strSpace++; + *strSpace = 0; + + // Update strCmdLine + strCmdLine += wcslen( strFlag ); + return true; + } + else + { + strFlag[0] = 0; + return false; + } +} + + +//-------------------------------------------------------------------------------------- +// Creates a window with the specified window title, icon, menu, and +// starting position. If DXUTInit() has not already been called, it will +// call it with the default parameters. Instead of calling this, you can +// call DXUTSetWindow() to use an existing window. +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTCreateWindow( const WCHAR* strWindowTitle, HINSTANCE hInstance, + HICON hIcon, HMENU hMenu, int x, int y ) +{ + HRESULT hr; + + // Not allowed to call this from inside the device callbacks + if( GetDXUTState().GetInsideDeviceCallback() ) + return DXUT_ERR_MSGBOX( L"DXUTCreateWindow", E_FAIL ); + + GetDXUTState().SetWindowCreateCalled( true ); + + if( !GetDXUTState().GetDXUTInited() ) + { + // If DXUTInit() was already called and failed, then fail. + // DXUTInit() must first succeed for this function to succeed + if( GetDXUTState().GetDXUTInitCalled() ) + return E_FAIL; + + // If DXUTInit() hasn't been called, then automatically call it + // with default params + hr = DXUTInit(); + if( FAILED( hr ) ) + return hr; + } + + if( DXUTGetHWNDFocus() == NULL ) + { + if( hInstance == NULL ) + hInstance = ( HINSTANCE )GetModuleHandle( NULL ); + GetDXUTState().SetHInstance( hInstance ); + + WCHAR szExePath[MAX_PATH]; + GetModuleFileName( NULL, szExePath, MAX_PATH ); + if( hIcon == NULL ) // If the icon is NULL, then use the first one found in the exe + hIcon = ExtractIcon( hInstance, szExePath, 0 ); + + // Register the windows class + WNDCLASS wndClass; + wndClass.style = CS_DBLCLKS; + wndClass.lpfnWndProc = DXUTStaticWndProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hInstance = hInstance; + wndClass.hIcon = hIcon; + wndClass.hCursor = LoadCursor( NULL, IDC_ARROW ); + wndClass.hbrBackground = ( HBRUSH )GetStockObject( BLACK_BRUSH ); + wndClass.lpszMenuName = NULL; + wndClass.lpszClassName = L"Direct3DWindowClass"; + + if( !RegisterClass( &wndClass ) ) + { + DWORD dwError = GetLastError(); + if( dwError != ERROR_CLASS_ALREADY_EXISTS ) + return DXUT_ERR_MSGBOX( L"RegisterClass", HRESULT_FROM_WIN32(dwError) ); + } + + // Override the window's initial & size position if there were cmd line args + if( GetDXUTState().GetOverrideStartX() != -1 ) + x = GetDXUTState().GetOverrideStartX(); + if( GetDXUTState().GetOverrideStartY() != -1 ) + y = GetDXUTState().GetOverrideStartY(); + + GetDXUTState().SetWindowCreatedWithDefaultPositions( false ); + if( x == CW_USEDEFAULT && y == CW_USEDEFAULT ) + GetDXUTState().SetWindowCreatedWithDefaultPositions( true ); + + // Find the window's initial size, but it might be changed later + int nDefaultWidth = 640; + int nDefaultHeight = 480; + if( GetDXUTState().GetOverrideWidth() != 0 ) + nDefaultWidth = GetDXUTState().GetOverrideWidth(); + if( GetDXUTState().GetOverrideHeight() != 0 ) + nDefaultHeight = GetDXUTState().GetOverrideHeight(); + + RECT rc; + SetRect( &rc, 0, 0, nDefaultWidth, nDefaultHeight ); + AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, ( hMenu != NULL ) ? true : false ); + + WCHAR* strCachedWindowTitle = GetDXUTState().GetWindowTitle(); + wcscpy_s( strCachedWindowTitle, 256, strWindowTitle ); + + // Create the render window + HWND hWnd = CreateWindow( L"Direct3DWindowClass", strWindowTitle, WS_OVERLAPPEDWINDOW, + x, y, ( rc.right - rc.left ), ( rc.bottom - rc.top ), 0, + hMenu, hInstance, 0 ); + if( hWnd == NULL ) + { + DWORD dwError = GetLastError(); + return DXUT_ERR_MSGBOX( L"CreateWindow", HRESULT_FROM_WIN32(dwError) ); + } + + GetDXUTState().SetWindowCreated( true ); + GetDXUTState().SetHWNDFocus( hWnd ); + GetDXUTState().SetHWNDDeviceFullScreen( hWnd ); + GetDXUTState().SetHWNDDeviceWindowed( hWnd ); + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Sets a previously created window for the framework to use. If DXUTInit() +// has not already been called, it will call it with the default parameters. +// Instead of calling this, you can call DXUTCreateWindow() to create a new window. +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTSetWindow( HWND hWndFocus, HWND hWndDeviceFullScreen, HWND hWndDeviceWindowed, bool bHandleMessages ) +{ + HRESULT hr; + + // Not allowed to call this from inside the device callbacks + if( GetDXUTState().GetInsideDeviceCallback() ) + return DXUT_ERR_MSGBOX( L"DXUTCreateWindow", E_FAIL ); + + GetDXUTState().SetWindowCreateCalled( true ); + + // To avoid confusion, we do not allow any HWND to be NULL here. The + // caller must pass in valid HWND for all three parameters. The same + // HWND may be used for more than one parameter. + if( hWndFocus == NULL || hWndDeviceFullScreen == NULL || hWndDeviceWindowed == NULL ) + return DXUT_ERR_MSGBOX( L"DXUTSetWindow", E_INVALIDARG ); + + // If subclassing the window, set the pointer to the local window procedure + if( bHandleMessages ) + { + // Switch window procedures +#ifdef _WIN64 + LONG_PTR nResult = SetWindowLongPtr( hWndFocus, GWLP_WNDPROC, (LONG_PTR)DXUTStaticWndProc ); +#else + LONG_PTR nResult = SetWindowLongPtr( hWndFocus, GWLP_WNDPROC, ( LONG )( LONG_PTR )DXUTStaticWndProc ); +#endif + + DWORD dwError = GetLastError(); + if( nResult == 0 ) + return DXUT_ERR_MSGBOX( L"SetWindowLongPtr", HRESULT_FROM_WIN32(dwError) ); + } + + if( !GetDXUTState().GetDXUTInited() ) + { + // If DXUTInit() was already called and failed, then fail. + // DXUTInit() must first succeed for this function to succeed + if( GetDXUTState().GetDXUTInitCalled() ) + return E_FAIL; + + // If DXUTInit() hasn't been called, then automatically call it + // with default params + hr = DXUTInit(); + if( FAILED( hr ) ) + return hr; + } + + WCHAR* strCachedWindowTitle = GetDXUTState().GetWindowTitle(); + GetWindowText( hWndFocus, strCachedWindowTitle, 255 ); + strCachedWindowTitle[255] = 0; + + HINSTANCE hInstance = ( HINSTANCE )( LONG_PTR )GetWindowLongPtr( hWndFocus, GWLP_HINSTANCE ); + GetDXUTState().SetHInstance( hInstance ); + GetDXUTState().SetWindowCreatedWithDefaultPositions( false ); + GetDXUTState().SetWindowCreated( true ); + GetDXUTState().SetHWNDFocus( hWndFocus ); + GetDXUTState().SetHWNDDeviceFullScreen( hWndDeviceFullScreen ); + GetDXUTState().SetHWNDDeviceWindowed( hWndDeviceWindowed ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Handles window messages +//-------------------------------------------------------------------------------------- +LRESULT CALLBACK DXUTStaticWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + + // Consolidate the keyboard messages and pass them to the app's keyboard callback + if( uMsg == WM_KEYDOWN || + uMsg == WM_SYSKEYDOWN || + uMsg == WM_KEYUP || + uMsg == WM_SYSKEYUP ) + { + bool bKeyDown = ( uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN ); + DWORD dwMask = ( 1 << 29 ); + bool bAltDown = ( ( lParam & dwMask ) != 0 ); + + bool* bKeys = GetDXUTState().GetKeys(); + bKeys[ ( BYTE )( wParam & 0xFF ) ] = bKeyDown; + + LPDXUTCALLBACKKEYBOARD pCallbackKeyboard = GetDXUTState().GetKeyboardFunc(); + if( pCallbackKeyboard ) + pCallbackKeyboard( ( UINT )wParam, bKeyDown, bAltDown, GetDXUTState().GetKeyboardFuncUserContext() ); + } + + // Consolidate the mouse button messages and pass them to the app's mouse callback + if( uMsg == WM_LBUTTONDOWN || + uMsg == WM_LBUTTONUP || + uMsg == WM_LBUTTONDBLCLK || + uMsg == WM_MBUTTONDOWN || + uMsg == WM_MBUTTONUP || + uMsg == WM_MBUTTONDBLCLK || + uMsg == WM_RBUTTONDOWN || + uMsg == WM_RBUTTONUP || + uMsg == WM_RBUTTONDBLCLK || + uMsg == WM_XBUTTONDOWN || + uMsg == WM_XBUTTONUP || + uMsg == WM_XBUTTONDBLCLK || + uMsg == WM_MOUSEWHEEL || + ( GetDXUTState().GetNotifyOnMouseMove() && uMsg == WM_MOUSEMOVE ) ) + { + int xPos = ( short )LOWORD( lParam ); + int yPos = ( short )HIWORD( lParam ); + + if( uMsg == WM_MOUSEWHEEL ) + { + // WM_MOUSEWHEEL passes screen mouse coords + // so convert them to client coords + POINT pt; + pt.x = xPos; pt.y = yPos; + ScreenToClient( hWnd, &pt ); + xPos = pt.x; yPos = pt.y; + } + + int nMouseWheelDelta = 0; + if( uMsg == WM_MOUSEWHEEL ) + nMouseWheelDelta = ( short )HIWORD( wParam ); + + int nMouseButtonState = LOWORD( wParam ); + bool bLeftButton = ( ( nMouseButtonState & MK_LBUTTON ) != 0 ); + bool bRightButton = ( ( nMouseButtonState & MK_RBUTTON ) != 0 ); + bool bMiddleButton = ( ( nMouseButtonState & MK_MBUTTON ) != 0 ); + bool bSideButton1 = ( ( nMouseButtonState & MK_XBUTTON1 ) != 0 ); + bool bSideButton2 = ( ( nMouseButtonState & MK_XBUTTON2 ) != 0 ); + + bool* bMouseButtons = GetDXUTState().GetMouseButtons(); + bMouseButtons[0] = bLeftButton; + bMouseButtons[1] = bMiddleButton; + bMouseButtons[2] = bRightButton; + bMouseButtons[3] = bSideButton1; + bMouseButtons[4] = bSideButton2; + + LPDXUTCALLBACKMOUSE pCallbackMouse = GetDXUTState().GetMouseFunc(); + if( pCallbackMouse ) + pCallbackMouse( bLeftButton, bRightButton, bMiddleButton, bSideButton1, bSideButton2, nMouseWheelDelta, + xPos, yPos, GetDXUTState().GetMouseFuncUserContext() ); + } + + // Pass all messages to the app's MsgProc callback, and don't + // process further messages if the apps says not to. + LPDXUTCALLBACKMSGPROC pCallbackMsgProc = GetDXUTState().GetWindowMsgFunc(); + if( pCallbackMsgProc ) + { + bool bNoFurtherProcessing = false; + LRESULT nResult = pCallbackMsgProc( hWnd, uMsg, wParam, lParam, &bNoFurtherProcessing, + GetDXUTState().GetWindowMsgFuncUserContext() ); + if( bNoFurtherProcessing ) + return nResult; + } + + switch( uMsg ) + { + case WM_PAINT: + { + + // Handle paint messages when the app is paused + if( DXUTIsRenderingPaused() && + GetDXUTState().GetDeviceObjectsCreated() && GetDXUTState().GetDeviceObjectsReset() ) + { + HRESULT hr; + double fTime = DXUTGetTime(); + float fElapsedTime = DXUTGetElapsedTime(); + + if( DXUTIsCurrentDeviceD3D9() ) + { + IDirect3DDevice9* pd3dDevice = DXUTGetD3D9Device(); + if( pd3dDevice ) + { + LPDXUTCALLBACKD3D9FRAMERENDER pCallbackFrameRender = GetDXUTState().GetD3D9FrameRenderFunc(); + if( pCallbackFrameRender != NULL ) + pCallbackFrameRender( pd3dDevice, fTime, fElapsedTime, + GetDXUTState().GetD3D9FrameRenderFuncUserContext() ); + + hr = pd3dDevice->Present( NULL, NULL, NULL, NULL ); + if( D3DERR_DEVICELOST == hr ) + { + GetDXUTState().SetDeviceLost( true ); + } + else if( D3DERR_DRIVERINTERNALERROR == hr ) + { + // When D3DERR_DRIVERINTERNALERROR is returned from Present(), + // the application can do one of the following: + // + // - End, with the pop-up window saying that the application cannot continue + // because of problems in the display adapter and that the user should + // contact the adapter manufacturer. + // + // - Attempt to restart by calling IDirect3DDevice9::Reset, which is essentially the same + // path as recovering from a lost device. If IDirect3DDevice9::Reset fails with + // D3DERR_DRIVERINTERNALERROR, the application should end immediately with the message + // that the user should contact the adapter manufacturer. + // + // The framework attempts the path of resetting the device + // + GetDXUTState().SetDeviceLost( true ); + } + } + } + else + { + ID3D11Device* pd3dDevice = DXUTGetD3D11Device(); + ID3D11DeviceContext *pDeferred = DXUTGetD3D11DeviceContext(); + if( pd3dDevice ) + { + LPDXUTCALLBACKD3D11FRAMERENDER pCallbackFrameRender = GetDXUTState().GetD3D11FrameRenderFunc(); + if( pCallbackFrameRender != NULL && + !GetDXUTState().GetRenderingOccluded() ) + { + pCallbackFrameRender( pd3dDevice,pDeferred, fTime, fElapsedTime, + GetDXUTState().GetD3D11FrameRenderFuncUserContext() ); + } + + DWORD dwFlags = 0; + if( GetDXUTState().GetRenderingOccluded() ) + dwFlags = DXGI_PRESENT_TEST; + else + dwFlags = GetDXUTState().GetCurrentDeviceSettings()->d3d11.PresentFlags; + + IDXGISwapChain* pSwapChain = DXUTGetDXGISwapChain(); + hr = pSwapChain->Present( 0, GetDXUTState().GetCurrentDeviceSettings()->d3d11.PresentFlags ); + if( DXGI_STATUS_OCCLUDED == hr ) + { + // There is a window covering our entire rendering area. + // Don't render until we're visible again. + GetDXUTState().SetRenderingOccluded( true ); + } + else if( SUCCEEDED( hr ) ) + { + if( GetDXUTState().GetRenderingOccluded() ) + { + // Now that we're no longer occluded + // allow us to render again + GetDXUTState().SetRenderingOccluded( false ); + } + } + } + } + } + break; + } + + case WM_SIZE: + + if( SIZE_MINIMIZED == wParam ) + { + DXUTPause( true, true ); // Pause while we're minimized + + GetDXUTState().SetMinimized( true ); + GetDXUTState().SetMaximized( false ); + } + else + { + RECT rcCurrentClient; + GetClientRect( DXUTGetHWND(), &rcCurrentClient ); + if( rcCurrentClient.top == 0 && rcCurrentClient.bottom == 0 ) + { + // Rapidly clicking the task bar to minimize and restore a window + // can cause a WM_SIZE message with SIZE_RESTORED when + // the window has actually become minimized due to rapid change + // so just ignore this message + } + else if( SIZE_MAXIMIZED == wParam ) + { + if( GetDXUTState().GetMinimized() ) + DXUTPause( false, false ); // Unpause since we're no longer minimized + GetDXUTState().SetMinimized( false ); + GetDXUTState().SetMaximized( true ); + DXUTCheckForWindowSizeChange(); + DXUTCheckForWindowChangingMonitors(); + } + else if( SIZE_RESTORED == wParam ) + { + //DXUTCheckForDXGIFullScreenSwitch(); + if( GetDXUTState().GetMaximized() ) + { + GetDXUTState().SetMaximized( false ); + DXUTCheckForWindowSizeChange(); + DXUTCheckForWindowChangingMonitors(); + } + else if( GetDXUTState().GetMinimized() ) + { + DXUTPause( false, false ); // Unpause since we're no longer minimized + GetDXUTState().SetMinimized( false ); + DXUTCheckForWindowSizeChange(); + DXUTCheckForWindowChangingMonitors(); + } + else if( GetDXUTState().GetInSizeMove() ) + { + // If we're neither maximized nor minimized, the window size + // is changing by the user dragging the window edges. In this + // case, we don't reset the device yet -- we wait until the + // user stops dragging, and a WM_EXITSIZEMOVE message comes. + } + else + { + // This WM_SIZE come from resizing the window via an API like SetWindowPos() so + // resize and reset the device now. + DXUTCheckForWindowSizeChange(); + DXUTCheckForWindowChangingMonitors(); + } + } + } + + break; + + + case WM_GETMINMAXINFO: + ( ( MINMAXINFO* )lParam )->ptMinTrackSize.x = DXUT_MIN_WINDOW_SIZE_X; + ( ( MINMAXINFO* )lParam )->ptMinTrackSize.y = DXUT_MIN_WINDOW_SIZE_Y; + break; + + case WM_ENTERSIZEMOVE: + // Halt frame movement while the app is sizing or moving + DXUTPause( true, true ); + GetDXUTState().SetInSizeMove( true ); + break; + + case WM_EXITSIZEMOVE: + DXUTPause( false, false ); + DXUTCheckForWindowSizeChange(); + DXUTCheckForWindowChangingMonitors(); + GetDXUTState().SetInSizeMove( false ); + break; + + case WM_MOUSEMOVE: + if( DXUTIsActive() && !DXUTIsWindowed() ) + { + if( DXUTIsCurrentDeviceD3D9() ) + { + IDirect3DDevice9* pd3dDevice = DXUTGetD3D9Device(); + if( pd3dDevice ) + { + POINT ptCursor; + GetCursorPos( &ptCursor ); + pd3dDevice->SetCursorPosition( ptCursor.x, ptCursor.y, 0 ); + } + } + else + { + // For D3D11, no processing is necessary. D3D11 cursor + // is handled in the traditional Windows manner. + } + } + break; + + case WM_SETCURSOR: + if( DXUTIsActive() && !DXUTIsWindowed() ) + { + if( DXUTIsCurrentDeviceD3D9() ) + { + IDirect3DDevice9* pd3dDevice = DXUTGetD3D9Device(); + if( pd3dDevice && GetDXUTState().GetShowCursorWhenFullScreen() ) + pd3dDevice->ShowCursor( true ); + } + else + { + if( !GetDXUTState().GetShowCursorWhenFullScreen() ) + SetCursor( NULL ); + } + + return true; // prevent Windows from setting cursor to window class cursor + } + break; + + case WM_ACTIVATEAPP: + if( wParam == TRUE && !DXUTIsActive() ) // Handle only if previously not active + { + GetDXUTState().SetActive( true ); + + // Enable controller rumble & input when activating app + DXUTEnableXInput( true ); + + // The GetMinimizedWhileFullscreen() varible is used instead of !DXUTIsWindowed() + // to handle the rare case toggling to windowed mode while the fullscreen application + // is minimized and thus making the pause count wrong + if( GetDXUTState().GetMinimizedWhileFullscreen() ) + { + if( DXUTIsD3D9( GetDXUTState().GetCurrentDeviceSettings() ) ) + DXUTPause( false, false ); // Unpause since we're no longer minimized + GetDXUTState().SetMinimizedWhileFullscreen( false ); + + if( DXUTIsAppRenderingWithD3D11() ) + { + DXUTToggleFullScreen(); + } + } + + // Upon returning to this app, potentially disable shortcut keys + // (Windows key, accessibility shortcuts) + DXUTAllowShortcutKeys( ( DXUTIsWindowed() ) ? GetDXUTState().GetAllowShortcutKeysWhenWindowed() : + GetDXUTState().GetAllowShortcutKeysWhenFullscreen() ); + + } + else if( wParam == FALSE && DXUTIsActive() ) // Handle only if previously active + { + GetDXUTState().SetActive( false ); + + // Disable any controller rumble & input when de-activating app + DXUTEnableXInput( false ); + + if( !DXUTIsWindowed() ) + { + // Going from full screen to a minimized state + ClipCursor( NULL ); // don't limit the cursor anymore + if( DXUTIsD3D9( GetDXUTState().GetCurrentDeviceSettings() ) ) + DXUTPause( true, true ); // Pause while we're minimized (take care not to pause twice by handling this message twice) + GetDXUTState().SetMinimizedWhileFullscreen( true ); + } + + // Restore shortcut keys (Windows key, accessibility shortcuts) to original state + // + // This is important to call here if the shortcuts are disabled, + // because if this is not done then the Windows key will continue to + // be disabled while this app is running which is very bad. + // If the app crashes, the Windows key will return to normal. + DXUTAllowShortcutKeys( true ); + } + break; + + case WM_ENTERMENULOOP: + // Pause the app when menus are displayed + DXUTPause( true, true ); + break; + + case WM_EXITMENULOOP: + DXUTPause( false, false ); + break; + + case WM_MENUCHAR: + // A menu is active and the user presses a key that does not correspond to any mnemonic or accelerator key + // So just ignore and don't beep + return MAKELRESULT( 0, MNC_CLOSE ); + break; + + case WM_NCHITTEST: + // Prevent the user from selecting the menu in full screen mode + if( !DXUTIsWindowed() ) + return HTCLIENT; + break; + + case WM_POWERBROADCAST: + switch( wParam ) + { +#ifndef PBT_APMQUERYSUSPEND +#define PBT_APMQUERYSUSPEND 0x0000 +#endif + case PBT_APMQUERYSUSPEND: + // At this point, the app should save any data for open + // network connections, files, etc., and prepare to go into + // a suspended mode. The app can use the MsgProc callback + // to handle this if desired. + return true; + +#ifndef PBT_APMRESUMESUSPEND +#define PBT_APMRESUMESUSPEND 0x0007 +#endif + case PBT_APMRESUMESUSPEND: + // At this point, the app should recover any data, network + // connections, files, etc., and resume running from when + // the app was suspended. The app can use the MsgProc callback + // to handle this if desired. + + // QPC may lose consistency when suspending, so reset the timer + // upon resume. + DXUTGetGlobalTimer()->Reset(); + GetDXUTState().SetLastStatsUpdateTime( 0 ); + return true; + } + break; + + case WM_SYSCOMMAND: + // Prevent moving/sizing in full screen mode + switch( ( wParam & 0xFFF0 ) ) + { + case SC_MOVE: + case SC_SIZE: + case SC_MAXIMIZE: + case SC_KEYMENU: + if( !DXUTIsWindowed() ) + return 0; + break; + } + break; + + case WM_SYSKEYDOWN: + { + switch( wParam ) + { + case VK_RETURN: + { + if( GetDXUTState().GetHandleAltEnter() && DXUTIsAppRenderingWithD3D9() ) + { + // Toggle full screen upon alt-enter + DWORD dwMask = ( 1 << 29 ); + if( ( lParam & dwMask ) != 0 ) // Alt is down also + { + // Toggle the full screen/window mode + DXUTPause( true, true ); + DXUTToggleFullScreen(); + DXUTPause( false, false ); + return 0; + } + } + + } + } + break; + } + + case WM_KEYDOWN: + { + switch( wParam ) + { + case VK_ESCAPE: + { + if( GetDXUTState().GetHandleEscape() ) + SendMessage( hWnd, WM_CLOSE, 0, 0 ); + break; + } + + case VK_PAUSE: + { + if( GetDXUTState().GetHandlePause() ) + { + bool bTimePaused = DXUTIsTimePaused(); + bTimePaused = !bTimePaused; + if( bTimePaused ) + DXUTPause( true, false ); + else + DXUTPause( false, false ); + } + break; + } + } + break; + } + + case WM_CLOSE: + { + HMENU hMenu; + hMenu = GetMenu( hWnd ); + if( hMenu != NULL ) + DestroyMenu( hMenu ); + DestroyWindow( hWnd ); + UnregisterClass( L"Direct3DWindowClass", NULL ); + GetDXUTState().SetHWNDFocus( NULL ); + GetDXUTState().SetHWNDDeviceFullScreen( NULL ); + GetDXUTState().SetHWNDDeviceWindowed( NULL ); + return 0; + } + + case WM_DESTROY: + PostQuitMessage( 0 ); + break; + } + + // Don't allow the F10 key to act as a shortcut to the menu bar + // by not passing these messages to the DefWindowProc only when + // there's no menu present + if( !GetDXUTState().GetCallDefWindowProc() || GetDXUTState().GetMenu() == NULL && + ( uMsg == WM_SYSKEYDOWN || uMsg == WM_SYSKEYUP ) && wParam == VK_F10 ) + return 0; + else + return DefWindowProc( hWnd, uMsg, wParam, lParam ); +} + + +//-------------------------------------------------------------------------------------- +// Handles app's message loop and rendering when idle. If DXUTCreateDevice() or DXUTSetD3D*Device() +// has not already been called, it will call DXUTCreateWindow() with the default parameters. +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTMainLoop( HACCEL hAccel ) +{ + HRESULT hr; + + // Not allowed to call this from inside the device callbacks or reenter + if( GetDXUTState().GetInsideDeviceCallback() || GetDXUTState().GetInsideMainloop() ) + { + if( ( GetDXUTState().GetExitCode() == 0 ) || ( GetDXUTState().GetExitCode() == 10 ) ) + GetDXUTState().SetExitCode( 1 ); + return DXUT_ERR_MSGBOX( L"DXUTMainLoop", E_FAIL ); + } + + GetDXUTState().SetInsideMainloop( true ); + + // If DXUTCreateDevice() or DXUTSetD3D*Device() has not already been called, + // then call DXUTCreateDevice() with the default parameters. + if( !GetDXUTState().GetDeviceCreated() ) + { + if( GetDXUTState().GetDeviceCreateCalled() ) + { + if( ( GetDXUTState().GetExitCode() == 0 ) || ( GetDXUTState().GetExitCode() == 10 ) ) + GetDXUTState().SetExitCode( 1 ); + return E_FAIL; // DXUTCreateDevice() must first succeed for this function to succeed + } + + hr = DXUTCreateDevice(D3D_FEATURE_LEVEL_10_0, true, 640, 480); + if( FAILED( hr ) ) + { + if( ( GetDXUTState().GetExitCode() == 0 ) || ( GetDXUTState().GetExitCode() == 10 ) ) + GetDXUTState().SetExitCode( 1 ); + return hr; + } + } + + HWND hWnd = DXUTGetHWND(); + + // DXUTInit() must have been called and succeeded for this function to proceed + // DXUTCreateWindow() or DXUTSetWindow() must have been called and succeeded for this function to proceed + // DXUTCreateDevice() or DXUTCreateDeviceFromSettings() or DXUTSetD3D*Device() must have been called and succeeded for this function to proceed + if( !GetDXUTState().GetDXUTInited() || !GetDXUTState().GetWindowCreated() || !GetDXUTState().GetDeviceCreated() ) + { + if( ( GetDXUTState().GetExitCode() == 0 ) || ( GetDXUTState().GetExitCode() == 10 ) ) + GetDXUTState().SetExitCode( 1 ); + return DXUT_ERR_MSGBOX( L"DXUTMainLoop", E_FAIL ); + } + + // Now we're ready to receive and process Windows messages. + bool bGotMsg; + MSG msg; + msg.message = WM_NULL; + PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE ); + + while( WM_QUIT != msg.message ) + { + // Use PeekMessage() so we can use idle time to render the scene. + bGotMsg = ( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) != 0 ); + + if( bGotMsg ) + { + // Translate and dispatch the message + if( hAccel == NULL || hWnd == NULL || + 0 == TranslateAccelerator( hWnd, hAccel, &msg ) ) + { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + } + else + { + // Render a frame during idle time (no messages are waiting) + DXUTRender3DEnvironment(); + } + } + + // Cleanup the accelerator table + if( hAccel != NULL ) + DestroyAcceleratorTable( hAccel ); + + GetDXUTState().SetInsideMainloop( false ); + + return S_OK; +} + + +//====================================================================================== +//====================================================================================== +// Direct3D section +//====================================================================================== +//====================================================================================== +HRESULT WINAPI DXUTCreateDevice(D3D_FEATURE_LEVEL reqFL, bool bWindowed, int nSuggestedWidth, int nSuggestedHeight) { + HRESULT hr = S_OK; + + + // Not allowed to call this from inside the device callbacks + if( GetDXUTState().GetInsideDeviceCallback() ) + return DXUT_ERR_MSGBOX( L"DXUTCreateWindow", E_FAIL ); + + GetDXUTState().SetDeviceCreateCalled( true ); + + // If DXUTCreateWindow() or DXUTSetWindow() has not already been called, + // then call DXUTCreateWindow() with the default parameters. + if( !GetDXUTState().GetWindowCreated() ) + { + // If DXUTCreateWindow() or DXUTSetWindow() was already called and failed, then fail. + // DXUTCreateWindow() or DXUTSetWindow() must first succeed for this function to succeed + if( GetDXUTState().GetWindowCreateCalled() ) + return E_FAIL; + + // If DXUTCreateWindow() or DXUTSetWindow() hasn't been called, then + // automatically call DXUTCreateWindow() with default params + hr = DXUTCreateWindow(); + if( FAILED( hr ) ) + return hr; + } + + DXUTDeviceSettings deviceSettings ; + DXUTApplyDefaultDeviceSettings(&deviceSettings); + deviceSettings.MinimumFeatureLevel = reqFL; + deviceSettings.d3d11.sd.BufferDesc.Width = nSuggestedWidth; + deviceSettings.d3d11.sd.BufferDesc.Height = nSuggestedHeight; + + deviceSettings.d3d9.pp.BackBufferWidth= nSuggestedWidth; + deviceSettings.d3d9.pp.BackBufferHeight = nSuggestedHeight; + + + //deviceSettings.d3d11.sd.BufferDesc.Width = 480; + + bool bAppSupportsD3D9 = DXUTDoesAppSupportD3D9(); + bool bAppSupportsD3D11 = DXUTDoesAppSupportD3D11(); + + if (bAppSupportsD3D11) { + deviceSettings.ver = DXUT_D3D11_DEVICE; + } + else if (bAppSupportsD3D9) { + deviceSettings.ver = DXUT_D3D9_DEVICE; + } + + DXUTUpdateDeviceSettingsWithOverrides(&deviceSettings); + + + // Change to a Direct3D device created from the new device settings. + // If there is an existing device, then either reset or recreated the scene + hr = DXUTChangeDevice( &deviceSettings, NULL, NULL, false, true ); + + if ( hr == DXUTERR_NODIRECT3D11 && GetDXUTState().GetMessageWhenD3D11NotAvailable() ) { + + OSVERSIONINFOEX osv; + memset( &osv, 0, sizeof(osv) ); + osv.dwOSVersionInfoSize = sizeof(osv); + GetVersionEx( (LPOSVERSIONINFO)&osv ); + + + if ( ( osv.dwMajorVersion > 6 ) + || ( osv.dwMajorVersion == 6 && osv.dwMinorVersion >= 1 ) + || ( osv.dwMajorVersion == 6 && osv.dwMinorVersion == 0 && osv.dwBuildNumber > 6002 ) ) + { + + MessageBox( 0, L"Direct3D 11 components were not found.", L"Error", MB_ICONEXCLAMATION ); + // This should not happen, but is here for completeness as the system could be + // corrupted or some future OS version could pull D3D11.DLL for some reason + } + else if ( osv.dwMajorVersion == 6 && osv.dwMinorVersion == 0 && osv.dwBuildNumber == 6002 ) + { + + MessageBox( 0, L"Direct3D 11 components were not found, but are available for"\ + L" this version of Windows.\n"\ + L"For details see Microsoft Knowledge Base Article #971644\n"\ + L"http://go.microsoft.com/fwlink/?LinkId=160189", L"Error", MB_ICONEXCLAMATION ); + + } + else if ( osv.dwMajorVersion == 6 && osv.dwMinorVersion == 0 ) + { + MessageBox( 0, L"Direct3D 11 components were not found. Please install the latest Service Pack.\n"\ + L"For details see Microsoft Knowledge Base Article #935791\n"\ + L"http://support.microsoft.com/kb/935791/", L"Error", MB_ICONEXCLAMATION ); + + } + else + { + MessageBox( 0, L"Direct3D 11 is not supported on this OS.", L"Error", MB_ICONEXCLAMATION ); + } + + + + } + + + if( FAILED( hr ) ) + return hr; + + return hr; +} + +//-------------------------------------------------------------------------------------- +// Tells the framework to change to a device created from the passed in device settings +// If DXUTCreateWindow() has not already been called, it will call it with the +// default parameters. Instead of calling this, you can call DXUTCreateDevice() +// or DXUTSetD3D*Device() +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTCreateDeviceFromSettings( DXUTDeviceSettings* pDeviceSettings, bool bPreserveInput, + bool bClipWindowToSingleAdapter ) +{ + HRESULT hr; + + GetDXUTState().SetDeviceCreateCalled( true ); + + // If DXUTCreateWindow() or DXUTSetWindow() has not already been called, + // then call DXUTCreateWindow() with the default parameters. + if( !GetDXUTState().GetWindowCreated() ) + { + // If DXUTCreateWindow() or DXUTSetWindow() was already called and failed, then fail. + // DXUTCreateWindow() or DXUTSetWindow() must first succeed for this function to succeed + if( GetDXUTState().GetWindowCreateCalled() ) + return E_FAIL; + + // If DXUTCreateWindow() or DXUTSetWindow() hasn't been called, then + // automatically call DXUTCreateWindow() with default params + hr = DXUTCreateWindow(); + if( FAILED( hr ) ) + return hr; + } + DXUTUpdateDeviceSettingsWithOverrides(pDeviceSettings); + + + // Change to a Direct3D device created from the new device settings. + // If there is an existing device, then either reset or recreate the scene + hr = DXUTChangeDevice( pDeviceSettings, NULL, NULL, false, bClipWindowToSingleAdapter ); + if( FAILED( hr ) ) + return hr; + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// All device changes are sent to this function. It looks at the current +// device (if any) and the new device and determines the best course of action. It +// also remembers and restores the window state if toggling between windowed and fullscreen +// as well as sets the proper window and system state for switching to the new device. +//-------------------------------------------------------------------------------------- +HRESULT DXUTChangeDevice( DXUTDeviceSettings* pNewDeviceSettings, + IDirect3DDevice9* pd3d9DeviceFromApp, + ID3D11Device* pd3d11DeviceFromApp, + bool bForceRecreate, bool bClipWindowToSingleAdapter ) +{ + HRESULT hr = S_OK; + DXUTDeviceSettings* pOldDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); + + if( !pNewDeviceSettings ) + return S_FALSE; + + + + if ( pNewDeviceSettings->ver == DXUT_D3D11_DEVICE ) { + hr = DXUTDelayLoadDXGI(); + } + + + if ( pNewDeviceSettings->ver == DXUT_D3D9_DEVICE || + ( FAILED( hr ) && DXUTDoesAppSupportD3D9() ) ) { + hr = DXUTDelayLoadD3D9(); + pNewDeviceSettings->ver = DXUT_D3D9_DEVICE; + if ( !FAILED( hr ) ) { + pNewDeviceSettings->ver = DXUT_D3D9_DEVICE; + } + } + + if( FAILED( hr ) ) + return hr; + + // Make a copy of the pNewDeviceSettings on the heap + DXUTDeviceSettings* pNewDeviceSettingsOnHeap = new DXUTDeviceSettings; + if( pNewDeviceSettingsOnHeap == NULL ) + return E_OUTOFMEMORY; + memcpy( pNewDeviceSettingsOnHeap, pNewDeviceSettings, sizeof( DXUTDeviceSettings ) ); + pNewDeviceSettings = pNewDeviceSettingsOnHeap; + + + GetDXUTState().SetCurrentDeviceSettings(pNewDeviceSettingsOnHeap); + DXUTSnapDeviceSettingsToEnumDevice(pNewDeviceSettingsOnHeap, false); + + if( FAILED( hr ) ) // the call will fail if no valid devices were found + { + DXUTDisplayErrorMessage( hr ); + return DXUT_ERR( L"DXUTFindValidDeviceSettings", hr ); + } + + // If the ModifyDeviceSettings callback is non-NULL, then call it to let the app + // change the settings or reject the device change by returning false. + LPDXUTCALLBACKMODIFYDEVICESETTINGS pCallbackModifyDeviceSettings = GetDXUTState().GetModifyDeviceSettingsFunc(); + if( pCallbackModifyDeviceSettings && pd3d9DeviceFromApp == NULL ) + { + bool bContinue = pCallbackModifyDeviceSettings( pNewDeviceSettings, + GetDXUTState().GetModifyDeviceSettingsFuncUserContext() ); + if( !bContinue ) + { + // The app rejected the device change by returning false, so just use the current device if there is one. + if( pOldDeviceSettings == NULL ) + DXUTDisplayErrorMessage( DXUTERR_NOCOMPATIBLEDEVICES ); + SAFE_DELETE( pNewDeviceSettings ); + return E_ABORT; + } + if( GetDXUTState().GetD3D9() == NULL && GetDXUTState().GetDXGIFactory() == NULL ) // if DXUTShutdown() was called in the modify callback, just return + { + SAFE_DELETE( pNewDeviceSettings ); + return S_FALSE; + } + DXUTSnapDeviceSettingsToEnumDevice(pNewDeviceSettingsOnHeap, false); // modify the app specified settings to the closed enumerated settigns + + if( FAILED( hr ) ) // the call will fail if no valid devices were found + { + DXUTDisplayErrorMessage( hr ); + return DXUT_ERR( L"DXUTFindValidDeviceSettings", hr ); + } + + } + + GetDXUTState().SetCurrentDeviceSettings( pNewDeviceSettingsOnHeap ); + + DXUTPause( true, true ); + + // When a WM_SIZE message is received, it calls DXUTCheckForWindowSizeChange(). + // A WM_SIZE message might be sent when adjusting the window, so tell + // DXUTCheckForWindowSizeChange() to ignore size changes temporarily + if( DXUTIsCurrentDeviceD3D9() ) + GetDXUTState().SetIgnoreSizeChange( true ); + + + // Take note if the backbuffer width & height are 0 now as they will change after pd3dDevice->Reset() + bool bKeepCurrentWindowSize = false; + if( DXUTGetBackBufferWidthFromDS( pNewDeviceSettings ) == 0 && + DXUTGetBackBufferHeightFromDS( pNewDeviceSettings ) == 0 ) + bKeepCurrentWindowSize = true; + + ////////////////////////// + // Before reset + ///////////////////////// + + // If we are using D3D9, adjust window style when switching from windowed to fullscreen and + // vice versa. Note that this is not necessary in D3D11 because DXGI handles this. If both + // DXUT and DXGI handle this, incorrect behavior would result. + if( DXUTIsCurrentDeviceD3D9() ) + { + if( DXUTGetIsWindowedFromDS( pNewDeviceSettings ) ) + { + // Going to windowed mode + + if( pOldDeviceSettings && !DXUTGetIsWindowedFromDS( pOldDeviceSettings ) ) + { + // Going from fullscreen -> windowed + GetDXUTState().SetFullScreenBackBufferWidthAtModeChange( DXUTGetBackBufferWidthFromDS( + pOldDeviceSettings ) ); + GetDXUTState().SetFullScreenBackBufferHeightAtModeChange( DXUTGetBackBufferHeightFromDS( + pOldDeviceSettings ) ); + + // Restore windowed mode style + SetWindowLong( DXUTGetHWNDDeviceWindowed(), GWL_STYLE, GetDXUTState().GetWindowedStyleAtModeChange() ); + } + + // If different device windows are used for windowed mode and fullscreen mode, + // hide the fullscreen window so that it doesn't obscure the screen. + if( DXUTGetHWNDDeviceFullScreen() != DXUTGetHWNDDeviceWindowed() ) + ShowWindow( DXUTGetHWNDDeviceFullScreen(), SW_HIDE ); + + // If using the same window for windowed and fullscreen mode, reattach menu if one exists + if( DXUTGetHWNDDeviceFullScreen() == DXUTGetHWNDDeviceWindowed() ) + { + if( GetDXUTState().GetMenu() != NULL ) + SetMenu( DXUTGetHWNDDeviceWindowed(), GetDXUTState().GetMenu() ); + } + } + else + { + // Going to fullscreen mode + + if( pOldDeviceSettings == NULL || ( pOldDeviceSettings && DXUTGetIsWindowedFromDS( pOldDeviceSettings ) ) ) + { + // Transistioning to full screen mode from a standard window so + // save current window position/size/style now in case the user toggles to windowed mode later + WINDOWPLACEMENT* pwp = GetDXUTState().GetWindowedPlacement(); + ZeroMemory( pwp, sizeof( WINDOWPLACEMENT ) ); + pwp->length = sizeof( WINDOWPLACEMENT ); + GetWindowPlacement( DXUTGetHWNDDeviceWindowed(), pwp ); + bool bIsTopmost = ( ( GetWindowLong( DXUTGetHWNDDeviceWindowed(), + GWL_EXSTYLE ) & WS_EX_TOPMOST ) != 0 ); + GetDXUTState().SetTopmostWhileWindowed( bIsTopmost ); + DWORD dwStyle = GetWindowLong( DXUTGetHWNDDeviceWindowed(), GWL_STYLE ); + dwStyle &= ~WS_MAXIMIZE & ~WS_MINIMIZE; // remove minimize/maximize style + GetDXUTState().SetWindowedStyleAtModeChange( dwStyle ); + if( pOldDeviceSettings ) + { + GetDXUTState().SetWindowBackBufferWidthAtModeChange( DXUTGetBackBufferWidthFromDS( + pOldDeviceSettings ) ); + GetDXUTState().SetWindowBackBufferHeightAtModeChange( DXUTGetBackBufferHeightFromDS( + pOldDeviceSettings ) ); + } + } + + // Hide the window to avoid animation of blank windows + ShowWindow( DXUTGetHWNDDeviceFullScreen(), SW_HIDE ); + + // Set FS window style + SetWindowLong( DXUTGetHWNDDeviceFullScreen(), GWL_STYLE, WS_POPUP | WS_SYSMENU ); + + // If using the same window for windowed and fullscreen mode, save and remove menu + if( DXUTGetHWNDDeviceFullScreen() == DXUTGetHWNDDeviceWindowed() ) + { + HMENU hMenu = GetMenu( DXUTGetHWNDDeviceFullScreen() ); + GetDXUTState().SetMenu( hMenu ); + SetMenu( DXUTGetHWNDDeviceFullScreen(), NULL ); + } + + WINDOWPLACEMENT wpFullscreen; + ZeroMemory( &wpFullscreen, sizeof( WINDOWPLACEMENT ) ); + wpFullscreen.length = sizeof( WINDOWPLACEMENT ); + GetWindowPlacement( DXUTGetHWNDDeviceFullScreen(), &wpFullscreen ); + if( ( wpFullscreen.flags & WPF_RESTORETOMAXIMIZED ) != 0 ) + { + // Restore the window to normal if the window was maximized then minimized. This causes the + // WPF_RESTORETOMAXIMIZED flag to be set which will cause SW_RESTORE to restore the + // window from minimized to maxmized which isn't what we want + wpFullscreen.flags &= ~WPF_RESTORETOMAXIMIZED; + wpFullscreen.showCmd = SW_RESTORE; + SetWindowPlacement( DXUTGetHWNDDeviceFullScreen(), &wpFullscreen ); + } + } + } + else + { + if( DXUTGetIsWindowedFromDS( pNewDeviceSettings ) ) + { + // Going to windowed mode + if( pOldDeviceSettings && !DXUTGetIsWindowedFromDS( pOldDeviceSettings ) ) + { + // Going from fullscreen -> windowed + GetDXUTState().SetFullScreenBackBufferWidthAtModeChange( DXUTGetBackBufferWidthFromDS( + pOldDeviceSettings ) ); + GetDXUTState().SetFullScreenBackBufferHeightAtModeChange( DXUTGetBackBufferHeightFromDS( + pOldDeviceSettings ) ); + //DXGI should handle this, but in the case where switching from d3d9 full screen to windowed d3d11 it does not. + SetWindowLong( DXUTGetHWNDDeviceWindowed(), GWL_STYLE, GetDXUTState().GetWindowedStyleAtModeChange() ); + + } + } + else + { + // Going to fullscreen mode + if( pOldDeviceSettings == NULL || ( pOldDeviceSettings && DXUTGetIsWindowedFromDS( pOldDeviceSettings ) ) ) + { + // Transistioning to full screen mode from a standard window so + if( pOldDeviceSettings ) + { + GetDXUTState().SetWindowBackBufferWidthAtModeChange( DXUTGetBackBufferWidthFromDS( + pOldDeviceSettings ) ); + GetDXUTState().SetWindowBackBufferHeightAtModeChange( DXUTGetBackBufferHeightFromDS( + pOldDeviceSettings ) ); + } + } + } + } + + if( pOldDeviceSettings ) + DXUTCleanup3DEnvironment( false ); + + // Create the D3D device and call the app's device callbacks + if( DXUTIsD3D9( pNewDeviceSettings ) ) { + hr = DXUTCreate3DEnvironment9( pd3d9DeviceFromApp ); + } + else { + hr = DXUTCreate3DEnvironment11( pd3d11DeviceFromApp ); + } + if( FAILED( hr ) ) + { + SAFE_DELETE( pOldDeviceSettings ); + DXUTCleanup3DEnvironment( true ); + DXUTDisplayErrorMessage( hr ); + DXUTPause( false, false ); + GetDXUTState().SetIgnoreSizeChange( false ); + return hr; + } + + // Enable/disable StickKeys shortcut, ToggleKeys shortcut, FilterKeys shortcut, and Windows key + // to prevent accidental task switching + DXUTAllowShortcutKeys( ( DXUTGetIsWindowedFromDS( pNewDeviceSettings ) ) ? + GetDXUTState().GetAllowShortcutKeysWhenWindowed() : + GetDXUTState().GetAllowShortcutKeysWhenFullscreen() ); + + HMONITOR hAdapterMonitor = DXUTGetMonitorFromAdapter( pNewDeviceSettings ); + GetDXUTState().SetAdapterMonitor( hAdapterMonitor ); + + // Update the device stats text + DXUTUpdateStaticFrameStats(); + + if( pOldDeviceSettings && !DXUTGetIsWindowedFromDS( pOldDeviceSettings ) && + DXUTGetIsWindowedFromDS( pNewDeviceSettings ) ) + { + // Going from fullscreen -> windowed + + // Restore the show state, and positions/size of the window to what it was + // It is important to adjust the window size + // after resetting the device rather than beforehand to ensure + // that the monitor resolution is correct and does not limit the size of the new window. + WINDOWPLACEMENT* pwp = GetDXUTState().GetWindowedPlacement(); + SetWindowPlacement( DXUTGetHWNDDeviceWindowed(), pwp ); + + // Also restore the z-order of window to previous state + HWND hWndInsertAfter = GetDXUTState().GetTopmostWhileWindowed() ? HWND_TOPMOST : HWND_NOTOPMOST; + SetWindowPos( DXUTGetHWNDDeviceWindowed(), hWndInsertAfter, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE ); + } + + // Check to see if the window needs to be resized. + // Handle cases where the window is minimized and maxmimized as well. + + bool bNeedToResize = false; + if( DXUTGetIsWindowedFromDS( pNewDeviceSettings ) && // only resize if in windowed mode + !bKeepCurrentWindowSize ) // only resize if pp.BackbufferWidth/Height were not 0 + { + UINT nClientWidth; + UINT nClientHeight; + if( IsIconic( DXUTGetHWNDDeviceWindowed() ) ) + { + // Window is currently minimized. To tell if it needs to resize, + // get the client rect of window when its restored the + // hard way using GetWindowPlacement() + WINDOWPLACEMENT wp; + ZeroMemory( &wp, sizeof( WINDOWPLACEMENT ) ); + wp.length = sizeof( WINDOWPLACEMENT ); + GetWindowPlacement( DXUTGetHWNDDeviceWindowed(), &wp ); + + if( ( wp.flags & WPF_RESTORETOMAXIMIZED ) != 0 && wp.showCmd == SW_SHOWMINIMIZED ) + { + // WPF_RESTORETOMAXIMIZED means that when the window is restored it will + // be maximized. So maximize the window temporarily to get the client rect + // when the window is maximized. GetSystemMetrics( SM_CXMAXIMIZED ) will give this + // information if the window is on the primary but this will work on multimon. + ShowWindow( DXUTGetHWNDDeviceWindowed(), SW_RESTORE ); + RECT rcClient; + GetClientRect( DXUTGetHWNDDeviceWindowed(), &rcClient ); + nClientWidth = ( UINT )( rcClient.right - rcClient.left ); + nClientHeight = ( UINT )( rcClient.bottom - rcClient.top ); + ShowWindow( DXUTGetHWNDDeviceWindowed(), SW_MINIMIZE ); + } + else + { + // Use wp.rcNormalPosition to get the client rect, but wp.rcNormalPosition + // includes the window frame so subtract it + RECT rcFrame = {0}; + AdjustWindowRect( &rcFrame, GetDXUTState().GetWindowedStyleAtModeChange(), GetDXUTState().GetMenu() != NULL ); + LONG nFrameWidth = rcFrame.right - rcFrame.left; + LONG nFrameHeight = rcFrame.bottom - rcFrame.top; + nClientWidth = ( UINT )( wp.rcNormalPosition.right - wp.rcNormalPosition.left - nFrameWidth ); + nClientHeight = ( UINT )( wp.rcNormalPosition.bottom - wp.rcNormalPosition.top - nFrameHeight ); + } + } + else + { + // Window is restored or maximized so just get its client rect + RECT rcClient; + GetClientRect( DXUTGetHWNDDeviceWindowed(), &rcClient ); + nClientWidth = ( UINT )( rcClient.right - rcClient.left ); + nClientHeight = ( UINT )( rcClient.bottom - rcClient.top ); + } + + // Now that we know the client rect, compare it against the back buffer size + // to see if the client rect is already the right size + if( nClientWidth != DXUTGetBackBufferWidthFromDS( pNewDeviceSettings ) || + nClientHeight != DXUTGetBackBufferHeightFromDS( pNewDeviceSettings ) ) + { + bNeedToResize = true; + } + + if( bClipWindowToSingleAdapter && !IsIconic( DXUTGetHWNDDeviceWindowed() ) ) + { + // Get the rect of the monitor attached to the adapter + MONITORINFO miAdapter; + miAdapter.cbSize = sizeof( MONITORINFO ); + HMONITOR hAdapterMonitor = DXUTGetMonitorFromAdapter( pNewDeviceSettings ); + DXUTGetMonitorInfo( hAdapterMonitor, &miAdapter ); + HMONITOR hWindowMonitor = DXUTMonitorFromWindow( DXUTGetHWND(), MONITOR_DEFAULTTOPRIMARY ); + + // Get the rect of the window + RECT rcWindow; + GetWindowRect( DXUTGetHWNDDeviceWindowed(), &rcWindow ); + + // Check if the window rect is fully inside the adapter's vitural screen rect + if( ( rcWindow.left < miAdapter.rcWork.left || + rcWindow.right > miAdapter.rcWork.right || + rcWindow.top < miAdapter.rcWork.top || + rcWindow.bottom > miAdapter.rcWork.bottom ) ) + { + if( hWindowMonitor == hAdapterMonitor && IsZoomed( DXUTGetHWNDDeviceWindowed() ) ) + { + // If the window is maximized and on the same monitor as the adapter, then + // no need to clip to single adapter as the window is already clipped + // even though the rcWindow rect is outside of the miAdapter.rcWork + } + else + { + bNeedToResize = true; + } + } + } + } + + // Only resize window if needed + + if( bNeedToResize ) + { + // Need to resize, so if window is maximized or minimized then restore the window + if( IsIconic( DXUTGetHWNDDeviceWindowed() ) ) + ShowWindow( DXUTGetHWNDDeviceWindowed(), SW_RESTORE ); + if( IsZoomed( DXUTGetHWNDDeviceWindowed() ) ) // doing the IsIconic() check first also handles the WPF_RESTORETOMAXIMIZED case + ShowWindow( DXUTGetHWNDDeviceWindowed(), SW_RESTORE ); + + if( bClipWindowToSingleAdapter ) + { + // Get the rect of the monitor attached to the adapter + MONITORINFO miAdapter; + miAdapter.cbSize = sizeof( MONITORINFO ); + HMONITOR hAdapterMonitor = DXUTGetMonitorFromAdapter( pNewDeviceSettings ); + DXUTGetMonitorInfo( hAdapterMonitor, &miAdapter ); + + // Get the rect of the monitor attached to the window + MONITORINFO miWindow; + miWindow.cbSize = sizeof( MONITORINFO ); + DXUTGetMonitorInfo( DXUTMonitorFromWindow( DXUTGetHWND(), MONITOR_DEFAULTTOPRIMARY ), &miWindow ); + + // Do something reasonable if the BackBuffer size is greater than the monitor size + int nAdapterMonitorWidth = miAdapter.rcWork.right - miAdapter.rcWork.left; + int nAdapterMonitorHeight = miAdapter.rcWork.bottom - miAdapter.rcWork.top; + + int nClientWidth = DXUTGetBackBufferWidthFromDS( pNewDeviceSettings ); + int nClientHeight = DXUTGetBackBufferHeightFromDS( pNewDeviceSettings ); + + // Get the rect of the window + RECT rcWindow; + GetWindowRect( DXUTGetHWNDDeviceWindowed(), &rcWindow ); + + // Make a window rect with a client rect that is the same size as the backbuffer + RECT rcResizedWindow; + rcResizedWindow.left = 0; + rcResizedWindow.right = nClientWidth; + rcResizedWindow.top = 0; + rcResizedWindow.bottom = nClientHeight; + AdjustWindowRect( &rcResizedWindow, GetWindowLong( DXUTGetHWNDDeviceWindowed(), GWL_STYLE ), + GetDXUTState().GetMenu() != NULL ); + + int nWindowWidth = rcResizedWindow.right - rcResizedWindow.left; + int nWindowHeight = rcResizedWindow.bottom - rcResizedWindow.top; + + if( nWindowWidth > nAdapterMonitorWidth ) + nWindowWidth = nAdapterMonitorWidth; + if( nWindowHeight > nAdapterMonitorHeight ) + nWindowHeight = nAdapterMonitorHeight; + + if( rcResizedWindow.left < miAdapter.rcWork.left || + rcResizedWindow.top < miAdapter.rcWork.top || + rcResizedWindow.right > miAdapter.rcWork.right || + rcResizedWindow.bottom > miAdapter.rcWork.bottom ) + { + int nWindowOffsetX = ( nAdapterMonitorWidth - nWindowWidth ) / 2; + int nWindowOffsetY = ( nAdapterMonitorHeight - nWindowHeight ) / 2; + + rcResizedWindow.left = miAdapter.rcWork.left + nWindowOffsetX; + rcResizedWindow.top = miAdapter.rcWork.top + nWindowOffsetY; + rcResizedWindow.right = miAdapter.rcWork.left + nWindowOffsetX + nWindowWidth; + rcResizedWindow.bottom = miAdapter.rcWork.top + nWindowOffsetY + nWindowHeight; + } + + // Resize the window. It is important to adjust the window size + // after resetting the device rather than beforehand to ensure + // that the monitor resolution is correct and does not limit the size of the new window. + SetWindowPos( DXUTGetHWNDDeviceWindowed(), 0, rcResizedWindow.left, rcResizedWindow.top, nWindowWidth, + nWindowHeight, SWP_NOZORDER ); + } + else + { + // Make a window rect with a client rect that is the same size as the backbuffer + RECT rcWindow = {0}; + rcWindow.right = (long)( DXUTGetBackBufferWidthFromDS(pNewDeviceSettings) ); + rcWindow.bottom = (long)( DXUTGetBackBufferHeightFromDS(pNewDeviceSettings) ); + AdjustWindowRect( &rcWindow, GetWindowLong( DXUTGetHWNDDeviceWindowed(), GWL_STYLE ), GetDXUTState().GetMenu() != NULL ); + + // Resize the window. It is important to adjust the window size + // after resetting the device rather than beforehand to ensure + // that the monitor resolution is correct and does not limit the size of the new window. + int cx = ( int )( rcWindow.right - rcWindow.left ); + int cy = ( int )( rcWindow.bottom - rcWindow.top ); + SetWindowPos( DXUTGetHWNDDeviceWindowed(), 0, 0, 0, cx, cy, SWP_NOZORDER | SWP_NOMOVE ); + } + + // Its possible that the new window size is not what we asked for. + // No window can be sized larger than the desktop, so see if the Windows OS resized the + // window to something smaller to fit on the desktop. Also if WM_GETMINMAXINFO + // will put a limit on the smallest/largest window size. + RECT rcClient; + GetClientRect( DXUTGetHWNDDeviceWindowed(), &rcClient ); + UINT nClientWidth = ( UINT )( rcClient.right - rcClient.left ); + UINT nClientHeight = ( UINT )( rcClient.bottom - rcClient.top ); + if( nClientWidth != DXUTGetBackBufferWidthFromDS( pNewDeviceSettings ) || + nClientHeight != DXUTGetBackBufferHeightFromDS( pNewDeviceSettings ) ) + { + // If its different, then resize the backbuffer again. This time create a backbuffer that matches the + // client rect of the current window w/o resizing the window. + DXUTDeviceSettings deviceSettings = DXUTGetDeviceSettings(); + if( DXUTIsD3D9( &deviceSettings ) ) deviceSettings.d3d9.pp.BackBufferWidth = 0; else deviceSettings.d3d11.sd.BufferDesc.Width = 0; + if( DXUTIsD3D9( &deviceSettings ) ) deviceSettings.d3d9.pp.BackBufferHeight = 0; else deviceSettings.d3d11.sd.BufferDesc.Height = 0; + + hr = DXUTChangeDevice( &deviceSettings, NULL, NULL, false, bClipWindowToSingleAdapter ); + if( FAILED( hr ) ) + { + SAFE_DELETE( pOldDeviceSettings ); + DXUTCleanup3DEnvironment( true ); + DXUTPause( false, false ); + GetDXUTState().SetIgnoreSizeChange( false ); + return hr; + } + } + } + + //if (DXUTGetIsWindowedFromDS( pNewDeviceSettings )) { + // RECT rcFrame = {0}; + // AdjustWindowRect( &rcFrame, GetDXUTState().GetWindowedStyleAtModeChange(), GetDXUTState().GetMenu() != NULL ); + // } + + // Make the window visible + if( !IsWindowVisible( DXUTGetHWND() ) ) + ShowWindow( DXUTGetHWND(), SW_SHOW ); + + // Ensure that the display doesn't power down when fullscreen but does when windowed + if( !DXUTIsWindowed() ) + SetThreadExecutionState( ES_DISPLAY_REQUIRED | ES_CONTINUOUS ); + else + SetThreadExecutionState( ES_CONTINUOUS ); + + SAFE_DELETE( pOldDeviceSettings ); + GetDXUTState().SetIgnoreSizeChange( false ); + DXUTPause( false, false ); + GetDXUTState().SetDeviceCreated( true ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Creates a DXGI factory object if one has not already been created +//-------------------------------------------------------------------------------------- +HRESULT DXUTDelayLoadDXGI() +{ + IDXGIFactory1* pDXGIFactory = GetDXUTState().GetDXGIFactory(); + if( pDXGIFactory == NULL ) + { + DXUT_Dynamic_CreateDXGIFactory1( __uuidof( IDXGIFactory1 ), ( LPVOID* )&pDXGIFactory ); + GetDXUTState().SetDXGIFactory( pDXGIFactory ); + if( pDXGIFactory == NULL ) + { + // If still NULL, then DXGI is not availible + GetDXUTState().SetD3D11Available( false ); + return DXUTERR_NODIRECT3D11; + } + + // TODO: check for D3D11 support + GetDXUTState().SetD3D11Available( true ); + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Creates a Direct3D object if one has not already been created +//-------------------------------------------------------------------------------------- +HRESULT DXUTDelayLoadD3D9() +{ + IDirect3D9* pD3D = GetDXUTState().GetD3D9(); + if( pD3D == NULL ) + { + // This may fail if Direct3D 9 isn't installed + // This may also fail if the Direct3D headers are somehow out of sync with the installed Direct3D DLLs + pD3D = DXUT_Dynamic_Direct3DCreate9( D3D_SDK_VERSION ); + if( pD3D == NULL ) + { + // If still NULL, then D3D9 is not availible + return DXUTERR_NODIRECT3D; + } + + GetDXUTState().SetD3D9( pD3D ); + } + + return S_OK; +} + + + +//-------------------------------------------------------------------------------------- +// Updates the device settings with default values.. +//-------------------------------------------------------------------------------------- +void DXUTUpdateDeviceSettingsWithOverrides( DXUTDeviceSettings* pDeviceSettings ) +{ + // Override with settings from the command line + if( GetDXUTState().GetOverrideWidth() != 0 ) + { + pDeviceSettings->d3d9.pp.BackBufferWidth = GetDXUTState().GetOverrideWidth(); + pDeviceSettings->d3d11.sd.BufferDesc.Width = GetDXUTState().GetOverrideWidth(); + } + if( GetDXUTState().GetOverrideHeight() != 0 ) + { + pDeviceSettings->d3d9.pp.BackBufferHeight = GetDXUTState().GetOverrideHeight(); + pDeviceSettings->d3d11.sd.BufferDesc.Height = GetDXUTState().GetOverrideHeight(); + } + + if( GetDXUTState().GetOverrideAdapterOrdinal() != -1 ) + { + pDeviceSettings->d3d9.AdapterOrdinal = GetDXUTState().GetOverrideAdapterOrdinal(); + pDeviceSettings->d3d11.AdapterOrdinal = GetDXUTState().GetOverrideAdapterOrdinal(); + } + + if( GetDXUTState().GetOverrideFullScreen() ) + { + pDeviceSettings->d3d9.pp.Windowed = FALSE; + pDeviceSettings->d3d11.sd.Windowed = FALSE; + } + + if( GetDXUTState().GetOverrideWindowed() ) { + pDeviceSettings->d3d9.pp.Windowed = TRUE; + pDeviceSettings->d3d11.sd.Windowed = TRUE; + } + + if( GetDXUTState().GetOverrideForceHAL() ) + { + pDeviceSettings->d3d9.DeviceType = D3DDEVTYPE_HAL; + pDeviceSettings->d3d11.DriverType = D3D_DRIVER_TYPE_HARDWARE; + } + + if( GetDXUTState().GetOverrideForceREF() ) + { + pDeviceSettings->d3d9.DeviceType = D3DDEVTYPE_REF; + pDeviceSettings->d3d11.DriverType = D3D_DRIVER_TYPE_REFERENCE; + } + + if( GetDXUTState().GetOverrideForceVsync() == 0 ) + { + pDeviceSettings->d3d9.pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + pDeviceSettings->d3d11.SyncInterval = 0; + } + else if( GetDXUTState().GetOverrideForceVsync() == 1 ) + { + pDeviceSettings->d3d9.pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + pDeviceSettings->d3d11.SyncInterval = 1; + } + + if( GetDXUTState().GetOverrideForceAPI() != -1 ) + { + if( GetDXUTState().GetOverrideForceAPI() == 9 ) + { + pDeviceSettings->ver = DXUT_D3D9_DEVICE; + } + else if( GetDXUTState().GetOverrideForceAPI() == 11 ) + { + pDeviceSettings->ver = DXUT_D3D11_DEVICE; + } + } + + if (GetDXUTState().GetOverrideForceFeatureLevel() != 0) { + pDeviceSettings->d3d11.DeviceFeatureLevel = (D3D_FEATURE_LEVEL)GetDXUTState().GetOverrideForceFeatureLevel(); + } +} + + +//-------------------------------------------------------------------------------------- +// Allows the app to explictly state if it supports D3D9 or D3D11. Typically +// calling this is not needed as DXUT will auto-detect this based on the callbacks set. +//-------------------------------------------------------------------------------------- +void WINAPI DXUTSetD3DVersionSupport( bool bAppCanUseD3D9, bool bAppCanUseD3D11 ) +{ + GetDXUTState().SetUseD3DVersionOverride( true ); + GetDXUTState().SetAppSupportsD3D9Override( bAppCanUseD3D9 ); + GetDXUTState().SetAppSupportsD3D11Override( bAppCanUseD3D11 ); +} + + +//-------------------------------------------------------------------------------------- +// Returns true if app has registered any D3D9 callbacks or +// used the DXUTSetD3DVersionSupport API and passed true for bAppCanUseD3D9 +//-------------------------------------------------------------------------------------- +bool WINAPI DXUTDoesAppSupportD3D9() +{ + if( GetDXUTState().GetUseD3DVersionOverride() ) + return GetDXUTState().GetAppSupportsD3D9Override(); + else + return GetDXUTState().GetIsD3D9DeviceAcceptableFunc() || + GetDXUTState().GetD3D9DeviceCreatedFunc() || + GetDXUTState().GetD3D9DeviceResetFunc() || + GetDXUTState().GetD3D9DeviceLostFunc() || + GetDXUTState().GetD3D9DeviceDestroyedFunc() || + GetDXUTState().GetD3D9FrameRenderFunc(); +} + + +//-------------------------------------------------------------------------------------- +// Returns true if app has registered any D3D11 callbacks or +// used the DXUTSetD3DVersionSupport API and passed true for bAppCanUseD3D11 +//-------------------------------------------------------------------------------------- +bool WINAPI DXUTDoesAppSupportD3D11() +{ + if( GetDXUTState().GetUseD3DVersionOverride() ) + return GetDXUTState().GetAppSupportsD3D11Override(); + else + return GetDXUTState().GetIsD3D11DeviceAcceptableFunc() || + GetDXUTState().GetD3D11DeviceCreatedFunc() || + GetDXUTState().GetD3D11SwapChainResizedFunc() || + GetDXUTState().GetD3D11FrameRenderFunc() || + GetDXUTState().GetD3D11SwapChainReleasingFunc() || + GetDXUTState().GetD3D11DeviceDestroyedFunc(); +} + + +//====================================================================================== +//====================================================================================== +// Direct3D 9 section +//====================================================================================== +//====================================================================================== + + +//-------------------------------------------------------------------------------------- +// Passes a previously created Direct3D9 device for use by the framework. +// If DXUTCreateWindow() has not already been called, it will call it with the +// default parameters. Instead of calling this, you can call DXUTCreateDevice() or +// DXUTCreateDeviceFromSettings() +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTSetD3D9Device( IDirect3DDevice9* pd3dDevice ) +{ + HRESULT hr; + + if( pd3dDevice == NULL ) + return DXUT_ERR_MSGBOX( L"DXUTSetD3D9Device", E_INVALIDARG ); + + // Not allowed to call this from inside the device callbacks + if( GetDXUTState().GetInsideDeviceCallback() ) + return DXUT_ERR_MSGBOX( L"DXUTSetD3D9Device", E_FAIL ); + + GetDXUTState().SetDeviceCreateCalled( true ); + + // If DXUTCreateWindow() or DXUTSetWindow() has not already been called, + // then call DXUTCreateWindow() with the default parameters. + if( !GetDXUTState().GetWindowCreated() ) + { + // If DXUTCreateWindow() or DXUTSetWindow() was already called and failed, then fail. + // DXUTCreateWindow() or DXUTSetWindow() must first succeed for this function to succeed + if( GetDXUTState().GetWindowCreateCalled() ) + return E_FAIL; + + // If DXUTCreateWindow() or DXUTSetWindow() hasn't been called, then + // automatically call DXUTCreateWindow() with default params + hr = DXUTCreateWindow(); + if( FAILED( hr ) ) + return hr; + } + + DXUTDeviceSettings DeviceSettings; + ZeroMemory( &DeviceSettings, sizeof( DXUTDeviceSettings ) ); + DeviceSettings.ver = DXUT_D3D9_DEVICE; + + // Get the present params from the swap chain + IDirect3DSurface9* pBackBuffer = NULL; + hr = pd3dDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer ); + if( SUCCEEDED( hr ) ) + { + IDirect3DSwapChain9* pSwapChain = NULL; + hr = pBackBuffer->GetContainer( IID_IDirect3DSwapChain9, ( void** )&pSwapChain ); + if( SUCCEEDED( hr ) ) + { + pSwapChain->GetPresentParameters( &DeviceSettings.d3d9.pp ); + SAFE_RELEASE( pSwapChain ); + } + + SAFE_RELEASE( pBackBuffer ); + } + + D3DDEVICE_CREATION_PARAMETERS d3dCreationParams; + pd3dDevice->GetCreationParameters( &d3dCreationParams ); + + // Fill out the rest of the device settings struct + DeviceSettings.d3d9.AdapterOrdinal = d3dCreationParams.AdapterOrdinal; + DeviceSettings.d3d9.DeviceType = d3dCreationParams.DeviceType; + DXUTFindD3D9AdapterFormat( DeviceSettings.d3d9.AdapterOrdinal, DeviceSettings.d3d9.DeviceType, + DeviceSettings.d3d9.pp.BackBufferFormat, DeviceSettings.d3d9.pp.Windowed, + &DeviceSettings.d3d9.AdapterFormat ); + DeviceSettings.d3d9.BehaviorFlags = d3dCreationParams.BehaviorFlags; + + // Change to the Direct3D device passed in + hr = DXUTChangeDevice( &DeviceSettings, pd3dDevice, NULL, false, false ); + if( FAILED( hr ) ) + return hr; + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Creates the 3D environment +//-------------------------------------------------------------------------------------- +HRESULT DXUTCreate3DEnvironment9( IDirect3DDevice9* pd3dDeviceFromApp ) +{ + HRESULT hr = S_OK; + + IDirect3DDevice9* pd3dDevice = NULL; + DXUTDeviceSettings* pNewDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); + + // Only create a Direct3D device if one hasn't been supplied by the app + if( pd3dDeviceFromApp == NULL ) + { + // Try to create the device with the chosen settings + IDirect3D9* pD3D = DXUTGetD3D9Object(); + hr = pD3D->CreateDevice( pNewDeviceSettings->d3d9.AdapterOrdinal, pNewDeviceSettings->d3d9.DeviceType, + DXUTGetHWNDFocus(), pNewDeviceSettings->d3d9.BehaviorFlags, + &pNewDeviceSettings->d3d9.pp, &pd3dDevice ); + if( hr == D3DERR_DEVICELOST ) + { + GetDXUTState().SetDeviceLost( true ); + return S_OK; + } + else if( FAILED( hr ) ) + { + DXUT_ERR( L"CreateDevice", hr ); + return DXUTERR_CREATINGDEVICE; + } + } + else + { + pd3dDeviceFromApp->AddRef(); + pd3dDevice = pd3dDeviceFromApp; + } + + GetDXUTState().SetD3D9Device( pd3dDevice ); + + // If switching to REF, set the exit code to 10. If switching to HAL and exit code was 10, then set it back to 0. + if( pNewDeviceSettings->d3d9.DeviceType == D3DDEVTYPE_REF && GetDXUTState().GetExitCode() == 0 ) + GetDXUTState().SetExitCode( 10 ); + else if( pNewDeviceSettings->d3d9.DeviceType == D3DDEVTYPE_HAL && GetDXUTState().GetExitCode() == 10 ) + GetDXUTState().SetExitCode( 0 ); + + // Update back buffer desc before calling app's device callbacks + DXUTUpdateBackBufferDesc(); + + // Setup cursor based on current settings (window/fullscreen mode, show cursor state, clip cursor state) + DXUTSetupCursor(); + + // Update GetDXUTState()'s copy of D3D caps + D3DCAPS9* pd3dCaps = GetDXUTState().GetCaps(); + DXUTGetD3D9Device()->GetDeviceCaps( pd3dCaps ); + + // Update the device stats text + CD3D9Enumeration* pd3dEnum = DXUTGetD3D9Enumeration(); + CD3D9EnumAdapterInfo* pAdapterInfo = pd3dEnum->GetAdapterInfo( pNewDeviceSettings->d3d9.AdapterOrdinal ); + DXUTUpdateD3D9DeviceStats( pNewDeviceSettings->d3d9.DeviceType, + pNewDeviceSettings->d3d9.BehaviorFlags, + &pAdapterInfo->AdapterIdentifier ); + + // Call the app's device created callback if non-NULL + const D3DSURFACE_DESC* pBackBufferSurfaceDesc = DXUTGetD3D9BackBufferSurfaceDesc(); + GetDXUTState().SetInsideDeviceCallback( true ); + LPDXUTCALLBACKD3D9DEVICECREATED pCallbackDeviceCreated = GetDXUTState().GetD3D9DeviceCreatedFunc(); + hr = S_OK; + if( pCallbackDeviceCreated != NULL ) + hr = pCallbackDeviceCreated( DXUTGetD3D9Device(), pBackBufferSurfaceDesc, + GetDXUTState().GetD3D9DeviceCreatedFuncUserContext() ); + GetDXUTState().SetInsideDeviceCallback( false ); + if( DXUTGetD3D9Device() == NULL ) // Handle DXUTShutdown from inside callback + return E_FAIL; + if( FAILED( hr ) ) + { + DXUT_ERR( L"DeviceCreated callback", hr ); + return ( hr == DXUTERR_MEDIANOTFOUND ) ? DXUTERR_MEDIANOTFOUND : DXUTERR_CREATINGDEVICEOBJECTS; + } + GetDXUTState().SetDeviceObjectsCreated( true ); + + // Call the app's device reset callback if non-NULL + GetDXUTState().SetInsideDeviceCallback( true ); + LPDXUTCALLBACKD3D9DEVICERESET pCallbackDeviceReset = GetDXUTState().GetD3D9DeviceResetFunc(); + hr = S_OK; + if( pCallbackDeviceReset != NULL ) + hr = pCallbackDeviceReset( DXUTGetD3D9Device(), pBackBufferSurfaceDesc, + GetDXUTState().GetD3D9DeviceResetFuncUserContext() ); + GetDXUTState().SetInsideDeviceCallback( false ); + if( DXUTGetD3D9Device() == NULL ) // Handle DXUTShutdown from inside callback + return E_FAIL; + if( FAILED( hr ) ) + { + DXUT_ERR( L"DeviceReset callback", hr ); + return ( hr == DXUTERR_MEDIANOTFOUND ) ? DXUTERR_MEDIANOTFOUND : DXUTERR_RESETTINGDEVICEOBJECTS; + } + GetDXUTState().SetDeviceObjectsReset( true ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Resets the 3D environment by: +// - Calls the device lost callback +// - Resets the device +// - Stores the back buffer description +// - Sets up the full screen Direct3D cursor if requested +// - Calls the device reset callback +//-------------------------------------------------------------------------------------- +HRESULT DXUTReset3DEnvironment9() +{ + HRESULT hr; + + IDirect3DDevice9* pd3dDevice = DXUTGetD3D9Device(); + assert( pd3dDevice != NULL ); + + // Call the app's device lost callback + if( GetDXUTState().GetDeviceObjectsReset() == true ) + { + GetDXUTState().SetInsideDeviceCallback( true ); + LPDXUTCALLBACKD3D9DEVICELOST pCallbackDeviceLost = GetDXUTState().GetD3D9DeviceLostFunc(); + if( pCallbackDeviceLost != NULL ) + pCallbackDeviceLost( GetDXUTState().GetD3D9DeviceLostFuncUserContext() ); + GetDXUTState().SetDeviceObjectsReset( false ); + GetDXUTState().SetInsideDeviceCallback( false ); + } + + // Reset the device + DXUTDeviceSettings* pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); + hr = pd3dDevice->Reset( &pDeviceSettings->d3d9.pp ); + if( FAILED( hr ) ) + { + if( hr == D3DERR_DEVICELOST ) + return D3DERR_DEVICELOST; // Reset could legitimately fail if the device is lost + else + return DXUT_ERR( L"Reset", DXUTERR_RESETTINGDEVICE ); + } + + // Update back buffer desc before calling app's device callbacks + DXUTUpdateBackBufferDesc(); + + // Setup cursor based on current settings (window/fullscreen mode, show cursor state, clip cursor state) + DXUTSetupCursor(); + + // Call the app's OnDeviceReset callback + GetDXUTState().SetInsideDeviceCallback( true ); + const D3DSURFACE_DESC* pBackBufferSurfaceDesc = DXUTGetD3D9BackBufferSurfaceDesc(); + LPDXUTCALLBACKD3D9DEVICERESET pCallbackDeviceReset = GetDXUTState().GetD3D9DeviceResetFunc(); + hr = S_OK; + if( pCallbackDeviceReset != NULL ) + hr = pCallbackDeviceReset( pd3dDevice, pBackBufferSurfaceDesc, + GetDXUTState().GetD3D9DeviceResetFuncUserContext() ); + GetDXUTState().SetInsideDeviceCallback( false ); + if( FAILED( hr ) ) + { + // If callback failed, cleanup + DXUT_ERR( L"DeviceResetCallback", hr ); + if( hr != DXUTERR_MEDIANOTFOUND ) + hr = DXUTERR_RESETTINGDEVICEOBJECTS; + + GetDXUTState().SetInsideDeviceCallback( true ); + LPDXUTCALLBACKD3D9DEVICELOST pCallbackDeviceLost = GetDXUTState().GetD3D9DeviceLostFunc(); + if( pCallbackDeviceLost != NULL ) + pCallbackDeviceLost( GetDXUTState().GetD3D9DeviceLostFuncUserContext() ); + GetDXUTState().SetInsideDeviceCallback( false ); + return hr; + } + + // Success + GetDXUTState().SetDeviceObjectsReset( true ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Render the 3D environment by: +// - Checking if the device is lost and trying to reset it if it is +// - Get the elapsed time since the last frame +// - Calling the app's framemove and render callback +// - Calling Present() +//-------------------------------------------------------------------------------------- +void DXUTRender3DEnvironment9() +{ + HRESULT hr; + + if( GetDXUTState().GetDeviceLost() || DXUTIsRenderingPaused() || !DXUTIsActive() ) + { + // Window is minimized or paused so yield CPU time to other processes + Sleep( 50 ); + } + + // If no device created yet because device was lost (ie. another fullscreen exclusive device exists), + // then wait and try to create every so often. + IDirect3DDevice9* pd3dDevice = DXUTGetD3D9Device(); + if( NULL == pd3dDevice ) + { + if( GetDXUTState().GetDeviceLost() ) + { + DXUTDeviceSettings deviceSettings = DXUTGetDeviceSettings(); + DXUTChangeDevice( &deviceSettings, NULL, NULL, false, true ); + } + + return; + } + + if( GetDXUTState().GetDeviceLost() && !GetDXUTState().GetRenderingPaused() ) + { + // Test the cooperative level to see if it's okay to render. + if( FAILED( hr = pd3dDevice->TestCooperativeLevel() ) ) + { + if( D3DERR_DEVICELOST == hr ) + { + // The device has been lost but cannot be reset at this time. + // So wait until it can be reset. + return; + } + + // If we are windowed, read the desktop format and + // ensure that the Direct3D device is using the same format + // since the user could have changed the desktop bitdepth + if( DXUTIsWindowed() ) + { + D3DDISPLAYMODE adapterDesktopDisplayMode; + IDirect3D9* pD3D = DXUTGetD3D9Object(); + DXUTDeviceSettings* pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); + pD3D->GetAdapterDisplayMode( pDeviceSettings->d3d9.AdapterOrdinal, &adapterDesktopDisplayMode ); + if( pDeviceSettings->d3d9.AdapterFormat != adapterDesktopDisplayMode.Format ) + { + + DXUTDeviceSettings deviceSettings = DXUTGetDeviceSettings(); + deviceSettings.d3d9.AdapterFormat = adapterDesktopDisplayMode.Format; + + hr = DXUTSnapDeviceSettingsToEnumDevice(&deviceSettings, false); + if( FAILED( hr ) ) // the call will fail if no valid devices were found + { + DXUTDisplayErrorMessage( DXUTERR_NOCOMPATIBLEDEVICES ); + DXUTShutdown(); + } + + // Change to a Direct3D device created from the new device settings. + // If there is an existing device, then either reset or recreate the scene + hr = DXUTChangeDevice( &deviceSettings, NULL, NULL, false, false ); + if( FAILED( hr ) ) + { + // If this fails, try to go fullscreen and if this fails also shutdown. + if( FAILED( DXUTToggleFullScreen() ) ) + DXUTShutdown(); + } + + return; + } + } + + // Try to reset the device + if( FAILED( hr = DXUTReset3DEnvironment9() ) ) + { + if( D3DERR_DEVICELOST == hr ) + { + // The device was lost again, so continue waiting until it can be reset. + return; + } + else if( DXUTERR_RESETTINGDEVICEOBJECTS == hr || + DXUTERR_MEDIANOTFOUND == hr ) + { + DXUTDisplayErrorMessage( hr ); + DXUTShutdown(); + return; + } + else + { + // Reset failed, but the device wasn't lost so something bad happened, + // so recreate the device to try to recover + DXUTDeviceSettings* pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); + if( FAILED( DXUTChangeDevice( pDeviceSettings, NULL, NULL, true, false ) ) ) + { + DXUTShutdown(); + return; + } + } + } + } + + GetDXUTState().SetDeviceLost( false ); + } + + // Get the app's time, in seconds. Skip rendering if no time elapsed + double fTime, fAbsTime; float fElapsedTime; + DXUTGetGlobalTimer()->GetTimeValues( &fTime, &fAbsTime, &fElapsedTime ); + + // Store the time for the app + if( GetDXUTState().GetConstantFrameTime() ) + { + fElapsedTime = GetDXUTState().GetTimePerFrame(); + fTime = DXUTGetTime() + fElapsedTime; + } + + GetDXUTState().SetTime( fTime ); + GetDXUTState().SetAbsoluteTime( fAbsTime ); + GetDXUTState().SetElapsedTime( fElapsedTime ); + + // Update the FPS stats + DXUTUpdateFrameStats(); + + DXUTHandleTimers(); + + // Animate the scene by calling the app's frame move callback + LPDXUTCALLBACKFRAMEMOVE pCallbackFrameMove = GetDXUTState().GetFrameMoveFunc(); + if( pCallbackFrameMove != NULL ) + { + pCallbackFrameMove( fTime, fElapsedTime, GetDXUTState().GetFrameMoveFuncUserContext() ); + pd3dDevice = DXUTGetD3D9Device(); + if( NULL == pd3dDevice ) // Handle DXUTShutdown from inside callback + return; + } + + if( !GetDXUTState().GetRenderingPaused() ) + { + // Render the scene by calling the app's render callback + LPDXUTCALLBACKD3D9FRAMERENDER pCallbackFrameRender = GetDXUTState().GetD3D9FrameRenderFunc(); + if( pCallbackFrameRender != NULL ) + { + pCallbackFrameRender( pd3dDevice, fTime, fElapsedTime, + GetDXUTState().GetD3D9FrameRenderFuncUserContext() ); + pd3dDevice = DXUTGetD3D9Device(); + if( NULL == pd3dDevice ) // Handle DXUTShutdown from inside callback + return; + } + +#if defined(DEBUG) || defined(_DEBUG) + // The back buffer should always match the client rect + // if the Direct3D backbuffer covers the entire window + RECT rcClient; + GetClientRect( DXUTGetHWND(), &rcClient ); + if( !IsIconic( DXUTGetHWND() ) ) + { + GetClientRect( DXUTGetHWND(), &rcClient ); + assert( DXUTGetD3D9BackBufferSurfaceDesc()->Width == (UINT)rcClient.right ); + assert( DXUTGetD3D9BackBufferSurfaceDesc()->Height == (UINT)rcClient.bottom ); + } +#endif + + // Show the frame on the primary surface. + hr = pd3dDevice->Present( NULL, NULL, NULL, NULL ); + if( FAILED( hr ) ) + { + if( D3DERR_DEVICELOST == hr ) + { + GetDXUTState().SetDeviceLost( true ); + } + else if( D3DERR_DRIVERINTERNALERROR == hr ) + { + // When D3DERR_DRIVERINTERNALERROR is returned from Present(), + // the application can do one of the following: + // + // - End, with the pop-up window saying that the application cannot continue + // because of problems in the display adapter and that the user should + // contact the adapter manufacturer. + // + // - Attempt to restart by calling IDirect3DDevice9::Reset, which is essentially the same + // path as recovering from a lost device. If IDirect3DDevice9::Reset fails with + // D3DERR_DRIVERINTERNALERROR, the application should end immediately with the message + // that the user should contact the adapter manufacturer. + // + // The framework attempts the path of resetting the device + // + GetDXUTState().SetDeviceLost( true ); + } + } + } + + // If the app called DXUTWasKeyPressed() then do the work + // to store the current state of the keys in bLastKeys + if( GetDXUTState().GetAppCalledWasKeyPressed() ) + { + bool* bLastKeys = GetDXUTState().GetLastKeys(); + bool* bKeys = GetDXUTState().GetKeys(); + memcpy( bLastKeys, bKeys, sizeof( bool ) * 256 ); + } + + // Update current frame # + int nFrame = GetDXUTState().GetCurrentFrameNumber(); + nFrame++; + GetDXUTState().SetCurrentFrameNumber( nFrame ); + + // Check to see if the app should shutdown due to cmdline + if( GetDXUTState().GetOverrideQuitAfterFrame() != 0 ) + { + if( nFrame > GetDXUTState().GetOverrideQuitAfterFrame() ) + DXUTShutdown(); + } + + return; +} + + +//-------------------------------------------------------------------------------------- +// Cleans up the 3D environment by: +// - Calls the device lost callback +// - Calls the device destroyed callback +// - Releases the D3D device +//-------------------------------------------------------------------------------------- +void DXUTCleanup3DEnvironment9( bool bReleaseSettings ) +{ + IDirect3DDevice9* pd3dDevice = DXUTGetD3D9Device(); + if( pd3dDevice != NULL ) + { + GetDXUTState().SetInsideDeviceCallback( true ); + + // Call the app's device lost callback + if( GetDXUTState().GetDeviceObjectsReset() == true ) + { + LPDXUTCALLBACKD3D9DEVICELOST pCallbackDeviceLost = GetDXUTState().GetD3D9DeviceLostFunc(); + if( pCallbackDeviceLost != NULL ) + pCallbackDeviceLost( GetDXUTState().GetD3D9DeviceLostFuncUserContext() ); + GetDXUTState().SetDeviceObjectsReset( false ); + } + + // Call the app's device destroyed callback + if( GetDXUTState().GetDeviceObjectsCreated() == true ) + { + LPDXUTCALLBACKD3D9DEVICEDESTROYED pCallbackDeviceDestroyed = GetDXUTState().GetD3D9DeviceDestroyedFunc(); + if( pCallbackDeviceDestroyed != NULL ) + pCallbackDeviceDestroyed( GetDXUTState().GetD3D9DeviceDestroyedFuncUserContext() ); + GetDXUTState().SetDeviceObjectsCreated( false ); + } + + GetDXUTState().SetInsideDeviceCallback( false ); + + // Release the D3D device and in debug configs, displays a message box if there + // are unrelease objects. + if( pd3dDevice ) + { + UINT references = pd3dDevice->Release(); + if( references > 0 ) + { + DXUTDisplayErrorMessage( DXUTERR_NONZEROREFCOUNT ); + DXUT_ERR( L"DXUTCleanup3DEnvironment", DXUTERR_NONZEROREFCOUNT ); + } + } + GetDXUTState().SetD3D9Device( NULL ); + + if( bReleaseSettings ) + { + DXUTDeviceSettings* pOldDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); + SAFE_DELETE(pOldDeviceSettings); + GetDXUTState().SetCurrentDeviceSettings( NULL ); + } + + D3DSURFACE_DESC* pBackBufferSurfaceDesc = GetDXUTState().GetBackBufferSurfaceDesc9(); + ZeroMemory( pBackBufferSurfaceDesc, sizeof( D3DSURFACE_DESC ) ); + + D3DCAPS9* pd3dCaps = GetDXUTState().GetCaps(); + ZeroMemory( pd3dCaps, sizeof( D3DCAPS9 ) ); + + GetDXUTState().SetDeviceCreated( false ); + } +} + + +//-------------------------------------------------------------------------------------- +// Gives the D3D device a cursor with image and hotspot from hCursor. +//-------------------------------------------------------------------------------------- +HRESULT DXUTSetD3D9DeviceCursor( IDirect3DDevice9* pd3dDevice, HCURSOR hCursor, bool bAddWatermark ) +{ + HRESULT hr = E_FAIL; + ICONINFO iconinfo; + bool bBWCursor = false; + LPDIRECT3DSURFACE9 pCursorSurface = NULL; + HDC hdcColor = NULL; + HDC hdcMask = NULL; + HDC hdcScreen = NULL; + BITMAP bm; + DWORD dwWidth = 0; + DWORD dwHeightSrc = 0; + DWORD dwHeightDest = 0; + COLORREF crColor; + COLORREF crMask; + UINT x; + UINT y; + BITMAPINFO bmi; + COLORREF* pcrArrayColor = NULL; + COLORREF* pcrArrayMask = NULL; + DWORD* pBitmap; + HGDIOBJ hgdiobjOld; + + ZeroMemory( &iconinfo, sizeof( iconinfo ) ); + if( !GetIconInfo( hCursor, &iconinfo ) ) + goto End; + + if( 0 == GetObject( ( HGDIOBJ )iconinfo.hbmMask, sizeof( BITMAP ), ( LPVOID )&bm ) ) + goto End; + dwWidth = bm.bmWidth; + dwHeightSrc = bm.bmHeight; + + if( iconinfo.hbmColor == NULL ) + { + bBWCursor = TRUE; + dwHeightDest = dwHeightSrc / 2; + } + else + { + bBWCursor = FALSE; + dwHeightDest = dwHeightSrc; + } + + // Create a surface for the fullscreen cursor + if( FAILED( hr = pd3dDevice->CreateOffscreenPlainSurface( dwWidth, dwHeightDest, + D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pCursorSurface, + NULL ) ) ) + { + goto End; + } + + pcrArrayMask = new DWORD[dwWidth * dwHeightSrc]; + + ZeroMemory( &bmi, sizeof( bmi ) ); + bmi.bmiHeader.biSize = sizeof( bmi.bmiHeader ); + bmi.bmiHeader.biWidth = dwWidth; + bmi.bmiHeader.biHeight = dwHeightSrc; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + + hdcScreen = GetDC( NULL ); + hdcMask = CreateCompatibleDC( hdcScreen ); + if( hdcMask == NULL ) + { + hr = E_FAIL; + goto End; + } + hgdiobjOld = SelectObject( hdcMask, iconinfo.hbmMask ); + GetDIBits( hdcMask, iconinfo.hbmMask, 0, dwHeightSrc, + pcrArrayMask, &bmi, DIB_RGB_COLORS ); + SelectObject( hdcMask, hgdiobjOld ); + + if( !bBWCursor ) + { + pcrArrayColor = new DWORD[dwWidth * dwHeightDest]; + hdcColor = CreateCompatibleDC( hdcScreen ); + if( hdcColor == NULL ) + { + hr = E_FAIL; + goto End; + } + SelectObject( hdcColor, iconinfo.hbmColor ); + GetDIBits( hdcColor, iconinfo.hbmColor, 0, dwHeightDest, + pcrArrayColor, &bmi, DIB_RGB_COLORS ); + } + + // Transfer cursor image into the surface + D3DLOCKED_RECT lr; + pCursorSurface->LockRect( &lr, NULL, 0 ); + pBitmap = ( DWORD* )lr.pBits; + for( y = 0; y < dwHeightDest; y++ ) + { + for( x = 0; x < dwWidth; x++ ) + { + if( bBWCursor ) + { + crColor = pcrArrayMask[dwWidth * ( dwHeightDest - 1 - y ) + x]; + crMask = pcrArrayMask[dwWidth * ( dwHeightSrc - 1 - y ) + x]; + } + else + { + crColor = pcrArrayColor[dwWidth * ( dwHeightDest - 1 - y ) + x]; + crMask = pcrArrayMask[dwWidth * ( dwHeightDest - 1 - y ) + x]; + } + if( crMask == 0 ) + pBitmap[dwWidth * y + x] = 0xff000000 | crColor; + else + pBitmap[dwWidth * y + x] = 0x00000000; + + // It may be helpful to make the D3D cursor look slightly + // different from the Windows cursor so you can distinguish + // between the two when developing/testing code. When + // bAddWatermark is TRUE, the following code adds some + // small grey "D3D" characters to the upper-left corner of + // the D3D cursor image. + if( bAddWatermark && x < 12 && y < 5 ) + { + // 11.. 11.. 11.. .... CCC0 + // 1.1. ..1. 1.1. .... A2A0 + // 1.1. .1.. 1.1. .... A4A0 + // 1.1. ..1. 1.1. .... A2A0 + // 11.. 11.. 11.. .... CCC0 + + const WORD wMask[5] = { 0xccc0, 0xa2a0, 0xa4a0, 0xa2a0, 0xccc0 }; + if( wMask[y] & (1 << (15 - x)) ) + { + pBitmap[dwWidth*y + x] |= 0xff808080; + } + } + } + } + pCursorSurface->UnlockRect(); + + // Set the device cursor + if( FAILED( hr = pd3dDevice->SetCursorProperties( iconinfo.xHotspot, + iconinfo.yHotspot, pCursorSurface ) ) ) + { + goto End; + } + + hr = S_OK; + +End: + if( iconinfo.hbmMask != NULL ) + DeleteObject( iconinfo.hbmMask ); + if( iconinfo.hbmColor != NULL ) + DeleteObject( iconinfo.hbmColor ); + if( hdcScreen != NULL ) + ReleaseDC( NULL, hdcScreen ); + if( hdcColor != NULL ) + DeleteDC( hdcColor ); + if( hdcMask != NULL ) + DeleteDC( hdcMask ); + SAFE_DELETE_ARRAY( pcrArrayColor ); + SAFE_DELETE_ARRAY( pcrArrayMask ); + SAFE_RELEASE( pCursorSurface ); + return hr; +} + + +//-------------------------------------------------------------------------------------- +// Internal helper function to return the adapter format from the first device settings +// combo that matches the passed adapter ordinal, device type, backbuffer format, and windowed. +//-------------------------------------------------------------------------------------- +HRESULT DXUTFindD3D9AdapterFormat( UINT AdapterOrdinal, D3DDEVTYPE DeviceType, D3DFORMAT BackBufferFormat, + BOOL Windowed, D3DFORMAT* pAdapterFormat ) +{ + CD3D9Enumeration* pd3dEnum = DXUTGetD3D9Enumeration( false ); + CD3D9EnumDeviceInfo* pDeviceInfo = pd3dEnum->GetDeviceInfo( AdapterOrdinal, DeviceType ); + if( pDeviceInfo ) + { + for( int iDeviceCombo = 0; iDeviceCombo < pDeviceInfo->deviceSettingsComboList.GetSize(); iDeviceCombo++ ) + { + CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo = pDeviceInfo->deviceSettingsComboList.GetAt( + iDeviceCombo ); + if( pDeviceSettingsCombo->BackBufferFormat == BackBufferFormat && + pDeviceSettingsCombo->Windowed == Windowed ) + { + // Return the adapter format from the first match + *pAdapterFormat = pDeviceSettingsCombo->AdapterFormat; + return S_OK; + } + } + } + + *pAdapterFormat = BackBufferFormat; + return E_FAIL; +} + +//-------------------------------------------------------------------------------------- +// Sets the viewport, render target view, and depth stencil view. +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTSetupD3D11Views( ID3D11DeviceContext* pd3dDeviceContext ) +{ + HRESULT hr = S_OK; + + // Setup the viewport to match the backbuffer + D3D11_VIEWPORT vp; + vp.Width = (FLOAT)DXUTGetDXGIBackBufferSurfaceDesc()->Width; + vp.Height = (FLOAT)DXUTGetDXGIBackBufferSurfaceDesc()->Height; + vp.MinDepth = 0; + vp.MaxDepth = 1; + vp.TopLeftX = 0; + vp.TopLeftY = 0; + pd3dDeviceContext->RSSetViewports( 1, &vp ); + + // Set the render targets + ID3D11RenderTargetView* pRTV = GetDXUTState().GetD3D11RenderTargetView(); + ID3D11DepthStencilView* pDSV = GetDXUTState().GetD3D11DepthStencilView(); + pd3dDeviceContext->OMSetRenderTargets( 1, &pRTV, pDSV ); + + return hr; +} + + +//-------------------------------------------------------------------------------------- +// Creates a render target view, and depth stencil texture and view. +//-------------------------------------------------------------------------------------- +HRESULT DXUTCreateD3D11Views( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, + DXUTDeviceSettings* pDeviceSettings ) +{ + HRESULT hr = S_OK; + IDXGISwapChain* pSwapChain = DXUTGetDXGISwapChain(); + ID3D11DepthStencilView* pDSV = NULL; + ID3D11RenderTargetView* pRTV = NULL; + + // Get the back buffer and desc + ID3D11Texture2D* pBackBuffer; + hr = pSwapChain->GetBuffer( 0, __uuidof( *pBackBuffer ), ( LPVOID* )&pBackBuffer ); + if( FAILED( hr ) ) + return hr; + D3D11_TEXTURE2D_DESC backBufferSurfaceDesc; + pBackBuffer->GetDesc( &backBufferSurfaceDesc ); + + // Create the render target view + hr = pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &pRTV ); + SAFE_RELEASE( pBackBuffer ); + if( FAILED( hr ) ) + return hr; + GetDXUTState().SetD3D11RenderTargetView( pRTV ); + + if( pDeviceSettings->d3d11.AutoCreateDepthStencil ) + { + // Create depth stencil texture + ID3D11Texture2D* pDepthStencil = NULL; + D3D11_TEXTURE2D_DESC descDepth; + descDepth.Width = backBufferSurfaceDesc.Width; + descDepth.Height = backBufferSurfaceDesc.Height; + descDepth.MipLevels = 1; + descDepth.ArraySize = 1; + descDepth.Format = pDeviceSettings->d3d11.AutoDepthStencilFormat; + descDepth.SampleDesc.Count = pDeviceSettings->d3d11.sd.SampleDesc.Count; + descDepth.SampleDesc.Quality = pDeviceSettings->d3d11.sd.SampleDesc.Quality; + descDepth.Usage = D3D11_USAGE_DEFAULT; + descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL; + descDepth.CPUAccessFlags = 0; + descDepth.MiscFlags = 0; + hr = pd3dDevice->CreateTexture2D( &descDepth, NULL, &pDepthStencil ); + if( FAILED( hr ) ) + return hr; + GetDXUTState().SetD3D11DepthStencil( pDepthStencil ); + + // Create the depth stencil view + D3D11_DEPTH_STENCIL_VIEW_DESC descDSV; + descDSV.Format = descDepth.Format; + descDSV.Flags = 0; + if( descDepth.SampleDesc.Count > 1 ) + descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; + else + descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + descDSV.Texture2D.MipSlice = 0; + hr = pd3dDevice->CreateDepthStencilView( pDepthStencil, &descDSV, &pDSV ); + if( FAILED( hr ) ) + return hr; + GetDXUTState().SetD3D11DepthStencilView( pDSV ); + } + + hr = DXUTSetupD3D11Views( pd3dImmediateContext ); + if( FAILED( hr ) ) + return hr; + + return hr; +} + + +//-------------------------------------------------------------------------------------- +// Creates the 3D environment +//-------------------------------------------------------------------------------------- +HRESULT DXUTCreate3DEnvironment11( ID3D11Device* pd3d11DeviceFromApp ) +{ + HRESULT hr = S_OK; + + ID3D11Device* pd3d11Device = NULL; + ID3D11DeviceContext* pd3dImmediateContext = NULL; + D3D_FEATURE_LEVEL FeatureLevel = D3D_FEATURE_LEVEL_11_0; + + IDXGISwapChain* pSwapChain = NULL; + DXUTDeviceSettings* pNewDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); + + IDXGIFactory1* pDXGIFactory = DXUTGetDXGIFactory(); + hr = pDXGIFactory->MakeWindowAssociation( DXUTGetHWND(), 0 ); + + // Only create a Direct3D device if one hasn't been supplied by the app + if( pd3d11DeviceFromApp == NULL ) + { + // Try to create the device with the chosen settings + IDXGIAdapter1* pAdapter = NULL; + + hr = S_OK; + D3D_DRIVER_TYPE ddt = pNewDeviceSettings->d3d11.DriverType; + if( pNewDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_HARDWARE ) + { + hr = pDXGIFactory->EnumAdapters1( pNewDeviceSettings->d3d11.AdapterOrdinal, &pAdapter ); + if ( FAILED( hr) ) + { + return E_FAIL; + } + ddt = D3D_DRIVER_TYPE_UNKNOWN; + } + else if (pNewDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_WARP) + { + ddt = D3D_DRIVER_TYPE_WARP; + pAdapter = NULL; + } + else if (pNewDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE) + { + ddt = D3D_DRIVER_TYPE_REFERENCE; + pAdapter = NULL; + } + + if( SUCCEEDED( hr ) ) + { + + hr = DXUT_Dynamic_D3D11CreateDevice( pAdapter, + ddt, + ( HMODULE )0, + pNewDeviceSettings->d3d11.CreateFlags, + &pNewDeviceSettings->d3d11.DeviceFeatureLevel, + 1, + D3D11_SDK_VERSION, + &pd3d11Device, + &FeatureLevel, + &pd3dImmediateContext + ); + + if ( FAILED( hr ) ) { + pAdapter = NULL; + // Remote desktop does not allow you to enumerate the adapter. In this case, we let D3D11 do the enumeration. + if ( ddt == D3D_DRIVER_TYPE_UNKNOWN ) { + hr = DXUT_Dynamic_D3D11CreateDevice( pAdapter, + D3D_DRIVER_TYPE_HARDWARE, + ( HMODULE )0, + pNewDeviceSettings->d3d11.CreateFlags, + &pNewDeviceSettings->d3d11.DeviceFeatureLevel, + 1, + D3D11_SDK_VERSION, + &pd3d11Device, + &FeatureLevel, + &pd3dImmediateContext + ); + } + if ( FAILED ( hr ) ) { + DXUT_ERR( L"D3D11CreateDevice", hr ); + return DXUTERR_CREATINGDEVICE; + } + } + } + + if( SUCCEEDED( hr ) ) + { + IDXGIDevice1* pDXGIDev = NULL; + hr = pd3d11Device->QueryInterface( __uuidof( IDXGIDevice1 ), ( LPVOID* )&pDXGIDev ); + if( SUCCEEDED( hr ) && pDXGIDev ) + { + if ( pAdapter == NULL ) + { + IDXGIAdapter *pTempAdapter; + pDXGIDev->GetAdapter( &pTempAdapter ); + V_RETURN( pTempAdapter->QueryInterface( __uuidof( IDXGIAdapter1 ), (LPVOID*) &pAdapter ) ); + V_RETURN( pAdapter->GetParent( __uuidof( IDXGIFactory1 ), (LPVOID*) &pDXGIFactory ) ); + SAFE_RELEASE ( pTempAdapter ); + GetDXUTState().SetDXGIFactory( pDXGIFactory ); + } + } + SAFE_RELEASE( pDXGIDev ); + GetDXUTState().SetDXGIAdapter( pAdapter ); + } + + // set default render state to msaa enabled + D3D11_RASTERIZER_DESC drd = { + D3D11_FILL_SOLID, //D3D11_FILL_MODE FillMode; + D3D11_CULL_BACK,//D3D11_CULL_MODE CullMode; + FALSE, //BOOL FrontCounterClockwise; + 0, //INT DepthBias; + 0.0f,//FLOAT DepthBiasClamp; + 0.0f,//FLOAT SlopeScaledDepthBias; + TRUE,//BOOL DepthClipEnable; + FALSE,//BOOL ScissorEnable; + TRUE,//BOOL MultisampleEnable; + FALSE//BOOL AntialiasedLineEnable; + }; + if( FAILED( hr ) ) + { + DXUT_ERR( L"D3D11CreateDevice", hr ); + return DXUTERR_CREATINGDEVICE; + } + ID3D11RasterizerState* pRS = NULL; + pd3d11Device->CreateRasterizerState(&drd, &pRS); + GetDXUTState().SetD3D11RasterizerState(pRS); + pd3dImmediateContext->RSSetState(pRS); + + + + + // Enumerate its outputs. + UINT OutputCount, iOutput; + for( OutputCount = 0; ; ++OutputCount ) + { + IDXGIOutput* pOutput; + if( FAILED( pAdapter->EnumOutputs( OutputCount, &pOutput ) ) ) + break; + SAFE_RELEASE( pOutput ); + } + IDXGIOutput** ppOutputArray = new IDXGIOutput*[OutputCount]; + if( !ppOutputArray ) + return E_OUTOFMEMORY; + for( iOutput = 0; iOutput < OutputCount; ++iOutput ) + pAdapter->EnumOutputs( iOutput, ppOutputArray + iOutput ); + GetDXUTState().SetDXGIOutputArray( ppOutputArray ); + GetDXUTState().SetDXGIOutputArraySize( OutputCount ); + + // Create the swapchain + + hr = pDXGIFactory->CreateSwapChain( pd3d11Device, &pNewDeviceSettings->d3d11.sd, &pSwapChain ); + + if( FAILED( hr ) ) + { + DXUT_ERR( L"CreateSwapChain", hr ); + return DXUTERR_CREATINGDEVICE; + } + } + else + { + pd3d11DeviceFromApp->AddRef(); + pd3d11Device = pd3d11DeviceFromApp; + } + + GetDXUTState().SetD3D11Device( pd3d11Device ); + GetDXUTState().SetD3D11DeviceContext( pd3dImmediateContext ); + GetDXUTState().SetD3D11FeatureLevel( FeatureLevel ); + GetDXUTState().SetDXGISwapChain( pSwapChain ); + + // If switching to REF, set the exit code to 11. If switching to HAL and exit code was 11, then set it back to 0. + if( pNewDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE && GetDXUTState().GetExitCode() == 0 ) + GetDXUTState().SetExitCode( 10 ); + else if( pNewDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_HARDWARE && GetDXUTState().GetExitCode() == 10 ) + GetDXUTState().SetExitCode( 0 ); + + // Update back buffer desc before calling app's device callbacks + DXUTUpdateBackBufferDesc(); + + // Setup cursor based on current settings (window/fullscreen mode, show cursor state, clip cursor state) + DXUTSetupCursor(); + + // Update the device stats text + CD3D11Enumeration* pd3dEnum = DXUTGetD3D11Enumeration(); + CD3D11EnumAdapterInfo* pAdapterInfo = pd3dEnum->GetAdapterInfo( pNewDeviceSettings->d3d11.AdapterOrdinal ); + DXUTUpdateD3D11DeviceStats( pNewDeviceSettings->d3d11.DriverType, &pAdapterInfo->AdapterDesc ); + + // Call the app's device created callback if non-NULL + const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc = DXUTGetDXGIBackBufferSurfaceDesc(); + GetDXUTState().SetInsideDeviceCallback( true ); + LPDXUTCALLBACKD3D11DEVICECREATED pCallbackDeviceCreated = GetDXUTState().GetD3D11DeviceCreatedFunc(); + hr = S_OK; + if( pCallbackDeviceCreated != NULL ) + hr = pCallbackDeviceCreated( DXUTGetD3D11Device(), pBackBufferSurfaceDesc, + GetDXUTState().GetD3D11DeviceCreatedFuncUserContext() ); + GetDXUTState().SetInsideDeviceCallback( false ); + if( DXUTGetD3D11Device() == NULL ) // Handle DXUTShutdown from inside callback + return E_FAIL; + if( FAILED( hr ) ) + { + DXUT_ERR( L"DeviceCreated callback", hr ); + return ( hr == DXUTERR_MEDIANOTFOUND ) ? DXUTERR_MEDIANOTFOUND : DXUTERR_CREATINGDEVICEOBJECTS; + } + GetDXUTState().SetDeviceObjectsCreated( true ); + + // Setup the render target view and viewport + hr = DXUTCreateD3D11Views( pd3d11Device, pd3dImmediateContext, pNewDeviceSettings ); + if( FAILED( hr ) ) + { + DXUT_ERR( L"DXUTCreateD3D11Views", hr ); + return DXUTERR_CREATINGDEVICEOBJECTS; + } + + // Create performance counters + //DXUTCreateD3D11Counters( pd3d11Device ); + + // Call the app's swap chain reset callback if non-NULL + GetDXUTState().SetInsideDeviceCallback( true ); + LPDXUTCALLBACKD3D11SWAPCHAINRESIZED pCallbackSwapChainResized = GetDXUTState().GetD3D11SwapChainResizedFunc(); + hr = S_OK; + if( pCallbackSwapChainResized != NULL ) + hr = pCallbackSwapChainResized( DXUTGetD3D11Device(), pSwapChain, pBackBufferSurfaceDesc, + GetDXUTState().GetD3D11SwapChainResizedFuncUserContext() ); + GetDXUTState().SetInsideDeviceCallback( false ); + if( DXUTGetD3D11Device() == NULL ) // Handle DXUTShutdown from inside callback + return E_FAIL; + if( FAILED( hr ) ) + { + DXUT_ERR( L"DeviceReset callback", hr ); + return ( hr == DXUTERR_MEDIANOTFOUND ) ? DXUTERR_MEDIANOTFOUND : DXUTERR_RESETTINGDEVICEOBJECTS; + } + GetDXUTState().SetDeviceObjectsReset( true ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Resets the 3D environment by: +// - Calls the device lost callback +// - Resets the device +// - Stores the back buffer description +// - Sets up the full screen Direct3D cursor if requested +// - Calls the device reset callback +//-------------------------------------------------------------------------------------- +HRESULT DXUTReset3DEnvironment11() +{ + HRESULT hr; + + GetDXUTState().SetDeviceObjectsReset( false ); + DXUTPause( true, true ); + + bool bDeferredDXGIAction = false; + DXUTDeviceSettings* pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); + IDXGISwapChain* pSwapChain = DXUTGetDXGISwapChain(); + + DXGI_SWAP_CHAIN_DESC SCDesc; + pSwapChain->GetDesc( &SCDesc ); + + // Resize backbuffer and target of the swapchain in case they have changed. + // For windowed mode, use the client rect as the desired size. Unlike D3D9, + // we can't use 0 for width or height. Therefore, fill in the values from + // the window size. For fullscreen mode, the width and height should have + // already been filled with the desktop resolution, so don't change it. + if( pDeviceSettings->d3d11.sd.Windowed && SCDesc.Windowed ) + { + RECT rcWnd; + GetClientRect( DXUTGetHWND(), &rcWnd ); + pDeviceSettings->d3d11.sd.BufferDesc.Width = rcWnd.right - rcWnd.left; + pDeviceSettings->d3d11.sd.BufferDesc.Height = rcWnd.bottom - rcWnd.top; + } + + // If the app wants to switch from windowed to fullscreen or vice versa, + // call the swapchain's SetFullscreenState + // mode. + if( SCDesc.Windowed != pDeviceSettings->d3d11.sd.Windowed ) + { + // Set the fullscreen state + if( pDeviceSettings->d3d11.sd.Windowed ) + { + V_RETURN( pSwapChain->SetFullscreenState( FALSE, NULL ) ); + bDeferredDXGIAction = true; + } + else + { + // Set fullscreen state by setting the display mode to fullscreen, then changing the resolution + // to the desired value. + + // SetFullscreenState causes a WM_SIZE message to be sent to the window. The WM_SIZE message calls + // DXUTCheckForDXGIBufferChange which normally stores the new height and width in + // pDeviceSettings->d3d11.sd.BufferDesc. SetDoNotStoreBufferSize tells DXUTCheckForDXGIBufferChange + // not to store the height and width so that we have the correct values when calling ResizeTarget. + + GetDXUTState().SetDoNotStoreBufferSize( true ); + V_RETURN( pSwapChain->SetFullscreenState( TRUE, NULL ) ); + GetDXUTState().SetDoNotStoreBufferSize( false ); + + V_RETURN( pSwapChain->ResizeTarget( &pDeviceSettings->d3d11.sd.BufferDesc ) ); + bDeferredDXGIAction = true; + } + } + else + { + if( pDeviceSettings->d3d11.sd.BufferDesc.Width == SCDesc.BufferDesc.Width && + pDeviceSettings->d3d11.sd.BufferDesc.Height == SCDesc.BufferDesc.Height && + pDeviceSettings->d3d11.sd.BufferDesc.Format != SCDesc.BufferDesc.Format ) + { + DXUTResizeDXGIBuffers( 0, 0, !pDeviceSettings->d3d11.sd.Windowed ); + bDeferredDXGIAction = true; + } + else if( pDeviceSettings->d3d11.sd.BufferDesc.Width != SCDesc.BufferDesc.Width || + pDeviceSettings->d3d11.sd.BufferDesc.Height != SCDesc.BufferDesc.Height ) + { + V_RETURN( pSwapChain->ResizeTarget( &pDeviceSettings->d3d11.sd.BufferDesc ) ); + bDeferredDXGIAction = true; + } + } + + // If no deferred DXGI actions are to take place, mark the device as reset. + // If there is a deferred DXGI action, then the device isn't reset until DXGI sends us a + // window message. Only then can we mark the device as reset. + if( !bDeferredDXGIAction ) + GetDXUTState().SetDeviceObjectsReset( true ); + DXUTPause( false, false ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Render the 3D environment by: +// - Checking if the device is lost and trying to reset it if it is +// - Get the elapsed time since the last frame +// - Calling the app's framemove and render callback +// - Calling Present() +//-------------------------------------------------------------------------------------- +void DXUTRender3DEnvironment11() +{ + HRESULT hr; + + ID3D11Device* pd3dDevice = DXUTGetD3D11Device(); + if( NULL == pd3dDevice ) + return; + + ID3D11DeviceContext* pd3dImmediateContext = DXUTGetD3D11DeviceContext(); + if( NULL == pd3dImmediateContext ) + return; + + IDXGISwapChain* pSwapChain = DXUTGetDXGISwapChain(); + if( NULL == pSwapChain ) + return; + + if( DXUTIsRenderingPaused() || !DXUTIsActive() || GetDXUTState().GetRenderingOccluded() ) + { + // Window is minimized/paused/occluded/or not exclusive so yield CPU time to other processes + Sleep( 50 ); + } + + // Get the app's time, in seconds. Skip rendering if no time elapsed + double fTime, fAbsTime; float fElapsedTime; + DXUTGetGlobalTimer()->GetTimeValues( &fTime, &fAbsTime, &fElapsedTime ); + + // Store the time for the app + if( GetDXUTState().GetConstantFrameTime() ) + { + fElapsedTime = GetDXUTState().GetTimePerFrame(); + fTime = DXUTGetTime() + fElapsedTime; + } + + GetDXUTState().SetTime( fTime ); + GetDXUTState().SetAbsoluteTime( fAbsTime ); + GetDXUTState().SetElapsedTime( fElapsedTime ); + + // Start Performance Counters + + // Update the FPS stats + DXUTUpdateFrameStats(); + + DXUTHandleTimers(); + + // Animate the scene by calling the app's frame move callback + LPDXUTCALLBACKFRAMEMOVE pCallbackFrameMove = GetDXUTState().GetFrameMoveFunc(); + if( pCallbackFrameMove != NULL ) + { + pCallbackFrameMove( fTime, fElapsedTime, GetDXUTState().GetFrameMoveFuncUserContext() ); + pd3dDevice = DXUTGetD3D11Device(); + if( NULL == pd3dDevice ) // Handle DXUTShutdown from inside callback + return; + } + + if( !GetDXUTState().GetRenderingPaused() ) + { + // Render the scene by calling the app's render callback + LPDXUTCALLBACKD3D11FRAMERENDER pCallbackFrameRender = GetDXUTState().GetD3D11FrameRenderFunc(); + if( pCallbackFrameRender != NULL && !GetDXUTState().GetRenderingOccluded() ) + { + pCallbackFrameRender( pd3dDevice, pd3dImmediateContext, fTime, fElapsedTime, + GetDXUTState().GetD3D11FrameRenderFuncUserContext() ); + + pd3dDevice = DXUTGetD3D11Device(); + if( NULL == pd3dDevice ) // Handle DXUTShutdown from inside callback + return; + } + +#if defined(DEBUG) || defined(_DEBUG) + // The back buffer should always match the client rect + // if the Direct3D backbuffer covers the entire window + RECT rcClient; + GetClientRect( DXUTGetHWND(), &rcClient ); + if( !IsIconic( DXUTGetHWND() ) ) + { + GetClientRect( DXUTGetHWND(), &rcClient ); + + assert( DXUTGetDXGIBackBufferSurfaceDesc()->Width == (UINT)rcClient.right ); + assert( DXUTGetDXGIBackBufferSurfaceDesc()->Height == (UINT)rcClient.bottom ); + } +#endif + } + + if ( GetDXUTState().GetSaveScreenShot() ) { + DXUTSnapD3D11Screenshot( GetDXUTState().GetScreenShotName(), D3DX11_IFF_BMP ); + } + if ( GetDXUTState().GetExitAfterScreenShot() ) { + DXUTShutdown(); + return; + } + + DWORD dwFlags = 0; + if( GetDXUTState().GetRenderingOccluded() ) + dwFlags = DXGI_PRESENT_TEST; + else + dwFlags = GetDXUTState().GetCurrentDeviceSettings()->d3d11.PresentFlags; + UINT SyncInterval = GetDXUTState().GetCurrentDeviceSettings()->d3d11.SyncInterval; + + // Show the frame on the primary surface. + hr = pSwapChain->Present( SyncInterval, dwFlags ); + if( DXGI_STATUS_OCCLUDED == hr ) + { + // There is a window covering our entire rendering area. + // Don't render until we're visible again. + GetDXUTState().SetRenderingOccluded( true ); + } + else if( DXGI_ERROR_DEVICE_RESET == hr ) + { + // If a mode change happened, we must reset the device + if( FAILED( hr = DXUTReset3DEnvironment11() ) ) + { + if( DXUTERR_RESETTINGDEVICEOBJECTS == hr || + DXUTERR_MEDIANOTFOUND == hr ) + { + DXUTDisplayErrorMessage( hr ); + DXUTShutdown(); + return; + } + else + { + // Reset failed, but the device wasn't lost so something bad happened, + // so recreate the device to try to recover + DXUTDeviceSettings* pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); + if( FAILED( DXUTChangeDevice( pDeviceSettings, NULL, NULL, true, false ) ) ) + { + DXUTShutdown(); + return; + } + + // TODO: Handle display orientation changes in full-screen mode. + } + } + } + else if( DXGI_ERROR_DEVICE_REMOVED == hr ) + { + // Use a callback to ask the app if it would like to find a new device. + // If no device removed callback is set, then look for a new device + if( FAILED( DXUTHandleDeviceRemoved() ) ) + { + // TODO: use pD3DDevice->GetDeviceRemovedReason() + DXUTDisplayErrorMessage( DXUTERR_DEVICEREMOVED ); + DXUTShutdown(); + return; + } + } + else if( SUCCEEDED( hr ) ) + { + if( GetDXUTState().GetRenderingOccluded() ) + { + // Now that we're no longer occluded + // allow us to render again + GetDXUTState().SetRenderingOccluded( false ); + } + } + + // Update current frame # + int nFrame = GetDXUTState().GetCurrentFrameNumber(); + nFrame++; + GetDXUTState().SetCurrentFrameNumber( nFrame ); + + + // Update the D3D11 counter stats + //DXUTUpdateD3D11CounterStats(); + + // Check to see if the app should shutdown due to cmdline + if( GetDXUTState().GetOverrideQuitAfterFrame() != 0 ) + { + if( nFrame > GetDXUTState().GetOverrideQuitAfterFrame() ) + DXUTShutdown(); + } + + return; +} + +void ClearD3D11DeviceContext( ID3D11DeviceContext* pd3dDeviceContext ) +{ + // Unbind all objects from the immediate context + if (pd3dDeviceContext == NULL) return; + + ID3D11ShaderResourceView* pSRVs[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; + ID3D11RenderTargetView* pRTVs[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; + ID3D11DepthStencilView* pDSV = NULL; + ID3D11Buffer* pBuffers[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; + ID3D11SamplerState* pSamplers[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; + UINT StrideOffset[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; + + // Shaders + pd3dDeviceContext->VSSetShader( NULL, NULL, 0 ); + pd3dDeviceContext->HSSetShader( NULL, NULL, 0 ); + pd3dDeviceContext->DSSetShader( NULL, NULL, 0 ); + pd3dDeviceContext->GSSetShader( NULL, NULL, 0 ); + pd3dDeviceContext->PSSetShader( NULL, NULL, 0 ); + + // IA clear + pd3dDeviceContext->IASetVertexBuffers( 0, 16, pBuffers, StrideOffset, StrideOffset ); + pd3dDeviceContext->IASetIndexBuffer( NULL, DXGI_FORMAT_R16_UINT, 0 ); + pd3dDeviceContext->IASetInputLayout( NULL ); + + // Constant buffers + pd3dDeviceContext->VSSetConstantBuffers( 0, 14, pBuffers ); + pd3dDeviceContext->HSSetConstantBuffers( 0, 14, pBuffers ); + pd3dDeviceContext->DSSetConstantBuffers( 0, 14, pBuffers ); + pd3dDeviceContext->GSSetConstantBuffers( 0, 14, pBuffers ); + pd3dDeviceContext->PSSetConstantBuffers( 0, 14, pBuffers ); + + // Resources + pd3dDeviceContext->VSSetShaderResources( 0, 16, pSRVs ); + pd3dDeviceContext->HSSetShaderResources( 0, 16, pSRVs ); + pd3dDeviceContext->DSSetShaderResources( 0, 16, pSRVs ); + pd3dDeviceContext->GSSetShaderResources( 0, 16, pSRVs ); + pd3dDeviceContext->PSSetShaderResources( 0, 16, pSRVs ); + + // Samplers + pd3dDeviceContext->VSSetSamplers( 0, 16, pSamplers ); + pd3dDeviceContext->HSSetSamplers( 0, 16, pSamplers ); + pd3dDeviceContext->DSSetSamplers( 0, 16, pSamplers ); + pd3dDeviceContext->GSSetSamplers( 0, 16, pSamplers ); + pd3dDeviceContext->PSSetSamplers( 0, 16, pSamplers ); + + // Render targets + pd3dDeviceContext->OMSetRenderTargets( 8, pRTVs, pDSV ); + + // States + FLOAT blendFactor[4] = { 0,0,0,0 }; + pd3dDeviceContext->OMSetBlendState( NULL, blendFactor, 0xFFFFFFFF ); + pd3dDeviceContext->OMSetDepthStencilState( NULL, 0 ); + pd3dDeviceContext->RSSetState( NULL ); +} + +//-------------------------------------------------------------------------------------- +// Cleans up the 3D environment by: +// - Calls the device lost callback +// - Calls the device destroyed callback +// - Releases the D3D device +//-------------------------------------------------------------------------------------- +void DXUTCleanup3DEnvironment11( bool bReleaseSettings ) +{ + ID3D11Device* pd3dDevice = DXUTGetD3D11Device(); + + if( pd3dDevice != NULL ) + { + if (GetDXUTState().GetD3D11RasterizerState()!= NULL ) + GetDXUTState().GetD3D11RasterizerState()->Release(); + + // Call ClearState to avoid tons of messy debug spew telling us that we're deleting bound objects + ID3D11DeviceContext* pImmediateContext = DXUTGetD3D11DeviceContext(); + ClearD3D11DeviceContext( pImmediateContext ); + + // Clear state and flush + pImmediateContext->ClearState(); + pImmediateContext->Flush(); + + // Call the app's SwapChain lost callback + GetDXUTState().SetInsideDeviceCallback( true ); + if( GetDXUTState().GetDeviceObjectsReset() ) + { + LPDXUTCALLBACKD3D11SWAPCHAINRELEASING pCallbackSwapChainReleasing = + GetDXUTState().GetD3D11SwapChainReleasingFunc(); + if( pCallbackSwapChainReleasing != NULL ) + pCallbackSwapChainReleasing( GetDXUTState().GetD3D11SwapChainReleasingFuncUserContext() ); + GetDXUTState().SetDeviceObjectsReset( false ); + } + + // Release our old depth stencil texture and view + ID3D11Texture2D* pDS = GetDXUTState().GetD3D11DepthStencil(); + SAFE_RELEASE( pDS ); + GetDXUTState().SetD3D11DepthStencil( NULL ); + ID3D11DepthStencilView* pDSV = GetDXUTState().GetD3D11DepthStencilView(); + SAFE_RELEASE( pDSV ); + GetDXUTState().SetD3D11DepthStencilView( NULL ); + + // Cleanup the render target view + ID3D11RenderTargetView* pRTV = GetDXUTState().GetD3D11RenderTargetView(); + SAFE_RELEASE( pRTV ); + GetDXUTState().SetD3D11RenderTargetView( NULL ); + + // Call the app's device destroyed callback + if( GetDXUTState().GetDeviceObjectsCreated() ) + { + LPDXUTCALLBACKD3D11DEVICEDESTROYED pCallbackDeviceDestroyed = GetDXUTState().GetD3D11DeviceDestroyedFunc(); + if( pCallbackDeviceDestroyed != NULL ) + pCallbackDeviceDestroyed( GetDXUTState().GetD3D11DeviceDestroyedFuncUserContext() ); + GetDXUTState().SetDeviceObjectsCreated( false ); + } + + GetDXUTState().SetInsideDeviceCallback( false ); + + // Release the swap chain + GetDXUTState().SetReleasingSwapChain( true ); + IDXGISwapChain* pSwapChain = DXUTGetDXGISwapChain(); + if( pSwapChain ) + { + pSwapChain->SetFullscreenState( FALSE, 0 ); + } + SAFE_RELEASE( pSwapChain ); + GetDXUTState().SetDXGISwapChain( NULL ); + GetDXUTState().SetReleasingSwapChain( false ); + + // Release the outputs. + IDXGIOutput** ppOutputArray = GetDXUTState().GetDXGIOutputArray(); + UINT OutputCount = GetDXUTState().GetDXGIOutputArraySize(); + for( UINT o = 0; o < OutputCount; ++o ) + SAFE_RELEASE( ppOutputArray[o] ); + delete[] ppOutputArray; + GetDXUTState().SetDXGIOutputArray( NULL ); + GetDXUTState().SetDXGIOutputArraySize( 0 ); + + // Release the D3D adapter. + IDXGIAdapter* pAdapter = GetDXUTState().GetDXGIAdapter(); + SAFE_RELEASE( pAdapter ); + GetDXUTState().SetDXGIAdapter( NULL ); + + // Release the counters + //DXUTDestroyD3D11Counters(); + + // Release the D3D11 immediate context (if it exists) because it has a extra ref count on it + ID3D11DeviceContext* pd3d11DeviceContext = GetDXUTState().GetD3D11DeviceContext(); + SAFE_RELEASE( pd3d11DeviceContext ); + GetDXUTState().SetD3D11DeviceContext( NULL ); + + // Release the D3D device and in debug configs, displays a message box if there + // are unrelease objects. + if( pd3dDevice ) + { + UINT references = pd3dDevice->Release(); + if( references > 0 ) + { + DXUTDisplayErrorMessage( DXUTERR_NONZEROREFCOUNT ); + DXUT_ERR( L"DXUTCleanup3DEnvironment", DXUTERR_NONZEROREFCOUNT ); + } + } + GetDXUTState().SetD3D11Device( NULL ); + + if( bReleaseSettings ) + { + DXUTDeviceSettings* pOldDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); + SAFE_DELETE(pOldDeviceSettings); + GetDXUTState().SetCurrentDeviceSettings( NULL ); + } + + DXGI_SURFACE_DESC* pBackBufferSurfaceDesc = GetDXUTState().GetBackBufferSurfaceDescDXGI(); + ZeroMemory( pBackBufferSurfaceDesc, sizeof( DXGI_SURFACE_DESC ) ); + + GetDXUTState().SetDeviceCreated( false ); + } +} + + +//-------------------------------------------------------------------------------------- +// Low level keyboard hook to disable Windows key to prevent accidental task switching. +//-------------------------------------------------------------------------------------- +LRESULT CALLBACK DXUTLowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam ) +{ + if( nCode < 0 || nCode != HC_ACTION ) // do not process message + return CallNextHookEx( GetDXUTState().GetKeyboardHook(), nCode, wParam, lParam ); + + bool bEatKeystroke = false; + KBDLLHOOKSTRUCT* p = ( KBDLLHOOKSTRUCT* )lParam; + switch( wParam ) + { + case WM_KEYDOWN: + case WM_KEYUP: + { + bEatKeystroke = ( !GetDXUTState().GetAllowShortcutKeys() && + ( p->vkCode == VK_LWIN || p->vkCode == VK_RWIN ) ); + break; + } + } + + if( bEatKeystroke ) + return 1; + else + return CallNextHookEx( GetDXUTState().GetKeyboardHook(), nCode, wParam, lParam ); +} + + + +//-------------------------------------------------------------------------------------- +// Controls how DXUT behaves when fullscreen and windowed mode with regard to +// shortcut keys (Windows keys, StickyKeys shortcut, ToggleKeys shortcut, FilterKeys shortcut) +//-------------------------------------------------------------------------------------- +void WINAPI DXUTSetShortcutKeySettings( bool bAllowWhenFullscreen, bool bAllowWhenWindowed ) +{ + GetDXUTState().SetAllowShortcutKeysWhenWindowed( bAllowWhenWindowed ); + GetDXUTState().SetAllowShortcutKeysWhenFullscreen( bAllowWhenFullscreen ); + + // DXUTInit() records initial accessibility states so don't change them until then + if( GetDXUTState().GetDXUTInited() ) + { + if( DXUTIsWindowed() ) + DXUTAllowShortcutKeys( GetDXUTState().GetAllowShortcutKeysWhenWindowed() ); + else + DXUTAllowShortcutKeys( GetDXUTState().GetAllowShortcutKeysWhenFullscreen() ); + } +} + + +//-------------------------------------------------------------------------------------- +// Enables/disables Windows keys, and disables or restores the StickyKeys/ToggleKeys/FilterKeys +// shortcut to help prevent accidental task switching +//-------------------------------------------------------------------------------------- +void DXUTAllowShortcutKeys( bool bAllowKeys ) +{ + GetDXUTState().SetAllowShortcutKeys( bAllowKeys ); + + if( bAllowKeys ) + { + // Restore StickyKeys/etc to original state and enable Windows key + STICKYKEYS sk = GetDXUTState().GetStartupStickyKeys(); + TOGGLEKEYS tk = GetDXUTState().GetStartupToggleKeys(); + FILTERKEYS fk = GetDXUTState().GetStartupFilterKeys(); + + SystemParametersInfo( SPI_SETSTICKYKEYS, sizeof( STICKYKEYS ), &sk, 0 ); + SystemParametersInfo( SPI_SETTOGGLEKEYS, sizeof( TOGGLEKEYS ), &tk, 0 ); + SystemParametersInfo( SPI_SETFILTERKEYS, sizeof( FILTERKEYS ), &fk, 0 ); + + // Remove the keyboard hoook when it isn't needed to prevent any slow down of other apps + if( GetDXUTState().GetKeyboardHook() ) + { + UnhookWindowsHookEx( GetDXUTState().GetKeyboardHook() ); + GetDXUTState().SetKeyboardHook( NULL ); + } + } + else + { + // Set low level keyboard hook if haven't already + if( GetDXUTState().GetKeyboardHook() == NULL ) + { + // Set the low-level hook procedure. Only works on Windows 2000 and above + OSVERSIONINFO OSVersionInfo; + OSVersionInfo.dwOSVersionInfoSize = sizeof( OSVersionInfo ); + GetVersionEx( &OSVersionInfo ); + if( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && OSVersionInfo.dwMajorVersion > 4 ) + { + HHOOK hKeyboardHook = SetWindowsHookEx( WH_KEYBOARD_LL, DXUTLowLevelKeyboardProc, + GetModuleHandle( NULL ), 0 ); + GetDXUTState().SetKeyboardHook( hKeyboardHook ); + } + } + + // Disable StickyKeys/etc shortcuts but if the accessibility feature is on, + // then leave the settings alone as its probably being usefully used + + STICKYKEYS skOff = GetDXUTState().GetStartupStickyKeys(); + if( ( skOff.dwFlags & SKF_STICKYKEYSON ) == 0 ) + { + // Disable the hotkey and the confirmation + skOff.dwFlags &= ~SKF_HOTKEYACTIVE; + skOff.dwFlags &= ~SKF_CONFIRMHOTKEY; + + SystemParametersInfo( SPI_SETSTICKYKEYS, sizeof( STICKYKEYS ), &skOff, 0 ); + } + + TOGGLEKEYS tkOff = GetDXUTState().GetStartupToggleKeys(); + if( ( tkOff.dwFlags & TKF_TOGGLEKEYSON ) == 0 ) + { + // Disable the hotkey and the confirmation + tkOff.dwFlags &= ~TKF_HOTKEYACTIVE; + tkOff.dwFlags &= ~TKF_CONFIRMHOTKEY; + + SystemParametersInfo( SPI_SETTOGGLEKEYS, sizeof( TOGGLEKEYS ), &tkOff, 0 ); + } + + FILTERKEYS fkOff = GetDXUTState().GetStartupFilterKeys(); + if( ( fkOff.dwFlags & FKF_FILTERKEYSON ) == 0 ) + { + // Disable the hotkey and the confirmation + fkOff.dwFlags &= ~FKF_HOTKEYACTIVE; + fkOff.dwFlags &= ~FKF_CONFIRMHOTKEY; + + SystemParametersInfo( SPI_SETFILTERKEYS, sizeof( FILTERKEYS ), &fkOff, 0 ); + } + } +} + + +//-------------------------------------------------------------------------------------- +// Pauses time or rendering. Keeps a ref count so pausing can be layered +//-------------------------------------------------------------------------------------- +void WINAPI DXUTPause( bool bPauseTime, bool bPauseRendering ) +{ + int nPauseTimeCount = GetDXUTState().GetPauseTimeCount(); + if( bPauseTime ) nPauseTimeCount++; + else + nPauseTimeCount--; + if( nPauseTimeCount < 0 ) nPauseTimeCount = 0; + GetDXUTState().SetPauseTimeCount( nPauseTimeCount ); + + int nPauseRenderingCount = GetDXUTState().GetPauseRenderingCount(); + if( bPauseRendering ) nPauseRenderingCount++; + else + nPauseRenderingCount--; + if( nPauseRenderingCount < 0 ) nPauseRenderingCount = 0; + GetDXUTState().SetPauseRenderingCount( nPauseRenderingCount ); + + if( nPauseTimeCount > 0 ) + { + // Stop the scene from animating + DXUTGetGlobalTimer()->Stop(); + } + else + { + // Restart the timer + DXUTGetGlobalTimer()->Start(); + } + + GetDXUTState().SetRenderingPaused( nPauseRenderingCount > 0 ); + GetDXUTState().SetTimePaused( nPauseTimeCount > 0 ); +} + + +//-------------------------------------------------------------------------------------- +// Starts a user defined timer callback +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTSetTimer( LPDXUTCALLBACKTIMER pCallbackTimer, float fTimeoutInSecs, UINT* pnIDEvent, + void* pCallbackUserContext ) +{ + if( pCallbackTimer == NULL ) + return DXUT_ERR_MSGBOX( L"DXUTSetTimer", E_INVALIDARG ); + + HRESULT hr; + DXUT_TIMER DXUTTimer; + DXUTTimer.pCallbackTimer = pCallbackTimer; + DXUTTimer.pCallbackUserContext = pCallbackUserContext; + DXUTTimer.fTimeoutInSecs = fTimeoutInSecs; + DXUTTimer.fCountdown = fTimeoutInSecs; + DXUTTimer.bEnabled = true; + DXUTTimer.nID = GetDXUTState().GetTimerLastID() + 1; + GetDXUTState().SetTimerLastID( DXUTTimer.nID ); + + CGrowableArray * pTimerList = GetDXUTState().GetTimerList(); + if( pTimerList == NULL ) + { + pTimerList = new CGrowableArray ; + if( pTimerList == NULL ) + return E_OUTOFMEMORY; + GetDXUTState().SetTimerList( pTimerList ); + } + + if( FAILED( hr = pTimerList->Add( DXUTTimer ) ) ) + return hr; + + if( pnIDEvent ) + *pnIDEvent = DXUTTimer.nID; + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Stops a user defined timer callback +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTKillTimer( UINT nIDEvent ) +{ + CGrowableArray * pTimerList = GetDXUTState().GetTimerList(); + if( pTimerList == NULL ) + return S_FALSE; + + bool bFound = false; + + for( int i = 0; i < pTimerList->GetSize(); i++ ) + { + DXUT_TIMER DXUTTimer = pTimerList->GetAt( i ); + if( DXUTTimer.nID == nIDEvent ) + { + DXUTTimer.bEnabled = false; + pTimerList->SetAt( i, DXUTTimer ); + bFound = true; + break; + } + } + + if( !bFound ) + return DXUT_ERR_MSGBOX( L"DXUTKillTimer", E_INVALIDARG ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Internal helper function to handle calling the user defined timer callbacks +//-------------------------------------------------------------------------------------- +void DXUTHandleTimers() +{ + float fElapsedTime = DXUTGetElapsedTime(); + + CGrowableArray * pTimerList = GetDXUTState().GetTimerList(); + if( pTimerList == NULL ) + return; + + // Walk through the list of timer callbacks + for( int i = 0; i < pTimerList->GetSize(); i++ ) + { + DXUT_TIMER DXUTTimer = pTimerList->GetAt( i ); + if( DXUTTimer.bEnabled ) + { + DXUTTimer.fCountdown -= fElapsedTime; + + // Call the callback if count down expired + if( DXUTTimer.fCountdown < 0 ) + { + DXUTTimer.pCallbackTimer( DXUTTimer.nID, DXUTTimer.pCallbackUserContext ); + // The callback my have changed the timer. + DXUTTimer = pTimerList->GetAt( i ); + DXUTTimer.fCountdown = DXUTTimer.fTimeoutInSecs; + } + pTimerList->SetAt( i, DXUTTimer ); + } + } +} + + +//-------------------------------------------------------------------------------------- +// Display an custom error msg box +//-------------------------------------------------------------------------------------- +void DXUTDisplayErrorMessage( HRESULT hr ) +{ + WCHAR strBuffer[512]; + + int nExitCode; + bool bFound = true; + switch( hr ) + { + case DXUTERR_NODIRECT3D: + { + nExitCode = 2; + if( DXUTDoesAppSupportD3D11() && !DXUTDoesAppSupportD3D9() ) + wcscpy_s( strBuffer, ARRAYSIZE(strBuffer), L"Could not initialize Direct3D 11. " ); + else + wcscpy_s( strBuffer, ARRAYSIZE(strBuffer), L"Could not initialize Direct3D 9. Check that the latest version of DirectX is correctly installed on your system. Also make sure that this program was compiled with header files that match the installed DirectX DLLs." ); + break; + } + case DXUTERR_NOCOMPATIBLEDEVICES: + nExitCode = 3; + if( GetSystemMetrics(0x1000) != 0 ) // SM_REMOTESESSION + wcscpy_s( strBuffer, ARRAYSIZE(strBuffer), L"Direct3D does not work over a remote session." ); + else + wcscpy_s( strBuffer, ARRAYSIZE(strBuffer), L"Could not find any compatible Direct3D devices." ); + break; + case DXUTERR_MEDIANOTFOUND: nExitCode = 4; wcscpy_s( strBuffer, ARRAYSIZE(strBuffer), L"Could not find required media." ); break; + case DXUTERR_NONZEROREFCOUNT: nExitCode = 5; wcscpy_s( strBuffer, ARRAYSIZE(strBuffer), L"The Direct3D device has a non-zero reference count, meaning some objects were not released." ); break; + case DXUTERR_CREATINGDEVICE: nExitCode = 6; wcscpy_s( strBuffer, ARRAYSIZE(strBuffer), L"Failed creating the Direct3D device." ); break; + case DXUTERR_RESETTINGDEVICE: nExitCode = 7; wcscpy_s( strBuffer, ARRAYSIZE(strBuffer), L"Failed resetting the Direct3D device." ); break; + case DXUTERR_CREATINGDEVICEOBJECTS: nExitCode = 8; wcscpy_s( strBuffer, ARRAYSIZE(strBuffer), L"An error occurred in the device create callback function." ); break; + case DXUTERR_RESETTINGDEVICEOBJECTS: nExitCode = 9; wcscpy_s( strBuffer, ARRAYSIZE(strBuffer), L"An error occurred in the device reset callback function." ); break; + // nExitCode 10 means the app exited using a REF device + case DXUTERR_DEVICEREMOVED: nExitCode = 11; wcscpy_s( strBuffer, ARRAYSIZE(strBuffer), L"The Direct3D device was removed." ); break; + default: bFound = false; nExitCode = 1; break; // nExitCode 1 means the API was incorrectly called + + } + + GetDXUTState().SetExitCode(nExitCode); + + bool bShowMsgBoxOnError = GetDXUTState().GetShowMsgBoxOnError(); + if( bFound && bShowMsgBoxOnError ) + { + if( DXUTGetWindowTitle()[0] == 0 ) + MessageBox( DXUTGetHWND(), strBuffer, L"DXUT Application", MB_ICONERROR | MB_OK ); + else + MessageBox( DXUTGetHWND(), strBuffer, DXUTGetWindowTitle(), MB_ICONERROR | MB_OK ); + } +} + + +//-------------------------------------------------------------------------------------- +// Internal function to map MK_* to an array index +//-------------------------------------------------------------------------------------- +int DXUTMapButtonToArrayIndex( BYTE vButton ) +{ + switch( vButton ) + { + case MK_LBUTTON: + return 0; + case VK_MBUTTON: + case MK_MBUTTON: + return 1; + case MK_RBUTTON: + return 2; + case VK_XBUTTON1: + case MK_XBUTTON1: + return 3; + case VK_XBUTTON2: + case MK_XBUTTON2: + return 4; + } + + return 0; +} + + + +//-------------------------------------------------------------------------------------- +// Toggle between full screen and windowed +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTToggleFullScreen() +{ + HRESULT hr; + DXUTDeviceSettings deviceSettings = DXUTGetDeviceSettings(); + DXUTDeviceSettings orginalDeviceSettings = DXUTGetDeviceSettings(); + + if (deviceSettings.ver == DXUT_D3D11_DEVICE) { + deviceSettings.d3d11.sd.Windowed = !deviceSettings.d3d11.sd.Windowed; // datut + if (!deviceSettings.d3d11.sd.Windowed) { + DXGI_MODE_DESC adapterDesktopDisplayMode = + { + 800, 600, { 60, 1 }, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB + }; + DXUTGetD3D11AdapterDisplayMode( deviceSettings.d3d11.AdapterOrdinal, 0, &adapterDesktopDisplayMode ); + + + deviceSettings.d3d11.sd.BufferDesc = adapterDesktopDisplayMode; + }else { + RECT r = DXUTGetWindowClientRectAtModeChange(); + deviceSettings.d3d11.sd.BufferDesc.Height = r.bottom; + deviceSettings.d3d11.sd.BufferDesc.Width = r.right; + } + }else if (deviceSettings.ver == DXUT_D3D9_DEVICE){ + deviceSettings.d3d9.pp.Windowed = !deviceSettings.d3d9.pp.Windowed; + if (!deviceSettings.d3d9.pp.Windowed) { + D3DDISPLAYMODE adapterDesktopDisplayMode; + IDirect3D9* pD3D = DXUTGetD3D9Object(); + DXUTDeviceSettings* pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); + pD3D->GetAdapterDisplayMode( pDeviceSettings->d3d9.AdapterOrdinal, &adapterDesktopDisplayMode ); + deviceSettings.d3d9.pp.BackBufferWidth = adapterDesktopDisplayMode.Width; + deviceSettings.d3d9.pp.BackBufferHeight = adapterDesktopDisplayMode.Height; + deviceSettings.d3d9.pp.BackBufferFormat = adapterDesktopDisplayMode.Format; + } else { + RECT r = DXUTGetWindowClientRectAtModeChange(); + deviceSettings.d3d9.pp.BackBufferHeight= r.bottom; + deviceSettings.d3d9.pp.FullScreen_RefreshRateInHz = 0; + deviceSettings.d3d9.pp.BackBufferWidth = r.right; + } + } + + hr = DXUTChangeDevice( &deviceSettings, NULL, NULL, false, false ); + + // If hr == E_ABORT, this means the app rejected the device settings in the ModifySettingsCallback so nothing changed + if( FAILED( hr ) && ( hr != E_ABORT ) ) + { + // Failed creating device, try to switch back. + HRESULT hr2 = DXUTChangeDevice( &orginalDeviceSettings, NULL, NULL, false, false ); + if( FAILED( hr2 ) ) + { + // If this failed, then shutdown + DXUTShutdown(); + } + } + + return hr; +} + + +//-------------------------------------------------------------------------------------- +// Toggle between HAL and WARP +//-------------------------------------------------------------------------------------- + +HRESULT WINAPI DXUTToggleWARP () { + HRESULT hr; + + DXUTDeviceSettings deviceSettings = DXUTGetDeviceSettings(); + DXUTDeviceSettings orginalDeviceSettings = DXUTGetDeviceSettings(); + + // Toggle between REF & HAL + if( DXUTIsCurrentDeviceD3D9() ) + { + + } + else + { + ID3D11SwitchToRef* pD3D11STR = NULL; + hr = DXUTGetD3D11Device()->QueryInterface( __uuidof( *pD3D11STR ), ( LPVOID* )&pD3D11STR ); + if( SUCCEEDED( hr ) ) + { + pD3D11STR->SetUseRef( pD3D11STR->GetUseRef() ? FALSE : TRUE ); + SAFE_RELEASE( pD3D11STR ); + return S_OK; + } + + if( deviceSettings.d3d11.DriverType == D3D_DRIVER_TYPE_HARDWARE || deviceSettings.d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE ) + deviceSettings.d3d11.DriverType = D3D_DRIVER_TYPE_WARP; + else if( deviceSettings.d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE || deviceSettings.d3d11.DriverType == D3D_DRIVER_TYPE_WARP ) + deviceSettings.d3d11.DriverType = D3D_DRIVER_TYPE_HARDWARE; + } + + hr = DXUTSnapDeviceSettingsToEnumDevice(&deviceSettings, false); + if( SUCCEEDED( hr ) ) + { + // Create a Direct3D device using the new device settings. + // If there is an existing device, then it will either reset or recreate the scene. + hr = DXUTChangeDevice( &deviceSettings, NULL, NULL, false, false ); + + // If hr == E_ABORT, this means the app rejected the device settings in the ModifySettingsCallback so nothing changed + if( FAILED( hr ) && ( hr != E_ABORT ) ) + { + // Failed creating device, try to switch back. + HRESULT hr2 = DXUTChangeDevice( &orginalDeviceSettings, NULL, NULL, false, false ); + if( FAILED( hr2 ) ) + { + // If this failed, then shutdown + DXUTShutdown(); + } + } + } + + return hr; +} +//-------------------------------------------------------------------------------------- +// Toggle between HAL and REF +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTToggleREF() +{ + HRESULT hr; + + DXUTDeviceSettings deviceSettings = DXUTGetDeviceSettings(); + DXUTDeviceSettings orginalDeviceSettings = DXUTGetDeviceSettings(); + + // Toggle between REF & HAL + if( DXUTIsCurrentDeviceD3D9() ) + { + if( deviceSettings.d3d9.DeviceType == D3DDEVTYPE_HAL ) + deviceSettings.d3d9.DeviceType = D3DDEVTYPE_REF; + else if( deviceSettings.d3d9.DeviceType == D3DDEVTYPE_REF ) + deviceSettings.d3d9.DeviceType = D3DDEVTYPE_HAL; + } + else + { + ID3D11SwitchToRef* pD3D11STR = NULL; + hr = DXUTGetD3D11Device()->QueryInterface( __uuidof( *pD3D11STR ), ( LPVOID* )&pD3D11STR ); + if( SUCCEEDED( hr ) ) + { + pD3D11STR->SetUseRef( pD3D11STR->GetUseRef() ? FALSE : TRUE ); + SAFE_RELEASE( pD3D11STR ); + return S_OK; + } + + if( deviceSettings.d3d11.DriverType == D3D_DRIVER_TYPE_HARDWARE ) + deviceSettings.d3d11.DriverType = D3D_DRIVER_TYPE_REFERENCE; + else if( deviceSettings.d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE ) + deviceSettings.d3d11.DriverType = D3D_DRIVER_TYPE_HARDWARE; + } + + hr = DXUTSnapDeviceSettingsToEnumDevice(&deviceSettings, false); + if( SUCCEEDED( hr ) ) + { + // Create a Direct3D device using the new device settings. + // If there is an existing device, then it will either reset or recreate the scene. + hr = DXUTChangeDevice( &deviceSettings, NULL, NULL, false, false ); + + // If hr == E_ABORT, this means the app rejected the device settings in the ModifySettingsCallback so nothing changed + if( FAILED( hr ) && ( hr != E_ABORT ) ) + { + // Failed creating device, try to switch back. + HRESULT hr2 = DXUTChangeDevice( &orginalDeviceSettings, NULL, NULL, false, false ); + if( FAILED( hr2 ) ) + { + // If this failed, then shutdown + DXUTShutdown(); + } + } + } + + return hr; +} + +//-------------------------------------------------------------------------------------- +// Checks to see if DXGI has switched us out of fullscreen or windowed mode +//-------------------------------------------------------------------------------------- +void DXUTCheckForDXGIFullScreenSwitch() +{ + DXUTDeviceSettings* pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); + if( !DXUTIsD3D9( pDeviceSettings ) ) + { + IDXGISwapChain* pSwapChain = DXUTGetDXGISwapChain(); + DXGI_SWAP_CHAIN_DESC SCDesc; + pSwapChain->GetDesc( &SCDesc ); + + BOOL bIsWindowed = ( BOOL )DXUTIsWindowed(); + if( bIsWindowed != SCDesc.Windowed ) + { + pDeviceSettings->d3d11.sd.Windowed = SCDesc.Windowed; + + DXUTDeviceSettings deviceSettings = DXUTGetDeviceSettings(); + + if( bIsWindowed ) + { + GetDXUTState().SetWindowBackBufferWidthAtModeChange( deviceSettings.d3d11.sd.BufferDesc.Width ); + GetDXUTState().SetWindowBackBufferHeightAtModeChange( deviceSettings.d3d11.sd.BufferDesc.Height ); + } + else + { + GetDXUTState().SetFullScreenBackBufferWidthAtModeChange( deviceSettings.d3d11.sd.BufferDesc.Width ); + GetDXUTState().SetFullScreenBackBufferHeightAtModeChange( deviceSettings.d3d11.sd.BufferDesc.Height ); + } + } + } +} + +void DXUTResizeDXGIBuffers( UINT Width, UINT Height, BOOL bFullScreen ) +{ + HRESULT hr = S_OK; + RECT rcCurrentClient; + GetClientRect( DXUTGetHWND(), &rcCurrentClient ); + + DXUTDeviceSettings* pDevSettings = GetDXUTState().GetCurrentDeviceSettings(); + IDXGISwapChain* pSwapChain = DXUTGetDXGISwapChain(); + + ID3D11Device* pd3dDevice = DXUTGetD3D11Device(); + ID3D11DeviceContext* pd3dImmediateContext = DXUTGetD3D11DeviceContext(); + + // Determine if we're fullscreen + pDevSettings->d3d11.sd.Windowed = !bFullScreen; + + // Call releasing + GetDXUTState().SetInsideDeviceCallback( true ); + LPDXUTCALLBACKD3D11SWAPCHAINRELEASING pCallbackSwapChainReleasing = GetDXUTState().GetD3D11SwapChainReleasingFunc + (); + if( pCallbackSwapChainReleasing != NULL ) + pCallbackSwapChainReleasing( GetDXUTState().GetD3D11SwapChainResizedFuncUserContext() ); + GetDXUTState().SetInsideDeviceCallback( false ); + + // Release our old depth stencil texture and view + ID3D11Texture2D* pDS = GetDXUTState().GetD3D11DepthStencil(); + SAFE_RELEASE( pDS ); + GetDXUTState().SetD3D11DepthStencil( NULL ); + ID3D11DepthStencilView* pDSV = GetDXUTState().GetD3D11DepthStencilView(); + SAFE_RELEASE( pDSV ); + GetDXUTState().SetD3D11DepthStencilView( NULL ); + + // Release our old render target view + ID3D11RenderTargetView* pRTV = GetDXUTState().GetD3D11RenderTargetView(); + SAFE_RELEASE( pRTV ); + GetDXUTState().SetD3D11RenderTargetView( NULL ); + + // Alternate between 0 and DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH when resizing buffers. + // When in windowed mode, we want 0 since this allows the app to change to the desktop + // resolution from windowed mode during alt+enter. However, in fullscreen mode, we want + // the ability to change display modes from the Device Settings dialog. Therefore, we + // want to set the DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH flag. + UINT Flags = 0; + if( bFullScreen ) + Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + + // ResizeBuffers + V( pSwapChain->ResizeBuffers( pDevSettings->d3d11.sd.BufferCount, + Width, + Height, + pDevSettings->d3d11.sd.BufferDesc.Format, + Flags ) ); + + if( !GetDXUTState().GetDoNotStoreBufferSize() ) + { + pDevSettings->d3d11.sd.BufferDesc.Width = ( UINT )rcCurrentClient.right; + pDevSettings->d3d11.sd.BufferDesc.Height = ( UINT )rcCurrentClient.bottom; + } + + // Save off backbuffer desc + DXUTUpdateBackBufferDesc(); + + // Update the device stats text + DXUTUpdateStaticFrameStats(); + + // Setup the render target view and viewport + hr = DXUTCreateD3D11Views( pd3dDevice, pd3dImmediateContext, pDevSettings ); + if( FAILED( hr ) ) + { + DXUT_ERR( L"DXUTCreateD3D11Views", hr ); + return; + } + + // Setup cursor based on current settings (window/fullscreen mode, show cursor state, clip cursor state) + DXUTSetupCursor(); + + // Call the app's SwapChain reset callback + GetDXUTState().SetInsideDeviceCallback( true ); + const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc = DXUTGetDXGIBackBufferSurfaceDesc(); + LPDXUTCALLBACKD3D11SWAPCHAINRESIZED pCallbackSwapChainResized = GetDXUTState().GetD3D11SwapChainResizedFunc(); + hr = S_OK; + if( pCallbackSwapChainResized != NULL ) + hr = pCallbackSwapChainResized( pd3dDevice, pSwapChain, pBackBufferSurfaceDesc, + GetDXUTState().GetD3D11SwapChainResizedFuncUserContext() ); + GetDXUTState().SetInsideDeviceCallback( false ); + if( FAILED( hr ) ) + { + // If callback failed, cleanup + DXUT_ERR( L"DeviceResetCallback", hr ); + if( hr != DXUTERR_MEDIANOTFOUND ) + hr = DXUTERR_RESETTINGDEVICEOBJECTS; + + GetDXUTState().SetInsideDeviceCallback( true ); + LPDXUTCALLBACKD3D11SWAPCHAINRELEASING pCallbackSwapChainReleasing = + GetDXUTState().GetD3D11SwapChainReleasingFunc(); + if( pCallbackSwapChainReleasing != NULL ) + pCallbackSwapChainReleasing( GetDXUTState().GetD3D11SwapChainResizedFuncUserContext() ); + GetDXUTState().SetInsideDeviceCallback( false ); + DXUTPause( false, false ); + PostQuitMessage( 0 ); + } + else + { + GetDXUTState().SetDeviceObjectsReset( true ); + DXUTPause( false, false ); + } +} + +//-------------------------------------------------------------------------------------- +// Checks if DXGI buffers need to change +//-------------------------------------------------------------------------------------- +void DXUTCheckForDXGIBufferChange() +{ + if(DXUTGetDXGISwapChain() != NULL && !GetDXUTState().GetReleasingSwapChain() ) + { + //DXUTgetdxgi + IDXGISwapChain* pSwapChain = DXUTGetDXGISwapChain(); + + // Determine if we're fullscreen + BOOL bFullScreen; + pSwapChain->GetFullscreenState( &bFullScreen, NULL ); + + DXUTResizeDXGIBuffers( 0, 0, bFullScreen ); + + ShowWindow( DXUTGetHWND(), SW_SHOW ); + } +} + +//-------------------------------------------------------------------------------------- +// Checks if the window client rect has changed and if it has, then reset the device +//-------------------------------------------------------------------------------------- +void DXUTCheckForWindowSizeChange() +{ + // Skip the check for various reasons + + if( GetDXUTState().GetIgnoreSizeChange() || !GetDXUTState().GetDeviceCreated() || + ( DXUTIsCurrentDeviceD3D9() && !DXUTIsWindowed() ) ) + return; + + DXUTDeviceSettings deviceSettings = DXUTGetDeviceSettings(); + if( DXUTIsD3D9( &deviceSettings ) ) + { + RECT rcCurrentClient; + GetClientRect( DXUTGetHWND(), &rcCurrentClient ); + + if( ( UINT )rcCurrentClient.right != DXUTGetBackBufferWidthFromDS( &deviceSettings ) || + ( UINT )rcCurrentClient.bottom != DXUTGetBackBufferHeightFromDS( &deviceSettings ) ) + { + // A new window size will require a new backbuffer size size + // Tell DXUTChangeDevice and D3D to size according to the HWND's client rect + if( DXUTIsD3D9( &deviceSettings ) ) deviceSettings.d3d9.pp.BackBufferWidth = 0; else deviceSettings.d3d11.sd.BufferDesc.Width = 0; + if( DXUTIsD3D9( &deviceSettings ) ) deviceSettings.d3d9.pp.BackBufferHeight = 0; else deviceSettings.d3d11.sd.BufferDesc.Height = 0; + + DXUTChangeDevice( &deviceSettings, NULL, NULL, false, false ); + } + } + else + { + DXUTCheckForDXGIBufferChange(); + } +} + + +//-------------------------------------------------------------------------------------- +// Checks to see if the HWND changed monitors, and if it did it creates a device +// from the monitor's adapter and recreates the scene. +//-------------------------------------------------------------------------------------- +void DXUTCheckForWindowChangingMonitors() +{ + // Skip this check for various reasons + if( !GetDXUTState().GetAutoChangeAdapter() || + GetDXUTState().GetIgnoreSizeChange() || !GetDXUTState().GetDeviceCreated() || !DXUTIsWindowed() ) + return; + + HRESULT hr; + HMONITOR hWindowMonitor = DXUTMonitorFromWindow( DXUTGetHWND(), MONITOR_DEFAULTTOPRIMARY ); + HMONITOR hAdapterMonitor = GetDXUTState().GetAdapterMonitor(); + if( hWindowMonitor != hAdapterMonitor ) + { + UINT newOrdinal; + if( SUCCEEDED( DXUTGetAdapterOrdinalFromMonitor( hWindowMonitor, &newOrdinal ) ) ) + { + // Find the closest valid device settings with the new ordinal + DXUTDeviceSettings deviceSettings = DXUTGetDeviceSettings(); + if( DXUTIsD3D9( &deviceSettings ) ) + { + deviceSettings.d3d9.AdapterOrdinal = newOrdinal; + } + else + { + deviceSettings.d3d11.AdapterOrdinal = newOrdinal; + UINT newOutput; + if( SUCCEEDED( DXUTGetOutputOrdinalFromMonitor( hWindowMonitor, &newOutput ) ) ) + deviceSettings.d3d11.Output = newOutput; + } + + hr = DXUTSnapDeviceSettingsToEnumDevice( &deviceSettings, false ); + if( SUCCEEDED( hr ) ) + { + // Create a Direct3D device using the new device settings. + // If there is an existing device, then it will either reset or recreate the scene. + hr = DXUTChangeDevice( &deviceSettings, NULL, NULL, false, false ); + + // If hr == E_ABORT, this means the app rejected the device settings in the ModifySettingsCallback + if( hr == E_ABORT ) + { + // so nothing changed and keep from attempting to switch adapters next time + GetDXUTState().SetAutoChangeAdapter( false ); + } + else if( FAILED( hr ) ) + { + DXUTShutdown(); + DXUTPause( false, false ); + return; + } + } + } + } +} + + +//-------------------------------------------------------------------------------------- +// Renders the scene using either D3D9 or D3D11 +//-------------------------------------------------------------------------------------- +void WINAPI DXUTRender3DEnvironment() +{ + if( DXUTIsCurrentDeviceD3D9() ) + DXUTRender3DEnvironment9(); + else + DXUTRender3DEnvironment11(); +} + + +//-------------------------------------------------------------------------------------- +// Cleans up both the D3D9 and D3D11 3D environment (but only one should be active at a time) +//-------------------------------------------------------------------------------------- +void DXUTCleanup3DEnvironment( bool bReleaseSettings ) +{ + if( DXUTGetD3D9Device() ) + DXUTCleanup3DEnvironment9( bReleaseSettings ); + if( DXUTGetD3D11Device() ) + DXUTCleanup3DEnvironment11( bReleaseSettings ); +} + + +//-------------------------------------------------------------------------------------- +// Returns the HMONITOR attached to an adapter/output +//-------------------------------------------------------------------------------------- +HMONITOR DXUTGetMonitorFromAdapter( DXUTDeviceSettings* pDeviceSettings ) +{ + if( pDeviceSettings->ver == DXUT_D3D9_DEVICE ) + { + IDirect3D9* pD3D = DXUTGetD3D9Object(); + return pD3D->GetAdapterMonitor( pDeviceSettings->d3d9.AdapterOrdinal ); + } + else if( pDeviceSettings->ver == DXUT_D3D11_DEVICE ) + { + CD3D11Enumeration* pD3DEnum = DXUTGetD3D11Enumeration(); + CD3D11EnumOutputInfo* pOutputInfo = pD3DEnum->GetOutputInfo( pDeviceSettings->d3d11.AdapterOrdinal, + pDeviceSettings->d3d11.Output ); + if( !pOutputInfo ) + return 0; + return DXUTMonitorFromRect( &pOutputInfo->Desc.DesktopCoordinates, MONITOR_DEFAULTTONEAREST ); + } + + return 0; +} + + +//-------------------------------------------------------------------------------------- +// Look for an adapter ordinal that is tied to a HMONITOR +//-------------------------------------------------------------------------------------- +HRESULT DXUTGetAdapterOrdinalFromMonitor( HMONITOR hMonitor, UINT* pAdapterOrdinal ) +{ + *pAdapterOrdinal = 0; + + if( DXUTIsCurrentDeviceD3D9() ) + { + CD3D9Enumeration* pd3dEnum = DXUTGetD3D9Enumeration(); + IDirect3D9* pD3D = DXUTGetD3D9Object(); + + CGrowableArray * pAdapterList = pd3dEnum->GetAdapterInfoList(); + for( int iAdapter = 0; iAdapter < pAdapterList->GetSize(); iAdapter++ ) + { + CD3D9EnumAdapterInfo* pAdapterInfo = pAdapterList->GetAt( iAdapter ); + HMONITOR hAdapterMonitor = pD3D->GetAdapterMonitor( pAdapterInfo->AdapterOrdinal ); + if( hAdapterMonitor == hMonitor ) + { + *pAdapterOrdinal = pAdapterInfo->AdapterOrdinal; + return S_OK; + } + } + } + else + { + // Get the monitor handle information + MONITORINFOEX mi; + mi.cbSize = sizeof( MONITORINFOEX ); + DXUTGetMonitorInfo( hMonitor, &mi ); + + // Search for this monitor in our enumeration hierarchy. + CD3D11Enumeration* pd3dEnum = DXUTGetD3D11Enumeration(); + CGrowableArray * pAdapterList = pd3dEnum->GetAdapterInfoList(); + for( int iAdapter = 0; iAdapter < pAdapterList->GetSize(); ++iAdapter ) + { + CD3D11EnumAdapterInfo* pAdapterInfo = pAdapterList->GetAt( iAdapter ); + for( int o = 0; o < pAdapterInfo->outputInfoList.GetSize(); ++o ) + { + CD3D11EnumOutputInfo* pOutputInfo = pAdapterInfo->outputInfoList.GetAt( o ); + // Convert output device name from MBCS to Unicode + if( wcsncmp( pOutputInfo->Desc.DeviceName, mi.szDevice, sizeof( mi.szDevice ) / sizeof + ( mi.szDevice[0] ) ) == 0 ) + { + *pAdapterOrdinal = pAdapterInfo->AdapterOrdinal; + return S_OK; + } + } + } + } + + return E_FAIL; +} + +//-------------------------------------------------------------------------------------- +// Look for a monitor ordinal that is tied to a HMONITOR (D3D11-only) +//-------------------------------------------------------------------------------------- +HRESULT DXUTGetOutputOrdinalFromMonitor( HMONITOR hMonitor, UINT* pOutputOrdinal ) +{ + // Get the monitor handle information + MONITORINFOEX mi; + mi.cbSize = sizeof( MONITORINFOEX ); + DXUTGetMonitorInfo( hMonitor, &mi ); + + // Search for this monitor in our enumeration hierarchy. + CD3D11Enumeration* pd3dEnum = DXUTGetD3D11Enumeration(); + CGrowableArray * pAdapterList = pd3dEnum->GetAdapterInfoList(); + for( int iAdapter = 0; iAdapter < pAdapterList->GetSize(); ++iAdapter ) + { + CD3D11EnumAdapterInfo* pAdapterInfo = pAdapterList->GetAt( iAdapter ); + for( int o = 0; o < pAdapterInfo->outputInfoList.GetSize(); ++o ) + { + CD3D11EnumOutputInfo* pOutputInfo = pAdapterInfo->outputInfoList.GetAt( o ); + DXGI_OUTPUT_DESC Desc; + pOutputInfo->m_pOutput->GetDesc( &Desc ); + + if( hMonitor == Desc.Monitor ) + { + *pOutputOrdinal = pOutputInfo->Output; + return S_OK; + } + } + } + + return E_FAIL; +} + +//-------------------------------------------------------------------------------------- +// This method is called when D3DERR_DEVICEREMOVED is returned from an API. DXUT +// calls the application's DeviceRemoved callback to inform it of the event. The +// application returns true if it wants DXUT to look for a closest device to run on. +// If no device is found, or the app returns false, DXUT shuts down. +//-------------------------------------------------------------------------------------- +HRESULT DXUTHandleDeviceRemoved() +{ + HRESULT hr = S_OK; + + // Device has been removed. Call the application's callback if set. If no callback + // has been set, then just look for a new device + bool bLookForNewDevice = true; + LPDXUTCALLBACKDEVICEREMOVED pDeviceRemovedFunc = GetDXUTState().GetDeviceRemovedFunc(); + if( pDeviceRemovedFunc ) + bLookForNewDevice = pDeviceRemovedFunc( GetDXUTState().GetDeviceRemovedFuncUserContext() ); + + if( bLookForNewDevice ) + { + DXUTDeviceSettings* pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); + + + hr = DXUTSnapDeviceSettingsToEnumDevice( pDeviceSettings, false); + if( SUCCEEDED( hr ) ) + { + // Change to a Direct3D device created from the new device settings + // that is compatible with the removed device. + hr = DXUTChangeDevice( pDeviceSettings, NULL, NULL, true, false ); + if( SUCCEEDED( hr ) ) + return S_OK; + } + } + + // The app does not wish to continue or continuing is not possible. + return DXUTERR_DEVICEREMOVED; +} + + +//-------------------------------------------------------------------------------------- +// Stores back buffer surface desc in GetDXUTState().GetBackBufferSurfaceDesc10() +//-------------------------------------------------------------------------------------- +void DXUTUpdateBackBufferDesc() +{ + if( DXUTIsCurrentDeviceD3D9() ) + { + HRESULT hr; + IDirect3DSurface9* pBackBuffer; + hr = GetDXUTState().GetD3D9Device()->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer ); + D3DSURFACE_DESC* pBBufferSurfaceDesc = GetDXUTState().GetBackBufferSurfaceDesc9(); + ZeroMemory( pBBufferSurfaceDesc, sizeof( D3DSURFACE_DESC ) ); + if( SUCCEEDED( hr ) ) + { + pBackBuffer->GetDesc( pBBufferSurfaceDesc ); + SAFE_RELEASE( pBackBuffer ); + } + } + else + { + HRESULT hr; + ID3D11Texture2D* pBackBuffer; + hr = GetDXUTState().GetDXGISwapChain()->GetBuffer( 0, __uuidof( *pBackBuffer ), ( LPVOID* )&pBackBuffer ); + DXGI_SURFACE_DESC* pBBufferSurfaceDesc = GetDXUTState().GetBackBufferSurfaceDescDXGI(); + ZeroMemory( pBBufferSurfaceDesc, sizeof( DXGI_SURFACE_DESC ) ); + if( SUCCEEDED( hr ) ) + { + D3D11_TEXTURE2D_DESC TexDesc; + pBackBuffer->GetDesc( &TexDesc ); + pBBufferSurfaceDesc->Width = ( UINT )TexDesc.Width; + pBBufferSurfaceDesc->Height = ( UINT )TexDesc.Height; + pBBufferSurfaceDesc->Format = TexDesc.Format; + pBBufferSurfaceDesc->SampleDesc = TexDesc.SampleDesc; + SAFE_RELEASE( pBackBuffer ); + } + } +} + + +//-------------------------------------------------------------------------------------- +// Setup cursor based on current settings (window/fullscreen mode, show cursor state, clip cursor state) +//-------------------------------------------------------------------------------------- +void DXUTSetupCursor() +{ + if( DXUTIsCurrentDeviceD3D9() ) + { + // Show the cursor again if returning to fullscreen + IDirect3DDevice9* pd3dDevice = DXUTGetD3D9Device(); + if( !DXUTIsWindowed() && pd3dDevice ) + { + if( GetDXUTState().GetShowCursorWhenFullScreen() ) + { + SetCursor( NULL ); // Turn off Windows cursor in full screen mode + HCURSOR hCursor = ( HCURSOR )( ULONG_PTR )GetClassLongPtr( DXUTGetHWNDDeviceFullScreen(), + GCLP_HCURSOR ); + DXUTSetD3D9DeviceCursor( pd3dDevice, hCursor, false ); + DXUTGetD3D9Device()->ShowCursor( true ); + } + else + { + SetCursor( NULL ); // Turn off Windows cursor in full screen mode + DXUTGetD3D9Device()->ShowCursor( false ); + } + } + + // Clip cursor if requested + if( !DXUTIsWindowed() && GetDXUTState().GetClipCursorWhenFullScreen() ) + { + // Confine cursor to full screen window + RECT rcWindow; + GetWindowRect( DXUTGetHWNDDeviceFullScreen(), &rcWindow ); + ClipCursor( &rcWindow ); + } + else + { + ClipCursor( NULL ); + } + } + else + { + // Clip cursor if requested + if( !DXUTIsWindowed() && GetDXUTState().GetClipCursorWhenFullScreen() ) + { + // Confine cursor to full screen window + RECT rcWindow; + GetWindowRect( DXUTGetHWNDDeviceFullScreen(), &rcWindow ); + ClipCursor( &rcWindow ); + } + else + { + ClipCursor( NULL ); + } + } +} + + +//-------------------------------------------------------------------------------------- +// Updates the static part of the frame stats so it doesn't have be generated every frame +//-------------------------------------------------------------------------------------- +void DXUTUpdateStaticFrameStats() +{ + if( GetDXUTState().GetNoStats() ) + return; + + DXUTDeviceSettings* pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); + if( NULL == pDeviceSettings ) + return; + + if( DXUTIsD3D9( pDeviceSettings ) ) + { + CD3D9Enumeration* pd3dEnum = DXUTGetD3D9Enumeration(); + if( NULL == pd3dEnum ) + return; + + CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo = pd3dEnum->GetDeviceSettingsCombo( + pDeviceSettings->d3d9.AdapterOrdinal, pDeviceSettings->d3d9.DeviceType, + pDeviceSettings->d3d9.AdapterFormat, pDeviceSettings->d3d9.pp.BackBufferFormat, + pDeviceSettings->d3d9.pp.Windowed ); + if( NULL == pDeviceSettingsCombo ) + return; + + WCHAR strFmt[100]; + D3DPRESENT_PARAMETERS* pPP = &pDeviceSettings->d3d9.pp; + + if( pDeviceSettingsCombo->AdapterFormat == pDeviceSettingsCombo->BackBufferFormat ) + { + wcscpy_s( strFmt, 100, DXUTD3DFormatToString( pDeviceSettingsCombo->AdapterFormat, false ) ); + } + else + { + swprintf_s( strFmt, 100, L"backbuf %s, adapter %s", + DXUTD3DFormatToString( pDeviceSettingsCombo->BackBufferFormat, false ), + DXUTD3DFormatToString( pDeviceSettingsCombo->AdapterFormat, false ) ); + } + + WCHAR strDepthFmt[100]; + if( pPP->EnableAutoDepthStencil ) + { + swprintf_s( strDepthFmt, 100, L" (%s)", DXUTD3DFormatToString( pPP->AutoDepthStencilFormat, false ) ); + } + else + { + // No depth buffer + strDepthFmt[0] = 0; + } + + WCHAR strMultiSample[100]; + switch( pPP->MultiSampleType ) + { + case D3DMULTISAMPLE_NONMASKABLE: + wcscpy_s( strMultiSample, 100, L" (Nonmaskable Multisample)" ); break; + case D3DMULTISAMPLE_NONE: + wcscpy_s( strMultiSample, 100, L"" ); break; + default: + swprintf_s( strMultiSample, 100, L" (%dx Multisample)", pPP->MultiSampleType ); break; + } + + WCHAR* pstrStaticFrameStats = GetDXUTState().GetStaticFrameStats(); + swprintf_s( pstrStaticFrameStats, 256, L"D3D9 %%sVsync %s (%dx%d), %s%s%s", + ( pPP->PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE ) ? L"off" : L"on", + pPP->BackBufferWidth, pPP->BackBufferHeight, + strFmt, strDepthFmt, strMultiSample ); + } + else + { + // D3D11 + CD3D11Enumeration* pd3dEnum = DXUTGetD3D11Enumeration(); + if( NULL == pd3dEnum ) + return; + + CD3D11EnumDeviceSettingsCombo* pDeviceSettingsCombo = pd3dEnum->GetDeviceSettingsCombo( + pDeviceSettings->d3d11.AdapterOrdinal, pDeviceSettings->d3d11.DriverType, pDeviceSettings->d3d11.Output, + pDeviceSettings->d3d11.sd.BufferDesc.Format, pDeviceSettings->d3d11.sd.Windowed ); + if( NULL == pDeviceSettingsCombo ) + return; + + WCHAR strFmt[100]; + + wcscpy_s( strFmt, 100, DXUTDXGIFormatToString( pDeviceSettingsCombo->BackBufferFormat, false ) ); + + WCHAR strMultiSample[100]; + swprintf_s( strMultiSample, 100, L" (MS%u, Q%u)", pDeviceSettings->d3d11.sd.SampleDesc.Count, + pDeviceSettings->d3d11.sd.SampleDesc.Quality ); + + WCHAR* pstrStaticFrameStats = GetDXUTState().GetStaticFrameStats(); + swprintf_s( pstrStaticFrameStats, 256, L"D3D11 %%sVsync %s (%dx%d), %s%s", + ( pDeviceSettings->d3d11.SyncInterval == 0 ) ? L"off" : L"on", + pDeviceSettings->d3d11.sd.BufferDesc.Width, pDeviceSettings->d3d11.sd.BufferDesc.Height, + strFmt, strMultiSample ); + } +} + + +//-------------------------------------------------------------------------------------- +// Updates the frames/sec stat once per second +//-------------------------------------------------------------------------------------- +void DXUTUpdateFrameStats() +{ + if( GetDXUTState().GetNoStats() ) + return; + + // Keep track of the frame count + double fLastTime = GetDXUTState().GetLastStatsUpdateTime(); + DWORD dwFrames = GetDXUTState().GetLastStatsUpdateFrames(); + double fAbsTime = GetDXUTState().GetAbsoluteTime(); + dwFrames++; + GetDXUTState().SetLastStatsUpdateFrames( dwFrames ); + + // Update the scene stats once per second + if( fAbsTime - fLastTime > 1.0f ) + { + float fFPS = ( float )( dwFrames / ( fAbsTime - fLastTime ) ); + GetDXUTState().SetFPS( fFPS ); + GetDXUTState().SetLastStatsUpdateTime( fAbsTime ); + GetDXUTState().SetLastStatsUpdateFrames( 0 ); + + WCHAR* pstrFPS = GetDXUTState().GetFPSStats(); + swprintf_s( pstrFPS, 64, L"%0.2f fps ", fFPS ); + } +} + +//-------------------------------------------------------------------------------------- +// Returns a string describing the current device. If bShowFPS is true, then +// the string contains the frames/sec. If "-nostats" was used in +// the command line, the string will be blank +//-------------------------------------------------------------------------------------- +LPCWSTR WINAPI DXUTGetFrameStats( bool bShowFPS ) +{ + WCHAR* pstrFrameStats = GetDXUTState().GetFrameStats(); + WCHAR* pstrFPS = ( bShowFPS ) ? GetDXUTState().GetFPSStats() : L""; + swprintf_s( pstrFrameStats, 256, GetDXUTState().GetStaticFrameStats(), pstrFPS ); + return pstrFrameStats; +} + + +//-------------------------------------------------------------------------------------- +// Updates the string which describes the device +//-------------------------------------------------------------------------------------- +void DXUTUpdateD3D9DeviceStats( D3DDEVTYPE DeviceType, DWORD BehaviorFlags, + D3DADAPTER_IDENTIFIER9* pAdapterIdentifier ) +{ + if( GetDXUTState().GetNoStats() ) + return; + + // Store device description + WCHAR* pstrDeviceStats = GetDXUTState().GetDeviceStats(); + if( DeviceType == D3DDEVTYPE_REF ) + wcscpy_s( pstrDeviceStats, 256, L"REF" ); + else if( DeviceType == D3DDEVTYPE_HAL ) + wcscpy_s( pstrDeviceStats, 256, L"HAL" ); + else if( DeviceType == D3DDEVTYPE_SW ) + wcscpy_s( pstrDeviceStats, 256, L"SW" ); + + if( DeviceType == D3DDEVTYPE_HAL ) + { + // Be sure not to overflow m_strDeviceStats when appending the adapter + // description, since it can be long. + wcscat_s( pstrDeviceStats, 256, L": " ); + + // Try to get a unique description from the CD3D9EnumDeviceSettingsCombo + DXUTDeviceSettings* pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); + if( !pDeviceSettings ) + return; + + CD3D9Enumeration* pd3dEnum = DXUTGetD3D9Enumeration(); + CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo = pd3dEnum->GetDeviceSettingsCombo( + pDeviceSettings->d3d9.AdapterOrdinal, pDeviceSettings->d3d9.DeviceType, + pDeviceSettings->d3d9.AdapterFormat, pDeviceSettings->d3d9.pp.BackBufferFormat, + pDeviceSettings->d3d9.pp.Windowed ); + if( pDeviceSettingsCombo ) + { + wcscat_s( pstrDeviceStats, 256, pDeviceSettingsCombo->pAdapterInfo->szUniqueDescription ); + } + else + { + const int cchDesc = sizeof( pAdapterIdentifier->Description ); + WCHAR szDescription[cchDesc]; + MultiByteToWideChar( CP_ACP, 0, pAdapterIdentifier->Description, -1, szDescription, cchDesc ); + szDescription[cchDesc - 1] = 0; + wcscat_s( pstrDeviceStats, 256, szDescription ); + } + } +} + + +//-------------------------------------------------------------------------------------- +// Updates the string which describes the device +//-------------------------------------------------------------------------------------- +void DXUTUpdateD3D11DeviceStats( D3D_DRIVER_TYPE DeviceType, DXGI_ADAPTER_DESC* pAdapterDesc ) +{ + if( GetDXUTState().GetNoStats() ) + return; + + // Store device description + WCHAR* pstrDeviceStats = GetDXUTState().GetDeviceStats(); + if( DeviceType == D3D_DRIVER_TYPE_REFERENCE ) + wcscpy_s( pstrDeviceStats, 256, L"REFERENCE" ); + else if( DeviceType == D3D_DRIVER_TYPE_HARDWARE ) + wcscpy_s( pstrDeviceStats, 256, L"HARDWARE" ); + else if( DeviceType == D3D_DRIVER_TYPE_SOFTWARE ) + wcscpy_s( pstrDeviceStats, 256, L"SOFTWARE" ); + else if( DeviceType == D3D_DRIVER_TYPE_WARP ) + wcscpy_s( pstrDeviceStats, 256, L"WARP" ); + + if( DeviceType == D3D_DRIVER_TYPE_HARDWARE ) + { + // Be sure not to overflow m_strDeviceStats when appending the adapter + // description, since it can be long. + wcscat_s( pstrDeviceStats, 256, L": " ); + + // Try to get a unique description from the CD3D11EnumDeviceSettingsCombo + DXUTDeviceSettings* pDeviceSettings = GetDXUTState().GetCurrentDeviceSettings(); + if( !pDeviceSettings ) + return; + + CD3D11Enumeration* pd3dEnum = DXUTGetD3D11Enumeration(); + CD3D11EnumDeviceSettingsCombo* pDeviceSettingsCombo = pd3dEnum->GetDeviceSettingsCombo( + pDeviceSettings->d3d11.AdapterOrdinal, pDeviceSettings->d3d11.DriverType, pDeviceSettings->d3d11.Output, + pDeviceSettings->d3d11.sd.BufferDesc.Format, pDeviceSettings->d3d11.sd.Windowed ); + if( pDeviceSettingsCombo ) + wcscat_s( pstrDeviceStats, 256, pDeviceSettingsCombo->pAdapterInfo->szUniqueDescription ); + else + wcscat_s( pstrDeviceStats, 256, pAdapterDesc->Description ); + } +} + + +//-------------------------------------------------------------------------------------- +// Misc functions +//-------------------------------------------------------------------------------------- +DXUTDeviceSettings WINAPI DXUTGetDeviceSettings() +{ + // Return a copy of device settings of the current device. If no device exists yet, then + // return a blank device settings struct + DXUTDeviceSettings* pDS = GetDXUTState().GetCurrentDeviceSettings(); + if( pDS ) + { + return *pDS; + } + else + { + DXUTDeviceSettings ds; + ZeroMemory( &ds, sizeof( DXUTDeviceSettings ) ); + return ds; + } +} + +D3DPRESENT_PARAMETERS WINAPI DXUTGetD3D9PresentParameters() +{ + // Return a copy of the present params of the current device. If no device exists yet, then + // return blank present params + DXUTDeviceSettings* pDS = GetDXUTState().GetCurrentDeviceSettings(); + if( pDS ) + { + return pDS->d3d9.pp; + } + else + { + D3DPRESENT_PARAMETERS pp; + ZeroMemory( &pp, sizeof( D3DPRESENT_PARAMETERS ) ); + return pp; + } +} + +bool WINAPI DXUTIsVsyncEnabled() +{ + DXUTDeviceSettings* pDS = GetDXUTState().GetCurrentDeviceSettings(); + if( pDS ) + { + if( DXUTIsD3D9( pDS ) ) + return ( pDS->d3d9.pp.PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE ); + else + return ( pDS->d3d11.SyncInterval == 0 ); + } + else + { + return true; + } +}; + +HRESULT WINAPI DXUTGetD3D9DeviceCaps( DXUTDeviceSettings* pDeviceSettings, D3DCAPS9* pCaps ) +{ + IDirect3D9* pD3D = DXUTGetD3D9Object(); + return pD3D->GetDeviceCaps( pDeviceSettings->d3d9.AdapterOrdinal, pDeviceSettings->d3d9.DeviceType, pCaps ); +} + + +bool WINAPI DXUTIsKeyDown( BYTE vKey ) +{ + bool* bKeys = GetDXUTState().GetKeys(); + if( vKey >= 0xA0 && vKey <= 0xA5 ) // VK_LSHIFT, VK_RSHIFT, VK_LCONTROL, VK_RCONTROL, VK_LMENU, VK_RMENU + return GetAsyncKeyState( vKey ) != 0; // these keys only are tracked via GetAsyncKeyState() + else if( vKey >= 0x01 && vKey <= 0x06 && vKey != 0x03 ) // mouse buttons (VK_*BUTTON) + return DXUTIsMouseButtonDown( vKey ); + else + return bKeys[vKey]; +} + +bool WINAPI DXUTWasKeyPressed( BYTE vKey ) +{ + bool* bLastKeys = GetDXUTState().GetLastKeys(); + bool* bKeys = GetDXUTState().GetKeys(); + GetDXUTState().SetAppCalledWasKeyPressed( true ); + return ( !bLastKeys[vKey] && bKeys[vKey] ); +} + +bool WINAPI DXUTIsMouseButtonDown( BYTE vButton ) +{ + bool* bMouseButtons = GetDXUTState().GetMouseButtons(); + int nIndex = DXUTMapButtonToArrayIndex( vButton ); + return bMouseButtons[nIndex]; +} + +void WINAPI DXUTSetMultimonSettings( bool bAutoChangeAdapter ) +{ + GetDXUTState().SetAutoChangeAdapter( bAutoChangeAdapter ); +} + +void WINAPI DXUTSetHotkeyHandling( bool bAltEnterToToggleFullscreen, bool bEscapeToQuit, bool bPauseToToggleTimePause ) +{ + GetDXUTState().SetHandleEscape( bEscapeToQuit ); + GetDXUTState().SetHandleAltEnter( bAltEnterToToggleFullscreen ); + GetDXUTState().SetHandlePause( bPauseToToggleTimePause ); +} + +void WINAPI DXUTSetCursorSettings( bool bShowCursorWhenFullScreen, bool bClipCursorWhenFullScreen ) +{ + GetDXUTState().SetClipCursorWhenFullScreen( bClipCursorWhenFullScreen ); + GetDXUTState().SetShowCursorWhenFullScreen( bShowCursorWhenFullScreen ); + DXUTSetupCursor(); +} + +void WINAPI DXUTSetWindowSettings( bool bCallDefWindowProc ) +{ + GetDXUTState().SetCallDefWindowProc( bCallDefWindowProc ); +} + +void WINAPI DXUTSetConstantFrameTime( bool bEnabled, float fTimePerFrame ) +{ + if( GetDXUTState().GetOverrideConstantFrameTime() ) + { + bEnabled = GetDXUTState().GetOverrideConstantFrameTime(); + fTimePerFrame = GetDXUTState().GetOverrideConstantTimePerFrame(); + } + GetDXUTState().SetConstantFrameTime( bEnabled ); + GetDXUTState().SetTimePerFrame( fTimePerFrame ); +} + + +//-------------------------------------------------------------------------------------- +// Resets the state associated with DXUT +//-------------------------------------------------------------------------------------- +void WINAPI DXUTResetFrameworkState() +{ + GetDXUTState().Destroy(); + GetDXUTState().Create(); +} + + +//-------------------------------------------------------------------------------------- +// Closes down the window. When the window closes, it will cleanup everything +//-------------------------------------------------------------------------------------- +void WINAPI DXUTShutdown( int nExitCode ) +{ + HWND hWnd = DXUTGetHWND(); + if( hWnd != NULL ) + SendMessage( hWnd, WM_CLOSE, 0, 0 ); + + GetDXUTState().SetExitCode( nExitCode ); + + DXUTCleanup3DEnvironment( true ); + + // Restore shortcut keys (Windows key, accessibility shortcuts) to original state + // This is important to call here if the shortcuts are disabled, + // because accessibility setting changes are permanent. + // This means that if this is not done then the accessibility settings + // might not be the same as when the app was started. + // If the app crashes without restoring the settings, this is also true so it + // would be wise to backup/restore the settings from a file so they can be + // restored when the crashed app is run again. + DXUTAllowShortcutKeys( true ); + + // Shutdown D3D9 + IDirect3D9* pD3D = GetDXUTState().GetD3D9(); + SAFE_RELEASE( pD3D ); + GetDXUTState().SetD3D9( NULL ); + + // Shutdown D3D11 + IDXGIFactory1* pDXGIFactory = GetDXUTState().GetDXGIFactory(); + SAFE_RELEASE( pDXGIFactory ); + GetDXUTState().SetDXGIFactory( NULL ); + + if( GetDXUTState().GetOverrideRelaunchMCE() ) + DXUTReLaunchMediaCenter(); +} + +//-------------------------------------------------------------------------------------- +// Tells DXUT whether to operate in gamma correct mode +//-------------------------------------------------------------------------------------- +void WINAPI DXUTSetIsInGammaCorrectMode( bool bGammaCorrect ) +{ + GetDXUTState().SetIsInGammaCorrectMode( bGammaCorrect ); +} + + +void DXUTApplyDefaultDeviceSettings(DXUTDeviceSettings *modifySettings) { + ZeroMemory( modifySettings, sizeof( DXUTDeviceSettings ) ); + + + modifySettings->ver = DXUT_D3D11_DEVICE; + modifySettings->d3d11.AdapterOrdinal = 0; + modifySettings->d3d11.AutoCreateDepthStencil = true; + modifySettings->d3d11.AutoDepthStencilFormat = DXGI_FORMAT_D24_UNORM_S8_UINT; +#if defined(DEBUG) || defined(_DEBUG) + modifySettings->d3d11.CreateFlags |= D3D10_CREATE_DEVICE_DEBUG; +#else + modifySettings->d3d11.CreateFlags = 0; +#endif + modifySettings->d3d11.DriverType = D3D_DRIVER_TYPE_HARDWARE; + modifySettings->d3d11.Output = 0; + modifySettings->d3d11.PresentFlags = 0; + modifySettings->d3d11.sd.BufferCount = 2; + modifySettings->d3d11.sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + modifySettings->d3d11.sd.BufferDesc.Height = 480; + modifySettings->d3d11.sd.BufferDesc.RefreshRate.Numerator = 60; + modifySettings->d3d11.sd.BufferDesc.RefreshRate.Denominator = 1; + modifySettings->d3d11.sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + modifySettings->d3d11.sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + modifySettings->d3d11.sd.BufferDesc.Width = 640; + modifySettings->d3d11.sd.BufferUsage = 32; + modifySettings->d3d11.sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH ; + modifySettings->d3d11.sd.OutputWindow = DXUTGetHWND(); + modifySettings->d3d11.sd.SampleDesc.Count = 1; + modifySettings->d3d11.sd.SampleDesc.Quality = 0; + modifySettings->d3d11.sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + modifySettings->d3d11.sd.Windowed = 1; + modifySettings->d3d11.SyncInterval = 0; + + modifySettings->d3d9.AdapterFormat = D3DFMT_X8R8G8B8; + modifySettings->d3d9.AdapterOrdinal = 0; + modifySettings->d3d9.BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING; + modifySettings->d3d9.DeviceType = D3DDEVTYPE_HAL; + modifySettings->d3d9.pp.AutoDepthStencilFormat = D3DFMT_D24X8; + modifySettings->d3d9.pp.BackBufferCount = 1; + modifySettings->d3d9.pp.BackBufferFormat = D3DFMT_X8R8G8B8; + modifySettings->d3d9.pp.BackBufferHeight = 480; + modifySettings->d3d9.pp.BackBufferWidth = 640; + modifySettings->d3d9.pp.EnableAutoDepthStencil = 1; + modifySettings->d3d9.pp.Flags = 2; + modifySettings->d3d9.pp.FullScreen_RefreshRateInHz = 0; + modifySettings->d3d9.pp.hDeviceWindow = DXUTGetHWND(); + modifySettings->d3d9.pp.MultiSampleQuality = 0; + modifySettings->d3d9.pp.MultiSampleType = D3DMULTISAMPLE_NONE; + modifySettings->d3d9.pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + modifySettings->d3d9.pp.SwapEffect = D3DSWAPEFFECT_DISCARD; + modifySettings->d3d9.pp.Windowed = 1; +} + + + +//-------------------------------------------------------------------------------------- +// Update settings based on what is enumeratabled +//-------------------------------------------------------------------------------------- +HRESULT DXUTSnapDeviceSettingsToEnumDevice( DXUTDeviceSettings* pDeviceSettings, bool forceEnum, D3D_FEATURE_LEVEL forceFL ) { + bool bAppSupportsD3D9 = DXUTDoesAppSupportD3D9(); + bool bAppSupportsD3D11 = DXUTDoesAppSupportD3D11(); + + if( GetSystemMetrics(0x1000) != 0 ) {// SM_REMOTESESSION + pDeviceSettings->d3d11.sd.Windowed = 1; + pDeviceSettings->d3d9.pp.Windowed = 1; + } + int bestModeIndex=0; + int bestMSAAIndex=0; + + + //DXUTSetDefaultDeviceSettings + if (bAppSupportsD3D11 && pDeviceSettings->ver == DXUT_D3D11_DEVICE ) { + CD3D11Enumeration *pEnum = NULL; + + + pEnum = DXUTGetD3D11Enumeration( forceEnum, false, forceFL); + + CD3D11EnumAdapterInfo* pAdapterInfo = NULL; + CGrowableArray * pAdapterList = pEnum->GetAdapterInfoList(); + CD3D11EnumAdapterInfo* tempAdapterInfo = pAdapterList->GetAt( 0 ); + for( int iAdapter = 0; iAdapter < pAdapterList->GetSize(); iAdapter++ ) + { + tempAdapterInfo = pAdapterList->GetAt( iAdapter ); + if (tempAdapterInfo->AdapterOrdinal == pDeviceSettings->d3d11.AdapterOrdinal) pAdapterInfo = tempAdapterInfo; + } + if (pAdapterInfo == NULL) return E_FAIL; // no adapters found. + CD3D11EnumDeviceSettingsCombo* pDeviceSettingsCombo = NULL; + float biggestScore = 0; + + int combo = 0; + for( int iDeviceCombo = 0; iDeviceCombo < pAdapterInfo->deviceSettingsComboList.GetSize(); iDeviceCombo++ ) + { + CD3D11EnumDeviceSettingsCombo* tempDeviceSettingsCombo = pAdapterInfo->deviceSettingsComboList.GetAt( iDeviceCombo ); + + DXGI_MODE_DESC adapterDisplayMode; + DXUTGetD3D11AdapterDisplayMode( pAdapterInfo->AdapterOrdinal, 0, &adapterDisplayMode ); + + int bestMode; + int bestMSAA; + float score = DXUTRankD3D11DeviceCombo(tempDeviceSettingsCombo, &(pDeviceSettings->d3d11), &adapterDisplayMode, bestMode, bestMSAA ); + if (score > biggestScore) { + combo = iDeviceCombo; + biggestScore = score; + pDeviceSettingsCombo = tempDeviceSettingsCombo; + bestModeIndex = bestMode; + bestMSAAIndex = bestMSAA; + } + + } + if (NULL == pDeviceSettingsCombo ) { + return E_FAIL; // no settigns found. + } + + pDeviceSettings->d3d11.AdapterOrdinal = pDeviceSettingsCombo->AdapterOrdinal; + pDeviceSettings->d3d11.DriverType = pDeviceSettingsCombo->DeviceType; + pDeviceSettings->d3d11.Output = pDeviceSettingsCombo->Output; + + pDeviceSettings->d3d11.sd.Windowed = pDeviceSettingsCombo->Windowed; + if( GetSystemMetrics(0x1000) != 0 ) {// SM_REMOTESESSION + pDeviceSettings->d3d11.sd.Windowed = 1; + } + if (pDeviceSettingsCombo->pOutputInfo != NULL) { + DXGI_MODE_DESC bestDisplayMode; + bestDisplayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList.GetAt(bestModeIndex); + if (!pDeviceSettingsCombo->Windowed) { + + pDeviceSettings->d3d11.sd.BufferDesc.Height = bestDisplayMode.Height; + pDeviceSettings->d3d11.sd.BufferDesc.Width = bestDisplayMode.Width; + pDeviceSettings->d3d11.sd.BufferDesc.RefreshRate.Numerator = bestDisplayMode.RefreshRate.Numerator; + pDeviceSettings->d3d11.sd.BufferDesc.RefreshRate.Denominator = bestDisplayMode.RefreshRate.Denominator; + pDeviceSettings->d3d11.sd.BufferDesc.Scaling = bestDisplayMode.Scaling; + pDeviceSettings->d3d11.sd.BufferDesc.ScanlineOrdering = bestDisplayMode.ScanlineOrdering; + } + } + if (pDeviceSettings->d3d11.DeviceFeatureLevel == 0) + pDeviceSettings->d3d11.DeviceFeatureLevel = pDeviceSettingsCombo->pDeviceInfo->SelectedLevel; + + + + + pDeviceSettings->d3d11.sd.SampleDesc.Count = pDeviceSettingsCombo->multiSampleCountList.GetAt(bestMSAAIndex); + if (pDeviceSettings->d3d11.sd.SampleDesc.Quality > pDeviceSettingsCombo->multiSampleQualityList.GetAt(bestMSAAIndex) - 1) + pDeviceSettings->d3d11.sd.SampleDesc.Quality = pDeviceSettingsCombo->multiSampleQualityList.GetAt(bestMSAAIndex) - 1; + + pDeviceSettings->d3d11.sd.BufferDesc.Format = pDeviceSettingsCombo->BackBufferFormat; + + return S_OK; + } + // didn't find a D3D11 adapter. + if (bAppSupportsD3D9) { + // Find the best combination of: + // Adapter Ordinal + // Device Type + // Adapter Format + // Back Buffer Format + // Windowed + // given what's available on the system and the match options combined with the device settings input. + // This combination of settings is encapsulated by the CD3D9EnumDeviceSettingsCombo class. + float fBestRanking = -1.0f; + CD3D9EnumDeviceSettingsCombo* pBestDeviceSettingsCombo = NULL; + D3DDISPLAYMODE adapterDesktopDisplayMode; + + IDirect3D9* pD3D = DXUTGetD3D9Object(); + CD3D9Enumeration* pd3dEnum = DXUTGetD3D9Enumeration( forceEnum ); + CGrowableArray * pAdapterList = pd3dEnum->GetAdapterInfoList(); + for( int iAdapter = 0; iAdapter < pAdapterList->GetSize(); iAdapter++ ) + { + CD3D9EnumAdapterInfo* pAdapterInfo = pAdapterList->GetAt( iAdapter ); + + // Get the desktop display mode of adapter + pD3D->GetAdapterDisplayMode( pAdapterInfo->AdapterOrdinal, &adapterDesktopDisplayMode ); + + // Enum all the device types supported by this adapter to find the best device settings + for( int iDeviceInfo = 0; iDeviceInfo < pAdapterInfo->deviceInfoList.GetSize(); iDeviceInfo++ ) + { + CD3D9EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( iDeviceInfo ); + + // Enum all the device settings combinations. A device settings combination is + // a unique set of an adapter format, back buffer format, and IsWindowed. + for( int iDeviceCombo = 0; iDeviceCombo < pDeviceInfo->deviceSettingsComboList.GetSize(); iDeviceCombo++ ) + { + CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo = pDeviceInfo->deviceSettingsComboList.GetAt( + iDeviceCombo ); + + // If windowed mode the adapter format has to be the same as the desktop + // display mode format so skip any that don't match + if( pDeviceSettingsCombo->Windowed && + ( pDeviceSettingsCombo->AdapterFormat != adapterDesktopDisplayMode.Format ) ) + continue; + + // Skip any combo that doesn't meet the preserve match options + int bestMode; + int bestMSAA; + + // Get a ranking number that describes how closely this device combo matches the optimal combo + float fCurRanking = DXUTRankD3D9DeviceCombo( pDeviceSettingsCombo, + &(pDeviceSettings->d3d9), &adapterDesktopDisplayMode, bestMode, bestMSAA ); + + // If this combo better matches the input device settings then save it + if( fCurRanking > fBestRanking ) + { + pBestDeviceSettingsCombo = pDeviceSettingsCombo; + fBestRanking = fCurRanking; + bestModeIndex = bestMode; + bestMSAAIndex = bestMSAA; + } + } + } + } + + // If no best device combination was found then fail + if( pBestDeviceSettingsCombo == NULL ) + return DXUTERR_NOCOMPATIBLEDEVICES; + + // Using the best device settings combo found, build valid device settings taking heed of + // the match options and the input device settings + pDeviceSettings->d3d9.AdapterFormat = pBestDeviceSettingsCombo->AdapterFormat;//D3DFMT_X8R8G8B8; + pDeviceSettings->d3d9.AdapterOrdinal = pBestDeviceSettingsCombo->AdapterOrdinal ;//0; + pDeviceSettings->d3d9.DeviceType = pBestDeviceSettingsCombo->DeviceType; + pDeviceSettings->d3d9.pp.BackBufferFormat = pBestDeviceSettingsCombo->BackBufferFormat;//D3DFMT_X8R8G8B8; + if( GetSystemMetrics(0x1000) != 0 ) {// SM_REMOTESESSION + pDeviceSettings->d3d9.pp.Windowed = 1; + } + if (!pBestDeviceSettingsCombo->Windowed) { + D3DDISPLAYMODE displayMode = pBestDeviceSettingsCombo->pAdapterInfo->displayModeList.GetAt( bestModeIndex ); + pDeviceSettings->d3d9.pp.BackBufferHeight = displayMode.Height; + pDeviceSettings->d3d9.pp.BackBufferWidth = displayMode.Width; + pDeviceSettings->d3d9.pp.FullScreen_RefreshRateInHz = displayMode.RefreshRate; + } + pDeviceSettings->d3d9.pp.hDeviceWindow = pBestDeviceSettingsCombo->Windowed ? DXUTGetHWNDDeviceWindowed() : DXUTGetHWNDDeviceFullScreen(); + if (pDeviceSettings->d3d9.pp.MultiSampleQuality > pBestDeviceSettingsCombo->multiSampleQualityList.GetAt(bestMSAAIndex) - 1) + pDeviceSettings->d3d9.pp.MultiSampleQuality = pBestDeviceSettingsCombo->multiSampleQualityList.GetAt( bestMSAAIndex )-1; + + pDeviceSettings->d3d9.pp.MultiSampleType = pBestDeviceSettingsCombo->multiSampleTypeList.GetAt( bestMSAAIndex );; + pDeviceSettings->d3d9.pp.Windowed = pBestDeviceSettingsCombo->Windowed; + return S_OK; + } + return E_FAIL; +} diff --git a/Demos/DX11ClothDemo/DXUT/Core/DXUT.h b/Demos/DX11ClothDemo/DXUT/Core/DXUT.h new file mode 100644 index 0000000..2d52b8d --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Core/DXUT.h @@ -0,0 +1,378 @@ +//-------------------------------------------------------------------------------------- +// File: DXUT.h +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once +#ifndef DXUT_H +#define DXUT_H + +#ifndef UNICODE +#error "DXUT requires a Unicode build. See the nearby comments for details" +// +// If you are using Microsoft Visual C++ .NET, under the General tab of the project +// properties change the Character Set to 'Use Unicode Character Set'. +// +// Windows XP and later are native Unicode so Unicode applications will perform better. +// For Windows 98 and Windows Me support, consider using the Microsoft Layer for Unicode (MSLU). +// +// To use MSLU, link against a set of libraries similar to this +// /nod:kernel32.lib /nod:advapi32.lib /nod:user32.lib /nod:gdi32.lib /nod:shell32.lib /nod:comdlg32.lib /nod:version.lib /nod:mpr.lib /nod:rasapi32.lib /nod:winmm.lib /nod:winspool.lib /nod:vfw32.lib /nod:secur32.lib /nod:oleacc.lib /nod:oledlg.lib /nod:sensapi.lib UnicoWS.lib kernel32.lib advapi32.lib user32.lib gdi32.lib shell32.lib comdlg32.lib version.lib mpr.lib rasapi32.lib winmm.lib winspool.lib vfw32.lib secur32.lib oleacc.lib oledlg.lib sensapi.lib dxerr.lib dxguid.lib d3dx9d.lib d3d9.lib comctl32.lib +// and put the unicows.dll (available for download from msdn.microsoft.com) in the exe's folder. +// +// For more details see the MSDN article titled: +// "MSLU: Develop Unicode Applications for Windows 9x Platforms with the Microsoft Layer for Unicode" +// at http://msdn.microsoft.com/msdnmag/issues/01/10/MSLU/default.aspx +// +#endif + +#include "dxsdkver.h" +#if ( _DXSDK_PRODUCT_MAJOR < 9 || _DXSDK_BUILD_MAJOR < 1455 ) +#error The installed DXSDK is out of date. +#endif + +#ifndef STRICT +#define STRICT +#endif + +// If app hasn't choosen, set to work with Windows 98, Windows Me, Windows 2000, Windows XP and beyond +#ifndef WINVER +#define WINVER 0x0500 +#endif +#ifndef _WIN32_WINDOWS +#define _WIN32_WINDOWS 0x0500 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 +#endif + +// #define DXUT_AUTOLIB to automatically include the libs needed for DXUT +#ifdef DXUT_AUTOLIB +#pragma comment( lib, "dxerr.lib" ) +#pragma comment( lib, "dxguid.lib" ) +#pragma comment( lib, "d3d9.lib" ) +#if defined(DEBUG) || defined(_DEBUG) +#pragma comment( lib, "d3dx9d.lib" ) +#else +#pragma comment( lib, "d3dx9.lib" ) +#endif +#pragma comment( lib, "winmm.lib" ) +#pragma comment( lib, "comctl32.lib" ) +#endif + +#pragma warning( disable : 4100 ) // disable unreference formal parameter warnings for /W4 builds + +// Enable extra D3D debugging in debug builds if using the debug DirectX runtime. +// This makes D3D objects work well in the debugger watch window, but slows down +// performance slightly. +#if defined(DEBUG) || defined(_DEBUG) +#ifndef D3D_DEBUG_INFO +#define D3D_DEBUG_INFO +#endif +#endif + +// Standard Windows includes +#include +#include +#include +#include +#include +#include // for InitCommonControls() +#include // for ExtractIcon() +#include // for placement new +#include +#include +#include +#include + +// CRT's memory leak detection +#if defined(DEBUG) || defined(_DEBUG) +#include +#endif + +// Direct3D9 includes +#include +#include + + +// Direct3D11 includes +#include +#include +#include +#include + +// XInput includes +#include + +// HRESULT translation for Direct3D10 and other APIs +#include + + +#if defined(DEBUG) || defined(_DEBUG) +#ifndef V +#define V(x) { hr = (x); if( FAILED(hr) ) { DXUTTrace( __FILE__, (DWORD)__LINE__, hr, L#x, true ); } } +#endif +#ifndef V_RETURN +#define V_RETURN(x) { hr = (x); if( FAILED(hr) ) { return DXUTTrace( __FILE__, (DWORD)__LINE__, hr, L#x, true ); } } +#endif +#else +#ifndef V +#define V(x) { hr = (x); } +#endif +#ifndef V_RETURN +#define V_RETURN(x) { hr = (x); if( FAILED(hr) ) { return hr; } } +#endif +#endif + +#ifndef SAFE_DELETE +#define SAFE_DELETE(p) { if (p) { delete (p); (p)=NULL; } } +#endif +#ifndef SAFE_DELETE_ARRAY +#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p)=NULL; } } +#endif +#ifndef SAFE_RELEASE +#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } } +#endif + + + +//-------------------------------------------------------------------------------------- +// Structs +//-------------------------------------------------------------------------------------- +struct DXUTD3D9DeviceSettings +{ + UINT AdapterOrdinal; + D3DDEVTYPE DeviceType; + D3DFORMAT AdapterFormat; + DWORD BehaviorFlags; + D3DPRESENT_PARAMETERS pp; +}; + +struct DXUTD3D11DeviceSettings +{ + UINT AdapterOrdinal; + D3D_DRIVER_TYPE DriverType; + UINT Output; + DXGI_SWAP_CHAIN_DESC sd; + UINT32 CreateFlags; + UINT32 SyncInterval; + DWORD PresentFlags; + bool AutoCreateDepthStencil; // DXUT will create the depth stencil resource and view if true + DXGI_FORMAT AutoDepthStencilFormat; + D3D_FEATURE_LEVEL DeviceFeatureLevel; +}; + +enum DXUTDeviceVersion +{ + DXUT_D3D9_DEVICE, + DXUT_D3D11_DEVICE +}; + +struct DXUTDeviceSettings +{ + DXUTDeviceVersion ver; + D3D_FEATURE_LEVEL MinimumFeatureLevel; + DXUTD3D9DeviceSettings d3d9; // only valid if ver == DXUT_D3D9_DEVICE + DXUTD3D11DeviceSettings d3d11; // only valid if ver == DXUT_D3D11_DEVICE +}; + + +//-------------------------------------------------------------------------------------- +// Error codes +//-------------------------------------------------------------------------------------- +#define DXUTERR_NODIRECT3D MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0901) +#define DXUTERR_NOCOMPATIBLEDEVICES MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0902) +#define DXUTERR_MEDIANOTFOUND MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0903) +#define DXUTERR_NONZEROREFCOUNT MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0904) +#define DXUTERR_CREATINGDEVICE MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0905) +#define DXUTERR_RESETTINGDEVICE MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0906) +#define DXUTERR_CREATINGDEVICEOBJECTS MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0907) +#define DXUTERR_RESETTINGDEVICEOBJECTS MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0908) +#define DXUTERR_DEVICEREMOVED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x090A) +#define DXUTERR_NODIRECT3D11 MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x090) + +//-------------------------------------------------------------------------------------- +// Callback registration +//-------------------------------------------------------------------------------------- + +// General callbacks +typedef void (CALLBACK *LPDXUTCALLBACKFRAMEMOVE)( double fTime, float fElapsedTime, void* pUserContext ); +typedef void (CALLBACK *LPDXUTCALLBACKKEYBOARD)( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext ); +typedef void (CALLBACK *LPDXUTCALLBACKMOUSE)( bool bLeftButtonDown, bool bRightButtonDown, bool bMiddleButtonDown, bool bSideButton1Down, bool bSideButton2Down, int nMouseWheelDelta, int xPos, int yPos, void* pUserContext ); +typedef LRESULT (CALLBACK *LPDXUTCALLBACKMSGPROC)( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext ); +typedef void (CALLBACK *LPDXUTCALLBACKTIMER)( UINT idEvent, void* pUserContext ); +typedef bool (CALLBACK *LPDXUTCALLBACKMODIFYDEVICESETTINGS)( DXUTDeviceSettings* pDeviceSettings, void* pUserContext ); +typedef bool (CALLBACK *LPDXUTCALLBACKDEVICEREMOVED)( void* pUserContext ); + +// Direct3D 9 callbacks +typedef bool (CALLBACK *LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE)( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext ); +typedef HRESULT (CALLBACK *LPDXUTCALLBACKD3D9DEVICECREATED)( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ); +typedef HRESULT (CALLBACK *LPDXUTCALLBACKD3D9DEVICERESET)( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ); +typedef void (CALLBACK *LPDXUTCALLBACKD3D9FRAMERENDER)( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ); +typedef void (CALLBACK *LPDXUTCALLBACKD3D9DEVICELOST)( void* pUserContext ); +typedef void (CALLBACK *LPDXUTCALLBACKD3D9DEVICEDESTROYED)( void* pUserContext ); + +class CD3D11EnumAdapterInfo; +class CD3D11EnumDeviceInfo; +// Direct3D 11 callbacks +typedef bool (CALLBACK *LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE)( const CD3D11EnumAdapterInfo *AdapterInfo, UINT Output, const CD3D11EnumDeviceInfo *DeviceInfo, DXGI_FORMAT BackBufferFormat, bool bWindowed, void* pUserContext ); +typedef HRESULT (CALLBACK *LPDXUTCALLBACKD3D11DEVICECREATED)( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ); +typedef HRESULT (CALLBACK *LPDXUTCALLBACKD3D11SWAPCHAINRESIZED)( ID3D11Device* pd3dDevice, IDXGISwapChain *pSwapChain, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ); +typedef void (CALLBACK *LPDXUTCALLBACKD3D11FRAMERENDER)( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime, float fElapsedTime, void* pUserContext ); +typedef void (CALLBACK *LPDXUTCALLBACKD3D11SWAPCHAINRELEASING)( void* pUserContext ); +typedef void (CALLBACK *LPDXUTCALLBACKD3D11DEVICEDESTROYED)( void* pUserContext ); + +// General callbacks +void WINAPI DXUTSetCallbackFrameMove( LPDXUTCALLBACKFRAMEMOVE pCallback, void* pUserContext = NULL ); +void WINAPI DXUTSetCallbackKeyboard( LPDXUTCALLBACKKEYBOARD pCallback, void* pUserContext = NULL ); +void WINAPI DXUTSetCallbackMouse( LPDXUTCALLBACKMOUSE pCallback, bool bIncludeMouseMove = false, void* pUserContext = NULL ); +void WINAPI DXUTSetCallbackMsgProc( LPDXUTCALLBACKMSGPROC pCallback, void* pUserContext = NULL ); +void WINAPI DXUTSetCallbackDeviceChanging( LPDXUTCALLBACKMODIFYDEVICESETTINGS pCallback, void* pUserContext = NULL ); +void WINAPI DXUTSetCallbackDeviceRemoved( LPDXUTCALLBACKDEVICEREMOVED pCallback, void* pUserContext = NULL ); + +// Direct3D 9 callbacks +void WINAPI DXUTSetCallbackD3D9DeviceAcceptable( LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE pCallback, void* pUserContext = NULL ); +void WINAPI DXUTSetCallbackD3D9DeviceCreated( LPDXUTCALLBACKD3D9DEVICECREATED pCallback, void* pUserContext = NULL ); +void WINAPI DXUTSetCallbackD3D9DeviceReset( LPDXUTCALLBACKD3D9DEVICERESET pCallback, void* pUserContext = NULL ); +void WINAPI DXUTSetCallbackD3D9FrameRender( LPDXUTCALLBACKD3D9FRAMERENDER pCallback, void* pUserContext = NULL ); +void WINAPI DXUTSetCallbackD3D9DeviceLost( LPDXUTCALLBACKD3D9DEVICELOST pCallback, void* pUserContext = NULL ); +void WINAPI DXUTSetCallbackD3D9DeviceDestroyed( LPDXUTCALLBACKD3D9DEVICEDESTROYED pCallback, void* pUserContext = NULL ); + +// Direct3D 11 callbacks +void WINAPI DXUTSetCallbackD3D11DeviceAcceptable( LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE pCallback, void* pUserContext = NULL ); +void WINAPI DXUTSetCallbackD3D11DeviceCreated( LPDXUTCALLBACKD3D11DEVICECREATED pCallback, void* pUserContext = NULL ); +void WINAPI DXUTSetCallbackD3D11SwapChainResized( LPDXUTCALLBACKD3D11SWAPCHAINRESIZED pCallback, void* pUserContext = NULL ); +void WINAPI DXUTSetCallbackD3D11FrameRender( LPDXUTCALLBACKD3D11FRAMERENDER pCallback, void* pUserContext = NULL ); +void WINAPI DXUTSetCallbackD3D11SwapChainReleasing( LPDXUTCALLBACKD3D11SWAPCHAINRELEASING pCallback, void* pUserContext = NULL ); +void WINAPI DXUTSetCallbackD3D11DeviceDestroyed( LPDXUTCALLBACKD3D11DEVICEDESTROYED pCallback, void* pUserContext = NULL ); + + +//-------------------------------------------------------------------------------------- +// Initialization +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTInit( bool bParseCommandLine = true, + bool bShowMsgBoxOnError = true, + __in_opt WCHAR* strExtraCommandLineParams = NULL, + bool bThreadSafeDXUT = false ); + +// Choose either DXUTCreateWindow or DXUTSetWindow. If using DXUTSetWindow, consider using DXUTStaticWndProc +HRESULT WINAPI DXUTCreateWindow( const WCHAR* strWindowTitle = L"Direct3D Window", + HINSTANCE hInstance = NULL, HICON hIcon = NULL, HMENU hMenu = NULL, + int x = CW_USEDEFAULT, int y = CW_USEDEFAULT ); +HRESULT WINAPI DXUTSetWindow( HWND hWndFocus, HWND hWndDeviceFullScreen, HWND hWndDeviceWindowed, bool bHandleMessages = true ); +LRESULT CALLBACK DXUTStaticWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + +// Choose either DXUTCreateDevice or DXUTSetD3D*Device or DXUTCreateD3DDeviceFromSettings + +HRESULT WINAPI DXUTCreateDevice(D3D_FEATURE_LEVEL reqFL, bool bWindowed= true, int nSuggestedWidth =0, int nSuggestedHeight =0 ); +HRESULT WINAPI DXUTCreateDeviceFromSettings( DXUTDeviceSettings* pDeviceSettings, bool bPreserveInput = false, bool bClipWindowToSingleAdapter = true ); +HRESULT WINAPI DXUTSetD3D9Device( IDirect3DDevice9* pd3dDevice ); +HRESULT WINAPI DXUTSetD3D11Device( ID3D11Device* pd3dDevice, IDXGISwapChain* pSwapChain ); + +// Choose either DXUTMainLoop or implement your own main loop +HRESULT WINAPI DXUTMainLoop( HACCEL hAccel = NULL ); + +// If not using DXUTMainLoop consider using DXUTRender3DEnvironment +void WINAPI DXUTRender3DEnvironment(); + + +//-------------------------------------------------------------------------------------- +// Common Tasks +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTToggleFullScreen(); +HRESULT WINAPI DXUTToggleREF(); +HRESULT WINAPI DXUTToggleWARP(); +void WINAPI DXUTPause( bool bPauseTime, bool bPauseRendering ); +void WINAPI DXUTSetConstantFrameTime( bool bConstantFrameTime, float fTimePerFrame = 0.0333f ); +void WINAPI DXUTSetCursorSettings( bool bShowCursorWhenFullScreen = false, bool bClipCursorWhenFullScreen = false ); +void WINAPI DXUTSetD3DVersionSupport( bool bAppCanUseD3D9 = true, bool bAppCanUseD3D11 = true ); +void WINAPI DXUTSetHotkeyHandling( bool bAltEnterToToggleFullscreen = true, bool bEscapeToQuit = true, bool bPauseToToggleTimePause = true ); +void WINAPI DXUTSetMultimonSettings( bool bAutoChangeAdapter = true ); +void WINAPI DXUTSetShortcutKeySettings( bool bAllowWhenFullscreen = false, bool bAllowWhenWindowed = true ); // Controls the Windows key, and accessibility shortcut keys +void WINAPI DXUTSetWindowSettings( bool bCallDefWindowProc = true ); +HRESULT WINAPI DXUTSetTimer( LPDXUTCALLBACKTIMER pCallbackTimer, float fTimeoutInSecs = 1.0f, UINT* pnIDEvent = NULL, void* pCallbackUserContext = NULL ); +HRESULT WINAPI DXUTKillTimer( UINT nIDEvent ); +void WINAPI DXUTResetFrameworkState(); +void WINAPI DXUTShutdown( int nExitCode = 0 ); +void WINAPI DXUTSetIsInGammaCorrectMode( bool bGammaCorrect ); +BOOL WINAPI DXUTGetMSAASwapChainCreated(); + +//-------------------------------------------------------------------------------------- +// State Retrieval +//-------------------------------------------------------------------------------------- + +// Direct3D 9 +IDirect3D9* WINAPI DXUTGetD3D9Object(); // Does not addref unlike typical Get* APIs +IDirect3DDevice9* WINAPI DXUTGetD3D9Device(); // Does not addref unlike typical Get* APIs +D3DPRESENT_PARAMETERS WINAPI DXUTGetD3D9PresentParameters(); +const D3DSURFACE_DESC* WINAPI DXUTGetD3D9BackBufferSurfaceDesc(); +const D3DCAPS9* WINAPI DXUTGetD3D9DeviceCaps(); +HRESULT WINAPI DXUTGetD3D9DeviceCaps( DXUTDeviceSettings* pDeviceSettings, D3DCAPS9* pCaps ); +bool WINAPI DXUTDoesAppSupportD3D9(); +bool WINAPI DXUTIsAppRenderingWithD3D9(); + + +// Direct3D 11 +IDXGIFactory1* WINAPI DXUTGetDXGIFactory(); // Does not addref unlike typical Get* APIs +IDXGISwapChain* WINAPI DXUTGetDXGISwapChain(); // Does not addref unlike typical Get* APIs +const DXGI_SURFACE_DESC* WINAPI DXUTGetDXGIBackBufferSurfaceDesc(); +bool WINAPI DXUTIsD3D11Available(); // If D3D11 APIs are availible +ID3D11Device* WINAPI DXUTGetD3D11Device(); // Does not addref unlike typical Get* APIs +ID3D11DeviceContext* WINAPI DXUTGetD3D11DeviceContext(); // Does not addref unlike typical Get* APIs +HRESULT WINAPI DXUTSetupD3D11Views( ID3D11DeviceContext* pd3dDeviceContext ); // Supports immediate or deferred context +D3D_FEATURE_LEVEL WINAPI DXUTGetD3D11DeviceFeatureLevel(); // Returns the D3D11 devices current feature level +ID3D11RenderTargetView* WINAPI DXUTGetD3D11RenderTargetView(); // Does not addref unlike typical Get* APIs +ID3D11DepthStencilView* WINAPI DXUTGetD3D11DepthStencilView(); // Does not addref unlike typical Get* APIs +bool WINAPI DXUTDoesAppSupportD3D11(); +bool WINAPI DXUTIsAppRenderingWithD3D11(); + + +// General +DXUTDeviceSettings WINAPI DXUTGetDeviceSettings(); +HINSTANCE WINAPI DXUTGetHINSTANCE(); +HWND WINAPI DXUTGetHWND(); +HWND WINAPI DXUTGetHWNDFocus(); +HWND WINAPI DXUTGetHWNDDeviceFullScreen(); +HWND WINAPI DXUTGetHWNDDeviceWindowed(); +RECT WINAPI DXUTGetWindowClientRect(); +LONG WINAPI DXUTGetWindowWidth(); +LONG WINAPI DXUTGetWindowHeight(); +RECT WINAPI DXUTGetWindowClientRectAtModeChange(); // Useful for returning to windowed mode with the same resolution as before toggle to full screen mode +RECT WINAPI DXUTGetFullsceenClientRectAtModeChange(); // Useful for returning to full screen mode with the same resolution as before toggle to windowed mode +double WINAPI DXUTGetTime(); +float WINAPI DXUTGetElapsedTime(); +bool WINAPI DXUTIsWindowed(); +bool WINAPI DXUTIsInGammaCorrectMode(); +float WINAPI DXUTGetFPS(); +LPCWSTR WINAPI DXUTGetWindowTitle(); +LPCWSTR WINAPI DXUTGetFrameStats( bool bIncludeFPS = false ); +LPCWSTR WINAPI DXUTGetDeviceStats(); + +bool WINAPI DXUTIsVsyncEnabled(); +bool WINAPI DXUTIsRenderingPaused(); +bool WINAPI DXUTIsTimePaused(); +bool WINAPI DXUTIsActive(); +int WINAPI DXUTGetExitCode(); +bool WINAPI DXUTGetShowMsgBoxOnError(); +bool WINAPI DXUTGetAutomation(); // Returns true if -automation parameter is used to launch the app +bool WINAPI DXUTIsKeyDown( BYTE vKey ); // Pass a virtual-key code, ex. VK_F1, 'A', VK_RETURN, VK_LSHIFT, etc +bool WINAPI DXUTWasKeyPressed( BYTE vKey ); // Like DXUTIsKeyDown() but return true only if the key was just pressed +bool WINAPI DXUTIsMouseButtonDown( BYTE vButton ); // Pass a virtual-key code: VK_LBUTTON, VK_RBUTTON, VK_MBUTTON, VK_XBUTTON1, VK_XBUTTON2 +HRESULT WINAPI DXUTCreateState(); // Optional method to create DXUT's memory. If its not called by the application it will be automatically called when needed +void WINAPI DXUTDestroyState(); // Optional method to destroy DXUT's memory. If its not called by the application it will be automatically called after the application exits WinMain + +//-------------------------------------------------------------------------------------- +// DXUT core layer includes +//-------------------------------------------------------------------------------------- +#include "DXUTmisc.h" +#include "DXUTDevice9.h" +#include "DXUTDevice11.h" + + + + +#endif + + + + diff --git a/Demos/DX11ClothDemo/DXUT/Core/DXUTDevice11.cpp b/Demos/DX11ClothDemo/DXUT/Core/DXUTDevice11.cpp new file mode 100644 index 0000000..7eaff55 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Core/DXUTDevice11.cpp @@ -0,0 +1,1154 @@ +//-------------------------------------------------------------------------------------- +// File: DXUTDevice11.cpp +// +// Enumerates D3D adapters, devices, modes, etc. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "DXUT.h" +#undef min // use __min instead +#undef max // use __max instead + +//-------------------------------------------------------------------------------------- +// Forward declarations +//-------------------------------------------------------------------------------------- +extern void DXUTGetCallbackD3D11DeviceAcceptable( LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE* ppCallbackIsDeviceAcceptable, void** ppUserContext ); + +static int __cdecl SortModesCallback( const void* arg1, const void* arg2 ); + +CD3D11Enumeration* g_pDXUTD3D11Enumeration = NULL; + + + + +HRESULT WINAPI DXUTCreateD3D11Enumeration() +{ + if( g_pDXUTD3D11Enumeration == NULL ) + { + g_pDXUTD3D11Enumeration = new CD3D11Enumeration(); + if( NULL == g_pDXUTD3D11Enumeration ) + return E_OUTOFMEMORY; + } + return S_OK; +} + +void WINAPI DXUTDestroyD3D11Enumeration() +{ + SAFE_DELETE( g_pDXUTD3D11Enumeration ); +} + +class DXUTMemoryHelperD3D11Enum +{ +public: +DXUTMemoryHelperD3D11Enum() +{ + DXUTCreateD3D11Enumeration(); +} +~DXUTMemoryHelperD3D11Enum() +{ + DXUTDestroyD3D11Enumeration(); +} +}; + + +//-------------------------------------------------------------------------------------- +CD3D11Enumeration* WINAPI DXUTGetD3D11Enumeration( bool bForceEnumerate, bool bEnumerateAllAdapterFormats, D3D_FEATURE_LEVEL forceFL ) +{ + // Using an static class with accessor function to allow control of the construction order + static DXUTMemoryHelperD3D11Enum d3d11enumMemory; + if( g_pDXUTD3D11Enumeration && ( !g_pDXUTD3D11Enumeration->HasEnumerated() || bForceEnumerate ) ) + { + g_pDXUTD3D11Enumeration->SetEnumerateAllAdapterFormats( bEnumerateAllAdapterFormats ); + LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE pCallbackIsDeviceAcceptable; + void* pUserContext; + DXUTGetCallbackD3D11DeviceAcceptable( &pCallbackIsDeviceAcceptable, &pUserContext ); + g_pDXUTD3D11Enumeration->SetForceFeatureLevel(forceFL); + + g_pDXUTD3D11Enumeration->Enumerate( pCallbackIsDeviceAcceptable, pUserContext ); + } + + return g_pDXUTD3D11Enumeration; +} + + +//-------------------------------------------------------------------------------------- +CD3D11Enumeration::CD3D11Enumeration() +{ + m_bHasEnumerated = false; + m_IsD3D11DeviceAcceptableFunc = NULL; + m_pIsD3D11DeviceAcceptableFuncUserContext = NULL; + + m_nMinWidth = 640; + m_nMinHeight = 480; + m_nMaxWidth = UINT_MAX; + m_nMaxHeight = UINT_MAX; + m_bEnumerateAllAdapterFormats = false; + + m_nRefreshMin = 0; + m_nRefreshMax = UINT_MAX; + + ResetPossibleDepthStencilFormats(); +} + + +//-------------------------------------------------------------------------------------- +CD3D11Enumeration::~CD3D11Enumeration() +{ + ClearAdapterInfoList(); +} + + +//-------------------------------------------------------------------------------------- +// Enumerate for each adapter all of the supported display modes, +// device types, adapter formats, back buffer formats, window/full screen support, +// depth stencil formats, multisampling types/qualities, and presentations intervals. +// +// For each combination of device type (HAL/REF), adapter format, back buffer format, and +// IsWindowed it will call the app's ConfirmDevice callback. This allows the app +// to reject or allow that combination based on its caps/etc. It also allows the +// app to change the BehaviorFlags. The BehaviorFlags defaults non-pure HWVP +// if supported otherwise it will default to SWVP, however the app can change this +// through the ConfirmDevice callback. +//-------------------------------------------------------------------------------------- +HRESULT CD3D11Enumeration::Enumerate( LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE IsD3D11DeviceAcceptableFunc, + void* pIsD3D11DeviceAcceptableFuncUserContext ) +{ + CDXUTPerfEventGenerator eventGenerator( DXUT_PERFEVENTCOLOR, L"DXUT D3D11 Enumeration" ); + HRESULT hr; + IDXGIFactory1* pFactory = DXUTGetDXGIFactory(); + if( pFactory == NULL ) + return E_FAIL; + + m_bHasEnumerated = true; + m_IsD3D11DeviceAcceptableFunc = IsD3D11DeviceAcceptableFunc; + m_pIsD3D11DeviceAcceptableFuncUserContext = pIsD3D11DeviceAcceptableFuncUserContext; + + ClearAdapterInfoList(); + + for( int index = 0; ; ++index ) + { + IDXGIAdapter* pAdapter = NULL; + hr = pFactory->EnumAdapters( index, &pAdapter ); + if( FAILED( hr ) ) // DXGIERR_NOT_FOUND is expected when the end of the list is hit + break; + + CD3D11EnumAdapterInfo* pAdapterInfo = new CD3D11EnumAdapterInfo; + if( !pAdapterInfo ) + { + SAFE_RELEASE( pAdapter ); + return E_OUTOFMEMORY; + } + ZeroMemory( pAdapterInfo, sizeof( CD3D11EnumAdapterInfo ) ); + pAdapterInfo->AdapterOrdinal = index; + pAdapter->GetDesc( &pAdapterInfo->AdapterDesc ); + pAdapterInfo->m_pAdapter = pAdapter; + + // Enumerate the device driver types on the adapter. + hr = EnumerateDevices( pAdapterInfo ); + if( FAILED( hr ) ) + { + delete pAdapterInfo; + continue; + } + + hr = EnumerateOutputs( pAdapterInfo ); + if( FAILED( hr ) || pAdapterInfo->outputInfoList.GetSize() <= 0 ) + { + delete pAdapterInfo; + continue; + } + + // Get info for each devicecombo on this device + if( FAILED( hr = EnumerateDeviceCombos( pFactory, pAdapterInfo ) ) ) + { + delete pAdapterInfo; + continue; + } + + hr = m_AdapterInfoList.Add( pAdapterInfo ); + if( FAILED( hr ) ) + { + delete pAdapterInfo; + return hr; + } + } + + + // If we did not get an adapter then we should still enumerate WARP and Ref. + if (m_AdapterInfoList.GetSize() == 0) { + + + CD3D11EnumAdapterInfo* pAdapterInfo = new CD3D11EnumAdapterInfo; + if( !pAdapterInfo ) + { + return E_OUTOFMEMORY; + } + ZeroMemory( pAdapterInfo, sizeof( CD3D11EnumAdapterInfo ) ); + pAdapterInfo->bAdapterUnavailable = true; + + hr = EnumerateDevices( pAdapterInfo ); + + // Get info for each devicecombo on this device + if( FAILED( hr = EnumerateDeviceCombosNoAdapter( pAdapterInfo ) ) ) + { + delete pAdapterInfo; + } + + if (!FAILED(hr)) hr = m_AdapterInfoList.Add( pAdapterInfo ); + } + + // + // Check for 2 or more adapters with the same name. Append the name + // with some instance number if that's the case to help distinguish + // them. + // + bool bUniqueDesc = true; + CD3D11EnumAdapterInfo* pAdapterInfo; + for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ ) + { + CD3D11EnumAdapterInfo* pAdapterInfo1 = m_AdapterInfoList.GetAt( i ); + + for( int j = i + 1; j < m_AdapterInfoList.GetSize(); j++ ) + { + CD3D11EnumAdapterInfo* pAdapterInfo2 = m_AdapterInfoList.GetAt( j ); + if( wcsncmp( pAdapterInfo1->AdapterDesc.Description, + pAdapterInfo2->AdapterDesc.Description, DXGI_MAX_DEVICE_IDENTIFIER_STRING ) == 0 ) + { + bUniqueDesc = false; + break; + } + } + + if( !bUniqueDesc ) + break; + } + + for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ ) + { + pAdapterInfo = m_AdapterInfoList.GetAt( i ); + + wcscpy_s( pAdapterInfo->szUniqueDescription, 100, pAdapterInfo->AdapterDesc.Description ); + if( !bUniqueDesc ) + { + WCHAR sz[100]; + swprintf_s( sz, 100, L" (#%d)", pAdapterInfo->AdapterOrdinal ); + wcscat_s( pAdapterInfo->szUniqueDescription, DXGI_MAX_DEVICE_IDENTIFIER_STRING, sz ); + } + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CD3D11Enumeration::EnumerateOutputs( CD3D11EnumAdapterInfo* pAdapterInfo ) +{ + HRESULT hr; + IDXGIOutput* pOutput; + + for( int iOutput = 0; ; ++iOutput ) + { + pOutput = NULL; + hr = pAdapterInfo->m_pAdapter->EnumOutputs( iOutput, &pOutput ); + if( DXGI_ERROR_NOT_FOUND == hr ) + { + return S_OK; + } + else if( FAILED( hr ) ) + { + return hr; //Something bad happened. + } + else //Success! + { + CD3D11EnumOutputInfo* pOutputInfo = new CD3D11EnumOutputInfo; + if( !pOutputInfo ) + { + SAFE_RELEASE( pOutput ); + return E_OUTOFMEMORY; + } + ZeroMemory( pOutputInfo, sizeof( CD3D11EnumOutputInfo ) ); + pOutput->GetDesc( &pOutputInfo->Desc ); + pOutputInfo->Output = iOutput; + pOutputInfo->m_pOutput = pOutput; + + EnumerateDisplayModes( pOutputInfo ); + if( pOutputInfo->displayModeList.GetSize() <= 0 ) + { + // If this output has no valid display mode, do not save it. + delete pOutputInfo; + continue; + } + + hr = pAdapterInfo->outputInfoList.Add( pOutputInfo ); + if( FAILED( hr ) ) + { + delete pOutputInfo; + return hr; + } + } + } +} + + +//-------------------------------------------------------------------------------------- +HRESULT CD3D11Enumeration::EnumerateDisplayModes( CD3D11EnumOutputInfo* pOutputInfo ) +{ + HRESULT hr = S_OK; + DXGI_FORMAT allowedAdapterFormatArray[] = + { + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, //This is DXUT's preferred mode + + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R10G10B10A2_UNORM + }; + int allowedAdapterFormatArrayCount = sizeof( allowedAdapterFormatArray ) / sizeof( allowedAdapterFormatArray[0] ); + + // Swap perferred modes for apps running in linear space + DXGI_FORMAT RemoteMode = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + if( !DXUTIsInGammaCorrectMode() ) + { + allowedAdapterFormatArray[0] = DXGI_FORMAT_R8G8B8A8_UNORM; + allowedAdapterFormatArray[1] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + RemoteMode = DXGI_FORMAT_R8G8B8A8_UNORM; + } + + // The fast path only enumerates R8G8B8A8_UNORM_SRGB modes + if( !m_bEnumerateAllAdapterFormats ) + allowedAdapterFormatArrayCount = 1; + + for( int f = 0; f < allowedAdapterFormatArrayCount; ++f ) + { + // Fast-path: Try to grab at least 512 modes. + // This is to avoid calling GetDisplayModeList more times than necessary. + // GetDisplayModeList is an expensive call. + UINT NumModes = 512; + DXGI_MODE_DESC* pDesc = new DXGI_MODE_DESC[ NumModes ]; + assert( pDesc ); + if( !pDesc ) + return E_OUTOFMEMORY; + + hr = pOutputInfo->m_pOutput->GetDisplayModeList( allowedAdapterFormatArray[f], + DXGI_ENUM_MODES_SCALING, + &NumModes, + pDesc ); + if( DXGI_ERROR_NOT_FOUND == hr ) + { + SAFE_DELETE_ARRAY( pDesc ); + NumModes = 0; + break; + } + else if( MAKE_DXGI_HRESULT( 34 ) == hr && RemoteMode == allowedAdapterFormatArray[f] ) + { + // DXGI cannot enumerate display modes over a remote session. Therefore, create a fake display + // mode for the current screen resolution for the remote session. + if( 0 != GetSystemMetrics( 0x1000 ) ) // SM_REMOTESESSION + { + DEVMODE DevMode; + DevMode.dmSize = sizeof( DEVMODE ); + if( EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &DevMode ) ) + { + NumModes = 1; + pDesc[0].Width = DevMode.dmPelsWidth; + pDesc[0].Height = DevMode.dmPelsHeight; + pDesc[0].Format = DXGI_FORMAT_R8G8B8A8_UNORM; + pDesc[0].RefreshRate.Numerator = 60; + pDesc[0].RefreshRate.Denominator = 1; + pDesc[0].ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE; + pDesc[0].Scaling = DXGI_MODE_SCALING_CENTERED; + hr = S_OK; + } + } + } + else if( DXGI_ERROR_MORE_DATA == hr ) + { + // Slow path. There were more than 512 modes. + SAFE_DELETE_ARRAY( pDesc ); + hr = pOutputInfo->m_pOutput->GetDisplayModeList( allowedAdapterFormatArray[f], + DXGI_ENUM_MODES_SCALING, + &NumModes, + NULL ); + if( FAILED( hr ) ) + { + NumModes = 0; + break; + } + + pDesc = new DXGI_MODE_DESC[ NumModes ]; + assert( pDesc ); + if( !pDesc ) + return E_OUTOFMEMORY; + + hr = pOutputInfo->m_pOutput->GetDisplayModeList( allowedAdapterFormatArray[f], + DXGI_ENUM_MODES_SCALING, + &NumModes, + pDesc ); + if( FAILED( hr ) ) + { + SAFE_DELETE_ARRAY( pDesc ); + NumModes = 0; + break; + } + + } + + if( 0 == NumModes && 0 == f ) + { + // No R8G8B8A8_UNORM_SRGB modes! + // Abort the fast-path if we're on it + allowedAdapterFormatArrayCount = sizeof( allowedAdapterFormatArray ) / sizeof + ( allowedAdapterFormatArray[0] ); + SAFE_DELETE_ARRAY( pDesc ); + continue; + } + + if( SUCCEEDED( hr ) ) + { + for( UINT m = 0; m < NumModes; m++ ) + { + pOutputInfo->displayModeList.Add( pDesc[m] ); + } + } + + SAFE_DELETE_ARRAY( pDesc ); + } + + return hr; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CD3D11Enumeration::EnumerateDevices( CD3D11EnumAdapterInfo* pAdapterInfo ) +{ + HRESULT hr; + DXUTDeviceSettings deviceSettings = DXUTGetDeviceSettings(); + const D3D_DRIVER_TYPE devTypeArray[] = + { + D3D_DRIVER_TYPE_HARDWARE, + D3D_DRIVER_TYPE_WARP, + D3D_DRIVER_TYPE_REFERENCE + }; + const UINT devTypeArrayCount = sizeof( devTypeArray ) / sizeof( devTypeArray[0] ); + + // Enumerate each Direct3D device type + for( UINT iDeviceType = 0; iDeviceType < devTypeArrayCount; iDeviceType++ ) + { + CD3D11EnumDeviceInfo* pDeviceInfo = new CD3D11EnumDeviceInfo; + if( pDeviceInfo == NULL ) + return E_OUTOFMEMORY; + + // Fill struct w/ AdapterOrdinal and D3DX10_DRIVER_TYPE + pDeviceInfo->AdapterOrdinal = pAdapterInfo->AdapterOrdinal; + pDeviceInfo->DeviceType = devTypeArray[iDeviceType]; + + D3D_FEATURE_LEVEL FeatureLevels[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, + D3D_FEATURE_LEVEL_9_1 + }; + UINT NumFeatureLevels = ARRAYSIZE( FeatureLevels ); + + // Call D3D11CreateDevice to ensure that this is a D3D11 device. + ID3D11Device* pd3dDevice = NULL; + ID3D11DeviceContext* pd3dDeviceContext = NULL; + IDXGIAdapter* pAdapter = NULL; + //if( devTypeArray[iDeviceType] == D3D_DRIVER_TYPE_HARDWARE ) + // pAdapter = pAdapterInfo->m_pAdapter; + hr = DXUT_Dynamic_D3D11CreateDevice( pAdapter, + devTypeArray[iDeviceType], + ( HMODULE )0, + 0, + FeatureLevels, + NumFeatureLevels, + D3D11_SDK_VERSION, + &pd3dDevice, + &pDeviceInfo->MaxLevel, + &pd3dDeviceContext ); + if( FAILED( hr ) || pDeviceInfo->MaxLevel < deviceSettings.MinimumFeatureLevel) + { + delete pDeviceInfo; + continue; + } + + if (g_forceFL == 0 || g_forceFL == pDeviceInfo->MaxLevel) { + pDeviceInfo->SelectedLevel = pDeviceInfo->MaxLevel; + } + else if (g_forceFL > pDeviceInfo->MaxLevel) { + delete pDeviceInfo; + SAFE_RELEASE( pd3dDevice ); + SAFE_RELEASE( pd3dDeviceContext ); + continue; + } else { + // A device was created with a higher feature level that the user-specified feature level. + SAFE_RELEASE( pd3dDevice ); + SAFE_RELEASE( pd3dDeviceContext ); + D3D_FEATURE_LEVEL rtFL; + hr = DXUT_Dynamic_D3D11CreateDevice( pAdapter, + devTypeArray[iDeviceType], + ( HMODULE )0, + 0, + &g_forceFL, + 1, + D3D11_SDK_VERSION, + &pd3dDevice, + &rtFL, + &pd3dDeviceContext ); + + if( !FAILED( hr ) && rtFL == g_forceFL ) { + + pDeviceInfo->SelectedLevel = g_forceFL; + }else { + delete pDeviceInfo; + SAFE_RELEASE( pd3dDevice ); + SAFE_RELEASE( pd3dDeviceContext ); + continue; + } + } + + IDXGIDevice1* pDXGIDev = NULL; + hr = pd3dDevice->QueryInterface( __uuidof( IDXGIDevice1 ), ( LPVOID* )&pDXGIDev ); + if( SUCCEEDED( hr ) && pDXGIDev ) + { + SAFE_RELEASE( pAdapterInfo->m_pAdapter ); + pDXGIDev->GetAdapter( &pAdapterInfo->m_pAdapter ); + } + SAFE_RELEASE( pDXGIDev ); + + + D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS ho; + pd3dDevice->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &ho, sizeof(ho)); + pDeviceInfo->ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x = ho.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x; + SAFE_RELEASE( pd3dDeviceContext ); + SAFE_RELEASE( pd3dDevice ); + pAdapterInfo->deviceInfoList.Add( pDeviceInfo ); + } + + return S_OK; +} + + +HRESULT CD3D11Enumeration::EnumerateDeviceCombosNoAdapter( CD3D11EnumAdapterInfo* pAdapterInfo ) +{ + // Iterate through each combination of device driver type, output, + // adapter format, and backbuffer format to build the adapter's device combo list. + // + + for( int device = 0; device < pAdapterInfo->deviceInfoList.GetSize(); ++device ) + { + CD3D11EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( device ); + + DXGI_FORMAT BufferFormatArray[] = + { + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, //This is DXUT's preferred mode + + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R10G10B10A2_UNORM + }; + const UINT BufferFormatArrayCount = sizeof( BufferFormatArray ) / sizeof + ( BufferFormatArray[0] ); + + // Swap perferred modes for apps running in linear space + if( !DXUTIsInGammaCorrectMode() ) + { + BufferFormatArray[0] = DXGI_FORMAT_R8G8B8A8_UNORM; + BufferFormatArray[1] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + } + + for( UINT iBufferFormat = 0; iBufferFormat < BufferFormatArrayCount; iBufferFormat++ ) + { + DXGI_FORMAT BufferFormat = BufferFormatArray[iBufferFormat]; + + + + // determine if there are any modes for this particular format + + + // If an application callback function has been provided, make sure this device + // is acceptable to the app. + if( m_IsD3D11DeviceAcceptableFunc != NULL ) + { + if( !m_IsD3D11DeviceAcceptableFunc( pAdapterInfo, + 0, + pDeviceInfo, + BufferFormat, + TRUE, + m_pIsD3D11DeviceAcceptableFuncUserContext ) ) + continue; + } + + // At this point, we have an adapter/device/backbufferformat/iswindowed + // DeviceCombo that is supported by the system. We still + // need to find one or more suitable depth/stencil buffer format, + // multisample type, and present interval. + CD3D11EnumDeviceSettingsCombo* pDeviceCombo = new CD3D11EnumDeviceSettingsCombo; + if( pDeviceCombo == NULL ) + return E_OUTOFMEMORY; + + pDeviceCombo->AdapterOrdinal = pDeviceInfo->AdapterOrdinal; + pDeviceCombo->DeviceType = pDeviceInfo->DeviceType; + pDeviceCombo->BackBufferFormat = BufferFormat; + pDeviceCombo->Windowed = TRUE; + pDeviceCombo->Output = 0; + pDeviceCombo->pAdapterInfo = pAdapterInfo; + pDeviceCombo->pDeviceInfo = pDeviceInfo; + pDeviceCombo->pOutputInfo = NULL; + + BuildMultiSampleQualityList( BufferFormat, pDeviceCombo ); + + if( FAILED( pAdapterInfo->deviceSettingsComboList.Add( pDeviceCombo ) ) ) + delete pDeviceCombo; + } + + } + + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CD3D11Enumeration::EnumerateDeviceCombos( IDXGIFactory1* pFactory, CD3D11EnumAdapterInfo* pAdapterInfo ) +{ + // Iterate through each combination of device driver type, output, + // adapter format, and backbuffer format to build the adapter's device combo list. + // + + for( int output = 0; output < pAdapterInfo->outputInfoList.GetSize(); ++output ) + { + CD3D11EnumOutputInfo* pOutputInfo = pAdapterInfo->outputInfoList.GetAt( output ); + + for( int device = 0; device < pAdapterInfo->deviceInfoList.GetSize(); ++device ) + { + CD3D11EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( device ); + + DXGI_FORMAT backBufferFormatArray[] = + { + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, //This is DXUT's preferred mode + + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R10G10B10A2_UNORM + }; + const UINT backBufferFormatArrayCount = sizeof( backBufferFormatArray ) / sizeof + ( backBufferFormatArray[0] ); + + // Swap perferred modes for apps running in linear space + if( !DXUTIsInGammaCorrectMode() ) + { + backBufferFormatArray[0] = DXGI_FORMAT_R8G8B8A8_UNORM; + backBufferFormatArray[1] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + } + + for( UINT iBackBufferFormat = 0; iBackBufferFormat < backBufferFormatArrayCount; iBackBufferFormat++ ) + { + DXGI_FORMAT backBufferFormat = backBufferFormatArray[iBackBufferFormat]; + + for( int nWindowed = 0; nWindowed < 2; nWindowed++ ) + { + if( !nWindowed && pOutputInfo->displayModeList.GetSize() == 0 ) + continue; + + // determine if there are any modes for this particular format + UINT iModes = 0; + for( int i = 0; i < pOutputInfo->displayModeList.GetSize(); i++ ) + { + if( backBufferFormat == pOutputInfo->displayModeList.GetAt( i ).Format ) + iModes ++; + } + if( 0 == iModes ) + continue; + + // If an application callback function has been provided, make sure this device + // is acceptable to the app. + if( m_IsD3D11DeviceAcceptableFunc != NULL ) + { + if( !m_IsD3D11DeviceAcceptableFunc( pAdapterInfo, output, + pDeviceInfo, backBufferFormat, + FALSE != nWindowed, + m_pIsD3D11DeviceAcceptableFuncUserContext ) ) + continue; + } + + // At this point, we have an adapter/device/backbufferformat/iswindowed + // DeviceCombo that is supported by the system. We still + // need to find one or more suitable depth/stencil buffer format, + // multisample type, and present interval. + CD3D11EnumDeviceSettingsCombo* pDeviceCombo = new CD3D11EnumDeviceSettingsCombo; + if( pDeviceCombo == NULL ) + return E_OUTOFMEMORY; + + pDeviceCombo->AdapterOrdinal = pDeviceInfo->AdapterOrdinal; + pDeviceCombo->DeviceType = pDeviceInfo->DeviceType; + pDeviceCombo->BackBufferFormat = backBufferFormat; + pDeviceCombo->Windowed = ( nWindowed != 0 ); + pDeviceCombo->Output = pOutputInfo->Output; + pDeviceCombo->pAdapterInfo = pAdapterInfo; + pDeviceCombo->pDeviceInfo = pDeviceInfo; + pDeviceCombo->pOutputInfo = pOutputInfo; + + BuildMultiSampleQualityList( backBufferFormat, pDeviceCombo ); + + if( FAILED( pAdapterInfo->deviceSettingsComboList.Add( pDeviceCombo ) ) ) + delete pDeviceCombo; + } + } + } + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Release all the allocated CD3D11EnumAdapterInfo objects and empty the list +//-------------------------------------------------------------------------------------- +void CD3D11Enumeration::ClearAdapterInfoList() +{ + CD3D11EnumAdapterInfo* pAdapterInfo; + for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ ) + { + pAdapterInfo = m_AdapterInfoList.GetAt( i ); + delete pAdapterInfo; + } + + m_AdapterInfoList.RemoveAll(); +} + + +//-------------------------------------------------------------------------------------- +void CD3D11Enumeration::ResetPossibleDepthStencilFormats() +{ + m_DepthStencilPossibleList.RemoveAll(); + m_DepthStencilPossibleList.Add( DXGI_FORMAT_D32_FLOAT_S8X24_UINT ); + m_DepthStencilPossibleList.Add( DXGI_FORMAT_D32_FLOAT ); + m_DepthStencilPossibleList.Add( DXGI_FORMAT_D24_UNORM_S8_UINT ); + m_DepthStencilPossibleList.Add( DXGI_FORMAT_D16_UNORM ); +} + +//-------------------------------------------------------------------------------------- +void CD3D11Enumeration::SetEnumerateAllAdapterFormats( bool bEnumerateAllAdapterFormats ) +{ + m_bEnumerateAllAdapterFormats = bEnumerateAllAdapterFormats; +} + + +//-------------------------------------------------------------------------------------- +void CD3D11Enumeration::BuildMultiSampleQualityList( DXGI_FORMAT fmt, CD3D11EnumDeviceSettingsCombo* pDeviceCombo ) +{ + ID3D11Device* pd3dDevice = NULL; + ID3D11DeviceContext* pd3dDeviceContext = NULL; + IDXGIAdapter* pAdapter = NULL; + + //if( pDeviceCombo->DeviceType == D3D_DRIVER_TYPE_HARDWARE ) + // DXUTGetDXGIFactory()->EnumAdapters( pDeviceCombo->pAdapterInfo->AdapterOrdinal, &pAdapter ); + + //DXGI_ADAPTER_DESC dad; + //pAdapter->GetDesc(&dad); + + D3D_FEATURE_LEVEL *FeatureLevels = &(pDeviceCombo->pDeviceInfo->SelectedLevel); + D3D_FEATURE_LEVEL returnedFeatureLevel; + + UINT NumFeatureLevels = 1; + + HRESULT hr = DXUT_Dynamic_D3D11CreateDevice( pAdapter, + pDeviceCombo->DeviceType, + ( HMODULE )0, + 0, + FeatureLevels, + NumFeatureLevels, + D3D11_SDK_VERSION, + &pd3dDevice, + &returnedFeatureLevel, + &pd3dDeviceContext ) ; + + if( FAILED( hr)) return; + + if (returnedFeatureLevel != pDeviceCombo->pDeviceInfo->SelectedLevel) return; + + for( int i = 1; i <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; ++i ) + { + UINT Quality; + if( SUCCEEDED( pd3dDevice->CheckMultisampleQualityLevels( fmt, i, &Quality ) ) && Quality > 0 ) + { + //From D3D10 docs: When multisampling a texture, the number of quality levels available for an adapter is dependent on the texture + //format used and the number of samples requested. The maximum sample count is defined by + //D3D10_MAX_MULTISAMPLE_SAMPLE_COUNT in d3d10.h. If the returned value of pNumQualityLevels is 0, + //the format and sample count combination is not supported for the installed adapter. + + if (Quality != 0) { + pDeviceCombo->multiSampleCountList.Add( i ); + pDeviceCombo->multiSampleQualityList.Add( Quality ); + } + } + } + + SAFE_RELEASE( pAdapter ); + SAFE_RELEASE( pd3dDevice ); + SAFE_RELEASE (pd3dDeviceContext); +} + + +//-------------------------------------------------------------------------------------- +// Call GetAdapterInfoList() after Enumerate() to get a STL vector of +// CD3D11EnumAdapterInfo* +//-------------------------------------------------------------------------------------- +CGrowableArray * CD3D11Enumeration::GetAdapterInfoList() +{ + return &m_AdapterInfoList; +} + + +//-------------------------------------------------------------------------------------- +CD3D11EnumAdapterInfo* CD3D11Enumeration::GetAdapterInfo( UINT AdapterOrdinal ) +{ + for( int iAdapter = 0; iAdapter < m_AdapterInfoList.GetSize(); iAdapter++ ) + { + CD3D11EnumAdapterInfo* pAdapterInfo = m_AdapterInfoList.GetAt( iAdapter ); + if( pAdapterInfo->AdapterOrdinal == AdapterOrdinal ) + return pAdapterInfo; + } + + return NULL; +} + + +//-------------------------------------------------------------------------------------- +CD3D11EnumDeviceInfo* CD3D11Enumeration::GetDeviceInfo( UINT AdapterOrdinal, D3D_DRIVER_TYPE DeviceType ) +{ + CD3D11EnumAdapterInfo* pAdapterInfo = GetAdapterInfo( AdapterOrdinal ); + if( pAdapterInfo ) + { + for( int iDeviceInfo = 0; iDeviceInfo < pAdapterInfo->deviceInfoList.GetSize(); iDeviceInfo++ ) + { + CD3D11EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( iDeviceInfo ); + if( pDeviceInfo->DeviceType == DeviceType ) + return pDeviceInfo; + } + } + + return NULL; +} + + +//-------------------------------------------------------------------------------------- +CD3D11EnumOutputInfo* CD3D11Enumeration::GetOutputInfo( UINT AdapterOrdinal, UINT Output ) +{ + CD3D11EnumAdapterInfo* pAdapterInfo = GetAdapterInfo( AdapterOrdinal ); + if( pAdapterInfo && pAdapterInfo->outputInfoList.GetSize() > int( Output ) ) + { + return pAdapterInfo->outputInfoList.GetAt( Output ); + } + + return NULL; +} + + +//-------------------------------------------------------------------------------------- +CD3D11EnumDeviceSettingsCombo* CD3D11Enumeration::GetDeviceSettingsCombo( UINT AdapterOrdinal, + D3D_DRIVER_TYPE DeviceType, UINT Output, + DXGI_FORMAT BackBufferFormat, BOOL Windowed ) +{ + CD3D11EnumAdapterInfo* pAdapterInfo = GetAdapterInfo( AdapterOrdinal ); + if( pAdapterInfo ) + { + for( int iDeviceCombo = 0; iDeviceCombo < pAdapterInfo->deviceSettingsComboList.GetSize(); iDeviceCombo++ ) + { + CD3D11EnumDeviceSettingsCombo* pDeviceSettingsCombo = pAdapterInfo->deviceSettingsComboList.GetAt( + iDeviceCombo ); + if( pDeviceSettingsCombo->BackBufferFormat == BackBufferFormat && + pDeviceSettingsCombo->Windowed == Windowed ) + return pDeviceSettingsCombo; + } + } + + return NULL; +} + + +//-------------------------------------------------------------------------------------- +CD3D11EnumOutputInfo::~CD3D11EnumOutputInfo( void ) +{ + SAFE_RELEASE( m_pOutput ); + displayModeList.RemoveAll(); +} + + +//-------------------------------------------------------------------------------------- +CD3D11EnumDeviceInfo::~CD3D11EnumDeviceInfo() +{ +} + + +//-------------------------------------------------------------------------------------- +CD3D11EnumAdapterInfo::~CD3D11EnumAdapterInfo( void ) +{ + for( int i = 0; i < outputInfoList.GetSize(); i++ ) + { + CD3D11EnumOutputInfo* pOutputInfo = outputInfoList.GetAt( i ); + delete pOutputInfo; + } + outputInfoList.RemoveAll(); + + for( int i = 0; i < deviceInfoList.GetSize(); ++i ) + { + CD3D11EnumDeviceInfo* pDeviceInfo = deviceInfoList.GetAt( i ); + delete pDeviceInfo; + } + deviceInfoList.RemoveAll(); + + for( int i = 0; i < deviceSettingsComboList.GetSize(); ++i ) + { + CD3D11EnumDeviceSettingsCombo* pDeviceCombo = deviceSettingsComboList.GetAt( i ); + delete pDeviceCombo; + } + deviceSettingsComboList.RemoveAll(); + + SAFE_RELEASE( m_pAdapter ); +} + +//-------------------------------------------------------------------------------------- +// Returns the number of color channel bits in the specified DXGI_FORMAT +//-------------------------------------------------------------------------------------- +UINT WINAPI DXUTGetDXGIColorChannelBits( DXGI_FORMAT fmt ) +{ + switch( fmt ) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return 32; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + return 16; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + return 10; + + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + return 8; + + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + return 5; + + default: + return 0; + } +} + +//-------------------------------------------------------------------------------------- +// Returns a ranking number that describes how closely this device +// combo matches the optimal combo based on the match options and the optimal device settings +//-------------------------------------------------------------------------------------- +float DXUTRankD3D11DeviceCombo( CD3D11EnumDeviceSettingsCombo* pDeviceSettingsCombo, + DXUTD3D11DeviceSettings* pOptimalDeviceSettings, + DXGI_MODE_DESC* pAdapterDisplayMode, + int &bestModeIndex, + int &bestMSAAIndex + ) +{ + float fCurRanking = 0.0f; + + // Arbitrary weights. Gives preference to the ordinal, device type, and windowed + const float fAdapterOrdinalWeight = 1000.0f; + const float fAdapterOutputWeight = 500.0f; + const float fDeviceTypeWeight = 100.0f; + const float fWARPOverRefWeight = 80.0f; + + const float fWindowWeight = 10.0f; + const float fResolutionWeight = 1.0f; + const float fBackBufferFormatWeight = 1.0f; + const float fMultiSampleWeight = 1.0f; + const float fRefreshRateWeight = 1.0f; + + //--------------------- + // Adapter ordinal + //--------------------- + if( pDeviceSettingsCombo->AdapterOrdinal == pOptimalDeviceSettings->AdapterOrdinal ) + fCurRanking += fAdapterOrdinalWeight; + + //--------------------- + // Adapter ordinal + //--------------------- + if( pDeviceSettingsCombo->Output == pOptimalDeviceSettings->Output ) + fCurRanking += fAdapterOutputWeight; + + //--------------------- + // Device type + //--------------------- + if( pDeviceSettingsCombo->DeviceType == pOptimalDeviceSettings->DriverType ) + fCurRanking += fDeviceTypeWeight; + else if (pDeviceSettingsCombo->DeviceType == D3D_DRIVER_TYPE_WARP && pOptimalDeviceSettings->DriverType == D3D_DRIVER_TYPE_HARDWARE) { + fCurRanking += fWARPOverRefWeight; + } + + // Slightly prefer HAL + if( pDeviceSettingsCombo->DeviceType == D3DDEVTYPE_HAL ) + fCurRanking += 0.1f; + + //--------------------- + // Windowed + //--------------------- + if( pDeviceSettingsCombo->Windowed == pOptimalDeviceSettings->sd.Windowed ) + fCurRanking += fWindowWeight; + + //--------------------- + // Resolution + //--------------------- + bool bResolutionFound = false; + unsigned int best = 0xffffffff; + bestModeIndex=0; + for( int idm = 0; pDeviceSettingsCombo->pOutputInfo != NULL && idm < pDeviceSettingsCombo->pOutputInfo->displayModeList.GetSize() && !bResolutionFound; idm++ ) + { + DXGI_MODE_DESC displayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList.GetAt( idm ); + if( displayMode.Width == pOptimalDeviceSettings->sd.BufferDesc.Width && + displayMode.Height == pOptimalDeviceSettings->sd.BufferDesc.Height ) + bResolutionFound = true; + + unsigned int current = + (UINT) abs ((int)displayMode.Width - (int)pOptimalDeviceSettings->sd.BufferDesc.Width) + + (UINT) abs ((int)displayMode.Height - (int)pOptimalDeviceSettings->sd.BufferDesc.Height ); + + if (current < best) { + best = current; + bestModeIndex= idm; + + } + + } + if( bResolutionFound ) + fCurRanking += fResolutionWeight; + + //--------------------- + // Back buffer format + //--------------------- + if( pDeviceSettingsCombo->BackBufferFormat == pOptimalDeviceSettings->sd.BufferDesc.Format ) + { + fCurRanking += fBackBufferFormatWeight; + } + else + { + int nBitDepthDelta = abs( ( long )DXUTGetDXGIColorChannelBits( pDeviceSettingsCombo->BackBufferFormat ) - + ( long )DXUTGetDXGIColorChannelBits( + pOptimalDeviceSettings->sd.BufferDesc.Format ) ); + float fScale = __max( 0.9f - ( float )nBitDepthDelta * 0.2f, 0.0f ); + fCurRanking += fScale * fBackBufferFormatWeight; + } + + //--------------------- + // Back buffer count + //--------------------- + // No caps for the back buffer count + + //--------------------- + // Multisample + //--------------------- + bool bMultiSampleFound = false; + bestMSAAIndex = 0; + for( int i = 0; i < pDeviceSettingsCombo->multiSampleCountList.GetSize(); i++ ) + { + UINT Count = pDeviceSettingsCombo->multiSampleCountList.GetAt( i ); + + if( Count == pOptimalDeviceSettings->sd.SampleDesc.Count ) + { + bestMSAAIndex = i; + bMultiSampleFound = true; + break; + } + } + if( bMultiSampleFound ) + fCurRanking += fMultiSampleWeight; + + //--------------------- + // Swap effect + //--------------------- + // No caps for swap effects + + //--------------------- + // Depth stencil + //--------------------- + // No caps for swap effects + + //--------------------- + // Present flags + //--------------------- + // No caps for the present flags + + //--------------------- + // Refresh rate + //--------------------- + bool bRefreshFound = false; + for( int idm = 0; pDeviceSettingsCombo->pOutputInfo != NULL && idm < pDeviceSettingsCombo->pOutputInfo->displayModeList.GetSize(); idm++ ) + { + DXGI_MODE_DESC displayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList.GetAt( idm ); + if( fabs( float( displayMode.RefreshRate.Numerator ) / displayMode.RefreshRate.Denominator - + float( pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Numerator ) / + pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Denominator ) < 0.1f ) + bRefreshFound = true; + } + if( bRefreshFound ) + fCurRanking += fRefreshRateWeight; + + //--------------------- + // Present interval + //--------------------- + // No caps for the present flags + + return fCurRanking; +} + + +//-------------------------------------------------------------------------------------- +// Returns the DXGI_MODE_DESC struct for a given adapter and output +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTGetD3D11AdapterDisplayMode( UINT AdapterOrdinal, UINT nOutput, DXGI_MODE_DESC* pModeDesc ) +{ + if( !pModeDesc ) + return E_INVALIDARG; + + CD3D11Enumeration* pD3DEnum = DXUTGetD3D11Enumeration(); + CD3D11EnumOutputInfo* pOutputInfo = pD3DEnum->GetOutputInfo( AdapterOrdinal, nOutput ); + if( pOutputInfo ) + { + pModeDesc->Width = 640; + pModeDesc->Height = 480; + pModeDesc->RefreshRate.Numerator = 60; + pModeDesc->RefreshRate.Denominator = 1; + pModeDesc->Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + pModeDesc->Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + pModeDesc->ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + + DXGI_OUTPUT_DESC Desc; + pOutputInfo->m_pOutput->GetDesc( &Desc ); + pModeDesc->Width = Desc.DesktopCoordinates.right - Desc.DesktopCoordinates.left; + pModeDesc->Height = Desc.DesktopCoordinates.bottom - Desc.DesktopCoordinates.top; + } + + // TODO: verify this is needed + if( pModeDesc->Format == DXGI_FORMAT_B8G8R8A8_UNORM ) + pModeDesc->Format = DXGI_FORMAT_R8G8B8A8_UNORM; + + return S_OK; +} diff --git a/Demos/DX11ClothDemo/DXUT/Core/DXUTDevice11.h b/Demos/DX11ClothDemo/DXUT/Core/DXUTDevice11.h new file mode 100644 index 0000000..c15c571 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Core/DXUTDevice11.h @@ -0,0 +1,210 @@ +//-------------------------------------------------------------------------------------- +// File: DXUTDevice11.h +// +// Enumerates D3D adapters, devices, modes, etc. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once +#ifndef DXUT_DEVICE11_H +#define DXUT_DEVICE11_H + +void DXUTApplyDefaultDeviceSettings(DXUTDeviceSettings *modifySettings); + +//-------------------------------------------------------------------------------------- +// Functions to get bit depth from formats +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTGetD3D11AdapterDisplayMode( UINT AdapterOrdinal, UINT Output, DXGI_MODE_DESC* pModeDesc ); + + + + +//-------------------------------------------------------------------------------------- +// Optional memory create/destory functions. If not call, these will be called automatically +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTCreateD3D11Enumeration(); +void WINAPI DXUTDestroyD3D11Enumeration(); + + + + +//-------------------------------------------------------------------------------------- +// Forward declarations +//-------------------------------------------------------------------------------------- +class CD3D11EnumAdapterInfo; +class CD3D11EnumDeviceInfo; +class CD3D11EnumOutputInfo; +struct CD3D11EnumDeviceSettingsCombo; + + + +//-------------------------------------------------------------------------------------- +// Enumerates available Direct3D10 adapters, devices, modes, etc. +// Use DXUTGetD3D9Enumeration() to access global instance +//-------------------------------------------------------------------------------------- +class CD3D11Enumeration +{ +public: + // These should be called before Enumerate(). + // + // Use these calls and the IsDeviceAcceptable to control the contents of + // the enumeration object, which affects the device selection and the device settings dialog. + void SetResolutionMinMax( UINT nMinWidth, UINT nMinHeight, UINT nMaxWidth, UINT nMaxHeight ); + void SetRefreshMinMax( UINT nMin, UINT nMax ); + void SetForceFeatureLevel( D3D_FEATURE_LEVEL forceFL) { + g_forceFL = forceFL; + }; + void SetMultisampleQualityMax( UINT nMax ); + CGrowableArray* GetPossibleDepthStencilFormatList(); + void ResetPossibleDepthStencilFormats(); + void SetEnumerateAllAdapterFormats( bool bEnumerateAllAdapterFormats ); + + // Call Enumerate() to enumerate available D3D11 adapters, devices, modes, etc. + bool HasEnumerated() { return m_bHasEnumerated; } + HRESULT Enumerate( LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE IsD3D11DeviceAcceptableFunc, + void* pIsD3D11DeviceAcceptableFuncUserContext ); + + // These should be called after Enumerate() is called + CGrowableArray* GetAdapterInfoList(); + CD3D11EnumAdapterInfo* GetAdapterInfo( UINT AdapterOrdinal ); + CD3D11EnumDeviceInfo* GetDeviceInfo( UINT AdapterOrdinal, D3D_DRIVER_TYPE DeviceType ); + CD3D11EnumOutputInfo* GetOutputInfo( UINT AdapterOrdinal, UINT Output ); + CD3D11EnumDeviceSettingsCombo* GetDeviceSettingsCombo( DXUTD3D11DeviceSettings* pDeviceSettings ) { return GetDeviceSettingsCombo( pDeviceSettings->AdapterOrdinal, pDeviceSettings->DriverType, pDeviceSettings->Output, pDeviceSettings->sd.BufferDesc.Format, pDeviceSettings->sd.Windowed ); } + CD3D11EnumDeviceSettingsCombo* GetDeviceSettingsCombo( UINT AdapterOrdinal, D3D_DRIVER_TYPE DeviceType, UINT Output, DXGI_FORMAT BackBufferFormat, BOOL Windowed ); + + ~CD3D11Enumeration(); + +private: + friend HRESULT WINAPI DXUTCreateD3D11Enumeration(); + + // Use DXUTGetD3D11Enumeration() to access global instance + CD3D11Enumeration(); + + bool m_bHasEnumerated; + LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE m_IsD3D11DeviceAcceptableFunc; + void* m_pIsD3D11DeviceAcceptableFuncUserContext; + + CGrowableArray m_DepthStencilPossibleList; + + UINT m_nMinWidth; + UINT m_nMaxWidth; + UINT m_nMinHeight; + UINT m_nMaxHeight; + UINT m_nRefreshMin; + UINT m_nRefreshMax; + UINT m_nMultisampleQualityMax; + bool m_bEnumerateAllAdapterFormats; + D3D_FEATURE_LEVEL g_forceFL; + + // Array of CD3D9EnumAdapterInfo* with unique AdapterOrdinals + CGrowableArray m_AdapterInfoList; + + HRESULT EnumerateOutputs( CD3D11EnumAdapterInfo *pAdapterInfo ); + HRESULT EnumerateDevices( CD3D11EnumAdapterInfo *pAdapterInfo ); + HRESULT EnumerateDeviceCombos( IDXGIFactory1 *pFactory, CD3D11EnumAdapterInfo* pAdapterInfo ); + HRESULT EnumerateDeviceCombosNoAdapter( CD3D11EnumAdapterInfo* pAdapterInfo ); + + HRESULT EnumerateDisplayModes( CD3D11EnumOutputInfo *pOutputInfo ); + void BuildMultiSampleQualityList( DXGI_FORMAT fmt, CD3D11EnumDeviceSettingsCombo* pDeviceCombo ); + void ClearAdapterInfoList(); +}; + +CD3D11Enumeration* WINAPI DXUTGetD3D11Enumeration(bool bForceEnumerate = false, bool EnumerateAllAdapterFormats = false, D3D_FEATURE_LEVEL forceFL = ((D3D_FEATURE_LEVEL )0) ); + + +#define DXGI_MAX_DEVICE_IDENTIFIER_STRING 128 + +//-------------------------------------------------------------------------------------- +// A class describing an adapter which contains a unique adapter ordinal +// that is installed on the system +//-------------------------------------------------------------------------------------- +class CD3D11EnumAdapterInfo +{ + const CD3D11EnumAdapterInfo &operator = ( const CD3D11EnumAdapterInfo &rhs ); + +public: + ~CD3D11EnumAdapterInfo(); + + UINT AdapterOrdinal; + DXGI_ADAPTER_DESC AdapterDesc; + WCHAR szUniqueDescription[DXGI_MAX_DEVICE_IDENTIFIER_STRING]; + IDXGIAdapter *m_pAdapter; + bool bAdapterUnavailable; + + CGrowableArray outputInfoList; // Array of CD3D11EnumOutputInfo* + CGrowableArray deviceInfoList; // Array of CD3D11EnumDeviceInfo* + // List of CD3D11EnumDeviceSettingsCombo* with a unique set + // of BackBufferFormat, and Windowed + CGrowableArray deviceSettingsComboList; +}; + + +class CD3D11EnumOutputInfo +{ + const CD3D11EnumOutputInfo &operator = ( const CD3D11EnumOutputInfo &rhs ); + +public: + ~CD3D11EnumOutputInfo(); + + UINT AdapterOrdinal; + UINT Output; + IDXGIOutput* m_pOutput; + DXGI_OUTPUT_DESC Desc; + + CGrowableArray displayModeList; // Array of supported D3DDISPLAYMODEs +}; + + +//-------------------------------------------------------------------------------------- +// A class describing a Direct3D10 device that contains a +// unique supported driver type +//-------------------------------------------------------------------------------------- +class CD3D11EnumDeviceInfo +{ + const CD3D11EnumDeviceInfo& operator =( const CD3D11EnumDeviceInfo& rhs ); + +public: + ~CD3D11EnumDeviceInfo(); + + UINT AdapterOrdinal; + D3D_DRIVER_TYPE DeviceType; + D3D_FEATURE_LEVEL SelectedLevel; + D3D_FEATURE_LEVEL MaxLevel; + BOOL ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x; +}; + + +//-------------------------------------------------------------------------------------- +// A struct describing device settings that contains a unique combination of +// adapter format, back buffer format, and windowed that is compatible with a +// particular Direct3D device and the app. +//-------------------------------------------------------------------------------------- +struct CD3D11EnumDeviceSettingsCombo +{ + UINT AdapterOrdinal; + D3D_DRIVER_TYPE DeviceType; + DXGI_FORMAT BackBufferFormat; + BOOL Windowed; + UINT Output; + + CGrowableArray multiSampleCountList; // List of valid sampling counts (multisampling) + CGrowableArray multiSampleQualityList; // List of number of quality levels for each multisample count + + CD3D11EnumAdapterInfo* pAdapterInfo; + CD3D11EnumDeviceInfo* pDeviceInfo; + CD3D11EnumOutputInfo* pOutputInfo; +}; + +float DXUTRankD3D11DeviceCombo( CD3D11EnumDeviceSettingsCombo* pDeviceSettingsCombo, + DXUTD3D11DeviceSettings* pOptimalDeviceSettings, + DXGI_MODE_DESC* pAdapterDisplayMode, + int &bestModeIndex, + int &bestMSAAIndex + ); + + + + +#endif + + diff --git a/Demos/DX11ClothDemo/DXUT/Core/DXUTDevice9.cpp b/Demos/DX11ClothDemo/DXUT/Core/DXUTDevice9.cpp new file mode 100644 index 0000000..a1d12e3 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Core/DXUTDevice9.cpp @@ -0,0 +1,1177 @@ +//-------------------------------------------------------------------------------------- +// File: DXUTDevice9.cpp +// +// Enumerates D3D adapters, devices, modes, etc. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "DXUT.h" +#undef min // use __min instead +#undef max // use __max instead + +//-------------------------------------------------------------------------------------- +// Forward declarations +//-------------------------------------------------------------------------------------- +extern void DXUTGetCallbackD3D9DeviceAcceptable( LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE* ppCallbackIsDeviceAcceptable, void** ppUserContext ); + + + + +static int __cdecl SortModesCallback( const void* arg1, const void* arg2 ); + + +CD3D9Enumeration* g_pDXUTD3D9Enumeration = NULL; + +HRESULT WINAPI DXUTCreateD3D9Enumeration() +{ + if( g_pDXUTD3D9Enumeration == NULL ) + { + g_pDXUTD3D9Enumeration = new CD3D9Enumeration(); + if( NULL == g_pDXUTD3D9Enumeration ) + return E_OUTOFMEMORY; + } + return S_OK; +} + +void WINAPI DXUTDestroyD3D9Enumeration() +{ + SAFE_DELETE( g_pDXUTD3D9Enumeration ); +} + +class DXUTMemoryHelperD3D9Enum +{ +public: +DXUTMemoryHelperD3D9Enum() +{ + DXUTCreateD3D9Enumeration(); +} +~DXUTMemoryHelperD3D9Enum() +{ + DXUTDestroyD3D9Enumeration(); +} +}; + +//-------------------------------------------------------------------------------------- +CD3D9Enumeration* WINAPI DXUTGetD3D9Enumeration( bool bForceEnumerate ) +{ + // Using an static class with accessor function to allow control of the construction order + static DXUTMemoryHelperD3D9Enum d3d9enumMemory; + + if( g_pDXUTD3D9Enumeration && ( !g_pDXUTD3D9Enumeration->HasEnumerated() || bForceEnumerate ) ) + { + LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE pCallbackIsDeviceAcceptable; + void* pUserContext; + DXUTGetCallbackD3D9DeviceAcceptable( &pCallbackIsDeviceAcceptable, &pUserContext ); + g_pDXUTD3D9Enumeration->Enumerate( pCallbackIsDeviceAcceptable, pUserContext ); + } + + return g_pDXUTD3D9Enumeration; +} + + +//-------------------------------------------------------------------------------------- +CD3D9Enumeration::CD3D9Enumeration() +{ + m_bHasEnumerated = false; + m_pD3D = NULL; + m_IsD3D9DeviceAcceptableFunc = NULL; + m_pIsD3D9DeviceAcceptableFuncUserContext = NULL; + m_bRequirePostPixelShaderBlending = true; + + m_nMinWidth = 640; + m_nMinHeight = 480; + m_nMaxWidth = UINT_MAX; + m_nMaxHeight = UINT_MAX; + + m_nRefreshMin = 0; + m_nRefreshMax = UINT_MAX; + + m_nMultisampleQualityMax = 0xFFFF; + + ResetPossibleDepthStencilFormats(); + ResetPossibleMultisampleTypeList(); + ResetPossiblePresentIntervalList(); + SetPossibleVertexProcessingList( true, true, true, false ); +} + + +//-------------------------------------------------------------------------------------- +CD3D9Enumeration::~CD3D9Enumeration() +{ + ClearAdapterInfoList(); +} + + + +//-------------------------------------------------------------------------------------- +// Enumerate for each adapter all of the supported display modes, +// device types, adapter formats, back buffer formats, window/full screen support, +// depth stencil formats, multisampling types/qualities, and presentations intervals. +// +// For each combination of device type (HAL/REF), adapter format, back buffer format, and +// IsWindowed it will call the app's ConfirmDevice callback. This allows the app +// to reject or allow that combination based on its caps/etc. It also allows the +// app to change the BehaviorFlags. The BehaviorFlags defaults non-pure HWVP +// if supported otherwise it will default to SWVP, however the app can change this +// through the ConfirmDevice callback. +//-------------------------------------------------------------------------------------- +HRESULT CD3D9Enumeration::Enumerate( LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE IsD3D9DeviceAcceptableFunc, + void* pIsD3D9DeviceAcceptableFuncUserContext ) +{ + CDXUTPerfEventGenerator eventGenerator( DXUT_PERFEVENTCOLOR, L"DXUT D3D9 Enumeration" ); + IDirect3D9* pD3D = DXUTGetD3D9Object(); + if( pD3D == NULL ) + { + pD3D = DXUTGetD3D9Object(); + if( pD3D == NULL ) + return DXUTERR_NODIRECT3D; + } + + m_bHasEnumerated = true; + m_pD3D = pD3D; + m_IsD3D9DeviceAcceptableFunc = IsD3D9DeviceAcceptableFunc; + m_pIsD3D9DeviceAcceptableFuncUserContext = pIsD3D9DeviceAcceptableFuncUserContext; + + HRESULT hr; + ClearAdapterInfoList(); + CGrowableArray adapterFormatList; + + const D3DFORMAT allowedAdapterFormatArray[] = + { + D3DFMT_X8R8G8B8, + D3DFMT_X1R5G5B5, + D3DFMT_R5G6B5, + D3DFMT_A2R10G10B10 + }; + const UINT allowedAdapterFormatArrayCount = sizeof( allowedAdapterFormatArray ) / sizeof + ( allowedAdapterFormatArray[0] ); + + UINT numAdapters = pD3D->GetAdapterCount(); + for( UINT adapterOrdinal = 0; adapterOrdinal < numAdapters; adapterOrdinal++ ) + { + CD3D9EnumAdapterInfo* pAdapterInfo = new CD3D9EnumAdapterInfo; + if( pAdapterInfo == NULL ) + return E_OUTOFMEMORY; + + pAdapterInfo->AdapterOrdinal = adapterOrdinal; + pD3D->GetAdapterIdentifier( adapterOrdinal, 0, &pAdapterInfo->AdapterIdentifier ); + + // Get list of all display modes on this adapter. + // Also build a temporary list of all display adapter formats. + adapterFormatList.RemoveAll(); + + for( UINT iFormatList = 0; iFormatList < allowedAdapterFormatArrayCount; iFormatList++ ) + { + D3DFORMAT allowedAdapterFormat = allowedAdapterFormatArray[iFormatList]; + UINT numAdapterModes = pD3D->GetAdapterModeCount( adapterOrdinal, allowedAdapterFormat ); + for( UINT mode = 0; mode < numAdapterModes; mode++ ) + { + D3DDISPLAYMODE displayMode; + pD3D->EnumAdapterModes( adapterOrdinal, allowedAdapterFormat, mode, &displayMode ); + + if( displayMode.Width < m_nMinWidth || + displayMode.Height < m_nMinHeight || + displayMode.Width > m_nMaxWidth || + displayMode.Height > m_nMaxHeight || + displayMode.RefreshRate < m_nRefreshMin || + displayMode.RefreshRate > m_nRefreshMax ) + { + continue; + } + + pAdapterInfo->displayModeList.Add( displayMode ); + + if( !adapterFormatList.Contains( displayMode.Format ) ) + adapterFormatList.Add( displayMode.Format ); + } + + } + + D3DDISPLAYMODE displayMode; + pD3D->GetAdapterDisplayMode( adapterOrdinal, &displayMode ); + if( !adapterFormatList.Contains( displayMode.Format ) ) + adapterFormatList.Add( displayMode.Format ); + + // Sort displaymode list + qsort( pAdapterInfo->displayModeList.GetData(), + pAdapterInfo->displayModeList.GetSize(), sizeof( D3DDISPLAYMODE ), + SortModesCallback ); + + // Get info for each device on this adapter + if( FAILED( EnumerateDevices( pAdapterInfo, &adapterFormatList ) ) ) + { + delete pAdapterInfo; + continue; + } + + // If at least one device on this adapter is available and compatible + // with the app, add the adapterInfo to the list + if( pAdapterInfo->deviceInfoList.GetSize() > 0 ) + { + hr = m_AdapterInfoList.Add( pAdapterInfo ); + if( FAILED( hr ) ) + return hr; + } + else + delete pAdapterInfo; + } + + // + // Check for 2 or more adapters with the same name. Append the name + // with some instance number if that's the case to help distinguish + // them. + // + bool bUniqueDesc = true; + CD3D9EnumAdapterInfo* pAdapterInfo; + for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ ) + { + CD3D9EnumAdapterInfo* pAdapterInfo1 = m_AdapterInfoList.GetAt( i ); + + for( int j = i + 1; j < m_AdapterInfoList.GetSize(); j++ ) + { + CD3D9EnumAdapterInfo* pAdapterInfo2 = m_AdapterInfoList.GetAt( j ); + if( _stricmp( pAdapterInfo1->AdapterIdentifier.Description, + pAdapterInfo2->AdapterIdentifier.Description ) == 0 ) + { + bUniqueDesc = false; + break; + } + } + + if( !bUniqueDesc ) + break; + } + + for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ ) + { + pAdapterInfo = m_AdapterInfoList.GetAt( i ); + + MultiByteToWideChar( CP_ACP, 0, + pAdapterInfo->AdapterIdentifier.Description, -1, + pAdapterInfo->szUniqueDescription, 100 ); + pAdapterInfo->szUniqueDescription[100] = 0; + + if( !bUniqueDesc ) + { + WCHAR sz[100]; + swprintf_s( sz, 100, L" (#%d)", pAdapterInfo->AdapterOrdinal ); + wcscat_s( pAdapterInfo->szUniqueDescription, 256, sz ); + + } + } + + return S_OK; +} + + + +//-------------------------------------------------------------------------------------- +// Enumerates D3D devices for a particular adapter. +//-------------------------------------------------------------------------------------- +HRESULT CD3D9Enumeration::EnumerateDevices( CD3D9EnumAdapterInfo* pAdapterInfo, + CGrowableArray * pAdapterFormatList ) +{ + HRESULT hr; + + const D3DDEVTYPE devTypeArray[] = + { + D3DDEVTYPE_HAL, + D3DDEVTYPE_SW, + D3DDEVTYPE_REF + }; + const UINT devTypeArrayCount = sizeof( devTypeArray ) / sizeof( devTypeArray[0] ); + + // Enumerate each Direct3D device type + for( UINT iDeviceType = 0; iDeviceType < devTypeArrayCount; iDeviceType++ ) + { + CD3D9EnumDeviceInfo* pDeviceInfo = new CD3D9EnumDeviceInfo; + if( pDeviceInfo == NULL ) + return E_OUTOFMEMORY; + + // Fill struct w/ AdapterOrdinal and D3DDEVTYPE + pDeviceInfo->AdapterOrdinal = pAdapterInfo->AdapterOrdinal; + pDeviceInfo->DeviceType = devTypeArray[iDeviceType]; + + // Store device caps + if( FAILED( hr = m_pD3D->GetDeviceCaps( pAdapterInfo->AdapterOrdinal, pDeviceInfo->DeviceType, + &pDeviceInfo->Caps ) ) ) + { + delete pDeviceInfo; + continue; + } + + if( pDeviceInfo->DeviceType != D3DDEVTYPE_HAL ) + { + // Create a temp device to verify that it is really possible to create a REF device + // [the developer DirectX redist has to be installed] + D3DDISPLAYMODE Mode; + m_pD3D->GetAdapterDisplayMode( 0, &Mode ); + D3DPRESENT_PARAMETERS pp; + ZeroMemory( &pp, sizeof( D3DPRESENT_PARAMETERS ) ); + pp.BackBufferWidth = 1; + pp.BackBufferHeight = 1; + pp.BackBufferFormat = Mode.Format; + pp.BackBufferCount = 1; + pp.SwapEffect = D3DSWAPEFFECT_COPY; + pp.Windowed = TRUE; + pp.hDeviceWindow = DXUTGetHWNDFocus(); + IDirect3DDevice9* pDevice = NULL; + if( FAILED( hr = m_pD3D->CreateDevice( pAdapterInfo->AdapterOrdinal, pDeviceInfo->DeviceType, + DXUTGetHWNDFocus(), + D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &pp, + &pDevice ) ) ) + { + delete pDeviceInfo; + continue; + } + SAFE_RELEASE( pDevice ); + } + + // Get info for each devicecombo on this device + if( FAILED( hr = EnumerateDeviceCombos( pAdapterInfo, pDeviceInfo, pAdapterFormatList ) ) ) + { + delete pDeviceInfo; + continue; + } + + // If at least one devicecombo for this device is found, + // add the deviceInfo to the list + if( pDeviceInfo->deviceSettingsComboList.GetSize() > 0 ) + pAdapterInfo->deviceInfoList.Add( pDeviceInfo ); + else + delete pDeviceInfo; + } + + return S_OK; +} + + + +//-------------------------------------------------------------------------------------- +// Enumerates DeviceCombos for a particular device. +//-------------------------------------------------------------------------------------- +HRESULT CD3D9Enumeration::EnumerateDeviceCombos( CD3D9EnumAdapterInfo* pAdapterInfo, CD3D9EnumDeviceInfo* pDeviceInfo, + CGrowableArray * pAdapterFormatList ) +{ + const D3DFORMAT backBufferFormatArray[] = + { + D3DFMT_A8R8G8B8, + D3DFMT_X8R8G8B8, + D3DFMT_A2R10G10B10, + D3DFMT_R5G6B5, + D3DFMT_A1R5G5B5, + D3DFMT_X1R5G5B5 + }; + const UINT backBufferFormatArrayCount = sizeof( backBufferFormatArray ) / sizeof( backBufferFormatArray[0] ); + + // See which adapter formats are supported by this device + for( int iFormat = 0; iFormat < pAdapterFormatList->GetSize(); iFormat++ ) + { + D3DFORMAT adapterFormat = pAdapterFormatList->GetAt( iFormat ); + + for( UINT iBackBufferFormat = 0; iBackBufferFormat < backBufferFormatArrayCount; iBackBufferFormat++ ) + { + D3DFORMAT backBufferFormat = backBufferFormatArray[iBackBufferFormat]; + + for( int nWindowed = 0; nWindowed < 2; nWindowed++ ) + { + if( !nWindowed && pAdapterInfo->displayModeList.GetSize() == 0 ) + continue; + + if( FAILED( m_pD3D->CheckDeviceType( pAdapterInfo->AdapterOrdinal, pDeviceInfo->DeviceType, + adapterFormat, backBufferFormat, nWindowed ) ) ) + { + continue; + } + + if( m_bRequirePostPixelShaderBlending ) + { + // If the backbuffer format doesn't support D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING + // then alpha test, pixel fog, render-target blending, color write enable, and dithering. + // are not supported. + if( FAILED( m_pD3D->CheckDeviceFormat( pAdapterInfo->AdapterOrdinal, pDeviceInfo->DeviceType, + adapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, + D3DRTYPE_TEXTURE, backBufferFormat ) ) ) + { + continue; + } + } + + // If an application callback function has been provided, make sure this device + // is acceptable to the app. + if( m_IsD3D9DeviceAcceptableFunc != NULL ) + { + if( !m_IsD3D9DeviceAcceptableFunc( &pDeviceInfo->Caps, adapterFormat, backBufferFormat, + FALSE != nWindowed, m_pIsD3D9DeviceAcceptableFuncUserContext ) ) + continue; + } + + // At this point, we have an adapter/device/adapterformat/backbufferformat/iswindowed + // DeviceCombo that is supported by the system and acceptable to the app. We still + // need to find one or more suitable depth/stencil buffer format, + // multisample type, and present interval. + CD3D9EnumDeviceSettingsCombo* pDeviceCombo = new CD3D9EnumDeviceSettingsCombo; + if( pDeviceCombo == NULL ) + return E_OUTOFMEMORY; + + pDeviceCombo->AdapterOrdinal = pAdapterInfo->AdapterOrdinal; + pDeviceCombo->DeviceType = pDeviceInfo->DeviceType; + pDeviceCombo->AdapterFormat = adapterFormat; + pDeviceCombo->BackBufferFormat = backBufferFormat; + pDeviceCombo->Windowed = ( nWindowed != 0 ); + + BuildDepthStencilFormatList( pDeviceCombo ); + BuildMultiSampleTypeList( pDeviceCombo ); + if( pDeviceCombo->multiSampleTypeList.GetSize() == 0 ) + { + delete pDeviceCombo; + continue; + } + BuildDSMSConflictList( pDeviceCombo ); + BuildPresentIntervalList( pDeviceInfo, pDeviceCombo ); + pDeviceCombo->pAdapterInfo = pAdapterInfo; + pDeviceCombo->pDeviceInfo = pDeviceInfo; + + if( FAILED( pDeviceInfo->deviceSettingsComboList.Add( pDeviceCombo ) ) ) + delete pDeviceCombo; + } + } + } + + return S_OK; +} + + + +//-------------------------------------------------------------------------------------- +// Adds all depth/stencil formats that are compatible with the device +// and app to the given D3DDeviceCombo. +//-------------------------------------------------------------------------------------- +void CD3D9Enumeration::BuildDepthStencilFormatList( CD3D9EnumDeviceSettingsCombo* pDeviceCombo ) +{ + D3DFORMAT depthStencilFmt; + for( int idsf = 0; idsf < m_DepthStencilPossibleList.GetSize(); idsf++ ) + { + depthStencilFmt = m_DepthStencilPossibleList.GetAt( idsf ); + if( SUCCEEDED( m_pD3D->CheckDeviceFormat( pDeviceCombo->AdapterOrdinal, + pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat, + D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFmt ) ) ) + { + if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( pDeviceCombo->AdapterOrdinal, + pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat, + pDeviceCombo->BackBufferFormat, depthStencilFmt ) ) ) + { + pDeviceCombo->depthStencilFormatList.Add( depthStencilFmt ); + } + } + } +} + + + + +//-------------------------------------------------------------------------------------- +// Adds all multisample types that are compatible with the device and app to +// the given D3DDeviceCombo. +//-------------------------------------------------------------------------------------- +void CD3D9Enumeration::BuildMultiSampleTypeList( CD3D9EnumDeviceSettingsCombo* pDeviceCombo ) +{ + D3DMULTISAMPLE_TYPE msType; + DWORD msQuality; + for( int imst = 0; imst < m_MultiSampleTypeList.GetSize(); imst++ ) + { + msType = m_MultiSampleTypeList.GetAt( imst ); + if( SUCCEEDED( m_pD3D->CheckDeviceMultiSampleType( pDeviceCombo->AdapterOrdinal, + pDeviceCombo->DeviceType, pDeviceCombo->BackBufferFormat, + pDeviceCombo->Windowed, msType, &msQuality ) ) ) + { + pDeviceCombo->multiSampleTypeList.Add( msType ); + if( msQuality > m_nMultisampleQualityMax + 1 ) + msQuality = m_nMultisampleQualityMax + 1; + pDeviceCombo->multiSampleQualityList.Add( msQuality ); + } + } +} + + + + +//-------------------------------------------------------------------------------------- +// Find any conflicts between the available depth/stencil formats and +// multisample types. +//-------------------------------------------------------------------------------------- +void CD3D9Enumeration::BuildDSMSConflictList( CD3D9EnumDeviceSettingsCombo* pDeviceCombo ) +{ + CD3D9EnumDSMSConflict DSMSConflict; + + for( int iDS = 0; iDS < pDeviceCombo->depthStencilFormatList.GetSize(); iDS++ ) + { + D3DFORMAT dsFmt = pDeviceCombo->depthStencilFormatList.GetAt( iDS ); + + for( int iMS = 0; iMS < pDeviceCombo->multiSampleTypeList.GetSize(); iMS++ ) + { + D3DMULTISAMPLE_TYPE msType = pDeviceCombo->multiSampleTypeList.GetAt( iMS ); + + if( FAILED( m_pD3D->CheckDeviceMultiSampleType( pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, + dsFmt, pDeviceCombo->Windowed, msType, NULL ) ) ) + { + DSMSConflict.DSFormat = dsFmt; + DSMSConflict.MSType = msType; + pDeviceCombo->DSMSConflictList.Add( DSMSConflict ); + } + } + } +} + + +//-------------------------------------------------------------------------------------- +// Adds all present intervals that are compatible with the device and app +// to the given D3DDeviceCombo. +//-------------------------------------------------------------------------------------- +void CD3D9Enumeration::BuildPresentIntervalList( CD3D9EnumDeviceInfo* pDeviceInfo, + CD3D9EnumDeviceSettingsCombo* pDeviceCombo ) +{ + UINT pi; + for( int ipi = 0; ipi < m_PresentIntervalList.GetSize(); ipi++ ) + { + pi = m_PresentIntervalList.GetAt( ipi ); + if( pDeviceCombo->Windowed ) + { + if( pi == D3DPRESENT_INTERVAL_TWO || + pi == D3DPRESENT_INTERVAL_THREE || + pi == D3DPRESENT_INTERVAL_FOUR ) + { + // These intervals are not supported in windowed mode. + continue; + } + } + // Note that D3DPRESENT_INTERVAL_DEFAULT is zero, so you + // can't do a caps check for it -- it is always available. + if( pi == D3DPRESENT_INTERVAL_DEFAULT || + ( pDeviceInfo->Caps.PresentationIntervals & pi ) ) + { + pDeviceCombo->presentIntervalList.Add( pi ); + } + } +} + + + +//-------------------------------------------------------------------------------------- +// Release all the allocated CD3D9EnumAdapterInfo objects and empty the list +//-------------------------------------------------------------------------------------- +void CD3D9Enumeration::ClearAdapterInfoList() +{ + CD3D9EnumAdapterInfo* pAdapterInfo; + for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ ) + { + pAdapterInfo = m_AdapterInfoList.GetAt( i ); + delete pAdapterInfo; + } + + m_AdapterInfoList.RemoveAll(); +} + + + +//-------------------------------------------------------------------------------------- +// Call GetAdapterInfoList() after Enumerate() to get a STL vector of +// CD3D9EnumAdapterInfo* +//-------------------------------------------------------------------------------------- +CGrowableArray * CD3D9Enumeration::GetAdapterInfoList() +{ + return &m_AdapterInfoList; +} + + + +//-------------------------------------------------------------------------------------- +CD3D9EnumAdapterInfo* CD3D9Enumeration::GetAdapterInfo( UINT AdapterOrdinal ) +{ + for( int iAdapter = 0; iAdapter < m_AdapterInfoList.GetSize(); iAdapter++ ) + { + CD3D9EnumAdapterInfo* pAdapterInfo = m_AdapterInfoList.GetAt( iAdapter ); + if( pAdapterInfo->AdapterOrdinal == AdapterOrdinal ) + return pAdapterInfo; + } + + return NULL; +} + + +//-------------------------------------------------------------------------------------- +CD3D9EnumDeviceInfo* CD3D9Enumeration::GetDeviceInfo( UINT AdapterOrdinal, D3DDEVTYPE DeviceType ) +{ + CD3D9EnumAdapterInfo* pAdapterInfo = GetAdapterInfo( AdapterOrdinal ); + if( pAdapterInfo ) + { + for( int iDeviceInfo = 0; iDeviceInfo < pAdapterInfo->deviceInfoList.GetSize(); iDeviceInfo++ ) + { + CD3D9EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( iDeviceInfo ); + if( pDeviceInfo->DeviceType == DeviceType ) + return pDeviceInfo; + } + } + + return NULL; +} + + +//-------------------------------------------------------------------------------------- +// +//-------------------------------------------------------------------------------------- +CD3D9EnumDeviceSettingsCombo* CD3D9Enumeration::GetDeviceSettingsCombo( UINT AdapterOrdinal, D3DDEVTYPE DeviceType, + D3DFORMAT AdapterFormat, + D3DFORMAT BackBufferFormat, BOOL bWindowed ) +{ + CD3D9EnumDeviceInfo* pDeviceInfo = GetDeviceInfo( AdapterOrdinal, DeviceType ); + if( pDeviceInfo ) + { + for( int iDeviceCombo = 0; iDeviceCombo < pDeviceInfo->deviceSettingsComboList.GetSize(); iDeviceCombo++ ) + { + CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo = pDeviceInfo->deviceSettingsComboList.GetAt( + iDeviceCombo ); + if( pDeviceSettingsCombo->AdapterFormat == AdapterFormat && + pDeviceSettingsCombo->BackBufferFormat == BackBufferFormat && + pDeviceSettingsCombo->Windowed == bWindowed ) + return pDeviceSettingsCombo; + } + } + + return NULL; +} + + +//-------------------------------------------------------------------------------------- +// Returns the number of color channel bits in the specified D3DFORMAT +//-------------------------------------------------------------------------------------- +UINT WINAPI DXUTGetD3D9ColorChannelBits( D3DFORMAT fmt ) +{ + switch( fmt ) + { + case D3DFMT_R8G8B8: + return 8; + case D3DFMT_A8R8G8B8: + return 8; + case D3DFMT_X8R8G8B8: + return 8; + case D3DFMT_R5G6B5: + return 5; + case D3DFMT_X1R5G5B5: + return 5; + case D3DFMT_A1R5G5B5: + return 5; + case D3DFMT_A4R4G4B4: + return 4; + case D3DFMT_R3G3B2: + return 2; + case D3DFMT_A8R3G3B2: + return 2; + case D3DFMT_X4R4G4B4: + return 4; + case D3DFMT_A2B10G10R10: + return 10; + case D3DFMT_A8B8G8R8: + return 8; + case D3DFMT_A2R10G10B10: + return 10; + case D3DFMT_A16B16G16R16: + return 16; + default: + return 0; + } +} + + +//-------------------------------------------------------------------------------------- +// Returns the number of alpha channel bits in the specified D3DFORMAT +//-------------------------------------------------------------------------------------- +UINT WINAPI DXUTGetAlphaChannelBits( D3DFORMAT fmt ) +{ + switch( fmt ) + { + case D3DFMT_R8G8B8: + return 0; + case D3DFMT_A8R8G8B8: + return 8; + case D3DFMT_X8R8G8B8: + return 0; + case D3DFMT_R5G6B5: + return 0; + case D3DFMT_X1R5G5B5: + return 0; + case D3DFMT_A1R5G5B5: + return 1; + case D3DFMT_A4R4G4B4: + return 4; + case D3DFMT_R3G3B2: + return 0; + case D3DFMT_A8R3G3B2: + return 8; + case D3DFMT_X4R4G4B4: + return 0; + case D3DFMT_A2B10G10R10: + return 2; + case D3DFMT_A8B8G8R8: + return 8; + case D3DFMT_A2R10G10B10: + return 2; + case D3DFMT_A16B16G16R16: + return 16; + default: + return 0; + } +} + + +//-------------------------------------------------------------------------------------- +// Returns the number of depth bits in the specified D3DFORMAT +//-------------------------------------------------------------------------------------- +UINT WINAPI DXUTGetDepthBits( D3DFORMAT fmt ) +{ + switch( fmt ) + { + case D3DFMT_D32F_LOCKABLE: + case D3DFMT_D32: + return 32; + + case D3DFMT_D24X8: + case D3DFMT_D24S8: + case D3DFMT_D24X4S4: + case D3DFMT_D24FS8: + return 24; + + case D3DFMT_D16_LOCKABLE: + case D3DFMT_D16: + return 16; + + case D3DFMT_D15S1: + return 15; + + default: + return 0; + } +} + + + + +//-------------------------------------------------------------------------------------- +// Returns the number of stencil bits in the specified D3DFORMAT +//-------------------------------------------------------------------------------------- +UINT WINAPI DXUTGetStencilBits( D3DFORMAT fmt ) +{ + switch( fmt ) + { + case D3DFMT_D16_LOCKABLE: + case D3DFMT_D16: + case D3DFMT_D32F_LOCKABLE: + case D3DFMT_D32: + case D3DFMT_D24X8: + return 0; + + case D3DFMT_D15S1: + return 1; + + case D3DFMT_D24X4S4: + return 4; + + case D3DFMT_D24S8: + case D3DFMT_D24FS8: + return 8; + + default: + return 0; + } +} + + + +//-------------------------------------------------------------------------------------- +// Used to sort D3DDISPLAYMODEs +//-------------------------------------------------------------------------------------- +static int __cdecl SortModesCallback( const void* arg1, const void* arg2 ) +{ + D3DDISPLAYMODE* pdm1 = ( D3DDISPLAYMODE* )arg1; + D3DDISPLAYMODE* pdm2 = ( D3DDISPLAYMODE* )arg2; + + if( pdm1->Width > pdm2->Width ) + return 1; + if( pdm1->Width < pdm2->Width ) + return -1; + if( pdm1->Height > pdm2->Height ) + return 1; + if( pdm1->Height < pdm2->Height ) + return -1; + if( pdm1->Format > pdm2->Format ) + return 1; + if( pdm1->Format < pdm2->Format ) + return -1; + if( pdm1->RefreshRate > pdm2->RefreshRate ) + return 1; + if( pdm1->RefreshRate < pdm2->RefreshRate ) + return -1; + return 0; +} + + + +//-------------------------------------------------------------------------------------- +CD3D9EnumAdapterInfo::~CD3D9EnumAdapterInfo( void ) +{ + CD3D9EnumDeviceInfo* pDeviceInfo; + for( int i = 0; i < deviceInfoList.GetSize(); i++ ) + { + pDeviceInfo = deviceInfoList.GetAt( i ); + delete pDeviceInfo; + } + deviceInfoList.RemoveAll(); +} + + + + +//-------------------------------------------------------------------------------------- +CD3D9EnumDeviceInfo::~CD3D9EnumDeviceInfo( void ) +{ + CD3D9EnumDeviceSettingsCombo* pDeviceCombo; + for( int i = 0; i < deviceSettingsComboList.GetSize(); i++ ) + { + pDeviceCombo = deviceSettingsComboList.GetAt( i ); + delete pDeviceCombo; + } + deviceSettingsComboList.RemoveAll(); +} + + +//-------------------------------------------------------------------------------------- +void CD3D9Enumeration::ResetPossibleDepthStencilFormats() +{ + m_DepthStencilPossibleList.RemoveAll(); + m_DepthStencilPossibleList.Add( D3DFMT_D16 ); + m_DepthStencilPossibleList.Add( D3DFMT_D15S1 ); + m_DepthStencilPossibleList.Add( D3DFMT_D24X8 ); + m_DepthStencilPossibleList.Add( D3DFMT_D24S8 ); + m_DepthStencilPossibleList.Add( D3DFMT_D24X4S4 ); + m_DepthStencilPossibleList.Add( D3DFMT_D32 ); +} + + +//-------------------------------------------------------------------------------------- +CGrowableArray * CD3D9Enumeration::GetPossibleDepthStencilFormatList() +{ + return &m_DepthStencilPossibleList; +} + + +//-------------------------------------------------------------------------------------- +CGrowableArray * CD3D9Enumeration::GetPossibleMultisampleTypeList() +{ + return &m_MultiSampleTypeList; +} + + +//-------------------------------------------------------------------------------------- +void CD3D9Enumeration::ResetPossibleMultisampleTypeList() +{ + m_MultiSampleTypeList.RemoveAll(); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_NONE ); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_NONMASKABLE ); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_2_SAMPLES ); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_3_SAMPLES ); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_4_SAMPLES ); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_5_SAMPLES ); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_6_SAMPLES ); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_7_SAMPLES ); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_8_SAMPLES ); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_9_SAMPLES ); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_10_SAMPLES ); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_11_SAMPLES ); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_12_SAMPLES ); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_13_SAMPLES ); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_14_SAMPLES ); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_15_SAMPLES ); + m_MultiSampleTypeList.Add( D3DMULTISAMPLE_16_SAMPLES ); +} + + +//-------------------------------------------------------------------------------------- +void CD3D9Enumeration::GetPossibleVertexProcessingList( bool* pbSoftwareVP, bool* pbHardwareVP, bool* pbPureHarewareVP, + bool* pbMixedVP ) +{ + *pbSoftwareVP = m_bSoftwareVP; + *pbHardwareVP = m_bHardwareVP; + *pbPureHarewareVP = m_bPureHarewareVP; + *pbMixedVP = m_bMixedVP; +} + + +//-------------------------------------------------------------------------------------- +void CD3D9Enumeration::SetPossibleVertexProcessingList( bool bSoftwareVP, bool bHardwareVP, bool bPureHarewareVP, + bool bMixedVP ) +{ + m_bSoftwareVP = bSoftwareVP; + m_bHardwareVP = bHardwareVP; + m_bPureHarewareVP = bPureHarewareVP; + m_bMixedVP = bMixedVP; +} + + +//-------------------------------------------------------------------------------------- +CGrowableArray * CD3D9Enumeration::GetPossiblePresentIntervalList() +{ + return &m_PresentIntervalList; +} + + +//-------------------------------------------------------------------------------------- +void CD3D9Enumeration::ResetPossiblePresentIntervalList() +{ + m_PresentIntervalList.RemoveAll(); + m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_IMMEDIATE ); + m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_DEFAULT ); + m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_ONE ); + m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_TWO ); + m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_THREE ); + m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_FOUR ); +} + + +//-------------------------------------------------------------------------------------- +void CD3D9Enumeration::SetResolutionMinMax( UINT nMinWidth, UINT nMinHeight, + UINT nMaxWidth, UINT nMaxHeight ) +{ + m_nMinWidth = nMinWidth; + m_nMinHeight = nMinHeight; + m_nMaxWidth = nMaxWidth; + m_nMaxHeight = nMaxHeight; +} + + +//-------------------------------------------------------------------------------------- +void CD3D9Enumeration::SetRefreshMinMax( UINT nMin, UINT nMax ) +{ + m_nRefreshMin = nMin; + m_nRefreshMax = nMax; +} + + +//-------------------------------------------------------------------------------------- +void CD3D9Enumeration::SetMultisampleQualityMax( UINT nMax ) +{ + if( nMax > 0xFFFF ) + nMax = 0xFFFF; + m_nMultisampleQualityMax = nMax; +} + + + +//-------------------------------------------------------------------------------------- +// Returns a ranking number that describes how closely this device +// combo matches the optimal combo based on the match options and the optimal device settings +//-------------------------------------------------------------------------------------- +float DXUTRankD3D9DeviceCombo( CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo, + DXUTD3D9DeviceSettings* pOptimalDeviceSettings, + D3DDISPLAYMODE* pAdapterDesktopDisplayMode, + int &bestModeIndex, + int &bestMSAAIndex + ) +{ + float fCurRanking = 0.0f; + + // Arbitrary weights. Gives preference to the ordinal, device type, and windowed + const float fAdapterOrdinalWeight = 1000.0f; + const float fDeviceTypeWeight = 100.0f; + const float fWindowWeight = 10.0f; + const float fAdapterFormatWeight = 1.0f; + const float fVertexProcessingWeight = 1.0f; + const float fResolutionWeight = 1.0f; + const float fBackBufferFormatWeight = 1.0f; + const float fMultiSampleWeight = 1.0f; + const float fDepthStencilWeight = 1.0f; + const float fRefreshRateWeight = 1.0f; + const float fPresentIntervalWeight = 1.0f; + + //--------------------- + // Adapter ordinal + //--------------------- + if( pDeviceSettingsCombo->AdapterOrdinal == pOptimalDeviceSettings->AdapterOrdinal ) + fCurRanking += fAdapterOrdinalWeight; + + //--------------------- + // Device type + //--------------------- + if( pDeviceSettingsCombo->DeviceType == pOptimalDeviceSettings->DeviceType ) + fCurRanking += fDeviceTypeWeight; + // Slightly prefer HAL + if( pDeviceSettingsCombo->DeviceType == D3DDEVTYPE_HAL ) + fCurRanking += 0.1f; + + //--------------------- + // Windowed + //--------------------- + if( pDeviceSettingsCombo->Windowed == pOptimalDeviceSettings->pp.Windowed ) + fCurRanking += fWindowWeight; + + //--------------------- + // Adapter format + //--------------------- + if( pDeviceSettingsCombo->AdapterFormat == pOptimalDeviceSettings->AdapterFormat ) + { + fCurRanking += fAdapterFormatWeight; + } + else + { + int nBitDepthDelta = abs( ( long )DXUTGetD3D9ColorChannelBits( pDeviceSettingsCombo->AdapterFormat ) - + ( long )DXUTGetD3D9ColorChannelBits( pOptimalDeviceSettings->AdapterFormat ) ); + float fScale = __max( 0.9f - ( float )nBitDepthDelta * 0.2f, 0.0f ); + fCurRanking += fScale * fAdapterFormatWeight; + } + + if( !pDeviceSettingsCombo->Windowed ) + { + // Slightly prefer when it matches the desktop format or is D3DFMT_X8R8G8B8 + bool bAdapterOptimalMatch; + if( DXUTGetD3D9ColorChannelBits( pAdapterDesktopDisplayMode->Format ) >= 8 ) + bAdapterOptimalMatch = ( pDeviceSettingsCombo->AdapterFormat == pAdapterDesktopDisplayMode->Format ); + else + bAdapterOptimalMatch = ( pDeviceSettingsCombo->AdapterFormat == D3DFMT_X8R8G8B8 ); + + if( bAdapterOptimalMatch ) + fCurRanking += 0.1f; + } + + //--------------------- + // Vertex processing + //--------------------- + if( ( pOptimalDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING ) != 0 || + ( pOptimalDeviceSettings->BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING ) != 0 ) + { + if( ( pDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) != 0 ) + fCurRanking += fVertexProcessingWeight; + } + // Slightly prefer HW T&L + if( ( pDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) != 0 ) + fCurRanking += 0.1f; + + //--------------------- + // Resolution + //--------------------- + bool bResolutionFound = false; + unsigned int best = 0xffffffff; + bestModeIndex=0; + + + + + + for( int idm = 0; idm < pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetSize(); idm++ ) + { + D3DDISPLAYMODE displayMode = pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetAt( idm ); + if( displayMode.Format != pDeviceSettingsCombo->AdapterFormat ) + continue; + if( displayMode.Width == pOptimalDeviceSettings->pp.BackBufferWidth && + displayMode.Height == pOptimalDeviceSettings->pp.BackBufferHeight ) + bResolutionFound = true; + + unsigned int current = + (UINT) abs ((int)displayMode.Width - (int)pOptimalDeviceSettings->pp.BackBufferWidth) + + (UINT) abs ((int)displayMode.Height - (int)pOptimalDeviceSettings->pp.BackBufferHeight ); + if (current < best) { + best = current; + bestModeIndex= idm; + + } + + + } + if( bResolutionFound ) + fCurRanking += fResolutionWeight; + + //--------------------- + // Back buffer format + //--------------------- + if( pDeviceSettingsCombo->BackBufferFormat == pOptimalDeviceSettings->pp.BackBufferFormat ) + { + fCurRanking += fBackBufferFormatWeight; + } + else + { + int nBitDepthDelta = abs( ( long )DXUTGetD3D9ColorChannelBits( pDeviceSettingsCombo->BackBufferFormat ) - + ( long )DXUTGetD3D9ColorChannelBits( pOptimalDeviceSettings->pp.BackBufferFormat ) ); + float fScale = __max( 0.9f - ( float )nBitDepthDelta * 0.2f, 0.0f ); + fCurRanking += fScale * fBackBufferFormatWeight; + } + + // Check if this back buffer format is the same as + // the adapter format since this is preferred. + bool bAdapterMatchesBB = ( pDeviceSettingsCombo->BackBufferFormat == pDeviceSettingsCombo->AdapterFormat ); + if( bAdapterMatchesBB ) + fCurRanking += 0.1f; + + //--------------------- + // Back buffer count + //--------------------- + // No caps for the back buffer count + + //--------------------- + // Multisample + //--------------------- + bool bMultiSampleFound = false; + for( int i = 0; i < pDeviceSettingsCombo->multiSampleTypeList.GetSize(); i++ ) + { + D3DMULTISAMPLE_TYPE msType = pDeviceSettingsCombo->multiSampleTypeList.GetAt( i ); + DWORD msQuality = pDeviceSettingsCombo->multiSampleQualityList.GetAt( i ); + + if( msType == pOptimalDeviceSettings->pp.MultiSampleType && + msQuality > pOptimalDeviceSettings->pp.MultiSampleQuality ) + { + bMultiSampleFound = true; + bestMSAAIndex = i; + break; + } + } + if( bMultiSampleFound ) + fCurRanking += fMultiSampleWeight; + + //--------------------- + // Swap effect + //--------------------- + // No caps for swap effects + + //--------------------- + // Depth stencil + //--------------------- + if( pDeviceSettingsCombo->depthStencilFormatList.Contains( pOptimalDeviceSettings->pp.AutoDepthStencilFormat ) ) + fCurRanking += fDepthStencilWeight; + + //--------------------- + // Present flags + //--------------------- + // No caps for the present flags + + //--------------------- + // Refresh rate + //--------------------- + bool bRefreshFound = false; + for( int idm = 0; idm < pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetSize(); idm++ ) + { + D3DDISPLAYMODE displayMode = pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetAt( idm ); + if( displayMode.Format != pDeviceSettingsCombo->AdapterFormat ) + continue; + if( displayMode.RefreshRate == pOptimalDeviceSettings->pp.FullScreen_RefreshRateInHz ) + bRefreshFound = true; + } + if( bRefreshFound ) + fCurRanking += fRefreshRateWeight; + + //--------------------- + // Present interval + //--------------------- + // If keep present interval then check that the present interval is supported by this combo + if( pDeviceSettingsCombo->presentIntervalList.Contains( pOptimalDeviceSettings->pp.PresentationInterval ) ) + fCurRanking += fPresentIntervalWeight; + + return fCurRanking; +} + diff --git a/Demos/DX11ClothDemo/DXUT/Core/DXUTDevice9.h b/Demos/DX11ClothDemo/DXUT/Core/DXUTDevice9.h new file mode 100644 index 0000000..c5ee6db --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Core/DXUTDevice9.h @@ -0,0 +1,207 @@ +//-------------------------------------------------------------------------------------- +// File: DXUTDevice9.h +// +// Enumerates D3D adapters, devices, modes, etc. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once +#ifndef DXUT_DEVICE9_H +#define DXUT_DEVICE9_H + +//void DXUTApplyDefaultDeviceSettings(DXUTDeviceSettings *modifySettings); + +//-------------------------------------------------------------------------------------- +// Functions to get bit depth from formats +//-------------------------------------------------------------------------------------- +UINT WINAPI DXUTGetD3D9ColorChannelBits( D3DFORMAT fmt ); +UINT WINAPI DXUTGetAlphaChannelBits( D3DFORMAT fmt ); +UINT WINAPI DXUTGetStencilBits( D3DFORMAT fmt ); +UINT WINAPI DXUTGetDepthBits( D3DFORMAT fmt ); +UINT WINAPI DXUTGetDXGIColorChannelBits( DXGI_FORMAT fmt ); + + +//-------------------------------------------------------------------------------------- +// Forward declarations +//-------------------------------------------------------------------------------------- + +class CD3D9EnumAdapterInfo; +class CD3D9EnumDeviceInfo; +struct CD3D9EnumDeviceSettingsCombo; +struct CD3D9EnumDSMSConflict; + + + + + +//-------------------------------------------------------------------------------------- +// Optional memory create/destory functions. If not call, these will be called automatically +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTCreateD3D9Enumeration(); +void WINAPI DXUTDestroyD3D9Enumeration(); + + + +//-------------------------------------------------------------------------------------- +// Enumerates available Direct3D9 adapters, devices, modes, etc. +// Use DXUTGetD3D9Enumeration() to access global instance +//-------------------------------------------------------------------------------------- +class CD3D9Enumeration +{ +public: + // These should be called before Enumerate(). + // + // Use these calls and the IsDeviceAcceptable to control the contents of + // the enumeration object, which affects the device selection and the device settings dialog. + void SetRequirePostPixelShaderBlending( bool bRequire ) { m_bRequirePostPixelShaderBlending = bRequire; } + void SetResolutionMinMax( UINT nMinWidth, UINT nMinHeight, UINT nMaxWidth, UINT nMaxHeight ); + void SetRefreshMinMax( UINT nMin, UINT nMax ); + void SetMultisampleQualityMax( UINT nMax ); + void GetPossibleVertexProcessingList( bool* pbSoftwareVP, bool* pbHardwareVP, bool* pbPureHarewareVP, bool* pbMixedVP ); + void SetPossibleVertexProcessingList( bool bSoftwareVP, bool bHardwareVP, bool bPureHarewareVP, bool bMixedVP ); + CGrowableArray* GetPossibleDepthStencilFormatList(); + CGrowableArray* GetPossibleMultisampleTypeList(); + CGrowableArray* GetPossiblePresentIntervalList(); + void ResetPossibleDepthStencilFormats(); + void ResetPossibleMultisampleTypeList(); + void ResetPossiblePresentIntervalList(); + + // Call Enumerate() to enumerate available D3D adapters, devices, modes, etc. + bool HasEnumerated() { return m_bHasEnumerated; } + HRESULT Enumerate( LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE IsD3D9DeviceAcceptableFunc = NULL, + void* pIsD3D9DeviceAcceptableFuncUserContext = NULL ); + + // These should be called after Enumerate() is called + CGrowableArray* GetAdapterInfoList(); + CD3D9EnumAdapterInfo* GetAdapterInfo( UINT AdapterOrdinal ); + CD3D9EnumDeviceInfo* GetDeviceInfo( UINT AdapterOrdinal, D3DDEVTYPE DeviceType ); + CD3D9EnumDeviceSettingsCombo* GetDeviceSettingsCombo( DXUTD3D9DeviceSettings* pD3D9DeviceSettings ) { return GetDeviceSettingsCombo( pD3D9DeviceSettings->AdapterOrdinal, pD3D9DeviceSettings->DeviceType, pD3D9DeviceSettings->AdapterFormat, pD3D9DeviceSettings->pp.BackBufferFormat, pD3D9DeviceSettings->pp.Windowed ); } + CD3D9EnumDeviceSettingsCombo* GetDeviceSettingsCombo( UINT AdapterOrdinal, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, BOOL Windowed ); + + ~CD3D9Enumeration(); + +private: + friend HRESULT WINAPI DXUTCreateD3D9Enumeration(); + + // Use DXUTGetD3D9Enumeration() to access global instance + CD3D9Enumeration(); + + bool m_bHasEnumerated; + IDirect3D9* m_pD3D; + LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE m_IsD3D9DeviceAcceptableFunc; + void* m_pIsD3D9DeviceAcceptableFuncUserContext; + bool m_bRequirePostPixelShaderBlending; + CGrowableArray m_DepthStencilPossibleList; + CGrowableArray m_MultiSampleTypeList; + CGrowableArray m_PresentIntervalList; + + bool m_bSoftwareVP; + bool m_bHardwareVP; + bool m_bPureHarewareVP; + bool m_bMixedVP; + + UINT m_nMinWidth; + UINT m_nMaxWidth; + UINT m_nMinHeight; + UINT m_nMaxHeight; + UINT m_nRefreshMin; + UINT m_nRefreshMax; + UINT m_nMultisampleQualityMax; + + // Array of CD3D9EnumAdapterInfo* with unique AdapterOrdinals + CGrowableArray m_AdapterInfoList; + + HRESULT EnumerateDevices( CD3D9EnumAdapterInfo* pAdapterInfo, CGrowableArray* pAdapterFormatList ); + HRESULT EnumerateDeviceCombos( CD3D9EnumAdapterInfo* pAdapterInfo, CD3D9EnumDeviceInfo* pDeviceInfo, CGrowableArray* pAdapterFormatList ); + void BuildDepthStencilFormatList( CD3D9EnumDeviceSettingsCombo* pDeviceCombo ); + void BuildMultiSampleTypeList( CD3D9EnumDeviceSettingsCombo* pDeviceCombo ); + void BuildDSMSConflictList( CD3D9EnumDeviceSettingsCombo* pDeviceCombo ); + void BuildPresentIntervalList( CD3D9EnumDeviceInfo* pDeviceInfo, CD3D9EnumDeviceSettingsCombo* pDeviceCombo ); + void ClearAdapterInfoList(); +}; + +CD3D9Enumeration* WINAPI DXUTGetD3D9Enumeration( bool bForceEnumerate = false ); + + +//-------------------------------------------------------------------------------------- +// A class describing an adapter which contains a unique adapter ordinal +// that is installed on the system +//-------------------------------------------------------------------------------------- +class CD3D9EnumAdapterInfo +{ +public: + ~CD3D9EnumAdapterInfo(); + + UINT AdapterOrdinal; + D3DADAPTER_IDENTIFIER9 AdapterIdentifier; + WCHAR szUniqueDescription[256]; + + CGrowableArray displayModeList; // Array of supported D3DDISPLAYMODEs + CGrowableArray deviceInfoList; // Array of CD3D9EnumDeviceInfo* with unique supported DeviceTypes +}; + + +//-------------------------------------------------------------------------------------- +// A class describing a Direct3D device that contains a +// unique supported device type +//-------------------------------------------------------------------------------------- +class CD3D9EnumDeviceInfo +{ +public: + ~CD3D9EnumDeviceInfo(); + + UINT AdapterOrdinal; + D3DDEVTYPE DeviceType; + D3DCAPS9 Caps; + + // List of CD3D9EnumDeviceSettingsCombo* with a unique set + // of AdapterFormat, BackBufferFormat, and Windowed + CGrowableArray deviceSettingsComboList; +}; + + +//-------------------------------------------------------------------------------------- +// A struct describing device settings that contains a unique combination of +// adapter format, back buffer format, and windowed that is compatible with a +// particular Direct3D device and the app. +//-------------------------------------------------------------------------------------- +struct CD3D9EnumDeviceSettingsCombo +{ + UINT AdapterOrdinal; + D3DDEVTYPE DeviceType; + D3DFORMAT AdapterFormat; + D3DFORMAT BackBufferFormat; + BOOL Windowed; + + CGrowableArray depthStencilFormatList; // List of D3DFORMATs + CGrowableArray multiSampleTypeList; // List of D3DMULTISAMPLE_TYPEs + CGrowableArray multiSampleQualityList; // List of number of quality levels for each multisample type + CGrowableArray presentIntervalList; // List of D3DPRESENT flags + CGrowableArray DSMSConflictList; // List of CD3D9EnumDSMSConflict + + CD3D9EnumAdapterInfo* pAdapterInfo; + CD3D9EnumDeviceInfo* pDeviceInfo; +}; + + +//-------------------------------------------------------------------------------------- +// A depth/stencil buffer format that is incompatible with a +// multisample type. +//-------------------------------------------------------------------------------------- +struct CD3D9EnumDSMSConflict +{ + D3DFORMAT DSFormat; + D3DMULTISAMPLE_TYPE MSType; +}; + + + +float DXUTRankD3D9DeviceCombo( CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo, + DXUTD3D9DeviceSettings* pOptimalDeviceSettings, + D3DDISPLAYMODE* pAdapterDesktopDisplayMode, + int &bestModeIndex, + int &bestMSAAIndex + ); + + +#endif diff --git a/Demos/DX11ClothDemo/DXUT/Core/DXUTmisc.cpp b/Demos/DX11ClothDemo/DXUT/Core/DXUTmisc.cpp new file mode 100644 index 0000000..f60c5f4 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Core/DXUTmisc.cpp @@ -0,0 +1,1785 @@ +//-------------------------------------------------------------------------------------- +// File: DXUTMisc.cpp +// +// Shortcut macros and functions for using DX objects +// +// Copyright (c) Microsoft Corporation. All rights reserved +//-------------------------------------------------------------------------------------- +#include "dxut.h" +#include +#define DXUT_GAMEPAD_TRIGGER_THRESHOLD 30 +#undef min // use __min instead +#undef max // use __max instead + +CDXUTTimer* WINAPI DXUTGetGlobalTimer() +{ + // Using an accessor function gives control of the construction order + static CDXUTTimer timer; + return &timer; +} + + +//-------------------------------------------------------------------------------------- +CDXUTTimer::CDXUTTimer() +{ + m_bTimerStopped = true; + m_llQPFTicksPerSec = 0; + + m_llStopTime = 0; + m_llLastElapsedTime = 0; + m_llBaseTime = 0; + + // Use QueryPerformanceFrequency to get the frequency of the counter + LARGE_INTEGER qwTicksPerSec = { 0 }; + QueryPerformanceFrequency( &qwTicksPerSec ); + m_llQPFTicksPerSec = qwTicksPerSec.QuadPart; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTTimer::Reset() +{ + LARGE_INTEGER qwTime = GetAdjustedCurrentTime(); + + m_llBaseTime = qwTime.QuadPart; + m_llLastElapsedTime = qwTime.QuadPart; + m_llStopTime = 0; + m_bTimerStopped = FALSE; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTTimer::Start() +{ + // Get the current time + LARGE_INTEGER qwTime = { 0 }; + QueryPerformanceCounter( &qwTime ); + + if( m_bTimerStopped ) + m_llBaseTime += qwTime.QuadPart - m_llStopTime; + m_llStopTime = 0; + m_llLastElapsedTime = qwTime.QuadPart; + m_bTimerStopped = FALSE; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTTimer::Stop() +{ + if( !m_bTimerStopped ) + { + LARGE_INTEGER qwTime = { 0 }; + QueryPerformanceCounter( &qwTime ); + m_llStopTime = qwTime.QuadPart; + m_llLastElapsedTime = qwTime.QuadPart; + m_bTimerStopped = TRUE; + } +} + + +//-------------------------------------------------------------------------------------- +void CDXUTTimer::Advance() +{ + m_llStopTime += m_llQPFTicksPerSec / 10; +} + + +//-------------------------------------------------------------------------------------- +double CDXUTTimer::GetAbsoluteTime() +{ + LARGE_INTEGER qwTime = { 0 }; + QueryPerformanceCounter( &qwTime ); + + double fTime = qwTime.QuadPart / ( double )m_llQPFTicksPerSec; + + return fTime; +} + + +//-------------------------------------------------------------------------------------- +double CDXUTTimer::GetTime() +{ + LARGE_INTEGER qwTime = GetAdjustedCurrentTime(); + + double fAppTime = ( double )( qwTime.QuadPart - m_llBaseTime ) / ( double )m_llQPFTicksPerSec; + + return fAppTime; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTTimer::GetTimeValues( double* pfTime, double* pfAbsoluteTime, float* pfElapsedTime ) +{ + assert( pfTime && pfAbsoluteTime && pfElapsedTime ); + + LARGE_INTEGER qwTime = GetAdjustedCurrentTime(); + + float fElapsedTime = (float) ((double) ( qwTime.QuadPart - m_llLastElapsedTime ) / (double) m_llQPFTicksPerSec); + m_llLastElapsedTime = qwTime.QuadPart; + + // Clamp the timer to non-negative values to ensure the timer is accurate. + // fElapsedTime can be outside this range if processor goes into a + // power save mode or we somehow get shuffled to another processor. + // However, the main thread should call SetThreadAffinityMask to ensure that + // we don't get shuffled to another processor. Other worker threads should NOT call + // SetThreadAffinityMask, but use a shared copy of the timer data gathered from + // the main thread. + if( fElapsedTime < 0.0f ) + fElapsedTime = 0.0f; + + *pfAbsoluteTime = qwTime.QuadPart / ( double )m_llQPFTicksPerSec; + *pfTime = ( qwTime.QuadPart - m_llBaseTime ) / ( double )m_llQPFTicksPerSec; + *pfElapsedTime = fElapsedTime; +} + + +//-------------------------------------------------------------------------------------- +float CDXUTTimer::GetElapsedTime() +{ + LARGE_INTEGER qwTime = GetAdjustedCurrentTime(); + + double fElapsedTime = (float) ((double) ( qwTime.QuadPart - m_llLastElapsedTime ) / (double) m_llQPFTicksPerSec); + m_llLastElapsedTime = qwTime.QuadPart; + + // See the explanation about clamping in CDXUTTimer::GetTimeValues() + if( fElapsedTime < 0.0f ) + fElapsedTime = 0.0f; + + return ( float )fElapsedTime; +} + + +//-------------------------------------------------------------------------------------- +// If stopped, returns time when stopped otherwise returns current time +//-------------------------------------------------------------------------------------- +LARGE_INTEGER CDXUTTimer::GetAdjustedCurrentTime() +{ + LARGE_INTEGER qwTime; + if( m_llStopTime != 0 ) + qwTime.QuadPart = m_llStopTime; + else + QueryPerformanceCounter( &qwTime ); + return qwTime; +} + +//-------------------------------------------------------------------------------------- +bool CDXUTTimer::IsStopped() +{ + return m_bTimerStopped; +} + +//-------------------------------------------------------------------------------------- +// Limit the current thread to one processor (the current one). This ensures that timing code +// runs on only one processor, and will not suffer any ill effects from power management. +// See "Game Timing and Multicore Processors" for more details +//-------------------------------------------------------------------------------------- +void CDXUTTimer::LimitThreadAffinityToCurrentProc() +{ + HANDLE hCurrentProcess = GetCurrentProcess(); + + // Get the processor affinity mask for this process + DWORD_PTR dwProcessAffinityMask = 0; + DWORD_PTR dwSystemAffinityMask = 0; + + if( GetProcessAffinityMask( hCurrentProcess, &dwProcessAffinityMask, &dwSystemAffinityMask ) != 0 && + dwProcessAffinityMask ) + { + // Find the lowest processor that our process is allows to run against + DWORD_PTR dwAffinityMask = ( dwProcessAffinityMask & ( ( ~dwProcessAffinityMask ) + 1 ) ); + + // Set this as the processor that our thread must always run against + // This must be a subset of the process affinity mask + HANDLE hCurrentThread = GetCurrentThread(); + if( INVALID_HANDLE_VALUE != hCurrentThread ) + { + SetThreadAffinityMask( hCurrentThread, dwAffinityMask ); + CloseHandle( hCurrentThread ); + } + } + + CloseHandle( hCurrentProcess ); +} + + +//-------------------------------------------------------------------------------------- +// Returns the string for the given D3DFORMAT. +//-------------------------------------------------------------------------------------- +LPCWSTR WINAPI DXUTD3DFormatToString( D3DFORMAT format, bool bWithPrefix ) +{ + WCHAR* pstr = NULL; + switch( format ) + { + case D3DFMT_UNKNOWN: + pstr = L"D3DFMT_UNKNOWN"; break; + case D3DFMT_R8G8B8: + pstr = L"D3DFMT_R8G8B8"; break; + case D3DFMT_A8R8G8B8: + pstr = L"D3DFMT_A8R8G8B8"; break; + case D3DFMT_X8R8G8B8: + pstr = L"D3DFMT_X8R8G8B8"; break; + case D3DFMT_R5G6B5: + pstr = L"D3DFMT_R5G6B5"; break; + case D3DFMT_X1R5G5B5: + pstr = L"D3DFMT_X1R5G5B5"; break; + case D3DFMT_A1R5G5B5: + pstr = L"D3DFMT_A1R5G5B5"; break; + case D3DFMT_A4R4G4B4: + pstr = L"D3DFMT_A4R4G4B4"; break; + case D3DFMT_R3G3B2: + pstr = L"D3DFMT_R3G3B2"; break; + case D3DFMT_A8: + pstr = L"D3DFMT_A8"; break; + case D3DFMT_A8R3G3B2: + pstr = L"D3DFMT_A8R3G3B2"; break; + case D3DFMT_X4R4G4B4: + pstr = L"D3DFMT_X4R4G4B4"; break; + case D3DFMT_A2B10G10R10: + pstr = L"D3DFMT_A2B10G10R10"; break; + case D3DFMT_A8B8G8R8: + pstr = L"D3DFMT_A8B8G8R8"; break; + case D3DFMT_X8B8G8R8: + pstr = L"D3DFMT_X8B8G8R8"; break; + case D3DFMT_G16R16: + pstr = L"D3DFMT_G16R16"; break; + case D3DFMT_A2R10G10B10: + pstr = L"D3DFMT_A2R10G10B10"; break; + case D3DFMT_A16B16G16R16: + pstr = L"D3DFMT_A16B16G16R16"; break; + case D3DFMT_A8P8: + pstr = L"D3DFMT_A8P8"; break; + case D3DFMT_P8: + pstr = L"D3DFMT_P8"; break; + case D3DFMT_L8: + pstr = L"D3DFMT_L8"; break; + case D3DFMT_A8L8: + pstr = L"D3DFMT_A8L8"; break; + case D3DFMT_A4L4: + pstr = L"D3DFMT_A4L4"; break; + case D3DFMT_V8U8: + pstr = L"D3DFMT_V8U8"; break; + case D3DFMT_L6V5U5: + pstr = L"D3DFMT_L6V5U5"; break; + case D3DFMT_X8L8V8U8: + pstr = L"D3DFMT_X8L8V8U8"; break; + case D3DFMT_Q8W8V8U8: + pstr = L"D3DFMT_Q8W8V8U8"; break; + case D3DFMT_V16U16: + pstr = L"D3DFMT_V16U16"; break; + case D3DFMT_A2W10V10U10: + pstr = L"D3DFMT_A2W10V10U10"; break; + case D3DFMT_UYVY: + pstr = L"D3DFMT_UYVY"; break; + case D3DFMT_YUY2: + pstr = L"D3DFMT_YUY2"; break; + case D3DFMT_DXT1: + pstr = L"D3DFMT_DXT1"; break; + case D3DFMT_DXT2: + pstr = L"D3DFMT_DXT2"; break; + case D3DFMT_DXT3: + pstr = L"D3DFMT_DXT3"; break; + case D3DFMT_DXT4: + pstr = L"D3DFMT_DXT4"; break; + case D3DFMT_DXT5: + pstr = L"D3DFMT_DXT5"; break; + case D3DFMT_D16_LOCKABLE: + pstr = L"D3DFMT_D16_LOCKABLE"; break; + case D3DFMT_D32: + pstr = L"D3DFMT_D32"; break; + case D3DFMT_D15S1: + pstr = L"D3DFMT_D15S1"; break; + case D3DFMT_D24S8: + pstr = L"D3DFMT_D24S8"; break; + case D3DFMT_D24X8: + pstr = L"D3DFMT_D24X8"; break; + case D3DFMT_D24X4S4: + pstr = L"D3DFMT_D24X4S4"; break; + case D3DFMT_D16: + pstr = L"D3DFMT_D16"; break; + case D3DFMT_L16: + pstr = L"D3DFMT_L16"; break; + case D3DFMT_VERTEXDATA: + pstr = L"D3DFMT_VERTEXDATA"; break; + case D3DFMT_INDEX16: + pstr = L"D3DFMT_INDEX16"; break; + case D3DFMT_INDEX32: + pstr = L"D3DFMT_INDEX32"; break; + case D3DFMT_Q16W16V16U16: + pstr = L"D3DFMT_Q16W16V16U16"; break; + case D3DFMT_MULTI2_ARGB8: + pstr = L"D3DFMT_MULTI2_ARGB8"; break; + case D3DFMT_R16F: + pstr = L"D3DFMT_R16F"; break; + case D3DFMT_G16R16F: + pstr = L"D3DFMT_G16R16F"; break; + case D3DFMT_A16B16G16R16F: + pstr = L"D3DFMT_A16B16G16R16F"; break; + case D3DFMT_R32F: + pstr = L"D3DFMT_R32F"; break; + case D3DFMT_G32R32F: + pstr = L"D3DFMT_G32R32F"; break; + case D3DFMT_A32B32G32R32F: + pstr = L"D3DFMT_A32B32G32R32F"; break; + case D3DFMT_CxV8U8: + pstr = L"D3DFMT_CxV8U8"; break; + default: + pstr = L"Unknown format"; break; + } + if( bWithPrefix || wcsstr( pstr, L"D3DFMT_" ) == NULL ) + return pstr; + else + return pstr + lstrlen( L"D3DFMT_" ); +} + + +//-------------------------------------------------------------------------------------- +// Returns the string for the given DXGI_FORMAT. +//-------------------------------------------------------------------------------------- +LPCWSTR WINAPI DXUTDXGIFormatToString( DXGI_FORMAT format, bool bWithPrefix ) +{ + WCHAR* pstr = NULL; + switch( format ) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + pstr = L"DXGI_FORMAT_R32G32B32A32_TYPELESS"; break; + case DXGI_FORMAT_R32G32B32A32_FLOAT: + pstr = L"DXGI_FORMAT_R32G32B32A32_FLOAT"; break; + case DXGI_FORMAT_R32G32B32A32_UINT: + pstr = L"DXGI_FORMAT_R32G32B32A32_UINT"; break; + case DXGI_FORMAT_R32G32B32A32_SINT: + pstr = L"DXGI_FORMAT_R32G32B32A32_SINT"; break; + case DXGI_FORMAT_R32G32B32_TYPELESS: + pstr = L"DXGI_FORMAT_R32G32B32_TYPELESS"; break; + case DXGI_FORMAT_R32G32B32_FLOAT: + pstr = L"DXGI_FORMAT_R32G32B32_FLOAT"; break; + case DXGI_FORMAT_R32G32B32_UINT: + pstr = L"DXGI_FORMAT_R32G32B32_UINT"; break; + case DXGI_FORMAT_R32G32B32_SINT: + pstr = L"DXGI_FORMAT_R32G32B32_SINT"; break; + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + pstr = L"DXGI_FORMAT_R16G16B16A16_TYPELESS"; break; + case DXGI_FORMAT_R16G16B16A16_FLOAT: + pstr = L"DXGI_FORMAT_R16G16B16A16_FLOAT"; break; + case DXGI_FORMAT_R16G16B16A16_UNORM: + pstr = L"DXGI_FORMAT_R16G16B16A16_UNORM"; break; + case DXGI_FORMAT_R16G16B16A16_UINT: + pstr = L"DXGI_FORMAT_R16G16B16A16_UINT"; break; + case DXGI_FORMAT_R16G16B16A16_SNORM: + pstr = L"DXGI_FORMAT_R16G16B16A16_SNORM"; break; + case DXGI_FORMAT_R16G16B16A16_SINT: + pstr = L"DXGI_FORMAT_R16G16B16A16_SINT"; break; + case DXGI_FORMAT_R32G32_TYPELESS: + pstr = L"DXGI_FORMAT_R32G32_TYPELESS"; break; + case DXGI_FORMAT_R32G32_FLOAT: + pstr = L"DXGI_FORMAT_R32G32_FLOAT"; break; + case DXGI_FORMAT_R32G32_UINT: + pstr = L"DXGI_FORMAT_R32G32_UINT"; break; + case DXGI_FORMAT_R32G32_SINT: + pstr = L"DXGI_FORMAT_R32G32_SINT"; break; + case DXGI_FORMAT_R32G8X24_TYPELESS: + pstr = L"DXGI_FORMAT_R32G8X24_TYPELESS"; break; + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + pstr = L"DXGI_FORMAT_D32_FLOAT_S8X24_UINT"; break; + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + pstr = L"DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS"; break; + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + pstr = L"DXGI_FORMAT_X32_TYPELESS_G8X24_UINT"; break; + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + pstr = L"DXGI_FORMAT_R10G10B10A2_TYPELESS"; break; + case DXGI_FORMAT_R10G10B10A2_UNORM: + pstr = L"DXGI_FORMAT_R10G10B10A2_UNORM"; break; + case DXGI_FORMAT_R10G10B10A2_UINT: + pstr = L"DXGI_FORMAT_R10G10B10A2_UINT"; break; + case DXGI_FORMAT_R11G11B10_FLOAT: + pstr = L"DXGI_FORMAT_R11G11B10_FLOAT"; break; + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + pstr = L"DXGI_FORMAT_R8G8B8A8_TYPELESS"; break; + case DXGI_FORMAT_R8G8B8A8_UNORM: + pstr = L"DXGI_FORMAT_R8G8B8A8_UNORM"; break; + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + pstr = L"DXGI_FORMAT_R8G8B8A8_UNORM_SRGB"; break; + case DXGI_FORMAT_R8G8B8A8_UINT: + pstr = L"DXGI_FORMAT_R8G8B8A8_UINT"; break; + case DXGI_FORMAT_R8G8B8A8_SNORM: + pstr = L"DXGI_FORMAT_R8G8B8A8_SNORM"; break; + case DXGI_FORMAT_R8G8B8A8_SINT: + pstr = L"DXGI_FORMAT_R8G8B8A8_SINT"; break; + case DXGI_FORMAT_R16G16_TYPELESS: + pstr = L"DXGI_FORMAT_R16G16_TYPELESS"; break; + case DXGI_FORMAT_R16G16_FLOAT: + pstr = L"DXGI_FORMAT_R16G16_FLOAT"; break; + case DXGI_FORMAT_R16G16_UNORM: + pstr = L"DXGI_FORMAT_R16G16_UNORM"; break; + case DXGI_FORMAT_R16G16_UINT: + pstr = L"DXGI_FORMAT_R16G16_UINT"; break; + case DXGI_FORMAT_R16G16_SNORM: + pstr = L"DXGI_FORMAT_R16G16_SNORM"; break; + case DXGI_FORMAT_R16G16_SINT: + pstr = L"DXGI_FORMAT_R16G16_SINT"; break; + case DXGI_FORMAT_R32_TYPELESS: + pstr = L"DXGI_FORMAT_R32_TYPELESS"; break; + case DXGI_FORMAT_D32_FLOAT: + pstr = L"DXGI_FORMAT_D32_FLOAT"; break; + case DXGI_FORMAT_R32_FLOAT: + pstr = L"DXGI_FORMAT_R32_FLOAT"; break; + case DXGI_FORMAT_R32_UINT: + pstr = L"DXGI_FORMAT_R32_UINT"; break; + case DXGI_FORMAT_R32_SINT: + pstr = L"DXGI_FORMAT_R32_SINT"; break; + case DXGI_FORMAT_R24G8_TYPELESS: + pstr = L"DXGI_FORMAT_R24G8_TYPELESS"; break; + case DXGI_FORMAT_D24_UNORM_S8_UINT: + pstr = L"DXGI_FORMAT_D24_UNORM_S8_UINT"; break; + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + pstr = L"DXGI_FORMAT_R24_UNORM_X8_TYPELESS"; break; + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + pstr = L"DXGI_FORMAT_X24_TYPELESS_G8_UINT"; break; + case DXGI_FORMAT_R8G8_TYPELESS: + pstr = L"DXGI_FORMAT_R8G8_TYPELESS"; break; + case DXGI_FORMAT_R8G8_UNORM: + pstr = L"DXGI_FORMAT_R8G8_UNORM"; break; + case DXGI_FORMAT_R8G8_UINT: + pstr = L"DXGI_FORMAT_R8G8_UINT"; break; + case DXGI_FORMAT_R8G8_SNORM: + pstr = L"DXGI_FORMAT_R8G8_SNORM"; break; + case DXGI_FORMAT_R8G8_SINT: + pstr = L"DXGI_FORMAT_R8G8_SINT"; break; + case DXGI_FORMAT_R16_TYPELESS: + pstr = L"DXGI_FORMAT_R16_TYPELESS"; break; + case DXGI_FORMAT_R16_FLOAT: + pstr = L"DXGI_FORMAT_R16_FLOAT"; break; + case DXGI_FORMAT_D16_UNORM: + pstr = L"DXGI_FORMAT_D16_UNORM"; break; + case DXGI_FORMAT_R16_UNORM: + pstr = L"DXGI_FORMAT_R16_UNORM"; break; + case DXGI_FORMAT_R16_UINT: + pstr = L"DXGI_FORMAT_R16_UINT"; break; + case DXGI_FORMAT_R16_SNORM: + pstr = L"DXGI_FORMAT_R16_SNORM"; break; + case DXGI_FORMAT_R16_SINT: + pstr = L"DXGI_FORMAT_R16_SINT"; break; + case DXGI_FORMAT_R8_TYPELESS: + pstr = L"DXGI_FORMAT_R8_TYPELESS"; break; + case DXGI_FORMAT_R8_UNORM: + pstr = L"DXGI_FORMAT_R8_UNORM"; break; + case DXGI_FORMAT_R8_UINT: + pstr = L"DXGI_FORMAT_R8_UINT"; break; + case DXGI_FORMAT_R8_SNORM: + pstr = L"DXGI_FORMAT_R8_SNORM"; break; + case DXGI_FORMAT_R8_SINT: + pstr = L"DXGI_FORMAT_R8_SINT"; break; + case DXGI_FORMAT_A8_UNORM: + pstr = L"DXGI_FORMAT_A8_UNORM"; break; + case DXGI_FORMAT_R1_UNORM: + pstr = L"DXGI_FORMAT_R1_UNORM"; break; + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + pstr = L"DXGI_FORMAT_R9G9B9E5_SHAREDEXP"; break; + case DXGI_FORMAT_R8G8_B8G8_UNORM: + pstr = L"DXGI_FORMAT_R8G8_B8G8_UNORM"; break; + case DXGI_FORMAT_G8R8_G8B8_UNORM: + pstr = L"DXGI_FORMAT_G8R8_G8B8_UNORM"; break; + case DXGI_FORMAT_BC1_TYPELESS: + pstr = L"DXGI_FORMAT_BC1_TYPELESS"; break; + case DXGI_FORMAT_BC1_UNORM: + pstr = L"DXGI_FORMAT_BC1_UNORM"; break; + case DXGI_FORMAT_BC1_UNORM_SRGB: + pstr = L"DXGI_FORMAT_BC1_UNORM_SRGB"; break; + case DXGI_FORMAT_BC2_TYPELESS: + pstr = L"DXGI_FORMAT_BC2_TYPELESS"; break; + case DXGI_FORMAT_BC2_UNORM: + pstr = L"DXGI_FORMAT_BC2_UNORM"; break; + case DXGI_FORMAT_BC2_UNORM_SRGB: + pstr = L"DXGI_FORMAT_BC2_UNORM_SRGB"; break; + case DXGI_FORMAT_BC3_TYPELESS: + pstr = L"DXGI_FORMAT_BC3_TYPELESS"; break; + case DXGI_FORMAT_BC3_UNORM: + pstr = L"DXGI_FORMAT_BC3_UNORM"; break; + case DXGI_FORMAT_BC3_UNORM_SRGB: + pstr = L"DXGI_FORMAT_BC3_UNORM_SRGB"; break; + case DXGI_FORMAT_BC4_TYPELESS: + pstr = L"DXGI_FORMAT_BC4_TYPELESS"; break; + case DXGI_FORMAT_BC4_UNORM: + pstr = L"DXGI_FORMAT_BC4_UNORM"; break; + case DXGI_FORMAT_BC4_SNORM: + pstr = L"DXGI_FORMAT_BC4_SNORM"; break; + case DXGI_FORMAT_BC5_TYPELESS: + pstr = L"DXGI_FORMAT_BC5_TYPELESS"; break; + case DXGI_FORMAT_BC5_UNORM: + pstr = L"DXGI_FORMAT_BC5_UNORM"; break; + case DXGI_FORMAT_BC5_SNORM: + pstr = L"DXGI_FORMAT_BC5_SNORM"; break; + case DXGI_FORMAT_B5G6R5_UNORM: + pstr = L"DXGI_FORMAT_B5G6R5_UNORM"; break; + case DXGI_FORMAT_B5G5R5A1_UNORM: + pstr = L"DXGI_FORMAT_B5G5R5A1_UNORM"; break; + case DXGI_FORMAT_B8G8R8A8_UNORM: + pstr = L"DXGI_FORMAT_B8G8R8A8_UNORM"; break; + default: + pstr = L"Unknown format"; break; + } + if( bWithPrefix || wcsstr( pstr, L"DXGI_FORMAT_" ) == NULL ) + return pstr; + else + return pstr + lstrlen( L"DXGI_FORMAT_" ); +} + + +//-------------------------------------------------------------------------------------- +// Outputs to the debug stream a formatted Unicode string with a variable-argument list. +//-------------------------------------------------------------------------------------- +VOID WINAPI DXUTOutputDebugStringW( LPCWSTR strMsg, ... ) +{ +#if defined(DEBUG) || defined(_DEBUG) + WCHAR strBuffer[512]; + + va_list args; + va_start(args, strMsg); + vswprintf_s( strBuffer, 512, strMsg, args ); + strBuffer[511] = L'\0'; + va_end(args); + + OutputDebugString( strBuffer ); +#else + UNREFERENCED_PARAMETER( strMsg ); +#endif +} + + +//-------------------------------------------------------------------------------------- +// Outputs to the debug stream a formatted MBCS string with a variable-argument list. +//-------------------------------------------------------------------------------------- +VOID WINAPI DXUTOutputDebugStringA( LPCSTR strMsg, ... ) +{ +#if defined(DEBUG) || defined(_DEBUG) + CHAR strBuffer[512]; + + va_list args; + va_start(args, strMsg); + sprintf_s( strBuffer, 512, strMsg, args ); + strBuffer[511] = '\0'; + va_end(args); + + OutputDebugStringA( strBuffer ); +#else + UNREFERENCED_PARAMETER( strMsg ); +#endif +} + + +//-------------------------------------------------------------------------------------- +// Direct3D9 dynamic linking support -- calls top-level D3D9 APIs with graceful +// failure if APIs are not present. +//-------------------------------------------------------------------------------------- + +// Function prototypes +typedef IDirect3D9* (WINAPI * LPDIRECT3DCREATE9) (UINT); +typedef INT (WINAPI * LPD3DPERF_BEGINEVENT)(D3DCOLOR, LPCWSTR); +typedef INT (WINAPI * LPD3DPERF_ENDEVENT)(void); +typedef VOID (WINAPI * LPD3DPERF_SETMARKER)(D3DCOLOR, LPCWSTR); +typedef VOID (WINAPI * LPD3DPERF_SETREGION)(D3DCOLOR, LPCWSTR); +typedef BOOL (WINAPI * LPD3DPERF_QUERYREPEATFRAME)(void); +typedef VOID (WINAPI * LPD3DPERF_SETOPTIONS)( DWORD dwOptions ); +typedef DWORD (WINAPI * LPD3DPERF_GETSTATUS)( void ); +typedef HRESULT (WINAPI * LPCREATEDXGIFACTORY)(REFIID, void ** ); +typedef HRESULT (WINAPI * LPD3D11CREATEDEVICE)( IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT32, D3D_FEATURE_LEVEL*, UINT, UINT32, ID3D11Device**, D3D_FEATURE_LEVEL*, ID3D11DeviceContext** ); + +// Module and function pointers +static HMODULE s_hModD3D9 = NULL; +static LPDIRECT3DCREATE9 s_DynamicDirect3DCreate9 = NULL; +static LPD3DPERF_BEGINEVENT s_DynamicD3DPERF_BeginEvent = NULL; +static LPD3DPERF_ENDEVENT s_DynamicD3DPERF_EndEvent = NULL; +static LPD3DPERF_SETMARKER s_DynamicD3DPERF_SetMarker = NULL; +static LPD3DPERF_SETREGION s_DynamicD3DPERF_SetRegion = NULL; +static LPD3DPERF_QUERYREPEATFRAME s_DynamicD3DPERF_QueryRepeatFrame = NULL; +static LPD3DPERF_SETOPTIONS s_DynamicD3DPERF_SetOptions = NULL; +static LPD3DPERF_GETSTATUS s_DynamicD3DPERF_GetStatus = NULL; +static HMODULE s_hModDXGI = NULL; +static LPCREATEDXGIFACTORY s_DynamicCreateDXGIFactory = NULL; +static HMODULE s_hModD3D11 = NULL; +static LPD3D11CREATEDEVICE s_DynamicD3D11CreateDevice = NULL; + +// Ensure function pointers are initialized +static bool DXUT_EnsureD3D9APIs( void ) +{ + // If the module is non-NULL, this function has already been called. Note + // that this doesn't guarantee that all ProcAddresses were found. + if( s_hModD3D9 != NULL ) + return true; + + // This may fail if Direct3D 9 isn't installed + s_hModD3D9 = LoadLibrary( L"d3d9.dll" ); + if( s_hModD3D9 != NULL ) + { + s_DynamicDirect3DCreate9 = (LPDIRECT3DCREATE9)GetProcAddress( s_hModD3D9, "Direct3DCreate9" ); + s_DynamicD3DPERF_BeginEvent = (LPD3DPERF_BEGINEVENT)GetProcAddress( s_hModD3D9, "D3DPERF_BeginEvent" ); + s_DynamicD3DPERF_EndEvent = (LPD3DPERF_ENDEVENT)GetProcAddress( s_hModD3D9, "D3DPERF_EndEvent" ); + s_DynamicD3DPERF_SetMarker = (LPD3DPERF_SETMARKER)GetProcAddress( s_hModD3D9, "D3DPERF_SetMarker" ); + s_DynamicD3DPERF_SetRegion = (LPD3DPERF_SETREGION)GetProcAddress( s_hModD3D9, "D3DPERF_SetRegion" ); + s_DynamicD3DPERF_QueryRepeatFrame = (LPD3DPERF_QUERYREPEATFRAME)GetProcAddress( s_hModD3D9, "D3DPERF_QueryRepeatFrame" ); + s_DynamicD3DPERF_SetOptions = (LPD3DPERF_SETOPTIONS)GetProcAddress( s_hModD3D9, "D3DPERF_SetOptions" ); + s_DynamicD3DPERF_GetStatus = (LPD3DPERF_GETSTATUS)GetProcAddress( s_hModD3D9, "D3DPERF_GetStatus" ); + } + + return s_hModD3D9 != NULL; +} + +bool DXUT_EnsureD3D11APIs( void ) +{ + // If both modules are non-NULL, this function has already been called. Note + // that this doesn't guarantee that all ProcAddresses were found. + if( s_hModD3D11 != NULL && s_hModDXGI != NULL ) + return true; + + // This may fail if Direct3D 11 isn't installed + s_hModD3D11 = LoadLibrary( L"d3d11.dll" ); + if( s_hModD3D11 != NULL ) + { + s_DynamicD3D11CreateDevice = ( LPD3D11CREATEDEVICE )GetProcAddress( s_hModD3D11, "D3D11CreateDevice" ); + } + + if( !s_DynamicCreateDXGIFactory ) + { + s_hModDXGI = LoadLibrary( L"dxgi.dll" ); + if( s_hModDXGI ) + { + s_DynamicCreateDXGIFactory = ( LPCREATEDXGIFACTORY )GetProcAddress( s_hModDXGI, "CreateDXGIFactory1" ); + } + + return ( s_hModDXGI != NULL ) && ( s_hModD3D11 != NULL ); + } + + return ( s_hModD3D11 != NULL ); +} + +IDirect3D9* WINAPI DXUT_Dynamic_Direct3DCreate9( UINT SDKVersion ) +{ + if( DXUT_EnsureD3D9APIs() && s_DynamicDirect3DCreate9 != NULL ) + return s_DynamicDirect3DCreate9( SDKVersion ); + else + return NULL; +} + +int WINAPI DXUT_Dynamic_D3DPERF_BeginEvent( D3DCOLOR col, LPCWSTR wszName ) +{ + if( DXUT_EnsureD3D9APIs() && s_DynamicD3DPERF_BeginEvent != NULL ) + return s_DynamicD3DPERF_BeginEvent( col, wszName ); + else + return -1; +} + +int WINAPI DXUT_Dynamic_D3DPERF_EndEvent( void ) +{ + if( DXUT_EnsureD3D9APIs() && s_DynamicD3DPERF_EndEvent != NULL ) + return s_DynamicD3DPERF_EndEvent(); + else + return -1; +} + +void WINAPI DXUT_Dynamic_D3DPERF_SetMarker( D3DCOLOR col, LPCWSTR wszName ) +{ + if( DXUT_EnsureD3D9APIs() && s_DynamicD3DPERF_SetMarker != NULL ) + s_DynamicD3DPERF_SetMarker( col, wszName ); +} + +void WINAPI DXUT_Dynamic_D3DPERF_SetRegion( D3DCOLOR col, LPCWSTR wszName ) +{ + if( DXUT_EnsureD3D9APIs() && s_DynamicD3DPERF_SetRegion != NULL ) + s_DynamicD3DPERF_SetRegion( col, wszName ); +} + +BOOL WINAPI DXUT_Dynamic_D3DPERF_QueryRepeatFrame( void ) +{ + if( DXUT_EnsureD3D9APIs() && s_DynamicD3DPERF_QueryRepeatFrame != NULL ) + return s_DynamicD3DPERF_QueryRepeatFrame(); + else + return FALSE; +} + +void WINAPI DXUT_Dynamic_D3DPERF_SetOptions( DWORD dwOptions ) +{ + if( DXUT_EnsureD3D9APIs() && s_DynamicD3DPERF_SetOptions != NULL ) + s_DynamicD3DPERF_SetOptions( dwOptions ); +} + +DWORD WINAPI DXUT_Dynamic_D3DPERF_GetStatus( void ) +{ + if( DXUT_EnsureD3D9APIs() && s_DynamicD3DPERF_GetStatus != NULL ) + return s_DynamicD3DPERF_GetStatus(); + else + return 0; +} + +HRESULT WINAPI DXUT_Dynamic_CreateDXGIFactory1( REFIID rInterface, void** ppOut ) +{ + if( DXUT_EnsureD3D11APIs() && s_DynamicCreateDXGIFactory != NULL ) + return s_DynamicCreateDXGIFactory( rInterface, ppOut ); + else + return DXUTERR_NODIRECT3D11; +} + + + +HRESULT WINAPI DXUT_Dynamic_D3D11CreateDevice( IDXGIAdapter* pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT32 Flags, + D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + UINT32 SDKVersion, + ID3D11Device** ppDevice, + D3D_FEATURE_LEVEL* pFeatureLevel, + ID3D11DeviceContext** ppImmediateContext ) +{ + if( DXUT_EnsureD3D11APIs() && s_DynamicD3D11CreateDevice != NULL ) + return s_DynamicD3D11CreateDevice( pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, + SDKVersion, ppDevice, pFeatureLevel, ppImmediateContext ); + else + return DXUTERR_NODIRECT3D11; +} + +//-------------------------------------------------------------------------------------- +// Trace a string description of a decl +//-------------------------------------------------------------------------------------- +void WINAPI DXUTTraceDecl( D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE] ) +{ + int iDecl = 0; + for( iDecl = 0; iDecl < MAX_FVF_DECL_SIZE; iDecl++ ) + { + if( decl[iDecl].Stream == 0xFF ) + break; + + DXUTOutputDebugString( L"decl[%d]=Stream:%d, Offset:%d, %s, %s, %s, UsageIndex:%d\n", iDecl, + decl[iDecl].Stream, + decl[iDecl].Offset, + DXUTTraceD3DDECLTYPEtoString( decl[iDecl].Type ), + DXUTTraceD3DDECLMETHODtoString( decl[iDecl].Method ), + DXUTTraceD3DDECLUSAGEtoString( decl[iDecl].Usage ), + decl[iDecl].UsageIndex ); + } + + DXUTOutputDebugString( L"decl[%d]=D3DDECL_END\n", iDecl ); +} + +#define TRACE_ID(iD) case iD: return L#iD; + +//-------------------------------------------------------------------------------------- +WCHAR* WINAPI DXUTTraceWindowsMessage( UINT uMsg ) +{ + switch( uMsg ) + { + TRACE_ID(WM_NULL); + TRACE_ID(WM_CREATE); + TRACE_ID(WM_DESTROY); + TRACE_ID(WM_MOVE); + TRACE_ID(WM_SIZE); + TRACE_ID(WM_ACTIVATE); + TRACE_ID(WM_SETFOCUS); + TRACE_ID(WM_KILLFOCUS); + TRACE_ID(WM_ENABLE); + TRACE_ID(WM_SETREDRAW); + TRACE_ID(WM_SETTEXT); + TRACE_ID(WM_GETTEXT); + TRACE_ID(WM_GETTEXTLENGTH); + TRACE_ID(WM_PAINT); + TRACE_ID(WM_CLOSE); + TRACE_ID(WM_QUERYENDSESSION); + TRACE_ID(WM_QUERYOPEN); + TRACE_ID(WM_ENDSESSION); + TRACE_ID(WM_QUIT); + TRACE_ID(WM_ERASEBKGND); + TRACE_ID(WM_SYSCOLORCHANGE); + TRACE_ID(WM_SHOWWINDOW); + TRACE_ID(WM_WININICHANGE); + TRACE_ID(WM_DEVMODECHANGE); + TRACE_ID(WM_ACTIVATEAPP); + TRACE_ID(WM_FONTCHANGE); + TRACE_ID(WM_TIMECHANGE); + TRACE_ID(WM_CANCELMODE); + TRACE_ID(WM_SETCURSOR); + TRACE_ID(WM_MOUSEACTIVATE); + TRACE_ID(WM_CHILDACTIVATE); + TRACE_ID(WM_QUEUESYNC); + TRACE_ID(WM_GETMINMAXINFO); + TRACE_ID(WM_PAINTICON); + TRACE_ID(WM_ICONERASEBKGND); + TRACE_ID(WM_NEXTDLGCTL); + TRACE_ID(WM_SPOOLERSTATUS); + TRACE_ID(WM_DRAWITEM); + TRACE_ID(WM_MEASUREITEM); + TRACE_ID(WM_DELETEITEM); + TRACE_ID(WM_VKEYTOITEM); + TRACE_ID(WM_CHARTOITEM); + TRACE_ID(WM_SETFONT); + TRACE_ID(WM_GETFONT); + TRACE_ID(WM_SETHOTKEY); + TRACE_ID(WM_GETHOTKEY); + TRACE_ID(WM_QUERYDRAGICON); + TRACE_ID(WM_COMPAREITEM); + TRACE_ID(WM_GETOBJECT); + TRACE_ID(WM_COMPACTING); + TRACE_ID(WM_COMMNOTIFY); + TRACE_ID(WM_WINDOWPOSCHANGING); + TRACE_ID(WM_WINDOWPOSCHANGED); + TRACE_ID(WM_POWER); + TRACE_ID(WM_COPYDATA); + TRACE_ID(WM_CANCELJOURNAL); + TRACE_ID(WM_NOTIFY); + TRACE_ID(WM_INPUTLANGCHANGEREQUEST); + TRACE_ID(WM_INPUTLANGCHANGE); + TRACE_ID(WM_TCARD); + TRACE_ID(WM_HELP); + TRACE_ID(WM_USERCHANGED); + TRACE_ID(WM_NOTIFYFORMAT); + TRACE_ID(WM_CONTEXTMENU); + TRACE_ID(WM_STYLECHANGING); + TRACE_ID(WM_STYLECHANGED); + TRACE_ID(WM_DISPLAYCHANGE); + TRACE_ID(WM_GETICON); + TRACE_ID(WM_SETICON); + TRACE_ID(WM_NCCREATE); + TRACE_ID(WM_NCDESTROY); + TRACE_ID(WM_NCCALCSIZE); + TRACE_ID(WM_NCHITTEST); + TRACE_ID(WM_NCPAINT); + TRACE_ID(WM_NCACTIVATE); + TRACE_ID(WM_GETDLGCODE); + TRACE_ID(WM_SYNCPAINT); + TRACE_ID(WM_NCMOUSEMOVE); + TRACE_ID(WM_NCLBUTTONDOWN); + TRACE_ID(WM_NCLBUTTONUP); + TRACE_ID(WM_NCLBUTTONDBLCLK); + TRACE_ID(WM_NCRBUTTONDOWN); + TRACE_ID(WM_NCRBUTTONUP); + TRACE_ID(WM_NCRBUTTONDBLCLK); + TRACE_ID(WM_NCMBUTTONDOWN); + TRACE_ID(WM_NCMBUTTONUP); + TRACE_ID(WM_NCMBUTTONDBLCLK); + TRACE_ID(WM_NCXBUTTONDOWN); + TRACE_ID(WM_NCXBUTTONUP); + TRACE_ID(WM_NCXBUTTONDBLCLK); + TRACE_ID(WM_INPUT); + TRACE_ID(WM_KEYDOWN); + TRACE_ID(WM_KEYUP); + TRACE_ID(WM_CHAR); + TRACE_ID(WM_DEADCHAR); + TRACE_ID(WM_SYSKEYDOWN); + TRACE_ID(WM_SYSKEYUP); + TRACE_ID(WM_SYSCHAR); + TRACE_ID(WM_SYSDEADCHAR); + TRACE_ID(WM_UNICHAR); + TRACE_ID(WM_IME_STARTCOMPOSITION); + TRACE_ID(WM_IME_ENDCOMPOSITION); + TRACE_ID(WM_IME_COMPOSITION); + TRACE_ID(WM_INITDIALOG); + TRACE_ID(WM_COMMAND); + TRACE_ID(WM_SYSCOMMAND); + TRACE_ID(WM_TIMER); + TRACE_ID(WM_HSCROLL); + TRACE_ID(WM_VSCROLL); + TRACE_ID(WM_INITMENU); + TRACE_ID(WM_INITMENUPOPUP); + TRACE_ID(WM_MENUSELECT); + TRACE_ID(WM_MENUCHAR); + TRACE_ID(WM_ENTERIDLE); + TRACE_ID(WM_MENURBUTTONUP); + TRACE_ID(WM_MENUDRAG); + TRACE_ID(WM_MENUGETOBJECT); + TRACE_ID(WM_UNINITMENUPOPUP); + TRACE_ID(WM_MENUCOMMAND); + TRACE_ID(WM_CHANGEUISTATE); + TRACE_ID(WM_UPDATEUISTATE); + TRACE_ID(WM_QUERYUISTATE); + TRACE_ID(WM_CTLCOLORMSGBOX); + TRACE_ID(WM_CTLCOLOREDIT); + TRACE_ID(WM_CTLCOLORLISTBOX); + TRACE_ID(WM_CTLCOLORBTN); + TRACE_ID(WM_CTLCOLORDLG); + TRACE_ID(WM_CTLCOLORSCROLLBAR); + TRACE_ID(WM_CTLCOLORSTATIC); + TRACE_ID(MN_GETHMENU); + TRACE_ID(WM_MOUSEMOVE); + TRACE_ID(WM_LBUTTONDOWN); + TRACE_ID(WM_LBUTTONUP); + TRACE_ID(WM_LBUTTONDBLCLK); + TRACE_ID(WM_RBUTTONDOWN); + TRACE_ID(WM_RBUTTONUP); + TRACE_ID(WM_RBUTTONDBLCLK); + TRACE_ID(WM_MBUTTONDOWN); + TRACE_ID(WM_MBUTTONUP); + TRACE_ID(WM_MBUTTONDBLCLK); + TRACE_ID(WM_MOUSEWHEEL); + TRACE_ID(WM_XBUTTONDOWN); + TRACE_ID(WM_XBUTTONUP); + TRACE_ID(WM_XBUTTONDBLCLK); + TRACE_ID(WM_PARENTNOTIFY); + TRACE_ID(WM_ENTERMENULOOP); + TRACE_ID(WM_EXITMENULOOP); + TRACE_ID(WM_NEXTMENU); + TRACE_ID(WM_SIZING); + TRACE_ID(WM_CAPTURECHANGED); + TRACE_ID(WM_MOVING); + TRACE_ID(WM_POWERBROADCAST); + TRACE_ID(WM_DEVICECHANGE); + TRACE_ID(WM_MDICREATE); + TRACE_ID(WM_MDIDESTROY); + TRACE_ID(WM_MDIACTIVATE); + TRACE_ID(WM_MDIRESTORE); + TRACE_ID(WM_MDINEXT); + TRACE_ID(WM_MDIMAXIMIZE); + TRACE_ID(WM_MDITILE); + TRACE_ID(WM_MDICASCADE); + TRACE_ID(WM_MDIICONARRANGE); + TRACE_ID(WM_MDIGETACTIVE); + TRACE_ID(WM_MDISETMENU); + TRACE_ID(WM_ENTERSIZEMOVE); + TRACE_ID(WM_EXITSIZEMOVE); + TRACE_ID(WM_DROPFILES); + TRACE_ID(WM_MDIREFRESHMENU); + TRACE_ID(WM_IME_SETCONTEXT); + TRACE_ID(WM_IME_NOTIFY); + TRACE_ID(WM_IME_CONTROL); + TRACE_ID(WM_IME_COMPOSITIONFULL); + TRACE_ID(WM_IME_SELECT); + TRACE_ID(WM_IME_CHAR); + TRACE_ID(WM_IME_REQUEST); + TRACE_ID(WM_IME_KEYDOWN); + TRACE_ID(WM_IME_KEYUP); + TRACE_ID(WM_MOUSEHOVER); + TRACE_ID(WM_MOUSELEAVE); + TRACE_ID(WM_NCMOUSEHOVER); + TRACE_ID(WM_NCMOUSELEAVE); + TRACE_ID(WM_WTSSESSION_CHANGE); + TRACE_ID(WM_TABLET_FIRST); + TRACE_ID(WM_TABLET_LAST); + TRACE_ID(WM_CUT); + TRACE_ID(WM_COPY); + TRACE_ID(WM_PASTE); + TRACE_ID(WM_CLEAR); + TRACE_ID(WM_UNDO); + TRACE_ID(WM_RENDERFORMAT); + TRACE_ID(WM_RENDERALLFORMATS); + TRACE_ID(WM_DESTROYCLIPBOARD); + TRACE_ID(WM_DRAWCLIPBOARD); + TRACE_ID(WM_PAINTCLIPBOARD); + TRACE_ID(WM_VSCROLLCLIPBOARD); + TRACE_ID(WM_SIZECLIPBOARD); + TRACE_ID(WM_ASKCBFORMATNAME); + TRACE_ID(WM_CHANGECBCHAIN); + TRACE_ID(WM_HSCROLLCLIPBOARD); + TRACE_ID(WM_QUERYNEWPALETTE); + TRACE_ID(WM_PALETTEISCHANGING); + TRACE_ID(WM_PALETTECHANGED); + TRACE_ID(WM_HOTKEY); + TRACE_ID(WM_PRINT); + TRACE_ID(WM_PRINTCLIENT); + TRACE_ID(WM_APPCOMMAND); + TRACE_ID(WM_THEMECHANGED); + TRACE_ID(WM_HANDHELDFIRST); + TRACE_ID(WM_HANDHELDLAST); + TRACE_ID(WM_AFXFIRST); + TRACE_ID(WM_AFXLAST); + TRACE_ID(WM_PENWINFIRST); + TRACE_ID(WM_PENWINLAST); + TRACE_ID(WM_APP); + default: + return L"Unknown"; + } +} + + +//-------------------------------------------------------------------------------------- +WCHAR* WINAPI DXUTTraceD3DDECLTYPEtoString( BYTE t ) +{ + switch( t ) + { + case D3DDECLTYPE_FLOAT1: + return L"D3DDECLTYPE_FLOAT1"; + case D3DDECLTYPE_FLOAT2: + return L"D3DDECLTYPE_FLOAT2"; + case D3DDECLTYPE_FLOAT3: + return L"D3DDECLTYPE_FLOAT3"; + case D3DDECLTYPE_FLOAT4: + return L"D3DDECLTYPE_FLOAT4"; + case D3DDECLTYPE_D3DCOLOR: + return L"D3DDECLTYPE_D3DCOLOR"; + case D3DDECLTYPE_UBYTE4: + return L"D3DDECLTYPE_UBYTE4"; + case D3DDECLTYPE_SHORT2: + return L"D3DDECLTYPE_SHORT2"; + case D3DDECLTYPE_SHORT4: + return L"D3DDECLTYPE_SHORT4"; + case D3DDECLTYPE_UBYTE4N: + return L"D3DDECLTYPE_UBYTE4N"; + case D3DDECLTYPE_SHORT2N: + return L"D3DDECLTYPE_SHORT2N"; + case D3DDECLTYPE_SHORT4N: + return L"D3DDECLTYPE_SHORT4N"; + case D3DDECLTYPE_USHORT2N: + return L"D3DDECLTYPE_USHORT2N"; + case D3DDECLTYPE_USHORT4N: + return L"D3DDECLTYPE_USHORT4N"; + case D3DDECLTYPE_UDEC3: + return L"D3DDECLTYPE_UDEC3"; + case D3DDECLTYPE_DEC3N: + return L"D3DDECLTYPE_DEC3N"; + case D3DDECLTYPE_FLOAT16_2: + return L"D3DDECLTYPE_FLOAT16_2"; + case D3DDECLTYPE_FLOAT16_4: + return L"D3DDECLTYPE_FLOAT16_4"; + case D3DDECLTYPE_UNUSED: + return L"D3DDECLTYPE_UNUSED"; + default: + return L"D3DDECLTYPE Unknown"; + } +} + +WCHAR* WINAPI DXUTTraceD3DDECLMETHODtoString( BYTE m ) +{ + switch( m ) + { + case D3DDECLMETHOD_DEFAULT: + return L"D3DDECLMETHOD_DEFAULT"; + case D3DDECLMETHOD_PARTIALU: + return L"D3DDECLMETHOD_PARTIALU"; + case D3DDECLMETHOD_PARTIALV: + return L"D3DDECLMETHOD_PARTIALV"; + case D3DDECLMETHOD_CROSSUV: + return L"D3DDECLMETHOD_CROSSUV"; + case D3DDECLMETHOD_UV: + return L"D3DDECLMETHOD_UV"; + case D3DDECLMETHOD_LOOKUP: + return L"D3DDECLMETHOD_LOOKUP"; + case D3DDECLMETHOD_LOOKUPPRESAMPLED: + return L"D3DDECLMETHOD_LOOKUPPRESAMPLED"; + default: + return L"D3DDECLMETHOD Unknown"; + } +} + +WCHAR* WINAPI DXUTTraceD3DDECLUSAGEtoString( BYTE u ) +{ + switch( u ) + { + case D3DDECLUSAGE_POSITION: + return L"D3DDECLUSAGE_POSITION"; + case D3DDECLUSAGE_BLENDWEIGHT: + return L"D3DDECLUSAGE_BLENDWEIGHT"; + case D3DDECLUSAGE_BLENDINDICES: + return L"D3DDECLUSAGE_BLENDINDICES"; + case D3DDECLUSAGE_NORMAL: + return L"D3DDECLUSAGE_NORMAL"; + case D3DDECLUSAGE_PSIZE: + return L"D3DDECLUSAGE_PSIZE"; + case D3DDECLUSAGE_TEXCOORD: + return L"D3DDECLUSAGE_TEXCOORD"; + case D3DDECLUSAGE_TANGENT: + return L"D3DDECLUSAGE_TANGENT"; + case D3DDECLUSAGE_BINORMAL: + return L"D3DDECLUSAGE_BINORMAL"; + case D3DDECLUSAGE_TESSFACTOR: + return L"D3DDECLUSAGE_TESSFACTOR"; + case D3DDECLUSAGE_POSITIONT: + return L"D3DDECLUSAGE_POSITIONT"; + case D3DDECLUSAGE_COLOR: + return L"D3DDECLUSAGE_COLOR"; + case D3DDECLUSAGE_FOG: + return L"D3DDECLUSAGE_FOG"; + case D3DDECLUSAGE_DEPTH: + return L"D3DDECLUSAGE_DEPTH"; + case D3DDECLUSAGE_SAMPLE: + return L"D3DDECLUSAGE_SAMPLE"; + default: + return L"D3DDECLUSAGE Unknown"; + } +} + + +//-------------------------------------------------------------------------------------- +// Multimon API handling for OSes with or without multimon API support +//-------------------------------------------------------------------------------------- +#define DXUT_PRIMARY_MONITOR ((HMONITOR)0x12340042) +typedef HMONITOR ( WINAPI* LPMONITORFROMWINDOW )( HWND, DWORD ); +typedef BOOL ( WINAPI* LPGETMONITORINFO )( HMONITOR, LPMONITORINFO ); +typedef HMONITOR ( WINAPI* LPMONITORFROMRECT )( LPCRECT lprcScreenCoords, DWORD dwFlags ); + +BOOL WINAPI DXUTGetMonitorInfo( HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo ) +{ + static bool s_bInited = false; + static LPGETMONITORINFO s_pFnGetMonitorInfo = NULL; + if( !s_bInited ) + { + s_bInited = true; + HMODULE hUser32 = GetModuleHandle( L"USER32" ); + if( hUser32 ) + { + OSVERSIONINFOA osvi = + { + 0 + }; osvi.dwOSVersionInfoSize = sizeof( osvi ); GetVersionExA( ( OSVERSIONINFOA* )&osvi ); + bool bNT = ( VER_PLATFORM_WIN32_NT == osvi.dwPlatformId ); + s_pFnGetMonitorInfo = ( LPGETMONITORINFO )( bNT ? GetProcAddress( hUser32, + "GetMonitorInfoW" ) : + GetProcAddress( hUser32, "GetMonitorInfoA" ) ); + } + } + + if( s_pFnGetMonitorInfo ) + return s_pFnGetMonitorInfo( hMonitor, lpMonitorInfo ); + + RECT rcWork; + if( ( hMonitor == DXUT_PRIMARY_MONITOR ) && lpMonitorInfo && ( lpMonitorInfo->cbSize >= sizeof( MONITORINFO ) ) && + SystemParametersInfoA( SPI_GETWORKAREA, 0, &rcWork, 0 ) ) + { + lpMonitorInfo->rcMonitor.left = 0; + lpMonitorInfo->rcMonitor.top = 0; + lpMonitorInfo->rcMonitor.right = GetSystemMetrics( SM_CXSCREEN ); + lpMonitorInfo->rcMonitor.bottom = GetSystemMetrics( SM_CYSCREEN ); + lpMonitorInfo->rcWork = rcWork; + lpMonitorInfo->dwFlags = MONITORINFOF_PRIMARY; + return TRUE; + } + return FALSE; +} + + +HMONITOR WINAPI DXUTMonitorFromWindow( HWND hWnd, DWORD dwFlags ) +{ + static bool s_bInited = false; + static LPMONITORFROMWINDOW s_pFnGetMonitorFromWindow = NULL; + if( !s_bInited ) + { + s_bInited = true; + HMODULE hUser32 = GetModuleHandle( L"USER32" ); + if( hUser32 ) s_pFnGetMonitorFromWindow = ( LPMONITORFROMWINDOW )GetProcAddress( hUser32, + "MonitorFromWindow" ); + } + + if( s_pFnGetMonitorFromWindow ) + return s_pFnGetMonitorFromWindow( hWnd, dwFlags ); + else + return DXUT_PRIMARY_MONITOR; +} + + +HMONITOR WINAPI DXUTMonitorFromRect( LPCRECT lprcScreenCoords, DWORD dwFlags ) +{ + static bool s_bInited = false; + static LPMONITORFROMRECT s_pFnGetMonitorFromRect = NULL; + if( !s_bInited ) + { + s_bInited = true; + HMODULE hUser32 = GetModuleHandle( L"USER32" ); + if( hUser32 ) s_pFnGetMonitorFromRect = ( LPMONITORFROMRECT )GetProcAddress( hUser32, "MonitorFromRect" ); + } + + if( s_pFnGetMonitorFromRect ) + return s_pFnGetMonitorFromRect( lprcScreenCoords, dwFlags ); + else + return DXUT_PRIMARY_MONITOR; +} + + +//-------------------------------------------------------------------------------------- +// Get the desktop resolution of an adapter. This isn't the same as the current resolution +// from GetAdapterDisplayMode since the device might be fullscreen +//-------------------------------------------------------------------------------------- +void WINAPI DXUTGetDesktopResolution( UINT AdapterOrdinal, UINT* pWidth, UINT* pHeight ) +{ + DXUTDeviceSettings DeviceSettings = DXUTGetDeviceSettings(); + + WCHAR strDeviceName[256] = {0}; + DEVMODE devMode; + ZeroMemory( &devMode, sizeof( DEVMODE ) ); + devMode.dmSize = sizeof( DEVMODE ); + if( DeviceSettings.ver == DXUT_D3D9_DEVICE ) + { + CD3D9Enumeration* pd3dEnum = DXUTGetD3D9Enumeration(); + CD3D9EnumAdapterInfo* pAdapterInfo = pd3dEnum->GetAdapterInfo( AdapterOrdinal ); + if( pAdapterInfo ) + { + MultiByteToWideChar( CP_ACP, 0, pAdapterInfo->AdapterIdentifier.DeviceName, -1, strDeviceName, 256 ); + strDeviceName[255] = 0; + } + } + else + { + CD3D11Enumeration* pd3dEnum = DXUTGetD3D11Enumeration(); + CD3D11EnumOutputInfo* pOutputInfo = pd3dEnum->GetOutputInfo( AdapterOrdinal, DeviceSettings.d3d11.Output ); + if( pOutputInfo ) + { + wcscpy_s( strDeviceName, 256, pOutputInfo->Desc.DeviceName ); + } + } + + EnumDisplaySettings( strDeviceName, ENUM_REGISTRY_SETTINGS, &devMode ); + if( pWidth ) + *pWidth = devMode.dmPelsWidth; + if( pHeight ) + *pHeight = devMode.dmPelsHeight; +} + + +//-------------------------------------------------------------------------------------- +// Display error msg box to help debug +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTTrace( const CHAR* strFile, DWORD dwLine, HRESULT hr, + const WCHAR* strMsg, bool bPopMsgBox ) +{ + bool bShowMsgBoxOnError = DXUTGetShowMsgBoxOnError(); + if( bPopMsgBox && bShowMsgBoxOnError == false ) + bPopMsgBox = false; + + return DXTrace( strFile, dwLine, hr, strMsg, bPopMsgBox ); +} + + +//-------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------------- +void WINAPI DXUTConvertDeviceSettings11to9( DXUTD3D11DeviceSettings* pIn, DXUTD3D9DeviceSettings* pOut ) +{ + pOut->AdapterOrdinal = pIn->AdapterOrdinal; + + if( pIn->DriverType == D3D_DRIVER_TYPE_HARDWARE ) + pOut->DeviceType = D3DDEVTYPE_HAL; + else if( pIn->DriverType == D3D_DRIVER_TYPE_REFERENCE ) + pOut->DeviceType = D3DDEVTYPE_REF; + else if( pIn->DriverType == D3D_DRIVER_TYPE_NULL ) + pOut->DeviceType = D3DDEVTYPE_NULLREF; + + pOut->AdapterFormat = ConvertFormatDXGIToD3D9( pIn->sd.BufferDesc.Format ); + pOut->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING; + pOut->pp.BackBufferWidth = pIn->sd.BufferDesc.Width; + pOut->pp.BackBufferHeight = pIn->sd.BufferDesc.Height; + pOut->pp.BackBufferFormat = ConvertFormatDXGIToD3D9( pIn->sd.BufferDesc.Format ); + pOut->pp.BackBufferCount = pIn->sd.BufferCount; + pOut->pp.MultiSampleType = ( D3DMULTISAMPLE_TYPE )pIn->sd.SampleDesc.Count; + pOut->pp.MultiSampleQuality = pIn->sd.SampleDesc.Quality; + pOut->pp.SwapEffect = D3DSWAPEFFECT_DISCARD; + pOut->pp.hDeviceWindow = pIn->sd.OutputWindow; + pOut->pp.Windowed = pIn->sd.Windowed; + pOut->pp.EnableAutoDepthStencil = true; + pOut->pp.AutoDepthStencilFormat = D3DFMT_D24FS8; + pOut->pp.Flags = 0; + if( pIn->sd.BufferDesc.RefreshRate.Denominator == 0 ) + pOut->pp.FullScreen_RefreshRateInHz = 60; + else + pOut->pp.FullScreen_RefreshRateInHz = pIn->sd.BufferDesc.RefreshRate.Numerator / + pIn->sd.BufferDesc.RefreshRate.Denominator; + + switch( pIn->SyncInterval ) + { + case 0: + pOut->pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; break; + case 2: + pOut->pp.PresentationInterval = D3DPRESENT_INTERVAL_TWO; break; + case 3: + pOut->pp.PresentationInterval = D3DPRESENT_INTERVAL_THREE; break; + case 4: + pOut->pp.PresentationInterval = D3DPRESENT_INTERVAL_FOUR; break; + + case 1: + default: + pOut->pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + break; + } +} + + +//-------------------------------------------------------------------------------------- +void WINAPI DXUTConvertDeviceSettings9to11( DXUTD3D9DeviceSettings* pIn, DXUTD3D11DeviceSettings* pOut ) +{ + pOut->AdapterOrdinal = pIn->AdapterOrdinal; + + if( pIn->DeviceType == D3DDEVTYPE_HAL ) + pOut->DriverType = D3D_DRIVER_TYPE_HARDWARE; + else if( pIn->DeviceType == D3DDEVTYPE_REF ) + pOut->DriverType = D3D_DRIVER_TYPE_REFERENCE; + else if( pIn->DeviceType == D3DDEVTYPE_NULLREF ) + pOut->DriverType = D3D_DRIVER_TYPE_NULL; + + pOut->Output = 0; + + pOut->sd.BufferDesc.Width = pIn->pp.BackBufferWidth; + pOut->sd.BufferDesc.Height = pIn->pp.BackBufferHeight; + pOut->sd.BufferDesc.RefreshRate.Numerator = pIn->pp.FullScreen_RefreshRateInHz; + pOut->sd.BufferDesc.RefreshRate.Denominator = 1; + pOut->sd.BufferDesc.Format = ConvertFormatD3D9ToDXGI( pIn->pp.BackBufferFormat ); + + if( pIn->pp.MultiSampleType == D3DMULTISAMPLE_NONMASKABLE ) + { + pOut->sd.SampleDesc.Count = pIn->pp.MultiSampleQuality; + pOut->sd.SampleDesc.Quality = 0; + } + else + { + pOut->sd.SampleDesc.Count = pIn->pp.MultiSampleType; + pOut->sd.SampleDesc.Quality = pIn->pp.MultiSampleQuality; + } + + pOut->sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + pOut->sd.BufferCount = pIn->pp.BackBufferCount; + pOut->sd.OutputWindow = pIn->pp.hDeviceWindow; + pOut->sd.Windowed = pIn->pp.Windowed; + +#if defined(DEBUG) || defined(_DEBUG) + pOut->CreateFlags = D3D11_CREATE_DEVICE_DEBUG; +#else + pOut->CreateFlags = 0; +#endif + + switch( pIn->pp.PresentationInterval ) + { + case D3DPRESENT_INTERVAL_IMMEDIATE: + pOut->SyncInterval = 0; break; + case D3DPRESENT_INTERVAL_ONE: + pOut->SyncInterval = 1; break; + case D3DPRESENT_INTERVAL_TWO: + pOut->SyncInterval = 2; break; + case D3DPRESENT_INTERVAL_THREE: + pOut->SyncInterval = 3; break; + case D3DPRESENT_INTERVAL_FOUR: + pOut->SyncInterval = 4; break; + + case D3DPRESENT_INTERVAL_DEFAULT: + default: + pOut->SyncInterval = 1; + break; + } + + pOut->PresentFlags = 0; +} + + + +DXGI_FORMAT WINAPI ConvertFormatD3D9ToDXGI( D3DFORMAT fmt ) +{ + switch( fmt ) + { + case D3DFMT_UNKNOWN: + return DXGI_FORMAT_UNKNOWN; + case D3DFMT_R8G8B8: + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DFMT_R5G6B5: + return DXGI_FORMAT_B5G6R5_UNORM; + case D3DFMT_X1R5G5B5: + case D3DFMT_A1R5G5B5: + return DXGI_FORMAT_B5G5R5A1_UNORM; + case D3DFMT_A4R4G4B4: + return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DFMT_R3G3B2: + return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DFMT_A8: + return DXGI_FORMAT_A8_UNORM; + case D3DFMT_A8R3G3B2: + return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DFMT_X4R4G4B4: + return DXGI_FORMAT_R8G8B8A8_UNORM; + case D3DFMT_A2B10G10R10: + return DXGI_FORMAT_R10G10B10A2_UNORM; + case D3DFMT_A8B8G8R8: + case D3DFMT_X8B8G8R8: + return DXGI_FORMAT_B8G8R8A8_UNORM; + case D3DFMT_G16R16: + return DXGI_FORMAT_R16G16_UNORM; + case D3DFMT_A2R10G10B10: + return DXGI_FORMAT_R10G10B10A2_UNORM; + case D3DFMT_A16B16G16R16: + return DXGI_FORMAT_R16G16B16A16_UNORM; + case D3DFMT_R16F: + return DXGI_FORMAT_R16_FLOAT; + case D3DFMT_G16R16F: + return DXGI_FORMAT_R16G16_FLOAT; + case D3DFMT_A16B16G16R16F: + return DXGI_FORMAT_R16G16B16A16_FLOAT; + case D3DFMT_R32F: + return DXGI_FORMAT_R32_FLOAT; + case D3DFMT_G32R32F: + return DXGI_FORMAT_R32G32_FLOAT; + case D3DFMT_A32B32G32R32F: + return DXGI_FORMAT_R32G32B32A32_FLOAT; + } + return DXGI_FORMAT_UNKNOWN; +} + + +D3DFORMAT WINAPI ConvertFormatDXGIToD3D9( DXGI_FORMAT fmt ) +{ + switch( fmt ) + { + case DXGI_FORMAT_UNKNOWN: + return D3DFMT_UNKNOWN; + case DXGI_FORMAT_R8G8B8A8_UNORM: + return D3DFMT_A8R8G8B8; + case DXGI_FORMAT_B5G6R5_UNORM: + return D3DFMT_R5G6B5; + case DXGI_FORMAT_B5G5R5A1_UNORM: + return D3DFMT_A1R5G5B5; + case DXGI_FORMAT_A8_UNORM: + return D3DFMT_A8; + case DXGI_FORMAT_R10G10B10A2_UNORM: + return D3DFMT_A2B10G10R10; + case DXGI_FORMAT_B8G8R8A8_UNORM: + return D3DFMT_A8B8G8R8; + case DXGI_FORMAT_R16G16_UNORM: + return D3DFMT_G16R16; + case DXGI_FORMAT_R16G16B16A16_UNORM: + return D3DFMT_A16B16G16R16; + case DXGI_FORMAT_R16_FLOAT: + return D3DFMT_R16F; + case DXGI_FORMAT_R16G16_FLOAT: + return D3DFMT_G16R16F; + case DXGI_FORMAT_R16G16B16A16_FLOAT: + return D3DFMT_A16B16G16R16F; + case DXGI_FORMAT_R32_FLOAT: + return D3DFMT_R32F; + case DXGI_FORMAT_R32G32_FLOAT: + return D3DFMT_G32R32F; + case DXGI_FORMAT_R32G32B32A32_FLOAT: + return D3DFMT_A32B32G32R32F; + } + return D3DFMT_UNKNOWN; +} + +//-------------------------------------------------------------------------------------- +IDirect3DDevice9* WINAPI DXUTCreateRefDevice9( HWND hWnd, bool bNullRef ) +{ + HRESULT hr; + IDirect3D9* pD3D = DXUT_Dynamic_Direct3DCreate9( D3D_SDK_VERSION ); + if( NULL == pD3D ) + return NULL; + + D3DDISPLAYMODE Mode; + pD3D->GetAdapterDisplayMode( 0, &Mode ); + + D3DPRESENT_PARAMETERS pp; + ZeroMemory( &pp, sizeof( D3DPRESENT_PARAMETERS ) ); + pp.BackBufferWidth = 1; + pp.BackBufferHeight = 1; + pp.BackBufferFormat = Mode.Format; + pp.BackBufferCount = 1; + pp.SwapEffect = D3DSWAPEFFECT_COPY; + pp.Windowed = TRUE; + pp.hDeviceWindow = hWnd; + + IDirect3DDevice9* pd3dDevice = NULL; + hr = pD3D->CreateDevice( D3DADAPTER_DEFAULT, bNullRef ? D3DDEVTYPE_NULLREF : D3DDEVTYPE_REF, + hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, &pd3dDevice ); + + SAFE_RELEASE( pD3D ); + return pd3dDevice; +} + + +//-------------------------------------------------------------------------------------- +// Helper function to launch the Media Center UI after the program terminates +//-------------------------------------------------------------------------------------- +bool DXUTReLaunchMediaCenter() +{ + // Get the path to Media Center + WCHAR szExpandedPath[MAX_PATH]; + if( !ExpandEnvironmentStrings( L"%SystemRoot%\\ehome\\ehshell.exe", szExpandedPath, MAX_PATH ) ) + return false; + + // Skip if ehshell.exe doesn't exist + if( GetFileAttributes( szExpandedPath ) == 0xFFFFFFFF ) + return false; + + // Launch ehshell.exe + INT_PTR result = ( INT_PTR )ShellExecute( NULL, TEXT( "open" ), szExpandedPath, NULL, NULL, SW_SHOWNORMAL ); + return ( result > 32 ); +} + +typedef DWORD ( WINAPI* LPXINPUTGETSTATE )( DWORD dwUserIndex, XINPUT_STATE* pState ); +typedef DWORD ( WINAPI* LPXINPUTSETSTATE )( DWORD dwUserIndex, XINPUT_VIBRATION* pVibration ); +typedef DWORD ( WINAPI* LPXINPUTGETCAPABILITIES )( DWORD dwUserIndex, DWORD dwFlags, + XINPUT_CAPABILITIES* pCapabilities ); +typedef void ( WINAPI* LPXINPUTENABLE )( BOOL bEnable ); + +//-------------------------------------------------------------------------------------- +// Does extra processing on XInput data to make it slightly more convenient to use +//-------------------------------------------------------------------------------------- +HRESULT DXUTGetGamepadState( DWORD dwPort, DXUT_GAMEPAD* pGamePad, bool bThumbstickDeadZone, + bool bSnapThumbstickToCardinals ) +{ + if( dwPort >= DXUT_MAX_CONTROLLERS || pGamePad == NULL ) + return E_FAIL; + + static LPXINPUTGETSTATE s_pXInputGetState = NULL; + static LPXINPUTGETCAPABILITIES s_pXInputGetCapabilities = NULL; + if( NULL == s_pXInputGetState || NULL == s_pXInputGetCapabilities ) + { + HINSTANCE hInst = LoadLibrary( XINPUT_DLL ); + if( hInst ) + { + s_pXInputGetState = ( LPXINPUTGETSTATE )GetProcAddress( hInst, "XInputGetState" ); + s_pXInputGetCapabilities = ( LPXINPUTGETCAPABILITIES )GetProcAddress( hInst, "XInputGetCapabilities" ); + } + } + if( s_pXInputGetState == NULL ) + return E_FAIL; + + XINPUT_STATE InputState; + DWORD dwResult = s_pXInputGetState( dwPort, &InputState ); + + // Track insertion and removals + BOOL bWasConnected = pGamePad->bConnected; + pGamePad->bConnected = ( dwResult == ERROR_SUCCESS ); + pGamePad->bRemoved = ( bWasConnected && !pGamePad->bConnected ); + pGamePad->bInserted = ( !bWasConnected && pGamePad->bConnected ); + + // Don't update rest of the state if not connected + if( !pGamePad->bConnected ) + return S_OK; + + // Store the capabilities of the device + if( pGamePad->bInserted ) + { + ZeroMemory( pGamePad, sizeof( DXUT_GAMEPAD ) ); + pGamePad->bConnected = true; + pGamePad->bInserted = true; + if( s_pXInputGetCapabilities ) + s_pXInputGetCapabilities( dwPort, XINPUT_DEVTYPE_GAMEPAD, &pGamePad->caps ); + } + + // Copy gamepad to local structure (assumes that XINPUT_GAMEPAD at the front in CONTROLER_STATE) + memcpy( pGamePad, &InputState.Gamepad, sizeof( XINPUT_GAMEPAD ) ); + + if( bSnapThumbstickToCardinals ) + { + // Apply deadzone to each axis independantly to slightly snap to up/down/left/right + if( pGamePad->sThumbLX < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && + pGamePad->sThumbLX > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ) + pGamePad->sThumbLX = 0; + if( pGamePad->sThumbLY < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && + pGamePad->sThumbLY > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ) + pGamePad->sThumbLY = 0; + if( pGamePad->sThumbRX < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE && + pGamePad->sThumbRX > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ) + pGamePad->sThumbRX = 0; + if( pGamePad->sThumbRY < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE && + pGamePad->sThumbRY > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ) + pGamePad->sThumbRY = 0; + } + else if( bThumbstickDeadZone ) + { + // Apply deadzone if centered + if( ( pGamePad->sThumbLX < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && + pGamePad->sThumbLX > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ) && + ( pGamePad->sThumbLY < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && + pGamePad->sThumbLY > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ) ) + { + pGamePad->sThumbLX = 0; + pGamePad->sThumbLY = 0; + } + if( ( pGamePad->sThumbRX < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE && + pGamePad->sThumbRX > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ) && + ( pGamePad->sThumbRY < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE && + pGamePad->sThumbRY > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ) ) + { + pGamePad->sThumbRX = 0; + pGamePad->sThumbRY = 0; + } + } + + // Convert [-1,+1] range + pGamePad->fThumbLX = pGamePad->sThumbLX / 32767.0f; + pGamePad->fThumbLY = pGamePad->sThumbLY / 32767.0f; + pGamePad->fThumbRX = pGamePad->sThumbRX / 32767.0f; + pGamePad->fThumbRY = pGamePad->sThumbRY / 32767.0f; + + // Get the boolean buttons that have been pressed since the last call. + // Each button is represented by one bit. + pGamePad->wPressedButtons = ( pGamePad->wLastButtons ^ pGamePad->wButtons ) & pGamePad->wButtons; + pGamePad->wLastButtons = pGamePad->wButtons; + + // Figure out if the left trigger has been pressed or released + bool bPressed = ( pGamePad->bLeftTrigger > DXUT_GAMEPAD_TRIGGER_THRESHOLD ); + pGamePad->bPressedLeftTrigger = ( bPressed ) ? !pGamePad->bLastLeftTrigger : false; + pGamePad->bLastLeftTrigger = bPressed; + + // Figure out if the right trigger has been pressed or released + bPressed = ( pGamePad->bRightTrigger > DXUT_GAMEPAD_TRIGGER_THRESHOLD ); + pGamePad->bPressedRightTrigger = ( bPressed ) ? !pGamePad->bLastRightTrigger : false; + pGamePad->bLastRightTrigger = bPressed; + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Don't pause the game or deactive the window without first stopping rumble otherwise +// the controller will continue to rumble +//-------------------------------------------------------------------------------------- +void DXUTEnableXInput( bool bEnable ) +{ + static LPXINPUTENABLE s_pXInputEnable = NULL; + if( NULL == s_pXInputEnable ) + { + HINSTANCE hInst = LoadLibrary( XINPUT_DLL ); + if( hInst ) + s_pXInputEnable = ( LPXINPUTENABLE )GetProcAddress( hInst, "XInputEnable" ); + } + + if( s_pXInputEnable ) + s_pXInputEnable( bEnable ); +} + + +//-------------------------------------------------------------------------------------- +// Don't pause the game or deactive the window without first stopping rumble otherwise +// the controller will continue to rumble +//-------------------------------------------------------------------------------------- +HRESULT DXUTStopRumbleOnAllControllers() +{ + static LPXINPUTSETSTATE s_pXInputSetState = NULL; + if( NULL == s_pXInputSetState ) + { + HINSTANCE hInst = LoadLibrary( XINPUT_DLL ); + if( hInst ) + s_pXInputSetState = ( LPXINPUTSETSTATE )GetProcAddress( hInst, "XInputSetState" ); + } + if( s_pXInputSetState == NULL ) + return E_FAIL; + + XINPUT_VIBRATION vibration; + vibration.wLeftMotorSpeed = 0; + vibration.wRightMotorSpeed = 0; + for( int iUserIndex = 0; iUserIndex < DXUT_MAX_CONTROLLERS; iUserIndex++ ) + s_pXInputSetState( iUserIndex, &vibration ); + + return S_OK; +} + +//-------------------------------------------------------------------------------------- +// Helper functions to create SRGB formats from typeless formats and vice versa +//-------------------------------------------------------------------------------------- +DXGI_FORMAT MAKE_SRGB( DXGI_FORMAT format ) +{ + if( !DXUTIsInGammaCorrectMode() ) + return format; + + switch( format ) + { + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + return DXGI_FORMAT_BC1_UNORM_SRGB; + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + return DXGI_FORMAT_BC2_UNORM_SRGB; + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + return DXGI_FORMAT_BC3_UNORM_SRGB; + + }; + + return format; +} + +//-------------------------------------------------------------------------------------- +DXGI_FORMAT MAKE_TYPELESS( DXGI_FORMAT format ) +{ + if( !DXUTIsInGammaCorrectMode() ) + return format; + + switch( format ) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + return DXGI_FORMAT_R8G8B8A8_TYPELESS; + + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC1_UNORM: + return DXGI_FORMAT_BC1_TYPELESS; + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC2_UNORM: + return DXGI_FORMAT_BC2_TYPELESS; + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC3_UNORM: + return DXGI_FORMAT_BC3_TYPELESS; + }; + + return format; +} + +//-------------------------------------------------------------------------------------- +HRESULT DXUTSnapD3D9Screenshot( LPCTSTR szFileName ) +{ + HRESULT hr = S_OK; + IDirect3DDevice9* pDev = DXUTGetD3D9Device(); + if( !pDev ) + return E_FAIL; + + IDirect3DSurface9* pBackBuffer = NULL; + V_RETURN( pDev->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer ) ); + + return D3DXSaveSurfaceToFile( szFileName, D3DXIFF_BMP, pBackBuffer, NULL, NULL ); +} + + + + +//-------------------------------------------------------------------------------------- +HRESULT DXUTSnapD3D11Screenshot( LPCTSTR szFileName, D3DX11_IMAGE_FILE_FORMAT iff ) +{ + IDXGISwapChain *pSwap = DXUTGetDXGISwapChain(); + + if (!pSwap) + return E_FAIL; + + ID3D11Texture2D* pBackBuffer; + HRESULT hr = pSwap->GetBuffer( 0, __uuidof( *pBackBuffer ), ( LPVOID* )&pBackBuffer ); + if (hr != S_OK) + return hr; + + ID3D11DeviceContext *dc = DXUTGetD3D11DeviceContext(); + if (!dc) { + SAFE_RELEASE(pBackBuffer); + return E_FAIL; + } + ID3D11Device *pDevice = DXUTGetD3D11Device(); + if (!dc) { + SAFE_RELEASE(pBackBuffer); + return E_FAIL; + } + + D3D11_TEXTURE2D_DESC dsc; + pBackBuffer->GetDesc(&dsc); + D3D11_RESOURCE_DIMENSION dim; + pBackBuffer->GetType(&dim); + // special case msaa textures + ID3D11Texture2D *pCompatableTexture = pBackBuffer; + if ( dsc.SampleDesc.Count > 1) { + D3D11_TEXTURE2D_DESC dsc_new = dsc; + dsc_new.SampleDesc.Count = 1; + dsc_new.SampleDesc.Quality = 0; + dsc_new.Usage = D3D11_USAGE_DEFAULT; + dsc_new.BindFlags = 0; + dsc_new.CPUAccessFlags = 0; + ID3D11Texture2D *resolveTexture; + hr = pDevice->CreateTexture2D(&dsc_new, NULL, &resolveTexture); + dc->ResolveSubresource(resolveTexture, 0, pBackBuffer, 0, dsc.Format); + pCompatableTexture = resolveTexture; + pCompatableTexture->GetDesc(&dsc); + } + + hr = D3DX11SaveTextureToFileW(dc, pCompatableTexture, iff, szFileName); + + + SAFE_RELEASE(pBackBuffer); + SAFE_RELEASE(pCompatableTexture); + + return hr; + +} diff --git a/Demos/DX11ClothDemo/DXUT/Core/DXUTmisc.h b/Demos/DX11ClothDemo/DXUT/Core/DXUTmisc.h new file mode 100644 index 0000000..74ac064 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Core/DXUTmisc.h @@ -0,0 +1,594 @@ +//-------------------------------------------------------------------------------------- +// File: DXUTMisc.h +// +// Helper functions for Direct3D programming. +// +// Copyright (c) Microsoft Corporation. All rights reserved +//-------------------------------------------------------------------------------------- +#pragma once +#ifndef DXUT_MISC_H +#define DXUT_MISC_H + +#ifndef MAX_FVF_DECL_SIZE +#define MAX_FVF_DECL_SIZE MAXD3DDECLLENGTH + 1 // +1 for END +#endif + +//-------------------------------------------------------------------------------------- +// XInput helper state/function +// This performs extra processing on XInput gamepad data to make it slightly more convenient to use +// +// Example usage: +// +// DXUT_GAMEPAD gamepad[4]; +// for( DWORD iPort=0; iPort class CGrowableArray +{ +public: + CGrowableArray() { m_pData = NULL; m_nSize = 0; m_nMaxSize = 0; } + CGrowableArray( const CGrowableArray& a ) { for( int i=0; i < a.m_nSize; i++ ) Add( a.m_pData[i] ); } + ~CGrowableArray() { RemoveAll(); } + + const TYPE& operator[]( int nIndex ) const { return GetAt( nIndex ); } + TYPE& operator[]( int nIndex ) { return GetAt( nIndex ); } + + CGrowableArray& operator=( const CGrowableArray& a ) { if( this == &a ) return *this; RemoveAll(); for( int i=0; i < a.m_nSize; i++ ) Add( a.m_pData[i] ); return *this; } + + HRESULT SetSize( int nNewMaxSize ); + HRESULT Add( const TYPE& value ); + HRESULT Insert( int nIndex, const TYPE& value ); + HRESULT SetAt( int nIndex, const TYPE& value ); + TYPE& GetAt( int nIndex ) const { assert( nIndex >= 0 && nIndex < m_nSize ); return m_pData[nIndex]; } + int GetSize() const { return m_nSize; } + TYPE* GetData() { return m_pData; } + bool Contains( const TYPE& value ){ return ( -1 != IndexOf( value ) ); } + + int IndexOf( const TYPE& value ) { return ( m_nSize > 0 ) ? IndexOf( value, 0, m_nSize ) : -1; } + int IndexOf( const TYPE& value, int iStart ) { return IndexOf( value, iStart, m_nSize - iStart ); } + int IndexOf( const TYPE& value, int nIndex, int nNumElements ); + + int LastIndexOf( const TYPE& value ) { return ( m_nSize > 0 ) ? LastIndexOf( value, m_nSize-1, m_nSize ) : -1; } + int LastIndexOf( const TYPE& value, int nIndex ) { return LastIndexOf( value, nIndex, nIndex+1 ); } + int LastIndexOf( const TYPE& value, int nIndex, int nNumElements ); + + HRESULT Remove( int nIndex ); + void RemoveAll() { SetSize(0); } + void Reset() { m_nSize = 0; } + +protected: + TYPE* m_pData; // the actual array of data + int m_nSize; // # of elements (upperBound - 1) + int m_nMaxSize; // max allocated + + HRESULT SetSizeInternal( int nNewMaxSize ); // This version doesn't call ctor or dtor. +}; + + +//-------------------------------------------------------------------------------------- +// Performs timer operations +// Use DXUTGetGlobalTimer() to get the global instance +//-------------------------------------------------------------------------------------- +class CDXUTTimer +{ +public: + CDXUTTimer(); + + void Reset(); // resets the timer + void Start(); // starts the timer + void Stop(); // stop (or pause) the timer + void Advance(); // advance the timer by 0.1 seconds + double GetAbsoluteTime(); // get the absolute system time + double GetTime(); // get the current time + float GetElapsedTime(); // get the time that elapsed between Get*ElapsedTime() calls + void GetTimeValues( double* pfTime, double* pfAbsoluteTime, float* pfElapsedTime ); // get all time values at once + bool IsStopped(); // returns true if timer stopped + + // Limit the current thread to one processor (the current one). This ensures that timing code runs + // on only one processor, and will not suffer any ill effects from power management. + void LimitThreadAffinityToCurrentProc(); + +protected: + LARGE_INTEGER GetAdjustedCurrentTime(); + + bool m_bUsingQPF; + bool m_bTimerStopped; + LONGLONG m_llQPFTicksPerSec; + + LONGLONG m_llStopTime; + LONGLONG m_llLastElapsedTime; + LONGLONG m_llBaseTime; +}; + +CDXUTTimer* WINAPI DXUTGetGlobalTimer(); + + +//-------------------------------------------------------------------------------------- +// Returns the string for the given D3DFORMAT. +// bWithPrefix determines whether the string should include the "D3DFMT_" +//-------------------------------------------------------------------------------------- +LPCWSTR WINAPI DXUTD3DFormatToString( D3DFORMAT format, bool bWithPrefix ); + + +//-------------------------------------------------------------------------------------- +// Returns the string for the given DXGI_FORMAT. +// bWithPrefix determines whether the string should include the "DXGI_FORMAT_" +//-------------------------------------------------------------------------------------- +LPCWSTR WINAPI DXUTDXGIFormatToString( DXGI_FORMAT format, bool bWithPrefix ); + + +//-------------------------------------------------------------------------------------- +// Device settings conversion +//-------------------------------------------------------------------------------------- +void WINAPI DXUTConvertDeviceSettings11to9( DXUTD3D11DeviceSettings* pIn, DXUTD3D9DeviceSettings* pOut ); +void WINAPI DXUTConvertDeviceSettings9to11( DXUTD3D9DeviceSettings* pIn, DXUTD3D11DeviceSettings* pOut ); + +DXGI_FORMAT WINAPI ConvertFormatD3D9ToDXGI( D3DFORMAT fmt ); +D3DFORMAT WINAPI ConvertFormatDXGIToD3D9( DXGI_FORMAT fmt ); + + +//-------------------------------------------------------------------------------------- +// Debug printing support +// See dxerr.h for more debug printing support +//-------------------------------------------------------------------------------------- +void WINAPI DXUTOutputDebugStringW( LPCWSTR strMsg, ... ); +void WINAPI DXUTOutputDebugStringA( LPCSTR strMsg, ... ); +HRESULT WINAPI DXUTTrace( const CHAR* strFile, DWORD dwLine, HRESULT hr, const WCHAR* strMsg, bool bPopMsgBox ); +void WINAPI DXUTTraceDecl( D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE] ); +WCHAR* WINAPI DXUTTraceD3DDECLUSAGEtoString( BYTE u ); +WCHAR* WINAPI DXUTTraceD3DDECLMETHODtoString( BYTE m ); +WCHAR* WINAPI DXUTTraceD3DDECLTYPEtoString( BYTE t ); +WCHAR* WINAPI DXUTTraceWindowsMessage( UINT uMsg ); + +#ifdef UNICODE +#define DXUTOutputDebugString DXUTOutputDebugStringW +#else +#define DXUTOutputDebugString DXUTOutputDebugStringA +#endif + +// These macros are very similar to dxerr's but it special cases the HRESULT defined +// by DXUT to pop better message boxes. +#if defined(DEBUG) || defined(_DEBUG) +#define DXUT_ERR(str,hr) DXUTTrace( __FILE__, (DWORD)__LINE__, hr, str, false ) +#define DXUT_ERR_MSGBOX(str,hr) DXUTTrace( __FILE__, (DWORD)__LINE__, hr, str, true ) +#define DXUTTRACE DXUTOutputDebugString +#else +#define DXUT_ERR(str,hr) (hr) +#define DXUT_ERR_MSGBOX(str,hr) (hr) +#define DXUTTRACE (__noop) +#endif + + +//-------------------------------------------------------------------------------------- +// Direct3D9 dynamic linking support -- calls top-level D3D9 APIs with graceful +// failure if APIs are not present. +//-------------------------------------------------------------------------------------- + +IDirect3D9 * WINAPI DXUT_Dynamic_Direct3DCreate9(UINT SDKVersion); +int WINAPI DXUT_Dynamic_D3DPERF_BeginEvent( D3DCOLOR col, LPCWSTR wszName ); +int WINAPI DXUT_Dynamic_D3DPERF_EndEvent( void ); +void WINAPI DXUT_Dynamic_D3DPERF_SetMarker( D3DCOLOR col, LPCWSTR wszName ); +void WINAPI DXUT_Dynamic_D3DPERF_SetRegion( D3DCOLOR col, LPCWSTR wszName ); +BOOL WINAPI DXUT_Dynamic_D3DPERF_QueryRepeatFrame( void ); +void WINAPI DXUT_Dynamic_D3DPERF_SetOptions( DWORD dwOptions ); +DWORD WINAPI DXUT_Dynamic_D3DPERF_GetStatus( void ); +HRESULT WINAPI DXUT_Dynamic_CreateDXGIFactory1( REFIID rInterface, void** ppOut ); + +HRESULT WINAPI DXUT_Dynamic_D3D11CreateDevice( IDXGIAdapter* pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT32 Flags, + D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + UINT32 SDKVersion, + ID3D11Device** ppDevice, + D3D_FEATURE_LEVEL* pFeatureLevel, + ID3D11DeviceContext** ppImmediateContext ); + +bool DXUT_EnsureD3D11APIs( void ); + + +//-------------------------------------------------------------------------------------- +// Profiling/instrumentation support +//-------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------------- +// Some D3DPERF APIs take a color that can be used when displaying user events in +// performance analysis tools. The following constants are provided for your +// convenience, but you can use any colors you like. +//-------------------------------------------------------------------------------------- +const D3DCOLOR DXUT_PERFEVENTCOLOR = D3DCOLOR_XRGB( 200, 100, 100 ); +const D3DCOLOR DXUT_PERFEVENTCOLOR2 = D3DCOLOR_XRGB( 100, 200, 100 ); +const D3DCOLOR DXUT_PERFEVENTCOLOR3 = D3DCOLOR_XRGB( 100, 100, 200 ); + +//-------------------------------------------------------------------------------------- +// The following macros provide a convenient way for your code to call the D3DPERF +// functions only when PROFILE is defined. If PROFILE is not defined (as for the final +// release version of a program), these macros evaluate to nothing, so no detailed event +// information is embedded in your shipping program. It is recommended that you create +// and use three build configurations for your projects: +// Debug (nonoptimized code, asserts active, PROFILE defined to assist debugging) +// Profile (optimized code, asserts disabled, PROFILE defined to assist optimization) +// Release (optimized code, asserts disabled, PROFILE not defined) +//-------------------------------------------------------------------------------------- +#ifdef PROFILE +// PROFILE is defined, so these macros call the D3DPERF functions +#define DXUT_BeginPerfEvent( color, pstrMessage ) DXUT_Dynamic_D3DPERF_BeginEvent( color, pstrMessage ) +#define DXUT_EndPerfEvent() DXUT_Dynamic_D3DPERF_EndEvent() +#define DXUT_SetPerfMarker( color, pstrMessage ) DXUT_Dynamic_D3DPERF_SetMarker( color, pstrMessage ) +#else +// PROFILE is not defined, so these macros do nothing +#define DXUT_BeginPerfEvent( color, pstrMessage ) (__noop) +#define DXUT_EndPerfEvent() (__noop) +#define DXUT_SetPerfMarker( color, pstrMessage ) (__noop) +#endif + +//-------------------------------------------------------------------------------------- +// CDXUTPerfEventGenerator is a helper class that makes it easy to attach begin and end +// events to a block of code. Simply define a CDXUTPerfEventGenerator variable anywhere +// in a block of code, and the class's constructor will call DXUT_BeginPerfEvent when +// the block of code begins, and the class's destructor will call DXUT_EndPerfEvent when +// the block ends. +//-------------------------------------------------------------------------------------- +class CDXUTPerfEventGenerator +{ +public: +CDXUTPerfEventGenerator( D3DCOLOR color, LPCWSTR pstrMessage ) +{ + DXUT_BeginPerfEvent( color, pstrMessage ); +} +~CDXUTPerfEventGenerator( void ) +{ + DXUT_EndPerfEvent(); +} +}; + + +//-------------------------------------------------------------------------------------- +// Multimon handling to support OSes with or without multimon API support. +// Purposely avoiding the use of multimon.h so DXUT.lib doesn't require +// COMPILE_MULTIMON_STUBS and cause complication with MFC or other users of multimon.h +//-------------------------------------------------------------------------------------- +#ifndef MONITOR_DEFAULTTOPRIMARY +#define MONITORINFOF_PRIMARY 0x00000001 +#define MONITOR_DEFAULTTONULL 0x00000000 +#define MONITOR_DEFAULTTOPRIMARY 0x00000001 +#define MONITOR_DEFAULTTONEAREST 0x00000002 +typedef struct tagMONITORINFO +{ + DWORD cbSize; + RECT rcMonitor; + RECT rcWork; + DWORD dwFlags; +} MONITORINFO, *LPMONITORINFO; +typedef struct tagMONITORINFOEXW : public tagMONITORINFO +{ + WCHAR szDevice[CCHDEVICENAME]; +} MONITORINFOEXW, *LPMONITORINFOEXW; +typedef MONITORINFOEXW MONITORINFOEX; +typedef LPMONITORINFOEXW LPMONITORINFOEX; +#endif + +HMONITOR WINAPI DXUTMonitorFromWindow( HWND hWnd, DWORD dwFlags ); +HMONITOR WINAPI DXUTMonitorFromRect( LPCRECT lprcScreenCoords, DWORD dwFlags ); +BOOL WINAPI DXUTGetMonitorInfo( HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo ); +void WINAPI DXUTGetDesktopResolution( UINT AdapterOrdinal, UINT* pWidth, UINT* pHeight ); + + +//-------------------------------------------------------------------------------------- +// Implementation of CGrowableArray +//-------------------------------------------------------------------------------------- + +// This version doesn't call ctor or dtor. +template HRESULT CGrowableArray ::SetSizeInternal( int nNewMaxSize ) +{ + if( nNewMaxSize < 0 || ( nNewMaxSize > INT_MAX / sizeof( TYPE ) ) ) + { + assert( false ); + return E_INVALIDARG; + } + + if( nNewMaxSize == 0 ) + { + // Shrink to 0 size & cleanup + if( m_pData ) + { + free( m_pData ); + m_pData = NULL; + } + + m_nMaxSize = 0; + m_nSize = 0; + } + else if( m_pData == NULL || nNewMaxSize > m_nMaxSize ) + { + // Grow array + int nGrowBy = ( m_nMaxSize == 0 ) ? 16 : m_nMaxSize; + + // Limit nGrowBy to keep m_nMaxSize less than INT_MAX + if( ( UINT )m_nMaxSize + ( UINT )nGrowBy > ( UINT )INT_MAX ) + nGrowBy = INT_MAX - m_nMaxSize; + + nNewMaxSize = __max( nNewMaxSize, m_nMaxSize + nGrowBy ); + + // Verify that (nNewMaxSize * sizeof(TYPE)) is not greater than UINT_MAX or the realloc will overrun + if( sizeof( TYPE ) > UINT_MAX / ( UINT )nNewMaxSize ) + return E_INVALIDARG; + + TYPE* pDataNew = ( TYPE* )realloc( m_pData, nNewMaxSize * sizeof( TYPE ) ); + if( pDataNew == NULL ) + return E_OUTOFMEMORY; + + m_pData = pDataNew; + m_nMaxSize = nNewMaxSize; + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +template HRESULT CGrowableArray ::SetSize( int nNewMaxSize ) +{ + int nOldSize = m_nSize; + + if( nOldSize > nNewMaxSize ) + { + assert( m_pData ); + if( m_pData ) + { + // Removing elements. Call dtor. + + for( int i = nNewMaxSize; i < nOldSize; ++i ) + m_pData[i].~TYPE(); + } + } + + // Adjust buffer. Note that there's no need to check for error + // since if it happens, nOldSize == nNewMaxSize will be true.) + HRESULT hr = SetSizeInternal( nNewMaxSize ); + + if( nOldSize < nNewMaxSize ) + { + assert( m_pData ); + if( m_pData ) + { + // Adding elements. Call ctor. + + for( int i = nOldSize; i < nNewMaxSize; ++i ) + ::new ( &m_pData[i] ) TYPE; + } + } + + return hr; +} + + +//-------------------------------------------------------------------------------------- +template HRESULT CGrowableArray ::Add( const TYPE& value ) +{ + HRESULT hr; + if( FAILED( hr = SetSizeInternal( m_nSize + 1 ) ) ) + return hr; + + // Construct the new element + ::new ( &m_pData[m_nSize] ) TYPE; + + // Assign + m_pData[m_nSize] = value; + ++m_nSize; + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +template HRESULT CGrowableArray ::Insert( int nIndex, const TYPE& value ) +{ + HRESULT hr; + + // Validate index + if( nIndex < 0 || + nIndex > m_nSize ) + { + assert( false ); + return E_INVALIDARG; + } + + // Prepare the buffer + if( FAILED( hr = SetSizeInternal( m_nSize + 1 ) ) ) + return hr; + + // Shift the array + MoveMemory( &m_pData[nIndex + 1], &m_pData[nIndex], sizeof( TYPE ) * ( m_nSize - nIndex ) ); + + // Construct the new element + ::new ( &m_pData[nIndex] ) TYPE; + + // Set the value and increase the size + m_pData[nIndex] = value; + ++m_nSize; + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +template HRESULT CGrowableArray ::SetAt( int nIndex, const TYPE& value ) +{ + // Validate arguments + if( nIndex < 0 || + nIndex >= m_nSize ) + { + assert( false ); + return E_INVALIDARG; + } + + m_pData[nIndex] = value; + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Searches for the specified value and returns the index of the first occurrence +// within the section of the data array that extends from iStart and contains the +// specified number of elements. Returns -1 if value is not found within the given +// section. +//-------------------------------------------------------------------------------------- +template int CGrowableArray ::IndexOf( const TYPE& value, int iStart, int nNumElements ) +{ + // Validate arguments + if( iStart < 0 || + iStart >= m_nSize || + nNumElements < 0 || + iStart + nNumElements > m_nSize ) + { + assert( false ); + return -1; + } + + // Search + for( int i = iStart; i < ( iStart + nNumElements ); i++ ) + { + if( value == m_pData[i] ) + return i; + } + + // Not found + return -1; +} + + +//-------------------------------------------------------------------------------------- +// Searches for the specified value and returns the index of the last occurrence +// within the section of the data array that contains the specified number of elements +// and ends at iEnd. Returns -1 if value is not found within the given section. +//-------------------------------------------------------------------------------------- +template int CGrowableArray ::LastIndexOf( const TYPE& value, int iEnd, int nNumElements ) +{ + // Validate arguments + if( iEnd < 0 || + iEnd >= m_nSize || + nNumElements < 0 || + iEnd - nNumElements < 0 ) + { + assert( false ); + return -1; + } + + // Search + for( int i = iEnd; i > ( iEnd - nNumElements ); i-- ) + { + if( value == m_pData[i] ) + return i; + } + + // Not found + return -1; +} + + + +//-------------------------------------------------------------------------------------- +template HRESULT CGrowableArray ::Remove( int nIndex ) +{ + if( nIndex < 0 || + nIndex >= m_nSize ) + { + assert( false ); + return E_INVALIDARG; + } + + // Destruct the element to be removed + m_pData[nIndex].~TYPE(); + + // Compact the array and decrease the size + MoveMemory( &m_pData[nIndex], &m_pData[nIndex + 1], sizeof( TYPE ) * ( m_nSize - ( nIndex + 1 ) ) ); + --m_nSize; + + return S_OK; +} + +//-------------------------------------------------------------------------------------- +// Creates a REF or NULLREF D3D9 device and returns that device. The caller should call +// Release() when done with the device. +//-------------------------------------------------------------------------------------- +IDirect3DDevice9* WINAPI DXUTCreateRefDevice9( HWND hWnd, bool bNullRef = true ); + +//-------------------------------------------------------------------------------------- +// Creates a REF or NULLREF D3D10 device and returns the device. The caller should call +// Release() when done with the device. +//-------------------------------------------------------------------------------------- +//test d3d10 version ID3D10Device* WINAPI DXUTCreateRefDevice10( bool bNullRef = true ); + +//-------------------------------------------------------------------------------------- +// Helper function to launch the Media Center UI after the program terminates +//-------------------------------------------------------------------------------------- +bool DXUTReLaunchMediaCenter(); + +//-------------------------------------------------------------------------------------- +// Helper functions to create SRGB formats from typeless formats and vice versa +//-------------------------------------------------------------------------------------- +DXGI_FORMAT MAKE_SRGB( DXGI_FORMAT format ); +DXGI_FORMAT MAKE_TYPELESS( DXGI_FORMAT format ); + +#endif diff --git a/Demos/DX11ClothDemo/DXUT/Core/dpiaware.manifest b/Demos/DX11ClothDemo/DXUT/Core/dpiaware.manifest new file mode 100644 index 0000000..3d5eccc --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Core/dpiaware.manifest @@ -0,0 +1,7 @@ + + + + true + + + \ No newline at end of file diff --git a/Demos/DX11ClothDemo/DXUT/Optional/DXUTLockFreePipe.h b/Demos/DX11ClothDemo/DXUT/Optional/DXUTLockFreePipe.h new file mode 100644 index 0000000..ed10747 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/DXUTLockFreePipe.h @@ -0,0 +1,227 @@ +//-------------------------------------------------------------------------------------- +// DXUTLockFreePipe.h +// +// See the "Lockless Programming Considerations for Xbox 360 and Microsoft Windows" +// article in the DirectX SDK for more details. +// +// http://msdn2.microsoft.com/en-us/library/bb310595.aspx +// +// XNA Developer Connection +// Copyright (C) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once + +#include + +#ifdef _XBOX_VER + // Prevent the CPU from rearranging loads + // and stores, sufficiently for read-acquire + // and write-release. + #define DXUTImportBarrier __lwsync + #define DXUTExportBarrier __lwsync +#else + #pragma pack(push) + #pragma pack(8) + #include + #pragma pack (pop) + + extern "C" + void _ReadWriteBarrier(); + #pragma intrinsic(_ReadWriteBarrier) + + // Prevent the compiler from rearranging loads + // and stores, sufficiently for read-acquire + // and write-release. This is sufficient on + // x86 and x64. + #define DXUTImportBarrier _ReadWriteBarrier + #define DXUTExportBarrier _ReadWriteBarrier +#endif + +// +// Pipe class designed for use by at most two threads: one reader, one writer. +// Access by more than two threads isn't guaranteed to be safe. +// +// In order to provide efficient access the size of the buffer is passed +// as a template parameter and restricted to powers of two less than 31. +// + +template class DXUTLockFreePipe +{ +public: + DXUTLockFreePipe() : m_readOffset( 0 ), + m_writeOffset( 0 ) + { + } + + DWORD GetBufferSize() const + { + return c_cbBufferSize; + } + + __forceinline unsigned long BytesAvailable() const + { + return m_writeOffset - m_readOffset; + } + + bool __forceinline Read( void* pvDest, unsigned long cbDest ) + { + // Store the read and write offsets into local variables--this is + // essentially a snapshot of their values so that they stay constant + // for the duration of the function (and so we don't end up with cache + // misses due to false sharing). + DWORD readOffset = m_readOffset; + DWORD writeOffset = m_writeOffset; + + // Compare the two offsets to see if we have anything to read. + // Note that we don't do anything to synchronize the offsets here. + // Really there's not much we *can* do unless we're willing to completely + // synchronize access to the entire object. We have to assume that as we + // read, someone else may be writing, and the write offset we have now + // may be out of date by the time we read it. Fortunately that's not a + // very big deal. We might miss reading some data that was just written. + // But the assumption is that we'll be back before long to grab more data + // anyway. + // + // Note that this comparison works because we're careful to constrain + // the total buffer size to be a power of 2, which means it will divide + // evenly into ULONG_MAX+1. That, and the fact that the offsets are + // unsigned, means that the calculation returns correct results even + // when the values wrap around. + DWORD cbAvailable = writeOffset - readOffset; + if( cbDest > cbAvailable ) + { + return false; + } + + // The data has been made available, but we need to make sure + // that our view on the data is up to date -- at least as up to + // date as the control values we just read. We need to prevent + // the compiler or CPU from moving any of the data reads before + // the control value reads. This import barrier serves this + // purpose, on Xbox 360 and on Windows. + + // Reading a control value and then having a barrier is known + // as a "read-acquire." + DXUTImportBarrier(); + + unsigned char* pbDest = ( unsigned char* )pvDest; + + unsigned long actualReadOffset = readOffset & c_sizeMask; + unsigned long bytesLeft = cbDest; + + // + // Copy from the tail, then the head. Note that there's no explicit + // check to see if the write offset comes between the read offset + // and the end of the buffer--that particular condition is implicitly + // checked by the comparison with AvailableToRead(), above. If copying + // cbDest bytes off the tail would cause us to cross the write offset, + // then the previous comparison would have failed since that would imply + // that there were less than cbDest bytes available to read. + // + unsigned long cbTailBytes = min( bytesLeft, c_cbBufferSize - actualReadOffset ); + memcpy( pbDest, m_pbBuffer + actualReadOffset, cbTailBytes ); + bytesLeft -= cbTailBytes; + + if( bytesLeft ) + { + memcpy( pbDest + cbTailBytes, m_pbBuffer, bytesLeft ); + } + + // When we update the read offset we are, effectively, 'freeing' buffer + // memory so that the writing thread can use it. We need to make sure that + // we don't free the memory before we have finished reading it. That is, + // we need to make sure that the write to m_readOffset can't get reordered + // above the reads of the buffer data. The only way to guarantee this is to + // have an export barrier to prevent both compiler and CPU rearrangements. + DXUTExportBarrier(); + + // Advance the read offset. From the CPUs point of view this is several + // operations--read, modify, store--and we'd normally want to make sure that + // all of the operations happened atomically. But in the case of a single + // reader, only one thread updates this value and so the only operation that + // must be atomic is the store. That's lucky, because 32-bit aligned stores are + // atomic on all modern processors. + // + readOffset += cbDest; + m_readOffset = readOffset; + + return true; + } + + bool __forceinline Write( const void* pvSrc, unsigned long cbSrc ) + { + // Reading the read offset here has the same caveats as reading + // the write offset had in the Read() function above. + DWORD readOffset = m_readOffset; + DWORD writeOffset = m_writeOffset; + + // Compute the available write size. This comparison relies on + // the fact that the buffer size is always a power of 2, and the + // offsets are unsigned integers, so that when the write pointer + // wraps around the subtraction still yields a value (assuming + // we haven't messed up somewhere else) between 0 and c_cbBufferSize - 1. + DWORD cbAvailable = c_cbBufferSize - ( writeOffset - readOffset ); + if( cbSrc > cbAvailable ) + { + return false; + } + + // It is theoretically possible for writes of the data to be reordered + // above the reads to see if the data is available. Improbable perhaps, + // but possible. This barrier guarantees that the reordering will not + // happen. + DXUTImportBarrier(); + + // Write the data + const unsigned char* pbSrc = ( const unsigned char* )pvSrc; + unsigned long actualWriteOffset = writeOffset & c_sizeMask; + unsigned long bytesLeft = cbSrc; + + // See the explanation in the Read() function as to why we don't + // explicitly check against the read offset here. + unsigned long cbTailBytes = min( bytesLeft, c_cbBufferSize - actualWriteOffset ); + memcpy( m_pbBuffer + actualWriteOffset, pbSrc, cbTailBytes ); + bytesLeft -= cbTailBytes; + + if( bytesLeft ) + { + memcpy( m_pbBuffer, pbSrc + cbTailBytes, bytesLeft ); + } + + // Now it's time to update the write offset, but since the updated position + // of the write offset will imply that there's data to be read, we need to + // make sure that the data all actually gets written before the update to + // the write offset. The writes could be reordered by the compiler (on any + // platform) or by the CPU (on Xbox 360). We need a barrier which prevents + // the writes from being reordered past each other. + // + // Having a barrier and then writing a control value is called "write-release." + DXUTExportBarrier(); + + // See comments in Read() as to why this operation isn't interlocked. + writeOffset += cbSrc; + m_writeOffset = writeOffset; + + return true; + } + +private: + // Values derived from the buffer size template parameter + // + const static BYTE c_cbBufferSizeLog2 = min( cbBufferSizeLog2, 31 ); + const static DWORD c_cbBufferSize = ( 1 << c_cbBufferSizeLog2 ); + const static DWORD c_sizeMask = c_cbBufferSize - 1; + + // Leave these private and undefined to prevent their use + DXUTLockFreePipe( const DXUTLockFreePipe& ); + DXUTLockFreePipe& operator =( const DXUTLockFreePipe& ); + + // Member data + // + BYTE m_pbBuffer[c_cbBufferSize]; + // Note that these offsets are not clamped to the buffer size. + // Instead the calculations rely on wrapping at ULONG_MAX+1. + // See the comments in Read() for details. + volatile DWORD __declspec( align( 4 ) ) m_readOffset; + volatile DWORD __declspec( align( 4 ) ) m_writeOffset; +}; \ No newline at end of file diff --git a/Demos/DX11ClothDemo/DXUT/Optional/DXUTShapes.cpp b/Demos/DX11ClothDemo/DXUT/Optional/DXUTShapes.cpp new file mode 100644 index 0000000..9084926 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/DXUTShapes.cpp @@ -0,0 +1,5663 @@ +//-------------------------------------------------------------------------------------- +// File: DXUTShapes.cpp +// +// Shape creation functions for DXUT +// +// Copyright (c) Microsoft Corporation. All rights reserved +//-------------------------------------------------------------------------------------- +#include "DXUT.h" +#include "DXUTShapes.h" + + +//-------------------------------------------------------------------------------------- +// VERTEX is the vertex layout for all DXUT created shapes +//-------------------------------------------------------------------------------------- +struct VERTEX +{ + D3DXVECTOR3 pos; + D3DXVECTOR3 norm; +}; + +static const D3D10_INPUT_ELEMENT_DESC s_ShapeLayout[] = +{ + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 }, +}; + + +//-------------------------------------------------------------------------------------- +static inline void sincosf( float angle, float* psin, float* pcos ) +{ + *psin = sinf( angle ); + *pcos = cosf( angle ); +} + + +//-------------------------------------------------------------------------------------- +// Create D3DX10Mesh from the input vertex and index data +//-------------------------------------------------------------------------------------- +HRESULT CreateShapeMesh( ID3D10Device* pDev10, ID3DX10Mesh** ppMesh, VERTEX* pVertices, UINT NumVertices, + WORD* pIndices, UINT NumIndices ) +{ + HRESULT hr = S_OK; + + // Create the mesh + hr = D3DX10CreateMesh( pDev10, + s_ShapeLayout, + sizeof( s_ShapeLayout ) / sizeof( s_ShapeLayout[0] ), + s_ShapeLayout[0].SemanticName, + NumVertices, + NumIndices / 3, + 0, + ppMesh ); + if( FAILED( hr ) ) + return hr; + + // Set the Vertex Data + ( *ppMesh )->SetVertexData( 0, pVertices ); + + // Set the Index Data + ( *ppMesh )->SetIndexData( pIndices, NumIndices ); + + // Set attributes + DWORD dwNumAttr = 1; + D3DX10_ATTRIBUTE_RANGE* pAttr = new D3DX10_ATTRIBUTE_RANGE[dwNumAttr]; + if( !pAttr ) + return E_OUTOFMEMORY; + + pAttr[0].AttribId = 0; + pAttr[0].FaceStart = 0; + pAttr[0].FaceCount = NumIndices / 3; + pAttr[0].VertexStart = 0; + pAttr[0].VertexCount = NumVertices; + ( *ppMesh )->SetAttributeTable( pAttr, dwNumAttr ); + SAFE_DELETE_ARRAY( pAttr ); + + // Create the internal mesh VBs and IBs + ( *ppMesh )->CommitToDevice(); + + return hr; +} + + +//---------------------------------------------------------------------------- +// Box +//---------------------------------------------------------------------------- +static float cubeN[6][3] = +{ + {-1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f} +}; + +static WORD cubeF[6][4] = +{ + { 0, 1, 5, 4 }, { 4, 5, 6, 7 }, { 7, 6, 2, 3 }, + { 1, 0, 3, 2 }, { 1, 2, 6, 5 }, { 0, 4, 7, 3 } +}; + +static float cubeV[8][3] = +{ + // Lower tier (lower in y) + {-.5f, -.5f, -.5f}, + {-.5f, -.5f, .5f}, + { .5f, -.5f, .5f}, + { .5f, -.5f, -.5f}, + + // Upper tier + {-.5f, .5f, -.5f}, + {-.5f, .5f, .5f}, + { .5f, .5f, .5f}, + { .5f, .5f, -.5f}, +}; + +static float cubeT[4][2] = +{ + // Lower tier (lower in y) + {0.0f, 0.0f}, + {0.0f, 1.0f}, + {1.0f, 1.0f}, + {1.0f, 0.0f} +}; + +static WORD cubeFT[6][4] = +{ + { 3, 0, 1, 2 }, { 0, 1, 2, 3 }, { 1, 2, 3, 0 }, + { 0, 1, 2, 3 }, { 3, 0, 1, 2 }, { 0, 1, 2, 3 } +}; + + +//-------------------------------------------------------------------------------------- +// MakeBox helper +//-------------------------------------------------------------------------------------- +static void MakeBox( +VERTEX* pVertices, +DWORD* pPointRep, +WORD* pwIndices, +float fWidth, +float fHeight, +float fDepth ) +{ + // Fill in the data + VERTEX* pVertex = pVertices; + WORD* pwFace = pwIndices; + UINT iVertex = 0; + + // i iterates over the faces, 2 triangles per face + for( int i = 0; i < 6; i++ ) + { + for( int j = 0; j < 4; j++ ) + { + pVertex->pos.x = cubeV[cubeF[i][j]][0] * fWidth; + pVertex->pos.y = cubeV[cubeF[i][j]][1] * fHeight; + pVertex->pos.z = cubeV[cubeF[i][j]][2] * fDepth; + + pVertex->norm.x = cubeN[i][0]; + pVertex->norm.y = cubeN[i][1]; + pVertex->norm.z = cubeN[i][2]; + + if( pPointRep != NULL ) + { + *pPointRep = cubeF[i][j]; + pPointRep++; + } + + pVertex++; + } + + pwFace[0] = ( WORD )( iVertex ); + pwFace[1] = ( WORD )( iVertex + 1 ); + pwFace[2] = ( WORD )( iVertex + 2 ); + pwFace += 3; + + pwFace[0] = ( WORD )( iVertex + 2 ); + pwFace[1] = ( WORD )( iVertex + 3 ); + pwFace[2] = ( WORD )( iVertex ); + pwFace += 3; + + iVertex += 4; + } +} + + +//-------------------------------------------------------------------------------------- +// DXUTCreateBox - create a box mesh +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTCreateBox( ID3D10Device* pDevice, float fWidth, float fHeight, float fDepth, ID3DX10Mesh** ppMesh ) +{ + HRESULT hr = S_OK; + + WORD* pwIndices = NULL; + VERTEX* pVertices = NULL; + + // Set up the defaults + if( D3DX_DEFAULT_FLOAT == fWidth ) + fWidth = 1.0f; + if( D3DX_DEFAULT_FLOAT == fHeight ) + fHeight = 1.0f; + if( D3DX_DEFAULT_FLOAT == fDepth ) + fDepth = 1.0f; + + + // Validate parameters + if( !pDevice ) + return D3DERR_INVALIDCALL; + if( !ppMesh ) + return D3DERR_INVALIDCALL; + if( fWidth < 0.0f ) + return D3DERR_INVALIDCALL; + if( fHeight < 0.0f ) + return D3DERR_INVALIDCALL; + if( fDepth < 0.0f ) + return D3DERR_INVALIDCALL; + + // Create the mesh + UINT cFaces = 12; + UINT cVertices = 24; + + // Create enough memory for the vertices and indices + pVertices = new VERTEX[ cVertices ]; + if( !pVertices ) + return E_OUTOFMEMORY; + pwIndices = new WORD[ cFaces * 3 ]; + if( !pwIndices ) + return E_OUTOFMEMORY; + + // Create a box + MakeBox( pVertices, NULL, pwIndices, fWidth, fHeight, fDepth ); + + // Create a mesh + hr = CreateShapeMesh( pDevice, ppMesh, pVertices, cVertices, pwIndices, cFaces * 3 ); + + // Free up the memory + SAFE_DELETE_ARRAY( pVertices ); + SAFE_DELETE_ARRAY( pwIndices ); + + return hr; + +} + +#define CACHE_SIZE 240 + +//---------------------------------------------------------------------------- +// MakeCylinder helper +//---------------------------------------------------------------------------- +static void MakeCylinder( +VERTEX* pVertices, +DWORD* pPointReps, +WORD* pwIndices, +float fRadius1, +float fRadius2, +float fLength, +UINT uSlices, +UINT uStacks ) +{ + UINT i, j; + + // Sin/Cos caches + float sinI[CACHE_SIZE], cosI[CACHE_SIZE]; + + for( i = 0; i < uSlices; i++ ) + sincosf( 2.0f * D3DX_PI * i / uSlices, sinI + i, cosI + i ); + + + // Compute side normal angle + float fDeltaRadius = fRadius2 - fRadius1; + float fSideLength = sqrtf( fDeltaRadius * fDeltaRadius + fLength * fLength ); + + float fNormalXY = ( fSideLength > 0.00001f ) ? ( fLength / fSideLength ) : 1.0f; + float fNormalZ = ( fSideLength > 0.00001f ) ? ( -fDeltaRadius / fSideLength ) : 0.0f; + + + + // Generate vertices + VERTEX* pVertex = pVertices; + float fZ, fRadius; + DWORD iVertex; + + // Base cap (uSlices + 1) + fZ = fLength * -0.5f; + fRadius = fRadius1; + iVertex = 0; + + pVertex->pos = D3DXVECTOR3( 0.0f, 0.0f, fZ ); + pVertex->norm = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); + pVertex++; + if( pPointReps != NULL ) + pPointReps[iVertex] = iVertex; + iVertex++; + + for( i = 0; i < uSlices; i++ ) + { + pVertex->pos = D3DXVECTOR3( fRadius * sinI[i], fRadius * cosI[i], fZ ); + pVertex->norm = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); + pVertex++; + + // link into stack vertices, which follow + if( pPointReps != NULL ) + pPointReps[iVertex] = iVertex + uSlices; + iVertex++; + } + + // Stacks ((uStacks + 1)*uSlices) + for( j = 0; j <= uStacks; j++ ) + { + float f = ( float )j / ( float )uStacks; + + fZ = fLength * ( f - 0.5f ); + fRadius = fRadius1 + f * fDeltaRadius; + + for( i = 0; i < uSlices; i++ ) + { + pVertex->pos = D3DXVECTOR3( fRadius * sinI[i], fRadius * cosI[i], fZ ); + pVertex->norm = D3DXVECTOR3( fNormalXY * sinI[i], fNormalXY * cosI[i], fNormalZ ); + pVertex++; + if( pPointReps != NULL ) + pPointReps[iVertex] = iVertex; + iVertex++; + } + } + + // Top cap (uSlices + 1) + fZ = fLength * 0.5f; + fRadius = fRadius2; + + for( i = 0; i < uSlices; i++ ) + { + pVertex->pos = D3DXVECTOR3( fRadius * sinI[i], fRadius * cosI[i], fZ ); + pVertex->norm = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); + pVertex++; + + // link into stack vertices, which precede + if( pPointReps != NULL ) + pPointReps[iVertex] = iVertex - uSlices; + iVertex++; + } + + pVertex->pos = D3DXVECTOR3( 0.0f, 0.0f, fZ ); + pVertex->norm = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); + pVertex++; + if( pPointReps != NULL ) + pPointReps[iVertex] = iVertex; + iVertex++; + + + + // Generate indices + WORD* pwFace = pwIndices; + UINT uRowA, uRowB; + + // Z+ pole (uSlices) + uRowA = 0; + uRowB = 1; + + for( i = 0; i < uSlices - 1; i++ ) + { + pwFace[0] = ( WORD )( uRowA ); + pwFace[1] = ( WORD )( uRowB + i ); + pwFace[2] = ( WORD )( uRowB + i + 1 ); + pwFace += 3; + } + + pwFace[0] = ( WORD )( uRowA ); + pwFace[1] = ( WORD )( uRowB + i ); + pwFace[2] = ( WORD )( uRowB ); + pwFace += 3; + + // Interior stacks (uStacks * uSlices * 2) + for( j = 0; j < uStacks; j++ ) + { + uRowA = 1 + ( j + 1 ) * uSlices; + uRowB = uRowA + uSlices; + + for( i = 0; i < uSlices - 1; i++ ) + { + pwFace[0] = ( WORD )( uRowA + i ); + pwFace[1] = ( WORD )( uRowB + i ); + pwFace[2] = ( WORD )( uRowA + i + 1 ); + pwFace += 3; + + pwFace[0] = ( WORD )( uRowA + i + 1 ); + pwFace[1] = ( WORD )( uRowB + i ); + pwFace[2] = ( WORD )( uRowB + i + 1 ); + pwFace += 3; + } + + pwFace[0] = ( WORD )( uRowA + i ); + pwFace[1] = ( WORD )( uRowB + i ); + pwFace[2] = ( WORD )( uRowA ); + pwFace += 3; + + pwFace[0] = ( WORD )( uRowA ); + pwFace[1] = ( WORD )( uRowB + i ); + pwFace[2] = ( WORD )( uRowB ); + pwFace += 3; + } + + // Z- pole (uSlices) + uRowA = 1 + ( uStacks + 2 ) * uSlices; + uRowB = uRowA + uSlices; + + for( i = 0; i < uSlices - 1; i++ ) + { + pwFace[0] = ( WORD )( uRowA + i ); + pwFace[1] = ( WORD )( uRowB ); + pwFace[2] = ( WORD )( uRowA + i + 1 ); + pwFace += 3; + } + + pwFace[0] = ( WORD )( uRowA + i ); + pwFace[1] = ( WORD )( uRowB ); + pwFace[2] = ( WORD )( uRowA ); + pwFace += 3; +} + + +//---------------------------------------------------------------------------- +// DXUTCreateCylinder - create a cylinder mesh +//---------------------------------------------------------------------------- +HRESULT WINAPI DXUTCreateCylinder( ID3D10Device* pDevice, float fRadius1, float fRadius2, float fLength, UINT uSlices, + UINT uStacks, ID3DX10Mesh** ppMesh ) +{ + HRESULT hr = S_OK; + + WORD* pwIndices = NULL; + VERTEX* pVertices = NULL; + + // Set up the defaults + if( D3DX_DEFAULT_FLOAT == fRadius1 ) + fRadius1 = 1.0f; + if( D3DX_DEFAULT_FLOAT == fRadius2 ) + fRadius2 = 1.0f; + if( D3DX_DEFAULT_FLOAT == fLength ) + fLength = 1.0f; + if( D3DX_DEFAULT == uSlices ) + uSlices = 8; + if( D3DX_DEFAULT == uStacks ) + uStacks = 8; + + + // Validate parameters + if( !pDevice ) + return D3DERR_INVALIDCALL; + if( !ppMesh ) + return D3DERR_INVALIDCALL; + if( fRadius1 < 0.0f ) + return D3DERR_INVALIDCALL; + if( fRadius2 < 0.0f ) + return D3DERR_INVALIDCALL; + if( fLength < 0.0f ) + return D3DERR_INVALIDCALL; + if( uSlices < 2 ) + return D3DERR_INVALIDCALL; + if( uStacks < 1 ) + return D3DERR_INVALIDCALL; + if( uSlices >= CACHE_SIZE ) + uSlices = CACHE_SIZE - 1; + + // Create the mesh + UINT cFaces = ( uStacks + 1 ) * uSlices * 2; + UINT cVertices = 2 + ( uStacks + 3 ) * uSlices; + + // Create enough memory for the vertices and indices + pVertices = new VERTEX[ cVertices ]; + if( !pVertices ) + return E_OUTOFMEMORY; + pwIndices = new WORD[ cFaces * 3 ]; + if( !pwIndices ) + return E_OUTOFMEMORY; + + // Create a cylinder + MakeCylinder( pVertices, NULL, pwIndices, fRadius1, fRadius2, + fLength, uSlices, uStacks ); + + // Create a mesh + hr = CreateShapeMesh( pDevice, ppMesh, pVertices, cVertices, pwIndices, cFaces * 3 ); + + // Free up the memory + SAFE_DELETE_ARRAY( pVertices ); + SAFE_DELETE_ARRAY( pwIndices ); + + return hr; +} + + +//-------------------------------------------------------------------------------------- +// MakePolygon helper +//-------------------------------------------------------------------------------------- +static void MakePolygon( VERTEX* pVertices, + WORD* pwIndices, + float fLength, + UINT uSides ) +{ + // Calculate the radius + float radius = fLength * 0.5f / sinf( D3DX_PI / ( float )uSides ); + float angle = ( float )( 2.0f * D3DX_PI / ( float )uSides ); + + // Fill in vertices + VERTEX* pVertex = pVertices; + + pVertex->pos = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); + pVertex->norm = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); + pVertex++; + + for( UINT j = 0; j < uSides; j++ ) + { + float s, c; + sincosf( angle * j, &s, &c ); + + pVertex->pos = D3DXVECTOR3( c * radius, s * radius, 0.0f ); + pVertex->norm = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); + pVertex++; + } + + // Fill in indices + WORD* pwFace = pwIndices; + + UINT iFace; + for( iFace = 0; iFace < uSides - 1; iFace++ ) + { + pwFace[0] = 0; + pwFace[1] = ( WORD )iFace + 1; + pwFace[2] = ( WORD )iFace + 2; + + pwFace += 3; + } + + // handle the wrapping of the last case + pwFace[0] = 0; + pwFace[1] = ( WORD )iFace + 1; + pwFace[2] = 1; +} + + +//---------------------------------------------------------------------------- +// DXUTCreatePolygon - create a polygon mesh +//---------------------------------------------------------------------------- +HRESULT WINAPI DXUTCreatePolygon( ID3D10Device* pDevice, float fLength, UINT uSides, ID3DX10Mesh** ppMesh ) +{ + HRESULT hr = S_OK; + WORD* pwIndices = NULL; + VERTEX* pVertices = NULL; + + // Set up the defaults + if( D3DX_DEFAULT == uSides ) + uSides = 3; + if( D3DX_DEFAULT_FLOAT == fLength ) + fLength = 1.0f; + + + // Validate parameters + if( !pDevice ) + return D3DERR_INVALIDCALL; + if( !ppMesh ) + return D3DERR_INVALIDCALL; + if( fLength < 0.0f ) + return D3DERR_INVALIDCALL; + if( uSides < 3 ) + return D3DERR_INVALIDCALL; + + // Create the mesh + UINT cFaces = uSides; + UINT cVertices = uSides + 1; + + // Create enough memory for the vertices and indices + pVertices = new VERTEX[ cVertices ]; + if( !pVertices ) + return E_OUTOFMEMORY; + pwIndices = new WORD[ cFaces * 3 ]; + if( !pwIndices ) + return E_OUTOFMEMORY; + + // Create a polygon + MakePolygon( pVertices, pwIndices, fLength, uSides ); + + // Create a mesh + hr = CreateShapeMesh( pDevice, ppMesh, pVertices, cVertices, pwIndices, cFaces * 3 ); + + // Free up the memory + SAFE_DELETE_ARRAY( pVertices ); + SAFE_DELETE_ARRAY( pwIndices ); + + return hr; +} + + +//--------------------------------------------------------------------- +// MakeSphere helper +//--------------------------------------------------------------------- +static void MakeSphere( +VERTEX* pVertices, +WORD* pwIndices, +float fRadius, +UINT uSlices, +UINT uStacks ) +{ + UINT i, j; + + + // Sin/Cos caches + float sinI[CACHE_SIZE], cosI[CACHE_SIZE]; + float sinJ[CACHE_SIZE], cosJ[CACHE_SIZE]; + + for( i = 0; i < uSlices; i++ ) + sincosf( 2.0f * D3DX_PI * i / uSlices, sinI + i, cosI + i ); + + for( j = 0; j < uStacks; j++ ) + sincosf( D3DX_PI * j / uStacks, sinJ + j, cosJ + j ); + + + + // Generate vertices + VERTEX* pVertex = pVertices; + + // +Z pole + pVertex->pos = D3DXVECTOR3( 0.0f, 0.0f, fRadius ); + pVertex->norm = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); + pVertex++; + + // Stacks + for( j = 1; j < uStacks; j++ ) + { + for( i = 0; i < uSlices; i++ ) + { + D3DXVECTOR3 norm( sinI[i]* sinJ[j], cosI[i]* sinJ[j], cosJ[j] ); + + pVertex->pos = norm * fRadius; + pVertex->norm = norm; + + pVertex++; + } + } + + // Z- pole + pVertex->pos = D3DXVECTOR3( 0.0f, 0.0f, -fRadius ); + pVertex->norm = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); + pVertex++; + + + + // Generate indices + WORD* pwFace = pwIndices; + UINT uRowA, uRowB; + + // Z+ pole + uRowA = 0; + uRowB = 1; + + for( i = 0; i < uSlices - 1; i++ ) + { + pwFace[0] = ( WORD )( uRowA ); + pwFace[1] = ( WORD )( uRowB + i + 1 ); + pwFace[2] = ( WORD )( uRowB + i ); + pwFace += 3; + } + + pwFace[0] = ( WORD )( uRowA ); + pwFace[1] = ( WORD )( uRowB ); + pwFace[2] = ( WORD )( uRowB + i ); + pwFace += 3; + + // Interior stacks + for( j = 1; j < uStacks - 1; j++ ) + { + uRowA = 1 + ( j - 1 ) * uSlices; + uRowB = uRowA + uSlices; + + for( i = 0; i < uSlices - 1; i++ ) + { + pwFace[0] = ( WORD )( uRowA + i ); + pwFace[1] = ( WORD )( uRowA + i + 1 ); + pwFace[2] = ( WORD )( uRowB + i ); + pwFace += 3; + + pwFace[0] = ( WORD )( uRowA + i + 1 ); + pwFace[1] = ( WORD )( uRowB + i + 1 ); + pwFace[2] = ( WORD )( uRowB + i ); + pwFace += 3; + } + + pwFace[0] = ( WORD )( uRowA + i ); + pwFace[1] = ( WORD )( uRowA ); + pwFace[2] = ( WORD )( uRowB + i ); + pwFace += 3; + + pwFace[0] = ( WORD )( uRowA ); + pwFace[1] = ( WORD )( uRowB ); + pwFace[2] = ( WORD )( uRowB + i ); + pwFace += 3; + } + + // Z- pole + uRowA = 1 + ( uStacks - 2 ) * uSlices; + uRowB = uRowA + uSlices; + + for( i = 0; i < uSlices - 1; i++ ) + { + pwFace[0] = ( WORD )( uRowA + i ); + pwFace[1] = ( WORD )( uRowA + i + 1 ); + pwFace[2] = ( WORD )( uRowB ); + pwFace += 3; + } + + pwFace[0] = ( WORD )( uRowA + i ); + pwFace[1] = ( WORD )( uRowA ); + pwFace[2] = ( WORD )( uRowB ); + pwFace += 3; +} + + +//---------------------------------------------------------------------------- +// DXUTCreateSphere - create a sphere mesh +//---------------------------------------------------------------------------- +HRESULT WINAPI DXUTCreateSphere( ID3D10Device* pDevice, float fRadius, UINT uSlices, UINT uStacks, + ID3DX10Mesh** ppMesh ) +{ + HRESULT hr = S_OK; + + WORD* pwIndices = NULL; + VERTEX* pVertices = NULL; + + // Set up the defaults + if( D3DX_DEFAULT_FLOAT == fRadius ) + fRadius = 1.0f; + if( D3DX_DEFAULT == uSlices ) + uSlices = 8; + if( D3DX_DEFAULT == uStacks ) + uStacks = 8; + + // Validate parameters + if( !pDevice ) + return D3DERR_INVALIDCALL; + if( !ppMesh ) + return D3DERR_INVALIDCALL; + if( fRadius < 0.0f ) + return D3DERR_INVALIDCALL; + if( uSlices < 2 ) + return D3DERR_INVALIDCALL; + if( uStacks < 2 ) + return D3DERR_INVALIDCALL; + + if( uSlices > CACHE_SIZE ) + uSlices = CACHE_SIZE; + if( uStacks > CACHE_SIZE ) + uStacks = CACHE_SIZE; + + // Create the mesh + UINT cFaces = 2 * ( uStacks - 1 ) * uSlices; + UINT cVertices = ( uStacks - 1 ) * uSlices + 2; + + // Create enough memory for the vertices and indices + pVertices = new VERTEX[ cVertices ]; + if( !pVertices ) + return E_OUTOFMEMORY; + pwIndices = new WORD[ cFaces * 3 ]; + if( !pwIndices ) + return E_OUTOFMEMORY; + + // Create a sphere + MakeSphere( pVertices, pwIndices, fRadius, uSlices, uStacks ); + + // Create a mesh + hr = CreateShapeMesh( pDevice, ppMesh, pVertices, cVertices, pwIndices, cFaces * 3 ); + + // Free up the memory + SAFE_DELETE_ARRAY( pVertices ); + SAFE_DELETE_ARRAY( pwIndices ); + + return hr; +} + + +//--------------------------------------------------------------------- +// MakeTorus helper +//--------------------------------------------------------------------- +static void MakeTorus( +VERTEX* pVertices, +WORD* pwIndices, +float fInnerRadius, +float fOuterRadius, +UINT uSides, +UINT uRings ) +{ + UINT i, j; + + // + // Compute the vertices + // + + VERTEX* pVertex = pVertices; + + for( i = 0; i < uRings; i++ ) + { + float theta = ( float )i * 2.0f * D3DX_PI / ( float )uRings; + float st, ct; + + sincosf( theta, &st, &ct ); + + for( j = 0; j < uSides; j++ ) + { + float phi = ( float )j * 2.0f * D3DX_PI / uSides; + float sp, cp; + + sincosf( phi, &sp, &cp ); + + pVertex->pos.x = ct * ( fOuterRadius + fInnerRadius * cp ); + pVertex->pos.y = -st * ( fOuterRadius + fInnerRadius * cp ); + pVertex->pos.z = sp * fInnerRadius; + + pVertex->norm.x = ct * cp; + pVertex->norm.y = -st * cp; + pVertex->norm.z = sp; + + pVertex++; + } + } + + // + // Compute the indices: + // There are uRings * uSides faces + // Each face has 2 triangles (6 indices) + // + + // Tube i has indices: + // Left Edge: i*(uSides+1) -- i*(uSides+1)+uSides + // Right Edge: (i+1)*(uSides+1) -- (i+1)*(uSides+1)+uSides + // + // Face j on tube i has the 4 indices: + // Left Edge: i*(uSides+1)+j -- i*(uSides+1)+j+1 + // Right Edge: (i+1)*(uSides+1)+j -- (i+1)*(uSides+1)+j+1 + // + WORD* pwFace = pwIndices; + + for( i = 0; i < uRings - 1; i++ ) + { + for( j = 0; j < uSides - 1; j++ ) + { + + // Tri 1 (Top-Left tri, CCW) + pwFace[0] = ( WORD )( i * uSides + j ); + pwFace[1] = ( WORD )( i * uSides + j + 1 ); + pwFace[2] = ( WORD )( ( i + 1 ) * uSides + j ); + pwFace += 3; + + // Tri 2 (Bottom-Right tri, CCW) + pwFace[0] = ( WORD )( ( i + 1 ) * uSides + j ); + pwFace[1] = ( WORD )( i * uSides + j + 1 ); + pwFace[2] = ( WORD )( ( i + 1 ) * uSides + j + 1 ); + pwFace += 3; + } + + // Tri 1 (Top-Left tri, CCW) + pwFace[0] = ( WORD )( i * uSides + j ); + pwFace[1] = ( WORD )( i * uSides ); + pwFace[2] = ( WORD )( ( i + 1 ) * uSides + j ); + pwFace += 3; + + // Tri 2 (Bottom-Right tri, CCW) + pwFace[0] = ( WORD )( ( i + 1 ) * uSides + j ); + pwFace[1] = ( WORD )( i * uSides + 0 ); + pwFace[2] = ( WORD )( ( i + 1 ) * uSides + 0 ); + pwFace += 3; + } + + + // join the two ends of the tube + for( j = 0; j < uSides - 1; j++ ) + { + // Tri 1 (Top-Left tri, CCW) + pwFace[0] = ( WORD )( i * uSides + j ); + pwFace[1] = ( WORD )( i * uSides + j + 1 ); + pwFace[2] = ( WORD )( j ); + pwFace += 3; + + // Tri 2 (Bottom-Right tri, CCW) + pwFace[0] = ( WORD )( j ); + pwFace[1] = ( WORD )( i * uSides + j + 1 ); + pwFace[2] = ( WORD )( j + 1 ); + pwFace += 3; + } + + // Tri 1 (Top-Left tri, CCW) + pwFace[0] = ( WORD )( i * uSides + j ); + pwFace[1] = ( WORD )( i * uSides ); + pwFace[2] = ( WORD )( j ); + pwFace += 3; + + // Tri 2 (Bottom-Right tri, CCW) + pwFace[0] = ( WORD )( j ); + pwFace[1] = ( WORD )( i * uSides ); + pwFace[2] = ( WORD )( 0 ); + pwFace += 3; +} + + +//---------------------------------------------------------------------------- +// DXUTCreateTorus - create a torus mesh +//---------------------------------------------------------------------------- +HRESULT WINAPI DXUTCreateTorus( ID3D10Device* pDevice, float fInnerRadius, float fOuterRadius, UINT uSides, + UINT uRings, ID3DX10Mesh** ppMesh ) +{ + HRESULT hr = S_OK; + + WORD* pwIndices = NULL; + VERTEX* pVertices = NULL; + + + // Set up the defaults + if( D3DX_DEFAULT_FLOAT == fInnerRadius ) + fInnerRadius = 1.0f; + if( D3DX_DEFAULT_FLOAT == fOuterRadius ) + fOuterRadius = 2.0f; + if( D3DX_DEFAULT == uSides ) + uSides = 8; + if( D3DX_DEFAULT == uRings ) + uRings = 15; + + // Validate parameters + if( !pDevice ) + return D3DERR_INVALIDCALL; + if( !ppMesh ) + return D3DERR_INVALIDCALL; + if( fInnerRadius < 0.0f ) + return D3DERR_INVALIDCALL; + if( fOuterRadius < 0.0f ) + return D3DERR_INVALIDCALL; + if( uSides < 3 ) + return D3DERR_INVALIDCALL; + if( uRings < 3 ) + return D3DERR_INVALIDCALL; + + // Create the mesh + UINT cFaces = 2 * uSides * uRings; + UINT cVertices = uRings * uSides; + + // Create enough memory for the vertices and indices + pVertices = new VERTEX[ cVertices ]; + if( !pVertices ) + return E_OUTOFMEMORY; + pwIndices = new WORD[ cFaces * 3 ]; + if( !pwIndices ) + return E_OUTOFMEMORY; + + // Create a torus + MakeTorus( pVertices, pwIndices, fInnerRadius, fOuterRadius, + uSides, uRings ); + + // Create a mesh + hr = CreateShapeMesh( pDevice, ppMesh, pVertices, cVertices, pwIndices, cFaces * 3 ); + + // Free up the memory + SAFE_DELETE_ARRAY( pVertices ); + SAFE_DELETE_ARRAY( pwIndices ); + + return hr; +} + + +//---------------------------------------------------------------------------- +// Teapot data +//---------------------------------------------------------------------------- +#define NUMTEAPOTVERTICES 1178 +#define NUMTEAPOTINDICES 6768 + +static float teapotPositionsFloats[NUMTEAPOTVERTICES*3] = +{ + 0.678873f, 0.330678f, 0.000000f, + 0.669556f, 0.358022f, 0.000000f, + 0.671003f, 0.374428f, 0.000000f, + 0.680435f, 0.379897f, 0.000000f, + 0.695077f, 0.374428f, 0.000000f, + 0.712148f, 0.358022f, 0.000000f, + 0.728873f, 0.330678f, 0.000000f, + 0.654243f, 0.330678f, 0.187963f, + 0.645254f, 0.358022f, 0.185461f, + 0.646650f, 0.374428f, 0.185850f, + 0.655751f, 0.379897f, 0.188383f, + 0.669877f, 0.374428f, 0.192314f, + 0.686348f, 0.358022f, 0.196898f, + 0.702484f, 0.330678f, 0.201389f, + 0.584502f, 0.330678f, 0.355704f, + 0.576441f, 0.358022f, 0.350969f, + 0.577693f, 0.374428f, 0.351704f, + 0.585854f, 0.379897f, 0.356498f, + 0.598522f, 0.374428f, 0.363938f, + 0.613292f, 0.358022f, 0.372613f, + 0.627762f, 0.330678f, 0.381111f, + 0.475873f, 0.330678f, 0.497000f, + 0.469258f, 0.358022f, 0.490385f, + 0.470285f, 0.374428f, 0.491412f, + 0.476982f, 0.379897f, 0.498109f, + 0.487377f, 0.374428f, 0.508505f, + 0.499498f, 0.358022f, 0.520626f, + 0.511373f, 0.330678f, 0.532500f, + 0.334576f, 0.330678f, 0.605630f, + 0.329842f, 0.358022f, 0.597569f, + 0.330577f, 0.374428f, 0.598820f, + 0.335370f, 0.379897f, 0.606982f, + 0.342810f, 0.374428f, 0.619649f, + 0.351485f, 0.358022f, 0.634419f, + 0.359984f, 0.330678f, 0.648889f, + 0.166836f, 0.330678f, 0.675370f, + 0.164334f, 0.358022f, 0.666381f, + 0.164722f, 0.374428f, 0.667777f, + 0.167255f, 0.379897f, 0.676878f, + 0.171187f, 0.374428f, 0.691004f, + 0.175771f, 0.358022f, 0.707475f, + 0.180262f, 0.330678f, 0.723611f, + -0.021127f, 0.330678f, 0.700000f, + -0.021127f, 0.358022f, 0.690683f, + -0.021127f, 0.374428f, 0.692130f, + -0.021127f, 0.379897f, 0.701563f, + -0.021127f, 0.374428f, 0.716204f, + -0.021127f, 0.358022f, 0.733276f, + -0.021127f, 0.330678f, 0.750000f, + -0.224715f, 0.330678f, 0.675370f, + -0.215631f, 0.358022f, 0.666381f, + -0.211606f, 0.374428f, 0.667777f, + -0.211463f, 0.379897f, 0.676878f, + -0.214020f, 0.374428f, 0.691004f, + -0.218098f, 0.358022f, 0.707475f, + -0.222516f, 0.330678f, 0.723611f, + -0.396831f, 0.330678f, 0.605630f, + -0.383671f, 0.358022f, 0.597569f, + -0.378758f, 0.374428f, 0.598820f, + -0.380125f, 0.379897f, 0.606982f, + -0.385806f, 0.374428f, 0.619649f, + -0.393832f, 0.358022f, 0.634419f, + -0.402238f, 0.330678f, 0.648889f, + -0.535002f, 0.330678f, 0.497000f, + -0.521278f, 0.358022f, 0.490385f, + -0.517539f, 0.374428f, 0.491412f, + -0.521346f, 0.379897f, 0.498109f, + -0.530257f, 0.374428f, 0.508505f, + -0.541831f, 0.358022f, 0.520626f, + -0.553627f, 0.330678f, 0.532500f, + -0.636757f, 0.330678f, 0.355704f, + -0.624483f, 0.358022f, 0.350969f, + -0.622910f, 0.374428f, 0.351704f, + -0.629359f, 0.379897f, 0.356498f, + -0.641146f, 0.374428f, 0.363938f, + -0.655593f, 0.358022f, 0.372613f, + -0.670016f, 0.330678f, 0.381111f, + -0.699623f, 0.330678f, 0.187963f, + -0.689317f, 0.358022f, 0.185461f, + -0.689830f, 0.374428f, 0.185850f, + -0.698396f, 0.379897f, 0.188382f, + -0.712247f, 0.374428f, 0.192314f, + -0.728617f, 0.358022f, 0.196898f, + -0.744738f, 0.330678f, 0.201389f, + -0.721127f, 0.330678f, 0.000000f, + -0.711810f, 0.358022f, 0.000000f, + -0.713257f, 0.374428f, 0.000000f, + -0.722690f, 0.379897f, 0.000000f, + -0.737331f, 0.374428f, 0.000000f, + -0.754403f, 0.358022f, 0.000000f, + -0.771127f, 0.330678f, 0.000000f, + -0.696498f, 0.330678f, -0.187963f, + -0.687508f, 0.358022f, -0.185461f, + -0.688904f, 0.374428f, -0.185850f, + -0.698005f, 0.379897f, -0.188383f, + -0.712131f, 0.374428f, -0.192314f, + -0.728602f, 0.358022f, -0.196898f, + -0.744738f, 0.330678f, -0.201389f, + -0.626757f, 0.330678f, -0.355704f, + -0.618696f, 0.358022f, -0.350969f, + -0.619948f, 0.374428f, -0.351704f, + -0.628109f, 0.379897f, -0.356498f, + -0.640776f, 0.374428f, -0.363938f, + -0.655546f, 0.358022f, -0.372613f, + -0.670016f, 0.330678f, -0.381111f, + -0.518127f, 0.330678f, -0.497000f, + -0.511512f, 0.358022f, -0.490385f, + -0.512539f, 0.374428f, -0.491412f, + -0.519237f, 0.379897f, -0.498109f, + -0.529632f, 0.374428f, -0.508505f, + -0.541753f, 0.358022f, -0.520626f, + -0.553627f, 0.330678f, -0.532500f, + -0.376831f, 0.330678f, -0.605630f, + -0.372096f, 0.358022f, -0.597569f, + -0.372832f, 0.374428f, -0.598820f, + -0.377625f, 0.379897f, -0.606982f, + -0.385065f, 0.374428f, -0.619649f, + -0.393740f, 0.358022f, -0.634419f, + -0.402238f, 0.330678f, -0.648889f, + -0.209090f, 0.330678f, -0.675370f, + -0.206588f, 0.358022f, -0.666381f, + -0.206977f, 0.374428f, -0.667777f, + -0.209510f, 0.379897f, -0.676878f, + -0.213441f, 0.374428f, -0.691004f, + -0.218025f, 0.358022f, -0.707475f, + -0.222516f, 0.330678f, -0.723611f, + -0.021127f, 0.330678f, -0.700000f, + -0.021127f, 0.358022f, -0.690683f, + -0.021127f, 0.374428f, -0.692130f, + -0.021127f, 0.379897f, -0.701563f, + -0.021127f, 0.374428f, -0.716204f, + -0.021127f, 0.358022f, -0.733276f, + -0.021127f, 0.330678f, -0.750000f, + 0.166836f, 0.330678f, -0.675370f, + 0.164334f, 0.358022f, -0.666381f, + 0.164722f, 0.374428f, -0.667777f, + 0.167255f, 0.379897f, -0.676878f, + 0.171187f, 0.374428f, -0.691004f, + 0.175771f, 0.358022f, -0.707475f, + 0.180262f, 0.330678f, -0.723611f, + 0.334576f, 0.330678f, -0.605630f, + 0.329842f, 0.358022f, -0.597569f, + 0.330577f, 0.374428f, -0.598820f, + 0.335370f, 0.379897f, -0.606982f, + 0.342810f, 0.374428f, -0.619649f, + 0.351485f, 0.358022f, -0.634419f, + 0.359984f, 0.330678f, -0.648889f, + 0.475873f, 0.330678f, -0.497000f, + 0.469258f, 0.358022f, -0.490385f, + 0.470285f, 0.374428f, -0.491412f, + 0.476982f, 0.379897f, -0.498109f, + 0.487377f, 0.374428f, -0.508505f, + 0.499498f, 0.358022f, -0.520626f, + 0.511373f, 0.330678f, -0.532500f, + 0.584502f, 0.330678f, -0.355704f, + 0.576441f, 0.358022f, -0.350969f, + 0.577693f, 0.374428f, -0.351704f, + 0.585854f, 0.379897f, -0.356498f, + 0.598522f, 0.374428f, -0.363938f, + 0.613292f, 0.358022f, -0.372613f, + 0.627762f, 0.330678f, -0.381111f, + 0.654243f, 0.330678f, -0.187963f, + 0.645254f, 0.358022f, -0.185461f, + 0.646650f, 0.374428f, -0.185850f, + 0.655751f, 0.379897f, -0.188382f, + 0.669877f, 0.374428f, -0.192314f, + 0.686348f, 0.358022f, -0.196898f, + 0.702484f, 0.330678f, -0.201389f, + 0.790794f, 0.199602f, 0.000000f, + 0.849243f, 0.069567f, 0.000000f, + 0.900748f, -0.058384f, 0.000000f, + 0.941836f, -0.183211f, 0.000000f, + 0.969035f, -0.303870f, 0.000000f, + 0.978873f, -0.419322f, 0.000000f, + 0.762227f, 0.199602f, 0.218016f, + 0.818619f, 0.069567f, 0.233711f, + 0.868312f, -0.058384f, 0.247541f, + 0.907954f, -0.183211f, 0.258573f, + 0.934196f, -0.303870f, 0.265877f, + 0.943688f, -0.419322f, 0.268519f, + 0.681335f, 0.199602f, 0.412576f, + 0.731904f, 0.069567f, 0.442277f, + 0.776465f, -0.058384f, 0.468449f, + 0.812014f, -0.183211f, 0.489328f, + 0.835546f, -0.303870f, 0.503149f, + 0.844058f, -0.419322f, 0.508148f, + 0.555337f, 0.199602f, 0.576464f, + 0.596836f, 0.069567f, 0.617963f, + 0.633404f, -0.058384f, 0.654531f, + 0.662577f, -0.183211f, 0.683704f, + 0.681888f, -0.303870f, 0.703015f, + 0.688873f, -0.419322f, 0.710000f, + 0.391449f, 0.199602f, 0.702462f, + 0.421150f, 0.069567f, 0.753032f, + 0.447322f, -0.058384f, 0.797593f, + 0.468201f, -0.183211f, 0.833141f, + 0.482022f, -0.303870f, 0.856674f, + 0.487021f, -0.419322f, 0.865185f, + 0.196889f, 0.199602f, 0.783354f, + 0.212583f, 0.069567f, 0.839746f, + 0.226413f, -0.058384f, 0.889439f, + 0.237446f, -0.183211f, 0.929081f, + 0.244750f, -0.303870f, 0.955323f, + 0.247391f, -0.419322f, 0.964815f, + -0.021127f, 0.199602f, 0.811921f, + -0.021127f, 0.069567f, 0.870370f, + -0.021127f, -0.058384f, 0.921875f, + -0.021127f, -0.183211f, 0.962963f, + -0.021127f, -0.303870f, 0.990162f, + -0.021127f, -0.419322f, 1.000000f, + -0.239143f, 0.199602f, 0.783354f, + -0.254838f, 0.069567f, 0.839746f, + -0.268668f, -0.058384f, 0.889439f, + -0.279701f, -0.183211f, 0.929081f, + -0.287004f, -0.303870f, 0.955323f, + -0.289646f, -0.419322f, 0.964815f, + -0.433704f, 0.199602f, 0.702462f, + -0.463404f, 0.069567f, 0.753032f, + -0.489576f, -0.058384f, 0.797593f, + -0.510455f, -0.183211f, 0.833141f, + -0.524276f, -0.303870f, 0.856674f, + -0.529275f, -0.419322f, 0.865185f, + -0.597591f, 0.199602f, 0.576464f, + -0.639090f, 0.069567f, 0.617963f, + -0.675658f, -0.058384f, 0.654531f, + -0.704831f, -0.183211f, 0.683704f, + -0.724142f, -0.303870f, 0.703015f, + -0.731127f, -0.419322f, 0.710000f, + -0.723589f, 0.199602f, 0.412576f, + -0.774159f, 0.069567f, 0.442277f, + -0.818720f, -0.058384f, 0.468449f, + -0.854269f, -0.183211f, 0.489328f, + -0.877801f, -0.303870f, 0.503149f, + -0.886312f, -0.419322f, 0.508148f, + -0.804481f, 0.199602f, 0.218016f, + -0.860873f, 0.069567f, 0.233711f, + -0.910566f, -0.058384f, 0.247540f, + -0.950208f, -0.183211f, 0.258573f, + -0.976450f, -0.303870f, 0.265877f, + -0.985942f, -0.419322f, 0.268518f, + -0.833049f, 0.199602f, 0.000000f, + -0.891498f, 0.069567f, 0.000000f, + -0.943002f, -0.058384f, 0.000000f, + -0.984090f, -0.183211f, 0.000000f, + -1.011289f, -0.303870f, 0.000000f, + -1.021127f, -0.419322f, 0.000000f, + -0.804481f, 0.199602f, -0.218016f, + -0.860873f, 0.069567f, -0.233711f, + -0.910566f, -0.058384f, -0.247541f, + -0.950208f, -0.183211f, -0.258573f, + -0.976450f, -0.303870f, -0.265877f, + -0.985942f, -0.419322f, -0.268519f, + -0.723589f, 0.199602f, -0.412576f, + -0.774159f, 0.069567f, -0.442277f, + -0.818720f, -0.058384f, -0.468449f, + -0.854269f, -0.183211f, -0.489328f, + -0.877801f, -0.303870f, -0.503149f, + -0.886312f, -0.419322f, -0.508148f, + -0.597591f, 0.199602f, -0.576464f, + -0.639090f, 0.069567f, -0.617963f, + -0.675658f, -0.058384f, -0.654531f, + -0.704831f, -0.183211f, -0.683704f, + -0.724142f, -0.303870f, -0.703015f, + -0.731127f, -0.419322f, -0.710000f, + -0.433704f, 0.199602f, -0.702462f, + -0.463404f, 0.069567f, -0.753032f, + -0.489576f, -0.058384f, -0.797593f, + -0.510455f, -0.183211f, -0.833141f, + -0.524276f, -0.303870f, -0.856674f, + -0.529275f, -0.419322f, -0.865185f, + -0.239143f, 0.199602f, -0.783354f, + -0.254838f, 0.069567f, -0.839746f, + -0.268668f, -0.058384f, -0.889439f, + -0.279701f, -0.183211f, -0.929081f, + -0.287004f, -0.303870f, -0.955323f, + -0.289646f, -0.419322f, -0.964815f, + -0.021127f, 0.199602f, -0.811921f, + -0.021127f, 0.069567f, -0.870370f, + -0.021127f, -0.058384f, -0.921875f, + -0.021127f, -0.183211f, -0.962963f, + -0.021127f, -0.303870f, -0.990162f, + -0.021127f, -0.419322f, -1.000000f, + 0.196889f, 0.199602f, -0.783354f, + 0.212583f, 0.069567f, -0.839746f, + 0.226413f, -0.058384f, -0.889439f, + 0.237446f, -0.183211f, -0.929081f, + 0.244750f, -0.303870f, -0.955323f, + 0.247391f, -0.419322f, -0.964815f, + 0.391449f, 0.199602f, -0.702462f, + 0.421150f, 0.069567f, -0.753032f, + 0.447322f, -0.058384f, -0.797593f, + 0.468201f, -0.183211f, -0.833141f, + 0.482022f, -0.303870f, -0.856674f, + 0.487021f, -0.419322f, -0.865185f, + 0.555337f, 0.199602f, -0.576464f, + 0.596836f, 0.069567f, -0.617963f, + 0.633404f, -0.058384f, -0.654531f, + 0.662577f, -0.183211f, -0.683704f, + 0.681888f, -0.303870f, -0.703015f, + 0.688873f, -0.419322f, -0.710000f, + 0.681335f, 0.199602f, -0.412576f, + 0.731904f, 0.069567f, -0.442277f, + 0.776465f, -0.058384f, -0.468449f, + 0.812014f, -0.183211f, -0.489328f, + 0.835546f, -0.303870f, -0.503149f, + 0.844058f, -0.419322f, -0.508148f, + 0.762227f, 0.199602f, -0.218016f, + 0.818619f, 0.069567f, -0.233711f, + 0.868312f, -0.058384f, -0.247540f, + 0.907954f, -0.183211f, -0.258573f, + 0.934196f, -0.303870f, -0.265877f, + 0.943688f, -0.419322f, -0.268518f, + 0.960354f, -0.522620f, 0.000000f, + 0.914058f, -0.608211f, 0.000000f, + 0.853873f, -0.677134f, 0.000000f, + 0.793688f, -0.730433f, 0.000000f, + 0.747391f, -0.769148f, 0.000000f, + 0.728873f, -0.794322f, 0.000000f, + 0.925821f, -0.522620f, 0.263546f, + 0.881153f, -0.608211f, 0.251115f, + 0.823086f, -0.677134f, 0.234954f, + 0.765018f, -0.730433f, 0.218793f, + 0.720351f, -0.769148f, 0.206361f, + 0.702484f, -0.794322f, 0.201389f, + 0.828036f, -0.522620f, 0.498738f, + 0.787981f, -0.608211f, 0.475213f, + 0.735910f, -0.677134f, 0.444630f, + 0.683839f, -0.730433f, 0.414047f, + 0.643784f, -0.769148f, 0.390521f, + 0.627762f, -0.794322f, 0.381111f, + 0.675725f, -0.522620f, 0.696852f, + 0.642854f, -0.608211f, 0.663981f, + 0.600123f, -0.677134f, 0.621250f, + 0.557391f, -0.730433f, 0.578519f, + 0.524521f, -0.769148f, 0.545648f, + 0.511373f, -0.794322f, 0.532500f, + 0.477611f, -0.522620f, 0.849163f, + 0.454085f, -0.608211f, 0.809108f, + 0.423502f, -0.677134f, 0.757037f, + 0.392919f, -0.730433f, 0.704966f, + 0.369394f, -0.769148f, 0.664911f, + 0.359984f, -0.794322f, 0.648889f, + 0.242419f, -0.522620f, 0.946948f, + 0.229987f, -0.608211f, 0.902281f, + 0.213826f, -0.677134f, 0.844213f, + 0.197666f, -0.730433f, 0.786145f, + 0.185234f, -0.769148f, 0.741478f, + 0.180262f, -0.794322f, 0.723611f, + -0.021127f, -0.522620f, 0.981482f, + -0.021127f, -0.608211f, 0.935185f, + -0.021127f, -0.677134f, 0.875000f, + -0.021127f, -0.730433f, 0.814815f, + -0.021127f, -0.769148f, 0.768519f, + -0.021127f, -0.794322f, 0.750000f, + -0.284673f, -0.522620f, 0.946948f, + -0.272242f, -0.608211f, 0.902281f, + -0.256081f, -0.677134f, 0.844213f, + -0.239920f, -0.730433f, 0.786145f, + -0.227489f, -0.769148f, 0.741478f, + -0.222516f, -0.794322f, 0.723611f, + -0.519865f, -0.522620f, 0.849163f, + -0.496340f, -0.608211f, 0.809108f, + -0.465757f, -0.677134f, 0.757037f, + -0.435174f, -0.730433f, 0.704966f, + -0.411649f, -0.769148f, 0.664911f, + -0.402238f, -0.794322f, 0.648889f, + -0.717979f, -0.522620f, 0.696852f, + -0.685109f, -0.608211f, 0.663981f, + -0.642377f, -0.677134f, 0.621250f, + -0.599646f, -0.730433f, 0.578519f, + -0.566775f, -0.769148f, 0.545648f, + -0.553627f, -0.794322f, 0.532500f, + -0.870290f, -0.522620f, 0.498738f, + -0.830236f, -0.608211f, 0.475213f, + -0.778164f, -0.677134f, 0.444630f, + -0.726093f, -0.730433f, 0.414047f, + -0.686038f, -0.769148f, 0.390521f, + -0.670016f, -0.794322f, 0.381111f, + -0.968075f, -0.522620f, 0.263546f, + -0.923408f, -0.608211f, 0.251115f, + -0.865340f, -0.677134f, 0.234954f, + -0.807273f, -0.730433f, 0.218793f, + -0.762605f, -0.769148f, 0.206361f, + -0.744738f, -0.794322f, 0.201389f, + -1.002609f, -0.522620f, 0.000000f, + -0.956312f, -0.608211f, 0.000000f, + -0.896127f, -0.677134f, 0.000000f, + -0.835942f, -0.730433f, 0.000000f, + -0.789646f, -0.769148f, 0.000000f, + -0.771127f, -0.794322f, 0.000000f, + -0.968075f, -0.522620f, -0.263546f, + -0.923408f, -0.608211f, -0.251115f, + -0.865340f, -0.677134f, -0.234954f, + -0.807273f, -0.730433f, -0.218793f, + -0.762605f, -0.769148f, -0.206361f, + -0.744738f, -0.794322f, -0.201389f, + -0.870290f, -0.522620f, -0.498738f, + -0.830236f, -0.608211f, -0.475213f, + -0.778164f, -0.677134f, -0.444630f, + -0.726093f, -0.730433f, -0.414047f, + -0.686038f, -0.769148f, -0.390521f, + -0.670016f, -0.794322f, -0.381111f, + -0.717979f, -0.522620f, -0.696852f, + -0.685109f, -0.608211f, -0.663981f, + -0.642377f, -0.677134f, -0.621250f, + -0.599646f, -0.730433f, -0.578519f, + -0.566775f, -0.769148f, -0.545648f, + -0.553627f, -0.794322f, -0.532500f, + -0.519865f, -0.522620f, -0.849163f, + -0.496340f, -0.608211f, -0.809108f, + -0.465757f, -0.677134f, -0.757037f, + -0.435174f, -0.730433f, -0.704966f, + -0.411648f, -0.769148f, -0.664911f, + -0.402238f, -0.794322f, -0.648889f, + -0.284673f, -0.522620f, -0.946948f, + -0.272242f, -0.608211f, -0.902281f, + -0.256081f, -0.677134f, -0.844213f, + -0.239920f, -0.730433f, -0.786145f, + -0.227489f, -0.769148f, -0.741478f, + -0.222516f, -0.794322f, -0.723611f, + -0.021127f, -0.522620f, -0.981482f, + -0.021127f, -0.608211f, -0.935185f, + -0.021127f, -0.677134f, -0.875000f, + -0.021127f, -0.730433f, -0.814815f, + -0.021127f, -0.769148f, -0.768519f, + -0.021127f, -0.794322f, -0.750000f, + 0.242419f, -0.522620f, -0.946948f, + 0.229987f, -0.608211f, -0.902281f, + 0.213827f, -0.677134f, -0.844213f, + 0.197666f, -0.730433f, -0.786145f, + 0.185234f, -0.769148f, -0.741478f, + 0.180262f, -0.794322f, -0.723611f, + 0.477611f, -0.522620f, -0.849163f, + 0.454085f, -0.608211f, -0.809108f, + 0.423502f, -0.677134f, -0.757037f, + 0.392919f, -0.730433f, -0.704966f, + 0.369394f, -0.769148f, -0.664911f, + 0.359984f, -0.794322f, -0.648889f, + 0.675725f, -0.522620f, -0.696852f, + 0.642854f, -0.608211f, -0.663981f, + 0.600123f, -0.677134f, -0.621250f, + 0.557391f, -0.730433f, -0.578519f, + 0.524521f, -0.769148f, -0.545648f, + 0.511373f, -0.794322f, -0.532500f, + 0.828036f, -0.522620f, -0.498738f, + 0.787981f, -0.608211f, -0.475213f, + 0.735910f, -0.677134f, -0.444630f, + 0.683839f, -0.730433f, -0.414047f, + 0.643784f, -0.769148f, -0.390521f, + 0.627762f, -0.794322f, -0.381111f, + 0.925821f, -0.522620f, -0.263546f, + 0.881153f, -0.608211f, -0.251115f, + 0.823086f, -0.677134f, -0.234954f, + 0.765018f, -0.730433f, -0.218793f, + 0.720351f, -0.769148f, -0.206361f, + 0.702484f, -0.794322f, -0.201389f, + 0.722796f, -0.812898f, 0.000000f, + 0.692762f, -0.830433f, 0.000000f, + 0.621060f, -0.845884f, 0.000000f, + 0.489984f, -0.858211f, 0.000000f, + 0.281824f, -0.866370f, 0.000000f, + -0.021127f, -0.869322f, 0.000000f, + 0.696621f, -0.812898f, 0.199757f, + 0.667643f, -0.830433f, 0.191692f, + 0.598465f, -0.845884f, 0.172439f, + 0.472000f, -0.858211f, 0.137243f, + 0.271165f, -0.866370f, 0.081348f, + 0.622505f, -0.812898f, 0.378023f, + 0.596519f, -0.830433f, 0.362761f, + 0.534484f, -0.845884f, 0.326326f, + 0.421079f, -0.858211f, 0.259720f, + 0.240982f, -0.866370f, 0.153944f, + 0.507059f, -0.812898f, 0.528186f, + 0.485734f, -0.830433f, 0.506861f, + 0.434826f, -0.845884f, 0.455953f, + 0.341762f, -0.858211f, 0.362889f, + 0.193968f, -0.866370f, 0.215095f, + 0.356896f, -0.812898f, 0.643632f, + 0.341634f, -0.830433f, 0.617646f, + 0.305199f, -0.845884f, 0.555611f, + 0.238593f, -0.858211f, 0.442206f, + 0.132817f, -0.866370f, 0.262109f, + 0.178630f, -0.812898f, 0.717749f, + 0.170565f, -0.830433f, 0.688771f, + 0.151312f, -0.845884f, 0.619592f, + 0.116116f, -0.858211f, 0.493128f, + 0.060221f, -0.866370f, 0.292292f, + -0.021127f, -0.812898f, 0.743924f, + -0.021127f, -0.830433f, 0.713889f, + -0.021127f, -0.845884f, 0.642188f, + -0.021127f, -0.858211f, 0.511111f, + -0.021127f, -0.866370f, 0.302951f, + -0.220884f, -0.812898f, 0.717749f, + -0.212820f, -0.830433f, 0.688771f, + -0.193566f, -0.845884f, 0.619592f, + -0.158370f, -0.858211f, 0.493128f, + -0.102475f, -0.866370f, 0.292292f, + -0.399151f, -0.812898f, 0.643632f, + -0.383889f, -0.830433f, 0.617646f, + -0.347454f, -0.845884f, 0.555611f, + -0.280847f, -0.858211f, 0.442206f, + -0.175071f, -0.866370f, 0.262109f, + -0.549313f, -0.812898f, 0.528186f, + -0.527988f, -0.830433f, 0.506861f, + -0.477080f, -0.845884f, 0.455953f, + -0.384016f, -0.858211f, 0.362889f, + -0.236223f, -0.866370f, 0.215095f, + -0.664759f, -0.812898f, 0.378023f, + -0.638773f, -0.830433f, 0.362761f, + -0.576738f, -0.845884f, 0.326326f, + -0.463333f, -0.858211f, 0.259720f, + -0.283236f, -0.866370f, 0.153944f, + -0.738876f, -0.812898f, 0.199757f, + -0.709898f, -0.830433f, 0.191692f, + -0.640719f, -0.845884f, 0.172439f, + -0.514255f, -0.858211f, 0.137243f, + -0.313419f, -0.866370f, 0.081348f, + -0.765051f, -0.812898f, 0.000000f, + -0.735016f, -0.830433f, 0.000000f, + -0.663315f, -0.845884f, 0.000000f, + -0.532238f, -0.858211f, 0.000000f, + -0.324079f, -0.866370f, 0.000000f, + -0.738876f, -0.812898f, -0.199757f, + -0.709898f, -0.830433f, -0.191692f, + -0.640719f, -0.845884f, -0.172439f, + -0.514255f, -0.858211f, -0.137243f, + -0.313419f, -0.866370f, -0.081348f, + -0.664759f, -0.812898f, -0.378023f, + -0.638773f, -0.830433f, -0.362761f, + -0.576738f, -0.845884f, -0.326326f, + -0.463333f, -0.858211f, -0.259720f, + -0.283236f, -0.866370f, -0.153944f, + -0.549313f, -0.812898f, -0.528186f, + -0.527988f, -0.830433f, -0.506861f, + -0.477080f, -0.845884f, -0.455953f, + -0.384016f, -0.858211f, -0.362889f, + -0.236223f, -0.866370f, -0.215095f, + -0.399151f, -0.812898f, -0.643632f, + -0.383889f, -0.830433f, -0.617646f, + -0.347454f, -0.845884f, -0.555611f, + -0.280847f, -0.858211f, -0.442206f, + -0.175071f, -0.866370f, -0.262109f, + -0.220884f, -0.812898f, -0.717749f, + -0.212820f, -0.830433f, -0.688771f, + -0.193566f, -0.845884f, -0.619592f, + -0.158370f, -0.858211f, -0.493128f, + -0.102475f, -0.866370f, -0.292292f, + -0.021127f, -0.812898f, -0.743924f, + -0.021127f, -0.830433f, -0.713889f, + -0.021127f, -0.845884f, -0.642188f, + -0.021127f, -0.858211f, -0.511111f, + -0.021127f, -0.866370f, -0.302951f, + 0.178630f, -0.812898f, -0.717749f, + 0.170565f, -0.830433f, -0.688771f, + 0.151312f, -0.845884f, -0.619592f, + 0.116116f, -0.858211f, -0.493128f, + 0.060221f, -0.866370f, -0.292292f, + 0.356896f, -0.812898f, -0.643632f, + 0.341634f, -0.830433f, -0.617646f, + 0.305199f, -0.845884f, -0.555611f, + 0.238593f, -0.858211f, -0.442206f, + 0.132817f, -0.866370f, -0.262109f, + 0.507059f, -0.812898f, -0.528186f, + 0.485734f, -0.830433f, -0.506861f, + 0.434826f, -0.845884f, -0.455953f, + 0.341762f, -0.858211f, -0.362889f, + 0.193968f, -0.866370f, -0.215095f, + 0.622505f, -0.812898f, -0.378023f, + 0.596519f, -0.830433f, -0.362761f, + 0.534484f, -0.845884f, -0.326326f, + 0.421079f, -0.858211f, -0.259720f, + 0.240982f, -0.866370f, -0.153944f, + 0.696621f, -0.812898f, -0.199757f, + 0.667643f, -0.830433f, -0.191692f, + 0.598465f, -0.845884f, -0.172439f, + 0.472000f, -0.858211f, -0.137243f, + 0.271165f, -0.866370f, -0.081348f, + -0.821127f, 0.143178f, 0.000000f, + -0.983396f, 0.142657f, 0.000000f, + -1.119275f, 0.139012f, 0.000000f, + -1.227377f, 0.129116f, 0.000000f, + -1.306313f, 0.109845f, 0.000000f, + -1.354692f, 0.078074f, 0.000000f, + -1.371127f, 0.030678f, 0.000000f, + -0.817424f, 0.151512f, 0.062500f, + -0.984648f, 0.150952f, 0.062500f, + -1.124351f, 0.147036f, 0.062500f, + -1.235248f, 0.136407f, 0.062500f, + -1.316052f, 0.115709f, 0.062500f, + -1.365477f, 0.081585f, 0.062500f, + -1.382239f, 0.030678f, 0.062500f, + -0.808164f, 0.172345f, 0.100000f, + -0.987777f, 0.171689f, 0.100000f, + -1.137040f, 0.167098f, 0.100000f, + -1.254924f, 0.154637f, 0.100000f, + -1.340400f, 0.130370f, 0.100000f, + -1.392441f, 0.090362f, 0.100000f, + -1.410016f, 0.030678f, 0.100000f, + -0.796127f, 0.199428f, 0.112500f, + -0.991845f, 0.198647f, 0.112500f, + -1.153535f, 0.193178f, 0.112500f, + -1.280502f, 0.178335f, 0.112500f, + -1.372053f, 0.149428f, 0.112500f, + -1.427493f, 0.101772f, 0.112500f, + -1.446127f, 0.030678f, 0.112500f, + -0.784090f, 0.226511f, 0.100000f, + -0.995913f, 0.225605f, 0.100000f, + -1.170030f, 0.219258f, 0.100000f, + -1.306081f, 0.202032f, 0.100000f, + -1.403706f, 0.168487f, 0.100000f, + -1.462545f, 0.113182f, 0.100000f, + -1.482238f, 0.030678f, 0.100000f, + -0.774831f, 0.247345f, 0.062500f, + -0.999042f, 0.246342f, 0.062500f, + -1.182719f, 0.239320f, 0.062500f, + -1.325757f, 0.220261f, 0.062500f, + -1.428054f, 0.183147f, 0.062500f, + -1.489509f, 0.121959f, 0.062500f, + -1.510016f, 0.030678f, 0.062500f, + -0.771127f, 0.255678f, 0.000000f, + -1.000294f, 0.254636f, 0.000000f, + -1.187794f, 0.247345f, 0.000000f, + -1.333627f, 0.227553f, 0.000000f, + -1.437794f, 0.189011f, 0.000000f, + -1.500294f, 0.125470f, 0.000000f, + -1.521127f, 0.030678f, 0.000000f, + -0.774831f, 0.247345f, -0.062500f, + -0.999042f, 0.246342f, -0.062500f, + -1.182719f, 0.239320f, -0.062500f, + -1.325757f, 0.220261f, -0.062500f, + -1.428054f, 0.183147f, -0.062500f, + -1.489509f, 0.121959f, -0.062500f, + -1.510016f, 0.030678f, -0.062500f, + -0.784090f, 0.226511f, -0.100000f, + -0.995913f, 0.225605f, -0.100000f, + -1.170030f, 0.219258f, -0.100000f, + -1.306081f, 0.202032f, -0.100000f, + -1.403706f, 0.168487f, -0.100000f, + -1.462545f, 0.113182f, -0.100000f, + -1.482238f, 0.030678f, -0.100000f, + -0.796127f, 0.199428f, -0.112500f, + -0.991845f, 0.198647f, -0.112500f, + -1.153535f, 0.193178f, -0.112500f, + -1.280502f, 0.178335f, -0.112500f, + -1.372053f, 0.149428f, -0.112500f, + -1.427493f, 0.101772f, -0.112500f, + -1.446127f, 0.030678f, -0.112500f, + -0.808164f, 0.172345f, -0.100000f, + -0.987777f, 0.171689f, -0.100000f, + -1.137040f, 0.167098f, -0.100000f, + -1.254924f, 0.154637f, -0.100000f, + -1.340400f, 0.130370f, -0.100000f, + -1.392441f, 0.090362f, -0.100000f, + -1.410016f, 0.030678f, -0.100000f, + -0.817424f, 0.151512f, -0.062500f, + -0.984648f, 0.150952f, -0.062500f, + -1.124351f, 0.147036f, -0.062500f, + -1.235248f, 0.136407f, -0.062500f, + -1.316052f, 0.115709f, -0.062500f, + -1.365477f, 0.081585f, -0.062500f, + -1.382239f, 0.030678f, -0.062500f, + -1.362563f, -0.033905f, 0.000000f, + -1.335942f, -0.110988f, 0.000000f, + -1.289877f, -0.194322f, 0.000000f, + -1.222979f, -0.277655f, 0.000000f, + -1.133859f, -0.354739f, 0.000000f, + -1.021127f, -0.419322f, 0.000000f, + -1.373219f, -0.037332f, 0.062500f, + -1.345270f, -0.116647f, 0.062500f, + -1.297053f, -0.201440f, 0.062500f, + -1.227232f, -0.285886f, 0.062500f, + -1.134467f, -0.364159f, 0.062500f, + -1.017424f, -0.430433f, 0.062500f, + -1.399861f, -0.045900f, 0.100000f, + -1.368590f, -0.130793f, 0.100000f, + -1.314993f, -0.219235f, 0.100000f, + -1.237862f, -0.306462f, 0.100000f, + -1.135989f, -0.387709f, 0.100000f, + -1.008164f, -0.458211f, 0.100000f, + -1.434495f, -0.057039f, 0.112500f, + -1.398905f, -0.149183f, 0.112500f, + -1.338315f, -0.242369f, 0.112500f, + -1.251683f, -0.333211f, 0.112500f, + -1.137967f, -0.418324f, 0.112500f, + -0.996127f, -0.494322f, 0.112500f, + -1.469130f, -0.068177f, 0.100000f, + -1.429221f, -0.167573f, 0.100000f, + -1.361637f, -0.265502f, 0.100000f, + -1.265503f, -0.359960f, 0.100000f, + -1.139946f, -0.448939f, 0.100000f, + -0.984090f, -0.530433f, 0.100000f, + -1.495772f, -0.076745f, 0.062500f, + -1.452540f, -0.181719f, 0.062500f, + -1.379576f, -0.283298f, 0.062500f, + -1.276134f, -0.380536f, 0.062500f, + -1.141468f, -0.472489f, 0.062500f, + -0.974831f, -0.558211f, 0.062500f, + -1.506428f, -0.080173f, 0.000000f, + -1.461868f, -0.187377f, 0.000000f, + -1.386752f, -0.290416f, 0.000000f, + -1.280387f, -0.388766f, 0.000000f, + -1.142076f, -0.481909f, 0.000000f, + -0.971127f, -0.569322f, 0.000000f, + -1.495772f, -0.076745f, -0.062500f, + -1.452540f, -0.181719f, -0.062500f, + -1.379576f, -0.283298f, -0.062500f, + -1.276134f, -0.380536f, -0.062500f, + -1.141468f, -0.472489f, -0.062500f, + -0.974831f, -0.558211f, -0.062500f, + -1.469130f, -0.068177f, -0.100000f, + -1.429221f, -0.167573f, -0.100000f, + -1.361637f, -0.265502f, -0.100000f, + -1.265503f, -0.359960f, -0.100000f, + -1.139946f, -0.448939f, -0.100000f, + -0.984090f, -0.530433f, -0.100000f, + -1.434495f, -0.057039f, -0.112500f, + -1.398905f, -0.149183f, -0.112500f, + -1.338315f, -0.242369f, -0.112500f, + -1.251683f, -0.333211f, -0.112500f, + -1.137967f, -0.418324f, -0.112500f, + -0.996127f, -0.494322f, -0.112500f, + -1.399861f, -0.045900f, -0.100000f, + -1.368590f, -0.130793f, -0.100000f, + -1.314993f, -0.219235f, -0.100000f, + -1.237862f, -0.306462f, -0.100000f, + -1.135989f, -0.387709f, -0.100000f, + -1.008164f, -0.458211f, -0.100000f, + -1.373219f, -0.037332f, -0.062500f, + -1.345270f, -0.116647f, -0.062500f, + -1.297053f, -0.201440f, -0.062500f, + -1.227232f, -0.285886f, -0.062500f, + -1.134467f, -0.364159f, -0.062500f, + -1.017424f, -0.430433f, -0.062500f, + 0.828873f, -0.156822f, 0.000000f, + 1.008271f, -0.131127f, 0.000000f, + 1.114058f, -0.063766f, 0.000000f, + 1.172623f, 0.030678f, 0.000000f, + 1.210354f, 0.137623f, 0.000000f, + 1.253641f, 0.242484f, 0.000000f, + 1.328873f, 0.330678f, 0.000000f, + 0.828873f, -0.187377f, 0.137500f, + 1.015061f, -0.156719f, 0.131173f, + 1.123935f, -0.083314f, 0.115355f, + 1.183734f, 0.017484f, 0.094792f, + 1.222700f, 0.130318f, 0.074228f, + 1.269073f, 0.239835f, 0.058411f, + 1.351095f, 0.330678f, 0.052083f, + 0.828873f, -0.263766f, 0.220000f, + 1.032036f, -0.220698f, 0.209877f, + 1.148626f, -0.132182f, 0.184568f, + 1.211512f, -0.015502f, 0.151667f, + 1.253564f, 0.112057f, 0.118765f, + 1.307654f, 0.233212f, 0.093457f, + 1.406651f, 0.330678f, 0.083333f, + 0.828873f, -0.363072f, 0.247500f, + 1.054104f, -0.303870f, 0.236111f, + 1.180725f, -0.195711f, 0.207639f, + 1.247623f, -0.058384f, 0.170625f, + 1.293688f, 0.088317f, 0.133611f, + 1.357808f, 0.224602f, 0.105139f, + 1.478873f, 0.330678f, 0.093750f, + 0.828873f, -0.462377f, 0.220000f, + 1.076172f, -0.387043f, 0.209877f, + 1.212823f, -0.259240f, 0.184568f, + 1.283734f, -0.101266f, 0.151667f, + 1.333811f, 0.064577f, 0.118765f, + 1.407962f, 0.215992f, 0.093457f, + 1.551095f, 0.330678f, 0.083333f, + 0.828873f, -0.538766f, 0.137500f, + 1.093148f, -0.451022f, 0.131173f, + 1.237515f, -0.308108f, 0.115355f, + 1.311512f, -0.134252f, 0.094792f, + 1.364675f, 0.046316f, 0.074228f, + 1.446543f, 0.209369f, 0.058410f, + 1.606651f, 0.330678f, 0.052083f, + 0.828873f, -0.569322f, 0.000000f, + 1.099938f, -0.476614f, 0.000000f, + 1.247391f, -0.327655f, 0.000000f, + 1.322623f, -0.147447f, 0.000000f, + 1.377021f, 0.039012f, 0.000000f, + 1.461975f, 0.206720f, 0.000000f, + 1.628873f, 0.330678f, 0.000000f, + 0.828873f, -0.538766f, -0.137500f, + 1.093148f, -0.451022f, -0.131173f, + 1.237515f, -0.308108f, -0.115355f, + 1.311512f, -0.134252f, -0.094792f, + 1.364675f, 0.046316f, -0.074228f, + 1.446543f, 0.209369f, -0.058410f, + 1.606651f, 0.330678f, -0.052083f, + 0.828873f, -0.462377f, -0.220000f, + 1.076172f, -0.387043f, -0.209877f, + 1.212823f, -0.259240f, -0.184568f, + 1.283734f, -0.101266f, -0.151667f, + 1.333811f, 0.064577f, -0.118765f, + 1.407962f, 0.215992f, -0.093457f, + 1.551095f, 0.330678f, -0.083333f, + 0.828873f, -0.363072f, -0.247500f, + 1.054104f, -0.303870f, -0.236111f, + 1.180725f, -0.195711f, -0.207639f, + 1.247623f, -0.058384f, -0.170625f, + 1.293688f, 0.088317f, -0.133611f, + 1.357808f, 0.224602f, -0.105139f, + 1.478873f, 0.330678f, -0.093750f, + 0.828873f, -0.263766f, -0.220000f, + 1.032036f, -0.220698f, -0.209877f, + 1.148626f, -0.132182f, -0.184568f, + 1.211512f, -0.015502f, -0.151667f, + 1.253564f, 0.112057f, -0.118765f, + 1.307654f, 0.233212f, -0.093457f, + 1.406651f, 0.330678f, -0.083333f, + 0.828873f, -0.187377f, -0.137500f, + 1.015061f, -0.156719f, -0.131173f, + 1.123935f, -0.083314f, -0.115355f, + 1.183734f, 0.017484f, -0.094792f, + 1.222700f, 0.130318f, -0.074228f, + 1.269073f, 0.239835f, -0.058410f, + 1.351095f, 0.330678f, -0.052083f, + 1.353410f, 0.346303f, 0.000000f, + 1.375169f, 0.355678f, 0.000000f, + 1.391373f, 0.358803f, 0.000000f, + 1.399243f, 0.355678f, 0.000000f, + 1.396003f, 0.346303f, 0.000000f, + 1.378873f, 0.330678f, 0.000000f, + 1.377077f, 0.346641f, 0.050540f, + 1.398763f, 0.356295f, 0.046682f, + 1.413711f, 0.359584f, 0.041667f, + 1.419477f, 0.356450f, 0.036651f, + 1.413617f, 0.346834f, 0.032793f, + 1.393688f, 0.330678f, 0.031250f, + 1.436244f, 0.347485f, 0.080864f, + 1.457748f, 0.357839f, 0.074691f, + 1.469556f, 0.361538f, 0.066667f, + 1.470060f, 0.358379f, 0.058642f, + 1.457652f, 0.348160f, 0.052469f, + 1.430725f, 0.330678f, 0.050000f, + 1.513161f, 0.348582f, 0.090972f, + 1.534428f, 0.359845f, 0.084028f, + 1.542154f, 0.364077f, 0.075000f, + 1.535817f, 0.360886f, 0.065972f, + 1.514897f, 0.349884f, 0.059028f, + 1.478873f, 0.330678f, 0.056250f, + 1.590078f, 0.349679f, 0.080864f, + 1.611109f, 0.361851f, 0.074691f, + 1.614753f, 0.366616f, 0.066667f, + 1.601575f, 0.363394f, 0.058642f, + 1.572143f, 0.351608f, 0.052469f, + 1.527021f, 0.330678f, 0.050000f, + 1.649245f, 0.350523f, 0.050540f, + 1.670094f, 0.363394f, 0.046682f, + 1.670597f, 0.368569f, 0.041667f, + 1.652158f, 0.365323f, 0.036651f, + 1.616178f, 0.352934f, 0.032793f, + 1.564058f, 0.330678f, 0.031250f, + 1.672912f, 0.350860f, 0.000000f, + 1.693688f, 0.364011f, 0.000000f, + 1.692935f, 0.369350f, 0.000000f, + 1.672391f, 0.366095f, 0.000000f, + 1.633792f, 0.353465f, 0.000000f, + 1.578873f, 0.330678f, 0.000000f, + 1.649245f, 0.350523f, -0.050540f, + 1.670094f, 0.363394f, -0.046682f, + 1.670597f, 0.368569f, -0.041667f, + 1.652158f, 0.365323f, -0.036651f, + 1.616178f, 0.352934f, -0.032793f, + 1.564058f, 0.330678f, -0.031250f, + 1.590078f, 0.349679f, -0.080864f, + 1.611109f, 0.361851f, -0.074691f, + 1.614753f, 0.366616f, -0.066667f, + 1.601575f, 0.363394f, -0.058642f, + 1.572143f, 0.351608f, -0.052469f, + 1.527021f, 0.330678f, -0.050000f, + 1.513161f, 0.348582f, -0.090972f, + 1.534428f, 0.359845f, -0.084028f, + 1.542154f, 0.364077f, -0.075000f, + 1.535817f, 0.360886f, -0.065972f, + 1.514897f, 0.349884f, -0.059028f, + 1.478873f, 0.330678f, -0.056250f, + 1.436244f, 0.347485f, -0.080864f, + 1.457748f, 0.357839f, -0.074691f, + 1.469556f, 0.361538f, -0.066667f, + 1.470060f, 0.358379f, -0.058642f, + 1.457652f, 0.348160f, -0.052469f, + 1.430725f, 0.330678f, -0.050000f, + 1.377077f, 0.346641f, -0.050540f, + 1.398763f, 0.356295f, -0.046682f, + 1.413711f, 0.359584f, -0.041667f, + 1.419477f, 0.356450f, -0.036651f, + 1.413617f, 0.346834f, -0.032793f, + 1.393688f, 0.330678f, -0.031250f, + -0.021127f, 0.705678f, 0.000000f, + 0.118225f, 0.694220f, 0.000000f, + 0.160354f, 0.664011f, 0.000000f, + 0.141373f, 0.621303f, 0.000000f, + 0.097391f, 0.572345f, 0.000000f, + 0.064521f, 0.523386f, 0.000000f, + 0.078873f, 0.480678f, 0.000000f, + 0.113346f, 0.694220f, 0.037539f, + 0.154000f, 0.664011f, 0.048885f, + 0.135681f, 0.621303f, 0.043764f, + 0.093237f, 0.572345f, 0.031902f, + 0.061512f, 0.523386f, 0.023022f, + 0.075354f, 0.480678f, 0.026852f, + 0.099515f, 0.694220f, 0.070966f, + 0.135987f, 0.664011f, 0.092417f, + 0.119549f, 0.621303f, 0.082741f, + 0.081463f, 0.572345f, 0.060324f, + 0.052990f, 0.523386f, 0.043553f, + 0.065391f, 0.480678f, 0.050815f, + 0.077943f, 0.694220f, 0.099070f, + 0.107891f, 0.664011f, 0.129019f, + 0.094388f, 0.621303f, 0.115516f, + 0.063104f, 0.572345f, 0.084231f, + 0.039709f, 0.523386f, 0.060836f, + 0.049873f, 0.480678f, 0.071000f, + 0.049838f, 0.694220f, 0.120642f, + 0.071290f, 0.664011f, 0.157114f, + 0.061614f, 0.621303f, 0.140676f, + 0.039197f, 0.572345f, 0.102590f, + 0.022426f, 0.523386f, 0.074117f, + 0.029688f, 0.480678f, 0.086519f, + 0.016412f, 0.694220f, 0.134473f, + 0.027758f, 0.664011f, 0.175127f, + 0.022637f, 0.621303f, 0.156808f, + 0.010774f, 0.572345f, 0.114364f, + 0.001895f, 0.523386f, 0.082639f, + 0.005725f, 0.480678f, 0.096482f, + -0.021127f, 0.694220f, 0.139352f, + -0.021127f, 0.664011f, 0.181482f, + -0.021127f, 0.621303f, 0.162500f, + -0.021127f, 0.572345f, 0.118519f, + -0.021127f, 0.523386f, 0.085648f, + -0.021127f, 0.480678f, 0.100000f, + -0.058666f, 0.694220f, 0.134473f, + -0.070013f, 0.664011f, 0.175127f, + -0.064892f, 0.621303f, 0.156808f, + -0.053029f, 0.572345f, 0.114364f, + -0.044149f, 0.523386f, 0.082639f, + -0.047979f, 0.480678f, 0.096481f, + -0.092093f, 0.694220f, 0.120642f, + -0.113544f, 0.664011f, 0.157114f, + -0.103868f, 0.621303f, 0.140676f, + -0.081451f, 0.572345f, 0.102590f, + -0.064680f, 0.523386f, 0.074117f, + -0.071942f, 0.480678f, 0.086519f, + -0.120197f, 0.694220f, 0.099070f, + -0.150146f, 0.664011f, 0.129019f, + -0.136643f, 0.621303f, 0.115516f, + -0.105359f, 0.572345f, 0.084231f, + -0.081963f, 0.523386f, 0.060836f, + -0.092127f, 0.480678f, 0.071000f, + -0.141770f, 0.694220f, 0.070966f, + -0.178241f, 0.664011f, 0.092417f, + -0.161803f, 0.621303f, 0.082741f, + -0.123717f, 0.572345f, 0.060324f, + -0.095244f, 0.523386f, 0.043553f, + -0.107646f, 0.480678f, 0.050815f, + -0.155600f, 0.694220f, 0.037539f, + -0.196254f, 0.664011f, 0.048885f, + -0.177936f, 0.621303f, 0.043764f, + -0.135491f, 0.572345f, 0.031902f, + -0.103767f, 0.523386f, 0.023022f, + -0.117609f, 0.480678f, 0.026852f, + -0.160479f, 0.694220f, 0.000000f, + -0.202609f, 0.664011f, 0.000000f, + -0.183627f, 0.621303f, 0.000000f, + -0.139646f, 0.572345f, 0.000000f, + -0.106775f, 0.523386f, 0.000000f, + -0.121127f, 0.480678f, 0.000000f, + -0.155600f, 0.694220f, -0.037539f, + -0.196254f, 0.664011f, -0.048885f, + -0.177936f, 0.621303f, -0.043764f, + -0.135491f, 0.572345f, -0.031902f, + -0.103767f, 0.523386f, -0.023022f, + -0.117609f, 0.480678f, -0.026852f, + -0.141770f, 0.694220f, -0.070966f, + -0.178241f, 0.664011f, -0.092417f, + -0.161803f, 0.621303f, -0.082741f, + -0.123717f, 0.572345f, -0.060324f, + -0.095244f, 0.523386f, -0.043553f, + -0.107646f, 0.480678f, -0.050815f, + -0.120197f, 0.694220f, -0.099070f, + -0.150146f, 0.664011f, -0.129019f, + -0.136643f, 0.621303f, -0.115516f, + -0.105359f, 0.572345f, -0.084231f, + -0.081963f, 0.523386f, -0.060836f, + -0.092127f, 0.480678f, -0.071000f, + -0.092093f, 0.694220f, -0.120642f, + -0.113544f, 0.664011f, -0.157114f, + -0.103868f, 0.621303f, -0.140676f, + -0.081451f, 0.572345f, -0.102590f, + -0.064680f, 0.523386f, -0.074117f, + -0.071942f, 0.480678f, -0.086519f, + -0.058666f, 0.694220f, -0.134473f, + -0.070013f, 0.664011f, -0.175127f, + -0.064892f, 0.621303f, -0.156808f, + -0.053029f, 0.572345f, -0.114364f, + -0.044149f, 0.523386f, -0.082639f, + -0.047979f, 0.480678f, -0.096482f, + -0.021127f, 0.694220f, -0.139352f, + -0.021127f, 0.664011f, -0.181482f, + -0.021127f, 0.621303f, -0.162500f, + -0.021127f, 0.572345f, -0.118519f, + -0.021127f, 0.523386f, -0.085648f, + -0.021127f, 0.480678f, -0.100000f, + 0.016412f, 0.694220f, -0.134473f, + 0.027758f, 0.664011f, -0.175127f, + 0.022637f, 0.621303f, -0.156808f, + 0.010774f, 0.572345f, -0.114364f, + 0.001895f, 0.523386f, -0.082639f, + 0.005725f, 0.480678f, -0.096481f, + 0.049838f, 0.694220f, -0.120642f, + 0.071290f, 0.664011f, -0.157114f, + 0.061614f, 0.621303f, -0.140676f, + 0.039197f, 0.572345f, -0.102590f, + 0.022426f, 0.523386f, -0.074117f, + 0.029688f, 0.480678f, -0.086519f, + 0.077943f, 0.694220f, -0.099070f, + 0.107891f, 0.664011f, -0.129019f, + 0.094388f, 0.621303f, -0.115516f, + 0.063104f, 0.572345f, -0.084231f, + 0.039709f, 0.523386f, -0.060836f, + 0.049873f, 0.480678f, -0.071000f, + 0.099515f, 0.694220f, -0.070966f, + 0.135987f, 0.664011f, -0.092417f, + 0.119549f, 0.621303f, -0.082741f, + 0.081463f, 0.572345f, -0.060324f, + 0.052990f, 0.523386f, -0.043553f, + 0.065391f, 0.480678f, -0.050815f, + 0.113346f, 0.694220f, -0.037539f, + 0.154000f, 0.664011f, -0.048885f, + 0.135681f, 0.621303f, -0.043764f, + 0.093237f, 0.572345f, -0.031902f, + 0.061512f, 0.523386f, -0.023022f, + 0.075354f, 0.480678f, -0.026852f, + 0.154336f, 0.448734f, 0.000000f, + 0.265910f, 0.425123f, 0.000000f, + 0.391373f, 0.405678f, 0.000000f, + 0.508502f, 0.386234f, 0.000000f, + 0.595077f, 0.362623f, 0.000000f, + 0.628873f, 0.330678f, 0.000000f, + 0.148162f, 0.448734f, 0.047115f, + 0.255810f, 0.425123f, 0.077075f, + 0.376859f, 0.405678f, 0.110764f, + 0.489867f, 0.386234f, 0.142215f, + 0.573395f, 0.362623f, 0.165462f, + 0.606002f, 0.330678f, 0.174537f, + 0.130681f, 0.448734f, 0.089161f, + 0.227213f, 0.425123f, 0.145857f, + 0.335762f, 0.405678f, 0.209611f, + 0.437101f, 0.386234f, 0.269130f, + 0.512003f, 0.362623f, 0.313123f, + 0.541243f, 0.330678f, 0.330296f, + 0.103451f, 0.448734f, 0.124579f, + 0.182669f, 0.425123f, 0.203796f, + 0.271748f, 0.405678f, 0.292875f, + 0.354910f, 0.386234f, 0.376037f, + 0.416377f, 0.362623f, 0.437505f, + 0.440373f, 0.330678f, 0.461500f, + 0.068034f, 0.448734f, 0.151808f, + 0.124730f, 0.425123f, 0.248340f, + 0.188484f, 0.405678f, 0.356889f, + 0.248003f, 0.386234f, 0.458228f, + 0.291995f, 0.362623f, 0.533130f, + 0.309169f, 0.330678f, 0.562370f, + 0.025988f, 0.448734f, 0.169289f, + 0.055948f, 0.425123f, 0.276938f, + 0.089637f, 0.405678f, 0.397986f, + 0.121088f, 0.386234f, 0.510995f, + 0.144335f, 0.362623f, 0.594523f, + 0.153410f, 0.330678f, 0.627130f, + -0.021127f, 0.448734f, 0.175463f, + -0.021127f, 0.425123f, 0.287037f, + -0.021127f, 0.405678f, 0.412500f, + -0.021127f, 0.386234f, 0.529630f, + -0.021127f, 0.362623f, 0.616204f, + -0.021127f, 0.330678f, 0.650000f, + -0.068242f, 0.448734f, 0.169289f, + -0.098202f, 0.425123f, 0.276938f, + -0.131891f, 0.405678f, 0.397986f, + -0.163343f, 0.386234f, 0.510995f, + -0.186589f, 0.362623f, 0.594523f, + -0.195664f, 0.330678f, 0.627130f, + -0.110288f, 0.448734f, 0.151808f, + -0.166985f, 0.425123f, 0.248340f, + -0.230738f, 0.405678f, 0.356889f, + -0.290258f, 0.386234f, 0.458228f, + -0.334250f, 0.362623f, 0.533130f, + -0.351424f, 0.330678f, 0.562370f, + -0.145706f, 0.448734f, 0.124579f, + -0.224924f, 0.425123f, 0.203796f, + -0.314002f, 0.405678f, 0.292875f, + -0.397164f, 0.386234f, 0.376037f, + -0.458632f, 0.362623f, 0.437505f, + -0.482627f, 0.330678f, 0.461500f, + -0.172935f, 0.448734f, 0.089161f, + -0.269467f, 0.425123f, 0.145857f, + -0.378016f, 0.405678f, 0.209611f, + -0.479355f, 0.386234f, 0.269130f, + -0.554258f, 0.362623f, 0.313123f, + -0.583498f, 0.330678f, 0.330296f, + -0.190416f, 0.448734f, 0.047115f, + -0.298065f, 0.425123f, 0.077075f, + -0.419113f, 0.405678f, 0.110764f, + -0.532122f, 0.386234f, 0.142215f, + -0.615650f, 0.362623f, 0.165462f, + -0.648257f, 0.330678f, 0.174537f, + -0.196590f, 0.448734f, 0.000000f, + -0.308164f, 0.425123f, 0.000000f, + -0.433627f, 0.405678f, 0.000000f, + -0.550757f, 0.386234f, 0.000000f, + -0.637331f, 0.362623f, 0.000000f, + -0.671127f, 0.330678f, 0.000000f, + -0.190416f, 0.448734f, -0.047115f, + -0.298065f, 0.425123f, -0.077075f, + -0.419113f, 0.405678f, -0.110764f, + -0.532122f, 0.386234f, -0.142215f, + -0.615650f, 0.362623f, -0.165462f, + -0.648257f, 0.330678f, -0.174537f, + -0.172935f, 0.448734f, -0.089161f, + -0.269467f, 0.425123f, -0.145857f, + -0.378016f, 0.405678f, -0.209611f, + -0.479355f, 0.386234f, -0.269130f, + -0.554258f, 0.362623f, -0.313123f, + -0.583498f, 0.330678f, -0.330296f, + -0.145706f, 0.448734f, -0.124579f, + -0.224924f, 0.425123f, -0.203796f, + -0.314002f, 0.405678f, -0.292875f, + -0.397164f, 0.386234f, -0.376037f, + -0.458632f, 0.362623f, -0.437505f, + -0.482627f, 0.330678f, -0.461500f, + -0.110288f, 0.448734f, -0.151808f, + -0.166985f, 0.425123f, -0.248340f, + -0.230738f, 0.405678f, -0.356889f, + -0.290258f, 0.386234f, -0.458228f, + -0.334250f, 0.362623f, -0.533130f, + -0.351424f, 0.330678f, -0.562370f, + -0.068242f, 0.448734f, -0.169289f, + -0.098202f, 0.425123f, -0.276938f, + -0.131891f, 0.405678f, -0.397986f, + -0.163343f, 0.386234f, -0.510995f, + -0.186589f, 0.362623f, -0.594523f, + -0.195664f, 0.330678f, -0.627130f, + -0.021127f, 0.448734f, -0.175463f, + -0.021127f, 0.425123f, -0.287037f, + -0.021127f, 0.405678f, -0.412500f, + -0.021127f, 0.386234f, -0.529630f, + -0.021127f, 0.362623f, -0.616204f, + -0.021127f, 0.330678f, -0.650000f, + 0.025988f, 0.448734f, -0.169289f, + 0.055948f, 0.425123f, -0.276938f, + 0.089637f, 0.405678f, -0.397986f, + 0.121088f, 0.386234f, -0.510995f, + 0.144335f, 0.362623f, -0.594523f, + 0.153410f, 0.330678f, -0.627130f, + 0.068034f, 0.448734f, -0.151808f, + 0.124730f, 0.425123f, -0.248340f, + 0.188484f, 0.405678f, -0.356889f, + 0.248003f, 0.386234f, -0.458228f, + 0.291996f, 0.362623f, -0.533130f, + 0.309169f, 0.330678f, -0.562370f, + 0.103451f, 0.448734f, -0.124579f, + 0.182669f, 0.425123f, -0.203796f, + 0.271748f, 0.405678f, -0.292875f, + 0.354910f, 0.386234f, -0.376037f, + 0.416377f, 0.362623f, -0.437505f, + 0.440373f, 0.330678f, -0.461500f, + 0.130681f, 0.448734f, -0.089161f, + 0.227213f, 0.425123f, -0.145857f, + 0.335762f, 0.405678f, -0.209611f, + 0.437101f, 0.386234f, -0.269130f, + 0.512003f, 0.362623f, -0.313123f, + 0.541243f, 0.330678f, -0.330296f, + 0.148162f, 0.448734f, -0.047115f, + 0.255810f, 0.425123f, -0.077075f, + 0.376859f, 0.405678f, -0.110764f, + 0.489867f, 0.386234f, -0.142215f, + 0.573395f, 0.362623f, -0.165462f, + 0.606002f, 0.330678f, -0.174537f, +}; +static D3DXVECTOR3* teapotPositions = ( D3DXVECTOR3* )teapotPositionsFloats; + +static float teapotNormalsfloats[NUMTEAPOTVERTICES*3] = +{ + -0.945751f, -0.322256f, -0.041309f, + -0.992771f, -0.120019f, -0.001089f, + -0.842751f, 0.538169f, 0.012052f, + -0.083588f, 0.996288f, 0.020560f, + 0.532170f, 0.846603f, 0.007614f, + 0.779300f, 0.626641f, 0.003491f, + 0.879896f, 0.475165f, 0.001103f, + -0.902413f, -0.322783f, -0.285416f, + -0.958558f, -0.120097f, -0.258348f, + -0.816875f, 0.538579f, -0.206514f, + -0.086190f, 0.996277f, -0.001604f, + 0.511484f, 0.846942f, 0.145167f, + 0.751363f, 0.627164f, 0.205227f, + 0.849281f, 0.475682f, 0.229015f, + -0.797449f, -0.323303f, -0.509461f, + -0.858625f, -0.120328f, -0.498282f, + -0.735017f, 0.538957f, -0.411431f, + -0.082580f, 0.996294f, -0.024043f, + 0.455735f, 0.847352f, 0.272581f, + 0.671856f, 0.627868f, 0.392927f, + 0.760399f, 0.476384f, 0.441420f, + -0.639341f, -0.323439f, -0.697589f, + -0.701183f, -0.120461f, -0.702731f, + -0.604040f, 0.539064f, -0.586980f, + -0.073399f, 0.996309f, -0.044511f, + 0.369925f, 0.847499f, 0.380659f, + 0.547722f, 0.628143f, 0.552663f, + 0.620826f, 0.476660f, 0.622391f, + -0.437782f, -0.323142f, -0.839003f, + -0.496373f, -0.120437f, -0.859715f, + -0.432443f, 0.538876f, -0.722914f, + -0.059523f, 0.996312f, -0.061801f, + 0.259388f, 0.847326f, 0.463418f, + 0.386844f, 0.627880f, 0.675366f, + 0.439492f, 0.476398f, 0.761506f, + -0.204681f, -0.322547f, -0.924159f, + -0.256209f, -0.120257f, -0.959112f, + -0.230122f, 0.538458f, -0.810621f, + -0.041668f, 0.996304f, -0.075119f, + 0.130300f, 0.846904f, 0.515534f, + 0.198391f, 0.627182f, 0.753183f, + 0.226852f, 0.475703f, 0.849850f, + 0.035941f, -0.330214f, -0.943221f, + -0.001376f, -0.125569f, -0.992084f, + -0.012701f, 0.535792f, -0.844254f, + -0.020672f, 0.996343f, -0.082901f, + -0.007571f, 0.846427f, 0.532451f, + -0.003482f, 0.626608f, 0.779327f, + -0.001103f, 0.475165f, 0.879896f, + 0.269574f, -0.386954f, -0.881814f, + 0.249993f, -0.181783f, -0.951030f, + 0.211872f, 0.499984f, -0.839718f, + 0.002768f, 0.995768f, -0.091859f, + -0.146446f, 0.844150f, 0.515718f, + -0.205497f, 0.625909f, 0.752335f, + -0.229034f, 0.475536f, 0.849358f, + 0.482854f, -0.445924f, -0.753661f, + 0.483883f, -0.261599f, -0.835118f, + 0.442338f, 0.434016f, -0.784836f, + 0.036680f, 0.993502f, -0.107746f, + -0.278510f, 0.839949f, 0.465746f, + -0.394390f, 0.624142f, 0.674465f, + -0.441541f, 0.475913f, 0.760624f, + 0.669165f, -0.453044f, -0.589041f, + 0.686401f, -0.287530f, -0.667967f, + 0.643212f, 0.404496f, -0.650124f, + 0.074604f, 0.991460f, -0.106959f, + -0.391289f, 0.837987f, 0.380356f, + -0.555484f, 0.623132f, 0.550586f, + -0.622636f, 0.476008f, 0.621080f, + 0.821788f, -0.407716f, -0.398036f, + 0.849894f, -0.244430f, -0.466834f, + 0.778095f, 0.435804f, -0.452374f, + 0.095458f, 0.992115f, -0.081218f, + -0.473659f, 0.839871f, 0.265074f, + -0.678265f, 0.623724f, 0.388490f, + -0.761768f, 0.475842f, 0.439641f, + 0.919150f, -0.348512f, -0.183583f, + 0.956218f, -0.171139f, -0.237398f, + 0.838823f, 0.493898f, -0.229000f, + 0.094322f, 0.994404f, -0.047578f, + -0.520640f, 0.843596f, 0.131452f, + -0.754753f, 0.625180f, 0.198741f, + -0.849997f, 0.475426f, 0.226882f, + 0.945537f, -0.322183f, 0.046446f, + 0.991881f, -0.126966f, 0.007216f, + 0.847572f, 0.530605f, -0.008996f, + 0.087879f, 0.995918f, -0.020615f, + -0.533063f, 0.846041f, -0.007711f, + -0.779612f, 0.626253f, -0.003532f, + -0.879926f, 0.475109f, -0.001109f, + 0.902413f, -0.322783f, 0.285416f, + 0.958558f, -0.120097f, 0.258348f, + 0.816875f, 0.538579f, 0.206514f, + 0.086190f, 0.996277f, 0.001604f, + -0.511484f, 0.846942f, -0.145167f, + -0.751363f, 0.627164f, -0.205227f, + -0.849281f, 0.475682f, -0.229015f, + 0.797449f, -0.323303f, 0.509461f, + 0.858625f, -0.120328f, 0.498282f, + 0.735017f, 0.538957f, 0.411431f, + 0.082580f, 0.996294f, 0.024043f, + -0.455735f, 0.847352f, -0.272581f, + -0.671856f, 0.627868f, -0.392927f, + -0.760399f, 0.476384f, -0.441420f, + 0.639341f, -0.323439f, 0.697589f, + 0.701183f, -0.120461f, 0.702731f, + 0.604040f, 0.539064f, 0.586980f, + 0.073399f, 0.996309f, 0.044511f, + -0.369925f, 0.847499f, -0.380659f, + -0.547722f, 0.628143f, -0.552663f, + -0.620826f, 0.476660f, -0.622391f, + 0.437782f, -0.323142f, 0.839003f, + 0.496373f, -0.120437f, 0.859715f, + 0.432443f, 0.538876f, 0.722914f, + 0.059523f, 0.996312f, 0.061801f, + -0.259388f, 0.847326f, -0.463418f, + -0.386844f, 0.627880f, -0.675366f, + -0.439492f, 0.476398f, -0.761506f, + 0.204681f, -0.322547f, 0.924159f, + 0.256209f, -0.120257f, 0.959112f, + 0.230122f, 0.538458f, 0.810621f, + 0.041668f, 0.996304f, 0.075119f, + -0.130300f, 0.846904f, -0.515534f, + -0.198391f, 0.627182f, -0.753183f, + -0.226852f, 0.475703f, -0.849850f, + -0.041309f, -0.322256f, 0.945751f, + -0.001089f, -0.120019f, 0.992771f, + 0.012052f, 0.538169f, 0.842751f, + 0.020560f, 0.996288f, 0.083588f, + 0.007614f, 0.846603f, -0.532170f, + 0.003491f, 0.626641f, -0.779300f, + 0.001103f, 0.475165f, -0.879896f, + -0.285416f, -0.322783f, 0.902413f, + -0.258348f, -0.120097f, 0.958558f, + -0.206514f, 0.538579f, 0.816875f, + -0.001604f, 0.996277f, 0.086190f, + 0.145167f, 0.846942f, -0.511484f, + 0.205227f, 0.627164f, -0.751363f, + 0.229015f, 0.475682f, -0.849281f, + -0.509461f, -0.323303f, 0.797449f, + -0.498282f, -0.120328f, 0.858625f, + -0.411431f, 0.538957f, 0.735017f, + -0.024043f, 0.996294f, 0.082580f, + 0.272581f, 0.847352f, -0.455735f, + 0.392927f, 0.627868f, -0.671856f, + 0.441420f, 0.476384f, -0.760399f, + -0.697589f, -0.323439f, 0.639341f, + -0.702731f, -0.120461f, 0.701183f, + -0.586980f, 0.539064f, 0.604040f, + -0.044511f, 0.996309f, 0.073399f, + 0.380659f, 0.847499f, -0.369925f, + 0.552663f, 0.628143f, -0.547722f, + 0.622391f, 0.476660f, -0.620826f, + -0.839003f, -0.323142f, 0.437782f, + -0.859715f, -0.120437f, 0.496373f, + -0.722914f, 0.538876f, 0.432443f, + -0.061801f, 0.996312f, 0.059523f, + 0.463418f, 0.847326f, -0.259388f, + 0.675366f, 0.627880f, -0.386844f, + 0.761506f, 0.476398f, -0.439492f, + -0.924159f, -0.322547f, 0.204681f, + -0.959112f, -0.120257f, 0.256209f, + -0.810621f, 0.538458f, 0.230122f, + -0.075119f, 0.996304f, 0.041668f, + 0.515534f, 0.846904f, -0.130300f, + 0.753183f, 0.627182f, -0.198391f, + 0.849850f, 0.475703f, -0.226852f, + 0.908180f, 0.418579f, 0.000170f, + 0.920061f, 0.391776f, 0.000335f, + 0.939254f, 0.343222f, 0.000478f, + 0.963807f, 0.266599f, 0.000552f, + 0.988261f, 0.152772f, 0.000449f, + 0.998933f, -0.046187f, -0.000262f, + 0.876892f, 0.419073f, 0.235451f, + 0.888349f, 0.392247f, 0.238702f, + 0.906891f, 0.343648f, 0.243832f, + 0.930644f, 0.266938f, 0.250291f, + 0.954351f, 0.152959f, 0.256551f, + 0.964867f, -0.046304f, 0.258627f, + 0.785456f, 0.419734f, 0.454843f, + 0.795707f, 0.392883f, 0.460971f, + 0.812334f, 0.344228f, 0.470766f, + 0.833667f, 0.267414f, 0.483207f, + 0.855012f, 0.153250f, 0.495448f, + 0.864663f, -0.046372f, 0.500207f, + 0.641599f, 0.419990f, 0.641841f, + 0.649935f, 0.393130f, 0.650410f, + 0.663494f, 0.344457f, 0.664173f, + 0.680925f, 0.267607f, 0.681710f, + 0.698421f, 0.153377f, 0.699059f, + 0.706532f, -0.046369f, 0.706160f, + 0.454545f, 0.419737f, 0.785627f, + 0.460384f, 0.392890f, 0.796043f, + 0.469929f, 0.344241f, 0.812813f, + 0.482239f, 0.267436f, 0.834220f, + 0.494660f, 0.153286f, 0.855462f, + 0.500666f, -0.046300f, 0.864402f, + 0.235117f, 0.419078f, 0.876980f, + 0.238044f, 0.392258f, 0.888521f, + 0.242894f, 0.343667f, 0.907136f, + 0.249206f, 0.266970f, 0.930926f, + 0.255668f, 0.153012f, 0.954579f, + 0.259142f, -0.046198f, 0.964734f, + -0.000170f, 0.418579f, 0.908181f, + -0.000335f, 0.391776f, 0.920061f, + -0.000478f, 0.343222f, 0.939254f, + -0.000552f, 0.266599f, 0.963807f, + -0.000449f, 0.152772f, 0.988261f, + 0.000262f, -0.046187f, 0.998933f, + -0.235451f, 0.419073f, 0.876892f, + -0.238702f, 0.392247f, 0.888349f, + -0.243832f, 0.343648f, 0.906891f, + -0.250291f, 0.266938f, 0.930644f, + -0.256551f, 0.152959f, 0.954351f, + -0.258627f, -0.046304f, 0.964867f, + -0.454843f, 0.419734f, 0.785456f, + -0.460971f, 0.392883f, 0.795707f, + -0.470766f, 0.344228f, 0.812334f, + -0.483207f, 0.267414f, 0.833667f, + -0.495448f, 0.153250f, 0.855012f, + -0.500207f, -0.046372f, 0.864663f, + -0.641841f, 0.419990f, 0.641599f, + -0.650410f, 0.393130f, 0.649935f, + -0.664173f, 0.344457f, 0.663494f, + -0.681710f, 0.267607f, 0.680925f, + -0.699059f, 0.153377f, 0.698421f, + -0.706160f, -0.046369f, 0.706532f, + -0.785627f, 0.419737f, 0.454545f, + -0.796043f, 0.392890f, 0.460384f, + -0.812813f, 0.344241f, 0.469929f, + -0.834220f, 0.267436f, 0.482239f, + -0.855462f, 0.153286f, 0.494660f, + -0.864402f, -0.046300f, 0.500666f, + -0.876980f, 0.419078f, 0.235117f, + -0.888521f, 0.392258f, 0.238044f, + -0.907136f, 0.343667f, 0.242894f, + -0.930926f, 0.266970f, 0.249206f, + -0.954579f, 0.153012f, 0.255668f, + -0.964734f, -0.046198f, 0.259142f, + -0.908181f, 0.418579f, -0.000170f, + -0.920061f, 0.391776f, -0.000335f, + -0.939254f, 0.343222f, -0.000478f, + -0.963807f, 0.266599f, -0.000552f, + -0.988261f, 0.152772f, -0.000449f, + -0.998933f, -0.046187f, 0.000262f, + -0.876892f, 0.419073f, -0.235451f, + -0.888349f, 0.392247f, -0.238702f, + -0.906891f, 0.343648f, -0.243832f, + -0.930644f, 0.266938f, -0.250291f, + -0.954351f, 0.152959f, -0.256551f, + -0.964867f, -0.046304f, -0.258627f, + -0.785456f, 0.419734f, -0.454843f, + -0.795707f, 0.392883f, -0.460971f, + -0.812334f, 0.344228f, -0.470766f, + -0.833667f, 0.267414f, -0.483207f, + -0.855012f, 0.153250f, -0.495448f, + -0.864663f, -0.046372f, -0.500207f, + -0.641599f, 0.419990f, -0.641841f, + -0.649935f, 0.393130f, -0.650410f, + -0.663494f, 0.344457f, -0.664173f, + -0.680925f, 0.267607f, -0.681710f, + -0.698421f, 0.153377f, -0.699059f, + -0.706532f, -0.046369f, -0.706160f, + -0.454545f, 0.419737f, -0.785627f, + -0.460384f, 0.392890f, -0.796043f, + -0.469929f, 0.344241f, -0.812813f, + -0.482239f, 0.267436f, -0.834220f, + -0.494660f, 0.153286f, -0.855462f, + -0.500666f, -0.046300f, -0.864402f, + -0.235117f, 0.419078f, -0.876980f, + -0.238044f, 0.392258f, -0.888521f, + -0.242894f, 0.343667f, -0.907136f, + -0.249206f, 0.266970f, -0.930926f, + -0.255668f, 0.153012f, -0.954579f, + -0.259142f, -0.046198f, -0.964734f, + 0.000170f, 0.418579f, -0.908181f, + 0.000335f, 0.391776f, -0.920061f, + 0.000478f, 0.343222f, -0.939254f, + 0.000552f, 0.266599f, -0.963807f, + 0.000449f, 0.152772f, -0.988261f, + -0.000262f, -0.046187f, -0.998933f, + 0.235451f, 0.419073f, -0.876892f, + 0.238702f, 0.392247f, -0.888349f, + 0.243832f, 0.343648f, -0.906891f, + 0.250291f, 0.266938f, -0.930644f, + 0.256551f, 0.152959f, -0.954351f, + 0.258627f, -0.046304f, -0.964867f, + 0.454843f, 0.419734f, -0.785456f, + 0.460971f, 0.392883f, -0.795707f, + 0.470766f, 0.344228f, -0.812334f, + 0.483207f, 0.267414f, -0.833667f, + 0.495448f, 0.153250f, -0.855012f, + 0.500207f, -0.046372f, -0.864663f, + 0.641841f, 0.419990f, -0.641599f, + 0.650410f, 0.393130f, -0.649935f, + 0.664173f, 0.344457f, -0.663494f, + 0.681710f, 0.267607f, -0.680925f, + 0.699059f, 0.153377f, -0.698421f, + 0.706160f, -0.046369f, -0.706532f, + 0.785627f, 0.419737f, -0.454545f, + 0.796043f, 0.392890f, -0.460384f, + 0.812813f, 0.344241f, -0.469929f, + 0.834220f, 0.267436f, -0.482239f, + 0.855462f, 0.153286f, -0.494660f, + 0.864402f, -0.046300f, -0.500666f, + 0.876980f, 0.419078f, -0.235117f, + 0.888521f, 0.392258f, -0.238044f, + 0.907136f, 0.343667f, -0.242894f, + 0.930926f, 0.266970f, -0.249206f, + 0.954579f, 0.153012f, -0.255668f, + 0.964734f, -0.046198f, -0.259142f, + 0.943833f, -0.330414f, -0.002283f, + 0.821403f, -0.570341f, -0.002745f, + 0.709541f, -0.704661f, -0.001958f, + 0.652305f, -0.757957f, -0.000466f, + 0.728669f, -0.684856f, 0.003576f, + 0.889124f, -0.457656f, 0.003164f, + 0.912037f, -0.330868f, 0.242313f, + 0.793697f, -0.570897f, 0.210051f, + 0.685340f, -0.705168f, 0.181787f, + 0.629635f, -0.758420f, 0.168401f, + 0.702387f, -0.685364f, 0.192168f, + 0.857690f, -0.458122f, 0.233435f, + 0.817716f, -0.331385f, 0.470664f, + 0.711528f, -0.571608f, 0.408646f, + 0.614071f, -0.705839f, 0.353140f, + 0.563713f, -0.759034f, 0.325721f, + 0.627891f, -0.686037f, 0.367569f, + 0.767411f, -0.458787f, 0.447879f, + 0.668728f, -0.331557f, 0.665486f, + 0.582010f, -0.571874f, 0.578122f, + 0.502096f, -0.706097f, 0.499327f, + 0.460496f, -0.759271f, 0.459838f, + 0.511760f, -0.686297f, 0.516816f, + 0.625950f, -0.459060f, 0.630437f, + 0.474660f, -0.331321f, 0.815429f, + 0.413434f, -0.571590f, 0.708771f, + 0.356547f, -0.705839f, 0.612100f, + 0.326530f, -0.759035f, 0.563244f, + 0.361346f, -0.686040f, 0.631489f, + 0.442349f, -0.458832f, 0.770585f, + 0.246794f, -0.330773f, 0.910869f, + 0.215429f, -0.570870f, 0.792274f, + 0.185619f, -0.705168f, 0.684313f, + 0.169311f, -0.758421f, 0.629390f, + 0.185170f, -0.685368f, 0.704260f, + 0.227231f, -0.458188f, 0.859319f, + 0.002283f, -0.330414f, 0.943833f, + 0.002745f, -0.570341f, 0.821403f, + 0.001958f, -0.704661f, 0.709541f, + 0.000466f, -0.757957f, 0.652305f, + -0.003576f, -0.684856f, 0.728669f, + -0.003164f, -0.457656f, 0.889124f, + -0.242313f, -0.330868f, 0.912037f, + -0.210051f, -0.570897f, 0.793697f, + -0.181787f, -0.705168f, 0.685340f, + -0.168401f, -0.758420f, 0.629635f, + -0.192168f, -0.685364f, 0.702387f, + -0.233435f, -0.458122f, 0.857690f, + -0.470664f, -0.331385f, 0.817716f, + -0.408646f, -0.571608f, 0.711528f, + -0.353140f, -0.705839f, 0.614071f, + -0.325721f, -0.759034f, 0.563713f, + -0.367569f, -0.686037f, 0.627891f, + -0.447879f, -0.458787f, 0.767411f, + -0.665486f, -0.331557f, 0.668728f, + -0.578122f, -0.571874f, 0.582010f, + -0.499327f, -0.706097f, 0.502096f, + -0.459838f, -0.759271f, 0.460496f, + -0.516816f, -0.686297f, 0.511760f, + -0.630437f, -0.459060f, 0.625950f, + -0.815429f, -0.331321f, 0.474660f, + -0.708771f, -0.571590f, 0.413434f, + -0.612100f, -0.705839f, 0.356547f, + -0.563244f, -0.759035f, 0.326530f, + -0.631489f, -0.686040f, 0.361346f, + -0.770585f, -0.458832f, 0.442349f, + -0.910869f, -0.330773f, 0.246794f, + -0.792274f, -0.570870f, 0.215429f, + -0.684313f, -0.705168f, 0.185619f, + -0.629390f, -0.758421f, 0.169311f, + -0.704260f, -0.685368f, 0.185170f, + -0.859319f, -0.458188f, 0.227231f, + -0.943833f, -0.330414f, 0.002283f, + -0.821403f, -0.570341f, 0.002745f, + -0.709541f, -0.704661f, 0.001958f, + -0.652305f, -0.757957f, 0.000466f, + -0.728669f, -0.684856f, -0.003576f, + -0.889124f, -0.457656f, -0.003164f, + -0.912037f, -0.330868f, -0.242313f, + -0.793697f, -0.570897f, -0.210051f, + -0.685340f, -0.705168f, -0.181787f, + -0.629635f, -0.758420f, -0.168401f, + -0.702387f, -0.685364f, -0.192168f, + -0.857690f, -0.458122f, -0.233435f, + -0.817716f, -0.331385f, -0.470664f, + -0.711528f, -0.571608f, -0.408646f, + -0.614071f, -0.705839f, -0.353140f, + -0.563713f, -0.759034f, -0.325721f, + -0.627891f, -0.686037f, -0.367569f, + -0.767411f, -0.458787f, -0.447879f, + -0.668728f, -0.331557f, -0.665486f, + -0.582010f, -0.571874f, -0.578122f, + -0.502096f, -0.706097f, -0.499327f, + -0.460496f, -0.759271f, -0.459838f, + -0.511760f, -0.686297f, -0.516816f, + -0.625950f, -0.459060f, -0.630437f, + -0.474660f, -0.331321f, -0.815429f, + -0.413434f, -0.571590f, -0.708771f, + -0.356547f, -0.705839f, -0.612100f, + -0.326530f, -0.759035f, -0.563244f, + -0.361346f, -0.686040f, -0.631489f, + -0.442349f, -0.458832f, -0.770585f, + -0.246794f, -0.330773f, -0.910869f, + -0.215429f, -0.570870f, -0.792274f, + -0.185619f, -0.705168f, -0.684313f, + -0.169311f, -0.758421f, -0.629390f, + -0.185170f, -0.685368f, -0.704260f, + -0.227231f, -0.458188f, -0.859319f, + -0.002283f, -0.330414f, -0.943833f, + -0.002745f, -0.570341f, -0.821403f, + -0.001958f, -0.704661f, -0.709541f, + -0.000466f, -0.757957f, -0.652305f, + 0.003576f, -0.684856f, -0.728669f, + 0.003164f, -0.457656f, -0.889124f, + 0.242313f, -0.330868f, -0.912037f, + 0.210051f, -0.570897f, -0.793697f, + 0.181787f, -0.705168f, -0.685340f, + 0.168401f, -0.758420f, -0.629635f, + 0.192168f, -0.685364f, -0.702387f, + 0.233435f, -0.458122f, -0.857690f, + 0.470664f, -0.331385f, -0.817716f, + 0.408646f, -0.571608f, -0.711528f, + 0.353140f, -0.705839f, -0.614071f, + 0.325721f, -0.759034f, -0.563713f, + 0.367569f, -0.686037f, -0.627891f, + 0.447879f, -0.458787f, -0.767411f, + 0.665486f, -0.331557f, -0.668728f, + 0.578122f, -0.571874f, -0.582010f, + 0.499327f, -0.706097f, -0.502096f, + 0.459838f, -0.759271f, -0.460496f, + 0.516816f, -0.686297f, -0.511760f, + 0.630437f, -0.459060f, -0.625950f, + 0.815429f, -0.331321f, -0.474660f, + 0.708771f, -0.571590f, -0.413434f, + 0.612100f, -0.705839f, -0.356547f, + 0.563244f, -0.759035f, -0.326530f, + 0.631489f, -0.686040f, -0.361346f, + 0.770585f, -0.458832f, -0.442349f, + 0.910869f, -0.330773f, -0.246794f, + 0.792274f, -0.570870f, -0.215429f, + 0.684313f, -0.705168f, -0.185619f, + 0.629390f, -0.758421f, -0.169311f, + 0.704260f, -0.685368f, -0.185170f, + 0.859319f, -0.458188f, -0.227231f, + 0.777345f, -0.628990f, -0.010332f, + 0.361793f, -0.932236f, -0.006477f, + 0.152402f, -0.988315f, -0.002559f, + 0.066422f, -0.997791f, -0.001190f, + 0.027401f, -0.999624f, -0.001027f, + 0.000000f, -1.000000f, 0.000000f, + 0.753154f, -0.629440f, 0.191218f, + 0.350766f, -0.932386f, 0.087291f, + 0.147688f, -0.988344f, 0.036926f, + 0.064386f, -0.997796f, 0.016021f, + 0.026706f, -0.999625f, 0.006087f, + 0.677297f, -0.629962f, 0.380023f, + 0.315543f, -0.932612f, 0.175124f, + 0.132774f, -0.988389f, 0.073881f, + 0.057900f, -0.997805f, 0.032133f, + 0.024157f, -0.999626f, 0.012794f, + 0.556310f, -0.630147f, 0.541695f, + 0.259523f, -0.932707f, 0.250409f, + 0.109137f, -0.988408f, 0.105540f, + 0.047613f, -0.997809f, 0.045941f, + 0.020018f, -0.999627f, 0.018575f, + 0.398014f, -0.629932f, 0.666911f, + 0.186318f, -0.932635f, 0.308995f, + 0.078296f, -0.988394f, 0.130182f, + 0.034185f, -0.997806f, 0.056696f, + 0.014564f, -0.999627f, 0.023117f, + 0.211443f, -0.629395f, 0.747766f, + 0.099921f, -0.932420f, 0.347287f, + 0.041912f, -0.988352f, 0.146303f, + 0.018338f, -0.997798f, 0.063741f, + 0.008087f, -0.999625f, 0.026150f, + 0.010332f, -0.628990f, 0.777345f, + 0.006477f, -0.932236f, 0.361793f, + 0.002559f, -0.988315f, 0.152402f, + 0.001190f, -0.997791f, 0.066422f, + 0.001027f, -0.999624f, 0.027401f, + -0.191218f, -0.629440f, 0.753154f, + -0.087291f, -0.932386f, 0.350766f, + -0.036926f, -0.988344f, 0.147688f, + -0.016021f, -0.997796f, 0.064386f, + -0.006087f, -0.999625f, 0.026706f, + -0.380023f, -0.629962f, 0.677297f, + -0.175124f, -0.932612f, 0.315543f, + -0.073881f, -0.988389f, 0.132774f, + -0.032133f, -0.997805f, 0.057900f, + -0.012794f, -0.999626f, 0.024157f, + -0.541695f, -0.630147f, 0.556310f, + -0.250409f, -0.932707f, 0.259523f, + -0.105540f, -0.988408f, 0.109137f, + -0.045941f, -0.997809f, 0.047613f, + -0.018575f, -0.999627f, 0.020018f, + -0.666911f, -0.629932f, 0.398014f, + -0.308995f, -0.932635f, 0.186318f, + -0.130182f, -0.988394f, 0.078296f, + -0.056696f, -0.997806f, 0.034185f, + -0.023117f, -0.999627f, 0.014564f, + -0.747766f, -0.629395f, 0.211443f, + -0.347287f, -0.932420f, 0.099921f, + -0.146303f, -0.988352f, 0.041912f, + -0.063741f, -0.997798f, 0.018338f, + -0.026150f, -0.999625f, 0.008087f, + -0.777345f, -0.628990f, 0.010332f, + -0.361793f, -0.932236f, 0.006477f, + -0.152402f, -0.988315f, 0.002559f, + -0.066422f, -0.997791f, 0.001190f, + -0.027401f, -0.999624f, 0.001027f, + -0.753154f, -0.629440f, -0.191218f, + -0.350766f, -0.932386f, -0.087291f, + -0.147688f, -0.988344f, -0.036926f, + -0.064386f, -0.997796f, -0.016021f, + -0.026706f, -0.999625f, -0.006087f, + -0.677297f, -0.629962f, -0.380023f, + -0.315543f, -0.932612f, -0.175124f, + -0.132774f, -0.988389f, -0.073881f, + -0.057900f, -0.997805f, -0.032133f, + -0.024157f, -0.999626f, -0.012794f, + -0.556310f, -0.630147f, -0.541695f, + -0.259523f, -0.932707f, -0.250409f, + -0.109137f, -0.988408f, -0.105540f, + -0.047613f, -0.997809f, -0.045941f, + -0.020018f, -0.999627f, -0.018575f, + -0.398014f, -0.629932f, -0.666911f, + -0.186318f, -0.932635f, -0.308995f, + -0.078296f, -0.988394f, -0.130182f, + -0.034185f, -0.997806f, -0.056696f, + -0.014564f, -0.999627f, -0.023117f, + -0.211443f, -0.629395f, -0.747766f, + -0.099921f, -0.932420f, -0.347287f, + -0.041912f, -0.988352f, -0.146303f, + -0.018338f, -0.997798f, -0.063741f, + -0.008087f, -0.999625f, -0.026150f, + -0.010332f, -0.628990f, -0.777345f, + -0.006477f, -0.932236f, -0.361793f, + -0.002559f, -0.988315f, -0.152402f, + -0.001190f, -0.997791f, -0.066422f, + -0.001027f, -0.999624f, -0.027401f, + 0.191218f, -0.629440f, -0.753154f, + 0.087291f, -0.932386f, -0.350766f, + 0.036926f, -0.988344f, -0.147688f, + 0.016021f, -0.997796f, -0.064386f, + 0.006087f, -0.999625f, -0.026706f, + 0.380023f, -0.629962f, -0.677297f, + 0.175124f, -0.932612f, -0.315543f, + 0.073881f, -0.988389f, -0.132774f, + 0.032133f, -0.997805f, -0.057900f, + 0.012794f, -0.999626f, -0.024157f, + 0.541695f, -0.630147f, -0.556310f, + 0.250409f, -0.932707f, -0.259523f, + 0.105540f, -0.988408f, -0.109137f, + 0.045941f, -0.997809f, -0.047613f, + 0.018575f, -0.999627f, -0.020018f, + 0.666911f, -0.629932f, -0.398014f, + 0.308995f, -0.932635f, -0.186318f, + 0.130182f, -0.988394f, -0.078296f, + 0.056696f, -0.997806f, -0.034185f, + 0.023117f, -0.999627f, -0.014564f, + 0.747766f, -0.629395f, -0.211443f, + 0.347287f, -0.932420f, -0.099921f, + 0.146303f, -0.988352f, -0.041912f, + 0.063741f, -0.997798f, -0.018338f, + 0.026150f, -0.999625f, -0.008087f, + 0.003252f, -0.999017f, 0.044215f, + 0.015240f, -0.999884f, -0.000426f, + 0.059928f, -0.998202f, -0.000876f, + 0.167134f, -0.985934f, -0.001083f, + 0.403838f, -0.914830f, -0.000203f, + 0.792445f, -0.609943f, 0.000242f, + 0.995161f, -0.098254f, -0.001013f, + 0.003195f, -0.927908f, 0.372795f, + 0.015041f, -0.949764f, 0.312606f, + 0.059227f, -0.948266f, 0.311904f, + 0.164453f, -0.933549f, 0.318499f, + 0.388162f, -0.854219f, 0.345890f, + 0.729394f, -0.561905f, 0.390189f, + 0.912351f, -0.095332f, 0.398156f, + 0.002232f, -0.597680f, 0.801731f, + 0.010830f, -0.681497f, 0.731741f, + 0.043613f, -0.679614f, 0.732272f, + 0.120047f, -0.660320f, 0.741327f, + 0.267930f, -0.580441f, 0.768962f, + 0.467285f, -0.367107f, 0.804287f, + 0.584006f, -0.067606f, 0.808929f, + -0.000653f, 0.152635f, 0.988282f, + -0.002559f, 0.000905f, 0.999996f, + -0.007405f, 0.000384f, 0.999972f, + -0.016090f, -0.004746f, 0.999859f, + -0.025703f, -0.019620f, 0.999477f, + -0.020936f, -0.035053f, 0.999166f, + -0.002824f, -0.023899f, 0.999710f, + -0.003296f, 0.756255f, 0.654269f, + -0.015405f, 0.681251f, 0.731887f, + -0.059217f, 0.676283f, 0.734258f, + -0.158438f, 0.643792f, 0.748619f, + -0.334170f, 0.526967f, 0.781432f, + -0.518177f, 0.278028f, 0.808822f, + -0.588929f, 0.016391f, 0.808019f, + -0.004352f, 0.967350f, 0.253408f, + -0.020677f, 0.949300f, 0.313691f, + -0.081844f, 0.945117f, 0.316317f, + -0.226175f, 0.916097f, 0.331076f, + -0.500500f, 0.784289f, 0.366594f, + -0.804374f, 0.439635f, 0.399630f, + -0.916460f, 0.037237f, 0.398390f, + -0.004517f, 0.999011f, -0.044228f, + -0.021584f, 0.999767f, 0.000265f, + -0.086245f, 0.996274f, 0.000157f, + -0.240673f, 0.970606f, -0.000608f, + -0.540280f, 0.841484f, -0.001597f, + -0.877811f, 0.479008f, 0.000390f, + -0.999074f, 0.043021f, 0.000686f, + -0.004094f, 0.927919f, -0.372759f, + -0.019687f, 0.949518f, -0.313093f, + -0.079023f, 0.945545f, -0.315752f, + -0.219600f, 0.917458f, -0.331734f, + -0.488715f, 0.790534f, -0.369071f, + -0.797673f, 0.452036f, -0.399226f, + -0.916555f, 0.045675f, -0.397293f, + -0.002516f, 0.597699f, -0.801716f, + -0.012433f, 0.681272f, -0.731925f, + -0.050950f, 0.677183f, -0.734048f, + -0.140298f, 0.648898f, -0.747829f, + -0.303501f, 0.546934f, -0.780224f, + -0.495541f, 0.315794f, -0.809143f, + -0.586888f, 0.043544f, -0.808497f, + 0.000557f, -0.152599f, -0.988288f, + 0.002074f, -0.000969f, -0.999997f, + 0.005499f, -0.001410f, -0.999984f, + 0.011569f, 0.000546f, -0.999933f, + 0.019331f, 0.010342f, -0.999760f, + 0.017294f, 0.025347f, -0.999529f, + 0.002733f, 0.020710f, -0.999782f, + 0.002668f, -0.756195f, -0.654340f, + 0.012416f, -0.681586f, -0.731633f, + 0.047946f, -0.679845f, -0.731787f, + 0.130533f, -0.659594f, -0.740200f, + 0.293034f, -0.569168f, -0.768231f, + 0.500213f, -0.318883f, -0.805047f, + 0.587808f, -0.026599f, -0.808563f, + 0.003191f, -0.967332f, -0.253494f, + 0.014981f, -0.949482f, -0.313464f, + 0.058954f, -0.947784f, -0.313417f, + 0.164056f, -0.933187f, -0.319761f, + 0.391212f, -0.853217f, -0.344925f, + 0.743675f, -0.542841f, -0.390219f, + 0.913602f, -0.073956f, -0.399828f, + 0.972925f, 0.231121f, -0.000918f, + 0.912330f, 0.409438f, -0.003849f, + 0.828029f, 0.560649f, -0.006408f, + 0.716807f, 0.697239f, -0.006712f, + 0.575989f, 0.817451f, -0.003302f, + 0.495133f, 0.867633f, -0.045350f, + 0.893985f, 0.213142f, 0.394158f, + 0.840605f, 0.383895f, 0.382108f, + 0.768860f, 0.531454f, 0.355543f, + 0.672509f, 0.665677f, 0.323426f, + 0.545610f, 0.779633f, 0.307380f, + 0.479303f, 0.843050f, 0.244000f, + 0.576388f, 0.133958f, 0.806122f, + 0.544470f, 0.253746f, 0.799478f, + 0.508754f, 0.364144f, 0.780108f, + 0.461180f, 0.471780f, 0.751490f, + 0.387281f, 0.561166f, 0.731509f, + 0.371347f, 0.666129f, 0.646818f, + 0.002410f, -0.014515f, 0.999892f, + 0.001301f, -0.016411f, 0.999865f, + 0.000720f, -0.020201f, 0.999796f, + 0.003256f, -0.021359f, 0.999767f, + 0.008876f, -0.013337f, 0.999872f, + 0.072759f, 0.131709f, 0.988615f, + -0.569088f, -0.161451f, 0.806271f, + -0.524317f, -0.294841f, 0.798850f, + -0.472635f, -0.410610f, 0.779754f, + -0.415783f, -0.508606f, 0.753953f, + -0.349674f, -0.579676f, 0.736006f, + -0.279208f, -0.530698f, 0.800252f, + -0.885693f, -0.241406f, 0.396574f, + -0.803204f, -0.449996f, 0.390343f, + -0.697513f, -0.613444f, 0.370354f, + -0.588462f, -0.732277f, 0.342757f, + -0.485206f, -0.813008f, 0.321860f, + -0.425879f, -0.823534f, 0.374725f, + -0.965787f, -0.259335f, 0.000592f, + -0.872611f, -0.488406f, 0.003010f, + -0.748651f, -0.662945f, 0.005037f, + -0.622443f, -0.782648f, 0.005056f, + -0.509112f, -0.860697f, 0.002551f, + -0.455515f, -0.889038f, 0.046023f, + -0.888605f, -0.232245f, -0.395529f, + -0.809378f, -0.443445f, -0.385051f, + -0.704052f, -0.611598f, -0.360913f, + -0.592713f, -0.733528f, -0.332607f, + -0.486334f, -0.814293f, -0.316868f, + -0.441890f, -0.860789f, -0.252538f, + -0.574477f, -0.139332f, -0.806575f, + -0.532235f, -0.275661f, -0.800460f, + -0.480844f, -0.396171f, -0.782201f, + -0.423172f, -0.499323f, -0.756044f, + -0.355443f, -0.574187f, -0.737543f, + -0.348424f, -0.670745f, -0.654753f, + -0.001891f, 0.012937f, -0.999915f, + 0.001397f, 0.011921f, -0.999928f, + 0.005089f, 0.014178f, -0.999887f, + 0.004896f, 0.016722f, -0.999848f, + -0.002003f, 0.012285f, -0.999922f, + -0.068183f, -0.130578f, -0.989091f, + 0.573387f, 0.149188f, -0.805587f, + 0.541227f, 0.266714f, -0.797456f, + 0.503525f, 0.377270f, -0.777258f, + 0.451452f, 0.484144f, -0.749530f, + 0.372386f, 0.571022f, -0.731616f, + 0.289707f, 0.529053f, -0.797604f, + 0.892654f, 0.216131f, -0.395546f, + 0.837234f, 0.384836f, -0.388510f, + 0.763231f, 0.531640f, -0.367202f, + 0.665469f, 0.666102f, -0.336837f, + 0.537995f, 0.781974f, -0.314766f, + 0.455324f, 0.810920f, -0.367545f, + -0.145927f, 0.987044f, 0.066705f, + -0.350253f, 0.936641f, -0.005157f, + -0.710995f, 0.703191f, -0.003047f, + -0.899400f, 0.437101f, 0.004678f, + -0.930238f, 0.366579f, 0.016656f, + -0.845840f, 0.533040f, 0.020564f, + -0.646372f, 0.763018f, 0.002776f, + -0.128906f, 0.841567f, 0.524546f, + -0.292019f, 0.852082f, 0.434375f, + -0.615355f, 0.675119f, 0.406882f, + -0.799678f, 0.453205f, 0.393853f, + -0.814130f, 0.384381f, 0.435251f, + -0.711742f, 0.496654f, 0.496746f, + -0.538718f, 0.683956f, 0.491922f, + -0.054328f, 0.445430f, 0.893667f, + -0.120328f, 0.535740f, 0.835765f, + -0.285367f, 0.495269f, 0.820533f, + -0.427214f, 0.405516f, 0.808112f, + -0.455262f, 0.354182f, 0.816880f, + -0.386518f, 0.375163f, 0.842530f, + -0.289150f, 0.468105f, 0.835027f, + 0.075157f, -0.092491f, 0.992873f, + 0.130249f, 0.040179f, 0.990667f, + 0.205304f, 0.124938f, 0.970691f, + 0.176764f, 0.184322f, 0.966840f, + 0.082193f, 0.182483f, 0.979767f, + 0.009842f, 0.124532f, 0.992167f, + -0.004171f, 0.105296f, 0.994432f, + 0.213849f, -0.587755f, 0.780264f, + 0.361728f, -0.447069f, 0.818097f, + 0.601635f, -0.258541f, 0.755772f, + 0.672221f, -0.099063f, 0.733693f, + 0.583247f, -0.084870f, 0.807849f, + 0.409251f, -0.235708f, 0.881451f, + 0.284284f, -0.385654f, 0.877755f, + 0.302637f, -0.880762f, 0.364237f, + 0.496428f, -0.756105f, 0.426456f, + 0.790450f, -0.487110f, 0.371365f, + 0.895860f, -0.277360f, 0.347141f, + 0.865262f, -0.295907f, 0.404673f, + 0.690272f, -0.542643f, 0.478606f, + 0.467747f, -0.753579f, 0.461879f, + 0.321563f, -0.944505f, -0.067141f, + 0.531566f, -0.847002f, 0.005046f, + 0.833505f, -0.552508f, 0.002163f, + 0.944185f, -0.329343f, -0.006880f, + 0.932318f, -0.361245f, -0.016874f, + 0.768639f, -0.639601f, -0.010215f, + 0.513002f, -0.858387f, 0.000964f, + 0.278331f, -0.809595f, -0.516806f, + 0.491568f, -0.763636f, -0.418594f, + 0.788478f, -0.493107f, -0.367624f, + 0.891089f, -0.275271f, -0.360815f, + 0.856479f, -0.282922f, -0.431739f, + 0.692218f, -0.527331f, -0.492704f, + 0.473487f, -0.749262f, -0.463052f, + 0.166654f, -0.429938f, -0.887344f, + 0.339768f, -0.458348f, -0.821264f, + 0.590160f, -0.276240f, -0.758553f, + 0.668115f, -0.103914f, -0.736766f, + 0.590009f, -0.076740f, -0.803741f, + 0.433287f, -0.219357f, -0.874154f, + 0.299036f, -0.368898f, -0.880052f, + 0.027869f, 0.102187f, -0.994375f, + 0.088152f, 0.031815f, -0.995599f, + 0.174456f, 0.096185f, -0.979956f, + 0.188708f, 0.161291f, -0.968697f, + 0.127686f, 0.175774f, -0.976115f, + 0.054509f, 0.130986f, -0.989885f, + 0.015877f, 0.116730f, -0.993037f, + -0.081072f, 0.607187f, -0.790412f, + -0.164116f, 0.522469f, -0.836715f, + -0.319626f, 0.463405f, -0.826495f, + -0.422971f, 0.383450f, -0.821013f, + -0.424534f, 0.353597f, -0.833511f, + -0.351612f, 0.388106f, -0.851905f, + -0.270475f, 0.475063f, -0.837352f, + -0.133739f, 0.917541f, -0.374476f, + -0.316043f, 0.839490f, -0.442011f, + -0.631181f, 0.656649f, -0.412823f, + -0.807405f, 0.443017f, -0.389658f, + -0.821659f, 0.386229f, -0.419171f, + -0.707748f, 0.517393f, -0.481037f, + -0.526814f, 0.693790f, -0.491043f, + -0.461017f, 0.887371f, -0.005987f, + -0.290675f, 0.956710f, -0.014601f, + 0.085518f, 0.995086f, -0.049913f, + 0.887713f, 0.456166f, -0.062285f, + 0.822992f, -0.567263f, 0.029937f, + 0.659878f, -0.743158f, 0.110798f, + -0.391094f, 0.831360f, 0.394824f, + -0.253310f, 0.936825f, 0.241231f, + 0.015366f, 0.995010f, -0.098588f, + 0.520185f, 0.549881f, -0.653482f, + 0.628856f, -0.382376f, -0.677000f, + 0.578948f, -0.646092f, -0.497378f, + -0.223422f, 0.660928f, 0.716420f, + -0.156131f, 0.874986f, 0.458282f, + -0.036467f, 0.998264f, -0.046261f, + 0.156637f, 0.682491f, -0.713913f, + 0.263632f, 0.005571f, -0.964607f, + 0.312409f, -0.324778f, -0.892704f, + -0.001751f, 0.339383f, 0.940647f, + -0.021119f, 0.759902f, 0.649695f, + -0.044404f, 0.998121f, 0.042219f, + -0.032529f, 0.802862f, -0.595277f, + -0.008745f, 0.371564f, -0.928366f, + 0.042529f, 0.077913f, -0.996053f, + 0.280020f, -0.238192f, 0.929975f, + 0.227305f, 0.491486f, 0.840699f, + -0.003105f, 0.987407f, 0.158172f, + -0.143918f, 0.895866f, -0.420370f, + -0.200177f, 0.683872f, -0.701604f, + -0.187188f, 0.500198f, -0.845437f, + 0.453673f, -0.746835f, 0.486229f, + 0.692158f, -0.080062f, 0.717291f, + 0.185758f, 0.942536f, 0.277704f, + -0.211188f, 0.955274f, -0.207004f, + -0.312961f, 0.881061f, -0.354665f, + -0.336331f, 0.811345f, -0.478122f, + 0.482445f, -0.875816f, -0.013906f, + 0.913013f, -0.405572f, -0.043811f, + 0.506909f, 0.853920f, 0.117742f, + -0.234033f, 0.972124f, 0.014295f, + -0.348033f, 0.937468f, 0.005277f, + -0.384064f, 0.921073f, -0.064185f, + 0.457762f, -0.717668f, -0.524792f, + 0.683347f, -0.063014f, -0.727369f, + 0.357361f, 0.898186f, -0.256038f, + -0.207010f, 0.947863f, 0.242287f, + -0.314387f, 0.872357f, 0.374372f, + -0.361040f, 0.872819f, 0.328385f, + 0.280225f, -0.218552f, -0.934724f, + 0.261124f, 0.434074f, -0.862203f, + 0.060553f, 0.978577f, -0.196775f, + -0.131809f, 0.881094f, 0.454203f, + -0.195016f, 0.658858f, 0.726550f, + -0.247824f, 0.630359f, 0.735684f, + 0.008860f, 0.321862f, -0.946745f, + 0.001382f, 0.733189f, -0.680023f, + -0.012720f, 0.997949f, -0.062734f, + -0.011656f, 0.785221f, 0.619106f, + 0.000967f, 0.344022f, 0.938961f, + -0.037360f, 0.214324f, 0.976048f, + -0.213360f, 0.648838f, -0.730401f, + -0.140052f, 0.865891f, -0.480227f, + -0.000809f, 0.999500f, 0.031611f, + 0.194529f, 0.659081f, 0.726478f, + 0.266832f, -0.005234f, 0.963729f, + 0.219380f, -0.217247f, 0.951145f, + -0.384886f, 0.827121f, -0.409553f, + -0.240915f, 0.932642f, -0.268588f, + 0.065830f, 0.996786f, 0.045658f, + 0.597011f, 0.507703f, 0.621141f, + 0.613004f, -0.369418f, 0.698395f, + 0.486873f, -0.566787f, 0.664610f, + 0.000000f, 1.000000f, 0.000000f, + 0.395791f, 0.918207f, 0.015676f, + 0.964544f, 0.263762f, 0.009177f, + 0.839041f, -0.544056f, -0.003654f, + 0.788969f, -0.614430f, 0.001943f, + 0.991025f, -0.133647f, 0.002953f, + 0.732531f, 0.680606f, -0.013206f, + 0.377669f, 0.918491f, 0.117221f, + 0.929557f, 0.263662f, 0.257694f, + 0.811158f, -0.544801f, 0.212638f, + 0.761156f, -0.615195f, 0.205370f, + 0.956515f, -0.133833f, 0.259168f, + 0.710689f, 0.680955f, 0.176694f, + 0.333696f, 0.918791f, 0.210878f, + 0.830713f, 0.263784f, 0.490239f, + 0.727549f, -0.545809f, 0.415650f, + 0.681011f, -0.616288f, 0.395491f, + 0.856413f, -0.134443f, 0.498480f, + 0.640176f, 0.681271f, 0.355027f, + 0.267591f, 0.918878f, 0.289928f, + 0.675416f, 0.263955f, 0.688579f, + 0.594970f, -0.546203f, 0.589638f, + 0.555330f, -0.616730f, 0.557901f, + 0.698694f, -0.134804f, 0.702606f, + 0.526898f, 0.681345f, 0.508082f, + 0.183499f, 0.918711f, 0.349712f, + 0.474031f, 0.264098f, 0.839969f, + 0.422194f, -0.545768f, 0.723802f, + 0.392296f, -0.616276f, 0.682867f, + 0.493598f, -0.134679f, 0.859199f, + 0.378184f, 0.681197f, 0.626856f, + 0.086498f, 0.918378f, 0.386136f, + 0.239605f, 0.264096f, 0.934261f, + 0.219887f, -0.544743f, 0.809262f, + 0.201667f, -0.615183f, 0.762155f, + 0.253529f, -0.134173f, 0.957977f, + 0.202631f, 0.680866f, 0.703820f, + -0.015676f, 0.918207f, 0.395791f, + -0.009177f, 0.263762f, 0.964544f, + 0.003654f, -0.544057f, 0.839041f, + -0.001943f, -0.614430f, 0.788969f, + -0.002953f, -0.133647f, 0.991025f, + 0.013206f, 0.680606f, 0.732531f, + -0.117221f, 0.918491f, 0.377669f, + -0.257694f, 0.263662f, 0.929557f, + -0.212638f, -0.544801f, 0.811158f, + -0.205370f, -0.615195f, 0.761156f, + -0.259168f, -0.133833f, 0.956515f, + -0.176694f, 0.680955f, 0.710689f, + -0.210878f, 0.918791f, 0.333696f, + -0.490239f, 0.263784f, 0.830713f, + -0.415650f, -0.545809f, 0.727549f, + -0.395491f, -0.616288f, 0.681011f, + -0.498480f, -0.134443f, 0.856413f, + -0.355027f, 0.681271f, 0.640176f, + -0.289928f, 0.918878f, 0.267591f, + -0.688579f, 0.263955f, 0.675416f, + -0.589638f, -0.546203f, 0.594970f, + -0.557901f, -0.616730f, 0.555330f, + -0.702606f, -0.134804f, 0.698694f, + -0.508082f, 0.681345f, 0.526898f, + -0.349712f, 0.918711f, 0.183499f, + -0.839969f, 0.264098f, 0.474031f, + -0.723802f, -0.545768f, 0.422194f, + -0.682867f, -0.616276f, 0.392296f, + -0.859199f, -0.134679f, 0.493598f, + -0.626856f, 0.681197f, 0.378184f, + -0.386136f, 0.918378f, 0.086498f, + -0.934261f, 0.264096f, 0.239605f, + -0.809262f, -0.544743f, 0.219887f, + -0.762155f, -0.615183f, 0.201667f, + -0.957977f, -0.134173f, 0.253529f, + -0.703820f, 0.680866f, 0.202631f, + -0.395791f, 0.918207f, -0.015676f, + -0.964544f, 0.263762f, -0.009177f, + -0.839041f, -0.544057f, 0.003654f, + -0.788969f, -0.614430f, -0.001943f, + -0.991025f, -0.133647f, -0.002953f, + -0.732531f, 0.680606f, 0.013206f, + -0.377669f, 0.918491f, -0.117221f, + -0.929557f, 0.263662f, -0.257694f, + -0.811158f, -0.544801f, -0.212638f, + -0.761156f, -0.615195f, -0.205370f, + -0.956515f, -0.133833f, -0.259168f, + -0.710689f, 0.680955f, -0.176694f, + -0.333696f, 0.918791f, -0.210878f, + -0.830713f, 0.263784f, -0.490239f, + -0.727549f, -0.545809f, -0.415650f, + -0.681011f, -0.616288f, -0.395491f, + -0.856413f, -0.134443f, -0.498480f, + -0.640176f, 0.681271f, -0.355027f, + -0.267591f, 0.918878f, -0.289928f, + -0.675416f, 0.263955f, -0.688579f, + -0.594970f, -0.546203f, -0.589638f, + -0.555330f, -0.616730f, -0.557901f, + -0.698694f, -0.134804f, -0.702606f, + -0.526898f, 0.681345f, -0.508082f, + -0.183499f, 0.918711f, -0.349712f, + -0.474031f, 0.264098f, -0.839969f, + -0.422194f, -0.545768f, -0.723802f, + -0.392296f, -0.616276f, -0.682867f, + -0.493598f, -0.134679f, -0.859199f, + -0.378184f, 0.681197f, -0.626856f, + -0.086498f, 0.918378f, -0.386136f, + -0.239605f, 0.264096f, -0.934261f, + -0.219887f, -0.544743f, -0.809262f, + -0.201667f, -0.615183f, -0.762155f, + -0.253529f, -0.134173f, -0.957977f, + -0.202631f, 0.680866f, -0.703820f, + 0.015676f, 0.918207f, -0.395791f, + 0.009177f, 0.263762f, -0.964544f, + -0.003654f, -0.544057f, -0.839041f, + 0.001943f, -0.614430f, -0.788969f, + 0.002953f, -0.133647f, -0.991025f, + -0.013206f, 0.680606f, -0.732531f, + 0.117221f, 0.918491f, -0.377669f, + 0.257694f, 0.263662f, -0.929557f, + 0.212638f, -0.544801f, -0.811158f, + 0.205370f, -0.615195f, -0.761156f, + 0.259168f, -0.133833f, -0.956515f, + 0.176694f, 0.680955f, -0.710689f, + 0.210878f, 0.918791f, -0.333696f, + 0.490239f, 0.263784f, -0.830713f, + 0.415650f, -0.545809f, -0.727549f, + 0.395491f, -0.616288f, -0.681011f, + 0.498480f, -0.134443f, -0.856413f, + 0.355027f, 0.681271f, -0.640176f, + 0.289928f, 0.918878f, -0.267591f, + 0.688579f, 0.263955f, -0.675416f, + 0.589638f, -0.546203f, -0.594970f, + 0.557901f, -0.616730f, -0.555330f, + 0.702606f, -0.134804f, -0.698694f, + 0.508082f, 0.681345f, -0.526898f, + 0.349712f, 0.918711f, -0.183499f, + 0.839969f, 0.264098f, -0.474031f, + 0.723802f, -0.545768f, -0.422194f, + 0.682867f, -0.616276f, -0.392296f, + 0.859199f, -0.134679f, -0.493598f, + 0.626856f, 0.681197f, -0.378184f, + 0.386136f, 0.918378f, -0.086498f, + 0.934261f, 0.264096f, -0.239605f, + 0.809262f, -0.544743f, -0.219887f, + 0.762155f, -0.615183f, -0.201667f, + 0.957977f, -0.134173f, -0.253529f, + 0.703820f, 0.680866f, -0.202631f, + 0.299763f, 0.954005f, -0.004004f, + 0.180158f, 0.983637f, -0.001176f, + 0.158462f, 0.987365f, 0.000232f, + 0.213709f, 0.976895f, 0.002171f, + 0.489301f, 0.872063f, 0.009504f, + 0.686607f, 0.726410f, -0.029990f, + 0.290238f, 0.954117f, 0.073644f, + 0.174086f, 0.983681f, 0.045452f, + 0.152777f, 0.987401f, 0.041212f, + 0.205547f, 0.976963f, 0.057393f, + 0.469598f, 0.872357f, 0.135911f, + 0.670656f, 0.726754f, 0.148493f, + 0.260698f, 0.954280f, 0.146242f, + 0.156021f, 0.983742f, 0.088932f, + 0.136587f, 0.987448f, 0.079312f, + 0.183282f, 0.977046f, 0.108577f, + 0.417739f, 0.872696f, 0.252776f, + 0.608331f, 0.727460f, 0.317389f, + 0.214008f, 0.954348f, 0.208377f, + 0.127716f, 0.983767f, 0.126063f, + 0.111442f, 0.987466f, 0.111767f, + 0.149005f, 0.977076f, 0.152056f, + 0.338347f, 0.872812f, 0.351738f, + 0.505565f, 0.727811f, 0.463351f, + 0.153158f, 0.954293f, 0.256647f, + 0.090962f, 0.983745f, 0.154830f, + 0.078913f, 0.987448f, 0.136822f, + 0.104831f, 0.977040f, 0.185479f, + 0.236319f, 0.872663f, 0.427333f, + 0.369272f, 0.727651f, 0.578067f, + 0.081449f, 0.954136f, 0.288080f, + 0.047744f, 0.983685f, 0.173450f, + 0.040760f, 0.987400f, 0.152903f, + 0.053164f, 0.976955f, 0.206721f, + 0.117360f, 0.872307f, 0.474665f, + 0.207008f, 0.727038f, 0.654648f, + 0.004004f, 0.954005f, 0.299763f, + 0.001176f, 0.983637f, 0.180158f, + -0.000232f, 0.987365f, 0.158462f, + -0.002171f, 0.976895f, 0.213709f, + -0.009504f, 0.872063f, 0.489301f, + 0.029990f, 0.726410f, 0.686607f, + -0.073644f, 0.954117f, 0.290238f, + -0.045452f, 0.983681f, 0.174086f, + -0.041212f, 0.987401f, 0.152777f, + -0.057393f, 0.976963f, 0.205547f, + -0.135911f, 0.872357f, 0.469598f, + -0.148493f, 0.726754f, 0.670656f, + -0.146242f, 0.954280f, 0.260698f, + -0.088932f, 0.983742f, 0.156021f, + -0.079312f, 0.987448f, 0.136587f, + -0.108577f, 0.977046f, 0.183282f, + -0.252776f, 0.872696f, 0.417739f, + -0.317389f, 0.727460f, 0.608331f, + -0.208377f, 0.954348f, 0.214008f, + -0.126063f, 0.983767f, 0.127716f, + -0.111767f, 0.987466f, 0.111442f, + -0.152056f, 0.977076f, 0.149005f, + -0.351738f, 0.872812f, 0.338347f, + -0.463351f, 0.727811f, 0.505565f, + -0.256647f, 0.954293f, 0.153158f, + -0.154830f, 0.983745f, 0.090962f, + -0.136822f, 0.987448f, 0.078913f, + -0.185479f, 0.977040f, 0.104831f, + -0.427333f, 0.872663f, 0.236319f, + -0.578067f, 0.727651f, 0.369272f, + -0.288080f, 0.954136f, 0.081449f, + -0.173450f, 0.983685f, 0.047744f, + -0.152903f, 0.987400f, 0.040760f, + -0.206721f, 0.976955f, 0.053164f, + -0.474665f, 0.872307f, 0.117360f, + -0.654648f, 0.727038f, 0.207008f, + -0.299763f, 0.954005f, 0.004004f, + -0.180158f, 0.983637f, 0.001176f, + -0.158462f, 0.987365f, -0.000232f, + -0.213709f, 0.976895f, -0.002171f, + -0.489301f, 0.872063f, -0.009504f, + -0.686607f, 0.726410f, 0.029990f, + -0.290238f, 0.954117f, -0.073644f, + -0.174086f, 0.983681f, -0.045452f, + -0.152777f, 0.987401f, -0.041212f, + -0.205547f, 0.976963f, -0.057393f, + -0.469598f, 0.872357f, -0.135911f, + -0.670656f, 0.726754f, -0.148493f, + -0.260698f, 0.954280f, -0.146242f, + -0.156021f, 0.983742f, -0.088932f, + -0.136587f, 0.987448f, -0.079312f, + -0.183282f, 0.977046f, -0.108577f, + -0.417739f, 0.872696f, -0.252776f, + -0.608331f, 0.727460f, -0.317389f, + -0.214008f, 0.954348f, -0.208377f, + -0.127716f, 0.983767f, -0.126063f, + -0.111442f, 0.987466f, -0.111767f, + -0.149005f, 0.977076f, -0.152056f, + -0.338347f, 0.872812f, -0.351738f, + -0.505565f, 0.727811f, -0.463351f, + -0.153158f, 0.954293f, -0.256647f, + -0.090962f, 0.983745f, -0.154830f, + -0.078913f, 0.987448f, -0.136822f, + -0.104831f, 0.977040f, -0.185479f, + -0.236319f, 0.872663f, -0.427333f, + -0.369272f, 0.727651f, -0.578067f, + -0.081449f, 0.954136f, -0.288080f, + -0.047744f, 0.983685f, -0.173450f, + -0.040760f, 0.987400f, -0.152903f, + -0.053164f, 0.976955f, -0.206721f, + -0.117360f, 0.872307f, -0.474665f, + -0.207008f, 0.727038f, -0.654648f, + -0.004004f, 0.954005f, -0.299763f, + -0.001176f, 0.983637f, -0.180158f, + 0.000232f, 0.987365f, -0.158462f, + 0.002171f, 0.976895f, -0.213709f, + 0.009504f, 0.872063f, -0.489301f, + -0.029990f, 0.726410f, -0.686607f, + 0.073644f, 0.954117f, -0.290238f, + 0.045452f, 0.983681f, -0.174086f, + 0.041212f, 0.987401f, -0.152777f, + 0.057393f, 0.976963f, -0.205547f, + 0.135911f, 0.872357f, -0.469598f, + 0.148493f, 0.726754f, -0.670656f, + 0.146242f, 0.954280f, -0.260698f, + 0.088932f, 0.983742f, -0.156021f, + 0.079312f, 0.987448f, -0.136587f, + 0.108577f, 0.977046f, -0.183282f, + 0.252776f, 0.872696f, -0.417739f, + 0.317389f, 0.727460f, -0.608331f, + 0.208377f, 0.954348f, -0.214008f, + 0.126063f, 0.983767f, -0.127716f, + 0.111767f, 0.987466f, -0.111442f, + 0.152056f, 0.977076f, -0.149005f, + 0.351738f, 0.872812f, -0.338347f, + 0.463351f, 0.727811f, -0.505565f, + 0.256647f, 0.954293f, -0.153158f, + 0.154830f, 0.983745f, -0.090962f, + 0.136822f, 0.987448f, -0.078913f, + 0.185479f, 0.977040f, -0.104831f, + 0.427333f, 0.872663f, -0.236319f, + 0.578067f, 0.727651f, -0.369272f, + 0.288080f, 0.954136f, -0.081449f, + 0.173450f, 0.983685f, -0.047744f, + 0.152903f, 0.987400f, -0.040760f, + 0.206721f, 0.976955f, -0.053164f, + 0.474665f, 0.872307f, -0.117360f, + 0.654648f, 0.727038f, -0.207008f, +}; +static D3DXVECTOR3* teapotNormals = ( D3DXVECTOR3* )teapotNormalsfloats; + +static WORD teapotIndices[NUMTEAPOTINDICES] = +{ + 0, 7, 8, + 8, 1, 0, + 1, 8, 9, + 9, 2, 1, + 2, 9, 10, + 10, 3, 2, + 3, 10, 11, + 11, 4, 3, + 4, 11, 12, + 12, 5, 4, + 5, 12, 13, + 13, 6, 5, + 7, 14, 15, + 15, 8, 7, + 8, 15, 16, + 16, 9, 8, + 9, 16, 17, + 17, 10, 9, + 10, 17, 18, + 18, 11, 10, + 11, 18, 19, + 19, 12, 11, + 12, 19, 20, + 20, 13, 12, + 14, 21, 22, + 22, 15, 14, + 15, 22, 23, + 23, 16, 15, + 16, 23, 24, + 24, 17, 16, + 17, 24, 25, + 25, 18, 17, + 18, 25, 26, + 26, 19, 18, + 19, 26, 27, + 27, 20, 19, + 21, 28, 29, + 29, 22, 21, + 22, 29, 30, + 30, 23, 22, + 23, 30, 31, + 31, 24, 23, + 24, 31, 32, + 32, 25, 24, + 25, 32, 33, + 33, 26, 25, + 26, 33, 34, + 34, 27, 26, + 28, 35, 36, + 36, 29, 28, + 29, 36, 37, + 37, 30, 29, + 30, 37, 38, + 38, 31, 30, + 31, 38, 39, + 39, 32, 31, + 32, 39, 40, + 40, 33, 32, + 33, 40, 41, + 41, 34, 33, + 35, 42, 43, + 43, 36, 35, + 36, 43, 44, + 44, 37, 36, + 37, 44, 45, + 45, 38, 37, + 38, 45, 46, + 46, 39, 38, + 39, 46, 47, + 47, 40, 39, + 40, 47, 48, + 48, 41, 40, + 42, 49, 50, + 50, 43, 42, + 43, 50, 51, + 51, 44, 43, + 44, 51, 52, + 52, 45, 44, + 45, 52, 53, + 53, 46, 45, + 46, 53, 54, + 54, 47, 46, + 47, 54, 55, + 55, 48, 47, + 49, 56, 57, + 57, 50, 49, + 50, 57, 58, + 58, 51, 50, + 51, 58, 59, + 59, 52, 51, + 52, 59, 60, + 60, 53, 52, + 53, 60, 61, + 61, 54, 53, + 54, 61, 62, + 62, 55, 54, + 56, 63, 64, + 64, 57, 56, + 57, 64, 65, + 65, 58, 57, + 58, 65, 66, + 66, 59, 58, + 59, 66, 67, + 67, 60, 59, + 60, 67, 68, + 68, 61, 60, + 61, 68, 69, + 69, 62, 61, + 63, 70, 71, + 71, 64, 63, + 64, 71, 72, + 72, 65, 64, + 65, 72, 73, + 73, 66, 65, + 66, 73, 74, + 74, 67, 66, + 67, 74, 75, + 75, 68, 67, + 68, 75, 76, + 76, 69, 68, + 70, 77, 78, + 78, 71, 70, + 71, 78, 79, + 79, 72, 71, + 72, 79, 80, + 80, 73, 72, + 73, 80, 81, + 81, 74, 73, + 74, 81, 82, + 82, 75, 74, + 75, 82, 83, + 83, 76, 75, + 77, 84, 85, + 85, 78, 77, + 78, 85, 86, + 86, 79, 78, + 79, 86, 87, + 87, 80, 79, + 80, 87, 88, + 88, 81, 80, + 81, 88, 89, + 89, 82, 81, + 82, 89, 90, + 90, 83, 82, + 84, 91, 92, + 92, 85, 84, + 85, 92, 93, + 93, 86, 85, + 86, 93, 94, + 94, 87, 86, + 87, 94, 95, + 95, 88, 87, + 88, 95, 96, + 96, 89, 88, + 89, 96, 97, + 97, 90, 89, + 91, 98, 99, + 99, 92, 91, + 92, 99, 100, + 100, 93, 92, + 93, 100, 101, + 101, 94, 93, + 94, 101, 102, + 102, 95, 94, + 95, 102, 103, + 103, 96, 95, + 96, 103, 104, + 104, 97, 96, + 98, 105, 106, + 106, 99, 98, + 99, 106, 107, + 107, 100, 99, + 100, 107, 108, + 108, 101, 100, + 101, 108, 109, + 109, 102, 101, + 102, 109, 110, + 110, 103, 102, + 103, 110, 111, + 111, 104, 103, + 105, 112, 113, + 113, 106, 105, + 106, 113, 114, + 114, 107, 106, + 107, 114, 115, + 115, 108, 107, + 108, 115, 116, + 116, 109, 108, + 109, 116, 117, + 117, 110, 109, + 110, 117, 118, + 118, 111, 110, + 112, 119, 120, + 120, 113, 112, + 113, 120, 121, + 121, 114, 113, + 114, 121, 122, + 122, 115, 114, + 115, 122, 123, + 123, 116, 115, + 116, 123, 124, + 124, 117, 116, + 117, 124, 125, + 125, 118, 117, + 119, 126, 127, + 127, 120, 119, + 120, 127, 128, + 128, 121, 120, + 121, 128, 129, + 129, 122, 121, + 122, 129, 130, + 130, 123, 122, + 123, 130, 131, + 131, 124, 123, + 124, 131, 132, + 132, 125, 124, + 126, 133, 134, + 134, 127, 126, + 127, 134, 135, + 135, 128, 127, + 128, 135, 136, + 136, 129, 128, + 129, 136, 137, + 137, 130, 129, + 130, 137, 138, + 138, 131, 130, + 131, 138, 139, + 139, 132, 131, + 133, 140, 141, + 141, 134, 133, + 134, 141, 142, + 142, 135, 134, + 135, 142, 143, + 143, 136, 135, + 136, 143, 144, + 144, 137, 136, + 137, 144, 145, + 145, 138, 137, + 138, 145, 146, + 146, 139, 138, + 140, 147, 148, + 148, 141, 140, + 141, 148, 149, + 149, 142, 141, + 142, 149, 150, + 150, 143, 142, + 143, 150, 151, + 151, 144, 143, + 144, 151, 152, + 152, 145, 144, + 145, 152, 153, + 153, 146, 145, + 147, 154, 155, + 155, 148, 147, + 148, 155, 156, + 156, 149, 148, + 149, 156, 157, + 157, 150, 149, + 150, 157, 158, + 158, 151, 150, + 151, 158, 159, + 159, 152, 151, + 152, 159, 160, + 160, 153, 152, + 154, 161, 162, + 162, 155, 154, + 155, 162, 163, + 163, 156, 155, + 156, 163, 164, + 164, 157, 156, + 157, 164, 165, + 165, 158, 157, + 158, 165, 166, + 166, 159, 158, + 159, 166, 167, + 167, 160, 159, + 161, 0, 1, + 1, 162, 161, + 162, 1, 2, + 2, 163, 162, + 163, 2, 3, + 3, 164, 163, + 164, 3, 4, + 4, 165, 164, + 165, 4, 5, + 5, 166, 165, + 166, 5, 6, + 6, 167, 166, + 6, 13, 174, + 174, 168, 6, + 168, 174, 175, + 175, 169, 168, + 169, 175, 176, + 176, 170, 169, + 170, 176, 177, + 177, 171, 170, + 171, 177, 178, + 178, 172, 171, + 172, 178, 179, + 179, 173, 172, + 13, 20, 180, + 180, 174, 13, + 174, 180, 181, + 181, 175, 174, + 175, 181, 182, + 182, 176, 175, + 176, 182, 183, + 183, 177, 176, + 177, 183, 184, + 184, 178, 177, + 178, 184, 185, + 185, 179, 178, + 20, 27, 186, + 186, 180, 20, + 180, 186, 187, + 187, 181, 180, + 181, 187, 188, + 188, 182, 181, + 182, 188, 189, + 189, 183, 182, + 183, 189, 190, + 190, 184, 183, + 184, 190, 191, + 191, 185, 184, + 27, 34, 192, + 192, 186, 27, + 186, 192, 193, + 193, 187, 186, + 187, 193, 194, + 194, 188, 187, + 188, 194, 195, + 195, 189, 188, + 189, 195, 196, + 196, 190, 189, + 190, 196, 197, + 197, 191, 190, + 34, 41, 198, + 198, 192, 34, + 192, 198, 199, + 199, 193, 192, + 193, 199, 200, + 200, 194, 193, + 194, 200, 201, + 201, 195, 194, + 195, 201, 202, + 202, 196, 195, + 196, 202, 203, + 203, 197, 196, + 41, 48, 204, + 204, 198, 41, + 198, 204, 205, + 205, 199, 198, + 199, 205, 206, + 206, 200, 199, + 200, 206, 207, + 207, 201, 200, + 201, 207, 208, + 208, 202, 201, + 202, 208, 209, + 209, 203, 202, + 48, 55, 210, + 210, 204, 48, + 204, 210, 211, + 211, 205, 204, + 205, 211, 212, + 212, 206, 205, + 206, 212, 213, + 213, 207, 206, + 207, 213, 214, + 214, 208, 207, + 208, 214, 215, + 215, 209, 208, + 55, 62, 216, + 216, 210, 55, + 210, 216, 217, + 217, 211, 210, + 211, 217, 218, + 218, 212, 211, + 212, 218, 219, + 219, 213, 212, + 213, 219, 220, + 220, 214, 213, + 214, 220, 221, + 221, 215, 214, + 62, 69, 222, + 222, 216, 62, + 216, 222, 223, + 223, 217, 216, + 217, 223, 224, + 224, 218, 217, + 218, 224, 225, + 225, 219, 218, + 219, 225, 226, + 226, 220, 219, + 220, 226, 227, + 227, 221, 220, + 69, 76, 228, + 228, 222, 69, + 222, 228, 229, + 229, 223, 222, + 223, 229, 230, + 230, 224, 223, + 224, 230, 231, + 231, 225, 224, + 225, 231, 232, + 232, 226, 225, + 226, 232, 233, + 233, 227, 226, + 76, 83, 234, + 234, 228, 76, + 228, 234, 235, + 235, 229, 228, + 229, 235, 236, + 236, 230, 229, + 230, 236, 237, + 237, 231, 230, + 231, 237, 238, + 238, 232, 231, + 232, 238, 239, + 239, 233, 232, + 83, 90, 240, + 240, 234, 83, + 234, 240, 241, + 241, 235, 234, + 235, 241, 242, + 242, 236, 235, + 236, 242, 243, + 243, 237, 236, + 237, 243, 244, + 244, 238, 237, + 238, 244, 245, + 245, 239, 238, + 90, 97, 246, + 246, 240, 90, + 240, 246, 247, + 247, 241, 240, + 241, 247, 248, + 248, 242, 241, + 242, 248, 249, + 249, 243, 242, + 243, 249, 250, + 250, 244, 243, + 244, 250, 251, + 251, 245, 244, + 97, 104, 252, + 252, 246, 97, + 246, 252, 253, + 253, 247, 246, + 247, 253, 254, + 254, 248, 247, + 248, 254, 255, + 255, 249, 248, + 249, 255, 256, + 256, 250, 249, + 250, 256, 257, + 257, 251, 250, + 104, 111, 258, + 258, 252, 104, + 252, 258, 259, + 259, 253, 252, + 253, 259, 260, + 260, 254, 253, + 254, 260, 261, + 261, 255, 254, + 255, 261, 262, + 262, 256, 255, + 256, 262, 263, + 263, 257, 256, + 111, 118, 264, + 264, 258, 111, + 258, 264, 265, + 265, 259, 258, + 259, 265, 266, + 266, 260, 259, + 260, 266, 267, + 267, 261, 260, + 261, 267, 268, + 268, 262, 261, + 262, 268, 269, + 269, 263, 262, + 118, 125, 270, + 270, 264, 118, + 264, 270, 271, + 271, 265, 264, + 265, 271, 272, + 272, 266, 265, + 266, 272, 273, + 273, 267, 266, + 267, 273, 274, + 274, 268, 267, + 268, 274, 275, + 275, 269, 268, + 125, 132, 276, + 276, 270, 125, + 270, 276, 277, + 277, 271, 270, + 271, 277, 278, + 278, 272, 271, + 272, 278, 279, + 279, 273, 272, + 273, 279, 280, + 280, 274, 273, + 274, 280, 281, + 281, 275, 274, + 132, 139, 282, + 282, 276, 132, + 276, 282, 283, + 283, 277, 276, + 277, 283, 284, + 284, 278, 277, + 278, 284, 285, + 285, 279, 278, + 279, 285, 286, + 286, 280, 279, + 280, 286, 287, + 287, 281, 280, + 139, 146, 288, + 288, 282, 139, + 282, 288, 289, + 289, 283, 282, + 283, 289, 290, + 290, 284, 283, + 284, 290, 291, + 291, 285, 284, + 285, 291, 292, + 292, 286, 285, + 286, 292, 293, + 293, 287, 286, + 146, 153, 294, + 294, 288, 146, + 288, 294, 295, + 295, 289, 288, + 289, 295, 296, + 296, 290, 289, + 290, 296, 297, + 297, 291, 290, + 291, 297, 298, + 298, 292, 291, + 292, 298, 299, + 299, 293, 292, + 153, 160, 300, + 300, 294, 153, + 294, 300, 301, + 301, 295, 294, + 295, 301, 302, + 302, 296, 295, + 296, 302, 303, + 303, 297, 296, + 297, 303, 304, + 304, 298, 297, + 298, 304, 305, + 305, 299, 298, + 160, 167, 306, + 306, 300, 160, + 300, 306, 307, + 307, 301, 300, + 301, 307, 308, + 308, 302, 301, + 302, 308, 309, + 309, 303, 302, + 303, 309, 310, + 310, 304, 303, + 304, 310, 311, + 311, 305, 304, + 167, 6, 168, + 168, 306, 167, + 306, 168, 169, + 169, 307, 306, + 307, 169, 170, + 170, 308, 307, + 308, 170, 171, + 171, 309, 308, + 309, 171, 172, + 172, 310, 309, + 310, 172, 173, + 173, 311, 310, + 173, 179, 318, + 318, 312, 173, + 312, 318, 319, + 319, 313, 312, + 313, 319, 320, + 320, 314, 313, + 314, 320, 321, + 321, 315, 314, + 315, 321, 322, + 322, 316, 315, + 316, 322, 323, + 323, 317, 316, + 179, 185, 324, + 324, 318, 179, + 318, 324, 325, + 325, 319, 318, + 319, 325, 326, + 326, 320, 319, + 320, 326, 327, + 327, 321, 320, + 321, 327, 328, + 328, 322, 321, + 322, 328, 329, + 329, 323, 322, + 185, 191, 330, + 330, 324, 185, + 324, 330, 331, + 331, 325, 324, + 325, 331, 332, + 332, 326, 325, + 326, 332, 333, + 333, 327, 326, + 327, 333, 334, + 334, 328, 327, + 328, 334, 335, + 335, 329, 328, + 191, 197, 336, + 336, 330, 191, + 330, 336, 337, + 337, 331, 330, + 331, 337, 338, + 338, 332, 331, + 332, 338, 339, + 339, 333, 332, + 333, 339, 340, + 340, 334, 333, + 334, 340, 341, + 341, 335, 334, + 197, 203, 342, + 342, 336, 197, + 336, 342, 343, + 343, 337, 336, + 337, 343, 344, + 344, 338, 337, + 338, 344, 345, + 345, 339, 338, + 339, 345, 346, + 346, 340, 339, + 340, 346, 347, + 347, 341, 340, + 203, 209, 348, + 348, 342, 203, + 342, 348, 349, + 349, 343, 342, + 343, 349, 350, + 350, 344, 343, + 344, 350, 351, + 351, 345, 344, + 345, 351, 352, + 352, 346, 345, + 346, 352, 353, + 353, 347, 346, + 209, 215, 354, + 354, 348, 209, + 348, 354, 355, + 355, 349, 348, + 349, 355, 356, + 356, 350, 349, + 350, 356, 357, + 357, 351, 350, + 351, 357, 358, + 358, 352, 351, + 352, 358, 359, + 359, 353, 352, + 215, 221, 360, + 360, 354, 215, + 354, 360, 361, + 361, 355, 354, + 355, 361, 362, + 362, 356, 355, + 356, 362, 363, + 363, 357, 356, + 357, 363, 364, + 364, 358, 357, + 358, 364, 365, + 365, 359, 358, + 221, 227, 366, + 366, 360, 221, + 360, 366, 367, + 367, 361, 360, + 361, 367, 368, + 368, 362, 361, + 362, 368, 369, + 369, 363, 362, + 363, 369, 370, + 370, 364, 363, + 364, 370, 371, + 371, 365, 364, + 227, 233, 372, + 372, 366, 227, + 366, 372, 373, + 373, 367, 366, + 367, 373, 374, + 374, 368, 367, + 368, 374, 375, + 375, 369, 368, + 369, 375, 376, + 376, 370, 369, + 370, 376, 377, + 377, 371, 370, + 233, 239, 378, + 378, 372, 233, + 372, 378, 379, + 379, 373, 372, + 373, 379, 380, + 380, 374, 373, + 374, 380, 381, + 381, 375, 374, + 375, 381, 382, + 382, 376, 375, + 376, 382, 383, + 383, 377, 376, + 239, 245, 384, + 384, 378, 239, + 378, 384, 385, + 385, 379, 378, + 379, 385, 386, + 386, 380, 379, + 380, 386, 387, + 387, 381, 380, + 381, 387, 388, + 388, 382, 381, + 382, 388, 389, + 389, 383, 382, + 245, 251, 390, + 390, 384, 245, + 384, 390, 391, + 391, 385, 384, + 385, 391, 392, + 392, 386, 385, + 386, 392, 393, + 393, 387, 386, + 387, 393, 394, + 394, 388, 387, + 388, 394, 395, + 395, 389, 388, + 251, 257, 396, + 396, 390, 251, + 390, 396, 397, + 397, 391, 390, + 391, 397, 398, + 398, 392, 391, + 392, 398, 399, + 399, 393, 392, + 393, 399, 400, + 400, 394, 393, + 394, 400, 401, + 401, 395, 394, + 257, 263, 402, + 402, 396, 257, + 396, 402, 403, + 403, 397, 396, + 397, 403, 404, + 404, 398, 397, + 398, 404, 405, + 405, 399, 398, + 399, 405, 406, + 406, 400, 399, + 400, 406, 407, + 407, 401, 400, + 263, 269, 408, + 408, 402, 263, + 402, 408, 409, + 409, 403, 402, + 403, 409, 410, + 410, 404, 403, + 404, 410, 411, + 411, 405, 404, + 405, 411, 412, + 412, 406, 405, + 406, 412, 413, + 413, 407, 406, + 269, 275, 414, + 414, 408, 269, + 408, 414, 415, + 415, 409, 408, + 409, 415, 416, + 416, 410, 409, + 410, 416, 417, + 417, 411, 410, + 411, 417, 418, + 418, 412, 411, + 412, 418, 419, + 419, 413, 412, + 275, 281, 420, + 420, 414, 275, + 414, 420, 421, + 421, 415, 414, + 415, 421, 422, + 422, 416, 415, + 416, 422, 423, + 423, 417, 416, + 417, 423, 424, + 424, 418, 417, + 418, 424, 425, + 425, 419, 418, + 281, 287, 426, + 426, 420, 281, + 420, 426, 427, + 427, 421, 420, + 421, 427, 428, + 428, 422, 421, + 422, 428, 429, + 429, 423, 422, + 423, 429, 430, + 430, 424, 423, + 424, 430, 431, + 431, 425, 424, + 287, 293, 432, + 432, 426, 287, + 426, 432, 433, + 433, 427, 426, + 427, 433, 434, + 434, 428, 427, + 428, 434, 435, + 435, 429, 428, + 429, 435, 436, + 436, 430, 429, + 430, 436, 437, + 437, 431, 430, + 293, 299, 438, + 438, 432, 293, + 432, 438, 439, + 439, 433, 432, + 433, 439, 440, + 440, 434, 433, + 434, 440, 441, + 441, 435, 434, + 435, 441, 442, + 442, 436, 435, + 436, 442, 443, + 443, 437, 436, + 299, 305, 444, + 444, 438, 299, + 438, 444, 445, + 445, 439, 438, + 439, 445, 446, + 446, 440, 439, + 440, 446, 447, + 447, 441, 440, + 441, 447, 448, + 448, 442, 441, + 442, 448, 449, + 449, 443, 442, + 305, 311, 450, + 450, 444, 305, + 444, 450, 451, + 451, 445, 444, + 445, 451, 452, + 452, 446, 445, + 446, 452, 453, + 453, 447, 446, + 447, 453, 454, + 454, 448, 447, + 448, 454, 455, + 455, 449, 448, + 311, 173, 312, + 312, 450, 311, + 450, 312, 313, + 313, 451, 450, + 451, 313, 314, + 314, 452, 451, + 452, 314, 315, + 315, 453, 452, + 453, 315, 316, + 316, 454, 453, + 454, 316, 317, + 317, 455, 454, + 317, 323, 462, + 462, 456, 317, + 456, 462, 463, + 463, 457, 456, + 457, 463, 464, + 464, 458, 457, + 458, 464, 465, + 465, 459, 458, + 459, 465, 466, + 466, 460, 459, + 460, 466, 461, + 323, 329, 467, + 467, 462, 323, + 462, 467, 468, + 468, 463, 462, + 463, 468, 469, + 469, 464, 463, + 464, 469, 470, + 470, 465, 464, + 465, 470, 471, + 471, 466, 465, + 466, 471, 461, + 329, 335, 472, + 472, 467, 329, + 467, 472, 473, + 473, 468, 467, + 468, 473, 474, + 474, 469, 468, + 469, 474, 475, + 475, 470, 469, + 470, 475, 476, + 476, 471, 470, + 471, 476, 461, + 335, 341, 477, + 477, 472, 335, + 472, 477, 478, + 478, 473, 472, + 473, 478, 479, + 479, 474, 473, + 474, 479, 480, + 480, 475, 474, + 475, 480, 481, + 481, 476, 475, + 476, 481, 461, + 341, 347, 482, + 482, 477, 341, + 477, 482, 483, + 483, 478, 477, + 478, 483, 484, + 484, 479, 478, + 479, 484, 485, + 485, 480, 479, + 480, 485, 486, + 486, 481, 480, + 481, 486, 461, + 347, 353, 487, + 487, 482, 347, + 482, 487, 488, + 488, 483, 482, + 483, 488, 489, + 489, 484, 483, + 484, 489, 490, + 490, 485, 484, + 485, 490, 491, + 491, 486, 485, + 486, 491, 461, + 353, 359, 492, + 492, 487, 353, + 487, 492, 493, + 493, 488, 487, + 488, 493, 494, + 494, 489, 488, + 489, 494, 495, + 495, 490, 489, + 490, 495, 496, + 496, 491, 490, + 491, 496, 461, + 359, 365, 497, + 497, 492, 359, + 492, 497, 498, + 498, 493, 492, + 493, 498, 499, + 499, 494, 493, + 494, 499, 500, + 500, 495, 494, + 495, 500, 501, + 501, 496, 495, + 496, 501, 461, + 365, 371, 502, + 502, 497, 365, + 497, 502, 503, + 503, 498, 497, + 498, 503, 504, + 504, 499, 498, + 499, 504, 505, + 505, 500, 499, + 500, 505, 506, + 506, 501, 500, + 501, 506, 461, + 371, 377, 507, + 507, 502, 371, + 502, 507, 508, + 508, 503, 502, + 503, 508, 509, + 509, 504, 503, + 504, 509, 510, + 510, 505, 504, + 505, 510, 511, + 511, 506, 505, + 506, 511, 461, + 377, 383, 512, + 512, 507, 377, + 507, 512, 513, + 513, 508, 507, + 508, 513, 514, + 514, 509, 508, + 509, 514, 515, + 515, 510, 509, + 510, 515, 516, + 516, 511, 510, + 511, 516, 461, + 383, 389, 517, + 517, 512, 383, + 512, 517, 518, + 518, 513, 512, + 513, 518, 519, + 519, 514, 513, + 514, 519, 520, + 520, 515, 514, + 515, 520, 521, + 521, 516, 515, + 516, 521, 461, + 389, 395, 522, + 522, 517, 389, + 517, 522, 523, + 523, 518, 517, + 518, 523, 524, + 524, 519, 518, + 519, 524, 525, + 525, 520, 519, + 520, 525, 526, + 526, 521, 520, + 521, 526, 461, + 395, 401, 527, + 527, 522, 395, + 522, 527, 528, + 528, 523, 522, + 523, 528, 529, + 529, 524, 523, + 524, 529, 530, + 530, 525, 524, + 525, 530, 531, + 531, 526, 525, + 526, 531, 461, + 401, 407, 532, + 532, 527, 401, + 527, 532, 533, + 533, 528, 527, + 528, 533, 534, + 534, 529, 528, + 529, 534, 535, + 535, 530, 529, + 530, 535, 536, + 536, 531, 530, + 531, 536, 461, + 407, 413, 537, + 537, 532, 407, + 532, 537, 538, + 538, 533, 532, + 533, 538, 539, + 539, 534, 533, + 534, 539, 540, + 540, 535, 534, + 535, 540, 541, + 541, 536, 535, + 536, 541, 461, + 413, 419, 542, + 542, 537, 413, + 537, 542, 543, + 543, 538, 537, + 538, 543, 544, + 544, 539, 538, + 539, 544, 545, + 545, 540, 539, + 540, 545, 546, + 546, 541, 540, + 541, 546, 461, + 419, 425, 547, + 547, 542, 419, + 542, 547, 548, + 548, 543, 542, + 543, 548, 549, + 549, 544, 543, + 544, 549, 550, + 550, 545, 544, + 545, 550, 551, + 551, 546, 545, + 546, 551, 461, + 425, 431, 552, + 552, 547, 425, + 547, 552, 553, + 553, 548, 547, + 548, 553, 554, + 554, 549, 548, + 549, 554, 555, + 555, 550, 549, + 550, 555, 556, + 556, 551, 550, + 551, 556, 461, + 431, 437, 557, + 557, 552, 431, + 552, 557, 558, + 558, 553, 552, + 553, 558, 559, + 559, 554, 553, + 554, 559, 560, + 560, 555, 554, + 555, 560, 561, + 561, 556, 555, + 556, 561, 461, + 437, 443, 562, + 562, 557, 437, + 557, 562, 563, + 563, 558, 557, + 558, 563, 564, + 564, 559, 558, + 559, 564, 565, + 565, 560, 559, + 560, 565, 566, + 566, 561, 560, + 561, 566, 461, + 443, 449, 567, + 567, 562, 443, + 562, 567, 568, + 568, 563, 562, + 563, 568, 569, + 569, 564, 563, + 564, 569, 570, + 570, 565, 564, + 565, 570, 571, + 571, 566, 565, + 566, 571, 461, + 449, 455, 572, + 572, 567, 449, + 567, 572, 573, + 573, 568, 567, + 568, 573, 574, + 574, 569, 568, + 569, 574, 575, + 575, 570, 569, + 570, 575, 576, + 576, 571, 570, + 571, 576, 461, + 455, 317, 456, + 456, 572, 455, + 572, 456, 457, + 457, 573, 572, + 573, 457, 458, + 458, 574, 573, + 574, 458, 459, + 459, 575, 574, + 575, 459, 460, + 460, 576, 575, + 576, 460, 461, + 577, 584, 585, + 585, 578, 577, + 578, 585, 586, + 586, 579, 578, + 579, 586, 587, + 587, 580, 579, + 580, 587, 588, + 588, 581, 580, + 581, 588, 589, + 589, 582, 581, + 582, 589, 590, + 590, 583, 582, + 584, 591, 592, + 592, 585, 584, + 585, 592, 593, + 593, 586, 585, + 586, 593, 594, + 594, 587, 586, + 587, 594, 595, + 595, 588, 587, + 588, 595, 596, + 596, 589, 588, + 589, 596, 597, + 597, 590, 589, + 591, 598, 599, + 599, 592, 591, + 592, 599, 600, + 600, 593, 592, + 593, 600, 601, + 601, 594, 593, + 594, 601, 602, + 602, 595, 594, + 595, 602, 603, + 603, 596, 595, + 596, 603, 604, + 604, 597, 596, + 598, 605, 606, + 606, 599, 598, + 599, 606, 607, + 607, 600, 599, + 600, 607, 608, + 608, 601, 600, + 601, 608, 609, + 609, 602, 601, + 602, 609, 610, + 610, 603, 602, + 603, 610, 611, + 611, 604, 603, + 605, 612, 613, + 613, 606, 605, + 606, 613, 614, + 614, 607, 606, + 607, 614, 615, + 615, 608, 607, + 608, 615, 616, + 616, 609, 608, + 609, 616, 617, + 617, 610, 609, + 610, 617, 618, + 618, 611, 610, + 612, 619, 620, + 620, 613, 612, + 613, 620, 621, + 621, 614, 613, + 614, 621, 622, + 622, 615, 614, + 615, 622, 623, + 623, 616, 615, + 616, 623, 624, + 624, 617, 616, + 617, 624, 625, + 625, 618, 617, + 619, 626, 627, + 627, 620, 619, + 620, 627, 628, + 628, 621, 620, + 621, 628, 629, + 629, 622, 621, + 622, 629, 630, + 630, 623, 622, + 623, 630, 631, + 631, 624, 623, + 624, 631, 632, + 632, 625, 624, + 626, 633, 634, + 634, 627, 626, + 627, 634, 635, + 635, 628, 627, + 628, 635, 636, + 636, 629, 628, + 629, 636, 637, + 637, 630, 629, + 630, 637, 638, + 638, 631, 630, + 631, 638, 639, + 639, 632, 631, + 633, 640, 641, + 641, 634, 633, + 634, 641, 642, + 642, 635, 634, + 635, 642, 643, + 643, 636, 635, + 636, 643, 644, + 644, 637, 636, + 637, 644, 645, + 645, 638, 637, + 638, 645, 646, + 646, 639, 638, + 640, 647, 648, + 648, 641, 640, + 641, 648, 649, + 649, 642, 641, + 642, 649, 650, + 650, 643, 642, + 643, 650, 651, + 651, 644, 643, + 644, 651, 652, + 652, 645, 644, + 645, 652, 653, + 653, 646, 645, + 647, 654, 655, + 655, 648, 647, + 648, 655, 656, + 656, 649, 648, + 649, 656, 657, + 657, 650, 649, + 650, 657, 658, + 658, 651, 650, + 651, 658, 659, + 659, 652, 651, + 652, 659, 660, + 660, 653, 652, + 654, 577, 578, + 578, 655, 654, + 655, 578, 579, + 579, 656, 655, + 656, 579, 580, + 580, 657, 656, + 657, 580, 581, + 581, 658, 657, + 658, 581, 582, + 582, 659, 658, + 659, 582, 583, + 583, 660, 659, + 583, 590, 667, + 667, 661, 583, + 661, 667, 668, + 668, 662, 661, + 662, 668, 669, + 669, 663, 662, + 663, 669, 670, + 670, 664, 663, + 664, 670, 671, + 671, 665, 664, + 665, 671, 672, + 672, 666, 665, + 590, 597, 673, + 673, 667, 590, + 667, 673, 674, + 674, 668, 667, + 668, 674, 675, + 675, 669, 668, + 669, 675, 676, + 676, 670, 669, + 670, 676, 677, + 677, 671, 670, + 671, 677, 678, + 678, 672, 671, + 597, 604, 679, + 679, 673, 597, + 673, 679, 680, + 680, 674, 673, + 674, 680, 681, + 681, 675, 674, + 675, 681, 682, + 682, 676, 675, + 676, 682, 683, + 683, 677, 676, + 677, 683, 684, + 684, 678, 677, + 604, 611, 685, + 685, 679, 604, + 679, 685, 686, + 686, 680, 679, + 680, 686, 687, + 687, 681, 680, + 681, 687, 688, + 688, 682, 681, + 682, 688, 689, + 689, 683, 682, + 683, 689, 690, + 690, 684, 683, + 611, 618, 691, + 691, 685, 611, + 685, 691, 692, + 692, 686, 685, + 686, 692, 693, + 693, 687, 686, + 687, 693, 694, + 694, 688, 687, + 688, 694, 695, + 695, 689, 688, + 689, 695, 696, + 696, 690, 689, + 618, 625, 697, + 697, 691, 618, + 691, 697, 698, + 698, 692, 691, + 692, 698, 699, + 699, 693, 692, + 693, 699, 700, + 700, 694, 693, + 694, 700, 701, + 701, 695, 694, + 695, 701, 702, + 702, 696, 695, + 625, 632, 703, + 703, 697, 625, + 697, 703, 704, + 704, 698, 697, + 698, 704, 705, + 705, 699, 698, + 699, 705, 706, + 706, 700, 699, + 700, 706, 707, + 707, 701, 700, + 701, 707, 708, + 708, 702, 701, + 632, 639, 709, + 709, 703, 632, + 703, 709, 710, + 710, 704, 703, + 704, 710, 711, + 711, 705, 704, + 705, 711, 712, + 712, 706, 705, + 706, 712, 713, + 713, 707, 706, + 707, 713, 714, + 714, 708, 707, + 639, 646, 715, + 715, 709, 639, + 709, 715, 716, + 716, 710, 709, + 710, 716, 717, + 717, 711, 710, + 711, 717, 718, + 718, 712, 711, + 712, 718, 719, + 719, 713, 712, + 713, 719, 720, + 720, 714, 713, + 646, 653, 721, + 721, 715, 646, + 715, 721, 722, + 722, 716, 715, + 716, 722, 723, + 723, 717, 716, + 717, 723, 724, + 724, 718, 717, + 718, 724, 725, + 725, 719, 718, + 719, 725, 726, + 726, 720, 719, + 653, 660, 727, + 727, 721, 653, + 721, 727, 728, + 728, 722, 721, + 722, 728, 729, + 729, 723, 722, + 723, 729, 730, + 730, 724, 723, + 724, 730, 731, + 731, 725, 724, + 725, 731, 732, + 732, 726, 725, + 660, 583, 661, + 661, 727, 660, + 727, 661, 662, + 662, 728, 727, + 728, 662, 663, + 663, 729, 728, + 729, 663, 664, + 664, 730, 729, + 730, 664, 665, + 665, 731, 730, + 731, 665, 666, + 666, 732, 731, + 733, 740, 741, + 741, 734, 733, + 734, 741, 742, + 742, 735, 734, + 735, 742, 743, + 743, 736, 735, + 736, 743, 744, + 744, 737, 736, + 737, 744, 745, + 745, 738, 737, + 738, 745, 746, + 746, 739, 738, + 740, 747, 748, + 748, 741, 740, + 741, 748, 749, + 749, 742, 741, + 742, 749, 750, + 750, 743, 742, + 743, 750, 751, + 751, 744, 743, + 744, 751, 752, + 752, 745, 744, + 745, 752, 753, + 753, 746, 745, + 747, 754, 755, + 755, 748, 747, + 748, 755, 756, + 756, 749, 748, + 749, 756, 757, + 757, 750, 749, + 750, 757, 758, + 758, 751, 750, + 751, 758, 759, + 759, 752, 751, + 752, 759, 760, + 760, 753, 752, + 754, 761, 762, + 762, 755, 754, + 755, 762, 763, + 763, 756, 755, + 756, 763, 764, + 764, 757, 756, + 757, 764, 765, + 765, 758, 757, + 758, 765, 766, + 766, 759, 758, + 759, 766, 767, + 767, 760, 759, + 761, 768, 769, + 769, 762, 761, + 762, 769, 770, + 770, 763, 762, + 763, 770, 771, + 771, 764, 763, + 764, 771, 772, + 772, 765, 764, + 765, 772, 773, + 773, 766, 765, + 766, 773, 774, + 774, 767, 766, + 768, 775, 776, + 776, 769, 768, + 769, 776, 777, + 777, 770, 769, + 770, 777, 778, + 778, 771, 770, + 771, 778, 779, + 779, 772, 771, + 772, 779, 780, + 780, 773, 772, + 773, 780, 781, + 781, 774, 773, + 775, 782, 783, + 783, 776, 775, + 776, 783, 784, + 784, 777, 776, + 777, 784, 785, + 785, 778, 777, + 778, 785, 786, + 786, 779, 778, + 779, 786, 787, + 787, 780, 779, + 780, 787, 788, + 788, 781, 780, + 782, 789, 790, + 790, 783, 782, + 783, 790, 791, + 791, 784, 783, + 784, 791, 792, + 792, 785, 784, + 785, 792, 793, + 793, 786, 785, + 786, 793, 794, + 794, 787, 786, + 787, 794, 795, + 795, 788, 787, + 789, 796, 797, + 797, 790, 789, + 790, 797, 798, + 798, 791, 790, + 791, 798, 799, + 799, 792, 791, + 792, 799, 800, + 800, 793, 792, + 793, 800, 801, + 801, 794, 793, + 794, 801, 802, + 802, 795, 794, + 796, 803, 804, + 804, 797, 796, + 797, 804, 805, + 805, 798, 797, + 798, 805, 806, + 806, 799, 798, + 799, 806, 807, + 807, 800, 799, + 800, 807, 808, + 808, 801, 800, + 801, 808, 809, + 809, 802, 801, + 803, 810, 811, + 811, 804, 803, + 804, 811, 812, + 812, 805, 804, + 805, 812, 813, + 813, 806, 805, + 806, 813, 814, + 814, 807, 806, + 807, 814, 815, + 815, 808, 807, + 808, 815, 816, + 816, 809, 808, + 810, 733, 734, + 734, 811, 810, + 811, 734, 735, + 735, 812, 811, + 812, 735, 736, + 736, 813, 812, + 813, 736, 737, + 737, 814, 813, + 814, 737, 738, + 738, 815, 814, + 815, 738, 739, + 739, 816, 815, + 739, 746, 823, + 823, 817, 739, + 817, 823, 824, + 824, 818, 817, + 818, 824, 825, + 825, 819, 818, + 819, 825, 826, + 826, 820, 819, + 820, 826, 827, + 827, 821, 820, + 821, 827, 828, + 828, 822, 821, + 746, 753, 829, + 829, 823, 746, + 823, 829, 830, + 830, 824, 823, + 824, 830, 831, + 831, 825, 824, + 825, 831, 832, + 832, 826, 825, + 826, 832, 833, + 833, 827, 826, + 827, 833, 834, + 834, 828, 827, + 753, 760, 835, + 835, 829, 753, + 829, 835, 836, + 836, 830, 829, + 830, 836, 837, + 837, 831, 830, + 831, 837, 838, + 838, 832, 831, + 832, 838, 839, + 839, 833, 832, + 833, 839, 840, + 840, 834, 833, + 760, 767, 841, + 841, 835, 760, + 835, 841, 842, + 842, 836, 835, + 836, 842, 843, + 843, 837, 836, + 837, 843, 844, + 844, 838, 837, + 838, 844, 845, + 845, 839, 838, + 839, 845, 846, + 846, 840, 839, + 767, 774, 847, + 847, 841, 767, + 841, 847, 848, + 848, 842, 841, + 842, 848, 849, + 849, 843, 842, + 843, 849, 850, + 850, 844, 843, + 844, 850, 851, + 851, 845, 844, + 845, 851, 852, + 852, 846, 845, + 774, 781, 853, + 853, 847, 774, + 847, 853, 854, + 854, 848, 847, + 848, 854, 855, + 855, 849, 848, + 849, 855, 856, + 856, 850, 849, + 850, 856, 857, + 857, 851, 850, + 851, 857, 858, + 858, 852, 851, + 781, 788, 859, + 859, 853, 781, + 853, 859, 860, + 860, 854, 853, + 854, 860, 861, + 861, 855, 854, + 855, 861, 862, + 862, 856, 855, + 856, 862, 863, + 863, 857, 856, + 857, 863, 864, + 864, 858, 857, + 788, 795, 865, + 865, 859, 788, + 859, 865, 866, + 866, 860, 859, + 860, 866, 867, + 867, 861, 860, + 861, 867, 868, + 868, 862, 861, + 862, 868, 869, + 869, 863, 862, + 863, 869, 870, + 870, 864, 863, + 795, 802, 871, + 871, 865, 795, + 865, 871, 872, + 872, 866, 865, + 866, 872, 873, + 873, 867, 866, + 867, 873, 874, + 874, 868, 867, + 868, 874, 875, + 875, 869, 868, + 869, 875, 876, + 876, 870, 869, + 802, 809, 877, + 877, 871, 802, + 871, 877, 878, + 878, 872, 871, + 872, 878, 879, + 879, 873, 872, + 873, 879, 880, + 880, 874, 873, + 874, 880, 881, + 881, 875, 874, + 875, 881, 882, + 882, 876, 875, + 809, 816, 883, + 883, 877, 809, + 877, 883, 884, + 884, 878, 877, + 878, 884, 885, + 885, 879, 878, + 879, 885, 886, + 886, 880, 879, + 880, 886, 887, + 887, 881, 880, + 881, 887, 888, + 888, 882, 881, + 816, 739, 817, + 817, 883, 816, + 883, 817, 818, + 818, 884, 883, + 884, 818, 819, + 819, 885, 884, + 885, 819, 820, + 820, 886, 885, + 886, 820, 821, + 821, 887, 886, + 887, 821, 822, + 822, 888, 887, + 896, 890, 889, + 890, 896, 897, + 897, 891, 890, + 891, 897, 898, + 898, 892, 891, + 892, 898, 899, + 899, 893, 892, + 893, 899, 900, + 900, 894, 893, + 894, 900, 901, + 901, 895, 894, + 902, 896, 889, + 896, 902, 903, + 903, 897, 896, + 897, 903, 904, + 904, 898, 897, + 898, 904, 905, + 905, 899, 898, + 899, 905, 906, + 906, 900, 899, + 900, 906, 907, + 907, 901, 900, + 908, 902, 889, + 902, 908, 909, + 909, 903, 902, + 903, 909, 910, + 910, 904, 903, + 904, 910, 911, + 911, 905, 904, + 905, 911, 912, + 912, 906, 905, + 906, 912, 913, + 913, 907, 906, + 914, 908, 889, + 908, 914, 915, + 915, 909, 908, + 909, 915, 916, + 916, 910, 909, + 910, 916, 917, + 917, 911, 910, + 911, 917, 918, + 918, 912, 911, + 912, 918, 919, + 919, 913, 912, + 920, 914, 889, + 914, 920, 921, + 921, 915, 914, + 915, 921, 922, + 922, 916, 915, + 916, 922, 923, + 923, 917, 916, + 917, 923, 924, + 924, 918, 917, + 918, 924, 925, + 925, 919, 918, + 926, 920, 889, + 920, 926, 927, + 927, 921, 920, + 921, 927, 928, + 928, 922, 921, + 922, 928, 929, + 929, 923, 922, + 923, 929, 930, + 930, 924, 923, + 924, 930, 931, + 931, 925, 924, + 932, 926, 889, + 926, 932, 933, + 933, 927, 926, + 927, 933, 934, + 934, 928, 927, + 928, 934, 935, + 935, 929, 928, + 929, 935, 936, + 936, 930, 929, + 930, 936, 937, + 937, 931, 930, + 938, 932, 889, + 932, 938, 939, + 939, 933, 932, + 933, 939, 940, + 940, 934, 933, + 934, 940, 941, + 941, 935, 934, + 935, 941, 942, + 942, 936, 935, + 936, 942, 943, + 943, 937, 936, + 944, 938, 889, + 938, 944, 945, + 945, 939, 938, + 939, 945, 946, + 946, 940, 939, + 940, 946, 947, + 947, 941, 940, + 941, 947, 948, + 948, 942, 941, + 942, 948, 949, + 949, 943, 942, + 950, 944, 889, + 944, 950, 951, + 951, 945, 944, + 945, 951, 952, + 952, 946, 945, + 946, 952, 953, + 953, 947, 946, + 947, 953, 954, + 954, 948, 947, + 948, 954, 955, + 955, 949, 948, + 956, 950, 889, + 950, 956, 957, + 957, 951, 950, + 951, 957, 958, + 958, 952, 951, + 952, 958, 959, + 959, 953, 952, + 953, 959, 960, + 960, 954, 953, + 954, 960, 961, + 961, 955, 954, + 962, 956, 889, + 956, 962, 963, + 963, 957, 956, + 957, 963, 964, + 964, 958, 957, + 958, 964, 965, + 965, 959, 958, + 959, 965, 966, + 966, 960, 959, + 960, 966, 967, + 967, 961, 960, + 968, 962, 889, + 962, 968, 969, + 969, 963, 962, + 963, 969, 970, + 970, 964, 963, + 964, 970, 971, + 971, 965, 964, + 965, 971, 972, + 972, 966, 965, + 966, 972, 973, + 973, 967, 966, + 974, 968, 889, + 968, 974, 975, + 975, 969, 968, + 969, 975, 976, + 976, 970, 969, + 970, 976, 977, + 977, 971, 970, + 971, 977, 978, + 978, 972, 971, + 972, 978, 979, + 979, 973, 972, + 980, 974, 889, + 974, 980, 981, + 981, 975, 974, + 975, 981, 982, + 982, 976, 975, + 976, 982, 983, + 983, 977, 976, + 977, 983, 984, + 984, 978, 977, + 978, 984, 985, + 985, 979, 978, + 986, 980, 889, + 980, 986, 987, + 987, 981, 980, + 981, 987, 988, + 988, 982, 981, + 982, 988, 989, + 989, 983, 982, + 983, 989, 990, + 990, 984, 983, + 984, 990, 991, + 991, 985, 984, + 992, 986, 889, + 986, 992, 993, + 993, 987, 986, + 987, 993, 994, + 994, 988, 987, + 988, 994, 995, + 995, 989, 988, + 989, 995, 996, + 996, 990, 989, + 990, 996, 997, + 997, 991, 990, + 998, 992, 889, + 992, 998, 999, + 999, 993, 992, + 993, 999, 1000, + 1000, 994, 993, + 994, 1000, 1001, + 1001, 995, 994, + 995, 1001, 1002, + 1002, 996, 995, + 996, 1002, 1003, + 1003, 997, 996, + 1004, 998, 889, + 998, 1004, 1005, + 1005, 999, 998, + 999, 1005, 1006, + 1006, 1000, 999, + 1000, 1006, 1007, + 1007, 1001, 1000, + 1001, 1007, 1008, + 1008, 1002, 1001, + 1002, 1008, 1009, + 1009, 1003, 1002, + 1010, 1004, 889, + 1004, 1010, 1011, + 1011, 1005, 1004, + 1005, 1011, 1012, + 1012, 1006, 1005, + 1006, 1012, 1013, + 1013, 1007, 1006, + 1007, 1013, 1014, + 1014, 1008, 1007, + 1008, 1014, 1015, + 1015, 1009, 1008, + 1016, 1010, 889, + 1010, 1016, 1017, + 1017, 1011, 1010, + 1011, 1017, 1018, + 1018, 1012, 1011, + 1012, 1018, 1019, + 1019, 1013, 1012, + 1013, 1019, 1020, + 1020, 1014, 1013, + 1014, 1020, 1021, + 1021, 1015, 1014, + 1022, 1016, 889, + 1016, 1022, 1023, + 1023, 1017, 1016, + 1017, 1023, 1024, + 1024, 1018, 1017, + 1018, 1024, 1025, + 1025, 1019, 1018, + 1019, 1025, 1026, + 1026, 1020, 1019, + 1020, 1026, 1027, + 1027, 1021, 1020, + 1028, 1022, 889, + 1022, 1028, 1029, + 1029, 1023, 1022, + 1023, 1029, 1030, + 1030, 1024, 1023, + 1024, 1030, 1031, + 1031, 1025, 1024, + 1025, 1031, 1032, + 1032, 1026, 1025, + 1026, 1032, 1033, + 1033, 1027, 1026, + 890, 1028, 889, + 1028, 890, 891, + 891, 1029, 1028, + 1029, 891, 892, + 892, 1030, 1029, + 1030, 892, 893, + 893, 1031, 1030, + 1031, 893, 894, + 894, 1032, 1031, + 1032, 894, 895, + 895, 1033, 1032, + 895, 901, 1040, + 1040, 1034, 895, + 1034, 1040, 1041, + 1041, 1035, 1034, + 1035, 1041, 1042, + 1042, 1036, 1035, + 1036, 1042, 1043, + 1043, 1037, 1036, + 1037, 1043, 1044, + 1044, 1038, 1037, + 1038, 1044, 1045, + 1045, 1039, 1038, + 901, 907, 1046, + 1046, 1040, 901, + 1040, 1046, 1047, + 1047, 1041, 1040, + 1041, 1047, 1048, + 1048, 1042, 1041, + 1042, 1048, 1049, + 1049, 1043, 1042, + 1043, 1049, 1050, + 1050, 1044, 1043, + 1044, 1050, 1051, + 1051, 1045, 1044, + 907, 913, 1052, + 1052, 1046, 907, + 1046, 1052, 1053, + 1053, 1047, 1046, + 1047, 1053, 1054, + 1054, 1048, 1047, + 1048, 1054, 1055, + 1055, 1049, 1048, + 1049, 1055, 1056, + 1056, 1050, 1049, + 1050, 1056, 1057, + 1057, 1051, 1050, + 913, 919, 1058, + 1058, 1052, 913, + 1052, 1058, 1059, + 1059, 1053, 1052, + 1053, 1059, 1060, + 1060, 1054, 1053, + 1054, 1060, 1061, + 1061, 1055, 1054, + 1055, 1061, 1062, + 1062, 1056, 1055, + 1056, 1062, 1063, + 1063, 1057, 1056, + 919, 925, 1064, + 1064, 1058, 919, + 1058, 1064, 1065, + 1065, 1059, 1058, + 1059, 1065, 1066, + 1066, 1060, 1059, + 1060, 1066, 1067, + 1067, 1061, 1060, + 1061, 1067, 1068, + 1068, 1062, 1061, + 1062, 1068, 1069, + 1069, 1063, 1062, + 925, 931, 1070, + 1070, 1064, 925, + 1064, 1070, 1071, + 1071, 1065, 1064, + 1065, 1071, 1072, + 1072, 1066, 1065, + 1066, 1072, 1073, + 1073, 1067, 1066, + 1067, 1073, 1074, + 1074, 1068, 1067, + 1068, 1074, 1075, + 1075, 1069, 1068, + 931, 937, 1076, + 1076, 1070, 931, + 1070, 1076, 1077, + 1077, 1071, 1070, + 1071, 1077, 1078, + 1078, 1072, 1071, + 1072, 1078, 1079, + 1079, 1073, 1072, + 1073, 1079, 1080, + 1080, 1074, 1073, + 1074, 1080, 1081, + 1081, 1075, 1074, + 937, 943, 1082, + 1082, 1076, 937, + 1076, 1082, 1083, + 1083, 1077, 1076, + 1077, 1083, 1084, + 1084, 1078, 1077, + 1078, 1084, 1085, + 1085, 1079, 1078, + 1079, 1085, 1086, + 1086, 1080, 1079, + 1080, 1086, 1087, + 1087, 1081, 1080, + 943, 949, 1088, + 1088, 1082, 943, + 1082, 1088, 1089, + 1089, 1083, 1082, + 1083, 1089, 1090, + 1090, 1084, 1083, + 1084, 1090, 1091, + 1091, 1085, 1084, + 1085, 1091, 1092, + 1092, 1086, 1085, + 1086, 1092, 1093, + 1093, 1087, 1086, + 949, 955, 1094, + 1094, 1088, 949, + 1088, 1094, 1095, + 1095, 1089, 1088, + 1089, 1095, 1096, + 1096, 1090, 1089, + 1090, 1096, 1097, + 1097, 1091, 1090, + 1091, 1097, 1098, + 1098, 1092, 1091, + 1092, 1098, 1099, + 1099, 1093, 1092, + 955, 961, 1100, + 1100, 1094, 955, + 1094, 1100, 1101, + 1101, 1095, 1094, + 1095, 1101, 1102, + 1102, 1096, 1095, + 1096, 1102, 1103, + 1103, 1097, 1096, + 1097, 1103, 1104, + 1104, 1098, 1097, + 1098, 1104, 1105, + 1105, 1099, 1098, + 961, 967, 1106, + 1106, 1100, 961, + 1100, 1106, 1107, + 1107, 1101, 1100, + 1101, 1107, 1108, + 1108, 1102, 1101, + 1102, 1108, 1109, + 1109, 1103, 1102, + 1103, 1109, 1110, + 1110, 1104, 1103, + 1104, 1110, 1111, + 1111, 1105, 1104, + 967, 973, 1112, + 1112, 1106, 967, + 1106, 1112, 1113, + 1113, 1107, 1106, + 1107, 1113, 1114, + 1114, 1108, 1107, + 1108, 1114, 1115, + 1115, 1109, 1108, + 1109, 1115, 1116, + 1116, 1110, 1109, + 1110, 1116, 1117, + 1117, 1111, 1110, + 973, 979, 1118, + 1118, 1112, 973, + 1112, 1118, 1119, + 1119, 1113, 1112, + 1113, 1119, 1120, + 1120, 1114, 1113, + 1114, 1120, 1121, + 1121, 1115, 1114, + 1115, 1121, 1122, + 1122, 1116, 1115, + 1116, 1122, 1123, + 1123, 1117, 1116, + 979, 985, 1124, + 1124, 1118, 979, + 1118, 1124, 1125, + 1125, 1119, 1118, + 1119, 1125, 1126, + 1126, 1120, 1119, + 1120, 1126, 1127, + 1127, 1121, 1120, + 1121, 1127, 1128, + 1128, 1122, 1121, + 1122, 1128, 1129, + 1129, 1123, 1122, + 985, 991, 1130, + 1130, 1124, 985, + 1124, 1130, 1131, + 1131, 1125, 1124, + 1125, 1131, 1132, + 1132, 1126, 1125, + 1126, 1132, 1133, + 1133, 1127, 1126, + 1127, 1133, 1134, + 1134, 1128, 1127, + 1128, 1134, 1135, + 1135, 1129, 1128, + 991, 997, 1136, + 1136, 1130, 991, + 1130, 1136, 1137, + 1137, 1131, 1130, + 1131, 1137, 1138, + 1138, 1132, 1131, + 1132, 1138, 1139, + 1139, 1133, 1132, + 1133, 1139, 1140, + 1140, 1134, 1133, + 1134, 1140, 1141, + 1141, 1135, 1134, + 997, 1003, 1142, + 1142, 1136, 997, + 1136, 1142, 1143, + 1143, 1137, 1136, + 1137, 1143, 1144, + 1144, 1138, 1137, + 1138, 1144, 1145, + 1145, 1139, 1138, + 1139, 1145, 1146, + 1146, 1140, 1139, + 1140, 1146, 1147, + 1147, 1141, 1140, + 1003, 1009, 1148, + 1148, 1142, 1003, + 1142, 1148, 1149, + 1149, 1143, 1142, + 1143, 1149, 1150, + 1150, 1144, 1143, + 1144, 1150, 1151, + 1151, 1145, 1144, + 1145, 1151, 1152, + 1152, 1146, 1145, + 1146, 1152, 1153, + 1153, 1147, 1146, + 1009, 1015, 1154, + 1154, 1148, 1009, + 1148, 1154, 1155, + 1155, 1149, 1148, + 1149, 1155, 1156, + 1156, 1150, 1149, + 1150, 1156, 1157, + 1157, 1151, 1150, + 1151, 1157, 1158, + 1158, 1152, 1151, + 1152, 1158, 1159, + 1159, 1153, 1152, + 1015, 1021, 1160, + 1160, 1154, 1015, + 1154, 1160, 1161, + 1161, 1155, 1154, + 1155, 1161, 1162, + 1162, 1156, 1155, + 1156, 1162, 1163, + 1163, 1157, 1156, + 1157, 1163, 1164, + 1164, 1158, 1157, + 1158, 1164, 1165, + 1165, 1159, 1158, + 1021, 1027, 1166, + 1166, 1160, 1021, + 1160, 1166, 1167, + 1167, 1161, 1160, + 1161, 1167, 1168, + 1168, 1162, 1161, + 1162, 1168, 1169, + 1169, 1163, 1162, + 1163, 1169, 1170, + 1170, 1164, 1163, + 1164, 1170, 1171, + 1171, 1165, 1164, + 1027, 1033, 1172, + 1172, 1166, 1027, + 1166, 1172, 1173, + 1173, 1167, 1166, + 1167, 1173, 1174, + 1174, 1168, 1167, + 1168, 1174, 1175, + 1175, 1169, 1168, + 1169, 1175, 1176, + 1176, 1170, 1169, + 1170, 1176, 1177, + 1177, 1171, 1170, + 1033, 895, 1034, + 1034, 1172, 1033, + 1172, 1034, 1035, + 1035, 1173, 1172, + 1173, 1035, 1036, + 1036, 1174, 1173, + 1174, 1036, 1037, + 1037, 1175, 1174, + 1175, 1037, 1038, + 1038, 1176, 1175, + 1176, 1038, 1039, + 1039, 1177, 1176, +}; + + +//---------------------------------------------------------------------------- +// MakeTeapot Helper +//---------------------------------------------------------------------------- +static void MakeTeapot( +VERTEX* pVertices, +WORD* pwIndices ) +{ + DWORD iVertex; + + // Copy vertices + for( iVertex = 0; iVertex < NUMTEAPOTVERTICES; iVertex++ ) + { + pVertices[iVertex].pos = teapotPositions[iVertex]; + pVertices[iVertex].norm = teapotNormals[iVertex]; + } + + // Copy face indices + WORD* pwFace = pwIndices; + WORD* pwFaceLim = pwFace + NUMTEAPOTINDICES; + WORD* pwTeapotFace = teapotIndices; + + while( pwFace < pwFaceLim ) + { + pwFace[0] = pwTeapotFace[0]; + pwFace[1] = pwTeapotFace[1]; + pwFace[2] = pwTeapotFace[2]; + + pwFace += 3; + pwTeapotFace += 3; + } +} + + +//---------------------------------------------------------------------------- +// DXUTCreateTeapot - createa teapot mesh +//---------------------------------------------------------------------------- +HRESULT WINAPI DXUTCreateTeapot( ID3D10Device* pDevice, ID3DX10Mesh** ppMesh ) +{ + HRESULT hr = S_OK; + + WORD* pwIndices = NULL; + VERTEX* pVertices = NULL; + + + // Validate parameters + if( !pDevice ) + return D3DERR_INVALIDCALL; + if( !ppMesh ) + return D3DERR_INVALIDCALL; + + // Create the mesh + UINT cFaces = NUMTEAPOTINDICES / 3; + UINT cVertices = NUMTEAPOTVERTICES; + + // Create enough memory for the vertices and indices + pVertices = new VERTEX[ cVertices ]; + if( !pVertices ) + return E_OUTOFMEMORY; + pwIndices = new WORD[ cFaces * 3 ]; + if( !pwIndices ) + return E_OUTOFMEMORY; + + // Create a teapot + MakeTeapot( pVertices, pwIndices ); + + // Create a mesh + hr = CreateShapeMesh( pDevice, ppMesh, pVertices, cVertices, pwIndices, cFaces * 3 ); + + // Free up the memory + SAFE_DELETE_ARRAY( pVertices ); + SAFE_DELETE_ARRAY( pwIndices ); + + return hr; +} diff --git a/Demos/DX11ClothDemo/DXUT/Optional/DXUTShapes.h b/Demos/DX11ClothDemo/DXUT/Optional/DXUTShapes.h new file mode 100644 index 0000000..c289231 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/DXUTShapes.h @@ -0,0 +1,24 @@ +//-------------------------------------------------------------------------------------- +// File: DXUTShapes.h +// +// Shape creation functions for DXUT +// +// Copyright (c) Microsoft Corporation. All rights reserved +//-------------------------------------------------------------------------------------- +#pragma once +#ifndef DXUT_SHAPES_H +#define DXUT_SHAPES_H +#include +#include + +HRESULT WINAPI DXUTCreateBox( ID3D10Device* pDevice, float fWidth, float fHeight, float fDepth, ID3DX10Mesh** ppMesh ); +HRESULT WINAPI DXUTCreateCylinder( ID3D10Device* pDevice, float fRadius1, float fRadius2, float fLength, UINT uSlices, + UINT uStacks, ID3DX10Mesh** ppMesh ); +HRESULT WINAPI DXUTCreatePolygon( ID3D10Device* pDevice, float fLength, UINT uSides, ID3DX10Mesh** ppMesh ); +HRESULT WINAPI DXUTCreateSphere( ID3D10Device* pDevice, float fRadius, UINT uSlices, UINT uStacks, + ID3DX10Mesh** ppMesh ); +HRESULT WINAPI DXUTCreateTorus( ID3D10Device* pDevice, float fInnerRadius, float fOuterRadius, UINT uSides, + UINT uRings, ID3DX10Mesh** ppMesh ); +HRESULT WINAPI DXUTCreateTeapot( ID3D10Device* pDevice, ID3DX10Mesh** ppMesh ); + +#endif diff --git a/Demos/DX11ClothDemo/DXUT/Optional/DXUTcamera.cpp b/Demos/DX11ClothDemo/DXUT/Optional/DXUTcamera.cpp new file mode 100644 index 0000000..8142e7c --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/DXUTcamera.cpp @@ -0,0 +1,1525 @@ +//-------------------------------------------------------------------------------------- +// File: DXUTcamera.cpp +// +// Copyright (c) Microsoft Corporation. All rights reserved +//-------------------------------------------------------------------------------------- +#include "DXUT.h" +#include "DXUTcamera.h" +#include "DXUTres.h" +#undef min // use __min instead +#undef max // use __max instead + +//-------------------------------------------------------------------------------------- +CD3DArcBall::CD3DArcBall() +{ + Reset(); + m_vDownPt = D3DXVECTOR3( 0, 0, 0 ); + m_vCurrentPt = D3DXVECTOR3( 0, 0, 0 ); + m_Offset.x = m_Offset.y = 0; + + RECT rc; + GetClientRect( GetForegroundWindow(), &rc ); + SetWindow( rc.right, rc.bottom ); +} + + + + + +//-------------------------------------------------------------------------------------- +void CD3DArcBall::Reset() +{ + D3DXQuaternionIdentity( &m_qDown ); + D3DXQuaternionIdentity( &m_qNow ); + D3DXMatrixIdentity( &m_mRotation ); + D3DXMatrixIdentity( &m_mTranslation ); + D3DXMatrixIdentity( &m_mTranslationDelta ); + m_bDrag = FALSE; + m_fRadiusTranslation = 1.0f; + m_fRadius = 1.0f; +} + + + + +//-------------------------------------------------------------------------------------- +D3DXVECTOR3 CD3DArcBall::ScreenToVector( float fScreenPtX, float fScreenPtY ) +{ + // Scale to screen + FLOAT x = -( fScreenPtX - m_Offset.x - m_nWidth / 2 ) / ( m_fRadius * m_nWidth / 2 ); + FLOAT y = ( fScreenPtY - m_Offset.y - m_nHeight / 2 ) / ( m_fRadius * m_nHeight / 2 ); + + FLOAT z = 0.0f; + FLOAT mag = x * x + y * y; + + if( mag > 1.0f ) + { + FLOAT scale = 1.0f / sqrtf( mag ); + x *= scale; + y *= scale; + } + else + z = sqrtf( 1.0f - mag ); + + // Return vector + return D3DXVECTOR3( x, y, z ); +} + + + + +//-------------------------------------------------------------------------------------- +D3DXQUATERNION CD3DArcBall::QuatFromBallPoints( const D3DXVECTOR3& vFrom, const D3DXVECTOR3& vTo ) +{ + D3DXVECTOR3 vPart; + float fDot = D3DXVec3Dot( &vFrom, &vTo ); + D3DXVec3Cross( &vPart, &vFrom, &vTo ); + + return D3DXQUATERNION( vPart.x, vPart.y, vPart.z, fDot ); +} + + + + +//-------------------------------------------------------------------------------------- +void CD3DArcBall::OnBegin( int nX, int nY ) +{ + // Only enter the drag state if the click falls + // inside the click rectangle. + if( nX >= m_Offset.x && + nX < m_Offset.x + m_nWidth && + nY >= m_Offset.y && + nY < m_Offset.y + m_nHeight ) + { + m_bDrag = true; + m_qDown = m_qNow; + m_vDownPt = ScreenToVector( ( float )nX, ( float )nY ); + } +} + + + + +//-------------------------------------------------------------------------------------- +void CD3DArcBall::OnMove( int nX, int nY ) +{ + if( m_bDrag ) + { + m_vCurrentPt = ScreenToVector( ( float )nX, ( float )nY ); + m_qNow = m_qDown * QuatFromBallPoints( m_vDownPt, m_vCurrentPt ); + } +} + + + + +//-------------------------------------------------------------------------------------- +void CD3DArcBall::OnEnd() +{ + m_bDrag = false; +} + + + + +//-------------------------------------------------------------------------------------- +// Desc: +//-------------------------------------------------------------------------------------- +LRESULT CD3DArcBall::HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + // Current mouse position + int iMouseX = ( short )LOWORD( lParam ); + int iMouseY = ( short )HIWORD( lParam ); + + switch( uMsg ) + { + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + SetCapture( hWnd ); + OnBegin( iMouseX, iMouseY ); + return TRUE; + + case WM_LBUTTONUP: + ReleaseCapture(); + OnEnd(); + return TRUE; + case WM_CAPTURECHANGED: + if( ( HWND )lParam != hWnd ) + { + ReleaseCapture(); + OnEnd(); + } + return TRUE; + + case WM_RBUTTONDOWN: + case WM_RBUTTONDBLCLK: + case WM_MBUTTONDOWN: + case WM_MBUTTONDBLCLK: + SetCapture( hWnd ); + // Store off the position of the cursor when the button is pressed + m_ptLastMouse.x = iMouseX; + m_ptLastMouse.y = iMouseY; + return TRUE; + + case WM_RBUTTONUP: + case WM_MBUTTONUP: + ReleaseCapture(); + return TRUE; + + case WM_MOUSEMOVE: + if( MK_LBUTTON & wParam ) + { + OnMove( iMouseX, iMouseY ); + } + else if( ( MK_RBUTTON & wParam ) || ( MK_MBUTTON & wParam ) ) + { + // Normalize based on size of window and bounding sphere radius + FLOAT fDeltaX = ( m_ptLastMouse.x - iMouseX ) * m_fRadiusTranslation / m_nWidth; + FLOAT fDeltaY = ( m_ptLastMouse.y - iMouseY ) * m_fRadiusTranslation / m_nHeight; + + if( wParam & MK_RBUTTON ) + { + D3DXMatrixTranslation( &m_mTranslationDelta, -2 * fDeltaX, 2 * fDeltaY, 0.0f ); + D3DXMatrixMultiply( &m_mTranslation, &m_mTranslation, &m_mTranslationDelta ); + } + else // wParam & MK_MBUTTON + { + D3DXMatrixTranslation( &m_mTranslationDelta, 0.0f, 0.0f, 5 * fDeltaY ); + D3DXMatrixMultiply( &m_mTranslation, &m_mTranslation, &m_mTranslationDelta ); + } + + // Store mouse coordinate + m_ptLastMouse.x = iMouseX; + m_ptLastMouse.y = iMouseY; + } + return TRUE; + } + + return FALSE; +} + + + + +//-------------------------------------------------------------------------------------- +// Constructor +//-------------------------------------------------------------------------------------- +CBaseCamera::CBaseCamera() +{ + m_cKeysDown = 0; + ZeroMemory( m_aKeys, sizeof( BYTE ) * CAM_MAX_KEYS ); + ZeroMemory( m_GamePad, sizeof( DXUT_GAMEPAD ) * DXUT_MAX_CONTROLLERS ); + + // Set attributes for the view matrix + D3DXVECTOR3 vEyePt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); + D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); + + // Setup the view matrix + SetViewParams( &vEyePt, &vLookatPt ); + + // Setup the projection matrix + SetProjParams( D3DX_PI / 4, 1.0f, 1.0f, 1000.0f ); + + GetCursorPos( &m_ptLastMousePosition ); + m_bMouseLButtonDown = false; + m_bMouseMButtonDown = false; + m_bMouseRButtonDown = false; + m_nCurrentButtonMask = 0; + m_nMouseWheelDelta = 0; + + m_fCameraYawAngle = 0.0f; + m_fCameraPitchAngle = 0.0f; + + SetRect( &m_rcDrag, LONG_MIN, LONG_MIN, LONG_MAX, LONG_MAX ); + m_vVelocity = D3DXVECTOR3( 0, 0, 0 ); + m_bMovementDrag = false; + m_vVelocityDrag = D3DXVECTOR3( 0, 0, 0 ); + m_fDragTimer = 0.0f; + m_fTotalDragTimeToZero = 0.25; + m_vRotVelocity = D3DXVECTOR2( 0, 0 ); + + m_fRotationScaler = 0.01f; + m_fMoveScaler = 5.0f; + + m_bInvertPitch = false; + m_bEnableYAxisMovement = true; + m_bEnablePositionMovement = true; + + m_vMouseDelta = D3DXVECTOR2( 0, 0 ); + m_fFramesToSmoothMouseData = 2.0f; + + m_bClipToBoundary = false; + m_vMinBoundary = D3DXVECTOR3( -1, -1, -1 ); + m_vMaxBoundary = D3DXVECTOR3( 1, 1, 1 ); + + m_bResetCursorAfterMove = false; +} + + +//-------------------------------------------------------------------------------------- +// Client can call this to change the position and direction of camera +//-------------------------------------------------------------------------------------- +VOID CBaseCamera::SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt ) +{ + if( NULL == pvEyePt || NULL == pvLookatPt ) + return; + + m_vDefaultEye = m_vEye = *pvEyePt; + m_vDefaultLookAt = m_vLookAt = *pvLookatPt; + + // Calc the view matrix + D3DXVECTOR3 vUp( 0,1,0 ); + D3DXMatrixLookAtLH( &m_mView, pvEyePt, pvLookatPt, &vUp ); + + D3DXMATRIX mInvView; + D3DXMatrixInverse( &mInvView, NULL, &m_mView ); + + // The axis basis vectors and camera position are stored inside the + // position matrix in the 4 rows of the camera's world matrix. + // To figure out the yaw/pitch of the camera, we just need the Z basis vector + D3DXVECTOR3* pZBasis = ( D3DXVECTOR3* )&mInvView._31; + + m_fCameraYawAngle = atan2f( pZBasis->x, pZBasis->z ); + float fLen = sqrtf( pZBasis->z * pZBasis->z + pZBasis->x * pZBasis->x ); + m_fCameraPitchAngle = -atan2f( pZBasis->y, fLen ); +} + + + + +//-------------------------------------------------------------------------------------- +// Calculates the projection matrix based on input params +//-------------------------------------------------------------------------------------- +VOID CBaseCamera::SetProjParams( FLOAT fFOV, FLOAT fAspect, FLOAT fNearPlane, + FLOAT fFarPlane ) +{ + // Set attributes for the projection matrix + m_fFOV = fFOV; + m_fAspect = fAspect; + m_fNearPlane = fNearPlane; + m_fFarPlane = fFarPlane; + + D3DXMatrixPerspectiveFovLH( &m_mProj, fFOV, fAspect, fNearPlane, fFarPlane ); +} + + + + +//-------------------------------------------------------------------------------------- +// Call this from your message proc so this class can handle window messages +//-------------------------------------------------------------------------------------- +LRESULT CBaseCamera::HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + UNREFERENCED_PARAMETER( hWnd ); + UNREFERENCED_PARAMETER( lParam ); + + switch( uMsg ) + { + case WM_KEYDOWN: + { + // Map this key to a D3DUtil_CameraKeys enum and update the + // state of m_aKeys[] by adding the KEY_WAS_DOWN_MASK|KEY_IS_DOWN_MASK mask + // only if the key is not down + D3DUtil_CameraKeys mappedKey = MapKey( ( UINT )wParam ); + if( mappedKey != CAM_UNKNOWN ) + { + if( FALSE == IsKeyDown( m_aKeys[mappedKey] ) ) + { + m_aKeys[ mappedKey ] = KEY_WAS_DOWN_MASK | KEY_IS_DOWN_MASK; + ++m_cKeysDown; + } + } + break; + } + + case WM_KEYUP: + { + // Map this key to a D3DUtil_CameraKeys enum and update the + // state of m_aKeys[] by removing the KEY_IS_DOWN_MASK mask. + D3DUtil_CameraKeys mappedKey = MapKey( ( UINT )wParam ); + if( mappedKey != CAM_UNKNOWN && ( DWORD )mappedKey < 8 ) + { + m_aKeys[ mappedKey ] &= ~KEY_IS_DOWN_MASK; + --m_cKeysDown; + } + break; + } + + case WM_RBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_LBUTTONDOWN: + case WM_RBUTTONDBLCLK: + case WM_MBUTTONDBLCLK: + case WM_LBUTTONDBLCLK: + { + // Compute the drag rectangle in screen coord. + POINT ptCursor = + { + ( short )LOWORD( lParam ), ( short )HIWORD( lParam ) + }; + + // Update member var state + if( ( uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK ) && PtInRect( &m_rcDrag, ptCursor ) ) + { + m_bMouseLButtonDown = true; m_nCurrentButtonMask |= MOUSE_LEFT_BUTTON; + } + if( ( uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONDBLCLK ) && PtInRect( &m_rcDrag, ptCursor ) ) + { + m_bMouseMButtonDown = true; m_nCurrentButtonMask |= MOUSE_MIDDLE_BUTTON; + } + if( ( uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK ) && PtInRect( &m_rcDrag, ptCursor ) ) + { + m_bMouseRButtonDown = true; m_nCurrentButtonMask |= MOUSE_RIGHT_BUTTON; + } + + // Capture the mouse, so if the mouse button is + // released outside the window, we'll get the WM_LBUTTONUP message + SetCapture( hWnd ); + GetCursorPos( &m_ptLastMousePosition ); + return TRUE; + } + + case WM_RBUTTONUP: + case WM_MBUTTONUP: + case WM_LBUTTONUP: + { + // Update member var state + if( uMsg == WM_LBUTTONUP ) + { + m_bMouseLButtonDown = false; m_nCurrentButtonMask &= ~MOUSE_LEFT_BUTTON; + } + if( uMsg == WM_MBUTTONUP ) + { + m_bMouseMButtonDown = false; m_nCurrentButtonMask &= ~MOUSE_MIDDLE_BUTTON; + } + if( uMsg == WM_RBUTTONUP ) + { + m_bMouseRButtonDown = false; m_nCurrentButtonMask &= ~MOUSE_RIGHT_BUTTON; + } + + // Release the capture if no mouse buttons down + if( !m_bMouseLButtonDown && + !m_bMouseRButtonDown && + !m_bMouseMButtonDown ) + { + ReleaseCapture(); + } + break; + } + + case WM_CAPTURECHANGED: + { + if( ( HWND )lParam != hWnd ) + { + if( ( m_nCurrentButtonMask & MOUSE_LEFT_BUTTON ) || + ( m_nCurrentButtonMask & MOUSE_MIDDLE_BUTTON ) || + ( m_nCurrentButtonMask & MOUSE_RIGHT_BUTTON ) ) + { + m_bMouseLButtonDown = false; + m_bMouseMButtonDown = false; + m_bMouseRButtonDown = false; + m_nCurrentButtonMask &= ~MOUSE_LEFT_BUTTON; + m_nCurrentButtonMask &= ~MOUSE_MIDDLE_BUTTON; + m_nCurrentButtonMask &= ~MOUSE_RIGHT_BUTTON; + ReleaseCapture(); + } + } + break; + } + + case WM_MOUSEWHEEL: + // Update member var state + m_nMouseWheelDelta += ( short )HIWORD( wParam ); + break; + } + + return FALSE; +} + +//-------------------------------------------------------------------------------------- +// Figure out the velocity based on keyboard input & drag if any +//-------------------------------------------------------------------------------------- +void CBaseCamera::GetInput( bool bGetKeyboardInput, bool bGetMouseInput, bool bGetGamepadInput, + bool bResetCursorAfterMove ) +{ + m_vKeyboardDirection = D3DXVECTOR3( 0, 0, 0 ); + if( bGetKeyboardInput ) + { + // Update acceleration vector based on keyboard state + if( IsKeyDown( m_aKeys[CAM_MOVE_FORWARD] ) ) + m_vKeyboardDirection.z += 1.0f; + if( IsKeyDown( m_aKeys[CAM_MOVE_BACKWARD] ) ) + m_vKeyboardDirection.z -= 1.0f; + if( m_bEnableYAxisMovement ) + { + if( IsKeyDown( m_aKeys[CAM_MOVE_UP] ) ) + m_vKeyboardDirection.y += 1.0f; + if( IsKeyDown( m_aKeys[CAM_MOVE_DOWN] ) ) + m_vKeyboardDirection.y -= 1.0f; + } + if( IsKeyDown( m_aKeys[CAM_STRAFE_RIGHT] ) ) + m_vKeyboardDirection.x += 1.0f; + if( IsKeyDown( m_aKeys[CAM_STRAFE_LEFT] ) ) + m_vKeyboardDirection.x -= 1.0f; + } + + if( bGetMouseInput ) + { + UpdateMouseDelta(); + } + + if( bGetGamepadInput ) + { + m_vGamePadLeftThumb = D3DXVECTOR3( 0, 0, 0 ); + m_vGamePadRightThumb = D3DXVECTOR3( 0, 0, 0 ); + + // Get controller state + for( DWORD iUserIndex = 0; iUserIndex < DXUT_MAX_CONTROLLERS; iUserIndex++ ) + { + DXUTGetGamepadState( iUserIndex, &m_GamePad[iUserIndex], true, true ); + + // Mark time if the controller is in a non-zero state + if( m_GamePad[iUserIndex].wButtons || + m_GamePad[iUserIndex].sThumbLX || m_GamePad[iUserIndex].sThumbLX || + m_GamePad[iUserIndex].sThumbRX || m_GamePad[iUserIndex].sThumbRY || + m_GamePad[iUserIndex].bLeftTrigger || m_GamePad[iUserIndex].bRightTrigger ) + { + m_GamePadLastActive[iUserIndex] = DXUTGetTime(); + } + } + + // Find out which controller was non-zero last + int iMostRecentlyActive = -1; + double fMostRecentlyActiveTime = 0.0f; + for( DWORD iUserIndex = 0; iUserIndex < DXUT_MAX_CONTROLLERS; iUserIndex++ ) + { + if( m_GamePadLastActive[iUserIndex] > fMostRecentlyActiveTime ) + { + fMostRecentlyActiveTime = m_GamePadLastActive[iUserIndex]; + iMostRecentlyActive = iUserIndex; + } + } + + // Use the most recent non-zero controller if its connected + if( iMostRecentlyActive >= 0 && m_GamePad[iMostRecentlyActive].bConnected ) + { + m_vGamePadLeftThumb.x = m_GamePad[iMostRecentlyActive].fThumbLX; + m_vGamePadLeftThumb.y = 0.0f; + m_vGamePadLeftThumb.z = m_GamePad[iMostRecentlyActive].fThumbLY; + + m_vGamePadRightThumb.x = m_GamePad[iMostRecentlyActive].fThumbRX; + m_vGamePadRightThumb.y = 0.0f; + m_vGamePadRightThumb.z = m_GamePad[iMostRecentlyActive].fThumbRY; + } + } +} + + +//-------------------------------------------------------------------------------------- +// Figure out the mouse delta based on mouse movement +//-------------------------------------------------------------------------------------- +void CBaseCamera::UpdateMouseDelta() +{ + POINT ptCurMouseDelta; + POINT ptCurMousePos; + + // Get current position of mouse + GetCursorPos( &ptCurMousePos ); + + // Calc how far it's moved since last frame + ptCurMouseDelta.x = ptCurMousePos.x - m_ptLastMousePosition.x; + ptCurMouseDelta.y = ptCurMousePos.y - m_ptLastMousePosition.y; + + // Record current position for next time + m_ptLastMousePosition = ptCurMousePos; + + if( m_bResetCursorAfterMove && DXUTIsActive() ) + { + // Set position of camera to center of desktop, + // so it always has room to move. This is very useful + // if the cursor is hidden. If this isn't done and cursor is hidden, + // then invisible cursor will hit the edge of the screen + // and the user can't tell what happened + POINT ptCenter; + + // Get the center of the current monitor + MONITORINFO mi; + mi.cbSize = sizeof( MONITORINFO ); + DXUTGetMonitorInfo( DXUTMonitorFromWindow( DXUTGetHWND(), MONITOR_DEFAULTTONEAREST ), &mi ); + ptCenter.x = ( mi.rcMonitor.left + mi.rcMonitor.right ) / 2; + ptCenter.y = ( mi.rcMonitor.top + mi.rcMonitor.bottom ) / 2; + SetCursorPos( ptCenter.x, ptCenter.y ); + m_ptLastMousePosition = ptCenter; + } + + // Smooth the relative mouse data over a few frames so it isn't + // jerky when moving slowly at low frame rates. + float fPercentOfNew = 1.0f / m_fFramesToSmoothMouseData; + float fPercentOfOld = 1.0f - fPercentOfNew; + m_vMouseDelta.x = m_vMouseDelta.x * fPercentOfOld + ptCurMouseDelta.x * fPercentOfNew; + m_vMouseDelta.y = m_vMouseDelta.y * fPercentOfOld + ptCurMouseDelta.y * fPercentOfNew; + + m_vRotVelocity = m_vMouseDelta * m_fRotationScaler; +} + + + + +//-------------------------------------------------------------------------------------- +// Figure out the velocity based on keyboard input & drag if any +//-------------------------------------------------------------------------------------- +void CBaseCamera::UpdateVelocity( float fElapsedTime ) +{ + D3DXMATRIX mRotDelta; + D3DXVECTOR2 vGamePadRightThumb = D3DXVECTOR2( m_vGamePadRightThumb.x, -m_vGamePadRightThumb.z ); + m_vRotVelocity = m_vMouseDelta * m_fRotationScaler + vGamePadRightThumb * 0.02f; + + D3DXVECTOR3 vAccel = m_vKeyboardDirection + m_vGamePadLeftThumb; + + // Normalize vector so if moving 2 dirs (left & forward), + // the camera doesn't move faster than if moving in 1 dir + D3DXVec3Normalize( &vAccel, &vAccel ); + + // Scale the acceleration vector + vAccel *= m_fMoveScaler; + + if( m_bMovementDrag ) + { + // Is there any acceleration this frame? + if( D3DXVec3LengthSq( &vAccel ) > 0 ) + { + // If so, then this means the user has pressed a movement key\ + // so change the velocity immediately to acceleration + // upon keyboard input. This isn't normal physics + // but it will give a quick response to keyboard input + m_vVelocity = vAccel; + m_fDragTimer = m_fTotalDragTimeToZero; + m_vVelocityDrag = vAccel / m_fDragTimer; + } + else + { + // If no key being pressed, then slowly decrease velocity to 0 + if( m_fDragTimer > 0 ) + { + // Drag until timer is <= 0 + m_vVelocity -= m_vVelocityDrag * fElapsedTime; + m_fDragTimer -= fElapsedTime; + } + else + { + // Zero velocity + m_vVelocity = D3DXVECTOR3( 0, 0, 0 ); + } + } + } + else + { + // No drag, so immediately change the velocity + m_vVelocity = vAccel; + } +} + + + + +//-------------------------------------------------------------------------------------- +// Clamps pV to lie inside m_vMinBoundary & m_vMaxBoundary +//-------------------------------------------------------------------------------------- +void CBaseCamera::ConstrainToBoundary( D3DXVECTOR3* pV ) +{ + // Constrain vector to a bounding box + pV->x = __max( pV->x, m_vMinBoundary.x ); + pV->y = __max( pV->y, m_vMinBoundary.y ); + pV->z = __max( pV->z, m_vMinBoundary.z ); + + pV->x = __min( pV->x, m_vMaxBoundary.x ); + pV->y = __min( pV->y, m_vMaxBoundary.y ); + pV->z = __min( pV->z, m_vMaxBoundary.z ); +} + + + + +//-------------------------------------------------------------------------------------- +// Maps a windows virtual key to an enum +//-------------------------------------------------------------------------------------- +D3DUtil_CameraKeys CBaseCamera::MapKey( UINT nKey ) +{ + // This could be upgraded to a method that's user-definable but for + // simplicity, we'll use a hardcoded mapping. + switch( nKey ) + { + case VK_CONTROL: + return CAM_CONTROLDOWN; + case VK_LEFT: + return CAM_STRAFE_LEFT; + case VK_RIGHT: + return CAM_STRAFE_RIGHT; + case VK_UP: + return CAM_MOVE_FORWARD; + case VK_DOWN: + return CAM_MOVE_BACKWARD; + case VK_PRIOR: + return CAM_MOVE_UP; // pgup + case VK_NEXT: + return CAM_MOVE_DOWN; // pgdn + + case 'A': + return CAM_STRAFE_LEFT; + case 'D': + return CAM_STRAFE_RIGHT; + case 'W': + return CAM_MOVE_FORWARD; + case 'S': + return CAM_MOVE_BACKWARD; + case 'Q': + return CAM_MOVE_DOWN; + case 'E': + return CAM_MOVE_UP; + + case VK_NUMPAD4: + return CAM_STRAFE_LEFT; + case VK_NUMPAD6: + return CAM_STRAFE_RIGHT; + case VK_NUMPAD8: + return CAM_MOVE_FORWARD; + case VK_NUMPAD2: + return CAM_MOVE_BACKWARD; + case VK_NUMPAD9: + return CAM_MOVE_UP; + case VK_NUMPAD3: + return CAM_MOVE_DOWN; + + case VK_HOME: + return CAM_RESET; + } + + return CAM_UNKNOWN; +} + + + + +//-------------------------------------------------------------------------------------- +// Reset the camera's position back to the default +//-------------------------------------------------------------------------------------- +VOID CBaseCamera::Reset() +{ + SetViewParams( &m_vDefaultEye, &m_vDefaultLookAt ); +} + + + + +//-------------------------------------------------------------------------------------- +// Constructor +//-------------------------------------------------------------------------------------- +CFirstPersonCamera::CFirstPersonCamera() : m_nActiveButtonMask( 0x07 ) +{ + m_bRotateWithoutButtonDown = false; +} + + + + +//-------------------------------------------------------------------------------------- +// Update the view matrix based on user input & elapsed time +//-------------------------------------------------------------------------------------- +VOID CFirstPersonCamera::FrameMove( FLOAT fElapsedTime ) +{ + if( DXUTGetGlobalTimer()->IsStopped() ) { + if (DXUTGetFPS() == 0.0f) fElapsedTime = 0; + else fElapsedTime = 1.0f / DXUTGetFPS(); + } + + if( IsKeyDown( m_aKeys[CAM_RESET] ) ) + Reset(); + + // Get keyboard/mouse/gamepad input + GetInput( m_bEnablePositionMovement, ( m_nActiveButtonMask & m_nCurrentButtonMask ) || m_bRotateWithoutButtonDown, + true, m_bResetCursorAfterMove ); + + //// Get the mouse movement (if any) if the mouse button are down + //if( (m_nActiveButtonMask & m_nCurrentButtonMask) || m_bRotateWithoutButtonDown ) + // UpdateMouseDelta( fElapsedTime ); + + // Get amount of velocity based on the keyboard input and drag (if any) + UpdateVelocity( fElapsedTime ); + + // Simple euler method to calculate position delta + D3DXVECTOR3 vPosDelta = m_vVelocity * fElapsedTime; + + // If rotating the camera + if( ( m_nActiveButtonMask & m_nCurrentButtonMask ) || + m_bRotateWithoutButtonDown || + m_vGamePadRightThumb.x != 0 || + m_vGamePadRightThumb.z != 0 ) + { + // Update the pitch & yaw angle based on mouse movement + float fYawDelta = m_vRotVelocity.x; + float fPitchDelta = m_vRotVelocity.y; + + // Invert pitch if requested + if( m_bInvertPitch ) + fPitchDelta = -fPitchDelta; + + m_fCameraPitchAngle += fPitchDelta; + m_fCameraYawAngle += fYawDelta; + + // Limit pitch to straight up or straight down + m_fCameraPitchAngle = __max( -D3DX_PI / 2.0f, m_fCameraPitchAngle ); + m_fCameraPitchAngle = __min( +D3DX_PI / 2.0f, m_fCameraPitchAngle ); + } + + // Make a rotation matrix based on the camera's yaw & pitch + D3DXMATRIX mCameraRot; + D3DXMatrixRotationYawPitchRoll( &mCameraRot, m_fCameraYawAngle, m_fCameraPitchAngle, 0 ); + + // Transform vectors based on camera's rotation matrix + D3DXVECTOR3 vWorldUp, vWorldAhead; + D3DXVECTOR3 vLocalUp = D3DXVECTOR3( 0, 1, 0 ); + D3DXVECTOR3 vLocalAhead = D3DXVECTOR3( 0, 0, 1 ); + D3DXVec3TransformCoord( &vWorldUp, &vLocalUp, &mCameraRot ); + D3DXVec3TransformCoord( &vWorldAhead, &vLocalAhead, &mCameraRot ); + + // Transform the position delta by the camera's rotation + D3DXVECTOR3 vPosDeltaWorld; + if( !m_bEnableYAxisMovement ) + { + // If restricting Y movement, do not include pitch + // when transforming position delta vector. + D3DXMatrixRotationYawPitchRoll( &mCameraRot, m_fCameraYawAngle, 0.0f, 0.0f ); + } + D3DXVec3TransformCoord( &vPosDeltaWorld, &vPosDelta, &mCameraRot ); + + // Move the eye position + m_vEye += vPosDeltaWorld; + if( m_bClipToBoundary ) + ConstrainToBoundary( &m_vEye ); + + // Update the lookAt position based on the eye position + m_vLookAt = m_vEye + vWorldAhead; + + // Update the view matrix + D3DXMatrixLookAtLH( &m_mView, &m_vEye, &m_vLookAt, &vWorldUp ); + + D3DXMatrixInverse( &m_mCameraWorld, NULL, &m_mView ); +} + + +//-------------------------------------------------------------------------------------- +// Enable or disable each of the mouse buttons for rotation drag. +//-------------------------------------------------------------------------------------- +void CFirstPersonCamera::SetRotateButtons( bool bLeft, bool bMiddle, bool bRight, bool bRotateWithoutButtonDown ) +{ + m_nActiveButtonMask = ( bLeft ? MOUSE_LEFT_BUTTON : 0 ) | + ( bMiddle ? MOUSE_MIDDLE_BUTTON : 0 ) | + ( bRight ? MOUSE_RIGHT_BUTTON : 0 ); + m_bRotateWithoutButtonDown = bRotateWithoutButtonDown; +} + + +//-------------------------------------------------------------------------------------- +// Constructor +//-------------------------------------------------------------------------------------- +CModelViewerCamera::CModelViewerCamera() +{ + D3DXMatrixIdentity( &m_mWorld ); + D3DXMatrixIdentity( &m_mModelRot ); + D3DXMatrixIdentity( &m_mModelLastRot ); + D3DXMatrixIdentity( &m_mCameraRotLast ); + m_vModelCenter = D3DXVECTOR3( 0, 0, 0 ); + m_fRadius = 5.0f; + m_fDefaultRadius = 5.0f; + m_fMinRadius = 1.0f; + m_fMaxRadius = FLT_MAX; + m_bLimitPitch = false; + m_bEnablePositionMovement = false; + m_bAttachCameraToModel = false; + + m_nRotateModelButtonMask = MOUSE_LEFT_BUTTON; + m_nZoomButtonMask = MOUSE_WHEEL; + m_nRotateCameraButtonMask = MOUSE_RIGHT_BUTTON; + m_bDragSinceLastUpdate = true; +} + + + + +//-------------------------------------------------------------------------------------- +// Update the view matrix & the model's world matrix based +// on user input & elapsed time +//-------------------------------------------------------------------------------------- +VOID CModelViewerCamera::FrameMove( FLOAT fElapsedTime ) +{ + if( IsKeyDown( m_aKeys[CAM_RESET] ) ) + Reset(); + + // If no dragged has happend since last time FrameMove is called, + // and no camera key is held down, then no need to handle again. + if( !m_bDragSinceLastUpdate && 0 == m_cKeysDown ) + return; + m_bDragSinceLastUpdate = false; + + //// If no mouse button is held down, + //// Get the mouse movement (if any) if the mouse button are down + //if( m_nCurrentButtonMask != 0 ) + // UpdateMouseDelta( fElapsedTime ); + + GetInput( m_bEnablePositionMovement, m_nCurrentButtonMask != 0, true, false ); + + // Get amount of velocity based on the keyboard input and drag (if any) + UpdateVelocity( fElapsedTime ); + + // Simple euler method to calculate position delta + D3DXVECTOR3 vPosDelta = m_vVelocity * fElapsedTime; + + // Change the radius from the camera to the model based on wheel scrolling + if( m_nMouseWheelDelta && m_nZoomButtonMask == MOUSE_WHEEL ) + m_fRadius -= m_nMouseWheelDelta * m_fRadius * 0.1f / 120.0f; + m_fRadius = __min( m_fMaxRadius, m_fRadius ); + m_fRadius = __max( m_fMinRadius, m_fRadius ); + m_nMouseWheelDelta = 0; + + // Get the inverse of the arcball's rotation matrix + D3DXMATRIX mCameraRot; + D3DXMatrixInverse( &mCameraRot, NULL, m_ViewArcBall.GetRotationMatrix() ); + + // Transform vectors based on camera's rotation matrix + D3DXVECTOR3 vWorldUp, vWorldAhead; + D3DXVECTOR3 vLocalUp = D3DXVECTOR3( 0, 1, 0 ); + D3DXVECTOR3 vLocalAhead = D3DXVECTOR3( 0, 0, 1 ); + D3DXVec3TransformCoord( &vWorldUp, &vLocalUp, &mCameraRot ); + D3DXVec3TransformCoord( &vWorldAhead, &vLocalAhead, &mCameraRot ); + + // Transform the position delta by the camera's rotation + D3DXVECTOR3 vPosDeltaWorld; + D3DXVec3TransformCoord( &vPosDeltaWorld, &vPosDelta, &mCameraRot ); + + // Move the lookAt position + m_vLookAt += vPosDeltaWorld; + if( m_bClipToBoundary ) + ConstrainToBoundary( &m_vLookAt ); + + // Update the eye point based on a radius away from the lookAt position + m_vEye = m_vLookAt - vWorldAhead * m_fRadius; + + // Update the view matrix + D3DXMatrixLookAtLH( &m_mView, &m_vEye, &m_vLookAt, &vWorldUp ); + + D3DXMATRIX mInvView; + D3DXMatrixInverse( &mInvView, NULL, &m_mView ); + mInvView._41 = mInvView._42 = mInvView._43 = 0; + + D3DXMATRIX mModelLastRotInv; + D3DXMatrixInverse( &mModelLastRotInv, NULL, &m_mModelLastRot ); + + // Accumulate the delta of the arcball's rotation in view space. + // Note that per-frame delta rotations could be problematic over long periods of time. + D3DXMATRIX mModelRot; + mModelRot = *m_WorldArcBall.GetRotationMatrix(); + m_mModelRot *= m_mView * mModelLastRotInv * mModelRot * mInvView; + + if( m_ViewArcBall.IsBeingDragged() && m_bAttachCameraToModel && !IsKeyDown( m_aKeys[CAM_CONTROLDOWN] ) ) + { + // Attach camera to model by inverse of the model rotation + D3DXMATRIX mCameraLastRotInv; + D3DXMatrixInverse( &mCameraLastRotInv, NULL, &m_mCameraRotLast ); + D3DXMATRIX mCameraRotDelta = mCameraLastRotInv * mCameraRot; // local to world matrix + m_mModelRot *= mCameraRotDelta; + } + m_mCameraRotLast = mCameraRot; + + m_mModelLastRot = mModelRot; + + // Since we're accumulating delta rotations, we need to orthonormalize + // the matrix to prevent eventual matrix skew + D3DXVECTOR3* pXBasis = ( D3DXVECTOR3* )&m_mModelRot._11; + D3DXVECTOR3* pYBasis = ( D3DXVECTOR3* )&m_mModelRot._21; + D3DXVECTOR3* pZBasis = ( D3DXVECTOR3* )&m_mModelRot._31; + D3DXVec3Normalize( pXBasis, pXBasis ); + D3DXVec3Cross( pYBasis, pZBasis, pXBasis ); + D3DXVec3Normalize( pYBasis, pYBasis ); + D3DXVec3Cross( pZBasis, pXBasis, pYBasis ); + + // Translate the rotation matrix to the same position as the lookAt position + m_mModelRot._41 = m_vLookAt.x; + m_mModelRot._42 = m_vLookAt.y; + m_mModelRot._43 = m_vLookAt.z; + + // Translate world matrix so its at the center of the model + D3DXMATRIX mTrans; + D3DXMatrixTranslation( &mTrans, -m_vModelCenter.x, -m_vModelCenter.y, -m_vModelCenter.z ); + m_mWorld = mTrans * m_mModelRot; +} + + +void CModelViewerCamera::SetDragRect( RECT& rc ) +{ + CBaseCamera::SetDragRect( rc ); + + m_WorldArcBall.SetOffset( rc.left, rc.top ); + m_ViewArcBall.SetOffset( rc.left, rc.top ); + SetWindow( rc.right - rc.left, rc.bottom - rc.top ); +} + + +//-------------------------------------------------------------------------------------- +// Reset the camera's position back to the default +//-------------------------------------------------------------------------------------- +VOID CModelViewerCamera::Reset() +{ + CBaseCamera::Reset(); + + D3DXMatrixIdentity( &m_mWorld ); + D3DXMatrixIdentity( &m_mModelRot ); + D3DXMatrixIdentity( &m_mModelLastRot ); + D3DXMatrixIdentity( &m_mCameraRotLast ); + + m_fRadius = m_fDefaultRadius; + m_WorldArcBall.Reset(); + m_ViewArcBall.Reset(); +} + + +//-------------------------------------------------------------------------------------- +// Override for setting the view parameters +//-------------------------------------------------------------------------------------- +void CModelViewerCamera::SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt ) +{ + CBaseCamera::SetViewParams( pvEyePt, pvLookatPt ); + + // Propogate changes to the member arcball + D3DXQUATERNION quat; + D3DXMATRIXA16 mRotation; + D3DXVECTOR3 vUp( 0,1,0 ); + D3DXMatrixLookAtLH( &mRotation, pvEyePt, pvLookatPt, &vUp ); + D3DXQuaternionRotationMatrix( &quat, &mRotation ); + m_ViewArcBall.SetQuatNow( quat ); + + // Set the radius according to the distance + D3DXVECTOR3 vEyeToPoint; + D3DXVec3Subtract( &vEyeToPoint, pvLookatPt, pvEyePt ); + SetRadius( D3DXVec3Length( &vEyeToPoint ) ); + + // View information changed. FrameMove should be called. + m_bDragSinceLastUpdate = true; +} + + + +//-------------------------------------------------------------------------------------- +// Call this from your message proc so this class can handle window messages +//-------------------------------------------------------------------------------------- +LRESULT CModelViewerCamera::HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + CBaseCamera::HandleMessages( hWnd, uMsg, wParam, lParam ); + + if( ( ( uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK ) && m_nRotateModelButtonMask & MOUSE_LEFT_BUTTON ) || + ( ( uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONDBLCLK ) && m_nRotateModelButtonMask & MOUSE_MIDDLE_BUTTON ) || + ( ( uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK ) && m_nRotateModelButtonMask & MOUSE_RIGHT_BUTTON ) ) + { + int iMouseX = ( short )LOWORD( lParam ); + int iMouseY = ( short )HIWORD( lParam ); + m_WorldArcBall.OnBegin( iMouseX, iMouseY ); + } + + if( ( ( uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK ) && m_nRotateCameraButtonMask & MOUSE_LEFT_BUTTON ) || + ( ( uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONDBLCLK ) && + m_nRotateCameraButtonMask & MOUSE_MIDDLE_BUTTON ) || + ( ( uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK ) && m_nRotateCameraButtonMask & MOUSE_RIGHT_BUTTON ) ) + { + int iMouseX = ( short )LOWORD( lParam ); + int iMouseY = ( short )HIWORD( lParam ); + m_ViewArcBall.OnBegin( iMouseX, iMouseY ); + } + + if( uMsg == WM_MOUSEMOVE ) + { + int iMouseX = ( short )LOWORD( lParam ); + int iMouseY = ( short )HIWORD( lParam ); + m_WorldArcBall.OnMove( iMouseX, iMouseY ); + m_ViewArcBall.OnMove( iMouseX, iMouseY ); + } + + if( ( uMsg == WM_LBUTTONUP && m_nRotateModelButtonMask & MOUSE_LEFT_BUTTON ) || + ( uMsg == WM_MBUTTONUP && m_nRotateModelButtonMask & MOUSE_MIDDLE_BUTTON ) || + ( uMsg == WM_RBUTTONUP && m_nRotateModelButtonMask & MOUSE_RIGHT_BUTTON ) ) + { + m_WorldArcBall.OnEnd(); + } + + if( ( uMsg == WM_LBUTTONUP && m_nRotateCameraButtonMask & MOUSE_LEFT_BUTTON ) || + ( uMsg == WM_MBUTTONUP && m_nRotateCameraButtonMask & MOUSE_MIDDLE_BUTTON ) || + ( uMsg == WM_RBUTTONUP && m_nRotateCameraButtonMask & MOUSE_RIGHT_BUTTON ) ) + { + m_ViewArcBall.OnEnd(); + } + + if( uMsg == WM_CAPTURECHANGED ) + { + if( ( HWND )lParam != hWnd ) + { + if( ( m_nRotateModelButtonMask & MOUSE_LEFT_BUTTON ) || + ( m_nRotateModelButtonMask & MOUSE_MIDDLE_BUTTON ) || + ( m_nRotateModelButtonMask & MOUSE_RIGHT_BUTTON ) ) + { + m_WorldArcBall.OnEnd(); + } + + if( ( m_nRotateCameraButtonMask & MOUSE_LEFT_BUTTON ) || + ( m_nRotateCameraButtonMask & MOUSE_MIDDLE_BUTTON ) || + ( m_nRotateCameraButtonMask & MOUSE_RIGHT_BUTTON ) ) + { + m_ViewArcBall.OnEnd(); + } + } + } + + if( uMsg == WM_LBUTTONDOWN || + uMsg == WM_LBUTTONDBLCLK || + uMsg == WM_MBUTTONDOWN || + uMsg == WM_MBUTTONDBLCLK || + uMsg == WM_RBUTTONDOWN || + uMsg == WM_RBUTTONDBLCLK || + uMsg == WM_LBUTTONUP || + uMsg == WM_MBUTTONUP || + uMsg == WM_RBUTTONUP || + uMsg == WM_MOUSEWHEEL || + uMsg == WM_MOUSEMOVE ) + { + m_bDragSinceLastUpdate = true; + } + + return FALSE; +} + + + +//-------------------------------------------------------------------------------------- +// D3D9 +IDirect3DDevice9* CDXUTDirectionWidget::s_pd3d9Device = NULL; +ID3DXEffect* CDXUTDirectionWidget::s_pD3D9Effect = NULL; +ID3DXMesh* CDXUTDirectionWidget::s_pD3D9Mesh = NULL; +D3DXHANDLE CDXUTDirectionWidget::s_hRenderWith1LightNoTexture = NULL; +D3DXHANDLE CDXUTDirectionWidget::s_hMaterialDiffuseColor = NULL; +D3DXHANDLE CDXUTDirectionWidget::s_hLightDir = NULL; +D3DXHANDLE CDXUTDirectionWidget::s_hWorldViewProjection = NULL; +D3DXHANDLE CDXUTDirectionWidget::s_hWorld = NULL; + + +//-------------------------------------------------------------------------------------- +CDXUTDirectionWidget::CDXUTDirectionWidget() +{ + m_fRadius = 1.0f; + m_vDefaultDir = D3DXVECTOR3( 0, 1, 0 ); + m_vCurrentDir = m_vDefaultDir; + m_nRotateMask = MOUSE_RIGHT_BUTTON; + + D3DXMatrixIdentity( &m_mView ); + D3DXMatrixIdentity( &m_mRot ); + D3DXMatrixIdentity( &m_mRotSnapshot ); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDirectionWidget::StaticOnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice ) +{ + HRESULT hr; + + s_pd3d9Device = pd3dDevice; + + const char* g_strBuffer = + "float4 g_MaterialDiffuseColor; // Material's diffuse color\r\n" + "float3 g_LightDir; // Light's direction in world space\r\n" + "float4x4 g_mWorld; // World matrix for object\r\n" + "float4x4 g_mWorldViewProjection; // World * View * Projection matrix\r\n" + "\r\n" + "struct VS_OUTPUT\r\n" + "{\r\n" + " float4 Position : POSITION; // vertex position\r\n" + " float4 Diffuse : COLOR0; // vertex diffuse color\r\n" + "};\r\n" + "\r\n" + "VS_OUTPUT RenderWith1LightNoTextureVS( float4 vPos : POSITION,\r\n" + " float3 vNormal : NORMAL )\r\n" + "{\r\n" + " VS_OUTPUT Output;\r\n" + "\r\n" + " // Transform the position from object space to homogeneous projection space\r\n" + " Output.Position = mul(vPos, g_mWorldViewProjection);\r\n" + "\r\n" + " // Transform the normal from object space to world space\r\n" + " float3 vNormalWorldSpace;\r\n" + " vNormalWorldSpace = normalize(mul(vNormal, (float3x3)g_mWorld)); // normal (world space)\r\n" + "\r\n" + " // Compute simple directional lighting equation\r\n" + " Output.Diffuse.rgb = g_MaterialDiffuseColor * max(0,dot(vNormalWorldSpace, g_LightDir));\r\n" + " Output.Diffuse.a = 1.0f;\r\n" + "\r\n" + " return Output;\r\n" + "}\r\n" + "\r\n" + "float4 RenderWith1LightNoTexturePS( float4 Diffuse : COLOR0 ) : COLOR0\r\n" + "{\r\n" + " return Diffuse;\r\n" + "}\r\n" + "\r\n" + "technique RenderWith1LightNoTexture\r\n" + "{\r\n" + " pass P0\r\n" + " {\r\n" + " VertexShader = compile vs_2_0 RenderWith1LightNoTextureVS();\r\n" + " PixelShader = compile ps_2_0 RenderWith1LightNoTexturePS();\r\n" + " }\r\n" + "}\r\n" + ""; + + UINT dwBufferSize = ( UINT )strlen( g_strBuffer ) + 1; + + V_RETURN( D3DXCreateEffect( s_pd3d9Device, g_strBuffer, dwBufferSize, NULL, NULL, D3DXFX_NOT_CLONEABLE, + NULL, &s_pD3D9Effect, NULL ) ); + + // Save technique handles for use when rendering + s_hRenderWith1LightNoTexture = s_pD3D9Effect->GetTechniqueByName( "RenderWith1LightNoTexture" ); + s_hMaterialDiffuseColor = s_pD3D9Effect->GetParameterByName( NULL, "g_MaterialDiffuseColor" ); + s_hLightDir = s_pD3D9Effect->GetParameterByName( NULL, "g_LightDir" ); + s_hWorld = s_pD3D9Effect->GetParameterByName( NULL, "g_mWorld" ); + s_hWorldViewProjection = s_pD3D9Effect->GetParameterByName( NULL, "g_mWorldViewProjection" ); + + // Load the mesh with D3DX and get back a ID3DXMesh*. For this + // sample we'll ignore the X file's embedded materials since we know + // exactly the model we're loading. See the mesh samples such as + // "OptimizedMesh" for a more generic mesh loading example. + V_RETURN( DXUTCreateArrowMeshFromInternalArray( s_pd3d9Device, &s_pD3D9Mesh ) ); + + // Optimize the mesh for this graphics card's vertex cache + // so when rendering the mesh's triangle list the vertices will + // cache hit more often so it won't have to re-execute the vertex shader + // on those vertices so it will improve perf. + DWORD* rgdwAdjacency = new DWORD[s_pD3D9Mesh->GetNumFaces() * 3]; + if( rgdwAdjacency == NULL ) + return E_OUTOFMEMORY; + V( s_pD3D9Mesh->GenerateAdjacency( 1e-6f, rgdwAdjacency ) ); + V( s_pD3D9Mesh->OptimizeInplace( D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL ) ); + delete []rgdwAdjacency; + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDirectionWidget::OnD3D9ResetDevice( const D3DSURFACE_DESC* pBackBufferSurfaceDesc ) +{ + m_ArcBall.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height ); + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDirectionWidget::StaticOnD3D9LostDevice() +{ + if( s_pD3D9Effect ) + s_pD3D9Effect->OnLostDevice(); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDirectionWidget::StaticOnD3D9DestroyDevice() +{ + SAFE_RELEASE( s_pD3D9Effect ); + SAFE_RELEASE( s_pD3D9Mesh ); +} + + +//-------------------------------------------------------------------------------------- +LRESULT CDXUTDirectionWidget::HandleMessages( HWND hWnd, UINT uMsg, + WPARAM wParam, LPARAM lParam ) +{ + switch( uMsg ) + { + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + { + if( ( ( m_nRotateMask & MOUSE_LEFT_BUTTON ) != 0 && uMsg == WM_LBUTTONDOWN ) || + ( ( m_nRotateMask & MOUSE_MIDDLE_BUTTON ) != 0 && uMsg == WM_MBUTTONDOWN ) || + ( ( m_nRotateMask & MOUSE_RIGHT_BUTTON ) != 0 && uMsg == WM_RBUTTONDOWN ) ) + { + int iMouseX = ( int )( short )LOWORD( lParam ); + int iMouseY = ( int )( short )HIWORD( lParam ); + m_ArcBall.OnBegin( iMouseX, iMouseY ); + SetCapture( hWnd ); + } + return TRUE; + } + + case WM_MOUSEMOVE: + { + if( m_ArcBall.IsBeingDragged() ) + { + int iMouseX = ( int )( short )LOWORD( lParam ); + int iMouseY = ( int )( short )HIWORD( lParam ); + m_ArcBall.OnMove( iMouseX, iMouseY ); + UpdateLightDir(); + } + return TRUE; + } + + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + { + if( ( ( m_nRotateMask & MOUSE_LEFT_BUTTON ) != 0 && uMsg == WM_LBUTTONUP ) || + ( ( m_nRotateMask & MOUSE_MIDDLE_BUTTON ) != 0 && uMsg == WM_MBUTTONUP ) || + ( ( m_nRotateMask & MOUSE_RIGHT_BUTTON ) != 0 && uMsg == WM_RBUTTONUP ) ) + { + m_ArcBall.OnEnd(); + ReleaseCapture(); + } + + UpdateLightDir(); + return TRUE; + } + + case WM_CAPTURECHANGED: + { + if( ( HWND )lParam != hWnd ) + { + if( ( m_nRotateMask & MOUSE_LEFT_BUTTON ) || + ( m_nRotateMask & MOUSE_MIDDLE_BUTTON ) || + ( m_nRotateMask & MOUSE_RIGHT_BUTTON ) ) + { + m_ArcBall.OnEnd(); + ReleaseCapture(); + } + } + return TRUE; + } + } + + return 0; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDirectionWidget::OnRender9( D3DXCOLOR color, const D3DXMATRIX* pmView, + const D3DXMATRIX* pmProj, const D3DXVECTOR3* pEyePt ) +{ + m_mView = *pmView; + + // Render the light spheres so the user can visually see the light dir + UINT iPass, cPasses; + D3DXMATRIX mRotate; + D3DXMATRIX mScale; + D3DXMATRIX mTrans; + D3DXMATRIXA16 mWorldViewProj; + HRESULT hr; + + V( s_pD3D9Effect->SetTechnique( s_hRenderWith1LightNoTexture ) ); + V( s_pD3D9Effect->SetVector( s_hMaterialDiffuseColor, ( D3DXVECTOR4* )&color ) ); + + D3DXVECTOR3 vEyePt; + D3DXVec3Normalize( &vEyePt, pEyePt ); + V( s_pD3D9Effect->SetValue( s_hLightDir, &vEyePt, sizeof( D3DXVECTOR3 ) ) ); + + // Rotate arrow model to point towards origin + D3DXMATRIX mRotateA, mRotateB; + D3DXVECTOR3 vAt = D3DXVECTOR3( 0, 0, 0 ); + D3DXVECTOR3 vUp = D3DXVECTOR3( 0, 1, 0 ); + D3DXMatrixRotationX( &mRotateB, D3DX_PI ); + D3DXMatrixLookAtLH( &mRotateA, &m_vCurrentDir, &vAt, &vUp ); + D3DXMatrixInverse( &mRotateA, NULL, &mRotateA ); + mRotate = mRotateB * mRotateA; + + D3DXVECTOR3 vL = m_vCurrentDir * m_fRadius * 1.0f; + D3DXMatrixTranslation( &mTrans, vL.x, vL.y, vL.z ); + D3DXMatrixScaling( &mScale, m_fRadius * 0.2f, m_fRadius * 0.2f, m_fRadius * 0.2f ); + + D3DXMATRIX mWorld = mRotate * mScale * mTrans; + mWorldViewProj = mWorld * ( m_mView )*( *pmProj ); + + V( s_pD3D9Effect->SetMatrix( s_hWorldViewProjection, &mWorldViewProj ) ); + V( s_pD3D9Effect->SetMatrix( s_hWorld, &mWorld ) ); + + for( int iSubset = 0; iSubset < 2; iSubset++ ) + { + V( s_pD3D9Effect->Begin( &cPasses, 0 ) ); + for( iPass = 0; iPass < cPasses; iPass++ ) + { + V( s_pD3D9Effect->BeginPass( iPass ) ); + V( s_pD3D9Mesh->DrawSubset( iSubset ) ); + V( s_pD3D9Effect->EndPass() ); + } + V( s_pD3D9Effect->End() ); + } + + return S_OK; +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDirectionWidget::UpdateLightDir() +{ + D3DXMATRIX mInvView; + D3DXMatrixInverse( &mInvView, NULL, &m_mView ); + mInvView._41 = mInvView._42 = mInvView._43 = 0; + + D3DXMATRIX mLastRotInv; + D3DXMatrixInverse( &mLastRotInv, NULL, &m_mRotSnapshot ); + + D3DXMATRIX mRot = *m_ArcBall.GetRotationMatrix(); + m_mRotSnapshot = mRot; + + // Accumulate the delta of the arcball's rotation in view space. + // Note that per-frame delta rotations could be problematic over long periods of time. + m_mRot *= m_mView * mLastRotInv * mRot * mInvView; + + // Since we're accumulating delta rotations, we need to orthonormalize + // the matrix to prevent eventual matrix skew + D3DXVECTOR3* pXBasis = ( D3DXVECTOR3* )&m_mRot._11; + D3DXVECTOR3* pYBasis = ( D3DXVECTOR3* )&m_mRot._21; + D3DXVECTOR3* pZBasis = ( D3DXVECTOR3* )&m_mRot._31; + D3DXVec3Normalize( pXBasis, pXBasis ); + D3DXVec3Cross( pYBasis, pZBasis, pXBasis ); + D3DXVec3Normalize( pYBasis, pYBasis ); + D3DXVec3Cross( pZBasis, pXBasis, pYBasis ); + + // Transform the default direction vector by the light's rotation matrix + D3DXVec3TransformNormal( &m_vCurrentDir, &m_vDefaultDir, &m_mRot ); + + return S_OK; +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDirectionWidget::StaticOnD3D11CreateDevice( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext ) +{ + + + //s_pd3d10Device = pd3dDevice; + + //const char* g_strBuffer = + // "float4 g_MaterialDiffuseColor; // Material's diffuse color\r\n" + // "float4 g_LightDir; // Light's direction in world space\r\n" + // "float4x4 g_mWorld; // World matrix for object\r\n" + // "float4x4 g_mWorldViewProjection; // World * View * Projection matrix\r\n" + // "\r\n" + // "struct VS_OUTPUT\r\n" + // "{\r\n" + // " float4 Position : SV_POSITION; // vertex position\r\n" + // " float4 Diffuse : COLOR0; // vertex diffuse color\r\n" + // "};\r\n" + // "\r\n" + // "VS_OUTPUT RenderWith1LightNoTextureVS( float3 vPos : POSITION,\r\n" + // " float3 vNormal : NORMAL )\r\n" + // "{\r\n" + // " VS_OUTPUT Output;\r\n" + // "\r\n" + // " // Transform the position from object space to homogeneous projection space\r\n" + // " Output.Position = mul( float4(vPos,1), g_mWorldViewProjection);\r\n" + // "\r\n" + // " // Transform the normal from object space to world space\r\n" + // " float3 vNormalWorldSpace;\r\n" + // " vNormalWorldSpace = normalize(mul(vNormal, (float3x3)g_mWorld)); // normal (world space)\r\n" + // "\r\n" + // " // Compute simple directional lighting equation\r\n" + // " Output.Diffuse.rgb = g_MaterialDiffuseColor * max(0,dot(vNormalWorldSpace, g_LightDir));\r\n" + // " Output.Diffuse.a = 1.0f;\r\n" + // "\r\n" + // " return Output;\r\n" + // "}\r\n" + // "\r\n" + // "float4 RenderWith1LightNoTexturePS( VS_OUTPUT Input ) : SV_TARGET\r\n" + // "{\r\n" + // " return Input.Diffuse;\r\n" + // "}\r\n" + // "\r\n" + // "technique10 RenderWith1LightNoTexture\r\n" + // "{\r\n" + // " pass p0\r\n" + // " {\r\n" + // " SetVertexShader( CompileShader( vs_4_0, RenderWith1LightNoTextureVS() ) );\r\n" + // " SetGeometryShader( NULL );\r\n" + // " SetPixelShader( CompileShader( ps_4_0, RenderWith1LightNoTexturePS() ) );\r\n" + // " }\r\n" + // "}\r\n" + // ""; + + //UINT dwBufferSize = ( UINT )strlen( g_strBuffer ) + 1; + + //HRESULT hr = D3DX10CreateEffectFromMemory( g_strBuffer, dwBufferSize, "None", NULL, NULL, "fx_4_0", + // D3D10_SHADER_ENABLE_STRICTNESS, 0, pd3dDevice, NULL, + // NULL, &s_pD3D10Effect, NULL, NULL ); + //if( FAILED( hr ) ) + // return hr; + + //s_pRenderTech = s_pD3D10Effect->GetTechniqueByName( "RenderWith1LightNoTexture" ); + //g_pMaterialDiffuseColor = s_pD3D10Effect->GetVariableByName( "g_MaterialDiffuseColor" )->AsVector(); + //g_pLightDir = s_pD3D10Effect->GetVariableByName( "g_LightDir" )->AsVector(); + //g_pmWorld = s_pD3D10Effect->GetVariableByName( "g_mWorld" )->AsMatrix(); + //g_pmWorldViewProjection = s_pD3D10Effect->GetVariableByName( "g_mWorldViewProjection" )->AsMatrix(); + + //const D3D10_INPUT_ELEMENT_DESC layout[] = + //{ + // { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, + // { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 }, + //}; + //D3D10_PASS_DESC PassDesc; + //V_RETURN( s_pRenderTech->GetPassByIndex( 0 )->GetDesc( &PassDesc ) ); + //V_RETURN( pd3dDevice->CreateInputLayout( layout, 2, PassDesc.pIAInputSignature, + // PassDesc.IAInputSignatureSize, &s_pVertexLayout ) ); + + //TODO: Add loading code here + + return S_OK; +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDirectionWidget::OnRender11( D3DXCOLOR color, const D3DXMATRIX* pmView, const D3DXMATRIX* pmProj, + const D3DXVECTOR3* pEyePt ) +{ + // NO D3DX11 YET + // m_mView = *pmView; + + // // Render the light spheres so the user can visually see the light dir + // D3DXMATRIX mRotate; + // D3DXMATRIX mScale; + // D3DXMATRIX mTrans; + // D3DXMATRIXA16 mWorldViewProj; + + // g_pMaterialDiffuseColor->SetFloatVector( ( float* )&color ); + // D3DXVECTOR3 vEyePt; + // D3DXVec3Normalize( &vEyePt, pEyePt ); + // g_pLightDir->SetFloatVector( ( float* )&vEyePt ); + + // // Rotate arrow model to point towards origin + // D3DXMATRIX mRotateA, mRotateB; + // D3DXVECTOR3 vAt = D3DXVECTOR3( 0, 0, 0 ); + // D3DXVECTOR3 vUp = D3DXVECTOR3( 0, 1, 0 ); + // D3DXMatrixRotationX( &mRotateB, D3DX_PI ); + // D3DXMatrixLookAtLH( &mRotateA, &m_vCurrentDir, &vAt, &vUp ); + // D3DXMatrixInverse( &mRotateA, NULL, &mRotateA ); + // mRotate = mRotateB * mRotateA; + + // D3DXVECTOR3 vL = m_vCurrentDir * m_fRadius * 1.0f; + // D3DXMatrixTranslation( &mTrans, vL.x, vL.y, vL.z ); + // D3DXMatrixScaling( &mScale, m_fRadius * 0.2f, m_fRadius * 0.2f, m_fRadius * 0.2f ); + + // D3DXMATRIX mWorld = mRotate * mScale * mTrans; + // mWorldViewProj = mWorld * ( m_mView )*( *pmProj ); + + // g_pmWorldViewProjection->SetMatrix( ( float* )&mWorldViewProj ); + // g_pmWorld->SetMatrix( ( float* )&mWorld ); + + // s_pd3d10Device->IASetInputLayout( s_pVertexLayout ); + + //TODO: Add rendering code here + + return S_OK; +} + +//-------------------------------------------------------------------------------------- +void CDXUTDirectionWidget::StaticOnD3D11DestroyDevice() +{ +// SAFE_RELEASE( s_pVertexLayout ); +// SAFE_RELEASE( s_pD3D11Effect ); +} diff --git a/Demos/DX11ClothDemo/DXUT/Optional/DXUTcamera.h b/Demos/DX11ClothDemo/DXUT/Optional/DXUTcamera.h new file mode 100644 index 0000000..6325fa8 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/DXUTcamera.h @@ -0,0 +1,517 @@ +//-------------------------------------------------------------------------------------- +// File: Camera.h +// +// Helper functions for Direct3D programming. +// +// Copyright (c) Microsoft Corporation. All rights reserved +//-------------------------------------------------------------------------------------- +#pragma once +#ifndef CAMERA_H +#define CAMERA_H + +//-------------------------------------------------------------------------------------- +class CD3DArcBall +{ +public: + CD3DArcBall(); + + // Functions to change behavior + void Reset(); + void SetTranslationRadius( FLOAT fRadiusTranslation ) + { + m_fRadiusTranslation = fRadiusTranslation; + } + void SetWindow( INT nWidth, INT nHeight, FLOAT fRadius = 0.9f ) + { + m_nWidth = nWidth; m_nHeight = nHeight; m_fRadius = fRadius; + m_vCenter = D3DXVECTOR2( m_nWidth / 2.0f, m_nHeight / 2.0f ); + } + void SetOffset( INT nX, INT nY ) + { + m_Offset.x = nX; m_Offset.y = nY; + } + + // Call these from client and use GetRotationMatrix() to read new rotation matrix + void OnBegin( int nX, int nY ); // start the rotation (pass current mouse position) + void OnMove( int nX, int nY ); // continue the rotation (pass current mouse position) + void OnEnd(); // end the rotation + + // Or call this to automatically handle left, middle, right buttons + LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + + // Functions to get/set state + const D3DXMATRIX* GetRotationMatrix() + { + return D3DXMatrixRotationQuaternion( &m_mRotation, &m_qNow ); + }; + const D3DXMATRIX* GetTranslationMatrix() const + { + return &m_mTranslation; + } + const D3DXMATRIX* GetTranslationDeltaMatrix() const + { + return &m_mTranslationDelta; + } + bool IsBeingDragged() const + { + return m_bDrag; + } + D3DXQUATERNION GetQuatNow() const + { + return m_qNow; + } + void SetQuatNow( D3DXQUATERNION q ) + { + m_qNow = q; + } + + static D3DXQUATERNION WINAPI QuatFromBallPoints( const D3DXVECTOR3& vFrom, const D3DXVECTOR3& vTo ); + + +protected: + D3DXMATRIXA16 m_mRotation; // Matrix for arc ball's orientation + D3DXMATRIXA16 m_mTranslation; // Matrix for arc ball's position + D3DXMATRIXA16 m_mTranslationDelta; // Matrix for arc ball's position + + POINT m_Offset; // window offset, or upper-left corner of window + INT m_nWidth; // arc ball's window width + INT m_nHeight; // arc ball's window height + D3DXVECTOR2 m_vCenter; // center of arc ball + FLOAT m_fRadius; // arc ball's radius in screen coords + FLOAT m_fRadiusTranslation; // arc ball's radius for translating the target + + D3DXQUATERNION m_qDown; // Quaternion before button down + D3DXQUATERNION m_qNow; // Composite quaternion for current drag + bool m_bDrag; // Whether user is dragging arc ball + + POINT m_ptLastMouse; // position of last mouse point + D3DXVECTOR3 m_vDownPt; // starting point of rotation arc + D3DXVECTOR3 m_vCurrentPt; // current point of rotation arc + + D3DXVECTOR3 ScreenToVector( float fScreenPtX, float fScreenPtY ); +}; + + +//-------------------------------------------------------------------------------------- +// used by CCamera to map WM_KEYDOWN keys +//-------------------------------------------------------------------------------------- +enum D3DUtil_CameraKeys +{ + CAM_STRAFE_LEFT = 0, + CAM_STRAFE_RIGHT, + CAM_MOVE_FORWARD, + CAM_MOVE_BACKWARD, + CAM_MOVE_UP, + CAM_MOVE_DOWN, + CAM_RESET, + CAM_CONTROLDOWN, + CAM_MAX_KEYS, + CAM_UNKNOWN = 0xFF +}; + +#define KEY_WAS_DOWN_MASK 0x80 +#define KEY_IS_DOWN_MASK 0x01 + +#define MOUSE_LEFT_BUTTON 0x01 +#define MOUSE_MIDDLE_BUTTON 0x02 +#define MOUSE_RIGHT_BUTTON 0x04 +#define MOUSE_WHEEL 0x08 + + +//-------------------------------------------------------------------------------------- +// Simple base camera class that moves and rotates. The base class +// records mouse and keyboard input for use by a derived class, and +// keeps common state. +//-------------------------------------------------------------------------------------- +class CBaseCamera +{ +public: + CBaseCamera(); + + // Call these from client and use Get*Matrix() to read new matrices + virtual LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + virtual void FrameMove( FLOAT fElapsedTime ) = 0; + + // Functions to change camera matrices + virtual void Reset(); + virtual void SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt ); + virtual void SetProjParams( FLOAT fFOV, FLOAT fAspect, FLOAT fNearPlane, FLOAT fFarPlane ); + + // Functions to change behavior + virtual void SetDragRect( RECT& rc ) + { + m_rcDrag = rc; + } + void SetInvertPitch( bool bInvertPitch ) + { + m_bInvertPitch = bInvertPitch; + } + void SetDrag( bool bMovementDrag, FLOAT fTotalDragTimeToZero = 0.25f ) + { + m_bMovementDrag = bMovementDrag; m_fTotalDragTimeToZero = fTotalDragTimeToZero; + } + void SetEnableYAxisMovement( bool bEnableYAxisMovement ) + { + m_bEnableYAxisMovement = bEnableYAxisMovement; + } + void SetEnablePositionMovement( bool bEnablePositionMovement ) + { + m_bEnablePositionMovement = bEnablePositionMovement; + } + void SetClipToBoundary( bool bClipToBoundary, D3DXVECTOR3* pvMinBoundary, + D3DXVECTOR3* pvMaxBoundary ) + { + m_bClipToBoundary = bClipToBoundary; if( pvMinBoundary ) m_vMinBoundary = *pvMinBoundary; + if( pvMaxBoundary ) m_vMaxBoundary = *pvMaxBoundary; + } + void SetScalers( FLOAT fRotationScaler = 0.01f, FLOAT fMoveScaler = 5.0f ) + { + m_fRotationScaler = fRotationScaler; m_fMoveScaler = fMoveScaler; + } + void SetNumberOfFramesToSmoothMouseData( int nFrames ) + { + if( nFrames > 0 ) m_fFramesToSmoothMouseData = ( float )nFrames; + } + void SetResetCursorAfterMove( bool bResetCursorAfterMove ) + { + m_bResetCursorAfterMove = bResetCursorAfterMove; + } + + // Functions to get state + const D3DXMATRIX* GetViewMatrix() const + { + return &m_mView; + } + const D3DXMATRIX* GetProjMatrix() const + { + return &m_mProj; + } + const D3DXVECTOR3* GetEyePt() const + { + return &m_vEye; + } + const D3DXVECTOR3* GetLookAtPt() const + { + return &m_vLookAt; + } + float GetNearClip() const + { + return m_fNearPlane; + } + float GetFarClip() const + { + return m_fFarPlane; + } + + bool IsBeingDragged() const + { + return ( m_bMouseLButtonDown || m_bMouseMButtonDown || m_bMouseRButtonDown ); + } + bool IsMouseLButtonDown() const + { + return m_bMouseLButtonDown; + } + bool IsMouseMButtonDown() const + { + return m_bMouseMButtonDown; + } + bool IsMouseRButtonDown() const + { + return m_bMouseRButtonDown; + } + +protected: + // Functions to map a WM_KEYDOWN key to a D3DUtil_CameraKeys enum + virtual D3DUtil_CameraKeys MapKey( UINT nKey ); + bool IsKeyDown( BYTE key ) const + { + return( ( key & KEY_IS_DOWN_MASK ) == KEY_IS_DOWN_MASK ); + } + bool WasKeyDown( BYTE key ) const + { + return( ( key & KEY_WAS_DOWN_MASK ) == KEY_WAS_DOWN_MASK ); + } + + void ConstrainToBoundary( D3DXVECTOR3* pV ); + void UpdateMouseDelta(); + void UpdateVelocity( float fElapsedTime ); + void GetInput( bool bGetKeyboardInput, bool bGetMouseInput, bool bGetGamepadInput, + bool bResetCursorAfterMove ); + + D3DXMATRIX m_mView; // View matrix + D3DXMATRIX m_mProj; // Projection matrix + + DXUT_GAMEPAD m_GamePad[DXUT_MAX_CONTROLLERS]; // XInput controller state + D3DXVECTOR3 m_vGamePadLeftThumb; + D3DXVECTOR3 m_vGamePadRightThumb; + double m_GamePadLastActive[DXUT_MAX_CONTROLLERS]; + + int m_cKeysDown; // Number of camera keys that are down. + BYTE m_aKeys[CAM_MAX_KEYS]; // State of input - KEY_WAS_DOWN_MASK|KEY_IS_DOWN_MASK + D3DXVECTOR3 m_vKeyboardDirection; // Direction vector of keyboard input + POINT m_ptLastMousePosition; // Last absolute position of mouse cursor + bool m_bMouseLButtonDown; // True if left button is down + bool m_bMouseMButtonDown; // True if middle button is down + bool m_bMouseRButtonDown; // True if right button is down + int m_nCurrentButtonMask; // mask of which buttons are down + int m_nMouseWheelDelta; // Amount of middle wheel scroll (+/-) + D3DXVECTOR2 m_vMouseDelta; // Mouse relative delta smoothed over a few frames + float m_fFramesToSmoothMouseData; // Number of frames to smooth mouse data over + + D3DXVECTOR3 m_vDefaultEye; // Default camera eye position + D3DXVECTOR3 m_vDefaultLookAt; // Default LookAt position + D3DXVECTOR3 m_vEye; // Camera eye position + D3DXVECTOR3 m_vLookAt; // LookAt position + float m_fCameraYawAngle; // Yaw angle of camera + float m_fCameraPitchAngle; // Pitch angle of camera + + RECT m_rcDrag; // Rectangle within which a drag can be initiated. + D3DXVECTOR3 m_vVelocity; // Velocity of camera + bool m_bMovementDrag; // If true, then camera movement will slow to a stop otherwise movement is instant + D3DXVECTOR3 m_vVelocityDrag; // Velocity drag force + FLOAT m_fDragTimer; // Countdown timer to apply drag + FLOAT m_fTotalDragTimeToZero; // Time it takes for velocity to go from full to 0 + D3DXVECTOR2 m_vRotVelocity; // Velocity of camera + + float m_fFOV; // Field of view + float m_fAspect; // Aspect ratio + float m_fNearPlane; // Near plane + float m_fFarPlane; // Far plane + + float m_fRotationScaler; // Scaler for rotation + float m_fMoveScaler; // Scaler for movement + + bool m_bInvertPitch; // Invert the pitch axis + bool m_bEnablePositionMovement; // If true, then the user can translate the camera/model + bool m_bEnableYAxisMovement; // If true, then camera can move in the y-axis + + bool m_bClipToBoundary; // If true, then the camera will be clipped to the boundary + D3DXVECTOR3 m_vMinBoundary; // Min point in clip boundary + D3DXVECTOR3 m_vMaxBoundary; // Max point in clip boundary + + bool m_bResetCursorAfterMove;// If true, the class will reset the cursor position so that the cursor always has space to move +}; + + +//-------------------------------------------------------------------------------------- +// Simple first person camera class that moves and rotates. +// It allows yaw and pitch but not roll. It uses WM_KEYDOWN and +// GetCursorPos() to respond to keyboard and mouse input and updates the +// view matrix based on input. +//-------------------------------------------------------------------------------------- +class CFirstPersonCamera : public CBaseCamera +{ +public: + CFirstPersonCamera(); + + // Call these from client and use Get*Matrix() to read new matrices + virtual void FrameMove( FLOAT fElapsedTime ); + + // Functions to change behavior + void SetRotateButtons( bool bLeft, bool bMiddle, bool bRight, bool bRotateWithoutButtonDown = false ); + + // Functions to get state + D3DXMATRIX* GetWorldMatrix() + { + return &m_mCameraWorld; + } + + const D3DXVECTOR3* GetWorldRight() const + { + return ( D3DXVECTOR3* )&m_mCameraWorld._11; + } + const D3DXVECTOR3* GetWorldUp() const + { + return ( D3DXVECTOR3* )&m_mCameraWorld._21; + } + const D3DXVECTOR3* GetWorldAhead() const + { + return ( D3DXVECTOR3* )&m_mCameraWorld._31; + } + const D3DXVECTOR3* GetEyePt() const + { + return ( D3DXVECTOR3* )&m_mCameraWorld._41; + } + +protected: + D3DXMATRIX m_mCameraWorld; // World matrix of the camera (inverse of the view matrix) + + int m_nActiveButtonMask; // Mask to determine which button to enable for rotation + bool m_bRotateWithoutButtonDown; +}; + + +//-------------------------------------------------------------------------------------- +// Simple model viewing camera class that rotates around the object. +//-------------------------------------------------------------------------------------- +class CModelViewerCamera : public CBaseCamera +{ +public: + CModelViewerCamera(); + + // Call these from client and use Get*Matrix() to read new matrices + virtual LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + virtual void FrameMove( FLOAT fElapsedTime ); + + + // Functions to change behavior + virtual void SetDragRect( RECT& rc ); + void Reset(); + void SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt ); + void SetButtonMasks( int nRotateModelButtonMask = MOUSE_LEFT_BUTTON, int nZoomButtonMask = MOUSE_WHEEL, + int nRotateCameraButtonMask = MOUSE_RIGHT_BUTTON ) + { + m_nRotateModelButtonMask = nRotateModelButtonMask, m_nZoomButtonMask = nZoomButtonMask; + m_nRotateCameraButtonMask = nRotateCameraButtonMask; + } + void SetAttachCameraToModel( bool bEnable = false ) + { + m_bAttachCameraToModel = bEnable; + } + void SetWindow( int nWidth, int nHeight, float fArcballRadius=0.9f ) + { + m_WorldArcBall.SetWindow( nWidth, nHeight, fArcballRadius ); + m_ViewArcBall.SetWindow( nWidth, nHeight, fArcballRadius ); + } + void SetRadius( float fDefaultRadius=5.0f, float fMinRadius=1.0f, float fMaxRadius=FLT_MAX ) + { + m_fDefaultRadius = m_fRadius = fDefaultRadius; m_fMinRadius = fMinRadius; m_fMaxRadius = fMaxRadius; + m_bDragSinceLastUpdate = true; + } + void SetModelCenter( D3DXVECTOR3 vModelCenter ) + { + m_vModelCenter = vModelCenter; + } + void SetLimitPitch( bool bLimitPitch ) + { + m_bLimitPitch = bLimitPitch; + } + void SetViewQuat( D3DXQUATERNION q ) + { + m_ViewArcBall.SetQuatNow( q ); m_bDragSinceLastUpdate = true; + } + void SetWorldQuat( D3DXQUATERNION q ) + { + m_WorldArcBall.SetQuatNow( q ); m_bDragSinceLastUpdate = true; + } + + // Functions to get state + const D3DXMATRIX* GetWorldMatrix() const + { + return &m_mWorld; + } + void SetWorldMatrix( D3DXMATRIX& mWorld ) + { + m_mWorld = mWorld; m_bDragSinceLastUpdate = true; + } + +protected: + CD3DArcBall m_WorldArcBall; + CD3DArcBall m_ViewArcBall; + D3DXVECTOR3 m_vModelCenter; + D3DXMATRIX m_mModelLastRot; // Last arcball rotation matrix for model + D3DXMATRIX m_mModelRot; // Rotation matrix of model + D3DXMATRIX m_mWorld; // World matrix of model + + int m_nRotateModelButtonMask; + int m_nZoomButtonMask; + int m_nRotateCameraButtonMask; + + bool m_bAttachCameraToModel; + bool m_bLimitPitch; + float m_fRadius; // Distance from the camera to model + float m_fDefaultRadius; // Distance from the camera to model + float m_fMinRadius; // Min radius + float m_fMaxRadius; // Max radius + bool m_bDragSinceLastUpdate; // True if mouse drag has happened since last time FrameMove is called. + + D3DXMATRIX m_mCameraRotLast; + +}; + +//-------------------------------------------------------------------------------------- +// Manages the mesh, direction, mouse events of a directional arrow that +// rotates around a radius controlled by an arcball +//-------------------------------------------------------------------------------------- +class CDXUTDirectionWidget +{ +public: + CDXUTDirectionWidget(); + + static HRESULT WINAPI StaticOnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice ); + HRESULT OnD3D9ResetDevice( const D3DSURFACE_DESC* pBackBufferSurfaceDesc ); + HRESULT OnRender9( D3DXCOLOR color, const D3DXMATRIX* pmView, const D3DXMATRIX* pmProj, + const D3DXVECTOR3* pEyePt ); + LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + static void WINAPI StaticOnD3D9LostDevice(); + static void WINAPI StaticOnD3D9DestroyDevice(); + + static HRESULT WINAPI StaticOnD3D11CreateDevice( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext ); + HRESULT OnRender11( D3DXCOLOR color, const D3DXMATRIX* pmView, const D3DXMATRIX* pmProj, + const D3DXVECTOR3* pEyePt ); + static void WINAPI StaticOnD3D11DestroyDevice(); + + D3DXVECTOR3 GetLightDirection() + { + return m_vCurrentDir; + }; + void SetLightDirection( D3DXVECTOR3 vDir ) + { + m_vDefaultDir = m_vCurrentDir = vDir; + }; + void SetButtonMask( int nRotate = MOUSE_RIGHT_BUTTON ) + { + m_nRotateMask = nRotate; + } + + float GetRadius() + { + return m_fRadius; + }; + void SetRadius( float fRadius ) + { + m_fRadius = fRadius; + }; + + bool IsBeingDragged() + { + return m_ArcBall.IsBeingDragged(); + }; + +protected: + HRESULT UpdateLightDir(); + + // D3D9 objects + static IDirect3DDevice9* s_pd3d9Device; + static ID3DXEffect* s_pD3D9Effect; + static ID3DXMesh* s_pD3D9Mesh; + static D3DXHANDLE s_hRenderWith1LightNoTexture; + static D3DXHANDLE s_hMaterialDiffuseColor; + static D3DXHANDLE s_hLightDir; + static D3DXHANDLE s_hWorldViewProjection; + static D3DXHANDLE s_hWorld; + + // D3D10 objects + //static ID3D10Device* s_pd3d10Device; + //static ID3D10Effect* s_pD3D10Effect; + //TODO: add some sort of d3d10 mesh object here + //static ID3D10InputLayout* s_pVertexLayout; + //static ID3D10EffectTechnique* s_pRenderTech; + //static ID3D10EffectVectorVariable* g_pMaterialDiffuseColor; + //static ID3D10EffectVectorVariable* g_pLightDir; + //static ID3D10EffectMatrixVariable* g_pmWorld; + //static ID3D10EffectMatrixVariable* g_pmWorldViewProjection; + + D3DXMATRIXA16 m_mRot; + D3DXMATRIXA16 m_mRotSnapshot; + float m_fRadius; + int m_nRotateMask; + CD3DArcBall m_ArcBall; + D3DXVECTOR3 m_vDefaultDir; + D3DXVECTOR3 m_vCurrentDir; + D3DXMATRIX m_mView; +}; + + + +#endif diff --git a/Demos/DX11ClothDemo/DXUT/Optional/DXUTgui.cpp b/Demos/DX11ClothDemo/DXUT/Optional/DXUTgui.cpp new file mode 100644 index 0000000..dba0b17 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/DXUTgui.cpp @@ -0,0 +1,7241 @@ +//-------------------------------------------------------------------------------------- +// File: DXUTgui.cpp +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "DXUT.h" +#include "DXUTgui.h" +#include "DXUTsettingsDlg.h" +#include "DXUTres.h" + +#include "SDKMisc.h" + +#undef min // use __min instead +#undef max // use __max instead + +#ifndef WM_XBUTTONDOWN +#define WM_XBUTTONDOWN 0x020B // (not always defined) +#endif +#ifndef WM_XBUTTONUP +#define WM_XBUTTONUP 0x020C // (not always defined) +#endif +#ifndef WM_MOUSEWHEEL +#define WM_MOUSEWHEEL 0x020A // (not always defined) +#endif +#ifndef WHEEL_DELTA +#define WHEEL_DELTA 120 // (not always defined) +#endif + +// Minimum scroll bar thumb size +#define SCROLLBAR_MINTHUMBSIZE 8 + +// Delay and repeat period when clicking on the scroll bar arrows +#define SCROLLBAR_ARROWCLICK_DELAY 0.33 +#define SCROLLBAR_ARROWCLICK_REPEAT 0.05 + +#define DXUT_NEAR_BUTTON_DEPTH 0.6f +#define DXUT_FAR_BUTTON_DEPTH 0.8f + +#define DXUT_MAX_GUI_SPRITES 500 + +D3DCOLORVALUE D3DCOLOR_TO_D3DCOLORVALUE( D3DCOLOR c ) +{ + D3DCOLORVALUE cv = + { + ( ( c >> 16 ) & 0xFF ) / 255.0f, + ( ( c >> 8 ) & 0xFF ) / 255.0f, + ( c & 0xFF ) / 255.0f, + ( ( c >> 24 ) & 0xFF ) / 255.0f + }; + return cv; +} + +#define UNISCRIBE_DLLNAME L"usp10.dll" + +#define GETPROCADDRESS( Module, APIName, Temp ) \ + Temp = GetProcAddress( Module, #APIName ); \ + if( Temp ) \ + *(FARPROC*)&_##APIName = Temp + +#define PLACEHOLDERPROC( APIName ) \ + _##APIName = Dummy_##APIName + +#define IMM32_DLLNAME L"imm32.dll" +#define VER_DLLNAME L"version.dll" + +CHAR g_strUIEffectFile[] = \ + "Texture2D g_Texture;"\ + ""\ + "SamplerState Sampler"\ + "{"\ + " Filter = MIN_MAG_MIP_LINEAR;"\ + " AddressU = Wrap;"\ + " AddressV = Wrap;"\ + "};"\ + ""\ + "BlendState UIBlend"\ + "{"\ + " AlphaToCoverageEnable = FALSE;"\ + " BlendEnable[0] = TRUE;"\ + " SrcBlend = SRC_ALPHA;"\ + " DestBlend = INV_SRC_ALPHA;"\ + " BlendOp = ADD;"\ + " SrcBlendAlpha = ONE;"\ + " DestBlendAlpha = ZERO;"\ + " BlendOpAlpha = ADD;"\ + " RenderTargetWriteMask[0] = 0x0F;"\ + "};"\ + ""\ + "BlendState NoBlending"\ + "{"\ + " BlendEnable[0] = FALSE;"\ + " RenderTargetWriteMask[0] = 0x0F;"\ + "};"\ + ""\ + "DepthStencilState DisableDepth"\ + "{"\ + " DepthEnable = false;"\ + "};"\ + "DepthStencilState EnableDepth"\ + "{"\ + " DepthEnable = true;"\ + "};"\ + "struct VS_OUTPUT"\ + "{"\ + " float4 Pos : POSITION;"\ + " float4 Dif : COLOR;"\ + " float2 Tex : TEXCOORD;"\ + "};"\ + ""\ + "VS_OUTPUT VS( float3 vPos : POSITION,"\ + " float4 Dif : COLOR,"\ + " float2 vTexCoord0 : TEXCOORD )"\ + "{"\ + " VS_OUTPUT Output;"\ + ""\ + " Output.Pos = float4( vPos, 1.0f );"\ + " Output.Dif = Dif;"\ + " Output.Tex = vTexCoord0;"\ + ""\ + " return Output;"\ + "}"\ + ""\ + "float4 PS( VS_OUTPUT In ) : SV_Target"\ + "{"\ + " return g_Texture.Sample( Sampler, In.Tex ) * In.Dif;"\ + "}"\ + ""\ + "float4 PSUntex( VS_OUTPUT In ) : SV_Target"\ + "{"\ + " return In.Dif;"\ + "}"\ + ""\ + "technique10 RenderUI"\ + "{"\ + " pass P0"\ + " {"\ + " SetVertexShader( CompileShader( vs_4_0, VS() ) );"\ + " SetGeometryShader( NULL );"\ + " SetPixelShader( CompileShader( ps_4_0, PS() ) );"\ + " SetDepthStencilState( DisableDepth, 0 );"\ + " SetBlendState( UIBlend, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );"\ + " }"\ + "}"\ + "technique10 RenderUIUntex"\ + "{"\ + " pass P0"\ + " {"\ + " SetVertexShader( CompileShader( vs_4_0, VS() ) );"\ + " SetGeometryShader( NULL );"\ + " SetPixelShader( CompileShader( ps_4_0, PSUntex() ) );"\ + " SetDepthStencilState( DisableDepth, 0 );"\ + " SetBlendState( UIBlend, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );"\ + " }"\ + "}"\ + "technique10 RestoreState"\ + "{"\ + " pass P0"\ + " {"\ + " SetDepthStencilState( EnableDepth, 0 );"\ + " SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );"\ + " }"\ + "}"; +const UINT g_uUIEffectFileSize = sizeof( g_strUIEffectFile ); + + +// DXUT_MAX_EDITBOXLENGTH is the maximum string length allowed in edit boxes, +// including the NULL terminator. +// +// Uniscribe does not support strings having bigger-than-16-bits length. +// This means that the string must be less than 65536 characters long, +// including the NULL terminator. +#define DXUT_MAX_EDITBOXLENGTH 0xFFFF + + +double CDXUTDialog::s_fTimeRefresh = 0.0f; +CDXUTControl* CDXUTDialog::s_pControlFocus = NULL; // The control which has focus +CDXUTControl* CDXUTDialog::s_pControlPressed = NULL; // The control currently pressed + + +struct DXUT_SCREEN_VERTEX +{ + float x, y, z, h; + D3DCOLOR color; + float tu, tv; + + static DWORD FVF; +}; +DWORD DXUT_SCREEN_VERTEX::FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1; + + +struct DXUT_SCREEN_VERTEX_UNTEX +{ + float x, y, z, h; + D3DCOLOR color; + + static DWORD FVF; +}; +DWORD DXUT_SCREEN_VERTEX_UNTEX::FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE; + + +struct DXUT_SCREEN_VERTEX_10 +{ + float x, y, z; + D3DCOLORVALUE color; + float tu, tv; +}; + + +inline int RectWidth( RECT& rc ) +{ + return ( ( rc ).right - ( rc ).left ); +} +inline int RectHeight( RECT& rc ) +{ + return ( ( rc ).bottom - ( rc ).top ); +} + + +HRESULT InitFont11( ID3D11Device* pd3d11Device, ID3D11InputLayout* pInputLayout ); +void EndFont11(); + +//-------------------------------------------------------------------------------------- +// CDXUTDialog class +//-------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------------- +CDXUTDialog::CDXUTDialog() +{ + m_x = 0; + m_y = 0; + m_width = 0; + m_height = 0; + + m_pManager = NULL; + m_bVisible = true; + m_bCaption = false; + m_bMinimized = false; + m_bDrag = false; + m_wszCaption[0] = L'\0'; + m_nCaptionHeight = 18; + + m_colorTopLeft = 0; + m_colorTopRight = 0; + m_colorBottomLeft = 0; + m_colorBottomRight = 0; + + m_pCallbackEvent = NULL; + m_pCallbackEventUserContext = NULL; + + m_fTimeLastRefresh = 0; + + m_pControlMouseOver = NULL; + + m_pNextDialog = this; + m_pPrevDialog = this; + + m_nDefaultControlID = 0xffff; + m_bNonUserEvents = false; + m_bKeyboardInput = false; + m_bMouseInput = true; +} + + +//-------------------------------------------------------------------------------------- +CDXUTDialog::~CDXUTDialog() +{ + int i = 0; + + RemoveAllControls(); + + m_Fonts.RemoveAll(); + m_Textures.RemoveAll(); + + for( i = 0; i < m_DefaultElements.GetSize(); i++ ) + { + DXUTElementHolder* pElementHolder = m_DefaultElements.GetAt( i ); + SAFE_DELETE( pElementHolder ); + } + + m_DefaultElements.RemoveAll(); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::Init( CDXUTDialogResourceManager* pManager, bool bRegisterDialog ) +{ + m_pManager = pManager; + if( bRegisterDialog ) + pManager->RegisterDialog( this ); + + SetTexture( 0, MAKEINTRESOURCE( 0xFFFF ), ( HMODULE )0xFFFF ); + InitDefaultElements(); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::Init( CDXUTDialogResourceManager* pManager, bool bRegisterDialog, LPCWSTR pszControlTextureFilename ) +{ + m_pManager = pManager; + if( bRegisterDialog ) + pManager->RegisterDialog( this ); + SetTexture( 0, pszControlTextureFilename ); + InitDefaultElements(); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::Init( CDXUTDialogResourceManager* pManager, bool bRegisterDialog, + LPCWSTR szControlTextureResourceName, HMODULE hControlTextureResourceModule ) +{ + m_pManager = pManager; + if( bRegisterDialog ) + pManager->RegisterDialog( this ); + + SetTexture( 0, szControlTextureResourceName, hControlTextureResourceModule ); + InitDefaultElements(); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::SetCallback( PCALLBACKDXUTGUIEVENT pCallback, void* pUserContext ) +{ + // If this assert triggers, you need to call CDXUTDialog::Init() first. This change + // was made so that the DXUT's GUI could become seperate and optional from DXUT's core. The + // creation and interfacing with CDXUTDialogResourceManager is now the responsibility + // of the application if it wishes to use DXUT's GUI. + assert( m_pManager != NULL && L"To fix call CDXUTDialog::Init() first. See comments for details." ); + + m_pCallbackEvent = pCallback; + m_pCallbackEventUserContext = pUserContext; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::RemoveControl( int ID ) +{ + for( int i = 0; i < m_Controls.GetSize(); i++ ) + { + CDXUTControl* pControl = m_Controls.GetAt( i ); + if( pControl->GetID() == ID ) + { + // Clean focus first + ClearFocus(); + + // Clear references to this control + if( s_pControlFocus == pControl ) + s_pControlFocus = NULL; + if( s_pControlPressed == pControl ) + s_pControlPressed = NULL; + if( m_pControlMouseOver == pControl ) + m_pControlMouseOver = NULL; + + SAFE_DELETE( pControl ); + m_Controls.Remove( i ); + + return; + } + } +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::RemoveAllControls() +{ + if( s_pControlFocus && s_pControlFocus->m_pDialog == this ) + s_pControlFocus = NULL; + if( s_pControlPressed && s_pControlPressed->m_pDialog == this ) + s_pControlPressed = NULL; + m_pControlMouseOver = NULL; + + for( int i = 0; i < m_Controls.GetSize(); i++ ) + { + CDXUTControl* pControl = m_Controls.GetAt( i ); + SAFE_DELETE( pControl ); + } + + m_Controls.RemoveAll(); +} + + +//-------------------------------------------------------------------------------------- +CDXUTDialogResourceManager::CDXUTDialogResourceManager() +{ + // Begin D3D9-specific + m_pd3d9Device = NULL; + m_pStateBlock = NULL; + m_pSprite = NULL; + + // Begin D3D11-specific + // Shaders + m_pVSRenderUI11 = NULL; + m_pPSRenderUI11 = NULL; + m_pPSRenderUIUntex11 = NULL; + + // States + m_pDepthStencilStateUI11 = NULL; + m_pRasterizerStateUI11 = NULL; + m_pBlendStateUI11 = NULL; + m_pSamplerStateUI11 = NULL; + m_pDepthStencilStateStored11 = NULL; + m_pRasterizerStateStored11 = NULL; + m_pBlendStateStored11 = NULL; + m_pSamplerStateStored11 = NULL; + + m_pInputLayout11 = NULL; + m_pVBScreenQuad11 = NULL; + m_pSpriteBuffer11 = NULL; +} + + +//-------------------------------------------------------------------------------------- +CDXUTDialogResourceManager::~CDXUTDialogResourceManager() +{ + int i; + for( i = 0; i < m_FontCache.GetSize(); i++ ) + { + DXUTFontNode* pFontNode = m_FontCache.GetAt( i ); + SAFE_DELETE( pFontNode ); + } + m_FontCache.RemoveAll(); + + for( i = 0; i < m_TextureCache.GetSize(); i++ ) + { + DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( i ); + SAFE_DELETE( pTextureNode ); + } + m_TextureCache.RemoveAll(); + + CUniBuffer::Uninitialize(); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialogResourceManager::OnD3D9CreateDevice( LPDIRECT3DDEVICE9 pd3dDevice ) +{ + HRESULT hr = S_OK; + int i = 0; + + m_pd3d9Device = pd3dDevice; + + for( i = 0; i < m_FontCache.GetSize(); i++ ) + { + hr = CreateFont9( i ); + if( FAILED( hr ) ) + return hr; + } + + for( i = 0; i < m_TextureCache.GetSize(); i++ ) + { + hr = CreateTexture9( i ); + if( FAILED( hr ) ) + return hr; + } + + hr = D3DXCreateSprite( pd3dDevice, &m_pSprite ); + if( FAILED( hr ) ) + return DXUT_ERR( L"D3DXCreateSprite", hr ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialogResourceManager::OnD3D9ResetDevice() +{ + HRESULT hr = S_OK; + + for( int i = 0; i < m_FontCache.GetSize(); i++ ) + { + DXUTFontNode* pFontNode = m_FontCache.GetAt( i ); + + if( pFontNode->pFont9 ) + pFontNode->pFont9->OnResetDevice(); + } + + if( m_pSprite ) + m_pSprite->OnResetDevice(); + + V_RETURN( m_pd3d9Device->CreateStateBlock( D3DSBT_ALL, &m_pStateBlock ) ); + + return S_OK; +} + +//-------------------------------------------------------------------------------------- +bool CDXUTDialogResourceManager::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + return false; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialogResourceManager::OnD3D9LostDevice() +{ + for( int i = 0; i < m_FontCache.GetSize(); i++ ) + { + DXUTFontNode* pFontNode = m_FontCache.GetAt( i ); + + if( pFontNode->pFont9 ) + pFontNode->pFont9->OnLostDevice(); + } + + if( m_pSprite ) + m_pSprite->OnLostDevice(); + + SAFE_RELEASE( m_pStateBlock ); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialogResourceManager::OnD3D9DestroyDevice() +{ + int i = 0; + + m_pd3d9Device = NULL; + + // Release the resources but don't clear the cache, as these will need to be + // recreated if the device is recreated + for( i = 0; i < m_FontCache.GetSize(); i++ ) + { + DXUTFontNode* pFontNode = m_FontCache.GetAt( i ); + SAFE_RELEASE( pFontNode->pFont9 ); + } + + for( i = 0; i < m_TextureCache.GetSize(); i++ ) + { + DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( i ); + SAFE_RELEASE( pTextureNode->pTexture9 ); + } + + SAFE_RELEASE( m_pSprite ); +} + + + +HRESULT CDXUTDialogResourceManager::OnD3D11CreateDevice( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3d11DeviceContext ) +{ + m_pd3d11Device = pd3dDevice; + m_pd3d11DeviceContext = pd3d11DeviceContext; + + HRESULT hr = S_OK; + + // Compile Shaders + ID3DBlob* pVSBlob = NULL; + ID3DBlob* pPSBlob = NULL; + ID3DBlob* pPSUntexBlob = NULL; + V_RETURN( D3DCompile( g_strUIEffectFile, g_uUIEffectFileSize, "none", NULL, NULL, "VS", "vs_4_0_level_9_1", + D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY, 0, &pVSBlob, NULL ) ); + V_RETURN( D3DCompile( g_strUIEffectFile, g_uUIEffectFileSize, "none", NULL, NULL, "PS", "ps_4_0_level_9_1", + D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY, 0, &pPSBlob, NULL ) ); + V_RETURN( D3DCompile( g_strUIEffectFile, g_uUIEffectFileSize, "none", NULL, NULL, "PSUntex", "ps_4_0_level_9_1", + D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY, 0, &pPSUntexBlob, NULL ) ); +//D3D10_SHADER_ENABLE_STRICTNESS + + // Create Shaders + V_RETURN( pd3dDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &m_pVSRenderUI11 ) ); + V_RETURN( pd3dDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &m_pPSRenderUI11 ) ); + V_RETURN( pd3dDevice->CreatePixelShader( pPSUntexBlob->GetBufferPointer(), pPSUntexBlob->GetBufferSize(), NULL, &m_pPSRenderUIUntex11 ) ); + + // States + D3D11_DEPTH_STENCIL_DESC DSDesc; + ZeroMemory( &DSDesc, sizeof( D3D11_DEPTH_STENCIL_DESC ) ); + DSDesc.DepthEnable = FALSE; + DSDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + DSDesc.DepthFunc = D3D11_COMPARISON_LESS; + DSDesc.StencilEnable = FALSE; + V_RETURN( pd3dDevice->CreateDepthStencilState( &DSDesc, &m_pDepthStencilStateUI11 ) ); + + D3D11_RASTERIZER_DESC RSDesc; + RSDesc.AntialiasedLineEnable = FALSE; + RSDesc.CullMode = D3D11_CULL_BACK; + RSDesc.DepthBias = 0; + RSDesc.DepthBiasClamp = 0.0f; + RSDesc.DepthClipEnable = TRUE; + RSDesc.FillMode = D3D11_FILL_SOLID; + RSDesc.FrontCounterClockwise = FALSE; + RSDesc.MultisampleEnable = TRUE; + RSDesc.ScissorEnable = FALSE; + RSDesc.SlopeScaledDepthBias = 0.0f; + V_RETURN( pd3dDevice->CreateRasterizerState( &RSDesc, &m_pRasterizerStateUI11 ) ); + + D3D11_BLEND_DESC BSDesc; + ZeroMemory( &BSDesc, sizeof( D3D11_BLEND_DESC ) ); + + BSDesc.RenderTarget[0].BlendEnable = TRUE; + BSDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + BSDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + BSDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + BSDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + BSDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; + BSDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + BSDesc.RenderTarget[0].RenderTargetWriteMask = 0x0F; + + V_RETURN( pd3dDevice->CreateBlendState( &BSDesc, &m_pBlendStateUI11 ) ); + + D3D11_SAMPLER_DESC SSDesc; + ZeroMemory( &SSDesc, sizeof( D3D11_SAMPLER_DESC ) ); + SSDesc.Filter = D3D11_FILTER_ANISOTROPIC ; + SSDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + SSDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + SSDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + SSDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + SSDesc.MaxAnisotropy = 16; + SSDesc.MinLOD = 0; + SSDesc.MaxLOD = D3D11_FLOAT32_MAX; + if ( pd3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3 ) { + SSDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + SSDesc.MaxAnisotropy = 0; + } + V_RETURN( pd3dDevice->CreateSamplerState( &SSDesc, &m_pSamplerStateUI11 ) ); + + // Create the font and texture objects in the cache arrays. + int i = 0; + for( i = 0; i < m_FontCache.GetSize(); i++ ) + { + hr = CreateFont11( i ); + if( FAILED( hr ) ) + return hr; + } + + for( i = 0; i < m_TextureCache.GetSize(); i++ ) + { + hr = CreateTexture11( i ); + if( FAILED( hr ) ) + return hr; + } + + // Create input layout + const D3D11_INPUT_ELEMENT_DESC layout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + V_RETURN( pd3dDevice->CreateInputLayout( layout, ARRAYSIZE( layout ), pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &m_pInputLayout11 ) ); + + // Release the blobs + SAFE_RELEASE( pVSBlob ); + SAFE_RELEASE( pPSBlob ); + SAFE_RELEASE( pPSUntexBlob ); + + // Create a vertex buffer quad for rendering later + D3D11_BUFFER_DESC BufDesc; + BufDesc.ByteWidth = sizeof( DXUT_SCREEN_VERTEX_10 ) * 4; + BufDesc.Usage = D3D11_USAGE_DYNAMIC; + BufDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + BufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + BufDesc.MiscFlags = 0; + V_RETURN( pd3dDevice->CreateBuffer( &BufDesc, NULL, &m_pVBScreenQuad11 ) ); + + // Init the D3D11 font + InitFont11( pd3dDevice, m_pInputLayout11 ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialogResourceManager::OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, + const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc ) +{ + HRESULT hr = S_OK; + + m_nBackBufferWidth = pBackBufferSurfaceDesc->Width; + m_nBackBufferHeight = pBackBufferSurfaceDesc->Height; + + return hr; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialogResourceManager::OnD3D11ReleasingSwapChain() +{ +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialogResourceManager::OnD3D11DestroyDevice() +{ + int i; + + // Release the resources but don't clear the cache, as these will need to be + // recreated if the device is recreated + + for( i = 0; i < m_TextureCache.GetSize(); i++ ) + { + DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( i ); + SAFE_RELEASE( pTextureNode->pTexResView11 ); + SAFE_RELEASE( pTextureNode->pTexture11 ); + } + + // D3D11 + SAFE_RELEASE( m_pVBScreenQuad11 ); + SAFE_RELEASE( m_pSpriteBuffer11 ); + m_SpriteBufferBytes11 = 0; + SAFE_RELEASE( m_pInputLayout11 ); + + // Shaders + SAFE_RELEASE( m_pVSRenderUI11 ); + SAFE_RELEASE( m_pPSRenderUI11 ); + SAFE_RELEASE( m_pPSRenderUIUntex11 ); + + // States + SAFE_RELEASE( m_pDepthStencilStateUI11 ); + SAFE_RELEASE( m_pRasterizerStateUI11 ); + SAFE_RELEASE( m_pBlendStateUI11 ); + SAFE_RELEASE( m_pSamplerStateUI11 ); + + SAFE_RELEASE( m_pDepthStencilStateStored11 ); + SAFE_RELEASE( m_pRasterizerStateStored11 ); + SAFE_RELEASE( m_pBlendStateStored11 ); + SAFE_RELEASE( m_pSamplerStateStored11 ); + + EndFont11(); +} + +//-------------------------------------------------------------------------------------- +void CDXUTDialogResourceManager::StoreD3D11State( ID3D11DeviceContext* pd3dImmediateContext ) +{ + pd3dImmediateContext->OMGetDepthStencilState( &m_pDepthStencilStateStored11, &m_StencilRefStored11 ); + pd3dImmediateContext->RSGetState( &m_pRasterizerStateStored11 ); + pd3dImmediateContext->OMGetBlendState( &m_pBlendStateStored11, m_BlendFactorStored11, &m_SampleMaskStored11 ); + pd3dImmediateContext->PSGetSamplers( 0, 1, &m_pSamplerStateStored11 ); +} + +//-------------------------------------------------------------------------------------- +void CDXUTDialogResourceManager::RestoreD3D11State( ID3D11DeviceContext* pd3dImmediateContext ) +{ + pd3dImmediateContext->OMSetDepthStencilState( m_pDepthStencilStateStored11, m_StencilRefStored11 ); + pd3dImmediateContext->RSSetState( m_pRasterizerStateStored11 ); + pd3dImmediateContext->OMSetBlendState( m_pBlendStateStored11, m_BlendFactorStored11, m_SampleMaskStored11 ); + pd3dImmediateContext->PSSetSamplers( 0, 1, &m_pSamplerStateStored11 ); + + SAFE_RELEASE( m_pDepthStencilStateStored11 ); + SAFE_RELEASE( m_pRasterizerStateStored11 ); + SAFE_RELEASE( m_pBlendStateStored11 ); + SAFE_RELEASE( m_pSamplerStateStored11 ); +} + +//-------------------------------------------------------------------------------------- +void CDXUTDialogResourceManager::ApplyRenderUI11( ID3D11DeviceContext* pd3dImmediateContext ) +{ + // Shaders + pd3dImmediateContext->VSSetShader( m_pVSRenderUI11, NULL, 0 ); + pd3dImmediateContext->HSSetShader( NULL, NULL, 0 ); + pd3dImmediateContext->DSSetShader( NULL, NULL, 0 ); + pd3dImmediateContext->GSSetShader( NULL, NULL, 0 ); + pd3dImmediateContext->PSSetShader( m_pPSRenderUI11, NULL, 0 ); + + // States + pd3dImmediateContext->OMSetDepthStencilState( m_pDepthStencilStateUI11, 0 ); + pd3dImmediateContext->RSSetState( m_pRasterizerStateUI11 ); + float BlendFactor[4] = { 0, 0, 0, 0 }; + pd3dImmediateContext->OMSetBlendState( m_pBlendStateUI11, BlendFactor, 0xFFFFFFFF ); + pd3dImmediateContext->PSSetSamplers( 0, 1, &m_pSamplerStateUI11 ); +} + +//-------------------------------------------------------------------------------------- +void CDXUTDialogResourceManager::ApplyRenderUIUntex11( ID3D11DeviceContext* pd3dImmediateContext ) +{ + // Shaders + pd3dImmediateContext->VSSetShader( m_pVSRenderUI11, NULL, 0 ); + pd3dImmediateContext->HSSetShader( NULL, NULL, 0 ); + pd3dImmediateContext->DSSetShader( NULL, NULL, 0 ); + pd3dImmediateContext->GSSetShader( NULL, NULL, 0 ); + pd3dImmediateContext->PSSetShader( m_pPSRenderUIUntex11, NULL, 0 ); + + // States + pd3dImmediateContext->OMSetDepthStencilState( m_pDepthStencilStateUI11, 0 ); + pd3dImmediateContext->RSSetState( m_pRasterizerStateUI11 ); + float BlendFactor[4] = { 0, 0, 0, 0 }; + pd3dImmediateContext->OMSetBlendState( m_pBlendStateUI11, BlendFactor, 0xFFFFFFFF ); + pd3dImmediateContext->PSSetSamplers( 0, 1, &m_pSamplerStateUI11 ); +} + +//-------------------------------------------------------------------------------------- +void CDXUTDialogResourceManager::BeginSprites11( ) +{ + m_SpriteVertices.Reset(); +} + +//-------------------------------------------------------------------------------------- +void CDXUTDialogResourceManager::EndSprites11( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext ) +{ + + // ensure our buffer size can hold our sprites + UINT SpriteDataBytes = m_SpriteVertices.GetSize() * sizeof( DXUTSpriteVertex ); + if( m_SpriteBufferBytes11 < SpriteDataBytes ) + { + SAFE_RELEASE( m_pSpriteBuffer11 ); + m_SpriteBufferBytes11 = SpriteDataBytes; + + D3D11_BUFFER_DESC BufferDesc; + BufferDesc.ByteWidth = m_SpriteBufferBytes11; + BufferDesc.Usage = D3D11_USAGE_DYNAMIC; + BufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + BufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + BufferDesc.MiscFlags = 0; + + pd3dDevice->CreateBuffer( &BufferDesc, NULL, &m_pSpriteBuffer11 ); + } + + // Copy the sprites over + D3D11_BOX destRegion; + destRegion.left = 0; + destRegion.right = SpriteDataBytes; + destRegion.top = 0; + destRegion.bottom = 1; + destRegion.front = 0; + destRegion.back = 1; + D3D11_MAPPED_SUBRESOURCE MappedResource; + if ( S_OK == pd3dImmediateContext->Map( m_pSpriteBuffer11, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) ) { + CopyMemory( MappedResource.pData, (void*)m_SpriteVertices.GetData(), SpriteDataBytes ); + pd3dImmediateContext->Unmap(m_pSpriteBuffer11, 0); + } + + // Draw + UINT Stride = sizeof( DXUTSpriteVertex ); + UINT Offset = 0; + pd3dImmediateContext->IASetVertexBuffers( 0, 1, &m_pSpriteBuffer11, &Stride, &Offset ); + pd3dImmediateContext->IASetInputLayout( m_pInputLayout11 ); + pd3dImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); + pd3dImmediateContext->Draw( m_SpriteVertices.GetSize(), 0 ); + + m_SpriteVertices.Reset(); +} + +//-------------------------------------------------------------------------------------- +bool CDXUTDialogResourceManager::RegisterDialog( CDXUTDialog* pDialog ) +{ + // Check that the dialog isn't already registered. + for( int i = 0; i < m_Dialogs.GetSize(); ++i ) + if( m_Dialogs.GetAt( i ) == pDialog ) + return true; + + // Add to the list. + if( FAILED( m_Dialogs.Add( pDialog ) ) ) + return false; + + // Set up next and prev pointers. + if( m_Dialogs.GetSize() > 1 ) + m_Dialogs[m_Dialogs.GetSize() - 2]->SetNextDialog( pDialog ); + m_Dialogs[m_Dialogs.GetSize() - 1]->SetNextDialog( m_Dialogs[0] ); + + return true; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialogResourceManager::UnregisterDialog( CDXUTDialog* pDialog ) +{ + // Search for the dialog in the list. + for( int i = 0; i < m_Dialogs.GetSize(); ++i ) + if( m_Dialogs.GetAt( i ) == pDialog ) + { + m_Dialogs.Remove( i ); + if( m_Dialogs.GetSize() > 0 ) + { + int l, r; + + if( 0 == i ) + l = m_Dialogs.GetSize() - 1; + else + l = i - 1; + + if( m_Dialogs.GetSize() == i ) + r = 0; + else + r = i; + + m_Dialogs[l]->SetNextDialog( m_Dialogs[r] ); + } + return; + } +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialogResourceManager::EnableKeyboardInputForAllDialogs() +{ + // Enable keyboard input for all registered dialogs + for( int i = 0; i < m_Dialogs.GetSize(); ++i ) + m_Dialogs[i]->EnableKeyboardInput( true ); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::Refresh() +{ + if( s_pControlFocus ) + s_pControlFocus->OnFocusOut(); + + if( m_pControlMouseOver ) + m_pControlMouseOver->OnMouseLeave(); + + s_pControlFocus = NULL; + s_pControlPressed = NULL; + m_pControlMouseOver = NULL; + + for( int i = 0; i < m_Controls.GetSize(); i++ ) + { + CDXUTControl* pControl = m_Controls.GetAt( i ); + pControl->Refresh(); + } + + if( m_bKeyboardInput ) + FocusDefaultControl(); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::OnRender( float fElapsedTime ) +{ + if( m_pManager->GetD3D9Device() ) + return OnRender9( fElapsedTime ); + else + return OnRender11( fElapsedTime ); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::OnRender9( float fElapsedTime ) +{ + // If this assert triggers, you need to call CDXUTDialogResourceManager::On*Device() from inside + // the application's device callbacks. See the SDK samples for an example of how to do this. + assert( m_pManager->GetD3D9Device() && m_pManager->m_pStateBlock && + L"To fix hook up CDXUTDialogResourceManager to device callbacks. See comments for details" ); + + // See if the dialog needs to be refreshed + if( m_fTimeLastRefresh < s_fTimeRefresh ) + { + m_fTimeLastRefresh = DXUTGetTime(); + Refresh(); + } + + // For invisible dialog, out now. + if( !m_bVisible || + ( m_bMinimized && !m_bCaption ) ) + return S_OK; + + IDirect3DDevice9* pd3dDevice = m_pManager->GetD3D9Device(); + + // Set up a state block here and restore it when finished drawing all the controls + m_pManager->m_pStateBlock->Capture(); + + //pd3dDevice->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, TRUE); + //pd3dDevice->SetRenderState( D3DRS_SRGBWRITEENABLE, TRUE ); + + pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); + pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); + pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); + pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE ); + pd3dDevice->SetRenderState( D3DRS_SEPARATEALPHABLENDENABLE, FALSE ); + pd3dDevice->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD ); + pd3dDevice->SetRenderState( D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | + D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED ); + pd3dDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD ); + pd3dDevice->SetRenderState( D3DRS_FOGENABLE, FALSE ); + pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE ); + pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); + pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ); + + pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 ); + pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); + pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); + pd3dDevice->SetTextureStageState( 0, D3DTSS_RESULTARG, D3DTA_CURRENT ); + pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE ); + pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); + + BOOL bBackgroundIsVisible = ( m_colorTopLeft | m_colorTopRight | m_colorBottomRight | m_colorBottomLeft ) & + 0xff000000; + if( !m_bMinimized && bBackgroundIsVisible ) + { + DXUT_SCREEN_VERTEX_UNTEX vertices[4] = + { + ( float )m_x, ( float )m_y, 0.5f, 1.0f, m_colorTopLeft, + ( float )m_x + m_width, ( float )m_y, 0.5f, 1.0f, m_colorTopRight, + ( float )m_x + m_width, ( float )m_y + m_height, 0.5f, 1.0f, m_colorBottomRight, + ( float )m_x, ( float )m_y + m_height, 0.5f, 1.0f, m_colorBottomLeft, + }; + + pd3dDevice->SetVertexShader( NULL ); + pd3dDevice->SetPixelShader( NULL ); + + pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE ); + + pd3dDevice->SetFVF( DXUT_SCREEN_VERTEX_UNTEX::FVF ); + pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, vertices, sizeof( DXUT_SCREEN_VERTEX_UNTEX ) ); + } + + pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); + pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); + + pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); + pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); + + pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); + + DXUTTextureNode* pTextureNode = GetTexture( 0 ); + pd3dDevice->SetTexture( 0, pTextureNode->pTexture9 ); + + m_pManager->m_pSprite->Begin( D3DXSPRITE_DONOTSAVESTATE ); + + // Render the caption if it's enabled. + if( m_bCaption ) + { + // DrawSprite will offset the rect down by + // m_nCaptionHeight, so adjust the rect higher + // here to negate the effect. + RECT rc = + { + 0, -m_nCaptionHeight, m_width, 0 + }; + DrawSprite9( &m_CapElement, &rc ); + rc.left += 5; // Make a left margin + WCHAR wszOutput[256]; + wcscpy_s( wszOutput, 256, m_wszCaption ); + if( m_bMinimized ) + wcscat_s( wszOutput, 256, L" (Minimized)" ); + DrawText9( wszOutput, &m_CapElement, &rc, true ); + } + + // If the dialog is minimized, skip rendering + // its controls. + if( !m_bMinimized ) + { + for( int i = 0; i < m_Controls.GetSize(); i++ ) + { + CDXUTControl* pControl = m_Controls.GetAt( i ); + + // Focused control is drawn last + if( pControl == s_pControlFocus ) + continue; + + pControl->Render( fElapsedTime ); + } + + if( s_pControlFocus != NULL && s_pControlFocus->m_pDialog == this ) + s_pControlFocus->Render( fElapsedTime ); + } + + m_pManager->m_pSprite->End(); + + m_pManager->m_pStateBlock->Apply(); + + return S_OK; +} + + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::OnRender11( float fElapsedTime ) +{ + // If this assert triggers, you need to call CDXUTDialogResourceManager::On*Device() from inside + // the application's device callbacks. See the SDK samples for an example of how to do this. + assert( m_pManager->GetD3D11Device() && + L"To fix hook up CDXUTDialogResourceManager to device callbacks. See comments for details" ); + + // See if the dialog needs to be refreshed + if( m_fTimeLastRefresh < s_fTimeRefresh ) + { + m_fTimeLastRefresh = DXUTGetTime(); + Refresh(); + } + + // For invisible dialog, out now. + if( !m_bVisible || + ( m_bMinimized && !m_bCaption ) ) + return S_OK; + + ID3D11Device* pd3dDevice = m_pManager->GetD3D11Device(); + ID3D11DeviceContext* pd3dDeviceContext = m_pManager->GetD3D11DeviceContext(); + + // Set up a state block here and restore it when finished drawing all the controls + m_pManager->StoreD3D11State( pd3dDeviceContext ); + + BOOL bBackgroundIsVisible = ( m_colorTopLeft | m_colorTopRight | m_colorBottomRight | m_colorBottomLeft ) & + 0xff000000; + if( !m_bMinimized && bBackgroundIsVisible ) + { + // Convert the draw rectangle from screen coordinates to clip space coordinates. + float Left, Right, Top, Bottom; + Left = m_x * 2.0f / m_pManager->m_nBackBufferWidth - 1.0f; + Right = ( m_x + m_width ) * 2.0f / m_pManager->m_nBackBufferWidth - 1.0f; + Top = 1.0f - m_y * 2.0f / m_pManager->m_nBackBufferHeight; + Bottom = 1.0f - ( m_y + m_height ) * 2.0f / m_pManager->m_nBackBufferHeight; + + DXUT_SCREEN_VERTEX_10 vertices[4] = + { + Left, Top, 0.5f, D3DCOLOR_TO_D3DCOLORVALUE( m_colorTopLeft ), 0.0f, 0.0f, + Right, Top, 0.5f, D3DCOLOR_TO_D3DCOLORVALUE( m_colorTopRight ), 1.0f, 0.0f, + Left, Bottom, 0.5f, D3DCOLOR_TO_D3DCOLORVALUE( m_colorBottomLeft ), 0.0f, 1.0f, + Right, Bottom, 0.5f, D3DCOLOR_TO_D3DCOLORVALUE( m_colorBottomRight ), 1.0f, 1.0f, + }; + + //DXUT_SCREEN_VERTEX_10 *pVB; + D3D11_MAPPED_SUBRESOURCE MappedData; + if( SUCCEEDED( pd3dDeviceContext->Map( m_pManager->m_pVBScreenQuad11, 0, D3D11_MAP_WRITE_DISCARD, + 0, &MappedData ) ) ) + { + CopyMemory( MappedData.pData, vertices, sizeof( vertices ) ); + pd3dDeviceContext->Unmap( m_pManager->m_pVBScreenQuad11, 0 ); + } + + // Set the quad VB as current + UINT stride = sizeof( DXUT_SCREEN_VERTEX_10 ); + UINT offset = 0; + pd3dDeviceContext->IASetVertexBuffers( 0, 1, &m_pManager->m_pVBScreenQuad11, &stride, &offset ); + pd3dDeviceContext->IASetInputLayout( m_pManager->m_pInputLayout11 ); + pd3dDeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP ); + + // Setup for rendering + m_pManager->ApplyRenderUIUntex11( pd3dDeviceContext ); + pd3dDeviceContext->Draw( 4, 0 ); + } + + DXUTTextureNode* pTextureNode = GetTexture( 0 ); + pd3dDeviceContext->PSSetShaderResources( 0, 1, &pTextureNode->pTexResView11 ); + + // Sort depth back to front + m_pManager->BeginSprites11(); + BeginText11(); + + m_pManager->ApplyRenderUI11( pd3dDeviceContext ); + + // Render the caption if it's enabled. + if( m_bCaption ) + { + // DrawSprite will offset the rect down by + // m_nCaptionHeight, so adjust the rect higher + // here to negate the effect. + RECT rc = { 0, -m_nCaptionHeight, m_width, 0 }; + DrawSprite11( &m_CapElement, &rc, 0.99f ); + rc.left += 5; // Make a left margin + WCHAR wszOutput[256]; + wcscpy_s( wszOutput, 256, m_wszCaption ); + if( m_bMinimized ) + wcscat_s( wszOutput, 256, L" (Minimized)" ); + DrawText11( pd3dDevice, pd3dDeviceContext, wszOutput, &m_CapElement, &rc, true ); + } + + // If the dialog is minimized, skip rendering + // its controls. + if( !m_bMinimized ) + { + for( int i = 0; i < m_Controls.GetSize(); i++ ) + { + CDXUTControl* pControl = m_Controls.GetAt( i ); + + // Focused control is drawn last + if( pControl == s_pControlFocus ) + continue; + + pControl->Render( fElapsedTime ); + } + + if( s_pControlFocus != NULL && s_pControlFocus->m_pDialog == this ) + s_pControlFocus->Render( fElapsedTime ); + } + + // End sprites + if( m_bCaption ) + { + m_pManager->EndSprites11( pd3dDevice, pd3dDeviceContext ); + EndText11( pd3dDevice, pd3dDeviceContext ); + } + m_pManager->RestoreD3D11State( pd3dDeviceContext ); + + return S_OK; +} + +//-------------------------------------------------------------------------------------- +VOID CDXUTDialog::SendEvent( UINT nEvent, bool bTriggeredByUser, CDXUTControl* pControl ) +{ + // If no callback has been registered there's nowhere to send the event to + if( m_pCallbackEvent == NULL ) + return; + + // Discard events triggered programatically if these types of events haven't been + // enabled + if( !bTriggeredByUser && !m_bNonUserEvents ) + return; + + m_pCallbackEvent( nEvent, pControl->GetID(), pControl, m_pCallbackEventUserContext ); +} + + +//-------------------------------------------------------------------------------------- +int CDXUTDialogResourceManager::AddFont( LPCWSTR strFaceName, LONG height, LONG weight ) +{ + // See if this font already exists + for( int i = 0; i < m_FontCache.GetSize(); i++ ) + { + DXUTFontNode* pFontNode = m_FontCache.GetAt( i ); + size_t nLen = 0; + nLen = wcsnlen( strFaceName, MAX_PATH); + if( 0 == _wcsnicmp( pFontNode->strFace, strFaceName, nLen ) && + pFontNode->nHeight == height && + pFontNode->nWeight == weight ) + { + return i; + } + } + + // Add a new font and try to create it + DXUTFontNode* pNewFontNode = new DXUTFontNode; + if( pNewFontNode == NULL ) + return -1; + + ZeroMemory( pNewFontNode, sizeof( DXUTFontNode ) ); + wcscpy_s( pNewFontNode->strFace, MAX_PATH, strFaceName ); + pNewFontNode->nHeight = height; + pNewFontNode->nWeight = weight; + m_FontCache.Add( pNewFontNode ); + + int iFont = m_FontCache.GetSize() - 1; + + // If a device is available, try to create immediately + if( m_pd3d9Device ) + CreateFont9( iFont ); + + return iFont; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::SetFont( UINT index, LPCWSTR strFaceName, LONG height, LONG weight ) +{ + // If this assert triggers, you need to call CDXUTDialog::Init() first. This change + // was made so that the DXUT's GUI could become seperate and optional from DXUT's core. The + // creation and interfacing with CDXUTDialogResourceManager is now the responsibility + // of the application if it wishes to use DXUT's GUI. + assert( m_pManager != NULL && L"To fix call CDXUTDialog::Init() first. See comments for details." ); + + // Make sure the list is at least as large as the index being set + UINT i; + for( i = m_Fonts.GetSize(); i <= index; i++ ) + { + m_Fonts.Add( -1 ); + } + + int iFont = m_pManager->AddFont( strFaceName, height, weight ); + m_Fonts.SetAt( index, iFont ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +DXUTFontNode* CDXUTDialog::GetFont( UINT index ) +{ + if( NULL == m_pManager ) + return NULL; + return m_pManager->GetFontNode( m_Fonts.GetAt( index ) ); +} + + +//-------------------------------------------------------------------------------------- +int CDXUTDialogResourceManager::AddTexture( LPCWSTR strFilename ) +{ + // See if this texture already exists + for( int i = 0; i < m_TextureCache.GetSize(); i++ ) + { + DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( i ); + size_t nLen = 0; + nLen = wcsnlen( strFilename, MAX_PATH); + if( pTextureNode->bFileSource && // Sources must match + 0 == _wcsnicmp( pTextureNode->strFilename, strFilename, nLen ) ) + { + return i; + } + } + + // Add a new texture and try to create it + DXUTTextureNode* pNewTextureNode = new DXUTTextureNode; + if( pNewTextureNode == NULL ) + return -1; + + ZeroMemory( pNewTextureNode, sizeof( DXUTTextureNode ) ); + pNewTextureNode->bFileSource = true; + wcscpy_s( pNewTextureNode->strFilename, MAX_PATH, strFilename ); + + m_TextureCache.Add( pNewTextureNode ); + + int iTexture = m_TextureCache.GetSize() - 1; + + // If a device is available, try to create immediately + if( m_pd3d9Device ) + CreateTexture9( iTexture ); + + return iTexture; +} + + +//-------------------------------------------------------------------------------------- +int CDXUTDialogResourceManager::AddTexture( LPCWSTR strResourceName, HMODULE hResourceModule ) +{ + // See if this texture already exists + for( int i = 0; i < m_TextureCache.GetSize(); i++ ) + { + DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( i ); + if( !pTextureNode->bFileSource && // Sources must match + pTextureNode->hResourceModule == hResourceModule ) // Module handles must match + { + if( IS_INTRESOURCE( strResourceName ) ) + { + // Integer-based ID + if( ( INT_PTR )strResourceName == pTextureNode->nResourceID ) + return i; + } + else + { + // String-based ID + size_t nLen = 0; + nLen = wcsnlen ( strResourceName, MAX_PATH ); + if( 0 == _wcsnicmp( pTextureNode->strFilename, strResourceName, nLen ) ) + return i; + } + } + } + + // Add a new texture and try to create it + DXUTTextureNode* pNewTextureNode = new DXUTTextureNode; + if( pNewTextureNode == NULL ) + return -1; + + ZeroMemory( pNewTextureNode, sizeof( DXUTTextureNode ) ); + pNewTextureNode->hResourceModule = hResourceModule; + if( IS_INTRESOURCE( strResourceName ) ) + { + pNewTextureNode->nResourceID = ( int )( size_t )strResourceName; + } + else + { + pNewTextureNode->nResourceID = 0; + wcscpy_s( pNewTextureNode->strFilename, MAX_PATH, strResourceName ); + } + + m_TextureCache.Add( pNewTextureNode ); + + int iTexture = m_TextureCache.GetSize() - 1; + + // If a device is available, try to create immediately + if( m_pd3d9Device ) + CreateTexture9( iTexture ); + + return iTexture; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::SetTexture( UINT index, LPCWSTR strFilename ) +{ + // If this assert triggers, you need to call CDXUTDialog::Init() first. This change + // was made so that the DXUT's GUI could become seperate and optional from DXUT's core. The + // creation and interfacing with CDXUTDialogResourceManager is now the responsibility + // of the application if it wishes to use DXUT's GUI. + assert( m_pManager != NULL && L"To fix this, call CDXUTDialog::Init() first. See comments for details." ); + + // Make sure the list is at least as large as the index being set + for( UINT i = m_Textures.GetSize(); i <= index; i++ ) + { + m_Textures.Add( -1 ); + } + + int iTexture = m_pManager->AddTexture( strFilename ); + + m_Textures.SetAt( index, iTexture ); + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::SetTexture( UINT index, LPCWSTR strResourceName, HMODULE hResourceModule ) +{ + // If this assert triggers, you need to call CDXUTDialog::Init() first. This change + // was made so that the DXUT's GUI could become seperate and optional from DXUT's core. The + // creation and interfacing with CDXUTDialogResourceManager is now the responsibility + // of the application if it wishes to use DXUT's GUI. + assert( m_pManager != NULL && L"To fix this, call CDXUTDialog::Init() first. See comments for details." ); + + // Make sure the list is at least as large as the index being set + for( UINT i = m_Textures.GetSize(); i <= index; i++ ) + { + m_Textures.Add( -1 ); + } + + int iTexture = m_pManager->AddTexture( strResourceName, hResourceModule ); + + m_Textures.SetAt( index, iTexture ); + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +DXUTTextureNode* CDXUTDialog::GetTexture( UINT index ) +{ + if( NULL == m_pManager ) + return NULL; + return m_pManager->GetTextureNode( m_Textures.GetAt( index ) ); +} + + + +//-------------------------------------------------------------------------------------- +bool CDXUTDialog::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + bool bHandled = false; + + // For invisible dialog, do not handle anything. + if( !m_bVisible ) + return false; + + // If automation command-line switch is on, enable this dialog's keyboard input + // upon any key press or mouse click. + if( DXUTGetAutomation() && + ( WM_LBUTTONDOWN == uMsg || WM_LBUTTONDBLCLK == uMsg || WM_KEYDOWN == uMsg ) ) + { + m_pManager->EnableKeyboardInputForAllDialogs(); + } + + // If caption is enable, check for clicks in the caption area. + if( m_bCaption ) + { + if( uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK ) + { + POINT mousePoint = + { + short( LOWORD( lParam ) ), short( HIWORD( lParam ) ) + }; + + if( mousePoint.x >= m_x && mousePoint.x < m_x + m_width && + mousePoint.y >= m_y && mousePoint.y < m_y + m_nCaptionHeight ) + { + m_bDrag = true; + SetCapture( DXUTGetHWND() ); + return true; + } + } + else if( uMsg == WM_LBUTTONUP && m_bDrag ) + { + POINT mousePoint = + { + short( LOWORD( lParam ) ), short( HIWORD( lParam ) ) + }; + + if( mousePoint.x >= m_x && mousePoint.x < m_x + m_width && + mousePoint.y >= m_y && mousePoint.y < m_y + m_nCaptionHeight ) + { + ReleaseCapture(); + m_bDrag = false; + m_bMinimized = !m_bMinimized; + return true; + } + } + } + + // If the dialog is minimized, don't send any messages to controls. + if( m_bMinimized ) + return false; + + // If a control is in focus, it belongs to this dialog, and it's enabled, then give + // it the first chance at handling the message. + if( s_pControlFocus && + s_pControlFocus->m_pDialog == this && + s_pControlFocus->GetEnabled() ) + { + // If the control MsgProc handles it, then we don't. + if( s_pControlFocus->MsgProc( uMsg, wParam, lParam ) ) + return true; + } + + switch( uMsg ) + { + case WM_SIZE: + case WM_MOVE: + { + // Handle sizing and moving messages so that in case the mouse cursor is moved out + // of an UI control because of the window adjustment, we can properly + // unhighlight the highlighted control. + POINT pt = + { + -1, -1 + }; + OnMouseMove( pt ); + break; + } + + case WM_ACTIVATEAPP: + // Call OnFocusIn()/OnFocusOut() of the control that currently has the focus + // as the application is activated/deactivated. This matches the Windows + // behavior. + if( s_pControlFocus && + s_pControlFocus->m_pDialog == this && + s_pControlFocus->GetEnabled() ) + { + if( wParam ) + s_pControlFocus->OnFocusIn(); + else + s_pControlFocus->OnFocusOut(); + } + break; + + // Keyboard messages + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + case WM_KEYUP: + case WM_SYSKEYUP: + { + // If a control is in focus, it belongs to this dialog, and it's enabled, then give + // it the first chance at handling the message. + if( s_pControlFocus && + s_pControlFocus->m_pDialog == this && + s_pControlFocus->GetEnabled() ) + { + if( s_pControlFocus->HandleKeyboard( uMsg, wParam, lParam ) ) + return true; + } + + // Not yet handled, see if this matches a control's hotkey + // Activate the hotkey if the focus doesn't belong to an + // edit box. + if( uMsg == WM_KEYDOWN && ( !s_pControlFocus || + ( s_pControlFocus->GetType() != DXUT_CONTROL_EDITBOX + && s_pControlFocus->GetType() != DXUT_CONTROL_IMEEDITBOX ) ) ) + { + for( int i = 0; i < m_Controls.GetSize(); i++ ) + { + CDXUTControl* pControl = m_Controls.GetAt( i ); + if( pControl->GetHotkey() == wParam ) + { + pControl->OnHotkey(); + return true; + } + } + } + + // Not yet handled, check for focus messages + if( uMsg == WM_KEYDOWN ) + { + // If keyboard input is not enabled, this message should be ignored + if( !m_bKeyboardInput ) + return false; + + switch( wParam ) + { + case VK_RIGHT: + case VK_DOWN: + if( s_pControlFocus != NULL ) + { + return OnCycleFocus( true ); + } + break; + + case VK_LEFT: + case VK_UP: + if( s_pControlFocus != NULL ) + { + return OnCycleFocus( false ); + } + break; + + case VK_TAB: + { + bool bShiftDown = ( ( GetKeyState( VK_SHIFT ) & 0x8000 ) != 0 ); + return OnCycleFocus( !bShiftDown ); + } + } + } + + break; + } + + + // Mouse messages + case WM_MOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_XBUTTONDOWN: + case WM_XBUTTONUP: + case WM_LBUTTONDBLCLK: + case WM_MBUTTONDBLCLK: + case WM_RBUTTONDBLCLK: + case WM_XBUTTONDBLCLK: + case WM_MOUSEWHEEL: + { + // If not accepting mouse input, return false to indicate the message should still + // be handled by the application (usually to move the camera). + if( !m_bMouseInput ) + return false; + + POINT mousePoint = + { + short( LOWORD( lParam ) ), short( HIWORD( lParam ) ) + }; + mousePoint.x -= m_x; + mousePoint.y -= m_y; + + // If caption is enabled, offset the Y coordinate by the negative of its height. + if( m_bCaption ) + mousePoint.y -= m_nCaptionHeight; + + // If a control is in focus, it belongs to this dialog, and it's enabled, then give + // it the first chance at handling the message. + if( s_pControlFocus && + s_pControlFocus->m_pDialog == this && + s_pControlFocus->GetEnabled() ) + { + if( s_pControlFocus->HandleMouse( uMsg, mousePoint, wParam, lParam ) ) + return true; + } + + // Not yet handled, see if the mouse is over any controls + CDXUTControl* pControl = GetControlAtPoint( mousePoint ); + if( pControl != NULL && pControl->GetEnabled() ) + { + bHandled = pControl->HandleMouse( uMsg, mousePoint, wParam, lParam ); + if( bHandled ) + return true; + } + else + { + // Mouse not over any controls in this dialog, if there was a control + // which had focus it just lost it + if( uMsg == WM_LBUTTONDOWN && + s_pControlFocus && + s_pControlFocus->m_pDialog == this ) + { + s_pControlFocus->OnFocusOut(); + s_pControlFocus = NULL; + } + } + + // Still not handled, hand this off to the dialog. Return false to indicate the + // message should still be handled by the application (usually to move the camera). + switch( uMsg ) + { + case WM_MOUSEMOVE: + OnMouseMove( mousePoint ); + return false; + } + + break; + } + + case WM_CAPTURECHANGED: + { + // The application has lost mouse capture. + // The dialog object may not have received + // a WM_MOUSEUP when capture changed. Reset + // m_bDrag so that the dialog does not mistakenly + // think the mouse button is still held down. + if( ( HWND )lParam != hWnd ) + m_bDrag = false; + } + } + + return false; +} + +//-------------------------------------------------------------------------------------- +CDXUTControl* CDXUTDialog::GetControlAtPoint( POINT pt ) +{ + // Search through all child controls for the first one which + // contains the mouse point + for( int i = 0; i < m_Controls.GetSize(); i++ ) + { + CDXUTControl* pControl = m_Controls.GetAt( i ); + + if( pControl == NULL ) + { + continue; + } + + // We only return the current control if it is visible + // and enabled. Because GetControlAtPoint() is used to do mouse + // hittest, it makes sense to perform this filtering. + if( pControl->ContainsPoint( pt ) && pControl->GetEnabled() && pControl->GetVisible() ) + { + return pControl; + } + } + + return NULL; +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTDialog::GetControlEnabled( int ID ) +{ + CDXUTControl* pControl = GetControl( ID ); + if( pControl == NULL ) + return false; + + return pControl->GetEnabled(); +} + + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::SetControlEnabled( int ID, bool bEnabled ) +{ + CDXUTControl* pControl = GetControl( ID ); + if( pControl == NULL ) + return; + + pControl->SetEnabled( bEnabled ); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::OnMouseUp( POINT pt ) +{ + s_pControlPressed = NULL; + m_pControlMouseOver = NULL; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::OnMouseMove( POINT pt ) +{ + // Figure out which control the mouse is over now + CDXUTControl* pControl = GetControlAtPoint( pt ); + + // If the mouse is still over the same control, nothing needs to be done + if( pControl == m_pControlMouseOver ) + return; + + // Handle mouse leaving the old control + if( m_pControlMouseOver ) + m_pControlMouseOver->OnMouseLeave(); + + // Handle mouse entering the new control + m_pControlMouseOver = pControl; + if( pControl != NULL ) + m_pControlMouseOver->OnMouseEnter(); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::SetDefaultElement( UINT nControlType, UINT iElement, CDXUTElement* pElement ) +{ + // If this Element type already exist in the list, simply update the stored Element + for( int i = 0; i < m_DefaultElements.GetSize(); i++ ) + { + DXUTElementHolder* pElementHolder = m_DefaultElements.GetAt( i ); + + if( pElementHolder->nControlType == nControlType && + pElementHolder->iElement == iElement ) + { + pElementHolder->Element = *pElement; + return S_OK; + } + } + + // Otherwise, add a new entry + DXUTElementHolder* pNewHolder; + pNewHolder = new DXUTElementHolder; + if( pNewHolder == NULL ) + return E_OUTOFMEMORY; + + pNewHolder->nControlType = nControlType; + pNewHolder->iElement = iElement; + pNewHolder->Element = *pElement; + + HRESULT hr = m_DefaultElements.Add( pNewHolder ); + if( FAILED( hr ) ) + { + delete pNewHolder; + } + return hr; +} + + +//-------------------------------------------------------------------------------------- +CDXUTElement* CDXUTDialog::GetDefaultElement( UINT nControlType, UINT iElement ) +{ + for( int i = 0; i < m_DefaultElements.GetSize(); i++ ) + { + DXUTElementHolder* pElementHolder = m_DefaultElements.GetAt( i ); + + if( pElementHolder->nControlType == nControlType && + pElementHolder->iElement == iElement ) + { + return &pElementHolder->Element; + } + } + + return NULL; +} + + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::AddStatic( int ID, LPCWSTR strText, int x, int y, int width, int height, bool bIsDefault, + CDXUTStatic** ppCreated ) +{ + HRESULT hr = S_OK; + + CDXUTStatic* pStatic = new CDXUTStatic( this ); + + if( ppCreated != NULL ) + *ppCreated = pStatic; + + if( pStatic == NULL ) + return E_OUTOFMEMORY; + + hr = AddControl( pStatic ); + if( FAILED( hr ) ) + return hr; + + // Set the ID and list index + pStatic->SetID( ID ); + pStatic->SetText( strText ); + pStatic->SetLocation( x, y ); + pStatic->SetSize( width, height ); + pStatic->m_bIsDefault = bIsDefault; + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::AddButton( int ID, LPCWSTR strText, int x, int y, int width, int height, UINT nHotkey, + bool bIsDefault, CDXUTButton** ppCreated ) +{ + HRESULT hr = S_OK; + + CDXUTButton* pButton = new CDXUTButton( this ); + + if( ppCreated != NULL ) + *ppCreated = pButton; + + if( pButton == NULL ) + return E_OUTOFMEMORY; + + hr = AddControl( pButton ); + if( FAILED( hr ) ) + return hr; + + // Set the ID and list index + pButton->SetID( ID ); + pButton->SetText( strText ); + pButton->SetLocation( x, y ); + pButton->SetSize( width, height ); + pButton->SetHotkey( nHotkey ); + pButton->m_bIsDefault = bIsDefault; + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::AddCheckBox( int ID, LPCWSTR strText, int x, int y, int width, int height, bool bChecked, + UINT nHotkey, bool bIsDefault, CDXUTCheckBox** ppCreated ) +{ + HRESULT hr = S_OK; + + CDXUTCheckBox* pCheckBox = new CDXUTCheckBox( this ); + + if( ppCreated != NULL ) + *ppCreated = pCheckBox; + + if( pCheckBox == NULL ) + return E_OUTOFMEMORY; + + hr = AddControl( pCheckBox ); + if( FAILED( hr ) ) + return hr; + + // Set the ID and list index + pCheckBox->SetID( ID ); + pCheckBox->SetText( strText ); + pCheckBox->SetLocation( x, y ); + pCheckBox->SetSize( width, height ); + pCheckBox->SetHotkey( nHotkey ); + pCheckBox->m_bIsDefault = bIsDefault; + pCheckBox->SetChecked( bChecked ); + + return S_OK; +} + + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::AddRadioButton( int ID, UINT nButtonGroup, LPCWSTR strText, int x, int y, int width, int height, + bool bChecked, UINT nHotkey, bool bIsDefault, CDXUTRadioButton** ppCreated ) +{ + HRESULT hr = S_OK; + + CDXUTRadioButton* pRadioButton = new CDXUTRadioButton( this ); + + if( ppCreated != NULL ) + *ppCreated = pRadioButton; + + if( pRadioButton == NULL ) + return E_OUTOFMEMORY; + + hr = AddControl( pRadioButton ); + if( FAILED( hr ) ) + return hr; + + // Set the ID and list index + pRadioButton->SetID( ID ); + pRadioButton->SetText( strText ); + pRadioButton->SetButtonGroup( nButtonGroup ); + pRadioButton->SetLocation( x, y ); + pRadioButton->SetSize( width, height ); + pRadioButton->SetHotkey( nHotkey ); + pRadioButton->SetChecked( bChecked ); + pRadioButton->m_bIsDefault = bIsDefault; + pRadioButton->SetChecked( bChecked ); + + return S_OK; +} + + + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::AddComboBox( int ID, int x, int y, int width, int height, UINT nHotkey, bool bIsDefault, + CDXUTComboBox** ppCreated ) +{ + HRESULT hr = S_OK; + + CDXUTComboBox* pComboBox = new CDXUTComboBox( this ); + + if( ppCreated != NULL ) + *ppCreated = pComboBox; + + if( pComboBox == NULL ) + return E_OUTOFMEMORY; + + hr = AddControl( pComboBox ); + if( FAILED( hr ) ) + return hr; + + // Set the ID and list index + pComboBox->SetID( ID ); + pComboBox->SetLocation( x, y ); + pComboBox->SetSize( width, height ); + pComboBox->SetHotkey( nHotkey ); + pComboBox->m_bIsDefault = bIsDefault; + + return S_OK; +} + + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::AddSlider( int ID, int x, int y, int width, int height, int min, int max, int value, + bool bIsDefault, CDXUTSlider** ppCreated ) +{ + HRESULT hr = S_OK; + + CDXUTSlider* pSlider = new CDXUTSlider( this ); + + if( ppCreated != NULL ) + *ppCreated = pSlider; + + if( pSlider == NULL ) + return E_OUTOFMEMORY; + + hr = AddControl( pSlider ); + if( FAILED( hr ) ) + return hr; + + // Set the ID and list index + pSlider->SetID( ID ); + pSlider->SetLocation( x, y ); + pSlider->SetSize( width, height ); + pSlider->m_bIsDefault = bIsDefault; + pSlider->SetRange( min, max ); + pSlider->SetValue( value ); + pSlider->UpdateRects(); + + return S_OK; +} + + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::AddEditBox( int ID, LPCWSTR strText, int x, int y, int width, int height, bool bIsDefault, + CDXUTEditBox** ppCreated ) +{ + HRESULT hr = S_OK; + + CDXUTEditBox* pEditBox = new CDXUTEditBox( this ); + + if( ppCreated != NULL ) + *ppCreated = pEditBox; + + if( pEditBox == NULL ) + return E_OUTOFMEMORY; + + hr = AddControl( pEditBox ); + if( FAILED( hr ) ) + return hr; + + // Set the ID and position + pEditBox->SetID( ID ); + pEditBox->SetLocation( x, y ); + pEditBox->SetSize( width, height ); + pEditBox->m_bIsDefault = bIsDefault; + + if( strText ) + pEditBox->SetText( strText ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::AddListBox( int ID, int x, int y, int width, int height, DWORD dwStyle, CDXUTListBox** ppCreated ) +{ + HRESULT hr = S_OK; + CDXUTListBox* pListBox = new CDXUTListBox( this ); + + if( ppCreated != NULL ) + *ppCreated = pListBox; + + if( pListBox == NULL ) + return E_OUTOFMEMORY; + + hr = AddControl( pListBox ); + if( FAILED( hr ) ) + return hr; + + // Set the ID and position + pListBox->SetID( ID ); + pListBox->SetLocation( x, y ); + pListBox->SetSize( width, height ); + pListBox->SetStyle( dwStyle ); + + return S_OK; +} + + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::InitControl( CDXUTControl* pControl ) +{ + HRESULT hr; + + if( pControl == NULL ) + return E_INVALIDARG; + + pControl->m_Index = m_Controls.GetSize(); + + // Look for a default Element entries + for( int i = 0; i < m_DefaultElements.GetSize(); i++ ) + { + DXUTElementHolder* pElementHolder = m_DefaultElements.GetAt( i ); + if( pElementHolder->nControlType == pControl->GetType() ) + pControl->SetElement( pElementHolder->iElement, &pElementHolder->Element ); + } + + V_RETURN( pControl->OnInit() ); + + return S_OK; +} + + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::AddControl( CDXUTControl* pControl ) +{ + HRESULT hr = S_OK; + + hr = InitControl( pControl ); + if( FAILED( hr ) ) + return DXTRACE_ERR( L"CDXUTDialog::InitControl", hr ); + + // Add to the list + hr = m_Controls.Add( pControl ); + if( FAILED( hr ) ) + { + return DXTRACE_ERR( L"CGrowableArray::Add", hr ); + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +CDXUTControl* CDXUTDialog::GetControl( int ID ) +{ + // Try to find the control with the given ID + for( int i = 0; i < m_Controls.GetSize(); i++ ) + { + CDXUTControl* pControl = m_Controls.GetAt( i ); + + if( pControl->GetID() == ID ) + { + return pControl; + } + } + + // Not found + return NULL; +} + + + +//-------------------------------------------------------------------------------------- +CDXUTControl* CDXUTDialog::GetControl( int ID, UINT nControlType ) +{ + // Try to find the control with the given ID + for( int i = 0; i < m_Controls.GetSize(); i++ ) + { + CDXUTControl* pControl = m_Controls.GetAt( i ); + + if( pControl->GetID() == ID && pControl->GetType() == nControlType ) + { + return pControl; + } + } + + // Not found + return NULL; +} + + + +//-------------------------------------------------------------------------------------- +CDXUTControl* CDXUTDialog::GetNextControl( CDXUTControl* pControl ) +{ + int index = pControl->m_Index + 1; + + CDXUTDialog* pDialog = pControl->m_pDialog; + + // Cycle through dialogs in the loop to find the next control. Note + // that if only one control exists in all looped dialogs it will + // be the returned 'next' control. + while( index >= ( int )pDialog->m_Controls.GetSize() ) + { + pDialog = pDialog->m_pNextDialog; + index = 0; + } + + return pDialog->m_Controls.GetAt( index ); +} + +//-------------------------------------------------------------------------------------- +CDXUTControl* CDXUTDialog::GetPrevControl( CDXUTControl* pControl ) +{ + int index = pControl->m_Index - 1; + + CDXUTDialog* pDialog = pControl->m_pDialog; + + // Cycle through dialogs in the loop to find the next control. Note + // that if only one control exists in all looped dialogs it will + // be the returned 'previous' control. + while( index < 0 ) + { + pDialog = pDialog->m_pPrevDialog; + if( pDialog == NULL ) + pDialog = pControl->m_pDialog; + + index = pDialog->m_Controls.GetSize() - 1; + } + + return pDialog->m_Controls.GetAt( index ); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::ClearRadioButtonGroup( UINT nButtonGroup ) +{ + // Find all radio buttons with the given group number + for( int i = 0; i < m_Controls.GetSize(); i++ ) + { + CDXUTControl* pControl = m_Controls.GetAt( i ); + + if( pControl->GetType() == DXUT_CONTROL_RADIOBUTTON ) + { + CDXUTRadioButton* pRadioButton = ( CDXUTRadioButton* )pControl; + + if( pRadioButton->GetButtonGroup() == nButtonGroup ) + pRadioButton->SetChecked( false, false ); + } + } +} + + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::ClearComboBox( int ID ) +{ + CDXUTComboBox* pComboBox = GetComboBox( ID ); + if( pComboBox == NULL ) + return; + + pComboBox->RemoveAllItems(); +} + + + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::RequestFocus( CDXUTControl* pControl ) +{ + if( s_pControlFocus == pControl ) + return; + + if( !pControl->CanHaveFocus() ) + return; + + if( s_pControlFocus ) + s_pControlFocus->OnFocusOut(); + + pControl->OnFocusIn(); + s_pControlFocus = pControl; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::DrawRect( RECT* pRect, D3DCOLOR color ) +{ + if( m_pManager->GetD3D9Device() ) + return DrawRect9( pRect, color ); + return E_FAIL; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::DrawRect9( RECT* pRect, D3DCOLOR color ) +{ + RECT rcScreen = *pRect; + OffsetRect( &rcScreen, m_x, m_y ); + + // If caption is enabled, offset the Y position by its height. + if( m_bCaption ) + OffsetRect( &rcScreen, 0, m_nCaptionHeight ); + + DXUT_SCREEN_VERTEX vertices[4] = + { + ( float )rcScreen.left - 0.5f, ( float )rcScreen.top - 0.5f, 0.5f, 1.0f, color, 0, 0, + ( float )rcScreen.right - 0.5f, ( float )rcScreen.top - 0.5f, 0.5f, 1.0f, color, 0, 0, + ( float )rcScreen.right - 0.5f, ( float )rcScreen.bottom - 0.5f, 0.5f, 1.0f, color, 0, 0, + ( float )rcScreen.left - 0.5f, ( float )rcScreen.bottom - 0.5f, 0.5f, 1.0f, color, 0, 0, + }; + + IDirect3DDevice9* pd3dDevice = m_pManager->GetD3D9Device(); + + // Since we're doing our own drawing here we need to flush the sprites + m_pManager->m_pSprite->Flush(); + IDirect3DVertexDeclaration9* pDecl = NULL; + pd3dDevice->GetVertexDeclaration( &pDecl ); // Preserve the sprite's current vertex decl + pd3dDevice->SetFVF( DXUT_SCREEN_VERTEX::FVF ); + + pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 ); + pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 ); + + pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, vertices, sizeof( DXUT_SCREEN_VERTEX ) ); + + pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); + pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); + + // Restore the vertex decl + pd3dDevice->SetVertexDeclaration( pDecl ); + pDecl->Release(); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::DrawPolyLine( POINT* apPoints, UINT nNumPoints, D3DCOLOR color ) +{ + DXUT_SCREEN_VERTEX* vertices = new DXUT_SCREEN_VERTEX[ nNumPoints ]; + if( vertices == NULL ) + return E_OUTOFMEMORY; + + DXUT_SCREEN_VERTEX* pVertex = vertices; + POINT* pt = apPoints; + for( UINT i = 0; i < nNumPoints; i++ ) + { + pVertex->x = m_x + ( float )pt->x; + pVertex->y = m_y + ( float )pt->y; + pVertex->z = 0.5f; + pVertex->h = 1.0f; + pVertex->color = color; + pVertex->tu = 0.0f; + pVertex->tv = 0.0f; + + pVertex++; + pt++; + } + + IDirect3DDevice9* pd3dDevice = m_pManager->GetD3D9Device(); + + // Since we're doing our own drawing here we need to flush the sprites + m_pManager->m_pSprite->Flush(); + IDirect3DVertexDeclaration9* pDecl = NULL; + pd3dDevice->GetVertexDeclaration( &pDecl ); // Preserve the sprite's current vertex decl + pd3dDevice->SetFVF( DXUT_SCREEN_VERTEX::FVF ); + + pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 ); + pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 ); + + pd3dDevice->DrawPrimitiveUP( D3DPT_LINESTRIP, nNumPoints - 1, vertices, sizeof( DXUT_SCREEN_VERTEX ) ); + + pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); + pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); + + // Restore the vertex decl + pd3dDevice->SetVertexDeclaration( pDecl ); + pDecl->Release(); + + SAFE_DELETE_ARRAY( vertices ); + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::DrawSprite( CDXUTElement* pElement, RECT* prcDest, float fDepth ) +{ + if( m_pManager->GetD3D9Device() ) + return DrawSprite9( pElement, prcDest ); + else + return DrawSprite11( pElement, prcDest, fDepth ); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::DrawSprite9( CDXUTElement* pElement, RECT* prcDest ) +{ + // No need to draw fully transparent layers + if( pElement->TextureColor.Current.a == 0 ) + return S_OK; + + RECT rcTexture = pElement->rcTexture; + + RECT rcScreen = *prcDest; + OffsetRect( &rcScreen, m_x, m_y ); + + // If caption is enabled, offset the Y position by its height. + if( m_bCaption ) + OffsetRect( &rcScreen, 0, m_nCaptionHeight ); + + DXUTTextureNode* pTextureNode = GetTexture( pElement->iTexture ); + if( pTextureNode == NULL ) + return E_FAIL; + + float fScaleX = ( float )RectWidth( rcScreen ) / RectWidth( rcTexture ); + float fScaleY = ( float )RectHeight( rcScreen ) / RectHeight( rcTexture ); + + D3DXMATRIXA16 matTransform; + D3DXMatrixScaling( &matTransform, fScaleX, fScaleY, 1.0f ); + + m_pManager->m_pSprite->SetTransform( &matTransform ); + + D3DXVECTOR3 vPos( ( float )rcScreen.left, ( float )rcScreen.top, 0.0f ); + + vPos.x /= fScaleX; + vPos.y /= fScaleY; + + return m_pManager->m_pSprite->Draw( pTextureNode->pTexture9, &rcTexture, NULL, &vPos, + pElement->TextureColor.Current ); +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::DrawSprite11( CDXUTElement* pElement, RECT* prcDest, float fDepth ) +{ + // No need to draw fully transparent layers + if( pElement->TextureColor.Current.a == 0 ) + return S_OK; + + RECT rcTexture = pElement->rcTexture; + + RECT rcScreen = *prcDest; + OffsetRect( &rcScreen, m_x, m_y ); + + // If caption is enabled, offset the Y position by its height. + if( m_bCaption ) + OffsetRect( &rcScreen, 0, m_nCaptionHeight ); + + DXUTTextureNode* pTextureNode = GetTexture( pElement->iTexture ); + if( pTextureNode == NULL ) + return E_FAIL; + + float fBBWidth = ( float )m_pManager->m_nBackBufferWidth; + float fBBHeight = ( float )m_pManager->m_nBackBufferHeight; + float fTexWidth = ( float )pTextureNode->dwWidth; + float fTexHeight = ( float )pTextureNode->dwHeight; + + float fRectLeft = rcScreen.left / fBBWidth; + float fRectTop = 1.0f - rcScreen.top / fBBHeight; + float fRectRight = rcScreen.right / fBBWidth; + float fRectBottom = 1.0f - rcScreen.bottom / fBBHeight; + + fRectLeft = fRectLeft * 2.0f - 1.0f; + fRectTop = fRectTop * 2.0f - 1.0f; + fRectRight = fRectRight * 2.0f - 1.0f; + fRectBottom = fRectBottom * 2.0f - 1.0f; + + float fTexLeft = rcTexture.left / fTexWidth; + float fTexTop = rcTexture.top / fTexHeight; + float fTexRight = rcTexture.right / fTexWidth; + float fTexBottom = rcTexture.bottom / fTexHeight; + + // Add 6 sprite vertices + DXUTSpriteVertex SpriteVertex; + + // tri1 + SpriteVertex.vPos = D3DXVECTOR3( fRectLeft, fRectTop, fDepth ); + SpriteVertex.vTex = D3DXVECTOR2( fTexLeft, fTexTop ); + SpriteVertex.vColor = pElement->TextureColor.Current; + m_pManager->m_SpriteVertices.Add( SpriteVertex ); + + SpriteVertex.vPos = D3DXVECTOR3( fRectRight, fRectTop, fDepth ); + SpriteVertex.vTex = D3DXVECTOR2( fTexRight, fTexTop ); + SpriteVertex.vColor = pElement->TextureColor.Current; + m_pManager->m_SpriteVertices.Add( SpriteVertex ); + + SpriteVertex.vPos = D3DXVECTOR3( fRectLeft, fRectBottom, fDepth ); + SpriteVertex.vTex = D3DXVECTOR2( fTexLeft, fTexBottom ); + SpriteVertex.vColor = pElement->TextureColor.Current; + m_pManager->m_SpriteVertices.Add( SpriteVertex ); + + // tri2 + SpriteVertex.vPos = D3DXVECTOR3( fRectRight, fRectTop, fDepth ); + SpriteVertex.vTex = D3DXVECTOR2( fTexRight, fTexTop ); + SpriteVertex.vColor = pElement->TextureColor.Current; + m_pManager->m_SpriteVertices.Add( SpriteVertex ); + + SpriteVertex.vPos = D3DXVECTOR3( fRectRight, fRectBottom, fDepth ); + SpriteVertex.vTex = D3DXVECTOR2( fTexRight, fTexBottom ); + SpriteVertex.vColor = pElement->TextureColor.Current; + m_pManager->m_SpriteVertices.Add( SpriteVertex ); + + SpriteVertex.vPos = D3DXVECTOR3( fRectLeft, fRectBottom, fDepth ); + SpriteVertex.vTex = D3DXVECTOR2( fTexLeft, fTexBottom ); + SpriteVertex.vColor = pElement->TextureColor.Current; + m_pManager->m_SpriteVertices.Add( SpriteVertex ); + + // TODO: Why are we drawing the sprite every time? This is very inefficient, but the sprite workaround doesn't have support for sorting now, so we have to + // draw a sprite every time to keep the order correct between sprites and text. + m_pManager->EndSprites11( DXUTGetD3D11Device(), DXUTGetD3D11DeviceContext() ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::CalcTextRect( LPCWSTR strText, CDXUTElement* pElement, RECT* prcDest, int nCount ) +{ + HRESULT hr = S_OK; + + DXUTFontNode* pFontNode = GetFont( pElement->iFont ); + if( pFontNode == NULL ) + return E_FAIL; + + DWORD dwTextFormat = pElement->dwTextFormat | DT_CALCRECT; + // Since we are only computing the rectangle, we don't need a sprite. + if( pFontNode->pFont9 ) + { + hr = pFontNode->pFont9->DrawText( NULL, strText, nCount, prcDest, dwTextFormat, pElement->FontColor.Current ); + if( FAILED( hr ) ) + return hr; + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::DrawText( LPCWSTR strText, CDXUTElement* pElement, RECT* prcDest, bool bShadow, int nCount, bool bCenter ) +{ + if( m_pManager->GetD3D9Device() ) + return DrawText9( strText, pElement, prcDest, bShadow, nCount ); + else + return DrawText11( m_pManager->GetD3D11Device(), m_pManager->GetD3D11DeviceContext(), strText, pElement, prcDest, bShadow, nCount, bCenter ); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::DrawText9( LPCWSTR strText, CDXUTElement* pElement, RECT* prcDest, bool bShadow, int nCount ) +{ + HRESULT hr = S_OK; + + // No need to draw fully transparent layers + if( pElement->FontColor.Current.a == 0 ) + return S_OK; + + RECT rcScreen = *prcDest; + OffsetRect( &rcScreen, m_x, m_y ); + + // If caption is enabled, offset the Y position by its height. + if( m_bCaption ) + OffsetRect( &rcScreen, 0, m_nCaptionHeight ); + + D3DXMATRIX matTransform; + D3DXMatrixIdentity( &matTransform ); + m_pManager->m_pSprite->SetTransform( &matTransform ); + + DXUTFontNode* pFontNode = GetFont( pElement->iFont ); + + if( bShadow ) + { + RECT rcShadow = rcScreen; + OffsetRect( &rcShadow, 1, 1 ); + hr = pFontNode->pFont9->DrawText( m_pManager->m_pSprite, strText, nCount, &rcShadow, pElement->dwTextFormat, + D3DCOLOR_ARGB( DWORD( pElement->FontColor.Current.a * 255 ), 0, 0, 0 ) ); + if( FAILED( hr ) ) + return hr; + } + + hr = pFontNode->pFont9->DrawText( m_pManager->m_pSprite, strText, nCount, &rcScreen, pElement->dwTextFormat, + pElement->FontColor.Current ); + if( FAILED( hr ) ) + return hr; + + return S_OK; +} + +ID3D11Buffer* g_pFontBuffer11 = NULL; +UINT g_FontBufferBytes11 = 0; +CGrowableArray g_FontVertices; +ID3D11ShaderResourceView* g_pFont11 = NULL; +ID3D11InputLayout* g_pInputLayout11 = NULL; +HRESULT InitFont11( ID3D11Device* pd3d11Device, ID3D11InputLayout* pInputLayout ) +{ + HRESULT hr = S_OK; + WCHAR str[MAX_PATH]; + V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"UI\\Font.dds" ) ); + + if (pd3d11Device->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0 ) { + + D3DX11_IMAGE_INFO dii; + D3DX11GetImageInfoFromFile( str, NULL, &dii, NULL ); + + D3DX11_IMAGE_LOAD_INFO dili; + dili.BindFlags = D3DX11_DEFAULT; + dili.CpuAccessFlags = D3DX11_DEFAULT; + dili.Depth = D3DX11_DEFAULT; + dili.Filter = D3DX11_DEFAULT; + dili.FirstMipLevel = 0; + dili.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + dili.Height = D3DX11_DEFAULT; + dili.MipFilter = D3DX11_DEFAULT; + dili.MipLevels = 1; + dili.MiscFlags = D3DX11_DEFAULT; + dili.pSrcInfo = &dii; + dili.Usage = D3D11_USAGE_DEFAULT ; + dili.Width = D3DX11_DEFAULT; + + V_RETURN( D3DX11CreateShaderResourceViewFromFile( pd3d11Device, str, &dili, NULL, &g_pFont11, &hr) ); + } else { + V_RETURN( D3DX11CreateShaderResourceViewFromFile( pd3d11Device, str, NULL, NULL, &g_pFont11, &hr) ); + + } + + + g_pInputLayout11 = pInputLayout; + return hr; +} + +void EndFont11() +{ + SAFE_RELEASE( g_pFontBuffer11 ); + g_FontBufferBytes11 = 0; + SAFE_RELEASE( g_pFont11 ); +} + +void BeginText11() +{ + g_FontVertices.Reset(); +} + +void DrawText11DXUT( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3d11DeviceContext, + LPCWSTR strText, RECT rcScreen, D3DXCOLOR vFontColor, + float fBBWidth, float fBBHeight, bool bCenter ) +{ + float fCharTexSizeX = 0.010526315f; + //float fGlyphSizeX = 14.0f / fBBWidth; + //float fGlyphSizeY = 32.0f / fBBHeight; + float fGlyphSizeX = 15.0f / fBBWidth; + float fGlyphSizeY = 42.0f / fBBHeight; + + + float fRectLeft = rcScreen.left / fBBWidth; + float fRectTop = 1.0f - rcScreen.top / fBBHeight; + + fRectLeft = fRectLeft * 2.0f - 1.0f; + fRectTop = fRectTop * 2.0f - 1.0f; + + int NumChars = (int)wcslen( strText ); + if (bCenter) { + float fRectRight = rcScreen.right / fBBWidth; + fRectRight = fRectRight * 2.0f - 1.0f; + float fRectBottom = 1.0f - rcScreen.bottom / fBBHeight; + fRectBottom = fRectBottom * 2.0f - 1.0f; + float fcenterx = ((fRectRight - fRectLeft) - (float)NumChars*fGlyphSizeX) *0.5f; + float fcentery = ((fRectTop - fRectBottom) - (float)1*fGlyphSizeY) *0.5f; + fRectLeft += fcenterx ; + fRectTop -= fcentery; + } + float fOriginalLeft = fRectLeft; + float fTexTop = 0.0f; + float fTexBottom = 1.0f; + + float fDepth = 0.5f; + for( int i=0; i 126 ) + { + continue; + } + + // Add 6 sprite vertices + DXUTSpriteVertex SpriteVertex; + float fRectRight = fRectLeft + fGlyphSizeX; + float fRectBottom = fRectTop - fGlyphSizeY; + float fTexLeft = ( strText[i] - 32 ) * fCharTexSizeX; + float fTexRight = fTexLeft + fCharTexSizeX; + + // tri1 + SpriteVertex.vPos = D3DXVECTOR3( fRectLeft, fRectTop, fDepth ); + SpriteVertex.vTex = D3DXVECTOR2( fTexLeft, fTexTop ); + SpriteVertex.vColor = vFontColor; + g_FontVertices.Add( SpriteVertex ); + + SpriteVertex.vPos = D3DXVECTOR3( fRectRight, fRectTop, fDepth ); + SpriteVertex.vTex = D3DXVECTOR2( fTexRight, fTexTop ); + SpriteVertex.vColor = vFontColor; + g_FontVertices.Add( SpriteVertex ); + + SpriteVertex.vPos = D3DXVECTOR3( fRectLeft, fRectBottom, fDepth ); + SpriteVertex.vTex = D3DXVECTOR2( fTexLeft, fTexBottom ); + SpriteVertex.vColor = vFontColor; + g_FontVertices.Add( SpriteVertex ); + + // tri2 + SpriteVertex.vPos = D3DXVECTOR3( fRectRight, fRectTop, fDepth ); + SpriteVertex.vTex = D3DXVECTOR2( fTexRight, fTexTop ); + SpriteVertex.vColor = vFontColor; + g_FontVertices.Add( SpriteVertex ); + + SpriteVertex.vPos = D3DXVECTOR3( fRectRight, fRectBottom, fDepth ); + SpriteVertex.vTex = D3DXVECTOR2( fTexRight, fTexBottom ); + SpriteVertex.vColor = vFontColor; + g_FontVertices.Add( SpriteVertex ); + + SpriteVertex.vPos = D3DXVECTOR3( fRectLeft, fRectBottom, fDepth ); + SpriteVertex.vTex = D3DXVECTOR2( fTexLeft, fTexBottom ); + SpriteVertex.vColor = vFontColor; + g_FontVertices.Add( SpriteVertex ); + + fRectLeft += fGlyphSizeX; + + } + + // TODO: We have to end text after every line so that rendering order between sprites and fonts is preserved + EndText11( pd3dDevice, pd3d11DeviceContext ); +} + +void EndText11( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3d11DeviceContext ) +{ + + // ensure our buffer size can hold our sprites + UINT FontDataBytes = g_FontVertices.GetSize() * sizeof( DXUTSpriteVertex ); + if( g_FontBufferBytes11 < FontDataBytes ) + { + SAFE_RELEASE( g_pFontBuffer11 ); + g_FontBufferBytes11 = FontDataBytes; + + D3D11_BUFFER_DESC BufferDesc; + BufferDesc.ByteWidth = g_FontBufferBytes11; + BufferDesc.Usage = D3D11_USAGE_DYNAMIC; + BufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + BufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + BufferDesc.MiscFlags = 0; + + pd3dDevice->CreateBuffer( &BufferDesc, NULL, &g_pFontBuffer11 ); + } + + // Copy the sprites over + D3D11_BOX destRegion; + destRegion.left = 0; + destRegion.right = FontDataBytes; + destRegion.top = 0; + destRegion.bottom = 1; + destRegion.front = 0; + destRegion.back = 1; + D3D11_MAPPED_SUBRESOURCE MappedResource; + if ( S_OK == pd3d11DeviceContext->Map( g_pFontBuffer11, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) ) { + CopyMemory( MappedResource.pData, (void*)g_FontVertices.GetData(), FontDataBytes ); + pd3d11DeviceContext->Unmap(g_pFontBuffer11, 0); + } + + ID3D11ShaderResourceView* pOldTexture = NULL; + pd3d11DeviceContext->PSGetShaderResources( 0, 1, &pOldTexture ); + pd3d11DeviceContext->PSSetShaderResources( 0, 1, &g_pFont11 ); + + // Draw + UINT Stride = sizeof( DXUTSpriteVertex ); + UINT Offset = 0; + pd3d11DeviceContext->IASetVertexBuffers( 0, 1, &g_pFontBuffer11, &Stride, &Offset ); + pd3d11DeviceContext->IASetInputLayout( g_pInputLayout11 ); + pd3d11DeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); + pd3d11DeviceContext->Draw( g_FontVertices.GetSize(), 0 ); + + pd3d11DeviceContext->PSSetShaderResources( 0, 1, &pOldTexture ); + SAFE_RELEASE( pOldTexture ); + + g_FontVertices.Reset(); +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialog::DrawText11( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3d11DeviceContext, + LPCWSTR strText, CDXUTElement* pElement, RECT* prcDest, bool bShadow, int nCount, bool bCenter ) +{ + //HRESULT hr = S_OK; + + // No need to draw fully transparent layers + if( pElement->FontColor.Current.a == 0 ) + return S_OK; + + RECT rcScreen = *prcDest; + OffsetRect( &rcScreen, m_x, m_y); + + // If caption is enabled, offset the Y position by its height. + if( m_bCaption ) + OffsetRect( &rcScreen, 0, m_nCaptionHeight ); + + float fBBWidth = ( float )m_pManager->m_nBackBufferWidth; + float fBBHeight = ( float )m_pManager->m_nBackBufferHeight; + + if( bShadow ) + { + RECT rcShadow = rcScreen; + OffsetRect( &rcShadow, 1, 1 ); + + D3DXCOLOR vShadowColor( 0,0,0, 1.0f ); + DrawText11DXUT( pd3dDevice, pd3d11DeviceContext, + strText, rcShadow, vShadowColor, + fBBWidth, fBBHeight, bCenter ); + + } + + D3DXCOLOR vFontColor( pElement->FontColor.Current.r, pElement->FontColor.Current.g, pElement->FontColor.Current.b, 1.0f ); + DrawText11DXUT( pd3dDevice, pd3d11DeviceContext, + strText, rcScreen, vFontColor, + fBBWidth, fBBHeight, bCenter ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::SetBackgroundColors( D3DCOLOR colorTopLeft, D3DCOLOR colorTopRight, D3DCOLOR colorBottomLeft, + D3DCOLOR colorBottomRight ) +{ + m_colorTopLeft = colorTopLeft; + m_colorTopRight = colorTopRight; + m_colorBottomLeft = colorBottomLeft; + m_colorBottomRight = colorBottomRight; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::SetNextDialog( CDXUTDialog* pNextDialog ) +{ + if( pNextDialog == NULL ) + pNextDialog = this; + + m_pNextDialog = pNextDialog; + if( pNextDialog ) + m_pNextDialog->m_pPrevDialog = this; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::ClearFocus() +{ + if( s_pControlFocus ) + { + s_pControlFocus->OnFocusOut(); + s_pControlFocus = NULL; + } + + ReleaseCapture(); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::FocusDefaultControl() +{ + // Check for default control in this dialog + for( int i = 0; i < m_Controls.GetSize(); i++ ) + { + CDXUTControl* pControl = m_Controls.GetAt( i ); + if( pControl->m_bIsDefault ) + { + // Remove focus from the current control + ClearFocus(); + + // Give focus to the default control + s_pControlFocus = pControl; + s_pControlFocus->OnFocusIn(); + return; + } + } +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTDialog::OnCycleFocus( bool bForward ) +{ + CDXUTControl* pControl = NULL; + CDXUTDialog* pDialog = NULL; // pDialog and pLastDialog are used to track wrapping of + CDXUTDialog* pLastDialog; // focus from first control to last or vice versa. + + if( s_pControlFocus == NULL ) + { + // If s_pControlFocus is NULL, we focus the first control of first dialog in + // the case that bForward is true, and focus the last control of last dialog when + // bForward is false. + // + if( bForward ) + { + // Search for the first control from the start of the dialog + // array. + for( int d = 0; d < m_pManager->m_Dialogs.GetSize(); ++d ) + { + pDialog = pLastDialog = m_pManager->m_Dialogs.GetAt( d ); + if( pDialog && pDialog->m_Controls.GetSize() > 0 ) + { + pControl = pDialog->m_Controls.GetAt( 0 ); + break; + } + } + + if( !pDialog || !pControl ) + { + // No dialog has been registered yet or no controls have been + // added to the dialogs. Cannot proceed. + return true; + } + } + else + { + // Search for the first control from the end of the dialog + // array. + for( int d = m_pManager->m_Dialogs.GetSize() - 1; d >= 0; --d ) + { + pDialog = pLastDialog = m_pManager->m_Dialogs.GetAt( d ); + if( pDialog && pDialog->m_Controls.GetSize() > 0 ) + { + pControl = pDialog->m_Controls.GetAt( pDialog->m_Controls.GetSize() - 1 ); + break; + } + } + + if( !pDialog || !pControl ) + { + // No dialog has been registered yet or no controls have been + // added to the dialogs. Cannot proceed. + return true; + } + } + } + else if( s_pControlFocus->m_pDialog != this ) + { + // If a control belonging to another dialog has focus, let that other + // dialog handle this event by returning false. + // + return false; + } + else + { + // Focused control belongs to this dialog. Cycle to the + // next/previous control. + pLastDialog = s_pControlFocus->m_pDialog; + pControl = ( bForward ) ? GetNextControl( s_pControlFocus ) : GetPrevControl( s_pControlFocus ); + pDialog = pControl->m_pDialog; + } + + for( int i = 0; i < 0xffff; i++ ) + { + // If we just wrapped from last control to first or vice versa, + // set the focused control to NULL. This state, where no control + // has focus, allows the camera to work. + int nLastDialogIndex = m_pManager->m_Dialogs.IndexOf( pLastDialog ); + int nDialogIndex = m_pManager->m_Dialogs.IndexOf( pDialog ); + if( ( !bForward && nLastDialogIndex < nDialogIndex ) || + ( bForward && nDialogIndex < nLastDialogIndex ) ) + { + if( s_pControlFocus ) + s_pControlFocus->OnFocusOut(); + s_pControlFocus = NULL; + return true; + } + + // If we've gone in a full circle then focus doesn't change + if( pControl == s_pControlFocus ) + return true; + + // If the dialog accepts keybord input and the control can have focus then + // move focus + if( pControl->m_pDialog->m_bKeyboardInput && pControl->CanHaveFocus() ) + { + if( s_pControlFocus ) + s_pControlFocus->OnFocusOut(); + s_pControlFocus = pControl; + s_pControlFocus->OnFocusIn(); + return true; + } + + pLastDialog = pDialog; + pControl = ( bForward ) ? GetNextControl( pControl ) : GetPrevControl( pControl ); + pDialog = pControl->m_pDialog; + } + + // If we reached this point, the chain of dialogs didn't form a complete loop + DXTRACE_ERR( L"CDXUTDialog: Multiple dialogs are improperly chained together", E_FAIL ); + return false; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialogResourceManager::CreateFont9( UINT iFont ) +{ + HRESULT hr = S_OK; + + DXUTFontNode* pFontNode = m_FontCache.GetAt( iFont ); + + SAFE_RELEASE( pFontNode->pFont9 ); + + V_RETURN( D3DXCreateFont( m_pd3d9Device, pFontNode->nHeight, 0, pFontNode->nWeight, 1, FALSE, DEFAULT_CHARSET, + OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, + pFontNode->strFace, &pFontNode->pFont9 ) ); + + return S_OK; +} + + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialogResourceManager::CreateFont11( UINT iFont ) +{ + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialogResourceManager::CreateTexture9( UINT iTexture ) +{ + HRESULT hr = S_OK; + + DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( iTexture ); + + + D3DXIMAGE_INFO info; + + if( !pTextureNode->bFileSource ) + { + if( pTextureNode->nResourceID == 0xFFFF && pTextureNode->hResourceModule == ( HMODULE )0xFFFF ) + { + hr = DXUTCreateGUITextureFromInternalArray9( m_pd3d9Device, &pTextureNode->pTexture9, &info ); + if( FAILED( hr ) ) + return DXTRACE_ERR( L"D3DXCreateTextureFromFileInMemoryEx", hr ); + } + else + { + LPCWSTR pID = pTextureNode->nResourceID ? ( LPCWSTR )( size_t )pTextureNode->nResourceID : + pTextureNode->strFilename; + + // Create texture from resource + hr = D3DXCreateTextureFromResourceEx( m_pd3d9Device, pTextureNode->hResourceModule, pID, D3DX_DEFAULT, + D3DX_DEFAULT, + 1, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, + D3DX_DEFAULT, D3DX_DEFAULT, 0, + &info, NULL, &pTextureNode->pTexture9 ); + if( FAILED( hr ) ) + return DXTRACE_ERR( L"D3DXCreateTextureFromResourceEx", hr ); + } + } + else + { + // Make sure there's a texture to create + if( pTextureNode->strFilename[0] == 0 ) + return S_OK; + + // Create texture from file + hr = D3DXCreateTextureFromFileEx( m_pd3d9Device, pTextureNode->strFilename, D3DX_DEFAULT, D3DX_DEFAULT, + 1, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, + D3DX_DEFAULT, D3DX_DEFAULT, 0, + &info, NULL, &pTextureNode->pTexture9 ); + if( FAILED( hr ) ) + { + return DXTRACE_ERR( L"D3DXCreateTextureFromFileEx", hr ); + } + } + + // Store dimensions + pTextureNode->dwWidth = info.Width; + pTextureNode->dwHeight = info.Height; + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTDialogResourceManager::CreateTexture11( UINT iTexture ) +{ + HRESULT hr = S_OK; + + DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( iTexture ); + + if( !pTextureNode->bFileSource ) + { + if( pTextureNode->nResourceID == 0xFFFF && pTextureNode->hResourceModule == ( HMODULE )0xFFFF ) + { + hr = DXUTCreateGUITextureFromInternalArray11( m_pd3d11Device, &pTextureNode->pTexture11, NULL ); + if( FAILED( hr ) ) + return DXTRACE_ERR( L"D3DX10CreateResourceFromFileInMemory", hr ); + } + //else + //{ + // LPCWSTR pID = pTextureNode->nResourceID ? ( LPCWSTR )( size_t )pTextureNode->nResourceID : + // pTextureNode->strFilename; + + // D3DX10_IMAGE_INFO SrcInfo; + // D3DX10GetImageInfoFromResource( NULL, pID, NULL, &SrcInfo, NULL ); + + // // Create texture from resource + // ID3D10Resource* pRes; + // D3DX10_IMAGE_LOAD_INFO loadInfo; + // loadInfo.Width = D3DX10_DEFAULT; + // loadInfo.Height = D3DX10_DEFAULT; + // loadInfo.Depth = D3DX10_DEFAULT; + // loadInfo.FirstMipLevel = 0; + // loadInfo.MipLevels = 1; + // loadInfo.Usage = D3D10_USAGE_DEFAULT; + // loadInfo.BindFlags = D3D10_BIND_SHADER_RESOURCE; + // loadInfo.CpuAccessFlags = 0; + // loadInfo.MiscFlags = 0; + // loadInfo.Format = MAKE_TYPELESS( SrcInfo.Format ); + // loadInfo.Filter = D3DX10_FILTER_NONE; + // loadInfo.MipFilter = D3DX10_FILTER_NONE; + // loadInfo.pSrcInfo = &SrcInfo; + + // hr = D3DX10CreateTextureFromResource( m_pd3d10Device, pTextureNode->hResourceModule, pID, &loadInfo, + // NULL, &pRes, NULL ); + // if( FAILED( hr ) ) + // return DXTRACE_ERR( L"D3DX10CreateResourceFromResource", hr ); + // hr = pRes->QueryInterface( __uuidof( ID3D10Texture2D ), ( LPVOID* )&pTextureNode->pTexture10 ); + // SAFE_RELEASE( pRes ); + // if( FAILED( hr ) ) + // return hr; + //} + } + else + { + // + //// Make sure there's a texture to create + //if( pTextureNode->strFilename[0] == 0 ) + // return S_OK; + + //D3DX10_IMAGE_INFO SrcInfo; + //D3DX10GetImageInfoFromFile( pTextureNode->strFilename, NULL, &SrcInfo, NULL ); + + //// Create texture from file + //ID3D10Resource* pRes; + //D3DX10_IMAGE_LOAD_INFO loadInfo; + //loadInfo.Width = D3DX10_DEFAULT; + //loadInfo.Height = D3DX10_DEFAULT; + //loadInfo.Depth = D3DX10_DEFAULT; + //loadInfo.FirstMipLevel = 0; + //loadInfo.MipLevels = 1; + //loadInfo.Usage = D3D10_USAGE_DEFAULT; + //loadInfo.BindFlags = D3D10_BIND_SHADER_RESOURCE; + //loadInfo.CpuAccessFlags = 0; + //loadInfo.MiscFlags = 0; + //loadInfo.Format = MAKE_TYPELESS( SrcInfo.Format ); + //loadInfo.Filter = D3DX10_FILTER_NONE; + //loadInfo.MipFilter = D3DX10_FILTER_NONE; + //loadInfo.pSrcInfo = &SrcInfo; + //hr = D3DX10CreateTextureFromFile( m_pd3d10Device, pTextureNode->strFilename, &loadInfo, NULL, &pRes, NULL ); + //if( FAILED( hr ) ) + //{ + // return DXTRACE_ERR( L"D3DX10CreateResourceFromFileEx", hr ); + //} + //hr = pRes->QueryInterface( __uuidof( ID3D10Texture2D ), ( LPVOID* )&pTextureNode->pTexture10 ); + //SAFE_RELEASE( pRes ); + //if( FAILED( hr ) ) + // return hr; + // + } + + // Store dimensions + D3D11_TEXTURE2D_DESC desc; + pTextureNode->pTexture11->GetDesc( &desc ); + pTextureNode->dwWidth = desc.Width; + pTextureNode->dwHeight = desc.Height; + + // Create resource view + D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + SRVDesc.Format = MAKE_SRGB( desc.Format ); + SRVDesc.Texture2D.MipLevels = 1; + SRVDesc.Texture2D.MostDetailedMip = 0; + hr = m_pd3d11Device->CreateShaderResourceView( pTextureNode->pTexture11, &SRVDesc, &pTextureNode->pTexResView11 ); + + return hr; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTDialog::InitDefaultElements() +{ + SetFont( 0, L"Arial", 14, FW_NORMAL ); + + CDXUTElement Element; + RECT rcTexture; + + //------------------------------------- + // Element for the caption + //------------------------------------- + m_CapElement.SetFont( 0 ); + SetRect( &rcTexture, 17, 269, 241, 287 ); + m_CapElement.SetTexture( 0, &rcTexture ); + m_CapElement.TextureColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 255, 255, 255, 255 ); + m_CapElement.FontColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 255, 255, 255, 255 ); + m_CapElement.SetFont( 0, D3DCOLOR_ARGB( 255, 255, 255, 255 ), DT_LEFT | DT_VCENTER ); + // Pre-blend as we don't need to transition the state + m_CapElement.TextureColor.Blend( DXUT_STATE_NORMAL, 10.0f ); + m_CapElement.FontColor.Blend( DXUT_STATE_NORMAL, 10.0f ); + + //------------------------------------- + // CDXUTStatic + //------------------------------------- + Element.SetFont( 0 ); + Element.FontColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 200, 200, 200, 200 ); + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_STATIC, 0, &Element ); + + + //------------------------------------- + // CDXUTButton - Button + //------------------------------------- + SetRect( &rcTexture, 0, 0, 136, 54 ); + Element.SetTexture( 0, &rcTexture ); + Element.SetFont( 0 ); + Element.TextureColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 150, 255, 255, 255 ); + Element.TextureColor.States[ DXUT_STATE_PRESSED ] = D3DCOLOR_ARGB( 200, 255, 255, 255 ); + Element.FontColor.States[ DXUT_STATE_MOUSEOVER ] = D3DCOLOR_ARGB( 255, 0, 0, 0 ); + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_BUTTON, 0, &Element ); + + + //------------------------------------- + // CDXUTButton - Fill layer + //------------------------------------- + SetRect( &rcTexture, 136, 0, 252, 54 ); + Element.SetTexture( 0, &rcTexture, D3DCOLOR_ARGB( 0, 255, 255, 255 ) ); + Element.TextureColor.States[ DXUT_STATE_MOUSEOVER ] = D3DCOLOR_ARGB( 160, 255, 255, 255 ); + Element.TextureColor.States[ DXUT_STATE_PRESSED ] = D3DCOLOR_ARGB( 60, 0, 0, 0 ); + Element.TextureColor.States[ DXUT_STATE_FOCUS ] = D3DCOLOR_ARGB( 30, 255, 255, 255 ); + + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_BUTTON, 1, &Element ); + + + //------------------------------------- + // CDXUTCheckBox - Box + //------------------------------------- + SetRect( &rcTexture, 0, 54, 27, 81 ); + Element.SetTexture( 0, &rcTexture ); + Element.SetFont( 0, D3DCOLOR_ARGB( 255, 255, 255, 255 ), DT_LEFT | DT_VCENTER ); + Element.FontColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 200, 200, 200, 200 ); + Element.TextureColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 150, 255, 255, 255 ); + Element.TextureColor.States[ DXUT_STATE_FOCUS ] = D3DCOLOR_ARGB( 200, 255, 255, 255 ); + Element.TextureColor.States[ DXUT_STATE_PRESSED ] = D3DCOLOR_ARGB( 255, 255, 255, 255 ); + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_CHECKBOX, 0, &Element ); + + + //------------------------------------- + // CDXUTCheckBox - Check + //------------------------------------- + SetRect( &rcTexture, 27, 54, 54, 81 ); + Element.SetTexture( 0, &rcTexture ); + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_CHECKBOX, 1, &Element ); + + + //------------------------------------- + // CDXUTRadioButton - Box + //------------------------------------- + SetRect( &rcTexture, 54, 54, 81, 81 ); + Element.SetTexture( 0, &rcTexture ); + Element.SetFont( 0, D3DCOLOR_ARGB( 255, 255, 255, 255 ), DT_LEFT | DT_VCENTER ); + Element.FontColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 200, 200, 200, 200 ); + Element.TextureColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 150, 255, 255, 255 ); + Element.TextureColor.States[ DXUT_STATE_FOCUS ] = D3DCOLOR_ARGB( 200, 255, 255, 255 ); + Element.TextureColor.States[ DXUT_STATE_PRESSED ] = D3DCOLOR_ARGB( 255, 255, 255, 255 ); + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_RADIOBUTTON, 0, &Element ); + + + //------------------------------------- + // CDXUTRadioButton - Check + //------------------------------------- + SetRect( &rcTexture, 81, 54, 108, 81 ); + Element.SetTexture( 0, &rcTexture ); + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_RADIOBUTTON, 1, &Element ); + + + //------------------------------------- + // CDXUTComboBox - Main + //------------------------------------- + SetRect( &rcTexture, 7, 81, 247, 123 ); + Element.SetTexture( 0, &rcTexture ); + Element.SetFont( 0 ); + Element.TextureColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 150, 200, 200, 200 ); + Element.TextureColor.States[ DXUT_STATE_FOCUS ] = D3DCOLOR_ARGB( 170, 230, 230, 230 ); + Element.TextureColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 70, 200, 200, 200 ); + Element.FontColor.States[ DXUT_STATE_MOUSEOVER ] = D3DCOLOR_ARGB( 255, 0, 0, 0 ); + Element.FontColor.States[ DXUT_STATE_PRESSED ] = D3DCOLOR_ARGB( 255, 0, 0, 0 ); + Element.FontColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 200, 200, 200, 200 ); + + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_COMBOBOX, 0, &Element ); + + + //------------------------------------- + // CDXUTComboBox - Button + //------------------------------------- + SetRect( &rcTexture, 98, 189, 151, 238 ); + Element.SetTexture( 0, &rcTexture ); + Element.TextureColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 150, 255, 255, 255 ); + Element.TextureColor.States[ DXUT_STATE_PRESSED ] = D3DCOLOR_ARGB( 255, 150, 150, 150 ); + Element.TextureColor.States[ DXUT_STATE_FOCUS ] = D3DCOLOR_ARGB( 200, 255, 255, 255 ); + Element.TextureColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 70, 255, 255, 255 ); + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_COMBOBOX, 1, &Element ); + + + //------------------------------------- + // CDXUTComboBox - Dropdown + //------------------------------------- + SetRect( &rcTexture, 13, 123, 241, 160 ); + Element.SetTexture( 0, &rcTexture ); + Element.SetFont( 0, D3DCOLOR_ARGB( 255, 0, 0, 0 ), DT_LEFT | DT_TOP ); + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_COMBOBOX, 2, &Element ); + + + //------------------------------------- + // CDXUTComboBox - Selection + //------------------------------------- + SetRect( &rcTexture, 12, 163, 239, 183 ); + Element.SetTexture( 0, &rcTexture ); + Element.SetFont( 0, D3DCOLOR_ARGB( 255, 255, 255, 255 ), DT_LEFT | DT_TOP ); + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_COMBOBOX, 3, &Element ); + + + //------------------------------------- + // CDXUTSlider - Track + //------------------------------------- + SetRect( &rcTexture, 1, 187, 93, 228 ); + Element.SetTexture( 0, &rcTexture ); + Element.TextureColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 150, 255, 255, 255 ); + Element.TextureColor.States[ DXUT_STATE_FOCUS ] = D3DCOLOR_ARGB( 200, 255, 255, 255 ); + Element.TextureColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 70, 255, 255, 255 ); + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_SLIDER, 0, &Element ); + + //------------------------------------- + // CDXUTSlider - Button + //------------------------------------- + SetRect( &rcTexture, 151, 193, 192, 234 ); + Element.SetTexture( 0, &rcTexture ); + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_SLIDER, 1, &Element ); + + //------------------------------------- + // CDXUTScrollBar - Track + //------------------------------------- + int nScrollBarStartX = 196; + int nScrollBarStartY = 191; + SetRect( &rcTexture, nScrollBarStartX + 0, nScrollBarStartY + 21, nScrollBarStartX + 22, nScrollBarStartY + 32 ); + Element.SetTexture( 0, &rcTexture ); + Element.TextureColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 255, 200, 200, 200 ); + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_SCROLLBAR, 0, &Element ); + + //------------------------------------- + // CDXUTScrollBar - Up Arrow + //------------------------------------- + SetRect( &rcTexture, nScrollBarStartX + 0, nScrollBarStartY + 1, nScrollBarStartX + 22, nScrollBarStartY + 21 ); + Element.SetTexture( 0, &rcTexture ); + Element.TextureColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 255, 200, 200, 200 ); + + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_SCROLLBAR, 1, &Element ); + + //------------------------------------- + // CDXUTScrollBar - Down Arrow + //------------------------------------- + SetRect( &rcTexture, nScrollBarStartX + 0, nScrollBarStartY + 32, nScrollBarStartX + 22, nScrollBarStartY + 53 ); + Element.SetTexture( 0, &rcTexture ); + Element.TextureColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 255, 200, 200, 200 ); + + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_SCROLLBAR, 2, &Element ); + + //------------------------------------- + // CDXUTScrollBar - Button + //------------------------------------- + SetRect( &rcTexture, 220, 192, 238, 234 ); + Element.SetTexture( 0, &rcTexture ); + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_SCROLLBAR, 3, &Element ); + + + //------------------------------------- + // CDXUTEditBox + //------------------------------------- + // Element assignment: + // 0 - text area + // 1 - top left border + // 2 - top border + // 3 - top right border + // 4 - left border + // 5 - right border + // 6 - lower left border + // 7 - lower border + // 8 - lower right border + + Element.SetFont( 0, D3DCOLOR_ARGB( 255, 0, 0, 0 ), DT_LEFT | DT_TOP ); + + // Assign the style + SetRect( &rcTexture, 14, 90, 241, 113 ); + Element.SetTexture( 0, &rcTexture ); + SetDefaultElement( DXUT_CONTROL_EDITBOX, 0, &Element ); + SetRect( &rcTexture, 8, 82, 14, 90 ); + Element.SetTexture( 0, &rcTexture ); + SetDefaultElement( DXUT_CONTROL_EDITBOX, 1, &Element ); + SetRect( &rcTexture, 14, 82, 241, 90 ); + Element.SetTexture( 0, &rcTexture ); + SetDefaultElement( DXUT_CONTROL_EDITBOX, 2, &Element ); + SetRect( &rcTexture, 241, 82, 246, 90 ); + Element.SetTexture( 0, &rcTexture ); + SetDefaultElement( DXUT_CONTROL_EDITBOX, 3, &Element ); + SetRect( &rcTexture, 8, 90, 14, 113 ); + Element.SetTexture( 0, &rcTexture ); + SetDefaultElement( DXUT_CONTROL_EDITBOX, 4, &Element ); + SetRect( &rcTexture, 241, 90, 246, 113 ); + Element.SetTexture( 0, &rcTexture ); + SetDefaultElement( DXUT_CONTROL_EDITBOX, 5, &Element ); + SetRect( &rcTexture, 8, 113, 14, 121 ); + Element.SetTexture( 0, &rcTexture ); + SetDefaultElement( DXUT_CONTROL_EDITBOX, 6, &Element ); + SetRect( &rcTexture, 14, 113, 241, 121 ); + Element.SetTexture( 0, &rcTexture ); + SetDefaultElement( DXUT_CONTROL_EDITBOX, 7, &Element ); + SetRect( &rcTexture, 241, 113, 246, 121 ); + Element.SetTexture( 0, &rcTexture ); + SetDefaultElement( DXUT_CONTROL_EDITBOX, 8, &Element ); + + //------------------------------------- + // CDXUTListBox - Main + //------------------------------------- + SetRect( &rcTexture, 13, 123, 241, 160 ); + Element.SetTexture( 0, &rcTexture ); + Element.SetFont( 0, D3DCOLOR_ARGB( 255, 0, 0, 0 ), DT_LEFT | DT_TOP ); + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_LISTBOX, 0, &Element ); + + //------------------------------------- + // CDXUTListBox - Selection + //------------------------------------- + + SetRect( &rcTexture, 16, 166, 240, 183 ); + Element.SetTexture( 0, &rcTexture ); + Element.SetFont( 0, D3DCOLOR_ARGB( 255, 255, 255, 255 ), DT_LEFT | DT_TOP ); + + // Assign the Element + SetDefaultElement( DXUT_CONTROL_LISTBOX, 1, &Element ); +} + + + +//-------------------------------------------------------------------------------------- +// CDXUTControl class +//-------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------------- +CDXUTControl::CDXUTControl( CDXUTDialog* pDialog ) +{ + m_Type = DXUT_CONTROL_BUTTON; + m_pDialog = pDialog; + m_ID = 0; + m_Index = 0; + m_pUserData = NULL; + + m_bEnabled = true; + m_bVisible = true; + m_bMouseOver = false; + m_bHasFocus = false; + m_bIsDefault = false; + + m_pDialog = NULL; + + m_x = 0; + m_y = 0; + m_width = 0; + m_height = 0; + + ZeroMemory( &m_rcBoundingBox, sizeof( m_rcBoundingBox ) ); +} + + +CDXUTControl::~CDXUTControl() +{ + for( int i = 0; i < m_Elements.GetSize(); ++i ) + { + delete m_Elements[i]; + } + m_Elements.RemoveAll(); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTControl::SetTextColor( D3DCOLOR Color ) +{ + CDXUTElement* pElement = m_Elements.GetAt( 0 ); + + if( pElement ) + pElement->FontColor.States[DXUT_STATE_NORMAL] = Color; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTControl::SetElement( UINT iElement, CDXUTElement* pElement ) +{ + HRESULT hr = S_OK; + + if( pElement == NULL ) + return E_INVALIDARG; + + // Make certain the array is this large + for( UINT i = m_Elements.GetSize(); i <= iElement; i++ ) + { + CDXUTElement* pNewElement = new CDXUTElement(); + if( pNewElement == NULL ) + return E_OUTOFMEMORY; + + hr = m_Elements.Add( pNewElement ); + if( FAILED( hr ) ) + { + SAFE_DELETE( pNewElement ); + return hr; + } + } + + // Update the data + CDXUTElement* pCurElement = m_Elements.GetAt( iElement ); + *pCurElement = *pElement; + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTControl::Refresh() +{ + m_bMouseOver = false; + m_bHasFocus = false; + + for( int i = 0; i < m_Elements.GetSize(); i++ ) + { + CDXUTElement* pElement = m_Elements.GetAt( i ); + pElement->Refresh(); + } +} + + +//-------------------------------------------------------------------------------------- +void CDXUTControl::UpdateRects() +{ + SetRect( &m_rcBoundingBox, m_x, m_y, m_x + m_width, m_y + m_height ); +} + + +//-------------------------------------------------------------------------------------- +// CDXUTStatic class +//-------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------------- +CDXUTStatic::CDXUTStatic( CDXUTDialog* pDialog ) +{ + m_Type = DXUT_CONTROL_STATIC; + m_pDialog = pDialog; + + ZeroMemory( &m_strText, sizeof( m_strText ) ); + + for( int i = 0; i < m_Elements.GetSize(); i++ ) + { + CDXUTElement* pElement = m_Elements.GetAt( i ); + SAFE_DELETE( pElement ); + } + + m_Elements.RemoveAll(); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTStatic::Render( float fElapsedTime ) +{ + if( m_bVisible == false ) + return; + + DXUT_CONTROL_STATE iState = DXUT_STATE_NORMAL; + + if( m_bEnabled == false ) + iState = DXUT_STATE_DISABLED; + + CDXUTElement* pElement = m_Elements.GetAt( 0 ); + + pElement->FontColor.Blend( iState, fElapsedTime ); + + m_pDialog->DrawText( m_strText, pElement, &m_rcBoundingBox, false, -1, false); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTStatic::GetTextCopy( __out_ecount(bufferCount) LPWSTR strDest, + UINT bufferCount ) +{ + // Validate incoming parameters + if( strDest == NULL || bufferCount == 0 ) + { + return E_INVALIDARG; + } + + // Copy the window text + wcscpy_s( strDest, bufferCount, m_strText ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTStatic::SetText( LPCWSTR strText ) +{ + if( strText == NULL ) + { + m_strText[0] = 0; + return S_OK; + } + + wcscpy_s( m_strText, MAX_PATH, strText ); + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// CDXUTButton class +//-------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------------- +CDXUTButton::CDXUTButton( CDXUTDialog* pDialog ) +{ + m_Type = DXUT_CONTROL_BUTTON; + m_pDialog = pDialog; + + m_bPressed = false; + m_nHotkey = 0; +} + +//-------------------------------------------------------------------------------------- +bool CDXUTButton::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + if( !m_bEnabled || !m_bVisible ) + return false; + + switch( uMsg ) + { + case WM_KEYDOWN: + { + switch( wParam ) + { + case VK_SPACE: + m_bPressed = true; + return true; + } + } + + case WM_KEYUP: + { + switch( wParam ) + { + case VK_SPACE: + if( m_bPressed == true ) + { + m_bPressed = false; + m_pDialog->SendEvent( EVENT_BUTTON_CLICKED, true, this ); + } + return true; + } + } + } + return false; +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTButton::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ) +{ + if( !m_bEnabled || !m_bVisible ) + return false; + + switch( uMsg ) + { + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + { + if( ContainsPoint( pt ) ) + { + // Pressed while inside the control + m_bPressed = true; + SetCapture( DXUTGetHWND() ); + + if( !m_bHasFocus ) + m_pDialog->RequestFocus( this ); + + return true; + } + + break; + } + + case WM_LBUTTONUP: + { + if( m_bPressed ) + { + m_bPressed = false; + ReleaseCapture(); + + if( !m_pDialog->m_bKeyboardInput ) + m_pDialog->ClearFocus(); + + // Button click + if( ContainsPoint( pt ) ) + m_pDialog->SendEvent( EVENT_BUTTON_CLICKED, true, this ); + + return true; + } + + break; + } + }; + + return false; +} + +//-------------------------------------------------------------------------------------- +void CDXUTButton::Render( float fElapsedTime ) +{ + if( m_bVisible == false ) + return; + + int nOffsetX = 0; + int nOffsetY = 0; + + DXUT_CONTROL_STATE iState = DXUT_STATE_NORMAL; + + if( m_bVisible == false ) + { + iState = DXUT_STATE_HIDDEN; + } + else if( m_bEnabled == false ) + { + iState = DXUT_STATE_DISABLED; + } + else if( m_bPressed ) + { + iState = DXUT_STATE_PRESSED; + + nOffsetX = 1; + nOffsetY = 2; + } + else if( m_bMouseOver ) + { + iState = DXUT_STATE_MOUSEOVER; + + nOffsetX = -1; + nOffsetY = -2; + } + else if( m_bHasFocus ) + { + iState = DXUT_STATE_FOCUS; + } + + // Background fill layer + //TODO: remove magic numbers + CDXUTElement* pElement = m_Elements.GetAt( 0 ); + + float fBlendRate = ( iState == DXUT_STATE_PRESSED ) ? 0.0f : 0.8f; + + RECT rcWindow = m_rcBoundingBox; + OffsetRect( &rcWindow, nOffsetX, nOffsetY ); + + + // Blend current color + pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate ); + pElement->FontColor.Blend( iState, fElapsedTime, fBlendRate ); + + m_pDialog->DrawSprite( pElement, &rcWindow, DXUT_FAR_BUTTON_DEPTH ); + m_pDialog->DrawText( m_strText, pElement, &rcWindow, false, -1, true ); + + // Main button + pElement = m_Elements.GetAt( 1 ); + + // Blend current color + pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate ); + pElement->FontColor.Blend( iState, fElapsedTime, fBlendRate ); + + m_pDialog->DrawSprite( pElement, &rcWindow, DXUT_NEAR_BUTTON_DEPTH ); + m_pDialog->DrawText( m_strText, pElement, &rcWindow, false, -1, true ); +} + + + +//-------------------------------------------------------------------------------------- +// CDXUTCheckBox class +//-------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------------- +CDXUTCheckBox::CDXUTCheckBox( CDXUTDialog* pDialog ) +{ + m_Type = DXUT_CONTROL_CHECKBOX; + m_pDialog = pDialog; + + m_bChecked = false; +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTCheckBox::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + if( !m_bEnabled || !m_bVisible ) + return false; + + switch( uMsg ) + { + case WM_KEYDOWN: + { + switch( wParam ) + { + case VK_SPACE: + m_bPressed = true; + return true; + } + } + + case WM_KEYUP: + { + switch( wParam ) + { + case VK_SPACE: + if( m_bPressed == true ) + { + m_bPressed = false; + SetCheckedInternal( !m_bChecked, true ); + } + return true; + } + } + } + return false; +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTCheckBox::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ) +{ + if( !m_bEnabled || !m_bVisible ) + return false; + + switch( uMsg ) + { + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + { + if( ContainsPoint( pt ) ) + { + // Pressed while inside the control + m_bPressed = true; + SetCapture( DXUTGetHWND() ); + + if( !m_bHasFocus ) + m_pDialog->RequestFocus( this ); + + return true; + } + + break; + } + + case WM_LBUTTONUP: + { + if( m_bPressed ) + { + m_bPressed = false; + ReleaseCapture(); + + // Button click + if( ContainsPoint( pt ) ) + SetCheckedInternal( !m_bChecked, true ); + + return true; + } + + break; + } + }; + + return false; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTCheckBox::SetCheckedInternal( bool bChecked, bool bFromInput ) +{ + m_bChecked = bChecked; + + m_pDialog->SendEvent( EVENT_CHECKBOX_CHANGED, bFromInput, this ); +} + + +//-------------------------------------------------------------------------------------- +BOOL CDXUTCheckBox::ContainsPoint( POINT pt ) +{ + return ( PtInRect( &m_rcBoundingBox, pt ) || + PtInRect( &m_rcButton, pt ) ); +} + + + +//-------------------------------------------------------------------------------------- +void CDXUTCheckBox::UpdateRects() +{ + CDXUTButton::UpdateRects(); + + m_rcButton = m_rcBoundingBox; + m_rcButton.right = m_rcButton.left + RectHeight( m_rcButton ); + + m_rcText = m_rcBoundingBox; + m_rcText.left += ( int )( 1.25f * RectWidth( m_rcButton ) ); +} + + + +//-------------------------------------------------------------------------------------- +void CDXUTCheckBox::Render( float fElapsedTime ) +{ + if( m_bVisible == false ) + return; + DXUT_CONTROL_STATE iState = DXUT_STATE_NORMAL; + + if( m_bVisible == false ) + iState = DXUT_STATE_HIDDEN; + else if( m_bEnabled == false ) + iState = DXUT_STATE_DISABLED; + else if( m_bPressed ) + iState = DXUT_STATE_PRESSED; + else if( m_bMouseOver ) + iState = DXUT_STATE_MOUSEOVER; + else if( m_bHasFocus ) + iState = DXUT_STATE_FOCUS; + + CDXUTElement* pElement = m_Elements.GetAt( 0 ); + + float fBlendRate = ( iState == DXUT_STATE_PRESSED ) ? 0.0f : 0.8f; + + pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate ); + pElement->FontColor.Blend( iState, fElapsedTime, fBlendRate ); + + m_pDialog->DrawSprite( pElement, &m_rcButton, DXUT_NEAR_BUTTON_DEPTH ); + m_pDialog->DrawText( m_strText, pElement, &m_rcText, false, -1, false ); + + if( !m_bChecked ) + iState = DXUT_STATE_HIDDEN; + + pElement = m_Elements.GetAt( 1 ); + + pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate ); + m_pDialog->DrawSprite( pElement, &m_rcButton, DXUT_FAR_BUTTON_DEPTH ); +} + + + + +//-------------------------------------------------------------------------------------- +// CDXUTRadioButton class +//-------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------------- +CDXUTRadioButton::CDXUTRadioButton( CDXUTDialog* pDialog ) +{ + m_Type = DXUT_CONTROL_RADIOBUTTON; + m_pDialog = pDialog; +} + + + +//-------------------------------------------------------------------------------------- +bool CDXUTRadioButton::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + if( !m_bEnabled || !m_bVisible ) + return false; + + switch( uMsg ) + { + case WM_KEYDOWN: + { + switch( wParam ) + { + case VK_SPACE: + m_bPressed = true; + return true; + } + } + + case WM_KEYUP: + { + switch( wParam ) + { + case VK_SPACE: + if( m_bPressed == true ) + { + m_bPressed = false; + + m_pDialog->ClearRadioButtonGroup( m_nButtonGroup ); + m_bChecked = !m_bChecked; + + m_pDialog->SendEvent( EVENT_RADIOBUTTON_CHANGED, true, this ); + } + return true; + } + } + } + return false; +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTRadioButton::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ) +{ + if( !m_bEnabled || !m_bVisible ) + return false; + + switch( uMsg ) + { + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + { + if( ContainsPoint( pt ) ) + { + // Pressed while inside the control + m_bPressed = true; + SetCapture( DXUTGetHWND() ); + + if( !m_bHasFocus ) + m_pDialog->RequestFocus( this ); + + return true; + } + + break; + } + + case WM_LBUTTONUP: + { + if( m_bPressed ) + { + m_bPressed = false; + ReleaseCapture(); + + // Button click + if( ContainsPoint( pt ) ) + { + m_pDialog->ClearRadioButtonGroup( m_nButtonGroup ); + m_bChecked = !m_bChecked; + + m_pDialog->SendEvent( EVENT_RADIOBUTTON_CHANGED, true, this ); + } + + return true; + } + + break; + } + }; + + return false; +} + +//-------------------------------------------------------------------------------------- +void CDXUTRadioButton::SetCheckedInternal( bool bChecked, bool bClearGroup, bool bFromInput ) +{ + if( bChecked && bClearGroup ) + m_pDialog->ClearRadioButtonGroup( m_nButtonGroup ); + + m_bChecked = bChecked; + m_pDialog->SendEvent( EVENT_RADIOBUTTON_CHANGED, bFromInput, this ); +} + + + + +//-------------------------------------------------------------------------------------- +// CDXUTComboBox class +//-------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------------- +CDXUTComboBox::CDXUTComboBox( CDXUTDialog* pDialog ) : m_ScrollBar( pDialog ) +{ + m_Type = DXUT_CONTROL_COMBOBOX; + m_pDialog = pDialog; + + m_nDropHeight = 100; + + m_nSBWidth = 16; + m_bOpened = false; + m_iSelected = -1; + m_iFocused = -1; +} + + +//-------------------------------------------------------------------------------------- +CDXUTComboBox::~CDXUTComboBox() +{ + RemoveAllItems(); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTComboBox::SetTextColor( D3DCOLOR Color ) +{ + CDXUTElement* pElement = m_Elements.GetAt( 0 ); + + if( pElement ) + pElement->FontColor.States[DXUT_STATE_NORMAL] = Color; + + pElement = m_Elements.GetAt( 2 ); + + if( pElement ) + pElement->FontColor.States[DXUT_STATE_NORMAL] = Color; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTComboBox::UpdateRects() +{ + + CDXUTButton::UpdateRects(); + + m_rcButton = m_rcBoundingBox; + m_rcButton.left = m_rcButton.right - RectHeight( m_rcButton ); + + m_rcText = m_rcBoundingBox; + m_rcText.right = m_rcButton.left; + + m_rcDropdown = m_rcText; + OffsetRect( &m_rcDropdown, 0, ( int )( 0.90f * RectHeight( m_rcText ) ) ); + m_rcDropdown.bottom += m_nDropHeight; + m_rcDropdown.right -= m_nSBWidth; + + m_rcDropdownText = m_rcDropdown; + m_rcDropdownText.left += ( int )( 0.1f * RectWidth( m_rcDropdown ) ); + m_rcDropdownText.right -= ( int )( 0.1f * RectWidth( m_rcDropdown ) ); + m_rcDropdownText.top += ( int )( 0.1f * RectHeight( m_rcDropdown ) ); + m_rcDropdownText.bottom -= ( int )( 0.1f * RectHeight( m_rcDropdown ) ); + + // Update the scrollbar's rects + m_ScrollBar.SetLocation( m_rcDropdown.right, m_rcDropdown.top + 2 ); + m_ScrollBar.SetSize( m_nSBWidth, RectHeight( m_rcDropdown ) - 2 ); + DXUTFontNode* pFontNode = m_pDialog->GetManager()->GetFontNode( m_Elements.GetAt( 2 )->iFont ); + if( pFontNode && pFontNode->nHeight ) + { + m_ScrollBar.SetPageSize( RectHeight( m_rcDropdownText ) / pFontNode->nHeight ); + + // The selected item may have been scrolled off the page. + // Ensure that it is in page again. + m_ScrollBar.ShowItem( m_iSelected ); + } +} + + +//-------------------------------------------------------------------------------------- +void CDXUTComboBox::OnFocusOut() +{ + CDXUTButton::OnFocusOut(); + + m_bOpened = false; +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTComboBox::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + const DWORD REPEAT_MASK = ( 0x40000000 ); + + if( !m_bEnabled || !m_bVisible ) + return false; + + // Let the scroll bar have a chance to handle it first + if( m_ScrollBar.HandleKeyboard( uMsg, wParam, lParam ) ) + return true; + + switch( uMsg ) + { + case WM_KEYDOWN: + { + switch( wParam ) + { + case VK_RETURN: + if( m_bOpened ) + { + if( m_iSelected != m_iFocused ) + { + m_iSelected = m_iFocused; + m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this ); + } + m_bOpened = false; + + if( !m_pDialog->m_bKeyboardInput ) + m_pDialog->ClearFocus(); + + return true; + } + break; + + case VK_F4: + // Filter out auto-repeats + if( lParam & REPEAT_MASK ) + return true; + + m_bOpened = !m_bOpened; + + if( !m_bOpened ) + { + m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this ); + + if( !m_pDialog->m_bKeyboardInput ) + m_pDialog->ClearFocus(); + } + + return true; + + case VK_LEFT: + case VK_UP: + if( m_iFocused > 0 ) + { + m_iFocused--; + m_iSelected = m_iFocused; + + if( !m_bOpened ) + m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this ); + } + + return true; + + case VK_RIGHT: + case VK_DOWN: + if( m_iFocused + 1 < ( int )GetNumItems() ) + { + m_iFocused++; + m_iSelected = m_iFocused; + + if( !m_bOpened ) + m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this ); + } + + return true; + } + break; + } + } + + return false; +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTComboBox::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ) +{ + if( !m_bEnabled || !m_bVisible ) + return false; + + // Let the scroll bar handle it first. + if( m_ScrollBar.HandleMouse( uMsg, pt, wParam, lParam ) ) + return true; + + switch( uMsg ) + { + case WM_MOUSEMOVE: + { + if( m_bOpened && PtInRect( &m_rcDropdown, pt ) ) + { + // Determine which item has been selected + for( int i = 0; i < m_Items.GetSize(); i++ ) + { + DXUTComboBoxItem* pItem = m_Items.GetAt( i ); + if( pItem->bVisible && + PtInRect( &pItem->rcActive, pt ) ) + { + m_iFocused = i; + } + } + return true; + } + break; + } + + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + { + if( ContainsPoint( pt ) ) + { + // Pressed while inside the control + m_bPressed = true; + SetCapture( DXUTGetHWND() ); + + if( !m_bHasFocus ) + m_pDialog->RequestFocus( this ); + + // Toggle dropdown + if( m_bHasFocus ) + { + m_bOpened = !m_bOpened; + + if( !m_bOpened ) + { + if( !m_pDialog->m_bKeyboardInput ) + m_pDialog->ClearFocus(); + } + } + + return true; + } + + // Perhaps this click is within the dropdown + if( m_bOpened && PtInRect( &m_rcDropdown, pt ) ) + { + // Determine which item has been selected + for( int i = m_ScrollBar.GetTrackPos(); i < m_Items.GetSize(); i++ ) + { + DXUTComboBoxItem* pItem = m_Items.GetAt( i ); + if( pItem->bVisible && + PtInRect( &pItem->rcActive, pt ) ) + { + m_iFocused = m_iSelected = i; + m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this ); + m_bOpened = false; + + if( !m_pDialog->m_bKeyboardInput ) + m_pDialog->ClearFocus(); + + break; + } + } + + return true; + } + + // Mouse click not on main control or in dropdown, fire an event if needed + if( m_bOpened ) + { + m_iFocused = m_iSelected; + + m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this ); + m_bOpened = false; + } + + // Make sure the control is no longer in a pressed state + m_bPressed = false; + + // Release focus if appropriate + if( !m_pDialog->m_bKeyboardInput ) + { + m_pDialog->ClearFocus(); + } + + break; + } + + case WM_LBUTTONUP: + { + if( m_bPressed && ContainsPoint( pt ) ) + { + // Button click + m_bPressed = false; + ReleaseCapture(); + return true; + } + + break; + } + + case WM_MOUSEWHEEL: + { + int zDelta = ( short )HIWORD( wParam ) / WHEEL_DELTA; + if( m_bOpened ) + { + UINT uLines; + SystemParametersInfo( SPI_GETWHEELSCROLLLINES, 0, &uLines, 0 ); + m_ScrollBar.Scroll( -zDelta * uLines ); + } + else + { + if( zDelta > 0 ) + { + if( m_iFocused > 0 ) + { + m_iFocused--; + m_iSelected = m_iFocused; + + if( !m_bOpened ) + m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this ); + } + } + else + { + if( m_iFocused + 1 < ( int )GetNumItems() ) + { + m_iFocused++; + m_iSelected = m_iFocused; + + if( !m_bOpened ) + m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this ); + } + } + } + return true; + } + }; + + return false; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTComboBox::OnHotkey() +{ + if( m_bOpened ) + return; + + if( m_iSelected == -1 ) + return; + + if( m_pDialog->IsKeyboardInputEnabled() ) + m_pDialog->RequestFocus( this ); + + m_iSelected++; + + if( m_iSelected >= ( int )m_Items.GetSize() ) + m_iSelected = 0; + + m_iFocused = m_iSelected; + m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this ); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTComboBox::Render( float fElapsedTime ) +{ + if( m_bVisible == false ) + return; + DXUT_CONTROL_STATE iState = DXUT_STATE_NORMAL; + + if( !m_bOpened ) + iState = DXUT_STATE_HIDDEN; + + // Dropdown box + CDXUTElement* pElement = m_Elements.GetAt( 2 ); + + // If we have not initialized the scroll bar page size, + // do that now. + static bool bSBInit; + if( !bSBInit ) + { + // Update the page size of the scroll bar + if( m_pDialog->GetManager()->GetFontNode( pElement->iFont )->nHeight ) + m_ScrollBar.SetPageSize( RectHeight( m_rcDropdownText ) / + m_pDialog->GetManager()->GetFontNode( pElement->iFont )->nHeight ); + else + m_ScrollBar.SetPageSize( RectHeight( m_rcDropdownText ) ); + bSBInit = true; + } + + // Scroll bar + if( m_bOpened ) + m_ScrollBar.Render( fElapsedTime ); + + // Blend current color + pElement->TextureColor.Blend( iState, fElapsedTime ); + pElement->FontColor.Blend( iState, fElapsedTime ); + + m_pDialog->DrawSprite( pElement, &m_rcDropdown, DXUT_NEAR_BUTTON_DEPTH ); + + // Selection outline + CDXUTElement* pSelectionElement = m_Elements.GetAt( 3 ); + pSelectionElement->TextureColor.Current = pElement->TextureColor.Current; + pSelectionElement->FontColor.Current = pSelectionElement->FontColor.States[ DXUT_STATE_NORMAL ]; + + DXUTFontNode* pFont = m_pDialog->GetFont( pElement->iFont ); + if( pFont ) + { + int curY = m_rcDropdownText.top; + int nRemainingHeight = RectHeight( m_rcDropdownText ); + //WCHAR strDropdown[4096] = {0}; + + for( int i = m_ScrollBar.GetTrackPos(); i < m_Items.GetSize(); i++ ) + { + DXUTComboBoxItem* pItem = m_Items.GetAt( i ); + + // Make sure there's room left in the dropdown + nRemainingHeight -= pFont->nHeight; + if( nRemainingHeight < 0 ) + { + pItem->bVisible = false; + continue; + } + + SetRect( &pItem->rcActive, m_rcDropdownText.left, curY, m_rcDropdownText.right, curY + pFont->nHeight ); + curY += pFont->nHeight; + + //debug + //int blue = 50 * i; + //m_pDialog->DrawRect( &pItem->rcActive, 0xFFFF0000 | blue ); + + pItem->bVisible = true; + + if( m_bOpened ) + { + if( ( int )i == m_iFocused ) + { + RECT rc; + SetRect( &rc, m_rcDropdown.left, pItem->rcActive.top - 2, m_rcDropdown.right, + pItem->rcActive.bottom + 2 ); + m_pDialog->DrawSprite( pSelectionElement, &rc, DXUT_NEAR_BUTTON_DEPTH ); + m_pDialog->DrawText( pItem->strText, pSelectionElement, &pItem->rcActive ); + } + else + { + m_pDialog->DrawText( pItem->strText, pElement, &pItem->rcActive ); + } + } + } + } + + int nOffsetX = 0; + int nOffsetY = 0; + + iState = DXUT_STATE_NORMAL; + + if( m_bVisible == false ) + iState = DXUT_STATE_HIDDEN; + else if( m_bEnabled == false ) + iState = DXUT_STATE_DISABLED; + else if( m_bPressed ) + { + iState = DXUT_STATE_PRESSED; + + nOffsetX = 1; + nOffsetY = 2; + } + else if( m_bMouseOver ) + { + iState = DXUT_STATE_MOUSEOVER; + + nOffsetX = -1; + nOffsetY = -2; + } + else if( m_bHasFocus ) + iState = DXUT_STATE_FOCUS; + + float fBlendRate = ( iState == DXUT_STATE_PRESSED ) ? 0.0f : 0.8f; + + // Button + pElement = m_Elements.GetAt( 1 ); + + // Blend current color + pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate ); + + RECT rcWindow = m_rcButton; + OffsetRect( &rcWindow, nOffsetX, nOffsetY ); + m_pDialog->DrawSprite( pElement, &rcWindow, DXUT_FAR_BUTTON_DEPTH ); + + if( m_bOpened ) + iState = DXUT_STATE_PRESSED; + + // Main text box + //TODO: remove magic numbers + pElement = m_Elements.GetAt( 0 ); + + // Blend current color + pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate ); + pElement->FontColor.Blend( iState, fElapsedTime, fBlendRate ); + + m_pDialog->DrawSprite( pElement, &m_rcText, DXUT_NEAR_BUTTON_DEPTH ); + + if( m_iSelected >= 0 && m_iSelected < ( int )m_Items.GetSize() ) + { + DXUTComboBoxItem* pItem = m_Items.GetAt( m_iSelected ); + if( pItem != NULL ) + { + m_pDialog->DrawText( pItem->strText, pElement, &m_rcText, false, -1, true ); + + } + } +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTComboBox::AddItem( const WCHAR* strText, void* pData ) +{ + // Validate parameters + if( strText == NULL ) + { + return E_INVALIDARG; + } + + // Create a new item and set the data + DXUTComboBoxItem* pItem = new DXUTComboBoxItem; + if( pItem == NULL ) + { + return DXTRACE_ERR_MSGBOX( L"new", E_OUTOFMEMORY ); + } + + ZeroMemory( pItem, sizeof( DXUTComboBoxItem ) ); + wcscpy_s( pItem->strText, 256, strText ); + pItem->pData = pData; + + m_Items.Add( pItem ); + + // Update the scroll bar with new range + m_ScrollBar.SetTrackRange( 0, m_Items.GetSize() ); + + // If this is the only item in the list, it's selected + if( GetNumItems() == 1 ) + { + m_iSelected = 0; + m_iFocused = 0; + m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, false, this ); + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTComboBox::RemoveItem( UINT index ) +{ + DXUTComboBoxItem* pItem = m_Items.GetAt( index ); + SAFE_DELETE( pItem ); + m_Items.Remove( index ); + m_ScrollBar.SetTrackRange( 0, m_Items.GetSize() ); + if( m_iSelected >= m_Items.GetSize() ) + m_iSelected = m_Items.GetSize() - 1; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTComboBox::RemoveAllItems() +{ + for( int i = 0; i < m_Items.GetSize(); i++ ) + { + DXUTComboBoxItem* pItem = m_Items.GetAt( i ); + SAFE_DELETE( pItem ); + } + + m_Items.RemoveAll(); + m_ScrollBar.SetTrackRange( 0, 1 ); + m_iFocused = m_iSelected = -1; +} + + + +//-------------------------------------------------------------------------------------- +bool CDXUTComboBox::ContainsItem( const WCHAR* strText, UINT iStart ) +{ + return ( -1 != FindItem( strText, iStart ) ); +} + + +//-------------------------------------------------------------------------------------- +int CDXUTComboBox::FindItem( const WCHAR* strText, UINT iStart ) +{ + if( strText == NULL ) + return -1; + + for( int i = iStart; i < m_Items.GetSize(); i++ ) + { + DXUTComboBoxItem* pItem = m_Items.GetAt( i ); + + if( 0 == wcscmp( pItem->strText, strText ) ) + { + return i; + } + } + + return -1; +} + + +//-------------------------------------------------------------------------------------- +void* CDXUTComboBox::GetSelectedData() +{ + if( m_iSelected < 0 ) + return NULL; + + DXUTComboBoxItem* pItem = m_Items.GetAt( m_iSelected ); + return pItem->pData; +} + + +//-------------------------------------------------------------------------------------- +DXUTComboBoxItem* CDXUTComboBox::GetSelectedItem() +{ + if( m_iSelected < 0 ) + return NULL; + + return m_Items.GetAt( m_iSelected ); +} + + +//-------------------------------------------------------------------------------------- +void* CDXUTComboBox::GetItemData( const WCHAR* strText ) +{ + int index = FindItem( strText ); + if( index == -1 ) + { + return NULL; + } + + DXUTComboBoxItem* pItem = m_Items.GetAt( index ); + if( pItem == NULL ) + { + DXTRACE_ERR( L"CGrowableArray::GetAt", E_FAIL ); + return NULL; + } + + return pItem->pData; +} + + +//-------------------------------------------------------------------------------------- +void* CDXUTComboBox::GetItemData( int nIndex ) +{ + if( nIndex < 0 || nIndex >= m_Items.GetSize() ) + return NULL; + + return m_Items.GetAt( nIndex )->pData; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTComboBox::SetSelectedByIndex( UINT index ) +{ + if( index >= GetNumItems() ) + return E_INVALIDARG; + + m_iFocused = m_iSelected = index; + m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, false, this ); + + return S_OK; +} + + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTComboBox::SetSelectedByText( const WCHAR* strText ) +{ + if( strText == NULL ) + return E_INVALIDARG; + + int index = FindItem( strText ); + if( index == -1 ) + return E_FAIL; + + m_iFocused = m_iSelected = index; + m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, false, this ); + + return S_OK; +} + + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTComboBox::SetSelectedByData( void* pData ) +{ + for( int i = 0; i < m_Items.GetSize(); i++ ) + { + DXUTComboBoxItem* pItem = m_Items.GetAt( i ); + + if( pItem->pData == pData ) + { + m_iFocused = m_iSelected = i; + m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, false, this ); + return S_OK; + } + } + + return E_FAIL; +} + + + +//-------------------------------------------------------------------------------------- +CDXUTSlider::CDXUTSlider( CDXUTDialog* pDialog ) +{ + m_Type = DXUT_CONTROL_SLIDER; + m_pDialog = pDialog; + + m_nMin = 0; + m_nMax = 100; + m_nValue = 50; + + m_bPressed = false; +} + + +//-------------------------------------------------------------------------------------- +BOOL CDXUTSlider::ContainsPoint( POINT pt ) +{ + return ( PtInRect( &m_rcBoundingBox, pt ) || + PtInRect( &m_rcButton, pt ) ); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTSlider::UpdateRects() +{ + CDXUTControl::UpdateRects(); + + m_rcButton = m_rcBoundingBox; + m_rcButton.right = m_rcButton.left + RectHeight( m_rcButton ); + OffsetRect( &m_rcButton, -RectWidth( m_rcButton ) / 2, 0 ); + + m_nButtonX = ( int )( ( m_nValue - m_nMin ) * ( float )RectWidth( m_rcBoundingBox ) / ( m_nMax - m_nMin ) ); + OffsetRect( &m_rcButton, m_nButtonX, 0 ); +} + +int CDXUTSlider::ValueFromPos( int x ) +{ + float fValuePerPixel = ( float )( m_nMax - m_nMin ) / RectWidth( m_rcBoundingBox ); + return ( int )( 0.5f + m_nMin + fValuePerPixel * ( x - m_rcBoundingBox.left ) ); +} + +//-------------------------------------------------------------------------------------- +bool CDXUTSlider::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + if( !m_bEnabled || !m_bVisible ) + return false; + + switch( uMsg ) + { + case WM_KEYDOWN: + { + switch( wParam ) + { + case VK_HOME: + SetValueInternal( m_nMin, true ); + return true; + + case VK_END: + SetValueInternal( m_nMax, true ); + return true; + + case VK_LEFT: + case VK_DOWN: + SetValueInternal( m_nValue - 1, true ); + return true; + + case VK_RIGHT: + case VK_UP: + SetValueInternal( m_nValue + 1, true ); + return true; + + case VK_NEXT: + SetValueInternal( m_nValue - ( 10 > ( m_nMax - m_nMin ) / 10 ? 10 : ( m_nMax - m_nMin ) / 10 ), + true ); + return true; + + case VK_PRIOR: + SetValueInternal( m_nValue + ( 10 > ( m_nMax - m_nMin ) / 10 ? 10 : ( m_nMax - m_nMin ) / 10 ), + true ); + return true; + } + break; + } + } + + + return false; +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTSlider::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ) +{ + if( !m_bEnabled || !m_bVisible ) + return false; + + switch( uMsg ) + { + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + { + if( PtInRect( &m_rcButton, pt ) ) + { + // Pressed while inside the control + m_bPressed = true; + SetCapture( DXUTGetHWND() ); + + m_nDragX = pt.x; + //m_nDragY = pt.y; + m_nDragOffset = m_nButtonX - m_nDragX; + + //m_nDragValue = m_nValue; + + if( !m_bHasFocus ) + m_pDialog->RequestFocus( this ); + + return true; + } + + if( PtInRect( &m_rcBoundingBox, pt ) ) + { + m_nDragX = pt.x; + m_nDragOffset = 0; + m_bPressed = true; + + if( !m_bHasFocus ) + m_pDialog->RequestFocus( this ); + + if( pt.x > m_nButtonX + m_x ) + { + SetValueInternal( m_nValue + 1, true ); + return true; + } + + if( pt.x < m_nButtonX + m_x ) + { + SetValueInternal( m_nValue - 1, true ); + return true; + } + } + + break; + } + + case WM_LBUTTONUP: + { + if( m_bPressed ) + { + m_bPressed = false; + ReleaseCapture(); + m_pDialog->SendEvent( EVENT_SLIDER_VALUE_CHANGED_UP, true, this ); + + return true; + } + + break; + } + + case WM_MOUSEMOVE: + { + if( m_bPressed ) + { + SetValueInternal( ValueFromPos( m_x + pt.x + m_nDragOffset ), true ); + return true; + } + + break; + } + + case WM_MOUSEWHEEL: + { + int nScrollAmount = int( ( short )HIWORD( wParam ) ) / WHEEL_DELTA; + SetValueInternal( m_nValue - nScrollAmount, true ); + return true; + } + }; + + return false; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTSlider::SetRange( int nMin, int nMax ) +{ + m_nMin = nMin; + m_nMax = nMax; + + SetValueInternal( m_nValue, false ); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTSlider::SetValueInternal( int nValue, bool bFromInput ) +{ + // Clamp to range + nValue = __max( m_nMin, nValue ); + nValue = __min( m_nMax, nValue ); + + if( nValue == m_nValue ) + return; + + m_nValue = nValue; + UpdateRects(); + + m_pDialog->SendEvent( EVENT_SLIDER_VALUE_CHANGED, bFromInput, this ); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTSlider::Render( float fElapsedTime ) +{ + if( m_bVisible == false ) + return; + + int nOffsetX = 0; + int nOffsetY = 0; + + DXUT_CONTROL_STATE iState = DXUT_STATE_NORMAL; + + if( m_bVisible == false ) + { + iState = DXUT_STATE_HIDDEN; + } + else if( m_bEnabled == false ) + { + iState = DXUT_STATE_DISABLED; + } + else if( m_bPressed ) + { + iState = DXUT_STATE_PRESSED; + + nOffsetX = 1; + nOffsetY = 2; + } + else if( m_bMouseOver ) + { + iState = DXUT_STATE_MOUSEOVER; + + nOffsetX = -1; + nOffsetY = -2; + } + else if( m_bHasFocus ) + { + iState = DXUT_STATE_FOCUS; + } + + float fBlendRate = ( iState == DXUT_STATE_PRESSED ) ? 0.0f : 0.8f; + + CDXUTElement* pElement = m_Elements.GetAt( 0 ); + + // Blend current color + pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate ); + m_pDialog->DrawSprite( pElement, &m_rcBoundingBox, DXUT_FAR_BUTTON_DEPTH ); + + //TODO: remove magic numbers + pElement = m_Elements.GetAt( 1 ); + + // Blend current color + pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate ); + m_pDialog->DrawSprite( pElement, &m_rcButton, DXUT_NEAR_BUTTON_DEPTH ); +} + + +//-------------------------------------------------------------------------------------- +// CDXUTScrollBar class +//-------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------------- +CDXUTScrollBar::CDXUTScrollBar( CDXUTDialog* pDialog ) +{ + m_Type = DXUT_CONTROL_SCROLLBAR; + m_pDialog = pDialog; + + m_bShowThumb = true; + m_bDrag = false; + + SetRect( &m_rcUpButton, 0, 0, 0, 0 ); + SetRect( &m_rcDownButton, 0, 0, 0, 0 ); + SetRect( &m_rcTrack, 0, 0, 0, 0 ); + SetRect( &m_rcThumb, 0, 0, 0, 0 ); + m_nPosition = 0; + m_nPageSize = 1; + m_nStart = 0; + m_nEnd = 1; + m_Arrow = CLEAR; + m_dArrowTS = 0.0; +} + + +//-------------------------------------------------------------------------------------- +CDXUTScrollBar::~CDXUTScrollBar() +{ +} + + +//-------------------------------------------------------------------------------------- +void CDXUTScrollBar::UpdateRects() +{ + CDXUTControl::UpdateRects(); + + // Make the buttons square + + SetRect( &m_rcUpButton, m_rcBoundingBox.left, m_rcBoundingBox.top, + m_rcBoundingBox.right, m_rcBoundingBox.top + RectWidth( m_rcBoundingBox ) ); + SetRect( &m_rcDownButton, m_rcBoundingBox.left, m_rcBoundingBox.bottom - RectWidth( m_rcBoundingBox ), + m_rcBoundingBox.right, m_rcBoundingBox.bottom ); + SetRect( &m_rcTrack, m_rcUpButton.left, m_rcUpButton.bottom, + m_rcDownButton.right, m_rcDownButton.top ); + m_rcThumb.left = m_rcUpButton.left; + m_rcThumb.right = m_rcUpButton.right; + + UpdateThumbRect(); +} + + +//-------------------------------------------------------------------------------------- +// Compute the dimension of the scroll thumb +void CDXUTScrollBar::UpdateThumbRect() +{ + if( m_nEnd - m_nStart > m_nPageSize ) + { + int nThumbHeight = __max( RectHeight( m_rcTrack ) * m_nPageSize / ( m_nEnd - m_nStart ), + SCROLLBAR_MINTHUMBSIZE ); + int nMaxPosition = m_nEnd - m_nStart - m_nPageSize; + m_rcThumb.top = m_rcTrack.top + ( m_nPosition - m_nStart ) * ( RectHeight( m_rcTrack ) - nThumbHeight ) + / nMaxPosition; + m_rcThumb.bottom = m_rcThumb.top + nThumbHeight; + m_bShowThumb = true; + + } + else + { + // No content to scroll + m_rcThumb.bottom = m_rcThumb.top; + m_bShowThumb = false; + } +} + + +//-------------------------------------------------------------------------------------- +// Scroll() scrolls by nDelta items. A positive value scrolls down, while a negative +// value scrolls up. +void CDXUTScrollBar::Scroll( int nDelta ) +{ + // Perform scroll + m_nPosition += nDelta; + + // Cap position + Cap(); + + // Update thumb position + UpdateThumbRect(); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTScrollBar::ShowItem( int nIndex ) +{ + // Cap the index + + if( nIndex < 0 ) + nIndex = 0; + + if( nIndex >= m_nEnd ) + nIndex = m_nEnd - 1; + + // Adjust position + + if( m_nPosition > nIndex ) + m_nPosition = nIndex; + else if( m_nPosition + m_nPageSize <= nIndex ) + m_nPosition = nIndex - m_nPageSize + 1; + + UpdateThumbRect(); +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTScrollBar::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + return false; +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTScrollBar::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ) +{ + static int ThumbOffsetY; + + m_LastMouse = pt; + switch( uMsg ) + { + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + { + // Check for click on up button + + if( PtInRect( &m_rcUpButton, pt ) ) + { + SetCapture( DXUTGetHWND() ); + if( m_nPosition > m_nStart ) + --m_nPosition; + UpdateThumbRect(); + m_Arrow = CLICKED_UP; + m_dArrowTS = DXUTGetTime(); + return true; + } + + // Check for click on down button + + if( PtInRect( &m_rcDownButton, pt ) ) + { + SetCapture( DXUTGetHWND() ); + if( m_nPosition + m_nPageSize < m_nEnd ) + ++m_nPosition; + UpdateThumbRect(); + m_Arrow = CLICKED_DOWN; + m_dArrowTS = DXUTGetTime(); + return true; + } + + // Check for click on thumb + + if( PtInRect( &m_rcThumb, pt ) ) + { + SetCapture( DXUTGetHWND() ); + m_bDrag = true; + ThumbOffsetY = pt.y - m_rcThumb.top; + return true; + } + + // Check for click on track + + if( m_rcThumb.left <= pt.x && + m_rcThumb.right > pt.x ) + { + SetCapture( DXUTGetHWND() ); + if( m_rcThumb.top > pt.y && + m_rcTrack.top <= pt.y ) + { + Scroll( -( m_nPageSize - 1 ) ); + return true; + } + else if( m_rcThumb.bottom <= pt.y && + m_rcTrack.bottom > pt.y ) + { + Scroll( m_nPageSize - 1 ); + return true; + } + } + + break; + } + + case WM_LBUTTONUP: + { + m_bDrag = false; + ReleaseCapture(); + UpdateThumbRect(); + m_Arrow = CLEAR; + break; + } + + case WM_MOUSEMOVE: + { + if( m_bDrag ) + { + m_rcThumb.bottom += pt.y - ThumbOffsetY - m_rcThumb.top; + m_rcThumb.top = pt.y - ThumbOffsetY; + if( m_rcThumb.top < m_rcTrack.top ) + OffsetRect( &m_rcThumb, 0, m_rcTrack.top - m_rcThumb.top ); + else if( m_rcThumb.bottom > m_rcTrack.bottom ) + OffsetRect( &m_rcThumb, 0, m_rcTrack.bottom - m_rcThumb.bottom ); + + // Compute first item index based on thumb position + + int nMaxFirstItem = m_nEnd - m_nStart - m_nPageSize; // Largest possible index for first item + int nMaxThumb = RectHeight( m_rcTrack ) - RectHeight( m_rcThumb ); // Largest possible thumb position from the top + + m_nPosition = m_nStart + + ( m_rcThumb.top - m_rcTrack.top + + nMaxThumb / ( nMaxFirstItem * 2 ) ) * // Shift by half a row to avoid last row covered by only one pixel + nMaxFirstItem / nMaxThumb; + + return true; + } + + break; + } + } + + return false; +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTScrollBar::MsgProc( UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + if( WM_CAPTURECHANGED == uMsg ) + { + // The application just lost mouse capture. We may not have gotten + // the WM_MOUSEUP message, so reset m_bDrag here. + if( ( HWND )lParam != DXUTGetHWND() ) + m_bDrag = false; + } + + return false; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTScrollBar::Render( float fElapsedTime ) +{ + if( m_bVisible == false ) + return; + + // Check if the arrow button has been held for a while. + // If so, update the thumb position to simulate repeated + // scroll. + if( m_Arrow != CLEAR ) + { + double dCurrTime = DXUTGetTime(); + if( PtInRect( &m_rcUpButton, m_LastMouse ) ) + { + switch( m_Arrow ) + { + case CLICKED_UP: + if( SCROLLBAR_ARROWCLICK_DELAY < dCurrTime - m_dArrowTS ) + { + Scroll( -1 ); + m_Arrow = HELD_UP; + m_dArrowTS = dCurrTime; + } + break; + case HELD_UP: + if( SCROLLBAR_ARROWCLICK_REPEAT < dCurrTime - m_dArrowTS ) + { + Scroll( -1 ); + m_dArrowTS = dCurrTime; + } + break; + } + } + else if( PtInRect( &m_rcDownButton, m_LastMouse ) ) + { + switch( m_Arrow ) + { + case CLICKED_DOWN: + if( SCROLLBAR_ARROWCLICK_DELAY < dCurrTime - m_dArrowTS ) + { + Scroll( 1 ); + m_Arrow = HELD_DOWN; + m_dArrowTS = dCurrTime; + } + break; + case HELD_DOWN: + if( SCROLLBAR_ARROWCLICK_REPEAT < dCurrTime - m_dArrowTS ) + { + Scroll( 1 ); + m_dArrowTS = dCurrTime; + } + break; + } + } + } + + DXUT_CONTROL_STATE iState = DXUT_STATE_NORMAL; + + if( m_bVisible == false ) + iState = DXUT_STATE_HIDDEN; + else if( m_bEnabled == false || m_bShowThumb == false ) + iState = DXUT_STATE_DISABLED; + else if( m_bMouseOver ) + iState = DXUT_STATE_MOUSEOVER; + else if( m_bHasFocus ) + iState = DXUT_STATE_FOCUS; + + + float fBlendRate = ( iState == DXUT_STATE_PRESSED ) ? 0.0f : 0.8f; + + // Background track layer + CDXUTElement* pElement = m_Elements.GetAt( 0 ); + + // Blend current color + pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate ); + m_pDialog->DrawSprite( pElement, &m_rcTrack, DXUT_FAR_BUTTON_DEPTH ); + + // Up Arrow + pElement = m_Elements.GetAt( 1 ); + + // Blend current color + pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate ); + m_pDialog->DrawSprite( pElement, &m_rcUpButton, DXUT_NEAR_BUTTON_DEPTH ); + + // Down Arrow + pElement = m_Elements.GetAt( 2 ); + + // Blend current color + pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate ); + m_pDialog->DrawSprite( pElement, &m_rcDownButton, DXUT_NEAR_BUTTON_DEPTH ); + + // Thumb button + pElement = m_Elements.GetAt( 3 ); + + // Blend current color + pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate ); + m_pDialog->DrawSprite( pElement, &m_rcThumb, DXUT_NEAR_BUTTON_DEPTH ); + +} + + +//-------------------------------------------------------------------------------------- +void CDXUTScrollBar::SetTrackRange( int nStart, int nEnd ) +{ + m_nStart = nStart; m_nEnd = nEnd; + Cap(); + UpdateThumbRect(); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTScrollBar::Cap() // Clips position at boundaries. Ensures it stays within legal range. +{ + if( m_nPosition < m_nStart || + m_nEnd - m_nStart <= m_nPageSize ) + { + m_nPosition = m_nStart; + } + else if( m_nPosition + m_nPageSize > m_nEnd ) + m_nPosition = m_nEnd - m_nPageSize; +} + +//-------------------------------------------------------------------------------------- +// CDXUTListBox class +//-------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------------- +CDXUTListBox::CDXUTListBox( CDXUTDialog* pDialog ) : m_ScrollBar( pDialog ) +{ + m_Type = DXUT_CONTROL_LISTBOX; + m_pDialog = pDialog; + + m_dwStyle = 0; + m_nSBWidth = 16; + m_nSelected = -1; + m_nSelStart = 0; + m_bDrag = false; + m_nBorder = 6; + m_nMargin = 5; + m_nTextHeight = 0; +} + + +//-------------------------------------------------------------------------------------- +CDXUTListBox::~CDXUTListBox() +{ + RemoveAllItems(); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTListBox::UpdateRects() +{ + CDXUTControl::UpdateRects(); + + m_rcSelection = m_rcBoundingBox; + m_rcSelection.right -= m_nSBWidth; + InflateRect( &m_rcSelection, -m_nBorder, -m_nBorder ); + m_rcText = m_rcSelection; + InflateRect( &m_rcText, -m_nMargin, 0 ); + + // Update the scrollbar's rects + m_ScrollBar.SetLocation( m_rcBoundingBox.right - m_nSBWidth, m_rcBoundingBox.top ); + m_ScrollBar.SetSize( m_nSBWidth, m_height ); + DXUTFontNode* pFontNode = m_pDialog->GetManager()->GetFontNode( m_Elements.GetAt( 0 )->iFont ); + if( pFontNode && pFontNode->nHeight ) + { + m_ScrollBar.SetPageSize( RectHeight( m_rcText ) / pFontNode->nHeight ); + + // The selected item may have been scrolled off the page. + // Ensure that it is in page again. + m_ScrollBar.ShowItem( m_nSelected ); + } +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTListBox::AddItem( const WCHAR* wszText, void* pData ) +{ + DXUTListBoxItem* pNewItem = new DXUTListBoxItem; + if( !pNewItem ) + return E_OUTOFMEMORY; + + wcscpy_s( pNewItem->strText, 256, wszText ); + pNewItem->pData = pData; + SetRect( &pNewItem->rcActive, 0, 0, 0, 0 ); + pNewItem->bSelected = false; + + HRESULT hr = m_Items.Add( pNewItem ); + if( FAILED( hr ) ) + { + SAFE_DELETE( pNewItem ); + } + else + { + m_ScrollBar.SetTrackRange( 0, m_Items.GetSize() ); + } + + return hr; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTListBox::InsertItem( int nIndex, const WCHAR* wszText, void* pData ) +{ + DXUTListBoxItem* pNewItem = new DXUTListBoxItem; + if( !pNewItem ) + return E_OUTOFMEMORY; + + wcscpy_s( pNewItem->strText, 256, wszText ); + pNewItem->pData = pData; + SetRect( &pNewItem->rcActive, 0, 0, 0, 0 ); + pNewItem->bSelected = false; + + HRESULT hr = m_Items.Insert( nIndex, pNewItem ); + if( SUCCEEDED( hr ) ) + m_ScrollBar.SetTrackRange( 0, m_Items.GetSize() ); + else + SAFE_DELETE( pNewItem ); + + return hr; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTListBox::RemoveItem( int nIndex ) +{ + if( nIndex < 0 || nIndex >= ( int )m_Items.GetSize() ) + return; + + DXUTListBoxItem* pItem = m_Items.GetAt( nIndex ); + + delete pItem; + m_Items.Remove( nIndex ); + m_ScrollBar.SetTrackRange( 0, m_Items.GetSize() ); + if( m_nSelected >= ( int )m_Items.GetSize() ) + m_nSelected = m_Items.GetSize() - 1; + + m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION, true, this ); +} + + + + + +//-------------------------------------------------------------------------------------- +void CDXUTListBox::RemoveAllItems() +{ + for( int i = 0; i < m_Items.GetSize(); ++i ) + { + DXUTListBoxItem* pItem = m_Items.GetAt( i ); + delete pItem; + } + + m_Items.RemoveAll(); + m_ScrollBar.SetTrackRange( 0, 1 ); +} + + +//-------------------------------------------------------------------------------------- +DXUTListBoxItem* CDXUTListBox::GetItem( int nIndex ) +{ + if( nIndex < 0 || nIndex >= ( int )m_Items.GetSize() ) + return NULL; + + return m_Items[nIndex]; +} + + +//-------------------------------------------------------------------------------------- +// For single-selection listbox, returns the index of the selected item. +// For multi-selection, returns the first selected item after the nPreviousSelected position. +// To search for the first selected item, the app passes -1 for nPreviousSelected. For +// subsequent searches, the app passes the returned index back to GetSelectedIndex as. +// nPreviousSelected. +// Returns -1 on error or if no item is selected. +int CDXUTListBox::GetSelectedIndex( int nPreviousSelected ) +{ + if( nPreviousSelected < -1 ) + return -1; + + if( m_dwStyle & MULTISELECTION ) + { + // Multiple selection enabled. Search for the next item with the selected flag. + for( int i = nPreviousSelected + 1; i < ( int )m_Items.GetSize(); ++i ) + { + DXUTListBoxItem* pItem = m_Items.GetAt( i ); + + if( pItem->bSelected ) + return i; + } + + return -1; + } + else + { + // Single selection + return m_nSelected; + } +} + + +//-------------------------------------------------------------------------------------- +void CDXUTListBox::SelectItem( int nNewIndex ) +{ + // If no item exists, do nothing. + if( m_Items.GetSize() == 0 ) + return; + + int nOldSelected = m_nSelected; + + // Adjust m_nSelected + m_nSelected = nNewIndex; + + // Perform capping + if( m_nSelected < 0 ) + m_nSelected = 0; + if( m_nSelected >= ( int )m_Items.GetSize() ) + m_nSelected = m_Items.GetSize() - 1; + + if( nOldSelected != m_nSelected ) + { + if( m_dwStyle & MULTISELECTION ) + { + m_Items[m_nSelected]->bSelected = true; + } + + // Update selection start + m_nSelStart = m_nSelected; + + // Adjust scroll bar + m_ScrollBar.ShowItem( m_nSelected ); + } + + m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION, true, this ); +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTListBox::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + if( !m_bEnabled || !m_bVisible ) + return false; + + // Let the scroll bar have a chance to handle it first + if( m_ScrollBar.HandleKeyboard( uMsg, wParam, lParam ) ) + return true; + + switch( uMsg ) + { + case WM_KEYDOWN: + switch( wParam ) + { + case VK_UP: + case VK_DOWN: + case VK_NEXT: + case VK_PRIOR: + case VK_HOME: + case VK_END: + { + // If no item exists, do nothing. + if( m_Items.GetSize() == 0 ) + return true; + + int nOldSelected = m_nSelected; + + // Adjust m_nSelected + switch( wParam ) + { + case VK_UP: + --m_nSelected; break; + case VK_DOWN: + ++m_nSelected; break; + case VK_NEXT: + m_nSelected += m_ScrollBar.GetPageSize() - 1; break; + case VK_PRIOR: + m_nSelected -= m_ScrollBar.GetPageSize() - 1; break; + case VK_HOME: + m_nSelected = 0; break; + case VK_END: + m_nSelected = m_Items.GetSize() - 1; break; + } + + // Perform capping + if( m_nSelected < 0 ) + m_nSelected = 0; + if( m_nSelected >= ( int )m_Items.GetSize() ) + m_nSelected = m_Items.GetSize() - 1; + + if( nOldSelected != m_nSelected ) + { + if( m_dwStyle & MULTISELECTION ) + { + // Multiple selection + + // Clear all selection + for( int i = 0; i < ( int )m_Items.GetSize(); ++i ) + { + DXUTListBoxItem* pItem = m_Items[i]; + pItem->bSelected = false; + } + + if( GetKeyState( VK_SHIFT ) < 0 ) + { + // Select all items from m_nSelStart to + // m_nSelected + int nEnd = __max( m_nSelStart, m_nSelected ); + + for( int n = __min( m_nSelStart, m_nSelected ); n <= nEnd; ++n ) + m_Items[n]->bSelected = true; + } + else + { + m_Items[m_nSelected]->bSelected = true; + + // Update selection start + m_nSelStart = m_nSelected; + } + } + else + m_nSelStart = m_nSelected; + + // Adjust scroll bar + + m_ScrollBar.ShowItem( m_nSelected ); + + // Send notification + + m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION, true, this ); + } + return true; + } + + // Space is the hotkey for double-clicking an item. + // + case VK_SPACE: + m_pDialog->SendEvent( EVENT_LISTBOX_ITEM_DBLCLK, true, this ); + return true; + } + break; + } + + return false; +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTListBox::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ) +{ + if( !m_bEnabled || !m_bVisible ) + return false; + + // First acquire focus + if( WM_LBUTTONDOWN == uMsg ) + if( !m_bHasFocus ) + m_pDialog->RequestFocus( this ); + + // Let the scroll bar handle it first. + if( m_ScrollBar.HandleMouse( uMsg, pt, wParam, lParam ) ) + return true; + + switch( uMsg ) + { + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + // Check for clicks in the text area + if( m_Items.GetSize() > 0 && PtInRect( &m_rcSelection, pt ) ) + { + // Compute the index of the clicked item + + int nClicked; + if( m_nTextHeight ) + nClicked = m_ScrollBar.GetTrackPos() + ( pt.y - m_rcText.top ) / m_nTextHeight; + else + nClicked = -1; + + // Only proceed if the click falls on top of an item. + + if( nClicked >= m_ScrollBar.GetTrackPos() && + nClicked < ( int )m_Items.GetSize() && + nClicked < m_ScrollBar.GetTrackPos() + m_ScrollBar.GetPageSize() ) + { + SetCapture( DXUTGetHWND() ); + m_bDrag = true; + + // If this is a double click, fire off an event and exit + // since the first click would have taken care of the selection + // updating. + if( uMsg == WM_LBUTTONDBLCLK ) + { + m_pDialog->SendEvent( EVENT_LISTBOX_ITEM_DBLCLK, true, this ); + return true; + } + + m_nSelected = nClicked; + if( !( wParam & MK_SHIFT ) ) + m_nSelStart = m_nSelected; + + // If this is a multi-selection listbox, update per-item + // selection data. + + if( m_dwStyle & MULTISELECTION ) + { + // Determine behavior based on the state of Shift and Ctrl + + DXUTListBoxItem* pSelItem = m_Items.GetAt( m_nSelected ); + if( ( wParam & ( MK_SHIFT | MK_CONTROL ) ) == MK_CONTROL ) + { + // Control click. Reverse the selection of this item. + + pSelItem->bSelected = !pSelItem->bSelected; + } + else if( ( wParam & ( MK_SHIFT | MK_CONTROL ) ) == MK_SHIFT ) + { + // Shift click. Set the selection for all items + // from last selected item to the current item. + // Clear everything else. + + int nBegin = __min( m_nSelStart, m_nSelected ); + int nEnd = __max( m_nSelStart, m_nSelected ); + + for( int i = 0; i < nBegin; ++i ) + { + DXUTListBoxItem* pItem = m_Items.GetAt( i ); + pItem->bSelected = false; + } + + for( int i = nEnd + 1; i < ( int )m_Items.GetSize(); ++i ) + { + DXUTListBoxItem* pItem = m_Items.GetAt( i ); + pItem->bSelected = false; + } + + for( int i = nBegin; i <= nEnd; ++i ) + { + DXUTListBoxItem* pItem = m_Items.GetAt( i ); + pItem->bSelected = true; + } + } + else if( ( wParam & ( MK_SHIFT | MK_CONTROL ) ) == ( MK_SHIFT | MK_CONTROL ) ) + { + // Control-Shift-click. + + // The behavior is: + // Set all items from m_nSelStart to m_nSelected to + // the same state as m_nSelStart, not including m_nSelected. + // Set m_nSelected to selected. + + int nBegin = __min( m_nSelStart, m_nSelected ); + int nEnd = __max( m_nSelStart, m_nSelected ); + + // The two ends do not need to be set here. + + bool bLastSelected = m_Items.GetAt( m_nSelStart )->bSelected; + for( int i = nBegin + 1; i < nEnd; ++i ) + { + DXUTListBoxItem* pItem = m_Items.GetAt( i ); + pItem->bSelected = bLastSelected; + } + + pSelItem->bSelected = true; + + // Restore m_nSelected to the previous value + // This matches the Windows behavior + + m_nSelected = m_nSelStart; + } + else + { + // Simple click. Clear all items and select the clicked + // item. + + + for( int i = 0; i < ( int )m_Items.GetSize(); ++i ) + { + DXUTListBoxItem* pItem = m_Items.GetAt( i ); + pItem->bSelected = false; + } + + pSelItem->bSelected = true; + } + } // End of multi-selection case + + m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION, true, this ); + } + + return true; + } + break; + + case WM_LBUTTONUP: + { + ReleaseCapture(); + m_bDrag = false; + + if( m_nSelected != -1 ) + { + // Set all items between m_nSelStart and m_nSelected to + // the same state as m_nSelStart + int nEnd = __max( m_nSelStart, m_nSelected ); + + for( int n = __min( m_nSelStart, m_nSelected ) + 1; n < nEnd; ++n ) + m_Items[n]->bSelected = m_Items[m_nSelStart]->bSelected; + m_Items[m_nSelected]->bSelected = m_Items[m_nSelStart]->bSelected; + + // If m_nSelStart and m_nSelected are not the same, + // the user has dragged the mouse to make a selection. + // Notify the application of this. + if( m_nSelStart != m_nSelected ) + m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION, true, this ); + + m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION_END, true, this ); + } + return false; + } + + case WM_MOUSEMOVE: + if( m_bDrag ) + { + // Compute the index of the item below cursor + + int nItem; + if( m_nTextHeight ) + nItem = m_ScrollBar.GetTrackPos() + ( pt.y - m_rcText.top ) / m_nTextHeight; + else + nItem = -1; + + // Only proceed if the cursor is on top of an item. + + if( nItem >= ( int )m_ScrollBar.GetTrackPos() && + nItem < ( int )m_Items.GetSize() && + nItem < m_ScrollBar.GetTrackPos() + m_ScrollBar.GetPageSize() ) + { + m_nSelected = nItem; + m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION, true, this ); + } + else if( nItem < ( int )m_ScrollBar.GetTrackPos() ) + { + // User drags the mouse above window top + m_ScrollBar.Scroll( -1 ); + m_nSelected = m_ScrollBar.GetTrackPos(); + m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION, true, this ); + } + else if( nItem >= m_ScrollBar.GetTrackPos() + m_ScrollBar.GetPageSize() ) + { + // User drags the mouse below window bottom + m_ScrollBar.Scroll( 1 ); + m_nSelected = __min( ( int )m_Items.GetSize(), m_ScrollBar.GetTrackPos() + + m_ScrollBar.GetPageSize() ) - 1; + m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION, true, this ); + } + } + break; + + case WM_MOUSEWHEEL: + { + UINT uLines; + SystemParametersInfo( SPI_GETWHEELSCROLLLINES, 0, &uLines, 0 ); + int nScrollAmount = int( ( short )HIWORD( wParam ) ) / WHEEL_DELTA * uLines; + m_ScrollBar.Scroll( -nScrollAmount ); + return true; + } + } + + return false; +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTListBox::MsgProc( UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + if( WM_CAPTURECHANGED == uMsg ) + { + // The application just lost mouse capture. We may not have gotten + // the WM_MOUSEUP message, so reset m_bDrag here. + if( ( HWND )lParam != DXUTGetHWND() ) + m_bDrag = false; + } + + return false; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTListBox::Render( float fElapsedTime ) +{ + if( m_bVisible == false ) + return; + + CDXUTElement* pElement = m_Elements.GetAt( 0 ); + pElement->TextureColor.Blend( DXUT_STATE_NORMAL, fElapsedTime ); + pElement->FontColor.Blend( DXUT_STATE_NORMAL, fElapsedTime ); + + CDXUTElement* pSelElement = m_Elements.GetAt( 1 ); + pSelElement->TextureColor.Blend( DXUT_STATE_NORMAL, fElapsedTime ); + pSelElement->FontColor.Blend( DXUT_STATE_NORMAL, fElapsedTime ); + + m_pDialog->DrawSprite( pElement, &m_rcBoundingBox, DXUT_FAR_BUTTON_DEPTH ); + + // Render the text + if( m_Items.GetSize() > 0 ) + { + // Find out the height of a single line of text + RECT rc = m_rcText; + RECT rcSel = m_rcSelection; + rc.bottom = rc.top + m_pDialog->GetManager()->GetFontNode( pElement->iFont )->nHeight; + + // Update the line height formation + m_nTextHeight = rc.bottom - rc.top; + + static bool bSBInit; + if( !bSBInit ) + { + // Update the page size of the scroll bar + if( m_nTextHeight ) + m_ScrollBar.SetPageSize( RectHeight( m_rcText ) / m_nTextHeight ); + else + m_ScrollBar.SetPageSize( RectHeight( m_rcText ) ); + bSBInit = true; + } + + rc.right = m_rcText.right; + for( int i = m_ScrollBar.GetTrackPos(); i < ( int )m_Items.GetSize(); ++i ) + { + if( rc.bottom > m_rcText.bottom ) + break; + + DXUTListBoxItem* pItem = m_Items.GetAt( i ); + + // Determine if we need to render this item with the + // selected element. + bool bSelectedStyle = false; + + if( !( m_dwStyle & MULTISELECTION ) && i == m_nSelected ) + bSelectedStyle = true; + else if( m_dwStyle & MULTISELECTION ) + { + if( m_bDrag && + ( ( i >= m_nSelected && i < m_nSelStart ) || + ( i <= m_nSelected && i > m_nSelStart ) ) ) + bSelectedStyle = m_Items[m_nSelStart]->bSelected; + else if( pItem->bSelected ) + bSelectedStyle = true; + } + + if( bSelectedStyle ) + { + rcSel.top = rc.top; rcSel.bottom = rc.bottom; + m_pDialog->DrawSprite( pSelElement, &rcSel, DXUT_NEAR_BUTTON_DEPTH ); + m_pDialog->DrawText( pItem->strText, pSelElement, &rc ); + } + else + m_pDialog->DrawText( pItem->strText, pElement, &rc ); + + OffsetRect( &rc, 0, m_nTextHeight ); + } + } + + // Render the scroll bar + + m_ScrollBar.Render( fElapsedTime ); +} + + +// Static member initialization +HINSTANCE CUniBuffer::s_hDll = NULL; +HRESULT ( WINAPI*CUniBuffer::_ScriptApplyDigitSubstitution )( const SCRIPT_DIGITSUBSTITUTE*, SCRIPT_CONTROL*, + SCRIPT_STATE* ) = Dummy_ScriptApplyDigitSubstitution; +HRESULT ( WINAPI*CUniBuffer::_ScriptStringAnalyse )( HDC, const void*, int, int, int, DWORD, int, SCRIPT_CONTROL*, + SCRIPT_STATE*, const int*, SCRIPT_TABDEF*, const BYTE*, + SCRIPT_STRING_ANALYSIS* ) = Dummy_ScriptStringAnalyse; +HRESULT ( WINAPI*CUniBuffer::_ScriptStringCPtoX )( SCRIPT_STRING_ANALYSIS, int, BOOL, int* ) = Dummy_ScriptStringCPtoX; +HRESULT ( WINAPI*CUniBuffer::_ScriptStringXtoCP )( SCRIPT_STRING_ANALYSIS, int, int*, int* ) = Dummy_ScriptStringXtoCP; +HRESULT ( WINAPI*CUniBuffer::_ScriptStringFree )( SCRIPT_STRING_ANALYSIS* ) = Dummy_ScriptStringFree; +const SCRIPT_LOGATTR* ( WINAPI*CUniBuffer::_ScriptString_pLogAttr )( SCRIPT_STRING_ANALYSIS ) = + Dummy_ScriptString_pLogAttr; +const int* ( WINAPI*CUniBuffer::_ScriptString_pcOutChars )( SCRIPT_STRING_ANALYSIS ) = + Dummy_ScriptString_pcOutChars; +bool CDXUTEditBox::s_bHideCaret; // If true, we don't render the caret. + + + +//-------------------------------------------------------------------------------------- +// CDXUTEditBox class +//-------------------------------------------------------------------------------------- + +// When scrolling, EDITBOX_SCROLLEXTENT is reciprocal of the amount to scroll. +// If EDITBOX_SCROLLEXTENT = 4, then we scroll 1/4 of the control each time. +#define EDITBOX_SCROLLEXTENT 4 + +//-------------------------------------------------------------------------------------- +CDXUTEditBox::CDXUTEditBox( CDXUTDialog* pDialog ) +{ + m_Type = DXUT_CONTROL_EDITBOX; + m_pDialog = pDialog; + + m_nBorder = 5; // Default border width + m_nSpacing = 4; // Default spacing + + m_bCaretOn = true; + m_dfBlink = GetCaretBlinkTime() * 0.001f; + m_dfLastBlink = DXUTGetGlobalTimer()->GetAbsoluteTime(); + s_bHideCaret = false; + m_nFirstVisible = 0; + m_TextColor = D3DCOLOR_ARGB( 255, 16, 16, 16 ); + m_SelTextColor = D3DCOLOR_ARGB( 255, 255, 255, 255 ); + m_SelBkColor = D3DCOLOR_ARGB( 255, 40, 50, 92 ); + m_CaretColor = D3DCOLOR_ARGB( 255, 0, 0, 0 ); + m_nCaret = m_nSelStart = 0; + m_bInsertMode = true; + + m_bMouseDrag = false; +} + + +//-------------------------------------------------------------------------------------- +CDXUTEditBox::~CDXUTEditBox() +{ +} + + +//-------------------------------------------------------------------------------------- +// PlaceCaret: Set the caret to a character position, and adjust the scrolling if +// necessary. +//-------------------------------------------------------------------------------------- +void CDXUTEditBox::PlaceCaret( int nCP ) +{ + assert( nCP >= 0 && nCP <= m_Buffer.GetTextSize() ); + m_nCaret = nCP; + + // Obtain the X offset of the character. + int nX1st, nX, nX2; + m_Buffer.CPtoX( m_nFirstVisible, FALSE, &nX1st ); // 1st visible char + m_Buffer.CPtoX( nCP, FALSE, &nX ); // LEAD + // If nCP is the NULL terminator, get the leading edge instead of trailing. + if( nCP == m_Buffer.GetTextSize() ) + nX2 = nX; + else + m_Buffer.CPtoX( nCP, TRUE, &nX2 ); // TRAIL + + // If the left edge of the char is smaller than the left edge of the 1st visible char, + // we need to scroll left until this char is visible. + if( nX < nX1st ) + { + // Simply make the first visible character the char at the new caret position. + m_nFirstVisible = nCP; + } + else // If the right of the character is bigger than the offset of the control's + // right edge, we need to scroll right to this character. + if( nX2 > nX1st + RectWidth( m_rcText ) ) + { + // Compute the X of the new left-most pixel + int nXNewLeft = nX2 - RectWidth( m_rcText ); + + // Compute the char position of this character + int nCPNew1st, nNewTrail; + m_Buffer.XtoCP( nXNewLeft, &nCPNew1st, &nNewTrail ); + + // If this coordinate is not on a character border, + // start from the next character so that the caret + // position does not fall outside the text rectangle. + int nXNew1st; + m_Buffer.CPtoX( nCPNew1st, FALSE, &nXNew1st ); + if( nXNew1st < nXNewLeft ) + ++nCPNew1st; + + m_nFirstVisible = nCPNew1st; + } +} + + +//-------------------------------------------------------------------------------------- +void CDXUTEditBox::ClearText() +{ + m_Buffer.Clear(); + m_nFirstVisible = 0; + PlaceCaret( 0 ); + m_nSelStart = 0; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTEditBox::SetText( LPCWSTR wszText, bool bSelected ) +{ + assert( wszText != NULL ); + + m_Buffer.SetText( wszText ); + m_nFirstVisible = 0; + // Move the caret to the end of the text + PlaceCaret( m_Buffer.GetTextSize() ); + m_nSelStart = bSelected ? 0 : m_nCaret; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTEditBox::GetTextCopy( __out_ecount(bufferCount) LPWSTR strDest, + UINT bufferCount ) +{ + assert( strDest ); + + wcscpy_s( strDest, bufferCount, m_Buffer.GetBuffer() ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTEditBox::DeleteSelectionText() +{ + int nFirst = __min( m_nCaret, m_nSelStart ); + int nLast = __max( m_nCaret, m_nSelStart ); + // Update caret and selection + PlaceCaret( nFirst ); + m_nSelStart = m_nCaret; + // Remove the characters + for( int i = nFirst; i < nLast; ++i ) + m_Buffer.RemoveChar( nFirst ); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTEditBox::UpdateRects() +{ + CDXUTControl::UpdateRects(); + + // Update the text rectangle + m_rcText = m_rcBoundingBox; + // First inflate by m_nBorder to compute render rects + InflateRect( &m_rcText, -m_nBorder, -m_nBorder ); + + // Update the render rectangles + m_rcRender[0] = m_rcText; + SetRect( &m_rcRender[1], m_rcBoundingBox.left, m_rcBoundingBox.top, m_rcText.left, m_rcText.top ); + SetRect( &m_rcRender[2], m_rcText.left, m_rcBoundingBox.top, m_rcText.right, m_rcText.top ); + SetRect( &m_rcRender[3], m_rcText.right, m_rcBoundingBox.top, m_rcBoundingBox.right, m_rcText.top ); + SetRect( &m_rcRender[4], m_rcBoundingBox.left, m_rcText.top, m_rcText.left, m_rcText.bottom ); + SetRect( &m_rcRender[5], m_rcText.right, m_rcText.top, m_rcBoundingBox.right, m_rcText.bottom ); + SetRect( &m_rcRender[6], m_rcBoundingBox.left, m_rcText.bottom, m_rcText.left, m_rcBoundingBox.bottom ); + SetRect( &m_rcRender[7], m_rcText.left, m_rcText.bottom, m_rcText.right, m_rcBoundingBox.bottom ); + SetRect( &m_rcRender[8], m_rcText.right, m_rcText.bottom, m_rcBoundingBox.right, m_rcBoundingBox.bottom ); + + // Inflate further by m_nSpacing + InflateRect( &m_rcText, -m_nSpacing, -m_nSpacing ); +} + + +void CDXUTEditBox::CopyToClipboard() +{ + // Copy the selection text to the clipboard + if( m_nCaret != m_nSelStart && OpenClipboard( NULL ) ) + { + EmptyClipboard(); + + HGLOBAL hBlock = GlobalAlloc( GMEM_MOVEABLE, sizeof( WCHAR ) * ( m_Buffer.GetTextSize() + 1 ) ); + if( hBlock ) + { + WCHAR* pwszText = ( WCHAR* )GlobalLock( hBlock ); + if( pwszText ) + { + int nFirst = __min( m_nCaret, m_nSelStart ); + int nLast = __max( m_nCaret, m_nSelStart ); + if( nLast - nFirst > 0 ) + CopyMemory( pwszText, m_Buffer.GetBuffer() + nFirst, ( nLast - nFirst ) * sizeof( WCHAR ) ); + pwszText[nLast - nFirst] = L'\0'; // Terminate it + GlobalUnlock( hBlock ); + } + SetClipboardData( CF_UNICODETEXT, hBlock ); + } + CloseClipboard(); + // We must not free the object until CloseClipboard is called. + if( hBlock ) + GlobalFree( hBlock ); + } +} + + +void CDXUTEditBox::PasteFromClipboard() +{ + DeleteSelectionText(); + + if( OpenClipboard( NULL ) ) + { + HANDLE handle = GetClipboardData( CF_UNICODETEXT ); + if( handle ) + { + // Convert the ANSI string to Unicode, then + // insert to our buffer. + WCHAR* pwszText = ( WCHAR* )GlobalLock( handle ); + if( pwszText ) + { + // Copy all characters up to null. + if( m_Buffer.InsertString( m_nCaret, pwszText ) ) + PlaceCaret( m_nCaret + lstrlenW( pwszText ) ); + m_nSelStart = m_nCaret; + GlobalUnlock( handle ); + } + } + CloseClipboard(); + } +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTEditBox::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + if( !m_bEnabled || !m_bVisible ) + return false; + + bool bHandled = false; + + switch( uMsg ) + { + case WM_KEYDOWN: + { + switch( wParam ) + { + case VK_TAB: + // We don't process Tab in case keyboard input is enabled and the user + // wishes to Tab to other controls. + break; + + case VK_HOME: + PlaceCaret( 0 ); + if( GetKeyState( VK_SHIFT ) >= 0 ) + // Shift is not down. Update selection + // start along with the caret. + m_nSelStart = m_nCaret; + ResetCaretBlink(); + bHandled = true; + break; + + case VK_END: + PlaceCaret( m_Buffer.GetTextSize() ); + if( GetKeyState( VK_SHIFT ) >= 0 ) + // Shift is not down. Update selection + // start along with the caret. + m_nSelStart = m_nCaret; + ResetCaretBlink(); + bHandled = true; + break; + + case VK_INSERT: + if( GetKeyState( VK_CONTROL ) < 0 ) + { + // Control Insert. Copy to clipboard + CopyToClipboard(); + } + else if( GetKeyState( VK_SHIFT ) < 0 ) + { + // Shift Insert. Paste from clipboard + PasteFromClipboard(); + } + else + { + // Toggle caret insert mode + m_bInsertMode = !m_bInsertMode; + } + break; + + case VK_DELETE: + // Check if there is a text selection. + if( m_nCaret != m_nSelStart ) + { + DeleteSelectionText(); + m_pDialog->SendEvent( EVENT_EDITBOX_CHANGE, true, this ); + } + else + { + // Deleting one character + if( m_Buffer.RemoveChar( m_nCaret ) ) + m_pDialog->SendEvent( EVENT_EDITBOX_CHANGE, true, this ); + } + ResetCaretBlink(); + bHandled = true; + break; + + case VK_LEFT: + if( GetKeyState( VK_CONTROL ) < 0 ) + { + // Control is down. Move the caret to a new item + // instead of a character. + m_Buffer.GetPriorItemPos( m_nCaret, &m_nCaret ); + PlaceCaret( m_nCaret ); + } + else if( m_nCaret > 0 ) + PlaceCaret( m_nCaret - 1 ); + if( GetKeyState( VK_SHIFT ) >= 0 ) + // Shift is not down. Update selection + // start along with the caret. + m_nSelStart = m_nCaret; + ResetCaretBlink(); + bHandled = true; + break; + + case VK_RIGHT: + if( GetKeyState( VK_CONTROL ) < 0 ) + { + // Control is down. Move the caret to a new item + // instead of a character. + m_Buffer.GetNextItemPos( m_nCaret, &m_nCaret ); + PlaceCaret( m_nCaret ); + } + else if( m_nCaret < m_Buffer.GetTextSize() ) + PlaceCaret( m_nCaret + 1 ); + if( GetKeyState( VK_SHIFT ) >= 0 ) + // Shift is not down. Update selection + // start along with the caret. + m_nSelStart = m_nCaret; + ResetCaretBlink(); + bHandled = true; + break; + + case VK_UP: + case VK_DOWN: + // Trap up and down arrows so that the dialog + // does not switch focus to another control. + bHandled = true; + break; + + default: + bHandled = wParam != VK_ESCAPE; // Let the application handle Esc. + } + } + } + return bHandled; +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTEditBox::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ) +{ + if( !m_bEnabled || !m_bVisible ) + return false; + + switch( uMsg ) + { + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + { + if( !m_bHasFocus ) + m_pDialog->RequestFocus( this ); + + if( !ContainsPoint( pt ) ) + return false; + + m_bMouseDrag = true; + SetCapture( DXUTGetHWND() ); + // Determine the character corresponding to the coordinates. + int nCP, nTrail, nX1st; + m_Buffer.CPtoX( m_nFirstVisible, FALSE, &nX1st ); // X offset of the 1st visible char + if( SUCCEEDED( m_Buffer.XtoCP( pt.x - m_rcText.left + nX1st, &nCP, &nTrail ) ) ) + { + // Cap at the NULL character. + if( nTrail && nCP < m_Buffer.GetTextSize() ) + PlaceCaret( nCP + 1 ); + else + PlaceCaret( nCP ); + m_nSelStart = m_nCaret; + ResetCaretBlink(); + } + return true; + } + + case WM_LBUTTONUP: + ReleaseCapture(); + m_bMouseDrag = false; + break; + + case WM_MOUSEMOVE: + if( m_bMouseDrag ) + { + // Determine the character corresponding to the coordinates. + int nCP, nTrail, nX1st; + m_Buffer.CPtoX( m_nFirstVisible, FALSE, &nX1st ); // X offset of the 1st visible char + if( SUCCEEDED( m_Buffer.XtoCP( pt.x - m_rcText.left + nX1st, &nCP, &nTrail ) ) ) + { + // Cap at the NULL character. + if( nTrail && nCP < m_Buffer.GetTextSize() ) + PlaceCaret( nCP + 1 ); + else + PlaceCaret( nCP ); + } + } + break; + } + + return false; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTEditBox::OnFocusIn() +{ + CDXUTControl::OnFocusIn(); + + ResetCaretBlink(); +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTEditBox::MsgProc( UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + if( !m_bEnabled || !m_bVisible ) + return false; + + switch( uMsg ) + { + // Make sure that while editing, the keyup and keydown messages associated with + // WM_CHAR messages don't go to any non-focused controls or cameras + case WM_KEYUP: + case WM_KEYDOWN: + return true; + + case WM_CHAR: + { + switch( ( WCHAR )wParam ) + { + // Backspace + case VK_BACK: + { + // If there's a selection, treat this + // like a delete key. + if( m_nCaret != m_nSelStart ) + { + DeleteSelectionText(); + m_pDialog->SendEvent( EVENT_EDITBOX_CHANGE, true, this ); + } + else if( m_nCaret > 0 ) + { + // Move the caret, then delete the char. + PlaceCaret( m_nCaret - 1 ); + m_nSelStart = m_nCaret; + m_Buffer.RemoveChar( m_nCaret ); + m_pDialog->SendEvent( EVENT_EDITBOX_CHANGE, true, this ); + } + ResetCaretBlink(); + break; + } + + case 24: // Ctrl-X Cut + case VK_CANCEL: // Ctrl-C Copy + { + CopyToClipboard(); + + // If the key is Ctrl-X, delete the selection too. + if( ( WCHAR )wParam == 24 ) + { + DeleteSelectionText(); + m_pDialog->SendEvent( EVENT_EDITBOX_CHANGE, true, this ); + } + + break; + } + + // Ctrl-V Paste + case 22: + { + PasteFromClipboard(); + m_pDialog->SendEvent( EVENT_EDITBOX_CHANGE, true, this ); + break; + } + + // Ctrl-A Select All + case 1: + if( m_nSelStart == m_nCaret ) + { + m_nSelStart = 0; + PlaceCaret( m_Buffer.GetTextSize() ); + } + break; + + case VK_RETURN: + // Invoke the callback when the user presses Enter. + m_pDialog->SendEvent( EVENT_EDITBOX_STRING, true, this ); + break; + + // Junk characters we don't want in the string + case 26: // Ctrl Z + case 2: // Ctrl B + case 14: // Ctrl N + case 19: // Ctrl S + case 4: // Ctrl D + case 6: // Ctrl F + case 7: // Ctrl G + case 10: // Ctrl J + case 11: // Ctrl K + case 12: // Ctrl L + case 17: // Ctrl Q + case 23: // Ctrl W + case 5: // Ctrl E + case 18: // Ctrl R + case 20: // Ctrl T + case 25: // Ctrl Y + case 21: // Ctrl U + case 9: // Ctrl I + case 15: // Ctrl O + case 16: // Ctrl P + case 27: // Ctrl [ + case 29: // Ctrl ] + case 28: // Ctrl \ + break; + + default: + { + // If there's a selection and the user + // starts to type, the selection should + // be deleted. + if( m_nCaret != m_nSelStart ) + DeleteSelectionText(); + + // If we are in overwrite mode and there is already + // a char at the caret's position, simply replace it. + // Otherwise, we insert the char as normal. + if( !m_bInsertMode && m_nCaret < m_Buffer.GetTextSize() ) + { + m_Buffer[m_nCaret] = ( WCHAR )wParam; + PlaceCaret( m_nCaret + 1 ); + m_nSelStart = m_nCaret; + } + else + { + // Insert the char + if( m_Buffer.InsertChar( m_nCaret, ( WCHAR )wParam ) ) + { + PlaceCaret( m_nCaret + 1 ); + m_nSelStart = m_nCaret; + } + } + ResetCaretBlink(); + m_pDialog->SendEvent( EVENT_EDITBOX_CHANGE, true, this ); + } + } + return true; + } + } + return false; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTEditBox::Render( float fElapsedTime ) +{ + if( m_bVisible == false ) + return; + + HRESULT hr; + int nSelStartX = 0, nCaretX = 0; // Left and right X cordinates of the selection region + + CDXUTElement* pElement = GetElement( 0 ); + if( pElement ) + { + m_Buffer.SetFontNode( m_pDialog->GetFont( pElement->iFont ) ); + PlaceCaret( m_nCaret ); // Call PlaceCaret now that we have the font info (node), + // so that scrolling can be handled. + } + + // Render the control graphics + for( int e = 0; e < 9; ++e ) + { + pElement = m_Elements.GetAt( e ); + pElement->TextureColor.Blend( DXUT_STATE_NORMAL, fElapsedTime ); + + m_pDialog->DrawSprite( pElement, &m_rcRender[e], DXUT_FAR_BUTTON_DEPTH ); + } + + // + // Compute the X coordinates of the first visible character. + // + int nXFirst; + m_Buffer.CPtoX( m_nFirstVisible, FALSE, &nXFirst ); + + // + // Compute the X coordinates of the selection rectangle + // + hr = m_Buffer.CPtoX( m_nCaret, FALSE, &nCaretX ); + if( m_nCaret != m_nSelStart ) + hr = m_Buffer.CPtoX( m_nSelStart, FALSE, &nSelStartX ); + else + nSelStartX = nCaretX; + + // + // Render the selection rectangle + // + RECT rcSelection; // Make this available for rendering selected text + if( m_nCaret != m_nSelStart ) + { + int nSelLeftX = nCaretX, nSelRightX = nSelStartX; + // Swap if left is bigger than right + if( nSelLeftX > nSelRightX ) + { + int nTemp = nSelLeftX; nSelLeftX = nSelRightX; nSelRightX = nTemp; + } + + SetRect( &rcSelection, nSelLeftX, m_rcText.top, nSelRightX, m_rcText.bottom ); + OffsetRect( &rcSelection, m_rcText.left - nXFirst, 0 ); + IntersectRect( &rcSelection, &m_rcText, &rcSelection ); + + IDirect3DDevice9* pd3dDevice = m_pDialog->GetManager()->GetD3D9Device(); + if( pd3dDevice ) + pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE ); + m_pDialog->DrawRect( &rcSelection, m_SelBkColor ); + if( pd3dDevice ) + pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE ); + } + + // + // Render the text + // + // Element 0 for text + m_Elements.GetAt( 0 )->FontColor.Current = m_TextColor; + m_pDialog->DrawText( m_Buffer.GetBuffer() + m_nFirstVisible, m_Elements.GetAt( 0 ), &m_rcText ); + + // Render the selected text + if( m_nCaret != m_nSelStart ) + { + int nFirstToRender = __max( m_nFirstVisible, __min( m_nSelStart, m_nCaret ) ); + int nNumChatToRender = __max( m_nSelStart, m_nCaret ) - nFirstToRender; + m_Elements.GetAt( 0 )->FontColor.Current = m_SelTextColor; + m_pDialog->DrawText( m_Buffer.GetBuffer() + nFirstToRender, + m_Elements.GetAt( 0 ), &rcSelection, false, nNumChatToRender ); + } + + // + // Blink the caret + // + if( DXUTGetGlobalTimer()->GetAbsoluteTime() - m_dfLastBlink >= m_dfBlink ) + { + m_bCaretOn = !m_bCaretOn; + m_dfLastBlink = DXUTGetGlobalTimer()->GetAbsoluteTime(); + } + + // + // Render the caret if this control has the focus + // + if( m_bHasFocus && m_bCaretOn && !s_bHideCaret ) + { + // Start the rectangle with insert mode caret + RECT rcCaret = + { + m_rcText.left - nXFirst + nCaretX - 1, m_rcText.top, + m_rcText.left - nXFirst + nCaretX + 1, m_rcText.bottom + }; + + // If we are in overwrite mode, adjust the caret rectangle + // to fill the entire character. + if( !m_bInsertMode ) + { + // Obtain the right edge X coord of the current character + int nRightEdgeX; + m_Buffer.CPtoX( m_nCaret, TRUE, &nRightEdgeX ); + rcCaret.right = m_rcText.left - nXFirst + nRightEdgeX; + } + + m_pDialog->DrawRect( &rcCaret, m_CaretColor ); + } +} + + +#define IN_FLOAT_CHARSET( c ) \ + ( (c) == L'-' || (c) == L'.' || ( (c) >= L'0' && (c) <= L'9' ) ) + +void CDXUTEditBox::ParseFloatArray( float* pNumbers, int nCount ) +{ + int nWritten = 0; // Number of floats written + const WCHAR* pToken, *pEnd; + WCHAR wszToken[60]; + + pToken = m_Buffer.GetBuffer(); + while( nWritten < nCount && *pToken != L'\0' ) + { + // Skip leading spaces + while( *pToken == L' ' ) + ++pToken; + + if( *pToken == L'\0' ) + break; + + // Locate the end of number + pEnd = pToken; + while( IN_FLOAT_CHARSET( *pEnd ) ) + ++pEnd; + + // Copy the token to our buffer + int nTokenLen = __min( sizeof( wszToken ) / sizeof( wszToken[0] ) - 1, int( pEnd - pToken ) ); + wcscpy_s( wszToken, nTokenLen, pToken ); + *pNumbers = ( float )wcstod( wszToken, NULL ); + ++nWritten; + ++pNumbers; + pToken = pEnd; + } +} + + +void CDXUTEditBox::SetTextFloatArray( const float* pNumbers, int nCount ) +{ + WCHAR wszBuffer[512] = + { + 0 + }; + WCHAR wszTmp[64]; + + if( pNumbers == NULL ) + return; + + for( int i = 0; i < nCount; ++i ) + { + swprintf_s( wszTmp, 64, L"%.4f ", pNumbers[i] ); + wcscat_s( wszBuffer, 512, wszTmp ); + } + + // Don't want the last space + if( nCount > 0 && wcslen( wszBuffer ) > 0 ) + wszBuffer[wcslen( wszBuffer ) - 1] = 0; + + SetText( wszBuffer ); +} + + + + +//-------------------------------------------------------------------------------------- +void CUniBuffer::Initialize() +{ + if( s_hDll ) // Only need to do once + return; + + s_hDll = LoadLibrary( UNISCRIBE_DLLNAME ); + if( s_hDll ) + { + FARPROC Temp; + GETPROCADDRESS( s_hDll, ScriptApplyDigitSubstitution, Temp ); + GETPROCADDRESS( s_hDll, ScriptStringAnalyse, Temp ); + GETPROCADDRESS( s_hDll, ScriptStringCPtoX, Temp ); + GETPROCADDRESS( s_hDll, ScriptStringXtoCP, Temp ); + GETPROCADDRESS( s_hDll, ScriptStringFree, Temp ); + GETPROCADDRESS( s_hDll, ScriptString_pLogAttr, Temp ); + GETPROCADDRESS( s_hDll, ScriptString_pcOutChars, Temp ); + } +} + + +//-------------------------------------------------------------------------------------- +void CUniBuffer::Uninitialize() +{ + if( s_hDll ) + { + PLACEHOLDERPROC( ScriptApplyDigitSubstitution ); + PLACEHOLDERPROC( ScriptStringAnalyse ); + PLACEHOLDERPROC( ScriptStringCPtoX ); + PLACEHOLDERPROC( ScriptStringXtoCP ); + PLACEHOLDERPROC( ScriptStringFree ); + PLACEHOLDERPROC( ScriptString_pLogAttr ); + PLACEHOLDERPROC( ScriptString_pcOutChars ); + + FreeLibrary( s_hDll ); + s_hDll = NULL; + } +} + + +//-------------------------------------------------------------------------------------- +bool CUniBuffer::SetBufferSize( int nNewSize ) +{ + // If the current size is already the maximum allowed, + // we can't possibly allocate more. + if( m_nBufferSize == DXUT_MAX_EDITBOXLENGTH ) + return false; + + int nAllocateSize = ( nNewSize == -1 || nNewSize < m_nBufferSize * 2 ) ? ( m_nBufferSize ? m_nBufferSize * + 2 : 256 ) : nNewSize * 2; + + // Cap the buffer size at the maximum allowed. + if( nAllocateSize > DXUT_MAX_EDITBOXLENGTH ) + nAllocateSize = DXUT_MAX_EDITBOXLENGTH; + + WCHAR* pTempBuffer = new WCHAR[nAllocateSize]; + if( !pTempBuffer ) + return false; + + ZeroMemory( pTempBuffer, sizeof( WCHAR ) * nAllocateSize ); + + if( m_pwszBuffer ) + { + CopyMemory( pTempBuffer, m_pwszBuffer, m_nBufferSize * sizeof( WCHAR ) ); + delete[] m_pwszBuffer; + } + + m_pwszBuffer = pTempBuffer; + m_nBufferSize = nAllocateSize; + return true; +} + + +//-------------------------------------------------------------------------------------- +// Uniscribe -- Analyse() analyses the string in the buffer +//-------------------------------------------------------------------------------------- +HRESULT CUniBuffer::Analyse() +{ + if( m_Analysis ) + _ScriptStringFree( &m_Analysis ); + + SCRIPT_CONTROL ScriptControl; // For uniscribe + SCRIPT_STATE ScriptState; // For uniscribe + ZeroMemory( &ScriptControl, sizeof( ScriptControl ) ); + ZeroMemory( &ScriptState, sizeof( ScriptState ) ); + _ScriptApplyDigitSubstitution( NULL, &ScriptControl, &ScriptState ); + + if( !m_pFontNode ) + return E_FAIL; + + HDC hDC = + ( m_pFontNode->pFont9 ? m_pFontNode->pFont9->GetDC() : NULL ); + HRESULT hr = _ScriptStringAnalyse( hDC, + m_pwszBuffer, + lstrlenW( m_pwszBuffer ) + 1, // NULL is also analyzed. + lstrlenW( m_pwszBuffer ) * 3 / 2 + 16, + -1, + SSA_BREAK | SSA_GLYPHS | SSA_FALLBACK | SSA_LINK, + 0, + &ScriptControl, + &ScriptState, + NULL, + NULL, + NULL, + &m_Analysis ); + if( SUCCEEDED( hr ) ) + m_bAnalyseRequired = false; // Analysis is up-to-date + return hr; +} + + +//-------------------------------------------------------------------------------------- +CUniBuffer::CUniBuffer( int nInitialSize ) +{ + CUniBuffer::Initialize(); // ensure static vars are properly init'ed first + + m_nBufferSize = 0; + m_pwszBuffer = NULL; + m_bAnalyseRequired = true; + m_Analysis = NULL; + m_pFontNode = NULL; + + if( nInitialSize > 0 ) + SetBufferSize( nInitialSize ); +} + + +//-------------------------------------------------------------------------------------- +CUniBuffer::~CUniBuffer() +{ + delete[] m_pwszBuffer; + if( m_Analysis ) + _ScriptStringFree( &m_Analysis ); +} + + +//-------------------------------------------------------------------------------------- +WCHAR& CUniBuffer::operator[]( int n ) // No param checking +{ + // This version of operator[] is called only + // if we are asking for write access, so + // re-analysis is required. + m_bAnalyseRequired = true; + return m_pwszBuffer[n]; +} + + +//-------------------------------------------------------------------------------------- +void CUniBuffer::Clear() +{ + *m_pwszBuffer = L'\0'; + m_bAnalyseRequired = true; +} + + +//-------------------------------------------------------------------------------------- +// Inserts the char at specified index. +// If nIndex == -1, insert to the end. +//-------------------------------------------------------------------------------------- +bool CUniBuffer::InsertChar( int nIndex, WCHAR wChar ) +{ + assert( nIndex >= 0 ); + + if( nIndex < 0 || nIndex > lstrlenW( m_pwszBuffer ) ) + return false; // invalid index + + // Check for maximum length allowed + if( GetTextSize() + 1 >= DXUT_MAX_EDITBOXLENGTH ) + return false; + + if( lstrlenW( m_pwszBuffer ) + 1 >= m_nBufferSize ) + { + if( !SetBufferSize( -1 ) ) + return false; // out of memory + } + + assert( m_nBufferSize >= 2 ); + + // Shift the characters after the index, start by copying the null terminator + WCHAR* dest = m_pwszBuffer + lstrlenW( m_pwszBuffer ) + 1; + WCHAR* stop = m_pwszBuffer + nIndex; + WCHAR* src = dest - 1; + + while( dest > stop ) + { + *dest-- = *src--; + } + + // Set new character + m_pwszBuffer[ nIndex ] = wChar; + m_bAnalyseRequired = true; + + return true; +} + + +//-------------------------------------------------------------------------------------- +// Removes the char at specified index. +// If nIndex == -1, remove the last char. +//-------------------------------------------------------------------------------------- +bool CUniBuffer::RemoveChar( int nIndex ) +{ + if( !lstrlenW( m_pwszBuffer ) || nIndex < 0 || nIndex >= lstrlenW( m_pwszBuffer ) ) + return false; // Invalid index + + MoveMemory( m_pwszBuffer + nIndex, m_pwszBuffer + nIndex + 1, sizeof( WCHAR ) * + ( lstrlenW( m_pwszBuffer ) - nIndex ) ); + m_bAnalyseRequired = true; + return true; +} + + +//-------------------------------------------------------------------------------------- +// Inserts the first nCount characters of the string pStr at specified index. +// If nCount == -1, the entire string is inserted. +// If nIndex == -1, insert to the end. +//-------------------------------------------------------------------------------------- +bool CUniBuffer::InsertString( int nIndex, const WCHAR* pStr, int nCount ) +{ + assert( nIndex >= 0 ); + if( nIndex < 0 ) + return false; + + if( nIndex > lstrlenW( m_pwszBuffer ) ) + return false; // invalid index + + if( -1 == nCount ) + nCount = lstrlenW( pStr ); + + // Check for maximum length allowed + if( GetTextSize() + nCount >= DXUT_MAX_EDITBOXLENGTH ) + return false; + + if( lstrlenW( m_pwszBuffer ) + nCount >= m_nBufferSize ) + { + if( !SetBufferSize( lstrlenW( m_pwszBuffer ) + nCount + 1 ) ) + return false; // out of memory + } + + MoveMemory( m_pwszBuffer + nIndex + nCount, m_pwszBuffer + nIndex, sizeof( WCHAR ) * + ( lstrlenW( m_pwszBuffer ) - nIndex + 1 ) ); + CopyMemory( m_pwszBuffer + nIndex, pStr, nCount * sizeof( WCHAR ) ); + m_bAnalyseRequired = true; + + return true; +} + + +//-------------------------------------------------------------------------------------- +bool CUniBuffer::SetText( LPCWSTR wszText ) +{ + assert( wszText != NULL ); + + int nRequired = int( wcslen( wszText ) + 1 ); + + // Check for maximum length allowed + if( nRequired >= DXUT_MAX_EDITBOXLENGTH ) + return false; + + while( GetBufferSize() < nRequired ) + if( !SetBufferSize( -1 ) ) + break; + // Check again in case out of memory occurred inside while loop. + if( GetBufferSize() >= nRequired ) + { + wcscpy_s( m_pwszBuffer, GetBufferSize(), wszText ); + m_bAnalyseRequired = true; + return true; + } + else + return false; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CUniBuffer::CPtoX( int nCP, BOOL bTrail, int* pX ) +{ + assert( pX ); + *pX = 0; // Default + + HRESULT hr = S_OK; + if( m_bAnalyseRequired ) + hr = Analyse(); + + if( SUCCEEDED( hr ) ) + hr = _ScriptStringCPtoX( m_Analysis, nCP, bTrail, pX ); + + return hr; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CUniBuffer::XtoCP( int nX, int* pCP, int* pnTrail ) +{ + assert( pCP && pnTrail ); + *pCP = 0; *pnTrail = FALSE; // Default + + HRESULT hr = S_OK; + if( m_bAnalyseRequired ) + hr = Analyse(); + + if( SUCCEEDED( hr ) ) + hr = _ScriptStringXtoCP( m_Analysis, nX, pCP, pnTrail ); + + // If the coordinate falls outside the text region, we + // can get character positions that don't exist. We must + // filter them here and convert them to those that do exist. + if( *pCP == -1 && *pnTrail == TRUE ) + { + *pCP = 0; *pnTrail = FALSE; + } + else if( *pCP > lstrlenW( m_pwszBuffer ) && *pnTrail == FALSE ) + { + *pCP = lstrlenW( m_pwszBuffer ); *pnTrail = TRUE; + } + + return hr; +} + + +//-------------------------------------------------------------------------------------- +void CUniBuffer::GetPriorItemPos( int nCP, int* pPrior ) +{ + *pPrior = nCP; // Default is the char itself + + if( m_bAnalyseRequired ) + if( FAILED( Analyse() ) ) + return; + + const SCRIPT_LOGATTR* pLogAttr = _ScriptString_pLogAttr( m_Analysis ); + if( !pLogAttr ) + return; + + if( !_ScriptString_pcOutChars( m_Analysis ) ) + return; + int nInitial = *_ScriptString_pcOutChars( m_Analysis ); + if( nCP - 1 < nInitial ) + nInitial = nCP - 1; + for( int i = nInitial; i > 0; --i ) + if( pLogAttr[i].fWordStop || // Either the fWordStop flag is set + ( !pLogAttr[i].fWhiteSpace && // Or the previous char is whitespace but this isn't. + pLogAttr[i - 1].fWhiteSpace ) ) + { + *pPrior = i; + return; + } + // We have reached index 0. 0 is always a break point, so simply return it. + *pPrior = 0; +} + + +//-------------------------------------------------------------------------------------- +void CUniBuffer::GetNextItemPos( int nCP, int* pPrior ) +{ + *pPrior = nCP; // Default is the char itself + + HRESULT hr = S_OK; + if( m_bAnalyseRequired ) + hr = Analyse(); + if( FAILED( hr ) ) + return; + + const SCRIPT_LOGATTR* pLogAttr = _ScriptString_pLogAttr( m_Analysis ); + if( !pLogAttr ) + return; + + if( !_ScriptString_pcOutChars( m_Analysis ) ) + return; + int nInitial = *_ScriptString_pcOutChars( m_Analysis ); + if( nCP + 1 < nInitial ) + nInitial = nCP + 1; + + int i = nInitial; + int limit = *_ScriptString_pcOutChars( m_Analysis ); + while( limit > 0 && i < limit - 1 ) + { + if( pLogAttr[i].fWordStop ) // Either the fWordStop flag is set + { + *pPrior = i; + return; + } + else if( pLogAttr[i].fWhiteSpace && // Or this whitespace but the next char isn't. + !pLogAttr[i + 1].fWhiteSpace ) + { + *pPrior = i + 1; // The next char is a word stop + return; + } + + ++i; + limit = *_ScriptString_pcOutChars( m_Analysis ); + } + // We have reached the end. It's always a word stop, so simply return it. + *pPrior = *_ScriptString_pcOutChars( m_Analysis ) - 1; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTEditBox::ResetCaretBlink() +{ + m_bCaretOn = true; + m_dfLastBlink = DXUTGetGlobalTimer()->GetAbsoluteTime(); +} + + +//-------------------------------------------------------------------------------------- +void DXUTBlendColor::Init( D3DCOLOR defaultColor, D3DCOLOR disabledColor, D3DCOLOR hiddenColor ) +{ + for( int i = 0; i < MAX_CONTROL_STATES; i++ ) + { + States[ i ] = defaultColor; + } + + States[ DXUT_STATE_DISABLED ] = disabledColor; + States[ DXUT_STATE_HIDDEN ] = hiddenColor; + Current = hiddenColor; +} + + +//-------------------------------------------------------------------------------------- +void DXUTBlendColor::Blend( UINT iState, float fElapsedTime, float fRate ) +{ + D3DXCOLOR destColor = States[ iState ]; + D3DXColorLerp( &Current, &Current, &destColor, 1.0f - powf( fRate, 30 * fElapsedTime ) ); +} + + + +//-------------------------------------------------------------------------------------- +void CDXUTElement::SetTexture( UINT iTexture, RECT* prcTexture, D3DCOLOR defaultTextureColor ) +{ + this->iTexture = iTexture; + + if( prcTexture ) + rcTexture = *prcTexture; + else + SetRectEmpty( &rcTexture ); + + TextureColor.Init( defaultTextureColor ); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTElement::SetFont( UINT iFont, D3DCOLOR defaultFontColor, DWORD dwTextFormat ) +{ + this->iFont = iFont; + this->dwTextFormat = dwTextFormat; + + FontColor.Init( defaultFontColor ); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTElement::Refresh() +{ + TextureColor.Current = TextureColor.States[ DXUT_STATE_HIDDEN ]; + FontColor.Current = FontColor.States[ DXUT_STATE_HIDDEN ]; +} + + diff --git a/Demos/DX11ClothDemo/DXUT/Optional/DXUTgui.h b/Demos/DX11ClothDemo/DXUT/Optional/DXUTgui.h new file mode 100644 index 0000000..765020b --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/DXUTgui.h @@ -0,0 +1,1383 @@ +//-------------------------------------------------------------------------------------- +// File: DXUTgui.h +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once +#ifndef DXUT_GUI_H +#define DXUT_GUI_H + +#include +#include + + +//-------------------------------------------------------------------------------------- +// Defines and macros +//-------------------------------------------------------------------------------------- +#define EVENT_BUTTON_CLICKED 0x0101 +#define EVENT_COMBOBOX_SELECTION_CHANGED 0x0201 +#define EVENT_RADIOBUTTON_CHANGED 0x0301 +#define EVENT_CHECKBOX_CHANGED 0x0401 +#define EVENT_SLIDER_VALUE_CHANGED 0x0501 +#define EVENT_SLIDER_VALUE_CHANGED_UP 0x0502 + +#define EVENT_EDITBOX_STRING 0x0601 +// EVENT_EDITBOX_CHANGE is sent when the listbox content changes +// due to user input. +#define EVENT_EDITBOX_CHANGE 0x0602 +#define EVENT_LISTBOX_ITEM_DBLCLK 0x0701 +// EVENT_LISTBOX_SELECTION is fired off when the selection changes in +// a single selection list box. +#define EVENT_LISTBOX_SELECTION 0x0702 +#define EVENT_LISTBOX_SELECTION_END 0x0703 + + +//-------------------------------------------------------------------------------------- +// Forward declarations +//-------------------------------------------------------------------------------------- +class CDXUTDialogResourceManager; +class CDXUTControl; +class CDXUTButton; +class CDXUTStatic; +class CDXUTCheckBox; +class CDXUTRadioButton; +class CDXUTComboBox; +class CDXUTSlider; +class CDXUTEditBox; +class CDXUTListBox; +class CDXUTScrollBar; +class CDXUTElement; +struct DXUTElementHolder; +struct DXUTTextureNode; +struct DXUTFontNode; +typedef VOID ( CALLBACK*PCALLBACKDXUTGUIEVENT )( UINT nEvent, int nControlID, CDXUTControl* pControl, + void* pUserContext ); + + +//-------------------------------------------------------------------------------------- +// Enums for pre-defined control types +//-------------------------------------------------------------------------------------- +enum DXUT_CONTROL_TYPE +{ + DXUT_CONTROL_BUTTON, + DXUT_CONTROL_STATIC, + DXUT_CONTROL_CHECKBOX, + DXUT_CONTROL_RADIOBUTTON, + DXUT_CONTROL_COMBOBOX, + DXUT_CONTROL_SLIDER, + DXUT_CONTROL_EDITBOX, + DXUT_CONTROL_IMEEDITBOX, + DXUT_CONTROL_LISTBOX, + DXUT_CONTROL_SCROLLBAR, +}; + +enum DXUT_CONTROL_STATE +{ + DXUT_STATE_NORMAL = 0, + DXUT_STATE_DISABLED, + DXUT_STATE_HIDDEN, + DXUT_STATE_FOCUS, + DXUT_STATE_MOUSEOVER, + DXUT_STATE_PRESSED, +}; + +#define MAX_CONTROL_STATES 6 + +struct DXUTBlendColor +{ + void Init( D3DCOLOR defaultColor, D3DCOLOR disabledColor = D3DCOLOR_ARGB( 200, 128, 128, 128 ), + D3DCOLOR hiddenColor = 0 ); + void Blend( UINT iState, float fElapsedTime, float fRate = 0.7f ); + + D3DCOLOR States[ MAX_CONTROL_STATES ]; // Modulate colors for all possible control states + D3DXCOLOR Current; +}; + + +//----------------------------------------------------------------------------- +// Contains all the display tweakables for a sub-control +//----------------------------------------------------------------------------- +class CDXUTElement +{ +public: + void SetTexture( UINT iTexture, RECT* prcTexture, D3DCOLOR defaultTextureColor = D3DCOLOR_ARGB( 255, 255, 255, + 255 ) ); + void SetFont( UINT iFont, D3DCOLOR defaultFontColor = D3DCOLOR_ARGB( 255, 255, 255, + 255 ), DWORD dwTextFormat = DT_CENTER | + DT_VCENTER ); + + void Refresh(); + + UINT iTexture; // Index of the texture for this Element + UINT iFont; // Index of the font for this Element + DWORD dwTextFormat; // The format argument to DrawText + + RECT rcTexture; // Bounding rect of this element on the composite texture + + DXUTBlendColor TextureColor; + DXUTBlendColor FontColor; +}; + + +//----------------------------------------------------------------------------- +// All controls must be assigned to a dialog, which handles +// input and rendering for the controls. +//----------------------------------------------------------------------------- +class CDXUTDialog +{ + friend class CDXUTDialogResourceManager; + +public: + CDXUTDialog(); + ~CDXUTDialog(); + + // Need to call this now + void Init( CDXUTDialogResourceManager* pManager, bool bRegisterDialog = true ); + void Init( CDXUTDialogResourceManager* pManager, bool bRegisterDialog, + LPCWSTR pszControlTextureFilename ); + void Init( CDXUTDialogResourceManager* pManager, bool bRegisterDialog, + LPCWSTR szControlTextureResourceName, HMODULE hControlTextureResourceModule ); + + // Windows message handler + bool MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + + // Control creation + HRESULT AddStatic( int ID, LPCWSTR strText, int x, int y, int width, int height, bool bIsDefault=false, + CDXUTStatic** ppCreated=NULL ); + HRESULT AddButton( int ID, LPCWSTR strText, int x, int y, int width, int height, UINT nHotkey=0, + bool bIsDefault=false, CDXUTButton** ppCreated=NULL ); + HRESULT AddCheckBox( int ID, LPCWSTR strText, int x, int y, int width, int height, bool bChecked=false, + UINT nHotkey=0, bool bIsDefault=false, CDXUTCheckBox** ppCreated=NULL ); + HRESULT AddRadioButton( int ID, UINT nButtonGroup, LPCWSTR strText, int x, int y, int width, + int height, bool bChecked=false, UINT nHotkey=0, bool bIsDefault=false, + CDXUTRadioButton** ppCreated=NULL ); + HRESULT AddComboBox( int ID, int x, int y, int width, int height, UINT nHotKey=0, bool bIsDefault= + false, CDXUTComboBox** ppCreated=NULL ); + HRESULT AddSlider( int ID, int x, int y, int width, int height, int min=0, int max=100, int value=50, + bool bIsDefault=false, CDXUTSlider** ppCreated=NULL ); + // AddIMEEditBox has been renamed into DXUTguiIME.cpp as CDXUTIMEEditBox::CreateIMEEditBox + HRESULT AddEditBox( int ID, LPCWSTR strText, int x, int y, int width, int height, bool bIsDefault= + false, CDXUTEditBox** ppCreated=NULL ); + HRESULT AddListBox( int ID, int x, int y, int width, int height, DWORD dwStyle=0, + CDXUTListBox** ppCreated=NULL ); + HRESULT AddControl( CDXUTControl* pControl ); + HRESULT InitControl( CDXUTControl* pControl ); + + // Control retrieval + CDXUTStatic* GetStatic( int ID ) + { + return ( CDXUTStatic* )GetControl( ID, DXUT_CONTROL_STATIC ); + } + CDXUTButton* GetButton( int ID ) + { + return ( CDXUTButton* )GetControl( ID, DXUT_CONTROL_BUTTON ); + } + CDXUTCheckBox* GetCheckBox( int ID ) + { + return ( CDXUTCheckBox* )GetControl( ID, DXUT_CONTROL_CHECKBOX ); + } + CDXUTRadioButton* GetRadioButton( int ID ) + { + return ( CDXUTRadioButton* )GetControl( ID, DXUT_CONTROL_RADIOBUTTON ); + } + CDXUTComboBox* GetComboBox( int ID ) + { + return ( CDXUTComboBox* )GetControl( ID, DXUT_CONTROL_COMBOBOX ); + } + CDXUTSlider* GetSlider( int ID ) + { + return ( CDXUTSlider* )GetControl( ID, DXUT_CONTROL_SLIDER ); + } + CDXUTEditBox* GetEditBox( int ID ) + { + return ( CDXUTEditBox* )GetControl( ID, DXUT_CONTROL_EDITBOX ); + } + CDXUTListBox* GetListBox( int ID ) + { + return ( CDXUTListBox* )GetControl( ID, DXUT_CONTROL_LISTBOX ); + } + + CDXUTControl* GetControl( int ID ); + CDXUTControl* GetControl( int ID, UINT nControlType ); + CDXUTControl* GetControlAtPoint( POINT pt ); + + bool GetControlEnabled( int ID ); + void SetControlEnabled( int ID, bool bEnabled ); + + void ClearRadioButtonGroup( UINT nGroup ); + void ClearComboBox( int ID ); + + // Access the default display Elements used when adding new controls + HRESULT SetDefaultElement( UINT nControlType, UINT iElement, CDXUTElement* pElement ); + CDXUTElement* GetDefaultElement( UINT nControlType, UINT iElement ); + + // Methods called by controls + void SendEvent( UINT nEvent, bool bTriggeredByUser, CDXUTControl* pControl ); + void RequestFocus( CDXUTControl* pControl ); + + // Render helpers + HRESULT DrawRect( RECT* pRect, D3DCOLOR color ); + HRESULT DrawRect9( RECT* pRect, D3DCOLOR color ); + HRESULT DrawPolyLine( POINT* apPoints, UINT nNumPoints, D3DCOLOR color ); + HRESULT DrawSprite( CDXUTElement* pElement, RECT* prcDest, float fDepth ); + HRESULT DrawSprite9( CDXUTElement* pElement, RECT* prcDest ); + HRESULT DrawSprite11( CDXUTElement* pElement, RECT* prcDest, float fDepth ); + HRESULT CalcTextRect( LPCWSTR strText, CDXUTElement* pElement, RECT* prcDest, int nCount = -1 ); + HRESULT DrawText( LPCWSTR strText, CDXUTElement* pElement, RECT* prcDest, bool bShadow = false, + int nCount = -1, bool bCenter = false ); + HRESULT DrawText9( LPCWSTR strText, CDXUTElement* pElement, RECT* prcDest, bool bShadow = false, + int nCount = -1 ); + HRESULT DrawText11( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3d11DeviceContext, + LPCWSTR strText, CDXUTElement* pElement, RECT* prcDest, bool bShadow = false, + int nCount = -1, bool bCenter = false ); + + // Attributes + bool GetVisible() + { + return m_bVisible; + } + void SetVisible( bool bVisible ) + { + m_bVisible = bVisible; + } + bool GetMinimized() + { + return m_bMinimized; + } + void SetMinimized( bool bMinimized ) + { + m_bMinimized = bMinimized; + } + void SetBackgroundColors( D3DCOLOR colorAllCorners ) + { + SetBackgroundColors( colorAllCorners, colorAllCorners, colorAllCorners, colorAllCorners ); + } + void SetBackgroundColors( D3DCOLOR colorTopLeft, D3DCOLOR colorTopRight, D3DCOLOR colorBottomLeft, + D3DCOLOR colorBottomRight ); + void EnableCaption( bool bEnable ) + { + m_bCaption = bEnable; + } + int GetCaptionHeight() const + { + return m_nCaptionHeight; + } + void SetCaptionHeight( int nHeight ) + { + m_nCaptionHeight = nHeight; + } + void SetCaptionText( const WCHAR* pwszText ) + { + wcscpy_s( m_wszCaption, sizeof( m_wszCaption ) / sizeof( m_wszCaption[0] ), pwszText ); + } + void GetLocation( POINT& Pt ) const + { + Pt.x = m_x; Pt.y = m_y; + } + void SetLocation( int x, int y ) + { + m_x = x; m_y = y; + } + void SetSize( int width, int height ) + { + m_width = width; m_height = height; + } + int GetWidth() + { + return m_width; + } + int GetHeight() + { + return m_height; + } + + static void WINAPI SetRefreshTime( float fTime ) + { + s_fTimeRefresh = fTime; + } + + static CDXUTControl* WINAPI GetNextControl( CDXUTControl* pControl ); + static CDXUTControl* WINAPI GetPrevControl( CDXUTControl* pControl ); + + void RemoveControl( int ID ); + void RemoveAllControls(); + + // Sets the callback used to notify the app of control events + void SetCallback( PCALLBACKDXUTGUIEVENT pCallback, void* pUserContext = NULL ); + void EnableNonUserEvents( bool bEnable ) + { + m_bNonUserEvents = bEnable; + } + void EnableKeyboardInput( bool bEnable ) + { + m_bKeyboardInput = bEnable; + } + void EnableMouseInput( bool bEnable ) + { + m_bMouseInput = bEnable; + } + bool IsKeyboardInputEnabled() const + { + return m_bKeyboardInput; + } + + // Device state notification + void Refresh(); + HRESULT OnRender( float fElapsedTime ); + + // Shared resource access. Indexed fonts and textures are shared among + // all the controls. + HRESULT SetFont( UINT index, LPCWSTR strFaceName, LONG height, LONG weight ); + DXUTFontNode* GetFont( UINT index ); + + HRESULT SetTexture( UINT index, LPCWSTR strFilename ); + HRESULT SetTexture( UINT index, LPCWSTR strResourceName, HMODULE hResourceModule ); + DXUTTextureNode* GetTexture( UINT index ); + + CDXUTDialogResourceManager* GetManager() + { + return m_pManager; + } + + static void WINAPI ClearFocus(); + void FocusDefaultControl(); + + bool m_bNonUserEvents; + bool m_bKeyboardInput; + bool m_bMouseInput; + +private: + int m_nDefaultControlID; + + HRESULT OnRender9( float fElapsedTime ); + HRESULT OnRender10( float fElapsedTime ); + HRESULT OnRender11( float fElapsedTime ); + + static double s_fTimeRefresh; + double m_fTimeLastRefresh; + + // Initialize default Elements + void InitDefaultElements(); + + // Windows message handlers + void OnMouseMove( POINT pt ); + void OnMouseUp( POINT pt ); + + void SetNextDialog( CDXUTDialog* pNextDialog ); + + // Control events + bool OnCycleFocus( bool bForward ); + + static CDXUTControl* s_pControlFocus; // The control which has focus + static CDXUTControl* s_pControlPressed; // The control currently pressed + + CDXUTControl* m_pControlMouseOver; // The control which is hovered over + + bool m_bVisible; + bool m_bCaption; + bool m_bMinimized; + bool m_bDrag; + WCHAR m_wszCaption[256]; + + int m_x; + int m_y; + int m_width; + int m_height; + int m_nCaptionHeight; + + D3DCOLOR m_colorTopLeft; + D3DCOLOR m_colorTopRight; + D3DCOLOR m_colorBottomLeft; + D3DCOLOR m_colorBottomRight; + + CDXUTDialogResourceManager* m_pManager; + PCALLBACKDXUTGUIEVENT m_pCallbackEvent; + void* m_pCallbackEventUserContext; + + CGrowableArray m_Textures; // Index into m_TextureCache; + CGrowableArray m_Fonts; // Index into m_FontCache; + + CGrowableArray m_Controls; + CGrowableArray m_DefaultElements; + + CDXUTElement m_CapElement; // Element for the caption + + CDXUTDialog* m_pNextDialog; + CDXUTDialog* m_pPrevDialog; +}; + + +//-------------------------------------------------------------------------------------- +// Structs for shared resources +//-------------------------------------------------------------------------------------- +struct DXUTTextureNode +{ + bool bFileSource; // True if this texture is loaded from a file. False if from resource. + HMODULE hResourceModule; + int nResourceID; // Resource ID. If 0, string-based ID is used and stored in strFilename. + WCHAR strFilename[MAX_PATH]; + DWORD dwWidth; + DWORD dwHeight; + IDirect3DTexture9* pTexture9; + ID3D11Texture2D* pTexture11; + ID3D11ShaderResourceView* pTexResView11; +}; + +struct DXUTFontNode +{ + WCHAR strFace[MAX_PATH]; + LONG nHeight; + LONG nWeight; + ID3DXFont* pFont9; +}; + +struct DXUTSpriteVertex +{ + D3DXVECTOR3 vPos; + D3DXCOLOR vColor; + D3DXVECTOR2 vTex; +}; + +//----------------------------------------------------------------------------- +// Manages shared resources of dialogs +//----------------------------------------------------------------------------- +class CDXUTDialogResourceManager +{ +public: + CDXUTDialogResourceManager(); + ~CDXUTDialogResourceManager(); + + bool MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + + // D3D9 specific + HRESULT OnD3D9CreateDevice( LPDIRECT3DDEVICE9 pd3dDevice ); + HRESULT OnD3D9ResetDevice(); + void OnD3D9LostDevice(); + void OnD3D9DestroyDevice(); + IDirect3DDevice9* GetD3D9Device() + { + return m_pd3d9Device; + } + + // D3D11 specific + HRESULT OnD3D11CreateDevice( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3d11DeviceContext ); + HRESULT OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc ); + void OnD3D11ReleasingSwapChain(); + void OnD3D11DestroyDevice(); + void StoreD3D11State( ID3D11DeviceContext* pd3dImmediateContext ); + void RestoreD3D11State( ID3D11DeviceContext* pd3dImmediateContext ); + void ApplyRenderUI11( ID3D11DeviceContext* pd3dImmediateContext ); + void ApplyRenderUIUntex11( ID3D11DeviceContext* pd3dImmediateContext ); + void BeginSprites11( ); + void EndSprites11( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext ); + ID3D11Device* GetD3D11Device() + { + return m_pd3d11Device; + } + ID3D11DeviceContext* GetD3D11DeviceContext() + { + return m_pd3d11DeviceContext; + } + + DXUTFontNode* GetFontNode( int iIndex ) + { + return m_FontCache.GetAt( iIndex ); + }; + DXUTTextureNode* GetTextureNode( int iIndex ) + { + return m_TextureCache.GetAt( iIndex ); + }; + + int AddFont( LPCWSTR strFaceName, LONG height, LONG weight ); + int AddTexture( LPCWSTR strFilename ); + int AddTexture( LPCWSTR strResourceName, HMODULE hResourceModule ); + + bool RegisterDialog( CDXUTDialog* pDialog ); + void UnregisterDialog( CDXUTDialog* pDialog ); + void EnableKeyboardInputForAllDialogs(); + + // Shared between all dialogs + + // D3D9 + IDirect3DStateBlock9* m_pStateBlock; + ID3DXSprite* m_pSprite; // Sprite used for drawing + + // D3D11 + // Shaders + ID3D11VertexShader* m_pVSRenderUI11; + ID3D11PixelShader* m_pPSRenderUI11; + ID3D11PixelShader* m_pPSRenderUIUntex11; + + // States + ID3D11DepthStencilState* m_pDepthStencilStateUI11; + ID3D11RasterizerState* m_pRasterizerStateUI11; + ID3D11BlendState* m_pBlendStateUI11; + ID3D11SamplerState* m_pSamplerStateUI11; + + // Stored states + ID3D11DepthStencilState* m_pDepthStencilStateStored11; + UINT m_StencilRefStored11; + ID3D11RasterizerState* m_pRasterizerStateStored11; + ID3D11BlendState* m_pBlendStateStored11; + float m_BlendFactorStored11[4]; + UINT m_SampleMaskStored11; + ID3D11SamplerState* m_pSamplerStateStored11; + + ID3D11InputLayout* m_pInputLayout11; + ID3D11Buffer* m_pVBScreenQuad11; + + // Sprite workaround + ID3D11Buffer* m_pSpriteBuffer11; + UINT m_SpriteBufferBytes11; + CGrowableArray m_SpriteVertices; + + UINT m_nBackBufferWidth; + UINT m_nBackBufferHeight; + + CGrowableArray m_Dialogs; // Dialogs registered + +protected: + // D3D9 specific + IDirect3DDevice9* m_pd3d9Device; + HRESULT CreateFont9( UINT index ); + HRESULT CreateTexture9( UINT index ); + + // D3D11 specific + ID3D11Device* m_pd3d11Device; + ID3D11DeviceContext* m_pd3d11DeviceContext; + HRESULT CreateFont11( UINT index ); + HRESULT CreateTexture11( UINT index ); + + CGrowableArray m_TextureCache; // Shared textures + CGrowableArray m_FontCache; // Shared fonts +}; + +void BeginText11(); +void DrawText11DXUT( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3d11DeviceContext, + LPCWSTR strText, RECT rcScreen, D3DXCOLOR vFontColor, + float fBBWidth, float fBBHeight, bool bCenter ); +void EndText11( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3d11DeviceContext ); + +//----------------------------------------------------------------------------- +// Base class for controls +//----------------------------------------------------------------------------- +class CDXUTControl +{ +public: + CDXUTControl( CDXUTDialog* pDialog = NULL ); + virtual ~CDXUTControl(); + + virtual HRESULT OnInit() + { + return S_OK; + } + virtual void Refresh(); + virtual void Render( float fElapsedTime ) + { + }; + + // Windows message handler + virtual bool MsgProc( UINT uMsg, WPARAM wParam, LPARAM lParam ) + { + return false; + } + + virtual bool HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ) + { + return false; + } + virtual bool HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ) + { + return false; + } + + virtual bool CanHaveFocus() + { + return false; + } + virtual void OnFocusIn() + { + m_bHasFocus = true; + } + virtual void OnFocusOut() + { + m_bHasFocus = false; + } + virtual void OnMouseEnter() + { + m_bMouseOver = true; + } + virtual void OnMouseLeave() + { + m_bMouseOver = false; + } + virtual void OnHotkey() + { + } + + virtual BOOL ContainsPoint( POINT pt ) + { + return PtInRect( &m_rcBoundingBox, pt ); + } + + virtual void SetEnabled( bool bEnabled ) + { + m_bEnabled = bEnabled; + } + virtual bool GetEnabled() + { + return m_bEnabled; + } + virtual void SetVisible( bool bVisible ) + { + m_bVisible = bVisible; + } + virtual bool GetVisible() + { + return m_bVisible; + } + + UINT GetType() const + { + return m_Type; + } + + int GetID() const + { + return m_ID; + } + void SetID( int ID ) + { + m_ID = ID; + } + + void SetLocation( int x, int y ) + { + m_x = x; m_y = y; UpdateRects(); + } + void SetSize( int width, int height ) + { + m_width = width; m_height = height; UpdateRects(); + } + + void SetHotkey( UINT nHotkey ) + { + m_nHotkey = nHotkey; + } + UINT GetHotkey() + { + return m_nHotkey; + } + + void SetUserData( void* pUserData ) + { + m_pUserData = pUserData; + } + void* GetUserData() const + { + return m_pUserData; + } + + virtual void SetTextColor( D3DCOLOR Color ); + CDXUTElement* GetElement( UINT iElement ) + { + return m_Elements.GetAt( iElement ); + } + HRESULT SetElement( UINT iElement, CDXUTElement* pElement ); + + bool m_bVisible; // Shown/hidden flag + bool m_bMouseOver; // Mouse pointer is above control + bool m_bHasFocus; // Control has input focus + bool m_bIsDefault; // Is the default control + + // Size, scale, and positioning members + int m_x, m_y; + int m_width, m_height; + + // These members are set by the container + CDXUTDialog* m_pDialog; // Parent container + UINT m_Index; // Index within the control list + + CGrowableArray m_Elements; // All display elements + +protected: + virtual void UpdateRects(); + + int m_ID; // ID number + DXUT_CONTROL_TYPE m_Type; // Control type, set once in constructor + UINT m_nHotkey; // Virtual key code for this control's hotkey + void* m_pUserData; // Data associated with this control that is set by user. + + bool m_bEnabled; // Enabled/disabled flag + + RECT m_rcBoundingBox; // Rectangle defining the active region of the control +}; + + +//----------------------------------------------------------------------------- +// Contains all the display information for a given control type +//----------------------------------------------------------------------------- +struct DXUTElementHolder +{ + UINT nControlType; + UINT iElement; + + CDXUTElement Element; +}; + + +//----------------------------------------------------------------------------- +// Static control +//----------------------------------------------------------------------------- +class CDXUTStatic : public CDXUTControl +{ +public: + CDXUTStatic( CDXUTDialog* pDialog = NULL ); + + virtual void Render( float fElapsedTime ); + virtual BOOL ContainsPoint( POINT pt ) + { + return false; + } + + HRESULT GetTextCopy( __out_ecount(bufferCount) LPWSTR strDest, + UINT bufferCount ); + LPCWSTR GetText() + { + return m_strText; + } + HRESULT SetText( LPCWSTR strText ); + + +protected: + WCHAR m_strText[MAX_PATH]; // Window text +}; + + +//----------------------------------------------------------------------------- +// Button control +//----------------------------------------------------------------------------- +class CDXUTButton : public CDXUTStatic +{ +public: + CDXUTButton( CDXUTDialog* pDialog = NULL ); + + virtual bool HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ); + virtual bool HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ); + virtual void OnHotkey() + { + if( m_pDialog->IsKeyboardInputEnabled() ) m_pDialog->RequestFocus( this ); + m_pDialog->SendEvent( EVENT_BUTTON_CLICKED, true, this ); + } + + virtual BOOL ContainsPoint( POINT pt ) + { + return PtInRect( &m_rcBoundingBox, pt ); + } + virtual bool CanHaveFocus() + { + return ( m_bVisible && m_bEnabled ); + } + + virtual void Render( float fElapsedTime ); + +protected: + bool m_bPressed; +}; + + +//----------------------------------------------------------------------------- +// CheckBox control +//----------------------------------------------------------------------------- +class CDXUTCheckBox : public CDXUTButton +{ +public: + CDXUTCheckBox( CDXUTDialog* pDialog = NULL ); + + virtual bool HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ); + virtual bool HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ); + virtual void OnHotkey() + { + if( m_pDialog->IsKeyboardInputEnabled() ) m_pDialog->RequestFocus( this ); + SetCheckedInternal( !m_bChecked, true ); + } + + virtual BOOL ContainsPoint( POINT pt ); + virtual void UpdateRects(); + + virtual void Render( float fElapsedTime ); + + bool GetChecked() + { + return m_bChecked; + } + void SetChecked( bool bChecked ) + { + SetCheckedInternal( bChecked, false ); + } + +protected: + virtual void SetCheckedInternal( bool bChecked, bool bFromInput ); + + bool m_bChecked; + RECT m_rcButton; + RECT m_rcText; +}; + + +//----------------------------------------------------------------------------- +// RadioButton control +//----------------------------------------------------------------------------- +class CDXUTRadioButton : public CDXUTCheckBox +{ +public: + CDXUTRadioButton( CDXUTDialog* pDialog = NULL ); + + virtual bool HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ); + virtual bool HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ); + virtual void OnHotkey() + { + if( m_pDialog->IsKeyboardInputEnabled() ) m_pDialog->RequestFocus( this ); + SetCheckedInternal( true, true, true ); + } + + void SetChecked( bool bChecked, bool bClearGroup=true ) + { + SetCheckedInternal( bChecked, bClearGroup, false ); + } + void SetButtonGroup( UINT nButtonGroup ) + { + m_nButtonGroup = nButtonGroup; + } + UINT GetButtonGroup() + { + return m_nButtonGroup; + } + +protected: + virtual void SetCheckedInternal( bool bChecked, bool bClearGroup, bool bFromInput ); + UINT m_nButtonGroup; +}; + + +//----------------------------------------------------------------------------- +// Scrollbar control +//----------------------------------------------------------------------------- +class CDXUTScrollBar : public CDXUTControl +{ +public: + CDXUTScrollBar( CDXUTDialog* pDialog = NULL ); + virtual ~CDXUTScrollBar(); + + virtual bool HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ); + virtual bool HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ); + virtual bool MsgProc( UINT uMsg, WPARAM wParam, LPARAM lParam ); + + virtual void Render( float fElapsedTime ); + virtual void UpdateRects(); + + void SetTrackRange( int nStart, int nEnd ); + int GetTrackPos() + { + return m_nPosition; + } + void SetTrackPos( int nPosition ) + { + m_nPosition = nPosition; Cap(); UpdateThumbRect(); + } + int GetPageSize() + { + return m_nPageSize; + } + void SetPageSize( int nPageSize ) + { + m_nPageSize = nPageSize; Cap(); UpdateThumbRect(); + } + + void Scroll( int nDelta ); // Scroll by nDelta items (plus or minus) + void ShowItem( int nIndex ); // Ensure that item nIndex is displayed, scroll if necessary + +protected: + // ARROWSTATE indicates the state of the arrow buttons. + // CLEAR No arrow is down. + // CLICKED_UP Up arrow is clicked. + // CLICKED_DOWN Down arrow is clicked. + // HELD_UP Up arrow is held down for sustained period. + // HELD_DOWN Down arrow is held down for sustained period. + enum ARROWSTATE + { + CLEAR, + CLICKED_UP, + CLICKED_DOWN, + HELD_UP, + HELD_DOWN + }; + + void UpdateThumbRect(); + void Cap(); // Clips position at boundaries. Ensures it stays within legal range. + + bool m_bShowThumb; + bool m_bDrag; + RECT m_rcUpButton; + RECT m_rcDownButton; + RECT m_rcTrack; + RECT m_rcThumb; + int m_nPosition; // Position of the first displayed item + int m_nPageSize; // How many items are displayable in one page + int m_nStart; // First item + int m_nEnd; // The index after the last item + POINT m_LastMouse;// Last mouse position + ARROWSTATE m_Arrow; // State of the arrows + double m_dArrowTS; // Timestamp of last arrow event. +}; + + +//----------------------------------------------------------------------------- +// ListBox control +//----------------------------------------------------------------------------- +struct DXUTListBoxItem +{ + WCHAR strText[256]; + void* pData; + + RECT rcActive; + bool bSelected; +}; + +class CDXUTListBox : public CDXUTControl +{ +public: + CDXUTListBox( CDXUTDialog* pDialog = NULL ); + virtual ~CDXUTListBox(); + + virtual HRESULT OnInit() + { + return m_pDialog->InitControl( &m_ScrollBar ); + } + virtual bool CanHaveFocus() + { + return ( m_bVisible && m_bEnabled ); + } + virtual bool HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ); + virtual bool HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ); + virtual bool MsgProc( UINT uMsg, WPARAM wParam, LPARAM lParam ); + + virtual void Render( float fElapsedTime ); + virtual void UpdateRects(); + + DWORD GetStyle() const + { + return m_dwStyle; + } + int GetSize() const + { + return m_Items.GetSize(); + } + void SetStyle( DWORD dwStyle ) + { + m_dwStyle = dwStyle; + } + int GetScrollBarWidth() const + { + return m_nSBWidth; + } + void SetScrollBarWidth( int nWidth ) + { + m_nSBWidth = nWidth; UpdateRects(); + } + void SetBorder( int nBorder, int nMargin ) + { + m_nBorder = nBorder; m_nMargin = nMargin; + } + HRESULT AddItem( const WCHAR* wszText, void* pData ); + HRESULT InsertItem( int nIndex, const WCHAR* wszText, void* pData ); + void RemoveItem( int nIndex ); + void RemoveAllItems(); + + DXUTListBoxItem* GetItem( int nIndex ); + int GetSelectedIndex( int nPreviousSelected = -1 ); + DXUTListBoxItem* GetSelectedItem( int nPreviousSelected = -1 ) + { + return GetItem( GetSelectedIndex( nPreviousSelected ) ); + } + void SelectItem( int nNewIndex ); + + enum STYLE + { + MULTISELECTION = 1 + }; + +protected: + RECT m_rcText; // Text rendering bound + RECT m_rcSelection; // Selection box bound + CDXUTScrollBar m_ScrollBar; + int m_nSBWidth; + int m_nBorder; + int m_nMargin; + int m_nTextHeight; // Height of a single line of text + DWORD m_dwStyle; // List box style + int m_nSelected; // Index of the selected item for single selection list box + int m_nSelStart; // Index of the item where selection starts (for handling multi-selection) + bool m_bDrag; // Whether the user is dragging the mouse to select + + CGrowableArray m_Items; +}; + + +//----------------------------------------------------------------------------- +// ComboBox control +//----------------------------------------------------------------------------- +struct DXUTComboBoxItem +{ + WCHAR strText[256]; + void* pData; + + RECT rcActive; + bool bVisible; +}; + + +class CDXUTComboBox : public CDXUTButton +{ +public: + CDXUTComboBox( CDXUTDialog* pDialog = NULL ); + virtual ~CDXUTComboBox(); + + virtual void SetTextColor( D3DCOLOR Color ); + virtual HRESULT OnInit() + { + return m_pDialog->InitControl( &m_ScrollBar ); + } + + virtual bool HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ); + virtual bool HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ); + virtual void OnHotkey(); + + virtual bool CanHaveFocus() + { + return ( m_bVisible && m_bEnabled ); + } + virtual void OnFocusOut(); + virtual void Render( float fElapsedTime ); + + virtual void UpdateRects(); + + HRESULT AddItem( const WCHAR* strText, void* pData ); + void RemoveAllItems(); + void RemoveItem( UINT index ); + bool ContainsItem( const WCHAR* strText, UINT iStart=0 ); + int FindItem( const WCHAR* strText, UINT iStart=0 ); + void* GetItemData( const WCHAR* strText ); + void* GetItemData( int nIndex ); + void SetDropHeight( UINT nHeight ) + { + m_nDropHeight = nHeight; UpdateRects(); + } + int GetScrollBarWidth() const + { + return m_nSBWidth; + } + void SetScrollBarWidth( int nWidth ) + { + m_nSBWidth = nWidth; UpdateRects(); + } + + int GetSelectedIndex() const + { + return m_iSelected; + } + void* GetSelectedData(); + DXUTComboBoxItem* GetSelectedItem(); + + UINT GetNumItems() + { + return m_Items.GetSize(); + } + DXUTComboBoxItem* GetItem( UINT index ) + { + return m_Items.GetAt( index ); + } + + HRESULT SetSelectedByIndex( UINT index ); + HRESULT SetSelectedByText( const WCHAR* strText ); + HRESULT SetSelectedByData( void* pData ); + +protected: + int m_iSelected; + int m_iFocused; + int m_nDropHeight; + CDXUTScrollBar m_ScrollBar; + int m_nSBWidth; + + bool m_bOpened; + + RECT m_rcText; + RECT m_rcButton; + RECT m_rcDropdown; + RECT m_rcDropdownText; + + + CGrowableArray m_Items; +}; + + +//----------------------------------------------------------------------------- +// Slider control +//----------------------------------------------------------------------------- +class CDXUTSlider : public CDXUTControl +{ +public: + CDXUTSlider( CDXUTDialog* pDialog = NULL ); + + virtual BOOL ContainsPoint( POINT pt ); + virtual bool CanHaveFocus() + { + return ( m_bVisible && m_bEnabled ); + } + virtual bool HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ); + virtual bool HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ); + + virtual void UpdateRects(); + + virtual void Render( float fElapsedTime ); + + void SetValue( int nValue ) + { + SetValueInternal( nValue, false ); + } + int GetValue() const + { + return m_nValue; + }; + + void GetRange( int& nMin, int& nMax ) const + { + nMin = m_nMin; nMax = m_nMax; + } + void SetRange( int nMin, int nMax ); + +protected: + void SetValueInternal( int nValue, bool bFromInput ); + int ValueFromPos( int x ); + + int m_nValue; + + int m_nMin; + int m_nMax; + + int m_nDragX; // Mouse position at start of drag + int m_nDragOffset; // Drag offset from the center of the button + int m_nButtonX; + + bool m_bPressed; + RECT m_rcButton; +}; + + +//----------------------------------------------------------------------------- +// CUniBuffer class for the edit control +//----------------------------------------------------------------------------- +class CUniBuffer +{ +public: + CUniBuffer( int nInitialSize = 1 ); + ~CUniBuffer(); + + static void WINAPI Initialize(); + static void WINAPI Uninitialize(); + + int GetBufferSize() + { + return m_nBufferSize; + } + bool SetBufferSize( int nSize ); + int GetTextSize() + { + return lstrlenW( m_pwszBuffer ); + } + const WCHAR* GetBuffer() + { + return m_pwszBuffer; + } + const WCHAR& operator[]( int n ) const + { + return m_pwszBuffer[n]; + } + WCHAR& operator[]( int n ); + DXUTFontNode* GetFontNode() + { + return m_pFontNode; + } + void SetFontNode( DXUTFontNode* pFontNode ) + { + m_pFontNode = pFontNode; + } + void Clear(); + + bool InsertChar( int nIndex, WCHAR wChar ); // Inserts the char at specified index. If nIndex == -1, insert to the end. + bool RemoveChar( int nIndex ); // Removes the char at specified index. If nIndex == -1, remove the last char. + bool InsertString( int nIndex, const WCHAR* pStr, int nCount = -1 ); // Inserts the first nCount characters of the string pStr at specified index. If nCount == -1, the entire string is inserted. If nIndex == -1, insert to the end. + bool SetText( LPCWSTR wszText ); + + // Uniscribe + HRESULT CPtoX( int nCP, BOOL bTrail, int* pX ); + HRESULT XtoCP( int nX, int* pCP, int* pnTrail ); + void GetPriorItemPos( int nCP, int* pPrior ); + void GetNextItemPos( int nCP, int* pPrior ); + +private: + HRESULT Analyse(); // Uniscribe -- Analyse() analyses the string in the buffer + + WCHAR* m_pwszBuffer; // Buffer to hold text + int m_nBufferSize; // Size of the buffer allocated, in characters + + // Uniscribe-specific + DXUTFontNode* m_pFontNode; // Font node for the font that this buffer uses + bool m_bAnalyseRequired; // True if the string has changed since last analysis. + SCRIPT_STRING_ANALYSIS m_Analysis; // Analysis for the current string + +private: + // Empty implementation of the Uniscribe API + static HRESULT WINAPI Dummy_ScriptApplyDigitSubstitution( const SCRIPT_DIGITSUBSTITUTE*, SCRIPT_CONTROL*, + SCRIPT_STATE* ) + { + return E_NOTIMPL; + } + static HRESULT WINAPI Dummy_ScriptStringAnalyse( HDC, const void*, int, int, int, DWORD, int, SCRIPT_CONTROL*, + SCRIPT_STATE*, const int*, SCRIPT_TABDEF*, const BYTE*, + SCRIPT_STRING_ANALYSIS* ) + { + return E_NOTIMPL; + } + static HRESULT WINAPI Dummy_ScriptStringCPtoX( SCRIPT_STRING_ANALYSIS, int, BOOL, int* ) + { + return E_NOTIMPL; + } + static HRESULT WINAPI Dummy_ScriptStringXtoCP( SCRIPT_STRING_ANALYSIS, int, int*, int* ) + { + return E_NOTIMPL; + } + static HRESULT WINAPI Dummy_ScriptStringFree( SCRIPT_STRING_ANALYSIS* ) + { + return E_NOTIMPL; + } + static const SCRIPT_LOGATTR* WINAPI Dummy_ScriptString_pLogAttr( SCRIPT_STRING_ANALYSIS ) + { + return NULL; + } + static const int* WINAPI Dummy_ScriptString_pcOutChars( SCRIPT_STRING_ANALYSIS ) + { + return NULL; + } + + // Function pointers + static HRESULT( WINAPI* _ScriptApplyDigitSubstitution )( const SCRIPT_DIGITSUBSTITUTE*, + SCRIPT_CONTROL*, SCRIPT_STATE* ); + static HRESULT( WINAPI* _ScriptStringAnalyse )( HDC, const void*, int, int, int, DWORD, int, + SCRIPT_CONTROL*, SCRIPT_STATE*, const int*, + SCRIPT_TABDEF*, const BYTE*, + SCRIPT_STRING_ANALYSIS* ); + static HRESULT( WINAPI* _ScriptStringCPtoX )( SCRIPT_STRING_ANALYSIS, int, BOOL, int* ); + static HRESULT( WINAPI* _ScriptStringXtoCP )( SCRIPT_STRING_ANALYSIS, int, int*, int* ); + static HRESULT( WINAPI* _ScriptStringFree )( SCRIPT_STRING_ANALYSIS* ); + static const SCRIPT_LOGATTR* ( WINAPI*_ScriptString_pLogAttr )( SCRIPT_STRING_ANALYSIS ); + static const int* ( WINAPI*_ScriptString_pcOutChars )( SCRIPT_STRING_ANALYSIS ); + + static HINSTANCE s_hDll; // Uniscribe DLL handle + +}; + +//----------------------------------------------------------------------------- +// EditBox control +//----------------------------------------------------------------------------- +class CDXUTEditBox : public CDXUTControl +{ +public: + CDXUTEditBox( CDXUTDialog* pDialog = NULL ); + virtual ~CDXUTEditBox(); + + virtual bool HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ); + virtual bool HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ); + virtual bool MsgProc( UINT uMsg, WPARAM wParam, LPARAM lParam ); + virtual void UpdateRects(); + virtual bool CanHaveFocus() + { + return ( m_bVisible && m_bEnabled ); + } + virtual void Render( float fElapsedTime ); + virtual void OnFocusIn(); + + void SetText( LPCWSTR wszText, bool bSelected = false ); + LPCWSTR GetText() + { + return m_Buffer.GetBuffer(); + } + int GetTextLength() + { + return m_Buffer.GetTextSize(); + } // Returns text length in chars excluding NULL. + HRESULT GetTextCopy( __out_ecount(bufferCount) LPWSTR strDest, + UINT bufferCount ); + void ClearText(); + virtual void SetTextColor( D3DCOLOR Color ) + { + m_TextColor = Color; + } // Text color + void SetSelectedTextColor( D3DCOLOR Color ) + { + m_SelTextColor = Color; + } // Selected text color + void SetSelectedBackColor( D3DCOLOR Color ) + { + m_SelBkColor = Color; + } // Selected background color + void SetCaretColor( D3DCOLOR Color ) + { + m_CaretColor = Color; + } // Caret color + void SetBorderWidth( int nBorder ) + { + m_nBorder = nBorder; UpdateRects(); + } // Border of the window + void SetSpacing( int nSpacing ) + { + m_nSpacing = nSpacing; UpdateRects(); + } + void ParseFloatArray( float* pNumbers, int nCount ); + void SetTextFloatArray( const float* pNumbers, int nCount ); + +protected: + void PlaceCaret( int nCP ); + void DeleteSelectionText(); + void ResetCaretBlink(); + void CopyToClipboard(); + void PasteFromClipboard(); + + CUniBuffer m_Buffer; // Buffer to hold text + int m_nBorder; // Border of the window + int m_nSpacing; // Spacing between the text and the edge of border + RECT m_rcText; // Bounding rectangle for the text + RECT m_rcRender[9]; // Convenient rectangles for rendering elements + double m_dfBlink; // Caret blink time in milliseconds + double m_dfLastBlink; // Last timestamp of caret blink + bool m_bCaretOn; // Flag to indicate whether caret is currently visible + int m_nCaret; // Caret position, in characters + bool m_bInsertMode; // If true, control is in insert mode. Else, overwrite mode. + int m_nSelStart; // Starting position of the selection. The caret marks the end. + int m_nFirstVisible;// First visible character in the edit control + D3DCOLOR m_TextColor; // Text color + D3DCOLOR m_SelTextColor; // Selected text color + D3DCOLOR m_SelBkColor; // Selected background color + D3DCOLOR m_CaretColor; // Caret color + + // Mouse-specific + bool m_bMouseDrag; // True to indicate drag in progress + + // Static + static bool s_bHideCaret; // If true, we don't render the caret. +}; + + + + +#endif // DXUT_GUI_H diff --git a/Demos/DX11ClothDemo/DXUT/Optional/DXUTguiIME.cpp b/Demos/DX11ClothDemo/DXUT/Optional/DXUTguiIME.cpp new file mode 100644 index 0000000..1196179 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/DXUTguiIME.cpp @@ -0,0 +1,990 @@ +//-------------------------------------------------------------------------------------- +// File: DXUTguiIME.cpp +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "DXUT.h" +#include "DXUTgui.h" +#include "DXUTsettingsDlg.h" +#include "DXUTres.h" +#include "DXUTgui.h" +#include "DXUTguiIME.h" + +#undef min // use __min instead +#undef max // use __max instead +#define DXUT_NEAR_BUTTON_DEPTH 0.6f + + +//-------------------------------------------------------------------------------------- +// CDXUTIMEEditBox class +//-------------------------------------------------------------------------------------- +// IME constants + +POINT CDXUTIMEEditBox::s_ptCompString; // Composition string position. Updated every frame. +int CDXUTIMEEditBox::s_nFirstTargetConv; // Index of the first target converted char in comp string. If none, -1. +CUniBuffer CDXUTIMEEditBox::s_CompString = CUniBuffer( 0 ); +DWORD CDXUTIMEEditBox::s_adwCompStringClause[MAX_COMPSTRING_SIZE]; +WCHAR CDXUTIMEEditBox::s_wszReadingString[32]; +CDXUTIMEEditBox::CCandList CDXUTIMEEditBox::s_CandList; // Data relevant to the candidate list +bool CDXUTIMEEditBox::s_bImeFlag = true; + + +#if defined(DEBUG) || defined(_DEBUG) +bool CDXUTIMEEditBox::m_bIMEStaticMsgProcCalled = false; +#endif + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTIMEEditBox::CreateIMEEditBox( CDXUTDialog* pDialog, int ID, LPCWSTR strText, int x, int y, int width, + int height, bool bIsDefault, CDXUTIMEEditBox** ppCreated ) +{ + CDXUTIMEEditBox* pEditBox = new CDXUTIMEEditBox( pDialog ); + + if( ppCreated != NULL ) + *ppCreated = pEditBox; + + if( pEditBox == NULL ) + return E_OUTOFMEMORY; + + // Set the ID and position + pEditBox->SetID( ID ); + pEditBox->SetLocation( x, y ); + pEditBox->SetSize( width, height ); + pEditBox->m_bIsDefault = bIsDefault; + + if( strText ) + pEditBox->SetText( strText ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTIMEEditBox::InitDefaultElements( CDXUTDialog* pDialog ) +{ + //------------------------------------- + // CDXUTIMEEditBox + //------------------------------------- + + CDXUTElement Element; + RECT rcTexture; + + Element.SetFont( 0, D3DCOLOR_ARGB( 255, 0, 0, 0 ), DT_LEFT | DT_TOP ); + + // Assign the style + SetRect( &rcTexture, 14, 90, 241, 113 ); + Element.SetTexture( 0, &rcTexture ); + pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 0, &Element ); + SetRect( &rcTexture, 8, 82, 14, 90 ); + Element.SetTexture( 0, &rcTexture ); + pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 1, &Element ); + SetRect( &rcTexture, 14, 82, 241, 90 ); + Element.SetTexture( 0, &rcTexture ); + pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 2, &Element ); + SetRect( &rcTexture, 241, 82, 246, 90 ); + Element.SetTexture( 0, &rcTexture ); + pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 3, &Element ); + SetRect( &rcTexture, 8, 90, 14, 113 ); + Element.SetTexture( 0, &rcTexture ); + pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 4, &Element ); + SetRect( &rcTexture, 241, 90, 246, 113 ); + Element.SetTexture( 0, &rcTexture ); + pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 5, &Element ); + SetRect( &rcTexture, 8, 113, 14, 121 ); + Element.SetTexture( 0, &rcTexture ); + pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 6, &Element ); + SetRect( &rcTexture, 14, 113, 241, 121 ); + Element.SetTexture( 0, &rcTexture ); + pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 7, &Element ); + SetRect( &rcTexture, 241, 113, 246, 121 ); + Element.SetTexture( 0, &rcTexture ); + pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 8, &Element ); + // Element 9 for IME text, and indicator button + SetRect( &rcTexture, 0, 0, 136, 54 ); + Element.SetTexture( 0, &rcTexture ); + Element.SetFont( 0, D3DCOLOR_ARGB( 255, 0, 0, 0 ), DT_CENTER | DT_VCENTER ); + pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 9, &Element ); +} + + +//-------------------------------------------------------------------------------------- +CDXUTIMEEditBox::CDXUTIMEEditBox( CDXUTDialog* pDialog ) +{ + m_Type = DXUT_CONTROL_IMEEDITBOX; + m_pDialog = pDialog; + + m_nIndicatorWidth = 0; + m_ReadingColor = D3DCOLOR_ARGB( 188, 255, 255, 255 ); + m_ReadingWinColor = D3DCOLOR_ARGB( 128, 0, 0, 0 ); + m_ReadingSelColor = D3DCOLOR_ARGB( 255, 255, 0, 0 ); + m_ReadingSelBkColor = D3DCOLOR_ARGB( 128, 80, 80, 80 ); + m_CandidateColor = D3DCOLOR_ARGB( 255, 200, 200, 200 ); + m_CandidateWinColor = D3DCOLOR_ARGB( 128, 0, 0, 0 ); + m_CandidateSelColor = D3DCOLOR_ARGB( 255, 255, 255, 255 ); + m_CandidateSelBkColor = D3DCOLOR_ARGB( 128, 158, 158, 158 ); + m_CompColor = D3DCOLOR_ARGB( 255, 200, 200, 255 ); + m_CompWinColor = D3DCOLOR_ARGB( 198, 0, 0, 0 ); + m_CompCaretColor = D3DCOLOR_ARGB( 255, 255, 255, 255 ); + m_CompTargetColor = D3DCOLOR_ARGB( 255, 255, 255, 255 ); + m_CompTargetBkColor = D3DCOLOR_ARGB( 255, 150, 150, 150 ); + m_CompTargetNonColor = D3DCOLOR_ARGB( 255, 255, 255, 0 ); + m_CompTargetNonBkColor = D3DCOLOR_ARGB( 255, 150, 150, 150 ); + m_IndicatorImeColor = D3DCOLOR_ARGB( 255, 255, 255, 255 ); + m_IndicatorEngColor = D3DCOLOR_ARGB( 255, 0, 0, 0 ); + m_IndicatorBkColor = D3DCOLOR_ARGB( 255, 128, 128, 128 ); +} + + +//-------------------------------------------------------------------------------------- +CDXUTIMEEditBox::~CDXUTIMEEditBox() +{ +} + + +//-------------------------------------------------------------------------------------- +void CDXUTIMEEditBox::SendKey( BYTE nVirtKey ) +{ + keybd_event( nVirtKey, 0, 0, 0 ); + keybd_event( nVirtKey, 0, KEYEVENTF_KEYUP, 0 ); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTIMEEditBox::UpdateRects() +{ + // Temporary adjust m_width so that CDXUTEditBox can compute + // the correct rects for its rendering since we need to make space + // for the indicator button + int nWidth = m_width; + m_width -= m_nIndicatorWidth + m_nBorder * 2; // Make room for the indicator button + CDXUTEditBox::UpdateRects(); + m_width = nWidth; // Restore + + // Compute the indicator button rectangle + SetRect( &m_rcIndicator, m_rcBoundingBox.right, m_rcBoundingBox.top, m_x + m_width, m_rcBoundingBox.bottom ); + // InflateRect( &m_rcIndicator, -m_nBorder, -m_nBorder ); + m_rcBoundingBox.right = m_rcBoundingBox.left + m_width; +} + + +//-------------------------------------------------------------------------------------- +// GetImeId( UINT uIndex ) +// returns +// returned value: +// 0: In the following cases +// - Non Chinese IME input locale +// - Older Chinese IME +// - Other error cases +// +// Othewise: +// When uIndex is 0 (default) +// bit 31-24: Major version +// bit 23-16: Minor version +// bit 15-0: Language ID +// When uIndex is 1 +// pVerFixedInfo->dwFileVersionLS +// +// Use IMEID_VER and IMEID_LANG macro to extract version and language information. +// + +// We define the locale-invariant ID ourselves since it doesn't exist prior to WinXP +// For more information, see the CompareString() reference. +#define LCID_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) +//-------------------------------------------------------------------------------------- +// Enable/disable the entire IME system. When disabled, the default IME handling +// kicks in. +void CDXUTIMEEditBox::EnableImeSystem( bool bEnable ) +{ + ImeUi_EnableIme( bEnable ); +} + + +//-------------------------------------------------------------------------------------- +// Resets the composition string. +void CDXUTIMEEditBox::ResetCompositionString() +{ + s_CompString.SetText( L"" ); +} + + +//-------------------------------------------------------------------------------------- +// This function is used only briefly in CHT IME handling, +// so accelerator isn't processed. +void CDXUTIMEEditBox::PumpMessage() +{ + MSG msg; + + while( PeekMessageW( &msg, NULL, 0, 0, PM_NOREMOVE ) ) + { + if( !GetMessageW( &msg, NULL, 0, 0 ) ) + { + PostQuitMessage( ( int )msg.wParam ); + return; + } + TranslateMessage( &msg ); + DispatchMessageA( &msg ); + } +} + + +//-------------------------------------------------------------------------------------- +void CDXUTIMEEditBox::OnFocusIn() +{ + ImeUi_EnableIme( s_bImeFlag ); + CDXUTEditBox::OnFocusIn(); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTIMEEditBox::OnFocusOut() +{ + ImeUi_FinalizeString(); + ImeUi_EnableIme( false ); + CDXUTEditBox::OnFocusOut(); +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTIMEEditBox::StaticMsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + + if( !ImeUi_IsEnabled() ) + return false; + +#if defined(DEBUG) || defined(_DEBUG) + m_bIMEStaticMsgProcCalled = true; +#endif + + switch( uMsg ) + { + case WM_INPUTLANGCHANGE: + DXUTTRACE( L"WM_INPUTLANGCHANGE\n" ); + { + } + return true; + + case WM_IME_SETCONTEXT: + DXUTTRACE( L"WM_IME_SETCONTEXT\n" ); + // + // We don't want anything to display, so we have to clear this + // + lParam = 0; + return false; + + // Handle WM_IME_STARTCOMPOSITION here since + // we do not want the default IME handler to see + // this when our fullscreen app is running. + case WM_IME_STARTCOMPOSITION: + DXUTTRACE( L"WM_IME_STARTCOMPOSITION\n" ); + ResetCompositionString(); + // Since the composition string has its own caret, we don't render + // the edit control's own caret to avoid double carets on screen. + s_bHideCaret = true; + return true; + case WM_IME_ENDCOMPOSITION: + DXUTTRACE( L"WM_IME_ENDCOMPOSITION\n" ); + s_bHideCaret = false; + return false; + case WM_IME_COMPOSITION: + DXUTTRACE( L"WM_IME_COMPOSITION\n" ); + return false; + } + + return false; +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTIMEEditBox::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ) +{ + if( !m_bEnabled || !m_bVisible ) + return false; + + switch( uMsg ) + { + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + { + DXUTFontNode* pFont = m_pDialog->GetFont( m_Elements.GetAt( 9 )->iFont ); + + // Check if this click is on top of the composition string + int nCompStrWidth; + s_CompString.CPtoX( s_CompString.GetTextSize(), FALSE, &nCompStrWidth ); + + if( s_ptCompString.x <= pt.x && + s_ptCompString.y <= pt.y && + s_ptCompString.x + nCompStrWidth > pt.x && + s_ptCompString.y + pFont->nHeight > pt.y ) + { + int nCharBodyHit, nCharHit; + int nTrail; + + // Determine the character clicked on. + s_CompString.XtoCP( pt.x - s_ptCompString.x, &nCharBodyHit, &nTrail ); + if( nTrail && nCharBodyHit < s_CompString.GetTextSize() ) + nCharHit = nCharBodyHit + 1; + else + nCharHit = nCharBodyHit; + + + switch( GetPrimaryLanguage() ) + { + case LANG_JAPANESE: + // For Japanese, there are two cases. If s_nFirstTargetConv is + // -1, the comp string hasn't been converted yet, and we use + // s_nCompCaret. For any other value of s_nFirstTargetConv, + // the string has been converted, so we use clause information. + + if( s_nFirstTargetConv != -1 ) + { + int nClauseClicked = 0; + while( ( int )s_adwCompStringClause[nClauseClicked + 1] <= nCharBodyHit ) + ++nClauseClicked; + + int nClauseSelected = 0; + while( ( int )s_adwCompStringClause[nClauseSelected + 1] <= s_nFirstTargetConv ) + ++nClauseSelected; + + BYTE nVirtKey = nClauseClicked > nClauseSelected ? VK_RIGHT : VK_LEFT; + int nSendCount = abs( nClauseClicked - nClauseSelected ); + while( nSendCount-- > 0 ) + SendKey( nVirtKey ); + + return true; + } + + // Not converted case. Fall thru to Chinese case. + + case LANG_CHINESE: + { + // For Chinese, use s_nCompCaret. + BYTE nVirtKey = nCharHit > ( int )ImeUi_GetImeCursorChars() ? VK_RIGHT : VK_LEFT; + int nSendCount = abs( nCharHit - ( int )ImeUi_GetImeCursorChars() ); + while( nSendCount-- > 0 ) + SendKey( nVirtKey ); + break; + } + } + + return true; + } + + // Check if the click is on top of the candidate window + if( ImeUi_IsShowCandListWindow() && PtInRect( &s_CandList.rcCandidate, pt ) ) + { + if( ImeUi_IsVerticalCand() ) + { + // Vertical candidate window + + // Compute the row the click is on + int nRow = ( pt.y - s_CandList.rcCandidate.top ) / pFont->nHeight; + + if( nRow < ( int )ImeUi_GetCandidateCount() ) + { + // nRow is a valid entry. + // Now emulate keystrokes to select the candidate at this row. + switch( GetPrimaryLanguage() ) + { + case LANG_CHINESE: + case LANG_KOREAN: + // For Chinese and Korean, simply send the number keystroke. + SendKey( ( BYTE )( '0' + nRow + 1 ) ); + break; + + case LANG_JAPANESE: + // For Japanese, move the selection to the target row, + // then send Right, then send Left. + + BYTE nVirtKey; + if( nRow > ( int )ImeUi_GetCandidateSelection() ) + nVirtKey = VK_DOWN; + else + nVirtKey = VK_UP; + int nNumToHit = abs( int( nRow - ImeUi_GetCandidateSelection() ) ); + for( int nStrike = 0; nStrike < nNumToHit; ++nStrike ) + SendKey( nVirtKey ); + + // Do this to close the candidate window without ending composition. + SendKey( VK_RIGHT ); + SendKey( VK_LEFT ); + + break; + } + } + } + else + { + // Horizontal candidate window + + // Determine which the character the click has hit. + int nCharHit; + int nTrail; + s_CandList.HoriCand.XtoCP( pt.x - s_CandList.rcCandidate.left, &nCharHit, &nTrail ); + + // Determine which candidate string the character belongs to. + int nCandidate = ImeUi_GetCandidateCount() - 1; + + int nEntryStart = 0; + for( UINT i = 0; i < ImeUi_GetCandidateCount(); ++i ) + { + if( nCharHit >= nEntryStart ) + { + // Haven't found it. + nEntryStart += lstrlenW( ImeUi_GetCandidate( i ) ) + 1; // plus space separator + } + else + { + // Found it. This entry starts at the right side of the click point, + // so the char belongs to the previous entry. + nCandidate = i - 1; + break; + } + } + + // Now emulate keystrokes to select the candidate entry. + switch( GetPrimaryLanguage() ) + { + case LANG_CHINESE: + case LANG_KOREAN: + // For Chinese and Korean, simply send the number keystroke. + SendKey( ( BYTE )( '0' + nCandidate + 1 ) ); + break; + } + } + + return true; + } + } + } + + // If we didn't care for the msg, let the parent process it. + return CDXUTEditBox::HandleMouse( uMsg, pt, wParam, lParam ); +} + + +//-------------------------------------------------------------------------------------- +bool CDXUTIMEEditBox::MsgProc( UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + if( !m_bEnabled || !m_bVisible ) + return false; + +#if defined(DEBUG) || defined(_DEBUG) + // DXUT.cpp used to call CDXUTIMEEditBox::StaticMsgProc() so that, but now + // this is the application's responsiblity. To do this, call + // CDXUTDialogResourceManager::MsgProc() before calling this function. + assert( m_bIMEStaticMsgProcCalled && L"To fix, call CDXUTDialogResourceManager::MsgProc() first" ); +#endif + switch( uMsg ) + { + case WM_DESTROY: + ImeUi_Uninitialize(); + break; + } + + bool trappedData; + bool* trapped = &trappedData; + + *trapped = false; + if( !ImeUi_IsEnabled() ) + return CDXUTEditBox::MsgProc( uMsg, wParam, lParam ); + + ImeUi_ProcessMessage( DXUTGetHWND(), uMsg, wParam, lParam, trapped ); + if( *trapped == false ) + CDXUTEditBox::MsgProc( uMsg, wParam, lParam ); + + return *trapped; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTIMEEditBox::RenderCandidateReadingWindow( float fElapsedTime, bool bReading ) +{ + RECT rc; + UINT nNumEntries = bReading ? 4 : MAX_CANDLIST; + D3DCOLOR TextColor, TextBkColor, SelTextColor, SelBkColor; + int nX, nXFirst, nXComp; + m_Buffer.CPtoX( m_nCaret, FALSE, &nX ); + m_Buffer.CPtoX( m_nFirstVisible, FALSE, &nXFirst ); + + if( bReading ) + { + TextColor = m_ReadingColor; + TextBkColor = m_ReadingWinColor; + SelTextColor = m_ReadingSelColor; + SelBkColor = m_ReadingSelBkColor; + } + else + { + TextColor = m_CandidateColor; + TextBkColor = m_CandidateWinColor; + SelTextColor = m_CandidateSelColor; + SelBkColor = m_CandidateSelBkColor; + } + + // For Japanese IME, align the window with the first target converted character. + // For all other IMEs, align with the caret. This is because the caret + // does not move for Japanese IME. + if( GetLanguage() == MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL ) && !GetImeId() ) + nXComp = 0; + else if( GetPrimaryLanguage() == LANG_JAPANESE ) + s_CompString.CPtoX( s_nFirstTargetConv, FALSE, &nXComp ); + else + s_CompString.CPtoX( ImeUi_GetImeCursorChars(), FALSE, &nXComp ); + + // Compute the size of the candidate window + int nWidthRequired = 0; + int nHeightRequired = 0; + int nSingleLineHeight = 0; + + if( ( ImeUi_IsVerticalCand() && !bReading ) || + ( !ImeUi_IsHorizontalReading() && bReading ) ) + { + // Vertical window + for( UINT i = 0; i < nNumEntries; ++i ) + { + if( *( ImeUi_GetCandidate( i ) ) == L'\0' ) + break; + SetRect( &rc, 0, 0, 0, 0 ); + m_pDialog->CalcTextRect( ImeUi_GetCandidate( i ), m_Elements.GetAt( 1 ), &rc ); + nWidthRequired = __max( nWidthRequired, rc.right - rc.left ); + nSingleLineHeight = __max( nSingleLineHeight, rc.bottom - rc.top ); + } + nHeightRequired = nSingleLineHeight * nNumEntries; + } + else + { + // Horizontal window + SetRect( &rc, 0, 0, 0, 0 ); + if( bReading ) + m_pDialog->CalcTextRect( s_wszReadingString, m_Elements.GetAt( 1 ), &rc ); + else + { + + WCHAR wszCand[256] = L""; + + s_CandList.nFirstSelected = 0; + s_CandList.nHoriSelectedLen = 0; + for( UINT i = 0; i < MAX_CANDLIST; ++i ) + { + if( *ImeUi_GetCandidate( i ) == L'\0' ) + break; + + WCHAR wszEntry[32]; + swprintf_s( wszEntry, 32, L"%s ", ImeUi_GetCandidate( i ) ); + // If this is the selected entry, mark its char position. + if( ImeUi_GetCandidateSelection() == i ) + { + s_CandList.nFirstSelected = lstrlen( wszCand ); + s_CandList.nHoriSelectedLen = lstrlen( wszEntry ) - 1; // Minus space + } + wcscat_s( wszCand, 256, wszEntry ); + } + wszCand[lstrlen( wszCand ) - 1] = L'\0'; // Remove the last space + s_CandList.HoriCand.SetText( wszCand ); + + m_pDialog->CalcTextRect( s_CandList.HoriCand.GetBuffer(), m_Elements.GetAt( 1 ), &rc ); + } + nWidthRequired = rc.right - rc.left; + nSingleLineHeight = nHeightRequired = rc.bottom - rc.top; + } + + // Now that we have the dimension, calculate the location for the candidate window. + // We attempt to fit the window in this order: + // bottom, top, right, left. + + bool bHasPosition = false; + + // Bottom + SetRect( &rc, s_ptCompString.x + nXComp, s_ptCompString.y + m_rcText.bottom - m_rcText.top, + s_ptCompString.x + nXComp + nWidthRequired, s_ptCompString.y + m_rcText.bottom - m_rcText.top + + nHeightRequired ); + // if the right edge is cut off, move it left. + if( rc.right > m_pDialog->GetWidth() ) + { + rc.left -= rc.right - m_pDialog->GetWidth(); + rc.right = m_pDialog->GetWidth(); + } + if( rc.bottom <= m_pDialog->GetHeight() ) + bHasPosition = true; + + // Top + if( !bHasPosition ) + { + SetRect( &rc, s_ptCompString.x + nXComp, s_ptCompString.y - nHeightRequired, + s_ptCompString.x + nXComp + nWidthRequired, s_ptCompString.y ); + // if the right edge is cut off, move it left. + if( rc.right > m_pDialog->GetWidth() ) + { + rc.left -= rc.right - m_pDialog->GetWidth(); + rc.right = m_pDialog->GetWidth(); + } + if( rc.top >= 0 ) + bHasPosition = true; + } + + // Right + if( !bHasPosition ) + { + int nXCompTrail; + s_CompString.CPtoX( ImeUi_GetImeCursorChars(), TRUE, &nXCompTrail ); + SetRect( &rc, s_ptCompString.x + nXCompTrail, 0, + s_ptCompString.x + nXCompTrail + nWidthRequired, nHeightRequired ); + if( rc.right <= m_pDialog->GetWidth() ) + bHasPosition = true; + } + + // Left + if( !bHasPosition ) + { + SetRect( &rc, s_ptCompString.x + nXComp - nWidthRequired, 0, + s_ptCompString.x + nXComp, nHeightRequired ); + if( rc.right >= 0 ) + bHasPosition = true; + } + + if( !bHasPosition ) + { + // The dialog is too small for the candidate window. + // Fall back to render at 0, 0. Some part of the window + // will be cut off. + rc.left = 0; + rc.right = nWidthRequired; + } + + // If we are rendering the candidate window, save the position + // so that mouse clicks are checked properly. + if( !bReading ) + s_CandList.rcCandidate = rc; + + // Render the elements + m_pDialog->DrawRect( &rc, TextBkColor ); + if( ( ImeUi_IsVerticalCand() && !bReading ) || + ( !ImeUi_IsHorizontalReading() && bReading ) ) + { + // Vertical candidate window + for( UINT i = 0; i < nNumEntries; ++i ) + { + // Here we are rendering one line at a time + rc.bottom = rc.top + nSingleLineHeight; + // Use a different color for the selected string + if( ImeUi_GetCandidateSelection() == i ) + { + m_pDialog->DrawRect( &rc, SelBkColor ); + m_Elements.GetAt( 1 )->FontColor.Current = SelTextColor; + } + else + m_Elements.GetAt( 1 )->FontColor.Current = TextColor; + + m_pDialog->DrawText( ImeUi_GetCandidate( i ), m_Elements.GetAt( 1 ), &rc ); + + rc.top += nSingleLineHeight; + } + } + else + { + // Horizontal candidate window + m_Elements.GetAt( 1 )->FontColor.Current = TextColor; + if( bReading ) + m_pDialog->DrawText( s_wszReadingString, m_Elements.GetAt( 1 ), &rc ); + else + m_pDialog->DrawText( s_CandList.HoriCand.GetBuffer(), m_Elements.GetAt( 1 ), &rc ); + + // Render the selected entry differently + if( !bReading ) + { + int nXLeft, nXRight; + s_CandList.HoriCand.CPtoX( s_CandList.nFirstSelected, FALSE, &nXLeft ); + s_CandList.HoriCand.CPtoX( s_CandList.nFirstSelected + s_CandList.nHoriSelectedLen, FALSE, &nXRight ); + + rc.right = rc.left + nXRight; + rc.left += nXLeft; + m_pDialog->DrawRect( &rc, SelBkColor ); + m_Elements.GetAt( 1 )->FontColor.Current = SelTextColor; + m_pDialog->DrawText( s_CandList.HoriCand.GetBuffer() + s_CandList.nFirstSelected, + m_Elements.GetAt( 1 ), &rc, false, s_CandList.nHoriSelectedLen ); + } + } +} + + +//-------------------------------------------------------------------------------------- +void CDXUTIMEEditBox::RenderComposition( float fElapsedTime ) +{ + + s_CompString.SetText( ImeUi_GetCompositionString() ); + + RECT rcCaret = + { + 0, 0, 0, 0 + }; + int nX, nXFirst; + m_Buffer.CPtoX( m_nCaret, FALSE, &nX ); + m_Buffer.CPtoX( m_nFirstVisible, FALSE, &nXFirst ); + CDXUTElement* pElement = m_Elements.GetAt( 1 ); + + // Get the required width + RECT rc = + { + m_rcText.left + nX - nXFirst, m_rcText.top, + m_rcText.left + nX - nXFirst, m_rcText.bottom + }; + m_pDialog->CalcTextRect( s_CompString.GetBuffer(), pElement, &rc ); + + // If the composition string is too long to fit within + // the text area, move it to below the current line. + // This matches the behavior of the default IME. + if( rc.right > m_rcText.right ) + OffsetRect( &rc, m_rcText.left - rc.left, rc.bottom - rc.top ); + + // Save the rectangle position for processing highlighted text. + RECT rcFirst = rc; + + // Update s_ptCompString for RenderCandidateReadingWindow(). + s_ptCompString.x = rc.left; s_ptCompString.y = rc.top; + + + D3DCOLOR TextColor = m_CompColor; + // Render the window and string. + // If the string is too long, we must wrap the line. + pElement->FontColor.Current = TextColor; + const WCHAR* pwszComp = s_CompString.GetBuffer(); + int nCharLeft = s_CompString.GetTextSize(); + for(; ; ) + { + // Find the last character that can be drawn on the same line. + int nLastInLine; + int bTrail; + s_CompString.XtoCP( m_rcText.right - rc.left, &nLastInLine, &bTrail ); + int nNumCharToDraw = __min( nCharLeft, nLastInLine ); + m_pDialog->CalcTextRect( pwszComp, pElement, &rc, nNumCharToDraw ); + + // Draw the background + // For Korean IME, blink the composition window background as if it + // is a cursor. + if( GetPrimaryLanguage() == LANG_KOREAN ) + { + if( m_bCaretOn ) + { + m_pDialog->DrawRect( &rc, m_CompWinColor ); + } + else + { + // Not drawing composition string background. We + // use the editbox's text color for composition + // string text. + TextColor = m_Elements.GetAt( 0 )->FontColor.States[DXUT_STATE_NORMAL]; + } + } + else + { + // Non-Korean IME. Always draw composition background. + m_pDialog->DrawRect( &rc, m_CompWinColor ); + } + + // Draw the text + pElement->FontColor.Current = TextColor; + m_pDialog->DrawText( pwszComp, pElement, &rc, false, nNumCharToDraw ); + + // Advance pointer and counter + nCharLeft -= nNumCharToDraw; + pwszComp += nNumCharToDraw; + if( nCharLeft <= 0 ) + break; + + // Advance rectangle coordinates to beginning of next line + OffsetRect( &rc, m_rcText.left - rc.left, rc.bottom - rc.top ); + } + + // Load the rect for the first line again. + rc = rcFirst; + + // Inspect each character in the comp string. + // For target-converted and target-non-converted characters, + // we display a different background color so they appear highlighted. + int nCharFirst = 0; + nXFirst = 0; + s_nFirstTargetConv = -1; + BYTE* pAttr; + const WCHAR* pcComp; + for( pcComp = s_CompString.GetBuffer(), pAttr = ImeUi_GetCompStringAttr(); + *pcComp != L'\0'; ++pcComp, ++pAttr ) + { + D3DCOLOR bkColor; + + // Render a different background for this character + int nXLeft, nXRight; + s_CompString.CPtoX( int( pcComp - s_CompString.GetBuffer() ), FALSE, &nXLeft ); + s_CompString.CPtoX( int( pcComp - s_CompString.GetBuffer() ), TRUE, &nXRight ); + + // Check if this character is off the right edge and should + // be wrapped to the next line. + if( nXRight - nXFirst > m_rcText.right - rc.left ) + { + // Advance rectangle coordinates to beginning of next line + OffsetRect( &rc, m_rcText.left - rc.left, rc.bottom - rc.top ); + + // Update the line's first character information + nCharFirst = int( pcComp - s_CompString.GetBuffer() ); + s_CompString.CPtoX( nCharFirst, FALSE, &nXFirst ); + } + + // If the caret is on this character, save the coordinates + // for drawing the caret later. + if( ImeUi_GetImeCursorChars() == ( DWORD )( pcComp - s_CompString.GetBuffer() ) ) + { + rcCaret = rc; + rcCaret.left += nXLeft - nXFirst - 1; + rcCaret.right = rcCaret.left + 2; + } + + // Set up color based on the character attribute + if( *pAttr == ATTR_TARGET_CONVERTED ) + { + pElement->FontColor.Current = m_CompTargetColor; + bkColor = m_CompTargetBkColor; + } + else if( *pAttr == ATTR_TARGET_NOTCONVERTED ) + { + pElement->FontColor.Current = m_CompTargetNonColor; + bkColor = m_CompTargetNonBkColor; + } + else + { + continue; + } + + RECT rcTarget = + { + rc.left + nXLeft - nXFirst, rc.top, rc.left + nXRight - nXFirst, rc.bottom + }; + m_pDialog->DrawRect( &rcTarget, bkColor ); + m_pDialog->DrawText( pcComp, pElement, &rcTarget, false, 1 ); + + // Record the first target converted character's index + if( -1 == s_nFirstTargetConv ) + s_nFirstTargetConv = int( pAttr - ImeUi_GetCompStringAttr() ); + } + + // Render the composition caret + if( m_bCaretOn ) + { + // If the caret is at the very end, its position would not have + // been computed in the above loop. We compute it here. + if( ImeUi_GetImeCursorChars() == ( DWORD )s_CompString.GetTextSize() ) + { + s_CompString.CPtoX( ImeUi_GetImeCursorChars(), FALSE, &nX ); + rcCaret = rc; + rcCaret.left += nX - nXFirst - 1; + rcCaret.right = rcCaret.left + 2; + } + + m_pDialog->DrawRect( &rcCaret, m_CompCaretColor ); + } +} + + +//-------------------------------------------------------------------------------------- +void CDXUTIMEEditBox::RenderIndicator( float fElapsedTime ) +{ + CDXUTElement* pElement = m_Elements.GetAt( 9 ); + pElement->TextureColor.Blend( DXUT_STATE_NORMAL, fElapsedTime ); + + m_pDialog->DrawSprite( pElement, &m_rcIndicator, DXUT_NEAR_BUTTON_DEPTH ); + RECT rc = m_rcIndicator; + InflateRect( &rc, -m_nSpacing, -m_nSpacing ); + + pElement->FontColor.Current = m_IndicatorImeColor; + RECT rcCalc = + { + 0, 0, 0, 0 + }; + // If IME system is off, draw English indicator. + WCHAR* pwszIndicator = ImeUi_IsEnabled() ? ImeUi_GetIndicatior() : L"En"; + + m_pDialog->CalcTextRect( pwszIndicator, pElement, &rcCalc ); + m_pDialog->DrawText( pwszIndicator, pElement, &rc ); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTIMEEditBox::Render( float fElapsedTime ) +{ + if( m_bVisible == false ) + return; + + // If we have not computed the indicator symbol width, + // do it. + if( !m_nIndicatorWidth ) + { + RECT rc = + { + 0, 0, 0, 0 + }; + m_pDialog->CalcTextRect( L"En", m_Elements.GetAt( 9 ), &rc ); + m_nIndicatorWidth = rc.right - rc.left; + + // Update the rectangles now that we have the indicator's width + UpdateRects(); + } + + // Let the parent render first (edit control) + CDXUTEditBox::Render( fElapsedTime ); + + CDXUTElement* pElement = GetElement( 1 ); + if( pElement ) + { + s_CompString.SetFontNode( m_pDialog->GetFont( pElement->iFont ) ); + s_CandList.HoriCand.SetFontNode( m_pDialog->GetFont( pElement->iFont ) ); + } + + // + // Now render the IME elements + // + + ImeUi_RenderUI(); + + if( m_bHasFocus ) + { + // Render the input locale indicator + RenderIndicator( fElapsedTime ); + + // Display the composition string. + // This method should also update s_ptCompString + // for RenderCandidateReadingWindow. + RenderComposition( fElapsedTime ); + + // Display the reading/candidate window. RenderCandidateReadingWindow() + // uses s_ptCompString to position itself. s_ptCompString must have + // been filled in by RenderComposition(). + if( ImeUi_IsShowReadingWindow() ) + // Reading window + RenderCandidateReadingWindow( fElapsedTime, true ); + else if( ImeUi_IsShowCandListWindow() ) + // Candidate list window + RenderCandidateReadingWindow( fElapsedTime, false ); + } +} + + +//-------------------------------------------------------------------------------------- +void CDXUTIMEEditBox::SetImeEnableFlag( bool bFlag ) +{ + s_bImeFlag = bFlag; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTIMEEditBox::Initialize( HWND hWnd ) +{ + ImeUiCallback_DrawRect = NULL; + ImeUiCallback_Malloc = malloc; + ImeUiCallback_Free = free; + ImeUiCallback_DrawFans = NULL; + + ImeUi_Initialize( hWnd ); + + s_CompString.SetBufferSize( MAX_COMPSTRING_SIZE ); + ImeUi_EnableIme( true ); +} + + diff --git a/Demos/DX11ClothDemo/DXUT/Optional/DXUTguiIME.h b/Demos/DX11ClothDemo/DXUT/Optional/DXUTguiIME.h new file mode 100644 index 0000000..6739be3 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/DXUTguiIME.h @@ -0,0 +1,141 @@ +//-------------------------------------------------------------------------------------- +// File: DXUTguiIME.h +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once +#ifndef DXUT_IME_H +#define DXUT_IME_H + +#include +#include +#include + + +//-------------------------------------------------------------------------------------- +// Forward declarations +//-------------------------------------------------------------------------------------- +class CDXUTIMEEditBox; + + +//----------------------------------------------------------------------------- +// IME-enabled EditBox control +//----------------------------------------------------------------------------- +#define MAX_COMPSTRING_SIZE 256 + + +class CDXUTIMEEditBox : public CDXUTEditBox +{ +public: + + static HRESULT CreateIMEEditBox( CDXUTDialog* pDialog, int ID, LPCWSTR strText, int x, int y, int width, + int height, bool bIsDefault=false, CDXUTIMEEditBox** ppCreated=NULL ); + + CDXUTIMEEditBox( CDXUTDialog* pDialog = NULL ); + virtual ~CDXUTIMEEditBox(); + + static void InitDefaultElements( CDXUTDialog* pDialog ); + + static void WINAPI Initialize( HWND hWnd ); + static void WINAPI Uninitialize(); + + static HRESULT WINAPI StaticOnCreateDevice(); + static bool WINAPI StaticMsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + + static void WINAPI SetImeEnableFlag( bool bFlag ); + + virtual void Render( float fElapsedTime ); + virtual bool MsgProc( UINT uMsg, WPARAM wParam, LPARAM lParam ); + virtual bool HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ); + virtual void UpdateRects(); + virtual void OnFocusIn(); + virtual void OnFocusOut(); + + void PumpMessage(); + + virtual void RenderCandidateReadingWindow( float fElapsedTime, bool bReading ); + virtual void RenderComposition( float fElapsedTime ); + virtual void RenderIndicator( float fElapsedTime ); + +protected: + static void WINAPI EnableImeSystem( bool bEnable ); + + static WORD WINAPI GetLanguage() + { + return ImeUi_GetLanguage(); + } + static WORD WINAPI GetPrimaryLanguage() + { + return ImeUi_GetPrimaryLanguage(); + } + static void WINAPI SendKey( BYTE nVirtKey ); + static DWORD WINAPI GetImeId( UINT uIndex = 0 ) + { + return ImeUi_GetImeId( uIndex ); + }; + static void WINAPI CheckInputLocale(); + static void WINAPI CheckToggleState(); + static void WINAPI SetupImeApi(); + static void WINAPI ResetCompositionString(); + + + static void SetupImeUiCallback(); + +protected: + enum + { + INDICATOR_NON_IME, + INDICATOR_CHS, + INDICATOR_CHT, + INDICATOR_KOREAN, + INDICATOR_JAPANESE + }; + + struct CCandList + { + CUniBuffer HoriCand; // Candidate list string (for horizontal candidate window) + int nFirstSelected; // First character position of the selected string in HoriCand + int nHoriSelectedLen; // Length of the selected string in HoriCand + RECT rcCandidate; // Candidate rectangle computed and filled each time before rendered + }; + + static POINT s_ptCompString; // Composition string position. Updated every frame. + static int s_nFirstTargetConv; // Index of the first target converted char in comp string. If none, -1. + static CUniBuffer s_CompString; // Buffer to hold the composition string (we fix its length) + static DWORD s_adwCompStringClause[MAX_COMPSTRING_SIZE]; + static CCandList s_CandList; // Data relevant to the candidate list + static WCHAR s_wszReadingString[32];// Used only with horizontal reading window (why?) + static bool s_bImeFlag; // Is ime enabled + + // Color of various IME elements + D3DCOLOR m_ReadingColor; // Reading string color + D3DCOLOR m_ReadingWinColor; // Reading window color + D3DCOLOR m_ReadingSelColor; // Selected character in reading string + D3DCOLOR m_ReadingSelBkColor; // Background color for selected char in reading str + D3DCOLOR m_CandidateColor; // Candidate string color + D3DCOLOR m_CandidateWinColor; // Candidate window color + D3DCOLOR m_CandidateSelColor; // Selected candidate string color + D3DCOLOR m_CandidateSelBkColor; // Selected candidate background color + D3DCOLOR m_CompColor; // Composition string color + D3DCOLOR m_CompWinColor; // Composition string window color + D3DCOLOR m_CompCaretColor; // Composition string caret color + D3DCOLOR m_CompTargetColor; // Composition string target converted color + D3DCOLOR m_CompTargetBkColor; // Composition string target converted background + D3DCOLOR m_CompTargetNonColor; // Composition string target non-converted color + D3DCOLOR m_CompTargetNonBkColor;// Composition string target non-converted background + D3DCOLOR m_IndicatorImeColor; // Indicator text color for IME + D3DCOLOR m_IndicatorEngColor; // Indicator text color for English + D3DCOLOR m_IndicatorBkColor; // Indicator text background color + + // Edit-control-specific data + int m_nIndicatorWidth; // Width of the indicator symbol + RECT m_rcIndicator; // Rectangle for drawing the indicator button + +#if defined(DEBUG) || defined(_DEBUG) + static bool m_bIMEStaticMsgProcCalled; +#endif +}; + + + +#endif // DXUT_IME_H diff --git a/Demos/DX11ClothDemo/DXUT/Optional/DXUTres.cpp b/Demos/DX11ClothDemo/DXUT/Optional/DXUTres.cpp new file mode 100644 index 0000000..c91080a --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/DXUTres.cpp @@ -0,0 +1,8338 @@ +//---------------------------------------------------------------------------- +// File: DXUTRes.cpp +// +// Copyright (c) Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#include "DXUT.h" +#include "DXUTres.h" + +static const DWORD g_DXUTGUITextureSrcData[] = +{ + 0x20534444, 0x0000007c, 0x00001007, 0x00000100, 0x00000100, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000020, 0x00000041, 0x00000000, 0x00000020, 0x000000ff, + 0x0000ff00, 0x00ff0000, 0xff000000, 0x00001002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000400, 0x11000400, 0x11000400, 0x11000400, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000400, 0x11000400, 0x11000400, 0x11000400, 0x11000400, 0x11000400, 0x11000400, 0x11000400, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000400, 0x11000400, 0x11000400, 0x11000400, + 0x11000400, 0x11000400, 0x11000400, 0x11000400, 0x11000400, 0x11000400, 0x11000400, 0x11000400, + 0x11000000, 0x00000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00080408, 0x00080408, 0x00080408, 0x00080408, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, + 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x22000400, 0x22000400, 0x22000400, 0x22000400, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000400, 0x22000400, 0x22000400, 0x22000400, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000400, 0x22000400, 0x22000400, 0x22000400, 0x22000400, 0x22000400, 0x22000400, 0x22000400, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000400, 0x22000400, 0x22000400, 0x22000400, + 0x22000400, 0x22000400, 0x22000400, 0x22000400, 0x22000400, 0x22000400, 0x22000400, 0x22000400, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00080408, 0x00080408, 0x00080408, 0x00080408, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, + 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, 0x22000000, 0x33000000, 0x44000000, + 0x44000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x66000000, 0x66000000, + 0x66000400, 0x66000400, 0x66000400, 0x66000400, 0x66000000, 0x66000000, 0x661e1e1e, 0x771e1e1e, + 0x771e1c1e, 0x771e1c1e, 0x771e1c1e, 0x771e1c1e, 0x771e1e1e, 0x771e1e1e, 0x771e1e1e, 0x771e1e1e, + 0x771e1c1e, 0x881e1c1e, 0x881e1c1e, 0x881e1c1e, 0x88373937, 0x88373937, 0x881b1c1b, 0x881b1c1b, + 0x881e201e, 0x881e201e, 0x881e201e, 0x881e201e, 0x88313631, 0x88313631, 0x88313631, 0x88191b19, + 0x881b1f1b, 0x881b1f1b, 0x881b1f1b, 0x881b1f1b, 0x881b1e1b, 0x881b1e1b, 0x881b1e1b, 0x88373737, + 0x88313331, 0x88313331, 0x88313331, 0x88313331, 0x881b1f1b, 0x881b1f1b, 0x881b1f1b, 0x881b1f1b, + 0x881b1f1b, 0x881b1f1b, 0x881b1f1b, 0x881b1f1b, 0x88191e19, 0x88191e19, 0x88191e19, 0x77191e19, + 0x77191a19, 0x77191a19, 0x77191a19, 0x77191a19, 0x77191719, 0x77191719, 0x77191719, 0x66191719, + 0x66161616, 0x66161616, 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x66000000, + 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x44000000, 0x44000000, + 0x44000000, 0x33000000, 0x22000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x22000400, 0x22000400, 0x333c413c, 0x443c3d3f, 0x443c3d3f, 0x443c3d3f, 0x553c3d3f, + 0x66454145, 0x77454145, 0x77454145, 0x88817d81, 0x99797779, 0x99797779, 0x99797779, 0x99797779, + 0x99797979, 0xaa797979, 0xaa797979, 0xaa797979, 0xbb7e7c7e, 0xcc7e7c7e, 0xbb7e7c7e, 0xbb7e7c7e, + 0xbb7e7f7e, 0xbb7e7f7e, 0xcc7e7f7e, 0xcc7e7f7e, 0xcc7e7f7e, 0xcc7e7f7e, 0xcc7e7f7e, 0xcc7e7f7e, + 0xbb7e7c7e, 0xcc7c7b7d, 0xcc7a7879, 0xbb707071, 0xbb686869, 0xbb5d6060, 0xbb565858, 0xbb4d4f4c, + 0xcc454745, 0xcc3c3b3e, 0x77383838, 0x55393837, 0x55373737, 0x44373737, 0x33373737, 0x33373937, + 0x22000400, 0x22000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, + 0x22000000, 0x33000000, 0x44000000, 0x55000000, 0x55030303, 0x66030303, 0x66050505, 0x66080808, + 0x66101010, 0x77212021, 0x77212021, 0x77313131, 0x88373637, 0x88373637, 0x99525152, 0x99525152, + 0x995a595a, 0x995a595a, 0x995a595a, 0x995a595a, 0x995a595a, 0x995a595a, 0x995a595a, 0x995a595a, + 0x995a555a, 0x995a555a, 0x995a555a, 0x995a555a, 0x995a595a, 0x995a595a, 0x995a595a, 0x995a595a, + 0x995a555a, 0x995a555a, 0x995a555a, 0x995a555a, 0x99525552, 0x99525552, 0x99525552, 0x99525552, + 0x995a595a, 0x995a595a, 0x995a595a, 0x995a595a, 0x994a514a, 0x994a514a, 0x994a514a, 0x994a514a, + 0x99525552, 0x99525552, 0x99525552, 0x99525552, 0x99525152, 0x99525152, 0x99525152, 0x99525152, + 0x994a4d4a, 0x994a4d4a, 0x994a4d4a, 0x994a4d4a, 0x99525552, 0x99525552, 0x99525552, 0x99525552, + 0x99525552, 0x99525552, 0x99525552, 0x99525552, 0x994a514a, 0x994a514a, 0x994a514a, 0x994a514a, + 0x994a4d4a, 0x994a4d4a, 0x994a4d4a, 0x994a4d4a, 0x994a454a, 0x994a454a, 0x994a454a, 0x994a454a, + 0x99424142, 0x99424142, 0x99424142, 0x99424142, 0x99424142, 0x99424142, 0x99424142, 0x992c2b2c, + 0x88293129, 0x881b201b, 0x771b201b, 0x771b201b, 0x66101010, 0x66101010, 0x660b0b0b, 0x66050505, + 0x66000400, 0x66000100, 0x55000100, 0x55000000, 0x55000000, 0x44000000, 0x33000000, 0x22000000, + 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00080708, 0x11100d10, 0x11100d10, 0x22191419, + 0x33212324, 0x55424647, 0x66424647, 0x8863696b, 0x99737473, 0xbb737473, 0xccadaead, 0xeeadaead, + 0xffb5bab5, 0xffb5bab5, 0xffb5bab5, 0xffb5bab5, 0xffb5b6bd, 0xffb5b6bd, 0xffb5b6bd, 0xffb5b6bd, + 0xffbdbabd, 0xffbdbabd, 0xffbdbabd, 0xffbdbabd, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, + 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffbdbabd, 0xffbdbabd, 0xffbdbabd, 0xffbdbabd, + 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, + 0xffbdbabd, 0xffbcbabd, 0xffbcb8bc, 0xffb6b2b6, 0xffb3afb3, 0xffb0aeaf, 0xffadabaa, 0xffaaa9aa, + 0xffa9a7a8, 0xffa7a7a7, 0xffa6a6a6, 0xffa6a6a5, 0xffa6a6a5, 0xffa5a6a5, 0xffa5a6a5, 0xffa5a2a5, + 0xffa5a2a5, 0xffa5a2a5, 0xeea5a2a5, 0xdd9c9a9c, 0xcc9c9a9c, 0xaa686768, 0x99686768, 0x885a5d5a, + 0x553c3e3c, 0x443c3e3c, 0x331e1f1e, 0x11101010, 0x11101010, 0x110b0b0b, 0x00050505, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000400, 0x33000400, 0x44000400, 0x55000400, + 0x66080808, 0x66080808, 0x663a3a3a, 0x773a3a3a, 0x885a5d5a, 0x886b6f6e, 0x996b6f6e, 0x997b8081, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99797879, 0x99737173, 0x99737173, 0x99737173, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x996b716b, 0x99737773, 0x996b716b, 0x996b716b, + 0x99737173, 0x99797779, 0x99737173, 0x99737173, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, + 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, + 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, + 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, 0x99636563, 0x99636563, 0x99636563, 0x99636563, + 0x99636163, 0x99636163, 0x99636163, 0x99636163, 0x995a5d5a, 0x995a5d5a, 0x995a5d5a, 0x995a5d5a, + 0x995a5552, 0x995a5552, 0x995a5552, 0x995a5552, 0x994a4d50, 0x994a4d50, 0x994a4d50, 0x9931353a, + 0x88313331, 0x88313331, 0x77101010, 0x66101010, 0x66080408, 0x66080408, 0x66080408, 0x55080408, + 0x55000000, 0x44000000, 0x22000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11191819, 0x22191819, 0x33191819, 0x66656465, 0x887b7d7b, 0xbba2a5a5, 0xddc8ccce, 0xffc8ccce, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, + 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, + 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, + 0xffd6d2d6, 0xffd9d8d9, 0xffd6d2d6, 0xffd6d2d6, 0xffd6cece, 0xffcfcccc, 0xffc8c7c8, 0xffc6c2c3, + 0xffc4c0c2, 0xffc2c0c2, 0xffc5c2c4, 0xffc4c2c5, 0xffc5c2c5, 0xffc5c2c5, 0xffc5c2c5, 0xffbdbebd, + 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffa5a6a5, + 0xffa5a6a5, 0xffa5a6a5, 0xffa5a6a5, 0xee868a86, 0xdd868a86, 0xaa868a86, 0x885a615a, 0x55505250, + 0x33101410, 0x11101410, 0x11101410, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, + 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x11000000, 0x44000000, 0x55000400, 0x66000400, 0x77343634, 0x77686868, + 0x886b6c6b, 0x999c9e9c, 0x999c9e9c, 0x999c9e9c, 0x998c9294, 0x998c9294, 0x998c9294, 0x998c9294, + 0x998c8e8c, 0x99868786, 0x99868786, 0x99868786, 0x99848384, 0x99848384, 0x99848384, 0x99848384, + 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x997e7f7e, + 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x997e7c7e, 0x99848284, + 0x9984827b, 0x9984827b, 0x9984827b, 0x9984827b, 0x99848284, 0x99848284, 0x99848284, 0x997e7c7e, + 0x99848284, 0x997e7c7e, 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x997b7c7b, + 0x997e7c7e, 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x997b7b7b, 0x99848284, 0x99848284, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x99767776, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x99737373, 0x997b797b, + 0x99737473, 0x99737473, 0x99737473, 0x99737473, 0x997b797b, 0x997b797b, 0x997b797b, 0x99707070, + 0x9970706e, 0x9970706e, 0x9970706e, 0x9970706e, 0x99636565, 0x99636565, 0x99636565, 0x99636565, + 0x99525652, 0x99525652, 0x99525652, 0x99525652, 0x99504d50, 0x882c282c, 0x772c282c, 0x77080408, + 0x66000000, 0x66000000, 0x55000000, 0x55000000, 0x44000000, 0x22000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x11000000, 0x33525452, 0x77525452, + 0xaab2afb2, 0xddfffbff, 0xfffffbff, 0xfffffbff, 0xffeff3f7, 0xffeff3f7, 0xffeff3f7, 0xffeff3f7, + 0xffefefef, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e5e6, + 0xffe1e4e1, 0xffe1e4e1, 0xffe1e4e1, 0xffe1e4e1, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe1e1e1, + 0xffe6e1e6, 0xffe6e1e6, 0xffe6e1e6, 0xffe6e1e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, + 0xffe6e3de, 0xffe6e3de, 0xffe6e3de, 0xffe6e3de, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe1dde1, + 0xffe6e3de, 0xffe6e3de, 0xffe6e3de, 0xffe6e3de, 0xffdee3de, 0xffdee3de, 0xffdee3de, 0xffdee3de, + 0xffdee3de, 0xffdee3de, 0xffdee3de, 0xffdee3de, 0xffdee3dd, 0xffdee3dd, 0xffdee1de, 0xffdee0db, + 0xffdedbd9, 0xffe2dddc, 0xffdbd9db, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd3d4d3, + 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, 0xffd0d0d0, 0xffd0d0d0, 0xffd0d0d0, 0xffd0d0d0, 0xffcbc9cb, + 0xffcbc9cb, 0xffcbc9cb, 0xffcbc9cb, 0xffb2b2b2, 0xffb2b2b2, 0xffb2b2b2, 0xffb2b2b2, 0xff8f908f, + 0xff8f908f, 0xbb8f908f, 0x88505250, 0x663c3d3c, 0x333c3d3c, 0x11000000, 0x00000000, 0x00000400, + 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11000000, 0x44000000, 0x55000000, 0x77343234, 0x77686868, 0x999c9a9c, 0x999c9a9c, 0x999c9a9c, + 0x999c9e9c, 0x999c9e9c, 0x999c9e9c, 0x999c9e9c, 0x998c9294, 0x998c9294, 0x998c9294, 0x998c9294, + 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, + 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x997e7f7e, 0x99848684, + 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848284, + 0x9984827b, 0x9984827b, 0x9984827b, 0x9984827b, 0x99848284, 0x99848284, 0x997e7c7e, 0x997e7c7e, + 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x997b7c7b, 0x997b7c7b, + 0x99848284, 0x997e7c7e, 0x997e7c7e, 0x997e7c7e, 0x99848284, 0x99848284, 0x997b7b7b, 0x997b7b7b, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x99737973, 0x99737973, 0x99737973, 0x99737973, 0x99737173, 0x99737173, 0x99504d50, 0x99504d50, + 0x88424142, 0x88212021, 0x77212021, 0x66000000, 0x55000000, 0x55000000, 0x44000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x00000400, 0x00000400, 0x22000400, 0x66525452, 0xaaa5a7a5, 0xeef7fbf7, 0xfff7fbf7, + 0xfffffbff, 0xfffffbff, 0xfffffbff, 0xfffffbff, 0xffeff3f7, 0xffeff3f7, 0xffeff3f7, 0xffeff3f7, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, + 0xffe6ebe6, 0xffe6ebe6, 0xffe1e4e1, 0xffe1e4e1, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, + 0xffe6e1e6, 0xffe6e1e6, 0xffe6e1e6, 0xffefe7ef, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, + 0xffe6e3de, 0xffe6e3de, 0xffe6e3de, 0xffe6e3de, 0xffe6e3e6, 0xffe6e3e6, 0xffe1dde1, 0xffe6e3e6, + 0xffe6e3de, 0xffe6e3de, 0xffe6e3de, 0xffe6e3de, 0xffdee3de, 0xffdee3de, 0xffdee3de, 0xffdee3de, + 0xffdee3de, 0xffdee3de, 0xffdee3de, 0xffdee3de, 0xffdee3de, 0xffdee3de, 0xffdee3de, 0xffdee3de, + 0xffe5e2df, 0xffe1e0dd, 0xffdcdbdc, 0xffdddfe0, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, + 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffb5b6b5, 0xdd797979, 0xaa797979, 0x663c3d3c, 0x22000400, + 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22000000, + 0x55000000, 0x77343234, 0x88686468, 0x999c969c, 0x999c9a9c, 0x999c9a9c, 0x999c9a9c, 0x999c9a9c, + 0x999c9e9c, 0x999c9e9c, 0x999c9e9c, 0x999c9e9c, 0x998c9294, 0x998c9294, 0x998c9294, 0x998c9294, + 0x99868786, 0x99868786, 0x99868786, 0x99868786, 0x99848384, 0x99848384, 0x99848384, 0x99848384, + 0x997e807e, 0x997e807e, 0x997e807e, 0x997e807e, 0x997e7f7e, 0x997e7f7e, 0x997e7f7e, 0x997e7f7e, + 0x997e7c7e, 0x997e7c7e, 0x997e7c7e, 0x997e7c7e, 0x997e7c7e, 0x997e7c7e, 0x997e7c7e, 0x997e7c7e, + 0x997e7c79, 0x997e7c79, 0x997e7c79, 0x99797776, 0x99797779, 0x99797779, 0x997e7c7e, 0x997e7c7e, + 0x997e7c7e, 0x997e7c7e, 0x997e7c7e, 0x997e7c7e, 0x997b7c7b, 0x997b7c7b, 0x99737773, 0x997b7c7b, + 0x99797779, 0x997e7c7e, 0x99797779, 0x997e7c7e, 0x997b7b7b, 0x997b7b7b, 0x997b7b7b, 0x997b7b7b, + 0x99767876, 0x99767876, 0x99767876, 0x99767876, 0x99767876, 0x99767876, 0x99767876, 0x99767876, + 0x99767776, 0x997b7d7b, 0x997b7d7b, 0x99767776, 0x99767776, 0x99767776, 0x99767776, 0x99767776, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x99737973, 0x99737973, 0x99737973, 0x99737973, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x99636163, 0x99636163, 0x99424142, 0x88212021, 0x77191419, 0x66000000, 0x55000000, 0x55000000, + 0x22000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x11000400, 0x66797b79, 0xccb5b6b5, 0xfff7fbf7, 0xfff7fbf7, 0xfff7fbf7, 0xfff7fbf7, + 0xfffffbff, 0xfffffbff, 0xfffffbff, 0xfffffbff, 0xffeff3f7, 0xffeff3f7, 0xffeff3f7, 0xffeff3f7, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e5e6, + 0xffe1e4e1, 0xffe1e4e1, 0xffe1e4e1, 0xffdbdddb, 0xffe1e1e1, 0xffe1e1e1, 0xffdbdcdb, 0xffe1e1e1, + 0xffdedcde, 0xffdedcde, 0xffdedcde, 0xffdedcde, 0xffe1dde1, 0xffe1dde1, 0xffe1dde1, 0xffe1dde1, + 0xffe1dddb, 0xffe1dddb, 0xffe1dddb, 0xffe1dddb, 0xffe1dde1, 0xffe1dde1, 0xffe1dde1, 0xffe1dde1, + 0xffe1dddb, 0xffe1dddb, 0xffe1dddb, 0xffe1dddb, 0xffdbdddb, 0xffdbdddb, 0xffdbdddb, 0xffdbdddb, + 0xffdbdddb, 0xffdbdddb, 0xffdbdddb, 0xffdbdddb, 0xffdbdcd9, 0xffdbdcd9, 0xffdcdcda, 0xffdcdbda, + 0xffdddadb, 0xffddd9dc, 0xffdad8d9, 0xffd7dadb, 0xffdbdddc, 0xffdddfdd, 0xffdedfde, 0xffdedfde, + 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xbb737973, + 0x664d524d, 0x11000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00080808, 0x00080808, 0x33080808, 0x66080808, + 0x8852555a, 0x99848686, 0x999c9e9c, 0x999c9e9c, 0x999c9e9c, 0x999c9e9c, 0x999c9e9c, 0x999c9e9c, + 0x99949294, 0x99949294, 0x99949294, 0x99898889, 0x998c8684, 0x998c8684, 0x998c8684, 0x9984807e, + 0x99848284, 0x99848284, 0x99848284, 0x997b7b7e, 0x997b7d7b, 0x997b7d7b, 0x99767876, 0x99767876, + 0x997b797b, 0x997b797b, 0x99767576, 0x99767576, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737473, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99767570, 0x99767570, 0x997b7973, 0x99767570, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99767576, 0x99767576, 0x997b797b, 0x997b797b, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x997b7973, 0x9973706e, 0x996b6768, 0x99635d63, 0x994a4a4a, 0x77292b29, 0x66080c08, 0x66080c08, + 0x66000000, 0x33000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x333a393a, 0xbbb2b2b2, 0xeeefefef, 0xffefefef, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfff7f7f7, 0xfff7f7f7, 0xffececec, 0xffececec, 0xffefebe6, 0xffefebe6, 0xffe6e4e1, 0xffe6e4e1, + 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffdedce1, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd3d7d3, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd3d7d3, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d6d6, 0xffd8d7d6, + 0xffd8d6d7, 0xffd8d3d6, 0xffd8d3d7, 0xffd9d4d8, 0xffd9d6d9, 0xffd8d7d7, 0xffd6d7d6, 0xffd3d7d3, + 0xffd3d7d3, 0xffd3d7d3, 0xffd6dbd6, 0xffd3d7d3, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbde, + 0xffd6dbde, 0xffd6dbde, 0xffd6dbde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, + 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffd6dbd6, 0xffd0d1ce, 0xffd0d1ce, 0xffc5bebd, 0xffc5c6c5, + 0xee9a9797, 0xaa6e6868, 0x3342393a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00080808, 0x33080808, 0x66080808, 0x885a595a, + 0x99848686, 0x99848686, 0x999c9e9c, 0x999c9e9c, 0x99919291, 0x99919291, 0x99919291, 0x99919291, + 0x99898889, 0x99898889, 0x99898889, 0x997e7f7e, 0x9984807e, 0x997b7b79, 0x997b7b79, 0x997b7b79, + 0x997b7b7e, 0x997b7b7e, 0x997b7b7e, 0x99737479, 0x99767876, 0x99767876, 0x99707370, 0x99707370, + 0x99767576, 0x99767576, 0x99767576, 0x99767576, 0x99737573, 0x99737573, 0x99737573, 0x99707370, + 0x99707370, 0x99707370, 0x99707370, 0x99707370, 0x99707370, 0x99707370, 0x99707370, 0x99707370, + 0x996e706e, 0x99707370, 0x99707370, 0x996e706e, 0x99707370, 0x99707370, 0x99707370, 0x996e706e, + 0x996e706e, 0x996e706e, 0x996e706e, 0x996e706e, 0x99707370, 0x996e706e, 0x99707370, 0x99707370, + 0x99737173, 0x99737473, 0x99737373, 0x99737173, 0x99737370, 0x99737370, 0x99737370, 0x99737370, + 0x99737373, 0x99737373, 0x99737373, 0x99737373, 0x99737373, 0x99737373, 0x99737373, 0x99737373, + 0x9970716e, 0x99767570, 0x99767570, 0x99767570, 0x99737573, 0x99737370, 0x99737370, 0x99737370, + 0x99737370, 0x99737573, 0x99737370, 0x99737370, 0x99707370, 0x99707370, 0x99707370, 0x99707370, + 0x99707373, 0x99707373, 0x99707373, 0x99707373, 0x99707370, 0x99707370, 0x99707370, 0x99707370, + 0x99707370, 0x99707370, 0x99707370, 0x99707370, 0x99767576, 0x99767576, 0x99767576, 0x99767576, + 0x99767576, 0x99767576, 0x99767576, 0x99767576, 0x99767876, 0x99767876, 0x99767876, 0x99767876, + 0x997b7973, 0x997b7973, 0x997b7973, 0x9973706e, 0x996b696b, 0x994a4a4a, 0x88292b29, 0x77080c08, + 0x66000000, 0x66000000, 0x33000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x55474847, + 0xddb2b2b2, 0xffefefef, 0xffefefef, 0xffefefef, 0xfff4f3f4, 0xfff4f3f4, 0xfff4f3f4, 0xfff4f3f4, + 0xffececec, 0xffececec, 0xffe1e1e1, 0xffe1e1e1, 0xffe6e4e1, 0xffdedddb, 0xffdedddb, 0xffdedddb, + 0xffdedce1, 0xffdedce1, 0xffdedce1, 0xffd6d5db, 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, 0xffd3d4d3, + 0xffd9d7d9, 0xffd9d7d9, 0xffd9d7d9, 0xffd9d7d9, 0xffd3d7d3, 0xffd3d7d3, 0xffd3d7d3, 0xffd3d7d3, + 0xffd3d7d3, 0xffd3d7d3, 0xffd3d7d3, 0xffd0d2d0, 0xffd3d7d3, 0xffd0d2d0, 0xffd0d2d0, 0xffd0d2d0, + 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, + 0xffd3d4d3, 0xffd0d1d0, 0xffd3d4d3, 0xffd0d1d0, 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, + 0xffd0d4d0, 0xffd3d5d3, 0xffd0d4d0, 0xffd3d5d3, 0xffd6d4d3, 0xffd6d4d3, 0xffd6d4d3, 0xffd7d4d4, + 0xffd6d2d3, 0xffd5cfd3, 0xffd5d0d4, 0xffd5d3d4, 0xffd5d5d4, 0xffd2d5d3, 0xffd3d4d3, 0xffd3d7d3, + 0xffd3d7d3, 0xffd3d7d3, 0xffd3d7d3, 0xffd0d2d0, 0xffd3d7d3, 0xffd3d7d3, 0xffd0d2d0, 0xffd3d7d9, + 0xffd3d7d9, 0xffd3d7d9, 0xffd3d7d9, 0xffd3d4d3, 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, + 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd0d1ce, 0xffc5c6c5, + 0xffc5c6c5, 0xff9a9797, 0xcc9a9797, 0x55313231, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x33080808, 0x66080808, 0x995a595a, 0x99848284, + 0x99848686, 0x99848686, 0x99848686, 0x99848686, 0x99919291, 0x99868686, 0x99868686, 0x99868686, + 0x997e7f7e, 0x997e7f7e, 0x99737573, 0x99737573, 0x997b7b79, 0x997b7b79, 0x99737573, 0x99737573, + 0x99737479, 0x99737479, 0x99737479, 0x99737479, 0x99707370, 0x99707370, 0x99707370, 0x99707370, + 0x99707170, 0x99707170, 0x99707170, 0x996b6d6b, 0x996e706e, 0x996e706e, 0x996e706e, 0x996b6d6b, + 0x996e706e, 0x996e706e, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, + 0x996b6d6b, 0x996e706e, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, + 0x996e706e, 0x996e706e, 0x996e706e, 0x996b6d6b, 0x996e706e, 0x996e706e, 0x996e706e, 0x996e706e, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x9973706e, 0x9973706e, 0x9973706e, 0x9973706e, + 0x99737073, 0x99737073, 0x99737073, 0x99737373, 0x99737373, 0x99737073, 0x99737073, 0x99737073, + 0x9970716e, 0x9970716e, 0x9970716e, 0x9970716e, 0x9973706e, 0x99737370, 0x9973706e, 0x9973706e, + 0x9973706e, 0x9973706e, 0x99737370, 0x99737370, 0x99707370, 0x99707370, 0x996e706e, 0x996e706e, + 0x996e7073, 0x996e7073, 0x996e7073, 0x996e7073, 0x996e706e, 0x996e706e, 0x996e706e, 0x996e706e, + 0x996e706e, 0x996e706e, 0x996e706e, 0x996e706e, 0x99707170, 0x99707170, 0x99707170, 0x99707170, + 0x99707170, 0x99707170, 0x99707170, 0x99707170, 0x99707370, 0x99707370, 0x99707370, 0x99707370, + 0x997b7973, 0x9973706e, 0x9973706e, 0x9973706e, 0x996b696b, 0x996b696b, 0x994a4a4a, 0x99292b29, + 0x66101010, 0x66000000, 0x66000000, 0x22000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x66474847, 0xeed6d7d6, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xfff4f3f4, 0xffe9e7e9, 0xffe9e7e9, 0xffe9e7e9, + 0xffe1e1e1, 0xffe1e1e1, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d5db, 0xffd6d5db, 0xffd6d5db, 0xffd6d5db, 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, + 0xffd3d2d3, 0xffd3d2d3, 0xffd3d2d3, 0xffcecece, 0xffd0d2d0, 0xffd0d2d0, 0xffd0d2d0, 0xffcecece, + 0xffd0d2d0, 0xffd0d2d0, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, + 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd3d4d3, 0xffd0d1d0, 0xffd0d1d0, + 0xffced2ce, 0xffd0d4d0, 0xffd0d4d0, 0xffced2ce, 0xffd6d1d0, 0xffd6d1d0, 0xffd6d4d3, 0xffd6d2d2, + 0xffd6d2d3, 0xffd4d0d2, 0xffd4d0d3, 0xffd5d2d5, 0xffd6d3d6, 0xffd5d4d5, 0xffd3d4d3, 0xffd0d2d0, + 0xffd0d2d0, 0xffd0d2d0, 0xffd0d2d0, 0xffd0d2d0, 0xffd0d2d0, 0xffd0d2d0, 0xffd0d2d0, 0xffd0d2d3, + 0xffd0d2d3, 0xffd0d2d3, 0xffd0d2d3, 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, + 0xffd3d4d3, 0xffd9d9d9, 0xffd9d9d9, 0xffd6dbd6, 0xffd0d1ce, 0xffd0d1ce, 0xffd0d1ce, 0xffc5c6c5, + 0xffc5c6c5, 0xffc5c6c5, 0xff9a9797, 0xdd949694, 0x44313231, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x66080808, 0x995a595a, 0x99848284, 0x99848284, + 0x99848686, 0x99848686, 0x99848686, 0x99848686, 0x99868686, 0x99868686, 0x99868686, 0x997b797b, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x996b6d73, 0x996b6d73, 0x996b6d73, 0x996b6d73, 0x996b6d6b, 0x996b6d6b, 0x99707370, 0x996b6d6b, + 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, + 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, + 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, + 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996e706e, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99736d6b, 0x9973706e, 0x9973706e, 0x9973706e, + 0x99737073, 0x99736d73, 0x99737073, 0x99737073, 0x99736d73, 0x99736d73, 0x99736d73, 0x99737073, + 0x996b6d6b, 0x9970716e, 0x9970716e, 0x996b6d6b, 0x99736d6b, 0x99736d6b, 0x99736d6b, 0x99736d6b, + 0x9973706e, 0x9973706e, 0x99736d6b, 0x9973706e, 0x996e706e, 0x99707370, 0x99707370, 0x996b6d6b, + 0x996e7073, 0x996b6d73, 0x996b6d73, 0x996e7073, 0x996e706e, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, + 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, + 0x99707170, 0x996b6d6b, 0x99707170, 0x996b6d6b, 0x99707370, 0x99707370, 0x996b6d6b, 0x996b6d6b, + 0x9973706e, 0x9973706e, 0x9973706e, 0x9973706e, 0x996b696b, 0x996b696b, 0x996b696b, 0x994a4a4a, + 0x88313131, 0x66101010, 0x66000000, 0x55000000, 0x22000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x44474847, 0xeed6d7d6, 0xffd6d7d6, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffe9e7e9, 0xffe9e7e9, 0xffe9e7e9, 0xffdedbde, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d5db, 0xffceced6, 0xffceced6, 0xffceced6, 0xffcecece, 0xffcecece, 0xffd3d4d3, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, + 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffd6d1d0, 0xffd6d1d0, 0xffd6d1d0, 0xffd7d2d2, + 0xffd7d3d5, 0xffd6d1d5, 0xffd6d1d4, 0xffd6d3d5, 0xffd5d4d5, 0xffd1d2d1, 0xffd0d1d0, 0xffd0d2d0, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffd3d4d3, 0xffcecece, 0xffd3d4d3, 0xffcecece, 0xffd3d4d3, + 0xffd3d4d3, 0xffcecece, 0xffcecece, 0xffd0d1ce, 0xffd0d1ce, 0xffd0d1ce, 0xffd0d1ce, 0xffc5c6c5, + 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xff949694, 0xcc949694, 0x33313231, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x44000000, 0x884a4542, 0x99737173, 0x99737173, 0x99737173, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b797b, 0x997b797b, 0x997b797b, 0x99737373, + 0x99737173, 0x99737173, 0x99706f70, 0x99706f70, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, + 0x99706d70, 0x99737173, 0x99706d70, 0x99706d70, 0x996b6b6b, 0x996b6c6b, 0x996b6b6b, 0x996b6b6b, + 0x996b6c6b, 0x996b6c6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6c6b, 0x996b6d6b, + 0x996b6d6b, 0x996b6b6b, 0x996b6b6b, 0x996b6c6b, 0x996e6c6e, 0x99706f70, 0x996e6c6e, 0x99706f70, + 0x996b6f6b, 0x996b6d6b, 0x996b6f6b, 0x996b6f6b, 0x996e6d6e, 0x996e6d6e, 0x996e6d6e, 0x996e6d6e, + 0x996b7070, 0x996b6f6e, 0x996b6f6e, 0x996b6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, + 0x99736f6e, 0x99737070, 0x99737070, 0x99737070, 0x996e6f6e, 0x99737173, 0x99707070, 0x996e6f6e, + 0x9970706e, 0x9970706e, 0x9970706e, 0x9970706e, 0x996e6f6e, 0x996e6f6e, 0x99707070, 0x996e6f6e, + 0x996b6f70, 0x996b6f70, 0x996b6f70, 0x996b6f70, 0x996e6f6e, 0x99707070, 0x99707070, 0x996e6f6e, + 0x996e6f6e, 0x99707070, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x99707070, 0x996e6f6e, + 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6c6b, 0x996b6c6b, 0x996b6c6b, + 0x996b6d6b, 0x996b6d6b, 0x996b6c6b, 0x996b6c6b, 0x996b6c6b, 0x996b6b6b, 0x996b6d6b, 0x996b6c6b, + 0x996b6f70, 0x996b6f70, 0x996b6c6e, 0x996b6c6e, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x99686b6b, + 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, 0x9963656b, 0x9963656b, 0x995d6065, 0x9952555a, + 0x994a4d4a, 0x881e1f1e, 0x66080808, 0x66080808, 0x44000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11101010, 0xccc5cac5, 0xffc5cac5, 0xffc5cac5, + 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedbd6, 0xffdedbd6, 0xffdedbd6, 0xffd6d5d3, + 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd3d0d3, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecdce, 0xffced0ce, 0xffced0ce, 0xffced0ce, 0xffcecdce, 0xffcecece, 0xffcecdce, 0xffcecdce, + 0xffcecece, 0xffcecece, 0xffcecdce, 0xffcecdce, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffced0d0, 0xffcecece, 0xffced0d0, + 0xffced0ce, 0xffcecece, 0xffced0ce, 0xffced0ce, 0xffd0ced0, 0xffd0ced0, 0xffd0ced0, 0xffd0ced0, + 0xffced1d3, 0xffced0d0, 0xffced0d0, 0xffced0d0, 0xffd0d0d0, 0xffd0d0d0, 0xffd0d0d0, 0xffd0d0d0, + 0xffd6d0d0, 0xffd6d1d3, 0xffd6d1d3, 0xffd6d1d3, 0xffd0d0d0, 0xffd6d2d6, 0xffd3d1d3, 0xffd1d0d1, + 0xffd5d2d4, 0xffd7d3d6, 0xffd7d3d6, 0xffd6d3d5, 0xffd1d2d3, 0xffcecfce, 0xffcdcece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcbcccb, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcbcacb, 0xffc5cac5, + 0xffc0c4c0, 0xffc0c4c0, 0xffb5b6b5, 0xffa5a6a5, 0xffa5a6a5, 0xaa737473, 0x11101010, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x22000000, 0x661e1e1e, 0x99656263, 0x99737173, 0x99737173, 0x99737173, + 0x99767776, 0x99767776, 0x99767776, 0x99767776, 0x99737373, 0x99737373, 0x99737373, 0x996b6c6b, + 0x996e6c6e, 0x996e6c6e, 0x99706f70, 0x99706f70, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, + 0x99706d70, 0x99706d70, 0x99706d70, 0x996e696e, 0x996b6b6b, 0x996b6b6b, 0x996b696b, 0x996b6b6b, + 0x996b696b, 0x996b6b6b, 0x996b696b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6d6b, + 0x996b6c6b, 0x996b6b6b, 0x996b6c6b, 0x996b6b6b, 0x996e6c6e, 0x996e6c6e, 0x99706f70, 0x996e6c6e, + 0x996b6f6b, 0x996b6f6b, 0x996b6f6b, 0x996b6f6b, 0x996e6d6e, 0x996e6d6e, 0x996e6d6e, 0x996e6d6e, + 0x996b6f6e, 0x996b7070, 0x996b7070, 0x996b6f6e, 0x996e6f6e, 0x99707070, 0x99707070, 0x996e6f6e, + 0x99737070, 0x99737070, 0x99736f6e, 0x99736f6e, 0x996e6f6e, 0x99707070, 0x99737173, 0x996e6f6e, + 0x996e6f68, 0x996e6f68, 0x9970706e, 0x9970706e, 0x99707070, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, + 0x996b6f70, 0x996b6f70, 0x996b6f70, 0x996b706e, 0x996e6f6e, 0x99707070, 0x996e6f6e, 0x996e6f6e, + 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, + 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6c6b, 0x996b6c6b, 0x996b6b6b, + 0x996b6d6b, 0x996b6c6b, 0x996b6b6b, 0x996b6b6b, 0x996b6c6b, 0x996b6c6b, 0x996b6c6b, 0x996b6b6b, + 0x996b6f70, 0x996b6c6e, 0x996b6c6e, 0x996b6c6e, 0x99686b6b, 0x99686b6b, 0x9965686b, 0x99686b6b, + 0x996b696b, 0x99686768, 0x99686768, 0x99686768, 0x9963656b, 0x995d6065, 0x995d6065, 0x9952555a, + 0x994a4d4a, 0x99343634, 0x77080808, 0x66080808, 0x66000000, 0x22000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x664d4e4d, 0xffc5cac5, 0xffc5cac5, 0xffc5cac5, + 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, 0xffd6d5d3, 0xffd6d5d3, 0xffced0d0, 0xffced0d0, + 0xffd0cdd0, 0xffd0cdd0, 0xffd3d0d3, 0xffd3d0d3, 0xffcbcdcb, 0xffcbcdcb, 0xffcbcdcb, 0xffcbcdcb, + 0xffcecdce, 0xffced0ce, 0xffced0ce, 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecace, 0xffcecdce, + 0xffcecace, 0xffcecdce, 0xffcecace, 0xffcecdce, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffced0d0, 0xffcecece, + 0xffced0ce, 0xffced0ce, 0xffced0ce, 0xffced0ce, 0xffd0ced0, 0xffd0ced0, 0xffd0ced0, 0xffd0ced0, + 0xffced0d0, 0xffced1d3, 0xffced1d3, 0xffced0d0, 0xffd0d0d0, 0xffd3d1d3, 0xffd3d1d3, 0xffd0d0d0, + 0xffd6d1d3, 0xffd6d1d3, 0xffd6d0d0, 0xffd6d0d0, 0xffd0d0d0, 0xffd3d1d3, 0xffd3d1d3, 0xffd0d0d0, + 0xffd5d2d3, 0xffd6d3d6, 0xffd7d2d5, 0xffd6d1d5, 0xffd6d1d5, 0xffd4cfd3, 0xffd0ced0, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffced2ce, 0xffcecace, 0xffcecece, 0xffcecece, 0xffcbcccb, + 0xffcbcccb, 0xffcbcccb, 0xffcbcccb, 0xffcbcacb, 0xffcbcacb, 0xffcbcacb, 0xffcbcacb, 0xffc5cac5, + 0xffc0c4c0, 0xffc0c4c0, 0xffb5b6b5, 0xffa5a6a5, 0xffa5a6a5, 0xffa5a6a5, 0x66424242, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x44000000, 0x883c3b3c, 0x99656263, 0x99656263, 0x99656263, 0x99737173, + 0x99707070, 0x99707070, 0x99707070, 0x99707070, 0x996b6c6b, 0x996b6c6b, 0x996b6c6b, 0x996b6c6b, + 0x996b696b, 0x996b696b, 0x996e6c6e, 0x996e6c6e, 0x996b6b6b, 0x996b6b6b, 0x996b686b, 0x996b6b6b, + 0x996e696e, 0x996e696e, 0x996e696e, 0x996e696e, 0x996b696b, 0x996b696b, 0x996b6b6b, 0x996b696b, + 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, + 0x996b6b6b, 0x996b6c6b, 0x996b6c6b, 0x996b6b6b, 0x99706f70, 0x99706f70, 0x99706f70, 0x99706f70, + 0x996b6d6b, 0x996b6f6b, 0x996b6f6b, 0x996b6f6b, 0x996e6d6e, 0x996e6d6e, 0x996e6d6e, 0x996e6d6e, + 0x996b6f6e, 0x996b6f6e, 0x996b7070, 0x996b7070, 0x99707070, 0x99707070, 0x996e6f6e, 0x99707070, + 0x99736f6e, 0x99737070, 0x99736f6e, 0x99737070, 0x99707070, 0x996e6f6e, 0x99707070, 0x99707070, + 0x9970706e, 0x9970706e, 0x9970706e, 0x9970706e, 0x99707070, 0x996e6f6e, 0x99707070, 0x996e6f6e, + 0x996b706e, 0x996b706e, 0x996b6f70, 0x996b6f70, 0x996e6f6e, 0x99737173, 0x99707070, 0x99707070, + 0x99707070, 0x996e6f6e, 0x99707070, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, + 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6c6b, 0x996b6d6b, 0x996b6c6b, 0x996b6c6b, + 0x996b6c6b, 0x996b6b6b, 0x996b6d6b, 0x996b6c6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, + 0x996b6c6e, 0x996b6c6e, 0x996b6c6e, 0x996b6c6e, 0x9965686b, 0x9965686b, 0x9965686b, 0x9965686b, + 0x99686768, 0x99686768, 0x99656465, 0x99656465, 0x9963656b, 0x995d6065, 0x99585a60, 0x9952555a, + 0x994a4d4a, 0x994a4d4a, 0x881e1f1e, 0x66080808, 0x66000000, 0x44000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0xddc5cac5, 0xffc5cac5, 0xffc5cac5, 0xffc5cac5, + 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, 0xffcecece, 0xffced0d0, 0xffced0d0, 0xffced0d0, 0xffc5cace, + 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcbcdcb, 0xffcbcdcb, 0xffc8ccc8, 0xffcbcdcb, + 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecdce, 0xffcecace, + 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffced1d3, + 0xffcecece, 0xffced0ce, 0xffced0ce, 0xffced0ce, 0xffd0ced0, 0xffd0ced0, 0xffd0ced0, 0xffd0ced0, + 0xffced0d0, 0xffced0d0, 0xffced1d3, 0xffced1d3, 0xffd3d1d3, 0xffd6d2d6, 0xffd0d0d0, 0xffd3d1d3, + 0xffd6d0d0, 0xffd6d1d3, 0xffd6d0d0, 0xffd6d1d3, 0xffd3d1d3, 0xffd0d0d0, 0xffd3d1d3, 0xffd3d1d3, + 0xffd4d2d2, 0xffd6d2d6, 0xffd6d1d5, 0xffd5d1d5, 0xffd5d2d4, 0xffd2d1d2, 0xffcfcfcf, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcbcccb, + 0xffc8c9c8, 0xffc8c9c8, 0xffc8c9c8, 0xffcbcacb, 0xffc8c6c8, 0xffc8c6c8, 0xffc8c6c8, 0xffc0c4c0, + 0xffc0c4c0, 0xffbabdba, 0xffb5b6b5, 0xffa5a6a5, 0xffa5a6a5, 0xffa5a6a5, 0xbb737473, 0x110e0d0e, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0x55000000, 0x995a595a, 0x99656263, 0x99656263, 0x99656263, 0x99656263, + 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b6c6b, 0x996b6c6b, 0x99636563, 0x99636563, + 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b686b, 0x996b686b, 0x996b686b, 0x996b686b, + 0x996b656b, 0x996e696e, 0x996e696e, 0x996e696e, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, + 0x996b696b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, + 0x996b6b6b, 0x996b6c6b, 0x996b6c6b, 0x996b6c6b, 0x99706f70, 0x99737173, 0x99706f70, 0x99737173, + 0x996b6f6b, 0x996b6f6b, 0x996b6f6b, 0x996b706b, 0x99706d70, 0x996e6d6e, 0x996e6d6e, 0x99706d70, + 0x996b7070, 0x996b7070, 0x996b6f6e, 0x996b6f6e, 0x99707070, 0x99707070, 0x99737173, 0x99707070, + 0x99737070, 0x99737070, 0x99737173, 0x99737173, 0x99707070, 0x99737173, 0x99707070, 0x99707070, + 0x9970706e, 0x9970706e, 0x9970706e, 0x9970706e, 0x99707070, 0x99707070, 0x99707070, 0x99707070, + 0x996b706e, 0x996b706e, 0x996b706e, 0x996b706e, 0x99707070, 0x99707070, 0x99737173, 0x99737173, + 0x99737173, 0x99707070, 0x99707070, 0x996e6f6e, 0x99707070, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, + 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6c6b, 0x996b6c6b, 0x996b6c6b, 0x996b6d6b, + 0x996b6c6b, 0x996b6d6b, 0x996b6c6b, 0x996b6c6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, + 0x996b6c6e, 0x996b696b, 0x996b696b, 0x996b696b, 0x9965686b, 0x9965686b, 0x9963656b, 0x9963656b, + 0x99656465, 0x99656465, 0x99656465, 0x99636163, 0x995d6065, 0x995d6065, 0x99585a60, 0x9952555a, + 0x994a4d4a, 0x994a4d4a, 0x99343634, 0x66080808, 0x66000000, 0x55000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x44313131, 0xffc5cac5, 0xffc5cac5, 0xffc5cac5, 0xffc5cac5, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffc5cace, 0xffc5cace, 0xffc5cace, 0xffc5cace, + 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffc5cac5, 0xffc5cac5, 0xffc5cac5, 0xffc5cac5, + 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, + 0xffcecace, 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffced1d3, 0xffced0d0, 0xffced1d3, + 0xffced0ce, 0xffced0ce, 0xffced0ce, 0xffced2ce, 0xffd3ced3, 0xffd0ced0, 0xffd0ced0, 0xffd3ced3, + 0xffced1d3, 0xffced1d3, 0xffced0d0, 0xffced0d0, 0xffd3d1d3, 0xffd6d2d6, 0xffd6d2d6, 0xffd3d1d3, + 0xffd6d1d3, 0xffd6d1d3, 0xffd6d2d6, 0xffd6d2d6, 0xffd3d1d3, 0xffd6d2d6, 0xffd3d1d3, 0xffd6d2d6, + 0xffd6d2d6, 0xffd7d2d6, 0xffd5d3d5, 0xffd5d1d5, 0xffd3d1d2, 0xffd0d0d0, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecace, 0xffcecace, 0xffcecace, 0xffc8c9c8, + 0xffc8c9c8, 0xffc8c9c8, 0xffc8c9c8, 0xffc8c6c8, 0xffc8c6c8, 0xffc8c6c8, 0xffc5c2c5, 0xffc0c4c0, + 0xffbabdba, 0xffbabdba, 0xffb5b6b5, 0xffa5a6a5, 0xffa5a6a5, 0xffa5a6a5, 0xeea5a6a5, 0x44292829, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x22000400, 0x771e201e, 0x995a595a, 0x99525452, 0x995a5a5a, 0x99636163, 0x99636163, + 0x996b696b, 0x99656568, 0x99656568, 0x99656568, 0x99636563, 0x99636563, 0x99636563, 0x99636563, + 0x99686568, 0x99656565, 0x99656565, 0x99656565, 0x996b6765, 0x996b6765, 0x996b6868, 0x996b6765, + 0x996b676b, 0x996b686b, 0x996b676b, 0x996b686b, 0x996b696b, 0x996b696b, 0x996b6b6b, 0x996b696b, + 0x996b696b, 0x996b696b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6c6b, + 0x996e6f6e, 0x996b6d6b, 0x996b6d6b, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, + 0x99737173, 0x99737173, 0x99737173, 0x996e746e, 0x99737173, 0x99737373, 0x99737173, 0x99737173, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99707173, 0x996e7173, 0x99707173, 0x99707173, + 0x99707070, 0x99707070, 0x996e6f6e, 0x99707070, 0x99736f6e, 0x99737070, 0x99736f6e, 0x99737070, + 0x99707070, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996b6d6b, 0x996b6d6b, + 0x996b6f6e, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6c6b, + 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, 0x99686868, 0x99656765, 0x99656765, 0x99636563, + 0x99636463, 0x99636463, 0x99636263, 0x99636163, 0x99636163, 0x995d5c5d, 0x995d5c5d, 0x995a595a, + 0x99525552, 0x993f423f, 0x993f423f, 0x77191c19, 0x77000000, 0x66000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x88737173, 0xffbdbabd, 0xffbdbabd, 0xffc5c2c5, 0xffc5c2c5, + 0xffc5cac5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, + 0xffc5c9c5, 0xffc5c8c5, 0xffc5c9c5, 0xffc5c8c5, 0xffc5c9c5, 0xffc5c9c5, 0xffc5cac5, 0xffc5c9c5, + 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecdce, 0xffcecace, + 0xffcecace, 0xffcecace, 0xffcecdce, 0xffcecdce, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffd0d0d0, 0xffcecece, 0xffd0d0d0, 0xffd0d0d0, 0xffd0d0d0, 0xffd0d0d0, 0xffd0d0d0, 0xffd0d0d0, + 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d5d0, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, + 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d4d6, 0xffd6d2d6, 0xffd6d4d6, 0xffd6d2d6, + 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d4d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d4d6, 0xffd6d4d6, + 0xffd6d4d6, 0xffd6d3d6, 0xffd7d1d5, 0xffd5d1d4, 0xffd2d0d2, 0xffd0d0d0, 0xffd0d0d0, 0xffd0d0d0, + 0xffd0d0d0, 0xffcecece, 0xffcecece, 0xffced0d0, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecdce, 0xffcecdce, 0xffcecace, 0xffcecace, 0xffc5cac5, + 0xffc5c8c5, 0xffc5c8c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c4c5, 0xffc5c4c5, 0xffc5c2bd, + 0xffc0bdbd, 0xffc0bdbd, 0xffbdbabd, 0xffb5b6b5, 0xffadadad, 0xffa5a3a5, 0xff9c9a9c, 0x77585a58, + 0x00000400, 0x00000300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x33000400, 0x883c3d3c, 0x995a595a, 0x99525452, 0x99525452, 0x995a5a5a, 0x99636163, + 0x99656568, 0x99656568, 0x99656568, 0x99656568, 0x99636563, 0x99636463, 0x99636463, 0x99636463, + 0x99656565, 0x99656565, 0x99656565, 0x99656565, 0x996b6765, 0x996b6765, 0x996b6765, 0x996b6765, + 0x996b676b, 0x996b686b, 0x996b686b, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b6b6b, + 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6c6b, 0x996b6d6b, 0x996b6b6b, 0x996b6d6b, 0x996b6c6b, + 0x996e6f6e, 0x996b6d6b, 0x99707070, 0x99737173, 0x996e6f6e, 0x996e6f6e, 0x99707070, 0x99707070, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737373, 0x99737473, 0x99737373, 0x99737373, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737373, 0x99737173, 0x99737173, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x99737373, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99707173, 0x99737173, 0x99737173, 0x99707173, + 0x99707070, 0x99707070, 0x99707070, 0x99707070, 0x99737070, 0x99737070, 0x99737070, 0x99737070, + 0x996e6f6e, 0x99707070, 0x99707070, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996b6d6b, + 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6c6b, 0x996b6b6b, 0x996b6b6b, 0x996b6c6b, + 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, 0x99686868, 0x99656765, 0x99656765, 0x99656765, + 0x99636263, 0x99636263, 0x99636263, 0x99636163, 0x99605e60, 0x99605e60, 0x995d5c5d, 0x995a595a, + 0x99525552, 0x993f423f, 0x993f423f, 0x88191c19, 0x77030303, 0x66000000, 0x22000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xddadaaad, 0xffb5b2b5, 0xffbdbabd, 0xffbdbabd, 0xffc5c2c5, + 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, + 0xffc5c6c5, 0xffc5c6c5, 0xffc5c8c5, 0xffc5c8c5, 0xffc5c9c5, 0xffc5c8c5, 0xffc5c9c5, 0xffc5c9c5, + 0xffcecace, 0xffcecace, 0xffcecace, 0xffcbccc8, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecdce, + 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffd0d0d0, 0xffd0d0d0, 0xffd3d1d3, 0xffd3d1d3, 0xffd0d0d0, 0xffd0d0d0, 0xffd3d1d3, 0xffd3d1d3, + 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d4d6, 0xffd6d5d6, 0xffd6d4d6, 0xffd6d4d6, + 0xffd6d2d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d5d6, 0xffd6d4d6, 0xffd6d4d6, + 0xffd6d4d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d2d6, + 0xffd6d5d6, 0xffd6d4d6, 0xffd6d1d3, 0xffd1d1d1, 0xffd3d1d3, 0xffd3d1d3, 0xffd0d0d0, 0xffd0d0d0, + 0xffd0d0d0, 0xffd0d0d0, 0xffcecece, 0xffcecece, 0xffcecece, 0xffced0d0, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecdce, 0xffcecace, 0xffcecace, 0xffcecace, 0xffc5cac5, + 0xffc5c8c5, 0xffc5c8c5, 0xffc5c8c5, 0xffc5c5c5, 0xffc5c5c5, 0xffc5c5c5, 0xffc5c4c5, 0xffc5c2bd, + 0xffc3c0bd, 0xffc0bdbd, 0xffbdbabd, 0xffb5b6b5, 0xffadadad, 0xffa5a3a5, 0xffa5a3a5, 0xaa585a58, + 0x11000400, 0x00000300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x44000400, 0x993c3d3c, 0x995a595a, 0x994a4d4a, 0x99525452, 0x995a5a5a, 0x99636163, + 0x99606165, 0x99606165, 0x99656568, 0x99656568, 0x99636563, 0x99636263, 0x99636263, 0x99636263, + 0x99686568, 0x99656565, 0x99656565, 0x99656565, 0x996b6765, 0x996b6563, 0x996b6765, 0x996b6868, + 0x996b686b, 0x996b686b, 0x996b686b, 0x996b696b, 0x996b696b, 0x996b6b6b, 0x996b6b6b, 0x996b6c6b, + 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6c6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, + 0x996e6f6e, 0x996e6f6e, 0x99707070, 0x99737173, 0x99707070, 0x99707070, 0x99707070, 0x99707070, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737573, 0x99737373, 0x99737573, + 0x99737373, 0x99737473, 0x99737373, 0x99737373, 0x99737373, 0x99737473, 0x99737173, 0x99737473, + 0x99737173, 0x99737473, 0x99737373, 0x99737373, 0x99737473, 0x99737373, 0x99737173, 0x99737173, + 0x99737373, 0x99737373, 0x99737473, 0x99737473, 0x99737173, 0x99737373, 0x99737373, 0x99737373, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99707173, 0x99707173, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x99707070, 0x99707070, 0x99707070, 0x996e6f6e, 0x99707070, 0x99707070, 0x996e6f6e, 0x996e6f6e, + 0x996b7070, 0x996b6f6e, 0x996b6f6e, 0x996b6d6b, 0x996b6d6b, 0x996b6b6b, 0x996b6b6b, 0x996b6c6b, + 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, 0x99656765, 0x99686868, 0x99656765, 0x99656765, + 0x99636463, 0x99636263, 0x99636263, 0x99636163, 0x99605e60, 0x995d5c5d, 0x995d5c5d, 0x995a595a, + 0x99525552, 0x99525552, 0x993f423f, 0x882c2f2c, 0x77050505, 0x66000000, 0x33000000, 0x00000000, + 0x00000000, 0x00000000, 0x11000000, 0xffadaaad, 0xffb5b2b5, 0xffb5b2b5, 0xffbdbabd, 0xffc5c2c5, + 0xffc5c2c5, 0xffc5c2c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c5c5, 0xffc5c5c5, 0xffc5c5c5, + 0xffc5c8c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c8c5, 0xffc5c8c5, 0xffc5c6c5, 0xffc5c9c5, 0xffc5cac5, + 0xffcecace, 0xffcecace, 0xffcecace, 0xffcbccc8, 0xffcecace, 0xffcecdce, 0xffcecdce, 0xffcecece, + 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffd0d0d0, 0xffd0d0d0, 0xffd3d1d3, 0xffd6d2d6, 0xffd3d1d3, 0xffd6d2d6, 0xffd6d2d6, 0xffd3d1d3, + 0xffd6d4d3, 0xffd6d2d6, 0xffd6d4d3, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d7d6, 0xffd6d4d6, 0xffd6d7d6, + 0xffd6d4d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d7d6, 0xffd6d4d6, 0xffd6d7d6, + 0xffd6d4d6, 0xffd6d7d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d7d6, 0xffd6d5d6, 0xffd6d4d6, 0xffd6d4d6, + 0xffd6d5d6, 0xffd6d5d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd3d1d3, 0xffd3d1d3, 0xffd0d0d0, 0xffd3d1d3, + 0xffd3d1d3, 0xffd0d0d0, 0xffd0d0d0, 0xffced1d3, 0xffced0d0, 0xffced0d0, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecdce, 0xffcecace, 0xffcecace, 0xffcecace, 0xffc5c9c5, + 0xffc5cac5, 0xffc5c8c5, 0xffc5c8c5, 0xffc5c6c5, 0xffc5c5c5, 0xffc5c4c5, 0xffc5c2c5, 0xffc5c2bd, + 0xffc0bdbd, 0xffc0bdbd, 0xffbdbabd, 0xffb5b6b5, 0xffadadad, 0xffa5a3a5, 0xffa5a3a5, 0xcc848684, + 0x22000400, 0x00000300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x55000400, 0x993c3d3c, 0x993c3d3c, 0x994a4d4a, 0x99525452, 0x995a5a5a, 0x995a5a5a, + 0x995a5d63, 0x99606165, 0x99606165, 0x99606165, 0x99636163, 0x99636263, 0x99636463, 0x99636263, + 0x99686568, 0x99656565, 0x99656565, 0x99656565, 0x996b6563, 0x996b6868, 0x996b6765, 0x996b6868, + 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b6b6b, 0x996b6c6b, 0x996b6c6b, + 0x996b6c6b, 0x996b6b6b, 0x996b6c6b, 0x996b6d6b, 0x996b6c6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, + 0x996e6f6e, 0x99707070, 0x99737173, 0x99707070, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x99707370, 0x99707370, 0x99737173, 0x99707370, 0x99737373, 0x99737473, 0x99737173, 0x99737473, + 0x99737573, 0x99737573, 0x99737373, 0x99737373, 0x99737373, 0x99737473, 0x99737373, 0x99737473, + 0x99737573, 0x99737473, 0x99737473, 0x99737473, 0x99737473, 0x99737473, 0x99737473, 0x99737373, + 0x99737573, 0x99737373, 0x99737473, 0x99737473, 0x99737373, 0x99737573, 0x99737473, 0x99737473, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x99737173, 0x99737173, 0x99707070, 0x99707070, 0x99737173, 0x99737173, 0x99737173, 0x99707070, + 0x996b7070, 0x996b6f6e, 0x996b6f6e, 0x996b6f6e, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6b6b, + 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, 0x99656765, 0x99686868, 0x99656765, + 0x99636463, 0x99636463, 0x99636263, 0x99636163, 0x99605e60, 0x99605e60, 0x995d5c5d, 0x995d5c5d, + 0x99525552, 0x99525552, 0x993f423f, 0x992c2f2c, 0x77080808, 0x77000000, 0x44000000, 0x00000000, + 0x00000000, 0x00000000, 0x443a393a, 0xffadaaad, 0xffadaaad, 0xffb5b2b5, 0xffbdbabd, 0xffbdbabd, + 0xffc5c2c5, 0xffc5c2c5, 0xffc5c2c5, 0xffc5c2c5, 0xffc5c4c5, 0xffc5c4c5, 0xffc5c6c5, 0xffc5c4c5, + 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c8c5, 0xffc5c6c5, 0xffc5cac5, 0xffc5c9c5, 0xffc5cac5, + 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecdce, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecdce, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffd0d0d0, 0xffd3d1d3, 0xffd6d2d6, 0xffd3d1d3, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, + 0xffd6d4d3, 0xffd6d4d3, 0xffd6d2d6, 0xffd6d4d3, 0xffd6d5d6, 0xffd6d7d6, 0xffd6d4d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d7d6, 0xffd6d5d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d4d5, + 0xffd6d7d6, 0xffd6d5d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd3d1d3, 0xffd6d2d6, 0xffd6d2d6, + 0xffd6d2d6, 0xffd6d2d6, 0xffd3d1d3, 0xffced1d3, 0xffced0d0, 0xffced0d0, 0xffced0d0, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffceccce, 0xffc5cac5, + 0xffc5c9c5, 0xffc5cac5, 0xffc5c9c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c4c5, 0xffc5c4c5, 0xffc5c2bd, + 0xffc3c0bd, 0xffc0bdbd, 0xffc0bdbd, 0xffb5b6b5, 0xffadadad, 0xffa5a3a5, 0xffa5a3a5, 0xdd848684, + 0x222c2f2c, 0x00000300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x55161716, 0x99424542, 0x99424542, 0x994a4c4a, 0x99525252, 0x995a595a, 0x995a595a, + 0x995d5e5d, 0x995d5e5d, 0x99606060, 0x99606060, 0x99636263, 0x99636263, 0x99636263, 0x99636463, + 0x99636563, 0x99636563, 0x99656765, 0x99636563, 0x996b686b, 0x996b676b, 0x996b686b, 0x996b696b, + 0x996b696b, 0x996b6b6b, 0x996b696b, 0x996b696b, 0x996e6c6e, 0x996e6c6e, 0x996e6c6e, 0x99706f70, + 0x996b6d6b, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x99707070, 0x996e6f6e, 0x99707070, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737373, 0x99737373, 0x99737173, + 0x99737373, 0x99737373, 0x99737373, 0x99737373, 0x99737373, 0x99737373, 0x99737373, 0x99737573, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737573, 0x99767776, 0x99767776, 0x99767776, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737473, 0x99737473, 0x99737473, 0x99737373, 0x99737573, 0x99737473, 0x99737473, 0x99737373, + 0x99737373, 0x99737373, 0x99737473, 0x99737373, 0x99737373, 0x99737173, 0x99737173, 0x99737373, + 0x99737373, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x99707070, 0x996e6f6e, 0x99707070, 0x996e6f6e, 0x99707070, 0x996e6f6e, 0x996e6f6e, 0x996b6d6b, + 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b696b, 0x996b6868, 0x996b6765, 0x996b6765, + 0x99656465, 0x99656465, 0x99656465, 0x99636163, 0x99636163, 0x99605e60, 0x995d5c5d, 0x995a595a, + 0x995a555a, 0x99524e52, 0x994a484a, 0x99424142, 0x770b0b0b, 0x77000000, 0x55000000, 0x00000000, + 0x00000000, 0x00000000, 0x44373737, 0xffa5a6a5, 0xffadaaad, 0xffb2b5b8, 0xffb5babd, 0xffb5babd, + 0xffbdc0c0, 0xffbdc0c0, 0xffbdc0c0, 0xffbdc2c5, 0xffc5c4c5, 0xffc5c4c5, 0xffc5c4c5, 0xffc5c6c5, + 0xffc5c6c5, 0xffc5c6c5, 0xffc5c8c5, 0xffc5c6c5, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecccb, + 0xffcecace, 0xffcecdce, 0xffcecace, 0xffcecace, 0xffcecece, 0xffcecece, 0xffcecece, 0xffced0d0, + 0xffd0d0d0, 0xffd0d0d0, 0xffd0d0d0, 0xffd0d0d0, 0xffd0d0d0, 0xffd3d1d3, 0xffd0d0d0, 0xffd3d1d3, + 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d4d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d8d9, 0xffd7d7d7, 0xffd8d7d8, 0xffd6d6d6, 0xffd7d6d6, + 0xffd5d8d9, 0xffd6d8d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d4d6, + 0xffd6d4d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d1d6, 0xffd6d1d6, 0xffd6d1d6, 0xffd6d1d6, 0xffd3d1d3, + 0xffd0d0d0, 0xffd0d0d0, 0xffcecece, 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffceccce, 0xffcecccb, + 0xffcec9c8, 0xffcec9c8, 0xffcec9c8, 0xffcbc8cb, 0xffcbc8cb, 0xffc8c5c8, 0xffc8c5c8, 0xffc5c2c5, + 0xffc3c0c3, 0xffc0bdc0, 0xffbdbabd, 0xffb5bab5, 0xffafb2af, 0xffaaaaaa, 0xffa5a2a5, 0xff9c9e9c, + 0x44343534, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x55161716, 0x99424542, 0x99424542, 0x99424542, 0x994a4c4a, 0x99525252, 0x995a595a, + 0x995a5d5a, 0x995d5e5d, 0x99636163, 0x99606060, 0x99636263, 0x99636263, 0x99636263, 0x99636463, + 0x99636563, 0x99636563, 0x99636563, 0x99656765, 0x996b676b, 0x996b686b, 0x996b686b, 0x996b696b, + 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996e6c6e, 0x996e6c6e, 0x99706f70, 0x99706f70, + 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x99707070, 0x99707070, 0x99707070, 0x99707070, 0x99737173, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737373, + 0x99737373, 0x99737373, 0x99737573, 0x99737473, 0x99737473, 0x99737573, 0x99737473, 0x99737473, + 0x99737573, 0x99737573, 0x99767776, 0x99737573, 0x99737573, 0x99767776, 0x99767776, 0x99767776, + 0x99767776, 0x997b797b, 0x99797879, 0x99767776, 0x99737776, 0x99737776, 0x99737776, 0x99737776, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737573, 0x99737473, 0x99737473, 0x99737573, 0x99737573, 0x99737473, 0x99737473, 0x99737473, + 0x99737573, 0x99737573, 0x99737473, 0x99737573, 0x99737473, 0x99737473, 0x99737373, 0x99737473, + 0x99737373, 0x99737473, 0x99737473, 0x99737173, 0x99737373, 0x99737373, 0x99737173, 0x99737173, + 0x99737173, 0x99707070, 0x99707070, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996b6d6b, + 0x996b6c6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b6765, + 0x99686768, 0x99656465, 0x99656465, 0x99656465, 0x99636163, 0x99605e60, 0x995d5c5d, 0x995a595a, + 0x995a555a, 0x99524e52, 0x994a484a, 0x99424142, 0x77101010, 0x77000000, 0x55000000, 0x11000000, + 0x00000000, 0x00000000, 0x55373737, 0xffa5a6a5, 0xffadaaad, 0xffafafb2, 0xffb2b5b8, 0xffb5babd, + 0xffbdbebd, 0xffbdc0c0, 0xffbdc2c5, 0xffbdc1c3, 0xffc5c4c5, 0xffc5c4c5, 0xffc5c5c5, 0xffc5c6c5, + 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c9c5, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecccb, + 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecece, 0xffcecece, 0xffced0d0, 0xffced0d0, + 0xffd0d0d0, 0xffd0d0d0, 0xffd0d0d0, 0xffd3d1d3, 0xffd3d1d3, 0xffd6d2d6, 0xffd3d1d3, 0xffd6d2d6, + 0xffd6d4d6, 0xffd6d4d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d5d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd9d8d9, 0xffd6d7d6, 0xffd6d7d6, 0xffd9d8d6, 0xffdbd9d6, 0xffd9d8d6, + 0xffd6d7d6, 0xffd6dbde, 0xffd6d9db, 0xffd7d9dc, 0xffd9d9d9, 0xffdbd8dc, 0xffdcd8dd, 0xffd9d7da, + 0xffd5d7da, 0xffd5d7d6, 0xffd5d5d6, 0xffd6d5d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d4d6, 0xffd6d5d6, + 0xffd6d4d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d1d6, 0xffd0d0d0, + 0xffd0d0d0, 0xffd0d0d0, 0xffd0d0d0, 0xffcecece, 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecccb, + 0xffcecccb, 0xffcecccb, 0xffcec9c8, 0xffcbc8cb, 0xffc8c5c8, 0xffc8c5c8, 0xffc8c5c8, 0xffc5c2c5, + 0xffc3c0c3, 0xffc0bdc0, 0xffbdbabd, 0xffb5bab5, 0xffafb2af, 0xffaaaaaa, 0xffa5a2a5, 0xff9c9e9c, + 0x55343534, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x66161716, 0x99424542, 0x99424542, 0x99424542, 0x994a4c4a, 0x99525252, 0x995a595a, + 0x995a5d5a, 0x995d5e5d, 0x995d5e5d, 0x99636163, 0x99636163, 0x99636263, 0x99636463, 0x99636463, + 0x99636563, 0x99656765, 0x99656765, 0x99656765, 0x996b686b, 0x996b676b, 0x996b686b, 0x996b696b, + 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996e6c6e, 0x99706f70, 0x99737173, 0x99706f70, + 0x996e6f6e, 0x99707070, 0x99707070, 0x99707070, 0x99707070, 0x99707070, 0x99737173, 0x99737173, + 0x99737473, 0x99737573, 0x99737373, 0x99737473, 0x99737373, 0x99737373, 0x99737473, 0x99737573, + 0x99737473, 0x99737473, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99767776, 0x997b797b, 0x99767776, 0x99767776, 0x99767776, 0x99767776, 0x99767776, 0x997b797b, + 0x99797879, 0x99767776, 0x99767776, 0x99767776, 0x99737776, 0x99737776, 0x99737776, 0x99737776, + 0x99737773, 0x99737573, 0x99737773, 0x99737773, 0x99767773, 0x99767773, 0x99767773, 0x99767773, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737373, 0x99737573, 0x99737373, 0x99737573, 0x99737373, 0x99737473, 0x99737373, 0x99737173, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99707070, 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, + 0x996b6d6b, 0x996b6d6b, 0x996b6b6b, 0x996b6b6b, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b6868, + 0x99686768, 0x99686768, 0x99656465, 0x99656465, 0x99636163, 0x99605e60, 0x995d5c5d, 0x995d5c5d, + 0x995a555a, 0x99524e52, 0x994a484a, 0x99424142, 0x77101010, 0x77000000, 0x55000000, 0x11000000, + 0x00000000, 0x00000000, 0x66373737, 0xffa5a6a5, 0xffadaaad, 0xffafafb2, 0xffb5babd, 0xffb5babd, + 0xffbdbebd, 0xffbdc0c0, 0xffbdc0c0, 0xffbdc2c5, 0xffc5c4c5, 0xffc5c4c5, 0xffc5c6c5, 0xffc5c6c5, + 0xffc5c6c5, 0xffc5c8c5, 0xffc5c9c5, 0xffc5c9c5, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecccb, + 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecece, 0xffcecece, 0xffced1d3, 0xffced0d0, + 0xffd0d0d0, 0xffd3d1d3, 0xffd3d1d3, 0xffd6d2d6, 0xffd3d1d3, 0xffd3d1d3, 0xffd6d2d6, 0xffd6d2d6, + 0xffd6d5d6, 0xffd6d7d6, 0xffd6d5d6, 0xffd6d7d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d8d6, 0xffd6d7d6, 0xffd6d8d6, 0xffd6d9d6, + 0xffd9d8d9, 0xffdbd9db, 0xffd9d8d9, 0xffdbd9db, 0xffdbd9d6, 0xffdbd9d6, 0xffdbd9d6, 0xffdedbd6, + 0xffd6d9db, 0xffd6d8d9, 0xffd6d9db, 0xffd7d8dc, 0xffd9dadb, 0xffdbdadc, 0xffdcd8dc, 0xffdcd8dc, + 0xffdcd7dc, 0xffdad7da, 0xffd8d8d7, 0xffd6d5d6, 0xffd6d7d6, 0xffd6d5d6, 0xffd6d7d6, 0xffd6d5d6, + 0xffd6d5d6, 0xffd6d5d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd3d1d3, + 0xffd0d0d0, 0xffd0d0d0, 0xffd0d0d0, 0xffcecece, 0xffcecece, 0xffcecdce, 0xffcecdce, 0xffcecccb, + 0xffcecccb, 0xffcecccb, 0xffcec9c8, 0xffcecace, 0xffcbc8cb, 0xffcbc8cb, 0xffc8c5c8, 0xffc5c2c5, + 0xffc5c2c5, 0xffc0bdc0, 0xffc0bdc0, 0xffb5bab5, 0xffafb2af, 0xffaaaaaa, 0xffa5a2a5, 0xff9c9e9c, + 0x55343534, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x66161716, 0x99424542, 0x99424542, 0x99424542, 0x994a4c4a, 0x99525252, 0x995a595a, + 0x995a5d5a, 0x995d5e5d, 0x995d5e5d, 0x99606060, 0x99636163, 0x99636263, 0x99636263, 0x99636463, + 0x99636563, 0x99656765, 0x99686868, 0x99686868, 0x996b686b, 0x996b686b, 0x996b696b, 0x996b696b, + 0x996b6b6b, 0x996b6c6b, 0x996b6c6b, 0x996b6c6b, 0x99706f70, 0x99706f70, 0x99706f70, 0x99706f70, + 0x99707070, 0x99707070, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x99737473, 0x99737573, 0x99737473, 0x99737373, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99797879, 0x997b797b, 0x99767776, 0x99767776, 0x99767776, 0x99767776, 0x99797879, 0x99767776, + 0x99767776, 0x99767776, 0x99767776, 0x997b797b, 0x99737776, 0x99737879, 0x99737776, 0x99737776, + 0x99737973, 0x99737773, 0x99737973, 0x99737973, 0x997b7973, 0x99767773, 0x99767773, 0x997b7973, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737573, 0x99737473, 0x99737573, 0x99737473, 0x99737573, 0x99737573, 0x99737373, 0x99737373, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99707070, 0x99707070, 0x996e6f6e, + 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6c6b, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, + 0x99686768, 0x99686768, 0x99656465, 0x99656465, 0x99636163, 0x99636163, 0x995d5c5d, 0x995d5c5d, + 0x995a555a, 0x99524e52, 0x994a484a, 0x99424142, 0x77101010, 0x77000000, 0x66000000, 0x11000000, + 0x00000000, 0x00000000, 0x776e6f6e, 0xffa5a6a5, 0xffadaaad, 0xffafafb2, 0xffb2b5b8, 0xffb5babd, + 0xffbdbebd, 0xffbdc0c0, 0xffbdc0c0, 0xffbdc1c3, 0xffc5c4c5, 0xffc5c4c5, 0xffc5c5c5, 0xffc5c6c5, + 0xffc5c6c5, 0xffc5c8c5, 0xffc5cac5, 0xffc5cac5, 0xffcecace, 0xffcecace, 0xffcecccb, 0xffcecccb, + 0xffcecdce, 0xffcecece, 0xffcecece, 0xffcecece, 0xffced0d0, 0xffced0d0, 0xffced1d3, 0xffced1d3, + 0xffd3d1d3, 0xffd3d1d3, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, + 0xffd6d5d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d5d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d8d6, 0xffd6d9d6, 0xffd6d9d6, 0xffd6d8d6, + 0xffdbd9db, 0xffdedbde, 0xffdbd9db, 0xffdbd9db, 0xffdbd9d6, 0xffdbd9d6, 0xffdedbd6, 0xffdbd9d6, + 0xffd6d9db, 0xffd6d9db, 0xffd6dadb, 0xffd7dade, 0xffdadbdb, 0xffdbdadc, 0xffdbd8dc, 0xffdcd8dc, + 0xffdcdadc, 0xffd9dad9, 0xffd7d8d7, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d2d6, + 0xffd3d1d3, 0xffd3d1d3, 0xffd0d0d0, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecccb, + 0xffcecccb, 0xffcecccb, 0xffcecccb, 0xffcecace, 0xffcbc8cb, 0xffcbc8cb, 0xffc8c5c8, 0xffc5c2c5, + 0xffc5c2c5, 0xffc0bdc0, 0xffc0bdc0, 0xffb5bab5, 0xffafb2af, 0xffaaaaaa, 0xffa5a2a5, 0xff9c9e9c, + 0x66343534, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11000000, 0x66161616, 0x99424142, 0x99424142, 0x994a454a, 0x99504c50, 0x995a595a, 0x995a595a, + 0x995d5c5d, 0x99605e60, 0x99605e60, 0x99605e60, 0x99636163, 0x99636263, 0x99636463, 0x99636563, + 0x996b656b, 0x996b676b, 0x996b686b, 0x996b686b, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b6b6b, + 0x996e6c6b, 0x996e6c6b, 0x99706f6b, 0x996e6c6b, 0x996e7070, 0x996e7070, 0x99686f6e, 0x99737173, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737373, 0x99737473, 0x99737473, 0x99737473, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99767776, 0x99767776, 0x99767776, 0x99767776, + 0x99767776, 0x99767776, 0x99767776, 0x99767776, 0x99767876, 0x99767876, 0x99767876, 0x99767876, + 0x997b7979, 0x997b7d7b, 0x997b7576, 0x997b7979, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x99767876, 0x99797b79, 0x99767876, 0x99767876, + 0x997b787b, 0x997b787b, 0x997b787b, 0x997b787b, 0x99767876, 0x99767876, 0x99767876, 0x99767876, + 0x99767876, 0x99767876, 0x99767876, 0x99767876, 0x99767776, 0x99767776, 0x99767776, 0x99767776, + 0x99767776, 0x99767776, 0x99767776, 0x99737573, 0x99737776, 0x99737573, 0x99737573, 0x99737573, + 0x99737473, 0x99737373, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x996e6f6e, 0x996e6f6e, 0x996e6f6e, 0x996b6d6b, 0x996b6c6b, 0x996b6c6b, 0x996b6b6b, 0x996b696b, + 0x99656865, 0x99656865, 0x99636563, 0x99636563, 0x99606160, 0x99606160, 0x995d5d5d, 0x995d5d5d, + 0x995a555a, 0x99524e52, 0x994a484a, 0x99424142, 0x77101410, 0x77000000, 0x66000000, 0x11000000, + 0x00000000, 0x00000000, 0x77686968, 0xff9c9e9c, 0xffa5aaa5, 0xffadb1ad, 0xffb5b7b5, 0xffb5b7b5, + 0xffbdbebd, 0xffc0c0c0, 0xffc3c1c3, 0xffc3c1c3, 0xffc5c2c5, 0xffc8c5c5, 0xffc8c5c5, 0xffcbc8c5, + 0xffc5c6c5, 0xffc8c9c8, 0xffc8c9c8, 0xffc8c9c8, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecdce, + 0xffcecece, 0xffcecece, 0xffd0d0d0, 0xffcecece, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd3d4d3, + 0xffd6d4d6, 0xffd6d2d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d9d6, 0xffd6d8d6, + 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, 0xffd6dbd6, 0xffd6dbd6, 0xffd9dcd9, 0xffd6dbd6, + 0xffdedbde, 0xffdeddde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedcde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedade, 0xffdcdcdd, 0xffdbdbdc, 0xffdbdbdc, 0xffdbdbdc, 0xffdcdadc, + 0xffdcdadd, 0xffdcdadc, 0xffd9d9d9, 0xffd8d9db, 0xffd9d8d9, 0xffdbd9db, 0xffd9d8d9, 0xffd6d9d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d4d6, + 0xffd6d4d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd0d0d0, 0xffd0d0d0, 0xffd0d0d0, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecdd0, 0xffceccd3, 0xffcbcccb, 0xffc8c9c8, 0xffc8c9c8, 0xffc5c6c5, 0xffc5c6c5, + 0xffc3c2c3, 0xffc0bec0, 0xffc0bec0, 0xffbdbab5, 0xffb5b2af, 0xffadaaaa, 0xffa5a2a5, 0xff9c9e9c, + 0x66343734, 0x00000300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11000000, 0x66161616, 0x99424142, 0x99424142, 0x994a454a, 0x99504c50, 0x99555255, 0x995a595a, + 0x995d5c5d, 0x99605e60, 0x99605e60, 0x99636163, 0x99636263, 0x99636263, 0x99636563, 0x99636563, + 0x996b676b, 0x996b686b, 0x996b676b, 0x996b696b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, 0x996b6b6b, + 0x99706f6b, 0x996e6c6b, 0x99706f6b, 0x99706f6b, 0x996e7070, 0x996e7070, 0x996e7070, 0x996e7070, + 0x99737173, 0x99737373, 0x99737173, 0x99737473, 0x99737373, 0x99737373, 0x99737573, 0x99737573, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99767776, 0x99767776, 0x99767776, 0x99767776, + 0x99767776, 0x99767776, 0x99767776, 0x99767776, 0x99767876, 0x99767876, 0x99767876, 0x99797b79, + 0x997b7979, 0x997b7979, 0x997b7979, 0x997b7979, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b7b7b, + 0x997b797b, 0x997b797b, 0x997b7b7b, 0x997b7c7b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x99797b79, 0x99797b79, 0x99797b79, 0x99797b79, + 0x997b787b, 0x997b787b, 0x997b787b, 0x997b787b, 0x99797b79, 0x99767876, 0x99767876, 0x99797b79, + 0x99797b79, 0x99767876, 0x99767876, 0x99767876, 0x997b797b, 0x99797879, 0x997b797b, 0x99797879, + 0x99767776, 0x99767776, 0x99767776, 0x99767776, 0x99737776, 0x99737776, 0x99737776, 0x99737573, + 0x99737573, 0x99737573, 0x99737473, 0x99737373, 0x99737173, 0x99737373, 0x99737173, 0x99737173, + 0x99707070, 0x99737173, 0x99707070, 0x996e6f6e, 0x996b6c6b, 0x996b6d6b, 0x996b6c6b, 0x996b6b6b, + 0x99686b68, 0x99656865, 0x99656865, 0x99636563, 0x99636563, 0x99606160, 0x99606160, 0x995a595a, + 0x995a555a, 0x99524e52, 0x994a484a, 0x99424142, 0x77101410, 0x77000000, 0x66000000, 0x11000000, + 0x00000000, 0x00000000, 0x88686968, 0xff9c9e9c, 0xffa5aaa5, 0xffadb1ad, 0xffb5b7b5, 0xffb5b7b5, + 0xffbdbebd, 0xffc0c0c0, 0xffc0c0c0, 0xffc5c2c5, 0xffc8c5c5, 0xffc8c5c5, 0xffcbc8c5, 0xffcbc8c5, + 0xffc8c9c8, 0xffc8c9c8, 0xffc8c9c8, 0xffcbcccb, 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecdce, + 0xffd0d0d0, 0xffcecece, 0xffd0d0d0, 0xffd0d0d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, + 0xffd6d2d6, 0xffd6d5d6, 0xffd6d4d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d9d6, 0xffd6d9d6, 0xffd6d9d6, + 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, 0xffd6dbd6, 0xffd9dcd9, 0xffd9dcd9, 0xffd9dcd9, + 0xffdedbde, 0xffdedcde, 0xffdedcde, 0xffdedcde, 0xffdedcde, 0xffdedcde, 0xffdedbde, 0xffdeddde, + 0xffdedcde, 0xffdedcde, 0xffdddddd, 0xffdbdddd, 0xffdbdddc, 0xffdbdddc, 0xffdddbdd, 0xffdedbde, + 0xffdfdbdf, 0xffe0dbdf, 0xffdcdadc, 0xffd7dadc, 0xffd8d9d9, 0xffdad9da, 0xffdbd9db, 0xffd6d9d6, + 0xffd6d9d6, 0xffd6d8d6, 0xffd6d7d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d4d6, + 0xffd6d5d6, 0xffd6d4d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd3d1d3, 0xffd0d0d0, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecdd0, 0xffcbcccb, 0xffcbcccb, 0xffc8c9c8, 0xffc5c6c5, 0xffc5c6c5, + 0xffc3c2c3, 0xffc3c2c3, 0xffbdbabd, 0xffbdbab5, 0xffb5b2af, 0xffadaaaa, 0xffa5a2a5, 0xff9c9e9c, + 0x66343734, 0x00000300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11000000, 0x77161616, 0x99424142, 0x99424142, 0x994a454a, 0x99504c50, 0x99555255, 0x995a595a, + 0x995d5c5d, 0x99605e60, 0x99636163, 0x99636163, 0x99636463, 0x99636563, 0x99636563, 0x99636563, + 0x996b676b, 0x996b676b, 0x996b696b, 0x996b696b, 0x996b6b6b, 0x996b6b6b, 0x996b6c6b, 0x996b6d6b, + 0x99706f6b, 0x99706f6b, 0x99706f6b, 0x99706f6b, 0x996e7070, 0x996e7070, 0x99737173, 0x99737173, + 0x99737373, 0x99737373, 0x99737373, 0x99737373, 0x99737473, 0x99737473, 0x99737573, 0x99737573, + 0x99737573, 0x99737573, 0x99737773, 0x99737773, 0x99767776, 0x99767776, 0x99767776, 0x99767776, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x99767876, 0x99797b79, 0x99797b79, 0x99797b79, + 0x997b7979, 0x997b7979, 0x997b7979, 0x997b7979, 0x997b797b, 0x997b7c7b, 0x997b7c7b, 0x997b7b7b, + 0x997b7b7b, 0x997b7b7b, 0x997b7b7b, 0x997b7c7b, 0x997b7b7b, 0x997b7d7b, 0x997b7c7b, 0x997b7c7b, + 0x997e7c7b, 0x997e7c7b, 0x99817f7b, 0x997e7c7b, 0x99797b79, 0x99797b79, 0x997b7d7b, 0x997b7d7b, + 0x997b7b7b, 0x997b7b7b, 0x997b7b7b, 0x997b7b7b, 0x99797b79, 0x99797b79, 0x99797b79, 0x99797b79, + 0x99797b79, 0x99767876, 0x99797b79, 0x99797b79, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, + 0x997b797b, 0x997b797b, 0x997b797b, 0x99767776, 0x99737776, 0x99737776, 0x99737776, 0x99737776, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737373, 0x99737473, 0x99737173, 0x99737173, + 0x99737173, 0x99737173, 0x99707070, 0x99707070, 0x996b6d6b, 0x996b6c6b, 0x996b6c6b, 0x996b6b6b, + 0x99686b68, 0x99656865, 0x99656865, 0x99656865, 0x99636563, 0x99606160, 0x995d5d5d, 0x995d5d5d, + 0x995a555a, 0x99524e52, 0x994a484a, 0x99424142, 0x77101410, 0x77000000, 0x66000000, 0x11000000, + 0x00000000, 0x00000000, 0x99686968, 0xff9c9e9c, 0xffa5aaa5, 0xffadb1ad, 0xffb5b7b5, 0xffbdbebd, + 0xffbdbebd, 0xffc0c0c0, 0xffc5c2c5, 0xffc5c2c5, 0xffc8c5c5, 0xffcbc8c5, 0xffcbc8c5, 0xffcbc8c5, + 0xffc8c9c8, 0xffc8c9c8, 0xffcbcccb, 0xffcbcccb, 0xffcecdce, 0xffcecdce, 0xffcecece, 0xffcecece, + 0xffd0d0d0, 0xffd0d0d0, 0xffd3d1d3, 0xffd3d1d3, 0xffd0d1d0, 0xffd0d1d0, 0xffd3d4d3, 0xffd3d4d3, + 0xffd6d5d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d8d6, 0xffd6d9d6, 0xffd6d9d6, 0xffd6d9d6, 0xffd6d9d6, 0xffd6d9d6, 0xffd6d9d6, + 0xffdbdcdb, 0xffdbdcdb, 0xffdbdcdb, 0xffdbdcdb, 0xffd9dcd9, 0xffd9dcd9, 0xffd9dcd9, 0xffdbdddb, + 0xffdedcde, 0xffdeddde, 0xffdedcde, 0xffdedcde, 0xffdedcde, 0xffdedfde, 0xffdedfde, 0xffdeddde, + 0xffdeddde, 0xffdeddde, 0xffe1dee1, 0xffdfdedf, 0xffdddfdd, 0xffdddddc, 0xffdddcdd, 0xffdddfe0, + 0xffdfdedf, 0xffdfdcdf, 0xffdfdcdf, 0xffdfdbdf, 0xffdfdbde, 0xffdfdbdf, 0xffdcd9dc, 0xffd6d9d6, + 0xffd6d9d6, 0xffd6d9d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d5d6, + 0xffd6d7d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd3d1d3, 0xffd3d1d3, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecdd0, 0xffcbcccb, 0xffc8c9c8, 0xffc8c9c8, 0xffc8c9c8, 0xffc5c6c5, + 0xffc3c2c3, 0xffc3c2c3, 0xffc0bec0, 0xffbdbab5, 0xffb5b2af, 0xffadaaaa, 0xffa5a2a5, 0xff9c9e9c, + 0x66343734, 0x00000300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11000000, 0x77161616, 0x99424142, 0x99424142, 0x994a454a, 0x99504c50, 0x995a595a, 0x995a595a, + 0x99605e60, 0x99605e60, 0x99636163, 0x99636163, 0x99636563, 0x99636563, 0x99636563, 0x99636563, + 0x996b676b, 0x996b686b, 0x996b696b, 0x996b696b, 0x996b6c6b, 0x996b6b6b, 0x996b6c6b, 0x996b6d6b, + 0x99706f6b, 0x99706f6b, 0x99706f6b, 0x9973716b, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x99737173, 0x99737473, 0x99737473, 0x99737473, 0x99737473, 0x99737573, 0x99737573, 0x99737573, + 0x99737773, 0x99737773, 0x99737773, 0x99737973, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x99797b79, 0x99797b79, 0x99797b79, 0x997b7d7b, + 0x997b7979, 0x997b7d7b, 0x997b7979, 0x997b7d7b, 0x997b7c7b, 0x997b7c7b, 0x997b7c7b, 0x997b7d7b, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7c7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x997e7c7b, 0x99817f7b, 0x99817f7b, 0x997e7c7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x99797b79, + 0x997b7d7b, 0x997b7b7b, 0x997b7d7b, 0x997b7b7b, 0x99797b79, 0x99797b79, 0x99797b79, 0x99797b79, + 0x997b7d7b, 0x99797b79, 0x997b7d7b, 0x99797b79, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x9973797b, 0x99737776, 0x99737776, 0x99737776, + 0x99737573, 0x99737573, 0x99737573, 0x99737473, 0x99737573, 0x99737473, 0x99737373, 0x99737173, + 0x99737173, 0x99737173, 0x99737173, 0x99707070, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6b6b, + 0x996b6d6b, 0x99686b68, 0x99656865, 0x99656865, 0x99636563, 0x99606160, 0x99606160, 0x995d5d5d, + 0x995a555a, 0x99524e52, 0x994a484a, 0x99424142, 0x77101410, 0x77000000, 0x66000000, 0x11000000, + 0x00000000, 0x00000000, 0x88686968, 0xff9c9e9c, 0xffa5aaa5, 0xffadb1ad, 0xffb5b7b5, 0xffbdbebd, + 0xffc0c0c0, 0xffc0c0c0, 0xffc3c1c3, 0xffc5c2c5, 0xffc8c5c5, 0xffcbc8c5, 0xffcbc8c5, 0xffcbc8c5, + 0xffc8c9c8, 0xffc8c9c8, 0xffcbcccb, 0xffcbcccb, 0xffcecece, 0xffcecdce, 0xffcecece, 0xffcecece, + 0xffd0d0d0, 0xffd3d1d3, 0xffd0d0d0, 0xffd3d1d3, 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, 0xffd3d4d3, + 0xffd6d4d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d9d6, + 0xffd6d9d6, 0xffd6d9d6, 0xffd6d9d6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffdbdcdb, 0xffdbdcdb, 0xffdbdcdb, 0xffdbdcdb, 0xffd9dcd9, 0xffd9dcd9, 0xffdbdddb, 0xffdedfde, + 0xffdeddde, 0xffdedfde, 0xffdeddde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, + 0xffdedfde, 0xffdfdee0, 0xffe1dfe1, 0xffe2dfe2, 0xffe2dfe2, 0xffe4dfe4, 0xffe2dee1, 0xffdddee2, + 0xffdedddf, 0xffdedcdf, 0xffdedcdf, 0xffdfdedf, 0xffdfdede, 0xffdedede, 0xffdedbde, 0xffd5dbd5, + 0xffd6d9d6, 0xffd6d9d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d5d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d5d6, 0xffd6d4d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecdd0, 0xffcecece, 0xffcbcccb, 0xffcbcccb, 0xffc8c9c8, 0xffc5c6c5, + 0xffc3c2c3, 0xffc3c2c3, 0xffc0bec0, 0xffbdbab5, 0xffb5b2af, 0xffadaaaa, 0xffa5a2a5, 0xff9c9e9c, + 0x66343734, 0x00000300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11000000, 0x66161616, 0x99424142, 0x99424142, 0x994a454a, 0x99504c50, 0x99555255, 0x995a595a, + 0x995a5d5a, 0x995d605d, 0x99606260, 0x99606260, 0x99656465, 0x99686768, 0x99686768, 0x99686768, + 0x996b696b, 0x996b6b6b, 0x996b6b6b, 0x996b6c6b, 0x996b6d6b, 0x996e6f6e, 0x996b6d6b, 0x996e6f6e, + 0x99737173, 0x996e6f73, 0x99707073, 0x99707073, 0x99737373, 0x99737173, 0x99737473, 0x99737473, + 0x99737573, 0x99737573, 0x99737776, 0x99737776, 0x99767776, 0x99767776, 0x99767776, 0x99767776, + 0x997b7876, 0x997b7876, 0x997b7876, 0x997b7876, 0x997b797b, 0x997b797b, 0x997b7b7b, 0x997b797b, + 0x997b7d7b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997e7c7e, 0x997e7c7e, 0x997e7c7e, 0x997e7c7e, + 0x997e807e, 0x99818381, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997e7f7e, 0x997b7d7b, 0x997b7d7b, + 0x997b7d7b, 0x997e7f7e, 0x997e7f7e, 0x997e7f7e, 0x997e807e, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x997b7d7b, 0x997b7d7b, 0x997e7f7e, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x997b7c7b, 0x997b797b, 0x997b797b, 0x997b797b, 0x99797b79, 0x99767876, 0x99767876, 0x99767876, + 0x99767776, 0x99767776, 0x99767776, 0x99767776, 0x99737573, 0x99737573, 0x99737573, 0x99737373, + 0x99737373, 0x99737173, 0x99737173, 0x99737173, 0x99707070, 0x99707070, 0x996e6f6e, 0x996e6f6e, + 0x996b6c6b, 0x996b6b6b, 0x996b696b, 0x996b696b, 0x99636563, 0x99606160, 0x995d5d5d, 0x995d5d5d, + 0x995a5552, 0x99524e4d, 0x99424142, 0x99424142, 0x77101010, 0x77000000, 0x66000000, 0x11000000, + 0x00000400, 0x00000400, 0x886e6d6e, 0xffa5a2a5, 0xffa5aaa5, 0xffadb1ad, 0xffb5b7b5, 0xffbdbebd, + 0xffc0c1c0, 0xffc0c1c0, 0xffc3c4c3, 0xffc3c4c3, 0xffc5c6c5, 0xffc8c9c8, 0xffc8c9c8, 0xffc8c9c8, + 0xffcecace, 0xffcecdce, 0xffcecdce, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffced0d0, + 0xffd0d1d6, 0xffd0d1d6, 0xffd0d1d6, 0xffd0d1d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d5d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, + 0xffdedbd6, 0xffdedbd6, 0xffdedcd9, 0xffdedcd9, 0xffdedcde, 0xffdedbde, 0xffdeddde, 0xffdedcde, + 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, + 0xffe1e0e1, 0xffe6e3e6, 0xffe1e0e1, 0xffdedfde, 0xffdedfde, 0xffe1e1e1, 0xffe1e1e1, 0xffdddfdd, + 0xffe1dfe1, 0xffe3e0e3, 0xffe4e1e4, 0xffe3e0e3, 0xffe4e1e4, 0xffe4dfe4, 0xffe5dfe4, 0xffe5dee5, + 0xffe6dfe5, 0xffe6dfe5, 0xffe4dfe3, 0xffe0dee0, 0xffdfdedf, 0xffdfdede, 0xffdededf, 0xffdedcdb, + 0xffdedcdb, 0xffdedcdb, 0xffdedbde, 0xffd9d8d9, 0xffdbd9db, 0xffd9d8d9, 0xffd9d8d9, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d5d6, 0xffd6d4d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd0d1d0, + 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffcecece, 0xffcecdce, 0xffcecace, 0xffcecace, 0xffc5c6c5, + 0xffc5c6c5, 0xffc0c1c0, 0xffbdbebd, 0xffb5b6b5, 0xffafafaf, 0xffaaa9aa, 0xffa5a2a5, 0xff9c9a9c, + 0x55343334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x66161616, 0x99424142, 0x99424142, 0x994a454a, 0x99504c50, 0x99555255, 0x995a595a, + 0x995a5d5a, 0x995d605d, 0x99606260, 0x99636563, 0x99656465, 0x99656465, 0x99686768, 0x996b696b, + 0x996b6b6b, 0x996b6c6b, 0x996b6c6b, 0x996b6c6b, 0x99737173, 0x99707070, 0x99707070, 0x99737173, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737373, 0x99737373, 0x99737473, 0x99737473, + 0x99737573, 0x99737573, 0x99737776, 0x99737879, 0x99797879, 0x99767776, 0x99767776, 0x99767776, + 0x997b7b79, 0x997b7876, 0x997b7876, 0x997b7876, 0x997b797b, 0x997b797b, 0x997b7c7b, 0x997b7c7b, + 0x997b797b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x99817f81, 0x997e7c7e, 0x997e7c7e, 0x997e7c7e, + 0x997e807e, 0x997e807e, 0x997b7d7b, 0x997b7d7b, 0x997e7f7e, 0x997e7f7e, 0x99818081, 0x997e7f7e, + 0x99818081, 0x99818081, 0x99848284, 0x99848284, 0x997e807e, 0x997e807e, 0x997e807e, 0x997e807e, + 0x99818081, 0x997e7f7e, 0x997e7f7e, 0x99818081, 0x997e7f7e, 0x997e7f7e, 0x997e7f7e, 0x997e7f7e, + 0x997e7f7e, 0x997e7f7e, 0x997e7f7e, 0x997e7f7e, 0x997b7d7b, 0x997e807e, 0x997e807e, 0x997e807e, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x997b7c7b, 0x997b7b7b, 0x997b797b, 0x997b7b7b, 0x99797b79, 0x99797b79, 0x99767876, 0x99767876, + 0x99797879, 0x99767776, 0x99767776, 0x99767776, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737473, 0x99737173, 0x99737173, 0x99737173, 0x99707070, 0x99707070, 0x996e6f6e, 0x996e6f6e, + 0x996b6c6b, 0x996b6c6b, 0x996b6b6b, 0x996b696b, 0x99636563, 0x99636563, 0x99606160, 0x995d5d5d, + 0x995a5552, 0x99524e4d, 0x994a4847, 0x99424142, 0x77101010, 0x77000000, 0x66000000, 0x11000000, + 0x00000400, 0x00000400, 0x776e6d6e, 0xffa5a2a5, 0xffa5aaa5, 0xffadb1ad, 0xffb5b7b5, 0xffbdbebd, + 0xffc0c1c0, 0xffc0c1c0, 0xffc3c4c3, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc8c9c8, 0xffcbcccb, + 0xffceccce, 0xffcecdce, 0xffcecece, 0xffcecece, 0xffced1d3, 0xffced1d3, 0xffced1d3, 0xffced2d6, + 0xffd3d4d6, 0xffd3d4d6, 0xffd3d4d6, 0xffd3d4d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d5d6, 0xffd6d5d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d8d6, 0xffd6dbd6, 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, + 0xffdedcd9, 0xffdedcd9, 0xffdedcd9, 0xffdedcd9, 0xffdedcde, 0xffdedcde, 0xffdedfde, 0xffdedfde, + 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdee0de, 0xffdedfde, 0xffdedfde, 0xffdedfde, + 0xffe4e1e4, 0xffe4e1e4, 0xffe1e0e1, 0xffe1e0e1, 0xffe1e1e1, 0xffe1e1e1, 0xffe4e4e4, 0xffe0e0e0, + 0xffe3e0e3, 0xffe3e0e3, 0xffe4e1e4, 0xffe5e2e5, 0xffe4e1e4, 0xffe4dfe4, 0xffe5e0e5, 0xffe5e2e5, + 0xffe6e2e5, 0xffe6e2e5, 0xffe6dfe6, 0xffe0dedf, 0xffdfdedf, 0xffdfdedf, 0xffdfdede, 0xffdfdcdd, + 0xffdedcdb, 0xffdedcdb, 0xffdedbde, 0xffdedbde, 0xffdbd9db, 0xffd9d8d9, 0xffd9d8d9, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d2d6, 0xffd0d1d0, + 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffcecece, 0xffcecece, 0xffcecdce, 0xffcecace, 0xffc5c6c5, + 0xffc5c6c5, 0xffc0c1c0, 0xffbdbebd, 0xffb5b6b5, 0xffafafaf, 0xffaaa9aa, 0xffa5a2a5, 0xff9c9a9c, + 0x55343334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x66161616, 0x99424142, 0x99424142, 0x994a454a, 0x99504c50, 0x995a595a, 0x995a595a, + 0x995d605d, 0x99606260, 0x99606260, 0x99606260, 0x99656465, 0x99686768, 0x99686768, 0x996b696b, + 0x996b6d6b, 0x996b6d6b, 0x996b6b6b, 0x996b6c6b, 0x996e6f6e, 0x996e6f6e, 0x99707070, 0x99707070, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737373, 0x99737573, 0x99737573, 0x99737573, + 0x99737776, 0x99737776, 0x99737776, 0x9973797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, + 0x997b7b79, 0x997b7b79, 0x997b7b79, 0x997b7d7b, 0x997b7b7b, 0x997b7b7b, 0x997b7c7b, 0x997b7c7b, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x99817f81, 0x99817f81, 0x99817f81, 0x99817f81, + 0x997b7d7b, 0x997e807e, 0x997e807e, 0x997e807e, 0x99818081, 0x99818081, 0x99818081, 0x997e7f7e, + 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99818381, 0x997e807e, 0x99818381, 0x997e807e, + 0x99848284, 0x99818081, 0x99818081, 0x99818081, 0x99848284, 0x997e7f7e, 0x99818081, 0x99818081, + 0x99818081, 0x997e7f7e, 0x99818081, 0x99818081, 0x997e807e, 0x997e807e, 0x997e807e, 0x997e807e, + 0x997e807e, 0x997e807e, 0x997e807e, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x997b7d7b, 0x997b7c7b, 0x997b7c7b, 0x997b7c7b, 0x99797b79, 0x99797b79, 0x99797b79, 0x99797b79, + 0x99797879, 0x99767776, 0x99797879, 0x99767776, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737473, 0x99737473, 0x99737373, 0x99737173, 0x99737173, 0x99707070, 0x99707070, 0x996e6f6e, + 0x996b6d6b, 0x996b6d6b, 0x996b6b6b, 0x996b696b, 0x99636563, 0x99636563, 0x995d5d5d, 0x995d5d5d, + 0x995a5552, 0x99524e4d, 0x99424142, 0x99424142, 0x77101010, 0x77000000, 0x66000000, 0x11000000, + 0x00000400, 0x00000400, 0x66373937, 0xffa5a2a5, 0xffa5aaa5, 0xffadb1ad, 0xffb5b7b5, 0xffbdbebd, + 0xffc0c1c0, 0xffc3c4c3, 0xffc3c4c3, 0xffc5c6c5, 0xffc5c6c5, 0xffc8c9c8, 0xffc8c9c8, 0xffcbcccb, + 0xffcecece, 0xffcecece, 0xffcecdce, 0xffcecece, 0xffced0d0, 0xffced0d0, 0xffced1d3, 0xffced1d3, + 0xffd3d4d6, 0xffd3d4d6, 0xffd3d4d6, 0xffd3d4d6, 0xffd6d5d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d8d6, + 0xffd6d8d6, 0xffd6d9d6, 0xffd6d9d6, 0xffd6dbd6, 0xffd9d9d9, 0xffdbdcdb, 0xffdbdcdb, 0xffdbdcdb, + 0xffdedcd9, 0xffdedddb, 0xffdedcd9, 0xffdedfde, 0xffdeddde, 0xffdeddde, 0xffdedfde, 0xffdedfde, + 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdee1de, 0xffdee1de, 0xffdee0de, 0xffdee1de, + 0xffe1e0e1, 0xffe6e3e6, 0xffe6e3e6, 0xffe4e1e4, 0xffe4e4e4, 0xffe3e3e4, 0xffe3e3e3, 0xffe2e3e2, + 0xffe3e3e3, 0xffe4e2e4, 0xffe4e2e4, 0xffe4e2e4, 0xffe5e2e5, 0xffe5e3e5, 0xffe5e2e5, 0xffe5e2e5, + 0xffe5e2e5, 0xffe6e2e5, 0xffe6e3e5, 0xffe3e0e3, 0xffe0dfe0, 0xffe0dfdf, 0xffe0dfdf, 0xffe0dede, + 0xffdfdddd, 0xffdedcdb, 0xffdedcdb, 0xffdedbde, 0xffdbd9db, 0xffdedbde, 0xffdbd9db, 0xffd6d9d6, + 0xffd6d8d6, 0xffd6d8d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d5d6, 0xffd6d4d6, 0xffd3d4d3, + 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffcecece, 0xffcecece, 0xffcecdce, 0xffcecace, 0xffc5c6c5, + 0xffc5c6c5, 0xffc0c1c0, 0xffbdbebd, 0xffb5b6b5, 0xffafafaf, 0xffa5a2a5, 0xffa5a2a5, 0xff9c9a9c, + 0x55343334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x66161616, 0x99424142, 0x99424142, 0x994a454a, 0x99504c50, 0x99555255, 0x995a595a, + 0x995a5d5a, 0x995d605d, 0x99606260, 0x99606260, 0x99686768, 0x99656465, 0x99686768, 0x996b696b, + 0x996b6b6b, 0x996b6c6b, 0x996b6c6b, 0x996b6d6b, 0x996e6f6e, 0x99707070, 0x99737173, 0x99707070, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737776, 0x99737776, 0x99737776, 0x99737776, 0x99797879, 0x997b797b, 0x997b797b, 0x997b797b, + 0x997b7b79, 0x997b7b79, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b827b, 0x99817f81, 0x99817f81, 0x99817f81, 0x99848284, + 0x99818381, 0x99818381, 0x997e807e, 0x99818381, 0x99848284, 0x99848284, 0x99848284, 0x99848284, + 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99818381, 0x99818381, 0x99818381, 0x99818381, + 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848284, + 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848684, 0x99818381, 0x99848684, 0x99818381, + 0x99848684, 0x997e807e, 0x997e807e, 0x997e807e, 0x997b7f7b, 0x997b827b, 0x997b7f7b, 0x997b7d7b, + 0x997b7d7b, 0x997b7d7b, 0x997b7c7b, 0x997b7c7b, 0x99797b79, 0x997b7d7b, 0x99797b79, 0x99767876, + 0x997b797b, 0x997b797b, 0x99797879, 0x99767776, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x99737473, 0x99737473, 0x99737473, 0x99737373, 0x99737173, 0x99737173, 0x99707070, 0x99707070, + 0x996b6d6b, 0x996b6c6b, 0x996b6b6b, 0x996b696b, 0x99636563, 0x99606160, 0x995d5d5d, 0x995a595a, + 0x995a5552, 0x99524e4d, 0x99424142, 0x99424142, 0x77101010, 0x77000000, 0x55000000, 0x11000000, + 0x00000400, 0x00000400, 0x66373937, 0xffa5a2a5, 0xffa5aaa5, 0xffadb1ad, 0xffb5b7b5, 0xffbdbebd, + 0xffc0c1c0, 0xffc0c1c0, 0xffc3c4c3, 0xffc5c6c5, 0xffc8c9c8, 0xffc5c6c5, 0xffc8c9c8, 0xffcbcccb, + 0xffcecdce, 0xffcecece, 0xffcecece, 0xffcecece, 0xffced0d0, 0xffced1d3, 0xffced2d6, 0xffced2d6, + 0xffd3d4d6, 0xffd3d4d6, 0xffd3d4d6, 0xffd3d4d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d8d6, + 0xffd6d8d6, 0xffd6d9d6, 0xffd6d9d6, 0xffd6d9d6, 0xffdbdcdb, 0xffdbdcdb, 0xffdbdcdb, 0xffdbdcdb, + 0xffdedddb, 0xffdedddb, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, + 0xffdee0de, 0xffdee1de, 0xffdee0de, 0xffdee3de, 0xffdee1de, 0xffdee1de, 0xffdee1de, 0xffdee3de, + 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe3e4e3, 0xffe3e4e3, 0xffe2e4e2, 0xffe3e4e3, + 0xffe4e4e3, 0xffe4e3e4, 0xffe4e3e4, 0xffe4e4e5, 0xffe5e5e4, 0xffe5e3e5, 0xffe5e3e5, 0xffe5e2e5, + 0xffe6e2e5, 0xffe6e3e5, 0xffe6e3e5, 0xffe6e1e5, 0xffe3e0e3, 0xffe2dfe2, 0xffe0dfdf, 0xffe0dedf, + 0xffe0dfdc, 0xffdedcdc, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdbd9db, 0xffd6d9d6, + 0xffd6d9d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d5d6, 0xffd3d4d3, + 0xffd3d4d3, 0xffd0d1d0, 0xffd0d1d0, 0xffcecece, 0xffcecece, 0xffcecdce, 0xffcecace, 0xffc5c6c5, + 0xffc5c6c5, 0xffc0c1c0, 0xffbdbebd, 0xffb5b6b5, 0xffafafaf, 0xffaaa9aa, 0xffa5a2a5, 0xff9c9a9c, + 0x55343334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x66161616, 0x99424142, 0x99424142, 0x99424542, 0x994a4c4a, 0x99525252, 0x995a595a, + 0x995d5d5d, 0x99606160, 0x99606160, 0x99636563, 0x99656765, 0x99656765, 0x996b696b, 0x996b696b, + 0x996b6b6b, 0x996b6b6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d73, 0x996e7073, 0x99707373, 0x996e7073, + 0x99737373, 0x99737373, 0x99737473, 0x99737573, 0x99767776, 0x99767776, 0x99767776, 0x99767776, + 0x99767776, 0x99767776, 0x997b797b, 0x99797879, 0x997b797b, 0x997b797b, 0x997b7b7b, 0x997b7b7b, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997e807e, 0x997b7d7b, 0x997e807e, + 0x997e8084, 0x997e8084, 0x997e8084, 0x997e8084, 0x99848284, 0x99848284, 0x99848284, 0x99848384, + 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848384, 0x99848484, 0x99848484, + 0x99898484, 0x99898484, 0x99898484, 0x99898484, 0x99848684, 0x99848684, 0x99848684, 0x99848684, + 0x99898789, 0x99868486, 0x99868486, 0x99868486, 0x99868486, 0x99868486, 0x99848284, 0x99868486, + 0x99848484, 0x99848384, 0x99848384, 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99848384, + 0x99848384, 0x99848384, 0x99848284, 0x99848284, 0x99818081, 0x997e7f7e, 0x997e7f7e, 0x99818081, + 0x997e7f7e, 0x997e7f7e, 0x997b7d7b, 0x997b7d7b, 0x997b7c7b, 0x997b7c7b, 0x997b7b7b, 0x997b7c7b, + 0x997b7b7b, 0x997b797b, 0x997b797b, 0x997b797b, 0x99767876, 0x99767876, 0x99767876, 0x99737573, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737373, 0x99737373, 0x99737073, 0x99736d73, + 0x99737173, 0x99706d6e, 0x996e6968, 0x996e6968, 0x99636563, 0x99606060, 0x99606060, 0x995d5a5d, + 0x99525152, 0x99525152, 0x99454345, 0x99454345, 0x77080c08, 0x77000000, 0x55000000, 0x11000000, + 0x00000000, 0x00000000, 0x66373637, 0xffa5a2a5, 0xffadaaad, 0xffadaaad, 0xffb5b2b5, 0xffbdbabd, + 0xffc0bec0, 0xffc3c2c3, 0xffc3c2c3, 0xffc5c6c5, 0xffc8c9c8, 0xffc8c9c8, 0xffcbcccb, 0xffcbcccb, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffd0ced0, 0xffd0ced0, 0xffd3d2d3, 0xffd3d2d3, 0xffd3d2d3, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d9d6, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedcde, 0xffdedcde, 0xffdeddde, 0xffdeddde, + 0xffdedfde, 0xffdedfde, 0xffdee0e1, 0xffdedfde, 0xffdedfde, 0xffe1e1e1, 0xffe1e1e1, 0xffe1e1e1, + 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e5e6, + 0xffe6e3e6, 0xffe6e3e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe5e3e5, 0xffe4e5e4, 0xffe3e5e3, 0xffe4e5e3, + 0xffe4e6e4, 0xffe5e5e4, 0xffe5e6e5, 0xffe5e7e5, 0xffe5e6e4, 0xffe6e6e5, 0xffe6e6e6, 0xffe6e4e6, + 0xffe6e4e6, 0xffe6e4e6, 0xffe6e4e6, 0xffe6e3e5, 0xffe6e3e5, 0xffe6e1e5, 0xffe5e2e4, 0xffdfdfde, + 0xffdfe1df, 0xffdfdede, 0xffdedfde, 0xffdeddde, 0xffdedcde, 0xffdedcde, 0xffdedbde, 0xffd9d9d9, + 0xffdbdcdb, 0xffd9d9d9, 0xffd9d9d9, 0xffd6d7d6, 0xffd6d8d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d4d6, + 0xffd6d4d6, 0xffd6d1d6, 0xffd6d1d6, 0xffced2d6, 0xffceced0, 0xffceced0, 0xffcecacb, 0xffc5c6c5, + 0xffc3c2c3, 0xffc3c2c3, 0xffc0bec0, 0xffb5b2b5, 0xffadabad, 0xffa5a5a5, 0xff9c9e9c, 0xff8c8e8c, + 0x442f322f, 0x00000300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x55000000, 0x99424142, 0x99424142, 0x99424542, 0x994a4c4a, 0x99525252, 0x995a595a, + 0x995d5d5d, 0x995d5d5d, 0x99606160, 0x99636563, 0x99636563, 0x99656765, 0x99686868, 0x996b696b, + 0x996b6b6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996e7073, 0x996e7073, 0x996e7073, 0x99707373, + 0x99737473, 0x99737473, 0x99737573, 0x99737573, 0x99767776, 0x99767776, 0x99767776, 0x99767776, + 0x997b797b, 0x99767776, 0x997b797b, 0x997b797b, 0x997b7b7b, 0x997b7b7b, 0x997b7c7b, 0x997b7c7b, + 0x997e7f7e, 0x997b7d7b, 0x997e7f7e, 0x997e7f7e, 0x997b7d7b, 0x997e807e, 0x997e807e, 0x99818381, + 0x997e8084, 0x997e8084, 0x99818384, 0x99818384, 0x99848384, 0x99848384, 0x99848384, 0x99848484, + 0x99868686, 0x99898a89, 0x99848284, 0x99868686, 0x99848684, 0x99848684, 0x99848684, 0x99848484, + 0x99898484, 0x99898484, 0x99898484, 0x99868784, 0x99848684, 0x99848684, 0x99848684, 0x99848684, + 0x99898789, 0x99898789, 0x99868486, 0x99898789, 0x99898789, 0x99868486, 0x99868486, 0x99868486, + 0x99848684, 0x99848684, 0x99848484, 0x99848484, 0x99848484, 0x99848384, 0x99848484, 0x99848384, + 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99848284, 0x99818081, 0x99818081, 0x99818081, + 0x99818081, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7c7b, 0x997b7c7b, + 0x997b7b7b, 0x997b7b7b, 0x997b7b7b, 0x997b797b, 0x99767876, 0x99767876, 0x99767876, 0x99767876, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737373, 0x99737373, 0x99737373, 0x99737073, + 0x99706d6e, 0x99706d6e, 0x996e6968, 0x996e6968, 0x99636563, 0x99606060, 0x99606060, 0x995d5a5d, + 0x99525152, 0x99525152, 0x99454345, 0x99373637, 0x77050805, 0x77000000, 0x55000000, 0x00000000, + 0x00000000, 0x00000000, 0x33373637, 0xffa5a2a5, 0xffa5a2a5, 0xffadaaad, 0xffb5b2b5, 0xffbdbabd, + 0xffc0bec0, 0xffc3c2c3, 0xffc3c2c3, 0xffc5c6c5, 0xffc5c6c5, 0xffc8c9c8, 0xffcbcccb, 0xffcbcccb, + 0xffcecece, 0xffcecece, 0xffd0ced0, 0xffd3ced3, 0xffd3d2d3, 0xffd3d2d3, 0xffd3d2d3, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d8d6, 0xffd6d9d6, 0xffd6d9d6, 0xffd6d9d6, 0xffd6d9d6, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedcde, 0xffdeddde, 0xffdeddde, 0xffdedfde, 0xffdedfde, + 0xffdee0e1, 0xffdedfde, 0xffdee0e1, 0xffdee0e1, 0xffe1e1e1, 0xffe4e4e4, 0xffe4e4e4, 0xffe4e4e4, + 0xffe6e3e6, 0xffe6e3e6, 0xffe6e4e6, 0xffe6e4e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e5e6, + 0xffe6e5e6, 0xffe6e8e6, 0xffe6e5e6, 0xffe6e8e6, 0xffe5e8e5, 0xffe4e7e4, 0xffe3e7e4, 0xffe4e5e4, + 0xffe5e6e5, 0xffe5e6e5, 0xffe5e7e5, 0xffe5e8e6, 0xffe6e7e5, 0xffe6e7e6, 0xffe6e6e6, 0xffe6e7e6, + 0xffe6e7e6, 0xffe6e4e6, 0xffe6e4e6, 0xffe6e3e6, 0xffe6e4e5, 0xffe6e3e5, 0xffe6e1e5, 0xffe4e2e3, + 0xffe1e1e1, 0xffdfdfde, 0xffdedfde, 0xffdeddde, 0xffdeddde, 0xffdeddde, 0xffdedbde, 0xffdbdcdb, + 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, 0xffd6d8d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d4d6, + 0xffd6d4d6, 0xffd6d4d6, 0xffd6d1d6, 0xffceced0, 0xffceced0, 0xffceced0, 0xffcecacb, 0xffc5c6c5, + 0xffc3c2c3, 0xffc3c2c3, 0xffbdbabd, 0xffb5b2b5, 0xffadabad, 0xffa5a5a5, 0xff9c9e9c, 0xee8c8e8c, + 0x332f322f, 0x00000300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x44000000, 0x99424142, 0x99424142, 0x99424542, 0x994a4c4a, 0x99525252, 0x995a595a, + 0x995d5d5d, 0x995d5d5d, 0x99606160, 0x99606160, 0x99636563, 0x99656765, 0x99686868, 0x996b696b, + 0x996b6b6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996e7073, 0x996e7073, 0x996e7073, 0x99707373, + 0x99737473, 0x99737573, 0x99737573, 0x99737573, 0x99767776, 0x99767776, 0x99797879, 0x99797879, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b7c7b, 0x997b7c7b, 0x997b7c7b, 0x997b7d7b, + 0x997e7f7e, 0x997e7f7e, 0x997e7f7e, 0x997e7f7e, 0x997e807e, 0x99818381, 0x99818381, 0x99818381, + 0x99818384, 0x99818384, 0x99818384, 0x99818384, 0x99848384, 0x99848684, 0x99848684, 0x99848484, + 0x99868686, 0x99868686, 0x99868686, 0x99868686, 0x99848684, 0x99848684, 0x99848684, 0x99848684, + 0x99868784, 0x99868784, 0x99868784, 0x99868784, 0x99848684, 0x99848684, 0x99848684, 0x99848684, + 0x99898789, 0x99898789, 0x99898789, 0x99898789, 0x998c8a8c, 0x99898789, 0x99898789, 0x99898789, + 0x99848684, 0x99848684, 0x99848684, 0x99848484, 0x99848684, 0x99848484, 0x99848484, 0x99848384, + 0x99848484, 0x99848384, 0x99848384, 0x99848484, 0x99848284, 0x99848284, 0x99818081, 0x99848284, + 0x99818081, 0x99818081, 0x997e7f7e, 0x997e7f7e, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7c7b, + 0x997b7d7b, 0x997b7b7b, 0x997b7b7b, 0x997b797b, 0x99797b79, 0x99797b79, 0x99767876, 0x99767876, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737373, 0x99737373, 0x99737373, 0x99737073, + 0x99706d6e, 0x99706d6e, 0x996e6968, 0x996b6563, 0x99636563, 0x99606060, 0x995d5a5d, 0x995a555a, + 0x99525152, 0x99454345, 0x99454345, 0x88292829, 0x77030403, 0x77000000, 0x44000000, 0x00000000, + 0x00000000, 0x00000000, 0x11000000, 0xffa5a2a5, 0xffa5a2a5, 0xffadaaad, 0xffb5b2b5, 0xffbdbabd, + 0xffc0bec0, 0xffc3c2c3, 0xffc3c2c3, 0xffc3c2c3, 0xffc5c6c5, 0xffc8c9c8, 0xffc8c9c8, 0xffcbcccb, + 0xffcecece, 0xffcecece, 0xffd0ced0, 0xffd3ced3, 0xffd3d2d3, 0xffd3d2d3, 0xffd3d2d3, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d8d6, 0xffd6d9d6, 0xffd6d9d6, 0xffd6d9d6, 0xffd6dbd6, 0xffd6dbd6, + 0xffdedbde, 0xffdedcde, 0xffdeddde, 0xffdeddde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, + 0xffdee0e1, 0xffdee0e1, 0xffdee1e4, 0xffdee1e4, 0xffe4e4e4, 0xffe4e4e4, 0xffe4e4e4, 0xffe4e4e4, + 0xffe6e5e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e5e6, + 0xffe6e5e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe8e9e7, 0xffebeae9, 0xffeeeaed, + 0xffe9e7e8, 0xffe9e8ea, 0xffe6e8e8, 0xffe6e8e6, 0xffe6e9e6, 0xffe6e8e6, 0xffe7e9e7, 0xffe7e7e5, + 0xffe6e6e5, 0xffe7e7e6, 0xffe6e7e6, 0xffe6e4e6, 0xffe6e6e6, 0xffe6e3e5, 0xffe5e3e5, 0xffe5e1e4, + 0xffe1e1e1, 0xffdfe1df, 0xffdee0de, 0xffdedfde, 0xffdeddde, 0xffdeddde, 0xffdedcde, 0xffdbdcdb, + 0xffdbdcdb, 0xffdbdcdb, 0xffd9d9d9, 0xffd6d9d6, 0xffd6d8d6, 0xffd6d9d6, 0xffd6d7d6, 0xffd6d4d6, + 0xffd6d4d6, 0xffd6d4d6, 0xffd6d4d6, 0xffceced0, 0xffceced0, 0xffceced0, 0xffcecacb, 0xffc5c6c5, + 0xffc3c2c3, 0xffc0bec0, 0xffbdbabd, 0xffb5b2b5, 0xffadabad, 0xffa5a5a5, 0xff9c9e9c, 0xdd8c8e8c, + 0x22000400, 0x00000300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x44000000, 0x882c2b2c, 0x99424142, 0x99424542, 0x99424542, 0x994a4c4a, 0x995a595a, + 0x995a595a, 0x995d5d5d, 0x995d5d5d, 0x99606160, 0x99636563, 0x99656765, 0x996b696b, 0x996b696b, + 0x996b6b6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996e7073, 0x996e7073, 0x99707373, 0x99707373, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99767776, 0x99767776, 0x997b797b, 0x997b797b, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x997e7f7e, 0x997e7f7e, 0x99818081, 0x99848284, 0x99818381, 0x99818381, 0x99818381, 0x99818381, + 0x99818384, 0x99818384, 0x99818384, 0x99818384, 0x99848684, 0x99848684, 0x99848684, 0x99848684, + 0x99868686, 0x99868686, 0x99868686, 0x99868686, 0x99848684, 0x99848684, 0x99848684, 0x99848684, + 0x99848a84, 0x99868784, 0x99868784, 0x99848a84, 0x99848684, 0x99848684, 0x99848684, 0x99848684, + 0x998c8a8c, 0x99898789, 0x99898789, 0x998c8a8c, 0x998c8a8c, 0x99898789, 0x99898789, 0x99898789, + 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99848684, + 0x99848684, 0x99848684, 0x99848484, 0x99848484, 0x99848284, 0x99848284, 0x99848284, 0x99848284, + 0x997e7f7e, 0x99818081, 0x997e7f7e, 0x997e7f7e, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x997b7d7b, 0x997b7d7b, 0x997b7c7b, 0x997b7b7b, 0x99797b79, 0x99797b79, 0x99797b79, 0x99767876, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737373, 0x99737373, 0x99737073, + 0x99706d6e, 0x996e6968, 0x996e6968, 0x996b6563, 0x99606060, 0x99606060, 0x995d5a5d, 0x995a555a, + 0x99525152, 0x99454345, 0x99454345, 0x88292829, 0x77030403, 0x77000000, 0x33000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xdda5a2a5, 0xffa5a2a5, 0xffadaaad, 0xffb5b2b5, 0xffbdbabd, + 0xffbdbabd, 0xffc0bec0, 0xffc3c2c3, 0xffc3c2c3, 0xffc5c6c5, 0xffc8c9c8, 0xffcbcccb, 0xffcbcccb, + 0xffcecece, 0xffd0ced0, 0xffd0ced0, 0xffd0ced0, 0xffd3d2d3, 0xffd3d2d3, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d9d6, 0xffd6d9d6, 0xffd6dbd6, 0xffd6dbd6, + 0xffdedcde, 0xffdeddde, 0xffdeddde, 0xffdeddde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, + 0xffdee0e1, 0xffdee1e4, 0xffdee3e6, 0xffdee3e6, 0xffe4e4e4, 0xffe4e4e4, 0xffe4e4e4, 0xffe6e7e6, + 0xffe6e5e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe7e9e7, 0xffe8e8e8, + 0xffeaece9, 0xffe7e9e6, 0xffe6e9e6, 0xffe6ebe6, 0xffe6e9e6, 0xffe7e9e7, 0xffe9e9e9, 0xffe7e7e6, + 0xffe6e6e6, 0xffe6e7e7, 0xffe7e4e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e4e5, 0xffe5e3e5, 0xffe4e1e4, + 0xffe2e1e2, 0xffdfe0df, 0xffdee0de, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdeddde, 0xffdedfde, + 0xffdbdcdb, 0xffdbdcdb, 0xffdbdcdb, 0xffd6d9d6, 0xffd6d9d6, 0xffd6d9d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d4d6, 0xffd6d1d6, 0xffceced0, 0xffceced0, 0xffcecacb, 0xffcec6c5, 0xffc3c2c3, + 0xffc3c2c3, 0xffc0bec0, 0xffbdbabd, 0xffb5b2b5, 0xffadabad, 0xff9c9e9c, 0xff9c9e9c, 0xbb5d605d, + 0x22000400, 0x00000300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x22000000, 0x77262826, 0x993a3d3a, 0x99424142, 0x99424142, 0x994d4c4d, 0x99525152, + 0x99525452, 0x995a5a5a, 0x99636163, 0x99636163, 0x99656565, 0x99656565, 0x996b696b, 0x996b696b, + 0x996b6c6e, 0x996b6c6e, 0x996b6f70, 0x996b6f70, 0x99737173, 0x99737173, 0x99737173, 0x99737473, + 0x99737576, 0x99737576, 0x99737576, 0x99737576, 0x99767876, 0x99797b79, 0x99797b79, 0x99797b79, + 0x997e7c7e, 0x997e7c7e, 0x997e7c7e, 0x997e7c7e, 0x997b7d7b, 0x997b7d7b, 0x997e807e, 0x997e807e, + 0x99848084, 0x99848084, 0x99848384, 0x99848384, 0x99868486, 0x99868486, 0x99868486, 0x99868486, + 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99868786, 0x99868786, 0x99868786, 0x99848684, + 0x99868886, 0x99868886, 0x99868886, 0x99868886, 0x99868886, 0x99868886, 0x99868886, 0x99868886, + 0x998c888c, 0x998c888c, 0x998c888c, 0x998c888c, 0x99898a89, 0x99868686, 0x99898a89, 0x99898a89, + 0x998c888c, 0x998c888c, 0x998c888c, 0x998c8b8c, 0x99898b89, 0x99868886, 0x99868886, 0x99868886, + 0x99868786, 0x99868786, 0x99868786, 0x99868786, 0x99868786, 0x99848684, 0x99848684, 0x99868786, + 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99848284, 0x99868686, 0x99848284, 0x99848284, + 0x99848384, 0x99848384, 0x99848284, 0x99848284, 0x997e807e, 0x997e807e, 0x997e807e, 0x997b7d7b, + 0x997e7f7e, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7b7b, 0x997b7b7b, 0x997b797b, 0x997b797b, + 0x99767776, 0x99767776, 0x99767776, 0x99767776, 0x99737573, 0x99707370, 0x99707370, 0x996e706e, + 0x996b6d6b, 0x99686968, 0x99656565, 0x99656565, 0x99636163, 0x99636163, 0x995d5c5d, 0x99585658, + 0x994a494a, 0x994a494a, 0x994a494a, 0x77191b19, 0x77000000, 0x77000000, 0x22000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xaa736d73, 0xff9fa29f, 0xff9fa29f, 0xffb5b6b5, 0xffb5b6b5, + 0xffbdbabd, 0xffbdbabd, 0xffc5c2c5, 0xffc5c2c5, 0xffc8c6c8, 0xffc8c6c8, 0xffcecace, 0xffcecace, + 0xffd0cdd0, 0xffd0cdd0, 0xffd3d0d3, 0xffd3d0d3, 0xffd6d2d6, 0xffd6d4d6, 0xffd6d4d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d8d6, 0xffd6d8d6, 0xffd6d9d6, 0xffdedbde, 0xffdedcde, 0xffdedcde, 0xffdedcde, + 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffe1e1e1, 0xffe1e1e1, 0xffe1e1e1, + 0xffe6e3e6, 0xffe6e3e6, 0xffe6e4e6, 0xffe6e4e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, + 0xffe6e7e6, 0xffe6e8e9, 0xffe6e8e9, 0xffe6e7e6, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe6e7e6, + 0xffefebe6, 0xffefebe6, 0xffefebe6, 0xffefebe6, 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, + 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, 0xffedeaed, 0xffede9ed, + 0xffeae8e9, 0xffe5e7e9, 0xffe8e7e9, 0xffe7e7e6, 0xffe6e6e6, 0xffe6e6e5, 0xffe5e6e5, 0xffe3e4e3, + 0xffe3e3e3, 0xffe1e1e1, 0xffe1e1e1, 0xffe1e0e1, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedddb, + 0xffdedddb, 0xffdedcd9, 0xffdedcd9, 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, 0xffd6d7d6, + 0xffd6d7d6, 0xffd3d4d3, 0xffd0d1d0, 0xffcecece, 0xffcecece, 0xffc8cacb, 0xffc3c6c8, 0xffc5c2c5, + 0xffc5c2c5, 0xffbdbcbd, 0xffb5b5b5, 0xffadaead, 0xffadaead, 0xffadaead, 0xff8f908f, 0x774a4d4a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0x66131413, 0x993a3d3a, 0x99424142, 0x99424142, 0x99474647, 0x994d4c4d, + 0x99525452, 0x995a5a5a, 0x995a5a5a, 0x99636163, 0x99656565, 0x99656565, 0x99656565, 0x996b696b, + 0x996b6c6e, 0x996b6c6e, 0x996b6f70, 0x996b6f70, 0x99737173, 0x99737173, 0x99737173, 0x99737373, + 0x99737573, 0x99737576, 0x99737576, 0x99737576, 0x99767876, 0x99767876, 0x99767876, 0x99797b79, + 0x997e7c7e, 0x997e7c7e, 0x99817f81, 0x99817f81, 0x997b7d7b, 0x997e807e, 0x997e807e, 0x997e807e, + 0x99848384, 0x99848384, 0x99848384, 0x99848384, 0x99868486, 0x99868486, 0x99868486, 0x99868486, + 0x99868786, 0x99868786, 0x99868786, 0x99868786, 0x99868786, 0x99898889, 0x99868786, 0x99868786, + 0x99868886, 0x99868886, 0x99898b89, 0x99898b89, 0x99868886, 0x99898b89, 0x99898b89, 0x99898b89, + 0x998c8b8c, 0x998c8b8c, 0x998c8b8c, 0x998c8b8c, 0x99898a89, 0x99898a89, 0x99898a89, 0x99898a89, + 0x998c8b8c, 0x998c8b8c, 0x998c8b8c, 0x998c8b8c, 0x99868886, 0x99898b89, 0x99868886, 0x99868886, + 0x99898889, 0x99898889, 0x99898889, 0x99868786, 0x99868786, 0x99868786, 0x99848684, 0x99868786, + 0x99848684, 0x99868786, 0x99898889, 0x99848684, 0x99868686, 0x99848284, 0x99868686, 0x99868686, + 0x99848384, 0x99848484, 0x99848284, 0x99848384, 0x99818381, 0x997e807e, 0x997e807e, 0x997e807e, + 0x997e7f7e, 0x997e7f7e, 0x997e7f7e, 0x997b7d7b, 0x997b7d7b, 0x997b7c7b, 0x997b7b7b, 0x997b7b7b, + 0x997b797b, 0x99797879, 0x99767776, 0x99767776, 0x99737573, 0x99707370, 0x99707370, 0x996b6d6b, + 0x99686968, 0x99686968, 0x99656565, 0x99636163, 0x99636163, 0x995d5c5d, 0x99585658, 0x99585658, + 0x994a494a, 0x994a494a, 0x99313231, 0x77000400, 0x77000000, 0x66000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x554d494d, 0xff9fa29f, 0xff9fa29f, 0xff9fa29f, 0xffb5b6b5, + 0xffb5b2b5, 0xffbdbabd, 0xffbdbabd, 0xffc5c2c5, 0xffc8c6c8, 0xffc8c6c8, 0xffc8c6c8, 0xffcecace, + 0xffd0cdd0, 0xffd0cdd0, 0xffd3d0d3, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d4d6, 0xffd6d5d6, + 0xffd6d7d6, 0xffd6d9d6, 0xffd6d9d6, 0xffd6d9d6, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedcde, + 0xffdedfde, 0xffdedfde, 0xffdee0de, 0xffdee0de, 0xffe1e1e1, 0xffe1e1e1, 0xffe1e1e1, 0xffe1e1e1, + 0xffe6e5e6, 0xffe6e4e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, + 0xffe6e9ec, 0xffe6e8e9, 0xffe6e9ec, 0xffe6e9ec, 0xffe9e9e9, 0xffececec, 0xffe9e9e9, 0xffe9e9e9, + 0xffefece9, 0xffefebe6, 0xffefece9, 0xffefece9, 0xffefebef, 0xffefecef, 0xffefecef, 0xffefecef, + 0xffefecef, 0xffefecef, 0xffefecef, 0xffefecef, 0xffefebef, 0xffeeecef, 0xffeeeced, 0xffede9ed, + 0xffede9ed, 0xffede7ec, 0xffece7ec, 0xffeae7ea, 0xffe7e7e7, 0xffe6e6e6, 0xffe5e6e5, 0xffe3e5e3, + 0xffe3e4e3, 0xffe4e4e4, 0xffe1e1e1, 0xffe1e0e1, 0xffe1e0e1, 0xffe1e0e1, 0xffdedfde, 0xffdedfde, + 0xffdedfde, 0xffdedddb, 0xffdedddb, 0xffdbdcdb, 0xffdbdcdb, 0xffd9d9d9, 0xffd9d9d9, 0xffd6d7d6, + 0xffd3d4d3, 0xffd3d4d3, 0xffd0d1d0, 0xffcecece, 0xffcecece, 0xffc8cacb, 0xffc3c6c8, 0xffc5c2c5, + 0xffbdbcbd, 0xffbdbcbd, 0xffb5b5b5, 0xffadaead, 0xffadaead, 0xffadaead, 0xff8f908f, 0x44313331, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x55000000, 0x993a3d3a, 0x99424142, 0x99424142, 0x99424142, 0x994d4c4d, + 0x99525452, 0x995a5a5a, 0x995a5a5a, 0x995a5a5a, 0x99606160, 0x99606160, 0x99656565, 0x996b696b, + 0x996b696b, 0x996b6c6e, 0x996b6f70, 0x996b6f70, 0x99737173, 0x99737173, 0x99737373, 0x99737373, + 0x99737573, 0x99737576, 0x99737576, 0x99737579, 0x99767876, 0x99767876, 0x99797b79, 0x997b7d7b, + 0x99817f81, 0x997e7c7e, 0x997e7c7e, 0x99817f81, 0x997e807e, 0x997e807e, 0x99818381, 0x99818381, + 0x99848384, 0x99848384, 0x99848384, 0x99848384, 0x99868486, 0x99898789, 0x99868486, 0x99898789, + 0x99868786, 0x99868786, 0x99868786, 0x99868786, 0x99898889, 0x99898889, 0x998c8a8c, 0x99898889, + 0x99898b89, 0x99898b89, 0x99898b89, 0x99898b89, 0x99898b89, 0x99898b89, 0x99898b89, 0x99898b89, + 0x998c8b8c, 0x998c8b8c, 0x998c8b8c, 0x998c8e8c, 0x998c8e8c, 0x99898a89, 0x998c8e8c, 0x99898a89, + 0x998c8b8c, 0x998c8b8c, 0x998c8b8c, 0x998c8b8c, 0x99898b89, 0x99898b89, 0x99898b89, 0x99868886, + 0x998c8a8c, 0x998c8a8c, 0x99898889, 0x99868786, 0x998c8a8c, 0x99898889, 0x99868786, 0x99868786, + 0x99868786, 0x99898889, 0x998c8a8c, 0x99868786, 0x99868686, 0x99868686, 0x99868686, 0x99868686, + 0x99848484, 0x99848484, 0x99848484, 0x99848384, 0x99818381, 0x997e807e, 0x997e807e, 0x997e807e, + 0x997e7f7e, 0x997e7f7e, 0x997e7f7e, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7b7b, 0x997b797b, + 0x997b797b, 0x997b797b, 0x99767776, 0x99767776, 0x99737573, 0x99707370, 0x996e706e, 0x996b6d6b, + 0x99686968, 0x99686968, 0x99656565, 0x99636163, 0x99636163, 0x995d5c5d, 0x99585658, 0x99525152, + 0x994a494a, 0x994a494a, 0x88313231, 0x77000400, 0x77000000, 0x55000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x22262426, 0xee9fa29f, 0xff9fa29f, 0xff9fa29f, 0xff9fa29f, + 0xffb5b2b5, 0xffbdbabd, 0xffbdbabd, 0xffbdbabd, 0xffc3c2c3, 0xffc3c2c3, 0xffc8c6c8, 0xffcecace, + 0xffcecace, 0xffd0cdd0, 0xffd3d0d3, 0xffd3d0d3, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d5d6, 0xffd6d5d6, + 0xffd6d8d6, 0xffd6d7d6, 0xffd6d9d6, 0xffd6d9d6, 0xffdedbde, 0xffdedbde, 0xffdedcde, 0xffdedfde, + 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdee0de, 0xffe1e1e1, 0xffe4e4e4, 0xffe4e4e4, 0xffe4e4e4, + 0xffe6e4e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e7e6, 0xffe9e8e9, 0xffe6e7e6, 0xffe9e8e9, + 0xffe6e9ec, 0xffe6e9ec, 0xffe6e9ec, 0xffe6e9ec, 0xffececec, 0xffececec, 0xffececec, 0xffececec, + 0xffefedec, 0xffefece9, 0xffefece9, 0xffefece9, 0xffefecef, 0xffefecef, 0xffefedef, 0xffefecef, + 0xffefedef, 0xffefedef, 0xffefedef, 0xffefefef, 0xffefedef, 0xffefedef, 0xffeeecee, 0xffeee9ee, + 0xffede9ed, 0xffedeaec, 0xffeceaec, 0xffe9eae9, 0xffe8e7e8, 0xffe7e7e7, 0xffe7e5e7, 0xffe4e4e4, + 0xffe4e4e4, 0xffe4e4e4, 0xffe4e4e4, 0xffe4e1e4, 0xffe4e1e4, 0xffe1e0e1, 0xffe1e0e1, 0xffdedfde, + 0xffdedfde, 0xffdedddb, 0xffdedcd9, 0xffdbdcdb, 0xffdbdcdb, 0xffd9d9d9, 0xffd9d9d9, 0xffd6d7d6, + 0xffd3d4d3, 0xffd0d1d0, 0xffd0d1d0, 0xffcecece, 0xffc8cacb, 0xffc3c6c8, 0xffbdc2c5, 0xffc5c2c5, + 0xffbdbcbd, 0xffb5b5b5, 0xffb5b5b5, 0xffadaead, 0xffadaead, 0xff8f908f, 0xbb707370, 0x11191a19, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x33000000, 0x77131413, 0x99424142, 0x99424142, 0x99424142, 0x99424142, + 0x994a4d4a, 0x99525452, 0x99525452, 0x995a5a5a, 0x995a5d5a, 0x99606160, 0x99656565, 0x99656565, + 0x996b696b, 0x996b6c6e, 0x996b6c6e, 0x996b6f70, 0x99737173, 0x99737173, 0x99737373, 0x99737573, + 0x99737576, 0x99737576, 0x99737576, 0x99737579, 0x99767876, 0x99797b79, 0x997b7d7b, 0x997b7d7b, + 0x99817f81, 0x997e7c7e, 0x99817f81, 0x99848284, 0x997e807e, 0x99818381, 0x99818381, 0x99818381, + 0x99848384, 0x99848684, 0x99848684, 0x99848684, 0x99898789, 0x99898789, 0x99898789, 0x998c8a8c, + 0x99898889, 0x99868786, 0x99898889, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, + 0x99898b89, 0x99898b89, 0x99898b89, 0x998c8e8c, 0x99898b89, 0x998c8e8c, 0x99898b89, 0x998c8e8c, + 0x998c8b8c, 0x998c8e8c, 0x998c8b8c, 0x998c8b8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, + 0x998c8b8c, 0x998c8b8c, 0x998c8b8c, 0x998c8b8c, 0x99898b89, 0x998c8e8c, 0x99898b89, 0x99898b89, + 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x99898889, 0x99898889, + 0x99898889, 0x99868786, 0x99868786, 0x99868786, 0x99898a89, 0x99868686, 0x99868686, 0x99868686, + 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99818381, 0x99818381, 0x99818381, 0x997e807e, + 0x99848284, 0x997e7f7e, 0x99818081, 0x997e7f7e, 0x997b7d7b, 0x997b7d7b, 0x997b7c7b, 0x997b7c7b, + 0x997b797b, 0x99797879, 0x99767776, 0x99767776, 0x99737573, 0x996e706e, 0x996b6d6b, 0x996b6d6b, + 0x99686968, 0x99656565, 0x99636163, 0x99636163, 0x995d5c5d, 0x99585658, 0x99585658, 0x99525152, + 0x994a494a, 0x994a494a, 0x77191b19, 0x77000400, 0x77000000, 0x33000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x99737973, 0xff9fa29f, 0xff9fa29f, 0xff9fa29f, + 0xffadaaad, 0xffb5b2b5, 0xffbdbabd, 0xffbdbabd, 0xffbdbebd, 0xffc3c2c3, 0xffc8c6c8, 0xffc8c6c8, + 0xffcecace, 0xffd0cdd0, 0xffd0cdd0, 0xffd3d0d3, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d5d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d8d6, 0xffd6d9d6, 0xffd6d9d6, 0xffdedbde, 0xffdeddde, 0xffdedfde, 0xffdedfde, + 0xffdee1de, 0xffdedfde, 0xffdee0de, 0xffdee3de, 0xffe4e4e4, 0xffe4e4e4, 0xffe4e4e4, 0xffe6e7e6, + 0xffe6e5e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe9e8e9, 0xffe9e8e9, 0xffe9e8e9, 0xffefebef, + 0xffe6ebef, 0xffe6e9ec, 0xffe6ebef, 0xffe6ebef, 0xffececec, 0xffececec, 0xffececec, 0xffececec, + 0xffefedec, 0xffefedec, 0xffefefef, 0xffefefef, 0xffefedef, 0xffefefef, 0xffefedef, 0xffefefef, + 0xffefedef, 0xffefefef, 0xffefedef, 0xffefedef, 0xffefedef, 0xffefedef, 0xffeeedef, 0xffeeeded, + 0xffeeebed, 0xffece9eb, 0xffeaeaea, 0xffe8e9e8, 0xffe8e9e8, 0xffe8e9e8, 0xffe6e7e7, 0xffe6e7e6, + 0xffe6e7e6, 0xffe4e4e4, 0xffe4e4e4, 0xffe6e3e6, 0xffe4e1e4, 0xffe6e3e6, 0xffe1e0e1, 0xffdedfde, + 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdbdcdb, 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, 0xffd6d7d6, + 0xffd3d4d3, 0xffd0d1d0, 0xffcecece, 0xffc8cacb, 0xffc3c6c8, 0xffc3c6c8, 0xffbdc2c5, 0xffbdbcbd, + 0xffbdbcbd, 0xffb5b5b5, 0xffadaead, 0xffadaead, 0xffadaead, 0xff8f908f, 0x66525552, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x11000000, 0x55080408, 0x882c2b2c, 0x99424142, 0x99424142, 0x99424142, + 0x99424142, 0x994d4e4d, 0x99525552, 0x99525552, 0x995a5a5d, 0x99636163, 0x99636163, 0x99636163, + 0x9968686e, 0x9968686e, 0x996b6d73, 0x996b6d73, 0x99736d6b, 0x9973706e, 0x99737370, 0x99737573, + 0x99737573, 0x99767776, 0x99767776, 0x997b797b, 0x997b797b, 0x997b797b, 0x997e7c7e, 0x997e7c7e, + 0x997b7d7b, 0x997b7d7b, 0x997e807e, 0x99818381, 0x99848284, 0x99848284, 0x99848284, 0x99848284, + 0x99848684, 0x99848684, 0x99848684, 0x99868786, 0x998c8886, 0x998c8886, 0x998c8886, 0x998c8b89, + 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998f8c8f, 0x998f8c8f, 0x998c8a8c, 0x998c8a8c, + 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, + 0x998f908f, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, + 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, + 0x998f8c8f, 0x998c8a8c, 0x998f8c8f, 0x998c8a8c, 0x998c8e8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, + 0x9986888c, 0x9986888c, 0x9986888c, 0x9986888c, 0x998c8886, 0x998c8886, 0x998c8886, 0x998c8886, + 0x99868786, 0x99868786, 0x99848684, 0x99848684, 0x99848684, 0x99848484, 0x99848484, 0x99848384, + 0x99818381, 0x997e807e, 0x997e807e, 0x997e807e, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x99797b79, + 0x9973797b, 0x9973797b, 0x99737779, 0x99737476, 0x99737173, 0x99737173, 0x996e6d6e, 0x99686968, + 0x9963656b, 0x9963656b, 0x99606065, 0x99606065, 0x995a5d5a, 0x995a5d5a, 0x994a4c4a, 0x994a4c4a, + 0x994a494a, 0x88343234, 0x77080408, 0x77080408, 0x66000000, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22000400, 0xdda5a2a5, 0xffa5a2a5, 0xffa5a2a5, + 0xffaaa9aa, 0xffafafaf, 0xffb5b6b5, 0xffb5b6b5, 0xffbdbcbd, 0xffc5c2c5, 0xffc5c2c5, 0xffc5c2c5, + 0xffc8cacb, 0xffcbced0, 0xffcbced0, 0xffcbced0, 0xffd6d1d0, 0xffd6d4d3, 0xffd6d4d3, 0xffd6d7d6, + 0xffd6d7d6, 0xffd9d9d9, 0xffd9d9d9, 0xffdbdcdb, 0xffdeddde, 0xffdeddde, 0xffdeddde, 0xffdeddde, + 0xffdedfde, 0xffe1e1e1, 0xffe1e1e1, 0xffe4e4e4, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e5e6, 0xffe6e5e6, + 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe9e9e9, 0xffefebe6, 0xffefebe6, 0xffefebe6, 0xffefece9, + 0xffefebef, 0xffefebef, 0xffefebef, 0xffefedf1, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xfff1f2f1, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xfff0efef, 0xfff3f2f2, 0xfff1efef, + 0xfff1eeef, 0xffeeebec, 0xffeeebee, 0xffebe9ea, 0xffe9e9e9, 0xffe6e7e7, 0xffe6e7e6, 0xffe6e8e6, + 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe4e4e4, 0xffe4e4e4, 0xffe1e1e1, 0xffe1e1e1, 0xffdedfde, + 0xffdedfde, 0xffdedfde, 0xffdbdddb, 0xffd6dbde, 0xffd6dbde, 0xffd6d8db, 0xffd6d5d9, 0xffd6d7de, + 0xffd0d1d6, 0xffd0d1d6, 0xffcbccce, 0xffc5c6c5, 0xffc5c6c5, 0xffc0c2c0, 0xffc0c2c0, 0xffbdbebd, + 0xffb5b5b5, 0xffb5b5b5, 0xffadabad, 0xffa5a6a5, 0xffa5a6a5, 0xcc707170, 0x11080808, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x33000000, 0x66161616, 0x99424142, 0x99424142, 0x99424142, + 0x99424142, 0x99474847, 0x994d4e4d, 0x99525552, 0x995a5a5d, 0x995a5a5d, 0x99636163, 0x99636163, + 0x9968686e, 0x9968686e, 0x9968686e, 0x996b6d73, 0x99736d6b, 0x99737370, 0x99737573, 0x99737573, + 0x99767776, 0x99767776, 0x99767776, 0x997b797b, 0x997e7c7e, 0x99817f81, 0x997e7c7e, 0x99817f81, + 0x997e807e, 0x997e807e, 0x997e807e, 0x997e807e, 0x99848284, 0x99848686, 0x99848686, 0x99848686, + 0x99848684, 0x99868786, 0x99868786, 0x99868786, 0x998c8886, 0x998c8886, 0x998c8b89, 0x998c8b89, + 0x998c8c8f, 0x998c8c8f, 0x998c8a8c, 0x998c8c8f, 0x998f8c8f, 0x99918f91, 0x998f8c8f, 0x99918f91, + 0x998f8f8f, 0x998f8f8f, 0x998f8f8f, 0x998f8f8f, 0x998f908f, 0x998f908f, 0x998f908f, 0x998f908f, + 0x998f908f, 0x998f908f, 0x998f908f, 0x998f908f, 0x998f908f, 0x998f908f, 0x998f908f, 0x998f908f, + 0x998f908f, 0x998f908f, 0x998c8e8c, 0x998f908f, 0x998c8e8c, 0x998f908f, 0x998f908f, 0x998c8e8c, + 0x99918f91, 0x998f8c8f, 0x998f8c8f, 0x998f8c8f, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8a8c, + 0x99898b8c, 0x99898b8c, 0x99898b8c, 0x99898b8c, 0x998c8b89, 0x998c8886, 0x998c8b89, 0x998c8886, + 0x99898889, 0x99868786, 0x99868786, 0x99868786, 0x99848684, 0x99848684, 0x99848684, 0x99848684, + 0x99818381, 0x99818381, 0x99818381, 0x997e807e, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x99797b79, + 0x9973797b, 0x99737779, 0x99737779, 0x99737476, 0x99737173, 0x996e6d6e, 0x99686968, 0x99686968, + 0x9963656b, 0x9963656b, 0x99606065, 0x995d5a60, 0x995a5d5a, 0x995a5d5a, 0x994a4c4a, 0x994a4c4a, + 0x99343234, 0x771e1b1e, 0x77080408, 0x77080408, 0x33000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0x55373937, 0xeea5a2a5, 0xffa5a2a5, + 0xffa5a2a5, 0xffaaa9aa, 0xffafafaf, 0xffb5b6b5, 0xffbdbcbd, 0xffbdbcbd, 0xffc5c2c5, 0xffc5c2c5, + 0xffc8cacb, 0xffc8cacb, 0xffc8cacb, 0xffced2d6, 0xffd6d1d0, 0xffd6d4d3, 0xffd6d7d6, 0xffd6d7d6, + 0xffd9d9d9, 0xffd9d9d9, 0xffd9d9d9, 0xffdbdcdb, 0xffdeddde, 0xffdee0de, 0xffdeddde, 0xffdee0de, + 0xffe1e1e1, 0xffe1e1e1, 0xffe4e4e4, 0xffe4e4e4, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e7e6, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffefebe6, 0xffefebe6, 0xffefece9, 0xffefece9, + 0xffefedf1, 0xffefedf1, 0xffefedf1, 0xffefedf1, 0xffefefef, 0xfff1f0f1, 0xffefefef, 0xfff1f0f1, + 0xfff1f2f1, 0xfff1f2f1, 0xfff1f2f1, 0xfff1f2f1, 0xfff1f2f1, 0xfff1f2f1, 0xfff1f2f1, 0xfff1f2f1, + 0xfff4f4f4, 0xfff1f2f1, 0xfff1f2f1, 0xfff1f2f1, 0xfff4f4f4, 0xfff1f2f1, 0xfff2f2f1, 0xfff1f0f0, + 0xfff1efef, 0xffefeded, 0xffede9ed, 0xffece9ec, 0xffeae9ea, 0xffe9e9e9, 0xffe9e9e9, 0xffe6e7e6, + 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe4e4e4, 0xffe4e4e4, 0xffe4e4e4, 0xffe4e4e4, 0xffdedfde, + 0xffdedfde, 0xffdedfde, 0xffdbdddb, 0xffd6dbde, 0xffd6d8db, 0xffd6d8db, 0xffd6d5d9, 0xffd0d1d6, + 0xffd0d1d6, 0xffcbccce, 0xffcbccce, 0xffc5c6c5, 0xffc5c6c5, 0xffc0c2c0, 0xffbabeba, 0xffbdbebd, + 0xffb5b5b5, 0xffb5b5b5, 0xffadabad, 0xffa5a6a5, 0xdda5a6a5, 0x443c3d3c, 0x00080808, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x55000000, 0x77161616, 0x99424142, 0x99424142, + 0x99424142, 0x99424142, 0x99474847, 0x994d4e4d, 0x99525458, 0x995a5a5d, 0x99636163, 0x99636163, + 0x99656268, 0x9968686e, 0x9968686e, 0x996b6d73, 0x9973706e, 0x99737370, 0x99737573, 0x99737573, + 0x99767776, 0x99767776, 0x997b797b, 0x997b797b, 0x99817f81, 0x99817f81, 0x99817f81, 0x99817f81, + 0x997e807e, 0x997e807e, 0x99818381, 0x99818381, 0x99848686, 0x99848686, 0x99848686, 0x99848686, + 0x99868786, 0x99868786, 0x998c8a8c, 0x998c8a8c, 0x998c8b89, 0x998c8b89, 0x998c8b89, 0x998c8b89, + 0x998c8c8f, 0x998c8c8f, 0x998c8c8f, 0x998c8f91, 0x99918f91, 0x99918f91, 0x99949294, 0x99949294, + 0x99919091, 0x99919091, 0x998f8f8f, 0x99919091, 0x998f908f, 0x99919391, 0x998f908f, 0x99919391, + 0x998f908f, 0x998f908f, 0x99919391, 0x998f908f, 0x998f908f, 0x998f908f, 0x99919391, 0x998f908f, + 0x998f908f, 0x998f908f, 0x99919391, 0x998f908f, 0x998f908f, 0x998f908f, 0x998f908f, 0x998f908f, + 0x99918f91, 0x99918f91, 0x99918f91, 0x99918f91, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, + 0x99898b8c, 0x99898b8c, 0x99898b8c, 0x99898b8c, 0x998c8b89, 0x998c8b89, 0x998c8b89, 0x998c8886, + 0x998c8a8c, 0x99868786, 0x99868786, 0x99868786, 0x99848684, 0x99848684, 0x99848684, 0x99848484, + 0x99818381, 0x99818381, 0x99818381, 0x99818381, 0x997b7d7b, 0x997b7d7b, 0x99797b79, 0x99797b79, + 0x99737779, 0x99737779, 0x99737476, 0x99737173, 0x99737173, 0x996e6d6e, 0x99686968, 0x99636563, + 0x9963656b, 0x99606065, 0x99606065, 0x995d5a60, 0x995a5d5a, 0x994a4c4a, 0x994a4c4a, 0x994a4c4a, + 0x771e1b1e, 0x77080408, 0x77080408, 0x55080408, 0x11000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0x00000400, 0x886e6d6e, 0xffa5a2a5, + 0xffa5a2a5, 0xffa5a2a5, 0xffaaa9aa, 0xffafafaf, 0xffb5b5b5, 0xffbdbcbd, 0xffc5c2c5, 0xffc5c2c5, + 0xffc5c6c5, 0xffc8cacb, 0xffc8cacb, 0xffcbced0, 0xffd6d1d0, 0xffd6d4d3, 0xffd6d7d6, 0xffd6d7d6, + 0xffd9d9d9, 0xffd9d9d9, 0xffdbdcdb, 0xffdbdcdb, 0xffdee0de, 0xffdee0de, 0xffdee0de, 0xffdee0de, + 0xffe1e1e1, 0xffe4e4e4, 0xffe4e4e4, 0xffe4e4e4, 0xffe6e5e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe9e9e9, 0xffe9e9e9, 0xffececec, 0xffececec, 0xffefedec, 0xffefece9, 0xffefedec, 0xffefedec, + 0xffefedf1, 0xffefedf1, 0xffefedf1, 0xffeff0f4, 0xfff1f0f1, 0xfff1f0f1, 0xfff4f2f4, 0xfff4f2f4, + 0xfff1f2f1, 0xfff4f4f4, 0xfff1f2f1, 0xfff4f4f4, 0xfff4f4f4, 0xfff4f4f4, 0xfff4f4f4, 0xfff4f4f4, + 0xfff4f4f4, 0xfff4f4f4, 0xfff4f4f4, 0xfff4f4f4, 0xfff4f4f4, 0xfff4f4f4, 0xfff4f4f4, 0xfff2f1f1, + 0xfff0edee, 0xffeceae9, 0xffeae8e7, 0xffeae7ea, 0xffe8e6e8, 0xffeae9ea, 0xffe9e9e9, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe4e4e4, 0xffe4e4e4, 0xffe4e4e4, 0xffdedfde, + 0xffdedfde, 0xffdbdddb, 0xffdbdddb, 0xffd6d8db, 0xffd6d8db, 0xffd6d5d9, 0xffd6d2d6, 0xffd0d1d6, + 0xffcbccce, 0xffcbccce, 0xffc5c6c5, 0xffc5c6c5, 0xffc0c2c0, 0xffbabeba, 0xffbabeba, 0xffb5b5b5, + 0xffb5b5b5, 0xffadabad, 0xffadabad, 0xeea5a6a5, 0x773c3d3c, 0x00080808, 0x00080808, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x55000000, 0x77161616, 0x99424142, + 0x99424142, 0x99424142, 0x99424142, 0x99474847, 0x994a4d52, 0x99525458, 0x995a5a5d, 0x99636163, + 0x99656268, 0x99656268, 0x9968686e, 0x9968686e, 0x99736d6b, 0x9973706e, 0x99737370, 0x99737573, + 0x99737573, 0x99767776, 0x99797879, 0x997b797b, 0x997e7c7e, 0x997e7c7e, 0x99817f81, 0x99848284, + 0x99818381, 0x99818381, 0x99818381, 0x99848684, 0x99848686, 0x99848686, 0x99848686, 0x99848a89, + 0x99898889, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998c8b89, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, + 0x998c8f91, 0x998c8f91, 0x998c8f91, 0x998c9294, 0x99949294, 0x99949294, 0x99949294, 0x99949294, + 0x99949294, 0x99949294, 0x99949294, 0x99949294, 0x99919391, 0x99919391, 0x99919391, 0x99919391, + 0x99919391, 0x99919391, 0x99919391, 0x99919391, 0x99919391, 0x99919391, 0x99919391, 0x99919391, + 0x99919391, 0x99919391, 0x99919391, 0x99919391, 0x99919391, 0x99919391, 0x99919391, 0x998f908f, + 0x99949294, 0x99949294, 0x99949294, 0x99949294, 0x998c928c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, + 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8b89, 0x998c8b89, 0x998c8b89, 0x998c8b89, + 0x998c8a8c, 0x998c8a8c, 0x99868786, 0x99868786, 0x99848684, 0x99848684, 0x99848684, 0x99848684, + 0x99818381, 0x99818381, 0x997e807e, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x99797b79, 0x99767876, + 0x99737476, 0x99737476, 0x99737173, 0x99737173, 0x996e6d6e, 0x99686968, 0x99686968, 0x99636563, + 0x99606065, 0x99606065, 0x995d5a60, 0x995a555a, 0x994a4c4a, 0x994a4c4a, 0x994a4c4a, 0x77292829, + 0x77080408, 0x77080408, 0x66080408, 0x11080408, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0x00000400, 0x00000400, 0x996e6d6e, + 0xeea5a2a5, 0xffa5a2a5, 0xffa5a2a5, 0xffaaa9aa, 0xffadaead, 0xffb5b5b5, 0xffbdbcbd, 0xffc5c2c5, + 0xffc5c6c5, 0xffc5c6c5, 0xffc8cacb, 0xffcbced0, 0xffd6d1d0, 0xffd6d1d0, 0xffd6d4d3, 0xffd6d7d6, + 0xffd6d7d6, 0xffd9d9d9, 0xffdbdcdb, 0xffdbdcdb, 0xffdeddde, 0xffdeddde, 0xffdee0de, 0xffdee3de, + 0xffe4e4e4, 0xffe6e7e6, 0xffe4e4e4, 0xffe6e7e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6ebe6, + 0xffececec, 0xffececec, 0xffececec, 0xffececec, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffeff0f4, 0xffeff0f4, 0xffeff0f4, 0xffeff3f7, 0xfff7f3f7, 0xfff7f3f7, 0xfff7f3f7, 0xfff7f3f7, + 0xfff4f4f4, 0xfff4f4f4, 0xfff4f4f4, 0xfff4f4f4, 0xfff7f7f7, 0xfff4f4f4, 0xfff4f4f4, 0xfff7f7f7, + 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff4f4f4, 0xfff4f4f4, 0xfff4f4f4, 0xfff5f5f4, + 0xffefeeeb, 0xffebe8e8, 0xffe8e5e8, 0xffe7e4e8, 0xffe8e5e8, 0xffeae8ea, 0xffe9e9e9, 0xffe6e9e6, + 0xffe6e9e6, 0xffe6e7e6, 0xffe6e8e6, 0xffe6e7e6, 0xffe4e4e4, 0xffe4e4e4, 0xffe1e1e1, 0xffdedfde, + 0xffdedfde, 0xffdbdddb, 0xffd6dbd6, 0xffd6d8db, 0xffd6d5d9, 0xffd6d2d6, 0xffd6d2d6, 0xffcbccce, + 0xffcbccce, 0xffcbccce, 0xffc5c6c5, 0xffc0c2c0, 0xffc0c2c0, 0xffbabeba, 0xffb5bab5, 0xffb5b5b5, + 0xffb5b5b5, 0xffadabad, 0xeea5a2a5, 0x773c3d3c, 0x11080808, 0x00080808, 0x00080808, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22000000, 0x55000000, 0x77191419, + 0x882f2d2f, 0x99424142, 0x99424142, 0x99424142, 0x993c3b3c, 0x99525152, 0x99525152, 0x99525152, + 0x99636163, 0x99636163, 0x99636163, 0x99636163, 0x99636565, 0x996b7173, 0x996b7173, 0x996b7173, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, + 0x99868886, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998f8f8f, 0x998f8f8f, 0x998f8f8f, 0x998f8f8f, + 0x99949094, 0x99949094, 0x99949094, 0x999c969c, 0x99949694, 0x99949694, 0x99949694, 0x99949694, + 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, + 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, + 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x998f9091, + 0x99949294, 0x99949294, 0x99949294, 0x99949294, 0x998f8c8f, 0x99949294, 0x99949294, 0x99949294, + 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, + 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x99848684, 0x99848684, 0x99848684, 0x99848684, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7973, 0x997b7973, 0x997b7973, 0x997b7973, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x99636563, 0x99636563, 0x99636563, 0x99636563, + 0x99525552, 0x99525552, 0x99525552, 0x99525552, 0x99525152, 0x88373637, 0x771b1b1b, 0x77000000, + 0x77000305, 0x66000000, 0x22000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x77686968, 0xdd9c9e9c, 0xff9c9e9c, 0xff9c9e9c, 0xffadaaad, 0xffadaaad, 0xffadaaad, 0xffadaaad, + 0xffb8b9b8, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd9dbde, 0xffdee3e6, 0xffdee3e6, 0xffdee3e6, + 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, + 0xffe9e9e9, 0xffefefef, 0xffefefef, 0xffefefef, 0xfff1f0ef, 0xfff1f0ef, 0xfff1f0ef, 0xfff1f0ef, + 0xfff1f3f1, 0xfff1f3f1, 0xfff1f3f1, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, + 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, + 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff6f6f6, + 0xffefefef, 0xffeaeae9, 0xffe6e7e7, 0xffe5e4e5, 0xffe5e3e6, 0xffece9ed, 0xffefebef, 0xffe6e7e6, + 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffc8c9c8, 0xffc5c6c5, + 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xff9c9e9c, + 0xff9c9e9c, 0xcc9c9e9c, 0x55343534, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22000000, 0x55000000, + 0x66080408, 0x771b181b, 0x99424142, 0x99424142, 0x993c3b3c, 0x993c3b3c, 0x99525152, 0x99525152, + 0x99555555, 0x99555555, 0x99636163, 0x99636163, 0x99636565, 0x99636565, 0x996b7173, 0x996b7173, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99848384, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, + 0x998c8e8c, 0x99868886, 0x998c8e8c, 0x998c8e8c, 0x998f8f8f, 0x99949694, 0x998f8f8f, 0x998f8f8f, + 0x99949094, 0x99949094, 0x99949094, 0x99949094, 0x99949694, 0x99949694, 0x99949694, 0x99949694, + 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, + 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, + 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x998f9091, + 0x99949294, 0x99949294, 0x99949294, 0x99949294, 0x99949294, 0x99949294, 0x998f8c8f, 0x99949294, + 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x99868886, + 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x99848384, 0x99848684, 0x99848684, 0x997e7f7e, 0x997e7f7e, + 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x99767576, 0x997b7973, 0x997b7973, 0x9973706e, 0x9973706e, + 0x99737173, 0x99737173, 0x99656465, 0x99656465, 0x99636563, 0x99636563, 0x99636563, 0x99505150, + 0x99525552, 0x99525552, 0x99525552, 0x993a3b3a, 0x771b1b1b, 0x66000000, 0x77000000, 0x77000000, + 0x66000000, 0x22000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x33343534, 0x99686968, 0xee9c9e9c, 0xffadaaad, 0xffadaaad, 0xffadaaad, 0xffadaaad, + 0xffb8b9b8, 0xffb8b9b8, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c8c3, 0xffc5c8c3, 0xffced2ce, 0xffced2ce, + 0xffd0d1d0, 0xffd0d1d0, 0xffd6dbd6, 0xffd6dbd6, 0xffd9dbde, 0xffd9dbde, 0xffdee3e6, 0xffdee3e6, + 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e5e6, 0xffefebef, 0xffefebef, 0xffefebef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xfff1f0ef, 0xfff7f7f7, 0xfff1f0ef, 0xfff1f0ef, + 0xfff1f3f1, 0xfff1f3f1, 0xfff1f3f1, 0xfff1f3f1, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, + 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, + 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff6f7f6, + 0xfff2f1f1, 0xffebeaea, 0xffe4e5e5, 0xffe3e1e4, 0xffe6e4e7, 0xffedeaed, 0xffefebef, 0xffe6e7e6, + 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffced0ce, 0xffd6d7d6, 0xffc8c9c8, 0xffc8c9c8, 0xffc8c9c8, 0xffc5c6c5, + 0xffc5c6c5, 0xffc5c6c5, 0xffb8b7b8, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xdd9c9e9c, + 0x88686968, 0x33343534, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, + 0x44080408, 0x66080408, 0x66080408, 0x771b181b, 0x993c3b3c, 0x993c3b3c, 0x993c3b3c, 0x993c3b3c, + 0x99474947, 0x99555555, 0x99555555, 0x99555555, 0x995a5958, 0x99636565, 0x99636565, 0x99636565, + 0x99686868, 0x996e6f6e, 0x996e6f6e, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x997e7f7e, 0x997e7f7e, 0x997e7f7e, 0x997e7f7e, 0x99848384, 0x99848384, 0x99848384, 0x99848384, + 0x99868886, 0x99868886, 0x99868886, 0x99868886, 0x998f8f8f, 0x99898889, 0x998f8f8f, 0x998f8f8f, + 0x99949094, 0x998c8b8c, 0x99949094, 0x99949094, 0x998f908f, 0x99949694, 0x998f908f, 0x99949694, + 0x998f908f, 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99919291, 0x99919291, 0x99919291, + 0x99949694, 0x99949694, 0x99949694, 0x99949694, 0x99919291, 0x99919291, 0x99919291, 0x99919291, + 0x99949694, 0x9991908f, 0x9991908f, 0x9991908f, 0x998f9091, 0x998f9091, 0x998f9091, 0x998f9091, + 0x998f8e8f, 0x998f8e8f, 0x998f8e8f, 0x99949294, 0x99949294, 0x998f8c8f, 0x998f8c8f, 0x998f8c8f, + 0x998c8e8c, 0x998c8e8c, 0x998c8e8c, 0x99868886, 0x99868886, 0x99868886, 0x99868886, 0x99818381, + 0x99848384, 0x99848384, 0x99848384, 0x99848384, 0x997e7f7e, 0x997e7f7e, 0x99797879, 0x99797879, + 0x99767576, 0x99767576, 0x99767576, 0x99767576, 0x9973706e, 0x9973706e, 0x996b6768, 0x996b6768, + 0x99656465, 0x99656465, 0x99656465, 0x99585658, 0x99505150, 0x99505150, 0x99505150, 0x99505150, + 0x993a3b3a, 0x993a3b3a, 0x77212221, 0x66080808, 0x77000000, 0x77000000, 0x77000000, 0x44000000, + 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x11000000, 0x44343534, 0xaa7b797b, 0xeeadaaad, 0xffadaaad, 0xffadaaad, + 0xffaaabaa, 0xffaaabaa, 0xffb8b9b8, 0xffb8b9b8, 0xffbdbdb8, 0xffc5c8c3, 0xffc5c8c3, 0xffc5c8c3, + 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd3d2d6, 0xffd9dbde, 0xffd9dbde, 0xffd9dbde, + 0xffe1e0e1, 0xffe1e0e1, 0xffe1e0e1, 0xffe6e7e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e5e6, 0xffe6e5e6, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xfff1f0ef, 0xfff1f0ef, 0xfff1f0ef, 0xfff1f0ef, + 0xfff1f3f1, 0xffecefec, 0xfff1f3f1, 0xfff1f3f1, 0xfff1f3f1, 0xfff7f7f7, 0xfff1f3f1, 0xfff7f7f7, + 0xfff4f3f4, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, + 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff4f3f4, 0xfff7f7f7, 0xfff4f3f4, + 0xfff5f5f4, 0xffeeedec, 0xffe4e4e5, 0xffe1e1e2, 0xffe3e1e3, 0xffe5e4e6, 0xffe6e4e6, 0xffe1dfde, + 0xffe1dfde, 0xffe1dfde, 0xffe1dfde, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffced0ce, + 0xffced0ce, 0xffced0ce, 0xffc5c5c5, 0xffc8c9c8, 0xffc8c9c8, 0xffbabcba, 0xffbabcba, 0xffb8b7b8, + 0xffb8b7b8, 0xffb8b7b8, 0xffaaa9aa, 0xffb5b2b5, 0xeeb5b2b5, 0xdd7b7b7e, 0x997b7b7e, 0x33343534, + 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00080408, 0x22080408, 0x55080408, 0x66080408, 0x66101010, 0x77101010, 0x88262626, 0x883c3b3c, + 0x993a3d3a, 0x993a3d3a, 0x99474947, 0x99474947, 0x99524d4a, 0x99524d4a, 0x995a5958, 0x995a5958, + 0x99636163, 0x99636163, 0x99636163, 0x99686868, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, 0x996b6d6b, + 0x99737173, 0x99737173, 0x99797879, 0x99797879, 0x99737573, 0x997b7c7b, 0x997b7c7b, 0x997b7c7b, + 0x997b7d7b, 0x997b7d7b, 0x99818381, 0x99818381, 0x99848284, 0x99848284, 0x99848284, 0x99848284, + 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99848684, + 0x99898b89, 0x99848684, 0x99898b89, 0x99898b89, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, + 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, 0x998c8a8c, + 0x998c8684, 0x998c8684, 0x998c8684, 0x998c8684, 0x9984868c, 0x9984868c, 0x9984868c, 0x9984868c, + 0x99848684, 0x99848684, 0x99848684, 0x99848684, 0x99898789, 0x99848284, 0x99848284, 0x99848284, + 0x99818381, 0x997b7d7b, 0x99818381, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, 0x997b7d7b, + 0x997b7c7b, 0x997b7c7b, 0x99737573, 0x99737573, 0x99737173, 0x99737173, 0x99737173, 0x99737173, + 0x99706d70, 0x99706d70, 0x996b656b, 0x996b656b, 0x99635d63, 0x99635d63, 0x99635d63, 0x99635d63, + 0x99585658, 0x99585658, 0x994a494a, 0x994a494a, 0x993c3d3c, 0x993c3d3c, 0x993c3d3c, 0x88292829, + 0x77080808, 0x66080808, 0x77080808, 0x77080808, 0x77000000, 0x55000000, 0x22000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11191819, 0x33191819, 0x664a494a, 0xbb7b797b, + 0xdd9c9e9c, 0xee9c9e9c, 0xffaaabaa, 0xffaaabaa, 0xffb5b2ad, 0xffb5b2ad, 0xffb5b2ad, 0xffbdbdb8, + 0xffc5bec5, 0xffc5bec5, 0xffcbc8cb, 0xffcbc8cb, 0xffcecace, 0xffcecace, 0xffcecace, 0xffd3d2d6, + 0xffd6d2d6, 0xffd6d2d6, 0xffdbd9db, 0xffdbd9db, 0xffd6dbd6, 0xffd6dbd6, 0xffdee0de, 0xffdee0de, + 0xffdedfde, 0xffdedfde, 0xffe4e4e4, 0xffe4e4e4, 0xffe6e3de, 0xffe6e3de, 0xffece9e6, 0xffece9e6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, + 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, + 0xffefebe6, 0xffeeeae5, 0xffdedfde, 0xffddddde, 0xffdeddde, 0xffd6d7d6, 0xffd6d7d6, 0xffdbd7d6, + 0xffdbd7d6, 0xffdbd7d6, 0xffd6cece, 0xffcecece, 0xffcecece, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c5c5, + 0xffc5c5c5, 0xffc5c5c5, 0xffbdbabd, 0xffbabcba, 0xffadaead, 0xffadaead, 0xffadaead, 0xffaaa9aa, + 0xffaaa9aa, 0xee9c9a9c, 0xdd9c9a9c, 0xaa7b7b7e, 0x55424347, 0x22080c10, 0x11080c10, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x11000000, 0x22000000, 0x44000000, 0x55030103, 0x66050305, 0x66080408, + 0x66131213, 0x77131213, 0x88262326, 0x883a353a, 0x88313131, 0x99313131, 0x994a494a, 0x994a494a, + 0x994a4d4a, 0x994a4d4a, 0x994a4d4a, 0x994a4d4a, 0x995a595a, 0x995a595a, 0x995a595a, 0x995a595a, + 0x99636563, 0x99636563, 0x99636563, 0x99636563, 0x996b6d73, 0x996b6d73, 0x996b6d73, 0x996b6d73, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x997b757b, 0x997b757b, 0x997b757b, 0x997b757b, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, + 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, 0x997b797b, + 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, 0x99737573, + 0x996b716b, 0x996b716b, 0x996b716b, 0x996b716b, 0x996b696b, 0x996b696b, 0x996b696b, 0x996b696b, + 0x99636563, 0x99636563, 0x99636563, 0x99636563, 0x995a595a, 0x995a595a, 0x995a595a, 0x995a595a, + 0x99525152, 0x99525152, 0x99525152, 0x99525152, 0x994a494a, 0x994a494a, 0x994a494a, 0x994a494a, + 0x99313531, 0x99313531, 0x88313531, 0x88212321, 0x77191419, 0x77100d10, 0x66080708, 0x66000000, + 0x77000000, 0x77000000, 0x66000000, 0x55000000, 0x22000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00030403, 0x11080c08, + 0x22000400, 0x442f312f, 0x885d5d5d, 0xbb8c8a8c, 0xdd9c9a9c, 0xdd9c9a9c, 0xee9c9a9c, 0xff9c9a9c, + 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, + 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, + 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcececd, 0xffcccdce, 0xffcccdcc, + 0xffcbc9cc, 0xffc9c8c9, 0xffc7c4c7, 0xffc2c1c3, 0xffbebdbf, 0xffb6babd, 0xffb5babd, 0xffadaead, + 0xffadaead, 0xffadaead, 0xffadaead, 0xffa5a6a5, 0xffa5a6a5, 0xffa5a6a5, 0xffa5a6a5, 0xffa5a2a5, + 0xffa5a2a5, 0xffa5a2a5, 0xffa5a2a5, 0xee9c9a9c, 0xee9c9a9c, 0xdd9c9a9c, 0xdd9c9a9c, 0xbb7b797b, + 0x77525252, 0x44292b29, 0x22000400, 0x11080c08, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x33000000, 0x44000000, + 0x55000000, 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x66191819, 0x77191819, 0x77191819, + 0x88313331, 0x88313331, 0x88313331, 0x88313331, 0x993f3d3f, 0x993f3d3f, 0x993f3d3f, 0x993f3d3f, + 0x99424342, 0x99424342, 0x99424342, 0x99424342, 0x99474a4d, 0x99474a4d, 0x99474a4d, 0x99474a4d, + 0x99504d50, 0x99504d50, 0x99504d50, 0x99504d50, 0x99555155, 0x99555155, 0x99555155, 0x99555155, + 0x99555455, 0x99555455, 0x99555455, 0x99555455, 0x99555455, 0x99555455, 0x99555455, 0x99555455, + 0x99555455, 0x99555455, 0x99555455, 0x99555455, 0x99555455, 0x99555455, 0x99555455, 0x99555455, + 0x99555455, 0x99555455, 0x99555455, 0x99555455, 0x99555455, 0x99555455, 0x99555455, 0x99555455, + 0x99555455, 0x99555455, 0x99555455, 0x99555455, 0x99555455, 0x99555455, 0x99555455, 0x99555455, + 0x99505150, 0x99505150, 0x99505150, 0x99505150, 0x99505150, 0x99505150, 0x99505150, 0x99505150, + 0x994a4d4a, 0x994a4d4a, 0x994a4d4a, 0x994a4d4a, 0x99474847, 0x99474847, 0x99474847, 0x99474847, + 0x99424342, 0x99424342, 0x99424342, 0x99424342, 0x993c3b3c, 0x993c3b3c, 0x993c3b3c, 0x993c3b3c, + 0x99373737, 0x99373737, 0x88373737, 0x88373737, 0x88313131, 0x88313131, 0x77191819, 0x77191819, + 0x77101210, 0x66000000, 0x66000000, 0x66000000, 0x77000000, 0x77000000, 0x66000000, 0x55000000, + 0x44000000, 0x33000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x00000400, 0x00000400, 0x11000400, 0x11000400, 0x22000400, 0x44343634, 0x77686868, + 0x99797b79, 0xbb797b79, 0xcc797b79, 0xcc797b79, 0xddadaead, 0xeeadaead, 0xeeadaead, 0xeeadaead, + 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, + 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcccbcb, 0xffc8c8c9, 0xffc6c5c6, + 0xffb3b2b4, 0xffadadaf, 0xffb0b0b3, 0xffafb1b4, 0xffb1b5b9, 0xffb4b9bc, 0xffb5babd, 0xffadaead, + 0xffadaead, 0xffadaead, 0xeeadaead, 0xeea5a6a5, 0xeea5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xcca5a2a5, + 0xcca5a2a5, 0xbb6e6d6e, 0x886e6d6e, 0x66343334, 0x55343334, 0x22343334, 0x11000000, 0x11000400, + 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11000000, 0x22000000, 0x33000000, 0x44000000, 0x55000000, 0x55000000, 0x55000000, 0x66000000, + 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x66080408, 0x66080408, 0x77080408, 0x77242024, + 0x77212221, 0x77212221, 0x77212221, 0x88212221, 0x88242726, 0x88242726, 0x88242726, 0x88242726, + 0x882c282c, 0x882c282c, 0x882c282c, 0x882c282c, 0x882f2d2f, 0x882f2d2f, 0x882f2d2f, 0x992f2d2f, + 0x882f2e2f, 0x882f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, + 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, + 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, + 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, 0x992f2e2f, + 0x992c2d2c, 0x992c2d2c, 0x992c2d2c, 0x992c2d2c, 0x992c2d2c, 0x882c2d2c, 0x882c2d2c, 0x882c2d2c, + 0x88292829, 0x88292829, 0x88292829, 0x88292829, 0x88242624, 0x88242624, 0x88242624, 0x88242624, + 0x88212221, 0x88212221, 0x88212221, 0x88212221, 0x771e1e1e, 0x771e1e1e, 0x771e1e1e, 0x771e1e1e, + 0x77000400, 0x66000400, 0x66000400, 0x66000400, 0x66000000, 0x66000000, 0x77000000, 0x77000000, + 0x77000000, 0x66000000, 0x66000000, 0x55000000, 0x44000000, 0x33000000, 0x11000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, + 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x22000400, 0x443a3d3a, 0x443a3d3a, 0x663a3d3a, + 0x663c3f3c, 0x773c3f3c, 0x88797b79, 0xaa797b79, 0xbb7e7f7e, 0xbb7e7f7e, 0xbb7e7f7e, 0xbb7e7f7e, + 0xcc848684, 0xcc848684, 0xcc848684, 0xcc848684, 0xcc898889, 0xdd898889, 0xdd898889, 0xdd898889, + 0xdd8c8b8c, 0xdd8c8b8c, 0xdd8c8b8c, 0xdd8c8b8c, 0xdd8c8b8c, 0xdd8c8b8c, 0xee8c8b8c, 0xee8c8b8c, + 0xee8c8b8c, 0xee8c8b8c, 0xee8c8b8c, 0xee8c8b8c, 0xee8c8b8c, 0xee8c8b8c, 0xee8c8b8c, 0xee8c8b8c, + 0xee8c8b8c, 0xee8c8b8c, 0xee8c8b8c, 0xee8c8b8c, 0xee8c8b8c, 0xee8c8b8c, 0xee8b8b8b, 0xee898989, + 0xee878588, 0xee848285, 0xcc7e7d80, 0xbb7b7c7f, 0xbb797c7e, 0xbb797c7e, 0xaa797c7e, 0xaa737473, + 0x88737473, 0x77737473, 0x663a3a3a, 0x55373a37, 0x44373a37, 0x33373a37, 0x22000400, 0x00000400, + 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, + 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, 0x22000000, + 0x33000000, 0x44000000, 0x44000000, 0x55000000, 0x55080408, 0x55080408, 0x66080408, 0x66080408, + 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x66000400, 0x66000400, 0x66000400, 0x66000400, + 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080808, 0x66080808, 0x66080808, 0x66080808, + 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, + 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, + 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, + 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, + 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, + 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66000400, 0x66000400, 0x66000400, 0x66000400, + 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x77000000, 0x77000000, 0x77000000, 0x77000000, + 0x66000400, 0x66000400, 0x66000400, 0x55000400, 0x55000000, 0x44000000, 0x44000000, 0x33000000, + 0x22000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, + 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, + 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, + 0x00080408, 0x00080408, 0x00080408, 0x00080408, 0x00080408, 0x00080408, 0x00080408, 0x00080408, + 0x00080408, 0x00080408, 0x00080408, 0x00080408, 0x00080408, 0x00080408, 0x00080408, 0x00080408, + 0x00080408, 0x00080408, 0x00080408, 0x00080408, 0x00080408, 0x00080408, 0x00080408, 0x00080407, + 0x00080408, 0x00060308, 0x00000400, 0x00010100, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, + 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, + 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x22000000, 0x22000000, 0x22000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x44000000, + 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x55000000, 0x55000000, 0x55000000, + 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, + 0x55000000, 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x66000000, + 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x55000000, 0x55000000, 0x55000000, + 0x55000000, 0x55000000, 0x55000000, 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x66000000, + 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, + 0x55000000, 0x55000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, + 0x44000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x22000000, 0x22000000, + 0x11000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00030403, 0x00030403, + 0x00050505, 0x00050505, 0x00050505, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00030403, 0x00030403, 0x00030403, + 0x00030303, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x11000000, 0x22000000, 0x22000000, 0x22000000, 0x33000000, 0x33000000, + 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000, + 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x22000000, 0x22000000, + 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00030403, 0x00050805, 0x11080c08, + 0x22101010, 0x22101010, 0x11101010, 0x11050505, 0x00000400, 0x00000100, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00050805, 0x11050805, 0x11080c08, 0x11080c08, + 0x11080808, 0x00030303, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, + 0x22000000, 0x22000000, 0x22000000, 0x33000000, 0x22000000, 0x22000000, 0x22000000, 0x11000000, + 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0x55050705, 0xaa101410, 0xcc191819, 0xcc191819, 0xcc191819, 0xcc191819, + 0xcc191c19, 0xcc191c19, 0xcc191c19, 0xcc191c19, 0xcc191c19, 0xcc191c19, 0xcc191c19, 0xcc191c19, + 0xcc191c19, 0xcc191c19, 0xcc191c19, 0xcc191c19, 0xcc191819, 0xcc191819, 0xcc191819, 0xbb191819, + 0x66080808, 0x22000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x44050405, 0x66100c10, + 0x99101010, 0xbb191819, 0xcc191819, 0xdd191819, 0xcc191819, 0xbb191819, 0x99101010, 0x77101010, + 0x44080408, 0x22030103, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11080808, 0x55080808, 0xbb4a494a, 0xdd8c8a8c, 0xeea5a6a5, 0xeea5a6a5, 0xeea5a6a5, 0xeea5a6a5, + 0xeeadaaad, 0xeeadaaad, 0xeeadaaad, 0xeeadaaad, 0xeeadaaad, 0xeeadaaad, 0xeeadaaad, 0xeeadaaad, + 0xeeadaaad, 0xeeadaaad, 0xeeadaaad, 0xeeadaaad, 0xeea5a6a5, 0xeea5a6a5, 0xeea5a6a5, 0xee8c8e8c, + 0xbb3c3b3c, 0x77080808, 0x22080808, 0x00080808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00080408, 0x00080408, 0x00080408, 0x11080408, 0x33080408, 0x88080408, 0xcc4a464a, 0xee4a464a, + 0xee8c8a8c, 0xffa7a6a7, 0xffa7a6a7, 0xffa7a6a7, 0xffafb3af, 0xff898c89, 0xee898c89, 0xee636563, + 0xcc4a494a, 0x88080408, 0x44080408, 0x22080408, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x22080808, 0xaa080808, 0xdd8c8a8c, 0xffcecace, 0xffcbcccb, 0xffcbcccb, 0xffcbcccb, 0xffcbcccb, + 0xffd3d0d3, 0xffd3d0d3, 0xffd3d0d3, 0xffd3d0d3, 0xffd3d0d3, 0xffd3d0d3, 0xffd3d0d3, 0xffd3d0d3, + 0xffd3d0d3, 0xffd3d0d3, 0xffd3d0d3, 0xffd3d0d3, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffbdbebd, + 0xeea5a2a5, 0xbb080808, 0x33080808, 0x00080808, 0x00000000, 0x110e0d0e, 0x110e0d0e, 0x331b1b1b, + 0x44212021, 0x55212021, 0x44212021, 0x22101010, 0x11100f10, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x110b0b0b, 0x110e0f0e, 0x330e0f0e, 0x441b1e1b, 0x330e0f0e, + 0x220b0b0b, 0x110b0b0b, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00080408, 0x00080408, 0x11080408, 0x55080408, 0xaa4a464a, 0xee8c888c, 0xff8c888c, 0xffcecace, + 0xffc3c2c3, 0xffc3c2c3, 0xffc3c2c3, 0xffdedfde, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffafb3af, + 0xff8c8e8c, 0xee8c8e8c, 0xbb4a494a, 0x66080408, 0x22000000, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x22080808, 0xcc080808, 0xee8c8a8c, 0xffcecace, 0xffcbcccb, 0xffcbcccb, 0xffdedfde, 0xffdedfde, + 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, + 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffa5a2a5, 0xdd080808, 0x44080808, 0x00080808, 0x00000000, 0x110e0d0e, 0x331b1b1b, 0x551b1b1b, + 0x77212021, 0x88212021, 0x88212021, 0x55212021, 0x33211e21, 0x11100f10, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x110b0b0b, 0x22161616, 0x441b1e1b, 0x661b1e1b, 0x661b1e1b, 0x551b1e1b, + 0x44161616, 0x220b0b0b, 0x000b0b0b, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00080408, 0x11080408, 0x66080408, 0xcc3c3b3c, 0xee8c888c, 0xffcecace, 0xffcecace, 0xffcecace, + 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffced2ce, 0xffced2ce, 0xee8c8e8c, 0xcc4a494a, 0x771b1a1b, 0x22000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x22080808, 0xcc080808, 0xee8c8a8c, 0xffcecace, 0xffcbcccb, 0xffdedfde, 0xffdedfde, 0xffdedfde, + 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, + 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffa5a2a5, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x220e0d0e, 0x551b1b1b, 0x77292829, + 0x99313131, 0xaa313131, 0xbb313131, 0xaa313131, 0x77312d31, 0x33211e21, 0x11100f10, 0x11000000, + 0x00000000, 0x110b0b0b, 0x22161616, 0x44212021, 0x88292d29, 0x99292d29, 0x99292d29, 0x77292d29, + 0x66212021, 0x33161616, 0x110b0b0b, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11080408, 0x55080408, 0xcc3c3b3c, 0xffa5aaa5, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, + 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xff8c8e8c, 0xcc524d52, 0x771b1a1b, 0x22000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33101010, 0xcc101010, 0xee9a9a9a, 0xffdedfde, 0xffd6d7d6, 0xffdedfde, 0xffdedfde, 0xffe6e7e6, + 0xffe6e7e6, 0xffe6e7e6, 0xffecedec, 0xffecedec, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, 0xffe4e5e4, 0xffe4e5e4, 0xffdedfde, 0xffdedfde, + 0xffb5b2b5, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x220e0d0e, 0x551b1b1b, 0x88292829, + 0xaa292d29, 0xbb292d29, 0xcc292d29, 0xcc212321, 0xbb2c2e2c, 0x882c2e2c, 0x442c2e2c, 0x22101010, + 0x11191419, 0x22191419, 0x44292629, 0x99292629, 0xbb292729, 0xbb313131, 0xaa313131, 0x99313131, + 0x77212421, 0x44161816, 0x110b0c0b, 0x00000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, + 0x33080808, 0xbb4a4a4a, 0xee8c8c8c, 0xffcecece, 0xffd6d7d6, 0xffd6d7d6, 0xffdeddde, 0xffdeddde, + 0xffdee3de, 0xffe6e9e6, 0xffe6e9e6, 0xffe6e9e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, + 0xffe6e7e6, 0xffdedbde, 0xffdedbde, 0xffd6ced6, 0xee8c8e8c, 0xbb4a494a, 0x55080408, 0x11080408, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00080808, 0x00080808, 0x00080808, 0x00080808, + 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33101010, 0xcc101010, 0xee9a9a9a, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffe6e7e6, 0xffe6e7e6, + 0xffecedec, 0xffecedec, 0xfff1f4f1, 0xfff1f4f1, 0xfff1f3f1, 0xfff1f3f1, 0xfff1f3f1, 0xfff1f3f1, + 0xfff1f0f1, 0xfff1f0f1, 0xfff1f0f1, 0xfff1f0f1, 0xffe9ece9, 0xffe9ece9, 0xffe4e5e4, 0xffdedfde, + 0xffb5b2b5, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x110e0d0e, 0x441b1b1b, 0x88292829, + 0xbb292d29, 0xcc212321, 0xcc212321, 0xdd191a19, 0xdd1e1f1e, 0xcc1e1f1e, 0x992c2e2c, 0x552c2e2c, + 0x33292629, 0x553a373a, 0x993a373a, 0xcc292629, 0xcc211e21, 0xcc292729, 0xbb292729, 0xbb292729, + 0x88212421, 0x33161816, 0x110b0c0b, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x11000000, + 0x88080808, 0xee8c8c8c, 0xffcecece, 0xffcecece, 0xffd6d7d6, 0xffdeddde, 0xffe6e4e6, 0xffe6e4e6, + 0xffe6e9e6, 0xffe6e9e6, 0xffeff0ef, 0xffeff0ef, 0xfff1f2f1, 0xffececec, 0xffececec, 0xffececec, + 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffdedbde, 0xffced2ce, 0xee8c8e8c, 0x99080408, 0x33080408, + 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x110e0c0e, 0x11131413, 0x22131413, 0x22131413, 0x22131413, + 0x110e120e, 0x110e120e, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33101010, 0xcc101010, 0xee9a9a9a, 0xffdedfde, 0xffdedfde, 0xffe6e7e6, 0xffe6e7e6, 0xffefefef, + 0xfff1f4f1, 0xfff1f4f1, 0xfff1f4f1, 0xfff1f4f1, 0xfff4f7f4, 0xfff4f7f4, 0xfff4f7f4, 0xfff4f7f4, + 0xfff4f6f4, 0xfff4f6f4, 0xfff4f6f4, 0xfff4f6f4, 0xffeff3ef, 0xffe9ece9, 0xffe9ece9, 0xffe4e5e4, + 0xffb5b2b5, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x000e0d0e, 0x221b1b1b, 0x55292829, + 0xaa292d29, 0xcc212321, 0xdd191a19, 0xdd191a19, 0xee101010, 0xdd101010, 0xdd1e1f1e, 0xaa3a3d3a, + 0x774a494a, 0x993a373a, 0xcc292629, 0xdd191419, 0xdd211e21, 0xdd211e21, 0xcc292729, 0xaa292729, + 0x66212421, 0x33161816, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x00000000, 0x44050405, + 0xcc4a4a4a, 0xff8c8c8c, 0xffcecece, 0xffcecece, 0xffdeddde, 0xffe6e4e6, 0xffe6e4e6, 0xffefebef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xfff1f2f1, 0xfff1f2f1, 0xfff1f2f1, 0xfff1f2f1, + 0xffeff3ef, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffced2ce, 0xff8c8e8c, 0xcc4a494a, 0x55080408, + 0x22000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x110e0c0e, 0x221b181b, 0x441e201e, 0x661e201e, 0x66292d29, 0x66292d29, + 0x551b1f1b, 0x331b1f1b, 0x110e120e, 0x11000400, 0x00030303, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33101010, 0xcc101010, 0xee9a9a9a, 0xffdedfde, 0xffdedfde, 0xffe6e7e6, 0xffefefef, 0xffefefef, + 0xfff1f4f1, 0xfff1f4f1, 0xfff7fbf7, 0xfff7fbf7, 0xfff7fbf7, 0xfff7fbf7, 0xfff7fbf7, 0xfff7fbf7, + 0xfff7fbf7, 0xfff7fbf7, 0xfff4f6f4, 0xfff4f6f4, 0xffeff3ef, 0xffeff3ef, 0xffe9ece9, 0xffe4e5e4, + 0xffb5b2b5, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x00000000, 0x110e0d0e, 0x221b1b1b, + 0x66292d29, 0xbb292d29, 0xdd191a19, 0xee101010, 0xee101010, 0xee101010, 0xee101010, 0xdd1e1f1e, + 0xbb292629, 0xdd292629, 0xee191419, 0xee191419, 0xdd191419, 0xdd191419, 0xcc292729, 0x88313131, + 0x44212421, 0x330b0c0b, 0x22000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x66100c10, + 0xee4a4a4a, 0xffcecece, 0xffcecece, 0xffcecece, 0xffe6e4e6, 0xffe6e4e6, 0xffefebef, 0xffefebef, + 0xffeff0ef, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, + 0xffeff3ef, 0xffeff3ef, 0xffe6e7e6, 0xffe6e7e6, 0xffced2ce, 0xffced2ce, 0xee4a494a, 0x88080408, + 0x22000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x110e0c0e, 0x331b181b, 0x66292429, 0x88292d29, 0xaa292d29, 0xaa292d29, 0xaa292d29, + 0x99292d29, 0x77292d29, 0x551b1f1b, 0x220e120e, 0x11080808, 0x00030303, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33101010, 0xcc101010, 0xee9f9f9f, 0xffe6e7e6, 0xffe6e3e6, 0xffece9ec, 0xfff1f0f1, 0xfff1f0f1, + 0xfff7f7f7, 0xfffafafa, 0xfffcfcfc, 0xfffcfcfc, 0xfffffcff, 0xfffffcff, 0xfffffcff, 0xfffffcff, + 0xfffffcff, 0xfffffcff, 0xfffffbff, 0xfffffbff, 0xfff1f4f1, 0xfff1f4f1, 0xffecedec, 0xffe6e7e6, + 0xffbdbabd, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x00000000, 0x00050405, 0x11100c10, + 0x33212321, 0x77313531, 0xbb313531, 0xee101210, 0xee080808, 0xee080808, 0xee080808, 0xee080808, + 0xee100c10, 0xee100c10, 0xee100c10, 0xee100c10, 0xee101010, 0xdd212021, 0xaa313131, 0x55313131, + 0x33101010, 0x33050505, 0x22000000, 0x11000000, 0x11000000, 0x00000000, 0x11000000, 0x99101310, + 0xee8c8e8c, 0xffc3c4c3, 0xffdedfde, 0xffdedfde, 0xffe6e7e6, 0xffecedec, 0xffecedec, 0xfff1f4f1, + 0xfff7f7f7, 0xfff7f7f7, 0xfffafafa, 0xfffafafa, 0xfffafafa, 0xfffafafa, 0xfffafafa, 0xfff7f7f7, + 0xfffaf6fa, 0xfff4f0f4, 0xfff4f0f4, 0xffefebef, 0xffe6e7e6, 0xffe6e7e6, 0xeea2a3a2, 0xaa191c19, + 0x33000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00030303, + 0x11080808, 0x221e201e, 0x66292d29, 0xaa292d29, 0xbb292d29, 0xcc262726, 0xcc262726, 0xcc262726, + 0xcc262726, 0xbb292d29, 0x88262726, 0x55242224, 0x220b0c0b, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33101010, 0xcc101010, 0xee9f9f9f, 0xffe6e7e6, 0xffe6e3e6, 0xffece9ec, 0xfff1f0f1, 0xfff7f7f7, + 0xfff7f7f7, 0xfffcfcfc, 0xfffcfcfc, 0xffffffff, 0xfffffeff, 0xfffffeff, 0xfffffeff, 0xfffffeff, + 0xfffffeff, 0xfffffeff, 0xfffffeff, 0xfffffbff, 0xfff7fbf7, 0xfff1f4f1, 0xfff1f4f1, 0xffe6e7e6, + 0xffbdbabd, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x00000000, 0x00000000, 0x11050405, + 0x11101210, 0x33212321, 0x77313531, 0xcc313531, 0xee080808, 0xee080808, 0xff080808, 0xff080808, + 0xff050705, 0xee050705, 0xee0b090b, 0xee100c10, 0xee101010, 0xbb313131, 0x77313131, 0x44212021, + 0x33050505, 0x33000000, 0x22000000, 0x11000000, 0x11000000, 0x00000000, 0x22000000, 0xbb191c19, + 0xffa7a9a7, 0xffc3c4c3, 0xffdedfde, 0xffdedfde, 0xffe6e7e6, 0xffecedec, 0xfff1f4f1, 0xfff1f4f1, + 0xfffafafa, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffffbff, 0xfffaf6fa, 0xfff4f0f4, 0xfff4f0f4, 0xffe6e7e6, 0xffe6e7e6, 0xffa2a3a2, 0xcc191c19, + 0x44000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00050505, + 0x11131413, 0x551e201e, 0x99292d29, 0xbb292d29, 0xcc242224, 0xcc242224, 0xdd242224, 0xdd242224, + 0xdd242224, 0xcc262726, 0xbb292d29, 0x88262726, 0x33161816, 0x110b0c0b, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33101010, 0xcc101010, 0xee9f9f9f, 0xffe6e7e6, 0xffe6e3e6, 0xffece9ec, 0xfff1f0f1, 0xfff7f7f7, + 0xfffafafa, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffeff, 0xfffffcff, 0xfff7fbf7, 0xfff1f4f1, 0xfff1f4f1, 0xffe6e7e6, + 0xffbdbabd, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11000000, 0x22101210, 0x44212321, 0x88313531, 0xcc2f332f, 0xee080808, 0xff080808, 0xff080808, + 0xff050705, 0xff050705, 0xee0b090b, 0xee100c10, 0xcc212021, 0x99424142, 0x66212021, 0x44101010, + 0x33000000, 0x33000000, 0x22000000, 0x11000000, 0x11000000, 0x00000000, 0x22000000, 0xcc191c19, + 0xffa7a9a7, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffecedec, 0xfff1f4f1, 0xfff1f4f1, 0xfff7fbf7, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xfffcfcfc, + 0xfffffbff, 0xfffaf6fa, 0xfffaf6fa, 0xfff4f0f4, 0xffe6e7e6, 0xffe6e7e6, 0xffa2a3a2, 0xdd191c19, + 0x44000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00080808, + 0x22131413, 0x66292d29, 0xaa292d29, 0xcc1e201e, 0xdd242224, 0xdd242224, 0xdd242224, 0xdd211c21, + 0xdd211c21, 0xcc242224, 0xbb292d29, 0x99292d29, 0x55212421, 0x220b0c0b, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33101010, 0xcc101010, 0xee9f9f9f, 0xffe6e7e6, 0xffece9ec, 0xfff1f0f1, 0xfff1f0f1, 0xfff7f7f7, + 0xfffafafa, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffeff, 0xfffffcff, 0xfff7fbf7, 0xfff1f4f1, 0xfff1f4f1, 0xffecedec, + 0xffbdbabd, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0x22101210, 0x55313531, 0x99424942, 0xdd1b1e1b, 0xff080808, 0xff080808, + 0xff000400, 0xff050705, 0xff050705, 0xee100c10, 0xcc313131, 0x99424142, 0x66212021, 0x44101010, + 0x33050505, 0x33000000, 0x22000000, 0x11000000, 0x00000000, 0x00000000, 0x33000000, 0xdd191c19, + 0xffa7a9a7, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffecedec, 0xfff1f4f1, 0xfff1f4f1, 0xfff7fbf7, + 0xfffcfcfc, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffcfcfc, + 0xfffffbff, 0xfffffbff, 0xfffaf6fa, 0xfff4f0f4, 0xffe6e7e6, 0xffe6e7e6, 0xffa2a3a2, 0xdd191c19, + 0x55000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00080808, + 0x33131413, 0x77292d29, 0xbb292d29, 0xcc1e201e, 0xdd211c21, 0xdd242224, 0xdd242224, 0xdd242224, + 0xdd211c21, 0xdd242224, 0xcc292d29, 0xaa292d29, 0x66212421, 0x330b0c0b, 0x11000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33101010, 0xcc101010, 0xeea5a2a5, 0xffefebef, 0xffe6e7e6, 0xffececec, 0xfff1f2f1, 0xfff7f7f7, + 0xfff7fbf7, 0xfffafcfa, 0xfffcfefc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffeff, 0xfffffcff, 0xfff7fbf7, 0xfff4f6f4, 0xfff1f0f1, 0xffefebef, + 0xffbdbabd, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00080408, 0x11080408, 0x22191619, 0x553a393a, 0xaa424542, 0xee1b1c1b, 0xff080808, 0xff080808, + 0xff000400, 0xff000400, 0xff000400, 0xee0e100e, 0xee1e1e1e, 0xbb3a393a, 0x882c2b2c, 0x551e1e1e, + 0x440e0d0e, 0x33000000, 0x22000000, 0x11000000, 0x00000000, 0x00000000, 0x22000000, 0xcc191c19, + 0xffb8bab8, 0xffdee3de, 0xffdee3de, 0xffdee3de, 0xffefefef, 0xfff1f3f1, 0xfff4f7f4, 0xfff7fbf7, + 0xfffffcff, 0xfffffeff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfffcfbfc, 0xfffcfbfc, 0xfffaf7fa, 0xfff7f3f7, 0xffe6e7e6, 0xffe6e7e6, 0xffa2a2a2, 0xdd191819, + 0x55000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00080808, + 0x22131713, 0x77292d29, 0xbb292d29, 0xcc1e221e, 0xdd242224, 0xdd242224, 0xdd211c21, 0xdd211c21, + 0xdd191c19, 0xdd1e221e, 0xcc292d29, 0xaa292d29, 0x66292429, 0x330e0c0e, 0x11000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33101010, 0xcc101010, 0xeea5a2a5, 0xffefebef, 0xffe6e7e6, 0xffececec, 0xfff1f2f1, 0xfff7f7f7, + 0xfff7fbf7, 0xfffafcfa, 0xfffcfefc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffeff, 0xfffffcff, 0xfff7fbf7, 0xfff4f6f4, 0xfff1f0f1, 0xffefebef, + 0xffbdbabd, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00080408, 0x11080408, 0x33292729, 0x773a393a, 0xdd1b1c1b, 0xee080808, 0xff080808, 0xff080808, + 0xff000400, 0xff000400, 0xff000400, 0xee0e100e, 0xee101010, 0xdd1e1e1e, 0xbb3a393a, 0x772c2b2c, + 0x441b1b1b, 0x330e0d0e, 0x22000000, 0x11000000, 0x00000000, 0x00000000, 0x22000000, 0xbb191c19, + 0xff919291, 0xffdee3de, 0xffdee3de, 0xffdee3de, 0xffefefef, 0xfff1f3f1, 0xfff4f7f4, 0xfff7fbf7, + 0xfffffeff, 0xfffffeff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfffcfbfc, 0xfffcfbfc, 0xfffaf7fa, 0xfff7f3f7, 0xffe6e7e6, 0xffe6e7e6, 0xffa2a2a2, 0xcc191819, + 0x44000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00050505, + 0x22131713, 0x661e221e, 0xaa292d29, 0xcc292d29, 0xdd242224, 0xdd242224, 0xdd211c21, 0xdd211c21, + 0xdd1e221e, 0xdd242724, 0xcc292d29, 0x99242724, 0x551b181b, 0x330e0c0e, 0x11000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33101010, 0xcc101010, 0xeea5a2a5, 0xffefebef, 0xffe6e7e6, 0xffececec, 0xfff1f2f1, 0xfff7f7f7, + 0xfff7fbf7, 0xfffafcfa, 0xfffcfefc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffeff, 0xfffffcff, 0xfff7fbf7, 0xfff4f6f4, 0xfff1f0f1, 0xffefebef, + 0xffbdbabd, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x00000000, 0x00000000, 0x00030103, + 0x11080408, 0x22191619, 0x663a393a, 0xcc292729, 0xee080808, 0xff080808, 0xff080808, 0xff080808, + 0xee0e100e, 0xee0e100e, 0xee0e100e, 0xee0e100e, 0xee101010, 0xee101010, 0xdd1e1e1e, 0xaa2c2b2c, + 0x66292829, 0x330e0d0e, 0x220e0d0e, 0x11000000, 0x11000000, 0x00000000, 0x22000000, 0x99101310, + 0xee919291, 0xffdee3de, 0xffdee3de, 0xffdee3de, 0xffefefef, 0xfff1f3f1, 0xfff4f7f4, 0xfff7fbf7, + 0xfffffcff, 0xfffffeff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfffcfbfc, 0xfffcfbfc, 0xfffaf7fa, 0xfff7f3f7, 0xffe6e7e6, 0xffe6e7e6, 0xeea2a2a2, 0xaa191819, + 0x44000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00030303, + 0x11080c08, 0x441e221e, 0x88292d29, 0xbb292d29, 0xcc262726, 0xdd242224, 0xdd242224, 0xdd242224, + 0xdd1e221e, 0xcc292d29, 0xbb292d29, 0x88242724, 0x441b181b, 0x330e0c0e, 0x11000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33101010, 0xcc101010, 0xeea5a2a5, 0xffefebef, 0xffe6e7e6, 0xffececec, 0xfff1f2f1, 0xfff7f7f7, + 0xfff7fbf7, 0xfffafcfa, 0xfffcfefc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffeff, 0xfffffcff, 0xfff7fbf7, 0xfff4f6f4, 0xfff1f0f1, 0xffefebef, + 0xffbdbabd, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x00000000, 0x00030103, 0x00080408, + 0x11191619, 0x44292729, 0xaa3a393a, 0xdd191619, 0xee080808, 0xee080808, 0xee080808, 0xee080808, + 0xdd1b1c1b, 0xdd292829, 0xee0e100e, 0xee0e100e, 0xee101010, 0xee1e1e1e, 0xdd1e1e1e, 0xcc2c2b2c, + 0x99292829, 0x55292829, 0x220e0d0e, 0x11000000, 0x11080908, 0x11000000, 0x11000000, 0x77080908, + 0xee6b696b, 0xffb8bab8, 0xffdee3de, 0xffdee3de, 0xffefefef, 0xfff1f3f1, 0xfff4f7f4, 0xfff7fbf7, + 0xfffffcff, 0xfffffeff, 0xfffffeff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfffcfbfc, 0xfffaf7fa, 0xfffaf7fa, 0xfff7f3f7, 0xffe6e7e6, 0xffe6e7e6, 0xee5d5d5d, 0x88191819, + 0x33000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11080c08, 0x22131713, 0x661e221e, 0x99292d29, 0xbb292d29, 0xcc292d29, 0xcc262726, 0xcc292d29, + 0xcc292d29, 0xbb292d29, 0x99242724, 0x66191c19, 0x330e0c0e, 0x22000000, 0x11000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33101010, 0xcc101010, 0xee9f9f9f, 0xffe6e7e6, 0xffe6e9e6, 0xffe6e9e6, 0xffeff0ef, 0xfff7f7f7, + 0xfffaf7fa, 0xfffcfbfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xfff7fbf7, 0xfff1f4f1, 0xfff1f4f1, 0xffe6e7e6, + 0xffbdbabd, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x00000000, 0x00000000, 0x110b0c0b, + 0x33262826, 0x88313531, 0xdd1b1c1b, 0xee101010, 0xee101010, 0xee101010, 0xee101010, 0xdd1e1e1e, + 0xaa4a454a, 0x994a454a, 0xcc312f31, 0xdd191a19, 0xee191c19, 0xdd191c19, 0xdd212321, 0xcc292a29, + 0xbb262426, 0x88262426, 0x441b181b, 0x22100c10, 0x22080c08, 0x11030403, 0x11000000, 0x44050805, + 0xcc504c50, 0xff979397, 0xffdedbde, 0xffdedbde, 0xffececec, 0xffececec, 0xfff7f7f7, 0xfff7f7f7, + 0xfffafbfa, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xfffcfcfc, + 0xfff7f3f7, 0xfff7f3f7, 0xfff7f3f7, 0xfff7f3f7, 0xffdee3de, 0xff979897, 0xcc504e50, 0x66080408, + 0x22000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x110b0b0b, 0x33161616, 0x66212021, 0x88292d29, 0xaa292d29, 0xbb292d29, 0xbb292d29, + 0xaa292829, 0x88292829, 0x661b1b1b, 0x440e0d0e, 0x33080408, 0x22030103, 0x11000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33101010, 0xcc101010, 0xee9f9f9f, 0xffe6e7e6, 0xffdee3de, 0xffe6e9e6, 0xffeff0ef, 0xfff7f7f7, + 0xfffaf7fa, 0xfffcfbfc, 0xfffcfbfc, 0xffffffff, 0xfffcfefc, 0xfffcfefc, 0xfffcfefc, 0xfffcfefc, + 0xffffffff, 0xffffffff, 0xfffcfcfc, 0xfffcfcfc, 0xfff7fbf7, 0xfff1f4f1, 0xfff1f4f1, 0xffe6e7e6, + 0xffbdbabd, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x00000000, 0x110b0c0b, 0x22161816, + 0x66262826, 0xbb262826, 0xdd1b1c1b, 0xee101010, 0xee101010, 0xee101010, 0xdd1e1e1e, 0xaa3a393a, + 0x77312f31, 0x77312f31, 0x88312f31, 0xbb312f31, 0xdd212321, 0xdd212321, 0xdd292a29, 0xcc313131, + 0xbb313131, 0x99262426, 0x661b181b, 0x33100c10, 0x33080c08, 0x11030403, 0x00000000, 0x22000000, + 0x88080408, 0xee979397, 0xffdedbde, 0xffdedbde, 0xffececec, 0xffececec, 0xfff7f7f7, 0xfff7f7f7, + 0xfffafbfa, 0xfffafbfa, 0xfffafbfa, 0xfffafbfa, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfff7f3f7, 0xfff7f3f7, 0xfff7f3f7, 0xfff7f3f7, 0xffdee3de, 0xee979897, 0x99080408, 0x44080408, + 0x22000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0x110b0b0b, 0x33161616, 0x441e1f1e, 0x661e1f1e, 0x77292d29, 0x771e1f1e, + 0x661b1b1b, 0x551b1b1b, 0x440e0d0e, 0x33000000, 0x22030103, 0x22000000, 0x11000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33101010, 0xcc101010, 0xee9f9f9f, 0xffe6e7e6, 0xffdee3de, 0xffe6e9e6, 0xffeff0ef, 0xffeff0ef, + 0xfffaf7fa, 0xfffaf7fa, 0xfffcfbfc, 0xfffcfbfc, 0xfffafcfa, 0xfffafcfa, 0xfffafcfa, 0xfffafcfa, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffafafa, 0xfff1f4f1, 0xfff1f4f1, 0xffecedec, 0xffe6e7e6, + 0xffbdbabd, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x00000000, 0x110b0c0b, 0x44212421, + 0x99262826, 0xcc262826, 0xdd1b1c1b, 0xdd1b1c1b, 0xdd101010, 0xdd1e1e1e, 0xbb3a393a, 0x772c2b2c, + 0x66191a19, 0x66191a19, 0x66191a19, 0x88312f31, 0xaa292a29, 0xcc292a29, 0xcc292a29, 0xbb313131, + 0xaa313131, 0x99262426, 0x77262426, 0x441b181b, 0x33050805, 0x22030403, 0x00000000, 0x11000000, + 0x44080408, 0xbb504c50, 0xee979397, 0xffdedbde, 0xffe1e1e1, 0xffececec, 0xffececec, 0xfff7f7f7, + 0xfff4f7f4, 0xfff4f7f4, 0xfffafbfa, 0xfffafbfa, 0xfffafafa, 0xfffafafa, 0xfffafafa, 0xfff7f7f7, + 0xfff7f3f7, 0xfff7f3f7, 0xfff7f3f7, 0xffe1dfe1, 0xee979897, 0xcc504e50, 0x66080408, 0x33080408, + 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x11000000, 0x110b0b0b, 0x22131213, 0x33131213, 0x44131213, 0x44131213, + 0x440e0d0e, 0x330e0d0e, 0x33000000, 0x22000000, 0x22000000, 0x11000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33101010, 0xcc101010, 0xee9f9f9f, 0xffe6e7e6, 0xffdee3de, 0xffe6e9e6, 0xffeff0ef, 0xffeff0ef, + 0xfff7f3f7, 0xfffaf7fa, 0xfffaf7fa, 0xfffaf7fa, 0xfff7fbf7, 0xfff7fbf7, 0xfff7fbf7, 0xfff7fbf7, + 0xfffafafa, 0xfffafafa, 0xfff7f7f7, 0xfff7f7f7, 0xfff1f4f1, 0xfff1f4f1, 0xffecedec, 0xffe6e7e6, + 0xffbdbabd, 0xdd080808, 0x55080808, 0x00080808, 0x00000000, 0x000b0c0b, 0x22161816, 0x66212421, + 0x99262826, 0xbb262826, 0xcc262826, 0xdd1b1c1b, 0xdd1e1e1e, 0xbb2c2b2c, 0x772c2b2c, 0x551e1e1e, + 0x55000400, 0x55000400, 0x55000400, 0x55191a19, 0x66212321, 0x99292a29, 0xaa292a29, 0xaa292a29, + 0x99313131, 0x88262426, 0x661b181b, 0x441b181b, 0x22050805, 0x22030403, 0x00000000, 0x00000000, + 0x22080408, 0x66080408, 0xcc504c50, 0xff979397, 0xffd6d7d6, 0xffe1e1e1, 0xffececec, 0xffececec, + 0xffeff3ef, 0xfff4f7f4, 0xfff4f7f4, 0xfff4f7f4, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, + 0xfff7f3f7, 0xfff7f3f7, 0xffe1dfe1, 0xffb5b6b5, 0xdd504e50, 0x88080408, 0x44080408, 0x22080408, + 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11080408, 0x22080408, 0x22080408, 0x22080408, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33080808, 0xcc080808, 0xee919491, 0xffd6dbd6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, + 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, + 0xffa5a6a5, 0xdd080408, 0x55080408, 0x00080408, 0x00000000, 0x110b0b0b, 0x33161616, 0x66212021, + 0x88292829, 0xaa292829, 0xbb292829, 0xcc292829, 0xbb292829, 0x77292829, 0x551b1b1b, 0x550e0d0e, + 0x44030303, 0x44000000, 0x44030303, 0x44080808, 0x440b0b0b, 0x55212021, 0x77212021, 0x88212021, + 0x88212021, 0x77212021, 0x55191819, 0x44101010, 0x22080408, 0x11030103, 0x00000000, 0x00000000, + 0x00000000, 0x22000000, 0x771b1b1b, 0xcc525152, 0xee979397, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffdee3de, 0xffdee3de, 0xff979897, 0xdd504e50, 0x88101410, 0x44000000, 0x22000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x22080808, 0xbb080808, 0xee919491, 0xffd6dbd6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, + 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xffefebef, 0xffefebef, 0xffefebef, 0xffefebef, + 0xeea5a6a5, 0xcc080408, 0x44080408, 0x00080408, 0x00000000, 0x110b0b0b, 0x220b0b0b, 0x44161616, + 0x661e1e1e, 0x77292829, 0x88292829, 0x99292829, 0x77292829, 0x551b1b1b, 0x440e0d0e, 0x44000000, + 0x44000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x330b0b0b, 0x44161616, 0x66161616, + 0x66191819, 0x66191819, 0x55101010, 0x33101010, 0x22030103, 0x11030103, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0x22000000, 0x771b1b1b, 0xbb504c50, 0xee979397, 0xff979397, 0xffdedbde, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xff979897, 0xee979897, 0xcc504e50, 0x88080408, 0x44000000, 0x22000000, 0x11000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11080808, 0x66080808, 0xbb4d4e4d, 0xee919491, 0xeea5a7a5, 0xffa5a7a5, 0xffa5a7a5, 0xffa5a7a5, + 0xffb2b1b2, 0xffb2b1b2, 0xffb2b1b2, 0xffb2b1b2, 0xffb2b1b2, 0xffb2b1b2, 0xffb2b1b2, 0xffb2b1b2, + 0xffb2b1b2, 0xffb2b1b2, 0xffb2b1b2, 0xffb2b1b2, 0xffaaa7aa, 0xffaaa7aa, 0xeeaaa7aa, 0xeeaaa7aa, + 0xcc707070, 0x99080408, 0x33080408, 0x00080408, 0x00000000, 0x00000000, 0x110b0b0b, 0x220b0b0b, + 0x33131313, 0x441e1e1e, 0x441e1e1e, 0x441e1e1e, 0x440e0d0e, 0x440e0d0e, 0x44000000, 0x44000000, + 0x33000000, 0x33000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x220b0b0b, 0x330b0b0b, + 0x44101010, 0x44101010, 0x44080808, 0x33080808, 0x11030103, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x11000000, 0x22000000, 0x55080408, 0x99080408, 0xcc504c50, 0xee504c50, + 0xeeaaa9aa, 0xffaaa9aa, 0xffaaa9aa, 0xffaaa9aa, 0xffa7a9a7, 0xffa7a9a7, 0xeea7a9a7, 0xee606260, + 0xcc504e50, 0x99080408, 0x66080408, 0x44080408, 0x22000000, 0x11000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00080808, 0x22080808, 0x77080808, 0xbb080808, 0xdd212021, 0xdd212021, 0xdd212021, 0xdd212021, + 0xdd292429, 0xdd292429, 0xdd292429, 0xdd292429, 0xdd292429, 0xdd292429, 0xdd292429, 0xdd292429, + 0xdd292429, 0xdd292429, 0xdd292429, 0xdd292429, 0xdd212021, 0xdd212021, 0xdd212021, 0xcc212021, + 0x99080408, 0x44080408, 0x22080408, 0x00080408, 0x00000000, 0x00000000, 0x00000000, 0x110b0b0b, + 0x11080808, 0x11080808, 0x22080808, 0x22080808, 0x33000000, 0x33000000, 0x33000000, 0x33000000, + 0x33000000, 0x22000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x22000000, + 0x22080808, 0x33080808, 0x33080808, 0x22080808, 0x11000000, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11080408, 0x33080408, 0x55080408, 0x88080408, + 0xaa211c21, 0xcc211c21, 0xdd211c21, 0xdd211c21, 0xdd191c19, 0xcc191c19, 0xaa191c19, 0x88191c19, + 0x66080408, 0x44080408, 0x33080408, 0x22080408, 0x11000000, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0x22000000, 0x33000000, 0x44000000, 0x55000000, 0x55000000, 0x55000000, + 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, + 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x44000000, + 0x33000000, 0x22000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11000000, 0x11000000, 0x11000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x11000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x22000000, 0x22000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x22000000, 0x22000000, + 0x33000000, 0x44000000, 0x44000000, 0x55000000, 0x55000000, 0x44000000, 0x44000000, 0x33000000, + 0x22000000, 0x22000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x33000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, + 0x22000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0x22000000, 0x22000000, 0x33000300, 0x33000300, 0x44000400, 0x44000400, + 0x55080808, 0x55101010, 0x66101010, 0x66191819, 0x661b1e1b, 0x661b1e1b, 0x66292d29, 0x66292d29, + 0x77313531, 0x77313531, 0x77313531, 0x77313531, 0x773a3d3a, 0x773a3d3a, 0x773a3d3a, 0x773a3d3a, + 0x77424142, 0x77424142, 0x77424142, 0x77424142, 0x77424542, 0x77424542, 0x77424542, 0x77424542, + 0x77424542, 0x77424542, 0x77424542, 0x77424542, 0x88424542, 0x88424542, 0x88424542, 0x88424542, + 0x88424542, 0x88424542, 0x88424542, 0x88424542, 0x88424542, 0x88424542, 0x88424542, 0x88424542, + 0x88424142, 0x88424142, 0x88424142, 0x88424142, 0x88424142, 0x88424142, 0x88424142, 0x88424142, + 0x88424142, 0x88424142, 0x88424142, 0x88424142, 0x883a3d3a, 0x883a3d3a, 0x883a3d3a, 0x883a3d3a, + 0x883a3d3a, 0x883a3d3a, 0x883a3d3a, 0x883a3d3a, 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, + 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, + 0x88313531, 0x88313531, 0x88313531, 0x88313531, 0x88313131, 0x88313131, 0x88313131, 0x88313131, + 0x88313131, 0x88313131, 0x88313131, 0x88313131, 0x88312d31, 0x88312d31, 0x88312d31, 0x88312d31, + 0x88312d31, 0x88312d31, 0x88312d31, 0x88312d31, 0x88292d29, 0x88292d29, 0x88292d29, 0x88292d29, + 0x88292d29, 0x88292d29, 0x88292d29, 0x88292d29, 0x88292d29, 0x88292d29, 0x88292d29, 0x88292d29, + 0x88292d29, 0x88292d29, 0x88292d29, 0x88292d29, 0x88292d29, 0x88292d29, 0x88292d29, 0x88292d29, + 0x88292d29, 0x88292d29, 0x88292d29, 0x88292d29, 0x88292d29, 0x88292d29, 0x88292d29, 0x88292d29, + 0x88312d31, 0x88312d31, 0x88312d31, 0x88312d31, 0x88312d31, 0x88312d31, 0x88312d31, 0x88312d31, + 0x88313131, 0x88313131, 0x88313131, 0x88313131, 0x88313131, 0x88313131, 0x88313131, 0x88313131, + 0x88313131, 0x88313131, 0x88313131, 0x88313131, 0x88313531, 0x88313531, 0x88313531, 0x88313531, + 0x88313531, 0x88313531, 0x88313531, 0x88313531, 0x88313531, 0x88313531, 0x88313531, 0x88313531, + 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, + 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, + 0x883a393a, 0x883a393a, 0x883a393a, 0x883a393a, 0x88313531, 0x88313531, 0x88313531, 0x88313531, + 0x88313531, 0x77313531, 0x77313531, 0x88313531, 0x88313131, 0x77313131, 0x77313131, 0x77313131, + 0x77292d29, 0x77292d29, 0x77292d29, 0x77292d29, 0x77292829, 0x77292829, 0x77292829, 0x77292829, + 0x77212021, 0x77212021, 0x77212021, 0x77212021, 0x77191819, 0x77191819, 0x77191819, 0x66101010, + 0x66101010, 0x660b0b0b, 0x660b0b0b, 0x660b0b0b, 0x55080808, 0x55080808, 0x55050505, 0x44050505, + 0x33000400, 0x33000400, 0x22000400, 0x22000300, 0x11000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00080408, 0x22080408, 0x44080408, 0x55080408, + 0x66191419, 0x66191419, 0x77423f42, 0x77423f42, 0x77424542, 0x77424542, 0x77606260, 0x77606260, + 0x77636163, 0x77636163, 0x88636163, 0x88636163, 0x886b696b, 0x886b696b, 0x886b696b, 0x886b696b, + 0x99737173, 0x99737173, 0x99737173, 0x99737173, 0x9973797b, 0x9973797b, 0x9973797b, 0x9973797b, + 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, + 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, + 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, + 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b797b, 0xaa7b7573, 0xaa7b7573, 0xaa7b7573, 0xaa7b7573, + 0xaa737573, 0xaa737573, 0xaa737573, 0xaa737573, 0xaa737573, 0xaa737573, 0xaa737573, 0xaa737573, + 0xaa737573, 0xaa737573, 0xaa737573, 0xaa737573, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, + 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, + 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, + 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, + 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, + 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b696b, 0xaa6b696b, 0xaa6b696b, 0xaa6b696b, + 0xaa6b696b, 0xaa6b696b, 0xaa6b696b, 0xaa6b696b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, + 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, + 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, + 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, + 0xaa736d73, 0xaa736d73, 0xaa736d73, 0xaa736d73, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, + 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, + 0xaa737573, 0xaa737573, 0xbb737573, 0xbb737573, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, + 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, + 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, + 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b696b, 0xaa6b696b, 0xaa6b696b, 0xaa6b696b, + 0xaa6b696b, 0xaa6b696b, 0xaa6b696b, 0xaa6b696b, 0xaa636563, 0xaa636563, 0xaa636563, 0xaa636563, + 0x995a5d5a, 0x995a5d5a, 0x995a5d5a, 0x995a5d5a, 0x99525552, 0x99525552, 0x99525552, 0x88525552, + 0x88424542, 0x88424542, 0x88424542, 0x88424542, 0x88312d31, 0x88312d31, 0x88312d31, 0x88312d31, + 0x88191c19, 0x77191c19, 0x77191c19, 0x77191c19, 0x66080c08, 0x44080c08, 0x33080c08, 0x22080c08, + 0x11080408, 0x00080408, 0x00080408, 0x00080408, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x55080408, 0x77343134, 0x88605d60, 0x88605d60, + 0x886b6b6b, 0x886b6b6b, 0x886b6b6b, 0x996b6b6b, 0x997e807e, 0x997e807e, 0xaa7e807e, 0xaa7e807e, + 0xaa898a89, 0xaa898a89, 0xaa898a89, 0xaa898a89, 0xbb8c8f8c, 0xbb8c8f8c, 0xbb8c8f8c, 0xbb8c8f8c, + 0xbb949494, 0xbb949494, 0xbb949494, 0xcc949494, 0xcc949797, 0xcc949797, 0xcc949797, 0xcc949797, + 0xcc979a97, 0xcc979a97, 0xcc979a97, 0xcc979a97, 0xcc9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, + 0xcc9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, + 0xcc9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, + 0xcc9c9d9c, 0xcc9c9d9c, 0xcc9c9d9c, 0xcc9c9d9c, 0xcc9c9b9a, 0xcc9c9b9a, 0xcc9c9b9a, 0xcc9c9b9a, + 0xcc9a9b9a, 0xcc9a9b9a, 0xcc9a9b9a, 0xcc9a9b9a, 0xcc9a9b9a, 0xcc9a9b9a, 0xcc9a9b9a, 0xcc9a9b9a, + 0xcc9a9b9a, 0xcc9a9b9a, 0xcc9a9b9a, 0xcc9a9b9a, 0xcc9f9d9f, 0xcc9f9d9f, 0xcc9f9d9f, 0xcc9f9d9f, + 0xcc9f9d9f, 0xcc9f9d9f, 0xcc9f9d9f, 0xcc9f9d9f, 0xcc9f9d9f, 0xcc9f9d9f, 0xcc9f9d9f, 0xcc9f9d9f, + 0xcc9f9d9f, 0xcc9f9d9f, 0xcc9f9d9f, 0xcc9f9d9f, 0xcc9f9d9f, 0xcc9f9d9f, 0xcc9f9d9f, 0xcc9f9d9f, + 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, + 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, + 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9d9c, 0xcc9c9d9c, 0xcc9c9d9c, 0xcc9c9d9c, + 0xcc9c9d9c, 0xcc9c9d9c, 0xcc9c9d9c, 0xcc9c9d9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, + 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, + 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, + 0xcc9c9b9c, 0xcc9c9b9c, 0xcc9c9b9c, 0xcc9c9b9c, 0xcc9c9b9c, 0xcc9c9b9c, 0xcc9c9b9c, 0xcc9c9b9c, + 0xcc9f9b9f, 0xcc9f9b9f, 0xcc9f9b9f, 0xcc9f9b9f, 0xcc9f9d9f, 0xcc9f9d9f, 0xcc9f9d9f, 0xcc9f9d9f, + 0xcc9a9d9f, 0xcc9a9d9f, 0xcc9a9d9f, 0xcc9a9d9f, 0xcc9a9a9a, 0xcc9a9a9a, 0xcc9a9a9a, 0xcc9a9a9a, + 0xcc9a9b9a, 0xcc9a9b9a, 0xcc9a9b9a, 0xcc9a9b9a, 0xcc9a9a9a, 0xcc9a9a9a, 0xcc9a9a9a, 0xcc9a9a9a, + 0xcc9a979a, 0xcc9a979a, 0xcc9a979a, 0xcc9a979a, 0xcc9a979a, 0xcc9a979a, 0xcc9a979a, 0xcc9a979a, + 0xcc9a979a, 0xcc9a979a, 0xcc9a979a, 0xcc9a979a, 0xcc94979a, 0xcc94979a, 0xcc94979a, 0xcc94979a, + 0xcc979697, 0xcc979697, 0xcc979697, 0xcc979697, 0xcc919291, 0xcc919291, 0xcc919291, 0xcc919291, + 0xcc919291, 0xcc919291, 0xcc919291, 0xcc919291, 0xcc8f908f, 0xcc8f908f, 0xcc8f908f, 0xcc8f908f, + 0xcc8c8b8c, 0xcc8c8b8c, 0xcc8c8b8c, 0xcc8c8b8c, 0xbb848884, 0xbb848884, 0xbb848884, 0xbb848884, + 0xbb7e7d7e, 0xbb7e7d7e, 0xbb7e7d7e, 0xbb7e7d7e, 0xaa737073, 0xaa737073, 0xaa737073, 0xaa737073, + 0xaa6b6b6b, 0x996b6b6b, 0x99424342, 0x99424342, 0x99373937, 0x88373937, 0x77373937, 0x66080c08, + 0x66080408, 0x22080408, 0x00080408, 0x00080408, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x33000000, 0x77262626, 0x88605d60, 0x88605d60, 0x998c8a8c, 0xaa8c8a8c, + 0xaa949694, 0xaa949694, 0xbb949694, 0xbb949694, 0xbb9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, + 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9ca29c, 0xcc9ca29c, 0xdd9ca29c, 0xdd9ca29c, + 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, + 0xdda5aaa5, 0xdda5aaa5, 0xdda5aaa5, 0xdda5aaa5, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, + 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, + 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, + 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, + 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, + 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddadb2b5, 0xddadb2b5, 0xddadb2b5, 0xddadb2b5, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, + 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, + 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, + 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xdda5aaad, 0xdda5aaad, 0xdda5aaad, 0xdda5aaad, + 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, + 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, + 0xdda5a2a5, 0xdda5a2a5, 0xdda5a2a5, 0xdda5a2a5, 0xdd9ca29c, 0xdd9ca29c, 0xdd9ca29c, 0xdd9ca29c, + 0xdd9c9a9c, 0xdd9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, 0xcc949294, 0xcc949294, 0xcc949294, 0xcc949294, + 0xcc949294, 0xcc949294, 0xcc949294, 0xbb6b6b6b, 0xbb656565, 0xbb656565, 0xaa656565, 0xaa656565, + 0xbb656265, 0x77373337, 0x44080408, 0x11080408, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x33000000, 0x884d4c4d, 0x99737173, 0xaa8c8a8c, 0xaa8c8a8c, 0xcc8c8a8c, 0xcc8c8a8c, + 0xcc949694, 0xcc949694, 0xdd949694, 0xdd949694, 0xdd9c9e9c, 0xdd9c9e9c, 0xdd9c9e9c, 0xdd9c9e9c, + 0xdd9c9e9c, 0xdd9c9e9c, 0xdd9c9e9c, 0xdd9c9e9c, 0xdd9ca29c, 0xdd9ca29c, 0xdd9ca29c, 0xdd9ca29c, + 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, + 0xdda5aaa5, 0xdda5aaa5, 0xdda5aaa5, 0xdda5aaa5, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, + 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, + 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, + 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, + 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, + 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddadb2b5, 0xddadb2b5, 0xddadb2b5, 0xddadb2b5, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, + 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, + 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, + 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xdda5aaad, 0xdda5aaad, 0xdda5aaad, 0xdda5aaad, + 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xddadaaad, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, + 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, + 0xdda5a2a5, 0xdda5a2a5, 0xdda5a2a5, 0xdda5a2a5, 0xdd9ca29c, 0xdd9ca29c, 0xdd9ca29c, 0xdd9ca29c, + 0xdd9c9a9c, 0xdd9c9a9c, 0xdd9c9a9c, 0xdd9c9a9c, 0xdd949294, 0xdd949294, 0xdd949294, 0xdd949294, + 0xdd949294, 0xdd949294, 0xdd949294, 0xdd949294, 0xdd949294, 0xcc949294, 0xcc949294, 0xcc949294, + 0xee949294, 0xbb656265, 0x99373337, 0x55080408, 0x11080808, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11100c10, 0x773c393a, 0x9994928c, 0xbb94928c, 0xcc8f908f, 0xcc8f908f, 0xdd9ca29c, 0xdd9ca29c, + 0xdda5a1a2, 0xdda5a1a2, 0xdda5a1a2, 0xdda5a1a2, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, + 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, + 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, + 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, + 0xdda7a6a7, 0xddb5b2b5, 0xddb5b2b5, 0xdda7a6a7, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, + 0xddb5aead, 0xddb5aead, 0xddb5aead, 0xddb5aead, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, + 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, + 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, + 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb2b3b2, 0xddb2b3b2, 0xddb2b3b2, 0xddb2b3b2, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xdda7a6a7, + 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, + 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, + 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, + 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdd9a9a9a, 0xdd9a9a9a, 0xdd9a9a9a, + 0xdd9a9a9a, 0xdd9a9a9a, 0xdd9a9a9a, 0xdd9a9a9a, 0xdd9a979a, 0xdd9a979a, 0xdd9a979a, 0xdd9a979a, + 0xeea5a2a5, 0xdd8c8b8c, 0xbb8c8b8c, 0xaa5a5d5a, 0x662c2d2c, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x44100c10, 0x99686563, 0xbb94928c, 0xcc94928c, 0xdd9ca29c, 0xcc8f908f, 0xdd9ca29c, 0xdd9ca29c, + 0xdda5a1a2, 0xdda5a1a2, 0xdda5a1a2, 0xdda5a1a2, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, + 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, + 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, + 0xddb5b2b5, 0xddb5b2b5, 0xdda7a6a7, 0xdda7a6a7, 0xddb5b2b5, 0xdda7a6a7, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, + 0xddb5aead, 0xddb5aead, 0xddb5aead, 0xddb5aead, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, + 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, + 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, + 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb2b3b2, 0xddb2b3b2, 0xddb2b3b2, 0xddb2b3b2, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xdda7a6a7, 0xddb5b2b5, + 0xddb5b2b5, 0xddb5b2b5, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, + 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a9a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, + 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdda7a6a7, 0xdd9a9a9a, + 0xdd9a9a9a, 0xdd9a9a9a, 0xdd9a9a9a, 0xdd9a9a9a, 0xdd9a979a, 0xdd9a979a, 0xdd9a979a, 0xdd9a979a, + 0xeea5a2a5, 0xeea5a2a5, 0xdd8c8b8c, 0xcc8c8b8c, 0xbb585958, 0x332c2d2c, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00050405, + 0x773c393a, 0xbb94928c, 0xcc94928c, 0xdd94928c, 0xdd9ca29c, 0xdd817f81, 0xff736d73, 0xff817f81, + 0xff847d7b, 0xff948f8f, 0xff948f8f, 0xff948f8f, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c928c, 0xff8c928c, 0xff8c928c, 0xff8c928c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c928c, 0xff8c928c, 0xff8c928c, 0xff8c928c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8a8c, 0xff8c8a8c, 0xff8c8a8c, 0xff8c8a8c, + 0xffa5a2a5, 0xeea5a2a5, 0xdda5a2a5, 0xdda5a2a5, 0xdd848684, 0x77585958, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11100c10, + 0x88686563, 0xcc94928c, 0xdd94928c, 0xdd94928c, 0xdd9ca29c, 0xdd817f81, 0xff817f81, 0xff8f908f, + 0xffa5a1a2, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, + 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, + 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, + 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, + 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, + 0xffb5aead, 0xffb5aead, 0xffb5aead, 0xffb5aead, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, + 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, + 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, + 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, + 0xffb5bab5, 0xffb5bab5, 0xffb5bab5, 0xffb5bab5, 0xffb5bab5, 0xffb5bab5, 0xffb5bab5, 0xffb5bab5, + 0xffbdbabd, 0xffbdbabd, 0xffbdbabd, 0xffbdbabd, 0xffbdbabd, 0xffbdbabd, 0xffbdbabd, 0xffbdbabd, + 0xffbdbabd, 0xffbdbabd, 0xffbdbabd, 0xffbdbabd, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, + 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, + 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, + 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, + 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, + 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, + 0xffbdbabd, 0xffbdbabd, 0xffbdbabd, 0xffbdbabd, 0xffb5bab5, 0xffb5bab5, 0xffb5bab5, 0xffb5bab5, + 0xffb5bab5, 0xffb5bab5, 0xffb5bab5, 0xffb5bab5, 0xffb2b3b2, 0xffb2b3b2, 0xffb2b3b2, 0xffb2b3b2, + 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, + 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, + 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, + 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, + 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, + 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, + 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, + 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, + 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffb5b2b5, 0xffa7a5a7, + 0xffa5a2a5, 0xeea5a2a5, 0xdda5a2a5, 0xdda5a2a5, 0xdd848684, 0xaa585958, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22191419, + 0x99636163, 0xcc898a89, 0xdd9c9e9c, 0xdd9c9e9c, 0xdda7a6a7, 0xdd949294, 0xff949294, 0xffa7a6a7, + 0xffbdbebd, 0xffd0d2d0, 0xffd0d2d0, 0xffd0d2d0, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffd0d2d0, 0xffd0d2d0, 0xffd0d2d0, 0xffbdbebd, + 0xffb2b2b2, 0xee9c9a9c, 0xdd9c9a9c, 0xdd9c9a9c, 0xdd9c9e9c, 0xbb686968, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x33191419, + 0xaa636163, 0xdd898a89, 0xdd9c9e9c, 0xdd9c9e9c, 0xdda7a6a7, 0xdd949294, 0xffa7a6a7, 0xffbababa, + 0xffd0d2d0, 0xffe4e7e4, 0xffe4e7e4, 0xffe4e7e4, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, + 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffeff0ef, 0xffe4e7e4, 0xffe4e7e4, 0xffe4e7e4, 0xffd0d2d0, + 0xffb2b2b2, 0xeea7a6a7, 0xdd9c9a9c, 0xdd9c9a9c, 0xdd9c9e9c, 0xcc686968, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x33100d10, + 0xaa636163, 0xdd898a89, 0xdd9c9e9c, 0xdd9c9e9c, 0xdda7a6a7, 0xdd949294, 0xffa7a6a7, 0xffcecece, + 0xffe4e7e4, 0xfff7fbf7, 0xfff7fbf7, 0xfff7fbf7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7fbf7, 0xfff7fbf7, 0xfff7fbf7, 0xffe4e7e4, + 0xffbdbebd, 0xeea7a6a7, 0xdd9c9a9c, 0xdd9c9a9c, 0xdd9c9e9c, 0xcc686968, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x33100d10, + 0xaa636163, 0xdd898a89, 0xdd9c9e9c, 0xdd9c9e9c, 0xdda7a6a7, 0xdd949294, 0xffbababa, 0xffcecece, + 0xffe4e7e4, 0xfff7fbf7, 0xfff7fbf7, 0xfff7fbf7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7fbf7, 0xfff7fbf7, 0xfff7fbf7, 0xffe4e7e4, + 0xffbdbebd, 0xeea7a6a7, 0xdd9c9a9c, 0xdd9c9a9c, 0xdd9c9e9c, 0xcc9c9e9c, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x33101010, + 0xaa4a5152, 0xdd868a89, 0xdda5a6a5, 0xdda5a6a5, 0xddadadad, 0xdd9c9a9c, 0xffadadad, 0xffced2ce, + 0xffe6ebe6, 0xfff7f8f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7f8f7, 0xffe6ebe6, + 0xffbdbebd, 0xeea7a9a7, 0xdd9c9e9c, 0xdd9c9e9c, 0xdda5aaa5, 0xcc6e736e, 0x00000400, 0x00000300, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22191819, + 0x994a5152, 0xdd868a89, 0xdda5a6a5, 0xdda5a6a5, 0xddadadad, 0xdd9c9a9c, 0xffadadad, 0xffced2ce, + 0xffe6ebe6, 0xfff7f8f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7f8f7, 0xffe6ebe6, + 0xffbdbebd, 0xeea7a9a7, 0xdd9c9e9c, 0xdd9c9e9c, 0xdda5aaa5, 0xbb6e736e, 0x00000400, 0x00000400, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22101010, + 0x994a5152, 0xcc868a89, 0xdda5a6a5, 0xdda5a6a5, 0xddadadad, 0xdd9c9a9c, 0xffadadad, 0xffced2ce, + 0xffe6ebe6, 0xfff7f8f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7f8f7, 0xffe6ebe6, + 0xffbdbebd, 0xeea7a9a7, 0xdd9c9e9c, 0xdd9c9e9c, 0xdda5aaa5, 0xbb6e736e, 0x00000400, 0x00000400, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22101010, + 0x994a5152, 0xcc868a89, 0xdda5a6a5, 0xdda5a6a5, 0xddadadad, 0xdd9c9a9c, 0xffadadad, 0xffced2ce, + 0xffe6ebe6, 0xfff7f8f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7f8f7, 0xffe6ebe6, + 0xffbdbebd, 0xeea7a9a7, 0xdd9c9e9c, 0xdd9c9e9c, 0xdda5aaa5, 0xbb6e736e, 0x00000400, 0x00000400, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22101010, + 0x884a494a, 0xcc868486, 0xdda5a2a5, 0xdda5a2a5, 0xddadaead, 0xdd9c9a9c, 0xffadaead, 0xffced7ce, + 0xffe6ebe6, 0xfff7f8f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7f8f7, 0xffe6ebe6, + 0xffc5c2c5, 0xeeaaaaaa, 0xdd9c9e9c, 0xdd9c9e9c, 0xdda5aaa5, 0xaa6e716e, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11101010, + 0x884a494a, 0xcc868486, 0xdda5a2a5, 0xdda5a2a5, 0xddadaead, 0xdd9c9a9c, 0xffadaead, 0xffced7ce, + 0xffe6ebe6, 0xfff7f8f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7f8f7, 0xffe6ebe6, + 0xffc5c2c5, 0xeeaaaaaa, 0xdd9c9e9c, 0xdd9c9e9c, 0xdda5aaa5, 0xaa6e716e, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22101010, + 0x884a494a, 0xcca5a2a5, 0xdda5a2a5, 0xdda5a2a5, 0xddadaead, 0xdd9c9a9c, 0xffadaead, 0xffced7ce, + 0xffe6ebe6, 0xfff7f8f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7f8f7, 0xffe6ebe6, + 0xffc5c2c5, 0xeeaaaaaa, 0xdd9c9e9c, 0xdd9c9e9c, 0xdda5aaa5, 0xaa6e716e, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22101010, + 0x994a494a, 0xcca5a2a5, 0xdda5a2a5, 0xdda5a2a5, 0xddadaead, 0xdd9c9a9c, 0xffadaead, 0xffced7ce, + 0xffe6ebe6, 0xfff7f8f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7f8f7, 0xffe6ebe6, + 0xffc5c2c5, 0xeeaaaaaa, 0xdd9c9e9c, 0xddaaaaaa, 0xdda5aaa5, 0xaa6e716e, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22101310, + 0x995a595a, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xddafaeaf, 0xdd9c9a9c, 0xffafaeaf, 0xffd6d7d6, + 0xffe6ebe6, 0xfff7f8f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7f8f7, 0xffe6ebe6, + 0xffc5c2c5, 0xeeafadaf, 0xdda5a2a5, 0xdda5a2a5, 0xddb5b6b5, 0xbb797b79, 0x00000400, 0x00000400, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22101310, + 0x995a595a, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xddafaeaf, 0xdd9c9a9c, 0xffafaeaf, 0xffd6d7d6, + 0xffe6ebe6, 0xfff7f8f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7f8f7, 0xffe6ebe6, + 0xffc5c2c5, 0xeeafadaf, 0xdda5a2a5, 0xdda5a2a5, 0xddb5b6b5, 0xbb797b79, 0x00000400, 0x00000400, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22101310, + 0xaa5a595a, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xddafaeaf, 0xdd9c9a9c, 0xffafaeaf, 0xffd6d7d6, + 0xffe6ebe6, 0xfff7f8f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7f8f7, 0xffe6ebe6, + 0xffc5c2c5, 0xeeafadaf, 0xdda5a2a5, 0xddafadaf, 0xddb5b6b5, 0xcc797b79, 0x00000400, 0x00000400, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x33101310, + 0xaa737373, 0xdda5a6a5, 0xdda5a6a5, 0xdda5a6a5, 0xddafaeaf, 0xdd9c9a9c, 0xffafaeaf, 0xffd6d7d6, + 0xffe6ebe6, 0xfff7f8f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff7f8f7, 0xffe6ebe6, + 0xffc5c2c5, 0xeeafadaf, 0xdda5a2a5, 0xddafadaf, 0xddb5b6b5, 0xcc797b79, 0x00000400, 0x00000400, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x33101010, + 0xaa606060, 0xddada6ad, 0xddada6ad, 0xddada6ad, 0xddbab7ba, 0xdd949294, 0xffbab7ba, 0xffcecace, + 0xffeff0ef, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffeff0ef, + 0xffc5c2c5, 0xeea5aaa5, 0xdda5aaa5, 0xdda5aaa5, 0xddadaeb5, 0xcc737479, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x33080808, + 0xaa606060, 0xddada6ad, 0xddada6ad, 0xddada6ad, 0xddbab7ba, 0xdd949294, 0xffbab7ba, 0xffcecace, + 0xffeff0ef, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffeff0ef, + 0xffc5c2c5, 0xeea5aaa5, 0xdda5aaa5, 0xdda5aaa5, 0xddadaeb5, 0xbb737479, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x33191819, + 0x99606060, 0xccada6ad, 0xddada6ad, 0xddada6ad, 0xddbab7ba, 0xdd949294, 0xffa7a5a7, 0xffcecace, + 0xffdee1de, 0xffeff0ef, 0xffffffff, 0xffffffff, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, + 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xfff7f8f7, 0xffffffff, 0xffffffff, 0xffeff0ef, 0xffdee1de, + 0xffc5c2c5, 0xeea5aaa5, 0xdda5aaa5, 0xdda5aaa5, 0xddadaeb5, 0xbb737479, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22101010, + 0x883a3d3a, 0xbb868386, 0xddada6ad, 0xddada6ad, 0xddbab7ba, 0xdd949294, 0xffa7a5a7, 0xffbab7ba, + 0xffced2ce, 0xffdee1de, 0xffeff0ef, 0xffeff0ef, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffeff0ef, 0xffeff0ef, 0xffdee1de, 0xffced2ce, + 0xffbababa, 0xeea5aaa5, 0xdda5aaa5, 0xdda5aaa5, 0xddadaeb5, 0x99737479, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11080808, + 0x773a3a3a, 0xaa6b6c6b, 0xcc9c9e9c, 0xdd9c9e9c, 0xddadaaad, 0xdd949294, 0xff949294, 0xffadaaad, + 0xffbdbebd, 0xffcecece, 0xffcecece, 0xffcecece, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced0ce, 0xffced0ce, 0xffced0ce, 0xffced0ce, + 0xffced0ce, 0xffced0ce, 0xffced0ce, 0xffced0ce, 0xffced1d3, 0xffced1d3, 0xffced1d3, 0xffced1d3, + 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, 0xffd0d1d0, + 0xffced1ce, 0xffced1ce, 0xffced1ce, 0xffced1ce, 0xffced0ce, 0xffced0ce, 0xffced0ce, 0xffced0ce, + 0xffced0ce, 0xffced0ce, 0xffced0ce, 0xffced0ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, + 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffced2ce, 0xffb8bcb8, + 0xffadaead, 0xeeadaead, 0xddadaead, 0xddadaead, 0xcc848a84, 0x772c2e2c, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x66080808, 0x883a3a3a, 0xaa6b6c6b, 0xcc9c9e9c, 0xddadaaad, 0xccadaaad, 0xddadaaad, 0xddadaaad, + 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddb2b2b2, 0xddb2b2b2, 0xddb2b2b2, 0xddb2b2b2, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, + 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddc3c2c3, 0xddc3c2c3, 0xddc3c2c3, 0xddc3c2c3, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, + 0xddc5c2c5, 0xddc5c2c5, 0xddc8c8c8, 0xddc8c8c8, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, + 0xddc5c6c5, 0xddc5c6c5, 0xddc8cac8, 0xddc8cac8, 0xddcecace, 0xddcecace, 0xddcecace, 0xddcecace, + 0xddcecdce, 0xddcecdce, 0xddcecdce, 0xddcecdce, 0xddcecece, 0xddcecece, 0xddcecece, 0xddcecece, + 0xddd0d1d0, 0xddd3d0d3, 0xddd0d1d0, 0xddd0d1d0, 0xddd6d2d6, 0xddd6d2d6, 0xddd6d2d6, 0xddd6d2d6, + 0xddd0d4d0, 0xddd0d4d0, 0xddd0d4d0, 0xddd0d4d0, 0xddd0d4d0, 0xddd0d4d0, 0xddd6d7d6, 0xddd6d7d6, + 0xddd3d8d3, 0xddd3d8d3, 0xddd3d8d3, 0xddd3d8d3, 0xddd9d8d9, 0xddd9d8d9, 0xddd9d8d9, 0xddd9d8d9, + 0xddd9d8d9, 0xddd9d8d9, 0xddd9d8d9, 0xddd9d8d9, 0xddd3d7d3, 0xddd9dbd9, 0xddd9dbd9, 0xddd9dbd9, + 0xddd9d8d9, 0xdddedbde, 0xddd9d8d9, 0xddd9d8d9, 0xddd9dbd9, 0xddd9dbd9, 0xddd9dbd9, 0xddd9dbd9, + 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xddd9dbd9, 0xddd9dbd9, 0xddd9dbd9, 0xddd9dbd9, + 0xdddedbde, 0xdddedbde, 0xddd9d8d9, 0xddd9d8d9, 0xddd9d8d9, 0xddd9d8d9, 0xddd9d8d9, 0xddd9d8d9, + 0xddd9d8d9, 0xddd9d8d9, 0xddd9d8d9, 0xddd9d8d9, 0xddd3d8d3, 0xddd3d8d3, 0xddd3d8d3, 0xddd3d8d3, + 0xddd6d7d6, 0xddd6d7d6, 0xddd6d7d6, 0xddd3d5d3, 0xddd3d5d3, 0xddd0d4d0, 0xddd0d4d0, 0xddd0d4d0, + 0xddd3d5d3, 0xddd3d5d3, 0xddced2ce, 0xddced2ce, 0xddd0d1d0, 0xddd0d1d0, 0xddd0d1d0, 0xddd0d1d0, + 0xddcecece, 0xddced0ce, 0xddcecece, 0xddcecece, 0xddcecdce, 0xddcecdce, 0xddcecdce, 0xddcecdce, + 0xddcecdce, 0xddcecdce, 0xddcecace, 0xddcecace, 0xddcecace, 0xddcecace, 0xddcecace, 0xddcecace, + 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, + 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddadb2b5, 0xddadb2b5, 0xddadb2b5, 0xddadb2b5, + 0xddadadad, 0xddadadad, 0xddadadad, 0xddadadad, 0xdda2a5a2, 0xdda2a5a2, 0xdda2a5a2, 0xdda2a5a2, + 0xeeadaead, 0xeeadaead, 0xcc818381, 0xbb818381, 0xaa585c58, 0x442c2e2c, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33080808, 0x883a3a3a, 0x883a3a3a, 0xaa6b6c6b, 0xcc949294, 0xbb949294, 0xccadaaad, 0xddadaaad, + 0xddadaead, 0xddadaead, 0xddadaead, 0xddadaead, 0xddb2b2b2, 0xddb2b2b2, 0xddb2b2b2, 0xddb2b2b2, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, + 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddc3c2c3, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddc3c2c3, 0xddc3c2c3, 0xddc3c2c3, 0xddc3c2c3, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddc8c8c8, + 0xddc8c8c8, 0xddc8c8c8, 0xddc8c8c8, 0xddc8c8c8, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc8cac8, + 0xddc8cac8, 0xddc8cac8, 0xddc8cac8, 0xddcbcecb, 0xddcecdce, 0xddcecdce, 0xddcecdce, 0xddcecdce, + 0xddcecdce, 0xddcecdce, 0xddcecdce, 0xddcecdce, 0xddced0d0, 0xddced0d0, 0xddced0d0, 0xddced2d6, + 0xddced2ce, 0xddd0d1d0, 0xddd0d1d0, 0xddd0d1d0, 0xddd6d2d6, 0xddd6d2d6, 0xddd6d2d6, 0xddd3d4d3, + 0xddd3d5d3, 0xddd3d5d3, 0xddd3d5d3, 0xddd6d7d6, 0xddd6d7d6, 0xddd6d7d6, 0xddd6d7d6, 0xddd6d7d6, + 0xddd3d8d3, 0xddd3d8d3, 0xddd3d8d3, 0xddd6dbd6, 0xddd9d8d9, 0xddd9d8d9, 0xddd9d8d9, 0xddd9d8d9, + 0xddd9d8d9, 0xddd9d8d9, 0xdddedbde, 0xdddedbde, 0xddd9dbd9, 0xddd9dbd9, 0xddd9dbd9, 0xddd9dbd9, + 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xddd9dbd9, 0xddd9dbd9, 0xddd9dbd9, 0xddd9dbd9, + 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xddd9dbd9, 0xddd9dbd9, 0xddd9dbd9, 0xddd9dbd9, + 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xddd9d8d9, 0xddd9d8d9, + 0xddd9d8d9, 0xddd9d8d9, 0xddd9d8d9, 0xddd9d8d9, 0xddd3d8d3, 0xddd6dbd6, 0xddd3d8d3, 0xddd6dbd6, + 0xddd6d7d6, 0xddd6d7d6, 0xddd6d7d6, 0xddd6d7d6, 0xddd6d7d6, 0xddd3d5d3, 0xddd3d5d3, 0xddd3d5d3, + 0xddd3d5d3, 0xddd6d7d6, 0xddd3d5d3, 0xddd0d4d0, 0xddd0d1d0, 0xddd0d1d0, 0xddd0d1d0, 0xddd0d1d0, + 0xddced0ce, 0xddced0ce, 0xddced0ce, 0xddced0ce, 0xddcecdce, 0xddcecdce, 0xddcecdce, 0xddcecdce, + 0xddcecdce, 0xddcecdce, 0xddcecdce, 0xddcecace, 0xddcecace, 0xddcecace, 0xddcecace, 0xddcec6ce, + 0xddc8cac8, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, + 0xddc8c8c8, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, + 0xddc3c5c3, 0xddbfc0bf, 0xddc2c4c2, 0xddbebfbe, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddadb2b5, 0xddadb2b5, 0xddadb2b5, 0xddadb2b5, + 0xddadadad, 0xddadadad, 0xddadadad, 0xddadadad, 0xdda2a5a2, 0xdda2a5a2, 0xdda2a5a2, 0xdda2a5a2, + 0xeeadaead, 0xdd818381, 0xbb818381, 0x99555855, 0x772c2e2c, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11080808, 0x66080808, 0x773a3a3a, 0x773a3a3a, 0x99636163, 0x997b797b, 0xbb949294, 0xbb949294, + 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcc9c9e9c, 0xcca5a2a5, 0xddb2b2b2, 0xddb2b2b2, 0xddb2b2b2, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, + 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddc3c2c3, 0xddc3c2c3, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddc3c5c3, 0xddc3c5c3, + 0xddc3c2c3, 0xddc3c2c3, 0xddc3c2c3, 0xddc3c2c3, 0xddc5c2c5, 0xddc8c8c8, 0xddc5c2c5, 0xddc8c8c8, + 0xddc8c8c8, 0xddc8c8c8, 0xddc8c8c8, 0xddc8c8c8, 0xddc8cac8, 0xddc5c6c5, 0xddc8cac8, 0xddcbcecb, + 0xddcbcecb, 0xddc8cac8, 0xddc8cac8, 0xddcbcecb, 0xddcecdce, 0xddcecdce, 0xddcecdce, 0xddcecdce, + 0xddcecdce, 0xddcecdce, 0xddcecdce, 0xddcecdce, 0xddced0d0, 0xddced1d3, 0xddced1d3, 0xddced2d6, + 0xddced2ce, 0xddced2ce, 0xddced2ce, 0xddced2ce, 0xddd3d4d3, 0xddd3d4d3, 0xddd3d4d3, 0xddd0d5d0, + 0xddd6d7d6, 0xddd3d5d3, 0xddd6d7d6, 0xddd6d7d6, 0xddd6d7d6, 0xddd6d7d6, 0xddd6d7d6, 0xddd6d7d6, + 0xddd6dbd6, 0xddd3d8d3, 0xddd6dbd6, 0xddd6dbd6, 0xddd9d8d9, 0xdddedbde, 0xdddedbde, 0xdddedbde, + 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xddd9dbd9, 0xdddedfde, 0xdddedfde, 0xddd9dbd9, + 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xddd9dbd9, 0xddd9dbd9, 0xdddedfde, 0xdddedfde, + 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xddd9dbd9, 0xddd9dbd9, 0xddd9dbd9, 0xdddedfde, + 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xdddedbde, + 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xdddedbde, 0xddd6dbd6, 0xddd6dbd6, 0xddd3d8d3, 0xddd6dbd6, + 0xddd6d7d6, 0xddd6d7d6, 0xddd6d7d6, 0xddd6d7d6, 0xddd6d7d6, 0xddd6d7d6, 0xddd3d5d3, 0xddd6d7d6, + 0xddd3d5d3, 0xddd6d7d6, 0xddd3d5d3, 0xddd0d4d0, 0xddd6d2d6, 0xddd6d2d6, 0xddd0d1d0, 0xddd0d1d0, + 0xddced2ce, 0xddced1ce, 0xddced0ce, 0xddced0ce, 0xddcecdce, 0xddcecdce, 0xddcecdce, 0xddcecdce, + 0xddcecdce, 0xddcecdce, 0xddcecdce, 0xddcecdce, 0xddcecace, 0xddcecace, 0xddcecace, 0xddcecace, + 0xddc8cac8, 0xddc5c6c5, 0xddc8cac8, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, + 0xddc8c8c8, 0xddc8c8c8, 0xddc8c8c8, 0xddc5c3c6, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, + 0xddc4c4c3, 0xddc4c4c3, 0xddc4c4c2, 0xddc1c0c1, 0xddbfc1bf, 0xddbdbebe, 0xddbdbebe, 0xddbdbebd, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, 0xddb5bab5, + 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddb5b2b5, 0xddadb2b5, 0xddadb2b5, 0xddadb2b5, 0xddadb2b5, + 0xddadadad, 0xddadadad, 0xdd9c9a9c, 0xcc9c9a9c, 0xcca2a5a2, 0xcc8c8e8c, 0xcc8c8e8c, 0xcc8c8e8c, + 0xdd818381, 0xaa555855, 0x77292d29, 0x55292d29, 0x22000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x22000000, 0x77101010, 0x77313131, 0x773f3f3f, 0x773f3f3f, 0x885a5d5a, 0x995a5d5a, + 0x99737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa8c8a8c, 0xbb8c8a8c, 0xbb8c8a8c, 0xbb8c8a8c, + 0xcc9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, 0xcc9c9a9c, 0xcca5a6a5, 0xcca5a6a5, 0xcca5a6a5, 0xcca5a6a5, + 0xccadaead, 0xccadaead, 0xccadaead, 0xccadaead, 0xccb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, + 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, 0xddb5b6b5, + 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbabd, 0xddbdbebd, 0xddbdbebd, 0xddbec0bf, 0xddc0c2c1, + 0xddc7cacc, 0xddc8cccd, 0xddc0c3c5, 0xddc2c6c9, 0xddc3c5c7, 0xddc3c3c4, 0xddc0c3c2, 0xddbfc2c0, + 0xddc3c2c3, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, + 0xddc5cac5, 0xddc5cac5, 0xddc5cac5, 0xddc5cac5, 0xddcecace, 0xddcecace, 0xddcecace, 0xddcecace, + 0xddcecace, 0xddcecace, 0xddcecace, 0xddcecace, 0xddcecace, 0xddcecace, 0xddcecace, 0xddcecace, + 0xddcecece, 0xddcecece, 0xddcecece, 0xddcecece, 0xddcecece, 0xddcecece, 0xddcecece, 0xddcecece, + 0xddcecece, 0xddcecece, 0xddcecece, 0xddcecece, 0xddcecece, 0xddcecece, 0xddcecece, 0xddcecece, + 0xddced2ce, 0xddced2ce, 0xddced2ce, 0xddced2ce, 0xddced2ce, 0xddced2ce, 0xddced2ce, 0xddced2ce, + 0xddcecfce, 0xddcfd0cf, 0xddd2d0d0, 0xddd1d3d2, 0xddd7d9d7, 0xddd9dad8, 0xdddbdddb, 0xdddde0de, + 0xdde0e3e2, 0xdde2e2e3, 0xdde2e3e1, 0xdde3e3e4, 0xdde5e3e5, 0xdde4e3e4, 0xdde3e0e2, 0xdddfdcdf, + 0xddd3d1d0, 0xddcecece, 0xddcfd0cf, 0xddd1d0d0, 0xddd5d6d4, 0xddd5d4d5, 0xddd5d4d4, 0xddd2d1d2, + 0xddd0cdd0, 0xddcfccd0, 0xddcecace, 0xddcecace, 0xddcecace, 0xddcecace, 0xddcecace, 0xddcecace, + 0xddc5cace, 0xddc5cace, 0xddc5cace, 0xddc5cace, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, + 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, + 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddc5c2c5, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, 0xddbdbebd, + 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc5c6c5, 0xddc8c8c9, 0xddc9c8ca, 0xddc9cbcb, 0xddcacdcc, + 0xddc9c7c8, 0xddc8c8c9, 0xddcac8ca, 0xddc8c7c9, 0xddc6c7c6, 0xddc2c6c3, 0xddc2c3c1, 0xddc4c7c3, + 0xddb9bab9, 0xddb8b6b8, 0xddb7b7b7, 0xddbababa, 0xddbcbfbc, 0xddbcc0bc, 0xddbdc2bd, 0xddbdc2bd, + 0xddb5b6b5, 0xddb5b6b5, 0xccb5b6b5, 0xccb5b6b5, 0xccadb2ad, 0xccadb2ad, 0xccadb2ad, 0xccadb2ad, + 0xcca5a6a5, 0xcca5a6a5, 0xcca5a6a5, 0xcca5a6a5, 0xcc9c9a94, 0xcc9c9a94, 0xcc9c9a94, 0xcc9c9a94, + 0xbb84827b, 0xbb84827b, 0xbb84827b, 0xaa84827b, 0xaa6b6d6b, 0xaa6b6d6b, 0x996b6d6b, 0x99474947, + 0xbb524d52, 0x661b1a1b, 0x44000000, 0x22000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x22000000, 0x66101010, 0x77242224, 0x663f3f3f, 0x663f3f3f, 0x663f3f3f, + 0x77504e50, 0x77504e50, 0x77504e50, 0x77504e50, 0x88656565, 0x88656565, 0x88656565, 0x99656565, + 0x99767476, 0x99767476, 0x99767476, 0xaa767476, 0xaa7e7f7e, 0xaa7e7f7e, 0xaa7e7f7e, 0xaa7e7f7e, + 0xaa868786, 0xaa868786, 0xbb868786, 0xbb868786, 0xbb8c8e8c, 0xbb8c8e8c, 0xbb8c8e8c, 0xbb8c8e8c, + 0xbb949494, 0xbb949494, 0xbb949494, 0xbb949494, 0xcc9c989c, 0xcc9c989c, 0xcc9c989c, 0xcc9c989c, + 0xccb5b6b5, 0xccb5b6b5, 0xccb5b6b5, 0xccb5b6b5, 0xccb5b6b5, 0xccb5b6b5, 0xccb5b6b5, 0xccb5b6b5, + 0xccbdbabd, 0xccbdbabd, 0xccbdbabd, 0xccbdbabd, 0xccbdbebd, 0xccbdbebd, 0xccbcbdbc, 0xccb9baba, + 0xccb1b3b4, 0xccb2b4b4, 0xccb2b5b5, 0xccb3b5b6, 0xccb1b4b6, 0xccb3b5b6, 0xccb4b8b8, 0xccb7b9b9, + 0xccc0c0c2, 0xccc5c2c5, 0xccc5c2c5, 0xccc5c2c5, 0xccbdbebd, 0xccbdbebd, 0xccbdbebd, 0xccbdbebd, + 0xccbdbebd, 0xccbdbebd, 0xccbdbebd, 0xccbdbebd, 0xccc5c6c5, 0xccc5c6c5, 0xccc5c6c5, 0xccc5c6c5, + 0xccc5cac5, 0xccc5cac5, 0xccc5cac5, 0xccc5cac5, 0xcccecace, 0xcccecace, 0xcccecace, 0xcccecace, + 0xcccecace, 0xcccecace, 0xcccecace, 0xcccecace, 0xcccecace, 0xcccecace, 0xcccecace, 0xcccecace, + 0xcccecece, 0xcccecece, 0xcccecece, 0xcccecece, 0xcccecece, 0xcccecece, 0xcccecece, 0xcccecece, + 0xcccecece, 0xcccecece, 0xcccecece, 0xcccecece, 0xcccecece, 0xcccecece, 0xcccecece, 0xcccecece, + 0xccced2ce, 0xccced2ce, 0xccced2ce, 0xccced2ce, 0xccced2ce, 0xccced2ce, 0xccced2ce, 0xccced2ce, + 0xcccecfce, 0xcccdcecd, 0xcccdcdcd, 0xcccbcbca, 0xccc7c8c7, 0xccc3c5c5, 0xccc3c4c4, 0xccc2c3c2, + 0xccbec1bf, 0xccbbbdbc, 0xccb7b8b6, 0xccb0b2b0, 0xccaeb1af, 0xccb0b1b0, 0xccb5b4b4, 0xccbcbabb, + 0xcca3a6a3, 0xccb8bab7, 0xccc9c9c7, 0xccc9c7c8, 0xccacacac, 0xccb5b3b7, 0xccb8b5b7, 0xccb7b5b5, + 0xccb0aeb1, 0xccb7b6b5, 0xcccecace, 0xcccecace, 0xcccecace, 0xcccecace, 0xcccecace, 0xcccecace, + 0xccc5cace, 0xccc5cace, 0xccc5cace, 0xccc5cace, 0xccc5c6c5, 0xccc5c6c5, 0xccc5c6c5, 0xccc5c6c5, + 0xccc5c6c5, 0xccc5c6c5, 0xccc5c6c5, 0xccc5c6c5, 0xccc5c2c5, 0xccc5c2c5, 0xccc5c2c5, 0xccc5c2c5, + 0xccc5c2c5, 0xccc5c2c5, 0xccc5c2c5, 0xccc5c2c5, 0xccbdbebd, 0xccbdbebd, 0xccbdbebd, 0xccbdbebd, + 0xccbdbebd, 0xccbdbebd, 0xccbdbebd, 0xccbdbebd, 0xccbdbebd, 0xccbdbebd, 0xccbdbebd, 0xccbdbebd, + 0xccc5c6c5, 0xccc5c6c5, 0xccabaeac, 0xcca5a6a5, 0xcca8a9a8, 0xccaeadac, 0xccaeacab, 0xccb5b5b4, + 0xccbcbdbd, 0xccb0b1b2, 0xcca9a9a9, 0xcca5a4a6, 0xcc9f9fa1, 0xcc9da09f, 0xcc9ca09e, 0xccafb3b1, + 0xccacadab, 0xcca8a9a7, 0xcca0a09f, 0xcc999a99, 0xbb939492, 0xbb8d918e, 0xbb8c908c, 0xbb8c908c, + 0xbb868686, 0xbb868686, 0xbb868686, 0xbb868686, 0xbb7b7f7b, 0xbb7b7f7b, 0xaa7b7f7b, 0xaa7b7f7b, + 0xaa737370, 0xaa737370, 0xaa737370, 0xaa737370, 0x99686763, 0x99686763, 0x99686763, 0x99686763, + 0x995a5955, 0x885a5955, 0x885a5955, 0x8831312f, 0x77242424, 0x77242424, 0x77242424, 0x66242424, + 0x661b1a1b, 0x33000000, 0x22000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x44080408, 0x66080408, 0x66242224, 0x66242224, + 0x662c2b2c, 0x662c2b2c, 0x662c2b2c, 0x662c2b2c, 0x663f413f, 0x663f413f, 0x663f413f, 0x663f413f, + 0x77504e50, 0x77504e50, 0x77504e50, 0x77504e50, 0x77585858, 0x77585858, 0x77585858, 0x77585858, + 0x88606060, 0x88606060, 0x88606060, 0x88606060, 0x88636563, 0x88636563, 0x88636563, 0x88636563, + 0x886b6b6b, 0x886b6b6b, 0x996b6b6b, 0x996b6b6b, 0x99736f73, 0x99736f73, 0x99736f73, 0x99736f73, + 0x996e6d6e, 0x996e6d6e, 0x996e6d6e, 0x996e6d6e, 0x996e706e, 0x996e706e, 0x996e706e, 0x996e706e, + 0x99707170, 0x99707170, 0x99707170, 0x99707170, 0xaa767576, 0x99767576, 0xaa767576, 0xaa767576, + 0xaa7b7c7e, 0xaa7b7c7e, 0xaa7b7c7f, 0xaa7d7e80, 0xaa7a7a7c, 0xaa7b7a7c, 0xaa787979, 0xaa777677, + 0xaa797979, 0xaa797979, 0xaa797979, 0xaa797979, 0xaa979694, 0xaa979694, 0xaa979694, 0xaa979694, + 0xaa949694, 0xaa949694, 0xaa949694, 0xaa949694, 0xaa797b79, 0xaa797b79, 0xaa797b79, 0xaa797b79, + 0xaa797979, 0xaa797979, 0xaa797979, 0xaa797979, 0xaa7b7976, 0xaa7b7976, 0xaa7b7976, 0xaa7b7976, + 0xaa767776, 0xaa767776, 0xaa767776, 0xaa767776, 0xaa767776, 0xaa767776, 0xaa767776, 0xaa767776, + 0xaa767576, 0x99767576, 0x99767576, 0x99767576, 0x99767876, 0x99767876, 0x99767876, 0x99767876, + 0x99767576, 0x99767576, 0x99767576, 0x99767576, 0x99767576, 0x99767576, 0x99767576, 0x99767576, + 0x99767776, 0x99767776, 0x99767776, 0x99767776, 0x99707770, 0x99707770, 0x99707770, 0x99707770, + 0x99707370, 0x99707370, 0x99707370, 0x99717571, 0x99787c79, 0x99787d79, 0x99787d79, 0x99797d79, + 0x99787d79, 0x99797d79, 0x99797d78, 0x99797d79, 0x99797c79, 0x99797c79, 0x99797c79, 0x99797c78, + 0x99747672, 0x99727672, 0x99727371, 0x99707371, 0x99797879, 0x99797878, 0x99797879, 0x99787879, + 0x99777577, 0xaa777676, 0xaa767476, 0xaa767476, 0xaa767476, 0xaa767476, 0xaa767476, 0xaa767476, + 0xaa6e7170, 0xaa6e7170, 0xaa6e7170, 0xaa6e7170, 0xaa737373, 0xaa737373, 0xaa737373, 0xaa737373, + 0xaa737373, 0xaa737373, 0xaa737373, 0xaa737373, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, + 0xaa737173, 0xaa737173, 0xaa737173, 0xaa737173, 0xaa707070, 0xaa707070, 0xaa707070, 0xaa707070, + 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, 0xaa6b6d6b, + 0x996e706e, 0xaa6f716f, 0x99747673, 0x99757774, 0x99767676, 0x99777876, 0x99737373, 0x99737272, + 0x99757577, 0x996e6e72, 0x996b6c70, 0x996b6c70, 0x99686c68, 0x99686c68, 0x99686c68, 0x996b6f6b, + 0x99636563, 0x995d5e5d, 0x995d5e5d, 0x995d5e5d, 0x995a5e5a, 0x885a5e5a, 0x885a5e5a, 0x885a5e5a, + 0x88585558, 0x88585558, 0x88585558, 0x88585558, 0x884a4c4a, 0x884a4c4a, 0x884a4c4a, 0x884a4c4a, + 0x77423f3c, 0x77423f3c, 0x77423f3c, 0x77423f3c, 0x77343331, 0x77343331, 0x77343331, 0x77343331, + 0x6631312f, 0x66080808, 0x66080808, 0x66080808, 0x66000000, 0x66000000, 0x55000000, 0x33000000, + 0x44000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00080408, 0x11080408, 0x22080408, 0x33080408, + 0x44080808, 0x55080808, 0x55080808, 0x66080808, 0x66191c19, 0x66191c19, 0x66191c19, 0x66191c19, + 0x66292829, 0x66292829, 0x66292829, 0x66292829, 0x66313131, 0x66313131, 0x66313131, 0x66313131, + 0x663a393a, 0x663a393a, 0x663a393a, 0x663a393a, 0x663a3d3a, 0x663a3d3a, 0x663a3d3a, 0x663a3d3a, + 0x66424142, 0x66424142, 0x66424142, 0x66424142, 0x664a454a, 0x664a454a, 0x664a454a, 0x664a454a, + 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a4d4a, 0x774a4d4a, 0x774a4d4a, 0x774a4d4a, + 0x774a4d4a, 0x774a4d4a, 0x774a4d4a, 0x774a4d4a, 0x77525152, 0x77525152, 0x77525152, 0x77525152, + 0x77525152, 0x77525152, 0x77525152, 0x77525152, 0x77525152, 0x77525152, 0x77525152, 0x77525152, + 0x77525552, 0x77525552, 0x77525552, 0x77525552, 0x774a4542, 0x774a4542, 0x774a4542, 0x774a4542, + 0x77424542, 0x77424542, 0x77424542, 0x77424542, 0x77525552, 0x77525552, 0x77525552, 0x77525552, + 0x77525152, 0x77525152, 0x77525152, 0x77525152, 0x7752514a, 0x7752514a, 0x7752514a, 0x7752514a, + 0x774a4d4a, 0x774a4d4a, 0x774a4d4a, 0x774a4d4a, 0x774a4d4a, 0x774a4d4a, 0x774a4d4a, 0x774a4d4a, + 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a4d4a, 0x774a4d4a, 0x774a4d4a, 0x774a4d4a, + 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, + 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x77424942, 0x77424942, 0x77424942, 0x77424942, + 0x77424542, 0x77424542, 0x77424542, 0x77424542, 0x77424942, 0x77424942, 0x77424942, 0x77424942, + 0x77424942, 0x77424942, 0x77424942, 0x77424942, 0x77424942, 0x77424942, 0x77424942, 0x77424942, + 0x77424542, 0x77424542, 0x77424542, 0x77424542, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, + 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, + 0x77424542, 0x77424542, 0x77424542, 0x77424542, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, + 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, + 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, 0x774a494a, + 0x77424542, 0x77424542, 0x77424542, 0x77424542, 0x77424542, 0x77424542, 0x77424542, 0x77424542, + 0x77424542, 0x77424542, 0x77424542, 0x77424542, 0x77424142, 0x77424142, 0x77424142, 0x77424142, + 0x773a3d42, 0x773a3d42, 0x773a3d42, 0x773a3d42, 0x773a3d3a, 0x773a3d3a, 0x773a3d3a, 0x773a3d3a, + 0x66313531, 0x66313531, 0x66313531, 0x66313531, 0x66292d29, 0x66292d29, 0x66292d29, 0x66292d29, + 0x66292429, 0x66292429, 0x66292429, 0x66292429, 0x66191819, 0x66191819, 0x66191819, 0x66191819, + 0x66100c08, 0x66100c08, 0x66100c08, 0x66100c08, 0x66000000, 0x66000000, 0x66000000, 0x66000000, + 0x66080808, 0x66080808, 0x66080808, 0x55080808, 0x44000000, 0x22000000, 0x11000000, 0x11000000, + 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x11000000, 0x11000000, 0x22000000, 0x22000000, 0x33000000, 0x44000000, + 0x44000000, 0x44000000, 0x55000000, 0x55000000, 0x55000400, 0x55000400, 0x55000400, 0x55000400, + 0x55080808, 0x66080808, 0x66080808, 0x66080808, 0x662f2f2f, 0x662f2f2f, 0x662f2f2f, 0x662f2f2f, + 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, + 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, + 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, + 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, + 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, + 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, 0x66312f31, + 0x662f2f2f, 0x662f2f2f, 0x662f2f2f, 0x662f2f2f, 0x66080808, 0x66080808, 0x66080808, 0x66080808, + 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, + 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, 0x66080808, + 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, + 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, + 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, + 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, + 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, + 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, + 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, + 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, + 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, + 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080408, + 0x66080408, 0x66080408, 0x66080408, 0x66080408, 0x66080400, 0x66080400, 0x66080400, 0x66080400, + 0x66000400, 0x66000400, 0x66000400, 0x66000400, 0x66000400, 0x66000400, 0x66000400, 0x66000400, + 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x66000000, + 0x66000000, 0x66000000, 0x66000000, 0x66000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, + 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x44000000, 0x44000000, 0x33000000, 0x33000000, + 0x22000000, 0x22000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11000400, 0x11000400, 0x11000400, 0x22000400, + 0x22080808, 0x22080808, 0x22080808, 0x22080808, 0x33000000, 0x33000000, 0x33000000, 0x33000000, + 0x33000000, 0x33000000, 0x33000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, + 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, + 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x55000000, 0x44000000, 0x44000000, 0x44000000, + 0x44000000, 0x44000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, + 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, + 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55000000, + 0x55000000, 0x55000000, 0x55000000, 0x55000000, 0x55080808, 0x44080808, 0x44080808, 0x44080808, + 0x55080808, 0x44080808, 0x44080808, 0x55080808, 0x55080808, 0x44080808, 0x44080808, 0x44080808, + 0x44080808, 0x44080808, 0x44080808, 0x44080808, 0x44080808, 0x44080808, 0x44080808, 0x44080808, + 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, + 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, + 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, + 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, + 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, + 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, + 0x44080408, 0x55080408, 0x55080408, 0x55080408, 0x55080408, 0x55080408, 0x55080408, 0x55080408, + 0x55080408, 0x55080408, 0x55080408, 0x55080408, 0x55080408, 0x55080408, 0x55080408, 0x55080408, + 0x55080408, 0x55080408, 0x55080408, 0x55080408, 0x55080408, 0x55080408, 0x55080408, 0x55080408, + 0x55080408, 0x55080408, 0x55080408, 0x55080408, 0x44080408, 0x44080408, 0x44080408, 0x44080408, + 0x44080408, 0x44080408, 0x44080408, 0x44080408, 0x44080400, 0x44080400, 0x44080400, 0x44080400, + 0x44000400, 0x44000400, 0x44000400, 0x44000400, 0x44000400, 0x44000400, 0x44000400, 0x44000400, + 0x44000000, 0x44000000, 0x44000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000, + 0x33000000, 0x33000000, 0x22000000, 0x22000000, 0x22000000, 0x22000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0x00000400, 0x00000400, 0x00000400, + 0x00080808, 0x00080808, 0x00080808, 0x00080808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11080808, 0x11080808, 0x11080808, 0x11080808, + 0x11080808, 0x11080808, 0x11080808, 0x11080808, 0x11080808, 0x11080808, 0x11080808, 0x11080808, + 0x11080808, 0x11080808, 0x11080808, 0x11080808, 0x11080808, 0x11080808, 0x11080808, 0x11080808, + 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, + 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, + 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, + 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, + 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, + 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, + 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, + 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, + 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, + 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080408, + 0x11080408, 0x11080408, 0x11080408, 0x11080408, 0x11080400, 0x11080400, 0x11080400, 0x11080400, + 0x11000400, 0x11000400, 0x11000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000400, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xbb4d4e4d, 0xbb737573, 0xbb737573, + 0xbb8c8e8c, 0xbb8c8e8c, 0xbb8c8e8c, 0xbb8c8e8c, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb8c8e8c, 0xbb8c8e8c, 0xbb8c8e8c, 0xbb8c8e8c, + 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, + 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, + 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, + 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, + 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, + 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, 0xbb948e94, + 0xbb8c8e8c, 0xbb8c8e8c, 0xbb8c8e8c, 0xbb8c8e8c, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, + 0xbb949294, 0xbb949294, 0xbb949294, 0xbb949294, 0xbb8c8e8c, 0xbb8c8e8c, 0xbb8c8e8c, 0xbb8c8e8c, + 0xbb737573, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xcc737573, 0xcc737573, 0xcc737573, + 0xcca5a6a5, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, + 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xccffffff, 0xcca5a6a5, 0xcca5a6a5, + 0xcc737173, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xdd737573, 0xdd737573, 0xddadaead, + 0xdda5a6a5, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, + 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddffffff, 0xddbabcba, 0xdda5a6a5, + 0xddadaaad, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xee737573, 0xeeadaead, 0xeeadaead, + 0xeebabcba, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeeffffff, 0xeed0d1d0, 0xeebabcba, + 0xeeadaaad, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xee737573, 0xeeadaead, 0xeeadaead, + 0xeed0d1d0, 0xeefffffe, 0xeeffffff, 0xeeffffff, 0xeefefffe, 0xfffefeff, 0xeefffeff, 0xeefefeff, + 0xeefeffff, 0xeefeffff, 0xeeffffff, 0xeefeffff, 0xeeffffff, 0xeefffefe, 0xeefffefe, 0xeefeffff, + 0xfffefefe, 0xeefefffe, 0xeefffffe, 0xeeffffff, 0xfffefffe, 0xeefffefe, 0xeeffffff, 0xeefffffe, + 0xfffefffe, 0xeefffeff, 0xeefeffff, 0xeefffeff, 0xffffffff, 0xeefffffe, 0xfffffefe, 0xfffffeff, + 0xeefeffff, 0xffffffff, 0xfffffffe, 0xeefffeff, 0xeefefffe, 0xffffffff, 0xeefffeff, 0xeefefffe, + 0xeefffffe, 0xeefffeff, 0xeefeffff, 0xeefeffff, 0xeefffffe, 0xeeffffff, 0xeeffffff, 0xeeffffff, + 0xeeffffff, 0xeefffeff, 0xfffeffff, 0xeefffffe, 0xeefffeff, 0xfffefffe, 0xeefffffe, 0xeeffffff, + 0xeefffefe, 0xffffffff, 0xeeffffff, 0xeefefefe, 0xeefefefe, 0xeeffffff, 0xeefffefe, 0xeefeffff, + 0xfffffffe, 0xeefffffe, 0xeefffefe, 0xeeffffff, 0xeefefeff, 0xeefefeff, 0xfffffeff, 0xfffffeff, + 0xffffffff, 0xeefeffff, 0xeefefeff, 0xeefffeff, 0xfffeffff, 0xeefffefe, 0xffffffff, 0xeefffffe, + 0xeeffffff, 0xfffffeff, 0xeefffffe, 0xeeffffff, 0xeefeffff, 0xfffefefe, 0xeefffeff, 0xeefffffe, + 0xeefffefe, 0xeefffeff, 0xfffefefe, 0xfffffffe, 0xeefffeff, 0xeefefeff, 0xeefffefe, 0xeeffffff, + 0xeefffeff, 0xeefefeff, 0xfffefeff, 0xeefefefe, 0xfffffffe, 0xfffefeff, 0xeefefeff, 0xeeffffff, + 0xeefefefe, 0xeefffffe, 0xeefefefe, 0xeefffeff, 0xfffefffe, 0xfffefefe, 0xeefefffe, 0xeefefffe, + 0xfffffffe, 0xffffffff, 0xeefeffff, 0xfffffefe, 0xeefefefe, 0xeefffefe, 0xfffefefe, 0xeefefeff, + 0xfffeffff, 0xeeffffff, 0xfffefefe, 0xfffefefe, 0xeefeffff, 0xeefeffff, 0xfffffefe, 0xeeffffff, + 0xeefffefe, 0xeefefffe, 0xeefefffe, 0xeefffeff, 0xfffffefe, 0xeeffffff, 0xfffefeff, 0xfffffefe, + 0xeefeffff, 0xeefefeff, 0xeefefeff, 0xeefffffe, 0xfffffefe, 0xeefffeff, 0xeefefffe, 0xeefefefe, + 0xeefeffff, 0xeefefefe, 0xeefeffff, 0xeefffeff, 0xeefeffff, 0xeeffffff, 0xfffffeff, 0xeeffffff, + 0xeefefffe, 0xfffefffe, 0xfffefffe, 0xeefffeff, 0xfffffeff, 0xeefefefe, 0xeefefffe, 0xeefefffe, + 0xeefefffe, 0xeefffeff, 0xeefffeff, 0xfffeffff, 0xeefffffe, 0xeeffffff, 0xeefffefe, 0xeefefefe, + 0xeefefeff, 0xeefefefe, 0xeefefeff, 0xeeffffff, 0xeeffffff, 0xfffefffe, 0xfffeffff, 0xeefffefe, + 0xeefffffe, 0xeefefefe, 0xeefffefe, 0xeefeffff, 0xeefffffe, 0xeefefefe, 0xeefefffe, 0xeefeffff, + 0xeefffeff, 0xfffffffe, 0xeefeffff, 0xeefeffff, 0xeefffffe, 0xeefffffe, 0xeefefffe, 0xeefffeff, + 0xeefefeff, 0xfffffffe, 0xeefefeff, 0xeefefffe, 0xeeffffff, 0xeefffefe, 0xeefefeff, 0xeefffffe, + 0xeefefffe, 0xeefffeff, 0xeefefeff, 0xfffeffff, 0xeefefeff, 0xeefffeff, 0xeefffffe, 0xeefffeff, + 0xeefffefe, 0xeefefeff, 0xeefefffe, 0xeefefeff, 0xeefffeff, 0xeefffffe, 0xeefffffe, 0xeefefeff, + 0xeefefefe, 0xfffffeff, 0xeefffefe, 0xeefefeff, 0xeefefefe, 0xfffeffff, 0xeee6e7e6, 0xeed0d1d0, + 0xeeadaaad, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff848384, 0xffc5c2c5, 0xffc5c2c5, + 0xffdedfde, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefeff, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefffe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefeff, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefffe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, + 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xfffefefe, 0xffe9e9e9, 0xffdedfde, + 0xffdedfde, 0x00060306, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff848384, 0xffc5c2c5, 0xffc5c2c5, + 0xffdedfde, 0xfffefdfd, 0xfffdfdfd, 0xfffdfefd, 0xfffdfdfd, 0xfffdfdfe, 0xfffdfdfd, 0xfffefefd, + 0xfffdfefe, 0xfffdfefd, 0xfffefefd, 0xfffefefd, 0xfffefefd, 0xfffdfefd, 0xfffdfdfd, 0xfffdfdfd, + 0xfffefefe, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfe, 0xfffefdfd, 0xfffefefd, 0xfffdfefd, 0xfffdfdfd, + 0xfffdfdfd, 0xfffdfefe, 0xfffdfdfd, 0xfffdfefd, 0xfffdfefe, 0xfffefdfd, 0xfffefdfd, 0xfffdfdfe, + 0xfffdfdfd, 0xfffdfefd, 0xfffdfdfe, 0xfffdfdfd, 0xfffdfdfe, 0xfffdfefd, 0xfffefdfe, 0xfffefdfd, + 0xfffdfefd, 0xfffefdfe, 0xfffefdfd, 0xfffefefd, 0xfffefefe, 0xfffefdfe, 0xfffefefe, 0xfffdfdfd, + 0xfffdfefd, 0xfffdfefd, 0xfffdfdfd, 0xfffdfdfd, 0xfffefdfe, 0xfffdfefe, 0xfffefdfd, 0xfffdfefd, + 0xfffdfdfd, 0xfffdfefe, 0xfffdfefd, 0xfffefdfd, 0xfffdfefe, 0xfffdfdfe, 0xfffdfefd, 0xfffefdfe, + 0xfffdfefd, 0xfffefefd, 0xfffdfefd, 0xfffdfefd, 0xfffdfefd, 0xfffdfefe, 0xfffefdfe, 0xfffdfefd, + 0xfffefefe, 0xfffdfdfe, 0xfffefefd, 0xfffdfdfd, 0xfffefefd, 0xfffefdfe, 0xfffefdfd, 0xfffefefd, + 0xfffdfefd, 0xfffdfefd, 0xfffdfdfe, 0xfffdfdfd, 0xfffefdfe, 0xfffdfefe, 0xfffdfdfd, 0xfffdfefd, + 0xfffdfdfe, 0xfffefdfe, 0xfffdfdfe, 0xfffdfefe, 0xfffefefe, 0xfffefefd, 0xfffefdfe, 0xfffdfdfe, + 0xfffdfdfd, 0xfffdfefd, 0xfffefdfd, 0xfffdfdfd, 0xfffdfdfe, 0xfffdfdfd, 0xfffefefe, 0xfffefdfd, + 0xfffefdfd, 0xfffdfefe, 0xfffdfdfe, 0xfffefdfd, 0xfffefdfd, 0xfffefdfe, 0xfffdfdfd, 0xfffdfdfd, + 0xfffefefe, 0xfffdfefe, 0xfffefdfd, 0xfffefefe, 0xfffdfdfd, 0xfffefdfd, 0xfffdfdfd, 0xfffefdfd, + 0xfffefdfe, 0xfffdfefd, 0xfffdfdfd, 0xfffdfefe, 0xfffdfdfd, 0xfffdfefe, 0xfffdfdfe, 0xfffdfdfd, + 0xfffefefe, 0xfffdfefd, 0xfffdfefe, 0xfffdfdfe, 0xfffdfdfe, 0xfffefefd, 0xfffefdfe, 0xfffdfdfd, + 0xfffdfdfd, 0xfffefefe, 0xfffdfdfe, 0xfffefdfe, 0xfffdfdfd, 0xfffdfefd, 0xfffefefe, 0xfffefdfd, + 0xfffdfefe, 0xfffdfefe, 0xfffefefe, 0xfffdfdfe, 0xfffdfdfd, 0xfffefdfd, 0xfffdfdfd, 0xfffdfdfd, + 0xfffdfdfd, 0xfffdfefd, 0xfffdfdfd, 0xfffefdfd, 0xfffefefe, 0xfffdfefd, 0xfffefdfd, 0xfffdfefe, + 0xfffefdfd, 0xfffefdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffefdfe, 0xfffefdfd, 0xfffefdfd, 0xfffdfefe, + 0xfffdfefd, 0xfffdfefd, 0xfffdfdfd, 0xfffefefe, 0xfffdfefd, 0xfffefdfd, 0xfffdfdfd, 0xfffefefd, + 0xfffefefd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfefd, 0xfffdfdfe, 0xfffefdfe, 0xfffefdfd, + 0xfffdfdfd, 0xfffefefd, 0xfffefefd, 0xfffdfefd, 0xfffefefd, 0xfffefdfd, 0xfffdfefe, 0xfffdfefd, + 0xfffdfdfd, 0xfffdfdfe, 0xfffdfdfe, 0xfffdfdfd, 0xfffdfdfe, 0xfffefdfe, 0xfffefdfd, 0xfffdfefe, + 0xfffdfdfd, 0xfffefefd, 0xfffdfdfd, 0xfffefdfe, 0xfffdfefe, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfe, + 0xfffefdfe, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffefdfe, 0xfffefdfe, 0xfffdfdfd, 0xfffdfdfe, + 0xfffefefd, 0xfffdfdfd, 0xfffefefe, 0xfffdfefd, 0xfffdfdfe, 0xfffdfdfe, 0xfff4f4f4, 0xffdedfde, + 0xffdedfde, 0x00060306, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff848384, 0xffc5c2c5, 0xffc5c2c5, + 0xffe9e9e9, 0xfffdfcfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfc, 0xfffcfcfd, 0xfffdfdfd, 0xfffdfdfd, + 0xfffcfdfd, 0xfffdfdfc, 0xfffcfdfd, 0xfffcfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfcfd, 0xfffdfdfc, + 0xfffdfcfd, 0xfffdfcfd, 0xfffdfcfc, 0xfffcfcfc, 0xfffdfcfd, 0xfffdfdfd, 0xfffdfcfd, 0xfffdfdfd, + 0xfffdfdfd, 0xfffdfcfc, 0xfffdfcfd, 0xfffcfcfd, 0xfffdfdfc, 0xfffdfcfd, 0xfffdfdfc, 0xfffdfdfd, + 0xfffdfdfc, 0xfffcfdfd, 0xfffdfdfc, 0xfffdfcfd, 0xfffcfcfd, 0xfffdfdfd, 0xfffdfdfc, 0xfffdfdfd, + 0xfffdfdfd, 0xfffdfdfd, 0xfffcfcfc, 0xfffdfdfd, 0xfffcfdfd, 0xfffdfdfc, 0xfffdfdfc, 0xfffdfcfd, + 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffcfdfd, + 0xfffdfcfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffcfdfd, 0xfffcfcfc, 0xfffcfdfd, 0xfffdfdfc, 0xfffdfcfd, + 0xfffdfcfd, 0xfffdfcfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffcfdfd, 0xfffdfcfd, 0xfffdfdfd, + 0xfffdfdfd, 0xfffdfdfc, 0xfffdfdfd, 0xfffdfcfd, 0xfffcfdfd, 0xfffdfcfc, 0xfffdfcfd, 0xfffdfdfd, + 0xfffcfdfc, 0xfffdfdfd, 0xfffdfcfc, 0xfffdfcfc, 0xfffcfdfc, 0xfffcfdfd, 0xfffdfdfd, 0xfffcfcfd, + 0xfffdfcfd, 0xfffcfcfc, 0xfffdfdfc, 0xfffcfcfd, 0xfffcfdfd, 0xfffdfdfd, 0xfffcfcfd, 0xfffdfdfd, + 0xfffdfcfd, 0xfffcfdfd, 0xfffdfdfd, 0xfffdfdfc, 0xfffcfcfc, 0xfffdfcfd, 0xfffcfdfd, 0xfffdfcfc, + 0xfffcfdfc, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfc, 0xfffdfdfd, 0xfffdfdfd, 0xfffcfcfd, 0xfffdfdfd, + 0xfffdfdfc, 0xfffdfdfd, 0xfffdfdfd, 0xfffcfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfc, 0xfffdfcfd, + 0xfffdfdfd, 0xfffcfcfc, 0xfffdfcfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, + 0xfffdfcfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfcfd, 0xfffdfdfd, + 0xfffdfdfd, 0xfffcfdfd, 0xfffdfcfc, 0xfffcfdfc, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, + 0xfffdfdfd, 0xfffdfcfc, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffcfdfd, 0xfffdfcfd, 0xfffdfdfd, + 0xfffdfdfc, 0xfffdfdfc, 0xfffcfdfd, 0xfffcfdfd, 0xfffdfdfc, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfdfd, + 0xfffdfcfd, 0xfffdfdfd, 0xfffdfdfc, 0xfffdfdfc, 0xfffdfdfc, 0xfffdfdfd, 0xfffcfdfc, 0xfffdfdfd, + 0xfffdfdfd, 0xfffcfcfd, 0xfffdfcfd, 0xfffcfdfc, 0xfffdfcfd, 0xfffcfdfc, 0xfffdfdfd, 0xfffdfdfd, + 0xfffdfcfc, 0xfffdfdfd, 0xfffcfcfd, 0xfffdfdfc, 0xfffdfdfc, 0xfffdfdfc, 0xfffdfcfd, 0xfffdfdfd, + 0xfffcfdfd, 0xfffdfcfd, 0xfffdfcfd, 0xfffdfdfc, 0xfffdfdfd, 0xfffcfdfd, 0xfffdfdfd, 0xfffcfdfd, + 0xfffdfcfd, 0xfffcfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfcfd, 0xfffdfdfd, 0xfffcfdfd, 0xfffdfcfc, + 0xfffcfcfd, 0xfffdfcfd, 0xfffdfdfc, 0xfffcfdfd, 0xfffdfdfd, 0xfffdfdfd, 0xfffdfcfd, 0xfffdfdfc, + 0xfffdfdfd, 0xfffdfdfd, 0xfffdfcfc, 0xfffdfdfd, 0xfffdfcfd, 0xfffcfdfd, 0xfffcfdfc, 0xfffdfdfd, + 0xfffdfdfc, 0xfffdfdfd, 0xfffdfdfd, 0xfffcfdfd, 0xfffcfdfd, 0xfffdfcfd, 0xfff4f4f4, 0xffe9e9e9, + 0xffdedfde, 0x00060306, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff848384, 0xffc5c2c5, 0xffc5c2c5, + 0xffe9e9e9, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfbfc, + 0xfffbfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffbfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfbfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfbfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfb, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfb, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfb, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfb, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, + 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfffcfcfc, 0xfff4f4f4, 0xffe9e9e9, + 0xffdedfde, 0x00060306, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff848684, 0xffc5c6c5, 0xffc5c6c5, + 0xffe6ebe6, 0xfffbfbfb, 0xfffbfbfc, 0xfffbfbfb, 0xfffbfbfc, 0xfffbfcfb, 0xfffbfbfb, 0xfffbfbfb, + 0xfffbfcfb, 0xfffbfbfb, 0xfffbfbfc, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffcfbfb, 0xfffcfbfb, + 0xfffbfbfb, 0xfffbfbfb, 0xfffcfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfc, 0xfffbfbfb, + 0xfffbfcfc, 0xfffcfbfb, 0xfffcfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfc, 0xfffbfbfc, + 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffcfcfc, 0xfffbfbfb, 0xfffcfbfb, 0xfffbfcfb, 0xfffbfbfb, + 0xfffbfbfb, 0xfffbfcfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfcfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, + 0xfffcfbfb, 0xfffbfbfb, 0xfffcfbfb, 0xfffbfcfb, 0xfffbfbfb, 0xfffbfcfb, 0xfffbfbfb, 0xfffcfbfb, + 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfcfc, 0xfffbfcfb, 0xfffbfcfb, + 0xfffbfcfc, 0xfffbfbfb, 0xfffcfbfb, 0xfffbfcfb, 0xfffbfbfc, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, + 0xfffcfbfb, 0xfffcfbfb, 0xfffcfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfcfc, 0xfffbfbfb, 0xfffbfbfb, + 0xfffbfbfc, 0xfffbfbfb, 0xfffbfcfc, 0xfffcfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfcfb, + 0xfffbfbfb, 0xfffbfbfb, 0xfffbfcfb, 0xfffbfbfb, 0xfffcfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffcfbfb, + 0xfffbfcfb, 0xfffbfcfb, 0xfffcfbfb, 0xfffbfcfb, 0xfffbfbfb, 0xfffbfbfc, 0xfffcfbfb, 0xfffbfbfc, + 0xfffbfbfb, 0xfffcfbfb, 0xfffbfbfc, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, + 0xfffbfbfb, 0xfffbfcfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfcfc, 0xfffcfbfb, + 0xfffbfcfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffcfbfb, 0xfffbfcfb, 0xfffbfbfb, 0xfffbfbfc, 0xfffbfbfb, + 0xfffbfbfc, 0xfffbfbfc, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffcfbfc, 0xfffcfbfb, 0xfffbfcfb, + 0xfffbfbfb, 0xfffcfbfb, 0xfffcfbfb, 0xfffbfbfb, 0xfffcfbfb, 0xfffbfcfb, 0xfffbfbfb, 0xfffbfbfb, + 0xfffbfbfc, 0xfffbfcfc, 0xfffcfcfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfcfb, 0xfffbfbfc, 0xfffbfbfb, + 0xfffcfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfcfb, 0xfffbfbfb, + 0xfffbfcfb, 0xfffbfbfb, 0xfffcfbfb, 0xfffbfbfc, 0xfffbfcfc, 0xfffbfbfc, 0xfffbfbfb, 0xfffbfcfc, + 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfc, 0xfffbfcfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfc, + 0xfffbfcfb, 0xfffbfbfb, 0xfffcfbfb, 0xfffbfbfb, 0xfffcfbfb, 0xfffcfbfb, 0xfffbfbfc, 0xfffbfcfc, + 0xfffbfbfb, 0xfffbfbfb, 0xfffcfbfc, 0xfffcfbfb, 0xfffbfbfb, 0xfffbfbfc, 0xfffbfcfb, 0xfffbfbfb, + 0xfffbfbfb, 0xfffbfcfb, 0xfffcfbfb, 0xfffbfbfc, 0xfffbfbfb, 0xfffcfbfb, 0xfffcfbfb, 0xfffbfbfb, + 0xfffbfbfb, 0xfffbfcfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffcfbfb, 0xfffbfbfb, 0xfffbfcfb, 0xfffbfbfb, + 0xfffbfbfb, 0xfffbfbfb, 0xfffcfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffcfbfb, + 0xfffbfbfc, 0xfffbfcfb, 0xfffbfcfb, 0xfffbfbfb, 0xfffbfbfb, 0xfffbfbfc, 0xfff7f8f7, 0xffe6ebe6, + 0xffdedfde, 0x00000300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff848684, 0xffc5c6c5, 0xffc5c6c5, + 0xffe6ebe6, 0xfffafafb, 0xfffafafb, 0xfffafafa, 0xfffafbfa, 0xfffbfafb, 0xfffafafa, 0xfffafafa, + 0xfffafbfa, 0xfffbfafa, 0xfffbfafa, 0xfffafbfa, 0xfffbfafa, 0xfffbfafb, 0xfffafafa, 0xfffbfafa, + 0xfffafafa, 0xfffafafb, 0xfffbfafb, 0xfffafafa, 0xfffbfbfa, 0xfffafafa, 0xfffafbfb, 0xfffafbfb, + 0xfffafbfa, 0xfffafafb, 0xfffafbfa, 0xfffbfafa, 0xfffbfbfa, 0xfffafbfa, 0xfffbfafa, 0xfffafbfa, + 0xfffafafa, 0xfffbfafa, 0xfffafbfa, 0xfffbfafb, 0xfffafafb, 0xfffafafa, 0xfffafbfa, 0xfffbfbfb, + 0xfffafbfa, 0xfffbfafb, 0xfffafafa, 0xfffafbfb, 0xfffafbfa, 0xfffafafa, 0xfffafafb, 0xfffafbfb, + 0xfffbfafa, 0xfffafbfa, 0xfffafafb, 0xfffafafb, 0xfffafafb, 0xfffafafb, 0xfffbfbfb, 0xfffafafa, + 0xfffafafa, 0xfffafafb, 0xfffbfafa, 0xfffafbfa, 0xfffafbfa, 0xfffafbfa, 0xfffafafa, 0xfffbfbfa, + 0xfffafafa, 0xfffbfbfa, 0xfffbfafa, 0xfffbfafb, 0xfffafafa, 0xfffafbfa, 0xfffafafa, 0xfffafbfa, + 0xfffafafa, 0xfffafafa, 0xfffbfafb, 0xfffafafa, 0xfffafbfa, 0xfffafafa, 0xfffafafa, 0xfffafafa, + 0xfffbfbfa, 0xfffafafa, 0xfffbfafa, 0xfffafafb, 0xfffbfbfa, 0xfffafbfa, 0xfffafbfa, 0xfffafafa, + 0xfffafbfb, 0xfffbfbfa, 0xfffafafa, 0xfffafafa, 0xfffbfafb, 0xfffafafb, 0xfffafbfa, 0xfffafbfa, + 0xfffbfbfa, 0xfffbfbfb, 0xfffafbfa, 0xfffafafa, 0xfffbfbfa, 0xfffbfafa, 0xfffafbfa, 0xfffafafa, + 0xfffbfafb, 0xfffafafa, 0xfffbfafb, 0xfffbfbfb, 0xfffbfafb, 0xfffafafa, 0xfffafafa, 0xfffafbfa, + 0xfffafafa, 0xfffafafb, 0xfffafafb, 0xfffafafb, 0xfffbfafb, 0xfffbfafb, 0xfffafbfa, 0xfffbfafa, + 0xfffafafa, 0xfffafbfb, 0xfffbfafa, 0xfffafafb, 0xfffafbfb, 0xfffafbfa, 0xfffafafa, 0xfffbfbfa, + 0xfffafbfa, 0xfffafafa, 0xfffafafb, 0xfffbfafa, 0xfffafafa, 0xfffbfafa, 0xfffbfafb, 0xfffbfafb, + 0xfffafafa, 0xfffafbfa, 0xfffbfbfa, 0xfffafbfa, 0xfffbfbfa, 0xfffafbfa, 0xfffafbfb, 0xfffafbfa, + 0xfffbfbfb, 0xfffafbfb, 0xfffbfafb, 0xfffafafa, 0xfffafafa, 0xfffbfafa, 0xfffbfafa, 0xfffbfafb, + 0xfffbfbfa, 0xfffafbfa, 0xfffafafa, 0xfffafbfa, 0xfffbfafa, 0xfffafafb, 0xfffafbfa, 0xfffafafb, + 0xfffbfbfa, 0xfffbfafa, 0xfffbfbfa, 0xfffbfafb, 0xfffbfafa, 0xfffafafa, 0xfffafafa, 0xfffbfafb, + 0xfffafafa, 0xfffbfbfb, 0xfffbfafb, 0xfffafafb, 0xfffafafa, 0xfffbfafa, 0xfffbfafb, 0xfffbfafb, + 0xfffbfafa, 0xfffafafb, 0xfffbfafa, 0xfffafafb, 0xfffafafa, 0xfffafbfb, 0xfffbfbfa, 0xfffbfafa, + 0xfffafbfa, 0xfffafafa, 0xfffafbfa, 0xfffbfbfa, 0xfffafbfb, 0xfffafbfb, 0xfffbfafb, 0xfffafafa, + 0xfffafbfb, 0xfffafafb, 0xfffbfbfa, 0xfffafafa, 0xfffafafb, 0xfffafafa, 0xfffafafb, 0xfffafbfa, + 0xfffbfafa, 0xfffbfbfb, 0xfffafafb, 0xfffafbfb, 0xfffafbfb, 0xfffbfafa, 0xfffafbfb, 0xfffafafa, + 0xfffafafa, 0xfffafbfa, 0xfffbfafa, 0xfffafbfa, 0xfffbfafa, 0xfffbfafa, 0xfffafbfa, 0xfffbfafb, + 0xfffafbfa, 0xfffafafb, 0xfffbfafa, 0xfffbfafb, 0xfffafbfb, 0xfffbfbfa, 0xfff7f8f7, 0xffe6ebe6, + 0xffdedfde, 0x00000300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff848684, 0xffc5c6c5, 0xffc5c6c5, + 0xffe6ebe6, 0xfffafafa, 0xfff9f9fa, 0xfffaf9fa, 0xfff9faf9, 0xfff9faf9, 0xfffafafa, 0xfff9f9f9, + 0xfffaf9f9, 0xfff9f9f9, 0xfff9f9f9, 0xfffaf9f9, 0xfff9fafa, 0xfff9fafa, 0xfff9f9fa, 0xfffafaf9, + 0xfff9faf9, 0xfffafafa, 0xfff9f9fa, 0xfff9f9f9, 0xfff9f9f9, 0xfffaf9fa, 0xfffaf9fa, 0xfff9f9f9, + 0xfffafaf9, 0xfff9f9f9, 0xfff9faf9, 0xfffaf9f9, 0xfffafaf9, 0xfffaf9f9, 0xfff9f9fa, 0xfff9f9f9, + 0xfffafafa, 0xfff9faf9, 0xfff9f9f9, 0xfff9fafa, 0xfffafaf9, 0xfff9f9fa, 0xfffaf9f9, 0xfff9f9fa, + 0xfff9faf9, 0xfffafafa, 0xfffafafa, 0xfffafaf9, 0xfff9faf9, 0xfff9f9f9, 0xfff9fafa, 0xfffafaf9, + 0xfffafaf9, 0xfffafafa, 0xfff9f9fa, 0xfffaf9fa, 0xfffafaf9, 0xfff9f9f9, 0xfffaf9f9, 0xfff9fafa, + 0xfff9fafa, 0xfff9faf9, 0xfffaf9f9, 0xfffaf9fa, 0xfffaf9f9, 0xfff9f9fa, 0xfffaf9f9, 0xfff9f9f9, + 0xfff9faf9, 0xfffaf9fa, 0xfffaf9f9, 0xfffaf9f9, 0xfff9faf9, 0xfffafafa, 0xfff9f9f9, 0xfff9f9fa, + 0xfffafafa, 0xfff9f9f9, 0xfffafaf9, 0xfffaf9f9, 0xfff9faf9, 0xfff9f9f9, 0xfffafaf9, 0xfff9f9fa, + 0xfff9faf9, 0xfff9fafa, 0xfffaf9fa, 0xfffafaf9, 0xfffafaf9, 0xfffaf9fa, 0xfff9f9fa, 0xfffaf9f9, + 0xfffaf9fa, 0xfff9fafa, 0xfffaf9f9, 0xfff9f9f9, 0xfffaf9f9, 0xfff9f9fa, 0xfffafafa, 0xfff9fafa, + 0xfff9f9fa, 0xfffaf9f9, 0xfffafaf9, 0xfffafaf9, 0xfff9faf9, 0xfff9f9fa, 0xfff9fafa, 0xfffaf9fa, + 0xfff9f9fa, 0xfffaf9f9, 0xfffafafa, 0xfff9faf9, 0xfffafaf9, 0xfffaf9f9, 0xfff9faf9, 0xfffaf9fa, + 0xfffafafa, 0xfffafaf9, 0xfff9faf9, 0xfffafaf9, 0xfffafafa, 0xfffafafa, 0xfff9f9f9, 0xfff9f9fa, + 0xfffaf9fa, 0xfff9f9f9, 0xfffafaf9, 0xfffafaf9, 0xfffafaf9, 0xfffaf9f9, 0xfffafafa, 0xfff9f9fa, + 0xfff9fafa, 0xfff9faf9, 0xfffaf9f9, 0xfffaf9fa, 0xfff9f9f9, 0xfff9fafa, 0xfff9f9fa, 0xfff9f9fa, + 0xfff9f9f9, 0xfffafaf9, 0xfff9f9f9, 0xfff9faf9, 0xfff9f9fa, 0xfffaf9fa, 0xfff9faf9, 0xfffafafa, + 0xfff9f9fa, 0xfffaf9fa, 0xfffafaf9, 0xfffaf9f9, 0xfffafafa, 0xfff9f9fa, 0xfffafaf9, 0xfffaf9f9, + 0xfff9faf9, 0xfffafaf9, 0xfff9faf9, 0xfff9f9f9, 0xfff9f9f9, 0xfff9f9f9, 0xfffafaf9, 0xfffaf9fa, + 0xfff9faf9, 0xfffaf9f9, 0xfffafaf9, 0xfffafaf9, 0xfff9fafa, 0xfffafafa, 0xfffaf9f9, 0xfff9fafa, + 0xfff9f9f9, 0xfffafaf9, 0xfffaf9fa, 0xfff9f9f9, 0xfff9faf9, 0xfffafaf9, 0xfff9f9fa, 0xfff9f9fa, + 0xfffafaf9, 0xfffaf9fa, 0xfff9fafa, 0xfff9f9f9, 0xfff9faf9, 0xfff9f9f9, 0xfff9f9fa, 0xfff9fafa, + 0xfff9f9fa, 0xfffafafa, 0xfff9f9fa, 0xfffaf9fa, 0xfff9f9fa, 0xfffafaf9, 0xfff9fafa, 0xfff9f9fa, + 0xfff9faf9, 0xfff9f9fa, 0xfff9fafa, 0xfffaf9f9, 0xfff9f9f9, 0xfffafafa, 0xfff9f9f9, 0xfff9faf9, + 0xfffafaf9, 0xfff9faf9, 0xfff9f9fa, 0xfffaf9f9, 0xfffaf9fa, 0xfff9f9fa, 0xfff9f9f9, 0xfff9fafa, + 0xfffafafa, 0xfffafafa, 0xfff9f9f9, 0xfffafafa, 0xfff9f9f9, 0xfffaf9fa, 0xfff9f9f9, 0xfff9fafa, + 0xfff9f9f9, 0xfff9f9f9, 0xfffaf9fa, 0xfffaf9f9, 0xfffaf9f9, 0xfffaf9f9, 0xfff7f8f7, 0xffe6ebe6, + 0xffdedfde, 0x00000300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff848684, 0xffc5c6c5, 0xffc5c6c5, + 0xffe6ebe6, 0xfff8f9f9, 0xfff9f8f8, 0xfff8f9f9, 0xfff9f8f9, 0xfff8f9f9, 0xfff9f8f9, 0xfff9f8f8, + 0xfff8f8f9, 0xfff9f9f9, 0xfff8f9f9, 0xfff8f8f9, 0xfff8f8f8, 0xfff9f8f8, 0xfff9f9f9, 0xfff9f9f8, + 0xfff9f9f9, 0xfff9f8f9, 0xfff8f9f9, 0xfff8f9f9, 0xfff9f9f8, 0xfff9f8f8, 0xfff8f9f8, 0xfff8f8f9, + 0xfff9f8f9, 0xfff8f9f8, 0xfff9f8f8, 0xfff9f9f8, 0xfff9f8f8, 0xfff9f8f8, 0xfff8f9f9, 0xfff9f9f9, + 0xfff9f8f8, 0xfff8f9f9, 0xfff8f8f9, 0xfff9f8f9, 0xfff9f9f8, 0xfff9f8f8, 0xfff8f9f8, 0xfff8f8f9, + 0xfff9f9f9, 0xfff9f9f9, 0xfff8f9f9, 0xfff8f9f8, 0xfff9f8f9, 0xfff9f9f9, 0xfff8f9f9, 0xfff8f9f8, + 0xfff9f8f9, 0xfff8f8f8, 0xfff8f9f9, 0xfff9f9f9, 0xfff8f8f8, 0xfff9f8f9, 0xfff8f8f8, 0xfff9f9f9, + 0xfff8f9f9, 0xfff8f9f9, 0xfff8f9f9, 0xfff8f9f9, 0xfff8f8f9, 0xfff8f8f9, 0xfff8f9f8, 0xfff8f8f8, + 0xfff9f8f8, 0xfff8f9f9, 0xfff8f9f9, 0xfff8f9f9, 0xfff8f9f9, 0xfff9f9f9, 0xfff9f9f8, 0xfff8f8f8, + 0xfff8f8f8, 0xfff9f9f9, 0xfff9f8f8, 0xfff9f8f8, 0xfff8f8f9, 0xfff9f8f9, 0xfff9f9f9, 0xfff9f9f8, + 0xfff9f8f8, 0xfff8f8f8, 0xfff8f9f9, 0xfff9f9f9, 0xfff8f9f8, 0xfff9f9f8, 0xfff8f9f9, 0xfff8f9f9, + 0xfff9f8f8, 0xfff9f9f9, 0xfff8f8f8, 0xfff8f8f8, 0xfff9f9f8, 0xfff9f9f8, 0xfff9f9f9, 0xfff9f9f8, + 0xfff8f9f9, 0xfff9f8f8, 0xfff8f8f8, 0xfff9f9f8, 0xfff8f8f8, 0xfff8f8f9, 0xfff8f8f9, 0xfff8f9f9, + 0xfff9f9f9, 0xfff9f9f9, 0xfff8f8f9, 0xfff9f8f9, 0xfff8f8f9, 0xfff8f8f9, 0xfff9f8f8, 0xfff9f9f9, + 0xfff9f9f9, 0xfff8f9f9, 0xfff9f9f8, 0xfff9f9f9, 0xfff9f8f8, 0xfff8f8f8, 0xfff9f8f9, 0xfff8f8f8, + 0xfff9f8f9, 0xfff9f8f9, 0xfff9f9f8, 0xfff8f8f8, 0xfff8f8f9, 0xfff9f8f9, 0xfff9f8f9, 0xfff8f8f8, + 0xfff8f8f9, 0xfff9f9f9, 0xfff8f8f8, 0xfff8f9f8, 0xfff9f9f8, 0xfff9f8f8, 0xfff9f8f9, 0xfff9f9f9, + 0xfff9f9f9, 0xfff9f9f8, 0xfff9f8f8, 0xfff9f9f9, 0xfff9f9f9, 0xfff9f8f8, 0xfff8f8f9, 0xfff8f9f8, + 0xfff8f9f8, 0xfff9f8f9, 0xfff9f9f8, 0xfff9f9f8, 0xfff9f8f8, 0xfff8f9f9, 0xfff8f8f9, 0xfff8f8f9, + 0xfff9f8f8, 0xfff9f8f9, 0xfff8f8f9, 0xfff9f9f9, 0xfff9f8f9, 0xfff8f8f8, 0xfff8f9f8, 0xfff9f8f9, + 0xfff9f8f8, 0xfff9f9f9, 0xfff8f8f8, 0xfff9f8f8, 0xfff9f9f9, 0xfff8f9f9, 0xfff8f9f9, 0xfff9f8f8, + 0xfff8f9f9, 0xfff8f9f8, 0xfff8f8f9, 0xfff9f8f8, 0xfff8f8f8, 0xfff9f9f9, 0xfff8f9f8, 0xfff8f9f8, + 0xfff9f8f8, 0xfff8f9f9, 0xfff8f8f8, 0xfff9f9f8, 0xfff9f9f8, 0xfff8f9f8, 0xfff9f8f8, 0xfff8f8f8, + 0xfff9f8f8, 0xfff9f9f9, 0xfff9f9f9, 0xfff9f8f8, 0xfff9f8f8, 0xfff9f9f8, 0xfff8f9f9, 0xfff9f8f9, + 0xfff8f8f9, 0xfff9f9f9, 0xfff9f9f8, 0xfff8f9f9, 0xfff8f9f9, 0xfff9f9f8, 0xfff9f8f9, 0xfff9f9f8, + 0xfff9f9f9, 0xfff9f8f9, 0xfff9f9f9, 0xfff8f8f9, 0xfff9f9f8, 0xfff8f9f9, 0xfff9f8f9, 0xfff9f9f9, + 0xfff9f9f8, 0xfff9f8f9, 0xfff8f8f8, 0xfff9f8f8, 0xfff8f8f9, 0xfff8f9f8, 0xfff8f8f8, 0xfff8f8f9, + 0xfff8f9f9, 0xfff9f9f9, 0xfff9f9f9, 0xfff8f9f8, 0xfff9f9f9, 0xfff9f8f8, 0xfff7f8f7, 0xffe6ebe6, + 0xffdedfde, 0x00000300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797d79, 0xffb5bab5, 0xffb5bab5, + 0xffdedbde, 0xfff7f8f7, 0xfff7f7f8, 0xfff8f8f8, 0xfff7f7f7, 0xfff8f7f8, 0xfff7f7f8, 0xfff8f8f8, + 0xfff8f8f8, 0xfff7f8f8, 0xfff7f7f8, 0xfff8f7f8, 0xfff7f8f8, 0xfff8f8f8, 0xfff8f7f7, 0xfff8f8f7, + 0xfff7f8f8, 0xfff7f7f7, 0xfff7f7f8, 0xfff8f7f8, 0xfff8f8f7, 0xfff8f7f7, 0xfff7f8f7, 0xfff8f8f8, + 0xfff8f7f7, 0xfff8f7f8, 0xfff8f7f8, 0xfff8f8f7, 0xfff8f7f7, 0xfff8f8f8, 0xfff7f8f7, 0xfff8f8f7, + 0xfff8f8f7, 0xfff7f8f8, 0xfff7f7f7, 0xfff8f7f8, 0xfff8f7f7, 0xfff7f8f8, 0xfff8f8f8, 0xfff7f7f7, + 0xfff7f8f8, 0xfff7f7f8, 0xfff7f8f8, 0xfff7f8f8, 0xfff7f8f8, 0xfff7f7f8, 0xfff8f8f8, 0xfff7f8f8, + 0xfff7f8f8, 0xfff8f8f8, 0xfff7f8f7, 0xfff8f8f7, 0xfff7f7f7, 0xfff8f8f8, 0xfff7f7f8, 0xfff8f7f7, + 0xfff7f8f7, 0xfff8f8f7, 0xfff7f8f7, 0xfff8f8f8, 0xfff7f7f7, 0xfff8f7f7, 0xfff8f8f7, 0xfff7f8f8, + 0xfff7f8f7, 0xfff8f7f8, 0xfff7f8f8, 0xfff8f8f7, 0xfff7f8f7, 0xfff8f8f7, 0xfff7f7f8, 0xfff8f7f8, + 0xfff8f8f8, 0xfff8f7f8, 0xfff7f8f8, 0xfff7f7f7, 0xfff7f8f7, 0xfff8f8f8, 0xfff7f7f8, 0xfff8f7f8, + 0xfff7f8f8, 0xfff8f8f7, 0xfff8f7f8, 0xfff8f8f8, 0xfff7f8f7, 0xfff8f7f8, 0xfff8f8f7, 0xfff7f8f8, + 0xfff7f7f8, 0xfff8f8f7, 0xfff8f8f7, 0xfff8f7f7, 0xfff7f7f7, 0xfff7f7f8, 0xfff7f8f8, 0xfff8f8f7, + 0xfff7f8f8, 0xfff8f7f8, 0xfff7f8f8, 0xfff8f8f8, 0xfff7f7f7, 0xfff7f8f7, 0xfff8f7f7, 0xfff8f7f8, + 0xfff8f8f7, 0xfff8f7f8, 0xfff8f7f7, 0xfff7f8f8, 0xfff7f7f8, 0xfff7f7f8, 0xfff8f7f8, 0xfff8f7f7, + 0xfff7f7f8, 0xfff8f8f8, 0xfff7f7f8, 0xfff7f7f7, 0xfff8f8f7, 0xfff7f8f8, 0xfff8f7f8, 0xfff7f8f8, + 0xfff8f7f7, 0xfff8f7f8, 0xfff8f8f7, 0xfff7f8f8, 0xfff8f8f7, 0xfff8f8f7, 0xfff7f8f8, 0xfff8f8f7, + 0xfff8f8f8, 0xfff7f7f8, 0xfff7f7f8, 0xfff8f8f8, 0xfff7f7f7, 0xfff8f8f7, 0xfff7f7f8, 0xfff7f8f8, + 0xfff7f7f7, 0xfff7f7f7, 0xfff7f8f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff8f8f8, 0xfff7f7f8, 0xfff8f8f8, + 0xfff7f8f8, 0xfff8f8f8, 0xfff7f8f8, 0xfff7f8f7, 0xfff8f7f8, 0xfff7f8f8, 0xfff8f7f8, 0xfff7f8f7, + 0xfff7f8f7, 0xfff8f8f7, 0xfff8f7f7, 0xfff8f7f8, 0xfff8f7f8, 0xfff7f8f8, 0xfff8f7f7, 0xfff8f8f8, + 0xfff8f7f8, 0xfff8f8f7, 0xfff8f7f8, 0xfff8f7f7, 0xfff7f8f8, 0xfff8f8f7, 0xfff8f7f7, 0xfff8f8f7, + 0xfff7f8f7, 0xfff7f8f8, 0xfff7f8f8, 0xfff8f8f8, 0xfff8f8f7, 0xfff7f8f8, 0xfff7f8f8, 0xfff7f8f7, + 0xfff8f8f8, 0xfff8f8f7, 0xfff8f8f8, 0xfff7f7f7, 0xfff7f7f8, 0xfff8f7f8, 0xfff8f8f8, 0xfff8f7f8, + 0xfff8f8f8, 0xfff7f8f7, 0xfff7f8f7, 0xfff8f7f7, 0xfff8f7f7, 0xfff8f8f8, 0xfff7f7f8, 0xfff8f7f7, + 0xfff8f8f8, 0xfff8f8f7, 0xfff8f7f7, 0xfff7f7f8, 0xfff7f8f8, 0xfff8f7f7, 0xfff8f7f7, 0xfff8f8f7, + 0xfff8f7f7, 0xfff8f8f8, 0xfff8f8f8, 0xfff8f7f7, 0xfff8f8f8, 0xfff7f8f8, 0xfff7f8f8, 0xfff7f7f8, + 0xfff7f8f7, 0xfff7f8f7, 0xfff8f8f7, 0xfff8f8f8, 0xfff8f8f8, 0xfff7f7f8, 0xfff7f8f8, 0xfff8f7f7, + 0xfff7f7f8, 0xfff8f7f7, 0xfff8f8f8, 0xfff7f8f7, 0xfff7f8f7, 0xfff8f8f8, 0xffe9e8e9, 0xffdedbde, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797d79, 0xffb5bab5, 0xffb5bab5, + 0xffdedbde, 0xfff6f7f7, 0xfff7f6f7, 0xfff7f6f7, 0xfff6f7f6, 0xfff7f6f7, 0xfff6f6f7, 0xfff6f7f7, + 0xfff6f6f7, 0xfff7f6f7, 0xfff7f7f7, 0xfff6f7f6, 0xfff7f7f7, 0xfff6f7f7, 0xfff7f6f6, 0xfff7f7f6, + 0xfff6f6f6, 0xfff7f7f7, 0xfff6f6f6, 0xfff6f7f6, 0xfff7f7f6, 0xfff7f7f7, 0xfff6f6f7, 0xfff7f7f6, + 0xfff7f7f7, 0xfff7f7f6, 0xfff6f6f6, 0xfff6f7f6, 0xfff7f7f6, 0xfff7f7f6, 0xfff7f6f7, 0xfff7f6f7, + 0xfff6f7f6, 0xfff6f6f7, 0xfff7f7f7, 0xfff6f6f6, 0xfff6f7f7, 0xfff6f6f6, 0xfff6f7f6, 0xfff6f7f7, + 0xfff7f6f7, 0xfff6f6f6, 0xfff7f7f6, 0xfff6f7f6, 0xfff6f7f7, 0xfff7f7f7, 0xfff7f7f6, 0xfff7f7f7, + 0xfff6f6f6, 0xfff6f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f6f7, 0xfff7f6f7, 0xfff7f7f7, 0xfff6f7f7, + 0xfff6f7f6, 0xfff6f6f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f6f6, 0xfff7f7f6, 0xfff7f7f7, + 0xfff7f7f6, 0xfff6f6f7, 0xfff6f6f7, 0xfff7f7f6, 0xfff7f6f7, 0xfff7f6f6, 0xfff7f7f6, 0xfff6f7f7, + 0xfff7f6f7, 0xfff7f6f7, 0xfff7f6f7, 0xfff6f6f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f6, 0xfff6f6f6, + 0xfff6f7f6, 0xfff6f6f7, 0xfff7f6f7, 0xfff7f7f6, 0xfff6f6f7, 0xfff7f7f7, 0xfff7f6f6, 0xfff7f6f7, + 0xfff6f6f6, 0xfff6f7f7, 0xfff7f6f7, 0xfff7f7f6, 0xfff7f6f7, 0xfff7f6f6, 0xfff7f6f7, 0xfff7f7f6, + 0xfff6f7f7, 0xfff7f6f6, 0xfff7f6f6, 0xfff7f6f6, 0xfff7f6f6, 0xfff6f7f7, 0xfff6f6f7, 0xfff7f6f7, + 0xfff6f7f7, 0xfff6f7f7, 0xfff6f7f6, 0xfff7f6f7, 0xfff7f7f6, 0xfff7f7f6, 0xfff6f7f7, 0xfff7f6f7, + 0xfff7f7f7, 0xfff7f7f6, 0xfff6f6f6, 0xfff7f7f7, 0xfff6f6f7, 0xfff7f7f7, 0xfff6f6f7, 0xfff6f6f6, + 0xfff6f6f7, 0xfff6f6f7, 0xfff7f6f7, 0xfff7f6f6, 0xfff7f6f6, 0xfff7f6f7, 0xfff7f7f6, 0xfff6f6f7, + 0xfff7f7f7, 0xfff6f7f6, 0xfff6f7f6, 0xfff7f7f7, 0xfff7f6f7, 0xfff6f6f6, 0xfff7f7f7, 0xfff7f6f7, + 0xfff7f7f6, 0xfff6f6f7, 0xfff7f6f7, 0xfff6f6f7, 0xfff6f7f6, 0xfff6f7f6, 0xfff6f6f7, 0xfff7f6f7, + 0xfff7f6f6, 0xfff7f6f6, 0xfff6f7f6, 0xfff7f7f7, 0xfff6f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f6f6, + 0xfff6f7f6, 0xfff7f6f6, 0xfff6f7f7, 0xfff6f6f6, 0xfff7f6f7, 0xfff6f7f7, 0xfff7f6f7, 0xfff7f7f7, + 0xfff6f6f6, 0xfff6f6f6, 0xfff6f7f6, 0xfff7f7f6, 0xfff7f6f7, 0xfff6f7f7, 0xfff6f6f6, 0xfff6f6f7, + 0xfff6f6f7, 0xfff6f7f7, 0xfff6f7f7, 0xfff6f7f7, 0xfff6f6f6, 0xfff6f7f7, 0xfff7f6f7, 0xfff7f7f7, + 0xfff6f7f7, 0xfff7f6f7, 0xfff6f6f6, 0xfff7f6f7, 0xfff6f7f6, 0xfff7f6f6, 0xfff6f7f7, 0xfff6f7f7, + 0xfff6f7f7, 0xfff6f7f6, 0xfff6f7f7, 0xfff6f7f7, 0xfff7f7f7, 0xfff7f6f6, 0xfff7f6f6, 0xfff7f6f7, + 0xfff7f7f6, 0xfff7f7f6, 0xfff7f6f7, 0xfff6f6f7, 0xfff7f6f7, 0xfff7f6f6, 0xfff7f7f7, 0xfff7f6f7, + 0xfff6f6f7, 0xfff7f7f6, 0xfff6f7f6, 0xfff6f7f6, 0xfff7f7f7, 0xfff7f6f7, 0xfff6f7f6, 0xfff7f6f6, + 0xfff6f6f7, 0xfff6f7f7, 0xfff7f6f7, 0xfff7f6f6, 0xfff6f6f7, 0xfff7f7f6, 0xfff6f6f7, 0xfff7f6f6, + 0xfff6f6f7, 0xfff6f6f7, 0xfff7f7f6, 0xfff6f7f7, 0xfff7f6f6, 0xfff7f7f7, 0xffe9e8e9, 0xffdedbde, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797d79, 0xffb5bab5, 0xffb5bab5, + 0xffdedbde, 0xfff6f6f6, 0xfff6f6f5, 0xfff6f5f6, 0xfff5f5f6, 0xfff6f5f6, 0xfff6f6f6, 0xfff5f6f5, + 0xfff6f6f5, 0xfff5f6f6, 0xfff6f6f5, 0xfff6f5f6, 0xfff6f5f5, 0xfff6f5f6, 0xfff5f6f6, 0xfff6f5f6, + 0xfff6f5f6, 0xfff5f5f6, 0xfff6f6f6, 0xfff6f5f6, 0xfff5f6f6, 0xfff6f5f5, 0xfff6f6f6, 0xfff6f5f6, + 0xfff6f5f6, 0xfff5f5f6, 0xfff6f6f5, 0xfff5f6f5, 0xfff6f6f6, 0xfff6f5f6, 0xfff6f6f6, 0xfff6f6f5, + 0xfff6f5f5, 0xfff5f5f6, 0xfff5f6f5, 0xfff5f6f5, 0xfff6f6f5, 0xfff5f5f6, 0xfff6f5f6, 0xfff6f6f6, + 0xfff5f6f6, 0xfff6f5f6, 0xfff5f5f6, 0xfff5f6f6, 0xfff5f6f5, 0xfff5f6f5, 0xfff6f6f6, 0xfff6f6f6, + 0xfff5f5f5, 0xfff5f6f6, 0xfff6f6f5, 0xfff5f5f6, 0xfff5f6f5, 0xfff6f6f6, 0xfff6f6f6, 0xfff5f6f6, + 0xfff5f5f6, 0xfff5f6f6, 0xfff5f5f6, 0xfff5f5f5, 0xfff6f5f5, 0xfff6f6f6, 0xfff5f5f5, 0xfff5f6f6, + 0xfff6f5f6, 0xfff6f6f5, 0xfff5f6f5, 0xfff5f6f5, 0xfff6f6f6, 0xfff5f6f6, 0xfff6f5f6, 0xfff5f5f5, + 0xfff6f5f6, 0xfff6f6f6, 0xfff6f6f6, 0xfff5f5f6, 0xfff6f5f6, 0xfff5f6f5, 0xfff6f5f6, 0xfff6f6f5, + 0xfff6f6f6, 0xfff6f5f6, 0xfff6f6f5, 0xfff5f6f6, 0xfff5f6f6, 0xfff5f6f5, 0xfff5f5f5, 0xfff6f6f5, + 0xfff6f6f6, 0xfff6f6f6, 0xfff5f6f5, 0xfff5f6f5, 0xfff5f5f6, 0xfff6f6f5, 0xfff6f5f5, 0xfff6f6f6, + 0xfff5f5f6, 0xfff6f5f6, 0xfff6f5f6, 0xfff6f5f6, 0xfff5f5f6, 0xfff6f6f5, 0xfff6f5f5, 0xfff6f6f5, + 0xfff6f6f6, 0xfff6f5f6, 0xfff5f6f6, 0xfff5f6f5, 0xfff6f6f6, 0xfff6f6f6, 0xfff6f5f6, 0xfff5f5f5, + 0xfff5f6f5, 0xfff5f5f6, 0xfff5f6f5, 0xfff6f6f6, 0xfff5f6f5, 0xfff6f5f5, 0xfff6f6f5, 0xfff6f6f5, + 0xfff5f6f6, 0xfff6f5f5, 0xfff6f6f6, 0xfff6f5f5, 0xfff5f5f6, 0xfff6f6f5, 0xfff5f6f6, 0xfff6f6f6, + 0xfff5f6f5, 0xfff5f5f5, 0xfff5f6f6, 0xfff6f6f6, 0xfff5f6f6, 0xfff6f6f5, 0xfff5f6f6, 0xfff5f6f5, + 0xfff6f5f6, 0xfff6f5f5, 0xfff5f6f6, 0xfff6f6f5, 0xfff5f6f5, 0xfff6f5f5, 0xfff5f5f5, 0xfff6f6f6, + 0xfff5f6f6, 0xfff5f6f5, 0xfff6f6f6, 0xfff5f6f6, 0xfff5f6f6, 0xfff6f5f6, 0xfff5f6f6, 0xfff6f6f6, + 0xfff6f5f5, 0xfff6f6f6, 0xfff6f6f6, 0xfff5f6f5, 0xfff6f6f6, 0xfff6f5f5, 0xfff6f6f5, 0xfff6f5f6, + 0xfff6f6f5, 0xfff5f6f5, 0xfff6f5f6, 0xfff5f6f5, 0xfff6f5f6, 0xfff5f6f5, 0xfff6f6f6, 0xfff6f6f5, + 0xfff6f5f6, 0xfff6f6f6, 0xfff5f6f6, 0xfff5f6f6, 0xfff6f6f5, 0xfff5f5f6, 0xfff5f6f5, 0xfff6f6f6, + 0xfff6f6f6, 0xfff6f6f5, 0xfff6f6f6, 0xfff6f5f6, 0xfff5f6f6, 0xfff5f5f6, 0xfff6f5f5, 0xfff5f6f6, + 0xfff5f6f6, 0xfff6f5f6, 0xfff5f5f5, 0xfff5f5f6, 0xfff5f6f6, 0xfff6f6f5, 0xfff6f6f6, 0xfff5f6f5, + 0xfff5f6f5, 0xfff6f5f6, 0xfff6f5f6, 0xfff6f6f6, 0xfff6f5f6, 0xfff6f6f5, 0xfff6f6f6, 0xfff6f5f6, + 0xfff6f6f5, 0xfff5f5f5, 0xfff5f6f5, 0xfff6f6f6, 0xfff6f5f6, 0xfff6f5f6, 0xfff6f6f5, 0xfff6f6f5, + 0xfff6f6f6, 0xfff5f6f5, 0xfff6f6f5, 0xfff6f6f5, 0xfff6f5f6, 0xfff6f6f6, 0xfff6f6f5, 0xfff5f6f6, + 0xfff6f6f6, 0xfff6f6f5, 0xfff6f5f5, 0xfff6f5f5, 0xfff6f6f6, 0xfff6f6f6, 0xffe9e8e9, 0xffdedbde, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797d79, 0xffb5bab5, 0xffb5bab5, + 0xffdedbde, 0xfff4f4f4, 0xfff5f5f5, 0xfff5f5f4, 0xfff5f4f5, 0xfff5f4f4, 0xfff5f4f4, 0xfff5f4f5, + 0xfff4f5f4, 0xfff4f4f5, 0xfff5f4f4, 0xfff5f4f4, 0xfff4f5f5, 0xfff5f5f4, 0xfff4f5f4, 0xfff4f4f5, + 0xfff5f4f5, 0xfff4f5f5, 0xfff5f4f4, 0xfff5f5f5, 0xfff4f5f5, 0xfff4f5f5, 0xfff4f4f5, 0xfff4f5f4, + 0xfff4f5f4, 0xfff5f5f4, 0xfff5f5f4, 0xfff4f5f4, 0xfff5f4f5, 0xfff5f5f5, 0xfff4f5f5, 0xfff4f5f5, + 0xfff5f5f4, 0xfff4f4f4, 0xfff4f5f4, 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff4f5f4, 0xfff5f5f5, + 0xfff4f4f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff4f4f5, 0xfff4f5f4, 0xfff5f5f4, 0xfff5f5f5, 0xfff5f4f4, + 0xfff5f4f5, 0xfff5f4f5, 0xfff4f5f4, 0xfff5f4f5, 0xfff5f5f4, 0xfff5f5f5, 0xfff4f4f5, 0xfff4f5f4, + 0xfff4f4f4, 0xfff4f5f4, 0xfff5f5f4, 0xfff5f5f4, 0xfff4f4f5, 0xfff4f5f5, 0xfff4f5f5, 0xfff4f5f4, + 0xfff5f5f5, 0xfff4f5f5, 0xfff4f5f5, 0xfff5f4f5, 0xfff4f4f5, 0xfff5f4f5, 0xfff4f5f5, 0xfff4f5f4, + 0xfff5f5f5, 0xfff5f5f5, 0xfff5f5f5, 0xfff4f5f5, 0xfff4f4f5, 0xfff4f4f4, 0xfff5f5f5, 0xfff5f5f5, + 0xfff4f5f5, 0xfff5f4f5, 0xfff4f5f5, 0xfff4f5f5, 0xfff5f4f5, 0xfff5f5f5, 0xfff5f4f5, 0xfff4f5f5, + 0xfff5f5f4, 0xfff4f4f4, 0xfff4f5f5, 0xfff4f4f4, 0xfff4f5f5, 0xfff5f5f4, 0xfff5f5f4, 0xfff4f5f5, + 0xfff4f4f4, 0xfff4f5f4, 0xfff4f5f5, 0xfff5f5f4, 0xfff4f5f5, 0xfff4f4f5, 0xfff5f5f4, 0xfff4f4f5, + 0xfff5f5f4, 0xfff4f4f5, 0xfff4f5f5, 0xfff4f5f4, 0xfff5f4f5, 0xfff5f5f5, 0xfff4f4f5, 0xfff5f4f5, + 0xfff5f5f5, 0xfff4f5f4, 0xfff5f5f5, 0xfff5f5f5, 0xfff4f5f5, 0xfff4f5f4, 0xfff4f4f5, 0xfff4f4f5, + 0xfff4f4f5, 0xfff5f4f5, 0xfff4f4f4, 0xfff5f5f5, 0xfff4f4f5, 0xfff5f5f5, 0xfff4f4f5, 0xfff5f4f4, + 0xfff4f4f4, 0xfff5f4f4, 0xfff5f5f5, 0xfff5f5f4, 0xfff5f5f5, 0xfff4f5f4, 0xfff5f5f5, 0xfff4f5f5, + 0xfff4f5f4, 0xfff5f4f4, 0xfff4f4f4, 0xfff5f5f4, 0xfff4f4f5, 0xfff5f4f5, 0xfff5f4f5, 0xfff5f4f5, + 0xfff5f5f5, 0xfff5f4f4, 0xfff4f5f4, 0xfff4f4f5, 0xfff5f5f5, 0xfff5f4f4, 0xfff5f5f5, 0xfff5f4f5, + 0xfff4f5f5, 0xfff4f5f5, 0xfff5f4f4, 0xfff5f5f5, 0xfff5f5f4, 0xfff5f4f4, 0xfff4f5f4, 0xfff5f4f4, + 0xfff5f5f4, 0xfff4f4f5, 0xfff5f4f4, 0xfff5f4f5, 0xfff4f5f5, 0xfff4f5f5, 0xfff5f5f5, 0xfff4f5f5, + 0xfff4f5f4, 0xfff4f5f5, 0xfff5f5f5, 0xfff4f4f5, 0xfff4f5f5, 0xfff4f5f5, 0xfff4f4f5, 0xfff4f5f5, + 0xfff5f4f4, 0xfff5f5f5, 0xfff4f5f4, 0xfff5f5f4, 0xfff5f4f4, 0xfff4f5f5, 0xfff4f5f5, 0xfff5f5f5, + 0xfff4f4f4, 0xfff5f5f5, 0xfff5f5f5, 0xfff4f5f5, 0xfff5f5f5, 0xfff4f4f5, 0xfff5f5f5, 0xfff4f5f5, + 0xfff4f5f4, 0xfff5f5f4, 0xfff5f5f5, 0xfff5f4f5, 0xfff5f4f4, 0xfff4f4f4, 0xfff5f5f4, 0xfff5f5f4, + 0xfff5f4f5, 0xfff5f5f4, 0xfff4f5f4, 0xfff4f5f4, 0xfff5f5f5, 0xfff4f4f5, 0xfff5f4f5, 0xfff4f5f5, + 0xfff5f5f4, 0xfff5f4f5, 0xfff5f5f5, 0xfff4f5f5, 0xfff4f4f5, 0xfff5f4f5, 0xfff4f4f5, 0xfff5f5f4, + 0xfff5f5f5, 0xfff4f5f5, 0xfff4f4f5, 0xfff5f5f5, 0xfff4f5f4, 0xfff4f5f5, 0xffe9e8e9, 0xffdedbde, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff797c79, 0xffb5bab5, 0xffb5bab5, + 0xffdedbde, 0xfff3f4f4, 0xfff4f3f3, 0xfff3f4f4, 0xfff4f4f4, 0xfff3f4f4, 0xfff3f3f4, 0xfff4f3f3, + 0xfff3f3f4, 0xfff3f3f3, 0xfff4f4f4, 0xfff4f4f3, 0xfff3f4f4, 0xfff4f3f4, 0xfff3f4f4, 0xfff3f3f4, + 0xfff3f3f3, 0xfff3f4f3, 0xfff4f4f3, 0xfff4f4f3, 0xfff4f4f4, 0xfff4f4f3, 0xfff4f4f4, 0xfff3f3f4, + 0xfff4f4f4, 0xfff3f3f3, 0xfff3f4f3, 0xfff3f4f3, 0xfff4f4f3, 0xfff3f4f4, 0xfff4f4f4, 0xfff4f4f3, + 0xfff4f4f3, 0xfff3f3f3, 0xfff3f3f4, 0xfff4f3f3, 0xfff4f4f4, 0xfff4f3f4, 0xfff3f3f3, 0xfff4f4f3, + 0xfff4f3f4, 0xfff3f4f3, 0xfff3f4f3, 0xfff4f3f4, 0xfff3f4f3, 0xfff4f4f4, 0xfff4f4f4, 0xfff4f3f4, + 0xfff4f4f4, 0xfff4f4f3, 0xfff4f3f3, 0xfff3f4f3, 0xfff3f4f3, 0xfff4f3f4, 0xfff3f4f4, 0xfff3f4f3, + 0xfff4f3f3, 0xfff4f3f4, 0xfff3f3f4, 0xfff4f4f4, 0xfff3f3f3, 0xfff4f3f3, 0xfff3f3f4, 0xfff3f3f3, + 0xfff4f3f3, 0xfff3f3f4, 0xfff4f3f3, 0xfff3f3f4, 0xfff3f4f4, 0xfff4f3f3, 0xfff3f3f3, 0xfff4f3f4, + 0xfff4f4f4, 0xfff3f4f4, 0xfff4f3f3, 0xfff3f3f4, 0xfff3f3f3, 0xfff4f4f3, 0xfff4f4f4, 0xfff4f3f3, + 0xfff3f4f4, 0xfff3f3f4, 0xfff3f3f4, 0xfff3f4f3, 0xfff3f4f3, 0xfff3f4f4, 0xfff4f3f4, 0xfff4f3f3, + 0xfff4f4f4, 0xfff4f4f4, 0xfff4f4f4, 0xfff3f4f4, 0xfff4f4f4, 0xfff3f4f3, 0xfff4f4f4, 0xfff4f3f4, + 0xfff3f3f3, 0xfff4f3f3, 0xfff4f3f3, 0xfff3f3f3, 0xfff3f4f3, 0xfff4f4f3, 0xfff3f3f3, 0xfff3f3f3, + 0xfff4f4f3, 0xfff3f3f3, 0xfff4f3f3, 0xfff4f4f4, 0xfff4f4f4, 0xfff3f3f4, 0xfff3f4f3, 0xfff4f3f4, + 0xfff4f3f4, 0xfff4f4f4, 0xfff3f3f3, 0xfff4f4f3, 0xfff4f3f3, 0xfff3f3f3, 0xfff4f4f4, 0xfff3f4f4, + 0xfff3f3f4, 0xfff3f3f4, 0xfff4f4f4, 0xfff3f4f4, 0xfff3f3f3, 0xfff4f3f4, 0xfff3f4f4, 0xfff4f4f4, + 0xfff4f4f4, 0xfff3f4f3, 0xfff3f4f4, 0xfff3f4f4, 0xfff3f4f3, 0xfff4f4f4, 0xfff4f4f3, 0xfff3f3f4, + 0xfff4f3f4, 0xfff3f3f3, 0xfff3f3f4, 0xfff4f4f4, 0xfff4f3f4, 0xfff3f3f3, 0xfff3f4f4, 0xfff3f3f3, + 0xfff4f3f4, 0xfff3f4f4, 0xfff4f3f4, 0xfff4f3f4, 0xfff4f4f4, 0xfff3f3f4, 0xfff4f3f3, 0xfff4f4f4, + 0xfff4f3f3, 0xfff3f4f4, 0xfff4f4f4, 0xfff3f4f3, 0xfff4f3f4, 0xfff4f4f4, 0xfff4f3f3, 0xfff3f3f4, + 0xfff4f3f3, 0xfff4f4f3, 0xfff3f4f3, 0xfff3f4f3, 0xfff4f4f3, 0xfff3f4f3, 0xfff4f4f4, 0xfff4f4f3, + 0xfff4f4f4, 0xfff4f4f3, 0xfff4f3f3, 0xfff4f3f4, 0xfff3f3f4, 0xfff3f4f3, 0xfff3f3f3, 0xfff4f4f4, + 0xfff3f3f4, 0xfff4f4f4, 0xfff4f3f3, 0xfff4f4f4, 0xfff4f4f3, 0xfff3f3f3, 0xfff4f4f4, 0xfff3f3f4, + 0xfff4f3f3, 0xfff4f3f3, 0xfff3f4f4, 0xfff3f4f3, 0xfff3f4f3, 0xfff4f4f4, 0xfff3f3f4, 0xfff4f4f3, + 0xfff3f3f4, 0xfff4f3f4, 0xfff3f4f4, 0xfff3f3f3, 0xfff3f3f4, 0xfff3f3f3, 0xfff4f4f4, 0xfff4f4f4, + 0xfff3f3f4, 0xfff3f4f3, 0xfff4f4f3, 0xfff3f4f3, 0xfff3f3f4, 0xfff4f4f4, 0xfff4f4f3, 0xfff3f4f4, + 0xfff3f3f3, 0xfff4f3f4, 0xfff4f3f3, 0xfff3f3f4, 0xfff4f4f3, 0xfff3f4f3, 0xfff3f3f4, 0xfff3f4f3, + 0xfff4f3f4, 0xfff4f3f4, 0xfff4f4f3, 0xfff4f3f3, 0xfff3f4f4, 0xfff3f4f3, 0xffe9e8e9, 0xffdedbde, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff797c79, 0xffb5bab5, 0xffb5bab5, + 0xffdedbde, 0xfff3f3f3, 0xfff2f3f2, 0xfff3f2f3, 0xfff2f3f2, 0xfff2f3f3, 0xfff3f2f2, 0xfff2f3f2, + 0xfff2f3f3, 0xfff3f3f2, 0xfff3f3f2, 0xfff3f2f3, 0xfff2f3f3, 0xfff3f2f3, 0xfff2f2f2, 0xfff2f3f3, + 0xfff2f3f3, 0xfff2f2f2, 0xfff2f3f2, 0xfff2f3f2, 0xfff2f2f3, 0xfff2f3f3, 0xfff2f3f2, 0xfff2f2f3, + 0xfff3f2f3, 0xfff3f2f3, 0xfff3f3f3, 0xfff2f2f2, 0xfff3f3f2, 0xfff3f2f3, 0xfff3f2f3, 0xfff2f2f3, + 0xfff2f3f3, 0xfff3f3f3, 0xfff3f2f3, 0xfff3f3f3, 0xfff2f3f2, 0xfff3f3f3, 0xfff3f2f3, 0xfff3f2f2, + 0xfff2f3f3, 0xfff2f2f3, 0xfff3f3f3, 0xfff2f2f3, 0xfff2f3f2, 0xfff2f2f3, 0xfff2f2f2, 0xfff3f2f3, + 0xfff2f2f3, 0xfff3f2f2, 0xfff2f3f2, 0xfff2f2f2, 0xfff2f3f3, 0xfff2f3f2, 0xfff2f2f3, 0xfff3f2f3, + 0xfff3f2f3, 0xfff2f3f2, 0xfff3f2f2, 0xfff3f2f3, 0xfff2f2f2, 0xfff3f2f2, 0xfff3f3f3, 0xfff3f3f2, + 0xfff2f3f3, 0xfff2f3f2, 0xfff3f3f2, 0xfff3f3f2, 0xfff2f2f2, 0xfff2f3f2, 0xfff2f3f3, 0xfff2f3f3, + 0xfff3f2f2, 0xfff3f2f2, 0xfff3f2f3, 0xfff3f3f3, 0xfff3f2f3, 0xfff2f3f2, 0xfff2f2f3, 0xfff2f2f2, + 0xfff3f3f2, 0xfff2f3f3, 0xfff2f3f3, 0xfff2f3f3, 0xfff3f2f3, 0xfff2f2f3, 0xfff2f2f3, 0xfff2f3f2, + 0xfff2f3f3, 0xfff2f3f2, 0xfff2f3f3, 0xfff3f2f2, 0xfff3f3f3, 0xfff2f2f2, 0xfff2f2f3, 0xfff2f2f3, + 0xfff3f2f2, 0xfff3f3f2, 0xfff3f3f3, 0xfff3f3f3, 0xfff3f3f2, 0xfff2f2f2, 0xfff3f3f3, 0xfff3f2f2, + 0xfff3f2f2, 0xfff2f3f3, 0xfff3f2f3, 0xfff2f3f2, 0xfff2f2f2, 0xfff2f2f2, 0xfff3f3f3, 0xfff3f2f3, + 0xfff3f2f3, 0xfff2f2f3, 0xfff3f2f2, 0xfff3f3f3, 0xfff2f3f3, 0xfff3f2f2, 0xfff3f2f3, 0xfff3f3f3, + 0xfff2f3f3, 0xfff2f2f3, 0xfff2f2f3, 0xfff2f2f2, 0xfff3f3f2, 0xfff3f2f2, 0xfff3f2f2, 0xfff2f2f3, + 0xfff2f3f2, 0xfff2f3f2, 0xfff3f2f3, 0xfff2f2f2, 0xfff3f2f3, 0xfff2f2f3, 0xfff2f3f2, 0xfff3f3f2, + 0xfff2f3f3, 0xfff3f2f3, 0xfff2f2f3, 0xfff3f3f3, 0xfff3f2f2, 0xfff2f2f3, 0xfff3f3f2, 0xfff3f2f2, + 0xfff3f2f3, 0xfff2f2f3, 0xfff3f3f2, 0xfff3f3f2, 0xfff3f2f3, 0xfff2f3f2, 0xfff2f2f2, 0xfff3f2f2, + 0xfff2f3f3, 0xfff3f2f2, 0xfff2f2f3, 0xfff3f3f2, 0xfff3f2f2, 0xfff3f2f2, 0xfff3f3f3, 0xfff2f3f2, + 0xfff2f3f3, 0xfff2f3f3, 0xfff2f3f2, 0xfff3f2f3, 0xfff2f2f2, 0xfff2f3f2, 0xfff2f2f3, 0xfff3f3f3, + 0xfff3f2f3, 0xfff2f3f2, 0xfff3f2f2, 0xfff3f2f2, 0xfff3f2f2, 0xfff3f3f3, 0xfff3f3f3, 0xfff3f3f2, + 0xfff3f3f3, 0xfff3f2f2, 0xfff2f3f2, 0xfff3f2f3, 0xfff3f2f2, 0xfff2f2f3, 0xfff3f2f2, 0xfff3f2f3, + 0xfff2f2f3, 0xfff2f3f3, 0xfff2f2f2, 0xfff2f3f3, 0xfff2f2f3, 0xfff3f3f3, 0xfff2f3f2, 0xfff3f2f2, + 0xfff2f2f2, 0xfff3f2f3, 0xfff3f2f2, 0xfff2f2f3, 0xfff2f2f3, 0xfff3f2f3, 0xfff2f2f3, 0xfff2f3f2, + 0xfff3f3f3, 0xfff3f3f3, 0xfff3f2f2, 0xfff2f2f2, 0xfff2f3f3, 0xfff3f2f3, 0xfff2f3f2, 0xfff3f3f2, + 0xfff2f2f2, 0xfff3f3f2, 0xfff2f2f2, 0xfff2f3f3, 0xfff2f2f3, 0xfff3f2f3, 0xfff3f2f3, 0xfff3f2f3, + 0xfff3f3f2, 0xfff3f3f2, 0xfff3f3f2, 0xfff3f2f3, 0xfff3f2f3, 0xfff2f3f3, 0xffe9e8e9, 0xffdedbde, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff797c79, 0xffb5bab5, 0xffb5bab5, + 0xffdedbde, 0xfff2f1f2, 0xfff1f1f1, 0xfff2f2f1, 0xfff1f2f2, 0xfff2f2f2, 0xfff1f2f1, 0xfff1f1f2, + 0xfff2f2f2, 0xfff1f2f1, 0xfff1f2f2, 0xfff1f2f2, 0xfff1f2f2, 0xfff2f1f1, 0xfff2f1f2, 0xfff1f2f1, + 0xfff2f2f1, 0xfff1f1f1, 0xfff2f2f1, 0xfff1f1f1, 0xfff2f1f1, 0xfff2f1f1, 0xfff1f1f1, 0xfff2f1f2, + 0xfff1f2f2, 0xfff2f1f1, 0xfff1f2f2, 0xfff1f1f2, 0xfff1f1f1, 0xfff1f1f2, 0xfff1f2f1, 0xfff2f1f1, + 0xfff2f2f1, 0xfff1f1f1, 0xfff1f2f2, 0xfff1f2f2, 0xfff1f1f2, 0xfff1f2f2, 0xfff1f2f1, 0xfff1f1f1, + 0xfff1f2f2, 0xfff2f1f1, 0xfff2f2f2, 0xfff1f2f2, 0xfff2f2f1, 0xfff2f1f2, 0xfff2f1f2, 0xfff1f2f1, + 0xfff1f2f2, 0xfff1f1f2, 0xfff2f2f2, 0xfff1f1f2, 0xfff2f2f1, 0xfff1f2f1, 0xfff2f2f1, 0xfff1f2f2, + 0xfff1f2f1, 0xfff2f2f2, 0xfff1f1f1, 0xfff1f1f2, 0xfff1f1f2, 0xfff2f1f2, 0xfff1f1f2, 0xfff2f1f1, + 0xfff1f2f1, 0xfff2f1f1, 0xfff1f2f1, 0xfff1f2f2, 0xfff2f1f2, 0xfff1f1f1, 0xfff2f1f1, 0xfff2f1f2, + 0xfff1f2f1, 0xfff2f2f1, 0xfff2f1f1, 0xfff1f2f2, 0xfff1f1f1, 0xfff1f1f1, 0xfff2f1f2, 0xfff2f1f2, + 0xfff1f2f2, 0xfff1f1f2, 0xfff2f2f2, 0xfff2f1f1, 0xfff2f2f1, 0xfff2f2f1, 0xfff2f1f1, 0xfff1f2f1, + 0xfff2f1f1, 0xfff1f2f1, 0xfff2f1f1, 0xfff2f2f1, 0xfff1f1f2, 0xfff2f1f1, 0xfff2f1f2, 0xfff1f1f1, + 0xfff1f2f1, 0xfff2f1f1, 0xfff1f2f2, 0xfff2f2f2, 0xfff1f1f1, 0xfff1f1f1, 0xfff1f2f1, 0xfff1f1f1, + 0xfff1f1f2, 0xfff1f2f2, 0xfff1f2f1, 0xfff2f1f1, 0xfff1f1f1, 0xfff1f2f1, 0xfff1f1f2, 0xfff1f1f2, + 0xfff2f1f1, 0xfff1f1f1, 0xfff1f2f2, 0xfff1f1f2, 0xfff2f1f1, 0xfff2f2f1, 0xfff2f2f2, 0xfff2f1f1, + 0xfff1f1f1, 0xfff1f1f2, 0xfff1f1f1, 0xfff2f1f2, 0xfff1f1f1, 0xfff1f1f2, 0xfff1f2f1, 0xfff2f1f1, + 0xfff1f2f2, 0xfff1f1f2, 0xfff2f1f2, 0xfff1f1f2, 0xfff2f1f1, 0xfff2f1f1, 0xfff2f2f1, 0xfff1f1f1, + 0xfff2f2f1, 0xfff1f1f1, 0xfff1f2f2, 0xfff2f1f2, 0xfff2f1f1, 0xfff1f1f1, 0xfff1f2f1, 0xfff1f2f1, + 0xfff2f2f1, 0xfff1f1f1, 0xfff2f1f1, 0xfff1f2f2, 0xfff1f1f1, 0xfff1f2f2, 0xfff2f2f2, 0xfff2f1f2, + 0xfff2f1f1, 0xfff2f2f1, 0xfff1f1f2, 0xfff1f2f2, 0xfff2f2f1, 0xfff2f1f2, 0xfff2f1f1, 0xfff1f2f1, + 0xfff1f2f2, 0xfff2f2f1, 0xfff2f2f1, 0xfff2f1f2, 0xfff1f1f2, 0xfff2f2f2, 0xfff1f2f2, 0xfff2f1f2, + 0xfff1f2f1, 0xfff1f2f2, 0xfff1f2f2, 0xfff1f2f1, 0xfff1f2f1, 0xfff1f2f2, 0xfff1f1f1, 0xfff2f2f2, + 0xfff1f1f2, 0xfff2f1f2, 0xfff1f1f1, 0xfff1f2f1, 0xfff1f1f1, 0xfff1f2f1, 0xfff1f2f2, 0xfff2f1f1, + 0xfff2f1f1, 0xfff1f2f2, 0xfff1f2f2, 0xfff2f1f1, 0xfff2f1f2, 0xfff1f2f2, 0xfff2f1f1, 0xfff1f1f1, + 0xfff2f1f1, 0xfff2f1f2, 0xfff2f1f1, 0xfff1f1f2, 0xfff2f2f1, 0xfff1f1f1, 0xfff1f1f2, 0xfff2f1f1, + 0xfff2f1f2, 0xfff2f2f2, 0xfff1f2f2, 0xfff2f2f2, 0xfff1f2f1, 0xfff1f1f2, 0xfff2f2f2, 0xfff1f1f1, + 0xfff1f2f2, 0xfff2f1f1, 0xfff2f1f1, 0xfff2f1f2, 0xfff1f1f2, 0xfff2f1f2, 0xfff1f1f2, 0xfff1f1f1, + 0xfff2f1f2, 0xfff1f2f2, 0xfff1f1f2, 0xfff2f1f1, 0xfff2f1f1, 0xfff2f1f2, 0xffe9e8e9, 0xffdedbde, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff797c79, 0xffb5bab5, 0xffb5bab5, + 0xffdedbde, 0xfff1f0f0, 0xfff1f1f1, 0xfff1f0f0, 0xfff0f1f0, 0xfff0f0f1, 0xfff1f0f1, 0xfff0f0f1, + 0xfff0f1f1, 0xfff0f1f0, 0xfff1f1f1, 0xfff0f1f1, 0xfff1f1f1, 0xfff1f0f0, 0xfff1f0f0, 0xfff0f1f1, + 0xfff0f0f0, 0xfff0f1f0, 0xfff0f1f0, 0xfff1f1f0, 0xfff0f0f0, 0xfff1f0f0, 0xfff0f1f1, 0xfff1f1f0, + 0xfff0f1f0, 0xfff1f0f1, 0xfff0f1f1, 0xfff1f0f0, 0xfff1f1f1, 0xfff1f0f0, 0xfff1f0f0, 0xfff1f0f1, + 0xfff0f1f1, 0xfff1f1f1, 0xfff1f1f0, 0xfff1f0f1, 0xfff0f0f0, 0xfff1f1f1, 0xfff0f0f1, 0xfff0f1f0, + 0xfff1f1f0, 0xfff0f0f0, 0xfff0f1f1, 0xfff0f1f1, 0xfff1f1f0, 0xfff0f1f1, 0xfff1f1f1, 0xfff1f0f0, + 0xfff1f0f1, 0xfff1f0f1, 0xfff0f0f1, 0xfff1f1f0, 0xfff0f0f0, 0xfff0f1f0, 0xfff1f1f0, 0xfff0f0f1, + 0xfff1f0f0, 0xfff1f1f1, 0xfff1f1f1, 0xfff0f0f0, 0xfff0f0f0, 0xfff1f1f1, 0xfff1f0f0, 0xfff0f1f1, + 0xfff1f1f0, 0xfff1f0f0, 0xfff1f0f0, 0xfff1f0f1, 0xfff0f0f1, 0xfff0f0f1, 0xfff1f0f1, 0xfff1f0f1, + 0xfff1f1f1, 0xfff0f1f1, 0xfff0f0f1, 0xfff1f0f1, 0xfff0f1f1, 0xfff0f0f0, 0xfff1f1f1, 0xfff1f1f0, + 0xfff1f1f1, 0xfff1f0f0, 0xfff0f0f0, 0xfff1f0f1, 0xfff0f0f1, 0xfff0f0f0, 0xfff1f0f1, 0xfff1f1f0, + 0xfff1f0f0, 0xfff1f0f0, 0xfff0f0f0, 0xfff1f1f0, 0xfff0f0f1, 0xfff0f0f1, 0xfff1f0f0, 0xfff1f1f1, + 0xfff1f0f1, 0xfff0f0f1, 0xfff0f0f1, 0xfff0f0f0, 0xfff1f0f0, 0xfff0f0f0, 0xfff0f0f1, 0xfff1f1f1, + 0xfff0f0f0, 0xfff0f1f0, 0xfff0f0f0, 0xfff1f0f1, 0xfff0f0f0, 0xfff0f0f0, 0xfff0f1f0, 0xfff0f1f0, + 0xfff1f1f0, 0xfff1f1f1, 0xfff0f1f1, 0xfff1f0f0, 0xfff0f0f0, 0xfff1f0f0, 0xfff0f0f0, 0xfff0f0f1, + 0xfff0f0f1, 0xfff1f1f1, 0xfff0f0f0, 0xfff0f0f0, 0xfff0f1f0, 0xfff0f1f1, 0xfff1f0f0, 0xfff1f1f1, + 0xfff0f0f0, 0xfff0f1f0, 0xfff0f1f0, 0xfff1f0f0, 0xfff1f0f0, 0xfff0f1f1, 0xfff0f0f1, 0xfff1f0f0, + 0xfff0f0f1, 0xfff0f0f1, 0xfff0f0f1, 0xfff1f1f0, 0xfff1f0f0, 0xfff1f0f0, 0xfff0f1f0, 0xfff0f0f0, + 0xfff0f1f1, 0xfff0f0f0, 0xfff0f1f1, 0xfff0f0f1, 0xfff0f1f1, 0xfff1f1f0, 0xfff1f0f0, 0xfff1f1f0, + 0xfff0f0f0, 0xfff0f0f0, 0xfff0f0f0, 0xfff0f0f1, 0xfff1f0f0, 0xfff0f0f0, 0xfff0f0f0, 0xfff0f1f0, + 0xfff0f1f0, 0xfff0f0f1, 0xfff1f0f1, 0xfff0f1f1, 0xfff1f1f0, 0xfff1f1f1, 0xfff1f0f0, 0xfff0f0f0, + 0xfff0f0f1, 0xfff0f0f0, 0xfff0f0f0, 0xfff0f1f0, 0xfff1f0f1, 0xfff0f1f0, 0xfff0f1f1, 0xfff0f0f0, + 0xfff0f0f0, 0xfff0f0f0, 0xfff1f0f0, 0xfff0f1f1, 0xfff1f1f0, 0xfff0f0f0, 0xfff0f0f0, 0xfff0f0f1, + 0xfff0f0f1, 0xfff1f0f0, 0xfff0f1f1, 0xfff0f1f1, 0xfff1f1f0, 0xfff1f1f0, 0xfff0f1f0, 0xfff1f0f1, + 0xfff0f0f1, 0xfff1f1f0, 0xfff0f0f1, 0xfff0f1f0, 0xfff0f1f1, 0xfff1f0f0, 0xfff0f0f1, 0xfff1f1f0, + 0xfff0f1f0, 0xfff0f0f0, 0xfff0f0f1, 0xfff0f1f1, 0xfff0f0f1, 0xfff1f0f1, 0xfff1f1f0, 0xfff1f0f1, + 0xfff1f0f0, 0xfff0f0f1, 0xfff0f1f0, 0xfff0f0f1, 0xfff1f0f1, 0xfff1f0f0, 0xfff1f0f0, 0xfff0f0f1, + 0xfff0f0f0, 0xfff0f0f1, 0xfff1f0f0, 0xfff0f0f0, 0xfff0f0f0, 0xfff0f1f1, 0xffe9e8e9, 0xffdedbde, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797b79, 0xffb5b6b5, 0xffb5b6b5, + 0xffd6dbd6, 0xfff0eff0, 0xffefeff0, 0xfff0f0ef, 0xfff0eff0, 0xfff0eff0, 0xffefefef, 0xffeff0f0, + 0xfff0efef, 0xffefefef, 0xffefefef, 0xfff0efef, 0xffefeff0, 0xfff0efef, 0xffeff0f0, 0xfff0efef, + 0xffefefef, 0xffefefef, 0xffeff0f0, 0xfff0efef, 0xffefefef, 0xffeff0f0, 0xffefeff0, 0xffefefef, + 0xfff0f0f0, 0xfff0eff0, 0xfff0efef, 0xfff0eff0, 0xfff0efef, 0xfff0f0ef, 0xfff0eff0, 0xfff0efef, + 0xffeff0f0, 0xffefeff0, 0xfff0efef, 0xfff0f0ef, 0xffefeff0, 0xffeff0f0, 0xfff0f0f0, 0xfff0efef, + 0xfff0f0ef, 0xffefefef, 0xffeff0f0, 0xfff0f0ef, 0xffefefef, 0xffefefef, 0xffefefef, 0xfff0eff0, + 0xffefefef, 0xffefefef, 0xfff0eff0, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xfff0efef, + 0xfff0efef, 0xfff0f0f0, 0xffeff0ef, 0xffeff0f0, 0xfff0f0f0, 0xffefefef, 0xffefefef, 0xfff0f0f0, + 0xffefefef, 0xffefefef, 0xffefefef, 0xfff0efef, 0xfff0f0f0, 0xfff0f0f0, 0xfff0efef, 0xffeff0f0, + 0xfff0efef, 0xffefeff0, 0xfff0eff0, 0xffeff0ef, 0xfff0eff0, 0xfff0eff0, 0xfff0eff0, 0xffeff0f0, + 0xffeff0ef, 0xfff0eff0, 0xffeff0f0, 0xfff0eff0, 0xffefefef, 0xfff0efef, 0xfff0f0ef, 0xffefefef, + 0xffeff0f0, 0xffeff0ef, 0xffefeff0, 0xffeff0ef, 0xffeff0ef, 0xffefeff0, 0xfff0f0f0, 0xffefefef, + 0xffefeff0, 0xfff0f0ef, 0xfff0efef, 0xfff0efef, 0xffefeff0, 0xfff0f0ef, 0xffeff0ef, 0xffefefef, + 0xfff0efef, 0xffefefef, 0xffefefef, 0xfff0f0f0, 0xfff0f0ef, 0xfff0f0ef, 0xffeff0f0, 0xfff0f0ef, + 0xffefefef, 0xfff0eff0, 0xfff0efef, 0xfff0efef, 0xffefeff0, 0xfff0efef, 0xffeff0f0, 0xfff0f0ef, + 0xffeff0f0, 0xffefefef, 0xffefeff0, 0xfff0eff0, 0xfff0efef, 0xfff0f0f0, 0xfff0efef, 0xfff0f0ef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffeff0f0, 0xfff0eff0, 0xffefeff0, 0xffeff0ef, 0xffefefef, + 0xffeff0f0, 0xffefeff0, 0xffefeff0, 0xffefeff0, 0xffeff0ef, 0xffefeff0, 0xffeff0ef, 0xfff0eff0, + 0xffeff0ef, 0xfff0eff0, 0xfff0efef, 0xfff0f0ef, 0xffeff0f0, 0xfff0efef, 0xffeff0f0, 0xfff0f0ef, + 0xfff0efef, 0xfff0efef, 0xffefefef, 0xffefeff0, 0xffefefef, 0xfff0efef, 0xffefefef, 0xfff0efef, + 0xfff0f0f0, 0xfff0f0ef, 0xfff0efef, 0xfff0eff0, 0xffefeff0, 0xffefefef, 0xffeff0ef, 0xffeff0ef, + 0xffefeff0, 0xffeff0ef, 0xfff0f0ef, 0xfff0efef, 0xffeff0ef, 0xfff0f0f0, 0xfff0f0ef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffeff0ef, 0xfff0f0ef, 0xffefeff0, 0xffefeff0, 0xffefefef, 0xffefefef, + 0xffefeff0, 0xfff0eff0, 0xffeff0f0, 0xffeff0ef, 0xffefefef, 0xffeff0ef, 0xffeff0ef, 0xfff0f0f0, + 0xfff0f0f0, 0xfff0eff0, 0xfff0efef, 0xffefefef, 0xfff0eff0, 0xffeff0f0, 0xffefeff0, 0xffefeff0, + 0xfff0f0ef, 0xfff0f0ef, 0xffefefef, 0xffefeff0, 0xfff0efef, 0xfff0f0f0, 0xfff0efef, 0xffefefef, + 0xfff0eff0, 0xffefefef, 0xffefeff0, 0xffeff0ef, 0xfff0efef, 0xffefefef, 0xffefeff0, 0xffeff0f0, + 0xffeff0ef, 0xfff0f0ef, 0xffeff0ef, 0xffefefef, 0xffefeff0, 0xffefefef, 0xffe6e8e6, 0xffd6dbd6, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797b79, 0xffb5b6b5, 0xffb5b6b5, + 0xffd6dbd6, 0xffefeeee, 0xffeeeeee, 0xffeeefee, 0xffeeeeee, 0xffeeeeef, 0xffeeeeee, 0xffefefee, + 0xffeeefef, 0xffeeefee, 0xffefefee, 0xffefefee, 0xffefefee, 0xffeeefee, 0xffeeeeee, 0xffeeeeee, + 0xffefefef, 0xffeeeeee, 0xffeeeeee, 0xffeeeeef, 0xffefeeee, 0xffefefee, 0xffeeefee, 0xffeeeeee, + 0xffeeeeee, 0xffeeefef, 0xffeeeeee, 0xffeeefee, 0xffeeefef, 0xffefeeee, 0xffefeeee, 0xffeeeeef, + 0xffeeeeee, 0xffeeefee, 0xffeeeeef, 0xffeeeeee, 0xffeeeeef, 0xffeeefee, 0xffefeeef, 0xffefeeee, + 0xffeeefee, 0xffefeeef, 0xffefeeee, 0xffefefee, 0xffefefef, 0xffefeeef, 0xffefefef, 0xffeeeeee, + 0xffeeefee, 0xffeeefee, 0xffeeeeee, 0xffeeeeee, 0xffefeeef, 0xffeeefef, 0xffefeeee, 0xffeeefee, + 0xffeeeeee, 0xffeeefef, 0xffeeefee, 0xffefeeee, 0xffeeefef, 0xffeeeeef, 0xffeeefee, 0xffefeeef, + 0xffeeefee, 0xffefefee, 0xffeeefee, 0xffeeefee, 0xffeeefee, 0xffeeefef, 0xffefeeef, 0xffeeefee, + 0xffefefef, 0xffeeeeef, 0xffefefee, 0xffeeeeee, 0xffefefee, 0xffefeeef, 0xffefeeee, 0xffefefee, + 0xffeeefee, 0xffeeefee, 0xffeeeeef, 0xffeeeeee, 0xffefeeef, 0xffeeeeef, 0xffeeeeee, 0xffeeefee, + 0xffeeeeef, 0xffefeeef, 0xffeeeeef, 0xffeeefef, 0xffefefef, 0xffefefee, 0xffefeeef, 0xffeeeeef, + 0xffeeeeee, 0xffeeefee, 0xffefeeee, 0xffeeeeee, 0xffeeeeef, 0xffeeeeee, 0xffefefef, 0xffefeeee, + 0xffefeeee, 0xffeeefef, 0xffeeeeef, 0xffefeeee, 0xffefeeee, 0xffefeeef, 0xffeeeeee, 0xffeeeeee, + 0xffefefef, 0xffeeefef, 0xffefeeee, 0xffefefef, 0xffeeeeee, 0xffefeeee, 0xffeeeeee, 0xffeeeeee, + 0xffefeeef, 0xffeeefee, 0xffeeeeee, 0xffeeefef, 0xffeeeeee, 0xffeeefef, 0xffeeeeef, 0xffeeeeee, + 0xffefefef, 0xffeeefee, 0xffeeefef, 0xffeeeeef, 0xffeeeeef, 0xffefefee, 0xffefeeef, 0xffeeeeee, + 0xffeeeeee, 0xffefefef, 0xffeeeeef, 0xffefeeef, 0xffeeeeee, 0xffeeefee, 0xffefefef, 0xffefeeee, + 0xffeeefef, 0xffeeefef, 0xffefefef, 0xffeeeeef, 0xffeeeeee, 0xffefeeee, 0xffeeeeee, 0xffeeeeee, + 0xffeeeeee, 0xffeeefee, 0xffeeeeee, 0xffefeeee, 0xffefefef, 0xffeeefee, 0xffefeeee, 0xffeeefef, + 0xffefeeee, 0xffefeeee, 0xffeeeeee, 0xffeeeeee, 0xffefeeef, 0xffefeeee, 0xffefeeee, 0xffeeefef, + 0xffeeefee, 0xffeeefee, 0xffeeeeee, 0xffefefef, 0xffeeefee, 0xffefeeee, 0xffeeeeee, 0xffefefee, + 0xffefefee, 0xffeeeeee, 0xffeeeeee, 0xffeeeeee, 0xffeeefee, 0xffeeeeef, 0xffefeeef, 0xffefeeee, + 0xffeeeeee, 0xffefefee, 0xffefefee, 0xffeeefee, 0xffefefee, 0xffefeeee, 0xffeeefef, 0xffeeefee, + 0xffeeeeee, 0xffeeeeef, 0xffeeeeef, 0xffeeeeee, 0xffeeeeef, 0xffefeeef, 0xffefeeee, 0xffeeefef, + 0xffeeeeee, 0xffefefee, 0xffeeeeee, 0xffefeeef, 0xffeeefef, 0xffeeeeee, 0xffeeeeee, 0xffeeeeef, + 0xffefeeef, 0xffeeeeee, 0xffeeeeee, 0xffeeeeee, 0xffefeeef, 0xffefeeef, 0xffeeeeee, 0xffeeeeef, + 0xffefefee, 0xffeeeeee, 0xffefefef, 0xffeeefee, 0xffeeeeef, 0xffeeeeef, 0xffe6e8e6, 0xffd6dbd6, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797b79, 0xffb5b6b5, 0xffb5b6b5, + 0xffd6dbd6, 0xffeeeded, 0xffeeedee, 0xffeeeded, 0xffeeeded, 0xffededed, 0xffedeeed, 0xffedeeed, + 0xffedeeee, 0xffeeeded, 0xffedeeee, 0xffedeeed, 0xffeeedee, 0xffeeeeed, 0xffededed, 0xffeeeded, + 0xffeeeded, 0xffededee, 0xffeeeded, 0xffededed, 0xffededed, 0xffedeeed, 0xffeeedee, 0xffeeeded, + 0xffededee, 0xffeeeded, 0xffededed, 0xffededee, 0xffeeeeed, 0xffededed, 0xffededed, 0xffeeedee, + 0xffeeeded, 0xffedeeed, 0xffedeeed, 0xffededed, 0xffededed, 0xffeeeded, 0xffededed, 0xffededed, + 0xffeeeeed, 0xffedeeed, 0xffededed, 0xffedeeed, 0xffededed, 0xffeeeeed, 0xffeeeded, 0xffeeeded, + 0xffeeeeed, 0xffeeedee, 0xffeeeded, 0xffeeeeee, 0xffedeeed, 0xffeeeded, 0xffedeeee, 0xffededee, + 0xffeeeded, 0xffeeedee, 0xffedeeee, 0xffededee, 0xffededed, 0xffedeeee, 0xffeeeded, 0xffeeedee, + 0xffededed, 0xffeeedee, 0xffedeeee, 0xffeeedee, 0xffeeeeee, 0xffededee, 0xffededee, 0xffeeedee, + 0xffedeeed, 0xffededed, 0xffeeeded, 0xffeeedee, 0xffededee, 0xffeeeded, 0xffededee, 0xffededed, + 0xffedeeed, 0xffedeeed, 0xffededed, 0xffededed, 0xffededed, 0xffededed, 0xffedeeee, 0xffededee, + 0xffeeeded, 0xffededed, 0xffeeeded, 0xffededed, 0xffedeeed, 0xffeeedee, 0xffededed, 0xffedeeed, + 0xffeeedee, 0xffededed, 0xffeeedee, 0xffededed, 0xffededed, 0xffeeedee, 0xffedeeed, 0xffeeeded, + 0xffedeeed, 0xffededee, 0xffeeedee, 0xffeeeeed, 0xffedeeed, 0xffeeeeed, 0xffededee, 0xffededee, + 0xffedeeed, 0xffeeeded, 0xffededed, 0xffedeeed, 0xffeeeeee, 0xffeeeded, 0xffeeeeed, 0xffeeeded, + 0xffeeedee, 0xffededed, 0xffeeeded, 0xffeeeeed, 0xffededee, 0xffeeeeee, 0xffededed, 0xffeeeeed, + 0xffeeeded, 0xffeeedee, 0xffededed, 0xffeeedee, 0xffeeeeed, 0xffedeeee, 0xffeeedee, 0xffededed, + 0xffeeeeed, 0xffededed, 0xffeeeded, 0xffededed, 0xffededee, 0xffedeeed, 0xffeeeeed, 0xffeeeeee, + 0xffedeeee, 0xffededed, 0xffeeeded, 0xffeeeeee, 0xffeeedee, 0xffededed, 0xffeeedee, 0xffedeeed, + 0xffeeeeed, 0xffededed, 0xffededed, 0xffedeeee, 0xffedeeed, 0xffedeeed, 0xffededee, 0xffeeeeee, + 0xffededed, 0xffeeeeee, 0xffedeeed, 0xffeeeded, 0xffeeeeed, 0xffeeeeee, 0xffedeeed, 0xffeeedee, + 0xffedeeee, 0xffededee, 0xffeeeded, 0xffedeeed, 0xffeeeded, 0xffedeeed, 0xffededee, 0xffededee, + 0xffeeeded, 0xffededee, 0xffededed, 0xffeeeded, 0xffedeeed, 0xffeeeeed, 0xffededee, 0xffeeedee, + 0xffededed, 0xffeeedee, 0xffeeedee, 0xffededed, 0xffedeeed, 0xffedeeee, 0xffeeeeee, 0xffededee, + 0xffededee, 0xffedeeed, 0xffeeeeed, 0xffedeeee, 0xffededed, 0xffeeeeed, 0xffedeeed, 0xffededed, + 0xffededee, 0xffeeedee, 0xffeeeeed, 0xffedeeee, 0xffeeedee, 0xffedeeee, 0xffededed, 0xffedeeed, + 0xffedeeed, 0xffededed, 0xffeeeded, 0xffedeeed, 0xffeeeded, 0xffedeeed, 0xffededed, 0xffeeeeed, + 0xffedeeed, 0xffeeeeee, 0xffedeeee, 0xffedeeed, 0xffedeeed, 0xffeeeded, 0xffe6e8e6, 0xffd6dbd6, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797b79, 0xffb5b6b5, 0xffb5b6b5, + 0xffd6dbd6, 0xffecedec, 0xffedeced, 0xffededec, 0xffececec, 0xffedeced, 0xffeceded, 0xffedeced, + 0xffeceded, 0xffededed, 0xffedecec, 0xffecedec, 0xffececec, 0xffeceded, 0xffececec, 0xffededed, + 0xffeceded, 0xffeceded, 0xffededec, 0xffedeced, 0xffedeced, 0xffededec, 0xffedeced, 0xffedeced, + 0xffecedec, 0xffecedec, 0xffececec, 0xffecedec, 0xffededec, 0xffecedec, 0xffececec, 0xffecedec, + 0xffececed, 0xffececec, 0xffededec, 0xffececed, 0xffecedec, 0xffededec, 0xffececed, 0xffedecec, + 0xffececec, 0xffecedec, 0xffededec, 0xffecedec, 0xffeceded, 0xffedecec, 0xffedeced, 0xffececed, + 0xffecedec, 0xffedecec, 0xffeceded, 0xffececec, 0xffededed, 0xffececed, 0xffedecec, 0xffededec, + 0xffeceded, 0xffededed, 0xffededec, 0xffedecec, 0xffececec, 0xffececed, 0xffececed, 0xffeceded, + 0xffededec, 0xffececed, 0xffececec, 0xffecedec, 0xffededec, 0xffecedec, 0xffececed, 0xffededed, + 0xffececec, 0xffececed, 0xffedeced, 0xffececed, 0xffecedec, 0xffedeced, 0xffececed, 0xffecedec, + 0xffececec, 0xffececec, 0xffedecec, 0xffededed, 0xffededec, 0xffececed, 0xffececec, 0xffececed, + 0xffececec, 0xffedeced, 0xffececed, 0xffececed, 0xffececec, 0xffededed, 0xffededed, 0xffedecec, + 0xffedeced, 0xffedecec, 0xffececec, 0xffedecec, 0xffeceded, 0xffedecec, 0xffececed, 0xffeceded, + 0xffececec, 0xffececed, 0xffededec, 0xffeceded, 0xffececed, 0xffececed, 0xffeceded, 0xffededec, + 0xffececed, 0xffeceded, 0xffedecec, 0xffececed, 0xffededec, 0xffecedec, 0xffececec, 0xffedecec, + 0xffedeced, 0xffececec, 0xffedecec, 0xffececed, 0xffededec, 0xffeceded, 0xffededec, 0xffececec, + 0xffedecec, 0xffededec, 0xffededec, 0xffececec, 0xffececed, 0xffecedec, 0xffececec, 0xffecedec, + 0xffececec, 0xffededec, 0xffedeced, 0xffedecec, 0xffececec, 0xffededed, 0xffecedec, 0xffededec, + 0xffedeced, 0xffedeced, 0xffecedec, 0xffecedec, 0xffececec, 0xffececed, 0xffedecec, 0xffececec, + 0xffececec, 0xffedeced, 0xffeceded, 0xffececec, 0xffececec, 0xffececec, 0xffececec, 0xffececec, + 0xffedeced, 0xffececed, 0xffededed, 0xffedeced, 0xffededed, 0xffedecec, 0xffececed, 0xffededed, + 0xffedeced, 0xffececed, 0xffedecec, 0xffececed, 0xffededec, 0xffededed, 0xffededec, 0xffecedec, + 0xffececec, 0xffececed, 0xffececec, 0xffedeced, 0xffededec, 0xffedeced, 0xffedecec, 0xffedeced, + 0xffececed, 0xffededed, 0xffececec, 0xffedeced, 0xffececed, 0xffedeced, 0xffececec, 0xffececed, + 0xffececed, 0xffececec, 0xffededed, 0xffedecec, 0xffecedec, 0xffecedec, 0xffededec, 0xffededed, + 0xffececec, 0xffececec, 0xffedeced, 0xffededec, 0xffececed, 0xffeceded, 0xffeceded, 0xffecedec, + 0xffeceded, 0xffececec, 0xffececec, 0xffedecec, 0xffecedec, 0xffeceded, 0xffececec, 0xffedeced, + 0xffedeced, 0xffecedec, 0xffededed, 0xffededec, 0xffededed, 0xffededed, 0xffe6e8e6, 0xffd6dbd6, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797b79, 0xffb5b6b5, 0xffb5b6b5, + 0xffd6dbd6, 0xffebebeb, 0xffebebec, 0xffecebeb, 0xffebecec, 0xffebecec, 0xffececeb, 0xffebebec, + 0xffebecec, 0xffebebeb, 0xffebecec, 0xffecebec, 0xffecebeb, 0xffebebeb, 0xffecebec, 0xffecebeb, + 0xffebeceb, 0xffebebec, 0xffecebeb, 0xffececeb, 0xffecebeb, 0xffebeceb, 0xffebebec, 0xffebecec, + 0xffebecec, 0xffecebec, 0xffecebec, 0xffecebec, 0xffecebec, 0xffecebeb, 0xffecebec, 0xffecebec, + 0xffecebeb, 0xffebebeb, 0xffebeceb, 0xffececec, 0xffecebeb, 0xffecebec, 0xffebecec, 0xffebeceb, + 0xffebebec, 0xffececec, 0xffecebeb, 0xffecebec, 0xffececeb, 0xffececeb, 0xffebeceb, 0xffebebec, + 0xffececeb, 0xffebebec, 0xffecebec, 0xffececec, 0xffececeb, 0xffebeceb, 0xffebecec, 0xffecebeb, + 0xffebecec, 0xffebecec, 0xffececec, 0xffecebeb, 0xffecebec, 0xffececec, 0xffebecec, 0xffebecec, + 0xffececec, 0xffebebeb, 0xffececeb, 0xffececeb, 0xffecebec, 0xffecebeb, 0xffececeb, 0xffebebec, + 0xffecebec, 0xffececeb, 0xffececec, 0xffebebec, 0xffebebeb, 0xffececec, 0xffebecec, 0xffebebec, + 0xffececec, 0xffebebec, 0xffebecec, 0xffecebec, 0xffebebeb, 0xffecebec, 0xffebebec, 0xffececeb, + 0xffecebeb, 0xffececec, 0xffececeb, 0xffebebeb, 0xffecebeb, 0xffebebec, 0xffebebec, 0xffececeb, + 0xffececeb, 0xffebeceb, 0xffececeb, 0xffececeb, 0xffebebeb, 0xffebebec, 0xffececeb, 0xffebebec, + 0xffececeb, 0xffecebeb, 0xffebebec, 0xffecebec, 0xffecebec, 0xffececec, 0xffebeceb, 0xffececec, + 0xffebebec, 0xffebecec, 0xffebebeb, 0xffecebeb, 0xffebebeb, 0xffececec, 0xffebecec, 0xffececeb, + 0xffececeb, 0xffebecec, 0xffecebec, 0xffececeb, 0xffebeceb, 0xffececeb, 0xffebecec, 0xffecebec, + 0xffebebec, 0xffebecec, 0xffebeceb, 0xffebebeb, 0xffebecec, 0xffecebec, 0xffecebeb, 0xffebeceb, + 0xffebeceb, 0xffecebec, 0xffececec, 0xffecebeb, 0xffececeb, 0xffececeb, 0xffecebec, 0xffecebec, + 0xffebebec, 0xffebecec, 0xffececec, 0xffebebeb, 0xffecebeb, 0xffececeb, 0xffebebec, 0xffebebec, + 0xffecebeb, 0xffebebec, 0xffebebeb, 0xffebebeb, 0xffebecec, 0xffebecec, 0xffebeceb, 0xffececec, + 0xffebeceb, 0xffecebeb, 0xffecebeb, 0xffececec, 0xffebecec, 0xffebecec, 0xffebeceb, 0xffebecec, + 0xffebecec, 0xffebecec, 0xffebebec, 0xffebeceb, 0xffebebeb, 0xffecebeb, 0xffebebec, 0xffebecec, + 0xffececeb, 0xffebebec, 0xffecebec, 0xffebebeb, 0xffececec, 0xffecebeb, 0xffebebec, 0xffebecec, + 0xffebebec, 0xffebebeb, 0xffecebec, 0xffecebeb, 0xffebebeb, 0xffecebec, 0xffebecec, 0xffebebeb, + 0xffebeceb, 0xffececec, 0xffececec, 0xffecebec, 0xffebebec, 0xffececec, 0xffecebeb, 0xffebeceb, + 0xffebebec, 0xffececeb, 0xffebebec, 0xffebecec, 0xffecebec, 0xffebeceb, 0xffebecec, 0xffecebeb, + 0xffecebec, 0xffebeceb, 0xffecebec, 0xffebecec, 0xffebeceb, 0xffebeceb, 0xffecebeb, 0xffececeb, + 0xffebebec, 0xffececec, 0xffececeb, 0xffecebec, 0xffebebeb, 0xffebebec, 0xffe6e8e6, 0xffd6dbd6, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797b79, 0xffb5b6b5, 0xffb5b6b5, + 0xffd6dbd6, 0xffebebeb, 0xffeaebeb, 0xffeaeaea, 0xffebebeb, 0xffebeaeb, 0xffeaeaea, 0xffebeaeb, + 0xffeaebea, 0xffebebea, 0xffebeaea, 0xffeaebea, 0xffebebea, 0xffebeaeb, 0xffeaebea, 0xffebeaea, + 0xffeaebea, 0xffeaeaeb, 0xffebeaeb, 0xffeaeaea, 0xffebebea, 0xffeaebeb, 0xffebebeb, 0xffeaebeb, + 0xffebebeb, 0xffebebeb, 0xffeaebeb, 0xffebeaea, 0xffebebeb, 0xffebebeb, 0xffebebeb, 0xffeaebea, + 0xffeaeaeb, 0xffebebeb, 0xffebebea, 0xffebebeb, 0xffebeaeb, 0xffebebeb, 0xffebebea, 0xffebebeb, + 0xffebebeb, 0xffebebeb, 0xffebeaea, 0xffeaebeb, 0xffeaebea, 0xffeaeaeb, 0xffeaeaeb, 0xffebebeb, + 0xffebeaeb, 0xffebebea, 0xffeaeaeb, 0xffebebeb, 0xffebeaeb, 0xffeaebeb, 0xffebebeb, 0xffebebea, + 0xffeaeaea, 0xffeaeaeb, 0xffebeaeb, 0xffebebeb, 0xffebebea, 0xffebebea, 0xffebeaea, 0xffebebeb, + 0xffeaebeb, 0xffebebea, 0xffebebea, 0xffebeaeb, 0xffeaebea, 0xffebebea, 0xffeaeaea, 0xffeaebea, + 0xffeaebea, 0xffebebea, 0xffebeaeb, 0xffebebeb, 0xffeaebea, 0xffebebea, 0xffeaeaeb, 0xffeaebeb, + 0xffebebeb, 0xffebeaeb, 0xffebeaeb, 0xffeaebeb, 0xffebebea, 0xffeaebea, 0xffebebea, 0xffeaeaeb, + 0xffebebeb, 0xffebebeb, 0xffeaeaea, 0xffeaebeb, 0xffebeaeb, 0xffeaebeb, 0xffeaebeb, 0xffebebeb, + 0xffebebea, 0xffebebeb, 0xffeaebeb, 0xffeaebea, 0xffebebea, 0xffebebeb, 0xffebebeb, 0xffeaebeb, + 0xffebebeb, 0xffebeaeb, 0xffebeaeb, 0xffebebeb, 0xffebeaeb, 0xffeaebea, 0xffeaeaea, 0xffebebea, + 0xffeaeaea, 0xffebebeb, 0xffeaeaeb, 0xffebeaeb, 0xffebeaeb, 0xffebeaeb, 0xffeaebea, 0xffebeaea, + 0xffeaeaea, 0xffebebeb, 0xffebeaea, 0xffeaeaeb, 0xffeaebeb, 0xffeaebea, 0xffeaeaea, 0xffebebea, + 0xffeaebea, 0xffeaebea, 0xffebebeb, 0xffebeaeb, 0xffeaebeb, 0xffebebeb, 0xffebeaeb, 0xffebeaeb, + 0xffeaebeb, 0xffebebea, 0xffebebea, 0xffebebea, 0xffebebea, 0xffebebeb, 0xffeaebeb, 0xffeaebea, + 0xffebebeb, 0xffebebeb, 0xffebeaeb, 0xffeaebea, 0xffebeaeb, 0xffebebea, 0xffebebea, 0xffebebeb, + 0xffebebea, 0xffeaebeb, 0xffebeaeb, 0xffeaebeb, 0xffebeaea, 0xffeaebeb, 0xffeaebea, 0xffeaeaeb, + 0xffebebeb, 0xffebeaea, 0xffebebea, 0xffebeaeb, 0xffebebeb, 0xffebeaea, 0xffeaeaeb, 0xffebeaeb, + 0xffebebea, 0xffebebeb, 0xffebeaeb, 0xffebeaeb, 0xffebeaea, 0xffebeaea, 0xffebeaeb, 0xffebeaeb, + 0xffebeaeb, 0xffeaeaeb, 0xffebeaea, 0xffebeaeb, 0xffeaebeb, 0xffeaebeb, 0xffebebeb, 0xffebebea, + 0xffeaebea, 0xffebeaea, 0xffeaebea, 0xffebebeb, 0xffebebeb, 0xffeaebeb, 0xffebebeb, 0xffeaeaeb, + 0xffeaebeb, 0xffebebeb, 0xffebebeb, 0xffeaebea, 0xffeaebeb, 0xffeaebeb, 0xffebebeb, 0xffeaebeb, + 0xffebebea, 0xffebebeb, 0xffeaeaeb, 0xffebebeb, 0xffebebeb, 0xffebebea, 0xffeaebeb, 0xffeaebea, + 0xffeaeaeb, 0xffebebea, 0xffebeaea, 0xffebebea, 0xffebeaea, 0xffebebea, 0xffebebea, 0xffebebeb, + 0xffebebea, 0xffebebeb, 0xffebebea, 0xffebebeb, 0xffeaebeb, 0xffebebeb, 0xffe6e8e6, 0xffd6dbd6, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797b79, 0xffb5b6b5, 0xffb5b6b5, + 0xffd6dbd6, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffe9eae9, 0xffeaeaea, 0xffe9eaea, + 0xffeae9ea, 0xffeaeae9, 0xffeaeae9, 0xffeae9e9, 0xffeaeaea, 0xffeaeaea, 0xffeae9ea, 0xffeaeaea, + 0xffe9eae9, 0xffeaeaea, 0xffe9e9ea, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffeaeae9, + 0xffeaeae9, 0xffe9e9e9, 0xffe9eaea, 0xffeae9ea, 0xffeaeaea, 0xffeae9e9, 0xffeae9ea, 0xffe9e9e9, + 0xffeaeaea, 0xffeaeaea, 0xffe9e9ea, 0xffe9eaea, 0xffeaeae9, 0xffeaeaea, 0xffeae9ea, 0xffe9eaea, + 0xffe9eaea, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffe9eae9, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, + 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffeae9ea, 0xffeaeaea, 0xffeae9ea, 0xffeae9ea, 0xffe9eaea, + 0xffeaeaea, 0xffeaeaea, 0xffeae9e9, 0xffeaeaea, 0xffeaeaea, 0xffeae9ea, 0xffeae9e9, 0xffe9eaea, + 0xffeaeaea, 0xffeaeaea, 0xffeaeae9, 0xffeae9e9, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffe9e9ea, + 0xffeaeaea, 0xffeaeae9, 0xffeaeaea, 0xffeae9ea, 0xffe9eaea, 0xffeaeae9, 0xffeaeae9, 0xffeaeaea, + 0xffeaeaea, 0xffe9eaea, 0xffeaeaea, 0xffeaeaea, 0xffeaeae9, 0xffeaeaea, 0xffe9eaea, 0xffeae9ea, + 0xffeaeaea, 0xffeaeaea, 0xffeaeae9, 0xffe9eae9, 0xffeaeaea, 0xffe9eaea, 0xffeaeaea, 0xffeaeaea, + 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffeaeae9, 0xffeaeae9, 0xffe9eaea, 0xffe9eaea, 0xffeaeaea, + 0xffeaeaea, 0xffeae9e9, 0xffeaeaea, 0xffeaeae9, 0xffeaeae9, 0xffeaeaea, 0xffeaeae9, 0xffeaeaea, + 0xffeaeaea, 0xffeaeae9, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, + 0xffeaeaea, 0xffeaeaea, 0xffeaeae9, 0xffeaeaea, 0xffeaeae9, 0xffeaeaea, 0xffeaeaea, 0xffe9eaea, + 0xffeaeaea, 0xffe9eae9, 0xffeaeae9, 0xffeae9ea, 0xffeaeaea, 0xffe9eaea, 0xffe9eaea, 0xffeae9ea, + 0xffeaeae9, 0xffeaeaea, 0xffeae9e9, 0xffeaeaea, 0xffe9eaea, 0xffeae9ea, 0xffeaeaea, 0xffeaeaea, + 0xffe9eaea, 0xffeae9ea, 0xffeaeae9, 0xffeae9e9, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffeaeae9, + 0xffeaeaea, 0xffeaeaea, 0xffe9eaea, 0xffe9e9ea, 0xffe9eae9, 0xffeaeaea, 0xffeaeae9, 0xffeaeaea, + 0xffeaeae9, 0xffeae9ea, 0xffeaeae9, 0xffeaeae9, 0xffe9eaea, 0xffeaeaea, 0xffeaeae9, 0xffe9eaea, + 0xffeaeaea, 0xffeaeae9, 0xffeae9ea, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffe9eaea, 0xffeae9ea, + 0xffeaeae9, 0xffeae9ea, 0xffe9eaea, 0xffeaeae9, 0xffeaeae9, 0xffeae9ea, 0xffeaeaea, 0xffe9eaea, + 0xffeaeaea, 0xffeaeaea, 0xffeae9ea, 0xffeaeaea, 0xffeaeaea, 0xffeaeae9, 0xffe9eaea, 0xffe9e9ea, + 0xffeaeaea, 0xffe9e9ea, 0xffe9eaea, 0xffeae9ea, 0xffe9e9e9, 0xffeaeaea, 0xffeaeaea, 0xffeaeae9, + 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffeae9ea, 0xffeaeaea, 0xffeaeaea, 0xffe9e9ea, 0xffeaeaea, + 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffeaeaea, 0xffe9eaea, + 0xffeaeaea, 0xffe9eae9, 0xffeaeaea, 0xffeae9ea, 0xffeaeae9, 0xffeaeaea, 0xffe6e8e6, 0xffd6dbd6, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797b79, 0xffb5b6b5, 0xffb5b6b5, + 0xffd6dbd6, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffeae9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe6e8e6, 0xffd6dbd6, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797b79, 0xffb5b6b5, 0xffb5b6b5, + 0xffd6dbd6, 0xffe8e8e8, 0xffe8e8e9, 0xffe9e9e9, 0xffe8e8e8, 0xffe9e8e9, 0xffe8e8e9, 0xffe8e8e9, + 0xffe8e8e9, 0xffe8e8e8, 0xffe8e8e9, 0xffe8e8e9, 0xffe8e9e9, 0xffe9e8e8, 0xffe9e8e8, 0xffe8e9e8, + 0xffe8e9e9, 0xffe8e8e8, 0xffe8e8e9, 0xffe9e8e8, 0xffe8e9e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e9e9, + 0xffe9e8e8, 0xffe8e8e9, 0xffe9e8e9, 0xffe9e9e8, 0xffe9e8e8, 0xffe8e9e8, 0xffe8e9e8, 0xffe8e8e8, + 0xffe8e9e8, 0xffe8e8e9, 0xffe8e8e8, 0xffe9e8e8, 0xffe8e8e8, 0xffe8e8e9, 0xffe8e9e8, 0xffe8e8e8, + 0xffe8e9e8, 0xffe8e8e8, 0xffe8e9e8, 0xffe8e9e8, 0xffe8e9e9, 0xffe8e8e8, 0xffe9e8e9, 0xffe8e8e8, + 0xffe8e9e8, 0xffe9e8e8, 0xffe8e8e8, 0xffe9e9e8, 0xffe8e8e8, 0xffe8e9e9, 0xffe8e8e9, 0xffe8e8e8, + 0xffe8e9e8, 0xffe9e9e8, 0xffe8e8e8, 0xffe9e9e9, 0xffe8e8e8, 0xffe9e8e8, 0xffe8e8e8, 0xffe8e8e9, + 0xffe8e9e8, 0xffe8e8e9, 0xffe8e9e9, 0xffe9e8e8, 0xffe8e8e8, 0xffe9e8e8, 0xffe8e8e8, 0xffe9e8e9, + 0xffe8e8e8, 0xffe9e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e9e8, 0xffe9e8e9, 0xffe8e8e8, 0xffe8e8e9, + 0xffe8e8e8, 0xffe9e9e8, 0xffe9e8e9, 0xffe8e8e9, 0xffe8e9e8, 0xffe9e8e9, 0xffe8e9e8, 0xffe8e9e9, + 0xffe8e8e8, 0xffe9e9e8, 0xffe8e9e8, 0xffe9e8e8, 0xffe8e8e8, 0xffe8e8e9, 0xffe8e9e9, 0xffe8e8e8, + 0xffe8e8e8, 0xffe8e8e9, 0xffe8e9e8, 0xffe8e9e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe9e8e8, 0xffe8e8e9, + 0xffe8e9e8, 0xffe9e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e8e8, + 0xffe8e8e9, 0xffe8e8e9, 0xffe8e8e8, 0xffe8e8e8, 0xffe9e9e8, 0xffe8e9e9, 0xffe8e8e8, 0xffe8e8e8, + 0xffe8e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe9e9e8, 0xffe9e8e8, 0xffe8e8e8, 0xffe8e9e8, + 0xffe8e8e9, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e9e9, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e9e8, + 0xffe8e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe9e8e8, 0xffe8e8e9, 0xffe9e9e8, + 0xffe8e8e8, 0xffe9e9e8, 0xffe8e9e9, 0xffe8e9e8, 0xffe9e8e9, 0xffe8e9e8, 0xffe8e8e8, 0xffe8e8e8, + 0xffe8e8e8, 0xffe9e8e8, 0xffe9e8e8, 0xffe9e8e9, 0xffe8e8e9, 0xffe8e9e8, 0xffe9e8e8, 0xffe8e9e9, + 0xffe9e8e9, 0xffe9e8e8, 0xffe8e8e9, 0xffe9e8e8, 0xffe8e9e8, 0xffe8e9e8, 0xffe8e8e8, 0xffe9e9e8, + 0xffe8e8e8, 0xffe8e8e9, 0xffe8e9e9, 0xffe8e9e8, 0xffe9e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e8e8, + 0xffe8e8e8, 0xffe8e9e8, 0xffe8e9e9, 0xffe8e8e8, 0xffe8e8e9, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e8e9, + 0xffe8e9e8, 0xffe8e9e8, 0xffe8e8e8, 0xffe9e8e8, 0xffe8e8e8, 0xffe8e9e8, 0xffe8e8e8, 0xffe8e8e8, + 0xffe9e8e9, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e9e9, 0xffe9e8e8, 0xffe8e8e8, 0xffe9e8e8, + 0xffe9e8e8, 0xffe8e9e8, 0xffe9e8e8, 0xffe8e8e8, 0xffe8e9e8, 0xffe8e9e8, 0xffe8e8e8, 0xffe8e8e8, + 0xffe8e8e8, 0xffe8e9e8, 0xffe8e8e8, 0xffe9e8e9, 0xffe9e9e9, 0xffe8e8e8, 0xffe8e9e9, 0xffe9e8e8, + 0xffe8e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e9e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe6e8e6, 0xffd6dbd6, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797b79, 0xffb5b6b5, 0xffb5b6b5, + 0xffd6dbd6, 0xffe7e8e8, 0xffe8e7e8, 0xffe8e7e8, 0xffe7e8e7, 0xffe8e7e8, 0xffe7e7e8, 0xffe7e8e8, + 0xffe7e7e8, 0xffe8e7e8, 0xffe8e8e8, 0xffe7e8e7, 0xffe8e8e8, 0xffe7e8e8, 0xffe8e7e7, 0xffe8e8e7, + 0xffe7e7e7, 0xffe8e8e8, 0xffe7e7e7, 0xffe7e8e7, 0xffe8e8e7, 0xffe8e8e8, 0xffe7e7e8, 0xffe8e8e7, + 0xffe8e8e8, 0xffe8e8e7, 0xffe7e7e7, 0xffe7e8e7, 0xffe8e8e7, 0xffe8e8e7, 0xffe8e7e8, 0xffe8e7e8, + 0xffe7e8e7, 0xffe7e7e8, 0xffe8e8e8, 0xffe7e7e7, 0xffe7e8e8, 0xffe7e7e7, 0xffe7e8e7, 0xffe7e8e8, + 0xffe8e7e8, 0xffe7e7e7, 0xffe8e8e7, 0xffe7e8e7, 0xffe7e8e8, 0xffe8e8e8, 0xffe8e8e7, 0xffe8e8e8, + 0xffe7e7e7, 0xffe7e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e7e8, 0xffe8e7e8, 0xffe8e8e8, 0xffe7e8e8, + 0xffe7e8e7, 0xffe7e7e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e7e7, 0xffe8e8e7, 0xffe8e8e8, + 0xffe8e8e7, 0xffe7e7e8, 0xffe7e7e8, 0xffe8e8e7, 0xffe8e7e8, 0xffe8e7e7, 0xffe8e8e7, 0xffe7e8e8, + 0xffe8e7e8, 0xffe8e7e8, 0xffe8e7e8, 0xffe7e7e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e8e7, 0xffe7e7e7, + 0xffe7e8e7, 0xffe7e7e8, 0xffe8e7e8, 0xffe8e8e7, 0xffe7e7e8, 0xffe8e8e8, 0xffe8e7e7, 0xffe8e7e8, + 0xffe7e7e7, 0xffe7e8e8, 0xffe8e7e8, 0xffe8e8e7, 0xffe8e7e8, 0xffe8e7e7, 0xffe8e7e8, 0xffe8e8e7, + 0xffe7e8e8, 0xffe8e7e7, 0xffe8e7e7, 0xffe8e7e7, 0xffe8e7e7, 0xffe7e8e8, 0xffe7e7e8, 0xffe8e7e8, + 0xffe7e8e8, 0xffe7e8e8, 0xffe7e8e7, 0xffe8e7e8, 0xffe8e8e7, 0xffe8e8e7, 0xffe7e8e8, 0xffe8e7e8, + 0xffe8e8e8, 0xffe8e8e7, 0xffe7e7e7, 0xffe8e8e8, 0xffe7e7e8, 0xffe8e8e8, 0xffe7e7e8, 0xffe7e7e7, + 0xffe7e7e8, 0xffe7e7e8, 0xffe8e7e8, 0xffe8e7e7, 0xffe8e7e7, 0xffe8e7e8, 0xffe8e8e7, 0xffe7e7e8, + 0xffe8e8e8, 0xffe7e8e7, 0xffe7e8e7, 0xffe8e8e8, 0xffe8e7e8, 0xffe7e7e7, 0xffe8e8e8, 0xffe8e7e8, + 0xffe8e8e7, 0xffe7e7e8, 0xffe8e7e8, 0xffe7e7e8, 0xffe7e8e7, 0xffe7e8e7, 0xffe7e7e8, 0xffe8e7e7, + 0xffe8e7e7, 0xffe8e7e7, 0xffe7e8e7, 0xffe8e8e8, 0xffe7e8e8, 0xffe8e8e8, 0xffe8e8e8, 0xffe8e7e7, + 0xffe7e8e7, 0xffe8e7e7, 0xffe7e8e8, 0xffe7e7e7, 0xffe8e7e8, 0xffe7e8e8, 0xffe8e7e8, 0xffe8e8e8, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e8e7, 0xffe8e8e7, 0xffe8e7e8, 0xffe7e8e8, 0xffe7e7e7, 0xffe7e7e8, + 0xffe7e7e8, 0xffe7e8e8, 0xffe7e8e8, 0xffe7e8e8, 0xffe7e7e7, 0xffe7e8e8, 0xffe8e7e8, 0xffe8e8e8, + 0xffe7e8e8, 0xffe8e7e8, 0xffe7e7e7, 0xffe8e7e8, 0xffe7e8e7, 0xffe8e7e7, 0xffe7e8e8, 0xffe7e8e8, + 0xffe7e8e8, 0xffe7e8e7, 0xffe7e8e8, 0xffe7e8e8, 0xffe8e8e8, 0xffe8e7e7, 0xffe8e7e7, 0xffe8e7e8, + 0xffe8e8e7, 0xffe8e8e7, 0xffe8e7e8, 0xffe7e7e8, 0xffe8e7e8, 0xffe8e7e7, 0xffe8e8e8, 0xffe8e7e8, + 0xffe7e7e8, 0xffe8e8e7, 0xffe7e8e7, 0xffe7e8e7, 0xffe8e8e8, 0xffe8e7e8, 0xffe7e8e7, 0xffe8e7e7, + 0xffe7e7e8, 0xffe7e8e8, 0xffe8e7e8, 0xffe8e7e7, 0xffe7e7e8, 0xffe8e8e7, 0xffe7e7e8, 0xffe8e7e7, + 0xffe7e7e8, 0xffe7e7e8, 0xffe8e8e7, 0xffe7e8e8, 0xffe8e7e7, 0xffe8e8e8, 0xffe6e8e6, 0xffd6dbd6, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797b79, 0xffb5b6b5, 0xffb5b6b5, + 0xffd6dbd6, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e6, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e6e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e6e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e6e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e6, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e6, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e6, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe6e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe6e8e6, 0xffd6dbd6, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797b79, 0xffb5b6b5, 0xffb5b6b5, + 0xffd6dbd6, 0xffe6e6e6, 0xffe6e7e7, 0xffe6e7e6, 0xffe7e6e7, 0xffe7e6e6, 0xffe7e6e6, 0xffe6e6e7, + 0xffe6e6e6, 0xffe6e6e6, 0xffe7e6e6, 0xffe7e6e6, 0xffe6e7e7, 0xffe7e6e6, 0xffe6e7e6, 0xffe6e6e7, + 0xffe7e6e6, 0xffe6e7e7, 0xffe7e6e6, 0xffe7e7e7, 0xffe6e7e7, 0xffe6e7e7, 0xffe6e6e7, 0xffe6e7e6, + 0xffe6e7e6, 0xffe7e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e6e6, 0xffe6e7e7, 0xffe6e7e7, 0xffe6e7e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe7e7e7, 0xffe7e7e7, 0xffe6e7e6, 0xffe6e6e6, 0xffe7e7e7, + 0xffe6e6e7, 0xffe7e7e7, 0xffe7e6e7, 0xffe6e6e7, 0xffe6e7e6, 0xffe6e6e6, 0xffe7e7e7, 0xffe7e6e6, + 0xffe7e6e7, 0xffe7e6e7, 0xffe6e7e6, 0xffe6e6e7, 0xffe7e7e6, 0xffe7e7e6, 0xffe6e6e7, 0xffe6e7e6, + 0xffe6e6e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe7e6e6, 0xffe6e6e7, 0xffe6e7e7, 0xffe6e7e7, 0xffe6e7e6, + 0xffe6e6e7, 0xffe6e6e7, 0xffe6e6e7, 0xffe6e6e7, 0xffe6e6e7, 0xffe7e6e6, 0xffe6e7e6, 0xffe6e7e6, + 0xffe7e7e7, 0xffe7e7e7, 0xffe7e7e7, 0xffe6e7e7, 0xffe6e6e7, 0xffe6e6e6, 0xffe6e7e7, 0xffe7e7e7, + 0xffe6e7e7, 0xffe7e6e6, 0xffe6e6e7, 0xffe6e7e7, 0xffe7e6e7, 0xffe7e7e7, 0xffe6e6e7, 0xffe6e6e6, + 0xffe7e7e6, 0xffe6e6e6, 0xffe6e7e7, 0xffe6e6e6, 0xffe6e7e6, 0xffe7e7e6, 0xffe7e7e6, 0xffe6e7e7, + 0xffe6e6e6, 0xffe6e7e6, 0xffe6e7e7, 0xffe7e7e6, 0xffe6e7e6, 0xffe6e6e7, 0xffe7e7e6, 0xffe6e6e6, + 0xffe7e7e6, 0xffe6e6e7, 0xffe6e7e7, 0xffe6e7e6, 0xffe7e6e7, 0xffe6e7e7, 0xffe6e6e7, 0xffe7e6e7, + 0xffe6e7e7, 0xffe6e7e6, 0xffe7e7e7, 0xffe7e7e7, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e6e7, 0xffe6e6e7, + 0xffe6e6e6, 0xffe7e6e7, 0xffe6e6e6, 0xffe7e6e7, 0xffe6e6e7, 0xffe7e7e7, 0xffe6e6e7, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe7e6e6, 0xffe7e7e6, 0xffe7e7e7, 0xffe6e6e6, 0xffe7e7e7, 0xffe6e7e7, + 0xffe6e7e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe7e7e6, 0xffe6e6e7, 0xffe7e6e6, 0xffe7e6e7, 0xffe6e6e7, + 0xffe6e7e7, 0xffe7e6e6, 0xffe6e7e6, 0xffe6e6e7, 0xffe7e7e7, 0xffe7e6e6, 0xffe6e7e6, 0xffe7e6e6, + 0xffe6e7e7, 0xffe6e7e7, 0xffe6e6e6, 0xffe7e7e6, 0xffe7e6e6, 0xffe7e6e6, 0xffe6e7e6, 0xffe7e6e6, + 0xffe7e7e6, 0xffe6e6e7, 0xffe6e6e6, 0xffe6e6e7, 0xffe6e7e7, 0xffe6e7e7, 0xffe6e6e7, 0xffe6e7e6, + 0xffe6e7e6, 0xffe6e7e7, 0xffe7e7e7, 0xffe6e6e7, 0xffe6e7e7, 0xffe6e6e7, 0xffe6e6e7, 0xffe6e7e7, + 0xffe7e6e6, 0xffe7e6e7, 0xffe6e6e6, 0xffe7e7e6, 0xffe7e6e6, 0xffe6e7e7, 0xffe6e7e7, 0xffe7e7e7, + 0xffe6e6e6, 0xffe7e7e7, 0xffe7e7e7, 0xffe6e7e6, 0xffe7e7e7, 0xffe6e6e7, 0xffe7e7e7, 0xffe6e6e7, + 0xffe6e7e6, 0xffe7e7e6, 0xffe7e6e7, 0xffe7e6e7, 0xffe7e6e6, 0xffe6e6e6, 0xffe7e7e6, 0xffe6e7e6, + 0xffe7e6e6, 0xffe7e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e6e7, 0xffe7e6e7, 0xffe6e7e7, + 0xffe7e7e6, 0xffe7e6e7, 0xffe7e7e7, 0xffe6e6e6, 0xffe6e6e7, 0xffe7e6e6, 0xffe6e6e7, 0xffe7e7e6, + 0xffe7e7e7, 0xffe6e7e6, 0xffe6e6e7, 0xffe7e6e6, 0xffe6e7e6, 0xffe6e7e7, 0xffe6e8e6, 0xffd6dbd6, + 0xffc5c2c5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797879, 0xffb5b2b5, 0xffb5b2b5, + 0xffd9dbd9, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, + 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6e6e6, 0xffe6ebe6, 0xffd9dbd9, + 0xffbdbebd, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797879, 0xffb5b2b5, 0xffb5b2b5, + 0xffd9dbd9, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, + 0xffefefef, 0xffefefef, 0xffefefef, 0xffefefef, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffd9dbd9, + 0xffbdbebd, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff797879, 0xffb5b2b5, 0xffb5b2b5, + 0xffcbcacb, 0xffd9dbd9, 0xffe6ebe6, 0xffe6ebe6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, + 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6e8e6, 0xffe6ebe6, 0xffe6ebe6, 0xffd9dbd9, 0xffcbcacb, + 0xffbdbebd, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0x00000400, 0xff797879, 0xffb5b2b5, + 0xffbdbabd, 0xffcbcacb, 0xffd9dbd9, 0xffd9dbd9, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, + 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd9dbd9, 0xffd9dbd9, 0xffcbcacb, 0xffbdbabd, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff848284, + 0xff9c9f9c, 0xff9c9f9c, 0xff9c9f9c, 0xff9c9f9c, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, + 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xffa2a5a2, 0xff9c9e9c, 0xff9c9e9c, 0xff9c9e9c, 0x00080408, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff848284, 0xffc5c2c5, 0xffc5c2c5, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffbdbebd, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff848284, 0xff848284, 0xffc5c2c5, 0xffe6ebe6, + 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, + 0xffeff3ef, 0xffeff3ef, 0xffeff3ef, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffe6ebe6, 0xffbdbebd, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff6e3e3c, 0xffa55d5a, 0xffa55d5a, 0xffc5716b, + 0xffd07770, 0xffd67973, 0xffd67973, 0xffd67970, 0xffd67970, 0xffd67970, 0xffd67970, 0xffd6796b, + 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6786b, 0xffd6786b, 0xffd6776b, 0xffd6776b, 0xffd6756b, + 0xffd6756b, 0xffd6756b, 0xffd6746b, 0xffd6746b, 0xffd6736b, 0xffd6736b, 0xffd6736b, 0xffce7163, + 0xffce7163, 0xffce7063, 0xffce6f63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6c63, + 0xffce6c63, 0xffce6b63, 0xffce6963, 0xffce695a, 0xffce685a, 0xffce675a, 0xffce675a, 0xffc5655a, + 0xffc5655a, 0xffc5655a, 0xffc5645a, 0xffc5645d, 0xffc56258, 0xffc56258, 0xffc56258, 0xffc56052, + 0xffc56052, 0xffc55e52, 0xffc55e52, 0xffc55d52, 0xffc55c52, 0xffc55c52, 0xffc55a52, 0xffbd594a, + 0xffbd594a, 0xffbd584a, 0xffbd564a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd544a, + 0xffbd544a, 0xffbd544a, 0xffbd544a, 0xffbd5142, 0xffbd5142, 0xffba5042, 0xffba5042, 0xffba4d42, + 0xffb84d42, 0xffb84d42, 0xffb84d42, 0xffb54c3f, 0xffb54a3c, 0xffb54a3c, 0xffb5493a, 0xffb5483a, + 0xffb5483a, 0xffb5463a, 0xffb5463a, 0xffb5453a, 0xffb5433a, 0xffb5433a, 0xffb5433a, 0xffb54237, + 0xffb54237, 0xffb54131, 0xffb54131, 0xffad4131, 0xffad4131, 0xffad3f31, 0xffad3f31, 0xffad3f31, + 0xffad3e31, 0xffad3e31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3b2f, + 0xffad3b2f, 0xffad3b2f, 0xffad3a2c, 0xffad392f, 0xffad392c, 0xffad392c, 0xffad392c, 0xffad392f, + 0xffad392c, 0xffad392f, 0xffad392f, 0xffad3a2c, 0xffad3a2c, 0xffad3b2f, 0xffad3b2f, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3e31, 0xffad3e31, 0xffad3f31, 0xffad3f31, + 0xffad3f31, 0xffad3f31, 0xffad4131, 0xffb54237, 0xffb54237, 0xffb54237, 0xffb54237, 0xffb5453a, + 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5463a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb54a3c, + 0xffb54a3c, 0xffb54c3f, 0xffb54c3f, 0xffb54d42, 0xffb54d42, 0xffb84e42, 0xffba5042, 0xffbd5045, + 0xffbd5142, 0xffbd5142, 0xffbd5142, 0xffbd544a, 0xffbd544a, 0xffbd544a, 0xffbd554a, 0xffbd554a, + 0xffbd564a, 0xffbd564a, 0xffbd564a, 0xffc0594d, 0xffc35950, 0xffc35950, 0xffc35950, 0xffc55a52, + 0xffc55d52, 0xffc55d52, 0xffc55d52, 0xffc55e52, 0xffc56052, 0xffc56052, 0xffc56152, 0xffc56258, + 0xffc56258, 0xffc56455, 0xffc56455, 0xffcb655a, 0xffcb655a, 0xffcb655a, 0xffcb655a, 0xffce675d, + 0xffce6860, 0xffce6860, 0xffce6963, 0xffce6b63, 0xffce6b63, 0xffce6c63, 0xffce6d63, 0xffce6d63, + 0xffce6f63, 0xffce6f63, 0xffce7063, 0xffd07165, 0xffd07165, 0xffd37168, 0xffd37168, 0xffd6736b, + 0xffd6736b, 0xffd6746b, 0xffd6746b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6776b, + 0xffd6786b, 0xffd6796b, 0xffd6786b, 0xffd6796e, 0xffd6796e, 0xffd6796e, 0xffd67970, 0xffd67973, + 0xffd67973, 0xffd67973, 0xffd67973, 0xffd67973, 0xffd67973, 0xffd07770, 0xffc5716b, 0xffb5655a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff6e3e3c, 0xffa55d5a, 0xffa55d5a, 0xffc5716b, + 0xffd07770, 0xffd67973, 0xffd67973, 0xffd67970, 0xffd67970, 0xffd67970, 0xffd67970, 0xffd6796b, + 0xffd6796b, 0xffd6796b, 0xffd6786b, 0xffd6776b, 0xffd6776b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6746b, 0xffd6746b, 0xffd6746b, 0xffd6736b, 0xffd6716b, 0xffd6716b, 0xffd6716b, 0xffce7063, + 0xffce7063, 0xffce7063, 0xffce7063, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6c63, + 0xffce6c63, 0xffce6b63, 0xffce6b63, 0xffce695a, 0xffce685a, 0xffce685a, 0xffce675a, 0xffc5655a, + 0xffc5655a, 0xffc5645a, 0xffc5645a, 0xffc56258, 0xffc56258, 0xffc56152, 0xffc56152, 0xffc56052, + 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc55d52, 0xffc55d52, 0xffc55a52, 0xffc55a52, 0xffbd594a, + 0xffbd594a, 0xffbd594a, 0xffbd564a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd544a, + 0xffbd524a, 0xffbd524a, 0xffbd514a, 0xffba5042, 0xffba5042, 0xffba5042, 0xffb54d42, 0xffb84d42, + 0xffb84d42, 0xffb84d42, 0xffb84d42, 0xffb54c3f, 0xffb54a3c, 0xffb5493a, 0xffb5493a, 0xffb5483a, + 0xffb5483a, 0xffb5483a, 0xffb5463a, 0xffb5453a, 0xffb5433a, 0xffb5433a, 0xffb5423a, 0xffb54237, + 0xffb54237, 0xffb54131, 0xffb54131, 0xffad3f31, 0xffad3f31, 0xffad3f31, 0xffad3e31, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3a2c, + 0xffad3b2f, 0xffad3a2c, 0xffad3929, 0xffad392c, 0xffad392c, 0xffad392c, 0xffad392c, 0xffad392c, + 0xffad392c, 0xffad392c, 0xffad392c, 0xffad3929, 0xffad3a2c, 0xffad3a2c, 0xffad3b2f, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3e31, 0xffad3f31, + 0xffad3f31, 0xffad3f31, 0xffad3f31, 0xffb5413a, 0xffb5413a, 0xffb54237, 0xffb54237, 0xffb5453a, + 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5463a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb5493a, + 0xffb54a3c, 0xffb54c3f, 0xffb54c3f, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb84e42, 0xffbd4e47, + 0xffbd5045, 0xffbd5045, 0xffbd5142, 0xffbd524a, 0xffbd544a, 0xffbd544a, 0xffbd554a, 0xffbd554a, + 0xffbd564a, 0xffbd564a, 0xffbd564a, 0xffc0594d, 0xffc0594d, 0xffc0594d, 0xffc35950, 0xffc55a52, + 0xffc55d52, 0xffc55d52, 0xffc55d52, 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc56052, 0xffc5615a, + 0xffc56258, 0xffc56258, 0xffc56455, 0xffc8655a, 0xffc8655a, 0xffcb655a, 0xffcb655a, 0xffce675d, + 0xffce6860, 0xffce6860, 0xffce6963, 0xffce6b63, 0xffce6b63, 0xffce6c63, 0xffce6c63, 0xffce6d63, + 0xffce6f63, 0xffce6f63, 0xffce6f63, 0xffd07165, 0xffd07165, 0xffd07165, 0xffd37168, 0xffd6716b, + 0xffd6716b, 0xffd6736b, 0xffd6736b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6776b, + 0xffd6776b, 0xffd6786b, 0xffd6786b, 0xffd6796e, 0xffd6796e, 0xffd6796e, 0xffd6796e, 0xffd67973, + 0xffd67973, 0xffd67973, 0xffd67973, 0xffd67973, 0xffd67973, 0xffd07770, 0xffc5716b, 0xffb5655a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff6e3e3c, 0xffa55d5a, 0xffa55d5a, 0xffc5716b, + 0xffd07770, 0xffd67973, 0xffd67973, 0xffd67970, 0xffd67970, 0xffd67970, 0xffd67970, 0xffd6796b, + 0xffd6796b, 0xffd6786b, 0xffd6786b, 0xffd6776b, 0xffd6776b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6756b, 0xffd6746b, 0xffd6746b, 0xffd6736b, 0xffd6716b, 0xffd6716b, 0xffd6716b, 0xffce7063, + 0xffce7063, 0xffce7063, 0xffce7063, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6c63, + 0xffce6b63, 0xffce6b63, 0xffce6b63, 0xffce695a, 0xffce685a, 0xffce685a, 0xffce675a, 0xffc5655a, + 0xffc5655a, 0xffc5645a, 0xffc5645a, 0xffc56258, 0xffc56258, 0xffc56258, 0xffc56152, 0xffc55e52, + 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc55d52, 0xffc55d52, 0xffc55c52, 0xffc55a52, 0xffbd594a, + 0xffbd594a, 0xffbd594a, 0xffbd564a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd544a, + 0xffbd524a, 0xffbd514a, 0xffbd514a, 0xffba5042, 0xffba5042, 0xffba5042, 0xffb84e42, 0xffb84d42, + 0xffb84d42, 0xffb84d42, 0xffb84d42, 0xffb54a3c, 0xffb54a3c, 0xffb5493a, 0xffb5493a, 0xffb5483a, + 0xffb5483a, 0xffb5463a, 0xffb5453a, 0xffb5433a, 0xffb5453a, 0xffb5433a, 0xffb5433a, 0xffb54237, + 0xffb54237, 0xffb54131, 0xffb54131, 0xffad3f31, 0xffad3f31, 0xffad3f31, 0xffad3e31, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3a2c, + 0xffad3a2c, 0xffad3a2c, 0xffad3a2c, 0xffad392c, 0xffad392c, 0xffad392c, 0xffad392c, 0xffad392c, + 0xffad392c, 0xffad392c, 0xffad392c, 0xffad3a2c, 0xffad3a2c, 0xffad3a2c, 0xffad3a2c, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3e31, 0xffad3e31, + 0xffad3f31, 0xffad3f31, 0xffad3f31, 0xffb54237, 0xffb54237, 0xffb54237, 0xffb54237, 0xffb5453a, + 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5463a, 0xffb5483a, 0xffb5483a, 0xffb5493a, 0xffb54a3c, + 0xffb54a3c, 0xffb54c3f, 0xffb54c3f, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffbd4e47, + 0xffbd5045, 0xffbd5045, 0xffbd5142, 0xffbd524a, 0xffbd544a, 0xffbd544a, 0xffbd544a, 0xffbd554a, + 0xffbd564a, 0xffbd564a, 0xffbd564a, 0xffc0594d, 0xffc0594d, 0xffc0594d, 0xffc35950, 0xffc55c52, + 0xffc55c52, 0xffc55d52, 0xffc55d52, 0xffc55e52, 0xffc55e52, 0xffc56052, 0xffc56052, 0xffc5615a, + 0xffc56258, 0xffc56258, 0xffc56258, 0xffc8655a, 0xffcb655a, 0xffc8655a, 0xffcb655a, 0xffce675d, + 0xffce6860, 0xffce6963, 0xffce6963, 0xffce6b63, 0xffce6b63, 0xffce6c63, 0xffce6d63, 0xffce6d63, + 0xffce6f63, 0xffce6f63, 0xffce7063, 0xffd07165, 0xffd07165, 0xffd07165, 0xffd07165, 0xffd6716b, + 0xffd6736b, 0xffd6736b, 0xffd6746b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6776b, 0xffd6776b, 0xffd6786b, 0xffd6796e, 0xffd6796e, 0xffd6796e, 0xffd67970, 0xffd67973, + 0xffd67973, 0xffd67973, 0xffd67973, 0xffd67973, 0xffd67973, 0xffd07770, 0xffc5716b, 0xffb5655a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff6e3e3c, 0xffa55d5a, 0xffa55d5a, 0xffc5716b, + 0xffd07770, 0xffd67973, 0xffd67973, 0xffd67970, 0xffd67970, 0xffd67970, 0xffd6796e, 0xffd6796b, + 0xffd6796b, 0xffd6786b, 0xffd6776b, 0xffd6776b, 0xffd6776b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6756b, 0xffd6746b, 0xffd6736b, 0xffd6716b, 0xffd6736b, 0xffd6716b, 0xffd6716b, 0xffce7063, + 0xffce7063, 0xffce7063, 0xffce6f63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6c63, + 0xffce6b63, 0xffce6b63, 0xffce6b63, 0xffce695a, 0xffce695a, 0xffce675a, 0xffce675a, 0xffc5655a, + 0xffc5655a, 0xffc5645a, 0xffc5625a, 0xffc56258, 0xffc56258, 0xffc56152, 0xffc56152, 0xffc55e52, + 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc55d52, 0xffc55d52, 0xffc55a52, 0xffc55a52, 0xffbd594a, + 0xffbd594a, 0xffbd584a, 0xffbd564a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd544a, + 0xffbd524a, 0xffbd524a, 0xffbd514a, 0xffba5042, 0xffba5042, 0xffba5042, 0xffb54d42, 0xffb84d42, + 0xffb84d42, 0xffb84d42, 0xffb84d42, 0xffb54c3f, 0xffb5493a, 0xffb5493a, 0xffb5493a, 0xffb5483a, + 0xffb5483a, 0xffb5463a, 0xffb5463a, 0xffb5453a, 0xffb5433a, 0xffb5433a, 0xffb5433a, 0xffb54237, + 0xffb54237, 0xffb54131, 0xffb54131, 0xffad3f31, 0xffad3f31, 0xffad3e31, 0xffad3e31, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3a2c, + 0xffad3a2c, 0xffad3a2c, 0xffad3929, 0xffad392c, 0xffad392c, 0xffad392c, 0xffad392c, 0xffad392c, + 0xffad392c, 0xffad392c, 0xffad392c, 0xffad3929, 0xffad3a2c, 0xffad3a2c, 0xffad3b2f, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3e31, 0xffad3e31, + 0xffad3f31, 0xffad3f31, 0xffad3f31, 0xffb54237, 0xffb54237, 0xffb54237, 0xffb54237, 0xffb5453a, + 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5463a, 0xffb5463a, 0xffb5483a, 0xffb5483a, 0xffb5493a, + 0xffb54a3c, 0xffb54c3f, 0xffb54c3f, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb84e42, 0xffbd4e47, + 0xffbd5045, 0xffbd5045, 0xffbd5142, 0xffbd514a, 0xffbd544a, 0xffbd544a, 0xffbd544a, 0xffbd554a, + 0xffbd564a, 0xffbd564a, 0xffbd584a, 0xffc0594d, 0xffc0594d, 0xffc0594d, 0xffc0594d, 0xffc55c52, + 0xffc55d52, 0xffc55d52, 0xffc55d52, 0xffc55e52, 0xffc55e52, 0xffc56052, 0xffc56152, 0xffc5615a, + 0xffc5615a, 0xffc56258, 0xffc56258, 0xffc8655a, 0xffc8655a, 0xffcb655a, 0xffcb655a, 0xffce675d, + 0xffce6860, 0xffce6860, 0xffce6963, 0xffce6b63, 0xffce6b63, 0xffce6c63, 0xffce6d63, 0xffce6f63, + 0xffce6f63, 0xffce6f63, 0xffce7063, 0xffd07165, 0xffd07165, 0xffd07165, 0xffd37168, 0xffd6716b, + 0xffd6736b, 0xffd6736b, 0xffd6736b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6776b, 0xffd6776b, 0xffd6786b, 0xffd6796e, 0xffd6796e, 0xffd6796e, 0xffd6796e, 0xffd67973, + 0xffd67973, 0xffd67973, 0xffd67973, 0xffd67973, 0xffd67973, 0xffd07770, 0xffc5716b, 0xffb5655a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff6e3e3c, 0xffa55d5a, 0xffa55d5a, 0xffce716b, + 0xffd37770, 0xffd67973, 0xffd67973, 0xffd67970, 0xffd67970, 0xffd67970, 0xffd67970, 0xffd6796b, + 0xffd6786b, 0xffd6786b, 0xffd6786b, 0xffd6776b, 0xffd6776b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6756b, 0xffd6746b, 0xffd6746b, 0xffd67168, 0xffd67168, 0xffd67168, 0xffd67168, 0xffce7063, + 0xffce7063, 0xffce7063, 0xffce7063, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6c63, + 0xffce6b63, 0xffce6b63, 0xffce6b63, 0xffce695a, 0xffce685a, 0xffce675a, 0xffce675a, 0xffc5655a, + 0xffc5655a, 0xffc5645a, 0xffc5645a, 0xffc56158, 0xffc56158, 0xffc56155, 0xffc56155, 0xffc55e52, + 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc55d52, 0xffc55c52, 0xffc55c52, 0xffc55a52, 0xffbd594a, + 0xffbd594a, 0xffbd584a, 0xffbd584a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd544a, + 0xffbd524a, 0xffbd514a, 0xffbd514a, 0xffba5042, 0xffba5042, 0xffb84e42, 0xffb84e42, 0xffb54d42, + 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54a3f, 0xffb54a3f, 0xffb5493a, 0xffb5493a, 0xffb5483a, + 0xffb5483a, 0xffb5463a, 0xffb5453a, 0xffb5453a, 0xffb5433a, 0xffb5433a, 0xffb5423a, 0xffb24137, + 0xffaf4134, 0xffaf4134, 0xffaf4134, 0xffad3f31, 0xffad3f31, 0xffad3e31, 0xffad3e31, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3b2f, 0xffad3b2f, 0xffad3b2f, 0xffad3a2c, 0xffad3929, + 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, + 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3a2c, 0xffad3a2c, 0xffad3a2c, 0xffad3a2c, + 0xffad3b2f, 0xffad3b2f, 0xffad3b2f, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3e31, + 0xffad3f31, 0xffad3f31, 0xffad3f31, 0xffb54131, 0xffb54131, 0xffb54234, 0xffb54337, 0xffb5453a, + 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5463a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb5493a, + 0xffb54a3c, 0xffb54c3f, 0xffb54c3f, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffbd4e47, + 0xffbd5045, 0xffbd5045, 0xffbd5142, 0xffbd524a, 0xffbd524a, 0xffbd544a, 0xffbd544a, 0xffbd554a, + 0xffbd564a, 0xffbd564a, 0xffbd564a, 0xffc0594d, 0xffc0594d, 0xffc0594d, 0xffc35950, 0xffc55c52, + 0xffc55d52, 0xffc55d52, 0xffc55d52, 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc56152, 0xffc5615a, + 0xffc56258, 0xffc56258, 0xffc56258, 0xffc8655a, 0xffc8655a, 0xffcb655a, 0xffcb655a, 0xffce685d, + 0xffce685d, 0xffce695a, 0xffce695a, 0xffce6b63, 0xffce6c63, 0xffce6c63, 0xffce6c63, 0xffce6d63, + 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffd07165, 0xffd07165, 0xffd07165, 0xffd07165, 0xffd6716b, + 0xffd6716b, 0xffd6736b, 0xffd6736b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6776b, 0xffd6776b, 0xffd6786b, 0xffd6796e, 0xffd6796e, 0xffd67970, 0xffd6796e, 0xffd67970, + 0xffd67970, 0xffd67970, 0xffd67970, 0xffd67973, 0xffd67973, 0xffd37770, 0xffce716b, 0xffb5655a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff6e3e3c, 0xffa55d5a, 0xffa55d5a, 0xffce716b, + 0xffd37770, 0xffd67973, 0xffd67973, 0xffd67970, 0xffd67970, 0xffd67970, 0xffd67970, 0xffd6796b, + 0xffd6796b, 0xffd6786b, 0xffd6776b, 0xffd6776b, 0xffd6776b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6756b, 0xffd6746b, 0xffd6746b, 0xffd67168, 0xffd67168, 0xffd67168, 0xffd67165, 0xffce7063, + 0xffce7063, 0xffce7063, 0xffce6f63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6c63, + 0xffce6c63, 0xffce6b63, 0xffce6963, 0xffce695a, 0xffce695a, 0xffce675a, 0xffce675a, 0xffc5655a, + 0xffc5655a, 0xffc5645a, 0xffc5625a, 0xffc56158, 0xffc56158, 0xffc56158, 0xffc56155, 0xffc55e52, + 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc55d52, 0xffc55c52, 0xffc55c52, 0xffc55a52, 0xffbd594a, + 0xffbd594a, 0xffbd584a, 0xffbd564a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd544a, + 0xffbd544a, 0xffbd524a, 0xffbd514a, 0xffba5042, 0xffba5042, 0xffb84e42, 0xffb54d42, 0xffb54d42, + 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54a3f, 0xffb5493a, 0xffb5493a, 0xffb5493a, 0xffb5483a, + 0xffb5463a, 0xffb5463a, 0xffb5453a, 0xffb5453a, 0xffb5433a, 0xffb5433a, 0xffb5433a, 0xffb24137, + 0xffb24137, 0xffaf4134, 0xffaf4134, 0xffad3f31, 0xffad3f31, 0xffad3e31, 0xffad3d31, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3b2f, 0xffad3b2f, 0xffad3b2f, 0xffad3a2c, 0xffad3929, + 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, + 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3a2c, 0xffad3a2c, 0xffad3b2f, + 0xffad3b2f, 0xffad3b2f, 0xffad3b2f, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3e31, + 0xffad3e31, 0xffad3f31, 0xffad3f31, 0xffb54131, 0xffb54234, 0xffb54234, 0xffb54337, 0xffb5453a, + 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5463a, 0xffb5463a, 0xffb5483a, 0xffb5483a, 0xffb5493a, + 0xffb54a3c, 0xffb54c3f, 0xffb54c3f, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffbd4e47, + 0xffbd5045, 0xffbd5045, 0xffbd5045, 0xffbd514a, 0xffbd524a, 0xffbd544a, 0xffbd544a, 0xffbd554a, + 0xffbd554a, 0xffbd564a, 0xffbd564a, 0xffc0594d, 0xffc0594d, 0xffc0594d, 0xffc35950, 0xffc55c52, + 0xffc55c52, 0xffc55d52, 0xffc55d52, 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc56052, 0xffc5615a, + 0xffc5615a, 0xffc56258, 0xffc56258, 0xffc8655a, 0xffc8655a, 0xffcb655a, 0xffcb655a, 0xffce685d, + 0xffce685d, 0xffce695a, 0xffce685d, 0xffce6b63, 0xffce6c63, 0xffce6c63, 0xffce6d63, 0xffce6d63, + 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffd07165, 0xffd07165, 0xffd07165, 0xffd37168, 0xffd6716b, + 0xffd6736b, 0xffd6736b, 0xffd6746b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6776b, 0xffd6786b, 0xffd6786b, 0xffd6796e, 0xffd6796e, 0xffd6796e, 0xffd67970, 0xffd6796e, + 0xffd67970, 0xffd67970, 0xffd67970, 0xffd67973, 0xffd67973, 0xffd37770, 0xffce716b, 0xffb5655a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff6e3e3c, 0xffa55d5a, 0xffa55d5a, 0xffce716b, + 0xffd37770, 0xffd67973, 0xffd67973, 0xffd67970, 0xffd67970, 0xffd6796e, 0xffd6796e, 0xffd6796b, + 0xffd6796b, 0xffd6786b, 0xffd6776b, 0xffd6776b, 0xffd6776b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6756b, 0xffd6756b, 0xffd6746b, 0xffd67168, 0xffd67168, 0xffd67168, 0xffd67168, 0xffce7163, + 0xffce7063, 0xffce7063, 0xffce6f63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6c63, + 0xffce6b63, 0xffce6b63, 0xffce6b63, 0xffce695a, 0xffce695a, 0xffce675a, 0xffce675a, 0xffc5655a, + 0xffc5655a, 0xffc5645a, 0xffc5645a, 0xffc56158, 0xffc56158, 0xffc56158, 0xffc56155, 0xffc55e52, + 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc55d52, 0xffc55c52, 0xffc55a52, 0xffc55a52, 0xffbd594a, + 0xffbd594a, 0xffbd584a, 0xffbd564a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd544a, + 0xffbd524a, 0xffbd524a, 0xffbd514a, 0xffba5042, 0xffba5042, 0xffba5042, 0xffb84e42, 0xffb54d42, + 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54a3f, 0xffb54a3f, 0xffb5493a, 0xffb5493a, 0xffb5483a, + 0xffb5483a, 0xffb5463a, 0xffb5453a, 0xffb5453a, 0xffb5433a, 0xffb5433a, 0xffb5433a, 0xffb24137, + 0xffaf4134, 0xffaf4134, 0xffaf4134, 0xffad3f31, 0xffad3f31, 0xffad3e31, 0xffad3e31, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3b2f, 0xffad3b2f, 0xffad3b2f, 0xffad3a2c, 0xffad3929, + 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, + 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3a2c, 0xffad3a2c, 0xffad3b2f, + 0xffad3b2f, 0xffad3b2f, 0xffad3b2f, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3e31, + 0xffad3f31, 0xffad3f31, 0xffad3f31, 0xffb54131, 0xffb54234, 0xffb54234, 0xffb54337, 0xffb5453a, + 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5463a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb5493a, + 0xffb54a3c, 0xffb54a3c, 0xffb54c3f, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffbd5045, + 0xffbd5045, 0xffbd5045, 0xffbd5142, 0xffbd514a, 0xffbd524a, 0xffbd544a, 0xffbd544a, 0xffbd554a, + 0xffbd564a, 0xffbd564a, 0xffbd564a, 0xffc0594d, 0xffc0594d, 0xffc0594d, 0xffc35950, 0xffc55a52, + 0xffc55d52, 0xffc55d52, 0xffc55d52, 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc56152, 0xffc5615a, + 0xffc56258, 0xffc56258, 0xffc56455, 0xffc8655a, 0xffc8655a, 0xffcb655a, 0xffcb655a, 0xffce685d, + 0xffce685d, 0xffce695a, 0xffce695a, 0xffce6b63, 0xffce6b63, 0xffce6c63, 0xffce6d63, 0xffce6d63, + 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffd07165, 0xffd07165, 0xffd07165, 0xffd37168, 0xffd6716b, + 0xffd6716b, 0xffd6736b, 0xffd6736b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6776b, + 0xffd6756b, 0xffd6786b, 0xffd6786b, 0xffd6796e, 0xffd6796e, 0xffd6796e, 0xffd67970, 0xffd6796e, + 0xffd67970, 0xffd67970, 0xffd67970, 0xffd67973, 0xffd67973, 0xffd37770, 0xffce716b, 0xffb5655a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff6e3e3c, 0xffa55d5a, 0xffa55d5a, 0xffce716b, + 0xffd37770, 0xffd67973, 0xffd67973, 0xffd67970, 0xffd67970, 0xffd67970, 0xffd67970, 0xffd6796b, + 0xffd6786b, 0xffd6786b, 0xffd6776b, 0xffd6786b, 0xffd6756b, 0xffd6776b, 0xffd6756b, 0xffd6756b, + 0xffd6746b, 0xffd6746b, 0xffd6736b, 0xffd67168, 0xffd67168, 0xffd67168, 0xffd67168, 0xffce7063, + 0xffce7063, 0xffce7063, 0xffce7063, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6c63, + 0xffce6b63, 0xffce6b63, 0xffce6963, 0xffce695a, 0xffce685a, 0xffce675a, 0xffce675a, 0xffc5655a, + 0xffc5655a, 0xffc5655a, 0xffc5645a, 0xffc56158, 0xffc56158, 0xffc56158, 0xffc56155, 0xffc56052, + 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc55d52, 0xffc55c52, 0xffc55c52, 0xffc55a52, 0xffbd594a, + 0xffbd594a, 0xffbd584a, 0xffbd584a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd544a, + 0xffbd524a, 0xffbd524a, 0xffbd514a, 0xffba5042, 0xffba5042, 0xffba5042, 0xffb54d42, 0xffb54d42, + 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54a3f, 0xffb54a3f, 0xffb5493a, 0xffb5493a, 0xffb5483a, + 0xffb5463a, 0xffb5463a, 0xffb5453a, 0xffb5453a, 0xffb5433a, 0xffb5433a, 0xffb5423a, 0xffb24137, + 0xffaf4134, 0xffaf4134, 0xffaf4134, 0xffad3f31, 0xffad3f31, 0xffad3e31, 0xffad3e31, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3b2f, 0xffad3b2f, 0xffad3a2c, 0xffad3a2c, 0xffad3929, + 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, + 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3929, 0xffad3a2c, 0xffad3a2c, 0xffad3b2f, 0xffad3b2f, + 0xffad3b2f, 0xffad3b2f, 0xffad3b2f, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3e31, + 0xffad3f31, 0xffad3f31, 0xffad3f31, 0xffb54131, 0xffb54131, 0xffb54234, 0xffb54234, 0xffb5453a, + 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5463a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb5493a, + 0xffb54a3c, 0xffb54a3c, 0xffb54c3f, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffbd4e47, + 0xffbd5045, 0xffbd5045, 0xffbd5142, 0xffbd524a, 0xffbd524a, 0xffbd544a, 0xffbd544a, 0xffbd554a, + 0xffbd564a, 0xffbd564a, 0xffbd584a, 0xffc0594d, 0xffc0594d, 0xffc0594d, 0xffc0594d, 0xffc55a52, + 0xffc55c52, 0xffc55d52, 0xffc55d52, 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc56152, 0xffc56258, + 0xffc56258, 0xffc56258, 0xffc56455, 0xffc8655a, 0xffc8655a, 0xffcb655a, 0xffcb655a, 0xffce685d, + 0xffce685d, 0xffce695a, 0xffce695a, 0xffce6b63, 0xffce6b63, 0xffce6c63, 0xffce6d63, 0xffce6d63, + 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffd07165, 0xffd07165, 0xffd07165, 0xffd07165, 0xffd6716b, + 0xffd6716b, 0xffd6736b, 0xffd6746b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6776b, 0xffd6786b, 0xffd6776b, 0xffd6796e, 0xffd6796e, 0xffd6796e, 0xffd67970, 0xffd67970, + 0xffd67970, 0xffd67970, 0xffd67970, 0xffd67973, 0xffd67973, 0xffd37770, 0xffce716b, 0xffb5655a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff6e3e37, 0xffa55d52, 0xffa55d52, 0xffc57163, + 0xffd0776e, 0xffd67973, 0xffd67973, 0xffd67970, 0xffd6796e, 0xffd6796e, 0xffd6796e, 0xffd6786b, + 0xffd6786b, 0xffd6786b, 0xffd6776b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6756b, 0xffd6746b, 0xffd6746b, 0xffd37168, 0xffd37168, 0xffd37168, 0xffd07165, 0xffce7063, + 0xffce7063, 0xffce6f63, 0xffce6f63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6c63, 0xffce6960, + 0xffce6960, 0xffce6960, 0xffce695d, 0xffcb685a, 0xffcb685a, 0xffc8675a, 0xffc8675a, 0xffc5655a, + 0xffc5655a, 0xffc5645a, 0xffc5625a, 0xffc56158, 0xffc56158, 0xffc56155, 0xffc56155, 0xffc56052, + 0xffc55e52, 0xffc55e52, 0xffc55d52, 0xffc55c52, 0xffc55c52, 0xffc55a52, 0xffc55952, 0xffbd594a, + 0xffbd584a, 0xffbd584a, 0xffbd564a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd544a, + 0xffbd524a, 0xffbd514a, 0xffbd514a, 0xffb55042, 0xffb55042, 0xffb55042, 0xffb54e42, 0xffb54d42, + 0xffb54c42, 0xffb54c42, 0xffb54a42, 0xffb5493f, 0xffb5493c, 0xffb5493c, 0xffb5493c, 0xffb5483a, + 0xffb5483a, 0xffb5463a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb24137, + 0xffaf4134, 0xffaf4134, 0xffaf4134, 0xffad3f31, 0xffad3f31, 0xffad3e31, 0xffad3d31, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3b31, 0xffad3a31, 0xffad3a31, 0xffad3931, 0xffad392c, + 0xffad392c, 0xffad392c, 0xffad392c, 0xffaa3929, 0xffaa3929, 0xffa73929, 0xffaa3929, 0xffa73929, + 0xffaa3929, 0xffaa3929, 0xffaa3929, 0xffad392c, 0xffad392c, 0xffad392c, 0xffad392c, 0xffad3a31, + 0xffad3a31, 0xffad3b31, 0xffad3b31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3e31, + 0xffad3f31, 0xffad3f31, 0xffad3f31, 0xffad4131, 0xffaf4234, 0xffaf4234, 0xffb24337, 0xffb5453a, + 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb54942, + 0xffb54a3c, 0xffb54a3c, 0xffb54a3c, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffba5045, + 0xffba5045, 0xffba5045, 0xffbd5142, 0xffbd514a, 0xffbd524a, 0xffbd544a, 0xffbd544a, 0xffbd554a, + 0xffbd554a, 0xffbd564a, 0xffbd584a, 0xffbd594d, 0xffbd594d, 0xffbd594d, 0xffbd5950, 0xffc55a52, + 0xffc55a52, 0xffc55c52, 0xffc55d52, 0xffc55e52, 0xffc55e52, 0xffc56052, 0xffc56052, 0xffc5615a, + 0xffc56258, 0xffc56258, 0xffc56258, 0xffc5655a, 0xffc5655a, 0xffc5655a, 0xffc5655a, 0xffcb685a, + 0xffcb685a, 0xffcb685a, 0xffce695a, 0xffce6b63, 0xffce6b63, 0xffce6b63, 0xffce6c63, 0xffce6d63, + 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6f65, 0xffce6f65, 0xffce7068, 0xffce7068, 0xffd6716b, + 0xffd6716b, 0xffd6736b, 0xffd6746b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6776b, 0xffd6786b, 0xffd6786b, 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6796e, + 0xffd6796e, 0xffd6796e, 0xffd67970, 0xffd67973, 0xffd67973, 0xffd0776e, 0xffc57163, 0xffb5655a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff6e3e37, 0xffa55d52, 0xffa55d52, 0xffc57163, + 0xffd0776e, 0xffd67973, 0xffd67973, 0xffd67970, 0xffd6796e, 0xffd6796e, 0xffd6796e, 0xffd6786b, + 0xffd6786b, 0xffd6786b, 0xffd6786b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6756b, 0xffd6746b, 0xffd6736b, 0xffd37168, 0xffd37168, 0xffd37168, 0xffd37168, 0xffce7063, + 0xffce7063, 0xffce6f63, 0xffce6f63, 0xffce6d63, 0xffce6d63, 0xffce6c63, 0xffce6b63, 0xffce6960, + 0xffce6960, 0xffce6960, 0xffce695d, 0xffcb685a, 0xffcb685a, 0xffcb685a, 0xffc8675a, 0xffc5655a, + 0xffc5655a, 0xffc5645a, 0xffc5645a, 0xffc56158, 0xffc56158, 0xffc56155, 0xffc56155, 0xffc56052, + 0xffc55e52, 0xffc55e52, 0xffc55d52, 0xffc55c52, 0xffc55a52, 0xffc55a52, 0xffc55a52, 0xffbd594a, + 0xffbd584a, 0xffbd584a, 0xffbd584a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd544a, + 0xffbd524a, 0xffbd524a, 0xffbd514a, 0xffb55042, 0xffb55042, 0xffb54e42, 0xffb54d42, 0xffb54d42, + 0xffb54c42, 0xffb54c42, 0xffb54c42, 0xffb5493f, 0xffb5493c, 0xffb5493c, 0xffb5493c, 0xffb5483a, + 0xffb5463a, 0xffb5463a, 0xffb5463a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb24137, + 0xffb24137, 0xffaf4134, 0xffaf4134, 0xffad3f31, 0xffad3e31, 0xffad3f31, 0xffad3e31, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3b31, 0xffad3a31, 0xffad3a31, 0xffad3931, 0xffad392c, + 0xffad392c, 0xffad392c, 0xffad392c, 0xffaa3929, 0xffaa3929, 0xffaa3929, 0xffaa3929, 0xffa73929, + 0xffaa3929, 0xffaa3929, 0xffaa3929, 0xffad392c, 0xffad392c, 0xffad392f, 0xffad392c, 0xffad3a31, + 0xffad3b31, 0xffad3b31, 0xffad3b31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3e31, + 0xffad3f31, 0xffad3f31, 0xffad3f31, 0xffaf4234, 0xffaf4234, 0xffaf4234, 0xffb24337, 0xffb5453a, + 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5463a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb54942, + 0xffb54a3c, 0xffb54a3c, 0xffb54a3c, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb84e47, + 0xffba5045, 0xffba5045, 0xffbd5142, 0xffbd514a, 0xffbd524a, 0xffbd544a, 0xffbd544a, 0xffbd554a, + 0xffbd564a, 0xffbd564a, 0xffbd564a, 0xffbd594d, 0xffbd594d, 0xffbd594d, 0xffbd5950, 0xffc55a52, + 0xffc55a52, 0xffc55c52, 0xffc55d52, 0xffc55e52, 0xffc55e52, 0xffc56052, 0xffc56152, 0xffc5615a, + 0xffc56258, 0xffc56258, 0xffc56455, 0xffc5655a, 0xffc5655a, 0xffc5655a, 0xffc5655a, 0xffcb685a, + 0xffcb685a, 0xffcb685a, 0xffce695a, 0xffce6963, 0xffce6b63, 0xffce6b63, 0xffce6b63, 0xffce6d63, + 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6f65, 0xffce6f65, 0xffce7068, 0xffce7068, 0xffd6716b, + 0xffd6736b, 0xffd6736b, 0xffd6736b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6776b, + 0xffd6776b, 0xffd6786b, 0xffd6786b, 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6796e, + 0xffd6796e, 0xffd67970, 0xffd67970, 0xffd67973, 0xffd67973, 0xffd0776e, 0xffc57163, 0xffb5655a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff6e3e37, 0xffa55d52, 0xffa55d52, 0xffc57163, + 0xffd0776e, 0xffd67973, 0xffd67973, 0xffd67970, 0xffd67970, 0xffd6796e, 0xffd6796e, 0xffd6786b, + 0xffd6786b, 0xffd6786b, 0xffd6786b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6756b, 0xffd6746b, 0xffd6746b, 0xffd37168, 0xffd37168, 0xffd37168, 0xffd37168, 0xffce7063, + 0xffce7063, 0xffce6f63, 0xffce6f63, 0xffce6d63, 0xffce6d63, 0xffce6c63, 0xffce6c63, 0xffce6960, + 0xffce6960, 0xffce6960, 0xffce695d, 0xffcb685a, 0xffcb685a, 0xffcb685a, 0xffc8675a, 0xffc5655a, + 0xffc5655a, 0xffc5645a, 0xffc5625a, 0xffc56158, 0xffc56158, 0xffc56155, 0xffc56155, 0xffc56052, + 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc55c52, 0xffc55c52, 0xffc55a52, 0xffc55a52, 0xffbd594a, + 0xffbd584a, 0xffbd584a, 0xffbd564a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd544a, + 0xffbd544a, 0xffbd524a, 0xffbd514a, 0xffb55042, 0xffb55042, 0xffb54e42, 0xffb54e42, 0xffb54d42, + 0xffb54d42, 0xffb54c42, 0xffb54a42, 0xffb5493f, 0xffb5493c, 0xffb5493c, 0xffb5493c, 0xffb5483a, + 0xffb5483a, 0xffb5463a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb24137, + 0xffaf4134, 0xffaf4134, 0xffaf4134, 0xffad3f31, 0xffad3f31, 0xffad3e31, 0xffad3e31, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3b31, 0xffad3b31, 0xffad3a31, 0xffad3a31, 0xffad392c, + 0xffad392c, 0xffad392c, 0xffad392c, 0xffaa3929, 0xffaa3929, 0xffaa3929, 0xffaa3929, 0xffaa3929, + 0xffaa3929, 0xffaa3929, 0xffaa3929, 0xffad392c, 0xffad392c, 0xffad392f, 0xffad392c, 0xffad3a31, + 0xffad3b31, 0xffad3b31, 0xffad3b31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3f31, + 0xffad3f31, 0xffad3f31, 0xffad3f31, 0xffad4131, 0xffaf4234, 0xffaf4234, 0xffb24337, 0xffb5453a, + 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb54942, + 0xffb54942, 0xffb54a3c, 0xffb54a3c, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb84e47, + 0xffba5045, 0xffba5045, 0xffbd5142, 0xffbd524a, 0xffbd544a, 0xffbd544a, 0xffbd544a, 0xffbd554a, + 0xffbd564a, 0xffbd564a, 0xffbd584a, 0xffbd594d, 0xffbd594d, 0xffbd594d, 0xffbd5950, 0xffc55a52, + 0xffc55c52, 0xffc55c52, 0xffc55d52, 0xffc55e52, 0xffc55e52, 0xffc56052, 0xffc56052, 0xffc5615a, + 0xffc56258, 0xffc56258, 0xffc56455, 0xffc5655a, 0xffc5655a, 0xffc5655a, 0xffc5655a, 0xffc8675a, + 0xffcb685a, 0xffcb685a, 0xffce695a, 0xffce6b63, 0xffce6b63, 0xffce6b63, 0xffce6c63, 0xffce6d63, + 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6f65, 0xffce7068, 0xffce7068, 0xffce7068, 0xffd6716b, + 0xffd6716b, 0xffd6736b, 0xffd6746b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6776b, + 0xffd6756b, 0xffd6786b, 0xffd6786b, 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6796e, + 0xffd67970, 0xffd6796e, 0xffd67970, 0xffd67973, 0xffd67973, 0xffd0776e, 0xffc57163, 0xffb5655a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff6e3e37, 0xffa55d52, 0xffa55d52, 0xffc57163, + 0xffd0776e, 0xffd67973, 0xffd67973, 0xffd67970, 0xffd6796e, 0xffd6796e, 0xffd6796e, 0xffd6786b, + 0xffd6786b, 0xffd6786b, 0xffd6786b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6756b, 0xffd6746b, 0xffd6746b, 0xffd37168, 0xffd37168, 0xffd37168, 0xffd37168, 0xffce7063, + 0xffce7063, 0xffce6f63, 0xffce6f63, 0xffce6d63, 0xffce6d63, 0xffce6c63, 0xffce6c63, 0xffce6960, + 0xffce6960, 0xffce6960, 0xffce695d, 0xffcb685a, 0xffcb685a, 0xffc8675a, 0xffc8675a, 0xffc5655a, + 0xffc5655a, 0xffc5655a, 0xffc5645a, 0xffc56158, 0xffc56158, 0xffc56155, 0xffc56155, 0xffc56052, + 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc55d52, 0xffc55a52, 0xffc55a52, 0xffc55952, 0xffbd594a, + 0xffbd584a, 0xffbd584a, 0xffbd584a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd544a, + 0xffbd524a, 0xffbd524a, 0xffbd514a, 0xffb55042, 0xffb55042, 0xffb54e42, 0xffb54e42, 0xffb54d42, + 0xffb54c42, 0xffb54c42, 0xffb54c42, 0xffb5493f, 0xffb5493f, 0xffb5493c, 0xffb5493c, 0xffb5483a, + 0xffb5483a, 0xffb5483a, 0xffb5463a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb24137, + 0xffb24137, 0xffb24137, 0xffaf4134, 0xffad3f31, 0xffad3f31, 0xffad3e31, 0xffad3e31, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3b31, 0xffad3b31, 0xffad3a31, 0xffad3a31, 0xffad392f, + 0xffad392c, 0xffad392c, 0xffad392c, 0xffaa3929, 0xffaa3929, 0xffaa3929, 0xffaa3929, 0xffaa3929, + 0xffaa3929, 0xffaa3929, 0xffaa3929, 0xffad392c, 0xffad392c, 0xffad392c, 0xffad392f, 0xffad3a31, + 0xffad3b31, 0xffad3b31, 0xffad3b31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3e31, + 0xffad3f31, 0xffad3f31, 0xffad4131, 0xffaf4234, 0xffaf4234, 0xffaf4234, 0xffaf4234, 0xffb5453a, + 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb54942, + 0xffb54942, 0xffb54a3c, 0xffb54a3c, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffba5045, + 0xffba5045, 0xffba5045, 0xffbd5142, 0xffbd524a, 0xffbd544a, 0xffbd544a, 0xffbd554a, 0xffbd554a, + 0xffbd564a, 0xffbd564a, 0xffbd584a, 0xffbd594d, 0xffbd594d, 0xffbd594d, 0xffbd5950, 0xffc55a52, + 0xffc55c52, 0xffc55c52, 0xffc55d52, 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc56152, 0xffc5615a, + 0xffc56258, 0xffc56258, 0xffc56258, 0xffc5655a, 0xffc5655a, 0xffc5655a, 0xffc5655a, 0xffcb685a, + 0xffcb685a, 0xffcb685a, 0xffce695a, 0xffce6963, 0xffce6b63, 0xffce6b63, 0xffce6c63, 0xffce6d63, + 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6f65, 0xffce7068, 0xffce7068, 0xffce7068, 0xffd6716b, + 0xffd6716b, 0xffd6736b, 0xffd6746b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6776b, 0xffd6776b, 0xffd6776b, 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6796e, + 0xffd6796e, 0xffd67970, 0xffd67970, 0xffd67973, 0xffd67973, 0xffd0776e, 0xffc57163, 0xffb5655a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff6e3e37, 0xffa55d52, 0xffa55d52, 0xffc57163, + 0xffd0776e, 0xffd67973, 0xffd67973, 0xffd67970, 0xffd6796e, 0xffd6796e, 0xffd6796e, 0xffd6786b, + 0xffd6786b, 0xffd6786b, 0xffd6786b, 0xffd6776b, 0xffd6776b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6756b, 0xffd6746b, 0xffd6736b, 0xffd6736b, 0xffd6736b, 0xffd6716b, 0xffd6716b, 0xffce7063, + 0xffce7063, 0xffce6f63, 0xffce6f63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6c5d, + 0xffce6b60, 0xffce6963, 0xffce6963, 0xffcb685a, 0xffcb685a, 0xffc8675a, 0xffc8675a, 0xffc5655a, + 0xffc5655a, 0xffc5655a, 0xffc5655a, 0xffc56158, 0xffc56158, 0xffc56158, 0xffc56155, 0xffc56052, + 0xffc55e52, 0xffc55e52, 0xffc55d52, 0xffc55d52, 0xffc55a52, 0xffc55a52, 0xffc55a52, 0xffbd594a, + 0xffbd594a, 0xffbd584d, 0xffbd584d, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd544a, + 0xffbd544a, 0xffbd524a, 0xffbd514a, 0xffb55042, 0xffb55042, 0xffb55042, 0xffb54e42, 0xffb54d42, + 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54a3f, 0xffb54a3f, 0xffb5493a, 0xffb5493a, 0xffb5483a, + 0xffb5483a, 0xffb5483a, 0xffb5463a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffaf4234, + 0xffaf4234, 0xffaf4234, 0xffad4131, 0xffad3f31, 0xffad3f31, 0xffad3f31, 0xffad3e31, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3b31, 0xffad3b31, 0xffad3b31, 0xffad3a31, 0xffad3a2c, + 0xffad3a2c, 0xffad3a2c, 0xffad3a2c, 0xffad392c, 0xffad392c, 0xffad392c, 0xffad392c, 0xffad392c, + 0xffad392c, 0xffad392c, 0xffad392c, 0xffad3931, 0xffad3931, 0xffad3a31, 0xffad3b31, 0xffad3a31, + 0xffad3b31, 0xffad3b31, 0xffad3b31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3e31, 0xffad3e37, + 0xffad3f34, 0xffad3f34, 0xffad3f34, 0xffad413a, 0xffad413a, 0xffaf423a, 0xffb2433a, 0xffb5453a, + 0xffb5453a, 0xffb5453a, 0xffb5463a, 0xffb5463a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb54a3f, + 0xffb54942, 0xffb54a3f, 0xffb54a3f, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffba5047, + 0xffba5047, 0xffbd5142, 0xffbd5142, 0xffbd524a, 0xffbd544a, 0xffbd544a, 0xffbd544a, 0xffbd554a, + 0xffbd564a, 0xffbd564a, 0xffbd564a, 0xffc0594d, 0xffc0594d, 0xffc0594d, 0xffc35950, 0xffc55a52, + 0xffc55c52, 0xffc55c52, 0xffc55d52, 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc56052, 0xffc5615a, + 0xffc5625a, 0xffc5625a, 0xffc5625a, 0xffc8655a, 0xffc8655a, 0xffc8655a, 0xffc8655a, 0xffce685d, + 0xffce685d, 0xffce685d, 0xffce685d, 0xffce6963, 0xffce6b63, 0xffce6b63, 0xffce6b63, 0xffce6d63, + 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce7068, 0xffce7068, 0xffce7068, 0xffce7163, 0xffd6716b, + 0xffd6736b, 0xffd6736b, 0xffd6736b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6776b, 0xffd6776b, 0xffd6786b, 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6796e, + 0xffd67970, 0xffd6796e, 0xffd67970, 0xffd67973, 0xffd67973, 0xffd0776e, 0xffc57163, 0xffb5655a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff6e3e37, 0xffa55d52, 0xffa55d52, 0xffc57163, + 0xffd0776e, 0xffd67973, 0xffd67973, 0xffd67970, 0xffd67970, 0xffd6796e, 0xffd6796e, 0xffd6796b, + 0xffd6786b, 0xffd6786b, 0xffd6786b, 0xffd6786b, 0xffd6776b, 0xffd6776b, 0xffd6756b, 0xffd6756b, + 0xffd6756b, 0xffd6746b, 0xffd6746b, 0xffd6736b, 0xffd6716b, 0xffd6716b, 0xffd6716b, 0xffce7163, + 0xffce7063, 0xffce6f63, 0xffce6f63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6b60, + 0xffce6b60, 0xffce6b60, 0xffce6963, 0xffcb685a, 0xffcb685a, 0xffcb685a, 0xffc8675a, 0xffc5655a, + 0xffc5655a, 0xffc5655a, 0xffc5655a, 0xffc56158, 0xffc56158, 0xffc56155, 0xffc56155, 0xffc56052, + 0xffc55e52, 0xffc55e52, 0xffc55d52, 0xffc55c52, 0xffc55a52, 0xffc55a52, 0xffc55a52, 0xffbd594a, + 0xffbd584d, 0xffbd584d, 0xffbd584d, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd544a, + 0xffbd544a, 0xffbd524a, 0xffbd514a, 0xffb55042, 0xffb55042, 0xffb55042, 0xffb54e42, 0xffb54d42, + 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54a3f, 0xffb54a3f, 0xffb54a3f, 0xffb5493a, 0xffb5483a, + 0xffb5483a, 0xffb5463a, 0xffb5463a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb24337, + 0xffaf4234, 0xffaf4234, 0xffad4131, 0xffad3f31, 0xffad3f31, 0xffad3f31, 0xffad3e31, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3b31, 0xffad3b31, 0xffad3b31, 0xffad3b31, 0xffad3a2c, + 0xffad3a2c, 0xffad3a2c, 0xffad3a2c, 0xffad392c, 0xffad392c, 0xffad392c, 0xffad392c, 0xffad392c, + 0xffad392c, 0xffad392c, 0xffad392c, 0xffad3a31, 0xffad3a31, 0xffad3a31, 0xffad3b31, 0xffad3b31, + 0xffad3b31, 0xffad3b31, 0xffad3b31, 0xffad3d31, 0xffad3e31, 0xffad3e31, 0xffad3e31, 0xffad3f34, + 0xffad3f34, 0xffad3f34, 0xffad4131, 0xffaf423a, 0xffaf423a, 0xffaf423a, 0xffb2433a, 0xffb5453a, + 0xffb5453a, 0xffb5453a, 0xffb5463a, 0xffb5463a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb54942, + 0xffb54a3f, 0xffb54a3f, 0xffb54a3f, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffba5047, + 0xffba5047, 0xffba5047, 0xffbd5142, 0xffbd524a, 0xffbd544a, 0xffbd544a, 0xffbd544a, 0xffbd554a, + 0xffbd564a, 0xffbd564a, 0xffbd584a, 0xffc0594d, 0xffc0594d, 0xffc0594d, 0xffc35950, 0xffc55a52, + 0xffc55c52, 0xffc55c52, 0xffc55d52, 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc56052, 0xffc5615a, + 0xffc5625a, 0xffc5625a, 0xffc5645a, 0xffc8655a, 0xffc8655a, 0xffc8655a, 0xffc8655a, 0xffce685d, + 0xffce685d, 0xffce685d, 0xffce695a, 0xffce6963, 0xffce6b63, 0xffce6b63, 0xffce6c63, 0xffce6d63, + 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce7068, 0xffce7068, 0xffce7068, 0xffce7163, 0xffd6716b, + 0xffd6736b, 0xffd6736b, 0xffd6746b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6776b, 0xffd6776b, 0xffd6786b, 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6796e, + 0xffd6796e, 0xffd67970, 0xffd67970, 0xffd67973, 0xffd67973, 0xffd0776e, 0xffc57163, 0xffb5655a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff6e3e37, 0xffa55d52, 0xffa55d52, 0xffc57163, + 0xffd0776e, 0xffd67973, 0xffd67973, 0xffd67970, 0xffd6796e, 0xffd6796e, 0xffd6796e, 0xffd6786b, + 0xffd6786b, 0xffd6786b, 0xffd6776b, 0xffd6786b, 0xffd6776b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6756b, 0xffd6746b, 0xffd6736b, 0xffd6746b, 0xffd6716b, 0xffd6716b, 0xffd6716b, 0xffce7163, + 0xffce7063, 0xffce6f63, 0xffce6f63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6b60, + 0xffce6b60, 0xffce6b60, 0xffce6963, 0xffce695a, 0xffcb685a, 0xffcb685a, 0xffc8675a, 0xffc5655a, + 0xffc5655a, 0xffc5655a, 0xffc5655a, 0xffc56158, 0xffc56158, 0xffc56158, 0xffc56155, 0xffc56052, + 0xffc55e52, 0xffc55e52, 0xffc55d52, 0xffc55d52, 0xffc55c52, 0xffc55a52, 0xffc55a52, 0xffbd594a, + 0xffbd584d, 0xffbd584d, 0xffbd584d, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd544a, + 0xffbd524a, 0xffbd524a, 0xffbd524a, 0xffb55042, 0xffb55042, 0xffb54e42, 0xffb54e42, 0xffb54d42, + 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54a3f, 0xffb54a3f, 0xffb5493a, 0xffb5493a, 0xffb5483a, + 0xffb5483a, 0xffb5483a, 0xffb5463a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb24337, + 0xffaf4234, 0xffaf4234, 0xffad4131, 0xffad3f31, 0xffad3f31, 0xffad3f31, 0xffad3f31, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3b31, 0xffad3b31, 0xffad3b31, 0xffad3b31, 0xffad3b2f, + 0xffad3b2f, 0xffad3a2c, 0xffad3a2c, 0xffad392c, 0xffad392f, 0xffad392c, 0xffad392c, 0xffad392f, + 0xffad392c, 0xffad392f, 0xffad392f, 0xffad3a31, 0xffad3a31, 0xffad3b31, 0xffad3b31, 0xffad3b31, + 0xffad3b31, 0xffad3b31, 0xffad3b31, 0xffad3d31, 0xffad3e31, 0xffad3e31, 0xffad3e31, 0xffad3f34, + 0xffad3f34, 0xffad3f34, 0xffad4131, 0xffad413a, 0xffaf423a, 0xffaf423a, 0xffb2433a, 0xffb5453a, + 0xffb5453a, 0xffb5463a, 0xffb5463a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb54942, + 0xffb54942, 0xffb54c3c, 0xffb54a3f, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffba5047, + 0xffba5047, 0xffba5047, 0xffba5047, 0xffbd524a, 0xffbd544a, 0xffbd544a, 0xffbd544a, 0xffbd564a, + 0xffbd564a, 0xffbd564a, 0xffbd584a, 0xffc0594d, 0xffc0594d, 0xffc0594d, 0xffc35950, 0xffc55a52, + 0xffc55a52, 0xffc55d52, 0xffc55d52, 0xffc55e52, 0xffc55e52, 0xffc56052, 0xffc56152, 0xffc5625a, + 0xffc5625a, 0xffc5645a, 0xffc5645a, 0xffc8655a, 0xffc8655a, 0xffc8655a, 0xffcb655a, 0xffce685d, + 0xffce685d, 0xffce695a, 0xffce695a, 0xffce6b63, 0xffce6b63, 0xffce6b63, 0xffce6c63, 0xffce6d63, + 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce7068, 0xffce7068, 0xffce7068, 0xffce7068, 0xffd6716b, + 0xffd6736b, 0xffd6736b, 0xffd6746b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6776b, 0xffd6776b, 0xffd6786b, 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6796e, + 0xffd6796e, 0xffd6796e, 0xffd67970, 0xffd67973, 0xffd67973, 0xffd0776e, 0xffc57163, 0xffb5655a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff6e3e37, 0xffa55d52, 0xffa55d52, 0xffc57163, + 0xffd0776e, 0xffd67973, 0xffd67973, 0xffd67970, 0xffd67970, 0xffd6796e, 0xffd6796e, 0xffd6796b, + 0xffd6786b, 0xffd6786b, 0xffd6786b, 0xffd6776b, 0xffd6776b, 0xffd6756b, 0xffd6756b, 0xffd6756b, + 0xffd6756b, 0xffd6746b, 0xffd6746b, 0xffd6736b, 0xffd6736b, 0xffd6716b, 0xffd6716b, 0xffce7163, + 0xffce7063, 0xffce7063, 0xffce6f63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce6c5d, + 0xffce6b60, 0xffce6b60, 0xffce6963, 0xffcb685a, 0xffcb685a, 0xffcb685a, 0xffc8675a, 0xffc5655a, + 0xffc5655a, 0xffc5655a, 0xffc5655a, 0xffc56158, 0xffc56158, 0xffc56158, 0xffc56155, 0xffc56052, + 0xffc55e52, 0xffc55e52, 0xffc55e52, 0xffc55c52, 0xffc55c52, 0xffc55a52, 0xffc55a52, 0xffbd594a, + 0xffbd594a, 0xffbd584d, 0xffbd584d, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd554a, 0xffbd544a, + 0xffbd544a, 0xffbd524a, 0xffbd514a, 0xffb55142, 0xffb55042, 0xffb55042, 0xffb54e42, 0xffb54d42, + 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54a3f, 0xffb54a3f, 0xffb54a3f, 0xffb5493a, 0xffb5483a, + 0xffb5483a, 0xffb5483a, 0xffb5463a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb5453a, 0xffb24337, + 0xffaf4234, 0xffaf4234, 0xffaf4234, 0xffad4131, 0xffad3f31, 0xffad3f31, 0xffad3f31, 0xffad3d31, + 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3b31, 0xffad3b31, 0xffad3b31, 0xffad3b31, 0xffad3a2c, + 0xffad3b2f, 0xffad3b2f, 0xffad3b2f, 0xffad392f, 0xffad392f, 0xffad392f, 0xffad392f, 0xffad392f, + 0xffad392f, 0xffad392f, 0xffad392f, 0xffad3a31, 0xffad3a31, 0xffad3b31, 0xffad3b31, 0xffad3b31, + 0xffad3b31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3d31, 0xffad3e31, 0xffad3f31, 0xffad3f34, + 0xffad3f34, 0xffad3f34, 0xffad4131, 0xffaf423a, 0xffb2433a, 0xffb2433a, 0xffb2433a, 0xffb5453a, + 0xffb5453a, 0xffb5463a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb5483a, 0xffb54942, + 0xffb54942, 0xffb54a3f, 0xffb54a3f, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffb54d42, 0xffba5047, + 0xffba5047, 0xffbd5142, 0xffbd5142, 0xffbd524a, 0xffbd544a, 0xffbd544a, 0xffbd554a, 0xffbd564a, + 0xffbd564a, 0xffbd564a, 0xffbd584a, 0xffc0594d, 0xffc0594d, 0xffc35950, 0xffc35950, 0xffc55a52, + 0xffc55c52, 0xffc55c52, 0xffc55d52, 0xffc55e52, 0xffc55e52, 0xffc56052, 0xffc56152, 0xffc5625a, + 0xffc5625a, 0xffc5625a, 0xffc5645a, 0xffc8655a, 0xffc8655a, 0xffc8655a, 0xffc8655a, 0xffce685d, + 0xffce685d, 0xffce685d, 0xffce695a, 0xffce6b63, 0xffce6b63, 0xffce6c63, 0xffce6c63, 0xffce6d63, + 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffce7068, 0xffce7068, 0xffce7068, 0xffce7068, 0xffd6716b, + 0xffd6716b, 0xffd6746b, 0xffd6746b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6756b, 0xffd6776b, + 0xffd6776b, 0xffd6776b, 0xffd6786b, 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6796b, 0xffd6796e, + 0xffd67970, 0xffd6796e, 0xffd67970, 0xffd67973, 0xffd67973, 0xffd0776e, 0xffc57163, 0xffb5655a, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00100400, 0xff473531, 0xff7e6563, 0xff7e6563, 0xffad655a, + 0xffad7b73, 0xffad7b73, 0xffad7b73, 0xffb57573, 0xffb57573, 0xffb57573, 0xffb57573, 0xffb5756b, + 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5716b, + 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffad716b, + 0xffad716b, 0xffad716b, 0xffad716b, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, + 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffb5655a, 0xffb5655a, 0xffb5655a, 0xffb5655a, 0xffb5615a, + 0xffb5615a, 0xffb5615a, 0xffb5615a, 0xffb55d52, 0xffb55d52, 0xffb55d52, 0xffb55d52, 0xffb55d52, + 0xffb55d52, 0xffb55d52, 0xffb55d52, 0xffad5952, 0xffad5952, 0xffad5952, 0xffad5952, 0xffad594a, + 0xffad594a, 0xffad594a, 0xffad594a, 0xffad554a, 0xffad554a, 0xffad554a, 0xffad554a, 0xffad514a, + 0xffad514a, 0xffad514a, 0xffad514a, 0xffa55142, 0xffa55142, 0xffa55142, 0xffa55142, 0xffa54d42, + 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54942, + 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54942, 0xff9c453a, + 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c413a, + 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, + 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c3d3a, + 0xff9c3d3a, 0xff9c3d3a, 0xff9c3d3a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, + 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c453a, + 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xffa54942, + 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54d42, + 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffad514a, + 0xffad514a, 0xffad514a, 0xffad514a, 0xffad554a, 0xffad554a, 0xffad554a, 0xffad554a, 0xffad554a, + 0xffad554a, 0xffad554a, 0xffad554a, 0xffad5952, 0xffad5952, 0xffad5952, 0xffad5952, 0xffb55952, + 0xffb55952, 0xffb55952, 0xffb55952, 0xffb55d52, 0xffb55d52, 0xffb55d52, 0xffb55d52, 0xffb55d5a, + 0xffb55d5a, 0xffb55d5a, 0xffb55d5a, 0xffb5615a, 0xffb5615a, 0xffb5615a, 0xffb5615a, 0xffbd655a, + 0xffbd655a, 0xffbd655a, 0xffbd655a, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, + 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffad716b, 0xffad716b, 0xffad716b, 0xffad716b, 0xffb5716b, + 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5756b, + 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb57573, + 0xffb57573, 0xffb57573, 0xffb57573, 0xffad7b73, 0xffad7b73, 0xffad7b73, 0xffad655a, 0xff7e6463, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00100400, 0xff473531, 0xff7e6563, 0xff7e6563, 0xffad655a, + 0xffad7b73, 0xffad7b73, 0xffad7b73, 0xffb57573, 0xffb57573, 0xffb57573, 0xffb57573, 0xffb5756b, + 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5716b, + 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffad716b, + 0xffad716b, 0xffad716b, 0xffad716b, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, + 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffb5655a, 0xffb5655a, 0xffb5655a, 0xffb5655a, 0xffb5615a, + 0xffb5615a, 0xffb5615a, 0xffb5615a, 0xffb55d52, 0xffb55d52, 0xffb55d52, 0xffb55d52, 0xffb55d52, + 0xffb55d52, 0xffb55d52, 0xffb55d52, 0xffad5952, 0xffad5952, 0xffad5952, 0xffad5952, 0xffad594a, + 0xffad594a, 0xffad594a, 0xffad594a, 0xffad554a, 0xffad554a, 0xffad554a, 0xffad554a, 0xffad514a, + 0xffad514a, 0xffad514a, 0xffad514a, 0xffa55142, 0xffa55142, 0xffa55142, 0xffa55142, 0xffa54d42, + 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54942, + 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54942, 0xff9c453a, + 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c413a, + 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, + 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c3d3a, + 0xff9c3d3a, 0xff9c3d3a, 0xff9c3d3a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, + 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c413a, 0xff9c453a, + 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xff9c453a, 0xffa54942, + 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54942, 0xffa54d42, + 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffa54d42, 0xffad514a, + 0xffad514a, 0xffad514a, 0xffad514a, 0xffad554a, 0xffad554a, 0xffad554a, 0xffad554a, 0xffad554a, + 0xffad554a, 0xffad554a, 0xffad554a, 0xffad5952, 0xffad5952, 0xffad5952, 0xffad5952, 0xffb55952, + 0xffb55952, 0xffb55952, 0xffb55952, 0xffb55d52, 0xffb55d52, 0xffb55d52, 0xffb55d52, 0xffb55d5a, + 0xffb55d5a, 0xffb55d5a, 0xffb55d5a, 0xffb5615a, 0xffb5615a, 0xffb5615a, 0xffb5615a, 0xffbd655a, + 0xffbd655a, 0xffbd655a, 0xffbd655a, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, + 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffad716b, 0xffad716b, 0xffad716b, 0xffad716b, 0xffb5716b, + 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5756b, + 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb57573, + 0xffb57573, 0xffb57573, 0xffb57573, 0xffad7b73, 0xffad7b73, 0xffad7b73, 0xffad655a, 0xff7e6463, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00100400, 0xff7e6563, 0xff7e6563, 0xff7e6563, 0xffad655a, + 0xffad655a, 0xffad7b73, 0xffad7b73, 0xffb57573, 0xffb57573, 0xffb57573, 0xffb57573, 0xffb5756b, + 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5716b, + 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffad716b, + 0xffad716b, 0xffad716b, 0xffad716b, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, + 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffad7c76, 0xffad7c76, 0xffad7c76, 0xffad7c76, 0xffad7976, + 0xffad7976, 0xffad7976, 0xffad7976, 0xffad7770, 0xffad7770, 0xffad7770, 0xffad7770, 0xffad7870, + 0xffad7870, 0xffad7870, 0xffad7870, 0xffa77570, 0xffa77570, 0xffa77570, 0xffa77570, 0xffa7756b, + 0xffa7756b, 0xffa7756b, 0xffa7756b, 0xffa7736b, 0xffa7736b, 0xffa7736b, 0xffa7736b, 0xffa7706b, + 0xffa7706b, 0xffa7706b, 0xffa7706b, 0xffa27065, 0xffa27065, 0xffa27065, 0xffa27065, 0xffa26d65, + 0xffa26d65, 0xffa26d65, 0xffa26d65, 0xffa26d65, 0xffa26d65, 0xffa26d65, 0xffa26d65, 0xffa26b68, + 0xffa26b68, 0xffa26b68, 0xffa26b68, 0xffa26c68, 0xffa26c68, 0xffa26c68, 0xffa26c68, 0xff9c6963, + 0xff9c6963, 0xff9c6963, 0xff9c6963, 0xff9c6963, 0xff9c6963, 0xff9c6963, 0xff9c6963, 0xff9c6763, + 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6763, + 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6463, + 0xff9c6463, 0xff9c6463, 0xff9c6463, 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6763, + 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6763, 0xff9c6963, + 0xff9c6963, 0xff9c6963, 0xff9c6963, 0xff9c6963, 0xff9c6963, 0xff9c6963, 0xff9c6963, 0xffa26c68, + 0xffa26c68, 0xffa26c68, 0xffa26c68, 0xffa26b68, 0xffa26b68, 0xffa26b68, 0xffa26b68, 0xffa26d65, + 0xffa26d65, 0xffa26d65, 0xffa26d65, 0xffa26d65, 0xffa26d65, 0xffa26d65, 0xffa26d65, 0xffa7706b, + 0xffa7706b, 0xffa7706b, 0xffa7706b, 0xffa7736b, 0xffa7736b, 0xffa7736b, 0xffa7736b, 0xffa7736b, + 0xffa7736b, 0xffa7736b, 0xffa7736b, 0xffa77570, 0xffa77570, 0xffa77570, 0xffa77570, 0xffad7570, + 0xffad7570, 0xffad7570, 0xffad7570, 0xffad7870, 0xffad7870, 0xffad7870, 0xffad7870, 0xffad7776, + 0xffad7776, 0xffad7776, 0xffad7776, 0xffad7976, 0xffad7976, 0xffad7976, 0xffad7976, 0xffaf7c76, + 0xffaf7c76, 0xffaf7c76, 0xffaf7c76, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, + 0xffad6d6b, 0xffad6d6b, 0xffad6d6b, 0xffad716b, 0xffad716b, 0xffad716b, 0xffad716b, 0xffb5716b, + 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5716b, 0xffb5756b, + 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb5756b, 0xffb57573, + 0xffb57573, 0xffb57573, 0xffb57573, 0xffad7b73, 0xffad7b73, 0xffad655a, 0xffad655a, 0xff7e6463, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00100400, 0xff7e6563, 0xffb59694, 0xffb59694, 0xffada6a5, + 0xffada6a5, 0xffada6a5, 0xffada6a5, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, + 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, + 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, + 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, + 0xffadaead, 0xffadaead, 0xffadaead, 0xff9caaad, 0xff9caaad, 0xff9caaad, 0xff9caaad, 0xff9caaad, + 0xff9caaad, 0xff9caaad, 0xff9caaad, 0xff9caaad, 0xff9caaad, 0xff9caaad, 0xff9caaad, 0xff9caead, + 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, + 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, + 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, + 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caeb5, + 0xff9caeb5, 0xff9caeb5, 0xff9caeb5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, + 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, + 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, + 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, + 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, + 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, + 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, + 0xff9cb2b5, 0xff9cb2b5, 0xff9cb2b5, 0xff9caeb5, 0xff9caeb5, 0xff9caeb5, 0xff9caeb5, 0xff9caead, + 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, + 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, + 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, + 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caaad, + 0xff9caaad, 0xff9caaad, 0xff9caaad, 0xff9caaad, 0xff9caaad, 0xff9caaad, 0xff9caaad, 0xff94aaad, + 0xff94aaad, 0xff94aaad, 0xff94aaad, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, + 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, + 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, + 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, 0xffadaead, + 0xffadaead, 0xffadaead, 0xffadaead, 0xffada6a5, 0xffada6a5, 0xffada6a5, 0xffada6a5, 0xffbd9694, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff737473, 0xffadaead, 0xffadaead, 0xffd6d2d6, + 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffb5b6b5, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, + 0x11000000, 0x22000000, 0x22000000, 0x33000000, 0x44000000, 0x55000000, 0x44000000, 0x33000000, + 0x33000000, 0x22000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x22000000, 0x55000000, 0x88000000, 0xbb000000, + 0xdd0e0403, 0xdd0e0403, 0xee100503, 0xee100503, 0xff100503, 0xff100503, 0xff100503, 0xee100503, + 0xee100503, 0xee100503, 0xdd0e0403, 0xaa000000, 0x77000000, 0x44000000, 0x22000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff737573, 0xffa5a6a5, 0xffa5a6a5, 0xffa5a6a5, + 0xffa5a6a5, 0xffadaaad, 0xffadaaad, 0xffadaaad, 0xffadaaad, 0xffadaaad, 0xffadaaad, 0xffadaaad, + 0xffadaaad, 0xffadaaad, 0xffadaaad, 0xffadaaad, 0xffadaaad, 0xffa5a6a5, 0xffa5a6a5, 0xffa5a6a5, + 0xffa5a6a5, 0xff737173, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11000000, 0x33000000, 0x880e0403, 0xcc0e0403, 0xee0e0403, 0xff1b0805, 0xff1b0805, 0xff1b0805, + 0xff1b0805, 0xff1b0805, 0xff210b05, 0xff210b05, 0xff210b05, 0xff210b05, 0xff210b05, 0xff210b05, + 0xff210b05, 0xff210b05, 0xff1b0805, 0xff1b0805, 0xff1b0805, 0xee1b0805, 0xdd0b0403, 0x880b0403, + 0x44000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffadaaad, 0xffdbbeb8, 0xffe9dfdb, 0xffe9dfdb, + 0xffe9dfdb, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, + 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6dbd6, 0xffe6dbd6, 0xffe6dbd6, + 0xffe6dbd6, 0xffa5a6a5, 0x00000000, 0x00000000, 0x00000000, 0x00080000, 0x00080000, 0x11080000, + 0x11080000, 0x22210400, 0x22210400, 0x33210400, 0x33210400, 0x33210400, 0x33210400, 0x33210400, + 0x22210400, 0x11100400, 0x11100400, 0x00100400, 0x00100400, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22000000, 0x66080303, + 0xaa100505, 0xee190808, 0xff1b0805, 0xff1b0805, 0xff290c08, 0xff290c08, 0xff290c08, 0xff290c08, + 0xff290c08, 0xff290c08, 0xff311008, 0xff311008, 0xff311008, 0xff311008, 0xff311008, 0xff311008, + 0xff210b05, 0xff311008, 0xff290c08, 0xff290c08, 0xff290c08, 0xff290c08, 0xff210c08, 0xff210c08, + 0xee160805, 0xaa0b0403, 0x55000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11030303, 0x22030303, 0x22080808, 0x330b0b0b, 0x44101010, 0x33101010, 0x330b0b0b, 0x33080808, + 0x22050505, 0x11030303, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffadaaad, 0xffe9dfdb, 0xfff7ffff, 0xffce9e94, + 0xffce9e94, 0xffd6a294, 0xffd6a294, 0xffd6a294, 0xffd6a294, 0xffce9e94, 0xffce9e94, 0xffce9e94, + 0xffce9e94, 0xffce968c, 0xffce968c, 0xffce968c, 0xffce968c, 0xffc59284, 0xffc59284, 0xfff7ffff, + 0xffe6dbd6, 0xffa5a6a5, 0x00000000, 0x00000000, 0x00000000, 0x00080000, 0x11080000, 0x22080000, + 0x33080000, 0x66210400, 0x99210400, 0xaa210400, 0xbb210400, 0xbb210400, 0xbb210400, 0xaa210400, + 0x66210400, 0x33100400, 0x22100400, 0x11100400, 0x00100400, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x66190705, 0xcc210808, 0xff340f0e, + 0xff340f0e, 0xff340f0e, 0xff3a1010, 0xff3a1010, 0xff3a1010, 0xff3a1010, 0xff3a1010, 0xff4a1613, + 0xff4a1613, 0xff3a1010, 0xff421410, 0xff421410, 0xff421410, 0xff421410, 0xff3a1010, 0xff471613, + 0xff3a1010, 0xff3a1010, 0xff311010, 0xff311010, 0xff311010, 0xff311010, 0xff37100b, 0xff37100b, + 0xff290c08, 0xff290c08, 0xee160705, 0xaa160705, 0x33000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00080808, 0x00080808, 0x11080808, 0x55503a37, 0x886b494a, + 0xbb8c6160, 0xddad7976, 0xeead7976, 0xffa57479, 0xffa57479, 0xeea57479, 0xdd9c6163, 0xcc794542, + 0x99794542, 0x663c2421, 0x22000400, 0x11080400, 0x11080400, 0x00080400, 0x00080400, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffadaaad, 0xffe9dfdb, 0xffce9e94, 0xffce9e94, + 0xffce9e94, 0xffd6a294, 0xffd6a294, 0xffd6a294, 0xffd6a294, 0xffce9e94, 0xffce9e94, 0xffce9e94, + 0xffce9e94, 0xffce968c, 0xffce968c, 0xffce968c, 0xffce968c, 0xffc59284, 0xffc59284, 0xffc59284, + 0xffe6dbd6, 0xffa5a6a5, 0x00000000, 0x00000000, 0x00000000, 0x11080000, 0x22080000, 0x44080000, + 0xaa080000, 0xdd55241b, 0xee894537, 0xee894537, 0xee894537, 0xee9f584d, 0xee9f584d, 0xee9f584d, + 0xdd9f584d, 0xbb100400, 0x55100400, 0x22100400, 0x11100400, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x22000000, 0x99190705, 0xee310d0b, 0xff340f0e, 0xff340f0e, + 0xff340f0e, 0xff471613, 0xff471613, 0xff471613, 0xff471613, 0xff471613, 0xff4a1613, 0xff5a1b16, + 0xff4a1613, 0xff5a1b16, 0xff501813, 0xff501813, 0xff501813, 0xff501813, 0xff551b16, 0xff471613, + 0xff471613, 0xff471613, 0xff421613, 0xff421613, 0xff421613, 0xff421613, 0xff37100b, 0xff37100b, + 0xff37100b, 0xff37100b, 0xff2c0d0b, 0xff2c0d0b, 0xcc160705, 0x44000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x33080808, 0x88503a37, 0xcc976c65, 0xffde9e94, 0xffce928c, + 0xffce928c, 0xffce928c, 0xffad7976, 0xffad878f, 0xffad878f, 0xffad878f, 0xffa57479, 0xffb56563, + 0xffb56563, 0xffb56563, 0xdd794542, 0x994a2019, 0x44080400, 0x11080400, 0x11080400, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffadaaad, 0xffe9dfdb, 0xffce9e94, 0xffce9e94, + 0xffce9e94, 0xffd6a294, 0xffd6a294, 0xffd6a294, 0xffd6a294, 0xffce9e94, 0xffce9e94, 0xffce9e94, + 0xffce9e94, 0xffce968c, 0xffce968c, 0xffce968c, 0xffce968c, 0xffc59284, 0xffc59284, 0xffc59284, + 0xffe6dbd6, 0xffa5a6a5, 0x00000000, 0x00000000, 0x00000000, 0x11080000, 0x33080000, 0xaa080000, + 0xee9c3d31, 0xee894537, 0xeebd6552, 0xeebd6552, 0xeebd6552, 0xee9f584d, 0xee9f584d, 0xee9f584d, + 0xeede8273, 0xeed6c2bd, 0xbb100400, 0x33100400, 0x11100400, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x66190705, 0xdd310d0b, 0xff4a1410, 0xff4a1410, 0xff471613, 0xff471613, + 0xff471613, 0xff471613, 0xff551b16, 0xff551b16, 0xff551b16, 0xff551b16, 0xff5a1b16, 0xff5a1b16, + 0xff6b2019, 0xff5a1b16, 0xff5d1c16, 0xff5d1c16, 0xff5d1c16, 0xff5d1c16, 0xff551b16, 0xff551b16, + 0xff551b16, 0xff551b16, 0xff521b16, 0xff421613, 0xff421613, 0xff421613, 0xff45140e, 0xff45140e, + 0xff45140e, 0xff45140e, 0xff421410, 0xff421410, 0xff2c0d0b, 0xdd160705, 0x77000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x22000000, 0x884d3634, 0xdd976c65, 0xffde9e94, 0xffde9e94, 0xffde9e94, 0xffce928c, + 0xffce928c, 0xffad7976, 0xffad7976, 0xffad878f, 0xffb59aa5, 0xffad878f, 0xffad878f, 0xffb56563, + 0xffb56563, 0xffb56563, 0xffb56563, 0xffce594a, 0xdd8c3d31, 0x994a2019, 0x44080400, 0x11000000, + 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00080408, 0xff979697, 0xffe6e3e6, 0xffce9a8c, 0xffce9a8c, + 0xffce9a8c, 0xffce9e94, 0xffce9e94, 0xffce9a8f, 0xffce9a8f, 0xffce9a94, 0xffce9a94, 0xffce9a94, + 0xffce9a94, 0xffce968c, 0xffc88f84, 0xffc88f84, 0xffc88f84, 0xffbd8273, 0xffbd8273, 0xffbd8273, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x00000000, 0x11000000, 0x22210400, 0x66210400, 0xdd210400, + 0xee945a52, 0xeea5615a, 0xeeaa6d68, 0xeeaa6d68, 0xeeaa6d68, 0xeead6563, 0xeead6563, 0xeeaf6c68, + 0xeeb57973, 0xeea7938f, 0xeeefdbd6, 0x77190400, 0x22190400, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x77190808, 0xee4a1410, 0xff4a1410, 0xff4a1410, 0xff4a1410, 0xff5a1c19, 0xff5a1c19, + 0xff5a1c19, 0xff5a1c19, 0xff632019, 0xff632019, 0xff632019, 0xff632019, 0xff6b2019, 0xff6b2019, + 0xff6b2019, 0xff6b2019, 0xff6b2019, 0xff6b2019, 0xff6b2019, 0xff6b2019, 0xff632019, 0xff632019, + 0xff632019, 0xff632019, 0xff632019, 0xff521b16, 0xff521b16, 0xff521b16, 0xff521810, 0xff521810, + 0xff521810, 0xff45140e, 0xff421410, 0xff421410, 0xff421410, 0xff421410, 0xee290c08, 0x66000000, + 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x554d3634, 0xbb9a6c68, 0xffe6a29c, 0xffde9e94, 0xffde9e94, 0xffde9e94, 0xffde9e94, 0xffce928c, + 0xffce928c, 0xffad7976, 0xffad7976, 0xffad878f, 0xffb59aa5, 0xffb59aa5, 0xffad878f, 0xffb56563, + 0xffb56563, 0xffb56563, 0xffb56563, 0xffce594a, 0xffce594a, 0xffce594a, 0xcc8c3d31, 0x77311010, + 0x22000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00080408, 0xff979697, 0xffe6e3e6, 0xffce9a8c, 0xffce9a8c, + 0xffce9a8c, 0xffce9a8f, 0xffce9a8f, 0xffce9a8f, 0xffce9689, 0xffce9a94, 0xffdebab8, 0xffdebab8, + 0xffce9a94, 0xffc88f84, 0xffc88f84, 0xffc88f84, 0xffc3887b, 0xffbd8273, 0xffbd8273, 0xffbd8273, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x00000000, 0x11000000, 0x33210400, 0x99210400, 0xee945a52, + 0xee945a52, 0xeeaa6d68, 0xeeaf7976, 0xeeaf7976, 0xeeaf7976, 0xeeaf6c68, 0xeeaf6c68, 0xeeaf6c68, + 0xeeb2736e, 0xeea7938f, 0xeeefdbd6, 0xaa190400, 0x33190400, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00080000, 0x00080000, + 0x662c0c08, 0xee501810, 0xff521819, 0xff521819, 0xff521819, 0xff631e1b, 0xff631c19, 0xff631c19, + 0xff6e221b, 0xff6e221b, 0xff6b2019, 0xff76241b, 0xff76241b, 0xff76241b, 0xff732421, 0xff732421, + 0xff732421, 0xff732421, 0xff732421, 0xff732421, 0xff732421, 0xff732421, 0xff76241b, 0xff6b2019, + 0xff6b2019, 0xff6b2019, 0xff65201b, 0xff65201b, 0xff65201b, 0xff5a1c19, 0xff581c16, 0xff581c16, + 0xff581c16, 0xff4a1810, 0xff4d1813, 0xff4d1813, 0xff4d1813, 0xff421410, 0xff34120b, 0xdd1e0b05, + 0x55080400, 0x11080400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x775a413a, + 0xddb27f76, 0xffde9e94, 0xffde9e94, 0xffde9e94, 0xffde9e94, 0xffde9e94, 0xffdb9a91, 0xffd68e8c, + 0xffc07f7e, 0xffaa7070, 0xffaa7070, 0xffaa8e97, 0xffb8a2aa, 0xffb8a2aa, 0xffaa8e97, 0xff94696b, + 0xff9c5e5d, 0xff9c5e5d, 0xffa55450, 0xffbd5142, 0xffbd5142, 0xffbd493c, 0xffbd493c, 0xeeb53929, + 0x9942160e, 0x33080400, 0x11080400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00080408, 0xff979697, 0xffe6e3e6, 0xffce9a8c, 0xffce9a8c, + 0xffce9a8c, 0xffce9689, 0xffce9689, 0xffce9689, 0xffce9284, 0xffce9a94, 0xfffffbff, 0xfffffbff, + 0xffce9a94, 0xffc88f84, 0xffc3887b, 0xffc3887b, 0xffc3887b, 0xffbd8273, 0xffbd8273, 0xffbd8273, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x00000000, 0x11000000, 0x44210400, 0xbb210400, 0xee945a52, + 0xeece867b, 0xeeaf7976, 0xeeaf7976, 0xeeaf7976, 0xeeaf7976, 0xeeb2736e, 0xeeb2736e, 0xeeaf6c68, + 0xeeb2736e, 0xeea7938f, 0xeeefdbd6, 0xcc604c47, 0x44190400, 0x22000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00080000, 0x55080000, + 0xee501810, 0xff501810, 0xff631e1b, 0xff631e1b, 0xff631e1b, 0xff73231e, 0xff6e221b, 0xff6e221b, + 0xff79271e, 0xff6e221b, 0xff76241b, 0xff76241b, 0xff76241b, 0xff81281e, 0xff792721, 0xff792721, + 0xff792721, 0xff792721, 0xff7b2721, 0xff7b2721, 0xff7b2721, 0xff7b2721, 0xff76241b, 0xff76241b, + 0xff76241b, 0xff76241b, 0xff70241e, 0xff70241e, 0xff70241e, 0xff65201b, 0xff65201b, 0xff65201b, + 0xff581c16, 0xff581c16, 0xff4d1813, 0xff4d1813, 0xff4d1813, 0xff4d1813, 0xff4a1810, 0xff34120b, + 0xcc1e0b05, 0x44080400, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x7745312f, 0xeede9e94, + 0xffde9e94, 0xffde9e94, 0xffde9e94, 0xffde9e94, 0xffde9e94, 0xffdb9a91, 0xffd9968f, 0xffd68e8c, + 0xffc07f7e, 0xffaa7070, 0xffaa7070, 0xffaa8e97, 0xffb8a2aa, 0xffb8a2aa, 0xffaa8e97, 0xff9c5e5d, + 0xffa55450, 0xffa55450, 0xffa55450, 0xffbd5142, 0xffbd493c, 0xffbd493c, 0xffbd4137, 0xffb53929, + 0xeeb53929, 0x9942160e, 0x33080400, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00080408, 0xff979697, 0xffe6e3e6, 0xffce9a8c, 0xffce9a8c, + 0xffce9a8c, 0xffce9689, 0xffce9284, 0xffce9284, 0xffce9284, 0xffdebab8, 0xfffffbff, 0xfffffbff, + 0xffefdbdb, 0xffc3887b, 0xffc3887b, 0xffc3887b, 0xffbd8273, 0xffbd8273, 0xffbd8273, 0xffbd8273, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x22000000, 0x55210400, 0xcc210400, 0xeece867b, + 0xeece867b, 0xeeb58684, 0xeeb58684, 0xeeb58684, 0xeeaf7976, 0xeeb57973, 0xeeb57973, 0xeeb2736e, + 0xeeb57973, 0xeea7938f, 0xeea7938f, 0xdda7938f, 0x66190400, 0x22000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x33080000, 0xdd501810, + 0xff732419, 0xff732419, 0xff73231e, 0xff73231e, 0xff73231e, 0xff73231e, 0xff79271e, 0xff79271e, + 0xff79271e, 0xff79271e, 0xff81281e, 0xff81281e, 0xff81281e, 0xff81281e, 0xff7e2a21, 0xff7e2a21, + 0xff7e2a21, 0xff7e2a21, 0xff842a21, 0xff842a21, 0xff842a21, 0xff842a21, 0xff8c2d21, 0xff81281e, + 0xff81281e, 0xff81281e, 0xff7b2821, 0xff70241e, 0xff70241e, 0xff70241e, 0xff732421, 0xff65201b, + 0xff65201b, 0xff581c16, 0xff581c16, 0xff581c16, 0xff4d1813, 0xff4d1813, 0xff4a1810, 0xff4a1810, + 0xff34120b, 0x99080400, 0x22000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x7745312f, 0xeece928c, 0xffde9e94, + 0xffde9e94, 0xffde9e94, 0xffde9e94, 0xffde9e94, 0xffdb9a91, 0xffdb9a91, 0xffd9968f, 0xffd68e8c, + 0xffc07f7e, 0xffaa7070, 0xff946163, 0xff9c7984, 0xffc5b6bd, 0xffc5b6bd, 0xff9c7984, 0xffa55450, + 0xffa55450, 0xffa55450, 0xffad4942, 0xffbd493c, 0xffbd493c, 0xffbd4137, 0xffbd3931, 0xffb53929, + 0xffb53929, 0xeeb53929, 0x9942160e, 0x33000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffce9684, 0xffce9684, + 0xffce9684, 0xffce9284, 0xffce9284, 0xffce9284, 0xffce9284, 0xfffffbf7, 0xffffffff, 0xffffffff, + 0xfffffbf7, 0xffd3aaa2, 0xffbd8273, 0xffbd8273, 0xffbd8273, 0xffad796b, 0xffad796b, 0xffad796b, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x22000000, 0x66190000, 0xdd523331, 0xeec59a94, + 0xeec59a94, 0xeeb88e84, 0xeeb88e84, 0xeeb5867b, 0xeeb5867b, 0xeeaf7c73, 0xeead756b, 0xeead756b, + 0xeead756b, 0xee947168, 0xeecea69c, 0xeecea69c, 0x77210800, 0x22000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0xaa2c0c08, 0xff732419, + 0xff732419, 0xff732419, 0xff73231e, 0xff73231e, 0xff842821, 0xff842821, 0xff79271e, 0xff842d21, + 0xff842d21, 0xff842d21, 0xff8c2d21, 0xff8c2d21, 0xff8c2d21, 0xff8c2d21, 0xff842d21, 0xff842d21, + 0xff842d21, 0xff842d21, 0xff8c2d21, 0xff8c2d21, 0xff8c2d21, 0xff8c2d21, 0xff8c2d21, 0xff8c2d21, + 0xff8c2d21, 0xff81281e, 0xff7b2821, 0xff7b2821, 0xff7b2821, 0xff7b2821, 0xff732421, 0xff732421, + 0xff732421, 0xff65201b, 0xff632019, 0xff581c16, 0xff581c16, 0xff581c16, 0xff4a1810, 0xff4a1810, + 0xff34120b, 0xee1e0b05, 0x66000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5545312f, 0xddce928c, 0xffce928c, 0xffde9e94, + 0xffde9e94, 0xffde9e94, 0xffde9e94, 0xffdb9a91, 0xffdb9a91, 0xffd9968f, 0xffd6928c, 0xffd68e8c, + 0xffc07f7e, 0xffaa7070, 0xff946163, 0xff9c7984, 0xffc5b6bd, 0xffc5b6bd, 0xff9c7984, 0xffa55450, + 0xffad4942, 0xffad4942, 0xffad4942, 0xffbd493c, 0xffbd4137, 0xffbd3931, 0xffbd3931, 0xffb53929, + 0xffb53929, 0xffb53929, 0xee7b271b, 0x88290c08, 0x33000000, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffce9684, 0xffce9684, + 0xffce9684, 0xffce9284, 0xffce9284, 0xffce9284, 0xffefdbd6, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffe9d2d0, 0xffbd8273, 0xffbd8273, 0xffbd8273, 0xffad796b, 0xffad796b, 0xffad796b, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x22000000, 0x77190000, 0xdd523331, 0xeec59a94, + 0xeec59a94, 0xeeba968c, 0xeeb88e84, 0xeeb88e84, 0xeeb5867b, 0xeeb2837b, 0xeeaf7c73, 0xeead756b, + 0xeead756b, 0xee947168, 0xeecea69c, 0xeecea69c, 0x77210800, 0x22000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x44000000, 0xee6b2021, 0xff762421, + 0xff762421, 0xff762421, 0xff7b2421, 0xff862824, 0xff862824, 0xff912d26, 0xff943121, 0xff943121, + 0xff943121, 0xff943121, 0xff8c3129, 0xff8c3129, 0xff8c3129, 0xff8c3129, 0xff8c3529, 0xff8c3529, + 0xff8c3529, 0xff8c3529, 0xff8c3529, 0xff8c3529, 0xff8c3529, 0xff8c3529, 0xff8c3129, 0xff8c3129, + 0xff8c3129, 0xff8c3129, 0xff7b2d21, 0xff7b2d21, 0xff7b2d21, 0xff7b2d21, 0xff7b2d29, 0xff7b2d29, + 0xff7b2d29, 0xff7b2d29, 0xff6b2019, 0xff6b2019, 0xff6b2019, 0xff6b2019, 0xff581c16, 0xff4d1813, + 0xff4d1813, 0xff421410, 0xaa000000, 0x33000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x22191419, 0xbb976865, 0xffd6928c, 0xffd6928c, 0xffde9694, + 0xffde9694, 0xffde9694, 0xffde9694, 0xffde9694, 0xffde9694, 0xffdb908c, 0xffdb908c, 0xffd68a7b, + 0xffbd776b, 0xffa5645a, 0xff8c514a, 0xff9a7484, 0xffd6cad6, 0xffd6cad6, 0xff9a7484, 0xffad4942, + 0xffa2423a, 0xffad4942, 0xffad4942, 0xffc54131, 0xffbd3d2f, 0xffb5392c, 0xffb5392c, 0xffaa352c, + 0xffaa352c, 0xffaa352c, 0xff9f3126, 0xdd652216, 0x55080400, 0x22080400, 0x11080400, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffce9684, 0xffce9684, + 0xffce9684, 0xffce9284, 0xffce9284, 0xffdeb6ad, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xfffffbff, 0xffd3aaa2, 0xffbd8273, 0xffbd8273, 0xffad796b, 0xffad796b, 0xffad796b, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x22000000, 0x77190000, 0xee8c6763, 0xeec59a94, + 0xeec59a94, 0xeebd9e94, 0xeeba968c, 0xeeb88e84, 0xeeb88e84, 0xeeb2837b, 0xeeb2837b, 0xeeaf7c73, + 0xeead756b, 0xee947168, 0xeecea69c, 0xeecea69c, 0x88210800, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0xaa31100e, 0xff812821, 0xff812821, + 0xff762421, 0xff812821, 0xff862824, 0xff862824, 0xff912d26, 0xff912d26, 0xff943121, 0xff9a746e, + 0xff9c9694, 0xff9c9694, 0xff978481, 0xff978481, 0xff978481, 0xff978481, 0xffa29391, 0xffa29391, + 0xffa29391, 0xffa29391, 0xffa29391, 0xffa29391, 0xffa29391, 0xffa29391, 0xffa29291, 0xffa29291, + 0xffa29291, 0xffa29291, 0xffb2aeaa, 0xffb2aeaa, 0xffb2aeaa, 0xffb2aeaa, 0xffceb6b2, 0xfff7fbf7, + 0xfff7fbf7, 0xfff7fbf7, 0xffbd9694, 0xff6b2019, 0xff6b2019, 0xff6b2019, 0xff581c16, 0xff581c16, + 0xff4d1813, 0xff4d1813, 0xee2c0d0b, 0x66000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x88583e3f, 0xffd6928c, 0xffd6928c, 0xffd6928c, 0xffdb928f, + 0xffdb928f, 0xffdb928f, 0xffdb928f, 0xffdb908c, 0xffdb908c, 0xffdb908c, 0xffdb908c, 0xffd68a7b, + 0xffbd776b, 0xffa5645a, 0xff8c514a, 0xff9a7484, 0xffd6cad6, 0xffd6cad6, 0xff9a7484, 0xff973b31, + 0xffa2423a, 0xffa2423a, 0xffa2423a, 0xffbd3d2f, 0xffb5392c, 0xffb5392c, 0xffad3529, 0xffaa352c, + 0xffaa352c, 0xff9f3126, 0xff9f3126, 0xff943121, 0xaa37130b, 0x44080400, 0x11080400, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffce9684, 0xffce9684, + 0xffce9684, 0xffce9284, 0xffce9284, 0xffefdbd6, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xfffffbff, 0xfffffbff, 0xffbd8273, 0xffbd8273, 0xffad796b, 0xffad796b, 0xffad796b, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x22000000, 0x88190000, 0xee8c6763, 0xeec59a94, + 0xeec59a94, 0xeebd9e94, 0xeeba968c, 0xeeba968c, 0xeeb88e84, 0xeeb58a84, 0xeeb2837b, 0xeeaf7c73, + 0xeead756b, 0xee947168, 0xeecea69c, 0xeecea69c, 0x99210800, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x33000000, 0xee63201b, 0xff812821, 0xff812821, + 0xff812821, 0xff8c2d21, 0xff912d26, 0xff912d26, 0xff912d26, 0xff912d26, 0xff943121, 0xff943121, + 0xff9c9694, 0xff9c9694, 0xff978481, 0xff978481, 0xff978481, 0xff9caead, 0xffa29391, 0xffa29391, + 0xffa29391, 0xffa29391, 0xffa29391, 0xffa29391, 0xffa29391, 0xffa29391, 0xffa29291, 0xffa29291, + 0xffa29291, 0xffa29291, 0xffb2aeaa, 0xffb2aeaa, 0xffb2aeaa, 0xffb2aeaa, 0xfff7fbf7, 0xfff7fbf7, + 0xfff7fbf7, 0xfff7fbf7, 0xff864842, 0xff6b2019, 0xff6b2019, 0xff6b2019, 0xff581c16, 0xff581c16, + 0xff581c16, 0xff4d1813, 0xff421410, 0x99000000, 0x33000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x33211413, 0xdd976865, 0xffd6928c, 0xffd6928c, 0xffd6928c, 0xffd98e89, + 0xffd98e89, 0xffd98e89, 0xffd98e89, 0xffdb908c, 0xffdb908c, 0xffd98b84, 0xffd98b84, 0xffd68a7b, + 0xffbd776b, 0xffa5645a, 0xff8c514a, 0xff7b495a, 0xffd6cad6, 0xffd6cad6, 0xff7b495a, 0xff8c3529, + 0xff973b31, 0xff973b31, 0xff973b31, 0xffb5392c, 0xffb5392c, 0xffad3529, 0xffad3529, 0xffaa352c, + 0xff9f3126, 0xff9f3126, 0xff9f3126, 0xff943121, 0xee652216, 0x77080400, 0x33080400, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffc58a7b, 0xffc58a7b, + 0xffc58a7b, 0xffbd8273, 0xffe9d0cb, 0xfffff7f7, 0xfffff7f7, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xfff7f3f7, 0xfff7f3f7, 0xffdec9c8, 0xffad756b, 0xffa57163, 0xffa57163, 0xffa57163, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x22000000, 0x88190000, 0xee977779, 0xeed6b2b5, + 0xeed6b2b5, 0xeec3a39f, 0xeec09d9a, 0xeebd9694, 0xeebd9694, 0xeeb58b84, 0xeeb5847b, 0xeeb57d73, + 0xeeb57d73, 0xee9a6f68, 0xeecea29c, 0xeecea29c, 0x99310800, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00080408, 0xff4a464a, 0xff8c888c, 0xff8c888c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff949294, 0xff949294, 0xff9c9a9c, 0xff9c9a9c, + 0xff9c9a9c, 0xff9c9a9c, 0xff9c9a9c, 0xff9c9a9c, 0xff9c9a9c, 0xff9c9a9c, 0xff9c9a9c, 0xff9c9a9c, + 0xff9c9a9c, 0xff9c9a9c, 0xff9c9a9c, 0xff949694, 0xff949694, 0xff949694, 0xff949694, 0xff949694, + 0xff949694, 0xff949694, 0xff949694, 0xff949694, 0xff949694, 0xff949694, 0xff949694, 0xff949694, + 0xff949694, 0xff949694, 0xff949694, 0xff949694, 0xff949694, 0xff949694, 0xff949694, 0xff949294, + 0xff949294, 0xff949294, 0xff949294, 0xff949294, 0xff949294, 0xff949294, 0xff949294, 0xff949294, + 0xff949294, 0xff949294, 0xff949294, 0xff949294, 0xff949294, 0xff949294, 0xff949294, 0xff948e94, + 0xff948e94, 0xff948e94, 0xff948e94, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, + 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff8c8e8c, 0xff949694, + 0xff949694, 0xff949694, 0xff737573, 0xff5d5c5d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x7731100e, 0xff943129, 0xff8c2d21, 0xff8c2d21, + 0xff8c2d21, 0xff8c2d21, 0xff912d26, 0xff9c3129, 0xff9c3129, 0xff9c3129, 0xff943121, 0xff943121, + 0xff9a746e, 0xff9c9694, 0xff9caead, 0xff9caead, 0xff9caead, 0xff9caead, 0xffadc2c5, 0xffadc2c5, + 0xffadc2c5, 0xffadc2c5, 0xffadc2c5, 0xffadc2c5, 0xffadc2c5, 0xffadc2c5, 0xffadc2c5, 0xffadc2c5, + 0xffadc2c5, 0xffadc2c5, 0xffb2aeaa, 0xffb2aeaa, 0xffceefef, 0xffceefef, 0xfff7fbf7, 0xfff7fbf7, + 0xfff7fbf7, 0xffa5716e, 0xff6b2019, 0xff6b2019, 0xff6b2019, 0xff6b2019, 0xff632019, 0xff581c16, + 0xff581c16, 0xff4d1813, 0xff421410, 0xcc160705, 0x44000000, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x88633d3a, 0xffd6928c, 0xffd6928c, 0xffd6928c, 0xffd6928c, 0xffd98e89, + 0xffd98e89, 0xffd98e89, 0xffd68a84, 0xffd98b84, 0xffd98b84, 0xffd6867b, 0xffd6867b, 0xffbd776b, + 0xffbd776b, 0xffa5645a, 0xff8c514a, 0xff7b495a, 0xffd6cad6, 0xffd6cad6, 0xff7b495a, 0xff8c3529, + 0xff8c3529, 0xff8c3529, 0xff973b31, 0xffb5392c, 0xffad3529, 0xffad3529, 0xffad3529, 0xff9f3126, + 0xff9f3126, 0xff942d21, 0xff942d21, 0xff943121, 0xff943121, 0xbb37130b, 0x44080400, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffc58a7b, 0xffc58a7b, + 0xffc58a7b, 0xffbd8273, 0xffe9d0cb, 0xfffff7f7, 0xfffff7f7, 0xffe6d2ce, 0xffe6d2ce, 0xffe6d2ce, + 0xffe6d2ce, 0xfff7f3f7, 0xfff7f3f7, 0xffdec9c8, 0xffad756b, 0xffa57163, 0xffa57163, 0xffa57163, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x33000000, 0x88190000, 0xee977779, 0xeed6b2b5, + 0xeed6b2b5, 0xeec5aaa5, 0xeec3a39f, 0xeebd9694, 0xeebd9694, 0xeeb58b84, 0xeeb5847b, 0xeeb5847b, + 0xeeb57d73, 0xee9a6f68, 0xeecea29c, 0xeecea29c, 0x99310800, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00080408, 0xff8c888c, 0xff8c888c, 0xffcecace, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, + 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, + 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffc0c0c0, 0xffc0c0c0, 0xffced0ce, 0xffcecdce, + 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcecdce, + 0xffcecdce, 0xffcecdce, 0xffcecdce, 0xffcbc9cb, 0xffcbc9cb, 0xffcbc9cb, 0xffcbc9cb, 0xffc5c9c5, + 0xffc5c9c5, 0xffc5c9c5, 0xffc5c9c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, + 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c5c5, + 0xffc5c5c5, 0xffc5c5c5, 0xffc5c5c5, 0xffc5c2c5, 0xffc5c2c5, 0xffc5c2c5, 0xffc5c2c5, 0xffc5c2c5, + 0xffc5c2c5, 0xffc5c2c5, 0xffc5c2c5, 0xffc0c2c0, 0xffc0c2c0, 0xffc0c2c0, 0xffc0c2c0, 0xffc0bec0, + 0xffc0bec0, 0xffc0bec0, 0xffc0bec0, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, + 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xffb5b6b5, + 0xffb5b6b5, 0xffb5b6b5, 0xffb5b6b5, 0xff8c8a8c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000400, 0x00000000, 0x11000000, 0xaa31100e, 0xff943129, 0xff8c2d21, 0xff8c2d21, + 0xff912f24, 0xff912f24, 0xff9c3129, 0xff9c3129, 0xffa23329, 0xffa23329, 0xffad3929, 0xffad3929, + 0xffad3929, 0xffb59a9c, 0xffc8b5b5, 0xffc8b5b5, 0xffc8b5b5, 0xffc8b5b5, 0xffd6d2d6, 0xffd6d2d6, + 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, + 0xffd6d2d6, 0xffd6d2d6, 0xffdee3de, 0xffe9ece9, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffdbb9b5, 0xff942d21, 0xff812821, 0xff812821, 0xff762421, 0xff6b2021, 0xff682019, 0xff682019, + 0xff5d1c19, 0xff521819, 0xff4a1810, 0xdd190805, 0x66000000, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0xcc8f514d, 0xffd6867b, 0xffd6867b, 0xffd6867b, 0xffd6867b, 0xffd6827b, + 0xffd6827b, 0xffd6827b, 0xffd6827b, 0xffd6867b, 0xffd6867b, 0xffd6867b, 0xffd07970, 0xffce7573, + 0xffce7573, 0xffb25e5a, 0xff974842, 0xff632d3a, 0xffefefef, 0xffefefef, 0xff632d3a, 0xff862b1e, + 0xff9a3224, 0xff9a3224, 0xffad3929, 0xffad3529, 0xffad3529, 0xff9c3126, 0xff9c3126, 0xff943121, + 0xff892d21, 0xff892d21, 0xff892d21, 0xff7b2821, 0xff7b2821, 0xdd551b16, 0x66080000, 0x22000000, + 0x11000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffc58a7b, 0xffc58a7b, + 0xffc58a7b, 0xffbd8273, 0xffbd8273, 0xffbd8273, 0xffbd8273, 0xffb5796b, 0xffb5796b, 0xffb5796b, + 0xffb5796b, 0xffad756b, 0xffad756b, 0xffad756b, 0xffad756b, 0xffa57163, 0xffa57163, 0xffa57163, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x33000000, 0x99190000, 0xee977779, 0xeed6b2b5, + 0xeed6b2b5, 0xeec5aaa5, 0xeec3a39f, 0xeec09d9a, 0xeebd9694, 0xeeb58b84, 0xeeb58b84, 0xeeb5847b, + 0xeeb57d73, 0xee9a6f68, 0xeecea29c, 0xeecea29c, 0xaa310800, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00080408, 0xff8c888c, 0xffcecace, 0xffcecace, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffe6ebe6, 0xffe6e7e6, + 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, + 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffdee3de, + 0xffdee3de, 0xffdee3de, 0xffdee3de, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, + 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, + 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffb5b6b5, 0xff8c8a8c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000400, 0x00000000, 0x22000000, 0xdd63201b, 0xff943129, 0xff912f24, 0xff912f24, + 0xff912f24, 0xff912f24, 0xffa23329, 0xffa23329, 0xffa23329, 0xffa73629, 0xffad3929, 0xffad3929, + 0xffad3929, 0xffaf5950, 0xffc8b5b5, 0xffc8b5b5, 0xffd6dbde, 0xffd6dbde, 0xffe1dfe1, 0xffe1dfe1, + 0xffecebec, 0xffecebec, 0xfff1f0f1, 0xfff1f0f1, 0xfff1f0f1, 0xfff1f0f1, 0xfff1f0f1, 0xfff1f0f1, + 0xfff1f0f1, 0xfff1f0f1, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffb8736b, 0xff942d21, 0xff8c2d21, 0xff812821, 0xff762421, 0xff762421, 0xff682019, 0xff682019, + 0xff5d1c19, 0xff521819, 0xff4a1810, 0xee31100b, 0x88000000, 0x22000000, 0x00000000, 0x00000000, + 0x00000000, 0x55472826, 0xffd67973, 0xffd37f76, 0xffd37f76, 0xffd37f76, 0xffd37f76, 0xffd6827b, + 0xffd6827b, 0xffd6827b, 0xffd6827b, 0xffd07970, 0xffd07970, 0xffd07970, 0xffd07970, 0xffce7573, + 0xffb25e5a, 0xff974842, 0xff974842, 0xff632d3a, 0xffefefef, 0xffefefef, 0xff632d3a, 0xff732419, + 0xff862b1e, 0xff9a3224, 0xff9a3224, 0xff9c3126, 0xff9c3126, 0xff9c3126, 0xff8c2d24, 0xff892d21, + 0xff892d21, 0xff7e2821, 0xff7e2821, 0xff7b2821, 0xff7b2821, 0xff7b2821, 0x992f0d0b, 0x33000000, + 0x11000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffc58a7b, 0xffc58a7b, + 0xffc58a7b, 0xffbd8273, 0xffbd8273, 0xffbd8273, 0xffbd8273, 0xffb5796b, 0xffb5796b, 0xffb5796b, + 0xffb5796b, 0xffad756b, 0xffad756b, 0xffad756b, 0xffad756b, 0xffa57163, 0xffa57163, 0xffa57163, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x33000000, 0x99190000, 0xee977779, 0xeed6b2b5, + 0xeed6b2b5, 0xeec5aaa5, 0xeec5aaa5, 0xeec09d9a, 0xeebd9694, 0xeeb5928c, 0xeeb58b84, 0xeeb5847b, + 0xeeb5847b, 0xee9a6f68, 0xeecea29c, 0xeecea29c, 0xaa310800, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00080408, 0xff8c888c, 0xffcecace, 0xffcecace, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffe6ebe6, 0xffe6e7e6, + 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, + 0xffe6e7e6, 0xffe6e7e6, 0xffe6e7e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffe6e3e6, 0xffdee3de, + 0xffdee3de, 0xffdee3de, 0xffdee3de, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, + 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedfde, + 0xffdedfde, 0xffdedfde, 0xffdedfde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffdedbde, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6dbd6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffb5b6b5, 0xff8c8a8c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000400, 0x00000000, 0x5531100e, 0xff943129, 0xff943129, 0xff912f24, 0xff912f24, + 0xff973226, 0xff973226, 0xffa23329, 0xffa23329, 0xffa73629, 0xffa73629, 0xffad3929, 0xffad3929, + 0xffad3929, 0xffad3929, 0xffba8f8c, 0xffd6dbde, 0xffd6dbde, 0xffd6dbde, 0xffecebec, 0xffecebec, + 0xfff7f7f7, 0xfff7f7f7, 0xfff1f0f1, 0xfff1f0f1, 0xfff1f0f1, 0xfff1f0f1, 0xfff1f0f1, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffdbb9b5, + 0xff942d21, 0xff942d21, 0xff8c2d21, 0xff812821, 0xff812821, 0xff762421, 0xff682019, 0xff682019, + 0xff682019, 0xff5d1c19, 0xff4a1810, 0xff4a1810, 0xaa000000, 0x33000000, 0x00000000, 0x00000000, + 0x00000000, 0x88472826, 0xffd67973, 0xffd07870, 0xffd07870, 0xffd07870, 0xffd07870, 0xffd37b73, + 0xffd37b73, 0xffd37b73, 0xffd0746b, 0xffd07970, 0xffcb6d65, 0xffcb6d65, 0xffcb6d65, 0xffb25e5a, + 0xffb25e5a, 0xff974842, 0xff7b3129, 0xff632d3a, 0xffefefef, 0xffefefef, 0xff632d3a, 0xff732419, + 0xff862b1e, 0xff9a3224, 0xff9a3224, 0xff9c3126, 0xff8c2d24, 0xff8c2d24, 0xff8c2d24, 0xff7e2821, + 0xff7e2821, 0xff7e2821, 0xff732421, 0xff7b2821, 0xff7b2821, 0xff7b2821, 0xbb2f0d0b, 0x44000000, + 0x22000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe9d5d0, 0xffbd8273, 0xffbd8273, + 0xffbd8273, 0xffad756b, 0xffad756b, 0xffad756b, 0xffad756b, 0xff9c6d63, 0xff9c6d63, 0xff9c6d63, + 0xff9c6d63, 0xff9c6963, 0xff9c6963, 0xff9c6963, 0xff9c6963, 0xff9c6d63, 0xff9c6d63, 0xff9c6d63, + 0xffdececb, 0xffadaaad, 0x00000000, 0x11000000, 0x33000000, 0x99190000, 0xee97827e, 0xeed6c2bd, + 0xeed6c2bd, 0xeec5b2b5, 0xeec3aaaa, 0xeec0a29f, 0xeebd9a94, 0xeeba8f86, 0xeeba8f86, 0xeeb88881, + 0xeeb5827b, 0xee976c6b, 0xeec59e9c, 0xeec59e9c, 0xaa3a0808, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0xff7e807e, 0xffbdbebd, 0xffbdbebd, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, + 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, + 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffd6d7d6, 0xffd6d7d6, + 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d7d6, 0xffd6d2d6, + 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffd6d2d6, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, + 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecece, 0xffcecace, + 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, 0xffcecace, + 0xffcecace, 0xffcecace, 0xffcecace, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, + 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, + 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffc5c6c5, 0xffbdbebd, + 0xffbdbebd, 0xffbdbebd, 0xffbdbebd, 0xff848284, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000400, 0x00000000, 0x7731100e, 0xff943129, 0xff943129, 0xff973226, 0xff973226, + 0xff973226, 0xff973226, 0xffa23329, 0xffa73629, 0xffa73629, 0xffa73629, 0xffad3929, 0xffad3929, + 0xffad3929, 0xffad3929, 0xffad6963, 0xffd6dbde, 0xffd6dbde, 0xffd6dbde, 0xffecebec, 0xfff7f7f7, + 0xfff7f7f7, 0xfff7f7f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff942d21, + 0xff942d21, 0xff942d21, 0xff8c2d21, 0xff8c2d21, 0xff812821, 0xff812821, 0xff732419, 0xff682019, + 0xff682019, 0xff5d1c19, 0xff4a1810, 0xff4a1810, 0xbb190805, 0x44000000, 0x11000000, 0x00000000, + 0x11000000, 0xaa8f514d, 0xffd67973, 0xffce716b, 0xffce716b, 0xffce716b, 0xffce716b, 0xffce6d63, + 0xffce6d63, 0xffce6d63, 0xffce6d63, 0xffcb6d65, 0xffcb6d65, 0xffc5615a, 0xffc5615a, 0xffb25e5a, + 0xff974842, 0xff974842, 0xff7b3129, 0xff632d3a, 0xffefefef, 0xffefefef, 0xff632d3a, 0xff732419, + 0xff732419, 0xff862b1e, 0xff862b1e, 0xff8c2d24, 0xff7b2821, 0xff7b2821, 0xff7b2821, 0xff732421, + 0xff732421, 0xff732421, 0xff732421, 0xff7b2821, 0xff7b2821, 0xff7b2821, 0xdd551b16, 0x55000000, + 0x22000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe9d5d0, 0xffbd8273, 0xffbd8273, + 0xffbd8273, 0xffad756b, 0xffad756b, 0xffad756b, 0xffad756b, 0xff9c6d63, 0xff9c6d63, 0xff9c6d63, + 0xff9c6d63, 0xff9c6963, 0xff9c6963, 0xff9c6963, 0xff9c6963, 0xff9c6d63, 0xff9c6d63, 0xff9c6d63, + 0xffdececb, 0xffadaaad, 0x00000000, 0x11000000, 0x33000000, 0x99190000, 0xee97827e, 0xeed6c2bd, + 0xeed6c2bd, 0xeec5b2b5, 0xeec3aaaa, 0xeec0a29f, 0xeebd9a94, 0xeebd968c, 0xeeba8f86, 0xeeb88881, + 0xeeb5827b, 0xee976c6b, 0xeec59e9c, 0xeec59e9c, 0xaa3a0808, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0xff3f423f, 0xff7e807e, 0xff7e807e, 0xff848484, 0xff848484, 0xff848484, 0xff848484, + 0xff848484, 0xff848484, 0xff848484, 0xff848484, 0xff848484, 0xff848484, 0xff848484, 0xff848484, + 0xff848484, 0xff848484, 0xff848484, 0xff848484, 0xff848484, 0xff848484, 0xff8f8f8f, 0xff8f8f8f, + 0xff8f8f8f, 0xff8f8f8f, 0xff8f8f8f, 0xff8f8f8f, 0xff8f8f8f, 0xff8f8f8f, 0xff8f8f8f, 0xff8f8e8f, + 0xff8f8e8f, 0xff8f8e8f, 0xff8f8e8f, 0xff8f8c8f, 0xff8f8c8f, 0xff8f8c8f, 0xff8f8c8f, 0xff898a89, + 0xff898a89, 0xff898a89, 0xff898a89, 0xff898a89, 0xff898a89, 0xff898a89, 0xff898a89, 0xff898a89, + 0xff898a89, 0xff898a89, 0xff898a89, 0xff898a89, 0xff898a89, 0xff898a89, 0xff898a89, 0xff898789, + 0xff898789, 0xff898789, 0xff898789, 0xff898789, 0xff898789, 0xff898789, 0xff898789, 0xff898789, + 0xff898789, 0xff898789, 0xff898789, 0xff848484, 0xff848484, 0xff848484, 0xff848484, 0xff848484, + 0xff848484, 0xff848484, 0xff848484, 0xff848484, 0xff848484, 0xff848484, 0xff848484, 0xff848484, + 0xff848484, 0xff848484, 0xff848484, 0xff848484, 0xff848484, 0xff848484, 0xff848484, 0xff7e7f7e, + 0xff7e7f7e, 0xff7e7f7e, 0xff7e7f7e, 0xff585658, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x8834120e, 0xff9c3529, 0xff9c3529, 0xff9f3229, 0xff9f3229, + 0xff9f3229, 0xffa53529, 0xffaa362f, 0xffaf372c, 0xffaf372c, 0xffaf372c, 0xffb53931, 0xffb53931, + 0xffb83a2f, 0xffb53931, 0xffb53d31, 0xffcba39f, 0xffd6d7d6, 0xffd6d7d6, 0xffe6e3e6, 0xffefefef, + 0xfff7fbf7, 0xfff7fbf7, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffd69e9c, 0xff9c3529, + 0xff9c3529, 0xff9c3529, 0xff942e21, 0xff8c2b21, 0xff8c2b21, 0xff842821, 0xff7b2421, 0xff651f1b, + 0xff651f1b, 0xff5a1c19, 0xff521810, 0xff521810, 0xcc1b0805, 0x55000000, 0x11000000, 0x00000000, + 0x11000000, 0xcc8f4c42, 0xffd67163, 0xffce6963, 0xffce6963, 0xffce6963, 0xffce6963, 0xffc5655a, + 0xffc5655a, 0xffc5655a, 0xffc5655a, 0xffc55952, 0xffc55952, 0xffc55952, 0xffc55952, 0xffbd493a, + 0xffbd493a, 0xff7e3126, 0xff7e3126, 0xff190808, 0xffffffff, 0xffffffff, 0xff190808, 0xff581b16, + 0xff842821, 0xff842821, 0xff842821, 0xff7b2821, 0xff7b2821, 0xff7b2821, 0xff7b2821, 0xff6b2019, + 0xff6b2019, 0xff6b2019, 0xff6b2019, 0xff6b2019, 0xff6b2019, 0xff6b2019, 0xee471610, 0x55000000, + 0x22000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe9d5d0, 0xffffffff, 0xffbd8273, + 0xffbd8273, 0xffad756b, 0xffad756b, 0xffad756b, 0xffad756b, 0xff9c6d63, 0xff9c6d63, 0xff9c6d63, + 0xff9c6d63, 0xff9c6963, 0xff9c6963, 0xff9c6963, 0xff9c6963, 0xff9c6d63, 0xff9c6d63, 0xffffffff, + 0xffdececb, 0xffadaaad, 0x00000000, 0x11000000, 0x33000000, 0x99190000, 0xee97827e, 0xeed6c2bd, + 0xeed6c2bd, 0xeec5b2b5, 0xeec3aaaa, 0xeec0a29f, 0xeebd9a94, 0xeebd968c, 0xeeba8f86, 0xeeb88881, + 0xeeb5827b, 0xee976c6b, 0xeec59e9c, 0xeec59e9c, 0xaa3a0808, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, + 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x9934120e, 0xff9c3529, 0xff9c3529, 0xff9f3229, 0xff9c3129, + 0xffa23329, 0xffa53529, 0xffaf372c, 0xffaf372c, 0xffb53929, 0xffb53929, 0xffb53931, 0xffb83a2f, + 0xffb53931, 0xffb83a2f, 0xffb53d31, 0xffb53d31, 0xffd6d7d6, 0xffd6d7d6, 0xffe6e3e6, 0xffefefef, + 0xffefefef, 0xfff7fbf7, 0xfffcfcfc, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff9c3529, 0xff9c3529, + 0xff9c3529, 0xff9c3529, 0xff942e21, 0xff942e21, 0xff8c2b21, 0xff842821, 0xff7b2421, 0xff70221e, + 0xff651f1b, 0xff5a1c19, 0xff521810, 0xff521810, 0xcc1b0805, 0x55000000, 0x11000000, 0x00000000, + 0x11000000, 0x22000000, 0x44000000, 0x66000000, 0x77000000, 0x77000000, 0x77000000, 0x77000000, + 0x77000000, 0x77000000, 0x77000000, 0x77000000, 0x77000000, 0x77000000, 0x77000000, 0x77000000, + 0x88000000, 0x99000000, 0xaa000000, 0xcc190808, 0xffffffff, 0xffffffff, 0xbb190808, 0xaa000000, + 0x99000000, 0x88000000, 0x77000000, 0x77000000, 0x77000000, 0x77000000, 0x77000000, 0x77000000, + 0x77000000, 0x77000000, 0x77000000, 0x77000000, 0x77000000, 0x77000000, 0x66000000, 0x44000000, + 0x22000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe9d5d0, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffdececb, 0xffadaaad, 0x00000000, 0x11000000, 0x33000000, 0x99190000, 0xee97827e, 0xeed6c2bd, + 0xeed6c2bd, 0xeec5b2b5, 0xeec3aaaa, 0xeec0a29f, 0xeebd9a94, 0xeebd968c, 0xeeba8f86, 0xeeb88881, + 0xeeb5827b, 0xee976c6b, 0xeec59e9c, 0xeec59e9c, 0xaa3a0808, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, + 0x00000400, 0x00000400, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xaa34120e, 0xff9c3529, 0xff9c3529, 0xff9f3229, 0xff9f3229, + 0xffa53529, 0xffa53529, 0xffaf372c, 0xffb53929, 0xffb53929, 0xffb53929, 0xffb83a2f, 0xffb83a2f, + 0xffb83a2f, 0xffb83a2f, 0xffb53d31, 0xffb53d31, 0xffc07068, 0xffd6d7d6, 0xffded7de, 0xffe6e3e6, + 0xffefefef, 0xffefefef, 0xfffafafa, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffc87d76, 0xff9c3529, 0xff9c3529, + 0xff9c3529, 0xff9c3529, 0xff942e21, 0xff942e21, 0xff8c2b21, 0xff842821, 0xff7b2421, 0xff70221e, + 0xff651f1b, 0xff651f1b, 0xff521810, 0xff521810, 0xdd1b0805, 0x66000000, 0x11000000, 0x00000000, + 0x00000000, 0x11000000, 0x22000000, 0x33000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, + 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, + 0x55000000, 0x66000000, 0x88000000, 0xaa190808, 0xffffffff, 0xffffffff, 0xaa190808, 0x88000000, + 0x66000000, 0x55000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, + 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x44000000, 0x33000000, 0x22000000, + 0x11000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x33000000, 0x99190000, 0xee9c827e, 0xeedec2bd, + 0xeedec2bd, 0xeec5b6b5, 0xeec3aead, 0xeec0a6a5, 0xeebd9e9c, 0xeebd9694, 0xeeba8f8c, 0xeeb88884, + 0xeeb5827b, 0xee9c6d6b, 0xeece9e9c, 0xeece9e9c, 0xaa3a0c08, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x11000000, 0xbb68231b, 0xff9c3529, 0xff9c3529, 0xffa53529, 0xffa53529, + 0xffa53529, 0xffa53529, 0xffb53929, 0xffb53929, 0xffb53929, 0xffb53929, 0xffb83a2f, 0xffb83a2f, + 0xffba3b2c, 0xffb83a2f, 0xffb53d31, 0xffb53d31, 0xffb53d31, 0xffcba39f, 0xffded7de, 0xffe6e3e6, + 0xffe6e3e6, 0xffefefef, 0xfff7f7f7, 0xfffcfcfc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe4beba, 0xffad3d31, 0xff9c3529, 0xff9c3529, + 0xff9c3529, 0xff9c3529, 0xff9c3121, 0xff942e21, 0xff8c2b21, 0xff842821, 0xff7b2421, 0xff70221e, + 0xff651f1b, 0xff651f1b, 0xff521810, 0xff521810, 0xdd1b0805, 0x66000000, 0x22000000, 0x00000000, + 0x00000000, 0x00000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x22000000, 0x44000000, 0x66000000, 0x99190808, 0xffffffff, 0xffffffff, 0x88190808, 0x66000000, + 0x44000000, 0x22000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x33000000, 0x99190000, 0xee9c827e, 0xeedec2bd, + 0xeedec2bd, 0xeec5b6b5, 0xeec3aead, 0xeec0a6a5, 0xeebd9e9c, 0xeebd9694, 0xeeba8f8c, 0xeeb88884, + 0xeeb5827b, 0xee9c6d6b, 0xeece9e9c, 0xeece9e9c, 0xaa3a0c08, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000400, 0x00000000, 0x9937120e, 0xffa53529, 0xffa53529, 0xffa53529, 0xffa53529, + 0xffa53529, 0xffaa3729, 0xffb53929, 0xffb53a2c, 0xffb53b2f, 0xffb53b2f, 0xffbd3b31, 0xffbd3b31, + 0xffbd3b31, 0xffbd3b31, 0xffbd3d31, 0xffbd3d31, 0xffbd3d31, 0xffbd6152, 0xffdedbde, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xfff7f7f7, 0xfff7f7f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffbff, 0xfffffbff, 0xffc87970, 0xffad3929, 0xffa53529, 0xffa53529, + 0xffa53529, 0xff9c3129, 0xff943129, 0xff8f2e26, 0xff892b24, 0xff842821, 0xff732421, 0xff6b221e, + 0xff631f1b, 0xff631f1b, 0xff521c10, 0xff37130b, 0xdd1b0905, 0x66000000, 0x22000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11000000, 0x33000000, 0x55000000, 0x88190808, 0xfffffbff, 0xfffffbff, 0x88190808, 0x55000000, + 0x33000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x33000000, 0x99190000, 0xee9c827e, 0xeedec2bd, + 0xeedec2bd, 0xeec5b6b5, 0xeec3aead, 0xeec0a6a5, 0xeebd9e9c, 0xeebd9694, 0xeeba8f8c, 0xeeb88884, + 0xeeb5827b, 0xee9c6d6b, 0xeece9e9c, 0xeece9e9c, 0xaa3a0c08, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000400, 0x00000000, 0x8837120e, 0xffa53529, 0xffa53529, 0xffa53529, 0xffa53529, + 0xffa73629, 0xffad3929, 0xffb53a2c, 0xffb53a2c, 0xffb53a2c, 0xffb53a2c, 0xffbd3b31, 0xffbd3b31, + 0xffbd3b31, 0xffbd3b31, 0xffbd3d31, 0xffbd3d31, 0xffbd3d31, 0xffbd3d31, 0xffd3a9a7, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffefefef, 0xfff7f7f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffbff, 0xffe4bab8, 0xffad3929, 0xffad3929, 0xffa53529, 0xffa53529, + 0xffa53529, 0xff9c3129, 0xff943129, 0xff8f2e26, 0xff892b24, 0xff842821, 0xff732421, 0xff6b221e, + 0xff631f1b, 0xff5a1c19, 0xff521c10, 0xff37130b, 0xcc1b0905, 0x66000000, 0x22000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11000000, 0x33000000, 0x55000000, 0x88190808, 0xfffffbff, 0xfffffbff, 0x88190808, 0x55000000, + 0x33000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x33000000, 0x99190000, 0xee9c827e, 0xeedec2bd, + 0xeedec2bd, 0xeec5b6b5, 0xeec3aead, 0xeec0a6a5, 0xeebd9e9c, 0xeebd9694, 0xeeba8f8c, 0xeeb88884, + 0xeeb5827b, 0xee9c6d6b, 0xeece9e9c, 0xeece9e9c, 0xaa3a0c08, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000400, 0x00000000, 0x7737120e, 0xffa53529, 0xffa53529, 0xffa73629, 0xffa73629, + 0xffa53529, 0xffad3929, 0xffb53929, 0xffb53a2c, 0xffb53a2c, 0xffb53b2f, 0xffbd3a31, 0xffbd3b31, + 0xffbd3b31, 0xffbd3b31, 0xffbd3d31, 0xffbd3d31, 0xffbd3d31, 0xffbd3d31, 0xffbd453a, 0xffdedbde, + 0xffdedbde, 0xffdedbde, 0xffefefef, 0xfff7f7f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffbff, 0xffad3929, 0xffad3929, 0xffad3929, 0xffa53529, 0xffa53529, + 0xffa53529, 0xff9f3229, 0xff943129, 0xff8f2e26, 0xff892b24, 0xff842821, 0xff732421, 0xff6b221e, + 0xff631f1b, 0xff5a1c19, 0xff521c10, 0xff37130b, 0xcc1b0905, 0x66000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x22000000, 0x44000000, 0x66000000, 0x99190808, 0xfffffbff, 0xfffffbff, 0x99190808, 0x66000000, + 0x44000000, 0x22000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x33000000, 0x99190000, 0xee977f79, 0xeed6beb5, + 0xeed6beb5, 0xeec5b2b5, 0xeec3abaa, 0xeec0a59f, 0xeebd9e94, 0xeebd968c, 0xeeba8f86, 0xeeb88881, + 0xeeb5827b, 0xee9a6d65, 0xeece9e94, 0xeece9e94, 0xaa310c08, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000400, 0x00000000, 0x6637120e, 0xffa53529, 0xffa53529, 0xffa53529, 0xffa53529, + 0xffa53529, 0xffaa3729, 0xffb53929, 0xffb53a2c, 0xffb53b2f, 0xffb53b2f, 0xffbd3b31, 0xffbd3b31, + 0xffbd3d31, 0xffbd3b31, 0xffbd3d31, 0xffbd3d31, 0xffbd3d31, 0xffbd3d31, 0xffbd453a, 0xffc87770, + 0xffdedbde, 0xffdedbde, 0xffe6e7e6, 0xfff7f7f7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffc87970, 0xffad3929, 0xffad3929, 0xffad3929, 0xffa53529, 0xffa53529, + 0xffa53529, 0xff9f3229, 0xff943129, 0xff8f2e26, 0xff892b24, 0xff842821, 0xff732421, 0xff6b221e, + 0xff631f1b, 0xff5a1c19, 0xff521c10, 0xff37130b, 0xbb000000, 0x55000000, 0x11000000, 0x00000000, + 0x00000000, 0x7745221e, 0xffce655a, 0xffc56152, 0xffc56152, 0xffc56152, 0xffc56152, 0xffc5594a, + 0xffc5594a, 0xffc5594a, 0xffc5594a, 0xffbd5142, 0xffbd5142, 0xffbd5142, 0xffbd5142, 0xffce4531, + 0xff892e21, 0xff892e21, 0xff892e21, 0xff190808, 0xfffffbff, 0xfffffbff, 0xff190808, 0xff581b16, + 0xff581b16, 0xff842821, 0xff842821, 0xff732419, 0xff732419, 0xff732419, 0xff732419, 0xff632019, + 0xff632019, 0xff632019, 0xff632019, 0xff632019, 0xff632019, 0xff632019, 0x88210b08, 0x22000000, + 0x11000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x33000000, 0x99190000, 0xee977f79, 0xeed6beb5, + 0xeed6beb5, 0xeec5b2b5, 0xeec3abaa, 0xeec0a59f, 0xeebd9e94, 0xeebd968c, 0xeeba8f86, 0xeeb88881, + 0xeeb5827b, 0xee9a6d65, 0xeece9e94, 0xeece9e94, 0xaa310c08, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00080000, 0x33080000, 0xee9c3529, 0xff9c3529, 0xffa53529, 0xffa53529, + 0xffa73629, 0xffad3929, 0xffaf392c, 0xffb2392f, 0xffb2392f, 0xffb2392f, 0xffba3b2f, 0xffba3b2f, + 0xffba3b2f, 0xffba3b2f, 0xffba3b31, 0xffb83a31, 0xffba3b31, 0xffba3b31, 0xffb53931, 0xffb53931, + 0xffcba7a5, 0xffd6dfde, 0xffe6e3e6, 0xfff7f6f7, 0xffffffff, 0xffffffff, 0xfffffbff, 0xfffffbff, + 0xfffffbff, 0xfffffbff, 0xffb53d31, 0xffaf372c, 0xffaf372c, 0xffaf372c, 0xffa53529, 0xffa23329, + 0xff9f3229, 0xff9c3129, 0xff943121, 0xff8c2d21, 0xff8c2d21, 0xff842821, 0xff732421, 0xff68201b, + 0xff5d1c16, 0xff5d1c16, 0xff4a1810, 0xff31100b, 0xaa000000, 0x44000000, 0x11000000, 0x00000000, + 0x00000000, 0x55451f1b, 0xffce5d52, 0xffc5594a, 0xffc5594a, 0xffc5594a, 0xffc5594a, 0xffc5554a, + 0xffc5554a, 0xffc04c3f, 0xffc04c3f, 0xffc5453a, 0xffc5453a, 0xffba3e34, 0xffba3e34, 0xffad3529, + 0xffad3529, 0xff76271e, 0xff5a2019, 0xff5a2d3a, 0xffe6e7e6, 0xffe6e7e6, 0xff5a2d3a, 0xff4a1819, + 0xff652019, 0xff652019, 0xff732419, 0xff632019, 0xff632019, 0xff632019, 0xff632019, 0xff632019, + 0xff5d1e16, 0xff5d1e16, 0xff5d1e16, 0xff5a1c19, 0xff5a1c19, 0xff5a1c19, 0x88240908, 0x33000000, + 0x11000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x33000000, 0x99190000, 0xee977f79, 0xeed6beb5, + 0xeed6beb5, 0xeec5b2b5, 0xeec3abaa, 0xeec0a59f, 0xeebd9e94, 0xeebd968c, 0xeeba8f86, 0xeeb88881, + 0xeeb5827b, 0xee9a6d65, 0xeece9e94, 0xeece9e94, 0xaa310c08, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00080000, 0x11080000, 0xcc6b231b, 0xff9c3529, 0xffa53529, 0xffa53529, + 0xffa53529, 0xffaa3729, 0xffaf392c, 0xffb2392f, 0xffb2392f, 0xffb2392f, 0xffb83a2c, 0xffba3b2f, + 0xffba3b2f, 0xffba3b2f, 0xffb83a31, 0xffb83a31, 0xffba3b31, 0xffba3b31, 0xffb53931, 0xffb53931, + 0xffc0706b, 0xffd6dfde, 0xffe6e3e6, 0xfff7f6f7, 0xffffffff, 0xffffffff, 0xfffffbff, 0xfffffbff, + 0xfffffbff, 0xffc87770, 0xffaf372c, 0xffaf372c, 0xffaf372c, 0xffad3529, 0xffa53529, 0xffa23329, + 0xffa23329, 0xff9c3129, 0xff943121, 0xff8c2d21, 0xff8c2d21, 0xff842821, 0xff732421, 0xff68201b, + 0xff5d1c16, 0xff5d1c16, 0xff4a1810, 0xee31100b, 0x99000000, 0x33000000, 0x00000000, 0x00000000, + 0x00000000, 0x22000000, 0xcc893e37, 0xffbd5042, 0xffbd5042, 0xffbd5042, 0xffbd5042, 0xffc04c3f, + 0xffc04c3f, 0xffba4234, 0xffba4234, 0xffba3e34, 0xffba3e34, 0xffaf372f, 0xffaf372f, 0xffad3529, + 0xff912e24, 0xff76271e, 0xff5a2019, 0xff5a2d3a, 0xffe6e7e6, 0xffe6e7e6, 0xff5a2d3a, 0xff4a1819, + 0xff581c19, 0xff652019, 0xff652019, 0xff632019, 0xff632019, 0xff5a1e16, 0xff5a1e16, 0xff581b13, + 0xff581b13, 0xff581b13, 0xff581b13, 0xff5a1c19, 0xff5a1c19, 0xdd3f1310, 0x77080000, 0x44000000, + 0x11000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x33000000, 0x99190000, 0xee977f79, 0xeed6beb5, + 0xeed6beb5, 0xeec3abaa, 0xeec3abaa, 0xeec0a59f, 0xeebd9e94, 0xeebd968c, 0xeeba8f86, 0xeeb88881, + 0xeeb5827b, 0xee9a6d65, 0xeece9e94, 0xeece9e94, 0xaa310c08, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00080000, 0x00080000, 0x993a120e, 0xff9c3529, 0xffa53529, 0xffa53529, + 0xffa53529, 0xffa73629, 0xffaf392c, 0xffaf392c, 0xffb2392f, 0xffb2392f, 0xffb83a2c, 0xffba3b2f, + 0xffb83a2c, 0xffba3b2f, 0xffb83a31, 0xffba3b31, 0xffb83a31, 0xffba3b31, 0xffb53931, 0xffb53931, + 0xffb53931, 0xffcba7a5, 0xffe6e3e6, 0xfff7f6f7, 0xffffffff, 0xffffffff, 0xfffffbff, 0xfffffbff, + 0xffe4b9b8, 0xffad3529, 0xffaf372c, 0xffaf372c, 0xffad3529, 0xffad3529, 0xffa53529, 0xffa23329, + 0xff9f3229, 0xff9c3129, 0xff8c2d21, 0xff8c2d21, 0xff842821, 0xff7b2421, 0xff732421, 0xff68201b, + 0xff5d1c16, 0xff521810, 0xff4a1810, 0xdd190805, 0x77000000, 0x22000000, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0x99451f1b, 0xffbd5042, 0xffb5463a, 0xffb5463a, 0xffb5463a, 0xffba4234, + 0xffba4234, 0xffb53929, 0xffb53929, 0xffaf372f, 0xffaf372f, 0xffaf372f, 0xffaf372f, 0xffad3529, + 0xff912e24, 0xff76271e, 0xff5a2019, 0xff5a2d3a, 0xffe6e7e6, 0xffe6e7e6, 0xff5a2d3a, 0xff4a1819, + 0xff4a1819, 0xff581c19, 0xff652019, 0xff5a1e16, 0xff5a1e16, 0xff521b13, 0xff521b13, 0xff581b13, + 0xff581b13, 0xff581b13, 0xff581b13, 0xff5a1c19, 0xff5a1c19, 0xcc240908, 0x77080000, 0x33000000, + 0x11000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x33000000, 0x88290400, 0xee977873, 0xeeceb2ad, + 0xeeceb2ad, 0xeec5aead, 0xeec3a6a2, 0xeec09e97, 0xeec09e97, 0xeebd928c, 0xeeba8b84, 0xeeb8847b, + 0xeeb8847b, 0xeeb58a84, 0xeeb58a84, 0xeeb58a84, 0xaa210400, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00080000, 0x00080000, 0x66080000, 0xff9c3529, 0xffa53529, 0xffa53529, + 0xffa53529, 0xffa53529, 0xffaf392c, 0xffaf392c, 0xffaf392c, 0xffb2392f, 0xffb83a2c, 0xffb83a2c, + 0xffb83a2c, 0xffb83a2c, 0xffb53931, 0xffb83a31, 0xffb83a31, 0xffb53931, 0xffb53931, 0xffb53931, + 0xffb53931, 0xffc0706b, 0xffe6e3e6, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffbff, 0xfffffbff, + 0xffc87770, 0xffad3529, 0xffaf372c, 0xffaf372c, 0xffad3529, 0xffad3529, 0xffa53529, 0xffa23329, + 0xff9c3129, 0xff9c3129, 0xff8c2d21, 0xff8c2d21, 0xff842821, 0xff7b2421, 0xff68201b, 0xff5d1c16, + 0xff521810, 0xff521810, 0xff31100b, 0xbb000000, 0x66000000, 0x22000000, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0x44000000, 0xddad3d31, 0xffb5463a, 0xffad3d31, 0xffad3d31, 0xffb53929, + 0xffb53929, 0xffb53929, 0xffb53929, 0xffaf372f, 0xffaf372f, 0xffa53129, 0xffa53129, 0xff912e24, + 0xff912e24, 0xff5a2019, 0xff5a2019, 0xff5a2d3a, 0xffe6e7e6, 0xffe6e7e6, 0xff5a2d3a, 0xff4a1819, + 0xff4a1819, 0xff4a1819, 0xff581c19, 0xff521b13, 0xff521b13, 0xff521b13, 0xff4a1810, 0xff521810, + 0xff521810, 0xff521810, 0xff521810, 0xff5a1c19, 0xee3f1310, 0x99080000, 0x55080000, 0x22000000, + 0x11000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x22000000, 0x88290400, 0xee977873, 0xeeceb2ad, + 0xeeceb2ad, 0xeec3a6a2, 0xeec3a6a2, 0xeec09e97, 0xeebd968c, 0xeebd928c, 0xeeba8b84, 0xeeb8847b, + 0xeeb8847b, 0xeeb58a84, 0xeeb58a84, 0xeeb58a84, 0x99210400, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000400, 0x00000000, 0x00000000, 0x22000000, 0xdd6b2019, 0xff9c3129, 0xff9c3129, + 0xff9c3129, 0xff9c3129, 0xffa23329, 0xffa73629, 0xffa73629, 0xffa73629, 0xffb53929, 0xffb53929, + 0xffb53929, 0xffb53929, 0xffaf3729, 0xffb53929, 0xffaf3729, 0xffb53929, 0xffaf3729, 0xffb53929, + 0xffaf3729, 0xffaf3729, 0xffdbb9b5, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfffff7f7, 0xffe1b7b2, + 0xffa53929, 0xffa53929, 0xffa53529, 0xffa53529, 0xffa53529, 0xffa53529, 0xff9c3129, 0xff9c3129, + 0xff9c3129, 0xff942e26, 0xff8c2d21, 0xff8c2d21, 0xff7e271e, 0xff70221b, 0xff632019, 0xff632019, + 0xff471710, 0xff471710, 0xee290c08, 0xaa000000, 0x44000000, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x11000000, 0x99451710, 0xffbd3d31, 0xffbd3d31, 0xffbd3d31, 0xffad3929, + 0xffad3929, 0xffa73629, 0xffa73629, 0xffa53529, 0xffa53529, 0xff9a3126, 0xff9a3126, 0xff842d29, + 0xff762824, 0xff5a2019, 0xff5a2019, 0xff6b495a, 0xffd6cad6, 0xffd6cad6, 0xff6b495a, 0xff4d1c1e, + 0xff4a1410, 0xff4d1c1e, 0xff4d1c1e, 0xff4a1810, 0xff4a1810, 0xff4a1810, 0xff4a1810, 0xff4a1810, + 0xff4a1810, 0xff4a1810, 0xff4a1810, 0xff4a1810, 0xcc190805, 0x77000000, 0x44000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x22000000, 0x88290400, 0xee603e3a, 0xeeceb2ad, + 0xeeceb2ad, 0xeec3a6a2, 0xeec09e97, 0xeec09e97, 0xeebd968c, 0xeebd928c, 0xeeba8b84, 0xeeb8847b, + 0xeeb57d73, 0xeeb58a84, 0xeeb58a84, 0xeeb58a84, 0x99210400, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x77240b08, 0xff9c3129, 0xff9c3129, + 0xff9c3129, 0xff9c3129, 0xffa23329, 0xffa23329, 0xffa73629, 0xffa73629, 0xffb53929, 0xffad3629, + 0xffad3629, 0xffad3629, 0xffaf3729, 0xffaf3729, 0xffaf3729, 0xffaf3729, 0xffaf3729, 0xffaf3729, + 0xffaf3729, 0xffaf3729, 0xffa53d31, 0xfff7f7f7, 0xfff7f7f7, 0xfff7f7f7, 0xfffff7f7, 0xffa53929, + 0xffa53929, 0xffa53929, 0xffa53529, 0xffa53529, 0xff9f3329, 0xff9f3329, 0xff9c3129, 0xff9c3129, + 0xff942e26, 0xff942e26, 0xff8c2d21, 0xff8c2d21, 0xff7e271e, 0xff70221b, 0xff632019, 0xff471710, + 0xff471710, 0xff471710, 0xcc0e0403, 0x88000000, 0x33000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x11000000, 0x44080400, 0xcc812a21, 0xffbd3d31, 0xffbd3d31, 0xffa73629, + 0xffa73629, 0xffa73629, 0xffa23329, 0xff9a3126, 0xff9a3126, 0xff9a3126, 0xff8f2d24, 0xff762824, + 0xff68241e, 0xff5a2019, 0xff5a2019, 0xff6b495a, 0xffd6cad6, 0xffd6cad6, 0xff6b495a, 0xff4d1c1e, + 0xff4a1410, 0xff4a1410, 0xff4d1c1e, 0xff4a1810, 0xff4a1810, 0xff471710, 0xff471710, 0xff4a1810, + 0xff4a1810, 0xff4a1810, 0xff4a1810, 0xee31100b, 0x99000000, 0x55000000, 0x33000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x11000000, 0x22000000, 0x77290400, 0xee603e3a, 0xeeceb2ad, + 0xeeceb2ad, 0xeec3a6a2, 0xeec09e97, 0xeebd968c, 0xeebd968c, 0xeeba8b84, 0xeeba8b84, 0xeeb8847b, + 0xeeb57d73, 0xeeb58a84, 0xeeb58a84, 0xeeb58a84, 0x99210400, 0x33000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x22000000, 0xcc6e221e, 0xff9c3129, + 0xff9c3129, 0xff9c3129, 0xff9c3129, 0xffa23329, 0xffa23329, 0xffa73629, 0xffad3629, 0xffad3629, + 0xffad3629, 0xffad3629, 0xffaf3729, 0xffaa3629, 0xffa53529, 0xffaa3629, 0xffa53529, 0xffaf3729, + 0xffaa3629, 0xffa53529, 0xffa53d31, 0xffc07b73, 0xfff7f7f7, 0xfff7f7f7, 0xffc3786e, 0xffa53929, + 0xffa53929, 0xffa53929, 0xff9f3329, 0xff9f3329, 0xff9f3329, 0xff9a3229, 0xff9c3129, 0xff942e26, + 0xff942e26, 0xff942e26, 0xff7e271e, 0xff7e271e, 0xff70221b, 0xff70221b, 0xff632019, 0xff471710, + 0xff471710, 0xee2c0d08, 0xaa000000, 0x55000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x11080400, 0x77451710, 0xee812a21, 0xffbd3d31, 0xffa73629, + 0xffa23329, 0xffa23329, 0xffa23329, 0xff9a3126, 0xff9a3126, 0xff8f2d24, 0xff8f2d24, 0xff762824, + 0xff68241e, 0xff5a2019, 0xff68241e, 0xff6b495a, 0xffb29fad, 0xffb29fad, 0xff8f7484, 0xff50242c, + 0xff4a1410, 0xff4a1410, 0xff4a1410, 0xff471710, 0xff471710, 0xff451610, 0xff451610, 0xff4a1810, + 0xff4a1810, 0xff4a1810, 0xee3c130e, 0xbb190805, 0x66000000, 0x44000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe9dfdb, 0xfff7ffff, 0xffce9e94, + 0xffce9e94, 0xffd6a294, 0xffd6a294, 0xffd6a294, 0xffd6a294, 0xffd6a294, 0xffd6a294, 0xffd6a294, + 0xffd39e91, 0xffce9e94, 0xffce9e94, 0xffce988c, 0xffce988c, 0xffc58e7b, 0xffc58e7b, 0xfff7ffff, + 0xffe6d9d3, 0xffadaaad, 0x00000000, 0x11000000, 0x22000000, 0x77290400, 0xdd5d3731, 0xeec59e94, + 0xeec59e94, 0xeebd9e9c, 0xeebd9e9c, 0xeeba9794, 0xeeb8908c, 0xeeb58a84, 0xeeb2837b, 0xeeaf7c73, + 0xeeaf7c73, 0xee9c7168, 0xeed6a69c, 0xee9c7168, 0x88290800, 0x22000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x66100408, 0xee6e221e, + 0xff9c3129, 0xff9c3129, 0xff9c3129, 0xff9c3129, 0xff9c3129, 0xffa23329, 0xffa53329, 0xffa53329, + 0xffa53329, 0xffa53329, 0xffa53529, 0xffa53529, 0xffa53529, 0xffa53529, 0xffa53529, 0xffa53529, + 0xffa53529, 0xffa53529, 0xffa53d31, 0xffa53d31, 0xfff7f7f7, 0xfff7f7f7, 0xffa53929, 0xffa53929, + 0xffa53929, 0xffa53929, 0xff9a3229, 0xff9a3229, 0xff943129, 0xff943129, 0xff942e26, 0xff942e26, + 0xff8c2b24, 0xff842821, 0xff7e271e, 0xff70221b, 0xff70221b, 0xff631c19, 0xff471710, 0xff471710, + 0xff471710, 0xdd100400, 0x88000000, 0x33000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x11080400, 0x22080400, 0x99451710, 0xee812a21, 0xffa23329, + 0xffa23329, 0xff9c3129, 0xff9c3129, 0xff8f2d24, 0xff8f2d24, 0xff8f2d24, 0xff842821, 0xff68241e, + 0xff68241e, 0xff5a2019, 0xff842d29, 0xff8f7484, 0xffb29fad, 0xffb29fad, 0xff8f7484, 0xff522d3a, + 0xff4d1c1e, 0xff4a1410, 0xff4a1410, 0xff451610, 0xff451610, 0xff451610, 0xff451610, 0xff3c130e, + 0xff3c130e, 0xff3c130e, 0xcc210808, 0x77000000, 0x44000000, 0x22000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe9dfdb, 0xffce9e94, 0xffce9e94, + 0xffce9e94, 0xffd39f91, 0xffd39f91, 0xffd39f91, 0xffd39f91, 0xffd39e91, 0xffd39e91, 0xffd39e91, + 0xffd39e91, 0xffce988c, 0xffce988c, 0xffce988c, 0xffce9384, 0xffc58e7b, 0xffc58e7b, 0xffc58e7b, + 0xffe6d9d3, 0xffadaaad, 0x00000000, 0x11000000, 0x22000000, 0x66290400, 0xdd5d3731, 0xeec59e94, + 0xeec59e94, 0xeebd9e9c, 0xeeba9794, 0xeeb8908c, 0xeeb58a84, 0xeeb58a84, 0xeeb2837b, 0xeeaf7c73, + 0xeeaf7c73, 0xee9c7168, 0xeed6a69c, 0xee9c7168, 0x77290800, 0x22000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0xaa2c0f0b, + 0xff842d21, 0xff842d21, 0xff8c2d21, 0xff8c2d21, 0xff8c2d21, 0xff8c2d21, 0xff9c3129, 0xff9c3129, + 0xff9c3129, 0xff9c3129, 0xff9a3126, 0xffa53529, 0xff9a3126, 0xff9a3126, 0xff9c3129, 0xff9c3129, + 0xff9c3129, 0xff9c3129, 0xff8c2d21, 0xff8c2d21, 0xffbd6d6b, 0xffbd6d6b, 0xff9c3129, 0xff9c3129, + 0xff9c3129, 0xff9c3129, 0xff9c3121, 0xff9c3121, 0xff912d21, 0xff9c3121, 0xff842d21, 0xff842d21, + 0xff76271e, 0xff76271e, 0xff732421, 0xff732421, 0xff5d1e19, 0xff5d1e19, 0xff421410, 0xff421410, + 0xee2c0d0b, 0xaa000000, 0x55000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x33000000, 0x994a1410, 0xee942d21, + 0xff942d21, 0xff942d21, 0xff942d21, 0xff8c2d21, 0xff8c2d21, 0xff812821, 0xff812821, 0xff632019, + 0xff632019, 0xff632019, 0xff633134, 0xff846573, 0xffa596a5, 0xffa596a5, 0xff846573, 0xff5a3d42, + 0xff4a2221, 0xff421410, 0xff421410, 0xff421410, 0xff421410, 0xff421410, 0xff421410, 0xff421410, + 0xff421410, 0xcc160705, 0x77000000, 0x55000000, 0x33000000, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe9dfdb, 0xffce9e94, 0xffce9e94, + 0xffce9e94, 0xffd39f91, 0xffd09d8f, 0xffd09d8f, 0xffd09d8f, 0xffd09a8f, 0xffd09a8f, 0xffd09a8f, + 0xffd09a8f, 0xffce988c, 0xffce9384, 0xffce9384, 0xffce9384, 0xffc58e7b, 0xffc58e7b, 0xffc58e7b, + 0xffe6d9d3, 0xffadaaad, 0x00000000, 0x11000000, 0x22000000, 0x55290400, 0xcc290400, 0xeec59e94, + 0xeec59e94, 0xeeba9794, 0xeeb8908c, 0xeeb8908c, 0xeeb58a84, 0xeeb2837b, 0xeeaf7c73, 0xeeaf7c73, + 0xeead756b, 0xee9c7168, 0xeed6a69c, 0xdd633d34, 0x66290800, 0x22000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x22000000, + 0xbb2c0f0b, 0xff842d21, 0xff8c2d21, 0xff8c2d21, 0xff8c2d21, 0xff8c2d21, 0xff8f2d26, 0xff8f2d26, + 0xff8f2d26, 0xff9c3129, 0xff8f2d24, 0xff9a3126, 0xff9a3126, 0xff9a3126, 0xff942e26, 0xff9c3129, + 0xff942e26, 0xff9c3129, 0xff8c2d21, 0xff8c2d21, 0xff8c2d21, 0xff8c2d21, 0xff942e26, 0xff942e26, + 0xff942e26, 0xff942e26, 0xff9c3121, 0xff912d21, 0xff912d21, 0xff912d21, 0xff842d21, 0xff76271e, + 0xff76271e, 0xff76271e, 0xff732421, 0xff5d1e19, 0xff5d1e19, 0xff471710, 0xff421410, 0xee2c0d0b, + 0xbb000000, 0x77000000, 0x33000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x33000000, 0x99370f0b, + 0xee942d21, 0xff942d21, 0xff942d21, 0xff8c2d21, 0xff812821, 0xff812821, 0xff762421, 0xff632019, + 0xff632019, 0xff632019, 0xff633942, 0xff846573, 0xffa596a5, 0xffa596a5, 0xff846573, 0xff5a3d42, + 0xff4a2221, 0xff421410, 0xff421410, 0xff421410, 0xff421410, 0xff421410, 0xff421410, 0xee421410, + 0xcc160705, 0x77000000, 0x55000000, 0x33000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe9dfdb, 0xffce9e94, 0xffce9e94, + 0xffce9e94, 0xffd09d8f, 0xffd09d8f, 0xffd09d8f, 0xffce9a8c, 0xffd09a8f, 0xffce968c, 0xffce968c, + 0xffce968c, 0xffce9384, 0xffce9384, 0xffce8e7b, 0xffce8e7b, 0xffc58e7b, 0xffc58e7b, 0xffc58e7b, + 0xffe6d9d3, 0xffadaaad, 0x00000000, 0x00000000, 0x22000000, 0x44290400, 0xbb290400, 0xee916b63, + 0xeec59e94, 0xeeb8908c, 0xeeb8908c, 0xeeb58a84, 0xeeb58a84, 0xeeb2837b, 0xeeaf7c73, 0xeead756b, + 0xeead756b, 0xee9c7168, 0xeed6a69c, 0xcc290800, 0x55290800, 0x22000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x33000000, 0xcc2c0f0b, 0xff76241b, 0xff76241b, 0xff76241b, 0xff76241b, 0xff812824, 0xff812824, + 0xff812824, 0xff812824, 0xff8f2d24, 0xff8f2d24, 0xff8f2d24, 0xff8f2d24, 0xff8c2b24, 0xff8c2b24, + 0xff8c2b24, 0xff8c2b24, 0xff8c2d21, 0xff8c2d21, 0xff8c2d21, 0xff8c2d21, 0xff942e26, 0xff942e26, + 0xff942e26, 0xff942e26, 0xff912d21, 0xff912d21, 0xff862821, 0xff862821, 0xff76271e, 0xff76271e, + 0xff68221b, 0xff68221b, 0xff5d1e19, 0xff5d1e19, 0xff471710, 0xff471710, 0xff2c0d0b, 0xcc000000, + 0x88000000, 0x44000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x33080000, + 0x88370f0b, 0xdd651e16, 0xff942d21, 0xff812821, 0xff812821, 0xff762421, 0xff762421, 0xff632019, + 0xff632019, 0xff632826, 0xff633942, 0xff846573, 0xff947d8c, 0xff947d8c, 0xff846573, 0xff5a3d42, + 0xff4a2221, 0xff421410, 0xff421410, 0xff421410, 0xff421410, 0xff421410, 0xee2f0d0b, 0xbb160705, + 0x77000000, 0x55000000, 0x33000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0xff949694, 0xffe6e3e6, 0xffce9a8c, 0xffce9a8c, + 0xffce9a8c, 0xffce9a8c, 0xffce9a8c, 0xffce9a8c, 0xffce9a8c, 0xffce9a8c, 0xffce9a8c, 0xffce9a8c, + 0xffce9a8c, 0xffc58a7b, 0xffc58a7b, 0xffc58a7b, 0xffc58a7b, 0xffb57d73, 0xffb57d73, 0xffb57d73, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x00000000, 0x11000000, 0x33190400, 0xaa190400, 0xee91584d, + 0xeece8273, 0xeeb5867b, 0xeeb5867b, 0xeeb5867b, 0xeeb5867b, 0xeead7973, 0xeead7973, 0xeeaa6d65, + 0xeeaa6d65, 0xeeaa7d73, 0xeeefbaad, 0xbb210400, 0x44210400, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11000000, 0x44000000, 0xcc4a1410, 0xff76241b, 0xff76241b, 0xff76241b, 0xff732421, 0xff732421, + 0xff732421, 0xff812824, 0xff842821, 0xff842821, 0xff842821, 0xff842821, 0xff842821, 0xff842821, + 0xff8c2b24, 0xff842821, 0xff8c2d21, 0xff8c2d21, 0xff8c2d21, 0xff8c2d21, 0xff8c2b24, 0xff8c2b24, + 0xff8c2b24, 0xff842821, 0xff862821, 0xff862821, 0xff862821, 0xff7b2421, 0xff76271e, 0xff68221b, + 0xff68221b, 0xff5a1c19, 0xff5d1e19, 0xff471710, 0xff311008, 0xff311008, 0xdd160705, 0x99000000, + 0x55000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11080000, + 0x33080000, 0x55080000, 0xaa370f0b, 0xee6b2021, 0xff812821, 0xff762421, 0xff762421, 0xff632019, + 0xff632019, 0xff632019, 0xff633134, 0xff734d5a, 0xff846573, 0xff846573, 0xff734d5a, 0xff522f31, + 0xff4a2221, 0xff421410, 0xff421410, 0xff421410, 0xee2f0d0b, 0xcc1b0705, 0x99080000, 0x66000000, + 0x44000000, 0x33000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff949694, 0xffe6e3e6, 0xffce9a8c, 0xffce9a8c, + 0xffce9a8c, 0xffce9a8c, 0xffefdbd3, 0xfffffbf7, 0xfffffbf7, 0xffefddd9, 0xffefddd9, 0xffefddd9, + 0xffefddd9, 0xfffffbf7, 0xfffffbf7, 0xffecd5ce, 0xffc58a7b, 0xffb57d73, 0xffb57d73, 0xffb57d73, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x00000000, 0x11000000, 0x22190400, 0x77190400, 0xdd552e26, + 0xeece8273, 0xeeaf7165, 0xeeaf7165, 0xeeb5867b, 0xeeaf7165, 0xeead7973, 0xeeaa6d65, 0xeeaa6d65, + 0xeeaa6d65, 0xeeaa7d73, 0xeeaa7d73, 0x88210400, 0x22210400, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0x33000000, 0x99210b08, 0xee421610, 0xff632019, 0xff632019, 0xff632019, + 0xff632019, 0xff632019, 0xff732419, 0xff732419, 0xff732419, 0xff732419, 0xff6b221b, 0xff7b2821, + 0xff7b2821, 0xff7b2821, 0xff7b2821, 0xff7b2821, 0xff7b2821, 0xff7b2821, 0xff7b2821, 0xff7b2821, + 0xff7b2821, 0xff7b2821, 0xff7b2421, 0xff7b2421, 0xff7b2421, 0xff7b2421, 0xff6b2019, 0xff6b2019, + 0xff6b2019, 0xff4a1610, 0xff421410, 0xff421410, 0xee2c0d0b, 0xcc000000, 0x99000000, 0x55000000, + 0x22000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11000000, 0x22000000, 0x44000000, 0x771e0908, 0xbb3c1310, 0xdd5a1c19, 0xff5a1c19, 0xff55221b, + 0xff55221b, 0xff55221b, 0xff7b3129, 0xff58373c, 0xff7b4d52, 0xff7b4d52, 0xff58373c, 0xff5a2d29, + 0xff3f1f1b, 0xff24120e, 0xee24120e, 0xcc210808, 0x990b0303, 0x77000000, 0x55000000, 0x44000000, + 0x22000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff949694, 0xffe6e3e6, 0xffce9a8c, 0xffce9a8c, + 0xffce9a8c, 0xffce9a8c, 0xffefdbd3, 0xfffffbf7, 0xfffffbf7, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xfffffbf7, 0xfffffbf7, 0xffd9afa5, 0xffc58a7b, 0xffb57d73, 0xffb57d73, 0xffb57d73, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x00000000, 0x11000000, 0x22190400, 0x44190400, 0xbb190400, + 0xee91584d, 0xeeaa5d50, 0xeeaf7165, 0xeeaf7165, 0xeeaf7165, 0xeeaa6d65, 0xeea76158, 0xeea76158, + 0xeeaa6d65, 0xeeaa7d73, 0xcc210400, 0x55210400, 0x22210400, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x11000000, 0x22000000, 0x66000000, 0xcc210b08, 0xff451610, 0xff632019, + 0xff451610, 0xff632019, 0xff5d1c13, 0xff5d1c13, 0xff5d1c13, 0xff5d1c13, 0xff6b221b, 0xff6b221b, + 0xff6b221b, 0xff6b221b, 0xff6e231b, 0xff6e231b, 0xff6e231b, 0xff6e231b, 0xff6e231b, 0xff6e231b, + 0xff6e231b, 0xff6e231b, 0xff651e1b, 0xff7b2421, 0xff651e1b, 0xff651e1b, 0xff6b2019, 0xff4a1610, + 0xff4a1610, 0xff4a1610, 0xff2c0d0b, 0xee160705, 0xbb000000, 0x88000000, 0x55000000, 0x22000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0x11000000, 0x33000000, 0x44000000, 0x66000000, 0x991e0908, 0xbb2f130e, + 0xdd2f130e, 0xee55221b, 0xff55221b, 0xff58373c, 0xff58373c, 0xff58373c, 0xee342226, 0xdd3f1f1b, + 0xcc24120e, 0xaa080400, 0x88080400, 0x77000000, 0x55000000, 0x44000000, 0x33000000, 0x11000000, + 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff949694, 0xffe6e3e6, 0xffce9a8c, 0xffce9a8c, + 0xffce9a8c, 0xffce9a8c, 0xffce9a8c, 0xfffffbf7, 0xfffffbf7, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xfffffbf7, 0xffecd5ce, 0xffc58a7b, 0xffc58a7b, 0xffb57d73, 0xffb57d73, 0xffb57d73, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x00000000, 0x00000000, 0x11190400, 0x22190400, 0x77190400, + 0xcc190400, 0xeea5493a, 0xeeaa5d50, 0xeeaa5d50, 0xeeaa5d50, 0xeea76158, 0xeea76158, 0xeea76158, + 0xeea5554a, 0xcc210400, 0x77210400, 0x22210400, 0x11210400, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x44000000, 0x88080000, 0xdd260b08, + 0xee451610, 0xff451610, 0xff47140e, 0xff5d1c13, 0xff5d1c13, 0xff5d1c13, 0xff5a1b16, 0xff5a1b16, + 0xff5a1b16, 0xff5a1b16, 0xff601e16, 0xff601e16, 0xff6e231b, 0xff601e16, 0xff601e16, 0xff601e16, + 0xff601e16, 0xff601e16, 0xff651e1b, 0xff651e1b, 0xff501716, 0xff501716, 0xff4a1610, 0xff4a1610, + 0xff290b08, 0xee290b08, 0xdd000000, 0xaa000000, 0x77000000, 0x44000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, 0x22000000, 0x33000000, 0x55080400, + 0x66080400, 0x77080400, 0x88080400, 0x88100c10, 0x99100c10, 0x99100c10, 0x88100c10, 0x8824120e, + 0x77080400, 0x66080400, 0x55080400, 0x44000000, 0x22000000, 0x11000000, 0x11000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff949694, 0xffe6e3e6, 0xffce9284, 0xffce9284, + 0xffce9284, 0xffc58e7b, 0xffc58e7b, 0xffd9b3a7, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffcea9a2, 0xffb57d73, 0xffb57d73, 0xffad756b, 0xffad756b, 0xffad756b, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, 0x22000000, + 0x66000000, 0x99210400, 0xaa420800, 0xbb420800, 0xbb630c00, 0xcc520c00, 0xbb520c00, 0xbb370800, + 0x991b0400, 0x66000000, 0x33000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x22080000, 0x44080000, + 0x77080000, 0xbb080000, 0xee310c08, 0xff47140e, 0xff47140e, 0xff47140e, 0xff4a1410, 0xff4a1410, + 0xff5a1b16, 0xff5a1b16, 0xff521810, 0xff521810, 0xff521810, 0xff521810, 0xff521810, 0xff521810, + 0xff521810, 0xff521810, 0xff501716, 0xff501716, 0xff501716, 0xff3a1010, 0xff290b08, 0xee290b08, + 0xcc080000, 0xaa080000, 0x88000000, 0x55000000, 0x33000000, 0x11000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, 0x22080400, + 0x33080400, 0x33080400, 0x44080400, 0x44100c10, 0x55100c10, 0x55100c10, 0x44100c10, 0x44080400, + 0x33080400, 0x33080400, 0x22080400, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff949694, 0xffe6e3e6, 0xffce9284, 0xffce9284, + 0xffce9284, 0xffc58e7b, 0xffc58e7b, 0xffc58e7b, 0xffecd9d3, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffe6d4d0, 0xffb57d73, 0xffb57d73, 0xffb57d73, 0xffad756b, 0xffad756b, 0xffad756b, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, + 0x22000000, 0x22000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000, + 0x22000000, 0x22000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, + 0x22000000, 0x44000000, 0x66000000, 0x99000000, 0xbb080303, 0xdd190808, 0xee260b0b, 0xff3a1010, + 0xff3a1010, 0xff3a1010, 0xff3a1410, 0xff3a1410, 0xff3a1410, 0xff3a1410, 0xff4a1410, 0xff4a1410, + 0xff4a1410, 0xff4a1410, 0xff311010, 0xee210b0b, 0xdd100505, 0xcc100505, 0xbb000000, 0x99000000, + 0x77000000, 0x55000000, 0x33000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff949694, 0xffe6e3e6, 0xffce9284, 0xffce9284, + 0xffce9284, 0xffc58e7b, 0xffc58e7b, 0xffc58e7b, 0xffd9b3a7, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffcea9a2, 0xffb57d73, 0xffb57d73, 0xffb57d73, 0xffad756b, 0xffad756b, 0xffad756b, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0x11000000, 0x33000000, 0x44000000, 0x55000000, 0x77000000, 0x88000000, + 0xaa000000, 0xbb000000, 0xcc130705, 0xcc130705, 0xcc130705, 0xdd130705, 0xcc190705, 0xcc190705, + 0xcc000000, 0xbb000000, 0xbb000000, 0x99000000, 0x88000000, 0x66000000, 0x55000000, 0x44000000, + 0x33000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff949694, 0xffe6e3e6, 0xffce9284, 0xffce9284, + 0xffce9284, 0xffc58e7b, 0xffc58e7b, 0xffc58e7b, 0xffc58e7b, 0xffe9d7d3, 0xffffffff, 0xffffffff, + 0xffdec2bd, 0xffb57d73, 0xffb57d73, 0xffb57d73, 0xffb57d73, 0xffad756b, 0xffad756b, 0xffad756b, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x11000000, 0x22000000, 0x22000000, + 0x33000000, 0x44000000, 0x55000000, 0x55000000, 0x55000000, 0x66000000, 0x66000000, 0x66000000, + 0x55000000, 0x55000000, 0x44000000, 0x44000000, 0x33000000, 0x22000000, 0x11000000, 0x11000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff949694, 0xffe6e3e6, 0xffc5867b, 0xffc5867b, + 0xffc5867b, 0xffc58a7b, 0xffbd8376, 0xffbd8376, 0xffbd8376, 0xffc59b8f, 0xfff7e7e6, 0xfff7e7e6, + 0xffc59b8f, 0xffb5796b, 0xffb5796b, 0xffad7568, 0xffad7568, 0xffa56d63, 0xffa56d63, 0xffa56d63, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x11000000, + 0x11000000, 0x11000000, 0x11000000, 0x11000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff949694, 0xffe6e3e6, 0xffc5867b, 0xffc5867b, + 0xffc5867b, 0xffbd8376, 0xffbd8376, 0xffb57c70, 0xffb57c70, 0xffad7563, 0xffdec1ba, 0xffdec1ba, + 0xffad7563, 0xffad7568, 0xffad7568, 0xffa57165, 0xffa57165, 0xffa56d63, 0xffa56d63, 0xffa56d63, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff949694, 0xffe6e3e6, 0xffc5867b, 0xffc5867b, + 0xffc5867b, 0xffbd8376, 0xffb57c70, 0xffb57c70, 0xffb57c70, 0xffad7563, 0xffad7563, 0xffad7563, + 0xffad7563, 0xffa57165, 0xffa57165, 0xffa57165, 0xff9c6d63, 0xffa56d63, 0xffa56d63, 0xffa56d63, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff949694, 0xffe6e3e6, 0xffc5867b, 0xffc5867b, + 0xffc5867b, 0xffb57c70, 0xffb57c70, 0xffad756b, 0xffad756b, 0xffad7563, 0xffad7563, 0xffad7563, + 0xffad7563, 0xff9c6d63, 0xff9c6d63, 0xff9c6d63, 0xff9c6d63, 0xffa56d63, 0xffa56d63, 0xffa56d63, + 0xffe6e3e6, 0xffadaaad, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff8f8f8f, 0xffded4d0, 0xffad7d73, 0xffad7d73, + 0xffad7d73, 0xffa57163, 0xffa57163, 0xffa57163, 0xffa57163, 0xff9c695a, 0xff9c695a, 0xff9c695a, + 0xff9c695a, 0xff94655a, 0xff94655a, 0xff94655a, 0xff94655a, 0xff946d63, 0xff946d63, 0xff946d63, + 0xffdbcecb, 0xffa5a6a5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff8f8f8f, 0xffded4d0, 0xfff7ffff, 0xffad7d73, + 0xffad7d73, 0xffa57163, 0xffa57163, 0xffa57163, 0xffa57163, 0xff9c695a, 0xff9c695a, 0xff9c695a, + 0xff9c695a, 0xff94655a, 0xff94655a, 0xff94655a, 0xff94655a, 0xff946d63, 0xff946d63, 0xffffffff, + 0xffdbcecb, 0xffa5a6a5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff8f8f8f, 0xffded4d0, 0xffded4d0, 0xffded4d0, + 0xffded4d0, 0xffd6dbde, 0xffd6dbde, 0xffd6dbde, 0xffd6dbde, 0xffd6dbde, 0xffd6dbde, 0xffd6dbde, + 0xffd6dbde, 0xffd6dbde, 0xffd6dbde, 0xffd6dbde, 0xffd6dbde, 0xffdbcecb, 0xffdbcecb, 0xffdbcecb, + 0xffdbcecb, 0xffa5a6a5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff8f8f8f, 0xffc5a9a2, 0xffc5a9a2, 0xffc5a9a2, + 0xffc5a9a2, 0xffc5b7b5, 0xffc5b7b5, 0xffc5b7b5, 0xffc5b7b5, 0xffc3b5b2, 0xffc3b5b2, 0xffc3b5b2, + 0xffc3b5b2, 0xffc0b3b2, 0xffc0b3b2, 0xffc0b3b2, 0xffc0b3b2, 0xffb89e97, 0xffb89e97, 0xffb89e97, + 0xffb89e97, 0xff6e6f6e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}; + +static const UINT g_DXUTGUITextureSrcDataSizeInBytes = 262272; + +static const DWORD g_DXUTArrowMeshSrcData[] = +{ + 0x20666f78, 0x33303330, 0x70697a62, 0x32333030, 0x000030d7, 0x087930c7, 0x59ed4b43, 0xd51c6c5d, + 0x71dbbe15, 0xacbbc1d6, 0xe125d493, 0xc1024e27, 0x7133f9c1, 0xec1098ec, 0x1b1daef1, 0xc6d24eb7, + 0xc713fa10, 0x64866f59, 0xd9aecd95, 0x694304dd, 0x4485686b, 0xad2fb6a5, 0x78df44a8, 0x6cca8828, + 0x20a2895a, 0x2aaf60ef, 0x905215b5, 0x4fa9515a, 0xa45b4d45, 0xa1e09548, 0x9e94d282, 0xcf5df333, + 0x8a3acdf1, 0xec0c5368, 0xbefec6ac, 0xf77ee733, 0xdef73bdc, 0x9d667739, 0x4a65a90a, 0xf27c81a9, + 0x7040d394, 0xba2785e0, 0x7e7e38ff, 0xd5bb0be5, 0xba1f17fa, 0x56a633b0, 0x1546bf79, 0x1d7cec51, + 0x164bef39, 0x8ec9e9f3, 0xb02e0ec9, 0x1fe77ed7, 0xbf399e4f, 0x550707f2, 0x1fceceef, 0x36a1db3e, + 0xdc985b93, 0x316e794e, 0xc415a965, 0x2413551a, 0xf77d749a, 0xc2d993e5, 0x29fcb983, 0xe2d5905f, + 0x61519a86, 0x7a942488, 0x36fb0b90, 0x1df5c9ad, 0x5cc55272, 0x188e559e, 0x4288e08d, 0x1aee41e4, + 0x47c0123e, 0xae72c8b5, 0x189c29ca, 0xbebca648, 0x5a643318, 0xf91567c9, 0x90e1d964, 0x933a2f93, + 0xe963d943, 0x52685394, 0xaeaf8a1d, 0x8bcce8e4, 0x058b45b1, 0xaa87527d, 0x2afedab9, 0x642f72d5, + 0x4daeacb9, 0xfc8fd936, 0x4cc6ae0c, 0x15a5ae77, 0x2018bc05, 0x8feb9b20, 0x2bdd0e02, 0x6172b81f, + 0x50440c73, 0xbadd3f70, 0x31c0a664, 0xadf719f7, 0xf859fa15, 0x3d721e5c, 0xc62ff55f, 0x701d670c, + 0x40b14754, 0x11d86164, 0x903fbd84, 0xbd058b32, 0x97d2ddcc, 0x07f2e4cb, 0x0e711307, 0x1ffd4ffb, + 0x09963e74, 0x6121e6c2, 0x39de5391, 0xee0f8fe6, 0xc779e395, 0x6f94fac9, 0xb4e678d3, 0x664c5c13, + 0xe5244e26, 0x2cfad200, 0xcdf678ff, 0x7e4e75df, 0x20317918, 0x9f274593, 0x6f58664e, 0x8c32319f, + 0x7b94f916, 0x550533c3, 0x761ee44c, 0x300c2e88, 0x5627aea4, 0xa7527098, 0x4a3cc933, 0x4e717354, + 0xf4850ba5, 0x8e6a2d19, 0x1fb81586, 0x74e1d03a, 0x26c1c8a1, 0x06890caa, 0xb1da35be, 0x9a65dc60, + 0x3064ce14, 0x859df497, 0xd5c55639, 0xfb0b9c1f, 0xd25ef2e9, 0x46f1ae81, 0xfebf4f1f, 0x749913d3, + 0xe74c592a, 0x1c8998b2, 0x6ffdd0f0, 0x3f9bfcbc, 0xa9e868fc, 0x3fcf23f3, 0xe7f1da57, 0x3f3c31f9, + 0xcf14f5c9, 0x8fa7c81e, 0x8cc9b3a7, 0x917c919c, 0x983a7507, 0x3fb4b2f5, 0xeb6ac50a, 0xca48c6f7, + 0x07633ac9, 0xb3ea3973, 0xf58d2d2b, 0x352b3f5e, 0x8ecbab65, 0x0119b7ab, 0xf3e78c30, 0xa6af87b9, + 0xfddef7ee, 0xe5551ece, 0xafc27690, 0x65c7aaa8, 0xfbe37375, 0x6f50c91e, 0x773bf939, 0x9bc6f87c, + 0xa35729f6, 0xaef0ae99, 0x256f73b6, 0x00957ff8, 0x7d46b8f8, 0x7e7fc53e, 0x5f343232, 0x75de5ead, + 0xc1ef61ad, 0xf59d3773, 0x3950da6a, 0x35c4aa5e, 0x8a503e1e, 0x3adebfd7, 0xb2c778cb, 0x7f9dfc62, + 0x97c3d8ff, 0x8ef74db6, 0x61ecbaff, 0xd5fa7db5, 0xb2fb7024, 0xd9f6ace2, 0xab34a077, 0xece692cb, + 0x9d93d74c, 0xfe5d9cd0, 0x4757ab7a, 0xe1efef9b, 0xbf4db7f7, 0x68719a4a, 0x498126f6, 0x7c36fe33, + 0x461e3348, 0x68ce20d9, 0x5a338825, 0x568ce209, 0x95a33882, 0x2568ce20, 0x095a3388, 0x82568ce2, + 0xc44d3d38, 0x7104ad19, 0x9c412b46, 0xf4e2269e, 0xa7a71134, 0x67c93889, 0x6bf4f0fe, 0xec3ffb7d, + 0x937ab0db, 0x4e8bbc62, 0x19fabd0b, 0x5b82433a, 0x075e69b0, 0x6132f9ac, 0x9b0c23e3, 0x69b0f5e6, + 0xcd361cbe, 0xf34d83af, 0x8f34d806, 0x1479a6c0, 0x87afcd36, 0x6c18f34d, 0x6360879a, 0x9fa74cde, + 0x1d7c06ca, 0x4af0166c, 0xcd87af83, 0xf0655e02, 0xc059b00d, 0xadf8359f, 0x4dc059b0, 0x360dbf06, + 0x0673f80b, 0x059b08df, 0x6fc1837c, 0x5e02cd87, 0xd816f06d, 0x0635e02c, 0x059b04df, 0xefc1a37c, + 0xbe02cd80, 0xb0ade0c9, 0x1b37c059, 0x166c337c, 0xdf062df0, 0xdc059b02, 0x7166f068, 0xb9d2d6bf, + 0x826dce95, 0x382ede33, 0x19c136e3, 0xe33829df, 0x6e33821d, 0x4ef19c17, 0x087719c1, 0x7053b8ce, + 0x6704bbc6, 0x977825dc, 0x816b5f98, 0x1bbe0b77, 0x9592aa6d, 0x5990fe2f, 0xd25cbcf0, 0xb7df7d78, + 0x9f46a7ec, 0xe17666e9, 0x7dced644, 0xf1995cfb, 0xf6eda1e0, 0x78f667b3, 0x2607facf, 0xf479ee9f, + 0xd5e045bb, 0x6fb686e5, 0xddffb878, 0x7a707746, 0x7f4fc3c4, 0xf4cdd47f, 0xa6930f2a, 0xd0339a4b, + 0x07b34974, 0xda692e9a, 0x26932cd0, 0xd21eeaf0, 0x9369a1b4, 0x9b4d0da6, 0x60448d34, 0x33cc45ca, + 0x6515c7c2, 0x8ae9a15d, 0x83115cba, 0x8b2b622b, 0x5b45bb98, 0x5b46d16c, 0x7d16ddb4, 0xb2be8b62, + 0x98f61f45, 0x5c652f31, 0x1ed4c87b, 0xcc87b532, 0x44c87852, 0x87eedd16, 0x084ce7bd, 0x87e93f65, + 0xdea666f9, 0xb3feed9b, 0x2da69e4b, 0x5f5e2238, 0x448df95e, 0xe783dd58, 0x2758b377, 0x87573af4, + 0xb58c2c35, 0xa4d6396a, 0x513dac06, 0x8c3131ac, 0x135815cd, 0x376e6156, 0x80de8e61, 0x7306b6b9, + 0xfd8c26e6, 0xffef705b, 0xf04675df, 0x0f57b05b, 0xb2a52f7b, 0x5179b5ce, 0xced6ede0, 0xe45895bd, + 0x7c35c54d, 0xeeaea051, 0xd7b8c145, 0x85a12ddf, 0x274a972a, 0x9ec71a13, 0xa10a254f, 0x1c69b7a2, + 0xb89c3b5d, 0xe1e8ba54, 0x24b5cfb3, 0xe3274e7e, 0x08ed917f, 0x413c635d, 0xf5065cbe, 0x4eb5a4bf, + 0xdab38a87, 0xe2e941fe, 0x49fc28ec, 0x742cee63, 0x7dee6348, 0x5cef93e8, 0xc692f516, 0xf57ecfdc, + 0x7db497d3, 0xcf10b492, 0xd17b3a9c, 0xf9d225c3, 0xff8c9d05, 0xc5acfa49, 0x36f924f8, 0xb7bc1952, + 0xc62d62e9, 0xf4e3f75f, 0xc5ece870, 0x93f861f8, 0x9d04a246, 0xbdf18a31, 0x1a4faf92, 0x57a81389, + 0x6fe7db1f, 0x862f0d6d, 0x36a9636b, 0x1c1bfe96, 0xead38f56, 0x9c13f474, 0x1c8a37a3, 0xba39195d, + 0x65727232, 0xc8cae0e4, 0x639195b9, 0x56a7232b, 0x8cad0e46, 0x3919599c, 0x740dceb2, 0xe46edc4e, + 0xd45f3ac0, 0x234eef39, 0xa3f9d607, 0x8c3b79ce, 0x93e7581c, 0x44ede73a, 0x2ef9206e, 0x66e02cd8, + 0x66c17783, 0xf833af01, 0xc059b05d, 0x1bbe0deb, 0x83780b36, 0xcd86efc1, 0xe0d5be02, 0x80b3607b, + 0x3df8336f, 0x1bc059b0, 0x9b0dde0d, 0xc1bb7c05, 0x80b3607b, 0xc36e0c5b, 0x326f0166, 0x166c2f78, + 0x8f061df0, 0xb70166c3, 0x9b013c1a, 0xe0d9bc05, 0xc059b07d, 0x0fde0c5b, 0xd5bc059b, 0xb3617be0, + 0x7c19b780, 0x0679ec40, 0x7c91c7b0, 0x0681ec50, 0xfc91e7b1, 0xba27b15e, 0xc9207b17, 0x691ec487, + 0xf25b6308, 0x79de3176, 0x3a79f4bf, 0xe33820bf, 0xef19c161, 0x7ef19c13, 0x101f19c1, 0x0517f19c, + 0xc125fc67, 0x9c141f19, 0x8ce088f1, 0xf19c13ef, 0x3e3382fd, 0x07e33824, 0x65fc6704, 0x457f19c1, + 0x155fc670, 0x04d7f19c, 0x70587c67, 0x3382a3c6, 0xe338223e, 0x1f19c131, 0x52719c15, 0x7cfa24f0, + 0xd59117d1, 0xfda5d892, 0xe02969e2, 0xb71fbffd, 0xdfebfe5f, 0xe5fede67, 0xbb807a5f, 0x46c64719, + 0x5f9b96ec, 0xf1dc61ec, 0xdafda744, 0xcc66c440, 0xae3399ff, 0xc7eceba3, 0x7971cb98, 0xc98d19e0, + 0xa87daca7, 0xd2cbabac, 0xd26b577f, 0x750eb775, 0xc7573951, 0x7c233c00, 0x2baca2ca, 0x97515d34, + 0x4570622b, 0xf16e1e6c, 0x5b457663, 0x5746d15c, 0x25d75db7, 0xa58f5337, 0xcb78798e, 0xe27adff0, + 0x6fb61ccf, 0x187a67cc, 0x5eedfe1f, 0x0ba97bfb, 0x9be57e1e, 0x193e6c1b, 0x31af8db3, 0xc32e5f66, + 0x5ec16b58, 0x2ff276d6, 0x70d27f6b, 0xdcd90eb5, 0x5f27d093, 0x1a4bd757, 0x84a72f7c, 0x59fdacbd, + 0x46bceb4b, 0x4577d0a7, 0xc788aebd, 0x22ba7115, 0xcbb4577e, 0x093dedd5, 0x8dfd8e7d, 0x3f7afc87, + 0x3ffe2f4e, 0x624b5c0a, 0x2d6c496b, 0xb125ad89, 0xd3f624b5, 0xe95ec49e, 0xd638c743, 0x829fa3a9, + 0x0fb51d0f, 0x9887fe31, 0xb4bfd863, 0x621f847f, 0xdec7c59a, 0xecc3e20d, 0x7511f146, 0xa9e0f893, + 0x156e5c3f, 0xc4db201f, 0x7b8fc5c7, 0xf7e2221b, 0x0000001f +}; + +static const UINT g_DXUTArrowMeshSrcDataSizeInBytes = 2193; + +//----------------------------------------------------------------------------- +HRESULT WINAPI DXUTCreateGUITextureFromInternalArray9( LPDIRECT3DDEVICE9 pd3dDevice, IDirect3DTexture9** ppTexture, D3DXIMAGE_INFO* pInfo ) +{ + return D3DXCreateTextureFromFileInMemoryEx( pd3dDevice, g_DXUTGUITextureSrcData, g_DXUTGUITextureSrcDataSizeInBytes, + D3DX_DEFAULT, D3DX_DEFAULT, 1, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, + D3DX_DEFAULT, D3DX_DEFAULT, 0, pInfo, NULL, ppTexture ); +} + +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTCreateGUITextureFromInternalArray11(ID3D11Device* pd3dDevice, ID3D11Texture2D** ppTexture, D3DX11_IMAGE_INFO* pInfo) +{ + HRESULT hr; + + D3DX11_IMAGE_INFO SrcInfo; + if( !pInfo ) + { + D3DX11GetImageInfoFromMemory( g_DXUTGUITextureSrcData, g_DXUTGUITextureSrcDataSizeInBytes, NULL, &SrcInfo, NULL ); + pInfo = &SrcInfo; + } + + ID3D11Resource *pRes; + D3DX11_IMAGE_LOAD_INFO loadInfo; + loadInfo.Width = D3DX11_DEFAULT; + loadInfo.Height = D3DX11_DEFAULT; + loadInfo.Depth = D3DX11_DEFAULT; + loadInfo.FirstMipLevel = 0; + loadInfo.MipLevels = 1; + loadInfo.Usage = D3D11_USAGE_DEFAULT; + loadInfo.BindFlags = D3D11_BIND_SHADER_RESOURCE; + loadInfo.CpuAccessFlags = 0; + loadInfo.MiscFlags = 0; + //loadInfo.Format = MAKE_TYPELESS( pInfo->Format ); + loadInfo.Format = MAKE_SRGB( pInfo->Format ); + loadInfo.Filter = D3DX11_FILTER_NONE; + loadInfo.MipFilter = D3DX11_FILTER_NONE; + loadInfo.pSrcInfo = pInfo; + + hr = D3DX11CreateTextureFromMemory( pd3dDevice, g_DXUTGUITextureSrcData, g_DXUTGUITextureSrcDataSizeInBytes, &loadInfo, NULL, &pRes, NULL ); + if( FAILED( hr ) ) + return hr; + hr = pRes->QueryInterface( __uuidof( ID3D11Texture2D ), (LPVOID*)ppTexture ); + SAFE_RELEASE( pRes ); + + return S_OK; +} + +//----------------------------------------------------------------------------- +HRESULT WINAPI DXUTCreateArrowMeshFromInternalArray( LPDIRECT3DDEVICE9 pd3dDevice, ID3DXMesh** ppMesh ) +{ + return D3DXLoadMeshFromXInMemory( g_DXUTArrowMeshSrcData, g_DXUTArrowMeshSrcDataSizeInBytes, + D3DXMESH_MANAGED, pd3dDevice, NULL, NULL, NULL, NULL, ppMesh ); +} + diff --git a/Demos/DX11ClothDemo/DXUT/Optional/DXUTres.h b/Demos/DX11ClothDemo/DXUT/Optional/DXUTres.h new file mode 100644 index 0000000..beab017 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/DXUTres.h @@ -0,0 +1,18 @@ +//---------------------------------------------------------------------------- +// File: dxutres.h +// +// Functions to create DXUT media from arrays in memory +// +// Copyright (c) Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#pragma once +#ifndef DXUT_RES_H +#define DXUT_RES_H + +HRESULT WINAPI DXUTCreateGUITextureFromInternalArray9( LPDIRECT3DDEVICE9 pd3dDevice, IDirect3DTexture9** ppTexture, + D3DXIMAGE_INFO* pInfo ); +HRESULT WINAPI DXUTCreateGUITextureFromInternalArray11( ID3D11Device* pd3dDevice, ID3D11Texture2D** ppTexture, + D3DX11_IMAGE_INFO* pInfo ); +HRESULT WINAPI DXUTCreateArrowMeshFromInternalArray( LPDIRECT3DDEVICE9 pd3dDevice, ID3DXMesh** ppMesh ); + +#endif diff --git a/Demos/DX11ClothDemo/DXUT/Optional/DXUTsettingsdlg.cpp b/Demos/DX11ClothDemo/DXUT/Optional/DXUTsettingsdlg.cpp new file mode 100644 index 0000000..334fa26 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/DXUTsettingsdlg.cpp @@ -0,0 +1,2853 @@ +//-------------------------------------------------------------------------------------- +// File: DXUTSettingsDlg.cpp +// +// Dialog for selection of device settings +// +// Copyright (c) Microsoft Corporation. All rights reserved +//-------------------------------------------------------------------------------------- +#include "DXUT.h" +#include "DXUTgui.h" +#include "DXUTsettingsDlg.h" +#undef min // use __min instead +#undef max // use __max instead + + +//-------------------------------------------------------------------------------------- +// Internal functions forward declarations +//-------------------------------------------------------------------------------------- +WCHAR* DXUTAPIVersionToString( DXUTDeviceVersion version ); +WCHAR* DXUTPresentIntervalToString( UINT pi ); +WCHAR* DXUTMultisampleTypeToString( D3DMULTISAMPLE_TYPE MultiSampleType ); +WCHAR* DXUTD3DDeviceTypeToString( D3DDEVTYPE devType ); +WCHAR* DXUTD3DX11DeviceTypeToString( D3D_DRIVER_TYPE devType ); +WCHAR* DXUTVertexProcessingTypeToString( DWORD vpt ); + + +HRESULT DXUTSnapDeviceSettingsToEnumDevice( DXUTDeviceSettings* pDeviceSettings, bool forceEnum, D3D_FEATURE_LEVEL forceFL = D3D_FEATURE_LEVEL(0) ); + +//-------------------------------------------------------------------------------------- +// Global state +//-------------------------------------------------------------------------------------- +DXUTDeviceSettings g_DeviceSettings; + +CD3DSettingsDlg* WINAPI DXUTGetD3DSettingsDialog() +{ + // Using an accessor function gives control of the construction order + static CD3DSettingsDlg dlg; + return &dlg; +} + + +//-------------------------------------------------------------------------------------- +CD3DSettingsDlg::CD3DSettingsDlg() +{ + m_pStateBlock = NULL; + m_bActive = false; + m_pActiveDialog = NULL; + + m_Levels[0] = D3D_FEATURE_LEVEL_9_1; + m_Levels[1] = D3D_FEATURE_LEVEL_9_2; + m_Levels[2] = D3D_FEATURE_LEVEL_9_3; + m_Levels[3] = D3D_FEATURE_LEVEL_10_0; + m_Levels[4] = D3D_FEATURE_LEVEL_10_1; + m_Levels[5] = D3D_FEATURE_LEVEL_11_0; + +} + + +//-------------------------------------------------------------------------------------- +CD3DSettingsDlg::~CD3DSettingsDlg() +{ + // Release the memory used to hold the D3D11 refresh data in the combo box + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_REFRESH_RATE ); + if( pComboBox ) + for( UINT i = 0; i < pComboBox->GetNumItems(); ++i ) + { + DXGI_RATIONAL* pRate = reinterpret_cast( pComboBox->GetItemData( i ) ); + delete pRate; + } +} + + +//-------------------------------------------------------------------------------------- +void CD3DSettingsDlg::Init( CDXUTDialogResourceManager* pManager ) +{ + assert( pManager ); + m_Dialog.Init( pManager, false ); // Don't register this dialog. + m_RevertModeDialog.Init( pManager, false ); // Don't register this dialog. + m_pActiveDialog = &m_Dialog; + CreateControls(); +} + +//-------------------------------------------------------------------------------------- +void CD3DSettingsDlg::Init( CDXUTDialogResourceManager* pManager, LPCWSTR szControlTextureFileName ) +{ + assert( pManager ); + m_Dialog.Init( pManager, false, szControlTextureFileName ); // Don't register this dialog. + m_RevertModeDialog.Init( pManager, false, szControlTextureFileName ); // Don't register this dialog. + m_pActiveDialog = &m_Dialog; + CreateControls(); +} + + +//-------------------------------------------------------------------------------------- +void CD3DSettingsDlg::Init( CDXUTDialogResourceManager* pManager, LPCWSTR pszControlTextureResourcename, + HMODULE hModule ) +{ + assert( pManager ); + m_Dialog.Init( pManager, false, pszControlTextureResourcename, hModule ); // Don't register this dialog. + m_RevertModeDialog.Init( pManager, false, pszControlTextureResourcename, hModule ); // Don't register this dialog + m_pActiveDialog = &m_Dialog; + CreateControls(); +} + + +//-------------------------------------------------------------------------------------- +void CD3DSettingsDlg::CreateControls() +{ + // Set up main settings dialog + m_Dialog.EnableKeyboardInput( true ); + m_Dialog.SetFont( 0, L"Arial", 15, FW_NORMAL ); + m_Dialog.SetFont( 1, L"Arial", 28, FW_BOLD ); + + // Right-justify static controls + CDXUTElement* pElement = m_Dialog.GetDefaultElement( DXUT_CONTROL_STATIC, 0 ); + if( pElement ) + { + pElement->dwTextFormat = DT_VCENTER | DT_RIGHT; + + // Title + CDXUTStatic* pStatic = NULL; + m_Dialog.AddStatic( DXUTSETTINGSDLG_STATIC, L"Direct3D Settings", 10, 5, 400, 50, false, &pStatic ); + pElement = pStatic->GetElement( 0 ); + pElement->iFont = 1; + pElement->dwTextFormat = DT_TOP | DT_LEFT; + } + + // DXUTSETTINGSDLG_API_VERSION + m_Dialog.AddStatic( DXUTSETTINGSDLG_STATIC, L"API Version", 10, 35, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_API_VERSION, 200, 35, 300, 23 ); + + + //DXUTSETTINGSDLG_D3D11_FEATURE_LEVEL + m_Dialog.AddStatic( DXUTSETTINGSDLG_D3D11_FEATURE_LEVEL_LABEL, L"Feature Level", 10, 60, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_D3D11_FEATURE_LEVEL, 200, 60, 300, 23 ); + m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_FEATURE_LEVEL )->SetDropHeight( 106 ); + + + // DXUTSETTINGSDLG_ADAPTER + m_Dialog.AddStatic( DXUTSETTINGSDLG_STATIC, L"Display Adapter", 10, 85, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_ADAPTER, 200, 85, 300, 23 ); + + // DXUTSETTINGSDLG_DEVICE_TYPE + m_Dialog.AddStatic( DXUTSETTINGSDLG_STATIC, L"Render Device", 10, 110, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_DEVICE_TYPE, 200, 110, 300, 23 ); + + // DXUTSETTINGSDLG_WINDOWED, DXUTSETTINGSDLG_FULLSCREEN + m_Dialog.AddCheckBox( DXUTSETTINGSDLG_DEVICECLIP, L"Clip to device when window spans across multiple monitors", + 250, 136, 500, 16 ); + m_Dialog.AddRadioButton( DXUTSETTINGSDLG_WINDOWED, DXUTSETTINGSDLG_WINDOWED_GROUP, L"Windowed", + 360, 157, 100, 16 ); + m_Dialog.AddRadioButton( DXUTSETTINGSDLG_FULLSCREEN, DXUTSETTINGSDLG_WINDOWED_GROUP, L"Full Screen", + 220, 157, 100, 16 ); + + // DXUTSETTINGSDLG_ADAPTER_FORMAT + m_Dialog.AddStatic( DXUTSETTINGSDLG_ADAPTER_FORMAT_LABEL, L"Adapter Format", 10, 175, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_ADAPTER_FORMAT, 200, 175, 300, 23 ); + + // DXUTSETTINGSDLG_RESOLUTION + m_Dialog.AddStatic( DXUTSETTINGSDLG_RESOLUTION_LABEL, L"Resolution", 10, 200, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_RESOLUTION, 200, 200, 200, 23 ); + m_Dialog.GetComboBox( DXUTSETTINGSDLG_RESOLUTION )->SetDropHeight( 106 ); + + // DXUTSETTINGSDLG_RES_SHOW_ALL + m_Dialog.AddCheckBox( DXUTSETTINGSDLG_RESOLUTION_SHOW_ALL, L"Show All Aspect Ratios", 420, 200, 200, 23, false ); + + // DXUTSETTINGSDLG_REFRESH_RATE + m_Dialog.AddStatic( DXUTSETTINGSDLG_REFRESH_RATE_LABEL, L"Refresh Rate", 10, 225, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_REFRESH_RATE, 200, 225, 300, 23 ); + + // DXUTSETTINGSDLG_BACK_BUFFER_FORMAT + m_Dialog.AddStatic( DXUTSETTINGSDLG_BACK_BUFFER_FORMAT_LABEL, L"Back Buffer Format", 10, 260, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_BACK_BUFFER_FORMAT, 200, 260, 300, 23 ); + + // DXUTSETTINGSDLG_DEPTH_STENCIL + m_Dialog.AddStatic( DXUTSETTINGSDLG_DEPTH_STENCIL_LABEL, L"Depth/Stencil Format", 10, 285, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_DEPTH_STENCIL, 200, 285, 300, 23 ); + + // DXUTSETTINGSDLG_MULTISAMPLE_TYPE + m_Dialog.AddStatic( DXUTSETTINGSDLG_MULTISAMPLE_TYPE_LABEL, L"Multisample Type", 10, 310, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_MULTISAMPLE_TYPE, 200, 310, 300, 23 ); + + // DXUTSETTINGSDLG_MULTISAMPLE_QUALITY + m_Dialog.AddStatic( DXUTSETTINGSDLG_MULTISAMPLE_QUALITY_LABEL, L"Multisample Quality", 10, 335, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_MULTISAMPLE_QUALITY, 200, 335, 300, 23 ); + + // DXUTSETTINGSDLG_VERTEX_PROCESSING + m_Dialog.AddStatic( DXUTSETTINGSDLG_VERTEX_PROCESSING_LABEL, L"Vertex Processing", 10, 360, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_VERTEX_PROCESSING, 200, 360, 300, 23 ); + + // DXUTSETTINGSDLG_PRESENT_INTERVAL + m_Dialog.AddStatic( DXUTSETTINGSDLG_PRESENT_INTERVAL_LABEL, L"Vertical Sync", 10, 385, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_PRESENT_INTERVAL, 200, 385, 300, 23 ); + + // DXUTSETTINGSDLG_D3D11_ADAPTER_OUTPUT + m_Dialog.AddStatic( DXUTSETTINGSDLG_D3D11_ADAPTER_OUTPUT_LABEL, L"Adapter Output", 10, 175, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_D3D11_ADAPTER_OUTPUT, 200, 175, 300, 23 ); + + // DXUTSETTINGSDLG_D3D11_RESOLUTION + m_Dialog.AddStatic( DXUTSETTINGSDLG_D3D11_RESOLUTION_LABEL, L"Resolution", 10, 200, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_D3D11_RESOLUTION, 200, 200, 200, 23 ); + m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_RESOLUTION )->SetDropHeight( 106 ); + + // DXUTSETTINGSDLG_D3D11_REFRESH_RATE + m_Dialog.AddStatic( DXUTSETTINGSDLG_D3D11_REFRESH_RATE_LABEL, L"Refresh Rate", 10, 225, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_D3D11_REFRESH_RATE, 200, 225, 300, 23 ); + + // DXUTSETTINGSDLG_D3D11_BACK_BUFFER_FORMAT + m_Dialog.AddStatic( DXUTSETTINGSDLG_D3D11_BACK_BUFFER_FORMAT_LABEL, L"Back Buffer Format", 10, 260, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_D3D11_BACK_BUFFER_FORMAT, 200, 260, 300, 23 ); + + // DXUTSETTINGSDLG_D3D11_MULTISAMPLE_COUNT + m_Dialog.AddStatic( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_COUNT_LABEL, L"Multisample Count", 10, 285, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_COUNT, 200, 285, 300, 23 ); + + // DXUTSETTINGSDLG_D3D11_MULTISAMPLE_QUALITY + m_Dialog.AddStatic( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_QUALITY_LABEL, L"Multisample Quality", 10, 310, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_QUALITY, 200, 310, 300, 23 ); + + // DXUTSETTINGSDLG_D3D11_PRESENT_INTERVAL + m_Dialog.AddStatic( DXUTSETTINGSDLG_D3D11_PRESENT_INTERVAL_LABEL, L"Vertical Sync", 10, 335, 180, 23 ); + m_Dialog.AddComboBox( DXUTSETTINGSDLG_D3D11_PRESENT_INTERVAL, 200, 335, 300, 23 ); + + // DXUTSETTINGSDLG_D3D11_DEBUG_DEVICE + m_Dialog.AddCheckBox( DXUTSETTINGSDLG_D3D11_DEBUG_DEVICE, L"Create Debug Device", 200, 365, 180, 23 ); + + // DXUTSETTINGSDLG_OK, DXUTSETTINGSDLG_CANCEL + m_Dialog.AddButton( DXUTSETTINGSDLG_OK, L"OK", 230, 440, 73, 31 ); + m_Dialog.AddButton( DXUTSETTINGSDLG_CANCEL, L"Cancel", 315, 440, 73, 31, 0, true ); + + // Set up mode change dialog + m_RevertModeDialog.EnableKeyboardInput( true ); + m_RevertModeDialog.EnableNonUserEvents( true ); + m_RevertModeDialog.SetFont( 0, L"Arial", 15, FW_NORMAL ); + m_RevertModeDialog.SetFont( 1, L"Arial", 28, FW_BOLD ); + + pElement = m_RevertModeDialog.GetDefaultElement( DXUT_CONTROL_STATIC, 0 ); + if( pElement ) + { + pElement->dwTextFormat = DT_VCENTER | DT_RIGHT; + + // Title + CDXUTStatic* pStatic = NULL; + m_RevertModeDialog.AddStatic( DXUTSETTINGSDLG_STATIC, L"Do you want to keep these display settings?", 10, 5, + 640, 50, false, &pStatic ); + pElement = pStatic->GetElement( 0 ); + pElement->iFont = 1; + pElement->dwTextFormat = DT_TOP | DT_LEFT; + + // Timeout static text control + m_RevertModeDialog.AddStatic( DXUTSETTINGSDLG_STATIC_MODE_CHANGE_TIMEOUT, L"", 10, 90, 640, 30, + false, &pStatic ); + pElement = pStatic->GetElement( 0 ); + pElement->iFont = 0; + pElement->dwTextFormat = DT_TOP | DT_LEFT; + } + + // DXUTSETTINGSDLG_MODE_CHANGE_ACCEPT, DXUTSETTINGSDLG_MODE_CHANGE_REVERT + m_RevertModeDialog.AddButton( DXUTSETTINGSDLG_MODE_CHANGE_ACCEPT, L"Yes", 230, 50, 73, 31 ); + m_RevertModeDialog.AddButton( DXUTSETTINGSDLG_MODE_CHANGE_REVERT, L"No", 315, 50, 73, 31, 0, true ); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice ) +{ + if( pd3dDevice == NULL ) + return DXUT_ERR_MSGBOX( L"CD3DSettingsDlg::OnCreatedDevice", E_INVALIDARG ); + + // Create the fonts/textures + m_Dialog.SetCallback( StaticOnEvent, ( void* )this ); + m_RevertModeDialog.SetCallback( StaticOnEvent, ( void* )this ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Changes the UI defaults to the current device settings +//-------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::Refresh() +{ + HRESULT hr = S_OK; + + g_DeviceSettings = DXUTGetDeviceSettings(); + + CDXUTComboBox* pAPIComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_API_VERSION ); + pAPIComboBox->RemoveAllItems(); + if( DXUTDoesAppSupportD3D9() ) + { + // Ensure that at least one adapter got enumerated. + CD3D9Enumeration* pD3DEnum = DXUTGetD3D9Enumeration(); + if( pD3DEnum->GetAdapterInfoList()->GetSize() > 0 ) + AddAPIVersion( DXUT_D3D9_DEVICE ); + } + if( DXUTDoesAppSupportD3D11() && DXUTIsD3D11Available() ) + { + // Ensure that at least one adapter got enumerated. + CD3D11Enumeration* pD3DEnum = DXUTGetD3D11Enumeration(); + if( pD3DEnum->GetAdapterInfoList()->GetSize() > 0 ) + AddAPIVersion( DXUT_D3D11_DEVICE ); + } + + // If no API has been added, something has gone wrong. Exit the dialog. + if( pAPIComboBox->GetNumItems() == 0 ) + { + SetActive( false ); + return S_OK; + } + + pAPIComboBox->SetSelectedByData( ULongToPtr( g_DeviceSettings.ver ) ); + + switch( g_DeviceSettings.ver ) + { + case DXUT_D3D9_DEVICE: + { + // Show all D3D9-specific controls and hide controls for all other D3D versions. + ShowControlSet( DXUT_D3D9_DEVICE ); + + CD3D9Enumeration* pD3DEnum = DXUTGetD3D9Enumeration(); + + // Fill the UI with the current settings + AddDeviceType( g_DeviceSettings.d3d9.DeviceType ); + SetWindowed( FALSE != g_DeviceSettings.d3d9.pp.Windowed ); + SetDeviceClip( 0 != ( g_DeviceSettings.d3d9.pp.Flags & D3DPRESENTFLAG_DEVICECLIP ) ); + AddAdapterFormat( g_DeviceSettings.d3d9.AdapterFormat ); + AddResolution( g_DeviceSettings.d3d9.pp.BackBufferWidth, g_DeviceSettings.d3d9.pp.BackBufferHeight ); + AddRefreshRate( g_DeviceSettings.d3d9.pp.FullScreen_RefreshRateInHz ); + AddBackBufferFormat( g_DeviceSettings.d3d9.pp.BackBufferFormat ); + AddDepthStencilBufferFormat( g_DeviceSettings.d3d9.pp.AutoDepthStencilFormat ); + AddMultisampleType( g_DeviceSettings.d3d9.pp.MultiSampleType ); + AddMultisampleQuality( g_DeviceSettings.d3d9.pp.MultiSampleQuality ); + + if( g_DeviceSettings.d3d9.BehaviorFlags & D3DCREATE_PUREDEVICE ) + AddVertexProcessingType( D3DCREATE_PUREDEVICE ); + else if( g_DeviceSettings.d3d9.BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING ) + AddVertexProcessingType( D3DCREATE_HARDWARE_VERTEXPROCESSING ); + else if( g_DeviceSettings.d3d9.BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING ) + AddVertexProcessingType( D3DCREATE_SOFTWARE_VERTEXPROCESSING ); + else if( g_DeviceSettings.d3d9.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING ) + AddVertexProcessingType( D3DCREATE_MIXED_VERTEXPROCESSING ); + + CD3D9EnumDeviceSettingsCombo* pBestDeviceSettingsCombo = pD3DEnum->GetDeviceSettingsCombo( + g_DeviceSettings.d3d9.AdapterOrdinal, g_DeviceSettings.d3d9.DeviceType, + g_DeviceSettings.d3d9.AdapterFormat, g_DeviceSettings.d3d9.pp.BackBufferFormat, + ( g_DeviceSettings.d3d9.pp.Windowed != 0 ) ); + if( NULL == pBestDeviceSettingsCombo ) + return DXUT_ERR_MSGBOX( L"GetDeviceSettingsCombo", E_INVALIDARG ); + + // Get the adapters list from CD3D9Enumeration object + CGrowableArray * pAdapterInfoList = pD3DEnum->GetAdapterInfoList(); + + if( pAdapterInfoList->GetSize() == 0 ) + return DXUT_ERR_MSGBOX( L"CD3DSettingsDlg::OnCreatedDevice", DXUTERR_NOCOMPATIBLEDEVICES ); + + CDXUTComboBox* pAdapterCombo = m_Dialog.GetComboBox( DXUTSETTINGSDLG_ADAPTER ); + pAdapterCombo->RemoveAllItems(); + + // Add adapters + for( int iAdapter = 0; iAdapter < pAdapterInfoList->GetSize(); iAdapter++ ) + { + CD3D9EnumAdapterInfo* pAdapterInfo = pAdapterInfoList->GetAt( iAdapter ); + AddAdapter( pAdapterInfo->szUniqueDescription, pAdapterInfo->AdapterOrdinal ); + } + + pAdapterCombo->SetSelectedByData( ULongToPtr( g_DeviceSettings.d3d9.AdapterOrdinal ) ); + + hr = OnAPIVersionChanged( true ); + if( FAILED( hr ) ) + return hr; + + //m_Dialog.Refresh(); + CDXUTDialog::SetRefreshTime( ( float )DXUTGetTime() ); + break; + } + case DXUT_D3D11_DEVICE: + { + // Show all D3D11-specific controls and hide controls for all other D3D versions. + ShowControlSet( DXUT_D3D11_DEVICE ); + + CD3D11Enumeration* pD3DEnum = DXUTGetD3D11Enumeration(); + + // Fill the UI with the current settings + AddD3D11DeviceType( g_DeviceSettings.d3d11.DriverType ); + SetWindowed( FALSE != g_DeviceSettings.d3d11.sd.Windowed ); + CD3D11EnumOutputInfo* pOutputInfo = GetCurrentD3D11OutputInfo(); + AddD3D11AdapterOutput( pOutputInfo->Desc.DeviceName, g_DeviceSettings.d3d11.Output ); + + + + AddD3D11Resolution( g_DeviceSettings.d3d11.sd.BufferDesc.Width, + g_DeviceSettings.d3d11.sd.BufferDesc.Height ); + AddD3D11RefreshRate( g_DeviceSettings.d3d11.sd.BufferDesc.RefreshRate ); + AddD3D11BackBufferFormat( g_DeviceSettings.d3d11.sd.BufferDesc.Format ); + AddD3D11MultisampleCount( g_DeviceSettings.d3d11.sd.SampleDesc.Count ); + AddD3D11MultisampleQuality( g_DeviceSettings.d3d11.sd.SampleDesc.Quality ); + + CD3D11EnumDeviceSettingsCombo* pBestDeviceSettingsCombo = pD3DEnum->GetDeviceSettingsCombo( + g_DeviceSettings.d3d11.AdapterOrdinal, g_DeviceSettings.d3d11.DriverType, + g_DeviceSettings.d3d11.Output, g_DeviceSettings.d3d11.sd.BufferDesc.Format, + ( g_DeviceSettings.d3d11.sd.Windowed != 0 ) ); + + if( NULL == pBestDeviceSettingsCombo ) + return DXUT_ERR_MSGBOX( L"GetDeviceSettingsCombo", E_INVALIDARG ); + + CDXUTComboBox *pFeatureLevelBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_FEATURE_LEVEL ); + pFeatureLevelBox->RemoveAllItems(); + for (int fli = 0; fli < TOTAL_FEATURE_LEVLES; fli++) { + if (m_Levels[fli] >= g_DeviceSettings.MinimumFeatureLevel + && m_Levels[fli] <=pBestDeviceSettingsCombo->pDeviceInfo->MaxLevel) { + AddD3D11FeatureLevel( m_Levels[fli] ); + } + } + pFeatureLevelBox->SetSelectedByData( ULongToPtr( g_DeviceSettings.d3d11.DeviceFeatureLevel ) ); + + + // Get the adapters list from CD3D11Enumeration object + CGrowableArray * pAdapterInfoList = pD3DEnum->GetAdapterInfoList(); + + if( pAdapterInfoList->GetSize() == 0 ) + return DXUT_ERR_MSGBOX( L"CD3DSettingsDlg::OnCreatedDevice", DXUTERR_NOCOMPATIBLEDEVICES ); + + CDXUTComboBox* pAdapterCombo = m_Dialog.GetComboBox( DXUTSETTINGSDLG_ADAPTER ); + pAdapterCombo->RemoveAllItems(); + + // Add adapters + for( int iAdapter = 0; iAdapter < pAdapterInfoList->GetSize(); iAdapter++ ) + { + CD3D11EnumAdapterInfo* pAdapterInfo = pAdapterInfoList->GetAt( iAdapter ); + AddAdapter( pAdapterInfo->szUniqueDescription, pAdapterInfo->AdapterOrdinal ); + } + + pAdapterCombo->SetSelectedByData( ULongToPtr( g_DeviceSettings.d3d11.AdapterOrdinal ) ); + + hr = OnAPIVersionChanged( true ); + if( FAILED( hr ) ) + return hr; + + //m_Dialog.Refresh(); + CDXUTDialog::SetRefreshTime( ( float )DXUTGetTime() ); + break; + } + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnD3D9ResetDevice() +{ + const D3DSURFACE_DESC* pDesc = DXUTGetD3D9BackBufferSurfaceDesc(); + m_Dialog.SetLocation( 0, 0 ); + m_Dialog.SetSize( pDesc->Width, pDesc->Height ); + m_Dialog.SetBackgroundColors( D3DCOLOR_ARGB( 255, 98, 138, 206 ), + D3DCOLOR_ARGB( 255, 54, 105, 192 ), + D3DCOLOR_ARGB( 255, 54, 105, 192 ), + D3DCOLOR_ARGB( 255, 10, 73, 179 ) ); + + m_RevertModeDialog.SetLocation( 0, 0 ); + m_RevertModeDialog.SetSize( pDesc->Width, pDesc->Height ); + m_RevertModeDialog.SetBackgroundColors( D3DCOLOR_ARGB( 255, 98, 138, 206 ), + D3DCOLOR_ARGB( 255, 54, 105, 192 ), + D3DCOLOR_ARGB( 255, 54, 105, 192 ), + D3DCOLOR_ARGB( 255, 10, 73, 179 ) ); + + IDirect3DDevice9* pd3dDevice = DXUTGetD3D9Device(); + pd3dDevice->BeginStateBlock(); + pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); + pd3dDevice->EndStateBlock( &m_pStateBlock ); + + return S_OK; +} + +//-------------------------------------------------------------------------------------- +void CD3DSettingsDlg::SetSelectedD3D11RefreshRate( DXGI_RATIONAL RefreshRate ) +{ + CDXUTComboBox* pRefreshRateComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_REFRESH_RATE ); + + for( UINT i = 0; i < pRefreshRateComboBox->GetNumItems(); ++i ) + { + DXGI_RATIONAL* pRate = ( DXGI_RATIONAL* )pRefreshRateComboBox->GetItemData( i ); + + if( pRate && pRate->Numerator == RefreshRate.Numerator && pRate->Denominator == RefreshRate.Denominator ) + { + pRefreshRateComboBox->SetSelectedByIndex( i ); + return; + } + } +} + +//-------------------------------------------------------------------------------------- +void CD3DSettingsDlg::OnRender( float fElapsedTime ) +{ + if( DXUTGetD3D11Device() ) + OnRender11( fElapsedTime ); + else + OnRender9( fElapsedTime ); +} + + +//-------------------------------------------------------------------------------------- +void CD3DSettingsDlg::OnRender9( float fElapsedTime ) +{ + IDirect3DDevice9* pd3dDevice = DXUTGetD3D9Device(); + + // Clear the render target and the zbuffer + pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, 0x00003F3F, 1.0f, 0 ); + + // Render the scene + if( SUCCEEDED( pd3dDevice->BeginScene() ) ) + { + m_pStateBlock->Capture(); + pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); + m_pActiveDialog->OnRender( fElapsedTime ); + m_pStateBlock->Apply(); + pd3dDevice->EndScene(); + } +} + + + +//-------------------------------------------------------------------------------------- +void CD3DSettingsDlg::OnRender11( float fElapsedTime ) +{ + // Render the scene + m_pActiveDialog->OnRender( fElapsedTime ); +} + + +//-------------------------------------------------------------------------------------- +LRESULT CD3DSettingsDlg::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + m_pActiveDialog->MsgProc( hWnd, uMsg, wParam, lParam ); + if( uMsg == WM_KEYDOWN && wParam == VK_F2 ) + SetActive( false ); + return 0; +} + + +//-------------------------------------------------------------------------------------- +void CD3DSettingsDlg::OnD3D9LostDevice() +{ + SAFE_RELEASE( m_pStateBlock ); +} + + +//-------------------------------------------------------------------------------------- +void CD3DSettingsDlg::OnD3D9DestroyDevice() +{ +} + + + +//-------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnD3D11CreateDevice( ID3D11Device* pd3dDevice ) +{ + //HRESULT hr; + + if( pd3dDevice == NULL ) + return DXUT_ERR_MSGBOX( L"CD3DSettingsDlg::OnCreatedDevice", E_INVALIDARG ); + + // Create the fonts/textures + m_Dialog.SetCallback( StaticOnEvent, ( void* )this ); + m_RevertModeDialog.SetCallback( StaticOnEvent, ( void* )this ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, + const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc ) +{ + m_Dialog.SetLocation( 0, 0 ); + m_Dialog.SetSize( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height ); + m_Dialog.SetBackgroundColors( D3DCOLOR_ARGB( 255, 98, 138, 206 ), + D3DCOLOR_ARGB( 255, 54, 105, 192 ), + D3DCOLOR_ARGB( 255, 54, 105, 192 ), + D3DCOLOR_ARGB( 255, 10, 73, 179 ) ); + + m_RevertModeDialog.SetLocation( 0, 0 ); + m_RevertModeDialog.SetSize( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height ); + m_RevertModeDialog.SetBackgroundColors( D3DCOLOR_ARGB( 255, 98, 138, 206 ), + D3DCOLOR_ARGB( 255, 54, 105, 192 ), + D3DCOLOR_ARGB( 255, 54, 105, 192 ), + D3DCOLOR_ARGB( 255, 10, 73, 179 ) ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +void CD3DSettingsDlg::OnD3D11DestroyDevice() +{ + + +} + +//-------------------------------------------------------------------------------------- +void CD3DSettingsDlg::ShowControlSet( DXUTDeviceVersion ver ) +{ + switch( ver ) + { + case DXUT_D3D9_DEVICE: + + m_Dialog.GetControl( DXUTSETTINGSDLG_ADAPTER_FORMAT )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_ADAPTER_FORMAT_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_RESOLUTION )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_RESOLUTION_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_REFRESH_RATE )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_REFRESH_RATE_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_BACK_BUFFER_FORMAT )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_BACK_BUFFER_FORMAT_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_DEPTH_STENCIL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_DEPTH_STENCIL_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_MULTISAMPLE_TYPE )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_MULTISAMPLE_TYPE_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_MULTISAMPLE_QUALITY )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_MULTISAMPLE_QUALITY_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_VERTEX_PROCESSING )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_VERTEX_PROCESSING_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_PRESENT_INTERVAL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_PRESENT_INTERVAL_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_DEVICECLIP )->SetVisible( true ); + + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_FEATURE_LEVEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_FEATURE_LEVEL_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_ADAPTER_OUTPUT )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_ADAPTER_OUTPUT_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_RESOLUTION )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_RESOLUTION_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_REFRESH_RATE )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_REFRESH_RATE_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_BACK_BUFFER_FORMAT )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_BACK_BUFFER_FORMAT_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_COUNT )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_COUNT_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_QUALITY )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_QUALITY_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_PRESENT_INTERVAL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_PRESENT_INTERVAL_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_DEBUG_DEVICE )->SetVisible( false ); + + break; + + case DXUT_D3D11_DEVICE: + m_Dialog.GetControl( DXUTSETTINGSDLG_ADAPTER_FORMAT )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_ADAPTER_FORMAT_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_FEATURE_LEVEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_FEATURE_LEVEL_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_RESOLUTION )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_RESOLUTION_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_REFRESH_RATE )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_REFRESH_RATE_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_BACK_BUFFER_FORMAT )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_BACK_BUFFER_FORMAT_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_DEPTH_STENCIL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_DEPTH_STENCIL_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_MULTISAMPLE_TYPE )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_MULTISAMPLE_TYPE_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_MULTISAMPLE_QUALITY )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_MULTISAMPLE_QUALITY_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_VERTEX_PROCESSING )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_VERTEX_PROCESSING_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_PRESENT_INTERVAL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_PRESENT_INTERVAL_LABEL )->SetVisible( false ); + m_Dialog.GetControl( DXUTSETTINGSDLG_DEVICECLIP )->SetVisible( false ); + + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_ADAPTER_OUTPUT )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_ADAPTER_OUTPUT_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_RESOLUTION )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_RESOLUTION_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_REFRESH_RATE )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_REFRESH_RATE_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_BACK_BUFFER_FORMAT )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_BACK_BUFFER_FORMAT_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_COUNT )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_COUNT_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_QUALITY )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_QUALITY_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_PRESENT_INTERVAL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_PRESENT_INTERVAL_LABEL )->SetVisible( true ); + m_Dialog.GetControl( DXUTSETTINGSDLG_D3D11_DEBUG_DEVICE )->SetVisible( true ); + break; + } +} + + +//-------------------------------------------------------------------------------------- +void WINAPI CD3DSettingsDlg::StaticOnEvent( UINT nEvent, int nControlID, + CDXUTControl* pControl, void* pUserData ) +{ + CD3DSettingsDlg* pD3DSettings = ( CD3DSettingsDlg* )pUserData; + if( pD3DSettings ) + pD3DSettings->OnEvent( nEvent, nControlID, pControl ); +} + +//-------------------------------------------------------------------------------------- +// Name: CD3DSettingsDlg::StaticOnModeChangeTimer() +// Desc: Timer callback registered by a call to DXUTSetTimer. It is called each second +// until mode change timeout limit. +//-------------------------------------------------------------------------------------- +void WINAPI CD3DSettingsDlg::StaticOnModeChangeTimer( UINT nIDEvent, void* pUserContext ) +{ + CD3DSettingsDlg* pD3DSettings = ( CD3DSettingsDlg* )pUserContext; + assert( pD3DSettings ); + assert( pD3DSettings->m_pActiveDialog == &pD3DSettings->m_RevertModeDialog ); + assert( pD3DSettings->m_nIDEvent == nIDEvent ); + + if( 0 == --pD3DSettings->m_nRevertModeTimeout ) + { + CDXUTControl* pControl = pD3DSettings->m_RevertModeDialog.GetControl( DXUTSETTINGSDLG_MODE_CHANGE_REVERT ); + assert( pControl ); + pD3DSettings->m_RevertModeDialog.SendEvent( EVENT_BUTTON_CLICKED, false, pControl ); + } + pD3DSettings->UpdateModeChangeTimeoutText( pD3DSettings->m_nRevertModeTimeout ); +} + +//-------------------------------------------------------------------------------------- +void CD3DSettingsDlg::OnEvent( UINT nEvent, int nControlID, + CDXUTControl* pControl ) +{ + switch( nControlID ) + { + case DXUTSETTINGSDLG_ADAPTER: + OnAdapterChanged(); break; + case DXUTSETTINGSDLG_DEVICE_TYPE: + OnDeviceTypeChanged(); break; + case DXUTSETTINGSDLG_WINDOWED: + OnWindowedFullScreenChanged(); break; + case DXUTSETTINGSDLG_FULLSCREEN: + OnWindowedFullScreenChanged(); break; + case DXUTSETTINGSDLG_ADAPTER_FORMAT: + OnAdapterFormatChanged(); break; + case DXUTSETTINGSDLG_RESOLUTION_SHOW_ALL: + { + if( g_DeviceSettings.ver == DXUT_D3D9_DEVICE ) + { + OnAdapterFormatChanged(); + } + else + { + OnBackBufferFormatChanged(); + } + break; + } + case DXUTSETTINGSDLG_D3D11_RESOLUTION: + OnD3D11ResolutionChanged(); break; + case DXUTSETTINGSDLG_RESOLUTION: + OnResolutionChanged(); break; + case DXUTSETTINGSDLG_REFRESH_RATE: + OnRefreshRateChanged(); break; + case DXUTSETTINGSDLG_BACK_BUFFER_FORMAT: + OnBackBufferFormatChanged(); break; + case DXUTSETTINGSDLG_DEPTH_STENCIL: + OnDepthStencilBufferFormatChanged(); break; + case DXUTSETTINGSDLG_MULTISAMPLE_TYPE: + OnMultisampleTypeChanged(); break; + case DXUTSETTINGSDLG_MULTISAMPLE_QUALITY: + OnMultisampleQualityChanged(); break; + case DXUTSETTINGSDLG_VERTEX_PROCESSING: + OnVertexProcessingChanged(); break; + case DXUTSETTINGSDLG_PRESENT_INTERVAL: + OnPresentIntervalChanged(); break; + case DXUTSETTINGSDLG_DEVICECLIP: + OnDeviceClipChanged(); break; + case DXUTSETTINGSDLG_API_VERSION: + OnAPIVersionChanged(); break; + case DXUTSETTINGSDLG_D3D11_FEATURE_LEVEL: + OnFeatureLevelChanged(); break; + case DXUTSETTINGSDLG_D3D11_ADAPTER_OUTPUT: + OnAdapterOutputChanged(); break; + case DXUTSETTINGSDLG_D3D11_REFRESH_RATE: + OnRefreshRateChanged(); break; + case DXUTSETTINGSDLG_D3D11_BACK_BUFFER_FORMAT: + OnBackBufferFormatChanged(); break; + case DXUTSETTINGSDLG_D3D11_MULTISAMPLE_COUNT: + OnMultisampleTypeChanged(); break; + case DXUTSETTINGSDLG_D3D11_MULTISAMPLE_QUALITY: + OnMultisampleQualityChanged(); break; + case DXUTSETTINGSDLG_D3D11_PRESENT_INTERVAL: + OnPresentIntervalChanged(); break; + case DXUTSETTINGSDLG_D3D11_DEBUG_DEVICE: + OnDebugDeviceChanged(); break; + + case DXUTSETTINGSDLG_OK: + { + bool bFullScreenModeChange = false; + DXUTDeviceSettings currentSettings = DXUTGetDeviceSettings(); + g_DeviceSettings.MinimumFeatureLevel = currentSettings.MinimumFeatureLevel; + if( g_DeviceSettings.ver == DXUT_D3D9_DEVICE ) + { + if( g_DeviceSettings.d3d9.pp.Windowed ) + { + g_DeviceSettings.d3d9.pp.FullScreen_RefreshRateInHz = 0; + + RECT rcClient; + if( DXUTIsWindowed() ) + GetClientRect( DXUTGetHWND(), &rcClient ); + else + rcClient = DXUTGetWindowClientRectAtModeChange(); + DWORD dwWindowWidth = rcClient.right - rcClient.left; + DWORD dwWindowHeight = rcClient.bottom - rcClient.top; + + g_DeviceSettings.d3d9.pp.BackBufferWidth = dwWindowWidth; + g_DeviceSettings.d3d9.pp.BackBufferHeight = dwWindowHeight; + } + else + { + // Check for fullscreen mode change + bFullScreenModeChange = g_DeviceSettings.d3d9.pp.BackBufferWidth != + currentSettings.d3d9.pp.BackBufferWidth || + g_DeviceSettings.d3d9.pp.BackBufferHeight != currentSettings.d3d9.pp.BackBufferHeight || + g_DeviceSettings.d3d9.pp.FullScreen_RefreshRateInHz != + currentSettings.d3d9.pp.FullScreen_RefreshRateInHz; + } + + if( g_DeviceSettings.d3d9.pp.MultiSampleType != D3DMULTISAMPLE_NONE ) + { + g_DeviceSettings.d3d9.pp.Flags &= ~D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; + } + } + else // D3D11 + { + if( g_DeviceSettings.d3d11.sd.Windowed ) + { + g_DeviceSettings.d3d11.sd.BufferDesc.RefreshRate.Denominator = + g_DeviceSettings.d3d11.sd.BufferDesc.RefreshRate.Numerator = 0; + + RECT rcClient; + if( DXUTIsWindowed() ) + GetClientRect( DXUTGetHWND(), &rcClient ); + else + rcClient = DXUTGetWindowClientRectAtModeChange(); + DWORD dwWindowWidth = rcClient.right - rcClient.left; + DWORD dwWindowHeight = rcClient.bottom - rcClient.top; + + g_DeviceSettings.d3d11.sd.BufferDesc.Width = dwWindowWidth; + g_DeviceSettings.d3d11.sd.BufferDesc.Height = dwWindowHeight; + } + else + { + // Check for fullscreen mode change + bFullScreenModeChange = g_DeviceSettings.d3d11.sd.BufferDesc.Width != + currentSettings.d3d11.sd.BufferDesc.Width || + g_DeviceSettings.d3d11.sd.BufferDesc.Height != currentSettings.d3d11.sd.BufferDesc.Height || + g_DeviceSettings.d3d11.sd.BufferDesc.RefreshRate.Denominator != + currentSettings.d3d11.sd.BufferDesc.RefreshRate.Denominator || + g_DeviceSettings.d3d11.sd.BufferDesc.RefreshRate.Numerator != + currentSettings.d3d11.sd.BufferDesc.RefreshRate.Numerator; + } + } + + if( bFullScreenModeChange ) + { + // set appropriate global device settings to that of the current device + // settings. These will get set to the user-defined settings once the + // user accepts the mode change + DXUTDeviceSettings tSettings = g_DeviceSettings; + if( g_DeviceSettings.ver == DXUT_D3D9_DEVICE ) + { + g_DeviceSettings.d3d9.pp.BackBufferWidth = + currentSettings.d3d9.pp.BackBufferWidth; + g_DeviceSettings.d3d9.pp.BackBufferHeight = + currentSettings.d3d9.pp.BackBufferHeight; + g_DeviceSettings.d3d9.pp.FullScreen_RefreshRateInHz = + currentSettings.d3d9.pp.FullScreen_RefreshRateInHz; + g_DeviceSettings.d3d9.pp.Windowed = + currentSettings.d3d9.pp.Windowed; + } + else + { + + g_DeviceSettings.d3d11.sd.BufferDesc.Width = + currentSettings.d3d11.sd.BufferDesc.Width; + g_DeviceSettings.d3d11.sd.BufferDesc.Height = + currentSettings.d3d11.sd.BufferDesc.Height; + g_DeviceSettings.d3d11.sd.BufferDesc.RefreshRate.Denominator = + currentSettings.d3d11.sd.BufferDesc.RefreshRate.Denominator; + g_DeviceSettings.d3d11.sd.BufferDesc.RefreshRate.Numerator = + currentSettings.d3d11.sd.BufferDesc.RefreshRate.Numerator; + g_DeviceSettings.d3d11.sd.Windowed = currentSettings.d3d11.sd.Windowed; + + } + + // apply the user-defined settings + DXUTCreateDeviceFromSettings( &tSettings ); + // create the mode change timeout dialog + m_pActiveDialog = &m_RevertModeDialog; + m_nRevertModeTimeout = 15; + UpdateModeChangeTimeoutText( m_nRevertModeTimeout ); + // activate a timer for 1-second updates + DXUTSetTimer( StaticOnModeChangeTimer, 1.0f, &m_nIDEvent, ( void* )this ); + } + else + { + DXUTCreateDeviceFromSettings( &g_DeviceSettings ); + SetActive( false ); + } + break; + } + + case DXUTSETTINGSDLG_CANCEL: + { + SetActive( false ); + break; + } + + case DXUTSETTINGSDLG_MODE_CHANGE_ACCEPT: + { + DXUTKillTimer( m_nIDEvent ); + g_DeviceSettings = DXUTGetDeviceSettings(); + m_pActiveDialog = &m_Dialog; + SetActive( false ); + break; + } + + case DXUTSETTINGSDLG_MODE_CHANGE_REVERT: + { + DXUTKillTimer( m_nIDEvent ); + m_pActiveDialog = &m_Dialog; + m_nIDEvent = 0; + m_nRevertModeTimeout = 0; + DXUTCreateDeviceFromSettings( &g_DeviceSettings ); + Refresh(); + break; + } + } +} + + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::SetDeviceSettingsFromUI() +{ + CDXUTComboBox* pComboBox; + CDXUTRadioButton* pRadioButton; + + // DXUTSETTINGSDLG_DEVICE_TYPE + pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_DEVICE_TYPE ); + g_DeviceSettings.d3d9.DeviceType = ( D3DDEVTYPE )PtrToUlong( pComboBox->GetSelectedData() ); + + // DXUTSETTINGSDLG_WINDOWED + pRadioButton = m_Dialog.GetRadioButton( DXUTSETTINGSDLG_WINDOWED ); + g_DeviceSettings.d3d9.pp.Windowed = pRadioButton->GetChecked(); + + // DXUTSETTINGSDLG_ADAPTER_FORMAT + pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_ADAPTER_FORMAT ); + g_DeviceSettings.d3d9.AdapterFormat = ( D3DFORMAT )PtrToUlong( pComboBox->GetSelectedData() ); + + if( g_DeviceSettings.d3d9.pp.Windowed ) + { + g_DeviceSettings.d3d9.pp.BackBufferFormat = D3DFMT_UNKNOWN; + g_DeviceSettings.d3d9.pp.FullScreen_RefreshRateInHz = 0; + } + else + { + // DXUTSETTINGSDLG_BACK_BUFFER_FORMAT + pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_BACK_BUFFER_FORMAT ); + g_DeviceSettings.d3d9.pp.BackBufferFormat = ( D3DFORMAT )PtrToUlong( pComboBox->GetSelectedData() ); + + // DXUTSETTINGSDLG_RESOLUTION + pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_RESOLUTION ); + DWORD dwResolution = PtrToUlong( pComboBox->GetSelectedData() ); + g_DeviceSettings.d3d9.pp.BackBufferWidth = HIWORD( dwResolution ); + g_DeviceSettings.d3d9.pp.BackBufferHeight = LOWORD( dwResolution ); + + // DXUTSETTINGSDLG_REFRESH_RATE + pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_REFRESH_RATE ); + g_DeviceSettings.d3d9.pp.FullScreen_RefreshRateInHz = PtrToUlong( pComboBox->GetSelectedData() ); + } + + // DXUTSETTINGSDLG_DEPTH_STENCIL + pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_DEPTH_STENCIL ); + g_DeviceSettings.d3d9.pp.AutoDepthStencilFormat = ( D3DFORMAT )PtrToUlong( pComboBox->GetSelectedData() ); + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +CD3D9EnumAdapterInfo* CD3DSettingsDlg::GetCurrentAdapterInfo() +{ + CD3D9Enumeration* pD3DEnum = DXUTGetD3D9Enumeration(); + return pD3DEnum->GetAdapterInfo( g_DeviceSettings.d3d9.AdapterOrdinal ); +} + + +//------------------------------------------------------------------------------------- +CD3D9EnumDeviceInfo* CD3DSettingsDlg::GetCurrentDeviceInfo() +{ + CD3D9Enumeration* pD3DEnum = DXUTGetD3D9Enumeration(); + return pD3DEnum->GetDeviceInfo( g_DeviceSettings.d3d9.AdapterOrdinal, + g_DeviceSettings.d3d9.DeviceType ); +} + +//------------------------------------------------------------------------------------- +CD3D11EnumAdapterInfo* CD3DSettingsDlg::GetCurrentD3D11AdapterInfo() +{ + CD3D11Enumeration* pD3DEnum = DXUTGetD3D11Enumeration(); + return pD3DEnum->GetAdapterInfo( g_DeviceSettings.d3d11.AdapterOrdinal ); +} + + +//------------------------------------------------------------------------------------- +CD3D11EnumDeviceInfo* CD3DSettingsDlg::GetCurrentD3D11DeviceInfo() +{ + CD3D11Enumeration* pD3DEnum = DXUTGetD3D11Enumeration(); + return pD3DEnum->GetDeviceInfo( g_DeviceSettings.d3d11.AdapterOrdinal, + g_DeviceSettings.d3d11.DriverType ); +} + + +//------------------------------------------------------------------------------------- +CD3D11EnumOutputInfo* CD3DSettingsDlg::GetCurrentD3D11OutputInfo() +{ + CD3D11Enumeration* pD3DEnum = DXUTGetD3D11Enumeration(); + return pD3DEnum->GetOutputInfo( g_DeviceSettings.d3d11.AdapterOrdinal, + g_DeviceSettings.d3d11.Output ); +} + + +//------------------------------------------------------------------------------------- +CD3D9EnumDeviceSettingsCombo* CD3DSettingsDlg::GetCurrentDeviceSettingsCombo() +{ + CD3D9Enumeration* pD3DEnum = DXUTGetD3D9Enumeration(); + return pD3DEnum->GetDeviceSettingsCombo( g_DeviceSettings.d3d9.AdapterOrdinal, + g_DeviceSettings.d3d9.DeviceType, + g_DeviceSettings.d3d9.AdapterFormat, + g_DeviceSettings.d3d9.pp.BackBufferFormat, + ( g_DeviceSettings.d3d9.pp.Windowed == TRUE ) ); +} + +//------------------------------------------------------------------------------------- +CD3D11EnumDeviceSettingsCombo* CD3DSettingsDlg::GetCurrentD3D11DeviceSettingsCombo() +{ + CD3D11Enumeration* pD3DEnum = DXUTGetD3D11Enumeration(); + return pD3DEnum->GetDeviceSettingsCombo( g_DeviceSettings.d3d11.AdapterOrdinal, + g_DeviceSettings.d3d11.DriverType, + g_DeviceSettings.d3d11.Output, + g_DeviceSettings.d3d11.sd.BufferDesc.Format, + ( g_DeviceSettings.d3d11.sd.Windowed == TRUE ) ); +} + +HRESULT CD3DSettingsDlg::OnD3D11ResolutionChanged () { + DWORD dwWidth, dwHeight; + GetSelectedD3D11Resolution( &dwWidth, &dwHeight ); + g_DeviceSettings.d3d11.sd.BufferDesc.Width= dwWidth; + g_DeviceSettings.d3d11.sd.BufferDesc.Height = dwHeight; + + return S_OK; +} + +HRESULT CD3DSettingsDlg::OnFeatureLevelChanged () { + HRESULT hr = E_FAIL; + if (g_DeviceSettings.ver == DXUT_D3D11_DEVICE) { + if (g_DeviceSettings.d3d11.DeviceFeatureLevel == GetSelectedFeatureLevel()) return S_OK; + //if( !bRefresh ) + //{ + // Obtain a set of valid D3D10 device settings. + UINT CreateFlags = g_DeviceSettings.d3d11.CreateFlags; + ZeroMemory( &g_DeviceSettings, sizeof( g_DeviceSettings ) ); + + DXUTApplyDefaultDeviceSettings(&g_DeviceSettings); + g_DeviceSettings.d3d11.CreateFlags = CreateFlags; + g_DeviceSettings.ver = DXUT_D3D11_DEVICE; + //g_DeviceSettings.d3d11.fl = GetSelectedFeatureLevel(); + hr = DXUTSnapDeviceSettingsToEnumDevice(&g_DeviceSettings, true, GetSelectedFeatureLevel()); + + //} + + CD3D11Enumeration* pD3DEnum = DXUTGetD3D11Enumeration(); + CGrowableArray * pAdapterInfoList = pD3DEnum->GetAdapterInfoList(); + + CDXUTComboBox* pAdapterComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_ADAPTER ); + pAdapterComboBox->RemoveAllItems(); + + for( int iAdapter = 0; iAdapter < pAdapterInfoList->GetSize(); ++iAdapter ) + { + CD3D11EnumAdapterInfo* pAdapterInfo = pAdapterInfoList->GetAt( iAdapter ); + AddAdapter( pAdapterInfo->szUniqueDescription, pAdapterInfo->AdapterOrdinal ); + } + + pAdapterComboBox->SetSelectedByData( ULongToPtr( g_DeviceSettings.d3d11.AdapterOrdinal ) ); + + CDXUTCheckBox* pCheckBox = m_Dialog.GetCheckBox( DXUTSETTINGSDLG_D3D11_DEBUG_DEVICE ); + pCheckBox->SetChecked( 0 != ( g_DeviceSettings.d3d11.CreateFlags & D3D11_CREATE_DEVICE_DEBUG ) ); + + hr = OnAdapterChanged(); + if( FAILED( hr ) ) + return hr; + } + + return hr; +} + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnAPIVersionChanged( bool bRefresh ) +{ + HRESULT hr; + + // Store the API version + g_DeviceSettings.ver = GetSelectedAPIVersion(); + + // Show/hide appropriate dialog controls based on version. + ShowControlSet( g_DeviceSettings.ver ); + + switch( g_DeviceSettings.ver ) + { + case DXUT_D3D9_DEVICE: + { + if( !bRefresh ) + { + // Obtain a set of valid D3D9 device settings. + UINT CreateFlags = g_DeviceSettings.d3d11.CreateFlags; + ZeroMemory( &g_DeviceSettings, sizeof( g_DeviceSettings ) ); + // We want a specific API version, so set up match option to preserve it. + DXUTApplyDefaultDeviceSettings(&g_DeviceSettings); + g_DeviceSettings.d3d11.CreateFlags = CreateFlags; + g_DeviceSettings.ver = DXUT_D3D9_DEVICE; + DXUTSnapDeviceSettingsToEnumDevice ( &g_DeviceSettings, true); + } + + CD3D9Enumeration* pD3DEnum = DXUTGetD3D9Enumeration(); + CGrowableArray * pAdapterInfoList = pD3DEnum->GetAdapterInfoList(); + + CDXUTComboBox* pAdapterComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_ADAPTER ); + pAdapterComboBox->RemoveAllItems(); + + for( int iAdapter = 0; iAdapter < pAdapterInfoList->GetSize(); ++iAdapter ) + { + CD3D9EnumAdapterInfo* pAdapterInfo = pAdapterInfoList->GetAt( iAdapter ); + AddAdapter( pAdapterInfo->szUniqueDescription, pAdapterInfo->AdapterOrdinal ); + } + + pAdapterComboBox->SetSelectedByData( ULongToPtr( g_DeviceSettings.d3d9.AdapterOrdinal ) ); + + hr = OnAdapterChanged(); + if( FAILED( hr ) ) + return hr; + + break; + } + + case DXUT_D3D11_DEVICE: + { + if( !bRefresh ) + { + // Obtain a set of valid D3D10 device settings. + UINT CreateFlags = g_DeviceSettings.d3d11.CreateFlags; + ZeroMemory( &g_DeviceSettings, sizeof( g_DeviceSettings ) ); + // We want a specific API version, so set up match option to preserve it. + DXUTApplyDefaultDeviceSettings(&g_DeviceSettings); + g_DeviceSettings.d3d11.CreateFlags = CreateFlags; + g_DeviceSettings.ver = DXUT_D3D11_DEVICE; + DXUTSnapDeviceSettingsToEnumDevice(&g_DeviceSettings, true); + + } + + CD3D11Enumeration* pD3DEnum = DXUTGetD3D11Enumeration(); + CGrowableArray * pAdapterInfoList = pD3DEnum->GetAdapterInfoList(); + + CDXUTComboBox* pAdapterComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_ADAPTER ); + pAdapterComboBox->RemoveAllItems(); + + for( int iAdapter = 0; iAdapter < pAdapterInfoList->GetSize(); ++iAdapter ) + { + CD3D11EnumAdapterInfo* pAdapterInfo = pAdapterInfoList->GetAt( iAdapter ); + AddAdapter( pAdapterInfo->szUniqueDescription, pAdapterInfo->AdapterOrdinal ); + } + + pAdapterComboBox->SetSelectedByData( ULongToPtr( g_DeviceSettings.d3d11.AdapterOrdinal ) ); + + CDXUTCheckBox* pCheckBox = m_Dialog.GetCheckBox( DXUTSETTINGSDLG_D3D11_DEBUG_DEVICE ); + pCheckBox->SetChecked( 0 != ( g_DeviceSettings.d3d11.CreateFlags & D3D11_CREATE_DEVICE_DEBUG ) ); + + hr = OnAdapterChanged(); + if( FAILED( hr ) ) + return hr; + + break; + } + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnAdapterChanged() +{ + HRESULT hr = S_OK; + + switch( g_DeviceSettings.ver ) + { + case DXUT_D3D9_DEVICE: + { + // Store the adapter index + g_DeviceSettings.d3d9.AdapterOrdinal = GetSelectedAdapter(); + + // DXUTSETTINGSDLG_DEVICE_TYPE + CDXUTComboBox* pDeviceTypeComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_DEVICE_TYPE ); + pDeviceTypeComboBox->RemoveAllItems(); + + CD3D9EnumAdapterInfo* pAdapterInfo = GetCurrentAdapterInfo(); + if( pAdapterInfo == NULL ) + return E_FAIL; + + for( int iDeviceInfo = 0; iDeviceInfo < pAdapterInfo->deviceInfoList.GetSize(); iDeviceInfo++ ) + { + CD3D9EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( iDeviceInfo ); + AddDeviceType( pDeviceInfo->DeviceType ); + } + + pDeviceTypeComboBox->SetSelectedByData( ULongToPtr( g_DeviceSettings.d3d9.DeviceType ) ); + + hr = OnDeviceTypeChanged(); + if( FAILED( hr ) ) + return hr; + + break; + } + + case DXUT_D3D11_DEVICE: + { + // Store the adapter index + g_DeviceSettings.d3d11.AdapterOrdinal = GetSelectedAdapter(); + + // DXUTSETTINGSDLG_DEVICE_TYPE + CDXUTComboBox* pDeviceTypeComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_DEVICE_TYPE ); + pDeviceTypeComboBox->RemoveAllItems(); + + CD3D11EnumAdapterInfo* pAdapterInfo = GetCurrentD3D11AdapterInfo(); + if( pAdapterInfo == NULL ) + return E_FAIL; + + for( int iDeviceInfo = 0; iDeviceInfo < pAdapterInfo->deviceInfoList.GetSize(); iDeviceInfo++ ) + { + CD3D11EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( iDeviceInfo ); + AddD3D11DeviceType( pDeviceInfo->DeviceType ); + } + + pDeviceTypeComboBox->SetSelectedByData( ULongToPtr( g_DeviceSettings.d3d11.DriverType ) ); + + hr = OnDeviceTypeChanged(); + if( FAILED( hr ) ) + return hr; + + break; + } + } + + return S_OK; +} + + + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnDeviceTypeChanged() +{ + HRESULT hr = S_OK; + + switch( g_DeviceSettings.ver ) + { + case DXUT_D3D9_DEVICE: + { + g_DeviceSettings.d3d9.DeviceType = GetSelectedDeviceType(); + + // Update windowed/full screen radio buttons + bool bHasWindowedDeviceCombo = false; + bool bHasFullScreenDeviceCombo = false; + + CD3D9EnumDeviceInfo* pDeviceInfo = GetCurrentDeviceInfo(); + if( pDeviceInfo == NULL ) + return E_FAIL; + + for( int idc = 0; idc < pDeviceInfo->deviceSettingsComboList.GetSize(); idc++ ) + { + CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo = pDeviceInfo->deviceSettingsComboList.GetAt( idc ); + + if( pDeviceSettingsCombo->Windowed ) + bHasWindowedDeviceCombo = true; + else + bHasFullScreenDeviceCombo = true; + } + + // DXUTSETTINGSDLG_WINDOWED, DXUTSETTINGSDLG_FULLSCREEN + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_WINDOWED, bHasWindowedDeviceCombo ); + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_FULLSCREEN, bHasFullScreenDeviceCombo ); + + SetWindowed( g_DeviceSettings.d3d9.pp.Windowed && bHasWindowedDeviceCombo ); + + hr = OnWindowedFullScreenChanged(); + if( FAILED( hr ) ) + return hr; + + break; + } + case DXUT_D3D11_DEVICE: + { + g_DeviceSettings.d3d11.DriverType = GetSelectedD3D11DeviceType(); + + // DXUTSETTINGSDLG_WINDOWED, DXUTSETTINGSDLG_FULLSCREEN + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_WINDOWED, true ); + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_FULLSCREEN, true ); + + SetWindowed( g_DeviceSettings.d3d11.sd.Windowed != 0 ); + + hr = OnWindowedFullScreenChanged(); + if( FAILED( hr ) ) + return hr; + + break; + } + } + + return S_OK; +} + + + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnWindowedFullScreenChanged() +{ + HRESULT hr = S_OK; + bool bWindowed = IsWindowed(); + + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_ADAPTER_FORMAT_LABEL, !bWindowed ); + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_RESOLUTION_LABEL, !bWindowed ); + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_REFRESH_RATE_LABEL, !bWindowed ); + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_D3D11_ADAPTER_OUTPUT_LABEL, !bWindowed ); + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_D3D11_RESOLUTION_LABEL, !bWindowed ); + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_D3D11_REFRESH_RATE_LABEL, !bWindowed ); + + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_ADAPTER_FORMAT, !bWindowed ); + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_RESOLUTION, !bWindowed ); + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_RESOLUTION_SHOW_ALL, !bWindowed ); + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_REFRESH_RATE, !bWindowed ); + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_DEVICECLIP, bWindowed ); + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_D3D11_ADAPTER_OUTPUT, !bWindowed ); + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_D3D11_RESOLUTION, !bWindowed ); + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_D3D11_REFRESH_RATE, !bWindowed ); + + switch( g_DeviceSettings.ver ) + { + case DXUT_D3D9_DEVICE: + { + g_DeviceSettings.d3d9.pp.Windowed = bWindowed; + bool bDeviceClip = ( 0x0 != ( g_DeviceSettings.d3d9.pp.Flags & D3DPRESENTFLAG_DEVICECLIP ) ); + + // If windowed, get the appropriate adapter format from Direct3D + if( g_DeviceSettings.d3d9.pp.Windowed ) + { + IDirect3D9* pD3D = DXUTGetD3D9Object(); + if( pD3D == NULL ) + return DXTRACE_ERR( L"DXUTGetD3DObject", E_FAIL ); + + D3DDISPLAYMODE mode; + hr = pD3D->GetAdapterDisplayMode( g_DeviceSettings.d3d9.AdapterOrdinal, &mode ); + if( FAILED( hr ) ) + return DXTRACE_ERR( L"GetAdapterDisplayMode", hr ); + + // Default resolution to the fullscreen res that was last used + RECT rc = DXUTGetFullsceenClientRectAtModeChange(); + if( rc.right == 0 || rc.bottom == 0 ) + { + // If nothing last used, then default to the adapter desktop res + g_DeviceSettings.d3d9.pp.BackBufferWidth = mode.Width; + g_DeviceSettings.d3d9.pp.BackBufferHeight = mode.Height; + } + else + { + g_DeviceSettings.d3d9.pp.BackBufferWidth = rc.right; + g_DeviceSettings.d3d9.pp.BackBufferHeight = rc.bottom; + } + + g_DeviceSettings.d3d9.AdapterFormat = mode.Format; + g_DeviceSettings.d3d9.pp.FullScreen_RefreshRateInHz = mode.RefreshRate; + } + + const D3DFORMAT adapterFormat = g_DeviceSettings.d3d9.AdapterFormat; + const DWORD dwWidth = g_DeviceSettings.d3d9.pp.BackBufferWidth; + const DWORD dwHeight = g_DeviceSettings.d3d9.pp.BackBufferHeight; + const DWORD dwRefreshRate = g_DeviceSettings.d3d9.pp.FullScreen_RefreshRateInHz; + + // DXUTSETTINGSDLG_DEVICECLIP + SetDeviceClip( bDeviceClip ); + + // DXUTSETTINGSDLG_ADAPTER_FORMAT + CDXUTComboBox* pAdapterFormatComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_ADAPTER_FORMAT ); + if( pAdapterFormatComboBox == NULL ) + return E_FAIL; + pAdapterFormatComboBox->RemoveAllItems(); + + CD3D9EnumDeviceInfo* pDeviceInfo = GetCurrentDeviceInfo(); + if( pDeviceInfo == NULL ) + return E_FAIL; + + if( bWindowed ) + { + AddAdapterFormat( adapterFormat ); + } + else + { + for( int iSettingsCombo = 0; iSettingsCombo < pDeviceInfo->deviceSettingsComboList.GetSize(); + iSettingsCombo++ ) + { + CD3D9EnumDeviceSettingsCombo* pSettingsCombo = pDeviceInfo->deviceSettingsComboList.GetAt( + iSettingsCombo ); + AddAdapterFormat( pSettingsCombo->AdapterFormat ); + } + } + + pAdapterFormatComboBox->SetSelectedByData( ULongToPtr( adapterFormat ) ); + + hr = OnAdapterFormatChanged(); + if( FAILED( hr ) ) + return hr; + + // DXUTSETTINGSDLG_RESOLUTION + CDXUTComboBox* pResolutionComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_RESOLUTION ); + + if( bWindowed ) + { + pResolutionComboBox->RemoveAllItems(); + AddResolution( dwWidth, dwHeight ); + } + + pResolutionComboBox->SetSelectedByData( ULongToPtr( MAKELONG( dwWidth, dwHeight ) ) ); + + hr = OnResolutionChanged(); + if( FAILED( hr ) ) + return hr; + + // DXUTSETTINGSDLG_REFRESH_RATE + CDXUTComboBox* pRefreshRateComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_REFRESH_RATE ); + + if( bWindowed ) + { + pRefreshRateComboBox->RemoveAllItems(); + AddRefreshRate( dwRefreshRate ); + } + + pRefreshRateComboBox->SetSelectedByData( ULongToPtr( dwRefreshRate ) ); + + hr = OnRefreshRateChanged(); + if( FAILED( hr ) ) + return hr; + + break; + } + + case DXUT_D3D11_DEVICE: + { + g_DeviceSettings.d3d11.sd.Windowed = bWindowed; + + // Get available adapter output + CD3D11Enumeration* pD3DEnum = DXUTGetD3D11Enumeration(); + + CDXUTComboBox* pOutputComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_ADAPTER_OUTPUT ); + pOutputComboBox->RemoveAllItems(); + + CD3D11EnumAdapterInfo* pAdapterInfo = pD3DEnum->GetAdapterInfo( g_DeviceSettings.d3d11.AdapterOrdinal ); + for( int ioutput = 0; ioutput < pAdapterInfo->outputInfoList.GetSize(); ++ioutput ) + { + CD3D11EnumOutputInfo* pOutputInfo = pAdapterInfo->outputInfoList.GetAt( ioutput ); + AddD3D11AdapterOutput( pOutputInfo->Desc.DeviceName, pOutputInfo->Output ); + } + + pOutputComboBox->SetSelectedByData( ULongToPtr( g_DeviceSettings.d3d11.Output ) ); + + hr = OnAdapterOutputChanged(); + if( FAILED( hr ) ) + return hr; + + break; + } + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnAdapterOutputChanged() +{ + HRESULT hr; + + switch( g_DeviceSettings.ver ) + { + case DXUT_D3D11_DEVICE: + { + bool bWindowed = IsWindowed(); + g_DeviceSettings.d3d11.sd.Windowed = bWindowed; + + // If windowed, get the appropriate adapter format from Direct3D + if( g_DeviceSettings.d3d11.sd.Windowed ) + { + DXGI_MODE_DESC mode; + hr = DXUTGetD3D11AdapterDisplayMode( g_DeviceSettings.d3d11.AdapterOrdinal, + g_DeviceSettings.d3d11.Output, &mode ); + if( FAILED( hr ) ) + return DXTRACE_ERR( L"GetD3D11AdapterDisplayMode", hr ); + + // Default resolution to the fullscreen res that was last used + RECT rc = DXUTGetFullsceenClientRectAtModeChange(); + if( rc.right == 0 || rc.bottom == 0 ) + { + // If nothing last used, then default to the adapter desktop res + g_DeviceSettings.d3d11.sd.BufferDesc.Width = mode.Width; + g_DeviceSettings.d3d11.sd.BufferDesc.Height = mode.Height; + } + else + { + g_DeviceSettings.d3d11.sd.BufferDesc.Width = rc.right; + g_DeviceSettings.d3d11.sd.BufferDesc.Height = rc.bottom; + } + + g_DeviceSettings.d3d11.sd.BufferDesc.RefreshRate = mode.RefreshRate; + } + + const DXGI_RATIONAL RefreshRate = g_DeviceSettings.d3d11.sd.BufferDesc.RefreshRate; + + CD3D11EnumAdapterInfo* pAdapterInfo = GetCurrentD3D11AdapterInfo(); + if( pAdapterInfo == NULL ) + return E_FAIL; + + // DXUTSETTINGSDLG_D3D11_RESOLUTION + hr = UpdateD3D11Resolutions(); + if( FAILED( hr ) ) + return hr; + + // DXUTSETTINGSDLG_D3D11_BACK_BUFFER_FORMAT + CDXUTComboBox* pBackBufferFormatComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_BACK_BUFFER_FORMAT + ); + pBackBufferFormatComboBox->RemoveAllItems(); + + for( int idc = 0; idc < pAdapterInfo->deviceSettingsComboList.GetSize(); idc++ ) + { + CD3D11EnumDeviceSettingsCombo* pDeviceCombo = pAdapterInfo->deviceSettingsComboList.GetAt( idc ); + if( ( pDeviceCombo->Windowed == TRUE ) == bWindowed ) + { + AddD3D11BackBufferFormat( pDeviceCombo->BackBufferFormat ); + } + } + + pBackBufferFormatComboBox->SetSelectedByData( ULongToPtr( g_DeviceSettings.d3d11.sd.BufferDesc.Format ) ); + + hr = OnBackBufferFormatChanged(); + if( FAILED( hr ) ) + return hr; + + // DXUTSETTINGSDLG_D3D11_REFRESH_RATE + if( bWindowed ) + { + CDXUTComboBox* pRefreshRateComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_REFRESH_RATE ); + for( UINT i = 0; i < pRefreshRateComboBox->GetNumItems(); ++i ) + { + DXGI_RATIONAL* pRefreshRate = reinterpret_cast( + pRefreshRateComboBox->GetItemData( i ) ); + delete pRefreshRate; + } + pRefreshRateComboBox->RemoveAllItems(); + AddD3D11RefreshRate( RefreshRate ); + } + + SetSelectedD3D11RefreshRate( RefreshRate ); + break; + } + }; + + hr = OnRefreshRateChanged(); + if( FAILED( hr ) ) + return hr; + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnAdapterFormatChanged() +{ + HRESULT hr = S_OK; + + switch( g_DeviceSettings.ver ) + { + case DXUT_D3D9_DEVICE: + { + // DXUTSETTINGSDLG_ADAPTER_FORMAT + D3DFORMAT adapterFormat = GetSelectedAdapterFormat(); + g_DeviceSettings.d3d9.AdapterFormat = adapterFormat; + + // DXUTSETTINGSDLG_RESOLUTION + CDXUTComboBox* pResolutionComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_RESOLUTION ); + pResolutionComboBox->RemoveAllItems(); + + CD3D9EnumAdapterInfo* pAdapterInfo = GetCurrentAdapterInfo(); + if( pAdapterInfo == NULL ) + return E_FAIL; + + bool bShowAll = m_Dialog.GetCheckBox( DXUTSETTINGSDLG_RESOLUTION_SHOW_ALL )->GetChecked(); + + // Get the desktop aspect ratio + D3DDISPLAYMODE dmDesktop; + DXUTGetDesktopResolution( g_DeviceSettings.d3d9.AdapterOrdinal, &dmDesktop.Width, &dmDesktop.Height ); + float fDesktopAspectRatio = dmDesktop.Width / ( float )dmDesktop.Height; + + for( int idm = 0; idm < pAdapterInfo->displayModeList.GetSize(); idm++ ) + { + D3DDISPLAYMODE DisplayMode = pAdapterInfo->displayModeList.GetAt( idm ); + float fAspect = ( float )DisplayMode.Width / ( float )DisplayMode.Height; + + if( DisplayMode.Format == g_DeviceSettings.d3d9.AdapterFormat ) + { + // If "Show All" is not checked, then hide all resolutions + // that don't match the aspect ratio of the desktop resolution + if( bShowAll || ( !bShowAll && fabsf( fDesktopAspectRatio - fAspect ) < 0.05f ) ) + { + AddResolution( DisplayMode.Width, DisplayMode.Height ); + } + } + } + + const DWORD dwCurResolution = MAKELONG( g_DeviceSettings.d3d9.pp.BackBufferWidth, + g_DeviceSettings.d3d9.pp.BackBufferHeight ); + + pResolutionComboBox->SetSelectedByData( ULongToPtr( dwCurResolution ) ); + + hr = OnResolutionChanged(); + if( FAILED( hr ) ) + return hr; + + // DXUTSETTINGSDLG_BACK_BUFFER_FORMAT + CDXUTComboBox* pBackBufferFormatComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_BACK_BUFFER_FORMAT ); + pBackBufferFormatComboBox->RemoveAllItems(); + + CD3D9EnumDeviceInfo* pDeviceInfo = GetCurrentDeviceInfo(); + if( pDeviceInfo == NULL ) + return E_FAIL; + + const BOOL bWindowed = IsWindowed(); + bool bHasWindowedBackBuffer = false; + + for( int idc = 0; idc < pDeviceInfo->deviceSettingsComboList.GetSize(); idc++ ) + { + CD3D9EnumDeviceSettingsCombo* pDeviceCombo = pDeviceInfo->deviceSettingsComboList.GetAt( idc ); + if( pDeviceCombo->Windowed == bWindowed && + pDeviceCombo->AdapterFormat == g_DeviceSettings.d3d9.AdapterFormat ) + { + AddBackBufferFormat( pDeviceCombo->BackBufferFormat ); + bHasWindowedBackBuffer = true; + } + } + + pBackBufferFormatComboBox->SetSelectedByData( ULongToPtr( g_DeviceSettings.d3d9.pp.BackBufferFormat ) ); + + hr = OnBackBufferFormatChanged(); + if( FAILED( hr ) ) + return hr; + + if( !bHasWindowedBackBuffer ) + { + m_Dialog.SetControlEnabled( DXUTSETTINGSDLG_WINDOWED, false ); + + if( g_DeviceSettings.d3d9.pp.Windowed ) + { + SetWindowed( false ); + + hr = OnWindowedFullScreenChanged(); + if( FAILED( hr ) ) + return hr; + } + } + + break; + } + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnResolutionChanged() +{ + HRESULT hr = S_OK; + + CD3D9EnumAdapterInfo* pAdapterInfo = GetCurrentAdapterInfo(); + if( pAdapterInfo == NULL ) + return E_FAIL; + + // Set resolution + DWORD dwWidth, dwHeight; + GetSelectedResolution( &dwWidth, &dwHeight ); + g_DeviceSettings.d3d9.pp.BackBufferWidth = dwWidth; + g_DeviceSettings.d3d9.pp.BackBufferHeight = dwHeight; + + DWORD dwRefreshRate = g_DeviceSettings.d3d9.pp.FullScreen_RefreshRateInHz; + + // Update the refresh rate list + CDXUTComboBox* pRefreshRateComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_REFRESH_RATE ); + pRefreshRateComboBox->RemoveAllItems(); + + D3DFORMAT adapterFormat = g_DeviceSettings.d3d9.AdapterFormat; + for( int idm = 0; idm < pAdapterInfo->displayModeList.GetSize(); idm++ ) + { + D3DDISPLAYMODE displayMode = pAdapterInfo->displayModeList.GetAt( idm ); + + if( displayMode.Format == adapterFormat && + displayMode.Width == dwWidth && + displayMode.Height == dwHeight ) + { + AddRefreshRate( displayMode.RefreshRate ); + } + } + + pRefreshRateComboBox->SetSelectedByData( ULongToPtr( dwRefreshRate ) ); + + hr = OnRefreshRateChanged(); + if( FAILED( hr ) ) + return hr; + + return S_OK; +} + + + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnRefreshRateChanged() +{ + // Set refresh rate + switch( g_DeviceSettings.ver ) + { + case DXUT_D3D9_DEVICE: + g_DeviceSettings.d3d9.pp.FullScreen_RefreshRateInHz = GetSelectedRefreshRate(); + break; + + case DXUT_D3D11_DEVICE: + g_DeviceSettings.d3d11.sd.BufferDesc.RefreshRate = GetSelectedD3D11RefreshRate(); + break; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnBackBufferFormatChanged() +{ + HRESULT hr = S_OK; + + switch( g_DeviceSettings.ver ) + { + case DXUT_D3D9_DEVICE: + { + g_DeviceSettings.d3d9.pp.BackBufferFormat = GetSelectedBackBufferFormat(); + + D3DFORMAT adapterFormat = g_DeviceSettings.d3d9.AdapterFormat; + D3DFORMAT backBufferFormat = g_DeviceSettings.d3d9.pp.BackBufferFormat; + + CD3D9EnumDeviceInfo* pDeviceInfo = GetCurrentDeviceInfo(); + if( pDeviceInfo == NULL ) + return E_FAIL; + + bool bAllowSoftwareVP, bAllowHardwareVP, bAllowPureHardwareVP, bAllowMixedVP; + DXUTGetD3D9Enumeration()->GetPossibleVertexProcessingList( &bAllowSoftwareVP, &bAllowHardwareVP, + &bAllowPureHardwareVP, &bAllowMixedVP ); + + for( int idc = 0; idc < pDeviceInfo->deviceSettingsComboList.GetSize(); idc++ ) + { + CD3D9EnumDeviceSettingsCombo* pDeviceCombo = pDeviceInfo->deviceSettingsComboList.GetAt( idc ); + + if( pDeviceCombo->Windowed == ( g_DeviceSettings.d3d9.pp.Windowed == TRUE ) && + pDeviceCombo->AdapterFormat == adapterFormat && + pDeviceCombo->BackBufferFormat == backBufferFormat ) + { + CDXUTComboBox* pDepthStencilComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_DEPTH_STENCIL ); + pDepthStencilComboBox->RemoveAllItems(); + pDepthStencilComboBox->SetEnabled( ( g_DeviceSettings.d3d9.pp.EnableAutoDepthStencil == TRUE ) ); + + if( g_DeviceSettings.d3d9.pp.EnableAutoDepthStencil ) + { + for( int ifmt = 0; ifmt < pDeviceCombo->depthStencilFormatList.GetSize(); ifmt++ ) + { + D3DFORMAT fmt = pDeviceCombo->depthStencilFormatList.GetAt( ifmt ); + + AddDepthStencilBufferFormat( fmt ); + } + + pDepthStencilComboBox->SetSelectedByData( ULongToPtr( + g_DeviceSettings.d3d9.pp.AutoDepthStencilFormat ) ); + } + else + { + if( !pDepthStencilComboBox->ContainsItem( L"(not used)" ) ) + pDepthStencilComboBox->AddItem( L"(not used)", NULL ); + } + + hr = OnDepthStencilBufferFormatChanged(); + if( FAILED( hr ) ) + return hr; + + CDXUTComboBox* pVertexProcessingComboBox = + m_Dialog.GetComboBox( DXUTSETTINGSDLG_VERTEX_PROCESSING ); + pVertexProcessingComboBox->RemoveAllItems(); + + // Add valid vertex processing types + if( bAllowSoftwareVP ) + AddVertexProcessingType( D3DCREATE_SOFTWARE_VERTEXPROCESSING ); + + if( bAllowHardwareVP && pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) + AddVertexProcessingType( D3DCREATE_HARDWARE_VERTEXPROCESSING ); + + if( bAllowPureHardwareVP && pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_PUREDEVICE ) + AddVertexProcessingType( D3DCREATE_PUREDEVICE ); + + if( bAllowMixedVP && pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) + AddVertexProcessingType( D3DCREATE_MIXED_VERTEXPROCESSING ); + + if( g_DeviceSettings.d3d9.BehaviorFlags & D3DCREATE_PUREDEVICE ) + pVertexProcessingComboBox->SetSelectedByData( ULongToPtr( D3DCREATE_PUREDEVICE ) ); + else if( g_DeviceSettings.d3d9.BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING ) + pVertexProcessingComboBox->SetSelectedByData( ULongToPtr( + D3DCREATE_SOFTWARE_VERTEXPROCESSING ) ); + else if( g_DeviceSettings.d3d9.BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING ) + pVertexProcessingComboBox->SetSelectedByData( ULongToPtr( + D3DCREATE_HARDWARE_VERTEXPROCESSING ) ); + else if( g_DeviceSettings.d3d9.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING ) + pVertexProcessingComboBox->SetSelectedByData( ULongToPtr( D3DCREATE_MIXED_VERTEXPROCESSING ) ); + + hr = OnVertexProcessingChanged(); + if( FAILED( hr ) ) + return hr; + + CDXUTComboBox* pPresentIntervalComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_PRESENT_INTERVAL ); + pPresentIntervalComboBox->RemoveAllItems(); + pPresentIntervalComboBox->AddItem( L"On", ULongToPtr( D3DPRESENT_INTERVAL_DEFAULT ) ); + pPresentIntervalComboBox->AddItem( L"Off", ULongToPtr( D3DPRESENT_INTERVAL_IMMEDIATE ) ); + + pPresentIntervalComboBox->SetSelectedByData( ULongToPtr( + g_DeviceSettings.d3d9.pp.PresentationInterval ) ); + + hr = OnPresentIntervalChanged(); + if( FAILED( hr ) ) + return hr; + } + } + + break; + } + + case DXUT_D3D11_DEVICE: + { + g_DeviceSettings.d3d11.sd.BufferDesc.Format = GetSelectedD3D11BackBufferFormat(); + + DXGI_FORMAT backBufferFormat = g_DeviceSettings.d3d11.sd.BufferDesc.Format; + + CD3D11EnumAdapterInfo* pAdapterInfo = GetCurrentD3D11AdapterInfo(); + if( pAdapterInfo == NULL ) + return E_FAIL; + + for( int idc = 0; idc < pAdapterInfo->deviceSettingsComboList.GetSize(); idc++ ) + { + CD3D11EnumDeviceSettingsCombo* pDeviceCombo = pAdapterInfo->deviceSettingsComboList.GetAt( idc ); + + if( pDeviceCombo->Windowed == ( g_DeviceSettings.d3d11.sd.Windowed == TRUE ) && + pDeviceCombo->BackBufferFormat == backBufferFormat && + pDeviceCombo->DeviceType == g_DeviceSettings.d3d11.DriverType ) + { + CDXUTComboBox* pMultisampleCountCombo = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_COUNT + ); + pMultisampleCountCombo->RemoveAllItems(); + for( int i = 0; i < pDeviceCombo->multiSampleCountList.GetSize(); ++i ) + AddD3D11MultisampleCount( pDeviceCombo->multiSampleCountList.GetAt( i ) ); + pMultisampleCountCombo->SetSelectedByData( ULongToPtr( + g_DeviceSettings.d3d11.sd.SampleDesc.Count ) ); + + hr = OnMultisampleTypeChanged(); + if( FAILED( hr ) ) + return hr; + + CDXUTComboBox* pPresentIntervalComboBox = + m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_PRESENT_INTERVAL ); + pPresentIntervalComboBox->RemoveAllItems(); + pPresentIntervalComboBox->AddItem( L"On", ULongToPtr( 1 ) ); + pPresentIntervalComboBox->AddItem( L"Off", ULongToPtr( 0 ) ); + + pPresentIntervalComboBox->SetSelectedByData( ULongToPtr( g_DeviceSettings.d3d11.SyncInterval ) ); + + hr = OnPresentIntervalChanged(); + if( FAILED( hr ) ) + return hr; + + hr = UpdateD3D11Resolutions(); + if( FAILED( hr ) ) + return hr; + } + } + + break; + } + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnDepthStencilBufferFormatChanged() +{ + HRESULT hr = S_OK; + + D3DFORMAT depthStencilBufferFormat = GetSelectedDepthStencilBufferFormat(); + + if( g_DeviceSettings.d3d9.pp.EnableAutoDepthStencil ) + g_DeviceSettings.d3d9.pp.AutoDepthStencilFormat = depthStencilBufferFormat; + + CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo = GetCurrentDeviceSettingsCombo(); + if( pDeviceSettingsCombo == NULL ) + return E_FAIL; + + CDXUTComboBox* pMultisampleTypeCombo = m_Dialog.GetComboBox( DXUTSETTINGSDLG_MULTISAMPLE_TYPE ); + pMultisampleTypeCombo->RemoveAllItems(); + + for( int ims = 0; ims < pDeviceSettingsCombo->multiSampleTypeList.GetSize(); ims++ ) + { + D3DMULTISAMPLE_TYPE msType = pDeviceSettingsCombo->multiSampleTypeList.GetAt( ims ); + + bool bConflictFound = false; + for( int iConf = 0; iConf < pDeviceSettingsCombo->DSMSConflictList.GetSize(); iConf++ ) + { + CD3D9EnumDSMSConflict DSMSConf = pDeviceSettingsCombo->DSMSConflictList.GetAt( iConf ); + if( DSMSConf.DSFormat == depthStencilBufferFormat && + DSMSConf.MSType == msType ) + { + bConflictFound = true; + break; + } + } + + if( !bConflictFound ) + AddMultisampleType( msType ); + } + + CDXUTComboBox* pMultisampleQualityCombo = m_Dialog.GetComboBox( DXUTSETTINGSDLG_MULTISAMPLE_TYPE ); + pMultisampleQualityCombo->SetSelectedByData( ULongToPtr( g_DeviceSettings.d3d9.pp.MultiSampleType ) ); + + hr = OnMultisampleTypeChanged(); + if( FAILED( hr ) ) + return hr; + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnMultisampleTypeChanged() +{ + HRESULT hr = S_OK; + + switch( g_DeviceSettings.ver ) + { + case DXUT_D3D9_DEVICE: + { + D3DMULTISAMPLE_TYPE multisampleType = GetSelectedMultisampleType(); + g_DeviceSettings.d3d9.pp.MultiSampleType = multisampleType; + + CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo = GetCurrentDeviceSettingsCombo(); + if( pDeviceSettingsCombo == NULL ) + return E_FAIL; + + DWORD dwMaxQuality = 0; + for( int iType = 0; iType < pDeviceSettingsCombo->multiSampleTypeList.GetSize(); iType++ ) + { + D3DMULTISAMPLE_TYPE msType = pDeviceSettingsCombo->multiSampleTypeList.GetAt( iType ); + if( msType == multisampleType ) + { + dwMaxQuality = pDeviceSettingsCombo->multiSampleQualityList.GetAt( iType ); + break; + } + } + + // DXUTSETTINGSDLG_MULTISAMPLE_QUALITY + CDXUTComboBox* pMultisampleQualityCombo = m_Dialog.GetComboBox( DXUTSETTINGSDLG_MULTISAMPLE_QUALITY ); + pMultisampleQualityCombo->RemoveAllItems(); + + for( UINT iQuality = 0; iQuality < dwMaxQuality; iQuality++ ) + { + AddMultisampleQuality( iQuality ); + } + + pMultisampleQualityCombo->SetSelectedByData( ULongToPtr( g_DeviceSettings.d3d9.pp.MultiSampleQuality ) ); + + hr = OnMultisampleQualityChanged(); + if( FAILED( hr ) ) + return hr; + + break; + } + case DXUT_D3D11_DEVICE: + { + UINT multisampleCount = GetSelectedD3D11MultisampleCount(); + g_DeviceSettings.d3d11.sd.SampleDesc.Count = multisampleCount; + + CD3D11EnumDeviceSettingsCombo* pDeviceSettingsCombo = GetCurrentD3D11DeviceSettingsCombo(); + if( pDeviceSettingsCombo == NULL ) + return E_FAIL; + + UINT MaxQuality = 0; + for( int iCount = 0; iCount < pDeviceSettingsCombo->multiSampleCountList.GetSize(); iCount++ ) + { + UINT Count = pDeviceSettingsCombo->multiSampleCountList.GetAt( iCount ); + if( Count == multisampleCount ) + { + MaxQuality = pDeviceSettingsCombo->multiSampleQualityList.GetAt( iCount ); + break; + } + } + + // DXUTSETTINGSDLG_D3D11_MULTISAMPLE_QUALITY + CDXUTComboBox* pMultisampleQualityCombo = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_QUALITY + ); + pMultisampleQualityCombo->RemoveAllItems(); + + for( UINT iQuality = 0; iQuality < MaxQuality; iQuality++ ) + { + AddD3D11MultisampleQuality( iQuality ); + } + + pMultisampleQualityCombo->SetSelectedByData( ULongToPtr( g_DeviceSettings.d3d11.sd.SampleDesc.Quality ) ); + + hr = OnMultisampleQualityChanged(); + if( FAILED( hr ) ) + return hr; + + break; + } + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnMultisampleQualityChanged() +{ + switch( g_DeviceSettings.ver ) + { + case DXUT_D3D9_DEVICE: + g_DeviceSettings.d3d9.pp.MultiSampleQuality = GetSelectedMultisampleQuality(); + break; + + case DXUT_D3D11_DEVICE: + g_DeviceSettings.d3d11.sd.SampleDesc.Quality = GetSelectedD3D11MultisampleQuality(); + break; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnVertexProcessingChanged() +{ + DWORD dwBehavior = g_DeviceSettings.d3d9.BehaviorFlags; + + // Clear vertex processing flags + dwBehavior &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING; + dwBehavior &= ~D3DCREATE_SOFTWARE_VERTEXPROCESSING; + dwBehavior &= ~D3DCREATE_MIXED_VERTEXPROCESSING; + dwBehavior &= ~D3DCREATE_PUREDEVICE; + + // Determine new flags + DWORD dwNewFlags = GetSelectedVertexProcessingType(); + if( dwNewFlags & D3DCREATE_PUREDEVICE ) + dwNewFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; + + // Make changes + g_DeviceSettings.d3d9.BehaviorFlags = dwBehavior | dwNewFlags; + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnPresentIntervalChanged() +{ + switch( g_DeviceSettings.ver ) + { + case DXUT_D3D9_DEVICE: + g_DeviceSettings.d3d9.pp.PresentationInterval = GetSelectedPresentInterval(); + break; + + case DXUT_D3D11_DEVICE: + g_DeviceSettings.d3d11.SyncInterval = GetSelectedD3D11PresentInterval(); + break; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnDebugDeviceChanged() +{ + bool bDebugDevice = GetSelectedDebugDeviceValue(); + + if( bDebugDevice ) + g_DeviceSettings.d3d11.CreateFlags |= D3D11_CREATE_DEVICE_DEBUG; + else + g_DeviceSettings.d3d11.CreateFlags &= ~D3D11_CREATE_DEVICE_DEBUG; + + return S_OK; +} + +//------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::OnDeviceClipChanged() +{ + if( IsDeviceClip() ) + g_DeviceSettings.d3d9.pp.Flags |= D3DPRESENTFLAG_DEVICECLIP; + else + g_DeviceSettings.d3d9.pp.Flags &= ~D3DPRESENTFLAG_DEVICECLIP; + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddAPIVersion( DXUTDeviceVersion version ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_API_VERSION ); + + if( !pComboBox->ContainsItem( DXUTAPIVersionToString( version ) ) ) + pComboBox->AddItem( DXUTAPIVersionToString( version ), ULongToPtr( version ) ); +} + + +//------------------------------------------------------------------------------------- +DXUTDeviceVersion CD3DSettingsDlg::GetSelectedAPIVersion() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_API_VERSION ); + + return ( DXUTDeviceVersion )PtrToUlong( pComboBox->GetSelectedData() ); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddAdapter( const WCHAR* strDescription, UINT iAdapter ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_ADAPTER ); + + if( !pComboBox->ContainsItem( strDescription ) ) + pComboBox->AddItem( strDescription, ULongToPtr( iAdapter ) ); +} + + +//------------------------------------------------------------------------------------- +UINT CD3DSettingsDlg::GetSelectedAdapter() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_ADAPTER ); + + return PtrToUlong( pComboBox->GetSelectedData() ); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddDeviceType( D3DDEVTYPE devType ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_DEVICE_TYPE ); + + if( !pComboBox->ContainsItem( DXUTD3DDeviceTypeToString( devType ) ) ) + pComboBox->AddItem( DXUTD3DDeviceTypeToString( devType ), ULongToPtr( devType ) ); +} + + +//------------------------------------------------------------------------------------- +D3DDEVTYPE CD3DSettingsDlg::GetSelectedDeviceType() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_DEVICE_TYPE ); + + return ( D3DDEVTYPE )PtrToUlong( pComboBox->GetSelectedData() ); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::SetWindowed( bool bWindowed ) +{ + CDXUTRadioButton* pRadioButton = m_Dialog.GetRadioButton( DXUTSETTINGSDLG_WINDOWED ); + pRadioButton->SetChecked( bWindowed ); + + pRadioButton = m_Dialog.GetRadioButton( DXUTSETTINGSDLG_FULLSCREEN ); + pRadioButton->SetChecked( !bWindowed ); +} + + +//------------------------------------------------------------------------------------- +bool CD3DSettingsDlg::IsWindowed() +{ + CDXUTRadioButton* pRadioButton = m_Dialog.GetRadioButton( DXUTSETTINGSDLG_WINDOWED ); + return pRadioButton->GetChecked(); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddAdapterFormat( D3DFORMAT format ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_ADAPTER_FORMAT ); + + if( !pComboBox->ContainsItem( DXUTD3DFormatToString( format, TRUE ) ) ) + pComboBox->AddItem( DXUTD3DFormatToString( format, TRUE ), ULongToPtr( format ) ); +} + + +//------------------------------------------------------------------------------------- +D3DFORMAT CD3DSettingsDlg::GetSelectedAdapterFormat() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_ADAPTER_FORMAT ); + + return ( D3DFORMAT )PtrToUlong( pComboBox->GetSelectedData() ); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddD3D11AdapterOutput( const WCHAR* strName, UINT Output ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_ADAPTER_OUTPUT ); + + if( !pComboBox->ContainsItem( strName ) ) + pComboBox->AddItem( strName, ULongToPtr( Output ) ); +} + + +//------------------------------------------------------------------------------------- +UINT CD3DSettingsDlg::GetSelectedD3D11AdapterOutput() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_ADAPTER_OUTPUT ); + + return PtrToUlong( pComboBox->GetSelectedData() ); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddResolution( DWORD dwWidth, DWORD dwHeight ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_RESOLUTION ); + + DWORD dwResolutionData; + WCHAR strResolution[50]; + dwResolutionData = MAKELONG( dwWidth, dwHeight ); + swprintf_s( strResolution, 50, L"%d by %d", dwWidth, dwHeight ); + + if( !pComboBox->ContainsItem( strResolution ) ) + pComboBox->AddItem( strResolution, ULongToPtr( dwResolutionData ) ); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::GetSelectedResolution( DWORD* pdwWidth, DWORD* pdwHeight ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_RESOLUTION ); + + DWORD dwResolution = PtrToUlong( pComboBox->GetSelectedData() ); + + *pdwWidth = LOWORD( dwResolution ); + *pdwHeight = HIWORD( dwResolution ); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddD3D11Resolution( DWORD dwWidth, DWORD dwHeight ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_RESOLUTION ); + + DWORD dwResolutionData; + WCHAR strResolution[50]; + dwResolutionData = MAKELONG( dwWidth, dwHeight ); + swprintf_s( strResolution, 50, L"%d by %d", dwWidth, dwHeight ); + + if( !pComboBox->ContainsItem( strResolution ) ) + pComboBox->AddItem( strResolution, ULongToPtr( dwResolutionData ) ); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::GetSelectedD3D11Resolution( DWORD* pdwWidth, DWORD* pdwHeight ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_RESOLUTION ); + + DWORD dwResolution = PtrToUlong( pComboBox->GetSelectedData() ); + + *pdwWidth = LOWORD( dwResolution ); + *pdwHeight = HIWORD( dwResolution ); +} + +void CD3DSettingsDlg::AddD3D11FeatureLevel(D3D_FEATURE_LEVEL fl) { + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_FEATURE_LEVEL ); + switch( fl ) + { + case D3D_FEATURE_LEVEL_9_1: + { + if( !pComboBox->ContainsItem( L"D3D_FEATURE_LEVEL_9_1" ) ) + pComboBox->AddItem( L"D3D_FEATURE_LEVEL_9_1", ULongToPtr( D3D_FEATURE_LEVEL_9_1 ) ); + } + break; + case D3D_FEATURE_LEVEL_9_2: + { + if( !pComboBox->ContainsItem( L"D3D_FEATURE_LEVEL_9_2" ) ) + pComboBox->AddItem( L"D3D_FEATURE_LEVEL_9_2", ULongToPtr( D3D_FEATURE_LEVEL_9_2 ) ); + } + break; + case D3D_FEATURE_LEVEL_9_3: + { + if( !pComboBox->ContainsItem( L"D3D_FEATURE_LEVEL_9_3" ) ) + pComboBox->AddItem( L"D3D_FEATURE_LEVEL_9_3", ULongToPtr( D3D_FEATURE_LEVEL_9_3 ) ); + } + break; + case D3D_FEATURE_LEVEL_10_0: + { + if( !pComboBox->ContainsItem( L"D3D_FEATURE_LEVEL_10_0" ) ) + pComboBox->AddItem( L"D3D_FEATURE_LEVEL_10_0", ULongToPtr( D3D_FEATURE_LEVEL_10_0 ) ); + } + break; + case D3D_FEATURE_LEVEL_10_1: + { + if( !pComboBox->ContainsItem( L"D3D_FEATURE_LEVEL_10_1" ) ) + pComboBox->AddItem( L"D3D_FEATURE_LEVEL_10_1", ULongToPtr( D3D_FEATURE_LEVEL_10_1 ) ); + } + break; + case D3D_FEATURE_LEVEL_11_0: + { + if( !pComboBox->ContainsItem( L"D3D_FEATURE_LEVEL_11_0" ) ) + pComboBox->AddItem( L"D3D_FEATURE_LEVEL_11_0", ULongToPtr( D3D_FEATURE_LEVEL_11_0 ) ); + } + break; + } + +} + +D3D_FEATURE_LEVEL CD3DSettingsDlg::GetSelectedFeatureLevel() { + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_FEATURE_LEVEL ); + + return (D3D_FEATURE_LEVEL)PtrToUlong( pComboBox->GetSelectedData() ); +} +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddRefreshRate( DWORD dwRate ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_REFRESH_RATE ); + + WCHAR strRefreshRate[50]; + + if( dwRate == 0 ) + wcscpy_s( strRefreshRate, 50, L"Default Rate" ); + else + swprintf_s( strRefreshRate, 50, L"%d Hz", dwRate ); + + if( !pComboBox->ContainsItem( strRefreshRate ) ) + pComboBox->AddItem( strRefreshRate, ULongToPtr( dwRate ) ); +} + + +//------------------------------------------------------------------------------------- +DWORD CD3DSettingsDlg::GetSelectedRefreshRate() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_REFRESH_RATE ); + + return PtrToUlong( pComboBox->GetSelectedData() ); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddD3D11RefreshRate( DXGI_RATIONAL RefreshRate ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_REFRESH_RATE ); + + WCHAR strRefreshRate[50]; + + if( RefreshRate.Numerator == 0 && RefreshRate.Denominator == 0 ) + wcscpy_s( strRefreshRate, 50, L"Default Rate" ); + else + swprintf_s( strRefreshRate, 50, L"%d Hz", RefreshRate.Numerator / RefreshRate.Denominator ); + + if( !pComboBox->ContainsItem( strRefreshRate ) ) + { + DXGI_RATIONAL* pNewRate = new DXGI_RATIONAL; + if( pNewRate ) + { + *pNewRate = RefreshRate; + pComboBox->AddItem( strRefreshRate, pNewRate ); + } + } +} + + +//------------------------------------------------------------------------------------- +DXGI_RATIONAL CD3DSettingsDlg::GetSelectedD3D11RefreshRate() +{ + DXGI_RATIONAL dxgiR; + dxgiR.Numerator = 0; + dxgiR.Denominator = 1; + + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_REFRESH_RATE ); + + return *reinterpret_cast( pComboBox->GetSelectedData() ); + +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddBackBufferFormat( D3DFORMAT format ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_BACK_BUFFER_FORMAT ); + + if( !pComboBox->ContainsItem( DXUTD3DFormatToString( format, TRUE ) ) ) + pComboBox->AddItem( DXUTD3DFormatToString( format, TRUE ), ULongToPtr( format ) ); +} + + +//------------------------------------------------------------------------------------- +D3DFORMAT CD3DSettingsDlg::GetSelectedBackBufferFormat() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_BACK_BUFFER_FORMAT ); + + return ( D3DFORMAT )PtrToUlong( pComboBox->GetSelectedData() ); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddD3D11BackBufferFormat( DXGI_FORMAT format ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_BACK_BUFFER_FORMAT ); + + if( !pComboBox->ContainsItem( DXUTDXGIFormatToString( format, TRUE ) ) ) + pComboBox->AddItem( DXUTDXGIFormatToString( format, TRUE ), ULongToPtr( format ) ); +} + + +//------------------------------------------------------------------------------------- +DXGI_FORMAT CD3DSettingsDlg::GetSelectedD3D11BackBufferFormat() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_BACK_BUFFER_FORMAT ); + + return ( DXGI_FORMAT )PtrToUlong( pComboBox->GetSelectedData() ); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddDepthStencilBufferFormat( D3DFORMAT format ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_DEPTH_STENCIL ); + + if( !pComboBox->ContainsItem( DXUTD3DFormatToString( format, TRUE ) ) ) + pComboBox->AddItem( DXUTD3DFormatToString( format, TRUE ), ULongToPtr( format ) ); +} + + +//------------------------------------------------------------------------------------- +D3DFORMAT CD3DSettingsDlg::GetSelectedDepthStencilBufferFormat() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_DEPTH_STENCIL ); + + return ( D3DFORMAT )PtrToUlong( pComboBox->GetSelectedData() ); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddMultisampleType( D3DMULTISAMPLE_TYPE type ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_MULTISAMPLE_TYPE ); + + if( !pComboBox->ContainsItem( DXUTMultisampleTypeToString( type ) ) ) + pComboBox->AddItem( DXUTMultisampleTypeToString( type ), ULongToPtr( type ) ); +} + + +//------------------------------------------------------------------------------------- +D3DMULTISAMPLE_TYPE CD3DSettingsDlg::GetSelectedMultisampleType() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_MULTISAMPLE_TYPE ); + + return ( D3DMULTISAMPLE_TYPE )PtrToUlong( pComboBox->GetSelectedData() ); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddMultisampleQuality( DWORD dwQuality ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_MULTISAMPLE_QUALITY ); + + WCHAR strQuality[50]; + swprintf_s( strQuality, 50, L"%d", dwQuality ); + + if( !pComboBox->ContainsItem( strQuality ) ) + pComboBox->AddItem( strQuality, ULongToPtr( dwQuality ) ); +} + + +//------------------------------------------------------------------------------------- +DWORD CD3DSettingsDlg::GetSelectedMultisampleQuality() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_MULTISAMPLE_QUALITY ); + + return PtrToUlong( pComboBox->GetSelectedData() ); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddD3D11MultisampleCount( UINT Count ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_COUNT ); + + WCHAR str[50]; + swprintf_s( str, 50, L"%u", Count ); + + if( !pComboBox->ContainsItem( str ) ) + pComboBox->AddItem( str, ULongToPtr( Count ) ); +} + + +//------------------------------------------------------------------------------------- +UINT CD3DSettingsDlg::GetSelectedD3D11MultisampleCount() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_COUNT ); + + return ( UINT )PtrToUlong( pComboBox->GetSelectedData() ); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddD3D11MultisampleQuality( UINT Quality ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_QUALITY ); + + WCHAR strQuality[50]; + swprintf_s( strQuality, 50, L"%d", Quality ); + + if( !pComboBox->ContainsItem( strQuality ) ) + pComboBox->AddItem( strQuality, ULongToPtr( Quality ) ); +} + + +//------------------------------------------------------------------------------------- +UINT CD3DSettingsDlg::GetSelectedD3D11MultisampleQuality() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_MULTISAMPLE_QUALITY ); + + return ( UINT )PtrToUlong( pComboBox->GetSelectedData() ); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddVertexProcessingType( DWORD dwType ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_VERTEX_PROCESSING ); + + if( !pComboBox->ContainsItem( DXUTVertexProcessingTypeToString( dwType ) ) ) + pComboBox->AddItem( DXUTVertexProcessingTypeToString( dwType ), ULongToPtr( dwType ) ); +} + + +//------------------------------------------------------------------------------------- +DWORD CD3DSettingsDlg::GetSelectedVertexProcessingType() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_VERTEX_PROCESSING ); + + return PtrToUlong( pComboBox->GetSelectedData() ); +} + + +//------------------------------------------------------------------------------------- +DWORD CD3DSettingsDlg::GetSelectedPresentInterval() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_PRESENT_INTERVAL ); + + return PtrToUlong( pComboBox->GetSelectedData() ); +} + + +//------------------------------------------------------------------------------------- +DWORD CD3DSettingsDlg::GetSelectedD3D11PresentInterval() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_PRESENT_INTERVAL ); + + return PtrToUlong( pComboBox->GetSelectedData() ); +} + +//------------------------------------------------------------------------------------- +bool CD3DSettingsDlg::GetSelectedDebugDeviceValue() +{ + CDXUTCheckBox* pCheckBox = m_Dialog.GetCheckBox( DXUTSETTINGSDLG_D3D11_DEBUG_DEVICE ); + + return pCheckBox->GetChecked(); +} + + +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::SetDeviceClip( bool bDeviceClip ) +{ + CDXUTCheckBox* pCheckBox = m_Dialog.GetCheckBox( DXUTSETTINGSDLG_DEVICECLIP ); + pCheckBox->SetChecked( bDeviceClip ); +} + + +//------------------------------------------------------------------------------------- +bool CD3DSettingsDlg::IsDeviceClip() +{ + CDXUTCheckBox* pCheckBox = m_Dialog.GetCheckBox( DXUTSETTINGSDLG_DEVICECLIP ); + return pCheckBox->GetChecked(); +} + +//-------------------------------------------------------------------------------------- +// Updates the resolution list for D3D11 +//-------------------------------------------------------------------------------------- +HRESULT CD3DSettingsDlg::UpdateD3D11Resolutions() +{ + + const DWORD dwWidth = g_DeviceSettings.d3d11.sd.BufferDesc.Width; + const DWORD dwHeight = g_DeviceSettings.d3d11.sd.BufferDesc.Height; + + // DXUTSETTINGSDLG_D3D11_RESOLUTION + CDXUTComboBox* pResolutionComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_D3D11_RESOLUTION ); + pResolutionComboBox->RemoveAllItems(); + + CD3D11EnumOutputInfo* pOutputInfo = GetCurrentD3D11OutputInfo(); + if( pOutputInfo == NULL ) + return E_FAIL; + + bool bShowAll = m_Dialog.GetCheckBox( DXUTSETTINGSDLG_RESOLUTION_SHOW_ALL )->GetChecked(); + + // Get the desktop aspect ratio + DXGI_MODE_DESC dmDesktop; + DXUTGetDesktopResolution( g_DeviceSettings.d3d11.AdapterOrdinal, &dmDesktop.Width, &dmDesktop.Height ); + float fDesktopAspectRatio = dmDesktop.Width / ( float )dmDesktop.Height; + + for( int idm = 0; idm < pOutputInfo->displayModeList.GetSize(); idm++ ) + { + DXGI_MODE_DESC DisplayMode = pOutputInfo->displayModeList.GetAt( idm ); + float fAspect = ( float )DisplayMode.Width / ( float )DisplayMode.Height; + + if( DisplayMode.Format == g_DeviceSettings.d3d11.sd.BufferDesc.Format ) + { + // If "Show All" is not checked, then hide all resolutions + // that don't match the aspect ratio of the desktop resolution + if( bShowAll || ( !bShowAll && fabsf( fDesktopAspectRatio - fAspect ) < 0.05f ) ) + { + AddD3D11Resolution( DisplayMode.Width, DisplayMode.Height ); + } + } + } + + const DWORD dwCurResolution = MAKELONG( g_DeviceSettings.d3d11.sd.BufferDesc.Width, + g_DeviceSettings.d3d11.sd.BufferDesc.Height ); + + pResolutionComboBox->SetSelectedByData( ULongToPtr( dwCurResolution ) ); + + + bool bWindowed = IsWindowed(); + if( bWindowed ) + { + pResolutionComboBox->RemoveAllItems(); + AddD3D11Resolution( dwWidth, dwHeight ); + + pResolutionComboBox->SetSelectedByData( ULongToPtr( MAKELONG( dwWidth, dwHeight ) ) ); + + + } + + return S_OK; +} + + +// +//------------------------------------------------------------------------------------- +void CD3DSettingsDlg::AddD3D11DeviceType( D3D_DRIVER_TYPE devType ) +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_DEVICE_TYPE ); + + if( !pComboBox->ContainsItem( DXUTD3DX11DeviceTypeToString( devType ) ) ) + pComboBox->AddItem( DXUTD3DX11DeviceTypeToString( devType ), ULongToPtr( devType ) ); +} + + +//------------------------------------------------------------------------------------- +D3D_DRIVER_TYPE CD3DSettingsDlg::GetSelectedD3D11DeviceType() +{ + CDXUTComboBox* pComboBox = m_Dialog.GetComboBox( DXUTSETTINGSDLG_DEVICE_TYPE ); + + return ( D3D_DRIVER_TYPE )PtrToUlong( pComboBox->GetSelectedData() ); +} + + +void CD3DSettingsDlg::UpdateModeChangeTimeoutText( int nSecRemaining ) +{ + const WCHAR StrTimeout[] = L"Reverting to previous display settings in %d seconds"; + const DWORD CchBuf = sizeof( StrTimeout ) / sizeof( WCHAR ) + 16; + WCHAR buf[CchBuf]; + + swprintf_s( buf, CchBuf, StrTimeout, nSecRemaining ); + + CDXUTStatic* pStatic = m_RevertModeDialog.GetStatic( DXUTSETTINGSDLG_STATIC_MODE_CHANGE_TIMEOUT ); + pStatic->SetText( buf ); +} + +//-------------------------------------------------------------------------------------- +// Returns the string for the given DXUTDeviceVersion. +//-------------------------------------------------------------------------------------- +WCHAR* DXUTAPIVersionToString( DXUTDeviceVersion version ) +{ + switch( version ) + { + case DXUT_D3D9_DEVICE: + return L"Direct3D 9"; + case DXUT_D3D11_DEVICE: + return L"Direct3D 11"; + default: + return L"Unknown version"; + } +} + + +//-------------------------------------------------------------------------------------- +// Returns the string for the given D3DDEVTYPE. +//-------------------------------------------------------------------------------------- +WCHAR* DXUTD3DDeviceTypeToString( D3DDEVTYPE devType ) +{ + switch( devType ) + { + case D3DDEVTYPE_HAL: + return L"D3DDEVTYPE_HAL"; + case D3DDEVTYPE_SW: + return L"D3DDEVTYPE_SW"; + case D3DDEVTYPE_REF: + return L"D3DDEVTYPE_REF"; + default: + return L"Unknown devType"; + } +} + + + + +//-------------------------------------------------------------------------------------- +// Returns the string for the given D3D_DRIVER_TYPE. +//-------------------------------------------------------------------------------------- +WCHAR* DXUTD3DX11DeviceTypeToString( D3D_DRIVER_TYPE devType ) +{ + switch( devType ) + { + case D3D_DRIVER_TYPE_HARDWARE: + return L"D3D_DRIVER_TYPE_HARDWARE"; + case D3D_DRIVER_TYPE_REFERENCE: + return L"D3D_DRIVER_TYPE_REFERENCE"; + case D3D_DRIVER_TYPE_NULL: + return L"D3D_DRIVER_TYPE_NULL"; + case D3D_DRIVER_TYPE_WARP: + return L"D3D_DRIVER_TYPE_WARP"; + default: + return L"Unknown devType"; + } +} + + +//-------------------------------------------------------------------------------------- +// Returns the string for the given D3DMULTISAMPLE_TYPE. +//-------------------------------------------------------------------------------------- +WCHAR* DXUTMultisampleTypeToString( D3DMULTISAMPLE_TYPE MultiSampleType ) +{ + switch( MultiSampleType ) + { + case D3DMULTISAMPLE_NONE: + return L"D3DMULTISAMPLE_NONE"; + case D3DMULTISAMPLE_NONMASKABLE: + return L"D3DMULTISAMPLE_NONMASKABLE"; + case D3DMULTISAMPLE_2_SAMPLES: + return L"D3DMULTISAMPLE_2_SAMPLES"; + case D3DMULTISAMPLE_3_SAMPLES: + return L"D3DMULTISAMPLE_3_SAMPLES"; + case D3DMULTISAMPLE_4_SAMPLES: + return L"D3DMULTISAMPLE_4_SAMPLES"; + case D3DMULTISAMPLE_5_SAMPLES: + return L"D3DMULTISAMPLE_5_SAMPLES"; + case D3DMULTISAMPLE_6_SAMPLES: + return L"D3DMULTISAMPLE_6_SAMPLES"; + case D3DMULTISAMPLE_7_SAMPLES: + return L"D3DMULTISAMPLE_7_SAMPLES"; + case D3DMULTISAMPLE_8_SAMPLES: + return L"D3DMULTISAMPLE_8_SAMPLES"; + case D3DMULTISAMPLE_9_SAMPLES: + return L"D3DMULTISAMPLE_9_SAMPLES"; + case D3DMULTISAMPLE_10_SAMPLES: + return L"D3DMULTISAMPLE_10_SAMPLES"; + case D3DMULTISAMPLE_11_SAMPLES: + return L"D3DMULTISAMPLE_11_SAMPLES"; + case D3DMULTISAMPLE_12_SAMPLES: + return L"D3DMULTISAMPLE_12_SAMPLES"; + case D3DMULTISAMPLE_13_SAMPLES: + return L"D3DMULTISAMPLE_13_SAMPLES"; + case D3DMULTISAMPLE_14_SAMPLES: + return L"D3DMULTISAMPLE_14_SAMPLES"; + case D3DMULTISAMPLE_15_SAMPLES: + return L"D3DMULTISAMPLE_15_SAMPLES"; + case D3DMULTISAMPLE_16_SAMPLES: + return L"D3DMULTISAMPLE_16_SAMPLES"; + default: + return L"Unknown Multisample Type"; + } +} + + +//-------------------------------------------------------------------------------------- +// Returns the string for the given vertex processing type +//-------------------------------------------------------------------------------------- +WCHAR* DXUTVertexProcessingTypeToString( DWORD vpt ) +{ + switch( vpt ) + { + case D3DCREATE_SOFTWARE_VERTEXPROCESSING: + return L"Software vertex processing"; + case D3DCREATE_MIXED_VERTEXPROCESSING: + return L"Mixed vertex processing"; + case D3DCREATE_HARDWARE_VERTEXPROCESSING: + return L"Hardware vertex processing"; + case D3DCREATE_PUREDEVICE: + return L"Pure hardware vertex processing"; + default: + return L"Unknown vertex processing type"; + } +} + + +//-------------------------------------------------------------------------------------- +// Returns the string for the given present interval. +//-------------------------------------------------------------------------------------- +WCHAR* DXUTPresentIntervalToString( UINT pi ) +{ + switch( pi ) + { + case D3DPRESENT_INTERVAL_IMMEDIATE: + return L"D3DPRESENT_INTERVAL_IMMEDIATE"; + case D3DPRESENT_INTERVAL_DEFAULT: + return L"D3DPRESENT_INTERVAL_DEFAULT"; + case D3DPRESENT_INTERVAL_ONE: + return L"D3DPRESENT_INTERVAL_ONE"; + case D3DPRESENT_INTERVAL_TWO: + return L"D3DPRESENT_INTERVAL_TWO"; + case D3DPRESENT_INTERVAL_THREE: + return L"D3DPRESENT_INTERVAL_THREE"; + case D3DPRESENT_INTERVAL_FOUR: + return L"D3DPRESENT_INTERVAL_FOUR"; + default: + return L"Unknown PresentInterval"; + } +} + + diff --git a/Demos/DX11ClothDemo/DXUT/Optional/DXUTsettingsdlg.h b/Demos/DX11ClothDemo/DXUT/Optional/DXUTsettingsdlg.h new file mode 100644 index 0000000..fee91f3 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/DXUTsettingsdlg.h @@ -0,0 +1,248 @@ +//-------------------------------------------------------------------------------------- +// File: DXUTSettingsDlg.cpp +// +// Copyright (c) Microsoft Corporation. All rights reserved +//-------------------------------------------------------------------------------------- +#pragma once +#ifndef DXUT_SETTINGS_H +#define DXUT_SETTINGS_H + +//-------------------------------------------------------------------------------------- +// Header Includes +//-------------------------------------------------------------------------------------- +#include "DXUTgui.h" +//-------------------------------------------------------------------------------------- +// Control IDs +//-------------------------------------------------------------------------------------- +#define DXUTSETTINGSDLG_STATIC -1 +#define DXUTSETTINGSDLG_OK 1 +#define DXUTSETTINGSDLG_CANCEL 2 +#define DXUTSETTINGSDLG_ADAPTER 3 +#define DXUTSETTINGSDLG_DEVICE_TYPE 4 +#define DXUTSETTINGSDLG_WINDOWED 5 +#define DXUTSETTINGSDLG_FULLSCREEN 6 +#define DXUTSETTINGSDLG_ADAPTER_FORMAT 7 +#define DXUTSETTINGSDLG_ADAPTER_FORMAT_LABEL 8 +#define DXUTSETTINGSDLG_RESOLUTION 9 +#define DXUTSETTINGSDLG_RESOLUTION_LABEL 10 +#define DXUTSETTINGSDLG_REFRESH_RATE 11 +#define DXUTSETTINGSDLG_REFRESH_RATE_LABEL 12 +#define DXUTSETTINGSDLG_BACK_BUFFER_FORMAT 13 +#define DXUTSETTINGSDLG_BACK_BUFFER_FORMAT_LABEL 14 +#define DXUTSETTINGSDLG_DEPTH_STENCIL 15 +#define DXUTSETTINGSDLG_DEPTH_STENCIL_LABEL 16 +#define DXUTSETTINGSDLG_MULTISAMPLE_TYPE 17 +#define DXUTSETTINGSDLG_MULTISAMPLE_TYPE_LABEL 18 +#define DXUTSETTINGSDLG_MULTISAMPLE_QUALITY 19 +#define DXUTSETTINGSDLG_MULTISAMPLE_QUALITY_LABEL 20 +#define DXUTSETTINGSDLG_VERTEX_PROCESSING 21 +#define DXUTSETTINGSDLG_VERTEX_PROCESSING_LABEL 22 +#define DXUTSETTINGSDLG_PRESENT_INTERVAL 23 +#define DXUTSETTINGSDLG_PRESENT_INTERVAL_LABEL 24 +#define DXUTSETTINGSDLG_DEVICECLIP 25 +#define DXUTSETTINGSDLG_RESOLUTION_SHOW_ALL 26 +#define DXUTSETTINGSDLG_API_VERSION 27 +#define DXUTSETTINGSDLG_D3D11_ADAPTER_OUTPUT 28 +#define DXUTSETTINGSDLG_D3D11_ADAPTER_OUTPUT_LABEL 29 +#define DXUTSETTINGSDLG_D3D11_RESOLUTION 30 +#define DXUTSETTINGSDLG_D3D11_RESOLUTION_LABEL 31 +#define DXUTSETTINGSDLG_D3D11_REFRESH_RATE 32 +#define DXUTSETTINGSDLG_D3D11_REFRESH_RATE_LABEL 33 +#define DXUTSETTINGSDLG_D3D11_BACK_BUFFER_FORMAT 34 +#define DXUTSETTINGSDLG_D3D11_BACK_BUFFER_FORMAT_LABEL 35 +#define DXUTSETTINGSDLG_D3D11_MULTISAMPLE_COUNT 36 +#define DXUTSETTINGSDLG_D3D11_MULTISAMPLE_COUNT_LABEL 37 +#define DXUTSETTINGSDLG_D3D11_MULTISAMPLE_QUALITY 38 +#define DXUTSETTINGSDLG_D3D11_MULTISAMPLE_QUALITY_LABEL 39 +#define DXUTSETTINGSDLG_D3D11_PRESENT_INTERVAL 40 +#define DXUTSETTINGSDLG_D3D11_PRESENT_INTERVAL_LABEL 41 +#define DXUTSETTINGSDLG_D3D11_DEBUG_DEVICE 42 +#define DXUTSETTINGSDLG_D3D11_FEATURE_LEVEL 43 +#define DXUTSETTINGSDLG_D3D11_FEATURE_LEVEL_LABEL 44 + +#define DXUTSETTINGSDLG_MODE_CHANGE_ACCEPT 58 +#define DXUTSETTINGSDLG_MODE_CHANGE_REVERT 59 +#define DXUTSETTINGSDLG_STATIC_MODE_CHANGE_TIMEOUT 60 +#define DXUTSETTINGSDLG_WINDOWED_GROUP 0x0100 + +#define TOTAL_FEATURE_LEVLES 6 +//-------------------------------------------------------------------------------------- +// Dialog for selection of device settings +// Use DXUTGetD3DSettingsDialog() to access global instance +// To control the contents of the dialog, use the CD3D9Enumeration class. +//-------------------------------------------------------------------------------------- +class CD3DSettingsDlg +{ +public: + CD3DSettingsDlg(); + ~CD3DSettingsDlg(); + + void Init( CDXUTDialogResourceManager* pManager ); + void Init( CDXUTDialogResourceManager* pManager, LPCWSTR szControlTextureFileName ); + void Init( CDXUTDialogResourceManager* pManager, LPCWSTR pszControlTextureResourcename, + HMODULE hModule ); + + HRESULT Refresh(); + void OnRender( float fElapsedTime ); + void OnRender9( float fElapsedTime ); + void OnRender10( float fElapsedTime ); + void OnRender11( float fElapsedTime ); + + HRESULT OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice ); + HRESULT OnD3D9ResetDevice(); + void OnD3D9LostDevice(); + void OnD3D9DestroyDevice(); + + HRESULT OnD3D11CreateDevice( ID3D11Device* pd3dDevice ); + HRESULT OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, + const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc ); + void OnD3D11DestroyDevice(); + + CDXUTDialog* GetDialogControl() + { + return &m_Dialog; + } + bool IsActive() + { + return m_bActive; + } + void SetActive( bool bActive ) + { + m_bActive = bActive; if( bActive ) Refresh(); + } + void ShowControlSet( DXUTDeviceVersion ver ); + + LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + +protected: + friend CD3DSettingsDlg* WINAPI DXUTGetD3DSettingsDialog(); + + void CreateControls(); + HRESULT SetDeviceSettingsFromUI(); + void SetSelectedD3D11RefreshRate( DXGI_RATIONAL RefreshRate ); + HRESULT UpdateD3D11Resolutions(); + + void OnEvent( UINT nEvent, int nControlID, CDXUTControl* pControl ); + static void WINAPI StaticOnEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserData ); + static void WINAPI StaticOnModeChangeTimer( UINT nIDEvent, void* pUserContext ); + + CD3D9EnumAdapterInfo* GetCurrentAdapterInfo(); + CD3D9EnumDeviceInfo* GetCurrentDeviceInfo(); + CD3D9EnumDeviceSettingsCombo* GetCurrentDeviceSettingsCombo(); + + CD3D11EnumAdapterInfo* GetCurrentD3D11AdapterInfo(); + CD3D11EnumDeviceInfo* GetCurrentD3D11DeviceInfo(); + CD3D11EnumOutputInfo* GetCurrentD3D11OutputInfo(); + CD3D11EnumDeviceSettingsCombo* GetCurrentD3D11DeviceSettingsCombo(); + + void AddAPIVersion( DXUTDeviceVersion version ); + DXUTDeviceVersion GetSelectedAPIVersion(); + + void AddAdapter( const WCHAR* strDescription, UINT iAdapter ); + UINT GetSelectedAdapter(); + + void AddDeviceType( D3DDEVTYPE devType ); + D3DDEVTYPE GetSelectedDeviceType(); + + void SetWindowed( bool bWindowed ); + bool IsWindowed(); + + void AddAdapterFormat( D3DFORMAT format ); + D3DFORMAT GetSelectedAdapterFormat(); + + void AddResolution( DWORD dwWidth, DWORD dwHeight ); + void GetSelectedResolution( DWORD* pdwWidth, DWORD* pdwHeight ); + + void AddRefreshRate( DWORD dwRate ); + DWORD GetSelectedRefreshRate(); + + void AddBackBufferFormat( D3DFORMAT format ); + D3DFORMAT GetSelectedBackBufferFormat(); + + void AddDepthStencilBufferFormat( D3DFORMAT format ); + D3DFORMAT GetSelectedDepthStencilBufferFormat(); + + void AddMultisampleType( D3DMULTISAMPLE_TYPE type ); + D3DMULTISAMPLE_TYPE GetSelectedMultisampleType(); + + void AddMultisampleQuality( DWORD dwQuality ); + DWORD GetSelectedMultisampleQuality(); + + void AddVertexProcessingType( DWORD dwType ); + DWORD GetSelectedVertexProcessingType(); + + DWORD GetSelectedPresentInterval(); + + void SetDeviceClip( bool bDeviceClip ); + bool IsDeviceClip(); + + // D3D11 + void AddD3D11DeviceType( D3D_DRIVER_TYPE devType ); + D3D_DRIVER_TYPE GetSelectedD3D11DeviceType(); + + void AddD3D11AdapterOutput( const WCHAR* strName, UINT nOutput ); + UINT GetSelectedD3D11AdapterOutput(); + + void AddD3D11Resolution( DWORD dwWidth, DWORD dwHeight ); + void GetSelectedD3D11Resolution( DWORD* pdwWidth, DWORD* pdwHeight ); + + void AddD3D11FeatureLevel(D3D_FEATURE_LEVEL); + D3D_FEATURE_LEVEL GetSelectedFeatureLevel(); + + void AddD3D11RefreshRate( DXGI_RATIONAL RefreshRate ); + DXGI_RATIONAL GetSelectedD3D11RefreshRate(); + + void AddD3D11BackBufferFormat( DXGI_FORMAT format ); + DXGI_FORMAT GetSelectedD3D11BackBufferFormat(); + + void AddD3D11MultisampleCount( UINT count ); + UINT GetSelectedD3D11MultisampleCount(); + + void AddD3D11MultisampleQuality( UINT Quality ); + UINT GetSelectedD3D11MultisampleQuality(); + + DWORD GetSelectedD3D11PresentInterval(); + bool GetSelectedDebugDeviceValue(); + + + + HRESULT OnD3D11ResolutionChanged (); + HRESULT OnAPIVersionChanged( bool bRefresh=false ); + HRESULT OnFeatureLevelChanged(); + HRESULT OnAdapterChanged(); + HRESULT OnDeviceTypeChanged(); + HRESULT OnWindowedFullScreenChanged(); + HRESULT OnAdapterOutputChanged(); + HRESULT OnAdapterFormatChanged(); + HRESULT OnResolutionChanged(); + HRESULT OnRefreshRateChanged(); + HRESULT OnBackBufferFormatChanged(); + HRESULT OnDepthStencilBufferFormatChanged(); + HRESULT OnMultisampleTypeChanged(); + HRESULT OnMultisampleQualityChanged(); + HRESULT OnVertexProcessingChanged(); + HRESULT OnPresentIntervalChanged(); + HRESULT OnDebugDeviceChanged(); + HRESULT OnDeviceClipChanged(); + + void UpdateModeChangeTimeoutText( int nSecRemaining ); + + IDirect3DStateBlock9* m_pStateBlock; + CDXUTDialog* m_pActiveDialog; + CDXUTDialog m_Dialog; + CDXUTDialog m_RevertModeDialog; + int m_nRevertModeTimeout; + UINT m_nIDEvent; + bool m_bActive; + + D3D_FEATURE_LEVEL m_Levels[TOTAL_FEATURE_LEVLES]; + +}; + + +CD3DSettingsDlg* WINAPI DXUTGetD3DSettingsDialog(); + + + +#endif + diff --git a/Demos/DX11ClothDemo/DXUT/Optional/ImeUi.cpp b/Demos/DX11ClothDemo/DXUT/Optional/ImeUi.cpp new file mode 100644 index 0000000..912c6d6 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/ImeUi.cpp @@ -0,0 +1,3662 @@ +//-------------------------------------------------------------------------------------- +// File: ImeUi.cpp +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "dxut.h" +#include "ImeUi.h" +#include +#include +#include +#include + +// Ignore typecast warnings +#pragma warning( disable : 4312 ) +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4311 ) + + +#define MAX_CANDIDATE_LENGTH 256 +#define COUNTOF(a) ( sizeof( a ) / sizeof( ( a )[0] ) ) +#define POSITION_UNINITIALIZED ((DWORD)-1) + +#define LANG_CHT MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL) +#define LANG_CHS MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED) + +#define MAKEIMEVERSION(major,minor) ( (DWORD)( ( (BYTE)( major ) << 24 ) | ( (BYTE)( minor ) << 16 ) ) ) +#define IMEID_VER(dwId) ( ( dwId ) & 0xffff0000 ) +#define IMEID_LANG(dwId) ( ( dwId ) & 0x0000ffff ) + +#define _CHT_HKL_DAYI ( (HKL)0xE0060404 ) // DaYi +#define _CHT_HKL_NEW_PHONETIC ( (HKL)0xE0080404 ) // New Phonetic +#define _CHT_HKL_NEW_CHANG_JIE ( (HKL)0xE0090404 ) // New Chang Jie +#define _CHT_HKL_NEW_QUICK ( (HKL)0xE00A0404 ) // New Quick +#define _CHT_HKL_HK_CANTONESE ( (HKL)0xE00B0404 ) // Hong Kong Cantonese +#define _CHT_IMEFILENAME "TINTLGNT.IME" // New Phonetic +#define _CHT_IMEFILENAME2 "CINTLGNT.IME" // New Chang Jie +#define _CHT_IMEFILENAME3 "MSTCIPHA.IME" // Phonetic 5.1 +#define IMEID_CHT_VER42 ( LANG_CHT | MAKEIMEVERSION( 4, 2 ) ) // New(Phonetic/ChanJie)IME98 : 4.2.x.x // Win98 +#define IMEID_CHT_VER43 ( LANG_CHT | MAKEIMEVERSION( 4, 3 ) ) // New(Phonetic/ChanJie)IME98a : 4.3.x.x // Win2k +#define IMEID_CHT_VER44 ( LANG_CHT | MAKEIMEVERSION( 4, 4 ) ) // New ChanJie IME98b : 4.4.x.x // WinXP +#define IMEID_CHT_VER50 ( LANG_CHT | MAKEIMEVERSION( 5, 0 ) ) // New(Phonetic/ChanJie)IME5.0 : 5.0.x.x // WinME +#define IMEID_CHT_VER51 ( LANG_CHT | MAKEIMEVERSION( 5, 1 ) ) // New(Phonetic/ChanJie)IME5.1 : 5.1.x.x // IME2002(w/OfficeXP) +#define IMEID_CHT_VER52 ( LANG_CHT | MAKEIMEVERSION( 5, 2 ) ) // New(Phonetic/ChanJie)IME5.2 : 5.2.x.x // IME2002a(w/WinXP) +#define IMEID_CHT_VER60 ( LANG_CHT | MAKEIMEVERSION( 6, 0 ) ) // New(Phonetic/ChanJie)IME6.0 : 6.0.x.x // New IME 6.0(web download) +#define IMEID_CHT_VER_VISTA ( LANG_CHT | MAKEIMEVERSION( 7, 0 ) ) // All TSF TIP under Cicero UI-less mode: a hack to make GetImeId() return non-zero value + +#define _CHS_HKL ( (HKL)0xE00E0804 ) // MSPY +#define _CHS_IMEFILENAME "PINTLGNT.IME" // MSPY1.5/2/3 +#define _CHS_IMEFILENAME2 "MSSCIPYA.IME" // MSPY3 for OfficeXP +#define IMEID_CHS_VER41 ( LANG_CHS | MAKEIMEVERSION( 4, 1 ) ) // MSPY1.5 // SCIME97 or MSPY1.5 (w/Win98, Office97) +#define IMEID_CHS_VER42 ( LANG_CHS | MAKEIMEVERSION( 4, 2 ) ) // MSPY2 // Win2k/WinME +#define IMEID_CHS_VER53 ( LANG_CHS | MAKEIMEVERSION( 5, 3 ) ) // MSPY3 // WinXP + +static CHAR signature[] = "%%%IMEUILIB:070111%%%"; + +static IMEUI_APPEARANCE gSkinIME = +{ + 0, // symbolColor; + 0x404040, // symbolColorOff; + 0xff000000, // symbolColorText; + 24, // symbolHeight; + 0xa0, // symbolTranslucence; + 0, // symbolPlacement; + NULL, // symbolFont; + 0xffffffff, // candColorBase; + 0xff000000, // candColorBorder; + 0, // candColorText; + 0x00ffff00, // compColorInput; + 0x000000ff, // compColorTargetConv; + 0x0000ff00, // compColorConverted; + 0x00ff0000, // compColorTargetNotConv; + 0x00ff0000, // compColorInputErr; + 0x80, // compTranslucence; + 0, // compColorText; + 2, // caretWidth; + 1, // caretYMargin; +}; + +struct _SkinCompStr +{ + DWORD colorInput; + DWORD colorTargetConv; + DWORD colorConverted; + DWORD colorTargetNotConv; + DWORD colorInputErr; +}; + +_SkinCompStr gSkinCompStr; + +// Definition from Win98DDK version of IMM.H +typedef struct +tagINPUTCONTEXT2 +{ + HWND hWnd; + BOOL fOpen; + POINT ptStatusWndPos; + POINT ptSoftKbdPos; + DWORD fdwConversion; + DWORD fdwSentence; + union + { + LOGFONTA A; + LOGFONTW W; + } lfFont; + COMPOSITIONFORM cfCompForm; + CANDIDATEFORM cfCandForm[4]; + HIMCC hCompStr; + HIMCC hCandInfo; + HIMCC hGuideLine; + HIMCC hPrivate; + DWORD dwNumMsgBuf; + HIMCC hMsgBuf; + DWORD fdwInit; + DWORD dwReserve[3]; +} +INPUTCONTEXT2, *PINPUTCONTEXT2, NEAR *NPINPUTCONTEXT2, +FAR* LPINPUTCONTEXT2; + + +// Class to disable Cicero in case ImmDisableTextFrameService() doesn't disable it completely +class CDisableCicero +{ +public: + CDisableCicero() : m_ptim( NULL ), + m_bComInit( false ) + { + } + ~CDisableCicero() + { + Uninitialize(); + } + void Initialize() + { + if( m_bComInit ) + { + return; + } + HRESULT hr; + hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ); + if( SUCCEEDED( hr ) ) + { + m_bComInit = true; + hr = CoCreateInstance( CLSID_TF_ThreadMgr, + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( ITfThreadMgr ), + ( void** )&m_ptim ); + } + } + void Uninitialize() + { + if( m_ptim ) + { + m_ptim->Release(); + m_ptim = NULL; + } + if( m_bComInit ) + CoUninitialize(); + m_bComInit = false; + } + + void DisableCiceroOnThisWnd( HWND hwnd ) + { + if( m_ptim == NULL ) + return; + ITfDocumentMgr* pdimPrev; // the dim that is associated previously. + // Associate NULL dim to the window. + // When this window gets the focus, Cicero does not work and IMM32 IME + // will be activated. + if( SUCCEEDED( m_ptim->AssociateFocus( hwnd, NULL, &pdimPrev ) ) ) + { + if( pdimPrev ) + pdimPrev->Release(); + } + } +private: + ITfThreadMgr* m_ptim; + bool m_bComInit; +}; +static CDisableCicero g_disableCicero; + +#define _IsLeadByte(x) ( LeadByteTable[(BYTE)( x )] ) +static void _PumpMessage(); +static BYTE LeadByteTable[256]; +#define _ImmGetContext ImmGetContext +#define _ImmReleaseContext ImmReleaseContext +#define _ImmAssociateContext ImmAssociateContext +static LONG ( WINAPI* _ImmGetCompositionString )( HIMC himc, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen ); +#define _ImmGetOpenStatus ImmGetOpenStatus +#define _ImmSetOpenStatus ImmSetOpenStatus +#define _ImmGetConversionStatus ImmGetConversionStatus +static DWORD ( WINAPI* _ImmGetCandidateList )( HIMC himc, DWORD deIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen ); +static LPINPUTCONTEXT2 ( WINAPI* _ImmLockIMC )( HIMC hIMC ); +static BOOL ( WINAPI* _ImmUnlockIMC )( HIMC hIMC ); +static LPVOID ( WINAPI* _ImmLockIMCC )( HIMCC hIMCC ); +static BOOL ( WINAPI* _ImmUnlockIMCC )( HIMCC hIMCC ); +#define _ImmGetDefaultIMEWnd ImmGetDefaultIMEWnd +#define _ImmGetIMEFileNameA ImmGetIMEFileNameA +#define _ImmGetVirtualKey ImmGetVirtualKey +#define _ImmNotifyIME ImmNotifyIME +#define _ImmSetConversionStatus ImmSetConversionStatus +#define _ImmSimulateHotKey ImmSimulateHotKey +#define _ImmIsIME ImmIsIME + +// private API provided by CHT IME. Available on version 6.0 or later. +UINT ( WINAPI*_GetReadingString )( HIMC himc, UINT uReadingBufLen, LPWSTR lpwReadingBuf, PINT pnErrorIndex, + BOOL* pfIsVertical, PUINT puMaxReadingLen ); +BOOL ( WINAPI*_ShowReadingWindow )( HIMC himc, BOOL bShow ); + +// Callbacks +void ( CALLBACK*ImeUiCallback_DrawRect )( int x1, int y1, int x2, int y2, DWORD color ); +void ( CALLBACK*ImeUiCallback_DrawFans )( const IMEUI_VERTEX* paVertex, UINT uNum ); +void* ( __cdecl*ImeUiCallback_Malloc )( size_t bytes ); +void ( __cdecl*ImeUiCallback_Free )( void* ptr ); +void ( CALLBACK*ImeUiCallback_OnChar )( WCHAR wc ); + +static void (*_SendCompString )(); +static LRESULT ( WINAPI* _SendMessage )( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) = SendMessageA; +static DWORD (* _GetCandidateList )( HIMC himc, DWORD dwIndex, LPCANDIDATELIST* ppCandList ); + +static HWND g_hwndMain; +static HWND g_hwndCurr; +static HIMC g_himcOrg; +static bool g_bImeEnabled = false; +static TCHAR g_szCompositionString[256]; +static BYTE g_szCompAttrString[256]; +static DWORD g_IMECursorBytes = 0; +static DWORD g_IMECursorChars = 0; +static TCHAR g_szCandidate[MAX_CANDLIST][MAX_CANDIDATE_LENGTH]; +static DWORD g_dwSelection, g_dwCount; +static UINT g_uCandPageSize; +static DWORD g_bDisableImeCompletely = false; +static DWORD g_dwIMELevel; +static DWORD g_dwIMELevelSaved; +static TCHAR g_szMultiLineCompString[ 256 *( 3 - sizeof( TCHAR ) ) ]; +static bool g_bReadingWindow = false; +static bool g_bHorizontalReading = false; +static bool g_bVerticalCand = true; +static UINT g_uCaretBlinkTime = 0; +static UINT g_uCaretBlinkLast = 0; +static bool g_bCaretDraw = false; +static bool g_bChineseIME; +static bool g_bInsertMode = true; +static TCHAR g_szReadingString[32]; // Used only in case of horizontal reading window +static int g_iReadingError; // Used only in case of horizontal reading window +static UINT g_screenWidth, g_screenHeight; +static DWORD g_dwPrevFloat; +static bool bIsSendingKeyMessage = false; +static OSVERSIONINFOA g_osi; +static bool g_bInitialized = false; +static bool g_bCandList = false; +static DWORD g_dwCandX, g_dwCandY; +static DWORD g_dwCaretX, g_dwCaretY; +static DWORD g_hCompChar; +static int g_iCandListIndexBase; +static DWORD g_dwImeUiFlags = IMEUI_FLAG_SUPPORT_CARET; +static bool g_bUILessMode = false; +static HMODULE g_hImmDll = NULL; + +#define IsNT() (g_osi.dwPlatformId == VER_PLATFORM_WIN32_NT) + +struct CompStringAttribute +{ + UINT caretX; + UINT caretY; + CImeUiFont_Base* pFont; + DWORD colorComp; + DWORD colorCand; + RECT margins; +}; + +static CompStringAttribute g_CaretInfo; +static DWORD g_dwState = IMEUI_STATE_OFF; +static DWORD swirl = 0; +static double lastSwirl; + +#define INDICATOR_NON_IME 0 +#define INDICATOR_CHS 1 +#define INDICATOR_CHT 2 +#define INDICATOR_KOREAN 3 +#define INDICATOR_JAPANESE 4 + +#define GETLANG() LOWORD(g_hklCurrent) +#define GETPRIMLANG() ((WORD)PRIMARYLANGID(GETLANG())) +#define GETSUBLANG() SUBLANGID(GETLANG()) + +#define LANG_CHS MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED) +#define LANG_CHT MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL) + +static HKL g_hklCurrent = 0; +static UINT g_uCodePage = 0; +static LPTSTR g_aszIndicator[] = +{ + TEXT( "A" ), +#ifdef UNICODE + L"\x7B80", + L"\x7E41", + L"\xac00", + L"\x3042", +#else + "\xd6\xd0", + "\xa4\xa4", + "\xb0\xa1", + "\x82\xa0", +#endif +}; +static LPTSTR g_pszIndicatior = g_aszIndicator[0]; + +static void GetReadingString( HWND hWnd ); +static DWORD GetImeId( UINT uIndex = 0 ); +static void CheckToggleState(); +static void DrawImeIndicator(); +static void DrawCandidateList(); +static void DrawCompositionString( bool bDrawCompAttr ); +static void GetReadingWindowOrientation( DWORD dwId ); +static void OnInputLangChangeWorker(); +static void OnInputLangChange(); +static void SetImeApi(); +static void CheckInputLocale(); +static void SetSupportLevel( DWORD dwImeLevel ); +void ImeUi_SetSupportLevel( DWORD dwImeLevel ); + + +// +// local helper functions +// +inline LRESULT SendKeyMsg( HWND hwnd, UINT msg, WPARAM wp ) +{ + bIsSendingKeyMessage = true; + LRESULT lRc = _SendMessage( hwnd, msg, wp, 1 ); + bIsSendingKeyMessage = false; + return lRc; +} +#define SendKeyMsg_DOWN(hwnd,vk) SendKeyMsg(hwnd, WM_KEYDOWN, vk) +#define SendKeyMsg_UP(hwnd,vk) SendKeyMsg(hwnd, WM_KEYUP, vk) + +/////////////////////////////////////////////////////////////////////////////// +// +// CTsfUiLessMode +// Handles IME events using Text Service Framework (TSF). Before Vista, +// IMM (Input Method Manager) API has been used to handle IME events and +// inqueries. Some IMM functions lose backward compatibility due to design +// of TSF, so we have to use new TSF interfaces. +// +/////////////////////////////////////////////////////////////////////////////// +class CTsfUiLessMode +{ +protected: + // Sink receives event notifications + class CUIElementSink : public ITfUIElementSink, + public ITfInputProcessorProfileActivationSink, + public ITfCompartmentEventSink + { + public: + CUIElementSink(); + ~CUIElementSink(); + + // IUnknown + STDMETHODIMP QueryInterface( REFIID riid, void** ppvObj ); + STDMETHODIMP_( ULONG ) + AddRef( void ); + STDMETHODIMP_( ULONG ) + Release( void ); + + // ITfUIElementSink + // Notifications for Reading Window events. We could process candidate as well, but we'll use IMM for simplicity sake. + STDMETHODIMP BeginUIElement( DWORD dwUIElementId, BOOL* pbShow ); + STDMETHODIMP UpdateUIElement( DWORD dwUIElementId ); + STDMETHODIMP EndUIElement( DWORD dwUIElementId ); + + // ITfInputProcessorProfileActivationSink + // Notification for keyboard input locale change + STDMETHODIMP OnActivated( DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid, + REFGUID guidProfile, HKL hkl, DWORD dwFlags ); + + // ITfCompartmentEventSink + // Notification for open mode (toggle state) change + STDMETHODIMP OnChange( REFGUID rguid ); + + private: + LONG _cRef; + }; + + static void MakeReadingInformationString( ITfReadingInformationUIElement* preading ); + static void MakeCandidateStrings( ITfCandidateListUIElement* pcandidate ); + static ITfUIElement* GetUIElement( DWORD dwUIElementId ); + static BOOL GetCompartments( ITfCompartmentMgr** ppcm, ITfCompartment** ppTfOpenMode, + ITfCompartment** ppTfConvMode ); + static BOOL SetupCompartmentSinks( BOOL bResetOnly = FALSE, ITfCompartment* pTfOpenMode = NULL, + ITfCompartment* ppTfConvMode = NULL ); + + static ITfThreadMgrEx* m_tm; + static DWORD m_dwUIElementSinkCookie; + static DWORD m_dwAlpnSinkCookie; + static DWORD m_dwOpenModeSinkCookie; + static DWORD m_dwConvModeSinkCookie; + static CUIElementSink* m_TsfSink; + static int m_nCandidateRefCount; // Some IME shows multiple candidate lists but the Library doesn't support multiple candidate list. + // So track open / close events to make sure the candidate list opened last is shown. + CTsfUiLessMode() + { + } // this class can't be instanciated + +public: + static BOOL SetupSinks(); + static void ReleaseSinks(); + static BOOL CurrentInputLocaleIsIme(); + static void UpdateImeState( BOOL bResetCompartmentEventSink = FALSE ); + static void EnableUiUpdates( bool bEnable ); +}; + +ITfThreadMgrEx* CTsfUiLessMode::m_tm; +DWORD CTsfUiLessMode::m_dwUIElementSinkCookie = TF_INVALID_COOKIE; +DWORD CTsfUiLessMode::m_dwAlpnSinkCookie = TF_INVALID_COOKIE; +DWORD CTsfUiLessMode::m_dwOpenModeSinkCookie = TF_INVALID_COOKIE; +DWORD CTsfUiLessMode::m_dwConvModeSinkCookie = TF_INVALID_COOKIE; +CTsfUiLessMode::CUIElementSink* CTsfUiLessMode::m_TsfSink = NULL; +int CTsfUiLessMode::m_nCandidateRefCount = NULL; + +static unsigned long _strtoul( LPCSTR psz, LPTSTR*, int ) +{ + if( !psz ) + return 0; + + ULONG ulRet = 0; + if( psz[0] == '0' && ( psz[1] == 'x' || psz[1] == 'X' ) ) + { + psz += 2; + ULONG ul = 0; + while( *psz ) + { + if( '0' <= *psz && *psz <= '9' ) + ul = *psz - '0'; + else if( 'A' <= *psz && *psz <= 'F' ) + ul = *psz - 'A' + 10; + else if( 'a' <= *psz && *psz <= 'f' ) + ul = *psz - 'a' + 10; + else + break; + ulRet = ulRet * 16 + ul; + psz++; + } + } + else + { + while( *psz && ( '0' <= *psz && *psz <= '9' ) ) + { + ulRet = ulRet * 10 + ( *psz - '0' ); + psz++; + } + } + return ulRet; +} + +#ifdef UNICODE +#define GetCharCount(psz) lstrlen(psz) +#define GetCharCountFromBytes(psz,iBytes) (iBytes) +static void AW_SendCompString() +{ + int i, iLen; + if ( ImeUiCallback_OnChar ) + { + for ( i = 0; g_szCompositionString[i]; i++ ) + { + ImeUiCallback_OnChar( g_szCompositionString[i] ); + } + return; + } + + BYTE szCompStr[COUNTOF(g_szCompositionString) * 2]; + iLen = WideCharToMultiByte(g_uCodePage, 0, g_szCompositionString, -1, + (LPSTR)szCompStr, COUNTOF(szCompStr), NULL, NULL) - 1; // don't need to send NUL terminator; + for (i = 0; i < iLen; i++) + { + SendKeyMsg(g_hwndCurr, WM_CHAR, szCompStr[i]); + } +} + +// The following AW_Imm* functions are there to support Win95/98 first version. +// They can be deleted if the game doesn't supports them (i.e. games requires Win98 SE or later). +static DWORD AW_GetCandidateList(HIMC himc, DWORD dwIndex, LPCANDIDATELIST* ppCandList) +{ + DWORD dwBufLen = ImmGetCandidateListA( himc, dwIndex, NULL, 0 ); + if (dwBufLen) + { + LPCANDIDATELIST pCandList = (LPCANDIDATELIST)ImeUiCallback_Malloc(dwBufLen); + if (pCandList) { + dwBufLen = ImmGetCandidateListA( himc, dwIndex, pCandList, dwBufLen ); + if (dwBufLen) { + int i; + int wideBufLen = 0; + for (i = 0; i < (int)pCandList->dwCount; i++) { + wideBufLen += MultiByteToWideChar(g_uCodePage, 0, (LPSTR)pCandList + pCandList->dwOffset[i], -1, NULL, 0) * sizeof(WCHAR); + } + wideBufLen += pCandList->dwOffset[0]; + *ppCandList = (LPCANDIDATELIST)ImeUiCallback_Malloc(wideBufLen); + LPCANDIDATELIST pCandListW = *ppCandList; + memcpy(pCandListW, pCandList, pCandList->dwOffset[0]); + LPWSTR pwz = (LPWSTR)((LPSTR)pCandListW + pCandList->dwOffset[0]); + for (i = 0; i < (int)pCandList->dwCount; i++) { + pCandListW->dwOffset[i] = (LPSTR)pwz - (LPSTR)pCandListW; + pwz += MultiByteToWideChar(g_uCodePage, 0, (LPSTR)pCandList + pCandList->dwOffset[i], -1, pwz, 256); + } + dwBufLen = wideBufLen; + } + ImeUiCallback_Free(pCandList); + } + } + return dwBufLen; +} + +static LONG WINAPI AW_ImmGetCompositionString(HIMC himc, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen) +{ + char pszMb[COUNTOF(g_szCompositionString) * 2]; + DWORD dwRet = ImmGetCompositionStringA(himc, dwIndex, pszMb, sizeof(pszMb)); + switch (dwIndex) { + case GCS_RESULTSTR: + case GCS_COMPSTR: + if (dwRet) { + pszMb[dwRet] = 0; + dwRet = (DWORD)MultiByteToWideChar(g_uCodePage, 0, pszMb, -1, (LPWSTR)lpBuf, dwBufLen); + if (dwRet) { + // Note that ImmGetCompositionString() returns number of bytes copied, regardless of the width of character. + dwRet = (dwRet - 1) * sizeof(WCHAR); + } + } + break; + case GCS_CURSORPOS: + dwRet /= 2; + break; + case GCS_COMPATTR: { + char pszMb2[COUNTOF(g_szCompositionString) * 2]; + DWORD dwRet2 = ImmGetCompositionStringA(himc, GCS_COMPSTR, pszMb2, sizeof(pszMb2)); + if (!dwRet2) { + dwRet2 = ImmGetCompositionStringA(himc, GCS_RESULTSTR, pszMb2, sizeof(pszMb2)); + if (!dwRet2) { + return 0; + } + } + char* pOut = (char*)lpBuf; + for (DWORD i = 0; i < dwRet; i++) { + *pOut++ = pszMb[i]; // copy attribute + if (_IsLeadByte(pszMb2[i])) + i++; + } + dwRet = pOut - (char*)lpBuf; + } + break; + } + return dwRet; +} + +#else // !UNICODE +// returns number of characters from number of bytes +static int GetCharCountFromBytes( LPCSTR pszString, int iBytes ) +{ + int iCount = 0; + int i; + for( i = 0; pszString[i] && i < iBytes; i++ ) + { + iCount++; + if( _IsLeadByte(pszString[i]) ) + i++; + } + if( i != iBytes ) + iCount = -iCount; // indicate error - iBytes specifies wrong boundary (i.e. the last byte is leadbyte) + return iCount; +} + +static int GetCharCount( LPTSTR psz ) +{ + int i = 0; + while( *psz ) + { + if( _IsLeadByte(*psz) ) + { + psz++; + } + psz++; + i++; + } + return i; +} + +static DWORD WA_GetCandidateList( HIMC himc, DWORD dwIndex, LPCANDIDATELIST* ppCandList ) +{ + DWORD dwBufLen = ImmGetCandidateListW( himc, dwIndex, NULL, 0 ); + if( dwBufLen ) + { + LPCANDIDATELIST pCandList = ( LPCANDIDATELIST )ImeUiCallback_Malloc( dwBufLen ); + if( pCandList ) + { + dwBufLen = ImmGetCandidateListW( himc, dwIndex, pCandList, dwBufLen ); + if( dwBufLen ) + { + int i; + int mbBufLen = 0; + for( i = 0; i < ( int )pCandList->dwCount; i++ ) + { + mbBufLen += WideCharToMultiByte( g_uCodePage, 0, ( LPWSTR )( ( LPSTR )pCandList + + pCandList->dwOffset[i] ), -1, NULL, 0, + NULL, NULL ); + } + mbBufLen += pCandList->dwOffset[0]; + *ppCandList = ( LPCANDIDATELIST )ImeUiCallback_Malloc( mbBufLen ); + LPCANDIDATELIST pCandListA = *ppCandList; + memcpy( pCandListA, pCandList, pCandList->dwOffset[0] ); + LPSTR psz = ( LPSTR )pCandListA + pCandList->dwOffset[0]; + for( i = 0; i < ( int )pCandList->dwCount; i++ ) + { + pCandListA->dwOffset[i] = ( LPSTR )psz - ( LPSTR )pCandListA; + psz += WideCharToMultiByte( g_uCodePage, 0, ( LPWSTR )( ( LPSTR )pCandList + + pCandList->dwOffset[i] ), -1, psz, 256, + NULL, NULL ); + } + dwBufLen = mbBufLen; + } + ImeUiCallback_Free( pCandList ); + } + } + return dwBufLen; +} + +static LONG WINAPI WA_ImmGetCompositionString( HIMC himc, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen ) +{ + WCHAR pwzUc[COUNTOF(g_szCompositionString)]; + DWORD dwRet = ImmGetCompositionStringW( himc, dwIndex, pwzUc, sizeof( pwzUc ) ); + switch( dwIndex ) + { + case GCS_RESULTSTR: + case GCS_COMPSTR: + if( dwRet ) + { + pwzUc[dwRet / sizeof( WCHAR )] = 0; + dwRet = ( DWORD )WideCharToMultiByte( g_uCodePage, 0, pwzUc, -1, ( LPSTR )lpBuf, dwBufLen, NULL, + NULL ); + if( dwRet ) + { + dwRet = dwRet - 1; + } + } + break; + + case GCS_CURSORPOS: + { + WCHAR pwzUc2[COUNTOF(g_szCompositionString)]; + DWORD dwRet2 = ImmGetCompositionStringW( himc, GCS_COMPSTR, pwzUc2, sizeof( pwzUc2 ) ); + if( !dwRet2 ) + { + dwRet2 = ImmGetCompositionStringW( himc, GCS_RESULTSTR, pwzUc2, sizeof( pwzUc2 ) ); + if( !dwRet2 ) + { + return 0; + } + } + dwRet2 /= 2; + //The return value of WideCharToMultiByte() should probably be checked/asserted for success. + //bounds violation (overflow) 'pszMb[iRc]' + const int bufSize = COUNTOF(g_szCompositionString) * 2; + char pszMb[bufSize]; + int iRc = WideCharToMultiByte( g_uCodePage, 0, pwzUc2, dwRet2, pszMb, sizeof( pszMb ), NULL, NULL ); + assert( iRc > 0 ); //WideCharToMultiByte returns 0 if it failed, and it should *never* be negative in the first place + if( iRc >= bufSize ) //if we wrote more bytes than the length of the buffer, we need to terminate it + { + pszMb[ bufSize - 1] = 0; //0 terminate the end of the buffer + } + else + { + pszMb[ iRc ] = 0; + } + char* psz = pszMb; + for( dwRet2 = 0; dwRet2 != dwRet; dwRet2++ ) + { + if( _IsLeadByte( *psz ) ) + psz++; + psz++; + } + dwRet = psz - pszMb; + } + break; + + case GCS_COMPATTR: + { + WCHAR pwzUc2[COUNTOF(g_szCompositionString)]; + DWORD dwRet2 = ImmGetCompositionStringW( himc, GCS_COMPSTR, pwzUc2, sizeof( pwzUc2 ) ); + if( !dwRet2 ) + { + dwRet2 = ImmGetCompositionStringW( himc, GCS_RESULTSTR, pwzUc2, sizeof( pwzUc2 ) ); + if( !dwRet2 ) + { + return 0; + } + } + dwRet2 /= 2; + const int bufSize = COUNTOF(g_szCompositionString) * 2; + char pszMb[bufSize]; + int iRc = WideCharToMultiByte( g_uCodePage, 0, pwzUc2, dwRet2, pszMb, sizeof( pszMb ), NULL, NULL ); + assert( iRc > 0 ); //WideCharToMultiByte returns 0 if it failed, and it should *never* be negative in the first place + if( iRc >= bufSize ) //if we wrote more bytes than the length of the buffer, we need to terminate it + { + pszMb[ bufSize - 1] = 0; //0 terminate the end of the buffer + } + else + { + pszMb[ iRc ] = 0; + } + char* pSrc = ( char* )pwzUc; + char* pOut = ( char* )lpBuf; + for( char* psz = pszMb; *psz; psz++, pSrc++ ) + { + *pOut++ = *pSrc; // copy attribute + if( _IsLeadByte( *psz ) ) + { + *pOut++ = *pSrc; + psz++; + } + // buffer overrun protection, pOut is incremented in the loop, but not part of the + // loop invariant test. To make the code more readable we have a test rather than + // rolling this into the for stmt. + if( ( DWORD )( pOut - ( char* )lpBuf ) >= dwBufLen ) + break; + } + dwRet = pOut - ( char* )lpBuf; + } + break; + } + return dwRet; +} + +#endif // UNICODE + +static void ComposeCandidateLine( int index, LPCTSTR pszCandidate ) +{ + LPTSTR psz = g_szCandidate[index]; + *psz++ = ( TCHAR )( TEXT( '0' ) + ( ( index + g_iCandListIndexBase ) % 10 ) ); + if( g_bVerticalCand ) + { + *psz++ = TEXT( ' ' ); + } + while( *pszCandidate && ( COUNTOF(g_szCandidate[index]) > ( psz - g_szCandidate[index] ) ) ) + { + *psz++ = *pszCandidate++; + } + *psz = 0; +} + +static void SendCompString() +{ + int i, iLen = lstrlen( g_szCompositionString ); + if( ImeUiCallback_OnChar ) + { + LPCWSTR pwz; +#ifdef UNICODE + pwz = g_szCompositionString; +#else + WCHAR szUnicode[COUNTOF( g_szCompositionString ) ]; + pwz = szUnicode; + iLen = MultiByteToWideChar( g_uCodePage, 0, g_szCompositionString, -1, szUnicode, COUNTOF(szUnicode) ) - 1; +#endif + for( i = 0; i < iLen; i++ ) + { + ImeUiCallback_OnChar( pwz[i] ); + } + return; + } + for( i = 0; i < iLen; i++ ) + { + SendKeyMsg( g_hwndCurr, WM_CHAR, +#ifdef UNICODE + (WPARAM)g_szCompositionString[i] +#else + ( WPARAM )( BYTE )g_szCompositionString[i] +#endif + ); + } +} + +static DWORD GetCandidateList( HIMC himc, DWORD dwIndex, LPCANDIDATELIST* ppCandList ) +{ + DWORD dwBufLen = _ImmGetCandidateList( himc, dwIndex, NULL, 0 ); + if( dwBufLen ) + { + *ppCandList = ( LPCANDIDATELIST )ImeUiCallback_Malloc( dwBufLen ); + dwBufLen = _ImmGetCandidateList( himc, dwIndex, *ppCandList, dwBufLen ); + } + return dwBufLen; +} + +static void SendControlKeys( UINT vk, UINT num ) +{ + if( num == 0 ) + return; + for( UINT i = 0; i < num; i++ ) + { + SendKeyMsg_DOWN(g_hwndCurr, vk); + } + SendKeyMsg_UP(g_hwndCurr, vk); +} + +// send key messages to erase composition string. +static void CancelCompString( HWND hwnd, bool bUseBackSpace = true, int iNewStrLen = 0 ) +{ + if( g_dwIMELevel != 3 ) + return; + int cc = GetCharCount( g_szCompositionString ); + int i; + // move caret to the end of composition string + SendControlKeys( VK_RIGHT, cc - g_IMECursorChars ); + + if( bUseBackSpace || g_bInsertMode ) + iNewStrLen = 0; + + // The caller sets bUseBackSpace to false if there's possibility of sending + // new composition string to the app right after this function call. + // + // If the app is in overwriting mode and new comp string is + // shorter than current one, delete previous comp string + // till it's same long as the new one. Then move caret to the beginning of comp string. + // New comp string will overwrite old one. + if( iNewStrLen < cc ) + { + for( i = 0; i < cc - iNewStrLen; i++ ) + { + SendKeyMsg_DOWN(hwnd, VK_BACK); + SendKeyMsg( hwnd, WM_CHAR, 8 ); //Backspace character + } + SendKeyMsg_UP(hwnd, VK_BACK); + } + else + iNewStrLen = cc; + + SendControlKeys( VK_LEFT, iNewStrLen ); +} + +// initialize composition string data. +static void InitCompStringData( void ) +{ + g_IMECursorBytes = 0; + g_IMECursorChars = 0; + memset( &g_szCompositionString, 0, sizeof( g_szCompositionString ) ); + memset( &g_szCompAttrString, 0, sizeof( g_szCompAttrString ) ); +} + +static void DrawCaret( DWORD x, DWORD y, DWORD height ) +{ + if( g_bCaretDraw && ImeUiCallback_DrawRect ) + ImeUiCallback_DrawRect( x, y + gSkinIME.caretYMargin, x + gSkinIME.caretWidth, + y + height - gSkinIME.caretYMargin, g_CaretInfo.colorComp ); +} + +// +// Apps that draw the composition string on top of composition string attribute +// in level 3 support should call this function twice in rendering a frame. +// // Draw edit box UI; +// ImeUi_RenderUI(true, false); // paint composition string attribute; +// // Draw text in the edit box; +// ImeUi_RenderUi(false, true); // paint the rest of IME UI; +// +void ImeUi_RenderUI( bool bDrawCompAttr, bool bDrawOtherUi ) +{ + if( !g_bInitialized || !g_bImeEnabled || !g_CaretInfo.pFont ) + return; + if( !bDrawCompAttr && !bDrawOtherUi ) + return; // error case + if( g_dwIMELevel == 2 ) + { + if( !bDrawOtherUi ) + return; // 1st call for level 3 support + } + + if( bDrawOtherUi ) + DrawImeIndicator(); + + DrawCompositionString( bDrawCompAttr ); + + if( bDrawOtherUi ) + DrawCandidateList(); +} + +static void DrawImeIndicator() +{ + bool bOn = g_dwState != IMEUI_STATE_OFF; + + IMEUI_VERTEX PieData[17]; + float SizeOfPie = ( float )gSkinIME.symbolHeight; + + memset( PieData, 0, sizeof( PieData ) ); + + switch( gSkinIME.symbolPlacement ) + { + case 0: // vertical centering IME indicator + { + if( SizeOfPie + g_CaretInfo.margins.right + 4 > g_screenWidth ) + { + PieData[0].sx = ( -SizeOfPie / 2 ) + g_CaretInfo.margins.left - 4; + PieData[0].sy = ( float )g_CaretInfo.margins.top + ( g_CaretInfo.margins.bottom - + g_CaretInfo.margins.top ) / 2; + } + else + { + PieData[0].sx = -( SizeOfPie / 2 ) + g_CaretInfo.margins.right + gSkinIME.symbolHeight + 4; + PieData[0].sy = ( float )g_CaretInfo.margins.top + ( g_CaretInfo.margins.bottom - + g_CaretInfo.margins.top ) / 2; + } + break; + } + case 1: // upperleft + PieData[0].sx = 4 + ( SizeOfPie / 2 ); + PieData[0].sy = 4 + ( SizeOfPie / 2 ); + break; + case 2: // upperright + PieData[0].sx = g_screenWidth - ( 4 + ( SizeOfPie / 2 ) ); + PieData[0].sy = 4 + ( SizeOfPie / 2 ); + break; + case 3: // lowerright + PieData[0].sx = g_screenWidth - ( 4 + ( SizeOfPie / 2 ) ); + PieData[0].sy = g_screenHeight - ( 4 + ( SizeOfPie / 2 ) ); + break; + case 4: // lowerleft + PieData[0].sx = 4 + ( SizeOfPie / 2 ); + PieData[0].sy = g_screenHeight - ( 4 + ( SizeOfPie / 2 ) ); + break; + } + PieData[0].rhw = 1.0f; + if( bOn ) + { + if( GetTickCount() - lastSwirl > 250 ) + { + swirl++; + lastSwirl = GetTickCount(); + if( swirl > 13 ) + swirl = 0; + } + } + else + swirl = 0; + for( int t1 = 1; t1 < 16; t1++ ) + { + float radian = 2.0f * 3.1415926f * ( t1 - 1 + ( bOn * swirl ) ) / 14.0f; + PieData[t1].sx = ( float )( PieData[0].sx + SizeOfPie / 2 * cos( radian ) ); + PieData[t1].sy = ( float )( PieData[0].sy + SizeOfPie / 2 * sin( radian ) ); + PieData[t1].rhw = 1.0f; + } + + PieData[0].color = 0xffffff + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + if( !gSkinIME.symbolColor && bOn ) + { + { + PieData[1].color = 0xff0000 + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + PieData[2].color = 0xff3000 + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + PieData[3].color = 0xff6000 + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + PieData[4].color = 0xff9000 + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + PieData[5].color = 0xffC000 + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + PieData[6].color = 0xffff00 + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + PieData[7].color = 0xC0ff00 + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + PieData[8].color = 0x90ff00 + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + PieData[9].color = 0x60ff00 + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + PieData[10].color = 0x30c0ff + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + PieData[11].color = 0x00a0ff + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + PieData[12].color = 0x3090ff + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + PieData[13].color = 0x6060ff + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + PieData[14].color = 0x9030ff + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + PieData[15].color = 0xc000ff + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + } + } + else + { + DWORD dwColor = bOn ? gSkinIME.symbolColor : gSkinIME.symbolColorOff; + for( int t1 = 1; t1 < 16; t1++ ) + { + PieData[t1].color = dwColor + ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ); + } + } + PieData[16] = PieData[1]; + + if( ImeUiCallback_DrawFans ) + ImeUiCallback_DrawFans( PieData, 17 ); + + float fHeight = gSkinIME.symbolHeight * 0.625f; + + // fix for Ent Gen #120 - reduce the height of character when Korean IME is on + if( GETPRIMLANG() == LANG_KOREAN && bOn ) + { + fHeight *= 0.8f; + } + + if( gSkinIME.symbolFont ) + { +#ifdef DS2 + // save the font height here since DS2 shares editbox font and indicator font + DWORD _w, _h; + g_CaretInfo.pFont->GetTextExtent( TEXT(" "), &_w, &_h ); +#endif //DS2 + + // GOS deals height in points that is 1/72nd inch and assumes display device is 96dpi. + fHeight = fHeight * 96 / 72; + gSkinIME.symbolFont->SetHeight( ( UINT )fHeight ); + gSkinIME.symbolFont->SetColor( ( ( ( DWORD )gSkinIME.symbolTranslucence ) << 24 ) | gSkinIME.symbolColorText ); + + // + // draw the proper symbol over the fan + // + DWORD w, h; + LPCTSTR cszSymbol = ( g_dwState == IMEUI_STATE_ON ) ? g_pszIndicatior : g_aszIndicator[0]; + + gSkinIME.symbolFont->GetTextExtent( cszSymbol, &w, &h ); + gSkinIME.symbolFont->SetPosition( ( int )( PieData[0].sx ) - w / 2, ( int )( PieData[0].sy ) - h / 2 ); + gSkinIME.symbolFont->DrawText( cszSymbol ); + +#ifdef DS2 + // revert the height. + g_CaretInfo.pFont->SetHeight( _h ); + + // Double-check: Confirm match by testing a range of font heights to find best fit + DWORD _h2; + g_CaretInfo.pFont->GetTextExtent( TEXT(" "), &_w, &_h2 ); + if ( _h2 < _h ) + { + for ( int i=1; _h2<_h && i<10; i++ ) + { + g_CaretInfo.pFont->SetHeight( _h+i ); + g_CaretInfo.pFont->GetTextExtent( TEXT(" "), &_w, &_h2 ); + } + } + else if ( _h2 > _h ) + { + for ( int i=1; _h2>_h && i<10; i++ ) + { + g_CaretInfo.pFont->SetHeight( _h-i ); + g_CaretInfo.pFont->GetTextExtent( TEXT(" "), &_w, &_h2 ); + } + } +#endif //DS2 + } +} + +static void DrawCompositionString( bool bDrawCompAttr ) +{ + // Process timer for caret blink + UINT uCurrentTime = GetTickCount(); + if( uCurrentTime - g_uCaretBlinkLast > g_uCaretBlinkTime ) + { + g_uCaretBlinkLast = uCurrentTime; + g_bCaretDraw = !g_bCaretDraw; + } + + int i = 0; + + g_CaretInfo.pFont->SetColor( g_CaretInfo.colorComp ); + + DWORD uDummy; + + int len = lstrlen( g_szCompositionString ); + + DWORD bgX = g_CaretInfo.caretX; + DWORD bgY = g_CaretInfo.caretY; + g_dwCaretX = POSITION_UNINITIALIZED; + g_dwCaretY = POSITION_UNINITIALIZED; + DWORD candX = POSITION_UNINITIALIZED; + DWORD candY = 0; + LPTSTR pszMlcs = g_szMultiLineCompString; + + DWORD wCompChar = 0; + DWORD hCompChar = 0; + g_CaretInfo.pFont->GetTextExtent( TEXT( " " ), &uDummy, &hCompChar ); + if( g_dwIMELevel == 3 && g_IMECursorBytes && g_szCompositionString[0] ) + { + // shift starting point of drawing composition string according to the current caret position. + TCHAR temp = g_szCompositionString[g_IMECursorBytes]; + g_szCompositionString[g_IMECursorBytes] = 0; + g_CaretInfo.pFont->GetTextExtent( g_szCompositionString, &wCompChar, &hCompChar ); + g_szCompositionString[g_IMECursorBytes] = temp; + bgX -= wCompChar; + } + + // + // Draw the background colors for IME text nuggets + // + bool saveCandPos = false; + DWORD cType = 1; + LPTSTR pszCurrentCompLine = g_szCompositionString; + DWORD dwCompLineStart = bgX; + DWORD bgXnext = bgX; + + if( GETPRIMLANG() != LANG_KOREAN || g_bCaretDraw ) // Korean uses composition attribute as blinking block caret + for( i = 0; i < len; i += cType ) + { + DWORD bgColor = 0x00000000; + TCHAR szChar[3]; + szChar[0] = g_szCompositionString[i]; + szChar[1] = szChar[2] = 0; +#ifndef UNICODE + cType = 1 + ( ( _IsLeadByte(g_szCompositionString[i]) ) ? 1 : 0 ); + if( cType == 2 && g_szCompositionString[i + 1] ) // in case we have 0 in trailbyte, we don't count it. + szChar[1] = g_szCompositionString[i + 1]; +#endif + bgX = bgXnext; + TCHAR cSave = g_szCompositionString[i + cType]; + g_szCompositionString[i + cType] = 0; + g_CaretInfo.pFont->GetTextExtent( pszCurrentCompLine, &bgXnext, &hCompChar ); + g_szCompositionString[i + cType] = cSave; + bgXnext += dwCompLineStart; + wCompChar = bgXnext - bgX; + + switch( g_szCompAttrString[i] ) + { + case ATTR_INPUT: + bgColor = gSkinCompStr.colorInput; + break; + case ATTR_TARGET_CONVERTED: + bgColor = gSkinCompStr.colorTargetConv; + if( IMEID_LANG( GetImeId() ) != LANG_CHS ) + saveCandPos = true; + break; + case ATTR_CONVERTED: + bgColor = gSkinCompStr.colorConverted; + break; + case ATTR_TARGET_NOTCONVERTED: + // + // This is the one the user is working with currently + // + bgColor = gSkinCompStr.colorTargetNotConv; + break; + case ATTR_INPUT_ERROR: + bgColor = gSkinCompStr.colorInputErr; + break; + default: + // STOP( TEXT( "Attributes on IME characters are wrong" ) ); + break; + } + + if( g_dwIMELevel == 3 && bDrawCompAttr ) + { + if( ( LONG )bgX >= g_CaretInfo.margins.left && ( LONG )bgX <= g_CaretInfo.margins.right ) + { + if( g_dwImeUiFlags & IMEUI_FLAG_SUPPORT_CARET ) + { + if( ImeUiCallback_DrawRect ) + ImeUiCallback_DrawRect( bgX, bgY, bgX + wCompChar, bgY + hCompChar, bgColor ); + } + else + { + if( ImeUiCallback_DrawRect ) + ImeUiCallback_DrawRect( bgX - wCompChar, bgY, bgX, bgY + hCompChar, bgColor ); + } + } + } + else if( g_dwIMELevel == 2 ) + { + // make sure enough buffer space (possible space, NUL for current line, possible DBCS, 2 more NUL) + // are available in multiline composition string buffer + bool bWrite = ( pszMlcs - g_szMultiLineCompString < + COUNTOF( g_szMultiLineCompString ) - 5 * ( 3 - sizeof( TCHAR ) ) ); + + if( ( LONG )( bgX + wCompChar ) >= g_CaretInfo.margins.right ) + { + bgX = dwCompLineStart = bgXnext = g_CaretInfo.margins.left; + bgY = bgY + hCompChar; + pszCurrentCompLine = g_szCompositionString + i; + if( bWrite ) + { + if( pszMlcs == g_szMultiLineCompString || pszMlcs[-1] == 0 ) + *pszMlcs++ = ' '; // to avoid zero length line + *pszMlcs++ = 0; + } + } + if( ImeUiCallback_DrawRect ) + ImeUiCallback_DrawRect( bgX, bgY, bgX + wCompChar, bgY + hCompChar, bgColor ); + if( bWrite ) + { + *pszMlcs++ = g_szCompositionString[i]; +#ifndef UNICODE + if( cType == 2 ) + *pszMlcs++ = g_szCompositionString[i + 1]; +#endif + } + if( ( DWORD )i == g_IMECursorBytes ) + { + g_dwCaretX = bgX; + g_dwCaretY = bgY; + } + } + if( ( saveCandPos && candX == POSITION_UNINITIALIZED ) || + ( IMEID_LANG( GetImeId() ) == LANG_CHS && i / ( 3 - sizeof( TCHAR ) ) == ( int )g_IMECursorChars ) ) + { + candX = bgX; + candY = bgY; + } + saveCandPos = false; + } + + bgX = bgXnext; + if( g_dwIMELevel == 2 ) + { + // in case the caret in composition string is at the end of it, draw it here + if( len != 0 && ( DWORD )i == g_IMECursorBytes ) + { + g_dwCaretX = bgX; + g_dwCaretY = bgY; + } + + // Draw composition string. + //assert(pszMlcs - g_szMultiLineCompString <= + // sizeof(g_szMultiLineCompString) / sizeof(g_szMultiLineCompString[0]) - 2); + *pszMlcs++ = 0; + *pszMlcs++ = 0; + DWORD x, y; + x = g_CaretInfo.caretX; + y = g_CaretInfo.caretY; + pszMlcs = g_szMultiLineCompString; + while( *pszMlcs && + pszMlcs - g_szMultiLineCompString < sizeof( g_szMultiLineCompString ) / sizeof + ( g_szMultiLineCompString[0] ) ) + { + g_CaretInfo.pFont->SetPosition( x, y ); + g_CaretInfo.pFont->DrawText( pszMlcs ); + pszMlcs += lstrlen( pszMlcs ) + 1; + x = g_CaretInfo.margins.left; + y += hCompChar; + } + } + // for changing z-order of caret + if( g_dwCaretX != POSITION_UNINITIALIZED && g_dwCaretY != POSITION_UNINITIALIZED ) + { + DrawCaret( g_dwCaretX, g_dwCaretY, hCompChar ); + } + g_dwCandX = candX; + g_dwCandY = candY; + g_hCompChar = hCompChar; +} + +static void DrawCandidateList() +{ + DWORD candX = g_dwCandX; + DWORD candY = g_dwCandY; + DWORD hCompChar = g_hCompChar; + int i; + + // draw candidate list / reading window + if( !g_dwCount || g_szCandidate[0][0] == 0 ) + { + return; + } + + // If position of candidate list is not initialized yet, set it here. + if( candX == POSITION_UNINITIALIZED ) + { + // CHT IME in Vista doesn't have ATTR_TARGET_CONVERTED attribute while typing, + // so display the candidate list near the caret in the composition string + if( GETLANG() == LANG_CHT && GetImeId() != 0 && g_dwCaretX != POSITION_UNINITIALIZED ) + { + candX = g_dwCaretX; + candY = g_dwCaretY; + } + else + { + candX = g_CaretInfo.caretX; + candY = g_CaretInfo.caretY; + } + } + + SIZE largest = + { + 0,0 + }; + + static DWORD uDigitWidth = 0; + DWORD uSpaceWidth = 0; + static DWORD uDigitWidthList[10]; + static CImeUiFont_Base* pPrevFont = NULL; + // find out the widest width of the digits + if( pPrevFont != g_CaretInfo.pFont ) + { + pPrevFont = g_CaretInfo.pFont; + for( int cnt = 0; cnt <= 9; cnt++ ) + { + DWORD uDW = 0; + DWORD uDH = 0; + TCHAR ss[8]; + swprintf_s( ss, COUNTOF(ss), TEXT( "%d" ), cnt ); + g_CaretInfo.pFont->GetTextExtent( ss, &uDW, &uDH ); + uDigitWidthList[cnt] = uDW; + if( uDW > uDigitWidth ) + uDigitWidth = uDW; + if( ( signed )uDH > largest.cy ) + largest.cy = uDH; + } + } + uSpaceWidth = uDigitWidth; + DWORD dwMarginX = ( uSpaceWidth + 1 ) / 2; + DWORD adwCandWidth[ MAX_CANDLIST ]; + + // Find out the widest width of the candidate strings + DWORD dwCandWidth = 0; + if( g_bReadingWindow && g_bHorizontalReading ) + g_CaretInfo.pFont->GetTextExtent( g_szReadingString, ( DWORD* )&largest.cx, ( DWORD* )&largest.cy ); + else + { + for( i = 0; g_szCandidate[i][0] && i < ( int )g_uCandPageSize; i++ ) + { + DWORD tx = 0; + DWORD ty = 0; + + if( g_bReadingWindow ) + g_CaretInfo.pFont->GetTextExtent( g_szCandidate[i], &tx, &ty ); + else + { + if( g_bVerticalCand ) + g_CaretInfo.pFont->GetTextExtent( g_szCandidate[i] + 2, &tx, &ty ); + else + g_CaretInfo.pFont->GetTextExtent( g_szCandidate[i] + 1, &tx, &ty ); + tx = tx + uDigitWidth + uSpaceWidth; + } + + if( ( signed )tx > largest.cx ) + largest.cx = tx; + if( ( signed )ty > largest.cy ) + largest.cy = ty; + adwCandWidth[ i ] = tx; + dwCandWidth += tx; + } + } + + DWORD slotsUsed; + if( g_bReadingWindow && g_dwCount < g_uCandPageSize ) + slotsUsed = g_dwCount; + else + slotsUsed = g_uCandPageSize; + + // Show candidate list above composition string if there isn't enough room below. + DWORD dwCandHeight; + if( g_bVerticalCand && !( g_bReadingWindow && g_bHorizontalReading ) ) + dwCandHeight = slotsUsed * largest.cy + 2; + else + dwCandHeight = largest.cy + 2; + if( candY + hCompChar + dwCandHeight > g_screenHeight ) + candY -= dwCandHeight; + else + candY += hCompChar; + if( ( int )candY < 0 ) + candY = 0; + + // Move candidate list horizontally to keep it inside of screen + if( !g_bReadingWindow && IMEID_LANG( GetImeId() ) == LANG_CHS ) + dwCandWidth += dwMarginX * ( slotsUsed - 1 ); + else if( g_bReadingWindow && g_bHorizontalReading ) + dwCandWidth = largest.cx + 2 + dwMarginX * 2; + else if( g_bVerticalCand || g_bReadingWindow ) + dwCandWidth = largest.cx + 2 + dwMarginX * 2; + else + dwCandWidth = slotsUsed * ( largest.cx + 1 ) + 1; + if( candX + dwCandWidth > g_screenWidth ) + candX = g_screenWidth - dwCandWidth; + if( ( int )candX < 0 ) + candX = 0; + + // Draw frame and background of candidate list / reading window + int seperateLineX = 0; + int left = candX; + int top = candY; + int right = candX + dwCandWidth; + int bottom = candY + dwCandHeight; + if( ImeUiCallback_DrawRect ) + ImeUiCallback_DrawRect( left, top, right, bottom, gSkinIME.candColorBorder ); + left++; + top++; + right--; + bottom--; + if( g_bReadingWindow || IMEID_LANG( GetImeId() ) == LANG_CHS ) + { + if( ImeUiCallback_DrawRect ) + ImeUiCallback_DrawRect( left, top, right, bottom, gSkinIME.candColorBase ); + } + else if( g_bVerticalCand ) + { + // uDigitWidth is the max width of all digits. + if( !g_bReadingWindow ) + { + seperateLineX = left + dwMarginX + uDigitWidth + uSpaceWidth / 2; + if( ImeUiCallback_DrawRect ) + { + ImeUiCallback_DrawRect( left, top, seperateLineX - 1, bottom, gSkinIME.candColorBase ); + ImeUiCallback_DrawRect( seperateLineX, top, right, bottom, gSkinIME.candColorBase ); + } + } + } + else + { + for( i = 0; ( DWORD )i < slotsUsed; i++ ) + { + if( ImeUiCallback_DrawRect ) + ImeUiCallback_DrawRect( left, top, left + largest.cx, bottom, gSkinIME.candColorBase ); + left += largest.cx + 1; + } + } + + // Draw candidates / reading strings + candX++; + candY++; + if( g_bReadingWindow && g_bHorizontalReading ) + { + int iStart = -1, iEnd = -1, iDummy; + candX += dwMarginX; + + // draw background of error character if it exists + TCHAR szTemp[COUNTOF( g_szReadingString ) ]; + if( g_iReadingError >= 0 ) + { + StringCchCopy( szTemp, COUNTOF(szTemp), g_szReadingString ); + LPTSTR psz = szTemp + g_iReadingError; +#ifdef UNICODE + psz++; +#else + psz += ( _IsLeadByte( szTemp[g_iReadingError] ) ) ? 2 : 1; +#endif + *psz = 0; + g_CaretInfo.pFont->GetTextExtent( szTemp, ( DWORD* )&iEnd, ( DWORD* )&iDummy ); + TCHAR cSave = szTemp[ g_iReadingError ]; + szTemp[g_iReadingError] = 0; + g_CaretInfo.pFont->GetTextExtent( szTemp, ( DWORD* )&iStart, ( DWORD* )&iDummy ); + szTemp[g_iReadingError] = cSave; + if( ImeUiCallback_DrawRect ) + ImeUiCallback_DrawRect( candX + iStart, candY, candX + iEnd, candY + largest.cy, + gSkinIME.candColorBorder ); + } + + g_CaretInfo.pFont->SetPosition( candX, candY ); + g_CaretInfo.pFont->SetColor( g_CaretInfo.colorCand ); + g_CaretInfo.pFont->DrawText( g_szReadingString ); + + // draw error character if it exists + if( iStart >= 0 ) + { + g_CaretInfo.pFont->SetPosition( candX + iStart, candY ); + if( gSkinIME.candColorBase != 0xffffffff || gSkinIME.candColorBorder != 0xff000000 ) + g_CaretInfo.pFont->SetColor( g_CaretInfo.colorCand ); + else + g_CaretInfo.pFont->SetColor( 0xff000000 + ( ~( ( 0x00ffffff ) & g_CaretInfo.colorCand ) ) ); + g_CaretInfo.pFont->DrawText( szTemp + g_iReadingError ); + } + } + else + { + for( i = 0; i < ( int )g_uCandPageSize && ( DWORD )i < g_dwCount; i++ ) + { + if( g_dwSelection == ( DWORD )i ) + { + if( gSkinIME.candColorBase != 0xffffffff || gSkinIME.candColorBorder != 0xff000000 ) + g_CaretInfo.pFont->SetColor( g_CaretInfo.colorCand ); + else + g_CaretInfo.pFont->SetColor( 0xff000000 + ( ~( ( 0x00ffffff ) & g_CaretInfo.colorCand ) ) ); + + if( ImeUiCallback_DrawRect ) + { + if( g_bReadingWindow || g_bVerticalCand ) + ImeUiCallback_DrawRect( candX, candY + i * largest.cy, + candX - 1 + dwCandWidth, candY + ( i + 1 ) * largest.cy, + gSkinIME.candColorBorder ); + else + ImeUiCallback_DrawRect( candX, candY, + candX + adwCandWidth[i], candY + largest.cy, + gSkinIME.candColorBorder ); + } + } + else + g_CaretInfo.pFont->SetColor( g_CaretInfo.colorCand ); + if( g_szCandidate[i][0] != 0 ) + { + if( !g_bReadingWindow && g_bVerticalCand ) + { + TCHAR szOneDigit[2] = + { + g_szCandidate[i][0], 0 + }; + int nOneDigit = g_szCandidate[i][0] - TEXT( '0' ); + TCHAR* szCandidateBody = g_szCandidate[i] + 2; + + int dx = candX + ( seperateLineX - candX - uDigitWidthList[nOneDigit] ) / 2; + int dy = candY + largest.cy * i; + + g_CaretInfo.pFont->SetPosition( dx, dy ); + g_CaretInfo.pFont->DrawText( szOneDigit ); + g_CaretInfo.pFont->SetPosition( seperateLineX + dwMarginX, dy ); + g_CaretInfo.pFont->DrawText( szCandidateBody ); + } + else if( g_bReadingWindow ) + { + g_CaretInfo.pFont->SetPosition( dwMarginX + candX, candY + i * largest.cy ); + g_CaretInfo.pFont->DrawText( g_szCandidate[i] ); + } + else + { + g_CaretInfo.pFont->SetPosition( uSpaceWidth / 2 + candX, candY ); + g_CaretInfo.pFont->DrawText( g_szCandidate[i] ); + } + } + if( !g_bReadingWindow && !g_bVerticalCand ) + { + if( IMEID_LANG( GetImeId() ) == LANG_CHS ) + candX += adwCandWidth[i] + dwMarginX; + else + candX += largest.cx + 1; + } + } + } +} + +static void CloseCandidateList() +{ + g_bCandList = false; + if( !g_bReadingWindow ) // fix for Ent Gen #120. + { + g_dwCount = 0; + memset( &g_szCandidate, 0, sizeof( g_szCandidate ) ); + } +} + +// +// ProcessIMEMessages() +// Processes IME related messages and acquire information +// +LPARAM ImeUi_ProcessMessage( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM& lParam, bool* trapped ) +{ + HIMC himc; + int len; + static LPARAM lAlt = 0x80000000, lCtrl = 0x80000000, lShift = 0x80000000; + + *trapped = false; + if( !g_bInitialized || g_bDisableImeCompletely ) + { + return 0; + } + + switch( uMsg ) + { + // + // IME Handling + // + case WM_INPUTLANGCHANGE: + OnInputLangChange(); + break; + + case WM_IME_SETCONTEXT: + // + // We don't want anything to display, so we have to clear lParam and pass it to DefWindowProc(). + // Expecially important in Vista to receive IMN_CHANGECANDIDATE correctly. + // + lParam = 0; + break; + + case WM_IME_STARTCOMPOSITION: + InitCompStringData(); + *trapped = true; + break; + + case WM_IME_COMPOSITION: + { + LONG lRet; + TCHAR szCompStr[COUNTOF(g_szCompositionString)]; + + *trapped = true; + if( NULL == ( himc = _ImmGetContext( hWnd ) ) ) + { + break; + } + + // ResultStr must be processed before composition string. + if( lParam & GCS_RESULTSTR ) + { + lRet = ( LONG )_ImmGetCompositionString( himc, GCS_RESULTSTR, szCompStr, + COUNTOF( szCompStr ) ) / sizeof( TCHAR ); + szCompStr[lRet] = 0; + CancelCompString( g_hwndCurr, false, GetCharCount( szCompStr ) ); + StringCchCopy( g_szCompositionString, COUNTOF(g_szCompositionString), szCompStr ); + _SendCompString(); + InitCompStringData(); + } + // + // Reads in the composition string. + // + if( lParam & GCS_COMPSTR ) + { + ////////////////////////////////////////////////////// + // Retrieve the latest user-selected IME candidates + lRet = ( LONG )_ImmGetCompositionString( himc, GCS_COMPSTR, szCompStr, + COUNTOF( szCompStr ) ) / sizeof( TCHAR ); + szCompStr[lRet] = 0; + // + // Remove the whole of the string + // + CancelCompString( g_hwndCurr, false, GetCharCount( szCompStr ) ); + + StringCchCopy( g_szCompositionString, COUNTOF(g_szCompositionString), szCompStr ); + lRet = _ImmGetCompositionString( himc, GCS_COMPATTR, g_szCompAttrString, + COUNTOF( g_szCompAttrString ) ); + g_szCompAttrString[lRet] = 0; + // Older CHT IME uses composition string for reading string + if( GETLANG() == LANG_CHT && !GetImeId() ) + { + int i, chars = lstrlen( g_szCompositionString ) / ( 3 - sizeof( TCHAR ) ); + if( chars ) + { + g_dwCount = 4; + g_dwSelection = ( DWORD )-1; // don't select any candidate + + for( i = 3; i >= 0; i-- ) + { + if( i > chars - 1 ) + g_szCandidate[i][0] = 0; + else + { +#ifdef UNICODE + g_szCandidate[i][0] = g_szCompositionString[i]; + g_szCandidate[i][1] = 0; +#else + g_szCandidate[i][0] = g_szCompositionString[i * 2]; + g_szCandidate[i][1] = g_szCompositionString[i * 2 + 1]; + g_szCandidate[i][2] = 0; +#endif + } + } + g_uCandPageSize = MAX_CANDLIST; + memset( g_szCompositionString, 0, 8 ); + g_bReadingWindow = true; + GetReadingWindowOrientation( 0 ); + if( g_bHorizontalReading ) + { + g_iReadingError = -1; + g_szReadingString[0] = 0; + for( i = 0; i < ( int )g_dwCount; i++ ) + { + if( g_dwSelection == ( DWORD )i ) + g_iReadingError = lstrlen( g_szReadingString ); + LPCTSTR pszTmp = g_szCandidate[i]; + wcscat_s( g_szReadingString, COUNTOF(g_szReadingString), pszTmp ); + } + } + } + else + g_dwCount = 0; + } + + // get caret position in composition string + g_IMECursorBytes = _ImmGetCompositionString( himc, GCS_CURSORPOS, NULL, 0 ); + g_IMECursorChars = GetCharCountFromBytes( g_szCompositionString, g_IMECursorBytes ); + + if( g_dwIMELevel == 3 ) + { + // send composition string via WM_CHAR + _SendCompString(); + // move caret to appropreate location + len = GetCharCount( g_szCompositionString + g_IMECursorBytes ); + SendControlKeys( VK_LEFT, len ); + } + } + _ImmReleaseContext( hWnd, himc ); + } + break; + + case WM_IME_ENDCOMPOSITION: + CancelCompString( g_hwndCurr ); + InitCompStringData(); + break; + + case WM_IME_NOTIFY: + switch( wParam ) + { + case IMN_SETCONVERSIONMODE: + { + // Disable CHT IME software keyboard. + static bool bNoReentrance = false; + if( LANG_CHT == GETLANG() && !bNoReentrance ) + { + bNoReentrance = true; + DWORD dwConvMode, dwSentMode; + _ImmGetConversionStatus( g_himcOrg, &dwConvMode, &dwSentMode ); + const DWORD dwFlag = IME_CMODE_SOFTKBD | IME_CMODE_SYMBOL; + if( dwConvMode & dwFlag ) + _ImmSetConversionStatus( g_himcOrg, dwConvMode & ~dwFlag, dwSentMode ); + } + bNoReentrance = false; + } + // fall through + case IMN_SETOPENSTATUS: + if( g_bUILessMode ) + break; + CheckToggleState(); + break; + + case IMN_OPENCANDIDATE: + case IMN_CHANGECANDIDATE: + if( g_bUILessMode ) + { + break; + } + { + g_bCandList = true; + *trapped = true; + if( NULL == ( himc = _ImmGetContext( hWnd ) ) ) + break; + + LPCANDIDATELIST lpCandList; + DWORD dwIndex, dwBufLen; + + g_bReadingWindow = false; + dwIndex = 0; + dwBufLen = _GetCandidateList( himc, dwIndex, &lpCandList ); + + if( dwBufLen ) + { + g_dwSelection = lpCandList->dwSelection; + g_dwCount = lpCandList->dwCount; + + int startOfPage = 0; + if( GETLANG() == LANG_CHS && GetImeId() ) + { + // MSPY (CHS IME) has variable number of candidates in candidate window + // find where current page starts, and the size of current page + const int maxCandChar = 18 * ( 3 - sizeof( TCHAR ) ); + UINT cChars = 0; + UINT i; + for( i = 0; i < g_dwCount; i++ ) + { + UINT uLen = lstrlen( + ( LPTSTR )( ( DWORD )lpCandList + lpCandList->dwOffset[i] ) ) + + ( 3 - sizeof( TCHAR ) ); + if( uLen + cChars > maxCandChar ) + { + if( i > g_dwSelection ) + { + break; + } + startOfPage = i; + cChars = uLen; + } + else + { + cChars += uLen; + } + } + g_uCandPageSize = i - startOfPage; + } + else + { + g_uCandPageSize = min( lpCandList->dwPageSize, MAX_CANDLIST ); + startOfPage = g_bUILessMode ? lpCandList->dwPageStart : + ( g_dwSelection / g_uCandPageSize ) * g_uCandPageSize; + } + + g_dwSelection = ( GETLANG() == LANG_CHS && !GetImeId() ) ? ( DWORD )-1 + : g_dwSelection - startOfPage; + + memset( &g_szCandidate, 0, sizeof( g_szCandidate ) ); + for( UINT i = startOfPage, j = 0; + ( DWORD )i < lpCandList->dwCount && j < g_uCandPageSize; + i++, j++ ) + { + ComposeCandidateLine( j, + ( LPTSTR )( ( DWORD )lpCandList + lpCandList->dwOffset[i] ) ); + } + ImeUiCallback_Free( ( HANDLE )lpCandList ); + _ImmReleaseContext( hWnd, himc ); + + // don't display selection in candidate list in case of Korean and old Chinese IME. + if( GETPRIMLANG() == LANG_KOREAN || + GETLANG() == LANG_CHT && !GetImeId() ) + g_dwSelection = ( DWORD )-1; + } + break; + } + + case IMN_CLOSECANDIDATE: + if( g_bUILessMode ) + { + break; + } + CloseCandidateList(); + *trapped = true; + break; + + // Jun.16,2000 05:21 by yutaka. + case IMN_PRIVATE: + { + if( !g_bCandList ) + { + GetReadingString( hWnd ); + } + // Trap some messages to hide reading window + DWORD dwId = GetImeId(); + switch( dwId ) + { + case IMEID_CHT_VER42: + case IMEID_CHT_VER43: + case IMEID_CHT_VER44: + case IMEID_CHS_VER41: + case IMEID_CHS_VER42: + if( ( lParam == 1 ) || ( lParam == 2 ) ) + { + *trapped = true; + } + break; + case IMEID_CHT_VER50: + case IMEID_CHT_VER51: + case IMEID_CHT_VER52: + case IMEID_CHT_VER60: + case IMEID_CHS_VER53: + if( ( lParam == 16 ) || ( lParam == 17 ) || ( lParam == 26 ) || ( lParam == 27 ) || + ( lParam == 28 ) ) + { + *trapped = true; + } + break; + } + } + break; + + default: + *trapped = true; + break; + } + break; + + // fix for #15386 - When Text Service Framework is installed in Win2K, Alt+Shift and Ctrl+Shift combination (to switch + // input locale / keyboard layout) doesn't send WM_KEYUP message for the key that is released first. We need to check + // if these keys are actually up whenever we receive key up message for other keys. + case WM_KEYUP: + case WM_SYSKEYUP: + if( !( lAlt & 0x80000000 ) && wParam != VK_MENU && ( GetAsyncKeyState( VK_MENU ) & 0x8000 ) == 0 ) + { + PostMessageA( GetFocus(), WM_KEYUP, ( WPARAM )VK_MENU, ( lAlt & 0x01ff0000 ) | 0xC0000001 ); + } + else if( !( lCtrl & 0x80000000 ) && wParam != VK_CONTROL && + ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) == 0 ) + { + PostMessageA( GetFocus(), WM_KEYUP, ( WPARAM )VK_CONTROL, ( lCtrl & 0x01ff0000 ) | 0xC0000001 ); + } + else if( !( lShift & 0x80000000 ) && wParam != VK_SHIFT && ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) == 0 ) + { + PostMessageA( GetFocus(), WM_KEYUP, ( WPARAM )VK_SHIFT, ( lShift & 0x01ff0000 ) | 0xC0000001 ); + } + // fall through WM_KEYDOWN / WM_SYSKEYDOWN + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + { + switch( wParam ) + { + case VK_MENU: + lAlt = lParam; + break; + case VK_SHIFT: + lShift = lParam; + break; + case VK_CONTROL: + lCtrl = lParam; + break; + } + } + break; + } + return 0; +} + +void ImeUi_SetCaretPosition( UINT x, UINT y ) +{ + if( !g_bInitialized ) + return; + g_CaretInfo.caretX = x; + g_CaretInfo.caretY = y; +} + +void ImeUi_SetCompStringAppearance( CImeUiFont_Base* pFont, DWORD color, const RECT* prc ) +{ + if( !g_bInitialized ) + return; + g_CaretInfo.pFont = pFont; + g_CaretInfo.margins = *prc; + + if( 0 == gSkinIME.candColorText ) + g_CaretInfo.colorCand = color; + else + g_CaretInfo.colorCand = gSkinIME.candColorText; + if( 0 == gSkinIME.compColorText ) + g_CaretInfo.colorComp = color; + else + g_CaretInfo.colorComp = gSkinIME.compColorText; +} + +void ImeUi_SetState( DWORD dwState ) +{ + if( !g_bInitialized ) + return; + HIMC himc; + if( dwState == IMEUI_STATE_ON ) + { + ImeUi_EnableIme( true ); + } + if( NULL != ( himc = _ImmGetContext( g_hwndCurr ) ) ) + { + if( g_bDisableImeCompletely ) + dwState = IMEUI_STATE_OFF; + + bool bOn = dwState == IMEUI_STATE_ON; // for non-Chinese IME + switch( GETPRIMLANG() ) + { + case LANG_CHINESE: + { + // toggle Chinese IME + DWORD dwId; + DWORD dwConvMode = 0, dwSentMode = 0; + if( ( g_bChineseIME && dwState == IMEUI_STATE_OFF ) || + ( !g_bChineseIME && dwState != IMEUI_STATE_OFF ) ) + { + _ImmSimulateHotKey( g_hwndCurr, IME_THOTKEY_IME_NONIME_TOGGLE ); + _PumpMessage(); + } + if( dwState != IMEUI_STATE_OFF ) + { + dwId = GetImeId(); + if( dwId ) + { + _ImmGetConversionStatus( himc, &dwConvMode, &dwSentMode ); + dwConvMode = ( dwState == IMEUI_STATE_ON ) + ? ( dwConvMode | IME_CMODE_NATIVE ) + : ( dwConvMode & ~IME_CMODE_NATIVE ); + _ImmSetConversionStatus( himc, dwConvMode, dwSentMode ); + } + } + break; + } + case LANG_KOREAN: + // toggle Korean IME + if( ( bOn && g_dwState != IMEUI_STATE_ON ) || ( !bOn && g_dwState == IMEUI_STATE_ON ) ) + { + _ImmSimulateHotKey( g_hwndCurr, IME_KHOTKEY_ENGLISH ); + } + break; + case LANG_JAPANESE: + _ImmSetOpenStatus( himc, bOn ); + break; + } + _ImmReleaseContext( g_hwndCurr, himc ); + CheckToggleState(); + } +} + +DWORD ImeUi_GetState() +{ + if( !g_bInitialized ) + return IMEUI_STATE_OFF; + CheckToggleState(); + return g_dwState; +} + +void ImeUi_EnableIme( bool bEnable ) +{ + if( !g_bInitialized || !g_hwndCurr ) + return; + if( g_bDisableImeCompletely ) + bEnable = false; + + if( g_hwndCurr == g_hwndMain ) + { + HIMC himcDbg; + himcDbg = _ImmAssociateContext( g_hwndCurr, bEnable? g_himcOrg : NULL ); + } + g_bImeEnabled = bEnable; + if( bEnable ) + { + CheckToggleState(); + } + CTsfUiLessMode::EnableUiUpdates( bEnable ); +} + +bool ImeUi_IsEnabled( void ) +{ + return g_bImeEnabled; +} + +bool ImeUi_Initialize( HWND hwnd, bool bDisable ) +{ + if( g_bInitialized ) + { + return true; + } + g_hwndMain = hwnd; + g_disableCicero.Initialize(); + + g_osi.dwOSVersionInfoSize = sizeof( OSVERSIONINFOA ); + GetVersionExA( &g_osi ); + + bool bUnicodeImm = false; + // IMM in NT or Win98 supports Unicode + if( g_osi.dwPlatformId == VER_PLATFORM_WIN32_NT || + ( g_osi.dwMajorVersion > 4 ) || + ( g_osi.dwMajorVersion == 4 ) && ( g_osi.dwMinorVersion > 0 ) ) + { + bUnicodeImm = true; + } + + g_hImmDll = LoadLibraryA( "imm32.dll" ); + g_bDisableImeCompletely = false; + + if( g_hImmDll ) + { + _ImmLockIMC = ( LPINPUTCONTEXT2 ( WINAPI* )( HIMC hIMC ) )GetProcAddress( g_hImmDll, "ImmLockIMC" ); + _ImmUnlockIMC = ( BOOL ( WINAPI* )( HIMC hIMC ) )GetProcAddress( g_hImmDll, "ImmUnlockIMC" ); + _ImmLockIMCC = ( LPVOID ( WINAPI* )( HIMCC hIMCC ) )GetProcAddress( g_hImmDll, "ImmLockIMCC" ); + _ImmUnlockIMCC = ( BOOL ( WINAPI* )( HIMCC hIMCC ) )GetProcAddress( g_hImmDll, "ImmUnlockIMCC" ); + BOOL ( WINAPI* _ImmDisableTextFrameService )( DWORD ) = ( BOOL ( WINAPI* )( DWORD ) )GetProcAddress( g_hImmDll, + "ImmDisableTextFrameService" ); + if( _ImmDisableTextFrameService ) + { + _ImmDisableTextFrameService( ( DWORD )-1 ); + } + } + else + { + g_bDisableImeCompletely = true; + return false; + } +#ifdef UNICODE + if ( bUnicodeImm ) + { + _ImmGetCompositionString = ImmGetCompositionStringW; + _ImmGetCandidateList = ImmGetCandidateListW; + _GetCandidateList = GetCandidateList; + } + else + { + _ImmGetCandidateList = ImmGetCandidateListA; + _ImmGetCompositionString = AW_ImmGetCompositionString; + _GetCandidateList = AW_GetCandidateList; + } +#else + if( bUnicodeImm ) + { + _ImmGetCompositionString = WA_ImmGetCompositionString; + _ImmGetCandidateList = ImmGetCandidateListA; + _GetCandidateList = WA_GetCandidateList; + } + else + { + _ImmGetCompositionString = ImmGetCompositionStringA; + _ImmGetCandidateList = ImmGetCandidateListA; + _GetCandidateList = GetCandidateList; + } +#endif + + // There are the following combinations of code config, window type, and the method of sending characters. + // Wnd: Unicode, Code: Unicode, Method: SendMessageW (SendMessageW must be supported since RegisterClassW is successful) + // Wnd: non Uni, Code: Unicode, Method: AW_SendCompString (Send characters in multibyte after W->A conversion) + // Wnd: Unicode, Code: non Uni, Method: SendMessageA (System does A->W conversion) - possible, but unlikely to be used. + // Wnd: non Uni, Code: non Uni, Method: SendMessageA +#ifdef UNICODE + if ( !IsWindowUnicode( hwnd ) ) + { + _SendCompString = AW_SendCompString; + } + else +#endif + { + _SendCompString = SendCompString; +#ifdef UNICODE + _SendMessage = SendMessageW; +#endif + } + + // turn init flag on so that subsequent calls to ImeUi functions work. + g_bInitialized = true; + + ImeUi_SetWindow( g_hwndMain ); + g_himcOrg = _ImmGetContext( g_hwndMain ); + _ImmReleaseContext( g_hwndMain, g_himcOrg ); + + if( !g_himcOrg ) + { + bDisable = true; + } + + // the following pointers to function has to be initialized before this function is called. + if( bDisable || + !ImeUiCallback_Malloc || + !ImeUiCallback_Free + ) + { + g_bDisableImeCompletely = true; + ImeUi_EnableIme( false ); + g_bInitialized = bDisable; + return false; + } + + g_uCaretBlinkTime = GetCaretBlinkTime(); + +#ifndef UNICODE + // Check if system is SBCS system + CPINFO cpi; + BOOL bRc = GetCPInfo( CP_ACP, &cpi ); + if( bRc ) + { + if( cpi.MaxCharSize == 1 ) + { + g_bDisableImeCompletely = true; // SBCS system. Disable IME. + } + } +#endif + + g_CaretInfo.caretX = 0; + g_CaretInfo.caretY = 0; + g_CaretInfo.pFont = 0; + g_CaretInfo.colorComp = 0; + g_CaretInfo.colorCand = 0; + g_CaretInfo.margins.left = 0; + g_CaretInfo.margins.right = 640; + g_CaretInfo.margins.top = 0; + g_CaretInfo.margins.bottom = 480; + + CheckInputLocale(); + OnInputLangChangeWorker(); + ImeUi_SetSupportLevel( 2 ); + + // SetupTSFSinks has to be called before CheckToggleState to make it work correctly. + g_bUILessMode = CTsfUiLessMode::SetupSinks() != FALSE; + CheckToggleState(); + if( g_bUILessMode ) + { + g_bChineseIME = ( GETPRIMLANG() == LANG_CHINESE ) && CTsfUiLessMode::CurrentInputLocaleIsIme(); + CTsfUiLessMode::UpdateImeState(); + } + ImeUi_EnableIme( false ); + + return true; +} + +void ImeUi_Uninitialize() +{ + if( !g_bInitialized ) + { + return; + } + CTsfUiLessMode::ReleaseSinks(); + if( g_hwndMain ) + { + ImmAssociateContext( g_hwndMain, g_himcOrg ); + } + g_hwndMain = NULL; + g_himcOrg = NULL; + if( g_hImmDll ) + { + FreeLibrary( g_hImmDll ); + g_hImmDll = NULL; + } + g_disableCicero.Uninitialize(); + g_bInitialized = false; +} + +// +// GetImeId( UINT uIndex ) +// returns +// returned value: +// 0: In the following cases +// - Non Chinese IME input locale +// - Older Chinese IME +// - Other error cases +// +// Othewise: +// When uIndex is 0 (default) +// bit 31-24: Major version +// bit 23-16: Minor version +// bit 15-0: Language ID +// When uIndex is 1 +// pVerFixedInfo->dwFileVersionLS +// +// Use IMEID_VER and IMEID_LANG macro to extract version and language information. +// +static DWORD GetImeId( UINT uIndex ) +{ + static HKL hklPrev = 0; + static DWORD dwRet[2] = + { + 0, 0 + }; + + DWORD dwVerSize; + DWORD dwVerHandle; + LPVOID lpVerBuffer; + LPVOID lpVerData; + UINT cbVerData; + char szTmp[1024]; + + if( uIndex >= sizeof( dwRet ) / sizeof( dwRet[0] ) ) + return 0; + + HKL kl = g_hklCurrent; + if( hklPrev == kl ) + { + return dwRet[uIndex]; + } + hklPrev = kl; + DWORD dwLang = ( ( DWORD )kl & 0xffff ); + + if( g_bUILessMode && GETLANG() == LANG_CHT ) + { + // In case of Vista, artifitial value is returned so that it's not considered as older IME. + dwRet[0] = IMEID_CHT_VER_VISTA; + dwRet[1] = 0; + return dwRet[0]; + } + + if( kl != _CHT_HKL_NEW_PHONETIC && kl != _CHT_HKL_NEW_CHANG_JIE + && kl != _CHT_HKL_NEW_QUICK && kl != _CHT_HKL_HK_CANTONESE && kl != _CHS_HKL ) + { + goto error; + } + + if( _ImmGetIMEFileNameA( kl, szTmp, sizeof( szTmp ) - 1 ) <= 0 ) + { + goto error; + } + + if( !_GetReadingString ) // IME that doesn't implement private API + { +#define LCID_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) + if( ( CompareStringA( LCID_INVARIANT, NORM_IGNORECASE, szTmp, -1, _CHT_IMEFILENAME, -1 ) != 2 ) + && ( CompareStringA( LCID_INVARIANT, NORM_IGNORECASE, szTmp, -1, _CHT_IMEFILENAME2, -1 ) != 2 ) + && ( CompareStringA( LCID_INVARIANT, NORM_IGNORECASE, szTmp, -1, _CHT_IMEFILENAME3, -1 ) != 2 ) + && ( CompareStringA( LCID_INVARIANT, NORM_IGNORECASE, szTmp, -1, _CHS_IMEFILENAME, -1 ) != 2 ) + && ( CompareStringA( LCID_INVARIANT, NORM_IGNORECASE, szTmp, -1, _CHS_IMEFILENAME2, -1 ) != 2 ) + ) + { + goto error; + } + } + + dwVerSize = GetFileVersionInfoSizeA( szTmp, &dwVerHandle ); + if( dwVerSize ) + { + lpVerBuffer = ( LPVOID )ImeUiCallback_Malloc( dwVerSize ); + if( lpVerBuffer ) + { + if( GetFileVersionInfoA( szTmp, dwVerHandle, dwVerSize, lpVerBuffer ) ) + { + if( VerQueryValueA( lpVerBuffer, "\\", &lpVerData, &cbVerData ) ) + { +#define pVerFixedInfo ((VS_FIXEDFILEINFO FAR*)lpVerData) + DWORD dwVer = pVerFixedInfo->dwFileVersionMS; + dwVer = ( dwVer & 0x00ff0000 ) << 8 | ( dwVer & 0x000000ff ) << 16; + if( _GetReadingString || + dwLang == LANG_CHT && ( + dwVer == MAKEIMEVERSION(4, 2) || + dwVer == MAKEIMEVERSION(4, 3) || + dwVer == MAKEIMEVERSION(4, 4) || + dwVer == MAKEIMEVERSION(5, 0) || + dwVer == MAKEIMEVERSION(5, 1) || + dwVer == MAKEIMEVERSION(5, 2) || + dwVer == MAKEIMEVERSION(6, 0) ) + || + dwLang == LANG_CHS && ( + dwVer == MAKEIMEVERSION(4, 1) || + dwVer == MAKEIMEVERSION(4, 2) || + dwVer == MAKEIMEVERSION(5, 3) ) ) + { + dwRet[0] = dwVer | dwLang; + dwRet[1] = pVerFixedInfo->dwFileVersionLS; + ImeUiCallback_Free( lpVerBuffer ); + return dwRet[0]; + } +#undef pVerFixedInfo + } + } + } + ImeUiCallback_Free( lpVerBuffer ); + } + + // The flow comes here in the following conditions + // - Non Chinese IME input locale + // - Older Chinese IME + // - Other error cases +error: + dwRet[0] = dwRet[1] = 0; + return dwRet[uIndex]; +} + +static void GetReadingString( HWND hWnd ) +{ + if( g_bUILessMode ) + { + return; + } + DWORD dwId = GetImeId(); + if( !dwId ) + { + return; + } + + HIMC himc; + himc = _ImmGetContext( hWnd ); + if( !himc ) + return; + + DWORD dwlen = 0; + DWORD dwerr = 0; + WCHAR wzBuf[16]; // We believe 16 wchars are big enough to hold reading string after having discussion with CHT IME team. + WCHAR* wstr = wzBuf; + bool unicode = FALSE; + LPINPUTCONTEXT2 lpIMC = NULL; + + if( _GetReadingString ) + { + BOOL bVertical; + UINT uMaxUiLen; + dwlen = _GetReadingString( himc, 0, NULL, ( PINT )&dwerr, &bVertical, &uMaxUiLen ); + if( dwlen ) + { + if( dwlen > COUNTOF(wzBuf) ) + { + dwlen = COUNTOF(wzBuf); + } + dwlen = _GetReadingString( himc, dwlen, wstr, ( PINT )&dwerr, &bVertical, &uMaxUiLen ); + } + + g_bHorizontalReading = bVertical == 0; + unicode = true; + } + else // IMEs that doesn't implement Reading String API + { + lpIMC = _ImmLockIMC( himc ); + + // *** hacking code from Michael Yang *** + + LPBYTE p = 0; + + switch( dwId ) + { + + case IMEID_CHT_VER42: // New(Phonetic/ChanJie)IME98 : 4.2.x.x // Win98 + case IMEID_CHT_VER43: // New(Phonetic/ChanJie)IME98a : 4.3.x.x // WinMe, Win2k + case IMEID_CHT_VER44: // New ChanJie IME98b : 4.4.x.x // WinXP + + p = *( LPBYTE* )( ( LPBYTE )_ImmLockIMCC( lpIMC->hPrivate ) + 24 ); + if( !p ) break; + dwlen = *( DWORD* )( p + 7 * 4 + 32 * 4 ); //m_dwInputReadStrLen + dwerr = *( DWORD* )( p + 8 * 4 + 32 * 4 ); //m_dwErrorReadStrStart + wstr = ( WCHAR* )( p + 56 ); + unicode = TRUE; + break; + + case IMEID_CHT_VER50: // 5.0.x.x // WinME + + p = *( LPBYTE* )( ( LPBYTE )_ImmLockIMCC( lpIMC->hPrivate ) + 3 * 4 ); // PCKeyCtrlManager + if( !p ) break; + p = *( LPBYTE* )( ( LPBYTE )p + 1 * 4 + 5 * 4 + 4 * 2 ); // = PCReading = &STypingInfo + if( !p ) break; + dwlen = *( DWORD* )( p + 1 * 4 + ( 16 * 2 + 2 * 4 ) + 5 * 4 + 16 ); //m_dwDisplayStringLength; + dwerr = *( DWORD* )( p + 1 * 4 + ( 16 * 2 + 2 * 4 ) + 5 * 4 + 16 + 1 * 4 ); //m_dwDisplayErrorStart; + wstr = ( WCHAR* )( p + 1 * 4 + ( 16 * 2 + 2 * 4 ) + 5 * 4 ); + unicode = FALSE; + break; + + case IMEID_CHT_VER51: // 5.1.x.x // IME2002(w/OfficeXP) + case IMEID_CHT_VER52: // 5.2.x.x // (w/whistler) + case IMEID_CHS_VER53: // 5.3.x.x // SCIME2k or MSPY3 (w/OfficeXP and Whistler) + + p = *( LPBYTE* )( ( LPBYTE )_ImmLockIMCC( lpIMC->hPrivate ) + 4 ); // PCKeyCtrlManager + if( !p ) break; + p = *( LPBYTE* )( ( LPBYTE )p + 1 * 4 + 5 * 4 ); // = PCReading = &STypingInfo + if( !p ) break; + dwlen = *( DWORD* )( p + 1 * 4 + ( 16 * 2 + 2 * 4 ) + 5 * 4 + 16 * 2 ); //m_dwDisplayStringLength; + dwerr = *( DWORD* )( p + 1 * 4 + ( 16 * 2 + 2 * 4 ) + 5 * 4 + 16 * 2 + 1 * 4 ); //m_dwDisplayErrorStart; + wstr = ( WCHAR* )( p + 1 * 4 + ( 16 * 2 + 2 * 4 ) + 5 * 4 ); + unicode = TRUE; + break; + + // the code tested only with Win 98 SE (MSPY 1.5/ ver 4.1.0.21) + case IMEID_CHS_VER41: + { + int offset; + offset = ( GetImeId( 1 ) >= 0x00000002 ) ? 8 : 7; + + p = *( LPBYTE* )( ( LPBYTE )_ImmLockIMCC( lpIMC->hPrivate ) + offset * 4 ); + if( !p ) break; + dwlen = *( DWORD* )( p + 7 * 4 + 16 * 2 * 4 ); + dwerr = *( DWORD* )( p + 8 * 4 + 16 * 2 * 4 ); + dwerr = min( dwerr, dwlen ); + wstr = ( WCHAR* )( p + 6 * 4 + 16 * 2 * 1 ); + unicode = TRUE; + break; + } + + case IMEID_CHS_VER42: // 4.2.x.x // SCIME98 or MSPY2 (w/Office2k, Win2k, WinME, etc) + { + int nTcharSize = IsNT() ? sizeof( WCHAR ) : sizeof( char ); + p = *( LPBYTE* )( ( LPBYTE )_ImmLockIMCC( lpIMC->hPrivate ) + 1 * 4 + 1 * 4 + 6 * 4 ); // = PCReading = &STypintInfo + if( !p ) break; + dwlen = *( DWORD* )( p + 1 * 4 + ( 16 * 2 + 2 * 4 ) + 5 * 4 + 16 * nTcharSize ); //m_dwDisplayStringLength; + dwerr = *( DWORD* )( p + 1 * 4 + ( 16 * 2 + 2 * 4 ) + 5 * 4 + 16 * nTcharSize + 1 * 4 ); //m_dwDisplayErrorStart; + wstr = ( WCHAR* )( p + 1 * 4 + ( 16 * 2 + 2 * 4 ) + 5 * 4 ); //m_tszDisplayString + unicode = IsNT() ? TRUE : FALSE; + } + } // switch + + g_szCandidate[0][0] = 0; + g_szCandidate[1][0] = 0; + g_szCandidate[2][0] = 0; + g_szCandidate[3][0] = 0; + } + g_dwCount = dwlen; + g_dwSelection = ( DWORD )-1; // do not select any char + if( unicode ) + { + int i; + for( i = 0; ( DWORD )i < dwlen; i++ ) // dwlen > 0, if known IME : yutakah + { + if( dwerr <= ( DWORD )i && g_dwSelection == ( DWORD )-1 ) + { // select error char + g_dwSelection = i; + } +#ifdef UNICODE + g_szCandidate[i][0] = wstr[i]; + g_szCandidate[i][1] = 0; +#else + char mbc[3]; + mbc[1] = 0; + mbc[2] = 0; + WideCharToMultiByte( g_uCodePage, 0, wstr + i, 1, mbc, sizeof( mbc ), NULL, NULL ); + + g_szCandidate[i][0] = mbc[0]; + g_szCandidate[i][1] = mbc[1]; + g_szCandidate[i][2] = 0; +#endif + } + g_szCandidate[i][0] = 0; + } + else + { + char* p = ( char* )wstr; + int i, j; + for( i = 0, j = 0; ( DWORD )i < dwlen; i++, j++ ) // dwlen > 0, if known IME : yutakah + { + if( dwerr <= ( DWORD )i && g_dwSelection == ( DWORD )-1 ) + { + g_dwSelection = ( DWORD )j; + } +#ifdef UNICODE + MultiByteToWideChar( g_uCodePage, 0, p + i, 1 + ( _IsLeadByte( p[i] ) ? 1 : 0 ), + g_szCandidate[j], 1 ); + if ( _IsLeadByte( p[i] ) ) + { + i++; + } +#else + g_szCandidate[j][0] = p[i]; + g_szCandidate[j][1] = 0; + g_szCandidate[j][2] = 0; + if( _IsLeadByte(p[i]) ) + { + i++; + g_szCandidate[j][1] = p[i]; + } +#endif + } + g_szCandidate[j][0] = 0; + g_dwCount = j; + } + if( !_GetReadingString ) + { + _ImmUnlockIMCC( lpIMC->hPrivate ); + _ImmUnlockIMC( himc ); + GetReadingWindowOrientation( dwId ); + } + _ImmReleaseContext( hWnd, himc ); + + g_bReadingWindow = true; + if( g_bHorizontalReading ) + { + g_iReadingError = -1; + g_szReadingString[0] = 0; + for( UINT i = 0; i < g_dwCount; i++ ) + { + if( g_dwSelection == ( DWORD )i ) + g_iReadingError = lstrlen( g_szReadingString ); + LPCTSTR pszTmp = g_szCandidate[i]; + wcscat_s( g_szReadingString, COUNTOF(g_szReadingString), pszTmp ); + } + } + g_uCandPageSize = MAX_CANDLIST; +} + + +static struct +{ + bool m_bCtrl; + bool m_bShift; + bool m_bAlt; + UINT m_uVk; +} + aHotKeys[] = +{ + false, false, false, VK_APPS, + true, false, false, '8', + true, false, false, 'Y', + true, false, false, VK_DELETE, + true, false, false, VK_F7, + true, false, false, VK_F9, + true, false, false, VK_F10, + true, false, false, VK_F11, + true, false, false, VK_F12, + false, false, false, VK_F2, + false, false, false, VK_F3, + false, false, false, VK_F4, + false, false, false, VK_F5, + false, false, false, VK_F10, + false, true, false, VK_F6, + false, true, false, VK_F7, + false, true, false, VK_F8, + true, true, false, VK_F10, + true, true, false, VK_F11, + true, false, false, VK_CONVERT, + true, false, false, VK_SPACE, + true, false, true, 0xbc, // Alt + Ctrl + ',': SW keyboard for Trad. Chinese IME + true, false, false, VK_TAB, // ATOK2005's Ctrl+TAB +}; + +// +// Ignores specific keys when IME is on. Returns true if the message is a hot key to ignore. +// - Caller doesn't have to check whether IME is on. +// - This function must be called before TranslateMessage() is called. +// +bool ImeUi_IgnoreHotKey( const MSG* pmsg ) +{ + if( !g_bInitialized || !pmsg ) + return false; + + if( pmsg->wParam == VK_PROCESSKEY && ( pmsg->message == WM_KEYDOWN || pmsg->message == WM_SYSKEYDOWN ) ) + { + bool bCtrl, bShift, bAlt; + UINT uVkReal = _ImmGetVirtualKey( pmsg->hwnd ); + // special case #1 - VK_JUNJA toggles half/full width input mode in Korean IME. + // This VK (sent by Alt+'=' combo) is ignored regardless of the modifier state. + if( uVkReal == VK_JUNJA ) + { + return true; + } + // special case #2 - disable right arrow key that switches the candidate list to expanded mode in CHT IME. + if( uVkReal == VK_RIGHT && g_bCandList && GETLANG() == LANG_CHT ) + { + return true; + } +#ifndef ENABLE_HANJA_KEY + // special case #3 - we disable VK_HANJA key because 1. some Korean fonts don't Hanja and 2. to reduce testing cost. + if( uVkReal == VK_HANJA && GETPRIMLANG() == LANG_KOREAN ) + { + return true; + } +#endif + bCtrl = ( GetKeyState( VK_CONTROL ) & 0x8000 ) ? true : false; + bShift = ( GetKeyState( VK_SHIFT ) & 0x8000 ) ? true : false; + bAlt = ( GetKeyState( VK_MENU ) & 0x8000 ) ? true : false; + for( int i = 0; i < COUNTOF(aHotKeys); i++ ) + { + if( aHotKeys[i].m_bCtrl == bCtrl && + aHotKeys[i].m_bShift == bShift && + aHotKeys[i].m_bAlt == bAlt && + aHotKeys[i].m_uVk == uVkReal ) + return true; + } + } + return false; +} + +void ImeUi_FinalizeString( bool bSend ) +{ + HIMC himc; + static bool bProcessing = false; // to avoid infinite recursion + if( !g_bInitialized || bProcessing || NULL == ( himc = _ImmGetContext( g_hwndCurr ) ) ) + return; + bProcessing = true; + + if( g_dwIMELevel == 2 && bSend ) + { + // Send composition string to app. + LONG lRet = lstrlen( g_szCompositionString ); + assert( lRet >= 2 ); + // In case of CHT IME, don't send the trailing double byte space, if it exists. +#ifdef UNICODE + if ( GETLANG() == LANG_CHT && (lRet >= 1) + && g_szCompositionString[lRet - 1] == 0x3000 ) + { + lRet--; + } +#else + if( GETLANG() == LANG_CHT && ( lRet >= 2 ) + && ( BYTE )( g_szCompositionString[lRet - 2] ) == 0xa1 + && ( BYTE )( g_szCompositionString[lRet - 1] ) == 0x40 ) + { + lRet -= 2; + } +#endif + _SendCompString(); + } + + InitCompStringData(); + // clear composition string in IME + _ImmNotifyIME( himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0 ); + if( g_bUILessMode ) + { + // For some reason ImmNotifyIME doesn't work on DaYi and Array CHT IMEs. Cancel composition string by setting zero-length string. + ImmSetCompositionString( himc, SCS_SETSTR, TEXT( "" ), sizeof( TCHAR ), TEXT( "" ), sizeof( TCHAR ) ); + } + // the following line is necessary as Korean IME doesn't close cand list when comp string is cancelled. + _ImmNotifyIME( himc, NI_CLOSECANDIDATE, 0, 0 ); + _ImmReleaseContext( g_hwndCurr, himc ); + // Zooty2 RAID #4759: Sometimes application doesn't receive IMN_CLOSECANDIDATE on Alt+Tab + // So the same code for IMN_CLOSECANDIDATE is replicated here. + CloseCandidateList(); + bProcessing = false; + return; +} + +static void SetCompStringColor() +{ + // change color setting according to current IME level. + DWORD dwTranslucency = ( g_dwIMELevel == 2 ) ? 0xff000000 : ( ( DWORD )gSkinIME.compTranslucence << 24 ); + gSkinCompStr.colorInput = dwTranslucency | gSkinIME.compColorInput; + gSkinCompStr.colorTargetConv = dwTranslucency | gSkinIME.compColorTargetConv; + gSkinCompStr.colorConverted = dwTranslucency | gSkinIME.compColorConverted; + gSkinCompStr.colorTargetNotConv = dwTranslucency | gSkinIME.compColorTargetNotConv; + gSkinCompStr.colorInputErr = dwTranslucency | gSkinIME.compColorInputErr; +} + +static void SetSupportLevel( DWORD dwImeLevel ) +{ + if( dwImeLevel < 2 || 3 < dwImeLevel ) + return; + if( GETPRIMLANG() == LANG_KOREAN ) + { + dwImeLevel = 3; + } + g_dwIMELevel = dwImeLevel; + // cancel current composition string. + ImeUi_FinalizeString(); + SetCompStringColor(); +} + +void ImeUi_SetSupportLevel( DWORD dwImeLevel ) +{ + if( !g_bInitialized ) + return; + g_dwIMELevelSaved = dwImeLevel; + SetSupportLevel( dwImeLevel ); +} + +void ImeUi_SetAppearance( const IMEUI_APPEARANCE* pia ) +{ + if( !g_bInitialized || NULL == pia ) + return; + gSkinIME = *pia; + gSkinIME.symbolColor &= 0xffffff; // mask translucency + gSkinIME.symbolColorOff &= 0xffffff; // mask translucency + gSkinIME.symbolColorText &= 0xffffff; // mask translucency + gSkinIME.compColorInput &= 0xffffff; // mask translucency + gSkinIME.compColorTargetConv &= 0xffffff; // mask translucency + gSkinIME.compColorConverted &= 0xffffff; // mask translucency + gSkinIME.compColorTargetNotConv &= 0xffffff; // mask translucency + gSkinIME.compColorInputErr &= 0xffffff; // mask translucency + SetCompStringColor(); +} + +void ImeUi_GetAppearance( IMEUI_APPEARANCE* pia ) +{ + if( g_bInitialized && pia ) + { + *pia = gSkinIME; + } +} + +static void CheckToggleState() +{ + CheckInputLocale(); + + // In Vista, we have to use TSF since few IMM functions don't work as expected. + // WARNING: Because of timing, g_dwState and g_bChineseIME may not be updated + // immediately after the change on IME states by user. + if( g_bUILessMode ) + { + return; + } + + bool bIme = _ImmIsIME( g_hklCurrent ) != 0 + && ( ( 0xF0000000 & ( DWORD )g_hklCurrent ) == 0xE0000000 ); // Hack to detect IME correctly. When IME is running as TIP, ImmIsIME() returns true for CHT US keyboard. + g_bChineseIME = ( GETPRIMLANG() == LANG_CHINESE ) && bIme; + + HIMC himc; + if( NULL != ( himc = _ImmGetContext( g_hwndCurr ) ) ) + { + if( g_bChineseIME ) + { + DWORD dwConvMode, dwSentMode; + _ImmGetConversionStatus( himc, &dwConvMode, &dwSentMode ); + g_dwState = ( dwConvMode & IME_CMODE_NATIVE ) ? IMEUI_STATE_ON : IMEUI_STATE_ENGLISH; + } + else + { + g_dwState = ( bIme && _ImmGetOpenStatus( himc ) != 0 ) ? IMEUI_STATE_ON : IMEUI_STATE_OFF; + } + _ImmReleaseContext( g_hwndCurr, himc ); + } + else + g_dwState = IMEUI_STATE_OFF; +} + +void ImeUi_SetInsertMode( bool bInsert ) +{ + if( !g_bInitialized ) + return; + g_bInsertMode = bInsert; +} + +bool ImeUi_GetCaretStatus() +{ + return !g_bInitialized || !g_szCompositionString[0]; +} + +void ImeUi_SetScreenDimension( UINT width, UINT height ) +{ + if( !g_bInitialized ) + return; + g_screenWidth = width; + g_screenHeight = height; +} + +// this function is used only in brief time in CHT IME handling, so accelerator isn't processed. +static void _PumpMessage() +{ + MSG msg; + while( PeekMessageA( &msg, NULL, 0, 0, PM_NOREMOVE ) ) + { + if( !GetMessageA( &msg, NULL, 0, 0 ) ) + { + PostQuitMessage( msg.wParam ); + return; + } + // if (0 == TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { + TranslateMessage( &msg ); + DispatchMessageA( &msg ); + // } + } +} + +static void GetReadingWindowOrientation( DWORD dwId ) +{ + g_bHorizontalReading = ( g_hklCurrent == _CHS_HKL ) || ( g_hklCurrent == _CHT_HKL_NEW_CHANG_JIE ) || ( dwId == 0 ); + if( !g_bHorizontalReading && IMEID_LANG( dwId ) == LANG_CHT ) + { + char szRegPath[MAX_PATH]; + HKEY hkey; + DWORD dwVer = IMEID_VER( dwId ); + StringCchCopyA( szRegPath, COUNTOF(szRegPath), "software\\microsoft\\windows\\currentversion\\" ); + strcat_s( szRegPath, COUNTOF(szRegPath), ( dwVer >= MAKEIMEVERSION(5, 1) ) ? "MSTCIPH" : "TINTLGNT" ); + LONG lRc = RegOpenKeyExA( HKEY_CURRENT_USER, szRegPath, 0, KEY_READ, &hkey ); + if( lRc == ERROR_SUCCESS ) + { + DWORD dwSize = sizeof( DWORD ), dwMapping, dwType; + lRc = RegQueryValueExA( hkey, "keyboard mapping", NULL, &dwType, ( PBYTE )&dwMapping, &dwSize ); + if( lRc == ERROR_SUCCESS ) + { + if( + ( dwVer <= MAKEIMEVERSION( 5, 0 ) && + ( ( BYTE )dwMapping == 0x22 || ( BYTE )dwMapping == 0x23 ) + ) || + ( ( dwVer == MAKEIMEVERSION( 5, 1 ) || dwVer == MAKEIMEVERSION( 5, 2 ) ) && + ( ( BYTE )dwMapping >= 0x22 && ( BYTE )dwMapping <= 0x24 ) + ) + ) + { + g_bHorizontalReading = true; + } + } + RegCloseKey( hkey ); + } + } +} + +void ImeUi_ToggleLanguageBar( BOOL bRestore ) +{ + static BOOL prevRestore = TRUE; + bool bCheck = ( prevRestore == TRUE || bRestore == TRUE ); + prevRestore = bRestore; + if( !bCheck ) + return; + + static int iShowStatusWindow = -1; + if( iShowStatusWindow == -1 ) + { + iShowStatusWindow = IsNT() && g_osi.dwMajorVersion >= 5 && + ( g_osi.dwMinorVersion > 1 || ( g_osi.dwMinorVersion == 1 && lstrlenA( g_osi.szCSDVersion ) ) ) ? 1 : 0; + } + HWND hwndImeDef = _ImmGetDefaultIMEWnd( g_hwndCurr ); + if( hwndImeDef && bRestore && iShowStatusWindow ) + SendMessageA( hwndImeDef, WM_IME_CONTROL, IMC_OPENSTATUSWINDOW, 0 ); + HRESULT hr; + hr = CoInitialize( NULL ); + if( SUCCEEDED( hr ) ) + { + ITfLangBarMgr* plbm = NULL; + hr = CoCreateInstance( CLSID_TF_LangBarMgr, NULL, CLSCTX_INPROC_SERVER, __uuidof( ITfLangBarMgr ), + ( void** )&plbm ); + if( SUCCEEDED( hr ) && plbm ) + { + DWORD dwCur; + ULONG uRc; + if( SUCCEEDED( hr ) ) + { + if( bRestore ) + { + if( g_dwPrevFloat ) + hr = plbm->ShowFloating( g_dwPrevFloat ); + } + else + { + hr = plbm->GetShowFloatingStatus( &dwCur ); + if( SUCCEEDED( hr ) ) + g_dwPrevFloat = dwCur; + if( !( g_dwPrevFloat & TF_SFT_DESKBAND ) ) + { + hr = plbm->ShowFloating( TF_SFT_HIDDEN ); + } + } + } + uRc = plbm->Release(); + } + CoUninitialize(); + } + if( hwndImeDef && !bRestore ) + { + // The following OPENSTATUSWINDOW is required to hide ATOK16 toolbar (FS9:#7546) + SendMessageA( hwndImeDef, WM_IME_CONTROL, IMC_OPENSTATUSWINDOW, 0 ); + SendMessageA( hwndImeDef, WM_IME_CONTROL, IMC_CLOSESTATUSWINDOW, 0 ); + } +} + +bool ImeUi_IsSendingKeyMessage() +{ + return bIsSendingKeyMessage; +} + +static void OnInputLangChangeWorker() +{ + if( !g_bUILessMode ) + { + g_iCandListIndexBase = ( g_hklCurrent == _CHT_HKL_DAYI ) ? 0 : 1; + } + SetImeApi(); +} + +static void OnInputLangChange() +{ + UINT uLang = GETPRIMLANG(); + CheckToggleState(); + OnInputLangChangeWorker(); + if( uLang != GETPRIMLANG() ) + { + // Korean IME always uses level 3 support. + // Other languages use the level that is specified by ImeUi_SetSupportLevel() + SetSupportLevel( ( GETPRIMLANG() == LANG_KOREAN ) ? 3 : g_dwIMELevelSaved ); + } + HWND hwndImeDef = _ImmGetDefaultIMEWnd( g_hwndCurr ); + if( hwndImeDef ) + { + // Fix for Zooty #3995: prevent CHT IME toobar from showing up + SendMessageA( hwndImeDef, WM_IME_CONTROL, IMC_OPENSTATUSWINDOW, 0 ); + SendMessageA( hwndImeDef, WM_IME_CONTROL, IMC_CLOSESTATUSWINDOW, 0 ); + } +} + +static void SetImeApi() +{ + _GetReadingString = NULL; + _ShowReadingWindow = NULL; + if( g_bUILessMode ) + return; + + char szImeFile[MAX_PATH + 1]; + HKL kl = g_hklCurrent; + if( _ImmGetIMEFileNameA( kl, szImeFile, sizeof( szImeFile ) - 1 ) <= 0 ) + return; + HMODULE hIme = LoadLibraryA( szImeFile ); + if( !hIme ) + return; + _GetReadingString = ( UINT ( WINAPI* )( HIMC, UINT, LPWSTR, PINT, BOOL*, PUINT ) ) + ( GetProcAddress( hIme, "GetReadingString" ) ); + _ShowReadingWindow = ( BOOL ( WINAPI* )( HIMC himc, BOOL ) ) + ( GetProcAddress( hIme, "ShowReadingWindow" ) ); + if( _ShowReadingWindow ) + { + HIMC himc; + if( NULL != ( himc = _ImmGetContext( g_hwndCurr ) ) ) + { + _ShowReadingWindow( himc, false ); + _ImmReleaseContext( g_hwndCurr, himc ); + } + } +} + +static void CheckInputLocale() +{ + static HKL hklPrev = 0; + g_hklCurrent = GetKeyboardLayout( 0 ); + if( hklPrev == g_hklCurrent ) + { + return; + } + hklPrev = g_hklCurrent; + switch( GETPRIMLANG() ) + { + // Simplified Chinese + case LANG_CHINESE: + g_bVerticalCand = true; + switch( GETSUBLANG() ) + { + case SUBLANG_CHINESE_SIMPLIFIED: + g_pszIndicatior = g_aszIndicator[INDICATOR_CHS]; + //g_bVerticalCand = GetImeId() == 0; + g_bVerticalCand = false; + break; + case SUBLANG_CHINESE_TRADITIONAL: + g_pszIndicatior = g_aszIndicator[INDICATOR_CHT]; + break; + default: // unsupported sub-language + g_pszIndicatior = g_aszIndicator[INDICATOR_NON_IME]; + break; + } + break; + // Korean + case LANG_KOREAN: + g_pszIndicatior = g_aszIndicator[INDICATOR_KOREAN]; + g_bVerticalCand = false; + break; + // Japanese + case LANG_JAPANESE: + g_pszIndicatior = g_aszIndicator[INDICATOR_JAPANESE]; + g_bVerticalCand = true; + break; + default: + g_pszIndicatior = g_aszIndicator[INDICATOR_NON_IME]; + } + char szCodePage[8]; + int iRc = GetLocaleInfoA( MAKELCID( GETLANG(), SORT_DEFAULT ), LOCALE_IDEFAULTANSICODEPAGE, szCodePage, + COUNTOF( szCodePage ) ); iRc; + g_uCodePage = _strtoul( szCodePage, NULL, 0 ); + for( int i = 0; i < 256; i++ ) + { + LeadByteTable[i] = ( BYTE )IsDBCSLeadByteEx( g_uCodePage, ( BYTE )i ); + } +} + +void ImeUi_SetWindow( HWND hwnd ) +{ + g_hwndCurr = hwnd; + g_disableCicero.DisableCiceroOnThisWnd( hwnd ); +} + +UINT ImeUi_GetInputCodePage() +{ + return g_uCodePage; +} + +DWORD ImeUi_GetFlags() +{ + return g_dwImeUiFlags; +} + +void ImeUi_SetFlags( DWORD dwFlags, bool bSet ) +{ + if( bSet ) + { + g_dwImeUiFlags |= dwFlags; + } + else + { + g_dwImeUiFlags &= ~dwFlags; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// CTsfUiLessMode methods +// +/////////////////////////////////////////////////////////////////////////////// + +// +// SetupSinks() +// Set up sinks. A sink is used to receive a Text Service Framework event. +// CUIElementSink implements multiple sink interfaces to receive few different TSF events. +// +BOOL CTsfUiLessMode::SetupSinks() +{ + // ITfThreadMgrEx is available on Vista or later. + HRESULT hr; + hr = CoCreateInstance( CLSID_TF_ThreadMgr, + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( ITfThreadMgrEx ), + ( void** )&m_tm ); + + if( hr != S_OK ) + { + return FALSE; + } + + // ready to start interacting + TfClientId cid; // not used + if( FAILED( m_tm->ActivateEx( &cid, TF_TMAE_UIELEMENTENABLEDONLY ) ) ) + { + return FALSE; + } + + // Setup sinks + BOOL bRc = FALSE; + m_TsfSink = new CUIElementSink(); + if( m_TsfSink ) + { + ITfSource* srcTm; + if( SUCCEEDED( hr = m_tm->QueryInterface( __uuidof( ITfSource ), ( void** )&srcTm ) ) ) + { + // Sink for reading window change + if( SUCCEEDED( hr = srcTm->AdviseSink( __uuidof( ITfUIElementSink ), ( ITfUIElementSink* )m_TsfSink, + &m_dwUIElementSinkCookie ) ) ) + { + // Sink for input locale change + if( SUCCEEDED( hr = srcTm->AdviseSink( __uuidof( ITfInputProcessorProfileActivationSink ), + ( ITfInputProcessorProfileActivationSink* )m_TsfSink, + &m_dwAlpnSinkCookie ) ) ) + { + if( SetupCompartmentSinks() ) // Setup compartment sinks for the first time + { + bRc = TRUE; + } + } + } + srcTm->Release(); + } + } + return bRc; +} + +void CTsfUiLessMode::ReleaseSinks() +{ + HRESULT hr; + ITfSource* source; + + // Remove all sinks + if( m_tm && SUCCEEDED( m_tm->QueryInterface( __uuidof( ITfSource ), ( void** )&source ) ) ) + { + hr = source->UnadviseSink( m_dwUIElementSinkCookie ); + hr = source->UnadviseSink( m_dwAlpnSinkCookie ); + source->Release(); + SetupCompartmentSinks( TRUE ); // Remove all compartment sinks + m_tm->Deactivate(); + SAFE_RELEASE( m_tm ); + SAFE_RELEASE( m_TsfSink ); + } +} + +CTsfUiLessMode::CUIElementSink::CUIElementSink() +{ + _cRef = 1; +} + + +CTsfUiLessMode::CUIElementSink::~CUIElementSink() +{ +} + +STDAPI CTsfUiLessMode::CUIElementSink::QueryInterface( REFIID riid, void** ppvObj ) +{ + if( ppvObj == NULL ) + return E_INVALIDARG; + + *ppvObj = NULL; + + if( IsEqualIID( riid, IID_IUnknown ) ) + { + *ppvObj = reinterpret_cast( this ); + } + else if( IsEqualIID( riid, __uuidof( ITfUIElementSink ) ) ) + { + *ppvObj = ( ITfUIElementSink* )this; + } + else if( IsEqualIID( riid, __uuidof( ITfInputProcessorProfileActivationSink ) ) ) + { + *ppvObj = ( ITfInputProcessorProfileActivationSink* )this; + } + else if( IsEqualIID( riid, __uuidof( ITfCompartmentEventSink ) ) ) + { + *ppvObj = ( ITfCompartmentEventSink* )this; + } + + if( *ppvObj ) + { + AddRef(); + return S_OK; + } + + return E_NOINTERFACE; +} + +STDAPI_( ULONG ) +CTsfUiLessMode::CUIElementSink::AddRef() +{ + return ++_cRef; +} + +STDAPI_( ULONG ) +CTsfUiLessMode::CUIElementSink::Release() +{ + LONG cr = --_cRef; + + if( _cRef == 0 ) + { + delete this; + } + + return cr; +} + +STDAPI CTsfUiLessMode::CUIElementSink::BeginUIElement( DWORD dwUIElementId, BOOL* pbShow ) +{ + ITfUIElement* pElement = GetUIElement( dwUIElementId ); + if( !pElement ) + return E_INVALIDARG; + + ITfReadingInformationUIElement* preading = NULL; + ITfCandidateListUIElement* pcandidate = NULL; + *pbShow = FALSE; + if( !g_bCandList && SUCCEEDED( pElement->QueryInterface( __uuidof( ITfReadingInformationUIElement ), + ( void** )&preading ) ) ) + { + MakeReadingInformationString( preading ); + preading->Release(); + } + else if( SUCCEEDED( pElement->QueryInterface( __uuidof( ITfCandidateListUIElement ), + ( void** )&pcandidate ) ) ) + { + m_nCandidateRefCount++; + MakeCandidateStrings( pcandidate ); + pcandidate->Release(); + } + + pElement->Release(); + return S_OK; +} + +STDAPI CTsfUiLessMode::CUIElementSink::UpdateUIElement( DWORD dwUIElementId ) +{ + ITfUIElement* pElement = GetUIElement( dwUIElementId ); + if( !pElement ) + return E_INVALIDARG; + + ITfReadingInformationUIElement* preading = NULL; + ITfCandidateListUIElement* pcandidate = NULL; + if( !g_bCandList && SUCCEEDED( pElement->QueryInterface( __uuidof( ITfReadingInformationUIElement ), + ( void** )&preading ) ) ) + { + MakeReadingInformationString( preading ); + preading->Release(); + } + else if( SUCCEEDED( pElement->QueryInterface( __uuidof( ITfCandidateListUIElement ), + ( void** )&pcandidate ) ) ) + { + MakeCandidateStrings( pcandidate ); + pcandidate->Release(); + } + + pElement->Release(); + return S_OK; +} + +STDAPI CTsfUiLessMode::CUIElementSink::EndUIElement( DWORD dwUIElementId ) +{ + ITfUIElement* pElement = GetUIElement( dwUIElementId ); + if( !pElement ) + return E_INVALIDARG; + + ITfReadingInformationUIElement* preading = NULL; + if( !g_bCandList && SUCCEEDED( pElement->QueryInterface( __uuidof( ITfReadingInformationUIElement ), + ( void** )&preading ) ) ) + { + g_dwCount = 0; + preading->Release(); + } + + ITfCandidateListUIElement* pcandidate = NULL; + if( SUCCEEDED( pElement->QueryInterface( __uuidof( ITfCandidateListUIElement ), + ( void** )&pcandidate ) ) ) + { + m_nCandidateRefCount--; + if( m_nCandidateRefCount == 0 ) + CloseCandidateList(); + pcandidate->Release(); + } + + pElement->Release(); + return S_OK; +} + +void CTsfUiLessMode::UpdateImeState( BOOL bResetCompartmentEventSink ) +{ + ITfCompartmentMgr* pcm; + ITfCompartment* pTfOpenMode = NULL; + ITfCompartment* pTfConvMode = NULL; + if( GetCompartments( &pcm, &pTfOpenMode, &pTfConvMode ) ) + { + VARIANT valOpenMode; + VARIANT valConvMode; + pTfOpenMode->GetValue( &valOpenMode ); + pTfConvMode->GetValue( &valConvMode ); + if( valOpenMode.vt == VT_I4 ) + { + if( g_bChineseIME ) + { + g_dwState = valOpenMode.lVal != 0 && valConvMode.lVal != 0 ? IMEUI_STATE_ON : IMEUI_STATE_ENGLISH; + } + else + { + g_dwState = valOpenMode.lVal != 0 ? IMEUI_STATE_ON : IMEUI_STATE_OFF; + } + } + VariantClear( &valOpenMode ); + VariantClear( &valConvMode ); + + if( bResetCompartmentEventSink ) + { + SetupCompartmentSinks( FALSE, pTfOpenMode, pTfConvMode ); // Reset compartment sinks + } + pTfOpenMode->Release(); + pTfConvMode->Release(); + pcm->Release(); + } +} + +STDAPI CTsfUiLessMode::CUIElementSink::OnActivated( DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid, + REFGUID guidProfile, HKL hkl, DWORD dwFlags ) +{ + static GUID TF_PROFILE_DAYI = + { + 0x037B2C25, 0x480C, 0x4D7F, 0xB0, 0x27, 0xD6, 0xCA, 0x6B, 0x69, 0x78, 0x8A + }; + g_iCandListIndexBase = IsEqualGUID( TF_PROFILE_DAYI, guidProfile ) ? 0 : 1; + if( IsEqualIID( catid, GUID_TFCAT_TIP_KEYBOARD ) && ( dwFlags & TF_IPSINK_FLAG_ACTIVE ) ) + { + g_bChineseIME = ( dwProfileType & TF_PROFILETYPE_INPUTPROCESSOR ) && langid == LANG_CHT; + if( dwProfileType & TF_PROFILETYPE_INPUTPROCESSOR ) + { + UpdateImeState( TRUE ); + } + else + g_dwState = IMEUI_STATE_OFF; + OnInputLangChange(); + } + return S_OK; +} + +STDAPI CTsfUiLessMode::CUIElementSink::OnChange( REFGUID rguid ) +{ + UpdateImeState(); + return S_OK; +} + +void CTsfUiLessMode::MakeReadingInformationString( ITfReadingInformationUIElement* preading ) +{ + UINT cchMax; + UINT uErrorIndex = 0; + BOOL fVertical; + DWORD dwFlags; + + preading->GetUpdatedFlags( &dwFlags ); + preading->GetMaxReadingStringLength( &cchMax ); + preading->GetErrorIndex( &uErrorIndex ); // errorIndex is zero-based + preading->IsVerticalOrderPreferred( &fVertical ); + g_iReadingError = ( int )uErrorIndex; + g_bHorizontalReading = !fVertical; + g_bReadingWindow = true; + g_uCandPageSize = MAX_CANDLIST; + g_dwSelection = g_iReadingError ? g_iReadingError - 1 : ( DWORD )-1; + g_iReadingError--; // g_iReadingError is used only in horizontal window, and has to be -1 if there's no error. +#ifndef UNICODE + if( g_iReadingError > 0 ) + { + // convert g_iReadingError to byte based + LPCSTR pszNext = g_szReadingString; + for( int i = 0; i < g_iReadingError && pszNext && *pszNext; ++i ) + { + pszNext = CharNext( pszNext ); + } + if( pszNext ) // should be non-NULL, but just in case + { + g_iReadingError = pszNext - g_szReadingString; + } + } +#endif + + BSTR bstr; + if( SUCCEEDED( preading->GetString( &bstr ) ) ) + { + if( bstr ) + { +#ifndef UNICODE + char szStr[COUNTOF(g_szReadingString)*2]; + szStr[0] = 0; + int iRc = WideCharToMultiByte( CP_ACP, 0, bstr, -1, szStr, sizeof( szStr ), NULL, NULL ); + if( iRc >= sizeof( szStr ) ) + { + szStr[sizeof( szStr ) - 1] = 0; + } + StringCchCopy( g_szReadingString, COUNTOF(g_szReadingString), szStr ); +#else + StringCchCopy( g_szReadingString, COUNTOF(g_szReadingString), bstr ); +#endif + g_dwCount = cchMax; + LPCTSTR pszSource = g_szReadingString; + if( fVertical ) + { + // for vertical reading window, copy each character to g_szCandidate array. + for( UINT i = 0; i < cchMax; i++ ) + { + LPTSTR pszDest = g_szCandidate[i]; + if( *pszSource ) + { + LPTSTR pszNextSrc = CharNext( pszSource ); + SIZE_T size = ( LPSTR )pszNextSrc - ( LPSTR )pszSource; + CopyMemory( pszDest, pszSource, size ); + pszSource = pszNextSrc; + pszDest += size; + } + *pszDest = 0; + } + } + else + { + g_szCandidate[0][0] = TEXT( ' ' ); // hack to make rendering happen + } + SysFreeString( bstr ); + } + } +} + +void CTsfUiLessMode::MakeCandidateStrings( ITfCandidateListUIElement* pcandidate ) +{ + UINT uIndex = 0; + UINT uCount = 0; + UINT uCurrentPage = 0; + UINT* IndexList = NULL; + UINT uPageCnt = 0; + DWORD dwPageStart = 0; + DWORD dwPageSize = 0; + BSTR bstr; + + pcandidate->GetSelection( &uIndex ); + pcandidate->GetCount( &uCount ); + pcandidate->GetCurrentPage( &uCurrentPage ); + g_dwSelection = ( DWORD )uIndex; + g_dwCount = ( DWORD )uCount; + g_bCandList = true; + g_bReadingWindow = false; + + pcandidate->GetPageIndex( NULL, 0, &uPageCnt ); + if( uPageCnt > 0 ) + { + IndexList = ( UINT* )ImeUiCallback_Malloc( sizeof( UINT ) * uPageCnt ); + if( IndexList ) + { + pcandidate->GetPageIndex( IndexList, uPageCnt, &uPageCnt ); + dwPageStart = IndexList[uCurrentPage]; + dwPageSize = ( uCurrentPage < uPageCnt - 1 ) ? + min( uCount, IndexList[uCurrentPage + 1] ) - dwPageStart: + uCount - dwPageStart; + } + } + + g_uCandPageSize = min( dwPageSize, MAX_CANDLIST ); + g_dwSelection = g_dwSelection - dwPageStart; + + memset( &g_szCandidate, 0, sizeof( g_szCandidate ) ); + for( UINT i = dwPageStart, j = 0; ( DWORD )i < g_dwCount && j < g_uCandPageSize; i++, j++ ) + { + if( SUCCEEDED( pcandidate->GetString( i, &bstr ) ) ) + { + if( bstr ) + { +#ifndef UNICODE + char szStr[COUNTOF(g_szCandidate[0])*2]; + szStr[0] = 0; + int iRc = WideCharToMultiByte( CP_ACP, 0, bstr, -1, szStr, sizeof( szStr ), NULL, NULL ); + if( iRc >= sizeof( szStr ) ) + { + szStr[sizeof( szStr ) - 1] = 0; + } + ComposeCandidateLine( j, szStr ); +#else + ComposeCandidateLine( j, bstr ); +#endif + SysFreeString( bstr ); + } + } + } + + if( GETPRIMLANG() == LANG_KOREAN ) + { + g_dwSelection = ( DWORD )-1; + } + + if( IndexList ) + { + ImeUiCallback_Free( IndexList ); + } +} + +ITfUIElement* CTsfUiLessMode::GetUIElement( DWORD dwUIElementId ) +{ + ITfUIElementMgr* puiem; + ITfUIElement* pElement = NULL; + + if( SUCCEEDED( m_tm->QueryInterface( __uuidof( ITfUIElementMgr ), ( void** )&puiem ) ) ) + { + puiem->GetUIElement( dwUIElementId, &pElement ); + puiem->Release(); + } + + return pElement; +} + +BOOL CTsfUiLessMode::CurrentInputLocaleIsIme() +{ + BOOL ret = FALSE; + HRESULT hr; + + ITfInputProcessorProfiles* pProfiles; + hr = CoCreateInstance( CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER, + __uuidof( ITfInputProcessorProfiles ), ( LPVOID* )&pProfiles ); + if( SUCCEEDED( hr ) ) + { + ITfInputProcessorProfileMgr* pProfileMgr; + hr = pProfiles->QueryInterface( __uuidof( ITfInputProcessorProfileMgr ), ( LPVOID* )&pProfileMgr ); + if( SUCCEEDED( hr ) ) + { + TF_INPUTPROCESSORPROFILE tip; + hr = pProfileMgr->GetActiveProfile( GUID_TFCAT_TIP_KEYBOARD, &tip ); + if( SUCCEEDED( hr ) ) + { + ret = ( tip.dwProfileType & TF_PROFILETYPE_INPUTPROCESSOR ) != 0; + } + pProfileMgr->Release(); + } + pProfiles->Release(); + } + return ret; +} + +// Sets up or removes sink for UI element. +// UI element sink should be removed when IME is disabled, +// otherwise the sink can be triggered when a game has multiple instances of IME UI library. +void CTsfUiLessMode::EnableUiUpdates( bool bEnable ) +{ + if( m_tm == NULL || + ( bEnable && m_dwUIElementSinkCookie != TF_INVALID_COOKIE ) || + ( !bEnable && m_dwUIElementSinkCookie == TF_INVALID_COOKIE ) ) + { + return; + } + ITfSource* srcTm = NULL; + HRESULT hr = E_FAIL; + if( SUCCEEDED( hr = m_tm->QueryInterface( __uuidof( ITfSource ), ( void** )&srcTm ) ) ) + { + if( bEnable ) + { + hr = srcTm->AdviseSink( __uuidof( ITfUIElementSink ), ( ITfUIElementSink* )m_TsfSink, + &m_dwUIElementSinkCookie ); + } + else + { + hr = srcTm->UnadviseSink( m_dwUIElementSinkCookie ); + m_dwUIElementSinkCookie = TF_INVALID_COOKIE; + } + srcTm->Release(); + } +} + +// Returns open mode compartments and compartment manager. +// Function fails if it fails to acquire any of the objects to be returned. +BOOL CTsfUiLessMode::GetCompartments( ITfCompartmentMgr** ppcm, ITfCompartment** ppTfOpenMode, + ITfCompartment** ppTfConvMode ) +{ + ITfCompartmentMgr* pcm = NULL; + ITfCompartment* pTfOpenMode = NULL; + ITfCompartment* pTfConvMode = NULL; + + static GUID _GUID_COMPARTMENT_KEYBOARD_INPUTMODE_CONVERSION = + { + 0xCCF05DD8, 0x4A87, 0x11D7, 0xA6, 0xE2, 0x00, 0x06, 0x5B, 0x84, 0x43, 0x5C + }; + + HRESULT hr; + if( SUCCEEDED( hr = m_tm->QueryInterface( IID_ITfCompartmentMgr, ( void** )&pcm ) ) ) + { + if( SUCCEEDED( hr = pcm->GetCompartment( GUID_COMPARTMENT_KEYBOARD_OPENCLOSE, &pTfOpenMode ) ) ) + { + if( SUCCEEDED( hr = pcm->GetCompartment( _GUID_COMPARTMENT_KEYBOARD_INPUTMODE_CONVERSION, + &pTfConvMode ) ) ) + { + *ppcm = pcm; + *ppTfOpenMode = pTfOpenMode; + *ppTfConvMode = pTfConvMode; + return TRUE; + } + pTfOpenMode->Release(); + } + pcm->Release(); + } + return FALSE; +} + +// There are three ways to call this function: +// SetupCompartmentSinks() : initialization +// SetupCompartmentSinks(FALSE, openmode, convmode) : Resetting sinks. This is necessary as DaYi and Array IME resets compartment on switching input locale +// SetupCompartmentSinks(TRUE) : clean up sinks +BOOL CTsfUiLessMode::SetupCompartmentSinks( BOOL bRemoveOnly, ITfCompartment* pTfOpenMode, + ITfCompartment* pTfConvMode ) +{ + bool bLocalCompartments = false; + ITfCompartmentMgr* pcm = NULL; + BOOL bRc = FALSE; + HRESULT hr = E_FAIL; + + if( !pTfOpenMode && !pTfConvMode ) + { + bLocalCompartments = true; + GetCompartments( &pcm, &pTfOpenMode, &pTfConvMode ); + } + if( !( pTfOpenMode && pTfConvMode ) ) + { + // Invalid parameters or GetCompartments() has failed. + return FALSE; + } + ITfSource* srcOpenMode = NULL; + if( SUCCEEDED( hr = pTfOpenMode->QueryInterface( IID_ITfSource, ( void** )&srcOpenMode ) ) ) + { + // Remove existing sink for open mode + if( m_dwOpenModeSinkCookie != TF_INVALID_COOKIE ) + { + srcOpenMode->UnadviseSink( m_dwOpenModeSinkCookie ); + m_dwOpenModeSinkCookie = TF_INVALID_COOKIE; + } + // Setup sink for open mode (toggle state) change + if( bRemoveOnly || SUCCEEDED( hr = srcOpenMode->AdviseSink( IID_ITfCompartmentEventSink, + ( ITfCompartmentEventSink* )m_TsfSink, + &m_dwOpenModeSinkCookie ) ) ) + { + ITfSource* srcConvMode = NULL; + if( SUCCEEDED( hr = pTfConvMode->QueryInterface( IID_ITfSource, ( void** )&srcConvMode ) ) ) + { + // Remove existing sink for open mode + if( m_dwConvModeSinkCookie != TF_INVALID_COOKIE ) + { + srcConvMode->UnadviseSink( m_dwConvModeSinkCookie ); + m_dwConvModeSinkCookie = TF_INVALID_COOKIE; + } + // Setup sink for open mode (toggle state) change + if( bRemoveOnly || SUCCEEDED( hr = srcConvMode->AdviseSink( IID_ITfCompartmentEventSink, + ( ITfCompartmentEventSink* )m_TsfSink, + &m_dwConvModeSinkCookie ) ) ) + { + bRc = TRUE; + } + srcConvMode->Release(); + } + } + srcOpenMode->Release(); + } + if( bLocalCompartments ) + { + pTfOpenMode->Release(); + pTfConvMode->Release(); + pcm->Release(); + } + return bRc; +} + + +WORD ImeUi_GetPrimaryLanguage() +{ + return GETPRIMLANG(); +}; + +DWORD ImeUi_GetImeId( UINT uIndex ) +{ + return GetImeId( uIndex ); +}; + +WORD ImeUi_GetLanguage() +{ + return GETLANG(); +}; + +PTSTR ImeUi_GetIndicatior() +{ + return g_pszIndicatior; +}; + + +bool ImeUi_IsShowReadingWindow() +{ + return g_bReadingWindow; +}; + +bool ImeUi_IsShowCandListWindow() +{ + return g_bCandList; +}; + +bool ImeUi_IsVerticalCand() +{ + return g_bVerticalCand; +}; + +bool ImeUi_IsHorizontalReading() +{ + return g_bHorizontalReading; +}; + +TCHAR* ImeUi_GetCandidate( UINT idx ) +{ + if( idx < MAX_CANDLIST ) + return g_szCandidate[idx]; + else + return g_szCandidate[0]; +} + +DWORD ImeUi_GetCandidateSelection() +{ + return g_dwSelection; +} + +DWORD ImeUi_GetCandidateCount() +{ + return g_dwCount; +} + +TCHAR* ImeUi_GetCompositionString() +{ + return g_szCompositionString; +} + +BYTE* ImeUi_GetCompStringAttr() +{ + return g_szCompAttrString; +} + +DWORD ImeUi_GetImeCursorChars() +{ + return g_IMECursorChars; +} + diff --git a/Demos/DX11ClothDemo/DXUT/Optional/ImeUi.h b/Demos/DX11ClothDemo/DXUT/Optional/ImeUi.h new file mode 100644 index 0000000..c8d2b2f --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/ImeUi.h @@ -0,0 +1,124 @@ +//-------------------------------------------------------------------------------------- +// File: ImeUi.h +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#ifndef _IMEUI_H_ +#define _IMEUI_H_ +#if _WIN32_WINNT < 0x0400 +#error IMEUI requires _WIN32_WINNT to be 0x0400 or higher. Please add "_WIN32_WINNT=0x0400" to your project's preprocessor setting. +#endif +#include + +class CImeUiFont_Base +{ +public: + virtual void SetHeight( UINT uHeight ) + { + uHeight; + }; // for backward compatibility + virtual void SetColor( DWORD color ) = 0; + virtual void SetPosition( int x, int y ) = 0; + virtual void GetTextExtent( LPCTSTR szText, DWORD* puWidth, DWORD* puHeight ) = 0; + virtual void DrawText( LPCTSTR pszText ) = 0; +}; + +typedef struct +{ + // symbol (Henkan-kyu) + DWORD symbolColor; + DWORD symbolColorOff; + DWORD symbolColorText; + BYTE symbolHeight; + BYTE symbolTranslucence; + BYTE symbolPlacement; + CImeUiFont_Base* symbolFont; + + // candidate list + DWORD candColorBase; + DWORD candColorBorder; + DWORD candColorText; + + // composition string + DWORD compColorInput; + DWORD compColorTargetConv; + DWORD compColorConverted; + DWORD compColorTargetNotConv; + DWORD compColorInputErr; + BYTE compTranslucence; + DWORD compColorText; + + // caret + BYTE caretWidth; + BYTE caretYMargin; +} IMEUI_APPEARANCE; + +typedef struct // D3DTLVERTEX compatible +{ + float sx; + float sy; + float sz; + float rhw; + DWORD color; + DWORD specular; + float tu; + float tv; +} IMEUI_VERTEX; + +// IME States +#define IMEUI_STATE_OFF 0 +#define IMEUI_STATE_ON 1 +#define IMEUI_STATE_ENGLISH 2 + +// IME const +#define MAX_CANDLIST 10 + +// IME Flags +#define IMEUI_FLAG_SUPPORT_CARET 0x00000001 + +bool ImeUi_Initialize( HWND hwnd, bool bDisable = false ); +void ImeUi_Uninitialize(); +void ImeUi_SetAppearance( const IMEUI_APPEARANCE* pia ); +void ImeUi_GetAppearance( IMEUI_APPEARANCE* pia ); +bool ImeUi_IgnoreHotKey( const MSG* pmsg ); +LPARAM ImeUi_ProcessMessage( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM& lParam, bool* trapped ); +void ImeUi_SetScreenDimension( UINT width, UINT height ); +void ImeUi_RenderUI( bool bDrawCompAttr = true, bool bDrawOtherUi = true ); +void ImeUi_SetCaretPosition( UINT x, UINT y ); +void ImeUi_SetCompStringAppearance( CImeUiFont_Base* pFont, DWORD color, const RECT* prc ); +bool ImeUi_GetCaretStatus(); +void ImeUi_SetInsertMode( bool bInsert ); +void ImeUi_SetState( DWORD dwState ); +DWORD ImeUi_GetState(); +void ImeUi_EnableIme( bool bEnable ); +bool ImeUi_IsEnabled( void ); +void ImeUi_FinalizeString( bool bSend = false ); +void ImeUi_ToggleLanguageBar( BOOL bRestore ); +bool ImeUi_IsSendingKeyMessage(); +void ImeUi_SetWindow( HWND hwnd ); +UINT ImeUi_GetInputCodePage(); +DWORD ImeUi_GetFlags(); +void ImeUi_SetFlags( DWORD dwFlags, bool bSet ); + +WORD ImeUi_GetPrimaryLanguage(); +DWORD ImeUi_GetImeId( UINT uIndex ); +WORD ImeUi_GetLanguage(); +LPTSTR ImeUi_GetIndicatior(); +bool ImeUi_IsShowReadingWindow(); +bool ImeUi_IsShowCandListWindow(); +bool ImeUi_IsVerticalCand(); +bool ImeUi_IsHorizontalReading(); +TCHAR* ImeUi_GetCandidate( UINT idx ); +TCHAR* ImeUi_GetCompositionString(); +DWORD ImeUi_GetCandidateSelection(); +DWORD ImeUi_GetCandidateCount(); +BYTE* ImeUi_GetCompStringAttr(); +DWORD ImeUi_GetImeCursorChars(); + +extern void ( CALLBACK*ImeUiCallback_DrawRect )( int x1, int y1, int x2, int y2, DWORD color ); +extern void* ( __cdecl*ImeUiCallback_Malloc )( size_t bytes ); +extern void ( __cdecl*ImeUiCallback_Free )( void* ptr ); +extern void ( CALLBACK*ImeUiCallback_DrawFans )( const IMEUI_VERTEX* paVertex, UINT uNum ); +extern void ( CALLBACK*ImeUiCallback_OnChar )( WCHAR wc ); + +#endif //_IMEUI_H_ diff --git a/Demos/DX11ClothDemo/DXUT/Optional/SDKmesh.cpp b/Demos/DX11ClothDemo/DXUT/Optional/SDKmesh.cpp new file mode 100644 index 0000000..42bae83 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/SDKmesh.cpp @@ -0,0 +1,2348 @@ +//-------------------------------------------------------------------------------------- +// File: SDKMesh.cpp +// +// The SDK Mesh format (.sdkmesh) is not a recommended file format for games. +// It was designed to meet the specific needs of the SDK samples. Any real-world +// applications should avoid this file format in favor of a destination format that +// meets the specific needs of the application. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#include "DXUT.h" +#include "SDKMesh.h" +#include "SDKMisc.h" + +//-------------------------------------------------------------------------------------- +void CDXUTSDKMesh::LoadMaterials( ID3D11Device* pd3dDevice, SDKMESH_MATERIAL* pMaterials, UINT numMaterials, + SDKMESH_CALLBACKS11* pLoaderCallbacks ) +{ + // TODO: D3D11 + char strPath[MAX_PATH]; + + if( pLoaderCallbacks && pLoaderCallbacks->pCreateTextureFromFile ) + { + for( UINT m = 0; m < numMaterials; m++ ) + { + pMaterials[m].pDiffuseTexture11 = NULL; + pMaterials[m].pNormalTexture11 = NULL; + pMaterials[m].pSpecularTexture11 = NULL; + pMaterials[m].pDiffuseRV11 = NULL; + pMaterials[m].pNormalRV11 = NULL; + pMaterials[m].pSpecularRV11 = NULL; + + // load textures + if( pMaterials[m].DiffuseTexture[0] != 0 ) + { + pLoaderCallbacks->pCreateTextureFromFile( pd3dDevice, + pMaterials[m].DiffuseTexture, &pMaterials[m].pDiffuseRV11, + pLoaderCallbacks->pContext ); + } + if( pMaterials[m].NormalTexture[0] != 0 ) + { + pLoaderCallbacks->pCreateTextureFromFile( pd3dDevice, + pMaterials[m].NormalTexture, &pMaterials[m].pNormalRV11, + pLoaderCallbacks->pContext ); + } + if( pMaterials[m].SpecularTexture[0] != 0 ) + { + pLoaderCallbacks->pCreateTextureFromFile( pd3dDevice, + pMaterials[m].SpecularTexture, &pMaterials[m].pSpecularRV11, + pLoaderCallbacks->pContext ); + } + } + } + else + { + for( UINT m = 0; m < numMaterials; m++ ) + { + pMaterials[m].pDiffuseTexture11 = NULL; + pMaterials[m].pNormalTexture11 = NULL; + pMaterials[m].pSpecularTexture11 = NULL; + pMaterials[m].pDiffuseRV11 = NULL; + pMaterials[m].pNormalRV11 = NULL; + pMaterials[m].pSpecularRV11 = NULL; + + // load textures + if( pMaterials[m].DiffuseTexture[0] != 0 ) + { + sprintf_s( strPath, MAX_PATH, "%s%s", m_strPath, pMaterials[m].DiffuseTexture ); + if( FAILED( DXUTGetGlobalResourceCache().CreateTextureFromFile( pd3dDevice, DXUTGetD3D11DeviceContext(), + strPath, &pMaterials[m].pDiffuseRV11, + true ) ) ) + pMaterials[m].pDiffuseRV11 = ( ID3D11ShaderResourceView* )ERROR_RESOURCE_VALUE; + + } + if( pMaterials[m].NormalTexture[0] != 0 ) + { + sprintf_s( strPath, MAX_PATH, "%s%s", m_strPath, pMaterials[m].NormalTexture ); + if( FAILED( DXUTGetGlobalResourceCache().CreateTextureFromFile( pd3dDevice, DXUTGetD3D11DeviceContext(), + strPath, + &pMaterials[m].pNormalRV11 ) ) ) + pMaterials[m].pNormalRV11 = ( ID3D11ShaderResourceView* )ERROR_RESOURCE_VALUE; + } + if( pMaterials[m].SpecularTexture[0] != 0 ) + { + sprintf_s( strPath, MAX_PATH, "%s%s", m_strPath, pMaterials[m].SpecularTexture ); + if( FAILED( DXUTGetGlobalResourceCache().CreateTextureFromFile( pd3dDevice, DXUTGetD3D11DeviceContext(), + strPath, + &pMaterials[m].pSpecularRV11 ) ) ) + pMaterials[m].pSpecularRV11 = ( ID3D11ShaderResourceView* )ERROR_RESOURCE_VALUE; + } + } + } +} + +//-------------------------------------------------------------------------------------- +void CDXUTSDKMesh::LoadMaterials( IDirect3DDevice9* pd3dDevice, SDKMESH_MATERIAL* pMaterials, UINT numMaterials, + SDKMESH_CALLBACKS9* pLoaderCallbacks ) +{ + char strPath[MAX_PATH]; + + if( pLoaderCallbacks && pLoaderCallbacks->pCreateTextureFromFile ) + { + for( UINT m = 0; m < numMaterials; m++ ) + { + pMaterials[m].pDiffuseTexture9 = NULL; + pMaterials[m].pNormalTexture9 = NULL; + pMaterials[m].pSpecularTexture9 = NULL; + + // load textures + if( pMaterials[m].DiffuseTexture[0] != 0 ) + { + pLoaderCallbacks->pCreateTextureFromFile( pd3dDevice, + pMaterials[m].DiffuseTexture, + &pMaterials[m].pDiffuseTexture9, + pLoaderCallbacks->pContext ); + } + if( pMaterials[m].NormalTexture[0] != 0 ) + { + pLoaderCallbacks->pCreateTextureFromFile( pd3dDevice, + pMaterials[m].NormalTexture, &pMaterials[m].pNormalTexture9, + pLoaderCallbacks->pContext ); + } + if( pMaterials[m].SpecularTexture[0] != 0 ) + { + pLoaderCallbacks->pCreateTextureFromFile( pd3dDevice, + pMaterials[m].SpecularTexture, + &pMaterials[m].pSpecularTexture9, + pLoaderCallbacks->pContext ); + } + } + } + else + { + for( UINT m = 0; m < numMaterials; m++ ) + { + pMaterials[m].pDiffuseTexture9 = NULL; + pMaterials[m].pNormalTexture9 = NULL; + pMaterials[m].pSpecularTexture9 = NULL; + pMaterials[m].pDiffuseRV11 = NULL; + pMaterials[m].pNormalRV11 = NULL; + pMaterials[m].pSpecularRV11 = NULL; + + // load textures + if( pMaterials[m].DiffuseTexture[0] != 0 ) + { + sprintf_s( strPath, MAX_PATH, "%s%s", m_strPath, pMaterials[m].DiffuseTexture ); + if( FAILED( DXUTGetGlobalResourceCache().CreateTextureFromFile( pd3dDevice, + strPath, + &pMaterials[m].pDiffuseTexture9 ) ) ) + pMaterials[m].pDiffuseTexture9 = ( IDirect3DTexture9* )ERROR_RESOURCE_VALUE; + } + if( pMaterials[m].NormalTexture[0] != 0 ) + { + sprintf_s( strPath, MAX_PATH, "%s%s", m_strPath, pMaterials[m].NormalTexture ); + if( FAILED( DXUTGetGlobalResourceCache().CreateTextureFromFile( pd3dDevice, + strPath, + &pMaterials[m].pNormalTexture9 ) ) ) + pMaterials[m].pNormalTexture9 = ( IDirect3DTexture9* )ERROR_RESOURCE_VALUE; + } + if( pMaterials[m].SpecularTexture[0] != 0 ) + { + sprintf_s( strPath, MAX_PATH, "%s%s", m_strPath, pMaterials[m].SpecularTexture ); + if( FAILED( DXUTGetGlobalResourceCache().CreateTextureFromFile( pd3dDevice, + strPath, + &pMaterials[m].pSpecularTexture9 ) ) ) + pMaterials[m].pSpecularTexture9 = ( IDirect3DTexture9* )ERROR_RESOURCE_VALUE; + } + + } + } +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTSDKMesh::CreateVertexBuffer( ID3D11Device* pd3dDevice, SDKMESH_VERTEX_BUFFER_HEADER* pHeader, + void* pVertices, SDKMESH_CALLBACKS11* pLoaderCallbacks ) +{ + HRESULT hr = S_OK; + pHeader->DataOffset = 0; + //Vertex Buffer + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = ( UINT )( pHeader->SizeBytes ); + bufferDesc.Usage = D3D11_USAGE_DEFAULT; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.CPUAccessFlags = 0; + bufferDesc.MiscFlags = 0; + + if( pLoaderCallbacks && pLoaderCallbacks->pCreateVertexBuffer ) + { + pLoaderCallbacks->pCreateVertexBuffer( pd3dDevice, &pHeader->pVB11, bufferDesc, pVertices, + pLoaderCallbacks->pContext ); + } + else + { + D3D11_SUBRESOURCE_DATA InitData; + InitData.pSysMem = pVertices; + hr = pd3dDevice->CreateBuffer( &bufferDesc, &InitData, &pHeader->pVB11 ); + } + + return hr; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTSDKMesh::CreateIndexBuffer( ID3D11Device* pd3dDevice, SDKMESH_INDEX_BUFFER_HEADER* pHeader, + void* pIndices, SDKMESH_CALLBACKS11* pLoaderCallbacks ) +{ + HRESULT hr = S_OK; + pHeader->DataOffset = 0; + //Index Buffer + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = ( UINT )( pHeader->SizeBytes ); + bufferDesc.Usage = D3D11_USAGE_DEFAULT; + bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc.CPUAccessFlags = 0; + bufferDesc.MiscFlags = 0; + + if( pLoaderCallbacks && pLoaderCallbacks->pCreateIndexBuffer ) + { + pLoaderCallbacks->pCreateIndexBuffer( pd3dDevice, &pHeader->pIB11, bufferDesc, pIndices, + pLoaderCallbacks->pContext ); + } + else + { + D3D11_SUBRESOURCE_DATA InitData; + InitData.pSysMem = pIndices; + hr = pd3dDevice->CreateBuffer( &bufferDesc, &InitData, &pHeader->pIB11 ); + } + + return hr; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTSDKMesh::CreateVertexBuffer( IDirect3DDevice9* pd3dDevice, SDKMESH_VERTEX_BUFFER_HEADER* pHeader, + void* pVertices, SDKMESH_CALLBACKS9* pLoaderCallbacks ) +{ + HRESULT hr = S_OK; + + pHeader->DataOffset = 0; + if( pLoaderCallbacks && pLoaderCallbacks->pCreateVertexBuffer ) + { + pLoaderCallbacks->pCreateVertexBuffer( pd3dDevice, &pHeader->pVB9, ( UINT )pHeader->SizeBytes, + D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, pVertices, + pLoaderCallbacks->pContext ); + } + else + { + hr = pd3dDevice->CreateVertexBuffer( ( UINT )pHeader->SizeBytes, + D3DUSAGE_WRITEONLY, + 0, + D3DPOOL_DEFAULT, + &pHeader->pVB9, + NULL ); + + //lock + if( SUCCEEDED( hr ) ) + { + void* pLockedVerts = NULL; + V_RETURN( pHeader->pVB9->Lock( 0, 0, &pLockedVerts, 0 ) ); + CopyMemory( pLockedVerts, pVertices, ( size_t )pHeader->SizeBytes ); + pHeader->pVB9->Unlock(); + } + } + + return hr; +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTSDKMesh::CreateIndexBuffer( IDirect3DDevice9* pd3dDevice, SDKMESH_INDEX_BUFFER_HEADER* pHeader, + void* pIndices, SDKMESH_CALLBACKS9* pLoaderCallbacks ) +{ + HRESULT hr = S_OK; + + pHeader->DataOffset = 0; + + D3DFORMAT ibFormat = D3DFMT_INDEX16; + switch( pHeader->IndexType ) + { + case IT_16BIT: + ibFormat = D3DFMT_INDEX16; + break; + case IT_32BIT: + ibFormat = D3DFMT_INDEX32; + break; + }; + + if( pLoaderCallbacks && pLoaderCallbacks->pCreateIndexBuffer ) + { + pLoaderCallbacks->pCreateIndexBuffer( pd3dDevice, &pHeader->pIB9, ( UINT )pHeader->SizeBytes, + D3DUSAGE_WRITEONLY, ibFormat, D3DPOOL_DEFAULT, pIndices, + pLoaderCallbacks->pContext ); + } + else + { + hr = pd3dDevice->CreateIndexBuffer( ( UINT )( pHeader->SizeBytes ), + D3DUSAGE_WRITEONLY, + ibFormat, + D3DPOOL_DEFAULT, + &pHeader->pIB9, + NULL ); + + if( SUCCEEDED( hr ) ) + { + void* pLockedIndices = NULL; + V_RETURN( pHeader->pIB9->Lock( 0, 0, &pLockedIndices, 0 ) ); + CopyMemory( pLockedIndices, pIndices, ( size_t )( pHeader->SizeBytes ) ); + pHeader->pIB9->Unlock(); + } + } + + return hr; +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTSDKMesh::CreateFromFile( ID3D11Device* pDev11, + IDirect3DDevice9* pDev9, + LPCTSTR szFileName, + bool bCreateAdjacencyIndices, + SDKMESH_CALLBACKS11* pLoaderCallbacks11, + SDKMESH_CALLBACKS9* pLoaderCallbacks9 ) +{ + HRESULT hr = S_OK; + + // Find the path for the file + V_RETURN( DXUTFindDXSDKMediaFileCch( m_strPathW, sizeof( m_strPathW ) / sizeof( WCHAR ), szFileName ) ); + + // Open the file + m_hFile = CreateFile( m_strPathW, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, + NULL ); + if( INVALID_HANDLE_VALUE == m_hFile ) + return DXUTERR_MEDIANOTFOUND; + + // Change the path to just the directory + WCHAR* pLastBSlash = wcsrchr( m_strPathW, L'\\' ); + if( pLastBSlash ) + *( pLastBSlash + 1 ) = L'\0'; + else + *m_strPathW = L'\0'; + + WideCharToMultiByte( CP_ACP, 0, m_strPathW, -1, m_strPath, MAX_PATH, NULL, FALSE ); + + // Get the file size + LARGE_INTEGER FileSize; + GetFileSizeEx( m_hFile, &FileSize ); + UINT cBytes = FileSize.LowPart; + + // Allocate memory + m_pStaticMeshData = new BYTE[ cBytes ]; + if( !m_pStaticMeshData ) + { + CloseHandle( m_hFile ); + return E_OUTOFMEMORY; + } + + // Read in the file + DWORD dwBytesRead; + if( !ReadFile( m_hFile, m_pStaticMeshData, cBytes, &dwBytesRead, NULL ) ) + hr = E_FAIL; + + CloseHandle( m_hFile ); + + if( SUCCEEDED( hr ) ) + { + hr = CreateFromMemory( pDev11, + pDev9, + m_pStaticMeshData, + cBytes, + bCreateAdjacencyIndices, + false, + pLoaderCallbacks11, + pLoaderCallbacks9 ); + if( FAILED( hr ) ) + delete []m_pStaticMeshData; + } + + return hr; +} + +HRESULT CDXUTSDKMesh::CreateFromMemory( ID3D11Device* pDev11, + IDirect3DDevice9* pDev9, + BYTE* pData, + UINT DataBytes, + bool bCreateAdjacencyIndices, + bool bCopyStatic, + SDKMESH_CALLBACKS11* pLoaderCallbacks11, + SDKMESH_CALLBACKS9* pLoaderCallbacks9 ) +{ + HRESULT hr = E_FAIL; + D3DXVECTOR3 lower; + D3DXVECTOR3 upper; + + m_pDev9 = pDev9; + m_pDev11 = pDev11; + + // Set outstanding resources to zero + m_NumOutstandingResources = 0; + + if( bCopyStatic ) + { + SDKMESH_HEADER* pHeader = ( SDKMESH_HEADER* )pData; + + SIZE_T StaticSize = ( SIZE_T )( pHeader->HeaderSize + pHeader->NonBufferDataSize ); + m_pHeapData = new BYTE[ StaticSize ]; + if( !m_pHeapData ) + return hr; + + m_pStaticMeshData = m_pHeapData; + + CopyMemory( m_pStaticMeshData, pData, StaticSize ); + } + else + { + m_pHeapData = pData; + m_pStaticMeshData = pData; + } + + // Pointer fixup + m_pMeshHeader = ( SDKMESH_HEADER* )m_pStaticMeshData; + m_pVertexBufferArray = ( SDKMESH_VERTEX_BUFFER_HEADER* )( m_pStaticMeshData + + m_pMeshHeader->VertexStreamHeadersOffset ); + m_pIndexBufferArray = ( SDKMESH_INDEX_BUFFER_HEADER* )( m_pStaticMeshData + + m_pMeshHeader->IndexStreamHeadersOffset ); + m_pMeshArray = ( SDKMESH_MESH* )( m_pStaticMeshData + m_pMeshHeader->MeshDataOffset ); + m_pSubsetArray = ( SDKMESH_SUBSET* )( m_pStaticMeshData + m_pMeshHeader->SubsetDataOffset ); + m_pFrameArray = ( SDKMESH_FRAME* )( m_pStaticMeshData + m_pMeshHeader->FrameDataOffset ); + m_pMaterialArray = ( SDKMESH_MATERIAL* )( m_pStaticMeshData + m_pMeshHeader->MaterialDataOffset ); + + // Setup subsets + for( UINT i = 0; i < m_pMeshHeader->NumMeshes; i++ ) + { + m_pMeshArray[i].pSubsets = ( UINT* )( m_pStaticMeshData + m_pMeshArray[i].SubsetOffset ); + m_pMeshArray[i].pFrameInfluences = ( UINT* )( m_pStaticMeshData + m_pMeshArray[i].FrameInfluenceOffset ); + } + + // error condition + if( m_pMeshHeader->Version != SDKMESH_FILE_VERSION ) + { + hr = E_NOINTERFACE; + goto Error; + } + + // Setup buffer data pointer + BYTE* pBufferData = pData + m_pMeshHeader->HeaderSize + m_pMeshHeader->NonBufferDataSize; + + // Get the start of the buffer data + UINT64 BufferDataStart = m_pMeshHeader->HeaderSize + m_pMeshHeader->NonBufferDataSize; + + // Create VBs + m_ppVertices = new BYTE*[m_pMeshHeader->NumVertexBuffers]; + for( UINT i = 0; i < m_pMeshHeader->NumVertexBuffers; i++ ) + { + BYTE* pVertices = NULL; + pVertices = ( BYTE* )( pBufferData + ( m_pVertexBufferArray[i].DataOffset - BufferDataStart ) ); + + if( pDev11 ) + CreateVertexBuffer( pDev11, &m_pVertexBufferArray[i], pVertices, pLoaderCallbacks11 ); + else if( pDev9 ) + CreateVertexBuffer( pDev9, &m_pVertexBufferArray[i], pVertices, pLoaderCallbacks9 ); + + m_ppVertices[i] = pVertices; + } + + // Create IBs + m_ppIndices = new BYTE*[m_pMeshHeader->NumIndexBuffers]; + for( UINT i = 0; i < m_pMeshHeader->NumIndexBuffers; i++ ) + { + BYTE* pIndices = NULL; + pIndices = ( BYTE* )( pBufferData + ( m_pIndexBufferArray[i].DataOffset - BufferDataStart ) ); + + if( pDev11 ) + CreateIndexBuffer( pDev11, &m_pIndexBufferArray[i], pIndices, pLoaderCallbacks11 ); + else if( pDev9 ) + CreateIndexBuffer( pDev9, &m_pIndexBufferArray[i], pIndices, pLoaderCallbacks9 ); + + m_ppIndices[i] = pIndices; + } + + // Load Materials + if( pDev11 ) + LoadMaterials( pDev11, m_pMaterialArray, m_pMeshHeader->NumMaterials, pLoaderCallbacks11 ); + else if( pDev9 ) + LoadMaterials( pDev9, m_pMaterialArray, m_pMeshHeader->NumMaterials, pLoaderCallbacks9 ); + + // Create a place to store our bind pose frame matrices + m_pBindPoseFrameMatrices = new D3DXMATRIX[ m_pMeshHeader->NumFrames ]; + if( !m_pBindPoseFrameMatrices ) + goto Error; + + // Create a place to store our transformed frame matrices + m_pTransformedFrameMatrices = new D3DXMATRIX[ m_pMeshHeader->NumFrames ]; + if( !m_pTransformedFrameMatrices ) + goto Error; + m_pWorldPoseFrameMatrices = new D3DXMATRIX[ m_pMeshHeader->NumFrames ]; + if( !m_pWorldPoseFrameMatrices ) + goto Error; + + SDKMESH_SUBSET* pSubset = NULL; + D3D11_PRIMITIVE_TOPOLOGY PrimType; + + // update bounding volume + SDKMESH_MESH* currentMesh = &m_pMeshArray[0]; + int tris = 0; + for (UINT meshi=0; meshi < m_pMeshHeader->NumMeshes; ++meshi) { + lower.x = FLT_MAX; lower.y = FLT_MAX; lower.z = FLT_MAX; + upper.x = -FLT_MAX; upper.y = -FLT_MAX; upper.z = -FLT_MAX; + currentMesh = GetMesh( meshi ); + INT indsize; + if (m_pIndexBufferArray[currentMesh->IndexBuffer].IndexType == IT_16BIT ) { + indsize = 2; + }else { + indsize = 4; + } + + for( UINT subset = 0; subset < currentMesh->NumSubsets; subset++ ) + { + pSubset = GetSubset( meshi, subset ); //&m_pSubsetArray[ currentMesh->pSubsets[subset] ]; + + PrimType = GetPrimitiveType11( ( SDKMESH_PRIMITIVE_TYPE )pSubset->PrimitiveType ); + assert( PrimType == D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );// only triangle lists are handled. + + UINT IndexCount = ( UINT )pSubset->IndexCount; + UINT IndexStart = ( UINT )pSubset->IndexStart; + + /*if( bAdjacent ) + { + IndexCount *= 2; + IndexStart *= 2; + }*/ + + //BYTE* pIndices = NULL; + //m_ppIndices[i] + UINT *ind = ( UINT * )m_ppIndices[currentMesh->IndexBuffer]; + FLOAT *verts = ( FLOAT* )m_ppVertices[currentMesh->VertexBuffers[0]]; + UINT stride = (UINT)m_pVertexBufferArray[currentMesh->VertexBuffers[0]].StrideBytes; + assert (stride % 4 == 0); + stride /=4; + for (UINT vertind = IndexStart; vertind < IndexStart + IndexCount; ++vertind) { //TODO: test 16 bit and 32 bit + UINT current_ind=0; + if (indsize == 2) { + UINT ind_div2 = vertind / 2; + current_ind = ind[ind_div2]; + if (vertind %2 ==0) { + current_ind = current_ind << 16; + current_ind = current_ind >> 16; + }else { + current_ind = current_ind >> 16; + } + }else { + current_ind = ind[vertind]; + } + tris++; + D3DXVECTOR3 *pt = (D3DXVECTOR3*)&(verts[stride * current_ind]); + if (pt->x < lower.x) { + lower.x = pt->x; + } + if (pt->y < lower.y) { + lower.y = pt->y; + } + if (pt->z < lower.z) { + lower.z = pt->z; + } + if (pt->x > upper.x) { + upper.x = pt->x; + } + if (pt->y > upper.y) { + upper.y = pt->y; + } + if (pt->z > upper.z) { + upper.z = pt->z; + } + //BYTE** m_ppVertices; + //BYTE** m_ppIndices; + } + //pd3dDeviceContext->DrawIndexed( IndexCount, IndexStart, VertexStart ); + } + + D3DXVECTOR3 half = upper - lower; + half *=0.5f; + + currentMesh->BoundingBoxCenter = lower + half; + currentMesh->BoundingBoxExtents = half; + + } + // Update + + + + hr = S_OK; +Error: + + if( !pLoaderCallbacks9 ) + { + CheckLoadDone(); + } + + return hr; +} + +//-------------------------------------------------------------------------------------- +// transform bind pose frame using a recursive traversal +//-------------------------------------------------------------------------------------- +void CDXUTSDKMesh::TransformBindPoseFrame( UINT iFrame, D3DXMATRIX* pParentWorld ) +{ + if( !m_pBindPoseFrameMatrices ) + return; + + // Transform ourselves + D3DXMATRIX LocalWorld; + D3DXMatrixMultiply( &LocalWorld, &m_pFrameArray[iFrame].Matrix, pParentWorld ); + m_pBindPoseFrameMatrices[iFrame] = LocalWorld; + + // Transform our siblings + if( m_pFrameArray[iFrame].SiblingFrame != INVALID_FRAME ) + TransformBindPoseFrame( m_pFrameArray[iFrame].SiblingFrame, pParentWorld ); + + // Transform our children + if( m_pFrameArray[iFrame].ChildFrame != INVALID_FRAME ) + TransformBindPoseFrame( m_pFrameArray[iFrame].ChildFrame, &LocalWorld ); +} + +//-------------------------------------------------------------------------------------- +// transform frame using a recursive traversal +//-------------------------------------------------------------------------------------- +void CDXUTSDKMesh::TransformFrame( UINT iFrame, D3DXMATRIX* pParentWorld, double fTime ) +{ + // Get the tick data + D3DXMATRIX LocalTransform; + UINT iTick = GetAnimationKeyFromTime( fTime ); + + if( INVALID_ANIMATION_DATA != m_pFrameArray[iFrame].AnimationDataIndex ) + { + SDKANIMATION_FRAME_DATA* pFrameData = &m_pAnimationFrameData[ m_pFrameArray[iFrame].AnimationDataIndex ]; + SDKANIMATION_DATA* pData = &pFrameData->pAnimationData[ iTick ]; + + // turn it into a matrix (Ignore scaling for now) + D3DXVECTOR3 parentPos = pData->Translation; + D3DXMATRIX mTranslate; + D3DXMatrixTranslation( &mTranslate, parentPos.x, parentPos.y, parentPos.z ); + + D3DXQUATERNION quat; + D3DXMATRIX mQuat; + quat.w = pData->Orientation.w; + quat.x = pData->Orientation.x; + quat.y = pData->Orientation.y; + quat.z = pData->Orientation.z; + if( quat.w == 0 && quat.x == 0 && quat.y == 0 && quat.z == 0 ) + D3DXQuaternionIdentity( &quat ); + D3DXQuaternionNormalize( &quat, &quat ); + D3DXMatrixRotationQuaternion( &mQuat, &quat ); + LocalTransform = ( mQuat * mTranslate ); + } + else + { + LocalTransform = m_pFrameArray[iFrame].Matrix; + } + + // Transform ourselves + D3DXMATRIX LocalWorld; + D3DXMatrixMultiply( &LocalWorld, &LocalTransform, pParentWorld ); + m_pTransformedFrameMatrices[iFrame] = LocalWorld; + m_pWorldPoseFrameMatrices[iFrame] = LocalWorld; + + // Transform our siblings + if( m_pFrameArray[iFrame].SiblingFrame != INVALID_FRAME ) + TransformFrame( m_pFrameArray[iFrame].SiblingFrame, pParentWorld, fTime ); + + // Transform our children + if( m_pFrameArray[iFrame].ChildFrame != INVALID_FRAME ) + TransformFrame( m_pFrameArray[iFrame].ChildFrame, &LocalWorld, fTime ); +} + +//-------------------------------------------------------------------------------------- +// transform frame assuming that it is an absolute transformation +//-------------------------------------------------------------------------------------- +void CDXUTSDKMesh::TransformFrameAbsolute( UINT iFrame, double fTime ) +{ + D3DXMATRIX mTrans1; + D3DXMATRIX mTrans2; + D3DXMATRIX mRot1; + D3DXMATRIX mRot2; + D3DXQUATERNION quat1; + D3DXQUATERNION quat2; + D3DXMATRIX mTo; + D3DXMATRIX mInvTo; + D3DXMATRIX mFrom; + + UINT iTick = GetAnimationKeyFromTime( fTime ); + + if( INVALID_ANIMATION_DATA != m_pFrameArray[iFrame].AnimationDataIndex ) + { + SDKANIMATION_FRAME_DATA* pFrameData = &m_pAnimationFrameData[ m_pFrameArray[iFrame].AnimationDataIndex ]; + SDKANIMATION_DATA* pData = &pFrameData->pAnimationData[ iTick ]; + SDKANIMATION_DATA* pDataOrig = &pFrameData->pAnimationData[ 0 ]; + + D3DXMatrixTranslation( &mTrans1, -pDataOrig->Translation.x, + -pDataOrig->Translation.y, + -pDataOrig->Translation.z ); + D3DXMatrixTranslation( &mTrans2, pData->Translation.x, + pData->Translation.y, + pData->Translation.z ); + + quat1.x = pDataOrig->Orientation.x; + quat1.y = pDataOrig->Orientation.y; + quat1.z = pDataOrig->Orientation.z; + quat1.w = pDataOrig->Orientation.w; + D3DXQuaternionInverse( &quat1, &quat1 ); + D3DXMatrixRotationQuaternion( &mRot1, &quat1 ); + mInvTo = mTrans1 * mRot1; + + quat2.x = pData->Orientation.x; + quat2.y = pData->Orientation.y; + quat2.z = pData->Orientation.z; + quat2.w = pData->Orientation.w; + D3DXMatrixRotationQuaternion( &mRot2, &quat2 ); + mFrom = mRot2 * mTrans2; + + D3DXMATRIX mOutput = mInvTo * mFrom; + m_pTransformedFrameMatrices[iFrame] = mOutput; + } +} + +#define MAX_D3D11_VERTEX_STREAMS D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT +//-------------------------------------------------------------------------------------- +void CDXUTSDKMesh::RenderMesh( UINT iMesh, + bool bAdjacent, + ID3D11DeviceContext* pd3dDeviceContext, + UINT iDiffuseSlot, + UINT iNormalSlot, + UINT iSpecularSlot ) +{ + if( 0 < GetOutstandingBufferResources() ) + return; + + SDKMESH_MESH* pMesh = &m_pMeshArray[iMesh]; + + UINT Strides[MAX_D3D11_VERTEX_STREAMS]; + UINT Offsets[MAX_D3D11_VERTEX_STREAMS]; + ID3D11Buffer* pVB[MAX_D3D11_VERTEX_STREAMS]; + + if( pMesh->NumVertexBuffers > MAX_D3D11_VERTEX_STREAMS ) + return; + + for( UINT64 i = 0; i < pMesh->NumVertexBuffers; i++ ) + { + pVB[i] = m_pVertexBufferArray[ pMesh->VertexBuffers[i] ].pVB11; + Strides[i] = ( UINT )m_pVertexBufferArray[ pMesh->VertexBuffers[i] ].StrideBytes; + Offsets[i] = 0; + } + + SDKMESH_INDEX_BUFFER_HEADER* pIndexBufferArray; + if( bAdjacent ) + pIndexBufferArray = m_pAdjacencyIndexBufferArray; + else + pIndexBufferArray = m_pIndexBufferArray; + + ID3D11Buffer* pIB = pIndexBufferArray[ pMesh->IndexBuffer ].pIB11; + DXGI_FORMAT ibFormat = DXGI_FORMAT_R16_UINT; + switch( pIndexBufferArray[ pMesh->IndexBuffer ].IndexType ) + { + case IT_16BIT: + ibFormat = DXGI_FORMAT_R16_UINT; + break; + case IT_32BIT: + ibFormat = DXGI_FORMAT_R32_UINT; + break; + }; + + pd3dDeviceContext->IASetVertexBuffers( 0, pMesh->NumVertexBuffers, pVB, Strides, Offsets ); + pd3dDeviceContext->IASetIndexBuffer( pIB, ibFormat, 0 ); + + SDKMESH_SUBSET* pSubset = NULL; + SDKMESH_MATERIAL* pMat = NULL; + D3D11_PRIMITIVE_TOPOLOGY PrimType; + + for( UINT subset = 0; subset < pMesh->NumSubsets; subset++ ) + { + pSubset = &m_pSubsetArray[ pMesh->pSubsets[subset] ]; + + PrimType = GetPrimitiveType11( ( SDKMESH_PRIMITIVE_TYPE )pSubset->PrimitiveType ); + if( bAdjacent ) + { + switch( PrimType ) + { + case D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST: + PrimType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ; + break; + case D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP: + PrimType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ; + break; + case D3D11_PRIMITIVE_TOPOLOGY_LINELIST: + PrimType = D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ; + break; + case D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP: + PrimType = D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ; + break; + } + } + + pd3dDeviceContext->IASetPrimitiveTopology( PrimType ); + + pMat = &m_pMaterialArray[ pSubset->MaterialID ]; + if( iDiffuseSlot != INVALID_SAMPLER_SLOT && !IsErrorResource( pMat->pDiffuseRV11 ) ) + pd3dDeviceContext->PSSetShaderResources( iDiffuseSlot, 1, &pMat->pDiffuseRV11 ); + if( iNormalSlot != INVALID_SAMPLER_SLOT && !IsErrorResource( pMat->pNormalRV11 ) ) + pd3dDeviceContext->PSSetShaderResources( iNormalSlot, 1, &pMat->pNormalRV11 ); + if( iSpecularSlot != INVALID_SAMPLER_SLOT && !IsErrorResource( pMat->pSpecularRV11 ) ) + pd3dDeviceContext->PSSetShaderResources( iSpecularSlot, 1, &pMat->pSpecularRV11 ); + + UINT IndexCount = ( UINT )pSubset->IndexCount; + UINT IndexStart = ( UINT )pSubset->IndexStart; + UINT VertexStart = ( UINT )pSubset->VertexStart; + if( bAdjacent ) + { + IndexCount *= 2; + IndexStart *= 2; + } + + pd3dDeviceContext->DrawIndexed( IndexCount, IndexStart, VertexStart ); + } +} + +//-------------------------------------------------------------------------------------- +void CDXUTSDKMesh::RenderFrame( UINT iFrame, + bool bAdjacent, + ID3D11DeviceContext* pd3dDeviceContext, + UINT iDiffuseSlot, + UINT iNormalSlot, + UINT iSpecularSlot ) +{ + if( !m_pStaticMeshData || !m_pFrameArray ) + return; + + if( m_pFrameArray[iFrame].Mesh != INVALID_MESH ) + { + RenderMesh( m_pFrameArray[iFrame].Mesh, + bAdjacent, + pd3dDeviceContext, + iDiffuseSlot, + iNormalSlot, + iSpecularSlot ); + } + + // Render our children + if( m_pFrameArray[iFrame].ChildFrame != INVALID_FRAME ) + RenderFrame( m_pFrameArray[iFrame].ChildFrame, bAdjacent, pd3dDeviceContext, iDiffuseSlot, + iNormalSlot, iSpecularSlot ); + + // Render our siblings + if( m_pFrameArray[iFrame].SiblingFrame != INVALID_FRAME ) + RenderFrame( m_pFrameArray[iFrame].SiblingFrame, bAdjacent, pd3dDeviceContext, iDiffuseSlot, + iNormalSlot, iSpecularSlot ); +} + +//-------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------------- +void CDXUTSDKMesh::RenderMesh( UINT iMesh, + LPDIRECT3DDEVICE9 pd3dDevice, + LPD3DXEFFECT pEffect, + D3DXHANDLE hTechnique, + D3DXHANDLE htxDiffuse, + D3DXHANDLE htxNormal, + D3DXHANDLE htxSpecular ) +{ + if( 0 < GetOutstandingBufferResources() ) + return; + + SDKMESH_MESH* pMesh = &m_pMeshArray[iMesh]; + + // set vb streams + for( UINT i = 0; i < ( UINT )pMesh->NumVertexBuffers; i++ ) + { + pd3dDevice->SetStreamSource( i, + m_pVertexBufferArray[ pMesh->VertexBuffers[i] ].pVB9, + 0, + ( UINT )m_pVertexBufferArray[ pMesh->VertexBuffers[i] ].StrideBytes ); + } + + // Set our index buffer as well + pd3dDevice->SetIndices( m_pIndexBufferArray[ pMesh->IndexBuffer ].pIB9 ); + + // Render the scene with this technique + pEffect->SetTechnique( hTechnique ); + + SDKMESH_SUBSET* pSubset = NULL; + SDKMESH_MATERIAL* pMat = NULL; + D3DPRIMITIVETYPE PrimType; + UINT cPasses = 0; + pEffect->Begin( &cPasses, 0 ); + + for( UINT p = 0; p < cPasses; ++p ) + { + pEffect->BeginPass( p ); + + for( UINT subset = 0; subset < pMesh->NumSubsets; subset++ ) + { + pSubset = &m_pSubsetArray[ pMesh->pSubsets[subset] ]; + + PrimType = GetPrimitiveType9( ( SDKMESH_PRIMITIVE_TYPE )pSubset->PrimitiveType ); + + if( INVALID_MATERIAL != pSubset->MaterialID && m_pMeshHeader->NumMaterials > 0 ) + { + pMat = &m_pMaterialArray[ pSubset->MaterialID ]; + if( htxDiffuse && !IsErrorResource( pMat->pDiffuseTexture9 ) ) + pEffect->SetTexture( htxDiffuse, pMat->pDiffuseTexture9 ); + if( htxNormal && !IsErrorResource( pMat->pNormalTexture9 ) ) + pEffect->SetTexture( htxNormal, pMat->pNormalTexture9 ); + if( htxSpecular && !IsErrorResource( pMat->pSpecularTexture9 ) ) + pEffect->SetTexture( htxSpecular, pMat->pSpecularTexture9 ); + } + + pEffect->CommitChanges(); + + UINT PrimCount = ( UINT )pSubset->IndexCount; + UINT IndexStart = ( UINT )pSubset->IndexStart; + UINT VertexStart = ( UINT )pSubset->VertexStart; + UINT VertexCount = ( UINT )pSubset->VertexCount; + if( D3DPT_TRIANGLELIST == PrimType ) + PrimCount /= 3; + if( D3DPT_LINELIST == PrimType ) + PrimCount /= 2; + if( D3DPT_TRIANGLESTRIP == PrimType ) + PrimCount = ( PrimCount - 3 ) + 1; + if( D3DPT_LINESTRIP == PrimType ) + PrimCount -= 1; + + pd3dDevice->DrawIndexedPrimitive( PrimType, VertexStart, 0, VertexCount, IndexStart, PrimCount ); + } + + pEffect->EndPass(); + } + + pEffect->End(); +} + +//-------------------------------------------------------------------------------------- +void CDXUTSDKMesh::RenderFrame( UINT iFrame, + LPDIRECT3DDEVICE9 pd3dDevice, + LPD3DXEFFECT pEffect, + D3DXHANDLE hTechnique, + D3DXHANDLE htxDiffuse, + D3DXHANDLE htxNormal, + D3DXHANDLE htxSpecular ) +{ + if( !m_pStaticMeshData || !m_pFrameArray ) + return; + + if( m_pFrameArray[iFrame].Mesh != INVALID_MESH ) + { + RenderMesh( m_pFrameArray[iFrame].Mesh, + pd3dDevice, + pEffect, + hTechnique, + htxDiffuse, + htxNormal, + htxSpecular ); + } + + // Render our children + if( m_pFrameArray[iFrame].ChildFrame != INVALID_FRAME ) + RenderFrame( m_pFrameArray[iFrame].ChildFrame, pd3dDevice, pEffect, hTechnique, htxDiffuse, htxNormal, + htxSpecular ); + + // Render our siblings + if( m_pFrameArray[iFrame].SiblingFrame != INVALID_FRAME ) + RenderFrame( m_pFrameArray[iFrame].SiblingFrame, pd3dDevice, pEffect, hTechnique, htxDiffuse, htxNormal, + htxSpecular ); +} + + +//-------------------------------------------------------------------------------------- +CDXUTSDKMesh::CDXUTSDKMesh() : m_NumOutstandingResources( 0 ), + m_bLoading( false ), + m_hFile( 0 ), + m_hFileMappingObject( 0 ), + m_pMeshHeader( NULL ), + m_pStaticMeshData( NULL ), + m_pHeapData( NULL ), + m_pAdjacencyIndexBufferArray( NULL ), + m_pAnimationData( NULL ), + m_pAnimationHeader( NULL ), + m_ppVertices( NULL ), + m_ppIndices( NULL ), + m_pBindPoseFrameMatrices( NULL ), + m_pTransformedFrameMatrices( NULL ), + m_pWorldPoseFrameMatrices( NULL ), + m_pDev9( NULL ), + m_pDev11( NULL ) +{ +} + + +//-------------------------------------------------------------------------------------- +CDXUTSDKMesh::~CDXUTSDKMesh() +{ + Destroy(); +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTSDKMesh::Create( ID3D11Device* pDev11, LPCTSTR szFileName, bool bCreateAdjacencyIndices, + SDKMESH_CALLBACKS11* pLoaderCallbacks ) +{ + return CreateFromFile( pDev11, NULL, szFileName, bCreateAdjacencyIndices, pLoaderCallbacks, NULL ); +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTSDKMesh::Create( IDirect3DDevice9* pDev9, LPCTSTR szFileName, bool bCreateAdjacencyIndices, + SDKMESH_CALLBACKS9* pLoaderCallbacks ) +{ + return CreateFromFile( NULL, pDev9, szFileName, bCreateAdjacencyIndices, NULL, pLoaderCallbacks ); +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTSDKMesh::Create( ID3D11Device* pDev11, BYTE* pData, UINT DataBytes, bool bCreateAdjacencyIndices, + bool bCopyStatic, SDKMESH_CALLBACKS11* pLoaderCallbacks ) +{ + return CreateFromMemory( pDev11, NULL, pData, DataBytes, bCreateAdjacencyIndices, bCopyStatic, + pLoaderCallbacks, NULL ); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTSDKMesh::Create( IDirect3DDevice9* pDev9, BYTE* pData, UINT DataBytes, bool bCreateAdjacencyIndices, + bool bCopyStatic, SDKMESH_CALLBACKS9* pLoaderCallbacks ) +{ + return CreateFromMemory( NULL, pDev9, pData, DataBytes, bCreateAdjacencyIndices, bCopyStatic, NULL, + pLoaderCallbacks ); +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTSDKMesh::LoadAnimation( WCHAR* szFileName ) +{ + HRESULT hr = E_FAIL; + DWORD dwBytesRead = 0; + LARGE_INTEGER liMove; + WCHAR strPath[MAX_PATH]; + + // Find the path for the file + V_RETURN( DXUTFindDXSDKMediaFileCch( strPath, MAX_PATH, szFileName ) ); + + // Open the file + HANDLE hFile = CreateFile( strPath, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, NULL ); + if( INVALID_HANDLE_VALUE == hFile ) + return DXUTERR_MEDIANOTFOUND; + + ///////////////////////// + // Header + SDKANIMATION_FILE_HEADER fileheader; + if( !ReadFile( hFile, &fileheader, sizeof( SDKANIMATION_FILE_HEADER ), &dwBytesRead, NULL ) ) + goto Error; + + //allocate + m_pAnimationData = new BYTE[ ( size_t )( sizeof( SDKANIMATION_FILE_HEADER ) + fileheader.AnimationDataSize ) ]; + if( !m_pAnimationData ) + { + hr = E_OUTOFMEMORY; + goto Error; + } + + // read it all in + liMove.QuadPart = 0; + if( !SetFilePointerEx( hFile, liMove, NULL, FILE_BEGIN ) ) + goto Error; + if( !ReadFile( hFile, m_pAnimationData, ( DWORD )( sizeof( SDKANIMATION_FILE_HEADER ) + + fileheader.AnimationDataSize ), &dwBytesRead, NULL ) ) + goto Error; + + // pointer fixup + m_pAnimationHeader = ( SDKANIMATION_FILE_HEADER* )m_pAnimationData; + m_pAnimationFrameData = ( SDKANIMATION_FRAME_DATA* )( m_pAnimationData + m_pAnimationHeader->AnimationDataOffset ); + + UINT64 BaseOffset = sizeof( SDKANIMATION_FILE_HEADER ); + for( UINT i = 0; i < m_pAnimationHeader->NumFrames; i++ ) + { + m_pAnimationFrameData[i].pAnimationData = ( SDKANIMATION_DATA* )( m_pAnimationData + + m_pAnimationFrameData[i].DataOffset + + BaseOffset ); + SDKMESH_FRAME* pFrame = FindFrame( m_pAnimationFrameData[i].FrameName ); + if( pFrame ) + { + pFrame->AnimationDataIndex = i; + } + } + + hr = S_OK; +Error: + CloseHandle( hFile ); + return hr; +} + +//-------------------------------------------------------------------------------------- +void CDXUTSDKMesh::Destroy() +{ + if( !CheckLoadDone() ) + return; + + if( m_pStaticMeshData ) + { + if( m_pMaterialArray ) + { + for( UINT64 m = 0; m < m_pMeshHeader->NumMaterials; m++ ) + { + if( m_pDev9 ) + { + if( !IsErrorResource( m_pMaterialArray[m].pDiffuseTexture9 ) ) + SAFE_RELEASE( m_pMaterialArray[m].pDiffuseTexture9 ); + if( !IsErrorResource( m_pMaterialArray[m].pNormalTexture9 ) ) + SAFE_RELEASE( m_pMaterialArray[m].pNormalTexture9 ); + if( !IsErrorResource( m_pMaterialArray[m].pSpecularTexture9 ) ) + SAFE_RELEASE( m_pMaterialArray[m].pSpecularTexture9 ); + } + else if( m_pDev11 ) + { + //ID3D11Resource* pRes = NULL; + if( m_pMaterialArray[m].pDiffuseRV11 && !IsErrorResource( m_pMaterialArray[m].pDiffuseRV11 ) ) + { + //m_pMaterialArray[m].pDiffuseRV11->GetResource( &pRes ); + //SAFE_RELEASE( pRes ); + + SAFE_RELEASE( m_pMaterialArray[m].pDiffuseRV11 ); + } + if( m_pMaterialArray[m].pNormalRV11 && !IsErrorResource( m_pMaterialArray[m].pNormalRV11 ) ) + { + //m_pMaterialArray[m].pNormalRV11->GetResource( &pRes ); + //SAFE_RELEASE( pRes ); + + SAFE_RELEASE( m_pMaterialArray[m].pNormalRV11 ); + } + if( m_pMaterialArray[m].pSpecularRV11 && !IsErrorResource( m_pMaterialArray[m].pSpecularRV11 ) ) + { + //m_pMaterialArray[m].pSpecularRV11->GetResource( &pRes ); + //SAFE_RELEASE( pRes ); + + SAFE_RELEASE( m_pMaterialArray[m].pSpecularRV11 ); + } + } + } + } + + for( UINT64 i = 0; i < m_pMeshHeader->NumVertexBuffers; i++ ) + { + if( !IsErrorResource( m_pVertexBufferArray[i].pVB9 ) ) + SAFE_RELEASE( m_pVertexBufferArray[i].pVB9 ); + } + + for( UINT64 i = 0; i < m_pMeshHeader->NumIndexBuffers; i++ ) + { + if( !IsErrorResource( m_pIndexBufferArray[i].pIB9 ) ) + SAFE_RELEASE( m_pIndexBufferArray[i].pIB9 ); + } + } + + if( m_pAdjacencyIndexBufferArray ) + { + for( UINT64 i = 0; i < m_pMeshHeader->NumIndexBuffers; i++ ) + { + SAFE_RELEASE( m_pAdjacencyIndexBufferArray[i].pIB11 ); + } + } + SAFE_DELETE_ARRAY( m_pAdjacencyIndexBufferArray ); + + SAFE_DELETE_ARRAY( m_pHeapData ); + m_pStaticMeshData = NULL; + SAFE_DELETE_ARRAY( m_pAnimationData ); + SAFE_DELETE_ARRAY( m_pBindPoseFrameMatrices ); + SAFE_DELETE_ARRAY( m_pTransformedFrameMatrices ); + SAFE_DELETE_ARRAY( m_pWorldPoseFrameMatrices ); + + SAFE_DELETE_ARRAY( m_ppVertices ); + SAFE_DELETE_ARRAY( m_ppIndices ); + + m_pMeshHeader = NULL; + m_pVertexBufferArray = NULL; + m_pIndexBufferArray = NULL; + m_pMeshArray = NULL; + m_pSubsetArray = NULL; + m_pFrameArray = NULL; + m_pMaterialArray = NULL; + + m_pAnimationHeader = NULL; + m_pAnimationFrameData = NULL; + +} + +//-------------------------------------------------------------------------------------- +// transform the bind pose +//-------------------------------------------------------------------------------------- +void CDXUTSDKMesh::TransformBindPose( D3DXMATRIX* pWorld ) +{ + TransformBindPoseFrame( 0, pWorld ); +} + +//-------------------------------------------------------------------------------------- +// transform the mesh frames according to the animation for time fTime +//-------------------------------------------------------------------------------------- +void CDXUTSDKMesh::TransformMesh( D3DXMATRIX* pWorld, double fTime ) +{ + if( m_pAnimationHeader == NULL || FTT_RELATIVE == m_pAnimationHeader->FrameTransformType ) + { + TransformFrame( 0, pWorld, fTime ); + + // For each frame, move the transform to the bind pose, then + // move it to the final position + D3DXMATRIX mInvBindPose; + D3DXMATRIX mFinal; + for( UINT i = 0; i < m_pMeshHeader->NumFrames; i++ ) + { + D3DXMatrixInverse( &mInvBindPose, NULL, &m_pBindPoseFrameMatrices[i] ); + mFinal = mInvBindPose * m_pTransformedFrameMatrices[i]; + m_pTransformedFrameMatrices[i] = mFinal; + } + } + else if( FTT_ABSOLUTE == m_pAnimationHeader->FrameTransformType ) + { + for( UINT i = 0; i < m_pAnimationHeader->NumFrames; i++ ) + TransformFrameAbsolute( i, fTime ); + } +} + + +//-------------------------------------------------------------------------------------- +void CDXUTSDKMesh::Render( ID3D11DeviceContext* pd3dDeviceContext, + UINT iDiffuseSlot, + UINT iNormalSlot, + UINT iSpecularSlot ) +{ + RenderFrame( 0, false, pd3dDeviceContext, iDiffuseSlot, iNormalSlot, iSpecularSlot ); +} + +//-------------------------------------------------------------------------------------- +void CDXUTSDKMesh::RenderAdjacent( ID3D11DeviceContext* pd3dDeviceContext, + UINT iDiffuseSlot, + UINT iNormalSlot, + UINT iSpecularSlot ) +{ + RenderFrame( 0, true, pd3dDeviceContext, iDiffuseSlot, iNormalSlot, iSpecularSlot ); +} + + +//-------------------------------------------------------------------------------------- +void CDXUTSDKMesh::Render( LPDIRECT3DDEVICE9 pd3dDevice, + LPD3DXEFFECT pEffect, + D3DXHANDLE hTechnique, + D3DXHANDLE htxDiffuse, + D3DXHANDLE htxNormal, + D3DXHANDLE htxSpecular ) +{ + RenderFrame( 0, pd3dDevice, pEffect, hTechnique, htxDiffuse, htxNormal, htxSpecular ); +} + +//-------------------------------------------------------------------------------------- +D3D11_PRIMITIVE_TOPOLOGY CDXUTSDKMesh::GetPrimitiveType11( SDKMESH_PRIMITIVE_TYPE PrimType ) +{ + D3D11_PRIMITIVE_TOPOLOGY retType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + + switch( PrimType ) + { + case PT_TRIANGLE_LIST: + retType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + break; + case PT_TRIANGLE_STRIP: + retType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; + break; + case PT_LINE_LIST: + retType = D3D11_PRIMITIVE_TOPOLOGY_LINELIST; + break; + case PT_LINE_STRIP: + retType = D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP; + break; + case PT_POINT_LIST: + retType = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; + break; + case PT_TRIANGLE_LIST_ADJ: + retType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ; + break; + case PT_TRIANGLE_STRIP_ADJ: + retType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ; + break; + case PT_LINE_LIST_ADJ: + retType = D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ; + break; + case PT_LINE_STRIP_ADJ: + retType = D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ; + break; + }; + + return retType; +} + +//-------------------------------------------------------------------------------------- +DXGI_FORMAT CDXUTSDKMesh::GetIBFormat11( UINT iMesh ) +{ + switch( m_pIndexBufferArray[ m_pMeshArray[ iMesh ].IndexBuffer ].IndexType ) + { + case IT_16BIT: + return DXGI_FORMAT_R16_UINT; + case IT_32BIT: + return DXGI_FORMAT_R32_UINT; + }; + return DXGI_FORMAT_R16_UINT; +} + +//-------------------------------------------------------------------------------------- +ID3D11Buffer* CDXUTSDKMesh::GetVB11( UINT iMesh, UINT iVB ) +{ + return m_pVertexBufferArray[ m_pMeshArray[ iMesh ].VertexBuffers[iVB] ].pVB11; +} + +//-------------------------------------------------------------------------------------- +ID3D11Buffer* CDXUTSDKMesh::GetIB11( UINT iMesh ) +{ + return m_pIndexBufferArray[ m_pMeshArray[ iMesh ].IndexBuffer ].pIB11; +} +SDKMESH_INDEX_TYPE CDXUTSDKMesh::GetIndexType( UINT iMesh ) +{ + return ( SDKMESH_INDEX_TYPE ) m_pIndexBufferArray[m_pMeshArray[ iMesh ].IndexBuffer].IndexType; +} +//-------------------------------------------------------------------------------------- +ID3D11Buffer* CDXUTSDKMesh::GetAdjIB11( UINT iMesh ) +{ + return m_pAdjacencyIndexBufferArray[ m_pMeshArray[ iMesh ].IndexBuffer ].pIB11; +} + +//-------------------------------------------------------------------------------------- +D3DPRIMITIVETYPE CDXUTSDKMesh::GetPrimitiveType9( SDKMESH_PRIMITIVE_TYPE PrimType ) +{ + D3DPRIMITIVETYPE retType = D3DPT_TRIANGLELIST; + + switch( PrimType ) + { + case PT_TRIANGLE_LIST: + retType = D3DPT_TRIANGLELIST; + break; + case PT_TRIANGLE_STRIP: + retType = D3DPT_TRIANGLESTRIP; + break; + case PT_LINE_LIST: + retType = D3DPT_LINELIST; + break; + case PT_LINE_STRIP: + retType = D3DPT_LINESTRIP; + break; + case PT_POINT_LIST: + retType = D3DPT_POINTLIST; + break; + }; + + return retType; +} + +//-------------------------------------------------------------------------------------- +D3DFORMAT CDXUTSDKMesh::GetIBFormat9( UINT iMesh ) +{ + switch( m_pIndexBufferArray[ m_pMeshArray[ iMesh ].IndexBuffer ].IndexType ) + { + case IT_16BIT: + return D3DFMT_INDEX16; + case IT_32BIT: + return D3DFMT_INDEX32; + }; + return D3DFMT_INDEX16; +} + +//-------------------------------------------------------------------------------------- +IDirect3DVertexBuffer9* CDXUTSDKMesh::GetVB9( UINT iMesh, UINT iVB ) +{ + return m_pVertexBufferArray[ m_pMeshArray[ iMesh ].VertexBuffers[iVB] ].pVB9; +} + +//-------------------------------------------------------------------------------------- +IDirect3DIndexBuffer9* CDXUTSDKMesh::GetIB9( UINT iMesh ) +{ + return m_pIndexBufferArray[ m_pMeshArray[ iMesh ].IndexBuffer ].pIB9; +} + +//-------------------------------------------------------------------------------------- +char* CDXUTSDKMesh::GetMeshPathA() +{ + return m_strPath; +} + +//-------------------------------------------------------------------------------------- +WCHAR* CDXUTSDKMesh::GetMeshPathW() +{ + return m_strPathW; +} + +//-------------------------------------------------------------------------------------- +UINT CDXUTSDKMesh::GetNumMeshes() +{ + if( !m_pMeshHeader ) + return 0; + return m_pMeshHeader->NumMeshes; +} + +//-------------------------------------------------------------------------------------- +UINT CDXUTSDKMesh::GetNumMaterials() +{ + if( !m_pMeshHeader ) + return 0; + return m_pMeshHeader->NumMaterials; +} + +//-------------------------------------------------------------------------------------- +UINT CDXUTSDKMesh::GetNumVBs() +{ + if( !m_pMeshHeader ) + return 0; + return m_pMeshHeader->NumVertexBuffers; +} + +//-------------------------------------------------------------------------------------- +UINT CDXUTSDKMesh::GetNumIBs() +{ + if( !m_pMeshHeader ) + return 0; + return m_pMeshHeader->NumIndexBuffers; +} + +//-------------------------------------------------------------------------------------- +ID3D11Buffer* CDXUTSDKMesh::GetVB11At( UINT iVB ) +{ + return m_pVertexBufferArray[ iVB ].pVB11; +} + +//-------------------------------------------------------------------------------------- +ID3D11Buffer* CDXUTSDKMesh::GetIB11At( UINT iIB ) +{ + return m_pIndexBufferArray[ iIB ].pIB11; +} + +//-------------------------------------------------------------------------------------- +IDirect3DVertexBuffer9* CDXUTSDKMesh::GetVB9At( UINT iVB ) +{ + return m_pVertexBufferArray[ iVB ].pVB9; +} + +//-------------------------------------------------------------------------------------- +IDirect3DIndexBuffer9* CDXUTSDKMesh::GetIB9At( UINT iIB ) +{ + return m_pIndexBufferArray[ iIB ].pIB9; +} + +//-------------------------------------------------------------------------------------- +BYTE* CDXUTSDKMesh::GetRawVerticesAt( UINT iVB ) +{ + return m_ppVertices[iVB]; +} + +//-------------------------------------------------------------------------------------- +BYTE* CDXUTSDKMesh::GetRawIndicesAt( UINT iIB ) +{ + return m_ppIndices[iIB]; +} + +//-------------------------------------------------------------------------------------- +SDKMESH_MATERIAL* CDXUTSDKMesh::GetMaterial( UINT iMaterial ) +{ + return &m_pMaterialArray[ iMaterial ]; +} + +//-------------------------------------------------------------------------------------- +SDKMESH_MESH* CDXUTSDKMesh::GetMesh( UINT iMesh ) +{ + return &m_pMeshArray[ iMesh ]; +} + +//-------------------------------------------------------------------------------------- +UINT CDXUTSDKMesh::GetNumSubsets( UINT iMesh ) +{ + return m_pMeshArray[ iMesh ].NumSubsets; +} + +//-------------------------------------------------------------------------------------- +SDKMESH_SUBSET* CDXUTSDKMesh::GetSubset( UINT iMesh, UINT iSubset ) +{ + return &m_pSubsetArray[ m_pMeshArray[ iMesh ].pSubsets[iSubset] ]; +} + +//-------------------------------------------------------------------------------------- +UINT CDXUTSDKMesh::GetVertexStride( UINT iMesh, UINT iVB ) +{ + return ( UINT )m_pVertexBufferArray[ m_pMeshArray[ iMesh ].VertexBuffers[iVB] ].StrideBytes; +} + +//-------------------------------------------------------------------------------------- +UINT CDXUTSDKMesh::GetNumFrames() +{ + return m_pMeshHeader->NumFrames; +} + +//-------------------------------------------------------------------------------------- +SDKMESH_FRAME* CDXUTSDKMesh::GetFrame( UINT iFrame ) +{ + assert( iFrame < m_pMeshHeader->NumFrames ); + return &m_pFrameArray[ iFrame ]; +} + +//-------------------------------------------------------------------------------------- +SDKMESH_FRAME* CDXUTSDKMesh::FindFrame( char* pszName ) +{ + for( UINT i = 0; i < m_pMeshHeader->NumFrames; i++ ) + { + if( _stricmp( m_pFrameArray[i].Name, pszName ) == 0 ) + { + return &m_pFrameArray[i]; + } + } + return NULL; +} + +//-------------------------------------------------------------------------------------- +UINT64 CDXUTSDKMesh::GetNumVertices( UINT iMesh, UINT iVB ) +{ + return m_pVertexBufferArray[ m_pMeshArray[ iMesh ].VertexBuffers[iVB] ].NumVertices; +} + +//-------------------------------------------------------------------------------------- +UINT64 CDXUTSDKMesh::GetNumIndices( UINT iMesh ) +{ + return m_pIndexBufferArray[ m_pMeshArray[ iMesh ].IndexBuffer ].NumIndices; +} + +//-------------------------------------------------------------------------------------- +D3DXVECTOR3 CDXUTSDKMesh::GetMeshBBoxCenter( UINT iMesh ) +{ + return m_pMeshArray[iMesh].BoundingBoxCenter; +} + +//-------------------------------------------------------------------------------------- +D3DXVECTOR3 CDXUTSDKMesh::GetMeshBBoxExtents( UINT iMesh ) +{ + return m_pMeshArray[iMesh].BoundingBoxExtents; +} + +//-------------------------------------------------------------------------------------- +UINT CDXUTSDKMesh::GetOutstandingResources() +{ + UINT outstandingResources = 0; + if( !m_pMeshHeader ) + return 1; + + outstandingResources += GetOutstandingBufferResources(); + + if( m_pDev11 ) + { + for( UINT i = 0; i < m_pMeshHeader->NumMaterials; i++ ) + { + if( m_pMaterialArray[i].DiffuseTexture[0] != 0 ) + { + if( !m_pMaterialArray[i].pDiffuseRV11 && !IsErrorResource( m_pMaterialArray[i].pDiffuseRV11 ) ) + outstandingResources ++; + } + + if( m_pMaterialArray[i].NormalTexture[0] != 0 ) + { + if( !m_pMaterialArray[i].pNormalRV11 && !IsErrorResource( m_pMaterialArray[i].pNormalRV11 ) ) + outstandingResources ++; + } + + if( m_pMaterialArray[i].SpecularTexture[0] != 0 ) + { + if( !m_pMaterialArray[i].pSpecularRV11 && !IsErrorResource( m_pMaterialArray[i].pSpecularRV11 ) ) + outstandingResources ++; + } + } + } + else + { + for( UINT i = 0; i < m_pMeshHeader->NumMaterials; i++ ) + { + if( m_pMaterialArray[i].DiffuseTexture[0] != 0 ) + { + if( !m_pMaterialArray[i].pDiffuseTexture9 && !IsErrorResource( m_pMaterialArray[i].pDiffuseTexture9 ) ) + outstandingResources ++; + } + + if( m_pMaterialArray[i].NormalTexture[0] != 0 ) + { + if( !m_pMaterialArray[i].pNormalTexture9 && !IsErrorResource( m_pMaterialArray[i].pNormalTexture9 ) ) + outstandingResources ++; + } + + if( m_pMaterialArray[i].SpecularTexture[0] != 0 ) + { + if( !m_pMaterialArray[i].pSpecularTexture9 && + !IsErrorResource( m_pMaterialArray[i].pSpecularTexture9 ) ) + outstandingResources ++; + } + } + } + + return outstandingResources; +} + +//-------------------------------------------------------------------------------------- +UINT CDXUTSDKMesh::GetOutstandingBufferResources() +{ + UINT outstandingResources = 0; + if( !m_pMeshHeader ) + return 1; + + for( UINT i = 0; i < m_pMeshHeader->NumVertexBuffers; i++ ) + { + if( !m_pVertexBufferArray[i].pVB9 && !IsErrorResource( m_pVertexBufferArray[i].pVB9 ) ) + outstandingResources ++; + } + + for( UINT i = 0; i < m_pMeshHeader->NumIndexBuffers; i++ ) + { + if( !m_pIndexBufferArray[i].pIB9 && !IsErrorResource( m_pIndexBufferArray[i].pIB9 ) ) + outstandingResources ++; + } + + return outstandingResources; +} + +//-------------------------------------------------------------------------------------- +bool CDXUTSDKMesh::CheckLoadDone() +{ + if( 0 == GetOutstandingResources() ) + { + m_bLoading = false; + return true; + } + + return false; +} + +//-------------------------------------------------------------------------------------- +bool CDXUTSDKMesh::IsLoaded() +{ + if( m_pStaticMeshData && !m_bLoading ) + { + return true; + } + + return false; +} + +//-------------------------------------------------------------------------------------- +bool CDXUTSDKMesh::IsLoading() +{ + return m_bLoading; +} + +//-------------------------------------------------------------------------------------- +void CDXUTSDKMesh::SetLoading( bool bLoading ) +{ + m_bLoading = bLoading; +} + +//-------------------------------------------------------------------------------------- +BOOL CDXUTSDKMesh::HadLoadingError() +{ + if( m_pMeshHeader ) + { + for( UINT i = 0; i < m_pMeshHeader->NumVertexBuffers; i++ ) + { + if( IsErrorResource( m_pVertexBufferArray[i].pVB9 ) ) + return TRUE; + } + + for( UINT i = 0; i < m_pMeshHeader->NumIndexBuffers; i++ ) + { + if( IsErrorResource( m_pIndexBufferArray[i].pIB9 ) ) + return TRUE; + } + } + + return FALSE; +} + +//-------------------------------------------------------------------------------------- +UINT CDXUTSDKMesh::GetNumInfluences( UINT iMesh ) +{ + return m_pMeshArray[iMesh].NumFrameInfluences; +} + +//-------------------------------------------------------------------------------------- +const D3DXMATRIX* CDXUTSDKMesh::GetMeshInfluenceMatrix( UINT iMesh, UINT iInfluence ) +{ + UINT iFrame = m_pMeshArray[iMesh].pFrameInfluences[ iInfluence ]; + return &m_pTransformedFrameMatrices[iFrame]; +} + +const D3DXMATRIX* CDXUTSDKMesh::GetWorldMatrix( UINT iFrameIndex ) +{ + return &m_pWorldPoseFrameMatrices[iFrameIndex]; +} + +const D3DXMATRIX* CDXUTSDKMesh::GetInfluenceMatrix( UINT iFrameIndex ) +{ + return &m_pTransformedFrameMatrices[iFrameIndex]; +} + +//-------------------------------------------------------------------------------------- +UINT CDXUTSDKMesh::GetAnimationKeyFromTime( double fTime ) +{ + if( m_pAnimationHeader == NULL ) + { + return 0; + } + + UINT iTick = ( UINT )( m_pAnimationHeader->AnimationFPS * fTime ); + + iTick = iTick % ( m_pAnimationHeader->NumAnimationKeys - 1 ); + iTick ++; + + return iTick; +} + +bool CDXUTSDKMesh::GetAnimationProperties( UINT* pNumKeys, FLOAT* pFrameTime ) +{ + if( m_pAnimationHeader == NULL ) + { + return false; + } + + *pNumKeys = m_pAnimationHeader->NumAnimationKeys; + *pFrameTime = 1.0f / (FLOAT)m_pAnimationHeader->AnimationFPS; + + return true; +} + + +//------------------------------------------------------------------------------------- +// CDXUTXFileMesh implementation. +//------------------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +CDXUTXFileMesh::CDXUTXFileMesh( LPCWSTR strName ) +{ + wcscpy_s( m_strName, 512, strName ); + m_pMesh = NULL; + m_pMaterials = NULL; + m_pTextures = NULL; + m_bUseMaterials = TRUE; + m_pVB = NULL; + m_pIB = NULL; + m_pDecl = NULL; + m_strMaterials = NULL; + m_dwNumMaterials = 0; + m_dwNumVertices = 0; + m_dwNumFaces = 0; + m_dwBytesPerVertex = 0; +} + + + + +//----------------------------------------------------------------------------- +CDXUTXFileMesh::~CDXUTXFileMesh() +{ + Destroy(); +} + + + + +//----------------------------------------------------------------------------- +HRESULT CDXUTXFileMesh::Create( LPDIRECT3DDEVICE9 pd3dDevice, LPCWSTR strFilename ) +{ + WCHAR strPath[MAX_PATH]; + LPD3DXBUFFER pAdjacencyBuffer = NULL; + LPD3DXBUFFER pMtrlBuffer = NULL; + HRESULT hr; + + // Cleanup previous mesh if any + Destroy(); + + // Find the path for the file, and convert it to ANSI (for the D3DX API) + DXUTFindDXSDKMediaFileCch( strPath, sizeof( strPath ) / sizeof( WCHAR ), strFilename ); + + // Load the mesh + if( FAILED( hr = D3DXLoadMeshFromX( strPath, D3DXMESH_MANAGED, pd3dDevice, + &pAdjacencyBuffer, &pMtrlBuffer, NULL, + &m_dwNumMaterials, &m_pMesh ) ) ) + { + return hr; + } + + // Optimize the mesh for performance + if( FAILED( hr = m_pMesh->OptimizeInplace( + D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, + ( DWORD* )pAdjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL ) ) ) + { + SAFE_RELEASE( pAdjacencyBuffer ); + SAFE_RELEASE( pMtrlBuffer ); + return hr; + } + + // Set strPath to the path of the mesh file + WCHAR* pLastBSlash = wcsrchr( strPath, L'\\' ); + if( pLastBSlash ) + *( pLastBSlash + 1 ) = L'\0'; + else + *strPath = L'\0'; + + D3DXMATERIAL* d3dxMtrls = ( D3DXMATERIAL* )pMtrlBuffer->GetBufferPointer(); + hr = CreateMaterials( strPath, pd3dDevice, d3dxMtrls, m_dwNumMaterials ); + + SAFE_RELEASE( pAdjacencyBuffer ); + SAFE_RELEASE( pMtrlBuffer ); + + // Extract data from m_pMesh for easy access + D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE]; + m_dwNumVertices = m_pMesh->GetNumVertices(); + m_dwNumFaces = m_pMesh->GetNumFaces(); + m_dwBytesPerVertex = m_pMesh->GetNumBytesPerVertex(); + m_pMesh->GetIndexBuffer( &m_pIB ); + m_pMesh->GetVertexBuffer( &m_pVB ); + m_pMesh->GetDeclaration( decl ); + pd3dDevice->CreateVertexDeclaration( decl, &m_pDecl ); + + return hr; +} + + +//----------------------------------------------------------------------------- +HRESULT CDXUTXFileMesh::Create( LPDIRECT3DDEVICE9 pd3dDevice, + LPD3DXFILEDATA pFileData ) +{ + LPD3DXBUFFER pMtrlBuffer = NULL; + LPD3DXBUFFER pAdjacencyBuffer = NULL; + HRESULT hr; + + // Cleanup previous mesh if any + Destroy(); + + // Load the mesh from the DXFILEDATA object + if( FAILED( hr = D3DXLoadMeshFromXof( pFileData, D3DXMESH_MANAGED, pd3dDevice, + &pAdjacencyBuffer, &pMtrlBuffer, NULL, + &m_dwNumMaterials, &m_pMesh ) ) ) + { + return hr; + } + + // Optimize the mesh for performance + if( FAILED( hr = m_pMesh->OptimizeInplace( + D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, + ( DWORD* )pAdjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL ) ) ) + { + SAFE_RELEASE( pAdjacencyBuffer ); + SAFE_RELEASE( pMtrlBuffer ); + return hr; + } + + D3DXMATERIAL* d3dxMtrls = ( D3DXMATERIAL* )pMtrlBuffer->GetBufferPointer(); + hr = CreateMaterials( L"", pd3dDevice, d3dxMtrls, m_dwNumMaterials ); + + SAFE_RELEASE( pAdjacencyBuffer ); + SAFE_RELEASE( pMtrlBuffer ); + + // Extract data from m_pMesh for easy access + D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE]; + m_dwNumVertices = m_pMesh->GetNumVertices(); + m_dwNumFaces = m_pMesh->GetNumFaces(); + m_dwBytesPerVertex = m_pMesh->GetNumBytesPerVertex(); + m_pMesh->GetIndexBuffer( &m_pIB ); + m_pMesh->GetVertexBuffer( &m_pVB ); + m_pMesh->GetDeclaration( decl ); + pd3dDevice->CreateVertexDeclaration( decl, &m_pDecl ); + + return hr; +} + + +//----------------------------------------------------------------------------- +HRESULT CDXUTXFileMesh::Create( LPDIRECT3DDEVICE9 pd3dDevice, ID3DXMesh* pInMesh, + D3DXMATERIAL* pd3dxMaterials, DWORD dwMaterials ) +{ + // Cleanup previous mesh if any + Destroy(); + + // Optimize the mesh for performance + DWORD* rgdwAdjacency = NULL; + rgdwAdjacency = new DWORD[pInMesh->GetNumFaces() * 3]; + if( rgdwAdjacency == NULL ) + return E_OUTOFMEMORY; + pInMesh->GenerateAdjacency( 1e-6f, rgdwAdjacency ); + + D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE]; + pInMesh->GetDeclaration( decl ); + + DWORD dwOptions = pInMesh->GetOptions(); + dwOptions &= ~( D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM | D3DXMESH_WRITEONLY ); + dwOptions |= D3DXMESH_MANAGED; + dwOptions |= D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE; + + ID3DXMesh* pTempMesh = NULL; + if( FAILED( pInMesh->Optimize( dwOptions, rgdwAdjacency, NULL, NULL, NULL, &pTempMesh ) ) ) + { + SAFE_DELETE_ARRAY( rgdwAdjacency ); + return E_FAIL; + } + + SAFE_DELETE_ARRAY( rgdwAdjacency ); + SAFE_RELEASE( m_pMesh ); + m_pMesh = pTempMesh; + + HRESULT hr; + hr = CreateMaterials( L"", pd3dDevice, pd3dxMaterials, dwMaterials ); + + // Extract data from m_pMesh for easy access + m_dwNumVertices = m_pMesh->GetNumVertices(); + m_dwNumFaces = m_pMesh->GetNumFaces(); + m_dwBytesPerVertex = m_pMesh->GetNumBytesPerVertex(); + m_pMesh->GetIndexBuffer( &m_pIB ); + m_pMesh->GetVertexBuffer( &m_pVB ); + m_pMesh->GetDeclaration( decl ); + pd3dDevice->CreateVertexDeclaration( decl, &m_pDecl ); + + return hr; +} + + +//----------------------------------------------------------------------------- +HRESULT CDXUTXFileMesh::CreateMaterials( LPCWSTR strPath, IDirect3DDevice9* pd3dDevice, D3DXMATERIAL* d3dxMtrls, + DWORD dwNumMaterials ) +{ + // Get material info for the mesh + // Get the array of materials out of the buffer + m_dwNumMaterials = dwNumMaterials; + if( d3dxMtrls && m_dwNumMaterials > 0 ) + { + // Allocate memory for the materials and textures + m_pMaterials = new D3DMATERIAL9[m_dwNumMaterials]; + if( m_pMaterials == NULL ) + return E_OUTOFMEMORY; + m_pTextures = new LPDIRECT3DBASETEXTURE9[m_dwNumMaterials]; + if( m_pTextures == NULL ) + return E_OUTOFMEMORY; + m_strMaterials = new CHAR[m_dwNumMaterials][MAX_PATH]; + if( m_strMaterials == NULL ) + return E_OUTOFMEMORY; + + // Copy each material and create its texture + for( DWORD i = 0; i < m_dwNumMaterials; i++ ) + { + // Copy the material + m_pMaterials[i] = d3dxMtrls[i].MatD3D; + m_pTextures[i] = NULL; + + // Create a texture + if( d3dxMtrls[i].pTextureFilename ) + { + strcpy_s( m_strMaterials[i], MAX_PATH, d3dxMtrls[i].pTextureFilename ); + + WCHAR strTexture[MAX_PATH]; + WCHAR strTextureTemp[MAX_PATH]; + D3DXIMAGE_INFO ImgInfo; + + // First attempt to look for texture in the same folder as the input folder. + MultiByteToWideChar( CP_ACP, 0, d3dxMtrls[i].pTextureFilename, -1, strTextureTemp, MAX_PATH ); + strTextureTemp[MAX_PATH - 1] = 0; + + wcscpy_s( strTexture, MAX_PATH, strPath ); + wcscat_s( strTexture, MAX_PATH, strTextureTemp ); + + // Inspect the texture file to determine the texture type. + if( FAILED( D3DXGetImageInfoFromFile( strTexture, &ImgInfo ) ) ) + { + // Search the media folder + if( FAILED( DXUTFindDXSDKMediaFileCch( strTexture, MAX_PATH, strTextureTemp ) ) ) + continue; // Can't find. Skip. + + D3DXGetImageInfoFromFile( strTexture, &ImgInfo ); + } + + // Call the appropriate loader according to the texture type. + switch( ImgInfo.ResourceType ) + { + case D3DRTYPE_TEXTURE: + { + IDirect3DTexture9* pTex; + if( SUCCEEDED( D3DXCreateTextureFromFile( pd3dDevice, strTexture, &pTex ) ) ) + { + // Obtain the base texture interface + pTex->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&m_pTextures[i] ); + // Release the specialized instance + pTex->Release(); + } + break; + } + case D3DRTYPE_CUBETEXTURE: + { + IDirect3DCubeTexture9* pTex; + if( SUCCEEDED( D3DXCreateCubeTextureFromFile( pd3dDevice, strTexture, &pTex ) ) ) + { + // Obtain the base texture interface + pTex->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&m_pTextures[i] ); + // Release the specialized instance + pTex->Release(); + } + break; + } + case D3DRTYPE_VOLUMETEXTURE: + { + IDirect3DVolumeTexture9* pTex; + if( SUCCEEDED( D3DXCreateVolumeTextureFromFile( pd3dDevice, strTexture, &pTex ) ) ) + { + // Obtain the base texture interface + pTex->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&m_pTextures[i] ); + // Release the specialized instance + pTex->Release(); + } + break; + } + } + } + } + } + return S_OK; +} + + +//----------------------------------------------------------------------------- +HRESULT CDXUTXFileMesh::SetFVF( LPDIRECT3DDEVICE9 pd3dDevice, DWORD dwFVF ) +{ + LPD3DXMESH pTempMesh = NULL; + + if( m_pMesh ) + { + if( FAILED( m_pMesh->CloneMeshFVF( m_pMesh->GetOptions(), dwFVF, + pd3dDevice, &pTempMesh ) ) ) + { + SAFE_RELEASE( pTempMesh ); + return E_FAIL; + } + + DWORD dwOldFVF = 0; + dwOldFVF = m_pMesh->GetFVF(); + SAFE_RELEASE( m_pMesh ); + m_pMesh = pTempMesh; + + // Compute normals if they are being requested and + // the old mesh does not have them. + if( !( dwOldFVF & D3DFVF_NORMAL ) && dwFVF & D3DFVF_NORMAL ) + { + D3DXComputeNormals( m_pMesh, NULL ); + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Convert the mesh to the format specified by the given vertex declarations. +//----------------------------------------------------------------------------- +HRESULT CDXUTXFileMesh::SetVertexDecl( LPDIRECT3DDEVICE9 pd3dDevice, const D3DVERTEXELEMENT9* pDecl, + bool bAutoComputeNormals, bool bAutoComputeTangents, + bool bSplitVertexForOptimalTangents ) +{ + LPD3DXMESH pTempMesh = NULL; + + if( m_pMesh ) + { + if( FAILED( m_pMesh->CloneMesh( m_pMesh->GetOptions(), pDecl, + pd3dDevice, &pTempMesh ) ) ) + { + SAFE_RELEASE( pTempMesh ); + return E_FAIL; + } + } + + + // Check if the old declaration contains a normal. + bool bHadNormal = false; + bool bHadTangent = false; + D3DVERTEXELEMENT9 aOldDecl[MAX_FVF_DECL_SIZE]; + if( m_pMesh && SUCCEEDED( m_pMesh->GetDeclaration( aOldDecl ) ) ) + { + for( UINT index = 0; index < D3DXGetDeclLength( aOldDecl ); ++index ) + { + if( aOldDecl[index].Usage == D3DDECLUSAGE_NORMAL ) + { + bHadNormal = true; + } + if( aOldDecl[index].Usage == D3DDECLUSAGE_TANGENT ) + { + bHadTangent = true; + } + } + } + + // Check if the new declaration contains a normal. + bool bHaveNormalNow = false; + bool bHaveTangentNow = false; + D3DVERTEXELEMENT9 aNewDecl[MAX_FVF_DECL_SIZE]; + if( pTempMesh && SUCCEEDED( pTempMesh->GetDeclaration( aNewDecl ) ) ) + { + for( UINT index = 0; index < D3DXGetDeclLength( aNewDecl ); ++index ) + { + if( aNewDecl[index].Usage == D3DDECLUSAGE_NORMAL ) + { + bHaveNormalNow = true; + } + if( aNewDecl[index].Usage == D3DDECLUSAGE_TANGENT ) + { + bHaveTangentNow = true; + } + } + } + + SAFE_RELEASE( m_pMesh ); + + if( pTempMesh ) + { + m_pMesh = pTempMesh; + + if( !bHadNormal && bHaveNormalNow && bAutoComputeNormals ) + { + // Compute normals in case the meshes have them + D3DXComputeNormals( m_pMesh, NULL ); + } + + if( bHaveNormalNow && !bHadTangent && bHaveTangentNow && bAutoComputeTangents ) + { + ID3DXMesh* pNewMesh; + HRESULT hr; + + DWORD* rgdwAdjacency = NULL; + rgdwAdjacency = new DWORD[m_pMesh->GetNumFaces() * 3]; + if( rgdwAdjacency == NULL ) + return E_OUTOFMEMORY; + V( m_pMesh->GenerateAdjacency( 1e-6f, rgdwAdjacency ) ); + + float fPartialEdgeThreshold; + float fSingularPointThreshold; + float fNormalEdgeThreshold; + if( bSplitVertexForOptimalTangents ) + { + fPartialEdgeThreshold = 0.01f; + fSingularPointThreshold = 0.25f; + fNormalEdgeThreshold = 0.01f; + } + else + { + fPartialEdgeThreshold = -1.01f; + fSingularPointThreshold = 0.01f; + fNormalEdgeThreshold = -1.01f; + } + + // Compute tangents, which are required for normal mapping + hr = D3DXComputeTangentFrameEx( m_pMesh, + D3DDECLUSAGE_TEXCOORD, 0, + D3DDECLUSAGE_TANGENT, 0, + D3DX_DEFAULT, 0, + D3DDECLUSAGE_NORMAL, 0, + 0, rgdwAdjacency, + fPartialEdgeThreshold, fSingularPointThreshold, fNormalEdgeThreshold, + &pNewMesh, NULL ); + + SAFE_DELETE_ARRAY( rgdwAdjacency ); + if( FAILED( hr ) ) + return hr; + + SAFE_RELEASE( m_pMesh ); + m_pMesh = pNewMesh; + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +HRESULT CDXUTXFileMesh::RestoreDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice ) +{ + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +HRESULT CDXUTXFileMesh::InvalidateDeviceObjects() +{ + SAFE_RELEASE( m_pIB ); + SAFE_RELEASE( m_pVB ); + SAFE_RELEASE( m_pDecl ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +HRESULT CDXUTXFileMesh::Destroy() +{ + InvalidateDeviceObjects(); + for( UINT i = 0; i < m_dwNumMaterials; i++ ) + SAFE_RELEASE( m_pTextures[i] ); + SAFE_DELETE_ARRAY( m_pTextures ); + SAFE_DELETE_ARRAY( m_pMaterials ); + SAFE_DELETE_ARRAY( m_strMaterials ); + + SAFE_RELEASE( m_pMesh ); + + m_dwNumMaterials = 0L; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +HRESULT CDXUTXFileMesh::Render( LPDIRECT3DDEVICE9 pd3dDevice, bool bDrawOpaqueSubsets, + bool bDrawAlphaSubsets ) +{ + if( NULL == m_pMesh ) + return E_FAIL; + + // Frist, draw the subsets without alpha + if( bDrawOpaqueSubsets ) + { + for( DWORD i = 0; i < m_dwNumMaterials; i++ ) + { + if( m_bUseMaterials ) + { + if( m_pMaterials[i].Diffuse.a < 1.0f ) + continue; + pd3dDevice->SetMaterial( &m_pMaterials[i] ); + pd3dDevice->SetTexture( 0, m_pTextures[i] ); + } + m_pMesh->DrawSubset( i ); + } + } + + // Then, draw the subsets with alpha + if( bDrawAlphaSubsets && m_bUseMaterials ) + { + for( DWORD i = 0; i < m_dwNumMaterials; i++ ) + { + if( m_pMaterials[i].Diffuse.a == 1.0f ) + continue; + + // Set the material and texture + pd3dDevice->SetMaterial( &m_pMaterials[i] ); + pd3dDevice->SetTexture( 0, m_pTextures[i] ); + m_pMesh->DrawSubset( i ); + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +HRESULT CDXUTXFileMesh::Render( ID3DXEffect* pEffect, + D3DXHANDLE hTexture, + D3DXHANDLE hDiffuse, + D3DXHANDLE hAmbient, + D3DXHANDLE hSpecular, + D3DXHANDLE hEmissive, + D3DXHANDLE hPower, + bool bDrawOpaqueSubsets, + bool bDrawAlphaSubsets ) +{ + if( NULL == m_pMesh ) + return E_FAIL; + + UINT cPasses; + // Frist, draw the subsets without alpha + if( bDrawOpaqueSubsets ) + { + pEffect->Begin( &cPasses, 0 ); + for( UINT p = 0; p < cPasses; ++p ) + { + pEffect->BeginPass( p ); + for( DWORD i = 0; i < m_dwNumMaterials; i++ ) + { + if( m_bUseMaterials ) + { + if( m_pMaterials[i].Diffuse.a < 1.0f ) + continue; + if( hTexture ) + pEffect->SetTexture( hTexture, m_pTextures[i] ); + // D3DCOLORVALUE and D3DXVECTOR4 are data-wise identical. + // No conversion is needed. + if( hDiffuse ) + pEffect->SetVector( hDiffuse, ( D3DXVECTOR4* )&m_pMaterials[i].Diffuse ); + if( hAmbient ) + pEffect->SetVector( hAmbient, ( D3DXVECTOR4* )&m_pMaterials[i].Ambient ); + if( hSpecular ) + pEffect->SetVector( hSpecular, ( D3DXVECTOR4* )&m_pMaterials[i].Specular ); + if( hEmissive ) + pEffect->SetVector( hEmissive, ( D3DXVECTOR4* )&m_pMaterials[i].Emissive ); + if( hPower ) + pEffect->SetFloat( hPower, m_pMaterials[i].Power ); + pEffect->CommitChanges(); + } + m_pMesh->DrawSubset( i ); + } + pEffect->EndPass(); + } + pEffect->End(); + } + + // Then, draw the subsets with alpha + if( bDrawAlphaSubsets && m_bUseMaterials ) + { + pEffect->Begin( &cPasses, 0 ); + for( UINT p = 0; p < cPasses; ++p ) + { + pEffect->BeginPass( p ); + for( DWORD i = 0; i < m_dwNumMaterials; i++ ) + { + if( m_bUseMaterials ) + { + if( m_pMaterials[i].Diffuse.a == 1.0f ) + continue; + if( hTexture ) + pEffect->SetTexture( hTexture, m_pTextures[i] ); + // D3DCOLORVALUE and D3DXVECTOR4 are data-wise identical. + // No conversion is needed. + if( hDiffuse ) + pEffect->SetVector( hDiffuse, ( D3DXVECTOR4* )&m_pMaterials[i].Diffuse ); + if( hAmbient ) + pEffect->SetVector( hAmbient, ( D3DXVECTOR4* )&m_pMaterials[i].Ambient ); + if( hSpecular ) + pEffect->SetVector( hSpecular, ( D3DXVECTOR4* )&m_pMaterials[i].Specular ); + if( hEmissive ) + pEffect->SetVector( hEmissive, ( D3DXVECTOR4* )&m_pMaterials[i].Emissive ); + if( hPower ) + pEffect->SetFloat( hPower, m_pMaterials[i].Power ); + pEffect->CommitChanges(); + } + m_pMesh->DrawSubset( i ); + } + pEffect->EndPass(); + } + pEffect->End(); + } + + return S_OK; +} diff --git a/Demos/DX11ClothDemo/DXUT/Optional/SDKmesh.h b/Demos/DX11ClothDemo/DXUT/Optional/SDKmesh.h new file mode 100644 index 0000000..79a41d0 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/SDKmesh.h @@ -0,0 +1,589 @@ +//-------------------------------------------------------------------------------------- +// File: SDKMesh.h +// +// Disclaimer: +// The SDK Mesh format (.sdkmesh) is not a recommended file format for shipping titles. +// It was designed to meet the specific needs of the SDK samples. Any real-world +// applications should avoid this file format in favor of a destination format that +// meets the specific needs of the application. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +#pragma once +#ifndef _SDKMESH_ +#define _SDKMESH_ + +//-------------------------------------------------------------------------------------- +// Hard Defines for the various structures +//-------------------------------------------------------------------------------------- +#define SDKMESH_FILE_VERSION 101 +#define MAX_VERTEX_ELEMENTS 32 +#define MAX_VERTEX_STREAMS 16 +#define MAX_FRAME_NAME 100 +#define MAX_MESH_NAME 100 +#define MAX_SUBSET_NAME 100 +#define MAX_MATERIAL_NAME 100 +#define MAX_TEXTURE_NAME MAX_PATH +#define MAX_MATERIAL_PATH MAX_PATH +#define INVALID_FRAME ((UINT)-1) +#define INVALID_MESH ((UINT)-1) +#define INVALID_MATERIAL ((UINT)-1) +#define INVALID_SUBSET ((UINT)-1) +#define INVALID_ANIMATION_DATA ((UINT)-1) +#define INVALID_SAMPLER_SLOT ((UINT)-1) +#define ERROR_RESOURCE_VALUE 1 + +template BOOL IsErrorResource( TYPE data ) +{ + if( ( TYPE )ERROR_RESOURCE_VALUE == data ) + return TRUE; + return FALSE; +} +//-------------------------------------------------------------------------------------- +// Enumerated Types. These will have mirrors in both D3D9 and D3D11 +//-------------------------------------------------------------------------------------- +enum SDKMESH_PRIMITIVE_TYPE +{ + PT_TRIANGLE_LIST = 0, + PT_TRIANGLE_STRIP, + PT_LINE_LIST, + PT_LINE_STRIP, + PT_POINT_LIST, + PT_TRIANGLE_LIST_ADJ, + PT_TRIANGLE_STRIP_ADJ, + PT_LINE_LIST_ADJ, + PT_LINE_STRIP_ADJ, + PT_QUAD_PATCH_LIST, + PT_TRIANGLE_PATCH_LIST, +}; + +enum SDKMESH_INDEX_TYPE +{ + IT_16BIT = 0, + IT_32BIT, +}; + +enum FRAME_TRANSFORM_TYPE +{ + FTT_RELATIVE = 0, + FTT_ABSOLUTE, //This is not currently used but is here to support absolute transformations in the future +}; + +//-------------------------------------------------------------------------------------- +// Structures. Unions with pointers are forced to 64bit. +//-------------------------------------------------------------------------------------- +struct SDKMESH_HEADER +{ + //Basic Info and sizes + UINT Version; + BYTE IsBigEndian; + UINT64 HeaderSize; + UINT64 NonBufferDataSize; + UINT64 BufferDataSize; + + //Stats + UINT NumVertexBuffers; + UINT NumIndexBuffers; + UINT NumMeshes; + UINT NumTotalSubsets; + UINT NumFrames; + UINT NumMaterials; + + //Offsets to Data + UINT64 VertexStreamHeadersOffset; + UINT64 IndexStreamHeadersOffset; + UINT64 MeshDataOffset; + UINT64 SubsetDataOffset; + UINT64 FrameDataOffset; + UINT64 MaterialDataOffset; +}; + +struct SDKMESH_VERTEX_BUFFER_HEADER +{ + UINT64 NumVertices; + UINT64 SizeBytes; + UINT64 StrideBytes; + D3DVERTEXELEMENT9 Decl[MAX_VERTEX_ELEMENTS]; + union + { + UINT64 DataOffset; //(This also forces the union to 64bits) + IDirect3DVertexBuffer9* pVB9; + ID3D11Buffer* pVB11; + }; +}; + +struct SDKMESH_INDEX_BUFFER_HEADER +{ + UINT64 NumIndices; + UINT64 SizeBytes; + UINT IndexType; + union + { + UINT64 DataOffset; //(This also forces the union to 64bits) + IDirect3DIndexBuffer9* pIB9; + ID3D11Buffer* pIB11; + }; +}; + +struct SDKMESH_MESH +{ + char Name[MAX_MESH_NAME]; + BYTE NumVertexBuffers; + UINT VertexBuffers[MAX_VERTEX_STREAMS]; + UINT IndexBuffer; + UINT NumSubsets; + UINT NumFrameInfluences; //aka bones + + D3DXVECTOR3 BoundingBoxCenter; + D3DXVECTOR3 BoundingBoxExtents; + + union + { + UINT64 SubsetOffset; //Offset to list of subsets (This also forces the union to 64bits) + UINT* pSubsets; //Pointer to list of subsets + }; + union + { + UINT64 FrameInfluenceOffset; //Offset to list of frame influences (This also forces the union to 64bits) + UINT* pFrameInfluences; //Pointer to list of frame influences + }; +}; + +struct SDKMESH_SUBSET +{ + char Name[MAX_SUBSET_NAME]; + UINT MaterialID; + UINT PrimitiveType; + UINT64 IndexStart; + UINT64 IndexCount; + UINT64 VertexStart; + UINT64 VertexCount; +}; + +struct SDKMESH_FRAME +{ + char Name[MAX_FRAME_NAME]; + UINT Mesh; + UINT ParentFrame; + UINT ChildFrame; + UINT SiblingFrame; + D3DXMATRIX Matrix; + UINT AnimationDataIndex; //Used to index which set of keyframes transforms this frame +}; + +struct SDKMESH_MATERIAL +{ + char Name[MAX_MATERIAL_NAME]; + + // Use MaterialInstancePath + char MaterialInstancePath[MAX_MATERIAL_PATH]; + + // Or fall back to d3d8-type materials + char DiffuseTexture[MAX_TEXTURE_NAME]; + char NormalTexture[MAX_TEXTURE_NAME]; + char SpecularTexture[MAX_TEXTURE_NAME]; + + D3DXVECTOR4 Diffuse; + D3DXVECTOR4 Ambient; + D3DXVECTOR4 Specular; + D3DXVECTOR4 Emissive; + FLOAT Power; + + union + { + UINT64 Force64_1; //Force the union to 64bits + IDirect3DTexture9* pDiffuseTexture9; + ID3D11Texture2D* pDiffuseTexture11; + }; + union + { + UINT64 Force64_2; //Force the union to 64bits + IDirect3DTexture9* pNormalTexture9; + ID3D11Texture2D* pNormalTexture11; + }; + union + { + UINT64 Force64_3; //Force the union to 64bits + IDirect3DTexture9* pSpecularTexture9; + ID3D11Texture2D* pSpecularTexture11; + }; + + union + { + UINT64 Force64_4; //Force the union to 64bits + ID3D11ShaderResourceView* pDiffuseRV11; + }; + union + { + UINT64 Force64_5; //Force the union to 64bits + ID3D11ShaderResourceView* pNormalRV11; + }; + union + { + UINT64 Force64_6; //Force the union to 64bits + ID3D11ShaderResourceView* pSpecularRV11; + }; + +}; + +struct SDKANIMATION_FILE_HEADER +{ + UINT Version; + BYTE IsBigEndian; + UINT FrameTransformType; + UINT NumFrames; + UINT NumAnimationKeys; + UINT AnimationFPS; + UINT64 AnimationDataSize; + UINT64 AnimationDataOffset; +}; + +struct SDKANIMATION_DATA +{ + D3DXVECTOR3 Translation; + D3DXVECTOR4 Orientation; + D3DXVECTOR3 Scaling; +}; + +struct SDKANIMATION_FRAME_DATA +{ + char FrameName[MAX_FRAME_NAME]; + union + { + UINT64 DataOffset; + SDKANIMATION_DATA* pAnimationData; + }; +}; + +#ifndef _CONVERTER_APP_ + +//-------------------------------------------------------------------------------------- +// AsyncLoading callbacks +//-------------------------------------------------------------------------------------- +typedef void ( CALLBACK*LPCREATETEXTUREFROMFILE9 )( IDirect3DDevice9* pDev, char* szFileName, + IDirect3DTexture9** ppTexture, void* pContext ); +typedef void ( CALLBACK*LPCREATEVERTEXBUFFER9 )( IDirect3DDevice9* pDev, IDirect3DVertexBuffer9** ppBuffer, + UINT iSizeBytes, DWORD Usage, DWORD FVF, D3DPOOL Pool, void* pData, + void* pContext ); +typedef void ( CALLBACK*LPCREATEINDEXBUFFER9 )( IDirect3DDevice9* pDev, IDirect3DIndexBuffer9** ppBuffer, + UINT iSizeBytes, DWORD Usage, D3DFORMAT ibFormat, D3DPOOL Pool, + void* pData, void* pContext ); +struct SDKMESH_CALLBACKS9 +{ + LPCREATETEXTUREFROMFILE9 pCreateTextureFromFile; + LPCREATEVERTEXBUFFER9 pCreateVertexBuffer; + LPCREATEINDEXBUFFER9 pCreateIndexBuffer; + void* pContext; +}; + + +typedef void ( CALLBACK*LPCREATETEXTUREFROMFILE11 )( ID3D11Device* pDev, char* szFileName, + ID3D11ShaderResourceView** ppRV, void* pContext ); +typedef void ( CALLBACK*LPCREATEVERTEXBUFFER11 )( ID3D11Device* pDev, ID3D11Buffer** ppBuffer, + D3D11_BUFFER_DESC BufferDesc, void* pData, void* pContext ); +typedef void ( CALLBACK*LPCREATEINDEXBUFFER11 )( ID3D11Device* pDev, ID3D11Buffer** ppBuffer, + D3D11_BUFFER_DESC BufferDesc, void* pData, void* pContext ); +struct SDKMESH_CALLBACKS11 +{ + LPCREATETEXTUREFROMFILE11 pCreateTextureFromFile; + LPCREATEVERTEXBUFFER11 pCreateVertexBuffer; + LPCREATEINDEXBUFFER11 pCreateIndexBuffer; + void* pContext; +}; + +//-------------------------------------------------------------------------------------- +// CDXUTSDKMesh class. This class reads the sdkmesh file format for use by the samples +//-------------------------------------------------------------------------------------- +class CDXUTSDKMesh +{ +private: + UINT m_NumOutstandingResources; + bool m_bLoading; + //BYTE* m_pBufferData; + HANDLE m_hFile; + HANDLE m_hFileMappingObject; + CGrowableArray m_MappedPointers; + IDirect3DDevice9* m_pDev9; + ID3D11Device* m_pDev11; + ID3D11DeviceContext* m_pDevContext11; + +protected: + //These are the pointers to the two chunks of data loaded in from the mesh file + BYTE* m_pStaticMeshData; + BYTE* m_pHeapData; + BYTE* m_pAnimationData; + BYTE** m_ppVertices; + BYTE** m_ppIndices; + + //Keep track of the path + WCHAR m_strPathW[MAX_PATH]; + char m_strPath[MAX_PATH]; + + //General mesh info + SDKMESH_HEADER* m_pMeshHeader; + SDKMESH_VERTEX_BUFFER_HEADER* m_pVertexBufferArray; + SDKMESH_INDEX_BUFFER_HEADER* m_pIndexBufferArray; + SDKMESH_MESH* m_pMeshArray; + SDKMESH_SUBSET* m_pSubsetArray; + SDKMESH_FRAME* m_pFrameArray; + SDKMESH_MATERIAL* m_pMaterialArray; + + // Adjacency information (not part of the m_pStaticMeshData, so it must be created and destroyed separately ) + SDKMESH_INDEX_BUFFER_HEADER* m_pAdjacencyIndexBufferArray; + + //Animation (TODO: Add ability to load/track multiple animation sets) + SDKANIMATION_FILE_HEADER* m_pAnimationHeader; + SDKANIMATION_FRAME_DATA* m_pAnimationFrameData; + D3DXMATRIX* m_pBindPoseFrameMatrices; + D3DXMATRIX* m_pTransformedFrameMatrices; + D3DXMATRIX* m_pWorldPoseFrameMatrices; + +protected: + void LoadMaterials( ID3D11Device* pd3dDevice, SDKMESH_MATERIAL* pMaterials, + UINT NumMaterials, SDKMESH_CALLBACKS11* pLoaderCallbacks=NULL ); + + void LoadMaterials( IDirect3DDevice9* pd3dDevice, SDKMESH_MATERIAL* pMaterials, + UINT NumMaterials, SDKMESH_CALLBACKS9* pLoaderCallbacks=NULL ); + + HRESULT CreateVertexBuffer( ID3D11Device* pd3dDevice, + SDKMESH_VERTEX_BUFFER_HEADER* pHeader, void* pVertices, + SDKMESH_CALLBACKS11* pLoaderCallbacks=NULL ); + HRESULT CreateVertexBuffer( IDirect3DDevice9* pd3dDevice, + SDKMESH_VERTEX_BUFFER_HEADER* pHeader, void* pVertices, + SDKMESH_CALLBACKS9* pLoaderCallbacks=NULL ); + + HRESULT CreateIndexBuffer( ID3D11Device* pd3dDevice, SDKMESH_INDEX_BUFFER_HEADER* pHeader, + void* pIndices, SDKMESH_CALLBACKS11* pLoaderCallbacks=NULL ); + HRESULT CreateIndexBuffer( IDirect3DDevice9* pd3dDevice, + SDKMESH_INDEX_BUFFER_HEADER* pHeader, void* pIndices, + SDKMESH_CALLBACKS9* pLoaderCallbacks=NULL ); + + virtual HRESULT CreateFromFile( ID3D11Device* pDev11, + IDirect3DDevice9* pDev9, + LPCTSTR szFileName, + bool bCreateAdjacencyIndices, + SDKMESH_CALLBACKS11* pLoaderCallbacks11 = NULL, + SDKMESH_CALLBACKS9* pLoaderCallbacks9 = NULL ); + + virtual HRESULT CreateFromMemory( ID3D11Device* pDev11, + IDirect3DDevice9* pDev9, + BYTE* pData, + UINT DataBytes, + bool bCreateAdjacencyIndices, + bool bCopyStatic, + SDKMESH_CALLBACKS11* pLoaderCallbacks11 = NULL, + SDKMESH_CALLBACKS9* pLoaderCallbacks9 = NULL ); + + //frame manipulation + void TransformBindPoseFrame( UINT iFrame, D3DXMATRIX* pParentWorld ); + void TransformFrame( UINT iFrame, D3DXMATRIX* pParentWorld, double fTime ); + void TransformFrameAbsolute( UINT iFrame, double fTime ); + + //Direct3D 11 rendering helpers + void RenderMesh( UINT iMesh, + bool bAdjacent, + ID3D11DeviceContext* pd3dDeviceContext, + UINT iDiffuseSlot, + UINT iNormalSlot, + UINT iSpecularSlot ); + void RenderFrame( UINT iFrame, + bool bAdjacent, + ID3D11DeviceContext* pd3dDeviceContext, + UINT iDiffuseSlot, + UINT iNormalSlot, + UINT iSpecularSlot ); + + + //Direct3D 9 rendering helpers + void RenderMesh( UINT iMesh, + LPDIRECT3DDEVICE9 pd3dDevice, + LPD3DXEFFECT pEffect, + D3DXHANDLE hTechnique, + D3DXHANDLE htxDiffuse, + D3DXHANDLE htxNormal, + D3DXHANDLE htxSpecular ); + void RenderFrame( UINT iFrame, + LPDIRECT3DDEVICE9 pd3dDevice, + LPD3DXEFFECT pEffect, + D3DXHANDLE hTechnique, + D3DXHANDLE htxDiffuse, + D3DXHANDLE htxNormal, + D3DXHANDLE htxSpecular ); + +public: + CDXUTSDKMesh(); + virtual ~CDXUTSDKMesh(); + + virtual HRESULT Create( ID3D11Device* pDev11, LPCTSTR szFileName, bool bCreateAdjacencyIndices= + false, SDKMESH_CALLBACKS11* pLoaderCallbacks=NULL ); + virtual HRESULT Create( IDirect3DDevice9* pDev9, LPCTSTR szFileName, bool bCreateAdjacencyIndices= + false, SDKMESH_CALLBACKS9* pLoaderCallbacks=NULL ); + virtual HRESULT Create( ID3D11Device* pDev11, BYTE* pData, UINT DataBytes, + bool bCreateAdjacencyIndices=false, bool bCopyStatic=false, + SDKMESH_CALLBACKS11* pLoaderCallbacks=NULL ); + virtual HRESULT Create( IDirect3DDevice9* pDev9, BYTE* pData, UINT DataBytes, + bool bCreateAdjacencyIndices=false, bool bCopyStatic=false, + SDKMESH_CALLBACKS9* pLoaderCallbacks=NULL ); + virtual HRESULT LoadAnimation( WCHAR* szFileName ); + virtual void Destroy(); + + //Frame manipulation + void TransformBindPose( D3DXMATRIX* pWorld ); + void TransformMesh( D3DXMATRIX* pWorld, double fTime ); + + + //Direct3D 11 Rendering + virtual void Render( ID3D11DeviceContext* pd3dDeviceContext, + UINT iDiffuseSlot = INVALID_SAMPLER_SLOT, + UINT iNormalSlot = INVALID_SAMPLER_SLOT, + UINT iSpecularSlot = INVALID_SAMPLER_SLOT ); + virtual void RenderAdjacent( ID3D11DeviceContext* pd3dDeviceContext, + UINT iDiffuseSlot = INVALID_SAMPLER_SLOT, + UINT iNormalSlot = INVALID_SAMPLER_SLOT, + UINT iSpecularSlot = INVALID_SAMPLER_SLOT ); + + //Direct3D 9 Rendering + virtual void Render( LPDIRECT3DDEVICE9 pd3dDevice, + LPD3DXEFFECT pEffect, + D3DXHANDLE hTechnique, + D3DXHANDLE htxDiffuse = 0, + D3DXHANDLE htxNormal = 0, + D3DXHANDLE htxSpecular = 0 ); + + //Helpers (D3D11 specific) + static D3D11_PRIMITIVE_TOPOLOGY GetPrimitiveType11( SDKMESH_PRIMITIVE_TYPE PrimType ); + DXGI_FORMAT GetIBFormat11( UINT iMesh ); + ID3D11Buffer* GetVB11( UINT iMesh, UINT iVB ); + ID3D11Buffer* GetIB11( UINT iMesh ); + SDKMESH_INDEX_TYPE GetIndexType( UINT iMesh ); + + ID3D11Buffer* GetAdjIB11( UINT iMesh ); + + //Helpers (D3D9 specific) + static D3DPRIMITIVETYPE GetPrimitiveType9( SDKMESH_PRIMITIVE_TYPE PrimType ); + D3DFORMAT GetIBFormat9( UINT iMesh ); + IDirect3DVertexBuffer9* GetVB9( UINT iMesh, UINT iVB ); + IDirect3DIndexBuffer9* GetIB9( UINT iMesh ); + + //Helpers (general) + char* GetMeshPathA(); + WCHAR* GetMeshPathW(); + UINT GetNumMeshes(); + UINT GetNumMaterials(); + UINT GetNumVBs(); + UINT GetNumIBs(); + + ID3D11Buffer* GetVB11At( UINT iVB ); + ID3D11Buffer* GetIB11At( UINT iIB ); + + IDirect3DVertexBuffer9* GetVB9At( UINT iVB ); + IDirect3DIndexBuffer9* GetIB9At( UINT iIB ); + + BYTE* GetRawVerticesAt( UINT iVB ); + BYTE* GetRawIndicesAt( UINT iIB ); + SDKMESH_MATERIAL* GetMaterial( UINT iMaterial ); + SDKMESH_MESH* GetMesh( UINT iMesh ); + UINT GetNumSubsets( UINT iMesh ); + SDKMESH_SUBSET* GetSubset( UINT iMesh, UINT iSubset ); + UINT GetVertexStride( UINT iMesh, UINT iVB ); + UINT GetNumFrames(); + SDKMESH_FRAME* GetFrame( UINT iFrame ); + SDKMESH_FRAME* FindFrame( char* pszName ); + UINT64 GetNumVertices( UINT iMesh, UINT iVB ); + UINT64 GetNumIndices( UINT iMesh ); + D3DXVECTOR3 GetMeshBBoxCenter( UINT iMesh ); + D3DXVECTOR3 GetMeshBBoxExtents( UINT iMesh ); + UINT GetOutstandingResources(); + UINT GetOutstandingBufferResources(); + bool CheckLoadDone(); + bool IsLoaded(); + bool IsLoading(); + void SetLoading( bool bLoading ); + BOOL HadLoadingError(); + + //Animation + UINT GetNumInfluences( UINT iMesh ); + const D3DXMATRIX* GetMeshInfluenceMatrix( UINT iMesh, UINT iInfluence ); + UINT GetAnimationKeyFromTime( double fTime ); + const D3DXMATRIX* GetWorldMatrix( UINT iFrameIndex ); + const D3DXMATRIX* GetInfluenceMatrix( UINT iFrameIndex ); + bool GetAnimationProperties( UINT* pNumKeys, FLOAT* pFrameTime ); +}; + +//----------------------------------------------------------------------------- +// Name: class CDXUTXFileMesh +// Desc: Class for loading and rendering file-based meshes +//----------------------------------------------------------------------------- +class CDXUTXFileMesh +{ +public: + WCHAR m_strName[512]; + LPD3DXMESH m_pMesh; // Managed mesh + + // Cache of data in m_pMesh for easy access + IDirect3DVertexBuffer9* m_pVB; + IDirect3DIndexBuffer9* m_pIB; + IDirect3DVertexDeclaration9* m_pDecl; + DWORD m_dwNumVertices; + DWORD m_dwNumFaces; + DWORD m_dwBytesPerVertex; + + DWORD m_dwNumMaterials; // Materials for the mesh + D3DMATERIAL9* m_pMaterials; + CHAR (*m_strMaterials )[MAX_PATH]; + IDirect3DBaseTexture9** m_pTextures; + bool m_bUseMaterials; + +public: + // Rendering + HRESULT Render( LPDIRECT3DDEVICE9 pd3dDevice, + bool bDrawOpaqueSubsets = true, + bool bDrawAlphaSubsets = true ); + HRESULT Render( ID3DXEffect* pEffect, + D3DXHANDLE hTexture = NULL, + D3DXHANDLE hDiffuse = NULL, + D3DXHANDLE hAmbient = NULL, + D3DXHANDLE hSpecular = NULL, + D3DXHANDLE hEmissive = NULL, + D3DXHANDLE hPower = NULL, + bool bDrawOpaqueSubsets = true, + bool bDrawAlphaSubsets = true ); + + // Mesh access + LPD3DXMESH GetMesh() + { + return m_pMesh; + } + + // Rendering options + void UseMeshMaterials( bool bFlag ) + { + m_bUseMaterials = bFlag; + } + HRESULT SetFVF( LPDIRECT3DDEVICE9 pd3dDevice, DWORD dwFVF ); + HRESULT SetVertexDecl( LPDIRECT3DDEVICE9 pd3dDevice, const D3DVERTEXELEMENT9* pDecl, + bool bAutoComputeNormals = true, bool bAutoComputeTangents = true, + bool bSplitVertexForOptimalTangents = false ); + + // Initializing + HRESULT RestoreDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice ); + HRESULT InvalidateDeviceObjects(); + + // Creation/destruction + HRESULT Create( LPDIRECT3DDEVICE9 pd3dDevice, LPCWSTR strFilename ); + HRESULT Create( LPDIRECT3DDEVICE9 pd3dDevice, LPD3DXFILEDATA pFileData ); + HRESULT Create( LPDIRECT3DDEVICE9 pd3dDevice, ID3DXMesh* pInMesh, D3DXMATERIAL* pd3dxMaterials, + DWORD dwMaterials ); + HRESULT CreateMaterials( LPCWSTR strPath, IDirect3DDevice9* pd3dDevice, D3DXMATERIAL* d3dxMtrls, + DWORD dwNumMaterials ); + HRESULT Destroy(); + + CDXUTXFileMesh( LPCWSTR strName = L"CDXUTXMeshFile_Mesh" ); + virtual ~CDXUTXFileMesh(); +}; + + +#endif + +#endif + diff --git a/Demos/DX11ClothDemo/DXUT/Optional/SDKmisc.cpp b/Demos/DX11ClothDemo/DXUT/Optional/SDKmisc.cpp new file mode 100644 index 0000000..6fcb98f --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/SDKmisc.cpp @@ -0,0 +1,1695 @@ +//-------------------------------------------------------------------------------------- +// File: SDKmisc.cpp +// +// Various helper functionality that is shared between SDK samples +// +// Copyright (c) Microsoft Corporation. All rights reserved +//-------------------------------------------------------------------------------------- +#include "dxut.h" +#include "SDKmisc.h" +#include "DXUTres.h" +#undef min // use __min instead +#undef max // use __max instead + +#include "DXUTGui.h" + +//-------------------------------------------------------------------------------------- +// Global/Static Members +//-------------------------------------------------------------------------------------- +CDXUTResourceCache& WINAPI DXUTGetGlobalResourceCache() +{ + // Using an accessor function gives control of the construction order + static CDXUTResourceCache cache; + return cache; +} + + +//-------------------------------------------------------------------------------------- +// Internal functions forward declarations +//-------------------------------------------------------------------------------------- +bool DXUTFindMediaSearchTypicalDirs( __in_ecount(cchSearch) WCHAR* strSearchPath, + int cchSearch, + __in LPCWSTR strLeaf, + __in WCHAR* strExePath, + __in WCHAR* strExeName ); +bool DXUTFindMediaSearchParentDirs( __in_ecount(cchSearch) WCHAR* strSearchPath, + int cchSearch, + __in WCHAR* strStartAt, + __in WCHAR* strLeafName ); +INT_PTR CALLBACK DisplaySwitchToREFWarningProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ); + + +//-------------------------------------------------------------------------------------- +// Shared code for samples to ask user if they want to use a REF device or quit +//-------------------------------------------------------------------------------------- +void WINAPI DXUTDisplaySwitchingToREFWarning( DXUTDeviceVersion ver ) +{ + if( DXUTGetShowMsgBoxOnError() ) + { + DWORD dwSkipWarning = 0, dwRead = 0, dwWritten = 0; + HANDLE hFile = NULL; + + // Read previous user settings + WCHAR strPath[MAX_PATH]; + SHGetFolderPath( DXUTGetHWND(), CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, strPath ); + wcscat_s( strPath, MAX_PATH, L"\\DXUT\\SkipRefWarning.dat" ); + if( ( hFile = CreateFile( strPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, + NULL ) ) != INVALID_HANDLE_VALUE ) + { + ReadFile( hFile, &dwSkipWarning, sizeof( DWORD ), &dwRead, NULL ); + CloseHandle( hFile ); + } + + if( dwSkipWarning == 0 ) + { + // Compact code to create a custom dialog box without using a template in a resource file. + // If this dialog were in a .rc file, this would be a lot simpler but every sample calling this function would + // need a copy of the dialog in its own .rc file. Also MessageBox API could be used here instead, but + // the MessageBox API is simpler to call but it can't provide a "Don't show again" checkbox + typedef struct + { + DLGITEMTEMPLATE a; + WORD b; + WORD c; + WORD d; + WORD e; + WORD f; + } DXUT_DLG_ITEM; + typedef struct + { + DLGTEMPLATE a; + WORD b; + WORD c; + WCHAR d[2]; + WORD e; + WCHAR f[16]; + DXUT_DLG_ITEM i1; + DXUT_DLG_ITEM i2; + DXUT_DLG_ITEM i3; + DXUT_DLG_ITEM i4; + DXUT_DLG_ITEM i5; + } DXUT_DLG_DATA; + + DXUT_DLG_DATA dtp = + { + {WS_CAPTION | WS_POPUP | WS_VISIBLE | WS_SYSMENU | DS_ABSALIGN | DS_3DLOOK | DS_SETFONT | + DS_MODALFRAME | DS_CENTER,0,5,0,0,269,82},0,0,L" ",8,L"MS Shell Dlg 2", + { {WS_CHILD | WS_VISIBLE | SS_ICON | SS_CENTERIMAGE,0,7,7,24,24,0x100},0xFFFF,0x0082,0,0,0}, // icon + { {WS_CHILD | WS_VISIBLE,0,40,7,230,25,0x101},0xFFFF,0x0082,0,0,0}, // static text + { {WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON,0,80,39,50,14,IDYES},0xFFFF,0x0080,0,0,0}, // Yes button + { {WS_CHILD | WS_VISIBLE | WS_TABSTOP,0,133,39,50,14,IDNO},0xFFFF,0x0080,0,0,0}, // No button + { {WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_CHECKBOX,0,7,59,70,16,IDIGNORE},0xFFFF,0x0080,0,0,0}, // checkbox + }; + + LPARAM lParam; + if( ver == DXUT_D3D9_DEVICE ) + lParam = 9; + else + lParam = 11; + int nResult = ( int )DialogBoxIndirectParam( DXUTGetHINSTANCE(), ( DLGTEMPLATE* )&dtp, DXUTGetHWND(), + DisplaySwitchToREFWarningProc, lParam ); + + if( ( nResult & 0x80 ) == 0x80 ) // "Don't show again" checkbox was checked + { + // Save user settings + dwSkipWarning = 1; + SHGetFolderPath( DXUTGetHWND(), CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, strPath ); + wcscat_s( strPath, MAX_PATH, L"\\DXUT" ); + CreateDirectory( strPath, NULL ); + wcscat_s( strPath, MAX_PATH, L"\\SkipRefWarning.dat" ); + if( ( hFile = CreateFile( strPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, + NULL ) ) != INVALID_HANDLE_VALUE ) + { + WriteFile( hFile, &dwSkipWarning, sizeof( DWORD ), &dwWritten, NULL ); + CloseHandle( hFile ); + } + } + + // User choose not to continue + if( ( nResult & 0x0F ) == IDNO ) + DXUTShutdown( 1 ); + } + } +} + + +//-------------------------------------------------------------------------------------- +// MsgProc for DXUTDisplaySwitchingToREFWarning() dialog box +//-------------------------------------------------------------------------------------- +INT_PTR CALLBACK DisplaySwitchToREFWarningProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) +{ + switch( message ) + { + case WM_INITDIALOG: + // Easier to set text here than in the DLGITEMTEMPLATE + SetWindowText( hDlg, DXUTGetWindowTitle() ); + SendMessage( GetDlgItem( hDlg, 0x100 ), STM_SETIMAGE, IMAGE_ICON, ( LPARAM )LoadIcon( 0, IDI_QUESTION ) ); + WCHAR sz[512]; + swprintf_s( sz, 512, + L"This program needs to use the Direct3D %d reference device. This device implements the entire Direct3D %d feature set, but runs very slowly. Do you wish to continue?", lParam, lParam ); + SetDlgItemText( hDlg, 0x101, sz ); + SetDlgItemText( hDlg, IDYES, L"&Yes" ); + SetDlgItemText( hDlg, IDNO, L"&No" ); + SetDlgItemText( hDlg, IDIGNORE, L"&Don't show again" ); + break; + + case WM_COMMAND: + switch( LOWORD( wParam ) ) + { + case IDIGNORE: + CheckDlgButton( hDlg, IDIGNORE, ( IsDlgButtonChecked( hDlg, + IDIGNORE ) == BST_CHECKED ) ? BST_UNCHECKED : + BST_CHECKED ); + EnableWindow( GetDlgItem( hDlg, IDNO ), ( IsDlgButtonChecked( hDlg, IDIGNORE ) != BST_CHECKED ) ); + break; + case IDNO: + EndDialog( hDlg, ( IsDlgButtonChecked( hDlg, IDIGNORE ) == BST_CHECKED ) ? IDNO | 0x80 : IDNO | + 0x00 ); return TRUE; + case IDCANCEL: + case IDYES: + EndDialog( hDlg, ( IsDlgButtonChecked( hDlg, IDIGNORE ) == BST_CHECKED ) ? IDYES | 0x80 : IDYES | + 0x00 ); return TRUE; + } + break; + } + return FALSE; +} + + +//-------------------------------------------------------------------------------------- +// Returns pointer to static media search buffer +//-------------------------------------------------------------------------------------- +WCHAR* DXUTMediaSearchPath() +{ + static WCHAR s_strMediaSearchPath[MAX_PATH] = + { + 0 + }; + return s_strMediaSearchPath; + +} + +//-------------------------------------------------------------------------------------- +LPCWSTR WINAPI DXUTGetMediaSearchPath() +{ + return DXUTMediaSearchPath(); +} + + +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTSetMediaSearchPath( LPCWSTR strPath ) +{ + HRESULT hr; + + WCHAR* s_strSearchPath = DXUTMediaSearchPath(); + + hr = wcscpy_s( s_strSearchPath, MAX_PATH, strPath ); + if( SUCCEEDED( hr ) ) + { + // append slash if needed + size_t ch = 0; + ch = wcsnlen( s_strSearchPath, MAX_PATH); + if( SUCCEEDED( hr ) && s_strSearchPath[ch - 1] != L'\\' ) + { + hr = wcscat_s( s_strSearchPath, MAX_PATH, L"\\" ); + } + } + + return hr; +} + + +//-------------------------------------------------------------------------------------- +// Tries to find the location of a SDK media file +// cchDest is the size in WCHARs of strDestPath. Be careful not to +// pass in sizeof(strDest) on UNICODE builds. +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTFindDXSDKMediaFileCch(__in_ecount(cchDest) WCHAR* strDestPath, + int cchDest, + __in LPCWSTR strFilename ) +{ + bool bFound; + WCHAR strSearchFor[MAX_PATH]; + + if( NULL == strFilename || strFilename[0] == 0 || NULL == strDestPath || cchDest < 10 ) + return E_INVALIDARG; + + // Get the exe name, and exe path + WCHAR strExePath[MAX_PATH] = + { + 0 + }; + WCHAR strExeName[MAX_PATH] = + { + 0 + }; + WCHAR* strLastSlash = NULL; + GetModuleFileName( NULL, strExePath, MAX_PATH ); + strExePath[MAX_PATH - 1] = 0; + strLastSlash = wcsrchr( strExePath, TEXT( '\\' ) ); + if( strLastSlash ) + { + wcscpy_s( strExeName, MAX_PATH, &strLastSlash[1] ); + + // Chop the exe name from the exe path + *strLastSlash = 0; + + // Chop the .exe from the exe name + strLastSlash = wcsrchr( strExeName, TEXT( '.' ) ); + if( strLastSlash ) + *strLastSlash = 0; + } + + // Typical directories: + // .\ + // ..\ + // ..\..\ + // %EXE_DIR%\ + // %EXE_DIR%\..\ + // %EXE_DIR%\..\..\ + // %EXE_DIR%\..\%EXE_NAME% + // %EXE_DIR%\..\..\%EXE_NAME% + + // Typical directory search + bFound = DXUTFindMediaSearchTypicalDirs( strDestPath, cchDest, strFilename, strExePath, strExeName ); + if( bFound ) + return S_OK; + + // Typical directory search again, but also look in a subdir called "\media\" + swprintf_s( strSearchFor, MAX_PATH, L"media\\%s", strFilename ); + bFound = DXUTFindMediaSearchTypicalDirs( strDestPath, cchDest, strSearchFor, strExePath, strExeName ); + if( bFound ) + return S_OK; + + WCHAR strLeafName[MAX_PATH] = + { + 0 + }; + + // Search all parent directories starting at .\ and using strFilename as the leaf name + wcscpy_s( strLeafName, MAX_PATH, strFilename ); + bFound = DXUTFindMediaSearchParentDirs( strDestPath, cchDest, L".", strLeafName ); + if( bFound ) + return S_OK; + + // Search all parent directories starting at the exe's dir and using strFilename as the leaf name + bFound = DXUTFindMediaSearchParentDirs( strDestPath, cchDest, strExePath, strLeafName ); + if( bFound ) + return S_OK; + + // Search all parent directories starting at .\ and using "media\strFilename" as the leaf name + swprintf_s( strLeafName, MAX_PATH, L"media\\%s", strFilename ); + bFound = DXUTFindMediaSearchParentDirs( strDestPath, cchDest, L".", strLeafName ); + if( bFound ) + return S_OK; + + // Search all parent directories starting at the exe's dir and using "media\strFilename" as the leaf name + bFound = DXUTFindMediaSearchParentDirs( strDestPath, cchDest, strExePath, strLeafName ); + if( bFound ) + return S_OK; + + // On failure, return the file as the path but also return an error code + wcscpy_s( strDestPath, cchDest, strFilename ); + + return DXUTERR_MEDIANOTFOUND; +} + + +//-------------------------------------------------------------------------------------- +// Search a set of typical directories +//-------------------------------------------------------------------------------------- +bool DXUTFindMediaSearchTypicalDirs( __in_ecount(cchSearch) WCHAR* strSearchPath, + int cchSearch, + __in LPCWSTR strLeaf, + __in WCHAR* strExePath, + __in WCHAR* strExeName ) +{ + // Typical directories: + // .\ + // ..\ + // ..\..\ + // %EXE_DIR%\ + // %EXE_DIR%\..\ + // %EXE_DIR%\..\..\ + // %EXE_DIR%\..\%EXE_NAME% + // %EXE_DIR%\..\..\%EXE_NAME% + // DXSDK media path + + // Search in .\ + wcscpy_s( strSearchPath, cchSearch, strLeaf ); + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in ..\ + swprintf_s( strSearchPath, cchSearch, L"..\\%s", strLeaf ); + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in ..\..\ + swprintf_s( strSearchPath, cchSearch, L"..\\..\\%s", strLeaf ); + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in ..\..\ + swprintf_s( strSearchPath, cchSearch, L"..\\..\\%s", strLeaf ); + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in the %EXE_DIR%\ + swprintf_s( strSearchPath, cchSearch, L"%s\\%s", strExePath, strLeaf ); + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in the %EXE_DIR%\..\ + swprintf_s( strSearchPath, cchSearch, L"%s\\..\\%s", strExePath, strLeaf ); + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in the %EXE_DIR%\..\..\ + swprintf_s( strSearchPath, cchSearch, L"%s\\..\\..\\%s", strExePath, strLeaf ); + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in "%EXE_DIR%\..\%EXE_NAME%\". This matches the DirectX SDK layout + swprintf_s( strSearchPath, cchSearch, L"%s\\..\\%s\\%s", strExePath, strExeName, strLeaf ); + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in "%EXE_DIR%\..\..\%EXE_NAME%\". This matches the DirectX SDK layout + swprintf_s( strSearchPath, cchSearch, L"%s\\..\\..\\%s\\%s", strExePath, strExeName, strLeaf ); + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in "%EXE_DIR%\Demos\DX11ClothDemo\Media\". This matches the Bullet SDK layout + swprintf_s( strSearchPath, cchSearch, L"%s\\Demos\\DX11ClothDemo\\Media\\%s", strExePath, strLeaf ); + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in "%EXE_DIR%\Demos\DX11ClothDemo\". This matches the Bullet SDK layout + swprintf_s( strSearchPath, cchSearch, L"%s\\Demos\\DX11ClothDemo\\%s", strExePath, strLeaf ); + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + + // Search in media search dir + WCHAR* s_strSearchPath = DXUTMediaSearchPath(); + if( s_strSearchPath[0] != 0 ) + { + swprintf_s( strSearchPath, cchSearch, L"%s%s", s_strSearchPath, strLeaf ); + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + } + + return false; +} + + + +//-------------------------------------------------------------------------------------- +// Search parent directories starting at strStartAt, and appending strLeafName +// at each parent directory. It stops at the root directory. +//-------------------------------------------------------------------------------------- +bool DXUTFindMediaSearchParentDirs( __in_ecount(cchSearch) WCHAR* strSearchPath, + int cchSearch, + __in WCHAR* strStartAt, + __in WCHAR* strLeafName ) +{ + WCHAR strFullPath[MAX_PATH] = + { + 0 + }; + WCHAR strFullFileName[MAX_PATH] = + { + 0 + }; + WCHAR strSearch[MAX_PATH] = + { + 0 + }; + WCHAR* strFilePart = NULL; + + GetFullPathName( strStartAt, MAX_PATH, strFullPath, &strFilePart ); + if( strFilePart == NULL ) + return false; + + while( strFilePart != NULL && *strFilePart != '\0' ) + { + swprintf_s( strFullFileName, MAX_PATH, L"%s\\%s", strFullPath, strLeafName ); + if( GetFileAttributes( strFullFileName ) != 0xFFFFFFFF ) + { + wcscpy_s( strSearchPath, cchSearch, strFullFileName ); + return true; + } + + swprintf_s( strSearch, MAX_PATH, L"%s\\..", strFullPath ); + GetFullPathName( strSearch, MAX_PATH, strFullPath, &strFilePart ); + } + + return false; +} + + +//-------------------------------------------------------------------------------------- +// CDXUTResourceCache +//-------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------------- +CDXUTResourceCache::~CDXUTResourceCache() +{ + OnDestroyDevice(); + + m_TextureCache.RemoveAll(); + m_EffectCache.RemoveAll(); + m_FontCache.RemoveAll(); +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, + LPDIRECT3DTEXTURE9* ppTexture ) +{ + return CreateTextureFromFileEx( pDevice, pSrcFile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, + 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, + 0, NULL, NULL, ppTexture ); +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCSTR pSrcFile, + LPDIRECT3DTEXTURE9* ppTexture ) +{ + WCHAR szSrcFile[MAX_PATH]; + MultiByteToWideChar( CP_ACP, 0, pSrcFile, -1, szSrcFile, MAX_PATH ); + szSrcFile[MAX_PATH - 1] = 0; + + return CreateTextureFromFile( pDevice, szSrcFile, ppTexture ); +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateTextureFromFile( ID3D11Device* pDevice, ID3D11DeviceContext *pContext, LPCTSTR pSrcFile, + ID3D11ShaderResourceView** ppOutputRV, bool bSRGB ) +{ + return CreateTextureFromFileEx( pDevice, pContext, pSrcFile, NULL, NULL, ppOutputRV, bSRGB ); +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateTextureFromFile( ID3D11Device* pDevice, ID3D11DeviceContext *pContext, LPCSTR pSrcFile, + ID3D11ShaderResourceView** ppOutputRV, bool bSRGB ) +{ + WCHAR szSrcFile[MAX_PATH]; + MultiByteToWideChar( CP_ACP, 0, pSrcFile, -1, szSrcFile, MAX_PATH ); + szSrcFile[MAX_PATH - 1] = 0; + + return CreateTextureFromFile( pDevice, pContext, szSrcFile, ppOutputRV, bSRGB ); +} + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateTextureFromFileEx( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, UINT Width, + UINT Height, UINT MipLevels, DWORD Usage, D3DFORMAT Format, + D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, PALETTEENTRY* pPalette, + LPDIRECT3DTEXTURE9* ppTexture ) +{ + // Search the cache for a matching entry. + for( int i = 0; i < m_TextureCache.GetSize(); ++i ) + { + DXUTCache_Texture& Entry = m_TextureCache[i]; + if( Entry.Location == DXUTCACHE_LOCATION_FILE && + !lstrcmpW( Entry.wszSource, pSrcFile ) && + Entry.Width == Width && + Entry.Height == Height && + Entry.MipLevels == MipLevels && + Entry.Usage9 == Usage && + Entry.Format9 == Format && + Entry.Pool9 == Pool && + Entry.Type9 == D3DRTYPE_TEXTURE ) + { + // A match is found. Obtain the IDirect3DTexture9 interface and return that. + return Entry.pTexture9->QueryInterface( IID_IDirect3DTexture9, ( LPVOID* )ppTexture ); + } + } + + HRESULT hr; + + // No matching entry. Load the resource and create a new entry. + hr = D3DXCreateTextureFromFileEx( pDevice, pSrcFile, Width, Height, MipLevels, Usage, Format, + Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppTexture ); + if( FAILED( hr ) ) + return hr; + + DXUTCache_Texture NewEntry; + NewEntry.Location = DXUTCACHE_LOCATION_FILE; + wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcFile ); + NewEntry.Width = Width; + NewEntry.Height = Height; + NewEntry.MipLevels = MipLevels; + NewEntry.Usage9 = Usage; + NewEntry.Format9 = Format; + NewEntry.Pool9 = Pool; + NewEntry.Type9 = D3DRTYPE_TEXTURE; + ( *ppTexture )->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&NewEntry.pTexture9 ); + + m_TextureCache.Add( NewEntry ); + return S_OK; +} + + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateTextureFromFileEx( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, LPCTSTR pSrcFile, + D3DX11_IMAGE_LOAD_INFO* pLoadInfo, ID3DX11ThreadPump* pPump, + ID3D11ShaderResourceView** ppOutputRV, bool bSRGB ) +{ + + bool is10L9 = DXUTGetDeviceSettings().d3d11.DeviceFeatureLevel < D3D_FEATURE_LEVEL_10_0; + HRESULT hr = S_OK; + D3DX11_IMAGE_LOAD_INFO ZeroInfo; //D3DX11_IMAGE_LOAD_INFO has a default constructor + D3DX11_IMAGE_INFO SrcInfo; + + if( !pLoadInfo ) + { + pLoadInfo = &ZeroInfo; + } + + if( !pLoadInfo->pSrcInfo ) + { + D3DX11GetImageInfoFromFile( pSrcFile, NULL, &SrcInfo, NULL ); + pLoadInfo->pSrcInfo = &SrcInfo; + + pLoadInfo->Format = pLoadInfo->pSrcInfo->Format; + } + + // Search the cache for a matching entry. + for( int i = 0; i < m_TextureCache.GetSize(); ++i ) + { + DXUTCache_Texture& Entry = m_TextureCache[i]; + if( Entry.Location == DXUTCACHE_LOCATION_FILE && + !lstrcmpW( Entry.wszSource, pSrcFile ) && + Entry.Width == pLoadInfo->Width && + Entry.Height == pLoadInfo->Height && + Entry.MipLevels == pLoadInfo->MipLevels && + Entry.Usage11 == pLoadInfo->Usage && + Entry.Format == pLoadInfo->Format && + Entry.CpuAccessFlags == pLoadInfo->CpuAccessFlags && + Entry.BindFlags == pLoadInfo->BindFlags && + Entry.MiscFlags == pLoadInfo->MiscFlags ) + { + // A match is found. Obtain the IDirect3DTexture9 interface and return that. + return Entry.pSRV11->QueryInterface( __uuidof( ID3D11ShaderResourceView ), ( LPVOID* )ppOutputRV ); + } + } + + //Ready a new entry to the texture cache + //Do this before creating the texture since pLoadInfo may be volatile + DXUTCache_Texture NewEntry; + NewEntry.Location = DXUTCACHE_LOCATION_FILE; + wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcFile ); + NewEntry.Width = pLoadInfo->Width; + NewEntry.Height = pLoadInfo->Height; + NewEntry.MipLevels = pLoadInfo->MipLevels; + NewEntry.Usage11 = pLoadInfo->Usage; + // 10L9 can't handle typesless, so we cant make a typesless format + if (is10L9 && bSRGB) { + NewEntry.Format = MAKE_SRGB(pLoadInfo->Format); + }else { + NewEntry.Format = pLoadInfo->Format; + } + NewEntry.CpuAccessFlags = pLoadInfo->CpuAccessFlags; + NewEntry.BindFlags = pLoadInfo->BindFlags; + NewEntry.MiscFlags = pLoadInfo->MiscFlags; + + //Create the rexture + ID3D11Texture2D* pRes = NULL; + hr = D3DX11CreateTextureFromFile( pDevice, pSrcFile, pLoadInfo, pPump, ( ID3D11Resource** )&pRes, NULL ); + + if( FAILED( hr ) ) + return hr; + D3D11_TEXTURE2D_DESC tex_dsc; + pRes->GetDesc(&tex_dsc); + + + + if (bSRGB ) { + // This is a workaround so that we can load linearly, but sample in SRGB. Right now, we can't load + // as linear since D3DX will try to do conversion on load. Loading as TYPELESS doesn't work either, and + // loading as typed _UNORM doesn't allow us to create an SRGB view. + + // on d3d11 featuer levels this is just a copy, but on 10L9 we must use a cpu side copy with 2 staging resources. + ID3D11Texture2D* unormStaging = NULL; + ID3D11Texture2D* srgbStaging = NULL; + + D3D11_TEXTURE2D_DESC CopyDesc; + pRes->GetDesc( &CopyDesc ); + + pLoadInfo->BindFlags = 0; + pLoadInfo->CpuAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; + pLoadInfo->Depth = 0; + pLoadInfo->Filter = D3DX11_FILTER_POINT; + pLoadInfo->FirstMipLevel = 0; + pLoadInfo->Format = CopyDesc.Format; + pLoadInfo->Height = CopyDesc.Height; + pLoadInfo->MipFilter = D3DX11_FILTER_POINT; + pLoadInfo->MiscFlags = CopyDesc.MiscFlags; + pLoadInfo->Usage = D3D11_USAGE_STAGING; + pLoadInfo->Width = CopyDesc.Width; + + CopyDesc.BindFlags = 0; + CopyDesc.Usage = D3D11_USAGE_STAGING; + CopyDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; + CopyDesc.Format = MAKE_SRGB(CopyDesc.Format); + + hr = D3DX11CreateTextureFromFile( pDevice, pSrcFile, pLoadInfo, pPump, ( ID3D11Resource** )&unormStaging, NULL ); + + hr = pDevice->CreateTexture2D(&CopyDesc, NULL, &srgbStaging); + pContext->CopyResource( srgbStaging, unormStaging ); + ID3D11Texture2D* srgbGPU; + + pRes->GetDesc( &CopyDesc ); + CopyDesc.Format = MAKE_SRGB(CopyDesc.Format); + hr = pDevice->CreateTexture2D(&CopyDesc, NULL, &srgbGPU); + pContext->CopyResource( srgbGPU, srgbStaging ); + + SAFE_RELEASE(pRes); + SAFE_RELEASE(srgbStaging); + SAFE_RELEASE(unormStaging); + pRes = srgbGPU; + + } + + D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; + if( bSRGB ) + SRVDesc.Format = MAKE_SRGB( ZeroInfo.Format ); + else + SRVDesc.Format = ZeroInfo.Format; + if( pLoadInfo->pSrcInfo->ResourceDimension == D3D11_RESOURCE_DIMENSION_TEXTURE1D ) + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; + SRVDesc.Texture1D.MostDetailedMip = 0; + SRVDesc.Texture1D.MipLevels = pLoadInfo->pSrcInfo->MipLevels; + } + else if( pLoadInfo->pSrcInfo->ResourceDimension == D3D11_RESOURCE_DIMENSION_TEXTURE2D ) + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + SRVDesc.Texture2D.MostDetailedMip = 0; + SRVDesc.Texture2D.MipLevels = pLoadInfo->pSrcInfo->MipLevels; + + if( pLoadInfo->pSrcInfo->MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE ) + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + SRVDesc.TextureCube.MostDetailedMip = 0; + SRVDesc.TextureCube.MipLevels = pLoadInfo->pSrcInfo->MipLevels; + } + } + else if( pLoadInfo->pSrcInfo->ResourceDimension == D3D11_RESOURCE_DIMENSION_TEXTURE3D ) + { + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + SRVDesc.Texture3D.MostDetailedMip = 0; + SRVDesc.Texture3D.MipLevels = pLoadInfo->pSrcInfo->MipLevels; + } + if (bSRGB) { + SRVDesc.Format = MAKE_SRGB(tex_dsc.Format); + }else { + SRVDesc.Format = tex_dsc.Format; + } + SRVDesc.Texture2D.MipLevels = tex_dsc.MipLevels; + SRVDesc.Texture2D.MostDetailedMip = 0; + hr = pDevice->CreateShaderResourceView( pRes, &SRVDesc, ppOutputRV ); + pRes->Release(); + if( FAILED( hr ) ) + return hr; + + ( *ppOutputRV )->QueryInterface( __uuidof( ID3D11ShaderResourceView ), ( LPVOID* )&NewEntry.pSRV11 ); + + m_TextureCache.Add( NewEntry ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateTextureFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, + LPCTSTR pSrcResource, LPDIRECT3DTEXTURE9* ppTexture ) +{ + return CreateTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, D3DX_DEFAULT, D3DX_DEFAULT, + D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, + D3DX_DEFAULT, 0, NULL, NULL, ppTexture ); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateTextureFromResourceEx( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, + LPCTSTR pSrcResource, UINT Width, UINT Height, UINT MipLevels, + DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, + DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, LPDIRECT3DTEXTURE9* ppTexture ) +{ + // Search the cache for a matching entry. + for( int i = 0; i < m_TextureCache.GetSize(); ++i ) + { + DXUTCache_Texture& Entry = m_TextureCache[i]; + if( Entry.Location == DXUTCACHE_LOCATION_RESOURCE && + Entry.hSrcModule == hSrcModule && + !lstrcmpW( Entry.wszSource, pSrcResource ) && + Entry.Width == Width && + Entry.Height == Height && + Entry.MipLevels == MipLevels && + Entry.Usage9 == Usage && + Entry.Format9 == Format && + Entry.Pool9 == Pool && + Entry.Type9 == D3DRTYPE_TEXTURE ) + { + // A match is found. Obtain the IDirect3DTexture9 interface and return that. + return Entry.pTexture9->QueryInterface( IID_IDirect3DTexture9, ( LPVOID* )ppTexture ); + } + } + + HRESULT hr; + + // No matching entry. Load the resource and create a new entry. + hr = D3DXCreateTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, Width, Height, MipLevels, Usage, + Format, Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppTexture ); + if( FAILED( hr ) ) + return hr; + + DXUTCache_Texture NewEntry; + NewEntry.Location = DXUTCACHE_LOCATION_RESOURCE; + NewEntry.hSrcModule = hSrcModule; + wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcResource ); + NewEntry.Width = Width; + NewEntry.Height = Height; + NewEntry.MipLevels = MipLevels; + NewEntry.Usage9 = Usage; + NewEntry.Format9 = Format; + NewEntry.Pool9 = Pool; + NewEntry.Type9 = D3DRTYPE_TEXTURE; + ( *ppTexture )->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&NewEntry.pTexture9 ); + + m_TextureCache.Add( NewEntry ); + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateCubeTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture ) +{ + return CreateCubeTextureFromFileEx( pDevice, pSrcFile, D3DX_DEFAULT, D3DX_DEFAULT, 0, + D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, + 0, NULL, NULL, ppCubeTexture ); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateCubeTextureFromFileEx( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, UINT Size, + UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, + DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, PALETTEENTRY* pPalette, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture ) +{ + // Search the cache for a matching entry. + for( int i = 0; i < m_TextureCache.GetSize(); ++i ) + { + DXUTCache_Texture& Entry = m_TextureCache[i]; + if( Entry.Location == DXUTCACHE_LOCATION_FILE && + !lstrcmpW( Entry.wszSource, pSrcFile ) && + Entry.Width == Size && + Entry.MipLevels == MipLevels && + Entry.Usage9 == Usage && + Entry.Format9 == Format && + Entry.Pool9 == Pool && + Entry.Type9 == D3DRTYPE_CUBETEXTURE ) + { + // A match is found. Obtain the IDirect3DCubeTexture9 interface and return that. + return Entry.pTexture9->QueryInterface( IID_IDirect3DCubeTexture9, ( LPVOID* )ppCubeTexture ); + } + } + + HRESULT hr; + + // No matching entry. Load the resource and create a new entry. + hr = D3DXCreateCubeTextureFromFileEx( pDevice, pSrcFile, Size, MipLevels, Usage, Format, Pool, Filter, + MipFilter, ColorKey, pSrcInfo, pPalette, ppCubeTexture ); + if( FAILED( hr ) ) + return hr; + + DXUTCache_Texture NewEntry; + NewEntry.Location = DXUTCACHE_LOCATION_FILE; + wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcFile ); + NewEntry.Width = Size; + NewEntry.MipLevels = MipLevels; + NewEntry.Usage9 = Usage; + NewEntry.Format9 = Format; + NewEntry.Pool9 = Pool; + NewEntry.Type9 = D3DRTYPE_CUBETEXTURE; + ( *ppCubeTexture )->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&NewEntry.pTexture9 ); + + m_TextureCache.Add( NewEntry ); + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateCubeTextureFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, + LPCTSTR pSrcResource, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture ) +{ + return CreateCubeTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, D3DX_DEFAULT, D3DX_DEFAULT, + 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, + 0, NULL, NULL, ppCubeTexture ); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateCubeTextureFromResourceEx( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, + LPCTSTR pSrcResource, UINT Size, UINT MipLevels, + DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, + DWORD MipFilter, D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, PALETTEENTRY* pPalette, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture ) +{ + // Search the cache for a matching entry. + for( int i = 0; i < m_TextureCache.GetSize(); ++i ) + { + DXUTCache_Texture& Entry = m_TextureCache[i]; + if( Entry.Location == DXUTCACHE_LOCATION_RESOURCE && + Entry.hSrcModule == hSrcModule && + !lstrcmpW( Entry.wszSource, pSrcResource ) && + Entry.Width == Size && + Entry.MipLevels == MipLevels && + Entry.Usage9 == Usage && + Entry.Format9 == Format && + Entry.Pool9 == Pool && + Entry.Type9 == D3DRTYPE_CUBETEXTURE ) + { + // A match is found. Obtain the IDirect3DCubeTexture9 interface and return that. + return Entry.pTexture9->QueryInterface( IID_IDirect3DCubeTexture9, ( LPVOID* )ppCubeTexture ); + } + } + + HRESULT hr; + + // No matching entry. Load the resource and create a new entry. + hr = D3DXCreateCubeTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, Size, MipLevels, Usage, Format, + Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppCubeTexture ); + if( FAILED( hr ) ) + return hr; + + DXUTCache_Texture NewEntry; + NewEntry.Location = DXUTCACHE_LOCATION_RESOURCE; + NewEntry.hSrcModule = hSrcModule; + wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcResource ); + NewEntry.Width = Size; + NewEntry.MipLevels = MipLevels; + NewEntry.Usage9 = Usage; + NewEntry.Format9 = Format; + NewEntry.Pool9 = Pool; + NewEntry.Type9 = D3DRTYPE_CUBETEXTURE; + ( *ppCubeTexture )->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&NewEntry.pTexture9 ); + + m_TextureCache.Add( NewEntry ); + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateVolumeTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture ) +{ + return CreateVolumeTextureFromFileEx( pDevice, pSrcFile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, + 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, + 0, NULL, NULL, ppVolumeTexture ); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateVolumeTextureFromFileEx( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, UINT Width, + UINT Height, UINT Depth, UINT MipLevels, DWORD Usage, + D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, + DWORD MipFilter, D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, PALETTEENTRY* pPalette, + LPDIRECT3DVOLUMETEXTURE9* ppTexture ) +{ + // Search the cache for a matching entry. + for( int i = 0; i < m_TextureCache.GetSize(); ++i ) + { + DXUTCache_Texture& Entry = m_TextureCache[i]; + if( Entry.Location == DXUTCACHE_LOCATION_FILE && + !lstrcmpW( Entry.wszSource, pSrcFile ) && + Entry.Width == Width && + Entry.Height == Height && + Entry.Depth == Depth && + Entry.MipLevels == MipLevels && + Entry.Usage9 == Usage && + Entry.Format9 == Format && + Entry.Pool9 == Pool && + Entry.Type9 == D3DRTYPE_VOLUMETEXTURE ) + { + // A match is found. Obtain the IDirect3DVolumeTexture9 interface and return that. + return Entry.pTexture9->QueryInterface( IID_IDirect3DVolumeTexture9, ( LPVOID* )ppTexture ); + } + } + + HRESULT hr; + + // No matching entry. Load the resource and create a new entry. + hr = D3DXCreateVolumeTextureFromFileEx( pDevice, pSrcFile, Width, Height, Depth, MipLevels, Usage, Format, + Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppTexture ); + if( FAILED( hr ) ) + return hr; + + DXUTCache_Texture NewEntry; + NewEntry.Location = DXUTCACHE_LOCATION_FILE; + wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcFile ); + NewEntry.Width = Width; + NewEntry.Height = Height; + NewEntry.Depth = Depth; + NewEntry.MipLevels = MipLevels; + NewEntry.Usage9 = Usage; + NewEntry.Format9 = Format; + NewEntry.Pool9 = Pool; + NewEntry.Type9 = D3DRTYPE_VOLUMETEXTURE; + ( *ppTexture )->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&NewEntry.pTexture9 ); + + m_TextureCache.Add( NewEntry ); + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateVolumeTextureFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, + LPCTSTR pSrcResource, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture ) +{ + return CreateVolumeTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, D3DX_DEFAULT, D3DX_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, + D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, ppVolumeTexture ); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateVolumeTextureFromResourceEx( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, + LPCTSTR pSrcResource, UINT Width, UINT Height, + UINT Depth, UINT MipLevels, DWORD Usage, + D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, + DWORD MipFilter, D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, PALETTEENTRY* pPalette, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture ) +{ + // Search the cache for a matching entry. + for( int i = 0; i < m_TextureCache.GetSize(); ++i ) + { + DXUTCache_Texture& Entry = m_TextureCache[i]; + if( Entry.Location == DXUTCACHE_LOCATION_RESOURCE && + Entry.hSrcModule == hSrcModule && + !lstrcmpW( Entry.wszSource, pSrcResource ) && + Entry.Width == Width && + Entry.Height == Height && + Entry.Depth == Depth && + Entry.MipLevels == MipLevels && + Entry.Usage9 == Usage && + Entry.Format9 == Format && + Entry.Pool9 == Pool && + Entry.Type9 == D3DRTYPE_VOLUMETEXTURE ) + { + // A match is found. Obtain the IDirect3DVolumeTexture9 interface and return that. + return Entry.pTexture9->QueryInterface( IID_IDirect3DVolumeTexture9, ( LPVOID* )ppVolumeTexture ); + } + } + + HRESULT hr; + + // No matching entry. Load the resource and create a new entry. + hr = D3DXCreateVolumeTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, Width, Height, Depth, MipLevels, + Usage, + Format, Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, + ppVolumeTexture ); + if( FAILED( hr ) ) + return hr; + + DXUTCache_Texture NewEntry; + NewEntry.Location = DXUTCACHE_LOCATION_RESOURCE; + NewEntry.hSrcModule = hSrcModule; + wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcResource ); + NewEntry.Width = Width; + NewEntry.Height = Height; + NewEntry.Depth = Depth; + NewEntry.MipLevels = MipLevels; + NewEntry.Usage9 = Usage; + NewEntry.Format9 = Format; + NewEntry.Pool9 = Pool; + NewEntry.Type9 = D3DRTYPE_VOLUMETEXTURE; + ( *ppVolumeTexture )->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&NewEntry.pTexture9 ); + + m_TextureCache.Add( NewEntry ); + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateFont( LPDIRECT3DDEVICE9 pDevice, UINT Height, UINT Width, UINT Weight, + UINT MipLevels, BOOL Italic, DWORD CharSet, DWORD OutputPrecision, + DWORD Quality, DWORD PitchAndFamily, LPCTSTR pFacename, LPD3DXFONT* ppFont ) +{ + D3DXFONT_DESCW Desc; + + Desc.Height = Height; + Desc.Width = Width; + Desc.Weight = Weight; + Desc.MipLevels = MipLevels; + Desc.Italic = Italic; + Desc.CharSet = ( BYTE )CharSet; + Desc.OutputPrecision = ( BYTE )OutputPrecision; + Desc.Quality = ( BYTE )Quality; + Desc.PitchAndFamily = ( BYTE )PitchAndFamily; + wcscpy_s( Desc.FaceName, LF_FACESIZE, pFacename ); + + return CreateFontIndirect( pDevice, &Desc, ppFont ); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateFontIndirect( LPDIRECT3DDEVICE9 pDevice, CONST D3DXFONT_DESC *pDesc, LPD3DXFONT *ppFont ) + { + // Search the cache for a matching entry. + for( int i = 0; i < m_FontCache.GetSize(); ++i ) + { + DXUTCache_Font &Entry = m_FontCache[i]; + + if( Entry.Width == pDesc->Width && + Entry.Height == pDesc->Height && + Entry.Weight == pDesc->Weight && + Entry.MipLevels == pDesc->MipLevels && + Entry.Italic == pDesc->Italic && + Entry.CharSet == pDesc->CharSet && + Entry.OutputPrecision == pDesc->OutputPrecision && + Entry.Quality == pDesc->Quality && + Entry.PitchAndFamily == pDesc->PitchAndFamily && + CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE, + Entry.FaceName, -1, + pDesc->FaceName, -1 ) == CSTR_EQUAL ) + { + // A match is found. Increment the reference and return the ID3DXFont object. + Entry.pFont->AddRef(); + *ppFont = Entry.pFont; + return S_OK; + } + } + + HRESULT hr; + + // No matching entry. Load the resource and create a new entry. + hr = D3DXCreateFontIndirect( pDevice, pDesc, ppFont ); + if( FAILED( hr ) ) + return hr; + + DXUTCache_Font NewEntry; + ( D3DXFONT_DESC & )NewEntry = *pDesc; + NewEntry.pFont = *ppFont; + NewEntry.pFont->AddRef(); + + m_FontCache.Add( NewEntry ); + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateEffectFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, + const D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, + LPD3DXEFFECTPOOL pPool, LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors ) +{ + // Search the cache for a matching entry. + for( int i = 0; i < m_EffectCache.GetSize(); ++i ) + { + DXUTCache_Effect& Entry = m_EffectCache[i]; + + if( Entry.Location == DXUTCACHE_LOCATION_FILE && + !lstrcmpW( Entry.wszSource, pSrcFile ) && + Entry.dwFlags == Flags ) + { + // A match is found. Increment the ref coutn and return the ID3DXEffect object. + *ppEffect = Entry.pEffect; + ( *ppEffect )->AddRef(); + return S_OK; + } + } + + HRESULT hr; + + // No matching entry. Load the resource and create a new entry. + hr = D3DXCreateEffectFromFile( pDevice, pSrcFile, pDefines, pInclude, Flags, pPool, ppEffect, + ppCompilationErrors ); + if( FAILED( hr ) ) + return hr; + + DXUTCache_Effect NewEntry; + NewEntry.Location = DXUTCACHE_LOCATION_FILE; + wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcFile ); + NewEntry.dwFlags = Flags; + NewEntry.pEffect = *ppEffect; + NewEntry.pEffect->AddRef(); + + m_EffectCache.Add( NewEntry ); + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::CreateEffectFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, + LPCTSTR pSrcResource, const D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, LPD3DXBUFFER* ppCompilationErrors ) +{ + // Search the cache for a matching entry. + for( int i = 0; i < m_EffectCache.GetSize(); ++i ) + { + DXUTCache_Effect& Entry = m_EffectCache[i]; + + if( Entry.Location == DXUTCACHE_LOCATION_RESOURCE && + Entry.hSrcModule == hSrcModule && + !lstrcmpW( Entry.wszSource, pSrcResource ) && + Entry.dwFlags == Flags ) + { + // A match is found. Increment the ref coutn and return the ID3DXEffect object. + *ppEffect = Entry.pEffect; + ( *ppEffect )->AddRef(); + return S_OK; + } + } + + HRESULT hr; + + // No matching entry. Load the resource and create a new entry. + hr = D3DXCreateEffectFromResource( pDevice, hSrcModule, pSrcResource, pDefines, pInclude, Flags, + pPool, ppEffect, ppCompilationErrors ); + if( FAILED( hr ) ) + return hr; + + DXUTCache_Effect NewEntry; + NewEntry.Location = DXUTCACHE_LOCATION_RESOURCE; + NewEntry.hSrcModule = hSrcModule; + wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcResource ); + NewEntry.dwFlags = Flags; + NewEntry.pEffect = *ppEffect; + NewEntry.pEffect->AddRef(); + + m_EffectCache.Add( NewEntry ); + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Device event callbacks +//-------------------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::OnCreateDevice( IDirect3DDevice9* pd3dDevice ) +{ + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::OnResetDevice( IDirect3DDevice9* pd3dDevice ) +{ + // Call OnResetDevice on all effect and font objects + for( int i = 0; i < m_EffectCache.GetSize(); ++i ) + m_EffectCache[i].pEffect->OnResetDevice(); + for( int i = 0; i < m_FontCache.GetSize(); ++i ) + m_FontCache[i].pFont->OnResetDevice(); + + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::OnLostDevice() +{ + // Call OnLostDevice on all effect and font objects + for( int i = 0; i < m_EffectCache.GetSize(); ++i ) + m_EffectCache[i].pEffect->OnLostDevice(); + for( int i = 0; i < m_FontCache.GetSize(); ++i ) + m_FontCache[i].pFont->OnLostDevice(); + + // Release all the default pool textures + for( int i = m_TextureCache.GetSize() - 1; i >= 0; --i ) + if( m_TextureCache[i].Pool9 == D3DPOOL_DEFAULT ) + { + SAFE_RELEASE( m_TextureCache[i].pTexture9 ); + m_TextureCache.Remove( i ); // Remove the entry + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTResourceCache::OnDestroyDevice() +{ + // Release all resources + for( int i = m_EffectCache.GetSize() - 1; i >= 0; --i ) + { + SAFE_RELEASE( m_EffectCache[i].pEffect ); + m_EffectCache.Remove( i ); + } + for( int i = m_FontCache.GetSize() - 1; i >= 0; --i ) + { + SAFE_RELEASE( m_FontCache[i].pFont ); + m_FontCache.Remove( i ); + } + for( int i = m_TextureCache.GetSize() - 1; i >= 0; --i ) + { + SAFE_RELEASE( m_TextureCache[i].pTexture9 ); + SAFE_RELEASE( m_TextureCache[i].pSRV11 ); + m_TextureCache.Remove( i ); + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Desc: Returns a view matrix for rendering to a face of a cubemap. +//-------------------------------------------------------------------------------------- +D3DXMATRIX WINAPI DXUTGetCubeMapViewMatrix( DWORD dwFace ) +{ + D3DXVECTOR3 vEyePt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); + D3DXVECTOR3 vLookDir; + D3DXVECTOR3 vUpDir; + + switch( dwFace ) + { + case D3DCUBEMAP_FACE_POSITIVE_X: + vLookDir = D3DXVECTOR3( 1.0f, 0.0f, 0.0f ); + vUpDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); + break; + case D3DCUBEMAP_FACE_NEGATIVE_X: + vLookDir = D3DXVECTOR3( -1.0f, 0.0f, 0.0f ); + vUpDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); + break; + case D3DCUBEMAP_FACE_POSITIVE_Y: + vLookDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); + vUpDir = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); + break; + case D3DCUBEMAP_FACE_NEGATIVE_Y: + vLookDir = D3DXVECTOR3( 0.0f, -1.0f, 0.0f ); + vUpDir = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); + break; + case D3DCUBEMAP_FACE_POSITIVE_Z: + vLookDir = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); + vUpDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); + break; + case D3DCUBEMAP_FACE_NEGATIVE_Z: + vLookDir = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); + vUpDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); + break; + } + + // Set the view transform for this cubemap surface + D3DXMATRIXA16 mView; + D3DXMatrixLookAtLH( &mView, &vEyePt, &vLookDir, &vUpDir ); + return mView; +} + + +//-------------------------------------------------------------------------------------- +CDXUTLineManager::CDXUTLineManager() +{ + m_pd3dDevice = NULL; + m_pD3DXLine = NULL; +} + + +//-------------------------------------------------------------------------------------- +CDXUTLineManager::~CDXUTLineManager() +{ + OnDeletedDevice(); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTLineManager::OnCreatedDevice( IDirect3DDevice9* pd3dDevice ) +{ + m_pd3dDevice = pd3dDevice; + + HRESULT hr; + hr = D3DXCreateLine( m_pd3dDevice, &m_pD3DXLine ); + if( FAILED( hr ) ) + return hr; + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTLineManager::OnResetDevice() +{ + if( m_pD3DXLine ) + m_pD3DXLine->OnResetDevice(); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTLineManager::OnRender() +{ + HRESULT hr; + if( NULL == m_pD3DXLine ) + return E_INVALIDARG; + + bool bDrawingHasBegun = false; + float fLastWidth = 0.0f; + bool bLastAntiAlias = false; + + for( int i = 0; i < m_LinesList.GetSize(); i++ ) + { + LINE_NODE* pLineNode = m_LinesList.GetAt( i ); + if( pLineNode ) + { + if( !bDrawingHasBegun || + fLastWidth != pLineNode->fWidth || + bLastAntiAlias != pLineNode->bAntiAlias ) + { + if( bDrawingHasBegun ) + { + hr = m_pD3DXLine->End(); + if( FAILED( hr ) ) + return hr; + } + + m_pD3DXLine->SetWidth( pLineNode->fWidth ); + m_pD3DXLine->SetAntialias( pLineNode->bAntiAlias ); + + fLastWidth = pLineNode->fWidth; + bLastAntiAlias = pLineNode->bAntiAlias; + + hr = m_pD3DXLine->Begin(); + if( FAILED( hr ) ) + return hr; + bDrawingHasBegun = true; + } + + hr = m_pD3DXLine->Draw( pLineNode->pVertexList, pLineNode->dwVertexListCount, pLineNode->Color ); + if( FAILED( hr ) ) + return hr; + } + } + + if( bDrawingHasBegun ) + { + hr = m_pD3DXLine->End(); + if( FAILED( hr ) ) + return hr; + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTLineManager::OnLostDevice() +{ + if( m_pD3DXLine ) + m_pD3DXLine->OnLostDevice(); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTLineManager::OnDeletedDevice() +{ + RemoveAllLines(); + SAFE_RELEASE( m_pD3DXLine ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTLineManager::AddLine( int* pnLineID, D3DXVECTOR2* pVertexList, DWORD dwVertexListCount, D3DCOLOR Color, + float fWidth, float fScaleRatio, bool bAntiAlias ) +{ + if( pVertexList == NULL || dwVertexListCount == 0 ) + return E_INVALIDARG; + + LINE_NODE* pLineNode = new LINE_NODE; + if( pLineNode == NULL ) + return E_OUTOFMEMORY; + ZeroMemory( pLineNode, sizeof( LINE_NODE ) ); + + pLineNode->nLineID = m_LinesList.GetSize(); + pLineNode->Color = Color; + pLineNode->fWidth = fWidth; + pLineNode->bAntiAlias = bAntiAlias; + pLineNode->dwVertexListCount = dwVertexListCount; + + if( pnLineID ) + *pnLineID = pLineNode->nLineID; + + pLineNode->pVertexList = new D3DXVECTOR2[dwVertexListCount]; + if( pLineNode->pVertexList == NULL ) + { + delete pLineNode; + return E_OUTOFMEMORY; + } + for( DWORD i = 0; i < dwVertexListCount; i++ ) + { + pLineNode->pVertexList[i] = pVertexList[i] * fScaleRatio; + } + + m_LinesList.Add( pLineNode ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTLineManager::AddRect( int* pnLineID, RECT rc, D3DCOLOR Color, float fWidth, float fScaleRatio, + bool bAntiAlias ) +{ + if( fWidth > 2.0f ) + { + D3DXVECTOR2 vertexList[8]; + + vertexList[0].x = ( float )rc.left; + vertexList[0].y = ( float )rc.top - ( fWidth / 2.0f ); + + vertexList[1].x = ( float )rc.left; + vertexList[1].y = ( float )rc.bottom + ( fWidth / 2.0f ); + + vertexList[2].x = ( float )rc.left; + vertexList[2].y = ( float )rc.bottom - 0.5f; + + vertexList[3].x = ( float )rc.right; + vertexList[3].y = ( float )rc.bottom - 0.5f; + + vertexList[4].x = ( float )rc.right; + vertexList[4].y = ( float )rc.bottom + ( fWidth / 2.0f ); + + vertexList[5].x = ( float )rc.right; + vertexList[5].y = ( float )rc.top - ( fWidth / 2.0f ); + + vertexList[6].x = ( float )rc.right; + vertexList[6].y = ( float )rc.top; + + vertexList[7].x = ( float )rc.left; + vertexList[7].y = ( float )rc.top; + + return AddLine( pnLineID, vertexList, 8, Color, fWidth, fScaleRatio, bAntiAlias ); + } + else + { + D3DXVECTOR2 vertexList[5]; + vertexList[0].x = ( float )rc.left; + vertexList[0].y = ( float )rc.top; + + vertexList[1].x = ( float )rc.left; + vertexList[1].y = ( float )rc.bottom; + + vertexList[2].x = ( float )rc.right; + vertexList[2].y = ( float )rc.bottom; + + vertexList[3].x = ( float )rc.right; + vertexList[3].y = ( float )rc.top; + + vertexList[4].x = ( float )rc.left; + vertexList[4].y = ( float )rc.top; + + return AddLine( pnLineID, vertexList, 5, Color, fWidth, fScaleRatio, bAntiAlias ); + } +} + + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTLineManager::RemoveLine( int nLineID ) +{ + for( int i = 0; i < m_LinesList.GetSize(); i++ ) + { + LINE_NODE* pLineNode = m_LinesList.GetAt( i ); + if( pLineNode && pLineNode->nLineID == nLineID ) + { + SAFE_DELETE_ARRAY( pLineNode->pVertexList ); + delete pLineNode; + m_LinesList.SetAt( i, NULL ); + } + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTLineManager::RemoveAllLines() +{ + for( int i = 0; i < m_LinesList.GetSize(); i++ ) + { + LINE_NODE* pLineNode = m_LinesList.GetAt( i ); + if( pLineNode ) + { + SAFE_DELETE_ARRAY( pLineNode->pVertexList ); + delete pLineNode; + } + } + m_LinesList.RemoveAll(); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +CDXUTTextHelper::CDXUTTextHelper( ID3DXFont* pFont9, ID3DXSprite* pSprite9, int nLineHeight ) +{ + Init( pFont9, pSprite9, nLineHeight ); +} + +CDXUTTextHelper::CDXUTTextHelper( ID3D11Device* pd3d11Device, ID3D11DeviceContext* pd3d11DeviceContext, CDXUTDialogResourceManager* pManager, int nLineHeight ) +{ + Init( NULL, NULL, nLineHeight ); + m_pd3d11Device = pd3d11Device; + m_pd3d11DeviceContext = pd3d11DeviceContext; + m_pManager = pManager; +} +CDXUTTextHelper::~CDXUTTextHelper() +{ + +} + +//-------------------------------------------------------------------------------------- +void CDXUTTextHelper::Init( ID3DXFont* pFont9, ID3DXSprite* pSprite9, + int nLineHeight ) +{ + m_pFont9 = pFont9; + m_pSprite9 = pSprite9; + m_clr = D3DXCOLOR( 1, 1, 1, 1 ); + m_pt.x = 0; + m_pt.y = 0; + m_nLineHeight = nLineHeight; + m_pd3d11Device = NULL; + m_pd3d11DeviceContext = NULL; + m_pManager = NULL; + + // Create a blend state if a sprite is passed in +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTTextHelper::DrawFormattedTextLine( const WCHAR* strMsg, ... ) +{ + WCHAR strBuffer[512]; + + va_list args; + va_start( args, strMsg ); + vswprintf_s( strBuffer, 512, strMsg, args ); + strBuffer[511] = L'\0'; + va_end( args ); + + return DrawTextLine( strBuffer ); +} + + +//-------------------------------------------------------------------------------------- +HRESULT CDXUTTextHelper::DrawTextLine( const WCHAR* strMsg ) +{ + if( NULL == m_pFont9 && NULL == m_pd3d11DeviceContext ) + return DXUT_ERR_MSGBOX( L"DrawTextLine", E_INVALIDARG ); + + HRESULT hr = S_OK; + RECT rc; + SetRect( &rc, m_pt.x, m_pt.y, 0, 0 ); + if( m_pFont9 ) + hr = m_pFont9->DrawText( m_pSprite9, strMsg, -1, &rc, DT_NOCLIP, m_clr ); + else if( m_pd3d11DeviceContext ) + DrawText11DXUT( m_pd3d11Device, m_pd3d11DeviceContext, strMsg, rc, m_clr, + (float)m_pManager->m_nBackBufferWidth, (float)m_pManager->m_nBackBufferHeight, false ); + + if( FAILED( hr ) ) + return DXTRACE_ERR_MSGBOX( L"DrawText", hr ); + + m_pt.y += m_nLineHeight; + + return S_OK; +} + + +HRESULT CDXUTTextHelper::DrawFormattedTextLine( RECT& rc, DWORD dwFlags, const WCHAR* strMsg, ... ) +{ + WCHAR strBuffer[512]; + + va_list args; + va_start( args, strMsg ); + vswprintf_s( strBuffer, 512, strMsg, args ); + strBuffer[511] = L'\0'; + va_end( args ); + + return DrawTextLine( rc, dwFlags, strBuffer ); +} + + +HRESULT CDXUTTextHelper::DrawTextLine( RECT& rc, DWORD dwFlags, const WCHAR* strMsg ) +{ + if( NULL == m_pFont9 && NULL == m_pd3d11DeviceContext ) + return DXUT_ERR_MSGBOX( L"DrawTextLine", E_INVALIDARG ); + + HRESULT hr = S_OK; + if( m_pFont9 ) + hr = m_pFont9->DrawText( m_pSprite9, strMsg, -1, &rc, dwFlags, m_clr ); + else if( m_pd3d11DeviceContext ) + DrawText11DXUT( m_pd3d11Device, m_pd3d11DeviceContext, strMsg, rc, m_clr, + (float)m_pManager->m_nBackBufferWidth, (float)m_pManager->m_nBackBufferHeight, false ); + + if( FAILED( hr ) ) + return DXTRACE_ERR_MSGBOX( L"DrawText", hr ); + + m_pt.y += m_nLineHeight; + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +void CDXUTTextHelper::Begin() +{ + if( m_pSprite9 ) + m_pSprite9->Begin( D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_TEXTURE ); + + if( m_pd3d11DeviceContext ) + { + m_pManager->StoreD3D11State( m_pd3d11DeviceContext ); + m_pManager->ApplyRenderUI11( m_pd3d11DeviceContext ); + } + + +} +void CDXUTTextHelper::End() +{ + if( m_pSprite9 ) + m_pSprite9->End(); + + if( m_pd3d11DeviceContext ) + { + m_pManager->RestoreD3D11State( m_pd3d11DeviceContext ); + } +} diff --git a/Demos/DX11ClothDemo/DXUT/Optional/SDKmisc.h b/Demos/DX11ClothDemo/DXUT/Optional/SDKmisc.h new file mode 100644 index 0000000..ac91782 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/SDKmisc.h @@ -0,0 +1,368 @@ +//-------------------------------------------------------------------------------------- +// File: SDKMisc.h +// +// Various helper functionality that is shared between SDK samples +// +// Copyright (c) Microsoft Corporation. All rights reserved +//-------------------------------------------------------------------------------------- +#pragma once +#ifndef SDKMISC_H +#define SDKMISC_H + + +//----------------------------------------------------------------------------- +// Resource cache for textures, fonts, meshs, and effects. +// Use DXUTGetGlobalResourceCache() to access the global cache +//----------------------------------------------------------------------------- + +enum DXUTCACHE_SOURCELOCATION +{ + DXUTCACHE_LOCATION_FILE, + DXUTCACHE_LOCATION_RESOURCE +}; + +struct DXUTCache_Texture +{ + DXUTCACHE_SOURCELOCATION Location; + WCHAR wszSource[MAX_PATH]; + HMODULE hSrcModule; + UINT Width; + UINT Height; + UINT Depth; + UINT MipLevels; + UINT MiscFlags; + union + { + DWORD Usage9; + D3D11_USAGE Usage11; + }; + union + { + D3DFORMAT Format9; + DXGI_FORMAT Format; + }; + union + { + D3DPOOL Pool9; + UINT CpuAccessFlags; + }; + union + { + D3DRESOURCETYPE Type9; + UINT BindFlags; + }; + IDirect3DBaseTexture9* pTexture9; + ID3D11ShaderResourceView* pSRV11; + + DXUTCache_Texture() + { + pTexture9 = NULL; + pSRV11 = NULL; + } +}; + +struct DXUTCache_Font : public D3DXFONT_DESC +{ + ID3DXFont* pFont; +}; + +struct DXUTCache_Effect +{ + DXUTCACHE_SOURCELOCATION Location; + WCHAR wszSource[MAX_PATH]; + HMODULE hSrcModule; + DWORD dwFlags; + ID3DXEffect* pEffect; +}; + + +class CDXUTResourceCache +{ +public: + ~CDXUTResourceCache(); + + HRESULT CreateTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, + LPDIRECT3DTEXTURE9* ppTexture ); + HRESULT CreateTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCSTR pSrcFile, + LPDIRECT3DTEXTURE9* ppTexture ); + HRESULT CreateTextureFromFile( ID3D11Device* pDevice, ID3D11DeviceContext *pContext, LPCTSTR pSrcFile, + ID3D11ShaderResourceView** ppOutputRV, bool bSRGB=false ); + HRESULT CreateTextureFromFile( ID3D11Device* pDevice, ID3D11DeviceContext *pContext, LPCSTR pSrcFile, + ID3D11ShaderResourceView** ppOutputRV, bool bSRGB=false ); + HRESULT CreateTextureFromFileEx( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, UINT Width, + UINT Height, UINT MipLevels, DWORD Usage, D3DFORMAT Format, + D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, PALETTEENTRY* pPalette, + LPDIRECT3DTEXTURE9* ppTexture ); + HRESULT CreateTextureFromFileEx( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, LPCTSTR pSrcFile, + D3DX11_IMAGE_LOAD_INFO* pLoadInfo, ID3DX11ThreadPump* pPump, + ID3D11ShaderResourceView** ppOutputRV, bool bSRGB ); + HRESULT CreateTextureFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, + LPCTSTR pSrcResource, LPDIRECT3DTEXTURE9* ppTexture ); + HRESULT CreateTextureFromResourceEx( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, + LPCTSTR pSrcResource, UINT Width, UINT Height, UINT MipLevels, + DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, + DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, LPDIRECT3DTEXTURE9* ppTexture ); + HRESULT CreateCubeTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture ); + HRESULT CreateCubeTextureFromFileEx( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, UINT Size, + UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, + DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, PALETTEENTRY* pPalette, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture ); + HRESULT CreateCubeTextureFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, + LPCTSTR pSrcResource, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture ); + HRESULT CreateCubeTextureFromResourceEx( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, + LPCTSTR pSrcResource, UINT Size, UINT MipLevels, + DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, + DWORD MipFilter, D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, PALETTEENTRY* pPalette, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture ); + HRESULT CreateVolumeTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture ); + HRESULT CreateVolumeTextureFromFileEx( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, UINT Width, + UINT Height, UINT Depth, UINT MipLevels, DWORD Usage, + D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, + DWORD MipFilter, D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, PALETTEENTRY* pPalette, + LPDIRECT3DVOLUMETEXTURE9* ppTexture ); + HRESULT CreateVolumeTextureFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, + LPCTSTR pSrcResource, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture ); + HRESULT CreateVolumeTextureFromResourceEx( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, + LPCTSTR pSrcResource, UINT Width, UINT Height, + UINT Depth, UINT MipLevels, DWORD Usage, + D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, + DWORD MipFilter, D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, PALETTEENTRY* pPalette, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture ); + HRESULT CreateFont( LPDIRECT3DDEVICE9 pDevice, UINT Height, UINT Width, UINT Weight, + UINT MipLevels, BOOL Italic, DWORD CharSet, DWORD OutputPrecision, + DWORD Quality, DWORD PitchAndFamily, LPCTSTR pFacename, LPD3DXFONT* ppFont ); + HRESULT CreateFontIndirect( LPDIRECT3DDEVICE9 pDevice, CONST D3DXFONT_DESC *pDesc, LPD3DXFONT *ppFont ); + HRESULT CreateEffectFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, + const D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, + LPD3DXEFFECTPOOL pPool, LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors ); + HRESULT CreateEffectFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, + LPCTSTR pSrcResource, const D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, LPD3DXBUFFER* ppCompilationErrors ); + +public: + HRESULT OnCreateDevice( IDirect3DDevice9* pd3dDevice ); + HRESULT OnResetDevice( IDirect3DDevice9* pd3dDevice ); + HRESULT OnLostDevice(); + HRESULT OnDestroyDevice(); + +protected: + friend CDXUTResourceCache& WINAPI DXUTGetGlobalResourceCache(); + friend HRESULT WINAPI DXUTInitialize3DEnvironment(); + friend HRESULT WINAPI DXUTReset3DEnvironment(); + friend void WINAPI DXUTCleanup3DEnvironment( bool bReleaseSettings ); + + CDXUTResourceCache() + { + } + + CGrowableArray m_TextureCache; + CGrowableArray m_EffectCache; + CGrowableArray m_FontCache; +}; + +CDXUTResourceCache& WINAPI DXUTGetGlobalResourceCache(); + + +//-------------------------------------------------------------------------------------- +// Manages the insertion point when drawing text +//-------------------------------------------------------------------------------------- +class CDXUTDialogResourceManager; +class CDXUTTextHelper +{ +public: + CDXUTTextHelper( ID3DXFont* pFont9 = NULL, ID3DXSprite* pSprite9 = NULL, + int nLineHeight = 15 ); + CDXUTTextHelper( ID3D11Device* pd3d11Device, ID3D11DeviceContext* pd3dDeviceContext, CDXUTDialogResourceManager* pManager, int nLineHeight ); + ~CDXUTTextHelper(); + + void Init( ID3DXFont* pFont9 = NULL, ID3DXSprite* pSprite9 = NULL, + int nLineHeight = 15 ); + + void SetInsertionPos( int x, int y ) + { + m_pt.x = x; m_pt.y = y; + } + void SetForegroundColor( D3DXCOLOR clr ) + { + m_clr = clr; + } + + void Begin(); + HRESULT DrawFormattedTextLine( const WCHAR* strMsg, ... ); + HRESULT DrawTextLine( const WCHAR* strMsg ); + HRESULT DrawFormattedTextLine( RECT& rc, DWORD dwFlags, const WCHAR* strMsg, ... ); + HRESULT DrawTextLine( RECT& rc, DWORD dwFlags, const WCHAR* strMsg ); + void End(); + +protected: + ID3DXFont* m_pFont9; + ID3DXSprite* m_pSprite9; + D3DXCOLOR m_clr; + POINT m_pt; + int m_nLineHeight; + + // D3D11 font + ID3D11Device* m_pd3d11Device; + ID3D11DeviceContext* m_pd3d11DeviceContext; + CDXUTDialogResourceManager* m_pManager; +}; + + +//-------------------------------------------------------------------------------------- +// Manages a persistent list of lines and draws them using ID3DXLine +//-------------------------------------------------------------------------------------- +class CDXUTLineManager +{ +public: + CDXUTLineManager(); + ~CDXUTLineManager(); + + HRESULT OnCreatedDevice( IDirect3DDevice9* pd3dDevice ); + HRESULT OnResetDevice(); + HRESULT OnRender(); + HRESULT OnLostDevice(); + HRESULT OnDeletedDevice(); + + HRESULT AddLine( int* pnLineID, D3DXVECTOR2* pVertexList, DWORD dwVertexListCount, D3DCOLOR Color, float fWidth, + float fScaleRatio, bool bAntiAlias ); + HRESULT AddRect( int* pnLineID, RECT rc, D3DCOLOR Color, float fWidth, float fScaleRatio, bool bAntiAlias ); + HRESULT RemoveLine( int nLineID ); + HRESULT RemoveAllLines(); + +protected: + struct LINE_NODE + { + int nLineID; + D3DCOLOR Color; + float fWidth; + bool bAntiAlias; + float fScaleRatio; + D3DXVECTOR2* pVertexList; + DWORD dwVertexListCount; + }; + + CGrowableArray m_LinesList; + IDirect3DDevice9* m_pd3dDevice; + ID3DXLine* m_pD3DXLine; +}; + + +//-------------------------------------------------------------------------------------- +// Shared code for samples to ask user if they want to use a REF device or quit +//-------------------------------------------------------------------------------------- +void WINAPI DXUTDisplaySwitchingToREFWarning( DXUTDeviceVersion ver ); + +//-------------------------------------------------------------------------------------- +// Tries to finds a media file by searching in common locations +//-------------------------------------------------------------------------------------- +HRESULT WINAPI DXUTFindDXSDKMediaFileCch( __in_ecount(cchDest) WCHAR* strDestPath, + int cchDest, + __in LPCWSTR strFilename ); +HRESULT WINAPI DXUTSetMediaSearchPath( LPCWSTR strPath ); +LPCWSTR WINAPI DXUTGetMediaSearchPath(); + + +//-------------------------------------------------------------------------------------- +// Returns a view matrix for rendering to a face of a cubemap. +//-------------------------------------------------------------------------------------- +D3DXMATRIX WINAPI DXUTGetCubeMapViewMatrix( DWORD dwFace ); + + +//-------------------------------------------------------------------------------------- +// Simple helper stack class +//-------------------------------------------------------------------------------------- +template class CDXUTStack +{ +private: + UINT m_MemorySize; + UINT m_NumElements; + T* m_pData; + + bool EnsureStackSize( UINT64 iElements ) + { + if( m_MemorySize > iElements ) + return true; + + T* pTemp = new T[ ( size_t )( iElements * 2 + 256 ) ]; + if( !pTemp ) + return false; + + if( m_NumElements ) + { + CopyMemory( pTemp, m_pData, ( size_t )( m_NumElements * sizeof( T ) ) ); + } + + if( m_pData ) delete []m_pData; + m_pData = pTemp; + return true; + } + +public: + CDXUTStack() + { + m_pData = NULL; m_NumElements = 0; m_MemorySize = 0; + } + ~CDXUTStack() + { + if( m_pData ) delete []m_pData; + } + + UINT GetCount() + { + return m_NumElements; + } + T GetAt( UINT i ) + { + return m_pData[i]; + } + T GetTop() + { + if( m_NumElements < 1 ) + return NULL; + + return m_pData[ m_NumElements - 1 ]; + } + + T GetRelative( INT i ) + { + INT64 iVal = m_NumElements - 1 + i; + if( iVal < 0 ) + return NULL; + return m_pData[ iVal ]; + } + + bool Push( T pElem ) + { + if( !EnsureStackSize( m_NumElements + 1 ) ) + return false; + + m_pData[m_NumElements] = pElem; + m_NumElements++; + + return true; + } + + T Pop() + { + if( m_NumElements < 1 ) + return NULL; + + m_NumElements --; + return m_pData[m_NumElements]; + } +}; + + +#endif diff --git a/Demos/DX11ClothDemo/DXUT/Optional/SDKsound.cpp b/Demos/DX11ClothDemo/DXUT/Optional/SDKsound.cpp new file mode 100644 index 0000000..a1256c7 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/SDKsound.cpp @@ -0,0 +1,1053 @@ +//----------------------------------------------------------------------------- +// File: DXUTsound.cpp +// +// Desc: DirectSound framework classes for playing wav files in DirectSound +// buffers. Feel free to use these classes as a starting point for adding +// extra functionality. +// +// Copyright (c) Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include "DXUT.h" +#include +#include +#include "SDKsound.h" +#include "SDKwavefile.h" +#undef min // use __min instead +#undef max // use __max instead + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CSoundManager() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSoundManager::CSoundManager() +{ + m_pDS = NULL; +} + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::~CSoundManager() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSoundManager::~CSoundManager() +{ + SAFE_RELEASE( m_pDS ); +} + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Initialize() +// Desc: Initializes the IDirectSound object and also sets the primary buffer +// format. This function must be called before any others. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Initialize( HWND hWnd, + DWORD dwCoopLevel ) +{ + HRESULT hr; + + SAFE_RELEASE( m_pDS ); + + // Create IDirectSound using the primary sound device + if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) ) + return DXUT_ERR( L"DirectSoundCreate8", hr ); + + // Set DirectSound coop level + if( FAILED( hr = m_pDS->SetCooperativeLevel( hWnd, dwCoopLevel ) ) ) + return DXUT_ERR( L"SetCooperativeLevel", hr ); + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::SetPrimaryBufferFormat() +// Desc: Set primary buffer to a specified format +// !WARNING! - Setting the primary buffer format and then using this +// same DirectSound object for DirectMusic messes up +// DirectMusic! +// For example, to set the primary buffer format to 22kHz stereo, 16-bit +// then: dwPrimaryChannels = 2 +// dwPrimaryFreq = 22050, +// dwPrimaryBitRate = 16 +//----------------------------------------------------------------------------- +HRESULT CSoundManager::SetPrimaryBufferFormat( DWORD dwPrimaryChannels, + DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ) +{ + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + // Get the primary buffer + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof( DSBUFFERDESC ) ); + dsbd.dwSize = sizeof( DSBUFFERDESC ); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbd.dwBufferBytes = 0; + dsbd.lpwfxFormat = NULL; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) + return DXUT_ERR( L"CreateSoundBuffer", hr ); + + WAVEFORMATEX wfx; + ZeroMemory( &wfx, sizeof( WAVEFORMATEX ) ); + wfx.wFormatTag = ( WORD )WAVE_FORMAT_PCM; + wfx.nChannels = ( WORD )dwPrimaryChannels; + wfx.nSamplesPerSec = ( DWORD )dwPrimaryFreq; + wfx.wBitsPerSample = ( WORD )dwPrimaryBitRate; + wfx.nBlockAlign = ( WORD )( wfx.wBitsPerSample / 8 * wfx.nChannels ); + wfx.nAvgBytesPerSec = ( DWORD )( wfx.nSamplesPerSec * wfx.nBlockAlign ); + + if( FAILED( hr = pDSBPrimary->SetFormat( &wfx ) ) ) + return DXUT_ERR( L"SetFormat", hr ); + + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Get3DListenerInterface() +// Desc: Returns the 3D listener interface associated with primary buffer. +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ) +{ + HRESULT hr; + DSBUFFERDESC dsbdesc; + LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; + + if( ppDSListener == NULL ) + return E_INVALIDARG; + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + + *ppDSListener = NULL; + + // Obtain primary buffer, asking it for 3D control + ZeroMemory( &dsbdesc, sizeof( DSBUFFERDESC ) ); + dsbdesc.dwSize = sizeof( DSBUFFERDESC ); + dsbdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbdesc, &pDSBPrimary, NULL ) ) ) + return DXUT_ERR( L"CreateSoundBuffer", hr ); + + if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, + ( VOID** )ppDSListener ) ) ) + { + SAFE_RELEASE( pDSBPrimary ); + return DXUT_ERR( L"QueryInterface", hr ); + } + + // Release the primary buffer, since it is not need anymore + SAFE_RELEASE( pDSBPrimary ); + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::Create() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::Create( CSound** ppSound, + LPWSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + HRESULT hrRet = S_OK; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + if( pWaveFile->GetSize() == 0 ) + { + // Wave is blank, so don't create it. + hr = E_FAIL; + goto LFail; + } + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = pWaveFile->GetSize(); + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof( DSBUFFERDESC ) ); + dsbd.dwSize = sizeof( DSBUFFERDESC ); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + // DirectSound is only guarenteed to play PCM data. Other + // formats may or may not work depending the sound card driver. + hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ); + + // Be sure to return this error code if it occurs so the + // callers knows this happened. + if( hr == DS_NO_VIRTUALIZATION ) + hrRet = DS_NO_VIRTUALIZATION; + + if( FAILED( hr ) ) + { + // DSERR_BUFFERTOOSMALL will be returned if the buffer is + // less than DSBSIZE_FX_MIN and the buffer is created + // with DSBCAPS_CTRLFX. + + // It might also fail if hardware buffer mixing was requested + // on a device that doesn't support it. + DXUT_ERR( L"CreateSoundBuffer", hr ); + + goto LFail; + } + + // Default to use DuplicateSoundBuffer() when created extra buffers since always + // create a buffer that uses the same memory however DuplicateSoundBuffer() will fail if + // DSBCAPS_CTRLFX is used, so use CreateSoundBuffer() instead in this case. + if( ( dwCreationFlags & DSBCAPS_CTRLFX ) == 0 ) + { + for( i = 1; i < dwNumBuffers; i++ ) + { + if( FAILED( hr = m_pDS->DuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXUT_ERR( L"DuplicateSoundBuffer", hr ); + goto LFail; + } + } + } + else + { + for( i = 1; i < dwNumBuffers; i++ ) + { + hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[i], NULL ); + if( FAILED( hr ) ) + { + DXUT_ERR( L"CreateSoundBuffer", hr ); + goto LFail; + } + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile, dwCreationFlags ); + + SAFE_DELETE_ARRAY( apDSBuffer ); + return hrRet; + +LFail: + // Cleanup + SAFE_DELETE( pWaveFile ); + SAFE_DELETE_ARRAY( apDSBuffer ); + return hr; +} + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateFromMemory() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateFromMemory( CSound** ppSound, + BYTE* pbData, + ULONG ulDataSize, + LPWAVEFORMATEX pwfx, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNumBuffers ) +{ + HRESULT hr; + DWORD i; + LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( pbData == NULL || ppSound == NULL || dwNumBuffers < 1 ) + return E_INVALIDARG; + + apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( apDSBuffer == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + { + hr = E_OUTOFMEMORY; + goto LFail; + } + + pWaveFile->OpenFromMemory( pbData, ulDataSize, pwfx, WAVEFILE_READ ); + + + // Make the DirectSound buffer the same size as the wav file + dwDSBufferSize = ulDataSize; + + // Create the direct sound buffer, and only request the flags needed + // since each requires some overhead and limits if the buffer can + // be hardware accelerated + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof( DSBUFFERDESC ) ); + dsbd.dwSize = sizeof( DSBUFFERDESC ); + dsbd.dwFlags = dwCreationFlags; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ) ) ) + { + DXUT_ERR( L"CreateSoundBuffer", hr ); + goto LFail; + } + + // Default to use DuplicateSoundBuffer() when created extra buffers since always + // create a buffer that uses the same memory however DuplicateSoundBuffer() will fail if + // DSBCAPS_CTRLFX is used, so use CreateSoundBuffer() instead in this case. + if( ( dwCreationFlags & DSBCAPS_CTRLFX ) == 0 ) + { + for( i = 1; i < dwNumBuffers; i++ ) + { + if( FAILED( hr = m_pDS->DuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) + { + DXUT_ERR( L"DuplicateSoundBuffer", hr ); + goto LFail; + } + } + } + else + { + for( i = 1; i < dwNumBuffers; i++ ) + { + hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[i], NULL ); + if( FAILED( hr ) ) + { + DXUT_ERR( L"CreateSoundBuffer", hr ); + goto LFail; + } + } + } + + // Create the sound + *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile, dwCreationFlags ); + + SAFE_DELETE_ARRAY( apDSBuffer ); + return S_OK; + +LFail: + // Cleanup + + SAFE_DELETE_ARRAY( apDSBuffer ); + return hr; +} + + +//----------------------------------------------------------------------------- +// Name: CSoundManager::CreateStreaming() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, + LPWSTR strWaveFileName, + DWORD dwCreationFlags, + GUID guid3DAlgorithm, + DWORD dwNotifyCount, + DWORD dwNotifySize, + HANDLE hNotifyEvent ) +{ + HRESULT hr; + + if( m_pDS == NULL ) + return CO_E_NOTINITIALIZED; + if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL ) + return E_INVALIDARG; + + LPDIRECTSOUNDBUFFER pDSBuffer = NULL; + DWORD dwDSBufferSize = NULL; + CWaveFile* pWaveFile = NULL; + DSBPOSITIONNOTIFY* aPosNotify = NULL; + LPDIRECTSOUNDNOTIFY pDSNotify = NULL; + + pWaveFile = new CWaveFile(); + if( pWaveFile == NULL ) + return E_OUTOFMEMORY; + pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); + + // Figure out how big the DirectSound buffer should be + dwDSBufferSize = dwNotifySize * dwNotifyCount; + + // Set up the direct sound buffer. Request the NOTIFY flag, so + // that we are notified as the sound buffer plays. Note, that using this flag + // may limit the amount of hardware acceleration that can occur. + DSBUFFERDESC dsbd; + ZeroMemory( &dsbd, sizeof( DSBUFFERDESC ) ); + dsbd.dwSize = sizeof( DSBUFFERDESC ); + dsbd.dwFlags = dwCreationFlags | + DSBCAPS_CTRLPOSITIONNOTIFY | + DSBCAPS_GETCURRENTPOSITION2; + dsbd.dwBufferBytes = dwDSBufferSize; + dsbd.guid3DAlgorithm = guid3DAlgorithm; + dsbd.lpwfxFormat = pWaveFile->m_pwfx; + + if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) ) + { + // If wave format isn't then it will return + // either DSERR_BADFORMAT or E_INVALIDARG + if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG ) + return DXUT_ERR( L"CreateSoundBuffer", hr ); + + return DXUT_ERR( L"CreateSoundBuffer", hr ); + } + + // Create the notification events, so that we know when to fill + // the buffer as the sound plays. + if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, + ( VOID** )&pDSNotify ) ) ) + { + SAFE_DELETE_ARRAY( aPosNotify ); + return DXUT_ERR( L"QueryInterface", hr ); + } + + aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ]; + if( aPosNotify == NULL ) + return E_OUTOFMEMORY; + + for( DWORD i = 0; i < dwNotifyCount; i++ ) + { + aPosNotify[i].dwOffset = ( dwNotifySize * i ) + dwNotifySize - 1; + aPosNotify[i].hEventNotify = hNotifyEvent; + } + + // Tell DirectSound when to notify us. The notification will come in the from + // of signaled events that are handled in WinMain() + if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount, + aPosNotify ) ) ) + { + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE_ARRAY( aPosNotify ); + return DXUT_ERR( L"SetNotificationPositions", hr ); + } + + SAFE_RELEASE( pDSNotify ); + SAFE_DELETE_ARRAY( aPosNotify ); + + // Create the sound + *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize ); + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: CSound::CSound() +// Desc: Constructs the class +//----------------------------------------------------------------------------- +CSound::CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, + DWORD dwNumBuffers, CWaveFile* pWaveFile, DWORD dwCreationFlags ) +{ + DWORD i; + + if( dwNumBuffers <= 0 ) + return; + + m_apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; + if( NULL != m_apDSBuffer ) + { + for( i = 0; i < dwNumBuffers; i++ ) + m_apDSBuffer[i] = apDSBuffer[i]; + + m_dwDSBufferSize = dwDSBufferSize; + m_dwNumBuffers = dwNumBuffers; + m_pWaveFile = pWaveFile; + m_dwCreationFlags = dwCreationFlags; + + FillBufferWithSound( m_apDSBuffer[0], FALSE ); + } +} + + +//----------------------------------------------------------------------------- +// Name: CSound::~CSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CSound::~CSound() +{ + for( DWORD i = 0; i < m_dwNumBuffers; i++ ) + { + SAFE_RELEASE( m_apDSBuffer[i] ); + } + + SAFE_DELETE_ARRAY( m_apDSBuffer ); + SAFE_DELETE( m_pWaveFile ); +} + + +//----------------------------------------------------------------------------- +// Name: CSound::FillBufferWithSound() +// Desc: Fills a DirectSound buffer with a sound file +//----------------------------------------------------------------------------- +HRESULT CSound::FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger ) +{ + HRESULT hr; + VOID* pDSLockedBuffer = NULL; // Pointer to locked buffer memory + DWORD dwDSLockedBufferSize = 0; // Size of the locked DirectSound buffer + DWORD dwWavDataRead = 0; // Amount of data read from the wav file + + if( pDSB == NULL ) + return CO_E_NOTINITIALIZED; + + // Make sure we have focus, and we didn't just switch in from + // an app which had a DirectSound device + if( FAILED( hr = RestoreBuffer( pDSB, NULL ) ) ) + return DXUT_ERR( L"RestoreBuffer", hr ); + + // Lock the buffer down + if( FAILED( hr = pDSB->Lock( 0, m_dwDSBufferSize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + NULL, NULL, 0L ) ) ) + return DXUT_ERR( L"Lock", hr ); + + // Reset the wave file to the beginning + m_pWaveFile->ResetFile(); + + if( FAILED( hr = m_pWaveFile->Read( ( BYTE* )pDSLockedBuffer, + dwDSLockedBufferSize, + &dwWavDataRead ) ) ) + return DXUT_ERR( L"Read", hr ); + + if( dwWavDataRead == 0 ) + { + // Wav is blank, so just fill with silence + FillMemory( ( BYTE* )pDSLockedBuffer, + dwDSLockedBufferSize, + ( BYTE )( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + else if( dwWavDataRead < dwDSLockedBufferSize ) + { + // If the wav file was smaller than the DirectSound buffer, + // we need to fill the remainder of the buffer with data + if( bRepeatWavIfBufferLarger ) + { + // Reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwWavDataRead; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full + // for very short files + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXUT_ERR( L"ResetFile", hr ); + + hr = m_pWaveFile->Read( ( BYTE* )pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwWavDataRead ); + if( FAILED( hr ) ) + return DXUT_ERR( L"Read", hr ); + + dwReadSoFar += dwWavDataRead; + } + } + else + { + // Don't repeat the wav file, just fill in silence + FillMemory( ( BYTE* )pDSLockedBuffer + dwWavDataRead, + dwDSLockedBufferSize - dwWavDataRead, + ( BYTE )( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + } + } + + // Unlock the buffer, we don't need it anymore. + pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: CSound::RestoreBuffer() +// Desc: Restores the lost buffer. *pbWasRestored returns TRUE if the buffer was +// restored. It can also NULL if the information is not needed. +//----------------------------------------------------------------------------- +HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ) +{ + HRESULT hr; + + if( pDSB == NULL ) + return CO_E_NOTINITIALIZED; + if( pbWasRestored ) + *pbWasRestored = FALSE; + + DWORD dwStatus; + if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) ) + return DXUT_ERR( L"GetStatus", hr ); + + if( dwStatus & DSBSTATUS_BUFFERLOST ) + { + // Since the app could have just been activated, then + // DirectSound may not be giving us control yet, so + // the restoring the buffer may fail. + // If it does, sleep until DirectSound gives us control. + do + { + hr = pDSB->Restore(); + if( hr == DSERR_BUFFERLOST ) + Sleep( 10 ); + } while( ( hr = pDSB->Restore() ) == DSERR_BUFFERLOST ); + + if( pbWasRestored != NULL ) + *pbWasRestored = TRUE; + + return S_OK; + } + else + { + return S_FALSE; + } +} + + +//----------------------------------------------------------------------------- +// Name: CSound::GetFreeBuffer() +// Desc: Finding the first buffer that is not playing and return a pointer to +// it, or if all are playing return a pointer to a randomly selected buffer. +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetFreeBuffer() +{ + if( m_apDSBuffer == NULL ) + return FALSE; + + DWORD i; + for( i = 0; i < m_dwNumBuffers; i++ ) + { + if( m_apDSBuffer[i] ) + { + DWORD dwStatus = 0; + m_apDSBuffer[i]->GetStatus( &dwStatus ); + if( ( dwStatus & DSBSTATUS_PLAYING ) == 0 ) + break; + } + } + + if( i != m_dwNumBuffers ) + return m_apDSBuffer[ i ]; + else + return m_apDSBuffer[ rand() % m_dwNumBuffers ]; +} + + +//----------------------------------------------------------------------------- +// Name: CSound::GetBuffer() +// Desc: +//----------------------------------------------------------------------------- +LPDIRECTSOUNDBUFFER CSound::GetBuffer( DWORD dwIndex ) +{ + if( m_apDSBuffer == NULL ) + return NULL; + if( dwIndex >= m_dwNumBuffers ) + return NULL; + + return m_apDSBuffer[dwIndex]; +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Get3DBufferInterface() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CSound::Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ) +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + if( dwIndex >= m_dwNumBuffers ) + return E_INVALIDARG; + + *ppDS3DBuffer = NULL; + + return m_apDSBuffer[dwIndex]->QueryInterface( IID_IDirectSound3DBuffer, + ( VOID** )ppDS3DBuffer ); +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Play() +// Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING +// in the dwFlags to loop the sound +//----------------------------------------------------------------------------- +HRESULT CSound::Play( DWORD dwPriority, DWORD dwFlags, LONG lVolume, LONG lFrequency, LONG lPan ) +{ + HRESULT hr; + BOOL bRestored; + + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer(); + + if( pDSB == NULL ) + return DXUT_ERR( L"GetFreeBuffer", E_FAIL ); + + // Restore the buffer if it was lost + if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) ) + return DXUT_ERR( L"RestoreBuffer", hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) ) + return DXUT_ERR( L"FillBufferWithSound", hr ); + } + + if( m_dwCreationFlags & DSBCAPS_CTRLVOLUME ) + { + pDSB->SetVolume( lVolume ); + } + + if( lFrequency != -1 && + ( m_dwCreationFlags & DSBCAPS_CTRLFREQUENCY ) ) + { + pDSB->SetFrequency( lFrequency ); + } + + if( m_dwCreationFlags & DSBCAPS_CTRLPAN ) + { + pDSB->SetPan( lPan ); + } + + return pDSB->Play( 0, dwPriority, dwFlags ); +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Play3D() +// Desc: Plays the sound using voice management flags. Pass in DSBPLAY_LOOPING +// in the dwFlags to loop the sound +//----------------------------------------------------------------------------- +HRESULT CSound::Play3D( LPDS3DBUFFER p3DBuffer, DWORD dwPriority, DWORD dwFlags, LONG lFrequency ) +{ + HRESULT hr; + BOOL bRestored; + DWORD dwBaseFrequency; + + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer(); + if( pDSB == NULL ) + return DXUT_ERR( L"GetFreeBuffer", E_FAIL ); + + // Restore the buffer if it was lost + if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) ) + return DXUT_ERR( L"RestoreBuffer", hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) ) + return DXUT_ERR( L"FillBufferWithSound", hr ); + } + + if( m_dwCreationFlags & DSBCAPS_CTRLFREQUENCY ) + { + pDSB->GetFrequency( &dwBaseFrequency ); + pDSB->SetFrequency( dwBaseFrequency + lFrequency ); + } + + // QI for the 3D buffer + LPDIRECTSOUND3DBUFFER pDS3DBuffer; + hr = pDSB->QueryInterface( IID_IDirectSound3DBuffer, ( VOID** )&pDS3DBuffer ); + if( SUCCEEDED( hr ) ) + { + hr = pDS3DBuffer->SetAllParameters( p3DBuffer, DS3D_IMMEDIATE ); + if( SUCCEEDED( hr ) ) + { + hr = pDSB->Play( 0, dwPriority, dwFlags ); + } + + pDS3DBuffer->Release(); + } + + return hr; +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Stop() +// Desc: Stops the sound from playing +//----------------------------------------------------------------------------- +HRESULT CSound::Stop() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i = 0; i < m_dwNumBuffers; i++ ) + hr |= m_apDSBuffer[i]->Stop(); + + return hr; +} + + +//----------------------------------------------------------------------------- +// Name: CSound::Reset() +// Desc: Reset all of the sound buffers +//----------------------------------------------------------------------------- +HRESULT CSound::Reset() +{ + if( m_apDSBuffer == NULL ) + return CO_E_NOTINITIALIZED; + + HRESULT hr = 0; + + for( DWORD i = 0; i < m_dwNumBuffers; i++ ) + hr |= m_apDSBuffer[i]->SetCurrentPosition( 0 ); + + return hr; +} + + +//----------------------------------------------------------------------------- +// Name: CSound::IsSoundPlaying() +// Desc: Checks to see if a buffer is playing and returns TRUE if it is. +//----------------------------------------------------------------------------- +BOOL CSound::IsSoundPlaying() +{ + BOOL bIsPlaying = FALSE; + + if( m_apDSBuffer == NULL ) + return FALSE; + + for( DWORD i = 0; i < m_dwNumBuffers; i++ ) + { + if( m_apDSBuffer[i] ) + { + DWORD dwStatus = 0; + m_apDSBuffer[i]->GetStatus( &dwStatus ); + bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ); + } + } + + return bIsPlaying; +} + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::CStreamingSound() +// Desc: Setups up a buffer so data can be streamed from the wave file into +// a buffer. This is very useful for large wav files that would take a +// while to load. The buffer is initially filled with data, then +// as sound is played the notification events are signaled and more data +// is written into the buffer by calling HandleWaveStreamNotification() +//----------------------------------------------------------------------------- +CStreamingSound::CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, + CWaveFile* pWaveFile, DWORD dwNotifySize ) : CSound( &pDSBuffer, dwDSBufferSize, 1, + pWaveFile, 0 ) +{ + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNotifySize = dwNotifySize; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; +} + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::~CStreamingSound() +// Desc: Destroys the class +//----------------------------------------------------------------------------- +CStreamingSound::~CStreamingSound() +{ +} + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::HandleWaveStreamNotification() +// Desc: Handle the notification that tells us to put more wav data in the +// circular buffer +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::HandleWaveStreamNotification( BOOL bLoopedPlay ) +{ + HRESULT hr; + DWORD dwCurrentPlayPos; + DWORD dwPlayDelta; + DWORD dwBytesWrittenToBuffer; + VOID* pDSLockedBuffer = NULL; + VOID* pDSLockedBuffer2 = NULL; + DWORD dwDSLockedBufferSize; + DWORD dwDSLockedBufferSize2; + + if( m_apDSBuffer == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXUT_ERR( L"RestoreBuffer", hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXUT_ERR( L"FillBufferWithSound", hr ); + return S_OK; + } + + // Lock the DirectSound buffer + if( FAILED( hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize, + &pDSLockedBuffer, &dwDSLockedBufferSize, + &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) ) + return DXUT_ERR( L"Lock", hr ); + + // m_dwDSBufferSize and m_dwNextWriteOffset are both multiples of m_dwNotifySize, + // it should the second buffer, so it should never be valid + if( pDSLockedBuffer2 != NULL ) + return E_UNEXPECTED; + + if( !m_bFillNextNotificationWithSilence ) + { + // Fill the DirectSound buffer with wav data + if( FAILED( hr = m_pWaveFile->Read( ( BYTE* )pDSLockedBuffer, + dwDSLockedBufferSize, + &dwBytesWrittenToBuffer ) ) ) + return DXUT_ERR( L"Read", hr ); + } + else + { + // Fill the DirectSound buffer with silence + FillMemory( pDSLockedBuffer, dwDSLockedBufferSize, + ( BYTE )( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + dwBytesWrittenToBuffer = dwDSLockedBufferSize; + } + + // If the number of bytes written is less than the + // amount we requested, we have a short file. + if( dwBytesWrittenToBuffer < dwDSLockedBufferSize ) + { + if( !bLoopedPlay ) + { + // Fill in silence for the rest of the buffer. + FillMemory( ( BYTE* )pDSLockedBuffer + dwBytesWrittenToBuffer, + dwDSLockedBufferSize - dwBytesWrittenToBuffer, + ( BYTE )( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); + + // Any future notifications should just fill the buffer with silence + m_bFillNextNotificationWithSilence = TRUE; + } + else + { + // We are looping, so reset the file and fill the buffer with wav data + DWORD dwReadSoFar = dwBytesWrittenToBuffer; // From previous call above. + while( dwReadSoFar < dwDSLockedBufferSize ) + { + // This will keep reading in until the buffer is full (for very short files). + if( FAILED( hr = m_pWaveFile->ResetFile() ) ) + return DXUT_ERR( L"ResetFile", hr ); + + if( FAILED( hr = m_pWaveFile->Read( ( BYTE* )pDSLockedBuffer + dwReadSoFar, + dwDSLockedBufferSize - dwReadSoFar, + &dwBytesWrittenToBuffer ) ) ) + return DXUT_ERR( L"Read", hr ); + + dwReadSoFar += dwBytesWrittenToBuffer; + } + } + } + + // Unlock the DirectSound buffer + m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); + + // Figure out how much data has been played so far. When we have played + // past the end of the file, we will either need to start filling the + // buffer with silence or starting reading from the beginning of the file, + // depending if the user wants to loop the sound + if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) ) + return DXUT_ERR( L"GetCurrentPosition", hr ); + + // Check to see if the position counter looped + if( dwCurrentPlayPos < m_dwLastPlayPos ) + dwPlayDelta = ( m_dwDSBufferSize - m_dwLastPlayPos ) + dwCurrentPlayPos; + else + dwPlayDelta = dwCurrentPlayPos - m_dwLastPlayPos; + + m_dwPlayProgress += dwPlayDelta; + m_dwLastPlayPos = dwCurrentPlayPos; + + // If we are now filling the buffer with silence, then we have found the end so + // check to see if the entire sound has played, if it has then stop the buffer. + if( m_bFillNextNotificationWithSilence ) + { + // We don't want to cut off the sound before it's done playing. + if( m_dwPlayProgress >= m_pWaveFile->GetSize() ) + { + m_apDSBuffer[0]->Stop(); + } + } + + // Update where the buffer will lock (for next time) + m_dwNextWriteOffset += dwDSLockedBufferSize; + m_dwNextWriteOffset %= m_dwDSBufferSize; // Circular buffer + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: CStreamingSound::Reset() +// Desc: Resets the sound so it will begin playing at the beginning +//----------------------------------------------------------------------------- +HRESULT CStreamingSound::Reset() +{ + HRESULT hr; + + if( m_apDSBuffer[0] == NULL || m_pWaveFile == NULL ) + return CO_E_NOTINITIALIZED; + + m_dwLastPlayPos = 0; + m_dwPlayProgress = 0; + m_dwNextWriteOffset = 0; + m_bFillNextNotificationWithSilence = FALSE; + + // Restore the buffer if it was lost + BOOL bRestored; + if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) + return DXUT_ERR( L"RestoreBuffer", hr ); + + if( bRestored ) + { + // The buffer was restored, so we need to fill it with new data + if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) + return DXUT_ERR( L"FillBufferWithSound", hr ); + } + + m_pWaveFile->ResetFile(); + + return m_apDSBuffer[0]->SetCurrentPosition( 0L ); +} diff --git a/Demos/DX11ClothDemo/DXUT/Optional/SDKsound.h b/Demos/DX11ClothDemo/DXUT/Optional/SDKsound.h new file mode 100644 index 0000000..b79054a --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/SDKsound.h @@ -0,0 +1,124 @@ +//----------------------------------------------------------------------------- +// File: DXUTsound.h +// +// Copyright (c) Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#ifndef DXUTSOUND_H +#define DXUTSOUND_H + +//----------------------------------------------------------------------------- +// Header Includes +//----------------------------------------------------------------------------- +#include +#include + +//----------------------------------------------------------------------------- +// Classes used by this header +//----------------------------------------------------------------------------- +class CSoundManager; +class CSound; +class CStreamingSound; +class CWaveFile; + + +//----------------------------------------------------------------------------- +// Typing macros +//----------------------------------------------------------------------------- +#define DXUT_StopSound(s) { if(s) s->Stop(); } +#define DXUT_PlaySound(s) { if(s) s->Play( 0, 0 ); } +#define DXUT_PlaySoundLooping(s) { if(s) s->Play( 0, DSBPLAY_LOOPING ); } + + +//----------------------------------------------------------------------------- +// Name: class CSoundManager +// Desc: +//----------------------------------------------------------------------------- +class CSoundManager +{ +protected: + IDirectSound8* m_pDS; + +public: + CSoundManager(); + ~CSoundManager(); + + HRESULT Initialize( HWND hWnd, DWORD dwCoopLevel ); + inline LPDIRECTSOUND8 GetDirectSound() + { + return m_pDS; + } + HRESULT SetPrimaryBufferFormat( DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, + DWORD dwPrimaryBitRate ); + HRESULT Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener ); + + HRESULT Create( CSound** ppSound, LPWSTR strWaveFileName, DWORD dwCreationFlags = 0, + GUID guid3DAlgorithm = GUID_NULL, DWORD dwNumBuffers = 1 ); + HRESULT CreateFromMemory( CSound** ppSound, BYTE* pbData, ULONG ulDataSize, LPWAVEFORMATEX pwfx, + DWORD dwCreationFlags = 0, GUID guid3DAlgorithm = GUID_NULL, + DWORD dwNumBuffers = 1 ); + HRESULT CreateStreaming( CStreamingSound** ppStreamingSound, LPWSTR strWaveFileName, + DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNotifyCount, + DWORD dwNotifySize, HANDLE hNotifyEvent ); +}; + + +//----------------------------------------------------------------------------- +// Name: class CSound +// Desc: Encapsulates functionality of a DirectSound buffer. +//----------------------------------------------------------------------------- +class CSound +{ +protected: + LPDIRECTSOUNDBUFFER* m_apDSBuffer; + DWORD m_dwDSBufferSize; + CWaveFile* m_pWaveFile; + DWORD m_dwNumBuffers; + DWORD m_dwCreationFlags; + + HRESULT RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ); + +public: + CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, DWORD dwNumBuffers, + CWaveFile* pWaveFile, DWORD dwCreationFlags ); + virtual ~CSound(); + + HRESULT Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ); + HRESULT FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger ); + LPDIRECTSOUNDBUFFER GetFreeBuffer(); + LPDIRECTSOUNDBUFFER GetBuffer( DWORD dwIndex ); + + HRESULT Play( DWORD dwPriority = 0, DWORD dwFlags = 0, LONG lVolume = 0, LONG lFrequency = -1, + LONG lPan = 0 ); + HRESULT Play3D( LPDS3DBUFFER p3DBuffer, DWORD dwPriority = 0, DWORD dwFlags = 0, LONG lFrequency = 0 ); + HRESULT Stop(); + HRESULT Reset(); + BOOL IsSoundPlaying(); +}; + + +//----------------------------------------------------------------------------- +// Name: class CStreamingSound +// Desc: Encapsulates functionality to play a wave file with DirectSound. +// The Create() method loads a chunk of wave file into the buffer, +// and as sound plays more is written to the buffer by calling +// HandleWaveStreamNotification() whenever hNotifyEvent is signaled. +//----------------------------------------------------------------------------- +class CStreamingSound : public CSound +{ +protected: + DWORD m_dwLastPlayPos; + DWORD m_dwPlayProgress; + DWORD m_dwNotifySize; + DWORD m_dwNextWriteOffset; + BOOL m_bFillNextNotificationWithSilence; + +public: + CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, CWaveFile* pWaveFile, + DWORD dwNotifySize ); + ~CStreamingSound(); + + HRESULT HandleWaveStreamNotification( BOOL bLoopedPlay ); + HRESULT Reset(); +}; + +#endif // DXUTSOUND_H diff --git a/Demos/DX11ClothDemo/DXUT/Optional/SDKwavefile.cpp b/Demos/DX11ClothDemo/DXUT/Optional/SDKwavefile.cpp new file mode 100644 index 0000000..fb2725f --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/SDKwavefile.cpp @@ -0,0 +1,539 @@ +//----------------------------------------------------------------------------- +// File: SDKWaveFile.cpp +// +// Desc: Classes for reading and writing wav files. Feel free to use this class +// as a starting point for adding extra functionality. +// +// XNA Developer Connection +// +// Copyright (c) Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include "DXUT.h" +#include "SDKwavefile.h" +#undef min // use __min instead +#undef max // use __max instead + +//----------------------------------------------------------------------------- +// Name: CWaveFile::CWaveFile() +// Desc: Constructs the class. Call Open() to open a wave file for reading. +// Then call Read() as needed. Calling the destructor or Close() +// will close the file. +//----------------------------------------------------------------------------- +CWaveFile::CWaveFile() +{ + m_pwfx = NULL; + m_hmmio = NULL; + m_pResourceBuffer = NULL; + m_dwSize = 0; + m_bIsReadingFromMemory = FALSE; +} + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::~CWaveFile() +// Desc: Destructs the class +//----------------------------------------------------------------------------- +CWaveFile::~CWaveFile() +{ + Close(); + + if( !m_bIsReadingFromMemory ) + SAFE_DELETE_ARRAY( m_pwfx ); +} + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Open() +// Desc: Opens a wave file for reading +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Open( LPWSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + HRESULT hr; + + m_dwFlags = dwFlags; + m_bIsReadingFromMemory = FALSE; + + if( m_dwFlags == WAVEFILE_READ ) + { + if( strFileName == NULL ) + return E_INVALIDARG; + SAFE_DELETE_ARRAY( m_pwfx ); + + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ ); + + if( NULL == m_hmmio ) + { + HRSRC hResInfo; + HGLOBAL hResData; + DWORD dwSize; + VOID* pvRes; + + // Loading it as a file failed, so try it as a resource + if( NULL == ( hResInfo = FindResource( NULL, strFileName, L"WAVE" ) ) ) + { + if( NULL == ( hResInfo = FindResource( NULL, strFileName, L"WAV" ) ) ) + return DXTRACE_ERR( L"FindResource", E_FAIL ); + } + + if( NULL == ( hResData = LoadResource( GetModuleHandle( NULL ), hResInfo ) ) ) + return DXTRACE_ERR( L"LoadResource", E_FAIL ); + + if( 0 == ( dwSize = SizeofResource( GetModuleHandle( NULL ), hResInfo ) ) ) + return DXTRACE_ERR( L"SizeofResource", E_FAIL ); + + if( NULL == ( pvRes = LockResource( hResData ) ) ) + return DXTRACE_ERR( L"LockResource", E_FAIL ); + + m_pResourceBuffer = new CHAR[ dwSize ]; + if( m_pResourceBuffer == NULL ) + return DXTRACE_ERR( L"new", E_OUTOFMEMORY ); + memcpy( m_pResourceBuffer, pvRes, dwSize ); + + MMIOINFO mmioInfo; + ZeroMemory( &mmioInfo, sizeof( mmioInfo ) ); + mmioInfo.fccIOProc = FOURCC_MEM; + mmioInfo.cchBuffer = dwSize; + mmioInfo.pchBuffer = ( CHAR* )m_pResourceBuffer; + + m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ ); + } + + if( FAILED( hr = ReadMMIO() ) ) + { + // ReadMMIO will fail if its an not a wave file + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR( L"ReadMMIO", hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( L"ResetFile", hr ); + + // After the reset, the size of the wav file is m_ck.cksize so store it now + m_dwSize = m_ck.cksize; + } + else + { + m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | + MMIO_READWRITE | + MMIO_CREATE ); + if( NULL == m_hmmio ) + return DXTRACE_ERR( L"mmioOpen", E_FAIL ); + + if( FAILED( hr = WriteMMIO( pwfx ) ) ) + { + mmioClose( m_hmmio, 0 ); + return DXTRACE_ERR( L"WriteMMIO", hr ); + } + + if( FAILED( hr = ResetFile() ) ) + return DXTRACE_ERR( L"ResetFile", hr ); + } + + return hr; +} + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::OpenFromMemory() +// Desc: copy data to CWaveFile member variable from memory +//----------------------------------------------------------------------------- +HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize, + WAVEFORMATEX* pwfx, DWORD dwFlags ) +{ + m_pwfx = pwfx; + m_ulDataSize = ulDataSize; + m_pbData = pbData; + m_pbDataCur = m_pbData; + m_bIsReadingFromMemory = TRUE; + + if( dwFlags != WAVEFILE_READ ) + return E_NOTIMPL; + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ReadMMIO() +// Desc: Support function for reading from a multimedia I/O stream. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_pwfx. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ReadMMIO() +{ + MMCKINFO ckIn; // chunk info. for general use. + PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. + + m_pwfx = NULL; + + if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) + return DXTRACE_ERR( L"mmioDescend", E_FAIL ); + + // Check to make sure this is a valid wave file + if( ( m_ckRiff.ckid != FOURCC_RIFF ) || + ( m_ckRiff.fccType != mmioFOURCC( 'W', 'A', 'V', 'E' ) ) ) + return DXTRACE_ERR( L"mmioFOURCC", E_FAIL ); + + // Search the input file for for the 'fmt ' chunk. + ckIn.ckid = mmioFOURCC( 'f', 'm', 't', ' ' ); + if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( L"mmioDescend", E_FAIL ); + + // Expect the 'fmt' chunk to be at least as large as ; + // if there are extra parameters at the end, we'll ignore them + if( ckIn.cksize < ( LONG )sizeof( PCMWAVEFORMAT ) ) + return DXTRACE_ERR( L"sizeof(PCMWAVEFORMAT)", E_FAIL ); + + // Read the 'fmt ' chunk into . + if( mmioRead( m_hmmio, ( HPSTR )&pcmWaveFormat, + sizeof( pcmWaveFormat ) ) != sizeof( pcmWaveFormat ) ) + return DXTRACE_ERR( L"mmioRead", E_FAIL ); + + // Allocate the waveformatex, but if its not pcm format, read the next + // word, and thats how many extra bytes to allocate. + if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) + { + m_pwfx = ( WAVEFORMATEX* )new CHAR[ sizeof( WAVEFORMATEX ) ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( L"m_pwfx", E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof( pcmWaveFormat ) ); + m_pwfx->cbSize = 0; + } + else + { + // Read in length of extra bytes. + WORD cbExtraBytes = 0L; + if( mmioRead( m_hmmio, ( CHAR* )&cbExtraBytes, sizeof( WORD ) ) != sizeof( WORD ) ) + return DXTRACE_ERR( L"mmioRead", E_FAIL ); + + m_pwfx = ( WAVEFORMATEX* )new CHAR[ sizeof( WAVEFORMATEX ) + cbExtraBytes ]; + if( NULL == m_pwfx ) + return DXTRACE_ERR( L"new", E_FAIL ); + + // Copy the bytes from the pcm structure to the waveformatex structure + memcpy( m_pwfx, &pcmWaveFormat, sizeof( pcmWaveFormat ) ); + m_pwfx->cbSize = cbExtraBytes; + + // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. + if( mmioRead( m_hmmio, ( CHAR* )( ( ( BYTE* )&( m_pwfx->cbSize ) ) + sizeof( WORD ) ), + cbExtraBytes ) != cbExtraBytes ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( L"mmioRead", E_FAIL ); + } + } + + // Ascend the input file out of the 'fmt ' chunk. + if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) + { + SAFE_DELETE( m_pwfx ); + return DXTRACE_ERR( L"mmioAscend", E_FAIL ); + } + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::GetSize() +// Desc: Retuns the size of the read access wave file +//----------------------------------------------------------------------------- +DWORD CWaveFile::GetSize() +{ + return m_dwSize; +} + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::ResetFile() +// Desc: Resets the internal m_ck pointer so reading starts from the +// beginning of the file again +//----------------------------------------------------------------------------- +HRESULT CWaveFile::ResetFile() +{ + if( m_bIsReadingFromMemory ) + { + m_pbDataCur = m_pbData; + } + else + { + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( m_dwFlags == WAVEFILE_READ ) + { + // Seek to the data + if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof( FOURCC ), + SEEK_SET ) ) + return DXTRACE_ERR( L"mmioSeek", E_FAIL ); + + // Search the input file for the 'data' chunk. + m_ck.ckid = mmioFOURCC( 'd', 'a', 't', 'a' ); + if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + return DXTRACE_ERR( L"mmioDescend", E_FAIL ); + } + else + { + // Create the 'data' chunk that holds the waveform samples. + m_ck.ckid = mmioFOURCC( 'd', 'a', 't', 'a' ); + m_ck.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( L"mmioCreateChunk", E_FAIL ); + + if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( L"mmioGetInfo", E_FAIL ); + } + } + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Read() +// Desc: Reads section of data from a wave file into pBuffer and returns +// how much read in pdwSizeRead, reading not more than dwSizeToRead. +// This uses m_ck to determine where to start reading from. So +// subsequent calls will be continue where the last left off unless +// Reset() is called. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) +{ + if( m_bIsReadingFromMemory ) + { + if( m_pbDataCur == NULL ) + return CO_E_NOTINITIALIZED; + if( pdwSizeRead != NULL ) + *pdwSizeRead = 0; + + if( ( BYTE* )( m_pbDataCur + dwSizeToRead ) > + ( BYTE* )( m_pbData + m_ulDataSize ) ) + { + dwSizeToRead = m_ulDataSize - ( DWORD )( m_pbDataCur - m_pbData ); + } + +#pragma warning( disable: 4616 ) // disable warning about warning number '22104' being out of range +#pragma warning( disable: 22104 ) // disable PREfast warning during static code analysis + CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); +#pragma warning( default: 22104 ) +#pragma warning( default: 4616 ) + + if( pdwSizeRead != NULL ) + *pdwSizeRead = dwSizeToRead; + + return S_OK; + } + else + { + MMIOINFO mmioinfoIn; // current status of m_hmmio + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pBuffer == NULL || pdwSizeRead == NULL ) + return E_INVALIDARG; + + *pdwSizeRead = 0; + + if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( L"mmioGetInfo", E_FAIL ); + + UINT cbDataIn = dwSizeToRead; + if( cbDataIn > m_ck.cksize ) + cbDataIn = m_ck.cksize; + + m_ck.cksize -= cbDataIn; + + for( DWORD cT = 0; cT < cbDataIn; cT++ ) + { + // Copy the bytes from the io to the buffer. + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + { + if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) + return DXTRACE_ERR( L"mmioAdvance", E_FAIL ); + + if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) + return DXTRACE_ERR( L"mmioinfoIn.pchNext", E_FAIL ); + } + + // Actual copy. + *( ( BYTE* )pBuffer + cT ) = *( ( BYTE* )mmioinfoIn.pchNext ); + mmioinfoIn.pchNext++; + } + + if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) + return DXTRACE_ERR( L"mmioSetInfo", E_FAIL ); + + *pdwSizeRead = cbDataIn; + + return S_OK; + } +} + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Close() +// Desc: Closes the wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Close() +{ + if( m_dwFlags == WAVEFILE_READ ) + { + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + SAFE_DELETE_ARRAY( m_pResourceBuffer ); + } + else + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + + if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) + return DXTRACE_ERR( L"mmioSetInfo", E_FAIL ); + + // Ascend the output file out of the 'data' chunk -- this will cause + // the chunk size of the 'data' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( L"mmioAscend", E_FAIL ); + + // Do this here instead... + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( L"mmioAscend", E_FAIL ); + + mmioSeek( m_hmmio, 0, SEEK_SET ); + + if( 0 != ( INT )mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) + return DXTRACE_ERR( L"mmioDescend", E_FAIL ); + + m_ck.ckid = mmioFOURCC( 'f', 'a', 'c', 't' ); + + if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) + { + DWORD dwSamples = 0; + mmioWrite( m_hmmio, ( HPSTR )&dwSamples, sizeof( DWORD ) ); + mmioAscend( m_hmmio, &m_ck, 0 ); + } + + // Ascend the output file out of the 'RIFF' chunk -- this will cause + // the chunk size of the 'RIFF' chunk to be written. + if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) ) + return DXTRACE_ERR( L"mmioAscend", E_FAIL ); + + mmioClose( m_hmmio, 0 ); + m_hmmio = NULL; + } + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::WriteMMIO() +// Desc: Support function for reading from a multimedia I/O stream +// pwfxDest is the WAVEFORMATEX for this new wave file. +// m_hmmio must be valid before calling. This function uses it to +// update m_ckRiff, and m_ck. +//----------------------------------------------------------------------------- +HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX* pwfxDest ) +{ + DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile. + MMCKINFO ckOut1; + + dwFactChunk = ( DWORD )-1; + + // Create the output file RIFF chunk of form type 'WAVE'. + m_ckRiff.fccType = mmioFOURCC( 'W', 'A', 'V', 'E' ); + m_ckRiff.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) ) + return DXTRACE_ERR( L"mmioCreateChunk", E_FAIL ); + + // We are now descended into the 'RIFF' chunk we just created. + // Now create the 'fmt ' chunk. Since we know the size of this chunk, + // specify it in the MMCKINFO structure so MMIO doesn't have to seek + // back and set the chunk size after ascending from the chunk. + m_ck.ckid = mmioFOURCC( 'f', 'm', 't', ' ' ); + m_ck.cksize = sizeof( PCMWAVEFORMAT ); + + if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( L"mmioCreateChunk", E_FAIL ); + + // Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. + if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) + { + if( mmioWrite( m_hmmio, ( HPSTR )pwfxDest, + sizeof( PCMWAVEFORMAT ) ) != sizeof( PCMWAVEFORMAT ) ) + return DXTRACE_ERR( L"mmioWrite", E_FAIL ); + } + else + { + // Write the variable length size. + if( ( UINT )mmioWrite( m_hmmio, ( HPSTR )pwfxDest, + sizeof( *pwfxDest ) + pwfxDest->cbSize ) != + ( sizeof( *pwfxDest ) + pwfxDest->cbSize ) ) + return DXTRACE_ERR( L"mmioWrite", E_FAIL ); + } + + // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. + if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) + return DXTRACE_ERR( L"mmioAscend", E_FAIL ); + + // Now create the fact chunk, not required for PCM but nice to have. This is filled + // in when the close routine is called. + ckOut1.ckid = mmioFOURCC( 'f', 'a', 'c', 't' ); + ckOut1.cksize = 0; + + if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( L"mmioCreateChunk", E_FAIL ); + + if( mmioWrite( m_hmmio, ( HPSTR )&dwFactChunk, sizeof( dwFactChunk ) ) != + sizeof( dwFactChunk ) ) + return DXTRACE_ERR( L"mmioWrite", E_FAIL ); + + // Now ascend out of the fact chunk... + if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) ) + return DXTRACE_ERR( L"mmioAscend", E_FAIL ); + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: CWaveFile::Write() +// Desc: Writes data to the open wave file +//----------------------------------------------------------------------------- +HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote ) +{ + UINT cT; + + if( m_bIsReadingFromMemory ) + return E_NOTIMPL; + if( m_hmmio == NULL ) + return CO_E_NOTINITIALIZED; + if( pnSizeWrote == NULL || pbSrcData == NULL ) + return E_INVALIDARG; + + *pnSizeWrote = 0; + + for( cT = 0; cT < nSizeToWrite; cT++ ) + { + if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite ) + { + m_mmioinfoOut.dwFlags |= MMIO_DIRTY; + if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) ) + return DXTRACE_ERR( L"mmioAdvance", E_FAIL ); + } + + *( ( BYTE* )m_mmioinfoOut.pchNext ) = *( ( BYTE* )pbSrcData + cT ); + ( BYTE* )m_mmioinfoOut.pchNext++; + + ( *pnSizeWrote )++; + } + + return S_OK; +} diff --git a/Demos/DX11ClothDemo/DXUT/Optional/SDKwavefile.h b/Demos/DX11ClothDemo/DXUT/Optional/SDKwavefile.h new file mode 100644 index 0000000..921f1d4 --- /dev/null +++ b/Demos/DX11ClothDemo/DXUT/Optional/SDKwavefile.h @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// File: WaveFile.h +// +// Copyright (c) Microsoft Corp. All rights reserved. +//----------------------------------------------------------------------------- +#ifndef DXUTWAVEFILE_H +#define DXUTWAVEFILE_H + +//----------------------------------------------------------------------------- +// Typing macros +//----------------------------------------------------------------------------- +#define WAVEFILE_READ 1 +#define WAVEFILE_WRITE 2 + +//----------------------------------------------------------------------------- +// Name: class CWaveFile +// Desc: Encapsulates reading or writing sound data to or from a wave file +//----------------------------------------------------------------------------- +class CWaveFile +{ +public: + WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure + HMMIO m_hmmio; // MM I/O handle for the WAVE + MMCKINFO m_ck; // Multimedia RIFF chunk + MMCKINFO m_ckRiff; // Use in opening a WAVE file + DWORD m_dwSize; // The size of the wave file + MMIOINFO m_mmioinfoOut; + DWORD m_dwFlags; + BOOL m_bIsReadingFromMemory; + BYTE* m_pbData; + BYTE* m_pbDataCur; + ULONG m_ulDataSize; + CHAR* m_pResourceBuffer; + +protected: + HRESULT ReadMMIO(); + HRESULT WriteMMIO( WAVEFORMATEX* pwfxDest ); + +public: + CWaveFile(); + ~CWaveFile(); + + HRESULT Open( LPWSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT OpenFromMemory( BYTE* pbData, ULONG ulDataSize, WAVEFORMATEX* pwfx, DWORD dwFlags ); + HRESULT Close(); + + HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ); + HRESULT Write( UINT nSizeToWrite, BYTE* pbData, UINT* pnSizeWrote ); + + DWORD GetSize(); + HRESULT ResetFile(); + WAVEFORMATEX* GetFormat() + { + return m_pwfx; + }; +}; + + +#endif // DXUTWAVEFILE_H diff --git a/Demos/DX11ClothDemo/DXUT/Optional/directx.ico b/Demos/DX11ClothDemo/DXUT/Optional/directx.ico new file mode 100644 index 0000000000000000000000000000000000000000..bc43c1b2085df668dffff26d80adcb0ef73f23a9 GIT binary patch literal 25214 zcmeI5cVLg#_xSHS39q)lv}=A(BYsjRYY` zH7TWNZ8b`*#-_&kz0UJaROjc@&v*UvdpUTaG(n_2(TGm{_PcFOh|~~Ux5GdBRM&l zyS@?YKO>^Qtc#yK@=u5{>Hq1KU{6RG^@qxdybhWe6!5z*iT1>iBLf2i0)G1;F)?^# zV8BFP|K>v)#c5rObN$+f-L4fz{=Pz5qICr&I2w9ZA=o!DF>ZWtf_-8F&HR|vwHA+S zP{nE~FzDAF;&|;H84$z(0_?9pt3dI%xLlFpBZEgyw2$=+&#I6b7nfMqGcq#Jo?s8G z>p4OzD5~12M`UDVKydKL!F9QFDK%(Ci${(KPDs!KRM7WnalYOj`aV1;F?cLL!o&HH zo}QYR=;fsCL!B+pF9>D>DqtX+7fufKQRxlhe0_a0Thhkeyn_+~CQ{y; z@%qw|zKo3Ya1I_BkPwiRKHirPap3Byuh&#)kYKk51iqc_cQV6y=gx#&M~CO@L-E!DDMq{D4+R$L?E-5kdTxfq^}{V z_R1Ab1$!d>rj4h4Uq|aorEn_P6QL)?y&bKD>Y%L(3D6A!c{^J1u&ALu1T$YCvv07zrvnFZ+6(= z!6P&>)SF>b!Oc5So1q~)?>!?cSoAO+&WTntdR!`nNv zb#2Msz{^zdR)W)mg`~cvLSh3i$ZcKETGtOj<9V&ceSNL5>O1SQ2iYm_>+2vv)?4oO zVC(vAY5ksR*Xy~GfAJGJWQn3*@5$vY`SjS>tb2wrQ&nCi8&h8I$gKQ&N0Pbn&r|Ns z+#hqdaeu&FKT?f~#+=o=|F8FCeJ+oD%)E!_J-;Oi|Mae(jjQ$Vf6F~YoBEUflJ)&_ zc%9Yf=kU%NPuBRd#+x;Mp}5lH8GVvzPM@>rmqkwr$#2osBDh1(xKXzm@PDpn(hw@6 zeq|K<#EB}>vtFboCR*Y;vjmT-B^+XuGRWN^>Z^9p8fl4fb;E-bf`WL~8fkG}p5Y@$ zP8^Fw*5^c(l4}y|bt4hD`dOu8Kw?lXmB6Erv$|-*gU0Jy>)DbHBfTQIkcZ>rkhY$Y zYgBZ2ObkdzXj%n$40YxiS;=bE!lBM8h{vOP=SUTm z$VuN!v4jLmNU+3_Cm%yCkv3Arik1$wunc}XJ(c0{{Dt-ziX=%H@1lQ$VViZO@cg#p!Lh#i_pB~&XL-tMg_ozop8jWHRfS|$MhI-21%{>l zcaT+1@5$6Xo7s-GscmZ?+L!jJ_EZ7D4fx;T^R!Gpw8Ns%AkH-?5WY#P8yP${JRm(K zS7cz_$bfV-*cw=Fl%=vlCyw%tgTtyMjIxwcVB#oCQHBR6r8qIyk?Yb^>qf5f3iVA- zAMcsls{#|3T9+A88mBf;%8SH#J@6kn@@)RdfMnP7^blunj}YfI3C0!~Zfxo4##YzU z*a8yuImCGs-<>>?UBiPYANjz4RQhl2&Kywd&#$ArJ_zgwz6R2OFM++l9$*)+6W9(U z0b2n(unC9*Vt^=MEf5ZT28;&+0Y4zrW-|+bQ%+7M8Q2C)=D8QJ-`Uxu06TyfAl}8r zyvO}g_Uxt--@oO)2MEiS&3xzTYPJB$IdYhGl&MQQ@%)YgR`NbIS1$7~Up})vcW(0o z_w+n@%%{9Nls~`OQ?Q_k;{HqV;^rqHjOUXjN|=2mOPZ(d?#9mVI~6LJ!{y4E3mzV3 zFlDb-s$@!m&l68ivxIVa=x=q|vgU4$8pb6Bbz|?*!+1lFd*jC& znKa2%D^kSB=Qvw{)q= z;8~V0Hxe3Z9<5wyRt+C+rh~tPhnut+GmNZXZ!-8T8#kIe>(&`bNHCA$;*4zBVjgbV zWMunxb9U`oBfEAP*|W#UzJ2C0-(>%OGoL;lfBm(&#C#3p2K5%ZzR2Oyfi!PV`}W;|-NU#+iPz-MwqF^E*3z zI6=pp{LTa9OingAKKQ_7A2!T5*QsL)+`erJf^RNpnw_~X#&4FWDR%X$$unh&ae;q| zef5eQ)Svvx1^={H2Xn73fbvX!gC!opTj<&PEGv}x0#1xnhlWzQG-zCsr>W`C#^ zRKVknl{zawuv?;$xzYUAT7V>6n+`q4B|!LsGZI zT)2KuE397mc~%E4{e8+iLX!rtVJO z92b3n4j#>Uv3s8Z18?r4fv9iK{Rj=#g|ArZVAgK_HA?3#S+4EXwA4L26F0?tt0M^P z^kVNpM-$^?Hf-1sv;XwvhfhPlSh~P!ziXo!rE?XmNQI-@_ogHz#2#Y=le=|oosqIB zHYR3cyghN}srwP3%N^yrb!}d~OwL^SOO~tL;lvJbvd5gea^vanff?H<9vesL)T1}& ze(>qCr3>cKftJscD~D_DB1MaLID2&ap5%nDFI>6(^UptQ+z=hJ(Vo2L%bOu{=gj|j z>5>n1g;Ksk-rPA|v$+{&? zzC5{HU2Mjdw`{ErX(?MaMjg`9-yZwn!LZ>229F#)cKoF2vp<|Y%~8H!!Tfo1(}B&H zg2gI-w|5Iv$6`8g?A)dM!w0<7|CJ#DBSy1;W=^4eVDH9-3Kh)n=)ky?EPi&cJ$6GB z7v+Dty?8*MzJ2@k?>}Vhw3#y|QU0};n^Y@Y5R7tWceWYllC_Q|!$wh2RAFXs=u~&_ z)vH(EfJrl^jkn5otW%f@7Di6_%AMG`DK zZ#n=YXq2;1@iVj@4G+X6Y_`Y8z?^p<4QR&Iu2;bLv07eU>)oVI39CZBl7sfxH%5a= zOx)IOyS61J#99?z)5t*g{v!gkxV$#BW0N9Up+vEaU2)OTiu=aIy+_khQ<67Z6@FQS z=xEpLl_8Gu+Ch;bMatGZnq)N|6%}jWd$YsUgJ161rWLMT|0SZOceCz&9pxoxXvYR6 z%a(ih=uVJPLPp1JyIH&@ykS*1cHzp6hr^q;>)y+1USz^+z1zb&2UB;!{fbTO)+05G z6e(KEQDNi0@6X@w(X>;qewpRzpm&dQmCx?jYgO0~vuV$uLN3_~Dl^f;R(taCnvMNB zWi?L+K||ZOuGJy4LQMR&nci z@o2GJE>2X)M}>piQ;&A8*wC+2pI?iMyy>X$ouZVuw|HTegNrj2iq^V%l;S>qZC-f3 zxX9FJ6;k%xESoPk3yvDu3Ky%@wsYCKO6G>DMsYHzl zLx=Y6-L*Ma*RI{T{-(6{GU3gsZ@v~782IwbFAuOTN7sM%?`yB?HD=710R#T7*gyN0 zWe4d!xjd$qk*qiiPUuv9PR@+Ogy5j+Gq%(Jk6Zm3x67i(e=TnH*M2JGH`{jGq>?G7vcl9rvA5; zE1Qe>KM55pnkV>~8TgrdvHKr1Zfw@$M+iRU5u(}Bw5j=tcY<$_fe-m5K3lT-lpQ)4 zd;R*RGyQyrPbyuzT7Ku(l<@@DAKSGvmFeduKH_$KiuKf6gb$;>=uXOSZQk6((zd+x zlKB!}W;;G@EboVd4#v^g&>tk&z=!96o9i{;m3+AJNvE z_`zZ7qfVS?meF?t{p=q+*a&{hWqhrUj8~>lH}~+JBJf{}ft$>oYnJutV*>H7pW=5$ zQvQ(ote<}R%m*<4j0G%?Z0wr%E?-EL;!7fVWt z+5XW-M)1YH9$m z78$c(fid{@X2=j@!zZ^*n`WGnl8iGxq4TwC#u-1>>9fy_%j3t!1z*+$-_MD;a9Og% zxZ=mU;wNXP?`-($E{xZi_&^SDcftS9NgMeXTXxzn@XIeI7wr_`Irr?@rYQBw;Cq(C zH?6=uC;U}|d#xKcj0b&q>o@#fKl=5I*K5gFq@=NpK#fxSNc^XDi&j0WaMR2?*FgAGFtoaK*Ui7iUWPetwbmM=L)6bWvsx4Xc$ddnO_B*u{+d@4Ynm zwYMf8i8_D#$%@ZEaUj{eo?DrtN%rXQAFj~Az)=%I?dy(Tp}=PgtYJ2(TcPlQok{i$ z;pea4f4A?D$=}38hW&8m)}!T%=W7p5Jc}1Bma+?zFydmy!&e7{#;;!+v3B3NYfqQW z<#U_Ho;mXtF1CBmj;(QrF5mcQ@>dZNYop>4zW!;+!nw2bdnK1#`3e_1us3;2%*l&C zo;$W`_1c)Nd%u`I^Mg4v`0nfB?2;=_!J>D*PmEuC{D;%WkEL%o96EWzTT^GL;or@# zqKlKWYw`Sri|yI8F6`LxBO(s|aOK{_E*(4f96JR=erS(IrQEV- z&t3LZ{JJ&aYu3kX+;He(#xEhgTelxPezXu~YgEP6)xFUE^=rachp&sV-W?3DFT$ z-~3LIVn>rVM@O7Jce7=yj!NHG#|?O)*3q35Si3g*Oo6aIX?by{f4bN>vtJ9 zF|bdu6lQ2+?BTLGa^x?1VAuAtwk?`u@|X`T65 zUUd}MmHd4^4l}ssDO~G9jVcXWcggxL0TdYd&VdsJb3;j|TzSgWuG6qZr)Qsq0u$eu zJhGX4sq!8rOO&f#$FKQsK2vgB$fOAa+W9qTP`7d8CT%)&c&@VJ=gZ^Xe0|K&LH)b- z?%n%OK5L==Lx&C-GNgCcKh(8eum|vezwhwZc1jYmN^KO4lWzpnKFNxaui^I!U?DIC zP#Z;K{oX=w;d`4_}BX+_8exF5$-$wu6MxSQ@b!m4o@$GbMh|$;>n;JGW zt!OjV-`_~DUS=n{S%@{ys$JWhL}%a8SS~t0347u??=}AXgt%e?`ahJi5xk#=KG=*s zv61pG(r5Pnci?U9S553~^z3>n-zm>Qp0h=9m!G{hxns>Fqnn`48x$ui7o> z>k`E1e?foAjveL+dRpVcmw7&luGxyNpNqaaMLhE$`nw@^gr$$sJytweb+YPXVxd+% z7@cL%B~~n0PXY!t&7bhpVy8#daop_6Rrf7`5C#)%lR)5(*@ z>6>qiGjU&M^p`7r=Dc;wj}{h1eCpC7%K9le{4F&3qsE8{PT4lGOgY}jn& zu^C*Mll<6170`bk)TxBMkeir(UHWc>j`XLkGGoS=meljbPQc+YJ&9cx!qyu_eET)} z91W0%frN@p|9x#tXh zJ7ngHdX3w4SX05(#T0yZ@SxY<|D;(Juhwg7=F3^;jX?v43=96~(|%Qb)~xZUHahT? z0dsqdnKXNGCHiYpYwU=CH;d<*HEKeQ%8F3S7E_0RZga`=VRLtVT(hQ4x3F?Wik9`P z=y>E`zXo+`S9d%iqZ>Z(cW2-7^6g~To+Cn>-(4Bv{Ah)-En-pW!fIH}*v_zzc`+lz z`K7@j&XbQMyWW0sHvcCJ9>DNbnIZMj1_3tX#=rkFSF>i#T#6Sjo}1PS0VM%9pc0@c zsEep~eRc!%yOzrZI0OGzmlGZ5%AGrR@$A{NS95W3Y3l6k+#ML?ZeO#mHNF+j(n?fs8l@PkchU8PEuyyeQ3^C(fGgnzZ-#Rp9+S8mCQYSp&y zXwcxh?_0IHbftUuJNE|;eDrkWNVz|D?4zH?jk|N?wb!m}89MaDqF%lB4Qkvtx^UjS zvl-J^5bgyu2Fd|ChyNpU5)u;P#Kuf+cX#*lWy+LkHl=v++41Gd?KxAm>J@3&P^2}s zRkv<}Zp1bs{HhV#NkoySP8Ie}1z%OhnSp>W zP#VYq*nt1?r8MU_O|~XYniM5=SATA~a_{dhRqDWG$YljXU%1@|PZNS#@<+opTcfb3na%Fi^tCmRp`XVh`3b6||8(tO} zjdA|gTMpbm_&{U{+ce9UJ8+JS6xpyr@clVX5%&kUv1ZM^mE*=8u2;G8a`mf!NE7P*>zEVQMxPs8#jvB?IKA@!alhJwrvyQ7sCFz^)2nAk1h>u-`>s`-b5y} z1^-fj3-E7UnfN<%?kH!ME?p|FuT*LANe_=}KZE-%PfxiE&)nz!sA^St%DX33s>p*n zb>x1dM)E}0K=Q?7pf`gz1utoZ2}clX=Z!1G4Mijv{sA@IH2D^*G! z7A-0d3Ko>Bg$l`0H#a%Syxf7GIG-V$!EmhOz(B!X70y5iXC6eBv9GASuk*kdo~ES8 zlP|xNr)gF|A=EoPxtQ^&RdA=-YwYL))?LyFhJ+w zP4L(CplkY115J&eaGfBS7~T|fEoL*a~xaF#?q9x*~b zWNs4StskNJBgOx~0TG=K9Ru&quU>sCutNu354xsRE~#w&&6P=emmNEHen`%P_mA1K$pvR;`3Ah-1w7#u&UXmsGo<5{D>9DXtA-4bAK;(ISu#o2 zGw+14vF9Q(ZJKa?Mh+mOrXsT%^zJSG@cUb=gDtG@pLXt)$5~@geuBS)a48D0&rXxdA;C;>}$#@$>s4^J#-QV1Z3uKB&MGTkfBi6ait0JlajK`EU7+B?rfsfu z)vCSnb-8jkkAVA8=>9#p9|!M~;G70v$Ve&0owY}NRXF=2#i)!H5HOY3fA~Qn;F%wh zr;n9~R3B%}0lI;+O|lQ&JjBOG3bt)4PK=kcJkpqUMsi)Xtr)IUq(a^1=&5LHf&MbTenRWEpF_c8L<=j4ZM-UTvom zbU!(|ibq;$2Z!)jTjvkeL%!A6M$0}1<7n~E5JK^CE zU-tKp&Rhp-w_2CVdwYcnE50gIM)pDbeaMwP(4Ao~R9LEc)&GupN-xy{}E z_}-EwWe>F9jjY)U-t&OwKpxh!4VoI{q=60w8E4L)7Xz-Gdz0++TN<$D0DhPV-PXc0 z7kqu?2|D3E<4;FF3`3U`LcZGIhv#XahE`sn6ziZibJ(6XhTXU!A0R_hR;`lj*c^`) zf9$6dbLU)}a?*e6R{0cNaSFO~wousr5m~W9hWPu(LjUgIuYR1_ zSgF#iUC?HGks`7k-eLbwwu5sNFazicAauo<@fmCagDuZKj2PyYGlXK$0V+!iGX`(Q z&;xu%Gq&Z(($pF?BmvsIjGa*!xnxrwWPI!sIo1$36Q6R7NBQ#jadE~b;#{CKzz&~> z{yvS(%^69Hf7Fip{B{9f$ST*h-eq zgZ=c~#EDn)=g&V0)HNnxw$!L`X)AM_z#MaKSrWisaZU#I0Q)lU#D6V4fD#uLzp!{5 za{-;Lb^ZPKmTb)f?iHAWTHI?uXE&fAzq9eqWPy$WyMtsuaZ$Xn0qY=}hCr9)%x^k# za20*WnO%nu!8#TN*5B3O;Jcji3CWZ}Cb3SP`*!HRu|NTdMefIe|7LL82J8a91XLF& z=zOpPDQ^IcfINT=o8RIkbd5z%WV*_e5(*H7e zW*>GDXO@LC%kntOhn_X-S05B#;=$W*KPp3Nsg_u#+oe zyLLck&%zhli;TU5-sW7kJXT*+?IyMT)F)McT77BtN0A**(I3P<-pQi>)`ku5$Kj)_ zN4~9NeX88ib*nNo33z@Eh*%4|#c~+f01N}l1J2l^20pd$SKS7VD%YJe!6kDHYHyU~ z8|R6o9eB+^wtkI{xQ)JkqPkjrX|=u8_UqHfVT0>DC?8>aYb@izm@$t_mMj^J9;>YM z-`uq6N&;V9pD_aynv1TK6b?cX#Y_C25dts9-y|L#x&G^QX5eHAdSVm|Gr2_h+KR1 z)w`ujmwr7*jvVfae?s%--^M|QweaC;*6$kle;qhI&qv8T?*-BU<)80>uYpB?@=!L_ z&#cAgZ6mc$tug3W_-zA}pUNu!Ko9iyczl$##EdR$97f{-%!L(`LGE&P1LGWjROdqd zX>iwZob28EC*o&;=m1o!G4U;1#>XSCBC&tMa^#TJ%mMpLvK~;GqrComKGL-u4|E6e zW82tNAFEzcnXa-$aaX+cx4u(-r7|D+$r*O>1b@z-%MfJh^c_278+`K%aRE_)7ewPT z&{VLs1$ku6f%?+u?>(J59j{QKLLX2^l(R3^y!q?|=59SYK8!W63i~Gvydr?-*Fu&& z+L`&yvW@UTY%0H14=H|%ui~ws&-z~N%nKJBHV<}<%KjpZp$=nEyLl92n9JJV4-Sur z4+!>_V6O-=MOfRMrE$!G#`Rd&ku6%JRI664HK<$mPi&JWUG0o93R`6rJhYNISP2j5 z7}N&UG3Z**^{jGfKH#Oc40eenFI6ugGcDbubXQQjK<#X`w^etk-=Ol9b(>{x6l08V zjIdf|3~kK8Hsl0>(JhR52>md{v0hC5oaJIyOpW>axFIl*&j#U|ion|A}U_%BPbdkY! zG1!vqxjE(oz9I+0vi-X=hT%LKfe*3J9lQH zEU{qIF~qcJu`HhW(^~j%C3f8B@X%-A`Z@3k5CXIW^0Q8D>I10m&*Bxuo5n2A-^%aE zA*aw#$>r}a1!&6^JZ#7kGjpb8E3jwyn=wFPL3+vn=41?WHV0q%AnWlL=Go#Sja6dL z?(p|dCyv~H`0(Kj>{t9ZG-=W?p<~C}QLL9R=74-9`G`4~0?s{v%E;E7ue~PZr~Jw@ zS#*CMcYO!X+t5#i=}+yY4uB_+i}q~DMS~nP*fSPC>AGNT7Xa@njJ*-{Ij1ANv6nwY z9-YRY{iRwp%a6F*u;If+&6_Xggl3H$J9hjbjuP9ZP4q^1V-2>*GUi|!w%kkfSqXXM zij83VSaJsXkvAiqzw=*{|3HzZnDkMsALf zVP1072~pUi?@-yj38uzoY} z-wroycy@k|9wQemT2%4!<;$wVHP-p3`0F^L{QdjJckOzf{5uI_46|uxF!N9sIg*bt zIHMaa|4V&HT@NbL!QBPk()GF;*a@iJs=TA)P~3GKSz}OMssm(aojDC2EZMQ6y>jQ4 z>Covb?iYv=U1Oi*RGm6E*0yRj51y}e=+GgRIqF9ICGJ`C5Z$WPg!pdVe%5(d#a;zD zjq(a(@S^>^IuGb}gYGr>riM70jo3gb^rXrw)p2TXsO_z`>+i>*e5Lk@&QndG6#B9* z{4y1~??vvNCH{8_zWJec?K|;)e#__1o$Gz_0f97S5e8FQO5D8A|7ic0K$n$5!XukPrEYOx(Ue8yb-9K&27i)AMI zF&N$WK7D_|Sk|b_M{aQDTgXM07+@o?3E09r&VyS#l7e1Ig~!vN_cze{2y^&N&6+op zYS&)>S*uoUHgDcsG9x2H*XlFe{|c{v`aY&rs}~r@#*N*&-HpQTUyHtug0EtbQ_;{b znt6#P-V=-7iDS(t09$}0 zQJ3vc_0&Jb`}gJ7`T2EXZG0Y&FR>NdVk=|Wg6+G7dD)8Jl*pL2Vb5+y?{nT=cJq5L z@4iB}rvoWIJ|`2syh5XD)#7N>@Pe#SrL}^tQ+53<+`0ctS^0b1{>gK!+TP8Yb;E9& zy{S!`O&3&A-2AamoMo9rQvnQMB&h zm8{Rt-Opw|XWcXOnQ>Y4z%YEQ&)k(xro2TW$328+=p<*k3;$^ay;D%>$($Ki?p1m1 z1~dcy8_sDd1zm_w=H*@l&=^N~z#|j%x4zSFn4#9$hAgV{_@7;RzQ@hYEr+|idvRhb zo_aQ^Sg~T=3KuTizfhq<0R;;d9GNd)zL9zJ<{iqJtA6Z3bz%?1m)i}KgI(Z z+UPrb%a$#R`;o^zs$RXJYZ^BWO>NU=-`U>1&)p0Ry!CkE#K(`PPJNs)efsSaAt4u% z#*g1WuV25ICZ3)%vSrKm3V5`o?`l9nAd55k`PWxwzfSlQxqJ5PS>?lq4ae-MRcq_D zMvbnD#sS$sA~(ko_tSGr#P#``4%V3;>nsZXA4t<<>?s)Y;$Yx8K1(6pR#wOduY$j zz_9-!#BDBwgt5)JI^w~Z1 z@B{SRL+rPU=)ObX@iY3uItzkrZJo)%_qWbM=~*25wf5(Ae^SpHfQ$XT_YU|}tHz%# zaqgChgVNzQm-fA7%a+{izm%n`? z+1L{B;z_-(YK5F=^)DDf~z-m@HvGnfxmucS#!Ie@|f_JdJ&x``W+a z!CWXmWb&l03rmXY*duG#Zj)Z7%;~QgH@SVn!jatg;Wj-FLEOZZzCA%y7Q(~`Ic#Fsr`0_;YhRc>7|z>EE!yoy`$Jh@ zF&dL#U66Apv}6N)5Ot{k=-n>z_x z{0sUYM&B@put%n3#&_7S*S%@-5u6mK>U_Jx(s^icplAc`y+xKYDijZAV1t$4Z%xR!;c zUGNJQA}bC;$J^lYlz58j3)NYwJL%tp^Sux4_-f?KT74(d-)2B#%rk)gz%yDv$7g3O z7;|p=)V(+DzYtIy`jbm2o$yN*;@hXOM#(dk2hjeh?lb6q8#?Q8NXX-7{Wop;O9DPj zH2ufYSJuAB4t^^=RszZsC=YQ$2U&3$<#COv(kFS9k^|6ve)1lr5i(;kaW?X2g}>P( zPgPE;tX6%&9O!=8QhANMu=a~MBX@K7@LOubDF1C~-TDAI zzY>X`s{3?VIKZ=%4@`C_3VhQ4PBqzp#yoE5`m2P z20CPDoLl#FMhq?L(SI*s6!R2}9*m;>4C1BM-XF4>++>agm0@TmPi+1A z!^uIG4fxw%pl4?y1C-w6Ig2y<`qnzuzLeI=-wH}|#%<%=f)iu2;&$je3m5cGcJL$j zRa#TF8#EcjIgLHEFRHuQ6C-A`ioMcm{DGcq{0*@3_V(@1#^9fl$1UV`Ng?>hN#npO ze|7&*b%4s3tg*A^b#JaD`bzoIk`wT~6?fA;J1q~6g;}Q_%!@BJ(q`-#-FLh0=XZ6C zk57O*HZ9|~ba0HH-^UtD`Uo0zLFX2P53I9AdM-zCP(7$^s%%mD#_wEn=15=q*0rJQ z(~=SJ7Jur{A+MERkQJ`%-;&2J$I%gwp;c2s$EV0*0ru?O>g3Hr&bXg9nD&( z4(+ou50(!2_+tkSstZq_7ILITLJBJ`4C>?Z-7a4 z=)Qpdb^$7{R8IK-&-51kx?q?2Q9qJ)E}-9T5m(&as8N{O)oR;6-?#oo=Gvm0HvM7~ zI$d!HV7@$wt>%OuY-yM+{EY*dijAalY9nB$uSD*8HjBT*Ad$#W{)U3s(LINt-w%vCwN9P5&pLH#rnbHM z7k@SO=kd_FP=1K*-1&4Qd!vhqBh5$lFJlfP;f)yDkH=oKLz^V-JBjn{;oX<$ku+jp zhw&4>@$&j%yO-BIwX1h}k{H>h7jZzu8`=&Ki65>SNWORGT)lUl;oR%{qI&UHvT~ zHVqw2eL$GzED?uf?D7x?D7}MA7T?z38i^zu+a$x05 zM8r=oHETAH`jxWUP#%bF)TrBuk|i_98y0e6h1^gfC)Ya9Lo7kauNCq_g`8QrwRP*= zzW)B&hQ?J)O8@>PlZzBNMGmr%t19HI$^aTAZ&b+t6>@il98)1zRmd+Da&P5)WaO19 zrAw=w;SyKA{9EKP3%RM*UO)MMN&<8rMP(iNxz@Q0 za(pct)bi1gljKAT`Ont8=-hHHuuW8j3YXSUN9{XpL-joQzt7GFkxy*-OyuthInqKd zwskHeW6YS_%3~XRd{W5)mxa_Nr(4K5cGy8`kEnfu%}2hmkQ*%I{tEfeLN2$Q?9$~7 z=PJv`HElYcoNpnw+o8);pQ}y79FSuyMSX$LyBp{e1uDy$#RtnD2kDZ+P8*kNf)gIQ#bD*2lNuzAx{0j`i>Hon!vH zPkY?X#n<-t@A3TYT>gEn?dQMu2Jo2e-=6>P`~w2~_1|lPf`a7c=KjC=^#A`u|6lwD z*6ui{eQDX+v@cCbnfXdgKBcV(QnexRn6@1{p`FQD+Iu2b`_l8YeEn`Ersilfk8MAC zN;`OMa(02X9!l5V<2l-LI895xU8m%;MOw@I_on4)=aEcpNjjnBYqn`m>KW%f2Qu=s zVefIJ z+xMNv{=DCCJlluutKl_&@S4B$7q9z^=j}E3@BOa(cYfDD?9*QNw;hxH{l&iReC)B` z?>4;e?ydX!o#*Vew%K{!zs-Ajo&D$Aafq6Rwo&u2w(^bZCZATl zVyiFaP%a)C4*liTs)w2c$EaCwteOR} z`A4gfXP_Fnc&i2bx8t})a_s01a*1dwAI{Z1E`jsyswQ^)(0IftMQ|4_B?3zv(h zpB`{=mx~Xt^9oR7H*Yof@|AZ~E5&u~tqy&M$}b{LYSKb#)L2cLyEyx4)U<^fwQy78 zW-fZ5X>&Dd&VBxF>fx^@Y|YqDV~%J0ZRY7K7tW=LryV~)ZoYwX4~kY3caFvVrrtrE zW00Ego@Sgw3*TUF{pH3vHuVfpbI!4eho5uKw(kdAJ=N6BQ?3CK&iB^T!^_!kV-FwB z-CvD)z8Uu$bKm|uTY6PrtlF-E+Ba&@A(TIVXSDy^_m$$6zZ%6sx_ZtG0hWu33Rtvt@d-kXwLtZm8J zI+k-$N6!}PWKoTd-uR8h5#b53a&%5)^BOb4@ywRTsE ze%g9KD>m-eiF2j;Wp^?;>WKEHX6dnKUUF*Xp?wE+=gvJ|?<*T}J?WSsKcu#o^ zuc=fWk5^W(|MF^`&nr~%g^MaU&vxOG&gJIoQgMlM?CPpI)z@8B9q+B+SeJ@QReG^h zHQcY^IonrtMGfa#tqRVyg8i5CSox*0hQ~QZO=S(A;VQ4c>^xV)>o2pvzsMONE%~+V zpy1ec3Tc-h->7(b1V_j_qNRMzNh^8+dDK`?tVdX^$Cy* z*O9A#umagfMCbnUBR0LmTgfXlMq%yx@SZ*jX+?}jwpLJlXZeK1vCj?)h;Ac4Vkod> zM|p%s$s;IAEr^KLOb?m9|;QPewclx*tYVH>%cy{E2Mol4VXDk3*TF=*OvdH(T_gE zYso9bT61zoGf#iH2e;-sY{&UV$UUT`lVe%f@#U)UKDa`M2#Zzjgx@+Ig^i_`ckt+9-(Q`;x;Vx(`%L!Z3w&?4^MCF7oC1 z;EsLdMP3Zx`ws2UR~`|q|eWbT~{p5iM7kMmx;L=)e|=sZ?(iy6|vh8SL6g@v8s&cd0hp!l{{CN zU#j!ObZt$&e!F{5H*eh5wX4_38<%yls9dF&N>oBTmzP%Q9IwmEIj2HyExt>O%T#i) zjNDSmvFe@U-@0~#W7g`}ku)$$p%crMW!0)C<|}O@2UU^-s(7rXx}N=%aW0k4d6lrw zic1x$vFFGM6(tqmhx^2TV?}izq|i3qxhC2uw0&=dwC+Isw&Z$j#kDd*p!+odJIu?m%d!TUF8-SDSz^SFV~_6b<8`e9j}d* zXJ{;sw~|MAyu5hagZOo&t~GV_l8d*md@Q!fDfXBr$McVl=X&q1X!hT-*AQZcd_per zBTsp=KdXJN)JKc07Sv5I_8rist73bNc49ZAQ(xkv5Aoc~Imd8fJcw9xBY#-^3-3(q zgEs>C++iJt$eS37N*Jkd-V<(*5g$Q(H+J5^t-C0wLwEI>{E%k7@|NbkzEu6EJjycx$7gj5j^dobKXF~<14i-;ZzE6glUI0K@>-bO{J#7Ywa8>v{QdY zBn*)&-@6}q#+UaSw(;P6{9ARCC!foo+!n^?@Ne6bT-%n<*`42Rs3JOcS1|D(+_|4Z z_^pE5_u@AMqeZkPZ?)rGI?01`aOK>5pT$u83Iyb6_E zy$5!`q;%?IDqH%wN}VXGrG8%0?u-H*ICVj(`8CR_yrCoHh-0~2r#Jr8rlY5o3wFpW zyQ10~_jT@KrLNt*ud7^VS8m_aZ7^_I-8JX2%BweZ_m96-&Fxic?Ny$yy?TS&yQ;W+ zUHQbs<(qe%t+e*4^SaWStGfT^-@0<^o(jwBoLsPvI8Ud>XP4INtMz-q|2ZnGzO5fN zAJkfML3&}el8O5hg*D)jn@Zw*Q^6LAsb`g#l0^=>s-0l}l$=X?`_pfn`hPq%Rd+e( z^3rOjPG6?}R#W?JE4O$fH`Gwu?eCI{6}rOtRdK(LTv5h(S6GaZCk`Gwu3fthDf`R? z-MoHF_wL=-UGl)Ko40fYOi*50qnxwnbuv9$>8Yo5g8X~tRIW~+%vD})fr>7akZ&%N zH*SIV@9Xx>J4!!(O6yl_P)2H|6aUqf4Y`$JAx`WX1Oxp}3yI6h$2kZq)&CiHV-XR~)&fJ$brl1qH&&4y`;tGp@mV`6yvtzXsfRia8K-IU7HQ^Fi#6`y zh3e3MBv_z3-$gI^#C3GOw}ANePW;7o8$z7+BXdbowH7y6l=x7hh50iF|5ll?tkfqqC(dx$(PB6jV6%zUta< z4xYYp?+;>}8h7oEN@}jD_Ig7MU;pjCN{ADS+v2J#&i(Q$H+A_owY{RAzptzQ#$EmP z$6qR|zpheZ&fa^m8r;k4D%j@*YGL}>3rf!|)+HX#FRRnlyMHKy9JT$(X=?pRut0%+ zJ&>s##J7E(EaLk(yy0|lopz_^JD;bZ_NMZyZa6t^<+dcP+I|onAyrHNjsKJ*$+~*w zhEw|u-&<`pd|&x*eYY69N{*_f=3k|rU*r7jdCLd2nML$Oo1KEM_Z+(UObhD#*X2+^loNYlVa74J#OK`0eg*x^s)~lX{+> zd|c~SC2Gg|L>1%}=wd+$?}vMEE;UXrAP@Y@Ps;he%Gg&O_`!Hft(_mW-@yyyse9-G z(gO~rwHOQ}{v)~$BVM@%gM#6fA=IlNc}K>}Gb9}R+g{PV#;D`42Z@CVYTaj)22Gr$ zp>vi-`wdgOQPb6D(p>ePF;4?#%~Qv*(=_hU zC)xiLbsj!eaozeUw$EV2_812L7$DccC^bPVaQEk&$qQj!2C3c9scJiLJb4W+(5@@k zA;!sPVbuRna#Aq3J|MOm@iSK8-G);0!OP&65S|MMqxYEjh@N}@D~((5f;x_zDDRk- zYC&9iQ@@Q{*lYaa$rr5>_#V5HpWqc8`Z;lEkK1=^b=dM#GcZdFFT(-Ba^X8Lp5Ra3 z3qT7AcDM@o3I1et-xoe$`w0Z|M0FoY9Jl1}o_vn(3a5q#wxWiUa{^kytN5K9d=S%4 z0q`qdxRnpN)(f4+1uWGfAdLGh;d*Tp&i;IOpJ9L&o?c4KfG=OVOpKfZ#~11heBNqi za!!SV`E%g~<#2$U@*B#!SPN#ZQbs`)HT8;esq;6{rb?*oWmj&gs1l4!?B?+JdFpZ| zuRV;8w`#``2kU1S^EkYqp6jpX=I`)>i`3zIod7SNBc^RX$9e2@afOPh`RA#VWtZ)C8IH}C0E-3{=Vlfd>uSpfDTZkUDVYtf8MLz z@R7CX6>AS??za1eyX(Q!)x=L# zd6mPxjc1p_{S9YVR~sH^!2PAf^EvAGy7jxXW7|IEldtN~5NaG8e??cWTqAE>W8YWE zBUe?=cG;dMMolNMdVl-YZ@O{gCVw~Np*oIjv6~9^|Ne^=O5B>Li)aOPa0>^ESbRG< z0Bld)ucH3faL$HREFYC#DtBss72lKb7Rx)PZz5R1@u~Ax^QnJ+(Z<_b68{nMp?*Yy zm5sAUcO9s914gRnxJT7{;ym@4_?QwVJ*sXK9@NCA7i-ST@9Uu#-qy@#Ue^%v!N8gG zdHylAA2LZX{l_Y5z$o?Mc6e-e4T$QZPH^COp9s0wH5nQW?&zd`A#F4%vb&~`1KNVy zBe|xBQ@6Ve9;41FP1%F%6jU82f)jZHfP0lV+*kq#0`64~)=jxMKT`p_UGT z%XEQ*ph<$WJj*S{9|zaxeO?jN{_rUIpegu7M8iW`IrzgJ3}D#8 zCkCwmOcvE`gqnMJg7dkSuidBCgNMNYX=r~LaQeKe+vxX&+JCA9oxW5j!P6%S>a;hr zNR>B!1DD@Y9kt$S_ZhhSt>6FBO?0Jw$Fk7^inWz}9nLP*vX$H52^W<>$l{r=M^z{j5sR9E|^G zw1c}U1wUK|dz>r3OunhqR=CLNl6qNv-feBL?f?0L6tR zN=rGZ)jw|3;lw26=M{t1D;&+xa*1K`i$xbz%vOZ%S9BgcQ(!tknN!d6&g6jua&;lk zI6k-?ZO_RM#Bz4V8U4Cyy*6*$rkqnbD$2iz)`#ZEbCu-{TA-b?gGV?|<1m$Q{kkf{ z2ii#V>^V6HhY>X|P!(<3+(zS$Nm0RHXVTWyEUQiowv)qc<< zbssyE?I8`H`?Ll=_!KpNi3UFWoJP%iUV~>oslHPl*09-6t6%SN>fax{PTY4vi=PnL zL&KxHss}xV*509taSxQQr$6`t4G_%RB_y8O-%W$t_0#ZHeKa|~m*(~utr67JR{e%3 zs?RXBCkJ&LHd5_}O;Wcp6V!R+ByzyRYCUkYIt-mgjQ6Kb4kPY{IQo{=#Q^HAM`#@N z5j}!^84qy**SNvMgE^LQnoK0r$)7rMf;>^aZSNVr9BM~e*LH}FC4Gpykk)0*F2$L&-+vN{rDY?Z$u@GaCngy->naNfiF14(J|o@!SEVCazRwj5#WC}r5Dw!pze;c z(8r9^pNHF9oadF_)R{}y(dKV!AG%;#UYWAc+>61`^~8Vu_1h{%_r6Lk&n+%jCfeFT zxWUn!QXR~#(fR`?v=vFkSo3R_LSEyR>|BvfloFyS`04sV{bB=w$gl zz5DeBE%|z_cF}7%TXjbpkDj47Q19Ra)9iK~JFOhB^}+O9C7sH5_`BtjQgTC4)iqtL zybON0p`1(T1Nr3+*S}D6OWEj;o0Co}lb(g?ld0z_zz2oemXr&3IHAK?1$yz#51jZv zmYm|$`|1j`G-|qO|K;Uia_XtYyx{`V^h~=qZM}-W>+8@5iGRZe1qH=QI)wK4>o#R( z=F0HEEwsO@)cp!#)3|vtx?g5Swo;F!Y4^^(Ia#^>Ou@ zIET1Fow-Qmg)&7~4Y=h>wwA+=QSw z#e;n#-2)Wm>aQq|K(!BuRZn`51EM;sH~qoBaOd&yyr23%qtg(LB7bxOhXl3hB)^Wm z6gy~?g1Yyo-cxH6`ob@!g7eYr$YY^k@z4$focqT6qq+}QyW!KoGSptMxaplPXavpa ztwm7hO^bA=b_c?#!{Ee$@cGcTz16DcU`>4DMNORdl-i>|1fX-84$&FCqx;Ztis(sB zLi21l;vuldXudnsEjZ6%lhtv|Tn&Bb8TAJT^+ywFJ9x5U2Y^k;PvIQHmmY;X-?<09 z0Wa%w(vLKK#k7kS^b9=csd_~cv&6AyG+I5JD75n+g_GN?pJC@6gZ>{tz6t~jM0Dt- z==NYZc#9Xhq3Is>Js9UOOklaqhdk?Tbsz2!2;OVZHU_AftGjY)@1g4zp#9x-c(V1+ z&Q`*?>A_{f{ZAEJ+|b{nPF|q?R)E8c%IlSfu2hXqejW|~K=viAPcPNCJJR&|FK|?9 z{}J*)B3OLQp=|xg_Wh0w?LAYjr7L%7#l9Rp`S$nPaDpDgg{yjM>2f{((uewrT=C`R z!+PiYE&5_ZlGYx~*4gSi@cB!sMpw*&r)=Dp;oy-SY3H?mZ#o$NEaye94IRYV${??fWNo-e9_pKgV4As}5`B`6%*sJGxi@AF8!pXF3ZCSUISl+K(bo#6G-mdZ; z+3OAO8y+{^Fe~#c^*l={F7wdKq@V1WmwlLqq*z5M_0po@;c-1jDSqG-H1&~i=!sz9@rvs`N}UEzRKn=lYBg|@ z+M^o`2x+GTH1Lkp?NKqkG?`xh)Gos`x#J*>C!WUQ0T_;lphrk+wFdu2yZbB7BUl~i z?|1Qy)}YXK8WGk}qawO$NCbHxy0eDF_trRa$+);)n%JthM#d&6fw*Xg*4Gk^()ey{ z_r7Qg;}zX~2-kdXG<>kMX?FDftoIe)Z?p!@dP;5JB9Z84(Fudq0&Tz*{2hVb7r;4L zZz2GE9zt#Q4r@sdqmu?qnXP53HfzyGUux{Ur!{0c`HsF{_fhB$BPOfgjOWk-W~%e( zN$P?&*>T_~^2BiT$rOH3Xd0cjCj;m4*B z7d3J5z(U}zrra7gXo?rW1I^y>zv&aE$;KoMb#_J72Z*9q zL9O=(`+LJHg2@e5|2@zwe51e?@Q48TM5t*V+%|D>Q!QHX_QRQA^IWB%{U42X7k=&!vA=OCQhbZ2@ug-PUBSgD0#zn5)-6T}iBEYR&EpZ9!ocmHh7E_!<@+Qhl;18aP{?WhiLp4PL-gTI_Bsn*3> z@>9)qoi41xFF@V5zTf#uZ9064_&?8MXVE-wfe%X1GRn~=QuXeq-^&}%T(fV#X9stt{ zZGTqJjk6cQ-_z5xv|;TQ?cS28eLIr0Z_iO3-hEiPr@{Z^j!M%Sz!l~Vy z^vTh;gW}t&^SEhFO%0AAhC1{hRz`A-Bv3p1lLv+nYeOB59nEzZN*uK$4@A%->=xKk zqwxKVitIxCcG2j#9vauKuO_$Yqgk=NG^5K)Bh*lf?Hm%^kUBCl< z(ZGjReI z9voj{G7660XYwo!o-|!;;U0s=Pec2E+Q9<@r_R;j>D2XUb2W12Tx$H|>N8=QI)Q)M z44tUKGoDn>N%PbfoHTguLJfap5xV8m=pl2_O(!ZI9%EeJ`jUafv^Sr@m42yV632f8 zA869TRgIc7RSSBQUf_JgVE(O%S$>C5;@J;fFoZs5AXp$2+!Bf=7}BN-8b&Xt2kJ$P z2lKq)A2+^lH}>HZ-3~th9tq<)^cAf~64A9k`NoaD-F^Ij#KoaZhcBn*mFw$u`267U zSw(e@hMso5#KHPC@coNb;N5Gt@z<2<$IS=y=8t={oESQG4s3q z?ntiYFa2IGf4fDW{d!2-zz}=RTy%Q(JC5TubZPj%|Dxxl+@tY0ryu>(@i_K zm@hLPZ5W@}b$V@Jd5bOc;8=bzpO3{?7V)`y#b%`(N(K|a-Fe*fK8ydWSJ3;Y)up`W z3>g2|;p0j=fG2U^QEl7456qBAA28GL1Qnqpl$Ml%Ew1Rg;eX=)7TREDdbWP~@fYph zyhnLw&O3eq!~Nz7ss)df(C;gypHPD)@jtyl(*(#R=KC=Xql)AIgJx^|KMsx^h+o8b z=MXr3_c0I36>J*B^%O#_it9Os7y?(fN0Wn7T7TN~=RmM@bng)g0h4wOX{%A;9f|t{ zjcwVBnvISJ<{yrB?Yi_W&E36M&pr2shEd}Opm%rmk5LD|2zBrdQy1>Xdxa^^D^ybk zkCn&sk89FPuW9NVvt^`9_TLuNmtVKblL{v5UHKN8$D*69aC!>vqf45Y6TM6R;_pu2eh=}Ve- z@PWon9Bl569&7yr)BTM>QO|wZM=(8H(-zGGYU!VdH1XrXx`n@D|gZE%2iy4&JOpk zM|aP=Smo5tjR(^8=7Ff15@>@{-o1Ueb{Z)>{Bu z91P2 zY$JJTKXtuAm*6TtA3CL-S*3dD#gFyM$1C-9Vx~6JyDTR5%`;SmuP7UAZ@rA;=!~b~ z{|Bl6hqDUlU0l`nBz(^Jn=?7ivhP>Q$J<+}DXCy-)8lKMm^FWn^#M)uGrVuL-}tua z0>-%w-(O}k-;dSyM7-3S*OP}*Ppg<-yQB5aBbnQvG@j$4xq<2m>yejD|%VBCpm?6bEO z@#W`w4@}g@JyQL{+NpO?8+E0=cL6uV zRA_sRB=(1r0}Kna;q|@zTdE)XXipCDA%@LA=ou1)22UT8Yum2<0Q(Ho$6&n37OOqS zJxm|1n_3T;;KXucd@r8X!-M;KP=8&?0dDvh%^T$6jV4DvFh8Ov{Je#Ef?e?=;+1Ow zW^v`|?%__a~!x}C6V7aC}`-+C6hjylKX*i(|dBAj&E~93EB}SqV z3{*?%uH~v=xOt%IbrE=?-~rZiH4M-g53%JZ^C$&@<*k1Z0*5mHk}o|yAN)K%k?<69 zpLqzJz9u=`oBepf@k7xeqq?J!fGJK zyQ@W;F9oCL(tjw!dwia{ouTC$_G!`5@ASy4pX;?RH__L>0cWpu^o4IX9@IA*_iD}2 zvs$s|jMg8ypsnEhqxc6;oTG-)L%4{CIENlXVf|fvh`%}hkjVcMTyfgA;nF@u%-l`-%TIUy$3ouj#>+zi2F)K^yllwS)7=d4xDy zBpN_OV2lzv5ZkMktJ$Y-%k`@d0jf#W)@v&tUvX^g{!Qw-9s$KVr>11)ksqS3Js|cx$X@A3~n#JY4bD;^~F71~aupR|!X}3!`rPlRr%d zuzstHugwMcz{%Ym4ZuAh1YS=(!_mBmZ9mS#AH3jC&anQUANQ?S=*K<+$kW#Muv`#8 z?hS6wxp55p+j@PG-AB;J?XO7cejwN`2n`{y9WxTHZYsO;5B0c82Tm4i54`#qxHtoi zY(2fP6g0duXl_O5ez))c;lzI#wRbzrYZdD=N|Y&uTrI z-ClZxzoPN&P0!IU$%UG`}|JT%iAEg{UrfbBT_1ug% zo2S;iI_9gjI$sVCs6`vNLQTGc-exuZCfNKkT6`(K{j}s0aEJ_DA|~s2&U${=&D+Rk z@BdFHu-MK$b51GAnP>$Ew0+}F9ZEc+yS92Gjno@qRmw<&oUedHVV1 zElNr}sDhmQ22Mg=F>GKx2#51i!ZPz=KnX3eRDKv!^U1*>t0}HcW1++>gwZYcX6H}YUvpaj}KE@pKx_`4N>6KNow}q zD{}kbb-68jS8iXtuLnMUQ-jw0%y+&=3;Rsgb0g;H-3J%y{W**E{=+Y6RHwmu?xWA- zvG!Z}{`93hzWrEkU%e;K@0Y2`wDFq#*%umS_=Gv0A#jXtVGWognpzy??k_LS(LFGj zjs6+&=}B+R3ru1CdmsETVfYx#qZ0z}j>W@denFenvEEx#cY5&5`#8EAx30e7VB!E` zJ;3RyS#LkkW+TW2-t5bpbMOpm>0ou|dvSF9R*s$@Ous(9_i*(eKTF+)PK5U_ApU2e zlRl`P6COs39Iu$JeI37lD6ttz{0E>}*!ORos|A{0W3azr4Og&0AUMW1z9X?po*>Tz z!u0lVc_|b5&h;H~Fn5XiF2N=Hyz*7*@XPnyf9}o5!=jewa z?M*wN$Jt{jGfA$hMGMNp^OHz_e9!T-I)lI8=5~_6$=l)LDd7KF^Q?jW&7)s>`L+(7 zF3=Bq(XX$BnT z#sTtcZs0jEJ?;j5`dXg9)NpL{Jk#h;(QmYQgxvD0+Ir-ymaRRiCpg~HUy`)c1cU`lH0@btmqPS6dA&p;p(|G+$%5tF5M6Y#XP)L0sOsb(?s)6qBC4mWY(FV-7Yr39c z1@rls24LPGnTjvU^CMreHj z;{f-6`yKr6imsG^He|k&HfU$PsVN=t`w~OJal}Fxb3P4t*cGhpZgEAujCAp#f9I!I z;w0Moc*J02BUgDPBuHZhsL|kFQt!@spidV)(66i1zne6;ulhXwvSQ&1o#=1%0K+EW zONpocGxes}1&>RUN2t-{p=vZ`6mdURjYjsDM)VP6LZfCsDi6-sx2cQV8#PmlCe7v9 z#6=#Bn=@nA!r7X`og1T}H$mHL#N1tz7H-b1%`&+JP`mN{#gOmZ{DSoW@!tZS-G!~0 z#lNdJIlzv8M7CrcWOfPg{UvBK%%`c2O zJj)wAhQ1kx)^EE1h({M{(1TB^-5|V^LnbITVUVMvnrGkoa&}HO2j#=8fbok58aH)5 ziyK(Obo;>8_=fQ7*{#*}K+6N*`atr6D;OmJpGFwG#`05GNBj@Ow4Jlzed`;9P~#)$ zhlE>h?*#_1c_%Q9d5dgL$n=e@iaYrK>U5NPx-TP-IAKPn__7M??t+mE9Sy+dcC4OW z#4lG4rndRN&o&%pOQlbjLM}L`nTzP5)B73z^m1_j8Ty8GczUX}hxpCDgfEZ$QiOLP zulfeFM(_yY`yerV0Gyu-2RI2II87ePN4vMG4l? zXw)Nb$n?V;xX8AnnVjbZ$Gfxx-SDTx6L@`cRE{q>7p>xKQHA40EU3Ef@Eg-MY_8Gx z$04}JmLp(;Z&uL%GyOkVx5;%@uN|F_ShW~8Zf~=FhNTS;T%q1Ox*Yi4bUBOdf^&t+ zLzB;@K3m+GW><&SZuhNzU$Gtn_19w5_(U%L|D(kFu@rhA+Yc!9z%fVDyNDmi^nBy( z4)5m}<{38pZ+XV{mk##-dDX8vo|5M96YDA1Ia;6J?wf|;c$eWMR{t-9SsYwr8b)Qk z{&w_#IeL-xqJp@tLh!}}QeO<;n*Y^@_%vU=M=&)eqBVJ^itdD2fOJE#)pWn&m6s?yR&I~{>z1(p61W`SPGnc>|ARIrw|2QWvwCp<$ z?$2)x{`ZD6c=OrJ|C3wyhqB?vN%Y23@%ZFd-Nv`aENay)=I+3u=x9aw_A{uJr_kOC ziQ%+-e0FK)wDV+cum6tExLhfm(~jgb+Rgd>uqR7j@6XlS zzZ}u>P07xjf?<8*BdhnM;W;|3)rVM{AmyyG&=B%2;bnw_xfD;nIHyhD7P88J8 z-^kVaJ;xjz@CE$T`hV%EX~a8ybhLca-W}~99DarRZG6CD(!9Qw11zSE_us+WZ}D%s zzQtwXIqUn~0=GBh1&1Giz3uhadEDj&tv8>K$M00eX)u2V?>p(}dDcHX5C6BhV#^g4 z>kasV`G~vB4>1dHrH+2)@hoj#vjx6!5`0n$7O@^AJ^(O@=@vEM2CMm|`59NKCf}Gp zp^nGwvoy^AG^&DYx8oey3Zj}ZK?5pj5CY>pTFPEEC*I{*Nk z9}m7W3+V6g0qeP0E^+f`?t$0XjK6tp!iXn}+fZ~go70KH3lV{rz%=)WE+dFxya?Pk zP0p3~`LoV|c?sR{=bD$u{1Ss^KBkwKeXjxZ0RxD4|5)?%;ng9J*gS49nw$&s{LU=D z3-kJ3Ax?iH!1Vq0c>alTe`4Qyc)t8ro_r2(j^}MNJ>&&DA1_`TiI!_PAQ1dE?8#!GXVc|3gl z=S#S~tYkDn>-lHk2gokHsg(R0`fFG5_M~W4YMI{HbU}|SUBfJYy$<0cuvy$f>b+_H zsb~zF4xI$c<0&dcb0jAuQm4;@1-2Z{(2-N;@e&*%me1isEY_MG$yx)ZUkfijh~MuR zbH1C7ozq8KQuW-I8}$R;!3%Y_;qd4Q>}MCg-}ji0dHtKs+IaYsgH!VG1C&yCvkS{~ z7S53YjyMUXu=PW1U67PBMam*KEd6}BGyj{x{GY|C#lHFI4Yxa(xeVPO?*CtHHNJ1S zz^Tc^rFr*ra`FD{PjmWqR{IUF-vF;$E--Jf)pGL^87{ZYYJBF2ETyHM(joejhxZ=Q zS+Il61)Gn*0l!~!W(I8yk>6Rr!*1{1MTfyd^!=Bsm@nGP>`)0a24E64)Ba7nxa|0W zuAv9uQRH(}vp?G|b6k7Q))R5&f6?~M;~$827llR?z$}>$^Q!L51epfr&$Sr<-nBkK z2z4tyFjhT+TND3nG@N<0(fH&af?GCU_J*3iy;x1(dR|T6d``{ZdQr_@U8rXK-5d?D z*~`zU>B7e~;PrRZ8XsRkGj~k}Pmk<6NbXCXSCbd!tI3N`$d&gseR+YJz4ok{zy6$D zmMm8DH=a?8Hx{bNJFjZQTOX=@6ZnUBusYHI>w^zqKxhZ`=A1%^Hy>iabZ?(X)-(Xm zn3pCJt{l;&heC+uz}6j!v0&o;0oL~jb!PL;hi|q2fhJ8HKH!bE=0oi@{OruwGJhXJ zZ8f|eLO;Rg_N`|Z-FX->HIke#l=$sUEjBD*vxoFe@a(z53Eat(KEzrm{=*5+Ez#T; z-&Q+3#J=GP+Dt+izoW%_2wcHt`$PGx#sy3lY&U2!9`5Om7s&9xaRWPlKd?Y!xKcgy zzbDY;ZH_;e+HX3&VfNZPe=&=9!|~UrQTq*pr{}}n!RSf!%oEekK#9q`kHhZ5>^K9AJFhH1}+@1)DEA2>xD$FE0gNeuTQe`M^o%b*C;e z7fb%JUg1IV!G8G1iJ~gJyVa}{glG7>je7EpFX%14rsa5sZ067Ed@(x0melil^ZPw| zzm||hqA#3Su`QTI5;qrxpr{Mju zwK^JbzV-O5p4OwUSsYt@Sr7jzF=jKl*YWq%mzRPGSR>`z*L8U724(=t^!t6*^g%DZ zVXpxPSPeH$aSa}2n_=}j@I*0K|76-}G(&hl+@XkAE+x-ct+tuL`}co$_EVLQFF0|z zsteC3cmFD7?O9E)@sM`@^r=#QS*G0NUFZeo1F-%Cb)UGmIe>cZn{VMd8h|s?V0nPg zWNQZ5`X3Sa+yl{|O#ACFWU6A&0L&*FK+QKiYdTs49=^b~eH0x=+|$1sM131V|8EHI z8y3-C1LrT4`_~_+$$Kx$^`p1s`te(G;nvwcd{Zqxd|fUdyrD)fJ)wxjFVK%)q=+VN zS~zs3#w>b44}8S)_L`+^%icyed|U3HpdEhtu9_`lLMT&J#;-=2gPP|1JEj( znja7?!}Y1yxOdrh)>jDJ*bEZ?ZTDVzhn`*P0TW|RwS@Gjz8 zHqXC(maL*m?S~KK<9B%9>Ob*+A}yU-e#@DWx1O2ROydIP{k2(Li%Z9sM_knq^QO&b zZTVOycYLpd>y~TZCyx+^<+?|$t}e!(Tb!rg?)|CTtaES$yil5VlE=>T_kGopTl2E$ zf2JJNxx9-?KbFS2A%!X{D$;ed)+@E-h|)scXRhiuW|AxiSp1*(d^`Trpf6uvf z`+TWdEL$S?FW*;_WpAq47w_nS&t6yHBg_?pO^lFn2e; z2i6)$U_PI?4{i&$rmmU>VDWD;ACI5F=7_C7A4IPpfXBi+P-8nc%p>^F8+Cz8nb*Jj zsF|Ai?CVMxGXpPDZ%51bMR&D4Ve5U_T(Spxh0OukOwa>poR+^VpZW6p#PZwtqSbn# zJGg^Uyu(=sB{BwG5N!ahGKd~PC|n^Nt`pf6%@1s4YmvnDvl))j#60JO78pZ5u>QaC z8q0Y_*Z*;NcmaB!&E%afuF_iKxws15>l$lRo!{`$RqS=~jKdIh}O~ z>HF_Y(XV)cwx*Tn$)zjk#lERmzFg~g3(phpwq`&s`eQEGVn6w07`JwOwZy%7gKY+=wBQ2qoT>CRuPb%stJ?m_ zGdl9aOG^J`iOwhes*IoCQ0B(>bzEz~5 zmAc|(rLA46Jq()Z|Cdu<`0#=@_D?!tY`M)vno4#OsCep%|74JffY-& z?&DXq|Eq;c`Tlv8;X$&PH-2w^fAcCBcQKrC_20*w^?`{02L9iIzAzqN;y8k9!RBY< z*bL9wym>Tr!iyYW9@QYO_pa3X!CcRS$rnSx{zLJW4Pom}ZF6nmffnx~A7U?f?i{(j z@uC_%N4&E&A?_Q!@Pzuk_L9OEKBM5t6V!eB98FujN_yvIxlrqykvClN47hy4?PvVW z*68!M)$F5J70c^~hj-FQj~I0(*TfS`?E+%d6`ychxW7B=d3oaD_ccwO8W;&a_m87K z690bWslHR^u&yC|9DE(o1+SfNprilWdU}r6mYzbB=5CH2V0xa-LfLvdL16D-VmrWm zPfpFm0}20+W^OJVejSd#HoU!g>T0j$IlnVW45lEd9ZE06;EarZT&R&0CE#Oi6-JgMV0ujNTj2x1<{G{s=%AA-Rw0dR|GazU$p_PY+k1H?YSEU{pU2(X^% z{}-6eOQl9zP0m6~+jKC49v~id@N*$s8MSjiI{D$eYJI+*KKqVTZG#^?^ZrlTe4p8G&ge7ZxcnFHFx%)k-$cY-)erJko6->2Vq3Jjh^E=ezBwt$}A{%qnJ z?e8$XxHS3&N6xWE51#zf^bGfA6*-#0G2(v@y$PEw{1(se$LscJ>a*|b#brP1{gqqj zKd#mKlzip{zGuGRU9CQFmOPb;c1V8_{$D^`6!1Cn@dD(4_xGT29Hw7jo&sC9)Ybxg z_v0^}^>H(fqyM27Sj<}MUD?-r`E zFo)QGO{Lk%`rEkG&#x;#Ws|B)!C3o#R{H8!m9uxHvUYy0bNg58I{HiI*3Wcm%cr_< ze6NnLT&zoHQdM~&%jwhSC#_ZXwojC|f2E32w>UiDG_Ozk{v~aB?{V$?e6dn~cwVKs zr_dyBIQZVtDe*1YtdhmQ;}N1S=y;dl1r7aw=6|RWe#Czu*KsT6Rb%L12ed@%0z+Dj zGacKoKm>eoIO}&#ptg;m#tlUe7zx%L%hs7%981qI5+sn3V!raxxxJ( zczTYSJo%u4pPa8o3Dnjx!=)MH)NAKP1x^@C{kMAmhT|1zfnT86w_pJ@fsUibXafGf z@x=bHu#V~*+z!uw8+FJ3GcckPp1>{|%q&1B;>nk5J_sBh0ZxhOHJTnhT0FJi_;4)V zn;>*Ao0;)P`?h#$1mCwFUK4uljfwrHEj+3H#J;_TIeX*MHtTCMfh~J5yN8}0N=!vE z>tu0d`7so1U~@Fam#m*2%)V_7-wRzY7{6pFYYK$Jv0dqtxPk%v$VaW&r}f=pdK-tJ zuTLK@gzq*MZ;t7J=1s6QmORliUGNPG?>*lDWaqgi(&KI}H8B*8ed--D!Gc`|<4`I9bR% zOcHD5)#(g#KINC0r9r>jNKV+2oTp7}+u;4Le!hk^ABaI>|E(|A=||>yUjH^xkG{Q5 zudPhfkv!J>ET?~e{V%pZ|GoY9{tdhROPSaH)aifkH{AZ;U-!Qr`%_sr|5j4@b$yeZ ztHob#;}}W$Wcw+6rAP1`rR&9yf7Z&w=e7FqS#3!#V4aUsI?M4dp|{oF{7p62@99J? zee?=#q|9q8vFbQstmk0ljGcN;gHq7i`0prxxTQfWW zHZU#F`T&LSh<%^T)&6ZemAvLXT{yad82wJCw|(lwf9{?il)dvSW&HAn&hGl!sqNJl z&#N$FzcSXntLu0ER&L5p;{FBQVHV5kf63`2m7Yz}-CJmfC3(tNwOGX&iOK>Glw|H# z=K6P(b$GkBES;@izj#kazgwj2Lz|f~#Vr(`cUfW|h2d^M@_P(9LZyrwf- zJgH@0wFOHDcLCeB??B9sbY>LeEk@AA130I?GajMd4TB4?UJt!;*Pw7U2LF48##3L3 zeQK<2?#$qux7qsfwti?B@fHNukH9}<-%}{{KDy^F1d*!Jp^jSc4?KH$H+cwtnXzXAY=MpP`%=>!TSCpbu*~ z$b12==n!tKdFtwCzNT>E+h%!tuvXv*aL8b%2Waavxv)l?t@qQA511z)HwTg*{P8Eo z^<&U;2g>q60IzHA?m@4eo;w`)m)*y7@$!9U0nQQsRZi`%!0S_a z>v#RI<&f4LI-}H!*Y)+U2eov?E`5=hr5C>0sbyPi)-PY*q+Hajm%h?x%mbXea$n=8 z%;XyTfA7C3^A_k^{77H#OxMq6uW9kB486U*Ko7nAm6raLsFiz8a~|il=)G0?e$NTL zzI>B1@fy~l0UDP%o^_r+27M0t3+Zr?4g1o-Jm{KiZ@u@4@H+ZwGi;@;Mh4dNOK;eKTI(RhESsx!||1p_?X zZ@iuuK11^dPuAmur)oYL^W*&|XdZt*Idp~|?Khd%Ow=^$Eo|H*LqtfFei2WxA6*}B_> z^yG@zD)IUrKgW6*VDC@x_x{2>{{FLN%;y#8+dZfB@{jxV#jad^vHh6lz43zGLQvDEPa*gD}E)ct(si>lBvGl+j%&%ks5(+;IdRVVco3A%!J*~H9KdW~heopVrdr3>@ zEYgP~=O_-G?~BIg{_K3Yqx;P~m8Omxf7Z++2i1GYTUt8qF)f|>td>l9TuUa;*OG}( z>Wy*p_42d@dTji|nm6VlJw9-n77U!O1w*E5;jo!nJoXViHE4!LjG3(-)1OiTGbf>N zb6dC9xUUbmq!+z+Tff8l<<=u_;TzDv_tF0x{Eru*1$n@HL4FpG@CfU7wnRfWJ=AnJ z^VV4Wnl@tVX$P|=i8CJsevj&E>yS{7$u(BjL+I0a;oJAbo8yi@sxkdVTL(D?&fj(z z>kxn^;?d)5me2gZ##?M2sAc!T9Gh7^;@H;cvGu!ydEOI!!`A!v;QZXlVV+^E;mbJ~ zkMQQVu^9r(ZN_)JqFC<-{9tRknNQI2S4aoG3wjyG6->vCK%=l+5YFeZ__sAWO0V3} zY4r6Ab-%OzRtY_Ryy9Gswzl7Xp8t{=z2yh;srAQM!=r}vbx@gmmzDABTCll0`f ztMtk@yY&gPdh1z(^AO&>(crEyj@O#nVDm`PtdnH(SoU2;fHx!1NdnPKeBe8FYnrL~ z7g`S*&l*Y-G;r!88usuaE%|n}Vwty^M*TmCPPiDXKXCzl)WNegXX!6mf8@LlohjGO zw0!D+krsTkUaL>yPuzMOzd?pd@BrJI!=?BNbBOgU^oR|tC9p4p^@H=#8|XE@wse`i zo%z3Gx&^Pd9=gr@m=0Kn4sV$HKQB-Xo(SUv=D9ImaP$zG#Cu<9@9x8n$L=@gq%L1( zZWm9$b^3qS_cIT!^$M?E3VmoHc`g|DAuw zgLP5=_=EmGy+G>+IzAxwn|&%*E52E!AHVp~@g3P*qOApHGXR#O%)4M(e|=R0<~P5B ztp{qo&EHtF&FX&?zBbc@&EL{y=ya|P{yh*6{w;|>dVg?G;{tA6!?qqx7}rb!wQVxG zz#RM}Q>a(7@RUrW2R;(~I|EH=;kem)6AF@%OvE z@~nKm{6O>1o>JT0Th)E(J6d!yU5me6p?Omt)q)YT^y-5P_0oe+>zSEPY3_{2kqc(% zvC*@&XyRjfY0P7KcF;^cJ%~I2&REcYs%C*tI`kL{9!LKpzMNS&;xCXqFlyejie+u0 zz;@^vT>I9SZ`7=rGxygV{%`+gM{`fs;G!>RbT+gw@7 zm$RlP@ozKvrt{gHpUv>un*YA+)AEBa+JSp;w4+`4@LnIhgVv+4ncfI|8@}WM%O$2m z*nE(A0?qGWz9L_8iQ$ki^nV}lf)6u=!T1rZA7J|5Ir?YTXFJ3?`RV7YoOyU#-_O?F zy>{n!*2&7!2RpO%9DTh{6Ip-a_(g3!&g*llwEk!g^N$;~;!uI!*my#p?>giByC7%5 z5u>L+tPr%AZet&XS55&tjp27`$MqCVf5ZA5QRFrAYBGCCpVV-u;UUj3ypTc6V&gTp ze?MXLldteSbkL0X3v{IHs#YD&X5HC0G~$_W$T_>T1s~t8^b1;-ny=Ts+ov(}Ki0VU zZ|TL4en3mCrRUE&owe7THOX_)19u)}jgFKo);7J&ze|+q#Q%GrGkb#mpN9X(W^S$T z=gjR8x7Mq-zpbuXPu=_grI+yBUA|6^s8%X#25w;7sC zTKV-Vee~|?_HR>|_t$<8Ki1>%u)ZL_-H6CenoRDV#dY@(zwfjjBQ>6W(qQ=M z2ynuKtQoYB_5WU-yGW0&SgnqS5;b&hqI#}dt=3sK-~XX3l<$dh{Qr{v#)-*C=Yiu(299WP)Z4gIf%kt|xm>)}sky^F_*Jd*FQgrH5>3H!fq8&p@JU4ArE4`{3UNfO=UATfL5=SRqKnwvt@-MG;qSI4 zcR(wf?d#;=3S0Bv{@stZLno`(gxO9!`=Jf^@|_yaH$BlG{%*e92yl99G+3KCGR?u^ zA6@&gFM9m=8C(KckDZ+2Zl4eR&xgltzRA`rG|j^C7Ls?uiEqO|*57q>iO#HZ+=2Cp z*{9_P(?z1d|MqVZRowZzB?aZl!;jq4Vim`J>A%D<+U)@5t%TdVZK zC+oEluT5qdYk}uh=^+jkt_?loezVg28RnLhLCmYc_bnr%72 zYIT+A3SbYL^SQ(OZ2fQB?h*UHfe9?PT)$@T$8XGMN!+oQHNiK4L5{H>%Ok8sV%Wrb z6!?ft`?s~nj1OGq)^dccCHx1T1pBWwoH~rykEVWh14CPX+j6x18(8K8u-=t zK}ZhggtOb)Yp*qKv_KBCeeCNTx-3@uVhbn-_G57ZoLM4g%1h7O;L(< zawD%#nli#i^|KWhu`>N*X)sOgDCHv)D(nIds(4JH{F|41rO{IDX-XqYNIx0+K2t;p~E!7zL~L>e6#~B6aOJJfs_NJ4I++n zD*T`A@u{}+Fd95r`8H?iD#!oJJefwFmrmw=`<1?3I$95iN!|TuALuke`L(ombXRlv z;#E7abDyo6x7N1r*l!mv6cT6R`aW^KfIkz*>gV;LJn$S30P%};OC)Z;&yE~9K`ufsko=^4qWq-V zFCPH$|Ai|E3(y>+_?H);_yoUHW{_kwdKHH(#3X*x^=k zP#?37Ev!UyYG$Lx)@$5E^O{6&H}+c#S-Z@l)~~P#KK$1%g-0~W%8ul2X5JioV>nzQ zYM%!?I**_*s~c6_T9AKQ#=t*_u4DBgsewUJ=10zwzlQF5i@~8UL2WPQ8^+GOz4Hz6 z7aq@tt1aOD!DVanx?lVa2d(Cd`py{kK^ z$XdLYnFaiKO!eK;Pu73Shd`KHFxZ25J)Z1E%fR>R{mppZ^I&{%5dw*2@%MZ~&=Vl9 zYG!x2MDg#md33A)0s8`cM(V%;=5AOyLVE4G$u7>Ff>(Hq`?t}qLGwT`^GXcQIf$7+ zcLkd1qIoQ7jmf{kF9!TW+F;<0$`3(2p40zhN4+0RJeSzo3;#!&+V`pd56A;~?9kSr z$vJkx78}mq?d#cFZPn51HfC-t{Qj%#4jyo8lV@8l{$c}W?67YaaFcQo&OP{FyPo}t zfBJoLpcn5SAAYuhG3;09E5rHuR3WEU21lyQZdJXAe4aG>l%=21Ewk>NG`BSC1s9yx z+I`>?ryL z$#DE1@me0x%UlO@JI)PoJg--`&WUh?3eX4}hyJ(I{{sK}jrm=*Shf5CSe~#t?f;bn zRR7hZOUFalz*Y2q5ATb&(L>NWo4XWD?g|=Q*PUM24d#Sj;Rh;i#S_$L&GqiT-CeM5 z0^#hFYc!iHrgbayjCtYjx-ZY5U#a=(1(ZWx@Sz)^pZR`q5aRf|r%srG-$)Aa4^NT4 zMf*Kz{5ZZZxl4Gz>c4ou;spo;_?@}VxWp?57F@30$J~f@LjP;Hn_FFf2It2I&PvI^ zB96T7fuwySe~nP`LEW%Qj+4{2>|53veU9k0E6iujLi1cy#N+dwKgE2h{~pu6H%~DC z;@knf*6Cw=tqM0M)wy+jt%P-Yzm3`8-d1AdAol(22*<+r*M5LI0FO~atoXQL+z$0M z-!9y)kDp-G$pg|Vt`$)Q&9SQJ2BJ9{hEEx>UmQQcV!j~`yDUk)^`Mt`AKV32ZPd(a zwd}_JjT!`J#shty;@k`ep(`Y<-4gJCbVDrd4fzlHkxxpYVJ3_!n%OA2?#JxRRR8&4 z=8&dXIJ~E5aL}@v{lNjWE0rEc8RmI$1@s>Gi>zFfFNw#VqbK8AGJ@Q}UIkpwKZ?An z97`9UH@6eN`xGB8 zYKAnmPZiv?rCW}|ugSF$3lG>wy++!%b2i$R<7dzZNpYS!vE18E+kVy>bo$2D9?x-_ zJ(<^kwvK(j;KtxRo*TPRc;lM)ec8Eq2D8@;hck-yqdrRT@21(y`I6H2J3m%%f!EPO zRqm`p{(jvj*!q0+t)&pFyTJJ;p*u9^Xr2vQa?q9#`wMoTvR>bTC6D}(-NI5Ey?BRh zMuXtgB`{66Kli~ibiXYBfOFgnU49_Vk^AnZQGB2=lV`a8KQ)>8pLkb%sc*i8F28PS zh4(3rgq>+7&|ckfg81+Kdk)yDg{y31>~?VYG)rR^KYB31PG{!W@nb1=CgYroMd1g+ z{50Py)`bNq?)7`(6Y9goKXZcOUA=;OfTH}N8{ne+pg+@mpzlrP?^?fVv;74Apn2qu z<_U6_Fbeem(kD_+Am1e4yp4S!c$UjIci&5wNG z#jLL#f6389%(D`lo2vNu!aeBo#z*Gcyor?@eCsTy9{<$$`SxY74#Zs+}>x~}`#lG5}bALyRW6FrZ&+J1r- z2eqgS@j(w-LbE0HU;Ms+sH$L4+6Q>M-*>mb#G@bY%K&m*tNtDs0+>R1=A#gL1s^zm z@(5L*B0n%aZ)vRPZZVj;r(32_>U~UY{KuFZs=eO|{sH;{^vu#V52R-(x?u_hcf{9( zysW!z%`Tt&(Z&Y_m{(LeHdQfi~sy- z51xRRKY9iq|E8_lchZiM2Y$-BYh8xUwjSRvx6LQ7q7zi4>9qr{@6gHHtZAQ#wk9Eu z@3~@Uzy{iN>&<(N|8Z;ida>g6I+_cw6)VBLMG1b3|JLvE!T&ivCSSl@1`iu8ID73i ze$Cf1r+L6p(*LTzS&e;}2;;3Y7CBsjpaHe~v0 zn}4q$Zj{|*CidE#d`6DUXM z9!NPspS3ekZ@*_3xo7!WJAOD3Ex=2z_jh*+#;5C6q8-DfZQ`4T-lT0jSKxi`8aCH-u0!>(3^p73?FE42KTG3N8apA>C24qg2g#2|{@z9R_sSu{p#11{ z0)%~X?<9;brWW3#30P%@S!YYHv~TU3L)lnU}d`s>*Jx z68wg6eh%_bl6J5>Q+?=-g3DHPxvD(-nTlW+!W4w{X_gLQW(lpTk2+u!pftwi`#$d|EkrgYne}evpX;TV+-II4V<&x+Ji^T z->?_|pzCn|&Z8fG*+wjiv)Nk{(IG$Y?hXp+cW*y^g$4+EqB$4s0=mF6!Oc^1uUY~% zTHYq3Cl=Lz`Tsbs4;Y+cM)g!Pv*Q92_v)W-pvx<6jc$UZ(UqB&ZEKdm=RK8GG{2KC z3UUhV=z(}!O>C}O9BV7sVQ${Ai(UO(TfJzFZCtU*Hm=*|K6Y&0X-5tu+5UaUEH&|@ zWuMNrE93%sgP+UH#SbLkJ*U4lKvnnU4R-z79g9DZV9OS;|Kt0vl1r{Ij|k@%&&TP4 zqg`|dT)=4pz+b$MhlqT@ispYWa3kg|YJWv={Ms$LQY&;r+R%CC1cT8AgK>)!uRVGY zH8H{~*kU|`(A|K~LJp|p8*VlIqV2=58dhcfYGR$cJ?g*D0&4!8$wjrFS-=ZTKd<-L z^>*)u;)n6QVfHy%ybV3@!JIzcJoP=Zxc!?k&U~h7W*A{5(E;_~qXZvb+!2-P(7}Q= zLu!U)hZpJ@VE!KH{cyvhdpU2kcof^kxt~=`X!kD6BC2)+aQpVeL2YJZ_L;)*E)UAZ>`b*PaOOs#v$-)Sw zL#W#UPhvQT-oF&Rz=u5t+S~LW5%usFe~a%2I~4z4+98_%#rMbys1&(H`d`<<|FVgRZ0>S5>`Sy~V8f5$%<9Hpnp{&>$JwUT zLR-5x8Ew#C?7LM*?8n{d@NCfI+LmHtR~&$Qzt$$M+-GBE$8xWOX4cC;ssEq+Q=#u3 zryBJ?>**ivdCUjzo4&umx(uI%U(hu>gkDH&e75x&v&07fxY=fGJc6#tOULh%SJ%?>lU%!Uj z61!>(_roVFm;OVTfS#*9OaDW0uib@m+6`XQBfi)1|LE~l{~eDVEL-}%QN(>XwMKV; zzHnnhb!)~fP>Nla?&%|He&F6iVSeFO!5i%_A98?qs8vP}q_Rh_HUFTk73YrEle(?m z-D?gpO%r{M#mSN1w-32NHD3FTz|vJ+y>(iEhcx|t97bG3A65iSkhC7cC$6?{; zRGwX6B(bcU9r<$#@7KLiaWuTN?+a&sZ;S?M<8J7X(zn-X+?pF4ZmhvPqTm&lhC>m= z&M$;sOM5!;{2W#YH_^=};CsqL;{W?l<4Y0K5!7$_v6XMw%&IkM4gU>4gL=#*a2vIw z_2b`6eB%&s*)aIOLCRU+0m1Yy0sI_v3#q$7^#Q^9nSfiCbo}3kZtj=f_Zsf=o-!Lg z6oYoIDd&+2nLuy-=BcK$;P-Obir@i57Xy4{{M+%$HDB-^K_UW_p`*= zeeQfUM@y6QGMKx(G>YO3&pz&TGg30B>8owuwtdv!tB!vwuC2aDxbjlj>(o<&h&Rf41ZSEV^z2E2mVDuNw|7j0jfiGOPee3|be7D$oPFjifU^cggH*7Qd zz-#zeuoErKe00XiXJ^n86ON%B;1%${>-Y=nvpfd2a{HGI1|Xe*IZKv1{m)Y=sl=^f zmtDNu0iYd14k^r2UyZj0bwBSs{08QTD|qzjKH&7pbXx}xZ^Y0EmU@D_=|XhQv+(dD zMy0_o{Q%*8n&DkOfES>>pYVEleBB_PPb6lrM>t~JHg31oi#OW9KEv$uz5{F`@B5h( z=5XsD$FBd7wGIEo8FOvr!u3u=Ew-b{JAj43pr?m3io3laUHBc z{fcteee%z5U?I-`hk0LIcInK8(-(S!^@%&`?%Tn*L*c0C9z~j<;m&rt_lw>q(dlMQ}beeAW-Us|#62Ak*PQS|mxtyK5!7TUJGl_d5{5>Ms9 zb$c+Q)(9zQt;4EY*+E}eiG_;$spgFyfXB=q?6p~A?Zb7kHgWm_tNj`}KFsIdo@o6M zr{X7Q-uDHg@Gd1EVeVkq>lY)gRWpTM`bEMaceTX!ZBiL1kuq%|Gr+SF+ z3fw4u+>u)<_=C&^@*S_=x)&PioviN1@=;@#h*xoWxW3W@uhYCEJHEDX0Kx0)Hg;Zw zf#g*|2)h^mM>~wl(jTh}7QoFzBv@h?y+Ifp3F-ZcAMDBV6Mrs<*}qhE z`Jf3)tm*hc@)8M$D-giz4uP-XiU04(!iUVl_;C>bdlJt$t-o83f3^H;cU|qg^5`Ws zKi77kt$7H1@a$!LG_r5m^o>b2bpB3jI~XoMyt}VvZ-Nh)XFJdkFMRqR>)faRKN|n) z|I?}eSD*aLHYdPGr1$7Qb(786n}+W99-9LX`NxgNY;P*J#LO-yP8Zmf2ftbd{DoU+ z7-phDRKT2*dGQu8f5qK7oaFX5E$=G$-&zX@2w;zvU@zIVi-)87d6^iOZl-$qoUD9e zKhG}FhZp41ix$Sull@iOKZ)nU>m`I3V@Z1Dstspgg;TE=;{> zt7py0KelWdm;tdrdy*BKH_^h^F1HSS2HBeyV%2>kEtpxq1aT|QehKd&-s91(7ty>c zT}=6TC{~JtqkDyci4ilt;qvuhw?_Q?F>eQekEvIXHgFU;p6Yo><$A;ob3h1uL3Rlx zi2LHcd@utPC&#ECFAmmFO!Gjo66AxTdjZ|(iihI`7NNeR+}n+b@vd+eJGogyI{%G3 z_qY0OdfGc}dt0S@u$}po-rO z)P3m|lp=5GvE+AfoY})1p+r)d$**v#n%R{&KO8#Ysw@br6JL|kHpR?3Pe)%n$ zyqoCV(M8|1-8QV)Xt67|SuC--EctPl5!9iTV(DR!GB zfGeD5e#qsy=2QQ3@d&+o@tWm>L0qASDa=8$gr4BvPXDhs?=|8dZoh8Xb%P=G~Uu|9@b;;Scm+&)k|_Z$rNKjo@-d7mG#+ z{Gi1P%(Ht(D?8?UrvBH=i=D0)^}ihTwF{V8?a*@83?69b5dO{?>=4#2wvv;+u@G*B z-$#S2p*Or)zetPrWZtJ1>o%zvv%c=$bdwhaFD9mj{4nvj=RL36J{K$Gu#jjpdC37K z+4q+KNAn?ugwN~#NB+NM;Py+mPd*;OaGIs#t$RTA|HauUs1GRSg$4(oi^C1jJRm)e z*VtKUe;|K8afSkU&DE&It@;hMw_9|g?$_a#3SUHY2b%W61E9mFcmQ{?>ePGb3Y2E= zR+^c;VaI+}vl)0Eyx{WO7`)K}zwy>R=oQchBFBouA5M=UpKtBaAw&Z%35671BadE!@AJ_1Gh0indbH}ipSOa-^I(EOiC|DSVD z9^VD*0iVDDzF*{@1z+xoI5XVP-{9BM=~}Qk0bL)wHSRyN6V%mZNmp&;iX@w~{)i>z zKVgI)u)c+4!wEJh{U;97s|BccTCBBEwT4$fn*h{G%}{`2(I+VP#wI_tcB&yg4O-+AXR*!FFEZOpLIHgnP(FufC&2&T7l`##%8 z4Np3hY&-b%j!nBQZufqN^`#`?-)I{H^FPDv ze<7FoD<#Xeuiu4d*mhe1X8HAiZ*1I{$riU0EHUl~yn{sB4Gy7Sp8`KfPDr)G%n7OV z1P9_0oOj4Y_6mRe>p!mkmtp_!>cU@|Kk|#;qTf@_ z`ha0eNBjeJ3?K0xeYaI-crJJdfr+&ZtA?jo6|}}nTN&p5fZ}NMfZ2KB(WN_^s@(Hb zZralA#7nfe->EzcQV1mN?>$K=@eZQM+jobGk zpMuAMsnp~yvSIsA?Co}+a`%Up5_UM{O@99g(Uxpw+g1{nQ0%g)RO zYopIkI_bQ;=g(MT{d)AZj%_;Ig6Z>YGcmen>pr)aKf~9no@>AFy!zZ{W)fol8aKNa z=+iHPE9T{0U_X$BF91FX^c^|WZ~dJq2`SX|W7PRMHk@7ZoJlim^@>>Ay^($5c)V8T zF191v;%oyui0!ePU4B?NeW7h#PmcHzUefaQwtdqs+x^oX{Kd2ATdt!2A^gvSz7Z^_ z!W-~_J5rNAqIRKI$3Dy#EK2>cc<#D+6;ACBR_?*BNgO$G&!wgL7PxmWxN)Do*TMS1 zjqk%O+pYG8)(!qin@SC=DYJdEa6D+(t%ZP#M|&|p!~J`c$M3=2U>)MW5&ZBEz!y7K z#y7muJJzZ~eW&MJ-8ag@JeV1%`yL^snAN$<0eh&)Y*Duzo;n>BZ}0)&-U^44_P2C0 zyutlELf8XR80rbq;u#)Ueaq6C#^WR zzqEn%>yq$@g$D>Dly8XR1%UI_Yt_Y?_xRizcl{jw1n~r0kPo_9jV5g!PABi5GH(^_ z;iT=MdqiO<^5oL&pB_gh~Hgx&+cJ4TXoSc`E1LODnwl z#0shVkDtA=2i&IqO6)&;_L~)4zK2Hc6U(OGU%KOjtv^;^vo;??Yxja}j8C`KN9e%^ zO|uQ?fF*(Z=iDZ~9)YtHhu!`^nEy}HtM4WLcOE}$!zRqL7X7}nrk_r+-eZ^BVQ!H! zF5Y90`4s)IU*Z1b!0#zQ`vV`I=fB(CC(rHr!(Y%fVLx~KiQ5gzA2g%jj`RNt3<_lb zo&y9UW-%&XI zJMsD4XLF~_vkl8)ZR*5X^!meW#>D9k>pM#?qQ_djaE+~;yU128+hB`-Tw;r7Ewahq zPqCSB>sQZRZnMTswfR#P*o09NY!UyRh(GBadWygGzar?tr576mw^dyC2=>~3%(TM$ z)MHB5CK|mRVa9&U3EELRRVxYr_ojF&vps>a}9G&#hj~=GM7t zBWqvrJ^LUM>`?eQm_3fVR*zcy$-8h4h&SnoH;0SU_OIA~pM5~B0D2JO*OTWW-g*#y zaJhz!tyYVUcuNkjH`{zd&kRQ#JUk$}JhOgj7u(Xo@TJ!IMWXS;ZHv>i^w5P;^_QJfPYd20r@H zCtnh;U7U7WwWgi%`s|AzAei2J(gpgzkx*}IhVImCr8>t=LeDL(Y!@?MhGPYiiL z9~Hqwqv#>Zf$yoW*A2h00QvtYH@iC_^0m_zrXPr?g&q+6hKg{6%d!iIVy6(mpZn7r zD2J=>@dgWV_gkgm|C0y2;3jG=2;yg<_|JRzyVJ&%SH^wn=T#g&ym&b7y{@XbJT z8qVBG^tMOM-EN!HZrk`3yU^npfnVf0o4Gs3dH-c-c7Q{85KZ1|&;PXc-T&hM{X;NCZYkJ7Xjfc4-wsp-m zn~Pq@?8!51#`qs??&MiEbLu=|e7a2cf9HDe>9)$-m=T)%v@kor~GJ3=B}`DqsH0LfrD)(UqAl4Dc0d*Zt|#+ zqrVtxt7a{=o$EG}v+!F0zxeINAN;G7bbc}6)v599g`&Bmjj4;?HM^{m%(wEe2z0vu z@ImferKP9+yEmLUPxT1o2+aW%bQcfL^bO|SI&D9(R^*FMxr^_N&O;|2^V7FlS-Xl2 z?5$9+C@}J%;@<2GYS`!K2{mJ<&;bmhBiKRLO7Gi8W$Ial2x?n2o>bL0&F2Q3lXY0mA*qywAv}5#!OId=vBi_HT2I&xcaHFW3V_}J< z=-q|8=S1>UjfQA98_wNF$j0r5zMW>`UuE8Vn?w8Auvp73zP$ZnCm@ z(<2B62<7#NUo5R-U*cZ8V%^n*^R?muNc-q6w_w8iE?h@D{^?80pg%ly0gaq=bV1m+ zr4`(_ZHeb>^*(s^X#F0){KCFnxZS!9pJsz*Znbe6Qfzu`9GYLRY&*UiDfze1)Ol>( zJ{|B6MSju42>;jqPr807d1#LBNwSSeIaagfK=uH;Y&Ez*A{geX-FS$AW9~b3(P;r@ zk(c%!&%}%1k$Zi2m~Vdl<4=bZ$bVd30}EEKT+9q;G?3(R1 z?T4v0Yw}#1G6jyrX9I24l$kbT@;n>(`PVjX_y`*|V5qhEu#NTW*^e6kmBlWN#n)F@ z9UckumXlW&S<10whe^1-A^PI+`xE&4R`NJAZ0S63z`?`V8GdS0cy6OdjIj=Fx}mxC zwtYQlgniy^ur1FMUK6E`hp*73Fj#pUK74JJLpJ!I76v1+8fIoM?I$Q zM_g_oKWKNPI0>&xFF<^Hhw7FCodEh$X@gX4+zvf#`q!3StuFm&1LoN`+Vrq44K){_ z;alM?=lLDTd;cBk?VuJttSxz=|2rM5%iC?NIe0+zcUxNn?rYww_>R5F=bH4-&H4B-#@#xCpXu(wc^|?7RNVW5S1SLB>k~x}-;g<^ zEIa;c+)q_{4}2e8G}qfRt4K>w+`<6ru5^^dN7Q3UTfu|-7IFUNH7stCFWA2BfrZ;? zmmt1%5VMN-e0~vS+3i*5c~xT;K-Y)osk{CN?)_uH5Ttn;#f@OZ8|wYRG01`9ItB9g zhgIY*kmn)|G2IG??-_GamZgaAYTAN}mzL;vOl5g1g2d|uO*Ae0`iyc7WlmD>)|7YW0 z{GU_zU!qq=TwZ--SHJ@IXWz8Xr|m)u5dPfF7e)HzaF4g8g6(Bqx41LcY}Fp}0{P%F zxg#r&oBb!R>@+!U&(YMP{Q$o|a>8_{|C!-7~F^YsrlW)QkoeBT^)cdOyyO&CG{|NR7;GiAQ5m^GWv3#j8`Y%H~W*uat2 ztJ^?!eN$}Slvy^38og%zVp}$6k^S(^Wb4iR*t2yP+p=b}!wE7^W!i4$h!LL+1=rug z%zgzPA9wwC9-=dLg#5FFnE%$sjrflHzu7kAi!W_Z_fM=l7*u2Yx7#;sWy5;)vyYp! zwozYvZ4>ARcCFoJxf$o}7W{-iUKQ2<7%=ci^fk+Z-IYe~stj=`9ewG3XwHx1)<&Biv)--y+VI9b?EBUOowiTk_uAXX?Rui~@}<4o^D}G8 z?feH_`dHa_nNg^9A-u;u0>R_p@=7y1Od6cjv@mAt0P>Oe^V0q(35U)zOtnvVIXAk@ zFyaMxlOM`5`$v-0ajpFy{9 z{XRRuOp=MN_+>c!mu~3;4lO)_Qy1|T$hu%7snJ2q|MLHP3QtGxy_g~!xl4_pNLOp zmPaFb^i=zn{otr!W7+Nh1YW<__HZ+_d)pqoKjUog_TAu#7u@a7Mfe3%$Ir1&ZMuN( zO||qBY3v~J2s)N(Q^rkUCYWQ(m#(pIzWSCPVu*d-gIEJAYT2ZPyU}NGY}G{Z;G*D~)r9L(lbKkt(X97SYuEp4s{se* z9qME4O6cm-cUIvprg{J2%nV(vYlprzt}~i{J-q~H>A=YNVH`a3CaBIT%H|X5Q zDwEHuFjH4#Z{|r%l%Qt1+ZXC(0JxTL@MvB~Br~`0K;724_+lsE&3%m@@!$g{CM-ek zd1-5xN8_t37-Xb+A9ykmXn47u2RTapkZvDB=%1y362#o&&(A}7F9_^H{(aK-uHB?1 z`Qj~f!O$OS%|5S1Pv&&?iPYFo=5X~9(*E;drtt;q(7mybFjStm(*-5&#buHPkvs^L z14{ZZYw#RP3cp0}K(|be2f%X=sSKwV+*KGsX=2~q6ViXg)Z^cXoop#)fq*Lfj4Oc^ zmV>uN?$BM3JW)!rJCUEcKXEU;BFziB|GB}ee&jT|70-X8{{Ln-U5!O&>u{z`UcMjA z|HBrKp7%_8{KeeacKvdybsn|EdNFg?fd>+Q4&NU5ei_^fWm5a|iTy)ouGqlg=smOZ z(Veo>E_D45{A%h-G3F^2G)PeT@-Ea3pcn0^7dH&NUiF^zE8;#0tI_wq#?Pi~r7D*8 z=wIZke>uPM*xe`4@5-`Sc#nJn2YCe8#1`(9kH7_7x;NRzzy%&Mle>ha+wl}ZFXsuq zK2M+X@zQyk9nCDTgQ@WH+5b(Ry$}z{06TRe+1>w2N6+oe!Qjto&ZpmAzHqrMW4_<8 zBG$edI>rWk`h^YtjJ~_?XV$CJ0BchJ9h)_2COfxen=@;^4eC9}rr>wEZ|6?-@j2jj z8N}djJ5El}ozJmDN9o1S@%zk7{I_zBIE9;5t+gTj2ZKFq1w%-+vl(Y>&h*9hVdECo zsZ}RiK5vEX+_Z&0f3$tV{8<;Ar~&!E$-C5F=HSMB?$M^Vef!l2TSw2b0c>zL`+);| zWG1KKFLd+2_+JdV77^foQD}LE*OBg2LwalGN@}S5bN#4y>Jh|Q52f~tpCWCBGWFn` z!+VQ>gW_&onV0?Ob1U*5tj#{GJbSI0=mR(G(2v{u9(ZuIK+^_%n)jSMD=IW-YAt#U zgeTY1-tIowKJL)V+O_LV&%i$C(_!{*@4?ovb3gQaJ26vyjAuo2<`VYc)H88=RlmiP zRsIR!c}Q==`E)TeNK;BTz2fcYbp+El`<20mi+J<}vsZ86!=FcU&l^n)EAI80l>@?f z{krkdeT=wH;^vDJ9YQV;Hc+Ype-HSGbde+YdA!%DuT_FWS(dz4t9e&)B##G=!k4>Z z|8THKekQ_9bmyzPf8_${+7;dGp<4h(p;=4yU)*8s9pP`lc+;XYohtsd3`?1Sr?>r6OkJjYw1lyi^+4_u{ z!L9#S)@SZM>pEZzUss6V&sntg;1J^Xkp-rnb^TZ3e-xqZQ}kNdDNDOZn)AA|8uaZ1 zi`~4{4ksj9^2v1DcaWZT%|>p9`td!UE+4!OcH;$~Lwk(Z;9!<6SKiX;RZbP$!oL#^ z>_v2j*fT8IbILxOvdP+T3%HA3C8glDO<1wRMxjYIWa=85zTv1P6+E)Dg*UkYx`P(* zUHX6dom|0l>@uDJ@%B9!T5wR1^ZygyPrP2;(VfdUYo}Aw?Ep3Ur`R3L@w46hKjpje z7CUFPjTrJZu{y;1_8Dy5J9f7|-Fn$!`tuXH|d&-;IAAAj7#K5X!oHGZ?9b!gndTDIzJi>A%8wX>GkibbnzC$qzj4O{GZ zT)ZV8NU)3(nRYqvl0Bo>lm16pwEDE)Q}130P5+9GIJ zbE)RuXmGB|P1^C^ZNyDmE4)5>SOfY1X^dB(&X=Q~akq)gwqf+D{@MYsYxiW{FTwn- z+c@E7(kKpR?hUTQV^jBniDPMKcn6iHyomG1O-wm%7OH}Yv-1ump2e*f{x7{r-ScYy z7p{5^#u33xtez;6oS^<*e~0dWrFkSxefc74hZjUX5dPn!`{(fZ`q9s{a^4B@-HMmMNabI{jQtClHeA~U-B{cWe4H| zjxT>eX&8pncd4HVuMEGp3fxTkpGZE3*Ld6M2$!ubpAxvu?E0g5-KzaQ+(CQuxnk3{ zR*yNVeEsI;M=w^=$Co);`XBh?UV?`r?g_g;d1YqZd2SO{9<-Ue&Z4jXlkGZr+2(9M zj?Y(;4V$~eMlRfCQ&;V^h4k0b0Xm!kZjgVQS(|;=vp;R%*JF8){qO&Z;kmkg-CA@k zrDF#l{xLc=4|HEIKMlODpFBqILVmeV?R#!T{(t`$Q?WAqpFix-$sBj@n|kSyrLvz~ z7oPbq>%*D&`|5pDm{ZDlHxStdM{}LSEQ_1O;gr3LR*!8v-yl=+Dc{XzBcQ$OuH_YHe zZNwLYtY4Rb*0@n~YxZt4n>~BE;{+T(a?I`N7lIWoqh=pLA25wvm!6W&O#wH4Y3D4H zU+16Cv$W(4+p}%2#eyTmE?UD5AHp~cU*R1*0PwpBs!*HW5IqX&y0qt_$pMw$?+8z&8=SRn)c79uX3Or5 z=Mq7`Eq@wc_`jM3BB;gcMWgYl5I42*d#(6>bg7ux#g!F@E(qLSSeEYIO4ntssE1B; z(@qZ0Di7Wu?V2)ZLY1!9g!eJ;Z7@B}`nv7+pkG#v_b0}*7YwHdaei0i7suu0&xEl_ zyF{@ON}crK?-sThM*pFEd+~T;c#e_epVDaj1hMxk$Lo%!*9l=C8Np5@oLmq}FYiy? zF3JJY-6^`GlQwVw-_vTq2&>x(U6LmF0(?O3WDbx|uzHdpb`8$^6RhxWeM`5W2fq_X zPP{gWTC?ti5BDQwUuoY{frA3#s7dm&%udHDhaaNFd| z=b&=n71aHRn&=Cb=e9WtY!sX{tUR}n%mR`1n^^r%`qM9feS0Qa8z=Aq#TV#k7C8hT zzdOH>N4RA{7v#yGe_H=x-~Bg)+qP}%^lP6y;qK+ut^dD|n>V@Bxz3#mANup>&!6M7 zan~XuBL4drF8-hXVY`#g+vyumnd!yhe~MS=8GHv0*l_j`9X=m#>kg&cn)pmxdMMAn zo%fS{H+Q{d-F#*jZjo=Eu|EVi*p-;&b`%>ArdsZ;Uu-(Py_^5J-;rj<{X67|E8v=N z08$cD?BMnTwvt=BX+KP{@!yVjeZZ1AD{RPTUxC3-vw6(r)4}z|eEEaLu2|3R{~ULH zXpLv!n|34#PT+Cdx9cE%0UYVn)7171J8|T=!xxj`_oR_y5}6Bj!_zr>B-sw{hrgF} zlD*?bdUrHLHt(@>+JpBoQz|a1atp+J z(VLzvvL-%Kyk|8lSKy-teSIA?zZ!w<)kK5868MvF0_o<-FH|uu9}VerlzAI{A^L_8 zdIR;j+Nr&c=9Dk*W!>?Iu>T97zN%-|u0cEL=r=#0UgL#BFCN67OS`V5_HM*~3BF&k z;-@-F{t)*sl+W_EQLM`EuO#~}-Op>^uD-zS;rJfChG^=u(*~vf2a~g^koTksB;H)5 z_c}WswDxTw@EY`3p~OfKbz9FzjcD@55i(JG`bce&spsFok0X2k_)W zf2QB}VV3vSZl9l{_(hN5AO0)z^-X;8xQRWIegRL7EB1c70X9DNi1P{1egDFP=g|8~v*iir z?J#qG(z(l)PA{H)>nSxA9^iT5fxlUsZhc+s4jw$%&6~Gx-~NBay*xIY{uO!__wU`e zfB*a6?&}^te2AANcWU$nfBf->RjypwJ&xi(?J=Arb`6(*{@r?-qUkL$p8cJ3r8TUhkgcaBA=U;&=|j!Q}(t zi=Ix;aJrw;{kl#6p9{C=6!*Qy_b1w_MJpVqX7qOx?Yp7h+o&NU9rteayjWW>V~K4- z?`QAM-Ihpye>m=#o#gf>2kj2++fumWznFW;&ZeIs&J&p{sQvW(dhAmtPQfEcw*5QV zMaI)3fcG7xUys{)i1~dTcg4FbBQc$QV7^^|Bbd+a&sp>YG-s@X+qY=SLYqGB2bYtU z&4u$bX|_!!N6nl9PmsRj&~`Y;^!_>Y8-=+S?AoQP_LLl_`+sTLhcg4q=UR1NSXd}~ z@JKLm#j_g$j!>fJ@J<3*G;8I)0RG>o_ntgw~~&PFPK*t zF{Hl0D_HMq`doSn-OuQ=?(u}HyE|igaBl)-_yGEO@n)or z7f5^ylL({!%MVYrT>d!fo5fKIp+8q#hf?!HnKuG?E+Om(br+-<(p_v=b#{M$>H3s; zyES#ODHsSm8s-S~5+%uj^5+TRUQXD*_5#|EN;^O|Q}48*52A08e|pvT@lUMF&yt(o zaK1O3$M7meU1p!>cnS0lLG%T>$(P5l_&yQrQluvsQ}=!9H911Pi*}lt1(XBCUnHL? zXG!x@cgy|Q*KY7g0!KZ81sP1C=|JMAwcep==f0~th*5<`7 zv`O50tjWd~dj-my+aP3~3u@L=V z=KqsP$xi=M`kvC)lD_9TIJt3q6X4@4qsGs)DI-VOl39yw*dTU*Uw&nuGW#!^I@^}a zUtvq=-?yyWZhJOwcX->;!^y;Wy1U8A=l(|co_N6d?DlV7MMvP;b$82uI{lpKepfnP zJAQ&oz+-J#xyJTv+G)wh@hDBfXP7*3n$M?CvI{r@e-PcljbM?Zz8PrQD8W~D2;0@m8!}~LUIYGQv`FTi_AfOD~ zAm(SqQ6S%=8CUvt(#ZBBF8w3XEM=#r-GFYEgbhfSD;gb5f97Z13hI_ecR?}ml(esq zXJcT zG=kr1>iUDIH{cZWcgsh`kKW#kT%zZ#-;;)bxXfkfTPnUKtzWc;d5+rEYqoJ1CHx@q z8r3sN8&I(?-6H2%j9#g{yTxx(F4HbleSmVC{@uJwaWBmL5dhyo9DqpX4bQL;@R3?p zr3Lw#eTp}|fgbAy{8#EnFD?C4SV{@7~)Ggg{cI<~UFS-7|kU72mC!fN1M?;?&{yY93Q0K4TykX71 zXl)jS5>ya@?QiT&-u!R;|AEhy>i^&0qnTmvo<01#`nmd_fB%IYrO!Bj=b0U%M^WBc zwk^TFn!m?BnGt8-txmA@XcEueoMhv{{!_sVvkGrJKeO{!(d%RGk3W6U`G0NLp9Ej{ zq0L^h+TH&gJrr**e<{+|lzvWOK6)HyaxH=Rf8)wnctCS({=}I!xc^Y=4QAa7{P#n6 z@6DQgXg&D3em!uY4Iehnmj1ZJmJ!3th)L=GT*xbQclgo-xpwKAyTOxB&lPI1e7nTS zSFfPGe+D~9)&E3hh5fq^!1Xx{MwrMQz)9|q&RWu8Zm^P1+pz=3Y|gZKww~OzX3=VP zh0|>6*s17+zz6=3+d_E5`?tnf8oPx8Uc)7Fj&zN$6<)I!XgsU_S7^e`O)WUU;{VbM zL}?#Loeu{4_Sde;;m*VuFlE^xgpHA^^mu@c+>qtPWj``5_@s&&%j*Nj`F{mQK#7`brr0AYFbwbIlQejZNz z`VoJ+b639*Ko8*h0I)3GwE8f2NJ}?>_rC5KrHda8j-b0m|MK(>;E&$Y24#O(xmi#8 zo@Qv&)}wdeXF&W*`$T%$>fhzb9ZC-&Y(u*|&Hj4rZePgVqjrG0!>`%AEjK*We&!(g z`8ZDy@{x8DQS>H(`h2;^!00{!UzD?J6shOQY(%Yjr;C0{#jPtJ#O=BkxkD zAF7{;I2Pmr=?e&x(e1K&C~0Xr-C}Zsa+>&r>K&wmCVru37#ax76#nJ81Fp#9!2$3h z<|{PATcuqO_&;^v|9RPi|M}B$=%e#)|7=N_1@;UMK*7z&=;l7f58#GZ;?*qv!T zMl58IVEiC2Ub35Vq zg%6#_*qLkigr~8`BL}QIb&GqzIO{iMn+=$-%*HN4rx4wOA|4~0;rnnL@6y+BBanXS zfu)lZ5;6+zC@{#t(Rm zH2lC?vgc~mq`vj&&>tU4xb7`FS)U&LZTZ~!wr%r1Ji!vU7s_^VCvEOKx8xsm3vA#o zT@G?VZq5btMJ_TMoaNpp$FiC8_wQqez`TAwBiq$}-36a^xgj0hFXn^&$L!Fq{Wkx{ zMa2C~n>czrT%yIce%S_FPt9MqVxuL17arKY&rX0loR zXK?fAU)Z*EM4h%aGrVr-q@&?M9`I#GEr!;sG_zE@q`{}y)z^!=$JgtUFcZ&&_s^D$p5?t7@TF2Eq9qbnWxFmB(qdla6gzrSpQR*uhD zhC9b7dI51D%E1XLg*I0t{XiJKKp^Y6s>IhT!G^@{D-6dR`U4G!?SA|Yl~x24^uTV&~GJG~&qzkYt~3`+8Ac>_hmp$-&x(9J+_B)Au< zg1_E}pMCA{9O?h&+Y3<|aP$_~YHWh2GX*c;7Sj?}O%k zZT0%RYt=i*yAb}Cj|Z=X*Wgp!hJ5pt^%(StS!p8=r8w=~zrXhZzL`7rqKBc|!k2%b zJAR+r-ba>u?^io>?Eze%Uu^DA$<~|Lm-ln$FMhD3i;rz3+&|qU<*<{yOpcP@=Y?u;?UQH1NfIp2tOI|Llx2=l^S(|SAs`0yZ|@P>pcb59H!o!eU`YR;;QP#&goL|eiN5ozo+>1^cPOW?#=D6 zs7v0ORq^BS^mANu<$>3Vv)`o$;2$5I=i>GnypPw(18y#$$5nn%U#lDY*Gkams^0OQ z|NHmV-|IcE8CW$>I{`P-lS4|noBS|t-Qd0vcbe06-|SNwJpl3NE7x#yvKKk09QiJc zc-5}2G_#BPp9<_irHxY#4AjjBU;`o4e$61l19X!ghUSU-18LJ&|DdgX*mVFJd_~?B z;uxy#hx5728}GP1TV-~c!u`dkQeM>eiB~KwZefe!9Y>1u4<|RWc0+Q~JLDShd-AFm z90!*V!82c{-&fueN3ghfgZykYQ#lWF`YGjQck?U!m4B;JRp^Q6(Mr9+Z9pwMc3gq&hYPSP@w8oifLGoF{BO8zdhp^8>iu1} zL(C$V9L?hE;1W#X)+QMKe>(hsY4u5WL;hL9C&dN6c)k$MPNp5)DO_$JxA$w|_bs#7 z*-LEms?AP=XXeD&wrWW%v6{xcPlja?!>7RdFM+vBhew!#e1GoTk`@=Y{%CmX@#PgH zT`+kLJVI0a7e0%Fd=H;7?IADGe@K7mG#a33NvU=UPV)ZU2f6uUSGbJ3q*d!|!OSJx z4S@Br=S!wHNIWbJ0_FrT195(Gvd&vNI6?~e;w4_opTGYPKl~#9&(e6GYYr|(2J#~;3nbV5o|_cR}uufx2}{jcr^ z+Vo$e65)3h#xt`!_5{>`wni5e|er4j~fARP#PNI@Mt$6ZkcdC zaT~&j{|Gn`QN(;0{s-#$rK?+>{-88iNPucTzo(iV!1p^I135ys4^8I8)DsFN7AQApF`Yz{Ty`br~0q2 zSN#|MC+y#Y7#H5BJ%}IJi4VH~-8kxoM>|!w*MRe&oT$D`^O1B$-fZ2Ce*-)VYJrn* zGZXZhYeS5-g zYxZ>;YcskNH>Q678~psLb?eslKY#p(T@vrNDuK)hwd`N?Ab;0?#eZIYfvf*(;UTHt z5YHzS{NWJ0OU)bm@B#dC+D03`G#>8XahtMyD?DNJ{vP~lw;#W7`^~gm{JKujW8ZjU z`*@7A^bz7Kjh;5&`Tr&yX8!;6x%1LLzvM+`L*^9Vc>bXdDZ+Yu5raC^d#aBuvaTZ zttwNuA^kb=)VM7@UK8f>stz0QiA4KDeF~f)l7pL*y@?(5>e4L;sl?s@Y+d@-A=FwQ z=3?QI^7N?Eq>Iz`*Pb$hJ6-wvi33rFU8HV;f|zTx2h_YSoAo8?UOK0X(5U`teuDYC6@zuY}NmAJXUGVAn)Vx z+@LZ12IaYT>Hj-egDyR}6@K6KRhs`d?oY5QPk%?dFWa)&{r~popSC&fgq^3hkDR{T z`i)ygZCz$Vrfs!h_y8R`chj~UWWNPQkeYXwnHnG5oEx^D8@%J>kyLgE1?(38hSUS#Ph zS#SW4uxHq6%h>ae88M#Qze%=r&3Zcs=C@(ZHaCC7ZQ1K$KKCph>2Zm0|1UVr;{W;W zKm7EI!TZJg6TG_$dY6F7s!Rn3p_EgLYx`hj~k>OBPhA|CVP z58VT429P(OZe+#hRUc3qyiNBtzF_e&@ROp@E{mYYk6`An2>&4p{7qip;qV}|KNN;8 ze-G7i?HZLAwdV+yHafk~+w?N6`wnwIk4nt?k$jExJH;K8_pNekgVsIJ0qV_;q@Bwf z{?XOxnWD+5-1~u#hOpNRWY*Vwr5k2<)2tY0#?t;(o`;%sd>y7oZ%<$3Zu|B9M`Trif{-o1*1+1B9>yB@+&&Cb>KhaRGY+4MVDP_ViQxV}m@Uxyr@m|Vc=mLT!|vokD6Jvg2wi7qa9fxJ&qIC$(jPi|5}u-X zgehs{1@aI*#0B!hg&h08jv%#*<`SS96;tzTfL*B{*eAa*K!}((o7rHgjO<5qZAP!*w zF%&{=*B!EM1N_A+ggX?h8#wy^K-E<0VN4x*cygDpLiN$*&?qSb&Z&Dx-8rj&(H>N> zE*_-#jPgd%%p#tIbOMwUL#XkZ@1>_vg_w_~*O4c9IrfbD*#+=gwTF;ipYCj{H))Gr z8Fx_4xn*k9ftUq@<8kB-?tBaA<;4+lIT38a;rGm4+HJ_2)QfpVdH{M|5$p=}{d!$N z^fo^98uAW%9X>!Y4_`1E={DdYN?z7J;f;^Fpwrk2ULyURekSm%DsfNs;b+4f79i~K z#;ZSV)z*Xd6TSNdX7~%Yx!=EmSM;Ojc8-2K<=QiwxF^eo&EIcdPF{*$@O`vC@1g@t zZ@?@rjoozW^4S~sYd(6(9`HQB_lsTSy?y(y{#|waK6uu#j6_>@V6`RWFgvFow7sVf zSZu;Z`{~p!>o!{;vOzA3d^Vt79#JzvJlXLR+&Boh&f?j0P~inbcXusk}KZ5>J=c~KLzlDA zX$4%!<hE8@!qb=j{yDhA3-ZLT ze4V^I^>;sH29S4;9#>kR((l(zf^yQBLS?Yu(i>!od@J0i`*MSMVXXsFG)L)A`E z{5~J@jQU^c_-pU&8T8kUtR9a)Q*1ljE{vS;H%E^7!H*t1L~}Jax#}HCQYQo9>dKSH zj~-n&@TJIQ(clN-BL{OoTY`O>I5O25^#J#z=c)c4SRZ>&=AJU>bOw{(B8hKl?P|{% z!L6 zXVv=)1N5NxS5H-n=PkZtWo|2VGhLmVpWy0s!7UoO`+xD2-T-%vWIyqmho_tM<5JJt z9<+Oo!K=IW1l;Y(OZyF6;373O`_3zyvhT8ez2uM$9>16y{}=Fr=q=&-Z=&zcxNrwe zj_ZyGaP8Ue%+-(J=rf};3+txm?-DJ0*-rJS{GM^eZOSJ3~xWXEs5 zvd?F1M_aWs_lgB}m-+wh(^qgBo`6ke!*zJ%@{@Xo0p);HaK3G6bq8H)sa(^fJBA;AwA)7o!UvNGXE%Us~-2eST{QFpp`2TOV zz)z+$;HKfSY#hm%52aGd?0bTxZ^{-vd)B%ApB|2LM! zt;sIPvE}>L;MMt^4O#RJUPAM2#u?f=C875=CDA9>{{232=e^W_Pk_|qOw`gs?LeR=VuA4lhpeV=f@GtBF! z*?C-GPmoJraFzKW8~jh)|HAX&1*vBohamj~8p5gY_~K8%&HH~?dk^3!&um+J*Vr|f zA{9vm2!&EkB>|E^2oRJ&WP}isKtc#1gvdGP3uobL_ncGr&Yb#P)$a85*DbntT6^ua(Mt!b>9CDJwx>#Z%`k&+~6F2 z27Jcn@S6XQZ

    uD43V{F5$^&;Zgf~ivxoefcAlk4>OIRG62)#btnLa2lNRhtw4)Y}Tc?tJhA{%DCr(GOFvUHh|DQ-tCRA{)V> zYu4U^8_<8`81(`@@ech-%p1BNJ_E6o>4tFSmTf67;+QyPFx z`slrdMNkJ+t&!+vmAxY4o!y8_7Y_G9_=g{uy>ve!$pwPILSNQFe&j~t00;vS4x!v$ z{lGH#6vgXG@nHKma+0{HXA} z*RWY}`=nJYUW4QJ6UUVYhKqh_I{=Of#f&Y7DN1TXaF z-=}H~`VNio>);~N0+1e&YN7JuEoBR7$4zO(dDK+oc^t3ce~8Va(Me1{#I-oS+nI^k37-D}Jccpofvr0F*ru&QV+Z>_a`qZ={wq6j z`3`y?_gwz}9=*Dw7jA)Jva{?h&;D=i@6!H1x7(9={N?ZcIQaz411l%LhCQ8y54d|X z`_4A+v;(`Ctv`T9z;@>QsKHO;2h;=5&Q9&$5dZJQQTB3ieFhu7aQYH6JXgWx*wF!= zpnCrzk6k^_ZUHXmj(hqGm(UBoN3MSdPS6*`eCZO&59l-KwsH)&*PC2GdBH<4%DdS2 zJ@^9hJx;#}e|73pFhF`2H}NYEcw9d1SMXi45*E?81HCT#UD#uI1Mq7wFL7Y1wpYv~qQ7VPWm1E5Xepo=F$W zY1fk*>o=<%SF&fPcSZcGKyL5&@;oNqi{rk?7C5(JWGRjjkFFSx$wnN{6+BUR!fU0< z<0qoPE1Bab21D-!Q2L^DUsXV+&@?(c(rhvMhdvkV3ciE#P{;y{3h zfb$Cnt&HC*BR_-fdolknjS$TYNQbXsHX0=RnTK`pePaZxrx*g>4zHouG$4hm;cKC_Ept(Zv zd>sb}PQ3KU#1pC-fnIAwjN>8%Ne{esL;N#28`y_tAWHeM1AttsYHWfv>^6X!F9rKA z&0HV5tiJt~UK;#;dTK}MrLTPdfaA+P1mj!w-d-yhj_wrueNNs27kK`gee=to-3!he85MXr?8L5{-dL#oe%i0dBDHM`2Xql_uqeS4<0;lwy*zb z{!jV;RWJ(eA^qesyLF$j+walWa1rT0-gs(PpWu_Oe`!-z?geulYNHlx;d8>V{R|Cr zxQPeP-ymnW0PX)1 zrlwxsY0jfLpRMn0b^X9A)Z$m++1;ams{Ne8=x%|x3yagf@TZ?M*GLWj7<*NoFK)5& zbj?9Nd-9bB&m&%I&zJTJsaJP{nLq9H)^YkQ-#mjGK>qZM*FS?pB%i68N;^cfr(8S* zxBnBnSFR$y&?S78t5t44a9GAOj{W;@;{TKa3(5ueP9?Tb!xFQ@z`(@=QV%R#J!^Q4 z;@(KNPBXXCv(VhRW>l2-Yj2KlzY^GZMREi^ue@FUpqxL)kUzLxbl8vfVpbq-OHaq~ z`-Sy$5!ctvxZ^8?69}J|zOeZAC0+d=g8ehk20ozY+-xDeZ`J17!69r=T0rsvns=2B zsP>qPKPxW3V!ju)p&2~Q2&qmkflu?TmC9@YyY%Q;`cnsm^7o4KBi#aF1+x2a?gyd| z?s^Ww0I>Z~Fhk7@>X;_^eXU;GT<0qT@H^U@CV!^SqW36{j}(rWn5I4fJW=uhfBGq! zEz)uFt?KQ`{#_o=ZTUQ5Aev_ggo~vdM}0~0A}WI|I4weI2KD;%I&p)%=pmM)CJ7?u z2PUH9P+vPg>5*XXW#AGBZ>R)+qYQP4w1b=V8crXF{2%=9-t)hs`S;NFW3zX^Q9Vu0 zN<6&?ulD$r2R8l9%{FN2LL2kOQk%Mnd2(|74?hKO2Jb(Q4IL(jz6Az%nH=KcgRkkS z-3CiIZo|h;`iJe7EnC*EUq^TPx8K}c@Bd`)FCUYi_}kz9W?Q#z{m1KdL-v1G^Z)c3 zcEb5POa6c5>G!toqf^ZC!vW^A>^wp4Og=JY#TJ{o<&rHua+Bwowa2FklQ?je+L+$t z< zr|*7r=lh;~<2iWz-{D>V#{2#F{3rVfEbv!8gZh2HfM4i6e`7A{*Ppn}M@~bK}SFSid>nSh#G|_0r#nq(9&V2BkgW;EXiZM-$zz2jRst`O4v{y#xBzMoZ?FU51(ms|_pV(v<*G$hGz5NK zK6AfKECSsU?ds4hQ_0H8SIAqiWoea0HXuhx(f(h04%9rFVHEd4$Gk${?iD!C;z&Dg zAAZ3zzeJ9~OrYD*#%GtNzvlfF@0Bx%>+@Pg%}Sv!>hc`4(i0ncILBZNrKnTnN2KFW zE-AiWAtX*AV<n8{)PD;=6&`Nx1YQ~S0Aq0Y3loP)B`&XU$kv-dryli zdjVeW`P*=3j*{;m!lv#!y`Qyc?d_yb`1y-JyZCzs?SO~R|7KnL4gEjtS9fx9a@cEg z#o6~yKmBAs{J?Mj`Ez&uGZ>%d{rB(RZ?Unl|LwJb%rKq({x5F+_a^%N$G{qPp15YG z!SA%E-~_qH!3*eqlN;=T`@84*ceZHfWm~uruHF4_!TNr6dr8Fi-LU%@{(xNk4s!%g zesuaDC5siac4?{ByL%7o)wRfaa4GDVZ#}zo;j!*kRM5q`=jU6G&Yi7CerM~}xxfnA zci_?<9nb=Ie13KZ=6^a_5yy4o_#TB_xn1CHcjvy2>)xf%x^(Jf-3xdP&-d!u)p``^ z{WzBAyK?R#-lL};=e>1|jxFT8g?V|_v#`*5aIUVMIIfdEU!isF*vY!)@*J=4#$yE? zI#_;A2g}aLwEXNG>)avN3UWHS&)mIBR~yu~AMk$#_Gd8Tg3e8aNbHxozGMh5)S;AkbO z#YsZwJ4(yHGQH0%cs_6)Yg50|3yew0rrt*jl)OI#-%vG{I-OoXAbwC7Kvmg4`H(ce zyumco>yJrB*AOnE@QoYms~zUS|G*Acgo}6G#eOzZ;@7+uuknWbGA?H7dP7Rq^bG+6VNP>kHWSC zxGmn47dSz2e1$Mk?I6&x4x0gQX;jz`%r}+yrT_P5?ElN3?9AgI?CQ6Fvctsn)AZS{ zJp0+sU>lE_<^KY{=n-c8r3rSBJwK-(e{VO4#aFo;ha-4`%kAfXv2#!1+5Yr*yTJ9> zDbxO&4ZnP#Oqnt!O`!h$``fUggVD0@-i%-!jL1Xkdz5h$Z z+|yusM{hr|kI^mPORj$ce{hk$#X&H_y;tEU@wZ&!`1ABB_g=cg-0*jH0o>r!eR}Bd z2&OGuYMnZFVFwelu*9L4mw5bos~*EG7LC2?tvXs#4q9&=dNBvl-4e6d_0X=!>gTZE zmFs%h-K;@}9+sTj%Nlj;Weq#RWzc=D8}gVQug~l2weQa3y{vBg9&p$49NraFKh3Iv z57%jjPPWd^F-h5;b0z2Y^qhRhEzDiK(x%Q@XtNfsVjt35 zHfzypn=yZxy|HkG&036(+FNUE-tvw1I?v61d%Z1QwTZoH%WN)>>#>HGy@>!A(60aNlVL~~H}GF-1uoCax!sJEbA zsAikBr%QSOUYgtEapf>RU}*la((|JKhg}ELXK-_n;v-iC&!>+mUXONhh%=>GfIv9T z>R~!f1oSsvVGc@jJ*tJu(8m-{S$oOVTXb`ayiZwTx90zxM!06DdA({WY5eN*1i(}B zsg0HZJ^xTJKVRiKoJU+o@h`*`7Kfk$yeL2L)s&*X7N4H?Kib*<9}iZpSpMHXO*wy{ zXz2hm2Uc497R%F@tU!FytVe05{mK8xk#x+<|6bt+Ghr2&A;sSpt4s|l?g>4c*Q$oo z+JZa9{n9?G>wM zf&a^dbE`{x{W(s?bftHbN{9`!lD zyYO6+-cJ{}T=h7wZr9~@ZR$*Y#>BP-Rx35vS`_rN(b!$V@F{3@W%IY8)xqBw#J-w# z>1|vcp!z{|!;9};z`2C80KWJoc!cJWGz0DWk<=6FhkVO?lJ2{H1ovNX(Y|yY_XDs0 z;akq}J@t!f7wQ@}&qV+UPsZ_v=qTJ8s2S)IF-7^jcvg&v_5^PQ;(q=hf#^-P48K3WIaF zr((Z$psDv5MBcAG2!8Z2Do}S+7S|8kQ!OCePxXvA{NCgps%M1%1reWpxeld&5KQgj zLwz9bqh@g2EF}1ZG|PmE_|vx&Pbi2!i1^NK7Ml34-ks_Z7x#(R(mC+reT6e>Hb8q= z)C*LOAiZwo`{G@RHyl_inH&M_v?O#`no7e#JOy?Of)z-A)T76yJ_9ox_zPcZesA8t z7V*n30o^2eAYnt^ve5nuEV%D{F7vGV@HegI=w+5LcDdC+SHIS{6;^NZ8Xj9}Q9~A6 z_`ro0#IZqr=2=L;`R=uP{l8vmwXAkKgn-=y^Y>}C zGZ=n*2(uo#4$`hmFrENOFjSpeIO>;Q zpd|_B`5Eu4_ms_RZd>Ph_8G5npNsn(tG_{9svr4#3#iRV%w6BJDz>hC-meaR82i_p zj_Up@aDJ;$yQnuQ&TkmCLIrRXgzpC)B;g(C^W~fc|nifhjs;l zSrDs*mFjmLmPoxp-L3t5;`zSH+@3UkUuvz%*2M?bIi!W;uuyDYJBzi`NHxEk696;O z4v7_(76Ih9e(K+HTfCOA zCb{@%^rP|LzQVPdqR&q5Te&*eE*OpvwVDsuSNX_#*0^YtvkTcq4SF?gdJe}vyEvPQ zqh@QA+XKC;bcb>2-&T56n(?kmJaAm}m-o5W{)vBHwDVb7G91V2qz~JOTwd|s7yh-d zZ1G6Sk>AxO&Nm?^2%~qS9a8Qba5k&Jp?P^e&-?1VUtY*je}6ys7?_z4m|HknG|DxU z3#b9Gg*2^wsuGjMEs~~)Ke}Psh0?lksKZbzf-!2BZ&;m{t|uyc(>#Ogfr33q2UvP3!C;2c zOjqm{4_PzI((!l|-GkS#Rqa^T`)kklOJ0!r1CFyypF`a0N^qro$m4^^`JGb@WVTS)Fp0LwL04pft%V*$zX)Yo3ACd}snm;*1mDD0jdh@VluEVC^ zJz+JcZNv7rS;Cy%R&N3JK6Q&lje5tbP2Orz6Sr90>)S1${|bv9x4{x#M-yZPuYKpZ zWv)MNX{(P~gGGBS{*9d$J?#UFp8A2sO#9HPajDMh{_7=v;U~`iYq#rb&DkRm%-m&E zGiH@j(wWO_huvo}H`UGYrfO%ZUe0A7%n(b-A7IIy`dhz$lG*kk|1$42Df?fQ># zeNZxSn58Cw_ia*M9HC%LZs=LR>y%uGW}+?)WS5FRI}$bX}dlryl;c zX&&`^ho1aRUBI3jd-`DXvZY1kbT*0KwXoL|-oHu5p6t8q!f&gs!;OR;xpQ%D@yYal zI=`;3Lt5AV%-D~i*UWBP{sw>YhSuZ(ExHUOW-*^jj?^xrt^NALuO>}E z#ZYM;D2|G6tQh(bTe^P>t+M-%JRC>tNn9w+BI)>hx9-D#6wgqcL~I+|y$`qeb8OYc ze(YC%9E8_PGeO))z5W?9 z7<&B|xE!TuuEA@+*3z;y^{9otD;Z82`rX z00IvP#rC85-6_V3_fWxCcs(PO8WzOp#`((+OtPyImQb7k-y zC5Q>)C~4ogxE7k}QH+rOiZli)1VxY|YIj?*#Wc^b24Fw6+jL-m0yQ4_fEUO3RoDCm zbHvmO+AE;_q2gwihYOGhZy~Z_Ypc|f9dYYUy4YT0>igL5KC3-cYr+nU?H?4%EX z=TRB_Sb0(q-??VK!s&ncB&1p6Zlhh@uNql#GLgDn94&FIwTm^a>i~Ap^>wjXd{6a* zoPK)^PtQyGEiNx0Zu`(PQ{PNlP`U)s!>vpG-hIq;>o9P_>Yg zLX%Q0qt^)QHDM;cqB}l_JcWE;vB;g1T1f9BUaCHWZw+u?o>yO5IfLfsm18sn2h8X( z#Pxz?|EfQwQI|bnoW;Xg6Bd}6mgahuvZF7s)i0DY6W{OMhSTh>A2=?8<1EWQ$q^LG zKPSG+-X6hYczBl>%;U-j#F_erSgYAY)djNWN7&@&*s%P-7mE41kIm{FkBHqmPPVRG zK$wHx_bE26*D3x#l#k$i%H<#4C%)rv?!&Xb14lwOed8)UE7c-Ab{`((17;N%4 zn0nFmH>=YV<=iqj3CKB!FI7f!veyfhpRl607B zway{$DrY$#IXkT`F+XPf zMhhRg-Xcf8Ymvl#UCR$dkKJHVleSnmejs$@J64Ows!!TXod3{j&e~~>mh88bH}~TM z-nY;pt1W8WMyrb-X}RKvWpBX0;8&ttKJZUJ@Y4P@cN$E+A3;4H))YOeX6#ZWMn$0~ zAr50CbyYBS5Tt%Ie!7z8&dG7rlkpW_8-BJw_8h@3_Y%SICeTokeFxyngX`hbsRi^M z`{2t%8nvUZ0zVbs5QN_e5&xC%xKY=U)KTfyIIp+0=`qa3e9fn5COrgPw-)%H_Fl!d zWIqiv9F05mVK?OddCxp- znfK=W&4}wwJNI|>z3LaeM?9~MM32M6qlXvAZ>}kPm6k<=$&bMQGTS;%gK}tB#}hlh zz&6EU5U2P7v0S>Pm(Ic+ymrUU58Q@Rd>{WHUgAx03}wskG_@;Lb4jva*`IO=#ry}@ zpES+fj0E>pODG=84?H8EmoAie%Fb>7Y&dUqU*Bd?W3c)0n_Qfa9Jk5Ydrk6ym@)5J{IvHidJ;7NmoR)nb?Si{ z_=9TGwp*Nh!Q?F#ON@`>c=?8eS-ULZjU5(0b*u9yt>gzbo^tuc%Us~4{a2!fFYV9H zX?nWF%EN2I2No~yYp{ctqMLAgzycPM6AbMK< z)NuiI@CA+GWs?^u?uRzXcX@urX#U;Nxd{gU3j`ymOfDBm-cX5NccTL8IP6C8v1V!q zI4A6jf}<%N3FYE0Ig`fBZ^@03} zi{r$5<^K0LUbcOQV|9%32F*>~<+$5C=D`RaQ|k*`P%h7TdF~5pcAej2@60>FgM2^^ zaQzzdjoAIo>$lmDb{noGxd3+VW*@KJhi7(&`D{3pmv7kZ8@Ju=CIT0vY%udsMG z4=8;CU*%)?fFSh<$+e`J^cvhgX`_h;C{5(j*q-)@YS)R=MW>e69y7=N``z|c4@m1r zoJ++9)eqtjx&7Vb@Ws(C7JpH`!_@=S1ky*WW+vHLLMy<&b1Fo7Dx`|vRv z+$Eal&p++q9%yZG5CpU-~`ntY_w`)-@~VDuq1H91fH*nk7zW1x3yh&6f6MW z@O%C5SC<)daxC=#l)FoBKA4=qzkUbvt>4*vlECq5v6CtaybfPchJIf;@}E%Rdq{&U zasaRxYA@CQQBA@4iS?mPI&qCY40AvM=vfL63Q*$ z=#wai2<7k5yqNT=)FWsFw$QwAuw|ry|4|Ric7?A$5jKzgKfwO)-0rEPi_-{CMoSJM;k z$uo4GTf}|mSFq)~fT9^~UeB%s0^A9SmIa!-<=;dm2!LOS@=@VN4J32Nl!4m zF?eD!IUbKk;uFG~cX1eD0Ck%7zD739h4;8tXKs<_uU)x84o*BLXHZ>m z7h7|CPKdX+RTGdOxH$d*|3Z!-d_kJ$cjYe}jzH|k&hK$wk14NLzVJvf{nB+eLm{n$ zYxoY$QygcON;^%oKlSK=qs&ZQVIBhx_%ZYpFW+(Jen`Hrn&SR#4;HANfO-<*1UUS! zWJT)BTx#|-;sEmx_}(CLJk|E%ENf4(V!R)-g@Ir>(#;N`#~;COO>>XZ3lU$sVTV4J z1vaewP+H!qAG9|>_Uq9?R{rnNKdBIajgnJ(dO2vT(&u;D{^0uR?MX*jGmM^?kA@$= zhw{u*Xn(M{JQV`aPx1!?#Gj~7D7$uh#PJE@1#2!tvqIt-1cOER!VS>AqN=gfBlrh5 z|BLNQGbydlFu0Uxw6*GHZK(fa$7B1ldFpl-`xW=G`D)m{Fn~mA{P@?w{din99|IN` zhi%v5F&!5MCJ+gB5H^Y$g6CrBA4YI4z|lz{&lJC!T3Yz`v+1J=s4-!saGJZAOg*+V0fRt^bDGG z8|&sz!|J043$7#VF9f?6wyt;`)hx%h?feKVir*-9{qJ5p@&A2zSBVza9RHM{84}q) zdO7&^68Lnd?@A6JeufYBFYcyx$_Qf`_4>U3$o}=Y9z3}3IMxyH8U6U}M$rR^pg#P^ z-$i@~r?-;cI+fW1W*O+geNLSI8vISOLpQK7#px?&uc3#AmhoY9gR%cppPs?a&?5iD zvxnr;88nwP+sHBJnP0p?F0T2fE9W%Zc%7MMW}p?r@h!p!u98dK!Z+N({%`X>dhV8L z4Rnm8p(6X2jS6$PO6`A>^PS_o%H_{s@5i~EI(C5_YrF0J4Lj`P?d)}ChI9MI9kz4l ze)|MpaN!KPEX-kD!DmVDKzWFG40mqc2HSiBFX=bykeyBbUzQk>>-@j8jHK};eIIG} z2hrOPA=me%Pp;i2nlBE<7id?AKY4&O0{r9IZHV7U0TZs5-4ma|Y%{f}v;&lHmjnCP zKCTkjw5Pu#-6P^Jv0r*Am5B$+$;4wRi`}|eK`;Zwe2;y@0i?bV7eM?2Z_X>tmGYrz zt$-V8_P9zU_wgr=2gqEnt~CcCzDy9GKY;w+>6pdg&*&3~53C(yq0|U<28=P^I_MgJ z|F_?A!K#!0tG;&_KefO7KrFd@)aZ9Ck@#MB_AUz}m)G-pOf|mp{)pe>ehj!@IJO@~ ztdGFXRXfQ3bvuIIfbJ`ghyYuxOFfV{WwRwNJ?`RvM61s5k-FKSx3}BKJ@>8cf=_Jl z2iI)s!TXlG?39hzdDCVw%iDS7N$a@coaIbnS4ViFRd2%%O7V7x;eOOS;z9d__n*f8m+^n~#%;`AC0QJCS3GfF;)L>lHv@oJIq>1OkL=hdXYA0vqfYPiAlkx5(LOj$JU)(p(Dg}t!O0VsnK!(PErJ{1 zBhH+>L~bs7rY@(3*Y2}R=g=d;_RpQ6w$S4@nbE{|9LK(o9y`wtlpKqEF8uHM)mv@d+70YO-ooC~^|k;Gu{4->^4UJs=fWqPJAH+`L$wK*f$&Q50C9-K zTlz`ypBai*%T#gkTXR2}`4iTn8c$kZzWlpOYojW-n)rXx`}X7CPu^F!vdvitRA~J=g>@|n^CR=#)lt}eo9%i552>rBgo8@@ZVtS1o&>!0h1o8 z@&xT0)lTy&ytf}YhcryIlUTES6{tgkYcqGj?;{v|S98um-1nuX^9n(C5r5!aogPvm znoi)9k<^-+;gXK3_MdBya|PA3XoD0?on=8O%v^#0wcm7}dL5f5&a1y)gFap)b{a$6 zPMrU->+^?yNdlku*}6rZ4kad_FuH_ytSTx z)Y3*QAkRTlf;r6Q-NslH+S7sD4v}s%dA|6Z%IT_7pUDqI;0ILuhmj-rGw)dyA0F8} zAD@U06PREiHC^MPk*@zIj$GT`Bdp_)3D$AIXvd?It(;>nP&*0#-MIhqIK_Y2zZbQ< z>|eY8Yu3Xn%4&ef8Ic``@9~R!{9N_9%_9^x`(IL8sR%J+P9*goF-3GelxtzZ8Ed(n5=f;sG3 zSiQ}bFI;JJW-PY3{JYGZy$YNE)Yh(e*LH5*$xh@wXfKeDP?tzgT|Gcy1?m|{yFvYk zKmY0P)v;JM^~0)0$5R8KGZsetZ$|DnW|~z`1rJN>X1QB0S~cvyDZTp|6E|7hl&!9(moR%b z7@lG}v79&_4+l^_A|7l%e%dyCg{K~n5Afvwo87f;dt(2;_yh8WYWRz=p=+%sxkT*f zb=GYCd1wDot&1GC)@jNr8@>0THJi4_`fp(;$Ki+8cJ5*8%k7!if3FRfEos7D>o96Q z+OF`askN%He>y(Br^9Um`3|+iAru_95;J7J;{8zn`;+slM-Zr94w#|1K*99?{OJK` z7S)&DPs7fGts3?jL7gvsHeEM>XCIUR|CnE}Q3}4#yzkBWMADv&>e>|}`kUUIt zs?v7Q9H+znuz$^qDSwl15T87rTA>Pk=n>QA{IBf){{8#()$ifkQXK}+AgeQdVlXbS zz;J4uaC%mX|C&R7NFFYH&hcb~{gL}C7N0qB-f5W}*stI>U~?ue9-Du+icUu5AAK{kLJu+irp_`*V)_b zJbBMnFiW&?^T+H!`q)-2TgTqy?Y4g1hxnQ^cKp-RP7_rzUpflXkyAfHw*NJHvcEk4 z(K;|2`D!UItCi77zGj*TV`&%|O?O*^Hd-t`8j3NSrNU%WyTQ9sJ>H2Y?S$Yueswwdi2+%`&Y{%UpOX zS@<3HsnfTQZz2K+W61+9=~8R!Rhh3k@omS;A**Wvlq#jfd5cysZ^ zrzp2C1y&$!1KGTEjHTh^$8(xdsEqAPFIY3sC8-xe8n&{c$+IoGc^jAiH+YNP9&q>? z!}p5?+pA9euPHoV^}NFYHp2PY?l=JA0*KRB7c5XXKqP*lhWdW^f*5>=@Pa7i1NelP z$y+T#c>wu9G{;8MUkt&Q)B{UMS@4n7T>PoC{}5)d)l+FbXu9?N@UFFdh8(`7-}Re@1;;fAYEzaK&hN zMM3oZLeRLZN{>g{4guJG2y+0ABLrUH3m(vbIwBq{QM;|H;D4o2Ar5_L9saHHr|Ct5 zT>h`z`royE9rx1ywdX?iFD|az4dd)zeNK4YvVZzB!h1Adq8^}*t-@>mH}i0jxyat#@F6~Avu%8LyY1Mr)jrs=gL+`Iy|;Wd=X{@hfjRUe;1dUr*r^lfE%BLE zUx-^Ij*)OhT|4eEIly0k`PYb~Px zk*lj`r-PkzF5niBjCVIu+{@6 zFpD2Bh1#*o_w!Q&30@8?%reZL&ePwyY>Rz1Q%;kVelZ~(XK zp5q$k4d%PdwPx^ow3A)jAMrIK;aIwy437BO^B3rE!8iF2@xRp@xBg!LXL;fZb($A- znD*jocb&LDp5Bo5+sgjyP%C7)`hVoK{~Z5Q?l1e-JcMQw#1j<m5N8H?CS&YrZnD{T>T!YdcEtBmL0dV7W2oi=aQ zo3>;jImG(S_>OmM=@R*bRkm>6DtmAJc6`iE>U#2n&AaT-j*o2Du0t-*-%UPp9-Qy^ zrzfZ#!2OS+y~us_5yb@(KS8ra>M1%MR&Y)EHR&WtTcsoMU;V#m?B1X6)#-o`4=RSk zlconKy)O0gw9`O1fOwhO_bn|{?En(zQn;XY2kQHB`;Uq9RhT0UtxMdc2Pn>f_=4eJ zOeKj`$}g%Yr$;lTDn2<9u9@^ur5O;GtlRLk(NPH_M@wi!ylOGpCc7IFdxr~8h zt;2}%)^zAZ>o9$eja~7M%^`+hyIxO_n-s(ALIZI|EK?__+NuO zPjh;T!Rqyw^7426UiFBjmnGdhF%Qrn`=hB>|s~z^Eet$SV zU${>>&aeDGmDmzP9@-ZB|MAeFmqVT0nTc;{_5&h0War7trpK^Wb&o zs0(Co(my{0E^u)7VfKuir9W`OHm@T_leces2m8f0>>@|s1AZWV(!-}lwPuSeo0^7oBCR{yfnnLS12HX9Y?AacuaFZ;@C--Go0R&+at^_6ydhw4r&L9 zb_gpDl>_h5zA-QSMOEUKYDypYCr(e5oYd)iaEzDqR5`z9j$IEQUn1?YDxB9p5!?Yk zqdtK2k5sRymJFn)Tp5fqv<|&TmjkOu*_^&_8*+r+_z86NM@_P!{FVx5EVS;k7u#5J zv*z9VTjjLg76-;wW6r*RxiHf=%X3LsbjX^nK4}@7E?6cwVfqH<{??zd7HdygyDb+j z6YfwZ&$Zof)>^GTZVeY5u=?}&TBF4Wt?^rj-R)!^OI>};TCY86c^_Q1mb|vw?7fz- z%!B`VYo?d_yewQ>@e`}J$hVfW4q4yr53I}jtJZP#70a5tkGy}VRg44&4PlM~Y(#jy zdU@*mr!yl^vtwVY(|!OoKfQD5F^E^dzi|}#Kmc{VPdq$NI33|U@5^^0tWX$YC|sk) z1;gA7qH?)L9eTK2S@u!|TNQssJzHOJ*xR>nn`-NSHwSoW|N35QH0ATso0Vpka($=c zB(4WovD3|j53Zh$58q{6^Gw(OA2s7Y>;LO>sZS9JcUn9HX$xrXRDX;3A<`5`L6b!N zzpV5$^vQm;XJG!~{ix?J?w|NP>c5K0K(&|ac*VE?D7$<>?RuU^5S6L#@D`lctr_~GoF0P8>g=_%LGzjB#=BUqsJ zpIirjyn-(3iR1JZPKkqX(Js&r(2kT(51{FcFVH!qsd|<76F2b&+#l^%lFzye?&m%; z*UI~)l`73s%@_U(-jNUf57~xV89a#EFsxB~>+fY4GnHZ_xb%ijnJo*IE2hbiNX?s>e z=d(QZh;rhps$=L4h{vQoX5nDHRXBfT{909d;ICq5f#l7vfjhE*$V$MGFP_-u|G2z{ zF2WycrrN7DTiGk|p3AG;*X=)|o2c8m6oYH?2OcX%94!l$Ql)8*`7|f5YL#!kaB%#% zuEN}H8TxLXV_VuE;##_MlqMGIKi@<+s`TKsgS8l(saN4XOW#EE05#k7vD#>JNH?{7 z7}^TxLsi5_ORHX--!k+}i&qS=29NrI_w&DR)qTUbT`wdD~4uHmMQ(-4? z1EqP3Ur?VQ3?7jm-$ni0er_&Db)0elY1AuU*4$>0!|d_1;KRefoqu}%oy)J4V~g{v z%h$Sm>A5&wFg#%O;C^}Wy={d5tDP~iU^{-)7K;DUu$SFC?FYEwZkG;!i*&5j0}%cv z{@;YzOYBcSqwD8*#vX3*%lFas%lFr3(d7sBEi7HPiQg1C6~En(1bRp=_ETHXS7^~? zfF-2ogMX%5n^rB+4*Z3EMh_fDuGt^W$UmcBF7A!y{JwgsIel^PpTgx=EWI(a{@lKPlf7qWoyPHP@{7CIZ_)dM7l2(~ zz%N|ov0K;R?b3Txum1}C0qs6NLf-Jn{!d*laTG4X8SMY^d3+B3;{wOX=I_BLmiBq=iPt3^#^zUmyhsXfB1vF@`wNVoG*{^e5QZi`|r2( zng8Gad3jZ^_>d55P`$bpF#kMq$Y5JAcMf&dT06Lh9hQgob2&hsb^sp5UiaAEo!jl> zogdnPJ-ck*t{wDwwv(^1Uv4M;*xw&NdT_rT_-Gf;?VtyI$S$5?*Yt(6e7EeIzlIk5 z750gqWf%6zV?2M5*MDGJ-(647W+}RP?btwx3&QSw>#8RYM+M(i#y1L$wkq&}(Ln{T ztU}C}{rFHHdEuwUX{eBwBuEA(}$YbKUV!1>=ImM;G{RK z>#&JdG<=ffQg3OGbyhFxtR6$GT~B6wsJrTCp~aN}w!^Glz05AIr%<2!((KR0FI8d)(^ zv-RT3effmBI_}G!#OoK1CSRcZ+Ua+2{|UQLbd0!zUvRu|1nHIQHR>s-4|n&LIQYy9 zUDIO^;S<6uB7UDcb(z?H$>sFQ;nlZ4OpbpD&cW7=)DN5a%~4zIpoZAD=a3!Vf7teH zr=Hl({^fm#>@3`%TbHl9J?odj{qBSHY3@gP!aaC@x-I^(;{O*0EU7j9OIe)YdgXq(1*FX?)mpPRRJYFG?eWGFD z#Ar!*6RWEblPdUw!4tR2IX;hiyWl!}w-wPbtPnu`g?}%{>ogZ!-Y=ASRc1hm!Qu&) z5(k(WAL){7_C?x(CCW>8UAXI*Xow|%Vfc&4?U-kNe;rnam$K_?z|I&F6#Sch3AOIYoA({fx z#fYZo(lEEDHDSh1@lrT|W`JX};*5xwRTX=6ePixR<4tv;Fhg;{ z)H~3%bboUC!^wq@?`D7aEvWx5``7P9959bgOr+!LSjNo;9=k1sH(x z%|+;?ty#c6tY3# z@0!Qc{^8Sb0X|_D$}#HtJv$Fz;~&`GT?dFApV03=V#`--vL*BamaC8O)_Pk=&wt*m z#kOSw`;1p_0{18W?A!+z`808cya1nYntVdLn3Q+iCZEt}Qy!w(Ma>LNM%=gBx)12CJzOMqSQr=@Cl@UGx0Py|f$Am+wlN%E9FS4htkViv(w?M9p8kH1j;- z=rjLT5==>G)5uO80b@CF+zuT%Vn>gIubkuG55DLFW=tNFPku(;`T%=(Hcp-U z1^MK?`^<034?JQfi+vpO2cOGlV8>s7|DApH9s6j}?Edyg^wxg*(Z2urCwuWH^sWE= zC;R2Ef3fGk{A`c$El)W2XUwfV;(hM37x=`f(^fJ+R zsPFyg8OZ)4(QNQV$2L5L-EZ*zH1nl>EKQ3>JNp+dn~>faY;**6)Xe1on(c2z+|7j# zRKG3t1%5zU8#Va;G+(ESG(U75OP!)TU-^42a)?^Y64q@)uZ>u(nSMQ{eGD&SguXxB zmZnoVUv_7}^A=C2C&%WHTO_s3ceBR{%pccm(ca;LI=^&5#Or_g{`xF2#PvHRo`+20l7E_FUU9dUEDW8{^{-vFIY=oV2RD1y2xIiy1-WA1J=PQShaKm z`Q{-zL~futpOfMf!AZP(jXhI*9@)R<05vy!1Khyj7kp;TG)Q;gOa7i`%4Ns}q#w9u z(>sn&pW1gk|31>|f^WwRsCJt9F%RZb9X(%u6Tx6Znltgi{ppx^rW>P!*9DL9M>5B-D{oJ=7;WqZi za^7y$4amS?zAbp^+#1zd7Y2HXP z-{O;ME!Yi7gfdF@`a z-p*XOfTsM9)}vyOy*GJ=-6HP)igtf~NpJYoXYA6|tM-8T&|c)-!{8VUVCUj6;^k1V zl2P#uY&5w>cRoWAIQP8tJR3=0bvU)Jjva#Uo7J|XJw9{6>Q(l(s%WbP^KVuwqmX>P z6*}e7me97VHR(Ru^;F7|BQ@$W!s_JoChj$&_ZM#|o%<2Do7o@Bvzs>9!;$pHH&=-! z-lE$a3FkkwA-gT;Es77IdH-PL`+Rp%;EU3GjZA5e4}ss$jBx$j{?7iD11LY1{#R^s zbV=$qXJ)<+x+7z)IdwrI_*rNY_zoQU5c+DG7m)r-IG0d9dnn((G(4mc5W;bx@H?XL zDYdD&Tf!kwUhl`;h44Oor_y$k4utGq-?Mmu+9{t}BwHPAdynMzhgJ%oNBW-`=zlz?|NqSs?Gr(t zgZx;tI*OrA?~9nPoLO^$s-bVf3(_9sPY!-+`}ZCNgNL_=UB9<_BmMuawtC6C@PJm? z(uHr@4EQB8r@v*(&;wqxe5Ea4yuzmO*dY4Zx$QbzyEbU&P)qgcG0?gc^s(XeraJW; zWdjCHwZ%);+S?0P+gnRk*$3P9+L_bm?bwmy%=;W=4&k_GPLR(dZm~EDSFrzk;1Xv~ zU2!}gX_DN%4o=IAur!KX9|PN0{r}_lKicy3tF20CHEYv#YWzlOwdn#khuLnhquM-Iy>WZ$ zzn<`Va`^2vw_534tT8%Ob@+X^q*vXdU?4reG|L`58r`1G#Csod19lTrla!~vP##bo z8!pZ7p=2fOpSV`468SAPfp-3BZ;<8+O7lAXhKe&oT%OvofoUamI^uG;jnyn0KTgjC-{Xbvmgc87zB`=ns%~~4Gyu@^2D1;;Tu>9V|H$(- z3mk+maPvaop5e@Y2Ez+(kl)|of3kn^w4||}0S~whu_=@5y7;gb_<=NHsPKW*!hzPR zZ~)xTA?~{O}Wxc1k%KD6{UG^0c#8k<4SX#z6{^Wg)H88XRw z?Y`LBS%cO8E?$7*|V10oS7?Z<!Ue~>F zg_%9Ne1UoXt9R|_NU!qUP!aZPssDHpjDt5;uo{*(e7eP@!U5v95!a@`;?jzkyC|@lnSJp6@M^%X6EeDk34y<46yZAy zU4OY2$0c__rwYudK|A!`^9B%~Mp^xgZs;&~!`Gv&#cwx>-=MVL>Tmj_vJS; z1RcvFr|;T*)J#imUx010BTU*{^!c=BT|0qGRzbImd4Muir1_&=YSIco%bOfPd4P5@ zyZt}p{iT@e*RD|=BYm=})FRr69!P&exKgpwUigPV8vyTre4Qp9`{a5sz3sjU$yUI7 z7cxII0{i@)TwQtlKDb#uDuuuYzhU40z^=bfj@q=AS@xV9;IG*J((VInP;_l)^CR#9 zW9v4vQN(=Nx30&?4{+(qc_%bWw>kKZF^MT0*ThCTpV7!Bk#8h`VU&&~Hzyv+27UO= zm*H=TY}pA-o`H^!QJx-463^Al>hAg)USTyYwbxj9QiJJxB)Fc3FFssz|AFxQs_~ts zFwYl4tPg1b=MJ7vZ0m01yy$n*UkOm}rEwm;6}Y}&gCXP}jk}Kghy6<*TN?hO<}J5g z6K7jfeyahoN#y%ztE9l4gWFlHq4Iy-=YsF7&Ls}6R~$XQn$0rY?bZ`zaPy4CANZB#`$YD&!DbX zok8x;=g@n{@|iq(fN)8Fzpv*5=`|*S8+IS}hK*rPrd82k;+uBddE$Ro+cxNTqyOu2 ze9iuQdU~1xd~i$i|K!rH*XQ8}Jz#Fn)$&(vk^f(!Pk+h|>^*FI_Z+kj=;<$Cw9;N5 z^SaHRHrp1?Tw*K81tyQ1X~PGNw(%n-*|;GStyf`p{0@6mhzY~{kFrsEZsI(9Yw^4A zeRtUAZ3mgHeuJfY@ znN2)!%+8*;Z0DFUxP@MUW)Ib$P!01HI>bM}_{Em5W7lI?b?Y!}2DMfm`BEpaz&=(Z ztuwV_AsUVytaer}xV-Fj$n42%Dtj5oJyYlr)dkDVqSxHK^AL_H#P1HXMDl>dwuRtE z{mI$7QMdNNFW@(t=i(=NTO(@K7F~y1)577*-BLql_aN6`{;KZ?Ynt5^y$>&DhR_=i zuT5UazST<9{KB*!#XuKDc z^RvZW`?x$nvA#E${Gm1Py8G9_aQcyx%ht!hEg6e184ibfFg)j;@Fn_GPqd=QnpOno zxE(o3PH2oxO>Jjm$PbizjN$lkTqfZ&YP|BARi^*vM}Di_8X*nRm{XvJPwi~Ysn5cR z71I397(B(Y$IpgK30?sHn!$I_Krez*;Phf=Tf`roF6Sp^xUD5-bfE^HZJmZqah%JR1^tNi zgMW{^#8lz^@T_#*rrTf_Z(9*xvd{gBmXq{H#0%`4rw zVE*le(^drY52uz$CiV-Xuh|N19%6PjujxPzp^M&I=Wg7AbCVymg8!9T*q?l4khKL{ z@O+lxmQI{ku8>Y%qFzB;K4XW$6RaQgbaIED?suoZF*q3=pv(-Xhb>%R`wqXR_jjLs z`3AP6SzeFkrZ{!d_44R>eaSJx1f=Pq8UC|yfsP(J%G?k5JaPKy;bXS*gMGH)oh@+s zH-YW#qhGX-*_>UrW#jwy_M6LW_Vk(526Jo)yE#_C4P3oun|%bwXV>my%oy&qkN17* zxCEL-I!`>;9z@x^v;ovxP|R1)LUCVO16R-A!WW%q590?dYdJua2K4mthNV`GO) zhyGwtT`fMd5IY`bjlqlSx0he&VT}t%u$QI3!>AjPw>Iw#A1_@yV(=a05B1TFNa;9$ z?{gw`9p7WNa)~^r(aL#>r>ur>7#aF_IeFl$=H-}0G37~8nD^{Q6e`q!xIe84p7srX_gtvoqPwX}Tn zzlXb7>dMs{P=B$zqVG6sKyDR_jkg^&-HN8Zg>F?IJ6)?;yP>aJ$H@!fTo=KafZr`Fo8{Z*L>52VM4uC#VHR{}c@0H>)2e=D{T z^(Ov01m1ZdI8sQ>`WA-Ijo>}PneEnlN0Lv4aXTm;o-dE<62|9n7arGZLimpS@X7xC zJ<17mQLWh?`~R8we_><703D7`>~~szS8uVa{51Uk>%`dG*p6_(r~ly5YhL&+HTNy) z>fsB74V;A|d=5^|(SyhAG&2L58xU_#`XJH}*@a(NxqQ97yOLRe^&i-pRdD#3B|Hdj zc!c@kgW!r+uEIaod9nBF*!OkCck=g#)bjE-`i$ZrX`WZwz``T7kNxD)URdZ7F5CQ%bK?TSAj zSExxIT94eIA$4nN;SlRIcn18{!DxmLXV!#WZX?Mf@_Jb@;<<1i=?0f}n2>aTy~zvM z?@2$eSXpuadI81g|Gmn-5YMi_(qR7T_pukGjCug<}HY*2&d#Qf$iKUW^^YJTFeaK8yj&B)hN$k*en3AjQouN%nkWdy&K(O}0Dm}Qv2 zYlmYOL%H;zX2=9{Xz1l_DdZo`(Id+Wim+5{KZ(5tvEW*<>?w*YRn{``35_^sr>Hm^ ziXC+(_fp<5mHZ?Ak0q=u{j6y0I+ffgi5jU2Ju~^?F5~Ah-^a`x{HHYHf9~j6*s|uT z8e`w^g7DG4L0P>xb_5+*_ieGpw zs{x0#X!P3_O@mCFRO>i=f%P1}$fmE_ZKG$cv+;AOdHHVKuI?&m)4-w5rT6ml z55L)0;9{Q(>!ZJSk9c|;o4a^YbNOg)T>)3e4rSlk5#sc{=oh-(AiU-xIr(XFa`ggk z(r=fhhkEhK$Hl?b{OuKPUm}M;ef%P``g?5Es&|>;Tj?B0-^dx%l z`xwsmGM?wz$ATYeKs`~&Ja*%beTn(nb*x!o^unp@OH~ebb)js#cm;O%I2&hIAid&O zOQ`?v*X(6N4SwHtOB29M|!W(b>rnM9!vQ^umfBGY@%WOm|h zo3fF)q@MF_#K!BEJ8qe!4_;tHS6&3)$+OWP-NQF5wyaSb$m@Dr+p+7c%gk+-JB9rS z!`=pSLz}(baBJM}b!$FgnYEv?%@XtQ7X#k1%%N{t;j&Md0|QIu@6Q^;zJ(^8t#0S3 z#E%~M1^5uug%twgz?QqA4^h{e^;v>GRdZrLx{35Y>Sq$KQpsD&f-J56;@h*T3aApq`N*x;F4z@u@k?|Na?1ytsYh`#hsh_9eXl)%<4^$I0cT z^Ccaio9rQ%?MusBJV9}IPm%jyB^Ot0*6iR7?BD5b@Ot&&)HBp;R6A&A`re&;sSWnP z0sGkAS+m8qGlQ~+UZLXwU4+Abl^x1_h9|`9C&cUT;D~7F$2ZiYU(&z-?mOwA!bg0f z8sxF#7(M;$OE`vbPw-X8KRu3*x#X}3=?mRM`&0RXbpOBR_0k*G?y|R6uXMRq?g(ba z=*xxCd#a9(Z=+5_EV*NUYd|bdCJrTl+qdb7O%v-IcO6RqhP)sAzEz(I))Fpyn?7T} z{`y-pv?DS&PF(v|_<)9;z+!uhp*FzBQ*+hJVV^{wiPnUAP~6hiT?gZD*!N0&OYPLp z)%=x0(C!O~cXhw(^O4iPR)*NmMY+Ihv(ch;dYaR4e+>XgHG7Aa`#5W z_cqvWhp=jvjebBXw;K`T)40wBYfwHvh+IL~fA?s13&Bljg)eG^rdf}eS}wO3@6OrC z263!vjq%w2M?I^_ruqf=}?0|AI5&jg9+Y%N2=xnw_c&w^{oW z%LKAZfu5g_;yLj%2>dSsELZj(%{l$h0+uFAFm^AW5lP=q`r*FJT~)+C`jAJ2!4dES zqi@z@tc(BE!Gn}{y+U5{YO&Jx)`jQRZ_yFUpS<2$_n2v^Ll#-HzH{m6aaXSoA5%YMGxN!E&a=3>RmyBTC@l}4m=vFzy|SkcPM;QGua)yo2- zNw&O+tF3O{2>czo=bTp>v{m4nBzK){70?Kcz|Jdz3wzNQPAZzhJOlGP&5Ee;T3b@y zWO~+M25rEs8+W$aZF^d~VN1~`ABO+RAl8hv)ci4)KW+*8<0_yrUB*g)EmsC-$szyO zZgJK9&zOyo-HWd$T`yfOGT(Fa{8j8p+P_zwE{JmQGw}Tt+ckH0N^zHCG%qM!Px1aV zE2Ma0$ihO95uCpPcAK0>{?=)*rF9<(ZvuYjkk{#< zi~+wJYncP5Sests$p?mjzl^YEh2nosbUA-Ruz8$5N1HOnb-y*qJD)srX%)-T=g;?)1e%EI>}ulK}%I6sc(=dpX``|=Cw zAGw?XEKqvE(g5@dVpb75_r;F9W6%a5{(A?8+J{S5*xIpEY${x~>CH0S_3KFhAU!c%DVP?^CU|4WO4VJ67&6k@~>-66(`<;(i0- zzb<{LJ74w!)DO_H@-gy3Q+Q46t0k;7oW2t3d%%%YE-yZ?A6$#la4^LOmVK(XUoL?C zNnrSz!75P+%_O+LmFOW#!#|u$Aa%S?ZDyaaX>WK!+R+pNe?$79n)%brzxw~7+}8|+ z_&=Hp^g$0O1s^W1bvQkCVJrqN=|c`aV(keln(?6(Oxnoz{f3R*c9Fb$KD);zSoisd z;Mt|yz?Da>$MSRRcd7+9B$K|+NMgt&D-UkthaYRuWtx?*8pZEznx&6ILpdoQe51Fu z7>SNLaXSVbIzQ&bDh0+^8StKzKJ(Bx+5&g19{iym7MC%^0;<91Ytz@_a%Nl2?8z40 zb{KXKhi~#ea+%K7pkNw4zo9kjJ=?sQUys1YweCK{y1lWD-{xfNGv!VGra!W4qNI5- zdk_f5*pB(1Z`qyo5Id2r3fH?u9{z|Ky7Ol*VoO)h{zCt6|4}>n$w|kxQN69Y|1|Oc z0y+JeV`s<{j>FCUlv*E7FIr!h&R?P)IFHXDA3skWPL3cPZ{M!N%m;37v*d1{@xzix}r_9@T9c3B)CeuS5=J0^F?4?m|kldNxADCY{H9*>yn$e`iH?>_r(2*#C+`lMjss8FJ4i7L9~U{1LU_RoKQOBUZFMMA;K}?_v8)tn54oI z>(+PJ{q+a;?A?(QZ6vlmuWg>qP4DQr=ypaYo1c|$3&8xA=Jl{e?FwvBcA>5A+TWIU z?rq~zT3asp|48x#+4^{}MCA!%f6pBz;0shg2m_3vuh)dUVJP^5e2Q#;1h|3nj{lFZ z_W-K$-rBy`#Ej9gFrqM2VJITP&_O{!1`rS{Dt0UgHn3yw6SyV-HX$CyP#7F=(^)@ z1N+jKqc0JjVxxCoWY&Hd^~Ex@MA<=xrg=1VeRla0OYXP8hOK@Jtf|TZ@c(@l?y=Gp z`z)^O1Zy{JBRR}4xF>`8_(H)LbF3M>^rnF^__XnsF=V;LcAaDiJ*P3Bz-&<`<*Veb zrE}?7jkf9Aj@iQ9HP*Ix95@R4JcmCs53nU1fWw-6;7ar_F1COC{-^8veT%&*XBJ-m z1+#t^&V6c{(L2peygq3Gop|>ox%-=T6yDG2ljq<8)iD2il9}E2;PB%I`2AZ4-nG4Z z-mt@O!rOoKEqiI#tIYAgZo788YTGwIW2=^Lu-VfW+B|v^E34PrlTV`G120foftvl3 zPN49@%U}S?G0vTZ<4a%N{o_4- zN4@Ypx1q% za1*H$5}W3%LBBzL0u=wH#pa_}L`@pTC}q z`CtLyYML2n$gN&e%^B4081*1uln>F4LCt(L4U2L1KWfal+TIcJ@v zJFK6adD!GV?#s?)yDQ+6>T!cORw+4(>Vw(bT;Cr%o-P~LeSE)|zIZwK zUMjZJ4ZLYFv0lFu?_gn8$J)Lh$JFtvv%6R<^HxFFMN2rck&RSKWaL&040`752iEyEzR@zCb9#U81Kt`kY;_P_t|m$VsN)L)OTop z;2+cjjAM=cr*L2HU`fW?JPF zM;(u(`=relLEJ7`{*qO0JdE9rFfV#I(b+}d$K$9$=Yj? z$Mk0`3~p2AAUJ%z=2$R!U2qC`V0u4z64jR4a{@i8X;wIH8FlJ%`r6F+QR{RaxyUxY zbHygCc)|R`BJCme-bgF5X>L#J)wK&8&);3#mtMAJd^GQ?9A3J+XRzs$hnVlDeM_L7(rB&7IY}ukEX#Z@(N9?s-aQww7-uu#CIK%tV6?hMf|Gd-m z`TU}IK3ADTVg`wMKl!T<&!G8(yEJ3yg+%4{zh{^_o*W`gZ~GC zUk{r8sOvNPfcZo-51mZ>Z`*^Nslod_(#H4XF2p?KKG&b{Gr(7h=tV z!T+cMv>!v-&t5IsVE;ZgY5E*z|CheFYD)&dzW|S0*0GpgU>9eL>f;T>{)@ozdk06_ zn1r@2c2A|pBwJTKFaSM6^#tZqx2sn$7j3M?a8Rb_bg~KQc{ZNhztq#m2GSGg4&Pv8 zOSr)at*t615zcR-O^A%O$uS8wBP!k&$E8>`eX}&`(WcDl#q}6wiD>XeIBqVs%GWgJ z_!7I9!Q<&+8T3^W=%;jr6Oco{B?4|tQ|wcRP>0Ga>CXX{^EbjYQ}!O6B*-uK$q&f4;4-m!(x z9JD@giWY3$XJZyHm-6xnE1kT`*1mPYW<7b#lHes|_hqlfkeN1V<9=cYT#-IimQTGt zZp(4>_N#b3E3NOWEocqQvhr2?taR~CuBnAK`MDET^} z{4bud$pV;7izMet?LL|ue<^&lG1g_`O6$&!^}h4bR4Y~=iam+5x7fg$8<_zZY*X-E z(^l=asq0>}DXVr^G}l<&#=guK(yQe6z2X1-`78SW*u8S>ub98~Ny z*O1$b^RIm1h0?qUs!51jb?|OQ-J%OFCT)f(rE_~FckDp@GC(g3z zQ|8;UdCP3n;0hZ`zkEblmG$q@$Acng4=31fa_Onuq_+5+5Q*z zqZhKbR@a-HUUB|whbz?9{F+79zJgDvF+L$@(A=9r*=He9A30_Lq|*aaxC?~w7UY~pr-aj%L|+}jd_!3c)abw0NRrqcE)dY9W}># z(i7@Tt=Jd4FCh2t2^J{4zvsAW#|JE`SYX{M<`JXjS{wR)Z8%O2J?uQ}za#y^-sA;C zr!NO9tgy*TAG7Qtbce`gweLL?TuWSV=|X6RM|$C!32dZ1ps9F3+{gn|pVs;ZFaUDZ zCh%dKg)#q6y{ug!J|Xe}+Vhp@k(fKjYAXARmiYr z#PMu!lXmn?BH>kcBF-klzv@8^mCOuGym;31^&9y|!gGiM&qLD>oGS|ZYmv=vFJga- zTzLCgXn;~rctWfxzi8@c9=gKi#@|YlcgPQ3GqlV9C|F{0-8e0Du?s+o4n2@K5@W? zFMif4s<+$v{U6(=H!s?xW!r4jthF|A;bXkJx{e#-k5)t|oYsEq|NDu0_**daJ7DCp zksDxX;sQ&HL;JL9-a10gf4~mDbX1RbA~zmFFcDK%3!~-^pIK*Lt?=L+Y)~==rMO1KEpau z{}(C82M;VL2lt~cXak1V9>cM@zo*yRG^4U-lY&!Y{eml8tWuKZrWqgPOl_a13!9nd`$cjuif`g)~y~`oa6v&M)S1=mALUr><8xzB0(o z1Vm5+GzW7}f>$WcZ#cT(>H#{R0XHBAELZ<>hfW83Pq#YYEJ^T_4qyJkrdDsXJvEnX z?)n|J{-qcDv`9=+5$!HZt_?7LREd^35vD;J7#+ zYK8|c&=GQocfknuy@X!(i_{I|_y^y38%zN`Abzhr{yk>=+isAuCS3oz-@BV;> zkMj6?^aRC0{NCZ0;swGT0RIG3Wz4wc}ayBiHRmEuKcs zuNj>fG-{+j83h+30$Yr1uUS3#nDhqI(4grwavuD&IWC5GrB~F0{(fhA|Luoh=j3*= z@YT|=ckPEv=~7M~M!Tto(EI7Z{Le_sgb$bvC#a|bKSIx-E&R`l*~`h}2EhZ1gU{U? zT)2q%&n!6gySRK_^zoF>djv3_OdX)Uln3#?KD&}&>Vb1QFeR#ulgzf=>*>Vg4q6v+1?Aaw^u&K5AgFb?mv0W>Qoc7x`xqmMR$TA#-==absE0$vyMcKDYdY`-!2g6z66epPy4G1M6SW~?9| zm}A-4eVvEvI*x(%0YBW>&vM{{ZQRRj`ukUG`x~ci&yfqZnX-^3Re9TpI(}MKakI?0VlOZFs{bl6MRo zzuX3lnQ1GYKWLA?e9~S!^`&ip>wVkw+Hu>o_qgqS@3Osj{YSg--5+-O?mz64yZ^NK ztPa$YzW7yqcl$opm;S%z;id5-j9j)N4G`gGn%Dmb{@$?zM_u1ud-XI^Cw`FPsI)YH zAhx>t8lQ2GyjuM=*{OIoKivJv`H7qI6~t=w1HUFOzXC_#6!^hgV1vit7f9<%@%$D! zy6o1)b?jQafqUQ6|Ch}=oBxp>U~T<=mtOweZ|`!$2Y~Zk{0NQ${l&{1>na$5Gz>J$ zaErR;4n0Km{%?^tNDJiWdq3NTZCmKOCfQ)Fzl2Uh+?-eo>|Ap_Epp+5rg!D~U?vcZ zG^xu_as;$D!SV{r!1}=Z+B-~O3^QqC;d+C`_L)Gf2UiF`5d+67g&DwvLgohx*uRWF zNhs*&W`a7<2kbZ$ZC~;Q>C2Q(U2JWbsnLG+C}uLGU89)o_I?o?w6oKbn5XMj{y=qs zIDSpAbq{_ou3%%u{J>Vs4``n>_%L?wv`Wz%@C5%0h|P5NKVkB8XaApHzh-lKm)K0~ zc=v=^wy9)<&Eflr)Z+c&p(@AkMGjF(e@~nr%?YUfSG}*iKy$t7;bo?$n`bj+@Bic9 z|Fr+z=gjtSdxw1B^E+l|$q#m(wdfDNHJh~5{c#lMIF%YJc`)xMjMzByQ9i=~4%b%>Aij?@{ldV_x=mPO`SfV~ z>GKCNV;F*dqO=#AFk|VTMDGF2p@h7+sA?(Pj45a_Jp`sW6-|hAqp@Or(Ouqg5Ur^j z_wD7w7wo{<>$VFYFm1(Fd+o!o?WqIjtQWP)@|{Pla?w^Ro4WygX9L{4(Qx+G!q-Q) zdCF@10({T>GW@}6FlD$Q6-(ijjkh^3en`&0#;SIH2={a}c+xuXy2aoWXa}*kC>p<& z1s*kM(GK)n=^a+Cg#*16Zr@salGm~ODlsotWJw~&4vh$D6qwxct z@IEpAD#wyWkM?|Dy)3Q}`Xbk4x5Rb)i~jEC`w#2^J$v>4@7{qAa1TH5;{(?hy!jRS zLgX8t!T*s?*s0_2hp81*2k7}^_byN2{Rj*E5kKXrMz1@jKV2ZWF}Py?t(roAHe zP$R3FI?LJrRqTI$-+|=wIktIFg>C3xPVc^xO=*+!pY|{OPd`rs`*XcIY<@8qL07oN z;tk6Ob+}~7Vw)+FK)$h2tZ`Xe?`{rB62F3r@96K;E zA0BlipIyGa{sFx9FYnmFkFMF_PrtD}htH7wU!-1SC(pX0Hfqx`X354_ zd+@vVWecqL%q{RtmU3-Qv+<9;&R)_b%mA&mK2uiOc=C$r>`9xs>2+K4(qVgQ{~6o1 z|2^#gl)aAqpSk+2?LB_p_TdBGsQJi_oWExKYd*FE?_G3SG}5Q?g8SbBzO~~2KYst0 zoBfyGhj{$r09^t{)81Wi|4)GVtFJG+`rz~j*wzepu>E~#hrb1;aO`l6;|OR^&-E|3@z`&P>py}?$o}vDc%Pje z_z&`Z+59gLesQ_K{DkWJk3aa-%_yEcR)aPj`PoR$v4#22erC?(l@(J{-J$m zPZ0lo=w%gGfeqsalbJPb3-?zuXKlIK!PKT;B zcAi3x-%5370elXww^;R;u=@z|QfUFVNY!58cK8rx1L1W?Gkcu{Mw~|-kWT$o#4LFX zaaBFL2x4q7cBQ_gbf?v$@l&5B1RZK_{^${jAM7;5sFQVHljhhr^{p%HfdUI{r@@o_45V{aTwmJuKjFP(E!KCnFP59=zvqqri=%GJr`M7KR-6rQI*4ArKmC90{L-vm za5}tw`uEzwA`Q=0?dk8sdk^LH1~Ka!j6X@}If6QRv#Zh6_YVQ@m%lGW^Fg?706hn9 z{7ik{2&>yH1is!__gbU_*n(bR-DbfqN3Z$vo}K>uTYKy5RXcsnAVR(R1kFeRH4hFIuaV zT(^VX?Uo~!_36>w<-_99eT%J1^FunB*Dt~4CI3H3et!53_G%ns2Oxa_Vf`2J15R@T zE$}a~+t2X_(h6|p4-05UZu}>9A9wa_(}MG zm+>i@FS_MkgL08?ZZT^_{-9doTk3fAC6w#mxUN}%+Ige%=>DEK`W`t7I|tSOSIq*? zNHYkU^>Z_g{H-_xnj3I+3I0X;AO7^HyU`nJ$L=}#0L_&qb)pAN?bb4<7q(akKGYj* zSXwUhlbEH~%vcKhvNS&#m0tq?nm!fSQ3CtrqL@30;Xdu2XeC}5*Pstv7IDzxm;+A5 z_SG9~TRfDxkWpy745e-;2lGc09J^NkHzu1s^VDY2fb?b#%#%7*yWqU3gO&dam-eA9 zmW`{&ulwak&9fcKDXrse5LNHaVLMhl}1M0(~`j z{7vEggn_@LQTL`|iX4p{v>u!z?5RU)jA z9?hvQzPCN^oVLRsT_?7FZ*QObl3M!{d$HzId!^=c+qD0zO<(n_t$OhkT>CAyVc&V1 zOy8q)=6Wlezr{+x`E%(7R=^*M%SYodSF`35tU10Xp~Dbzf@Q>hc%?HoTbHWM%sf6} zRqzS>O zU%I&e^1Em4#Y6Ag_Wj3+{a_XcPTS6R&ca6$XDXgKK;|tv^oRe`!~Xj7FIO*%uP=QZ zW z`Ek_PxKdkSyV_4eHZpSeBgzSI(-}V2O=x?qYS7obul-MRXewzl5vdx1l?deff zwxx8mE$h<9R>K8c)~UCxD;{jmRZO<+Wn*o5*Zx*af3Ot)ATGap0OA0aq-9yR+&n92 zmt_U`gM!pl%S}$Qg4QXPo0Mcd@^YOE}D z;yaj6BKm8ooz070oiF@7e{%Bx@`5JBc=_XabQofZqni5<1rG?KMr(;qLrY?HBi^_6 zHzv~4jwb)|p>Ajt7>x}pH=>5Z*8EdCkpmQfFM^Z6{r7Lvk>2@2>ot1~K3g1`8Js8T zf6d;Jx9M+F!RuZ-@u?m8@JoB~-4E>i^?UZg7vI{+&+pj@a+nXk`jy)IoV|4RCJ^U6 zTS|X(`{7HrbjRB^emS$P$3ACnY^se|!@i`v61ccK;f6fQ%-2kI3Uq<@&z>ZFSi9cj z9K6>QdQQS0+A%AXLd=M2lLx*u+9s`k(H`4-#N!Xk&bO6W*_I-HCOI0oQv=6q53v*%tZU`_uuRyI=!n0 z(euwQvUTi)T;92lEfo)l`d%C#-IVhyzAHZ%123SgRg#I*tC`+-^eX!?^P}HOOJFvB zV0LRTLCqE7530!(7J(1yetn&loNWu>3C-o_dHjAB$DEp)Yvb6XI6Vt3Ma}<$&-qew zd!VoEgVwJP^}0Vgj6R9EZlAZm<^kyIhvEmC#xa`@w>^;0Mi^f(KG>IdRv)g!L-3p$ z!;jV6kQaUbIv##-`2skew0iTb9=U!U_C7YHR?@kPp(mJCQsF-5_GQyC|2oWmi~)C~ z)*{d9$c*u-=iabWpWm^!KlsX?-hYf7`=af7=L6e*;Eb)`dB9db%g)(v{==R*bk!Da zdfOg-?vOq9>KWVk+I!4M;qPg;%d9}bsf3H;He%=h=PZ1}qA z#lvjWn*EkTjX8|D-9gm)OJA@)n*$xrRXXW!WS*X~&+*IYfHFltgXqQImy z|9AiHeV4y0M^^m*=GJ!(GZO}I2;QIkz#xUm;D236xx|}+)tD6mt#*U@a*QUn^cmQB` z*nJY%UV`fhvO^l2DTHe-k@zmXD9w(vWOuN7ed%DdN!_F$R_b)CTXD=#YOR*^57NLC z^5OkR&$d1JWL97LfZU`R)R%eSC^X@u_ZNx%M`y9G4(%?@1J{K=D-1A%+%zn+BY8xD z<195L&-WvK$^HYl&K2|h!O6uT@`;Fd`eD)$X-K}HeMY`q=MaaiU5AcVj$XwS{J{iz zYQpnn-_qjI9I*O);`_S$uv69lLy7ghLL#jny}%(+iB=ra(lVLp$v}fJ&o9U(B&53> zV4-{l$5F39GXUZdCg3L~fEB1$px;URPcw$f8KgI&dZL>5m0YKud9p{u2b{zkY|jfj z^&;2u#wREz@Zh}!6YKp`!0_Pe2Bovdhde=ZJHh}$ImdzcTlE9Am)VPR5(<8!nxJ*h zQRoT`feTRJ^0*Gna3)YY1jJ>Nb0uO6%vpE_x>=$2L#Md>KYc(Ioa0W8Yv9kEfP82` z3_69>B%UE)s$i{kz0qsK4~bV9kkJM0O8T^o>E-lb?o@FmoX@`z*s)(6IVL%6 zFZ4hEA^smZyLSCtM)TtWx>{G6!N0)#-+R>NufxlE0S?|tW&qyZcYvMTFS5sXw>`IQ zhwWmw=Znw3gr9iJ-hcN5J%U4agc+axyV%jWeTO{?4{!#0hzqCAwdrVG&6zmUii-N# z=phqq(x|aEd|7%4KeX6=>#1xTN#~R1f_6 z^KWkc*C!&@225Gbt~j(mu<>N@qNE~rVbT*;{T`1VP#pPWBK{x)Y*00PB)Cy9xoHdf z)v6)m!Htu_k0a?FMsh9s<5xAi8A(2&8MByNbcFg=lJ8Am&SwmL9q_;I5}^ptLrrMgi{(}<1(;w@p*Vo)%C*n#r<~}Kldr_%Z8^D zpG)|=LjO=33{E1A&nozSqv;V&;TXlCtt=Jo@m#;=Hi2u<%>wavI+kXMvzhyeXFj2j ze!-%wPX9Sm?B)jW1?nNpC-!Upw>5lpPj;_rzONa$z4me`-pdz+!0A;#z#qHU?k#^X zJ3sOQ>G^7}k@hA}ogr1>j zw&0T+V^`8_Zs^NgqF+Sq{Fa9|w(H3#VIzAOJ%NXut=GpLG~m{dQJez`d)!nrz!d| z%!}y$#=I_1YD(=gYL4G(&Up@}uT|2!*y;a^_oIHfbaT}Ul-94)_s0*Me)p6;wYHYS zzik6Ne(Lv~*!~mipR#?s_PX7jd$GrTd-h|KZ`tmr_uw-Q;2W6lf9^$F4ZnZ#xXCta z{2XR}=G(j}GhO^23;%CK$q1WJQDqBfJ!-2KthOgNZnx*Rvp*33AuTcK{R%fY`1;#U zU+}=bx9ueO;c0RW?Gb&F*Y(VHc7>yD_{y#q!7AUe59upjzsg=B>KNq!(*6(zAkL6x z34i+j2j>5t27gInu3{!VyMC@;*M{DIdY_TZSeAnY453duhF%bQAlxTyK<(iSMn9?* zKA;8IK#VXy{6tJ18uP>&?E+W5E$#0tcmOS_8Da~t{~p8W6O_W=s9-NQnhp4j476(t zhmI!CTWzuA%i{b;W_BRAU``!7_5^2>zIQ!hlQ((2KQpev58^wZUxS^55FfSMEu;;7 zuKZq37dk|^cnWiL_zQ95e5rFa`>s8?kB|p@`1zy%Tg%;%jcWc*cB?!!oo z3I>l2PJ`nMW*9-=#o>U&=k!72ER(v*oAV-@Z5owEzh*RfS}*WD@&jt9t`io+@fhs- zgCY2w4i$6o`Gc|RbnJh;i~rJua{8EjesKl8(I28NgwN5I>mZfSGMgT50&$@YGdj|a zN$$q}RQSm8Tr>K7TH=$MGgBaK;?UMv><^`Op_eHv*BiZ0^>f8r_6UNX9gOBTxu1BO z^6RSiydt!#oqc`G4vN2_UGvfq4o}XZZebrKzF(iQ53>(}G3=%!_wzxQ%`1`}l+;3j z;KiZ%#tUT94Ajd^*+5q`uEKDN~2R+Akqsuf8s;%I5grv_zat* zK0kEac0c)yJ^2_~;G4D+tDm!N>o+^y@OSA0zW&NVdvhPLn>_ylJv{XnzPQNz?v-ow z_0S;Tm=2Tt>t9?>0pqc;v0mU!bhfPV1${KC+UrB96}eN+eX4*C$P-&ztE zwUbtw@7gEQGDG^eozcz6q*f4C$&5R;-;8TUyR4Np9hUfu)FdZMab=X*2(ygE49BKaF#s5TbIpV!Hd3hi>OCa&xTRA&@ zJO4KL0(dZPM=*ZY3tbcSWHit33wJ*VU*R2z-f;_X6L=2~H}bWIdB63&(Ygx2&Zwd4 z)6099+au)r4dGQk0uQD!F~2D@HR`3*CuX<9KkHv=5qhD#_efrwIJpVA?EOgxr^sP% zDE-AazDD3LW4XUISdR35wdXyxQ$P56_zU%hG7HcF;PauU8iEgq1}ACJwmr3>W<1cD zrpNjfQ*ku@>LlizSgwH-0A0E%_ zRs^ppu|4|32AA}=Ap=X?t$&|B?9Uls<)uTcbkIO} z{N*;Xyv)i653!+x2Xh-z`?qD>H*|>g@7>$_k!SSn-N$-%?P7%m`PQ*R2kTf+V4XX5 zwBq7oE9nP!v!tI58qm-B_vy>m0XA?zi47ZC#9**So_!B=A|Gk34Yz#V=s6L2Eh z2S~-(;b+t?@Z`nNuqAkifieQfvIe!Q^fu1WA z3?MeAv$ZA`#goUhq0bMSG z_(u7oWPDC4bM;Z+W|8FBod_i^~WAg8g-aPkO!~sjD_n*c*PiEh-^pN12f)O_(2Wv_`)(U$~Lsuz-9&rNt zAetfR43^Yw_+*#oi)-gW3~xcNFR}ALi^q?&%>M={}Xj~4;DB9-`&HQfhSEwKfuEX{)5+y9<~GSRS$lH7d}8U`+g}M zi23OG!q*AH{{67)=JaCxuwVHC^AtdXXmwQj128ZXgT()q$V6gJSb&W6raqspk41F^fPAf-fE*ZEOm8R2z;e5_=Dn* zY5!*gxw#+yzhh|?+R;_;NCr_`2v=s;2s5Tpe9h+hG_x6l56|sa;qa#<`bQDuI9~YV zq1AJ3-GLWv{Q8yD_+iAA!Nd%DOXRR+)8IA@9*a%;I~^$Xj{W$|qQUu;8^%$a#B+_O z6b&KH4YB(8P+@;U9Za6q06etc{OQoVk6Sgnwd(stVNYn^!|B%bm^TD{LTc#zf$Yo}2>-c^T^RhX z{Xp<=@~&R+G;;V}y618Dh(z?LlEBKeV=0jQ+A}Q4R=&B%Uj6tKx(Fl4k0agh;tIfU z@Kd=ZqutzhOX}^`UHYKmNv+l$P9A=w75P~L{jC^spwyy1)Z>HbiKT#rrdo&LQ^C&Q z>0#gT^zOycbv1S}y{I7SG4gQn=|iYV+Y!fesWDrCL#6PU4}xpbcj5y0sI@cue$<=Z z)MgRns!_S*0OSxUXo@6q{U~2=3MWrEZBwq@Kx|C&#bxw9q~F{KJSUj@Z7DLXFgsym7u8VN`$-$hv zW;~`YJ+FY4=znMC(YvqB>lORO@9&R|_M)#pj#xgKxW0YX0#_rcE-bW0rdjZx{`lQ$ z_Pk=VI@Q*T`dybM{`iWvjteY2LAily24RO&$V1D}v(BeSkc4LGk{$!-Beb%L#5AY- z`9!~RThnu}t;MG$5dS@x_X&V+11FoJ-0QHaX*hGA7PAU3|%;4mXK%0@zw}2YIBe&v-)z%3tx@g>dr}dM zd_my~S@do-U!lIE{JtN@_ahewBuCKPU@&!aAbh=09v{T(5kE}3;MMDGthd8nbE^_hcy+~O(LxeBgQoksL7vUC4g2J*T2a=ijT!fjY=6Su6kkt?eW!AXZd`9{Ib;&B1d%yQ6| zZb~o5k8>d%7jfAd(VJ+5pK5^LmF7Y{UZ?h<3HKHTE-suuKK>DEx2o;yZ1JA$)JO^L zJc?M&3}i)P>{4SWK4&CI`JKRTXfW2L88hx1y$8ME@(a{%#4b9#CB{BZoE zX2)ajv&o%H+ztrgx((^+cu_xVKWGs6NgMjJ(vOJZ@!I1ukol9I=m#iQZ%pm)7X!y6 zn%9f%%7-M-FVGxtY#!V;YH;!Nn}ET3a-Q{B$HD)R7EmnpyJmO-*qaeT&aPdg^|=n4 z!U2?ik9J>cA5|uCN4>;QK0E0Jd1JFdT%W$Wj<`Oh_Z5b{3(rXIHWfAZhmck1rlM`t7M_Vv##r}#m?Hs01 znUH3aQsEqCcdE;Octt3$OTG3q})D`n&<;Hv!`Dq2=9e zJh)9Ub_PbOzF>1~GJ5)#Dd+lW;P&}eoi8s8uewPIWO5I?C&GiX+LlTpG!24 z6}Lk(McG5D&{PSeM#!g*U`7axEtu!mZn4^#YV}xa`>Wa$D<2Wa-+2+6geNq`{wF-O z);i4`jqRYX&AE{tvuwI47@u?;h3C6n=HPYyTvxJ*X4F~1vG_l1N;{~f>!|&&e)x3+ zNZpP%2TWK!>oF5O%DLmMc(!_#4Vk}ehK_9<*8qCHZ@LlJcN6&&a9NK4=G(CW z;bmU<0QIfC@sUmZnQOyln}*PzB)0i-URsLd$=_?vyX4WiHhf(*F|sYbuRi!E@f15y zuhk!W_2Osw?}pT!nxPjrwgDJxBi{gUp$O-Leefj#;4bpXsr^P!PYWa^@E3Vd`3ymY{D~3mZlM?(qS`Y$!gy zT|G}rrOz}sr;9ybImOn)^{b{H9g8389hYo(AKZ5~pTNa;m>KPx*!&qdAcM&3zrAmUwIissZu zUc}jE^yxI0;|CttoP1e2z1rs!4*nuNfadT3g2)FtGSk;@`YLMo42SJIeNXg0RL=)c z6Gh_BThfnhj-U17+V-Xos-B>*fDrf=!f>Q3)&ibaP*OJ9f_cs-cyP^xXZ3Xa!2o=# zH|IYXzatH0Vd~8}zPMQ7TnE}Cq39YK*t58yDP8;8fT{)Heq9{aBc0fX=_5Aq^mTTico9gAsJI^ve%z9p zzdre`2k}$KkA%Y-Mm`gq1g^}vQO+Zda2P!j)s-RiF#NztRMP~CXTkL^O{QjGFUmh2 zdZel4jV`y?e(X0KJq-Kza2ho}5%e*zO;7Av{!*G7;;jVX>w~~?)w>9crkUB6n${vBw5|qT}gRS|3K}TePb9AQ0r>~^l zkFmlwsq>@2JEOsAqVjtX+k5i4cP4KG1EStbrN(R17knSwDKI&YI01K`o_`eapsD)4 zfvq@x8^;riCo& zBT_u^=DC^>zqL!+pK}<(_1O%68cZFay??4{RCh>2K)H`{j7i;!?FKu$AF$)^{bR@N zxkuO7gu-stf!VnZjp6mwX=r)%;IClwPpx~*j*RY3jOiP%?2EbWV}uP3)CCN}nF4`~nhLp|XR6p~YHT(Hz`Z7&du4Y9nW8U0XH*9 zyzpnPRkOQILdBmZujG77Go-#3JJpFlp7>pl=CRle*BEgA)5hO!F?AEP}6{(SD*FRvJ(9S@JN>)r7HuwiMvi4XcngJ#$g zyIqpW`_htFRZ!pM7fsMuOan{s#TLXj(oUGV{N2NF4y0jTm)-Be1T-Jw5kQ}j*dk2% z5pP~Ik5%sKv?Jj&G=O*3gc;LDpJk%C^9!+^J)gscc5^thDd15_yWuCm2 zT8;z#8T70hP#4$deAL6gHjTl51~g?Zll+KdD?ey}KW%{4oL*;R&Yku^`;fEOCkJRi z?j<}&JMuip5xiQ&JKWF*4SP>&;sRoGVc8_--<5mCfFTL95dNk)GjXkyTZ`w>oX<-$ zywd0t4_}yiDmk|B2@l?v-h&s{oP37*?ycwn=k{gqPyf;2tDW8Fs`o0*-iFjrO?hk> zwQkdJ9;@24Nx)4)EaPd>4;=g!&no6KikNB13F zup77Fe-qp9a{H1wA>DuDHoH@J%#E+$RDAP|{qpedHpszP5k|rH<%e`cktJDzPIBiPS}+%u3AAf*If+ni(a4haSHeM zQN0bvB9QazOrPrR;yAn;DwT?@nJps}S6(2CR16VJgVIbTn=_b2f zYTlvLnp|(>o}T2f(hc$;XO&&c?#1=@2XoAY|5vBZ!+0}zI8K#F-;1~R@B1F&`#RWI zefWFucDT`O#t1{hc1e|L%MJ{O@DAyZ`=A$NRtidx+!ccshPVzUsMkyt;6O zbbRJ4;V0|9x(z+}%Htm4t6s-{`=`I*vG@n~mDli4-M=44%>W^Z-_^eEhs8Il!?Age z|8vvx==r(NeSL&7#1ntw<&IZ}W7Vk(N2zWT_d4t7y&GJn`g*+_x}pAFzNc~R^YT9Q zeuRBI%%!#rIVFsN0!~&D7`m zksp&?i`Nql1|Z+q*tdnt15!KJ;(GPDzLc9alCQzWWsjQuZCgB?+`k`u9_lLmX9F+{ z@k4c8%1=n^y3^1J7EInO|0wOg2IQX&>6?oS+K~LX1-Xi_grtsOq2w+h#366;YEOKG z_J20uSWSpMO^N%$X_WtK-Z+3d$De#62-}gb*3K902whk<(jNTd4`;JK{PYv^0KYR^ zea~)UqqlBh=el9*|Ley6H<%mJO+Ml3RdzA{kDL6*mtUgU{P*qJHO+Ig1Lps7`{vtk z?Vo@C>Gr#HiU$)#vp;~mSopuVe45SC&M#l`&_HZ7MEfu}r#|Ec<5xX}Mi2V9e12i{ zt%O8is1p&NxtkwQLUhTz~R(Lf%u$% z>wl$;=wmVc;O`77vgA@`1P6Ar*a7tC`oIV1U1(ul+F5XiwicA1iiRGTZCCm>Mer|* z+2_%do@{US3-+S_Pc9tG-|9Gt9LF8Alss}kXKO!|`Oi@UtZ-U|6;2;*xmD$sJ)z9P zI=8ckZn+lD*U*mOPI;*o)`|N#zV6fWMDje5z36%IT4GArIb6=}ioxA2x^E|L%smf5 zvt}szbv$pv(4LmSb4T^3zc&bsdk8Zuyr$L_{mCsu&HOy9^+@^x{4SBd(@lS$!13bv z`=ruhOD^lh^K`M8f$SOPc)DN5iP1UXJ+|Wg>UkqNu`e-?S*>o&$@VF9?_ZCJ9YEhu zkK;9mcZ2iLgWOc-s|ULZIZvUyuaLqF3oams<$Q*9BJav(uS*X23SR@VlKH;1`J^!W zn$*gC+QgVoTQHAwW@B@y8QQnu^GHWKqP=_0XwFG;S+P4Ot%vvJD|kHbU$+=uODw;S zDlW9vnfeQo7;Zk~>~D=v=knE+~c=Hw@| zm#=Q4rtIkPAwOd89@k?GSd?^sRMRvfm(UImJw{lrhw>`&a_tTdp!R7(4^O%b%8R7& z`7rt4BaPty2SxJt(!ioFicKfq1cMcx3E$=sc%={5_u$xyb8t?!W&;5FgZVz<(1&-Ckb<^GE2zKYLj^h24i_EWtrJH$_(xIMznsau7Qbs07QpL=M^Mbpf%5(qiQU9>Wv|MpA>=*O zZ(PsKvzQythC{%0uUl{~x(68vJSTHq*o1x#;%j&T_ypg#?3`us{kiV3*Z6_>Eo`=Z z6}ziPQ-_W#wY(}ctw;8^wiS9$11)1hDc5MUSwIuZoy-o~u|wSN(ke=vA4=!%vd0f~ zkJWj|nt)coqG{G~@+fOP1g?8gdyB+RwZJ!pbzuJrzA7{y`^`_|d;AnXNAZ{lUYCBa z*Br$83gIzfoIAb8;9Pi%I$yG5-mkM|9_N=qKAT4E-;Vi~c8UC58w<=zvJm`30AF=1 zKhA}Y;m=q7y>6{|zBXlGc=*+9Ua#I$8sBH~HFrWe?;p+r-)D{+g8%GD|Fz8ZkQ!m% z+PBw~UY~z7m@L?AT@PQ(H^eQMF2gX6YM2+MX5<_jk-aq*XY+HLi z)W>-Q9&JNvYu)NL^5A}+?_qMII**V`)w6o|Db*F)>muLeUL!Uk?vQlDr5VT{a(wpl zM#ot<@Zt{C;hm_-JHq4b$k#4W3D&1|hV@EGx8kHU>&dNedbX8h<<)-8&bNM`Hk>u2)ZJ3>0g8XA z*gyg{+h%w__nuODZ<*LfKuk+#{~6dr`rm#bbIf2%8OA;gy74kI59o3E zV~1L|S!1p3$N|pY0f6`W*Ci-|Od1$@R>uUxs*AZ@mc;eE2 zh@mg{F!L44{gd;+4(W5%!ET!nqm$uNY4=n;Fcg2Vf&jQzvQ;iN^6-|HoLlU4Dt%+K zETj7%`bh1td2r0e%xtwmzY1=Xv}^MEFbi1JpT4BDeVgNNz>w&j*X3~pZuGw*+2@L8 z9av}(xH}03c3%%&YA^}~8hTQZ!4}Rf6E#}vhWxBi%{*BzU&qi$AYr~&-)rN0)#YXUTFEq!dTQi@P zKOQ~SY0KEfyTr1GPK2w4-g?C>*DLXg0EY*26}B&oJ)vkYH9xol`9yQ-f9(YBh(@pe z<eC!%t2=pmgR?%IBo)YNi2DPtDe*Z*hg>`;L}hIfT~;zZ_drejbVq$}hE4je_q{ zP9)zTo0NYD1PfIz@KVtVTHV|!bu~nfS+|=`*CHK!TCrWNKL~zi053kDeZ-}68+J+=%|k4^~=|d z9_-$?e4D;c=X02~eY@Rw@RuF^7+s?4U{M#Y+2PNw+uI-Av}fNyr{wT?J9_D^J^#)* z^q$Zxy!pW1{rI+R+I7$ly#J-uT>aV}M|bt*W9RM0KbW`v;V*mZ+%fe!*`1@|T^s@TJXNyVJHGdf!fe@v|Mg{Ii`zKceR1H+G5NS3SDjWTVC9 z6Yb>9pX`ZO4%=#U9k#!F#`b^st-bdC4V%9HIV*xQ)wQ(J*1lL{yFR#MqZdAf_Ut;e z=}+6>L|4Z<9TH6n)4eAKSKf*o}VWo~7jzyNFr3zGJCxTlSy_!?maS zvPCyI>C}~B{63tYgB4TAOIs+`@%bkVpgtVL=fSn!W+?S0pHEcxe2XR4#F7)YChts9 ztxRndOPv)>Z7Tm9S)7k=ZER0o`O8+F`sRP#*1mt&roK>P^}(1m>n{xe_5CypqvF_s*q06k@OH*AA zrapkUKCa(iNPL6m8QU4ZOr8;u171i^D`&)9XaDKs#^#ZTGozjKFn97FYQ*Xd(y$fNVkBRYf~UD$Nbj_&+LVY{K} zaQ-^bha^sBaE~9$n*lYy$QoTb2DQM`%HA zlE{5+cumR!oG;PqD}!e^X&7~GoQwZy*u%fyM;5h$j-}^MF7It=e4pGK{&XU_<1lIi z-e(%QK`O^6m@v$8$CP55!>#>T=G(Bx&eR8aV}@GpXmW3C(d8suOA(6WTn~Z7cCUEw z@(AiwZcU@Z%rlnU8=s&WDiZ8K=Q@AVaO*H-q!nSyMYG3S-$m1H;1c#NJvz^ZEN72G z^(-r%Kgl{ytF(g2BP<7BrPrFp>(;fHGis3Y6FFcidf&2reU2$yzj65NflC+I7x#X% z3t#_g@0__{pa1j^`|5{(+TNOvoo?D0bX_jo0w@3Bcf0iM&-T?%f7lX`e5yRd{u6Hmh#jrv?zd_YAt>Uqzj<+>&%Nm>V)H<8G?J;&; zZ?i=&Y_}yZJ!4B>c@7m!7q`&u_Kq+aI?nPp-3BPjBRJw%gnt zTW#Uar_iZ>%8F->clDX_gpC(|x8=vK|F7H16Sr;hj$_t<_$FH{9HWX;Ot`J5E{Pi&}E?p(0;@+z$P3{gZ#xH6z=XZ7GJw^`V1PYy4?i-y+Kz zF~HjK_@pB6ynOf@c|figndCnrlfv_g*l?dd@-TnwZ_T96W}2 z(XuN#7Mw$G@*i*BXVYl7t<*bBT7^1nPq8VLJSq>|LN?uv>!k$X3MwjwS5<^+sQ9}wEbtV+Y2YJ+tUZn*xobOZOyJj zHf{A&Hg(x{o6NlPFeIMD1J?Ow5`OH?neAH&F+07n`*X`w_ zm+g&9_w4Yw>sE8+zO|*67iJU!cAd#}H{AU&#_WslYDFGih0&=(Nyb* ze@Mh%gp=<@5=+_>i#mc^7m$PHb6#`Cm;LRd$MN`S){~s8H$HhJpVic-)>{$RiLe`M z^zi?~{%_gj-KSjK4{Tis7Y%!X&nw=K_V!BaQ}e)@2?(HO_fLTTK#kBMyQhWX8^Usn z;6}pP$frlreW)e%t+2Lm{4xhlgbT;4LDva2!uAh(W(c%dTcnXeVQfq>1;W~wsU1cOiepxx`PS!hLh*z za7Wb~Bi1a&KhFT`An(aYboH(9$3*vB$>VXbFB54J&|}npFL^pF6Mdk9J8Oj_uD`1>!1E<-~IH5efR61=r8?dU-CB>ZrrhVKDcBjKmXn?{q!I9#`&-9 zBFFpq`#=k?Y^mW^N`g42v#OJp0m8169ff{@1!<)8j%R!s5 z{8d}9VV})?=7?>1i+vPFKC$wtkJ_j?TW!Rm9k%@WH*C(6du-C0UH0^wpV{l5-a;Sp zxIJSN`6*+ty*GwFrQA_g2u#WJMz_ROw`Pr~# z^K3rnyG15^XzH{;Fj>{8>dQF%iCj}Stv|NmFKjlC`3L;GaN>5u`cvD&)l~fdWiWUU%lqAU#_e_yZcJ4E|`gOab2@*hxN0r_=kZD zr<2o+b@jJ@YkCVDKM-tDcz75#9@&FF8aLG^G1z|!$8N)OwdjKW9G_JfK0rN4UHkve zg|p~4`m_pj`M>O6_Y1F(Z%E>r5Y~~(d(0RJMwXXueFywb&v{kWhde^Df8yp}E* z$iUCF<2k!b0oUL>bl@E7+D^gl^*)8oq>SuqOSe6XrrQRX$M#_afY zdu`qeZ`qdDuAn==of)v@wg&(3I2yEjPJL$UUpQjptDmqJkAGsF;o*70p%Q*OlpL*X zWr@ol!^sgtv3b?~>cRMdW&5a~#VunXyAeC&SVn1Ys~6-A#v4U%Cf?lVI?0aEQaf>1h9u_Y02;pk9~ePgq9n zoStg`0BQkW>I2^d%?ssQ(^xQX>H&W+K=ld(;0A{0_GT^*z5UWDjtf*DewONd?Q!iq zdcO5!*GIvKndo)k55W~eIBrOK5&9pKo&9Gk{uA?Ck04(2RXKbMa-eYRpfx$AVs_72 z6U>(wCLBO@fzE|;+j!z`7Is}Uxq?|8_Himt=uhn9+7_Ob!SyGcDvx}iXd?S>$z}T} zc5$A2O&nznLj9>>O1TZOXpS93?GTKut5=vmaxnVk+6#<-AXiA|+RhjX9>dp^{@vJ_ zh@K=l+CY3tm#L#Ija)-`Koq%)FdAXvy8e~hWRm}fC4*Um|7C#%D*nqqWR3+NqYe~axx-*jq6<><-{df_iRO{=hW zUT)d2a!n!ywL``k1a??Wc%pRO$#dg{MBx1j6%q7&M zD_?ouR`1>AzRrJsi_14u3n(WknmNwl0Ls}qRB^7rD_z}1>=%Zs97yj!VOX)vShbej zNdK^7AAVt{F5LhFBu~dSzqtPkb^Nb(k$nC%nBa$B-m$abeFx88vLk2EBK?|O1b_Ss zyZ_a0-lJzuJ%9D~UHj(#@8k*e#Q*sh_Rn!YzG`pQoVOz%T()cc?t>c-$QORIT;!Z{&N*igP>>`U1qI9)Fy}0a z2{0fgOei2K1`KWY?(V(!J?HLypXXcua@%&d=bU@b-Mi0UHEXSZ#X0AiV~lsa;~nFB z760>g-15xHc=*JHc>U`?#62&)$6TO2@#N`mtj{D#FH10V1PTch5$8q<2-^B}O z{~WV6+#7>uu8(mm_Qake=VH>jeKBz1wwSkpIf~D}6T9wsiFwrcmh0|hZMtKLa~L{) zDzo$|MSbwz1bYHIZv$%64WsUb`jz7W44`{yrnGSdx5-vaG+K|AYVUeHA;V-yiO; zGV!}y^KQ%l#uv5ePpoH6Wc)(u`m8hB8ovPdSH0~3Gy>?;nWa=gJtVKG-U&TQFVI7eJ$VG!W_rxryE)av$8a8}@7fSk@uySZrbZI4 z`VhO?bIuxp&6|v5&I8wTU;M#9V)($7^T-26vIfD_=s%BnpF7sWJ5tMR+l=0%p;546 z>1YBLYc`fOZ&dP!Ydd3qRD7$9urF$+vZ@!0WG z@$^aJ{#QT6AOG)vkBk5EZ*k`9e~S0M`dtnmz}(Q^{W(s5@m+jGuK&#+n4!!4AIK9f z{?ot41$@B8-{UiwEB5Jy@8b;k;qB8G;>4*lar}Meq=Wz8`s{ac^2?v%t|RZo!^HGs zpZycHf)B~u#-`YM?+bD7u`lDP&wd}*vHt6VtvANz zgUn$)^M@EPc4FizQzU9pCmyw7MGRlNBu1=VN}NJV&viKfyY9buCVjJG!KQG^qlo7{ zJJLVho_w_rwckXu&KWoC_ z*(V^M-*nJa`aYWI#BZrBHYYuHR?D7a<|*JG!_)cxW0i2crg?v#W7 zJ1(6X^5E9ptSfmO)rtMua(8U5=Q8F%U_%Ya^~KyR;M|&W?bajqtACT{ZalPi;`aLR zT4Qk+a6o1Bcd%~O9$S{98-QPzdov%aJrG_Uu25W)us(Tm z<%V@K@gI&{Unf82a~}I7IG`by&8J6(9yMaH|BtZHU+farv8z!r9lM$dv48UkLsD(QT8jMt z5O9$`M7v(Z=bCG*KB&*RC3Zc0SL`OnY=MVff7ea1817n}FrIxi=je(LF^6i&_qM_Q zC*qs?!C8vwA)KmT%E`wSf49f#v~)|*(h?}4=L%#QnBfUAEZW-u4J^SH}m_5P<~ z*7nwR* z)e@&JA!e4SUlUzGuHT6NU&RvEvnW!VImIdWNAKT6954**36{r3i=&gM=8Z|%*zOPkjZxv%mIZLnc$W_`c~t%!f}k!otK zBep_^pgqd}Rcuf@*?(v7jJ%-7lxh#yO@Cr&eR%(&aQ;)U{mIzRDDn!izp>W*+qmy$ zK5p)Bem?iwttl5DM%?a8tw1}Lmopw)x2T36EycMgRuf%qwF=B#tPUsDEMYA9!8V+8 zIeRf_Uwqhbxczb1wBJAX+HLrl>r%YGlJB?9v>gm^CH61>umIet{r4jW=n8k;a@z2a zdu%wMJF#sRHH!uKxJ(Vin&OX2SS6ix=_^$o%RrvTP-~e&{Pvij?vGcdjejRUq_*tAf_f>oZmv{m0?-YLEW9kO) zf6Z+6*FK7yA2|~DJogUkuzeW!pf5PY{o9|Vj{nSwc;@5})C11O{jZ&4ZRz823QfRE zXMSSYywBslH@}J_)E-}jkGTBKS7I*t{QND4sQvGcfpd4p4DPSG<{&uW)|j#GmRPp+ zw%B(2lX2JcAH?%t{ZpL!>EGh5v%ia8!zV^=bUwA<X| zsH?Ir0sT+>M%HPHT~Z|q6PrrarQZs_EuU@u`_ew0&??c(LC;44I4kS8C9!qiXMb8J zuG5y_hvIdsp$Ym8`KABAQowx=dosfsyx#}?6g!myP4cOkaO3s~cmuSz`v zP>pCdv`?xhRA|BM*Dh`8 zKN^WGG>75jMo% zs6*(zm&HXon`{m@;5SN$X7tF)W2Zv#|@^RJ*I>YB%3$+g6c~Qe(lz34H zU+8t`_2M~eitlQL&ulvr4HEV{g!e5~+_8c0UU$b0 z346G26Su8PIj!|6YXI%!GVt3?IhXy(zmg`4V{ABONc3Z7;4|-jja~;{?j3qt!15n_ z`v;b%`%}^Y-1GF&cohur7BzwQ$=Od6-`_v;Wt@a7_!z$bGiHmP{`!YFN4@XNcR%4D ze$V3<;R1dipMVeE#aF!b=|!|R7vjZtK8a)G1gF0J7uJye5N`i)-0;MSxbw*qX?>^yhvp=(T%=@wb*|*}UQ}7Qz{(C(5#+ewmd}nMv^i1r$`)KUE z?eVzl#97v#do^}a58QO{q1brK!*T7SuYnuBio0KjuQ>aMxD7w^^m|`MzY!B6PuXHo zyJrV#%an0?7_T!)-fyx5cLv}gl3<|282BmQ5AW%nGz&U@0=LA_sFmg8%V zox|^o|4UN?DASl;=%(O)G(q+PmZG<*q*_7jzicCHv@^4IdB3v&?X!2@iJD61z2u{} z)cI%XpbMh&E==#0J(%{rI)|p3Js<4{F#ju4|8Gxhv{tU>NezBE@OsT|Z4;KX?&o=^ z#`&TR%07x%uEi zF{e03pIEd?d9I&&_kHNb7hk`dn&V#T zfP0e$Mcz^WGZ0>@2R^KWIEVAl6<=l!(1lz5kU5U}hlZWoW;A|>--!F4Jx;9tQ@r^8 z1vEWBu-@}eaogjEu>Ca=UZ^dEwf}{9_cZlz&zWkm#;dyEVV101I ztM7jvXTSereEEm}7N7j^ukq2vKc;or-Xb43M@)bDlW)-vev;~bFMLEz;Jq*61$f6p zubhmd=l>ATok9~xP4MU^zl&R6ekUG1d4?MPH*wdoFJjS_+hh9rgK^`tC&3A4PGPXZAU&rw|Ex)(2sG~3-3`|{5<-Nnh^ObmPGs7EyiwH zllb0F^C!Xk&59Od(8z#KD^Z6T4sTb7cp=tQ>yr4duFM4n6N(Z0teC|*HJhSf75Wds z`qsJRnn!F{7V53s7H~cEf&(bg2#rYr_`knb|2uXeR>1!iu1)VAd3a?oxwXI4&)Z=L zxE?HkU6-fcSFSPIHn;(~fAs+6!2R~_*#BRfex922TR9iJS{r7cHn1O%YprHeB-zf# zVm1tRpSK9}_|b3|q?g0qK-UG4`%@d-d3vV)*JI6`WJ9&kM3!x$9oJ60mG#WtQ=s@snq80@w@KB5Fzw|H&(wYmPQcWMS$MJN;ygORkAC1a7yq1Ui09!5t^c3;?hn}GskjzR&lAT# zM0@5qPlm(P3`FMjw9dV%xt5;ej@FTKtB($B@hs}97x#cR?19E*q1 z1Kjr1DYSh@s2x5Y2jTl4ed~L+FIkiR+t_-~3up?@#B=BdA0^kgi(KQ$*Uv@op<^RT z6ihj(^*^zYHa!8Zwkf=lJXEfz@VdmkmLLX3k>A$;EWh^{b#wdvo$mz>XapaRox2`z zIqccGUWt0}eayNk1NWycxFU~LMi*3>T0jMKfX)c2+l!u$q41Yu(ftjZ!CcAtX@ng4)#A^^u+*ak~6m9UiOMwJo^|oISpvBKduDuxEGdwlnqp_PoDNzpm&Kx`O41 zQ&Y&bnVZv~SLYbMYH_lEad*NDoZF)0$^Iq{r~`DF25$|P6(gh^8ed}GCEl>c*9f0v zt*saSdFs_0lWt}*Hq&n@b41C#FJZsE{^h^hFP_ZIsQM}Y?}!#4)&Atmv5h|X?JD@N zHq;>0FKG9pH?K;yKRH18zu9p7>UOTSC~*ce`$w7Jv}#NqnO=5UWm6NO(Z z%ynZfRH%GOd~z9PEHQ%!j49S~Kh-dHgxjzNp#E2V-w15l&m4ztWg0$cJo}-BMNRNz zu4VZ>{e+xjf8Nu3#q6ZT?7%VED_}jVuXPzPf$_iHqDicyTQ0UgbtZ0q>h*X9o4)z@ zh1iOg?w(`k;D#~(Exw^<9}z3*!SZI+WY6u{!=`Dnpk}N9I^Pb*!t*+xcS(b zc;@V%;;JW3N8fe##I)@X#ci*k`$PM8-#ZuLp5vd#!t0-iMK?YjcZ25_-10(<-*7Ny zY`ZI#?Yb*&CWp8SjsG*Bd`X`Fr+DR?e@7SecI4w*1d?hT1HoC=o4p>B{+d`d7GJNv|I*%_s1^1|I&XE{ExE?k_<0Rjx6W6g zWE84gmfCjD)DPDQoT>jcZ(DQ6fmACj-MsGqfd3Q!zY2ctmim4xcYu?pRD|&IGLnc4&pY*XcvQ-T-E};tLuNfOi_s`d@wF zw$TAK9R$zK|83FzIrpgWayj=<0QxQ9<%602jt}*K_6RWF$1#0u&s$kmUCf^j@K_r(I6d(_4e>$t8S1Bt6GKZktd(@d z<^k5%dV%A#fl=6>HLwo&C4E*m@-X>z`#9|HS0~(N!326;@y+FnM$grA6Ry)QsP}9( z9PM?(+R=3?H8e2KXfSwpG>X;~hEOw72cXTV0rFbV_NP$;^;WDt9PUp$^jeXJQ^!=B zI8wEW& z*Y+1<;GUx~VAl&V|E~99&^0edPaYe2?a`QW;CM{9>Ghb#>xT1x|J^Ueuxp-=aW}pm z^ADYfK|5cJLA-bT&9BAOTTjM#UOQ_4@fdym@fgPIdu}@tJ+>T)0laVUHLpa^tuI9P zEzd_k-q&sO;TUq=@fdLR(de=9spzo&>FBlLvFNq&$>^}|>FBWbsp!4!Mc#8H`tEp% z*FP5ncfA}Vu6`-z+RdMSopdpw5U{4TSV z(U+Ai8s_Q~IG6G~BQ9T@^eWbQ)Rxuh+c`$#YZGV0HQZv{pj7ME4~XBya?`~E#7UO^qWF}~ax4Y`Wt`_24+3I3@R_E!N6P`PzKIRD|)<-q(c z@B!fSY8|mp@V>Kwx$mGL>*`hVL+6BD;zkvMBVzIkaE`1fvHQ}TVz zx{zzPzs5dzYg*#klJvM0;F``~vS_O36|F}6hT|3|$^DD}%VPVb$ce0_^qR{&XJTv@ z?DGf<6S{u}6?c2DNV{V6EYE9f6 zw02R(wwBFEdLHdfKVY1niZ)jpRC}X68l$!SLFC}Z7yI$+4OREcx^8WoB)n3Hb0PLG z=*Bfvm}|&-K$#{Svs^2FLLAVV>(pANbq@7pYD)WoJ>5rd2NLJ46=XJg2Dmn@`&s|6 z2f*K|Ia)@0gF1lIJeT_K6#v2hCCall)pHkP;%#ron48~-sdu~`v+q3>Gwyyj-JgjM zn0fbmG4bHZ7=bMh#lFX4?{j!;;r*v#&OJPbKNxY~)fmI$v+jB~X7SvFTTaB7o8E}Y zyl?uUcVgO|Y<%{V+ux4Kx4#t=czgoy8;|Xd=XMH@&Em6W@O@+155H^pzE@)uv3m@D z#K$J!Q~aD6e8)6CbL`Ep$54F6kn4`di0faCv3%c{8{JOuoS%ClCf$~KkDtBd@pH_K z-VsHrl}3j;DDf)xXtkX%EOGUn@bwj2Hb^mF{9hKF9hDAlX1HxJ`lu$QR5_3)l;|A+DaviskNV)fx5;oyw_V)<$v;P%@Q z_u&HV`>E1lU?xAnPoy;h(En6y)|uMgF!rH2_xT_GzbdxgZQAmfzx9Tgz3s-By7rnF zx^P{LS-2@CuHG4QHXn#3J8nihc?bFTwrIneAAM)9LE|`z{%9co6zxDjm*nK7P zfa>sh_2FLhzs=wl$Yl zJ8-hOzcxIa+Jbe-Cg>A7qD?ZVQxjlb*Aq;yJq@5{km=2vPyAiR^>i8e_nMUZ8w32_ zF1+4aWxc`FbviM>2cKolzfeVaBi6RW{tLkY>I19;r2Ml*y_8Riy^J}Hxc*v<9|DIt zCe<=}FP?!vn2>sZ&F{PN9p)@8IKE~Rsgr=)%r~raTA#5WNIijiN@s_ftC{O`S~fk6 zK)dR-pJMrAAH_1Z<&S?HE7&r(r_=3{M?Ok6t=*5r&Su^9PON$2li2v&nb>&vY^(;m z&%s|zKKLfDdp8z8^kFP{e#mD^ox(9p>pO;?qVa$KQejF<~ zrgcZYjA5&%S#4_FJ<)BK%(&W0)$Q0HYi-J2%bLCDB}B(#KHGB!wFR(z1M(@)eVGPm2C$QS)L9CE zm#rff!{@4%?K*oxvN<`vZp3$SNG0pC+_ojwbt4vv^UZ(N2#Pc0|LVgJ%Kx{TJND=P zU*o@;cr~;Amd%2%K(E}VGrbb%6ww?Ex?*AS`)c!?htL`AL0hha?)VUG-CnUlms5`< zmo!HASVT$_O~n7dr$VyV`xGB zvlz3_cAflVYQnNMTQ)1Subr?`FUlURv;&&9^ZT>n~(Ja8=L-TPi_ zdj4$eIr@3*J@$EQe(r26xbIYo`O}E+i?LDP^Gjdi{bg>CWqiwWZkIid&*8D9-cMV` z2kD2hkNLXv+8p1s?6K3yPc3_t*Rn0eH!Xei!}Qq7$4_JDr{glddnNv9^^SzE#e57%`$Gxv`v$vzx^HUAQLIzx6{iVl7r5?wq&Z(*JFz{%`(Y7F(^^WhAkZ zIX&$M!V$ND18WKAJq)g&*&lFtt_k2ezUl(S>uDW8a6!cu*8e-DbpQ%8J3U{CvT5GA z>s{nxUP|slC76@K#+)YaJFm^zv}u+t>qJz+ca&?|lRSHVvVUje*o#_GP9MzLVjQ(% zj>(v&Ca^Iv#@QPU$1op{`^KCm_yqgTTZ1nX1ud^LdLFOuCE$@MY!&^?9$FcKwm_Fy!^CgR$&M z9H>@@yj)Jq+P^VS`&WM~N1%@|{;Pp)J%2nJi5jW?*O^!-CN@_#MmB_>Y{d1T?m&LX zTB5pv24lc19IINMPWUhJqnN1Mf~jzIXpS$N$BctHIlYnOSJ=LDQpEJyb+KA%Nr?T} zd?8}K=cF*V)Hs+D>eQF)+ zfXn1LoAG<-2lQ2Hv6>_e0Gg;A{v%J3+_C5FKgFgOK8ua`fc4n&mH2^mXl%8abvgcE z0kPOTe>Cxb5ixnkOP|G!CoaTIZ(N97#IPj~or+0d{;Amivd2D5zC-(4_2lWaUB<1O z|EK%d=VfWrR{whQb!*rzf5z<-Y?$q7K2ICx^bjm-q+?=KgD~rcQ*I?O12Fg z%f{!<#YXxAwjTRBCT+Qm+_QSZuJ(u+%kAqJuw)i73vR7zt2CFwnydAGHEA8df7<`( z^(&(3D0{+&rCRThmGe@Mo4Kzuo%H?ou{o#F8BF$QI}fflF)~l7za9Utdg**@!~PdB zryv(SI>oX1Qq=T|IVYZez5HnR)#?V zr>?^cE@uazBgAMjGj4;qME`?7*Rm;Cxgj}d1NvMSr&qU}?V52N)7%>SZ(1>{!X#;+88?O~?G#Sp==wPkR;ZQ?kd){w(*s9r>q7-tu=-EBm0K=gt?D%M)Y@0$s^lwtX=UB)`pz9(VU#bI4yR+1U;l2N?Gz1 z^F(VISuIoneE>W_@&V-kh0y_s53Fa%ai}G8o|v^w`voe)WjI?*&O8qvRE{nlD%n*|eD`>1GK`|h7&^NZ(`56};6!dA4G z>~?FI*2hRshWzn2fV3>(#dh$Y;vc;-Lu zuk}9o!pE}P<=E>lH(zrlxy1&)cN0Eo(-HRR`Ojkg^V)PKuBRCPi+H~Vta1gPyB>Sr zbmVMY^`hIkxauXh&tl7qpT&;j-w@aDB7Rm+z5mu~2N5Hz^*17RsOK~Ox0^6L@j93E z#+LXUnt;2U?K1R=#jLBxb-?v*-M8PO>1m#mGoPGq*&19slAJ<3E8n~5hMmcVoPis~ z^Zyn8zY4#373Y03KHy6H-0WKp$2?}5OuOOPn0d>Qm~qRCG41+iV&+YUW6mwl@!X5C z=b3W?&Gog;kT3hw?-RkUEh324zAslk<>O9 z!mrOvoK_p+saROez1OC*?bPa$i;*Y3n8?PMQ!yz+Va-}gIv zYvwig(f?OI&2XAZy{0GHEPp#~+M0DKVp5+ulag+vA-=L4=Uc6>wcBC%iG%^bt<$!x zOL?r?etAK)DCYX=K3c;Ms@s~6Hls#gdb;qzx&KD|_jo+d>6q|amp}Vita$QFEPedb zSoG-Wv@L$@)Aaw!C(p*Jr_b@4bFudDXR+>id}ETEN5Hc`=9Z3=VSd5a<-ShjIH2~?aUt90WOk*aNBMUD3I!8_WsoepVjHXy2RXem^dOv5%b4yxQx63 zoeS5qz53S8)%aPDk)KeDc`5mq8o{#KOUwFEmpY)@<<|4YN0mnPQvA37-}v8POurZg zhHDDGuF;_-J(KiTVQ<=&@AtmPB(9V1)aN;Ku+Bi%(&b##CD*CZlb$bpW_jjuTI=wA zDfZ(Bi<0{nrbnbu`3&|i2nUc4&1t^kg;UKWX#(&GnZBT^NjohrG9M_7{z*Ml(xu}k z?H^QkS-uUugyaeSZ_m0qR zVQ+tH^BUa%E?Dz4+yJp!e{eN6f8A?e#@<)INcMRp@%}PwaSa$<+t2tAeaWvjJ|{gU z&iEVKRlGjgD)xH~o1cFz+cn4e9=`J`{KA#b!Ap=E$mzM6D_rp``-N}N_OCw9e&uXe zqZ!l}=tp*8|Fic#NPl_hRB%3`c{)Q zb;tUo=^1myvS`IMru{bq3ts9q!0WospN#%vZ7g9P*n;bKq-HzF#z)v|=3FIb?PO<7$x+wo*9BcQI%KYM{Xnj~xsz=dA>JAD z)Lo~#A$G3~UL|$@&N!;r0R1oZe`^710-Z6chN}s&Utd%TT~5&&tffa@EzJ!+_tp(OH)^I6jtB1)=e^1HIo3kf{W-1zrR;^k{?U);B`4C? z-&ni#vC7`q7{v5q*j0i3>x z*Z$IvnB)4tw|}+qK5>Ve@$hHc=kxcyejyHkFK&Qm*!TKZv4`*T`Spj1gXH=de(|GN z1&?5!VeH?9tzY*VxP0V+P7#XALO^Jkgm}&Xs7H6RTtiKK3pyM)B5Wq zVv6_D3;9EcYhKb}{ z`iKd)y_Fsx$Me2sG&R-H={EEKcI9zD496OR1wQs8ArQmt^yz<03`F?qO`4V}Mq*(_iSsODq)<3Fqv*w*EUtVT7 z!%gI2%^Uis^a**v1!Dbt*oO9zpB@1@fHL@>s(iLNg80??!KL_<(hXTlPA-jjYVW4| zX+2iFQ54%Lir*;4V}+R~V$Y^}B4_RSd$~498~T5f{vZ4Axf=a1{=FeSy+6Nqr^%zR zA7*iL{Q30vWj@aZ#TXB*S`8Cxy4s;^GW6do%|ZE@vHQh@qGjKznYkD zoxr+*7+@_q!4|N=HRdI}_7>iEGu*^}d_e{~e4gyz_+Pp~HL%c_RR4E=Tod>l`~KDc zc&+zGj~+$I0g&uVY_%#CmrVydOoD7DS;*uHi@*jMeyoUcckv>!ZF%g}G_`q80Dsr|A z1~`}ebM`mW{#(w1|AR-e1|^P^1Mu3@=Jb)Jse7h5*4SH`U&%G+bK(SNd5nbznM!|z zvofqx)r9{mehF(ZQSZuAgmtj;WAk8uT)D{!{KFTR>*vawC*uQ%iSqqk!`go>`f!{D zVsDH+2aVvik}jF+y%*J1zKuIa&u#?>z-)y^7?Xh)+XfljobPRZ`Jh`NgSW` zKH@zwU)wH-ZQBQ_FO=JG_JOrP`%m+N0rUq67vKxTMQQ|6?Gv9?j(nm5cJEwqxkb4E zF+h1ZC^d_v>gMna@GXVyFUCJRU(h_kwMW!IxQ>JUkHsn$$NvAEa_!%;|LnD~6&u|~ zEY%03+?w0uJ9u1-;HHoG`SriD`@i>i`flE*KS}ma?6rUmfv{TEGV*1`_v%Q91Y($G{NR0HmO7V9a#&ze;g{J;E53u>_T2-&M3{5kBtuXzM zK9}^r_=1w)1Y>&%e1~@L+JU}454YkW|2H>CIRidIK2`r>oxs^a+O|E`CD@0e_#5j9 zo@4VB_uILm<|x(&?ANsB?R6^t&r>{a++h62_OieK-?LF4&)T*&pWXBc+2^v)|JG;x zt>?1u+kyR?zhC$Im(&-qe{BD@x4%t(-~c{B|F9AJmupBGBWe-W0JVSj<2r0zpK<5A z7vm1zCw9I|PT|Ixdnd8%p1^dX%4LZV`j3=I@ z_<}9SpG=@WXiRiwV|z6Ja$q&N4%M7k1DH!KNOcCO9$+=V83=S$Ijhuh21gWDcEx!v_j+IsGO1^c zO_*We&luup48sphAb*$#SMY25&;BmjV_USb&WN)I*qWF=ENe^Nruk9Uka^rqJXs5T zFPGAg8gmt{HRpf2X)kKqwUbKZtIkEK(WQ050>=GZZr}mqo_Rs8{Nw^)1UZ4y^)5+$ z8O{&!vs~Xs{#ve4Y;C?P$8Vj>^=;H9INK(}JupX)`)b|Xe|!Gb{dinHuEr@l|F;eK zj=mwg-dB1*`GB=^*A%lauM+VyL_R}~KjryZY+sn;;l6fn z-@ox*Jdh6zP?h}LIlXd)<~-WHJc;>%{pEQ$FJdOKfw%UXTQ||ih&K|4O03W5336%) zJZ~Q0dSi7tKgn;ydpd(q{geK&B{iPnl}f~c_x_mS|8o3)_B!}`x7up5*PPq`8Nc!O zJ}dipHvWtMuLl2{@85LtLbCnawg0!iN%{OP?H}H1mG-X|kWKAk*8a8igKvEscQX_0 z?o(iZocCRWPq{|>-}?YLVkP4LVDSIyv_8kMH4D>hIyJoZ|8~Wmou`uYllX>u)Olus zWv%Pf1Ov1scTi{IT8!4ITXEgh1fN#z+zOrWjF>=A$Yre(pqa##Qy*P z;Qu^s&!Mr`7;FwBE>|->AjSMwqBk+Wcd~2k|K;eu9sB>~rXR@h1-#|D5EwEszP1#*V!GpxI~4_W`~e)-phc&J9qI*~CkYg0)hgFn+w)WaHE z^#}51uFa`tzi=`p+0EMULGxX0c(4#t6Lb%OP$|qJ`eFuE+9`q zcz^Qc(%|Zz&L#(4Al2560(tEA7gMw+KMYuNF;*hfrYe^7qr%a|u5UO*1Pyn)Bm z4a-erbp(Zs{k%>;WWJVN3sB9vS}oU2ZETH%<9Gg1-V*uZ`cr?*#BYB4tUdnE-2U&d z`|S7p(*Ac-gWC5R_&;m^V0rET`ZvV!pXb>BY2tsz{^bGG{A?qh`o4qsi+fKoHxM6i z2k*`10DIo}F4=#9DkW22wCkwY_csFVpWJ>`Vv;eX75V(8`))<+Jvr&BT}NTeI{1ES z!L7f_d9D%#{-*tB>wju37ok_4 z3{Ph-MStRW->Y9qcALcl$+qzceRJ@?{=xe`pUndXfF0xv2JL?};eELR?Y{r+m+65z zihntg`X|I2<{k3??t}bm_P5afJ1(1+V*@#B0OALdJ%IYf{0}JI}KfudzlZKc;P4-_OtdBy|9VsfXt;Sv=uiW52dh5%I#-)b!P|Kt@E0CS zs@-vYdAzB%fgOv{Tfl3ypTZj1XvpO-;kLIZ11^pb1X=2lcj@58~8_-@D`{iqY9sfHy|Cbo3y=WIH9%4uSuU&}?+M|Ef zj$B*U^?#fJehJrbBXuy?zI`ukI1l!w$OWh&C|0j}!mLG!gYx3?TJmE>=!elJ%#riM zkr~6}&aA&zZrLc+{jAHo-j=^r8?>y(es#lj;3QH#-AKls7L zxaYm^5_Zs^Tzld>aQxlW?5iX_ggrd2XDy%P^{R$K|Lb}wS01`CtsUJS9a+cOA)2>1k*O9kKH>CslWao9Lv8>*?Wx}`Cxy8+eh=~agkpGI6jbqwWO=bkC z!IkTG4L;}Cw;_*r{Sh&jIfb+TQam$$v!z(aweG&_r?R<=kEdKE#}>?gv-5vDqW|&O z+vw*YHo-)p_Y*XsK`4$qDLOkCst_Wu+rS0rQq{O-Su0spJ^`~UUze`)_{e!%fJ z!Q*THDgQtDEw&B*r{0k4Kkd;DWE>x;MXz znam6++oWd7|JCPNBT^q}Om|%?=lVLw+qtUF@Uq|2bKYqdJtSy^oG0NL4h@L+C5dIu z{YrD?c)vYut8d%SJe*O?;Y4S~@97%0=9y8*`JaCs|Fh>!A7Cwh6@G2rJ@3Sr{YPWq zju&DG^B2Zp!}c#Pr`B<$m>rGeRcfr%Idi)O-NQEOE^eFo-*d4Xd~aXmBxW!|hNuLwGgAv7f5p}lAD)vBqsexSujzE18{6St+^=8SzBX-amk(@0F5=8Tv4#2{_5Ypm z0lqJbc|11P4R(gUT6(dD^peS&eRP^IF@{rx)rYH>9yXKeiyj`@uoePYABs;o$A?~V>Mvv zNyHG&gxGZ7!L;6weZsBa$&8b(Et9u&VRY8NZU5HdSHfj1pucho7=AD_So&;zF6Hgh z(Eyqsc#QkdG~K{)-pFQ+M4dxc?~px5`T%jl40<+JkSFcN&bQ$&oY^oFd?9C|zxi9g zv-aO*#mscgB<|c8nrz`0K7jwTc4Ev__n-}^%jpVU>a}Egnlod+kaKtCNorG1*Dl)7 zOK6Y3Jeqc|Hm+E8=9HR0!wGmRM`m7KfcaR?1+ov<*(}!F>hgK^vgu3IX4~g)FM_c? z<@MOP`|IZUPaFk!B>R}_`?&Age?{$|9@wtSW+Xf#PWE&3`|Z)k_<3rD#Q)+$YZ>Yd z)p{9!#eR*52W{YhJK>kq*4Qs7_Gw3tlKFcneFj)jtX~lgqZ%l+0@m@JHPi~eQH&|i zRGH&3@0Y)`wyCDqV-{DrcA9H1I2Y9UW@@opfV=ELP^Xc41nQ#4pgv)(Qa-^oQRPNF zCVivFt?%~Q?m&DiP@!nt1pc?C|Bn*?)fQg+T1LlX-fs=iI^KRB+x2t)e>&Cvmk<-> z&ezkcxP#}k|2wnx{~`9D@PAJH2mc%Y)&IHvr0YaESAF8nE7KaUuFIl!bPW0**YuUs zwzgD<-`M#La@f_VpUOQ~g8Oqel|I}4>b9I;=Poa#52aMgy3EHxJHR#RdA7GS)BpRo z?ceim&sBy41jA$ha}T{8|r{yz}-FU4S6SHw&93bv* ziEs0o^7)QjNAmp6ua(<(PJ%OQ^sDvZ0?Z4n3mWHoV;`=+T$Z?|oy%3(6DSW>gxpvT zK#fq++ECAyCzNYG~|c3mIiymp`PKlio&?0tQJ z_vQIoqH(U;wi)(cBs#HfuC^gQPQAW4zB_#uvBJ6L<HP3ax?mJ<> z&WIUEZP+!W+&|YlHiuVxXS}!+9Xz z&k+~s1LRM;@q0L1$X;x9Y<0*l)M2}hSkel!kLos!P4)SFd77-mT-ndl% z|9kOY8&m`6oRjJ3_2-K9nN>KSJYXpJzuU%V(yX;KQVzdfU)ES^SLkP`1S9u{dc=;PKtfnw|G&z@jBA3 z%m>W*v-z?y(^%-NPy2w{gU!3*6B=0;AqF{juQPt5|5Db$qt{mrulUv;xa{0J`73i{ z^>O9|`h@aLnG;6bG@q@;_1|OeR6^^K;Zb8TYOECwuPI0nU;6d>of{Z@f3x z5d*kpp?EyaEAC8Ps4p|eSVyF0XEajOKGZ_U9qPx#F&*$7Zfcv zYw>+@i28%NU=e52_+9oqsf!c~Y5&^2dIWXAo_ptidFlWzS$ARmZZwY^*Mxu0!x=Fv+5MMfqT9bMF zDz+szT^-Zm2^ZhEJ6zMxwN+d%%sKSxt^IwRKUW1^X+`w%<=}|Sg+0IN8YEVx`2Y9# ze~wokej%EC=dX=`kq&DZMFXntpAm? zJzW2;MeDJ+rP`R+5cc8!UQ_1C_LwF6=h~OcYGFP_er#`S7h+o<>|^L<^P@9!d7LLC zKdxPyr&{9|6DQrA+8Hqc`LaB_nBO{qHTKrz4V~yMsz@F#ZkA^>Cs)_*wXUYs{YtTo z^Y49aKI^-*fvkVfFSq3R>g`)3`_J_MXEaXT=n2jG3~$?j73>d{i*ujU1FJNtPAIAO4a01Q)be%-!boS!bbrmk@hy9ah z$PdUx%N<%DaNe@(A(>y6YFtpdJN(=&qu;; z`UAO6{x4CZ40@Zday0yZc^&-nn)uJSum6#UPy=|4IRNp>dfxS1*ZbiE_Z&xS%xl(j zP1|pro%M4$b|QYx#(%ZH_rUwPPU!9LW_*Wu!usFzt+#RQFw0`|rWl0&r^5nfUN4{~ zG6jr3q$O)y)q}%o#JaT1fn3ZwOw;;A(h)K#>b4^ zXJ%$ud$Si_{I5T3LyQ;iH$x}kI)TpS8g$t_;`bzaCI_eZXWm~Loq84WVS9VE3v1dw zuKgDw{@e2-|8L*Fc%d3L;~Ijl%b@++XDB9?Td;PfHal@S#5}KWaliYl&3o-94ij6@ zABbtp|LtWk|L?xinSPn$&FTYO2TVjS_ z{a3LSUj0AA#((QOlKq44cf1S-$oz3JfOUH{J=eZ^A@v$=1uJi04v2U;&G*6&th4u* zYhT{boXwo(1Gm)dkQ4to#_aKS0T=r|Z6y=`GiwJ`CZ89#t6#GB zMm@cH2iHaP7+k}rEcL)-``DzpjW9Ryc-<=ug3_<7fIG0boNYVlD z+Tzp`OHnUqNk2um`BTz7S~=8)A^|1v$gp-?0ZMhd1Og@x&hD|HO?4V$}A#V;(WKe3P{iCFVq~$}1yR&5e<# z`E`-E#%x1;FgZ$+sM z??u^d??;7QA4ZkEA4m0lpG55&&P2Ui&qm`rK8u$3oR3aV{S@W<431mh`{^(3AN#fc z*F3!Uwilwo+`FUE{Ck+mXgaP{ES`rxO{*yWT+|07ZM@hQ4&1&&>wd1))N&+i9q>Bqi>|TI zmiQ%KW9)P0h1{HWAZObNzmUcH;@zzNE$a`w^_ax`@`>jEuK%NrcwE`%v-Yn~QA2O9 zy>Z!I=PDelyr%hwbG`K-kM z=0u(g?LBSW7sGk{9hXdryyXjnw=ev|*njFR#QxK~4tPLgo4q^s@NeUBb*dYwf2)@h zw>m#a?0*%!xcEO)H`MN_8@xpi0lC9<;0Hfv&l?wG!uowNdgr|{V&^N&hu=f(cX>qF zdCY)ZiVs*9x$EzUJT0z^JZ%m{p7u9J{_b}~fx(YNk*Uu|@ujatiPa~g)VjB$B(`5d zKd_v~*1Q=duXrm;Z+th(Z8;UyuK6%(?fWOtI3GqP9D zPxEa4yzo1vzDxPX}c}hH}_jy@BaS0k*`?)cE&-CocN!e|KstR_xL{T zC5wCHbhLkCtN32shy3~_y*s2nY4d)2c;r6%;`@3no}T8!*yrRt5MQ6xk0f7^ud@#7 z%>I!ZS7z`(c*XSuoYkM~A8x>Us=d4NdairY86RNI;F>hm$Un@3+A^0>-cY^uCHNNe zDEUP>2J?S4*dB-2r`fbjZPWe+kKdlB5|@-u_Wuuq|A~8Y0BObmIf*m8G8?%+@oY18 zuDx5k_L|+~yb)s;w&Z(^^J@KWc;o9dH{<~IfRsDnL)8C|UAHI3?!KS3VeV&!HnXlv z&&2;Ph^V|ca@XA)d0Ov_{5|iC0s|h1f}@^{f)k&MBGX@pqH|w~VvCMP(fLQC=z?QW znE#7#TYTB8QDXV)QGVUYsJZ)tXmrErXmQ)QXnoiDXnWuJ=|u?|5N^t{>NEB zKCbQSCp>0tKh-*TT#a!>VtC^Jz~)uEGDmPo_oyWY2gY^|aG&MW8p34w_G1c&fj#T zYresm@VGpm=f~Mh;v;dB=TKdu@n3A#j?eVBa}x{r8>Zt&2a&s6A>!sgNdC{YC%?B9 zJ2%#g0qh6N&KOA=C9dnuZ060{y|_Qk4nq5H-XI1rUy$!lH9um%x&JQg|C$ru#^}|% zV)TxCW7h2_qE;tjf4%|K<_9yMXDIV`r$+8-OCwLiEs?j`uE^VJZ{+QKYZMsxU=$wn zWE7eBY!sRGQWTkk?ayPqp36^0nJeFl%G*yx^{YRMTGxIYb@zGuQPk(Q$<3ce`@7CX z&xb#c0neai0?W(yX=C21_npC73SBoHjs~+2MU9cy#U=OvalUJ&$no9%EuJqy`5uPta({_m~0-}q_|y|GsP zqcu6NcWvGERJH$}OJ^jUuAZvXRP=h-dcB_L|KP*gjAAx$zi#OoE=Hc~jIT6b=n^!n z)cfsSv!BvySgmkfdgRn)_gO+-v5ekCxIgi~b$5HXU6b8;d)i`CY(&1&eNERn`>EX< z2OEKhecWSei@v9NivLCF(ah)teJ<-Gv=@7dJ;ui9XvO=+em8wn4PtZ)w4=S~9dykQ z=Nviv+jwlhU={dEIRSNn>ICH~?Sbe_F67K``BCf1){5P?zOF0D`_0*{XX@jO`)S4* zc}gAXi0aVWfv@EK-g74XZ{mTPd2a`V(5A4SF z{|{$vtg*Wvi~(2NkNvM;-b6=yKqvV5z7eIyMeZt#BKM{1!2t&%U!QxU!0^YT;Mgal z==A5JBv`-9m2XG+E$>IUtH}G;zZDg?lKb!YAgb>AAnF|WBpQMF+a3BWdOiGQ41Dsd z81mFtF$&us@ig{N-QN8*_KW?UVLB2Hz73eZKK5UG;!RNpT;68&W2tY)byd_ZsAag0 zV;Mdu-Zzar zK@CB>RgXriTKYaZ3^*#VA_J_U}$-e`T7exUB4uJ9x?;3v@uPlFEt4|FGQs6V=I!tM42 zv}QBsv8E@+v5#up=2gs^pOFP!DV>&S(F%_be9jJh-V# zEl{}xx^Zmnl`nqI|FU`Df5mN92aqs;J|JiFf1k_Rys^qHYfnC>e@K`iARbUN znC61M{#^`Nx+%t8^DunW{;1Jr2D27AMC9*E{2vs#%1nw}RTsbmtR@%O6uF!1jXWI> z0udgHg5%)=r@t5lXTk-}h6h~oYLvd>WK`JlUR2$2Dr)WhDC!;fIGVuwwZZspto;cb2Dm-@B+~ zsAF0~ouI?2$D-!weNkiV^-*`mozZyVgVAioW8B_Pe(*@lyyGPOQs2P&{|@crw{bah z{>%%s|2}+|eSogF*jk@6=k91Q=bq@obLIf}$w%uMK#;c>QGYaPk3M zSFSHptDo9fbPvQT*Ozb2>s)V2ZJc<(bv@cm!0x9~;{wCW`PJc?&dw97)C%lQjZZx5 zOhIScsAW&}YwC!N;nS>piJ$GYc7CPnY&dJdy1D+xUN<=a>k!T&$=G~OoX1yXv3%NZ z{!jLReQTfU|6B2xwE^|<_5o=B$=Bh_jL-IoxIg0R!~wRbpZEZ0o-_upr?t?)?CN)& zzbU4%KU{s1brEZ$_D9>dVC^pTE|C*-=iH=o%lC-?`?J}zW1m^0(fu<$Kj0_xD`$T? zTX_)rv$0!QvjTsk?pmF%+Ex8g*_PBo!~*P}bIR2&Wpy0-Y<-$O&hw!DuTa&JscyWD zJo~@G-hcg_SvwZ%|9bPeEJjWD{huxS89%>Qd;jH@^O{}Q|KP1;p=s~{3ywyyWv@l? zRVSi^_jl(|b4?g2P)Ze6U0p{5OWTSV2t_K425Gk;VS^zkf0Lz1i5c>#g>ozAzfBF_U~_GI&6pLBn}>M-6fT zIY+ex&I9!P`sez8a_4`+hZ9G=ZjAdrZj5h+kMP=ajSy!bn!mdKWIKF=YiV^uuRaWW z?Fs)kU?KUym?5mIMK7(KJ=dt*xVkoN#rl|hm$6^1o$DysJK*d9*AuelZ@-Ld+3N$; zVY)uH>#>;omuXQi^~SnS+P~a|d4T(Cyw7T1v^OzuivQpa>;K*8ckp#77x#JWM9!=& z-=zk?IO;r;G|L~~qv?LGk@IU*smR^NP*mhfRej{RV6XJdwYVxj)+#fr1mPdc$^oScz zBn%+W=?r9R84JM#&F3GAD*ZM`)q&fh_JkV~C(vo#Gs&m99+TP!eZ?AlhwGmXWe(tQ zwrSKE)EPQE-1U;x0cii#M(&Sx+_zsqeC1y|t_|a#T(PlGd+LB*CR_9Kxz_07oX6qp zYw>UkVzaZkI;UgT^z$NXMH@jzH_G}+;9J{v$SebpSF)ujz8&Exo(|pEyk{h zrcZ54tpS}=F5L}W(S81uwC1og2{WI~x@{X*rW#mH^e-jxAFe+t2cZ3G^KxC;n6CyV z>0t0-KHiG@x7s4(zg)O+GW#B%xBo{!m+~CWLv4JKc3Y}J&7>Pvrza1nU$A$~TA+1) zwYt{h+-LKCdw9g=Vi(sEc3!%6+GGUUd~Dyjh4O#u4y^&G0d(zS@xHx1ebFX&TQDW{ zImrcxHC%_q_03zrb%+!68RjQq4{Lz>SAD1bKl-}l&$zD-@V87@0RFQ`&9bqD>+2uM z{i`GH{e=Ii16)cSu;EsG0D6E<@P7mDk3yrKAP0CR3QjmoP2g}8nEpbl0hCzr zdX$6vuX5G9ap~R+2e+_DhI8oc}utJkXrHfxYyuMb{Y2Pyw5<@6!63wxX8D85j24yT-WdCz}h~S0|^Coxw5yeZd4~I1XGn z4_|>kpZs6@cMUvy0kXC$hvB|vd{&14_kTG*HHOCj_T)I?1M?d>GN1RjJ=Rn|1XH*# zY3@GtOL0Kz`6VaNAJxGATQN4(s8SUvUXRN<1sf<@8g^pb0xVu^@HmFU31Ww zEKffSZF%A|@GZ_8sZQUJHBNaBH3Rk?iTOKnOyVooXqEG*NncvZ5%5jc{>-hM%W6F| z>$5!{9+$_YPnZ8JhW_Ut(f*SS=h*t+ypL_m4T$r#bGa)w{eZ9krQK)WpRxZdW6UnD z_5DYpX4@(7fBgRWT12jb@PH)-N3QbJ0BWp=+zqxxo@Up8|F4gH)&qw<5``u`8--`T z97Pr#Lj&}BlwSXCRM`H0)ZG6`)IWGGnjbnJ9UuHM;r{{feWQ+Cj48zZ*~h+*S+AqP zBZhCn*Dfaa7)p)5_m;!hEm|GyPMmIBb`1~L>zIPwPQQy;9oVT_Cvyfdjs5;Jh~q7n zJs4G~qolQ)4bIs(-Tqg-%qISX>s=8x!!kyMW zo^p@z%nMr2{w4cI8jy|=zD`&w_UXUOS`>$R`6?v`<#e!ZsHSZ}zyO#N?G3?w&Em*+a?X^j-}8)qV@ zS*X^THNn8~+P3+OeLs!i=>5*FoHy$Tt}Un^OY48>7dbE151U~3u9xom#?Dl%O&(FR zPy4h6iR%Jd%T)K5dX)HlF_C&Gd!Vw%lzcho!E?|8441zO_@8UxA1(f8ZT8o<#`i1- zs6E&#;H}rQIC*nUec;#c^MCDs;KD0o=7Gmq2YFAFt=*rw^Nr#E+7SP{GNX?gV1*fQ z0Lvp+U1|W0w@2P~;O5w_G@py zS|xeE?bJBDwdc`e)ZbYLI6!Ul3S#)g8(xhm^bBpnKd2SH{he=;_Q86o=SfZQ<=A-g zANWRjP-~;kRr9sZN!rcl+GC_H*#0Bu0{Pc%)$C*oUi-$)HehA#UVJQfmhd$((VR2& zsiJXpJ?{3@r|gAR(>4U`Z@<*g%NHfwt42QYV7#a6Z06bU+BCZ+**@`<{JBc!=AjMS z)9=h$?Y~O*R>`LQ-2Q9kM;CYpZBCr;x`acqw{CMLrFvI6bb!_SpuxkY(wr;ue~&@E zi~L?z4=A@O|6Q$JbK-xIl>d8N+KHRT=W*)~^n*>oG{#=-OAV7a+x)-2nqx4y{rE%I zEn{1fd_gN>wfZ1yhT5z(Ki5d|Tv@Xh<2c8x$1?h?J-=*z?-1VKoSwdFo>yKYmr$%W zYXVc(^E=I(Es-{1G~3o-QBZ)4m`%o`;BFL~{USp4Qsu^+oMA0M)ZJ{~mvJ2@8Xd+PHZ`}l`= z0-df}-N#R}@xPBfLf@V}{?0w|C$NRzC86${(C1Xit@Y&i_j>f*7y;xEVvW ziT;}Es0FfbU(HV9Ik0~i>Bv7EK)4{|WJ5 zOt0?8e%bYCfVJ~Xji2?$uz!02Hj=;omi-S}yfG&2dmR1g>L^gMC)gj{pT8sa--r7D zh{#oOCboY?!v6WY-Wml5-WP@8{tHifnz;Xb6rJ;OlvsK^N?-nFRM_+`b^rIH_Wsk+ z;N~;Y{PuIv_Rwe1_5SlQ2p=%|@YgY&*gxkea|e(8h$ioB45Aj-9qxT9eRygXomb*~ z6K(u{<`q6npT0Kw#3w(*Gt}^3K*RSk8eZ?)*JK}ref$UiAL`yaxXSZf*MBF;#P+x_ z*nzQ4v4>{b&^r=nKmySO>JkV65{M>5uL1<3h~9h06dMCJ*kFvijg7G#CoXAD+lhA^ zrzg9dGv~~l-^}m2-o+xsarQZX?lAMsl9pEa*5Z5G{oK#};5VMccAfwC@$!V#{ZJd= zBECTzfA&Xc1Hc{7kNCT<@zT!|x0mrVY6$Fw8)fZ~zvp_?85I}sUw^bQjrZ2R+KM(I zb{1_P+|T-6U3{-OIkECz-TCeQZ}(vjnKvcwP%R?=7rRm$RnCl$bD!Es?4{e-95~pC zJ%V!U+)-zbO`p(W7+P9I!_f9)c8+*14k!mtp1hh&ne*Wlat=Mn1KiOhw%)mLSnNeO zLuU`obM~6ohNIo%zr6O%fg>iy=V}?}f9u6s*xElG-jlWw`9s)cH*DW?au2E+gwEy1 z*?er#db<_agd7Fy8G93+iyC0+aoGFwb9*=&?LM&wI<$zr`gVmwLk>Pr%+K#P>J3r< z7p+~)_g+SBlNED({h50xts~S9dAJ+#9pBRkdyl>ZTfZNFP#?~(yh(LKoTIjnVm~ms z>)6jPUn?Fr^Ec<88+3RyEP3+nxCi$3Soz=a=V<@fw_H_iT`rJ%|IYl#m$#mkQzs|z ztIj{-|MTkN4($HpH-&FCF9Q3={_n}4|BwAQruKiVCh~v2*?mX&M%vMEN7mT{54Zxn z&)7fb2AqFt{~CJ#*ne|)KkecAcR%`*kaFthVZfPRgdrC`3&Sq`DinkJY5Pmw|4W#A z?dM@LKFhxTFtEPq)cDr);urFjoON<%sj*wmvhmybrOQA5V|e?se~X899&3B*oLcJm zmCOKIKWxPhx);eAXSqVJ;xpv_ULZHnFFZ-UpslMDpf*ZEOP#%Fyr+KC9ir+EI1lW8 zQU5vrqy1|;u~){=+K$>;v3E|Kv<5YomA4}X-e)2h7X5xXFz!IiCNJ0it#Q?;X-U3p ztR7#tGz{b#x4w6Fwhi{Jy)OJe1Ib~!)p{fINY*pr$h z^{_AXwIa^WXBV?*A`aj=b6BfeAINKJncf$!KePX09Qa86hPjfTLtk37dSMt2-_LnP zYZLn^CF_?({(;z@^Nezd9?f8W2w!6^kjw+@@!5ZH@4WlL!2JM;y#fs*rs~d` zsKHLIWDnCmgL$2wU(WMAEguYvPQJnJXE?xL%9sDU{l0;EII%DDXVKQRe>H-Safquq z1Lq!HAM;f?fcro5mhK4Sc3cT#HeCweYLQR>5B&e`^zgNMS;YS_;cHE2hOf0=8NS|u zdBBu?^Z-wUJ4T%kcjZ14?y?6k>6LIV+~51F-wzMfeG;1Q_+e;!_@|*8y}#bzfAap* zE>HtJ59jB#--d~A{x;10;D3f5RkNw5R(6^X3_;Yd>a(oY-V=ZOQ zUq(ODU4rs}{FgE(ft5K6o6H}zIcMU{y(1rS|V}@zyQ2%?Q3-*p0+0ku)pQs>;;(jyJOM5 zcnbbTK0wcM@ILZzwV8cA_mRb!B%q9q ziJg;MPi$5DTD$nNo<-80w%zz56l}W~N;X~&3oicz{J(zK3 zr}vj~Fnl8;Vf%N={i%2@+&f+D|3+xQtY0H$ep~MSN#y->ruOf17VMu{pF!|`<^PP5 z_xs9kW8Z(_$NxKYn=zN&q`!&tw&Ra|C(hh^Ugk8(^Go`G+i#-}z`s5Dy@a-x`9dxH z0kM5|A85PILyHeO=jiw0ynwa8`x$S4t-t%3=cxUo?qC@^!E(SQ+zsZxboT#Q1FL-* zuN87;aU*RfYWl&q5x0-mGqrhtdVhnkb7$L9iDx6h>E*(U*QfF~=Yj_l`_27R;J@~Q z@2cjdy0-Sw7A#O zZzQ+YxgqUSY|I$#>qmb;PTTH&vl`mP}3)spUq|LS!nCxZ^qb& zt@E1hif9c+C#DxQ$iXPA0h;l??kw?E-QS1N!FX(b zC1%zR%P>@nqY+XqeOd$YbOCVy~;UFo`I_|)0#S}0}@W&fxH8fPln zfE#N6_zgd&yHeD-@5_6c2grH2vqgij_~e`aB=O(b-(N)Av4_2Ze)kz>T&;08kqgYA zSFVQM3iLpdeZZt`dAl9^&)af7RP1~{jNWiDH0}WB_b&Q>chdj6Z!rD;am4>BYJe5t zo4vM&y9OT#cW0dj1AzaR0|%hsLbzu%zF^$daNpE7!UOZKhlgsvgLKIE!ecwW5C8W^ zq5JWlf&u(X81(cnLmvE}v9Ej)%C7%sXgO{YI14_39J>tczZ$!Z{Yq*8`x&>NXY%Ky zy*dZsT!Z<7xs5$M`TE9w{b1zn@;7~jc&MCb{Xz2i$=6HXdcWU~Scw`cm3(ix%m<~f zx)SFRwEr~XV1oO@ZohHV*Tkc~_yBW$?WrEuvT;ZaD(CSBVcY$=HiuH{=Ps^_95r`- z%XPOW-WUFVA=l_gI4j0h`vY>{&F9@4DtA}gcRyuQe2ej4&aE1I^5X3!%JXZ>`-`oO z;&s$v%d4Kr`^|`Y<7#8)ub78FKzmor4NO3rbWXNqCOjO@*BEUN-=3m*jC`GB|F0K) zGP%Fj<8m17H>&NX=7<_wNiAOI?Anr-tHY%pL3ix37j|VYKz*)m{N4pD@-ce%<_c<= z#~B?kPJ8k#h~4@)`}+1WjsFpkqdu3{ctk427)Sl4B8UG*}ipZO?q>a`DR>*V#GyxsQBuhG-I9H#Gmnc30(p=}2I-*0wE z9Cy+Oyo*|(K0Uz)+1J&iDtxU4x*#3ag|GM86XyW$qz!|kweaAg8{v`F%>2^# z>&&cQ%88$aq2PXbm*M_0?=ykieXu$eID%d0Rwba-+V<4 zj}`Rkzens_ja~PB-`A=M`sod0jjsNLIG(!@ zM{r%K?^%TXm9D7{#L>hN zw14AcrxN4;n2<@2%owLuURP|ZJG{9}^5!wC7lnKW zko(%5n>UuLNo3E?8og;+x6qlL0gcfi(f-x{wEmYXpluZL+9R;V6!8V(sysgP6!(6J zSE&2blJCU*kLr5MVe;=S@L}z-ae2SaEy@>2Y8JaM#Cb+>4zW3BhMkcd5IK3|9^e(8 zuXBHLjnq`l#7}DTQ+BTlRr|MundnQG@LlL9`r=#r^10+(jKUAPd#ZTt5_Sa4jGDsE z4yjw{t^$3wT;+<5E5r1ibus?i|Et%w@jsRQ%TF=(i&?q1bx|05#*|LfHL-{`eF+%f1xxHIo!xToa# zaPRo5aDb`%E8h(D7raaU|DDi?xxZ$+(D^v<)6o9VPeT{te(#ga06g)F*aIvA`zwd@ zC;nG?c#Ok4_luA&!=K@Ej!lg z!j#RcLvhV~G=GXi#aB6x!j^+?pJqz)WXU*gEtDy!8uxa$YK^^1>Wbpkoj-qD`Tr_ zV?K<=aA;IN#zOOd>u`_B+t)Sm*HEQ=%rYntaYG=;!kI{>+2yN64`<=N|-T()oY$tRCPQ#cLObiQCrj zeO1SL%KX1A7-wVZhzEPaMefONW$Un1-j~<*{d|mdh1lXCFcR}Ou~B(~Gk0$YH7EDS ze6A<&dvEK9vHyRL{NHQaJs)1j=B)0)xdJxkoU8UfnRuoymNuf@Bx7IlcH8w|VgJ`c z>DJ5Sp~u+$o`e0v|F}DY-v3zae+t;2vw!gayPyHkcQ;xfr^4Mu=>K5<_2K+9T!!th zqwmMOfBPdp4L!m8QqLzeJ~E#9Wf%_bpMUk&Vf^dA4YT0<)DZvIeDvqA_>=z?4uaju z!E=Y#czC|KyV%uDFJQ!$*V*;=R@D8Pgnv-S%lKXmzOT0NQnZc}@&1Qsd;SpY(AfXO zFz2GTKZ<`_j8E`$>kITFKHlA6?hPqL_bYb?`+?WJ9MWno!yUW;_xOD1z37>cUi(7G z!xuRlpkLKr_|NzsF=*nD`MEpf+vlONU0xV_eRs z=YFV*+!G=9M_mMYjg92=^=9q~Utk_!oKE6?`W|&gM^el5BLDAD$gK2?@ex1iPnVq{}a#Tr_F-LKIMrI!#eC=tovo`UoA{~>e|0?^1rhG;`JB9qAT?4i`Is(-7|>Y zoTK3W6~>(Z>upzsZ*dt$dlolBhH6A@}3KKItyHRE!3L_ z4*)%YCL2BpEw+Cj-v3WRw-Y~)nm;-4f5*M~`!F63Pz5=_SY`m_|JU&u#3!{ieb_j3 zdGg5vvbMZ|1|XU~_yc``vw_a*jl)lj!+ysedKdrjPK?oG*b7p^@7nb^ID2E!@EgP5 z-1Aq+Ysuvsw(-?C^E&{0Phmc=5BYsxj(*FY3mL1ghLOBq34EVQ_Jb@k@8F!|R+w}6 zFNIkju|9Ehxn%P2+=C?MK8iZq-rg{Bcy;gnc{KJ}v}!@jnVoU9X3m&e8pdFYRXf*3 z+f=L1y}fc}tkuQ9wSRZ6$X{)VUACeg5C?Gnts}UB=O7-Zj;LCBL&$ZtJ2i9)md_34 z8&@y`v^ef>A55O_T(EQa#(!&hx$oka{jeo*wsu8BW1Mtuw?{=`%*~DeDfBgs!`g&- z!$k5JXK$=ajQdfS0Q--1JUK%rX7_wQ=Mb$qJmme#0d~)cbIIbL8RYZbN~}Bh9>MUN z!55Y@?C;_W@+ho1#Q)R*7|!SHM*c6x+KpUE9U!@V>Y|D7Thn*UABHYKQJf97h8TcP zRA*i6K|f=z->@4TL;m0Fg~WZ844UVI;Sw|p?nKmKai^3E537cY}> z^S{fjIlZ-gC3<%W{>(3;wypZM8_Ai~(Q{AUm-TFu=WqNkIQV9mbAWocbWP|uY$p7l zcJu(-!vTN;^f3A#t*WE;&z+gh{hTHLzZ7Ht{j;xy220>f#HbFPa`|d!$r9 z8&c5-=*Q6?+s|12LKwnKvGYd7Xa|>5Yxw=SH_4j7+Cc1K9r)=6&Mj&G>Fob;j^29L z{+_y&^4i>QlgYK+AB@ail6`)4K1XrC`ju+^yECOXu|0zt!G50@T`D=Lc)@TUZ|*NI zO-f{ug(U|Kp6Ic-&axzxBR5FVcvKh1mbtwM#=O_p7;=iQSDN z@6Zo9M=QpV%;$R&|I8)q0Y-k|kiN0!-Yg|C|Kt8I^9<+X%zN@z%!PB`KVoMOVN22e zse#1RA0*c57v0@st!@v)-kP(${m4tK;hlqYx3u%g;%)jYdvNCUkBw5VYjDh4`tv== zRg|YM-syKLzuy@q`4R2|62lj#^fmOIW9pWK319+6s~5!@!Wk=fkGRiD9YAv%bAL|2Me^PGR#f_vqDV|F`fXV!%K8IcZDr_P=;s^7&%cJ~sLL z|I6*|&x!Ty&G#{O%4e@)26h_zEyVnc{a4|#ZQvT7js~Wf+DdW+pO-wxBEg{blce;4$L=kSJT7U9ese<-4J}l zC~$o7g)!s@6X-MOSNy)L7Z%g=be2&5fIS1Tz&h;S@5*yZ{@)t^)&G<)BEO^!{ii|H z*VD*}XYAV)@ik*qPp((-E9ZUG{4#E8|MK$eMGZiwO1(aHu(ge0^QOjnU5r{xP5ZZh zXdltICSTn?zwuw~ipUQlPFc6AF-H`F$9Z?5rwAp4HBe{%qF2{m@a@DufZf`6;+M_Wu`AKx(c z@eo_(DmG2)5%ZUZ#Oa27UopSOZ?@ulbFXZi+ryrHU-1<61gt}xi?G&jnUxkX2009w ze1G-_<^I|$jJple`$YV*kXmc}hUMfObE3{@5BG{-$5CI1b7@a6LcW5$L(ltO@|FAG z9NlN%5?}Bzxs1D0v&l=G+v-dY^qb8agz7Wb!>;fCInKw+k^6@S^E3WU9SslXY5w73 zlYdV>CVA`q|Chtp-ukY`@8YqA+buVK7dCU$UHf%dauv<|=l><_|IQ!6E5H07;iX^w z@35OXd-|G@me(F5*(-^1wtoDAO_ej(gZ_(Hg|{Oxe>>~DwrSA0J-T=!{c zu<@s%;ijL2hqnAIwA%S8y1(cF9Q;{m&pbftxz9rGi_8GL{s;6w{uoML|0DMQt3l&G-Z3aqY`+8S!D&;QWip&F4QS-bp>r?7oL{ylMlvD{K<_{l;|d z-23K$4=lL!^!ek|f)HoPA- zI|dWWqs}$99<_V9Hoe}(yjzVN7;|KM-tvRx$`}uOaV}!s*~?}{KC$+1tatu@+BP(u z%nfShggpF!ad9GegZYB|50>D#Q)RrVb%)zfPuvC`G>cM zoJBK;+5IB+*PQ)MP2u=N&0Ri|^G1WgAl34*zbQAtUZ{Q{)-OEXS)?RJ*MOYC&uSgj zj+tF`z|!zz@)X@)ZhzHYr+v;&#QkXhV3hXr%@MN5p@x%7=u6~K%Q;jd$=bmFgZyIm z|ENFSb|`!xa7kyC>Vw(d2VYU`pcX??_|D*EkSq8-_vSlkl8SCq>d-K@c2CHjRU2|< zulkB(HTSI!+5Bzf%#~rpj1?h^W0a3)o+gKx`oDRezjI{IS`|j|_)#-!Q>%sHcV} z4`wU)y~i;6tXZQ&z54Y-LEZ6Cxb_%)=_2y~Vc`F{TmzGt|K;a~ndAc_LTHf_0Dl4( zYWP|&d_&*y;f|Ctpu#Dk;fR@`Nx_29Z1kegykt>$C~tPCK5#a4+Vo-=uoDfBV>iN> zCqE3ur#=Xyxy>fm=ur23*!?DZie9GgfBW&uUw>cwGWgp|X!^gzZr&H!Y3yQ5r-d#s$MZHgN?V)!f2aY{#@=o)0aV2A(J8RVI z%p*pR1eed|nzKJpxszRq^a9E@)WkUf_3#^Zhf9a8m>1jkwh!QZOc(n6?!A&b?BXP@1@KFAY7eT+rs3ELzoXK%MS>BMG$<}$`gr(?wl8czDk0J) zoVOHvbcc|>s0SL#@-F>Ovhi2;LDfhdiZ*&WpT*rF&RE)KaYx-Cd{znHlRI0)JluhK ze}hKh@K63fVmg{pUpkD{#^H5ue-W0y@~>h3^S=nQp8HvtbBXx$B5~`jU&p_1Grn_p zyXl?ZhShI;9u^a)=Ux7JJdD}ix9R$C<9j6Xh`)coMBM)^v7UWZ*MAe%^S*T)Yl-`7 z-~2q@dM@kX(rw^a_ZB?2_x=#Je>)NDcik5AjsH7{``g|JALKC`-uZpl$Q=I4SJB{k zg>&ciw|xgr{YQTadpP!e@@Ee8vc3KI&tbp!d3=bDCb#>!-S=Jc2%fW-++)uNe?7K> zpX|E9o)I|w@@=E;VC3S+z5P6_y!2t1ef*U$``Ali*0C2u)e&s*&Bc$-ywGGwnh9rEg)mWVwZfN9BgJ1 zJ%SQ)^fYiQ>wEiI_O9F^?3|xHKzjkkTs3pMF+Y=nf05@qifep0wxAw{xkyp%!cc+j ztD`@boZb9*JoSLOTFxR5@Hxg#>{VW^n1=bf{6g*D-QwzhI14ORkjxb(Gq*SfevzDI zF-t#_^}F?uvr6{y#494ML7iit-uz?~_=H$!DLj7bbmsx(@ak{ueYmf?4SBlp+uXsK zM)?qZ$vaXw-x5AU2CwD0*(bG+=Ul~Od>`r$s2L{L$UWfJ@#Z^OOJ+v=(cZ_H)%IiO zMgG;0Szx8+Cgf6nUa`m2iqZJQB?&x~`A2cc29279z3c!_)_=F(+KaZIG>zPH0=ec` zc;aKwiSQ_eD>~&2@rSz7*?YNZa&u?Vo1aKNTEb)1v+=P$Z_??H=~)q*z`c_Fd3h-&F`g!rVkoeooXTSrV{$Z#*|HCl-Jblk|Kj8NtgevayZ!@1^?+=Hs zV~vn_J^O;6^7*Lu*&R}Ivks73kmLz?p5h|O+uJ`ww14cOD{;JGkG3)1h|{+LpU=SV z+;h>2TGsvB_T22LcP3WbbJ9;3yF2DF3y0nI96d6Om@_$Y1cuLLet`JvjGTNx`}pp* zi5eMPo8}JI|4jy>W7UVf-tg?YlV9}U=mXyGtiP|7gDa8HVgU<} z>Ld7D>G2Q47@qHIl;Q`b^0-8=IWeab@i5*mQ45Pn zCG>H9f9+GQyYn(~e%w{#t$3C_Zv8>h4ZKo_yzsT-};u@?ImgRp1*!A`k|XXOuoVr&cEuZkE71Uv=bi$wFjru ztC$4WZo;wmBj;{1`drQgTEnXaG~LI8aa!X~;ntt!Hr=|9``!6t4^iIp4ElJ}xNjm@ zfV)1*IHsKZPMC4Z_o6TQ_y_Slo%MBhYT~=P>D!Wilk?Xn_)q!_KaK zi#pZZRBX(BnsR^S%874@A#}`Pj-B}53p_wPaVS0@9h_b*F#Ui!;Bw}R!0aOzkQ`zD zfo)*{K42o(`ryh5aW7G)Vs_=yPg83k@{5^2O6>nr{|n7R{DXXft`m44KASxT&(qwy z03YK%L-7qU#BTU7`|DlES^TW6ty}oqp0_oPwr=jyn4C#};i0aVbIWp~&5g>bUG#_I z{;A|C=Ks^M|LGj|Mq_SJjwUhwR?d*Qe>2X3f8?m3y4+>VnceL(bE@w~zF#qW5}8qR$= zzH2_8(LLNnJFkWOt*?dR9dCrvJ#U3lcJvhO0?%i!S3bYn+b=o%ZYZIrKN{@5nBITk z{u`kH?BAd5)sN+Sa|d`4zZdYgB6tAK?Ixc0KAeCX@QdF@Uxe3$?^Ck(?f5=p_`Pr& z`hr_u4`b;8&VU2B1pcpn(^-kz`vLkd|D}P4Tc^s+ac@=HB=$#O!|v^Ko=tA6eSSH$ zYJXY_s8{77?qp1lxjVLQOmcp{^^kt}fC@N5;78P`>ia)HZ_8LJ-lttXmYp8)GjmmE zi8>PJobBz0oyfsYqo&TB$$mesZ~NKS49*bRgOeMWHFrwv1D3!|$|El>04rC2G@Wzp zLhMwhP>!CxhribU^}_%#Ni{gs43m#PmK=E)KEQp(BNk7Ge>gAVf@1e-eW`6IFF)q! zbI>H=h;vA@sUyHDdVwvPb2y{yVUF)(hhm5Qs0oJi_&K{bMqDNCEaSb6$0Mq%@B!=K zETV6~I|=X=DbyVH{?qAss(}`H2=oVv$p3Sw1B%uzialAeiIHd~ zWrKx?Ejar;6%1x%^$hrr!{Ps-wT}Jo`6QA5dwtuJ(q77l`z6FE_rx1-y{?_PH5Pj9 zI4kb8It<n!mc!v*U>LINM&o zMN{^8wTU(_2lioV;#TAb+P-`I?rqjM?(lV9PTpWw>I8K@;|@GxV+J|sSguoh_V&2M z7_|S+VDt9;+*>0)Z=5!NO=0#g@>p_)gaH+B-l-j&6%Z#dx9!Y%inF!md3~s<-IJ9v z4!tj8VMlUtvCFJ^Xa`cOSV!11^YQL3i2A?O{~7cN)c+9ww|`l=y)NXDN2q670T);u zgW=$UYVJCZAhwu8?XA9{^9JI7&hv}Yiv!B-6U$Ghc8DB5@(TN-+NHQ)%VP!3*Ewsln~ z0}F9BXdFJa7$26+xtO=OGoXa$IFoISp*B-je3aaV`yYBV?ELUQV$E#s>P|}SNt*$gF1XUd?l1 zFg^QBY;^>BKzYRLxVQHR^8onVshq+du9ywf?y3jG-Vwv@e} zzGpU^p`mpzhQaI-7$PTN*@ZB8$G7{Z`~L5 z0lJYl46eeq=v}$D*4cG?SmySx=OVN!!zI)%O{?i2fyhLmp+1VsyR9RqO}YXEpb*4`9wP49rg+lvqIq`MUEDnfL); z&pALf)yg)n!Y{3jHt+3ZxEWP&GxP%!IG1r7Id9G*f7Se`DX4EM0&^Y0IoQV?i!bO& z&$fPt=F$GQefQsQ*}wUqd=z7R9oM{gwmMa6Z5-fM9Z6@-jTzdm`{w1Sj;H3F$~CzF zn{!96T6J+g|C8UMIrBx-wlQYv1FU09!3M{3ts8%xJ24N4woBhT^4_s4^Z!`46O*Tc zH74!fyhMF$F$VpB7)1rIX-;B&V!mQ+U_EWl5N)5w7ao2;>T4GqAde=Fnpcm*2YK%L zt`h!k4qj@#!)wab*Qe-@A|{A`)JKYonrnz7>LVf63t`Z* zi{t^9!*KGA5#G=F4JTj7+WdOVBgXLAEBOEOpZZ^NWW=@9_4aVLukpPxc!2zpyBjrN zw)LSH|DAo4W8&`V`ksW4?ujZ3H5>bLd*$>;cEOC zkJYob{ug5xXO!1!UHu3KgYDHc#)%Twd2$ zbBiykCnR6k_}hm1!rG+8@Wig*zs~f9n|A3C#H@CU)27_VEfwE zL~;V>Zs#A_8Rj0|5oR9(YrqaC5nIP&U&iKg>@XKhLfaLqG=}F9yVXb&JGHMGdAQaF z_y_l`%Nd?delAXL??69dPr<|I=B-)~=l`7bor29zqnA2$&$=*u&-zf#oX`|vzw<&K zo_8MKxi;^vApJohuP0Vo$m_HRV|bu5nq=VryFUKUzroCnZPvBUl)F>=D0*}1QMp%p z7dkTL*z=zS2OxhQkKMSlUcS2Xqw3PAPqmZBY5!{5o&1QM6x0Fc0OscU0PR!z@>YA* z&gHr+MC0B#r0r{a+L$(N9Ix>Gzz!lVf&VBXmKWdbF=*rZ2WtW~w7vCr^L>4V`Zjs{ z%{y+~(%~r}{uN>?F`p(M$=gF5-FJhzJoal7%jL>0 zJ$#FMc3ul3H@_BgsPzlTvx|4X6^gLKyp6AfTeadb zuXN3lh}ZX_o^=Mtx}iS&6#I+Xf7IB`&kPTxc8Qpu*tKo12eyRi+-m!k`!|PqM|Om{9J3E@#U3}XqpK$B z`MB3pA24#+%vh6)naFAAI-0%)F*x=dr;iOCiT~CcH75>G)3Y;)I>UTDZ{^%r1DMYn zyY(xR@IPh5di_lW$8>zrRP+GU1kgA6-lZFA!f2i&b|HT0Y_NUG3^)LTzyahK+^_#^ z+~QXKZ*3bfE^ObQ-Mzh!>&`r0J3jUC@5t-_6+X$&W4-Jg`)F#>Jgz4>s?Mdz&0UJ^ zs$;GG+}ZE{E^5#n{@`Zl!fuK9(wt=(%!Rm68=x3~W8o*L)d-H+{IjcQ%4K2^DO zHSyNoVv+Hj!`_58u3yj(cxd-Y{4(Eq1G^pxKAE+HxjXswT<_M+Iq+(oxf$gxcAUG1 zx*MC8f2$t9en^~BZr)1bvNeghehKfNO|3qRx_j7`H)8D`^J#FovZL>YDd2w7I4Ta` z2on##6Dm)j`F;LlZ2kwK7F@y@zmeF!6T9Dw-5;C<2zn$O$Gj1eUb0;$?t{= z&Z(R_Vd^n-z8?Q}n8fXP&aH%*gZ$msnL~Ut48;$GuZ7T?-7s>-AL@-}h4nIdx!AIM z>jzF57q#Z@dgy_uMJt|GkGkOQM;?q?7k52)f860~9dJj(deO$+-zzq6uU^iuxSjjD z)U>sarv0n+CD+$^l|J$b$lHzm=JBluGk;Id+?qgtAZF;?u=&OV?VF=x*$Q9KH1hS; z&NlB?H?u4K3U&C^&hIgfUK+jlraZqD`GUAxod2W$=l(zIZ#6;WC(AFC|1WkRhp3D^ ze;oES5u1y4hJDY#{;Ljd!RE;UIOZMQ8GV9&VH)vxGIr^#zBRi#YSsbbbZQEvQVTin zuLhAlM-O#>)&9rx)^`ykct3vzlwW%O>XYUORsZ(jp; zU_QTupb|A7|i4t-}eb@TN~H*-Q#(l<7qU&&VPa*CYO2=-*5_Tz~lH-eTK8e zd-!g5@PD=mT{Lw;SA(Ohy87d=0v}LwnLa1^#w>b|RVTk4WGjrF^Fx9WO&O~(Be)E*D=y5{bkV@;2a z54;)Q+qf=guzowRM&iG^TJ|ZT{w29bH*)<>`EYD`UVk_P&K-&OwIb#_`!BBO&oTb@ z?3CdD&7T~#Mx6g~kM|I8b^GVe9Ebs^vo)I9+t@ny$o3fX=fDx3Nvw~4Kwp49$87GK zhCP}eSeJ_hh#eSz9=0!@?~Il4TYn+UxfOx&qY1@Kg3-V8;CLUi7OL{kwxT;+P-mAEYR6JcU-ASdy4pf0o~eX@BycY zUwgPt)#o*zw%_I~`%GfJSfhPz^Lumla(swK1-9n>u{VzG+w-o#F2&hOi21RehlgN% z&x^rLw^Kj|R&J3as&SbXEU6@0ufwh0* ze-ZvdJv{x78e6drp$54)%ke-zy7U4sv(y-FV*8{POCJ3#OO=J1F4evIeZ_ER5y5zc>%-^K1d zwEqj<;seYD^Z~~IqtpTiuA_y{_q`e0Ux!~=&G)+!-2it0E)`qheXH?53-Q_drP<6+ zFFf~g^a%@|{v^!fe5?3w#X^k#DYM4k?9aE2+Prdh?qK{6$JlKR-k`%{ zaX#*T@IZBM)yTV#Iza7vZ79z7fX%7fWlzqYyqdlC7L5PS%g6&X_PWzY{(Q{i$t&!6 zivjpLagW9nb_VgY@n4&F7XMz}OHF+1j&Iz54?Or3cstC-@c#YF(I^75mqYI?gLs4Q zss5JwKMzO!pZcNSZ1Fpajmc`M)`USb!Q_+MD@(C0abQu>bi- zcZKQ``@&2xL+gObeH)`KTAyo+?(}fCr?ZmjGscHuRTIM!@`a&`|GHzv`DAN>6fjCP z%={ku;1AV383F!p4(}muZ!O|^OpUcZ`3Sda1eNk$`i3$5-8@08(LTihcAJSmnn#FF zIv+8G{)Y9|eeIgT|NCqI?{@oFLv9B#=@{4I)8GGn+)v?N3hmf^bc>iFRX4(zpUnTq z(1VUz5;yJNJu~Xoszv|gC%=pMp}oM^-zNvqw(P&lD=_9y!uG}F$C6uX-`={v&Rkq= z41J3=hmR@YTDA7h+y8FN?Q^j8Y-;;#{L#qW?QS zektF#@%$ul-CSS0f0p_wc|6C@7xBgC@C&CuB>v+otQ+>2_v1r0p^0Q&u^RlPHrhY7 z&-*RGe=X)57jhm8F7Uaq_XVCeKYPB_o;T;efY0i`feR`U8k+Xz$b;=Q&*s{8p7#Ol zPMcPf!hHN&PJL*V$o~`jAHw6U-^K0+;X8)m$Lt@9ExP~LT_N@zipUElg9qvZtWUIY^Zs0L1LJ<& z#kQm}`k{PY%kyv!t5-Sv$DVB?|8L)y_`hNR+P@m{=I!p8aEF9i)K75jZR2{YCYM!n z%f7U8>tbkP=-#JYZ{anp|FwN}x~u`*VQWnxey)zKJ!ks}aqg9Caxz%GJpr+3@$`IN zH*#Hw$z#aneXpo_0d8-f%~))`ZXGWFXax2?Z0lQL2zl&a^74#zuZ02FegE34pK}d7YesSOfe#>KAOmes^3m z4@mfcQ(yq*{ui+K zd6{?s=i#|6A}6uuU~RCHW6hOMdEQTA{C795v0XihPVn5sr6zD)$<;SDYy0-#9_-eh zcnXIH?9Im-uUnE^+l!O)mH|J|IT-VJchz+)92)ubgDcCTF159Rc%1pa_Go=>AE6$( zy|{xK8Ro++sn^BC#SY}*$~O`RRG0gX2KB-{_yGG3cY#Tohs2p7e2-ed!{$tmd35UZ z(s+LMFg%~0^uOJwkIX~7l`P3ld2m`=5 zvbbNKLp|`nf5iV)YubHrCq5(wk;7lb{-4MG-6ge?YqSQw%M5a4G5->BZ?QjrHdi;d z-^}&=_;-!}iCtFipVF7;Q}i$50QM2=Gsaqg>rp)#F?D-zV$o_+8<)+?bEvW1Q=^8a zm_s2yySIK6wredul>9!Ex_%Hj{y^+HZS{+xAG&t#)=pW*fhI;OxBXWcyA=;S3Z`cr zU>;yCaF*jK^L}jKxUcOS_jmDqYWwq_d@tr5vrfXPpvE7!>y1#hA08k*h-|R`;+=1V zaeQyqAz}kH5f|V*Ip5VUd>YpKdGJ3m{?8}=59kqf>g19-`{z8(qhJE=rgU!Ad6Y-7 zd3VjYmqPn@*2P$^4xJnx=K{pM)X)-_)0Y^_-2-UvUHf+)*B#i-z?zrWZ;QqTd_f;8 z$HtntU7osOrRWVMW`BAz*Cy}Qyu%)({f3AEKKfAPCw2m3bMKIxKxY<4Q`5`8Q^(WY zS^6jS|C*(u|NiiOA#=&}ID?}u(Q;z*h`CeZKJ#4d9-C5A$QdH-anknHv9~7A#y*>M zxV64LIqUCIIdc#Xct4%s9m_vbdr+KJ&Y$*e z-7fDi6OD3b6YVFcPik&az~_?J=XvGg6O8@VDcL;7^R?$W5G+Uiqyioz4k5=t9g)6p z4!+g(G4Q{y&j0PzxsS$t|5@U7?Gx}`a%Zc+&sGsXjnhZy!)b^1<;2~^^3A>1(kpPM>K1w@gO)uV`Y$>g`piBa zx=h|5I+yJWeX5SrUt^w+zI@i|=imcA7dn=23)yQghQjsFhN*|%CXfFYd;mK=@V~x? zc;HEDeR~5(dEfomzWu&sU@&91z7Ps{-hhQCc-`Y+*oyO!^EY7eQ=#A7)1l||qoM8S zZK2o9W1P#GkTUOdm;vX&-mdw_TFzO_U@QM02k0e6{J*j!a`)uFtJ7!9=!(5GA*PGV zI~$}%ov}OC{M6ste^+{2VqB^4ZPW~Qr+(%{}B7e?Z+|J54e>h^n z^w%R%_+3c;p2c@DX!2OTr}Bt7n){3YYy0K_;*Ik3on6#s z?fuK)^Y7`@^6~+-ZTSch6X2Zm0lsI}(pjqMejzyfT8vA#@-EsC&TRXVN zNrSx+H+1P$tSiaXpc?5ArDvm8+||#*n&PlUa{D;y*9Br>-8ZXV0W3sd$GK9 z^7#S8`+hg$y>_31{l~b^eTlfA$ob6`v}>_`Iksb|C&ce3@SbvcNF=Rj2 z*MZP~?(xv3XmglKPjWB5cpJIc7WfDD4(uaF{BP#CnE$I+Z~m?AsY_#gZV!J)j=UOm z&cPc0)yGl;+uB@P7jLtFs3wjzym_;6OIxtcm-icW>8bPMTzr0J#N*w4?fk#5LRe)%}gObx}qs1w#J_W#+LjDJ<1#QkH#@l)#{56(lMw%JpZ`tv z|Ly(D_Y=2E+Q0R``M)^6oOtmu*o3KmU=(hJ@tRaTChI+MH1&1%PR&uv~Gz9_U;Z`?Y`)+GmLTs<=x9`{1E*7hhZ~z zA}1%--JmpA0C=rVpY_|{Hp=*{?`_`jn9rNrw?}thj6d!sA@1vo^Z{xU$Um0DByYex#<{zO zUE0O|-yrl3jl=S7XTYJ6cbtmf%fr63>k;G+&hClDTT^Gj<&je-$3JI9qBgKcXMXNZ zPc?`2B?GZR4`+Gw1IB6f(E3onsDb7_GJR<`@V?&oDQlqq;1=dS&MJx*s;?$@*!e(p z%)|`+*_=RZ(bv=ujDR;_j^fOL`9^Z5s6NFV1JOV5e_&lPWDYqQ-%I_Q_}|~zKi637 z{gZpTH}aPKlLv_ZY5&G-=Ut*6CpkcJhSeNi`xoaw!t>qFqy5`IdYzUBYwU(Ejt$O8(vwU?OBefAbh$O*&)=i$@rsfo>< z5)Z}pFN147XJ3Pw#`wPv?T@w3|1e~&JQqrLy++UfBW&;Eu<$ImPbYe9OR#A1KAWqj{J-Y#x09%l|OM?PMY*n!uu`Fp*`m?Ojf+w+(a#3g-z z^R8-BYm2>zzv5Hot?Af?`Mwyu_OG^p{GaY+1##Zp+1zHtf4P5=|HtdM#+Rr8r0u&m zukU!~5$H=a!grWw=m%PlL^Evk$k2)$K#q`oLg)0<0aGv6*@M{s6RSw;5p_jd#Qneb zg>-6bwDO1hTU|sy%X(j4o}7O1K=t{ZeKr1z_iO*|w!hT_poVp(z`a&6*WkV4Obzvb z+yL_c=YX8yk!xrF&DnQ%XV?!cqz)Gk98Uh8x&C#0z$+2sPg_kMK>cq%pkHtv(L7&l zU+mC%+Q|1Ow^tiepW^Su_<}t8e!2P=`N8A_`T%*w;~)PpzPG(jadmfZp8*efj#}n< zzLQJX|7q;s`hU^c?}nkv&V&if;LgCd=743+g7-6nUV9Z1p?A}>$2Aew_M$}QCEPFOg1h?CH9z{BHkMj6Y-X*^s@7 z-sa--%&?zk#^4-th4_HYuY}QXjmr*Q4^xld2vsNEkM=&p^MLmg&y8G79$>-77edbJ zXTlEnT5^f~=WZyqIpyigQy2SlhQ@18%-UFJt*cgs96fi@JMY(ox_vPG(j5By-A1$b znz$@4S6ehj$*pl_-`PTSGwQc(9{YXH<8}*(^Bq}pIlJhruNv#(c)qrC0&1;#F5(G;@k`bkzP9;= zzx)5ACZqhKxbKwL_H$|P<|y6Cd&E%u|7g&M91Q;7m*c;-sf`}RR_)tq|5vc#WDUQU z_+Q60X`fGip1eE{Ykzle)_@Ie!k&%)?xeQX?X4Z8K2F#_-wC!aFXAXZZXLDI z_`Pp2%R~Qz*DeF&AG`a_FnT+D`wcJf-9H^ht++_sIKeF5>5x(VBzWCvboP&f2OfiO zbDSFQ7@Ew7Lh6FEVHQ5s{)^wSJ-pZ_1fQ2LByUjPs-Mi=`bOwJ?Fg~s2=&JC&=-ua zPt{T8cTTXw^9kPT33}W3m8ECcH~$RUhnGX~=9j{l9k0_1csp`{2Oe#%8?QsIFLkPojbi)iHkoZE>wj+K;txf8Acj>5$ z;oOkgBHgJ$n$h2jdx|(u>yC1IWa5sEdcqs-)+W|A&c8J8m(c&}k3DOvYJ^qo-5B*V z`eEnB_Y&%R_56DiM`M0&{!Q(yO`GdGqo3sPM+{H<%w$FL0OXPg8{=goeIg0y)t*^|b z?58I7pR-qp$J+Z7ujtGB42_S)$M<87;w$XmYtLQt$FbG3T;s-Wb9ndd-HQL%sC_%R z`sM(MS)RlUt~tChO3wdzb7h{Z4>%utfW%8)+xJMu|J!{)G8a&1;PxJ&en38+a{%&l z#2h0Bh`c=yI~S`HClE7~KOlau%}?d}Rs&l<iTj*VRG;}PfLr-%JIo}TYQwOzaJ;-=xou$oPco~sA~fs3F1nuM!o$tU zse9#xo+GId!65rh-4li_eJYgWt7hZl=E4Vbr;7i&OvuHa*(sye2N-~Sy>xLm{D3hk z16xsh%Y3#kxw3Yi+~cKYhIo5=w9)=?x7QseedgBR9qI-GX-{^m9!{TL;pF9!`E$VM`4(knPg4E*DN2%wbFVlAYF0{!QbFnM) z{S@|!yF0a4tnaDyd8~DNa5y1H}WeeQ`;3*X2+5;XFM@_Z#=X@90mvjLVKX&Egg66WB}4M-#=~%Dr9S zZGr!PIsR*#&iWsxe{alwj=Vqi@NV*WodGgex6YTlGfQqcHM0D8a{}}CX#d1U?IdCU ze~PmJk7Gaf0KdxqZ~1|nxM0-D7ZhVN(2VN4f))K45}7o0$=c713^d~ejMUl=%XQ`q>{@4`+rk+-0=zZKnmcaZP?fElWf|H2-k=h&Bd zl6n1)Ld$}!TL%QAMnRX^dRKwEkFa*SUr(hzQM~cqM5Zl zv>LXAYkfv|IBj7VQ2i`A!*7KNYYv3%d}nGF?|cuPV|E{J1~c6D?r-9*gjr|=G;Ytn zo!+_R_qEi6yTXVS7sBYhZ%6z0daB=sxf=TV?&ffIE`{qWQHPFA?Qd9_`UVS zA9%n1z!^X5hBR#1`biw$UP=aWybI^pu^4?}auoA_H9)+L`%ah73GP=&C!Ze(7U65# zcS+&sjnB}(c%<-LHU6Bbc6KnHAAY43Sg4q)IIB8>V*c)2%)}R(zqlvO&-6eK^cS)J z+x5S+J$rxl=}&x=$p0^3w-5AzJUL)x}Ahdl{v<4rz?+dA`S z>Xev2z&EyD(f-vmQ$wWS(6{6KKrZoL3{d+oCiaUBiu+rKM~*MC-=3THzm4xl{;rsS zwS~L-2BNKD9^R|!OlaSO{I~i0uN_DOW~G~GWV&FyZNPiktT(yMSvrfoo~xOaSrB#dwKZ+r`L+yfM%}$G zaPaNTH^J8B3mc>CMQcOu#Hil}t{>QeTKDGDUaQ7(J6AGZ)s%Q-=R%8ujH(PI-U9gkG2Jw97E&l_9QP**T>yu9{LvhgyIQe z80rOf90M0J4;^28gd81vdLGsZ?o(BB$@+hwxj*r~GyX>Z=*|UqdAc81EYBl(F50|W zYW5D)VYUY&wrcL9{TufOfHAnc)q3IH_K$`K9&UyP{$KS!v^jf!``=G!e%P}!ZrjH< zmRtWHz<%ZT$N@B_I?J!^tGVT@tolFOxZa!{R5!rfA=*E$ar)!mz$;*H0Pm5sZ*Tu^ zhq;NqBIX1)^8tN<=b?>xPVx=q7r;gmsJoFoJj$8Xzi$|WkH9&K6Znf&u$VII))3AN*L{6}Jwf4w6 z5|f?#u@Cpyh=H-jRqrDO9I83@H79Pj9-bDjXE7_UQ}b|j1H=xrBkiv}xphk(=RS~! zs0*CeRr^{UK=TUgdguCDa=*UG`o#U5jd-keMC2!7`#p(?as<>S?uEUnn`zFWzi>7w z&K#7GYrt7j|4aQp>v;DYt5dFSdF!ER@%%Hv8v0RJt1;F#53OVJh&I@*en9(mN4WTf zIgB~IpUvBLh4eJ>0oDiNZ_eZS+12582G{#Kk4^XvwZE(bdZIsMA92~^`{L|`{nhBZ z^o_n2GkapE9?l56bHyD=av{Y*TJhb9okng1zOeaFw3Yaqb-|E%Q<*^oFXaEOlDVZp z)c+53Yn`zF+w_0DX1qT3zn9Sckna=mE^Oaeu5BH9pB++MQwhF~I(=$!6Z^@@R}zow zUj0S%A&0Q@Cq8Co1>Dcxfqq2(z#(dAXA8gF1Gr@;oWno*Iq3&{ZW5!Aqi~+rzNnuO zrv#f&CcG&F@T~{CMYS_tWb*h95i5 zJdQta0E<}4yv%H{#A*1E$LDcnmi|R0#APbPwWJN>&$t24j$2e-TZ9& zuGRR;$?%T~;V(_7dm(IvAJ8smQ)oG=E_AIt6^6rCau(T~MV!^SBza4z)C5&vyJQ*H^8fdd&aW zUuYb$0%AS&hVu$y=GOhrxfpBJ@Rq~Sj2y*0A!-g`zp?+QQ?TwGQ zOAnqScd!q7qMh+gate*L;uX>M^#k}mZC-m+Gg;1pao79w5#|Qsgz|Ic5xN_o0v!Z# zcsWlUi0OT);m!TU59R7a4lsRAb1wIU^&t=Fh`-X_eGlib#6Rq-dTXylEYv#48c1#B zme{`cwIUyImw?~9TqrqF(|4_lb-=wH(N4LI|L?Vuw10E-W5iSW|Jv-6*w~YwB(%Kb z@ELctb@$Yp1DIPcW8Z{2p61=w|7r(`A)euR=f0o7%umCawJzAntjm9e0e+SJC$DAm z=|kXe+P&HY&J`S`S8*Jhk2*!v81@*GykctuYXox?ZAosSv&L!+XkYRS<^GEuTJNu5 zj>nlAId{%5ngcz_cW@j(U=Ls`pM58TlE3-S_-|~M+iM+c43(GC)0m2lxmU)W zeA)2&>;alvo0}Wcy%tBJ^o6=)0|1xe@4t6KhTHRFZSm-SYw$VnE$JDF7Lv+ z-uQ3am-j3$+t1?rxhF**t*?}CVU1%Q)YM!4uGYCb*{u1aCNc5f9!K=Sz3AKChW{t+ z-@H|f-W=L~y*4avXYFo|EqDSC!&*{)~@GAOKC()9BBdmnW zvlEPP6@9#AXWk22UinGHS&kFy&wfJP#XQk!_JPf+I~nG0d?M_im$(MIcOOU%^M7I* z&K3Bt)3{L)cQ?PbPv`ZoZmpbr?Z9hXY&@+3Eh*xw+F;^;YJG~qXD_G>vv+NXyLycM zY6y$J4IsWc_hK(jjL-P5{HanHA$0%Lz)zTYIrSFI2+SI=24Vt0CY;s{;A6kF+Mh9t00 zXSC%%+t=`C-&^0Q{hNb`0hs@*_g6waW~~-?1um|Nxz_!?|JMGsH| zJO8TRqi@3g)gjmRjs0R2)5yQORGtn^a<+%2xjVx^IRDFu#rFD~6?T5uT^SRI^KyyB z^tE~Gd-vh^IQL;VAMZ@lCTvZ9(+PaudFmZGzR&;UkKsk;A7AS3Y(@rrjbOe6TMP`oPMymsR#x9eynCb^C=RBv<7Z}A%Z|@mA ze&P`@o;hp$DE1S1eq7(~ z0#V;To!PmL@ci!wpHzd`Iz>EBK7ccc1MJ~p@9yx`mKVY2bsw-Z3Hl3(beHxqG8*=3_a>e&zJkiJfu@{aosp7*pNl-4y$lqtKXhGe?Pgzqysy z95o8bF}zQo5&3q@=fs}A8l-BA=%>u*wNLv8askZ$w^K)pv55NstMS({Ag%ayf-v2IS`tUVa5$? zY_9R1*y_ws8goDL1J&#+rQWZ=c6{CfdWK8Ld5zbr!Qth;i1FLob8gX`-@fM+c+W3m z`>*}WU!vW=_xZnt?|l9r;oV>TdwA{Ve~S6QL3*Vd_)LqL^O+9Mw-k(i9JXDC4Xe9Z z1utkGc}Lab=z`*h#**{9lV?=ji(%yIDB&Vc)F?VY7fgmW{R-DLQtdz&?i7-j4|@*H_Z`WWZd3VhnsK??)TO&`TEuf-Kdw;OmY@OyB|+aA$KWU0_u%| znt72saBqi%{@3>J{zvSQS7Xce@a?BN+vhBRI~-`hytb|3N;WUosAg zMaUzRUo;S|e47bJLif4nL;I_V?!V1(*8fIPs`y=Vn(dL`tnxyqc~OCg_g$Y&;@2!3+$c4~fV6?KG4nK>HA z_f;xq7{4*$!1bsZvWU81H93W!TR(gR{Ba?BMyv&_QD##!RPY+^5-Y`?$6?Fybu*zU&y`d&mK2%*E%7f&V*^-2?NO4XovRu&1e>!8x#A?Z10@evJRl z$BV6X0XsMUPvIJLhlag1=WXr#cjSuBE zw3T;eJt|koeIfDy>}$zO(+3z6t)HD6G@q5PCuje$A^q41mK}!7D8uJuC3HufJ0wq0 zFGS2s?x1@_?N5}hTNW0>y+T_cZDuZaH-BJOK@a^&Y6 z*b;XQx~IVWKb_C523f5C>>OCguV1leM`f_=JeHfxl~q<_Y=i~|5MTE)AonpL**BW725kVZxQd8_Ym_C-Y1!p z*aHx!RI^L`yj5hbe=bm`v>ye zfz0I%AV-z6+Mnn8{Pa~Xgi&aCs2gJM(7NIFn4kRF+(a($2JkGg1ThI?e2=OpLSJ-! z)bn!AZvip?kh=I_4(gB2AqSTithTq)73)Cg8lMJ`B_0+KBPb zAokAZ{q+y(axMVRx3FF$L{kEJplA?B4G|KGGa|e$%M= zr#+6|559R0ep=nt$jN|*DJH4*r+TEb!8NDg6Q+=h%tHHP5%<-CajIExfO<+T!DsY$ zKmJ3sfAerPePXVRomzK`qsx!8x8`n+j_~~4$=8Lvyd`;hV;(2JUan7X@WT1nfBCxQ z@mdw57B{!%9XxwdjQ{!-I(v$bPN8nzHpZVa6W%e|)xkjQ{BWZ~E|mg~c!YGE_eO zDKjsh&^SrM+ z-!mYGq(+59O60JL9QLAN1xc`D2m&Ml5Cp&u_5y;vgJ5qU3HIJ8QY^A0N-|X`$+DVd zS#oU0vK_CpzR69pN$kxgds8+$cV_?F&*%5zReTfQon1S3GCRJQdFFY`^F9sFY2Wib z=Omd&X0sTlxsLnz{c@e&!}foy>|^J@^B2hfpZ}Nm^gm=|{#$?gx9Efn4xnE6HjCR^ z4X+mm+%J;#BaRMpw_jf?xmQm-H5(KRVdp9^_qo{BGWmb~fBC=iW2UTM&T&f8%-jk%PUXZB=I!h~ zBrnSI8_2cjhl|V0HFC-FZR}xae6DT~tCI_0KNMqr;~@JYPusOI#NXxaIp1>}zE7$H zK>wKoun*zlSGIictbW3D`K z6X&1IKeQv^02}d#lKlt&Z`S;Aj`tkr2j;xx6u#4OI0DDfSI5C9PQdv%!TX;5+=6w5_QcV)Z@^yalN7;O+emz(%@-4}*5C_$^#Aye$)?%sE@Shl zo5Rl)$GFV%Z{EOpM)Cx-`Qmtq>wpZ~v(&i%<0R+!{mTDeWaRu?fBN?c1N?$m;QPP$ zFYzOe^DO%49&v*;PWldFllNJhGt9jHYx*dOeP(hW<}bum)d}i|8!Yw=+Kx}NioO7g zsBvCGEM<@N4al{%xzW-b60PE9g3TUGL(< zlq=LWm$|0p1*vzr_Dc3-?g zZiDxzH!`1c7hID$L46)^PkkQq_{#tI74uS`K6`|yXA|y$%WiDdZdv>#Xbr zQUEq#4N$5#qE1TOz_FNo&^-kL7 zW5iDW-9Eo7ZeQ3JSB}@kjng~hQp47`e7rWUoY)rEPHs2`6Zi%ZW>f-vT9jv#- z#fHsnQy1qCZ;VTPccEcZTxCCQKXbmFRJ(8 zxcrmMJkqTHFD_t?PrGLwzOlMB`DOIeTn>h9KfF8GGV}kh{rkU-kMPrf_#gjk!tBKf z#2?imr;#J`5%PwV6>}1Ik^Se9j~7`hAMzB$7u6%*#3p`%o!2fJ1GxTnquu`=vj62T z|1rM&tN$7wv)#LFFJAB_zm@N#50dpm>=C3tqAVW4HY=CfWMyA2lzqdT{U;VD1~3yY z&pdR%THe<&Bf&UDT*7!jT+_KLGnpSa`@*MDjh@)cy*N)#LOGE7G-8FyznI=B{2k?8 zJMVeO!Mek~tR>K2v8RK*-SlC8@QZ&;&x5wm_&n9_VxO(6m5X96y0~>QG5oYGtD+29 z9D^-ZF3r)2(}@de^Eco}Z@zje)dCLX8PxudM0Qf&E9{YexbiPXo@U`7|JK#Yr!#I= z{+;n?11nX55|lLBtyNEYJtg1}-?f9lY&8>Z7IK z;c?{vn7`|iHzdXX_W!h>k+paB=MpDWW=n{j#VcII>+IQS-Hdq-w3xIB{TQ z)UKWp#d#f~>(Ft(R{pK`5r5nPHmUrZt6KtQRtpZM{A*7S!95yJ|F03Xucf(|)*GaF z9Qo4r%N;O=w*FXO{3f!eOzHzTtKfx3+o;?o9YD>(`^d(JfBJXC0{H$cpCTvv{NKeV z(Ek4b9qmcWAngX>y2g6~(vR{Z}h$bb3H^(p71os>Ty2S_}v6WE*nzgU@Zt+n&R zux&oq=CF;?)j!r1+FztIayytA9;I-LCK3}X_s;**2arRo%xVLNArraaWX3G!EN6my z8P``Gg7c2v@p{y4@^;#RSBn2n+(v&N;`6oWtg5~A$ibEy3m7w7-)t?8=Pv(d5cq^R zfd03!x7dccNB1WlsO-yOvLA^x!`fZ_2z@8x^~&w*(Tk^(Ew`_q*KO^iYwiEIb&FG< z1pAH}Yn5%M=l4G9hVd7y-7yzv??v+$y}4%dfpQ!3@VV?4lD~RUI#+Y9#s{98oFg$; zb-48m)@Ima^od6M|H|!#xO??LeC^po@#4)RtPjU4caFsiHxH-xclgfl??2ZN_paBc z?cR9tY})4j?W6J9*G|WsEBnLk?p)oU-amhX?O1MJ*q!;#@2~8O7ufghOMBzok@c}- z{p{GhYDTPCS{5@)sU7RoBzg?b|CjQQ?Cv9{SPf3-tQ}`&9AR;G?t)9-PIK+bPkaJ9lw84Li90`ejbpr5SlD#O+; z*#9J>3ycfo0c7F%t_PKC%@$c;|D7TO$-n;p7V3ZSdA3|T9a}HKy(G^lcIM21JnD(9 z19C2*afSJMB*?X26G!Fk*3+y3R|Wd^|m*8W>Vm5V-7m&y~=-ditZZZ-J?=oJTiymU1lym%$<^PTIv z&mNDL?wm{C-M)4-?%g^SFWfm3cdj3cm!H27cW<7EufKSi&rhcH*Pc5auiwAMcNgOo zmao5XIbP)VH!jr2c4C{Y)IIIz-t61HGOA`2##;Vw-G_~jOFz!cBhUK(uART>eDV3@ zx3+{!cdG6|a(P8SzXx?WMKN>pW?3IVZi6~NKR|3< zJ&^oy?544KvYp6|c*66IxWvqXJzwkln^RP` z*b_C`evWA$MR^0;i1X)OVm=}9jI$JHApgp@c>=jk`WXN2KmXtOA%CBKQ-dE=Nseab zMdl))FZ2Uy;4mNLo``vRE&3HH{+GjzZ=?U=xrigElO7=d`u~aFgb$FtmQ4IVGx5ok zLAfl}tmp&VV@5pMXQ&*G&%*j0u@JjjhD}bh`FPfP5r1o6)?GYC?fS+fLt;}tlX7A0 zYoTv$k1qXi@o??G{5Ls(`lIc#OXP_6D$5 ziF^UE19{0VsRjsH5C=5w)o-yUnOq_FtxR;Z{x8XYb*isd=B8tBoqg^MQu7#coBAT( z#z4*y)wfU=DC63D^_BcZug%hI(Y>Pr-%L&fmrJ&Aj$ zd$MzYd~d8Vc}sPw@waE%+=d<0POnJ(h*bN_KE(L+^~bFuw}4HzH<~tHzG2r%ugQ;PB3+KhIJyvN~RGMi0m>$lLNtbeVA> zp2*uC&HJs2M~3f+5!+r%b;-NH)r}q09}SJXME57}Q2w#;fQz$9trwCztX>c!5U1Cd zzC~V8U7#H47bwr-XJ1e9L?2+{{bc90sf}`$;(dOn+&kCP9^Ueb686XI%isM);xO3D zV;R>|EEkBLh8xHcT7$5hdW56I?&6T&|HVJXkH8r|19Mb|SeL90aITm$m!^<&olad~ zE&M}&BgT1+zP{=Jd7JtH&ImmV29niBnQO2nBU7JcZwK{(e|a@?5M)`e4D66?+>9_B{{&?AB}Gz+0)MLyq*BjUnXVi%BW}_6FCk z%T*nS9aHv|1AXR{|0AC#_c!(I9LUVELA~J@44E`sNN;M9p}4xv7Pv4C-ey)CV) zH|J(8-x&0Sc`$K3=U(d*>-(qUg3)#0cl!VG|E)bxE(_VWxlCu44xNb~3AW)3;Q?Hi z`8DmU+#0z&&gmKkzL)BMk$w3&=IF)st=Si2x9^5?Kmta+1Ae{O@23RSIpA%T$e&)KM@L}3_<@9gIxct|m zOV{Jks`b`r+qO2I8E`pz_qiM$I_~34)3#&BL^;@SDsHX zwQ{+eUya^N@5YF_H{l|EKlKi^-=95-t(}oes}5+uPflxJyP#Y2599>cTk9D0GuAiA ziIsCCW~iT#sbAsme=EET>f&aIX zcu0&;{Z{uHGriyo8w=>qJPRh6Iakihb89?Lb;C9CA)c?XiS}PVQ%x(i2BkARW(^}-J}M`rx2k2-{$LC3sC zImG^3FK_QVF){sH<79cQ;`!DN8?%f5i7}4m`8NkR3cuXGV2^iY_751L{D14>#Nw<` z(s$QB8biy2Q6Ctqiz_C-L-`+q{A2%(|LxafuD=A?RPXe|2N;1a8A3k;;|_Vx`axm} z^7x(4VLt;oQT9hwFPd+Yd*qA_d!5*G%ef$%Z=6j%$i(YMbKd&u*8XO5f6Be}hjIbL z1l+HbBfAo#nH z9DgGJuSH-Y@~r(^wCIOXR`zDhne)xGo;&x0^t!6*!&tI}y0Up6#q8Pd$E;c3h#529 zP2c(2&lW8BBxcThFTE}=e>*BF9;R&;E<|@!K1{!HTlYPEI{CVySEF0E-O;k;tmxU3 z{O0)Ue0DGT^*bKTVktf9e!cvg1F(;Wd3@&p%I$aNkg{$4@qY3HJKtiSDBs(Iz{Pq# z=Y+{gv^?~*aa-CVI?L(GQJrg!nyl zsg`HyEERD*{Sf`BL&M~l#JN0tl`rN&ZNW00g3;kT{VAf-DoL3<7l2gYx)L&Ee*y#D)-8X zKDqO@CgF>&A@9E$zPXs8wSmKk@3qOwzjJkl&MAwh;Ngq!>$j&G7;L{B80Y)-ET!)s zm|hQbgU7Oum@?_wyq>stIUN1og=12UV%wp868}z&(R{eFItVPlSYwhleSI;xx z{r@KiGItE#oVA0|xpj;t4pj#2yH$O1f6_Yx@t2L&hgacG5V!Z5nxE=uotvqin1BwD zA21WUE>>u5ownY2ozCB`K6@zjJa; z!@8!q`)i}-*#5+G?!vwIZ|PFz?JNdMLY|fP>C@l&O4gNUgWFG=#tbVK zb$~LyXwj!hC-~j``5&i!`JMX3eH0hJ8iNL%j*cBSBlEkXwDg4-KKxn?9C$h&Z?Ovb zAO36Yzc$Srp7@u&{p{awExa>3x4@+{M<%YWoL#`4S!WsZ&qb+%`rJq$O)t=&v+!8-d*EY=IEOYCi=elh=e0C_!v522sn`RE(SMacLF=mw7K zY$WCNJfGVuK>13XALRZL-=BjkVC*5^+1k7H@EEM~cMg#;hWR;XhgmyePmwa_7C4(o zp0qscN$`l55$hji|H`yJfjXiXZt;A$!%4@XxAbRH9T#=h#xceOXE?6sas=I|A7ZV8 z=cIolC(7&a&%AV}vCQ@w)C=32oA5jPMu=tUYw8D^BezH95S}aN?OLB}U%R>F(6-+^ zA2rxLebkJNsz^FOJZn79d*a~{|I05lUbVNK7?`{y?UGX~wGuWqhDF08fj+J8C6{m}#V0+hErWh=e1iKoTP|A8N8qO3ztO~N3l78op=ZK1QTpRuRpNk09BK>n3E zeRVmma(R_~#_xuoyz|YNihsR?I9ooTa_-FWwY*-< zepcZ_*b}6Nn&1`K*J}KR<J#7Kg15`7thDq0gvxIX8VV0 z<9#p2A>N_PAIGnd7pYI--%$BK_>Rh_xwR3*(r>xNifH6zB4$cw7V@>o2xBC6*T|G>xY zmOJME)&490V)*I+<;pK5xY~6UwNBO#*kjlkXa3&WD18I_ zX4qFu|3IH!A3bplQk+1Jk@HX&>6aWvUbn)#vG|R&&Is!ffNrA+gew)|K5$*edkK5VXXlFH%`{?9fut=|72~RKD=0-y?@N3dpv#r z5#Wy2xoXGd1)CeN@7EA)pZ)*rZ7~%2wkBpNKCJ$%wFq+mJM!G?1Iu-j2Pf8-;s9hu ztb7zUR!rV{1LqD~v)f@1_P;|bW+bdm@pm3EfHgn;(Mi3)6O5JZH)8COsp}t-@{Eb! zLwwK+Kii%l@^8#39xf^eO{Z730@~wDq|7N`Y%B^^f_1mxAi4Wd=nf2ZD z`ps8wr|;ax?cd=2hu?TL-hObG&!0=b@w@xa!~J>vZrax?FI-P+_wDP4Z`_MFAKZy! z+>>=H=u3)URYU%A2X>cKYen$QA52+{mDYXunz99|xC)NbmbJ6p$-Y3m(Lgt+>Qjg9w zX3)3MAM#JzWd1+#fAB3w@|-67kI!oyU@pz|IG$Obb>%=iyX`tQ;f)uWp?fy@!*X8I zoIC!%lhGgY>t+#u77*LIf3Yb!vG)ESy=Ff1Pck*Y%73b%DIS~b-avRi%AmTa@6-b9 z`QkJuXB9C<0T^W0{1M5oH)at}NHau`hu-?^$g<}sZ!eeYvMyKL!5V|7`f2}Lr+G)_ z;hj;CN4&4>^hU15{0B^fLxX%-*JLe(vSnOtOszj+Uw~BqkG^uB<}UTiokwWiQ$1TkGk8G&TLdzjk#uT-^0( zIeVxk8g?y=GxaOt46m=A+{m(t?>5A#gVpKtV|$jwiT%st^uZO;uzOLQZ&(wTj;@Pa z=j-Cysm*YF*T(hJ@_jeN&2zPJ^X%5R#y;*`-o<`4rhT2*w>%b9j*5bjJz{FXz*t{h z9%66b%P;=J~NM~dkgmn2*Qop2oeBv!czEW%zPtLf|OoX(ZEzZ9hTQlplPPIfI{|KfarOyYjg&s5N9? zENjpS<`Rqn!~n!AmH(TKIzW6v&Y?btHQ)9{s%9pF{*UG8F=2}jp_V3 zrn9_VKYFq4l`(pyV&f5zyWzna9>!|Kn>H@j!XO#wt_67M4)A zU&XbWd$s;xDEly{VlPE~4Rt}b4$%G|eK_Yq=sSC*$@MD-mn^AUldy;-ClACDu!kaI zfdvga@kh#%{5Nc!5jz%-h#kvD#ja(eW6#QQvA1Si99~}-2U&c-f6av0T{AXzt{4~l zR^`W`4U_n+AP#Su5)E6X#If3v*jYU`_O2Ws$F~;8KEK;g#P(z22;0=N{ZT$YxqWIJ zT3-}(9B0;qE-|{#WBC28Vr|u^SX0%H@5fAVHf4M&vqp=- z-zJ^-B#OY-3L8F3y#$;+JmmyEf63QZu-$CpgvH2?I$%38Z=IsPwfLHNyYheid%sL^ z!D0Mzdn_oUE2v%AK;OT;Z!_zIn0+_1gI6QRi!YFOx%3Hn!Y|XDzZF+Lj`I2kv5)-z zKH`lP%o{y6c7IR`mM<{-uW#Q%*` z_Q4S}hO*cBJo2T}uY8{5e*k`Kvd=u%sXiAwA*VdeqQU5f}xjmDKb?aZa z83$RGfT5fF^0~{ychLV=wyLq$>Hz!y=v!FhXZ&yO-TvQ+1Bjhe{>AgmV~ZW+;`iEz z(EcLI;t=xJ;%?UW)_|=!Q_J2Q=JwCq+DS+mU+m!d57V|Jz{_AKY0Ly!C(7SGV>JuYF<$eqgZM_zJtD*^G8N; zpPaua_s@EN@j-hth=B|Rx3EUb-2lA^AkH0DY%!T;r&6dK}H06i;sc zG}1`TFtr}PfWZNt;(N`r>5VGR&!s7R>fDMRq3^O zJpW`oG37!$Hks|po{cAGJQt5ozY{I_tR>sGoN*^wmGJ$@hGa*oK7c&|FJbTH*Hr~k+yLB)$n_) z_1}R^n=819o^V~y_j}+3>}Q>LJnX~%J#{Zr=ll8}z#sf8>^k#NwcqH1WAq5ISD}9W z5%_-_UZ9UDKEQf>9OtK6|9J89OfPorzkC66B@O5(`yZ_(7Fvi;WS@i*{2cAS{eSG` zYo9zh{r17l^4_eiG2iSW&TfAjbA0x!&-B~43ifv($x;P*y3{um`IhrC>)(jhAm=%$w?9wEx7>smI-vF~~nyBR+um-;>XDPd47%+!XTbOHb^Nx?AVdJT37) zZLjuN`L}nmGfb36IgHi^hzWGTt}CmZ;Kj5b)Hm^e3hUr0VgH?_rEe@pM%=-EL*g68 z`^FXWlJ%|CA)b$m_0I0!9s~)aR8KT+qp#w962njZIEcgb2lUmQ8Ke(j&6C%i;s9h? zJ)ke*93Oc;#yVms#!>qG&I`%MUr4!!+EppXDJMf6pxo=LIj_LEO!6M*9;!<-5akhh z{}=Lq(*9c;ZN9W***Z9tlOkvR&!Q=Lz9(vbzyokSnl1V$T2#FkO~>DfW|eP8&Zt|F zGxl~goAP2bnf@@E6x>bkbB14vCSz_!&V;+swCMS0UiNY{D}N)JOt>9QU6(zGM<(B4 zsNC6TK85dRJ&dLW?6dUMXv#K^%zrmpl-!S;JdRoOdE^yN`i)%WI!R;2~TUeiC4^sPdX=mjOS%+hf5wQU=HhYH~ zr*FFdqg1z}e#mfx=_7uH|PsMjg$2{>*@7jFLHT{)-`7KPoH+UJmwCa zQ?L^*@fzlkt_KGcpR^}w%8g?Ct#dH;H)omp6;fL$f6D7D!~W(USZ8lMZjT%7jhME1E@x+NrM|R=IMdu$$@VpAZk>I-?3G9or$&d~V5`o4^9rNe?q`1-Q2Hhw*n?e1POz zkh>7SG;X&((B3=t2Q(%yuhEV8!Wk#gv2~0mo-r0Tw^x9y=HeGmMCSB)%)KeQ*8Ix1 zSBIGQNI6E%FV!3IojDS9g|$ES0`c7KM{4{t6+3L~E=O1Xqj;)1Pnq|+mG^A?V-Cbz zfHeT-6zv64xfhNBc;GN{1=jzF!|GevL%0ZB(f!Iv^cv-A*xzsN!EMZzIh_6%`eV); zoXS4raTtT_1EZCzSiEEnwcI6lTH`{iGM7>8K0*?rYI>;=OpZ@M<*a zdoY?8T#x2c(GMffMT^pxqUi{7ezRVW=9BJ5lcA@h*^+O?@PfkMSpMY*nvZiXp?$L# zBg6XqV|Kod{J$Pkj(&iQ{vgS`ydOD0Vs_f(#0kLeii533hF76O&l(8L!9SVM_j(ac^%m4 z?HtSATh2+n@qK*sAO0eqhmY%W(sNea8$zKjHl%p8Y6q&ZqsS#GYS8nSO@=)V_UB<8Xw(Un>N=xgLc-sJLjH= zePnX~tB7Y-r5;1(_2l4+hsgDpC+*BG`|g0y({Ms^ldX8t;qqAKxGA$@9rQR4*?) zM(;n4?F^Dh#A%bzYsNWp42zenrRT|vh?(Dt7Smpf$5woTES`-P6|Y8%@>iqDfQD$A ze?_}iX<`8l-=v4x zyD=8qKZgD0)7NYY+*@;ta+2*)P>)VI4bCT5SKF=*a89s#L2Pn0xZ{RbenRgrdT^m5 zt|Gg4e*8Ca?t?#%Eti@1cNqWu{7+)vOMi^*{tGz5@DHna%0FLpG|5IGTcW7Wf(Ke5PTw6go^Gj9S;@ zd@JSN=Uba+?V9ts<)tgv+JF21t0T1k@?zw-nBx+YAERG@9+2ZJ#;5Nf&Q*xttWUe? z#u;Q}AH2M!$+qez+XGCSZSHRbSeQ9CeP}sy<{rft+C0-M#s6bA+Iz4n<;Ua}kKs4@ z_yKa2%l<$>FUHbNJ5w zR4>>Ub=K}pDc_-;SLVeXGMHb6|B&qeCa!~fqQ0z!OQjEB-xd7^?Z4cEv0RID+4SX= z`^uegqR6c{TO`?i_?L@`kM#S?(QC#SlefWxVn37CE{(15G~^>ss9H{(0}rU;LuB&B zWcQoqA+x-0UW8Bo%%SjoPOm-DbjV3${6OR&>rJuOIemEDYi~5^vpbsf+8;UHwm0ep zbOL&z>F~3W)Bk8R9egBmx@?H10}e&=$uCAu*Vj-BISPN@dBN5PIiIVr{$1q%L5$t`7J0%?;RXLVad@0l=A3bJ2=ZUdgF7$O zzQ*zdYmEzx3Ct7VHzaHUo=!17MbVKDqVVwh^gN_i0{(6lc)==kg}A%3f|Yl%Hs#;` zJ}0R;u*djDaDVf2%B0xb6?DV4t3Qp>1rKBL40UKJ^ICqc4luTr$6{TY__h2W^@2FK&wW3zdV6^) z|K{wSm7~4XZ;%sg{B1m7ZBOMs>udJJCgK47W$mIow9mrTY z=Q0P`R}Yl$Cf32`s{>}$*Cjn-9dS8%?u6TMAB^?0e!tjfuDE_Rcp&$~@ARL-@#M7Jc5$+`a zA*btBu!6T^81jGVNB{7@jQ?dZLHR+68-NVT)f4YG1{k;V4dnj~YUMsi^#gK-_5Tke z_ipbZU&i=B9gyL};0q8#>(e{yQ{Jt$HnWHatiM&4xR#fz?N?Wb+bLUOZrS=f=Z4v5 zSiH^H{{Z^M?GJt9&!cAl@5iL_mt%JI8?pQN4`bhH?DpQzqc=Kn*o0eAIsa~~-}AjV zdh?H>c*YAcZ`Fh7+#i2;!7EXF==)KB0o-!a2T?Kal_;rtCmJ67MdB;gKKNPk@9pDk zjiLI;T!i|_7{K@HDQgHl&Xd2Bf~3ByAEjkiUnTzGw6eE{uGA>I<6w7 z06*-zH*z|yi5zN!h7}b2R`RbNIEwt~+gmSazwbF$zQ9hupL!2F!pyu< zYVjKV0DS^|hy8Hm<=~6g)q<04L~flWS#;{RJ09z}I@)yM{^g9s5)X{W z+fXahd1kclGC!W^BwuR`%Yb;SRTUh-bc)`VLi)A?1_E$oV&C6`kB}UE?>)H?TdD^`s|@p7c&FDSfAQ_yuB&(1LWpu z|HdLa%7rnmJU8=X1Ll?{d_YdJIHLZqxZE`SU2EfvaZ|5ak948xxd!> z4n*!;r`l$0x^>Ojx#0RKW0A8_%<{CRz`EZ`7JU$FcM7b*MZekmBk>)$Uh99d@xMNh zI?()}9OA?s0MoO6*?K0qR=tYp`wzFtnm&6P6|7sDdVJd}NG!%#Uve$gd*&XLdut9S z5+_XKJo1PmrtzITsoWCknHSPCqyMwm>oeHpEBN(Cq8V6Tj&hFOj&{qDPh_=IP2_Y~ z647QM@?Op73nJ&KS?PUFo2n$^`u1*<({UxgT^iALG5TR;#H0C<^W+Rs1O=o~(Mi)F}74e^0Kg4=0R#n; z^*7?!spsR?oeyKtiW@Ou((Y*c^iq1aS4FpeTch9bL(#5l9r42c7&!TS^q6smnn$n! z&c$QO@zE!-_UC%C|MWQEoK6t;9N-$&5%v`Fnw0-RcMA^zVPtj*`d8B}83&H}LS zfAagWJwJi4hSj(~N2BFXu@d(AuR+FiUd*@_vnnT!x}sQ!bF#`T*n9 z2gFWtpTzUc?OVU&+);VH?ege}0yb-&Q5|XRh2N`>5?_KGpqycQDU9Iv1G$b7UchWcX7Kl;x(-b6z|Ugo7S6Ngvlu-7Zj{XbAjXtYQ@!-l z7(V&+C|~kPjG6jYlr8)qhUDLirCY)H5B@Bc*Zm}B*D%lHcABCOGrw&lwi@9if(`g^Yu8r5_4#`=Ok0Zu!t&a7-#=hA+ zxc)%m(Q{nCR~MM8k{4jyVE-Lu(>~qy1a&5O_X2wVP8r8*dUDy1d?NgJJ|6&B2q<5X7}E4esR z&6(x$Ca0haNAiE%dRWPK!KZ1aw5p zsptgsLo@mhp;wxK3q&h&5IyT-%-lV3@rS>?{HI(1F}-$OKi>R)ws%N5cwHHKpn}-F z3cmkJa(&hUiwB4UrdR;o;cpWrhz`l>0CNM%x;4ma?z{XX=>s`E+Sx{6D4B`*eH2f&$tf9uBhI+=epGAJ<8*$(YvB>2=irWu= z89Pq@G%mkPe*Y}9*3bPs`i!^}Yxn#(X02qd(#9`h+nqm*W9+Meeaan>Yh>>N`<_^5 z?7T*GQl{>YT3>XO*Q)PhPE!BHSV{S}2Dh_3xdEBJd)DDPgIoOFd7auGxi0zvgJxxV zVfma{i4yM1@MDRl7 zBlW@Y_ngyH=rv_Fga5UTF~r>F)K-2n3exE^h7TV!3CSI#mN!iki`PD z`@U8;48{+W_ctEj#Tm$b&@1Yr_UN28!~4ZkM=m9k$6GG zKH{1s=;&NxoTc!93W#&^%IS|(I~RL>2wV<3++ia+aT^PMd@KC?7Rc};Q;=hHKnvtp zUGT`H%xBGWBbtp!zI`-D4?K!}f3%SGxX5{o-?SKsj^Oi0ko)G?|K>x{3FwX%qtOA# zd(-}`@gcfw$>@|$buqMjGxq;)e{1`%{AaO1YwfMs)y7#bXfCe;?9P1NbTF@Z#J#KV zf1MLx%&gxa9;h#H1R3%72gC%ir`i0VJb?{h0_p+z^Y#jGj;J=*zCOyga_`JUdyXbw z1X(lZC-<%aKS7>Q9lrM#XY{}WT+2MJ8fp<1ouKw`53|zhK93~_eh{_i|6Qy+0xo!p zz6U$M8}s-69(^Ici0UhF2;mTI;P>vs+~aOI3}O)G7wX{y8o$^VIn^d}9_f6DPt-l; z1>{O>OZY}crvWYyZ&#+=Uv>t#wd9@id8UycpL5q;!2pa!<<*I)$)|U&rgekX_1I%m zeor@Kq6c<4$%gWbo$P>aQIE(iR&S)9)-@S_SnN@szc=!yjrG}9cC~fsna}MTt)5|S zJ+f`zpH}q$buH&l?!Pfhs?{OKXAOY)3-b*6>#0Ug`#+#Z(p9Z`cjYQ-%Xf52O z#q>1n$#3kLs}JFIDsx_|I>`OVfii!PS*R88HQ#mQ9$1rWJYbAq&!h2h@$3a;KSFc# z;-dOF3Fim%5bqEN5brYw`Bfi4^nf_v3UHOhM|Q%&#D{|4m-Hb23+;W<@WI3}jsKN<>y%6A8D##^UM;13*BgvwIPyPc{dDC2AXpxDxD9@Imp%CY z>#+5Uk?(OVMaV32-4t2ZA85{dKW~aWH>HPIQ{=oExRmJx_SXLW#fQhu>`Lc#=)8Fhv6fOM^J|hZ$%$$dif`@i5i7wdb$7 zL*+lk|JZ%)zZjssM^c>*GT&|_w%!H5yA5{kDQsR#WViJoX8vKv?F(j((zP+kGt}zX zyVvJio}HMNG4KHL2HH~naclP4v#(^s8~MKlwJQ?uz})#_FpAun%p=8KW@dYp;D_74 zgr0uL=V*NBOid%PHZpBraAO;nVZ=Mm+c37VM&EuNVs>JcekV__V&9gO^Uun>>#Q!& z?vDlsNo(|hx}bbFIOm}qQNjJTm%>0WjJ}n`JmgL7cPQ`Ao@C;K72tpNMw+!3T!dv> z9XJUw&7}3zZ1F#mD^Lpma^_Cz?~m64?5|6em zil!}#@b|%5de4ZK9VbM~r|IiHsD%A2iWV*LS8{8jb(f;(Ja~C@AGbTYj#wH`^x25~ zZ;XroO7=gC1tdI>XFk(&_t*zx6>IzQ)3O+bhfidG*I>cKG%Oe*m8VeS`d(bKHwQs3pd6j$j?S#rgo{ zTRHa{l=~$6jn`uzql3gd&S~CBK0@7S9N^zT{BLvQ`q$P0nERK<=S*s6Q?CKzlXqwR zjdP`!gR?I=x+me~#`xx`tO+pAckTRJc{uX;wTa2M)`vhAm4AIKXiY-)~_!mx9Hj$ zf8%@e64ptYFHrZWFYKEjA8If-gz{Ipe{;(5nHw>Dcs|B1I2m1s zF~6vMTMR7T5Pc_Lw<~wY@R>*A$xapVOyS1pJakEns;VdV`Ev9xTF0EI`WUx(U)s-r zqE)f@(#J8nYA^YXTO8*Kzo$og1O0)j55)N&{LR0L|NoWzYx8*Sm0|sOZMS&0Hs9VM z%D;>K#Fmib7b|e~p7O2_kaPg+e~Je({d@EU?E7J!QJvvDPkRPx|CKxEq27HHO#0(AZR z4KJ{c7(`z1UUY#mg*+o;dt(lJ`zZ4s*H}n@B;lgyp~Q7S7kR#W*}r-~&Vzq))5ZUt zxz~qS-I)^Q$kLoca9dcGkYlzlofvx&T(U{)mZimdQ)PZEzN^cq_%kItGuX8_5K z@4~DwWnWp;ChPMjd#Fqx5Ap%+jUzYEI)H>_vFLL;L00GuwQd*QI|h2B`nsDHr~4NAmyl{}FSWabRnzjT{mi_8{Xy&-VBaL`DeVO=e^{FVRf%qfPD?C$eYXp?-(+rA{Je}6AR9LFZrPRc+Qq#3s+qKPMTN0>Xxs+6-&>( z8`W1oiG3gZS#0HbTYCPzSbp(c{8;)`?70`qF46;d_Y2Htxk3E;daQZwQ+!n9f|z&N zg?D1b)sL_pUyD^Yza2G~-orPAUwh}XsJ{3fv#9=nei+QV{`N27I^O%WGeCb;hJMr6 zSsk#SYZS*5?>6T>{o-c{3vd>(eMOfttJnTuyE%Vje=#-X<{0vtjR`VbA-Mu@2H^^r zN7KKrM+TGc@Ud|R^4+KdJa&>niALsnP(q+U1S!_d`(D+FI zNc?XIKDcu{dWfOJ@$ngShONH8eQwMLrk+#y@oDBy!N`O?>-$?9qwN&8m!qQWIs@Ce z^ve6wVgUFQ_S3OvmwA49^2z6Ilz|iz6A$?Ok3`<&2Pua>!{*ntWy-Ou!A-$G!3OlW9^b; zfo)Ea13Q_XRgT5B4amZ8D&PMzzsu?X^Mc0j=J4jh;h9biuQ`EoFu_@uGk$>Bp7?pf z1o0h?D#KnAa-Gowa0Zd1!yn2Spcf$Ap~G+o#0!*t{eSP5Iv}Gz{B7pF=X#p!zCeCJ zxjp*v|Cw;R!ynMQli%8#&%WKxG4Ar9TT|^Y@1F##Yd4zM9XwF~-T3{zC?(+^2ayd*+FQD+9>} zV!u*7FrVoki_Q7G%bU{{YtNI7<$LGbPhJndb+I```v0LDw)f0jdV!4~|J1Q%*#B!R=ir>3$@uT1;UgIT>;EhF<}l0`8i$BQnuieMQwMfJ z2O6hz4R`8tcwX!FhY`T5h07@Pt%WfzuvgG(;skvK{bc1Ns{=B6 zKpWpEN9czm>WD@jVJ2?K`VIe2`Oo?g;tKA^THX{3s3-Wn{6V>c&ggiE+<*8d&KvuO zG@r{kea&qsd4RUE+khS#k5zQ;M0S`=h1$2<- zn0jLtk&DMyNi~MpU-@*_5*Y_r?{7a5{r|Dl9(v5h$M;5M-MYk`5x3BP>42Y-&F`rL zw4>%N{mfj3*Y3UP!m-Q^dasNv`b{rNGOzqks%1VBwpuQ-_XJudi zU%4N-8okH)THhdtu@GISpKl+tUdVS3dZcH35^@pfB42CkJr8}Gl!IV9&(TG^vrl;e z_#t!0@ByrI$bHp(wq4IOgJ2^?OV|)Q? zV&wViBd90T7y9-|wv?sD{UmwDc8U*V7e8}5eTA&QkhXIhj{6msh|is^JhEvN(ZoQ<~;v{;vb{&hqWix`)e~&zRTyDXGStj;ma_$OV-1H$Z!hp71w5$MS9TGt@ze zk3dbZdH+@{PY$GCIp>h(al#)^4vZJ<`)B>2F@`yJ`T25wyVDCKIy}MaOwH1QBfFAZ zdVuIJS8^!P4G96-7M)($TNa~ES! zzLj^EcPS=Fujf#+QOlF0|R#H2-AekbMsD;XY8s(5xTg{m}>4$MCys&oVg;_AnEpuVOJz zgwE%YH=vA~?^Dj?`j}5}kvphNyVQfFi3f-UxbGzM2^+{@Y~~HD6|gpM9h^Jk5BF^^ zQD++1XWTkr^MMWQ`|PKG8dr$#o#FQ^oMPvA9|tG#dpSSyn%0r`vu}wxd~jfxe2hP2!dE4)kr5ePu77dtq#! zy>4Y)y_9*MsR2^&c`h#I1N9s1HR5~gfvtHo?=YBn#@c9ky?r@untOoWQy2UH5F_!J z#!fEQA~;vXzC!9l`!jhDCNHV|owfg29gvL$l$mT^U?H-Y;Rk>TBwUa=XBR)CuI775 zUggSK6DSv0?u@c*J)ycm**14zp5NTSey{^|g>%NV(dOB$xwG!pTEaQ@EF{*Lb`A{E z{=%$hUj97Q7Fs8~2A(7 z`Bo1o?@8u)t*nb{ii5hHIS2KIeIaVKAzrCa@p(Ig)r~LM?N8H&XA*=egV`@54ytjPJdFURNHRp4@6Mf7brq z>v!ge>oJ?i^|6ij!TVZ3Ewb;2r)$A)Sc5*`I_y#4Z$@*hT<(e2>hVT^6QpGg*Ur8? zhHH;GX(xG*ZPhV~bI;rZ_zT?Y;=Su*{+R>OZB|hfFW>$)yVL?Af7S+RlkG8JZJl+&&gk1}jt{xF z$G_WJJFK5E_4KDP={P+`kA4^v=}%BdPZ4_zmz*RY0Z&;hvI-rsknI<7+y&2mH|Bv? z>XZ2U3VM&JKYU$9e*$%a^~hT}zPd{UZOA-Q@_UJ-AbmMt8?!$e14%u_}xaoZR_l{QW+rmYq9G%x5v&%EoJ2t-dJiQjT_d2=_ z1iN5g?K!Wf-R7(PQX|23ZMt`fuYSXCGxvjY;`2`ITMr zcdxH2I4Ae5Phj1%@r8YmwxNft^OL8n&!W7qrFO|$X0Z+Rk@Zpk|KIP{9q2oBHmAP2e!4n9o1S`ppa;woiV@DHr^s}4K)E?X zxx;BL*H9pWd6We<@N{CXYe=r_1bEE{8F}^asv53Mn5rT3lw4VeLd;e$LaH8 z_E&O>{Ug`Yj0?abD_C5+WaEXY=z&tUQU1%&Px=FL8TADg5yvRo#s%sjucaEDvJ=F8J>s&aTG* literal 0 HcmV?d00001 diff --git a/Demos/DX11ClothDemo/Media/Tiny/tiny.sdkmesh b/Demos/DX11ClothDemo/Media/Tiny/tiny.sdkmesh new file mode 100644 index 0000000000000000000000000000000000000000..c4a14121112c3c486da7ce5b07307ad42245e6f8 GIT binary patch literal 231612 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 LCZ53m{{;RIIudD- literal 0 HcmV?d00001 diff --git a/Demos/DX11ClothDemo/Media/Tiny/tiny.x b/Demos/DX11ClothDemo/Media/Tiny/tiny.x new file mode 100644 index 0000000..17f8d08 --- /dev/null +++ b/Demos/DX11ClothDemo/Media/Tiny/tiny.x @@ -0,0 +1,53984 @@ +xof 0303txt 0032 +template XSkinMeshHeader { + <3cf169ce-ff7c-44ab-93c0-f78f62d172e2> + WORD nMaxSkinWeightsPerVertex; + WORD nMaxSkinWeightsPerFace; + WORD nBones; +} + +template VertexDuplicationIndices { + + DWORD nIndices; + DWORD nOriginalVertices; + array DWORD indices[nIndices]; +} + +template SkinWeights { + <6f0d123b-bad2-4167-a0d0-80224f25fabb> + STRING transformNodeName; + DWORD nWeights; + array DWORD vertexIndices[nWeights]; + array FLOAT weights[nWeights]; + Matrix4x4 matrixOffset; +} + + +Frame Scene_Root { + + + FrameTransformMatrix { + 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000;; + } + + Frame body { + + + FrameTransformMatrix { + 1.278853,0.000000,-0.000000,0.000000,0.000000,0.000000,1.123165,0.000000,0.000000,-1.470235,0.000000,0.000000,0.135977,2.027985,133.967667,1.000000;; + } + + Frame { + + + FrameTransformMatrix { + 1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,-0.142114,0.000023,-49.556850,1.000000;; + } + + Mesh { + 4432; + -34.720058;-12.484819;48.088928;, + -25.565304;-9.924385;26.239328;, + -34.612186;-1.674418;34.789925;, + 0.141491;7.622670;25.743210;, + -34.612175;17.843525;39.827816;, + -9.608727;27.597115;38.148296;, + -9.798330;-0.357897;65.599075;, + -34.612179;8.990501;57.540577;, + 0.077733;21.348866;52.164078;, + -11.429913;16.434713;56.577648;, + 0.141490;12.205804;59.792637;, + -17.647087;-15.421692;74.962234;, + 0.139748;-15.745451;70.035706;, + -28.078594;-4.899444;63.550846;, + 0.141491;-27.796947;71.486557;, + -23.021046;8.957323;28.295084;, + 0.141491;-9.487318;27.256748;, + 0.141491;-26.664299;32.989830;, + -11.193695;-27.720463;30.196030;, + -20.920319;-26.441757;33.507900;, + -23.021046;22.545492;38.817097;, + -4.681036;23.543238;52.237732;, + -7.199147;18.381388;29.309721;, + -31.657711;-16.623283;68.586205;, + -7.168321;-28.208626;74.147346;, + -27.854467;-30.229647;72.082443;, + -16.966074;-26.227253;76.131516;, + -33.277031;-27.463528;63.505905;, + -31.930122;-26.942392;51.688797;, + -26.290180;-21.425268;74.259827;, + -32.341526;-14.948000;58.484459;, + -14.724298;0.438756;65.826607;, + -17.688755;-53.253067;77.227638;, + -30.976030;-51.338348;55.580246;, + 0.141491;-50.060425;24.873173;, + -22.127073;-50.465675;31.947027;, + -24.287395;-54.514771;54.652374;, + 0.141374;-56.516960;39.995022;, + 0.141491;-37.227283;70.123970;, + -29.140186;-40.740757;54.994888;, + -18.598015;-63.628139;61.096786;, + -18.580341;-63.659996;42.089684;, + 0.141491;-28.374607;32.989838;, + -11.193696;-29.430769;30.196033;, + -20.920321;-28.152065;33.507904;, + -25.494289;-63.762321;51.551601;, + 0.102538;-63.445549;68.379417;, + 0.102538;-63.638348;37.841175;, + -16.503817;-36.463478;72.030708;, + -24.298424;-39.992043;64.994545;, + -14.590791;-42.557045;68.336487;, + -26.760902;-31.939959;72.082443;, + -16.966076;-27.937576;75.155312;, + -32.183464;-29.173838;63.505913;, + -31.930124;-28.652702;51.688805;, + -19.449144;-51.888283;62.452682;, + -6.438459;-49.943382;70.242874;, + 0.141491;-49.688911;68.965103;, + 0.141491;-29.773867;26.064960;, + -12.711588;-29.992414;25.556252;, + -23.846188;-30.195030;29.093178;, + -32.848045;-32.305534;51.981480;, + -30.142681;-11.598551;37.311020;, + -28.347116;-31.250282;40.537331;, + -26.551552;-50.902012;43.763638;, + -24.332394;-52.295708;66.403946;, + -26.425222;-28.402384;42.598354;, + -32.056793;-28.913269;57.597359;, + -34.612183;9.271671;35.005108;, + -34.612183;13.697768;49.116459;, + -34.666122;-2.091087;56.933292;, + -34.666122;-7.473567;40.417480;, + -33.602604;-10.886051;47.766304;, + -33.245544;-1.592087;55.511299;, + -33.454399;8.516764;56.378914;, + -33.377022;12.971798;48.765106;, + -33.285355;-1.230055;35.845985;, + -33.422455;-6.066209;41.124596;, + -33.326355;16.538502;40.337154;, + -33.380333;8.824398;35.941063;, + 0.141491;-46.403996;39.221611;, + -5.525791;-46.932079;37.824707;, + -10.389103;-46.292725;39.480644;, + -20.399273;-44.550671;45.133575;, + -24.509207;-50.845016;55.877068;, + 0.141491;17.711647;27.783634;, + 0.077734;27.263643;33.720470;, + -5.109205;27.415857;34.161194;, + -9.139874;26.594124;45.452682;, + 0.141491;22.863007;31.002354;, + -6.363874;23.153360;30.623175;, + -9.748887;22.893982;32.226307;, + -13.398946;24.794630;34.246376;, + -16.294899;25.090145;38.449425;, + -18.686239;24.355274;46.119999;, + -13.692654;24.681557;52.324207;, + -8.242743;20.971973;54.090229;, + -3.765221;20.286398;55.975685;, + 0.141491;18.192966;54.231785;, + -10.778057;22.307632;52.895199;, + -8.655515;-23.637917;29.537901;, + -19.722260;-1.585354;65.224693;, + -20.110298;5.311386;60.448208;, + -21.278301;13.060091;57.191551;, + -19.918121;19.050785;53.541157;, + -15.815639;16.328318;56.204815;, + -10.153260;28.853861;37.612610;, + -11.867444;17.503666;57.664883;, + -15.160084;1.466462;66.822762;, + 0.141491;28.542030;33.277145;, + -5.618525;28.677891;33.713886;, + -9.625071;27.664139;46.092670;, + 0.141491;24.137672;30.525173;, + -6.801406;24.428030;30.145996;, + -10.186419;24.168652;31.749128;, + -13.836477;26.069300;33.769196;, + -16.732431;26.364815;37.972244;, + -19.123772;25.424227;46.716579;, + -11.215589;23.376585;53.491779;, + -20.159792;-0.516401;65.821274;, + -20.547831;6.380339;61.044788;, + -21.715834;14.129044;57.788132;, + -20.355654;20.119738;54.137737;, + -16.253172;17.397270;56.801395;, + -29.388227;-40.601273;63.974194;, + -30.997221;-35.165527;63.780437;, + -29.736418;-23.496841;70.352409;, + -30.377008;-28.942865;68.092697;, + -32.118473;-39.484562;59.515316;, + -29.846169;-43.697968;61.553284;, + -28.709795;-30.444099;72.554062;, + -30.243555;-40.815727;64.445816;, + -31.852549;-35.379982;64.252060;, + -30.591745;-23.711294;70.824028;, + -31.232336;-29.157318;68.564316;, + -32.973801;-39.699017;59.986935;, + -30.701496;-43.912422;62.024902;, + 35.004288;-12.484816;48.088928;, + 25.849533;-9.924379;26.239330;, + 34.896416;-1.674414;34.789925;, + 34.896404;17.843529;39.827820;, + 9.931857;27.639982;38.133949;, + 10.079079;-0.357885;66.089737;, + 34.896408;8.990503;57.540577;, + 11.714142;16.434715;57.068302;, + 17.931316;-15.421690;74.962234;, + 28.362823;-4.899441;63.550846;, + 23.305275;8.957328;28.295086;, + 11.477924;-27.720457;30.196030;, + 21.204548;-26.441751;33.507900;, + 23.305275;22.545494;38.817101;, + 4.827426;23.522514;52.188004;, + 7.483376;18.381392;29.309723;, + 31.941940;-16.623281;68.586205;, + 7.452550;-28.208622;74.147346;, + 28.138697;-30.229643;72.082443;, + 17.250303;-26.227251;76.131516;, + 33.561260;-27.463524;63.505905;, + 32.214352;-26.942389;51.688797;, + 26.574409;-21.425266;74.259827;, + 32.625755;-14.947996;58.484459;, + 15.005043;0.438756;66.317261;, + 17.972984;-53.253063;77.227638;, + 31.260260;-51.338341;55.580242;, + 22.411303;-50.465668;31.947027;, + 24.562241;-54.514763;54.652370;, + 29.424416;-40.740753;54.994888;, + 18.770283;-63.633057;61.106705;, + 18.773201;-63.677704;42.028572;, + 11.477925;-29.430763;30.196033;, + 21.204550;-28.152060;33.507904;, + 25.705898;-63.638660;51.490501;, + 16.788046;-36.463474;72.030708;, + 24.582653;-39.992039;64.994545;, + 14.875020;-42.557041;68.336487;, + 27.045132;-31.939955;72.082443;, + 17.250305;-27.937574;75.155312;, + 32.467693;-29.173834;63.505913;, + 32.214352;-28.652699;51.688805;, + 19.723988;-51.888283;62.452682;, + 6.722688;-49.943378;70.242874;, + 12.995817;-29.992407;25.556252;, + 24.130417;-30.195024;29.093178;, + 33.132275;-32.305531;51.981480;, + 30.426910;-11.598546;37.311020;, + 28.631346;-31.250277;40.537331;, + 26.835781;-50.902004;43.763638;, + 24.616623;-52.295704;66.403946;, + 26.709452;-28.402378;42.598354;, + 32.341022;-28.913265;57.597359;, + 34.896412;9.271675;35.005108;, + 34.896412;13.697771;49.116459;, + 34.950352;-2.091084;56.933292;, + 34.950352;-7.473563;40.417480;, + 33.931534;-10.798729;47.691635;, + 33.266479;-1.659648;55.141335;, + 33.733215;8.483885;56.324486;, + 33.578400;13.114620;48.755165;, + 33.395126;-1.314395;35.941048;, + 33.696419;-6.417687;40.866890;, + 33.477127;16.479158;40.343475;, + 33.569466;8.843540;35.935562;, + 5.810019;-46.932072;37.824707;, + 10.673332;-46.292717;39.480644;, + 20.683502;-44.550663;45.133575;, + 24.793436;-50.845009;55.877064;, + 5.227813;27.441788;34.143456;, + 9.646603;26.610264;45.446602;, + 6.648103;23.153364;30.623177;, + 10.033116;22.893986;32.226311;, + 13.683175;24.794634;34.246380;, + 16.579128;25.090147;38.449429;, + 18.970469;24.355276;46.119999;, + 13.976883;24.681559;52.324207;, + 8.526972;20.971975;54.090229;, + 4.049450;20.286400;55.975685;, + 11.062286;22.307634;52.895199;, + 8.939744;-23.637911;29.537901;, + 20.006489;-1.585352;65.224693;, + 20.394527;5.311388;60.448208;, + 21.562531;13.060093;57.191551;, + 20.202351;19.050787;53.541157;, + 16.099869;16.328320;56.204815;, + 10.437490;28.853863;37.612614;, + 12.151673;17.503668;57.664883;, + 15.444313;1.466464;66.822762;, + 5.902754;28.677893;33.713890;, + 9.909300;27.664141;46.092674;, + 7.085635;24.428034;30.145998;, + 10.470648;24.168655;31.749130;, + 14.120707;26.069304;33.769199;, + 17.016661;26.364817;37.972248;, + 19.408001;25.424229;46.716579;, + 11.499818;23.376587;53.491779;, + 20.444021;-0.516399;65.821274;, + 20.832060;6.380341;61.044788;, + 22.000063;14.129045;57.788132;, + 20.639883;20.119740;54.137737;, + 16.537401;17.397272;56.801395;, + 29.672457;-40.601269;63.974190;, + 31.281450;-35.165524;63.780437;, + 30.020647;-23.496838;70.352409;, + 30.661238;-28.942862;68.092697;, + 32.402702;-39.484558;59.515316;, + 30.130398;-43.697964;61.553280;, + 28.994024;-30.444096;72.554062;, + 30.527784;-40.815723;64.445816;, + 32.136776;-35.379978;64.252060;, + 30.875975;-23.711290;70.824028;, + 31.516565;-29.157314;68.564316;, + 33.258030;-39.699013;59.986935;, + 30.985725;-43.912418;62.024899;, + 0.100870;-93.627769;27.356903;, + 0.100870;-80.794510;68.288246;, + -41.760616;-103.151527;46.673916;, + -24.713787;-129.635101;24.771605;, + -18.089975;-112.633553;62.624924;, + 0.100870;-118.350113;30.024460;, + -5.798617;-124.775063;56.960815;, + -25.173319;-90.214371;26.265825;, + -37.889961;-84.783730;46.673920;, + -4.658672;-143.854736;42.160900;, + -33.648396;-119.084198;29.032738;, + -19.782078;-86.427551;62.399220;, + 0.100870;-105.624802;63.766800;, + -33.875122;-127.515556;35.677757;, + -41.014412;-121.305328;41.175835;, + -15.635758;-212.122009;56.766579;, + -11.671675;-229.887054;44.415508;, + -11.967894;-201.991714;48.101704;, + -33.998722;-220.566071;61.510651;, + -39.528782;-322.910553;59.808899;, + -23.342522;-325.221313;36.655556;, + -35.048260;-213.572937;32.058167;, + -43.113548;-194.904678;46.172501;, + -43.619999;-206.619293;50.933479;, + -46.585148;-323.985016;35.078949;, + -34.708954;-324.151184;32.796345;, + -44.766525;-223.910660;41.391571;, + -13.351915;-168.910248;60.740967;, + -8.177140;-173.738678;44.589825;, + -22.042976;-120.057648;62.105083;, + -30.082495;-176.538712;60.086678;, + -23.352434;-144.066956;25.433430;, + -38.057816;-164.488510;57.655933;, + -25.025139;-183.704147;31.840212;, + -41.240711;-158.109726;38.305466;, + -31.089090;-190.013657;63.028923;, + -27.205957;-198.419052;34.729908;, + -35.127117;-120.041656;57.534679;, + -36.447479;-347.590393;81.989037;, + -32.971939;-348.840668;75.068268;, + -30.483822;-349.513580;64.542366;, + -30.277090;-349.285034;45.291451;, + -30.731056;-349.140869;32.597919;, + -50.995792;-347.566376;80.111809;, + -54.063526;-348.805878;72.346741;, + -53.720398;-349.475220;61.544106;, + -49.480873;-349.253357;42.813530;, + -44.998409;-349.114563;30.769142;, + -37.752792;-344.579865;81.882141;, + -33.638000;-341.897522;75.396339;, + -32.718132;-336.016754;68.786903;, + -25.375702;-326.803925;43.166012;, + -50.401588;-344.387238;80.484764;, + -53.600422;-344.479889;72.777603;, + -52.430077;-341.348145;62.750374;, + -52.006966;-325.347748;41.525673;, + -37.431126;-348.022339;28.784142;, + -30.811893;-349.229279;40.184383;, + -47.579365;-349.201599;38.020824;, + -23.738852;-160.860565;27.560469;, + -32.426979;-277.766174;32.203541;, + -24.943554;-117.940918;21.795742;, + -27.146837;-312.724365;57.102558;, + -41.869755;-312.813507;56.621277;, + -19.773428;-311.714844;51.152798;, + -17.516390;-311.220673;43.257233;, + -53.350098;-311.978485;48.287319;, + -24.548374;-311.052429;38.861855;, + -49.043320;-311.481262;40.787697;, + -36.779060;-311.947937;34.579979;, + -13.444867;-241.724686;43.812698;, + -18.083738;-235.404388;32.990765;, + -39.270157;-235.407135;32.086258;, + -18.709482;-278.846039;51.472935;, + -47.800510;-278.654022;48.696930;, + -15.278575;-278.076538;41.723305;, + -42.724228;-277.794373;38.664391;, + -47.843460;-278.215302;43.605659;, + -37.205242;-278.835236;54.105011;, + -21.722435;-277.300140;35.149902;, + -42.656788;-120.929993;49.355263;, + -17.315336;-184.822891;56.888432;, + -37.002441;-178.638748;55.923828;, + -14.539805;-213.740479;34.164742;, + -28.676964;-235.063950;29.100901;, + -26.290127;-159.034851;62.359310;, + -44.822357;-162.486374;47.417561;, + -26.283358;-192.193878;33.507416;, + -27.280354;-203.100555;31.769535;, + -26.421682;-194.991638;31.950752;, + -25.691517;-188.165451;31.257717;, + -32.553154;-207.822937;62.845280;, + -38.257362;-201.972275;59.263458;, + -23.653395;-201.105835;63.411591;, + -25.556084;-324.127594;55.527039;, + -37.508007;-327.823730;63.943375;, + -48.660114;-323.846619;52.634663;, + -43.124073;-327.569916;63.163582;, + -46.985233;-330.924652;60.877213;, + -47.738998;-332.348511;57.905354;, + -48.218380;-333.043976;53.745155;, + -46.926067;-335.870056;46.077358;, + -46.011299;-336.928101;39.876133;, + -39.092888;-333.629852;32.004887;, + -42.781075;-334.302216;33.467194;, + -32.159611;-328.701721;61.163334;, + -32.027699;-330.586823;57.891068;, + -30.829683;-335.353180;51.935188;, + -30.289175;-336.679779;37.674358;, + -33.346500;-333.002716;32.172970;, + -30.620396;-337.228912;46.045479;, + -30.907063;-337.423279;41.478359;, + -30.290890;-334.903290;34.539791;, + -36.497189;-333.552704;31.073109;, + -44.659866;-335.766113;36.478382;, + -37.186310;-327.136566;64.882172;, + -43.760216;-326.861603;63.886238;, + -48.019054;-330.368195;61.125313;, + -48.864738;-331.923981;57.957317;, + -49.377052;-332.709412;53.701771;, + -48.091980;-335.719604;45.783157;, + -47.151276;-336.782074;39.490070;, + -39.525562;-333.437286;30.882923;, + -43.645668;-334.103790;32.636833;, + -31.204782;-328.177948;61.712044;, + -30.816942;-330.532898;57.981380;, + -29.621853;-335.235016;52.022976;, + -29.081070;-336.669037;37.797260;, + -32.739624;-332.828003;31.129665;, + -29.406822;-337.163391;46.021709;, + -29.694448;-337.386993;41.543434;, + -29.145948;-334.835358;34.136993;, + -36.550041;-333.356628;29.870857;, + -45.758202;-335.587708;35.996567;, + -45.427898;-130.595413;48.340775;, + -42.336990;-130.488724;54.945263;, + -37.678047;-130.227783;58.228161;, + -45.523903;-130.013565;42.878948;, + -41.142269;-130.155960;39.554146;, + -24.386381;-143.741119;62.231689;, + -32.621887;-188.625381;36.814716;, + -11.541974;-184.862228;45.883656;, + -41.620197;-179.552460;46.748608;, + -39.826946;-174.615158;38.212673;, + -43.535854;-120.777649;40.070557;, + -22.938877;-119.976494;64.392769;, + -30.902096;-176.652710;61.614151;, + -42.871780;-158.253891;37.723408;, + -36.567158;-119.911232;59.557304;, + -45.200268;-120.584846;49.944744;, + -38.287941;-178.810394;57.081314;, + -27.014326;-159.047546;63.937130;, + -42.580544;-130.073517;38.311958;, + -24.975321;-143.678299;63.863117;, + -43.319576;-179.781570;47.035759;, + -41.500957;-174.797165;37.779552;, + -23.619888;-130.097656;63.516205;, + -38.861588;-164.565750;58.167274;, + -45.622833;-162.561295;47.934299;, + -46.311371;-130.569748;48.698330;, + -38.258266;-130.203033;58.985287;, + -46.929386;-129.807648;42.502537;, + -39.136471;-178.898392;57.512791;, + -43.810833;-129.927979;37.517529;, + -44.150005;-179.891830;47.497341;, + -24.121252;-130.069931;64.903618;, + -43.136353;-130.426819;55.607552;, + -47.307560;-130.516037;48.990032;, + -38.841251;-130.165939;59.846836;, + 0.100870;-113.035980;52.159779;, + -42.175369;-334.770050;70.948944;, + -47.093388;-334.957916;67.363968;, + -35.253540;-336.022400;70.615288;, + -50.392654;-342.841522;46.961720;, + -31.481352;-343.813690;66.423645;, + -14.078679;-70.624992;36.359470;, + 0.100870;-70.522980;34.969410;, + -10.657997;-70.656097;64.141533;, + 0.100870;-70.455383;68.554764;, + -20.407236;-70.663857;37.704983;, + -25.309130;-70.709183;43.680515;, + -20.123388;-70.712914;61.395264;, + -25.333038;-70.735931;56.047955;, + -29.135050;-70.748413;50.137466;, + -3.877978;-63.520813;66.895554;, + -3.855402;-70.482147;66.867348;, + -19.676884;-63.736073;61.580589;, + -19.676886;-63.736065;41.365475;, + -27.052189;-63.743755;51.457161;, + 0.100870;-63.591896;69.324707;, + 0.100870;-63.725189;37.057167;, + -14.884621;-70.698990;35.456879;, + 0.100870;-70.596962;33.974888;, + -11.246261;-70.730103;64.830460;, + 0.100870;-70.535385;69.452461;, + -21.615906;-70.737846;36.711586;, + -26.829739;-70.783180;43.067379;, + -21.313995;-70.786911;61.909431;, + -26.855167;-70.809929;56.221832;, + -30.899126;-70.822411;49.935226;, + -4.034785;-63.594818;67.636086;, + -3.998070;-70.562149;67.711349;, + 0.100870;-63.526737;69.920647;, + 0.100870;-70.464218;70.091736;, + -4.383465;-63.529644;68.232056;, + -4.359452;-70.490974;68.296936;, + -3.386524;-75.591728;67.510147;, + -2.776832;-102.840965;65.045303;, + 0.100870;-80.880516;69.142647;, + 0.100870;-105.710800;64.621178;, + -3.516490;-75.677727;68.364532;, + -2.906797;-102.926964;65.899696;, + -22.798948;-79.832886;31.235064;, + -25.056231;-101.901466;22.759089;, + -26.274025;-98.021988;61.838871;, + -12.963859;-92.037811;25.319746;, + -13.494529;-98.258217;23.341805;, + -14.609492;-108.732101;22.072079;, + -14.476962;-118.111931;22.543592;, + -14.431333;-124.958817;24.257095;, + -14.850490;-137.747299;29.875664;, + -30.438990;-82.029594;36.202908;, + -32.929981;-95.527786;32.765190;, + -12.144010;-151.520721;33.476109;, + -14.428178;-166.866211;34.299915;, + -16.716248;-179.708649;34.860874;, + -32.423717;-145.852829;29.285240;, + -35.720222;-158.855484;33.087280;, + -34.360893;-178.742081;33.996445;, + -9.632311;-81.213554;66.041458;, + -27.866913;-87.057098;57.616055;, + -14.684381;-100.398880;63.420395;, + -19.517466;-85.226929;63.991261;, + -40.065174;-318.672638;64.375366;, + -35.993942;-318.696655;64.690056;, + -31.878841;-318.817719;31.286600;, + -36.170387;-318.762360;30.458429;, + -26.210686;-317.713867;48.030136;, + -25.361750;-319.393433;40.717945;, + -24.732561;-319.150665;36.669399;, + -48.911896;-319.507538;43.118351;, + -47.664860;-317.929291;52.098011;, + -44.133797;-318.262634;57.600853;, + -27.271666;-318.973633;33.779339;, + -40.532146;-318.881866;32.536850;, + -45.276333;-318.965332;34.026871;, + -29.160122;-318.455261;60.501675;, + -26.977306;-318.229187;56.671257;, + -46.791954;-319.251740;38.820690;, + -35.793861;-302.649597;62.947060;, + -26.227007;-302.503235;60.257622;, + -43.178516;-302.253784;56.495960;, + -39.922192;-302.337189;60.689114;, + -44.792736;-300.990540;35.366993;, + -47.422535;-301.286255;40.386948;, + -36.019176;-300.612274;28.811062;, + -32.605831;-300.673798;29.757746;, + -23.851152;-301.120178;37.022240;, + -27.166359;-300.722290;30.436232;, + -23.590527;-301.899200;50.070431;, + -21.858656;-301.316620;40.265823;, + -24.232523;-302.246063;55.899723;, + -48.612350;-301.920135;51.038540;, + -41.315552;-300.854462;32.999699;, + -48.634773;-301.610474;45.850082;, + -40.141144;-255.114700;53.952099;, + -36.110058;-255.272278;56.438984;, + -23.373695;-253.775467;31.533113;, + -30.086535;-252.832504;28.237844;, + -19.459860;-253.800369;31.844227;, + -25.706972;-255.490616;61.349560;, + -17.805582;-255.126160;53.579521;, + -46.995369;-254.835419;49.536797;, + -47.021446;-254.582092;45.376308;, + -46.248730;-254.337875;41.345463;, + -43.542858;-254.140945;38.043243;, + -16.171713;-254.259338;39.300293;, + -14.507923;-254.391815;41.434330;, + -15.366711;-254.579529;44.539597;, + -40.648895;-253.837158;32.980343;, + -36.819706;-253.722290;30.997900;, + -12.445428;-224.292206;47.498665;, + -15.667706;-223.691574;37.720806;, + -18.508575;-223.414154;32.083805;, + -35.438473;-223.276321;30.279057;, + -14.603230;-224.687500;54.050613;, + -24.829622;-225.708954;61.528713;, + -15.676450;-224.947296;58.346878;, + -40.303440;-224.300476;58.010777;, + -46.628914;-224.518768;52.147167;, + -34.276493;-225.076096;60.967789;, + -25.784931;-212.417236;28.070059;, + -27.219553;-222.078049;29.233458;, + -25.575615;-279.096832;57.975468;, + -42.281010;-210.077301;42.464180;, + -12.848580;-215.346298;46.368130;, + -15.573069;-134.748444;59.732529;, + -7.157517;-152.749008;49.893009;, + -23.513350;-142.361069;25.355200;, + -5.245355;-134.035217;49.777805;, + -14.712274;-189.112885;40.448975;, + -16.435289;-199.126770;56.824585;, + 0.100870;-77.831696;33.694950;, + 0.100870;-107.150894;26.804878;, + -13.586044;-80.087227;31.121128;, + 41.958218;-103.151527;46.673912;, + 24.911388;-129.635101;24.771599;, + 18.287577;-112.633553;62.624916;, + 5.996217;-124.775055;56.960815;, + 25.370918;-90.214363;26.265820;, + 38.087563;-84.783722;46.673916;, + 4.856273;-143.854736;42.160900;, + 33.845997;-119.084190;29.032734;, + 19.979677;-86.427544;62.399212;, + 34.072723;-127.515556;35.677750;, + 41.212013;-121.305321;41.175831;, + 15.833360;-212.121994;56.766575;, + 11.869275;-229.887054;44.415504;, + 12.165494;-201.991699;48.101700;, + 34.196323;-220.566040;61.510643;, + 39.726387;-322.910522;59.808895;, + 23.540123;-325.221313;36.655552;, + 35.245861;-213.572937;32.058163;, + 43.311150;-194.904678;46.172497;, + 43.817604;-206.619293;50.933479;, + 46.782749;-323.985016;35.078949;, + 34.906559;-324.151184;32.796345;, + 44.964127;-223.910675;41.391571;, + 13.549516;-168.910248;60.740959;, + 8.374740;-173.738678;44.589821;, + 22.240578;-120.057648;62.105080;, + 30.280094;-176.538696;60.086674;, + 23.550035;-144.066940;25.433426;, + 38.255417;-164.488495;57.655930;, + 25.222740;-183.704147;31.840208;, + 41.438313;-158.109711;38.305462;, + 31.286692;-190.013657;63.028919;, + 27.403559;-198.419037;34.729908;, + 35.324718;-120.041656;57.534676;, + 36.645081;-347.590363;81.989037;, + 33.169540;-348.840668;75.068268;, + 30.681425;-349.513580;64.542366;, + 30.474693;-349.285034;45.291451;, + 30.928658;-349.140839;32.597916;, + 51.193394;-347.566376;80.111809;, + 54.261131;-348.805878;72.346741;, + 53.918003;-349.475220;61.544106;, + 49.678474;-349.253357;42.813526;, + 45.196014;-349.114563;30.769142;, + 37.950394;-344.579834;81.882141;, + 33.835602;-341.897522;75.396339;, + 32.915733;-336.016724;68.786911;, + 25.573301;-326.803894;43.166008;, + 50.599190;-344.387238;80.484764;, + 53.798027;-344.479858;72.777603;, + 52.627678;-341.348145;62.750374;, + 52.204571;-325.347748;41.525669;, + 37.628727;-348.022308;28.784140;, + 31.009497;-349.229279;40.184380;, + 47.776966;-349.201569;38.020821;, + 23.936451;-160.860550;27.560463;, + 32.624580;-277.766174;32.203537;, + 25.141153;-117.940918;21.795738;, + 27.344439;-312.724365;57.102554;, + 42.067356;-312.813507;56.621273;, + 19.971029;-311.714844;51.152798;, + 17.713989;-311.220673;43.257229;, + 53.547699;-311.978485;48.287315;, + 24.745977;-311.052429;38.861851;, + 49.240925;-311.481262;40.787693;, + 36.976662;-311.947937;34.579979;, + 13.642469;-241.724686;43.812695;, + 18.281340;-235.404388;32.990765;, + 39.467758;-235.407135;32.086258;, + 18.907082;-278.846008;51.472931;, + 47.998108;-278.654022;48.696930;, + 15.476175;-278.076508;41.723305;, + 42.921829;-277.794373;38.664387;, + 48.041061;-278.215271;43.605659;, + 37.402847;-278.835236;54.105007;, + 21.920036;-277.300110;35.149902;, + 42.854393;-120.929985;49.355259;, + 17.512936;-184.822891;56.888428;, + 37.200043;-178.638748;55.923824;, + 14.737406;-213.740463;34.164738;, + 28.874565;-235.063934;29.100899;, + 26.487728;-159.034851;62.359303;, + 45.019958;-162.486359;47.417557;, + 26.480961;-192.193863;33.507412;, + 27.477957;-203.100555;31.769531;, + 26.619284;-194.991638;31.950748;, + 25.889118;-188.165451;31.257713;, + 32.750755;-207.822937;62.845276;, + 38.454964;-201.972275;59.263454;, + 23.850996;-201.105820;63.411583;, + 25.753687;-324.127563;55.527039;, + 37.705608;-327.823700;63.943378;, + 48.857719;-323.846619;52.634659;, + 43.321674;-327.569916;63.163586;, + 47.182835;-330.924622;60.877216;, + 47.936604;-332.348511;57.905350;, + 48.415981;-333.043976;53.745152;, + 47.123669;-335.870056;46.077354;, + 46.208900;-336.928101;39.876129;, + 39.290493;-333.629852;32.004887;, + 42.978680;-334.302216;33.467194;, + 32.357216;-328.701721;61.163334;, + 32.225300;-330.586823;57.891064;, + 31.027285;-335.353180;51.935184;, + 30.486776;-336.679749;37.674358;, + 33.544102;-333.002716;32.172966;, + 30.817997;-337.228882;46.045475;, + 31.104664;-337.423279;41.478355;, + 30.488491;-334.903290;34.539787;, + 36.694790;-333.552673;31.073109;, + 44.857464;-335.766083;36.478382;, + 37.383911;-327.136536;64.882172;, + 43.957817;-326.861603;63.886242;, + 48.216656;-330.368195;61.125313;, + 49.062340;-331.923950;57.957314;, + 49.574654;-332.709381;53.701767;, + 48.289585;-335.719604;45.783157;, + 47.348877;-336.782074;39.490070;, + 39.723164;-333.437256;30.882921;, + 43.843269;-334.103760;32.636829;, + 31.402386;-328.177948;61.712044;, + 31.014545;-330.532867;57.981380;, + 29.819454;-335.234985;52.022972;, + 29.278673;-336.669006;37.797256;, + 32.937225;-332.828003;31.129665;, + 29.604424;-337.163391;46.021706;, + 29.892050;-337.386993;41.543430;, + 29.343552;-334.835358;34.136990;, + 36.747643;-333.356598;29.870857;, + 45.955803;-335.587677;35.996567;, + 45.625500;-130.595398;48.340771;, + 42.534595;-130.488724;54.945255;, + 37.875648;-130.227783;58.228153;, + 45.721504;-130.013565;42.878941;, + 41.339870;-130.155960;39.554138;, + 24.583982;-143.741119;62.231686;, + 32.819485;-188.625366;36.814716;, + 11.739574;-184.862213;45.883652;, + 41.817802;-179.552460;46.748608;, + 40.024551;-174.615143;38.212673;, + 43.733459;-120.777641;40.070549;, + 23.136478;-119.976486;64.392761;, + 31.099697;-176.652695;61.614147;, + 43.069382;-158.253876;37.723404;, + 36.764759;-119.911224;59.557301;, + 45.397869;-120.584854;49.944736;, + 38.485538;-178.810379;57.081314;, + 27.211926;-159.047531;63.937126;, + 42.778149;-130.073502;38.311954;, + 25.172922;-143.678284;63.863113;, + 43.517178;-179.781570;47.035755;, + 41.698555;-174.797165;37.779549;, + 23.817490;-130.097641;63.516201;, + 39.059189;-164.565750;58.167271;, + 45.820435;-162.561295;47.934296;, + 46.508972;-130.569733;48.698326;, + 38.455868;-130.203018;58.985283;, + 47.126987;-129.807632;42.502533;, + 39.334072;-178.898392;57.512791;, + 44.008434;-129.927979;37.517525;, + 44.347607;-179.891815;47.497337;, + 24.318851;-130.069931;64.903610;, + 43.333954;-130.426819;55.607544;, + 47.505161;-130.516037;48.990028;, + 39.038853;-130.165924;59.846832;, + 42.372971;-334.770050;70.948944;, + 47.290989;-334.957916;67.363968;, + 35.451141;-336.022369;70.615288;, + 50.590260;-342.841522;46.961720;, + 31.678953;-343.813690;66.423653;, + 14.276281;-70.624985;36.359463;, + 10.855597;-70.656097;64.141525;, + 20.604836;-70.663849;37.704975;, + 25.506731;-70.709175;43.680508;, + 20.320988;-70.712906;61.395260;, + 25.530638;-70.735931;56.047947;, + 29.332651;-70.748413;50.137463;, + 4.075578;-63.520775;66.895554;, + 4.053002;-70.482147;66.867340;, + 19.874485;-63.736065;61.580585;, + 19.874485;-63.736057;41.365467;, + 27.249788;-63.743755;51.457157;, + 15.082223;-70.698982;35.456871;, + 11.443861;-70.730095;64.830460;, + 21.813507;-70.737846;36.711578;, + 27.027336;-70.783173;43.067371;, + 21.511593;-70.786903;61.909428;, + 27.052767;-70.809921;56.221828;, + 31.096729;-70.822411;49.935223;, + 4.232385;-63.594814;67.636078;, + 4.195670;-70.562141;67.711349;, + 4.581065;-63.529640;68.232048;, + 4.557052;-70.490967;68.296928;, + 3.584123;-75.591721;67.510139;, + 2.974431;-102.840958;65.045296;, + 3.714089;-75.677727;68.364525;, + 3.104397;-102.926956;65.899689;, + 22.996550;-79.832886;31.235056;, + 25.253832;-101.901466;22.759085;, + 26.471624;-98.021980;61.838863;, + 13.161459;-92.037811;25.319742;, + 13.692128;-98.258209;23.341801;, + 14.807093;-108.732094;22.072075;, + 14.674563;-118.111923;22.543589;, + 14.628933;-124.958817;24.257090;, + 15.048090;-137.747284;29.875660;, + 30.636589;-82.029587;36.202900;, + 33.127583;-95.527786;32.765182;, + 12.341610;-151.520721;33.476105;, + 14.625778;-166.866196;34.299911;, + 16.913849;-179.708649;34.860870;, + 32.621319;-145.852814;29.285236;, + 35.917824;-158.855484;33.087276;, + 34.558495;-178.742081;33.996445;, + 9.829911;-81.213554;66.041458;, + 28.064514;-87.057091;57.616047;, + 14.881982;-100.398872;63.420387;, + 19.715067;-85.226913;63.991257;, + 40.262775;-318.672607;64.375366;, + 36.191544;-318.696625;64.690056;, + 32.076443;-318.817719;31.286600;, + 36.367989;-318.762360;30.458429;, + 26.408287;-317.713867;48.030132;, + 25.559353;-319.393433;40.717941;, + 24.930161;-319.150635;36.669395;, + 49.109501;-319.507538;43.118351;, + 47.862465;-317.929291;52.098011;, + 44.331398;-318.262634;57.600853;, + 27.469267;-318.973633;33.779335;, + 40.729748;-318.881866;32.536850;, + 45.473934;-318.965332;34.026867;, + 29.357723;-318.455261;60.501675;, + 27.174908;-318.229156;56.671257;, + 46.989555;-319.251740;38.820686;, + 35.991463;-302.649597;62.947060;, + 26.424608;-302.503204;60.257622;, + 43.376122;-302.253784;56.495960;, + 40.119797;-302.337189;60.689114;, + 44.990337;-300.990540;35.366989;, + 47.620136;-301.286255;40.386948;, + 36.216778;-300.612274;28.811060;, + 32.803436;-300.673798;29.757744;, + 24.048756;-301.120178;37.022236;, + 27.363960;-300.722260;30.436230;, + 23.788128;-301.899200;50.070427;, + 22.056257;-301.316620;40.265823;, + 24.430126;-302.246063;55.899719;, + 48.809952;-301.920135;51.038536;, + 41.513157;-300.854462;32.999695;, + 48.832378;-301.610474;45.850079;, + 40.338745;-255.114685;53.952095;, + 36.307659;-255.272247;56.438980;, + 23.571297;-253.775452;31.533110;, + 30.284136;-252.832504;28.237841;, + 19.657463;-253.800369;31.844225;, + 25.904573;-255.490616;61.349560;, + 18.003183;-255.126160;53.579521;, + 47.192974;-254.835419;49.536793;, + 47.219048;-254.582077;45.376305;, + 46.446331;-254.337875;41.345459;, + 43.740459;-254.140930;38.043240;, + 16.369314;-254.259338;39.300289;, + 14.705525;-254.391815;41.434326;, + 15.564311;-254.579514;44.539597;, + 40.846497;-253.837143;32.980343;, + 37.017307;-253.722290;30.997898;, + 12.643028;-224.292191;47.498661;, + 15.865307;-223.691589;37.720802;, + 18.706177;-223.414139;32.083801;, + 35.636074;-223.276321;30.279055;, + 14.800831;-224.687500;54.050610;, + 25.027224;-225.708954;61.528706;, + 15.874051;-224.947296;58.346874;, + 40.501038;-224.300461;58.010777;, + 46.826515;-224.518753;52.147167;, + 34.474094;-225.076096;60.967781;, + 25.982531;-212.417236;28.070055;, + 27.417156;-222.078049;29.233456;, + 25.773218;-279.096802;57.975464;, + 42.478611;-210.077286;42.464176;, + 13.046181;-215.346298;46.368130;, + 15.770669;-134.748428;59.732525;, + 7.355118;-152.749008;49.893005;, + 23.710951;-142.361053;25.355196;, + 5.442955;-134.035202;49.777802;, + 14.909875;-189.112885;40.448971;, + 16.632891;-199.126770;56.824585;, + 13.783645;-80.087219;31.121120;, + -8.380501;25.169817;49.343712;, + 8.527061;25.316885;48.399185;, + 12.786732;-55.480198;44.790428;, + -12.997930;-55.440056;45.084347;, + 60.698940;10.489414;61.040886;, + 59.605530;7.137096;70.365372;, + 36.555004;14.780283;44.255161;, + 50.340195;11.466660;40.450012;, + 77.780144;-0.616348;69.076759;, + 61.100998;-12.097787;52.234310;, + 54.395813;-21.261244;55.889946;, + 42.876431;-10.391958;41.524540;, + 70.006081;2.367340;76.967026;, + 67.389786;-1.205821;78.118034;, + 68.045258;-14.292754;73.173157;, + 78.460449;-9.570584;65.570358;, + 75.694405;-15.631040;66.051804;, + 78.295067;-4.036124;86.370949;, + 87.136154;-19.603304;74.055412;, + 78.082153;2.534071;68.323830;, + 66.419693;-15.575734;72.678177;, + 87.648987;-4.948394;78.487473;, + 77.807617;-19.174520;83.090736;, + 83.368835;-3.849846;82.306015;, + 89.470627;-9.871181;75.022331;, + 69.084702;6.252669;77.456337;, + 64.973396;0.815134;79.337639;, + 80.264275;-7.343033;63.092098;, + 75.774590;-18.309954;63.527412;, + 64.148453;-7.608615;77.332436;, + 73.421997;6.648875;73.774124;, + 83.376282;-20.182905;76.867386;, + 70.002251;-18.073837;68.726471;, + 77.197746;-9.981779;85.393761;, + 80.318741;-7.420647;85.493256;, + 82.789978;-6.610463;83.296829;, + 79.655968;-17.333593;83.765129;, + 79.183868;-11.467402;85.242088;, + 86.196594;-18.624458;77.084518;, + 82.521919;-17.837069;80.497223;, + 86.199554;-6.060757;79.316513;, + 86.261154;-12.489821;78.381943;, + 71.219742;-15.793794;69.989906;, + 66.651627;-8.248512;76.491966;, + 73.890327;2.056242;73.440269;, + 77.791145;1.105025;78.607323;, + 75.326248;1.267426;80.857727;, + 71.689697;-0.853509;83.395920;, + 73.386116;1.385114;82.625687;, + 83.216957;-4.725611;71.840660;, + 84.570229;-9.819118;68.947449;, + 83.728851;-14.435865;68.167923;, + 81.882507;-19.600512;68.102516;, + 77.441238;-19.029276;72.249611;, + 75.713539;-17.538631;74.283043;, + 71.547607;-4.747393;82.232681;, + 71.182411;-7.791823;81.549644;, + 71.304077;-12.113186;80.009758;, + 79.083267;-19.016726;70.790459;, + 80.102303;-1.256049;75.765610;, + 82.761185;-1.128553;73.438354;, + 72.702766;-16.469456;77.320290;, + 98.099678;-15.343760;83.785767;, + 93.154732;-6.980587;90.899246;, + 93.242905;-25.622953;81.159538;, + 114.749481;-29.371605;104.351402;, + 116.328888;-21.406776;103.886078;, + 84.665817;-9.600757;93.965752;, + 92.986916;-29.187506;89.371254;, + 110.432236;-25.897305;108.404945;, + 110.916962;-20.728716;110.111130;, + 87.785217;-19.995790;96.978920;, + 90.982941;-23.993515;93.046989;, + 85.656944;-14.398671;96.109711;, + 93.408386;-29.026354;84.485863;, + 90.449799;-8.323028;93.510162;, + 97.216904;-8.657048;85.987465;, + 97.339188;-20.929985;83.303215;, + 106.770485;-25.673952;93.617485;, + 105.883774;-28.288433;93.625610;, + 107.882225;-22.395979;93.607300;, + 108.385857;-19.427256;94.058815;, + 107.024353;-17.016718;96.046471;, + 102.020210;-15.026966;101.239967;, + 103.800346;-13.394409;100.111961;, + 101.485901;-28.208586;97.676857;, + 103.374771;-29.259912;95.624199;, + 104.934151;-29.521204;94.116104;, + 105.666786;-14.613162;98.028366;, + 100.699852;-25.001989;99.382347;, + 98.765816;-23.374475;101.653488;, + 99.300377;-20.235739;102.128960;, + 99.750626;-17.848330;102.450653;, + 100.601974;-16.327637;102.138657;, + 94.361519;-7.107321;83.677322;, + 90.721161;-5.196348;81.449821;, + 88.812431;-6.982263;88.106316;, + 93.009644;-14.297369;82.089050;, + 45.919392;12.804501;48.821217;, + 67.424805;2.305351;54.072571;, + 51.500221;-7.577340;65.697365;, + 43.626652;11.654449;36.415169;, + 114.547729;-31.794006;101.703148;, + 116.597923;-18.573429;102.008530;, + 106.487419;-27.751755;108.534760;, + 108.661095;-18.210699;110.956673;, + 120.240417;-32.382523;107.405258;, + 120.625252;-22.188108;107.598892;, + 113.002747;-28.165403;111.418968;, + 115.310875;-21.371449;114.672195;, + 128.789810;-29.466074;108.954926;, + 133.926620;-25.436079;121.826721;, + 135.061844;-38.374813;119.353981;, + 132.477707;-23.264696;124.912544;, + 119.123390;-33.322960;112.785774;, + 128.149567;-26.597660;127.790276;, + 118.771370;-29.660498;118.893425;, + 137.268311;-36.747177;118.004539;, + 120.575157;-22.560459;120.307121;, + 119.121994;-28.036406;123.119385;, + 114.274811;-23.003649;117.528297;, + 117.293953;-23.343679;126.162247;, + 115.772141;-28.293201;126.710030;, + 114.847473;-23.354944;126.325142;, + 133.524338;-30.337019;122.600365;, + 131.403183;-26.611431;125.127594;, + 134.824646;-26.838270;122.262741;, + 135.487198;-33.834320;120.160095;, + 130.670029;-24.829245;124.070786;, + 135.851913;-31.051704;118.766632;, + 137.676193;-32.291035;118.807190;, + 136.074463;-28.661200;120.936546;, + 132.979828;-35.570160;121.777008;, + 130.007385;-30.424955;125.430290;, + 128.967941;-28.056011;126.763344;, + 134.236618;-36.868240;120.362709;, + 127.290657;-35.227036;113.798904;, + 123.047722;-33.416660;109.614326;, + 120.623116;-30.226761;117.721672;, + 116.504295;-28.635885;114.683411;, + 129.463760;-23.354002;127.461098;, + 123.396797;-27.431246;121.069450;, + 124.584869;-28.187895;119.902473;, + 121.760422;-25.243605;123.489906;, + 120.613640;-25.185886;123.257240;, + 117.859741;-27.379353;126.710335;, + 116.538414;-28.334110;120.958870;, + 114.465019;-26.505037;126.579056;, + 120.118660;-28.808155;129.262100;, + 115.234482;-28.095364;129.084930;, + 115.773735;-23.653730;128.726898;, + 119.515671;-24.100697;128.185318;, + 117.369904;-31.079527;128.957718;, + 120.607414;-29.430899;132.556305;, + 117.583008;-29.569143;132.374924;, + 118.315994;-26.222034;131.904175;, + 120.763031;-25.726934;131.562943;, + 118.686279;-31.174704;132.509644;, + 120.230301;-29.213165;134.837173;, + 118.653221;-29.758589;134.962555;, + 119.351463;-27.770924;134.521164;, + 120.681877;-27.087921;134.183151;, + 119.078453;-30.474968;135.038971;, + 134.292740;-27.557007;120.420303;, + 133.862167;-25.069214;123.489700;, + 136.922577;-30.224680;119.848274;, + 138.524689;-33.810150;117.661865;, + 131.526566;-21.883783;126.059494;, + 130.900803;-32.067825;124.310493;, + 132.172577;-33.992134;122.873032;, + 132.345215;-26.909451;126.571350;, + 133.379410;-24.327793;126.319145;, + 132.650177;-22.985157;127.267006;, + 130.886734;-24.224178;128.467072;, + 129.605988;-27.135897;128.838928;, + 130.335205;-28.478533;127.891075;, + 133.363693;-27.150629;127.933983;, + 134.300049;-24.941853;127.674355;, + 133.717270;-23.873322;128.430740;, + 132.198166;-25.013567;129.446793;, + 131.015244;-27.552404;129.826096;, + 131.598038;-28.620930;129.069702;, + 134.645630;-27.372400;128.641541;, + 135.366272;-25.452135;128.495346;, + 134.776291;-24.375912;129.259750;, + 133.465668;-25.219961;130.170334;, + 132.745026;-27.140228;130.316544;, + 133.335007;-28.216450;129.552139;, + 135.557129;-28.123676;129.259583;, + 136.419373;-25.779036;129.096115;, + 135.688400;-24.438776;130.044846;, + 134.095200;-25.443157;131.157074;, + 133.232941;-27.787798;131.320541;, + 133.963898;-29.128056;130.371811;, + 136.416260;-29.042286;130.719208;, + 137.311722;-26.758564;130.512604;, + 136.647217;-25.540148;131.375107;, + 135.087219;-26.605450;132.444199;, + 134.191742;-28.889170;132.650787;, + 134.856277;-30.107586;131.788284;, + 137.309525;-29.130545;131.811081;, + 137.970703;-27.438389;131.659988;, + 137.471268;-26.529640;132.306519;, + 136.310669;-27.313053;133.104141;, + 135.649460;-29.005211;133.255219;, + 136.148911;-29.913960;132.608688;, + 138.067566;-29.848610;132.534195;, + 138.751144;-28.014139;132.398666;, + 138.182465;-26.977980;133.135162;, + 136.930222;-27.776287;134.007202;, + 136.246643;-29.610752;134.142715;, + 136.815308;-30.646914;133.406219;, + 138.629425;-30.705997;132.982819;, + 139.286957;-28.643524;132.924973;, + 138.553925;-27.306091;133.874786;, + 137.163391;-28.031139;134.882431;, + 136.505844;-30.093613;134.940262;, + 137.238861;-31.431042;133.990463;, + 139.375854;-31.531094;134.386230;, + 139.871201;-29.845297;134.374817;, + 139.231964;-28.684835;135.201675;, + 138.097382;-29.210182;136.039948;, + 137.602036;-30.895979;136.051376;, + 138.241287;-32.056435;135.224518;, + 140.178970;-31.048899;135.399673;, + 140.418076;-30.152719;135.414230;, + 140.041107;-29.477694;135.899567;, + 139.425034;-29.698851;136.370346;, + 139.185928;-30.595028;136.355789;, + 139.562897;-31.270054;135.870453;, + 140.513062;-30.455763;135.941559;, + 140.258026;-30.001667;136.269287;, + 134.998978;-30.947582;124.347214;, + 136.184570;-27.988020;124.058090;, + 135.348587;-26.448853;125.144691;, + 133.326996;-27.869246;126.520409;, + 131.894867;-31.158863;126.929192;, + 132.730850;-32.698029;125.842598;, + 136.426865;-31.351122;126.151329;, + 137.500275;-28.819027;125.853668;, + 136.832184;-27.594086;126.720772;, + 135.090698;-28.901239;127.885551;, + 134.017303;-31.433332;128.183212;, + 134.685394;-32.658272;127.316093;, + 138.107239;-31.708241;127.158394;, + 138.933365;-29.506886;126.990791;, + 138.257019;-28.273127;127.867088;, + 136.754562;-29.240726;128.910980;, + 135.928421;-31.442081;129.078583;, + 136.604767;-32.675838;128.202286;, + 139.331543;-32.657040;128.033676;, + 140.320007;-29.969194;127.846275;, + 139.482040;-28.432751;128.933884;, + 137.655624;-29.584154;130.208908;, + 136.667160;-32.271999;130.396317;, + 137.505127;-33.808445;129.308701;, + 140.591125;-33.844181;129.962296;, + 141.617676;-31.226170;129.725464;, + 140.855896;-29.829403;130.714218;, + 139.067566;-31.050646;131.939789;, + 138.041000;-33.668652;132.176636;, + 138.802795;-35.065418;131.187897;, + 141.828308;-34.049400;131.412170;, + 142.586258;-32.109543;131.238968;, + 142.013733;-31.067778;131.980133;, + 140.683243;-31.965866;132.894485;, + 139.925278;-33.905720;133.067688;, + 140.497818;-34.947487;132.326523;, + 142.872879;-34.958260;132.404327;, + 143.656509;-32.855263;132.248962;, + 143.004608;-31.667431;133.093292;, + 141.569046;-32.582588;134.092957;, + 140.785416;-34.685585;134.248322;, + 141.437332;-35.873421;133.404007;, + 143.646179;-36.004208;133.038742;, + 144.399963;-33.639832;132.972427;, + 143.559647;-32.106628;134.061264;, + 141.965546;-32.937801;135.216400;, + 141.211761;-35.302185;135.282715;, + 142.052078;-36.835381;134.193878;, + 144.756668;-37.074436;134.884445;, + 145.324524;-35.141872;134.871353;, + 144.591705;-33.811550;135.819244;, + 143.291046;-34.413788;136.780243;, + 142.723190;-36.346355;136.793335;, + 143.456009;-37.676674;135.845428;, + 145.857040;-36.609371;136.213287;, + 146.131134;-35.582005;136.229980;, + 145.699005;-34.808174;136.786362;, + 144.992767;-35.061703;137.326050;, + 144.718674;-36.089062;137.309357;, + 145.150803;-36.862896;136.752975;, + 146.317627;-35.967274;136.906616;, + 146.025253;-35.446705;137.282303;, + 136.889267;-34.388729;121.786079;, + 138.043243;-31.519651;121.509171;, + 137.240128;-30.030424;122.570480;, + 135.283035;-31.410269;123.908699;, + 133.882507;-34.609402;124.305260;, + 134.685638;-36.098633;123.243958;, + 138.202103;-34.760567;123.442123;, + 139.246475;-32.305771;123.156197;, + 138.604645;-31.120579;124.003120;, + 136.918472;-32.390182;125.135963;, + 135.874115;-34.844978;125.421883;, + 136.515945;-36.030170;124.574966;, + 139.771439;-35.090023;124.340836;, + 140.575928;-32.956081;124.181114;, + 139.926163;-31.762369;125.036995;, + 138.471878;-32.702595;126.052612;, + 137.667374;-34.836536;126.212334;, + 138.317154;-36.030251;125.356453;, + 140.906357;-35.995464;125.122398;, + 141.869110;-33.389969;124.944168;, + 141.064072;-31.903385;126.006470;, + 139.296295;-33.022293;127.247002;, + 138.333542;-35.627785;127.425224;, + 139.138565;-37.114368;126.362930;, + 142.050705;-37.125763;126.892921;, + 143.050034;-34.587837;126.666389;, + 142.318192;-33.236397;127.632103;, + 140.587006;-34.422878;128.824356;, + 139.587677;-36.960800;129.050888;, + 140.319519;-38.312241;128.085159;, + 143.191742;-37.308819;128.222427;, + 143.929611;-35.428307;128.056824;, + 143.379562;-34.420353;128.780731;, + 142.091629;-35.292908;129.670227;, + 141.353745;-37.173420;129.835846;, + 141.903809;-38.181374;129.111954;, + 144.154083;-38.176163;129.119446;, + 144.917267;-36.137577;128.971481;, + 144.290955;-34.988300;129.796127;, + 142.901459;-35.877598;130.768753;, + 142.138290;-37.916183;130.916702;, + 142.764603;-39.065464;130.092056;, + 144.865631;-39.179722;129.685654;, + 145.600723;-36.888016;129.624908;, + 144.793411;-35.404579;130.688385;, + 143.251007;-36.212845;131.812622;, + 142.515900;-38.504547;131.873383;, + 143.323227;-39.987988;130.809906;, + 145.871307;-40.198315;131.383316;, + 146.425507;-38.325241;131.373688;, + 145.721451;-37.038101;132.299500;, + 144.463196;-37.624027;133.234940;, + 143.908981;-39.497101;133.244537;, + 144.613022;-40.784241;132.318726;, + 146.890518;-39.734459;132.609009;, + 147.158310;-38.738781;132.626938;, + 146.743103;-37.990078;133.170349;, + 146.060104;-38.237057;133.695831;, + 145.792313;-39.232731;133.677887;, + 146.207520;-39.981438;133.134476;, + 147.317841;-39.106766;133.255463;, + 147.036926;-38.603104;133.622391;, + 138.085999;-37.138863;119.175186;, + 139.090546;-34.734760;118.968651;, + 138.476166;-33.511417;119.918930;, + 136.857193;-34.692177;121.075745;, + 135.606110;-37.426338;121.401924;, + 136.220490;-38.649681;120.451653;, + 139.088989;-37.460236;120.374466;, + 139.994675;-35.402271;120.154755;, + 139.503555;-34.428730;120.913040;, + 138.106750;-35.513153;121.891022;, + 136.954514;-37.901169;122.230385;, + 137.445618;-38.874702;121.472107;, + 140.310577;-37.735165;120.957130;, + 141.014175;-35.948002;120.844086;, + 140.516815;-34.967522;121.610336;, + 139.315872;-35.774200;122.489632;, + 138.612274;-37.561363;122.602676;, + 139.109634;-38.541847;121.836426;, + 141.172485;-38.492016;121.459724;, + 142.015732;-36.310272;121.336426;, + 141.399719;-35.089157;122.287537;, + 139.940460;-36.049793;123.361938;, + 139.097214;-38.231537;123.485237;, + 139.713226;-39.452652;122.534126;, + 142.017715;-39.448486;122.736076;, + 142.888947;-37.322247;122.569550;, + 142.328949;-36.212143;123.434189;, + 140.897690;-37.228283;124.465363;, + 140.026443;-39.354527;124.631889;, + 140.586456;-40.464630;123.767242;, + 142.895447;-39.609592;123.696373;, + 143.538910;-38.034172;123.574936;, + 143.117813;-37.206295;124.223007;, + 142.053253;-37.953835;124.992500;, + 141.409805;-39.529259;125.113930;, + 141.830887;-40.357136;124.465874;, + 143.619232;-40.337288;124.304420;, + 144.287018;-38.630085;124.200493;, + 143.807587;-37.686111;124.938774;, + 142.660355;-38.449345;125.780983;, + 141.992584;-40.156551;125.884911;, + 142.472015;-41.100525;125.146629;, + 144.145706;-41.176258;124.664856;, + 144.796890;-39.259224;124.640663;, + 144.178955;-38.040764;125.592773;, + 142.909821;-38.739342;126.569069;, + 142.258636;-40.656376;126.593254;, + 142.876572;-41.874832;125.641159;, + 144.885223;-42.039631;125.897728;, + 145.379715;-40.473606;125.913101;, + 144.840652;-39.416443;126.741905;, + 143.807114;-39.925308;127.555336;, + 143.312622;-41.491337;127.539970;, + 143.851685;-42.548496;126.711159;, + 145.686615;-41.660812;126.807167;, + 145.927765;-40.828819;126.835564;, + 145.609604;-40.213989;127.321953;, + 145.050308;-40.431152;127.779945;, + 144.809174;-41.263145;127.751549;, + 145.127319;-41.877975;127.265160;, + 146.032715;-41.142326;127.308174;, + 145.817383;-40.728752;127.636574;, + 124.973160;-23.354237;117.701744;, + 130.100662;-32.931473;123.451958;, + 128.472305;-28.867155;125.483269;, + 131.961060;-36.499588;120.635719;, + 130.957870;-35.780834;116.981300;, + 124.282539;-24.769093;125.526192;, + 125.508987;-30.949331;117.392708;, + 127.017143;-25.364244;114.287338;, + 117.540039;-22.350718;100.953659;, + 112.563721;-15.887562;106.469879;, + 110.663788;-31.643456;105.394226;, + 106.306908;-24.835386;110.495728;, + 110.832993;-28.654867;112.050888;, + 110.854927;-23.530939;113.587791;, + 121.598297;-21.157846;106.522896;, + 120.238564;-20.029554;107.979340;, + 114.466507;-18.879122;111.705498;, + 111.886719;-19.639212;113.723465;, + 117.792206;-32.974083;105.142754;, + 119.345352;-28.410704;105.006744;, + 115.554443;-33.065868;107.042320;, + 112.233528;-30.176003;110.656517;, + 33.827938;10.960120;51.807289;, + 39.182789;8.123861;57.134254;, + 39.964428;-10.933758;50.220123;, + 41.310238;-5.151076;57.811226;, + 60.861866;5.824606;48.839558;, + 71.769287;-1.344572;58.966167;, + 52.727615;10.033523;60.222115;, + 48.911415;-16.086357;49.050552;, + 50.863899;-3.190058;44.773193;, + -60.511364;10.489422;61.040886;, + -59.417953;7.137104;70.365372;, + -36.367424;14.780292;44.255165;, + -50.152618;11.466668;40.450016;, + -77.592583;-0.616339;69.076759;, + -60.913422;-12.097776;52.234310;, + -54.208237;-21.261230;55.889942;, + -42.688854;-10.391947;41.524540;, + -69.818512;2.367348;76.967026;, + -67.202217;-1.205813;78.118034;, + -67.857689;-14.292745;73.173157;, + -78.272881;-9.570575;65.570358;, + -75.506836;-15.631029;66.051804;, + -78.107506;-4.036117;86.370941;, + -86.948593;-19.603292;74.055412;, + -77.894592;2.534080;68.323830;, + -66.232124;-15.575725;72.678177;, + -87.461426;-4.948386;78.487473;, + -77.620056;-19.174511;83.090729;, + -83.181274;-3.849838;82.306007;, + -89.283066;-9.871171;75.022331;, + -68.897133;6.252676;77.456337;, + -64.785828;0.815142;79.337639;, + -80.076714;-7.343022;63.092098;, + -75.587021;-18.309942;63.527412;, + -63.960876;-7.608606;77.332436;, + -73.234436;6.648881;73.774124;, + -83.188721;-20.182894;76.867378;, + -69.814682;-18.073826;68.726471;, + -77.010178;-9.981771;85.393753;, + -80.131180;-7.420639;85.493248;, + -82.859459;-6.312282;83.425949;, + -79.468399;-17.333584;83.765121;, + -78.996300;-11.467393;85.242081;, + -86.009033;-18.624449;77.084511;, + -82.334358;-17.837059;80.497215;, + -86.011993;-6.060749;79.316505;, + -86.073555;-12.696040;78.345314;, + -71.032173;-15.793784;69.989906;, + -66.464066;-8.248504;76.491966;, + -73.702766;2.056248;73.440269;, + -77.603577;1.105032;78.607323;, + -75.138687;1.267434;80.857719;, + -71.502121;-0.853501;83.395912;, + -73.198547;1.385122;82.625679;, + -83.029396;-4.725603;71.840660;, + -84.382668;-9.819108;68.947449;, + -83.541290;-14.435856;68.167923;, + -81.694946;-19.600500;68.102516;, + -77.253677;-19.029264;72.249611;, + -75.525970;-17.538622;74.283043;, + -71.360039;-4.747385;82.232674;, + -70.994850;-7.791813;81.549637;, + -71.116508;-12.113177;80.009750;, + -78.895706;-19.016714;70.790459;, + -79.914742;-1.256042;75.765610;, + -82.573624;-1.128545;73.438354;, + -72.515198;-16.469446;77.320282;, + -97.912117;-15.343751;83.785759;, + -92.967171;-6.980580;90.899239;, + -93.055344;-25.622944;81.159531;, + -114.561913;-29.371595;104.351395;, + -116.141319;-21.406767;103.886070;, + -84.478256;-9.600749;93.965744;, + -92.799355;-29.187496;89.371246;, + -110.244675;-25.897297;108.404938;, + -110.729401;-20.728708;110.111122;, + -87.597656;-19.995781;96.978912;, + -90.795380;-23.993507;93.046982;, + -85.469383;-14.398664;96.109703;, + -93.220825;-29.026344;84.485855;, + -90.262238;-8.323020;93.510155;, + -97.029335;-8.657041;85.987457;, + -97.151627;-20.929976;83.303207;, + -106.582924;-25.673943;93.617477;, + -105.696213;-28.288424;93.625603;, + -107.694664;-22.395969;93.607292;, + -108.198296;-19.427246;94.058807;, + -106.836792;-17.016710;96.046463;, + -101.832649;-15.026958;101.239960;, + -103.612785;-13.394403;100.111954;, + -101.298340;-28.208574;97.676849;, + -103.187210;-29.259903;95.624191;, + -104.746590;-29.521194;94.116096;, + -105.479225;-14.613154;98.028358;, + -100.512291;-25.001982;99.382339;, + -98.578255;-23.374466;101.653481;, + -99.112808;-20.235731;102.128952;, + -99.563057;-17.848322;102.450645;, + -100.414413;-16.327629;102.138649;, + -94.173958;-7.107313;83.677315;, + -90.533600;-5.196339;81.449814;, + -88.624870;-6.982255;88.106308;, + -92.822083;-14.297360;82.089043;, + -45.731812;12.804509;48.821217;, + -67.237244;2.305361;54.072567;, + -51.312645;-7.577330;65.697365;, + -43.439075;11.654459;36.415169;, + -114.360168;-31.793995;101.703140;, + -116.410362;-18.573421;102.008522;, + -106.299858;-27.751747;108.534752;, + -108.473534;-18.210691;110.956665;, + -118.763100;-32.416569;106.890343;, + -119.195221;-22.221508;107.119102;, + -112.815208;-28.165394;111.418961;, + -115.208687;-21.985653;115.587814;, + -128.864243;-29.984035;109.850922;, + -133.928619;-25.617853;122.127678;, + -134.985291;-38.562931;119.605125;, + -132.439087;-23.407928;125.120613;, + -118.979370;-33.894085;113.600273;, + -127.981033;-26.736771;127.892494;, + -118.573692;-30.116972;119.482887;, + -137.255630;-36.934776;118.303642;, + -120.451622;-22.976614;120.888481;, + -118.885986;-28.402800;123.534958;, + -114.103012;-23.569595;118.313278;, + -117.037895;-23.683615;126.520027;, + -115.439522;-28.633007;127.009117;, + -114.556931;-23.727386;126.708763;, + -133.461777;-30.497587;122.817970;, + -131.314377;-26.758501;125.303482;, + -134.818481;-26.994595;122.516602;, + -135.449875;-34.009403;120.420280;, + -130.603973;-25.013189;124.323257;, + -135.866348;-31.256813;119.114555;, + -137.701736;-32.465740;119.114777;, + -136.085159;-28.822893;121.211914;, + -132.869873;-35.744339;121.980255;, + -129.858322;-30.577702;125.569275;, + -128.810074;-28.201370;126.883720;, + -134.150055;-37.050697;120.597130;, + -127.220825;-35.652714;114.436562;, + -122.998520;-33.996376;110.515045;, + -120.460487;-30.679323;118.331627;, + -116.345764;-29.216154;115.501526;, + -129.349152;-23.487917;127.596153;, + -123.251488;-27.779137;121.524582;, + -124.463943;-28.541100;120.384758;, + -121.581490;-25.569689;123.884338;, + -120.423470;-25.533827;123.678185;, + -117.563560;-27.690514;126.991264;, + -116.295723;-28.783062;121.501877;, + -114.134766;-26.870768;126.921577;, + -119.802361;-29.029490;129.383438;, + -114.863617;-28.393749;129.288300;, + -115.458870;-23.961578;128.988220;, + -119.253044;-24.363922;128.414917;, + -116.999329;-31.342564;129.104553;, + -120.245399;-29.574646;132.518158;, + -117.182472;-29.760815;132.384308;, + -117.964737;-26.420248;131.961685;, + -120.453552;-25.897451;131.607895;, + -118.282471;-31.343769;132.480225;, + -119.833649;-29.315147;134.705521;, + -118.228737;-29.879900;134.840668;, + -118.961952;-27.895647;134.431473;, + -120.321297;-27.201702;134.097992;, + -118.651398;-30.586836;134.899963;, + -134.298187;-27.758150;120.755005;, + -133.843735;-25.217905;123.721947;, + -136.944122;-30.393238;120.142960;, + -138.562317;-33.993008;117.991791;, + -131.473114;-22.020031;126.245018;, + -130.762848;-32.227257;124.468689;, + -132.052338;-34.158718;123.056244;, + -132.245651;-27.011766;126.667183;, + -133.322495;-24.425945;126.440849;, + -132.583725;-23.077150;127.371544;, + -130.768127;-24.314178;128.528564;, + -129.436584;-27.230442;128.868927;, + -130.175354;-28.579237;127.938255;, + -133.256104;-27.208897;127.952965;, + -134.230194;-24.996719;127.716698;, + -133.639786;-23.923281;128.459366;, + -132.075287;-25.062017;129.438324;, + -130.846466;-27.604633;129.788620;, + -131.436874;-28.678068;129.045944;, + -134.542770;-27.396519;128.609299;, + -135.293900;-25.473001;128.481171;, + -134.696152;-24.391825;129.231689;, + -133.347275;-25.234171;130.110321;, + -132.596161;-27.157688;130.238464;, + -133.193909;-28.238865;129.487946;, + -135.450180;-28.119780;129.179245;, + -136.349197;-25.771114;129.037415;, + -135.608658;-24.424700;129.968933;, + -133.969086;-25.426950;131.042328;, + -133.070053;-27.775614;131.184158;, + -133.810593;-29.122028;130.252640;, + -136.291122;-28.993143;130.552338;, + -137.223816;-26.705677;130.368149;, + -136.550583;-25.481665;131.214996;, + -134.944672;-26.545113;132.246048;, + -134.011978;-28.832579;132.430222;, + -134.685211;-30.056591;131.583374;, + -137.179993;-29.045206;131.582748;, + -137.868683;-27.350267;131.448212;, + -137.362671;-26.437330;132.082977;, + -136.167953;-27.219339;132.852280;, + -135.479263;-28.914282;132.986816;, + -135.985291;-29.827215;132.352036;, + -137.930786;-29.735388;132.255539;, + -138.643372;-27.897797;132.137161;, + -138.067200;-26.856865;132.860275;, + -136.778458;-27.653521;133.701782;, + -136.065872;-29.491106;133.820175;, + -136.642044;-30.532040;133.097046;, + -138.485275;-30.573214;132.667130;, + -139.172653;-28.506882;132.625885;, + -138.429977;-27.163292;133.558441;, + -136.999939;-27.886042;134.532242;, + -136.312576;-29.952375;134.573486;, + -137.055237;-31.295958;133.640945;, + -139.213760;-31.356102;133.989075;, + -139.732437;-29.667019;133.990204;, + -139.084747;-28.501205;134.802032;, + -137.918381;-29.024487;135.612717;, + -137.399704;-30.713572;135.611588;, + -138.047409;-31.879387;134.799774;, + -140.018036;-30.841948;134.952103;, + -140.268936;-29.943945;134.972733;, + -139.886917;-29.265791;135.449203;, + -139.254013;-29.485641;135.905014;, + -139.003113;-30.383642;135.884384;, + -139.385117;-31.061798;135.407928;, + -140.354813;-30.233871;135.472046;, + -140.096344;-29.777664;135.793762;, + -134.925339;-31.048527;124.460655;, + -136.159790;-28.084190;124.201187;, + -135.312897;-26.537964;125.268112;, + -133.231537;-27.956072;126.594505;, + -131.742386;-31.250843;126.968010;, + -132.589279;-32.797073;125.901085;, + -136.342789;-31.392393;126.160988;, + -137.459473;-28.856398;125.890129;, + -136.782639;-27.625828;126.741508;, + -134.989136;-28.931255;127.863777;, + -133.872452;-31.467245;128.134628;, + -134.549286;-32.697823;127.283241;, + -138.027634;-31.702929;127.096672;, + -138.888702;-29.497849;126.949776;, + -138.203445;-28.258413;127.810158;, + -136.657150;-29.224060;128.817413;, + -135.796066;-31.429138;128.964310;, + -136.481308;-32.668583;128.103928;, + -139.246399;-32.613304;127.906013;, + -140.277039;-29.920834;127.743416;, + -139.428085;-28.377333;128.811295;, + -137.548523;-29.526291;130.041809;, + -136.517883;-32.218758;130.204422;, + -137.366837;-33.762257;129.136520;, + -140.483856;-33.738888;129.718903;, + -141.553055;-31.116575;129.507767;, + -140.781296;-29.713392;130.478592;, + -138.940323;-30.932508;131.660553;, + -137.871094;-33.554817;131.871689;, + -138.642868;-34.957996;130.900879;, + -141.714996;-33.895096;131.085495;, + -142.504501;-31.952051;130.931244;, + -141.924408;-30.905476;131.658936;, + -140.554810;-31.801954;132.540863;, + -139.765320;-33.745007;132.695084;, + -140.345413;-34.791569;131.967392;, + -142.750443;-34.765797;132.009415;, + -143.567322;-32.659225;131.873703;, + -142.906815;-31.465914;132.702682;, + -141.429428;-32.379189;133.667358;, + -140.612549;-34.485764;133.803070;, + -141.273041;-35.679066;132.974091;, + -143.514694;-35.784763;132.593597;, + -144.302673;-33.415970;132.546310;, + -143.451279;-31.875710;133.615356;, + -141.811935;-32.704250;134.731705;, + -141.023956;-35.073055;134.778992;, + -141.875320;-36.613304;133.709930;, + -144.603409;-36.797626;134.330566;, + -145.197998;-34.861298;134.331848;, + -144.455490;-33.524841;135.262497;, + -143.118393;-34.124710;136.191864;, + -142.523804;-36.061047;136.190567;, + -143.266312;-37.397495;135.259933;, + -145.704269;-36.289589;135.590790;, + -145.991882;-35.260136;135.614456;, + -145.553955;-34.482719;136.160660;, + -144.828415;-34.734749;136.683197;, + -144.540802;-35.764202;136.659546;, + -144.978714;-36.541618;136.113327;, + -146.167557;-35.627628;136.254303;, + -145.871262;-35.104645;136.623108;, + -136.842163;-34.507912;121.949051;, + -138.043503;-31.634064;121.700676;, + -137.229767;-30.137711;122.742432;, + -135.214676;-31.515200;124.032562;, + -133.758621;-34.719486;124.394966;, + -134.572357;-36.215839;123.353210;, + -138.145432;-34.824940;123.509781;, + -139.231766;-32.366253;123.249680;, + -138.581421;-31.175377;124.080971;, + -136.844757;-32.443195;125.172371;, + -135.758438;-34.901882;125.432487;, + -136.408783;-36.092754;124.601196;, + -139.719559;-35.111778;124.343742;, + -140.557938;-32.974113;124.203918;, + -139.899506;-31.774664;125.043983;, + -138.402664;-32.712887;126.023872;, + -137.564270;-34.850555;126.163696;, + -138.222717;-36.049999;125.323631;, + -140.849487;-35.982155;125.065216;, + -141.853134;-33.372047;124.910805;, + -141.037415;-31.878336;125.953506;, + -139.218048;-32.994740;127.150612;, + -138.214417;-35.604839;127.305016;, + -139.030136;-37.098549;126.262321;, + -141.972977;-37.056030;126.729210;, + -143.013672;-34.513821;126.527390;, + -142.272110;-33.155907;127.475288;, + -140.489838;-34.340195;128.625000;, + -139.449127;-36.882404;128.826813;, + -140.190689;-38.240322;127.878899;, + -143.108612;-37.194061;127.982307;, + -143.877075;-35.310364;127.834953;, + -143.319672;-34.297565;128.545441;, + -141.993790;-35.168465;129.403305;, + -141.225327;-37.052162;129.550674;, + -141.782730;-38.064957;128.840179;, + -144.062485;-38.026543;128.816864;, + -144.857895;-35.984383;128.687775;, + -144.223221;-34.829582;129.497177;, + -142.793137;-35.716938;130.435669;, + -141.997726;-37.759098;130.564743;, + -142.632401;-38.913898;129.755356;, + -144.765549;-39.005554;129.337189;, + -145.533783;-36.709423;129.294647;, + -144.715698;-35.218861;130.338470;, + -143.129379;-36.024429;131.424835;, + -142.361115;-38.320564;131.467377;, + -143.179214;-39.811123;130.423553;, + -145.750641;-39.971535;130.934662;, + -146.330765;-38.094688;130.938782;, + -145.617279;-36.801361;131.847458;, + -144.323669;-37.384869;132.751999;, + -143.743530;-39.261711;132.747849;, + -144.457001;-40.555042;131.839188;, + -146.770706;-39.468060;132.097397;, + -147.051620;-38.470287;132.121964;, + -146.630768;-37.717964;132.655273;, + -145.929031;-37.963417;133.163986;, + -145.648132;-38.961185;133.139404;, + -146.068970;-39.713509;132.606094;, + -147.200821;-38.821938;132.716400;, + -146.916077;-38.315838;133.076492;, + -138.063828;-37.289051;119.406982;, + -139.108231;-34.879868;119.222725;, + -138.484604;-33.648365;120.152847;, + -136.816589;-34.826042;121.267235;, + -135.517487;-37.565662;121.565521;, + -136.141098;-38.797169;120.635399;, + -139.060074;-37.569843;120.535957;, + -140.001053;-35.507759;120.336586;, + -139.502533;-34.527710;121.078781;, + -138.063034;-35.609749;122.020325;, + -136.867325;-38.002270;122.333717;, + -137.365829;-38.982311;121.591530;, + -140.286835;-37.814011;121.073189;, + -141.018921;-36.022858;120.975487;, + -140.514023;-35.035809;121.725449;, + -139.277069;-35.839912;122.573105;, + -138.544998;-37.631069;122.670799;, + -139.049896;-38.618114;121.920837;, + -141.145554;-38.545986;121.533401;, + -142.023148;-36.359291;121.428398;, + -141.397858;-35.130013;122.359329;, + -139.894958;-36.087437;123.395241;, + -139.017365;-38.274132;123.500229;, + -139.642654;-39.503407;122.569305;, + -141.974594;-39.461166;122.731110;, + -142.880615;-37.330349;122.583794;, + -142.312164;-36.212826;123.430077;, + -140.837692;-37.226124;124.423691;, + -139.931671;-39.356945;124.570999;, + -140.500122;-40.474468;123.724709;, + -142.848846;-39.588902;123.635170;, + -143.518021;-38.010078;123.527908;, + -143.090546;-37.176647;124.162201;, + -141.993881;-37.922039;124.903725;, + -141.324722;-39.500870;125.010979;, + -141.752197;-40.334293;124.376701;, + -143.566452;-40.291603;124.198372;, + -144.261322;-38.580566;124.108978;, + -143.774628;-37.630268;124.831566;, + -142.593063;-38.391006;125.643524;, + -141.898178;-40.102051;125.732918;, + -142.384872;-41.052349;125.010338;, + -144.086502;-41.113419;124.526360;, + -144.765533;-39.191589;124.515739;, + -144.138245;-37.964970;125.447609;, + -142.831924;-38.660183;126.390099;, + -142.152893;-40.582008;126.400719;, + -142.780182;-41.808628;125.468857;, + -144.809982;-41.938175;125.684982;, + -145.326218;-40.368050;125.710388;, + -144.778976;-39.303791;126.521545;, + -143.715500;-39.809662;127.307304;, + -143.199249;-41.379795;127.281898;, + -143.746490;-42.444050;126.470741;, + -145.612946;-41.529369;126.547478;, + -145.865082;-40.695091;126.580605;, + -145.542038;-40.076111;127.056602;, + -144.966858;-40.291412;127.499474;, + -144.714737;-41.125694;127.466347;, + -145.037766;-41.744671;126.990349;, + -145.961716;-40.996456;127.027367;, + -145.743073;-40.580086;127.348747;, + -124.935844;-23.758604;118.330032;, + -129.955658;-33.118725;123.649422;, + -128.317764;-29.044809;125.658051;, + -131.844467;-36.710579;120.893005;, + -130.886246;-36.084728;117.422089;, + -124.112961;-25.016518;125.801498;, + -125.407913;-31.335402;117.942909;, + -127.034424;-25.805647;115.016808;, + -117.352478;-22.350708;100.953651;, + -112.376160;-15.887554;106.469872;, + -110.476227;-31.643446;105.394218;, + -106.119347;-24.835379;110.495720;, + -110.645432;-28.654860;112.050880;, + -110.667366;-23.530931;113.587784;, + -120.163315;-21.191313;106.039421;, + -118.809158;-20.062948;107.500015;, + -114.278946;-18.879114;111.705490;, + -111.699158;-19.639204;113.723457;, + -117.604637;-32.974075;105.142746;, + -119.157791;-28.410696;105.006737;, + -115.366882;-33.065861;107.042313;, + -112.045959;-30.175995;110.656509;, + -33.640362;10.960128;51.807285;, + -38.995209;8.123871;57.134251;, + -39.776852;-10.933746;50.220119;, + -41.122662;-5.151066;57.811222;, + -60.674290;5.824616;48.839558;, + -71.581718;-1.344563;58.966167;, + -52.540039;10.033530;60.222115;, + -48.723839;-16.086346;49.050549;, + -50.676323;-3.190047;44.773193;, + -6.262792;13.473364;58.013275;, + 6.173337;13.337016;58.607582;, + -11.545969;16.822830;57.059074;, + 0.138007;12.423479;60.187363;, + 11.825384;16.819580;57.419716;, + -6.266276;13.691039;58.408001;, + 6.169853;13.554691;59.002308;, + 0.057848;95.886368;65.707542;, + 0.057848;97.662560;43.454536;, + 0.057848;90.668213;33.607914;, + 0.057848;73.976425;70.984543;, + 0.057848;63.606403;31.055357;, + 0.057848;99.177589;56.123409;, + 0.057848;84.042374;71.322975;, + 0.057848;75.714500;30.620197;, + 0.057848;53.154804;40.756420;, + -15.043728;50.197842;49.912075;, + -13.469022;92.920013;60.063766;, + -11.461862;93.826927;46.940403;, + -8.418667;86.102859;35.841724;, + -2.182251;64.795692;35.886501;, + -13.655560;74.702049;67.510803;, + -16.338684;73.054062;51.038074;, + -7.371841;73.847633;69.711700;, + -4.494127;83.274292;70.169548;, + -13.097512;71.430748;40.778584;, + -13.263326;61.285336;39.593838;, + -13.865308;81.275604;65.186821;, + -4.402893;95.093262;63.828449;, + -14.668218;94.575356;62.197353;, + -6.418187;97.562218;66.945374;, + -6.403885;85.831749;72.998459;, + -2.904975;98.340385;68.672066;, + -3.096079;86.564301;74.622665;, + -15.709467;82.386459;66.627968;, + -14.238920;86.733635;61.588871;, + -15.816927;87.518616;62.681839;, + -11.518435;84.699326;70.485474;, + -8.635912;82.575844;67.678185;, + -10.775403;96.597122;64.803986;, + -7.852941;94.312172;61.946106;, + -16.338850;66.013954;51.296288;, + -14.718096;68.331589;44.645512;, + -15.784473;69.911873;57.321053;, + -15.528388;63.130802;45.068886;, + -14.675630;70.832016;46.772766;, + -15.347429;57.616409;47.193058;, + -7.149835;52.817856;41.486317;, + -7.580388;47.204636;47.215710;, + -3.355227;56.332371;40.007046;, + -14.710178;77.561653;59.569633;, + -12.242872;104.272034;59.466625;, + -13.871002;106.867241;51.713676;, + -6.555738;100.376198;26.176455;, + -10.330755;93.744308;22.167315;, + -25.391743;66.042480;44.113369;, + -20.371532;85.581749;31.614416;, + -3.509032;68.824097;16.563112;, + -16.921518;68.428406;22.861071;, + -23.283691;91.554054;44.497189;, + -22.312506;78.019226;58.252476;, + -5.355029;81.806320;13.441270;, + -6.858363;107.464165;38.205128;, + -1.630455;58.319656;15.177998;, + -19.439602;55.002464;25.954828;, + -14.163750;71.116005;45.658489;, + -16.339277;34.462788;24.538301;, + -3.199738;106.311531;63.356800;, + -7.285188;105.334877;61.411713;, + -19.911991;74.556313;27.957836;, + -23.002449;68.454033;35.866280;, + -23.994633;83.695297;38.363724;, + -21.688162;63.338444;39.264874;, + -21.994913;54.244259;32.219749;, + -11.261707;52.068916;45.952110;, + -6.553079;49.986835;18.220219;, + -13.583147;45.560303;22.582418;, + -3.504504;39.875324;20.493166;, + -24.415617;69.041245;50.481827;, + -15.101998;82.440125;58.401062;, + -4.228397;103.816078;53.739082;, + -10.791362;101.190048;49.992683;, + -11.328189;101.622627;54.213688;, + -2.042533;104.242516;48.194424;, + -2.467957;102.354828;41.462799;, + -5.581229;102.438309;43.389084;, + -2.102569;101.711769;35.092808;, + -5.357594;98.838608;34.631802;, + -2.575568;97.464630;31.897514;, + -9.509275;96.133217;33.318790;, + -6.373484;96.717354;29.011164;, + -8.609506;92.094917;28.785583;, + -0.961346;89.876480;22.612808;, + -3.750705;87.223274;24.470808;, + -1.293535;83.343231;22.908096;, + -7.475338;76.444283;20.933500;, + -7.155903;71.146484;21.280985;, + -4.020619;75.279213;22.110722;, + -1.186798;66.427330;20.374010;, + -1.050320;61.116470;21.804775;, + -3.120998;63.629890;20.392683;, + -6.236067;57.664822;24.799372;, + -3.291713;57.533966;22.859617;, + -4.431494;55.146961;25.181421;, + -2.515443;47.986980;22.845200;, + -2.247637;45.361992;27.063856;, + -3.458311;46.185818;25.952394;, + -15.542780;91.786743;39.028736;, + -15.098378;89.391930;35.078747;, + -16.682585;85.833199;39.137646;, + -15.960197;80.988068;32.730686;, + -17.451015;78.322830;36.557224;, + -16.864700;74.552986;34.352123;, + -13.662128;75.346954;26.811104;, + -13.099884;69.581734;27.209919;, + -14.475806;72.210419;29.167706;, + -16.048969;64.284309;32.004520;, + -14.420856;61.870514;29.131302;, + -16.221205;60.286003;31.238237;, + -14.534574;44.794735;26.116779;, + -14.848799;44.863647;29.381424;, + -13.599534;41.942635;29.015915;, + -10.621090;54.617325;25.569170;, + -8.996603;52.321831;27.760847;, + -10.189517;51.242924;27.917196;, + -17.834475;94.101349;53.041599;, + -17.518343;94.489967;48.203121;, + -19.293009;90.274719;49.298183;, + -19.945814;88.506752;43.413734;, + -18.563108;84.403915;43.736874;, + -21.033463;85.001541;44.282993;, + -23.027826;71.019249;46.561157;, + -21.556767;69.493790;46.926170;, + -23.674259;69.104668;47.675011;, + -22.533089;73.345596;50.339439;, + -21.038176;75.381149;55.902035;, + -21.679085;72.997261;52.478176;, + -19.307541;61.902699;35.872772;, + -18.916523;58.344765;35.077782;, + -19.290819;59.542400;38.422955;, + -8.277215;99.647781;59.143467;, + -2.250754;97.063629;60.111290;, + -1.262086;99.482384;60.521812;, + -4.202026;99.742661;59.680969;, + -1.779861;73.225479;71.214066;, + -17.854918;48.596111;35.240131;, + -17.187716;41.811371;40.273598;, + 15.159414;50.197842;49.912075;, + 13.584708;92.920013;60.063766;, + 11.577548;93.826927;46.940403;, + 8.534353;86.102859;35.841724;, + 2.297937;64.795692;35.886501;, + 13.771247;74.702049;67.510803;, + 16.454370;73.054062;51.038074;, + 7.487527;73.847633;69.711700;, + 4.609814;83.274292;70.169548;, + 13.213199;71.430748;40.778584;, + 13.379013;61.285336;39.593838;, + 13.980994;81.275604;65.186821;, + 4.518579;95.093262;63.828449;, + 14.783904;94.575356;62.197353;, + 6.533874;97.562218;66.945374;, + 6.519572;85.831749;72.998459;, + 3.020661;98.340385;68.672066;, + 3.211765;86.564301;74.622665;, + 15.825153;82.386459;66.627968;, + 14.354607;86.733635;61.588871;, + 15.932613;87.518616;62.681839;, + 11.634122;84.699326;70.485474;, + 8.751598;82.575844;67.678185;, + 10.891089;96.597122;64.803986;, + 7.968627;94.312172;61.946106;, + 16.454536;66.013954;51.296288;, + 14.833782;68.331589;44.645512;, + 15.900160;69.911873;57.321053;, + 15.644074;63.130802;45.068886;, + 14.791316;70.832016;46.772766;, + 15.463116;57.616409;47.193058;, + 7.265521;52.817856;41.486317;, + 7.696074;47.204636;47.215710;, + 3.470914;56.332371;40.007046;, + 14.825865;77.561653;59.569633;, + 12.358559;104.272034;59.466625;, + 13.986689;106.867241;51.713676;, + 6.671424;100.376198;26.176455;, + 10.446442;93.744308;22.167315;, + 25.507429;66.042480;44.113369;, + 20.487219;85.581749;31.614416;, + 3.624719;68.824097;16.563112;, + 17.037205;68.428406;22.861071;, + 23.399378;91.554054;44.497189;, + 22.428192;78.019226;58.252476;, + 5.470715;81.806320;13.441270;, + 6.974050;107.464165;38.205128;, + 1.746141;58.319656;15.177998;, + 19.555288;55.002464;25.954828;, + 14.279436;71.116005;45.658489;, + 16.454964;34.462788;24.538301;, + 3.315424;106.311531;63.356800;, + 7.400875;105.334877;61.411713;, + 20.027678;74.556313;27.957836;, + 23.118135;68.454033;35.866280;, + 24.110319;83.695297;38.363724;, + 21.803848;63.338444;39.264874;, + 22.110600;54.244255;32.219749;, + 11.377394;52.068913;45.952110;, + 6.668766;49.986835;18.220219;, + 13.698833;45.560303;22.582418;, + 3.620190;39.875320;20.493166;, + 24.531303;69.041245;50.481827;, + 15.217685;82.440125;58.401062;, + 4.344084;103.816078;53.739082;, + 10.907048;101.190048;49.992683;, + 11.443875;101.622627;54.213688;, + 2.158219;104.242516;48.194424;, + 2.583643;102.354828;41.462799;, + 5.696916;102.438309;43.389084;, + 2.218256;101.711769;35.092808;, + 5.473281;98.838608;34.631802;, + 2.691255;97.464630;31.897514;, + 9.624962;96.133217;33.318790;, + 6.489170;96.717354;29.011164;, + 8.725192;92.094917;28.785583;, + 1.077032;89.876480;22.612808;, + 3.866392;87.223274;24.470808;, + 1.409221;83.343231;22.908096;, + 7.591025;76.444283;20.933500;, + 7.271590;71.146484;21.280985;, + 4.136305;75.279213;22.110722;, + 1.302485;66.427330;20.374010;, + 1.166007;61.116470;21.804775;, + 3.236684;63.629890;20.392683;, + 6.351754;57.664822;24.799372;, + 3.407399;57.533966;22.859617;, + 4.547181;55.146961;25.181421;, + 2.631130;47.986980;22.845200;, + 2.363323;45.361992;27.063856;, + 3.573997;46.185818;25.952394;, + 15.658466;91.786743;39.028736;, + 15.214065;89.391930;35.078747;, + 16.798271;85.833199;39.137646;, + 16.075884;80.988068;32.730686;, + 17.566702;78.322830;36.557224;, + 16.980387;74.552986;34.352123;, + 13.777815;75.346954;26.811104;, + 13.215570;69.581734;27.209919;, + 14.591493;72.210419;29.167706;, + 16.164656;64.284309;32.004520;, + 14.536543;61.870514;29.131302;, + 16.336891;60.286003;31.238237;, + 14.650260;44.794735;26.116779;, + 14.964485;44.863644;29.381424;, + 13.715221;41.942635;29.015915;, + 10.736776;54.617321;25.569170;, + 9.112289;52.321831;27.760847;, + 10.305203;51.242924;27.917196;, + 17.950161;94.101349;53.041599;, + 17.634029;94.489967;48.203121;, + 19.408695;90.274719;49.298183;, + 20.061501;88.506752;43.413734;, + 18.678795;84.403915;43.736874;, + 21.149149;85.001541;44.282993;, + 23.143513;71.019249;46.561157;, + 21.672453;69.493790;46.926170;, + 23.789946;69.104668;47.675011;, + 22.648775;73.345596;50.339439;, + 21.153862;75.381149;55.902035;, + 21.794771;72.997261;52.478176;, + 19.423227;61.902699;35.872772;, + 19.032209;58.344765;35.077782;, + 19.406506;59.542400;38.422955;, + 8.392901;99.647781;59.143467;, + 2.366440;97.063629;60.111290;, + 1.377773;99.482384;60.521812;, + 4.317712;99.742661;59.680969;, + 1.895548;73.225479;71.214066;, + 17.970604;48.596111;35.240131;, + 17.303402;41.811371;40.273598;, + 0.438559;57.282112;73.561638;, + 0.736964;56.934887;73.321701;, + 0.356253;56.468140;73.264908;, + -0.240559;56.468140;73.264908;, + -0.621271;56.934887;73.321701;, + -0.322864;57.282112;73.561638;, + -0.248436;71.854645;70.729988;, + 0.364132;71.854645;70.729988;, + 0.758169;70.963852;70.525764;, + 0.451886;70.057053;70.373367;, + -0.336191;70.057053;70.373360;, + -0.642476;70.963852;70.525764;, + 0.364132;73.351379;70.952026;, + -0.248436;73.351379;70.952026;, + 0.455698;61.693325;71.893539;, + 0.836409;60.952618;72.164238;, + 0.438559;60.724323;72.609840;, + -0.322864;60.724323;72.609840;, + -0.720715;60.952618;72.164238;, + -0.340003;61.693325;71.893539;, + -0.322864;59.615437;73.646515;, + 0.438559;59.615437;73.646515;, + 0.438559;58.736450;73.878487;, + -0.322864;58.736450;73.878487;, + -0.945781;48.617813;70.123962;, + -2.236765;48.914082;70.144196;, + -1.083371;49.222790;70.673294;, + -0.230488;49.179218;70.678032;, + 0.346183;49.179218;70.678032;, + 1.199065;49.222790;70.673294;, + 2.352458;48.914082;70.144196;, + 1.061476;48.617813;70.123962;, + 1.061476;46.043205;70.763565;, + 1.061476;45.315922;70.631477;, + -0.945781;45.315922;70.631477;, + -0.945781;46.043205;70.763565;, + -0.230488;50.744427;71.911613;, + 0.346183;50.744427;71.911613;, + 0.346183;50.290668;71.732040;, + -0.230488;50.290668;71.732040;, + 0.681346;41.262371;69.549492;, + 1.304843;39.983742;69.127930;, + 0.681345;39.288811;68.917770;, + -0.565651;39.288811;68.917770;, + -1.189150;39.983742;69.127930;, + -0.565651;41.262371;69.549492;, + -1.460927;43.933510;69.011917;, + -1.841057;44.861637;69.288826;, + -0.945781;45.001892;69.606239;, + 1.061476;45.001892;69.606239;, + 1.956750;44.861637;69.288826;, + 1.576620;43.933510;69.011917;, + 0.681346;43.309490;69.095680;, + -0.565651;43.309490;69.095680;, + 0.346183;51.987255;71.326790;, + 0.346183;51.362129;71.498451;, + -0.230488;51.362129;71.498451;, + -0.230488;51.987255;71.326790;, + -0.230488;53.243740;71.207901;, + -0.693861;53.723915;71.140991;, + -0.405525;54.361668;71.150101;, + 0.521220;54.361668;71.150101;, + 0.809554;53.723915;71.140991;, + 0.346183;53.243740;71.207901;, + -1.009302;55.219082;71.714081;, + -1.025449;55.481266;71.933746;, + -0.720078;55.895855;72.229713;, + -0.240559;56.053364;72.471550;, + 0.356253;56.053364;72.471550;, + 0.835771;55.895855;72.229713;, + 1.141142;55.481266;71.933746;, + 1.124995;55.219086;71.714081;, + 0.521220;55.117058;71.726410;, + -0.405525;55.117058;71.726410;, + -0.565651;38.742027;59.643063;, + 0.681345;38.742027;59.643063;, + 2.217954;38.776661;57.910744;, + 2.867495;39.371185;54.783699;, + 1.330886;37.590916;54.064663;, + -1.215191;37.590916;54.064663;, + -2.751802;39.371185;54.783699;, + -2.102260;38.776661;57.910744;, + -0.510998;50.219196;39.523888;, + 0.626693;50.219196;39.523888;, + -1.873620;26.054764;52.140381;, + -1.215191;29.188606;52.544262;, + 1.330886;29.188606;52.544262;, + 1.989312;26.054764;52.140381;, + 2.234568;33.522697;35.402046;, + 0.565745;37.216824;36.971302;, + -0.450050;37.216824;36.971302;, + -2.118875;33.522697;35.402046;, + -0.565651;37.436687;67.317482;, + 0.681345;37.436687;67.317482;, + 0.681345;37.195446;65.010315;, + -0.565651;37.195446;65.010315;, + -2.538574;41.449165;68.624062;, + -2.951183;40.302361;68.035011;, + -4.628216;39.976799;65.832298;, + -5.649843;41.666725;65.621597;, + -4.822110;42.776821;67.453926;, + -3.387875;42.233704;68.253677;, + -15.066837;51.644341;50.761562;, + -13.959147;50.054565;53.477966;, + -13.171544;47.816036;53.537487;, + -12.819518;47.844864;50.501919;, + -14.464008;51.746117;48.798912;, + -15.310171;52.496346;49.328674;, + -14.314348;64.191902;63.807819;, + -13.928720;63.485863;64.339012;, + -13.572276;62.304844;64.865723;, + -13.167170;61.067101;65.229462;, + -12.962619;58.564976;64.792267;, + -13.533698;58.152863;63.610909;, + -14.547876;60.533600;62.358631;, + -14.767531;62.889500;62.645046;, + -16.389227;56.612152;48.529644;, + -16.521999;56.337196;48.919449;, + -16.561354;57.052597;49.445042;, + -16.542124;57.916912;49.540932;, + -16.326410;58.083145;50.780964;, + -15.837441;56.684170;51.706242;, + -15.670477;54.844639;50.363594;, + -16.045902;55.654251;48.952625;, + -13.866287;76.274246;65.799950;, + -12.180278;74.145042;67.802490;, + -13.091559;73.365410;66.984734;, + -13.743665;72.909081;66.356583;, + -14.234488;73.032753;65.109230;, + -14.186148;74.380287;64.488983;, + -16.565777;71.776100;50.947868;, + -16.808704;72.864502;50.189095;, + -16.304464;72.598770;49.611454;, + -12.345559;69.888283;65.738831;, + -12.326240;69.568321;65.742271;, + -12.347851;69.289749;65.733955;, + -12.479330;68.737000;65.669327;, + -12.625326;68.411827;65.535583;, + -12.699836;68.129967;65.442223;, + -13.074884;67.260254;64.888390;, + -13.514962;67.960876;64.396080;, + -13.290691;70.147194;64.970589;, + -12.663944;70.601143;65.617447;, + -3.217402;61.792000;69.916451;, + -2.825095;61.031200;70.194847;, + -3.213592;59.684910;70.235397;, + -3.662069;58.804951;70.155693;, + -3.857313;58.498222;70.159554;, + -4.142841;58.239128;70.071960;, + -4.253828;58.105072;69.919785;, + -3.673181;58.191391;69.761742;, + -4.503674;59.898464;69.912605;, + -3.921128;61.008068;69.727730;, + -3.192633;55.084583;70.448547;, + -3.111558;54.744785;70.582428;, + -2.385719;54.680038;70.815506;, + -1.792563;54.532791;70.915924;, + -2.092454;53.903660;70.912537;, + -2.919086;53.404095;70.938629;, + -3.321806;54.305473;70.619545;, + -6.250182;49.317669;69.504501;, + -6.446180;48.549271;69.168564;, + -8.014235;48.270035;68.304420;, + -8.714692;50.122650;68.182167;, + -7.801420;51.763470;68.922615;, + -6.904962;50.679249;69.380814;, + -5.370491;51.804302;70.890030;, + -4.524282;52.698963;71.277252;, + -4.071008;51.834652;71.563766;, + -3.656876;50.892254;71.572784;, + -4.722633;50.442741;71.028595;, + -6.934566;47.145229;68.633385;, + -5.329893;47.425457;69.456062;, + -3.966182;46.793549;69.870453;, + -3.938172;46.091690;69.693321;, + -4.855957;46.051064;69.184097;, + -6.488640;46.472694;68.538559;, + -1.098645;50.973583;71.694138;, + -1.950218;51.124405;71.635803;, + -2.407137;52.052967;71.641159;, + -1.563598;52.530037;71.605721;, + -1.096965;52.051891;71.685753;, + -1.088933;51.424000;71.779518;, + -13.021915;53.488663;61.239902;, + -14.041900;55.868359;59.989929;, + -14.138645;57.389984;61.303249;, + -13.118661;55.010292;62.553223;, + -9.482656;49.163662;66.510292;, + -8.739838;47.333950;66.631050;, + -8.364165;46.637093;66.527420;, + -8.016644;45.674202;66.296745;, + -8.580020;44.714546;64.299896;, + -10.489306;46.236229;61.293800;, + -11.341558;48.442810;61.255726;, + -11.017628;49.345627;63.166481;, + -11.104903;50.871937;64.476662;, + -10.609887;51.240044;65.681923;, + -1.474512;58.398350;72.686012;, + -1.812058;58.122028;72.386444;, + -2.271988;58.206673;72.014107;, + -2.493294;58.257072;71.856972;, + -2.453580;58.564266;71.700531;, + -2.337840;58.869293;71.594749;, + -1.884961;59.340534;71.866264;, + -1.441849;59.261425;72.428749;, + -1.509435;57.558842;72.547653;, + -1.134018;57.032932;72.596863;, + -1.626426;56.943577;72.311104;, + -2.118178;57.221329;72.202080;, + -2.053061;57.660461;72.258942;, + -2.506476;58.943634;70.957291;, + -2.665209;58.656223;71.097099;, + -2.901366;58.531845;70.941536;, + -3.059159;58.630623;70.641769;, + -2.838635;58.924690;70.598763;, + -5.702873;55.781525;69.312447;, + -5.801723;57.970192;69.387802;, + -5.111734;58.670830;69.693558;, + -3.983715;58.045750;69.612915;, + -4.088572;57.287357;69.743599;, + -4.068023;56.821293;69.814964;, + -3.812485;56.347786;69.903954;, + -3.917183;55.572304;70.041840;, + -4.834018;54.668350;69.775490;, + -4.255816;56.976295;70.144569;, + -4.259132;57.438969;70.049438;, + -4.196453;57.593311;70.295357;, + -4.135692;57.244923;70.552475;, + -4.206871;56.894928;70.444580;, + -3.591207;57.666695;71.185127;, + -3.783044;57.561813;70.960518;, + -3.836649;57.893749;70.692024;, + -3.568345;58.165226;70.788643;, + -3.408157;58.065258;71.087090;, + -3.712499;55.370281;70.761353;, + -3.470078;55.416473;71.000565;, + -2.839330;55.237701;71.154488;, + -2.822697;54.988895;70.923553;, + -3.522735;55.051468;70.611397;, + -4.155221;56.153671;70.536667;, + -4.015416;55.782383;70.614700;, + -3.834426;55.439445;70.483299;, + -3.917668;55.755974;70.291489;, + -4.162768;56.246273;70.237022;, + -3.360456;57.598080;71.641861;, + -3.439125;57.720852;71.496246;, + -3.251950;58.117050;71.396477;, + -3.021049;58.246376;71.555511;, + -3.085086;57.947788;71.731819;, + -2.968136;57.499275;71.833702;, + -2.706439;57.428493;71.961281;, + -2.801483;56.969940;71.952415;, + -3.146882;56.789368;71.787590;, + -3.226831;57.136875;71.731987;, + -2.680634;56.379002;72.014671;, + -2.158215;56.120026;72.073334;, + -2.463775;55.692970;71.788239;, + -3.104754;55.851723;71.649239;, + -3.019568;56.201847;71.837547;, + -3.854640;56.847206;71.126411;, + -3.682065;56.967865;71.362190;, + -3.578869;56.835163;71.491699;, + -3.497496;56.487053;71.543762;, + -3.592218;56.139133;71.357254;, + -3.813043;56.122169;71.094490;, + -3.932611;56.500839;71.012955;, + -2.244552;60.233025;70.703400;, + -1.543128;60.758423;71.142464;, + -1.905732;59.838963;71.250046;, + -2.362187;59.370174;70.980934;, + -2.702353;59.358711;70.627777;, + -5.869700;72.868355;69.812210;, + -6.693674;72.552437;69.361465;, + -7.883108;73.155823;69.069405;, + -9.038418;73.717834;68.902939;, + -8.692574;68.018349;68.671463;, + -8.338293;68.821220;68.766014;, + -7.113932;68.489220;68.942162;, + -6.934299;67.847763;68.938004;, + -7.729776;67.687729;68.801422;, + -6.369604;71.293625;68.760429;, + -6.266792;70.787079;68.649055;, + -7.456227;71.390457;68.356995;, + -7.559039;71.897003;68.468361;, + -8.883052;64.549225;67.816406;, + -7.739773;64.507843;68.125893;, + -6.938856;64.740326;68.286102;, + -6.703542;64.155365;68.361183;, + -6.983939;63.322628;68.406448;, + -7.766936;63.148247;68.257492;, + -8.915951;63.725613;67.823822;, + -9.511546;64.526329;67.588211;, + -5.015405;68.108635;68.910416;, + -4.548992;67.765022;68.960190;, + -3.810864;67.410515;69.067841;, + -3.841677;66.485794;69.114601;, + -4.796024;65.666992;68.895134;, + -5.041750;66.255524;68.850845;, + -4.661049;66.762360;68.945168;, + -5.034431;67.060791;68.905960;, + -5.210155;67.702225;68.891853;, + -13.971161;79.561020;64.637955;, + -16.624105;67.403618;50.887012;, + -16.565861;68.256042;51.076977;, + -16.246441;65.836792;52.110813;, + -16.461342;64.238647;50.971241;, + -16.518333;64.809113;50.940807;, + -16.347895;65.639847;50.705421;, + -16.240040;66.024963;50.538170;, + -16.346189;66.463646;50.675999;, + -15.224072;69.450462;45.349747;, + -15.760094;69.213470;44.900475;, + -15.382089;67.644539;44.621346;, + -15.250605;71.985199;59.394108;, + -15.298944;70.637657;60.014355;, + -15.658424;68.405617;58.417435;, + -15.881517;67.001724;56.228691;, + -15.969252;67.785751;55.123196;, + -15.787234;65.044144;44.833035;, + -16.311890;64.137360;44.826756;, + -15.985520;62.777939;45.304832;, + -15.565753;61.898857;45.735703;, + -17.476997;71.515564;49.979080;, + -17.666685;72.283302;49.454979;, + -17.496593;72.551018;49.791622;, + -17.235834;71.461693;50.544392;, + -17.321030;70.610649;50.363503;, + -17.721493;64.826424;44.666374;, + -17.617994;63.963326;44.954117;, + -17.641233;62.991528;45.373825;, + -17.702808;62.384628;45.580582;, + -17.503719;62.235477;45.405041;, + -17.214645;62.635960;45.039047;, + -17.454624;64.026939;44.611488;, + -17.486305;67.273705;44.342857;, + -16.981884;68.189659;44.315788;, + -17.319111;69.740105;44.662109;, + -17.795025;70.146683;45.105915;, + -17.665180;69.380302;44.897526;, + -17.693687;68.057755;44.480789;, + -17.367353;55.732864;49.276451;, + -17.603033;56.078396;49.090916;, + -17.605160;56.805744;49.610336;, + -17.369478;56.460213;49.795868;, + -15.472936;71.487747;47.478798;, + -15.202838;70.700668;46.413372;, + -17.537380;72.607475;48.042797;, + -17.718521;72.353806;47.703808;, + -17.632210;72.075851;47.314693;, + -17.704372;71.657677;46.520592;, + -17.298006;71.305359;45.955624;, + -16.765556;71.583923;46.387459;, + -17.031307;72.320404;47.474106;, + -17.602358;59.477318;47.236622;, + -17.394125;59.880875;47.002865;, + -17.477081;61.053162;46.572697;, + -17.674273;61.202515;46.749283;, + -17.736586;60.467724;47.270435;, + -16.183525;61.853733;46.266216;, + -16.565636;61.401821;46.549980;, + -16.432093;60.244560;47.006794;, + -16.018494;59.781609;47.083752;, + -15.774214;60.941624;46.644413;, + -17.282442;56.325546;47.880959;, + -17.057690;55.958496;48.038124;, + -16.647417;56.352184;47.652000;, + -16.585321;57.122021;47.273716;, + -17.001896;57.588127;47.207531;, + -17.288742;57.185337;47.428646;, + -15.462021;56.205631;47.969166;, + -14.615860;55.455399;47.439404;, + -15.475274;59.141663;46.797791;, + -15.730730;57.946342;47.180832;, + -15.798254;57.165806;47.545010;, + -8.445348;40.588070;59.654636;, + -7.278510;39.094028;59.898464;, + -6.654146;38.770531;57.926445;, + -7.458086;40.307079;54.648247;, + -9.828319;42.345741;53.625164;, + -10.191217;42.303234;56.659534;, + -4.566577;37.981155;65.199509;, + -3.095984;38.031998;67.529678;, + -2.411773;37.506966;67.308975;, + -2.439468;37.185844;65.011452;, + -3.987151;37.529453;63.242748;, + -7.714421;47.308811;43.157204;, + -8.049258;44.606380;41.254444;, + -6.923997;49.765636;40.291908;, + -7.906905;51.757496;43.185513;, + -5.034308;41.098293;49.664669;, + -5.924514;37.964451;49.232517;, + -7.618621;39.077587;48.033279;, + -7.929698;44.502201;46.021900;, + -8.122182;48.950886;46.050209;, + -9.087849;46.348259;49.153736;, + -6.570920;44.494156;50.192978;, + -9.377964;32.507309;43.848045;, + -8.752393;35.209740;45.489132;, + -7.924005;29.785124;47.506119;, + -6.942506;32.835922;36.246323;, + -7.997331;36.389206;37.566708;, + -9.269050;31.085709;38.438145;, + -5.026693;51.522896;39.552273;, + -3.825413;48.113850;38.322987;, + -2.217535;51.807980;39.149200;, + -5.770691;27.953976;51.289192;, + -4.258096;26.840841;52.409973;, + -14.393597;77.704041;61.829361;, + -14.713458;75.810089;60.518398;, + -9.962842;51.383026;45.418407;, + -12.572998;52.681652;46.818928;, + -11.410388;71.412788;66.828568;, + -11.823878;72.111282;66.787140;, + -10.865562;72.920639;67.524742;, + -9.757876;72.328529;67.772369;, + -9.662718;71.817146;67.674042;, + -10.356916;71.710754;67.467834;, + -12.698816;64.099892;66.268402;, + -13.037525;65.302979;65.766319;, + -12.597655;66.151749;66.249695;, + -11.851852;65.260712;66.830208;, + -11.350214;64.474258;67.163437;, + -11.757308;64.162216;67.085007;, + -6.766061;66.263695;68.781013;, + -6.216946;66.492447;68.869522;, + -5.420580;66.654190;68.999702;, + -5.795310;66.145882;68.879105;, + -6.606440;65.917046;68.748558;, + -3.320212;69.375824;69.355331;, + -3.709178;68.309135;68.969109;, + -4.438835;68.674232;68.849876;, + -4.890217;69.410423;68.822868;, + -4.989970;69.919693;68.927238;, + -4.149621;70.250198;69.340469;, + -10.614668;69.347672;67.888069;, + -10.116972;69.031830;68.220833;, + -10.474522;68.229591;68.132561;, + -11.167147;67.985580;67.780556;, + -11.836740;68.545883;67.245644;, + -11.641810;69.105743;67.264893;, + -6.151947;45.663696;67.791992;, + -4.526884;45.235153;68.449783;, + -4.146754;44.288376;68.208298;, + -5.771818;44.716919;67.550507;, + -10.450169;70.821953;67.907776;, + -9.765457;70.555244;68.220161;, + -10.446616;70.475075;67.861671;, + -11.461811;70.225883;67.223770;, + -11.484657;70.544380;67.228043;, + -7.470517;71.123924;68.610703;, + -6.279786;70.515015;68.889984;, + -5.857738;69.792030;69.041931;, + -6.325098;70.114395;68.970451;, + -7.503110;70.711578;68.750259;, + -8.226480;70.998123;68.542450;, + -11.757306;66.061752;67.182938;, + -12.601673;66.949631;66.694183;, + -12.539265;67.224754;66.799522;, + -11.842525;66.625931;67.309013;, + -11.209784;66.065163;67.525764;, + -8.280282;65.338531;68.297150;, + -9.418466;65.381676;67.974045;, + -10.128361;65.908348;67.834045;, + -9.527828;65.743866;67.987259;, + -8.435413;65.687355;68.321404;, + -5.819896;67.066292;68.770218;, + -5.441578;66.767700;68.786415;, + -6.236395;66.607925;68.646599;, + -6.614712;66.906517;68.630394;, + -11.348783;70.134789;66.847923;, + -10.339741;70.382629;67.493866;, + -10.382211;70.102104;67.500931;, + -11.391253;69.854263;66.854988;, + -6.542440;69.634361;68.798340;, + -7.746741;69.958893;68.556709;, + -8.281987;70.288345;68.319221;, + -8.238889;70.568634;68.310120;, + -7.507647;70.645966;68.558647;, + -6.346445;70.041153;68.809387;, + -11.501963;67.061974;67.315300;, + -11.152501;66.503914;67.438225;, + -11.688239;66.665207;67.208046;, + -12.363090;67.291313;66.688377;, + -12.188178;67.618729;66.799240;, + -8.220766;66.419502;68.373581;, + -7.848414;66.116623;68.406441;, + -8.381545;65.898521;68.278526;, + -9.477689;65.951813;67.955978;, + -9.894917;66.509720;67.920815;, + -9.171124;66.759315;68.210503;, + -17.429979;70.690262;47.136501;, + -17.300325;71.068329;47.941162;, + -17.023735;70.899750;48.289326;, + -16.861496;70.700005;48.118645;, + -16.944355;70.155487;47.524551;, + -17.236248;69.977158;46.890572;, + -17.226145;68.629349;45.660595;, + -16.823431;68.867996;46.195717;, + -16.729546;68.371811;45.875668;, + -16.873161;67.340813;45.524662;, + -17.105501;66.543564;45.306343;, + -17.364603;67.335907;45.122231;, + -17.210119;64.694969;45.653248;, + -16.824369;65.503990;45.698051;, + -16.693214;64.944427;45.835949;, + -16.865488;63.931744;46.212234;, + -17.217360;63.707901;46.045494;, + -17.257675;62.592293;47.044037;, + -16.951664;62.847736;47.248653;, + -16.837200;62.523624;47.585892;, + -16.968355;61.957218;48.121510;, + -17.261364;61.378471;48.161098;, + -17.422873;61.297504;47.813133;, + -17.417713;61.989571;47.233940;, + -17.641174;59.537712;47.829380;, + -17.572170;59.655956;48.204098;, + -17.551355;59.356380;48.625698;, + -17.610889;58.393185;48.722862;, + -17.640314;57.667088;48.205170;, + -17.649786;58.512043;47.733288;, + -17.048664;58.888443;50.137520;, + -17.266785;59.234547;49.939693;, + -17.237478;60.194298;49.885609;, + -17.031002;61.167274;50.192562;, + -16.847815;61.964878;50.507847;, + -16.794952;61.394268;50.541176;, + -16.881783;59.817486;50.241066;, + -16.520054;67.426628;49.977383;, + -16.340061;67.565254;49.576904;, + -16.329565;67.737488;49.665955;, + -16.615074;68.525681;49.726234;, + -16.931223;69.285706;49.834728;, + -16.825703;68.358887;50.174931;, + -17.551683;71.775742;48.843681;, + -17.362616;71.012024;49.371750;, + -16.936705;70.317307;49.319000;, + -16.958307;70.820000;49.096962;, + -17.196766;71.293510;48.824539;, + -17.364233;71.554535;48.518509;, + -16.104570;66.411118;49.371330;, + -15.935796;66.244766;48.838696;, + -15.850468;66.336823;48.616936;, + -15.866637;66.633751;48.735458;, + -16.035194;66.980598;49.101681;, + -16.187799;66.850029;49.515789;, + -16.126511;65.664818;49.415100;, + -16.190468;65.289612;49.597702;, + -16.041357;65.036949;49.353294;, + -15.899192;65.163132;49.153240;, + -15.851497;65.262131;48.876595;, + -15.929707;65.511154;48.894043;, + -16.490780;64.863365;50.058357;, + -16.720278;64.048309;50.266247;, + -16.791843;63.235886;49.945076;, + -16.568014;63.725044;49.778568;, + -16.373796;64.287704;49.843987;, + -16.368130;64.613602;49.802601;, + -17.217245;60.928139;48.799614;, + -16.907705;61.495392;48.765743;, + -16.815966;61.430393;48.922810;, + -16.765753;61.620747;49.208321;, + -16.750641;62.064793;49.391998;, + -17.015625;61.599758;49.547829;, + -17.299763;60.700314;49.200974;, + -15.614582;65.022964;47.637421;, + -15.567803;65.459961;48.141235;, + -15.567249;65.398903;48.325111;, + -15.481506;65.150154;48.319054;, + -15.194538;65.020020;48.325905;, + -14.993324;64.845505;48.207409;, + -15.239534;64.746971;48.103077;, + -15.478746;64.410210;48.011654;, + -15.595269;64.437210;47.602276;, + -15.577514;66.367973;47.512394;, + -15.587451;66.170380;48.126865;, + -15.597684;65.873161;48.000294;, + -15.594285;65.462585;47.465916;, + -15.623907;65.954384;47.004478;, + -16.163324;69.702736;47.006084;, + -16.325090;70.179176;47.432697;, + -16.250225;70.720009;48.027470;, + -15.931003;70.309883;48.304401;, + -15.873635;69.724388;47.707878;, + -15.683133;67.779671;46.594791;, + -15.731870;67.422462;46.281384;, + -15.854837;66.999779;45.793983;, + -16.054199;66.752342;45.468372;, + -16.222563;67.364136;45.404732;, + -16.119137;68.397461;45.749371;, + -15.815002;68.405243;46.444931;, + -16.121750;63.590012;46.468613;, + -16.268213;63.939720;46.142395;, + -16.091532;64.937843;45.725086;, + -15.811086;65.184181;46.013538;, + -15.725762;64.678902;46.459305;, + -15.859744;64.082863;46.497070;, + -15.926024;62.989491;47.503284;, + -15.843936;62.895470;47.927868;, + -15.889503;62.652355;48.086254;, + -15.987683;62.236328;48.207397;, + -16.216883;61.851406;48.240868;, + -16.364000;61.953060;48.036350;, + -16.214388;62.510639;47.489380;, + -15.595205;68.402351;48.685631;, + -15.764951;68.966614;49.253052;, + -15.941114;69.119171;49.475651;, + -15.975425;68.539047;49.658321;, + -15.736507;67.748260;49.593555;, + -15.532450;67.764122;48.843464;, + -16.346699;71.171959;48.547527;, + -16.586071;71.314072;48.751896;, + -16.308315;70.874519;49.045010;, + -16.068941;70.732407;48.840641;, + -15.518588;67.185043;48.375042;, + -15.668723;67.181129;49.142185;, + -15.708892;66.982887;49.023090;, + -15.584141;66.642441;48.652946;, + -15.499434;66.834618;48.047215;, + -15.092333;64.988647;49.170685;, + -14.719754;65.032219;48.968830;, + -15.088419;65.204224;48.722855;, + -15.558498;65.271629;48.793575;, + -15.560716;65.164146;49.081577;, + -15.725241;64.271202;49.771698;, + -15.177734;64.013451;49.696068;, + -14.787019;64.137657;49.657894;, + -15.119205;64.553688;49.607170;, + -15.572768;64.774559;49.574314;, + -15.788092;64.616272;49.700668;, + -15.866501;61.957813;49.102505;, + -16.104591;61.579231;49.139591;, + -16.162405;61.394108;48.852608;, + -15.924313;61.772690;48.815525;, + -15.717142;63.853062;48.277557;, + -15.248356;64.229958;48.236816;, + -14.928309;64.044220;48.320805;, + -15.315211;63.808681;48.458256;, + -15.750184;63.597157;48.425735;, + -15.838925;62.957794;48.812828;, + -15.734231;63.319706;48.668522;, + -15.316200;63.570396;48.738605;, + -15.018495;63.530445;48.836395;, + -15.316642;63.369987;49.007088;, + -15.719042;63.048027;49.053600;, + -15.980401;62.618446;49.327629;, + -15.722883;62.949089;49.349140;, + -15.299875;63.228001;49.333504;, + -14.944921;63.170467;49.313648;, + -15.276262;63.393970;49.504761;, + -15.797068;63.623280;49.678589;, + -16.084009;63.113098;49.537724;, + -13.713379;64.330490;47.964046;, + -14.052535;64.570992;47.942337;, + -13.642416;64.727051;47.977783;, + -13.303260;64.486542;47.999493;, + -13.622803;64.867424;48.405872;, + -13.966632;65.018639;48.594540;, + -13.617676;64.821175;48.841949;, + -13.268164;64.565086;48.723537;, + -13.279479;64.634613;48.428219;, + -13.639128;64.418907;49.285206;, + -13.985892;64.368164;49.509857;, + -13.685705;63.932621;49.534199;, + -13.345568;63.706188;49.357521;, + -13.317171;63.849289;49.209923;, + -13.310544;64.126472;49.161942;, + -13.407900;63.991501;48.212700;, + -13.378046;63.842590;48.457138;, + -13.448744;63.599464;48.515327;, + -13.854336;63.502201;48.416882;, + -14.191032;63.583447;48.318527;, + -13.815295;63.829620;48.172535;, + -13.448471;63.334648;48.762100;, + -13.445812;63.215389;48.942604;, + -13.849804;63.106457;48.948494;, + -14.219306;63.163155;48.878448;, + -13.859849;63.274899;48.680103;, + -13.760653;63.319157;49.397713;, + -14.160416;63.179287;49.390675;, + -13.826283;62.948902;49.207973;, + -13.426521;63.088772;49.215008;, + -14.635970;54.643333;55.040348;, + -14.147105;54.452450;57.104122;, + -13.158237;52.062576;58.359673;, + -13.383351;51.207062;56.417542;, + -14.475186;52.802021;53.698296;, + -15.304926;68.186958;61.412601;, + -14.881803;70.420540;62.992817;, + -14.420024;70.296165;64.247795;, + -14.572822;68.117760;63.612282;, + -15.007770;66.809219;62.450409;, + -15.942458;60.483253;55.162083;, + -15.911017;62.698605;56.534737;, + -15.702338;64.100548;58.725273;, + -15.429958;62.728092;59.776882;, + -15.204959;60.373241;59.487785;, + -15.173355;58.842800;58.182579;, + -15.579103;59.052357;56.106335;, + -16.138069;62.572739;52.645168;, + -16.264805;60.348454;51.283993;, + -16.459799;60.184284;50.041332;, + -16.446999;61.758488;50.400814;, + -16.268988;63.355892;51.544556;, + -10.984770;59.171497;67.685600;, + -10.020209;59.249851;68.473320;, + -8.955151;58.376186;68.852272;, + -8.749995;56.214470;68.792267;, + -9.638556;54.576092;68.034088;, + -10.808270;56.659454;67.306381;, + -2.919356;66.059219;69.545708;, + -2.935508;67.427605;69.470802;, + -2.918927;68.351173;69.428009;, + -2.480527;69.424149;69.710426;, + -1.804423;69.821587;69.985138;, + -1.545340;68.905617;69.955627;, + -2.229242;66.840546;69.764442;, + -0.336191;68.430237;70.273201;, + 0.451886;68.430237;70.273201;, + 1.170602;66.378647;70.287239;, + 0.776565;65.605095;70.453270;, + -0.660870;65.605095;70.453270;, + -1.054910;66.378647;70.287239;, + -0.340003;62.900276;71.266731;, + -1.058722;62.556232;71.091965;, + -0.660870;63.757217;70.827621;, + 0.776565;63.757217;70.827621;, + 1.174414;62.556232;71.091965;, + 0.455698;62.900276;71.266731;, + -1.167291;72.975906;71.066788;, + -1.561331;72.093285;70.835541;, + -2.229468;71.696121;70.544289;, + -3.073710;72.557281;70.563393;, + -4.494940;62.101410;69.479050;, + -5.105907;62.962933;69.143433;, + -4.820986;63.796482;69.076340;, + -3.863764;64.606781;69.322395;, + -3.894372;63.243977;69.496239;, + -5.328853;60.484348;69.611397;, + -6.107750;61.054867;69.396408;, + -6.771271;62.188259;69.118797;, + -5.982145;62.362251;69.253105;, + -5.354429;61.491180;69.538467;, + -8.287384;62.278648;68.682831;, + -7.628970;61.197292;69.140694;, + -8.336544;60.522438;69.069862;, + -9.515740;61.319351;68.567192;, + -9.953496;62.560196;68.243744;, + -9.432715;62.866348;68.253067;, + -11.047081;62.546486;67.962914;, + -10.617968;61.313049;68.317123;, + -11.533367;61.247047;67.476128;, + -11.962482;62.480480;67.121918;, + 2.654264;41.449165;68.624062;, + 3.503563;42.233704;68.253677;, + 4.937797;42.776821;67.453926;, + 5.765529;41.666725;65.621597;, + 4.743902;39.976799;65.832298;, + 3.066870;40.302361;68.035011;, + 14.579695;51.746113;48.798912;, + 12.935205;47.844864;50.501919;, + 13.287230;47.816036;53.537487;, + 14.074833;50.054565;53.477966;, + 15.182524;51.644341;50.761562;, + 15.425858;52.496346;49.328674;, + 14.663563;60.533600;62.358627;, + 13.649384;58.152863;63.610909;, + 13.078305;58.564976;64.792267;, + 13.282856;61.067101;65.229462;, + 13.687963;62.304844;64.865723;, + 14.044406;63.485863;64.339012;, + 14.430035;64.191902;63.807819;, + 14.883218;62.889500;62.645046;, + 15.786164;54.844639;50.363594;, + 15.953128;56.684170;51.706242;, + 16.442099;58.083145;50.780964;, + 16.657810;57.916912;49.540932;, + 16.677040;57.052597;49.445042;, + 16.637686;56.337196;48.919449;, + 16.504915;56.612152;48.529644;, + 16.161591;55.654251;48.952625;, + 14.350174;73.032753;65.109230;, + 13.859351;72.909081;66.356583;, + 13.207247;73.365410;66.984734;, + 12.295963;74.145042;67.802490;, + 13.981975;76.274246;65.799950;, + 14.301835;74.380287;64.488983;, + 16.420151;72.598770;49.611454;, + 16.924391;72.864502;50.189095;, + 16.681463;71.776100;50.947868;, + 13.406377;70.147194;64.970589;, + 13.630649;67.960876;64.396080;, + 13.190571;67.260254;64.888390;, + 12.815522;68.129967;65.442223;, + 12.741013;68.411827;65.535583;, + 12.595016;68.737000;65.669327;, + 12.463537;69.289749;65.733955;, + 12.441926;69.568321;65.742271;, + 12.461246;69.888283;65.738831;, + 12.779631;70.601143;65.617447;, + 4.619360;59.898464;69.912605;, + 3.914352;58.191391;69.761742;, + 4.369514;58.105072;69.919785;, + 4.258527;58.239124;70.071960;, + 3.973000;58.498222;70.159554;, + 3.777756;58.804951;70.155693;, + 3.329280;59.684910;70.235397;, + 2.940784;61.031204;70.194847;, + 3.333090;61.791996;69.916451;, + 4.036814;61.008068;69.727730;, + 3.034772;53.404091;70.938629;, + 2.208143;53.903660;70.912537;, + 1.908253;54.532791;70.915924;, + 2.501408;54.680038;70.815506;, + 3.227245;54.744785;70.582428;, + 3.308319;55.084583;70.448547;, + 3.437492;54.305473;70.619545;, + 7.917106;51.763470;68.922615;, + 8.830380;50.122650;68.182167;, + 8.129922;48.270035;68.304428;, + 6.561869;48.549271;69.168564;, + 6.365870;49.317665;69.504501;, + 7.020649;50.679249;69.380814;, + 5.486177;51.804302;70.890030;, + 4.838321;50.442738;71.028595;, + 3.772563;50.892250;71.572784;, + 4.186694;51.834652;71.563766;, + 4.639969;52.698963;71.277252;, + 4.971645;46.051064;69.184097;, + 4.053861;46.091690;69.693321;, + 4.081872;46.793549;69.870453;, + 5.445580;47.425457;69.456062;, + 7.050251;47.145229;68.633385;, + 6.604327;46.472694;68.538559;, + 1.214336;50.973583;71.694138;, + 1.204623;51.423996;71.779518;, + 1.212656;52.051891;71.685745;, + 1.679286;52.530037;71.605721;, + 2.522823;52.052967;71.641159;, + 2.065906;51.124401;71.635803;, + 13.137602;53.488663;61.239902;, + 13.234347;55.010292;62.553223;, + 14.254332;57.389984;61.303249;, + 14.157586;55.868359;59.989929;, + 11.220590;50.871937;64.476662;, + 11.133315;49.345627;63.166481;, + 11.457245;48.442810;61.255726;, + 10.604994;46.236229;61.293800;, + 8.695706;44.714546;64.299896;, + 8.132330;45.674198;66.296745;, + 8.479852;46.637093;66.527420;, + 8.855523;47.333950;66.631050;, + 9.598343;49.163662;66.510292;, + 10.725574;51.240044;65.681923;, + 1.590202;58.398350;72.686012;, + 1.557539;59.261425;72.428749;, + 2.000650;59.340534;71.866264;, + 2.453526;58.869293;71.594749;, + 2.569266;58.564266;71.700531;, + 2.608980;58.257072;71.856972;, + 2.387675;58.206673;72.014107;, + 1.927747;58.122028;72.386436;, + 1.625123;57.558842;72.547653;, + 2.168747;57.660461;72.258942;, + 2.233865;57.221329;72.202080;, + 1.742114;56.943577;72.311104;, + 1.249707;57.032932;72.596863;, + 3.174846;58.630623;70.641769;, + 3.017052;58.531845;70.941544;, + 2.780896;58.656223;71.097099;, + 2.622163;58.943634;70.957291;, + 2.954322;58.924690;70.598763;, + 4.032869;55.572304;70.041840;, + 3.928171;56.347786;69.903954;, + 4.183709;56.821293;69.814964;, + 4.204257;57.287357;69.743599;, + 4.099401;58.045750;69.612915;, + 5.227420;58.717506;69.747047;, + 5.917409;57.970192;69.387802;, + 5.818560;55.781525;69.312447;, + 4.949705;54.668350;69.775490;, + 4.251379;57.244923;70.552475;, + 4.312139;57.593311;70.295357;, + 4.374818;57.438969;70.049438;, + 4.371503;56.976295;70.144569;, + 4.322558;56.894928;70.444588;, + 3.706894;57.666695;71.185127;, + 3.523844;58.065258;71.087090;, + 3.684032;58.165226;70.788643;, + 3.952336;57.893749;70.692024;, + 3.898730;57.561813;70.960518;, + 3.828186;55.370281;70.761353;, + 3.638421;55.051468;70.611397;, + 2.938384;54.988895;70.923553;, + 2.955018;55.237701;71.154488;, + 3.585764;55.416473;71.000565;, + 4.270908;56.153671;70.536667;, + 4.278454;56.246273;70.237022;, + 4.033355;55.755974;70.291489;, + 3.950112;55.439445;70.483299;, + 4.131103;55.782383;70.614700;, + 3.476142;57.598080;71.641861;, + 3.200772;57.947784;71.731819;, + 3.136734;58.246376;71.555511;, + 3.367636;58.117046;71.396477;, + 3.554811;57.720852;71.496246;, + 3.262567;56.789368;71.787590;, + 2.917169;56.969940;71.952415;, + 2.822125;57.428493;71.961281;, + 3.083823;57.499275;71.833702;, + 3.342518;57.136875;71.731987;, + 3.220440;55.851723;71.649239;, + 2.579464;55.692970;71.788246;, + 2.273904;56.120026;72.073334;, + 2.796321;56.379002;72.014671;, + 3.135255;56.201847;71.837547;, + 3.928730;56.122169;71.094490;, + 3.707905;56.139133;71.357254;, + 3.613183;56.487053;71.543762;, + 3.694555;56.835163;71.491699;, + 3.797751;56.967865;71.362190;, + 3.970327;56.847206;71.126411;, + 4.048297;56.500839;71.012955;, + 2.477874;59.370174;70.980934;, + 2.021420;59.838963;71.250046;, + 1.658818;60.758423;71.142464;, + 2.360240;60.233025;70.703400;, + 2.818039;59.358707;70.627777;, + 5.985386;72.868355;69.812210;, + 9.154104;73.717827;68.902939;, + 7.998795;73.155823;69.069405;, + 6.809360;72.552437;69.361465;, + 7.049986;67.847763;68.938004;, + 7.229618;68.489220;68.942162;, + 8.453979;68.821220;68.766014;, + 8.808260;68.018349;68.671463;, + 7.845464;67.687729;68.801422;, + 6.485291;71.293625;68.760429;, + 7.674726;71.897003;68.468361;, + 7.571912;71.390457;68.356995;, + 6.382478;70.787079;68.649055;, + 9.031637;63.725613;67.823822;, + 7.882623;63.148247;68.257492;, + 7.099626;63.322628;68.406448;, + 6.819228;64.155365;68.361183;, + 7.054543;64.740326;68.286102;, + 7.855459;64.507843;68.125900;, + 8.998738;64.549225;67.816406;, + 9.627233;64.526329;67.588211;, + 5.131092;68.108627;68.910416;, + 5.325842;67.702225;68.891853;, + 5.150118;67.060791;68.905960;, + 4.776736;66.762360;68.945175;, + 5.157436;66.255524;68.850845;, + 4.911710;65.666992;68.895134;, + 3.957364;66.485794;69.114601;, + 3.926550;67.410515;69.067841;, + 4.664679;67.765022;68.960190;, + 14.086849;79.561020;64.637955;, + 16.739792;67.403618;50.887012;, + 16.461876;66.463646;50.675999;, + 16.355726;66.024963;50.538170;, + 16.463581;65.639847;50.705421;, + 16.634022;64.809120;50.940807;, + 16.577030;64.238647;50.971241;, + 16.362127;65.836792;52.110813;, + 16.681547;68.256050;51.076977;, + 15.875778;69.213470;44.900475;, + 15.339758;69.450462;45.349747;, + 14.734314;69.212395;45.168884;, + 15.497775;67.644539;44.621346;, + 15.366291;71.985199;59.394108;, + 16.084938;67.785751;55.123196;, + 15.997204;67.001724;56.228691;, + 15.774111;68.405617;58.417435;, + 15.414630;70.637657;60.014355;, + 15.681439;61.898857;45.735703;, + 16.101208;62.777939;45.304836;, + 16.427576;64.137360;44.826752;, + 15.902921;65.044144;44.833035;, + 17.351522;71.461693;50.544392;, + 17.612280;72.551018;49.791622;, + 17.782373;72.283302;49.454979;, + 17.592686;71.515564;49.979080;, + 17.436718;70.610649;50.363503;, + 17.837181;64.826424;44.666374;, + 17.570311;64.026939;44.611488;, + 17.330330;62.635960;45.039047;, + 17.619406;62.235477;45.405041;, + 17.818495;62.384628;45.580582;, + 17.756922;62.991528;45.373825;, + 17.733683;63.963326;44.954117;, + 17.780867;69.380302;44.897526;, + 17.910711;70.146683;45.105915;, + 17.434797;69.740105;44.662109;, + 17.097572;68.189659;44.315792;, + 17.601992;67.273705;44.342861;, + 17.809376;68.057755;44.480789;, + 17.720846;56.805744;49.610336;, + 17.718719;56.078396;49.090916;, + 17.483042;55.732864;49.276451;, + 17.485168;56.460213;49.795868;, + 14.713079;70.462608;46.232510;, + 15.318524;70.700668;46.413372;, + 15.588622;71.487747;47.478798;, + 17.653069;72.607475;48.042797;, + 17.146994;72.320404;47.474106;, + 16.881243;71.583923;46.387459;, + 17.413694;71.305359;45.955624;, + 17.820061;71.657677;46.520592;, + 17.747896;72.075859;47.314693;, + 17.834208;72.353806;47.703804;, + 17.718044;59.477318;47.236622;, + 17.852270;60.467724;47.270435;, + 17.789957;61.202515;46.749283;, + 17.592766;61.053162;46.572697;, + 17.509811;59.880875;47.002865;, + 16.299212;61.853733;46.266216;, + 15.889900;60.941624;46.644413;, + 16.134180;59.781609;47.083752;, + 16.547779;60.244560;47.006794;, + 16.681320;61.401821;46.549984;, + 17.117582;57.588127;47.207531;, + 16.701010;57.122021;47.273716;, + 16.763103;56.352184;47.652000;, + 17.173376;55.958496;48.038124;, + 17.398129;56.325546;47.880959;, + 17.404427;57.185337;47.428650;, + 15.577708;56.205627;47.969166;, + 15.913940;57.165806;47.545010;, + 15.846416;57.946342;47.180832;, + 15.590961;59.141663;46.797791;, + 14.731544;55.455399;47.439404;, + 9.944007;42.345741;53.625164;, + 7.573774;40.307079;54.648247;, + 6.769834;38.770535;57.926445;, + 7.394196;39.094028;59.898464;, + 8.561033;40.588070;59.654636;, + 10.306905;42.303234;56.659534;, + 2.555157;37.185844;65.011452;, + 2.527462;37.506966;67.308975;, + 3.211673;38.031998;67.529678;, + 4.682263;37.981155;65.199509;, + 4.102839;37.529453;63.242748;, + 7.830108;47.308811;43.157204;, + 8.022593;51.757496;43.185513;, + 7.039683;49.765636;40.291908;, + 8.164946;44.606380;41.254444;, + 9.203535;46.348259;49.153736;, + 8.237869;48.950886;46.050209;, + 8.045384;44.502201;46.021900;, + 7.734308;39.077587;48.033279;, + 6.040202;37.964451;49.232517;, + 5.149999;41.098293;49.664669;, + 6.686608;44.494156;50.192978;, + 8.039693;29.785124;47.506119;, + 8.868079;35.209740;45.489132;, + 9.493651;32.507309;43.848045;, + 9.384735;31.085709;38.438145;, + 8.113016;36.389206;37.566708;, + 7.058194;32.835922;36.246323;, + 5.142379;51.522896;39.552273;, + 2.333225;51.807980;39.149200;, + 3.941101;48.113850;38.322987;, + 4.373784;26.840841;52.409973;, + 5.886379;27.953976;51.289192;, + 14.509283;77.704041;61.829361;, + 14.829144;75.810089;60.518398;, + 14.457141;70.604607;45.675373;, + 12.688684;52.681652;46.818928;, + 10.078528;51.383022;45.418407;, + 9.778404;71.817146;67.674042;, + 9.873562;72.328529;67.772369;, + 10.981249;72.920631;67.524742;, + 11.939566;72.111282;66.787140;, + 11.526075;71.412788;66.828560;, + 10.472603;71.710754;67.467834;, + 12.814504;64.099892;66.268402;, + 11.872994;64.162216;67.085007;, + 11.465900;64.474258;67.163437;, + 11.967539;65.260712;66.830208;, + 12.713342;66.151749;66.249695;, + 13.153212;65.302979;65.766319;, + 5.910997;66.145882;68.879105;, + 5.536267;66.654190;68.999702;, + 6.332633;66.492447;68.869522;, + 6.881747;66.263695;68.781013;, + 6.722126;65.917046;68.748558;, + 5.105657;69.919693;68.927238;, + 5.005903;69.410423;68.822868;, + 4.554521;68.674232;68.849876;, + 3.824864;68.309135;68.969109;, + 3.435898;69.375824;69.355331;, + 4.265308;70.250198;69.340469;, + 11.952425;68.545883;67.245644;, + 11.282833;67.985580;67.780556;, + 10.590207;68.229599;68.132561;, + 10.232657;69.031830;68.220833;, + 10.730354;69.347672;67.888069;, + 11.757496;69.105743;67.264893;, + 6.267634;45.663696;67.791992;, + 5.887505;44.716919;67.550507;, + 4.262442;44.288372;68.208298;, + 4.642571;45.235153;68.449783;, + 10.565856;70.821953;67.907776;, + 11.600344;70.544380;67.228043;, + 11.577497;70.225883;67.223770;, + 10.562302;70.475075;67.861671;, + 9.881144;70.555244;68.220161;, + 7.618796;70.711578;68.750259;, + 6.440785;70.114388;68.970451;, + 5.973425;69.792030;69.041931;, + 6.395473;70.515007;68.889984;, + 7.586203;71.123924;68.610703;, + 8.342167;70.998123;68.542450;, + 11.872992;66.061752;67.182938;, + 11.325470;66.065163;67.525764;, + 11.958210;66.625931;67.309013;, + 12.654950;67.224754;66.799522;, + 12.717360;66.949631;66.694183;, + 8.395967;65.338531;68.297150;, + 8.551100;65.687355;68.321404;, + 9.643514;65.743866;67.987259;, + 10.244047;65.908348;67.834045;, + 9.534150;65.381676;67.974045;, + 6.352082;66.607925;68.646599;, + 5.557265;66.767700;68.786423;, + 5.935583;67.066292;68.770218;, + 6.730400;66.906517;68.630394;, + 10.497897;70.102104;67.500931;, + 10.455427;70.382629;67.493866;, + 11.464467;70.134789;66.847923;, + 11.506937;69.854263;66.854988;, + 7.623333;70.645973;68.558647;, + 8.354575;70.568634;68.310120;, + 8.397674;70.288345;68.319221;, + 7.862427;69.958893;68.556709;, + 6.658127;69.634361;68.798340;, + 6.462132;70.041153;68.809387;, + 12.478778;67.291313;66.688377;, + 11.803926;66.665207;67.208046;, + 11.268188;66.503914;67.438225;, + 11.617651;67.061974;67.315300;, + 12.303864;67.618729;66.799240;, + 8.336453;66.419510;68.373581;, + 9.286811;66.759315;68.210503;, + 10.010603;66.509720;67.920815;, + 9.593375;65.951813;67.955978;, + 8.497231;65.898521;68.278526;, + 7.964100;66.116623;68.406441;, + 17.060043;70.155487;47.524548;, + 16.977182;70.700005;48.118645;, + 17.139421;70.899750;48.289326;, + 17.416012;71.068329;47.941158;, + 17.545664;70.690262;47.136501;, + 17.351934;69.977158;46.890572;, + 17.221189;66.543564;45.306343;, + 16.988846;67.340813;45.524662;, + 16.845232;68.371811;45.875668;, + 16.939117;68.867996;46.195717;, + 17.341833;68.629349;45.660599;, + 17.480291;67.335907;45.122231;, + 16.981171;63.931744;46.212234;, + 16.808901;64.944427;45.835949;, + 16.940056;65.503990;45.698055;, + 17.325806;64.694969;45.653248;, + 17.333046;63.707901;46.045494;, + 17.373362;62.592293;47.044037;, + 17.533400;61.989571;47.233940;, + 17.538557;61.297504;47.813133;, + 17.377050;61.378471;48.161098;, + 17.084042;61.957218;48.121510;, + 16.952885;62.523624;47.585892;, + 17.067348;62.847736;47.248653;, + 17.756001;57.667091;48.205170;, + 17.726576;58.393188;48.722862;, + 17.667044;59.356384;48.625698;, + 17.687859;59.655956;48.204098;, + 17.756863;59.537712;47.829380;, + 17.765472;58.512043;47.733288;, + 17.164349;58.888443;50.137520;, + 16.997469;59.817486;50.241066;, + 16.910639;61.394268;50.541176;, + 16.963501;61.964878;50.507847;, + 17.146688;61.167274;50.192562;, + 17.353167;60.194298;49.885605;, + 17.382475;59.234547;49.939693;, + 17.046909;69.285706;49.834724;, + 16.730762;68.525681;49.726234;, + 16.445251;67.737488;49.665955;, + 16.455748;67.565254;49.576904;, + 16.635740;67.426628;49.977383;, + 16.941389;68.358887;50.174927;, + 17.667368;71.775742;48.843681;, + 17.479918;71.554535;48.518509;, + 17.312452;71.293510;48.824539;, + 17.073994;70.820007;49.096962;, + 17.052391;70.317307;49.319000;, + 17.478302;71.012024;49.371750;, + 16.150881;66.980598;49.101681;, + 15.982324;66.633751;48.735458;, + 15.966154;66.336823;48.616936;, + 16.051481;66.244766;48.838696;, + 16.220257;66.411118;49.371330;, + 16.303486;66.850029;49.515789;, + 16.242199;65.664818;49.415100;, + 16.045393;65.511154;48.894043;, + 15.967184;65.262131;48.876595;, + 16.014877;65.163132;49.153240;, + 16.157045;65.036949;49.353294;, + 16.306154;65.289612;49.597702;, + 16.606468;64.863365;50.058353;, + 16.483816;64.613602;49.802601;, + 16.489483;64.287704;49.843987;, + 16.683701;63.725044;49.778568;, + 16.907532;63.235886;49.945076;, + 16.835964;64.048317;50.266247;, + 17.332932;60.928143;48.799614;, + 17.415449;60.700314;49.200974;, + 17.131311;61.599758;49.547829;, + 16.866329;62.064793;49.391998;, + 16.881441;61.620750;49.208321;, + 16.931652;61.430393;48.922810;, + 17.023394;61.495392;48.765743;, + 15.594433;64.410210;48.011654;, + 15.355221;64.746971;48.103077;, + 15.109011;64.845505;48.207409;, + 15.310225;65.020020;48.325905;, + 15.597193;65.150154;48.319054;, + 15.682936;65.398903;48.325111;, + 15.683491;65.459961;48.141235;, + 15.730268;65.022964;47.637424;, + 15.710956;64.437210;47.602276;, + 15.693200;66.367973;47.512394;, + 15.739593;65.954384;47.004478;, + 15.709971;65.462585;47.465916;, + 15.713370;65.873161;48.000294;, + 15.703137;66.170380;48.126865;, + 16.046690;70.309875;48.304401;, + 16.365913;70.720009;48.027470;, + 16.440777;70.179176;47.432697;, + 16.279011;69.702744;47.006084;, + 15.989321;69.724388;47.707878;, + 16.234823;68.397461;45.749371;, + 16.338247;67.364136;45.404732;, + 16.169886;66.752342;45.468372;, + 15.970524;66.999779;45.793983;, + 15.847556;67.422462;46.281384;, + 15.798820;67.779671;46.594791;, + 15.930688;68.405243;46.444931;, + 15.841449;64.678902;46.459305;, + 15.926772;65.184181;46.013538;, + 16.207218;64.937843;45.725086;, + 16.383900;63.939720;46.142395;, + 16.237436;63.590012;46.468613;, + 15.975430;64.082863;46.497070;, + 16.041712;62.989491;47.503284;, + 16.330074;62.510639;47.489380;, + 16.479687;61.953060;48.036350;, + 16.332567;61.851406;48.240868;, + 16.103371;62.236324;48.207397;, + 16.005190;62.652355;48.086254;, + 15.959622;62.895470;47.927872;, + 15.710892;68.402351;48.685627;, + 15.648136;67.764122;48.843464;, + 15.852196;67.748260;49.593555;, + 16.091112;68.539047;49.658321;, + 16.056801;69.119179;49.475651;, + 15.880638;68.966606;49.253052;, + 16.424000;70.874527;49.045010;, + 16.701757;71.314072;48.751896;, + 16.462385;71.171959;48.547527;, + 16.184629;70.732407;48.840641;, + 15.699827;66.642441;48.652946;, + 15.824578;66.982887;49.023090;, + 15.784410;67.181129;49.142185;, + 15.634274;67.185043;48.375042;, + 15.615120;66.834618;48.047215;, + 15.674185;65.271629;48.793575;, + 15.204105;65.204224;48.722855;, + 14.835443;65.032219;48.968830;, + 15.208019;64.988647;49.170685;, + 15.676402;65.164146;49.081577;, + 15.688455;64.774559;49.574314;, + 15.234891;64.553688;49.607170;, + 14.902706;64.137657;49.657894;, + 15.293420;64.013451;49.696068;, + 15.840926;64.271202;49.771698;, + 15.903778;64.616272;49.700668;, + 16.278091;61.394108;48.852608;, + 16.220278;61.579231;49.139591;, + 15.982187;61.957813;49.102505;, + 16.039999;61.772690;48.815525;, + 15.430898;63.808681;48.458256;, + 15.043995;64.044220;48.320808;, + 15.364042;64.229958;48.236816;, + 15.832829;63.853062;48.277557;, + 15.865870;63.597157;48.425735;, + 15.954613;62.957794;48.812828;, + 15.834729;63.048027;49.053604;, + 15.432328;63.369987;49.007088;, + 15.134183;63.530445;48.836395;, + 15.431887;63.570396;48.738605;, + 15.849918;63.319706;48.668522;, + 16.096088;62.618446;49.327629;, + 16.199696;63.113098;49.537724;, + 15.912754;63.623280;49.678589;, + 15.391949;63.393970;49.504761;, + 15.060607;63.170467;49.313648;, + 15.415560;63.228004;49.333504;, + 15.838570;62.949089;49.349140;, + 13.758102;64.727051;47.977783;, + 14.168221;64.570992;47.942337;, + 13.829064;64.330490;47.964046;, + 13.418945;64.486542;47.999493;, + 13.383851;64.565086;48.723537;, + 13.733362;64.821175;48.841949;, + 14.082317;65.018639;48.594540;, + 13.738489;64.867424;48.405872;, + 13.395164;64.634613;48.428219;, + 13.432858;63.849289;49.209923;, + 13.461254;63.706188;49.357521;, + 13.801391;63.932621;49.534199;, + 14.101580;64.368164;49.509857;, + 13.754813;64.418907;49.285202;, + 13.426229;64.126465;49.161942;, + 13.523585;63.991501;48.212700;, + 13.930980;63.829620;48.172535;, + 14.306720;63.583447;48.318527;, + 13.970022;63.502201;48.416882;, + 13.564429;63.599464;48.515327;, + 13.493731;63.842590;48.457138;, + 13.564157;63.334648;48.762100;, + 13.975533;63.274899;48.680103;, + 14.334991;63.163155;48.878448;, + 13.965490;63.106457;48.948494;, + 13.561500;63.215389;48.942604;, + 13.941969;62.948902;49.207970;, + 14.276101;63.179287;49.390675;, + 13.876339;63.319157;49.397709;, + 13.542208;63.088772;49.215008;, + 14.751657;54.643333;55.040348;, + 14.590873;52.802021;53.698296;, + 13.499039;51.207058;56.417542;, + 13.273923;52.062576;58.359673;, + 14.262792;54.452450;57.104122;, + 14.688508;68.117760;63.612282;, + 14.535710;70.296165;64.247795;, + 14.997487;70.420540;62.992817;, + 15.420611;68.186958;61.412601;, + 15.123456;66.809219;62.450409;, + 15.289042;58.842800;58.182579;, + 15.320647;60.373241;59.487785;, + 15.545645;62.728092;59.776886;, + 15.818025;64.100548;58.725273;, + 16.026705;62.698605;56.534737;, + 16.058146;60.483253;55.162083;, + 15.694791;59.052357;56.106335;, + 16.253756;62.572739;52.645172;, + 16.384674;63.355892;51.544556;, + 16.562685;61.758488;50.400814;, + 16.575487;60.184284;50.041332;, + 16.380493;60.348454;51.283993;, + 9.754243;54.576092;68.034088;, + 8.865682;56.214470;68.792267;, + 9.070836;58.376186;68.852272;, + 10.135895;59.249851;68.473312;, + 11.100456;59.171497;67.685600;, + 10.923957;56.659454;67.306381;, + 3.035042;66.059219;69.545708;, + 2.344930;66.840546;69.764442;, + 1.661030;68.905617;69.955627;, + 1.920111;69.821587;69.985138;, + 2.596213;69.424149;69.710426;, + 3.034613;68.351173;69.428009;, + 3.051194;67.427612;69.470802;, + 2.345155;71.696121;70.544289;, + 1.677019;72.093285;70.835541;, + 1.282981;72.975906;71.066788;, + 3.189397;72.557281;70.563393;, + 3.979451;64.606781;69.322395;, + 4.936673;63.796482;69.076340;, + 5.221594;62.962933;69.143433;, + 4.610626;62.101410;69.479050;, + 4.010058;63.243977;69.496239;, + 6.097832;62.362251;69.253105;, + 6.886958;62.188259;69.118797;, + 6.223436;61.054867;69.396408;, + 5.444539;60.484348;69.611397;, + 5.470115;61.491180;69.538467;, + 10.069182;62.560196;68.243744;, + 9.631428;61.319351;68.567192;, + 8.452230;60.522438;69.069862;, + 7.744656;61.197292;69.140694;, + 8.403069;62.278648;68.682831;, + 9.548402;62.866348;68.253067;, + 11.649054;61.247047;67.476128;, + 10.733654;61.313049;68.317123;, + 11.162767;62.546486;67.962914;, + 12.078169;62.480480;67.121918;, + -11.134334;90.849747;67.548500;, + 11.278329;90.396461;67.764954;, + 30.643127;-31.721945;45.652527;, + -30.350075;-31.719879;45.630089;, + -25.565304;-9.924385;26.239328;, + -30.142681;-11.598551;37.311020;, + -17.647087;-15.421692;74.962234;, + -17.647087;-15.421692;74.962234;, + 0.141491;-9.487318;27.256748;, + -16.966074;-26.227253;76.131516;, + -33.277031;-27.463528;63.505905;, + -34.720058;-12.484819;48.088928;, + -31.930122;-26.942392;51.688797;, + -34.720058;-12.484819;48.088928;, + -24.287395;-54.514771;54.652374;, + -24.509207;-50.845016;55.877068;, + -25.494289;-63.762321;51.551601;, + -29.140186;-40.740757;54.994888;, + -17.688755;-53.253067;77.227638;, + -26.760902;-31.939959;72.082443;, + -16.966076;-27.937576;75.155312;, + -24.332394;-52.295708;66.403946;, + -32.183464;-29.173838;63.505913;, + -32.056793;-28.913269;57.597359;, + -22.127073;-50.465675;31.947027;, + -20.920321;-28.152065;33.507904;, + -26.425222;-28.402384;42.598354;, + -31.930124;-28.652702;51.688805;, + 0.141491;-50.060425;24.873173;, + -11.193696;-29.430769;30.196033;, + -16.966074;-26.227253;76.131516;, + -30.976030;-51.338348;55.580246;, + -26.551552;-50.902012;43.763638;, + -34.720058;-12.484819;48.088928;, + -26.551552;-50.902012;43.763638;, + -31.930124;-28.652702;51.688805;, + -23.021046;22.545492;38.817097;, + -34.612175;17.843525;39.827816;, + -34.612186;-1.674418;34.789925;, + -34.666122;-7.473567;40.417480;, + -34.612183;9.271671;35.005108;, + 0.141491;-28.374607;32.989838;, + -16.294899;25.090145;38.449425;, + -9.139874;26.594124;45.452682;, + -14.724298;0.438756;65.826607;, + -19.722260;-1.585354;65.224693;, + -13.398946;24.794630;34.246376;, + -16.294899;25.090145;38.449425;, + -18.686239;24.355274;46.119999;, + -19.918121;19.050785;53.541157;, + -9.748887;22.893982;32.226307;, + 0.141491;22.863007;31.002354;, + -6.363874;23.153360;30.623175;, + -10.778057;22.307632;52.895199;, + -11.429913;16.434713;56.577648;, + -11.545969;16.822830;57.059074;, + -20.110298;5.311386;60.448208;, + -21.278301;13.060091;57.191551;, + -15.815639;16.328318;56.204815;, + -30.997221;-35.165527;63.780437;, + -32.118473;-39.484562;59.515316;, + -29.846169;-43.697968;61.553284;, + -29.388227;-40.601273;63.974194;, + -27.854467;-30.229647;72.082443;, + -29.736418;-23.496841;70.352409;, + -30.377008;-28.942865;68.092697;, + 25.849533;-9.924379;26.239330;, + 30.426910;-11.598546;37.311020;, + 17.931316;-15.421690;74.962234;, + 17.931316;-15.421690;74.962234;, + 17.250303;-26.227251;76.131516;, + 33.561260;-27.463524;63.505905;, + 32.214352;-26.942389;51.688797;, + 35.004288;-12.484816;48.088928;, + 24.793436;-50.845009;55.877064;, + 24.562241;-54.514763;54.652370;, + 25.705898;-63.638660;51.490501;, + 29.424416;-40.740753;54.994888;, + 17.972984;-53.253063;77.227638;, + 17.250305;-27.937574;75.155312;, + 27.045132;-31.939955;72.082443;, + 24.616623;-52.295704;66.403946;, + 32.467693;-29.173834;63.505913;, + 32.341022;-28.913265;57.597359;, + 21.204550;-28.152060;33.507904;, + 22.411303;-50.465668;31.947027;, + 26.709452;-28.402378;42.598354;, + 32.214352;-28.652699;51.688805;, + 11.477925;-29.430763;30.196033;, + 17.250303;-26.227251;76.131516;, + 31.260260;-51.338341;55.580242;, + 26.835781;-50.902004;43.763638;, + 35.004288;-12.484816;48.088928;, + 35.004288;-12.484816;48.088928;, + 26.835781;-50.902004;43.763638;, + 32.214352;-28.652699;51.688805;, + 23.305275;22.545494;38.817101;, + 34.896404;17.843529;39.827820;, + 34.896416;-1.674414;34.789925;, + 34.950352;-7.473563;40.417480;, + 34.896412;9.271675;35.005108;, + 16.579128;25.090147;38.449429;, + 15.005043;0.438756;66.317261;, + 20.006489;-1.585352;65.224693;, + 13.683175;24.794634;34.246380;, + 16.579128;25.090147;38.449429;, + 18.970469;24.355276;46.119999;, + 20.202351;19.050787;53.541157;, + 10.033116;22.893986;32.226311;, + 6.648103;23.153364;30.623177;, + 11.062286;22.307634;52.895199;, + 11.714142;16.434715;57.068302;, + 11.825384;16.819580;57.419716;, + 20.394527;5.311388;60.448208;, + 21.562531;13.060093;57.191551;, + 16.099869;16.328320;56.204815;, + 31.281450;-35.165524;63.780437;, + 32.402702;-39.484558;59.515316;, + 30.130398;-43.697964;61.553280;, + 29.672457;-40.601269;63.974190;, + 28.138697;-30.229643;72.082443;, + 30.020647;-23.496838;70.352409;, + 30.661238;-28.942862;68.092697;, + -29.135050;-70.748413;50.137466;, + -37.889961;-84.783730;46.673920;, + -41.760616;-103.151527;46.673916;, + -43.113548;-194.904678;46.172501;, + -8.177140;-173.738678;44.589825;, + -11.967894;-201.991714;48.101704;, + -35.253540;-336.022400;70.615288;, + -37.752792;-344.579865;81.882141;, + -36.447479;-347.590393;81.989037;, + -32.971939;-348.840668;75.068268;, + -30.483822;-349.513580;64.542366;, + -30.277090;-349.285034;45.291451;, + -30.731056;-349.140869;32.597919;, + -44.998409;-349.114563;30.769142;, + -47.579365;-349.201599;38.020824;, + -49.480873;-349.253357;42.813530;, + -53.720398;-349.475220;61.544106;, + -54.063526;-348.805878;72.346741;, + -50.995792;-347.566376;80.111809;, + -50.995792;-347.566376;80.111809;, + -36.447479;-347.590393;81.989037;, + -50.401588;-344.387238;80.484764;, + -30.811893;-349.229279;40.184383;, + -25.375702;-326.803925;43.166012;, + -25.361750;-319.393433;40.717945;, + -48.911896;-319.507538;43.118351;, + -53.350098;-311.978485;48.287319;, + -17.516390;-311.220673;43.257233;, + -4.658672;-143.854736;42.160900;, + 0.100870;-118.350113;30.024460;, + -21.858656;-301.316620;40.265823;, + -48.634773;-301.610474;45.850082;, + -15.366711;-254.579529;44.539597;, + -42.656788;-120.929993;49.355263;, + -12.445428;-224.292206;47.498665;, + -47.093388;-334.957916;67.363968;, + -46.985233;-330.924652;60.877213;, + -52.006966;-325.347748;41.525673;, + -32.159611;-328.701721;61.163334;, + -37.431126;-348.022339;28.784142;, + -37.431126;-348.022339;28.784142;, + -36.497189;-333.552704;31.073109;, + -43.124073;-327.569916;63.163582;, + -37.508007;-327.823730;63.943375;, + -32.027699;-330.586823;57.891068;, + -30.829683;-335.353180;51.935188;, + -30.289175;-336.679779;37.674358;, + -30.290890;-334.903290;34.539791;, + -46.926067;-335.870056;46.077358;, + -48.218380;-333.043976;53.745155;, + -33.346500;-333.002716;32.172970;, + -36.497189;-333.552704;31.073109;, + -32.159611;-328.701721;61.163334;, + -47.738998;-332.348511;57.905354;, + -46.985233;-330.924652;60.877213;, + -39.092888;-333.629852;32.004887;, + -42.781075;-334.302216;33.467194;, + -30.620396;-337.228912;46.045479;, + -44.659866;-335.766113;36.478382;, + -46.011299;-336.928101;39.876133;, + -30.907063;-337.423279;41.478359;, + -11.541974;-184.862228;45.883656;, + -41.620197;-179.552460;46.748608;, + -30.082495;-176.538712;60.086678;, + -26.290127;-159.034851;62.359310;, + -22.042976;-120.057648;62.105083;, + -35.127117;-120.041656;57.534679;, + -24.386381;-143.741119;62.231689;, + -37.002441;-178.638748;55.923828;, + -41.142269;-130.155960;39.554146;, + -41.240711;-158.109726;38.305466;, + -42.656788;-120.929993;49.355263;, + -41.014412;-121.305328;41.175835;, + -41.620197;-179.552460;46.748608;, + -39.826946;-174.615158;38.212673;, + -52.006966;-325.347748;41.525673;, + -25.375702;-326.803925;43.166012;, + -27.052189;-63.743755;51.457161;, + -30.899126;-70.822411;49.935226;, + -3.998070;-70.562149;67.711349;, + -14.078679;-70.624992;36.359470;, + -20.407236;-70.663857;37.704983;, + -25.309130;-70.709183;43.680515;, + -25.333038;-70.735931;56.047955;, + -20.123388;-70.712914;61.395264;, + -29.135050;-70.748413;50.137466;, + -29.135050;-70.748413;50.137466;, + -10.657997;-70.656097;64.141533;, + -18.580341;-63.659996;42.089684;, + 0.102538;-63.638348;37.841175;, + -3.877978;-63.520813;66.895554;, + -18.598015;-63.628139;61.096786;, + -25.494289;-63.762321;51.551601;, + -25.494289;-63.762321;51.551601;, + 0.102538;-63.445549;68.379417;, + -3.877978;-63.520813;66.895554;, + -4.034785;-63.594818;67.636086;, + -3.998070;-70.562149;67.711349;, + 0.100870;-70.535385;69.452461;, + -3.855402;-70.482147;66.867348;, + 0.100870;-80.880516;69.142647;, + 0.100870;-105.710800;64.621178;, + 0.100870;-105.624802;63.766800;, + -15.278575;-278.076538;41.723305;, + -47.843460;-278.215302;43.605659;, + -47.021446;-254.582092;45.376308;, + -44.766525;-223.910660;41.391571;, + -11.671675;-229.887054;44.415508;, + -13.444867;-241.724686;43.812698;, + -12.848580;-215.346298;46.368130;, + -42.281010;-210.077301;42.464180;, + 0.100870;-70.522980;34.969410;, + 38.087563;-84.783722;46.673916;, + 29.332651;-70.748413;50.137463;, + 41.958218;-103.151527;46.673912;, + 43.311150;-194.904678;46.172497;, + 8.374740;-173.738678;44.589821;, + 12.165494;-201.991699;48.101700;, + 35.451141;-336.022369;70.615288;, + 37.950394;-344.579834;81.882141;, + 36.645081;-347.590363;81.989037;, + 33.169540;-348.840668;75.068268;, + 30.681425;-349.513580;64.542366;, + 30.474693;-349.285034;45.291451;, + 30.928658;-349.140839;32.597916;, + 45.196014;-349.114563;30.769142;, + 47.776966;-349.201569;38.020821;, + 49.678474;-349.253357;42.813526;, + 53.918003;-349.475220;61.544106;, + 54.261131;-348.805878;72.346741;, + 51.193394;-347.566376;80.111809;, + 51.193394;-347.566376;80.111809;, + 36.645081;-347.590363;81.989037;, + 50.599190;-344.387238;80.484764;, + 31.009497;-349.229279;40.184380;, + 25.573301;-326.803894;43.166008;, + 25.559353;-319.393433;40.717941;, + 53.547699;-311.978485;48.287315;, + 49.109501;-319.507538;43.118351;, + 17.713989;-311.220673;43.257229;, + 4.856273;-143.854736;42.160900;, + 22.056257;-301.316620;40.265823;, + 48.832378;-301.610474;45.850079;, + 15.564311;-254.579514;44.539597;, + 42.854393;-120.929985;49.355259;, + 12.643028;-224.292191;47.498661;, + 47.290989;-334.957916;67.363968;, + 47.182835;-330.924622;60.877216;, + 52.204571;-325.347748;41.525669;, + 37.628727;-348.022308;28.784140;, + 37.628727;-348.022308;28.784140;, + 36.694790;-333.552673;31.073109;, + 43.321674;-327.569916;63.163586;, + 37.705608;-327.823700;63.943378;, + 32.225300;-330.586823;57.891064;, + 31.027285;-335.353180;51.935184;, + 30.486776;-336.679749;37.674358;, + 30.488491;-334.903290;34.539787;, + 47.123669;-335.870056;46.077354;, + 48.415981;-333.043976;53.745152;, + 33.544102;-333.002716;32.172966;, + 36.694790;-333.552673;31.073109;, + 32.357216;-328.701721;61.163334;, + 47.936604;-332.348511;57.905350;, + 47.182835;-330.924622;60.877216;, + 39.290493;-333.629852;32.004887;, + 42.978680;-334.302216;33.467194;, + 30.817997;-337.228882;46.045475;, + 44.857464;-335.766083;36.478382;, + 46.208900;-336.928101;39.876129;, + 31.104664;-337.423279;41.478355;, + 11.739574;-184.862213;45.883652;, + 41.817802;-179.552460;46.748608;, + 30.280094;-176.538696;60.086674;, + 26.487728;-159.034851;62.359303;, + 22.240578;-120.057648;62.105080;, + 35.324718;-120.041656;57.534676;, + 24.583982;-143.741119;62.231686;, + 37.200043;-178.638748;55.923824;, + 41.339870;-130.155960;39.554138;, + 41.438313;-158.109711;38.305462;, + 42.854393;-120.929985;49.355259;, + 41.212013;-121.305321;41.175831;, + 41.817802;-179.552460;46.748608;, + 40.024551;-174.615143;38.212673;, + 52.204571;-325.347748;41.525669;, + 25.573301;-326.803894;43.166008;, + 32.357216;-328.701721;61.163334;, + 31.096729;-70.822411;49.935223;, + 27.249788;-63.743755;51.457157;, + 4.195670;-70.562141;67.711349;, + 14.276281;-70.624985;36.359463;, + 20.604836;-70.663849;37.704975;, + 25.506731;-70.709175;43.680508;, + 25.530638;-70.735931;56.047947;, + 20.320988;-70.712906;61.395260;, + 29.332651;-70.748413;50.137463;, + 29.332651;-70.748413;50.137463;, + 10.855597;-70.656097;64.141525;, + 18.773201;-63.677704;42.028572;, + 4.075578;-63.520775;66.895554;, + 18.770283;-63.633057;61.106705;, + 25.705898;-63.638660;51.490501;, + 25.705898;-63.638660;51.490501;, + 4.232385;-63.594814;67.636078;, + 4.075578;-63.520775;66.895554;, + 4.195670;-70.562141;67.711349;, + 4.053002;-70.482147;66.867340;, + 15.476175;-278.076508;41.723305;, + 48.041061;-278.215271;43.605659;, + 47.219048;-254.582077;45.376305;, + 44.964127;-223.910675;41.391571;, + 11.869275;-229.887054;44.415504;, + 13.642469;-241.724686;43.812695;, + 13.046181;-215.346298;46.368130;, + 42.478611;-210.077286;42.464176;, + 9.646603;26.610264;45.446602;, + 33.395126;-1.314395;35.941048;, + 42.876431;-10.391958;41.524540;, + 61.100998;-12.097787;52.234310;, + 33.931534;-10.798729;47.691635;, + 33.395126;-1.314395;35.941048;, + 78.460449;-9.570584;65.570358;, + 73.386116;1.385114;82.625687;, + 78.295067;-4.036124;86.370949;, + 81.882507;-19.600512;68.102516;, + 87.136154;-19.603304;74.055412;, + 86.196594;-18.624458;77.084518;, + 80.318741;-7.420647;85.493256;, + 67.389786;-1.205821;78.118034;, + 70.006081;2.367340;76.967026;, + 77.780144;-0.616348;69.076759;, + 78.460449;-9.570584;65.570358;, + 75.694405;-15.631040;66.051804;, + 71.219742;-15.793794;69.989906;, + 68.045258;-14.292754;73.173157;, + 66.651627;-8.248512;76.491966;, + 73.890327;2.056242;73.440269;, + 70.006081;2.367340;76.967026;, + 69.084702;6.252669;77.456337;, + 75.694405;-15.631040;66.051804;, + 75.774590;-18.309954;63.527412;, + 66.651627;-8.248512;76.491966;, + 86.261154;-12.489821;78.381943;, + 82.521919;-17.837069;80.497223;, + 114.749481;-29.371605;104.351402;, + 79.183868;-11.467402;85.242088;, + 79.655968;-17.333593;83.765129;, + 110.916962;-20.728716;110.111130;, + 80.318741;-7.420647;85.493256;, + 86.196594;-18.624458;77.084518;, + 82.789978;-6.610463;83.296829;, + 80.318741;-7.420647;85.493256;, + 84.665817;-9.600757;93.965752;, + 105.883774;-28.288433;93.625610;, + 100.601974;-16.327637;102.138657;, + 93.242905;-25.622953;81.159538;, + 86.196594;-18.624458;77.084518;, + 86.199554;-6.060757;79.316513;, + 51.500221;-7.577340;65.697365;, + 33.477127;16.479158;40.343475;, + 33.578400;13.114620;48.755165;, + 33.569466;8.843540;35.935562;, + 114.749481;-29.371605;104.351402;, + 116.328888;-21.406776;103.886078;, + 114.749481;-29.371605;104.351402;, + 110.432236;-25.897305;108.404945;, + 114.547729;-31.794006;101.703148;, + 110.916962;-20.728716;110.111130;, + 110.916962;-20.728716;110.111130;, + 117.792206;-32.974083;105.142754;, + 120.240417;-32.382523;107.405258;, + 120.240417;-32.382523;107.405258;, + 119.345352;-28.410704;105.006744;, + 120.240417;-32.382523;107.405258;, + 115.310875;-21.371449;114.672195;, + 120.625252;-22.188108;107.598892;, + 128.789810;-29.466074;108.954926;, + 115.310875;-21.371449;114.672195;, + 114.274811;-23.003649;117.528297;, + 117.859741;-27.379353;126.710335;, + 120.613640;-25.185886;123.257240;, + 121.760422;-25.243605;123.489906;, + 114.847473;-23.354944;126.325142;, + 115.773735;-23.653730;128.726898;, + 120.118660;-28.808155;129.262100;, + 118.315994;-26.222034;131.904175;, + 120.118660;-28.808155;129.262100;, + 117.369904;-31.079527;128.957718;, + 118.686279;-31.174704;132.509644;, + 120.607414;-29.430899;132.556305;, + 119.351463;-27.770924;134.521164;, + 120.230301;-29.213165;134.837173;, + 137.268311;-36.747177;118.004539;, + 130.886734;-24.224178;128.467072;, + 129.463760;-23.354002;127.461098;, + 132.345215;-26.909451;126.571350;, + 131.403183;-26.611431;125.127594;, + 132.198166;-25.013567;129.446793;, + 133.363693;-27.150629;127.933983;, + 133.465668;-25.219961;130.170334;, + 134.645630;-27.372400;128.641541;, + 134.095200;-25.443157;131.157074;, + 135.557129;-28.123676;129.259583;, + 135.087219;-26.605450;132.444199;, + 136.416260;-29.042286;130.719208;, + 136.310669;-27.313053;133.104141;, + 137.309525;-29.130545;131.811081;, + 136.930222;-27.776287;134.007202;, + 138.067566;-29.848610;132.534195;, + 137.163391;-28.031139;134.882431;, + 138.629425;-30.705997;132.982819;, + 138.097382;-29.210182;136.039948;, + 139.375854;-31.531094;134.386230;, + 139.425034;-29.698851;136.370346;, + 140.178970;-31.048899;135.399673;, + 140.258026;-30.001667;136.269287;, + 140.513062;-30.455763;135.941559;, + 133.326996;-27.869246;126.520409;, + 134.998978;-30.947582;124.347214;, + 133.524338;-30.337019;122.600365;, + 135.090698;-28.901239;127.885551;, + 136.426865;-31.351122;126.151329;, + 136.754562;-29.240726;128.910980;, + 138.107239;-31.708241;127.158394;, + 137.655624;-29.584154;130.208908;, + 139.331543;-32.657040;128.033676;, + 139.067566;-31.050646;131.939789;, + 140.591125;-33.844181;129.962296;, + 140.683243;-31.965866;132.894485;, + 141.828308;-34.049400;131.412170;, + 141.569046;-32.582588;134.092957;, + 142.872879;-34.958260;132.404327;, + 141.965546;-32.937801;135.216400;, + 143.646179;-36.004208;133.038742;, + 143.291046;-34.413788;136.780243;, + 144.756668;-37.074436;134.884445;, + 144.992767;-35.061703;137.326050;, + 145.857040;-36.609371;136.213287;, + 146.025253;-35.446705;137.282303;, + 146.317627;-35.967274;136.906616;, + 135.283035;-31.410269;123.908699;, + 136.889267;-34.388729;121.786079;, + 135.487198;-33.834320;120.160095;, + 136.918472;-32.390182;125.135963;, + 138.202103;-34.760567;123.442123;, + 138.471878;-32.702595;126.052612;, + 139.771439;-35.090023;124.340836;, + 139.296295;-33.022293;127.247002;, + 140.906357;-35.995464;125.122398;, + 140.587006;-34.422878;128.824356;, + 142.050705;-37.125763;126.892921;, + 142.091629;-35.292908;129.670227;, + 143.191742;-37.308819;128.222427;, + 142.901459;-35.877598;130.768753;, + 144.154083;-38.176163;129.119446;, + 143.251007;-36.212845;131.812622;, + 144.865631;-39.179722;129.685654;, + 144.463196;-37.624027;133.234940;, + 145.871307;-40.198315;131.383316;, + 146.060104;-38.237057;133.695831;, + 146.890518;-39.734459;132.609009;, + 147.036926;-38.603104;133.622391;, + 147.317841;-39.106766;133.255463;, + 136.857193;-34.692177;121.075745;, + 138.085999;-37.138863;119.175186;, + 138.106750;-35.513153;121.891022;, + 139.088989;-37.460236;120.374466;, + 139.315872;-35.774200;122.489632;, + 140.310577;-37.735165;120.957130;, + 139.940460;-36.049793;123.361938;, + 141.172485;-38.492016;121.459724;, + 140.897690;-37.228283;124.465363;, + 142.017715;-39.448486;122.736076;, + 142.053253;-37.953835;124.992500;, + 142.895447;-39.609592;123.696373;, + 142.660355;-38.449345;125.780983;, + 143.619232;-40.337288;124.304420;, + 142.909821;-38.739342;126.569069;, + 144.145706;-41.176258;124.664856;, + 145.379715;-40.473606;125.913101;, + 143.807114;-39.925308;127.555336;, + 144.885223;-42.039631;125.897728;, + 145.050308;-40.431152;127.779945;, + 145.686615;-41.660812;126.807167;, + 145.817383;-40.728752;127.636574;, + 146.032715;-41.142326;127.308174;, + 124.282539;-24.769093;125.526192;, + 108.661095;-18.210699;110.956673;, + 113.002747;-28.165403;111.418968;, + 115.310875;-21.371449;114.672195;, + 111.886719;-19.639212;113.723465;, + 128.789810;-29.466074;108.954926;, + 41.310238;-5.151076;57.811226;, + 33.733215;8.483885;56.324486;, + 33.266479;-1.659648;55.141335;, + 33.266479;-1.659648;55.141335;, + -33.285355;-1.230055;35.845985;, + -60.913422;-12.097776;52.234310;, + -42.688854;-10.391947;41.524540;, + -33.422455;-6.066209;41.124596;, + -33.602604;-10.886051;47.766304;, + -78.272881;-9.570575;65.570358;, + -73.198547;1.385122;82.625679;, + -78.107506;-4.036117;86.370941;, + -86.948593;-19.603292;74.055412;, + -81.694946;-19.600500;68.102516;, + -86.009033;-18.624449;77.084511;, + -80.131180;-7.420639;85.493248;, + -67.202217;-1.205813;78.118034;, + -69.818512;2.367348;76.967026;, + -77.592583;-0.616339;69.076759;, + -78.272881;-9.570575;65.570358;, + -75.506836;-15.631029;66.051804;, + -71.032173;-15.793784;69.989906;, + -67.857689;-14.292745;73.173157;, + -66.464066;-8.248504;76.491966;, + -73.702766;2.056248;73.440269;, + -68.897133;6.252676;77.456337;, + -69.818512;2.367348;76.967026;, + -75.587021;-18.309942;63.527412;, + -75.506836;-15.631029;66.051804;, + -66.464066;-8.248504;76.491966;, + -86.073555;-12.696040;78.345314;, + -82.334358;-17.837059;80.497215;, + -114.561913;-29.371595;104.351395;, + -78.996300;-11.467393;85.242081;, + -79.468399;-17.333584;83.765121;, + -80.131180;-7.420639;85.493248;, + -85.469383;-14.398664;96.109703;, + -78.996300;-11.467393;85.242081;, + -86.009033;-18.624449;77.084511;, + -82.859459;-6.312282;83.425949;, + -99.563057;-17.848322;102.450645;, + -110.729401;-20.728708;110.111122;, + -105.696213;-28.288424;93.625603;, + -93.055344;-25.622944;81.159531;, + -86.009033;-18.624449;77.084511;, + -86.011993;-6.060749;79.316505;, + -51.312645;-7.577330;65.697365;, + -33.326355;16.538502;40.337154;, + -33.377022;12.971798;48.765106;, + -33.380333;8.824398;35.941063;, + -114.561913;-29.371595;104.351395;, + -116.141319;-21.406767;103.886070;, + -114.561913;-29.371595;104.351395;, + -110.244675;-25.897297;108.404938;, + -114.360168;-31.793995;101.703140;, + -110.729401;-20.728708;110.111122;, + -110.729401;-20.728708;110.111122;, + -118.763100;-32.416569;106.890343;, + -117.604637;-32.974075;105.142746;, + -119.195221;-22.221508;107.119102;, + -118.763100;-32.416569;106.890343;, + -118.763100;-32.416569;106.890343;, + -115.208687;-21.985653;115.587814;, + -128.864243;-29.984035;109.850922;, + -115.208687;-21.985653;115.587814;, + -114.103012;-23.569595;118.313278;, + -117.563560;-27.690514;126.991264;, + -120.423470;-25.533827;123.678185;, + -121.581490;-25.569689;123.884338;, + -114.556931;-23.727386;126.708763;, + -115.458870;-23.961578;128.988220;, + -119.802361;-29.029490;129.383438;, + -117.964737;-26.420248;131.961685;, + -120.245399;-29.574646;132.518158;, + -118.961952;-27.895647;134.431473;, + -119.833649;-29.315147;134.705521;, + -137.255630;-36.934776;118.303642;, + -131.314377;-26.758501;125.303482;, + -133.322495;-24.425945;126.440849;, + -129.349152;-23.487917;127.596153;, + -130.768127;-24.314178;128.528564;, + -132.245651;-27.011766;126.667183;, + -132.075287;-25.062017;129.438324;, + -133.256104;-27.208897;127.952965;, + -133.347275;-25.234171;130.110321;, + -134.542770;-27.396519;128.609299;, + -133.969086;-25.426950;131.042328;, + -135.450180;-28.119780;129.179245;, + -134.944672;-26.545113;132.246048;, + -136.291122;-28.993143;130.552338;, + -136.167953;-27.219339;132.852280;, + -137.179993;-29.045206;131.582748;, + -136.778458;-27.653521;133.701782;, + -137.930786;-29.735388;132.255539;, + -136.999939;-27.886042;134.532242;, + -138.485275;-30.573214;132.667130;, + -137.918381;-29.024487;135.612717;, + -139.213760;-31.356102;133.989075;, + -139.254013;-29.485641;135.905014;, + -140.018036;-30.841948;134.952103;, + -140.096344;-29.777664;135.793762;, + -140.354813;-30.233871;135.472046;, + -133.231537;-27.956072;126.594505;, + -134.925339;-31.048527;124.460655;, + -133.461777;-30.497587;122.817970;, + -134.989136;-28.931255;127.863777;, + -136.342789;-31.392393;126.160988;, + -136.657150;-29.224060;128.817413;, + -138.027634;-31.702929;127.096672;, + -137.548523;-29.526291;130.041809;, + -139.246399;-32.613304;127.906013;, + -138.940323;-30.932508;131.660553;, + -140.483856;-33.738888;129.718903;, + -140.554810;-31.801954;132.540863;, + -141.714996;-33.895096;131.085495;, + -141.429428;-32.379189;133.667358;, + -142.750443;-34.765797;132.009415;, + -141.811935;-32.704250;134.731705;, + -143.514694;-35.784763;132.593597;, + -143.118393;-34.124710;136.191864;, + -144.603409;-36.797626;134.330566;, + -144.828415;-34.734749;136.683197;, + -145.704269;-36.289589;135.590790;, + -145.871262;-35.104645;136.623108;, + -146.167557;-35.627628;136.254303;, + -135.214676;-31.515200;124.032562;, + -136.842163;-34.507912;121.949051;, + -135.449875;-34.009403;120.420280;, + -136.844757;-32.443195;125.172371;, + -138.145432;-34.824940;123.509781;, + -138.402664;-32.712887;126.023872;, + -139.719559;-35.111778;124.343742;, + -139.218048;-32.994740;127.150612;, + -140.849487;-35.982155;125.065216;, + -140.489838;-34.340195;128.625000;, + -141.972977;-37.056030;126.729210;, + -141.993790;-35.168465;129.403305;, + -143.108612;-37.194061;127.982307;, + -142.793137;-35.716938;130.435669;, + -144.062485;-38.026543;128.816864;, + -143.129379;-36.024429;131.424835;, + -144.765549;-39.005554;129.337189;, + -144.323669;-37.384869;132.751999;, + -145.750641;-39.971535;130.934662;, + -145.929031;-37.963417;133.163986;, + -146.770706;-39.468060;132.097397;, + -146.916077;-38.315838;133.076492;, + -147.200821;-38.821938;132.716400;, + -136.816589;-34.826042;121.267235;, + -138.063828;-37.289051;119.406982;, + -138.063034;-35.609749;122.020325;, + -139.060074;-37.569843;120.535957;, + -139.277069;-35.839912;122.573105;, + -140.286835;-37.814011;121.073189;, + -139.894958;-36.087437;123.395241;, + -141.145554;-38.545986;121.533401;, + -140.837692;-37.226124;124.423691;, + -141.974594;-39.461166;122.731110;, + -141.993881;-37.922039;124.903725;, + -142.848846;-39.588902;123.635170;, + -142.593063;-38.391006;125.643524;, + -143.566452;-40.291603;124.198372;, + -142.831924;-38.660183;126.390099;, + -144.086502;-41.113419;124.526360;, + -143.715500;-39.809662;127.307304;, + -144.809982;-41.938175;125.684982;, + -144.966858;-40.291412;127.499474;, + -145.612946;-41.529369;126.547478;, + -145.743073;-40.580086;127.348747;, + -145.961716;-40.996456;127.027367;, + -124.112961;-25.016518;125.801498;, + -108.473534;-18.210691;110.956665;, + -112.815208;-28.165394;111.418961;, + -111.699158;-19.639204;113.723457;, + -115.208687;-21.985653;115.587814;, + -41.122662;-5.151066;57.811222;, + -33.454399;8.516764;56.378914;, + -33.245544;-1.592087;55.511299;, + -33.245544;-1.592087;55.511299;, + 33.827938;10.960120;51.807289;, + 33.696419;-6.417687;40.866890;, + -33.285355;-1.230055;35.845985;, + -33.640362;10.960128;51.807285;, + -6.262792;13.473364;58.013275;, + -11.429913;16.434713;56.577648;, + 6.173337;13.337016;58.607582;, + 0.141490;12.205804;59.792637;, + 11.714142;16.434715;57.068302;, + -11.461862;93.826927;46.940403;, + -8.418667;86.102859;35.841724;, + -11.461862;93.826927;46.940403;, + -2.182251;64.795692;35.886501;, + -8.418667;86.102859;35.841724;, + -11.461862;93.826927;46.940403;, + -11.461862;93.826927;46.940403;, + -2.182251;64.795692;35.886501;, + -2.182251;64.795692;35.886501;, + -13.263326;61.285336;39.593838;, + -7.852941;94.312172;61.946106;, + -6.418187;97.562218;66.945374;, + -4.402893;95.093262;63.828449;, + -10.775403;96.597122;64.803986;, + -13.469022;92.920013;60.063766;, + 0.057848;95.886368;65.707542;, + -3.096079;86.564301;74.622665;, + 0.057848;84.042374;71.322975;, + -2.904975;98.340385;68.672066;, + -6.403885;85.831749;72.998459;, + -4.494127;83.274292;70.169548;, + -8.635912;82.575844;67.678185;, + -15.709467;82.386459;66.627968;, + -13.865308;81.275604;65.186821;, + -15.816927;87.518616;62.681839;, + -11.518435;84.699326;70.485474;, + -13.865308;81.275604;65.186821;, + -8.635912;82.575844;67.678185;, + -14.668218;94.575356;62.197353;, + -4.402893;95.093262;63.828449;, + -7.852941;94.312172;61.946106;, + -13.097512;71.430748;40.778584;, + -8.418667;86.102859;35.841724;, + -14.186148;74.380287;64.488983;, + -13.097512;71.430748;40.778584;, + -14.675630;70.832016;46.772766;, + -11.461862;93.826927;46.940403;, + -13.097512;71.430748;40.778584;, + -15.347429;57.616409;47.193058;, + -13.263326;61.285336;39.593838;, + 0.057848;63.606403;31.055357;, + -2.182251;64.795692;35.886501;, + -2.182251;64.795692;35.886501;, + 0.057848;63.606403;31.055357;, + -15.784473;69.911873;57.321053;, + -16.338684;73.054062;51.038074;, + -13.469022;92.920013;60.063766;, + 0.057848;90.668213;33.607914;, + -14.675630;70.832016;46.772766;, + -13.097512;71.430748;40.778584;, + -16.338684;73.054062;51.038074;, + 0.057848;75.714500;30.620197;, + -14.163750;71.116005;45.658489;, + -14.675630;70.832016;46.772766;, + -14.163750;71.116005;45.658489;, + -14.718096;68.331589;44.645512;, + 0.057848;99.177589;56.123409;, + -2.250754;97.063629;60.111290;, + 0.057848;99.177589;56.123409;, + -14.675630;70.832016;46.772766;, + -16.338684;73.054062;51.038074;, + -15.528388;63.130802;45.068886;, + -3.355227;56.332371;40.007046;, + -7.149835;52.817856;41.486317;, + -3.355227;56.332371;40.007046;, + -14.710178;77.561653;59.569633;, + -16.338684;73.054062;51.038074;, + -14.238920;86.733635;61.588871;, + -13.469022;92.920013;60.063766;, + -15.101998;82.440125;58.401062;, + -13.865308;81.275604;65.186821;, + 0.057848;99.177589;56.123409;, + 0.057848;97.662560;43.454536;, + -11.461862;93.826927;46.940403;, + 0.057848;75.714500;30.620197;, + 0.057848;90.668213;33.607914;, + -8.418667;86.102859;35.841724;, + -8.418667;86.102859;35.841724;, + -13.097512;71.430748;40.778584;, + -2.182251;64.795692;35.886501;, + -13.469022;92.920013;60.063766;, + -16.338684;73.054062;51.038074;, + -13.097512;71.430748;40.778584;, + 0.057848;99.177589;56.123409;, + -7.149835;52.817856;41.486317;, + -13.263326;61.285336;39.593838;, + -15.347429;57.616409;47.193058;, + -11.261707;52.068916;45.952110;, + 0.057848;99.177589;56.123409;, + 11.577548;93.826927;46.940403;, + 0.057848;90.668213;33.607914;, + 8.534353;86.102859;35.841724;, + 11.577548;93.826927;46.940403;, + 2.297937;64.795692;35.886501;, + 8.534353;86.102859;35.841724;, + 11.577548;93.826927;46.940403;, + 11.577548;93.826927;46.940403;, + 0.057848;97.662560;43.454536;, + 2.297937;64.795692;35.886501;, + 0.057848;63.606403;31.055357;, + 2.297937;64.795692;35.886501;, + 13.379013;61.285336;39.593838;, + 7.968627;94.312172;61.946106;, + 4.518579;95.093262;63.828449;, + 6.533874;97.562218;66.945374;, + 14.783904;94.575356;62.197353;, + 13.584708;92.920013;60.063766;, + 3.211765;86.564301;74.622665;, + 3.020661;98.340385;68.672066;, + 4.609814;83.274292;70.169548;, + 6.519572;85.831749;72.998459;, + 8.751598;82.575844;67.678185;, + 13.980994;81.275604;65.186821;, + 15.932613;87.518616;62.681839;, + 15.825153;82.386459;66.627968;, + 10.891089;96.597122;64.803986;, + 4.518579;95.093262;63.828449;, + 7.968627;94.312172;61.946106;, + 13.213199;71.430748;40.778584;, + 8.534353;86.102859;35.841724;, + 13.213199;71.430748;40.778584;, + 14.791316;70.832016;46.772766;, + 11.577548;93.826927;46.940403;, + 13.213199;71.430748;40.778584;, + 15.463116;57.616409;47.193058;, + 13.379013;61.285336;39.593838;, + 0.057848;63.606403;31.055357;, + 2.297937;64.795692;35.886501;, + 2.297937;64.795692;35.886501;, + 0.057848;53.154804;40.756420;, + 0.057848;63.606403;31.055357;, + 15.900160;69.911873;57.321053;, + 16.454370;73.054062;51.038074;, + 13.981975;76.274246;65.799950;, + 13.584708;92.920013;60.063766;, + 0.057848;90.668213;33.607914;, + 14.791316;70.832016;46.772766;, + 0.057848;75.714500;30.620197;, + 13.213199;71.430748;40.778584;, + 16.454370;73.054062;51.038074;, + 0.057848;75.714500;30.620197;, + 14.279436;71.116005;45.658489;, + 2.366440;97.063629;60.111290;, + 14.791316;70.832016;46.772766;, + 16.454370;73.054062;51.038074;, + 15.644074;63.130802;45.068886;, + 3.470914;56.332371;40.007046;, + 7.265521;52.817856;41.486317;, + 3.470914;56.332371;40.007046;, + 14.825865;77.561653;59.569633;, + 16.454370;73.054062;51.038074;, + 13.584708;92.920013;60.063766;, + 14.354607;86.733635;61.588871;, + 15.217685;82.440125;58.401062;, + 13.980994;81.275604;65.186821;, + 0.057848;99.177589;56.123409;, + 0.057848;97.662560;43.454536;, + 11.577548;93.826927;46.940403;, + 0.057848;75.714500;30.620197;, + 0.057848;90.668213;33.607914;, + 8.534353;86.102859;35.841724;, + 8.534353;86.102859;35.841724;, + 13.213199;71.430748;40.778584;, + 2.297937;64.795692;35.886501;, + 13.584708;92.920013;60.063766;, + 20.061501;88.506752;43.413734;, + 18.678795;84.403915;43.736874;, + 16.454370;73.054062;51.038074;, + 13.213199;71.430748;40.778584;, + 0.057848;99.177589;56.123409;, + 7.265521;52.817856;41.486317;, + 13.379013;61.285336;39.593838;, + 15.463116;57.616409;47.193058;, + 11.377394;52.068913;45.952110;, + 15.463116;57.616409;47.193058;, + 7.265521;52.817856;41.486317;, + 2.867495;39.371185;54.783699;, + 7.573774;40.307079;54.648247;, + 1.330886;37.590916;54.064663;, + 5.149999;41.098293;49.664669;, + -5.034308;41.098293;49.664669;, + -1.215191;37.590916;54.064663;, + -7.458086;40.307079;54.648247;, + -2.751802;39.371185;54.783699;, + 2.217954;38.776661;57.910744;, + -2.102260;38.776661;57.910744;, + -3.355227;56.332371;40.007046;, + 0.057848;53.154804;40.756420;, + 3.470914;56.332371;40.007046;, + 9.931857;27.639982;38.133949;, + 0.077734;27.263643;33.720470;, + -9.608727;27.597115;38.148296;, + -0.565651;37.436687;67.317482;, + -2.411773;37.506966;67.308975;, + 2.527462;37.506966;67.308975;, + 0.681345;37.436687;67.317482;, + -4.628216;39.976799;65.832298;, + -3.095984;38.031998;67.529678;, + -8.580020;44.714546;64.299896;, + -5.649843;41.666725;65.621597;, + -16.045902;55.654251;48.952625;, + -15.310171;52.496346;49.328674;, + -12.819518;47.844864;50.501919;, + -9.828319;42.345741;53.625164;, + -15.043728;50.197842;49.912075;, + -15.007770;66.809219;62.450409;, + -14.767531;62.889500;62.645046;, + -14.547876;60.533600;62.358631;, + -13.118661;55.010292;62.553223;, + -15.462021;56.205631;47.969166;, + -13.866287;76.274246;65.799950;, + -14.881803;70.420540;62.992817;, + -16.338850;66.013954;51.296288;, + -16.338684;73.054062;51.038074;, + -11.348783;70.134789;66.847923;, + -12.326240;69.568321;65.742271;, + -12.625326;68.411827;65.535583;, + -12.363090;67.291313;66.688377;, + -12.479330;68.737000;65.669327;, + -12.347851;69.289749;65.733955;, + -11.017628;49.345627;63.166481;, + -5.015405;68.108635;68.910416;, + -6.346445;70.041153;68.809387;, + -5.034431;67.060791;68.905960;, + -5.441578;66.767700;68.786415;, + -4.548992;67.765022;68.960190;, + -14.710178;77.561653;59.569633;, + -15.784473;69.911873;57.321053;, + -15.528388;63.130802;45.068886;, + -15.347429;57.616409;47.193058;, + -15.347429;57.616409;47.193058;, + -7.149835;52.817856;41.486317;, + -7.906905;51.757496;43.185513;, + -9.962842;51.383026;45.418407;, + -7.929698;44.502201;46.021900;, + -8.752393;35.209740;45.489132;, + -7.580388;47.204636;47.215710;, + -9.962842;51.383026;45.418407;, + -8.122182;48.950886;46.050209;, + -9.962842;51.383026;45.418407;, + -9.139874;26.594124;45.452682;, + -7.848414;66.116623;68.406441;, + -6.236395;66.607925;68.646599;, + -8.238889;70.568634;68.310120;, + -10.339741;70.382629;67.493866;, + -7.507647;70.645966;68.558647;, + -11.152501;66.503914;67.438225;, + -9.477689;65.951813;67.955978;, + -11.688239;66.665207;67.208046;, + -8.381545;65.898521;68.278526;, + 5.765529;41.666725;65.621597;, + 8.695706;44.714546;64.299896;, + 4.743902;39.976799;65.832298;, + 3.211673;38.031998;67.529678;, + 9.944007;42.345741;53.625164;, + 12.935205;47.844864;50.501919;, + 15.425858;52.496346;49.328674;, + 16.161591;55.654251;48.952625;, + 15.159414;50.197842;49.912075;, + 14.663563;60.533600;62.358627;, + 13.234347;55.010292;62.553223;, + 14.883218;62.889500;62.645046;, + 15.123456;66.809219;62.450409;, + 15.577708;56.205627;47.969166;, + 14.997487;70.420540;62.992817;, + 14.301835;74.380287;64.488983;, + 13.980994;81.275604;65.186821;, + 8.751598;82.575844;67.678185;, + 14.791316;70.832016;46.772766;, + 16.454370;73.054062;51.038074;, + 16.454536;66.013954;51.296288;, + 12.478778;67.291313;66.688377;, + 12.741013;68.411827;65.535583;, + 12.441926;69.568321;65.742271;, + 11.464467;70.134789;66.847923;, + 12.595016;68.737000;65.669327;, + 12.463537;69.289749;65.733955;, + 11.133315;49.345627;63.166481;, + 5.325842;67.702225;68.891853;, + 6.462132;70.041153;68.809387;, + 5.150118;67.060791;68.905960;, + 5.557265;66.767700;68.786423;, + 14.825865;77.561653;59.569633;, + 15.900160;69.911873;57.321053;, + 14.833782;68.331589;44.645512;, + 14.279436;71.116005;45.658489;, + 15.644074;63.130802;45.068886;, + 15.463116;57.616409;47.193058;, + 15.463116;57.616409;47.193058;, + 7.265521;52.817856;41.486317;, + 10.078528;51.383022;45.418407;, + 8.237869;48.950886;46.050209;, + 10.078528;51.383022;45.418407;, + 8.868079;35.209740;45.489132;, + 8.045384;44.502201;46.021900;, + 7.696074;47.204636;47.215710;, + 8.237869;48.950886;46.050209;, + 9.646603;26.610264;45.446602;, + 6.352082;66.607925;68.646599;, + 7.964100;66.116623;68.406441;, + 10.455427;70.382629;67.493866;, + 8.354575;70.568634;68.310120;, + 7.623333;70.645973;68.558647;, + 9.593375;65.951813;67.955978;, + 11.268188;66.503914;67.438225;, + 11.803926;66.665207;67.208046;, + 8.497231;65.898521;68.278526;, + 5.227813;27.441788;34.143456;, + -5.109205;27.415857;34.161194;, + 11.634122;84.699326;70.485474;, + 30.643127;-31.721945;45.652527;, + -30.350075;-31.719879;45.630089;; + 6841; + 3;28,62,1;, + 3;3,16,3420;, + 3;11,23,29;, + 3;104,69,7;, + 3;0,13,70;, + 3;9,97,96;, + 3;3421,71,2;, + 3;15,22,3;, + 3;3420,15,3;, + 3;68,4,15;, + 3;116,111,106;, + 3;3422,12,6;, + 3;6,12,1742;, + 3;24,14,12;, + 3;3423,108,119;, + 3;102,7,13;, + 3;13,30,23;, + 3;3420,2,15;, + 3;115,116,106;, + 3;100,3424,17;, + 3;100,1,3424;, + 3;1,18,19;, + 3;28,1,19;, + 3;104,94,69;, + 3;15,4,20;, + 3;98,8,97;, + 3;115,106,114;, + 3;29,23,126;, + 3;3422,24,12;, + 3;30,0,27;, + 3;26,11,29;, + 3;24,3422,3425;, + 3;27,126,23;, + 3;3426,3427,3428;, + 3;23,11,13;, + 3;13,0,30;, + 3;23,30,27;, + 3;108,107,120;, + 3;31,6,1741;, + 3;25,32,29;, + 3;32,26,29;, + 3;136,132,135;, + 3;32,25,65;, + 3;63,60,35;, + 3;3419,3429,63;, + 3;35,59,34;, + 3;58,59,16;, + 3;41,36,848;, + 3;51,53,49;, + 3;3430,55,49;, + 3;82,848,36;, + 3;24,38,14;, + 3;84,49,53;, + 3;81,82,43;, + 3;83,3431,39;, + 3;41,45,36;, + 3;40,3430,3432;, + 3;41,37,47;, + 3;24,52,48;, + 3;3430,49,84;, + 3;38,48,50;, + 3;38,24,48;, + 3;49,55,50;, + 3;50,51,49;, + 3;55,56,50;, + 3;48,51,50;, + 3;81,43,80;, + 3;67,54,3433;, + 3;39,66,44;, + 3;50,56,38;, + 3;3430,40,55;, + 3;56,57,38;, + 3;55,40,56;, + 3;56,436,57;, + 3;51,48,52;, + 3;3434,3435,3436;, + 3;3437,3438,3435;, + 3;3437,3439,3438;, + 3;33,3439,3437;, + 3;64,3440,3441;, + 3;3442,3443,33;, + 3;3440,3444,3445;, + 3;52,24,3425;, + 3;3434,3436,3446;, + 3;16,59,3420;, + 3;60,3420,59;, + 3;58,34,59;, + 3;60,3421,3420;, + 3;35,60,59;, + 3;61,27,0;, + 3;3447,61,3448;, + 3;28,3449,62;, + 3;3420,3421,2;, + 3;63,3429,3421;, + 3;3419,63,3450;, + 3;63,3421,60;, + 3;33,64,3442;, + 3;3450,63,35;, + 3;65,129,3447;, + 3;3434,3437,3435;, + 3;3444,42,3445;, + 3;3445,3441,3440;, + 3;39,3451,66;, + 3;3441,3442,64;, + 3;53,67,3433;, + 3;33,3443,3439;, + 3;2,68,15;, + 3;3452,3453,69;, + 3;70,13,7;, + 3;3421,3429,71;, + 3;0,70,73;, + 3;73,72,0;, + 3;7,69,75;, + 3;75,74,7;, + 3;3454,3455,77;, + 3;77,76,3454;, + 3;3453,3456,79;, + 3;79,78,3453;, + 3;70,7,74;, + 3;74,73,70;, + 3;69,3453,78;, + 3;78,75,69;, + 3;3456,3454,76;, + 3;76,79,3456;, + 3;3455,0,72;, + 3;72,77,3455;, + 3;80,43,3457;, + 3;43,82,44;, + 3;37,81,80;, + 3;44,82,83;, + 3;81,37,82;, + 3;44,83,39;, + 3;83,82,36;, + 3;3433,84,53;, + 3;83,36,3431;, + 3;3,22,85;, + 3;110,112,113;, + 3;22,89,85;, + 3;110,114,106;, + 3;95,118,111;, + 3;3447,128,61;, + 3;22,90,89;, + 3;110,113,114;, + 3;109,112,110;, + 3;90,22,91;, + 3;15,91,22;, + 3;15,92,91;, + 3;15,20,92;, + 3;92,20,93;, + 3;117,111,116;, + 3;3452,94,3458;, + 3;94,3452,69;, + 3;99,96,21;, + 3;111,117,95;, + 3;9,96,99;, + 3;1739,97,9;, + 3;97,8,21;, + 3;97,21,96;, + 3;10,98,97;, + 3;31,3422,6;, + 3;1741,6,1744;, + 3;88,99,845;, + 3;107,118,95;, + 3;18,100,17;, + 3;18,1,100;, + 3;101,102,13;, + 3;11,101,13;, + 3;119,108,120;, + 3;103,7,102;, + 3;107,121,120;, + 3;95,122,107;, + 3;107,123,121;, + 3;95,117,122;, + 3;107,122,123;, + 3;103,105,104;, + 3;103,104,7;, + 3;3459,5,106;, + 3;106,111,3459;, + 3;3423,3460,108;, + 3;3423,119,3461;, + 3;3462,3463,116;, + 3;116,115,3462;, + 3;3464,3465,122;, + 3;122,117,3464;, + 3;3466,3462,115;, + 3;115,114,3466;, + 3;107,108,3460;, + 3;3467,3468,113;, + 3;113,112,3467;, + 3;3469,3459,111;, + 3;111,118,3469;, + 3;3468,3466,114;, + 3;114,113,3468;, + 3;87,86,109;, + 3;109,110,87;, + 3;3463,3464,117;, + 3;117,116,3463;, + 3;3470,3469,118;, + 3;118,3471,3470;, + 3;3472,3461,119;, + 3;119,120,3472;, + 3;3473,3472,120;, + 3;120,121,3473;, + 3;3474,3473,121;, + 3;121,123,3474;, + 3;3465,3474,123;, + 3;123,122,3465;, + 3;65,25,124;, + 3;130,132,131;, + 3;127,126,27;, + 3;129,128,3447;, + 3;27,125,127;, + 3;29,126,25;, + 3;134,132,130;, + 3;130,133,134;, + 3;125,27,128;, + 3;128,27,61;, + 3;65,124,129;, + 3;131,132,136;, + 3;3475,3476,135;, + 3;135,132,3475;, + 3;3476,3477,136;, + 3;136,135,3476;, + 3;3478,3479,130;, + 3;130,131,3478;, + 3;3480,3481,134;, + 3;134,133,3480;, + 3;3481,3475,132;, + 3;132,134,3481;, + 3;3479,3480,133;, + 3;133,130,3479;, + 3;3477,3478,131;, + 3;131,136,3477;, + 3;158,138,184;, + 3;3,3482,16;, + 3;145,159,153;, + 3;221,143,191;, + 3;137,192,146;, + 3;144,214,215;, + 3;3483,139,193;, + 3;147,3,152;, + 3;3482,3,147;, + 3;190,147,140;, + 3;231,223,227;, + 3;3484,142,12;, + 3;142,1742,12;, + 3;154,12,14;, + 3;3485,234,225;, + 3;219,146,143;, + 3;146,153,160;, + 3;3482,147,139;, + 3;230,223,231;, + 3;217,17,3424;, + 3;217,3424,138;, + 3;138,149,148;, + 3;158,149,138;, + 3;221,191,212;, + 3;147,150,140;, + 3;98,215,8;, + 3;230,229,223;, + 3;159,241,153;, + 3;3484,12,154;, + 3;160,157,137;, + 3;156,159,145;, + 3;154,3486,3484;, + 3;157,153,241;, + 3;3487,3488,3489;, + 3;153,146,145;, + 3;146,160,137;, + 3;153,157,160;, + 3;225,235,224;, + 3;161,1743,142;, + 3;155,159,162;, + 3;162,159,156;, + 3;251,250,247;, + 3;162,187,155;, + 3;185,164,182;, + 3;183,3418,137;, + 3;164,34,181;, + 3;58,16,181;, + 3;168,37,847;, + 3;175,173,177;, + 3;165,173,179;, + 3;203,847,37;, + 3;154,14,38;, + 3;205,177,173;, + 3;202,169,203;, + 3;204,166,3490;, + 3;168,3491,171;, + 3;167,3492,165;, + 3;168,47,37;, + 3;154,172,176;, + 3;165,205,173;, + 3;38,174,172;, + 3;38,172,154;, + 3;173,174,179;, + 3;174,173,175;, + 3;179,174,180;, + 3;172,174,175;, + 3;202,80,169;, + 3;189,3493,178;, + 3;166,170,188;, + 3;174,38,180;, + 3;165,179,167;, + 3;180,38,57;, + 3;179,180,167;, + 3;734,57,46;, + 3;175,176,172;, + 3;3494,3495,3496;, + 3;3497,3496,3498;, + 3;3497,3498,3499;, + 3;163,3497,3499;, + 3;186,3500,3501;, + 3;3502,163,3503;, + 3;3501,3504,3444;, + 3;176,3486,154;, + 3;3494,3505,3495;, + 3;16,3482,181;, + 3;182,181,3482;, + 3;58,181,34;, + 3;182,3482,3483;, + 3;164,181,182;, + 3;183,137,157;, + 3;3506,3507,183;, + 3;158,184,3508;, + 3;3482,139,3483;, + 3;185,3483,3509;, + 3;183,3507,3418;, + 3;185,182,3483;, + 3;163,3502,186;, + 3;3510,164,185;, + 3;187,3506,244;, + 3;3494,3496,3497;, + 3;3444,3504,42;, + 3;3504,3501,3500;, + 3;166,188,3511;, + 3;3500,186,3502;, + 3;177,3493,189;, + 3;163,3499,3503;, + 3;139,147,190;, + 3;3512,191,3513;, + 3;192,143,146;, + 3;3483,193,3509;, + 3;137,195,192;, + 3;195,137,194;, + 3;143,197,191;, + 3;197,143,196;, + 3;3514,199,3515;, + 3;199,3514,198;, + 3;3513,201,3516;, + 3;201,3513,200;, + 3;192,196,143;, + 3;196,192,195;, + 3;191,200,3513;, + 3;200,191,197;, + 3;3516,198,3514;, + 3;198,3516,201;, + 3;3515,194,137;, + 3;194,3515,199;, + 3;80,3457,169;, + 3;169,170,203;, + 3;37,80,202;, + 3;170,204,203;, + 3;202,203,37;, + 3;170,166,204;, + 3;204,3491,203;, + 3;3493,177,205;, + 3;204,3490,3491;, + 3;3,85,152;, + 3;226,228,112;, + 3;152,85,89;, + 3;226,223,229;, + 3;213,227,233;, + 3;3506,183,243;, + 3;152,89,208;, + 3;226,229,228;, + 3;109,226,112;, + 3;208,209,152;, + 3;147,152,209;, + 3;147,209,210;, + 3;147,210,150;, + 3;210,211,150;, + 3;232,231,227;, + 3;3512,3517,212;, + 3;212,191,3512;, + 3;216,151,214;, + 3;227,213,232;, + 3;144,216,214;, + 3;10,1740,215;, + 3;215,151,8;, + 3;215,214,151;, + 3;10,215,98;, + 3;161,142,3484;, + 3;1745,1742,142;, + 3;846,151,216;, + 3;224,213,233;, + 3;148,17,217;, + 3;148,217,138;, + 3;218,146,219;, + 3;145,146,218;, + 3;234,235,225;, + 3;220,219,143;, + 3;224,235,236;, + 3;213,224,237;, + 3;224,236,238;, + 3;213,237,232;, + 3;224,238,237;, + 3;220,221,222;, + 3;220,143,221;, + 3;207,223,141;, + 3;223,207,227;, + 3;3485,225,3518;, + 3;3485,3519,234;, + 3;3520,231,3521;, + 3;231,3520,230;, + 3;3522,237,3523;, + 3;237,3522,232;, + 3;3524,230,3520;, + 3;230,3524,229;, + 3;224,3518,225;, + 3;3467,228,3525;, + 3;228,3467,112;, + 3;141,223,206;, + 3;226,206,223;, + 3;3526,227,207;, + 3;227,3526,233;, + 3;3525,229,3524;, + 3;229,3525,228;, + 3;206,109,86;, + 3;109,206,226;, + 3;3521,232,3522;, + 3;232,3521,231;, + 3;3527,233,3526;, + 3;233,3528,224;, + 3;3529,234,3519;, + 3;234,3529,235;, + 3;3530,235,3529;, + 3;235,3530,236;, + 3;3531,236,3530;, + 3;236,3531,238;, + 3;3523,238,3531;, + 3;238,3523,237;, + 3;187,239,155;, + 3;245,246,247;, + 3;242,157,241;, + 3;244,3506,243;, + 3;157,242,240;, + 3;159,155,241;, + 3;249,245,247;, + 3;245,249,248;, + 3;240,243,157;, + 3;243,183,157;, + 3;187,244,239;, + 3;246,251,247;, + 3;3532,250,3533;, + 3;250,3532,247;, + 3;3533,251,3534;, + 3;251,3533,250;, + 3;3535,245,3536;, + 3;245,3535,246;, + 3;3537,249,3538;, + 3;249,3537,248;, + 3;3538,247,3532;, + 3;247,3538,249;, + 3;3536,248,3537;, + 3;248,3536,245;, + 3;3534,246,3535;, + 3;246,3534,251;, + 3;255,472,550;, + 3;257,258,551;, + 3;252,467,554;, + 3;453,462,446;, + 3;439,447,448;, + 3;265,262,255;, + 3;462,463,460;, + 3;449,438,450;, + 3;439,443,447;, + 3;469,313,465;, + 3;254,289,466;, + 3;466,483,484;, + 3;260,435,432;, + 3;465,468,469;, + 3;260,473,474;, + 3;434,3539,3540;, + 3;259,465,474;, + 3;266,3541,262;, + 3;313,255,262;, + 3;438,449,445;, + 3;459,258,264;, + 3;265,266,262;, + 3;345,287,343;, + 3;486,485,271;, + 3;344,274,275;, + 3;335,534,535;, + 3;273,3542,340;, + 3;279,337,282;, + 3;393,333,269;, + 3;279,333,280;, + 3;3543,476,475;, + 3;397,400,417;, + 3;398,284,402;, + 3;388,284,405;, + 3;342,285,3544;, + 3;399,407,338;, + 3;394,392,3542;, + 3;480,479,285;, + 3;3542,392,342;, + 3;288,340,3542;, + 3;287,333,282;, + 3;344,334,274;, + 3;333,287,345;, + 3;343,275,270;, + 3;3544,285,552;, + 3;340,288,3544;, + 3;399,389,404;, + 3;290,295,296;, + 3;296,291,290;, + 3;291,296,297;, + 3;297,292,291;, + 3;292,297,298;, + 3;298,293,292;, + 3;309,310,299;, + 3;299,294,309;, + 3;300,301,424;, + 3;3545,422,3546;, + 3;301,302,424;, + 3;347,349,422;, + 3;305,423,306;, + 3;271,368,367;, + 3;3547,3548,301;, + 3;301,300,3547;, + 3;301,3549,426;, + 3;3549,301,3548;, + 3;358,426,359;, + 3;3550,359,426;, + 3;360,3551,364;, + 3;272,303,379;, + 3;374,276,277;, + 3;3552,3553,354;, + 3;3554,3555,306;, + 3;425,353,3553;, + 3;3555,3556,305;, + 3;305,306,3555;, + 3;305,3557,304;, + 3;3557,305,3556;, + 3;3558,3559,3546;, + 3;3546,3560,3558;, + 3;380,277,272;, + 3;294,299,308;, + 3;380,384,277;, + 3;3561,362,3550;, + 3;309,293,310;, + 3;310,293,298;, + 3;425,3553,3554;, + 3;518,517,330;, + 3;376,377,3562;, + 3;3543,477,476;, + 3;286,265,478;, + 3;487,277,488;, + 3;324,273,536;, + 3;313,470,255;, + 3;465,313,262;, + 3;502,501,314;, + 3;489,3562,490;, + 3;3563,491,317;, + 3;533,547,537;, + 3;318,492,493;, + 3;494,485,315;, + 3;330,503,504;, + 3;491,272,495;, + 3;495,487,319;, + 3;506,505,320;, + 3;488,277,496;, + 3;496,497,320;, + 3;519,312,520;, + 3;498,346,499;, + 3;499,489,316;, + 3;497,276,500;, + 3;500,3564,3565;, + 3;507,312,508;, + 3;510,509,319;, + 3;323,268,322;, + 3;512,511,3566;, + 3;466,3540,254;, + 3;550,478,255;, + 3;286,478,479;, + 3;410,387,411;, + 3;390,265,286;, + 3;332,289,254;, + 3;289,256,466;, + 3;281,256,289;, + 3;281,258,256;, + 3;279,548,391;, + 3;279,280,549;, + 3;549,280,261;, + 3;311,472,475;, + 3;3567,472,3568;, + 3;335,340,3544;, + 3;519,323,521;, + 3;513,511,325;, + 3;318,503,514;, + 3;3569,509,327;, + 3;515,505,328;, + 3;516,318,514;, + 3;506,3570,329;, + 3;504,501,330;, + 3;522,518,330;, + 3;267,538,539;, + 3;540,275,541;, + 3;526,278,527;, + 3;525,526,329;, + 3;507,321,515;, + 3;528,322,529;, + 3;521,528,331;, + 3;529,322,530;, + 3;502,513,325;, + 3;510,319,508;, + 3;531,328,527;, + 3;324,532,531;, + 3;325,3571,523;, + 3;420,400,418;, + 3;266,3572,3541;, + 3;279,282,333;, + 3;267,269,553;, + 3;414,409,416;, + 3;287,282,334;, + 3;536,544,336;, + 3;268,534,3573;, + 3;520,312,532;, + 3;548,281,391;, + 3;284,398,403;, + 3;410,416,409;, + 3;338,389,399;, + 3;288,341,3544;, + 3;3542,341,288;, + 3;273,340,543;, + 3;3542,339,341;, + 3;341,339,3544;, + 3;339,342,3544;, + 3;3542,342,339;, + 3;343,344,275;, + 3;267,343,270;, + 3;287,344,343;, + 3;287,334,344;, + 3;267,345,343;, + 3;553,345,267;, + 3;486,498,314;, + 3;347,3545,357;, + 3;271,367,346;, + 3;348,368,271;, + 3;493,348,494;, + 3;370,348,371;, + 3;350,3574,349;, + 3;422,3574,3560;, + 3;348,369,368;, + 3;3575,351,306;, + 3;369,348,370;, + 3;348,307,371;, + 3;306,425,3554;, + 3;351,352,306;, + 3;371,307,372;, + 3;354,3553,353;, + 3;384,374,277;, + 3;3576,276,375;, + 3;374,375,276;, + 3;346,376,3562;, + 3;367,376,346;, + 3;3577,302,358;, + 3;3550,426,3549;, + 3;359,3550,362;, + 3;3562,377,378;, + 3;385,373,3576;, + 3;3576,375,385;, + 3;355,3552,356;, + 3;3578,3552,355;, + 3;379,303,382;, + 3;3561,3551,360;, + 3;3551,361,364;, + 3;3551,3579,361;, + 3;378,381,3562;, + 3;3561,363,362;, + 3;360,363,3561;, + 3;383,380,272;, + 3;379,383,272;, + 3;361,3579,365;, + 3;3578,355,3580;, + 3;366,356,3552;, + 3;3552,354,366;, + 3;3581,3582,367;, + 3;367,368,3581;, + 3;3583,3584,378;, + 3;378,377,3583;, + 3;3585,3586,383;, + 3;383,379,3585;, + 3;3587,3588,371;, + 3;371,372,3587;, + 3;3589,3590,384;, + 3;384,380,3589;, + 3;3591,3583,377;, + 3;377,376,3591;, + 3;3582,3591,376;, + 3;376,367,3582;, + 3;3588,3592,370;, + 3;370,371,3588;, + 3;3593,3581,368;, + 3;368,369,3593;, + 3;3592,3593,369;, + 3;369,370,3592;, + 3;3590,3594,374;, + 3;374,384,3590;, + 3;3594,3595,375;, + 3;375,374,3594;, + 3;3584,3596,381;, + 3;381,378,3584;, + 3;3597,3598,373;, + 3;373,385,3597;, + 3;3595,3597,385;, + 3;385,375,3595;, + 3;3599,3585,379;, + 3;379,382,3599;, + 3;3586,3589,380;, + 3;380,383,3586;, + 3;338,386,389;, + 3;409,387,410;, + 3;418,400,401;, + 3;418,401,419;, + 3;409,412,387;, + 3;284,403,405;, + 3;419,401,413;, + 3;413,401,396;, + 3;415,413,396;, + 3;266,265,390;, + 3;405,408,388;, + 3;279,391,337;, + 3;395,479,480;, + 3;392,285,342;, + 3;393,280,333;, + 3;477,3543,3600;, + 3;338,407,406;, + 3;3601,274,334;, + 3;480,285,392;, + 3;395,392,394;, + 3;3602,3603,403;, + 3;403,398,3602;, + 3;3604,3605,400;, + 3;400,397,3604;, + 3;3606,3604,397;, + 3;397,408,3606;, + 3;3607,3602,398;, + 3;398,402,3607;, + 3;3603,3606,405;, + 3;405,403,3603;, + 3;3608,3609,399;, + 3;399,404,3608;, + 3;3605,3610,401;, + 3;401,400,3605;, + 3;3610,3611,396;, + 3;396,401,3610;, + 3;3612,3607,402;, + 3;402,406,3612;, + 3;3611,3608,404;, + 3;404,396,3611;, + 3;3609,3613,407;, + 3;407,399,3609;, + 3;3613,3612,406;, + 3;406,407,3613;, + 3;417,400,420;, + 3;408,405,3606;, + 3;397,417,408;, + 3;402,284,409;, + 3;409,414,402;, + 3;338,406,416;, + 3;416,410,338;, + 3;404,389,413;, + 3;413,415,404;, + 3;386,338,410;, + 3;410,411,386;, + 3;406,402,414;, + 3;414,416,406;, + 3;389,386,411;, + 3;411,413,389;, + 3;284,388,412;, + 3;412,409,284;, + 3;396,404,415;, + 3;388,408,417;, + 3;417,412,388;, + 3;411,387,418;, + 3;418,419,411;, + 3;387,412,420;, + 3;420,418,387;, + 3;413,411,419;, + 3;417,420,412;, + 3;258,421,264;, + 3;421,258,257;, + 3;3598,3576,373;, + 3;354,353,3614;, + 3;3587,372,307;, + 3;362,363,3615;, + 3;3599,382,303;, + 3;381,3596,3562;, + 3;422,349,3574;, + 3;422,3560,3546;, + 3;3575,306,423;, + 3;423,305,304;, + 3;424,302,3577;, + 3;422,3545,347;, + 3;306,352,425;, + 3;352,353,425;, + 3;358,302,426;, + 3;301,426,302;, + 3;444,443,442;, + 3;443,439,442;, + 3;454,457,455;, + 3;438,445,452;, + 3;432,431,464;, + 3;432,473,260;, + 3;263,433,434;, + 3;482,434,3540;, + 3;431,427,464;, + 3;464,427,556;, + 3;448,451,440;, + 3;448,440,439;, + 3;450,3616,3617;, + 3;438,3616,450;, + 3;429,433,263;, + 3;458,481,459;, + 3;452,445,3618;, + 3;454,456,457;, + 3;462,460,446;, + 3;428,3619,443;, + 3;443,444,428;, + 3;3620,3621,448;, + 3;448,447,3620;, + 3;3622,3623,449;, + 3;449,450,3622;, + 3;3619,3620,447;, + 3;447,443,3619;, + 3;3621,3624,451;, + 3;451,448,3621;, + 3;3625,3622,450;, + 3;450,3617,3625;, + 3;3623,3626,445;, + 3;445,449,3623;, + 3;3627,3628,442;, + 3;442,439,3627;, + 3;3629,3630,438;, + 3;438,452,3629;, + 3;3631,3627,439;, + 3;439,440,3631;, + 3;3630,3632,3616;, + 3;3616,438,3630;, + 3;3626,437,3618;, + 3;3618,445,3626;, + 3;3633,3634,3635;, + 3;3635,441,3633;, + 3;3636,3637,455;, + 3;455,457,3636;, + 3;3635,3636,457;, + 3;457,456,3635;, + 3;441,3635,456;, + 3;456,454,441;, + 3;429,458,3638;, + 3;429,481,458;, + 3;256,258,459;, + 3;463,461,460;, + 3;3638,458,462;, + 3;462,453,3638;, + 3;458,459,463;, + 3;463,462,458;, + 3;459,264,461;, + 3;461,463,459;, + 3;253,430,446;, + 3;446,460,253;, + 3;264,253,460;, + 3;3639,3640,3641;, + 3;556,427,554;, + 3;473,259,474;, + 3;3541,474,262;, + 3;259,468,465;, + 3;466,256,483;, + 3;3540,466,482;, + 3;259,467,468;, + 3;464,467,259;, + 3;467,252,468;, + 3;469,555,3568;, + 3;469,468,252;, + 3;470,313,469;, + 3;3568,470,469;, + 3;470,3568,471;, + 3;472,255,471;, + 3;470,471,255;, + 3;3568,472,471;, + 3;311,283,472;, + 3;432,464,473;, + 3;464,259,473;, + 3;474,465,262;, + 3;260,474,3541;, + 3;475,472,3567;, + 3;3543,475,3567;, + 3;476,477,311;, + 3;476,311,475;, + 3;3544,552,3600;, + 3;477,285,311;, + 3;265,255,478;, + 3;478,283,311;, + 3;479,478,311;, + 3;479,311,285;, + 3;395,480,392;, + 3;286,479,395;, + 3;429,263,481;, + 3;481,263,484;, + 3;482,466,484;, + 3;263,434,482;, + 3;483,256,459;, + 3;483,459,484;, + 3;484,459,481;, + 3;482,484,263;, + 3;486,315,485;, + 3;314,315,486;, + 3;319,487,488;, + 3;319,488,321;, + 3;316,489,490;, + 3;316,490,3566;, + 3;3563,272,491;, + 3;303,272,3563;, + 3;493,492,348;, + 3;492,307,348;, + 3;494,271,485;, + 3;348,271,494;, + 3;317,491,495;, + 3;317,495,319;, + 3;495,277,487;, + 3;272,277,495;, + 3;321,488,496;, + 3;321,496,320;, + 3;496,276,497;, + 3;277,276,496;, + 3;314,498,499;, + 3;314,499,316;, + 3;499,3562,489;, + 3;346,3562,499;, + 3;320,497,500;, + 3;320,500,3565;, + 3;500,3576,3564;, + 3;276,3576,500;, + 3;486,346,498;, + 3;271,346,486;, + 3;318,493,494;, + 3;318,494,315;, + 3;502,325,501;, + 3;325,545,501;, + 3;504,503,315;, + 3;503,318,315;, + 3;506,328,505;, + 3;329,328,506;, + 3;321,507,508;, + 3;321,508,319;, + 3;510,331,509;, + 3;331,327,509;, + 3;512,325,511;, + 3;3642,325,512;, + 3;513,3566,511;, + 3;316,3566,513;, + 3;514,503,326;, + 3;503,330,326;, + 3;3569,319,509;, + 3;317,319,3569;, + 3;515,320,505;, + 3;321,320,515;, + 3;3643,516,514;, + 3;3643,514,326;, + 3;506,3565,3570;, + 3;320,3565,506;, + 3;504,314,501;, + 3;315,314,504;, + 3;312,507,515;, + 3;312,515,328;, + 3;502,316,513;, + 3;314,316,502;, + 3;331,510,508;, + 3;331,508,312;, + 3;542,540,517;, + 3;336,519,520;, + 3;323,519,336;, + 3;331,519,521;, + 3;312,519,331;, + 3;538,542,522;, + 3;523,522,325;, + 3;522,545,325;, + 3;326,517,524;, + 3;330,517,326;, + 3;524,3644,326;, + 3;3644,3643,326;, + 3;329,526,527;, + 3;329,527,328;, + 3;525,278,526;, + 3;275,3645,541;, + 3;327,528,529;, + 3;331,528,327;, + 3;521,323,528;, + 3;323,322,528;, + 3;327,529,530;, + 3;3642,3571,325;, + 3;324,531,527;, + 3;324,527,278;, + 3;531,532,328;, + 3;532,312,328;, + 3;539,537,267;, + 3;336,520,532;, + 3;336,532,324;, + 3;267,537,547;, + 3;535,534,323;, + 3;534,268,323;, + 3;546,275,274;, + 3;278,273,324;, + 3;3646,533,537;, + 3;3646,537,3647;, + 3;536,336,324;, + 3;539,538,523;, + 3;538,522,523;, + 3;517,540,541;, + 3;517,541,524;, + 3;541,3644,524;, + 3;536,543,544;, + 3;273,543,536;, + 3;3573,534,335;, + 3;3573,335,3648;, + 3;535,323,336;, + 3;3542,273,3649;, + 3;518,542,517;, + 3;542,275,540;, + 3;270,275,542;, + 3;522,542,518;, + 3;538,267,542;, + 3;267,270,542;, + 3;541,3645,3644;, + 3;539,523,537;, + 3;523,3571,537;, + 3;3571,3647,537;, + 3;543,340,335;, + 3;543,335,535;, + 3;544,543,535;, + 3;544,535,336;, + 3;522,330,545;, + 3;545,330,501;, + 3;3649,273,278;, + 3;3645,275,546;, + 3;3648,335,3544;, + 3;547,269,267;, + 3;279,258,548;, + 3;258,281,548;, + 3;258,549,551;, + 3;279,549,258;, + 3;550,472,283;, + 3;283,478,550;, + 3;551,549,261;, + 3;257,551,261;, + 3;552,285,477;, + 3;552,477,3600;, + 3;553,269,333;, + 3;333,345,553;, + 3;554,427,3650;, + 3;469,252,555;, + 3;467,556,554;, + 3;464,556,467;, + 3;558,840,762;, + 3;257,841,560;, + 3;252,554,757;, + 3;747,446,752;, + 3;737,742,741;, + 3;566,558,564;, + 3;752,460,753;, + 3;743,744,736;, + 3;737,741,739;, + 3;759,755,614;, + 3;557,756,590;, + 3;756,774,773;, + 3;562,730,733;, + 3;755,759,758;, + 3;562,764,763;, + 3;732,3651,3652;, + 3;561,764,755;, + 3;567,564,3653;, + 3;614,564,558;, + 3;736,740,743;, + 3;751,264,560;, + 3;566,564,567;, + 3;646,644,588;, + 3;776,572,775;, + 3;645,576,575;, + 3;636,825,824;, + 3;574,641,3654;, + 3;580,583,638;, + 3;694,570,634;, + 3;580,581,634;, + 3;3655,765,766;, + 3;698,718,701;, + 3;699,703,585;, + 3;689,706,585;, + 3;643,3656,586;, + 3;700,639,708;, + 3;695,3654,693;, + 3;770,586,769;, + 3;3654,643,693;, + 3;589,3654,641;, + 3;588,583,634;, + 3;645,575,635;, + 3;634,646,588;, + 3;644,571,576;, + 3;3656,842,586;, + 3;641,3656,589;, + 3;700,705,690;, + 3;591,597,596;, + 3;597,591,592;, + 3;592,598,597;, + 3;598,592,593;, + 3;593,599,598;, + 3;599,593,594;, + 3;610,600,611;, + 3;600,610,595;, + 3;601,724,602;, + 3;3657,3658,722;, + 3;602,724,603;, + 3;648,722,650;, + 3;606,607,723;, + 3;572,668,669;, + 3;3659,602,3660;, + 3;602,3659,601;, + 3;602,726,3661;, + 3;3661,3660,602;, + 3;659,660,726;, + 3;3662,726,660;, + 3;661,665,3663;, + 3;573,680,604;, + 3;675,578,577;, + 3;3664,655,3665;, + 3;3666,607,3667;, + 3;725,3665,654;, + 3;3667,606,3668;, + 3;606,3667,607;, + 3;606,605,3669;, + 3;3669,3668,606;, + 3;3670,3658,3671;, + 3;3658,3670,3672;, + 3;681,573,578;, + 3;595,609,600;, + 3;681,578,685;, + 3;3673,3662,663;, + 3;610,611,594;, + 3;611,599,594;, + 3;725,3666,3665;, + 3;808,631,807;, + 3;677,3674,678;, + 3;3655,766,767;, + 3;587,768,566;, + 3;777,778,578;, + 3;625,826,574;, + 3;614,558,760;, + 3;755,564,614;, + 3;792,615,791;, + 3;779,780,3674;, + 3;3675,618,781;, + 3;823,827,837;, + 3;619,783,782;, + 3;784,616,775;, + 3;631,794,793;, + 3;781,785,573;, + 3;785,620,777;, + 3;796,621,795;, + 3;778,786,578;, + 3;786,621,787;, + 3;809,810,613;, + 3;788,789,647;, + 3;789,617,779;, + 3;787,790,577;, + 3;790,3676,3677;, + 3;797,798,613;, + 3;800,620,799;, + 3;624,623,569;, + 3;802,3678,801;, + 3;756,557,3651;, + 3;840,558,768;, + 3;587,769,768;, + 3;711,712,688;, + 3;691,587,566;, + 3;633,557,590;, + 3;590,756,559;, + 3;582,590,559;, + 3;582,559,560;, + 3;580,692,838;, + 3;580,839,581;, + 3;839,563,581;, + 3;612,765,762;, + 3;3679,3568,762;, + 3;636,3656,641;, + 3;809,811,624;, + 3;803,626,801;, + 3;619,804,793;, + 3;3680,628,799;, + 3;805,629,795;, + 3;806,804,619;, + 3;796,630,3681;, + 3;794,631,791;, + 3;812,631,808;, + 3;568,829,828;, + 3;830,831,576;, + 3;816,817,579;, + 3;815,630,816;, + 3;797,805,622;, + 3;818,819,623;, + 3;811,632,818;, + 3;819,820,623;, + 3;792,626,803;, + 3;800,798,620;, + 3;821,817,629;, + 3;625,821,822;, + 3;626,813,3682;, + 3;721,719,701;, + 3;567,3653,3683;, + 3;580,634,583;, + 3;568,843,570;, + 3;715,717,710;, + 3;588,635,583;, + 3;826,637,834;, + 3;569,3684,824;, + 3;810,822,613;, + 3;838,692,582;, + 3;585,704,699;, + 3;711,710,717;, + 3;639,700,690;, + 3;589,3656,642;, + 3;3654,589,642;, + 3;574,833,641;, + 3;3654,642,640;, + 3;642,3656,640;, + 3;640,3656,643;, + 3;3654,640,643;, + 3;644,576,645;, + 3;568,571,644;, + 3;588,644,645;, + 3;588,645,635;, + 3;568,644,646;, + 3;843,568,646;, + 3;776,615,788;, + 3;724,658,603;, + 3;572,647,668;, + 3;649,572,669;, + 3;783,784,649;, + 3;671,672,649;, + 3;651,650,3685;, + 3;722,3672,3685;, + 3;649,669,670;, + 3;3686,607,652;, + 3;670,671,649;, + 3;649,672,608;, + 3;607,3666,725;, + 3;652,607,653;, + 3;672,673,608;, + 3;655,654,3665;, + 3;685,578,675;, + 3;3687,676,577;, + 3;675,577,676;, + 3;647,3674,677;, + 3;668,647,677;, + 3;658,659,603;, + 3;3662,3661,726;, + 3;660,663,3662;, + 3;3674,679,678;, + 3;686,3687,674;, + 3;3687,686,676;, + 3;656,657,3664;, + 3;3688,656,3664;, + 3;680,683,604;, + 3;3673,661,3663;, + 3;3663,665,662;, + 3;3663,662,3689;, + 3;679,3674,682;, + 3;3673,663,664;, + 3;661,3673,664;, + 3;684,573,681;, + 3;680,573,684;, + 3;662,666,3689;, + 3;3688,3690,656;, + 3;667,3664,657;, + 3;3664,667,655;, + 3;3691,668,3692;, + 3;668,3691,669;, + 3;3693,679,3694;, + 3;679,3693,678;, + 3;3695,684,3696;, + 3;684,3695,680;, + 3;3697,672,3698;, + 3;672,3697,673;, + 3;3699,685,3700;, + 3;685,3699,681;, + 3;3701,678,3693;, + 3;678,3701,677;, + 3;3692,677,3701;, + 3;677,3692,668;, + 3;3698,671,3702;, + 3;671,3698,672;, + 3;3703,669,3691;, + 3;669,3703,670;, + 3;3702,670,3703;, + 3;670,3702,671;, + 3;3700,675,3704;, + 3;675,3700,685;, + 3;3704,676,3705;, + 3;676,3704,675;, + 3;3694,682,3706;, + 3;682,3694,679;, + 3;3707,674,3708;, + 3;674,3707,686;, + 3;3705,686,3707;, + 3;686,3705,676;, + 3;3709,680,3695;, + 3;680,3709,683;, + 3;3696,681,3699;, + 3;681,3696,684;, + 3;639,690,687;, + 3;710,711,688;, + 3;719,702,701;, + 3;719,720,702;, + 3;710,688,713;, + 3;585,706,704;, + 3;720,714,702;, + 3;714,697,702;, + 3;716,697,714;, + 3;567,691,566;, + 3;706,689,709;, + 3;580,638,692;, + 3;696,770,769;, + 3;693,643,586;, + 3;694,634,581;, + 3;767,3710,3655;, + 3;639,707,708;, + 3;3711,635,575;, + 3;770,693,586;, + 3;696,695,693;, + 3;3712,704,3713;, + 3;704,3712,699;, + 3;3714,701,3715;, + 3;701,3714,698;, + 3;3716,698,3714;, + 3;698,3716,709;, + 3;3717,699,3712;, + 3;699,3717,703;, + 3;3713,706,3716;, + 3;706,3713,704;, + 3;3718,700,3719;, + 3;700,3718,705;, + 3;3715,702,3720;, + 3;702,3715,701;, + 3;3720,697,3721;, + 3;697,3720,702;, + 3;3722,703,3717;, + 3;703,3722,707;, + 3;3721,705,3718;, + 3;705,3721,697;, + 3;3719,708,3723;, + 3;708,3719,700;, + 3;3723,707,3722;, + 3;707,3723,708;, + 3;718,721,701;, + 3;709,3716,706;, + 3;698,709,718;, + 3;703,710,585;, + 3;710,703,715;, + 3;639,717,707;, + 3;717,639,711;, + 3;705,714,690;, + 3;714,705,716;, + 3;687,711,639;, + 3;711,687,712;, + 3;707,715,703;, + 3;715,707,717;, + 3;690,712,687;, + 3;712,690,714;, + 3;585,713,689;, + 3;713,585,710;, + 3;697,716,705;, + 3;689,718,709;, + 3;718,689,713;, + 3;712,719,688;, + 3;719,712,720;, + 3;688,721,713;, + 3;721,688,719;, + 3;714,720,712;, + 3;718,713,721;, + 3;560,264,421;, + 3;421,257,560;, + 3;3708,674,3687;, + 3;655,3724,654;, + 3;3697,608,673;, + 3;663,3725,664;, + 3;3709,604,683;, + 3;682,3674,3706;, + 3;722,3685,650;, + 3;722,3658,3672;, + 3;3686,723,607;, + 3;723,605,606;, + 3;3657,648,3726;, + 3;722,648,3657;, + 3;607,725,653;, + 3;653,725,654;, + 3;659,726,603;, + 3;602,603,726;, + 3;444,442,739;, + 3;739,442,737;, + 3;454,455,749;, + 3;736,746,740;, + 3;730,754,729;, + 3;730,562,763;, + 3;565,732,731;, + 3;772,3651,732;, + 3;729,754,727;, + 3;754,844,727;, + 3;742,738,745;, + 3;742,737,738;, + 3;744,3727,3728;, + 3;736,744,3728;, + 3;728,565,731;, + 3;750,751,771;, + 3;746,3729,740;, + 3;454,749,748;, + 3;752,446,460;, + 3;428,739,3730;, + 3;739,428,444;, + 3;3731,742,3732;, + 3;742,3731,741;, + 3;3733,743,3734;, + 3;743,3733,744;, + 3;3730,741,3731;, + 3;741,3730,739;, + 3;3732,745,3735;, + 3;745,3732,742;, + 3;3736,744,3733;, + 3;744,3736,3727;, + 3;3734,740,3737;, + 3;740,3734,743;, + 3;3738,442,3628;, + 3;442,3738,737;, + 3;3739,736,3740;, + 3;736,3739,746;, + 3;3741,737,3738;, + 3;737,3741,738;, + 3;3740,3728,3742;, + 3;3728,3740,736;, + 3;3737,3729,735;, + 3;3729,3737,740;, + 3;3633,3743,3744;, + 3;3743,3633,441;, + 3;3745,455,3637;, + 3;455,3745,749;, + 3;3743,749,3745;, + 3;749,3743,748;, + 3;441,748,3743;, + 3;748,441,454;, + 3;728,3746,750;, + 3;728,750,771;, + 3;559,751,560;, + 3;753,460,461;, + 3;3746,752,750;, + 3;752,3746,747;, + 3;750,753,751;, + 3;753,750,752;, + 3;751,461,264;, + 3;461,751,753;, + 3;253,446,430;, + 3;446,253,460;, + 3;264,460,253;, + 3;460,264,461;, + 3;844,554,727;, + 3;763,764,561;, + 3;3653,564,764;, + 3;561,755,758;, + 3;756,773,559;, + 3;3651,772,756;, + 3;561,758,757;, + 3;754,561,757;, + 3;757,758,252;, + 3;759,3568,555;, + 3;759,252,758;, + 3;760,759,614;, + 3;3568,759,760;, + 3;760,761,3568;, + 3;762,761,558;, + 3;760,558,761;, + 3;3568,761,762;, + 3;612,762,584;, + 3;730,763,754;, + 3;754,763,561;, + 3;764,564,755;, + 3;562,3653,764;, + 3;765,3679,762;, + 3;3655,3679,765;, + 3;766,612,767;, + 3;766,765,612;, + 3;3656,3710,842;, + 3;767,612,586;, + 3;566,768,558;, + 3;768,612,584;, + 3;769,612,768;, + 3;769,586,612;, + 3;696,693,770;, + 3;587,696,769;, + 3;728,771,565;, + 3;771,774,565;, + 3;772,774,756;, + 3;565,772,732;, + 3;773,751,559;, + 3;773,774,751;, + 3;774,771,751;, + 3;772,565,774;, + 3;776,775,616;, + 3;615,776,616;, + 3;620,778,777;, + 3;620,622,778;, + 3;617,780,779;, + 3;617,3678,780;, + 3;3675,781,573;, + 3;604,3675,573;, + 3;783,649,782;, + 3;782,649,608;, + 3;784,775,572;, + 3;649,784,572;, + 3;618,785,781;, + 3;618,620,785;, + 3;785,777,578;, + 3;573,785,578;, + 3;622,786,778;, + 3;622,621,786;, + 3;786,787,577;, + 3;578,786,577;, + 3;615,789,788;, + 3;615,617,789;, + 3;789,779,3674;, + 3;647,789,3674;, + 3;621,790,787;, + 3;621,3676,790;, + 3;790,3677,3687;, + 3;577,790,3687;, + 3;776,788,647;, + 3;572,776,647;, + 3;619,784,783;, + 3;619,616,784;, + 3;792,791,626;, + 3;626,791,835;, + 3;794,616,793;, + 3;793,616,619;, + 3;796,795,629;, + 3;630,796,629;, + 3;622,798,797;, + 3;622,620,798;, + 3;800,799,632;, + 3;632,799,628;, + 3;802,801,626;, + 3;3747,802,626;, + 3;803,801,3678;, + 3;617,803,3678;, + 3;804,627,793;, + 3;793,627,631;, + 3;3680,799,620;, + 3;618,3680,620;, + 3;805,795,621;, + 3;622,805,621;, + 3;3748,804,806;, + 3;3748,627,804;, + 3;796,3681,3676;, + 3;621,796,3676;, + 3;794,791,615;, + 3;616,794,615;, + 3;613,805,797;, + 3;613,629,805;, + 3;792,803,617;, + 3;615,792,617;, + 3;632,798,800;, + 3;632,613,798;, + 3;832,807,830;, + 3;637,810,809;, + 3;624,637,809;, + 3;632,811,809;, + 3;613,632,809;, + 3;828,812,832;, + 3;813,626,812;, + 3;812,626,835;, + 3;627,814,807;, + 3;631,627,807;, + 3;814,627,3749;, + 3;3749,627,3748;, + 3;630,817,816;, + 3;630,629,817;, + 3;815,816,579;, + 3;576,831,3750;, + 3;628,819,818;, + 3;632,628,818;, + 3;811,818,624;, + 3;624,818,623;, + 3;628,820,819;, + 3;3747,626,3682;, + 3;625,817,821;, + 3;625,579,817;, + 3;821,629,822;, + 3;822,629,613;, + 3;829,568,827;, + 3;637,822,810;, + 3;637,625,822;, + 3;568,837,827;, + 3;825,624,824;, + 3;824,624,569;, + 3;836,575,576;, + 3;579,625,574;, + 3;3751,827,823;, + 3;3751,3752,827;, + 3;826,625,637;, + 3;829,813,828;, + 3;828,813,812;, + 3;807,831,830;, + 3;807,814,831;, + 3;831,814,3749;, + 3;826,834,833;, + 3;574,826,833;, + 3;3684,636,824;, + 3;3684,3753,636;, + 3;825,637,624;, + 3;3654,3754,574;, + 3;808,807,832;, + 3;832,830,576;, + 3;571,832,576;, + 3;812,808,832;, + 3;828,832,568;, + 3;568,832,571;, + 3;831,3749,3750;, + 3;829,827,813;, + 3;813,827,3682;, + 3;3682,827,3752;, + 3;833,636,641;, + 3;833,825,636;, + 3;834,825,833;, + 3;834,637,825;, + 3;812,835,631;, + 3;835,791,631;, + 3;3754,579,574;, + 3;3750,836,576;, + 3;3753,3656,636;, + 3;837,568,570;, + 3;580,838,560;, + 3;560,838,582;, + 3;560,841,839;, + 3;580,560,839;, + 3;840,584,762;, + 3;584,840,768;, + 3;841,563,839;, + 3;257,563,841;, + 3;842,767,586;, + 3;842,3710,767;, + 3;843,634,570;, + 3;634,843,646;, + 3;554,3650,727;, + 3;759,555,252;, + 3;757,554,844;, + 3;754,757,844;, + 3;845,99,21;, + 3;3755,846,216;, + 3;180,734,167;, + 3;180,57,734;, + 3;46,57,436;, + 3;436,56,40;, + 3;203,3491,847;, + 3;168,847,3491;, + 3;82,37,848;, + 3;41,848,37;, + 3;849,1291,850;, + 3;943,852,851;, + 3;849,1290,944;, + 3;1289,854,1293;, + 3;854,1289,944;, + 3;859,888,945;, + 3;855,861,887;, + 3;946,856,3756;, + 3;1292,3757,3758;, + 3;3757,3759,3760;, + 3;852,946,851;, + 3;857,889,849;, + 3;858,857,850;, + 3;850,857,849;, + 3;853,860,1290;, + 3;3761,861,3758;, + 3;3758,861,855;, + 3;887,859,945;, + 3;875,891,890;, + 3;893,892,862;, + 3;894,869,895;, + 3;897,896,863;, + 3;898,876,899;, + 3;900,862,892;, + 3;902,901,874;, + 3;898,877,903;, + 3;868,904,890;, + 3;894,864,905;, + 3;905,864,904;, + 3;896,872,895;, + 3;867,902,906;, + 3;3762,3763,891;, + 3;899,906,865;, + 3;903,3764,3765;, + 3;901,900,874;, + 3;3763,880,868;, + 3;880,3763,879;, + 3;867,882,878;, + 3;882,867,881;, + 3;3765,884,876;, + 3;884,3765,883;, + 3;866,886,869;, + 3;886,866,885;, + 3;868,880,866;, + 3;885,866,880;, + 3;869,3766,863;, + 3;3766,869,886;, + 3;876,881,867;, + 3;881,876,884;, + 3;878,3767,862;, + 3;3767,878,882;, + 3;870,3768,871;, + 3;3768,870,3769;, + 3;872,3770,864;, + 3;3770,872,3771;, + 3;873,3771,872;, + 3;3771,873,3772;, + 3;865,3773,877;, + 3;3773,865,3774;, + 3;871,3775,874;, + 3;3775,871,3768;, + 3;864,3776,875;, + 3;3776,864,3770;, + 3;874,3774,865;, + 3;3774,874,3775;, + 3;875,3777,3778;, + 3;3777,875,3776;, + 3;877,3779,3780;, + 3;3779,877,3773;, + 3;890,891,868;, + 3;868,891,3763;, + 3;892,893,871;, + 3;871,893,870;, + 3;894,895,864;, + 3;864,895,872;, + 3;896,897,872;, + 3;872,897,873;, + 3;898,899,877;, + 3;877,899,865;, + 3;900,892,874;, + 3;874,892,871;, + 3;901,902,878;, + 3;878,902,867;, + 3;898,903,876;, + 3;876,903,3765;, + 3;890,904,875;, + 3;875,904,864;, + 3;894,905,869;, + 3;869,905,866;, + 3;905,904,866;, + 3;866,904,868;, + 3;896,895,863;, + 3;863,895,869;, + 3;906,902,865;, + 3;865,902,874;, + 3;3762,891,3778;, + 3;3778,891,875;, + 3;906,899,867;, + 3;867,899,876;, + 3;3764,903,3780;, + 3;3780,903,877;, + 3;900,901,862;, + 3;862,901,878;, + 3;889,1290,849;, + 3;3781,858,850;, + 3;855,887,945;, + 3;921,939,908;, + 3;942,922,3782;, + 3;923,910,924;, + 3;907,926,925;, + 3;926,927,911;, + 3;929,928,915;, + 3;3783,919,913;, + 3;931,930,913;, + 3;941,920,908;, + 3;931,932,3784;, + 3;929,933,908;, + 3;916,918,3785;, + 3;917,3786,913;, + 3;935,934,914;, + 3;916,935,936;, + 3;937,3787,938;, + 3;3788,3785,918;, + 3;3789,909,919;, + 3;912,3790,3791;, + 3;916,3786,917;, + 3;934,930,914;, + 3;918,3792,3788;, + 3;936,3787,937;, + 3;3783,913,3786;, + 3;932,3793,3784;, + 3;928,3794,915;, + 3;940,908,939;, + 3;907,942,940;, + 3;927,933,911;, + 3;922,3795,3782;, + 3;925,910,923;, + 3;923,924,922;, + 3;922,924,3795;, + 3;925,926,910;, + 3;910,926,911;, + 3;927,926,921;, + 3;921,926,907;, + 3;928,929,920;, + 3;920,929,908;, + 3;930,931,914;, + 3;914,931,3784;, + 3;932,931,919;, + 3;919,931,913;, + 3;933,929,911;, + 3;911,929,915;, + 3;934,935,917;, + 3;917,935,916;, + 3;936,935,3787;, + 3;3787,935,914;, + 3;937,938,918;, + 3;918,938,3792;, + 3;930,934,913;, + 3;913,934,917;, + 3;936,937,916;, + 3;916,937,918;, + 3;3793,932,909;, + 3;909,932,919;, + 3;3794,928,912;, + 3;912,928,920;, + 3;933,927,908;, + 3;908,927,921;, + 3;925,923,907;, + 3;907,923,922;, + 3;912,920,3790;, + 3;3782,3795,3796;, + 3;940,3782,3797;, + 3;941,940,3790;, + 3;907,939,921;, + 3;939,907,940;, + 3;940,3797,3790;, + 3;3790,920,941;, + 3;908,940,941;, + 3;907,922,942;, + 3;942,3782,940;, + 3;3789,919,3783;, + 3;3785,3786,916;, + 3;1289,852,943;, + 3;849,944,1289;, + 3;854,944,1290;, + 3;3798,3781,850;, + 3;3799,3800,851;, + 3;852,856,946;, + 3;946,3801,3799;, + 3;1271,947,3802;, + 3;3802,3803,1271;, + 3;3804,949,3805;, + 3;1273,3804,3806;, + 3;3807,948,3803;, + 3;948,3807,1272;, + 3;1274,950,3808;, + 3;1274,3805,949;, + 3;1275,1276,1274;, + 3;1278,952,1277;, + 3;1279,1280,954;, + 3;1282,951,1281;, + 3;1283,1284,1273;, + 3;1283,3809,3810;, + 3;1008,1270,956;, + 3;955,3811,3812;, + 3;981,957,1267;, + 3;970,1009,973;, + 3;3813,959,953;, + 3;1268,963,988;, + 3;3814,1263,3815;, + 3;959,3813,982;, + 3;973,958,970;, + 3;959,984,953;, + 3;3816,962,957;, + 3;1011,955,974;, + 3;984,3817,953;, + 3;984,965,3817;, + 3;991,961,964;, + 3;1263,963,1012;, + 3;963,3814,3818;, + 3;989,990,964;, + 3;3819,3820,966;, + 3;991,967,992;, + 3;992,965,991;, + 3;3818,966,963;, + 3;966,3818,968;, + 3;961,986,964;, + 3;964,986,3821;, + 3;976,974,1008;, + 3;1009,956,973;, + 3;969,1008,971;, + 3;975,974,972;, + 3;1263,1012,973;, + 3;1270,1263,956;, + 3;955,3815,1270;, + 3;969,976,1008;, + 3;1011,974,975;, + 3;1010,974,976;, + 3;3816,981,982;, + 3;980,1267,957;, + 3;959,982,981;, + 3;3816,982,3813;, + 3;961,991,984;, + 3;959,983,984;, + 3;983,961,984;, + 3;1012,963,985;, + 3;963,1268,985;, + 3;983,986,961;, + 3;983,987,986;, + 3;3820,988,963;, + 3;963,966,3820;, + 3;964,3821,989;, + 3;967,964,990;, + 3;965,984,991;, + 3;964,967,991;, + 3;965,992,3822;, + 3;992,995,3822;, + 3;995,992,994;, + 3;966,993,3819;, + 3;993,966,996;, + 3;967,994,992;, + 3;994,967,997;, + 3;968,996,966;, + 3;996,968,3823;, + 3;990,997,967;, + 3;997,990,3824;, + 3;994,1000,995;, + 3;1000,994,999;, + 3;996,998,993;, + 3;998,996,1001;, + 3;3823,1001,996;, + 3;1001,3823,3825;, + 3;3826,1002,3827;, + 3;3828,3824,3829;, + 3;997,999,994;, + 3;999,997,3828;, + 3;999,1005,1000;, + 3;1005,999,1004;, + 3;1001,1003,998;, + 3;1003,1001,1006;, + 3;3825,1006,1001;, + 3;1006,3825,3830;, + 3;3829,1007,3828;, + 3;1007,3829,3831;, + 3;3828,1004,999;, + 3;1004,3828,1007;, + 3;1007,1005,1004;, + 3;3830,1003,1006;, + 3;3831,1005,1007;, + 3;974,955,1270;, + 3;971,1008,956;, + 3;971,956,1009;, + 3;972,974,1010;, + 3;3832,955,1011;, + 3;958,973,1012;, + 3;1016,1015,970;, + 3;958,1016,970;, + 3;1017,1016,958;, + 3;1012,1017,958;, + 3;1018,1017,1012;, + 3;985,1018,1012;, + 3;1019,3833,3834;, + 3;960,1019,3834;, + 3;1020,1019,960;, + 3;979,1020,960;, + 3;3835,1020,979;, + 3;3836,3835,979;, + 3;1022,1021,1015;, + 3;1016,1022,1015;, + 3;1023,1022,1016;, + 3;1017,1023,1016;, + 3;1024,1023,1017;, + 3;1018,1024,1017;, + 3;1025,3837,3833;, + 3;1019,1025,3833;, + 3;1026,1025,1019;, + 3;1020,1026,1019;, + 3;3838,1026,1020;, + 3;3835,3838,1020;, + 3;1028,1027,1021;, + 3;1022,1028,1021;, + 3;1029,1028,1022;, + 3;1023,1029,1022;, + 3;1030,1029,1023;, + 3;1024,1030,1023;, + 3;1031,3839,3837;, + 3;1025,1031,3837;, + 3;1032,1031,1025;, + 3;1026,1032,1025;, + 3;3840,1032,1026;, + 3;3838,3840,1026;, + 3;1034,1033,1027;, + 3;1028,1034,1027;, + 3;1035,1034,1028;, + 3;1029,1035,1028;, + 3;1036,1035,1029;, + 3;1030,1036,1029;, + 3;1037,3841,3839;, + 3;1031,1037,3839;, + 3;1038,1037,1031;, + 3;1032,1038,1031;, + 3;3842,1038,1032;, + 3;3840,3842,1032;, + 3;1040,1039,1033;, + 3;1034,1040,1033;, + 3;1041,1040,1034;, + 3;1035,1041,1034;, + 3;1042,1041,1035;, + 3;1036,1042,1035;, + 3;1043,3843,3841;, + 3;1037,1043,3841;, + 3;1044,1043,1037;, + 3;1038,1044,1037;, + 3;3844,1044,1038;, + 3;3842,3844,1038;, + 3;1046,1045,1039;, + 3;1040,1046,1039;, + 3;1047,1046,1040;, + 3;1041,1047,1040;, + 3;1048,1047,1041;, + 3;1042,1048,1041;, + 3;1049,3845,3843;, + 3;1043,1049,3843;, + 3;1050,1049,1043;, + 3;1044,1050,1043;, + 3;3846,1050,1044;, + 3;3844,3846,1044;, + 3;1052,1051,1045;, + 3;1046,1052,1045;, + 3;1053,1052,1046;, + 3;1047,1053,1046;, + 3;1054,1053,1047;, + 3;1048,1054,1047;, + 3;1055,3847,3845;, + 3;1049,1055,3845;, + 3;1056,1055,1049;, + 3;1050,1056,1049;, + 3;3848,1056,1050;, + 3;3846,3848,1050;, + 3;1058,1057,1051;, + 3;1052,1058,1051;, + 3;1059,1058,1052;, + 3;1053,1059,1052;, + 3;1060,1059,1053;, + 3;1054,1060,1053;, + 3;1061,3849,3847;, + 3;1055,1061,3847;, + 3;1062,1061,1055;, + 3;1056,1062,1055;, + 3;3850,1062,1056;, + 3;3848,3850,1056;, + 3;1064,1063,1057;, + 3;1058,1064,1057;, + 3;1065,1064,1058;, + 3;1059,1065,1058;, + 3;1066,1065,1059;, + 3;1060,1066,1059;, + 3;1067,3851,3849;, + 3;1061,1067,3849;, + 3;1068,1067,1061;, + 3;1062,1068,1061;, + 3;3852,1068,1062;, + 3;3850,3852,1062;, + 3;1070,1069,1063;, + 3;1064,1070,1063;, + 3;1071,1070,1064;, + 3;1065,1071,1064;, + 3;1072,1071,1065;, + 3;1066,1072,1065;, + 3;1073,3853,3851;, + 3;1067,1073,3851;, + 3;1074,1073,1067;, + 3;1068,1074,1067;, + 3;3854,1074,1068;, + 3;3852,3854,1068;, + 3;1070,1075,1069;, + 3;1071,1076,1070;, + 3;1075,1070,1076;, + 3;1072,1076,1071;, + 3;1073,3855,3853;, + 3;1074,3856,1073;, + 3;3855,1073,3856;, + 3;3854,3856,1074;, + 3;1078,1077,969;, + 3;971,1078,969;, + 3;1079,1078,971;, + 3;1009,1079,971;, + 3;1080,1079,1009;, + 3;970,1080,1009;, + 3;1081,3857,3836;, + 3;978,1081,3836;, + 3;1082,1081,978;, + 3;1013,1082,978;, + 3;3858,1082,1013;, + 3;3859,3858,1013;, + 3;1084,1083,1077;, + 3;1078,1084,1077;, + 3;1085,1084,1078;, + 3;1079,1085,1078;, + 3;1086,1085,1079;, + 3;1080,1086,1079;, + 3;1087,3860,3857;, + 3;1081,1087,3857;, + 3;1088,1087,1081;, + 3;1082,1088,1081;, + 3;3861,1088,1082;, + 3;3858,3861,1082;, + 3;1090,1089,1083;, + 3;1084,1090,1083;, + 3;1091,1090,1084;, + 3;1085,1091,1084;, + 3;1092,1091,1085;, + 3;1086,1092,1085;, + 3;1093,3862,3860;, + 3;1087,1093,3860;, + 3;1094,1093,1087;, + 3;1088,1094,1087;, + 3;3863,1094,1088;, + 3;3861,3863,1088;, + 3;1096,1095,1089;, + 3;1090,1096,1089;, + 3;1097,1096,1090;, + 3;1091,1097,1090;, + 3;1098,1097,1091;, + 3;1092,1098,1091;, + 3;1099,3864,3862;, + 3;1093,1099,3862;, + 3;1100,1099,1093;, + 3;1094,1100,1093;, + 3;3865,1100,1094;, + 3;3863,3865,1094;, + 3;1102,1101,1095;, + 3;1096,1102,1095;, + 3;1103,1102,1096;, + 3;1097,1103,1096;, + 3;1104,1103,1097;, + 3;1098,1104,1097;, + 3;1105,3866,3864;, + 3;1099,1105,3864;, + 3;1106,1105,1099;, + 3;1100,1106,1099;, + 3;3867,1106,1100;, + 3;3865,3867,1100;, + 3;1108,1107,1101;, + 3;1102,1108,1101;, + 3;1109,1108,1102;, + 3;1103,1109,1102;, + 3;1110,1109,1103;, + 3;1104,1110,1103;, + 3;1111,3868,3866;, + 3;1105,1111,3866;, + 3;1112,1111,1105;, + 3;1106,1112,1105;, + 3;3869,1112,1106;, + 3;3867,3869,1106;, + 3;1114,1113,1107;, + 3;1108,1114,1107;, + 3;1115,1114,1108;, + 3;1109,1115,1108;, + 3;1116,1115,1109;, + 3;1110,1116,1109;, + 3;1117,3870,3868;, + 3;1111,1117,3868;, + 3;1118,1117,1111;, + 3;1112,1118,1111;, + 3;3871,1118,1112;, + 3;3869,3871,1112;, + 3;1120,1119,1113;, + 3;1114,1120,1113;, + 3;1121,1120,1114;, + 3;1115,1121,1114;, + 3;1122,1121,1115;, + 3;1116,1122,1115;, + 3;1123,3872,3870;, + 3;1117,1123,3870;, + 3;1124,1123,1117;, + 3;1118,1124,1117;, + 3;3873,1124,1118;, + 3;3871,3873,1118;, + 3;1126,1125,1119;, + 3;1120,1126,1119;, + 3;1127,1126,1120;, + 3;1121,1127,1120;, + 3;1128,1127,1121;, + 3;1122,1128,1121;, + 3;1129,3874,3872;, + 3;1123,1129,3872;, + 3;1130,1129,1123;, + 3;1124,1130,1123;, + 3;3875,1130,1124;, + 3;3873,3875,1124;, + 3;1132,1131,1125;, + 3;1126,1132,1125;, + 3;1133,1132,1126;, + 3;1127,1133,1126;, + 3;1134,1133,1127;, + 3;1128,1134,1127;, + 3;1135,3876,3874;, + 3;1129,1135,3874;, + 3;1136,1135,1129;, + 3;1130,1136,1129;, + 3;3877,1136,1130;, + 3;3875,3877,1130;, + 3;1132,1137,1131;, + 3;1133,1138,1132;, + 3;1137,1132,1138;, + 3;1134,1138,1133;, + 3;1135,3878,3876;, + 3;1136,3879,1135;, + 3;3878,1135,3879;, + 3;3877,3879,1136;, + 3;1140,1139,972;, + 3;1010,1140,972;, + 3;1141,1140,1010;, + 3;976,1141,1010;, + 3;1142,1141,976;, + 3;969,1142,976;, + 3;1143,3880,3859;, + 3;1014,1143,3859;, + 3;1144,1143,1014;, + 3;977,1144,1014;, + 3;3881,1144,977;, + 3;3882,3881,977;, + 3;1146,1145,1139;, + 3;1140,1146,1139;, + 3;1147,1146,1140;, + 3;1141,1147,1140;, + 3;1148,1147,1141;, + 3;1142,1148,1141;, + 3;1149,3883,3880;, + 3;1143,1149,3880;, + 3;1150,1149,1143;, + 3;1144,1150,1143;, + 3;3884,1150,1144;, + 3;3881,3884,1144;, + 3;1152,1151,1145;, + 3;1146,1152,1145;, + 3;1153,1152,1146;, + 3;1147,1153,1146;, + 3;1154,1153,1147;, + 3;1148,1154,1147;, + 3;1155,3885,3883;, + 3;1149,1155,3883;, + 3;1156,1155,1149;, + 3;1150,1156,1149;, + 3;3886,1156,1150;, + 3;3884,3886,1150;, + 3;1158,1157,1151;, + 3;1152,1158,1151;, + 3;1159,1158,1152;, + 3;1153,1159,1152;, + 3;1160,1159,1153;, + 3;1154,1160,1153;, + 3;1161,3887,3885;, + 3;1155,1161,3885;, + 3;1162,1161,1155;, + 3;1156,1162,1155;, + 3;3888,1162,1156;, + 3;3886,3888,1156;, + 3;1164,1163,1157;, + 3;1158,1164,1157;, + 3;1165,1164,1158;, + 3;1159,1165,1158;, + 3;1166,1165,1159;, + 3;1160,1166,1159;, + 3;1167,3889,3887;, + 3;1161,1167,3887;, + 3;1168,1167,1161;, + 3;1162,1168,1161;, + 3;3890,1168,1162;, + 3;3888,3890,1162;, + 3;1170,1169,1163;, + 3;1164,1170,1163;, + 3;1171,1170,1164;, + 3;1165,1171,1164;, + 3;1172,1171,1165;, + 3;1166,1172,1165;, + 3;1173,3891,3889;, + 3;1167,1173,3889;, + 3;1174,1173,1167;, + 3;1168,1174,1167;, + 3;3892,1174,1168;, + 3;3890,3892,1168;, + 3;1176,1175,1169;, + 3;1170,1176,1169;, + 3;1177,1176,1170;, + 3;1171,1177,1170;, + 3;1178,1177,1171;, + 3;1172,1178,1171;, + 3;1179,3893,3891;, + 3;1173,1179,3891;, + 3;1180,1179,1173;, + 3;1174,1180,1173;, + 3;3894,1180,1174;, + 3;3892,3894,1174;, + 3;1182,1181,1175;, + 3;1176,1182,1175;, + 3;1183,1182,1176;, + 3;1177,1183,1176;, + 3;1184,1183,1177;, + 3;1178,1184,1177;, + 3;1185,3895,3893;, + 3;1179,1185,3893;, + 3;1186,1185,1179;, + 3;1180,1186,1179;, + 3;3896,1186,1180;, + 3;3894,3896,1180;, + 3;1188,1187,1181;, + 3;1182,1188,1181;, + 3;1189,1188,1182;, + 3;1183,1189,1182;, + 3;1190,1189,1183;, + 3;1184,1190,1183;, + 3;1191,3897,3895;, + 3;1185,1191,3895;, + 3;1192,1191,1185;, + 3;1186,1192,1185;, + 3;3898,1192,1186;, + 3;3896,3898,1186;, + 3;1194,1193,1187;, + 3;1188,1194,1187;, + 3;1195,1194,1188;, + 3;1189,1195,1188;, + 3;1196,1195,1189;, + 3;1190,1196,1189;, + 3;1197,3899,3897;, + 3;1191,1197,3897;, + 3;1198,1197,1191;, + 3;1192,1198,1191;, + 3;3900,1198,1192;, + 3;3898,3900,1192;, + 3;1194,1199,1193;, + 3;1195,1200,1194;, + 3;1199,1194,1200;, + 3;1196,1200,1195;, + 3;1197,3901,3899;, + 3;1198,3902,1197;, + 3;3901,1197,3902;, + 3;3900,3902,1198;, + 3;1202,1201,3832;, + 3;1011,1202,3832;, + 3;1203,1202,1011;, + 3;975,1203,1011;, + 3;1204,1203,975;, + 3;972,1204,975;, + 3;1205,3903,3882;, + 3;980,1205,3882;, + 3;1206,1205,980;, + 3;957,1206,980;, + 3;3904,1206,957;, + 3;962,3904,957;, + 3;1208,1207,1201;, + 3;1202,1208,1201;, + 3;1209,1208,1202;, + 3;1203,1209,1202;, + 3;1210,1209,1203;, + 3;1204,1210,1203;, + 3;1211,3905,3903;, + 3;1205,1211,3903;, + 3;1212,1211,1205;, + 3;1206,1212,1205;, + 3;3906,1212,1206;, + 3;3904,3906,1206;, + 3;1214,1213,1207;, + 3;1208,1214,1207;, + 3;1215,1214,1208;, + 3;1209,1215,1208;, + 3;1216,1215,1209;, + 3;1210,1216,1209;, + 3;1217,3907,3905;, + 3;1211,1217,3905;, + 3;1218,1217,1211;, + 3;1212,1218,1211;, + 3;3908,1218,1212;, + 3;3906,3908,1212;, + 3;1220,1219,1213;, + 3;1214,1220,1213;, + 3;1221,1220,1214;, + 3;1215,1221,1214;, + 3;1222,1221,1215;, + 3;1216,1222,1215;, + 3;1223,3909,3907;, + 3;1217,1223,3907;, + 3;1224,1223,1217;, + 3;1218,1224,1217;, + 3;3910,1224,1218;, + 3;3908,3910,1218;, + 3;1226,1225,1219;, + 3;1220,1226,1219;, + 3;1227,1226,1220;, + 3;1221,1227,1220;, + 3;1228,1227,1221;, + 3;1222,1228,1221;, + 3;1229,3911,3909;, + 3;1223,1229,3909;, + 3;1230,1229,1223;, + 3;1224,1230,1223;, + 3;3912,1230,1224;, + 3;3910,3912,1224;, + 3;1232,1231,1225;, + 3;1226,1232,1225;, + 3;1233,1232,1226;, + 3;1227,1233,1226;, + 3;1234,1233,1227;, + 3;1228,1234,1227;, + 3;1235,3913,3911;, + 3;1229,1235,3911;, + 3;1236,1235,1229;, + 3;1230,1236,1229;, + 3;3914,1236,1230;, + 3;3912,3914,1230;, + 3;1238,1237,1231;, + 3;1232,1238,1231;, + 3;1239,1238,1232;, + 3;1233,1239,1232;, + 3;1240,1239,1233;, + 3;1234,1240,1233;, + 3;1241,3915,3913;, + 3;1235,1241,3913;, + 3;1242,1241,1235;, + 3;1236,1242,1235;, + 3;3916,1242,1236;, + 3;3914,3916,1236;, + 3;1244,1243,1237;, + 3;1238,1244,1237;, + 3;1245,1244,1238;, + 3;1239,1245,1238;, + 3;1246,1245,1239;, + 3;1240,1246,1239;, + 3;1247,3917,3915;, + 3;1241,1247,3915;, + 3;1248,1247,1241;, + 3;1242,1248,1241;, + 3;3918,1248,1242;, + 3;3916,3918,1242;, + 3;1250,1249,3918;, + 3;1244,3919,1243;, + 3;1251,3919,1244;, + 3;1245,1251,1244;, + 3;1252,1251,1245;, + 3;1246,1252,1245;, + 3;1253,3920,3917;, + 3;1247,1253,3917;, + 3;1254,1253,1247;, + 3;1248,1254,1247;, + 3;1249,1254,1248;, + 3;3918,1249,1248;, + 3;1256,1255,3921;, + 3;3919,1256,3921;, + 3;1257,1256,3919;, + 3;1251,1257,3919;, + 3;1258,1257,1251;, + 3;1252,1258,1251;, + 3;1259,3922,3920;, + 3;1253,1259,3920;, + 3;1260,1259,1253;, + 3;1254,1260,1253;, + 3;3923,1260,1254;, + 3;1249,3923,1254;, + 3;1256,1261,1255;, + 3;1257,1262,1256;, + 3;1261,1256,1262;, + 3;1258,1262,1257;, + 3;1259,3924,3922;, + 3;1260,3925,1259;, + 3;3924,1259,3925;, + 3;3923,3925,1260;, + 3;3814,963,1263;, + 3;1263,973,956;, + 3;981,983,959;, + 3;983,981,1269;, + 3;3859,1264,1014;, + 3;1264,3859,1013;, + 3;3836,1265,978;, + 3;3836,979,1265;, + 3;3882,1266,980;, + 3;1266,3882,977;, + 3;1013,1265,1264;, + 3;1265,1013,978;, + 3;1014,1266,977;, + 3;1266,1014,1264;, + 3;1265,979,960;, + 3;957,981,3816;, + 3;3926,960,3834;, + 3;980,1266,1267;, + 3;1266,1269,1267;, + 3;983,1269,987;, + 3;1267,1269,981;, + 3;1269,1264,987;, + 3;1264,1269,1266;, + 3;1264,1265,987;, + 3;1265,986,987;, + 3;986,1265,960;, + 3;986,960,3926;, + 3;986,3926,3821;, + 3;1270,3815,1263;, + 3;974,1270,1008;, + 3;1277,1282,1271;, + 3;1271,3803,948;, + 3;1279,1278,1272;, + 3;1272,3807,3927;, + 3;949,3804,1273;, + 3;1284,3928,1275;, + 3;3808,3805,1274;, + 3;1276,3929,3930;, + 3;3928,1276,1275;, + 3;3928,3929,1276;, + 3;1274,949,1275;, + 3;1278,1277,948;, + 3;1272,1278,948;, + 3;1272,1280,1279;, + 3;1272,3927,1280;, + 3;1282,1281,947;, + 3;1271,1282,947;, + 3;1271,948,1277;, + 3;3810,1284,1283;, + 3;3810,3928,1284;, + 3;3806,3809,1283;, + 3;1273,3806,1283;, + 3;952,1282,1277;, + 3;952,3931,1282;, + 3;954,1278,1279;, + 3;954,952,1278;, + 3;1284,1275,949;, + 3;1273,1284,949;, + 3;1276,3930,950;, + 3;1274,1276,950;, + 3;1286,943,1285;, + 3;1286,850,1291;, + 3;1287,3759,3757;, + 3;1292,1287,3757;, + 3;1288,3798,1286;, + 3;1286,3798,850;, + 3;855,3932,1287;, + 3;855,945,3932;, + 3;849,1289,943;, + 3;1293,852,1289;, + 3;854,1290,860;, + 3;889,853,1290;, + 3;1286,1291,943;, + 3;849,943,1291;, + 3;855,1287,1292;, + 3;855,1292,3758;, + 3;856,852,1293;, + 3;1293,854,856;, + 3;3933,1286,1285;, + 3;946,3799,851;, + 3;946,3756,3801;, + 3;851,3800,943;, + 3;943,3800,1285;, + 3;3934,1286,3933;, + 3;3934,1288,1286;, + 3;1287,3932,3935;, + 3;1287,3935,3759;, + 3;1294,1295,1736;, + 3;1388,1296,1297;, + 3;1294,1389,1735;, + 3;1734,1738,1299;, + 3;1299,1389,1734;, + 3;1304,1390,1333;, + 3;1300,1332,1306;, + 3;1391,3936,1301;, + 3;1737,3937,3938;, + 3;3938,3939,3940;, + 3;1297,1296,1391;, + 3;1302,1294,1334;, + 3;1303,1295,1302;, + 3;1295,1294,1302;, + 3;1298,1735,1305;, + 3;3941,3937,1306;, + 3;3937,1300,1306;, + 3;1332,1390,1304;, + 3;1320,1335,1336;, + 3;1338,1307,1337;, + 3;1339,1340,1314;, + 3;1342,1308,1341;, + 3;1343,1344,1321;, + 3;1345,1337,1307;, + 3;1347,1319,1346;, + 3;1343,1348,1322;, + 3;1313,1335,1349;, + 3;1339,1350,1309;, + 3;1350,1349,1309;, + 3;1341,1340,1317;, + 3;1312,1351,1347;, + 3;3942,1336,3943;, + 3;1344,1310,1351;, + 3;1348,3944,3945;, + 3;1346,1319,1345;, + 3;3943,1313,1325;, + 3;1325,1324,3943;, + 3;1312,1323,1327;, + 3;1327,1326,1312;, + 3;3944,1321,1329;, + 3;1329,1328,3944;, + 3;1311,1314,1331;, + 3;1331,1330,1311;, + 3;1313,1311,1325;, + 3;1330,1325,1311;, + 3;1314,1308,3946;, + 3;3946,1331,1314;, + 3;1321,1312,1326;, + 3;1326,1329,1321;, + 3;1323,1307,3947;, + 3;3947,1327,1323;, + 3;1315,1316,3948;, + 3;3948,3949,1315;, + 3;1317,1309,3950;, + 3;3950,3951,1317;, + 3;1318,1317,3951;, + 3;3951,3952,1318;, + 3;1310,1322,3953;, + 3;3953,3954,1310;, + 3;1316,1319,3955;, + 3;3955,3948,1316;, + 3;1309,1320,3956;, + 3;3956,3950,1309;, + 3;1319,1310,3954;, + 3;3954,3955,1319;, + 3;1320,3957,3958;, + 3;3958,3956,1320;, + 3;1322,3959,3960;, + 3;3960,3953,1322;, + 3;1335,1313,1336;, + 3;1313,3943,1336;, + 3;1337,1316,1338;, + 3;1316,1315,1338;, + 3;1339,1309,1340;, + 3;1309,1317,1340;, + 3;1341,1317,1342;, + 3;1317,1318,1342;, + 3;1343,1322,1344;, + 3;1322,1310,1344;, + 3;1345,1319,1337;, + 3;1319,1316,1337;, + 3;1346,1323,1347;, + 3;1323,1312,1347;, + 3;1343,1321,1348;, + 3;1321,3944,1348;, + 3;1335,1320,1349;, + 3;1320,1309,1349;, + 3;1339,1314,1350;, + 3;1314,1311,1350;, + 3;1350,1311,1349;, + 3;1311,1313,1349;, + 3;1341,1308,1340;, + 3;1308,1314,1340;, + 3;1351,1310,1347;, + 3;1310,1319,1347;, + 3;3942,3957,1336;, + 3;3957,1320,1336;, + 3;1351,1312,1344;, + 3;1312,1321,1344;, + 3;3945,3959,1348;, + 3;3959,1322,1348;, + 3;1345,1307,1346;, + 3;1307,1323,1346;, + 3;1334,1294,1735;, + 3;3961,1295,1303;, + 3;1300,1390,1332;, + 3;1366,1353,1384;, + 3;1387,3962,1367;, + 3;1368,1369,1355;, + 3;1352,1370,1371;, + 3;1371,1356,1372;, + 3;1374,1360,1373;, + 3;3963,1358,1364;, + 3;1376,1358,1375;, + 3;1386,1353,1365;, + 3;1376,3964,1377;, + 3;1374,1353,1378;, + 3;1361,3965,1363;, + 3;1362,1358,3966;, + 3;1380,1359,1379;, + 3;1361,1381,1380;, + 3;1382,1383,1360;, + 3;3967,3968,3969;, + 3;3970,1364,1354;, + 3;1357,3967,3971;, + 3;1361,1362,3966;, + 3;1379,1359,1375;, + 3;3968,3967,1357;, + 3;1381,3972,3973;, + 3;3963,3966,1358;, + 3;1377,3964,3974;, + 3;1373,1360,1383;, + 3;1385,1384,1353;, + 3;1352,1385,1387;, + 3;1372,1356,1378;, + 3;1367,3962,3975;, + 3;1370,1368,1355;, + 3;1368,1367,1369;, + 3;1367,3975,1369;, + 3;1370,1355,1371;, + 3;1355,1356,1371;, + 3;1372,1366,1371;, + 3;1366,1352,1371;, + 3;1373,1365,1374;, + 3;1365,1353,1374;, + 3;1375,1359,1376;, + 3;1359,3964,1376;, + 3;1377,1364,1376;, + 3;1364,1358,1376;, + 3;1378,1356,1374;, + 3;1356,1360,1374;, + 3;1379,1362,1380;, + 3;1362,1361,1380;, + 3;1381,3973,1380;, + 3;3973,1359,1380;, + 3;1382,3968,1383;, + 3;3968,1357,1383;, + 3;1375,1358,1379;, + 3;1358,1362,1379;, + 3;1381,1361,3972;, + 3;1361,1363,3972;, + 3;3974,1354,1377;, + 3;1354,1364,1377;, + 3;1383,1357,1373;, + 3;1357,1365,1373;, + 3;1378,1353,1372;, + 3;1353,1366,1372;, + 3;1370,1352,1368;, + 3;1352,1367,1368;, + 3;1357,3971,1365;, + 3;1325,1324,1330;, + 3;3962,3976,3975;, + 3;1385,3977,3962;, + 3;1386,3971,1385;, + 3;1352,1366,1384;, + 3;1384,1385,1352;, + 3;1385,3971,3977;, + 3;3971,1386,1365;, + 3;1353,1386,1385;, + 3;1352,1387,1367;, + 3;1387,1385,3962;, + 3;3970,3963,1364;, + 3;3965,1361,3966;, + 3;1734,1388,1297;, + 3;1294,1734,1389;, + 3;1299,1735,1389;, + 3;3978,1295,3961;, + 3;3979,1296,3980;, + 3;1297,1391,1301;, + 3;1391,3979,3981;, + 3;1716,3982,1392;, + 3;3982,1716,3983;, + 3;3984,3985,1394;, + 3;1718,3986,3984;, + 3;3987,3983,1393;, + 3;1393,1717,3987;, + 3;1719,3988,1395;, + 3;1719,1394,3985;, + 3;1720,1719,1721;, + 3;1723,1722,1397;, + 3;1724,1399,1725;, + 3;1727,1726,1396;, + 3;1728,1718,1729;, + 3;1728,3989,3990;, + 3;1453,1401,1715;, + 3;1400,3991,3992;, + 3;1426,1712,1402;, + 3;1415,1418,1454;, + 3;3993,1398,1404;, + 3;1713,1433,1408;, + 3;3994,3991,1708;, + 3;1404,1427,3993;, + 3;1418,1415,1403;, + 3;1404,1398,1429;, + 3;3995,1402,1407;, + 3;1456,1419,1400;, + 3;1429,1398,3996;, + 3;1429,3996,1410;, + 3;1436,1409,1406;, + 3;1708,1457,1408;, + 3;1408,3997,3994;, + 3;1434,1409,1435;, + 3;3998,1411,3999;, + 3;1436,1437,1412;, + 3;1437,1436,1410;, + 3;3997,1408,1411;, + 3;1411,1413,3997;, + 3;1406,1409,1431;, + 3;1409,4000,1431;, + 3;1421,1453,1419;, + 3;1454,1418,1401;, + 3;1414,1416,1453;, + 3;1420,1417,1419;, + 3;1708,1418,1457;, + 3;1715,1401,1708;, + 3;1400,1715,3991;, + 3;1414,1453,1421;, + 3;1456,1420,1419;, + 3;1455,1421,1419;, + 3;3995,1427,1426;, + 3;1425,1402,1712;, + 3;1404,1426,1427;, + 3;3995,3993,1427;, + 3;1406,1429,1436;, + 3;1404,1429,1428;, + 3;1428,1429,1406;, + 3;1457,1430,1408;, + 3;1408,1430,1713;, + 3;1428,1406,1431;, + 3;1428,1431,1432;, + 3;3999,1408,1433;, + 3;1408,3999,1411;, + 3;1409,1434,4000;, + 3;1412,1435,1409;, + 3;1410,1436,1429;, + 3;1409,1436,1412;, + 3;1410,4001,1437;, + 3;1437,4001,1440;, + 3;1440,1439,1437;, + 3;1411,3998,1438;, + 3;1438,1441,1411;, + 3;1412,1437,1439;, + 3;1439,1442,1412;, + 3;1413,1411,1441;, + 3;1441,4002,1413;, + 3;1435,1412,1442;, + 3;1442,4003,1435;, + 3;1439,1440,1445;, + 3;1445,1444,1439;, + 3;1441,1438,1443;, + 3;1443,1446,1441;, + 3;4002,1441,1446;, + 3;1446,4004,4002;, + 3;4003,1442,1447;, + 3;1447,4005,4003;, + 3;1442,1439,1444;, + 3;1444,1447,1442;, + 3;1444,1445,1450;, + 3;1450,1449,1444;, + 3;1446,1443,1448;, + 3;1448,1451,1446;, + 3;4004,1446,1451;, + 3;1451,4006,4004;, + 3;4005,1447,1452;, + 3;1452,4007,4005;, + 3;1447,1444,1449;, + 3;1449,1452,1447;, + 3;1452,1449,1450;, + 3;4006,1451,1448;, + 3;4007,1452,1450;, + 3;1419,1715,1400;, + 3;1416,1401,1453;, + 3;1416,1454,1401;, + 3;1417,1455,1419;, + 3;4008,1456,1400;, + 3;1403,1457,1418;, + 3;1461,4009,1460;, + 3;1403,1415,4010;, + 3;1462,1403,4010;, + 3;1457,1403,1462;, + 3;1463,1457,1462;, + 3;1430,1457,1463;, + 3;1464,4011,4012;, + 3;1405,4011,1464;, + 3;1465,1405,1464;, + 3;1424,1405,1465;, + 3;1460,1424,1465;, + 3;4009,1424,1460;, + 3;1467,4013,1466;, + 3;4010,4013,1467;, + 3;1468,4010,1467;, + 3;1462,4010,1468;, + 3;1469,1462,1468;, + 3;1463,1462,1469;, + 3;1470,4012,4014;, + 3;1464,4012,1470;, + 3;1471,1464,1470;, + 3;1465,1464,1471;, + 3;4015,1465,1471;, + 3;1460,1465,4015;, + 3;1473,1466,1472;, + 3;1467,1466,1473;, + 3;1474,1467,1473;, + 3;1468,1467,1474;, + 3;1475,1468,1474;, + 3;1469,1468,1475;, + 3;1476,4014,4016;, + 3;1470,4014,1476;, + 3;1477,1470,1476;, + 3;1471,1470,1477;, + 3;4017,1471,1477;, + 3;4015,1471,4017;, + 3;1479,1472,1478;, + 3;1473,1472,1479;, + 3;1480,1473,1479;, + 3;1474,1473,1480;, + 3;1481,1474,1480;, + 3;1475,1474,1481;, + 3;1482,4016,4018;, + 3;1476,4016,1482;, + 3;1483,1476,1482;, + 3;1477,1476,1483;, + 3;4019,1477,1483;, + 3;4017,1477,4019;, + 3;1485,1478,1484;, + 3;1479,1478,1485;, + 3;1486,1479,1485;, + 3;1480,1479,1486;, + 3;1487,1480,1486;, + 3;1481,1480,1487;, + 3;1488,4018,4020;, + 3;1482,4018,1488;, + 3;1489,1482,1488;, + 3;1483,1482,1489;, + 3;4021,1483,1489;, + 3;4019,1483,4021;, + 3;1491,1484,1490;, + 3;1485,1484,1491;, + 3;1492,1485,1491;, + 3;1486,1485,1492;, + 3;1493,1486,1492;, + 3;1487,1486,1493;, + 3;1494,4020,4022;, + 3;1488,4020,1494;, + 3;1495,1488,1494;, + 3;1489,1488,1495;, + 3;4023,1489,1495;, + 3;4021,1489,4023;, + 3;1497,1490,1496;, + 3;1491,1490,1497;, + 3;1498,1491,1497;, + 3;1492,1491,1498;, + 3;1499,1492,1498;, + 3;1493,1492,1499;, + 3;1500,4022,4024;, + 3;1494,4022,1500;, + 3;1501,1494,1500;, + 3;1495,1494,1501;, + 3;4025,1495,1501;, + 3;4023,1495,4025;, + 3;1503,1496,1502;, + 3;1497,1496,1503;, + 3;1504,1497,1503;, + 3;1498,1497,1504;, + 3;1505,1498,1504;, + 3;1499,1498,1505;, + 3;1506,4024,4026;, + 3;1500,4024,1506;, + 3;1507,1500,1506;, + 3;1501,1500,1507;, + 3;4027,1501,1507;, + 3;4025,1501,4027;, + 3;1509,1502,1508;, + 3;1503,1502,1509;, + 3;1510,1503,1509;, + 3;1504,1503,1510;, + 3;1511,1504,1510;, + 3;1505,1504,1511;, + 3;1512,4026,4028;, + 3;1506,4026,1512;, + 3;1513,1506,1512;, + 3;1507,1506,1513;, + 3;4029,1507,1513;, + 3;4027,1507,4029;, + 3;1515,1508,1514;, + 3;1509,1508,1515;, + 3;1516,1509,1515;, + 3;1510,1509,1516;, + 3;1517,1510,1516;, + 3;1511,1510,1517;, + 3;1518,4028,4030;, + 3;1512,4028,1518;, + 3;1519,1512,1518;, + 3;1513,1512,1519;, + 3;4031,1513,1519;, + 3;4029,1513,4031;, + 3;1515,1514,1520;, + 3;1516,1515,1521;, + 3;1520,1521,1515;, + 3;1517,1516,1521;, + 3;1518,4030,4032;, + 3;1519,1518,4033;, + 3;4032,4033,1518;, + 3;4031,1519,4033;, + 3;1523,1414,1522;, + 3;1416,1414,1523;, + 3;1524,1416,1523;, + 3;1454,1416,1524;, + 3;1525,1454,1524;, + 3;1415,1454,1525;, + 3;1526,4009,4034;, + 3;1423,4009,1526;, + 3;1527,1423,1526;, + 3;1458,1423,1527;, + 3;4035,1458,1527;, + 3;4036,1458,4035;, + 3;1529,1522,1528;, + 3;1523,1522,1529;, + 3;1530,1523,1529;, + 3;1524,1523,1530;, + 3;1531,1524,1530;, + 3;1525,1524,1531;, + 3;1532,4034,4037;, + 3;1526,4034,1532;, + 3;1533,1526,1532;, + 3;1527,1526,1533;, + 3;4038,1527,1533;, + 3;4035,1527,4038;, + 3;1535,1528,1534;, + 3;1529,1528,1535;, + 3;1536,1529,1535;, + 3;1530,1529,1536;, + 3;1537,1530,1536;, + 3;1531,1530,1537;, + 3;1538,4037,4039;, + 3;1532,4037,1538;, + 3;1539,1532,1538;, + 3;1533,1532,1539;, + 3;4040,1533,1539;, + 3;4038,1533,4040;, + 3;1541,1534,1540;, + 3;1535,1534,1541;, + 3;1542,1535,1541;, + 3;1536,1535,1542;, + 3;1543,1536,1542;, + 3;1537,1536,1543;, + 3;1544,4039,4041;, + 3;1538,4039,1544;, + 3;1545,1538,1544;, + 3;1539,1538,1545;, + 3;4042,1539,1545;, + 3;4040,1539,4042;, + 3;1547,1540,1546;, + 3;1541,1540,1547;, + 3;1548,1541,1547;, + 3;1542,1541,1548;, + 3;1549,1542,1548;, + 3;1543,1542,1549;, + 3;1550,4041,4043;, + 3;1544,4041,1550;, + 3;1551,1544,1550;, + 3;1545,1544,1551;, + 3;4044,1545,1551;, + 3;4042,1545,4044;, + 3;1553,1546,1552;, + 3;1547,1546,1553;, + 3;1554,1547,1553;, + 3;1548,1547,1554;, + 3;1555,1548,1554;, + 3;1549,1548,1555;, + 3;1556,4043,4045;, + 3;1550,4043,1556;, + 3;1557,1550,1556;, + 3;1551,1550,1557;, + 3;4046,1551,1557;, + 3;4044,1551,4046;, + 3;1559,1552,1558;, + 3;1553,1552,1559;, + 3;1560,1553,1559;, + 3;1554,1553,1560;, + 3;1561,1554,1560;, + 3;1555,1554,1561;, + 3;1562,4045,4047;, + 3;1556,4045,1562;, + 3;1563,1556,1562;, + 3;1557,1556,1563;, + 3;4048,1557,1563;, + 3;4046,1557,4048;, + 3;1565,1558,1564;, + 3;1559,1558,1565;, + 3;1566,1559,1565;, + 3;1560,1559,1566;, + 3;1567,1560,1566;, + 3;1561,1560,1567;, + 3;1568,4047,4049;, + 3;1562,4047,1568;, + 3;1569,1562,1568;, + 3;1563,1562,1569;, + 3;4050,1563,1569;, + 3;4048,1563,4050;, + 3;1571,1564,1570;, + 3;1565,1564,1571;, + 3;1572,1565,1571;, + 3;1566,1565,1572;, + 3;1573,1566,1572;, + 3;1567,1566,1573;, + 3;1574,4049,4051;, + 3;1568,4049,1574;, + 3;1575,1568,1574;, + 3;1569,1568,1575;, + 3;4052,1569,1575;, + 3;4050,1569,4052;, + 3;1577,1570,1576;, + 3;1571,1570,1577;, + 3;1578,1571,1577;, + 3;1572,1571,1578;, + 3;1579,1572,1578;, + 3;1573,1572,1579;, + 3;1580,4051,4053;, + 3;1574,4051,1580;, + 3;1581,1574,1580;, + 3;1575,1574,1581;, + 3;4054,1575,1581;, + 3;4052,1575,4054;, + 3;1577,1576,1582;, + 3;1578,1577,1583;, + 3;1582,1583,1577;, + 3;1579,1578,1583;, + 3;1580,4053,4055;, + 3;1581,1580,4056;, + 3;4055,4056,1580;, + 3;4054,1581,4056;, + 3;1585,1417,1584;, + 3;1455,1417,1585;, + 3;1586,1455,1585;, + 3;1421,1455,1586;, + 3;1587,1421,1586;, + 3;1414,1421,1587;, + 3;1588,4036,4057;, + 3;1459,4036,1588;, + 3;1589,1459,1588;, + 3;1422,1459,1589;, + 3;4058,1422,1589;, + 3;4059,1422,4058;, + 3;1591,1584,1590;, + 3;1585,1584,1591;, + 3;1592,1585,1591;, + 3;1586,1585,1592;, + 3;1593,1586,1592;, + 3;1587,1586,1593;, + 3;1594,4057,4060;, + 3;1588,4057,1594;, + 3;1595,1588,1594;, + 3;1589,1588,1595;, + 3;4061,1589,1595;, + 3;4058,1589,4061;, + 3;1597,1590,1596;, + 3;1591,1590,1597;, + 3;1598,1591,1597;, + 3;1592,1591,1598;, + 3;1599,1592,1598;, + 3;1593,1592,1599;, + 3;1600,4060,4062;, + 3;1594,4060,1600;, + 3;1601,1594,1600;, + 3;1595,1594,1601;, + 3;4063,1595,1601;, + 3;4061,1595,4063;, + 3;1603,1596,1602;, + 3;1597,1596,1603;, + 3;1604,1597,1603;, + 3;1598,1597,1604;, + 3;1605,1598,1604;, + 3;1599,1598,1605;, + 3;1606,4062,4064;, + 3;1600,4062,1606;, + 3;1607,1600,1606;, + 3;1601,1600,1607;, + 3;4065,1601,1607;, + 3;4063,1601,4065;, + 3;1609,1602,1608;, + 3;1603,1602,1609;, + 3;1610,1603,1609;, + 3;1604,1603,1610;, + 3;1611,1604,1610;, + 3;1605,1604,1611;, + 3;1612,4064,4066;, + 3;1606,4064,1612;, + 3;1613,1606,1612;, + 3;1607,1606,1613;, + 3;4067,1607,1613;, + 3;4065,1607,4067;, + 3;1615,1608,1614;, + 3;1609,1608,1615;, + 3;1616,1609,1615;, + 3;1610,1609,1616;, + 3;1617,1610,1616;, + 3;1611,1610,1617;, + 3;1618,4066,4068;, + 3;1612,4066,1618;, + 3;1619,1612,1618;, + 3;1613,1612,1619;, + 3;4069,1613,1619;, + 3;4067,1613,4069;, + 3;1621,1614,1620;, + 3;1615,1614,1621;, + 3;1622,1615,1621;, + 3;1616,1615,1622;, + 3;1623,1616,1622;, + 3;1617,1616,1623;, + 3;1624,4068,4070;, + 3;1618,4068,1624;, + 3;1625,1618,1624;, + 3;1619,1618,1625;, + 3;4071,1619,1625;, + 3;4069,1619,4071;, + 3;1627,1620,1626;, + 3;1621,1620,1627;, + 3;1628,1621,1627;, + 3;1622,1621,1628;, + 3;1629,1622,1628;, + 3;1623,1622,1629;, + 3;1630,4070,4072;, + 3;1624,4070,1630;, + 3;1631,1624,1630;, + 3;1625,1624,1631;, + 3;4073,1625,1631;, + 3;4071,1625,4073;, + 3;1633,1626,1632;, + 3;1627,1626,1633;, + 3;1634,1627,1633;, + 3;1628,1627,1634;, + 3;1635,1628,1634;, + 3;1629,1628,1635;, + 3;1636,4072,4074;, + 3;1630,4072,1636;, + 3;1637,1630,1636;, + 3;1631,1630,1637;, + 3;4075,1631,1637;, + 3;4073,1631,4075;, + 3;1639,1632,1638;, + 3;1633,1632,1639;, + 3;1640,1633,1639;, + 3;1634,1633,1640;, + 3;1641,1634,1640;, + 3;1635,1634,1641;, + 3;1642,4074,4076;, + 3;1636,4074,1642;, + 3;1643,1636,1642;, + 3;1637,1636,1643;, + 3;4077,1637,1643;, + 3;4075,1637,4077;, + 3;1639,1638,1644;, + 3;1640,1639,1645;, + 3;1644,1645,1639;, + 3;1641,1640,1645;, + 3;1642,4076,4078;, + 3;1643,1642,4079;, + 3;4078,4079,1642;, + 3;4077,1643,4079;, + 3;1647,4008,1646;, + 3;1456,4008,1647;, + 3;1648,1456,1647;, + 3;1420,1456,1648;, + 3;1649,1420,1648;, + 3;1417,1420,1649;, + 3;1650,4059,4080;, + 3;1425,4059,1650;, + 3;1651,1425,1650;, + 3;1402,1425,1651;, + 3;4081,1402,1651;, + 3;1407,1402,4081;, + 3;1653,1646,1652;, + 3;1647,1646,1653;, + 3;1654,1647,1653;, + 3;1648,1647,1654;, + 3;1655,1648,1654;, + 3;1649,1648,1655;, + 3;1656,4080,4082;, + 3;1650,4080,1656;, + 3;1657,1650,1656;, + 3;1651,1650,1657;, + 3;4083,1651,1657;, + 3;4081,1651,4083;, + 3;1659,1652,1658;, + 3;1653,1652,1659;, + 3;1660,1653,1659;, + 3;1654,1653,1660;, + 3;1661,1654,1660;, + 3;1655,1654,1661;, + 3;1662,4082,4084;, + 3;1656,4082,1662;, + 3;1663,1656,1662;, + 3;1657,1656,1663;, + 3;4085,1657,1663;, + 3;4083,1657,4085;, + 3;1665,1658,1664;, + 3;1659,1658,1665;, + 3;1666,1659,1665;, + 3;1660,1659,1666;, + 3;1667,1660,1666;, + 3;1661,1660,1667;, + 3;1668,4084,4086;, + 3;1662,4084,1668;, + 3;1669,1662,1668;, + 3;1663,1662,1669;, + 3;4087,1663,1669;, + 3;4085,1663,4087;, + 3;1671,1664,1670;, + 3;1665,1664,1671;, + 3;1672,1665,1671;, + 3;1666,1665,1672;, + 3;1673,1666,1672;, + 3;1667,1666,1673;, + 3;1674,4086,4088;, + 3;1668,4086,1674;, + 3;1675,1668,1674;, + 3;1669,1668,1675;, + 3;4089,1669,1675;, + 3;4087,1669,4089;, + 3;1677,1670,1676;, + 3;1671,1670,1677;, + 3;1678,1671,1677;, + 3;1672,1671,1678;, + 3;1679,1672,1678;, + 3;1673,1672,1679;, + 3;1680,4088,4090;, + 3;1674,4088,1680;, + 3;1681,1674,1680;, + 3;1675,1674,1681;, + 3;4091,1675,1681;, + 3;4089,1675,4091;, + 3;1683,1676,1682;, + 3;1677,1676,1683;, + 3;1684,1677,1683;, + 3;1678,1677,1684;, + 3;1685,1678,1684;, + 3;1679,1678,1685;, + 3;1686,4090,4092;, + 3;1680,4090,1686;, + 3;1687,1680,1686;, + 3;1681,1680,1687;, + 3;4093,1681,1687;, + 3;4091,1681,4093;, + 3;1689,1682,1688;, + 3;1683,1682,1689;, + 3;1690,1683,1689;, + 3;1684,1683,1690;, + 3;1691,1684,1690;, + 3;1685,1684,1691;, + 3;1692,4092,4094;, + 3;1686,4092,1692;, + 3;1693,1686,1692;, + 3;1687,1686,1693;, + 3;4095,1687,1693;, + 3;4093,1687,4095;, + 3;1695,1688,1694;, + 3;1689,1688,1695;, + 3;1696,1689,1695;, + 3;1690,1689,1696;, + 3;1697,1690,1696;, + 3;1691,1690,1697;, + 3;1698,4094,4096;, + 3;1692,4094,1698;, + 3;1699,1692,1698;, + 3;1693,1692,1699;, + 3;4097,1693,1699;, + 3;4095,1693,4097;, + 3;1701,1694,1700;, + 3;1695,1694,1701;, + 3;1702,1695,1701;, + 3;1696,1695,1702;, + 3;1703,1696,1702;, + 3;1697,1696,1703;, + 3;1704,4096,4098;, + 3;1698,4096,1704;, + 3;1705,1698,1704;, + 3;1699,1698,1705;, + 3;4099,1699,1705;, + 3;4097,1699,4099;, + 3;1701,1700,1706;, + 3;1702,1701,1707;, + 3;1706,1707,1701;, + 3;1703,1702,1707;, + 3;1704,4098,4100;, + 3;1705,1704,4101;, + 3;4100,4101,1704;, + 3;4099,1705,4101;, + 3;3994,1708,1408;, + 3;1708,1401,1418;, + 3;1426,1404,1428;, + 3;1428,1714,1426;, + 3;4036,1459,1709;, + 3;1709,1458,4036;, + 3;4009,1423,1710;, + 3;4009,1710,1424;, + 3;4059,1425,1711;, + 3;1711,1422,4059;, + 3;1458,1709,1710;, + 3;1710,1423,1458;, + 3;1459,1422,1711;, + 3;1711,1709,1459;, + 3;1710,1405,1424;, + 3;1402,3995,1426;, + 3;4102,4011,1405;, + 3;1425,1712,1711;, + 3;1711,1712,1714;, + 3;1428,1432,1714;, + 3;1712,1426,1714;, + 3;1714,1432,1709;, + 3;1709,1711,1714;, + 3;1709,1432,1710;, + 3;1710,1432,1431;, + 3;1431,1405,1710;, + 3;1431,4102,1405;, + 3;1431,4000,4102;, + 3;1715,1708,3991;, + 3;1419,1453,1715;, + 3;1722,1716,1727;, + 3;1716,1393,3983;, + 3;1724,1717,1723;, + 3;1717,4103,3987;, + 3;1394,1718,3984;, + 3;1729,1720,4104;, + 3;3988,1719,3985;, + 3;1721,4105,4106;, + 3;4104,1720,1721;, + 3;4104,1721,4106;, + 3;1719,1720,1394;, + 3;1723,1393,1722;, + 3;1717,1393,1723;, + 3;1717,1724,1725;, + 3;1717,1725,4103;, + 3;1727,1392,1726;, + 3;1716,1392,1727;, + 3;1716,1722,1393;, + 3;3989,1728,1729;, + 3;3989,1729,4104;, + 3;3986,1728,3990;, + 3;1718,1728,3986;, + 3;1397,1722,1727;, + 3;1397,1727,1396;, + 3;1399,1724,1723;, + 3;1399,1723,1397;, + 3;1729,1394,1720;, + 3;1718,1394,1729;, + 3;1721,1395,4105;, + 3;1719,1395,1721;, + 3;1731,1730,1388;, + 3;1731,1736,1295;, + 3;1732,3938,3940;, + 3;1737,3938,1732;, + 3;1733,1731,3978;, + 3;1731,1295,3978;, + 3;1300,1732,4107;, + 3;1300,4107,1390;, + 3;1294,1388,1734;, + 3;1738,1734,1297;, + 3;1299,1305,1735;, + 3;1334,1735,1298;, + 3;1731,1388,1736;, + 3;1294,1736,1388;, + 3;1300,1737,1732;, + 3;1300,3937,1737;, + 3;1301,1738,1297;, + 3;1738,1301,1299;, + 3;4108,1730,1731;, + 3;1391,1296,3979;, + 3;1391,3981,3936;, + 3;1296,1388,3980;, + 3;1388,1730,3980;, + 3;4109,4108,1731;, + 3;4109,1731,1733;, + 3;1732,4110,4107;, + 3;1732,3940,4110;, + 3;196,4111,197;, + 3;3759,4112,3760;, + 3;3938,4113,3939;, + 3;74,75,4114;, + 3;1744,6,1742;, + 3;10,97,1739;, + 3;1743,1745,142;, + 3;1740,144,215;, + 3;4115,4116,1741;, + 3;1741,1744,4115;, + 3;4117,4118,1742;, + 3;1742,1745,4117;, + 3;4118,4115,1744;, + 3;1744,1742,4118;, + 3;4119,4117,1745;, + 3;1745,1743,4119;, + 3;118,107,3471;, + 3;3460,3471,107;, + 3;233,3527,3528;, + 3;3528,3518,224;, + 3;106,5,87;, + 3;106,87,110;, + 3;1779,1790,1756;, + 3;1757,1819,1751;, + 3;1825,1826,4120;, + 3;1758,1829,1748;, + 3;2386,2124,2140;, + 3;2330,2146,2425;, + 3;1870,1872,1782;, + 3;4121,1846,4122;, + 3;1834,1835,1759;, + 3;2183,2240,2182;, + 3;2698,2714,2138;, + 3;2344,2518,2356;, + 3;4123,1852,4124;, + 3;1761,1865,4125;, + 3;1818,1799,1766;, + 3;2711,2132,2707;, + 3;2288,2450,2748;, + 3;2129,2213,2725;, + 3;2726,2753,2169;, + 3;2461,2471,2433;, + 3;1762,1763,1760;, + 3;1770,1772,1771;, + 3;2214,2022,2040;, + 3;2457,2193,2206;, + 3;2749,2758,2168;, + 3;2184,2176,2239;, + 3;2041,2190,2052;, + 3;2163,2231,2287;, + 3;2739,2284,2036;, + 3;2724,2204,2180;, + 3;2194,2044,2056;, + 3;2185,2196,2175;, + 3;2186,2043,2195;, + 3;2189,2042,2178;, + 3;2205,2188,2179;, + 3;2113,2062,2070;, + 3;2192,2458,2064;, + 3;2075,2198,2074;, + 3;2177,2042,2187;, + 3;2199,2053,2073;, + 3;2191,2065,2051;, + 3;2174,2197,2076;, + 3;2200,2700,2211;, + 3;2712,2202,2131;, + 3;2121,2396,2209;, + 3;2203,2212,2130;, + 3;1833,1800,1831;, + 3;2222,2021,2215;, + 3;2173,2077,2090;, + 3;2221,2037,2034;, + 3;2084,2020,2223;, + 3;2285,2220,2035;, + 3;2723,2181,2232;, + 3;2256,2282,2245;, + 3;2261,2278,2270;, + 3;2251,2281,2257;, + 3;2246,2277,2262;, + 3;2269,2279,2275;, + 3;2164,2249,2230;, + 3;2248,2165,2243;, + 3;2170,2259,2238;, + 3;2258,2171,2255;, + 3;2216,2267,2226;, + 3;2266,2217,2265;, + 3;2081,2254,2172;, + 3;2253,2082,2273;, + 3;2224,2272,2083;, + 3;2271,2225,2268;, + 3;2228,2264,2218;, + 3;2263,2229,2250;, + 3;2236,2242,2166;, + 3;2241,2237,2260;, + 3;2280,2252,2274;, + 3;2276,2247,2244;, + 3;2160,2738,2732;, + 3;2227,2219,2286;, + 3;2143,2159,2429;, + 3;2297,2449,2289;, + 3;2142,2430,2291;, + 3;2309,2469,2495;, + 3;2434,2127,2768;, + 3;2472,2437,2308;, + 3;2477,2302,2444;, + 3;2730,2028,2746;, + 3;4126,1823,1747;, + 3;1769,1778,3416;, + 3;4127,1838,1750;, + 3;1883,1763,1762;, + 3;1765,1856,4128;, + 3;1764,1804,1784;, + 3;1858,1859,4129;, + 3;1777,1760,1763;, + 3;1749,1752,1763;, + 3;1746,1806,1767;, + 3;1773,3416,1775;, + 3;1771,1769,1770;, + 3;4130,4131,4132;, + 3;4133,4134,1768;, + 3;4135,4136,4137;, + 3;4136,4135,4138;, + 3;4137,4139,4140;, + 3;4139,4137,4136;, + 3;4141,4142,4143;, + 3;1776,4140,4139;, + 3;1774,1768,4134;, + 3;4144,4143,4142;, + 3;4132,4138,4135;, + 3;4138,4132,4131;, + 3;4143,4144,1774;, + 3;3416,1773,4145;, + 3;1768,1774,4144;, + 3;4142,4141,1776;, + 3;3416,4145,1770;, + 3;4146,2141,4147;, + 3;4140,1776,4141;, + 3;3416,4148,1775;, + 3;4131,4130,4133;, + 3;4149,1807,4150;, + 3;4134,4133,4130;, + 3;2715,2709,2333;, + 3;2319,2343,2549;, + 3;4151,1849,4152;, + 3;2145,4153,2704;, + 3;2710,2703,2332;, + 3;2524,2523,2346;, + 3;1783,1809,4154;, + 3;2320,2147,2342;, + 3;2335,2352,2329;, + 3;2351,2336,2350;, + 3;2363,2341,2148;, + 3;2367,2328,2353;, + 3;2375,2349,2337;, + 3;2370,2385,2536;, + 3;2537,2360,2135;, + 3;4155,1867,4156;, + 3;2327,2368,2362;, + 3;2513,2512,2355;, + 3;2149,2361,2369;, + 3;2531,2529,2374;, + 3;2348,2376,2372;, + 3;1785,1811,4157;, + 3;2389,2383,2378;, + 3;2381,2134,2357;, + 3;2384,2371,2377;, + 3;2133,2382,2390;, + 3;4158,1877,4159;, + 3;2338,2388,2379;, + 3;2393,2098,2401;, + 3;2392,2397,2115;, + 3;2109,2060,2399;, + 3;2394,2412,2097;, + 3;2411,2395,2122;, + 3;1755,1813,1787;, + 3;2407,2423,2101;, + 3;2422,2408,2415;, + 3;2402,2414,2409;, + 3;2413,2403,2418;, + 3;2419,2417,2404;, + 3;2416,2420,2108;, + 3;2099,2107,2421;, + 3;4160,1840,4161;, + 3;1788,1861,4162;, + 3;1754,1843,4163;, + 3;2102,2096,2406;, + 3;2114,2398,2061;, + 3;2112,2400,2091;, + 3;4164,1873,4165;, + 3;2424,2141,2318;, + 3;1779,1879,1790;, + 3;1756,1790,1879;, + 3;1757,4166,1820;, + 3;1751,1819,4166;, + 3;1825,4167,1827;, + 3;4120,1826,4167;, + 3;1758,1828,1830;, + 3;1748,1829,1828;, + 3;1870,1871,1794;, + 3;1782,1872,1871;, + 3;4121,4168,1847;, + 3;4122,1846,4168;, + 3;1834,1836,1796;, + 3;1759,1835,1753;, + 3;4123,4169,1853;, + 3;4124,1852,4169;, + 3;1761,1864,1866;, + 3;4125,1865,1864;, + 3;4170,1789,1799;, + 3;1766,1799,1789;, + 3;1833,1832,1800;, + 3;1831,1800,1832;, + 3;1824,1822,1801;, + 3;1747,1823,1822;, + 3;4127,4171,1837;, + 3;1750,1837,4171;, + 3;1857,1855,1803;, + 3;4128,1856,1855;, + 3;4154,1781,4172;, + 3;4173,4174,4175;, + 3;1858,1860,1805;, + 3;4129,1859,1786;, + 3;1746,4176,1881;, + 3;1767,1806,1880;, + 3;4149,4177,1807;, + 3;4150,1882,4178;, + 3;4151,1850,1851;, + 3;4152,1849,4179;, + 3;1783,1781,1809;, + 3;4154,1809,1781;, + 3;4155,4180,1868;, + 3;4156,1867,4180;, + 3;1785,4181,1811;, + 3;4157,1811,4181;, + 3;1878,1876,1812;, + 3;4159,1877,1876;, + 3;2410,2426,2405;, + 3;4160,4182,1841;, + 3;4161,1840,4182;, + 3;1788,4183,1862;, + 3;4162,1861,4183;, + 3;1754,4184,1844;, + 3;4163,1843,4184;, + 3;4164,1874,1875;, + 3;4165,1873,4185;, + 3;4186,4187,4188;, + 3;4187,4186,4189;, + 3;4170,1799,1818;, + 3;4187,4189,4190;, + 3;2152,2456,2489;, + 3;2431,2300,2290;, + 3;2156,2126,2435;, + 3;2476,2301,2478;, + 3;2438,2764,2307;, + 3;2501,2485,2296;, + 3;2446,2311,2728;, + 3;2310,2447,2468;, + 3;2155,2436,2473;, + 3;2452,2293,2491;, + 3;2459,2118,2063;, + 3;2150,2465,2428;, + 3;2432,2466,2299;, + 3;2451,2492,2488;, + 3;2467,2448,2298;, + 3;2153,2500,2455;, + 3;2454,2496,2505;, + 3;2453,2506,2292;, + 3;2295,2482,2316;, + 3;2462,2494,2470;, + 3;2493,2463,2487;, + 3;2315,2483,2442;, + 3;2440,2503,2481;, + 3;2502,2441,2484;, + 3;2151,2486,2464;, + 3;2479,2498,2475;, + 3;2497,2480,2504;, + 3;2154,2474,2499;, + 3;2317,2490,2294;, + 3;2507,2366,2354;, + 3;2550,2340,2364;, + 3;2326,2544,2561;, + 3;2345,2519,2517;, + 3;2562,2325,2556;, + 3;2373,2530,2347;, + 3;2568,2324,2563;, + 3;2359,2538,2534;, + 3;2323,2569,2541;, + 3;2535,2380,2358;, + 3;2574,2528,2532;, + 3;2717,2543,2136;, + 3;2620,2599,2606;, + 3;2548,2339,2551;, + 3;2621,2629,2598;, + 3;2508,2555,2365;, + 3;2590,2634,2601;, + 3;2630,2625,2600;, + 3;2613,2589,2612;, + 3;2592,2582,2558;, + 3;2655,2616,2649;, + 3;2615,2656,2654;, + 3;2570,2579,2540;, + 3;2539,2580,2533;, + 3;2583,2567,2557;, + 3;2614,2650,2588;, + 3;2611,2581,2593;, + 3;2610,2594,2602;, + 3;2525,2608,2522;, + 3;2607,2526,2619;, + 3;2514,2596,2511;, + 3;2595,2515,2605;, + 3;2545,2632,2560;, + 3;2631,2546,2624;, + 3;2520,2604,2516;, + 3;2603,2521,2609;, + 3;2564,2645,2573;, + 3;2644,2565,2639;, + 3;2575,2618,2527;, + 3;2617,2576,2648;, + 3;2552,2623,2547;, + 3;2622,2553,2628;, + 3;2509,2627,2554;, + 3;2626,2510,2597;, + 3;2591,2559,2633;, + 3;2661,2647,2577;, + 3;2666,2572,2640;, + 3;2584,2638,2566;, + 3;2683,2676,2671;, + 3;2684,2682,2675;, + 3;2689,2681,2685;, + 3;2680,2690,2697;, + 3;2578,2571,2667;, + 3;2662,2660,2646;, + 3;2657,2687,2653;, + 3;2686,2658,2693;, + 3;2651,2669,2587;, + 3;2668,2652,2688;, + 3;2635,2678,2643;, + 3;2677,2636,2674;, + 3;2641,2695,2665;, + 3;2694,2642,2679;, + 3;2585,2673,2637;, + 3;2672,2586,2670;, + 3;2663,2692,2659;, + 3;2691,2664,2696;, + 3;1819,1791,1821;, + 3;1757,1820,1819;, + 3;2701,2120,2210;, + 3;2119,2702,2139;, + 3;1820,1791,1819;, + 3;1820,1821,1791;, + 3;1819,1821,4166;, + 3;1820,4166,1821;, + 3;1747,1822,4191;, + 3;4126,4191,1822;, + 3;1823,1801,1822;, + 3;1824,1801,1823;, + 3;4126,1822,1824;, + 3;4126,1824,1823;, + 3;4192,4167,1825;, + 3;4192,1825,4120;, + 3;1826,1827,4167;, + 3;1825,1792,1826;, + 3;1825,1827,1792;, + 3;1826,1792,1827;, + 3;1748,1828,4193;, + 3;1758,4193,1828;, + 3;1829,1793,1828;, + 3;1758,1830,1829;, + 3;1830,1793,1829;, + 3;1830,1828,1793;, + 3;4194,1831,4195;, + 3;4195,1831,4196;, + 3;1831,1832,4196;, + 3;4194,4196,1832;, + 3;4194,1832,1833;, + 3;4194,1833,1831;, + 3;4197,1753,1834;, + 3;4197,1834,1759;, + 3;1835,1796,1836;, + 3;1834,1796,1835;, + 3;1835,1836,1753;, + 3;1834,1753,1836;, + 3;1839,1837,1802;, + 3;1750,1838,1837;, + 3;1838,1802,1837;, + 3;1839,1802,1838;, + 3;4127,1837,1839;, + 3;4127,1839,1838;, + 3;1840,1814,1842;, + 3;4160,1841,1840;, + 3;1841,1814,1840;, + 3;1841,1842,1814;, + 3;1840,1842,4182;, + 3;1841,4182,1842;, + 3;1843,1845,4184;, + 3;1754,1844,1843;, + 3;1844,1816,1843;, + 3;1844,4184,1845;, + 3;1844,1845,1816;, + 3;1843,1816,1845;, + 3;1846,1848,4168;, + 3;4121,1847,1846;, + 3;1847,1795,1846;, + 3;1847,4168,1848;, + 3;1847,1848,1795;, + 3;1846,1795,1848;, + 3;1849,1808,1850;, + 3;4151,1851,1849;, + 3;1849,1850,4179;, + 3;4151,4179,1850;, + 3;1851,1808,1849;, + 3;1851,1850,1808;, + 3;1852,1854,4169;, + 3;4123,1853,1852;, + 3;1853,1797,1852;, + 3;1853,4169,1854;, + 3;1853,1854,1797;, + 3;1852,1797,1854;, + 3;4128,1855,4198;, + 3;1765,4198,1855;, + 3;1856,1803,1855;, + 3;1857,1803,1856;, + 3;1765,1855,1857;, + 3;1765,1857,1856;, + 3;4199,1786,1858;, + 3;4199,1858,4129;, + 3;1859,1805,1860;, + 3;1858,1805,1859;, + 3;1859,1860,1786;, + 3;1858,1786,1860;, + 3;1861,1815,1863;, + 3;1788,1862,1861;, + 3;1862,1815,1861;, + 3;1862,1863,1815;, + 3;1861,1863,4183;, + 3;1862,4183,1863;, + 3;4125,1864,4200;, + 3;1761,4200,1864;, + 3;1865,1798,1864;, + 3;1761,1866,1865;, + 3;1866,1798,1865;, + 3;1866,1864,1798;, + 3;1867,1869,4180;, + 3;4155,1868,1867;, + 3;1868,1810,1867;, + 3;1868,4180,1869;, + 3;1868,1869,1810;, + 3;1867,1810,1869;, + 3;4201,1780,1870;, + 3;4201,1870,1782;, + 3;1782,1871,1780;, + 3;1870,1780,1871;, + 3;1872,1794,1871;, + 3;1870,1794,1872;, + 3;1873,1817,1874;, + 3;4164,1875,1873;, + 3;1873,1874,4185;, + 3;4164,4185,1874;, + 3;1875,1817,1873;, + 3;1875,1874,1817;, + 3;4159,1876,4202;, + 3;4158,4202,1876;, + 3;1877,1812,1876;, + 3;1878,1812,1877;, + 3;4158,1876,1878;, + 3;4158,1878,1877;, + 3;1756,1879,4203;, + 3;1779,4203,1879;, + 3;4177,4178,1882;, + 3;1880,1881,4176;, + 3;1746,1881,1806;, + 3;1880,1806,1881;, + 3;4177,1882,1807;, + 3;4150,1807,1882;, + 3;2144,2705,2158;, + 3;2706,2125,2157;, + 3;2699,2201,2713;, + 3;2137,2708,2716;, + 3;2322,2542,2718;, + 3;2321,2719,2334;, + 3;2117,2460,2207;, + 3;2116,2208,2391;, + 3;2306,2759,2756;, + 3;2303,2314,2443;, + 3;2168,2235,2167;, + 3;2445,2729,2747;, + 3;2027,2731,2733;, + 3;2161,2741,2737;, + 3;2162,2283,2740;, + 3;1749,1763,1883;, + 3;2745,2023,2030;, + 3;2313,2304,2751;, + 3;2727,2312,2752;, + 3;2750,2305,2757;, + 3;2761,2722,2233;, + 3;2760,2234,2755;, + 3;2439,2765,2763;, + 3;2766,2721,2762;, + 3;2767,2128,2720;, + 3;4204,1884,4205;, + 3;4206,1885,4207;, + 3;2387,2427,2123;, + 3;1884,4206,4205;, + 3;4204,4206,1884;, + 3;1885,4204,4207;, + 3;4206,4204,1885;, + 3;1910,1887,1921;, + 3;1888,4208,1950;, + 3;1956,4209,1957;, + 3;1889,4210,1960;, + 3;3044,2796,2780;, + 3;2987,3083,2802;, + 3;2001,1913,2003;, + 3;4211,4212,1977;, + 3;1965,1890,1966;, + 3;2839,2838,2896;, + 3;3357,2790,3373;, + 3;3001,3013,3177;, + 3;4213,4214,1983;, + 3;1892,4215,1996;, + 3;1949,1897,1930;, + 3;3369,3366,2788;, + 3;2944,3395,3109;, + 3;2783,3384,2869;, + 3;3385,2825,3400;, + 3;3120,3092,3130;, + 3;1893,1891,1894;, + 3;1901,1902,1903;, + 3;2870,2039,2017;, + 3;3116,2866,2849;, + 3;3399,2816,3405;, + 3;2843,2888,2832;, + 3;2048,2049,2846;, + 3;2821,2943,2887;, + 3;2744,2031,2941;, + 3;3379,2834,2868;, + 3;2850,2055,2045;, + 3;2842,2826,2854;, + 3;2841,2855,2046;, + 3;2847,2836,2047;, + 3;2867,2835,2848;, + 3;2769,2069,2057;, + 3;2844,2067,3119;, + 3;2080,2071,2852;, + 3;2837,2840,2047;, + 3;2851,2072,2054;, + 3;2845,2050,2066;, + 3;2827,2079,2853;, + 3;2856,2861,3360;, + 3;3368,2781,2858;, + 3;2777,2863,3054;, + 3;2857,2782,2860;, + 3;1964,1962,1931;, + 3;2878,2877,2018;, + 3;2828,2089,2078;, + 3;2871,2033,2038;, + 3;2085,2882,2019;, + 3;2940,2032,2872;, + 3;3380,2895,2833;, + 3;2912,2901,2938;, + 3;2917,2926,2935;, + 3;2907,2916,2932;, + 3;2902,2921,2936;, + 3;2922,2931,2934;, + 3;2820,2883,2904;, + 3;2905,2898,2819;, + 3;2831,2889,2914;, + 3;2915,2908,2830;, + 3;2876,2879,2924;, + 3;2925,2918,2875;, + 3;2088,2829,2909;, + 3;2910,2928,2087;, + 3;2881,2086,2929;, + 3;2930,2923,2880;, + 3;2885,2874,2919;, + 3;2920,2903,2884;, + 3;2891,2818,2899;, + 3;2900,2913,2890;, + 3;2933,2927,2911;, + 3;2937,2897,2906;, + 3;2824,3386,2735;, + 3;2886,2939,2873;, + 3;2799,3090,2815;, + 3;2953,2947,3104;, + 3;2800,2945,3089;, + 3;2965,3154,3126;, + 3;3093,3415,2785;, + 3;3131,2964,3096;, + 3;3136,3103,2962;, + 3;3388,3393,2025;, + 3;4216,4217,1954;, + 3;1900,1901,3417;, + 3;4218,4219,1969;, + 3;2014,1893,1894;, + 3;1896,4220,1987;, + 3;1895,1915,1935;, + 3;1989,4221,1990;, + 3;1908,1894,1891;, + 3;1749,1894,1752;, + 3;1746,1898,1937;, + 3;3417,1906,1899;, + 3;1902,1901,1900;, + 3;4222,4223,4224;, + 3;1909,4225,4226;, + 3;4135,4137,4227;, + 3;4227,4228,4135;, + 3;4137,4229,4230;, + 3;4230,4227,4137;, + 3;4231,4232,1904;, + 3;1907,4230,4229;, + 3;1905,4226,4225;, + 3;4233,1904,4232;, + 3;4223,4135,4228;, + 3;4228,4224,4223;, + 3;4232,1905,4233;, + 3;1906,3417,4234;, + 3;4225,4233,1905;, + 3;1904,1907,4231;, + 3;4235,1900,3417;, + 3;2801,1908,1891;, + 3;4229,4231,1907;, + 3;4235,3417,1899;, + 3;4224,1909,4222;, + 3;4236,4237,1938;, + 3;4226,4222,1909;, + 3;3374,2989,3371;, + 3;2975,3208,3000;, + 3;4238,4239,1980;, + 3;2802,3364,2991;, + 3;3370,2990,3365;, + 3;3183,3006,3182;, + 3;1914,4240,1940;, + 3;2982,2996,2805;, + 3;2995,2986,3011;, + 3;3012,3002,2994;, + 3;3021,2804,2997;, + 3;3024,3010,2983;, + 3;3033,2993,3003;, + 3;3028,3195,3043;, + 3;3196,2793,3017;, + 3;4241,4242,1998;, + 3;2984,3019,3023;, + 3;3176,3008,3171;, + 3;2803,3022,3020;, + 3;3194,3029,3185;, + 3;3004,3031,3037;, + 3;1916,4243,1942;, + 3;3046,3035,3039;, + 3;3041,3016,2794;, + 3;3038,3036,3032;, + 3;2795,3045,3040;, + 3;4244,4245,2008;, + 3;2992,3034,3047;, + 3;3051,3059,2093;, + 3;3052,2773,3058;, + 3;2110,3056,2059;, + 3;3050,2094,3070;, + 3;3064,2776,3049;, + 3;1886,1918,1944;, + 3;3068,2104,3080;, + 3;3081,3071,3067;, + 3;3060,3066,3072;, + 3;3073,3074,3063;, + 3;3077,3062,3075;, + 3;3076,2105,3079;, + 3;2100,3078,2106;, + 3;4246,4247,1971;, + 3;1919,4248,1992;, + 3;4249,4250,1974;, + 3;2103,3069,2095;, + 3;2774,2058,3057;, + 3;2111,2092,3055;, + 3;4251,4252,2004;, + 3;3082,2974,4253;, + 3;1910,1921,2010;, + 3;1887,2010,1921;, + 3;1888,1951,4254;, + 3;4208,4254,1950;, + 3;1956,1958,4255;, + 3;4209,4255,1957;, + 3;1889,1961,1959;, + 3;4210,1959,1960;, + 3;2001,1925,2002;, + 3;1913,2002,2003;, + 3;4211,1978,4256;, + 3;4212,4256,1977;, + 3;1965,1927,1967;, + 3;1890,4257,1966;, + 3;4213,1984,4258;, + 3;4214,4258,1983;, + 3;1892,1997,1995;, + 3;4215,1995,1996;, + 3;4259,1930,1920;, + 3;1897,1920,1930;, + 3;1964,1931,1963;, + 3;1962,1963,1931;, + 3;1955,1932,1953;, + 3;4217,1953,1954;, + 3;4218,1968,4260;, + 3;4219,4260,1968;, + 3;1988,1934,1986;, + 3;4220,1986,1987;, + 3;4240,4261,1912;, + 3;3018,2985,3084;, + 3;1989,1936,1991;, + 3;4221,1917,1990;, + 3;1746,2012,4176;, + 3;1898,2011,1937;, + 3;4236,1938,4262;, + 3;4237,4178,2013;, + 3;4238,1982,1981;, + 3;4239,4263,1980;, + 3;1914,1940,1912;, + 3;4240,1912,1940;, + 3;4241,1999,4264;, + 3;4242,4264,1998;, + 3;1916,1942,4265;, + 3;4243,4265,1942;, + 3;2009,1943,2007;, + 3;4245,2007,2008;, + 3;3065,3061,3086;, + 3;4246,1972,4266;, + 3;4247,4266,1971;, + 3;1919,1993,4267;, + 3;4248,4267,1992;, + 3;4249,1975,4268;, + 3;4250,4268,1974;, + 3;4251,2006,2005;, + 3;4252,4269,2004;, + 3;4270,4271,4272;, + 3;4272,4273,4270;, + 3;4259,1949,1930;, + 3;4272,4274,4273;, + 3;2812,3148,3115;, + 3;3088,2946,2954;, + 3;2808,3098,2786;, + 3;3132,3140,2963;, + 3;3095,2957,3411;, + 3;3160,2952,3144;, + 3;3107,3390,2972;, + 3;2973,3127,3106;, + 3;2809,3135,3097;, + 3;3113,3152,2950;, + 3;3118,2068,2770;, + 3;2814,3091,3121;, + 3;3087,2955,3129;, + 3;3114,3145,3151;, + 3;3128,2956,3105;, + 3;2811,3110,3159;, + 3;3111,3162,3158;, + 3;3112,2951,3161;, + 3;2948,2967,3143;, + 3;3124,3125,3149;, + 3;3150,3146,3123;, + 3;2968,3100,3142;, + 3;3102,3137,3164;, + 3;3165,3141,3101;, + 3;2813,3122,3147;, + 3;3139,3133,3156;, + 3;3157,3163,3138;, + 3;2810,3155,3134;, + 3;2966,2949,3153;, + 3;3170,3009,3025;, + 3;3209,3027,2998;, + 3;2976,3220,3207;, + 3;3007,3172,3181;, + 3;3221,3219,2977;, + 3;3030,3005,3184;, + 3;3227,3226,2978;, + 3;3014,3191,3202;, + 3;2979,3199,3232;, + 3;3190,3015,3042;, + 3;3233,3193,3186;, + 3;3377,2792,3197;, + 3;3279,3265,3258;, + 3;3203,3214,2999;, + 3;3284,3254,3288;, + 3;3169,3026,3210;, + 3;3249,3263,3293;, + 3;3292,3264,3280;, + 3;3272,3271,3248;, + 3;3252,3217,3246;, + 3;3314,3308,3276;, + 3;3277,3313,3319;, + 3;3231,3200,3235;, + 3;3201,3192,3234;, + 3;3245,3218,3222;, + 3;3278,3240,3312;, + 3;3266,3251,3247;, + 3;3267,3262,3250;, + 3;3189,3178,3269;, + 3;3270,3273,3188;, + 3;3175,3166,3256;, + 3;3257,3259,3174;, + 3;3206,3215,3290;, + 3;3291,3281,3205;, + 3;3180,3173,3260;, + 3;3261,3268,3179;, + 3;3225,3228,3304;, + 3;3299,3298,3224;, + 3;3239,3187,3274;, + 3;3275,3305,3238;, + 3;3213,3204,3282;, + 3;3283,3285,3212;, + 3;3168,3211,3286;, + 3;3287,3255,3167;, + 3;3253,3289,3216;, + 3;3320,3237,3306;, + 3;3322,3303,3229;, + 3;3244,3223,3294;, + 3;3342,3330,3335;, + 3;3347,3331,3341;, + 3;3348,3346,3336;, + 3;3337,3356,3352;, + 3;3236,3321,3230;, + 3;3326,3307,3315;, + 3;3318,3309,3344;, + 3;3345,3349,3317;, + 3;3311,3241,3328;, + 3;3329,3343,3310;, + 3;3297,3300,3339;, + 3;3340,3332,3296;, + 3;3302,3323,3354;, + 3;3355,3338,3301;, + 3;3243,3295,3333;, + 3;3334,3327,3242;, + 3;3325,3316,3350;, + 3;3351,3353,3324;, + 3;1950,1952,1922;, + 3;1888,1950,1951;, + 3;3359,2862,2778;, + 3;2779,2789,3358;, + 3;1951,1950,1922;, + 3;1951,1922,1952;, + 3;1950,4254,1952;, + 3;1951,1952,4254;, + 3;4217,4275,1953;, + 3;4216,1953,4275;, + 3;1954,1953,1932;, + 3;1955,1954,1932;, + 3;4216,1955,1953;, + 3;4216,1954,1955;, + 3;4276,1956,4255;, + 3;4276,4209,1956;, + 3;1957,4255,1958;, + 3;1956,1957,1923;, + 3;1956,1923,1958;, + 3;1957,1958,1923;, + 3;4210,4277,1959;, + 3;1889,1959,4277;, + 3;1960,1959,1924;, + 3;1889,1960,1961;, + 3;1961,1960,1924;, + 3;1961,1924,1959;, + 3;4278,4279,1962;, + 3;4279,4280,1962;, + 3;1962,4280,1963;, + 3;4278,1963,4280;, + 3;4278,1964,1963;, + 3;4278,1962,1964;, + 3;4281,1965,4257;, + 3;4281,1890,1965;, + 3;1966,1967,1927;, + 3;1965,1966,1927;, + 3;1966,4257,1967;, + 3;1965,1967,4257;, + 3;1970,1933,1968;, + 3;4219,1968,1969;, + 3;1969,1968,1933;, + 3;1970,1969,1933;, + 3;4218,1970,1968;, + 3;4218,1969,1970;, + 3;1971,1973,1945;, + 3;4246,1971,1972;, + 3;1972,1971,1945;, + 3;1972,1945,1973;, + 3;1971,4266,1973;, + 3;1972,1973,4266;, + 3;1974,4268,1976;, + 3;4249,1974,1975;, + 3;1975,1974,1947;, + 3;1975,1976,4268;, + 3;1975,1947,1976;, + 3;1974,1976,1947;, + 3;1977,4256,1979;, + 3;4211,1977,1978;, + 3;1978,1977,1926;, + 3;1978,1979,4256;, + 3;1978,1926,1979;, + 3;1977,1979,1926;, + 3;1980,1981,1939;, + 3;4238,1980,1982;, + 3;1980,4263,1981;, + 3;4238,1981,4263;, + 3;1982,1980,1939;, + 3;1982,1939,1981;, + 3;1983,4258,1985;, + 3;4213,1983,1984;, + 3;1984,1983,1928;, + 3;1984,1985,4258;, + 3;1984,1928,1985;, + 3;1983,1985,1928;, + 3;4220,4282,1986;, + 3;1896,1986,4282;, + 3;1987,1986,1934;, + 3;1988,1987,1934;, + 3;1896,1988,1986;, + 3;1896,1987,1988;, + 3;4283,1989,1917;, + 3;4283,4221,1989;, + 3;1990,1991,1936;, + 3;1989,1990,1936;, + 3;1990,1917,1991;, + 3;1989,1991,1917;, + 3;1992,1994,1946;, + 3;1919,1992,1993;, + 3;1993,1992,1946;, + 3;1993,1946,1994;, + 3;1992,4267,1994;, + 3;1993,1994,4267;, + 3;4215,4284,1995;, + 3;1892,1995,4284;, + 3;1996,1995,1929;, + 3;1892,1996,1997;, + 3;1997,1996,1929;, + 3;1997,1929,1995;, + 3;1998,4264,2000;, + 3;1915,4285,4286;, + 3;1999,1998,1941;, + 3;1999,2000,4264;, + 3;1999,1941,2000;, + 3;1998,2000,1941;, + 3;4287,2001,1911;, + 3;4287,1913,2001;, + 3;1913,1911,2002;, + 3;2001,2002,1911;, + 3;2003,2002,1925;, + 3;2001,2003,1925;, + 3;2004,2005,1948;, + 3;4251,2004,2006;, + 3;2004,4269,2005;, + 3;4251,2005,4269;, + 3;2006,2004,1948;, + 3;2006,1948,2005;, + 3;4245,4288,2007;, + 3;4244,2007,4288;, + 3;2008,2007,1943;, + 3;2009,2008,1943;, + 3;4244,2009,2007;, + 3;4244,2008,2009;, + 3;1887,4289,2010;, + 3;1910,2010,4289;, + 3;4262,2013,4178;, + 3;2011,4176,2012;, + 3;1746,1937,2012;, + 3;2011,2012,1937;, + 3;4262,1938,2013;, + 3;4237,2013,1938;, + 3;2798,2806,3363;, + 3;3362,2807,2787;, + 3;3361,3367,2859;, + 3;2791,3378,3372;, + 3;2980,3376,3198;, + 3;2981,2988,3375;, + 3;2771,2865,3117;, + 3;2772,3053,2864;, + 3;2958,3402,3410;, + 3;2961,3099,2969;, + 3;2893,2817,2892;, + 3;3108,3392,3389;, + 3;2026,2734,3387;, + 3;2823,2736,2742;, + 3;2822,2743,2942;, + 3;1749,2014,1894;, + 3;3394,2029,2024;, + 3;2970,3397,2960;, + 3;3391,3396,2971;, + 3;3398,3401,2959;, + 3;3408,2894,3381;, + 3;3409,3403,2893;, + 3;3094,3406,3414;, + 3;3413,3407,3382;, + 3;3412,3383,2784;, + 3;4290,4291,2015;, + 3;4292,4293,2016;, + 3;3048,2775,3085;, + 3;2015,4291,4294;, + 3;4290,2015,4294;, + 3;2016,4293,4295;, + 3;4292,2016,4295;, + 3;2017,2040,2022;, + 3;2017,2039,2040;, + 3;2018,2870,2017;, + 3;2018,2877,2870;, + 3;2019,2878,2018;, + 3;2019,2882,2878;, + 3;2020,2085,2019;, + 3;2020,2084,2085;, + 3;2021,2223,2020;, + 3;2021,2222,2223;, + 3;2022,2215,2021;, + 3;2022,2214,2215;, + 3;2019,2017,2020;, + 3;2020,2017,2022;, + 3;2020,2022,2021;, + 3;2017,2019,2018;, + 3;2023,2746,2028;, + 3;2023,2745,2746;, + 3;2024,2030,2023;, + 3;2024,2029,2030;, + 3;2025,3394,2024;, + 3;2025,3393,3394;, + 3;2026,3388,2025;, + 3;2026,3387,3388;, + 3;2027,2734,2026;, + 3;2027,2733,2734;, + 3;2028,2731,2027;, + 3;2028,2730,2731;, + 3;2025,2028,2026;, + 3;2026,2028,2027;, + 3;2028,2025,2024;, + 3;2028,2024,2023;, + 3;2029,2014,1749;, + 3;2029,3394,2014;, + 3;1749,2745,2030;, + 3;1749,1883,2745;, + 3;1749,2030,2029;, + 3;2031,2739,2036;, + 3;2031,2744,2739;, + 3;2032,2941,2031;, + 3;2032,2940,2941;, + 3;2033,2872,2032;, + 3;2033,2871,2872;, + 3;2034,2038,2033;, + 3;2034,2037,2038;, + 3;2035,2221,2034;, + 3;2035,2220,2221;, + 3;2036,2285,2035;, + 3;2036,2284,2285;, + 3;2031,2036,2034;, + 3;2031,2034,2033;, + 3;2031,2033,2032;, + 3;2034,2036,2035;, + 3;2037,2214,2040;, + 3;2037,2221,2214;, + 3;2039,2871,2038;, + 3;2039,2870,2871;, + 3;2039,2038,2040;, + 3;2040,2038,2037;, + 3;2041,2049,2048;, + 3;2041,2052,2049;, + 3;2042,2190,2041;, + 3;2042,2189,2190;, + 3;2042,2177,2178;, + 3;2043,2187,2042;, + 3;2043,2186,2187;, + 3;2044,2195,2043;, + 3;2044,2194,2195;, + 3;2045,2056,2044;, + 3;2045,2055,2056;, + 3;2046,2850,2045;, + 3;2046,2855,2850;, + 3;2047,2841,2046;, + 3;2047,2840,2841;, + 3;2047,2836,2837;, + 3;2048,2847,2047;, + 3;2048,2846,2847;, + 3;2045,2044,2048;, + 3;2045,2048,2046;, + 3;2046,2048,2047;, + 3;2048,2044,2041;, + 3;2041,2044,2043;, + 3;2041,2043,2042;, + 3;2050,2846,2049;, + 3;2050,2845,2846;, + 3;2051,2066,2050;, + 3;2051,2065,2066;, + 3;2052,2191,2051;, + 3;2052,2190,2191;, + 3;2050,2049,2051;, + 3;2051,2049,2052;, + 3;2053,2194,2056;, + 3;2053,2199,2194;, + 3;2054,2073,2053;, + 3;2054,2072,2073;, + 3;2055,2851,2054;, + 3;2055,2850,2851;, + 3;2055,2054,2056;, + 3;2056,2054,2053;, + 3;2057,2070,2062;, + 3;2057,2069,2070;, + 3;2058,2769,2057;, + 3;2058,2774,2769;, + 3;2059,3057,2058;, + 3;2059,3056,3057;, + 3;2060,2110,2059;, + 3;2060,2109,2110;, + 3;2061,2399,2060;, + 3;2061,2398,2399;, + 3;2062,2114,2061;, + 3;2062,2113,2114;, + 3;2057,2062,2058;, + 3;2058,2062,2061;, + 3;2058,2061,2059;, + 3;2059,2061,2060;, + 3;2063,2113,2070;, + 3;2063,2118,2113;, + 3;2064,2459,2063;, + 3;2064,2458,2459;, + 3;2065,2192,2064;, + 3;2065,2191,2192;, + 3;2067,2845,2066;, + 3;2067,2844,2845;, + 3;2068,3119,2067;, + 3;2068,3118,3119;, + 3;2069,2770,2068;, + 3;2069,2769,2770;, + 3;2066,2065,2069;, + 3;2066,2069,2068;, + 3;2066,2068,2067;, + 3;2069,2065,2070;, + 3;2070,2065,2063;, + 3;2063,2065,2064;, + 3;2071,2075,2074;, + 3;2071,2080,2075;, + 3;2072,2852,2071;, + 3;2072,2851,2852;, + 3;2074,2199,2073;, + 3;2074,2198,2199;, + 3;2072,2071,2073;, + 3;2073,2071,2074;, + 3;2076,2198,2075;, + 3;2076,2197,2198;, + 3;2077,2174,2076;, + 3;2077,2173,2174;, + 3;2078,2090,2077;, + 3;2078,2089,2090;, + 3;2079,2828,2078;, + 3;2079,2827,2828;, + 3;2080,2853,2079;, + 3;2080,2852,2853;, + 3;2078,2077,2079;, + 3;2079,2077,2076;, + 3;2079,2076,2080;, + 3;2080,2076,2075;, + 3;2081,2173,2090;, + 3;2081,2172,2173;, + 3;2082,2254,2081;, + 3;2082,2253,2254;, + 3;2083,2273,2082;, + 3;2083,2272,2273;, + 3;2084,2224,2083;, + 3;2084,2223,2224;, + 3;2086,2882,2085;, + 3;2086,2881,2882;, + 3;2087,2929,2086;, + 3;2087,2928,2929;, + 3;2088,2910,2087;, + 3;2088,2909,2910;, + 3;2089,2829,2088;, + 3;2089,2828,2829;, + 3;2085,2084,2090;, + 3;2085,2090,2089;, + 3;2085,2089,2086;, + 3;2086,2089,2087;, + 3;2087,2089,2088;, + 3;2090,2084,2083;, + 3;2090,2083,2082;, + 3;2090,2082,2081;, + 3;2091,2401,2098;, + 3;2091,2400,2401;, + 3;2092,2112,2091;, + 3;2092,2111,2112;, + 3;2093,3055,2092;, + 3;2093,3059,3055;, + 3;4296,3051,2093;, + 3;4296,4297,3051;, + 3;4298,3070,2094;, + 3;4298,4299,3070;, + 3;2096,2103,2095;, + 3;2096,2102,2103;, + 3;2097,4300,4301;, + 3;2097,2412,4300;, + 3;2098,4302,4303;, + 3;2098,2393,4302;, + 3;4304,4305,4298;, + 3;4304,4298,2094;, + 3;4298,4305,4301;, + 3;4301,4305,2097;, + 3;2098,2093,2092;, + 3;2098,2092,2091;, + 3;2099,4306,4307;, + 3;2099,2421,4306;, + 3;2100,2107,2099;, + 3;2100,2106,2107;, + 3;4307,3078,2100;, + 3;4307,4308,3078;, + 3;4307,2100,2099;, + 3;2101,21,8;, + 3;2101,2423,21;, + 3;2102,2407,2101;, + 3;2102,2406,2407;, + 3;2104,3069,2103;, + 3;2104,3068,3069;, + 3;8,3080,2104;, + 3;8,151,3080;, + 3;8,2102,2101;, + 3;8,2103,2102;, + 3;8,2104,2103;, + 3;2105,4309,4310;, + 3;2105,3076,4309;, + 3;2106,3079,2105;, + 3;2106,3078,3079;, + 3;2108,2421,2107;, + 3;2108,2420,2421;, + 3;4310,2416,2108;, + 3;4310,4311,2416;, + 3;4310,2106,2105;, + 3;4310,2107,2106;, + 3;4310,2108,2107;, + 3;4312,2400,2112;, + 3;4312,4313,2400;, + 3;2111,4314,4315;, + 3;2111,3055,4314;, + 3;4315,4312,2111;, + 3;2111,4312,2112;, + 3;4316,2398,2114;, + 3;2115,2397,4317;, + 3;2116,2392,2115;, + 3;2116,2391,2392;, + 3;2117,4318,4319;, + 3;2117,2207,4318;, + 3;2118,2460,2117;, + 3;2118,2459,2460;, + 3;2114,2118,2117;, + 3;2114,2117,4316;, + 3;4316,2117,4319;, + 3;2118,2114,2113;, + 3;2119,4320,4321;, + 3;2119,2139,4320;, + 3;2120,2702,2119;, + 3;2120,2701,2702;, + 3;2121,2210,2120;, + 3;2121,2209,2210;, + 3;4322,2396,2121;, + 3;4322,4323,2396;, + 3;1755,2411,2122;, + 3;1755,1787,2411;, + 3;2123,1813,1755;, + 3;2123,2427,1813;, + 3;2124,2387,2123;, + 3;2124,2386,2387;, + 3;1755,2124,2123;, + 3;4324,2119,4321;, + 3;4324,2120,2119;, + 3;4324,2121,2120;, + 3;4324,4322,2121;, + 3;2125,4325,4326;, + 3;2125,2706,4325;, + 3;2126,2157,2125;, + 3;2126,2156,2157;, + 3;2127,2435,2126;, + 3;2127,2434,2435;, + 3;2128,2768,2127;, + 3;2128,2767,2768;, + 3;2129,2720,2128;, + 3;2129,2725,2720;, + 3;2130,2213,2129;, + 3;2130,2212,2213;, + 3;4327,2203,2130;, + 3;2131,2202,4328;, + 3;2132,2712,2131;, + 3;2132,2711,2712;, + 3;4326,2127,2126;, + 3;4326,2126,2125;, + 3;2127,4326,4327;, + 3;2127,4327,2128;, + 3;2128,4327,2130;, + 3;2128,2130,2129;, + 3;2133,4329,4320;, + 3;2133,2390,4329;, + 3;2134,2382,2133;, + 3;2134,2381,2382;, + 3;2135,2357,2134;, + 3;2135,2360,2357;, + 3;2136,2537,2135;, + 3;2136,2543,2537;, + 3;2137,2717,2136;, + 3;2137,2716,2717;, + 3;2138,2708,2137;, + 3;2138,2714,2708;, + 3;2139,2698,2138;, + 3;2139,2702,2698;, + 3;2134,2133,2135;, + 3;2135,2133,4320;, + 3;2135,4320,2136;, + 3;2136,4320,2139;, + 3;2136,2139,2137;, + 3;2137,2139,2138;, + 3;2141,2425,2146;, + 3;2141,2424,2425;, + 3;2141,4146,2318;, + 3;4330,1760,1777;, + 3;2142,1762,1760;, + 3;2142,2291,1762;, + 3;2143,2430,2142;, + 3;2143,2429,2430;, + 3;2144,2159,2143;, + 3;2144,2158,2159;, + 3;2145,2705,2144;, + 3;2145,2704,2705;, + 3;2146,2331,4331;, + 3;2146,2330,2331;, + 3;1760,2143,2142;, + 3;1760,2144,2143;, + 3;1760,2145,2144;, + 3;1760,4330,2145;, + 3;2145,4330,4153;, + 3;2147,4332,4333;, + 3;2147,2320,4332;, + 3;2148,2342,2147;, + 3;2148,2341,2342;, + 3;2149,2363,2148;, + 3;2149,2369,2363;, + 3;4333,2361,2149;, + 3;4333,4173,2361;, + 3;4333,2148,2147;, + 3;4333,2149,2148;, + 3;2150,2429,2159;, + 3;2150,2428,2429;, + 3;2151,2465,2150;, + 3;2151,2464,2465;, + 3;2152,4334,4335;, + 3;2152,2489,4334;, + 3;2153,2456,2152;, + 3;2153,2455,2456;, + 3;4336,2500,2153;, + 3;4336,4337,2500;, + 3;2155,2474,2154;, + 3;2155,2473,2474;, + 3;2156,2436,2155;, + 3;2156,2435,2436;, + 3;2158,2706,2157;, + 3;2158,2705,2706;, + 3;2158,2154,4338;, + 3;2158,4338,4339;, + 3;2158,4339,2151;, + 3;2158,2151,2150;, + 3;2158,2150,2159;, + 3;2154,2158,2155;, + 3;2155,2158,2157;, + 3;2155,2157,2156;, + 3;2160,2726,2169;, + 3;2160,2732,2726;, + 3;2161,2738,2160;, + 3;2161,2737,2738;, + 3;2162,2741,2161;, + 3;2162,2740,2741;, + 3;2163,2283,2162;, + 3;2163,2287,2283;, + 3;2164,2231,2163;, + 3;2164,2230,2231;, + 3;2165,2249,2164;, + 3;2165,2248,2249;, + 3;2166,2243,2165;, + 3;2166,2242,2243;, + 3;2167,2236,2166;, + 3;2167,2235,2236;, + 3;2168,2754,2235;, + 3;2168,2758,2754;, + 3;2169,2749,2168;, + 3;2169,2753,2749;, + 3;2167,2165,2164;, + 3;2167,2164,2163;, + 3;2167,2163,2168;, + 3;2168,2163,2162;, + 3;2168,2162,2169;, + 3;2169,2162,2161;, + 3;2169,2161,2160;, + 3;2165,2167,2166;, + 3;2170,2239,2176;, + 3;2170,2238,2239;, + 3;2171,2259,2170;, + 3;2171,2258,2259;, + 3;2172,2255,2171;, + 3;2172,2254,2255;, + 3;2175,2197,2174;, + 3;2175,2196,2197;, + 3;2176,2185,2175;, + 3;2176,2184,2185;, + 3;2171,2176,2172;, + 3;2172,2176,2174;, + 3;2172,2174,2173;, + 3;2174,2176,2175;, + 3;2176,2171,2170;, + 3;2177,2183,2182;, + 3;2177,2187,2183;, + 3;2179,2189,2178;, + 3;2179,2188,2189;, + 3;2180,2205,2179;, + 3;2180,2204,2205;, + 3;2181,2724,2180;, + 3;2181,2723,2724;, + 3;2182,2232,2181;, + 3;2182,2240,2232;, + 3;2179,2178,2180;, + 3;2180,2178,2177;, + 3;2180,2177,2182;, + 3;2180,2182,2181;, + 3;2184,2240,2183;, + 3;2184,2239,2240;, + 3;2186,2196,2185;, + 3;2186,2195,2196;, + 3;2185,2187,2186;, + 3;2187,2185,2183;, + 3;2183,2185,2184;, + 3;2188,2206,2193;, + 3;2188,2205,2206;, + 3;2193,2458,2192;, + 3;2193,2457,2458;, + 3;2189,2193,2192;, + 3;2189,2192,2190;, + 3;2190,2192,2191;, + 3;2193,2189,2188;, + 3;2199,2195,2194;, + 3;2195,2199,2198;, + 3;2195,2198,2197;, + 3;2195,2197,2196;, + 3;2200,2211,4328;, + 3;2203,4340,2212;, + 3;2201,2700,2200;, + 3;2201,2699,2700;, + 3;2202,2713,2201;, + 3;2202,2712,2713;, + 3;4328,2201,2200;, + 3;2201,4328,2202;, + 3;2204,2725,2213;, + 3;2204,2724,2725;, + 3;2207,2457,2206;, + 3;2207,2460,2457;, + 3;2209,2391,2208;, + 3;2209,2396,2391;, + 3;2211,2701,2210;, + 3;2211,2700,2701;, + 3;2205,2207,2206;, + 3;2207,2205,2204;, + 3;2207,2204,4318;, + 3;4318,2204,4340;, + 3;2208,2211,2209;, + 3;2209,2211,2210;, + 3;4340,2204,2212;, + 3;2212,2204,2213;, + 3;2216,2222,2215;, + 3;2216,2226,2222;, + 3;2217,2267,2216;, + 3;2217,2266,2267;, + 3;2218,2265,2217;, + 3;2218,2264,2265;, + 3;2219,2228,2218;, + 3;2219,2227,2228;, + 3;2220,2286,2219;, + 3;2220,2285,2286;, + 3;2218,2216,2219;, + 3;2219,2216,2220;, + 3;2220,2216,2215;, + 3;2220,2215,2221;, + 3;2221,2215,2214;, + 3;2216,2218,2217;, + 3;2225,2272,2224;, + 3;2225,2271,2272;, + 3;2226,2268,2225;, + 3;2226,2267,2268;, + 3;2222,2226,2225;, + 3;2222,2225,2224;, + 3;2222,2224,2223;, + 3;2227,2287,2231;, + 3;2227,2286,2287;, + 3;2229,2264,2228;, + 3;2229,2263,2264;, + 3;2230,2250,2229;, + 3;2230,2249,2250;, + 3;2227,2231,2228;, + 3;2228,2231,2229;, + 3;2229,2231,2230;, + 3;2233,2723,2232;, + 3;2233,2722,2723;, + 3;2234,2761,2233;, + 3;2234,2760,2761;, + 3;2235,2754,2234;, + 3;2234,2754,2755;, + 3;2237,2242,2236;, + 3;2237,2241,2242;, + 3;2238,2260,2237;, + 3;2238,2259,2260;, + 3;2237,2236,2238;, + 3;2238,2236,2235;, + 3;2238,2235,2239;, + 3;2239,2235,2234;, + 3;2239,2234,2232;, + 3;2239,2232,2240;, + 3;2232,2234,2233;, + 3;2241,2256,2245;, + 3;2241,2260,2256;, + 3;2244,2248,2243;, + 3;2244,2247,2248;, + 3;2245,2276,2244;, + 3;2245,2282,2276;, + 3;2242,2241,2243;, + 3;2243,2241,2244;, + 3;2244,2241,2245;, + 3;2246,2263,2250;, + 3;2246,2262,2263;, + 3;2247,2277,2246;, + 3;2247,2276,2277;, + 3;2246,2250,2247;, + 3;2247,2250,2249;, + 3;2247,2249,2248;, + 3;2251,2258,2255;, + 3;2251,2257,2258;, + 3;2252,2281,2251;, + 3;2252,2280,2281;, + 3;2253,2274,2252;, + 3;2253,2273,2274;, + 3;2255,2252,2251;, + 3;2252,2255,2254;, + 3;2252,2254,2253;, + 3;2257,2282,2256;, + 3;2257,2281,2282;, + 3;2257,2259,2258;, + 3;2259,2257,2256;, + 3;2259,2256,2260;, + 3;2261,2266,2265;, + 3;2261,2270,2266;, + 3;2262,2278,2261;, + 3;2262,2277,2278;, + 3;2265,2263,2262;, + 3;2265,2262,2261;, + 3;2263,2265,2264;, + 3;2269,2271,2268;, + 3;2269,2275,2271;, + 3;2270,2279,2269;, + 3;2270,2278,2279;, + 3;2270,2269,2268;, + 3;2270,2268,2266;, + 3;2266,2268,2267;, + 3;2275,2280,2274;, + 3;2275,2279,2280;, + 3;2275,2273,2271;, + 3;2271,2273,2272;, + 3;2273,2275,2274;, + 3;2279,2278,2280;, + 3;2280,2278,2282;, + 3;2280,2282,2281;, + 3;2282,2278,2276;, + 3;2276,2278,2277;, + 3;2284,2740,2283;, + 3;2284,2739,2740;, + 3;2286,2283,2287;, + 3;2283,2286,2285;, + 3;2283,2285,2284;, + 3;2288,1883,1762;, + 3;2288,2748,1883;, + 3;2289,2450,2288;, + 3;2289,2449,2450;, + 3;2290,2297,2289;, + 3;2290,2300,2297;, + 3;2291,2431,2290;, + 3;2291,2430,2431;, + 3;1762,2289,2288;, + 3;1762,2290,2289;, + 3;1762,2291,2290;, + 3;2292,2501,2296;, + 3;2292,2506,2501;, + 3;2293,2453,2292;, + 3;2293,2452,2453;, + 3;2294,2491,2293;, + 3;2294,2490,2491;, + 3;2295,2317,2294;, + 3;2295,2316,2317;, + 3;2296,2482,2295;, + 3;2296,2485,2482;, + 3;2293,2296,2294;, + 3;2294,2296,2295;, + 3;2296,2293,2292;, + 3;2298,2449,2297;, + 3;2298,2448,2449;, + 3;2299,2467,2298;, + 3;2299,2466,2467;, + 3;2300,2432,2299;, + 3;2300,2431,2432;, + 3;2297,2299,2298;, + 3;2299,2297,2300;, + 3;2301,2472,2308;, + 3;2301,2476,2472;, + 3;2302,2478,2301;, + 3;2302,2477,2478;, + 3;2303,2444,2302;, + 3;2303,2443,2444;, + 3;2304,2314,2303;, + 3;2304,2313,2314;, + 3;2305,2751,2304;, + 3;2305,2750,2751;, + 3;2306,2757,2305;, + 3;2306,2756,2757;, + 3;2307,2759,2306;, + 3;2307,2764,2759;, + 3;2308,2438,2307;, + 3;2308,2437,2438;, + 3;2306,2302,2307;, + 3;2307,2302,2301;, + 3;2307,2301,2308;, + 3;2302,2306,2305;, + 3;2302,2305,2304;, + 3;2302,2304,2303;, + 3;4341,2490,2317;, + 3;4341,4342,2490;, + 3;2310,2469,2309;, + 3;2310,2468,2469;, + 3;2311,2447,2310;, + 3;2311,2446,2447;, + 3;2312,2728,2311;, + 3;2312,2727,2728;, + 3;2313,2752,2312;, + 3;2313,2751,2752;, + 3;2315,2443,2314;, + 3;2315,2442,2443;, + 3;4343,2483,2315;, + 3;2316,2482,4344;, + 3;2312,2315,2314;, + 3;2312,2314,2313;, + 3;2315,2312,2311;, + 3;2315,2311,4343;, + 3;4343,2311,2310;, + 3;2316,4345,2317;, + 3;2317,4345,4341;, + 3;4146,2424,2318;, + 3;4146,4346,2424;, + 3;2319,2544,2326;, + 3;2319,2549,2544;, + 3;2320,2343,2319;, + 3;2320,2342,2343;, + 3;2321,4347,4332;, + 3;2321,2334,4347;, + 3;2322,2719,2321;, + 3;2322,2718,2719;, + 3;2323,2542,2322;, + 3;2323,2541,2542;, + 3;2324,2569,2323;, + 3;2324,2568,2569;, + 3;2325,2563,2324;, + 3;2325,2562,2563;, + 3;2326,2556,2325;, + 3;2326,2561,2556;, + 3;4332,2322,2321;, + 3;4332,2323,2322;, + 3;4332,2324,2323;, + 3;4332,2325,2324;, + 3;4332,2326,2325;, + 3;4332,2319,2326;, + 3;4332,2320,2319;, + 3;4175,2335,2329;, + 3;4175,4348,2335;, + 3;2327,4173,4175;, + 3;2327,2362,4173;, + 3;2328,2368,2327;, + 3;2328,2367,2368;, + 3;2329,2353,2328;, + 3;2329,2352,2353;, + 3;4175,2328,2327;, + 3;4175,2329,2328;, + 3;2330,4346,4347;, + 3;2330,2425,4346;, + 3;2332,4331,2331;, + 3;2332,2703,4331;, + 3;2333,2710,2332;, + 3;2333,2709,2710;, + 3;2334,2715,2333;, + 3;2334,2719,2715;, + 3;4347,2331,2330;, + 3;4347,2332,2331;, + 3;4347,2333,2332;, + 3;4347,2334,2333;, + 3;2336,2352,2335;, + 3;2336,2351,2352;, + 3;2337,2350,2336;, + 3;2337,2349,2350;, + 3;2338,2375,2337;, + 3;2338,2379,2375;, + 3;4348,2388,2338;, + 3;4348,4349,2388;, + 3;4348,2336,2335;, + 3;4348,2337,2336;, + 3;4348,2338,2337;, + 3;2339,2549,2343;, + 3;2339,2548,2549;, + 3;2340,2551,2339;, + 3;2340,2550,2551;, + 3;2341,2364,2340;, + 3;2341,2363,2364;, + 3;2341,2340,2339;, + 3;2341,2339,2342;, + 3;2342,2339,2343;, + 3;2344,2351,2350;, + 3;2344,2356,2351;, + 3;2345,2518,2344;, + 3;2345,2517,2518;, + 3;2346,2519,2345;, + 3;2346,2523,2519;, + 3;2347,2524,2346;, + 3;2347,2530,2524;, + 3;2348,2373,2347;, + 3;2348,2372,2373;, + 3;2349,2376,2348;, + 3;2349,2375,2376;, + 3;2349,2346,2345;, + 3;2349,2345,2350;, + 3;2350,2345,2344;, + 3;2346,2349,2348;, + 3;2346,2348,2347;, + 3;2354,2367,2353;, + 3;2354,2366,2367;, + 3;2355,2507,2354;, + 3;2355,2512,2507;, + 3;2356,2513,2355;, + 3;2356,2518,2513;, + 3;2353,2355,2354;, + 3;2355,2353,2356;, + 3;2356,2353,2352;, + 3;2356,2352,2351;, + 3;2358,2381,2357;, + 3;2358,2380,2381;, + 3;2359,2535,2358;, + 3;2359,2534,2535;, + 3;2360,2538,2359;, + 3;2360,2537,2538;, + 3;2357,2360,2358;, + 3;2358,2360,2359;, + 3;2362,2369,2361;, + 3;2362,2368,2369;, + 3;4173,2362,2361;, + 3;2365,2550,2364;, + 3;2365,2555,2550;, + 3;2366,2508,2365;, + 3;2366,2507,2508;, + 3;2365,2364,2366;, + 3;2366,2364,2369;, + 3;2366,2369,2368;, + 3;2366,2368,2367;, + 3;2369,2364,2363;, + 3;2370,2531,2374;, + 3;2370,2536,2531;, + 3;2371,2385,2370;, + 3;2371,2384,2385;, + 3;2372,2377,2371;, + 3;2372,2376,2377;, + 3;2374,2530,2373;, + 3;2374,2529,2530;, + 3;2374,2373,2372;, + 3;2374,2372,2371;, + 3;2374,2371,2370;, + 3;2378,2384,2377;, + 3;2378,2383,2384;, + 3;2379,2389,2378;, + 3;2379,2388,2389;, + 3;2379,2376,2375;, + 3;2376,2379,2377;, + 3;2377,2379,2378;, + 3;2380,2536,2385;, + 3;2380,2535,2536;, + 3;2383,2390,2382;, + 3;2383,2389,2390;, + 3;2382,2380,2385;, + 3;2382,2385,2383;, + 3;2383,2385,2384;, + 3;2380,2382,2381;, + 3;4350,2427,2387;, + 3;4350,1813,2427;, + 3;4349,2389,2388;, + 3;4349,2390,2389;, + 3;4349,4329,2390;, + 3;4350,2387,2386;, + 3;2393,2397,2392;, + 3;2393,2401,2397;, + 3;2395,2412,2394;, + 3;2395,2411,2412;, + 3;4302,2396,4323;, + 3;2396,4302,2393;, + 3;2396,2393,2391;, + 3;2391,2393,2392;, + 3;4317,2397,4313;, + 3;4313,2397,2400;, + 3;2400,2397,2401;, + 3;2402,2410,2405;, + 3;2402,2409,2410;, + 3;2403,2414,2402;, + 3;2403,2413,2414;, + 3;2404,2418,2403;, + 3;2404,2417,2418;, + 3;4351,2419,2404;, + 3;4351,4306,2419;, + 3;4352,4207,4204;, + 3;4352,4353,4207;, + 3;4351,2402,2405;, + 3;4351,2403,2402;, + 3;4351,2404,2403;, + 3;2408,2423,2407;, + 3;2408,2422,2423;, + 3;4354,2415,2408;, + 3;4354,4355,2415;, + 3;4356,4357,4358;, + 3;1787,1813,4359;, + 3;1787,2412,2411;, + 3;1787,4300,2412;, + 3;4356,2407,2406;, + 3;4356,2408,2407;, + 3;4356,4354,2408;, + 3;4356,4358,4354;, + 3;2413,4311,4360;, + 3;2413,2418,4311;, + 3;88,2422,2415;, + 3;88,21,2422;, + 3;4360,2414,2413;, + 3;88,2415,4355;, + 3;2417,2420,2416;, + 3;2417,2419,2420;, + 3;4311,2418,2416;, + 3;2416,2418,2417;, + 3;4306,2420,2419;, + 3;4306,2421,2420;, + 3;21,2423,2422;, + 3;4346,2425,2424;, + 3;2428,2461,2433;, + 3;2428,2465,2461;, + 3;2433,2466,2432;, + 3;2433,2471,2466;, + 3;2429,2428,2430;, + 3;2430,2428,2433;, + 3;2430,2433,2431;, + 3;2431,2433,2432;, + 3;2434,2765,2439;, + 3;2434,2768,2765;, + 3;2437,2473,2436;, + 3;2437,2472,2473;, + 3;2439,2764,2438;, + 3;2439,2763,2764;, + 3;2436,2435,2437;, + 3;2437,2435,2434;, + 3;2437,2434,2439;, + 3;2437,2439,2438;, + 3;2440,2477,2444;, + 3;2440,2481,2477;, + 3;2441,2503,2440;, + 3;2441,2502,2503;, + 3;2442,2484,2441;, + 3;2442,2483,2484;, + 3;2442,2441,2443;, + 3;2443,2441,2444;, + 3;2444,2441,2440;, + 3;2445,2748,2450;, + 3;2445,2747,2748;, + 3;2446,2729,2445;, + 3;2446,2728,2729;, + 3;2448,2468,2447;, + 3;2448,2467,2468;, + 3;2446,2445,2447;, + 3;2447,2445,2448;, + 3;2448,2445,2449;, + 3;2449,2445,2450;, + 3;2451,2489,2456;, + 3;2451,2488,2489;, + 3;2452,2492,2451;, + 3;2452,2491,2492;, + 3;2454,2506,2453;, + 3;2454,2505,2506;, + 3;2455,2496,2454;, + 3;2455,2500,2496;, + 3;2456,2454,2451;, + 3;2451,2454,2453;, + 3;2451,2453,2452;, + 3;2454,2456,2455;, + 3;2460,2458,2457;, + 3;2458,2460,2459;, + 3;2462,2471,2461;, + 3;2462,2470,2471;, + 3;2463,2494,2462;, + 3;2463,2493,2494;, + 3;2464,2487,2463;, + 3;2464,2486,2487;, + 3;2465,2463,2461;, + 3;2461,2463,2462;, + 3;2463,2465,2464;, + 3;2470,2495,2469;, + 3;2470,2494,2495;, + 3;2467,2469,2468;, + 3;2469,2467,2470;, + 3;2470,2467,2466;, + 3;2470,2466,2471;, + 3;2475,2499,2474;, + 3;2475,2498,2499;, + 3;2476,2479,2475;, + 3;2476,2478,2479;, + 3;2474,2473,2475;, + 3;2475,2473,2472;, + 3;2475,2472,2476;, + 3;2480,2498,2479;, + 3;2480,2497,2498;, + 3;2481,2504,2480;, + 3;2481,2503,2504;, + 3;2478,2480,2479;, + 3;2480,2478,2481;, + 3;2481,2478,2477;, + 3;2485,4361,4362;, + 3;2485,2501,4361;, + 3;2482,4362,4344;, + 3;4362,2482,2485;, + 3;2488,4363,4364;, + 3;2488,2492,4363;, + 3;4334,2489,2488;, + 3;4334,2488,4364;, + 3;4342,4365,2490;, + 3;2490,4365,2491;, + 3;2491,4365,4363;, + 3;2491,4363,2492;, + 3;4366,2505,2496;, + 3;4366,4367,2505;, + 3;4337,4368,2500;, + 3;2500,4368,2496;, + 3;2496,4368,4366;, + 3;4369,2506,4367;, + 3;4367,2506,2505;, + 3;2506,4369,2501;, + 3;2501,4369,4361;, + 3;2509,2555,2508;, + 3;2509,2554,2555;, + 3;2510,2627,2509;, + 3;2510,2626,2627;, + 3;2511,2597,2510;, + 3;2511,2596,2597;, + 3;2512,2514,2511;, + 3;2512,2513,2514;, + 3;2510,2508,2511;, + 3;2511,2508,2507;, + 3;2511,2507,2512;, + 3;2508,2510,2509;, + 3;2515,2596,2514;, + 3;2515,2595,2596;, + 3;2516,2605,2515;, + 3;2516,2604,2605;, + 3;2517,2520,2516;, + 3;2517,2519,2520;, + 3;2516,2513,2518;, + 3;2516,2518,2517;, + 3;2513,2516,2515;, + 3;2513,2515,2514;, + 3;2521,2604,2520;, + 3;2521,2603,2604;, + 3;2522,2609,2521;, + 3;2522,2608,2609;, + 3;2523,2525,2522;, + 3;2523,2524,2525;, + 3;2519,2522,2521;, + 3;2519,2521,2520;, + 3;2522,2519,2523;, + 3;2526,2608,2525;, + 3;2526,2607,2608;, + 3;2527,2619,2526;, + 3;2527,2618,2619;, + 3;2528,2575,2527;, + 3;2528,2574,2575;, + 3;2529,2532,2528;, + 3;2529,2531,2532;, + 3;2527,2526,2528;, + 3;2528,2526,2529;, + 3;2529,2526,2530;, + 3;2530,2526,2525;, + 3;2530,2525,2524;, + 3;2533,2574,2532;, + 3;2533,2580,2574;, + 3;2534,2539,2533;, + 3;2534,2538,2539;, + 3;2536,2534,2531;, + 3;2531,2534,2532;, + 3;2532,2534,2533;, + 3;2534,2536,2535;, + 3;2540,2580,2539;, + 3;2540,2579,2580;, + 3;2541,2570,2540;, + 3;2541,2569,2570;, + 3;2543,2718,2542;, + 3;2543,2717,2718;, + 3;2543,2539,2538;, + 3;2543,2538,2537;, + 3;2539,2543,2540;, + 3;2540,2543,2542;, + 3;2540,2542,2541;, + 3;2545,2561,2544;, + 3;2545,2560,2561;, + 3;2546,2632,2545;, + 3;2546,2631,2632;, + 3;2547,2624,2546;, + 3;2547,2623,2624;, + 3;2548,2552,2547;, + 3;2548,2551,2552;, + 3;2546,2544,2549;, + 3;2546,2549,2547;, + 3;2547,2549,2548;, + 3;2544,2546,2545;, + 3;2553,2623,2552;, + 3;2553,2622,2623;, + 3;2554,2628,2553;, + 3;2554,2627,2628;, + 3;2554,2550,2555;, + 3;2550,2554,2551;, + 3;2551,2554,2553;, + 3;2551,2553,2552;, + 3;2557,2562,2556;, + 3;2557,2567,2562;, + 3;2558,2583,2557;, + 3;2558,2582,2583;, + 3;2559,2592,2558;, + 3;2559,2591,2592;, + 3;2560,2633,2559;, + 3;2560,2632,2633;, + 3;2560,2559,2557;, + 3;2560,2557,2556;, + 3;2560,2556,2561;, + 3;2557,2559,2558;, + 3;2564,2568,2563;, + 3;2564,2573,2568;, + 3;2565,2645,2564;, + 3;2565,2644,2645;, + 3;2566,2639,2565;, + 3;2566,2638,2639;, + 3;2567,2584,2566;, + 3;2567,2583,2584;, + 3;2565,2567,2566;, + 3;2567,2565,2564;, + 3;2567,2564,2562;, + 3;2562,2564,2563;, + 3;2571,2579,2570;, + 3;2571,2578,2579;, + 3;2572,2667,2571;, + 3;2572,2666,2667;, + 3;2573,2640,2572;, + 3;2573,2645,2640;, + 3;2572,2568,2573;, + 3;2568,2572,2569;, + 3;2569,2572,2571;, + 3;2569,2571,2570;, + 3;2576,2618,2575;, + 3;2576,2617,2618;, + 3;2577,2648,2576;, + 3;2577,2647,2648;, + 3;2578,2661,2577;, + 3;2578,2667,2661;, + 3;2576,2580,2577;, + 3;2577,2580,2579;, + 3;2577,2579,2578;, + 3;2580,2576,2574;, + 3;2574,2576,2575;, + 3;2581,2612,2589;, + 3;2581,2611,2612;, + 3;2582,2593,2581;, + 3;2582,2592,2593;, + 3;2585,2638,2584;, + 3;2585,2637,2638;, + 3;2586,2673,2585;, + 3;2586,2672,2673;, + 3;2587,2670,2586;, + 3;2587,2669,2670;, + 3;2588,2651,2587;, + 3;2588,2650,2651;, + 3;2589,2614,2588;, + 3;2589,2613,2614;, + 3;2584,2587,2585;, + 3;2585,2587,2586;, + 3;2587,2584,2582;, + 3;2587,2582,2581;, + 3;2587,2581,2588;, + 3;2588,2581,2589;, + 3;2582,2584,2583;, + 3;2590,2602,2594;, + 3;2590,2601,2602;, + 3;2591,2634,2590;, + 3;2591,2633,2634;, + 3;2594,2611,2593;, + 3;2594,2610,2611;, + 3;2592,2591,2593;, + 3;2593,2591,2590;, + 3;2593,2590,2594;, + 3;2595,2606,2599;, + 3;2595,2605,2606;, + 3;2598,2626,2597;, + 3;2598,2629,2626;, + 3;2599,2621,2598;, + 3;2599,2620,2621;, + 3;2597,2596,2598;, + 3;2598,2596,2599;, + 3;2599,2596,2595;, + 3;2600,2620,2606;, + 3;2600,2625,2620;, + 3;2601,2630,2600;, + 3;2601,2634,2630;, + 3;2603,2610,2602;, + 3;2603,2609,2610;, + 3;2604,2602,2605;, + 3;2605,2602,2601;, + 3;2605,2601,2606;, + 3;2606,2601,2600;, + 3;2602,2604,2603;, + 3;2607,2613,2612;, + 3;2607,2619,2613;, + 3;2609,2608,2610;, + 3;2610,2608,2612;, + 3;2610,2612,2611;, + 3;2612,2608,2607;, + 3;2615,2650,2614;, + 3;2615,2654,2650;, + 3;2616,2656,2615;, + 3;2616,2655,2656;, + 3;2617,2649,2616;, + 3;2617,2648,2649;, + 3;2618,2616,2619;, + 3;2619,2616,2615;, + 3;2619,2615,2614;, + 3;2619,2614,2613;, + 3;2616,2618,2617;, + 3;2622,2629,2621;, + 3;2622,2628,2629;, + 3;2625,2631,2624;, + 3;2625,2630,2631;, + 3;2624,2623,2625;, + 3;2625,2623,2621;, + 3;2625,2621,2620;, + 3;2621,2623,2622;, + 3;2627,2626,2628;, + 3;2628,2626,2629;, + 3;2633,2632,2631;, + 3;2633,2631,2630;, + 3;2633,2630,2634;, + 3;2635,2644,2639;, + 3;2635,2643,2644;, + 3;2636,2678,2635;, + 3;2636,2677,2678;, + 3;2637,2674,2636;, + 3;2637,2673,2674;, + 3;2638,2637,2639;, + 3;2639,2637,2635;, + 3;2635,2637,2636;, + 3;2641,2666,2640;, + 3;2641,2665,2666;, + 3;2642,2695,2641;, + 3;2642,2694,2695;, + 3;2643,2679,2642;, + 3;2643,2678,2679;, + 3;2640,2645,2644;, + 3;2640,2644,2643;, + 3;2640,2643,2641;, + 3;2641,2643,2642;, + 3;2646,2655,2649;, + 3;2646,2660,2655;, + 3;2647,2662,2646;, + 3;2647,2661,2662;, + 3;2648,2647,2649;, + 3;2649,2647,2646;, + 3;2652,2669,2651;, + 3;2652,2668,2669;, + 3;2653,2688,2652;, + 3;2653,2687,2688;, + 3;2654,2657,2653;, + 3;2654,2656,2657;, + 3;2650,2654,2653;, + 3;2650,2653,2651;, + 3;2651,2653,2652;, + 3;2658,2687,2657;, + 3;2658,2686,2687;, + 3;2659,2693,2658;, + 3;2659,2692,2693;, + 3;2660,2663,2659;, + 3;2660,2662,2663;, + 3;2656,2659,2657;, + 3;2657,2659,2658;, + 3;2659,2656,2660;, + 3;2660,2656,2655;, + 3;2664,2692,2663;, + 3;2664,2691,2692;, + 3;2665,2696,2664;, + 3;2665,2695,2696;, + 3;2662,2666,2665;, + 3;2662,2665,2663;, + 3;2663,2665,2664;, + 3;2666,2662,2667;, + 3;2667,2662,2661;, + 3;2668,2683,2671;, + 3;2668,2688,2683;, + 3;2671,2672,2670;, + 3;2671,2676,2672;, + 3;2671,2670,2668;, + 3;2668,2670,2669;, + 3;2675,2677,2674;, + 3;2675,2682,2677;, + 3;2676,2684,2675;, + 3;2676,2683,2684;, + 3;2675,2674,2676;, + 3;2676,2674,2672;, + 3;2672,2674,2673;, + 3;2680,2694,2679;, + 3;2680,2697,2694;, + 3;2681,2690,2680;, + 3;2681,2689,2690;, + 3;2682,2685,2681;, + 3;2682,2684,2685;, + 3;2680,2679,2681;, + 3;2681,2679,2682;, + 3;2682,2679,2677;, + 3;2677,2679,2678;, + 3;2686,2689,2685;, + 3;2686,2693,2689;, + 3;2685,2683,2688;, + 3;2685,2688,2686;, + 3;2686,2688,2687;, + 3;2683,2685,2684;, + 3;2691,2697,2690;, + 3;2691,2696,2697;, + 3;2689,2693,2690;, + 3;2690,2693,2691;, + 3;2691,2693,2692;, + 3;2697,2696,2694;, + 3;2694,2696,2695;, + 3;2699,2714,2698;, + 3;2699,2713,2714;, + 3;2701,2698,2702;, + 3;2698,2701,2699;, + 3;2699,2701,2700;, + 3;2703,2711,2707;, + 3;2703,2710,2711;, + 3;2704,2706,2705;, + 3;2707,4331,2703;, + 3;2706,2704,4325;, + 3;2709,2716,2708;, + 3;2709,2715,2716;, + 3;2709,2712,2711;, + 3;2709,2711,2710;, + 3;2712,2709,2713;, + 3;2713,2709,2714;, + 3;2714,2709,2708;, + 3;2718,2717,2716;, + 3;2718,2716,2719;, + 3;2719,2716,2715;, + 3;2721,2767,2720;, + 3;2721,2766,2767;, + 3;2722,2761,2721;, + 3;2721,2761,2762;, + 3;2722,2721,2720;, + 3;2722,2720,2725;, + 3;2722,2725,2723;, + 3;2723,2725,2724;, + 3;2727,2753,2726;, + 3;2727,2752,2753;, + 3;2730,2747,2729;, + 3;2730,2746,2747;, + 3;2732,2733,2731;, + 3;2732,2738,2733;, + 3;2728,2731,2729;, + 3;2729,2731,2730;, + 3;2731,2728,2727;, + 3;2731,2727,2732;, + 3;2732,2727,2726;, + 3;2735,3387,2734;, + 3;2735,3386,3387;, + 3;2736,2824,2735;, + 3;2736,2823,2824;, + 3;2737,2742,2736;, + 3;2737,2741,2742;, + 3;2734,2733,2735;, + 3;2735,2733,2738;, + 3;2735,2738,2736;, + 3;2736,2738,2737;, + 3;2743,2823,2742;, + 3;2743,2822,2823;, + 3;2744,2942,2743;, + 3;2744,2941,2942;, + 3;2742,2741,2744;, + 3;2742,2744,2743;, + 3;2744,2741,2739;, + 3;2739,2741,2740;, + 3;1883,2746,2745;, + 3;1883,2747,2746;, + 3;1883,2748,2747;, + 3;2750,2758,2749;, + 3;2750,2757,2758;, + 3;2753,2750,2749;, + 3;2750,2753,2751;, + 3;2751,2753,2752;, + 3;2756,2760,2755;, + 3;2756,2759,2760;, + 3;2757,2755,2758;, + 3;2758,2755,2754;, + 3;2755,2757,2756;, + 3;2763,2766,2762;, + 3;2763,2765,2766;, + 3;2759,2762,2761;, + 3;2759,2761,2760;, + 3;2762,2759,2764;, + 3;2762,2764,2763;, + 3;2765,2767,2766;, + 3;2767,2765,2768;, + 3;2771,3118,2770;, + 3;2771,3117,3118;, + 3;4370,2865,2771;, + 3;4370,4371,2865;, + 3;2773,3053,2772;, + 3;2773,3052,3053;, + 3;2774,3057,4372;, + 3;2773,4373,3058;, + 3;2774,2770,2769;, + 3;2770,2774,2771;, + 3;2771,2774,4372;, + 3;2771,4372,4370;, + 3;2775,3044,2780;, + 3;2775,3048,3044;, + 3;1886,3085,2775;, + 3;1886,1944,3085;, + 3;2776,1918,1886;, + 3;2776,3064,1918;, + 3;2777,4374,4375;, + 3;2777,3054,4374;, + 3;2778,2863,2777;, + 3;2778,2862,2863;, + 3;2779,3359,2778;, + 3;2779,3358,3359;, + 3;4376,2789,2779;, + 3;4376,4377,2789;, + 3;4378,2777,4375;, + 3;4378,2778,2777;, + 3;4378,2779,2778;, + 3;4378,4376,2779;, + 3;1886,2775,2780;, + 3;2781,3369,2788;, + 3;2781,3368,3369;, + 3;2782,2857,4379;, + 3;2781,4380,2858;, + 3;2783,2860,2782;, + 3;2783,2869,2860;, + 3;2784,3384,2783;, + 3;2784,3383,3384;, + 3;2785,3412,2784;, + 3;2785,3415,3412;, + 3;2786,3093,2785;, + 3;2786,3098,3093;, + 3;2787,2808,2786;, + 3;2787,2807,2808;, + 3;4381,3362,2787;, + 3;4381,4382,3362;, + 3;4381,2785,4379;, + 3;4379,2785,2784;, + 3;4379,2784,2782;, + 3;2782,2784,2783;, + 3;2785,4381,2786;, + 3;2786,4381,2787;, + 3;2790,3358,2789;, + 3;2790,3357,3358;, + 3;2791,3373,2790;, + 3;2791,3372,3373;, + 3;2792,3378,2791;, + 3;2792,3377,3378;, + 3;2793,3197,2792;, + 3;2793,3196,3197;, + 3;2794,3017,2793;, + 3;2794,3016,3017;, + 3;2795,3041,2794;, + 3;2795,3040,3041;, + 3;4377,3045,2795;, + 3;4377,4383,3045;, + 3;2794,2793,2795;, + 3;2795,2793,4377;, + 3;4377,2793,2792;, + 3;4377,2792,2789;, + 3;2789,2792,2791;, + 3;2789,2791,2790;, + 3;2797,4384,4385;, + 3;2802,2991,2987;, + 3;2798,4384,2797;, + 3;2798,3363,4384;, + 3;2799,2806,2798;, + 3;2799,2815,2806;, + 3;2800,3090,2799;, + 3;2800,3089,3090;, + 3;1891,2945,2800;, + 3;1891,1893,2945;, + 3;4253,4386,4387;, + 3;4253,2974,4386;, + 3;2802,3082,4253;, + 3;2802,3083,3082;, + 3;1891,4385,2801;, + 3;1891,2797,4385;, + 3;1891,2798,2797;, + 3;1891,2799,2798;, + 3;1891,2800,2799;, + 3;2803,4388,4389;, + 3;2803,3020,4388;, + 3;2804,3022,2803;, + 3;2804,3021,3022;, + 3;2805,2997,2804;, + 3;2805,2996,2997;, + 3;4389,2982,2805;, + 3;4389,4390,2982;, + 3;4389,2804,2803;, + 3;4389,2805,2804;, + 3;2807,3363,2806;, + 3;2807,3362,3363;, + 3;2809,3098,2808;, + 3;2809,3097,3098;, + 3;2810,3135,2809;, + 3;2810,3134,3135;, + 3;2811,4391,4392;, + 3;2811,3159,4391;, + 3;2812,3110,2811;, + 3;2812,3115,3110;, + 3;4393,3148,2812;, + 3;4393,4394,3148;, + 3;2814,3122,2813;, + 3;2814,3121,3122;, + 3;2815,3091,2814;, + 3;2815,3090,3091;, + 3;2806,2810,2809;, + 3;2806,2809,2807;, + 3;2807,2809,2808;, + 3;2810,2806,4395;, + 3;4395,2806,4396;, + 3;4396,2806,2813;, + 3;2813,2806,2814;, + 3;2814,2806,2815;, + 3;2816,3400,2825;, + 3;2816,3399,3400;, + 3;2817,3404,2816;, + 3;2816,3404,3405;, + 3;2818,2892,2817;, + 3;2818,2891,2892;, + 3;2819,2899,2818;, + 3;2819,2898,2899;, + 3;2820,2905,2819;, + 3;2820,2904,2905;, + 3;2821,2883,2820;, + 3;2821,2887,2883;, + 3;2822,2943,2821;, + 3;2822,2942,2943;, + 3;2825,3386,2824;, + 3;2825,3385,3386;, + 3;2817,2819,2818;, + 3;2819,2817,2820;, + 3;2820,2817,2821;, + 3;2821,2817,2816;, + 3;2821,2816,2822;, + 3;2822,2816,2825;, + 3;2822,2825,2823;, + 3;2823,2825,2824;, + 3;2826,2843,2832;, + 3;2826,2842,2843;, + 3;2827,2854,2826;, + 3;2827,2853,2854;, + 3;2830,2909,2829;, + 3;2830,2908,2909;, + 3;2831,2915,2830;, + 3;2831,2914,2915;, + 3;2832,2889,2831;, + 3;2832,2888,2889;, + 3;2830,2829,2832;, + 3;2830,2832,2831;, + 3;2832,2829,2827;, + 3;2832,2827,2826;, + 3;2827,2829,2828;, + 3;2833,2896,2838;, + 3;2833,2895,2896;, + 3;2834,3380,2833;, + 3;2834,3379,3380;, + 3;2835,2868,2834;, + 3;2835,2867,2868;, + 3;2836,2848,2835;, + 3;2836,2847,2848;, + 3;2838,2840,2837;, + 3;2838,2839,2840;, + 3;2835,2834,2836;, + 3;2836,2834,2837;, + 3;2837,2834,2838;, + 3;2838,2834,2833;, + 3;2839,2888,2843;, + 3;2839,2896,2888;, + 3;2842,2855,2841;, + 3;2842,2854,2855;, + 3;2842,2840,2839;, + 3;2842,2839,2843;, + 3;2840,2842,2841;, + 3;2844,3116,2849;, + 3;2844,3119,3116;, + 3;2849,2867,2848;, + 3;2849,2866,2867;, + 3;2847,2849,2848;, + 3;2849,2847,2844;, + 3;2844,2847,2846;, + 3;2844,2846,2845;, + 3;2851,2855,2852;, + 3;2852,2855,2853;, + 3;2853,2855,2854;, + 3;2855,2851,2850;, + 3;2856,3361,2859;, + 3;2856,3360,3361;, + 3;4380,2861,2856;, + 3;2857,2860,4397;, + 3;2859,3368,2858;, + 3;2859,3367,3368;, + 3;4380,2856,2859;, + 3;4380,2859,2858;, + 3;2862,3360,2861;, + 3;2862,3359,3360;, + 3;2864,3054,2863;, + 3;2864,3053,3054;, + 3;2866,3117,2865;, + 3;2866,3116,3117;, + 3;2869,3379,2868;, + 3;2869,3384,3379;, + 3;2867,2866,2865;, + 3;2867,2865,2868;, + 3;2868,2865,4371;, + 3;2868,4371,4397;, + 3;2868,4397,2860;, + 3;2868,2860,2869;, + 3;2861,2864,2863;, + 3;2861,2863,2862;, + 3;2873,2940,2872;, + 3;2873,2939,2940;, + 3;2874,2886,2873;, + 3;2874,2885,2886;, + 3;2875,2919,2874;, + 3;2875,2918,2919;, + 3;2876,2925,2875;, + 3;2876,2924,2925;, + 3;2877,2879,2876;, + 3;2877,2878,2879;, + 3;2874,2876,2875;, + 3;2876,2874,2873;, + 3;2876,2873,2872;, + 3;2876,2872,2877;, + 3;2877,2872,2871;, + 3;2877,2871,2870;, + 3;2880,2924,2879;, + 3;2880,2923,2924;, + 3;2881,2930,2880;, + 3;2881,2929,2930;, + 3;2878,2880,2879;, + 3;2880,2878,2881;, + 3;2881,2878,2882;, + 3;2884,2904,2883;, + 3;2884,2903,2904;, + 3;2885,2920,2884;, + 3;2885,2919,2920;, + 3;2887,2939,2886;, + 3;2887,2943,2939;, + 3;2886,2885,2887;, + 3;2887,2885,2884;, + 3;2887,2884,2883;, + 3;2890,2914,2889;, + 3;2890,2913,2914;, + 3;2891,2900,2890;, + 3;2891,2899,2900;, + 3;2893,3404,2817;, + 3;2893,3403,3404;, + 3;2894,3409,2893;, + 3;2894,3408,3409;, + 3;2895,3381,2894;, + 3;2895,3380,3381;, + 3;2890,2889,2891;, + 3;2891,2889,2892;, + 3;2892,2889,2888;, + 3;2892,2888,2893;, + 3;2893,2888,2895;, + 3;2893,2895,2894;, + 3;2895,2888,2896;, + 3;2897,2938,2901;, + 3;2897,2937,2938;, + 3;2898,2906,2897;, + 3;2898,2905,2906;, + 3;2901,2913,2900;, + 3;2901,2912,2913;, + 3;2899,2898,2900;, + 3;2900,2898,2897;, + 3;2900,2897,2901;, + 3;2902,2937,2906;, + 3;2902,2936,2937;, + 3;2903,2921,2902;, + 3;2903,2920,2921;, + 3;2902,2906,2903;, + 3;2903,2906,2904;, + 3;2904,2906,2905;, + 3;2907,2933,2911;, + 3;2907,2932,2933;, + 3;2908,2916,2907;, + 3;2908,2915,2916;, + 3;2911,2928,2910;, + 3;2911,2927,2928;, + 3;2908,2907,2911;, + 3;2908,2911,2909;, + 3;2909,2911,2910;, + 3;2912,2932,2916;, + 3;2912,2938,2932;, + 3;2916,2914,2912;, + 3;2912,2914,2913;, + 3;2914,2916,2915;, + 3;2917,2936,2921;, + 3;2917,2935,2936;, + 3;2918,2926,2917;, + 3;2918,2925,2926;, + 3;2918,2920,2919;, + 3;2920,2918,2921;, + 3;2921,2918,2917;, + 3;2922,2935,2926;, + 3;2922,2934,2935;, + 3;2923,2931,2922;, + 3;2923,2930,2931;, + 3;2926,2923,2922;, + 3;2923,2926,2925;, + 3;2923,2925,2924;, + 3;2927,2934,2931;, + 3;2927,2933,2934;, + 3;2931,2928,2927;, + 3;2928,2931,2930;, + 3;2928,2930,2929;, + 3;2934,2933,2935;, + 3;2935,2933,2938;, + 3;2935,2938,2937;, + 3;2935,2937,2936;, + 3;2938,2933,2932;, + 3;2939,2943,2942;, + 3;2939,2942,2940;, + 3;2940,2942,2941;, + 3;2944,3104,2947;, + 3;2944,3109,3104;, + 3;1893,3395,2944;, + 3;1893,2014,3395;, + 3;2946,3089,2945;, + 3;2946,3088,3089;, + 3;2947,2954,2946;, + 3;2947,2953,2954;, + 3;1893,2946,2945;, + 3;1893,2947,2946;, + 3;1893,2944,2947;, + 3;2948,3144,2952;, + 3;2948,3143,3144;, + 3;2949,2967,2948;, + 3;2949,2966,2967;, + 3;2950,3153,2949;, + 3;2950,3152,3153;, + 3;2951,3113,2950;, + 3;2951,3112,3113;, + 3;2952,3161,2951;, + 3;2952,3160,3161;, + 3;2950,2952,2951;, + 3;2952,2950,2949;, + 3;2952,2949,2948;, + 3;2953,3105,2956;, + 3;2953,3104,3105;, + 3;2955,3088,2954;, + 3;2955,3087,3088;, + 3;2956,3129,2955;, + 3;2956,3128,3129;, + 3;2953,2956,2955;, + 3;2953,2955,2954;, + 3;2957,3096,2964;, + 3;2957,3095,3096;, + 3;2958,3411,2957;, + 3;2958,3410,3411;, + 3;2959,3402,2958;, + 3;2959,3401,3402;, + 3;2960,3398,2959;, + 3;2960,3397,3398;, + 3;2961,2970,2960;, + 3;2961,2969,2970;, + 3;2962,3099,2961;, + 3;2962,3103,3099;, + 3;2963,3136,2962;, + 3;2963,3140,3136;, + 3;2964,3132,2963;, + 3;2964,3131,3132;, + 3;2958,2962,2959;, + 3;2959,2962,2960;, + 3;2960,2962,2961;, + 3;2962,2958,2957;, + 3;2962,2957,2963;, + 3;2963,2957,2964;, + 3;2965,3127,2973;, + 3;2965,3126,3127;, + 3;4398,3154,2965;, + 3;2966,3153,4399;, + 3;2968,3142,4400;, + 3;2967,4401,3143;, + 3;2969,3100,2968;, + 3;2969,3099,3100;, + 3;2971,3397,2970;, + 3;2971,3396,3397;, + 3;2972,3391,2971;, + 3;2972,3390,3391;, + 3;2973,3107,2972;, + 3;2973,3106,3107;, + 3;2971,2968,2972;, + 3;2972,2968,4400;, + 3;2972,4400,2973;, + 3;2973,4400,4398;, + 3;2973,4398,2965;, + 3;2968,2971,2969;, + 3;2969,2971,2970;, + 3;2974,4402,4386;, + 3;2974,3082,4402;, + 3;2975,2996,2982;, + 3;2975,3000,2996;, + 3;2976,3208,2975;, + 3;2976,3207,3208;, + 3;2977,3220,2976;, + 3;2977,3219,3220;, + 3;2978,3221,2977;, + 3;2978,3226,3221;, + 3;2979,3227,2978;, + 3;2979,3232,3227;, + 3;2980,3199,2979;, + 3;2980,3198,3199;, + 3;2981,3376,2980;, + 3;2981,3375,3376;, + 3;4390,2988,2981;, + 3;4390,4403,2988;, + 3;4390,2975,2982;, + 3;4390,2976,2975;, + 3;4390,2977,2976;, + 3;4390,2978,2977;, + 3;4390,2979,2978;, + 3;4390,2980,2979;, + 3;4390,2981,2980;, + 3;2983,3011,2986;, + 3;2983,3010,3011;, + 3;2984,3024,2983;, + 3;2984,3023,3024;, + 3;2985,3019,2984;, + 3;2985,3018,3019;, + 3;4404,3084,2985;, + 3;4404,4405,3084;, + 3;2986,4406,4404;, + 3;2986,2995,4406;, + 3;4404,2983,2986;, + 3;4404,2984,2983;, + 3;4404,2985,2984;, + 3;4403,3083,2987;, + 3;4403,4402,3083;, + 3;2989,3375,2988;, + 3;2989,3374,3375;, + 3;2990,3371,2989;, + 3;2990,3370,3371;, + 3;2991,3365,2990;, + 3;2991,3364,3365;, + 3;4403,2989,2988;, + 3;4403,2990,2989;, + 3;4403,2991,2990;, + 3;4403,2987,2991;, + 3;2992,4407,4406;, + 3;2992,3047,4407;, + 3;2993,3034,2992;, + 3;2993,3033,3034;, + 3;2994,3003,2993;, + 3;2994,3002,3003;, + 3;2995,3012,2994;, + 3;2995,3011,3012;, + 3;4406,2993,2992;, + 3;4406,2994,2993;, + 3;4406,2995,2994;, + 3;2998,3021,2997;, + 3;2998,3027,3021;, + 3;2999,3209,2998;, + 3;2999,3214,3209;, + 3;3000,3203,2999;, + 3;3000,3208,3203;, + 3;2997,2999,2998;, + 3;2999,2997,2996;, + 3;2999,2996,3000;, + 3;3001,3172,3007;, + 3;3001,3177,3172;, + 3;3002,3013,3001;, + 3;3002,3012,3013;, + 3;3004,3033,3003;, + 3;3004,3037,3033;, + 3;3005,3031,3004;, + 3;3005,3030,3031;, + 3;3006,3184,3005;, + 3;3006,3183,3184;, + 3;3007,3182,3006;, + 3;3007,3181,3182;, + 3;3003,3006,3004;, + 3;3004,3006,3005;, + 3;3006,3003,3007;, + 3;3007,3003,3002;, + 3;3007,3002,3001;, + 3;3008,3177,3013;, + 3;3008,3176,3177;, + 3;3009,3171,3008;, + 3;3009,3170,3171;, + 3;3010,3025,3009;, + 3;3010,3024,3025;, + 3;3010,3008,3013;, + 3;3010,3013,3011;, + 3;3011,3013,3012;, + 3;3008,3010,3009;, + 3;3014,3196,3017;, + 3;3014,3202,3196;, + 3;3015,3191,3014;, + 3;3015,3190,3191;, + 3;3016,3042,3015;, + 3;3016,3041,3042;, + 3;3016,3015,3017;, + 3;3017,3015,3014;, + 3;3018,4405,4388;, + 3;3018,3084,4405;, + 3;3020,3023,3019;, + 3;3020,3022,3023;, + 3;4388,3019,3018;, + 3;4388,3020,3019;, + 3;3026,3170,3025;, + 3;3026,3169,3170;, + 3;3027,3210,3026;, + 3;3027,3209,3210;, + 3;3026,3025,3027;, + 3;3027,3025,3022;, + 3;3027,3022,3021;, + 3;3022,3025,3023;, + 3;3023,3025,3024;, + 3;3028,3038,3032;, + 3;3028,3043,3038;, + 3;3029,3195,3028;, + 3;3029,3194,3195;, + 3;3030,3185,3029;, + 3;3030,3184,3185;, + 3;3032,3037,3031;, + 3;3032,3036,3037;, + 3;3029,3031,3030;, + 3;3031,3029,3032;, + 3;3032,3029,3028;, + 3;3035,3047,3034;, + 3;3035,3046,3047;, + 3;3036,3039,3035;, + 3;3036,3038,3039;, + 3;3034,3037,3036;, + 3;3034,3036,3035;, + 3;3037,3034,3033;, + 3;3040,3046,3039;, + 3;3040,3045,3046;, + 3;3043,3190,3042;, + 3;3043,3195,3190;, + 3;3040,3042,3041;, + 3;3042,3040,3043;, + 3;3043,3040,3039;, + 3;3043,3039,3038;, + 3;3048,1944,4408;, + 3;3048,3085,1944;, + 3;4408,3044,3048;, + 3;4407,3045,4383;, + 3;4407,3046,3045;, + 3;4407,3047,3046;, + 3;3050,3064,3049;, + 3;3050,3070,3064;, + 3;3052,3059,3051;, + 3;3052,3058,3059;, + 3;4297,3054,3051;, + 3;3051,3054,3053;, + 3;3051,3053,3052;, + 3;3054,4297,4374;, + 3;4373,4314,3058;, + 3;3058,4314,3055;, + 3;3058,3055,3059;, + 3;3060,3073,3063;, + 3;3060,3072,3073;, + 3;3061,3066,3060;, + 3;3061,3065,3066;, + 3;4409,3086,3061;, + 3;4295,4293,4410;, + 3;3062,4308,4409;, + 3;3062,3077,4308;, + 3;3063,3075,3062;, + 3;3063,3074,3075;, + 3;4409,3063,3062;, + 3;4409,3060,3063;, + 3;4409,3061,3060;, + 3;4411,1944,1918;, + 3;4411,4412,1944;, + 3;3067,4413,4414;, + 3;3067,3071,4413;, + 3;3068,3081,3067;, + 3;3068,3080,3081;, + 3;4415,4414,4416;, + 3;4415,3067,4414;, + 3;4415,3068,3067;, + 3;4415,3069,3068;, + 3;1918,3070,4299;, + 3;1918,3064,3070;, + 3;3071,151,3755;, + 3;3071,3081,151;, + 3;4417,3074,3073;, + 3;4417,4309,3074;, + 3;3755,4413,3071;, + 3;4417,3073,3072;, + 3;3076,3077,3075;, + 3;3076,3079,3077;, + 3;4309,3076,3074;, + 3;3074,3076,3075;, + 3;4308,3079,3078;, + 3;4308,3077,3079;, + 3;151,3081,3080;, + 3;4402,3082,3083;, + 3;3087,3130,3092;, + 3;3087,3129,3130;, + 3;3092,3121,3091;, + 3;3092,3120,3121;, + 3;3090,3089,3091;, + 3;3091,3089,3092;, + 3;3092,3089,3088;, + 3;3092,3088,3087;, + 3;3094,3415,3093;, + 3;3094,3414,3415;, + 3;3095,3406,3094;, + 3;3095,3411,3406;, + 3;3097,3131,3096;, + 3;3097,3135,3131;, + 3;3097,3096,3098;, + 3;3098,3096,3093;, + 3;3093,3096,3094;, + 3;3094,3096,3095;, + 3;3101,3142,3100;, + 3;3101,3141,3142;, + 3;3102,3165,3101;, + 3;3102,3164,3165;, + 3;3103,3137,3102;, + 3;3103,3136,3137;, + 3;3100,3099,3101;, + 3;3101,3099,3103;, + 3;3101,3103,3102;, + 3;3106,3128,3105;, + 3;3106,3127,3128;, + 3;3108,3390,3107;, + 3;3108,3389,3390;, + 3;3109,3392,3108;, + 3;3109,3395,3392;, + 3;3107,3106,3108;, + 3;3108,3106,3105;, + 3;3108,3105,3104;, + 3;3108,3104,3109;, + 3;3111,3159,3110;, + 3;3111,3158,3159;, + 3;3112,3162,3111;, + 3;3112,3161,3162;, + 3;3114,3152,3113;, + 3;3114,3151,3152;, + 3;3115,3145,3114;, + 3;3115,3148,3145;, + 3;3115,3111,3110;, + 3;3111,3115,3114;, + 3;3111,3114,3112;, + 3;3112,3114,3113;, + 3;3117,3119,3118;, + 3;3119,3117,3116;, + 3;3120,3125,3124;, + 3;3120,3130,3125;, + 3;3123,3147,3122;, + 3;3123,3146,3147;, + 3;3124,3150,3123;, + 3;3124,3149,3150;, + 3;3121,3123,3122;, + 3;3123,3121,3120;, + 3;3123,3120,3124;, + 3;3126,3149,3125;, + 3;3126,3154,3149;, + 3;3128,3126,3125;, + 3;3128,3125,3129;, + 3;3129,3125,3130;, + 3;3126,3128,3127;, + 3;3133,3140,3132;, + 3;3133,3139,3140;, + 3;3134,3156,3133;, + 3;3134,3155,3156;, + 3;3134,3133,3135;, + 3;3135,3133,3131;, + 3;3131,3133,3132;, + 3;3138,3164,3137;, + 3;3138,3163,3164;, + 3;3139,3157,3138;, + 3;3139,3156,3157;, + 3;3140,3138,3137;, + 3;3140,3137,3136;, + 3;3138,3140,3139;, + 3;4418,3160,3144;, + 3;4418,4419,3160;, + 3;3143,4401,4418;, + 3;3143,4418,3144;, + 3;4420,3151,3145;, + 3;4420,4421,3151;, + 3;4394,3145,3148;, + 3;3145,4394,4420;, + 3;4399,3153,4422;, + 3;4422,3153,3152;, + 3;4422,3152,4421;, + 3;4421,3152,3151;, + 3;3158,4423,4424;, + 3;3158,3162,4423;, + 3;4391,3159,4425;, + 3;4425,3159,3158;, + 3;4425,3158,4424;, + 3;4426,4423,3161;, + 3;4426,3161,3160;, + 3;4426,3160,4419;, + 3;3161,4423,3162;, + 3;3166,3176,3171;, + 3;3166,3175,3176;, + 3;3167,3256,3166;, + 3;3167,3255,3256;, + 3;3168,3287,3167;, + 3;3168,3286,3287;, + 3;3169,3211,3168;, + 3;3169,3210,3211;, + 3;3167,3169,3168;, + 3;3169,3167,3166;, + 3;3169,3166,3170;, + 3;3170,3166,3171;, + 3;3173,3181,3172;, + 3;3173,3180,3181;, + 3;3174,3260,3173;, + 3;3174,3259,3260;, + 3;3175,3257,3174;, + 3;3175,3256,3257;, + 3;3173,3176,3174;, + 3;3174,3176,3175;, + 3;3176,3173,3177;, + 3;3177,3173,3172;, + 3;3178,3183,3182;, + 3;3178,3189,3183;, + 3;3179,3269,3178;, + 3;3179,3268,3269;, + 3;3180,3261,3179;, + 3;3180,3260,3261;, + 3;3181,3178,3182;, + 3;3178,3181,3179;, + 3;3179,3181,3180;, + 3;3186,3194,3185;, + 3;3186,3193,3194;, + 3;3187,3233,3186;, + 3;3187,3239,3233;, + 3;3188,3274,3187;, + 3;3188,3273,3274;, + 3;3189,3270,3188;, + 3;3189,3269,3270;, + 3;3187,3186,3188;, + 3;3188,3186,3185;, + 3;3188,3185,3184;, + 3;3188,3184,3189;, + 3;3189,3184,3183;, + 3;3192,3202,3191;, + 3;3192,3201,3202;, + 3;3193,3234,3192;, + 3;3193,3233,3234;, + 3;3195,3191,3190;, + 3;3191,3195,3194;, + 3;3191,3194,3193;, + 3;3191,3193,3192;, + 3;3198,3377,3197;, + 3;3198,3376,3377;, + 3;3200,3232,3199;, + 3;3200,3231,3232;, + 3;3201,3235,3200;, + 3;3201,3234,3235;, + 3;3197,3201,3200;, + 3;3197,3200,3198;, + 3;3198,3200,3199;, + 3;3201,3197,3202;, + 3;3202,3197,3196;, + 3;3204,3214,3203;, + 3;3204,3213,3214;, + 3;3205,3282,3204;, + 3;3205,3281,3282;, + 3;3206,3291,3205;, + 3;3206,3290,3291;, + 3;3207,3215,3206;, + 3;3207,3220,3215;, + 3;3205,3207,3206;, + 3;3207,3205,3208;, + 3;3208,3205,3204;, + 3;3208,3204,3203;, + 3;3212,3286,3211;, + 3;3212,3285,3286;, + 3;3213,3283,3212;, + 3;3213,3282,3283;, + 3;3211,3209,3214;, + 3;3211,3214,3212;, + 3;3212,3214,3213;, + 3;3209,3211,3210;, + 3;3216,3290,3215;, + 3;3216,3289,3290;, + 3;3217,3253,3216;, + 3;3217,3252,3253;, + 3;3218,3246,3217;, + 3;3218,3245,3246;, + 3;3219,3222,3218;, + 3;3219,3221,3222;, + 3;3215,3218,3216;, + 3;3216,3218,3217;, + 3;3218,3215,3219;, + 3;3219,3215,3220;, + 3;3223,3245,3222;, + 3;3223,3244,3245;, + 3;3224,3294,3223;, + 3;3224,3298,3294;, + 3;3225,3299,3224;, + 3;3225,3304,3299;, + 3;3226,3228,3225;, + 3;3226,3227,3228;, + 3;3224,3222,3225;, + 3;3225,3222,3221;, + 3;3225,3221,3226;, + 3;3222,3224,3223;, + 3;3229,3304,3228;, + 3;3229,3303,3304;, + 3;3230,3322,3229;, + 3;3230,3321,3322;, + 3;3231,3236,3230;, + 3;3231,3235,3236;, + 3;3229,3228,3227;, + 3;3229,3227,3232;, + 3;3229,3232,3230;, + 3;3230,3232,3231;, + 3;3237,3321,3236;, + 3;3237,3320,3321;, + 3;3238,3306,3237;, + 3;3238,3305,3306;, + 3;3239,3275,3238;, + 3;3239,3274,3275;, + 3;3238,3237,3234;, + 3;3238,3234,3233;, + 3;3238,3233,3239;, + 3;3234,3237,3235;, + 3;3235,3237,3236;, + 3;3240,3272,3248;, + 3;3240,3278,3272;, + 3;3241,3312,3240;, + 3;3241,3311,3312;, + 3;3242,3328,3241;, + 3;3242,3327,3328;, + 3;3243,3334,3242;, + 3;3243,3333,3334;, + 3;3244,3295,3243;, + 3;3244,3294,3295;, + 3;3247,3252,3246;, + 3;3247,3251,3252;, + 3;3248,3266,3247;, + 3;3248,3271,3266;, + 3;3244,3241,3246;, + 3;3244,3246,3245;, + 3;3246,3241,3247;, + 3;3247,3241,3240;, + 3;3247,3240,3248;, + 3;3241,3244,3243;, + 3;3241,3243,3242;, + 3;3249,3289,3253;, + 3;3249,3293,3289;, + 3;3250,3263,3249;, + 3;3250,3262,3263;, + 3;3251,3267,3250;, + 3;3251,3266,3267;, + 3;3252,3251,3253;, + 3;3253,3251,3249;, + 3;3249,3251,3250;, + 3;3254,3279,3258;, + 3;3254,3284,3279;, + 3;3255,3288,3254;, + 3;3255,3287,3288;, + 3;3258,3259,3257;, + 3;3258,3265,3259;, + 3;3255,3254,3256;, + 3;3256,3254,3258;, + 3;3256,3258,3257;, + 3;3262,3268,3261;, + 3;3262,3267,3268;, + 3;3264,3293,3263;, + 3;3264,3292,3293;, + 3;3265,3280,3264;, + 3;3265,3279,3280;, + 3;3260,3259,3262;, + 3;3260,3262,3261;, + 3;3262,3259,3263;, + 3;3263,3259,3265;, + 3;3263,3265,3264;, + 3;3271,3273,3270;, + 3;3271,3272,3273;, + 3;3268,3267,3269;, + 3;3269,3267,3271;, + 3;3269,3271,3270;, + 3;3271,3267,3266;, + 3;3276,3305,3275;, + 3;3276,3308,3305;, + 3;3277,3314,3276;, + 3;3277,3319,3314;, + 3;3278,3313,3277;, + 3;3278,3312,3313;, + 3;3274,3276,3275;, + 3;3276,3274,3273;, + 3;3276,3273,3277;, + 3;3277,3273,3278;, + 3;3278,3273,3272;, + 3;3281,3292,3280;, + 3;3281,3291,3292;, + 3;3284,3285,3283;, + 3;3284,3288,3285;, + 3;3281,3280,3282;, + 3;3282,3280,3284;, + 3;3282,3284,3283;, + 3;3284,3280,3279;, + 3;3286,3285,3287;, + 3;3287,3285,3288;, + 3;3289,3291,3290;, + 3;3291,3289,3292;, + 3;3292,3289,3293;, + 3;3296,3333,3295;, + 3;3296,3332,3333;, + 3;3297,3340,3296;, + 3;3297,3339,3340;, + 3;3298,3300,3297;, + 3;3298,3299,3300;, + 3;3294,3298,3295;, + 3;3295,3298,3297;, + 3;3295,3297,3296;, + 3;3301,3339,3300;, + 3;3301,3338,3339;, + 3;3302,3355,3301;, + 3;3302,3354,3355;, + 3;3303,3323,3302;, + 3;3303,3322,3323;, + 3;3303,3299,3304;, + 3;3299,3303,3300;, + 3;3300,3303,3302;, + 3;3300,3302,3301;, + 3;3307,3320,3306;, + 3;3307,3326,3320;, + 3;3308,3315,3307;, + 3;3308,3314,3315;, + 3;3305,3308,3306;, + 3;3306,3308,3307;, + 3;3309,3319,3313;, + 3;3309,3318,3319;, + 3;3310,3344,3309;, + 3;3310,3343,3344;, + 3;3311,3329,3310;, + 3;3311,3328,3329;, + 3;3312,3309,3313;, + 3;3309,3312,3311;, + 3;3309,3311,3310;, + 3;3316,3326,3315;, + 3;3316,3325,3326;, + 3;3317,3350,3316;, + 3;3317,3349,3350;, + 3;3318,3345,3317;, + 3;3318,3344,3345;, + 3;3319,3316,3315;, + 3;3319,3315,3314;, + 3;3316,3319,3318;, + 3;3316,3318,3317;, + 3;3324,3354,3323;, + 3;3324,3353,3354;, + 3;3325,3351,3324;, + 3;3325,3350,3351;, + 3;3326,3322,3321;, + 3;3326,3321,3320;, + 3;3322,3326,3323;, + 3;3323,3326,3325;, + 3;3323,3325,3324;, + 3;3327,3335,3330;, + 3;3327,3334,3335;, + 3;3330,3343,3329;, + 3;3330,3342,3343;, + 3;3330,3329,3327;, + 3;3327,3329,3328;, + 3;3331,3342,3335;, + 3;3331,3347,3342;, + 3;3332,3341,3331;, + 3;3332,3340,3341;, + 3;3331,3335,3332;, + 3;3332,3335,3334;, + 3;3332,3334,3333;, + 3;3336,3347,3341;, + 3;3336,3346,3347;, + 3;3337,3348,3336;, + 3;3337,3352,3348;, + 3;3338,3356,3337;, + 3;3338,3355,3356;, + 3;3337,3336,3338;, + 3;3338,3336,3341;, + 3;3338,3341,3340;, + 3;3338,3340,3339;, + 3;3346,3349,3345;, + 3;3346,3348,3349;, + 3;3346,3342,3347;, + 3;3342,3346,3343;, + 3;3343,3346,3345;, + 3;3343,3345,3344;, + 3;3352,3353,3351;, + 3;3352,3356,3353;, + 3;3348,3352,3349;, + 3;3349,3352,3351;, + 3;3349,3351,3350;, + 3;3356,3355,3353;, + 3;3353,3355,3354;, + 3;3357,3367,3361;, + 3;3357,3373,3367;, + 3;3359,3357,3361;, + 3;3359,3361,3360;, + 3;3357,3359,3358;, + 3;3366,3370,3365;, + 3;3366,3369,3370;, + 3;4384,3362,4382;, + 3;3365,3364,3366;, + 3;3362,4384,3363;, + 3;3372,3374,3371;, + 3;3372,3378,3374;, + 3;3371,3368,3367;, + 3;3371,3367,3373;, + 3;3371,3373,3372;, + 3;3368,3371,3369;, + 3;3369,3371,3370;, + 3;3376,3378,3377;, + 3;3378,3376,3375;, + 3;3378,3375,3374;, + 3;3382,3408,3381;, + 3;3382,3407,3408;, + 3;3383,3413,3382;, + 3;3383,3412,3413;, + 3;3381,3383,3382;, + 3;3383,3381,3384;, + 3;3384,3381,3380;, + 3;3384,3380,3379;, + 3;3385,3396,3391;, + 3;3385,3400,3396;, + 3;3389,3393,3388;, + 3;3389,3392,3393;, + 3;3390,3389,3387;, + 3;3390,3387,3391;, + 3;3391,3387,3386;, + 3;3391,3386,3385;, + 3;3387,3389,3388;, + 3;2014,3392,3395;, + 3;2014,3393,3392;, + 3;2014,3394,3393;, + 3;3399,3401,3398;, + 3;3399,3405,3401;, + 3;3400,3399,3398;, + 3;3400,3398,3397;, + 3;3400,3397,3396;, + 3;3403,3410,3402;, + 3;3403,3409,3410;, + 3;3401,3405,3403;, + 3;3401,3403,3402;, + 3;3403,3405,3404;, + 3;3407,3414,3406;, + 3;3407,3413,3414;, + 3;3410,3407,3411;, + 3;3411,3407,3406;, + 3;3407,3410,3408;, + 3;3408,3410,3409;, + 3;3414,3413,3412;, + 3;3414,3412,3415;, + 3;21,88,845;, + 3;151,846,3755;, + 3;4310,4309,4427;, + 3;4310,4428,4311;, + 3;1769,3416,1770;, + 3;3416,1778,4148;, + 3;3417,1901,4429;, + 3;4429,4234,3417;, + 3;4430,3510,185;, + 3;4430,185,3509;, + 3;61,4431,3448;, + 3;61,0,4431;; + + MeshNormals { + 4432; + -0.989571;-0.011953;-0.143551;, + -0.433214;-0.193876;-0.880192;, + -0.984781;0.061328;-0.162622;, + -0.000005;0.123093;-0.992395;, + -0.989261;0.138490;-0.046722;, + -0.588256;0.730768;-0.346313;, + 0.077792;0.437259;0.895965;, + -0.812611;0.166144;0.558622;, + -0.008181;0.252116;0.967663;, + 0.485631;0.575618;0.657895;, + 0.055097;0.933688;0.353823;, + -0.093634;0.341116;0.935346;, + -0.006241;0.260589;0.965430;, + -0.649875;0.280683;0.706314;, + 0.000025;-0.011554;0.999933;, + -0.338437;0.350328;-0.873345;, + 0.000004;-0.093947;-0.995577;, + 0.000016;-0.316597;-0.948560;, + -0.015033;-0.328905;-0.944243;, + -0.576566;-0.459455;-0.675627;, + -0.434273;0.868349;-0.239535;, + -0.151234;0.506148;0.849083;, + -0.164626;0.337297;-0.926892;, + -0.802913;0.231146;0.549456;, + 0.210760;-0.136730;0.967928;, + -0.336341;-0.108795;0.935435;, + 0.244564;-0.065106;0.967445;, + -0.963334;-0.094433;0.251137;, + -0.885448;-0.301099;-0.354007;, + -0.495937;0.082114;0.864467;, + -0.957644;0.220431;0.185280;, + 0.693967;0.242883;0.677803;, + 0.527840;-0.168309;0.832500;, + 0.026768;-0.438717;0.898227;, + -0.000016;-0.990834;-0.135089;, + -0.701247;-0.651828;-0.288743;, + -0.982778;-0.084744;-0.164211;, + -0.001279;-0.024600;-0.999697;, + 0.000009;-0.204621;0.978841;, + -0.895650;-0.343271;-0.282799;, + -0.559206;0.508717;0.654596;, + -0.314707;0.781987;-0.538011;, + 0.000005;-0.999974;0.007152;, + 0.114825;-0.948131;-0.296416;, + -0.145665;-0.919602;-0.364848;, + -0.449270;0.893379;-0.005605;, + 0.000168;0.854980;0.518661;, + -0.000538;0.773627;-0.633641;, + -0.027645;-0.423869;0.905301;, + -0.705970;-0.446329;0.549906;, + -0.273835;-0.400153;0.874581;, + 0.233305;-0.886660;0.399253;, + 0.513833;-0.494239;0.701216;, + -0.790963;-0.525076;0.314122;, + 0.174039;-0.984266;0.030518;, + -0.591766;-0.268191;0.760188;, + -0.187456;-0.160792;0.969023;, + 0.000101;-0.114170;0.993461;, + 0.000002;0.058647;-0.998279;, + -0.131625;-0.050608;-0.990007;, + -0.731235;-0.158649;-0.663420;, + -0.974460;-0.127344;-0.184962;, + -0.859652;-0.309116;-0.406751;, + -0.916036;-0.145104;-0.373928;, + -0.817874;-0.539381;-0.200374;, + 0.278233;-0.273728;0.920684;, + 0.854774;-0.403493;0.326429;, + 0.853727;-0.007027;-0.520673;, + -0.977952;0.018441;0.208015;, + -0.951874;0.289606;0.100323;, + -0.979629;0.019166;-0.199899;, + -0.986179;0.140164;0.088351;, + -0.871225;-0.451441;0.192789;, + -0.529409;-0.220751;0.819143;, + -0.944779;0.327439;0.013305;, + -0.881035;0.426148;0.205365;, + -0.957604;-0.179816;-0.225078;, + -0.994196;0.051821;0.094280;, + -0.964421;0.191784;-0.181966;, + -0.980241;-0.139652;0.140090;, + 0.000023;-0.244851;-0.969561;, + -0.048245;-0.332029;-0.942035;, + -0.432334;-0.434648;-0.790043;, + -0.722354;-0.365988;-0.586734;, + -0.957758;-0.287242;0.013841;, + -0.000013;0.370748;-0.928733;, + -0.040453;0.710290;-0.702746;, + 0.313062;0.614710;0.723964;, + -0.460194;0.616751;0.638623;, + 0.000001;0.024616;-0.999697;, + -0.226499;-0.140193;-0.963869;, + -0.457101;-0.023022;-0.889117;, + -0.664851;0.117356;-0.737700;, + -0.897582;0.211412;-0.386848;, + -0.903847;0.420928;-0.076682;, + -0.135198;0.773486;0.619226;, + -0.141004;0.621292;0.770788;, + 0.124490;0.581568;0.803916;, + 0.000876;0.616105;0.787664;, + 0.387797;0.626448;0.676148;, + 0.149512;-0.247279;-0.957340;, + -0.905288;0.176534;0.386380;, + -0.867052;0.137579;0.478846;, + -0.829671;0.408671;0.380308;, + -0.701860;0.270507;0.658953;, + -0.892567;0.378889;-0.244475;, + 0.351384;0.936193;-0.008488;, + 0.237101;0.465138;0.852895;, + 0.221316;0.433286;0.873660;, + 0.000301;0.766126;0.642690;, + -0.037085;0.936295;-0.349251;, + 0.413738;0.852881;0.318456;, + 0.000002;0.301740;-0.953390;, + -0.138062;0.039474;-0.989637;, + -0.439435;0.173212;-0.881416;, + -0.632058;0.089542;-0.769730;, + -0.851652;0.387173;-0.353250;, + -0.886195;0.463152;-0.012222;, + 0.766299;0.388719;0.511550;, + -0.968326;0.059868;0.242406;, + -0.892378;0.166006;0.419647;, + -0.818963;0.564690;-0.102099;, + -0.830607;0.230508;0.506910;, + -0.758821;0.117889;0.640541;, + -0.044908;-0.611148;0.790241;, + -0.886549;0.392710;-0.244562;, + -0.899773;0.187812;0.393873;, + -0.898020;0.299543;-0.322233;, + -0.947696;-0.212901;-0.237792;, + -0.502434;-0.677413;0.537282;, + -0.291292;-0.349896;0.890349;, + -0.057118;-0.609638;0.790619;, + -0.987507;0.156917;-0.014374;, + -0.323785;0.508980;0.797560;, + -0.901688;0.259664;-0.345736;, + -0.805182;0.220087;-0.550676;, + -0.645712;-0.763581;-0.000279;, + 0.990082;-0.015546;-0.139630;, + 0.433214;-0.193877;-0.880192;, + 0.987185;0.081535;-0.137175;, + 0.990910;0.129582;-0.036136;, + 0.260508;0.727642;-0.634565;, + -0.091231;0.428920;0.898724;, + 0.811080;0.164853;0.561224;, + -0.559324;0.693597;0.453961;, + 0.100417;0.338390;0.935633;, + 0.649875;0.280683;0.706314;, + 0.338436;0.350327;-0.873346;, + 0.015042;-0.328899;-0.944245;, + 0.576566;-0.459455;-0.675627;, + 0.434273;0.868349;-0.239535;, + 0.306690;0.520580;0.796830;, + 0.164619;0.337297;-0.926893;, + 0.802913;0.231146;0.549456;, + -0.210733;-0.136750;0.967931;, + 0.336341;-0.108795;0.935435;, + -0.244564;-0.065106;0.967445;, + 0.963334;-0.094433;0.251137;, + 0.885448;-0.301099;-0.354007;, + 0.495937;0.082114;0.864467;, + 0.957644;0.220431;0.185280;, + -0.602846;0.290303;0.743169;, + -0.527840;-0.168309;0.832500;, + -0.026768;-0.438717;0.898227;, + 0.701248;-0.651828;-0.288742;, + 0.982279;-0.089104;-0.164890;, + 0.895650;-0.343271;-0.282799;, + 0.566570;0.495981;0.658028;, + 0.309521;0.783229;-0.539212;, + -0.114791;-0.948135;-0.296417;, + 0.145665;-0.919602;-0.364848;, + 0.481298;0.876550;-0.003471;, + 0.027647;-0.423868;0.905302;, + 0.705254;-0.446887;0.550372;, + 0.273873;-0.400246;0.874527;, + -0.233305;-0.886660;0.399253;, + -0.513833;-0.494239;0.701216;, + 0.790963;-0.525076;0.314122;, + -0.174039;-0.984266;0.030518;, + 0.591063;-0.270370;0.759963;, + 0.187382;-0.161599;0.968903;, + 0.131624;-0.050609;-0.990007;, + 0.731235;-0.158649;-0.663420;, + 0.974460;-0.127344;-0.184962;, + 0.859652;-0.309116;-0.406751;, + 0.916036;-0.145104;-0.373928;, + 0.817874;-0.539381;-0.200374;, + -0.278232;-0.273728;0.920684;, + -0.854773;-0.403493;0.326429;, + -0.853727;-0.007027;-0.520673;, + 0.972307;0.015440;0.233196;, + 0.956394;0.275771;0.096231;, + 0.981505;0.019792;-0.190410;, + 0.972924;0.196620;0.121487;, + 0.955178;-0.252865;0.153929;, + 0.506951;-0.238596;0.828295;, + 0.964289;0.264843;-0.002032;, + 0.916931;0.363083;0.165554;, + 0.987197;-0.118160;-0.107142;, + 0.774218;0.487454;0.403702;, + 0.963480;0.174780;-0.202875;, + 0.970183;-0.159926;0.182121;, + 0.048272;-0.332044;-0.942028;, + 0.430577;-0.435479;-0.790545;, + 0.722112;-0.366391;-0.586781;, + 0.957347;-0.288570;0.014659;, + -0.305307;0.626286;0.717324;, + 0.448693;0.679150;0.580886;, + 0.226504;-0.140193;-0.963868;, + 0.457101;-0.023022;-0.889117;, + 0.664851;0.117356;-0.737700;, + 0.897582;0.211412;-0.386848;, + 0.903847;0.420928;-0.076682;, + 0.135198;0.773486;0.619226;, + 0.122893;0.649057;0.750748;, + -0.142710;0.597235;0.789268;, + -0.439283;0.626634;0.643708;, + -0.149496;-0.247276;-0.957343;, + 0.905288;0.176534;0.386380;, + 0.867052;0.137579;0.478846;, + 0.829671;0.408671;0.380308;, + 0.701860;0.270507;0.658953;, + 0.892567;0.378889;-0.244475;, + -0.362258;0.932010;-0.011212;, + -0.188184;0.477638;0.858166;, + -0.167233;0.445019;0.879768;, + 0.042064;0.935662;-0.350382;, + -0.453111;0.835822;0.309986;, + 0.138068;0.039474;-0.989636;, + 0.439435;0.173212;-0.881416;, + 0.632058;0.089542;-0.769730;, + 0.851652;0.387173;-0.353250;, + 0.886195;0.463152;-0.012222;, + -0.740748;0.411825;0.530746;, + 0.968326;0.059868;0.242406;, + 0.892378;0.166006;0.419647;, + 0.818963;0.564690;-0.102099;, + 0.830607;0.230508;0.506910;, + 0.758821;0.117889;0.640541;, + 0.044907;-0.611148;0.790241;, + 0.886549;0.392710;-0.244561;, + 0.899773;0.187812;0.393873;, + 0.898020;0.299543;-0.322233;, + 0.947696;-0.212901;-0.237792;, + 0.502434;-0.677413;0.537282;, + 0.291292;-0.349896;0.890349;, + 0.057117;-0.609638;0.790619;, + 0.987507;0.156917;-0.014374;, + 0.323785;0.508980;0.797560;, + 0.901688;0.259664;-0.345736;, + 0.805182;0.220087;-0.550676;, + 0.645712;-0.763581;-0.000280;, + -0.000035;0.202257;-0.979333;, + 0.000000;-0.152057;-0.988372;, + -0.986678;0.148934;0.065464;, + -0.248728;-0.201732;-0.947332;, + -0.091949;-0.099791;0.990751;, + -0.000076;-0.461661;-0.887057;, + 0.675377;-0.238040;0.698000;, + -0.372066;0.352850;-0.858524;, + -0.920508;0.371208;0.121944;, + 0.954651;-0.166315;-0.246941;, + -0.770854;-0.091830;-0.630358;, + -0.522907;0.552336;0.649225;, + -0.269360;-0.762341;0.588456;, + -0.705008;-0.050622;-0.707390;, + -0.421748;0.283560;-0.861233;, + 0.643644;-0.015506;0.765168;, + 0.992661;-0.000187;-0.120932;, + 0.935445;-0.035033;-0.351732;, + -0.263483;-0.085234;0.960891;, + -0.344264;0.023341;0.938583;, + 0.887402;-0.082890;-0.453484;, + -0.649836;0.205407;-0.731793;, + -0.872109;0.095397;-0.479922;, + -0.894885;0.082610;0.438584;, + -0.554738;0.084178;-0.827756;, + 0.054057;-0.076987;-0.995566;, + -0.908432;0.107750;-0.403908;, + 0.495001;-0.126597;0.859620;, + 0.968704;-0.213268;-0.126998;, + 0.313056;0.378120;0.871219;, + 0.365426;-0.280297;0.887636;, + 0.067345;-0.084014;-0.994186;, + -0.012682;-0.010483;0.999865;, + 0.064836;-0.191491;-0.979351;, + -0.289534;0.030294;-0.956688;, + -0.200942;0.148449;0.968290;, + 0.020471;-0.061478;-0.997899;, + -0.400237;0.683181;0.610798;, + 0.453303;-0.497746;0.739435;, + 0.521055;-0.809078;0.271835;, + 0.735182;-0.666684;0.122637;, + 0.821914;-0.569537;-0.009215;, + 0.759558;-0.443873;-0.475446;, + -0.572197;-0.246884;0.782073;, + -0.565959;-0.798793;0.204013;, + -0.757874;-0.650275;-0.052618;, + -0.707861;-0.682627;-0.181530;, + -0.657196;-0.390140;-0.644891;, + 0.215407;0.452689;0.865259;, + 0.845085;0.295788;0.445355;, + 0.869444;0.325743;0.371427;, + 0.954242;-0.257523;0.152001;, + -0.520474;0.526586;0.672171;, + -0.936897;0.300664;0.178397;, + -0.940651;0.338859;-0.018731;, + -0.960352;-0.063982;-0.271348;, + 0.059122;-0.098574;-0.993372;, + 0.798460;-0.602012;-0.006594;, + -0.809310;-0.499093;-0.309716;, + 0.179068;-0.150961;-0.972186;, + -0.113992;0.003257;-0.993476;, + -0.245507;-0.085870;-0.965584;, + 0.381448;-0.090026;0.919996;, + -0.473877;0.315534;0.822119;, + 0.834619;-0.338308;0.434694;, + 0.968707;-0.002938;-0.248189;, + -0.984728;-0.003402;0.174069;, + 0.518085;0.053826;-0.853634;, + -0.717724;0.062444;-0.693523;, + -0.172176;-0.025937;-0.984725;, + 0.990528;-0.094784;-0.099347;, + 0.716933;-0.028565;-0.696556;, + -0.638618;0.047039;-0.768085;, + 0.860708;-0.108316;0.497444;, + -0.837234;0.055243;0.544046;, + 0.955485;-0.120740;-0.269203;, + -0.670236;0.022528;-0.741806;, + -0.945620;0.026607;-0.324184;, + -0.472020;0.096403;0.876301;, + 0.537901;-0.058446;-0.840980;, + -0.381353;0.920775;0.082119;, + 0.682106;-0.030649;0.730611;, + -0.557613;-0.562556;0.610408;, + 0.846805;0.072950;-0.526877;, + 0.049962;-0.004893;-0.998739;, + 0.666223;-0.143179;0.731879;, + -0.861291;-0.041597;-0.506406;, + 0.034482;-0.052609;-0.998020;, + 0.068707;0.488169;-0.870040;, + 0.007891;-0.135395;-0.990760;, + -0.145988;-0.211055;-0.966511;, + -0.279880;-0.147467;0.948641;, + -0.762165;0.039662;0.646167;, + 0.389810;-0.013375;0.920798;, + 0.757187;-0.049995;0.651282;, + 0.181561;-0.108135;0.977416;, + -0.887763;0.274320;0.369629;, + -0.354476;-0.066564;0.932693;, + -0.705742;-0.122863;0.697734;, + -0.804425;-0.481755;0.347580;, + -0.911357;-0.405828;0.068791;, + -0.868967;-0.391802;-0.302304;, + -0.955392;-0.286491;-0.071754;, + -0.212265;-0.554761;-0.804478;, + -0.300497;-0.671647;-0.677194;, + 0.566503;-0.333624;0.753505;, + 0.705192;-0.523353;0.478336;, + 0.734833;-0.590132;0.334314;, + 0.703206;-0.672001;-0.232197;, + 0.353830;-0.592859;-0.723410;, + 0.909177;-0.368835;-0.193282;, + 0.738914;-0.651028;0.173689;, + 0.318223;-0.742396;-0.589561;, + 0.039464;-0.745272;-0.665591;, + -0.507519;-0.687744;-0.519069;, + 0.143708;-0.090742;0.985451;, + -0.325692;0.036226;0.944782;, + -0.642110;-0.406225;0.650135;, + -0.726668;-0.619543;0.296850;, + -0.754218;-0.609442;0.244407;, + -0.480671;-0.816061;-0.320936;, + -0.438781;-0.895636;-0.072854;, + -0.216241;-0.550378;-0.806427;, + -0.375817;-0.659247;-0.651272;, + 0.524041;-0.621420;0.582424;, + 0.478543;-0.696415;0.534792;, + 0.479492;-0.729402;0.487915;, + 0.552158;-0.818101;-0.160724;, + 0.216081;-0.555173;-0.803176;, + 0.390037;-0.917415;-0.078869;, + 0.462565;-0.763825;0.450117;, + 0.298517;-0.762623;-0.573840;, + 0.099219;-0.723576;-0.683077;, + -0.363985;-0.781659;-0.506482;, + -0.687634;-0.340006;-0.641526;, + -0.554595;-0.700435;0.449238;, + 0.007793;-0.618390;0.785832;, + -0.700055;-0.676002;-0.230094;, + 0.152980;0.089858;-0.984136;, + 0.639689;-0.061333;0.766183;, + -0.671801;-0.148929;-0.725605;, + 0.982818;-0.144272;-0.115132;, + -0.539943;-0.790977;-0.287777;, + -0.425702;-0.452816;-0.783413;, + -0.120435;0.764300;-0.633515;, + 0.634155;0.239730;0.735103;, + 0.100998;-0.684788;0.721710;, + -0.373807;-0.009779;-0.927455;, + -0.400118;0.694772;0.597660;, + -0.642458;0.753052;0.141985;, + 0.220397;-0.805586;0.549959;, + 0.474612;-0.157723;0.865949;, + 0.286302;-0.330049;-0.899499;, + 0.364402;-0.047676;0.930020;, + -0.153579;-0.916119;-0.370324;, + -0.360583;-0.309427;-0.879906;, + 0.603621;-0.355989;0.713382;, + -0.339341;-0.048326;0.939421;, + -0.969969;-0.035649;-0.240603;, + -0.299431;-0.946414;-0.120998;, + 0.164304;-0.789581;0.591242;, + -0.678182;-0.699706;-0.224678;, + -0.069164;-0.822330;0.564792;, + -0.245535;-0.396112;-0.884764;, + -0.891450;-0.383892;-0.240717;, + 0.072762;-0.780842;0.620477;, + -0.595632;-0.621882;0.508414;, + -0.752466;-0.638225;0.162674;, + -0.299599;-0.795145;0.527243;, + -0.000137;-0.920182;0.391491;, + -0.114339;0.740537;0.662217;, + -0.673865;0.641908;0.365869;, + 0.368870;0.664338;0.650069;, + -0.929837;0.223510;-0.292314;, + 0.987497;0.100828;0.121175;, + -0.037200;-0.353239;-0.934793;, + 0.000005;-0.908853;-0.417117;, + -0.275159;-0.572461;0.772383;, + 1.000000;0.000000;0.000000;, + -0.311030;-0.795975;-0.519312;, + -0.790481;-0.221084;-0.571194;, + -0.264462;-0.862138;0.432178;, + -0.597714;-0.523944;0.606812;, + -0.550598;-0.834581;0.017782;, + -0.162744;0.615741;0.770959;, + -0.877145;-0.439089;0.194469;, + -0.415729;0.666519;0.618807;, + -0.278425;0.851658;-0.444026;, + -0.537797;0.842499;0.031136;, + 0.000014;0.999890;-0.014824;, + -0.000345;0.842160;-0.539228;, + -0.136592;-0.525506;-0.839754;, + 0.000010;-0.577151;-0.816638;, + -0.226785;-0.723353;0.652173;, + 0.000147;-0.426759;0.904366;, + -0.312156;-0.802806;-0.507998;, + -0.702614;-0.504599;-0.501711;, + -0.270629;-0.843099;0.464697;, + -0.618679;-0.620211;0.482259;, + -0.545698;-0.837393;0.031400;, + -0.530614;0.817949;0.222282;, + -0.520441;-0.817752;0.245812;, + 0.000135;0.503934;0.863742;, + 0.000081;-0.865374;0.501127;, + -0.494858;0.862986;0.101841;, + -0.877073;-0.347968;0.331150;, + -0.848954;-0.000633;0.528467;, + -0.435124;-0.365516;0.822840;, + -0.171310;-0.101103;0.980016;, + -0.280330;-0.874167;0.396545;, + -0.857649;-0.059936;0.510730;, + -0.851056;-0.296513;0.433340;, + -0.292987;0.538921;-0.789761;, + -0.385669;0.149737;-0.910405;, + -0.498102;0.070627;0.864237;, + 0.072329;0.379525;-0.922350;, + 0.076379;0.219461;-0.972627;, + 0.202960;-0.006085;-0.979168;, + 0.224477;-0.161615;-0.960984;, + 0.287531;-0.313110;-0.905145;, + 0.508736;-0.187881;-0.840171;, + -0.692298;0.454233;-0.560710;, + -0.793609;0.199236;-0.574882;, + 0.696581;-0.112033;-0.708677;, + 0.671521;-0.145121;-0.726636;, + 0.672596;-0.215313;-0.707993;, + -0.558239;-0.020619;-0.829424;, + -0.534769;-0.089005;-0.840298;, + -0.513705;-0.196613;-0.835135;, + -0.349154;0.242462;0.905154;, + -0.631346;0.402228;0.663035;, + -0.146145;-0.055401;0.987711;, + -0.321667;0.474266;0.819514;, + -0.592931;-0.025934;0.804835;, + 0.232003;0.000577;0.972715;, + 0.340346;0.050732;-0.938931;, + -0.044769;0.183553;-0.981990;, + 0.908812;-0.397053;0.128099;, + 0.918662;-0.341700;0.198244;, + 0.938847;-0.129908;-0.318889;, + -0.995822;0.066694;-0.062372;, + -0.913711;-0.184581;0.362025;, + -0.773515;-0.042525;0.632350;, + 0.562379;0.010758;-0.826809;, + -0.346217;0.118076;-0.930694;, + -0.716207;0.131762;-0.685336;, + 0.723032;0.009740;0.690746;, + 0.936260;-0.073710;0.343489;, + -0.899016;0.099518;-0.426458;, + 0.016111;-0.054691;0.998373;, + 0.652732;-0.056214;0.755500;, + -0.677075;0.091018;0.730264;, + -0.550517;-0.135376;0.823775;, + -0.748083;0.060359;-0.660855;, + -0.891510;0.146220;-0.428753;, + -0.200461;-0.141215;-0.969471;, + 0.229795;-0.207572;-0.950846;, + 0.832397;-0.148190;-0.534000;, + 0.583371;-0.208319;-0.785036;, + 0.980272;0.130639;0.148327;, + 0.965909;-0.084351;-0.244754;, + 0.951984;0.131127;0.276644;, + -0.935643;0.156818;0.316197;, + -0.559482;-0.050274;-0.827317;, + -0.972281;0.214777;-0.092415;, + -0.532795;-0.071842;0.843189;, + -0.476940;-0.083345;0.874975;, + 0.274845;-0.070215;-0.958921;, + 0.028471;-0.057604;-0.997933;, + 0.574856;-0.080803;-0.814255;, + 0.144145;-0.089235;0.985525;, + 0.827608;-0.099104;0.552489;, + -0.876485;-0.009071;0.481344;, + -0.995610;0.037774;-0.085641;, + -0.905860;0.032618;-0.422319;, + -0.808523;0.001652;-0.588462;, + 0.845060;-0.044480;-0.532817;, + 0.979465;-0.039533;-0.197703;, + 0.956895;-0.080204;0.279139;, + -0.691297;-0.047071;-0.721036;, + -0.412896;-0.055933;-0.909059;, + 0.999321;0.028755;-0.023042;, + 0.912214;-0.035085;-0.408209;, + 0.563445;-0.089914;-0.821246;, + -0.351468;0.039937;-0.935348;, + 0.956673;-0.049558;0.286915;, + 0.269123;0.056572;0.961443;, + 0.740501;-0.038151;0.670971;, + -0.562631;0.056481;0.824776;, + -0.925797;0.040436;0.375851;, + -0.315953;0.018351;0.948597;, + 0.056900;0.108101;-0.992510;, + 0.090328;-0.066382;-0.993697;, + 0.226044;-0.018716;0.973937;, + -0.906954;0.117975;-0.404371;, + 0.992970;-0.002293;0.118346;, + 0.263526;0.009804;0.964602;, + 0.960000;-0.111524;0.256830;, + 0.046754;-0.041359;-0.998050;, + 0.975814;-0.094575;0.197085;, + 0.713467;-0.239290;-0.658563;, + 0.796247;0.046297;0.603198;, + -0.000011;0.371222;-0.928544;, + -0.000042;-0.118764;-0.992922;, + 0.045742;0.462090;-0.885653;, + 0.986678;0.148934;0.065464;, + 0.248728;-0.201732;-0.947332;, + 0.091949;-0.099791;0.990751;, + -0.675428;-0.237979;0.697971;, + 0.372066;0.352850;-0.858524;, + 0.920508;0.371208;0.121944;, + -0.954652;-0.166280;-0.246961;, + 0.770854;-0.091830;-0.630359;, + 0.522907;0.552336;0.649225;, + 0.705008;-0.050621;-0.707390;, + 0.421748;0.283560;-0.861233;, + -0.643644;-0.015506;0.765168;, + -0.992661;-0.000187;-0.120933;, + -0.935445;-0.035034;-0.351733;, + 0.263483;-0.085234;0.960891;, + 0.344265;0.023340;0.938582;, + -0.887402;-0.082890;-0.453483;, + 0.649836;0.205407;-0.731793;, + 0.872109;0.095396;-0.479922;, + 0.894885;0.082610;0.438585;, + 0.554737;0.084178;-0.827756;, + -0.054057;-0.076987;-0.995566;, + 0.908432;0.107750;-0.403908;, + -0.495001;-0.126597;0.859620;, + -0.968704;-0.213269;-0.126998;, + -0.313056;0.378120;0.871218;, + -0.365426;-0.280297;0.887636;, + -0.067345;-0.084014;-0.994186;, + 0.012681;-0.010483;0.999865;, + -0.064836;-0.191491;-0.979351;, + 0.289534;0.030294;-0.956688;, + 0.200942;0.148449;0.968290;, + -0.020470;-0.061480;-0.997898;, + 0.400237;0.683181;0.610797;, + -0.453304;-0.497746;0.739435;, + -0.521055;-0.809078;0.271836;, + -0.735182;-0.666684;0.122637;, + -0.821914;-0.569537;-0.009216;, + -0.759558;-0.443871;-0.475447;, + 0.572196;-0.246884;0.782074;, + 0.565958;-0.798793;0.204014;, + 0.757874;-0.650275;-0.052618;, + 0.707861;-0.682627;-0.181531;, + 0.657196;-0.390140;-0.644891;, + -0.215408;0.452689;0.865258;, + -0.845086;0.295787;0.445354;, + -0.869444;0.325743;0.371427;, + -0.954242;-0.257523;0.152001;, + 0.520473;0.526586;0.672172;, + 0.936897;0.300664;0.178397;, + 0.940651;0.338859;-0.018732;, + 0.960352;-0.063982;-0.271348;, + -0.059122;-0.098573;-0.993372;, + -0.798459;-0.602012;-0.006595;, + 0.809310;-0.499092;-0.309716;, + -0.179068;-0.150961;-0.972186;, + 0.113992;0.003257;-0.993476;, + 0.245507;-0.085870;-0.965584;, + -0.381448;-0.090025;0.919996;, + 0.473877;0.315534;0.822118;, + -0.834619;-0.338308;0.434694;, + -0.968707;-0.002938;-0.248190;, + 0.984728;-0.003402;0.174069;, + -0.518085;0.053827;-0.853634;, + 0.717724;0.062444;-0.693523;, + 0.172176;-0.025937;-0.984725;, + -0.990528;-0.094784;-0.099347;, + -0.716933;-0.028565;-0.696556;, + 0.638618;0.047039;-0.768085;, + -0.860708;-0.108316;0.497444;, + 0.837234;0.055243;0.544047;, + -0.955485;-0.120740;-0.269203;, + 0.670236;0.022528;-0.741806;, + 0.945620;0.026607;-0.324184;, + 0.472020;0.096403;0.876301;, + -0.537901;-0.058446;-0.840980;, + 0.381356;0.920774;0.082120;, + -0.682106;-0.030649;0.730611;, + 0.557614;-0.562555;0.610409;, + -0.846805;0.072950;-0.526877;, + -0.049962;-0.004893;-0.998739;, + -0.666223;-0.143179;0.731879;, + 0.861291;-0.041597;-0.506406;, + -0.034481;-0.052611;-0.998020;, + -0.068707;0.488169;-0.870040;, + -0.007891;-0.135398;-0.990760;, + 0.145989;-0.211055;-0.966511;, + 0.279880;-0.147467;0.948642;, + 0.762165;0.039663;0.646167;, + -0.389810;-0.013375;0.920798;, + -0.757187;-0.049996;0.651282;, + -0.181560;-0.108135;0.977416;, + 0.887763;0.274319;0.369629;, + 0.354475;-0.066564;0.932693;, + 0.705738;-0.122868;0.697737;, + 0.804429;-0.481751;0.347578;, + 0.911362;-0.405818;0.068789;, + 0.868969;-0.391799;-0.302303;, + 0.955392;-0.286490;-0.071755;, + 0.212267;-0.554751;-0.804484;, + 0.300504;-0.671641;-0.677197;, + -0.566507;-0.333623;0.753502;, + -0.705199;-0.523347;0.478333;, + -0.734835;-0.590129;0.334313;, + -0.703206;-0.672002;-0.232196;, + -0.353826;-0.592860;-0.723412;, + -0.909176;-0.368837;-0.193284;, + -0.738915;-0.651028;0.173686;, + -0.318224;-0.742397;-0.589560;, + -0.039462;-0.745268;-0.665596;, + 0.507518;-0.687743;-0.519071;, + -0.143709;-0.090742;0.985451;, + 0.325692;0.036224;0.944782;, + 0.642109;-0.406228;0.650135;, + 0.726679;-0.619532;0.296847;, + 0.754223;-0.609436;0.244406;, + 0.480673;-0.816061;-0.320933;, + 0.438780;-0.895636;-0.072859;, + 0.216240;-0.550371;-0.806432;, + 0.375822;-0.659238;-0.651277;, + -0.524041;-0.621421;0.582424;, + -0.478550;-0.696413;0.534789;, + -0.479503;-0.729395;0.487914;, + -0.552157;-0.818101;-0.160725;, + -0.216079;-0.555173;-0.803177;, + -0.390036;-0.917416;-0.078869;, + -0.462568;-0.763826;0.450113;, + -0.298518;-0.762626;-0.573837;, + -0.099215;-0.723576;-0.683077;, + 0.363989;-0.781657;-0.506483;, + 0.687634;-0.340007;-0.641526;, + 0.554595;-0.700435;0.449238;, + -0.007792;-0.618390;0.785833;, + 0.700058;-0.676000;-0.230095;, + -0.152979;0.089859;-0.984136;, + -0.639690;-0.061333;0.766182;, + 0.671802;-0.148929;-0.725605;, + -0.982818;-0.144272;-0.115132;, + 0.539944;-0.790977;-0.287776;, + 0.425700;-0.452817;-0.783413;, + 0.120436;0.764300;-0.633515;, + -0.634158;0.239730;0.735101;, + -0.100997;-0.684786;0.721711;, + 0.373807;-0.009780;-0.927455;, + 0.400118;0.694773;0.597659;, + 0.642459;0.753051;0.141986;, + -0.220398;-0.805586;0.549960;, + -0.474612;-0.157723;0.865949;, + -0.286301;-0.330049;-0.899500;, + -0.364402;-0.047676;0.930020;, + 0.153577;-0.916119;-0.370323;, + 0.360580;-0.309427;-0.879907;, + -0.603625;-0.355989;0.713378;, + 0.339341;-0.048326;0.939421;, + 0.969969;-0.035649;-0.240603;, + 0.299429;-0.946415;-0.121000;, + -0.164303;-0.789579;0.591244;, + 0.678182;-0.699706;-0.224678;, + 0.069165;-0.822329;0.564792;, + 0.245531;-0.396115;-0.884764;, + 0.891451;-0.383891;-0.240714;, + -0.072761;-0.780841;0.620478;, + 0.595631;-0.621884;0.508413;, + 0.752462;-0.638231;0.162672;, + 0.299598;-0.795145;0.527243;, + 0.114341;0.740537;0.662217;, + 0.673864;0.641909;0.365870;, + -0.368870;0.664338;0.650069;, + 0.929837;0.223510;-0.292314;, + -0.987497;0.100827;0.121175;, + 0.037200;-0.353240;-0.934793;, + 0.275160;-0.572458;0.772385;, + 0.311029;-0.795977;-0.519309;, + 0.790480;-0.221084;-0.571194;, + 0.264462;-0.862137;0.432180;, + 0.597714;-0.523943;0.606812;, + 0.550599;-0.834580;0.017784;, + 0.162598;0.616218;0.770608;, + 0.877144;-0.439088;0.194473;, + 0.415142;0.667643;0.617989;, + 0.286302;0.846489;-0.448874;, + 0.557573;0.829476;0.032896;, + 0.136611;-0.525509;-0.839749;, + 0.226786;-0.723350;0.652175;, + 0.312154;-0.802808;-0.507996;, + 0.702613;-0.504600;-0.501711;, + 0.270630;-0.843098;0.464698;, + 0.618680;-0.620209;0.482260;, + 0.545698;-0.837393;0.031400;, + 0.530646;0.817913;0.222337;, + 0.520501;-0.817725;0.245773;, + 0.494932;0.862948;0.101798;, + 0.877148;-0.347914;0.331008;, + 0.848954;-0.000633;0.528467;, + 0.435262;-0.365357;0.822837;, + 0.857736;-0.059938;0.510585;, + 0.851169;-0.296328;0.433244;, + 0.292987;0.538920;-0.789761;, + 0.385669;0.149737;-0.910405;, + 0.498102;0.070626;0.864237;, + -0.072353;0.379524;-0.922348;, + -0.076406;0.219458;-0.972625;, + -0.203011;-0.006085;-0.979158;, + -0.224521;-0.161613;-0.960974;, + -0.287588;-0.313105;-0.905129;, + -0.508756;-0.187868;-0.840163;, + 0.692298;0.454233;-0.560710;, + 0.793609;0.199236;-0.574882;, + -0.696581;-0.112033;-0.708677;, + -0.671520;-0.145121;-0.726636;, + -0.672596;-0.215313;-0.707993;, + 0.558239;-0.020619;-0.829424;, + 0.534769;-0.089005;-0.840298;, + 0.513705;-0.196613;-0.835135;, + 0.349154;0.242462;0.905154;, + 0.631346;0.402228;0.663035;, + 0.146145;-0.055401;0.987711;, + 0.321667;0.474265;0.819514;, + 0.592932;-0.025934;0.804835;, + -0.232003;0.000577;0.972715;, + -0.340346;0.050732;-0.938931;, + 0.044769;0.183553;-0.981990;, + -0.908812;-0.397053;0.128100;, + -0.918662;-0.341700;0.198244;, + -0.938847;-0.129909;-0.318890;, + 0.995822;0.066694;-0.062372;, + 0.913711;-0.184581;0.362025;, + 0.773514;-0.042525;0.632351;, + -0.562379;0.010758;-0.826810;, + 0.346217;0.118076;-0.930694;, + 0.716207;0.131762;-0.685337;, + -0.723032;0.009739;0.690746;, + -0.936259;-0.073710;0.343490;, + 0.899016;0.099517;-0.426458;, + -0.016111;-0.054691;0.998373;, + -0.652733;-0.056213;0.755500;, + 0.677075;0.091018;0.730264;, + 0.550517;-0.135376;0.823775;, + 0.748083;0.060359;-0.660855;, + 0.891510;0.146220;-0.428753;, + 0.200461;-0.141215;-0.969471;, + -0.229795;-0.207571;-0.950846;, + -0.832396;-0.148190;-0.534000;, + -0.583371;-0.208318;-0.785036;, + -0.980272;0.130639;0.148328;, + -0.965909;-0.084351;-0.244754;, + -0.951984;0.131127;0.276643;, + 0.935643;0.156818;0.316197;, + 0.559482;-0.050274;-0.827317;, + 0.972281;0.214776;-0.092415;, + 0.532795;-0.071842;0.843189;, + 0.476940;-0.083345;0.874975;, + -0.274846;-0.070215;-0.958921;, + -0.028471;-0.057604;-0.997933;, + -0.574856;-0.080803;-0.814255;, + -0.144145;-0.089235;0.985525;, + -0.827608;-0.099104;0.552489;, + 0.876485;-0.009071;0.481343;, + 0.995610;0.037774;-0.085641;, + 0.905860;0.032618;-0.422319;, + 0.808523;0.001652;-0.588462;, + -0.845060;-0.044480;-0.532817;, + -0.979465;-0.039533;-0.197703;, + -0.956895;-0.080204;0.279139;, + 0.691297;-0.047071;-0.721036;, + 0.412896;-0.055933;-0.909059;, + -0.999321;0.028755;-0.023042;, + -0.912214;-0.035085;-0.408209;, + -0.563445;-0.089914;-0.821246;, + 0.351468;0.039937;-0.935348;, + -0.956673;-0.049558;0.286915;, + -0.269123;0.056572;0.961443;, + -0.740501;-0.038151;0.670971;, + 0.562631;0.056481;0.824777;, + 0.925797;0.040436;0.375851;, + 0.315953;0.018351;0.948597;, + -0.056900;0.108101;-0.992510;, + -0.090328;-0.066382;-0.993697;, + -0.226043;-0.018716;0.973937;, + 0.906954;0.117975;-0.404371;, + -0.992970;-0.002293;0.118346;, + -0.263526;0.009803;0.964602;, + -0.960000;-0.111524;0.256830;, + -0.046754;-0.041359;-0.998050;, + -0.975831;-0.094528;0.197025;, + -0.713467;-0.239291;-0.658563;, + -0.796247;0.046297;0.603198;, + -0.045755;0.462090;-0.885652;, + -0.120567;0.889102;0.441544;, + 0.089110;0.886500;0.454068;, + 0.495887;0.107622;-0.861692;, + -0.501661;0.110800;-0.857939;, + 0.381150;0.923821;0.035779;, + -0.392218;0.560751;0.729194;, + 0.186388;0.976894;0.104581;, + 0.567905;0.521114;-0.637122;, + -0.473718;0.414055;-0.777271;, + 0.529914;-0.324726;-0.783418;, + -0.226517;-0.970474;0.082885;, + 0.207701;-0.604118;-0.769351;, + -0.527039;0.781296;-0.334374;, + -0.834983;0.264476;-0.482552;, + -0.675963;0.077412;-0.732858;, + -0.160126;0.190092;-0.968620;, + -0.228376;-0.127237;-0.965223;, + 0.068168;0.237165;0.969075;, + 0.657416;-0.744773;-0.114531;, + 0.274099;0.701037;-0.658344;, + -0.876642;-0.442049;-0.189978;, + 0.779259;0.312381;0.543299;, + -0.327724;-0.696016;0.638873;, + 0.594374;0.647132;0.477430;, + 0.984981;0.135781;-0.106662;, + -0.422834;0.836078;-0.349551;, + -0.828790;0.540637;-0.144288;, + 0.034244;0.095893;-0.994802;, + -0.641365;-0.305210;-0.703916;, + -0.923773;-0.052793;0.379284;, + 0.076548;0.939750;-0.333181;, + 0.119540;-0.960477;0.251383;, + -0.669596;-0.615981;-0.414980;, + -0.303029;-0.186091;0.934635;, + -0.234676;0.256475;0.937629;, + 0.295362;0.740439;0.603748;, + -0.353633;-0.752104;0.556133;, + -0.520041;-0.156983;0.839592;, + 0.509538;-0.839165;-0.190193;, + -0.146089;-0.981553;0.123336;, + 0.914801;0.309243;0.259824;, + 0.897041;0.033289;-0.440692;, + -0.839542;-0.269781;-0.471581;, + -0.963227;0.157435;-0.217736;, + -0.259132;0.699308;-0.666197;, + 0.604434;0.762690;0.230139;, + 0.423330;0.778916;0.462689;, + -0.434554;0.075723;0.897457;, + 0.006566;0.677354;0.735628;, + 0.749936;0.407739;-0.520908;, + 0.822491;0.188949;-0.536477;, + 0.756906;-0.145054;-0.637223;, + 0.423190;-0.716621;-0.554404;, + -0.227209;-0.966292;0.121064;, + -0.317550;-0.933835;0.164662;, + -0.496371;-0.182434;0.848725;, + -0.533776;-0.178235;0.826629;, + -0.604641;-0.410889;0.682334;, + -0.097373;-0.993304;-0.062171;, + 0.544150;0.817947;0.186717;, + 0.671652;0.718204;-0.181845;, + -0.520633;-0.800173;0.297766;, + 0.610984;0.085141;-0.787051;, + 0.315955;0.940947;0.121620;, + 0.450770;-0.364624;-0.814773;, + 0.034059;-0.236374;-0.971065;, + 0.126855;0.710394;-0.692277;, + -0.318398;0.686232;0.653995;, + -0.509804;-0.823253;0.249710;, + -0.828231;-0.560343;0.007058;, + -0.898012;0.382182;0.217971;, + -0.638411;-0.335141;0.692901;, + -0.521920;-0.736948;0.429543;, + -0.653621;0.114522;0.748107;, + -0.219228;-0.910600;-0.350351;, + -0.117938;0.862199;0.492649;, + 0.701914;0.653797;-0.282606;, + 0.566939;-0.044140;-0.822576;, + 0.698404;-0.196958;-0.688069;, + 0.634338;-0.406257;-0.657701;, + 0.726870;-0.133185;-0.673737;, + 0.790864;0.239727;-0.563086;, + 0.657555;0.711316;-0.248296;, + -0.154310;0.679156;0.717590;, + 0.231918;0.882106;0.410004;, + -0.412377;-0.755835;0.508585;, + -0.140943;-0.970084;0.197668;, + 0.311225;-0.875510;-0.369624;, + 0.597394;0.775849;-0.202927;, + -0.489055;-0.692585;0.530237;, + -0.491338;-0.534968;0.687311;, + -0.489758;-0.036774;0.871083;, + -0.438815;0.143442;0.887054;, + -0.286418;0.500490;0.816991;, + 0.627373;0.683168;-0.373745;, + 0.326963;0.774904;-0.540942;, + -0.154464;0.954555;0.254884;, + 0.414311;0.073885;-0.907131;, + 0.104101;0.966242;0.235666;, + 0.755011;0.321454;-0.571512;, + -0.578072;-0.401336;0.710466;, + 0.308722;0.426939;-0.849949;, + -0.156866;-0.502085;-0.850473;, + -0.244364;0.495312;-0.833638;, + -0.891274;-0.244321;-0.382017;, + -0.886836;0.434833;0.156336;, + 0.396048;-0.852920;0.340107;, + 0.958459;-0.005318;0.285179;, + -0.727155;-0.559204;0.398166;, + 0.313446;0.294967;0.902633;, + 0.568943;-0.193580;-0.799269;, + 0.540259;0.790932;-0.287309;, + -0.190782;-0.966119;-0.173828;, + 0.699601;0.319552;-0.639097;, + -0.461959;-0.866725;0.188099;, + -0.593538;-0.430185;0.680187;, + -0.129662;-0.954140;0.269823;, + 0.507759;-0.548313;-0.664480;, + -0.102172;0.911919;0.397447;, + 0.280146;-0.794859;0.538254;, + -0.896153;0.443634;0.009920;, + 0.604915;0.795184;0.041942;, + -0.370304;-0.909123;-0.190710;, + -0.469045;0.851012;0.236169;, + 0.715283;-0.213463;0.665435;, + 0.725324;-0.198324;0.659221;, + 0.906461;0.267020;-0.327153;, + 0.730965;-0.293094;0.616268;, + 0.426783;0.803078;-0.415839;, + 0.656180;0.614047;-0.438605;, + 0.414340;0.787894;0.455572;, + 0.387641;0.909810;0.148256;, + 0.067928;-0.995530;0.065615;, + -0.546062;-0.385173;0.743947;, + 0.023950;-0.995082;0.096118;, + -0.517968;-0.562667;0.644294;, + -0.214003;-0.959327;0.184103;, + 0.088411;-0.867050;-0.490314;, + -0.168195;-0.803638;0.570856;, + -0.761202;-0.602561;0.239776;, + -0.362576;0.544444;0.756386;, + -0.135361;-0.825017;0.548656;, + -0.403113;-0.761478;0.507594;, + -0.205138;-0.005818;0.978716;, + 0.500952;0.279713;0.819029;, + 0.826841;-0.523263;-0.206226;, + -0.600234;-0.799045;0.035307;, + -0.970404;-0.229202;0.076040;, + 0.780352;-0.359300;-0.511814;, + -0.914460;-0.230698;0.332477;, + -0.502437;0.667098;0.550034;, + 0.719999;0.682490;-0.125735;, + -0.268806;-0.896766;-0.351502;, + 0.915472;-0.398064;-0.058788;, + -0.888214;-0.136248;0.438762;, + -0.506181;0.569758;0.647422;, + 0.756777;0.576678;0.307785;, + -0.129004;-0.984436;0.119344;, + 0.777616;-0.116615;0.617830;, + -0.770465;-0.143678;0.621080;, + -0.343908;0.401841;0.848676;, + 0.264638;0.646667;0.715394;, + 0.216767;-0.499110;0.838989;, + 0.807418;0.487228;-0.332693;, + 0.374558;0.861007;0.344055;, + 0.808068;0.254617;-0.531221;, + 0.818120;0.339082;-0.464439;, + 0.221900;0.974980;0.013185;, + -0.108706;-0.976161;0.187863;, + -0.368776;-0.455644;0.810181;, + 0.538295;-0.631424;-0.558159;, + 0.867721;0.146537;-0.474959;, + 0.452458;0.832414;0.319950;, + -0.257983;0.544602;0.798031;, + -0.597196;-0.209677;0.774204;, + -0.171970;-0.985088;-0.005321;, + 0.456380;-0.580050;-0.674729;, + 0.769932;0.170761;-0.614854;, + 0.382238;0.901984;0.200798;, + -0.276717;0.544754;0.791625;, + -0.379263;-0.183823;0.906845;, + -0.068508;-0.994742;0.076127;, + 0.314063;-0.536259;-0.783448;, + 0.579129;0.233663;-0.781032;, + 0.240758;0.970584;-0.001211;, + -0.464359;0.605477;0.646350;, + -0.699843;-0.168934;0.694032;, + -0.205561;-0.977861;-0.039144;, + 0.329202;-0.554979;-0.763953;, + 0.738986;0.202412;-0.642596;, + 0.334240;0.935996;0.110429;, + -0.470908;0.619311;0.628251;, + -0.896664;-0.131474;0.422738;, + -0.491550;-0.803875;-0.334908;, + 0.488072;-0.623641;-0.610621;, + 0.885331;0.131251;-0.446051;, + 0.509708;0.786985;0.347638;, + -0.242430;0.521770;0.817914;, + -0.613783;-0.209259;0.761236;, + -0.262272;-0.961626;-0.080548;, + 0.450906;-0.603711;-0.657432;, + 0.828994;0.160795;-0.535644;, + 0.441803;0.858053;0.261828;, + -0.339070;0.554869;0.759705;, + -0.677756;-0.206419;0.705719;, + -0.259052;-0.964613;-0.049126;, + 0.229922;-0.482476;-0.845194;, + 0.778129;0.185891;-0.599966;, + 0.358173;0.924866;0.127809;, + -0.560979;0.636505;0.529305;, + -0.921070;-0.106291;0.374610;, + -0.585179;-0.715104;-0.382351;, + 0.327893;-0.527492;-0.783734;, + 0.868350;0.160550;-0.469245;, + 0.532377;0.790350;0.303185;, + -0.480825;0.612885;0.627040;, + -0.898116;-0.162902;0.408473;, + -0.523134;-0.798786;-0.297106;, + 0.582448;-0.641920;-0.498692;, + 0.908436;0.168554;-0.382535;, + 0.589372;0.731411;0.343042;, + -0.130859;0.472769;0.871416;, + -0.448382;-0.259742;0.855271;, + -0.122373;-0.962341;0.242745;, + 0.738199;-0.672946;-0.046963;, + 0.954319;0.143966;-0.261819;, + 0.684008;0.694622;0.222786;, + 0.114891;0.475550;0.872154;, + 0.045777;-0.249705;0.967239;, + 0.271381;-0.699800;0.660782;, + 0.788837;-0.361752;0.496862;, + 0.654098;0.265568;0.708258;, + 0.497233;-0.613394;-0.613602;, + 0.827960;0.156360;-0.538548;, + 0.441440;0.854796;0.272864;, + -0.263126;0.546005;0.795389;, + -0.560849;-0.216898;0.799002;, + -0.170563;-0.985283;0.011240;, + 0.446317;-0.594873;-0.668526;, + 0.761715;0.172975;-0.624396;, + 0.374777;0.907354;0.190397;, + -0.306469;0.543138;0.781715;, + -0.462053;-0.212056;0.861127;, + -0.101970;-0.991153;0.084961;, + 0.308543;-0.543003;-0.780992;, + 0.601734;0.229221;-0.765097;, + 0.257610;0.966081;0.018033;, + -0.452795;0.600684;0.658905;, + -0.728428;-0.184026;0.659945;, + -0.306842;-0.947200;-0.093060;, + 0.335867;-0.559796;-0.757510;, + 0.736062;0.204405;-0.645315;, + 0.336864;0.934902;0.111722;, + -0.456215;0.614991;0.643159;, + -0.874861;-0.145367;0.462046;, + -0.474606;-0.826156;-0.303671;, + 0.471488;-0.618541;-0.628574;, + 0.864110;0.144078;-0.482240;, + 0.488532;0.813107;0.316535;, + -0.263346;0.532405;0.804484;, + -0.629310;-0.211268;0.747886;, + -0.275179;-0.957479;-0.086667;, + 0.439782;-0.600782;-0.667573;, + 0.813245;0.167489;-0.557296;, + 0.428662;0.870727;0.241007;, + -0.345261;0.558515;0.754225;, + -0.683079;-0.206987;0.700399;, + -0.272796;-0.960329;-0.057884;, + 0.252684;-0.497453;-0.829875;, + 0.769539;0.190134;-0.609638;, + 0.357894;0.925399;0.124696;, + -0.537976;0.628508;0.561747;, + -0.898785;-0.123848;0.420531;, + -0.560059;-0.751673;-0.348312;, + 0.333904;-0.534319;-0.776538;, + 0.850206;0.173471;-0.497050;, + 0.514423;0.813291;0.271896;, + -0.467237;0.607846;0.642038;, + -0.877223;-0.172768;0.447918;, + -0.507195;-0.819398;-0.267097;, + 0.554845;-0.638321;-0.533566;, + 0.886565;0.182189;-0.425217;, + 0.568559;0.763899;0.305283;, + -0.165833;0.490715;0.855393;, + -0.481870;-0.264147;0.835480;, + -0.153896;-0.966580;0.205035;, + 0.701497;-0.701342;-0.126576;, + 0.933336;0.163949;-0.319380;, + 0.662234;0.725654;0.186743;, + 0.068015;0.505465;0.860162;, + -0.023671;-0.259197;0.965534;, + 0.209331;-0.750697;0.626605;, + 0.782976;-0.407275;0.470186;, + 0.636095;0.307826;0.707549;, + 0.501872;-0.611244;-0.611969;, + 0.840103;0.146832;-0.522176;, + 0.462884;0.829633;0.312165;, + -0.265565;0.544402;0.795677;, + -0.559285;-0.215968;0.800349;, + -0.160805;-0.986764;0.020920;, + 0.440673;-0.592878;-0.674020;, + 0.759649;0.173641;-0.626724;, + 0.382754;0.902313;0.198317;, + -0.292472;0.536722;0.791448;, + -0.440960;-0.214732;0.871461;, + -0.091558;-0.991696;0.090310;, + 0.294817;-0.536769;-0.790545;, + 0.589764;0.232855;-0.773277;, + 0.257798;0.966021;0.018516;, + -0.447421;0.598812;0.664258;, + -0.724551;-0.183967;0.664215;, + -0.309688;-0.945740;-0.098333;, + 0.324769;-0.553847;-0.766667;, + 0.732523;0.205397;-0.649017;, + 0.341567;0.932610;0.116491;, + -0.451790;0.613142;0.648030;, + -0.878402;-0.141688;0.456437;, + -0.485264;-0.815031;-0.316611;, + 0.467816;-0.617010;-0.632809;, + 0.867241;0.140845;-0.477553;, + 0.500477;0.800802;0.328997;, + -0.247760;0.524381;0.814641;, + -0.619273;-0.212829;0.755781;, + -0.276709;-0.956627;-0.091087;, + 0.434085;-0.598441;-0.673379;, + 0.814055;0.166484;-0.556415;, + 0.438174;0.862994;0.251485;, + -0.334234;0.553031;0.763180;, + -0.676607;-0.208759;0.706132;, + -0.274057;-0.959798;-0.060661;, + 0.236650;-0.488015;-0.840142;, + 0.767921;0.190323;-0.611616;, + 0.363214;0.922428;0.131159;, + -0.537145;0.628597;0.562442;, + -0.902882;-0.118846;0.413135;, + -0.572783;-0.736091;-0.360680;, + 0.323287;-0.527601;-0.785571;, + 0.852535;0.170393;-0.494115;, + 0.524892;0.802194;0.284559;, + -0.462849;0.606173;0.646780;, + -0.880811;-0.169994;0.441898;, + -0.517099;-0.808991;-0.279539;, + 0.555697;-0.637603;-0.533538;, + 0.890633;0.178263;-0.418325;, + 0.579718;0.749722;0.319132;, + -0.146317;0.479991;0.864985;, + -0.465888;-0.265274;0.844143;, + -0.147113;-0.966458;0.210517;, + 0.709732;-0.695413;-0.112611;, + 0.938240;0.157523;-0.308047;, + 0.672570;0.712761;0.199049;, + 0.090407;0.490418;0.866785;, + 0.003757;-0.259574;0.965716;, + 0.230207;-0.738918;0.633249;, + 0.787167;-0.396002;0.472811;, + 0.646355;0.289593;0.705947;, + 0.516966;-0.608447;-0.602112;, + 0.874128;0.114718;-0.471953;, + 0.517818;0.767923;0.377039;, + -0.212404;0.516342;0.829624;, + -0.588810;-0.221694;0.777274;, + -0.185391;-0.982309;-0.026433;, + 0.400936;-0.557240;-0.727141;, + 0.742127;0.178734;-0.645989;, + 0.419212;0.878727;0.228253;, + -0.215861;0.514387;0.829946;, + -0.329958;-0.208178;0.920755;, + -0.091396;-0.995301;0.031967;, + 0.255763;-0.507343;-0.822915;, + 0.544399;0.251635;-0.800193;, + 0.270805;0.961926;0.036910;, + -0.409694;0.584477;0.700383;, + -0.665604;-0.180080;0.724253;, + -0.229438;-0.970608;-0.072654;, + 0.271222;-0.525963;-0.806102;, + 0.711132;0.211599;-0.670461;, + 0.367730;0.919170;0.141072;, + -0.416769;0.599193;0.683573;, + -0.878049;-0.128957;0.460869;, + -0.529271;-0.771744;-0.352540;, + 0.434921;-0.604440;-0.667455;, + 0.865473;0.129965;-0.483804;, + 0.547625;0.754213;0.362311;, + -0.182521;0.489258;0.852827;, + -0.578412;-0.225413;0.783982;, + -0.294771;-0.948174;-0.118642;, + 0.395442;-0.582473;-0.710176;, + 0.805338;0.164263;-0.569604;, + 0.478885;0.830388;0.284824;, + -0.280896;0.526446;0.802466;, + -0.646450;-0.219247;0.730776;, + -0.290151;-0.953341;-0.083390;, + 0.170371;-0.449244;-0.877014;, + 0.752258;0.192773;-0.630037;, + 0.391734;0.906032;0.160159;, + -0.512610;0.622446;0.591432;, + -0.904174;-0.101462;0.414939;, + -0.620865;-0.680541;-0.389089;, + 0.271016;-0.497964;-0.823761;, + 0.848604;0.160114;-0.504217;, + 0.567325;0.759364;0.318604;, + -0.427834;0.592777;0.682329;, + -0.881165;-0.159727;0.445011;, + -0.558070;-0.768267;-0.313567;, + 0.535967;-0.630109;-0.561873;, + 0.892887;0.164047;-0.419335;, + 0.623516;0.698005;0.352159;, + -0.071795;0.436064;0.897047;, + -0.409232;-0.281070;0.868060;, + -0.136787;-0.970094;0.200516;, + 0.717370;-0.686582;-0.118260;, + 0.944105;0.133893;-0.301228;, + 0.711039;0.665994;0.225558;, + 0.170183;0.433298;0.885037;, + 0.089845;-0.282505;0.955049;, + 0.288287;-0.730355;0.619251;, + 0.804020;-0.394183;0.445166;, + 0.689840;0.223648;0.688551;, + 0.361674;0.913139;-0.188064;, + -0.306548;-0.658610;0.687213;, + -0.365602;-0.684685;0.630508;, + -0.220903;-0.824258;0.521346;, + -0.581318;-0.745933;0.325044;, + -0.588806;0.000143;0.808275;, + -0.496007;-0.714259;0.493772;, + 0.593600;0.707690;-0.383162;, + -0.196206;0.085242;-0.976851;, + -0.140780;0.989203;-0.040729;, + -0.715299;-0.614274;-0.333189;, + -0.975349;0.164237;-0.147377;, + -0.212301;-0.514564;0.830754;, + -0.297653;-0.114959;0.947727;, + 0.980593;0.188926;-0.052382;, + 0.665653;0.649226;0.367983;, + 0.302101;0.824457;0.478545;, + -0.123513;0.634708;0.762817;, + 0.426128;-0.774572;-0.467389;, + 0.781451;-0.186179;-0.595543;, + -0.113738;-0.981032;0.156973;, + -0.125935;-0.756333;0.641950;, + 0.214009;0.839435;0.499548;, + -0.315118;0.517253;0.795707;, + -0.459333;-0.851040;0.254447;, + -0.557305;-0.389761;0.733143;, + 0.644141;0.420432;-0.638999;, + 0.740902;0.430944;-0.515123;, + -0.149490;0.928257;0.340575;, + -0.077287;-0.823913;-0.561422;, + 0.511461;-0.189138;-0.838233;, + -0.381149;0.923821;0.035779;, + 0.392217;0.560751;0.729194;, + -0.184282;0.976156;0.114712;, + -0.567905;0.521114;-0.637122;, + 0.473718;0.414055;-0.777271;, + -0.529914;-0.324726;-0.783418;, + 0.226517;-0.970474;0.082885;, + -0.148924;-0.632604;-0.760022;, + 0.527039;0.781296;-0.334374;, + 0.834983;0.264476;-0.482552;, + 0.675963;0.077412;-0.732859;, + 0.160126;0.190092;-0.968620;, + 0.228376;-0.127237;-0.965223;, + -0.057386;0.245516;0.967692;, + -0.657416;-0.744773;-0.114531;, + -0.274099;0.701037;-0.658344;, + 0.876642;-0.442049;-0.189978;, + -0.779526;0.329121;0.532934;, + 0.327724;-0.696016;0.638873;, + -0.578535;0.674540;0.458576;, + -0.984941;0.135767;-0.107045;, + 0.422834;0.836078;-0.349550;, + 0.828789;0.540638;-0.144288;, + -0.034244;0.095893;-0.994802;, + 0.641365;-0.305210;-0.703916;, + 0.923772;-0.052794;0.379286;, + -0.076548;0.939750;-0.333181;, + -0.119540;-0.960478;0.251382;, + 0.669596;-0.615981;-0.414980;, + 0.303030;-0.186090;0.934635;, + 0.391442;0.389355;0.833772;, + -0.190416;0.835663;0.515178;, + 0.353633;-0.752104;0.556133;, + 0.520040;-0.156982;0.839592;, + -0.509830;-0.838926;-0.190465;, + 0.146090;-0.981553;0.123336;, + -0.607672;0.793048;-0.042537;, + -0.897162;0.033159;-0.440455;, + 0.839542;-0.269781;-0.471581;, + 0.963227;0.157435;-0.217736;, + 0.259132;0.699308;-0.666198;, + -0.604433;0.762690;0.230140;, + -0.423330;0.778916;0.462689;, + 0.434554;0.075722;0.897457;, + -0.006566;0.677353;0.735628;, + -0.749936;0.407739;-0.520908;, + -0.822491;0.188949;-0.536477;, + -0.756906;-0.145054;-0.637223;, + -0.423190;-0.716621;-0.554404;, + 0.227209;-0.966292;0.121063;, + 0.317550;-0.933835;0.164662;, + 0.496370;-0.182435;0.848725;, + 0.533776;-0.178235;0.826629;, + 0.604641;-0.410889;0.682334;, + 0.097373;-0.993304;-0.062171;, + -0.544149;0.817947;0.186718;, + -0.671652;0.718204;-0.181845;, + 0.520633;-0.800173;0.297766;, + -0.610984;0.085141;-0.787051;, + -0.315955;0.940947;0.121620;, + -0.451041;-0.364729;-0.814576;, + -0.034059;-0.236375;-0.971065;, + -0.126856;0.710394;-0.692277;, + 0.329848;0.675467;0.659503;, + 0.509804;-0.823253;0.249710;, + 0.828231;-0.560342;0.007058;, + 0.898012;0.382183;0.217970;, + 0.638411;-0.335141;0.692901;, + 0.521920;-0.736948;0.429544;, + 0.653620;0.114523;0.748107;, + 0.219228;-0.910600;-0.350351;, + 0.106711;0.863012;0.493785;, + -0.701914;0.653797;-0.282606;, + -0.566975;-0.044447;-0.822535;, + -0.698404;-0.196958;-0.688069;, + -0.634338;-0.406257;-0.657701;, + -0.726870;-0.133185;-0.673737;, + -0.790864;0.239728;-0.563085;, + -0.657555;0.711316;-0.248296;, + 0.154310;0.679156;0.717590;, + -0.231918;0.882106;0.410004;, + 0.412377;-0.755835;0.508585;, + 0.140943;-0.970084;0.197668;, + -0.311225;-0.875510;-0.369624;, + -0.597394;0.775849;-0.202926;, + 0.489055;-0.692585;0.530237;, + 0.491338;-0.534968;0.687311;, + 0.489758;-0.036774;0.871083;, + 0.438815;0.143443;0.887054;, + 0.286417;0.500491;0.816991;, + -0.627373;0.683167;-0.373744;, + -0.335799;0.770037;-0.542478;, + 0.129022;0.958535;0.254096;, + -0.414688;0.073903;-0.906958;, + -0.101432;0.966761;0.234701;, + -0.755011;0.321454;-0.571512;, + 0.578072;-0.401336;0.710466;, + -0.311908;0.427644;-0.848430;, + 0.156866;-0.502085;-0.850473;, + 0.197343;0.520839;-0.830532;, + 0.891275;-0.244321;-0.382017;, + 0.886836;0.434833;0.156336;, + -0.667053;-0.649082;0.365696;, + -0.890395;-0.035250;0.453822;, + 0.773169;-0.532910;0.343826;, + -0.301252;0.328615;0.895131;, + -0.552096;-0.122315;-0.824760;, + -0.523265;0.793302;-0.311232;, + 0.178067;-0.970384;-0.163240;, + -0.685065;0.319620;-0.654621;, + 0.472466;-0.858796;0.198106;, + 0.564413;-0.431202;0.703920;, + 0.113817;-0.948975;0.294097;, + -0.499148;-0.545190;-0.673512;, + 0.108599;0.911995;0.395565;, + -0.283846;-0.779062;0.559012;, + 0.894433;0.447026;-0.012553;, + -0.593050;0.804457;0.033773;, + 0.369368;-0.910324;-0.186757;, + 0.475166;0.851493;0.221757;, + -0.703251;-0.226621;0.673855;, + -0.714900;-0.212902;0.666026;, + -0.901123;0.269970;-0.339253;, + -0.721934;-0.308194;0.619538;, + -0.406662;0.800438;-0.440369;, + -0.636644;0.614134;-0.466395;, + -0.410648;0.785543;0.462915;, + -0.378074;0.914236;0.145713;, + -0.082476;-0.992964;0.084972;, + 0.519481;-0.388496;0.761059;, + -0.037907;-0.992141;0.119241;, + 0.491463;-0.565202;0.662579;, + 0.194400;-0.959689;0.202992;, + -0.096513;-0.870901;-0.481889;, + 0.146372;-0.791374;0.593551;, + 0.771799;-0.600975;0.207740;, + 0.351827;0.537583;0.766305;, + 0.117570;-0.811190;0.572842;, + 0.382914;-0.755359;0.531799;, + 0.188469;-0.005536;0.982064;, + -0.489616;0.263036;0.831317;, + -0.823845;-0.530391;-0.199912;, + 0.593325;-0.803737;0.044415;, + 0.971456;-0.226261;0.071272;, + -0.774625;-0.362944;-0.517907;, + 0.910154;-0.232627;0.342788;, + 0.500593;0.666086;0.552935;, + -0.712383;0.688225;-0.137322;, + 0.268876;-0.898540;-0.346889;, + -0.913491;-0.404743;-0.041435;, + 0.880171;-0.136698;0.454546;, + 0.498824;0.566633;0.655822;, + -0.755600;0.570720;0.321476;, + 0.122431;-0.981567;0.146753;, + -0.765877;-0.131961;0.629300;, + 0.760728;-0.149787;0.631552;, + 0.338248;0.393374;0.854895;, + -0.264307;0.634389;0.726424;, + -0.213763;-0.497719;0.840584;, + -0.797886;0.487994;-0.353892;, + -0.371167;0.862227;0.344672;, + -0.796796;0.254304;-0.548129;, + -0.806062;0.342622;-0.482571;, + -0.211446;0.977387;0.002139;, + 0.091470;-0.973373;0.210186;, + 0.342640;-0.450430;0.824445;, + -0.533434;-0.631638;-0.562567;, + -0.857968;0.149295;-0.491531;, + -0.449701;0.833860;0.320073;, + 0.247538;0.533303;0.808896;, + 0.568264;-0.213516;0.794661;, + 0.155037;-0.987820;0.013252;, + -0.447982;-0.577196;-0.682757;, + -0.751659;0.174053;-0.636172;, + -0.374900;0.906643;0.193515;, + 0.266062;0.534893;0.801936;, + 0.351269;-0.182121;0.918391;, + 0.050535;-0.994436;0.092426;, + -0.302952;-0.528059;-0.793330;, + -0.549673;0.237349;-0.800952;, + -0.224332;0.974321;-0.019323;, + 0.457685;0.602796;0.653575;, + 0.684758;-0.171791;0.708233;, + 0.194642;-0.980191;-0.036613;, + -0.320375;-0.545709;-0.774314;, + -0.721049;0.208194;-0.660866;, + -0.322509;0.941211;0.100551;, + 0.464637;0.616931;0.635224;, + 0.890129;-0.133886;0.435598;, + 0.489652;-0.803849;-0.337738;, + -0.482310;-0.621551;-0.617294;, + -0.877595;0.134138;-0.460255;, + -0.508349;0.786638;0.350401;, + 0.231555;0.510140;0.828335;, + 0.589307;-0.209611;0.780244;, + 0.252160;-0.965191;-0.069438;, + -0.443595;-0.600833;-0.664998;, + -0.815942;0.164862;-0.554130;, + -0.437536;0.861083;0.259033;, + 0.330057;0.546220;0.769874;, + 0.657713;-0.211590;0.722941;, + 0.245100;-0.968694;-0.039466;, + -0.218196;-0.468925;-0.855862;, + -0.762091;0.193297;-0.617943;, + -0.349430;0.929707;0.116373;, + 0.557674;0.637189;0.531969;, + 0.917107;-0.107418;0.383895;, + 0.584169;-0.712581;-0.388554;, + -0.320194;-0.517249;-0.793681;, + -0.861337;0.165443;-0.480341;, + -0.529397;0.791179;0.306226;, + 0.475036;0.610817;0.633438;, + 0.891719;-0.164077;0.421801;, + 0.519657;-0.799974;-0.299996;, + -0.579460;-0.642332;-0.501632;, + -0.902703;0.169362;-0.395530;, + -0.586870;0.729783;0.350716;, + 0.120529;0.460012;0.879694;, + 0.424021;-0.257028;0.868414;, + 0.109887;-0.957719;0.265895;, + -0.737915;-0.674242;-0.029655;, + -0.953246;0.142139;-0.266682;, + -0.681447;0.696126;0.225917;, + -0.117801;0.461501;0.879284;, + -0.057760;-0.247480;0.967170;, + -0.276840;-0.682651;0.676274;, + -0.783249;-0.356084;0.509632;, + -0.649761;0.259288;0.714549;, + -0.490701;-0.611734;-0.620479;, + -0.814477;0.160417;-0.557578;, + -0.437465;0.857775;0.269901;, + 0.252546;0.535085;0.806166;, + 0.530851;-0.218848;0.818720;, + 0.153105;-0.987769;0.029507;, + -0.438220;-0.592052;-0.676341;, + -0.742663;0.176560;-0.645971;, + -0.366910;0.912208;0.182358;, + 0.295401;0.533999;0.792201;, + 0.430440;-0.211071;0.877593;, + 0.080883;-0.991491;0.101995;, + -0.297424;-0.534529;-0.791086;, + -0.573038;0.233183;-0.785654;, + -0.241843;0.970315;0.000870;, + 0.445511;0.597421;0.666789;, + 0.711169;-0.187864;0.677455;, + 0.294543;-0.951626;-0.087479;, + -0.326742;-0.550893;-0.767956;, + -0.717174;0.210252;-0.664422;, + -0.325128;0.940226;0.101326;, + 0.449368;0.612043;0.650747;, + 0.866118;-0.148627;0.477232;, + 0.471883;-0.827537;-0.304152;, + -0.465089;-0.615834;-0.635956;, + -0.854249;0.147700;-0.498441;, + -0.486239;0.814255;0.317113;, + 0.252472;0.521534;0.815021;, + 0.604359;-0.212396;0.767879;, + 0.264549;-0.961449;-0.075028;, + -0.432019;-0.597419;-0.675611;, + -0.798667;0.171837;-0.576717;, + -0.423554;0.874399;0.236705;, + 0.335949;0.550139;0.764517;, + 0.662056;-0.212295;0.718758;, + 0.258679;-0.964803;-0.047336;, + -0.240978;-0.484831;-0.840755;, + -0.752439;0.197302;-0.628417;, + -0.348656;0.930401;0.113105;, + 0.533739;0.628202;0.566114;, + 0.892616;-0.126233;0.432784;, + 0.558454;-0.751040;-0.352235;, + -0.325458;-0.524380;-0.786831;, + -0.841062;0.178988;-0.510468;, + -0.510649;0.815434;0.272590;, + 0.460786;0.605148;0.649209;, + 0.868674;-0.174616;0.463589;, + 0.503088;-0.821745;-0.267651;, + -0.550996;-0.638131;-0.537766;, + -0.878623;0.183950;-0.440663;, + -0.565503;0.764222;0.310116;, + 0.154787;0.478816;0.864162;, + 0.455817;-0.261788;0.850704;, + 0.139459;-0.963610;0.228052;, + -0.702169;-0.703184;-0.111764;, + -0.930325;0.163693;-0.328175;, + -0.658831;0.728629;0.187194;, + -0.072427;0.492303;0.867406;, + 0.007565;-0.256091;0.966623;, + -0.219306;-0.733148;0.643738;, + -0.780241;-0.399104;0.481601;, + -0.633977;0.303269;0.711408;, + -0.495277;-0.609732;-0.618812;, + -0.827977;0.150869;-0.540085;, + -0.460415;0.831003;0.312174;, + 0.254891;0.533546;0.806448;, + 0.529349;-0.217483;0.820055;, + 0.143045;-0.988931;0.039412;, + -0.432483;-0.589889;-0.681901;, + -0.740510;0.177313;-0.648232;, + -0.375236;0.907074;0.190826;, + 0.281251;0.527055;0.801942;, + 0.409295;-0.213533;0.887063;, + 0.070334;-0.991770;0.106986;, + -0.283571;-0.527836;-0.800610;, + -0.560679;0.236847;-0.793437;, + -0.241981;0.970280;0.001457;, + 0.440073;0.595333;0.672246;, + 0.707551;-0.187802;0.681250;, + 0.297766;-0.950032;-0.093671;, + -0.315564;-0.544433;-0.777182;, + -0.713702;0.211367;-0.667797;, + -0.330019;0.937937;0.106587;, + 0.444854;0.609993;0.655754;, + 0.870079;-0.144889;0.471136;, + 0.482938;-0.815853;-0.318049;, + -0.461342;-0.614098;-0.640349;, + -0.857754;0.144449;-0.493348;, + -0.498612;0.801373;0.330434;, + 0.236801;0.512915;0.825133;, + 0.594213;-0.213844;0.775359;, + 0.266370;-0.960543;-0.080021;, + -0.426219;-0.594861;-0.681526;, + -0.799637;0.170933;-0.575641;, + -0.433484;0.866383;0.247934;, + 0.324837;0.544170;0.773537;, + 0.655674;-0.214147;0.724039;, + 0.260147;-0.964238;-0.050689;, + -0.224869;-0.474782;-0.850891;, + -0.750921;0.197735;-0.630094;, + -0.354271;0.927410;0.120013;, + 0.532960;0.628250;0.566794;, + 0.897185;-0.121051;0.424742;, + 0.571470;-0.734766;-0.365432;, + -0.314900;-0.517199;-0.795828;, + -0.843867;0.175890;-0.506904;, + -0.521492;0.803821;0.286214;, + 0.456355;0.603310;0.654031;, + 0.872676;-0.171770;0.457090;, + 0.513321;-0.810862;-0.281077;, + -0.551857;-0.637341;-0.537819;, + -0.883114;0.179896;-0.433297;, + -0.576959;0.749316;0.325029;, + 0.135489;0.467543;0.873525;, + 0.440209;-0.262810;0.858573;, + 0.133199;-0.963203;0.233450;, + -0.710203;-0.697232;-0.097362;, + -0.935703;0.156918;-0.315970;, + -0.669545;0.715214;0.200446;, + -0.094199;0.476771;0.873966;, + -0.018339;-0.256626;0.966337;, + -0.238806;-0.721445;0.649991;, + -0.783588;-0.388614;0.484736;, + -0.643422;0.284541;0.710665;, + -0.510465;-0.607468;-0.608611;, + -0.865352;0.117258;-0.487255;, + -0.517106;0.766062;0.381772;, + 0.201577;0.503110;0.840385;, + 0.559705;-0.225972;0.797288;, + 0.169147;-0.985551;-0.008917;, + -0.391192;-0.551987;-0.736396;, + -0.722016;0.183057;-0.667221;, + -0.413059;0.883017;0.222853;, + 0.204883;0.502219;0.840119;, + 0.302341;-0.206622;0.930536;, + 0.074487;-0.996148;0.046270;, + -0.244152;-0.497096;-0.832638;, + -0.514194;0.255863;-0.818620;, + -0.255335;0.966621;0.021159;, + 0.401612;0.579399;0.709228;, + 0.649553;-0.183473;0.737847;, + 0.220057;-0.972841;-0.071803;, + -0.261639;-0.514291;-0.816731;, + -0.692069;0.218095;-0.688095;, + -0.357168;0.924491;0.133220;, + 0.408987;0.594527;0.692291;, + 0.870070;-0.132357;0.474826;, + 0.528108;-0.770628;-0.356699;, + -0.427611;-0.599957;-0.676166;, + -0.856204;0.133913;-0.498980;, + -0.546962;0.752871;0.366086;, + 0.171512;0.475490;0.862840;, + 0.552739;-0.226309;0.802037;, + 0.285690;-0.951981;-0.110058;, + -0.386791;-0.577398;-0.719030;, + -0.790608;0.169376;-0.588431;, + -0.475563;0.832664;0.283745;, + 0.271095;0.515384;0.812949;, + 0.625528;-0.224964;0.747065;, + 0.277394;-0.957771;-0.075676;, + -0.158619;-0.433804;-0.886935;, + -0.735093;0.201108;-0.647452;, + -0.383943;0.910904;0.151136;, + 0.507899;0.621019;0.596970;, + 0.898964;-0.103555;0.425605;, + 0.620222;-0.677171;-0.395935;, + -0.262650;-0.485562;-0.833813;, + -0.840648;0.165742;-0.515597;, + -0.564993;0.759241;0.323012;, + 0.420631;0.588517;0.690447;, + 0.873310;-0.161587;0.459587;, + 0.555273;-0.768494;-0.317946;, + -0.531432;-0.628929;-0.567476;, + -0.885679;0.165648;-0.433744;, + -0.621552;0.695340;0.360798;, + 0.062071;0.421776;0.904573;, + 0.384608;-0.278152;0.880175;, + 0.124293;-0.966893;0.222865;, + -0.717453;-0.688923;-0.103178;, + -0.942100;0.132658;-0.307975;, + -0.709039;0.666859;0.229265;, + -0.171508;0.418312;0.891964;, + -0.099615;-0.279056;0.955094;, + -0.293476;-0.713393;0.636351;, + -0.798889;-0.388529;0.459153;, + -0.684430;0.217897;0.695756;, + -0.341059;0.917128;-0.206289;, + 0.285530;-0.650577;0.703720;, + 0.340151;-0.678735;0.650858;, + 0.201228;-0.818516;0.538087;, + 0.561306;-0.750896;0.347982;, + 0.563755;-0.000870;0.825942;, + 0.476551;-0.712046;0.515644;, + -0.572616;0.710735;-0.408614;, + 0.160884;0.118423;-0.979843;, + 0.092128;0.995149;-0.034495;, + 0.715299;-0.614274;-0.333189;, + 0.975349;0.164237;-0.147377;, + 0.212302;-0.514565;0.830753;, + 0.364121;-0.117457;0.923915;, + -0.972391;0.228560;0.047083;, + -0.721943;0.609310;0.327933;, + -0.355783;0.818541;0.451009;, + 0.166307;0.647301;0.743870;, + -0.492298;-0.784288;-0.377538;, + -0.924095;-0.209976;-0.319310;, + 0.079861;-0.979451;0.185195;, + 0.091672;-0.754828;0.649485;, + -0.169599;0.852875;0.493802;, + 0.305489;0.522454;0.796064;, + 0.451821;-0.854320;0.256893;, + 0.549353;-0.390720;0.738613;, + -0.644141;0.420432;-0.638999;, + -0.740902;0.430944;-0.515123;, + 0.149490;0.928257;0.340575;, + 0.077287;-0.823913;-0.561422;, + -0.511461;-0.189138;-0.838233;, + 0.343698;0.922858;0.173795;, + -0.260653;0.953967;0.148347;, + 0.783381;0.503370;0.364599;, + -0.066996;0.879109;0.471889;, + -0.710934;0.444973;0.544584;, + 0.289636;0.949061;0.124075;, + -0.362112;0.926712;0.100395;, + -0.000001;0.818760;0.574136;, + -0.000000;0.868934;-0.494927;, + -0.000000;0.630324;-0.776332;, + 0.022686;-0.036383;0.999080;, + -0.000000;0.298174;-0.954511;, + -0.000000;0.998500;0.054759;, + -0.000000;-0.444151;0.895952;, + -0.000000;-0.029730;-0.999558;, + -0.142878;-0.121955;-0.982198;, + -0.808123;-0.461550;-0.365936;, + -0.793812;0.600245;-0.097818;, + -0.540286;0.724558;-0.427911;, + -0.496164;0.335976;-0.800588;, + -0.654263;-0.049613;-0.754638;, + -0.660157;-0.104107;0.743878;, + -0.861728;0.431543;-0.266824;, + -0.338650;-0.330283;0.881039;, + -0.231714;-0.275342;0.933003;, + -0.899678;-0.251384;-0.356911;, + -0.563708;-0.395781;-0.724976;, + -0.944986;-0.217661;0.244183;, + -0.232970;0.970399;0.063643;, + -0.886311;0.419497;-0.196151;, + -0.284112;0.944212;0.166567;, + -0.394637;-0.137254;0.908528;, + 0.012819;0.940525;0.339483;, + 0.382016;0.040071;0.923286;, + -0.733140;-0.437535;0.520643;, + -0.879018;0.070016;-0.471619;, + -0.965289;-0.090055;-0.245168;, + -0.404283;-0.450662;0.795902;, + -0.432713;-0.354931;0.828724;, + -0.302341;0.947980;-0.099615;, + -0.235609;0.971832;-0.005539;, + -0.978433;-0.005143;0.206502;, + -0.422789;0.519154;-0.742784;, + -0.929825;-0.231328;0.286203;, + -0.699443;-0.209423;-0.683316;, + -0.534104;0.546724;-0.644846;, + -0.806852;-0.393759;-0.440389;, + -0.691836;-0.542995;-0.475940;, + -0.877724;-0.460197;-0.133489;, + -0.178300;-0.323577;-0.929251;, + -0.937849;0.041613;0.344540;, + 0.109013;0.571900;0.813048;, + -0.863890;0.503678;-0.001488;, + -0.683696;0.235194;-0.690828;, + -0.778100;0.232231;-0.583635;, + -0.438702;-0.571900;-0.693160;, + -0.650020;0.481538;-0.587874;, + 0.244916;-0.017761;-0.969382;, + -0.903353;-0.418768;0.092664;, + -0.958406;0.281953;-0.044275;, + -0.880526;-0.190072;0.434220;, + -0.935327;-0.048151;-0.350493;, + -0.760323;0.281570;-0.585344;, + -0.722182;-0.107325;-0.683326;, + -0.967430;-0.242896;0.071282;, + -0.927251;-0.170149;-0.333550;, + -0.812213;-0.330990;0.480369;, + -0.587234;0.666265;-0.459617;, + 0.466081;0.838695;0.281709;, + -0.994998;-0.099822;0.003920;, + -0.742055;0.487282;0.460338;, + -0.638869;-0.759326;-0.123572;, + -0.715743;0.327208;0.616966;, + 0.371066;-0.555663;-0.744008;, + -0.559606;-0.645175;-0.520183;, + -0.649884;-0.689957;-0.318763;, + 0.681463;-0.724191;0.105620;, + -0.880620;-0.412930;0.232375;, + 0.709052;-0.704833;0.021360;, + -0.701635;0.645253;-0.302255;, + 0.427690;0.903455;0.029168;, + -0.710107;0.193070;-0.677105;, + -0.778125;0.252214;0.575248;, + 0.148716;0.940575;0.305291;, + 0.238521;-0.062437;-0.969128;, + -0.963144;0.085488;-0.255042;, + 0.369513;0.922029;-0.115428;, + -0.958565;-0.067036;-0.276873;, + 0.270983;-0.447194;-0.852400;, + -0.772474;0.623053;0.122835;, + 0.815356;0.157407;-0.557151;, + -0.138796;-0.893977;-0.426076;, + 0.364772;0.804729;-0.468352;, + -0.981550;-0.062615;-0.180661;, + 0.260027;-0.887566;-0.380279;, + -0.491771;0.675224;-0.549758;, + 0.216661;-0.945949;-0.241328;, + 0.945124;0.201537;-0.257146;, + 0.329095;0.723521;-0.606806;, + 0.194660;-0.960634;0.198216;, + -0.996307;-0.033233;-0.079173;, + -0.909493;0.374402;-0.180680;, + 0.854421;0.045584;-0.517577;, + 0.133919;-0.936841;0.323101;, + 0.090562;0.392235;-0.915396;, + -0.081213;-0.839344;0.537500;, + -0.974141;-0.162751;0.156724;, + -0.567495;0.823354;0.006191;, + 0.012874;0.004539;-0.999907;, + -0.920422;-0.390245;0.023083;, + 0.556206;0.718401;-0.417774;, + -0.948091;-0.001386;0.317996;, + -0.050023;-0.977498;-0.204928;, + -0.311902;0.571486;-0.759026;, + -0.196380;-0.929366;-0.312591;, + -0.949563;-0.144224;0.278441;, + -0.792912;0.574314;-0.203603;, + 0.639171;-0.463937;-0.613370;, + -0.225631;-0.823775;0.520082;, + 0.170996;0.152764;-0.973357;, + -0.879432;-0.156838;0.449446;, + 0.524143;-0.666593;0.530026;, + -0.269195;0.577034;-0.771081;, + 0.852228;-0.478675;-0.211134;, + -0.343783;-0.770945;0.536151;, + -0.679363;0.590395;0.435775;, + -0.069213;0.427125;-0.901540;, + -0.757904;-0.558344;-0.337392;, + 0.136274;0.884818;0.445562;, + 0.102555;-0.767205;-0.633151;, + -0.844716;-0.397357;0.358555;, + -0.146612;0.912426;-0.382077;, + 0.511756;-0.836540;-0.195723;, + -0.619780;-0.487134;0.615283;, + -0.387513;0.049103;-0.920555;, + -0.707902;-0.012374;0.706203;, + 0.139613;-0.971369;0.192223;, + -0.431272;0.675463;-0.598125;, + 0.565995;-0.635897;-0.524676;, + -0.798576;-0.307164;0.517617;, + 0.372732;0.864234;-0.337891;, + 0.014166;0.945681;-0.324786;, + 0.287479;0.796616;-0.531751;, + 0.136032;0.650716;-0.747037;, + -0.122359;-0.207776;0.970493;, + -0.744782;-0.430097;-0.510212;, + 0.065371;-0.737389;0.672298;, + 0.825383;-0.420119;-0.377152;, + 0.793812;0.600245;-0.097818;, + 0.540286;0.724558;-0.427911;, + 0.496164;0.335976;-0.800588;, + 0.654263;-0.049613;-0.754638;, + 0.690046;-0.132524;0.711529;, + 0.945515;0.306078;-0.110984;, + 0.329239;-0.308298;0.892499;, + 0.231714;-0.275342;0.933003;, + 0.899678;-0.251384;-0.356911;, + 0.563708;-0.395781;-0.724976;, + 0.930868;-0.256053;0.260617;, + 0.232970;0.970399;0.063643;, + 0.886230;0.418543;-0.198540;, + 0.284111;0.944212;0.166568;, + 0.394636;-0.137254;0.908528;, + -0.012819;0.940525;0.339483;, + -0.382017;0.040070;0.923286;, + 0.732571;-0.437022;0.521873;, + 0.879018;0.070016;-0.471619;, + 0.965023;-0.089095;-0.246563;, + 0.404283;-0.450662;0.795902;, + 0.432713;-0.354931;0.828724;, + 0.302341;0.947980;-0.099615;, + 0.235609;0.971832;-0.005539;, + 0.993793;-0.011471;0.110653;, + 0.629863;0.520365;-0.576622;, + 0.930521;-0.221376;0.291758;, + 0.490285;-0.201883;-0.847858;, + 0.553016;0.656553;-0.512944;, + 0.836668;-0.377812;-0.396542;, + 0.642185;-0.647026;-0.411043;, + 0.872770;-0.467932;-0.138969;, + 0.366430;-0.311048;-0.876914;, + 0.940115;0.027121;0.339777;, + -0.109013;0.571900;0.813048;, + 0.863890;0.503678;-0.001488;, + 0.683696;0.235194;-0.690828;, + 0.778100;0.232231;-0.583635;, + 0.438702;-0.571900;-0.693160;, + 0.650020;0.481538;-0.587874;, + -0.244916;-0.017761;-0.969382;, + 0.903353;-0.418768;0.092664;, + 0.958406;0.281953;-0.044275;, + 0.880526;-0.190072;0.434220;, + 0.935327;-0.048151;-0.350493;, + 0.760323;0.281570;-0.585344;, + 0.722182;-0.107325;-0.683326;, + 0.967430;-0.242896;0.071282;, + 0.932085;0.115972;-0.343175;, + 0.812213;-0.330991;0.480370;, + 0.587234;0.666265;-0.459616;, + -0.466081;0.838695;0.281709;, + 0.994998;-0.099822;0.003920;, + 0.742055;0.487282;0.460338;, + 0.638869;-0.759326;-0.123572;, + 0.715743;0.327208;0.616966;, + -0.371067;-0.555662;-0.744008;, + 0.559606;-0.645176;-0.520182;, + 0.649884;-0.689957;-0.318763;, + -0.681463;-0.724191;0.105620;, + 0.880620;-0.412930;0.232375;, + -0.709052;-0.704833;0.021360;, + 0.701635;0.645253;-0.302255;, + -0.427690;0.903455;0.029168;, + 0.710107;0.193070;-0.677105;, + 0.778125;0.252214;0.575248;, + -0.148717;0.940575;0.305291;, + -0.238521;-0.062437;-0.969128;, + 0.963144;0.085488;-0.255042;, + -0.369513;0.922029;-0.115427;, + 0.958565;-0.067035;-0.276873;, + -0.270983;-0.447194;-0.852400;, + 0.772474;0.623053;0.122835;, + -0.815356;0.157406;-0.557151;, + 0.138796;-0.893977;-0.426076;, + -0.364772;0.804729;-0.468351;, + 0.981550;-0.062615;-0.180662;, + -0.260027;-0.887566;-0.380279;, + 0.491771;0.675224;-0.549757;, + -0.216662;-0.945949;-0.241327;, + -0.945124;0.201537;-0.257145;, + -0.329095;0.723521;-0.606806;, + -0.194660;-0.960634;0.198216;, + 0.996307;-0.033233;-0.079173;, + 0.909493;0.374402;-0.180680;, + -0.854421;0.045584;-0.517577;, + -0.133919;-0.936841;0.323101;, + -0.090562;0.392236;-0.915396;, + 0.081214;-0.839343;0.537501;, + 0.974141;-0.162751;0.156724;, + 0.567495;0.823354;0.006191;, + -0.012874;0.004539;-0.999907;, + 0.920422;-0.390245;0.023083;, + -0.556206;0.718401;-0.417774;, + 0.948091;-0.001386;0.317996;, + 0.050023;-0.977498;-0.204928;, + 0.311902;0.571486;-0.759026;, + 0.196380;-0.929366;-0.312591;, + 0.949563;-0.144224;0.278441;, + 0.792912;0.574314;-0.203603;, + -0.639171;-0.463937;-0.613370;, + 0.225631;-0.823775;0.520082;, + -0.170996;0.152764;-0.973357;, + 0.879431;-0.156838;0.449446;, + -0.524143;-0.666593;0.530026;, + 0.269195;0.577035;-0.771081;, + -0.852228;-0.478675;-0.211134;, + 0.343783;-0.770945;0.536151;, + 0.679363;0.590395;0.435775;, + 0.069213;0.427125;-0.901540;, + 0.757904;-0.558344;-0.337392;, + -0.136274;0.884818;0.445562;, + -0.102555;-0.767205;-0.633151;, + 0.844716;-0.397357;0.358555;, + 0.146612;0.912426;-0.382077;, + -0.511756;-0.836540;-0.195723;, + 0.619780;-0.487134;0.615283;, + 0.387513;0.049103;-0.920555;, + 0.707902;-0.012374;0.706203;, + -0.139613;-0.971369;0.192223;, + 0.431272;0.675463;-0.598125;, + -0.565995;-0.635897;-0.524676;, + 0.798576;-0.307164;0.517617;, + -0.372732;0.864234;-0.337891;, + -0.014166;0.945682;-0.324786;, + -0.287480;0.796615;-0.531751;, + -0.136031;0.650716;-0.747037;, + 0.063281;-0.182379;0.981190;, + 0.744782;-0.430097;-0.510212;, + -0.065371;-0.737389;0.672297;, + 0.242215;-0.246754;0.938320;, + 0.635245;-0.260985;0.726877;, + 0.443696;-0.614785;0.652053;, + -0.265295;-0.652176;0.710130;, + -0.648919;-0.348867;0.676163;, + -0.397813;-0.198937;0.895639;, + 0.049073;-0.204317;0.977674;, + -0.039297;-0.189054;0.981180;, + 0.042148;-0.245267;0.968539;, + 0.122612;-0.131708;0.983676;, + -0.082911;-0.112202;0.990220;, + -0.065750;-0.212323;0.974985;, + -0.107811;-0.124346;0.986365;, + 0.072040;-0.126121;0.989396;, + 0.286232;0.533920;0.795614;, + 0.681710;0.448230;0.578240;, + 0.442638;0.535858;0.718977;, + -0.272537;0.592573;0.758011;, + -0.678219;0.463836;0.569978;, + -0.469139;0.498329;0.729093;, + -0.486813;0.401144;0.775949;, + 0.270328;0.467343;0.841733;, + 0.481839;0.061419;0.874105;, + -0.260992;0.019086;0.965152;, + -0.066960;-0.234819;0.969730;, + -0.176247;-0.368579;0.912736;, + -0.079517;-0.598520;0.797152;, + -0.104641;-0.637894;0.762982;, + 0.096455;-0.656739;0.747924;, + 0.084066;-0.581895;0.808907;, + 0.160432;-0.493238;0.854973;, + 0.092826;-0.336818;0.936983;, + 0.092734;0.032753;0.995152;, + 0.229366;-0.570134;0.788884;, + -0.129323;-0.659103;0.740850;, + -0.183671;-0.023684;0.982702;, + -0.067661;0.044691;0.996707;, + 0.019304;0.109444;0.993806;, + 0.226330;-0.455250;0.861117;, + -0.140511;-0.530214;0.836140;, + 0.173978;0.048446;0.983557;, + 0.259238;-0.273146;0.926384;, + 0.073201;-0.495418;0.865565;, + -0.058649;-0.557668;0.827990;, + -0.219771;-0.310915;0.924680;, + -0.239988;-0.091534;0.966451;, + -0.291412;-0.211959;0.932820;, + -0.286618;-0.466882;0.836583;, + -0.190235;-0.605085;0.773099;, + 0.172409;-0.697401;0.695634;, + 0.280972;-0.565349;0.775523;, + 0.289547;-0.289019;0.912486;, + 0.186923;-0.086989;0.978516;, + -0.151991;-0.014575;0.988274;, + -0.131683;0.178611;0.975068;, + -0.206562;0.358665;0.910325;, + 0.105053;0.413601;0.904377;, + 0.222869;0.170993;0.959735;, + 0.108320;0.139524;0.984276;, + 0.003378;0.187304;0.982296;, + -0.090953;-0.194377;0.976701;, + 0.077236;-0.374250;0.924106;, + 0.038429;0.134035;0.990231;, + -0.111070;0.170840;0.979018;, + -0.204097;-0.632222;0.747422;, + -0.161637;-0.628760;0.760614;, + -0.175808;-0.446894;0.877142;, + -0.281966;-0.632869;0.721091;, + 0.179888;-0.708343;0.682562;, + 0.214505;-0.445287;0.869314;, + 0.152468;-0.594574;0.789453;, + 0.193876;-0.662157;0.723851;, + 0.123846;-0.611873;0.781200;, + -0.079249;-0.616369;0.783460;, + 0.049874;-0.978437;-0.200432;, + -0.035951;-0.982834;-0.180953;, + 0.077777;-0.993666;-0.081114;, + 0.403086;-0.867962;-0.290108;, + 0.558443;-0.699105;0.446535;, + -0.488240;-0.590800;0.642322;, + -0.607999;-0.786791;-0.106285;, + -0.091466;-0.994758;-0.045715;, + 0.256995;0.268178;-0.928458;, + -0.166142;0.251406;-0.953516;, + -0.095345;0.037239;0.994747;, + -0.370667;-0.065770;0.926434;, + 0.280533;-0.103181;0.954282;, + 0.207488;0.068228;0.975855;, + 0.038993;0.114275;-0.992684;, + -0.175719;0.233559;-0.956333;, + 0.165697;0.233366;-0.958167;, + 0.053631;0.218456;-0.974372;, + -0.010918;-0.937228;0.348545;, + 0.014300;-0.847026;0.531360;, + 0.004816;-0.999834;-0.017554;, + 0.002019;-0.991929;-0.126778;, + -0.393237;-0.075695;0.916316;, + -0.593252;-0.198602;0.780134;, + -0.801728;-0.276819;0.529721;, + -0.745782;-0.452954;0.488509;, + -0.649090;-0.376567;0.660969;, + -0.458591;-0.157315;0.874612;, + -0.968072;-0.167164;0.186798;, + -0.934333;-0.238125;0.265177;, + -0.890013;-0.434949;0.136735;, + -0.707919;-0.624087;-0.330705;, + -0.639626;-0.282386;-0.714938;, + -0.856324;-0.247040;-0.453521;, + -0.832452;-0.027354;0.553421;, + -0.841263;0.012869;0.540474;, + -0.853170;-0.076223;0.516034;, + -0.834930;-0.138418;0.532666;, + -0.827207;-0.174679;0.534056;, + -0.881766;-0.204181;0.425205;, + -0.920811;-0.172908;0.349584;, + -0.930713;-0.092278;0.353918;, + 0.122342;-0.917267;-0.379018;, + 0.795254;-0.584691;0.160333;, + 0.561923;-0.336734;0.755548;, + -0.150071;-0.273204;0.950178;, + -0.980461;-0.107800;0.164548;, + -0.960272;-0.212083;0.181378;, + -0.960078;-0.207732;0.187344;, + -0.932337;-0.361278;-0.015029;, + -0.945731;0.117071;0.303128;, + -0.334038;-0.502642;0.797352;, + -0.350540;-0.465852;0.812468;, + -0.651677;-0.366116;0.664286;, + -0.967035;-0.000199;0.254642;, + -0.984181;0.095585;0.149171;, + -0.626720;0.119837;0.769975;, + -0.469079;0.821207;0.324936;, + 0.328196;0.910764;-0.250592;, + -0.727588;-0.072780;0.682143;, + -0.689076;-0.199468;0.696697;, + -0.759279;0.153427;0.632421;, + -0.823955;0.147553;0.547108;, + -0.741015;0.256716;0.620479;, + -0.905729;0.033236;0.422553;, + -0.846614;0.094112;0.523821;, + -0.711348;-0.027696;0.702294;, + -0.628541;-0.139705;0.765127;, + -0.517895;-0.349245;0.780905;, + -0.389382;0.113081;0.914108;, + -0.398643;0.133025;0.907407;, + -0.438066;0.181809;0.880366;, + -0.630900;0.151210;0.760987;, + -0.683144;0.666444;0.298609;, + -0.765711;0.612011;0.197811;, + -0.885977;0.311352;-0.343665;, + -0.882389;0.457062;-0.111735;, + -0.312289;-0.020978;0.949755;, + -0.282556;0.149017;0.947605;, + -0.841467;-0.090092;0.532745;, + -0.788033;-0.596961;0.150471;, + -0.281499;-0.319000;0.904985;, + -0.196716;-0.369433;0.908197;, + -0.161057;0.188926;0.968694;, + -0.117921;0.367554;0.922496;, + -0.165544;0.271340;0.948140;, + -0.448479;-0.324300;0.832884;, + -0.373171;-0.182007;0.909735;, + -0.585369;-0.257475;0.768797;, + -0.646693;-0.180851;0.741000;, + -0.433896;-0.034239;0.900312;, + -0.544015;0.013208;0.838971;, + -0.625281;0.038322;0.779458;, + -0.369810;0.339166;0.864990;, + -0.204468;0.130905;0.970081;, + -0.120885;-0.263543;0.957043;, + -0.337644;-0.437144;0.833607;, + -0.578208;-0.404603;0.708500;, + -0.370647;-0.182064;0.910754;, + -0.290198;-0.101172;0.951603;, + -0.376940;-0.512489;0.771538;, + -0.368633;-0.522608;0.768759;, + -0.486995;-0.560041;0.670216;, + -0.278178;-0.381573;0.881487;, + -0.075087;-0.187485;0.979393;, + -0.067375;0.165266;0.983945;, + -0.074430;0.262323;0.962105;, + 0.123594;0.167946;0.978018;, + 0.073851;0.127234;0.989120;, + -0.922972;-0.305031;0.234690;, + -0.940045;-0.272592;0.204959;, + -0.942479;-0.228737;0.243746;, + -0.916339;-0.265300;0.299899;, + -0.855199;-0.298439;0.423756;, + -0.762216;-0.394376;0.513317;, + -0.591911;-0.483389;0.644962;, + -0.696085;-0.423324;0.579881;, + -0.793967;-0.433457;0.426300;, + -0.881668;-0.367645;0.295802;, + -0.919076;-0.289884;0.266959;, + -0.896238;-0.324230;0.302709;, + -0.875589;-0.290272;0.386116;, + -0.837502;-0.227848;0.496665;, + -0.720126;0.080544;0.689153;, + -0.681826;0.051070;0.729729;, + -0.541528;0.261668;0.798923;, + -0.412827;0.304371;0.858448;, + -0.544132;0.538485;0.643393;, + -0.766691;0.438289;0.469135;, + -0.727958;0.390427;0.563599;, + -0.713113;0.317666;0.624947;, + -0.568038;-0.171249;0.804989;, + -0.614593;-0.512301;0.599852;, + -0.324992;-0.273417;0.905330;, + -0.325078;-0.097406;0.940657;, + -0.427217;0.076319;0.900922;, + -0.776082;0.381416;0.502213;, + -0.672565;0.634444;0.380968;, + -0.608698;0.697609;0.377927;, + -0.527897;0.632893;0.566367;, + -0.603113;0.411655;0.683224;, + -0.313344;0.022068;0.949383;, + -0.231524;-0.066876;0.970528;, + -0.168915;0.015046;0.985516;, + -0.221507;-0.014091;0.975057;, + -0.641279;-0.037093;-0.766410;, + -0.703969;-0.213682;-0.677324;, + -0.536901;-0.391985;-0.747051;, + -0.249177;0.220454;0.943033;, + -0.581291;0.278155;0.764677;, + -0.999289;-0.036353;-0.009963;, + -0.980048;-0.042446;-0.194177;, + -0.915136;0.144087;0.376517;, + -0.891750;0.158913;0.423707;, + -0.938708;0.033166;0.343115;, + -0.828350;0.374825;0.416345;, + -0.780750;0.319185;0.537169;, + -0.755930;0.332141;0.564138;, + -0.617201;0.537677;0.574427;, + -0.677696;0.597263;0.428958;, + -0.719767;-0.501742;0.479782;, + -0.506828;-0.552613;0.661622;, + -0.280970;-0.686116;0.671044;, + -0.292440;-0.656510;0.695323;, + -0.545799;-0.705691;0.451778;, + -0.967562;-0.216680;0.129901;, + -0.902540;-0.358906;0.237926;, + -0.767894;-0.587008;-0.256438;, + -0.649296;-0.476465;-0.592786;, + -0.838696;-0.334311;-0.429913;, + -0.596950;0.129505;0.791757;, + -0.784941;0.297168;0.543653;, + -0.720007;0.579195;0.382260;, + -0.583842;0.689444;0.428713;, + -0.529134;0.371967;0.762664;, + -0.395432;0.106411;0.912310;, + -0.447528;0.159246;0.879977;, + -0.407621;0.029059;0.912689;, + -0.490926;-0.004529;0.871189;, + -0.502973;0.024472;0.863955;, + -0.333013;-0.145713;0.931595;, + -0.207654;-0.252851;0.944958;, + -0.240287;-0.513231;0.823927;, + -0.450979;-0.500707;0.738857;, + -0.471005;-0.228916;0.851911;, + -0.842645;0.074691;0.533264;, + -0.816604;0.149701;0.557447;, + -0.737941;-0.003814;0.674855;, + -0.624475;-0.079418;0.776996;, + -0.702800;-0.238155;0.670339;, + -0.742410;-0.287823;0.604968;, + -0.834300;-0.079963;0.545482;, + -0.604495;0.234318;0.761367;, + -0.597482;0.269303;0.755308;, + -0.733246;0.420582;0.534286;, + -0.770729;0.354878;0.529187;, + -0.633754;0.199721;0.747307;, + -0.297362;-0.358005;0.885104;, + -0.394508;-0.419178;0.817712;, + -0.387859;-0.471158;0.792196;, + -0.360382;-0.488667;0.794563;, + -0.242655;-0.150104;0.958430;, + -0.204607;0.076638;0.975839;, + -0.075224;0.067895;0.994853;, + -0.072401;-0.157753;0.984821;, + -0.133760;-0.197065;0.971223;, + -0.421526;-0.376333;0.825039;, + -0.113815;0.102436;0.988207;, + -0.159036;0.237863;0.958190;, + -0.363394;-0.347889;0.864244;, + -0.340875;-0.250973;0.905990;, + -0.219814;-0.109322;0.969397;, + -0.110721;-0.227332;0.967502;, + -0.265841;0.064822;0.961835;, + -0.260969;0.257763;0.930297;, + -0.225523;0.367916;0.902096;, + -0.204636;0.250687;0.946192;, + -0.308536;-0.035566;0.950548;, + -0.280865;-0.155167;0.947121;, + -0.110123;-0.025715;0.993585;, + -0.225990;0.073774;0.971332;, + -0.317850;0.048584;0.946896;, + -0.286787;0.050884;0.956642;, + -0.135234;-0.128575;0.982436;, + -0.098581;0.034918;0.994516;, + -0.124352;-0.098909;0.987296;, + -0.027583;0.019128;0.999436;, + -0.990331;0.017071;0.137667;, + -0.973450;-0.198124;0.114640;, + -0.717508;-0.023630;0.696149;, + -0.990362;-0.013131;0.137880;, + -0.815899;-0.068843;0.574082;, + -0.919591;0.065600;0.387362;, + -0.964646;0.236442;-0.116421;, + -0.989021;0.026042;-0.145459;, + -0.960207;-0.224177;-0.166577;, + 0.341914;0.604075;-0.719853;, + 0.241749;0.480642;-0.842935;, + 0.136048;0.087503;-0.986830;, + -0.982644;0.096174;0.158626;, + -0.984714;0.084891;0.152090;, + -0.991473;0.037463;0.124814;, + -0.996531;0.005498;0.083044;, + -0.995489;-0.011539;0.094178;, + 0.157896;-0.099878;-0.982391;, + 0.117619;-0.172655;-0.977935;, + -0.023180;-0.471546;-0.881537;, + -0.642136;-0.415229;-0.644396;, + -0.985193;-0.114772;0.127367;, + -0.993842;-0.033310;0.105682;, + -0.840599;0.446641;0.306441;, + -0.751975;0.132709;0.645695;, + -0.940162;-0.115533;0.320542;, + -0.950011;-0.074948;-0.303088;, + -0.993523;-0.078642;0.082022;, + -0.991151;0.039768;-0.126645;, + -0.994943;0.013556;-0.099526;, + -0.485395;-0.513452;-0.707643;, + -0.229693;-0.529630;-0.816537;, + -0.295188;-0.242851;-0.924060;, + -0.210467;-0.041045;-0.976739;, + 0.040312;0.039373;-0.998411;, + -0.151436;0.353247;-0.923192;, + -0.835409;0.275429;-0.475637;, + -0.991667;-0.120179;-0.046409;, + -0.908512;0.062801;-0.413114;, + 0.083516;-0.876226;0.474609;, + -0.924920;-0.380144;0.003835;, + -0.947722;-0.049450;0.315243;, + -0.412440;-0.292679;0.862689;, + 0.402210;0.838808;-0.366918;, + 0.353181;0.729221;-0.586089;, + -0.198901;0.958333;-0.205027;, + -0.944823;0.308675;-0.109675;, + -0.884493;-0.444527;0.141662;, + -0.862185;0.430269;-0.267406;, + 0.013499;0.694024;-0.719825;, + 0.243556;0.731189;-0.637214;, + 0.197513;0.873282;-0.445384;, + -0.894910;-0.105076;-0.433700;, + -0.436112;-0.188372;-0.879956;, + -0.364055;-0.473683;-0.801928;, + -0.948565;-0.199078;-0.246157;, + -0.983673;-0.040697;-0.175301;, + -0.146382;-0.629542;-0.763052;, + 0.096478;-0.559529;-0.823176;, + 0.011927;-0.262782;-0.964781;, + -0.155590;-0.145800;-0.977003;, + -0.465377;-0.324842;-0.823348;, + -0.755154;-0.384266;-0.531113;, + -0.133038;-0.902773;-0.409025;, + 0.312386;-0.697431;-0.644985;, + 0.031574;-0.305537;-0.951657;, + -0.104452;-0.154902;-0.982393;, + -0.562599;-0.284042;-0.776403;, + -0.604821;-0.388772;-0.695017;, + -0.655051;-0.290024;-0.697707;, + -0.745770;-0.205337;-0.633769;, + -0.250413;-0.254174;-0.934178;, + 0.041562;-0.583144;-0.811305;, + -0.805809;-0.543792;0.234439;, + -0.782100;-0.570279;0.251199;, + -0.467073;-0.873594;-0.136662;, + -0.337534;-0.853552;-0.396886;, + -0.531094;-0.706015;-0.468489;, + -0.807521;-0.589785;0.008036;, + -0.602368;-0.756955;0.253322;, + -0.615086;-0.386827;0.687047;, + -0.238496;-0.799571;0.551186;, + -0.108202;-0.994107;-0.006522;, + -0.125377;-0.986922;-0.101321;, + -0.994704;0.028536;-0.098745;, + -0.987761;0.119054;-0.100772;, + -0.795270;0.185639;-0.577134;, + -0.767636;-0.389543;-0.508912;, + -0.833821;-0.284781;0.472909;, + -0.441591;0.115885;0.889701;, + -0.780037;0.083871;0.620087;, + -0.979289;0.016954;0.201754;, + -0.923625;-0.293416;-0.246623;, + -0.398686;-0.661959;-0.634713;, + -0.527934;-0.707186;-0.470290;, + -0.993981;0.072042;0.082538;, + -0.966193;0.076246;0.246286;, + -0.900595;0.023678;0.434013;, + -0.459569;0.109067;-0.881420;, + -0.609266;0.169694;-0.774596;, + -0.918178;0.118657;-0.377982;, + -0.473589;0.230470;-0.850057;, + -0.211760;0.199717;-0.956698;, + 0.270304;0.211165;-0.939332;, + -0.757123;0.021836;0.652907;, + -0.275522;0.128453;0.952674;, + -0.989453;0.037270;0.139976;, + -0.985345;0.075214;0.153095;, + -0.551796;-0.574616;-0.604431;, + -0.618692;-0.292564;-0.729127;, + -0.619769;0.060159;0.782475;, + -0.464479;-0.316670;0.827030;, + -0.372076;-0.368062;0.852109;, + -0.335690;-0.341328;0.877957;, + -0.285852;0.046274;0.957156;, + -0.355919;0.171383;0.918667;, + -0.723480;0.060884;0.687656;, + -0.814232;0.061779;0.577242;, + -0.886198;-0.021061;0.462827;, + -0.574120;-0.035273;0.818011;, + -0.243173;0.255052;0.935850;, + -0.418313;0.238912;0.876319;, + -0.255998;0.077691;0.963550;, + -0.261345;0.340963;0.903019;, + -0.153140;0.531302;0.833226;, + -0.004476;-0.270980;0.962575;, + -0.119564;-0.240178;0.963337;, + -0.327186;-0.256872;0.909377;, + -0.359013;-0.037721;0.932570;, + -0.047590;0.027451;0.998490;, + 0.022833;0.095235;0.995193;, + -0.377306;-0.316942;0.870166;, + -0.316548;-0.333267;0.888105;, + -0.477778;0.346040;0.807456;, + -0.323246;0.228712;0.918261;, + -0.376991;-0.033966;0.925594;, + -0.487857;-0.060488;0.870825;, + -0.761142;0.077824;0.643899;, + -0.720495;0.311094;0.619764;, + -0.524578;-0.521170;0.673201;, + -0.394926;-0.548853;0.736746;, + -0.356540;-0.270657;0.894217;, + -0.495468;-0.323313;0.806213;, + -0.463451;0.231939;0.855229;, + -0.256676;-0.425986;0.867556;, + -0.257064;-0.717534;0.647351;, + -0.264882;-0.777358;0.570571;, + -0.736052;0.062723;0.674013;, + -0.102010;0.499266;0.860423;, + 0.150316;0.449108;0.880743;, + 0.111995;0.138436;0.984019;, + -0.367057;-0.255284;0.894483;, + -0.278556;-0.296929;0.913367;, + -0.225628;0.375599;0.898898;, + -0.508485;-0.316227;0.800902;, + -0.840384;-0.146036;0.521946;, + -0.606247;0.434214;0.666275;, + -0.283006;0.307167;0.908601;, + -0.385943;-0.260360;0.885020;, + -0.221460;-0.237371;0.945839;, + -0.291186;-0.238537;0.926451;, + -0.160623;0.266772;0.950280;, + -0.283084;0.054206;0.957562;, + -0.282781;0.044475;0.958153;, + -0.135725;-0.254987;0.957371;, + -0.205252;0.312404;0.927510;, + -0.246128;0.432303;0.867488;, + -0.112957;-0.187289;0.975789;, + -0.531997;-0.340199;0.775399;, + -0.207669;-0.717728;0.664635;, + -0.470701;0.239290;0.849224;, + -0.660192;0.366644;0.655530;, + -0.098482;0.067836;0.992824;, + -0.227864;0.179884;0.956933;, + -0.333711;0.277181;0.901004;, + -0.304277;-0.311038;0.900372;, + -0.223441;-0.620814;0.751442;, + -0.478361;-0.492783;0.726868;, + -0.524366;-0.091050;0.846611;, + -0.371514;-0.104033;0.922580;, + -0.291101;0.296117;0.909711;, + -0.216517;0.601928;0.768637;, + -0.765717;0.109372;0.633811;, + -0.176319;-0.181296;0.967493;, + -0.237549;0.171176;0.956174;, + -0.290228;0.134824;0.947413;, + -0.292418;0.016174;0.956154;, + -0.352538;-0.172693;0.919725;, + -0.290964;-0.200100;0.935575;, + -0.909284;-0.286981;0.301404;, + -0.860343;-0.416762;0.293459;, + -0.527449;-0.725822;0.441566;, + -0.192717;-0.752991;0.629178;, + -0.413665;-0.662196;0.624803;, + -0.782661;-0.436604;0.443643;, + -0.739736;-0.304424;0.600097;, + -0.419309;-0.612197;0.670369;, + -0.178542;-0.532663;0.827280;, + -0.307625;-0.164296;0.937216;, + -0.692050;0.067912;0.718648;, + -0.773362;-0.044449;0.632405;, + -0.701142;0.222645;0.677370;, + -0.343154;0.141029;0.928631;, + -0.086339;0.227970;0.969832;, + -0.233405;0.474742;0.848612;, + -0.772564;0.372095;0.514481;, + -0.862219;0.333573;0.381192;, + -0.487320;0.574617;0.657522;, + -0.404061;0.641958;0.651632;, + -0.313427;0.711856;0.628510;, + -0.874726;0.363852;0.320104;, + -0.908715;0.258689;0.327593;, + -0.872452;0.309571;0.378146;, + -0.994626;0.037375;0.096552;, + -0.971560;0.138241;0.192251;, + -0.984564;0.133388;0.113322;, + -0.990615;0.053638;0.125719;, + -0.992423;-0.070546;-0.100601;, + -0.981912;-0.082005;-0.170656;, + 0.108071;-0.116143;0.987336;, + -0.797789;0.037538;0.601767;, + -0.920796;0.066458;0.384342;, + -0.928255;0.072027;0.364903;, + -0.930240;0.046030;0.364053;, + -0.415124;-0.114103;0.902581;, + -0.106608;-0.130975;0.985637;, + -0.933404;-0.160810;-0.320776;, + -0.736619;0.210971;-0.642560;, + -0.542357;0.242229;-0.804471;, + -0.523618;-0.179358;-0.832859;, + -0.870587;-0.276500;-0.406972;, + -0.922853;-0.232871;-0.306778;, + -0.901311;-0.421112;-0.101504;, + -0.851667;-0.383724;-0.356959;, + -0.545095;-0.326982;-0.771981;, + -0.333063;-0.417249;-0.845560;, + -0.554572;-0.744477;-0.371758;, + -0.863997;-0.496842;0.081586;, + -0.969478;-0.059688;-0.237801;, + -0.923894;-0.017241;-0.382259;, + -0.945693;-0.072099;-0.316964;, + -0.728538;0.351876;-0.587721;, + -0.723866;0.286506;-0.627640;, + -0.930880;-0.167827;-0.324496;, + -0.959100;-0.011290;-0.282843;, + -0.938731;0.123199;-0.321879;, + -0.709700;-0.318460;-0.628417;, + -0.330597;-0.726300;-0.602656;, + -0.452113;-0.839250;-0.302082;, + -0.857815;-0.222583;-0.463260;, + -0.902102;0.133251;-0.410435;, + -0.961728;0.190595;-0.196857;, + -0.978222;0.168444;-0.121282;, + -0.662740;0.264455;-0.700599;, + -0.476309;0.136397;-0.868634;, + -0.504309;-0.221320;-0.834679;, + -0.901494;0.354920;0.247672;, + -0.525457;0.668071;0.526854;, + -0.431549;0.860523;0.270676;, + -0.461883;0.559990;-0.687804;, + -0.494105;0.296706;-0.817206;, + -0.898829;0.268320;-0.346570;, + -0.941727;0.336079;-0.014200;, + -0.963121;0.021678;0.268195;, + -0.973111;-0.228118;-0.031884;, + -0.919379;-0.216115;-0.328690;, + -0.744589;-0.666942;-0.027853;, + -0.190314;-0.795142;0.575786;, + -0.060500;-0.787818;0.612930;, + -0.441276;-0.350415;0.826126;, + -0.840007;0.268555;0.471451;, + -0.964913;0.106253;0.240112;, + -0.995174;0.032352;0.092644;, + -0.934966;0.248566;-0.253088;, + -0.961037;0.049848;-0.271888;, + -0.998822;0.028759;0.039091;, + -0.990336;-0.002167;0.138672;, + -0.519203;-0.619776;0.588478;, + -0.391770;-0.654128;0.647018;, + -0.304486;-0.716860;0.627216;, + -0.910280;-0.362455;0.200043;, + -0.920418;-0.334077;0.203034;, + -0.988204;-0.086301;0.126514;, + -0.971693;-0.063695;0.227500;, + -0.923098;-0.057285;0.380275;, + -0.488334;0.063730;0.870327;, + -0.231105;-0.031755;0.972411;, + -0.512220;-0.385547;0.767453;, + -0.933438;-0.231048;0.274427;, + -0.473499;0.583805;0.659523;, + -0.308586;0.551748;0.774822;, + -0.255754;0.295329;0.920527;, + -0.877571;0.152218;0.454641;, + -0.979923;0.112462;0.164628;, + -0.889948;0.248106;0.382669;, + -0.883469;0.360672;0.298994;, + -0.946941;0.292536;0.133139;, + -0.962565;0.225045;0.151073;, + -0.879996;0.362170;0.307310;, + -0.453901;0.679771;0.576094;, + -0.231858;0.768436;0.596446;, + -0.521367;0.619633;0.586713;, + -0.987626;-0.156503;0.010098;, + -0.950732;-0.158522;-0.266418;, + -0.559545;-0.268517;-0.784097;, + -0.547278;-0.203637;-0.811799;, + -0.555973;0.130853;-0.820836;, + -0.983075;-0.050169;-0.176203;, + -0.589184;-0.777856;0.218638;, + -0.173867;-0.956818;0.232956;, + -0.412436;-0.546600;-0.728783;, + -0.867346;-0.396857;-0.300360;, + -0.999127;0.006755;-0.041222;, + -0.737443;0.369253;-0.565534;, + -0.294691;0.557341;-0.776227;, + -0.702347;0.471707;-0.533105;, + -0.999253;0.038278;0.005340;, + -0.208681;-0.785150;-0.583088;, + -0.214903;-0.821849;-0.527618;, + -0.174480;-0.970501;-0.166386;, + -0.133487;-0.990413;0.035549;, + -0.146752;-0.878664;-0.454328;, + -0.159714;-0.112935;-0.980682;, + -0.114641;0.109429;-0.987361;, + -0.097975;0.047333;-0.994063;, + -0.155868;-0.350626;-0.923454;, + -0.161498;-0.608488;-0.776956;, + -0.174065;-0.534580;-0.826998;, + -0.963396;0.255594;-0.080872;, + -0.495971;0.499732;-0.710127;, + -0.391198;0.918452;-0.058392;, + -0.910511;0.383051;0.155695;, + -0.801319;0.421929;0.424102;, + -0.173816;0.424341;0.888663;, + 0.132056;0.386729;0.912689;, + -0.059642;0.521187;0.851356;, + -0.717995;0.461191;0.521331;, + -0.963654;0.185646;0.192113;, + -0.826151;0.456218;0.330667;, + -0.202592;0.794997;0.571784;, + 0.122156;0.828715;0.546178;, + -0.156667;0.773674;0.613909;, + -0.783959;0.522880;0.334672;, + -0.247328;0.278644;-0.928001;, + -0.514676;0.484402;-0.707434;, + -0.221209;0.975219;-0.003702;, + 0.152157;0.982339;-0.108898;, + -0.086863;0.565088;-0.820445;, + -0.120370;0.286062;-0.950621;, + -0.217075;0.288626;-0.932509;, + -0.046481;0.258131;0.964991;, + 0.086883;0.146423;0.985399;, + -0.126526;-0.572079;0.810381;, + -0.678205;-0.266807;0.684728;, + -0.390094;-0.893060;0.224213;, + -0.215648;-0.938949;0.268088;, + -0.426159;-0.836851;-0.343610;, + -0.891225;-0.365388;-0.268717;, + -0.922702;-0.380591;0.061411;, + -0.479805;-0.561201;-0.674419;, + -0.263961;-0.572476;-0.776271;, + -0.401044;-0.160466;-0.901895;, + -0.812645;0.076717;-0.577688;, + -0.985268;-0.013185;-0.170509;, + -0.929545;-0.091642;-0.357137;, + -0.706692;0.408356;0.577781;, + -0.971905;0.201947;0.120901;, + -0.780984;0.429796;0.453144;, + -0.101385;0.740749;0.664088;, + 0.112055;0.771742;0.625986;, + -0.063776;0.461704;0.884738;, + -0.644377;0.580936;0.497285;, + -0.726201;0.594292;0.345614;, + -0.064509;0.887130;0.456988;, + 0.151722;0.889454;0.431106;, + 0.004774;0.752502;0.658573;, + -0.180513;0.319591;-0.930202;, + -0.071812;0.376860;-0.923482;, + -0.055318;0.875614;-0.479834;, + -0.604713;0.765248;-0.220720;, + -0.947576;-0.246188;0.203695;, + -0.945100;-0.267159;0.188180;, + -0.929894;-0.301728;0.210374;, + -0.938122;-0.247356;0.242367;, + -0.948037;-0.205364;0.243004;, + -0.982289;0.005861;0.187281;, + -0.970327;0.034796;0.239279;, + -0.821069;-0.164374;0.546650;, + -0.788342;-0.076790;0.610426;, + -0.948825;-0.033448;0.314026;, + -0.984684;-0.100876;0.142201;, + -0.990691;-0.060390;0.122001;, + -0.991477;-0.014669;0.129452;, + -0.977761;-0.074429;0.196069;, + -0.968921;-0.148629;0.197740;, + -0.963259;-0.202188;0.176785;, + -0.965124;-0.190436;0.179640;, + -0.996668;-0.000055;0.081571;, + -0.992952;-0.010172;0.118079;, + -0.653195;-0.150269;0.742129;, + -0.393828;-0.197542;0.897707;, + -0.986199;-0.027926;0.163190;, + -0.698788;-0.183747;0.691326;, + -0.477199;-0.092968;0.873864;, + -0.408888;-0.121595;0.904447;, + -0.383912;-0.053672;0.921808;, + -0.668225;-0.119696;0.734267;, + -0.707558;-0.149489;0.690662;, + -0.333263;0.082750;0.939196;, + -0.380632;0.065214;0.922424;, + -0.424222;0.027945;0.905127;, + -0.344899;-0.178549;0.921501;, + -0.228579;-0.246387;0.941831;, + -0.295296;-0.069069;0.952906;, + -0.351717;0.069372;0.933532;, + -0.150503;0.003474;0.988603;, + 0.100381;-0.018321;0.994780;, + 0.184877;0.074293;0.979949;, + 0.196102;0.167844;0.966112;, + -0.150811;0.174292;0.973077;, + -0.204636;0.123817;0.970976;, + -0.230074;0.372461;0.899077;, + -0.506615;0.220020;0.833626;, + -0.303228;0.319910;0.897613;, + 0.259931;0.297731;0.918581;, + 0.467914;0.186614;0.863847;, + 0.291782;0.351503;0.889555;, + 0.135206;-0.197296;0.970976;, + -0.056462;-0.303649;0.951110;, + -0.259365;-0.317494;0.912101;, + -0.300044;-0.323635;0.897348;, + -0.158828;0.184032;0.970003;, + -0.232666;0.262793;0.936379;, + -0.328859;0.141047;0.933787;, + -0.388761;0.111134;0.914611;, + -0.320469;0.119524;0.939688;, + -0.241856;-0.015663;0.970186;, + -0.206723;0.090179;0.974235;, + -0.214559;0.312331;0.925426;, + -0.214040;0.335101;0.917548;, + -0.175599;0.167179;0.970163;, + -0.207314;0.342570;0.916333;, + -0.204677;0.145172;0.968004;, + -0.267360;0.048646;0.962368;, + -0.242820;0.143189;0.959445;, + -0.216371;0.266677;0.939184;, + -0.191125;0.333044;0.923338;, + -0.546439;0.124024;0.828265;, + -0.421343;0.043606;0.905852;, + -0.710324;-0.088882;0.698241;, + -0.759262;-0.042020;0.649427;, + 0.457664;-0.046073;0.887931;, + 0.415472;-0.131980;0.899980;, + 0.601990;-0.320637;0.731300;, + 0.732447;-0.463382;0.498797;, + 0.796203;-0.311752;0.518528;, + 0.618889;-0.216199;0.755138;, + 0.650858;-0.279521;-0.705870;, + 0.627769;-0.641265;-0.441233;, + 0.881339;-0.465948;0.078326;, + 0.928462;-0.263842;0.261431;, + 0.964094;-0.165413;0.207751;, + 0.924341;-0.229764;-0.304633;, + 0.927430;-0.166498;0.334890;, + 0.883252;-0.199217;0.424473;, + 0.843025;-0.193507;0.501860;, + 0.834563;-0.142862;0.532067;, + 0.847343;-0.090185;0.523332;, + 0.859241;0.003695;0.511557;, + 0.786163;-0.008241;0.617964;, + 0.922761;-0.080766;0.376814;, + 0.964606;-0.206993;0.163368;, + 0.954750;-0.229736;0.188876;, + 0.977642;-0.134009;0.162042;, + 0.556167;-0.235673;0.796955;, + -0.566294;-0.282990;0.774098;, + -0.779621;-0.549588;0.300240;, + -0.453973;-0.875337;-0.166413;, + 0.885166;-0.437540;-0.158241;, + 0.965433;-0.004688;0.260610;, + 0.745205;-0.297817;0.596636;, + 0.383889;-0.464132;0.798255;, + 0.323830;-0.489051;0.809916;, + 0.924672;0.127786;0.358681;, + 0.983531;0.088214;0.157748;, + -0.363776;0.894300;-0.260567;, + 0.270665;0.955941;0.113652;, + 0.641266;0.188129;0.743899;, + 0.616460;-0.165561;0.769783;, + 0.677762;-0.074270;0.731521;, + 0.829313;0.074463;0.553800;, + 0.887257;0.039798;0.459556;, + 0.781695;0.234974;0.577703;, + 0.819624;0.148430;0.553340;, + 0.781224;0.181945;0.597148;, + 0.679518;-0.160347;0.715922;, + 0.771375;-0.034845;0.635426;, + 0.535532;-0.307662;0.786480;, + 0.285775;0.030248;0.957819;, + 0.817277;0.454475;0.354275;, + 0.810140;0.435116;-0.392871;, + 0.839666;0.520528;0.154955;, + 0.709256;0.641012;0.293361;, + 0.614890;0.217033;0.758160;, + 0.420168;0.159950;0.893238;, + 0.483411;0.190762;0.854356;, + 0.360033;0.104427;0.927077;, + 0.286110;0.137586;0.948268;, + 0.070070;0.358867;0.930755;, + 0.165214;0.238175;0.957067;, + 0.196627;-0.192079;0.961480;, + 0.247128;-0.341305;0.906884;, + 0.643177;-0.541832;0.541056;, + 0.809334;-0.483823;-0.333007;, + 0.218364;0.254619;0.942065;, + 0.396152;0.003364;0.918179;, + 0.609373;-0.153995;0.777786;, + 0.663145;-0.277587;0.695115;, + 0.382906;-0.177032;0.906666;, + 0.413901;-0.346606;0.841754;, + 0.585242;-0.040809;0.809831;, + 0.626492;0.149889;0.764880;, + 0.412419;-0.359405;0.837102;, + 0.144547;-0.399892;0.905093;, + 0.214707;0.074209;0.973855;, + 0.235312;0.330449;0.914019;, + 0.402156;-0.544015;0.736423;, + 0.349444;-0.577169;0.738081;, + 0.335755;-0.089838;0.937655;, + 0.309502;-0.188143;0.932100;, + 0.531786;-0.357341;0.767796;, + 0.532413;-0.519111;0.668625;, + 0.198806;-0.407566;0.891272;, + 0.050237;0.021161;0.998513;, + -0.154151;0.164731;0.974218;, + 0.014259;0.242570;0.970029;, + 0.101190;0.244238;0.964421;, + 0.075895;-0.122424;0.989572;, + 0.926394;-0.303016;0.223553;, + 0.916339;-0.265300;0.299899;, + 0.941193;-0.231274;0.246311;, + 0.942736;-0.258883;0.210308;, + 0.872017;-0.277751;0.403040;, + 0.891387;-0.329329;0.311403;, + 0.920623;-0.287190;0.264530;, + 0.888242;-0.359291;0.286246;, + 0.823502;-0.420165;0.381189;, + 0.712448;-0.424274;0.558935;, + 0.572964;-0.461769;0.677112;, + 0.734110;-0.436861;0.519842;, + 0.859424;-0.304858;0.410430;, + 0.820103;-0.223413;0.526800;, + 0.694020;0.045381;0.718524;, + 0.732903;0.294085;0.613487;, + 0.704924;0.372480;0.603606;, + 0.767741;0.423284;0.481046;, + 0.610611;0.550799;0.569012;, + 0.428564;0.378854;0.820246;, + 0.528841;0.287979;0.798370;, + 0.657818;0.087537;0.748073;, + 0.585630;-0.275362;0.762373;, + 0.487759;0.040891;0.872020;, + 0.366793;-0.058552;0.928458;, + 0.300364;-0.225631;0.926754;, + 0.529462;-0.449192;0.719651;, + 0.530125;0.561389;0.635461;, + 0.592261;0.685382;0.423648;, + 0.622463;0.688709;0.371779;, + 0.792469;0.431830;0.430715;, + 0.631199;0.391605;0.669503;, + 0.299096;0.239203;0.923755;, + 0.820659;-0.346212;-0.454594;, + 0.626383;-0.271076;-0.730864;, + 0.638572;-0.117365;-0.760560;, + 0.788158;0.351005;0.505571;, + 0.200084;-0.052108;0.978392;, + 0.246747;-0.051308;0.967721;, + 0.295036;-0.000370;0.955486;, + 0.509111;0.214011;0.833670;, + 0.902799;0.118400;0.413443;, + 0.910089;0.167693;0.378969;, + 0.999735;0.022967;0.001488;, + 0.996072;-0.042387;-0.077740;, + 0.968689;-0.002135;0.248269;, + 0.832590;0.320635;0.451650;, + 0.730488;0.555207;0.397659;, + 0.597202;0.573938;0.560308;, + 0.720968;0.387938;0.574203;, + 0.775558;0.322202;0.542858;, + 0.694246;-0.474535;0.541146;, + 0.644048;-0.677994;0.354297;, + 0.306835;-0.637411;0.706795;, + 0.266653;-0.673114;0.689793;, + 0.448030;-0.595143;0.667138;, + 0.953942;-0.228941;0.193855;, + 0.938814;-0.254695;-0.231861;, + 0.681733;-0.472937;-0.558184;, + 0.645724;-0.571945;-0.505885;, + 0.884756;-0.428469;0.183360;, + 0.649040;0.135351;0.748617;, + 0.529791;0.315074;0.787432;, + 0.553748;0.630029;0.544451;, + 0.678128;0.634870;0.370248;, + 0.796340;0.360973;0.485325;, + 0.510516;-0.005648;0.859850;, + 0.416079;0.034303;0.908681;, + 0.410099;0.086002;0.907977;, + 0.420062;0.136052;0.897239;, + 0.478583;0.042049;0.877035;, + 0.504686;-0.416381;0.756253;, + 0.267406;-0.542263;0.796520;, + 0.189664;-0.341747;0.920454;, + 0.305752;-0.160267;0.938525;, + 0.443105;-0.186385;0.876880;, + 0.785203;-0.238678;0.571392;, + 0.702825;-0.257963;0.662942;, + 0.632744;-0.132306;0.762974;, + 0.707627;-0.023756;0.706187;, + 0.823076;0.132453;0.552270;, + 0.827196;0.109153;0.551210;, + 0.840927;-0.044262;0.539336;, + 0.764042;0.302636;0.569781;, + 0.742909;0.415406;0.524903;, + 0.699619;0.385348;0.601698;, + 0.578906;0.224993;0.783739;, + 0.590168;0.194655;0.783461;, + 0.302061;-0.359334;0.882971;, + 0.349642;-0.508600;0.786814;, + 0.384855;-0.464307;0.797688;, + 0.416260;-0.438975;0.796259;, + 0.099726;-0.233237;0.967293;, + 0.048634;0.031907;0.998307;, + 0.180176;0.105444;0.977966;, + 0.252687;-0.100086;0.962358;, + 0.155669;-0.183842;0.970551;, + 0.411002;-0.338944;0.846282;, + 0.383695;-0.396116;0.834188;, + 0.249542;0.061763;0.966392;, + -0.016457;0.327055;0.944862;, + 0.224850;0.215443;0.950277;, + 0.196803;0.368723;0.908467;, + 0.250180;0.310646;0.917011;, + 0.277343;0.101996;0.955342;, + 0.152847;-0.155989;0.975861;, + 0.195391;-0.110401;0.974492;, + 0.305812;-0.230212;0.923841;, + 0.368641;-0.213324;0.904763;, + 0.330326;-0.205628;0.921196;, + 0.041593;0.020366;0.998927;, + 0.105429;-0.086429;0.990664;, + 0.129328;0.092742;0.987255;, + 0.068386;-0.183487;0.980641;, + 0.278092;0.030516;0.960070;, + 0.303773;0.055120;0.951149;, + 0.271522;0.061913;0.960439;, + 0.081953;0.023311;0.996364;, + 0.990331;0.017071;0.137667;, + 0.953548;-0.160770;0.254755;, + 0.955059;-0.249767;-0.159623;, + 0.989051;-0.010385;-0.147209;, + 0.968564;0.208434;-0.135792;, + 0.962753;0.114072;0.245141;, + 0.744378;-0.064698;0.664617;, + 0.986376;-0.020071;0.163278;, + 0.669899;-0.004795;0.742437;, + -0.235778;0.425628;-0.873642;, + -0.220215;0.603569;-0.766296;, + 0.417851;0.563338;-0.712777;, + -0.117525;0.013779;-0.992974;, + 0.982667;0.097694;0.157550;, + 0.995367;-0.011631;0.095439;, + 0.996248;-0.000196;0.086542;, + 0.993018;0.025522;0.115170;, + 0.985216;0.087350;0.147373;, + 0.723129;-0.344431;-0.598709;, + 0.154335;-0.521647;-0.839086;, + -0.133014;-0.196421;-0.971456;, + -0.156278;-0.099901;-0.982648;, + 0.783722;0.054151;0.618747;, + 0.800117;0.416289;0.431874;, + 0.984353;0.134697;0.113601;, + 0.979461;-0.119954;0.162070;, + 0.979140;-0.146299;0.141004;, + 0.991670;-0.062397;0.112684;, + 0.457966;-0.192146;-0.867956;, + 0.237393;-0.461566;-0.854752;, + 0.286927;-0.568203;-0.771244;, + 0.948440;-0.169360;-0.267917;, + 0.986431;0.066300;-0.150194;, + 0.998816;-0.041285;0.025724;, + 0.997505;-0.067738;-0.019863;, + 0.977410;0.022278;-0.210173;, + 0.251890;0.415533;-0.874004;, + -0.049975;0.093433;-0.994371;, + 0.097770;-0.050793;-0.993912;, + 0.766098;0.059984;-0.639918;, + 0.884732;-0.053391;0.463033;, + 0.961439;-0.267549;0.063666;, + 0.356172;-0.920978;0.157925;, + 0.137541;-0.415914;0.898943;, + 0.601662;0.572761;-0.556730;, + -0.202958;0.734881;-0.647115;, + -0.398591;0.825562;-0.399465;, + 0.467679;0.871282;-0.148809;, + -0.170588;0.897489;-0.406710;, + -0.258260;0.761324;-0.594717;, + -0.103593;0.680661;-0.725237;, + 0.665282;0.581928;-0.467718;, + 0.906891;-0.362904;0.214125;, + 0.986874;0.076429;-0.142259;, + 0.748399;-0.135655;-0.649228;, + 0.972144;-0.068447;-0.224170;, + 0.994963;-0.047062;-0.088507;, + 0.528323;-0.487037;-0.695464;, + 0.335614;-0.233313;-0.912649;, + 0.007851;-0.660221;-0.751031;, + 0.455960;-0.390419;-0.799796;, + 0.279711;-0.160851;-0.946514;, + -0.004749;-0.220237;-0.975435;, + -0.084670;-0.487141;-0.869209;, + 0.247045;-0.169890;-0.953995;, + 0.006335;-0.246126;-0.969217;, + -0.214712;-0.642232;-0.735824;, + -0.275438;-0.893885;-0.353699;, + 0.710787;-0.466778;-0.526214;, + 0.633158;-0.292738;-0.716530;, + 0.618095;-0.351774;-0.703004;, + 0.147006;-0.604143;-0.783199;, + 0.088495;-0.303567;-0.948692;, + 0.682342;-0.196035;-0.704258;, + 0.643874;-0.292915;-0.706843;, + 0.663539;-0.666241;-0.340352;, + 0.373002;-0.795669;-0.477263;, + 0.420448;-0.891526;-0.168539;, + 0.723608;-0.669946;0.166023;, + 0.799573;-0.544703;0.252945;, + 0.813432;-0.577021;0.073316;, + 0.073674;-0.995832;-0.053775;, + 0.193201;-0.890421;0.412097;, + 0.557281;-0.410177;0.721937;, + 0.626008;-0.721638;0.295555;, + 0.253351;-0.965876;-0.053822;, + 0.996795;0.059173;-0.053828;, + 0.870487;-0.276909;-0.406907;, + 0.718742;0.207815;-0.663493;, + 0.972577;0.124346;-0.196549;, + 0.360242;-0.674562;-0.644354;, + 0.831536;-0.420486;-0.362960;, + 0.992970;0.009011;0.118019;, + 0.832630;0.062414;0.550302;, + 0.429350;0.141609;0.891967;, + 0.772381;-0.152248;0.616642;, + 0.619530;-0.709222;-0.336434;, + 0.868190;-0.002769;0.496225;, + 0.955968;0.074254;0.283920;, + 0.993664;0.087718;0.070268;, + 0.944767;0.116170;-0.306464;, + 0.737612;0.161042;-0.655740;, + 0.449994;0.091497;-0.888332;, + 0.445506;0.217708;-0.868405;, + -0.291086;0.220952;-0.930833;, + 0.064085;0.200510;-0.977593;, + 0.166541;0.103506;0.980587;, + 0.694153;0.049571;0.718118;, + 0.988650;0.046011;0.143017;, + 0.984565;0.081079;0.155104;, + 0.893652;0.299498;-0.334196;, + 0.618693;-0.292564;-0.729127;, + 0.551796;-0.574616;-0.604431;, + 0.251449;0.254655;0.933769;, + 0.329189;-0.298075;0.895983;, + 0.374162;-0.369333;0.850644;, + 0.394027;-0.385974;0.834126;, + 0.629716;-0.045172;0.775511;, + 0.414482;0.150122;0.897590;, + 0.752482;0.042277;0.657254;, + 0.497044;0.192697;0.846059;, + 0.233967;0.315946;0.919477;, + 0.509045;0.023685;0.860414;, + 0.837737;-0.103276;0.536219;, + 0.825693;0.084952;0.557686;, + 0.037052;-0.285163;0.957763;, + 0.072545;0.261091;0.962584;, + 0.254955;0.442961;0.859525;, + 0.279810;0.168723;0.945113;, + 0.138900;-0.213260;0.967071;, + 0.368508;-0.334070;0.867525;, + 0.140609;-0.045717;0.989009;, + -0.019079;0.066742;0.997588;, + 0.299362;0.006168;0.954120;, + 0.352172;-0.219694;0.909785;, + 0.309812;-0.324424;0.893737;, + 0.805112;0.138732;0.576669;, + 0.538357;-0.045396;0.841493;, + 0.380736;-0.067302;0.922231;, + 0.328487;0.183332;0.926545;, + 0.432615;0.307403;0.847554;, + 0.653253;0.367666;0.661878;, + 0.492323;-0.585442;0.644108;, + 0.502064;-0.355000;0.788610;, + 0.401739;-0.251939;0.880416;, + 0.376888;-0.493204;0.784032;, + 0.408002;0.182946;0.894464;, + 0.686633;0.144018;0.712597;, + 0.519245;-0.551574;0.652803;, + 0.241814;-0.736624;0.631594;, + 0.189975;-0.684424;0.703898;, + 0.231331;-0.089643;0.968736;, + 0.437328;-0.396663;0.807095;, + -0.019958;0.064292;0.997732;, + -0.162579;0.374547;0.912843;, + 0.021642;0.552809;0.833027;, + 0.240174;0.350884;0.905095;, + 0.590551;-0.317529;0.741907;, + 0.378809;-0.263028;0.887310;, + 0.356270;0.140360;0.923781;, + 0.292827;0.581198;0.759250;, + 0.887962;-0.080435;0.452829;, + 0.232714;-0.268412;0.934772;, + 0.270973;-0.021494;0.962347;, + 0.249117;0.137702;0.958634;, + 0.240587;0.147886;0.959295;, + 0.297294;-0.186777;0.936339;, + 0.218225;0.244375;0.944806;, + 0.222570;0.434020;0.872977;, + 0.144213;-0.238035;0.960491;, + 0.105285;-0.243661;0.964129;, + 0.499498;0.317571;0.806009;, + 0.323872;-0.438181;0.838513;, + 0.358587;-0.591042;0.722554;, + 0.709020;0.269606;0.651616;, + 0.298672;-0.579421;0.758332;, + 0.236939;-0.570878;0.786103;, + 0.348584;0.203164;0.914994;, + 0.260867;0.212941;0.941597;, + 0.097898;0.105821;0.989554;, + 0.377267;-0.289994;0.879530;, + 0.479423;0.478311;0.735780;, + 0.249071;0.370670;0.894744;, + 0.302334;0.087757;0.949154;, + 0.470067;-0.109278;0.875840;, + 0.727706;0.050030;0.684063;, + 0.159681;-0.153441;0.975171;, + 0.267587;-0.200427;0.942457;, + 0.365349;-0.233476;0.901116;, + 0.305557;-0.031119;0.951665;, + 0.278707;0.095201;0.955646;, + 0.291626;0.332066;0.897043;, + 0.501613;-0.618956;0.604382;, + 0.178903;-0.749707;0.637129;, + 0.274708;-0.796173;0.539115;, + 0.841050;-0.462941;0.279859;, + 0.915403;-0.281528;0.287713;, + 0.874537;-0.332222;0.353288;, + 0.799068;0.056915;0.598541;, + 0.406283;-0.083515;0.909923;, + 0.131733;-0.475879;0.869589;, + 0.238303;-0.649785;0.721797;, + 0.701135;-0.368935;0.610161;, + 0.788343;-0.078957;0.610149;, + 0.396116;0.496106;0.772638;, + 0.080690;0.269931;0.959493;, + 0.097838;0.136147;0.985846;, + 0.673078;0.201405;0.711620;, + 0.814615;0.305380;0.493097;, + 0.791616;0.414216;0.449188;, + 0.871315;0.302480;0.386414;, + 0.904561;0.262540;0.335921;, + 0.910079;0.308658;0.276563;, + 0.525509;0.655009;0.542957;, + 0.397477;0.642652;0.654989;, + 0.369469;0.615521;0.696152;, + 0.980166;-0.106355;-0.167220;, + 0.993832;0.046691;0.100592;, + 0.981920;0.086298;0.168479;, + 0.981368;0.156012;0.112144;, + 0.974808;0.085085;0.206180;, + 0.988089;-0.076583;-0.133471;, + 0.233487;-0.090126;0.968174;, + 0.078736;-0.116167;0.990104;, + 0.160509;-0.156800;0.974500;, + 0.853642;0.016690;0.520593;, + 0.939670;0.050263;0.338368;, + 0.923190;0.094626;0.372514;, + 0.862014;0.056065;0.503774;, + 0.936010;-0.253687;-0.243985;, + 0.608655;-0.245946;-0.754353;, + 0.523086;0.163014;-0.836545;, + 0.568395;0.375488;-0.732077;, + 0.917980;-0.141801;-0.370411;, + 0.923300;-0.237465;-0.301874;, + 0.909875;-0.400036;-0.109997;, + 0.906412;-0.421235;0.031280;, + 0.675045;-0.722669;-0.148538;, + 0.309013;-0.470378;-0.826593;, + 0.372917;-0.313993;-0.873122;, + 0.818454;-0.384125;-0.427295;, + 0.810462;0.143367;-0.567977;, + 0.626725;0.447627;-0.637844;, + 0.910464;0.049229;-0.410649;, + 0.935713;-0.058966;-0.347798;, + 0.964018;-0.036088;-0.263376;, + 0.945373;-0.182223;-0.270306;, + 0.963343;0.024740;-0.267130;, + 0.880786;-0.181630;-0.437296;, + 0.650930;-0.680013;-0.337449;, + 0.335037;-0.782036;-0.525518;, + 0.563778;-0.458869;-0.686727;, + 0.913321;0.104053;-0.393723;, + 0.937081;0.163116;-0.308662;, + 0.668251;-0.161916;-0.726102;, + 0.486568;0.053293;-0.872016;, + 0.533594;0.277429;-0.798943;, + 0.928577;0.194671;-0.315987;, + 0.969092;0.183829;-0.164523;, + 0.866079;0.407632;0.289384;, + 0.941173;0.337920;-0.002044;, + 0.938375;0.259917;-0.227806;, + 0.624232;0.279202;-0.729644;, + 0.502694;0.464741;-0.728913;, + 0.436435;0.894881;0.093339;, + 0.353823;0.758467;0.547299;, + 0.933666;0.245227;0.261020;, + 0.535134;-0.219852;0.815657;, + 0.024104;-0.703755;0.710034;, + 0.178308;-0.751297;0.635421;, + 0.602066;-0.782297;0.159777;, + 0.901219;-0.248765;-0.354853;, + 0.961986;-0.258591;-0.087825;, + 0.968198;-0.019433;0.249429;, + 0.974126;0.109867;0.197503;, + 0.998120;0.046379;0.040070;, + 0.989245;0.018948;0.145036;, + 0.998196;0.033204;0.050015;, + 0.987221;0.030678;-0.156373;, + 0.915666;0.230725;-0.329122;, + 0.929875;-0.332924;0.156510;, + 0.548129;-0.661438;0.511912;, + 0.328608;-0.695385;0.639105;, + 0.393459;-0.640623;0.659388;, + 0.887822;-0.363940;0.281637;, + 0.667999;-0.377721;0.641174;, + 0.176666;-0.140491;0.974193;, + 0.341914;0.096830;0.934729;, + 0.887877;-0.038319;0.458482;, + 0.969393;-0.056384;0.238953;, + 0.987385;-0.098273;0.124147;, + 0.957678;-0.180684;0.224067;, + 0.978399;0.092216;0.185021;, + 0.903224;0.146776;0.403292;, + 0.492552;0.233622;0.838340;, + 0.283857;0.492640;0.822637;, + 0.297955;0.637549;0.710460;, + 0.848610;0.319927;0.421318;, + 0.905296;0.318015;0.281611;, + 0.636969;0.566446;0.522885;, + 0.186839;0.733572;0.653424;, + 0.320731;0.757519;0.568591;, + 0.837352;0.395678;0.377200;, + 0.959055;0.246703;0.139112;, + 0.955218;0.282513;0.088003;, + 0.990080;-0.140504;-0.000454;, + 0.987431;-0.083124;-0.134427;, + 0.770556;0.153218;-0.618683;, + 0.514955;-0.136927;-0.846211;, + 0.487689;-0.291792;-0.822810;, + 0.911993;-0.179968;-0.368620;, + 0.554420;-0.498946;-0.666086;, + 0.175684;-0.958552;-0.224307;, + 0.440194;-0.833213;0.334641;, + 0.883002;-0.445236;-0.148568;, + 0.833256;0.378313;-0.403191;, + 0.280903;0.598074;-0.750601;, + 0.607836;0.418934;-0.674559;, + 0.994040;0.019054;-0.107342;, + 0.998649;0.042991;0.029202;, + 0.067520;-0.991070;-0.114981;, + 0.206828;-0.976295;-0.063794;, + 0.201725;-0.842948;-0.498745;, + 0.199110;-0.789128;-0.581061;, + 0.182351;-0.838223;-0.513937;, + 0.179619;-0.612115;-0.770099;, + 0.161976;-0.446886;-0.879805;, + 0.103521;-0.032143;-0.994108;, + 0.083882;0.118846;-0.989363;, + 0.162750;-0.049292;-0.985435;, + 0.155187;-0.395059;-0.905453;, + 0.567095;0.799478;0.198086;, + 0.449374;0.616302;-0.646711;, + 0.849927;0.303096;-0.430996;, + 0.936005;0.320009;0.146594;, + 0.155449;0.563615;0.811279;, + -0.138213;0.387227;0.911566;, + -0.004277;0.391231;0.920283;, + 0.721355;0.437806;0.536631;, + 0.852050;0.350687;0.388626;, + 0.964763;0.203925;0.166276;, + 0.871839;0.392583;0.292873;, + 0.274136;0.799417;0.534586;, + -0.141042;0.765026;0.628365;, + 0.116728;0.857063;0.501815;, + 0.732098;0.530474;0.427353;, + 0.288643;0.263589;-0.920438;, + 0.254733;0.326813;-0.910112;, + 0.156678;0.269554;-0.950154;, + 0.107469;0.490481;-0.864800;, + -0.142335;0.937356;-0.317971;, + 0.076965;0.997000;-0.008263;, + 0.564368;0.602211;-0.564651;, + 0.240721;-0.608347;0.756285;, + -0.073068;-0.148548;0.986202;, + -0.009780;0.272046;0.962235;, + 0.570934;0.068021;0.818174;, + 0.970937;-0.213567;-0.108028;, + 0.499315;-0.779570;-0.378095;, + 0.230800;-0.972814;0.019097;, + 0.323398;-0.895943;0.304467;, + 0.834135;-0.545842;0.079219;, + 0.981707;0.015920;-0.189730;, + 0.949298;0.051192;-0.310183;, + 0.429925;-0.097791;-0.897553;, + 0.244202;-0.464371;-0.851308;, + 0.420516;-0.601479;-0.679256;, + 0.847608;-0.252333;-0.466786;, + 0.842275;0.348065;0.411611;, + 0.123801;0.481601;0.867602;, + -0.131402;0.605188;0.785163;, + 0.049951;0.809325;0.585234;, + 0.649010;0.538182;0.537723;, + 0.974070;0.179720;0.137432;, + 0.810052;0.462959;0.359841;, + 0.071975;0.766775;0.637868;, + -0.167942;0.811266;0.560038;, + -0.017901;0.898223;0.439175;, + 0.575245;0.693252;0.434161;, + 0.126094;0.962221;-0.241310;, + 0.028226;0.494821;-0.868536;, + 0.153941;0.305601;-0.939633;, + 0.584262;0.539674;-0.606128;, + 0.947656;-0.251190;0.197106;, + 0.949985;-0.211068;0.230172;, + 0.940140;-0.240408;0.241536;, + 0.930866;-0.286260;0.227033;, + 0.941418;-0.276414;0.193203;, + 0.845017;-0.054953;0.531908;, + 0.750383;-0.181846;0.635498;, + 0.962843;0.019373;0.269367;, + 0.984408;0.024365;0.174202;, + 0.959207;-0.033141;0.280754;, + 0.962017;-0.206528;0.178519;, + 0.966498;-0.168546;0.193582;, + 0.976406;-0.086182;0.198001;, + 0.987549;-0.026149;0.155126;, + 0.990651;-0.059208;0.122906;, + 0.991572;-0.052289;0.118536;, + 0.967265;-0.179678;0.179202;, + 0.996580;-0.008069;0.082235;, + 0.991472;-0.016919;0.129214;, + 0.747666;-0.139847;0.649183;, + 0.119081;-0.211793;0.970033;, + 0.990935;-0.007248;0.134150;, + 0.721351;-0.142669;0.677715;, + 0.443972;-0.060466;0.893998;, + 0.376067;-0.110373;0.919995;, + 0.434429;-0.090333;0.896165;, + 0.672873;-0.178482;0.717903;, + 0.709868;-0.146248;0.688984;, + 0.362721;0.087395;0.927791;, + 0.374887;0.073105;0.924183;, + 0.312884;-0.023254;0.949507;, + 0.212041;-0.224883;0.951034;, + 0.297241;-0.210499;0.931310;, + 0.417830;-0.014675;0.908406;, + 0.383091;0.055913;0.922017;, + 0.285816;-0.314551;0.905189;, + 0.097390;-0.315817;0.943809;, + -0.106431;-0.217381;0.970267;, + 0.289110;-0.330505;0.898433;, + 0.368538;0.102287;0.923968;, + 0.324933;0.131935;0.936489;, + 0.269458;0.248871;0.930299;, + 0.190265;0.215570;0.957773;, + 0.284323;0.139703;0.948496;, + 0.190706;0.300576;0.934497;, + 0.242287;0.344618;0.906937;, + 0.209863;0.120826;0.970236;, + 0.253672;-0.005589;0.967274;, + 0.192077;0.138798;0.971515;, + 0.242108;0.270614;0.931746;, + 0.243379;0.149539;0.958335;, + 0.258802;0.073888;0.963100;, + 0.212004;0.101858;0.971946;, + 0.216250;0.294970;0.930714;, + 0.145512;0.372407;0.916591;, + 0.741126;-0.084012;0.666089;, + 0.498990;-0.008124;0.866570;, + 0.473728;0.138060;0.869782;, + 0.731146;-0.000413;0.682221;, + -0.631357;0.354670;0.689636;, + 0.632039;0.355130;0.688773;, + 0.914875;-0.152402;-0.373869;, + -0.914875;-0.152402;-0.373869;, + -0.433214;-0.193876;-0.880192;, + -0.859652;-0.309116;-0.406751;, + -0.093634;0.341116;0.935346;, + -0.093634;0.341116;0.935346;, + 0.000004;-0.093947;-0.995577;, + 0.244564;-0.065106;0.967445;, + -0.963334;-0.094433;0.251137;, + -0.989571;-0.011953;-0.143551;, + -0.885448;-0.301099;-0.354007;, + -0.989571;-0.011953;-0.143551;, + -0.982778;-0.084744;-0.164211;, + -0.957758;-0.287242;0.013841;, + -0.449270;0.893379;-0.005605;, + -0.895650;-0.343271;-0.282799;, + 0.527840;-0.168309;0.832500;, + 0.233305;-0.886660;0.399253;, + 0.513833;-0.494239;0.701216;, + 0.278233;-0.273728;0.920684;, + -0.790963;-0.525076;0.314122;, + 0.853727;-0.007027;-0.520673;, + -0.701247;-0.651828;-0.288743;, + -0.145665;-0.919602;-0.364848;, + 0.854774;-0.403493;0.326429;, + 0.174039;-0.984266;0.030518;, + -0.000016;-0.990834;-0.135089;, + 0.114825;-0.948131;-0.296416;, + 0.244564;-0.065106;0.967445;, + 0.026768;-0.438717;0.898227;, + -0.817874;-0.539381;-0.200374;, + -0.989571;-0.011953;-0.143551;, + -0.817874;-0.539381;-0.200374;, + 0.174039;-0.984266;0.030518;, + -0.434273;0.868349;-0.239535;, + -0.989261;0.138490;-0.046722;, + -0.984781;0.061328;-0.162622;, + -0.986179;0.140164;0.088351;, + -0.977952;0.018441;0.208015;, + 0.000005;-0.999974;0.007152;, + -0.897582;0.211412;-0.386848;, + -0.460194;0.616751;0.638623;, + 0.693967;0.242883;0.677803;, + -0.905288;0.176534;0.386380;, + -0.664851;0.117356;-0.737700;, + -0.897582;0.211412;-0.386848;, + -0.903847;0.420928;-0.076682;, + -0.701860;0.270507;0.658953;, + -0.457101;-0.023022;-0.889117;, + 0.000001;0.024616;-0.999697;, + -0.226499;-0.140193;-0.963869;, + 0.387797;0.626448;0.676148;, + 0.485631;0.575618;0.657895;, + 0.783381;0.503370;0.364599;, + -0.867052;0.137579;0.478846;, + -0.829671;0.408671;0.380308;, + -0.892567;0.378889;-0.244475;, + -0.886549;0.392710;-0.244562;, + -0.947696;-0.212901;-0.237792;, + -0.502434;-0.677413;0.537282;, + -0.044908;-0.611148;0.790241;, + -0.336341;-0.108795;0.935435;, + -0.899773;0.187812;0.393873;, + -0.898020;0.299543;-0.322233;, + 0.433214;-0.193877;-0.880192;, + 0.859652;-0.309116;-0.406751;, + 0.100417;0.338390;0.935633;, + 0.100417;0.338390;0.935633;, + -0.244564;-0.065106;0.967445;, + 0.963334;-0.094433;0.251137;, + 0.885448;-0.301099;-0.354007;, + 0.990082;-0.015546;-0.139630;, + 0.957347;-0.288570;0.014659;, + 0.982279;-0.089104;-0.164890;, + 0.481298;0.876550;-0.003471;, + 0.895650;-0.343271;-0.282799;, + -0.527840;-0.168309;0.832500;, + -0.513833;-0.494239;0.701216;, + -0.233305;-0.886660;0.399253;, + -0.278232;-0.273728;0.920684;, + 0.790963;-0.525076;0.314122;, + -0.853727;-0.007027;-0.520673;, + 0.145665;-0.919602;-0.364848;, + 0.701248;-0.651828;-0.288742;, + -0.854773;-0.403493;0.326429;, + -0.174039;-0.984266;0.030518;, + -0.114791;-0.948135;-0.296417;, + -0.244564;-0.065106;0.967445;, + -0.026768;-0.438717;0.898227;, + 0.817874;-0.539381;-0.200374;, + 0.990082;-0.015546;-0.139630;, + 0.990082;-0.015546;-0.139630;, + 0.817874;-0.539381;-0.200374;, + -0.174039;-0.984266;0.030518;, + 0.434273;0.868349;-0.239535;, + 0.990910;0.129582;-0.036136;, + 0.987185;0.081535;-0.137175;, + 0.972924;0.196620;0.121487;, + 0.972307;0.015440;0.233196;, + 0.897582;0.211412;-0.386848;, + -0.602846;0.290303;0.743169;, + 0.905288;0.176534;0.386380;, + 0.664851;0.117356;-0.737700;, + 0.897582;0.211412;-0.386848;, + 0.903847;0.420928;-0.076682;, + 0.701860;0.270507;0.658953;, + 0.457101;-0.023022;-0.889117;, + 0.226504;-0.140193;-0.963868;, + -0.439283;0.626634;0.643708;, + -0.559324;0.693597;0.453961;, + -0.710934;0.444973;0.544584;, + 0.867052;0.137579;0.478846;, + 0.829671;0.408671;0.380308;, + 0.892567;0.378889;-0.244475;, + 0.886549;0.392710;-0.244561;, + 0.947696;-0.212901;-0.237792;, + 0.502434;-0.677413;0.537282;, + 0.044907;-0.611148;0.790241;, + 0.336341;-0.108795;0.935435;, + 0.899773;0.187812;0.393873;, + 0.898020;0.299543;-0.322233;, + -0.550598;-0.834581;0.017782;, + -0.920508;0.371208;0.121944;, + -0.986678;0.148934;0.065464;, + -0.872109;0.095397;-0.479922;, + 0.968704;-0.213268;-0.126998;, + 0.935445;-0.035033;-0.351732;, + 0.368870;0.664338;0.650069;, + 0.215407;0.452689;0.865259;, + 0.453303;-0.497746;0.739435;, + 0.521055;-0.809078;0.271835;, + 0.735182;-0.666684;0.122637;, + 0.821914;-0.569537;-0.009215;, + 0.759558;-0.443873;-0.475446;, + -0.657196;-0.390140;-0.644891;, + -0.809310;-0.499093;-0.309716;, + -0.707861;-0.682627;-0.181530;, + -0.757874;-0.650275;-0.052618;, + -0.565959;-0.798793;0.204013;, + -0.572197;-0.246884;0.782073;, + -0.572197;-0.246884;0.782073;, + 0.453303;-0.497746;0.739435;, + -0.520474;0.526586;0.672171;, + 0.798460;-0.602012;-0.006594;, + 0.954242;-0.257523;0.152001;, + 0.918662;-0.341700;0.198244;, + -0.995822;0.066694;-0.062372;, + -0.984728;-0.003402;0.174069;, + 0.968707;-0.002938;-0.248189;, + 0.954651;-0.166315;-0.246941;, + -0.000076;-0.461661;-0.887057;, + 0.965909;-0.084351;-0.244754;, + -0.972281;0.214777;-0.092415;, + 0.956895;-0.080204;0.279139;, + -0.381353;0.920775;0.082119;, + 0.999321;0.028755;-0.023042;, + -0.673865;0.641908;0.365869;, + -0.705742;-0.122863;0.697734;, + -0.960352;-0.063982;-0.271348;, + 0.566503;-0.333624;0.753505;, + 0.059122;-0.098574;-0.993372;, + 0.059122;-0.098574;-0.993372;, + 0.039464;-0.745272;-0.665591;, + -0.354476;-0.066564;0.932693;, + 0.181561;-0.108135;0.977416;, + 0.705192;-0.523353;0.478336;, + 0.734833;-0.590132;0.334314;, + 0.703206;-0.672001;-0.232197;, + 0.318223;-0.742396;-0.589561;, + -0.868967;-0.391802;-0.302304;, + -0.911357;-0.405828;0.068791;, + 0.353830;-0.592859;-0.723410;, + 0.039464;-0.745272;-0.665591;, + 0.566503;-0.333624;0.753505;, + -0.804425;-0.481755;0.347580;, + -0.705742;-0.122863;0.697734;, + -0.212265;-0.554761;-0.804478;, + -0.300497;-0.671647;-0.677194;, + 0.909177;-0.368835;-0.193282;, + -0.507519;-0.687744;-0.519069;, + -0.955392;-0.286491;-0.071754;, + 0.738914;-0.651028;0.173689;, + 0.982818;-0.144272;-0.115132;, + -0.539943;-0.790977;-0.287777;, + 0.365426;-0.280297;0.887636;, + 0.666223;-0.143179;0.731879;, + 0.313056;0.378120;0.871219;, + -0.400237;0.683181;0.610798;, + 0.639689;-0.061333;0.766183;, + -0.557613;-0.562556;0.610408;, + 0.152980;0.089858;-0.984136;, + -0.289534;0.030294;-0.956688;, + -0.381353;0.920775;0.082119;, + -0.421748;0.283560;-0.861233;, + -0.539943;-0.790977;-0.287777;, + -0.425702;-0.452816;-0.783413;, + -0.960352;-0.063982;-0.271348;, + 0.954242;-0.257523;0.152001;, + -0.537797;0.842499;0.031136;, + -0.545698;-0.837393;0.031400;, + -0.520441;-0.817752;0.245812;, + -0.037200;-0.353239;-0.934793;, + -0.311030;-0.795975;-0.519312;, + -0.790481;-0.221084;-0.571194;, + -0.597714;-0.523944;0.606812;, + -0.264462;-0.862138;0.432178;, + -0.550598;-0.834581;0.017782;, + -0.550598;-0.834581;0.017782;, + -0.275159;-0.572461;0.772383;, + -0.314707;0.781987;-0.538011;, + -0.000538;0.773627;-0.633641;, + -0.162744;0.615741;0.770959;, + -0.559206;0.508717;0.654596;, + -0.449270;0.893379;-0.005605;, + -0.449270;0.893379;-0.005605;, + 0.000168;0.854980;0.518661;, + -0.162744;0.615741;0.770959;, + -0.530614;0.817949;0.222282;, + -0.520441;-0.817752;0.245812;, + 0.000147;-0.426759;0.904366;, + -0.877145;-0.439089;0.194469;, + 1.000000;-0.000000;0.000000;, + 1.000000;-0.000000;0.000000;, + 1.000000;-0.000000;0.000000;, + 0.955485;-0.120740;-0.269203;, + -0.945620;0.026607;-0.324184;, + -0.995610;0.037774;-0.085641;, + -0.908432;0.107750;-0.403908;, + 0.992661;-0.000187;-0.120932;, + 0.990528;-0.094784;-0.099347;, + 0.992970;-0.002293;0.118346;, + -0.906954;0.117975;-0.404371;, + 0.000005;-0.908853;-0.417117;, + 0.920508;0.371208;0.121944;, + 0.550599;-0.834580;0.017784;, + 0.986678;0.148934;0.065464;, + 0.872109;0.095396;-0.479922;, + -0.968704;-0.213269;-0.126998;, + -0.935445;-0.035034;-0.351733;, + -0.368870;0.664338;0.650069;, + -0.215408;0.452689;0.865258;, + -0.453304;-0.497746;0.739435;, + -0.521055;-0.809078;0.271836;, + -0.735182;-0.666684;0.122637;, + -0.821914;-0.569537;-0.009216;, + -0.759558;-0.443871;-0.475447;, + 0.657196;-0.390140;-0.644891;, + 0.809310;-0.499092;-0.309716;, + 0.707861;-0.682627;-0.181531;, + 0.757874;-0.650275;-0.052618;, + 0.565958;-0.798793;0.204014;, + 0.572196;-0.246884;0.782074;, + 0.572196;-0.246884;0.782074;, + -0.453304;-0.497746;0.739435;, + 0.520473;0.526586;0.672172;, + -0.798459;-0.602012;-0.006595;, + -0.954242;-0.257523;0.152001;, + -0.918662;-0.341700;0.198244;, + 0.984728;-0.003402;0.174069;, + 0.995822;0.066694;-0.062372;, + -0.968707;-0.002938;-0.248190;, + -0.954652;-0.166280;-0.246961;, + -0.965909;-0.084351;-0.244754;, + 0.972281;0.214776;-0.092415;, + -0.956895;-0.080204;0.279139;, + 0.381356;0.920774;0.082120;, + -0.999321;0.028755;-0.023042;, + 0.673864;0.641909;0.365870;, + 0.705738;-0.122868;0.697737;, + 0.960352;-0.063982;-0.271348;, + -0.059122;-0.098573;-0.993372;, + -0.059122;-0.098573;-0.993372;, + -0.039462;-0.745268;-0.665596;, + 0.354475;-0.066564;0.932693;, + -0.181560;-0.108135;0.977416;, + -0.705199;-0.523347;0.478333;, + -0.734835;-0.590129;0.334313;, + -0.703206;-0.672002;-0.232196;, + -0.318224;-0.742397;-0.589560;, + 0.868969;-0.391799;-0.302303;, + 0.911362;-0.405818;0.068789;, + -0.353826;-0.592860;-0.723412;, + -0.039462;-0.745268;-0.665596;, + -0.566507;-0.333623;0.753502;, + 0.804429;-0.481751;0.347578;, + 0.705738;-0.122868;0.697737;, + 0.212267;-0.554751;-0.804484;, + 0.300504;-0.671641;-0.677197;, + -0.909176;-0.368837;-0.193284;, + 0.507518;-0.687743;-0.519071;, + 0.955392;-0.286490;-0.071755;, + -0.738915;-0.651028;0.173686;, + -0.982818;-0.144272;-0.115132;, + 0.539944;-0.790977;-0.287776;, + -0.365426;-0.280297;0.887636;, + -0.666223;-0.143179;0.731879;, + -0.313056;0.378120;0.871218;, + 0.400237;0.683181;0.610797;, + -0.639690;-0.061333;0.766182;, + 0.557614;-0.562555;0.610409;, + -0.152979;0.089859;-0.984136;, + 0.289534;0.030294;-0.956688;, + 0.381356;0.920774;0.082120;, + 0.421748;0.283560;-0.861233;, + 0.539944;-0.790977;-0.287776;, + 0.425700;-0.452817;-0.783413;, + 0.960352;-0.063982;-0.271348;, + -0.954242;-0.257523;0.152001;, + -0.566507;-0.333623;0.753502;, + 0.545698;-0.837393;0.031400;, + 0.557573;0.829476;0.032896;, + 0.520501;-0.817725;0.245773;, + 0.037200;-0.353240;-0.934793;, + 0.311029;-0.795977;-0.519309;, + 0.790480;-0.221084;-0.571194;, + 0.597714;-0.523943;0.606812;, + 0.264462;-0.862137;0.432180;, + 0.550599;-0.834580;0.017784;, + 0.550599;-0.834580;0.017784;, + 0.275160;-0.572458;0.772385;, + 0.309521;0.783229;-0.539212;, + 0.162598;0.616218;0.770608;, + 0.566570;0.495981;0.658028;, + 0.481298;0.876550;-0.003471;, + 0.481298;0.876550;-0.003471;, + 0.530646;0.817913;0.222337;, + 0.162598;0.616218;0.770608;, + 0.520501;-0.817725;0.245773;, + 0.877144;-0.439088;0.194473;, + -0.955485;-0.120740;-0.269203;, + 0.945620;0.026607;-0.324184;, + 0.995610;0.037774;-0.085641;, + 0.908432;0.107750;-0.403908;, + -0.992661;-0.000187;-0.120933;, + -0.990528;-0.094784;-0.099347;, + -0.992970;-0.002293;0.118346;, + 0.906954;0.117975;-0.404371;, + 0.448693;0.679150;0.580886;, + 0.987197;-0.118160;-0.107142;, + 0.207701;-0.604118;-0.769351;, + 0.529914;-0.324726;-0.783418;, + 0.955178;-0.252865;0.153929;, + 0.987197;-0.118160;-0.107142;, + -0.160126;0.190092;-0.968620;, + 0.006566;0.677354;0.735628;, + 0.068168;0.237165;0.969075;, + 0.423190;-0.716621;-0.554404;, + 0.657416;-0.744773;-0.114531;, + 0.509538;-0.839165;-0.190193;, + -0.234676;0.256475;0.937629;, + -0.834983;0.264476;-0.482552;, + -0.527039;0.781296;-0.334374;, + -0.473718;0.414055;-0.777271;, + -0.160126;0.190092;-0.968620;, + -0.228376;-0.127237;-0.965223;, + -0.839542;-0.269781;-0.471581;, + -0.675963;0.077412;-0.732858;, + -0.963227;0.157435;-0.217736;, + -0.259132;0.699308;-0.666197;, + -0.527039;0.781296;-0.334374;, + -0.422834;0.836078;-0.349551;, + -0.228376;-0.127237;-0.965223;, + -0.641365;-0.305210;-0.703916;, + -0.963227;0.157435;-0.217736;, + 0.897041;0.033289;-0.440692;, + -0.146089;-0.981553;0.123336;, + 0.034059;-0.236374;-0.971065;, + -0.520041;-0.156983;0.839592;, + -0.353633;-0.752104;0.556133;, + -0.898012;0.382182;0.217971;, + -0.234676;0.256475;0.937629;, + 0.509538;-0.839165;-0.190193;, + 0.295362;0.740439;0.603748;, + -0.234676;0.256475;0.937629;, + -0.318398;0.686232;0.653995;, + 0.634338;-0.406257;-0.657701;, + -0.286418;0.500490;0.816991;, + 0.450770;-0.364624;-0.814773;, + 0.509538;-0.839165;-0.190193;, + 0.914801;0.309243;0.259824;, + -0.578072;-0.401336;0.710466;, + 0.963480;0.174780;-0.202875;, + 0.916931;0.363083;0.165554;, + 0.970183;-0.159926;0.182121;, + 0.034059;-0.236374;-0.971065;, + 0.126855;0.710394;-0.692277;, + 0.034059;-0.236374;-0.971065;, + -0.828231;-0.560343;0.007058;, + -0.156866;-0.502085;-0.850473;, + -0.898012;0.382182;0.217971;, + -0.898012;0.382182;0.217971;, + 0.426128;-0.774572;-0.467389;, + 0.396048;-0.852920;0.340107;, + -0.039929;-0.807710;-0.588227;, + 0.303641;-0.441458;-0.844344;, + -0.039929;-0.807710;-0.588227;, + -0.472468;0.843730;0.254742;, + 0.489036;0.859909;-0.146290;, + 0.568943;-0.193580;-0.799269;, + -0.472468;0.843730;0.254742;, + -0.896153;0.443634;0.009920;, + 0.826841;-0.523263;-0.206226;, + 0.500952;0.279713;0.819029;, + -0.205138;-0.005818;0.978716;, + -0.469045;0.851012;0.236169;, + -0.502437;0.667098;0.550034;, + 0.780352;-0.359300;-0.511814;, + -0.506181;0.569758;0.647422;, + 0.780352;-0.359300;-0.511814;, + -0.268806;-0.896766;-0.351502;, + -0.129004;-0.984436;0.119344;, + 0.915472;-0.398064;-0.058788;, + -0.343908;0.401841;0.848676;, + 0.777616;-0.116615;0.617830;, + 0.507759;-0.548313;-0.664480;, + -0.257983;0.544602;0.798031;, + -0.362576;0.544444;0.756386;, + 0.538295;-0.631424;-0.558159;, + 0.725324;-0.198324;0.659221;, + -0.276717;0.544754;0.791625;, + 0.456380;-0.580050;-0.674729;, + -0.464359;0.605477;0.646350;, + 0.314063;-0.536259;-0.783448;, + -0.470908;0.619311;0.628251;, + 0.329202;-0.554979;-0.763953;, + -0.242430;0.521770;0.817914;, + 0.488072;-0.623641;-0.610621;, + -0.339070;0.554869;0.759705;, + 0.450906;-0.603711;-0.657432;, + -0.560979;0.636505;0.529305;, + 0.229922;-0.482476;-0.845194;, + -0.480825;0.612885;0.627040;, + 0.327893;-0.527492;-0.783734;, + -0.130859;0.472769;0.871416;, + 0.582448;-0.641920;-0.498692;, + 0.114891;0.475550;0.872154;, + 0.738199;-0.672946;-0.046963;, + 0.654098;0.265568;0.708258;, + 0.788837;-0.361752;0.496862;, + -0.263126;0.546005;0.795389;, + 0.497233;-0.613394;-0.613602;, + 0.715283;-0.213463;0.665435;, + -0.306469;0.543138;0.781715;, + 0.446317;-0.594873;-0.668526;, + -0.452795;0.600684;0.658905;, + 0.308543;-0.543003;-0.780992;, + -0.456215;0.614991;0.643159;, + 0.335867;-0.559796;-0.757510;, + -0.263346;0.532405;0.804484;, + 0.471488;-0.618541;-0.628574;, + -0.345261;0.558515;0.754225;, + 0.439782;-0.600782;-0.667573;, + -0.537976;0.628508;0.561747;, + 0.252684;-0.497453;-0.829875;, + -0.467237;0.607846;0.642038;, + 0.333904;-0.534319;-0.776538;, + -0.165833;0.490715;0.855393;, + 0.554845;-0.638321;-0.533566;, + 0.068015;0.505465;0.860162;, + 0.701497;-0.701342;-0.126576;, + 0.636095;0.307826;0.707549;, + 0.782976;-0.407275;0.470186;, + -0.265565;0.544402;0.795677;, + 0.501872;-0.611244;-0.611969;, + 0.730965;-0.293094;0.616268;, + -0.292472;0.536722;0.791448;, + 0.440673;-0.592878;-0.674020;, + -0.447421;0.598812;0.664258;, + 0.294817;-0.536769;-0.790545;, + -0.451790;0.613142;0.648030;, + 0.324769;-0.553847;-0.766667;, + -0.247760;0.524381;0.814641;, + 0.467816;-0.617010;-0.632809;, + -0.334234;0.553031;0.763180;, + 0.434085;-0.598441;-0.673379;, + -0.537145;0.628597;0.562442;, + 0.236650;-0.488015;-0.840142;, + -0.462849;0.606173;0.646780;, + 0.323287;-0.527601;-0.785571;, + -0.146317;0.479991;0.864985;, + 0.555697;-0.637603;-0.533538;, + 0.090407;0.490418;0.866785;, + 0.709732;-0.695413;-0.112611;, + 0.646355;0.289593;0.705947;, + 0.787167;-0.396002;0.472811;, + -0.212404;0.516342;0.829624;, + 0.516966;-0.608447;-0.602112;, + -0.215861;0.514387;0.829946;, + 0.400936;-0.557240;-0.727141;, + -0.409694;0.584477;0.700383;, + 0.255763;-0.507343;-0.822915;, + -0.416769;0.599193;0.683573;, + 0.271222;-0.525963;-0.806102;, + -0.182521;0.489258;0.852827;, + 0.434921;-0.604440;-0.667455;, + -0.280896;0.526446;0.802466;, + 0.395442;-0.582473;-0.710176;, + -0.512610;0.622446;0.591432;, + 0.170371;-0.449244;-0.877014;, + -0.427834;0.592777;0.682329;, + 0.271016;-0.497964;-0.823761;, + 0.892887;0.164047;-0.419335;, + -0.071795;0.436064;0.897047;, + 0.535967;-0.630109;-0.561873;, + 0.170183;0.433298;0.885037;, + 0.717370;-0.686582;-0.118260;, + 0.689840;0.223648;0.688551;, + 0.804020;-0.394183;0.445166;, + -0.588806;0.000143;0.808275;, + -0.886836;0.434833;0.156336;, + 0.226188;-0.397375;0.889344;, + 0.313446;0.294967;0.902633;, + -0.123513;0.634708;0.762817;, + 0.396692;0.282270;-0.873475;, + -0.557305;-0.389761;0.733143;, + 0.964289;0.264843;-0.002032;, + 0.506951;-0.238596;0.828295;, + 0.506951;-0.238596;0.828295;, + -0.957604;-0.179816;-0.225078;, + -0.529914;-0.324726;-0.783418;, + -0.148924;-0.632604;-0.760022;, + -0.994196;0.051821;0.094280;, + -0.871225;-0.451441;0.192789;, + 0.160126;0.190092;-0.968620;, + -0.006566;0.677353;0.735628;, + -0.057386;0.245516;0.967692;, + -0.657416;-0.744773;-0.114531;, + -0.423190;-0.716621;-0.554404;, + -0.509830;-0.838926;-0.190465;, + 0.391442;0.389355;0.833772;, + 0.834983;0.264476;-0.482552;, + 0.527039;0.781296;-0.334374;, + 0.473718;0.414055;-0.777271;, + 0.160126;0.190092;-0.968620;, + 0.228376;-0.127237;-0.965223;, + 0.839542;-0.269781;-0.471581;, + 0.675963;0.077412;-0.732859;, + 0.963227;0.157435;-0.217736;, + 0.259132;0.699308;-0.666198;, + 0.422834;0.836078;-0.349550;, + 0.527039;0.781296;-0.334374;, + 0.641365;-0.305210;-0.703916;, + 0.228376;-0.127237;-0.965223;, + 0.963227;0.157435;-0.217736;, + -0.897162;0.033159;-0.440455;, + 0.146090;-0.981553;0.123336;, + -0.034059;-0.236375;-0.971065;, + 0.520040;-0.156982;0.839592;, + 0.353633;-0.752104;0.556133;, + 0.391442;0.389355;0.833772;, + 0.653620;0.114523;0.748107;, + 0.520040;-0.156982;0.839592;, + -0.509830;-0.838926;-0.190465;, + -0.190416;0.835663;0.515178;, + 0.438815;0.143443;0.887054;, + 0.898012;0.382183;0.217970;, + -0.634338;-0.406257;-0.657701;, + -0.451041;-0.364729;-0.814576;, + -0.509830;-0.838926;-0.190465;, + -0.607672;0.793048;-0.042537;, + 0.578072;-0.401336;0.710466;, + -0.964421;0.191784;-0.181966;, + -0.881035;0.426148;0.205365;, + -0.980241;-0.139652;0.140090;, + -0.034059;-0.236375;-0.971065;, + -0.126856;0.710394;-0.692277;, + -0.034059;-0.236375;-0.971065;, + 0.828231;-0.560342;0.007058;, + 0.156866;-0.502085;-0.850473;, + 0.898012;0.382183;0.217970;, + 0.898012;0.382183;0.217970;, + -0.667053;-0.649082;0.365696;, + -0.492298;-0.784288;-0.377538;, + -0.494156;0.758623;-0.424618;, + 0.063298;-0.757803;-0.649405;, + 0.063298;-0.757803;-0.649405;, + 0.505009;0.836271;0.213581;, + -0.552096;-0.122315;-0.824760;, + 0.505009;0.836271;0.213581;, + 0.894433;0.447026;-0.012553;, + -0.823845;-0.530391;-0.199912;, + -0.489616;0.263036;0.831317;, + 0.188469;-0.005536;0.982064;, + 0.475166;0.851493;0.221757;, + 0.500593;0.666086;0.552935;, + -0.774625;-0.362944;-0.517907;, + 0.498824;0.566633;0.655822;, + -0.913491;-0.404743;-0.041435;, + 0.338248;0.393374;0.854895;, + -0.765877;-0.131961;0.629300;, + -0.499148;-0.545190;-0.673512;, + -0.714900;-0.212902;0.666026;, + -0.857968;0.149295;-0.491531;, + 0.351827;0.537583;0.766305;, + 0.247538;0.533303;0.808896;, + -0.533434;-0.631638;-0.562567;, + 0.266062;0.534893;0.801936;, + -0.447982;-0.577196;-0.682757;, + 0.457685;0.602796;0.653575;, + -0.302952;-0.528059;-0.793330;, + 0.464637;0.616931;0.635224;, + -0.320375;-0.545709;-0.774314;, + 0.231555;0.510140;0.828335;, + -0.482310;-0.621551;-0.617294;, + 0.330057;0.546220;0.769874;, + -0.443595;-0.600833;-0.664998;, + 0.557674;0.637189;0.531969;, + -0.218196;-0.468925;-0.855862;, + 0.475036;0.610817;0.633438;, + -0.320194;-0.517249;-0.793681;, + 0.120529;0.460012;0.879694;, + -0.579460;-0.642332;-0.501632;, + -0.117801;0.461501;0.879284;, + -0.737915;-0.674242;-0.029655;, + -0.649761;0.259288;0.714549;, + -0.783249;-0.356084;0.509632;, + 0.252546;0.535085;0.806166;, + -0.490701;-0.611734;-0.620479;, + -0.703251;-0.226621;0.673855;, + 0.295401;0.533999;0.792201;, + -0.438220;-0.592052;-0.676341;, + 0.445511;0.597421;0.666789;, + -0.297424;-0.534529;-0.791086;, + 0.449368;0.612043;0.650747;, + -0.326742;-0.550893;-0.767956;, + 0.252472;0.521534;0.815021;, + -0.465089;-0.615834;-0.635956;, + 0.335949;0.550139;0.764517;, + -0.432019;-0.597419;-0.675611;, + 0.533739;0.628202;0.566114;, + -0.240978;-0.484831;-0.840755;, + 0.460786;0.605148;0.649209;, + -0.325458;-0.524380;-0.786831;, + 0.154787;0.478816;0.864162;, + -0.550996;-0.638131;-0.537766;, + -0.072427;0.492303;0.867406;, + -0.702169;-0.703184;-0.111764;, + -0.633977;0.303269;0.711408;, + -0.780241;-0.399104;0.481601;, + 0.254891;0.533546;0.806448;, + -0.495277;-0.609732;-0.618812;, + -0.721934;-0.308194;0.619538;, + 0.281251;0.527055;0.801942;, + -0.432483;-0.589889;-0.681901;, + 0.440073;0.595333;0.672246;, + -0.283571;-0.527836;-0.800610;, + 0.444854;0.609993;0.655754;, + -0.315564;-0.544433;-0.777182;, + 0.236801;0.512915;0.825133;, + -0.461342;-0.614098;-0.640349;, + 0.324837;0.544170;0.773537;, + -0.426219;-0.594861;-0.681526;, + 0.532960;0.628250;0.566794;, + -0.224869;-0.474782;-0.850891;, + 0.456355;0.603310;0.654031;, + -0.314900;-0.517199;-0.795828;, + 0.135489;0.467543;0.873525;, + -0.551857;-0.637341;-0.537819;, + -0.094199;0.476771;0.873966;, + -0.710203;-0.697232;-0.097362;, + -0.643422;0.284541;0.710665;, + -0.783588;-0.388614;0.484736;, + 0.201577;0.503110;0.840385;, + -0.510465;-0.607468;-0.608611;, + 0.204883;0.502219;0.840119;, + -0.391192;-0.551987;-0.736396;, + 0.401612;0.579399;0.709228;, + -0.244152;-0.497096;-0.832638;, + 0.408987;0.594527;0.692291;, + -0.261639;-0.514291;-0.816731;, + 0.171512;0.475490;0.862840;, + -0.427611;-0.599957;-0.676166;, + 0.271095;0.515384;0.812949;, + -0.386791;-0.577398;-0.719030;, + 0.507899;0.621019;0.596970;, + -0.158619;-0.433804;-0.886935;, + 0.420631;0.588517;0.690447;, + -0.262650;-0.485562;-0.833813;, + 0.062071;0.421776;0.904573;, + -0.531432;-0.628929;-0.567476;, + -0.171508;0.418312;0.891964;, + -0.717453;-0.688923;-0.103178;, + -0.684430;0.217897;0.695756;, + -0.798889;-0.388529;0.459153;, + 0.563755;-0.000870;0.825942;, + 0.886836;0.434833;0.156336;, + -0.202243;-0.425807;0.881922;, + 0.166307;0.647301;0.743870;, + -0.301252;0.328615;0.895131;, + 0.549353;-0.390720;0.738613;, + -0.944779;0.327439;0.013305;, + -0.529409;-0.220751;0.819143;, + -0.529409;-0.220751;0.819143;, + 0.214009;0.839435;0.499548;, + 0.774218;0.487454;0.403702;, + -0.957604;-0.179816;-0.225078;, + -0.169599;0.852875;0.493802;, + 0.343698;0.922858;0.173795;, + 0.485631;0.575618;0.657895;, + -0.260653;0.953967;0.148347;, + 0.055097;0.933688;0.353823;, + -0.559324;0.693597;0.453961;, + -0.540286;0.724558;-0.427911;, + -0.496164;0.335976;-0.800588;, + -0.540286;0.724558;-0.427911;, + -0.654263;-0.049613;-0.754638;, + -0.496164;0.335976;-0.800588;, + -0.540286;0.724558;-0.427911;, + -0.540286;0.724558;-0.427911;, + -0.654263;-0.049613;-0.754638;, + -0.654263;-0.049613;-0.754638;, + -0.563708;-0.395781;-0.724976;, + -0.235609;0.971832;-0.005539;, + -0.284112;0.944212;0.166567;, + -0.232970;0.970399;0.063643;, + -0.302341;0.947980;-0.099615;, + -0.793812;0.600245;-0.097818;, + -0.000001;0.818760;0.574136;, + 0.382016;0.040071;0.923286;, + -0.000000;-0.444151;0.895952;, + 0.012819;0.940525;0.339483;, + -0.394637;-0.137254;0.908528;, + -0.231714;-0.275342;0.933003;, + -0.432713;-0.354931;0.828724;, + -0.733140;-0.437535;0.520643;, + -0.944986;-0.217661;0.244183;, + -0.965289;-0.090055;-0.245168;, + -0.404283;-0.450662;0.795902;, + -0.944986;-0.217661;0.244183;, + -0.432713;-0.354931;0.828724;, + -0.886311;0.419497;-0.196151;, + -0.232970;0.970399;0.063643;, + -0.235609;0.971832;-0.005539;, + -0.899678;-0.251384;-0.356911;, + -0.496164;0.335976;-0.800588;, + -0.984181;0.095585;0.149171;, + -0.899678;-0.251384;-0.356911;, + -0.534104;0.546724;-0.644846;, + -0.540286;0.724558;-0.427911;, + -0.899678;-0.251384;-0.356911;, + -0.806852;-0.393759;-0.440389;, + -0.563708;-0.395781;-0.724976;, + -0.000000;0.298174;-0.954511;, + -0.654263;-0.049613;-0.754638;, + -0.654263;-0.049613;-0.754638;, + -0.000000;0.298174;-0.954511;, + -0.929825;-0.231328;0.286203;, + -0.861728;0.431543;-0.266824;, + -0.793812;0.600245;-0.097818;, + -0.000000;0.630324;-0.776332;, + -0.534104;0.546724;-0.644846;, + -0.899678;-0.251384;-0.356911;, + -0.861728;0.431543;-0.266824;, + -0.000000;-0.029730;-0.999558;, + -0.927251;-0.170149;-0.333550;, + -0.534104;0.546724;-0.644846;, + -0.927251;-0.170149;-0.333550;, + -0.422789;0.519154;-0.742784;, + -0.000000;0.998500;0.054759;, + 0.014166;0.945681;-0.324786;, + -0.000000;0.998500;0.054759;, + -0.534104;0.546724;-0.644846;, + -0.861728;0.431543;-0.266824;, + -0.699443;-0.209423;-0.683316;, + -0.178300;-0.323577;-0.929251;, + -0.691836;-0.542995;-0.475940;, + -0.178300;-0.323577;-0.929251;, + -0.937849;0.041613;0.344540;, + -0.861728;0.431543;-0.266824;, + -0.879018;0.070016;-0.471619;, + -0.793812;0.600245;-0.097818;, + -0.701635;0.645253;-0.302255;, + -0.944986;-0.217661;0.244183;, + -0.000000;0.998500;0.054759;, + -0.000000;0.868934;-0.494927;, + -0.540286;0.724558;-0.427911;, + -0.000000;-0.029730;-0.999558;, + -0.000000;0.630324;-0.776332;, + -0.496164;0.335976;-0.800588;, + -0.496164;0.335976;-0.800588;, + -0.899678;-0.251384;-0.356911;, + -0.654263;-0.049613;-0.754638;, + -0.793812;0.600245;-0.097818;, + -0.861728;0.431543;-0.266824;, + -0.899678;-0.251384;-0.356911;, + -0.000000;0.998500;0.054759;, + -0.691836;-0.542995;-0.475940;, + -0.563708;-0.395781;-0.724976;, + -0.806852;-0.393759;-0.440389;, + -0.559606;-0.645175;-0.520183;, + -0.000000;0.998500;0.054759;, + 0.540286;0.724558;-0.427911;, + -0.000000;0.630324;-0.776332;, + 0.496164;0.335976;-0.800588;, + 0.540286;0.724558;-0.427911;, + 0.654263;-0.049613;-0.754638;, + 0.496164;0.335976;-0.800588;, + 0.540286;0.724558;-0.427911;, + 0.540286;0.724558;-0.427911;, + -0.000000;0.868934;-0.494927;, + 0.654263;-0.049613;-0.754638;, + -0.000000;0.298174;-0.954511;, + 0.654263;-0.049613;-0.754638;, + 0.563708;-0.395781;-0.724976;, + 0.235609;0.971832;-0.005539;, + 0.232970;0.970399;0.063643;, + 0.284111;0.944212;0.166568;, + 0.886230;0.418543;-0.198540;, + 0.793812;0.600245;-0.097818;, + -0.382017;0.040070;0.923286;, + -0.012819;0.940525;0.339483;, + 0.231714;-0.275342;0.933003;, + 0.394636;-0.137254;0.908528;, + 0.432713;-0.354931;0.828724;, + 0.930868;-0.256053;0.260617;, + 0.965023;-0.089095;-0.246563;, + 0.732571;-0.437022;0.521873;, + 0.302341;0.947980;-0.099615;, + 0.232970;0.970399;0.063643;, + 0.235609;0.971832;-0.005539;, + 0.899678;-0.251384;-0.356911;, + 0.496164;0.335976;-0.800588;, + 0.899678;-0.251384;-0.356911;, + 0.553016;0.656553;-0.512944;, + 0.540286;0.724558;-0.427911;, + 0.899678;-0.251384;-0.356911;, + 0.836668;-0.377812;-0.396542;, + 0.563708;-0.395781;-0.724976;, + -0.000000;0.298174;-0.954511;, + 0.654263;-0.049613;-0.754638;, + 0.654263;-0.049613;-0.754638;, + -0.142878;-0.121955;-0.982198;, + -0.000000;0.298174;-0.954511;, + 0.930521;-0.221376;0.291758;, + 0.945515;0.306078;-0.110984;, + 0.924672;0.127786;0.358681;, + 0.793812;0.600245;-0.097818;, + -0.000000;0.630324;-0.776332;, + 0.553016;0.656553;-0.512944;, + -0.000000;-0.029730;-0.999558;, + 0.899678;-0.251384;-0.356911;, + 0.945515;0.306078;-0.110984;, + -0.000000;-0.029730;-0.999558;, + 0.932085;0.115972;-0.343175;, + -0.014166;0.945682;-0.324786;, + 0.553016;0.656553;-0.512944;, + 0.945515;0.306078;-0.110984;, + 0.490285;-0.201883;-0.847858;, + 0.366430;-0.311048;-0.876914;, + 0.642185;-0.647026;-0.411043;, + 0.366430;-0.311048;-0.876914;, + 0.940115;0.027121;0.339777;, + 0.945515;0.306078;-0.110984;, + 0.793812;0.600245;-0.097818;, + 0.879018;0.070016;-0.471619;, + 0.701635;0.645253;-0.302255;, + 0.930868;-0.256053;0.260617;, + -0.000000;0.998500;0.054759;, + -0.000000;0.868934;-0.494927;, + 0.540286;0.724558;-0.427911;, + -0.000000;-0.029730;-0.999558;, + -0.000000;0.630324;-0.776332;, + 0.496164;0.335976;-0.800588;, + 0.496164;0.335976;-0.800588;, + 0.899678;-0.251384;-0.356911;, + 0.654263;-0.049613;-0.754638;, + 0.793812;0.600245;-0.097818;, + -0.136274;0.884818;0.445562;, + -0.102555;-0.767205;-0.633151;, + 0.945515;0.306078;-0.110984;, + 0.899678;-0.251384;-0.356911;, + -0.000000;0.998500;0.054759;, + 0.642185;-0.647026;-0.411043;, + 0.563708;-0.395781;-0.724976;, + 0.836668;-0.377812;-0.396542;, + 0.559606;-0.645176;-0.520182;, + 0.836668;-0.377812;-0.396542;, + 0.642185;-0.647026;-0.411043;, + 0.403086;-0.867962;-0.290108;, + 0.373002;-0.795669;-0.477263;, + 0.558443;-0.699105;0.446535;, + 0.772381;-0.152248;0.616642;, + -0.833821;-0.284781;0.472909;, + -0.488240;-0.590800;0.642322;, + -0.337534;-0.853552;-0.396886;, + -0.607999;-0.786791;-0.106285;, + 0.077777;-0.993666;-0.081114;, + -0.091466;-0.994758;-0.045715;, + -0.178300;-0.323577;-0.929251;, + -0.142878;-0.121955;-0.982198;, + 0.366430;-0.311048;-0.876914;, + 0.260508;0.727642;-0.634565;, + -0.040453;0.710290;-0.702746;, + -0.588256;0.730768;-0.346313;, + -0.010918;-0.937228;0.348545;, + -0.238496;-0.799571;0.551186;, + 0.193201;-0.890421;0.412097;, + 0.014300;-0.847026;0.531360;, + -0.801728;-0.276819;0.529721;, + -0.615086;-0.386827;0.687047;, + -0.793967;-0.433457;0.426300;, + -0.745782;-0.452954;0.488509;, + -0.932337;-0.361278;-0.015029;, + -0.856324;-0.247040;-0.453521;, + -0.707919;-0.624087;-0.330705;, + -0.531094;-0.706015;-0.468489;, + -0.808123;-0.461550;-0.365936;, + -0.948825;-0.033448;0.314026;, + -0.930713;-0.092278;0.353918;, + -0.920811;-0.172908;0.349584;, + -0.916339;-0.265300;0.299899;, + -0.604821;-0.388772;-0.695017;, + -0.945731;0.117071;0.303128;, + -0.970327;0.034796;0.239279;, + -0.978433;-0.005143;0.206502;, + -0.861728;0.431543;-0.266824;, + -0.531997;-0.340199;0.775399;, + -0.689076;-0.199468;0.696697;, + -0.741015;0.256716;0.620479;, + -0.216517;0.601928;0.768637;, + -0.823955;0.147553;0.547108;, + -0.759279;0.153427;0.632421;, + -0.896238;-0.324230;0.302709;, + -0.280865;-0.155167;0.947121;, + -0.478361;-0.492783;0.726868;, + -0.124352;-0.098909;0.987296;, + -0.205252;0.312404;0.927510;, + -0.110123;-0.025715;0.993585;, + -0.937849;0.041613;0.344540;, + -0.929825;-0.231328;0.286203;, + -0.699443;-0.209423;-0.683316;, + -0.806852;-0.393759;-0.440389;, + -0.806852;-0.393759;-0.440389;, + -0.691836;-0.542995;-0.475940;, + -0.767636;-0.389543;-0.508912;, + -0.551796;-0.574616;-0.604431;, + -0.979289;0.016954;0.201754;, + -0.966193;0.076246;0.246286;, + -0.877724;-0.460197;-0.133489;, + -0.551796;-0.574616;-0.604431;, + -0.923625;-0.293416;-0.246623;, + -0.551796;-0.574616;-0.604431;, + -0.460194;0.616751;0.638623;, + -0.237549;0.171176;0.956174;, + -0.246128;0.432303;0.867488;, + -0.304277;-0.311038;0.900372;, + -0.207669;-0.717728;0.664635;, + -0.223441;-0.620814;0.751442;, + -0.371514;-0.104033;0.922580;, + -0.292418;0.016174;0.956154;, + -0.291101;0.296117;0.909711;, + -0.290228;0.134824;0.947413;, + 0.732447;-0.463382;0.498797;, + 0.823502;-0.420165;0.381189;, + 0.796203;-0.311752;0.518528;, + 0.557281;-0.410177;0.721937;, + 0.663539;-0.666241;-0.340352;, + 0.627769;-0.641265;-0.441233;, + 0.924341;-0.229764;-0.304633;, + 0.885166;-0.437540;-0.158241;, + 0.825383;-0.420119;-0.377152;, + 0.927430;-0.166498;0.334890;, + 0.916339;-0.265300;0.299899;, + 0.922761;-0.080766;0.376814;, + 0.959207;-0.033141;0.280754;, + 0.618095;-0.351774;-0.703004;, + 0.962843;0.019373;0.269367;, + 0.983531;0.088214;0.157748;, + 0.930868;-0.256053;0.260617;, + 0.432713;-0.354931;0.828724;, + 0.553016;0.656553;-0.512944;, + 0.945515;0.306078;-0.110984;, + 0.993793;-0.011471;0.110653;, + 0.479423;0.478311;0.735780;, + 0.781695;0.234974;0.577703;, + 0.679518;-0.160347;0.715922;, + 0.358587;-0.591042;0.722554;, + 0.819624;0.148430;0.553340;, + 0.781224;0.181945;0.597148;, + 0.891387;-0.329329;0.311403;, + 0.041593;0.020366;0.998927;, + 0.377267;-0.289994;0.879530;, + 0.105429;-0.086429;0.990664;, + 0.222570;0.434020;0.872977;, + 0.940115;0.027121;0.339777;, + 0.930521;-0.221376;0.291758;, + 0.629863;0.520365;-0.576622;, + 0.932085;0.115972;-0.343175;, + 0.490285;-0.201883;-0.847858;, + 0.836668;-0.377812;-0.396542;, + 0.836668;-0.377812;-0.396542;, + 0.642185;-0.647026;-0.411043;, + 0.551796;-0.574616;-0.604431;, + 0.831536;-0.420486;-0.362960;, + 0.551796;-0.574616;-0.604431;, + 0.955968;0.074254;0.283920;, + 0.992970;0.009011;0.118019;, + 0.872770;-0.467932;-0.138969;, + 0.831536;-0.420486;-0.362960;, + 0.448693;0.679150;0.580886;, + 0.218225;0.244375;0.944806;, + 0.291626;0.332066;0.897043;, + 0.323872;-0.438181;0.838513;, + 0.236939;-0.570878;0.786103;, + 0.298672;-0.579421;0.758332;, + 0.305557;-0.031119;0.951665;, + 0.302334;0.087757;0.949154;, + 0.249071;0.370670;0.894744;, + 0.278707;0.095201;0.955646;, + -0.305307;0.626286;0.717324;, + 0.313062;0.614710;0.723964;, + 0.404283;-0.450662;0.795902;, + 0.914875;-0.152402;-0.373869;, + -0.914875;-0.152402;-0.373869;; + 6841; + 3;28,62,1;, + 3;3,16,3420;, + 3;11,23,29;, + 3;104,69,7;, + 3;0,13,70;, + 3;9,97,96;, + 3;3421,71,2;, + 3;15,22,3;, + 3;3420,15,3;, + 3;68,4,15;, + 3;116,111,106;, + 3;3422,12,6;, + 3;6,12,1742;, + 3;24,14,12;, + 3;3423,108,119;, + 3;102,7,13;, + 3;13,30,23;, + 3;3420,2,15;, + 3;115,116,106;, + 3;100,3424,17;, + 3;100,1,3424;, + 3;1,18,19;, + 3;28,1,19;, + 3;104,94,69;, + 3;15,4,20;, + 3;98,8,97;, + 3;115,106,114;, + 3;29,23,126;, + 3;3422,24,12;, + 3;30,0,27;, + 3;26,11,29;, + 3;24,3422,3425;, + 3;27,126,23;, + 3;3426,3427,3428;, + 3;23,11,13;, + 3;13,0,30;, + 3;23,30,27;, + 3;108,107,120;, + 3;31,6,1741;, + 3;25,32,29;, + 3;32,26,29;, + 3;136,132,135;, + 3;32,25,65;, + 3;63,60,35;, + 3;3419,3429,63;, + 3;35,59,34;, + 3;58,59,16;, + 3;41,36,848;, + 3;51,53,49;, + 3;3430,55,49;, + 3;82,848,36;, + 3;24,38,14;, + 3;84,49,53;, + 3;81,82,43;, + 3;83,3431,39;, + 3;41,45,36;, + 3;40,3430,3432;, + 3;41,37,47;, + 3;24,52,48;, + 3;3430,49,84;, + 3;38,48,50;, + 3;38,24,48;, + 3;49,55,50;, + 3;50,51,49;, + 3;55,56,50;, + 3;48,51,50;, + 3;81,43,80;, + 3;67,54,3433;, + 3;39,66,44;, + 3;50,56,38;, + 3;3430,40,55;, + 3;56,57,38;, + 3;55,40,56;, + 3;56,436,57;, + 3;51,48,52;, + 3;3434,3435,3436;, + 3;3437,3438,3435;, + 3;3437,3439,3438;, + 3;33,3439,3437;, + 3;64,3440,3441;, + 3;3442,3443,33;, + 3;3440,3444,3445;, + 3;52,24,3425;, + 3;3434,3436,3446;, + 3;16,59,3420;, + 3;60,3420,59;, + 3;58,34,59;, + 3;60,3421,3420;, + 3;35,60,59;, + 3;61,27,0;, + 3;3447,61,3448;, + 3;28,3449,62;, + 3;3420,3421,2;, + 3;63,3429,3421;, + 3;3419,63,3450;, + 3;63,3421,60;, + 3;33,64,3442;, + 3;3450,63,35;, + 3;65,129,3447;, + 3;3434,3437,3435;, + 3;3444,42,3445;, + 3;3445,3441,3440;, + 3;39,3451,66;, + 3;3441,3442,64;, + 3;53,67,3433;, + 3;33,3443,3439;, + 3;2,68,15;, + 3;3452,3453,69;, + 3;70,13,7;, + 3;3421,3429,71;, + 3;0,70,73;, + 3;73,72,0;, + 3;7,69,75;, + 3;75,74,7;, + 3;3454,3455,77;, + 3;77,76,3454;, + 3;3453,3456,79;, + 3;79,78,3453;, + 3;70,7,74;, + 3;74,73,70;, + 3;69,3453,78;, + 3;78,75,69;, + 3;3456,3454,76;, + 3;76,79,3456;, + 3;3455,0,72;, + 3;72,77,3455;, + 3;80,43,3457;, + 3;43,82,44;, + 3;37,81,80;, + 3;44,82,83;, + 3;81,37,82;, + 3;44,83,39;, + 3;83,82,36;, + 3;3433,84,53;, + 3;83,36,3431;, + 3;3,22,85;, + 3;110,112,113;, + 3;22,89,85;, + 3;110,114,106;, + 3;95,118,111;, + 3;3447,128,61;, + 3;22,90,89;, + 3;110,113,114;, + 3;109,112,110;, + 3;90,22,91;, + 3;15,91,22;, + 3;15,92,91;, + 3;15,20,92;, + 3;92,20,93;, + 3;117,111,116;, + 3;3452,94,3458;, + 3;94,3452,69;, + 3;99,96,21;, + 3;111,117,95;, + 3;9,96,99;, + 3;1739,97,9;, + 3;97,8,21;, + 3;97,21,96;, + 3;10,98,97;, + 3;31,3422,6;, + 3;1741,6,1744;, + 3;88,99,845;, + 3;107,118,95;, + 3;18,100,17;, + 3;18,1,100;, + 3;101,102,13;, + 3;11,101,13;, + 3;119,108,120;, + 3;103,7,102;, + 3;107,121,120;, + 3;95,122,107;, + 3;107,123,121;, + 3;95,117,122;, + 3;107,122,123;, + 3;103,105,104;, + 3;103,104,7;, + 3;3459,5,106;, + 3;106,111,3459;, + 3;3423,3460,108;, + 3;3423,119,3461;, + 3;3462,3463,116;, + 3;116,115,3462;, + 3;3464,3465,122;, + 3;122,117,3464;, + 3;3466,3462,115;, + 3;115,114,3466;, + 3;107,108,3460;, + 3;3467,3468,113;, + 3;113,112,3467;, + 3;3469,3459,111;, + 3;111,118,3469;, + 3;3468,3466,114;, + 3;114,113,3468;, + 3;87,86,109;, + 3;109,110,87;, + 3;3463,3464,117;, + 3;117,116,3463;, + 3;3470,3469,118;, + 3;118,3471,3470;, + 3;3472,3461,119;, + 3;119,120,3472;, + 3;3473,3472,120;, + 3;120,121,3473;, + 3;3474,3473,121;, + 3;121,123,3474;, + 3;3465,3474,123;, + 3;123,122,3465;, + 3;65,25,124;, + 3;130,132,131;, + 3;127,126,27;, + 3;129,128,3447;, + 3;27,125,127;, + 3;29,126,25;, + 3;134,132,130;, + 3;130,133,134;, + 3;125,27,128;, + 3;128,27,61;, + 3;65,124,129;, + 3;131,132,136;, + 3;3475,3476,135;, + 3;135,132,3475;, + 3;3476,3477,136;, + 3;136,135,3476;, + 3;3478,3479,130;, + 3;130,131,3478;, + 3;3480,3481,134;, + 3;134,133,3480;, + 3;3481,3475,132;, + 3;132,134,3481;, + 3;3479,3480,133;, + 3;133,130,3479;, + 3;3477,3478,131;, + 3;131,136,3477;, + 3;158,138,184;, + 3;3,3482,16;, + 3;145,159,153;, + 3;221,143,191;, + 3;137,192,146;, + 3;144,214,215;, + 3;3483,139,193;, + 3;147,3,152;, + 3;3482,3,147;, + 3;190,147,140;, + 3;231,223,227;, + 3;3484,142,12;, + 3;142,1742,12;, + 3;154,12,14;, + 3;3485,234,225;, + 3;219,146,143;, + 3;146,153,160;, + 3;3482,147,139;, + 3;230,223,231;, + 3;217,17,3424;, + 3;217,3424,138;, + 3;138,149,148;, + 3;158,149,138;, + 3;221,191,212;, + 3;147,150,140;, + 3;98,215,8;, + 3;230,229,223;, + 3;159,241,153;, + 3;3484,12,154;, + 3;160,157,137;, + 3;156,159,145;, + 3;154,3486,3484;, + 3;157,153,241;, + 3;3487,3488,3489;, + 3;153,146,145;, + 3;146,160,137;, + 3;153,157,160;, + 3;225,235,224;, + 3;161,1743,142;, + 3;155,159,162;, + 3;162,159,156;, + 3;251,250,247;, + 3;162,187,155;, + 3;185,164,182;, + 3;183,3418,137;, + 3;164,34,181;, + 3;58,16,181;, + 3;168,37,847;, + 3;175,173,177;, + 3;165,173,179;, + 3;203,847,37;, + 3;154,14,38;, + 3;205,177,173;, + 3;202,169,203;, + 3;204,166,3490;, + 3;168,3491,171;, + 3;167,3492,165;, + 3;168,47,37;, + 3;154,172,176;, + 3;165,205,173;, + 3;38,174,172;, + 3;38,172,154;, + 3;173,174,179;, + 3;174,173,175;, + 3;179,174,180;, + 3;172,174,175;, + 3;202,80,169;, + 3;189,3493,178;, + 3;166,170,188;, + 3;174,38,180;, + 3;165,179,167;, + 3;180,38,57;, + 3;179,180,167;, + 3;734,57,46;, + 3;175,176,172;, + 3;3494,3495,3496;, + 3;3497,3496,3498;, + 3;3497,3498,3499;, + 3;163,3497,3499;, + 3;186,3500,3501;, + 3;3502,163,3503;, + 3;3501,3504,3444;, + 3;176,3486,154;, + 3;3494,3505,3495;, + 3;16,3482,181;, + 3;182,181,3482;, + 3;58,181,34;, + 3;182,3482,3483;, + 3;164,181,182;, + 3;183,137,157;, + 3;3506,3507,183;, + 3;158,184,3508;, + 3;3482,139,3483;, + 3;185,3483,3509;, + 3;183,3507,3418;, + 3;185,182,3483;, + 3;163,3502,186;, + 3;3510,164,185;, + 3;187,3506,244;, + 3;3494,3496,3497;, + 3;3444,3504,42;, + 3;3504,3501,3500;, + 3;166,188,3511;, + 3;3500,186,3502;, + 3;177,3493,189;, + 3;163,3499,3503;, + 3;139,147,190;, + 3;3512,191,3513;, + 3;192,143,146;, + 3;3483,193,3509;, + 3;137,195,192;, + 3;195,137,194;, + 3;143,197,191;, + 3;197,143,196;, + 3;3514,199,3515;, + 3;199,3514,198;, + 3;3513,201,3516;, + 3;201,3513,200;, + 3;192,196,143;, + 3;196,192,195;, + 3;191,200,3513;, + 3;200,191,197;, + 3;3516,198,3514;, + 3;198,3516,201;, + 3;3515,194,137;, + 3;194,3515,199;, + 3;80,3457,169;, + 3;169,170,203;, + 3;37,80,202;, + 3;170,204,203;, + 3;202,203,37;, + 3;170,166,204;, + 3;204,3491,203;, + 3;3493,177,205;, + 3;204,3490,3491;, + 3;3,85,152;, + 3;226,228,112;, + 3;152,85,89;, + 3;226,223,229;, + 3;213,227,233;, + 3;3506,183,243;, + 3;152,89,208;, + 3;226,229,228;, + 3;109,226,112;, + 3;208,209,152;, + 3;147,152,209;, + 3;147,209,210;, + 3;147,210,150;, + 3;210,211,150;, + 3;232,231,227;, + 3;3512,3517,212;, + 3;212,191,3512;, + 3;216,151,214;, + 3;227,213,232;, + 3;144,216,214;, + 3;10,1740,215;, + 3;215,151,8;, + 3;215,214,151;, + 3;10,215,98;, + 3;161,142,3484;, + 3;1745,1742,142;, + 3;846,151,216;, + 3;224,213,233;, + 3;148,17,217;, + 3;148,217,138;, + 3;218,146,219;, + 3;145,146,218;, + 3;234,235,225;, + 3;220,219,143;, + 3;224,235,236;, + 3;213,224,237;, + 3;224,236,238;, + 3;213,237,232;, + 3;224,238,237;, + 3;220,221,222;, + 3;220,143,221;, + 3;207,223,141;, + 3;223,207,227;, + 3;3485,225,3518;, + 3;3485,3519,234;, + 3;3520,231,3521;, + 3;231,3520,230;, + 3;3522,237,3523;, + 3;237,3522,232;, + 3;3524,230,3520;, + 3;230,3524,229;, + 3;224,3518,225;, + 3;3467,228,3525;, + 3;228,3467,112;, + 3;141,223,206;, + 3;226,206,223;, + 3;3526,227,207;, + 3;227,3526,233;, + 3;3525,229,3524;, + 3;229,3525,228;, + 3;206,109,86;, + 3;109,206,226;, + 3;3521,232,3522;, + 3;232,3521,231;, + 3;3527,233,3526;, + 3;233,3528,224;, + 3;3529,234,3519;, + 3;234,3529,235;, + 3;3530,235,3529;, + 3;235,3530,236;, + 3;3531,236,3530;, + 3;236,3531,238;, + 3;3523,238,3531;, + 3;238,3523,237;, + 3;187,239,155;, + 3;245,246,247;, + 3;242,157,241;, + 3;244,3506,243;, + 3;157,242,240;, + 3;159,155,241;, + 3;249,245,247;, + 3;245,249,248;, + 3;240,243,157;, + 3;243,183,157;, + 3;187,244,239;, + 3;246,251,247;, + 3;3532,250,3533;, + 3;250,3532,247;, + 3;3533,251,3534;, + 3;251,3533,250;, + 3;3535,245,3536;, + 3;245,3535,246;, + 3;3537,249,3538;, + 3;249,3537,248;, + 3;3538,247,3532;, + 3;247,3538,249;, + 3;3536,248,3537;, + 3;248,3536,245;, + 3;3534,246,3535;, + 3;246,3534,251;, + 3;255,472,550;, + 3;257,258,551;, + 3;252,467,554;, + 3;453,462,446;, + 3;439,447,448;, + 3;265,262,255;, + 3;462,463,460;, + 3;449,438,450;, + 3;439,443,447;, + 3;469,313,465;, + 3;254,289,466;, + 3;466,483,484;, + 3;260,435,432;, + 3;465,468,469;, + 3;260,473,474;, + 3;434,3539,3540;, + 3;259,465,474;, + 3;266,3541,262;, + 3;313,255,262;, + 3;438,449,445;, + 3;459,258,264;, + 3;265,266,262;, + 3;345,287,343;, + 3;486,485,271;, + 3;344,274,275;, + 3;335,534,535;, + 3;273,3542,340;, + 3;279,337,282;, + 3;393,333,269;, + 3;279,333,280;, + 3;3543,476,475;, + 3;397,400,417;, + 3;398,284,402;, + 3;388,284,405;, + 3;342,285,3544;, + 3;399,407,338;, + 3;394,392,3542;, + 3;480,479,285;, + 3;3542,392,342;, + 3;288,340,3542;, + 3;287,333,282;, + 3;344,334,274;, + 3;333,287,345;, + 3;343,275,270;, + 3;3544,285,552;, + 3;340,288,3544;, + 3;399,389,404;, + 3;290,295,296;, + 3;296,291,290;, + 3;291,296,297;, + 3;297,292,291;, + 3;292,297,298;, + 3;298,293,292;, + 3;309,310,299;, + 3;299,294,309;, + 3;300,301,424;, + 3;3545,422,3546;, + 3;301,302,424;, + 3;347,349,422;, + 3;305,423,306;, + 3;271,368,367;, + 3;3547,3548,301;, + 3;301,300,3547;, + 3;301,3549,426;, + 3;3549,301,3548;, + 3;358,426,359;, + 3;3550,359,426;, + 3;360,3551,364;, + 3;272,303,379;, + 3;374,276,277;, + 3;3552,3553,354;, + 3;3554,3555,306;, + 3;425,353,3553;, + 3;3555,3556,305;, + 3;305,306,3555;, + 3;305,3557,304;, + 3;3557,305,3556;, + 3;3558,3559,3546;, + 3;3546,3560,3558;, + 3;380,277,272;, + 3;294,299,308;, + 3;380,384,277;, + 3;3561,362,3550;, + 3;309,293,310;, + 3;310,293,298;, + 3;425,3553,3554;, + 3;518,517,330;, + 3;376,377,3562;, + 3;3543,477,476;, + 3;286,265,478;, + 3;487,277,488;, + 3;324,273,536;, + 3;313,470,255;, + 3;465,313,262;, + 3;502,501,314;, + 3;489,3562,490;, + 3;3563,491,317;, + 3;533,547,537;, + 3;318,492,493;, + 3;494,485,315;, + 3;330,503,504;, + 3;491,272,495;, + 3;495,487,319;, + 3;506,505,320;, + 3;488,277,496;, + 3;496,497,320;, + 3;519,312,520;, + 3;498,346,499;, + 3;499,489,316;, + 3;497,276,500;, + 3;500,3564,3565;, + 3;507,312,508;, + 3;510,509,319;, + 3;323,268,322;, + 3;512,511,3566;, + 3;466,3540,254;, + 3;550,478,255;, + 3;286,478,479;, + 3;410,387,411;, + 3;390,265,286;, + 3;332,289,254;, + 3;289,256,466;, + 3;281,256,289;, + 3;281,258,256;, + 3;279,548,391;, + 3;279,280,549;, + 3;549,280,261;, + 3;311,472,475;, + 3;3567,472,3568;, + 3;335,340,3544;, + 3;519,323,521;, + 3;513,511,325;, + 3;318,503,514;, + 3;3569,509,327;, + 3;515,505,328;, + 3;516,318,514;, + 3;506,3570,329;, + 3;504,501,330;, + 3;522,518,330;, + 3;267,538,539;, + 3;540,275,541;, + 3;526,278,527;, + 3;525,526,329;, + 3;507,321,515;, + 3;528,322,529;, + 3;521,528,331;, + 3;529,322,530;, + 3;502,513,325;, + 3;510,319,508;, + 3;531,328,527;, + 3;324,532,531;, + 3;325,3571,523;, + 3;420,400,418;, + 3;266,3572,3541;, + 3;279,282,333;, + 3;267,269,553;, + 3;414,409,416;, + 3;287,282,334;, + 3;536,544,336;, + 3;268,534,3573;, + 3;520,312,532;, + 3;548,281,391;, + 3;284,398,403;, + 3;410,416,409;, + 3;338,389,399;, + 3;288,341,3544;, + 3;3542,341,288;, + 3;273,340,543;, + 3;3542,339,341;, + 3;341,339,3544;, + 3;339,342,3544;, + 3;3542,342,339;, + 3;343,344,275;, + 3;267,343,270;, + 3;287,344,343;, + 3;287,334,344;, + 3;267,345,343;, + 3;553,345,267;, + 3;486,498,314;, + 3;347,3545,357;, + 3;271,367,346;, + 3;348,368,271;, + 3;493,348,494;, + 3;370,348,371;, + 3;350,3574,349;, + 3;422,3574,3560;, + 3;348,369,368;, + 3;3575,351,306;, + 3;369,348,370;, + 3;348,307,371;, + 3;306,425,3554;, + 3;351,352,306;, + 3;371,307,372;, + 3;354,3553,353;, + 3;384,374,277;, + 3;3576,276,375;, + 3;374,375,276;, + 3;346,376,3562;, + 3;367,376,346;, + 3;3577,302,358;, + 3;3550,426,3549;, + 3;359,3550,362;, + 3;3562,377,378;, + 3;385,373,3576;, + 3;3576,375,385;, + 3;355,3552,356;, + 3;3578,3552,355;, + 3;379,303,382;, + 3;3561,3551,360;, + 3;3551,361,364;, + 3;3551,3579,361;, + 3;378,381,3562;, + 3;3561,363,362;, + 3;360,363,3561;, + 3;383,380,272;, + 3;379,383,272;, + 3;361,3579,365;, + 3;3578,355,3580;, + 3;366,356,3552;, + 3;3552,354,366;, + 3;3581,3582,367;, + 3;367,368,3581;, + 3;3583,3584,378;, + 3;378,377,3583;, + 3;3585,3586,383;, + 3;383,379,3585;, + 3;3587,3588,371;, + 3;371,372,3587;, + 3;3589,3590,384;, + 3;384,380,3589;, + 3;3591,3583,377;, + 3;377,376,3591;, + 3;3582,3591,376;, + 3;376,367,3582;, + 3;3588,3592,370;, + 3;370,371,3588;, + 3;3593,3581,368;, + 3;368,369,3593;, + 3;3592,3593,369;, + 3;369,370,3592;, + 3;3590,3594,374;, + 3;374,384,3590;, + 3;3594,3595,375;, + 3;375,374,3594;, + 3;3584,3596,381;, + 3;381,378,3584;, + 3;3597,3598,373;, + 3;373,385,3597;, + 3;3595,3597,385;, + 3;385,375,3595;, + 3;3599,3585,379;, + 3;379,382,3599;, + 3;3586,3589,380;, + 3;380,383,3586;, + 3;338,386,389;, + 3;409,387,410;, + 3;418,400,401;, + 3;418,401,419;, + 3;409,412,387;, + 3;284,403,405;, + 3;419,401,413;, + 3;413,401,396;, + 3;415,413,396;, + 3;266,265,390;, + 3;405,408,388;, + 3;279,391,337;, + 3;395,479,480;, + 3;392,285,342;, + 3;393,280,333;, + 3;477,3543,3600;, + 3;338,407,406;, + 3;3601,274,334;, + 3;480,285,392;, + 3;395,392,394;, + 3;3602,3603,403;, + 3;403,398,3602;, + 3;3604,3605,400;, + 3;400,397,3604;, + 3;3606,3604,397;, + 3;397,408,3606;, + 3;3607,3602,398;, + 3;398,402,3607;, + 3;3603,3606,405;, + 3;405,403,3603;, + 3;3608,3609,399;, + 3;399,404,3608;, + 3;3605,3610,401;, + 3;401,400,3605;, + 3;3610,3611,396;, + 3;396,401,3610;, + 3;3612,3607,402;, + 3;402,406,3612;, + 3;3611,3608,404;, + 3;404,396,3611;, + 3;3609,3613,407;, + 3;407,399,3609;, + 3;3613,3612,406;, + 3;406,407,3613;, + 3;417,400,420;, + 3;408,405,3606;, + 3;397,417,408;, + 3;402,284,409;, + 3;409,414,402;, + 3;338,406,416;, + 3;416,410,338;, + 3;404,389,413;, + 3;413,415,404;, + 3;386,338,410;, + 3;410,411,386;, + 3;406,402,414;, + 3;414,416,406;, + 3;389,386,411;, + 3;411,413,389;, + 3;284,388,412;, + 3;412,409,284;, + 3;396,404,415;, + 3;388,408,417;, + 3;417,412,388;, + 3;411,387,418;, + 3;418,419,411;, + 3;387,412,420;, + 3;420,418,387;, + 3;413,411,419;, + 3;417,420,412;, + 3;258,421,264;, + 3;421,258,257;, + 3;3598,3576,373;, + 3;354,353,3614;, + 3;3587,372,307;, + 3;362,363,3615;, + 3;3599,382,303;, + 3;381,3596,3562;, + 3;422,349,3574;, + 3;422,3560,3546;, + 3;3575,306,423;, + 3;423,305,304;, + 3;424,302,3577;, + 3;422,3545,347;, + 3;306,352,425;, + 3;352,353,425;, + 3;358,302,426;, + 3;301,426,302;, + 3;444,443,442;, + 3;443,439,442;, + 3;454,457,455;, + 3;438,445,452;, + 3;432,431,464;, + 3;432,473,260;, + 3;263,433,434;, + 3;482,434,3540;, + 3;431,427,464;, + 3;464,427,556;, + 3;448,451,440;, + 3;448,440,439;, + 3;450,3616,3617;, + 3;438,3616,450;, + 3;429,433,263;, + 3;458,481,459;, + 3;452,445,3618;, + 3;454,456,457;, + 3;462,460,446;, + 3;428,3619,443;, + 3;443,444,428;, + 3;3620,3621,448;, + 3;448,447,3620;, + 3;3622,3623,449;, + 3;449,450,3622;, + 3;3619,3620,447;, + 3;447,443,3619;, + 3;3621,3624,451;, + 3;451,448,3621;, + 3;3625,3622,450;, + 3;450,3617,3625;, + 3;3623,3626,445;, + 3;445,449,3623;, + 3;3627,3628,442;, + 3;442,439,3627;, + 3;3629,3630,438;, + 3;438,452,3629;, + 3;3631,3627,439;, + 3;439,440,3631;, + 3;3630,3632,3616;, + 3;3616,438,3630;, + 3;3626,437,3618;, + 3;3618,445,3626;, + 3;3633,3634,3635;, + 3;3635,441,3633;, + 3;3636,3637,455;, + 3;455,457,3636;, + 3;3635,3636,457;, + 3;457,456,3635;, + 3;441,3635,456;, + 3;456,454,441;, + 3;429,458,3638;, + 3;429,481,458;, + 3;256,258,459;, + 3;463,461,460;, + 3;3638,458,462;, + 3;462,453,3638;, + 3;458,459,463;, + 3;463,462,458;, + 3;459,264,461;, + 3;461,463,459;, + 3;253,430,446;, + 3;446,460,253;, + 3;264,253,460;, + 3;3639,3640,3641;, + 3;556,427,554;, + 3;473,259,474;, + 3;3541,474,262;, + 3;259,468,465;, + 3;466,256,483;, + 3;3540,466,482;, + 3;259,467,468;, + 3;464,467,259;, + 3;467,252,468;, + 3;469,555,3568;, + 3;469,468,252;, + 3;470,313,469;, + 3;3568,470,469;, + 3;470,3568,471;, + 3;472,255,471;, + 3;470,471,255;, + 3;3568,472,471;, + 3;311,283,472;, + 3;432,464,473;, + 3;464,259,473;, + 3;474,465,262;, + 3;260,474,3541;, + 3;475,472,3567;, + 3;3543,475,3567;, + 3;476,477,311;, + 3;476,311,475;, + 3;3544,552,3600;, + 3;477,285,311;, + 3;265,255,478;, + 3;478,283,311;, + 3;479,478,311;, + 3;479,311,285;, + 3;395,480,392;, + 3;286,479,395;, + 3;429,263,481;, + 3;481,263,484;, + 3;482,466,484;, + 3;263,434,482;, + 3;483,256,459;, + 3;483,459,484;, + 3;484,459,481;, + 3;482,484,263;, + 3;486,315,485;, + 3;314,315,486;, + 3;319,487,488;, + 3;319,488,321;, + 3;316,489,490;, + 3;316,490,3566;, + 3;3563,272,491;, + 3;303,272,3563;, + 3;493,492,348;, + 3;492,307,348;, + 3;494,271,485;, + 3;348,271,494;, + 3;317,491,495;, + 3;317,495,319;, + 3;495,277,487;, + 3;272,277,495;, + 3;321,488,496;, + 3;321,496,320;, + 3;496,276,497;, + 3;277,276,496;, + 3;314,498,499;, + 3;314,499,316;, + 3;499,3562,489;, + 3;346,3562,499;, + 3;320,497,500;, + 3;320,500,3565;, + 3;500,3576,3564;, + 3;276,3576,500;, + 3;486,346,498;, + 3;271,346,486;, + 3;318,493,494;, + 3;318,494,315;, + 3;502,325,501;, + 3;325,545,501;, + 3;504,503,315;, + 3;503,318,315;, + 3;506,328,505;, + 3;329,328,506;, + 3;321,507,508;, + 3;321,508,319;, + 3;510,331,509;, + 3;331,327,509;, + 3;512,325,511;, + 3;3642,325,512;, + 3;513,3566,511;, + 3;316,3566,513;, + 3;514,503,326;, + 3;503,330,326;, + 3;3569,319,509;, + 3;317,319,3569;, + 3;515,320,505;, + 3;321,320,515;, + 3;3643,516,514;, + 3;3643,514,326;, + 3;506,3565,3570;, + 3;320,3565,506;, + 3;504,314,501;, + 3;315,314,504;, + 3;312,507,515;, + 3;312,515,328;, + 3;502,316,513;, + 3;314,316,502;, + 3;331,510,508;, + 3;331,508,312;, + 3;542,540,517;, + 3;336,519,520;, + 3;323,519,336;, + 3;331,519,521;, + 3;312,519,331;, + 3;538,542,522;, + 3;523,522,325;, + 3;522,545,325;, + 3;326,517,524;, + 3;330,517,326;, + 3;524,3644,326;, + 3;3644,3643,326;, + 3;329,526,527;, + 3;329,527,328;, + 3;525,278,526;, + 3;275,3645,541;, + 3;327,528,529;, + 3;331,528,327;, + 3;521,323,528;, + 3;323,322,528;, + 3;327,529,530;, + 3;3642,3571,325;, + 3;324,531,527;, + 3;324,527,278;, + 3;531,532,328;, + 3;532,312,328;, + 3;539,537,267;, + 3;336,520,532;, + 3;336,532,324;, + 3;267,537,547;, + 3;535,534,323;, + 3;534,268,323;, + 3;546,275,274;, + 3;278,273,324;, + 3;3646,533,537;, + 3;3646,537,3647;, + 3;536,336,324;, + 3;539,538,523;, + 3;538,522,523;, + 3;517,540,541;, + 3;517,541,524;, + 3;541,3644,524;, + 3;536,543,544;, + 3;273,543,536;, + 3;3573,534,335;, + 3;3573,335,3648;, + 3;535,323,336;, + 3;3542,273,3649;, + 3;518,542,517;, + 3;542,275,540;, + 3;270,275,542;, + 3;522,542,518;, + 3;538,267,542;, + 3;267,270,542;, + 3;541,3645,3644;, + 3;539,523,537;, + 3;523,3571,537;, + 3;3571,3647,537;, + 3;543,340,335;, + 3;543,335,535;, + 3;544,543,535;, + 3;544,535,336;, + 3;522,330,545;, + 3;545,330,501;, + 3;3649,273,278;, + 3;3645,275,546;, + 3;3648,335,3544;, + 3;547,269,267;, + 3;279,258,548;, + 3;258,281,548;, + 3;258,549,551;, + 3;279,549,258;, + 3;550,472,283;, + 3;283,478,550;, + 3;551,549,261;, + 3;257,551,261;, + 3;552,285,477;, + 3;552,477,3600;, + 3;553,269,333;, + 3;333,345,553;, + 3;554,427,3650;, + 3;469,252,555;, + 3;467,556,554;, + 3;464,556,467;, + 3;558,840,762;, + 3;257,841,560;, + 3;252,554,757;, + 3;747,446,752;, + 3;737,742,741;, + 3;566,558,564;, + 3;752,460,753;, + 3;743,744,736;, + 3;737,741,739;, + 3;759,755,614;, + 3;557,756,590;, + 3;756,774,773;, + 3;562,730,733;, + 3;755,759,758;, + 3;562,764,763;, + 3;732,3651,3652;, + 3;561,764,755;, + 3;567,564,3653;, + 3;614,564,558;, + 3;736,740,743;, + 3;751,264,560;, + 3;566,564,567;, + 3;646,644,588;, + 3;776,572,775;, + 3;645,576,575;, + 3;636,825,824;, + 3;574,641,3654;, + 3;580,583,638;, + 3;694,570,634;, + 3;580,581,634;, + 3;3655,765,766;, + 3;698,718,701;, + 3;699,703,585;, + 3;689,706,585;, + 3;643,3656,586;, + 3;700,639,708;, + 3;695,3654,693;, + 3;770,586,769;, + 3;3654,643,693;, + 3;589,3654,641;, + 3;588,583,634;, + 3;645,575,635;, + 3;634,646,588;, + 3;644,571,576;, + 3;3656,842,586;, + 3;641,3656,589;, + 3;700,705,690;, + 3;591,597,596;, + 3;597,591,592;, + 3;592,598,597;, + 3;598,592,593;, + 3;593,599,598;, + 3;599,593,594;, + 3;610,600,611;, + 3;600,610,595;, + 3;601,724,602;, + 3;3657,3658,722;, + 3;602,724,603;, + 3;648,722,650;, + 3;606,607,723;, + 3;572,668,669;, + 3;3659,602,3660;, + 3;602,3659,601;, + 3;602,726,3661;, + 3;3661,3660,602;, + 3;659,660,726;, + 3;3662,726,660;, + 3;661,665,3663;, + 3;573,680,604;, + 3;675,578,577;, + 3;3664,655,3665;, + 3;3666,607,3667;, + 3;725,3665,654;, + 3;3667,606,3668;, + 3;606,3667,607;, + 3;606,605,3669;, + 3;3669,3668,606;, + 3;3670,3658,3671;, + 3;3658,3670,3672;, + 3;681,573,578;, + 3;595,609,600;, + 3;681,578,685;, + 3;3673,3662,663;, + 3;610,611,594;, + 3;611,599,594;, + 3;725,3666,3665;, + 3;808,631,807;, + 3;677,3674,678;, + 3;3655,766,767;, + 3;587,768,566;, + 3;777,778,578;, + 3;625,826,574;, + 3;614,558,760;, + 3;755,564,614;, + 3;792,615,791;, + 3;779,780,3674;, + 3;3675,618,781;, + 3;823,827,837;, + 3;619,783,782;, + 3;784,616,775;, + 3;631,794,793;, + 3;781,785,573;, + 3;785,620,777;, + 3;796,621,795;, + 3;778,786,578;, + 3;786,621,787;, + 3;809,810,613;, + 3;788,789,647;, + 3;789,617,779;, + 3;787,790,577;, + 3;790,3676,3677;, + 3;797,798,613;, + 3;800,620,799;, + 3;624,623,569;, + 3;802,3678,801;, + 3;756,557,3651;, + 3;840,558,768;, + 3;587,769,768;, + 3;711,712,688;, + 3;691,587,566;, + 3;633,557,590;, + 3;590,756,559;, + 3;582,590,559;, + 3;582,559,560;, + 3;580,692,838;, + 3;580,839,581;, + 3;839,563,581;, + 3;612,765,762;, + 3;3679,3568,762;, + 3;636,3656,641;, + 3;809,811,624;, + 3;803,626,801;, + 3;619,804,793;, + 3;3680,628,799;, + 3;805,629,795;, + 3;806,804,619;, + 3;796,630,3681;, + 3;794,631,791;, + 3;812,631,808;, + 3;568,829,828;, + 3;830,831,576;, + 3;816,817,579;, + 3;815,630,816;, + 3;797,805,622;, + 3;818,819,623;, + 3;811,632,818;, + 3;819,820,623;, + 3;792,626,803;, + 3;800,798,620;, + 3;821,817,629;, + 3;625,821,822;, + 3;626,813,3682;, + 3;721,719,701;, + 3;567,3653,3683;, + 3;580,634,583;, + 3;568,843,570;, + 3;715,717,710;, + 3;588,635,583;, + 3;826,637,834;, + 3;569,3684,824;, + 3;810,822,613;, + 3;838,692,582;, + 3;585,704,699;, + 3;711,710,717;, + 3;639,700,690;, + 3;589,3656,642;, + 3;3654,589,642;, + 3;574,833,641;, + 3;3654,642,640;, + 3;642,3656,640;, + 3;640,3656,643;, + 3;3654,640,643;, + 3;644,576,645;, + 3;568,571,644;, + 3;588,644,645;, + 3;588,645,635;, + 3;568,644,646;, + 3;843,568,646;, + 3;776,615,788;, + 3;724,658,603;, + 3;572,647,668;, + 3;649,572,669;, + 3;783,784,649;, + 3;671,672,649;, + 3;651,650,3685;, + 3;722,3672,3685;, + 3;649,669,670;, + 3;3686,607,652;, + 3;670,671,649;, + 3;649,672,608;, + 3;607,3666,725;, + 3;652,607,653;, + 3;672,673,608;, + 3;655,654,3665;, + 3;685,578,675;, + 3;3687,676,577;, + 3;675,577,676;, + 3;647,3674,677;, + 3;668,647,677;, + 3;658,659,603;, + 3;3662,3661,726;, + 3;660,663,3662;, + 3;3674,679,678;, + 3;686,3687,674;, + 3;3687,686,676;, + 3;656,657,3664;, + 3;3688,656,3664;, + 3;680,683,604;, + 3;3673,661,3663;, + 3;3663,665,662;, + 3;3663,662,3689;, + 3;679,3674,682;, + 3;3673,663,664;, + 3;661,3673,664;, + 3;684,573,681;, + 3;680,573,684;, + 3;662,666,3689;, + 3;3688,3690,656;, + 3;667,3664,657;, + 3;3664,667,655;, + 3;3691,668,3692;, + 3;668,3691,669;, + 3;3693,679,3694;, + 3;679,3693,678;, + 3;3695,684,3696;, + 3;684,3695,680;, + 3;3697,672,3698;, + 3;672,3697,673;, + 3;3699,685,3700;, + 3;685,3699,681;, + 3;3701,678,3693;, + 3;678,3701,677;, + 3;3692,677,3701;, + 3;677,3692,668;, + 3;3698,671,3702;, + 3;671,3698,672;, + 3;3703,669,3691;, + 3;669,3703,670;, + 3;3702,670,3703;, + 3;670,3702,671;, + 3;3700,675,3704;, + 3;675,3700,685;, + 3;3704,676,3705;, + 3;676,3704,675;, + 3;3694,682,3706;, + 3;682,3694,679;, + 3;3707,674,3708;, + 3;674,3707,686;, + 3;3705,686,3707;, + 3;686,3705,676;, + 3;3709,680,3695;, + 3;680,3709,683;, + 3;3696,681,3699;, + 3;681,3696,684;, + 3;639,690,687;, + 3;710,711,688;, + 3;719,702,701;, + 3;719,720,702;, + 3;710,688,713;, + 3;585,706,704;, + 3;720,714,702;, + 3;714,697,702;, + 3;716,697,714;, + 3;567,691,566;, + 3;706,689,709;, + 3;580,638,692;, + 3;696,770,769;, + 3;693,643,586;, + 3;694,634,581;, + 3;767,3710,3655;, + 3;639,707,708;, + 3;3711,635,575;, + 3;770,693,586;, + 3;696,695,693;, + 3;3712,704,3713;, + 3;704,3712,699;, + 3;3714,701,3715;, + 3;701,3714,698;, + 3;3716,698,3714;, + 3;698,3716,709;, + 3;3717,699,3712;, + 3;699,3717,703;, + 3;3713,706,3716;, + 3;706,3713,704;, + 3;3718,700,3719;, + 3;700,3718,705;, + 3;3715,702,3720;, + 3;702,3715,701;, + 3;3720,697,3721;, + 3;697,3720,702;, + 3;3722,703,3717;, + 3;703,3722,707;, + 3;3721,705,3718;, + 3;705,3721,697;, + 3;3719,708,3723;, + 3;708,3719,700;, + 3;3723,707,3722;, + 3;707,3723,708;, + 3;718,721,701;, + 3;709,3716,706;, + 3;698,709,718;, + 3;703,710,585;, + 3;710,703,715;, + 3;639,717,707;, + 3;717,639,711;, + 3;705,714,690;, + 3;714,705,716;, + 3;687,711,639;, + 3;711,687,712;, + 3;707,715,703;, + 3;715,707,717;, + 3;690,712,687;, + 3;712,690,714;, + 3;585,713,689;, + 3;713,585,710;, + 3;697,716,705;, + 3;689,718,709;, + 3;718,689,713;, + 3;712,719,688;, + 3;719,712,720;, + 3;688,721,713;, + 3;721,688,719;, + 3;714,720,712;, + 3;718,713,721;, + 3;560,264,421;, + 3;421,257,560;, + 3;3708,674,3687;, + 3;655,3724,654;, + 3;3697,608,673;, + 3;663,3725,664;, + 3;3709,604,683;, + 3;682,3674,3706;, + 3;722,3685,650;, + 3;722,3658,3672;, + 3;3686,723,607;, + 3;723,605,606;, + 3;3657,648,3726;, + 3;722,648,3657;, + 3;607,725,653;, + 3;653,725,654;, + 3;659,726,603;, + 3;602,603,726;, + 3;444,442,739;, + 3;739,442,737;, + 3;454,455,749;, + 3;736,746,740;, + 3;730,754,729;, + 3;730,562,763;, + 3;565,732,731;, + 3;772,3651,732;, + 3;729,754,727;, + 3;754,844,727;, + 3;742,738,745;, + 3;742,737,738;, + 3;744,3727,3728;, + 3;736,744,3728;, + 3;728,565,731;, + 3;750,751,771;, + 3;746,3729,740;, + 3;454,749,748;, + 3;752,446,460;, + 3;428,739,3730;, + 3;739,428,444;, + 3;3731,742,3732;, + 3;742,3731,741;, + 3;3733,743,3734;, + 3;743,3733,744;, + 3;3730,741,3731;, + 3;741,3730,739;, + 3;3732,745,3735;, + 3;745,3732,742;, + 3;3736,744,3733;, + 3;744,3736,3727;, + 3;3734,740,3737;, + 3;740,3734,743;, + 3;3738,442,3628;, + 3;442,3738,737;, + 3;3739,736,3740;, + 3;736,3739,746;, + 3;3741,737,3738;, + 3;737,3741,738;, + 3;3740,3728,3742;, + 3;3728,3740,736;, + 3;3737,3729,735;, + 3;3729,3737,740;, + 3;3633,3743,3744;, + 3;3743,3633,441;, + 3;3745,455,3637;, + 3;455,3745,749;, + 3;3743,749,3745;, + 3;749,3743,748;, + 3;441,748,3743;, + 3;748,441,454;, + 3;728,3746,750;, + 3;728,750,771;, + 3;559,751,560;, + 3;753,460,461;, + 3;3746,752,750;, + 3;752,3746,747;, + 3;750,753,751;, + 3;753,750,752;, + 3;751,461,264;, + 3;461,751,753;, + 3;253,446,430;, + 3;446,253,460;, + 3;264,460,253;, + 3;460,264,461;, + 3;844,554,727;, + 3;763,764,561;, + 3;3653,564,764;, + 3;561,755,758;, + 3;756,773,559;, + 3;3651,772,756;, + 3;561,758,757;, + 3;754,561,757;, + 3;757,758,252;, + 3;759,3568,555;, + 3;759,252,758;, + 3;760,759,614;, + 3;3568,759,760;, + 3;760,761,3568;, + 3;762,761,558;, + 3;760,558,761;, + 3;3568,761,762;, + 3;612,762,584;, + 3;730,763,754;, + 3;754,763,561;, + 3;764,564,755;, + 3;562,3653,764;, + 3;765,3679,762;, + 3;3655,3679,765;, + 3;766,612,767;, + 3;766,765,612;, + 3;3656,3710,842;, + 3;767,612,586;, + 3;566,768,558;, + 3;768,612,584;, + 3;769,612,768;, + 3;769,586,612;, + 3;696,693,770;, + 3;587,696,769;, + 3;728,771,565;, + 3;771,774,565;, + 3;772,774,756;, + 3;565,772,732;, + 3;773,751,559;, + 3;773,774,751;, + 3;774,771,751;, + 3;772,565,774;, + 3;776,775,616;, + 3;615,776,616;, + 3;620,778,777;, + 3;620,622,778;, + 3;617,780,779;, + 3;617,3678,780;, + 3;3675,781,573;, + 3;604,3675,573;, + 3;783,649,782;, + 3;782,649,608;, + 3;784,775,572;, + 3;649,784,572;, + 3;618,785,781;, + 3;618,620,785;, + 3;785,777,578;, + 3;573,785,578;, + 3;622,786,778;, + 3;622,621,786;, + 3;786,787,577;, + 3;578,786,577;, + 3;615,789,788;, + 3;615,617,789;, + 3;789,779,3674;, + 3;647,789,3674;, + 3;621,790,787;, + 3;621,3676,790;, + 3;790,3677,3687;, + 3;577,790,3687;, + 3;776,788,647;, + 3;572,776,647;, + 3;619,784,783;, + 3;619,616,784;, + 3;792,791,626;, + 3;626,791,835;, + 3;794,616,793;, + 3;793,616,619;, + 3;796,795,629;, + 3;630,796,629;, + 3;622,798,797;, + 3;622,620,798;, + 3;800,799,632;, + 3;632,799,628;, + 3;802,801,626;, + 3;3747,802,626;, + 3;803,801,3678;, + 3;617,803,3678;, + 3;804,627,793;, + 3;793,627,631;, + 3;3680,799,620;, + 3;618,3680,620;, + 3;805,795,621;, + 3;622,805,621;, + 3;3748,804,806;, + 3;3748,627,804;, + 3;796,3681,3676;, + 3;621,796,3676;, + 3;794,791,615;, + 3;616,794,615;, + 3;613,805,797;, + 3;613,629,805;, + 3;792,803,617;, + 3;615,792,617;, + 3;632,798,800;, + 3;632,613,798;, + 3;832,807,830;, + 3;637,810,809;, + 3;624,637,809;, + 3;632,811,809;, + 3;613,632,809;, + 3;828,812,832;, + 3;813,626,812;, + 3;812,626,835;, + 3;627,814,807;, + 3;631,627,807;, + 3;814,627,3749;, + 3;3749,627,3748;, + 3;630,817,816;, + 3;630,629,817;, + 3;815,816,579;, + 3;576,831,3750;, + 3;628,819,818;, + 3;632,628,818;, + 3;811,818,624;, + 3;624,818,623;, + 3;628,820,819;, + 3;3747,626,3682;, + 3;625,817,821;, + 3;625,579,817;, + 3;821,629,822;, + 3;822,629,613;, + 3;829,568,827;, + 3;637,822,810;, + 3;637,625,822;, + 3;568,837,827;, + 3;825,624,824;, + 3;824,624,569;, + 3;836,575,576;, + 3;579,625,574;, + 3;3751,827,823;, + 3;3751,3752,827;, + 3;826,625,637;, + 3;829,813,828;, + 3;828,813,812;, + 3;807,831,830;, + 3;807,814,831;, + 3;831,814,3749;, + 3;826,834,833;, + 3;574,826,833;, + 3;3684,636,824;, + 3;3684,3753,636;, + 3;825,637,624;, + 3;3654,3754,574;, + 3;808,807,832;, + 3;832,830,576;, + 3;571,832,576;, + 3;812,808,832;, + 3;828,832,568;, + 3;568,832,571;, + 3;831,3749,3750;, + 3;829,827,813;, + 3;813,827,3682;, + 3;3682,827,3752;, + 3;833,636,641;, + 3;833,825,636;, + 3;834,825,833;, + 3;834,637,825;, + 3;812,835,631;, + 3;835,791,631;, + 3;3754,579,574;, + 3;3750,836,576;, + 3;3753,3656,636;, + 3;837,568,570;, + 3;580,838,560;, + 3;560,838,582;, + 3;560,841,839;, + 3;580,560,839;, + 3;840,584,762;, + 3;584,840,768;, + 3;841,563,839;, + 3;257,563,841;, + 3;842,767,586;, + 3;842,3710,767;, + 3;843,634,570;, + 3;634,843,646;, + 3;554,3650,727;, + 3;759,555,252;, + 3;757,554,844;, + 3;754,757,844;, + 3;845,99,21;, + 3;3755,846,216;, + 3;180,734,167;, + 3;180,57,734;, + 3;46,57,436;, + 3;436,56,40;, + 3;203,3491,847;, + 3;168,847,3491;, + 3;82,37,848;, + 3;41,848,37;, + 3;849,1291,850;, + 3;943,852,851;, + 3;849,1290,944;, + 3;1289,854,1293;, + 3;854,1289,944;, + 3;859,888,945;, + 3;855,861,887;, + 3;946,856,3756;, + 3;1292,3757,3758;, + 3;3757,3759,3760;, + 3;852,946,851;, + 3;857,889,849;, + 3;858,857,850;, + 3;850,857,849;, + 3;853,860,1290;, + 3;3761,861,3758;, + 3;3758,861,855;, + 3;887,859,945;, + 3;875,891,890;, + 3;893,892,862;, + 3;894,869,895;, + 3;897,896,863;, + 3;898,876,899;, + 3;900,862,892;, + 3;902,901,874;, + 3;898,877,903;, + 3;868,904,890;, + 3;894,864,905;, + 3;905,864,904;, + 3;896,872,895;, + 3;867,902,906;, + 3;3762,3763,891;, + 3;899,906,865;, + 3;903,3764,3765;, + 3;901,900,874;, + 3;3763,880,868;, + 3;880,3763,879;, + 3;867,882,878;, + 3;882,867,881;, + 3;3765,884,876;, + 3;884,3765,883;, + 3;866,886,869;, + 3;886,866,885;, + 3;868,880,866;, + 3;885,866,880;, + 3;869,3766,863;, + 3;3766,869,886;, + 3;876,881,867;, + 3;881,876,884;, + 3;878,3767,862;, + 3;3767,878,882;, + 3;870,3768,871;, + 3;3768,870,3769;, + 3;872,3770,864;, + 3;3770,872,3771;, + 3;873,3771,872;, + 3;3771,873,3772;, + 3;865,3773,877;, + 3;3773,865,3774;, + 3;871,3775,874;, + 3;3775,871,3768;, + 3;864,3776,875;, + 3;3776,864,3770;, + 3;874,3774,865;, + 3;3774,874,3775;, + 3;875,3777,3778;, + 3;3777,875,3776;, + 3;877,3779,3780;, + 3;3779,877,3773;, + 3;890,891,868;, + 3;868,891,3763;, + 3;892,893,871;, + 3;871,893,870;, + 3;894,895,864;, + 3;864,895,872;, + 3;896,897,872;, + 3;872,897,873;, + 3;898,899,877;, + 3;877,899,865;, + 3;900,892,874;, + 3;874,892,871;, + 3;901,902,878;, + 3;878,902,867;, + 3;898,903,876;, + 3;876,903,3765;, + 3;890,904,875;, + 3;875,904,864;, + 3;894,905,869;, + 3;869,905,866;, + 3;905,904,866;, + 3;866,904,868;, + 3;896,895,863;, + 3;863,895,869;, + 3;906,902,865;, + 3;865,902,874;, + 3;3762,891,3778;, + 3;3778,891,875;, + 3;906,899,867;, + 3;867,899,876;, + 3;3764,903,3780;, + 3;3780,903,877;, + 3;900,901,862;, + 3;862,901,878;, + 3;889,1290,849;, + 3;3781,858,850;, + 3;855,887,945;, + 3;921,939,908;, + 3;942,922,3782;, + 3;923,910,924;, + 3;907,926,925;, + 3;926,927,911;, + 3;929,928,915;, + 3;3783,919,913;, + 3;931,930,913;, + 3;941,920,908;, + 3;931,932,3784;, + 3;929,933,908;, + 3;916,918,3785;, + 3;917,3786,913;, + 3;935,934,914;, + 3;916,935,936;, + 3;937,3787,938;, + 3;3788,3785,918;, + 3;3789,909,919;, + 3;912,3790,3791;, + 3;916,3786,917;, + 3;934,930,914;, + 3;918,3792,3788;, + 3;936,3787,937;, + 3;3783,913,3786;, + 3;932,3793,3784;, + 3;928,3794,915;, + 3;940,908,939;, + 3;907,942,940;, + 3;927,933,911;, + 3;922,3795,3782;, + 3;925,910,923;, + 3;923,924,922;, + 3;922,924,3795;, + 3;925,926,910;, + 3;910,926,911;, + 3;927,926,921;, + 3;921,926,907;, + 3;928,929,920;, + 3;920,929,908;, + 3;930,931,914;, + 3;914,931,3784;, + 3;932,931,919;, + 3;919,931,913;, + 3;933,929,911;, + 3;911,929,915;, + 3;934,935,917;, + 3;917,935,916;, + 3;936,935,3787;, + 3;3787,935,914;, + 3;937,938,918;, + 3;918,938,3792;, + 3;930,934,913;, + 3;913,934,917;, + 3;936,937,916;, + 3;916,937,918;, + 3;3793,932,909;, + 3;909,932,919;, + 3;3794,928,912;, + 3;912,928,920;, + 3;933,927,908;, + 3;908,927,921;, + 3;925,923,907;, + 3;907,923,922;, + 3;912,920,3790;, + 3;3782,3795,3796;, + 3;940,3782,3797;, + 3;941,940,3790;, + 3;907,939,921;, + 3;939,907,940;, + 3;940,3797,3790;, + 3;3790,920,941;, + 3;908,940,941;, + 3;907,922,942;, + 3;942,3782,940;, + 3;3789,919,3783;, + 3;3785,3786,916;, + 3;1289,852,943;, + 3;849,944,1289;, + 3;854,944,1290;, + 3;3798,3781,850;, + 3;3799,3800,851;, + 3;852,856,946;, + 3;946,3801,3799;, + 3;1271,947,3802;, + 3;3802,3803,1271;, + 3;3804,949,3805;, + 3;1273,3804,3806;, + 3;3807,948,3803;, + 3;948,3807,1272;, + 3;1274,950,3808;, + 3;1274,3805,949;, + 3;1275,1276,1274;, + 3;1278,952,1277;, + 3;1279,1280,954;, + 3;1282,951,1281;, + 3;1283,1284,1273;, + 3;1283,3809,3810;, + 3;1008,1270,956;, + 3;955,3811,3812;, + 3;981,957,1267;, + 3;970,1009,973;, + 3;3813,959,953;, + 3;1268,963,988;, + 3;3814,1263,3815;, + 3;959,3813,982;, + 3;973,958,970;, + 3;959,984,953;, + 3;3816,962,957;, + 3;1011,955,974;, + 3;984,3817,953;, + 3;984,965,3817;, + 3;991,961,964;, + 3;1263,963,1012;, + 3;963,3814,3818;, + 3;989,990,964;, + 3;3819,3820,966;, + 3;991,967,992;, + 3;992,965,991;, + 3;3818,966,963;, + 3;966,3818,968;, + 3;961,986,964;, + 3;964,986,3821;, + 3;976,974,1008;, + 3;1009,956,973;, + 3;969,1008,971;, + 3;975,974,972;, + 3;1263,1012,973;, + 3;1270,1263,956;, + 3;955,3815,1270;, + 3;969,976,1008;, + 3;1011,974,975;, + 3;1010,974,976;, + 3;3816,981,982;, + 3;980,1267,957;, + 3;959,982,981;, + 3;3816,982,3813;, + 3;961,991,984;, + 3;959,983,984;, + 3;983,961,984;, + 3;1012,963,985;, + 3;963,1268,985;, + 3;983,986,961;, + 3;983,987,986;, + 3;3820,988,963;, + 3;963,966,3820;, + 3;964,3821,989;, + 3;967,964,990;, + 3;965,984,991;, + 3;964,967,991;, + 3;965,992,3822;, + 3;992,995,3822;, + 3;995,992,994;, + 3;966,993,3819;, + 3;993,966,996;, + 3;967,994,992;, + 3;994,967,997;, + 3;968,996,966;, + 3;996,968,3823;, + 3;990,997,967;, + 3;997,990,3824;, + 3;994,1000,995;, + 3;1000,994,999;, + 3;996,998,993;, + 3;998,996,1001;, + 3;3823,1001,996;, + 3;1001,3823,3825;, + 3;3826,1002,3827;, + 3;3828,3824,3829;, + 3;997,999,994;, + 3;999,997,3828;, + 3;999,1005,1000;, + 3;1005,999,1004;, + 3;1001,1003,998;, + 3;1003,1001,1006;, + 3;3825,1006,1001;, + 3;1006,3825,3830;, + 3;3829,1007,3828;, + 3;1007,3829,3831;, + 3;3828,1004,999;, + 3;1004,3828,1007;, + 3;1007,1005,1004;, + 3;3830,1003,1006;, + 3;3831,1005,1007;, + 3;974,955,1270;, + 3;971,1008,956;, + 3;971,956,1009;, + 3;972,974,1010;, + 3;3832,955,1011;, + 3;958,973,1012;, + 3;1016,1015,970;, + 3;958,1016,970;, + 3;1017,1016,958;, + 3;1012,1017,958;, + 3;1018,1017,1012;, + 3;985,1018,1012;, + 3;1019,3833,3834;, + 3;960,1019,3834;, + 3;1020,1019,960;, + 3;979,1020,960;, + 3;3835,1020,979;, + 3;3836,3835,979;, + 3;1022,1021,1015;, + 3;1016,1022,1015;, + 3;1023,1022,1016;, + 3;1017,1023,1016;, + 3;1024,1023,1017;, + 3;1018,1024,1017;, + 3;1025,3837,3833;, + 3;1019,1025,3833;, + 3;1026,1025,1019;, + 3;1020,1026,1019;, + 3;3838,1026,1020;, + 3;3835,3838,1020;, + 3;1028,1027,1021;, + 3;1022,1028,1021;, + 3;1029,1028,1022;, + 3;1023,1029,1022;, + 3;1030,1029,1023;, + 3;1024,1030,1023;, + 3;1031,3839,3837;, + 3;1025,1031,3837;, + 3;1032,1031,1025;, + 3;1026,1032,1025;, + 3;3840,1032,1026;, + 3;3838,3840,1026;, + 3;1034,1033,1027;, + 3;1028,1034,1027;, + 3;1035,1034,1028;, + 3;1029,1035,1028;, + 3;1036,1035,1029;, + 3;1030,1036,1029;, + 3;1037,3841,3839;, + 3;1031,1037,3839;, + 3;1038,1037,1031;, + 3;1032,1038,1031;, + 3;3842,1038,1032;, + 3;3840,3842,1032;, + 3;1040,1039,1033;, + 3;1034,1040,1033;, + 3;1041,1040,1034;, + 3;1035,1041,1034;, + 3;1042,1041,1035;, + 3;1036,1042,1035;, + 3;1043,3843,3841;, + 3;1037,1043,3841;, + 3;1044,1043,1037;, + 3;1038,1044,1037;, + 3;3844,1044,1038;, + 3;3842,3844,1038;, + 3;1046,1045,1039;, + 3;1040,1046,1039;, + 3;1047,1046,1040;, + 3;1041,1047,1040;, + 3;1048,1047,1041;, + 3;1042,1048,1041;, + 3;1049,3845,3843;, + 3;1043,1049,3843;, + 3;1050,1049,1043;, + 3;1044,1050,1043;, + 3;3846,1050,1044;, + 3;3844,3846,1044;, + 3;1052,1051,1045;, + 3;1046,1052,1045;, + 3;1053,1052,1046;, + 3;1047,1053,1046;, + 3;1054,1053,1047;, + 3;1048,1054,1047;, + 3;1055,3847,3845;, + 3;1049,1055,3845;, + 3;1056,1055,1049;, + 3;1050,1056,1049;, + 3;3848,1056,1050;, + 3;3846,3848,1050;, + 3;1058,1057,1051;, + 3;1052,1058,1051;, + 3;1059,1058,1052;, + 3;1053,1059,1052;, + 3;1060,1059,1053;, + 3;1054,1060,1053;, + 3;1061,3849,3847;, + 3;1055,1061,3847;, + 3;1062,1061,1055;, + 3;1056,1062,1055;, + 3;3850,1062,1056;, + 3;3848,3850,1056;, + 3;1064,1063,1057;, + 3;1058,1064,1057;, + 3;1065,1064,1058;, + 3;1059,1065,1058;, + 3;1066,1065,1059;, + 3;1060,1066,1059;, + 3;1067,3851,3849;, + 3;1061,1067,3849;, + 3;1068,1067,1061;, + 3;1062,1068,1061;, + 3;3852,1068,1062;, + 3;3850,3852,1062;, + 3;1070,1069,1063;, + 3;1064,1070,1063;, + 3;1071,1070,1064;, + 3;1065,1071,1064;, + 3;1072,1071,1065;, + 3;1066,1072,1065;, + 3;1073,3853,3851;, + 3;1067,1073,3851;, + 3;1074,1073,1067;, + 3;1068,1074,1067;, + 3;3854,1074,1068;, + 3;3852,3854,1068;, + 3;1070,1075,1069;, + 3;1071,1076,1070;, + 3;1075,1070,1076;, + 3;1072,1076,1071;, + 3;1073,3855,3853;, + 3;1074,3856,1073;, + 3;3855,1073,3856;, + 3;3854,3856,1074;, + 3;1078,1077,969;, + 3;971,1078,969;, + 3;1079,1078,971;, + 3;1009,1079,971;, + 3;1080,1079,1009;, + 3;970,1080,1009;, + 3;1081,3857,3836;, + 3;978,1081,3836;, + 3;1082,1081,978;, + 3;1013,1082,978;, + 3;3858,1082,1013;, + 3;3859,3858,1013;, + 3;1084,1083,1077;, + 3;1078,1084,1077;, + 3;1085,1084,1078;, + 3;1079,1085,1078;, + 3;1086,1085,1079;, + 3;1080,1086,1079;, + 3;1087,3860,3857;, + 3;1081,1087,3857;, + 3;1088,1087,1081;, + 3;1082,1088,1081;, + 3;3861,1088,1082;, + 3;3858,3861,1082;, + 3;1090,1089,1083;, + 3;1084,1090,1083;, + 3;1091,1090,1084;, + 3;1085,1091,1084;, + 3;1092,1091,1085;, + 3;1086,1092,1085;, + 3;1093,3862,3860;, + 3;1087,1093,3860;, + 3;1094,1093,1087;, + 3;1088,1094,1087;, + 3;3863,1094,1088;, + 3;3861,3863,1088;, + 3;1096,1095,1089;, + 3;1090,1096,1089;, + 3;1097,1096,1090;, + 3;1091,1097,1090;, + 3;1098,1097,1091;, + 3;1092,1098,1091;, + 3;1099,3864,3862;, + 3;1093,1099,3862;, + 3;1100,1099,1093;, + 3;1094,1100,1093;, + 3;3865,1100,1094;, + 3;3863,3865,1094;, + 3;1102,1101,1095;, + 3;1096,1102,1095;, + 3;1103,1102,1096;, + 3;1097,1103,1096;, + 3;1104,1103,1097;, + 3;1098,1104,1097;, + 3;1105,3866,3864;, + 3;1099,1105,3864;, + 3;1106,1105,1099;, + 3;1100,1106,1099;, + 3;3867,1106,1100;, + 3;3865,3867,1100;, + 3;1108,1107,1101;, + 3;1102,1108,1101;, + 3;1109,1108,1102;, + 3;1103,1109,1102;, + 3;1110,1109,1103;, + 3;1104,1110,1103;, + 3;1111,3868,3866;, + 3;1105,1111,3866;, + 3;1112,1111,1105;, + 3;1106,1112,1105;, + 3;3869,1112,1106;, + 3;3867,3869,1106;, + 3;1114,1113,1107;, + 3;1108,1114,1107;, + 3;1115,1114,1108;, + 3;1109,1115,1108;, + 3;1116,1115,1109;, + 3;1110,1116,1109;, + 3;1117,3870,3868;, + 3;1111,1117,3868;, + 3;1118,1117,1111;, + 3;1112,1118,1111;, + 3;3871,1118,1112;, + 3;3869,3871,1112;, + 3;1120,1119,1113;, + 3;1114,1120,1113;, + 3;1121,1120,1114;, + 3;1115,1121,1114;, + 3;1122,1121,1115;, + 3;1116,1122,1115;, + 3;1123,3872,3870;, + 3;1117,1123,3870;, + 3;1124,1123,1117;, + 3;1118,1124,1117;, + 3;3873,1124,1118;, + 3;3871,3873,1118;, + 3;1126,1125,1119;, + 3;1120,1126,1119;, + 3;1127,1126,1120;, + 3;1121,1127,1120;, + 3;1128,1127,1121;, + 3;1122,1128,1121;, + 3;1129,3874,3872;, + 3;1123,1129,3872;, + 3;1130,1129,1123;, + 3;1124,1130,1123;, + 3;3875,1130,1124;, + 3;3873,3875,1124;, + 3;1132,1131,1125;, + 3;1126,1132,1125;, + 3;1133,1132,1126;, + 3;1127,1133,1126;, + 3;1134,1133,1127;, + 3;1128,1134,1127;, + 3;1135,3876,3874;, + 3;1129,1135,3874;, + 3;1136,1135,1129;, + 3;1130,1136,1129;, + 3;3877,1136,1130;, + 3;3875,3877,1130;, + 3;1132,1137,1131;, + 3;1133,1138,1132;, + 3;1137,1132,1138;, + 3;1134,1138,1133;, + 3;1135,3878,3876;, + 3;1136,3879,1135;, + 3;3878,1135,3879;, + 3;3877,3879,1136;, + 3;1140,1139,972;, + 3;1010,1140,972;, + 3;1141,1140,1010;, + 3;976,1141,1010;, + 3;1142,1141,976;, + 3;969,1142,976;, + 3;1143,3880,3859;, + 3;1014,1143,3859;, + 3;1144,1143,1014;, + 3;977,1144,1014;, + 3;3881,1144,977;, + 3;3882,3881,977;, + 3;1146,1145,1139;, + 3;1140,1146,1139;, + 3;1147,1146,1140;, + 3;1141,1147,1140;, + 3;1148,1147,1141;, + 3;1142,1148,1141;, + 3;1149,3883,3880;, + 3;1143,1149,3880;, + 3;1150,1149,1143;, + 3;1144,1150,1143;, + 3;3884,1150,1144;, + 3;3881,3884,1144;, + 3;1152,1151,1145;, + 3;1146,1152,1145;, + 3;1153,1152,1146;, + 3;1147,1153,1146;, + 3;1154,1153,1147;, + 3;1148,1154,1147;, + 3;1155,3885,3883;, + 3;1149,1155,3883;, + 3;1156,1155,1149;, + 3;1150,1156,1149;, + 3;3886,1156,1150;, + 3;3884,3886,1150;, + 3;1158,1157,1151;, + 3;1152,1158,1151;, + 3;1159,1158,1152;, + 3;1153,1159,1152;, + 3;1160,1159,1153;, + 3;1154,1160,1153;, + 3;1161,3887,3885;, + 3;1155,1161,3885;, + 3;1162,1161,1155;, + 3;1156,1162,1155;, + 3;3888,1162,1156;, + 3;3886,3888,1156;, + 3;1164,1163,1157;, + 3;1158,1164,1157;, + 3;1165,1164,1158;, + 3;1159,1165,1158;, + 3;1166,1165,1159;, + 3;1160,1166,1159;, + 3;1167,3889,3887;, + 3;1161,1167,3887;, + 3;1168,1167,1161;, + 3;1162,1168,1161;, + 3;3890,1168,1162;, + 3;3888,3890,1162;, + 3;1170,1169,1163;, + 3;1164,1170,1163;, + 3;1171,1170,1164;, + 3;1165,1171,1164;, + 3;1172,1171,1165;, + 3;1166,1172,1165;, + 3;1173,3891,3889;, + 3;1167,1173,3889;, + 3;1174,1173,1167;, + 3;1168,1174,1167;, + 3;3892,1174,1168;, + 3;3890,3892,1168;, + 3;1176,1175,1169;, + 3;1170,1176,1169;, + 3;1177,1176,1170;, + 3;1171,1177,1170;, + 3;1178,1177,1171;, + 3;1172,1178,1171;, + 3;1179,3893,3891;, + 3;1173,1179,3891;, + 3;1180,1179,1173;, + 3;1174,1180,1173;, + 3;3894,1180,1174;, + 3;3892,3894,1174;, + 3;1182,1181,1175;, + 3;1176,1182,1175;, + 3;1183,1182,1176;, + 3;1177,1183,1176;, + 3;1184,1183,1177;, + 3;1178,1184,1177;, + 3;1185,3895,3893;, + 3;1179,1185,3893;, + 3;1186,1185,1179;, + 3;1180,1186,1179;, + 3;3896,1186,1180;, + 3;3894,3896,1180;, + 3;1188,1187,1181;, + 3;1182,1188,1181;, + 3;1189,1188,1182;, + 3;1183,1189,1182;, + 3;1190,1189,1183;, + 3;1184,1190,1183;, + 3;1191,3897,3895;, + 3;1185,1191,3895;, + 3;1192,1191,1185;, + 3;1186,1192,1185;, + 3;3898,1192,1186;, + 3;3896,3898,1186;, + 3;1194,1193,1187;, + 3;1188,1194,1187;, + 3;1195,1194,1188;, + 3;1189,1195,1188;, + 3;1196,1195,1189;, + 3;1190,1196,1189;, + 3;1197,3899,3897;, + 3;1191,1197,3897;, + 3;1198,1197,1191;, + 3;1192,1198,1191;, + 3;3900,1198,1192;, + 3;3898,3900,1192;, + 3;1194,1199,1193;, + 3;1195,1200,1194;, + 3;1199,1194,1200;, + 3;1196,1200,1195;, + 3;1197,3901,3899;, + 3;1198,3902,1197;, + 3;3901,1197,3902;, + 3;3900,3902,1198;, + 3;1202,1201,3832;, + 3;1011,1202,3832;, + 3;1203,1202,1011;, + 3;975,1203,1011;, + 3;1204,1203,975;, + 3;972,1204,975;, + 3;1205,3903,3882;, + 3;980,1205,3882;, + 3;1206,1205,980;, + 3;957,1206,980;, + 3;3904,1206,957;, + 3;962,3904,957;, + 3;1208,1207,1201;, + 3;1202,1208,1201;, + 3;1209,1208,1202;, + 3;1203,1209,1202;, + 3;1210,1209,1203;, + 3;1204,1210,1203;, + 3;1211,3905,3903;, + 3;1205,1211,3903;, + 3;1212,1211,1205;, + 3;1206,1212,1205;, + 3;3906,1212,1206;, + 3;3904,3906,1206;, + 3;1214,1213,1207;, + 3;1208,1214,1207;, + 3;1215,1214,1208;, + 3;1209,1215,1208;, + 3;1216,1215,1209;, + 3;1210,1216,1209;, + 3;1217,3907,3905;, + 3;1211,1217,3905;, + 3;1218,1217,1211;, + 3;1212,1218,1211;, + 3;3908,1218,1212;, + 3;3906,3908,1212;, + 3;1220,1219,1213;, + 3;1214,1220,1213;, + 3;1221,1220,1214;, + 3;1215,1221,1214;, + 3;1222,1221,1215;, + 3;1216,1222,1215;, + 3;1223,3909,3907;, + 3;1217,1223,3907;, + 3;1224,1223,1217;, + 3;1218,1224,1217;, + 3;3910,1224,1218;, + 3;3908,3910,1218;, + 3;1226,1225,1219;, + 3;1220,1226,1219;, + 3;1227,1226,1220;, + 3;1221,1227,1220;, + 3;1228,1227,1221;, + 3;1222,1228,1221;, + 3;1229,3911,3909;, + 3;1223,1229,3909;, + 3;1230,1229,1223;, + 3;1224,1230,1223;, + 3;3912,1230,1224;, + 3;3910,3912,1224;, + 3;1232,1231,1225;, + 3;1226,1232,1225;, + 3;1233,1232,1226;, + 3;1227,1233,1226;, + 3;1234,1233,1227;, + 3;1228,1234,1227;, + 3;1235,3913,3911;, + 3;1229,1235,3911;, + 3;1236,1235,1229;, + 3;1230,1236,1229;, + 3;3914,1236,1230;, + 3;3912,3914,1230;, + 3;1238,1237,1231;, + 3;1232,1238,1231;, + 3;1239,1238,1232;, + 3;1233,1239,1232;, + 3;1240,1239,1233;, + 3;1234,1240,1233;, + 3;1241,3915,3913;, + 3;1235,1241,3913;, + 3;1242,1241,1235;, + 3;1236,1242,1235;, + 3;3916,1242,1236;, + 3;3914,3916,1236;, + 3;1244,1243,1237;, + 3;1238,1244,1237;, + 3;1245,1244,1238;, + 3;1239,1245,1238;, + 3;1246,1245,1239;, + 3;1240,1246,1239;, + 3;1247,3917,3915;, + 3;1241,1247,3915;, + 3;1248,1247,1241;, + 3;1242,1248,1241;, + 3;3918,1248,1242;, + 3;3916,3918,1242;, + 3;1250,1249,3918;, + 3;1244,3919,1243;, + 3;1251,3919,1244;, + 3;1245,1251,1244;, + 3;1252,1251,1245;, + 3;1246,1252,1245;, + 3;1253,3920,3917;, + 3;1247,1253,3917;, + 3;1254,1253,1247;, + 3;1248,1254,1247;, + 3;1249,1254,1248;, + 3;3918,1249,1248;, + 3;1256,1255,3921;, + 3;3919,1256,3921;, + 3;1257,1256,3919;, + 3;1251,1257,3919;, + 3;1258,1257,1251;, + 3;1252,1258,1251;, + 3;1259,3922,3920;, + 3;1253,1259,3920;, + 3;1260,1259,1253;, + 3;1254,1260,1253;, + 3;3923,1260,1254;, + 3;1249,3923,1254;, + 3;1256,1261,1255;, + 3;1257,1262,1256;, + 3;1261,1256,1262;, + 3;1258,1262,1257;, + 3;1259,3924,3922;, + 3;1260,3925,1259;, + 3;3924,1259,3925;, + 3;3923,3925,1260;, + 3;3814,963,1263;, + 3;1263,973,956;, + 3;981,983,959;, + 3;983,981,1269;, + 3;3859,1264,1014;, + 3;1264,3859,1013;, + 3;3836,1265,978;, + 3;3836,979,1265;, + 3;3882,1266,980;, + 3;1266,3882,977;, + 3;1013,1265,1264;, + 3;1265,1013,978;, + 3;1014,1266,977;, + 3;1266,1014,1264;, + 3;1265,979,960;, + 3;957,981,3816;, + 3;3926,960,3834;, + 3;980,1266,1267;, + 3;1266,1269,1267;, + 3;983,1269,987;, + 3;1267,1269,981;, + 3;1269,1264,987;, + 3;1264,1269,1266;, + 3;1264,1265,987;, + 3;1265,986,987;, + 3;986,1265,960;, + 3;986,960,3926;, + 3;986,3926,3821;, + 3;1270,3815,1263;, + 3;974,1270,1008;, + 3;1277,1282,1271;, + 3;1271,3803,948;, + 3;1279,1278,1272;, + 3;1272,3807,3927;, + 3;949,3804,1273;, + 3;1284,3928,1275;, + 3;3808,3805,1274;, + 3;1276,3929,3930;, + 3;3928,1276,1275;, + 3;3928,3929,1276;, + 3;1274,949,1275;, + 3;1278,1277,948;, + 3;1272,1278,948;, + 3;1272,1280,1279;, + 3;1272,3927,1280;, + 3;1282,1281,947;, + 3;1271,1282,947;, + 3;1271,948,1277;, + 3;3810,1284,1283;, + 3;3810,3928,1284;, + 3;3806,3809,1283;, + 3;1273,3806,1283;, + 3;952,1282,1277;, + 3;952,3931,1282;, + 3;954,1278,1279;, + 3;954,952,1278;, + 3;1284,1275,949;, + 3;1273,1284,949;, + 3;1276,3930,950;, + 3;1274,1276,950;, + 3;1286,943,1285;, + 3;1286,850,1291;, + 3;1287,3759,3757;, + 3;1292,1287,3757;, + 3;1288,3798,1286;, + 3;1286,3798,850;, + 3;855,3932,1287;, + 3;855,945,3932;, + 3;849,1289,943;, + 3;1293,852,1289;, + 3;854,1290,860;, + 3;889,853,1290;, + 3;1286,1291,943;, + 3;849,943,1291;, + 3;855,1287,1292;, + 3;855,1292,3758;, + 3;856,852,1293;, + 3;1293,854,856;, + 3;3933,1286,1285;, + 3;946,3799,851;, + 3;946,3756,3801;, + 3;851,3800,943;, + 3;943,3800,1285;, + 3;3934,1286,3933;, + 3;3934,1288,1286;, + 3;1287,3932,3935;, + 3;1287,3935,3759;, + 3;1294,1295,1736;, + 3;1388,1296,1297;, + 3;1294,1389,1735;, + 3;1734,1738,1299;, + 3;1299,1389,1734;, + 3;1304,1390,1333;, + 3;1300,1332,1306;, + 3;1391,3936,1301;, + 3;1737,3937,3938;, + 3;3938,3939,3940;, + 3;1297,1296,1391;, + 3;1302,1294,1334;, + 3;1303,1295,1302;, + 3;1295,1294,1302;, + 3;1298,1735,1305;, + 3;3941,3937,1306;, + 3;3937,1300,1306;, + 3;1332,1390,1304;, + 3;1320,1335,1336;, + 3;1338,1307,1337;, + 3;1339,1340,1314;, + 3;1342,1308,1341;, + 3;1343,1344,1321;, + 3;1345,1337,1307;, + 3;1347,1319,1346;, + 3;1343,1348,1322;, + 3;1313,1335,1349;, + 3;1339,1350,1309;, + 3;1350,1349,1309;, + 3;1341,1340,1317;, + 3;1312,1351,1347;, + 3;3942,1336,3943;, + 3;1344,1310,1351;, + 3;1348,3944,3945;, + 3;1346,1319,1345;, + 3;3943,1313,1325;, + 3;1325,1324,3943;, + 3;1312,1323,1327;, + 3;1327,1326,1312;, + 3;3944,1321,1329;, + 3;1329,1328,3944;, + 3;1311,1314,1331;, + 3;1331,1330,1311;, + 3;1313,1311,1325;, + 3;1330,1325,1311;, + 3;1314,1308,3946;, + 3;3946,1331,1314;, + 3;1321,1312,1326;, + 3;1326,1329,1321;, + 3;1323,1307,3947;, + 3;3947,1327,1323;, + 3;1315,1316,3948;, + 3;3948,3949,1315;, + 3;1317,1309,3950;, + 3;3950,3951,1317;, + 3;1318,1317,3951;, + 3;3951,3952,1318;, + 3;1310,1322,3953;, + 3;3953,3954,1310;, + 3;1316,1319,3955;, + 3;3955,3948,1316;, + 3;1309,1320,3956;, + 3;3956,3950,1309;, + 3;1319,1310,3954;, + 3;3954,3955,1319;, + 3;1320,3957,3958;, + 3;3958,3956,1320;, + 3;1322,3959,3960;, + 3;3960,3953,1322;, + 3;1335,1313,1336;, + 3;1313,3943,1336;, + 3;1337,1316,1338;, + 3;1316,1315,1338;, + 3;1339,1309,1340;, + 3;1309,1317,1340;, + 3;1341,1317,1342;, + 3;1317,1318,1342;, + 3;1343,1322,1344;, + 3;1322,1310,1344;, + 3;1345,1319,1337;, + 3;1319,1316,1337;, + 3;1346,1323,1347;, + 3;1323,1312,1347;, + 3;1343,1321,1348;, + 3;1321,3944,1348;, + 3;1335,1320,1349;, + 3;1320,1309,1349;, + 3;1339,1314,1350;, + 3;1314,1311,1350;, + 3;1350,1311,1349;, + 3;1311,1313,1349;, + 3;1341,1308,1340;, + 3;1308,1314,1340;, + 3;1351,1310,1347;, + 3;1310,1319,1347;, + 3;3942,3957,1336;, + 3;3957,1320,1336;, + 3;1351,1312,1344;, + 3;1312,1321,1344;, + 3;3945,3959,1348;, + 3;3959,1322,1348;, + 3;1345,1307,1346;, + 3;1307,1323,1346;, + 3;1334,1294,1735;, + 3;3961,1295,1303;, + 3;1300,1390,1332;, + 3;1366,1353,1384;, + 3;1387,3962,1367;, + 3;1368,1369,1355;, + 3;1352,1370,1371;, + 3;1371,1356,1372;, + 3;1374,1360,1373;, + 3;3963,1358,1364;, + 3;1376,1358,1375;, + 3;1386,1353,1365;, + 3;1376,3964,1377;, + 3;1374,1353,1378;, + 3;1361,3965,1363;, + 3;1362,1358,3966;, + 3;1380,1359,1379;, + 3;1361,1381,1380;, + 3;1382,1383,1360;, + 3;3967,3968,3969;, + 3;3970,1364,1354;, + 3;1357,3967,3971;, + 3;1361,1362,3966;, + 3;1379,1359,1375;, + 3;3968,3967,1357;, + 3;1381,3972,3973;, + 3;3963,3966,1358;, + 3;1377,3964,3974;, + 3;1373,1360,1383;, + 3;1385,1384,1353;, + 3;1352,1385,1387;, + 3;1372,1356,1378;, + 3;1367,3962,3975;, + 3;1370,1368,1355;, + 3;1368,1367,1369;, + 3;1367,3975,1369;, + 3;1370,1355,1371;, + 3;1355,1356,1371;, + 3;1372,1366,1371;, + 3;1366,1352,1371;, + 3;1373,1365,1374;, + 3;1365,1353,1374;, + 3;1375,1359,1376;, + 3;1359,3964,1376;, + 3;1377,1364,1376;, + 3;1364,1358,1376;, + 3;1378,1356,1374;, + 3;1356,1360,1374;, + 3;1379,1362,1380;, + 3;1362,1361,1380;, + 3;1381,3973,1380;, + 3;3973,1359,1380;, + 3;1382,3968,1383;, + 3;3968,1357,1383;, + 3;1375,1358,1379;, + 3;1358,1362,1379;, + 3;1381,1361,3972;, + 3;1361,1363,3972;, + 3;3974,1354,1377;, + 3;1354,1364,1377;, + 3;1383,1357,1373;, + 3;1357,1365,1373;, + 3;1378,1353,1372;, + 3;1353,1366,1372;, + 3;1370,1352,1368;, + 3;1352,1367,1368;, + 3;1357,3971,1365;, + 3;1325,1324,1330;, + 3;3962,3976,3975;, + 3;1385,3977,3962;, + 3;1386,3971,1385;, + 3;1352,1366,1384;, + 3;1384,1385,1352;, + 3;1385,3971,3977;, + 3;3971,1386,1365;, + 3;1353,1386,1385;, + 3;1352,1387,1367;, + 3;1387,1385,3962;, + 3;3970,3963,1364;, + 3;3965,1361,3966;, + 3;1734,1388,1297;, + 3;1294,1734,1389;, + 3;1299,1735,1389;, + 3;3978,1295,3961;, + 3;3979,1296,3980;, + 3;1297,1391,1301;, + 3;1391,3979,3981;, + 3;1716,3982,1392;, + 3;3982,1716,3983;, + 3;3984,3985,1394;, + 3;1718,3986,3984;, + 3;3987,3983,1393;, + 3;1393,1717,3987;, + 3;1719,3988,1395;, + 3;1719,1394,3985;, + 3;1720,1719,1721;, + 3;1723,1722,1397;, + 3;1724,1399,1725;, + 3;1727,1726,1396;, + 3;1728,1718,1729;, + 3;1728,3989,3990;, + 3;1453,1401,1715;, + 3;1400,3991,3992;, + 3;1426,1712,1402;, + 3;1415,1418,1454;, + 3;3993,1398,1404;, + 3;1713,1433,1408;, + 3;3994,3991,1708;, + 3;1404,1427,3993;, + 3;1418,1415,1403;, + 3;1404,1398,1429;, + 3;3995,1402,1407;, + 3;1456,1419,1400;, + 3;1429,1398,3996;, + 3;1429,3996,1410;, + 3;1436,1409,1406;, + 3;1708,1457,1408;, + 3;1408,3997,3994;, + 3;1434,1409,1435;, + 3;3998,1411,3999;, + 3;1436,1437,1412;, + 3;1437,1436,1410;, + 3;3997,1408,1411;, + 3;1411,1413,3997;, + 3;1406,1409,1431;, + 3;1409,4000,1431;, + 3;1421,1453,1419;, + 3;1454,1418,1401;, + 3;1414,1416,1453;, + 3;1420,1417,1419;, + 3;1708,1418,1457;, + 3;1715,1401,1708;, + 3;1400,1715,3991;, + 3;1414,1453,1421;, + 3;1456,1420,1419;, + 3;1455,1421,1419;, + 3;3995,1427,1426;, + 3;1425,1402,1712;, + 3;1404,1426,1427;, + 3;3995,3993,1427;, + 3;1406,1429,1436;, + 3;1404,1429,1428;, + 3;1428,1429,1406;, + 3;1457,1430,1408;, + 3;1408,1430,1713;, + 3;1428,1406,1431;, + 3;1428,1431,1432;, + 3;3999,1408,1433;, + 3;1408,3999,1411;, + 3;1409,1434,4000;, + 3;1412,1435,1409;, + 3;1410,1436,1429;, + 3;1409,1436,1412;, + 3;1410,4001,1437;, + 3;1437,4001,1440;, + 3;1440,1439,1437;, + 3;1411,3998,1438;, + 3;1438,1441,1411;, + 3;1412,1437,1439;, + 3;1439,1442,1412;, + 3;1413,1411,1441;, + 3;1441,4002,1413;, + 3;1435,1412,1442;, + 3;1442,4003,1435;, + 3;1439,1440,1445;, + 3;1445,1444,1439;, + 3;1441,1438,1443;, + 3;1443,1446,1441;, + 3;4002,1441,1446;, + 3;1446,4004,4002;, + 3;4003,1442,1447;, + 3;1447,4005,4003;, + 3;1442,1439,1444;, + 3;1444,1447,1442;, + 3;1444,1445,1450;, + 3;1450,1449,1444;, + 3;1446,1443,1448;, + 3;1448,1451,1446;, + 3;4004,1446,1451;, + 3;1451,4006,4004;, + 3;4005,1447,1452;, + 3;1452,4007,4005;, + 3;1447,1444,1449;, + 3;1449,1452,1447;, + 3;1452,1449,1450;, + 3;4006,1451,1448;, + 3;4007,1452,1450;, + 3;1419,1715,1400;, + 3;1416,1401,1453;, + 3;1416,1454,1401;, + 3;1417,1455,1419;, + 3;4008,1456,1400;, + 3;1403,1457,1418;, + 3;1461,4009,1460;, + 3;1403,1415,4010;, + 3;1462,1403,4010;, + 3;1457,1403,1462;, + 3;1463,1457,1462;, + 3;1430,1457,1463;, + 3;1464,4011,4012;, + 3;1405,4011,1464;, + 3;1465,1405,1464;, + 3;1424,1405,1465;, + 3;1460,1424,1465;, + 3;4009,1424,1460;, + 3;1467,4013,1466;, + 3;4010,4013,1467;, + 3;1468,4010,1467;, + 3;1462,4010,1468;, + 3;1469,1462,1468;, + 3;1463,1462,1469;, + 3;1470,4012,4014;, + 3;1464,4012,1470;, + 3;1471,1464,1470;, + 3;1465,1464,1471;, + 3;4015,1465,1471;, + 3;1460,1465,4015;, + 3;1473,1466,1472;, + 3;1467,1466,1473;, + 3;1474,1467,1473;, + 3;1468,1467,1474;, + 3;1475,1468,1474;, + 3;1469,1468,1475;, + 3;1476,4014,4016;, + 3;1470,4014,1476;, + 3;1477,1470,1476;, + 3;1471,1470,1477;, + 3;4017,1471,1477;, + 3;4015,1471,4017;, + 3;1479,1472,1478;, + 3;1473,1472,1479;, + 3;1480,1473,1479;, + 3;1474,1473,1480;, + 3;1481,1474,1480;, + 3;1475,1474,1481;, + 3;1482,4016,4018;, + 3;1476,4016,1482;, + 3;1483,1476,1482;, + 3;1477,1476,1483;, + 3;4019,1477,1483;, + 3;4017,1477,4019;, + 3;1485,1478,1484;, + 3;1479,1478,1485;, + 3;1486,1479,1485;, + 3;1480,1479,1486;, + 3;1487,1480,1486;, + 3;1481,1480,1487;, + 3;1488,4018,4020;, + 3;1482,4018,1488;, + 3;1489,1482,1488;, + 3;1483,1482,1489;, + 3;4021,1483,1489;, + 3;4019,1483,4021;, + 3;1491,1484,1490;, + 3;1485,1484,1491;, + 3;1492,1485,1491;, + 3;1486,1485,1492;, + 3;1493,1486,1492;, + 3;1487,1486,1493;, + 3;1494,4020,4022;, + 3;1488,4020,1494;, + 3;1495,1488,1494;, + 3;1489,1488,1495;, + 3;4023,1489,1495;, + 3;4021,1489,4023;, + 3;1497,1490,1496;, + 3;1491,1490,1497;, + 3;1498,1491,1497;, + 3;1492,1491,1498;, + 3;1499,1492,1498;, + 3;1493,1492,1499;, + 3;1500,4022,4024;, + 3;1494,4022,1500;, + 3;1501,1494,1500;, + 3;1495,1494,1501;, + 3;4025,1495,1501;, + 3;4023,1495,4025;, + 3;1503,1496,1502;, + 3;1497,1496,1503;, + 3;1504,1497,1503;, + 3;1498,1497,1504;, + 3;1505,1498,1504;, + 3;1499,1498,1505;, + 3;1506,4024,4026;, + 3;1500,4024,1506;, + 3;1507,1500,1506;, + 3;1501,1500,1507;, + 3;4027,1501,1507;, + 3;4025,1501,4027;, + 3;1509,1502,1508;, + 3;1503,1502,1509;, + 3;1510,1503,1509;, + 3;1504,1503,1510;, + 3;1511,1504,1510;, + 3;1505,1504,1511;, + 3;1512,4026,4028;, + 3;1506,4026,1512;, + 3;1513,1506,1512;, + 3;1507,1506,1513;, + 3;4029,1507,1513;, + 3;4027,1507,4029;, + 3;1515,1508,1514;, + 3;1509,1508,1515;, + 3;1516,1509,1515;, + 3;1510,1509,1516;, + 3;1517,1510,1516;, + 3;1511,1510,1517;, + 3;1518,4028,4030;, + 3;1512,4028,1518;, + 3;1519,1512,1518;, + 3;1513,1512,1519;, + 3;4031,1513,1519;, + 3;4029,1513,4031;, + 3;1515,1514,1520;, + 3;1516,1515,1521;, + 3;1520,1521,1515;, + 3;1517,1516,1521;, + 3;1518,4030,4032;, + 3;1519,1518,4033;, + 3;4032,4033,1518;, + 3;4031,1519,4033;, + 3;1523,1414,1522;, + 3;1416,1414,1523;, + 3;1524,1416,1523;, + 3;1454,1416,1524;, + 3;1525,1454,1524;, + 3;1415,1454,1525;, + 3;1526,4009,4034;, + 3;1423,4009,1526;, + 3;1527,1423,1526;, + 3;1458,1423,1527;, + 3;4035,1458,1527;, + 3;4036,1458,4035;, + 3;1529,1522,1528;, + 3;1523,1522,1529;, + 3;1530,1523,1529;, + 3;1524,1523,1530;, + 3;1531,1524,1530;, + 3;1525,1524,1531;, + 3;1532,4034,4037;, + 3;1526,4034,1532;, + 3;1533,1526,1532;, + 3;1527,1526,1533;, + 3;4038,1527,1533;, + 3;4035,1527,4038;, + 3;1535,1528,1534;, + 3;1529,1528,1535;, + 3;1536,1529,1535;, + 3;1530,1529,1536;, + 3;1537,1530,1536;, + 3;1531,1530,1537;, + 3;1538,4037,4039;, + 3;1532,4037,1538;, + 3;1539,1532,1538;, + 3;1533,1532,1539;, + 3;4040,1533,1539;, + 3;4038,1533,4040;, + 3;1541,1534,1540;, + 3;1535,1534,1541;, + 3;1542,1535,1541;, + 3;1536,1535,1542;, + 3;1543,1536,1542;, + 3;1537,1536,1543;, + 3;1544,4039,4041;, + 3;1538,4039,1544;, + 3;1545,1538,1544;, + 3;1539,1538,1545;, + 3;4042,1539,1545;, + 3;4040,1539,4042;, + 3;1547,1540,1546;, + 3;1541,1540,1547;, + 3;1548,1541,1547;, + 3;1542,1541,1548;, + 3;1549,1542,1548;, + 3;1543,1542,1549;, + 3;1550,4041,4043;, + 3;1544,4041,1550;, + 3;1551,1544,1550;, + 3;1545,1544,1551;, + 3;4044,1545,1551;, + 3;4042,1545,4044;, + 3;1553,1546,1552;, + 3;1547,1546,1553;, + 3;1554,1547,1553;, + 3;1548,1547,1554;, + 3;1555,1548,1554;, + 3;1549,1548,1555;, + 3;1556,4043,4045;, + 3;1550,4043,1556;, + 3;1557,1550,1556;, + 3;1551,1550,1557;, + 3;4046,1551,1557;, + 3;4044,1551,4046;, + 3;1559,1552,1558;, + 3;1553,1552,1559;, + 3;1560,1553,1559;, + 3;1554,1553,1560;, + 3;1561,1554,1560;, + 3;1555,1554,1561;, + 3;1562,4045,4047;, + 3;1556,4045,1562;, + 3;1563,1556,1562;, + 3;1557,1556,1563;, + 3;4048,1557,1563;, + 3;4046,1557,4048;, + 3;1565,1558,1564;, + 3;1559,1558,1565;, + 3;1566,1559,1565;, + 3;1560,1559,1566;, + 3;1567,1560,1566;, + 3;1561,1560,1567;, + 3;1568,4047,4049;, + 3;1562,4047,1568;, + 3;1569,1562,1568;, + 3;1563,1562,1569;, + 3;4050,1563,1569;, + 3;4048,1563,4050;, + 3;1571,1564,1570;, + 3;1565,1564,1571;, + 3;1572,1565,1571;, + 3;1566,1565,1572;, + 3;1573,1566,1572;, + 3;1567,1566,1573;, + 3;1574,4049,4051;, + 3;1568,4049,1574;, + 3;1575,1568,1574;, + 3;1569,1568,1575;, + 3;4052,1569,1575;, + 3;4050,1569,4052;, + 3;1577,1570,1576;, + 3;1571,1570,1577;, + 3;1578,1571,1577;, + 3;1572,1571,1578;, + 3;1579,1572,1578;, + 3;1573,1572,1579;, + 3;1580,4051,4053;, + 3;1574,4051,1580;, + 3;1581,1574,1580;, + 3;1575,1574,1581;, + 3;4054,1575,1581;, + 3;4052,1575,4054;, + 3;1577,1576,1582;, + 3;1578,1577,1583;, + 3;1582,1583,1577;, + 3;1579,1578,1583;, + 3;1580,4053,4055;, + 3;1581,1580,4056;, + 3;4055,4056,1580;, + 3;4054,1581,4056;, + 3;1585,1417,1584;, + 3;1455,1417,1585;, + 3;1586,1455,1585;, + 3;1421,1455,1586;, + 3;1587,1421,1586;, + 3;1414,1421,1587;, + 3;1588,4036,4057;, + 3;1459,4036,1588;, + 3;1589,1459,1588;, + 3;1422,1459,1589;, + 3;4058,1422,1589;, + 3;4059,1422,4058;, + 3;1591,1584,1590;, + 3;1585,1584,1591;, + 3;1592,1585,1591;, + 3;1586,1585,1592;, + 3;1593,1586,1592;, + 3;1587,1586,1593;, + 3;1594,4057,4060;, + 3;1588,4057,1594;, + 3;1595,1588,1594;, + 3;1589,1588,1595;, + 3;4061,1589,1595;, + 3;4058,1589,4061;, + 3;1597,1590,1596;, + 3;1591,1590,1597;, + 3;1598,1591,1597;, + 3;1592,1591,1598;, + 3;1599,1592,1598;, + 3;1593,1592,1599;, + 3;1600,4060,4062;, + 3;1594,4060,1600;, + 3;1601,1594,1600;, + 3;1595,1594,1601;, + 3;4063,1595,1601;, + 3;4061,1595,4063;, + 3;1603,1596,1602;, + 3;1597,1596,1603;, + 3;1604,1597,1603;, + 3;1598,1597,1604;, + 3;1605,1598,1604;, + 3;1599,1598,1605;, + 3;1606,4062,4064;, + 3;1600,4062,1606;, + 3;1607,1600,1606;, + 3;1601,1600,1607;, + 3;4065,1601,1607;, + 3;4063,1601,4065;, + 3;1609,1602,1608;, + 3;1603,1602,1609;, + 3;1610,1603,1609;, + 3;1604,1603,1610;, + 3;1611,1604,1610;, + 3;1605,1604,1611;, + 3;1612,4064,4066;, + 3;1606,4064,1612;, + 3;1613,1606,1612;, + 3;1607,1606,1613;, + 3;4067,1607,1613;, + 3;4065,1607,4067;, + 3;1615,1608,1614;, + 3;1609,1608,1615;, + 3;1616,1609,1615;, + 3;1610,1609,1616;, + 3;1617,1610,1616;, + 3;1611,1610,1617;, + 3;1618,4066,4068;, + 3;1612,4066,1618;, + 3;1619,1612,1618;, + 3;1613,1612,1619;, + 3;4069,1613,1619;, + 3;4067,1613,4069;, + 3;1621,1614,1620;, + 3;1615,1614,1621;, + 3;1622,1615,1621;, + 3;1616,1615,1622;, + 3;1623,1616,1622;, + 3;1617,1616,1623;, + 3;1624,4068,4070;, + 3;1618,4068,1624;, + 3;1625,1618,1624;, + 3;1619,1618,1625;, + 3;4071,1619,1625;, + 3;4069,1619,4071;, + 3;1627,1620,1626;, + 3;1621,1620,1627;, + 3;1628,1621,1627;, + 3;1622,1621,1628;, + 3;1629,1622,1628;, + 3;1623,1622,1629;, + 3;1630,4070,4072;, + 3;1624,4070,1630;, + 3;1631,1624,1630;, + 3;1625,1624,1631;, + 3;4073,1625,1631;, + 3;4071,1625,4073;, + 3;1633,1626,1632;, + 3;1627,1626,1633;, + 3;1634,1627,1633;, + 3;1628,1627,1634;, + 3;1635,1628,1634;, + 3;1629,1628,1635;, + 3;1636,4072,4074;, + 3;1630,4072,1636;, + 3;1637,1630,1636;, + 3;1631,1630,1637;, + 3;4075,1631,1637;, + 3;4073,1631,4075;, + 3;1639,1632,1638;, + 3;1633,1632,1639;, + 3;1640,1633,1639;, + 3;1634,1633,1640;, + 3;1641,1634,1640;, + 3;1635,1634,1641;, + 3;1642,4074,4076;, + 3;1636,4074,1642;, + 3;1643,1636,1642;, + 3;1637,1636,1643;, + 3;4077,1637,1643;, + 3;4075,1637,4077;, + 3;1639,1638,1644;, + 3;1640,1639,1645;, + 3;1644,1645,1639;, + 3;1641,1640,1645;, + 3;1642,4076,4078;, + 3;1643,1642,4079;, + 3;4078,4079,1642;, + 3;4077,1643,4079;, + 3;1647,4008,1646;, + 3;1456,4008,1647;, + 3;1648,1456,1647;, + 3;1420,1456,1648;, + 3;1649,1420,1648;, + 3;1417,1420,1649;, + 3;1650,4059,4080;, + 3;1425,4059,1650;, + 3;1651,1425,1650;, + 3;1402,1425,1651;, + 3;4081,1402,1651;, + 3;1407,1402,4081;, + 3;1653,1646,1652;, + 3;1647,1646,1653;, + 3;1654,1647,1653;, + 3;1648,1647,1654;, + 3;1655,1648,1654;, + 3;1649,1648,1655;, + 3;1656,4080,4082;, + 3;1650,4080,1656;, + 3;1657,1650,1656;, + 3;1651,1650,1657;, + 3;4083,1651,1657;, + 3;4081,1651,4083;, + 3;1659,1652,1658;, + 3;1653,1652,1659;, + 3;1660,1653,1659;, + 3;1654,1653,1660;, + 3;1661,1654,1660;, + 3;1655,1654,1661;, + 3;1662,4082,4084;, + 3;1656,4082,1662;, + 3;1663,1656,1662;, + 3;1657,1656,1663;, + 3;4085,1657,1663;, + 3;4083,1657,4085;, + 3;1665,1658,1664;, + 3;1659,1658,1665;, + 3;1666,1659,1665;, + 3;1660,1659,1666;, + 3;1667,1660,1666;, + 3;1661,1660,1667;, + 3;1668,4084,4086;, + 3;1662,4084,1668;, + 3;1669,1662,1668;, + 3;1663,1662,1669;, + 3;4087,1663,1669;, + 3;4085,1663,4087;, + 3;1671,1664,1670;, + 3;1665,1664,1671;, + 3;1672,1665,1671;, + 3;1666,1665,1672;, + 3;1673,1666,1672;, + 3;1667,1666,1673;, + 3;1674,4086,4088;, + 3;1668,4086,1674;, + 3;1675,1668,1674;, + 3;1669,1668,1675;, + 3;4089,1669,1675;, + 3;4087,1669,4089;, + 3;1677,1670,1676;, + 3;1671,1670,1677;, + 3;1678,1671,1677;, + 3;1672,1671,1678;, + 3;1679,1672,1678;, + 3;1673,1672,1679;, + 3;1680,4088,4090;, + 3;1674,4088,1680;, + 3;1681,1674,1680;, + 3;1675,1674,1681;, + 3;4091,1675,1681;, + 3;4089,1675,4091;, + 3;1683,1676,1682;, + 3;1677,1676,1683;, + 3;1684,1677,1683;, + 3;1678,1677,1684;, + 3;1685,1678,1684;, + 3;1679,1678,1685;, + 3;1686,4090,4092;, + 3;1680,4090,1686;, + 3;1687,1680,1686;, + 3;1681,1680,1687;, + 3;4093,1681,1687;, + 3;4091,1681,4093;, + 3;1689,1682,1688;, + 3;1683,1682,1689;, + 3;1690,1683,1689;, + 3;1684,1683,1690;, + 3;1691,1684,1690;, + 3;1685,1684,1691;, + 3;1692,4092,4094;, + 3;1686,4092,1692;, + 3;1693,1686,1692;, + 3;1687,1686,1693;, + 3;4095,1687,1693;, + 3;4093,1687,4095;, + 3;1695,1688,1694;, + 3;1689,1688,1695;, + 3;1696,1689,1695;, + 3;1690,1689,1696;, + 3;1697,1690,1696;, + 3;1691,1690,1697;, + 3;1698,4094,4096;, + 3;1692,4094,1698;, + 3;1699,1692,1698;, + 3;1693,1692,1699;, + 3;4097,1693,1699;, + 3;4095,1693,4097;, + 3;1701,1694,1700;, + 3;1695,1694,1701;, + 3;1702,1695,1701;, + 3;1696,1695,1702;, + 3;1703,1696,1702;, + 3;1697,1696,1703;, + 3;1704,4096,4098;, + 3;1698,4096,1704;, + 3;1705,1698,1704;, + 3;1699,1698,1705;, + 3;4099,1699,1705;, + 3;4097,1699,4099;, + 3;1701,1700,1706;, + 3;1702,1701,1707;, + 3;1706,1707,1701;, + 3;1703,1702,1707;, + 3;1704,4098,4100;, + 3;1705,1704,4101;, + 3;4100,4101,1704;, + 3;4099,1705,4101;, + 3;3994,1708,1408;, + 3;1708,1401,1418;, + 3;1426,1404,1428;, + 3;1428,1714,1426;, + 3;4036,1459,1709;, + 3;1709,1458,4036;, + 3;4009,1423,1710;, + 3;4009,1710,1424;, + 3;4059,1425,1711;, + 3;1711,1422,4059;, + 3;1458,1709,1710;, + 3;1710,1423,1458;, + 3;1459,1422,1711;, + 3;1711,1709,1459;, + 3;1710,1405,1424;, + 3;1402,3995,1426;, + 3;4102,4011,1405;, + 3;1425,1712,1711;, + 3;1711,1712,1714;, + 3;1428,1432,1714;, + 3;1712,1426,1714;, + 3;1714,1432,1709;, + 3;1709,1711,1714;, + 3;1709,1432,1710;, + 3;1710,1432,1431;, + 3;1431,1405,1710;, + 3;1431,4102,1405;, + 3;1431,4000,4102;, + 3;1715,1708,3991;, + 3;1419,1453,1715;, + 3;1722,1716,1727;, + 3;1716,1393,3983;, + 3;1724,1717,1723;, + 3;1717,4103,3987;, + 3;1394,1718,3984;, + 3;1729,1720,4104;, + 3;3988,1719,3985;, + 3;1721,4105,4106;, + 3;4104,1720,1721;, + 3;4104,1721,4106;, + 3;1719,1720,1394;, + 3;1723,1393,1722;, + 3;1717,1393,1723;, + 3;1717,1724,1725;, + 3;1717,1725,4103;, + 3;1727,1392,1726;, + 3;1716,1392,1727;, + 3;1716,1722,1393;, + 3;3989,1728,1729;, + 3;3989,1729,4104;, + 3;3986,1728,3990;, + 3;1718,1728,3986;, + 3;1397,1722,1727;, + 3;1397,1727,1396;, + 3;1399,1724,1723;, + 3;1399,1723,1397;, + 3;1729,1394,1720;, + 3;1718,1394,1729;, + 3;1721,1395,4105;, + 3;1719,1395,1721;, + 3;1731,1730,1388;, + 3;1731,1736,1295;, + 3;1732,3938,3940;, + 3;1737,3938,1732;, + 3;1733,1731,3978;, + 3;1731,1295,3978;, + 3;1300,1732,4107;, + 3;1300,4107,1390;, + 3;1294,1388,1734;, + 3;1738,1734,1297;, + 3;1299,1305,1735;, + 3;1334,1735,1298;, + 3;1731,1388,1736;, + 3;1294,1736,1388;, + 3;1300,1737,1732;, + 3;1300,3937,1737;, + 3;1301,1738,1297;, + 3;1738,1301,1299;, + 3;4108,1730,1731;, + 3;1391,1296,3979;, + 3;1391,3981,3936;, + 3;1296,1388,3980;, + 3;1388,1730,3980;, + 3;4109,4108,1731;, + 3;4109,1731,1733;, + 3;1732,4110,4107;, + 3;1732,3940,4110;, + 3;196,4111,197;, + 3;3759,4112,3760;, + 3;3938,4113,3939;, + 3;74,75,4114;, + 3;1744,6,1742;, + 3;10,97,1739;, + 3;1743,1745,142;, + 3;1740,144,215;, + 3;4115,4116,1741;, + 3;1741,1744,4115;, + 3;4117,4118,1742;, + 3;1742,1745,4117;, + 3;4118,4115,1744;, + 3;1744,1742,4118;, + 3;4119,4117,1745;, + 3;1745,1743,4119;, + 3;118,107,3471;, + 3;3460,3471,107;, + 3;233,3527,3528;, + 3;3528,3518,224;, + 3;106,5,87;, + 3;106,87,110;, + 3;1779,1790,1756;, + 3;1757,1819,1751;, + 3;1825,1826,4120;, + 3;1758,1829,1748;, + 3;2386,2124,2140;, + 3;2330,2146,2425;, + 3;1870,1872,1782;, + 3;4121,1846,4122;, + 3;1834,1835,1759;, + 3;2183,2240,2182;, + 3;2698,2714,2138;, + 3;2344,2518,2356;, + 3;4123,1852,4124;, + 3;1761,1865,4125;, + 3;1818,1799,1766;, + 3;2711,2132,2707;, + 3;2288,2450,2748;, + 3;2129,2213,2725;, + 3;2726,2753,2169;, + 3;2461,2471,2433;, + 3;1762,1763,1760;, + 3;1770,1772,1771;, + 3;2214,2022,2040;, + 3;2457,2193,2206;, + 3;2749,2758,2168;, + 3;2184,2176,2239;, + 3;2041,2190,2052;, + 3;2163,2231,2287;, + 3;2739,2284,2036;, + 3;2724,2204,2180;, + 3;2194,2044,2056;, + 3;2185,2196,2175;, + 3;2186,2043,2195;, + 3;2189,2042,2178;, + 3;2205,2188,2179;, + 3;2113,2062,2070;, + 3;2192,2458,2064;, + 3;2075,2198,2074;, + 3;2177,2042,2187;, + 3;2199,2053,2073;, + 3;2191,2065,2051;, + 3;2174,2197,2076;, + 3;2200,2700,2211;, + 3;2712,2202,2131;, + 3;2121,2396,2209;, + 3;2203,2212,2130;, + 3;1833,1800,1831;, + 3;2222,2021,2215;, + 3;2173,2077,2090;, + 3;2221,2037,2034;, + 3;2084,2020,2223;, + 3;2285,2220,2035;, + 3;2723,2181,2232;, + 3;2256,2282,2245;, + 3;2261,2278,2270;, + 3;2251,2281,2257;, + 3;2246,2277,2262;, + 3;2269,2279,2275;, + 3;2164,2249,2230;, + 3;2248,2165,2243;, + 3;2170,2259,2238;, + 3;2258,2171,2255;, + 3;2216,2267,2226;, + 3;2266,2217,2265;, + 3;2081,2254,2172;, + 3;2253,2082,2273;, + 3;2224,2272,2083;, + 3;2271,2225,2268;, + 3;2228,2264,2218;, + 3;2263,2229,2250;, + 3;2236,2242,2166;, + 3;2241,2237,2260;, + 3;2280,2252,2274;, + 3;2276,2247,2244;, + 3;2160,2738,2732;, + 3;2227,2219,2286;, + 3;2143,2159,2429;, + 3;2297,2449,2289;, + 3;2142,2430,2291;, + 3;2309,2469,2495;, + 3;2434,2127,2768;, + 3;2472,2437,2308;, + 3;2477,2302,2444;, + 3;2730,2028,2746;, + 3;4126,1823,1747;, + 3;1769,1778,3416;, + 3;4127,1838,1750;, + 3;1883,1763,1762;, + 3;1765,1856,4128;, + 3;1764,1804,1784;, + 3;1858,1859,4129;, + 3;1777,1760,1763;, + 3;1749,1752,1763;, + 3;1746,1806,1767;, + 3;1773,3416,1775;, + 3;1771,1769,1770;, + 3;4130,4131,4132;, + 3;4133,4134,1768;, + 3;4135,4136,4137;, + 3;4136,4135,4138;, + 3;4137,4139,4140;, + 3;4139,4137,4136;, + 3;4141,4142,4143;, + 3;1776,4140,4139;, + 3;1774,1768,4134;, + 3;4144,4143,4142;, + 3;4132,4138,4135;, + 3;4138,4132,4131;, + 3;4143,4144,1774;, + 3;3416,1773,4145;, + 3;1768,1774,4144;, + 3;4142,4141,1776;, + 3;3416,4145,1770;, + 3;4146,2141,4147;, + 3;4140,1776,4141;, + 3;3416,4148,1775;, + 3;4131,4130,4133;, + 3;4149,1807,4150;, + 3;4134,4133,4130;, + 3;2715,2709,2333;, + 3;2319,2343,2549;, + 3;4151,1849,4152;, + 3;2145,4153,2704;, + 3;2710,2703,2332;, + 3;2524,2523,2346;, + 3;1783,1809,4154;, + 3;2320,2147,2342;, + 3;2335,2352,2329;, + 3;2351,2336,2350;, + 3;2363,2341,2148;, + 3;2367,2328,2353;, + 3;2375,2349,2337;, + 3;2370,2385,2536;, + 3;2537,2360,2135;, + 3;4155,1867,4156;, + 3;2327,2368,2362;, + 3;2513,2512,2355;, + 3;2149,2361,2369;, + 3;2531,2529,2374;, + 3;2348,2376,2372;, + 3;1785,1811,4157;, + 3;2389,2383,2378;, + 3;2381,2134,2357;, + 3;2384,2371,2377;, + 3;2133,2382,2390;, + 3;4158,1877,4159;, + 3;2338,2388,2379;, + 3;2393,2098,2401;, + 3;2392,2397,2115;, + 3;2109,2060,2399;, + 3;2394,2412,2097;, + 3;2411,2395,2122;, + 3;1755,1813,1787;, + 3;2407,2423,2101;, + 3;2422,2408,2415;, + 3;2402,2414,2409;, + 3;2413,2403,2418;, + 3;2419,2417,2404;, + 3;2416,2420,2108;, + 3;2099,2107,2421;, + 3;4160,1840,4161;, + 3;1788,1861,4162;, + 3;1754,1843,4163;, + 3;2102,2096,2406;, + 3;2114,2398,2061;, + 3;2112,2400,2091;, + 3;4164,1873,4165;, + 3;2424,2141,2318;, + 3;1779,1879,1790;, + 3;1756,1790,1879;, + 3;1757,4166,1820;, + 3;1751,1819,4166;, + 3;1825,4167,1827;, + 3;4120,1826,4167;, + 3;1758,1828,1830;, + 3;1748,1829,1828;, + 3;1870,1871,1794;, + 3;1782,1872,1871;, + 3;4121,4168,1847;, + 3;4122,1846,4168;, + 3;1834,1836,1796;, + 3;1759,1835,1753;, + 3;4123,4169,1853;, + 3;4124,1852,4169;, + 3;1761,1864,1866;, + 3;4125,1865,1864;, + 3;4170,1789,1799;, + 3;1766,1799,1789;, + 3;1833,1832,1800;, + 3;1831,1800,1832;, + 3;1824,1822,1801;, + 3;1747,1823,1822;, + 3;4127,4171,1837;, + 3;1750,1837,4171;, + 3;1857,1855,1803;, + 3;4128,1856,1855;, + 3;4154,1781,4172;, + 3;4173,4174,4175;, + 3;1858,1860,1805;, + 3;4129,1859,1786;, + 3;1746,4176,1881;, + 3;1767,1806,1880;, + 3;4149,4177,1807;, + 3;4150,1882,4178;, + 3;4151,1850,1851;, + 3;4152,1849,4179;, + 3;1783,1781,1809;, + 3;4154,1809,1781;, + 3;4155,4180,1868;, + 3;4156,1867,4180;, + 3;1785,4181,1811;, + 3;4157,1811,4181;, + 3;1878,1876,1812;, + 3;4159,1877,1876;, + 3;2410,2426,2405;, + 3;4160,4182,1841;, + 3;4161,1840,4182;, + 3;1788,4183,1862;, + 3;4162,1861,4183;, + 3;1754,4184,1844;, + 3;4163,1843,4184;, + 3;4164,1874,1875;, + 3;4165,1873,4185;, + 3;4186,4187,4188;, + 3;4187,4186,4189;, + 3;4170,1799,1818;, + 3;4187,4189,4190;, + 3;2152,2456,2489;, + 3;2431,2300,2290;, + 3;2156,2126,2435;, + 3;2476,2301,2478;, + 3;2438,2764,2307;, + 3;2501,2485,2296;, + 3;2446,2311,2728;, + 3;2310,2447,2468;, + 3;2155,2436,2473;, + 3;2452,2293,2491;, + 3;2459,2118,2063;, + 3;2150,2465,2428;, + 3;2432,2466,2299;, + 3;2451,2492,2488;, + 3;2467,2448,2298;, + 3;2153,2500,2455;, + 3;2454,2496,2505;, + 3;2453,2506,2292;, + 3;2295,2482,2316;, + 3;2462,2494,2470;, + 3;2493,2463,2487;, + 3;2315,2483,2442;, + 3;2440,2503,2481;, + 3;2502,2441,2484;, + 3;2151,2486,2464;, + 3;2479,2498,2475;, + 3;2497,2480,2504;, + 3;2154,2474,2499;, + 3;2317,2490,2294;, + 3;2507,2366,2354;, + 3;2550,2340,2364;, + 3;2326,2544,2561;, + 3;2345,2519,2517;, + 3;2562,2325,2556;, + 3;2373,2530,2347;, + 3;2568,2324,2563;, + 3;2359,2538,2534;, + 3;2323,2569,2541;, + 3;2535,2380,2358;, + 3;2574,2528,2532;, + 3;2717,2543,2136;, + 3;2620,2599,2606;, + 3;2548,2339,2551;, + 3;2621,2629,2598;, + 3;2508,2555,2365;, + 3;2590,2634,2601;, + 3;2630,2625,2600;, + 3;2613,2589,2612;, + 3;2592,2582,2558;, + 3;2655,2616,2649;, + 3;2615,2656,2654;, + 3;2570,2579,2540;, + 3;2539,2580,2533;, + 3;2583,2567,2557;, + 3;2614,2650,2588;, + 3;2611,2581,2593;, + 3;2610,2594,2602;, + 3;2525,2608,2522;, + 3;2607,2526,2619;, + 3;2514,2596,2511;, + 3;2595,2515,2605;, + 3;2545,2632,2560;, + 3;2631,2546,2624;, + 3;2520,2604,2516;, + 3;2603,2521,2609;, + 3;2564,2645,2573;, + 3;2644,2565,2639;, + 3;2575,2618,2527;, + 3;2617,2576,2648;, + 3;2552,2623,2547;, + 3;2622,2553,2628;, + 3;2509,2627,2554;, + 3;2626,2510,2597;, + 3;2591,2559,2633;, + 3;2661,2647,2577;, + 3;2666,2572,2640;, + 3;2584,2638,2566;, + 3;2683,2676,2671;, + 3;2684,2682,2675;, + 3;2689,2681,2685;, + 3;2680,2690,2697;, + 3;2578,2571,2667;, + 3;2662,2660,2646;, + 3;2657,2687,2653;, + 3;2686,2658,2693;, + 3;2651,2669,2587;, + 3;2668,2652,2688;, + 3;2635,2678,2643;, + 3;2677,2636,2674;, + 3;2641,2695,2665;, + 3;2694,2642,2679;, + 3;2585,2673,2637;, + 3;2672,2586,2670;, + 3;2663,2692,2659;, + 3;2691,2664,2696;, + 3;1819,1791,1821;, + 3;1757,1820,1819;, + 3;2701,2120,2210;, + 3;2119,2702,2139;, + 3;1820,1791,1819;, + 3;1820,1821,1791;, + 3;1819,1821,4166;, + 3;1820,4166,1821;, + 3;1747,1822,4191;, + 3;4126,4191,1822;, + 3;1823,1801,1822;, + 3;1824,1801,1823;, + 3;4126,1822,1824;, + 3;4126,1824,1823;, + 3;4192,4167,1825;, + 3;4192,1825,4120;, + 3;1826,1827,4167;, + 3;1825,1792,1826;, + 3;1825,1827,1792;, + 3;1826,1792,1827;, + 3;1748,1828,4193;, + 3;1758,4193,1828;, + 3;1829,1793,1828;, + 3;1758,1830,1829;, + 3;1830,1793,1829;, + 3;1830,1828,1793;, + 3;4194,1831,4195;, + 3;4195,1831,4196;, + 3;1831,1832,4196;, + 3;4194,4196,1832;, + 3;4194,1832,1833;, + 3;4194,1833,1831;, + 3;4197,1753,1834;, + 3;4197,1834,1759;, + 3;1835,1796,1836;, + 3;1834,1796,1835;, + 3;1835,1836,1753;, + 3;1834,1753,1836;, + 3;1839,1837,1802;, + 3;1750,1838,1837;, + 3;1838,1802,1837;, + 3;1839,1802,1838;, + 3;4127,1837,1839;, + 3;4127,1839,1838;, + 3;1840,1814,1842;, + 3;4160,1841,1840;, + 3;1841,1814,1840;, + 3;1841,1842,1814;, + 3;1840,1842,4182;, + 3;1841,4182,1842;, + 3;1843,1845,4184;, + 3;1754,1844,1843;, + 3;1844,1816,1843;, + 3;1844,4184,1845;, + 3;1844,1845,1816;, + 3;1843,1816,1845;, + 3;1846,1848,4168;, + 3;4121,1847,1846;, + 3;1847,1795,1846;, + 3;1847,4168,1848;, + 3;1847,1848,1795;, + 3;1846,1795,1848;, + 3;1849,1808,1850;, + 3;4151,1851,1849;, + 3;1849,1850,4179;, + 3;4151,4179,1850;, + 3;1851,1808,1849;, + 3;1851,1850,1808;, + 3;1852,1854,4169;, + 3;4123,1853,1852;, + 3;1853,1797,1852;, + 3;1853,4169,1854;, + 3;1853,1854,1797;, + 3;1852,1797,1854;, + 3;4128,1855,4198;, + 3;1765,4198,1855;, + 3;1856,1803,1855;, + 3;1857,1803,1856;, + 3;1765,1855,1857;, + 3;1765,1857,1856;, + 3;4199,1786,1858;, + 3;4199,1858,4129;, + 3;1859,1805,1860;, + 3;1858,1805,1859;, + 3;1859,1860,1786;, + 3;1858,1786,1860;, + 3;1861,1815,1863;, + 3;1788,1862,1861;, + 3;1862,1815,1861;, + 3;1862,1863,1815;, + 3;1861,1863,4183;, + 3;1862,4183,1863;, + 3;4125,1864,4200;, + 3;1761,4200,1864;, + 3;1865,1798,1864;, + 3;1761,1866,1865;, + 3;1866,1798,1865;, + 3;1866,1864,1798;, + 3;1867,1869,4180;, + 3;4155,1868,1867;, + 3;1868,1810,1867;, + 3;1868,4180,1869;, + 3;1868,1869,1810;, + 3;1867,1810,1869;, + 3;4201,1780,1870;, + 3;4201,1870,1782;, + 3;1782,1871,1780;, + 3;1870,1780,1871;, + 3;1872,1794,1871;, + 3;1870,1794,1872;, + 3;1873,1817,1874;, + 3;4164,1875,1873;, + 3;1873,1874,4185;, + 3;4164,4185,1874;, + 3;1875,1817,1873;, + 3;1875,1874,1817;, + 3;4159,1876,4202;, + 3;4158,4202,1876;, + 3;1877,1812,1876;, + 3;1878,1812,1877;, + 3;4158,1876,1878;, + 3;4158,1878,1877;, + 3;1756,1879,4203;, + 3;1779,4203,1879;, + 3;4177,4178,1882;, + 3;1880,1881,4176;, + 3;1746,1881,1806;, + 3;1880,1806,1881;, + 3;4177,1882,1807;, + 3;4150,1807,1882;, + 3;2144,2705,2158;, + 3;2706,2125,2157;, + 3;2699,2201,2713;, + 3;2137,2708,2716;, + 3;2322,2542,2718;, + 3;2321,2719,2334;, + 3;2117,2460,2207;, + 3;2116,2208,2391;, + 3;2306,2759,2756;, + 3;2303,2314,2443;, + 3;2168,2235,2167;, + 3;2445,2729,2747;, + 3;2027,2731,2733;, + 3;2161,2741,2737;, + 3;2162,2283,2740;, + 3;1749,1763,1883;, + 3;2745,2023,2030;, + 3;2313,2304,2751;, + 3;2727,2312,2752;, + 3;2750,2305,2757;, + 3;2761,2722,2233;, + 3;2760,2234,2755;, + 3;2439,2765,2763;, + 3;2766,2721,2762;, + 3;2767,2128,2720;, + 3;4204,1884,4205;, + 3;4206,1885,4207;, + 3;2387,2427,2123;, + 3;1884,4206,4205;, + 3;4204,4206,1884;, + 3;1885,4204,4207;, + 3;4206,4204,1885;, + 3;1910,1887,1921;, + 3;1888,4208,1950;, + 3;1956,4209,1957;, + 3;1889,4210,1960;, + 3;3044,2796,2780;, + 3;2987,3083,2802;, + 3;2001,1913,2003;, + 3;4211,4212,1977;, + 3;1965,1890,1966;, + 3;2839,2838,2896;, + 3;3357,2790,3373;, + 3;3001,3013,3177;, + 3;4213,4214,1983;, + 3;1892,4215,1996;, + 3;1949,1897,1930;, + 3;3369,3366,2788;, + 3;2944,3395,3109;, + 3;2783,3384,2869;, + 3;3385,2825,3400;, + 3;3120,3092,3130;, + 3;1893,1891,1894;, + 3;1901,1902,1903;, + 3;2870,2039,2017;, + 3;3116,2866,2849;, + 3;3399,2816,3405;, + 3;2843,2888,2832;, + 3;2048,2049,2846;, + 3;2821,2943,2887;, + 3;2744,2031,2941;, + 3;3379,2834,2868;, + 3;2850,2055,2045;, + 3;2842,2826,2854;, + 3;2841,2855,2046;, + 3;2847,2836,2047;, + 3;2867,2835,2848;, + 3;2769,2069,2057;, + 3;2844,2067,3119;, + 3;2080,2071,2852;, + 3;2837,2840,2047;, + 3;2851,2072,2054;, + 3;2845,2050,2066;, + 3;2827,2079,2853;, + 3;2856,2861,3360;, + 3;3368,2781,2858;, + 3;2777,2863,3054;, + 3;2857,2782,2860;, + 3;1964,1962,1931;, + 3;2878,2877,2018;, + 3;2828,2089,2078;, + 3;2871,2033,2038;, + 3;2085,2882,2019;, + 3;2940,2032,2872;, + 3;3380,2895,2833;, + 3;2912,2901,2938;, + 3;2917,2926,2935;, + 3;2907,2916,2932;, + 3;2902,2921,2936;, + 3;2922,2931,2934;, + 3;2820,2883,2904;, + 3;2905,2898,2819;, + 3;2831,2889,2914;, + 3;2915,2908,2830;, + 3;2876,2879,2924;, + 3;2925,2918,2875;, + 3;2088,2829,2909;, + 3;2910,2928,2087;, + 3;2881,2086,2929;, + 3;2930,2923,2880;, + 3;2885,2874,2919;, + 3;2920,2903,2884;, + 3;2891,2818,2899;, + 3;2900,2913,2890;, + 3;2933,2927,2911;, + 3;2937,2897,2906;, + 3;2824,3386,2735;, + 3;2886,2939,2873;, + 3;2799,3090,2815;, + 3;2953,2947,3104;, + 3;2800,2945,3089;, + 3;2965,3154,3126;, + 3;3093,3415,2785;, + 3;3131,2964,3096;, + 3;3136,3103,2962;, + 3;3388,3393,2025;, + 3;4216,4217,1954;, + 3;1900,1901,3417;, + 3;4218,4219,1969;, + 3;2014,1893,1894;, + 3;1896,4220,1987;, + 3;1895,1915,1935;, + 3;1989,4221,1990;, + 3;1908,1894,1891;, + 3;1749,1894,1752;, + 3;1746,1898,1937;, + 3;3417,1906,1899;, + 3;1902,1901,1900;, + 3;4222,4223,4224;, + 3;1909,4225,4226;, + 3;4135,4137,4227;, + 3;4227,4228,4135;, + 3;4137,4229,4230;, + 3;4230,4227,4137;, + 3;4231,4232,1904;, + 3;1907,4230,4229;, + 3;1905,4226,4225;, + 3;4233,1904,4232;, + 3;4223,4135,4228;, + 3;4228,4224,4223;, + 3;4232,1905,4233;, + 3;1906,3417,4234;, + 3;4225,4233,1905;, + 3;1904,1907,4231;, + 3;4235,1900,3417;, + 3;2801,1908,1891;, + 3;4229,4231,1907;, + 3;4235,3417,1899;, + 3;4224,1909,4222;, + 3;4236,4237,1938;, + 3;4226,4222,1909;, + 3;3374,2989,3371;, + 3;2975,3208,3000;, + 3;4238,4239,1980;, + 3;2802,3364,2991;, + 3;3370,2990,3365;, + 3;3183,3006,3182;, + 3;1914,4240,1940;, + 3;2982,2996,2805;, + 3;2995,2986,3011;, + 3;3012,3002,2994;, + 3;3021,2804,2997;, + 3;3024,3010,2983;, + 3;3033,2993,3003;, + 3;3028,3195,3043;, + 3;3196,2793,3017;, + 3;4241,4242,1998;, + 3;2984,3019,3023;, + 3;3176,3008,3171;, + 3;2803,3022,3020;, + 3;3194,3029,3185;, + 3;3004,3031,3037;, + 3;1916,4243,1942;, + 3;3046,3035,3039;, + 3;3041,3016,2794;, + 3;3038,3036,3032;, + 3;2795,3045,3040;, + 3;4244,4245,2008;, + 3;2992,3034,3047;, + 3;3051,3059,2093;, + 3;3052,2773,3058;, + 3;2110,3056,2059;, + 3;3050,2094,3070;, + 3;3064,2776,3049;, + 3;1886,1918,1944;, + 3;3068,2104,3080;, + 3;3081,3071,3067;, + 3;3060,3066,3072;, + 3;3073,3074,3063;, + 3;3077,3062,3075;, + 3;3076,2105,3079;, + 3;2100,3078,2106;, + 3;4246,4247,1971;, + 3;1919,4248,1992;, + 3;4249,4250,1974;, + 3;2103,3069,2095;, + 3;2774,2058,3057;, + 3;2111,2092,3055;, + 3;4251,4252,2004;, + 3;3082,2974,4253;, + 3;1910,1921,2010;, + 3;1887,2010,1921;, + 3;1888,1951,4254;, + 3;4208,4254,1950;, + 3;1956,1958,4255;, + 3;4209,4255,1957;, + 3;1889,1961,1959;, + 3;4210,1959,1960;, + 3;2001,1925,2002;, + 3;1913,2002,2003;, + 3;4211,1978,4256;, + 3;4212,4256,1977;, + 3;1965,1927,1967;, + 3;1890,4257,1966;, + 3;4213,1984,4258;, + 3;4214,4258,1983;, + 3;1892,1997,1995;, + 3;4215,1995,1996;, + 3;4259,1930,1920;, + 3;1897,1920,1930;, + 3;1964,1931,1963;, + 3;1962,1963,1931;, + 3;1955,1932,1953;, + 3;4217,1953,1954;, + 3;4218,1968,4260;, + 3;4219,4260,1968;, + 3;1988,1934,1986;, + 3;4220,1986,1987;, + 3;4240,4261,1912;, + 3;3018,2985,3084;, + 3;1989,1936,1991;, + 3;4221,1917,1990;, + 3;1746,2012,4176;, + 3;1898,2011,1937;, + 3;4236,1938,4262;, + 3;4237,4178,2013;, + 3;4238,1982,1981;, + 3;4239,4263,1980;, + 3;1914,1940,1912;, + 3;4240,1912,1940;, + 3;4241,1999,4264;, + 3;4242,4264,1998;, + 3;1916,1942,4265;, + 3;4243,4265,1942;, + 3;2009,1943,2007;, + 3;4245,2007,2008;, + 3;3065,3061,3086;, + 3;4246,1972,4266;, + 3;4247,4266,1971;, + 3;1919,1993,4267;, + 3;4248,4267,1992;, + 3;4249,1975,4268;, + 3;4250,4268,1974;, + 3;4251,2006,2005;, + 3;4252,4269,2004;, + 3;4270,4271,4272;, + 3;4272,4273,4270;, + 3;4259,1949,1930;, + 3;4272,4274,4273;, + 3;2812,3148,3115;, + 3;3088,2946,2954;, + 3;2808,3098,2786;, + 3;3132,3140,2963;, + 3;3095,2957,3411;, + 3;3160,2952,3144;, + 3;3107,3390,2972;, + 3;2973,3127,3106;, + 3;2809,3135,3097;, + 3;3113,3152,2950;, + 3;3118,2068,2770;, + 3;2814,3091,3121;, + 3;3087,2955,3129;, + 3;3114,3145,3151;, + 3;3128,2956,3105;, + 3;2811,3110,3159;, + 3;3111,3162,3158;, + 3;3112,2951,3161;, + 3;2948,2967,3143;, + 3;3124,3125,3149;, + 3;3150,3146,3123;, + 3;2968,3100,3142;, + 3;3102,3137,3164;, + 3;3165,3141,3101;, + 3;2813,3122,3147;, + 3;3139,3133,3156;, + 3;3157,3163,3138;, + 3;2810,3155,3134;, + 3;2966,2949,3153;, + 3;3170,3009,3025;, + 3;3209,3027,2998;, + 3;2976,3220,3207;, + 3;3007,3172,3181;, + 3;3221,3219,2977;, + 3;3030,3005,3184;, + 3;3227,3226,2978;, + 3;3014,3191,3202;, + 3;2979,3199,3232;, + 3;3190,3015,3042;, + 3;3233,3193,3186;, + 3;3377,2792,3197;, + 3;3279,3265,3258;, + 3;3203,3214,2999;, + 3;3284,3254,3288;, + 3;3169,3026,3210;, + 3;3249,3263,3293;, + 3;3292,3264,3280;, + 3;3272,3271,3248;, + 3;3252,3217,3246;, + 3;3314,3308,3276;, + 3;3277,3313,3319;, + 3;3231,3200,3235;, + 3;3201,3192,3234;, + 3;3245,3218,3222;, + 3;3278,3240,3312;, + 3;3266,3251,3247;, + 3;3267,3262,3250;, + 3;3189,3178,3269;, + 3;3270,3273,3188;, + 3;3175,3166,3256;, + 3;3257,3259,3174;, + 3;3206,3215,3290;, + 3;3291,3281,3205;, + 3;3180,3173,3260;, + 3;3261,3268,3179;, + 3;3225,3228,3304;, + 3;3299,3298,3224;, + 3;3239,3187,3274;, + 3;3275,3305,3238;, + 3;3213,3204,3282;, + 3;3283,3285,3212;, + 3;3168,3211,3286;, + 3;3287,3255,3167;, + 3;3253,3289,3216;, + 3;3320,3237,3306;, + 3;3322,3303,3229;, + 3;3244,3223,3294;, + 3;3342,3330,3335;, + 3;3347,3331,3341;, + 3;3348,3346,3336;, + 3;3337,3356,3352;, + 3;3236,3321,3230;, + 3;3326,3307,3315;, + 3;3318,3309,3344;, + 3;3345,3349,3317;, + 3;3311,3241,3328;, + 3;3329,3343,3310;, + 3;3297,3300,3339;, + 3;3340,3332,3296;, + 3;3302,3323,3354;, + 3;3355,3338,3301;, + 3;3243,3295,3333;, + 3;3334,3327,3242;, + 3;3325,3316,3350;, + 3;3351,3353,3324;, + 3;1950,1952,1922;, + 3;1888,1950,1951;, + 3;3359,2862,2778;, + 3;2779,2789,3358;, + 3;1951,1950,1922;, + 3;1951,1922,1952;, + 3;1950,4254,1952;, + 3;1951,1952,4254;, + 3;4217,4275,1953;, + 3;4216,1953,4275;, + 3;1954,1953,1932;, + 3;1955,1954,1932;, + 3;4216,1955,1953;, + 3;4216,1954,1955;, + 3;4276,1956,4255;, + 3;4276,4209,1956;, + 3;1957,4255,1958;, + 3;1956,1957,1923;, + 3;1956,1923,1958;, + 3;1957,1958,1923;, + 3;4210,4277,1959;, + 3;1889,1959,4277;, + 3;1960,1959,1924;, + 3;1889,1960,1961;, + 3;1961,1960,1924;, + 3;1961,1924,1959;, + 3;4278,4279,1962;, + 3;4279,4280,1962;, + 3;1962,4280,1963;, + 3;4278,1963,4280;, + 3;4278,1964,1963;, + 3;4278,1962,1964;, + 3;4281,1965,4257;, + 3;4281,1890,1965;, + 3;1966,1967,1927;, + 3;1965,1966,1927;, + 3;1966,4257,1967;, + 3;1965,1967,4257;, + 3;1970,1933,1968;, + 3;4219,1968,1969;, + 3;1969,1968,1933;, + 3;1970,1969,1933;, + 3;4218,1970,1968;, + 3;4218,1969,1970;, + 3;1971,1973,1945;, + 3;4246,1971,1972;, + 3;1972,1971,1945;, + 3;1972,1945,1973;, + 3;1971,4266,1973;, + 3;1972,1973,4266;, + 3;1974,4268,1976;, + 3;4249,1974,1975;, + 3;1975,1974,1947;, + 3;1975,1976,4268;, + 3;1975,1947,1976;, + 3;1974,1976,1947;, + 3;1977,4256,1979;, + 3;4211,1977,1978;, + 3;1978,1977,1926;, + 3;1978,1979,4256;, + 3;1978,1926,1979;, + 3;1977,1979,1926;, + 3;1980,1981,1939;, + 3;4238,1980,1982;, + 3;1980,4263,1981;, + 3;4238,1981,4263;, + 3;1982,1980,1939;, + 3;1982,1939,1981;, + 3;1983,4258,1985;, + 3;4213,1983,1984;, + 3;1984,1983,1928;, + 3;1984,1985,4258;, + 3;1984,1928,1985;, + 3;1983,1985,1928;, + 3;4220,4282,1986;, + 3;1896,1986,4282;, + 3;1987,1986,1934;, + 3;1988,1987,1934;, + 3;1896,1988,1986;, + 3;1896,1987,1988;, + 3;4283,1989,1917;, + 3;4283,4221,1989;, + 3;1990,1991,1936;, + 3;1989,1990,1936;, + 3;1990,1917,1991;, + 3;1989,1991,1917;, + 3;1992,1994,1946;, + 3;1919,1992,1993;, + 3;1993,1992,1946;, + 3;1993,1946,1994;, + 3;1992,4267,1994;, + 3;1993,1994,4267;, + 3;4215,4284,1995;, + 3;1892,1995,4284;, + 3;1996,1995,1929;, + 3;1892,1996,1997;, + 3;1997,1996,1929;, + 3;1997,1929,1995;, + 3;1998,4264,2000;, + 3;1915,4285,4286;, + 3;1999,1998,1941;, + 3;1999,2000,4264;, + 3;1999,1941,2000;, + 3;1998,2000,1941;, + 3;4287,2001,1911;, + 3;4287,1913,2001;, + 3;1913,1911,2002;, + 3;2001,2002,1911;, + 3;2003,2002,1925;, + 3;2001,2003,1925;, + 3;2004,2005,1948;, + 3;4251,2004,2006;, + 3;2004,4269,2005;, + 3;4251,2005,4269;, + 3;2006,2004,1948;, + 3;2006,1948,2005;, + 3;4245,4288,2007;, + 3;4244,2007,4288;, + 3;2008,2007,1943;, + 3;2009,2008,1943;, + 3;4244,2009,2007;, + 3;4244,2008,2009;, + 3;1887,4289,2010;, + 3;1910,2010,4289;, + 3;4262,2013,4178;, + 3;2011,4176,2012;, + 3;1746,1937,2012;, + 3;2011,2012,1937;, + 3;4262,1938,2013;, + 3;4237,2013,1938;, + 3;2798,2806,3363;, + 3;3362,2807,2787;, + 3;3361,3367,2859;, + 3;2791,3378,3372;, + 3;2980,3376,3198;, + 3;2981,2988,3375;, + 3;2771,2865,3117;, + 3;2772,3053,2864;, + 3;2958,3402,3410;, + 3;2961,3099,2969;, + 3;2893,2817,2892;, + 3;3108,3392,3389;, + 3;2026,2734,3387;, + 3;2823,2736,2742;, + 3;2822,2743,2942;, + 3;1749,2014,1894;, + 3;3394,2029,2024;, + 3;2970,3397,2960;, + 3;3391,3396,2971;, + 3;3398,3401,2959;, + 3;3408,2894,3381;, + 3;3409,3403,2893;, + 3;3094,3406,3414;, + 3;3413,3407,3382;, + 3;3412,3383,2784;, + 3;4290,4291,2015;, + 3;4292,4293,2016;, + 3;3048,2775,3085;, + 3;2015,4291,4294;, + 3;4290,2015,4294;, + 3;2016,4293,4295;, + 3;4292,2016,4295;, + 3;2017,2040,2022;, + 3;2017,2039,2040;, + 3;2018,2870,2017;, + 3;2018,2877,2870;, + 3;2019,2878,2018;, + 3;2019,2882,2878;, + 3;2020,2085,2019;, + 3;2020,2084,2085;, + 3;2021,2223,2020;, + 3;2021,2222,2223;, + 3;2022,2215,2021;, + 3;2022,2214,2215;, + 3;2019,2017,2020;, + 3;2020,2017,2022;, + 3;2020,2022,2021;, + 3;2017,2019,2018;, + 3;2023,2746,2028;, + 3;2023,2745,2746;, + 3;2024,2030,2023;, + 3;2024,2029,2030;, + 3;2025,3394,2024;, + 3;2025,3393,3394;, + 3;2026,3388,2025;, + 3;2026,3387,3388;, + 3;2027,2734,2026;, + 3;2027,2733,2734;, + 3;2028,2731,2027;, + 3;2028,2730,2731;, + 3;2025,2028,2026;, + 3;2026,2028,2027;, + 3;2028,2025,2024;, + 3;2028,2024,2023;, + 3;2029,2014,1749;, + 3;2029,3394,2014;, + 3;1749,2745,2030;, + 3;1749,1883,2745;, + 3;1749,2030,2029;, + 3;2031,2739,2036;, + 3;2031,2744,2739;, + 3;2032,2941,2031;, + 3;2032,2940,2941;, + 3;2033,2872,2032;, + 3;2033,2871,2872;, + 3;2034,2038,2033;, + 3;2034,2037,2038;, + 3;2035,2221,2034;, + 3;2035,2220,2221;, + 3;2036,2285,2035;, + 3;2036,2284,2285;, + 3;2031,2036,2034;, + 3;2031,2034,2033;, + 3;2031,2033,2032;, + 3;2034,2036,2035;, + 3;2037,2214,2040;, + 3;2037,2221,2214;, + 3;2039,2871,2038;, + 3;2039,2870,2871;, + 3;2039,2038,2040;, + 3;2040,2038,2037;, + 3;2041,2049,2048;, + 3;2041,2052,2049;, + 3;2042,2190,2041;, + 3;2042,2189,2190;, + 3;2042,2177,2178;, + 3;2043,2187,2042;, + 3;2043,2186,2187;, + 3;2044,2195,2043;, + 3;2044,2194,2195;, + 3;2045,2056,2044;, + 3;2045,2055,2056;, + 3;2046,2850,2045;, + 3;2046,2855,2850;, + 3;2047,2841,2046;, + 3;2047,2840,2841;, + 3;2047,2836,2837;, + 3;2048,2847,2047;, + 3;2048,2846,2847;, + 3;2045,2044,2048;, + 3;2045,2048,2046;, + 3;2046,2048,2047;, + 3;2048,2044,2041;, + 3;2041,2044,2043;, + 3;2041,2043,2042;, + 3;2050,2846,2049;, + 3;2050,2845,2846;, + 3;2051,2066,2050;, + 3;2051,2065,2066;, + 3;2052,2191,2051;, + 3;2052,2190,2191;, + 3;2050,2049,2051;, + 3;2051,2049,2052;, + 3;2053,2194,2056;, + 3;2053,2199,2194;, + 3;2054,2073,2053;, + 3;2054,2072,2073;, + 3;2055,2851,2054;, + 3;2055,2850,2851;, + 3;2055,2054,2056;, + 3;2056,2054,2053;, + 3;2057,2070,2062;, + 3;2057,2069,2070;, + 3;2058,2769,2057;, + 3;2058,2774,2769;, + 3;2059,3057,2058;, + 3;2059,3056,3057;, + 3;2060,2110,2059;, + 3;2060,2109,2110;, + 3;2061,2399,2060;, + 3;2061,2398,2399;, + 3;2062,2114,2061;, + 3;2062,2113,2114;, + 3;2057,2062,2058;, + 3;2058,2062,2061;, + 3;2058,2061,2059;, + 3;2059,2061,2060;, + 3;2063,2113,2070;, + 3;2063,2118,2113;, + 3;2064,2459,2063;, + 3;2064,2458,2459;, + 3;2065,2192,2064;, + 3;2065,2191,2192;, + 3;2067,2845,2066;, + 3;2067,2844,2845;, + 3;2068,3119,2067;, + 3;2068,3118,3119;, + 3;2069,2770,2068;, + 3;2069,2769,2770;, + 3;2066,2065,2069;, + 3;2066,2069,2068;, + 3;2066,2068,2067;, + 3;2069,2065,2070;, + 3;2070,2065,2063;, + 3;2063,2065,2064;, + 3;2071,2075,2074;, + 3;2071,2080,2075;, + 3;2072,2852,2071;, + 3;2072,2851,2852;, + 3;2074,2199,2073;, + 3;2074,2198,2199;, + 3;2072,2071,2073;, + 3;2073,2071,2074;, + 3;2076,2198,2075;, + 3;2076,2197,2198;, + 3;2077,2174,2076;, + 3;2077,2173,2174;, + 3;2078,2090,2077;, + 3;2078,2089,2090;, + 3;2079,2828,2078;, + 3;2079,2827,2828;, + 3;2080,2853,2079;, + 3;2080,2852,2853;, + 3;2078,2077,2079;, + 3;2079,2077,2076;, + 3;2079,2076,2080;, + 3;2080,2076,2075;, + 3;2081,2173,2090;, + 3;2081,2172,2173;, + 3;2082,2254,2081;, + 3;2082,2253,2254;, + 3;2083,2273,2082;, + 3;2083,2272,2273;, + 3;2084,2224,2083;, + 3;2084,2223,2224;, + 3;2086,2882,2085;, + 3;2086,2881,2882;, + 3;2087,2929,2086;, + 3;2087,2928,2929;, + 3;2088,2910,2087;, + 3;2088,2909,2910;, + 3;2089,2829,2088;, + 3;2089,2828,2829;, + 3;2085,2084,2090;, + 3;2085,2090,2089;, + 3;2085,2089,2086;, + 3;2086,2089,2087;, + 3;2087,2089,2088;, + 3;2090,2084,2083;, + 3;2090,2083,2082;, + 3;2090,2082,2081;, + 3;2091,2401,2098;, + 3;2091,2400,2401;, + 3;2092,2112,2091;, + 3;2092,2111,2112;, + 3;2093,3055,2092;, + 3;2093,3059,3055;, + 3;4296,3051,2093;, + 3;4296,4297,3051;, + 3;4298,3070,2094;, + 3;4298,4299,3070;, + 3;2096,2103,2095;, + 3;2096,2102,2103;, + 3;2097,4300,4301;, + 3;2097,2412,4300;, + 3;2098,4302,4303;, + 3;2098,2393,4302;, + 3;4304,4305,4298;, + 3;4304,4298,2094;, + 3;4298,4305,4301;, + 3;4301,4305,2097;, + 3;2098,2093,2092;, + 3;2098,2092,2091;, + 3;2099,4306,4307;, + 3;2099,2421,4306;, + 3;2100,2107,2099;, + 3;2100,2106,2107;, + 3;4307,3078,2100;, + 3;4307,4308,3078;, + 3;4307,2100,2099;, + 3;2101,21,8;, + 3;2101,2423,21;, + 3;2102,2407,2101;, + 3;2102,2406,2407;, + 3;2104,3069,2103;, + 3;2104,3068,3069;, + 3;8,3080,2104;, + 3;8,151,3080;, + 3;8,2102,2101;, + 3;8,2103,2102;, + 3;8,2104,2103;, + 3;2105,4309,4310;, + 3;2105,3076,4309;, + 3;2106,3079,2105;, + 3;2106,3078,3079;, + 3;2108,2421,2107;, + 3;2108,2420,2421;, + 3;4310,2416,2108;, + 3;4310,4311,2416;, + 3;4310,2106,2105;, + 3;4310,2107,2106;, + 3;4310,2108,2107;, + 3;4312,2400,2112;, + 3;4312,4313,2400;, + 3;2111,4314,4315;, + 3;2111,3055,4314;, + 3;4315,4312,2111;, + 3;2111,4312,2112;, + 3;4316,2398,2114;, + 3;2115,2397,4317;, + 3;2116,2392,2115;, + 3;2116,2391,2392;, + 3;2117,4318,4319;, + 3;2117,2207,4318;, + 3;2118,2460,2117;, + 3;2118,2459,2460;, + 3;2114,2118,2117;, + 3;2114,2117,4316;, + 3;4316,2117,4319;, + 3;2118,2114,2113;, + 3;2119,4320,4321;, + 3;2119,2139,4320;, + 3;2120,2702,2119;, + 3;2120,2701,2702;, + 3;2121,2210,2120;, + 3;2121,2209,2210;, + 3;4322,2396,2121;, + 3;4322,4323,2396;, + 3;1755,2411,2122;, + 3;1755,1787,2411;, + 3;2123,1813,1755;, + 3;2123,2427,1813;, + 3;2124,2387,2123;, + 3;2124,2386,2387;, + 3;1755,2124,2123;, + 3;4324,2119,4321;, + 3;4324,2120,2119;, + 3;4324,2121,2120;, + 3;4324,4322,2121;, + 3;2125,4325,4326;, + 3;2125,2706,4325;, + 3;2126,2157,2125;, + 3;2126,2156,2157;, + 3;2127,2435,2126;, + 3;2127,2434,2435;, + 3;2128,2768,2127;, + 3;2128,2767,2768;, + 3;2129,2720,2128;, + 3;2129,2725,2720;, + 3;2130,2213,2129;, + 3;2130,2212,2213;, + 3;4327,2203,2130;, + 3;2131,2202,4328;, + 3;2132,2712,2131;, + 3;2132,2711,2712;, + 3;4326,2127,2126;, + 3;4326,2126,2125;, + 3;2127,4326,4327;, + 3;2127,4327,2128;, + 3;2128,4327,2130;, + 3;2128,2130,2129;, + 3;2133,4329,4320;, + 3;2133,2390,4329;, + 3;2134,2382,2133;, + 3;2134,2381,2382;, + 3;2135,2357,2134;, + 3;2135,2360,2357;, + 3;2136,2537,2135;, + 3;2136,2543,2537;, + 3;2137,2717,2136;, + 3;2137,2716,2717;, + 3;2138,2708,2137;, + 3;2138,2714,2708;, + 3;2139,2698,2138;, + 3;2139,2702,2698;, + 3;2134,2133,2135;, + 3;2135,2133,4320;, + 3;2135,4320,2136;, + 3;2136,4320,2139;, + 3;2136,2139,2137;, + 3;2137,2139,2138;, + 3;2141,2425,2146;, + 3;2141,2424,2425;, + 3;2141,4146,2318;, + 3;4330,1760,1777;, + 3;2142,1762,1760;, + 3;2142,2291,1762;, + 3;2143,2430,2142;, + 3;2143,2429,2430;, + 3;2144,2159,2143;, + 3;2144,2158,2159;, + 3;2145,2705,2144;, + 3;2145,2704,2705;, + 3;2146,2331,4331;, + 3;2146,2330,2331;, + 3;1760,2143,2142;, + 3;1760,2144,2143;, + 3;1760,2145,2144;, + 3;1760,4330,2145;, + 3;2145,4330,4153;, + 3;2147,4332,4333;, + 3;2147,2320,4332;, + 3;2148,2342,2147;, + 3;2148,2341,2342;, + 3;2149,2363,2148;, + 3;2149,2369,2363;, + 3;4333,2361,2149;, + 3;4333,4173,2361;, + 3;4333,2148,2147;, + 3;4333,2149,2148;, + 3;2150,2429,2159;, + 3;2150,2428,2429;, + 3;2151,2465,2150;, + 3;2151,2464,2465;, + 3;2152,4334,4335;, + 3;2152,2489,4334;, + 3;2153,2456,2152;, + 3;2153,2455,2456;, + 3;4336,2500,2153;, + 3;4336,4337,2500;, + 3;2155,2474,2154;, + 3;2155,2473,2474;, + 3;2156,2436,2155;, + 3;2156,2435,2436;, + 3;2158,2706,2157;, + 3;2158,2705,2706;, + 3;2158,2154,4338;, + 3;2158,4338,4339;, + 3;2158,4339,2151;, + 3;2158,2151,2150;, + 3;2158,2150,2159;, + 3;2154,2158,2155;, + 3;2155,2158,2157;, + 3;2155,2157,2156;, + 3;2160,2726,2169;, + 3;2160,2732,2726;, + 3;2161,2738,2160;, + 3;2161,2737,2738;, + 3;2162,2741,2161;, + 3;2162,2740,2741;, + 3;2163,2283,2162;, + 3;2163,2287,2283;, + 3;2164,2231,2163;, + 3;2164,2230,2231;, + 3;2165,2249,2164;, + 3;2165,2248,2249;, + 3;2166,2243,2165;, + 3;2166,2242,2243;, + 3;2167,2236,2166;, + 3;2167,2235,2236;, + 3;2168,2754,2235;, + 3;2168,2758,2754;, + 3;2169,2749,2168;, + 3;2169,2753,2749;, + 3;2167,2165,2164;, + 3;2167,2164,2163;, + 3;2167,2163,2168;, + 3;2168,2163,2162;, + 3;2168,2162,2169;, + 3;2169,2162,2161;, + 3;2169,2161,2160;, + 3;2165,2167,2166;, + 3;2170,2239,2176;, + 3;2170,2238,2239;, + 3;2171,2259,2170;, + 3;2171,2258,2259;, + 3;2172,2255,2171;, + 3;2172,2254,2255;, + 3;2175,2197,2174;, + 3;2175,2196,2197;, + 3;2176,2185,2175;, + 3;2176,2184,2185;, + 3;2171,2176,2172;, + 3;2172,2176,2174;, + 3;2172,2174,2173;, + 3;2174,2176,2175;, + 3;2176,2171,2170;, + 3;2177,2183,2182;, + 3;2177,2187,2183;, + 3;2179,2189,2178;, + 3;2179,2188,2189;, + 3;2180,2205,2179;, + 3;2180,2204,2205;, + 3;2181,2724,2180;, + 3;2181,2723,2724;, + 3;2182,2232,2181;, + 3;2182,2240,2232;, + 3;2179,2178,2180;, + 3;2180,2178,2177;, + 3;2180,2177,2182;, + 3;2180,2182,2181;, + 3;2184,2240,2183;, + 3;2184,2239,2240;, + 3;2186,2196,2185;, + 3;2186,2195,2196;, + 3;2185,2187,2186;, + 3;2187,2185,2183;, + 3;2183,2185,2184;, + 3;2188,2206,2193;, + 3;2188,2205,2206;, + 3;2193,2458,2192;, + 3;2193,2457,2458;, + 3;2189,2193,2192;, + 3;2189,2192,2190;, + 3;2190,2192,2191;, + 3;2193,2189,2188;, + 3;2199,2195,2194;, + 3;2195,2199,2198;, + 3;2195,2198,2197;, + 3;2195,2197,2196;, + 3;2200,2211,4328;, + 3;2203,4340,2212;, + 3;2201,2700,2200;, + 3;2201,2699,2700;, + 3;2202,2713,2201;, + 3;2202,2712,2713;, + 3;4328,2201,2200;, + 3;2201,4328,2202;, + 3;2204,2725,2213;, + 3;2204,2724,2725;, + 3;2207,2457,2206;, + 3;2207,2460,2457;, + 3;2209,2391,2208;, + 3;2209,2396,2391;, + 3;2211,2701,2210;, + 3;2211,2700,2701;, + 3;2205,2207,2206;, + 3;2207,2205,2204;, + 3;2207,2204,4318;, + 3;4318,2204,4340;, + 3;2208,2211,2209;, + 3;2209,2211,2210;, + 3;4340,2204,2212;, + 3;2212,2204,2213;, + 3;2216,2222,2215;, + 3;2216,2226,2222;, + 3;2217,2267,2216;, + 3;2217,2266,2267;, + 3;2218,2265,2217;, + 3;2218,2264,2265;, + 3;2219,2228,2218;, + 3;2219,2227,2228;, + 3;2220,2286,2219;, + 3;2220,2285,2286;, + 3;2218,2216,2219;, + 3;2219,2216,2220;, + 3;2220,2216,2215;, + 3;2220,2215,2221;, + 3;2221,2215,2214;, + 3;2216,2218,2217;, + 3;2225,2272,2224;, + 3;2225,2271,2272;, + 3;2226,2268,2225;, + 3;2226,2267,2268;, + 3;2222,2226,2225;, + 3;2222,2225,2224;, + 3;2222,2224,2223;, + 3;2227,2287,2231;, + 3;2227,2286,2287;, + 3;2229,2264,2228;, + 3;2229,2263,2264;, + 3;2230,2250,2229;, + 3;2230,2249,2250;, + 3;2227,2231,2228;, + 3;2228,2231,2229;, + 3;2229,2231,2230;, + 3;2233,2723,2232;, + 3;2233,2722,2723;, + 3;2234,2761,2233;, + 3;2234,2760,2761;, + 3;2235,2754,2234;, + 3;2234,2754,2755;, + 3;2237,2242,2236;, + 3;2237,2241,2242;, + 3;2238,2260,2237;, + 3;2238,2259,2260;, + 3;2237,2236,2238;, + 3;2238,2236,2235;, + 3;2238,2235,2239;, + 3;2239,2235,2234;, + 3;2239,2234,2232;, + 3;2239,2232,2240;, + 3;2232,2234,2233;, + 3;2241,2256,2245;, + 3;2241,2260,2256;, + 3;2244,2248,2243;, + 3;2244,2247,2248;, + 3;2245,2276,2244;, + 3;2245,2282,2276;, + 3;2242,2241,2243;, + 3;2243,2241,2244;, + 3;2244,2241,2245;, + 3;2246,2263,2250;, + 3;2246,2262,2263;, + 3;2247,2277,2246;, + 3;2247,2276,2277;, + 3;2246,2250,2247;, + 3;2247,2250,2249;, + 3;2247,2249,2248;, + 3;2251,2258,2255;, + 3;2251,2257,2258;, + 3;2252,2281,2251;, + 3;2252,2280,2281;, + 3;2253,2274,2252;, + 3;2253,2273,2274;, + 3;2255,2252,2251;, + 3;2252,2255,2254;, + 3;2252,2254,2253;, + 3;2257,2282,2256;, + 3;2257,2281,2282;, + 3;2257,2259,2258;, + 3;2259,2257,2256;, + 3;2259,2256,2260;, + 3;2261,2266,2265;, + 3;2261,2270,2266;, + 3;2262,2278,2261;, + 3;2262,2277,2278;, + 3;2265,2263,2262;, + 3;2265,2262,2261;, + 3;2263,2265,2264;, + 3;2269,2271,2268;, + 3;2269,2275,2271;, + 3;2270,2279,2269;, + 3;2270,2278,2279;, + 3;2270,2269,2268;, + 3;2270,2268,2266;, + 3;2266,2268,2267;, + 3;2275,2280,2274;, + 3;2275,2279,2280;, + 3;2275,2273,2271;, + 3;2271,2273,2272;, + 3;2273,2275,2274;, + 3;2279,2278,2280;, + 3;2280,2278,2282;, + 3;2280,2282,2281;, + 3;2282,2278,2276;, + 3;2276,2278,2277;, + 3;2284,2740,2283;, + 3;2284,2739,2740;, + 3;2286,2283,2287;, + 3;2283,2286,2285;, + 3;2283,2285,2284;, + 3;2288,1883,1762;, + 3;2288,2748,1883;, + 3;2289,2450,2288;, + 3;2289,2449,2450;, + 3;2290,2297,2289;, + 3;2290,2300,2297;, + 3;2291,2431,2290;, + 3;2291,2430,2431;, + 3;1762,2289,2288;, + 3;1762,2290,2289;, + 3;1762,2291,2290;, + 3;2292,2501,2296;, + 3;2292,2506,2501;, + 3;2293,2453,2292;, + 3;2293,2452,2453;, + 3;2294,2491,2293;, + 3;2294,2490,2491;, + 3;2295,2317,2294;, + 3;2295,2316,2317;, + 3;2296,2482,2295;, + 3;2296,2485,2482;, + 3;2293,2296,2294;, + 3;2294,2296,2295;, + 3;2296,2293,2292;, + 3;2298,2449,2297;, + 3;2298,2448,2449;, + 3;2299,2467,2298;, + 3;2299,2466,2467;, + 3;2300,2432,2299;, + 3;2300,2431,2432;, + 3;2297,2299,2298;, + 3;2299,2297,2300;, + 3;2301,2472,2308;, + 3;2301,2476,2472;, + 3;2302,2478,2301;, + 3;2302,2477,2478;, + 3;2303,2444,2302;, + 3;2303,2443,2444;, + 3;2304,2314,2303;, + 3;2304,2313,2314;, + 3;2305,2751,2304;, + 3;2305,2750,2751;, + 3;2306,2757,2305;, + 3;2306,2756,2757;, + 3;2307,2759,2306;, + 3;2307,2764,2759;, + 3;2308,2438,2307;, + 3;2308,2437,2438;, + 3;2306,2302,2307;, + 3;2307,2302,2301;, + 3;2307,2301,2308;, + 3;2302,2306,2305;, + 3;2302,2305,2304;, + 3;2302,2304,2303;, + 3;4341,2490,2317;, + 3;4341,4342,2490;, + 3;2310,2469,2309;, + 3;2310,2468,2469;, + 3;2311,2447,2310;, + 3;2311,2446,2447;, + 3;2312,2728,2311;, + 3;2312,2727,2728;, + 3;2313,2752,2312;, + 3;2313,2751,2752;, + 3;2315,2443,2314;, + 3;2315,2442,2443;, + 3;4343,2483,2315;, + 3;2316,2482,4344;, + 3;2312,2315,2314;, + 3;2312,2314,2313;, + 3;2315,2312,2311;, + 3;2315,2311,4343;, + 3;4343,2311,2310;, + 3;2316,4345,2317;, + 3;2317,4345,4341;, + 3;4146,2424,2318;, + 3;4146,4346,2424;, + 3;2319,2544,2326;, + 3;2319,2549,2544;, + 3;2320,2343,2319;, + 3;2320,2342,2343;, + 3;2321,4347,4332;, + 3;2321,2334,4347;, + 3;2322,2719,2321;, + 3;2322,2718,2719;, + 3;2323,2542,2322;, + 3;2323,2541,2542;, + 3;2324,2569,2323;, + 3;2324,2568,2569;, + 3;2325,2563,2324;, + 3;2325,2562,2563;, + 3;2326,2556,2325;, + 3;2326,2561,2556;, + 3;4332,2322,2321;, + 3;4332,2323,2322;, + 3;4332,2324,2323;, + 3;4332,2325,2324;, + 3;4332,2326,2325;, + 3;4332,2319,2326;, + 3;4332,2320,2319;, + 3;4175,2335,2329;, + 3;4175,4348,2335;, + 3;2327,4173,4175;, + 3;2327,2362,4173;, + 3;2328,2368,2327;, + 3;2328,2367,2368;, + 3;2329,2353,2328;, + 3;2329,2352,2353;, + 3;4175,2328,2327;, + 3;4175,2329,2328;, + 3;2330,4346,4347;, + 3;2330,2425,4346;, + 3;2332,4331,2331;, + 3;2332,2703,4331;, + 3;2333,2710,2332;, + 3;2333,2709,2710;, + 3;2334,2715,2333;, + 3;2334,2719,2715;, + 3;4347,2331,2330;, + 3;4347,2332,2331;, + 3;4347,2333,2332;, + 3;4347,2334,2333;, + 3;2336,2352,2335;, + 3;2336,2351,2352;, + 3;2337,2350,2336;, + 3;2337,2349,2350;, + 3;2338,2375,2337;, + 3;2338,2379,2375;, + 3;4348,2388,2338;, + 3;4348,4349,2388;, + 3;4348,2336,2335;, + 3;4348,2337,2336;, + 3;4348,2338,2337;, + 3;2339,2549,2343;, + 3;2339,2548,2549;, + 3;2340,2551,2339;, + 3;2340,2550,2551;, + 3;2341,2364,2340;, + 3;2341,2363,2364;, + 3;2341,2340,2339;, + 3;2341,2339,2342;, + 3;2342,2339,2343;, + 3;2344,2351,2350;, + 3;2344,2356,2351;, + 3;2345,2518,2344;, + 3;2345,2517,2518;, + 3;2346,2519,2345;, + 3;2346,2523,2519;, + 3;2347,2524,2346;, + 3;2347,2530,2524;, + 3;2348,2373,2347;, + 3;2348,2372,2373;, + 3;2349,2376,2348;, + 3;2349,2375,2376;, + 3;2349,2346,2345;, + 3;2349,2345,2350;, + 3;2350,2345,2344;, + 3;2346,2349,2348;, + 3;2346,2348,2347;, + 3;2354,2367,2353;, + 3;2354,2366,2367;, + 3;2355,2507,2354;, + 3;2355,2512,2507;, + 3;2356,2513,2355;, + 3;2356,2518,2513;, + 3;2353,2355,2354;, + 3;2355,2353,2356;, + 3;2356,2353,2352;, + 3;2356,2352,2351;, + 3;2358,2381,2357;, + 3;2358,2380,2381;, + 3;2359,2535,2358;, + 3;2359,2534,2535;, + 3;2360,2538,2359;, + 3;2360,2537,2538;, + 3;2357,2360,2358;, + 3;2358,2360,2359;, + 3;2362,2369,2361;, + 3;2362,2368,2369;, + 3;4173,2362,2361;, + 3;2365,2550,2364;, + 3;2365,2555,2550;, + 3;2366,2508,2365;, + 3;2366,2507,2508;, + 3;2365,2364,2366;, + 3;2366,2364,2369;, + 3;2366,2369,2368;, + 3;2366,2368,2367;, + 3;2369,2364,2363;, + 3;2370,2531,2374;, + 3;2370,2536,2531;, + 3;2371,2385,2370;, + 3;2371,2384,2385;, + 3;2372,2377,2371;, + 3;2372,2376,2377;, + 3;2374,2530,2373;, + 3;2374,2529,2530;, + 3;2374,2373,2372;, + 3;2374,2372,2371;, + 3;2374,2371,2370;, + 3;2378,2384,2377;, + 3;2378,2383,2384;, + 3;2379,2389,2378;, + 3;2379,2388,2389;, + 3;2379,2376,2375;, + 3;2376,2379,2377;, + 3;2377,2379,2378;, + 3;2380,2536,2385;, + 3;2380,2535,2536;, + 3;2383,2390,2382;, + 3;2383,2389,2390;, + 3;2382,2380,2385;, + 3;2382,2385,2383;, + 3;2383,2385,2384;, + 3;2380,2382,2381;, + 3;4350,2427,2387;, + 3;4350,1813,2427;, + 3;4349,2389,2388;, + 3;4349,2390,2389;, + 3;4349,4329,2390;, + 3;4350,2387,2386;, + 3;2393,2397,2392;, + 3;2393,2401,2397;, + 3;2395,2412,2394;, + 3;2395,2411,2412;, + 3;4302,2396,4323;, + 3;2396,4302,2393;, + 3;2396,2393,2391;, + 3;2391,2393,2392;, + 3;4317,2397,4313;, + 3;4313,2397,2400;, + 3;2400,2397,2401;, + 3;2402,2410,2405;, + 3;2402,2409,2410;, + 3;2403,2414,2402;, + 3;2403,2413,2414;, + 3;2404,2418,2403;, + 3;2404,2417,2418;, + 3;4351,2419,2404;, + 3;4351,4306,2419;, + 3;4352,4207,4204;, + 3;4352,4353,4207;, + 3;4351,2402,2405;, + 3;4351,2403,2402;, + 3;4351,2404,2403;, + 3;2408,2423,2407;, + 3;2408,2422,2423;, + 3;4354,2415,2408;, + 3;4354,4355,2415;, + 3;4356,4357,4358;, + 3;1787,1813,4359;, + 3;1787,2412,2411;, + 3;1787,4300,2412;, + 3;4356,2407,2406;, + 3;4356,2408,2407;, + 3;4356,4354,2408;, + 3;4356,4358,4354;, + 3;2413,4311,4360;, + 3;2413,2418,4311;, + 3;88,2422,2415;, + 3;88,21,2422;, + 3;4360,2414,2413;, + 3;88,2415,4355;, + 3;2417,2420,2416;, + 3;2417,2419,2420;, + 3;4311,2418,2416;, + 3;2416,2418,2417;, + 3;4306,2420,2419;, + 3;4306,2421,2420;, + 3;21,2423,2422;, + 3;4346,2425,2424;, + 3;2428,2461,2433;, + 3;2428,2465,2461;, + 3;2433,2466,2432;, + 3;2433,2471,2466;, + 3;2429,2428,2430;, + 3;2430,2428,2433;, + 3;2430,2433,2431;, + 3;2431,2433,2432;, + 3;2434,2765,2439;, + 3;2434,2768,2765;, + 3;2437,2473,2436;, + 3;2437,2472,2473;, + 3;2439,2764,2438;, + 3;2439,2763,2764;, + 3;2436,2435,2437;, + 3;2437,2435,2434;, + 3;2437,2434,2439;, + 3;2437,2439,2438;, + 3;2440,2477,2444;, + 3;2440,2481,2477;, + 3;2441,2503,2440;, + 3;2441,2502,2503;, + 3;2442,2484,2441;, + 3;2442,2483,2484;, + 3;2442,2441,2443;, + 3;2443,2441,2444;, + 3;2444,2441,2440;, + 3;2445,2748,2450;, + 3;2445,2747,2748;, + 3;2446,2729,2445;, + 3;2446,2728,2729;, + 3;2448,2468,2447;, + 3;2448,2467,2468;, + 3;2446,2445,2447;, + 3;2447,2445,2448;, + 3;2448,2445,2449;, + 3;2449,2445,2450;, + 3;2451,2489,2456;, + 3;2451,2488,2489;, + 3;2452,2492,2451;, + 3;2452,2491,2492;, + 3;2454,2506,2453;, + 3;2454,2505,2506;, + 3;2455,2496,2454;, + 3;2455,2500,2496;, + 3;2456,2454,2451;, + 3;2451,2454,2453;, + 3;2451,2453,2452;, + 3;2454,2456,2455;, + 3;2460,2458,2457;, + 3;2458,2460,2459;, + 3;2462,2471,2461;, + 3;2462,2470,2471;, + 3;2463,2494,2462;, + 3;2463,2493,2494;, + 3;2464,2487,2463;, + 3;2464,2486,2487;, + 3;2465,2463,2461;, + 3;2461,2463,2462;, + 3;2463,2465,2464;, + 3;2470,2495,2469;, + 3;2470,2494,2495;, + 3;2467,2469,2468;, + 3;2469,2467,2470;, + 3;2470,2467,2466;, + 3;2470,2466,2471;, + 3;2475,2499,2474;, + 3;2475,2498,2499;, + 3;2476,2479,2475;, + 3;2476,2478,2479;, + 3;2474,2473,2475;, + 3;2475,2473,2472;, + 3;2475,2472,2476;, + 3;2480,2498,2479;, + 3;2480,2497,2498;, + 3;2481,2504,2480;, + 3;2481,2503,2504;, + 3;2478,2480,2479;, + 3;2480,2478,2481;, + 3;2481,2478,2477;, + 3;2485,4361,4362;, + 3;2485,2501,4361;, + 3;2482,4362,4344;, + 3;4362,2482,2485;, + 3;2488,4363,4364;, + 3;2488,2492,4363;, + 3;4334,2489,2488;, + 3;4334,2488,4364;, + 3;4342,4365,2490;, + 3;2490,4365,2491;, + 3;2491,4365,4363;, + 3;2491,4363,2492;, + 3;4366,2505,2496;, + 3;4366,4367,2505;, + 3;4337,4368,2500;, + 3;2500,4368,2496;, + 3;2496,4368,4366;, + 3;4369,2506,4367;, + 3;4367,2506,2505;, + 3;2506,4369,2501;, + 3;2501,4369,4361;, + 3;2509,2555,2508;, + 3;2509,2554,2555;, + 3;2510,2627,2509;, + 3;2510,2626,2627;, + 3;2511,2597,2510;, + 3;2511,2596,2597;, + 3;2512,2514,2511;, + 3;2512,2513,2514;, + 3;2510,2508,2511;, + 3;2511,2508,2507;, + 3;2511,2507,2512;, + 3;2508,2510,2509;, + 3;2515,2596,2514;, + 3;2515,2595,2596;, + 3;2516,2605,2515;, + 3;2516,2604,2605;, + 3;2517,2520,2516;, + 3;2517,2519,2520;, + 3;2516,2513,2518;, + 3;2516,2518,2517;, + 3;2513,2516,2515;, + 3;2513,2515,2514;, + 3;2521,2604,2520;, + 3;2521,2603,2604;, + 3;2522,2609,2521;, + 3;2522,2608,2609;, + 3;2523,2525,2522;, + 3;2523,2524,2525;, + 3;2519,2522,2521;, + 3;2519,2521,2520;, + 3;2522,2519,2523;, + 3;2526,2608,2525;, + 3;2526,2607,2608;, + 3;2527,2619,2526;, + 3;2527,2618,2619;, + 3;2528,2575,2527;, + 3;2528,2574,2575;, + 3;2529,2532,2528;, + 3;2529,2531,2532;, + 3;2527,2526,2528;, + 3;2528,2526,2529;, + 3;2529,2526,2530;, + 3;2530,2526,2525;, + 3;2530,2525,2524;, + 3;2533,2574,2532;, + 3;2533,2580,2574;, + 3;2534,2539,2533;, + 3;2534,2538,2539;, + 3;2536,2534,2531;, + 3;2531,2534,2532;, + 3;2532,2534,2533;, + 3;2534,2536,2535;, + 3;2540,2580,2539;, + 3;2540,2579,2580;, + 3;2541,2570,2540;, + 3;2541,2569,2570;, + 3;2543,2718,2542;, + 3;2543,2717,2718;, + 3;2543,2539,2538;, + 3;2543,2538,2537;, + 3;2539,2543,2540;, + 3;2540,2543,2542;, + 3;2540,2542,2541;, + 3;2545,2561,2544;, + 3;2545,2560,2561;, + 3;2546,2632,2545;, + 3;2546,2631,2632;, + 3;2547,2624,2546;, + 3;2547,2623,2624;, + 3;2548,2552,2547;, + 3;2548,2551,2552;, + 3;2546,2544,2549;, + 3;2546,2549,2547;, + 3;2547,2549,2548;, + 3;2544,2546,2545;, + 3;2553,2623,2552;, + 3;2553,2622,2623;, + 3;2554,2628,2553;, + 3;2554,2627,2628;, + 3;2554,2550,2555;, + 3;2550,2554,2551;, + 3;2551,2554,2553;, + 3;2551,2553,2552;, + 3;2557,2562,2556;, + 3;2557,2567,2562;, + 3;2558,2583,2557;, + 3;2558,2582,2583;, + 3;2559,2592,2558;, + 3;2559,2591,2592;, + 3;2560,2633,2559;, + 3;2560,2632,2633;, + 3;2560,2559,2557;, + 3;2560,2557,2556;, + 3;2560,2556,2561;, + 3;2557,2559,2558;, + 3;2564,2568,2563;, + 3;2564,2573,2568;, + 3;2565,2645,2564;, + 3;2565,2644,2645;, + 3;2566,2639,2565;, + 3;2566,2638,2639;, + 3;2567,2584,2566;, + 3;2567,2583,2584;, + 3;2565,2567,2566;, + 3;2567,2565,2564;, + 3;2567,2564,2562;, + 3;2562,2564,2563;, + 3;2571,2579,2570;, + 3;2571,2578,2579;, + 3;2572,2667,2571;, + 3;2572,2666,2667;, + 3;2573,2640,2572;, + 3;2573,2645,2640;, + 3;2572,2568,2573;, + 3;2568,2572,2569;, + 3;2569,2572,2571;, + 3;2569,2571,2570;, + 3;2576,2618,2575;, + 3;2576,2617,2618;, + 3;2577,2648,2576;, + 3;2577,2647,2648;, + 3;2578,2661,2577;, + 3;2578,2667,2661;, + 3;2576,2580,2577;, + 3;2577,2580,2579;, + 3;2577,2579,2578;, + 3;2580,2576,2574;, + 3;2574,2576,2575;, + 3;2581,2612,2589;, + 3;2581,2611,2612;, + 3;2582,2593,2581;, + 3;2582,2592,2593;, + 3;2585,2638,2584;, + 3;2585,2637,2638;, + 3;2586,2673,2585;, + 3;2586,2672,2673;, + 3;2587,2670,2586;, + 3;2587,2669,2670;, + 3;2588,2651,2587;, + 3;2588,2650,2651;, + 3;2589,2614,2588;, + 3;2589,2613,2614;, + 3;2584,2587,2585;, + 3;2585,2587,2586;, + 3;2587,2584,2582;, + 3;2587,2582,2581;, + 3;2587,2581,2588;, + 3;2588,2581,2589;, + 3;2582,2584,2583;, + 3;2590,2602,2594;, + 3;2590,2601,2602;, + 3;2591,2634,2590;, + 3;2591,2633,2634;, + 3;2594,2611,2593;, + 3;2594,2610,2611;, + 3;2592,2591,2593;, + 3;2593,2591,2590;, + 3;2593,2590,2594;, + 3;2595,2606,2599;, + 3;2595,2605,2606;, + 3;2598,2626,2597;, + 3;2598,2629,2626;, + 3;2599,2621,2598;, + 3;2599,2620,2621;, + 3;2597,2596,2598;, + 3;2598,2596,2599;, + 3;2599,2596,2595;, + 3;2600,2620,2606;, + 3;2600,2625,2620;, + 3;2601,2630,2600;, + 3;2601,2634,2630;, + 3;2603,2610,2602;, + 3;2603,2609,2610;, + 3;2604,2602,2605;, + 3;2605,2602,2601;, + 3;2605,2601,2606;, + 3;2606,2601,2600;, + 3;2602,2604,2603;, + 3;2607,2613,2612;, + 3;2607,2619,2613;, + 3;2609,2608,2610;, + 3;2610,2608,2612;, + 3;2610,2612,2611;, + 3;2612,2608,2607;, + 3;2615,2650,2614;, + 3;2615,2654,2650;, + 3;2616,2656,2615;, + 3;2616,2655,2656;, + 3;2617,2649,2616;, + 3;2617,2648,2649;, + 3;2618,2616,2619;, + 3;2619,2616,2615;, + 3;2619,2615,2614;, + 3;2619,2614,2613;, + 3;2616,2618,2617;, + 3;2622,2629,2621;, + 3;2622,2628,2629;, + 3;2625,2631,2624;, + 3;2625,2630,2631;, + 3;2624,2623,2625;, + 3;2625,2623,2621;, + 3;2625,2621,2620;, + 3;2621,2623,2622;, + 3;2627,2626,2628;, + 3;2628,2626,2629;, + 3;2633,2632,2631;, + 3;2633,2631,2630;, + 3;2633,2630,2634;, + 3;2635,2644,2639;, + 3;2635,2643,2644;, + 3;2636,2678,2635;, + 3;2636,2677,2678;, + 3;2637,2674,2636;, + 3;2637,2673,2674;, + 3;2638,2637,2639;, + 3;2639,2637,2635;, + 3;2635,2637,2636;, + 3;2641,2666,2640;, + 3;2641,2665,2666;, + 3;2642,2695,2641;, + 3;2642,2694,2695;, + 3;2643,2679,2642;, + 3;2643,2678,2679;, + 3;2640,2645,2644;, + 3;2640,2644,2643;, + 3;2640,2643,2641;, + 3;2641,2643,2642;, + 3;2646,2655,2649;, + 3;2646,2660,2655;, + 3;2647,2662,2646;, + 3;2647,2661,2662;, + 3;2648,2647,2649;, + 3;2649,2647,2646;, + 3;2652,2669,2651;, + 3;2652,2668,2669;, + 3;2653,2688,2652;, + 3;2653,2687,2688;, + 3;2654,2657,2653;, + 3;2654,2656,2657;, + 3;2650,2654,2653;, + 3;2650,2653,2651;, + 3;2651,2653,2652;, + 3;2658,2687,2657;, + 3;2658,2686,2687;, + 3;2659,2693,2658;, + 3;2659,2692,2693;, + 3;2660,2663,2659;, + 3;2660,2662,2663;, + 3;2656,2659,2657;, + 3;2657,2659,2658;, + 3;2659,2656,2660;, + 3;2660,2656,2655;, + 3;2664,2692,2663;, + 3;2664,2691,2692;, + 3;2665,2696,2664;, + 3;2665,2695,2696;, + 3;2662,2666,2665;, + 3;2662,2665,2663;, + 3;2663,2665,2664;, + 3;2666,2662,2667;, + 3;2667,2662,2661;, + 3;2668,2683,2671;, + 3;2668,2688,2683;, + 3;2671,2672,2670;, + 3;2671,2676,2672;, + 3;2671,2670,2668;, + 3;2668,2670,2669;, + 3;2675,2677,2674;, + 3;2675,2682,2677;, + 3;2676,2684,2675;, + 3;2676,2683,2684;, + 3;2675,2674,2676;, + 3;2676,2674,2672;, + 3;2672,2674,2673;, + 3;2680,2694,2679;, + 3;2680,2697,2694;, + 3;2681,2690,2680;, + 3;2681,2689,2690;, + 3;2682,2685,2681;, + 3;2682,2684,2685;, + 3;2680,2679,2681;, + 3;2681,2679,2682;, + 3;2682,2679,2677;, + 3;2677,2679,2678;, + 3;2686,2689,2685;, + 3;2686,2693,2689;, + 3;2685,2683,2688;, + 3;2685,2688,2686;, + 3;2686,2688,2687;, + 3;2683,2685,2684;, + 3;2691,2697,2690;, + 3;2691,2696,2697;, + 3;2689,2693,2690;, + 3;2690,2693,2691;, + 3;2691,2693,2692;, + 3;2697,2696,2694;, + 3;2694,2696,2695;, + 3;2699,2714,2698;, + 3;2699,2713,2714;, + 3;2701,2698,2702;, + 3;2698,2701,2699;, + 3;2699,2701,2700;, + 3;2703,2711,2707;, + 3;2703,2710,2711;, + 3;2704,2706,2705;, + 3;2707,4331,2703;, + 3;2706,2704,4325;, + 3;2709,2716,2708;, + 3;2709,2715,2716;, + 3;2709,2712,2711;, + 3;2709,2711,2710;, + 3;2712,2709,2713;, + 3;2713,2709,2714;, + 3;2714,2709,2708;, + 3;2718,2717,2716;, + 3;2718,2716,2719;, + 3;2719,2716,2715;, + 3;2721,2767,2720;, + 3;2721,2766,2767;, + 3;2722,2761,2721;, + 3;2721,2761,2762;, + 3;2722,2721,2720;, + 3;2722,2720,2725;, + 3;2722,2725,2723;, + 3;2723,2725,2724;, + 3;2727,2753,2726;, + 3;2727,2752,2753;, + 3;2730,2747,2729;, + 3;2730,2746,2747;, + 3;2732,2733,2731;, + 3;2732,2738,2733;, + 3;2728,2731,2729;, + 3;2729,2731,2730;, + 3;2731,2728,2727;, + 3;2731,2727,2732;, + 3;2732,2727,2726;, + 3;2735,3387,2734;, + 3;2735,3386,3387;, + 3;2736,2824,2735;, + 3;2736,2823,2824;, + 3;2737,2742,2736;, + 3;2737,2741,2742;, + 3;2734,2733,2735;, + 3;2735,2733,2738;, + 3;2735,2738,2736;, + 3;2736,2738,2737;, + 3;2743,2823,2742;, + 3;2743,2822,2823;, + 3;2744,2942,2743;, + 3;2744,2941,2942;, + 3;2742,2741,2744;, + 3;2742,2744,2743;, + 3;2744,2741,2739;, + 3;2739,2741,2740;, + 3;1883,2746,2745;, + 3;1883,2747,2746;, + 3;1883,2748,2747;, + 3;2750,2758,2749;, + 3;2750,2757,2758;, + 3;2753,2750,2749;, + 3;2750,2753,2751;, + 3;2751,2753,2752;, + 3;2756,2760,2755;, + 3;2756,2759,2760;, + 3;2757,2755,2758;, + 3;2758,2755,2754;, + 3;2755,2757,2756;, + 3;2763,2766,2762;, + 3;2763,2765,2766;, + 3;2759,2762,2761;, + 3;2759,2761,2760;, + 3;2762,2759,2764;, + 3;2762,2764,2763;, + 3;2765,2767,2766;, + 3;2767,2765,2768;, + 3;2771,3118,2770;, + 3;2771,3117,3118;, + 3;4370,2865,2771;, + 3;4370,4371,2865;, + 3;2773,3053,2772;, + 3;2773,3052,3053;, + 3;2774,3057,4372;, + 3;2773,4373,3058;, + 3;2774,2770,2769;, + 3;2770,2774,2771;, + 3;2771,2774,4372;, + 3;2771,4372,4370;, + 3;2775,3044,2780;, + 3;2775,3048,3044;, + 3;1886,3085,2775;, + 3;1886,1944,3085;, + 3;2776,1918,1886;, + 3;2776,3064,1918;, + 3;2777,4374,4375;, + 3;2777,3054,4374;, + 3;2778,2863,2777;, + 3;2778,2862,2863;, + 3;2779,3359,2778;, + 3;2779,3358,3359;, + 3;4376,2789,2779;, + 3;4376,4377,2789;, + 3;4378,2777,4375;, + 3;4378,2778,2777;, + 3;4378,2779,2778;, + 3;4378,4376,2779;, + 3;1886,2775,2780;, + 3;2781,3369,2788;, + 3;2781,3368,3369;, + 3;2782,2857,4379;, + 3;2781,4380,2858;, + 3;2783,2860,2782;, + 3;2783,2869,2860;, + 3;2784,3384,2783;, + 3;2784,3383,3384;, + 3;2785,3412,2784;, + 3;2785,3415,3412;, + 3;2786,3093,2785;, + 3;2786,3098,3093;, + 3;2787,2808,2786;, + 3;2787,2807,2808;, + 3;4381,3362,2787;, + 3;4381,4382,3362;, + 3;4381,2785,4379;, + 3;4379,2785,2784;, + 3;4379,2784,2782;, + 3;2782,2784,2783;, + 3;2785,4381,2786;, + 3;2786,4381,2787;, + 3;2790,3358,2789;, + 3;2790,3357,3358;, + 3;2791,3373,2790;, + 3;2791,3372,3373;, + 3;2792,3378,2791;, + 3;2792,3377,3378;, + 3;2793,3197,2792;, + 3;2793,3196,3197;, + 3;2794,3017,2793;, + 3;2794,3016,3017;, + 3;2795,3041,2794;, + 3;2795,3040,3041;, + 3;4377,3045,2795;, + 3;4377,4383,3045;, + 3;2794,2793,2795;, + 3;2795,2793,4377;, + 3;4377,2793,2792;, + 3;4377,2792,2789;, + 3;2789,2792,2791;, + 3;2789,2791,2790;, + 3;2797,4384,4385;, + 3;2802,2991,2987;, + 3;2798,4384,2797;, + 3;2798,3363,4384;, + 3;2799,2806,2798;, + 3;2799,2815,2806;, + 3;2800,3090,2799;, + 3;2800,3089,3090;, + 3;1891,2945,2800;, + 3;1891,1893,2945;, + 3;4253,4386,4387;, + 3;4253,2974,4386;, + 3;2802,3082,4253;, + 3;2802,3083,3082;, + 3;1891,4385,2801;, + 3;1891,2797,4385;, + 3;1891,2798,2797;, + 3;1891,2799,2798;, + 3;1891,2800,2799;, + 3;2803,4388,4389;, + 3;2803,3020,4388;, + 3;2804,3022,2803;, + 3;2804,3021,3022;, + 3;2805,2997,2804;, + 3;2805,2996,2997;, + 3;4389,2982,2805;, + 3;4389,4390,2982;, + 3;4389,2804,2803;, + 3;4389,2805,2804;, + 3;2807,3363,2806;, + 3;2807,3362,3363;, + 3;2809,3098,2808;, + 3;2809,3097,3098;, + 3;2810,3135,2809;, + 3;2810,3134,3135;, + 3;2811,4391,4392;, + 3;2811,3159,4391;, + 3;2812,3110,2811;, + 3;2812,3115,3110;, + 3;4393,3148,2812;, + 3;4393,4394,3148;, + 3;2814,3122,2813;, + 3;2814,3121,3122;, + 3;2815,3091,2814;, + 3;2815,3090,3091;, + 3;2806,2810,2809;, + 3;2806,2809,2807;, + 3;2807,2809,2808;, + 3;2810,2806,4395;, + 3;4395,2806,4396;, + 3;4396,2806,2813;, + 3;2813,2806,2814;, + 3;2814,2806,2815;, + 3;2816,3400,2825;, + 3;2816,3399,3400;, + 3;2817,3404,2816;, + 3;2816,3404,3405;, + 3;2818,2892,2817;, + 3;2818,2891,2892;, + 3;2819,2899,2818;, + 3;2819,2898,2899;, + 3;2820,2905,2819;, + 3;2820,2904,2905;, + 3;2821,2883,2820;, + 3;2821,2887,2883;, + 3;2822,2943,2821;, + 3;2822,2942,2943;, + 3;2825,3386,2824;, + 3;2825,3385,3386;, + 3;2817,2819,2818;, + 3;2819,2817,2820;, + 3;2820,2817,2821;, + 3;2821,2817,2816;, + 3;2821,2816,2822;, + 3;2822,2816,2825;, + 3;2822,2825,2823;, + 3;2823,2825,2824;, + 3;2826,2843,2832;, + 3;2826,2842,2843;, + 3;2827,2854,2826;, + 3;2827,2853,2854;, + 3;2830,2909,2829;, + 3;2830,2908,2909;, + 3;2831,2915,2830;, + 3;2831,2914,2915;, + 3;2832,2889,2831;, + 3;2832,2888,2889;, + 3;2830,2829,2832;, + 3;2830,2832,2831;, + 3;2832,2829,2827;, + 3;2832,2827,2826;, + 3;2827,2829,2828;, + 3;2833,2896,2838;, + 3;2833,2895,2896;, + 3;2834,3380,2833;, + 3;2834,3379,3380;, + 3;2835,2868,2834;, + 3;2835,2867,2868;, + 3;2836,2848,2835;, + 3;2836,2847,2848;, + 3;2838,2840,2837;, + 3;2838,2839,2840;, + 3;2835,2834,2836;, + 3;2836,2834,2837;, + 3;2837,2834,2838;, + 3;2838,2834,2833;, + 3;2839,2888,2843;, + 3;2839,2896,2888;, + 3;2842,2855,2841;, + 3;2842,2854,2855;, + 3;2842,2840,2839;, + 3;2842,2839,2843;, + 3;2840,2842,2841;, + 3;2844,3116,2849;, + 3;2844,3119,3116;, + 3;2849,2867,2848;, + 3;2849,2866,2867;, + 3;2847,2849,2848;, + 3;2849,2847,2844;, + 3;2844,2847,2846;, + 3;2844,2846,2845;, + 3;2851,2855,2852;, + 3;2852,2855,2853;, + 3;2853,2855,2854;, + 3;2855,2851,2850;, + 3;2856,3361,2859;, + 3;2856,3360,3361;, + 3;4380,2861,2856;, + 3;2857,2860,4397;, + 3;2859,3368,2858;, + 3;2859,3367,3368;, + 3;4380,2856,2859;, + 3;4380,2859,2858;, + 3;2862,3360,2861;, + 3;2862,3359,3360;, + 3;2864,3054,2863;, + 3;2864,3053,3054;, + 3;2866,3117,2865;, + 3;2866,3116,3117;, + 3;2869,3379,2868;, + 3;2869,3384,3379;, + 3;2867,2866,2865;, + 3;2867,2865,2868;, + 3;2868,2865,4371;, + 3;2868,4371,4397;, + 3;2868,4397,2860;, + 3;2868,2860,2869;, + 3;2861,2864,2863;, + 3;2861,2863,2862;, + 3;2873,2940,2872;, + 3;2873,2939,2940;, + 3;2874,2886,2873;, + 3;2874,2885,2886;, + 3;2875,2919,2874;, + 3;2875,2918,2919;, + 3;2876,2925,2875;, + 3;2876,2924,2925;, + 3;2877,2879,2876;, + 3;2877,2878,2879;, + 3;2874,2876,2875;, + 3;2876,2874,2873;, + 3;2876,2873,2872;, + 3;2876,2872,2877;, + 3;2877,2872,2871;, + 3;2877,2871,2870;, + 3;2880,2924,2879;, + 3;2880,2923,2924;, + 3;2881,2930,2880;, + 3;2881,2929,2930;, + 3;2878,2880,2879;, + 3;2880,2878,2881;, + 3;2881,2878,2882;, + 3;2884,2904,2883;, + 3;2884,2903,2904;, + 3;2885,2920,2884;, + 3;2885,2919,2920;, + 3;2887,2939,2886;, + 3;2887,2943,2939;, + 3;2886,2885,2887;, + 3;2887,2885,2884;, + 3;2887,2884,2883;, + 3;2890,2914,2889;, + 3;2890,2913,2914;, + 3;2891,2900,2890;, + 3;2891,2899,2900;, + 3;2893,3404,2817;, + 3;2893,3403,3404;, + 3;2894,3409,2893;, + 3;2894,3408,3409;, + 3;2895,3381,2894;, + 3;2895,3380,3381;, + 3;2890,2889,2891;, + 3;2891,2889,2892;, + 3;2892,2889,2888;, + 3;2892,2888,2893;, + 3;2893,2888,2895;, + 3;2893,2895,2894;, + 3;2895,2888,2896;, + 3;2897,2938,2901;, + 3;2897,2937,2938;, + 3;2898,2906,2897;, + 3;2898,2905,2906;, + 3;2901,2913,2900;, + 3;2901,2912,2913;, + 3;2899,2898,2900;, + 3;2900,2898,2897;, + 3;2900,2897,2901;, + 3;2902,2937,2906;, + 3;2902,2936,2937;, + 3;2903,2921,2902;, + 3;2903,2920,2921;, + 3;2902,2906,2903;, + 3;2903,2906,2904;, + 3;2904,2906,2905;, + 3;2907,2933,2911;, + 3;2907,2932,2933;, + 3;2908,2916,2907;, + 3;2908,2915,2916;, + 3;2911,2928,2910;, + 3;2911,2927,2928;, + 3;2908,2907,2911;, + 3;2908,2911,2909;, + 3;2909,2911,2910;, + 3;2912,2932,2916;, + 3;2912,2938,2932;, + 3;2916,2914,2912;, + 3;2912,2914,2913;, + 3;2914,2916,2915;, + 3;2917,2936,2921;, + 3;2917,2935,2936;, + 3;2918,2926,2917;, + 3;2918,2925,2926;, + 3;2918,2920,2919;, + 3;2920,2918,2921;, + 3;2921,2918,2917;, + 3;2922,2935,2926;, + 3;2922,2934,2935;, + 3;2923,2931,2922;, + 3;2923,2930,2931;, + 3;2926,2923,2922;, + 3;2923,2926,2925;, + 3;2923,2925,2924;, + 3;2927,2934,2931;, + 3;2927,2933,2934;, + 3;2931,2928,2927;, + 3;2928,2931,2930;, + 3;2928,2930,2929;, + 3;2934,2933,2935;, + 3;2935,2933,2938;, + 3;2935,2938,2937;, + 3;2935,2937,2936;, + 3;2938,2933,2932;, + 3;2939,2943,2942;, + 3;2939,2942,2940;, + 3;2940,2942,2941;, + 3;2944,3104,2947;, + 3;2944,3109,3104;, + 3;1893,3395,2944;, + 3;1893,2014,3395;, + 3;2946,3089,2945;, + 3;2946,3088,3089;, + 3;2947,2954,2946;, + 3;2947,2953,2954;, + 3;1893,2946,2945;, + 3;1893,2947,2946;, + 3;1893,2944,2947;, + 3;2948,3144,2952;, + 3;2948,3143,3144;, + 3;2949,2967,2948;, + 3;2949,2966,2967;, + 3;2950,3153,2949;, + 3;2950,3152,3153;, + 3;2951,3113,2950;, + 3;2951,3112,3113;, + 3;2952,3161,2951;, + 3;2952,3160,3161;, + 3;2950,2952,2951;, + 3;2952,2950,2949;, + 3;2952,2949,2948;, + 3;2953,3105,2956;, + 3;2953,3104,3105;, + 3;2955,3088,2954;, + 3;2955,3087,3088;, + 3;2956,3129,2955;, + 3;2956,3128,3129;, + 3;2953,2956,2955;, + 3;2953,2955,2954;, + 3;2957,3096,2964;, + 3;2957,3095,3096;, + 3;2958,3411,2957;, + 3;2958,3410,3411;, + 3;2959,3402,2958;, + 3;2959,3401,3402;, + 3;2960,3398,2959;, + 3;2960,3397,3398;, + 3;2961,2970,2960;, + 3;2961,2969,2970;, + 3;2962,3099,2961;, + 3;2962,3103,3099;, + 3;2963,3136,2962;, + 3;2963,3140,3136;, + 3;2964,3132,2963;, + 3;2964,3131,3132;, + 3;2958,2962,2959;, + 3;2959,2962,2960;, + 3;2960,2962,2961;, + 3;2962,2958,2957;, + 3;2962,2957,2963;, + 3;2963,2957,2964;, + 3;2965,3127,2973;, + 3;2965,3126,3127;, + 3;4398,3154,2965;, + 3;2966,3153,4399;, + 3;2968,3142,4400;, + 3;2967,4401,3143;, + 3;2969,3100,2968;, + 3;2969,3099,3100;, + 3;2971,3397,2970;, + 3;2971,3396,3397;, + 3;2972,3391,2971;, + 3;2972,3390,3391;, + 3;2973,3107,2972;, + 3;2973,3106,3107;, + 3;2971,2968,2972;, + 3;2972,2968,4400;, + 3;2972,4400,2973;, + 3;2973,4400,4398;, + 3;2973,4398,2965;, + 3;2968,2971,2969;, + 3;2969,2971,2970;, + 3;2974,4402,4386;, + 3;2974,3082,4402;, + 3;2975,2996,2982;, + 3;2975,3000,2996;, + 3;2976,3208,2975;, + 3;2976,3207,3208;, + 3;2977,3220,2976;, + 3;2977,3219,3220;, + 3;2978,3221,2977;, + 3;2978,3226,3221;, + 3;2979,3227,2978;, + 3;2979,3232,3227;, + 3;2980,3199,2979;, + 3;2980,3198,3199;, + 3;2981,3376,2980;, + 3;2981,3375,3376;, + 3;4390,2988,2981;, + 3;4390,4403,2988;, + 3;4390,2975,2982;, + 3;4390,2976,2975;, + 3;4390,2977,2976;, + 3;4390,2978,2977;, + 3;4390,2979,2978;, + 3;4390,2980,2979;, + 3;4390,2981,2980;, + 3;2983,3011,2986;, + 3;2983,3010,3011;, + 3;2984,3024,2983;, + 3;2984,3023,3024;, + 3;2985,3019,2984;, + 3;2985,3018,3019;, + 3;4404,3084,2985;, + 3;4404,4405,3084;, + 3;2986,4406,4404;, + 3;2986,2995,4406;, + 3;4404,2983,2986;, + 3;4404,2984,2983;, + 3;4404,2985,2984;, + 3;4403,3083,2987;, + 3;4403,4402,3083;, + 3;2989,3375,2988;, + 3;2989,3374,3375;, + 3;2990,3371,2989;, + 3;2990,3370,3371;, + 3;2991,3365,2990;, + 3;2991,3364,3365;, + 3;4403,2989,2988;, + 3;4403,2990,2989;, + 3;4403,2991,2990;, + 3;4403,2987,2991;, + 3;2992,4407,4406;, + 3;2992,3047,4407;, + 3;2993,3034,2992;, + 3;2993,3033,3034;, + 3;2994,3003,2993;, + 3;2994,3002,3003;, + 3;2995,3012,2994;, + 3;2995,3011,3012;, + 3;4406,2993,2992;, + 3;4406,2994,2993;, + 3;4406,2995,2994;, + 3;2998,3021,2997;, + 3;2998,3027,3021;, + 3;2999,3209,2998;, + 3;2999,3214,3209;, + 3;3000,3203,2999;, + 3;3000,3208,3203;, + 3;2997,2999,2998;, + 3;2999,2997,2996;, + 3;2999,2996,3000;, + 3;3001,3172,3007;, + 3;3001,3177,3172;, + 3;3002,3013,3001;, + 3;3002,3012,3013;, + 3;3004,3033,3003;, + 3;3004,3037,3033;, + 3;3005,3031,3004;, + 3;3005,3030,3031;, + 3;3006,3184,3005;, + 3;3006,3183,3184;, + 3;3007,3182,3006;, + 3;3007,3181,3182;, + 3;3003,3006,3004;, + 3;3004,3006,3005;, + 3;3006,3003,3007;, + 3;3007,3003,3002;, + 3;3007,3002,3001;, + 3;3008,3177,3013;, + 3;3008,3176,3177;, + 3;3009,3171,3008;, + 3;3009,3170,3171;, + 3;3010,3025,3009;, + 3;3010,3024,3025;, + 3;3010,3008,3013;, + 3;3010,3013,3011;, + 3;3011,3013,3012;, + 3;3008,3010,3009;, + 3;3014,3196,3017;, + 3;3014,3202,3196;, + 3;3015,3191,3014;, + 3;3015,3190,3191;, + 3;3016,3042,3015;, + 3;3016,3041,3042;, + 3;3016,3015,3017;, + 3;3017,3015,3014;, + 3;3018,4405,4388;, + 3;3018,3084,4405;, + 3;3020,3023,3019;, + 3;3020,3022,3023;, + 3;4388,3019,3018;, + 3;4388,3020,3019;, + 3;3026,3170,3025;, + 3;3026,3169,3170;, + 3;3027,3210,3026;, + 3;3027,3209,3210;, + 3;3026,3025,3027;, + 3;3027,3025,3022;, + 3;3027,3022,3021;, + 3;3022,3025,3023;, + 3;3023,3025,3024;, + 3;3028,3038,3032;, + 3;3028,3043,3038;, + 3;3029,3195,3028;, + 3;3029,3194,3195;, + 3;3030,3185,3029;, + 3;3030,3184,3185;, + 3;3032,3037,3031;, + 3;3032,3036,3037;, + 3;3029,3031,3030;, + 3;3031,3029,3032;, + 3;3032,3029,3028;, + 3;3035,3047,3034;, + 3;3035,3046,3047;, + 3;3036,3039,3035;, + 3;3036,3038,3039;, + 3;3034,3037,3036;, + 3;3034,3036,3035;, + 3;3037,3034,3033;, + 3;3040,3046,3039;, + 3;3040,3045,3046;, + 3;3043,3190,3042;, + 3;3043,3195,3190;, + 3;3040,3042,3041;, + 3;3042,3040,3043;, + 3;3043,3040,3039;, + 3;3043,3039,3038;, + 3;3048,1944,4408;, + 3;3048,3085,1944;, + 3;4408,3044,3048;, + 3;4407,3045,4383;, + 3;4407,3046,3045;, + 3;4407,3047,3046;, + 3;3050,3064,3049;, + 3;3050,3070,3064;, + 3;3052,3059,3051;, + 3;3052,3058,3059;, + 3;4297,3054,3051;, + 3;3051,3054,3053;, + 3;3051,3053,3052;, + 3;3054,4297,4374;, + 3;4373,4314,3058;, + 3;3058,4314,3055;, + 3;3058,3055,3059;, + 3;3060,3073,3063;, + 3;3060,3072,3073;, + 3;3061,3066,3060;, + 3;3061,3065,3066;, + 3;4409,3086,3061;, + 3;4295,4293,4410;, + 3;3062,4308,4409;, + 3;3062,3077,4308;, + 3;3063,3075,3062;, + 3;3063,3074,3075;, + 3;4409,3063,3062;, + 3;4409,3060,3063;, + 3;4409,3061,3060;, + 3;4411,1944,1918;, + 3;4411,4412,1944;, + 3;3067,4413,4414;, + 3;3067,3071,4413;, + 3;3068,3081,3067;, + 3;3068,3080,3081;, + 3;4415,4414,4416;, + 3;4415,3067,4414;, + 3;4415,3068,3067;, + 3;4415,3069,3068;, + 3;1918,3070,4299;, + 3;1918,3064,3070;, + 3;3071,151,3755;, + 3;3071,3081,151;, + 3;4417,3074,3073;, + 3;4417,4309,3074;, + 3;3755,4413,3071;, + 3;4417,3073,3072;, + 3;3076,3077,3075;, + 3;3076,3079,3077;, + 3;4309,3076,3074;, + 3;3074,3076,3075;, + 3;4308,3079,3078;, + 3;4308,3077,3079;, + 3;151,3081,3080;, + 3;4402,3082,3083;, + 3;3087,3130,3092;, + 3;3087,3129,3130;, + 3;3092,3121,3091;, + 3;3092,3120,3121;, + 3;3090,3089,3091;, + 3;3091,3089,3092;, + 3;3092,3089,3088;, + 3;3092,3088,3087;, + 3;3094,3415,3093;, + 3;3094,3414,3415;, + 3;3095,3406,3094;, + 3;3095,3411,3406;, + 3;3097,3131,3096;, + 3;3097,3135,3131;, + 3;3097,3096,3098;, + 3;3098,3096,3093;, + 3;3093,3096,3094;, + 3;3094,3096,3095;, + 3;3101,3142,3100;, + 3;3101,3141,3142;, + 3;3102,3165,3101;, + 3;3102,3164,3165;, + 3;3103,3137,3102;, + 3;3103,3136,3137;, + 3;3100,3099,3101;, + 3;3101,3099,3103;, + 3;3101,3103,3102;, + 3;3106,3128,3105;, + 3;3106,3127,3128;, + 3;3108,3390,3107;, + 3;3108,3389,3390;, + 3;3109,3392,3108;, + 3;3109,3395,3392;, + 3;3107,3106,3108;, + 3;3108,3106,3105;, + 3;3108,3105,3104;, + 3;3108,3104,3109;, + 3;3111,3159,3110;, + 3;3111,3158,3159;, + 3;3112,3162,3111;, + 3;3112,3161,3162;, + 3;3114,3152,3113;, + 3;3114,3151,3152;, + 3;3115,3145,3114;, + 3;3115,3148,3145;, + 3;3115,3111,3110;, + 3;3111,3115,3114;, + 3;3111,3114,3112;, + 3;3112,3114,3113;, + 3;3117,3119,3118;, + 3;3119,3117,3116;, + 3;3120,3125,3124;, + 3;3120,3130,3125;, + 3;3123,3147,3122;, + 3;3123,3146,3147;, + 3;3124,3150,3123;, + 3;3124,3149,3150;, + 3;3121,3123,3122;, + 3;3123,3121,3120;, + 3;3123,3120,3124;, + 3;3126,3149,3125;, + 3;3126,3154,3149;, + 3;3128,3126,3125;, + 3;3128,3125,3129;, + 3;3129,3125,3130;, + 3;3126,3128,3127;, + 3;3133,3140,3132;, + 3;3133,3139,3140;, + 3;3134,3156,3133;, + 3;3134,3155,3156;, + 3;3134,3133,3135;, + 3;3135,3133,3131;, + 3;3131,3133,3132;, + 3;3138,3164,3137;, + 3;3138,3163,3164;, + 3;3139,3157,3138;, + 3;3139,3156,3157;, + 3;3140,3138,3137;, + 3;3140,3137,3136;, + 3;3138,3140,3139;, + 3;4418,3160,3144;, + 3;4418,4419,3160;, + 3;3143,4401,4418;, + 3;3143,4418,3144;, + 3;4420,3151,3145;, + 3;4420,4421,3151;, + 3;4394,3145,3148;, + 3;3145,4394,4420;, + 3;4399,3153,4422;, + 3;4422,3153,3152;, + 3;4422,3152,4421;, + 3;4421,3152,3151;, + 3;3158,4423,4424;, + 3;3158,3162,4423;, + 3;4391,3159,4425;, + 3;4425,3159,3158;, + 3;4425,3158,4424;, + 3;4426,4423,3161;, + 3;4426,3161,3160;, + 3;4426,3160,4419;, + 3;3161,4423,3162;, + 3;3166,3176,3171;, + 3;3166,3175,3176;, + 3;3167,3256,3166;, + 3;3167,3255,3256;, + 3;3168,3287,3167;, + 3;3168,3286,3287;, + 3;3169,3211,3168;, + 3;3169,3210,3211;, + 3;3167,3169,3168;, + 3;3169,3167,3166;, + 3;3169,3166,3170;, + 3;3170,3166,3171;, + 3;3173,3181,3172;, + 3;3173,3180,3181;, + 3;3174,3260,3173;, + 3;3174,3259,3260;, + 3;3175,3257,3174;, + 3;3175,3256,3257;, + 3;3173,3176,3174;, + 3;3174,3176,3175;, + 3;3176,3173,3177;, + 3;3177,3173,3172;, + 3;3178,3183,3182;, + 3;3178,3189,3183;, + 3;3179,3269,3178;, + 3;3179,3268,3269;, + 3;3180,3261,3179;, + 3;3180,3260,3261;, + 3;3181,3178,3182;, + 3;3178,3181,3179;, + 3;3179,3181,3180;, + 3;3186,3194,3185;, + 3;3186,3193,3194;, + 3;3187,3233,3186;, + 3;3187,3239,3233;, + 3;3188,3274,3187;, + 3;3188,3273,3274;, + 3;3189,3270,3188;, + 3;3189,3269,3270;, + 3;3187,3186,3188;, + 3;3188,3186,3185;, + 3;3188,3185,3184;, + 3;3188,3184,3189;, + 3;3189,3184,3183;, + 3;3192,3202,3191;, + 3;3192,3201,3202;, + 3;3193,3234,3192;, + 3;3193,3233,3234;, + 3;3195,3191,3190;, + 3;3191,3195,3194;, + 3;3191,3194,3193;, + 3;3191,3193,3192;, + 3;3198,3377,3197;, + 3;3198,3376,3377;, + 3;3200,3232,3199;, + 3;3200,3231,3232;, + 3;3201,3235,3200;, + 3;3201,3234,3235;, + 3;3197,3201,3200;, + 3;3197,3200,3198;, + 3;3198,3200,3199;, + 3;3201,3197,3202;, + 3;3202,3197,3196;, + 3;3204,3214,3203;, + 3;3204,3213,3214;, + 3;3205,3282,3204;, + 3;3205,3281,3282;, + 3;3206,3291,3205;, + 3;3206,3290,3291;, + 3;3207,3215,3206;, + 3;3207,3220,3215;, + 3;3205,3207,3206;, + 3;3207,3205,3208;, + 3;3208,3205,3204;, + 3;3208,3204,3203;, + 3;3212,3286,3211;, + 3;3212,3285,3286;, + 3;3213,3283,3212;, + 3;3213,3282,3283;, + 3;3211,3209,3214;, + 3;3211,3214,3212;, + 3;3212,3214,3213;, + 3;3209,3211,3210;, + 3;3216,3290,3215;, + 3;3216,3289,3290;, + 3;3217,3253,3216;, + 3;3217,3252,3253;, + 3;3218,3246,3217;, + 3;3218,3245,3246;, + 3;3219,3222,3218;, + 3;3219,3221,3222;, + 3;3215,3218,3216;, + 3;3216,3218,3217;, + 3;3218,3215,3219;, + 3;3219,3215,3220;, + 3;3223,3245,3222;, + 3;3223,3244,3245;, + 3;3224,3294,3223;, + 3;3224,3298,3294;, + 3;3225,3299,3224;, + 3;3225,3304,3299;, + 3;3226,3228,3225;, + 3;3226,3227,3228;, + 3;3224,3222,3225;, + 3;3225,3222,3221;, + 3;3225,3221,3226;, + 3;3222,3224,3223;, + 3;3229,3304,3228;, + 3;3229,3303,3304;, + 3;3230,3322,3229;, + 3;3230,3321,3322;, + 3;3231,3236,3230;, + 3;3231,3235,3236;, + 3;3229,3228,3227;, + 3;3229,3227,3232;, + 3;3229,3232,3230;, + 3;3230,3232,3231;, + 3;3237,3321,3236;, + 3;3237,3320,3321;, + 3;3238,3306,3237;, + 3;3238,3305,3306;, + 3;3239,3275,3238;, + 3;3239,3274,3275;, + 3;3238,3237,3234;, + 3;3238,3234,3233;, + 3;3238,3233,3239;, + 3;3234,3237,3235;, + 3;3235,3237,3236;, + 3;3240,3272,3248;, + 3;3240,3278,3272;, + 3;3241,3312,3240;, + 3;3241,3311,3312;, + 3;3242,3328,3241;, + 3;3242,3327,3328;, + 3;3243,3334,3242;, + 3;3243,3333,3334;, + 3;3244,3295,3243;, + 3;3244,3294,3295;, + 3;3247,3252,3246;, + 3;3247,3251,3252;, + 3;3248,3266,3247;, + 3;3248,3271,3266;, + 3;3244,3241,3246;, + 3;3244,3246,3245;, + 3;3246,3241,3247;, + 3;3247,3241,3240;, + 3;3247,3240,3248;, + 3;3241,3244,3243;, + 3;3241,3243,3242;, + 3;3249,3289,3253;, + 3;3249,3293,3289;, + 3;3250,3263,3249;, + 3;3250,3262,3263;, + 3;3251,3267,3250;, + 3;3251,3266,3267;, + 3;3252,3251,3253;, + 3;3253,3251,3249;, + 3;3249,3251,3250;, + 3;3254,3279,3258;, + 3;3254,3284,3279;, + 3;3255,3288,3254;, + 3;3255,3287,3288;, + 3;3258,3259,3257;, + 3;3258,3265,3259;, + 3;3255,3254,3256;, + 3;3256,3254,3258;, + 3;3256,3258,3257;, + 3;3262,3268,3261;, + 3;3262,3267,3268;, + 3;3264,3293,3263;, + 3;3264,3292,3293;, + 3;3265,3280,3264;, + 3;3265,3279,3280;, + 3;3260,3259,3262;, + 3;3260,3262,3261;, + 3;3262,3259,3263;, + 3;3263,3259,3265;, + 3;3263,3265,3264;, + 3;3271,3273,3270;, + 3;3271,3272,3273;, + 3;3268,3267,3269;, + 3;3269,3267,3271;, + 3;3269,3271,3270;, + 3;3271,3267,3266;, + 3;3276,3305,3275;, + 3;3276,3308,3305;, + 3;3277,3314,3276;, + 3;3277,3319,3314;, + 3;3278,3313,3277;, + 3;3278,3312,3313;, + 3;3274,3276,3275;, + 3;3276,3274,3273;, + 3;3276,3273,3277;, + 3;3277,3273,3278;, + 3;3278,3273,3272;, + 3;3281,3292,3280;, + 3;3281,3291,3292;, + 3;3284,3285,3283;, + 3;3284,3288,3285;, + 3;3281,3280,3282;, + 3;3282,3280,3284;, + 3;3282,3284,3283;, + 3;3284,3280,3279;, + 3;3286,3285,3287;, + 3;3287,3285,3288;, + 3;3289,3291,3290;, + 3;3291,3289,3292;, + 3;3292,3289,3293;, + 3;3296,3333,3295;, + 3;3296,3332,3333;, + 3;3297,3340,3296;, + 3;3297,3339,3340;, + 3;3298,3300,3297;, + 3;3298,3299,3300;, + 3;3294,3298,3295;, + 3;3295,3298,3297;, + 3;3295,3297,3296;, + 3;3301,3339,3300;, + 3;3301,3338,3339;, + 3;3302,3355,3301;, + 3;3302,3354,3355;, + 3;3303,3323,3302;, + 3;3303,3322,3323;, + 3;3303,3299,3304;, + 3;3299,3303,3300;, + 3;3300,3303,3302;, + 3;3300,3302,3301;, + 3;3307,3320,3306;, + 3;3307,3326,3320;, + 3;3308,3315,3307;, + 3;3308,3314,3315;, + 3;3305,3308,3306;, + 3;3306,3308,3307;, + 3;3309,3319,3313;, + 3;3309,3318,3319;, + 3;3310,3344,3309;, + 3;3310,3343,3344;, + 3;3311,3329,3310;, + 3;3311,3328,3329;, + 3;3312,3309,3313;, + 3;3309,3312,3311;, + 3;3309,3311,3310;, + 3;3316,3326,3315;, + 3;3316,3325,3326;, + 3;3317,3350,3316;, + 3;3317,3349,3350;, + 3;3318,3345,3317;, + 3;3318,3344,3345;, + 3;3319,3316,3315;, + 3;3319,3315,3314;, + 3;3316,3319,3318;, + 3;3316,3318,3317;, + 3;3324,3354,3323;, + 3;3324,3353,3354;, + 3;3325,3351,3324;, + 3;3325,3350,3351;, + 3;3326,3322,3321;, + 3;3326,3321,3320;, + 3;3322,3326,3323;, + 3;3323,3326,3325;, + 3;3323,3325,3324;, + 3;3327,3335,3330;, + 3;3327,3334,3335;, + 3;3330,3343,3329;, + 3;3330,3342,3343;, + 3;3330,3329,3327;, + 3;3327,3329,3328;, + 3;3331,3342,3335;, + 3;3331,3347,3342;, + 3;3332,3341,3331;, + 3;3332,3340,3341;, + 3;3331,3335,3332;, + 3;3332,3335,3334;, + 3;3332,3334,3333;, + 3;3336,3347,3341;, + 3;3336,3346,3347;, + 3;3337,3348,3336;, + 3;3337,3352,3348;, + 3;3338,3356,3337;, + 3;3338,3355,3356;, + 3;3337,3336,3338;, + 3;3338,3336,3341;, + 3;3338,3341,3340;, + 3;3338,3340,3339;, + 3;3346,3349,3345;, + 3;3346,3348,3349;, + 3;3346,3342,3347;, + 3;3342,3346,3343;, + 3;3343,3346,3345;, + 3;3343,3345,3344;, + 3;3352,3353,3351;, + 3;3352,3356,3353;, + 3;3348,3352,3349;, + 3;3349,3352,3351;, + 3;3349,3351,3350;, + 3;3356,3355,3353;, + 3;3353,3355,3354;, + 3;3357,3367,3361;, + 3;3357,3373,3367;, + 3;3359,3357,3361;, + 3;3359,3361,3360;, + 3;3357,3359,3358;, + 3;3366,3370,3365;, + 3;3366,3369,3370;, + 3;4384,3362,4382;, + 3;3365,3364,3366;, + 3;3362,4384,3363;, + 3;3372,3374,3371;, + 3;3372,3378,3374;, + 3;3371,3368,3367;, + 3;3371,3367,3373;, + 3;3371,3373,3372;, + 3;3368,3371,3369;, + 3;3369,3371,3370;, + 3;3376,3378,3377;, + 3;3378,3376,3375;, + 3;3378,3375,3374;, + 3;3382,3408,3381;, + 3;3382,3407,3408;, + 3;3383,3413,3382;, + 3;3383,3412,3413;, + 3;3381,3383,3382;, + 3;3383,3381,3384;, + 3;3384,3381,3380;, + 3;3384,3380,3379;, + 3;3385,3396,3391;, + 3;3385,3400,3396;, + 3;3389,3393,3388;, + 3;3389,3392,3393;, + 3;3390,3389,3387;, + 3;3390,3387,3391;, + 3;3391,3387,3386;, + 3;3391,3386,3385;, + 3;3387,3389,3388;, + 3;2014,3392,3395;, + 3;2014,3393,3392;, + 3;2014,3394,3393;, + 3;3399,3401,3398;, + 3;3399,3405,3401;, + 3;3400,3399,3398;, + 3;3400,3398,3397;, + 3;3400,3397,3396;, + 3;3403,3410,3402;, + 3;3403,3409,3410;, + 3;3401,3405,3403;, + 3;3401,3403,3402;, + 3;3403,3405,3404;, + 3;3407,3414,3406;, + 3;3407,3413,3414;, + 3;3410,3407,3411;, + 3;3411,3407,3406;, + 3;3407,3410,3408;, + 3;3408,3410,3409;, + 3;3414,3413,3412;, + 3;3414,3412,3415;, + 3;21,88,845;, + 3;151,846,3755;, + 3;4310,4309,4427;, + 3;4310,4428,4311;, + 3;1769,3416,1770;, + 3;3416,1778,4148;, + 3;3417,1901,4429;, + 3;4429,4234,3417;, + 3;4430,3510,185;, + 3;4430,185,3509;, + 3;61,4431,3448;, + 3;61,0,4431;; + } + + MeshTextureCoords { + 4432; + 0.551713;0.158481;, + 0.442939;0.266364;, + 0.465760;0.091118;, + 0.359428;0.057171;, + 0.465760;0.024419;, + 0.815422;0.057523;, + 0.083667;0.060652;, + 0.597076;0.069576;, + 0.920137;0.671109;, + 0.842554;0.693424;, + 0.920019;0.713969;, + 0.728562;0.172729;, + 0.118906;0.107861;, + 0.644406;0.127337;, + 0.118913;0.144835;, + 0.430296;0.052895;, + 0.359428;0.116154;, + 0.356021;0.319790;, + 0.394347;0.323160;, + 0.427233;0.319079;, + 0.430296;0.009352;, + 0.886645;0.662715;, + 0.381887;0.022695;, + 0.658351;0.174014;, + 0.092993;0.146098;, + 0.685906;0.229150;, + 0.736179;0.215636;, + 0.629846;0.219982;, + 0.464459;0.320677;, + 0.700253;0.195920;, + 0.610610;0.168595;, + 0.066200;0.058208;, + 0.733851;0.325871;, + 0.054606;0.442647;, + 0.359428;0.246170;, + 0.427560;0.247468;, + 0.438618;0.408674;, + 0.356022;0.415064;, + 0.118913;0.173767;, + 0.455026;0.364714;, + 0.052464;0.254765;, + 0.419322;0.437861;, + 0.116059;0.366961;, + 0.394347;0.328619;, + 0.427233;0.324538;, + 0.442698;0.438188;, + 0.118774;0.254205;, + 0.356153;0.437792;, + 0.059890;0.171424;, + 0.032251;0.182250;, + 0.066673;0.190119;, + 0.023519;0.157546;, + 0.058251;0.145266;, + 0.005628;0.152079;, + 0.006431;0.150480;, + 0.049446;0.218747;, + 0.095581;0.212780;, + 0.118913;0.212000;, + 0.359428;0.181162;, + 0.398753;0.181862;, + 0.432820;0.182511;, + 0.574290;0.239863;, + 0.458415;0.271707;, + 0.446591;0.185893;, + 0.065339;0.442780;, + 0.669024;0.320480;, + 0.445846;0.325337;, + 0.006030;0.151279;, + 0.465760;0.051887;, + 0.559147;0.049519;, + 0.595529;0.117266;, + 0.465925;0.109701;, + 0.549941;0.151917;, + 0.587717;0.115217;, + 0.590694;0.071521;, + 0.557217;0.052500;, + 0.495192;0.111541;, + 0.522997;0.132857;, + 0.516882;0.039315;, + 0.495714;0.070258;, + 0.356021;0.382789;, + 0.375183;0.384474;, + 0.391626;0.382434;, + 0.425472;0.376874;, + 0.031504;0.215546;, + 0.359428;0.024842;, + 0.867640;0.034178;, + 0.839678;0.036502;, + 0.857340;0.649725;, + 0.359428;0.008334;, + 0.379332;0.007404;, + 0.389688;0.008235;, + 0.400856;0.002144;, + 0.409716;0.001197;, + 0.583239;0.012330;, + 0.793406;0.132263;, + 0.861711;0.672549;, + 0.893865;0.675224;, + 0.920564;0.687001;, + 0.845283;0.668070;, + 0.385765;0.310131;, + 0.667913;0.113729;, + 0.650023;0.087602;, + 0.631536;0.052867;, + 0.617447;0.029000;, + 0.639832;0.037988;, + 0.812486;0.054699;, + 0.803245;0.160421;, + 0.785495;0.208704;, + 0.867984;0.031841;, + 0.836932;0.034143;, + 0.815334;0.099408;, + 0.867984;0.017331;, + 0.830556;0.015332;, + 0.812307;0.023785;, + 0.792631;0.034435;, + 0.777019;0.056595;, + 0.764128;0.102698;, + 0.806759;0.138419;, + 0.758543;0.203424;, + 0.756451;0.178241;, + 0.750154;0.161070;, + 0.757487;0.141824;, + 0.779602;0.155868;, + 0.644346;0.272464;, + 0.639107;0.250146;, + 0.671632;0.200776;, + 0.662200;0.223137;, + 0.613887;0.268609;, + 0.631047;0.289558;, + 0.902852;0.117289;, + 0.850579;0.117328;, + 0.858474;0.096123;, + 0.901940;0.096616;, + 0.888860;0.096164;, + 0.832815;0.095553;, + 0.833973;0.117980;, + 0.551713;0.158481;, + 0.269100;0.266364;, + 0.251153;0.091117;, + 0.251153;0.024419;, + 0.920762;0.057447;, + 0.154150;0.060652;, + 0.597076;0.069576;, + 0.999127;0.694070;, + 0.728563;0.172729;, + 0.644406;0.127337;, + 0.286617;0.052895;, + 0.317692;0.323160;, + 0.284805;0.319079;, + 0.288556;0.009352;, + 0.953569;0.662737;, + 0.336965;0.022695;, + 0.658351;0.174014;, + 0.144837;0.146098;, + 0.685906;0.229150;, + 0.736179;0.215636;, + 0.629846;0.219982;, + 0.247580;0.320677;, + 0.700253;0.195920;, + 0.610610;0.168595;, + 0.171617;0.058208;, + 0.733851;0.325871;, + 0.181585;0.442779;, + 0.289352;0.247468;, + 0.205506;0.226805;, + 0.257013;0.364714;, + 0.184968;0.254780;, + 0.293026;0.437918;, + 0.317692;0.328619;, + 0.284805;0.324538;, + 0.269586;0.437793;, + 0.177940;0.171424;, + 0.205578;0.182250;, + 0.171156;0.190119;, + 0.214310;0.157546;, + 0.179579;0.145266;, + 0.229734;0.152079;, + 0.228932;0.150480;, + 0.188350;0.218747;, + 0.142249;0.212780;, + 0.318160;0.181862;, + 0.284092;0.182511;, + 0.574290;0.239863;, + 0.253624;0.271707;, + 0.270321;0.185893;, + 0.170852;0.442780;, + 0.669025;0.320480;, + 0.266193;0.325337;, + 0.229333;0.151279;, + 0.251153;0.051887;, + 0.559147;0.049519;, + 0.595529;0.117266;, + 0.250988;0.109701;, + 0.549531;0.151558;, + 0.585685;0.115494;, + 0.590395;0.071657;, + 0.557163;0.051913;, + 0.495714;0.111887;, + 0.521581;0.134300;, + 0.516917;0.039559;, + 0.495684;0.070180;, + 0.336856;0.384474;, + 0.320412;0.382434;, + 0.286567;0.376874;, + 0.206326;0.215546;, + 0.895403;0.036408;, + 0.919225;0.096002;, + 0.339520;0.007404;, + 0.329164;0.008235;, + 0.317996;0.002144;, + 0.309135;0.001197;, + 0.583239;0.012330;, + 0.942568;0.132263;, + 0.979425;0.675217;, + 0.946726;0.677891;, + 0.996398;0.668070;, + 0.326274;0.310131;, + 0.667913;0.113729;, + 0.650023;0.087602;, + 0.631536;0.052867;, + 0.617447;0.029000;, + 0.639832;0.037988;, + 0.923488;0.054699;, + 0.932729;0.160421;, + 0.950479;0.208704;, + 0.899042;0.034144;, + 0.920641;0.099408;, + 0.905419;0.015332;, + 0.923667;0.023785;, + 0.943344;0.034435;, + 0.958955;0.056595;, + 0.971847;0.102698;, + 0.929215;0.138419;, + 0.977432;0.203424;, + 0.979524;0.178241;, + 0.985820;0.161071;, + 0.978488;0.141824;, + 0.956372;0.155868;, + 0.644346;0.272464;, + 0.639107;0.250146;, + 0.671632;0.200776;, + 0.662200;0.223137;, + 0.613887;0.268609;, + 0.631047;0.289558;, + 0.902852;0.117289;, + 0.850579;0.117328;, + 0.858475;0.096123;, + 0.901940;0.096616;, + 0.888860;0.096164;, + 0.832815;0.095553;, + 0.833973;0.117980;, + 0.362779;0.521593;, + 0.114079;0.496280;, + 0.015593;0.538621;, + 0.413067;0.590996;, + 0.071282;0.556579;, + 0.114079;0.567406;, + 0.099956;0.579574;, + 0.424300;0.515014;, + 0.462475;0.504546;, + 0.109294;0.615708;, + 0.446455;0.570659;, + 0.063583;0.507001;, + 0.114079;0.543305;, + 0.431632;0.586910;, + 0.460591;0.574244;, + 0.088110;0.748276;, + 0.375357;0.785656;, + 0.112550;0.731015;, + 0.049365;0.760989;, + 0.041062;0.962565;, + 0.410288;0.967981;, + 0.434010;0.752783;, + 0.015465;0.715644;, + 0.033054;0.737854;, + 0.457389;0.965598;, + 0.433322;0.965919;, + 0.477819;0.771756;, + 0.082704;0.664352;, + 0.114762;0.674474;, + 0.061982;0.570639;, + 0.046172;0.686846;, + 0.410308;0.618813;, + 0.788717;0.583537;, + 0.413698;0.695212;, + 0.446559;0.645880;, + 0.058540;0.706405;, + 0.418117;0.723574;, + 0.031199;0.570609;, + 0.742190;0.313064;, + 0.756779;0.321579;, + 0.783375;0.328557;, + 0.826151;0.329094;, + 0.853820;0.326370;, + 0.746033;0.275270;, + 0.762350;0.266786;, + 0.789513;0.268192;, + 0.831224;0.279205;, + 0.857563;0.289306;, + 0.724828;0.460339;, + 0.739319;0.455172;, + 0.757159;0.439798;, + 0.414408;0.971032;, + 0.728309;0.346757;, + 0.745926;0.344262;, + 0.772846;0.351868;, + 0.010735;0.967181;, + 0.861627;0.308964;, + 0.837868;0.327705;, + 0.842297;0.284145;, + 0.411091;0.651182;, + 0.428698;0.876513;, + 0.423699;0.568455;, + 0.065047;0.942678;, + 0.037106;0.942847;, + 0.079040;0.940766;, + 0.391091;0.940519;, + 0.011332;0.941808;, + 0.412732;0.940671;, + 0.462371;0.941498;, + 0.437517;0.942397;, + 0.375061;0.808473;, + 0.399631;0.794862;, + 0.442565;0.794868;, + 0.081790;0.877027;, + 0.024359;0.876663;, + 0.383056;0.878540;, + 0.449565;0.876567;, + 0.480165;0.877379;, + 0.046689;0.877006;, + 0.407005;0.875615;, + 0.013484;0.572291;, + 0.084679;0.696575;, + 0.030451;0.697677;, + 0.392449;0.753106;, + 0.421098;0.794206;, + 0.051990;0.644457;, + 0.750745;0.580656;, + 0.416248;0.711576;, + 0.418268;0.732598;, + 0.416528;0.716968;, + 0.415048;0.703811;, + 0.054057;0.740134;, + 0.043962;0.728755;, + 0.072651;0.727710;, + 0.061716;0.964870;, + 0.784783;0.408719;, + 0.023733;0.964338;, + 0.784278;0.388010;, + 0.790879;0.373359;, + 0.787672;0.372002;, + 0.799093;0.370321;, + 0.819904;0.363746;, + 0.836925;0.361193;, + 0.856879;0.367989;, + 0.852722;0.366515;, + 0.789870;0.422196;, + 0.790150;0.426709;, + 0.802645;0.438063;, + 0.841137;0.441531;, + 0.855986;0.431918;, + 0.818542;0.442967;, + 0.830870;0.443475;, + 0.849598;0.436887;, + 0.861367;0.437046;, + 0.844150;0.363301;, + 0.046193;0.968453;, + 0.034249;0.969452;, + 0.026167;0.976093;, + 0.024562;0.979040;, + 0.023590;0.980527;, + 0.021595;0.986662;, + 0.458536;0.990264;, + 0.443083;0.983817;, + 0.451432;0.985102;, + 0.054884;0.971077;, + 0.058812;0.974886;, + 0.061081;0.985310;, + 0.421917;0.990046;, + 0.429331;0.982643;, + 0.061489;0.988962;, + 0.423160;0.991430;, + 0.422049;0.986512;, + 0.437053;0.983662;, + 0.455713;0.987962;, + 0.751936;0.511608;, + 0.775565;0.511382;, + 0.790667;0.510828;, + 0.742260;0.511058;, + 0.446359;0.592000;, + 0.056469;0.615493;, + 0.429093;0.704697;, + 0.113358;0.698276;, + 0.471054;0.693874;, + 0.443694;0.677693;, + 0.732967;0.488721;, + 0.824812;0.489415;, + 0.811150;0.610036;, + 0.725246;0.572015;, + 0.797433;0.490302;, + 0.757124;0.490022;, + 0.786758;0.613931;, + 0.823818;0.573700;, + 0.726973;0.508449;, + 0.825801;0.540741;, + 0.750561;0.617018;, + 0.726834;0.606098;, + 0.821824;0.510894;, + 0.790460;0.583701;, + 0.752506;0.580815;, + 0.753155;0.511554;, + 0.793248;0.510776;, + 0.740977;0.510621;, + 0.788229;0.614117;, + 0.724265;0.508140;, + 0.752135;0.617252;, + 0.826553;0.510835;, + 0.777823;0.511251;, + 0.754149;0.511440;, + 0.805126;0.511381;, + 0.114079;0.557341;, + 0.759721;0.398421;, + 0.761054;0.366386;, + 0.752224;0.439813;, + 0.816369;0.348071;, + 0.763538;0.460181;, + 0.395296;0.477256;, + 0.359862;0.470419;, + 0.088767;0.477079;, + 0.114079;0.476699;, + 0.411840;0.477331;, + 0.424655;0.477418;, + 0.066498;0.477187;, + 0.054242;0.477230;, + 0.439588;0.477494;, + 0.104660;0.254436;, + 0.096806;0.469878;, + 0.042134;0.449763;, + 0.414949;0.445141;, + 0.445503;0.445173;, + 0.848943;0.392358;, + 0.359862;0.445094;, + 0.391297;0.471167;, + 0.359862;0.470734;, + 0.076342;0.470898;, + 0.114079;0.476851;, + 0.414326;0.471332;, + 0.432164;0.471525;, + 0.042403;0.471131;, + 0.023723;0.471226;, + 0.448021;0.471691;, + 0.096201;0.449182;, + 0.104436;0.476901;, + 0.848942;0.395254;, + 0.848943;0.414986;, + 0.838153;0.395231;, + 0.838152;0.414996;, + 0.104420;0.486605;, + 0.106000;0.540169;, + 0.114079;0.496443;, + 0.114079;0.543468;, + 0.104114;0.486767;, + 0.105694;0.540332;, + 0.418093;0.495004;, + 0.423993;0.537540;, + 0.052028;0.528907;, + 0.392382;0.518528;, + 0.393769;0.530518;, + 0.396684;0.550706;, + 0.396337;0.568785;, + 0.392230;0.581982;, + 0.393079;0.606632;, + 0.438065;0.499238;, + 0.444577;0.525255;, + 0.387594;0.633179;, + 0.392223;0.662757;, + 0.396860;0.687511;, + 0.428691;0.622255;, + 0.435371;0.647317;, + 0.432617;0.685648;, + 0.087463;0.497126;, + 0.044563;0.505211;, + 0.079294;0.533408;, + 0.064206;0.504727;, + 0.039557;0.954539;, + 0.047283;0.954585;, + 0.427587;0.955639;, + 0.436284;0.955532;, + 0.074460;0.952724;, + 0.107172;0.957531;, + 0.394046;0.960089;, + 0.011938;0.955578;, + 0.025135;0.953131;, + 0.031836;0.953763;, + 0.418250;0.955939;, + 0.445123;0.955762;, + 0.454737;0.955923;, + 0.060252;0.954128;, + 0.064395;0.953699;, + 0.468310;0.956951;, + 0.048881;0.923002;, + 0.067036;0.922724;, + 0.034866;0.922252;, + 0.041046;0.922410;, + 0.453757;0.921277;, + 0.459086;0.921847;, + 0.435977;0.920548;, + 0.429060;0.920667;, + 0.411319;0.921527;, + 0.418037;0.920760;, + 0.082849;0.921580;, + 0.105367;0.921562;, + 0.076317;0.922237;, + 0.022332;0.921620;, + 0.446710;0.921015;, + 0.009127;0.921034;, + 0.039900;0.830890;, + 0.047550;0.831189;, + 0.410351;0.830272;, + 0.423955;0.828454;, + 0.402420;0.830320;, + 0.067293;0.831602;, + 0.082288;0.830912;, + 0.028250;0.831256;, + 0.480055;0.833255;, + 0.466431;0.833260;, + 0.456669;0.830024;, + 0.393812;0.832157;, + 0.385383;0.831460;, + 0.377789;0.834202;, + 0.445359;0.830391;, + 0.437600;0.830169;, + 0.109740;0.773655;, + 0.394735;0.772286;, + 0.400492;0.771751;, + 0.434800;0.771486;, + 0.095454;0.772777;, + 0.068958;0.775796;, + 0.086328;0.774353;, + 0.039592;0.773128;, + 0.027588;0.773542;, + 0.051030;0.774597;, + 0.415238;0.750555;, + 0.418145;0.769176;, + 0.068759;0.877502;, + 0.013073;0.740827;, + 0.110236;0.754382;, + 0.078908;0.601144;, + 0.100667;0.632553;, + 0.410634;0.615525;, + 0.105165;0.597111;, + 0.392799;0.705637;, + 0.086349;0.723962;, + 0.362779;0.491146;, + 0.362779;0.547658;, + 0.394008;0.495494;, + 0.214445;0.539488;, + 0.312502;0.590996;, + 0.156867;0.556579;, + 0.127949;0.579574;, + 0.296719;0.515014;, + 0.263475;0.504546;, + 0.120939;0.615708;, + 0.274563;0.570659;, + 0.166661;0.506808;, + 0.293936;0.586910;, + 0.259858;0.571459;, + 0.148894;0.749622;, + 0.353177;0.784954;, + 0.127105;0.730907;, + 0.178784;0.760989;, + 0.194710;0.961754;, + 0.315281;0.967981;, + 0.291559;0.752783;, + 0.221894;0.714124;, + 0.202002;0.739201;, + 0.268180;0.965598;, + 0.292247;0.965919;, + 0.250861;0.773185;, + 0.148102;0.666339;, + 0.126837;0.672304;, + 0.166167;0.570639;, + 0.187128;0.679052;, + 0.315261;0.618812;, + 0.788717;0.583537;, + 0.311871;0.695212;, + 0.279010;0.645879;, + 0.176804;0.706885;, + 0.307451;0.723574;, + 0.198839;0.571476;, + 0.742190;0.312541;, + 0.756779;0.321055;, + 0.783375;0.328033;, + 0.826151;0.328571;, + 0.853820;0.325847;, + 0.746033;0.274746;, + 0.762350;0.266262;, + 0.789513;0.267668;, + 0.831224;0.278682;, + 0.857563;0.288782;, + 0.724828;0.460339;, + 0.739319;0.455172;, + 0.757159;0.439798;, + 0.319470;0.975754;, + 0.728309;0.346757;, + 0.745926;0.344262;, + 0.772846;0.351868;, + 0.227252;0.968539;, + 0.861627;0.308441;, + 0.837868;0.327181;, + 0.842297;0.283622;, + 0.314478;0.651182;, + 0.296871;0.876513;, + 0.297319;0.568455;, + 0.170740;0.942462;, + 0.198680;0.942631;, + 0.156747;0.940551;, + 0.346972;0.946444;, + 0.227556;0.941050;, + 0.312837;0.940671;, + 0.263198;0.941498;, + 0.288052;0.942397;, + 0.350771;0.806681;, + 0.325938;0.794862;, + 0.283003;0.794868;, + 0.154964;0.877145;, + 0.209435;0.877359;, + 0.350023;0.880017;, + 0.276004;0.876567;, + 0.248126;0.876903;, + 0.189592;0.877125;, + 0.327467;0.876705;, + 0.216554;0.573159;, + 0.150901;0.696187;, + 0.195986;0.685920;, + 0.333119;0.753106;, + 0.304470;0.794206;, + 0.179704;0.645000;, + 0.750745;0.580656;, + 0.309321;0.711576;, + 0.307301;0.732598;, + 0.309041;0.716968;, + 0.310520;0.703811;, + 0.179110;0.740324;, + 0.196462;0.720314;, + 0.163874;0.727025;, + 0.175639;0.964059;, + 0.784588;0.408840;, + 0.212039;0.963527;, + 0.784082;0.388131;, + 0.790683;0.373480;, + 0.787672;0.372002;, + 0.799093;0.370321;, + 0.819904;0.363746;, + 0.836925;0.361193;, + 0.856879;0.367989;, + 0.852722;0.366515;, + 0.781318;0.421781;, + 0.790151;0.426709;, + 0.802645;0.438063;, + 0.841137;0.441531;, + 0.855986;0.431918;, + 0.818542;0.442967;, + 0.830870;0.443475;, + 0.849598;0.436887;, + 0.861065;0.436308;, + 0.844150;0.363301;, + 0.188198;0.969250;, + 0.200851;0.969815;, + 0.208933;0.976456;, + 0.210538;0.979402;, + 0.211510;0.980889;, + 0.212619;0.987459;, + 0.267032;0.990264;, + 0.282486;0.983817;, + 0.274136;0.985102;, + 0.177024;0.972308;, + 0.172563;0.978070;, + 0.167812;0.984370;, + 0.311368;0.988230;, + 0.296237;0.982643;, + 0.167404;0.988023;, + 0.321700;0.992157;, + 0.303520;0.986512;, + 0.288516;0.983662;, + 0.269855;0.987962;, + 0.751936;0.511608;, + 0.775565;0.511382;, + 0.790667;0.510828;, + 0.742260;0.511058;, + 0.279210;0.591999;, + 0.172625;0.617805;, + 0.296476;0.704697;, + 0.127747;0.694998;, + 0.259571;0.683877;, + 0.281486;0.677693;, + 0.732967;0.488721;, + 0.824812;0.489415;, + 0.811150;0.610036;, + 0.725246;0.572015;, + 0.797433;0.490302;, + 0.757124;0.490022;, + 0.786758;0.613931;, + 0.823818;0.573700;, + 0.726973;0.508449;, + 0.825801;0.540741;, + 0.750561;0.617018;, + 0.726834;0.606098;, + 0.821824;0.510894;, + 0.790460;0.583701;, + 0.752506;0.580815;, + 0.753155;0.511554;, + 0.793248;0.510776;, + 0.740977;0.510621;, + 0.788229;0.614117;, + 0.724265;0.508140;, + 0.752135;0.617252;, + 0.826553;0.510835;, + 0.777823;0.511251;, + 0.754149;0.511440;, + 0.805126;0.511381;, + 0.759526;0.398542;, + 0.761054;0.366386;, + 0.752224;0.439813;, + 0.816369;0.348071;, + 0.763538;0.460181;, + 0.325722;0.477256;, + 0.139382;0.477079;, + 0.309178;0.477331;, + 0.296364;0.477418;, + 0.163540;0.478054;, + 0.175796;0.478097;, + 0.286362;0.477494;, + 0.132862;0.254436;, + 0.127918;0.469878;, + 0.186151;0.449763;, + 0.309627;0.445141;, + 0.276170;0.445173;, + 0.330860;0.471167;, + 0.152834;0.470898;, + 0.307830;0.471332;, + 0.289993;0.471525;, + 0.186773;0.471131;, + 0.205453;0.471226;, + 0.274619;0.471691;, + 0.128523;0.449182;, + 0.124295;0.476901;, + 0.858050;0.395224;, + 0.858013;0.415012;, + 0.124310;0.488385;, + 0.123749;0.539991;, + 0.124616;0.488548;, + 0.124054;0.540154;, + 0.302926;0.495004;, + 0.297025;0.537540;, + 0.178010;0.529774;, + 0.328636;0.518528;, + 0.327249;0.530518;, + 0.324335;0.550706;, + 0.324681;0.568785;, + 0.333339;0.581982;, + 0.332490;0.606632;, + 0.282953;0.499238;, + 0.276441;0.525255;, + 0.337974;0.633179;, + 0.333346;0.662757;, + 0.328709;0.687511;, + 0.296878;0.622255;, + 0.290197;0.647317;, + 0.292952;0.685648;, + 0.140893;0.496067;, + 0.185508;0.505018;, + 0.148854;0.533408;, + 0.166039;0.504534;, + 0.195019;0.954017;, + 0.187293;0.954062;, + 0.297982;0.955639;, + 0.289285;0.955532;, + 0.159912;0.950756;, + 0.134967;0.960262;, + 0.323148;0.959549;, + 0.227794;0.956682;, + 0.209442;0.952609;, + 0.202741;0.953240;, + 0.307318;0.955939;, + 0.280446;0.955762;, + 0.270832;0.955923;, + 0.174324;0.953605;, + 0.170182;0.953177;, + 0.267761;0.956475;, + 0.185260;0.923093;, + 0.166869;0.922238;, + 0.200928;0.922343;, + 0.194040;0.922790;, + 0.271812;0.921277;, + 0.266483;0.921847;, + 0.289591;0.920548;, + 0.296509;0.920667;, + 0.323153;0.922617;, + 0.307532;0.920760;, + 0.149462;0.921383;, + 0.134007;0.919990;, + 0.155182;0.922040;, + 0.211948;0.922290;, + 0.278858;0.921015;, + 0.225949;0.921414;, + 0.194927;0.831623;, + 0.186805;0.832210;, + 0.315217;0.830272;, + 0.301614;0.828454;, + 0.323149;0.830320;, + 0.167299;0.832624;, + 0.152776;0.831645;, + 0.208876;0.832250;, + 0.253050;0.830737;, + 0.267081;0.829903;, + 0.274345;0.830976;, + 0.328922;0.829025;, + 0.338526;0.829644;, + 0.351328;0.831822;, + 0.280209;0.830391;, + 0.287969;0.830169;, + 0.126361;0.773469;, + 0.330834;0.772286;, + 0.325077;0.771751;, + 0.290768;0.771486;, + 0.141975;0.768795;, + 0.164453;0.775643;, + 0.148027;0.773912;, + 0.195235;0.772686;, + 0.207004;0.772233;, + 0.179311;0.769531;, + 0.310331;0.750555;, + 0.307424;0.769176;, + 0.167049;0.878487;, + 0.222577;0.740583;, + 0.127126;0.753815;, + 0.151890;0.600774;, + 0.134216;0.634865;, + 0.314934;0.615524;, + 0.126647;0.597111;, + 0.332770;0.705637;, + 0.149467;0.725011;, + 0.327010;0.495494;, + 0.860789;0.657454;, + 0.978336;0.654931;, + 0.313267;0.411755;, + 0.400447;0.411627;, + 0.536289;0.424917;, + 0.499467;0.433281;, + 0.571290;0.353491;, + 0.590379;0.363402;, + 0.579112;0.483381;, + 0.615218;0.411951;, + 0.665610;0.410428;, + 0.615331;0.353127;, + 0.515344;0.481729;, + 0.498592;0.482057;, + 0.698075;0.478723;, + 0.614392;0.483897;, + 0.645237;0.478272;, + 0.715733;0.529411;, + 0.612983;0.524847;, + 0.523967;0.489788;, + 0.652416;0.486671;, + 0.526120;0.521423;, + 0.653761;0.532059;, + 0.495030;0.522681;, + 0.576437;0.524074;, + 0.715714;0.485627;, + 0.699421;0.485627;, + 0.577420;0.491458;, + 0.615127;0.491934;, + 0.679818;0.486289;, + 0.490235;0.487956;, + 0.635713;0.529981;, + 0.635720;0.486830;, + 0.678267;0.532636;, + 0.486373;0.534489;, + 0.494039;0.535189;, + 0.654239;0.538592;, + 0.679198;0.539289;, + 0.619681;0.536690;, + 0.636359;0.538445;, + 0.527499;0.535352;, + 0.576745;0.536475;, + 0.681707;0.479236;, + 0.716165;0.476668;, + 0.544027;0.484449;, + 0.501868;0.507433;, + 0.493455;0.506823;, + 0.697537;0.508227;, + 0.715163;0.508854;, + 0.550096;0.509441;, + 0.576243;0.509953;, + 0.593682;0.510741;, + 0.612347;0.510925;, + 0.633337;0.509019;, + 0.642214;0.509013;, + 0.687735;0.508461;, + 0.680802;0.508655;, + 0.669120;0.508902;, + 0.628648;0.508941;, + 0.520188;0.508274;, + 0.531694;0.509755;, + 0.653675;0.509091;, + 0.568360;0.596314;, + 0.521581;0.593697;, + 0.615591;0.580289;, + 0.570231;0.714150;, + 0.541700;0.715288;, + 0.505061;0.580731;, + 0.638820;0.606874;, + 0.670871;0.714940;, + 0.522733;0.717029;, + 0.693528;0.607941;, + 0.666459;0.608484;, + 0.706173;0.594310;, + 0.625995;0.593169;, + 0.512624;0.594919;, + 0.545974;0.592953;, + 0.580745;0.598731;, + 0.582736;0.661778;, + 0.592837;0.662044;, + 0.573003;0.661443;, + 0.563094;0.661023;, + 0.549894;0.660271;, + 0.517677;0.658749;, + 0.529421;0.658867;, + 0.647622;0.658026;, + 0.636012;0.658320;, + 0.623324;0.658018;, + 0.540126;0.659521;, + 0.662431;0.658703;, + 0.676303;0.658561;, + 0.685399;0.659635;, + 0.695076;0.660466;, + 0.710549;0.661174;, + 0.544941;0.576131;, + 0.541656;0.556865;, + 0.523025;0.572790;, + 0.563141;0.575307;, + 0.553866;0.374524;, + 0.579122;0.410083;, + 0.715663;0.424895;, + 0.599689;0.345884;, + 0.873230;0.274025;, + 0.898854;0.274219;, + 0.958184;0.540522;, + 0.935286;0.536674;, + 0.874609;0.301468;, + 0.894704;0.289223;, + 0.960279;0.517513;, + 0.923442;0.290776;, + 0.873524;0.323161;, + 0.908654;0.364066;, + 0.990069;0.437218;, + 0.921995;0.366162;, + 0.975391;0.495368;, + 0.936371;0.444829;, + 0.952487;0.485622;, + 0.992783;0.435764;, + 0.927528;0.325647;, + 0.939277;0.476721;, + 0.936325;0.504751;, + 0.946497;0.334246;, + 0.926817;0.477177;, + 0.949882;0.328775;, + 0.900982;0.369442;, + 0.917022;0.367144;, + 0.905700;0.368564;, + 0.885802;0.371364;, + 0.919110;0.361178;, + 0.887784;0.366305;, + 0.883099;0.371914;, + 0.897381;0.369979;, + 0.975720;0.439230;, + 0.952400;0.442506;, + 0.942930;0.443943;, + 0.983446;0.438196;, + 0.987224;0.471182;, + 0.988285;0.492297;, + 0.958862;0.483089;, + 0.957743;0.501239;, + 0.931439;0.365235;, + 0.948438;0.470833;, + 0.954353;0.469827;, + 0.927964;0.338719;, + 0.934931;0.474721;, + 0.927571;0.472571;, + 0.941879;0.487722;, + 0.921776;0.482053;, + 0.939058;0.353581;, + 0.919942;0.473511;, + 0.912300;0.476143;, + 0.946882;0.345223;, + 0.929139;0.466241;, + 0.944801;0.363381;, + 0.917960;0.459364;, + 0.913105;0.460961;, + 0.949839;0.357962;, + 1.000000;1.000000;, + 0.950983;0.367857;, + 0.913408;0.450900;, + 0.911252;0.451536;, + 0.953230;0.365413;, + 0.915244;0.449142;, + 0.900640;0.363431;, + 0.913324;0.367647;, + 0.890638;0.370774;, + 0.876313;0.372530;, + 0.928631;0.365429;, + 0.959662;0.441499;, + 0.968760;0.440024;, + 0.918587;0.373211;, + 0.921969;0.372736;, + 0.927792;0.372084;, + 0.930233;0.371906;, + 0.936779;0.438485;, + 0.942792;0.437735;, + 0.919984;0.379212;, + 0.922713;0.378822;, + 0.927354;0.378302;, + 0.929268;0.378172;, + 0.937025;0.432481;, + 0.941818;0.431883;, + 0.919581;0.384226;, + 0.922252;0.383857;, + 0.926937;0.383332;, + 0.928951;0.383176;, + 0.937170;0.427349;, + 0.942009;0.426744;, + 0.918353;0.388611;, + 0.921672;0.388155;, + 0.927494;0.387502;, + 0.929998;0.387306;, + 0.936685;0.423466;, + 0.942698;0.422715;, + 0.918796;0.395081;, + 0.921850;0.394655;, + 0.927143;0.394062;, + 0.929382;0.393895;, + 0.936942;0.417357;, + 0.942408;0.416675;, + 0.920034;0.399980;, + 0.922304;0.399663;, + 0.926264;0.399219;, + 0.927954;0.399093;, + 0.937559;0.412281;, + 0.941648;0.411769;, + 0.919307;0.404223;, + 0.921874;0.403869;, + 0.926387;0.403363;, + 0.928332;0.403212;, + 0.937409;0.408406;, + 0.942069;0.407823;, + 0.917905;0.407449;, + 0.921148;0.407016;, + 0.926970;0.406363;, + 0.929548;0.406145;, + 0.936795;0.405668;, + 0.942807;0.404917;, + 0.918548;0.413426;, + 0.921333;0.413058;, + 0.926395;0.412491;, + 0.928671;0.412292;, + 0.937141;0.399905;, + 0.942368;0.399251;, + 0.920875;0.417398;, + 0.922434;0.417195;, + 0.925394;0.416864;, + 0.926796;0.416735;, + 0.937785;0.395465;, + 0.940842;0.395081;, + 0.922919;0.418989;, + 0.924915;0.418765;, + 0.901952;0.377814;, + 0.905828;0.377270;, + 0.912504;0.376521;, + 0.915302;0.376318;, + 0.952663;0.433953;, + 0.959556;0.433094;, + 0.903532;0.386027;, + 0.906660;0.385579;, + 0.911981;0.384983;, + 0.914175;0.384834;, + 0.952869;0.425673;, + 0.958364;0.424987;, + 0.903053;0.392854;, + 0.906115;0.392431;, + 0.911486;0.391829;, + 0.913794;0.391650;, + 0.953130;0.418898;, + 0.958676;0.418205;, + 0.901631;0.398799;, + 0.905435;0.398276;, + 0.912109;0.397528;, + 0.914980;0.397303;, + 0.952576;0.413568;, + 0.959469;0.412708;, + 0.902116;0.407623;, + 0.905616;0.407134;, + 0.911684;0.406454;, + 0.914251;0.406263;, + 0.952875;0.405219;, + 0.959141;0.404437;, + 0.903517;0.414330;, + 0.906120;0.413967;, + 0.910659;0.413459;, + 0.912596;0.413313;, + 0.953585;0.398356;, + 0.958273;0.397770;, + 0.902669;0.420094;, + 0.905613;0.419688;, + 0.910786;0.419108;, + 0.913016;0.418935;, + 0.953416;0.393054;, + 0.958758;0.392386;, + 0.901052;0.424454;, + 0.904769;0.423957;, + 0.911443;0.423209;, + 0.914399;0.422959;, + 0.952714;0.389283;, + 0.959606;0.388422;, + 0.901767;0.432611;, + 0.904961;0.432189;, + 0.910763;0.431539;, + 0.913372;0.431311;, + 0.953114;0.381429;, + 0.959106;0.380679;, + 0.904421;0.438084;, + 0.906207;0.437851;, + 0.909601;0.437471;, + 0.911209;0.437325;, + 0.953855;0.375458;, + 0.957360;0.375018;, + 0.906757;0.440305;, + 0.909046;0.440049;, + 0.886697;0.379215;, + 0.890457;0.378707;, + 0.896932;0.378021;, + 0.899646;0.377844;, + 0.968718;0.432149;, + 0.975405;0.431354;, + 0.888142;0.386760;, + 0.891176;0.386342;, + 0.896337;0.385796;, + 0.898465;0.385667;, + 0.969012;0.424526;, + 0.974343;0.423891;, + 0.887606;0.393030;, + 0.890576;0.392636;, + 0.895785;0.392084;, + 0.898024;0.391927;, + 0.969344;0.418289;, + 0.974724;0.417647;, + 0.886166;0.398492;, + 0.889856;0.398005;, + 0.896330;0.397319;, + 0.899114;0.397121;, + 0.968874;0.413398;, + 0.975560;0.412602;, + 0.886544;0.406601;, + 0.889939;0.406144;, + 0.895825;0.405521;, + 0.898314;0.405354;, + 0.969265;0.405734;, + 0.975344;0.405010;, + 0.887831;0.412762;, + 0.890355;0.412423;, + 0.894759;0.411957;, + 0.896637;0.411830;, + 0.970033;0.399417;, + 0.974581;0.398875;, + 0.886950;0.418057;, + 0.889805;0.417679;, + 0.894822;0.417148;, + 0.896985;0.416995;, + 0.969934;0.394550;, + 0.975116;0.393932;, + 0.885337;0.422064;, + 0.888943;0.421602;, + 0.895416;0.420917;, + 0.898283;0.420694;, + 0.969302;0.391091;, + 0.975987;0.390294;, + 0.885945;0.429560;, + 0.889043;0.429168;, + 0.894671;0.428572;, + 0.897201;0.428368;, + 0.969784;0.383876;, + 0.975597;0.383182;, + 0.888458;0.434587;, + 0.890191;0.434371;, + 0.893483;0.434023;, + 0.895042;0.433891;, + 0.970570;0.378374;, + 0.973970;0.377966;, + 0.890699;0.436626;, + 0.892918;0.436391;, + 0.873590;0.378201;, + 0.876754;0.377927;, + 0.882197;0.377665;, + 0.884478;0.377676;, + 0.983808;0.432077;, + 0.989434;0.431709;, + 0.874466;0.383837;, + 0.877019;0.383608;, + 0.881358;0.383399;, + 0.883146;0.383419;, + 0.984483;0.426530;, + 0.988968;0.426236;, + 0.873741;0.388449;, + 0.876240;0.388241;, + 0.880620;0.388030;, + 0.882501;0.388027;, + 0.984975;0.421784;, + 0.989502;0.421487;, + 0.872297;0.392437;, + 0.875400;0.392181;, + 0.880844;0.391919;, + 0.883183;0.391913;, + 0.984828;0.418156;, + 0.990454;0.417787;, + 0.872256;0.398460;, + 0.875112;0.398216;, + 0.880061;0.397978;, + 0.882153;0.397983;, + 0.985540;0.412506;, + 0.990654;0.412170;, + 0.873061;0.403065;, + 0.875184;0.402884;, + 0.878886;0.402706;, + 0.880465;0.402709;, + 0.986482;0.407841;, + 0.990308;0.407589;, + 0.872091;0.406953;, + 0.874492;0.406754;, + 0.878711;0.406551;, + 0.880528;0.406547;, + 0.986642;0.404240;, + 0.991003;0.403953;, + 0.870567;0.409862;, + 0.873600;0.409628;, + 0.879042;0.409366;, + 0.881452;0.409338;, + 0.986290;0.401667;, + 0.991915;0.401297;, + 0.994179;0.395552;, + 0.991526;0.395405;, + 0.878083;0.415017;, + 0.880210;0.414985;, + 0.987050;0.396345;, + 0.991941;0.396022;, + 0.872625;0.419247;, + 0.874082;0.419141;, + 0.876850;0.419008;, + 0.878160;0.418981;, + 0.987960;0.392274;, + 0.990821;0.392084;, + 0.874408;0.420834;, + 0.876274;0.420745;, + 0.914444;0.330564;, + 0.962526;0.444760;, + 0.947098;0.447390;, + 0.979132;0.443610;, + 0.985271;0.454609;, + 0.930510;0.349332;, + 0.967355;0.470956;, + 0.895790;0.329672;, + 0.886980;0.274433;, + 0.919031;0.270101;, + 0.979186;0.534000;, + 0.947140;0.538822;, + 0.957002;0.521258;, + 0.942677;0.521568;, + 0.893105;0.283020;, + 0.900449;0.283372;, + 0.922519;0.283117;, + 0.928835;0.282544;, + 0.874763;0.291310;, + 0.881797;0.290567;, + 0.984320;0.517049;, + 0.965323;0.519657;, + 0.518646;0.336598;, + 0.519827;0.371410;, + 0.671119;0.374923;, + 0.486141;0.378023;, + 0.588878;0.384537;, + 0.569369;0.436791;, + 0.534201;0.395395;, + 0.634315;0.390683;, + 0.607304;0.371257;, + 0.535522;0.425621;, + 0.498701;0.433986;, + 0.570523;0.354195;, + 0.589889;0.363950;, + 0.579469;0.482740;, + 0.614731;0.411675;, + 0.665839;0.411302;, + 0.615331;0.353206;, + 0.514578;0.482433;, + 0.498517;0.482369;, + 0.698304;0.479598;, + 0.614112;0.483887;, + 0.645466;0.479147;, + 0.715264;0.526177;, + 0.613551;0.534271;, + 0.531096;0.486869;, + 0.661319;0.486708;, + 0.533898;0.532181;, + 0.661506;0.529282;, + 0.504149;0.531138;, + 0.578216;0.532151;, + 0.715484;0.485370;, + 0.707527;0.484666;, + 0.579350;0.488162;, + 0.611873;0.490245;, + 0.684034;0.484824;, + 0.499835;0.486315;, + 0.635407;0.528739;, + 0.636344;0.485738;, + 0.685374;0.525285;, + 0.485483;0.536544;, + 0.504181;0.535788;, + 0.662302;0.538686;, + 0.686436;0.536711;, + 0.619347;0.535324;, + 0.637355;0.536477;, + 0.534074;0.539453;, + 0.580776;0.536237;, + 0.681936;0.480111;, + 0.716394;0.477543;, + 0.543261;0.485154;, + 0.512380;0.507259;, + 0.504256;0.507372;, + 0.707913;0.505918;, + 0.715722;0.505571;, + 0.553334;0.507820;, + 0.578888;0.508498;, + 0.595809;0.509229;, + 0.612006;0.510097;, + 0.636064;0.506550;, + 0.642318;0.506299;, + 0.693723;0.505835;, + 0.684686;0.505729;, + 0.670350;0.505681;, + 0.629570;0.506812;, + 0.529308;0.507480;, + 0.536796;0.507313;, + 0.661416;0.507466;, + 0.517391;0.595133;, + 0.564857;0.592438;, + 0.620836;0.580957;, + 0.510599;0.715034;, + 0.533576;0.715994;, + 0.581447;0.576337;, + 0.651435;0.606044;, + 0.671670;0.716734;, + 0.561921;0.715897;, + 0.698810;0.603964;, + 0.674236;0.605860;, + 0.714006;0.590496;, + 0.634894;0.593138;, + 0.573783;0.592411;, + 0.540258;0.592834;, + 0.504639;0.596143;, + 0.509154;0.659816;, + 0.499862;0.659718;, + 0.514719;0.660512;, + 0.521908;0.660850;, + 0.535305;0.660098;, + 0.572964;0.654723;, + 0.560465;0.658285;, + 0.662012;0.654201;, + 0.650061;0.654890;, + 0.638790;0.656414;, + 0.548662;0.659348;, + 0.673319;0.653810;, + 0.686816;0.653084;, + 0.698475;0.652173;, + 0.586011;0.659448;, + 0.579484;0.655725;, + 0.541523;0.575780;, + 0.545091;0.556142;, + 0.563590;0.570593;, + 0.522875;0.573126;, + 0.553099;0.375229;, + 0.578355;0.410788;, + 0.715892;0.425770;, + 0.599584;0.345902;, + 0.869675;0.267770;, + 0.891620;0.274340;, + 0.956631;0.542084;, + 0.936131;0.537141;, + 0.875823;0.291903;, + 0.893307;0.290193;, + 0.959778;0.518762;, + 0.919671;0.294804;, + 0.874479;0.328054;, + 0.905832;0.366700;, + 0.991250;0.437386;, + 0.918895;0.367352;, + 0.973930;0.494549;, + 0.935919;0.443871;, + 0.950260;0.484642;, + 0.995481;0.435612;, + 0.924402;0.321874;, + 0.936502;0.475754;, + 0.934527;0.502788;, + 0.947699;0.339652;, + 0.925497;0.472065;, + 0.951238;0.332417;, + 0.899767;0.368320;, + 0.915033;0.365409;, + 0.903303;0.370687;, + 0.885310;0.370839;, + 0.916506;0.360664;, + 0.886275;0.368562;, + 0.881875;0.374620;, + 0.895343;0.372597;, + 0.976255;0.439156;, + 0.952245;0.441938;, + 0.942662;0.443125;, + 0.984457;0.438215;, + 0.987884;0.470638;, + 0.988977;0.491286;, + 0.957438;0.482110;, + 0.956048;0.499888;, + 0.928789;0.362833;, + 0.947826;0.469637;, + 0.954265;0.468662;, + 0.925919;0.332234;, + 0.933349;0.473352;, + 0.927207;0.467318;, + 0.938676;0.486689;, + 0.920476;0.476691;, + 0.942098;0.355717;, + 0.917880;0.468511;, + 0.911620;0.470496;, + 0.948399;0.350490;, + 0.927114;0.461639;, + 0.948339;0.363541;, + 0.915516;0.454745;, + 0.911867;0.455840;, + 0.952128;0.361098;, + 0.919864;0.450733;, + 0.954704;0.366563;, + 0.910633;0.446448;, + 0.909327;0.446777;, + 0.956207;0.366122;, + 0.912421;0.444793;, + 0.898308;0.365823;, + 0.910559;0.369492;, + 0.888924;0.373638;, + 0.875394;0.375543;, + 0.925274;0.366156;, + 0.959696;0.441092;, + 0.969126;0.439797;, + 0.946551;0.435660;, + 0.944197;0.435084;, + 0.924834;0.372188;, + 0.927874;0.369346;, + 0.936435;0.437653;, + 0.942611;0.437033;, + 0.918336;0.376837;, + 0.920307;0.378600;, + 0.924728;0.377903;, + 0.927179;0.375442;, + 0.936819;0.431756;, + 0.941743;0.431260;, + 0.918002;0.382171;, + 0.920028;0.383564;, + 0.924491;0.382858;, + 0.926928;0.380758;, + 0.937546;0.426583;, + 0.942517;0.426082;, + 0.917018;0.386350;, + 0.919551;0.388025;, + 0.925096;0.387150;, + 0.928109;0.384601;, + 0.936815;0.422845;, + 0.942991;0.422224;, + 0.917843;0.391984;, + 0.920124;0.393698;, + 0.925165;0.392903;, + 0.927926;0.390393;, + 0.936796;0.416961;, + 0.942410;0.416396;, + 0.919169;0.396797;, + 0.920867;0.398064;, + 0.924640;0.397465;, + 0.926715;0.395600;, + 0.937739;0.411927;, + 0.941942;0.411503;, + 0.918694;0.400689;, + 0.920646;0.402013;, + 0.924945;0.401331;, + 0.927293;0.399326;, + 0.937422;0.408184;, + 0.942210;0.407701;, + 0.917571;0.403505;, + 0.920137;0.404827;, + 0.925683;0.403949;, + 0.928663;0.401749;, + 0.936576;0.405558;, + 0.942753;0.404935;, + 0.918567;0.408659;, + 0.920806;0.409677;, + 0.925629;0.408910;, + 0.928213;0.407126;, + 0.936823;0.399965;, + 0.942195;0.399422;, + 0.920804;0.412883;, + 0.922075;0.413388;, + 0.924898;0.412934;, + 0.926450;0.411976;, + 0.938017;0.395490;, + 0.941162;0.395171;, + 0.922702;0.414751;, + 0.924606;0.414444;, + 0.901020;0.376297;, + 0.903892;0.378556;, + 0.910249;0.377557;, + 0.913734;0.374299;, + 0.952605;0.433562;, + 0.959684;0.432851;, + 0.902829;0.384176;, + 0.905088;0.386198;, + 0.910156;0.385399;, + 0.912966;0.382578;, + 0.953165;0.425379;, + 0.958810;0.424811;, + 0.902468;0.391336;, + 0.904790;0.392933;, + 0.909907;0.392123;, + 0.912701;0.389716;, + 0.953864;0.418645;, + 0.959563;0.418070;, + 0.901359;0.397016;, + 0.904262;0.398936;, + 0.910620;0.397933;, + 0.914074;0.395011;, + 0.953027;0.413502;, + 0.960107;0.412790;, + 0.902334;0.404835;, + 0.904949;0.406801;, + 0.910728;0.405890;, + 0.913893;0.403013;, + 0.953007;0.405443;, + 0.959443;0.404795;, + 0.903877;0.411410;, + 0.905823;0.412862;, + 0.910148;0.412176;, + 0.912527;0.410037;, + 0.954090;0.398652;, + 0.958908;0.398166;, + 0.903351;0.416741;, + 0.905589;0.418259;, + 0.910517;0.417478;, + 0.913209;0.415179;, + 0.953727;0.393522;, + 0.959217;0.392968;, + 0.902077;0.420610;, + 0.905019;0.422126;, + 0.911377;0.421119;, + 0.914793;0.418597;, + 0.952759;0.389894;, + 0.959840;0.389180;, + 0.903247;0.427782;, + 0.905813;0.428948;, + 0.911342;0.428069;, + 0.914305;0.426024;, + 0.953043;0.382263;, + 0.959202;0.381641;, + 0.905831;0.433515;, + 0.907288;0.434093;, + 0.910524;0.433573;, + 0.912302;0.432475;, + 0.954414;0.376274;, + 0.958019;0.375908;, + 0.908014;0.436040;, + 0.910197;0.435688;, + 0.886462;0.378350;, + 0.889248;0.380562;, + 0.895415;0.379631;, + 0.898797;0.376490;, + 0.969164;0.432079;, + 0.976032;0.431427;, + 0.888116;0.385590;, + 0.890308;0.387567;, + 0.895226;0.386822;, + 0.897951;0.384102;, + 0.969812;0.424541;, + 0.975288;0.424020;, + 0.887686;0.392198;, + 0.889939;0.393763;, + 0.894903;0.393008;, + 0.897614;0.390688;, + 0.970571;0.418336;, + 0.976099;0.417809;, + 0.886541;0.397415;, + 0.889358;0.399297;, + 0.895526;0.398363;, + 0.898877;0.395548;, + 0.969828;0.413622;, + 0.976697;0.412968;, + 0.887382;0.404568;, + 0.889919;0.406492;, + 0.895526;0.405643;, + 0.898596;0.402871;, + 0.969914;0.406230;, + 0.976158;0.405636;, + 0.888797;0.410616;, + 0.890686;0.412037;, + 0.894882;0.411398;, + 0.897189;0.409337;, + 0.971047;0.399978;, + 0.975720;0.399531;, + 0.888220;0.415505;, + 0.890391;0.416991;, + 0.895172;0.416264;, + 0.897783;0.414049;, + 0.970763;0.395271;, + 0.976088;0.394763;, + 0.886935;0.419043;, + 0.889789;0.420533;, + 0.895957;0.419595;, + 0.899271;0.417168;, + 0.969873;0.391947;, + 0.976742;0.391292;, + 0.887972;0.425601;, + 0.890462;0.426749;, + 0.895826;0.425931;, + 0.898700;0.423963;, + 0.970247;0.384942;, + 0.976222;0.384371;, + 0.890410;0.430892;, + 0.891823;0.431463;, + 0.894963;0.430978;, + 0.896688;0.429923;, + 0.971646;0.379415;, + 0.975143;0.379079;, + 0.892499;0.433232;, + 0.894616;0.432903;, + 0.873872;0.377973;, + 0.876220;0.379989;, + 0.881417;0.379511;, + 0.884266;0.377016;, + 0.984894;0.432226;, + 0.990673;0.431971;, + 0.874913;0.383392;, + 0.876760;0.385179;, + 0.880904;0.384796;, + 0.883200;0.382625;, + 0.985712;0.426784;, + 0.990320;0.426580;, + 0.874264;0.388323;, + 0.876163;0.389764;, + 0.880345;0.389374;, + 0.882630;0.387543;, + 0.986773;0.422001;, + 0.991425;0.421794;, + 0.873056;0.392136;, + 0.875429;0.393874;, + 0.880627;0.393393;, + 0.883450;0.391174;, + 0.986405;0.418515;, + 0.992184;0.418259;, + 0.873392;0.397396;, + 0.875529;0.399156;, + 0.880254;0.398719;, + 0.882841;0.396521;, + 0.986871;0.413082;, + 0.992125;0.412849;, + 0.874295;0.401938;, + 0.875886;0.403239;, + 0.879422;0.402908;, + 0.881366;0.401276;, + 0.988130;0.408461;, + 0.992063;0.408285;, + 0.873570;0.405513;, + 0.875399;0.406883;, + 0.879428;0.406507;, + 0.881628;0.404760;, + 0.988142;0.404988;, + 0.992623;0.404789;, + 0.872311;0.408050;, + 0.874716;0.409457;, + 0.879914;0.408973;, + 0.882707;0.407081;, + 0.987578;0.402524;, + 0.993359;0.402267;, + 0.872840;0.412876;, + 0.874937;0.413976;, + 0.879457;0.413552;, + 0.881880;0.412028;, + 0.988259;0.397367;, + 0.993286;0.397142;, + 0.874650;0.416931;, + 0.875841;0.417487;, + 0.878486;0.417234;, + 0.879940;0.416425;, + 0.989694;0.393267;, + 0.992637;0.393134;, + 0.876305;0.418781;, + 0.878089;0.418609;, + 0.911057;0.330810;, + 0.962285;0.444429;, + 0.946781;0.446617;, + 0.979370;0.443607;, + 0.986266;0.454302;, + 0.928386;0.343665;, + 0.967542;0.470029;, + 0.896709;0.331334;, + 0.879637;0.273628;, + 0.911211;0.271340;, + 0.978944;0.536142;, + 0.945667;0.539949;, + 0.955485;0.522522;, + 0.942009;0.522236;, + 0.891179;0.290655;, + 0.898435;0.289028;, + 0.916592;0.283109;, + 0.923544;0.279476;, + 0.872025;0.285035;, + 0.877537;0.287973;, + 0.984743;0.519101;, + 0.964298;0.521165;, + 0.517879;0.337303;, + 0.520333;0.371133;, + 0.671348;0.375798;, + 0.485728;0.377416;, + 0.588111;0.385241;, + 0.568603;0.437496;, + 0.533434;0.396100;, + 0.634543;0.391558;, + 0.608087;0.371187;, + 0.877145;0.707672;, + 0.960400;0.709690;, + 0.077470;0.007941;, + 0.118900;0.021439;, + 0.160343;0.007951;, + 0.096191;0.017550;, + 0.140289;0.017968;, + 0.746671;0.625954;, + 0.734244;0.671234;, + 0.732498;0.666622;, + 0.900272;0.786620;, + 0.731710;0.674849;, + 0.736027;0.666579;, + 0.900272;0.728227;, + 0.732977;0.667789;, + 0.734000;0.718795;, + 0.761074;0.747759;, + 0.736147;0.623785;, + 0.737496;0.718913;, + 0.734226;0.717671;, + 0.732523;0.718817;, + 0.810386;0.782411;, + 0.734467;0.716557;, + 0.851573;0.787367;, + 0.870436;0.732683;, + 0.553889;0.962996;, + 0.734131;0.719579;, + 0.720172;0.621381;, + 0.735588;0.646949;, + 0.030986;0.280838;, + 0.076380;0.281037;, + 0.076934;0.343481;, + 0.096103;0.280763;, + 0.095504;0.343480;, + 0.032738;0.343592;, + 0.000699;0.307701;, + 0.020304;0.311989;, + 0.047293;0.346485;, + 0.843288;0.736734;, + 0.053339;0.280612;, + 0.736338;0.664520;, + 0.725489;0.717083;, + 0.744737;0.664570;, + 0.721900;0.673406;, + 0.745925;0.715421;, + 0.562853;0.971381;, + 0.737065;0.715344;, + 0.733007;0.717941;, + 0.727989;0.737487;, + 0.733483;0.671167;, + 0.719031;0.668882;, + 0.834806;0.663521;, + 0.835007;0.658223;, + 0.834090;0.664155;, + 0.833989;0.663805;, + 0.829690;0.670101;, + 0.835801;0.668607;, + 0.835224;0.668707;, + 0.835029;0.670638;, + 0.835300;0.663893;, + 0.823120;0.662826;, + 0.832812;0.669285;, + 0.834416;0.664233;, + 0.835037;0.669733;, + 0.834887;0.666282;, + 0.561345;0.969626;, + 0.834183;0.666440;, + 0.834986;0.637076;, + 0.834482;0.664408;, + 0.835577;0.670567;, + 0.833537;0.664226;, + 0.834299;0.670158;, + 0.834830;0.672989;, + 0.833870;0.666754;, + 0.744960;0.730714;, + 0.834660;0.670688;, + 0.834070;0.669709;, + 0.832908;0.665243;, + 0.835705;0.664286;, + 0.737865;0.662673;, + 0.785973;0.667074;, + 0.787948;0.715301;, + 0.783925;0.625418;, + 0.783915;0.623808;, + 0.788056;0.716995;, + 0.784784;0.667199;, + 0.776092;0.624747;, + 0.775797;0.671137;, + 0.776148;0.714559;, + 0.786121;0.625026;, + 0.786733;0.665233;, + 0.789037;0.713793;, + 0.789604;0.625259;, + 0.792483;0.668681;, + 0.795224;0.714966;, + 0.789775;0.626794;, + 0.791308;0.716656;, + 0.788398;0.671637;, + 0.794055;0.624668;, + 0.793033;0.715686;, + 0.793153;0.675128;, + 0.789065;0.672254;, + 0.790982;0.624697;, + 0.788096;0.715701;, + 0.787237;0.625265;, + 0.782224;0.716131;, + 0.785418;0.669593;, + 0.786326;0.625266;, + 0.788118;0.668707;, + 0.790773;0.716699;, + 0.781179;0.626686;, + 0.783592;0.674061;, + 0.784872;0.713970;, + 0.792927;0.627680;, + 0.788729;0.713246;, + 0.790605;0.673075;, + 0.790030;0.625399;, + 0.791012;0.673650;, + 0.792563;0.715100;, + 0.794127;0.624315;, + 0.794834;0.671248;, + 0.795672;0.713800;, + 0.789358;0.626194;, + 0.791458;0.670782;, + 0.793092;0.716678;, + 0.788395;0.624014;, + 0.787444;0.664515;, + 0.787465;0.716819;, + 0.787466;0.627272;, + 0.786838;0.716115;, + 0.782936;0.672655;, + 0.789318;0.623431;, + 0.791531;0.717724;, + 0.791033;0.671303;, + 0.789060;0.669716;, + 0.787419;0.626528;, + 0.791040;0.712023;, + 0.785307;0.628266;, + 0.786651;0.674963;, + 0.788611;0.715906;, + 0.794461;0.691096;, + 0.735370;0.683056;, + 0.774251;0.692068;, + 0.799990;0.689774;, + 0.888227;0.790976;, + 0.835395;0.665671;, + 0.836233;0.664675;, + 0.627047;0.766014;, + 0.744572;0.715680;, + 0.736329;0.716113;, + 0.734454;0.717191;, + 0.735098;0.716966;, + 0.990159;0.782411;, + 0.734561;0.716147;, + 0.948971;0.787367;, + 0.930109;0.732683;, + 0.553889;0.962996;, + 0.734728;0.719064;, + 0.720913;0.621553;, + 0.735588;0.646949;, + 0.202979;0.278588;, + 0.159030;0.278453;, + 0.158950;0.343644;, + 0.137414;0.278462;, + 0.138487;0.343650;, + 0.204731;0.346559;, + 0.233593;0.308306;, + 0.216053;0.311410;, + 0.194414;0.346637;, + 0.957257;0.736734;, + 0.190507;0.280790;, + 0.742980;0.665126;, + 0.723160;0.707602;, + 0.740648;0.670873;, + 0.723155;0.622981;, + 0.739766;0.716934;, + 0.562853;0.971381;, + 0.733230;0.718871;, + 0.734658;0.719848;, + 0.659531;0.747477;, + 0.734644;0.670166;, + 0.721758;0.660849;, + 0.834509;0.661387;, + 0.835535;0.668135;, + 0.835670;0.666180;, + 0.834486;0.664209;, + 0.835569;0.668806;, + 0.833301;0.672000;, + 0.833602;0.671423;, + 0.834827;0.669711;, + 0.835528;0.660376;, + 0.834968;0.660657;, + 0.834747;0.664916;, + 0.834723;0.664911;, + 0.834790;0.666129;, + 0.834147;0.668202;, + 0.561345;0.969626;, + 0.836388;0.669082;, + 0.835301;0.637076;, + 0.834482;0.664408;, + 0.835101;0.665603;, + 0.834303;0.669128;, + 0.835741;0.665606;, + 0.833432;0.665737;, + 0.834464;0.665420;, + 0.642311;0.740696;, + 0.834776;0.666456;, + 0.834707;0.669011;, + 0.834423;0.666673;, + 0.833723;0.664507;, + 0.743295;0.664272;, + 0.778282;0.671219;, + 0.780253;0.710248;, + 0.775491;0.629282;, + 0.775715;0.625039;, + 0.775269;0.711772;, + 0.775669;0.666770;, + 0.776430;0.624558;, + 0.773472;0.669872;, + 0.782015;0.718525;, + 0.776570;0.627422;, + 0.778013;0.664842;, + 0.779315;0.713218;, + 0.789332;0.622118;, + 0.789420;0.664889;, + 0.792645;0.717509;, + 0.786473;0.622338;, + 0.792480;0.716735;, + 0.789424;0.671332;, + 0.789729;0.625677;, + 0.790252;0.715710;, + 0.789600;0.668773;, + 0.791820;0.669964;, + 0.789582;0.625337;, + 0.793545;0.715484;, + 0.788233;0.624304;, + 0.790431;0.718265;, + 0.790284;0.670447;, + 0.785843;0.626007;, + 0.782577;0.667710;, + 0.783500;0.716741;, + 0.790782;0.625718;, + 0.792564;0.716505;, + 0.791922;0.671684;, + 0.794635;0.627982;, + 0.794680;0.715878;, + 0.796221;0.672350;, + 0.788721;0.627413;, + 0.789794;0.670452;, + 0.791182;0.714226;, + 0.790307;0.624378;, + 0.792533;0.671815;, + 0.793801;0.716549;, + 0.784641;0.627340;, + 0.786011;0.670554;, + 0.787199;0.717576;, + 0.790351;0.663633;, + 0.793786;0.630159;, + 0.792190;0.703334;, + 0.795066;0.628478;, + 0.796832;0.714275;, + 0.796356;0.670301;, + 0.791512;0.670914;, + 0.793029;0.706406;, + 0.784249;0.635497;, + 0.771596;0.664582;, + 0.771802;0.630441;, + 0.773771;0.712776;, + 0.788489;0.625167;, + 0.799017;0.715708;, + 0.789250;0.665407;, + 0.796848;0.652952;, + 0.734108;0.683056;, + 0.774251;0.692068;, + 0.799990;0.689774;, + 0.912318;0.790976;, + 0.835605;0.668551;, + 0.834549;0.669792;, + 0.902768;0.883465;, + 0.904724;0.885479;, + 0.902228;0.888187;, + 0.898316;0.888187;, + 0.895821;0.885479;, + 0.897777;0.883465;, + 0.898265;0.798929;, + 0.902280;0.798929;, + 0.904863;0.804096;, + 0.902855;0.809357;, + 0.897690;0.809357;, + 0.895682;0.804096;, + 0.902280;0.790246;, + 0.898265;0.790246;, + 0.902880;0.857875;, + 0.905375;0.862172;, + 0.902768;0.863497;, + 0.897777;0.863497;, + 0.895169;0.862172;, + 0.897665;0.857875;, + 0.897777;0.869929;, + 0.902768;0.869929;, + 0.902768;0.875028;, + 0.897777;0.875028;, + 0.893694;0.933727;, + 0.885232;0.932009;, + 0.892792;0.930218;, + 0.898382;0.930471;, + 0.902162;0.930471;, + 0.907753;0.930218;, + 0.915313;0.932009;, + 0.906851;0.933727;, + 0.906851;0.948663;, + 0.906851;0.952882;, + 0.893694;0.952882;, + 0.893694;0.948663;, + 0.898382;0.921391;, + 0.902162;0.921391;, + 0.902162;0.926208;, + 0.898382;0.926208;, + 0.904359;0.976397;, + 0.908446;0.983814;, + 0.904359;0.987846;, + 0.896186;0.987846;, + 0.892099;0.983814;, + 0.896186;0.976397;, + 0.890317;0.960901;, + 0.887826;0.955517;, + 0.893694;0.954704;, + 0.906851;0.954704;, + 0.912719;0.955517;, + 0.910227;0.960901;, + 0.904359;0.964521;, + 0.896186;0.964521;, + 0.902162;0.914181;, + 0.902162;0.917807;, + 0.898382;0.917807;, + 0.898382;0.914181;, + 0.898382;0.906892;, + 0.895345;0.904106;, + 0.897235;0.900407;, + 0.903310;0.900407;, + 0.905199;0.904106;, + 0.902162;0.906892;, + 0.893278;0.895433;, + 0.893172;0.893912;, + 0.895173;0.891507;, + 0.898316;0.890593;, + 0.902228;0.890593;, + 0.905371;0.891507;, + 0.907373;0.893912;, + 0.907267;0.895433;, + 0.903310;0.896025;, + 0.897235;0.896025;, + 0.809585;0.995319;, + 0.809585;0.995319;, + 0.796174;0.997421;, + 0.680570;0.784109;, + 0.928526;0.597825;, + 0.911482;0.597825;, + 0.707399;0.779975;, + 0.796174;0.997421;, + 0.560395;0.749918;, + 0.553202;0.749918;, + 0.907074;0.649439;, + 0.911482;0.636891;, + 0.928526;0.636891;, + 0.932934;0.649439;, + 0.543036;0.821058;, + 0.553587;0.805318;, + 0.560009;0.805318;, + 0.570560;0.821058;, + 0.896186;0.998590;, + 0.904359;0.998590;, + 0.853099;0.996938;, + 0.853099;0.996938;, + 0.883254;0.975313;, + 0.880549;0.981966;, + 0.868039;0.983920;, + 0.861578;0.975339;, + 0.868286;0.967611;, + 0.877687;0.970762;, + 0.723494;0.934189;, + 0.746615;0.939569;, + 0.750123;0.952141;, + 0.752018;0.752872;, + 0.760772;0.738986;, + 0.765195;0.741466;, + 0.806068;0.843381;, + 0.808596;0.847477;, + 0.810932;0.854328;, + 0.813587;0.861508;, + 0.814928;0.876023;, + 0.811185;0.878414;, + 0.800855;0.868571;, + 0.799856;0.854877;, + 0.699911;0.911896;, + 0.703264;0.913021;, + 0.706468;0.908363;, + 0.706162;0.903342;, + 0.714873;0.897777;, + 0.723917;0.904455;, + 0.716064;0.916632;, + 0.767956;0.739408;, + 0.806619;0.772049;, + 0.820056;0.785642;, + 0.814083;0.790165;, + 0.809808;0.792812;, + 0.806591;0.792094;, + 0.804323;0.784892;, + 0.700241;0.822974;, + 0.693042;0.817639;, + 0.688890;0.819799;, + 0.818973;0.810336;, + 0.819099;0.812192;, + 0.836745;0.213089;, + 0.835593;0.219284;, + 0.816293;0.818786;, + 0.815805;0.820421;, + 0.814192;0.825581;, + 0.811307;0.821517;, + 0.812778;0.808834;, + 0.816886;0.806200;, + 0.878804;0.857303;, + 0.881376;0.861716;, + 0.878829;0.869526;, + 0.875890;0.874631;, + 0.874610;0.876410;, + 0.872738;0.877913;, + 0.872011;0.878691;, + 0.875817;0.878190;, + 0.870373;0.868288;, + 0.874192;0.861851;, + 0.878967;0.896213;, + 0.879498;0.898184;, + 0.884256;0.898560;, + 0.888144;0.899414;, + 0.886178;0.903064;, + 0.880760;0.905962;, + 0.878120;0.900733;, + 0.858925;0.929667;, + 0.857641;0.934125;, + 0.847363;0.935745;, + 0.842772;0.924998;, + 0.848758;0.915479;, + 0.854634;0.921769;, + 0.864692;0.915242;, + 0.870238;0.910052;, + 0.873209;0.915066;, + 0.875924;0.920533;, + 0.868938;0.923141;, + 0.854440;0.942270;, + 0.864958;0.940644;, + 0.873896;0.944310;, + 0.874080;0.948382;, + 0.868064;0.948617;, + 0.857362;0.946171;, + 0.892692;0.920061;, + 0.887110;0.919186;, + 0.884115;0.913800;, + 0.889644;0.911032;, + 0.892703;0.913806;, + 0.892756;0.917449;, + 0.801819;0.909866;, + 0.788935;0.898076;, + 0.796995;0.887735;, + 0.813905;0.896644;, + 0.837738;0.930561;, + 0.842607;0.941175;, + 0.845069;0.945218;, + 0.847347;0.950804;, + 0.841881;0.956079;, + 0.812113;0.950778;, + 0.808814;0.938359;, + 0.825141;0.930378;, + 0.827105;0.920651;, + 0.830349;0.918516;, + 0.890228;0.876990;, + 0.888016;0.878593;, + 0.885001;0.878102;, + 0.883550;0.877809;, + 0.883811;0.876027;, + 0.884569;0.874258;, + 0.887538;0.871524;, + 0.890442;0.871983;, + 0.889999;0.881860;, + 0.892460;0.884911;, + 0.889233;0.885429;, + 0.886009;0.883818;, + 0.886436;0.881270;, + 0.883464;0.873827;, + 0.882424;0.875494;, + 0.880876;0.876215;, + 0.879842;0.875642;, + 0.881287;0.873936;, + 0.862513;0.892170;, + 0.861865;0.879474;, + 0.866388;0.875409;, + 0.873781;0.879035;, + 0.873094;0.883435;, + 0.873229;0.886138;, + 0.874904;0.888885;, + 0.874217;0.893384;, + 0.868208;0.898628;, + 0.871998;0.885239;, + 0.871976;0.882555;, + 0.872387;0.881660;, + 0.872785;0.883681;, + 0.872319;0.885711;, + 0.876354;0.881234;, + 0.875097;0.881843;, + 0.874745;0.879917;, + 0.876504;0.878342;, + 0.877554;0.878922;, + 0.875559;0.894556;, + 0.877148;0.894288;, + 0.881282;0.895325;, + 0.881391;0.896768;, + 0.876803;0.896405;, + 0.872657;0.890011;, + 0.873574;0.892165;, + 0.874760;0.894155;, + 0.874214;0.892318;, + 0.872608;0.889474;, + 0.877867;0.881632;, + 0.877351;0.880920;, + 0.878578;0.878622;, + 0.880091;0.877871;, + 0.879672;0.879604;, + 0.880438;0.882205;, + 0.882153;0.882616;, + 0.881530;0.885276;, + 0.879267;0.886324;, + 0.878742;0.884308;, + 0.882323;0.888704;, + 0.885747;0.890207;, + 0.883744;0.892684;, + 0.879543;0.891763;, + 0.880101;0.889732;, + 0.874627;0.885988;, + 0.875759;0.885288;, + 0.876435;0.886058;, + 0.876968;0.888077;, + 0.876348;0.890096;, + 0.874900;0.890194;, + 0.874116;0.887997;, + 0.885181;0.866347;, + 0.889779;0.863299;, + 0.887402;0.868633;, + 0.884410;0.871352;, + 0.882180;0.871419;, + 0.861419;0.793048;, + 0.856019;0.794881;, + 0.848222;0.791381;, + 0.840650;0.788120;, + 0.868772;0.227338;, + 0.871877;0.218340;, + 0.882605;0.222061;, + 0.884179;0.229250;, + 0.877209;0.231043;, + 0.858143;0.802183;, + 0.858817;0.805122;, + 0.851020;0.801622;, + 0.850346;0.798683;, + 0.841668;0.841308;, + 0.849162;0.841548;, + 0.854411;0.840199;, + 0.855954;0.843593;, + 0.854116;0.848424;, + 0.848984;0.849435;, + 0.841452;0.846086;, + 0.837548;0.841441;, + 0.864295;0.820660;, + 0.867352;0.822653;, + 0.874914;0.824710;, + 0.874712;0.830074;, + 0.868457;0.834824;, + 0.866846;0.831410;, + 0.866617;0.828470;, + 0.900825;0.238070;, + 0.899286;0.230881;, + 0.792524;0.758021;, + 0.705076;0.847899;, + 0.705513;0.842839;, + 0.714572;0.852197;, + 0.709570;0.865796;, + 0.708642;0.862587;, + 0.705810;0.858129;, + 0.704047;0.856128;, + 0.704582;0.853479;, + 0.659696;0.842488;, + 0.656503;0.844340;, + 0.656245;0.853573;, + 0.762387;0.807790;, + 0.769007;0.814582;, + 0.759728;0.829314;, + 0.744754;0.840151;, + 0.735158;0.837187;, + 0.661040;0.868118;, + 0.662092;0.873280;, + 0.667446;0.880470;, + 0.671850;0.884983;, + 0.693052;0.825544;, + 0.688060;0.821769;, + 0.690343;0.819868;, + 0.697497;0.825214;, + 0.697128;0.830256;, + 0.660014;0.869543;, + 0.663290;0.874126;, + 0.667721;0.879178;, + 0.670059;0.882396;, + 0.668880;0.883441;, + 0.665559;0.881576;, + 0.660559;0.874149;, + 0.654537;0.855994;, + 0.653216;0.850818;, + 0.654017;0.841614;, + 0.656962;0.838804;, + 0.656277;0.843395;, + 0.654654;0.851382;, + 0.706763;0.916055;, + 0.704907;0.914299;, + 0.708048;0.909580;, + 0.709904;0.911336;, + 0.673717;0.828513;, + 0.666418;0.834185;, + 0.676727;0.821513;, + 0.674409;0.823336;, + 0.671732;0.825354;, + 0.666087;0.828624;, + 0.662138;0.831262;, + 0.665145;0.829193;, + 0.672670;0.823785;, + 0.686417;0.897062;, + 0.684116;0.895030;, + 0.679361;0.888850;, + 0.680547;0.887802;, + 0.685477;0.891393;, + 0.676015;0.884643;, + 0.678762;0.886893;, + 0.683705;0.892958;, + 0.684863;0.895504;, + 0.680052;0.889403;, + 0.695233;0.914254;, + 0.696896;0.916164;, + 0.693427;0.914360;, + 0.689562;0.910409;, + 0.688484;0.907834;, + 0.690686;0.909875;, + 0.764102;0.734585;, + 0.759679;0.732105;, + 0.683424;0.899463;, + 0.687842;0.905828;, + 0.691611;0.909855;, + 0.807160;0.984871;, + 0.811076;0.992991;, + 0.796303;0.997435;, + 0.727330;0.775774;, + 0.737141;0.770505;, + 0.781718;0.979152;, + 0.853488;0.992247;, + 0.879600;0.995136;, + 0.884085;0.998182;, + 0.853121;0.996991;, + 0.839008;0.997396;, + 0.609087;0.764632;, + 0.608054;0.773833;, + 0.600940;0.751850;, + 0.607154;0.743363;, + 0.885369;0.580065;, + 0.879410;0.592575;, + 0.868069;0.591687;, + 0.617169;0.768622;, + 0.613975;0.756093;, + 0.734130;0.748148;, + 0.723692;0.752707;, + 0.619519;0.824099;, + 0.624525;0.802560;, + 0.864390;0.635775;, + 0.601057;0.823984;, + 0.603096;0.809459;, + 0.615766;0.831442;, + 0.588944;0.744363;, + 0.581349;0.758888;, + 0.571184;0.743148;, + 0.880440;0.641059;, + 0.889476;0.646513;, + 0.773385;0.772241;, + 0.765851;0.784683;, + 0.620152;0.744959;, + 0.749855;0.729434;, + 0.825102;0.801492;, + 0.822392;0.797440;, + 0.828673;0.792745;, + 0.835934;0.796180;, + 0.836558;0.799146;, + 0.832007;0.799764;, + 0.816657;0.843915;, + 0.814437;0.836935;, + 0.817320;0.832012;, + 0.822209;0.837181;, + 0.825497;0.841743;, + 0.822828;0.843553;, + 0.855544;0.831362;, + 0.859143;0.830035;, + 0.861639;0.829097;, + 0.861907;0.832046;, + 0.856590;0.833373;, + 0.878130;0.813309;, + 0.875581;0.819497;, + 0.870798;0.817379;, + 0.867840;0.813108;, + 0.867186;0.810154;, + 0.872694;0.808236;, + 0.851931;0.212439;, + 0.856292;0.215979;, + 0.853159;0.224970;, + 0.847090;0.227705;, + 0.841223;0.221426;, + 0.842931;0.215151;, + 0.859569;0.950864;, + 0.870221;0.953350;, + 0.872713;0.958843;, + 0.862061;0.956357;, + 0.831396;0.804920;, + 0.835696;0.805432;, + 0.831419;0.806932;, + 0.824765;0.808377;, + 0.824615;0.806530;, + 0.850927;0.803168;, + 0.858731;0.806700;, + 0.861498;0.810894;, + 0.858434;0.811439;, + 0.850713;0.807974;, + 0.845972;0.803898;, + 0.822828;0.832534;, + 0.817294;0.827383;, + 0.817703;0.825787;, + 0.822270;0.829261;, + 0.826417;0.832514;, + 0.845619;0.836729;, + 0.838159;0.836479;, + 0.833506;0.833424;, + 0.837442;0.832998;, + 0.844602;0.833326;, + 0.893943;0.238008;, + 0.861501;0.828439;, + 0.859016;0.829365;, + 0.886979;0.239799;, + 0.825506;0.808906;, + 0.832120;0.807468;, + 0.853968;0.203984;, + 0.845126;0.206762;, + 0.887612;0.209226;, + 0.877060;0.205589;, + 0.872370;0.201897;, + 0.845702;0.805354;, + 0.850683;0.808355;, + 0.858295;0.811864;, + 0.844156;0.238056;, + 0.826793;0.828244;, + 0.823281;0.827308;, + 0.819797;0.824826;, + 0.838144;0.231817;, + 0.872906;0.245257;, + 0.848450;0.832215;, + 0.844955;0.832101;, + 0.837770;0.831792;, + 0.858237;0.244246;, + 0.864579;0.241448;, + 0.672033;0.833431;, + 0.677807;0.830377;, + 0.680709;0.830944;, + 0.679630;0.832272;, + 0.675688;0.836035;, + 0.670993;0.837761;, + 0.663100;0.846806;, + 0.666956;0.844848;, + 0.665079;0.848028;, + 0.663611;0.854284;, + 0.662887;0.859062;, + 0.660499;0.854764;, + 0.667818;0.869181;, + 0.667184;0.864531;, + 0.668931;0.867557;, + 0.673075;0.872891;, + 0.672055;0.874351;, + 0.681144;0.879570;, + 0.682419;0.877888;, + 0.685425;0.879351;, + 0.690262;0.881969;, + 0.691271;0.885215;, + 0.688674;0.886066;, + 0.683347;0.882783;, + 0.690935;0.896052;, + 0.693695;0.894958;, + 0.697324;0.896188;, + 0.699246;0.901554;, + 0.696117;0.906264;, + 0.691436;0.901991;, + 0.709604;0.897148;, + 0.707652;0.895403;, + 0.706068;0.890008;, + 0.707265;0.884132;, + 0.708739;0.879243;, + 0.709690;0.882449;, + 0.709279;0.891750;, + 0.698001;0.848790;, + 0.694731;0.848453;, + 0.695212;0.847373;, + 0.694722;0.842825;, + 0.694640;0.838382;, + 0.698400;0.843269;, + 0.683941;0.825341;, + 0.688958;0.829089;, + 0.689393;0.833098;, + 0.687063;0.830490;, + 0.684377;0.828104;, + 0.681690;0.826964;, + 0.694539;0.855245;, + 0.690615;0.856789;, + 0.688785;0.856515;, + 0.689343;0.854694;, + 0.691759;0.852310;, + 0.695125;0.852587;, + 0.695784;0.859438;, + 0.697654;0.861366;, + 0.696067;0.863077;, + 0.694364;0.862584;, + 0.692101;0.862333;, + 0.691934;0.860897;, + 0.701740;0.863271;, + 0.704339;0.867671;, + 0.702837;0.872650;, + 0.700954;0.870057;, + 0.700777;0.866784;, + 0.700061;0.864978;, + 0.696764;0.887057;, + 0.695813;0.883870;, + 0.697109;0.884063;, + 0.699090;0.882660;, + 0.699974;0.879929;, + 0.701745;0.882398;, + 0.700150;0.887901;, + 0.682791;0.865085;, + 0.686164;0.862035;, + 0.687662;0.862175;, + 0.687917;0.863596;, + 0.688128;0.864328;, + 0.687422;0.865453;, + 0.686734;0.866131;, + 0.686434;0.868148;, + 0.683230;0.868455;, + 0.680190;0.857580;, + 0.685190;0.858012;, + 0.684571;0.859844;, + 0.680929;0.862779;, + 0.676758;0.860502;, + 0.672221;0.839192;, + 0.674948;0.836003;, + 0.678899;0.832260;, + 0.681542;0.834280;, + 0.677631;0.838280;, + 0.671368;0.850586;, + 0.669374;0.852969;, + 0.666111;0.855920;, + 0.663889;0.857693;, + 0.662654;0.854286;, + 0.664069;0.848025;, + 0.669448;0.847198;, + 0.675476;0.874545;, + 0.672524;0.872924;, + 0.668080;0.867719;, + 0.670016;0.865994;, + 0.674082;0.868366;, + 0.675098;0.871712;, + 0.684220;0.876796;, + 0.687623;0.876853;, + 0.689145;0.878057;, + 0.690589;0.880286;, + 0.691315;0.882437;, + 0.689607;0.882089;, + 0.684693;0.879534;, + 0.686810;0.844696;, + 0.690521;0.840850;, + 0.692060;0.839733;, + 0.694180;0.842825;, + 0.694638;0.847394;, + 0.688808;0.848147;, + 0.682379;0.829107;, + 0.683790;0.828069;, + 0.686594;0.830238;, + 0.685183;0.831276;, + 0.685882;0.851965;, + 0.691829;0.851125;, + 0.691147;0.852386;, + 0.688693;0.854737;, + 0.683767;0.854326;, + 0.694711;0.863557;, + 0.693094;0.863536;, + 0.690980;0.862835;, + 0.691446;0.862372;, + 0.693808;0.862659;, + 0.700238;0.866960;, + 0.699964;0.868510;, + 0.699518;0.867847;, + 0.698620;0.865539;, + 0.698097;0.864320;, + 0.699268;0.865078;, + 0.697861;0.880863;, + 0.698608;0.882973;, + 0.696609;0.884348;, + 0.695862;0.882238;, + 0.689170;0.871016;, + 0.688397;0.868920;, + 0.689273;0.869881;, + 0.690624;0.871065;, + 0.690629;0.872304;, + 0.694403;0.875504;, + 0.692846;0.873609;, + 0.693085;0.872105;, + 0.693891;0.872222;, + 0.695408;0.872942;, + 0.696159;0.874720;, + 0.698803;0.876854;, + 0.698569;0.874951;, + 0.698109;0.873383;, + 0.698025;0.873732;, + 0.699234;0.872247;, + 0.700303;0.870748;, + 0.699830;0.873806;, + 0.686162;0.868655;, + 0.685702;0.867312;, + 0.685787;0.866385;, + 0.686247;0.867728;, + 0.688933;0.865106;, + 0.690211;0.864034;, + 0.692367;0.864878;, + 0.691761;0.866467;, + 0.689389;0.866404;, + 0.696289;0.866667;, + 0.698091;0.866703;, + 0.698808;0.869151;, + 0.697715;0.870637;, + 0.696397;0.869990;, + 0.695690;0.868468;, + 0.688500;0.870302;, + 0.690574;0.870874;, + 0.691320;0.872191;, + 0.690675;0.872854;, + 0.689815;0.872503;, + 0.688385;0.871268;, + 0.693553;0.873419;, + 0.695096;0.873894;, + 0.695274;0.874506;, + 0.694662;0.874263;, + 0.692990;0.873850;, + 0.698496;0.872792;, + 0.698611;0.873595;, + 0.697475;0.875110;, + 0.697360;0.874307;, + 0.752419;0.911565;, + 0.768600;0.909906;, + 0.781542;0.921746;, + 0.767724;0.929157;, + 0.744573;0.923751;, + 0.783132;0.826576;, + 0.802348;0.807248;, + 0.805375;0.807970;, + 0.804374;0.820607;, + 0.799209;0.833329;, + 0.745404;0.878402;, + 0.752976;0.864062;, + 0.767966;0.853234;, + 0.777948;0.859594;, + 0.778925;0.873285;, + 0.770940;0.883665;, + 0.754637;0.885236;, + 0.723141;0.869933;, + 0.715669;0.884309;, + 0.707286;0.889890;, + 0.708161;0.880536;, + 0.713583;0.866968;, + 0.827892;0.872505;, + 0.834214;0.872050;, + 0.841195;0.877118;, + 0.842540;0.889659;, + 0.836716;0.899163;, + 0.829049;0.887077;, + 0.880758;0.832548;, + 0.880652;0.824610;, + 0.880761;0.819253;, + 0.883634;0.813028;, + 0.888066;0.810723;, + 0.889764;0.816036;, + 0.885281;0.828016;, + 0.897690;0.818794;, + 0.902855;0.818794;, + 0.907566;0.830695;, + 0.904983;0.835183;, + 0.895561;0.835183;, + 0.892979;0.830695;, + 0.897665;0.850874;, + 0.892954;0.852870;, + 0.895561;0.845903;, + 0.904983;0.845903;, + 0.907591;0.852870;, + 0.902880;0.850874;, + 0.892242;0.792424;, + 0.889659;0.797544;, + 0.885280;0.799848;, + 0.879746;0.794853;, + 0.870430;0.855508;, + 0.866426;0.850510;, + 0.868293;0.845675;, + 0.874568;0.840974;, + 0.874367;0.848880;, + 0.864964;0.864889;, + 0.859859;0.861579;, + 0.855510;0.855004;, + 0.860682;0.853995;, + 0.864797;0.859048;, + 0.845572;0.854480;, + 0.849888;0.860753;, + 0.845250;0.864668;, + 0.837521;0.860045;, + 0.834652;0.852847;, + 0.838065;0.851071;, + 0.827484;0.852926;, + 0.830296;0.860081;, + 0.824296;0.860464;, + 0.821483;0.853309;, + 0.917291;0.975313;, + 0.922858;0.970762;, + 0.932259;0.967611;, + 0.861297;0.974650;, + 0.868039;0.983920;, + 0.919995;0.981966;, + 0.631865;0.755748;, + 0.637632;0.767666;, + 0.750123;0.952141;, + 0.746615;0.939569;, + 0.723494;0.934189;, + 0.628816;0.758604;, + 0.800855;0.868571;, + 0.989360;0.878414;, + 0.985617;0.876023;, + 0.986957;0.861508;, + 0.989613;0.854328;, + 0.991949;0.847477;, + 0.994477;0.843381;, + 0.799856;0.854877;, + 0.716064;0.916632;, + 0.723917;0.904455;, + 0.714873;0.897777;, + 0.706162;0.903342;, + 0.706468;0.908363;, + 0.703264;0.913021;, + 0.699911;0.911896;, + 0.625080;0.756874;, + 0.993953;0.792095;, + 0.990736;0.792812;, + 0.986462;0.790165;, + 0.980489;0.785642;, + 0.991540;0.773290;, + 0.804323;0.784892;, + 0.688890;0.819799;, + 0.693042;0.817639;, + 0.700241;0.822974;, + 0.987767;0.808834;, + 0.989237;0.821517;, + 0.986353;0.825581;, + 0.985491;0.820881;, + 0.985003;0.819246;, + 0.905184;0.219462;, + 0.903939;0.213590;, + 0.981445;0.812192;, + 0.981572;0.810336;, + 0.983659;0.806201;, + 0.930171;0.868288;, + 0.925550;0.878190;, + 0.928534;0.878691;, + 0.927806;0.877913;, + 0.925935;0.876410;, + 0.924655;0.874631;, + 0.921715;0.869526;, + 0.919169;0.861716;, + 0.921740;0.857303;, + 0.926353;0.861851;, + 0.919785;0.905962;, + 0.914367;0.903064;, + 0.912401;0.899414;, + 0.916289;0.898560;, + 0.921047;0.898184;, + 0.921578;0.896213;, + 0.922425;0.900733;, + 0.951787;0.915479;, + 0.957773;0.924998;, + 0.953182;0.935745;, + 0.942904;0.934125;, + 0.941619;0.929668;, + 0.945911;0.921769;, + 0.935853;0.915242;, + 0.931607;0.923141;, + 0.924621;0.920533;, + 0.927335;0.915066;, + 0.930306;0.910052;, + 0.932480;0.948617;, + 0.926465;0.948382;, + 0.926648;0.944310;, + 0.935587;0.940644;, + 0.946105;0.942270;, + 0.943182;0.946171;, + 0.907853;0.920061;, + 0.907789;0.917449;, + 0.907842;0.913806;, + 0.910900;0.911032;, + 0.916429;0.913800;, + 0.913434;0.919187;, + 0.801819;0.909866;, + 0.986639;0.896644;, + 0.796995;0.887735;, + 0.788935;0.898076;, + 0.973440;0.920651;, + 0.825141;0.930378;, + 0.808814;0.938359;, + 0.812113;0.950778;, + 0.841881;0.956079;, + 0.953198;0.950804;, + 0.955475;0.945218;, + 0.957938;0.941175;, + 0.962807;0.930561;, + 0.970195;0.918516;, + 0.910316;0.876990;, + 0.910102;0.871983;, + 0.913007;0.871524;, + 0.915975;0.874258;, + 0.916734;0.876027;, + 0.916994;0.877809;, + 0.915543;0.878102;, + 0.912529;0.878593;, + 0.910545;0.881860;, + 0.914109;0.881270;, + 0.914535;0.883818;, + 0.911312;0.885429;, + 0.908085;0.884911;, + 0.920703;0.875642;, + 0.919669;0.876215;, + 0.918121;0.875494;, + 0.917081;0.873827;, + 0.919258;0.873936;, + 0.926327;0.893384;, + 0.925641;0.888885;, + 0.927316;0.886138;, + 0.927450;0.883435;, + 0.926763;0.879035;, + 0.934157;0.875138;, + 0.938680;0.879474;, + 0.938032;0.892170;, + 0.932337;0.898628;, + 0.927759;0.883681;, + 0.928158;0.881660;, + 0.928568;0.882555;, + 0.928547;0.885239;, + 0.928226;0.885711;, + 0.924191;0.881234;, + 0.922991;0.878922;, + 0.924041;0.878342;, + 0.925799;0.879917;, + 0.925448;0.881843;, + 0.924985;0.894556;, + 0.923742;0.896405;, + 0.919153;0.896768;, + 0.919262;0.895325;, + 0.923396;0.894288;, + 0.927887;0.890011;, + 0.927937;0.889474;, + 0.926330;0.892318;, + 0.925785;0.894155;, + 0.926971;0.892165;, + 0.922678;0.881632;, + 0.920873;0.879604;, + 0.920453;0.877871;, + 0.921967;0.878622;, + 0.923194;0.880920;, + 0.921278;0.886324;, + 0.919014;0.885276;, + 0.918391;0.882616;, + 0.920106;0.882205;, + 0.921802;0.884308;, + 0.921002;0.891763;, + 0.916801;0.892684;, + 0.914798;0.890207;, + 0.918222;0.888704;, + 0.920444;0.889732;, + 0.925645;0.890194;, + 0.924197;0.890096;, + 0.923576;0.888077;, + 0.924110;0.886058;, + 0.924786;0.885288;, + 0.925917;0.885988;, + 0.926428;0.887997;, + 0.916135;0.871352;, + 0.913143;0.868633;, + 0.910766;0.863299;, + 0.915364;0.866347;, + 0.918364;0.871419;, + 0.939125;0.793048;, + 0.959895;0.788120;, + 0.952322;0.791381;, + 0.944526;0.794881;, + 0.852650;0.228909;, + 0.854352;0.222094;, + 0.865952;0.218567;, + 0.869308;0.227096;, + 0.860187;0.230609;, + 0.942402;0.802183;, + 0.950198;0.798683;, + 0.949524;0.801622;, + 0.941728;0.805122;, + 0.959092;0.846086;, + 0.951561;0.849435;, + 0.946429;0.848424;, + 0.944591;0.843593;, + 0.946133;0.840199;, + 0.951383;0.841548;, + 0.958877;0.841308;, + 0.962996;0.841441;, + 0.933526;0.820660;, + 0.836316;0.230455;, + 0.834651;0.237269;, + 0.931203;0.828470;, + 0.933698;0.831410;, + 0.932088;0.834824;, + 0.925832;0.830074;, + 0.925630;0.824710;, + 0.930468;0.822653;, + 0.792524;0.758021;, + 0.705076;0.847899;, + 0.704582;0.853479;, + 0.704047;0.856128;, + 0.705810;0.858129;, + 0.708642;0.862587;, + 0.709570;0.865796;, + 0.714572;0.852197;, + 0.705513;0.842839;, + 0.656503;0.844340;, + 0.659696;0.842488;, + 0.658583;0.844044;, + 0.656245;0.853573;, + 0.762387;0.807790;, + 0.735158;0.837187;, + 0.744754;0.840151;, + 0.759728;0.829314;, + 0.769007;0.814582;, + 0.671850;0.884983;, + 0.667446;0.880470;, + 0.662092;0.873280;, + 0.661040;0.868118;, + 0.697497;0.825214;, + 0.690343;0.819868;, + 0.688060;0.821769;, + 0.693052;0.825544;, + 0.697128;0.830256;, + 0.660014;0.869543;, + 0.660559;0.874149;, + 0.665559;0.881576;, + 0.668880;0.883441;, + 0.670059;0.882396;, + 0.667721;0.879178;, + 0.663290;0.874126;, + 0.656277;0.843395;, + 0.656962;0.838804;, + 0.654017;0.841614;, + 0.653216;0.850818;, + 0.654537;0.855994;, + 0.654654;0.851382;, + 0.708048;0.909580;, + 0.704907;0.914299;, + 0.706763;0.916055;, + 0.709904;0.911336;, + 0.665306;0.835742;, + 0.666418;0.834185;, + 0.673717;0.828513;, + 0.676727;0.821513;, + 0.672670;0.823785;, + 0.665146;0.829193;, + 0.662138;0.831262;, + 0.666087;0.828624;, + 0.671732;0.825354;, + 0.674409;0.823336;, + 0.686417;0.897062;, + 0.685477;0.891393;, + 0.680547;0.887802;, + 0.679361;0.888850;, + 0.684116;0.895030;, + 0.676015;0.884643;, + 0.680052;0.889403;, + 0.684863;0.895504;, + 0.683705;0.892958;, + 0.678762;0.886893;, + 0.688484;0.907834;, + 0.689562;0.910409;, + 0.693427;0.914360;, + 0.696896;0.916164;, + 0.695233;0.914254;, + 0.690686;0.909875;, + 0.626382;0.751791;, + 0.691611;0.909855;, + 0.687843;0.905828;, + 0.683424;0.899463;, + 0.629431;0.748934;, + 0.649842;0.784379;, + 0.661634;0.789005;, + 0.796303;0.997435;, + 0.811076;0.992991;, + 0.807160;0.984871;, + 0.781718;0.979152;, + 0.853121;0.996991;, + 0.916460;0.998182;, + 0.920944;0.995136;, + 0.853488;0.992247;, + 0.839008;0.997396;, + 0.501649;0.767269;, + 0.502150;0.750869;, + 0.512657;0.751850;, + 0.505542;0.773833;, + 0.652023;0.759221;, + 0.496782;0.758581;, + 0.495945;0.774158;, + 0.973029;0.592354;, + 0.962233;0.596576;, + 0.954638;0.582066;, + 0.663138;0.761836;, + 0.975073;0.631107;, + 0.491802;0.807701;, + 0.493658;0.821015;, + 0.497831;0.831442;, + 0.510501;0.809459;, + 0.512540;0.823984;, + 0.524652;0.744363;, + 0.542413;0.743148;, + 0.532247;0.758888;, + 0.949442;0.647846;, + 0.958479;0.641726;, + 0.773385;0.772241;, + 0.765851;0.784683;, + 0.660818;0.835561;, + 0.637646;0.745354;, + 0.493444;0.744959;, + 0.963987;0.799146;, + 0.964611;0.796180;, + 0.971871;0.792745;, + 0.978153;0.797440;, + 0.975442;0.801492;, + 0.968537;0.799764;, + 0.983888;0.843915;, + 0.977716;0.843553;, + 0.975048;0.841743;, + 0.978336;0.837181;, + 0.983225;0.832012;, + 0.986108;0.836936;, + 0.938638;0.832046;, + 0.936181;0.829097;, + 0.941401;0.830035;, + 0.945000;0.831362;, + 0.943954;0.833373;, + 0.933359;0.810154;, + 0.932705;0.813108;, + 0.929746;0.817379;, + 0.924964;0.819497;, + 0.922414;0.813309;, + 0.927851;0.808236;, + 0.899096;0.221492;, + 0.892752;0.227445;, + 0.886190;0.224852;, + 0.882803;0.216330;, + 0.887518;0.212975;, + 0.897249;0.215545;, + 0.940975;0.950864;, + 0.938484;0.956357;, + 0.927832;0.958843;, + 0.930323;0.953350;, + 0.969148;0.804920;, + 0.975929;0.806530;, + 0.975779;0.808377;, + 0.969125;0.806932;, + 0.964660;0.806467;, + 0.949832;0.807745;, + 0.942110;0.811209;, + 0.939047;0.810894;, + 0.941813;0.806700;, + 0.949618;0.803168;, + 0.954573;0.803898;, + 0.977716;0.832534;, + 0.974127;0.832514;, + 0.978275;0.829261;, + 0.982842;0.825787;, + 0.983251;0.827383;, + 0.954926;0.836729;, + 0.955943;0.833556;, + 0.963103;0.833228;, + 0.967039;0.832274;, + 0.962386;0.836479;, + 0.941529;0.829365;, + 0.936319;0.828439;, + 0.842092;0.237210;, + 0.849622;0.238907;, + 0.885316;0.204961;, + 0.968425;0.807468;, + 0.975039;0.808906;, + 0.894876;0.207594;, + 0.949861;0.808125;, + 0.954654;0.806389;, + 0.865418;0.202982;, + 0.860347;0.206482;, + 0.848938;0.209929;, + 0.942250;0.811634;, + 0.981687;0.824251;, + 0.977264;0.826044;, + 0.973752;0.827899;, + 0.895925;0.237256;, + 0.902426;0.231342;, + 0.864838;0.244081;, + 0.873842;0.240471;, + 0.880699;0.243123;, + 0.962774;0.831447;, + 0.955589;0.832331;, + 0.952095;0.832215;, + 0.675688;0.836035;, + 0.679630;0.832272;, + 0.680709;0.830944;, + 0.677807;0.830377;, + 0.672033;0.833431;, + 0.670993;0.837761;, + 0.662887;0.859062;, + 0.663611;0.854284;, + 0.665079;0.848028;, + 0.666956;0.844848;, + 0.663100;0.846806;, + 0.660499;0.854764;, + 0.673075;0.872891;, + 0.668931;0.867557;, + 0.667184;0.864531;, + 0.667818;0.869181;, + 0.672055;0.874351;, + 0.681144;0.879570;, + 0.683347;0.882783;, + 0.688674;0.886066;, + 0.691271;0.885215;, + 0.690262;0.881969;, + 0.685425;0.879351;, + 0.682419;0.877888;, + 0.696117;0.906264;, + 0.699246;0.901554;, + 0.697324;0.896188;, + 0.693695;0.894958;, + 0.690935;0.896052;, + 0.691436;0.901991;, + 0.709604;0.897148;, + 0.709279;0.891750;, + 0.709690;0.882449;, + 0.708739;0.879243;, + 0.707265;0.884132;, + 0.706068;0.890008;, + 0.707652;0.895403;, + 0.694640;0.838382;, + 0.694722;0.842825;, + 0.695212;0.847373;, + 0.694731;0.848453;, + 0.698001;0.848790;, + 0.698400;0.843269;, + 0.683941;0.825341;, + 0.681690;0.826964;, + 0.684378;0.828104;, + 0.687063;0.830490;, + 0.689393;0.833098;, + 0.688958;0.829089;, + 0.691759;0.852310;, + 0.689343;0.854694;, + 0.688785;0.856515;, + 0.690615;0.856789;, + 0.694539;0.855245;, + 0.695125;0.852587;, + 0.695784;0.859438;, + 0.691934;0.860897;, + 0.692101;0.862333;, + 0.694364;0.862584;, + 0.696067;0.863077;, + 0.697654;0.861366;, + 0.701740;0.863271;, + 0.700061;0.864978;, + 0.700778;0.866784;, + 0.700954;0.870057;, + 0.702837;0.872650;, + 0.704339;0.867671;, + 0.696764;0.887057;, + 0.700150;0.887901;, + 0.701745;0.882398;, + 0.699974;0.879929;, + 0.699090;0.882660;, + 0.697109;0.884063;, + 0.695813;0.883870;, + 0.686434;0.868148;, + 0.686734;0.866131;, + 0.687422;0.865453;, + 0.688128;0.864328;, + 0.687917;0.863596;, + 0.687662;0.862175;, + 0.686164;0.862035;, + 0.682791;0.865085;, + 0.683230;0.868455;, + 0.680190;0.857580;, + 0.676758;0.860502;, + 0.680929;0.862779;, + 0.684571;0.859844;, + 0.685190;0.858012;, + 0.681542;0.834280;, + 0.678899;0.832260;, + 0.674948;0.836003;, + 0.672221;0.839192;, + 0.677631;0.838280;, + 0.664069;0.848025;, + 0.662654;0.854286;, + 0.663889;0.857693;, + 0.666111;0.855920;, + 0.669374;0.852969;, + 0.671369;0.850586;, + 0.669448;0.847198;, + 0.674082;0.868366;, + 0.670016;0.865994;, + 0.668080;0.867719;, + 0.672524;0.872924;, + 0.675476;0.874545;, + 0.675098;0.871712;, + 0.684220;0.876796;, + 0.684693;0.879534;, + 0.689607;0.882089;, + 0.691315;0.882437;, + 0.690589;0.880286;, + 0.689145;0.878057;, + 0.687623;0.876853;, + 0.686810;0.844696;, + 0.688808;0.848147;, + 0.694638;0.847394;, + 0.694180;0.842825;, + 0.692061;0.839733;, + 0.690521;0.840850;, + 0.686594;0.830238;, + 0.683790;0.828069;, + 0.682379;0.829107;, + 0.685183;0.831276;, + 0.688693;0.854737;, + 0.691147;0.852386;, + 0.691829;0.851125;, + 0.685882;0.851965;, + 0.683767;0.854326;, + 0.691446;0.862372;, + 0.690980;0.862835;, + 0.693094;0.863536;, + 0.694711;0.863557;, + 0.693808;0.862659;, + 0.698097;0.864320;, + 0.698620;0.865539;, + 0.699518;0.867847;, + 0.699965;0.868510;, + 0.700238;0.866960;, + 0.699268;0.865078;, + 0.696609;0.884348;, + 0.698608;0.882973;, + 0.697861;0.880863;, + 0.695862;0.882238;, + 0.690624;0.871065;, + 0.689273;0.869881;, + 0.688397;0.868920;, + 0.689170;0.871016;, + 0.690629;0.872304;, + 0.694403;0.875504;, + 0.696159;0.874720;, + 0.695408;0.872942;, + 0.693891;0.872222;, + 0.693085;0.872105;, + 0.692846;0.873609;, + 0.698803;0.876854;, + 0.699830;0.873806;, + 0.700303;0.870748;, + 0.699234;0.872247;, + 0.698025;0.873732;, + 0.698109;0.873383;, + 0.698569;0.874951;, + 0.685787;0.866385;, + 0.685702;0.867312;, + 0.686162;0.868655;, + 0.686247;0.867728;, + 0.691761;0.866467;, + 0.692367;0.864878;, + 0.690211;0.864034;, + 0.688933;0.865106;, + 0.689389;0.866404;, + 0.696397;0.869990;, + 0.697715;0.870637;, + 0.698808;0.869151;, + 0.698091;0.866703;, + 0.696289;0.866667;, + 0.695690;0.868468;, + 0.688500;0.870302;, + 0.688385;0.871268;, + 0.689815;0.872503;, + 0.690675;0.872854;, + 0.691320;0.872191;, + 0.690574;0.870874;, + 0.693553;0.873419;, + 0.692990;0.873850;, + 0.694662;0.874263;, + 0.695274;0.874506;, + 0.695096;0.873894;, + 0.697475;0.875110;, + 0.698611;0.873595;, + 0.698496;0.872792;, + 0.697360;0.874307;, + 0.752419;0.911565;, + 0.744573;0.923751;, + 0.767724;0.929157;, + 0.781542;0.921746;, + 0.768600;0.909906;, + 0.996171;0.820607;, + 0.995169;0.807970;, + 0.799319;0.811168;, + 0.783132;0.826576;, + 0.798927;0.833329;, + 0.770940;0.883665;, + 0.778925;0.873285;, + 0.777948;0.859594;, + 0.767966;0.853234;, + 0.752976;0.864062;, + 0.745404;0.878402;, + 0.754637;0.885236;, + 0.723141;0.869933;, + 0.713583;0.866968;, + 0.708161;0.880536;, + 0.707286;0.889890;, + 0.715669;0.884309;, + 0.963829;0.899163;, + 0.958004;0.889659;, + 0.959349;0.877118;, + 0.966330;0.872050;, + 0.972653;0.872505;, + 0.971496;0.887077;, + 0.919787;0.832548;, + 0.915263;0.828016;, + 0.910781;0.816036;, + 0.912479;0.810723;, + 0.916910;0.813028;, + 0.919784;0.819253;, + 0.919893;0.824610;, + 0.915265;0.799848;, + 0.910885;0.797544;, + 0.908303;0.792424;, + 0.920798;0.794853;, + 0.925977;0.840974;, + 0.932251;0.845675;, + 0.934119;0.850510;, + 0.930114;0.855508;, + 0.926178;0.848880;, + 0.939862;0.853995;, + 0.945035;0.855004;, + 0.940686;0.861579;, + 0.935580;0.864889;, + 0.935748;0.859048;, + 0.965893;0.852847;, + 0.963024;0.860045;, + 0.955294;0.864668;, + 0.950657;0.860753;, + 0.954972;0.854480;, + 0.962479;0.851071;, + 0.976248;0.860464;, + 0.970248;0.860081;, + 0.973061;0.852926;, + 0.979061;0.853309;, + 0.050851;0.311418;, + 0.182352;0.311622;, + 0.552046;0.238197;, + 0.452719;0.187398;, + 0.438080;0.117554;, + 0.452085;0.122919;, + 0.055836;0.106868;, + 0.772088;0.251618;, + 0.356021;0.264969;, + 0.058251;0.140019;, + 0.013018;0.143812;, + 0.008445;0.097857;, + 0.017286;0.142213;, + 0.466090;0.125759;, + 0.032290;0.226805;, + 0.439368;0.396962;, + 0.028011;0.255177;, + 0.015083;0.184547;, + 0.003633;0.442765;, + 0.028225;0.366884;, + 0.008025;0.366913;, + 0.031155;0.442733;, + 0.035522;0.366908;, + 0.043503;0.366901;, + 0.078333;0.442781;, + 0.077972;0.366951;, + 0.063824;0.366910;, + 0.050581;0.366921;, + 0.116059;0.442822;, + 0.095599;0.366990;, + 0.003503;0.366840;, + 0.598234;0.316550;, + 0.550018;0.316218;, + 0.473892;0.274536;, + 0.441097;0.248866;, + 0.464459;0.326135;, + 0.538350;0.016111;, + 0.514084;0.033957;, + 0.489390;0.113365;, + 0.519113;0.138636;, + 0.490572;0.068422;, + 0.356021;0.325248;, + 0.555413;0.007122;, + 0.817949;0.096034;, + 0.787844;0.203452;, + 0.760901;0.200278;, + 0.794989;0.036951;, + 0.779378;0.059111;, + 0.766486;0.099552;, + 0.759845;0.138679;, + 0.814666;0.026300;, + 0.867984;0.019847;, + 0.832914;0.017848;, + 0.809118;0.135273;, + 0.805604;0.154688;, + 0.804978;0.157227;, + 0.758809;0.175095;, + 0.752513;0.157925;, + 0.781961;0.152723;, + 0.858184;0.093448;, + 0.831251;0.093463;, + 0.832409;0.120566;, + 0.848059;0.120499;, + 0.904949;0.121045;, + 0.904197;0.093746;, + 0.888889;0.093489;, + 0.278833;0.117554;, + 0.264828;0.122919;, + 0.181994;0.106868;, + 0.963886;0.251618;, + 0.179579;0.140019;, + 0.224812;0.143812;, + 0.220544;0.142213;, + 0.229385;0.097857;, + 0.272671;0.396962;, + 0.273453;0.408674;, + 0.209561;0.254798;, + 0.222747;0.184547;, + 0.231654;0.442713;, + 0.228618;0.366834;, + 0.207062;0.366884;, + 0.207750;0.442759;, + 0.197052;0.366829;, + 0.186357;0.366849;, + 0.156410;0.366951;, + 0.159214;0.442781;, + 0.168750;0.366884;, + 0.178828;0.366842;, + 0.136070;0.366990;, + 0.233592;0.366893;, + 0.598234;0.316550;, + 0.550018;0.316218;, + 0.238147;0.274536;, + 0.250823;0.125759;, + 0.275815;0.248866;, + 0.247580;0.326135;, + 0.538350;0.016111;, + 0.514084;0.033957;, + 0.489390;0.113365;, + 0.519113;0.138636;, + 0.490572;0.068422;, + 0.555413;0.007122;, + 0.948111;0.206039;, + 0.975073;0.200278;, + 0.940985;0.036951;, + 0.956597;0.059111;, + 0.969488;0.099552;, + 0.976129;0.138679;, + 0.921308;0.026300;, + 0.903060;0.017848;, + 0.926856;0.135273;, + 0.930370;0.157275;, + 0.930970;0.159128;, + 0.977165;0.175095;, + 0.983462;0.157925;, + 0.954013;0.152723;, + 0.858184;0.093448;, + 0.831251;0.093463;, + 0.832568;0.120761;, + 0.848059;0.120499;, + 0.904949;0.121045;, + 0.904197;0.093746;, + 0.888889;0.093489;, + 0.045297;0.477254;, + 0.024699;0.503835;, + 0.472594;0.539949;, + 0.472914;0.716324;, + 0.371776;0.675528;, + 0.373235;0.731889;, + 0.767119;0.421877;, + 0.727042;0.422032;, + 0.723334;0.470792;, + 0.740205;0.473323;, + 0.768616;0.475082;, + 0.820577;0.474485;, + 0.854839;0.474108;, + 0.857896;0.333084;, + 0.840158;0.333502;, + 0.826868;0.333518;, + 0.774925;0.333534;, + 0.746447;0.334508;, + 0.725798;0.335439;, + 0.718712;0.379084;, + 0.718703;0.421715;, + 0.726481;0.378657;, + 0.834362;0.474339;, + 0.100154;0.969885;, + 0.402711;0.957700;, + 0.481941;0.958396;, + 0.471098;0.942456;, + 0.106806;0.943084;, + 0.367369;0.618403;, + 0.362779;0.569244;, + 0.390556;0.922382;, + 0.481380;0.922948;, + 0.108160;0.830961;, + 0.474937;0.574217;, + 0.374591;0.772968;, + 0.770613;0.378738;, + 0.779658;0.375290;, + 0.468376;0.968225;, + 0.781318;0.421781;, + 0.864584;0.336319;, + 0.862721;0.473397;, + 0.861507;0.384730;, + 0.035279;0.972096;, + 0.046114;0.971274;, + 0.056515;0.976507;, + 0.058788;0.985534;, + 0.424365;0.990067;, + 0.424369;0.986643;, + 0.023807;0.986947;, + 0.025789;0.981161;, + 0.430561;0.982980;, + 0.436946;0.984040;, + 0.053072;0.973154;, + 0.026698;0.979844;, + 0.028129;0.977147;, + 0.442206;0.984188;, + 0.449680;0.985484;, + 0.059185;0.989086;, + 0.453487;0.988306;, + 0.456226;0.990546;, + 0.425617;0.991500;, + 0.371983;0.697920;, + 0.020286;0.699408;, + 0.817399;0.610136;, + 0.829895;0.574015;, + 0.829308;0.486167;, + 0.790539;0.483740;, + 0.831696;0.541216;, + 0.782813;0.613566;, + 0.720868;0.507940;, + 0.721642;0.571367;, + 0.755114;0.484599;, + 0.726396;0.484711;, + 0.749582;0.616531;, + 0.722723;0.608105;, + 0.829070;0.386901;, + 0.826063;0.425306;, + 0.002135;0.449795;, + 0.002967;0.471277;, + 0.096325;0.470207;, + 0.388540;0.470853;, + 0.410191;0.471018;, + 0.426962;0.471210;, + 0.028854;0.470922;, + 0.046416;0.470827;, + 0.441986;0.471377;, + 0.008914;0.470973;, + 0.078325;0.470594;, + 0.411197;0.444817;, + 0.359856;0.444726;, + 0.096730;0.448878;, + 0.045771;0.449319;, + 0.440173;0.445252;, + 0.007387;0.449871;, + 0.848952;0.391126;, + 0.835216;0.391122;, + 0.835524;0.392360;, + 0.835512;0.416900;, + 0.848943;0.416867;, + 0.104771;0.476750;, + 0.114079;0.496443;, + 0.114079;0.543468;, + 0.114079;0.543305;, + 0.107353;0.876654;, + 0.008722;0.875832;, + 0.010738;0.826008;, + 0.011091;0.767026;, + 0.109612;0.782815;, + 0.107819;0.799273;, + 0.373464;0.753821;, + 0.475894;0.744141;, + 0.362779;0.477059;, + 0.205339;0.504702;, + 0.184741;0.478121;, + 0.253357;0.539949;, + 0.254211;0.717753;, + 0.356515;0.676004;, + 0.353890;0.730460;, + 0.766924;0.421998;, + 0.726846;0.422153;, + 0.723334;0.470792;, + 0.740205;0.473323;, + 0.768616;0.475082;, + 0.820577;0.474485;, + 0.854839;0.474108;, + 0.857896;0.333084;, + 0.840158;0.333502;, + 0.826868;0.333518;, + 0.774925;0.333534;, + 0.746447;0.334508;, + 0.725798;0.335439;, + 0.718516;0.379205;, + 0.718508;0.421836;, + 0.726286;0.378778;, + 0.834362;0.474339;, + 0.141709;0.974550;, + 0.343835;0.965103;, + 0.248247;0.942456;, + 0.247517;0.958396;, + 0.133854;0.941784;, + 0.359367;0.618403;, + 0.346186;0.924812;, + 0.248079;0.922472;, + 0.129246;0.830609;, + 0.251014;0.574217;, + 0.352797;0.772717;, + 0.770418;0.378859;, + 0.779658;0.375290;, + 0.247079;0.968701;, + 0.864584;0.336319;, + 0.862721;0.473397;, + 0.861507;0.384730;, + 0.200708;0.973327;, + 0.188454;0.972288;, + 0.174861;0.978172;, + 0.170105;0.984594;, + 0.301203;0.990067;, + 0.301200;0.986643;, + 0.210406;0.987744;, + 0.209311;0.981523;, + 0.295008;0.982980;, + 0.288623;0.984040;, + 0.179545;0.975036;, + 0.208402;0.980206;, + 0.206971;0.977509;, + 0.283363;0.984188;, + 0.275889;0.985484;, + 0.169707;0.988147;, + 0.272081;0.988306;, + 0.269343;0.990546;, + 0.299951;0.991500;, + 0.357865;0.698872;, + 0.220267;0.695386;, + 0.817399;0.610136;, + 0.829895;0.574015;, + 0.829308;0.486167;, + 0.790539;0.483740;, + 0.831696;0.541216;, + 0.782813;0.613566;, + 0.720868;0.507940;, + 0.727230;0.571709;, + 0.755114;0.484599;, + 0.726396;0.484711;, + 0.749582;0.616531;, + 0.728311;0.605711;, + 0.829070;0.386901;, + 0.826063;0.425306;, + 0.789675;0.422317;, + 0.231551;0.471277;, + 0.232384;0.449795;, + 0.128399;0.470207;, + 0.333617;0.470853;, + 0.311966;0.471018;, + 0.295195;0.471210;, + 0.200322;0.470922;, + 0.182760;0.470827;, + 0.280654;0.471377;, + 0.225604;0.470973;, + 0.150851;0.470594;, + 0.313395;0.444893;, + 0.127994;0.448878;, + 0.182429;0.449339;, + 0.281452;0.444727;, + 0.227179;0.449362;, + 0.860812;0.392349;, + 0.861813;0.391103;, + 0.860809;0.416900;, + 0.123959;0.476750;, + 0.130619;0.875688;, + 0.223746;0.876529;, + 0.222682;0.831192;, + 0.222175;0.766782;, + 0.126664;0.781896;, + 0.127108;0.799289;, + 0.355244;0.754385;, + 0.253953;0.745093;, + 0.984741;0.646982;, + 0.615535;0.336575;, + 0.617993;0.370708;, + 0.618503;0.412274;, + 0.683406;0.333879;, + 0.617258;0.334147;, + 0.616727;0.478604;, + 0.486881;0.506343;, + 0.486377;0.522763;, + 0.619069;0.508845;, + 0.619014;0.529288;, + 0.613523;0.537819;, + 0.715761;0.536843;, + 0.698826;0.480362;, + 0.715249;0.479745;, + 0.524207;0.480304;, + 0.577151;0.481311;, + 0.614315;0.481181;, + 0.636157;0.481064;, + 0.652311;0.481307;, + 0.679859;0.480379;, + 0.490306;0.480268;, + 0.482948;0.479671;, + 0.482987;0.487223;, + 0.619378;0.479998;, + 0.618557;0.486635;, + 0.485819;0.480718;, + 0.559587;0.542715;, + 0.647989;0.541297;, + 0.637666;0.713938;, + 0.691713;0.542696;, + 0.668214;0.542030;, + 0.701857;0.714699;, + 0.712881;0.541485;, + 0.622792;0.540665;, + 0.526962;0.540637;, + 0.509701;0.540747;, + 0.715962;0.581565;, + 0.613254;0.657234;, + 0.506449;0.658654;, + 0.590872;0.585541;, + 0.576642;0.545365;, + 0.542761;0.538309;, + 0.485178;0.411726;, + 0.565621;0.335995;, + 0.536916;0.335282;, + 0.594197;0.337971;, + 0.879880;0.266471;, + 0.896585;0.266970;, + 0.981714;0.549754;, + 0.959173;0.550152;, + 0.993412;0.532121;, + 0.911361;0.265679;, + 0.944930;0.548958;, + 0.991594;0.515601;, + 0.987964;0.504932;, + 0.874609;0.301468;, + 0.881797;0.290567;, + 0.987964;0.504932;, + 0.923442;0.290776;, + 0.894704;0.289223;, + 0.988993;0.482104;, + 0.941215;0.509530;, + 0.928011;0.304107;, + 0.938862;0.340611;, + 0.928965;0.335341;, + 0.935938;0.471280;, + 0.916356;0.483920;, + 0.953678;0.337149;, + 0.927180;0.460289;, + 0.952654;0.353364;, + 1.000000;1.000000;, + 1.000000;1.000000;, + 0.922355;0.455126;, + 0.921067;0.451440;, + 0.954272;0.363662;, + 0.914584;0.447588;, + 0.872693;0.373015;, + 0.933280;0.438169;, + 0.932123;0.444577;, + 0.945306;0.436670;, + 0.947010;0.442402;, + 0.934191;0.432159;, + 0.943779;0.430962;, + 0.934464;0.427238;, + 0.944140;0.426029;, + 0.933322;0.423342;, + 0.945347;0.421842;, + 0.933852;0.417199;, + 0.944784;0.415835;, + 0.935261;0.412166;, + 0.943440;0.411143;, + 0.934807;0.408303;, + 0.944128;0.407138;, + 0.933499;0.405627;, + 0.945523;0.404125;, + 0.934306;0.399900;, + 0.944760;0.398593;, + 0.936197;0.395479;, + 0.942312;0.394711;, + 0.938126;0.393378;, + 0.940188;0.393119;, + 0.948663;0.433609;, + 0.962449;0.431891;, + 0.963569;0.439852;, + 0.949712;0.425444;, + 0.960702;0.424073;, + 0.950027;0.418771;, + 0.961120;0.417385;, + 0.948720;0.413426;, + 0.962506;0.411706;, + 0.949332;0.405039;, + 0.961865;0.403475;, + 0.950951;0.398224;, + 0.960328;0.397052;, + 0.950433;0.392937;, + 0.961118;0.391601;, + 0.948935;0.389236;, + 0.962720;0.387514;, + 0.949864;0.381423;, + 0.961849;0.379924;, + 0.952035;0.375474;, + 0.959045;0.374594;, + 0.954248;0.372686;, + 0.956611;0.372389;, + 0.964836;0.431793;, + 0.978209;0.430202;, + 0.979243;0.437677;, + 0.965950;0.424289;, + 0.976611;0.423020;, + 0.966334;0.418150;, + 0.977095;0.416868;, + 0.965133;0.413242;, + 0.978506;0.411649;, + 0.965829;0.405541;, + 0.977985;0.404094;, + 0.967479;0.399276;, + 0.976574;0.398191;, + 0.967041;0.394421;, + 0.977406;0.393185;, + 0.965636;0.391026;, + 0.979007;0.389433;, + 0.966632;0.383854;, + 0.978257;0.382466;, + 0.968804;0.378379;, + 0.975604;0.377565;, + 0.970980;0.375810;, + 0.973272;0.375535;, + 0.980527;0.431609;, + 0.991780;0.430872;, + 0.981826;0.426089;, + 0.990797;0.425501;, + 0.982442;0.421548;, + 0.991496;0.420953;, + 0.981680;0.417876;, + 0.992932;0.417138;, + 0.982647;0.412208;, + 0.992876;0.411538;, + 0.984331;0.407622;, + 0.991985;0.407118;, + 0.984207;0.404017;, + 0.992928;0.403443;, + 0.983205;0.401464;, + 0.994456;0.400724;, + 0.873351;0.415244;, + 0.984397;0.396197;, + 0.870746;0.415440;, + 0.986474;0.392206;, + 0.992196;0.391827;, + 0.988412;0.390367;, + 0.990341;0.390239;, + 0.933195;0.460832;, + 0.929516;0.270184;, + 0.960279;0.517513;, + 0.941215;0.509530;, + 0.935596;0.521485;, + 0.873524;0.323161;, + 0.715286;0.395988;, + 0.499149;0.337032;, + 0.484789;0.334008;, + 0.714967;0.334006;, + 0.616154;0.336767;, + 0.618732;0.413149;, + 0.618222;0.371582;, + 0.645009;0.344914;, + 0.684073;0.334711;, + 0.616956;0.479479;, + 0.485239;0.507463;, + 0.485593;0.530220;, + 0.619554;0.528041;, + 0.617878;0.506596;, + 0.614305;0.539126;, + 0.715662;0.536483;, + 0.707911;0.479876;, + 0.715316;0.480342;, + 0.530845;0.480046;, + 0.579638;0.481539;, + 0.611205;0.482665;, + 0.634599;0.480479;, + 0.659608;0.481359;, + 0.682447;0.479741;, + 0.500776;0.479904;, + 0.485365;0.486454;, + 0.485364;0.479957;, + 0.618547;0.487348;, + 0.618035;0.480859;, + 0.485593;0.480884;, + 0.526256;0.539496;, + 0.658985;0.539087;, + 0.642654;0.716241;, + 0.706306;0.540833;, + 0.676209;0.539484;, + 0.570340;0.539574;, + 0.589402;0.577637;, + 0.580114;0.538910;, + 0.630066;0.542891;, + 0.560574;0.538232;, + 0.707645;0.653215;, + 0.698825;0.716851;, + 0.626437;0.657671;, + 0.494342;0.580983;, + 0.509352;0.540802;, + 0.544101;0.536351;, + 0.484496;0.412560;, + 0.564904;0.336726;, + 0.536100;0.335995;, + 0.593407;0.338687;, + 0.880106;0.263780;, + 0.890029;0.264275;, + 0.983849;0.547217;, + 0.959557;0.551183;, + 0.995531;0.534564;, + 0.911710;0.264051;, + 0.946269;0.549368;, + 0.989370;0.511245;, + 0.993351;0.517791;, + 0.893307;0.290193;, + 0.875823;0.291903;, + 0.989370;0.511245;, + 0.919671;0.294804;, + 0.992837;0.480465;, + 0.940909;0.507167;, + 0.925087;0.297402;, + 0.941330;0.343586;, + 0.926942;0.328248;, + 0.934683;0.469925;, + 0.916037;0.478099;, + 0.955318;0.339833;, + 0.926602;0.455368;, + 0.955264;0.354332;, + 0.919668;0.446793;, + 0.957566;0.362848;, + 0.912527;0.443043;, + 0.872782;0.373158;, + 0.948367;0.441273;, + 0.919288;0.373060;, + 0.933018;0.443136;, + 0.934200;0.436900;, + 0.916783;0.371089;, + 0.935125;0.431048;, + 0.944973;0.430058;, + 0.935605;0.426190;, + 0.945547;0.425188;, + 0.934376;0.422378;, + 0.946729;0.421136;, + 0.934637;0.416466;, + 0.945867;0.415337;, + 0.936131;0.411562;, + 0.944536;0.410714;, + 0.935548;0.407812;, + 0.945126;0.406847;, + 0.934036;0.405221;, + 0.946391;0.403976;, + 0.934582;0.399720;, + 0.945327;0.398635;, + 0.936732;0.395377;, + 0.943022;0.394739;, + 0.938903;0.393308;, + 0.941024;0.393092;, + 0.950025;0.432725;, + 0.964184;0.431303;, + 0.965384;0.439088;, + 0.951087;0.424772;, + 0.962376;0.423636;, + 0.951639;0.418194;, + 0.963037;0.417045;, + 0.950231;0.412967;, + 0.964392;0.411542;, + 0.950532;0.404875;, + 0.963406;0.403580;, + 0.952246;0.398233;, + 0.961882;0.397261;, + 0.951580;0.393096;, + 0.962559;0.391989;, + 0.949847;0.389507;, + 0.964010;0.388079;, + 0.950475;0.381982;, + 0.962793;0.380738;, + 0.952940;0.376145;, + 0.960151;0.375413;, + 0.955429;0.373402;, + 0.957861;0.373154;, + 0.966666;0.431243;, + 0.980400;0.429939;, + 0.981495;0.437251;, + 0.967796;0.423937;, + 0.978747;0.422895;, + 0.968413;0.417885;, + 0.979469;0.416831;, + 0.967116;0.413084;, + 0.980852;0.411777;, + 0.967514;0.405663;, + 0.980002;0.404475;, + 0.969258;0.399559;, + 0.978605;0.398667;, + 0.968680;0.394844;, + 0.979330;0.393828;, + 0.967049;0.391554;, + 0.980787;0.390244;, + 0.967756;0.384653;, + 0.979704;0.383511;, + 0.970216;0.379281;, + 0.977211;0.378609;, + 0.972661;0.376752;, + 0.975020;0.376525;, + 0.982811;0.431347;, + 0.994369;0.430837;, + 0.984136;0.425982;, + 0.993352;0.425573;, + 0.984958;0.421504;, + 0.994262;0.421090;, + 0.984124;0.417916;, + 0.995683;0.417404;, + 0.984852;0.412471;, + 0.995361;0.412006;, + 0.986626;0.408010;, + 0.994491;0.407659;, + 0.986391;0.404516;, + 0.995353;0.404116;, + 0.985203;0.402047;, + 0.996764;0.401532;, + 0.986163;0.396997;, + 0.996218;0.396547;, + 0.988492;0.393082;, + 0.994378;0.392816;, + 0.990660;0.391272;, + 0.992645;0.391182;, + 0.932421;0.459512;, + 0.923257;0.263530;, + 0.959778;0.518762;, + 0.936222;0.521783;, + 0.940909;0.507167;, + 0.715515;0.396862;, + 0.499182;0.336927;, + 0.484655;0.334095;, + 0.716951;0.335782;, + 0.564387;0.076817;, + 0.643460;0.343672;, + 0.616978;0.334945;, + 0.564387;0.076817;, + 0.096204;0.018218;, + 0.077882;0.009132;, + 0.140301;0.018636;, + 0.118913;0.022106;, + 0.159948;0.009132;, + 0.733208;0.668843;, + 0.733271;0.671494;, + 0.733061;0.622205;, + 0.734636;0.718815;, + 0.733702;0.623688;, + 0.733817;0.666406;, + 0.734634;0.717573;, + 0.733411;0.719397;, + 0.733436;0.669007;, + 0.731958;0.668479;, + 0.065514;0.263969;, + 0.075463;0.280817;, + 0.088742;0.263945;, + 0.046752;0.280814;, + 0.020600;0.264050;, + 0.118135;0.263808;, + 0.097353;0.346425;, + 0.118135;0.361247;, + 0.098118;0.280881;, + 0.075557;0.346508;, + 0.087647;0.361135;, + 0.060355;0.361119;, + 0.034011;0.346597;, + 0.017495;0.361046;, + 0.017980;0.308672;, + 0.048694;0.343504;, + 0.794423;0.747604;, + 0.841006;0.735950;, + 0.032432;0.280852;, + 0.737977;0.623570;, + 0.742795;0.665101;, + 0.735401;0.718589;, + 0.735464;0.622670;, + 0.806908;0.784277;, + 0.744124;0.623382;, + 0.734055;0.716026;, + 0.735560;0.624194;, + 0.735259;0.624000;, + 0.736255;0.718648;, + 0.734441;0.669812;, + 0.733843;0.625481;, + 0.734435;0.670116;, + 0.735742;0.624306;, + 0.735112;0.623862;, + 0.721657;0.718291;, + 0.733828;0.668886;, + 0.733464;0.621691;, + 0.734023;0.717847;, + 0.733534;0.719777;, + 0.734009;0.671022;, + 0.734158;0.716596;, + 0.731633;0.621868;, + 0.731332;0.631315;, + 0.669043;0.833034;, + 0.660066;0.832672;, + 0.655598;0.849640;, + 0.737725;0.714443;, + 0.741942;0.676619;, + 0.741961;0.715542;, + 0.733665;0.674284;, + 0.734971;0.669387;, + 0.729903;0.675143;, + 0.734761;0.719063;, + 0.735332;0.716619;, + 0.734955;0.668426;, + 0.721716;0.621992;, + 0.490854;0.881098;, + 0.604315;0.879016;, + 0.619397;0.857270;, + 0.550381;0.879254;, + 0.614918;0.901410;, + 0.733632;0.622431;, + 0.733752;0.622431;, + 0.733619;0.621524;, + 0.734255;0.718460;, + 0.733645;0.623168;, + 0.734765;0.668727;, + 0.733004;0.624609;, + 0.732771;0.623537;, + 0.732742;0.623931;, + 0.733127;0.622943;, + 0.738124;0.626577;, + 0.733325;0.623897;, + 0.736550;0.716796;, + 0.733320;0.626103;, + 0.734626;0.670928;, + 0.735641;0.711463;, + 0.734563;0.670905;, + 0.735018;0.673031;, + 0.734433;0.669076;, + 0.734127;0.670046;, + 0.735105;0.667616;, + 0.734543;0.621846;, + 0.734712;0.717490;, + 0.734725;0.623514;, + 0.733232;0.624888;, + 0.736739;0.716543;, + 0.734684;0.670029;, + 0.734888;0.718644;, + 0.732628;0.670896;, + 0.733935;0.669238;, + 0.733037;0.669749;, + 0.170261;0.263941;, + 0.147528;0.263863;, + 0.159819;0.280672;, + 0.202812;0.280741;, + 0.212210;0.264050;, + 0.138917;0.346425;, + 0.137163;0.280736;, + 0.149118;0.361154;, + 0.160713;0.346508;, + 0.175915;0.361213;, + 0.217292;0.361140;, + 0.217795;0.309277;, + 0.203145;0.343675;, + 0.180652;0.278493;, + 0.737977;0.623570;, + 0.742795;0.665101;, + 0.734658;0.673204;, + 0.734427;0.624424;, + 0.741949;0.625748;, + 0.735977;0.717392;, + 0.735384;0.622600;, + 0.735442;0.624471;, + 0.734397;0.718833;, + 0.735195;0.674837;, + 0.731426;0.622834;, + 0.733554;0.671983;, + 0.732964;0.622128;, + 0.735365;0.720658;, + 0.732993;0.622640;, + 0.722763;0.718246;, + 0.734404;0.664391;, + 0.806292;0.771849;, + 0.733568;0.624201;, + 0.735564;0.717674;, + 0.734832;0.718436;, + 0.734634;0.672608;, + 0.733135;0.673954;, + 0.738890;0.713850;, + 0.734689;0.623399;, + 0.732473;0.640685;, + 0.741942;0.676619;, + 0.734732;0.719564;, + 0.736409;0.671560;, + 0.733928;0.669098;, + 0.734488;0.716382;, + 0.735985;0.719547;, + 0.734111;0.670206;, + 0.722716;0.624358;, + 0.490854;0.881098;, + 0.619397;0.857270;, + 0.604316;0.879016;, + 0.550381;0.879254;, + 0.614041;0.900874;, + 0.734698;0.623311;, + 0.733366;0.623859;, + 0.733853;0.622432;, + 0.736423;0.718140;, + 0.733794;0.624449;, + 0.733416;0.668524;, + 0.734057;0.624252;, + 0.733026;0.622840;, + 0.733957;0.622990;, + 0.733958;0.669768;, + 0.573787;0.946976;, + 0.570524;0.952054;, + 0.732989;0.677617;, + 0.733901;0.623536;, + 0.742194;0.624474;, + 0.735057;0.717697;, + 0.733910;0.670742;, + 0.722198;0.625877;, + 0.726309;0.666336;, + 0.732760;0.623866;, + 0.722409;0.718816;, + 0.771240;0.998210;, + 0.768920;0.993101;, + 0.688441;0.780145;, + 0.670920;0.758421;, + 0.716559;0.753271;, + 0.699682;0.779579;, + 0.768920;0.993101;, + 0.771240;0.998210;, + 0.684801;0.799303;, + 0.703203;0.796694;, + 0.578377;0.723871;, + 0.556798;0.737410;, + 0.535220;0.723871;, + 0.494371;0.846123;, + 0.556672;0.847727;, + 0.617913;0.846306;, + 0.883801;0.999405;, + 0.883640;0.999019;, + 0.883640;0.999019;, + 0.883801;0.999405;, + 0.869557;0.983855;, + 0.878434;0.995071;, + 0.843654;0.956371;, + 0.862861;0.974051;, + 0.704350;0.916866;, + 0.711279;0.931275;, + 0.726665;0.956005;, + 0.758250;0.982937;, + 0.718910;0.943490;, + 0.801523;0.828198;, + 0.803097;0.850936;, + 0.804537;0.864603;, + 0.813820;0.899525;, + 0.696062;0.914837;, + 0.809005;0.773290;, + 0.799319;0.811168;, + 0.709933;0.855338;, + 0.699389;0.815607;, + 0.845499;0.203618;, + 0.836934;0.209967;, + 0.834313;0.222928;, + 0.836611;0.235486;, + 0.817344;0.816095;, + 0.818300;0.813808;, + 0.827677;0.929505;, + 0.900992;0.226326;, + 0.889329;0.204667;, + 0.864170;0.826738;, + 0.897258;0.241354;, + 0.905079;0.230177;, + 0.756146;0.776044;, + 0.749218;0.822256;, + 0.665190;0.878729;, + 0.688338;0.907690;, + 0.762590;0.730701;, + 0.602368;0.738846;, + 0.723336;0.628567;, + 0.723137;0.664019;, + 0.864352;0.570403;, + 0.855895;0.608482;, + 0.865600;0.559362;, + 0.862728;0.546228;, + 0.857614;0.550540;, + 0.739543;0.726668;, + 0.631750;0.845695;, + 0.876169;0.248651;, + 0.890294;0.243145;, + 0.872748;0.198756;, + 0.854340;0.200840;, + 0.879155;0.197889;, + 0.847218;0.244311;, + 0.861893;0.250498;, + 0.842524;0.242503;, + 0.871498;0.251096;, + 0.937684;0.974051;, + 0.956890;0.956371;, + 0.930988;0.983855;, + 0.878434;0.995071;, + 0.758250;0.982937;, + 0.726665;0.956005;, + 0.711279;0.931275;, + 0.704350;0.916866;, + 0.718910;0.943490;, + 0.996007;0.864603;, + 0.813820;0.899525;, + 0.997447;0.850936;, + 0.999022;0.828198;, + 0.696062;0.914837;, + 0.998196;0.807248;, + 0.993636;0.784277;, + 0.794423;0.747604;, + 0.811872;0.736951;, + 0.669043;0.833034;, + 0.699389;0.815607;, + 0.709933;0.855338;, + 0.904083;0.234820;, + 0.906567;0.222917;, + 0.903734;0.210631;, + 0.894473;0.204614;, + 0.984046;0.817359;, + 0.982715;0.814038;, + 0.972868;0.929505;, + 0.934802;0.823017;, + 0.847081;0.205608;, + 0.933650;0.826738;, + 0.838508;0.240382;, + 0.756146;0.776044;, + 0.749218;0.822256;, + 0.655598;0.849640;, + 0.660066;0.832672;, + 0.665190;0.878729;, + 0.688338;0.907690;, + 0.625881;0.747856;, + 0.511229;0.738846;, + 0.721795;0.673083;, + 0.656300;0.740491;, + 0.647354;0.737719;, + 0.984113;0.609149;, + 0.981105;0.573070;, + 0.970594;0.556694;, + 0.980214;0.557876;, + 0.489245;0.841771;, + 0.846038;0.242079;, + 0.861311;0.247298;, + 0.884914;0.201981;, + 0.865010;0.200005;, + 0.858082;0.199183;, + 0.876747;0.249049;, + 0.892614;0.243184;, + 0.897689;0.241471;, + 0.866361;0.249615;, + 0.523805;0.842839;, + 0.590386;0.842199;, + 0.184823;0.343667;, + 0.264166;0.187404;, + 0.551922;0.238188;; + } + + VertexDuplicationIndices { + 4432; + 3420; + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387, + 388, + 389, + 390, + 391, + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419, + 420, + 421, + 422, + 423, + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451, + 452, + 453, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483, + 484, + 485, + 486, + 487, + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547, + 548, + 549, + 550, + 551, + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579, + 580, + 581, + 582, + 583, + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611, + 612, + 613, + 614, + 615, + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643, + 644, + 645, + 646, + 647, + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675, + 676, + 677, + 678, + 679, + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707, + 708, + 709, + 710, + 711, + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739, + 740, + 741, + 742, + 743, + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771, + 772, + 773, + 774, + 775, + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803, + 804, + 805, + 806, + 807, + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835, + 836, + 837, + 838, + 839, + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867, + 868, + 869, + 870, + 871, + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899, + 900, + 901, + 902, + 903, + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931, + 932, + 933, + 934, + 935, + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963, + 964, + 965, + 966, + 967, + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995, + 996, + 997, + 998, + 999, + 1000, + 1001, + 1002, + 1003, + 1004, + 1005, + 1006, + 1007, + 1008, + 1009, + 1010, + 1011, + 1012, + 1013, + 1014, + 1015, + 1016, + 1017, + 1018, + 1019, + 1020, + 1021, + 1022, + 1023, + 1024, + 1025, + 1026, + 1027, + 1028, + 1029, + 1030, + 1031, + 1032, + 1033, + 1034, + 1035, + 1036, + 1037, + 1038, + 1039, + 1040, + 1041, + 1042, + 1043, + 1044, + 1045, + 1046, + 1047, + 1048, + 1049, + 1050, + 1051, + 1052, + 1053, + 1054, + 1055, + 1056, + 1057, + 1058, + 1059, + 1060, + 1061, + 1062, + 1063, + 1064, + 1065, + 1066, + 1067, + 1068, + 1069, + 1070, + 1071, + 1072, + 1073, + 1074, + 1075, + 1076, + 1077, + 1078, + 1079, + 1080, + 1081, + 1082, + 1083, + 1084, + 1085, + 1086, + 1087, + 1088, + 1089, + 1090, + 1091, + 1092, + 1093, + 1094, + 1095, + 1096, + 1097, + 1098, + 1099, + 1100, + 1101, + 1102, + 1103, + 1104, + 1105, + 1106, + 1107, + 1108, + 1109, + 1110, + 1111, + 1112, + 1113, + 1114, + 1115, + 1116, + 1117, + 1118, + 1119, + 1120, + 1121, + 1122, + 1123, + 1124, + 1125, + 1126, + 1127, + 1128, + 1129, + 1130, + 1131, + 1132, + 1133, + 1134, + 1135, + 1136, + 1137, + 1138, + 1139, + 1140, + 1141, + 1142, + 1143, + 1144, + 1145, + 1146, + 1147, + 1148, + 1149, + 1150, + 1151, + 1152, + 1153, + 1154, + 1155, + 1156, + 1157, + 1158, + 1159, + 1160, + 1161, + 1162, + 1163, + 1164, + 1165, + 1166, + 1167, + 1168, + 1169, + 1170, + 1171, + 1172, + 1173, + 1174, + 1175, + 1176, + 1177, + 1178, + 1179, + 1180, + 1181, + 1182, + 1183, + 1184, + 1185, + 1186, + 1187, + 1188, + 1189, + 1190, + 1191, + 1192, + 1193, + 1194, + 1195, + 1196, + 1197, + 1198, + 1199, + 1200, + 1201, + 1202, + 1203, + 1204, + 1205, + 1206, + 1207, + 1208, + 1209, + 1210, + 1211, + 1212, + 1213, + 1214, + 1215, + 1216, + 1217, + 1218, + 1219, + 1220, + 1221, + 1222, + 1223, + 1224, + 1225, + 1226, + 1227, + 1228, + 1229, + 1230, + 1231, + 1232, + 1233, + 1234, + 1235, + 1236, + 1237, + 1238, + 1239, + 1240, + 1241, + 1242, + 1243, + 1244, + 1245, + 1246, + 1247, + 1248, + 1249, + 1250, + 1251, + 1252, + 1253, + 1254, + 1255, + 1256, + 1257, + 1258, + 1259, + 1260, + 1261, + 1262, + 1263, + 1264, + 1265, + 1266, + 1267, + 1268, + 1269, + 1270, + 1271, + 1272, + 1273, + 1274, + 1275, + 1276, + 1277, + 1278, + 1279, + 1280, + 1281, + 1282, + 1283, + 1284, + 1285, + 1286, + 1287, + 1288, + 1289, + 1290, + 1291, + 1292, + 1293, + 1294, + 1295, + 1296, + 1297, + 1298, + 1299, + 1300, + 1301, + 1302, + 1303, + 1304, + 1305, + 1306, + 1307, + 1308, + 1309, + 1310, + 1311, + 1312, + 1313, + 1314, + 1315, + 1316, + 1317, + 1318, + 1319, + 1320, + 1321, + 1322, + 1323, + 1324, + 1325, + 1326, + 1327, + 1328, + 1329, + 1330, + 1331, + 1332, + 1333, + 1334, + 1335, + 1336, + 1337, + 1338, + 1339, + 1340, + 1341, + 1342, + 1343, + 1344, + 1345, + 1346, + 1347, + 1348, + 1349, + 1350, + 1351, + 1352, + 1353, + 1354, + 1355, + 1356, + 1357, + 1358, + 1359, + 1360, + 1361, + 1362, + 1363, + 1364, + 1365, + 1366, + 1367, + 1368, + 1369, + 1370, + 1371, + 1372, + 1373, + 1374, + 1375, + 1376, + 1377, + 1378, + 1379, + 1380, + 1381, + 1382, + 1383, + 1384, + 1385, + 1386, + 1387, + 1388, + 1389, + 1390, + 1391, + 1392, + 1393, + 1394, + 1395, + 1396, + 1397, + 1398, + 1399, + 1400, + 1401, + 1402, + 1403, + 1404, + 1405, + 1406, + 1407, + 1408, + 1409, + 1410, + 1411, + 1412, + 1413, + 1414, + 1415, + 1416, + 1417, + 1418, + 1419, + 1420, + 1421, + 1422, + 1423, + 1424, + 1425, + 1426, + 1427, + 1428, + 1429, + 1430, + 1431, + 1432, + 1433, + 1434, + 1435, + 1436, + 1437, + 1438, + 1439, + 1440, + 1441, + 1442, + 1443, + 1444, + 1445, + 1446, + 1447, + 1448, + 1449, + 1450, + 1451, + 1452, + 1453, + 1454, + 1455, + 1456, + 1457, + 1458, + 1459, + 1460, + 1461, + 1462, + 1463, + 1464, + 1465, + 1466, + 1467, + 1468, + 1469, + 1470, + 1471, + 1472, + 1473, + 1474, + 1475, + 1476, + 1477, + 1478, + 1479, + 1480, + 1481, + 1482, + 1483, + 1484, + 1485, + 1486, + 1487, + 1488, + 1489, + 1490, + 1491, + 1492, + 1493, + 1494, + 1495, + 1496, + 1497, + 1498, + 1499, + 1500, + 1501, + 1502, + 1503, + 1504, + 1505, + 1506, + 1507, + 1508, + 1509, + 1510, + 1511, + 1512, + 1513, + 1514, + 1515, + 1516, + 1517, + 1518, + 1519, + 1520, + 1521, + 1522, + 1523, + 1524, + 1525, + 1526, + 1527, + 1528, + 1529, + 1530, + 1531, + 1532, + 1533, + 1534, + 1535, + 1536, + 1537, + 1538, + 1539, + 1540, + 1541, + 1542, + 1543, + 1544, + 1545, + 1546, + 1547, + 1548, + 1549, + 1550, + 1551, + 1552, + 1553, + 1554, + 1555, + 1556, + 1557, + 1558, + 1559, + 1560, + 1561, + 1562, + 1563, + 1564, + 1565, + 1566, + 1567, + 1568, + 1569, + 1570, + 1571, + 1572, + 1573, + 1574, + 1575, + 1576, + 1577, + 1578, + 1579, + 1580, + 1581, + 1582, + 1583, + 1584, + 1585, + 1586, + 1587, + 1588, + 1589, + 1590, + 1591, + 1592, + 1593, + 1594, + 1595, + 1596, + 1597, + 1598, + 1599, + 1600, + 1601, + 1602, + 1603, + 1604, + 1605, + 1606, + 1607, + 1608, + 1609, + 1610, + 1611, + 1612, + 1613, + 1614, + 1615, + 1616, + 1617, + 1618, + 1619, + 1620, + 1621, + 1622, + 1623, + 1624, + 1625, + 1626, + 1627, + 1628, + 1629, + 1630, + 1631, + 1632, + 1633, + 1634, + 1635, + 1636, + 1637, + 1638, + 1639, + 1640, + 1641, + 1642, + 1643, + 1644, + 1645, + 1646, + 1647, + 1648, + 1649, + 1650, + 1651, + 1652, + 1653, + 1654, + 1655, + 1656, + 1657, + 1658, + 1659, + 1660, + 1661, + 1662, + 1663, + 1664, + 1665, + 1666, + 1667, + 1668, + 1669, + 1670, + 1671, + 1672, + 1673, + 1674, + 1675, + 1676, + 1677, + 1678, + 1679, + 1680, + 1681, + 1682, + 1683, + 1684, + 1685, + 1686, + 1687, + 1688, + 1689, + 1690, + 1691, + 1692, + 1693, + 1694, + 1695, + 1696, + 1697, + 1698, + 1699, + 1700, + 1701, + 1702, + 1703, + 1704, + 1705, + 1706, + 1707, + 1708, + 1709, + 1710, + 1711, + 1712, + 1713, + 1714, + 1715, + 1716, + 1717, + 1718, + 1719, + 1720, + 1721, + 1722, + 1723, + 1724, + 1725, + 1726, + 1727, + 1728, + 1729, + 1730, + 1731, + 1732, + 1733, + 1734, + 1735, + 1736, + 1737, + 1738, + 1739, + 1740, + 1741, + 1742, + 1743, + 1744, + 1745, + 1746, + 1747, + 1748, + 1749, + 1750, + 1751, + 1752, + 1753, + 1754, + 1755, + 1756, + 1757, + 1758, + 1759, + 1760, + 1761, + 1762, + 1763, + 1764, + 1765, + 1766, + 1767, + 1768, + 1769, + 1770, + 1771, + 1772, + 1773, + 1774, + 1775, + 1776, + 1777, + 1778, + 1779, + 1780, + 1781, + 1782, + 1783, + 1784, + 1785, + 1786, + 1787, + 1788, + 1789, + 1790, + 1791, + 1792, + 1793, + 1794, + 1795, + 1796, + 1797, + 1798, + 1799, + 1800, + 1801, + 1802, + 1803, + 1804, + 1805, + 1806, + 1807, + 1808, + 1809, + 1810, + 1811, + 1812, + 1813, + 1814, + 1815, + 1816, + 1817, + 1818, + 1819, + 1820, + 1821, + 1822, + 1823, + 1824, + 1825, + 1826, + 1827, + 1828, + 1829, + 1830, + 1831, + 1832, + 1833, + 1834, + 1835, + 1836, + 1837, + 1838, + 1839, + 1840, + 1841, + 1842, + 1843, + 1844, + 1845, + 1846, + 1847, + 1848, + 1849, + 1850, + 1851, + 1852, + 1853, + 1854, + 1855, + 1856, + 1857, + 1858, + 1859, + 1860, + 1861, + 1862, + 1863, + 1864, + 1865, + 1866, + 1867, + 1868, + 1869, + 1870, + 1871, + 1872, + 1873, + 1874, + 1875, + 1876, + 1877, + 1878, + 1879, + 1880, + 1881, + 1882, + 1883, + 1884, + 1885, + 1886, + 1887, + 1888, + 1889, + 1890, + 1891, + 1892, + 1893, + 1894, + 1895, + 1896, + 1897, + 1898, + 1899, + 1900, + 1901, + 1902, + 1903, + 1904, + 1905, + 1906, + 1907, + 1908, + 1909, + 1910, + 1911, + 1912, + 1913, + 1914, + 1915, + 1916, + 1917, + 1918, + 1919, + 1920, + 1921, + 1922, + 1923, + 1924, + 1925, + 1926, + 1927, + 1928, + 1929, + 1930, + 1931, + 1932, + 1933, + 1934, + 1935, + 1936, + 1937, + 1938, + 1939, + 1940, + 1941, + 1942, + 1943, + 1944, + 1945, + 1946, + 1947, + 1948, + 1949, + 1950, + 1951, + 1952, + 1953, + 1954, + 1955, + 1956, + 1957, + 1958, + 1959, + 1960, + 1961, + 1962, + 1963, + 1964, + 1965, + 1966, + 1967, + 1968, + 1969, + 1970, + 1971, + 1972, + 1973, + 1974, + 1975, + 1976, + 1977, + 1978, + 1979, + 1980, + 1981, + 1982, + 1983, + 1984, + 1985, + 1986, + 1987, + 1988, + 1989, + 1990, + 1991, + 1992, + 1993, + 1994, + 1995, + 1996, + 1997, + 1998, + 1999, + 2000, + 2001, + 2002, + 2003, + 2004, + 2005, + 2006, + 2007, + 2008, + 2009, + 2010, + 2011, + 2012, + 2013, + 2014, + 2015, + 2016, + 2017, + 2018, + 2019, + 2020, + 2021, + 2022, + 2023, + 2024, + 2025, + 2026, + 2027, + 2028, + 2029, + 2030, + 2031, + 2032, + 2033, + 2034, + 2035, + 2036, + 2037, + 2038, + 2039, + 2040, + 2041, + 2042, + 2043, + 2044, + 2045, + 2046, + 2047, + 2048, + 2049, + 2050, + 2051, + 2052, + 2053, + 2054, + 2055, + 2056, + 2057, + 2058, + 2059, + 2060, + 2061, + 2062, + 2063, + 2064, + 2065, + 2066, + 2067, + 2068, + 2069, + 2070, + 2071, + 2072, + 2073, + 2074, + 2075, + 2076, + 2077, + 2078, + 2079, + 2080, + 2081, + 2082, + 2083, + 2084, + 2085, + 2086, + 2087, + 2088, + 2089, + 2090, + 2091, + 2092, + 2093, + 2094, + 2095, + 2096, + 2097, + 2098, + 2099, + 2100, + 2101, + 2102, + 2103, + 2104, + 2105, + 2106, + 2107, + 2108, + 2109, + 2110, + 2111, + 2112, + 2113, + 2114, + 2115, + 2116, + 2117, + 2118, + 2119, + 2120, + 2121, + 2122, + 2123, + 2124, + 2125, + 2126, + 2127, + 2128, + 2129, + 2130, + 2131, + 2132, + 2133, + 2134, + 2135, + 2136, + 2137, + 2138, + 2139, + 2140, + 2141, + 2142, + 2143, + 2144, + 2145, + 2146, + 2147, + 2148, + 2149, + 2150, + 2151, + 2152, + 2153, + 2154, + 2155, + 2156, + 2157, + 2158, + 2159, + 2160, + 2161, + 2162, + 2163, + 2164, + 2165, + 2166, + 2167, + 2168, + 2169, + 2170, + 2171, + 2172, + 2173, + 2174, + 2175, + 2176, + 2177, + 2178, + 2179, + 2180, + 2181, + 2182, + 2183, + 2184, + 2185, + 2186, + 2187, + 2188, + 2189, + 2190, + 2191, + 2192, + 2193, + 2194, + 2195, + 2196, + 2197, + 2198, + 2199, + 2200, + 2201, + 2202, + 2203, + 2204, + 2205, + 2206, + 2207, + 2208, + 2209, + 2210, + 2211, + 2212, + 2213, + 2214, + 2215, + 2216, + 2217, + 2218, + 2219, + 2220, + 2221, + 2222, + 2223, + 2224, + 2225, + 2226, + 2227, + 2228, + 2229, + 2230, + 2231, + 2232, + 2233, + 2234, + 2235, + 2236, + 2237, + 2238, + 2239, + 2240, + 2241, + 2242, + 2243, + 2244, + 2245, + 2246, + 2247, + 2248, + 2249, + 2250, + 2251, + 2252, + 2253, + 2254, + 2255, + 2256, + 2257, + 2258, + 2259, + 2260, + 2261, + 2262, + 2263, + 2264, + 2265, + 2266, + 2267, + 2268, + 2269, + 2270, + 2271, + 2272, + 2273, + 2274, + 2275, + 2276, + 2277, + 2278, + 2279, + 2280, + 2281, + 2282, + 2283, + 2284, + 2285, + 2286, + 2287, + 2288, + 2289, + 2290, + 2291, + 2292, + 2293, + 2294, + 2295, + 2296, + 2297, + 2298, + 2299, + 2300, + 2301, + 2302, + 2303, + 2304, + 2305, + 2306, + 2307, + 2308, + 2309, + 2310, + 2311, + 2312, + 2313, + 2314, + 2315, + 2316, + 2317, + 2318, + 2319, + 2320, + 2321, + 2322, + 2323, + 2324, + 2325, + 2326, + 2327, + 2328, + 2329, + 2330, + 2331, + 2332, + 2333, + 2334, + 2335, + 2336, + 2337, + 2338, + 2339, + 2340, + 2341, + 2342, + 2343, + 2344, + 2345, + 2346, + 2347, + 2348, + 2349, + 2350, + 2351, + 2352, + 2353, + 2354, + 2355, + 2356, + 2357, + 2358, + 2359, + 2360, + 2361, + 2362, + 2363, + 2364, + 2365, + 2366, + 2367, + 2368, + 2369, + 2370, + 2371, + 2372, + 2373, + 2374, + 2375, + 2376, + 2377, + 2378, + 2379, + 2380, + 2381, + 2382, + 2383, + 2384, + 2385, + 2386, + 2387, + 2388, + 2389, + 2390, + 2391, + 2392, + 2393, + 2394, + 2395, + 2396, + 2397, + 2398, + 2399, + 2400, + 2401, + 2402, + 2403, + 2404, + 2405, + 2406, + 2407, + 2408, + 2409, + 2410, + 2411, + 2412, + 2413, + 2414, + 2415, + 2416, + 2417, + 2418, + 2419, + 2420, + 2421, + 2422, + 2423, + 2424, + 2425, + 2426, + 2427, + 2428, + 2429, + 2430, + 2431, + 2432, + 2433, + 2434, + 2435, + 2436, + 2437, + 2438, + 2439, + 2440, + 2441, + 2442, + 2443, + 2444, + 2445, + 2446, + 2447, + 2448, + 2449, + 2450, + 2451, + 2452, + 2453, + 2454, + 2455, + 2456, + 2457, + 2458, + 2459, + 2460, + 2461, + 2462, + 2463, + 2464, + 2465, + 2466, + 2467, + 2468, + 2469, + 2470, + 2471, + 2472, + 2473, + 2474, + 2475, + 2476, + 2477, + 2478, + 2479, + 2480, + 2481, + 2482, + 2483, + 2484, + 2485, + 2486, + 2487, + 2488, + 2489, + 2490, + 2491, + 2492, + 2493, + 2494, + 2495, + 2496, + 2497, + 2498, + 2499, + 2500, + 2501, + 2502, + 2503, + 2504, + 2505, + 2506, + 2507, + 2508, + 2509, + 2510, + 2511, + 2512, + 2513, + 2514, + 2515, + 2516, + 2517, + 2518, + 2519, + 2520, + 2521, + 2522, + 2523, + 2524, + 2525, + 2526, + 2527, + 2528, + 2529, + 2530, + 2531, + 2532, + 2533, + 2534, + 2535, + 2536, + 2537, + 2538, + 2539, + 2540, + 2541, + 2542, + 2543, + 2544, + 2545, + 2546, + 2547, + 2548, + 2549, + 2550, + 2551, + 2552, + 2553, + 2554, + 2555, + 2556, + 2557, + 2558, + 2559, + 2560, + 2561, + 2562, + 2563, + 2564, + 2565, + 2566, + 2567, + 2568, + 2569, + 2570, + 2571, + 2572, + 2573, + 2574, + 2575, + 2576, + 2577, + 2578, + 2579, + 2580, + 2581, + 2582, + 2583, + 2584, + 2585, + 2586, + 2587, + 2588, + 2589, + 2590, + 2591, + 2592, + 2593, + 2594, + 2595, + 2596, + 2597, + 2598, + 2599, + 2600, + 2601, + 2602, + 2603, + 2604, + 2605, + 2606, + 2607, + 2608, + 2609, + 2610, + 2611, + 2612, + 2613, + 2614, + 2615, + 2616, + 2617, + 2618, + 2619, + 2620, + 2621, + 2622, + 2623, + 2624, + 2625, + 2626, + 2627, + 2628, + 2629, + 2630, + 2631, + 2632, + 2633, + 2634, + 2635, + 2636, + 2637, + 2638, + 2639, + 2640, + 2641, + 2642, + 2643, + 2644, + 2645, + 2646, + 2647, + 2648, + 2649, + 2650, + 2651, + 2652, + 2653, + 2654, + 2655, + 2656, + 2657, + 2658, + 2659, + 2660, + 2661, + 2662, + 2663, + 2664, + 2665, + 2666, + 2667, + 2668, + 2669, + 2670, + 2671, + 2672, + 2673, + 2674, + 2675, + 2676, + 2677, + 2678, + 2679, + 2680, + 2681, + 2682, + 2683, + 2684, + 2685, + 2686, + 2687, + 2688, + 2689, + 2690, + 2691, + 2692, + 2693, + 2694, + 2695, + 2696, + 2697, + 2698, + 2699, + 2700, + 2701, + 2702, + 2703, + 2704, + 2705, + 2706, + 2707, + 2708, + 2709, + 2710, + 2711, + 2712, + 2713, + 2714, + 2715, + 2716, + 2717, + 2718, + 2719, + 2720, + 2721, + 2722, + 2723, + 2724, + 2725, + 2726, + 2727, + 2728, + 2729, + 2730, + 2731, + 2732, + 2733, + 2734, + 2735, + 2736, + 2737, + 2738, + 2739, + 2740, + 2741, + 2742, + 2743, + 2744, + 2745, + 2746, + 2747, + 2748, + 2749, + 2750, + 2751, + 2752, + 2753, + 2754, + 2755, + 2756, + 2757, + 2758, + 2759, + 2760, + 2761, + 2762, + 2763, + 2764, + 2765, + 2766, + 2767, + 2768, + 2769, + 2770, + 2771, + 2772, + 2773, + 2774, + 2775, + 2776, + 2777, + 2778, + 2779, + 2780, + 2781, + 2782, + 2783, + 2784, + 2785, + 2786, + 2787, + 2788, + 2789, + 2790, + 2791, + 2792, + 2793, + 2794, + 2795, + 2796, + 2797, + 2798, + 2799, + 2800, + 2801, + 2802, + 2803, + 2804, + 2805, + 2806, + 2807, + 2808, + 2809, + 2810, + 2811, + 2812, + 2813, + 2814, + 2815, + 2816, + 2817, + 2818, + 2819, + 2820, + 2821, + 2822, + 2823, + 2824, + 2825, + 2826, + 2827, + 2828, + 2829, + 2830, + 2831, + 2832, + 2833, + 2834, + 2835, + 2836, + 2837, + 2838, + 2839, + 2840, + 2841, + 2842, + 2843, + 2844, + 2845, + 2846, + 2847, + 2848, + 2849, + 2850, + 2851, + 2852, + 2853, + 2854, + 2855, + 2856, + 2857, + 2858, + 2859, + 2860, + 2861, + 2862, + 2863, + 2864, + 2865, + 2866, + 2867, + 2868, + 2869, + 2870, + 2871, + 2872, + 2873, + 2874, + 2875, + 2876, + 2877, + 2878, + 2879, + 2880, + 2881, + 2882, + 2883, + 2884, + 2885, + 2886, + 2887, + 2888, + 2889, + 2890, + 2891, + 2892, + 2893, + 2894, + 2895, + 2896, + 2897, + 2898, + 2899, + 2900, + 2901, + 2902, + 2903, + 2904, + 2905, + 2906, + 2907, + 2908, + 2909, + 2910, + 2911, + 2912, + 2913, + 2914, + 2915, + 2916, + 2917, + 2918, + 2919, + 2920, + 2921, + 2922, + 2923, + 2924, + 2925, + 2926, + 2927, + 2928, + 2929, + 2930, + 2931, + 2932, + 2933, + 2934, + 2935, + 2936, + 2937, + 2938, + 2939, + 2940, + 2941, + 2942, + 2943, + 2944, + 2945, + 2946, + 2947, + 2948, + 2949, + 2950, + 2951, + 2952, + 2953, + 2954, + 2955, + 2956, + 2957, + 2958, + 2959, + 2960, + 2961, + 2962, + 2963, + 2964, + 2965, + 2966, + 2967, + 2968, + 2969, + 2970, + 2971, + 2972, + 2973, + 2974, + 2975, + 2976, + 2977, + 2978, + 2979, + 2980, + 2981, + 2982, + 2983, + 2984, + 2985, + 2986, + 2987, + 2988, + 2989, + 2990, + 2991, + 2992, + 2993, + 2994, + 2995, + 2996, + 2997, + 2998, + 2999, + 3000, + 3001, + 3002, + 3003, + 3004, + 3005, + 3006, + 3007, + 3008, + 3009, + 3010, + 3011, + 3012, + 3013, + 3014, + 3015, + 3016, + 3017, + 3018, + 3019, + 3020, + 3021, + 3022, + 3023, + 3024, + 3025, + 3026, + 3027, + 3028, + 3029, + 3030, + 3031, + 3032, + 3033, + 3034, + 3035, + 3036, + 3037, + 3038, + 3039, + 3040, + 3041, + 3042, + 3043, + 3044, + 3045, + 3046, + 3047, + 3048, + 3049, + 3050, + 3051, + 3052, + 3053, + 3054, + 3055, + 3056, + 3057, + 3058, + 3059, + 3060, + 3061, + 3062, + 3063, + 3064, + 3065, + 3066, + 3067, + 3068, + 3069, + 3070, + 3071, + 3072, + 3073, + 3074, + 3075, + 3076, + 3077, + 3078, + 3079, + 3080, + 3081, + 3082, + 3083, + 3084, + 3085, + 3086, + 3087, + 3088, + 3089, + 3090, + 3091, + 3092, + 3093, + 3094, + 3095, + 3096, + 3097, + 3098, + 3099, + 3100, + 3101, + 3102, + 3103, + 3104, + 3105, + 3106, + 3107, + 3108, + 3109, + 3110, + 3111, + 3112, + 3113, + 3114, + 3115, + 3116, + 3117, + 3118, + 3119, + 3120, + 3121, + 3122, + 3123, + 3124, + 3125, + 3126, + 3127, + 3128, + 3129, + 3130, + 3131, + 3132, + 3133, + 3134, + 3135, + 3136, + 3137, + 3138, + 3139, + 3140, + 3141, + 3142, + 3143, + 3144, + 3145, + 3146, + 3147, + 3148, + 3149, + 3150, + 3151, + 3152, + 3153, + 3154, + 3155, + 3156, + 3157, + 3158, + 3159, + 3160, + 3161, + 3162, + 3163, + 3164, + 3165, + 3166, + 3167, + 3168, + 3169, + 3170, + 3171, + 3172, + 3173, + 3174, + 3175, + 3176, + 3177, + 3178, + 3179, + 3180, + 3181, + 3182, + 3183, + 3184, + 3185, + 3186, + 3187, + 3188, + 3189, + 3190, + 3191, + 3192, + 3193, + 3194, + 3195, + 3196, + 3197, + 3198, + 3199, + 3200, + 3201, + 3202, + 3203, + 3204, + 3205, + 3206, + 3207, + 3208, + 3209, + 3210, + 3211, + 3212, + 3213, + 3214, + 3215, + 3216, + 3217, + 3218, + 3219, + 3220, + 3221, + 3222, + 3223, + 3224, + 3225, + 3226, + 3227, + 3228, + 3229, + 3230, + 3231, + 3232, + 3233, + 3234, + 3235, + 3236, + 3237, + 3238, + 3239, + 3240, + 3241, + 3242, + 3243, + 3244, + 3245, + 3246, + 3247, + 3248, + 3249, + 3250, + 3251, + 3252, + 3253, + 3254, + 3255, + 3256, + 3257, + 3258, + 3259, + 3260, + 3261, + 3262, + 3263, + 3264, + 3265, + 3266, + 3267, + 3268, + 3269, + 3270, + 3271, + 3272, + 3273, + 3274, + 3275, + 3276, + 3277, + 3278, + 3279, + 3280, + 3281, + 3282, + 3283, + 3284, + 3285, + 3286, + 3287, + 3288, + 3289, + 3290, + 3291, + 3292, + 3293, + 3294, + 3295, + 3296, + 3297, + 3298, + 3299, + 3300, + 3301, + 3302, + 3303, + 3304, + 3305, + 3306, + 3307, + 3308, + 3309, + 3310, + 3311, + 3312, + 3313, + 3314, + 3315, + 3316, + 3317, + 3318, + 3319, + 3320, + 3321, + 3322, + 3323, + 3324, + 3325, + 3326, + 3327, + 3328, + 3329, + 3330, + 3331, + 3332, + 3333, + 3334, + 3335, + 3336, + 3337, + 3338, + 3339, + 3340, + 3341, + 3342, + 3343, + 3344, + 3345, + 3346, + 3347, + 3348, + 3349, + 3350, + 3351, + 3352, + 3353, + 3354, + 3355, + 3356, + 3357, + 3358, + 3359, + 3360, + 3361, + 3362, + 3363, + 3364, + 3365, + 3366, + 3367, + 3368, + 3369, + 3370, + 3371, + 3372, + 3373, + 3374, + 3375, + 3376, + 3377, + 3378, + 3379, + 3380, + 3381, + 3382, + 3383, + 3384, + 3385, + 3386, + 3387, + 3388, + 3389, + 3390, + 3391, + 3392, + 3393, + 3394, + 3395, + 3396, + 3397, + 3398, + 3399, + 3400, + 3401, + 3402, + 3403, + 3404, + 3405, + 3406, + 3407, + 3408, + 3409, + 3410, + 3411, + 3412, + 3413, + 3414, + 3415, + 3416, + 3417, + 3418, + 3419, + 1, + 62, + 11, + 11, + 16, + 26, + 27, + 0, + 28, + 0, + 36, + 84, + 45, + 39, + 32, + 51, + 52, + 65, + 53, + 67, + 35, + 44, + 66, + 54, + 34, + 43, + 26, + 33, + 64, + 0, + 64, + 54, + 20, + 4, + 2, + 71, + 68, + 42, + 93, + 88, + 31, + 101, + 92, + 93, + 94, + 104, + 91, + 89, + 90, + 99, + 9, + 1741, + 102, + 103, + 105, + 125, + 128, + 129, + 124, + 25, + 126, + 127, + 138, + 184, + 145, + 145, + 156, + 157, + 158, + 137, + 205, + 165, + 171, + 166, + 162, + 176, + 175, + 187, + 177, + 189, + 170, + 164, + 188, + 178, + 169, + 156, + 163, + 186, + 137, + 137, + 186, + 178, + 150, + 140, + 139, + 193, + 190, + 211, + 161, + 218, + 210, + 211, + 212, + 221, + 209, + 208, + 216, + 144, + 1743, + 219, + 220, + 222, + 240, + 243, + 244, + 239, + 155, + 241, + 242, + 435, + 260, + 254, + 274, + 280, + 269, + 424, + 300, + 290, + 291, + 292, + 293, + 294, + 299, + 310, + 298, + 297, + 296, + 295, + 295, + 290, + 304, + 309, + 303, + 490, + 492, + 318, + 317, + 261, + 257, + 512, + 516, + 530, + 332, + 533, + 423, + 350, + 307, + 357, + 308, + 308, + 365, + 349, + 347, + 358, + 359, + 360, + 364, + 353, + 352, + 361, + 365, + 357, + 351, + 350, + 355, + 356, + 362, + 366, + 354, + 363, + 393, + 394, + 282, + 337, + 281, + 289, + 391, + 334, + 390, + 286, + 332, + 266, + 394, + 395, + 307, + 303, + 440, + 451, + 453, + 427, + 431, + 432, + 434, + 433, + 435, + 435, + 429, + 41, + 47, + 436, + 40, + 45, + 45, + 46, + 436, + 452, + 453, + 446, + 437, + 460, + 461, + 264, + 327, + 329, + 525, + 278, + 268, + 322, + 547, + 546, + 428, + 562, + 733, + 557, + 575, + 581, + 570, + 724, + 601, + 591, + 592, + 593, + 594, + 595, + 600, + 611, + 599, + 598, + 597, + 596, + 596, + 591, + 605, + 610, + 604, + 780, + 619, + 782, + 618, + 563, + 802, + 806, + 820, + 633, + 823, + 723, + 651, + 608, + 609, + 609, + 666, + 650, + 648, + 659, + 660, + 661, + 665, + 654, + 653, + 662, + 666, + 658, + 652, + 651, + 656, + 657, + 663, + 667, + 655, + 664, + 694, + 695, + 583, + 638, + 582, + 590, + 692, + 635, + 691, + 587, + 633, + 567, + 695, + 696, + 608, + 604, + 658, + 745, + 738, + 747, + 727, + 729, + 730, + 732, + 731, + 733, + 733, + 728, + 168, + 734, + 167, + 171, + 171, + 746, + 734, + 747, + 735, + 628, + 630, + 815, + 579, + 569, + 623, + 837, + 836, + 207, + 198, + 856, + 854, + 194, + 198, + 860, + 893, + 862, + 897, + 863, + 883, + 879, + 858, + 857, + 853, + 860, + 861, + 887, + 859, + 888, + 889, + 857, + 870, + 861, + 873, + 888, + 886, + 884, + 910, + 882, + 881, + 915, + 879, + 883, + 880, + 879, + 912, + 924, + 938, + 909, + 883, + 885, + 945, + 200, + 197, + 201, + 910, + 911, + 910, + 914, + 947, + 915, + 915, + 1281, + 951, + 951, + 1282, + 951, + 954, + 952, + 955, + 954, + 965, + 990, + 989, + 988, + 968, + 995, + 993, + 1000, + 993, + 997, + 1002, + 998, + 1005, + 1003, + 962, + 1018, + 985, + 1015, + 970, + 1024, + 1021, + 1030, + 1027, + 1036, + 1033, + 1042, + 1039, + 1048, + 1045, + 1054, + 1051, + 1060, + 1057, + 1066, + 1063, + 1072, + 1069, + 1076, + 1075, + 1080, + 1077, + 969, + 1086, + 1083, + 1092, + 1089, + 1098, + 1095, + 1104, + 1101, + 1110, + 1107, + 1116, + 1113, + 1122, + 1119, + 1128, + 1125, + 1134, + 1131, + 1138, + 1137, + 1142, + 1139, + 972, + 1148, + 1145, + 1154, + 1151, + 1160, + 1157, + 1166, + 1163, + 1172, + 1169, + 1178, + 1175, + 1184, + 1181, + 1190, + 1187, + 1196, + 1193, + 1200, + 1199, + 1204, + 1201, + 1210, + 1207, + 1216, + 1213, + 1222, + 1219, + 1228, + 1225, + 1234, + 1231, + 1240, + 1237, + 1246, + 1243, + 1250, + 1252, + 1249, + 1258, + 1255, + 1262, + 1261, + 1268, + 950, + 953, + 954, + 1280, + 955, + 1288, + 196, + 195, + 195, + 76, + 1299, + 1301, + 77, + 72, + 1305, + 1338, + 1307, + 1308, + 1342, + 1328, + 1324, + 1303, + 1302, + 1298, + 1305, + 1306, + 1332, + 1304, + 1333, + 1334, + 1315, + 1302, + 1318, + 1306, + 1333, + 1331, + 1329, + 1355, + 1327, + 1326, + 1324, + 1363, + 1327, + 1328, + 1325, + 1382, + 1360, + 1369, + 1354, + 1328, + 1330, + 1390, + 78, + 75, + 79, + 1355, + 1356, + 1355, + 1359, + 1392, + 1360, + 1360, + 1396, + 1726, + 1397, + 1396, + 1396, + 1399, + 1400, + 1399, + 1410, + 1435, + 1434, + 1433, + 1413, + 1440, + 1438, + 1445, + 1443, + 1450, + 1448, + 1407, + 1415, + 1461, + 1430, + 1463, + 1460, + 1469, + 1466, + 1475, + 1472, + 1481, + 1478, + 1487, + 1484, + 1493, + 1490, + 1499, + 1496, + 1505, + 1502, + 1511, + 1508, + 1517, + 1514, + 1521, + 1520, + 1525, + 1522, + 1414, + 1531, + 1528, + 1537, + 1534, + 1543, + 1540, + 1549, + 1546, + 1555, + 1552, + 1561, + 1558, + 1567, + 1564, + 1573, + 1570, + 1579, + 1576, + 1583, + 1582, + 1587, + 1584, + 1417, + 1593, + 1590, + 1599, + 1596, + 1605, + 1602, + 1611, + 1608, + 1617, + 1614, + 1623, + 1620, + 1629, + 1626, + 1635, + 1632, + 1641, + 1638, + 1645, + 1644, + 1649, + 1646, + 1655, + 1652, + 1661, + 1658, + 1667, + 1664, + 1673, + 1670, + 1679, + 1676, + 1685, + 1682, + 1691, + 1688, + 1697, + 1694, + 1703, + 1700, + 1707, + 1706, + 1713, + 1395, + 1398, + 1725, + 1399, + 1733, + 74, + 73, + 73, + 1285, + 199, + 76, + 1730, + 1739, + 9, + 1740, + 10, + 144, + 1757, + 1758, + 1757, + 1759, + 1758, + 1757, + 1757, + 1759, + 1759, + 1765, + 1779, + 1769, + 1767, + 1778, + 1756, + 1746, + 1772, + 1752, + 1771, + 1770, + 1763, + 1777, + 1773, + 1766, + 1775, + 1776, + 1766, + 1777, + 1768, + 1767, + 1779, + 1764, + 1758, + 2146, + 1764, + 1784, + 1757, + 1764, + 1785, + 1765, + 1750, + 1759, + 1759, + 1750, + 1782, + 1761, + 1756, + 1748, + 1784, + 1764, + 1761, + 1753, + 1804, + 1784, + 1804, + 1781, + 1751, + 1880, + 1751, + 1784, + 1761, + 1783, + 1788, + 1786, + 1788, + 1789, + 1761, + 1774, + 1756, + 1818, + 1766, + 1751, + 1747, + 1757, + 1753, + 1748, + 1758, + 1758, + 1764, + 1759, + 1756, + 1761, + 1764, + 1751, + 1786, + 1765, + 1785, + 1813, + 1751, + 1888, + 1748, + 1889, + 1888, + 1890, + 1889, + 1888, + 1888, + 1747, + 1890, + 1750, + 1890, + 1896, + 1910, + 1898, + 1900, + 1899, + 1887, + 1903, + 1902, + 1894, + 1901, + 1908, + 1897, + 1906, + 1904, + 1909, + 1898, + 1910, + 1895, + 1889, + 1895, + 1915, + 1888, + 1895, + 1916, + 1896, + 1750, + 1890, + 1890, + 1754, + 1750, + 1913, + 1892, + 2801, + 1887, + 1748, + 1915, + 1753, + 1895, + 1892, + 1753, + 1935, + 2011, + 1915, + 1892, + 1914, + 1919, + 1917, + 1919, + 1920, + 1892, + 1887, + 1905, + 1949, + 1897, + 1751, + 1747, + 1888, + 1753, + 1748, + 1889, + 1889, + 1895, + 1890, + 1887, + 1998, + 1999, + 1892, + 1895, + 1751, + 1917, + 1896, + 1916, + 1944, + 1916, + 1917, + 2094, + 3050, + 2095, + 3069, + 2406, + 2096, + 2394, + 2097, + 2093, + 2098, + 1788, + 1754, + 1919, + 141, + 86, + 5, + 2109, + 2399, + 3056, + 2110, + 2115, + 2398, + 2208, + 2116, + 2140, + 2124, + 2122, + 2395, + 1755, + 2707, + 2132, + 2131, + 2203, + 2386, + 2141, + 2704, + 1780, + 1761, + 2486, + 2151, + 2154, + 2499, + 2153, + 2152, + 2211, + 2309, + 2495, + 2316, + 2483, + 2310, + 1789, + 1782, + 1783, + 1785, + 1785, + 1786, + 2405, + 2426, + 2409, + 2414, + 1787, + 2426, + 2410, + 2426, + 88, + 2502, + 2484, + 2493, + 2487, + 2494, + 2497, + 2504, + 2498, + 2503, + 2772, + 2864, + 2773, + 3057, + 3049, + 2776, + 2780, + 2796, + 1886, + 2781, + 2857, + 2788, + 3366, + 3044, + 3364, + 2802, + 1897, + 1908, + 1915, + 1892, + 1911, + 3155, + 2810, + 2813, + 3147, + 2811, + 2812, + 2861, + 2966, + 3154, + 2967, + 3142, + 1920, + 1913, + 1912, + 1935, + 1914, + 1916, + 1916, + 1917, + 3086, + 3065, + 3086, + 3072, + 3066, + 1918, + 3065, + 207, + 3141, + 3165, + 3146, + 3150, + 3149, + 3163, + 3157, + 3156, + 3164, + 206, + 87, + 1907, + 3418, + 3419; + } + + MeshMaterialList { + 1; + 6841; + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0; + + Material { + 1.000000;1.000000;1.000000;1.000000;; + 0.000000; + 1.000000;1.000000;1.000000;; + 0.000000;0.000000;0.000000;; + + TextureFilename { + "Tiny_skin.dds"; + } + } + } + + XSkinMeshHeader { + 2; + 4; + 35; + } + + SkinWeights { + "Bip01_R_UpperArm"; + 156; + 0, + 3449, + 3429, + 3427, + 2, + 3454, + 4, + 3453, + 7, + 15, + 68, + 3456, + 69, + 70, + 71, + 3455, + 72, + 3940, + 73, + 4110, + 4109, + 74, + 4108, + 75, + 3980, + 76, + 4113, + 3936, + 77, + 3939, + 78, + 3979, + 79, + 3981, + 1294, + 1295, + 1296, + 1297, + 1298, + 3950, + 1299, + 3937, + 1300, + 1301, + 3938, + 1302, + 3958, + 3949, + 1303, + 3948, + 1304, + 3954, + 1305, + 3951, + 3941, + 1306, + 3960, + 3952, + 1307, + 3943, + 1308, + 3944, + 1309, + 1310, + 1311, + 1312, + 1313, + 1314, + 1315, + 3957, + 1316, + 1317, + 1318, + 3959, + 1319, + 1320, + 1321, + 1322, + 1323, + 1324, + 3967, + 3947, + 1325, + 3971, + 1326, + 3966, + 1327, + 3969, + 3965, + 1328, + 3976, + 3970, + 3946, + 1329, + 3963, + 1330, + 3977, + 1331, + 3962, + 1332, + 3953, + 1333, + 3961, + 3955, + 1334, + 3956, + 1335, + 1336, + 1337, + 1338, + 3942, + 1339, + 1340, + 1341, + 1342, + 3945, + 1343, + 1344, + 1345, + 1346, + 1347, + 1348, + 1349, + 1350, + 1351, + 1352, + 1353, + 1354, + 3975, + 1357, + 1358, + 1362, + 1364, + 1365, + 1366, + 1367, + 1384, + 1385, + 1386, + 1387, + 1388, + 1389, + 1390, + 3978, + 1391, + 1730, + 4114, + 1731, + 1732, + 1733, + 4107, + 1734, + 1735, + 1736, + 1737, + 1738; + 0.605239, + 0.605239, + 0.605239, + 0.605239, + 0.208568, + 0.208568, + 0.332183, + 0.332183, + 0.490972, + 0.001349, + 0.378335, + 0.378335, + 0.505176, + 0.547675, + 0.378478, + 0.378478, + 0.520681, + 0.520681, + 0.514052, + 0.514052, + 0.514052, + 0.489167, + 0.489167, + 0.500779, + 0.500779, + 0.344750, + 0.344750, + 0.344750, + 0.444251, + 0.444251, + 0.422197, + 0.422197, + 0.459563, + 0.459563, + 1.000000, + 1.000000, + 0.523285, + 0.702523, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.754566, + 0.754566, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999998, + 0.999998, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.937900, + 0.937900, + 0.843455, + 0.843455, + 1.000000, + 1.000000, + 0.692347, + 0.536598, + 0.635737, + 0.793743, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.562271, + 1.000000, + 0.606859, + 0.525610, + 0.525610, + 0.525610, + 0.505657, + 0.505657, + 0.499507, + 0.499507, + 0.502042, + 0.502042, + 0.502042, + 0.512201, + 0.512201, + 0.512201, + 0.512201, + 0.500000, + 0.500000, + 0.564140, + 0.564140, + 0.499982, + 0.499982, + 0.999997, + 0.999997, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.995135, + 0.936519, + 1.000000, + 0.999529, + 0.980016, + 0.999871, + 0.999950, + 1.000000, + 0.951632, + 0.002571, + 0.000138, + 0.003704, + 0.003704, + 0.000096, + 0.000000, + 0.000217, + 0.000002, + 0.000020, + 0.000376, + 0.001713, + 0.017345, + 0.266756, + 0.080934, + 0.226163, + 0.796931, + 1.000000, + 1.000000, + 1.000000, + 0.171247, + 0.501141, + 0.501141, + 0.569803, + 0.914754, + 0.873090, + 0.873090, + 1.000000, + 1.000000, + 0.999889, + 0.999994, + 0.979129; + -0.941743,-0.646748,0.574719,0.000000,-0.283133,-0.461979,-0.983825,0.000000,0.923060,-1.114919,0.257891,0.000000,-65.499557,30.497688,12.852692,1.000000;; + } + + SkinWeights { + "Bip01_Spine3"; + 299; + 0, + 3449, + 3429, + 3427, + 1, + 3420, + 2, + 3454, + 3, + 4, + 3453, + 5, + 4311, + 6, + 7, + 8, + 9, + 4116, + 3470, + 10, + 4118, + 12, + 13, + 15, + 16, + 3424, + 17, + 18, + 19, + 20, + 3452, + 21, + 22, + 30, + 31, + 3460, + 42, + 3457, + 43, + 3445, + 58, + 62, + 3421, + 68, + 3456, + 69, + 70, + 71, + 3455, + 72, + 3940, + 73, + 4110, + 4109, + 74, + 4108, + 75, + 3980, + 76, + 4113, + 3936, + 77, + 3939, + 78, + 3979, + 79, + 3981, + 85, + 86, + 4310, + 87, + 4428, + 88, + 4360, + 3459, + 89, + 3467, + 90, + 3468, + 91, + 3466, + 92, + 3462, + 93, + 3463, + 3458, + 94, + 3464, + 95, + 96, + 97, + 98, + 99, + 3469, + 100, + 101, + 3461, + 102, + 3472, + 103, + 3473, + 104, + 3465, + 105, + 3474, + 107, + 108, + 109, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 137, + 3509, + 3508, + 3489, + 138, + 3482, + 139, + 3514, + 140, + 3513, + 141, + 4309, + 142, + 143, + 144, + 4119, + 3527, + 146, + 147, + 148, + 149, + 150, + 3512, + 151, + 152, + 160, + 161, + 3518, + 169, + 3504, + 184, + 3483, + 190, + 3516, + 191, + 192, + 193, + 3515, + 194, + 3759, + 195, + 3935, + 3934, + 196, + 3933, + 197, + 3800, + 198, + 3760, + 3756, + 199, + 4112, + 200, + 3799, + 201, + 3801, + 206, + 4427, + 207, + 4417, + 3755, + 208, + 3525, + 209, + 3524, + 210, + 3520, + 211, + 3521, + 3517, + 212, + 3522, + 213, + 214, + 215, + 216, + 3526, + 217, + 218, + 3519, + 219, + 3529, + 220, + 3530, + 221, + 3523, + 222, + 3531, + 224, + 225, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 845, + 846, + 851, + 852, + 856, + 3757, + 943, + 946, + 1285, + 4111, + 1286, + 1287, + 1288, + 3932, + 1291, + 1293, + 1296, + 1297, + 1301, + 3938, + 1388, + 1391, + 1730, + 4114, + 1731, + 1732, + 1733, + 4107, + 1736, + 1738, + 1739, + 4115, + 1740, + 4117, + 1741, + 3471, + 1742, + 1743, + 3528, + 1744, + 1745, + 2101, + 2102, + 2103, + 2104, + 2105, + 2108, + 2109, + 4312, + 2110, + 4315, + 2111, + 2112, + 2392, + 2397, + 2398, + 4317, + 2399, + 4313, + 2400, + 2401, + 2416, + 2422, + 2423, + 3052, + 3055, + 3056, + 4314, + 3057, + 4373, + 3058, + 3059, + 3071, + 3076, + 3080, + 3081; + 0.394761, + 0.394761, + 0.394761, + 0.394761, + 1.000000, + 1.000000, + 0.791431, + 0.791431, + 0.934090, + 0.667817, + 0.667817, + 0.407500, + 0.407500, + 1.000000, + 0.509028, + 0.500334, + 0.742859, + 0.742859, + 0.742859, + 0.646150, + 0.646150, + 0.000826, + 1.000000, + 0.998651, + 1.000000, + 1.000000, + 0.002232, + 0.000057, + 0.000008, + 0.694294, + 0.694294, + 0.500000, + 0.500000, + 0.005182, + 1.000000, + 1.000000, + 0.000077, + 0.000077, + 0.000000, + 0.000000, + 0.000000, + 0.999987, + 0.999987, + 0.621665, + 0.621665, + 0.494824, + 0.452325, + 0.621522, + 0.621522, + 0.479319, + 0.479319, + 0.485948, + 0.485948, + 0.485948, + 0.510833, + 0.510833, + 0.499221, + 0.499221, + 0.655250, + 0.655250, + 0.655250, + 0.555749, + 0.555749, + 0.577803, + 0.577803, + 0.540437, + 0.540437, + 0.500000, + 0.518319, + 0.518319, + 0.330664, + 0.330664, + 0.499933, + 0.499933, + 0.499933, + 0.506729, + 0.506729, + 0.491771, + 0.491771, + 0.496988, + 0.496988, + 0.458505, + 0.458505, + 0.478085, + 0.478085, + 0.478085, + 0.509104, + 0.509104, + 0.500228, + 0.500000, + 0.500234, + 0.500000, + 0.500000, + 0.500000, + 0.098269, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.764280, + 1.000000, + 0.273957, + 0.495039, + 0.559469, + 0.432520, + 0.464423, + 0.334571, + 0.396879, + 0.503634, + 0.500003, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.388147, + 0.388147, + 0.388147, + 0.388147, + 1.000000, + 1.000000, + 0.792207, + 0.792207, + 0.667938, + 0.667938, + 0.401391, + 0.401391, + 1.000000, + 0.507531, + 0.789169, + 0.789169, + 0.789169, + 1.000000, + 0.998645, + 0.000055, + 0.000007, + 0.696843, + 0.696843, + 0.500000, + 0.500000, + 0.004977, + 1.000000, + 1.000000, + 0.000000, + 0.000000, + 0.999989, + 0.999989, + 0.622978, + 0.622978, + 0.494410, + 0.451237, + 0.619803, + 0.619803, + 0.471398, + 0.471398, + 0.488642, + 0.488642, + 0.488642, + 0.508940, + 0.508940, + 0.499498, + 0.499498, + 0.650302, + 0.650302, + 0.650302, + 0.577673, + 0.577673, + 0.575168, + 0.575168, + 0.540492, + 0.540492, + 0.329189, + 0.329189, + 0.499882, + 0.499882, + 0.499882, + 0.491653, + 0.491653, + 0.496898, + 0.496898, + 0.457891, + 0.457891, + 0.477594, + 0.477594, + 0.477594, + 0.510518, + 0.510518, + 0.500267, + 0.500000, + 0.500219, + 0.500000, + 0.500000, + 0.097802, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.770983, + 1.000000, + 0.494890, + 0.432088, + 0.463982, + 0.333385, + 0.395719, + 0.504955, + 0.500005, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.500000, + 0.500000, + 0.477163, + 0.297364, + 0.247515, + 0.247515, + 0.204713, + 0.827083, + 0.498934, + 0.498934, + 0.430994, + 0.086300, + 0.128177, + 0.128177, + 0.000124, + 0.021432, + 0.476715, + 0.297477, + 0.245434, + 0.245434, + 0.203069, + 0.828753, + 0.498859, + 0.498859, + 0.430197, + 0.085246, + 0.126910, + 0.126910, + 0.000111, + 0.020871, + 0.652828, + 0.652828, + 0.678677, + 0.678677, + 0.750800, + 0.750800, + 0.670469, + 0.786977, + 0.786977, + 0.692151, + 0.719323, + 0.510218, + 0.490223, + 0.490260, + 0.509821, + 0.001010, + 0.001002, + 0.000093, + 0.000093, + 0.000094, + 0.000094, + 0.000638, + 0.000637, + 0.000001, + 0.000017, + 0.000001, + 0.000001, + 0.000058, + 0.000058, + 0.000607, + 0.000268, + 0.002483, + 0.503803, + 0.525515, + 0.000001, + 0.000612, + 0.000059, + 0.000059, + 0.000001, + 0.000001, + 0.000018, + 0.000271, + 0.420472, + 0.002513, + 0.523967, + 0.503150; + -0.000000,-0.000002,1.278853,0.000000,1.100796,0.223046,0.000001,0.000000,-0.291970,1.440953,0.000002,0.000000,28.876726,-65.051079,-0.142296,1.000000;; + } + + SkinWeights { + "Bip01_Neck"; + 214; + 3, + 5, + 4311, + 8, + 9, + 4116, + 3470, + 10, + 4118, + 21, + 22, + 85, + 86, + 4310, + 87, + 4428, + 88, + 4360, + 3459, + 89, + 3467, + 90, + 3468, + 91, + 3466, + 92, + 3462, + 93, + 3463, + 3458, + 94, + 3464, + 95, + 96, + 97, + 98, + 99, + 3469, + 106, + 107, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 123, + 141, + 4309, + 144, + 4119, + 3527, + 151, + 152, + 206, + 4427, + 207, + 4417, + 3755, + 208, + 3525, + 209, + 3524, + 210, + 3520, + 211, + 3521, + 3517, + 212, + 3522, + 213, + 214, + 215, + 216, + 3526, + 223, + 224, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 238, + 845, + 846, + 1739, + 4115, + 1740, + 4117, + 1741, + 3471, + 1742, + 1743, + 3528, + 1744, + 1745, + 1754, + 4307, + 4249, + 1786, + 4351, + 4204, + 4183, + 1787, + 4356, + 1917, + 4409, + 4295, + 4290, + 4267, + 1918, + 4415, + 2091, + 2092, + 2093, + 4304, + 2094, + 4296, + 2095, + 4298, + 2096, + 4301, + 2097, + 4303, + 2098, + 4305, + 2099, + 2100, + 2101, + 2102, + 2103, + 2104, + 2105, + 2106, + 2107, + 2108, + 2393, + 2394, + 4302, + 2395, + 4323, + 2402, + 2403, + 2404, + 2405, + 4352, + 2406, + 4300, + 2407, + 2408, + 2409, + 4354, + 2410, + 4358, + 2411, + 2412, + 2413, + 2414, + 4355, + 2415, + 2416, + 2417, + 2418, + 2419, + 2420, + 2421, + 2422, + 2423, + 2426, + 4359, + 4357, + 4353, + 3049, + 4374, + 3050, + 4297, + 3051, + 3060, + 3061, + 3062, + 3063, + 3064, + 3065, + 4416, + 4411, + 3066, + 4414, + 3067, + 3068, + 3069, + 4299, + 3070, + 3071, + 3072, + 4413, + 3073, + 3074, + 3075, + 3076, + 3077, + 3078, + 3079, + 3080, + 3081, + 3086, + 4412, + 4410; + 0.065910, + 0.592500, + 0.592500, + 0.499666, + 0.257141, + 0.257141, + 0.257141, + 0.353850, + 0.353850, + 0.500000, + 0.500000, + 0.500000, + 0.481681, + 0.481681, + 0.669336, + 0.669336, + 0.500067, + 0.500067, + 0.500067, + 0.493271, + 0.493271, + 0.508229, + 0.508229, + 0.503012, + 0.503012, + 0.541495, + 0.541495, + 0.521915, + 0.521915, + 0.521915, + 0.490896, + 0.490896, + 0.499772, + 0.500000, + 0.499766, + 0.500000, + 0.500000, + 0.500000, + 1.000000, + 0.235720, + 0.726043, + 1.000000, + 0.504961, + 0.440531, + 0.567480, + 0.535577, + 0.665429, + 0.603121, + 0.496366, + 0.499997, + 0.000000, + 0.598609, + 0.598609, + 0.210831, + 0.210831, + 0.210831, + 0.500000, + 0.500000, + 0.670811, + 0.670811, + 0.500118, + 0.500118, + 0.500118, + 0.508347, + 0.508347, + 0.503102, + 0.503102, + 0.542109, + 0.542109, + 0.522406, + 0.522406, + 0.522406, + 0.489482, + 0.489482, + 0.499733, + 0.500000, + 0.499781, + 0.500000, + 0.500000, + 1.000000, + 0.229017, + 1.000000, + 0.505110, + 0.567912, + 0.536018, + 0.666615, + 0.604281, + 0.495045, + 0.499995, + 0.000000, + 0.500000, + 0.500000, + 0.347172, + 0.347172, + 0.321323, + 0.321323, + 0.249200, + 0.249200, + 0.329531, + 0.213023, + 0.213023, + 0.307849, + 0.280677, + 0.029899, + 0.029899, + 0.029899, + 0.000563, + 0.000563, + 0.000563, + 0.000563, + 0.447159, + 0.447159, + 0.000741, + 0.000741, + 0.000741, + 0.000741, + 0.000741, + 0.452299, + 0.452299, + 0.000256, + 0.000265, + 0.112240, + 0.112240, + 0.502882, + 0.502882, + 0.660151, + 0.660151, + 0.660342, + 0.660342, + 0.501958, + 0.501958, + 0.110146, + 0.110146, + 0.306701, + 0.307363, + 0.489782, + 0.509777, + 0.509740, + 0.490179, + 0.998990, + 0.966439, + 0.966459, + 0.998998, + 0.006305, + 0.286696, + 0.286696, + 0.102187, + 0.102187, + 0.432449, + 0.484491, + 0.144315, + 0.014990, + 0.014990, + 0.501776, + 0.501776, + 0.689126, + 0.616328, + 0.498337, + 0.498337, + 0.292995, + 0.292995, + 0.319511, + 0.489703, + 1.000000, + 0.970473, + 0.970473, + 1.000000, + 0.997517, + 0.986590, + 1.000000, + 0.043051, + 0.348847, + 0.069256, + 0.496197, + 0.474485, + 0.000614, + 0.000614, + 0.000614, + 0.000614, + 0.111179, + 0.111179, + 0.295001, + 0.295001, + 0.007394, + 0.437806, + 0.017223, + 0.151879, + 0.486630, + 0.330150, + 0.303562, + 0.303562, + 0.303562, + 0.498825, + 0.498825, + 0.615047, + 0.687810, + 0.501685, + 0.501685, + 0.491269, + 0.579528, + 0.970098, + 0.970098, + 1.000000, + 1.000000, + 0.986508, + 0.997487, + 0.046055, + 0.071046, + 0.352668, + 0.476033, + 0.496850, + 0.000875, + 0.000875, + 0.000875; + 0.000001,-0.000002,1.278853,0.000000,1.061682,-0.366513,-0.000001,0.000000,0.479769,1.389753,0.000002,0.000000,-44.801331,-49.085537,-0.142252,1.000000;; + } + + SkinWeights { + "Bip01_Spine2"; + 138; + 11, + 3423, + 3422, + 12, + 14, + 17, + 18, + 19, + 23, + 24, + 25, + 3479, + 26, + 3446, + 3425, + 27, + 3426, + 28, + 3428, + 29, + 30, + 38, + 39, + 3433, + 42, + 3457, + 43, + 3445, + 44, + 3441, + 48, + 49, + 51, + 3435, + 52, + 3436, + 53, + 3438, + 54, + 3451, + 3443, + 58, + 59, + 60, + 61, + 62, + 3421, + 63, + 66, + 3442, + 67, + 3439, + 80, + 81, + 82, + 83, + 100, + 125, + 3475, + 126, + 3480, + 127, + 3481, + 128, + 3476, + 130, + 132, + 133, + 134, + 135, + 145, + 3485, + 3484, + 148, + 149, + 153, + 154, + 155, + 3536, + 156, + 3505, + 3486, + 157, + 3487, + 158, + 3488, + 159, + 160, + 166, + 3493, + 169, + 3504, + 170, + 3500, + 172, + 173, + 175, + 3496, + 176, + 3495, + 177, + 3498, + 178, + 3511, + 3503, + 181, + 182, + 183, + 184, + 3483, + 185, + 188, + 3502, + 189, + 3499, + 202, + 203, + 204, + 217, + 240, + 3532, + 241, + 3537, + 242, + 3538, + 243, + 3533, + 245, + 247, + 248, + 249, + 250, + 1292, + 1737, + 3418, + 4430, + 3419, + 4431; + 1.000000, + 1.000000, + 1.000000, + 0.999173, + 0.999963, + 0.997768, + 0.999943, + 0.999992, + 1.000000, + 0.999958, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.994818, + 0.119980, + 0.012547, + 0.012547, + 0.999923, + 0.999923, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.026286, + 0.000075, + 0.992608, + 0.992608, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.000013, + 0.000013, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.025573, + 0.009055, + 0.013395, + 0.009298, + 0.901731, + 0.682231, + 0.682231, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.001628, + 0.001628, + 1.000000, + 0.574870, + 1.000000, + 1.000000, + 0.000066, + 1.000000, + 1.000000, + 1.000000, + 0.999945, + 0.999993, + 1.000000, + 0.999959, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.995023, + 0.012193, + 0.012193, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.025939, + 0.000070, + 0.992952, + 0.992952, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.000011, + 0.000011, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.009004, + 0.013264, + 0.009112, + 0.902198, + 0.683732, + 0.683732, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.001536, + 0.001536, + 1.000000, + 0.575759, + 1.000000, + 1.000000, + 0.000058, + 0.000008, + 0.000006, + 1.000000, + 1.000000, + 1.000000, + 1.000000; + -0.000000,-0.000002,1.278853,0.000000,1.106257,0.194155,0.000001,0.000000,-0.254150,1.448102,0.000002,0.000000,55.345093,-65.818558,-0.142298,1.000000;; + } + + SkinWeights { + "Bip01_Spine1"; + 135; + 14, + 24, + 32, + 3434, + 33, + 3447, + 34, + 3444, + 35, + 3440, + 36, + 3430, + 37, + 38, + 39, + 3433, + 40, + 3630, + 41, + 3627, + 45, + 3632, + 3631, + 3432, + 46, + 3633, + 47, + 3628, + 48, + 49, + 50, + 51, + 3435, + 55, + 56, + 57, + 64, + 3450, + 3448, + 65, + 3437, + 80, + 81, + 82, + 83, + 84, + 3431, + 124, + 3478, + 125, + 3475, + 128, + 3476, + 129, + 3477, + 131, + 132, + 135, + 136, + 154, + 162, + 3494, + 163, + 3506, + 164, + 3501, + 165, + 3491, + 166, + 3493, + 167, + 3740, + 168, + 3738, + 171, + 3742, + 3741, + 3492, + 172, + 173, + 174, + 175, + 3496, + 179, + 180, + 186, + 3510, + 3507, + 187, + 3497, + 202, + 203, + 204, + 205, + 3490, + 239, + 3535, + 240, + 3532, + 243, + 3533, + 244, + 3534, + 246, + 247, + 250, + 251, + 428, + 3650, + 436, + 3634, + 3629, + 438, + 439, + 440, + 3616, + 441, + 442, + 444, + 452, + 3635, + 454, + 456, + 734, + 3744, + 3739, + 736, + 737, + 738, + 3728, + 746, + 3743, + 748, + 847, + 848; + 0.000037, + 0.000042, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999541, + 0.880020, + 0.987453, + 0.987453, + 0.355829, + 0.355829, + 0.539595, + 0.539595, + 0.478610, + 0.478610, + 0.478610, + 0.478610, + 0.193697, + 0.193697, + 0.504065, + 0.504065, + 0.973714, + 0.999925, + 1.000000, + 0.007392, + 0.007392, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.974427, + 0.990945, + 0.986605, + 0.990703, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.317769, + 0.317769, + 0.998372, + 0.998372, + 1.000000, + 1.000000, + 1.000000, + 0.425130, + 0.999934, + 1.000000, + 0.000041, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.987807, + 0.987807, + 0.355636, + 0.355636, + 0.539137, + 0.539137, + 0.495096, + 0.495096, + 0.495096, + 0.495096, + 0.974061, + 0.999930, + 1.000000, + 0.007048, + 0.007048, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.990996, + 0.986736, + 0.990888, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.316268, + 0.316268, + 0.998464, + 0.998464, + 1.000000, + 1.000000, + 1.000000, + 0.424241, + 0.999942, + 1.000000, + 0.137283, + 0.137283, + 0.274429, + 0.274429, + 0.274429, + 0.292184, + 0.556285, + 0.480198, + 0.480198, + 0.108993, + 0.506586, + 0.129106, + 0.205417, + 0.205417, + 0.087526, + 0.173935, + 0.274599, + 0.274599, + 0.274599, + 0.292740, + 0.555983, + 0.480227, + 0.480227, + 0.205575, + 0.205575, + 0.174090, + 0.999988, + 0.999991; + -0.000000,-0.000002,1.278853,0.000000,1.106257,0.194155,0.000001,0.000000,-0.254150,1.448102,0.000002,0.000000,83.527077,-65.841003,-0.142298,1.000000;; + } + + SkinWeights { + "Bip01_R_Clavicle"; + 2; + 20, + 3452; + 0.305706, + 0.305706; + -1.253361,-0.000002,0.254069,0.000000,-0.218659,-0.223923,-1.078679,0.000000,0.058235,-1.440720,0.287274,0.000000,-7.853105,62.204407,2.554618,1.000000;; + } + + SkinWeights { + "Bip01_Spine"; + 196; + 37, + 40, + 3630, + 41, + 3627, + 45, + 3632, + 3631, + 3432, + 46, + 3633, + 47, + 3628, + 167, + 3740, + 168, + 3738, + 171, + 3742, + 3741, + 3492, + 252, + 253, + 256, + 257, + 3568, + 258, + 259, + 260, + 3540, + 263, + 264, + 3641, + 281, + 3604, + 289, + 3605, + 397, + 400, + 408, + 417, + 421, + 427, + 3619, + 428, + 3650, + 429, + 3626, + 430, + 431, + 3620, + 432, + 3621, + 433, + 3623, + 434, + 3622, + 435, + 3625, + 3624, + 3539, + 436, + 3634, + 3629, + 437, + 3638, + 438, + 439, + 440, + 3616, + 441, + 442, + 443, + 444, + 445, + 446, + 3637, + 447, + 448, + 449, + 450, + 451, + 3617, + 452, + 3635, + 453, + 3636, + 3618, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 3639, + 461, + 3640, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 473, + 474, + 481, + 482, + 483, + 484, + 548, + 551, + 554, + 555, + 556, + 559, + 560, + 561, + 562, + 3651, + 565, + 582, + 3714, + 590, + 3715, + 698, + 701, + 709, + 718, + 727, + 3730, + 728, + 3737, + 729, + 3731, + 730, + 3732, + 731, + 3734, + 732, + 3733, + 733, + 3736, + 3735, + 3652, + 734, + 3744, + 3739, + 735, + 3746, + 736, + 737, + 738, + 3728, + 739, + 740, + 741, + 742, + 743, + 744, + 745, + 3727, + 746, + 3743, + 747, + 3745, + 3729, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 763, + 764, + 771, + 772, + 773, + 774, + 838, + 841, + 844, + 847, + 848; + 0.000459, + 0.644171, + 0.644171, + 0.460405, + 0.460405, + 0.521390, + 0.521390, + 0.521390, + 0.521390, + 0.806303, + 0.806303, + 0.495935, + 0.495935, + 0.644364, + 0.644364, + 0.460863, + 0.460863, + 0.504904, + 0.504904, + 0.504904, + 0.504904, + 0.490317, + 1.000000, + 0.500000, + 1.000000, + 1.000000, + 1.000000, + 0.452523, + 1.000000, + 1.000000, + 1.000000, + 0.500000, + 0.500000, + 0.491192, + 0.491192, + 0.000010, + 0.000010, + 0.480348, + 0.000000, + 0.000731, + 0.000216, + 0.500000, + 1.000000, + 1.000000, + 0.862717, + 0.862717, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.725571, + 0.725571, + 0.725571, + 1.000000, + 1.000000, + 0.707816, + 0.443715, + 0.519802, + 0.519802, + 0.891007, + 0.493414, + 1.000000, + 0.870894, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.794583, + 0.794583, + 1.000000, + 1.000000, + 1.000000, + 0.912474, + 1.000000, + 0.826065, + 1.000000, + 1.000000, + 0.500000, + 1.000000, + 1.000000, + 0.500000, + 0.500000, + 1.000000, + 0.500000, + 1.000000, + 0.714864, + 0.500015, + 0.495456, + 0.537862, + 1.000000, + 0.362112, + 0.003282, + 1.000000, + 0.335473, + 1.000000, + 1.000000, + 0.500000, + 1.000000, + 0.061459, + 0.406936, + 0.725066, + 1.000000, + 1.000000, + 0.500000, + 1.000000, + 0.452941, + 1.000000, + 1.000000, + 1.000000, + 0.491389, + 0.491389, + 0.000010, + 0.000010, + 0.480816, + 0.000000, + 0.000763, + 0.000228, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.725401, + 0.725401, + 0.725401, + 1.000000, + 1.000000, + 0.707260, + 0.444017, + 0.519773, + 0.519773, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.794425, + 0.794425, + 1.000000, + 1.000000, + 1.000000, + 0.825910, + 1.000000, + 1.000000, + 0.500000, + 1.000000, + 0.500000, + 1.000000, + 0.716189, + 0.500014, + 0.495465, + 0.537762, + 1.000000, + 0.370655, + 0.003429, + 1.000000, + 0.336846, + 1.000000, + 1.000000, + 0.500000, + 1.000000, + 0.062153, + 0.407168, + 1.000000, + 0.000012, + 0.000009; + 0.000000,-0.000002,1.278853,0.000000,1.123165,-0.000895,-0.000000,0.000000,0.001171,1.470235,0.000002,0.000000,99.003029,-79.367149,-0.142336,1.000000;; + } + + SkinWeights { + "Bip01_L_UpperArm"; + 157; + 137, + 3509, + 3508, + 3489, + 139, + 3514, + 140, + 3513, + 143, + 147, + 190, + 3516, + 191, + 192, + 193, + 3515, + 194, + 3759, + 195, + 3935, + 3934, + 196, + 3933, + 197, + 3800, + 198, + 3760, + 3756, + 199, + 4112, + 200, + 3799, + 201, + 3801, + 849, + 850, + 851, + 852, + 853, + 3770, + 854, + 3758, + 855, + 856, + 3757, + 857, + 3777, + 3769, + 858, + 3768, + 859, + 3774, + 860, + 3771, + 3761, + 861, + 3779, + 3772, + 862, + 3763, + 863, + 3765, + 864, + 865, + 866, + 867, + 868, + 869, + 870, + 3778, + 871, + 872, + 873, + 3780, + 874, + 875, + 876, + 877, + 878, + 879, + 3791, + 3788, + 3767, + 880, + 3790, + 881, + 3786, + 882, + 3785, + 883, + 3796, + 3789, + 3766, + 884, + 3783, + 885, + 3797, + 886, + 3782, + 887, + 3773, + 888, + 3781, + 3775, + 889, + 3776, + 890, + 891, + 892, + 893, + 3762, + 894, + 895, + 896, + 897, + 3764, + 898, + 899, + 900, + 901, + 902, + 903, + 904, + 905, + 906, + 907, + 908, + 909, + 3795, + 912, + 3792, + 913, + 917, + 919, + 920, + 921, + 922, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 3798, + 946, + 1285, + 4111, + 1286, + 1287, + 1288, + 3932, + 1289, + 1290, + 1291, + 1292, + 1293; + 0.611853, + 0.611853, + 0.611853, + 0.611853, + 0.207793, + 0.207793, + 0.332061, + 0.332061, + 0.492469, + 0.001355, + 0.377022, + 0.377022, + 0.505590, + 0.548763, + 0.380197, + 0.380197, + 0.528602, + 0.528602, + 0.511358, + 0.511358, + 0.511358, + 0.491060, + 0.491060, + 0.500502, + 0.500502, + 0.349698, + 0.349698, + 0.349698, + 0.422326, + 0.422326, + 0.424832, + 0.424832, + 0.459508, + 0.459508, + 1.000000, + 1.000000, + 0.522837, + 0.702636, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.752485, + 0.752485, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999998, + 0.999998, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.940238, + 0.940238, + 0.843017, + 0.843017, + 1.000000, + 1.000000, + 0.692400, + 0.538017, + 0.636978, + 0.792629, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.562516, + 1.000000, + 0.609501, + 0.526981, + 0.526981, + 0.526981, + 0.526981, + 0.506875, + 0.506875, + 0.499506, + 0.499506, + 0.502402, + 0.502402, + 0.512438, + 0.512438, + 0.512438, + 0.512438, + 0.500000, + 0.500000, + 0.564264, + 0.564264, + 0.499990, + 0.499990, + 0.999998, + 0.999998, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.995240, + 0.937903, + 1.000000, + 0.999588, + 0.981116, + 0.999872, + 0.999950, + 1.000000, + 0.953465, + 0.002703, + 0.000144, + 0.003856, + 0.003856, + 0.000096, + 0.000096, + 0.000000, + 0.000218, + 0.000002, + 0.000021, + 0.000402, + 0.001797, + 0.017999, + 0.269651, + 0.082041, + 0.229561, + 0.795287, + 1.000000, + 1.000000, + 1.000000, + 0.172917, + 0.501066, + 0.501066, + 0.569005, + 0.913700, + 0.871823, + 0.871823, + 1.000000, + 1.000000, + 0.999876, + 0.999992, + 0.978568; + 0.941746,0.646745,0.574718,0.000000,-0.283133,-0.461979,0.983825,0.000000,0.923057,-1.114921,-0.257893,0.000000,-65.708862,30.353960,-12.980427,1.000000;; + } + + SkinWeights { + "Bip01_L_Clavicle"; + 2; + 150, + 3512; + 0.303157, + 0.303157; + 1.253361,-0.000002,0.254069,0.000000,-0.218659,-0.223923,1.078679,0.000000,0.058231,-1.440720,-0.287275,0.000000,-8.131670,62.204407,-2.611076,1.000000;; + } + + SkinWeights { + "Bip01_Pelvis"; + 33; + 252, + 254, + 3541, + 256, + 259, + 264, + 3641, + 421, + 459, + 461, + 3640, + 463, + 465, + 466, + 467, + 468, + 474, + 483, + 554, + 557, + 3653, + 559, + 561, + 751, + 753, + 755, + 756, + 757, + 758, + 764, + 773, + 1805, + 1936; + 0.509683, + 0.606020, + 0.606020, + 0.500000, + 0.547477, + 0.500000, + 0.500000, + 0.500000, + 0.500000, + 0.500000, + 0.500000, + 0.500000, + 0.285136, + 0.499985, + 0.504544, + 0.462138, + 0.664527, + 0.500000, + 0.274934, + 0.605750, + 0.605750, + 0.500000, + 0.547059, + 0.500000, + 0.500000, + 0.283811, + 0.499986, + 0.504535, + 0.462238, + 0.663154, + 0.500000, + 1.000000, + 1.000000; + -0.000002,0.000004,1.278853,0.000000,1.123165,-0.000000,0.000002,0.000000,0.000000,1.470235,-0.000004,0.000000,126.489456,-70.579353,-0.141854,1.000000;; + } + + SkinWeights { + "Bip01_R_Thigh"; + 144; + 254, + 3541, + 255, + 261, + 3567, + 262, + 265, + 266, + 3611, + 267, + 268, + 3646, + 269, + 3544, + 270, + 273, + 274, + 3542, + 275, + 278, + 3645, + 279, + 280, + 3543, + 281, + 3604, + 282, + 3602, + 283, + 284, + 285, + 286, + 3609, + 287, + 288, + 289, + 3605, + 311, + 313, + 322, + 3647, + 323, + 324, + 332, + 3610, + 3572, + 333, + 334, + 3607, + 335, + 336, + 337, + 3603, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 386, + 387, + 388, + 389, + 390, + 3608, + 391, + 3606, + 392, + 393, + 3600, + 394, + 3612, + 3601, + 395, + 3613, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419, + 420, + 470, + 471, + 472, + 475, + 476, + 477, + 478, + 479, + 480, + 517, + 518, + 524, + 525, + 3644, + 533, + 3573, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 546, + 3649, + 547, + 3648, + 548, + 549, + 550, + 551, + 552, + 553, + 563, + 3679, + 581, + 3655, + 839; + 0.393980, + 0.393980, + 1.000000, + 0.796821, + 0.796821, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.973372, + 0.426944, + 0.426944, + 1.000000, + 1.000000, + 0.544990, + 0.984533, + 0.999195, + 0.999195, + 0.743688, + 0.445745, + 0.445745, + 1.000000, + 0.984714, + 0.984714, + 0.508808, + 0.508808, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999990, + 0.999990, + 1.000000, + 1.000000, + 0.000009, + 0.000009, + 0.000489, + 0.002645, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.000320, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.908716, + 0.954129, + 0.999907, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.519652, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999269, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999784, + 1.000000, + 1.000000, + 1.000000, + 0.637888, + 0.996718, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.000011, + 0.000008, + 0.000000, + 0.000000, + 0.000000, + 0.798798, + 0.798798, + 0.883879, + 0.998063, + 0.778724, + 0.679390, + 0.492835, + 0.737200, + 0.477944, + 0.442104, + 0.471318, + 1.000000, + 0.988985, + 0.691131, + 0.691131, + 0.977434, + 0.977434, + 0.938541, + 0.887283, + 1.000000, + 0.593064, + 1.000000, + 0.999984, + 0.204819, + 0.204819, + 0.015759, + 0.015759, + 0.114201; + -0.122195,-0.009615,-1.272965,0.000000,-1.117778,0.024505,0.107113,0.000000,0.030875,1.469844,-0.014066,0.000000,-130.245026,-68.027489,-17.265657,1.000000;; + } + + SkinWeights { + "Bip01_L_Thigh"; + 144; + 261, + 3567, + 280, + 3543, + 549, + 557, + 3653, + 558, + 563, + 3679, + 564, + 566, + 567, + 3721, + 568, + 569, + 3751, + 570, + 3656, + 571, + 574, + 575, + 3654, + 576, + 579, + 3750, + 580, + 581, + 3655, + 582, + 3714, + 583, + 3712, + 584, + 585, + 586, + 587, + 3719, + 588, + 589, + 590, + 3715, + 612, + 614, + 623, + 3752, + 624, + 625, + 633, + 3720, + 3683, + 634, + 635, + 3717, + 636, + 637, + 638, + 3713, + 639, + 640, + 641, + 642, + 643, + 644, + 645, + 646, + 687, + 688, + 689, + 690, + 691, + 3718, + 692, + 3716, + 693, + 694, + 3710, + 695, + 3722, + 3711, + 696, + 3723, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707, + 708, + 709, + 710, + 711, + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 760, + 761, + 762, + 765, + 766, + 767, + 768, + 769, + 770, + 807, + 808, + 814, + 815, + 3749, + 823, + 3684, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 836, + 3754, + 837, + 3753, + 838, + 839, + 840, + 841, + 842, + 843; + 0.203179, + 0.203179, + 0.015286, + 0.015286, + 0.112717, + 0.394250, + 0.394250, + 1.000000, + 0.795181, + 0.795181, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.973936, + 0.428996, + 0.428996, + 1.000000, + 1.000000, + 0.544972, + 0.984486, + 0.999176, + 0.999176, + 0.742419, + 0.445910, + 0.445910, + 1.000000, + 0.984241, + 0.984241, + 0.508611, + 0.508611, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999990, + 0.999990, + 1.000000, + 1.000000, + 0.000009, + 0.000009, + 0.000473, + 0.002664, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.000318, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.908719, + 0.953856, + 0.999909, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.519184, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999237, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999772, + 1.000000, + 1.000000, + 1.000000, + 0.629345, + 0.996571, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.000011, + 0.000008, + 0.000000, + 0.000000, + 0.000000, + 0.800783, + 0.800783, + 0.885426, + 0.998182, + 0.778669, + 0.680971, + 0.493117, + 0.738892, + 0.478082, + 0.442423, + 0.471379, + 1.000000, + 0.989147, + 0.690110, + 0.690110, + 0.978029, + 0.978029, + 0.937847, + 0.885799, + 1.000000, + 0.592832, + 1.000000, + 0.999985; + 0.122195,0.009619,-1.272965,0.000000,-1.117778,0.024505,-0.107113,0.000000,0.030875,1.469844,0.014070,0.000000,-130.272186,-68.029633,17.548590,1.000000;; + } + + SkinWeights { + "Bip01_R_Calf"; + 195; + 267, + 268, + 3646, + 270, + 271, + 272, + 273, + 274, + 3542, + 275, + 276, + 277, + 278, + 3645, + 287, + 293, + 3550, + 298, + 3554, + 299, + 3552, + 303, + 3615, + 3562, + 307, + 3614, + 3576, + 309, + 3561, + 310, + 3553, + 312, + 314, + 315, + 316, + 317, + 3566, + 318, + 3565, + 319, + 320, + 321, + 322, + 3647, + 323, + 324, + 325, + 326, + 327, + 3642, + 328, + 329, + 3643, + 330, + 331, + 334, + 3607, + 336, + 343, + 344, + 345, + 346, + 347, + 3582, + 348, + 349, + 3581, + 350, + 3593, + 3575, + 351, + 3592, + 352, + 3588, + 353, + 3587, + 354, + 3598, + 355, + 3594, + 356, + 3595, + 357, + 3591, + 3577, + 358, + 3583, + 359, + 3584, + 360, + 3585, + 361, + 3589, + 362, + 3596, + 363, + 3599, + 364, + 3586, + 365, + 3590, + 3580, + 366, + 3597, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 425, + 485, + 486, + 487, + 488, + 489, + 490, + 3563, + 491, + 492, + 3564, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 3569, + 513, + 514, + 515, + 516, + 3570, + 517, + 518, + 519, + 520, + 521, + 522, + 523, + 524, + 525, + 3644, + 526, + 527, + 528, + 529, + 530, + 3571, + 531, + 532, + 533, + 3573, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 544, + 545, + 546, + 3649, + 547, + 3648, + 553; + 0.026628, + 0.573056, + 0.573056, + 0.455011, + 0.248355, + 0.607645, + 0.015467, + 0.000805, + 0.000805, + 0.256312, + 0.990209, + 0.999682, + 0.554255, + 0.554255, + 0.000000, + 0.000163, + 0.000163, + 0.006766, + 0.006766, + 0.000001, + 0.000001, + 0.274225, + 0.274225, + 0.274225, + 0.472155, + 0.472155, + 0.472155, + 0.000165, + 0.000165, + 0.003872, + 0.003872, + 1.000000, + 0.358415, + 0.498074, + 0.206102, + 0.997888, + 0.997888, + 0.519331, + 0.519331, + 1.000000, + 0.999600, + 1.000000, + 0.999990, + 0.999990, + 0.999511, + 0.997355, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.000000, + 0.000000, + 0.999680, + 0.091284, + 0.045871, + 0.000094, + 0.081106, + 0.000049, + 0.000049, + 0.472477, + 0.002229, + 0.002229, + 0.006004, + 0.006004, + 0.006004, + 0.062354, + 0.062354, + 0.261482, + 0.261482, + 0.447819, + 0.447819, + 0.390951, + 0.390951, + 0.607455, + 0.607455, + 0.319347, + 0.319347, + 0.002868, + 0.002868, + 0.002868, + 0.054570, + 0.054570, + 0.134541, + 0.134541, + 0.093624, + 0.093624, + 0.539311, + 0.539311, + 0.191663, + 0.191663, + 0.179730, + 0.179730, + 0.056340, + 0.056340, + 0.731088, + 0.731088, + 0.731088, + 0.319088, + 0.319088, + 0.000359, + 0.003064, + 0.049797, + 0.236320, + 0.425663, + 0.352796, + 0.823837, + 0.413038, + 0.000386, + 0.030880, + 0.090852, + 0.059474, + 0.715907, + 0.138563, + 0.128868, + 0.029103, + 0.898838, + 0.279490, + 0.056695, + 0.028800, + 0.011590, + 1.000000, + 1.000000, + 0.465069, + 0.852364, + 0.852364, + 0.999499, + 0.505223, + 0.505223, + 0.499388, + 0.444644, + 0.999998, + 0.999999, + 0.999981, + 0.091767, + 0.242068, + 0.959793, + 0.397987, + 0.340201, + 0.504990, + 0.489005, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.998151, + 1.000000, + 1.000000, + 0.539095, + 0.966305, + 1.000000, + 0.999994, + 0.999994, + 0.999989, + 0.999992, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.201202, + 0.201202, + 0.116121, + 0.001937, + 0.221276, + 0.320610, + 0.507165, + 0.262800, + 0.522056, + 0.557896, + 0.528682, + 0.011015, + 1.000000, + 0.308869, + 0.308869, + 0.022566, + 0.022566, + 0.000016; + -0.120906,-0.020142,-1.272965,0.000000,-1.115712,-0.072214,0.107113,0.000000,-0.096302,1.467010,-0.014066,0.000000,-242.661957,-89.338974,-17.265659,1.000000;; + } + + SkinWeights { + "Bip01_R_Foot"; + 153; + 271, + 272, + 276, + 277, + 290, + 3559, + 3547, + 291, + 3548, + 292, + 3549, + 293, + 3550, + 294, + 3551, + 295, + 3558, + 3557, + 296, + 3556, + 297, + 3555, + 298, + 3554, + 299, + 3552, + 300, + 3546, + 301, + 302, + 303, + 3615, + 3562, + 304, + 3560, + 305, + 306, + 307, + 3614, + 3576, + 308, + 3579, + 3578, + 309, + 3561, + 310, + 3553, + 314, + 315, + 316, + 317, + 3566, + 318, + 3565, + 319, + 320, + 321, + 346, + 347, + 3582, + 348, + 349, + 3581, + 350, + 3593, + 3575, + 351, + 3592, + 352, + 3588, + 353, + 3587, + 354, + 3598, + 355, + 3594, + 356, + 3595, + 357, + 3591, + 3577, + 358, + 3583, + 359, + 3584, + 360, + 3585, + 361, + 3589, + 362, + 3596, + 363, + 3599, + 364, + 3586, + 365, + 3590, + 3580, + 366, + 3597, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 422, + 423, + 3574, + 424, + 3545, + 425, + 426, + 485, + 486, + 487, + 488, + 489, + 490, + 3563, + 491, + 492, + 3564, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 511, + 513, + 514, + 516, + 3570; + 0.751645, + 0.392355, + 0.009791, + 0.000318, + 0.000001, + 0.000001, + 0.000001, + 0.057440, + 0.057440, + 1.000000, + 1.000000, + 0.999837, + 0.999837, + 1.000000, + 1.000000, + 0.000037, + 0.000037, + 0.000037, + 0.450821, + 0.450821, + 1.000000, + 1.000000, + 0.993234, + 0.993234, + 0.999999, + 0.999999, + 0.000045, + 0.000045, + 0.480823, + 0.999943, + 0.725775, + 0.725775, + 0.725775, + 0.000432, + 0.000432, + 0.558857, + 1.000000, + 0.527845, + 0.527845, + 0.527845, + 1.000000, + 1.000000, + 1.000000, + 0.999835, + 0.999835, + 0.996128, + 0.996128, + 0.641585, + 0.501926, + 0.793898, + 0.002112, + 0.002112, + 0.480669, + 0.480669, + 0.000000, + 0.000400, + 0.000000, + 0.918894, + 0.999951, + 0.999951, + 0.527523, + 0.997771, + 0.997771, + 0.993996, + 0.993996, + 0.993996, + 0.937646, + 0.937646, + 0.738518, + 0.738518, + 0.552181, + 0.552181, + 0.609049, + 0.609049, + 0.392545, + 0.392545, + 0.680653, + 0.680653, + 0.997131, + 0.997131, + 0.997131, + 0.945430, + 0.945430, + 0.865459, + 0.865459, + 0.906376, + 0.906376, + 0.460689, + 0.460689, + 0.808337, + 0.808337, + 0.820270, + 0.820270, + 0.943660, + 0.943660, + 0.268912, + 0.268912, + 0.268912, + 0.680912, + 0.680912, + 1.000000, + 0.999641, + 0.996936, + 0.950203, + 0.763680, + 0.574337, + 0.647204, + 0.176163, + 0.586962, + 0.999614, + 0.969120, + 0.909148, + 0.940526, + 0.284093, + 0.861437, + 0.871132, + 0.970897, + 0.101162, + 0.720510, + 0.620766, + 1.000000, + 1.000000, + 0.712070, + 0.712070, + 0.943305, + 1.000000, + 0.971200, + 0.988410, + 0.000000, + 0.000000, + 0.534931, + 0.147636, + 0.147636, + 0.000501, + 0.494777, + 0.494777, + 0.500612, + 0.555356, + 0.000002, + 0.000001, + 0.000019, + 0.908233, + 0.757932, + 0.040207, + 0.602013, + 0.659799, + 0.495010, + 0.510995, + 0.001849, + 0.460905, + 0.033695, + 0.000006, + 0.000006; + 0.000000,0.000002,-1.278853,0.000000,-1.123165,-0.000000,-0.000000,0.000000,-0.000000,1.470235,0.000002,0.000000,-363.589264,-65.273499,-52.807724,1.000000;; + } + + SkinWeights { + "Bip01_R_Toe0"; + 20; + 290, + 3559, + 3547, + 291, + 3548, + 295, + 3558, + 3557, + 296, + 3556, + 300, + 3546, + 301, + 302, + 304, + 3560, + 305, + 422, + 424, + 3545; + 0.999999, + 0.999999, + 0.999999, + 0.942560, + 0.942560, + 0.999963, + 0.999963, + 0.999963, + 0.549179, + 0.549179, + 0.999955, + 0.999955, + 0.519177, + 0.000057, + 0.999568, + 0.999568, + 0.441143, + 0.379234, + 0.287930, + 0.287930; + 0.000002,-0.000000,-1.278853,0.000000,-0.000000,1.123166,-0.000000,0.000000,1.470235,0.000000,0.000002,0.000000,-99.850662,391.012543,-52.807743,1.000000;; + } + + SkinWeights { + "Bip01_L_Calf"; + 195; + 568, + 569, + 3751, + 571, + 572, + 573, + 574, + 575, + 3654, + 576, + 577, + 578, + 579, + 3750, + 588, + 594, + 3662, + 599, + 3666, + 600, + 3664, + 604, + 3725, + 3674, + 608, + 3724, + 3687, + 610, + 3673, + 611, + 3665, + 613, + 615, + 616, + 617, + 618, + 3678, + 619, + 3676, + 620, + 621, + 622, + 623, + 3752, + 624, + 625, + 626, + 627, + 628, + 3747, + 629, + 630, + 3748, + 631, + 632, + 635, + 3717, + 637, + 644, + 645, + 646, + 647, + 648, + 3692, + 649, + 650, + 3691, + 651, + 3703, + 3686, + 652, + 3702, + 653, + 3698, + 654, + 3697, + 655, + 3708, + 656, + 3704, + 657, + 3705, + 658, + 3726, + 3701, + 659, + 3693, + 660, + 3694, + 661, + 3695, + 662, + 3699, + 663, + 3706, + 664, + 3709, + 665, + 3696, + 666, + 3700, + 3690, + 667, + 3707, + 669, + 670, + 671, + 672, + 673, + 674, + 675, + 676, + 677, + 678, + 679, + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 725, + 775, + 776, + 777, + 778, + 779, + 780, + 3675, + 781, + 782, + 3677, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 3680, + 803, + 804, + 805, + 806, + 3681, + 807, + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 3749, + 816, + 817, + 818, + 819, + 820, + 3682, + 821, + 822, + 823, + 3684, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 834, + 835, + 836, + 3754, + 837, + 3753, + 843; + 0.026064, + 0.571004, + 0.571004, + 0.455028, + 0.248249, + 0.604345, + 0.015514, + 0.000824, + 0.000824, + 0.257581, + 0.990195, + 0.999682, + 0.554089, + 0.554089, + 0.000000, + 0.000158, + 0.000158, + 0.006843, + 0.006843, + 0.000001, + 0.000001, + 0.272648, + 0.272648, + 0.272648, + 0.472624, + 0.472624, + 0.472624, + 0.000161, + 0.000161, + 0.003903, + 0.003903, + 1.000000, + 0.357429, + 0.498086, + 0.204317, + 0.997876, + 0.997876, + 0.519316, + 0.519316, + 1.000000, + 0.999598, + 1.000000, + 0.999991, + 0.999991, + 0.999527, + 0.997336, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.000000, + 0.000000, + 0.999682, + 0.091281, + 0.046144, + 0.000091, + 0.080118, + 0.000048, + 0.000048, + 0.472785, + 0.002242, + 0.002242, + 0.006073, + 0.006073, + 0.006073, + 0.062748, + 0.062748, + 0.262268, + 0.262268, + 0.448347, + 0.448347, + 0.391542, + 0.391542, + 0.607159, + 0.607159, + 0.319517, + 0.319517, + 0.002809, + 0.002809, + 0.002809, + 0.054075, + 0.054075, + 0.133582, + 0.133582, + 0.092798, + 0.092798, + 0.537874, + 0.537874, + 0.190501, + 0.190501, + 0.178618, + 0.178618, + 0.055746, + 0.055746, + 0.730401, + 0.730401, + 0.730401, + 0.319495, + 0.319495, + 0.000363, + 0.003114, + 0.050198, + 0.237229, + 0.426363, + 0.353552, + 0.823675, + 0.413357, + 0.000372, + 0.030495, + 0.089985, + 0.058787, + 0.714235, + 0.137448, + 0.127817, + 0.028669, + 0.898433, + 0.280034, + 0.057181, + 0.028794, + 0.011515, + 1.000000, + 1.000000, + 0.464511, + 0.852246, + 0.852246, + 0.999499, + 0.505163, + 0.505163, + 0.499411, + 0.444841, + 0.999999, + 0.999999, + 0.999981, + 0.091013, + 0.240829, + 0.959675, + 0.397767, + 0.339149, + 0.504983, + 0.489019, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.998162, + 1.000000, + 1.000000, + 0.538773, + 0.966243, + 1.000000, + 0.999994, + 0.999994, + 0.999989, + 0.999992, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.199217, + 0.199217, + 0.114574, + 0.001818, + 0.221331, + 0.319029, + 0.506883, + 0.261107, + 0.521918, + 0.557577, + 0.528621, + 0.010854, + 1.000000, + 0.309890, + 0.309890, + 0.021971, + 0.021971, + 0.000015; + 0.120906,0.020146,-1.272965,0.000000,-1.115712,-0.072214,-0.107113,0.000000,-0.096302,1.467010,0.014070,0.000000,-242.688828,-89.343452,17.548592,1.000000;; + } + + SkinWeights { + "Bip01_L_Foot"; + 153; + 572, + 573, + 577, + 578, + 591, + 3671, + 3659, + 592, + 3660, + 593, + 3661, + 594, + 3662, + 595, + 3663, + 596, + 3670, + 3669, + 597, + 3668, + 598, + 3667, + 599, + 3666, + 600, + 3664, + 601, + 3658, + 602, + 603, + 604, + 3725, + 3674, + 605, + 3672, + 606, + 607, + 608, + 3724, + 3687, + 609, + 3689, + 3688, + 610, + 3673, + 611, + 3665, + 615, + 616, + 617, + 618, + 3678, + 619, + 3676, + 620, + 621, + 622, + 647, + 648, + 3692, + 649, + 650, + 3691, + 651, + 3703, + 3686, + 652, + 3702, + 653, + 3698, + 654, + 3697, + 655, + 3708, + 656, + 3704, + 657, + 3705, + 658, + 3726, + 3701, + 659, + 3693, + 660, + 3694, + 661, + 3695, + 662, + 3699, + 663, + 3706, + 664, + 3709, + 665, + 3696, + 666, + 3700, + 3690, + 667, + 3707, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675, + 676, + 677, + 678, + 679, + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 722, + 723, + 3685, + 724, + 3657, + 725, + 726, + 775, + 776, + 777, + 778, + 779, + 780, + 3675, + 781, + 782, + 3677, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 801, + 803, + 804, + 806, + 3681; + 0.751751, + 0.395655, + 0.009805, + 0.000317, + 0.000001, + 0.000001, + 0.000001, + 0.057284, + 0.057284, + 1.000000, + 1.000000, + 0.999842, + 0.999842, + 1.000000, + 1.000000, + 0.000037, + 0.000037, + 0.000037, + 0.449247, + 0.449247, + 1.000000, + 1.000000, + 0.993157, + 0.993157, + 0.999999, + 0.999999, + 0.000045, + 0.000045, + 0.480725, + 0.999952, + 0.727352, + 0.727352, + 0.727352, + 0.000434, + 0.000434, + 0.557390, + 1.000000, + 0.527376, + 0.527376, + 0.527376, + 1.000000, + 1.000000, + 1.000000, + 0.999839, + 0.999839, + 0.996097, + 0.996097, + 0.642571, + 0.501914, + 0.795683, + 0.002124, + 0.002124, + 0.480684, + 0.480684, + 0.000000, + 0.000402, + 0.000000, + 0.919882, + 0.999952, + 0.999952, + 0.527215, + 0.997758, + 0.997758, + 0.993927, + 0.993927, + 0.993927, + 0.937252, + 0.937252, + 0.737732, + 0.737732, + 0.551653, + 0.551653, + 0.608458, + 0.608458, + 0.392841, + 0.392841, + 0.680483, + 0.680483, + 0.997191, + 0.997191, + 0.997191, + 0.945925, + 0.945925, + 0.866418, + 0.866418, + 0.907202, + 0.907202, + 0.462126, + 0.462126, + 0.809499, + 0.809499, + 0.821382, + 0.821382, + 0.944254, + 0.944254, + 0.269599, + 0.269599, + 0.269599, + 0.680505, + 0.680505, + 1.000000, + 0.999637, + 0.996886, + 0.949802, + 0.762771, + 0.573637, + 0.646448, + 0.176325, + 0.586643, + 0.999628, + 0.969505, + 0.910015, + 0.941213, + 0.285765, + 0.862552, + 0.872183, + 0.971331, + 0.101567, + 0.719966, + 0.620583, + 1.000000, + 1.000000, + 0.713557, + 0.713557, + 0.942819, + 1.000000, + 0.971206, + 0.988485, + 0.000000, + 0.000000, + 0.535488, + 0.147754, + 0.147754, + 0.000501, + 0.494837, + 0.494837, + 0.500589, + 0.555158, + 0.000002, + 0.000001, + 0.000019, + 0.908987, + 0.759171, + 0.040325, + 0.602233, + 0.660851, + 0.495017, + 0.510981, + 0.001838, + 0.461227, + 0.033757, + 0.000006, + 0.000006; + 0.000000,0.000002,-1.278853,0.000000,-1.123165,-0.000000,-0.000000,0.000000,-0.000000,1.470235,0.000002,0.000000,-363.589264,-65.273499,53.091980,1.000000;; + } + + SkinWeights { + "Bip01_L_Toe0"; + 20; + 591, + 3671, + 3659, + 592, + 3660, + 596, + 3670, + 3669, + 597, + 3668, + 601, + 3658, + 602, + 603, + 605, + 3672, + 606, + 722, + 724, + 3657; + 0.999999, + 0.999999, + 0.999999, + 0.942716, + 0.942716, + 0.999963, + 0.999963, + 0.999963, + 0.550753, + 0.550753, + 0.999955, + 0.999955, + 0.519275, + 0.000048, + 0.999566, + 0.999566, + 0.442610, + 0.379417, + 0.286443, + 0.286443; + 0.000002,0.000000,-1.278853,0.000000,-0.000000,1.123165,0.000000,0.000000,1.470235,0.000000,0.000002,0.000000,-99.850632,391.012512,53.091995,1.000000;; + } + + SkinWeights { + "Bip01_L_Forearm"; + 119; + 859, + 3774, + 862, + 3763, + 863, + 3765, + 866, + 867, + 868, + 869, + 876, + 878, + 879, + 3791, + 3788, + 3767, + 880, + 3790, + 881, + 3786, + 882, + 3785, + 883, + 3796, + 3789, + 3766, + 884, + 3783, + 885, + 3797, + 886, + 3782, + 887, + 3773, + 894, + 898, + 899, + 901, + 902, + 903, + 904, + 906, + 907, + 908, + 909, + 3795, + 910, + 3804, + 3802, + 3784, + 911, + 3803, + 912, + 3792, + 913, + 914, + 3805, + 915, + 3808, + 3807, + 3787, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 3793, + 925, + 926, + 927, + 928, + 929, + 930, + 931, + 932, + 933, + 934, + 935, + 936, + 937, + 938, + 3794, + 939, + 940, + 941, + 942, + 947, + 3806, + 948, + 949, + 950, + 3927, + 951, + 3813, + 3811, + 3810, + 952, + 3815, + 1271, + 1272, + 1273, + 1274, + 1275, + 1276, + 1277, + 1278, + 1279, + 1280, + 3930, + 1281, + 3809, + 1282, + 3812, + 1283, + 1284; + 0.000002, + 0.000002, + 0.059762, + 0.059762, + 0.156983, + 0.156983, + 0.307600, + 0.461983, + 0.363022, + 0.207371, + 0.437484, + 0.390499, + 0.473019, + 0.473019, + 0.473019, + 0.473019, + 0.493125, + 0.493125, + 0.500494, + 0.500494, + 0.497598, + 0.497598, + 0.487562, + 0.487562, + 0.487562, + 0.487562, + 0.500000, + 0.500000, + 0.435736, + 0.435736, + 0.500010, + 0.500010, + 0.000002, + 0.000002, + 0.000000, + 0.004760, + 0.062097, + 0.000412, + 0.018884, + 0.000128, + 0.000050, + 0.046535, + 0.997297, + 0.999856, + 0.996144, + 0.996144, + 0.971005, + 0.971005, + 0.971005, + 0.971005, + 0.998600, + 0.998600, + 0.999904, + 0.999904, + 1.000000, + 0.522519, + 0.522519, + 0.500009, + 0.500009, + 0.500009, + 0.500009, + 1.000000, + 0.999782, + 1.000000, + 0.999998, + 0.999979, + 0.999598, + 0.998203, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.982001, + 0.730349, + 0.917959, + 0.770439, + 1.000000, + 1.000000, + 1.000000, + 0.825192, + 0.479548, + 0.479548, + 0.280624, + 0.280624, + 0.280624, + 0.280624, + 0.454016, + 0.454016, + 1.000000, + 1.000000, + 0.999997, + 0.522228, + 0.479390, + 0.437447, + 0.393686, + 0.431087, + 0.457384, + 0.338176, + 0.338176, + 0.610102, + 0.610102, + 0.527919, + 0.527919, + 0.541473, + 0.495169; + 0.888611,0.718008,0.574718,0.000000,-0.246358,-0.482594,0.983825,0.000000,1.006948,-1.039778,-0.257893,0.000000,-156.802475,18.217770,-12.980429,1.000000;; + } + + SkinWeights { + "Bip01_L_Hand"; + 76; + 910, + 3804, + 3802, + 3784, + 911, + 3803, + 914, + 3805, + 915, + 3808, + 3807, + 3787, + 949, + 950, + 3927, + 951, + 3813, + 3811, + 3810, + 952, + 3815, + 953, + 3928, + 954, + 3929, + 3817, + 3814, + 955, + 3931, + 3816, + 956, + 959, + 961, + 963, + 964, + 965, + 3818, + 973, + 974, + 981, + 982, + 983, + 984, + 986, + 987, + 988, + 3821, + 989, + 3820, + 991, + 1008, + 1263, + 1264, + 1265, + 1266, + 1267, + 1268, + 3926, + 1269, + 1270, + 1272, + 1273, + 1274, + 1275, + 1276, + 1277, + 1278, + 1279, + 1280, + 3930, + 1281, + 3809, + 1282, + 3812, + 1283, + 1284; + 0.028995, + 0.028995, + 0.028995, + 0.028995, + 0.001400, + 0.001400, + 0.477481, + 0.477481, + 0.499991, + 0.499991, + 0.499991, + 0.499991, + 0.174808, + 0.520452, + 0.520452, + 0.719376, + 0.719376, + 0.719376, + 0.719376, + 0.545984, + 0.545984, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.000575, + 1.000000, + 1.000000, + 1.000000, + 0.489764, + 1.000000, + 1.000000, + 0.007399, + 0.000084, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.480738, + 0.480738, + 0.485043, + 0.485043, + 0.500000, + 0.008638, + 1.000000, + 0.044182, + 0.012334, + 0.004315, + 0.389840, + 0.201485, + 0.201485, + 1.000000, + 1.000000, + 0.000000, + 0.000002, + 0.477772, + 0.520610, + 0.562553, + 0.606314, + 0.568913, + 0.542616, + 0.661824, + 0.661824, + 0.389898, + 0.389898, + 0.472081, + 0.472081, + 0.458527, + 0.504831; + 0.888611,-0.574146,0.718465,0.000000,-0.246358,-0.984209,-0.481810,0.000000,1.006948,0.257065,-1.039984,0.000000,-218.473953,12.994934,18.207430,1.000000;; + } + + SkinWeights { + "Bip01_L_Finger1"; + 94; + 956, + 957, + 958, + 960, + 962, + 3832, + 969, + 3859, + 970, + 3836, + 971, + 972, + 3882, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 985, + 3834, + 993, + 3826, + 3824, + 998, + 3829, + 1001, + 1008, + 1009, + 1010, + 1011, + 1012, + 1013, + 1014, + 1015, + 3835, + 1016, + 1017, + 1018, + 3833, + 1019, + 1020, + 1021, + 3838, + 1022, + 1023, + 1024, + 3837, + 1025, + 1026, + 1077, + 3858, + 1078, + 1079, + 1080, + 3857, + 1081, + 1082, + 1083, + 3861, + 1087, + 1088, + 1139, + 3881, + 1140, + 1141, + 1142, + 3880, + 1143, + 1144, + 1148, + 3883, + 1149, + 1150, + 1201, + 3904, + 1202, + 1203, + 1204, + 3903, + 1205, + 1206, + 1210, + 3905, + 1211, + 1212, + 1264, + 1265, + 1266, + 1267, + 1268, + 3926; + 0.999425, + 0.999999, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.959444, + 0.959444, + 0.998224, + 0.998224, + 0.997435, + 0.994530, + 0.994530, + 0.992601, + 0.999916, + 0.999813, + 0.994714, + 0.988947, + 0.990024, + 0.999781, + 0.999208, + 1.000000, + 1.000000, + 0.056190, + 0.056190, + 0.056190, + 0.000462, + 0.000462, + 0.002074, + 0.991362, + 0.999365, + 0.998360, + 1.000000, + 1.000000, + 0.962750, + 0.958956, + 0.501562, + 0.501562, + 0.544088, + 0.624832, + 0.644254, + 0.644254, + 0.583404, + 0.507984, + 0.001016, + 0.001016, + 0.000028, + 0.000000, + 0.000000, + 0.000000, + 0.000074, + 0.001057, + 0.492123, + 0.492123, + 0.366961, + 0.325544, + 0.443569, + 0.443569, + 0.494251, + 0.499973, + 0.000000, + 0.000000, + 0.000000, + 0.000000, + 0.353513, + 0.353513, + 0.257215, + 0.363813, + 0.495090, + 0.495090, + 0.498815, + 0.462536, + 0.000000, + 0.000000, + 0.000000, + 0.000000, + 0.548101, + 0.548101, + 0.472535, + 0.435641, + 0.482943, + 0.482943, + 0.490011, + 0.524837, + 0.000024, + 0.000024, + 0.000028, + 0.000000, + 0.955818, + 0.987666, + 0.995685, + 0.610160, + 0.798515, + 0.798515; + 0.888611,-0.574718,0.718007,0.000000,-0.246358,-0.983825,-0.482594,0.000000,1.006948,0.257893,-1.039779,0.000000,-242.561966,12.625334,18.722528,1.000000;; + } + + SkinWeights { + "Bip01_L_Finger11"; + 246; + 957, + 958, + 960, + 969, + 3859, + 970, + 3836, + 971, + 972, + 3882, + 975, + 976, + 977, + 978, + 979, + 980, + 1009, + 1010, + 1013, + 1014, + 1015, + 3835, + 1016, + 1017, + 1018, + 3833, + 1019, + 1020, + 1021, + 3838, + 1022, + 1023, + 1024, + 3837, + 1025, + 1026, + 1027, + 3840, + 1028, + 1029, + 1030, + 3839, + 1031, + 1032, + 1033, + 3842, + 1034, + 1035, + 1036, + 3841, + 1037, + 1038, + 1039, + 3844, + 1040, + 1041, + 1042, + 3843, + 1043, + 1044, + 1045, + 3846, + 1046, + 1047, + 1048, + 3845, + 1049, + 1050, + 1051, + 3848, + 1052, + 1053, + 1054, + 3847, + 1055, + 1056, + 1057, + 3850, + 1058, + 1059, + 1060, + 3849, + 1061, + 1062, + 1077, + 3858, + 1078, + 1079, + 1080, + 3857, + 1081, + 1082, + 1083, + 3861, + 1084, + 1085, + 1086, + 3860, + 1087, + 1088, + 1089, + 3863, + 1090, + 1091, + 1092, + 3862, + 1093, + 1094, + 1095, + 3865, + 1096, + 1097, + 1098, + 3864, + 1099, + 1100, + 1101, + 3867, + 1102, + 1103, + 1104, + 3866, + 1105, + 1106, + 1107, + 3869, + 1108, + 1109, + 1110, + 3868, + 1111, + 1112, + 1139, + 3881, + 1140, + 1141, + 1142, + 3880, + 1143, + 1144, + 1145, + 3884, + 1146, + 1147, + 1148, + 3883, + 1149, + 1150, + 1151, + 3886, + 1152, + 1153, + 1154, + 3885, + 1155, + 1156, + 1157, + 3888, + 1158, + 1159, + 1160, + 3887, + 1161, + 1162, + 1163, + 3890, + 1164, + 1165, + 1166, + 3889, + 1167, + 1168, + 1169, + 3892, + 1170, + 1171, + 1172, + 3891, + 1173, + 1174, + 1178, + 3893, + 1201, + 3904, + 1202, + 1203, + 1204, + 3903, + 1205, + 1206, + 1207, + 3906, + 1208, + 1209, + 1210, + 3905, + 1211, + 1212, + 1213, + 3908, + 1214, + 1215, + 1216, + 3907, + 1217, + 1218, + 1219, + 3910, + 1220, + 1221, + 1222, + 3909, + 1223, + 1224, + 1225, + 3912, + 1226, + 1227, + 1228, + 3911, + 1229, + 1230, + 1231, + 3914, + 1232, + 1233, + 1234, + 3913, + 1235, + 1236, + 1237, + 3916, + 1238, + 1239, + 1240, + 3915, + 1241, + 1242, + 1243, + 3918, + 1244, + 1245, + 1246, + 3917, + 1247, + 1248; + 0.000001, + 0.000000, + 0.000000, + 0.040556, + 0.040556, + 0.001776, + 0.001776, + 0.002565, + 0.005470, + 0.005470, + 0.000187, + 0.005286, + 0.011053, + 0.009976, + 0.000219, + 0.000792, + 0.000635, + 0.001640, + 0.037250, + 0.041044, + 0.498439, + 0.498439, + 0.455912, + 0.375168, + 0.355747, + 0.355747, + 0.416596, + 0.492016, + 0.998984, + 0.998984, + 0.999972, + 1.000000, + 1.000000, + 1.000000, + 0.999926, + 0.998943, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999590, + 0.999590, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999972, + 0.687019, + 0.687019, + 0.853539, + 0.975075, + 0.984281, + 0.984281, + 0.931293, + 0.756339, + 0.454794, + 0.454794, + 0.386277, + 0.350143, + 0.375279, + 0.375279, + 0.395390, + 0.437087, + 0.047430, + 0.047430, + 0.013109, + 0.001288, + 0.000577, + 0.000577, + 0.003844, + 0.028016, + 0.507877, + 0.507877, + 0.633039, + 0.674456, + 0.556431, + 0.556431, + 0.505749, + 0.500027, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999996, + 0.999996, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999998, + 0.999965, + 0.763473, + 0.763473, + 0.945556, + 0.978392, + 0.941282, + 0.941282, + 0.833361, + 0.659726, + 0.455132, + 0.455132, + 0.309846, + 0.264637, + 0.353841, + 0.353841, + 0.421831, + 0.468652, + 0.000004, + 0.000004, + 0.000000, + 0.000000, + 0.000000, + 0.000000, + 0.000002, + 0.000008, + 0.646487, + 0.646487, + 0.742785, + 0.636187, + 0.504910, + 0.504910, + 0.501185, + 0.537464, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999946, + 0.999946, + 0.999997, + 0.999305, + 0.978899, + 0.978899, + 0.978208, + 0.997956, + 0.496668, + 0.496668, + 0.492731, + 0.498635, + 0.500000, + 0.500000, + 0.500000, + 0.499604, + 0.000245, + 0.000245, + 0.000164, + 0.000644, + 0.003351, + 0.003351, + 0.003048, + 0.000866, + 0.000000, + 0.000000, + 0.451899, + 0.451899, + 0.527465, + 0.564359, + 0.517057, + 0.517057, + 0.509989, + 0.475163, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999976, + 0.999976, + 0.999972, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999989, + 0.993070, + 0.993070, + 0.998995, + 1.000000, + 0.998765, + 0.998765, + 0.985174, + 0.792985, + 0.640530, + 0.640530, + 0.737351, + 0.957855, + 0.049642, + 0.049642, + 0.038349, + 0.067962, + 0.128283, + 0.128283, + 0.109217, + 0.077048; + 0.888611,-0.574718,0.718007,0.000000,-0.246358,-0.983825,-0.482594,0.000000,1.006948,0.257893,-1.039779,0.000000,-251.862015,12.625334,18.722525,1.000000;; + } + + SkinWeights { + "Bip01_L_Finger0"; + 17; + 964, + 966, + 967, + 968, + 3822, + 988, + 3821, + 989, + 3820, + 990, + 3819, + 991, + 992, + 994, + 995, + 3823, + 996; + 0.510236, + 0.957025, + 0.977791, + 1.000000, + 1.000000, + 0.519262, + 0.519262, + 0.514957, + 0.514957, + 0.500000, + 0.500000, + 0.500000, + 1.000000, + 0.000013, + 0.001700, + 0.001700, + 0.004007; + 0.131869,-1.109649,-0.621896,0.000000,0.164812,0.558010,-0.960710,0.000000,1.446397,0.024762,0.262515,0.000000,-185.006516,140.638351,15.450895,1.000000;; + } + + SkinWeights { + "Bip01_L_Finger01"; + 16; + 966, + 967, + 990, + 3819, + 992, + 993, + 3826, + 3824, + 994, + 995, + 3823, + 996, + 997, + 3827, + 1000, + 3825; + 0.042975, + 0.022209, + 0.500000, + 0.500000, + 0.000000, + 0.943810, + 0.943810, + 0.943810, + 0.999987, + 0.998300, + 0.998300, + 0.995993, + 1.000000, + 1.000000, + 0.019189, + 0.019189; + 0.588472,-0.949953,-0.621896,0.000000,-0.086455,0.575381,-0.960710,0.000000,1.300416,0.633716,0.262515,0.000000,-236.240311,45.016586,15.450904,1.000000;; + } + + SkinWeights { + "Bip01_L_Finger02"; + 15; + 998, + 3829, + 999, + 1000, + 3825, + 1001, + 1002, + 3828, + 1003, + 3831, + 1004, + 1005, + 3830, + 1006, + 1007; + 0.999538, + 0.999538, + 1.000000, + 0.980811, + 0.980811, + 0.997926, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000; + 0.322554,-1.069892,-0.621896,0.000000,0.065410,0.578152,-0.960710,0.000000,1.420123,0.275550,0.262515,0.000000,-222.297882,106.169159,15.450895,1.000000;; + } + + SkinWeights { + "Bip01_L_Finger12"; + 214; + 1039, + 3844, + 1044, + 1045, + 3846, + 1046, + 1047, + 1048, + 3845, + 1049, + 1050, + 1051, + 3848, + 1052, + 1053, + 1054, + 3847, + 1055, + 1056, + 1057, + 3850, + 1058, + 1059, + 1060, + 3849, + 1061, + 1062, + 1063, + 3852, + 1064, + 1065, + 1066, + 3851, + 1067, + 1068, + 1069, + 3854, + 1070, + 1071, + 1072, + 3853, + 1073, + 1074, + 1075, + 3856, + 1076, + 3855, + 1089, + 3863, + 1092, + 3862, + 1093, + 1094, + 1095, + 3865, + 1096, + 1097, + 1098, + 3864, + 1099, + 1100, + 1101, + 3867, + 1102, + 1103, + 1104, + 3866, + 1105, + 1106, + 1107, + 3869, + 1108, + 1109, + 1110, + 3868, + 1111, + 1112, + 1113, + 3871, + 1114, + 1115, + 1116, + 3870, + 1117, + 1118, + 1119, + 3873, + 1120, + 1121, + 1122, + 3872, + 1123, + 1124, + 1125, + 3875, + 1126, + 1127, + 1128, + 3874, + 1129, + 1130, + 1131, + 3877, + 1132, + 1133, + 1134, + 3876, + 1135, + 1136, + 1137, + 3879, + 1138, + 3878, + 1157, + 3888, + 1158, + 1159, + 1160, + 3887, + 1161, + 1162, + 1163, + 3890, + 1164, + 1165, + 1166, + 3889, + 1167, + 1168, + 1169, + 3892, + 1170, + 1171, + 1172, + 3891, + 1173, + 1174, + 1175, + 3894, + 1176, + 1177, + 1178, + 3893, + 1179, + 1180, + 1181, + 3896, + 1182, + 1183, + 1184, + 3895, + 1185, + 1186, + 1187, + 3898, + 1188, + 1189, + 1190, + 3897, + 1191, + 1192, + 1193, + 3900, + 1194, + 1195, + 1196, + 3899, + 1197, + 1198, + 1199, + 3902, + 1200, + 3901, + 1233, + 1234, + 3913, + 1235, + 1237, + 3916, + 1238, + 1239, + 1240, + 3915, + 1241, + 1242, + 1243, + 3918, + 1244, + 1245, + 1246, + 3917, + 1247, + 1248, + 1249, + 3921, + 1250, + 3919, + 1251, + 1252, + 3920, + 1253, + 1254, + 1255, + 3923, + 1256, + 1257, + 1258, + 3922, + 1259, + 1260, + 1261, + 3925, + 1262, + 3924; + 0.000410, + 0.000410, + 0.000028, + 0.312981, + 0.312981, + 0.146461, + 0.024925, + 0.015719, + 0.015719, + 0.068707, + 0.243661, + 0.545206, + 0.545206, + 0.613723, + 0.649857, + 0.624721, + 0.624721, + 0.604610, + 0.562913, + 0.952570, + 0.952570, + 0.986891, + 0.998712, + 0.999423, + 0.999423, + 0.996156, + 0.971984, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.000004, + 0.000004, + 0.000000, + 0.000000, + 0.000002, + 0.000035, + 0.236527, + 0.236527, + 0.054444, + 0.021608, + 0.058718, + 0.058718, + 0.166639, + 0.340274, + 0.544868, + 0.544868, + 0.690154, + 0.735363, + 0.646159, + 0.646159, + 0.578169, + 0.531348, + 0.999996, + 0.999996, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999998, + 0.999992, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.000054, + 0.000054, + 0.000003, + 0.000695, + 0.021101, + 0.021101, + 0.021792, + 0.002044, + 0.503332, + 0.503332, + 0.507269, + 0.501365, + 0.500000, + 0.500000, + 0.500000, + 0.500396, + 0.999754, + 0.999754, + 0.999836, + 0.999356, + 0.996649, + 0.996649, + 0.996952, + 0.999134, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.000011, + 0.006930, + 0.006930, + 0.001005, + 0.001235, + 0.001235, + 0.014826, + 0.207015, + 0.359470, + 0.359470, + 0.262649, + 0.042145, + 0.950358, + 0.950358, + 0.961651, + 0.932038, + 0.871718, + 0.871718, + 0.890783, + 0.922952, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000; + 0.888611,-0.574718,0.718007,0.000000,-0.246358,-0.983825,-0.482594,0.000000,1.006948,0.257893,-1.039779,0.000000,-262.712067,12.625349,18.722527,1.000000;; + } + + SkinWeights { + "Bip01_R_Forearm"; + 118; + 1304, + 3954, + 1307, + 3943, + 1308, + 3944, + 1311, + 1312, + 1313, + 1314, + 1321, + 1323, + 1324, + 3967, + 3947, + 1325, + 3971, + 1326, + 3966, + 1327, + 3969, + 3965, + 1328, + 3976, + 3970, + 3946, + 1329, + 3963, + 1330, + 3977, + 1331, + 3962, + 1332, + 3953, + 1339, + 1343, + 1344, + 1346, + 1347, + 1348, + 1349, + 1351, + 1352, + 1353, + 1354, + 3975, + 1355, + 3984, + 3982, + 3964, + 1356, + 3983, + 1357, + 1358, + 1359, + 3985, + 1360, + 3988, + 3987, + 3973, + 1361, + 1362, + 1363, + 3968, + 1364, + 1365, + 1366, + 1367, + 1368, + 1369, + 3974, + 1370, + 1371, + 1372, + 1373, + 1374, + 1375, + 1376, + 1377, + 1378, + 1379, + 1380, + 1381, + 1382, + 3972, + 1383, + 1384, + 1385, + 1386, + 1387, + 1392, + 3986, + 1393, + 1394, + 1395, + 4103, + 1396, + 3993, + 3992, + 3989, + 1397, + 3991, + 1716, + 1717, + 1718, + 1719, + 1720, + 1721, + 1722, + 1723, + 1724, + 1725, + 4105, + 1726, + 3990, + 1727, + 1728, + 1729; + 0.000002, + 0.000002, + 0.062100, + 0.062100, + 0.156545, + 0.156545, + 0.307653, + 0.463402, + 0.364263, + 0.206257, + 0.437729, + 0.393141, + 0.474390, + 0.474390, + 0.474390, + 0.494343, + 0.494343, + 0.500493, + 0.500493, + 0.497958, + 0.497958, + 0.497958, + 0.487799, + 0.487799, + 0.487799, + 0.487799, + 0.500000, + 0.500000, + 0.435860, + 0.435860, + 0.500018, + 0.500018, + 0.000003, + 0.000003, + 0.000000, + 0.004865, + 0.063481, + 0.000471, + 0.019984, + 0.000129, + 0.000050, + 0.048368, + 0.997429, + 0.999862, + 0.996296, + 0.996296, + 0.969578, + 0.969578, + 0.969578, + 0.969578, + 0.998534, + 0.998534, + 0.999904, + 1.000000, + 0.521478, + 0.521478, + 0.500006, + 0.500006, + 0.500006, + 0.500006, + 1.000000, + 0.999783, + 1.000000, + 1.000000, + 0.999998, + 0.999980, + 0.999624, + 0.998287, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.982655, + 0.733244, + 0.919066, + 0.773837, + 1.000000, + 1.000000, + 1.000000, + 0.821199, + 0.479127, + 0.479127, + 0.373080, + 0.373080, + 0.373080, + 0.373080, + 0.494538, + 0.494538, + 1.000000, + 1.000000, + 0.999997, + 0.521167, + 0.479837, + 0.438248, + 0.533577, + 0.511417, + 0.457177, + 0.338835, + 0.338835, + 0.606293, + 0.606293, + 0.526599, + 0.539169, + 0.495281; + -0.888608,-0.718010,0.574719,0.000000,-0.246358,-0.482594,-0.983825,0.000000,1.006950,-1.039776,0.257891,0.000000,-156.604965,18.377340,12.852691,1.000000;; + } + + SkinWeights { + "Bip01_R_Hand"; + 74; + 1355, + 3984, + 3982, + 3964, + 1356, + 3983, + 1359, + 3985, + 1360, + 3988, + 3987, + 3973, + 1394, + 1395, + 4103, + 1396, + 3993, + 3992, + 3989, + 1397, + 3991, + 1398, + 4104, + 1399, + 4106, + 3996, + 3994, + 1400, + 3995, + 1401, + 1404, + 1406, + 1408, + 1409, + 1410, + 3997, + 1418, + 1419, + 1426, + 1427, + 1428, + 1429, + 1431, + 1432, + 1433, + 4000, + 1434, + 3999, + 1436, + 1453, + 1708, + 1709, + 1710, + 1711, + 1712, + 1713, + 4102, + 1714, + 1715, + 1717, + 1718, + 1719, + 1720, + 1721, + 1722, + 1723, + 1724, + 1725, + 4105, + 1726, + 3990, + 1727, + 1728, + 1729; + 0.030422, + 0.030422, + 0.030422, + 0.030422, + 0.001466, + 0.001466, + 0.478522, + 0.478522, + 0.499994, + 0.499994, + 0.499994, + 0.499994, + 0.178801, + 0.520873, + 0.520873, + 0.626920, + 0.626920, + 0.626920, + 0.626920, + 0.505462, + 0.505462, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.000096, + 1.000000, + 1.000000, + 0.500000, + 0.470417, + 1.000000, + 1.000000, + 0.002561, + 0.000004, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.460453, + 0.460453, + 0.466427, + 0.466427, + 0.496454, + 0.002208, + 1.000000, + 0.022241, + 0.006276, + 0.001324, + 0.337075, + 0.124395, + 0.124395, + 1.000000, + 1.000000, + 0.000000, + 0.000003, + 0.478833, + 0.520163, + 0.561752, + 0.466423, + 0.488583, + 0.542824, + 0.661165, + 0.661165, + 0.393707, + 0.393707, + 0.473401, + 0.460831, + 0.504719; + -0.888608,0.574147,0.718468,0.000000,-0.246358,-0.984209,0.481810,0.000000,1.006950,0.257063,1.039981,0.000000,-218.276459,12.867327,-18.367111,1.000000;; + } + + SkinWeights { + "Bip01_R_Finger1"; + 88; + 1401, + 1402, + 1403, + 1405, + 1407, + 4008, + 1414, + 4036, + 1415, + 4009, + 1416, + 1417, + 4059, + 1418, + 1419, + 1420, + 1421, + 1422, + 1423, + 1424, + 1425, + 1430, + 4011, + 1438, + 4003, + 1443, + 4005, + 1446, + 1453, + 1454, + 1455, + 1456, + 1457, + 1458, + 1459, + 1460, + 4013, + 1461, + 4010, + 1462, + 1463, + 4012, + 1464, + 1465, + 1466, + 4015, + 1467, + 1469, + 4014, + 1470, + 1471, + 1522, + 4035, + 1523, + 1524, + 1525, + 4034, + 1526, + 1527, + 1533, + 1584, + 4058, + 1585, + 1586, + 1587, + 4057, + 1588, + 1589, + 1593, + 4060, + 1594, + 1646, + 4081, + 1647, + 1648, + 1649, + 4080, + 1650, + 1651, + 1655, + 4082, + 1656, + 1709, + 1710, + 1711, + 1712, + 1713, + 4102; + 0.999904, + 0.999575, + 0.999896, + 0.999998, + 0.999965, + 0.999965, + 0.826216, + 0.826216, + 0.988180, + 0.988180, + 0.963893, + 0.941790, + 0.941790, + 0.997439, + 0.999996, + 0.984101, + 0.927449, + 0.946660, + 0.969436, + 0.999024, + 0.990114, + 1.000000, + 1.000000, + 0.051519, + 0.051519, + 0.000312, + 0.000312, + 0.001440, + 0.997792, + 0.988519, + 0.958418, + 0.999946, + 1.000000, + 0.898404, + 0.871105, + 0.499901, + 0.499901, + 0.475211, + 0.475211, + 0.475116, + 0.551148, + 0.551148, + 0.553986, + 0.503293, + 0.000385, + 0.000385, + 0.000002, + 0.000000, + 0.000000, + 0.000073, + 0.000839, + 0.424792, + 0.424792, + 0.175096, + 0.154834, + 0.359990, + 0.359990, + 0.479599, + 0.496175, + 0.000000, + 0.162945, + 0.162945, + 0.064365, + 0.151668, + 0.434586, + 0.434586, + 0.478500, + 0.374775, + 0.000000, + 0.000000, + 0.000000, + 0.193238, + 0.193238, + 0.106886, + 0.203754, + 0.409137, + 0.409137, + 0.427054, + 0.345515, + 0.000000, + 0.000000, + 0.000001, + 0.977759, + 0.993724, + 0.998676, + 0.662925, + 0.875605, + 0.875605; + -0.888608,0.574719,0.718010,0.000000,-0.246358,-0.983825,0.482594,0.000000,1.006950,0.257891,1.039776,0.000000,-242.364456,12.497601,-18.882097,1.000000;; + } + + SkinWeights { + "Bip01_R_Finger11"; + 254; + 1402, + 1403, + 1405, + 1407, + 4008, + 1414, + 4036, + 1415, + 4009, + 1416, + 1417, + 4059, + 1420, + 1421, + 1422, + 1423, + 1424, + 1425, + 1454, + 1455, + 1456, + 1458, + 1459, + 1460, + 4013, + 1461, + 4010, + 1462, + 1463, + 4012, + 1464, + 1465, + 1466, + 4015, + 1467, + 1468, + 1469, + 4014, + 1470, + 1471, + 1472, + 4017, + 1473, + 1474, + 1475, + 4016, + 1476, + 1477, + 1478, + 4019, + 1479, + 1480, + 1481, + 4018, + 1482, + 1483, + 1484, + 4021, + 1485, + 1486, + 1487, + 4020, + 1488, + 1489, + 1490, + 4023, + 1491, + 1492, + 1493, + 4022, + 1494, + 1495, + 1496, + 4025, + 1497, + 1498, + 1499, + 4024, + 1500, + 1501, + 1502, + 4027, + 1503, + 1504, + 1505, + 4026, + 1506, + 1507, + 1508, + 4029, + 1513, + 1522, + 4035, + 1523, + 1524, + 1525, + 4034, + 1526, + 1527, + 1528, + 4038, + 1529, + 1530, + 1531, + 4037, + 1532, + 1533, + 1534, + 4040, + 1535, + 1536, + 1537, + 4039, + 1538, + 1539, + 1540, + 4042, + 1541, + 1542, + 1543, + 4041, + 1544, + 1545, + 1546, + 4044, + 1547, + 1548, + 1549, + 4043, + 1550, + 1551, + 1552, + 4046, + 1553, + 1554, + 1555, + 4045, + 1556, + 1557, + 1584, + 4058, + 1585, + 1586, + 1587, + 4057, + 1588, + 1589, + 1590, + 4061, + 1591, + 1592, + 1593, + 4060, + 1594, + 1595, + 1596, + 4063, + 1597, + 1598, + 1599, + 4062, + 1600, + 1601, + 1602, + 4065, + 1603, + 1604, + 1605, + 4064, + 1606, + 1607, + 1608, + 4067, + 1609, + 1610, + 1611, + 4066, + 1612, + 1613, + 1614, + 4069, + 1615, + 1616, + 1617, + 4068, + 1618, + 1619, + 1623, + 4070, + 1624, + 1646, + 4081, + 1647, + 1648, + 1649, + 4080, + 1650, + 1651, + 1652, + 4083, + 1653, + 1654, + 1655, + 4082, + 1656, + 1657, + 1658, + 4085, + 1659, + 1660, + 1661, + 4084, + 1662, + 1663, + 1664, + 4087, + 1665, + 1666, + 1667, + 4086, + 1668, + 1669, + 1670, + 4089, + 1671, + 1672, + 1673, + 4088, + 1674, + 1675, + 1676, + 4091, + 1677, + 1678, + 1679, + 4090, + 1680, + 1681, + 1682, + 4093, + 1683, + 1684, + 1685, + 4092, + 1686, + 1687, + 1688, + 4095, + 1689, + 1690, + 1691, + 4094, + 1692, + 1693; + 0.000425, + 0.000104, + 0.000002, + 0.000035, + 0.000035, + 0.173784, + 0.173784, + 0.011820, + 0.011820, + 0.036107, + 0.058210, + 0.058210, + 0.015899, + 0.072551, + 0.053340, + 0.030564, + 0.000976, + 0.009886, + 0.011481, + 0.041582, + 0.000054, + 0.101596, + 0.128895, + 0.500099, + 0.500099, + 0.524789, + 0.524789, + 0.524884, + 0.448852, + 0.448852, + 0.446014, + 0.496707, + 0.999615, + 0.999615, + 0.999998, + 1.000000, + 1.000000, + 1.000000, + 0.999927, + 0.999161, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999738, + 0.999738, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999990, + 0.732293, + 0.732293, + 0.886205, + 0.985333, + 0.992404, + 0.992404, + 0.959854, + 0.812284, + 0.489268, + 0.489268, + 0.456724, + 0.487872, + 0.558722, + 0.558722, + 0.534944, + 0.495299, + 0.141677, + 0.141677, + 0.042808, + 0.009349, + 0.010870, + 0.010870, + 0.042129, + 0.130213, + 0.000000, + 0.000000, + 0.000000, + 0.575208, + 0.575208, + 0.824904, + 0.845166, + 0.640010, + 0.640010, + 0.520401, + 0.503825, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999994, + 0.999994, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999999, + 0.999967, + 0.788284, + 0.788284, + 0.947229, + 0.980557, + 0.954581, + 0.954581, + 0.872298, + 0.693192, + 0.483189, + 0.483189, + 0.343736, + 0.320172, + 0.442659, + 0.442659, + 0.491581, + 0.499255, + 0.000025, + 0.000025, + 0.000001, + 0.000001, + 0.000008, + 0.000008, + 0.000046, + 0.000109, + 0.837055, + 0.837055, + 0.935635, + 0.848332, + 0.565414, + 0.565414, + 0.521500, + 0.625225, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999937, + 0.999937, + 0.999993, + 0.999085, + 0.980304, + 0.980304, + 0.982841, + 0.998364, + 0.503262, + 0.503262, + 0.492041, + 0.498016, + 0.500000, + 0.500000, + 0.500000, + 0.500995, + 0.000473, + 0.000473, + 0.000211, + 0.000957, + 0.007196, + 0.007196, + 0.009105, + 0.002560, + 0.000000, + 0.000000, + 0.000000, + 0.806762, + 0.806762, + 0.893114, + 0.796246, + 0.590863, + 0.590863, + 0.572946, + 0.654485, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999999, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999991, + 0.994261, + 0.994261, + 0.999425, + 1.000000, + 0.999589, + 0.999589, + 0.987588, + 0.800337, + 0.665842, + 0.665842, + 0.779593, + 0.974322, + 0.046310, + 0.046310, + 0.022865, + 0.060048, + 0.146116, + 0.146116, + 0.153619, + 0.123733; + -0.888608,0.574719,0.718010,0.000000,-0.246358,-0.983825,0.482594,0.000000,1.006950,0.257891,1.039776,0.000000,-251.664520,12.497601,-18.882095,1.000000;; + } + + SkinWeights { + "Bip01_R_Finger0"; + 17; + 1408, + 1409, + 1411, + 1412, + 1413, + 4001, + 1433, + 4000, + 1434, + 3999, + 1435, + 3998, + 1436, + 1437, + 1440, + 4002, + 1441; + 0.500000, + 0.529583, + 0.538317, + 0.843910, + 0.999997, + 0.999997, + 0.539547, + 0.539547, + 0.533573, + 0.533573, + 0.500000, + 0.500000, + 0.503546, + 0.999995, + 0.000235, + 0.000235, + 0.000825; + -0.131865,1.109649,-0.621897,0.000000,0.164812,0.558010,0.960710,0.000000,1.446398,0.024759,-0.262513,0.000000,-184.977188,140.391739,-15.312693,1.000000;; + } + + SkinWeights { + "Bip01_R_Finger01"; + 16; + 1411, + 1412, + 1413, + 4001, + 1435, + 3998, + 1437, + 1438, + 4003, + 1439, + 1440, + 4002, + 1441, + 1442, + 1445, + 4004; + 0.461683, + 0.156090, + 0.000003, + 0.000003, + 0.500000, + 0.500000, + 0.000006, + 0.948481, + 0.948481, + 1.000000, + 0.999765, + 0.999765, + 0.999175, + 1.000000, + 0.012123, + 0.012123; + -0.588468,0.949955,-0.621897,0.000000,-0.086455,0.575381,0.960710,0.000000,1.300418,0.633713,-0.262513,0.000000,-236.109512,44.805492,-15.312693,1.000000;; + } + + SkinWeights { + "Bip01_R_Finger02"; + 14; + 1443, + 4005, + 1444, + 1445, + 4004, + 1446, + 1447, + 1448, + 4007, + 1449, + 1450, + 4006, + 1451, + 1452; + 0.999688, + 0.999688, + 1.000000, + 0.987877, + 0.987877, + 0.998560, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000; + -0.322550,1.069893,-0.621897,0.000000,0.065410,0.578152,0.960710,0.000000,1.420124,0.275547,-0.262513,0.000000,-222.226196,105.931374,-15.312693,1.000000;; + } + + SkinWeights { + "Bip01_R_Finger12"; + 214; + 1484, + 4021, + 1489, + 1490, + 4023, + 1491, + 1492, + 1493, + 4022, + 1494, + 1495, + 1496, + 4025, + 1497, + 1498, + 1499, + 4024, + 1500, + 1501, + 1502, + 4027, + 1503, + 1504, + 1505, + 4026, + 1506, + 1507, + 1508, + 4029, + 1509, + 1510, + 1511, + 4028, + 1512, + 1513, + 1514, + 4031, + 1515, + 1516, + 1517, + 4030, + 1518, + 1519, + 1520, + 4033, + 1521, + 4032, + 1534, + 4040, + 1537, + 4039, + 1538, + 1539, + 1540, + 4042, + 1541, + 1542, + 1543, + 4041, + 1544, + 1545, + 1546, + 4044, + 1547, + 1548, + 1549, + 4043, + 1550, + 1551, + 1552, + 4046, + 1553, + 1554, + 1555, + 4045, + 1556, + 1557, + 1558, + 4048, + 1559, + 1560, + 1561, + 4047, + 1562, + 1563, + 1564, + 4050, + 1565, + 1566, + 1567, + 4049, + 1568, + 1569, + 1570, + 4052, + 1571, + 1572, + 1573, + 4051, + 1574, + 1575, + 1576, + 4054, + 1577, + 1578, + 1579, + 4053, + 1580, + 1581, + 1582, + 4056, + 1583, + 4055, + 1600, + 1602, + 4065, + 1603, + 1604, + 1605, + 4064, + 1606, + 1607, + 1608, + 4067, + 1609, + 1610, + 1611, + 4066, + 1612, + 1613, + 1614, + 4069, + 1615, + 1616, + 1617, + 4068, + 1618, + 1619, + 1620, + 4071, + 1621, + 1622, + 1623, + 4070, + 1624, + 1625, + 1626, + 4073, + 1627, + 1628, + 1629, + 4072, + 1630, + 1631, + 1632, + 4075, + 1633, + 1634, + 1635, + 4074, + 1636, + 1637, + 1638, + 4077, + 1639, + 1640, + 1641, + 4076, + 1642, + 1643, + 1644, + 4079, + 1645, + 4078, + 1678, + 1679, + 4090, + 1680, + 1682, + 4093, + 1683, + 1684, + 1685, + 4092, + 1686, + 1687, + 1688, + 4095, + 1689, + 1690, + 1691, + 4094, + 1692, + 1693, + 1694, + 4097, + 1695, + 1696, + 1697, + 4096, + 1698, + 1699, + 1700, + 4099, + 1701, + 1702, + 1703, + 4098, + 1704, + 1705, + 1706, + 4101, + 1707, + 4100; + 0.000262, + 0.000262, + 0.000010, + 0.267707, + 0.267707, + 0.113795, + 0.014667, + 0.007596, + 0.007596, + 0.040146, + 0.187716, + 0.510732, + 0.510732, + 0.543276, + 0.512128, + 0.441278, + 0.441278, + 0.465056, + 0.504701, + 0.858323, + 0.858323, + 0.957192, + 0.990651, + 0.989130, + 0.989130, + 0.957871, + 0.869787, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.000006, + 0.000006, + 0.000000, + 0.000000, + 0.000001, + 0.000033, + 0.211716, + 0.211716, + 0.052771, + 0.019443, + 0.045419, + 0.045419, + 0.127702, + 0.306808, + 0.516811, + 0.516811, + 0.656264, + 0.679828, + 0.557341, + 0.557341, + 0.508419, + 0.500745, + 0.999975, + 0.999975, + 0.999999, + 0.999999, + 0.999992, + 0.999992, + 0.999954, + 0.999891, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.000000, + 0.000063, + 0.000063, + 0.000007, + 0.000915, + 0.019696, + 0.019696, + 0.017159, + 0.001636, + 0.496738, + 0.496738, + 0.507959, + 0.501984, + 0.500000, + 0.500000, + 0.500000, + 0.499005, + 0.999527, + 0.999527, + 0.999789, + 0.999043, + 0.992804, + 0.992804, + 0.990895, + 0.997440, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.000009, + 0.005739, + 0.005739, + 0.000575, + 0.000411, + 0.000411, + 0.012412, + 0.199663, + 0.334158, + 0.334158, + 0.220407, + 0.025678, + 0.953690, + 0.953690, + 0.977135, + 0.939952, + 0.853884, + 0.853884, + 0.846381, + 0.876267, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000; + -0.888608,0.574719,0.718010,0.000000,-0.246358,-0.983825,0.482594,0.000000,1.006950,0.257891,1.039776,0.000000,-262.514587,12.497601,-18.882095,1.000000;; + } + + SkinWeights { + "Bip01_Head"; + 1955; + 1746, + 4135, + 1747, + 4276, + 4217, + 4192, + 1748, + 4279, + 4255, + 4210, + 4195, + 4167, + 1749, + 1750, + 4250, + 4246, + 4219, + 4163, + 4160, + 1751, + 4289, + 4275, + 4208, + 4203, + 4191, + 4178, + 4176, + 1752, + 4137, + 1753, + 4278, + 4260, + 4257, + 4194, + 4171, + 1754, + 4307, + 4249, + 1755, + 4324, + 1756, + 4200, + 4188, + 4166, + 4134, + 1757, + 4193, + 4156, + 4126, + 4125, + 4122, + 4120, + 1758, + 4197, + 4196, + 4152, + 4124, + 4121, + 1759, + 4199, + 4162, + 4161, + 4128, + 4127, + 4123, + 1760, + 1761, + 4333, + 4201, + 4186, + 4180, + 4170, + 4165, + 1762, + 1763, + 4140, + 1764, + 4202, + 4198, + 4169, + 4157, + 4154, + 4151, + 1765, + 4205, + 4159, + 4129, + 1766, + 4190, + 4146, + 4143, + 1767, + 4149, + 4132, + 1768, + 4148, + 1769, + 4131, + 1770, + 4139, + 1771, + 4138, + 1772, + 4136, + 1773, + 4142, + 1774, + 4187, + 1775, + 4144, + 1776, + 4145, + 1777, + 4147, + 4141, + 1778, + 4133, + 1779, + 4150, + 4130, + 1780, + 4332, + 1781, + 4175, + 1782, + 4347, + 4164, + 1783, + 4348, + 4181, + 1784, + 4179, + 4173, + 4168, + 4155, + 1785, + 4350, + 4349, + 4206, + 4158, + 1786, + 4351, + 4204, + 4183, + 1787, + 4356, + 1788, + 4306, + 4184, + 4182, + 1789, + 4346, + 4185, + 1790, + 1791, + 1792, + 1793, + 1794, + 1795, + 1796, + 1797, + 1798, + 1799, + 1800, + 1801, + 1802, + 1803, + 1804, + 4174, + 4172, + 1806, + 1807, + 1808, + 1809, + 1810, + 1811, + 1812, + 1813, + 4207, + 1814, + 1815, + 1816, + 1817, + 1818, + 4189, + 1819, + 1820, + 1821, + 1822, + 1823, + 1824, + 1825, + 1826, + 1827, + 1828, + 1829, + 1830, + 1831, + 1832, + 1833, + 1834, + 1835, + 1836, + 1837, + 1838, + 1839, + 1840, + 1841, + 1842, + 1843, + 1844, + 1845, + 1846, + 1847, + 1848, + 1849, + 1850, + 1851, + 1852, + 1853, + 1854, + 1855, + 1856, + 1857, + 1858, + 1859, + 1860, + 1861, + 1862, + 1863, + 1864, + 1865, + 1866, + 1867, + 1868, + 1869, + 1870, + 1871, + 1872, + 1873, + 1874, + 1875, + 1876, + 1877, + 1878, + 1879, + 1880, + 4177, + 1881, + 1882, + 1883, + 1884, + 1885, + 1886, + 4378, + 1887, + 4284, + 4271, + 4254, + 4226, + 1888, + 4277, + 4242, + 4216, + 4215, + 4212, + 4209, + 1889, + 4281, + 4280, + 4239, + 4214, + 4211, + 1890, + 4283, + 4248, + 4247, + 4220, + 4218, + 4213, + 1891, + 1892, + 4389, + 4287, + 4270, + 4264, + 4259, + 4252, + 1893, + 1894, + 4229, + 1895, + 4288, + 4282, + 4258, + 4243, + 4240, + 4238, + 1896, + 4291, + 4245, + 4221, + 1897, + 4386, + 4274, + 4232, + 1898, + 4236, + 4223, + 1899, + 4225, + 1900, + 4224, + 1901, + 4230, + 1902, + 4228, + 1903, + 4227, + 1904, + 4234, + 1905, + 4272, + 1906, + 4233, + 1907, + 4429, + 1908, + 4387, + 4231, + 1909, + 4235, + 1910, + 4237, + 4222, + 1911, + 4390, + 1912, + 4404, + 1913, + 4403, + 4251, + 1914, + 4406, + 4265, + 1915, + 4388, + 4263, + 4256, + 4241, + 1916, + 4408, + 4407, + 4294, + 4292, + 4244, + 1917, + 4409, + 4295, + 4290, + 4267, + 1918, + 4415, + 1919, + 4308, + 4268, + 4266, + 1920, + 4402, + 4269, + 1921, + 1922, + 1923, + 1924, + 1925, + 1926, + 1927, + 1928, + 1929, + 1930, + 1931, + 1932, + 1933, + 1934, + 1935, + 4405, + 4261, + 1937, + 1938, + 1939, + 1940, + 1941, + 1942, + 1943, + 1944, + 4293, + 1945, + 1946, + 1947, + 1948, + 1949, + 4273, + 1950, + 1951, + 1952, + 1953, + 1954, + 1955, + 1956, + 1957, + 1958, + 1959, + 1960, + 1961, + 1962, + 1963, + 1964, + 1965, + 1966, + 1967, + 1968, + 1969, + 1970, + 1971, + 1972, + 1973, + 1974, + 1975, + 1976, + 1977, + 1978, + 1979, + 1980, + 1981, + 1982, + 1983, + 1984, + 1985, + 1986, + 1987, + 1988, + 1989, + 1990, + 1991, + 1992, + 1993, + 1994, + 1995, + 1996, + 1997, + 1998, + 4285, + 1999, + 4286, + 2000, + 2001, + 2002, + 2003, + 2004, + 2005, + 2006, + 2007, + 2008, + 2009, + 2010, + 2011, + 4262, + 2012, + 2013, + 2014, + 2015, + 2016, + 2017, + 2018, + 2019, + 2020, + 2021, + 2022, + 2023, + 2024, + 2025, + 2026, + 2027, + 2028, + 2029, + 2030, + 2031, + 2032, + 2033, + 2034, + 2035, + 2036, + 2037, + 2038, + 2039, + 2040, + 2041, + 2042, + 2043, + 2044, + 2045, + 2046, + 2047, + 2048, + 2049, + 2050, + 2051, + 2052, + 2053, + 2054, + 2055, + 2056, + 2057, + 2058, + 2059, + 2060, + 2061, + 2062, + 2063, + 2064, + 2065, + 2066, + 2067, + 2068, + 2069, + 2070, + 2071, + 2072, + 2073, + 2074, + 2075, + 2076, + 2077, + 2078, + 2079, + 2080, + 2081, + 2082, + 2083, + 2084, + 2085, + 2086, + 2087, + 2088, + 2089, + 2090, + 2091, + 2092, + 2093, + 4304, + 2094, + 4296, + 2095, + 4298, + 2096, + 4301, + 2097, + 4303, + 2098, + 4305, + 2099, + 2100, + 2106, + 2107, + 2109, + 4312, + 2110, + 4315, + 2111, + 2112, + 2113, + 2114, + 2115, + 4316, + 2116, + 4319, + 2117, + 2118, + 2119, + 2120, + 2121, + 2122, + 4322, + 2123, + 2124, + 4321, + 2125, + 2126, + 2127, + 2128, + 2129, + 2130, + 2131, + 4327, + 2132, + 4326, + 2133, + 2134, + 2135, + 2136, + 2137, + 2138, + 2139, + 2140, + 4320, + 2141, + 4330, + 2142, + 2143, + 2144, + 2145, + 2146, + 4153, + 2147, + 2148, + 2149, + 2150, + 2151, + 4335, + 2152, + 4339, + 2153, + 4338, + 2154, + 4336, + 2155, + 2156, + 2157, + 2158, + 2159, + 2160, + 2161, + 2162, + 2163, + 2164, + 2165, + 2166, + 2167, + 2168, + 2169, + 2170, + 2171, + 2172, + 2173, + 2174, + 2175, + 2176, + 2177, + 2178, + 2179, + 2180, + 2181, + 2182, + 2183, + 2184, + 2185, + 2186, + 2187, + 2188, + 2189, + 2190, + 2191, + 2192, + 2193, + 2194, + 2195, + 2196, + 2197, + 2198, + 2199, + 2200, + 2201, + 2202, + 2203, + 4328, + 2204, + 2205, + 2206, + 2207, + 2208, + 4318, + 2209, + 2210, + 2211, + 4340, + 2212, + 2213, + 2214, + 2215, + 2216, + 2217, + 2218, + 2219, + 2220, + 2221, + 2222, + 2223, + 2224, + 2225, + 2226, + 2227, + 2228, + 2229, + 2230, + 2231, + 2232, + 2233, + 2234, + 2235, + 2236, + 2237, + 2238, + 2239, + 2240, + 2241, + 2242, + 2243, + 2244, + 2245, + 2246, + 2247, + 2248, + 2249, + 2250, + 2251, + 2252, + 2253, + 2254, + 2255, + 2256, + 2257, + 2258, + 2259, + 2260, + 2261, + 2262, + 2263, + 2264, + 2265, + 2266, + 2267, + 2268, + 2269, + 2270, + 2271, + 2272, + 2273, + 2274, + 2275, + 2276, + 2277, + 2278, + 2279, + 2280, + 2281, + 2282, + 2283, + 2284, + 2285, + 2286, + 2287, + 2288, + 2289, + 2290, + 2291, + 2292, + 2293, + 2294, + 2295, + 2296, + 2297, + 2298, + 2299, + 2300, + 2301, + 2302, + 2303, + 2304, + 2305, + 2306, + 2307, + 2308, + 2309, + 4341, + 2310, + 4345, + 2311, + 2312, + 2313, + 2314, + 2315, + 2316, + 4343, + 2317, + 2318, + 2319, + 2320, + 2321, + 2322, + 2323, + 2324, + 2325, + 2326, + 2327, + 2328, + 2329, + 2330, + 2331, + 2332, + 2333, + 2334, + 2335, + 2336, + 2337, + 2338, + 2339, + 2340, + 2341, + 2342, + 2343, + 2344, + 2345, + 2346, + 2347, + 2348, + 2349, + 2350, + 2351, + 2352, + 2353, + 2354, + 2355, + 2356, + 2357, + 2358, + 2359, + 2360, + 2361, + 2362, + 2363, + 2364, + 2365, + 2366, + 2367, + 2368, + 2369, + 2370, + 2371, + 2372, + 2373, + 2374, + 2375, + 2376, + 2377, + 2378, + 2379, + 2380, + 2381, + 2382, + 2383, + 2384, + 2385, + 2386, + 4329, + 2387, + 2388, + 2389, + 2390, + 2391, + 2392, + 2393, + 2394, + 4302, + 2395, + 4323, + 2396, + 2397, + 2398, + 4317, + 2399, + 4313, + 2400, + 2401, + 2402, + 2403, + 2404, + 2405, + 4352, + 2406, + 4300, + 2407, + 2408, + 2409, + 4354, + 2410, + 4358, + 2411, + 2412, + 2414, + 4355, + 2417, + 2419, + 2420, + 2421, + 2424, + 2425, + 2426, + 4359, + 4357, + 4353, + 2427, + 2428, + 2429, + 2430, + 2431, + 2432, + 2433, + 2434, + 2435, + 2436, + 2437, + 2438, + 2439, + 2440, + 2441, + 2442, + 2443, + 2444, + 2445, + 2446, + 2447, + 2448, + 2449, + 2450, + 2451, + 2452, + 2453, + 2454, + 2455, + 2456, + 2457, + 2458, + 2459, + 2460, + 2461, + 2462, + 2463, + 2464, + 2465, + 2466, + 2467, + 2468, + 2469, + 2470, + 2471, + 2472, + 2473, + 2474, + 2475, + 2476, + 2477, + 2478, + 2479, + 2480, + 2481, + 2482, + 2483, + 4344, + 2484, + 4362, + 2485, + 2486, + 4334, + 2487, + 4364, + 2488, + 2489, + 2490, + 2491, + 2492, + 2493, + 4363, + 2494, + 4365, + 2495, + 4342, + 2496, + 2497, + 4366, + 2498, + 4368, + 2499, + 4337, + 2500, + 2501, + 2502, + 4361, + 2503, + 4369, + 2504, + 4367, + 2505, + 2506, + 2507, + 2508, + 2509, + 2510, + 2511, + 2512, + 2513, + 2514, + 2515, + 2516, + 2517, + 2518, + 2519, + 2520, + 2521, + 2522, + 2523, + 2524, + 2525, + 2526, + 2527, + 2528, + 2529, + 2530, + 2531, + 2532, + 2533, + 2534, + 2535, + 2536, + 2537, + 2538, + 2539, + 2540, + 2541, + 2542, + 2543, + 2544, + 2545, + 2546, + 2547, + 2548, + 2549, + 2550, + 2551, + 2552, + 2553, + 2554, + 2555, + 2556, + 2557, + 2558, + 2559, + 2560, + 2561, + 2562, + 2563, + 2564, + 2565, + 2566, + 2567, + 2568, + 2569, + 2570, + 2571, + 2572, + 2573, + 2574, + 2575, + 2576, + 2577, + 2578, + 2579, + 2580, + 2581, + 2582, + 2583, + 2584, + 2585, + 2586, + 2587, + 2588, + 2589, + 2590, + 2591, + 2592, + 2593, + 2594, + 2595, + 2596, + 2597, + 2598, + 2599, + 2600, + 2601, + 2602, + 2603, + 2604, + 2605, + 2606, + 2607, + 2608, + 2609, + 2610, + 2611, + 2612, + 2613, + 2614, + 2615, + 2616, + 2617, + 2618, + 2619, + 2620, + 2621, + 2622, + 2623, + 2624, + 2625, + 2626, + 2627, + 2628, + 2629, + 2630, + 2631, + 2632, + 2633, + 2634, + 2635, + 2636, + 2637, + 2638, + 2639, + 2640, + 2641, + 2642, + 2643, + 2644, + 2645, + 2646, + 2647, + 2648, + 2649, + 2650, + 2651, + 2652, + 2653, + 2654, + 2655, + 2656, + 2657, + 2658, + 2659, + 2660, + 2661, + 2662, + 2663, + 2664, + 2665, + 2666, + 2667, + 2668, + 2669, + 2670, + 2671, + 2672, + 2673, + 2674, + 2675, + 2676, + 2677, + 2678, + 2679, + 2680, + 2681, + 2682, + 2683, + 2684, + 2685, + 2686, + 2687, + 2688, + 2689, + 2690, + 2691, + 2692, + 2693, + 2694, + 2695, + 2696, + 2697, + 2698, + 2699, + 2700, + 2701, + 2702, + 2703, + 2704, + 4331, + 2705, + 2706, + 2707, + 4325, + 2708, + 2709, + 2710, + 2711, + 2712, + 2713, + 2714, + 2715, + 2716, + 2717, + 2718, + 2719, + 2720, + 2721, + 2722, + 2723, + 2724, + 2725, + 2726, + 2727, + 2728, + 2729, + 2730, + 2731, + 2732, + 2733, + 2734, + 2735, + 2736, + 2737, + 2738, + 2739, + 2740, + 2741, + 2742, + 2743, + 2744, + 2745, + 2746, + 2747, + 2748, + 2749, + 2750, + 2751, + 2752, + 2753, + 2754, + 2755, + 2756, + 2757, + 2758, + 2759, + 2760, + 2761, + 2762, + 2763, + 2764, + 2765, + 2766, + 2767, + 2768, + 2769, + 2770, + 2771, + 2772, + 4370, + 2773, + 4372, + 2774, + 2775, + 2776, + 4375, + 2777, + 2778, + 2779, + 2780, + 4376, + 2781, + 4379, + 2782, + 2783, + 2784, + 2785, + 2786, + 2787, + 2788, + 4381, + 2789, + 2790, + 2791, + 2792, + 2793, + 2794, + 2795, + 2796, + 4377, + 2797, + 2798, + 2799, + 2800, + 2801, + 4253, + 2802, + 4385, + 2803, + 2804, + 2805, + 2806, + 2807, + 2808, + 2809, + 2810, + 4392, + 2811, + 4395, + 2812, + 4396, + 2813, + 4393, + 2814, + 2815, + 2816, + 2817, + 2818, + 2819, + 2820, + 2821, + 2822, + 2823, + 2824, + 2825, + 2826, + 2827, + 2828, + 2829, + 2830, + 2831, + 2832, + 2833, + 2834, + 2835, + 2836, + 2837, + 2838, + 2839, + 2840, + 2841, + 2842, + 2843, + 2844, + 2845, + 2846, + 2847, + 2848, + 2849, + 2850, + 2851, + 2852, + 2853, + 2854, + 2855, + 2856, + 2857, + 4380, + 2858, + 2859, + 2860, + 2861, + 4397, + 2862, + 2863, + 2864, + 4371, + 2865, + 2866, + 2867, + 2868, + 2869, + 2870, + 2871, + 2872, + 2873, + 2874, + 2875, + 2876, + 2877, + 2878, + 2879, + 2880, + 2881, + 2882, + 2883, + 2884, + 2885, + 2886, + 2887, + 2888, + 2889, + 2890, + 2891, + 2892, + 2893, + 2894, + 2895, + 2896, + 2897, + 2898, + 2899, + 2900, + 2901, + 2902, + 2903, + 2904, + 2905, + 2906, + 2907, + 2908, + 2909, + 2910, + 2911, + 2912, + 2913, + 2914, + 2915, + 2916, + 2917, + 2918, + 2919, + 2920, + 2921, + 2922, + 2923, + 2924, + 2925, + 2926, + 2927, + 2928, + 2929, + 2930, + 2931, + 2932, + 2933, + 2934, + 2935, + 2936, + 2937, + 2938, + 2939, + 2940, + 2941, + 2942, + 2943, + 2944, + 2945, + 2946, + 2947, + 2948, + 2949, + 2950, + 2951, + 2952, + 2953, + 2954, + 2955, + 2956, + 2957, + 2958, + 2959, + 2960, + 2961, + 2962, + 2963, + 2964, + 2965, + 2966, + 4398, + 2967, + 4400, + 2968, + 2969, + 2970, + 2971, + 2972, + 2973, + 2974, + 2975, + 2976, + 2977, + 2978, + 2979, + 2980, + 2981, + 2982, + 2983, + 2984, + 2985, + 2986, + 2987, + 2988, + 2989, + 2990, + 2991, + 2992, + 2993, + 2994, + 2995, + 2996, + 2997, + 2998, + 2999, + 3000, + 3001, + 3002, + 3003, + 3004, + 3005, + 3006, + 3007, + 3008, + 3009, + 3010, + 3011, + 3012, + 3013, + 3014, + 3015, + 3016, + 3017, + 3018, + 3019, + 3020, + 3021, + 3022, + 3023, + 3024, + 3025, + 3026, + 3027, + 3028, + 3029, + 3030, + 3031, + 3032, + 3033, + 3034, + 3035, + 3036, + 3037, + 3038, + 3039, + 3040, + 3041, + 3042, + 3043, + 3044, + 4383, + 3045, + 3046, + 3047, + 3048, + 3049, + 4374, + 3050, + 4297, + 3051, + 3052, + 3053, + 3054, + 3055, + 3056, + 4314, + 3057, + 4373, + 3058, + 3059, + 3060, + 3061, + 3062, + 3063, + 3064, + 3065, + 4416, + 4411, + 3066, + 4414, + 3067, + 3068, + 3069, + 4299, + 3070, + 3072, + 4413, + 3075, + 3077, + 3078, + 3079, + 3082, + 3083, + 3084, + 3085, + 3086, + 4412, + 4410, + 3087, + 3088, + 3089, + 3090, + 3091, + 3092, + 3093, + 3094, + 3095, + 3096, + 3097, + 3098, + 3099, + 3100, + 3101, + 3102, + 3103, + 3104, + 3105, + 3106, + 3107, + 3108, + 3109, + 3110, + 3111, + 3112, + 3113, + 3114, + 3115, + 3116, + 3117, + 3118, + 3119, + 3120, + 3121, + 3122, + 3123, + 3124, + 3125, + 3126, + 3127, + 3128, + 3129, + 3130, + 3131, + 3132, + 3133, + 3134, + 3135, + 3136, + 3137, + 3138, + 3139, + 3140, + 3141, + 4418, + 3142, + 4401, + 3143, + 3144, + 3145, + 3146, + 4420, + 3147, + 4394, + 3148, + 3149, + 4422, + 3150, + 4421, + 3151, + 3152, + 3153, + 3154, + 4399, + 3155, + 4391, + 3156, + 4425, + 3157, + 4424, + 3158, + 3159, + 3160, + 3161, + 3162, + 3163, + 4423, + 3164, + 4426, + 3165, + 4419, + 3166, + 3167, + 3168, + 3169, + 3170, + 3171, + 3172, + 3173, + 3174, + 3175, + 3176, + 3177, + 3178, + 3179, + 3180, + 3181, + 3182, + 3183, + 3184, + 3185, + 3186, + 3187, + 3188, + 3189, + 3190, + 3191, + 3192, + 3193, + 3194, + 3195, + 3196, + 3197, + 3198, + 3199, + 3200, + 3201, + 3202, + 3203, + 3204, + 3205, + 3206, + 3207, + 3208, + 3209, + 3210, + 3211, + 3212, + 3213, + 3214, + 3215, + 3216, + 3217, + 3218, + 3219, + 3220, + 3221, + 3222, + 3223, + 3224, + 3225, + 3226, + 3227, + 3228, + 3229, + 3230, + 3231, + 3232, + 3233, + 3234, + 3235, + 3236, + 3237, + 3238, + 3239, + 3240, + 3241, + 3242, + 3243, + 3244, + 3245, + 3246, + 3247, + 3248, + 3249, + 3250, + 3251, + 3252, + 3253, + 3254, + 3255, + 3256, + 3257, + 3258, + 3259, + 3260, + 3261, + 3262, + 3263, + 3264, + 3265, + 3266, + 3267, + 3268, + 3269, + 3270, + 3271, + 3272, + 3273, + 3274, + 3275, + 3276, + 3277, + 3278, + 3279, + 3280, + 3281, + 3282, + 3283, + 3284, + 3285, + 3286, + 3287, + 3288, + 3289, + 3290, + 3291, + 3292, + 3293, + 3294, + 3295, + 3296, + 3297, + 3298, + 3299, + 3300, + 3301, + 3302, + 3303, + 3304, + 3305, + 3306, + 3307, + 3308, + 3309, + 3310, + 3311, + 3312, + 3313, + 3314, + 3315, + 3316, + 3317, + 3318, + 3319, + 3320, + 3321, + 3322, + 3323, + 3324, + 3325, + 3326, + 3327, + 3328, + 3329, + 3330, + 3331, + 3332, + 3333, + 3334, + 3335, + 3336, + 3337, + 3338, + 3339, + 3340, + 3341, + 3342, + 3343, + 3344, + 3345, + 3346, + 3347, + 3348, + 3349, + 3350, + 3351, + 3352, + 3353, + 3354, + 3355, + 3356, + 3357, + 3358, + 3359, + 3360, + 3361, + 3362, + 3363, + 3364, + 4384, + 3365, + 3366, + 4382, + 3367, + 3368, + 3369, + 3370, + 3371, + 3372, + 3373, + 3374, + 3375, + 3376, + 3377, + 3378, + 3379, + 3380, + 3381, + 3382, + 3383, + 3384, + 3385, + 3386, + 3387, + 3388, + 3389, + 3390, + 3391, + 3392, + 3393, + 3394, + 3395, + 3396, + 3397, + 3398, + 3399, + 3400, + 3401, + 3402, + 3403, + 3404, + 3405, + 3406, + 3407, + 3408, + 3409, + 3410, + 3411, + 3412, + 3413, + 3414, + 3415, + 3416, + 3417; + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.970101, + 0.970101, + 0.970101, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999437, + 0.999437, + 0.999437, + 0.999437, + 0.552841, + 0.552841, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999259, + 0.999259, + 0.999259, + 0.999259, + 0.999259, + 0.547701, + 0.547701, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999744, + 0.999735, + 0.887760, + 0.887760, + 0.497118, + 0.497118, + 0.339849, + 0.339849, + 0.339658, + 0.339658, + 0.498042, + 0.498042, + 0.889854, + 0.889854, + 0.693299, + 0.692637, + 0.033561, + 0.033541, + 0.999907, + 0.999907, + 0.999906, + 0.999906, + 0.999362, + 0.999363, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999999, + 0.993695, + 0.713304, + 0.713304, + 0.897813, + 0.897813, + 1.000000, + 0.999983, + 0.999999, + 0.999999, + 0.999942, + 0.999942, + 0.999393, + 0.999732, + 0.567551, + 0.515509, + 0.855685, + 0.985010, + 0.985010, + 0.498224, + 0.498224, + 0.310874, + 0.383672, + 0.501663, + 0.501663, + 0.707005, + 0.707005, + 0.680489, + 0.510297, + 0.029527, + 0.029527, + 0.013410, + 0.956949, + 0.651153, + 0.930744, + 1.000000, + 1.000000, + 0.999386, + 0.999386, + 0.999386, + 0.999386, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.888821, + 0.888821, + 0.704999, + 0.704999, + 0.992606, + 0.999999, + 1.000000, + 1.000000, + 0.999388, + 0.999941, + 0.999941, + 0.999999, + 0.999999, + 0.999982, + 0.999729, + 0.562194, + 0.982777, + 0.848121, + 0.513370, + 0.669851, + 0.696438, + 0.696438, + 0.696438, + 0.501175, + 0.501175, + 0.384953, + 0.312190, + 0.498315, + 0.498315, + 0.508731, + 0.029902, + 0.029902, + 0.013492, + 0.953945, + 0.928954, + 0.647332, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 0.999125, + 0.999125, + 0.999125, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000; + 0.000000,-0.000002,1.278853,0.000000,1.112235,-0.156313,-0.000000,0.000000,0.204616,1.455927,0.000002,0.000000,-61.950306,-62.105236,-0.142288,1.000000;; + } + } + } + } + + Frame Box01 { + + + FrameTransformMatrix { + -1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.341751,858.815247,1.000000;; + } + + Frame Bip01 { + + + FrameTransformMatrix { + 0.186552,-0.974653,0.123489,0.000000,0.982171,0.187991,0.000000,0.000000,-0.023215,0.121288,0.992346,0.000000,-88.977890,-857.346008,247.541595,1.000000;; + } + + Frame Bip01_Footsteps { + + + FrameTransformMatrix { + 0.186552,0.982171,-0.023215,0.000000,-0.974653,0.187991,0.121288,0.000000,0.123489,-0.000000,0.992346,0.000000,-31.624149,0.000000,-254.128143,1.000000;; + } + } + + Frame Bip01_Pelvis { + + + FrameTransformMatrix { + -0.000000,0.011807,0.999930,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999930,-0.011807,0.000000,-2.454305,-1.950977,-0.000005,1.000000;; + } + + Frame Bip01_Spine { + + + FrameTransformMatrix { + 0.999137,0.041531,0.000982,0.000000,-0.040353,0.975880,-0.214545,0.000000,-0.009868,0.214320,0.976714,0.000000,27.422213,8.709480,-0.319006,1.000000;; + } + + Frame Bip01_Spine1 { + + + FrameTransformMatrix { + 0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178080,-0.022084,0.000000,1.000000;; + } + + Frame Bip01_Spine2 { + + + FrameTransformMatrix { + 0.999958,0.008483,0.003477,0.000000,-0.008313,0.998890,-0.046374,0.000000,-0.003867,0.046343,0.998918,0.000000,28.182159,-0.022430,0.001040,1.000000;; + } + + Frame Bip01_Spine3 { + + + FrameTransformMatrix { + 0.999837,-0.017696,0.003477,0.000000,0.017838,0.998765,-0.046374,0.000000,-0.002652,0.046428,0.998918,0.000000,28.181417,-0.033880,0.001568,1.000000;; + } + + Frame Bip01_Neck { + + + FrameTransformMatrix { + 0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566055,-0.019138,0.000001,1.000000;; + } + + Frame Bip01_Head { + + + FrameTransformMatrix { + 0.979775,-0.188667,-0.066683,0.000000,0.195389,0.973921,0.115333,0.000000,0.043184,-0.126029,0.991086,0.000000,27.900173,0.000003,0.000000,1.000000;; + } + + Frame Dummy21 { + + + FrameTransformMatrix { + 1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615768,0.000027,0.000002,1.000000;; + } + } + } + + Frame Bip01_L_Clavicle { + + + FrameTransformMatrix { + -0.185356,0.308957,0.932839,0.000000,-0.499811,-0.846968,0.181203,0.000000,0.846069,-0.432656,0.311411,0.000000,-12.374969,4.006883,8.346215,1.000000;; + } + + Frame Bip01_L_UpperArm { + + + FrameTransformMatrix { + 0.640423,0.117307,-0.759011,0.000000,0.064965,0.976451,0.205728,0.000000,0.765270,-0.181062,0.617720,0.000000,31.000208,-0.000032,-0.000004,1.000000;; + } + + Frame Bip01_L_Forearm { + + + FrameTransformMatrix { + 0.485335,-0.874328,-0.000000,0.000000,0.874328,0.485335,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202522,-0.000023,0.000014,1.000000;; + } + + Frame Bip01_L_Hand { + + + FrameTransformMatrix { + 0.999511,-0.027531,-0.014824,0.000000,-0.015327,-0.018154,-0.999718,0.000000,0.027254,0.999456,-0.018567,0.000000,61.671467,0.000001,-0.000001,1.000000;; + } + + Frame Bip01_L_Finger0 { + + + FrameTransformMatrix { + 0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410522,3.054963,-10.755418,1.000000;; + } + + Frame Bip01_L_Finger01 { + + + FrameTransformMatrix { + 1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075084,0.000006,-0.000007,1.000000;; + } + + Frame Bip01_L_Finger02 { + + + FrameTransformMatrix { + 1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961566,-0.000008,0.000006,1.000000;; + } + + Frame Dummy06 { + + + FrameTransformMatrix { + 1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961566,-0.000008,0.000003,1.000000;; + } + } + } + } + } + + Frame Bip01_L_Finger1 { + + + FrameTransformMatrix { + 1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087988,0.354694,-0.505022,1.000000;; + } + + Frame Bip01_L_Finger11 { + + + FrameTransformMatrix { + 1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300090,-0.000022,-0.000024,1.000000;; + } + + Frame Bip01_L_Finger12 { + + + FrameTransformMatrix { + 1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850065,0.000028,0.000040,1.000000;; + } + + Frame Dummy03 { + + + FrameTransformMatrix { + 1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207734,-0.000002,-0.000004,1.000000;; + } + } + } + } + } + } + } + } + } + + Frame Bip01_R_Clavicle { + + + FrameTransformMatrix { + -0.397155,0.379708,-0.835518,0.000000,-0.502616,-0.851720,-0.148157,0.000000,-0.767883,0.361103,0.529112,0.000000,-12.374941,4.006959,-8.346190,1.000000;; + } + + Frame Bip01_R_UpperArm { + + + FrameTransformMatrix { + 0.532891,0.645602,0.547015,0.000000,-0.380503,0.760229,-0.526564,0.000000,-0.755807,0.072461,0.650772,0.000000,31.000195,-0.000004,0.000004,1.000000;; + } + + Frame Bip01_R_Forearm { + + + FrameTransformMatrix { + 0.881719,-0.471776,0.000000,0.000000,0.471776,0.881718,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202530,-0.000026,0.000000,1.000000;; + } + + Frame Bip01_R_Hand { + + + FrameTransformMatrix { + 0.999848,-0.010016,0.014267,0.000000,-0.014446,-0.018025,0.999733,0.000000,-0.009756,-0.999787,-0.018167,0.000000,61.671482,0.000009,-0.000000,1.000000;; + } + + Frame Bip01_R_Finger0 { + + + FrameTransformMatrix { + 0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410507,3.054970,10.755430,1.000000;; + } + + Frame Bip01_R_Finger01 { + + + FrameTransformMatrix { + 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075073,0.000020,-0.000001,1.000000;; + } + + Frame Bip01_R_Finger02 { + + + FrameTransformMatrix { + 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961570,-0.000010,-0.000003,1.000000;; + } + + Frame Dummy01 { + + + FrameTransformMatrix { + 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,5.961568,-0.000011,0.000000,1.000000;; + } + } + } + } + } + + Frame Bip01_R_Finger1 { + + + FrameTransformMatrix { + 1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087997,0.354687,0.504994,1.000000;; + } + + Frame Bip01_R_Finger11 { + + + FrameTransformMatrix { + 1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300055,-0.000003,-0.000036,1.000000;; + } + + Frame Bip01_R_Finger12 { + + + FrameTransformMatrix { + 1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850063,0.000009,0.000012,1.000000;; + } + + Frame Dummy02 { + + + FrameTransformMatrix { + 1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,11.207763,0.000001,-0.000002,1.000000;; + } + } + } + } + } + } + } + } + } + } + } + } + } + + Frame Bip01_L_Thigh { + + + FrameTransformMatrix { + -0.959397,-0.281208,0.021883,0.000000,-0.279994,0.958874,0.046525,0.000000,-0.034066,0.038509,-0.998677,0.000000,-27.730272,-13.958670,28.295168,1.000000;; + } + + Frame Bip01_L_Calf { + + + FrameTransformMatrix { + 0.912034,-0.410114,-0.000000,0.000000,0.410114,0.912034,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231491,-0.000008,-0.000001,1.000000;; + } + + Frame Bip01_L_Foot { + + + FrameTransformMatrix { + 0.832169,0.546757,0.092472,0.000000,-0.549113,0.835748,0.000044,0.000000,-0.077259,-0.050814,0.995715,0.000000,119.231468,-0.000006,0.000000,1.000000;; + } + + Frame Bip01_L_Toe0 { + + + FrameTransformMatrix { + 0.000000,1.000000,0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423262,34.577110,0.000002,1.000000;; + } + + Frame Dummy16 { + + + FrameTransformMatrix { + 1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,15.738586,0.000005,-0.000001,1.000000;; + } + } + } + } + } + } + + Frame Bip01_R_Thigh { + + + FrameTransformMatrix { + -0.965965,0.253205,-0.052900,0.000000,0.253587,0.886612,-0.386799,0.000000,-0.051038,-0.387049,-0.920645,0.000000,-27.789658,-0.963900,-30.864017,1.000000;; + } + + Frame Bip01_R_Calf { + + + FrameTransformMatrix { + 1.000000,-0.000691,-0.000000,0.000000,0.000691,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231522,0.000021,-0.000011,1.000000;; + } + + Frame Bip01_R_Foot { + + + FrameTransformMatrix { + 0.988831,0.124156,0.082452,0.000000,-0.122246,0.992109,-0.027835,0.000000,-0.085257,0.017445,0.996206,0.000000,119.231476,-0.000039,0.000023,1.000000;; + } + + Frame Bip01_R_Toe0 { + + + FrameTransformMatrix { + 0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423260,34.577152,-0.000010,1.000000;; + } + + Frame Dummy11 { + + + FrameTransformMatrix { + 1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738579,0.000004,-0.000012,1.000000;; + } + } + } + } + } + } + } + } + } + } +} + +AnimationSet { + + + Animation { + + + AnimationKey { + 4; + 2; + 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000;;, + 4960;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000;;; + } + { Scene_Root } + } + + Animation { + + + AnimationKey { + 4; + 2; + 0;16;1.278853,0.000000,-0.000000,0.000000,0.000000,0.000000,1.123165,0.000000,0.000000,-1.470235,0.000000,0.000000,0.135977,2.027985,133.967667,1.000000;;, + 4960;16;1.278853,0.000000,-0.000000,0.000000,0.000000,0.000000,1.123165,0.000000,0.000000,-1.470235,0.000000,0.000000,0.135977,2.027985,133.967667,1.000000;;; + } + { body } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-245.951797,351.625824,1.000000;;, + 80;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-245.958298,360.078979,1.000000;;, + 160;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-245.964798,368.532135,1.000000;;, + 240;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-245.971298,376.985291,1.000000;;, + 320;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-245.977798,385.438446,1.000000;;, + 400;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-245.984299,393.891602,1.000000;;, + 480;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-245.990799,402.344757,1.000000;;, + 560;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-245.997299,410.797913,1.000000;;, + 640;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.003784,419.251099,1.000000;;, + 720;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.010284,427.704254,1.000000;;, + 800;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.016785,436.157410,1.000000;;, + 880;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.023285,444.610565,1.000000;;, + 960;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.029785,453.063721,1.000000;;, + 1040;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.036285,461.516876,1.000000;;, + 1120;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.042786,469.970032,1.000000;;, + 1200;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.049286,478.423187,1.000000;;, + 1280;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.055786,486.876343,1.000000;;, + 1360;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.062286,495.329498,1.000000;;, + 1440;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.068787,503.782654,1.000000;;, + 1520;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.075287,512.235779,1.000000;;, + 1600;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.081787,520.688965,1.000000;;, + 1680;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.088287,529.142090,1.000000;;, + 1760;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.094788,537.595276,1.000000;;, + 1840;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.101273,546.048462,1.000000;;, + 1920;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.107773,554.501587,1.000000;;, + 2000;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.114273,562.954773,1.000000;;, + 2080;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.120773,571.407898,1.000000;;, + 2160;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.127274,579.861084,1.000000;;, + 2240;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.133774,588.314209,1.000000;;, + 2320;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.140274,596.767395,1.000000;;, + 2400;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.146774,605.220520,1.000000;;, + 2480;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.153275,613.673706,1.000000;;, + 2560;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.159775,622.126892,1.000000;;, + 2640;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.166275,630.580017,1.000000;;, + 2720;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.172775,639.033142,1.000000;;, + 2800;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.179276,647.486328,1.000000;;, + 2880;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.185776,655.939514,1.000000;;, + 2960;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.192276,664.392639,1.000000;;, + 3040;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.198761,672.845764,1.000000;;, + 3120;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.205261,681.298950,1.000000;;, + 3200;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.211761,689.752136,1.000000;;, + 3280;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.218262,698.205261,1.000000;;, + 3360;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.224762,706.658386,1.000000;;, + 3440;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.231262,715.111572,1.000000;;, + 3520;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.237762,723.564758,1.000000;;, + 3600;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.244263,732.017883,1.000000;;, + 3680;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.250763,740.471069,1.000000;;, + 3760;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.257263,748.924194,1.000000;;, + 3840;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.263763,757.377380,1.000000;;, + 3920;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.270264,765.830505,1.000000;;, + 4000;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.276764,774.283691,1.000000;;, + 4080;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.283264,782.736816,1.000000;;, + 4160;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.289764,791.190002,1.000000;;, + 4240;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.296249,799.643127,1.000000;;, + 4320;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.302750,808.096313,1.000000;;, + 4400;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.309250,816.549500,1.000000;;, + 4480;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.315750,825.002625,1.000000;;, + 4560;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.322250,833.455750,1.000000;;, + 4640;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.328751,841.908936,1.000000;;, + 4720;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.335251,850.362122,1.000000;;, + 4800;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-246.341751,858.815247,1.000000;;, + 4960;16;-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-88.696747,-245.951797,351.625824,1.000000;;; + } + { Box01 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.215193,-0.969920,0.113783,0.000000,0.976260,0.216600,-0.000000,0.000000,-0.024646,0.111082,0.993506,0.000000,-88.995270,-350.280182,247.734116,1.000000;;, + 80;16;0.230210,-0.966046,0.117296,0.000000,0.972762,0.231808,-0.000015,0.000000,-0.027176,0.114104,0.993097,0.000000,-89.026062,-358.696838,245.527908,1.000000;;, + 160;16;0.245161,-0.961926,0.120806,0.000000,0.969026,0.246960,-0.000085,0.000000,-0.029752,0.117085,0.992676,0.000000,-89.057129,-367.113770,243.259003,1.000000;;, + 240;16;0.260919,-0.957329,0.124270,0.000000,0.964815,0.262931,-0.000218,0.000000,-0.032466,0.119955,0.992248,0.000000,-89.090034,-375.532227,240.737289,1.000000;;, + 320;16;0.274853,-0.952953,0.127816,0.000000,0.960847,0.277077,-0.000391,0.000000,-0.035042,0.122919,0.991798,0.000000,-89.121216,-383.949402,238.279861,1.000000;;, + 400;16;0.284678,-0.949573,0.131414,0.000000,0.957902,0.287096,-0.000570,0.000000,-0.037187,0.126044,0.991327,0.000000,-89.147224,-392.364716,236.076599,1.000000;;, + 480;16;0.290388,-0.947267,0.135499,0.000000,0.956114,0.292995,-0.000732,0.000000,-0.039008,0.129765,0.990777,0.000000,-89.169243,-400.772797,234.318848,1.000000;;, + 560;16;0.290787,-0.946384,0.140711,0.000000,0.955929,0.293596,-0.000834,0.000000,-0.040523,0.134752,0.990050,0.000000,-89.187599,-409.165558,233.295410,1.000000;;, + 640;16;0.287101,-0.946645,0.146409,0.000000,0.956994,0.290106,-0.000860,0.000000,-0.041660,0.140360,0.989224,0.000000,-89.201378,-417.550812,232.904465,1.000000;;, + 720;16;0.280185,-0.947747,0.152550,0.000000,0.959005,0.283386,-0.000790,0.000000,-0.042482,0.146518,0.988295,0.000000,-89.211227,-425.929321,233.223892,1.000000;;, + 800;16;0.269861,-0.949850,0.157988,0.000000,0.961957,0.273201,-0.000596,0.000000,-0.042596,0.152138,0.987441,0.000000,-89.212715,-434.314423,234.003555,1.000000;;, + 880;16;0.255996,-0.953099,0.161456,0.000000,0.965782,0.259355,-0.000282,0.000000,-0.041606,0.156003,0.986880,0.000000,-89.200623,-442.720734,235.017471,1.000000;;, + 960;16;0.239263,-0.957127,0.163283,0.000000,0.970142,0.242538,0.000126,0.000000,-0.039723,0.158377,0.986579,0.000000,-89.177910,-451.145142,236.268890,1.000000;;, + 1040;16;0.220092,-0.961751,0.163077,0.000000,0.974779,0.223171,0.000573,0.000000,-0.036945,0.158838,0.986613,0.000000,-89.144325,-459.592773,237.701111,1.000000;;, + 1120;16;0.199072,-0.966547,0.161733,0.000000,0.979407,0.201892,0.001023,0.000000,-0.033641,0.158199,0.986834,0.000000,-89.104233,-468.053619,239.267197,1.000000;;, + 1200;16;0.176961,-0.971115,0.160062,0.000000,0.983756,0.179506,0.001467,0.000000,-0.030157,0.157202,0.987106,0.000000,-89.062035,-476.518890,240.917862,1.000000;;, + 1280;16;0.153774,-0.975404,0.157925,0.000000,0.987752,0.156024,0.001873,0.000000,-0.026467,0.155703,0.987449,0.000000,-89.017326,-484.990173,242.604843,1.000000;;, + 1360;16;0.129723,-0.979294,0.155422,0.000000,0.991292,0.131664,0.002220,0.000000,-0.022637,0.153781,0.987846,0.000000,-88.970947,-493.466614,244.280289,1.000000;;, + 1440;16;0.105024,-0.982683,0.152656,0.000000,0.994293,0.106652,0.002489,0.000000,-0.018727,0.151523,0.988276,0.000000,-88.923561,-501.947113,245.893738,1.000000;;, + 1520;16;0.079902,-0.985493,0.149728,0.000000,0.996693,0.081216,0.002672,0.000000,-0.014793,0.149019,0.988724,0.000000,-88.875931,-510.430634,247.395233,1.000000;;, + 1600;16;0.054583,-0.987668,0.146741,0.000000,0.998450,0.055589,0.002762,0.000000,-0.010885,0.146363,0.989171,0.000000,-88.828560,-518.915955,248.734818,1.000000;;, + 1680;16;0.029299,-0.989173,0.143799,0.000000,0.999546,0.030007,0.002762,0.000000,-0.007047,0.143652,0.989603,0.000000,-88.782097,-527.401978,249.862305,1.000000;;, + 1760;16;0.004282,-0.990000,0.141004,0.000000,0.999985,0.004707,0.002680,0.000000,-0.003317,0.140991,0.990005,0.000000,-88.736885,-535.887329,250.727417,1.000000;;, + 1840;16;-0.020233,-0.990161,0.138461,0.000000,0.999795,-0.020076,0.002532,0.000000,0.000273,0.138484,0.990365,0.000000,-88.693428,-544.370850,251.288864,1.000000;;, + 1920;16;-0.044014,-0.989693,0.136270,0.000000,0.999024,-0.044107,0.002338,0.000000,0.003697,0.136240,0.990669,0.000000,-88.651924,-552.851196,251.468933,1.000000;;, + 2000;16;-0.066451,-0.988672,0.134580,0.000000,0.997766,-0.066772,0.002131,0.000000,0.006879,0.134421,0.990900,0.000000,-88.613358,-561.326355,251.154114,1.000000;;, + 2080;16;-0.088458,-0.987113,0.133352,0.000000,0.996030,-0.088998,0.001921,0.000000,0.009972,0.132992,0.991067,0.000000,-88.575897,-569.796814,250.409897,1.000000;;, + 2160;16;-0.110697,-0.984964,0.132636,0.000000,0.993768,-0.111454,0.001725,0.000000,0.013084,0.132000,0.991163,0.000000,-88.538185,-578.261963,249.224899,1.000000;;, + 2240;16;-0.133303,-0.982204,0.132311,0.000000,0.990942,-0.134282,0.001543,0.000000,0.016252,0.131318,0.991207,0.000000,-88.499825,-586.723389,247.716156,1.000000;;, + 2320;16;-0.156984,-0.978703,0.132274,0.000000,0.987407,-0.158195,0.001366,0.000000,0.019588,0.130823,0.991212,0.000000,-88.459404,-595.182617,245.969635,1.000000;;, + 2400;16;-0.180673,-0.974575,0.132518,0.000000,0.983275,-0.182121,0.001212,0.000000,0.022953,0.130521,0.991180,0.000000,-88.418640,-603.639404,244.067245,1.000000;;, + 2480;16;-0.203757,-0.969944,0.133012,0.000000,0.978669,-0.205441,0.001087,0.000000,0.026272,0.130397,0.991114,0.000000,-88.378433,-612.094116,242.093201,1.000000;;, + 2560;16;-0.225637,-0.964990,0.133725,0.000000,0.973766,-0.227551,0.000998,0.000000,0.029466,0.130442,0.991018,0.000000,-88.339745,-620.546692,240.126892,1.000000;;, + 2640;16;-0.245728,-0.959945,0.134624,0.000000,0.968795,-0.247860,0.000949,0.000000,0.032457,0.130656,0.990896,0.000000,-88.303505,-628.997253,238.248978,1.000000;;, + 2720;16;-0.263458,-0.955082,0.135677,0.000000,0.964030,-0.265793,0.000938,0.000000,0.035166,0.131044,0.990753,0.000000,-88.270691,-637.445679,236.540161,1.000000;;, + 2800;16;-0.278272,-0.950703,0.136852,0.000000,0.959769,-0.280788,0.000962,0.000000,0.037512,0.131614,0.990591,0.000000,-88.242264,-645.891968,235.080368,1.000000;;, + 2880;16;-0.289622,-0.947123,0.138118,0.000000,0.956329,-0.292289,0.001013,0.000000,0.039411,0.132380,0.990415,0.000000,-88.219269,-654.335876,233.952332,1.000000;;, + 2960;16;-0.296833,-0.944706,0.139362,0.000000,0.954060,-0.299614,0.001070,0.000000,0.040744,0.133278,0.990241,0.000000,-88.203102,-662.778076,233.258194,1.000000;;, + 3040;16;-0.299743,-0.943574,0.140795,0.000000,0.953116,-0.302602,0.001152,0.000000,0.041518,0.134539,0.990038,0.000000,-88.193741,-671.216003,233.019211,1.000000;;, + 3120;16;-0.297684,-0.943957,0.142584,0.000000,0.953755,-0.300582,0.001269,0.000000,0.041660,0.136368,0.989782,0.000000,-88.191994,-679.646973,233.327316,1.000000;;, + 3200;16;-0.291409,-0.945585,0.144741,0.000000,0.955708,-0.294313,0.001411,0.000000,0.041265,0.138741,0.989469,0.000000,-88.196808,-688.071472,234.072937,1.000000;;, + 3280;16;-0.281246,-0.948245,0.147418,0.000000,0.958786,-0.284126,0.001582,0.000000,0.040385,0.141787,0.989073,0.000000,-88.207474,-696.487671,235.200226,1.000000;;, + 3360;16;-0.267718,-0.951692,0.150366,0.000000,0.962706,-0.270543,0.001731,0.000000,0.039033,0.145222,0.988629,0.000000,-88.223839,-704.899170,236.639908,1.000000;;, + 3440;16;-0.251299,-0.955670,0.153436,0.000000,0.967193,-0.254036,0.001827,0.000000,0.037233,0.148862,0.988157,0.000000,-88.245697,-713.308228,238.327179,1.000000;;, + 3520;16;-0.232467,-0.959934,0.156480,0.000000,0.971974,-0.235082,0.001843,0.000000,0.035017,0.152523,0.987679,0.000000,-88.272491,-721.717102,240.193939,1.000000;;, + 3600;16;-0.211709,-0.964255,0.159346,0.000000,0.976795,-0.214171,0.001762,0.000000,0.032428,0.156021,0.987221,0.000000,-88.303909,-730.127869,242.173676,1.000000;;, + 3680;16;-0.189524,-0.968439,0.161884,0.000000,0.981432,-0.191803,0.001579,0.000000,0.029521,0.159178,0.986808,0.000000,-88.339073,-738.542786,244.197083,1.000000;;, + 3760;16;-0.166420,-0.972331,0.163945,0.000000,0.985703,-0.168490,0.001297,0.000000,0.026362,0.161817,0.986469,0.000000,-88.377380,-746.964050,246.194870,1.000000;;, + 3840;16;-0.142916,-0.975820,0.165378,0.000000,0.989467,-0.144756,0.000932,0.000000,0.023030,0.163769,0.986230,0.000000,-88.417694,-755.393494,248.100037,1.000000;;, + 3920;16;-0.120009,-0.978789,0.166042,0.000000,0.992578,-0.121612,0.000515,0.000000,0.019688,0.164871,0.986119,0.000000,-88.458206,-763.833313,249.845062,1.000000;;, + 4000;16;-0.096823,-0.981400,0.165766,0.000000,0.995170,-0.098171,0.000058,0.000000,0.016217,0.164971,0.986165,0.000000,-88.500229,-772.285217,251.362381,1.000000;;, + 4080;16;-0.072995,-0.983711,0.164270,0.000000,0.997253,-0.074069,-0.000416,0.000000,0.012576,0.163788,0.986415,0.000000,-88.544342,-780.752625,252.601303,1.000000;;, + 4160;16;-0.047948,-0.985668,0.161738,0.000000,0.998812,-0.048729,-0.000865,0.000000,0.008734,0.161504,0.986833,0.000000,-88.590874,-789.233582,253.443695,1.000000;;, + 4240;16;-0.020710,-0.987195,0.158170,0.000000,0.999775,-0.021175,-0.001258,0.000000,0.004591,0.158109,0.987411,0.000000,-88.641014,-797.727844,253.722046,1.000000;;, + 4320;16;0.007899,-0.988064,0.153839,0.000000,0.999969,0.007754,-0.001540,0.000000,0.000329,0.153846,0.988095,0.000000,-88.692696,-806.232605,253.533524,1.000000;;, + 4400;16;0.037495,-0.988134,0.148950,0.000000,0.999289,0.037666,-0.001676,0.000000,-0.003954,0.148907,0.988843,0.000000,-88.744514,-814.745667,252.858902,1.000000;;, + 4480;16;0.067688,-0.987302,0.143713,0.000000,0.997673,0.068160,-0.001645,0.000000,-0.008171,0.143490,0.989618,0.000000,-88.795670,-823.264404,251.879715,1.000000;;, + 4560;16;0.098083,-0.985516,0.138337,0.000000,0.995103,0.098835,-0.001442,0.000000,-0.012252,0.137801,0.990384,0.000000,-88.845009,-831.786499,250.727203,1.000000;;, + 4640;16;0.128286,-0.982774,0.133035,0.000000,0.991606,0.129293,-0.001079,0.000000,-0.016140,0.132057,0.991111,0.000000,-88.892197,-840.309204,249.532562,1.000000;;, + 4720;16;0.157601,-0.979148,0.128187,0.000000,0.987305,0.158835,-0.000603,0.000000,-0.019770,0.126655,0.991750,0.000000,-88.935722,-848.828125,248.514465,1.000000;;, + 4800;16;0.186552,-0.974653,0.123489,0.000000,0.982171,0.187991,0.000000,0.000000,-0.023215,0.121288,0.992346,0.000000,-88.977890,-857.346008,247.541595,1.000000;;, + 4960;16;0.215193,-0.969920,0.113783,0.000000,0.976260,0.216600,-0.000000,0.000000,-0.024646,0.111082,0.993506,0.000000,-88.995270,-350.280182,247.734116,1.000000;;; + } + { Bip01 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.215193,0.976260,-0.024646,0.000000,-0.969920,0.216600,0.111082,0.000000,0.113783,-0.000000,0.993506,0.000000,-28.695675,0.000000,-250.557556,1.000000;;, + 80;16;0.230210,0.972762,-0.027176,0.000000,-0.966046,0.231808,0.114104,0.000000,0.117296,-0.000015,0.993097,0.000000,-28.930368,0.003710,-244.942093,1.000000;;, + 160;16;0.245161,0.969026,-0.029752,0.000000,-0.961926,0.246960,0.117085,0.000000,0.120806,-0.000085,0.992676,0.000000,-29.871046,0.021084,-245.453903,1.000000;;, + 240;16;0.260919,0.964815,-0.032466,0.000000,-0.957329,0.262931,0.119955,0.000000,0.124270,-0.000218,0.992248,0.000000,-30.679300,0.053845,-244.962097,1.000000;;, + 320;16;0.274853,0.960848,-0.035042,0.000000,-0.952953,0.277077,0.122919,0.000000,0.127816,-0.000391,0.991798,0.000000,-31.485676,0.096353,-244.314850,1.000000;;, + 400;16;0.284678,0.957902,-0.037187,0.000000,-0.949573,0.287096,0.126044,0.000000,0.131414,-0.000570,0.991327,0.000000,-32.236568,0.139836,-243.178284,1.000000;;, + 480;16;0.290388,0.956114,-0.039008,0.000000,-0.947267,0.292995,0.129765,0.000000,0.135499,-0.000732,0.990777,0.000000,-33.082916,0.178625,-241.903809,1.000000;;, + 560;16;0.290787,0.955929,-0.040523,0.000000,-0.946384,0.293596,0.134752,0.000000,0.140711,-0.000834,0.990050,0.000000,-34.169113,0.202512,-240.416290,1.000000;;, + 640;16;0.287101,0.956994,-0.041660,0.000000,-0.946645,0.290106,0.140360,0.000000,0.146409,-0.000860,0.989224,0.000000,-35.483067,0.208447,-239.743652,1.000000;;, + 720;16;0.280185,0.959006,-0.042482,0.000000,-0.947747,0.283386,0.146518,0.000000,0.152550,-0.000790,0.988295,0.000000,-36.856628,0.190942,-238.775558,1.000000;;, + 800;16;0.269861,0.961957,-0.042596,0.000000,-0.949850,0.273201,0.152138,0.000000,0.157988,-0.000596,0.987441,0.000000,-38.280083,0.144505,-239.254517,1.000000;;, + 880;16;0.255996,0.965782,-0.041605,0.000000,-0.953099,0.259355,0.156003,0.000000,0.161456,-0.000282,0.986880,0.000000,-39.272747,0.068616,-240.050232,1.000000;;, + 960;16;0.239263,0.970142,-0.039723,0.000000,-0.957127,0.242538,0.158377,0.000000,0.163283,0.000126,0.986579,0.000000,-39.905502,-0.030840,-241.114822,1.000000;;, + 1040;16;0.220092,0.974779,-0.036945,0.000000,-0.961751,0.223171,0.158838,0.000000,0.163077,0.000573,0.986613,0.000000,-40.085278,-0.140866,-242.514786,1.000000;;, + 1120;16;0.199072,0.979407,-0.033641,0.000000,-0.966547,0.201892,0.158199,0.000000,0.161733,0.001023,0.986834,0.000000,-40.017071,-0.253015,-244.168747,1.000000;;, + 1200;16;0.176961,0.983756,-0.030157,0.000000,-0.971115,0.179506,0.157202,0.000000,0.160062,0.001467,0.987106,0.000000,-39.888794,-0.365580,-245.995041,1.000000;;, + 1280;16;0.153774,0.987751,-0.026467,0.000000,-0.975404,0.156024,0.155703,0.000000,0.157925,0.001873,0.987449,0.000000,-39.636044,-0.470161,-247.830200,1.000000;;, + 1360;16;0.129723,0.991292,-0.022637,0.000000,-0.979294,0.131664,0.153781,0.000000,0.155422,0.002220,0.987846,0.000000,-39.283993,-0.561041,-249.684158,1.000000;;, + 1440;16;0.105024,0.994293,-0.018727,0.000000,-0.982683,0.106652,0.151523,0.000000,0.152656,0.002489,0.988276,0.000000,-38.839005,-0.633379,-251.439117,1.000000;;, + 1520;16;0.079902,0.996693,-0.014793,0.000000,-0.985493,0.081216,0.149019,0.000000,0.149728,0.002672,0.988724,0.000000,-38.326859,-0.683906,-253.090744,1.000000;;, + 1600;16;0.054583,0.998450,-0.010885,0.000000,-0.987668,0.055589,0.146363,0.000000,0.146741,0.002762,0.989171,0.000000,-37.777111,-0.711023,-254.653427,1.000000;;, + 1680;16;0.029299,0.999546,-0.007047,0.000000,-0.989173,0.030007,0.143652,0.000000,0.143798,0.002762,0.989603,0.000000,-37.200829,-0.714508,-256.011414,1.000000;;, + 1760;16;0.004282,0.999985,-0.003317,0.000000,-0.990000,0.004707,0.140991,0.000000,0.141004,0.002680,0.990005,0.000000,-36.619717,-0.696093,-257.110870,1.000000;;, + 1840;16;-0.020233,0.999795,0.000273,0.000000,-0.990161,-0.020076,0.138484,0.000000,0.138461,0.002532,0.990365,0.000000,-36.057411,-0.659389,-257.906921,1.000000;;, + 1920;16;-0.044014,0.999024,0.003697,0.000000,-0.989694,-0.044107,0.136240,0.000000,0.136270,0.002338,0.990669,0.000000,-35.521038,-0.609429,-258.233765,1.000000;;, + 2000;16;-0.066451,0.997766,0.006879,0.000000,-0.988672,-0.066772,0.134421,0.000000,0.134580,0.002131,0.990900,0.000000,-35.047722,-0.554941,-258.053131,1.000000;;, + 2080;16;-0.088458,0.996030,0.009972,0.000000,-0.987113,-0.088998,0.132992,0.000000,0.133352,0.001921,0.991067,0.000000,-34.556820,-0.497754,-256.825684,1.000000;;, + 2160;16;-0.110697,0.993768,0.013084,0.000000,-0.984964,-0.111454,0.132000,0.000000,0.132636,0.001725,0.991163,0.000000,-34.142933,-0.444083,-255.143707,1.000000;;, + 2240;16;-0.133303,0.990942,0.016252,0.000000,-0.982204,-0.134282,0.131318,0.000000,0.132311,0.001543,0.991207,0.000000,-33.727978,-0.393298,-252.673233,1.000000;;, + 2320;16;-0.156984,0.987407,0.019588,0.000000,-0.978703,-0.158195,0.130822,0.000000,0.132274,0.001366,0.991212,0.000000,-33.356308,-0.344591,-249.960281,1.000000;;, + 2400;16;-0.180673,0.983275,0.022953,0.000000,-0.974575,-0.182121,0.130521,0.000000,0.132518,0.001212,0.991180,0.000000,-33.095207,-0.302633,-247.538528,1.000000;;, + 2480;16;-0.203757,0.978669,0.026272,0.000000,-0.969944,-0.205441,0.130397,0.000000,0.133012,0.001087,0.991114,0.000000,-32.885395,-0.268781,-245.038528,1.000000;;, + 2560;16;-0.225637,0.973766,0.029466,0.000000,-0.964990,-0.227551,0.130442,0.000000,0.133725,0.000998,0.991018,0.000000,-32.691967,-0.244099,-242.275589,1.000000;;, + 2640;16;-0.245728,0.968795,0.032457,0.000000,-0.959945,-0.247860,0.130656,0.000000,0.134624,0.000949,0.990896,0.000000,-32.764847,-0.230935,-241.164581,1.000000;;, + 2720;16;-0.263458,0.964030,0.035166,0.000000,-0.955082,-0.265793,0.131044,0.000000,0.135677,0.000938,0.990753,0.000000,-32.898090,-0.227433,-240.231201,1.000000;;, + 2800;16;-0.278272,0.959769,0.037512,0.000000,-0.950703,-0.280788,0.131614,0.000000,0.136852,0.000962,0.990591,0.000000,-33.050110,-0.232307,-239.229568,1.000000;;, + 2880;16;-0.289622,0.956329,0.039411,0.000000,-0.947123,-0.292289,0.132380,0.000000,0.138118,0.001013,0.990415,0.000000,-33.276829,-0.244129,-238.621353,1.000000;;, + 2960;16;-0.296833,0.954060,0.040744,0.000000,-0.944705,-0.299614,0.133278,0.000000,0.139362,0.001070,0.990241,0.000000,-33.489239,-0.257202,-237.958450,1.000000;;, + 3040;16;-0.299743,0.953116,0.041518,0.000000,-0.943574,-0.302602,0.134539,0.000000,0.140795,0.001152,0.990038,0.000000,-33.823746,-0.276747,-237.841446,1.000000;;, + 3120;16;-0.297684,0.953755,0.041660,0.000000,-0.943957,-0.300582,0.136368,0.000000,0.142584,0.001269,0.989782,0.000000,-34.225349,-0.304588,-237.584305,1.000000;;, + 3200;16;-0.291409,0.955708,0.041265,0.000000,-0.945585,-0.294313,0.138741,0.000000,0.144741,0.001411,0.989469,0.000000,-34.849762,-0.339790,-238.237503,1.000000;;, + 3280;16;-0.281246,0.958786,0.040385,0.000000,-0.948245,-0.284126,0.141787,0.000000,0.147418,0.001582,0.989073,0.000000,-35.660633,-0.382615,-239.258606,1.000000;;, + 3360;16;-0.267718,0.962706,0.039033,0.000000,-0.951692,-0.270543,0.145222,0.000000,0.150366,0.001731,0.988629,0.000000,-36.596420,-0.421292,-240.614899,1.000000;;, + 3440;16;-0.251299,0.967193,0.037233,0.000000,-0.955671,-0.254036,0.148862,0.000000,0.153436,0.001827,0.988157,0.000000,-37.616859,-0.447802,-242.259262,1.000000;;, + 3520;16;-0.232467,0.971974,0.035017,0.000000,-0.959934,-0.235082,0.152522,0.000000,0.156480,0.001843,0.987679,0.000000,-38.677807,-0.455441,-244.129257,1.000000;;, + 3600;16;-0.211709,0.976794,0.032428,0.000000,-0.964255,-0.214171,0.156021,0.000000,0.159346,0.001762,0.987221,0.000000,-39.733059,-0.439425,-246.164780,1.000000;;, + 3680;16;-0.189524,0.981432,0.029521,0.000000,-0.968439,-0.191803,0.159178,0.000000,0.161884,0.001579,0.986808,0.000000,-40.710854,-0.397097,-248.163681,1.000000;;, + 3760;16;-0.166420,0.985703,0.026362,0.000000,-0.972330,-0.168490,0.161817,0.000000,0.163945,0.001297,0.986469,0.000000,-41.575722,-0.328980,-250.164444,1.000000;;, + 3840;16;-0.142916,0.989467,0.023030,0.000000,-0.975820,-0.144756,0.163769,0.000000,0.165378,0.000932,0.986230,0.000000,-42.260056,-0.238165,-252.018021,1.000000;;, + 3920;16;-0.120009,0.992578,0.019688,0.000000,-0.978789,-0.121612,0.164871,0.000000,0.166042,0.000515,0.986119,0.000000,-42.725815,-0.132566,-253.747559,1.000000;;, + 4000;16;-0.096823,0.995170,0.016217,0.000000,-0.981401,-0.098171,0.164971,0.000000,0.165766,0.000058,0.986165,0.000000,-42.921295,-0.014893,-255.344513,1.000000;;, + 4080;16;-0.072995,0.997253,0.012576,0.000000,-0.983711,-0.074069,0.163788,0.000000,0.164270,-0.000416,0.986415,0.000000,-42.753769,0.108166,-256.729523,1.000000;;, + 4160;16;-0.047948,0.998812,0.008734,0.000000,-0.985668,-0.048729,0.161504,0.000000,0.161738,-0.000865,0.986833,0.000000,-42.248627,0.226077,-257.777344,1.000000;;, + 4240;16;-0.020710,0.999775,0.004591,0.000000,-0.987195,-0.021175,0.158109,0.000000,0.158170,-0.001258,0.987411,0.000000,-41.379543,0.329120,-258.320129,1.000000;;, + 4320;16;0.007899,0.999969,0.000329,0.000000,-0.988064,0.007754,0.153846,0.000000,0.153839,-0.001540,0.988095,0.000000,-40.226177,0.402630,-258.369110,1.000000;;, + 4400;16;0.037495,0.999289,-0.003954,0.000000,-0.988134,0.037666,0.148907,0.000000,0.148950,-0.001676,0.988843,0.000000,-38.856068,0.437144,-257.956085,1.000000;;, + 4480;16;0.067688,0.997673,-0.008171,0.000000,-0.987302,0.068160,0.143490,0.000000,0.143713,-0.001645,0.989618,0.000000,-37.303371,0.426951,-256.874268,1.000000;;, + 4560;16;0.098083,0.995103,-0.012252,0.000000,-0.985516,0.098835,0.137801,0.000000,0.138337,-0.001442,0.990384,0.000000,-35.704922,0.372164,-255.618713,1.000000;;, + 4640;16;0.128286,0.991606,-0.016140,0.000000,-0.982774,0.129293,0.132057,0.000000,0.133035,-0.001079,0.991111,0.000000,-34.232403,0.277539,-255.031479,1.000000;;, + 4720;16;0.157601,0.987305,-0.019770,0.000000,-0.979148,0.158835,0.126655,0.000000,0.128187,-0.000603,0.991750,0.000000,-32.951950,0.154989,-254.940338,1.000000;;, + 4800;16;0.186552,0.982171,-0.023215,0.000000,-0.974653,0.187991,0.121288,0.000000,0.123489,-0.000000,0.992346,0.000000,-31.477245,0.000000,-252.947632,1.000000;;, + 4960;16;0.215193,0.976260,-0.024646,0.000000,-0.969920,0.216600,0.111082,0.000000,0.113783,-0.000000,0.993506,0.000000,-28.695675,0.000000,-250.557556,1.000000;;; + } + { Bip01_Footsteps } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;-0.000000,0.003123,0.999995,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999995,-0.003123,0.000000,-2.498093,-1.716894,0.000001,1.000000;;, + 80;16;-0.000000,0.005798,0.999983,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999983,-0.005798,0.000000,-2.606007,-1.708811,-0.000001,1.000000;;, + 160;16;-0.000000,0.008569,0.999963,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999963,-0.008569,0.000000,-2.714359,-1.701997,0.000007,1.000000;;, + 240;16;-0.000000,0.011630,0.999932,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999932,-0.011630,0.000000,-2.825058,-1.704134,0.000006,1.000000;;, + 320;16;-0.000000,0.014786,0.999891,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999891,-0.014786,0.000000,-2.935028,-1.702141,-0.000002,1.000000;;, + 400;16;-0.000000,0.017942,0.999839,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999839,-0.017942,0.000000,-3.042238,-1.688488,-0.000005,1.000000;;, + 480;16;-0.000000,0.021002,0.999779,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999779,-0.021002,0.000000,-3.144488,-1.655950,-0.000001,1.000000;;, + 560;16;-0.000000,0.023869,0.999715,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999715,-0.023869,0.000000,-3.236930,-1.599010,0.000005,1.000000;;, + 640;16;-0.000000,0.026447,0.999650,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999650,-0.026447,0.000000,-3.326138,-1.506355,-0.000006,1.000000;;, + 720;16;-0.000000,0.028638,0.999590,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999590,-0.028638,0.000000,-3.421040,-1.360553,0.000007,1.000000;;, + 800;16;-0.000000,0.030348,0.999539,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999539,-0.030348,0.000000,-3.513980,-1.175462,0.000007,1.000000;;, + 880;16;-0.000000,0.031444,0.999506,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999506,-0.031444,0.000000,-3.607227,-0.951677,0.000001,1.000000;;, + 960;16;-0.000000,0.031938,0.999490,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999490,-0.031938,0.000000,-3.682334,-0.710419,0.000003,1.000000;;, + 1040;16;-0.000000,0.031748,0.999496,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999496,-0.031748,0.000000,-3.717381,-0.472458,0.000000,1.000000;;, + 1120;16;-0.000000,0.031018,0.999519,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999519,-0.031018,0.000000,-3.718616,-0.233649,-0.000006,1.000000;;, + 1200;16;-0.000000,0.029844,0.999555,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999555,-0.029844,0.000000,-3.677681,0.000361,0.000003,1.000000;;, + 1280;16;-0.000000,0.028287,0.999600,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999600,-0.028287,0.000000,-3.613708,0.239710,-0.000006,1.000000;;, + 1360;16;-0.000000,0.026418,0.999651,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999651,-0.026418,0.000000,-3.543681,0.493597,0.000005,1.000000;;, + 1440;16;-0.000000,0.024309,0.999704,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999705,-0.024309,0.000000,-3.467867,0.755770,-0.000003,1.000000;;, + 1520;16;-0.000000,0.022030,0.999757,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999757,-0.022030,0.000000,-3.390432,1.023540,0.000009,1.000000;;, + 1600;16;-0.000000,0.019653,0.999807,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999807,-0.019653,0.000000,-3.315237,1.293970,-0.000004,1.000000;;, + 1680;16;-0.000000,0.017248,0.999851,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999851,-0.017248,0.000000,-3.245844,1.563869,-0.000005,1.000000;;, + 1760;16;-0.000000,0.014885,0.999889,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999889,-0.014885,0.000000,-3.185597,1.829824,0.000003,1.000000;;, + 1840;16;-0.000000,0.012637,0.999920,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999920,-0.012637,0.000000,-3.137427,2.088194,-0.000000,1.000000;;, + 1920;16;-0.000000,0.010574,0.999944,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999944,-0.010574,0.000000,-3.103951,2.335164,0.000006,1.000000;;, + 2000;16;0.000000,0.008766,0.999961,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999962,-0.008766,0.000000,-3.087498,2.566761,-0.000003,1.000000;;, + 2080;16;0.000000,0.007285,0.999973,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999973,-0.007285,0.000000,-3.090148,2.778913,0.000000,1.000000;;, + 2160;16;0.000000,0.005903,0.999983,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999983,-0.005903,0.000000,-3.108274,2.971279,-0.000007,1.000000;;, + 2240;16;-0.000000,0.005588,0.999984,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999984,-0.005588,0.000000,-3.159645,3.128248,0.000006,1.000000;;, + 2320;16;-0.000000,0.007494,0.999972,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999972,-0.007494,0.000000,-3.264085,3.232729,-0.000002,1.000000;;, + 2400;16;-0.000000,0.010843,0.999941,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999941,-0.010843,0.000000,-3.409011,3.285896,0.000004,1.000000;;, + 2480;16;-0.000000,0.015881,0.999874,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999874,-0.015881,0.000000,-3.599284,3.278342,-0.000004,1.000000;;, + 2560;16;-0.000000,0.020687,0.999786,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999786,-0.020687,0.000000,-3.803129,3.227022,-0.000004,1.000000;;, + 2640;16;-0.000000,0.023550,0.999723,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999723,-0.023550,0.000000,-3.998868,3.143643,0.000006,1.000000;;, + 2720;16;-0.000000,0.024101,0.999710,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999710,-0.024101,0.000000,-4.165480,3.040740,0.000006,1.000000;;, + 2800;16;-0.000000,0.020898,0.999782,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999782,-0.020898,0.000000,-4.277241,2.936613,0.000006,1.000000;;, + 2880;16;-0.000000,0.015453,0.999881,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999881,-0.015453,0.000000,-4.329769,2.828214,-0.000001,1.000000;;, + 2960;16;-0.000000,0.008510,0.999964,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999964,-0.008510,0.000000,-4.302057,2.720577,-0.000001,1.000000;;, + 3040;16;-0.000000,0.000942,1.000000,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,1.000000,-0.000942,0.000000,-4.218734,2.604678,0.000002,1.000000;;, + 3120;16;0.000000,-0.006408,0.999979,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999979,0.006408,0.000000,-4.092600,2.470545,0.000005,1.000000;;, + 3200;16;0.000000,-0.012697,0.999919,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999919,0.012697,0.000000,-3.938424,2.322757,0.000001,1.000000;;, + 3280;16;0.000000,-0.016811,0.999859,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999859,0.016811,0.000000,-3.770470,2.162284,0.000001,1.000000;;, + 3360;16;0.000000,-0.018729,0.999825,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999825,0.018729,0.000000,-3.603011,1.990379,-0.000005,1.000000;;, + 3440;16;0.000000,-0.017737,0.999843,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999843,0.017737,0.000000,-3.456044,1.809228,0.000000,1.000000;;, + 3520;16;0.000000,-0.014794,0.999891,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999891,0.014794,0.000000,-3.326296,1.619980,-0.000004,1.000000;;, + 3600;16;0.000000,-0.010505,0.999945,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999945,0.010505,0.000000,-3.220668,1.425136,0.000007,1.000000;;, + 3680;16;0.000000,-0.005221,0.999986,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999986,0.005221,0.000000,-3.127975,1.224429,-0.000004,1.000000;;, + 3760;16;-0.000000,0.000645,1.000000,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,1.000000,-0.000645,0.000000,-3.037925,1.017790,-0.000003,1.000000;;, + 3840;16;0.000000,0.006680,0.999978,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999978,-0.006680,0.000000,-2.954320,0.805845,0.000004,1.000000;;, + 3920;16;-0.000000,0.012471,0.999922,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999922,-0.012471,0.000000,-2.877302,0.589109,0.000001,1.000000;;, + 4000;16;-0.000000,0.017603,0.999845,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999845,-0.017603,0.000000,-2.807037,0.368100,-0.000011,1.000000;;, + 4080;16;-0.000000,0.021570,0.999767,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999767,-0.021570,0.000000,-2.743605,0.143374,-0.000008,1.000000;;, + 4160;16;-0.000000,0.024240,0.999706,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999706,-0.024240,0.000000,-2.686979,-0.084498,0.000004,1.000000;;, + 4240;16;-0.000000,0.025148,0.999684,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999684,-0.025148,0.000000,-2.637086,-0.314932,-0.000005,1.000000;;, + 4320;16;-0.000000,0.024788,0.999693,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999693,-0.024788,0.000000,-2.593796,-0.547340,0.000006,1.000000;;, + 4400;16;-0.000000,0.023387,0.999727,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999727,-0.023387,0.000000,-2.556833,-0.781132,-0.000001,1.000000;;, + 4480;16;-0.000000,0.021274,0.999774,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999774,-0.021274,0.000000,-2.525928,-1.015728,-0.000006,1.000000;;, + 4560;16;-0.000000,0.018755,0.999824,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999824,-0.018755,0.000000,-2.500761,-1.250548,-0.000001,1.000000;;, + 4640;16;-0.000000,0.016135,0.999870,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999870,-0.016135,0.000000,-2.480774,-1.485050,-0.000002,1.000000;;, + 4720;16;-0.000000,0.013920,0.999903,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999903,-0.013920,0.000000,-2.464930,-1.718164,-0.000005,1.000000;;, + 4800;16;-0.000000,0.011807,0.999930,0.000000,1.000000,0.000001,-0.000000,0.000000,-0.000001,0.999930,-0.011807,0.000000,-2.454305,-1.950977,-0.000005,1.000000;;, + 4960;16;-0.000000,0.003123,0.999995,0.000000,1.000000,0.000001,0.000000,0.000000,-0.000001,0.999995,-0.003123,0.000000,-2.498093,-1.716894,0.000001,1.000000;;; + } + { Bip01_Pelvis } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.999123,0.041767,0.002963,0.000000,-0.039832,0.969877,-0.240317,0.000000,-0.012911,0.239988,0.970690,0.000000,27.423990,8.709621,-0.080291,1.000000;;, + 80;16;0.999057,0.043399,-0.000923,0.000000,-0.042240,0.967043,-0.251084,0.000000,-0.010004,0.250886,0.967965,0.000000,27.423712,8.709688,-0.153400,1.000000;;, + 160;16;0.998974,0.045019,-0.004910,0.000000,-0.044731,0.963995,-0.262132,0.000000,-0.007067,0.262083,0.965020,0.000000,27.423220,8.709748,-0.229143,1.000000;;, + 240;16;0.998870,0.046629,-0.009154,0.000000,-0.047350,0.960438,-0.274438,0.000000,-0.004004,0.274561,0.961561,0.000000,27.422466,8.709834,-0.312789,1.000000;;, + 320;16;0.998745,0.048222,-0.013527,0.000000,-0.050076,0.956816,-0.286348,0.000000,-0.000865,0.286666,0.958030,0.000000,27.421347,8.709902,-0.399080,1.000000;;, + 400;16;0.998598,0.049795,-0.017967,0.000000,-0.052886,0.953448,-0.296885,0.000000,0.002347,0.297419,0.954744,0.000000,27.420021,8.709992,-0.485405,1.000000;;, + 480;16;0.998429,0.051349,-0.022410,0.000000,-0.055741,0.950693,-0.305085,0.000000,0.005639,0.305855,0.952062,0.000000,27.418449,8.710045,-0.569127,1.000000;;, + 560;16;0.998245,0.052832,-0.026768,0.000000,-0.058535,0.948912,-0.310064,0.000000,0.009019,0.311086,0.950339,0.000000,27.416719,8.710094,-0.647637,1.000000;;, + 640;16;0.998037,0.054406,-0.031026,0.000000,-0.061365,0.948540,-0.310654,0.000000,0.012528,0.311948,0.950017,0.000000,27.415018,8.710110,-0.718311,1.000000;;, + 720;16;0.997794,0.056292,-0.035203,0.000000,-0.064365,0.950186,-0.304965,0.000000,0.016283,0.306558,0.951713,0.000000,27.413412,8.710062,-0.778545,1.000000;;, + 800;16;0.997534,0.058300,-0.039081,0.000000,-0.067245,0.953380,-0.294185,0.000000,0.020108,0.296087,0.954949,0.000000,27.412104,8.709989,-0.825681,1.000000;;, + 880;16;0.997266,0.060451,-0.042510,0.000000,-0.069929,0.957960,-0.278248,0.000000,0.023903,0.280460,0.959568,0.000000,27.411259,8.709897,-0.856093,1.000000;;, + 960;16;0.997026,0.062340,-0.045313,0.000000,-0.071994,0.963208,-0.258933,0.000000,0.027504,0.261425,0.964832,0.000000,27.410852,8.709781,-0.870053,1.000000;;, + 1040;16;0.996863,0.063519,-0.047220,0.000000,-0.072985,0.968531,-0.237953,0.000000,0.030619,0.240653,0.970128,0.000000,27.411047,8.709651,-0.865323,1.000000;;, + 1120;16;0.996767,0.064080,-0.048470,0.000000,-0.073083,0.973748,-0.215580,0.000000,0.033383,0.218425,0.975282,0.000000,27.411665,8.709511,-0.845809,1.000000;;, + 1200;16;0.996748,0.063848,-0.049164,0.000000,-0.072196,0.978567,-0.192861,0.000000,0.035796,0.195783,0.979994,0.000000,27.412643,8.709426,-0.814108,1.000000;;, + 1280;16;0.996775,0.063168,-0.049484,0.000000,-0.070700,0.983031,-0.169270,0.000000,0.037952,0.172223,0.984327,0.000000,27.413853,8.709321,-0.771938,1.000000;;, + 1360;16;0.996821,0.062333,-0.049630,0.000000,-0.068920,0.987101,-0.144503,0.000000,0.039982,0.147464,0.988259,0.000000,27.415201,8.709247,-0.721257,1.000000;;, + 1440;16;0.996884,0.061336,-0.049598,0.000000,-0.066870,0.990648,-0.118935,0.000000,0.041840,0.121881,0.991662,0.000000,27.416634,8.709151,-0.663992,1.000000;;, + 1520;16;0.996959,0.060241,-0.049434,0.000000,-0.064637,0.993586,-0.092783,0.000000,0.043528,0.095696,0.994458,0.000000,27.418028,8.709090,-0.602090,1.000000;;, + 1600;16;0.997039,0.059108,-0.049178,0.000000,-0.062306,0.995855,-0.066263,0.000000,0.045058,0.069131,0.996590,0.000000,27.419365,8.709007,-0.537485,1.000000;;, + 1680;16;0.997120,0.057998,-0.048867,0.000000,-0.059956,0.997415,-0.039601,0.000000,0.046444,0.042417,0.998020,0.000000,27.420511,8.708969,-0.472121,1.000000;;, + 1760;16;0.997196,0.056968,-0.048536,0.000000,-0.057662,0.998251,-0.013023,0.000000,0.047709,0.015785,0.998737,0.000000,27.421484,8.708943,-0.407935,1.000000;;, + 1840;16;0.997262,0.056071,-0.048214,0.000000,-0.055493,0.998371,0.013244,0.000000,0.048878,-0.010532,0.998749,0.000000,27.422323,8.708948,-0.346869,1.000000;;, + 1920;16;0.997316,0.055359,-0.047930,0.000000,-0.053513,0.997806,0.038972,0.000000,0.049982,-0.036302,0.998090,0.000000,27.422901,8.708982,-0.290859,1.000000;;, + 2000;16;0.997353,0.054879,-0.047708,0.000000,-0.051780,0.996610,0.063936,0.000000,0.051055,-0.061296,0.996813,0.000000,27.423340,8.708994,-0.241852,1.000000;;, + 2080;16;0.997370,0.054677,-0.047570,0.000000,-0.050346,0.994855,0.087914,0.000000,0.052132,-0.085287,0.994992,0.000000,27.423624,8.709033,-0.201784,1.000000;;, + 2160;16;0.997381,0.054703,-0.047314,0.000000,-0.049197,0.992647,0.110592,0.000000,0.053016,-0.107975,0.992739,0.000000,27.423874,8.709077,-0.164378,1.000000;;, + 2240;16;0.997334,0.055280,-0.047632,0.000000,-0.048570,0.990053,0.132043,0.000000,0.054458,-0.129378,0.990099,0.000000,27.423906,8.709186,-0.156224,1.000000;;, + 2320;16;0.997165,0.056772,-0.049377,0.000000,-0.048657,0.987131,0.152331,0.000000,0.057390,-0.149496,0.987095,0.000000,27.423563,8.709200,-0.208964,1.000000;;, + 2400;16;0.996914,0.058971,-0.051814,0.000000,-0.049309,0.984002,0.171196,0.000000,0.061081,-0.168113,0.983874,0.000000,27.422709,8.709292,-0.301226,1.000000;;, + 2480;16;0.996559,0.061976,-0.055031,0.000000,-0.050578,0.980749,0.188608,0.000000,0.065661,-0.185176,0.980509,0.000000,27.420868,8.709354,-0.439755,1.000000;;, + 2560;16;0.996214,0.065247,-0.057455,0.000000,-0.052261,0.977576,0.203994,0.000000,0.069476,-0.200219,0.977285,0.000000,27.418518,8.709438,-0.571916,1.000000;;, + 2640;16;0.995992,0.068417,-0.057617,0.000000,-0.054407,0.974679,0.216890,0.000000,0.070997,-0.212886,0.974494,0.000000,27.416853,8.709501,-0.650709,1.000000;;, + 2720;16;0.995927,0.071133,-0.055404,0.000000,-0.056821,0.972261,0.226894,0.000000,0.070007,-0.222822,0.972342,0.000000,27.416513,8.709535,-0.666055,1.000000;;, + 2800;16;0.996094,0.072957,-0.049737,0.000000,-0.059430,0.970551,0.233449,0.000000,0.065304,-0.229581,0.971096,0.000000,27.418550,8.709614,-0.578335,1.000000;;, + 2880;16;0.996384,0.073821,-0.042075,0.000000,-0.061852,0.969652,0.236534,0.000000,0.058259,-0.233076,0.970712,0.000000,27.421329,8.709619,-0.429106,1.000000;;, + 2960;16;0.996750,0.073367,-0.033278,0.000000,-0.063506,0.969726,0.235792,0.000000,0.049569,-0.232913,0.971234,0.000000,27.423607,8.709618,-0.238672,1.000000;;, + 3040;16;0.997114,0.072017,-0.024018,0.000000,-0.064522,0.970635,0.231744,0.000000,0.040002,-0.229526,0.972480,0.000000,27.424623,8.709596,-0.031054,1.000000;;, + 3120;16;0.997436,0.069989,-0.014943,0.000000,-0.064858,0.972275,0.224666,0.000000,0.030253,-0.223120,0.974321,0.000000,27.424124,8.709539,0.170648,1.000000;;, + 3200;16;0.997693,0.067528,-0.006951,0.000000,-0.064461,0.974507,0.214897,0.000000,0.021285,-0.213953,0.976612,0.000000,27.422415,8.709509,0.343353,1.000000;;, + 3280;16;0.997893,0.064869,-0.001153,0.000000,-0.063289,0.977180,0.202767,0.000000,0.014280,-0.202267,0.979226,0.000000,27.420753,8.709398,0.456439,1.000000;;, + 3360;16;0.998058,0.062249,0.002426,0.000000,-0.061590,0.980136,0.188522,0.000000,0.009357,-0.188306,0.982066,0.000000,27.419783,8.709392,0.509363,1.000000;;, + 3440;16;0.998194,0.060003,0.003050,0.000000,-0.059630,0.983218,0.172412,0.000000,0.007346,-0.172283,0.985020,0.000000,27.420202,8.709322,0.482506,1.000000;;, + 3520;16;0.998312,0.058058,0.001693,0.000000,-0.057620,0.986277,0.154716,0.000000,0.007313,-0.154552,0.987958,0.000000,27.421497,8.709218,0.402188,1.000000;;, + 3600;16;0.998401,0.056518,-0.001049,0.000000,-0.055853,0.989165,0.135769,0.000000,0.008711,-0.135493,0.990740,0.000000,27.422939,8.709164,0.285022,1.000000;;, + 3680;16;0.998465,0.055179,-0.004804,0.000000,-0.054254,0.991800,0.115711,0.000000,0.011149,-0.115272,0.993271,0.000000,27.424032,8.709114,0.140571,1.000000;;, + 3760;16;0.998507,0.053849,-0.009127,0.000000,-0.052744,0.994098,0.094798,0.000000,0.014178,-0.094175,0.995455,0.000000,27.424370,8.709086,-0.019833,1.000000;;, + 3840;16;0.998524,0.052587,-0.013613,0.000000,-0.051458,0.996000,0.073054,0.000000,0.017400,-0.072246,0.997235,0.000000,27.423771,8.709007,-0.184858,1.000000;;, + 3920;16;0.998519,0.051392,-0.017847,0.000000,-0.050433,0.997446,0.050570,0.000000,0.020400,-0.049595,0.998561,0.000000,27.422205,8.708976,-0.343148,1.000000;;, + 4000;16;0.998507,0.050259,-0.021413,0.000000,-0.049665,0.998389,0.027438,0.000000,0.022758,-0.026334,0.999394,0.000000,27.420103,8.708972,-0.483372,1.000000;;, + 4080;16;0.998506,0.049186,-0.023804,0.000000,-0.049111,0.998786,0.003750,0.000000,0.023959,-0.002576,0.999710,0.000000,27.417946,8.708911,-0.591626,1.000000;;, + 4160;16;0.998529,0.048169,-0.024885,0.000000,-0.048681,0.998606,-0.020381,0.000000,0.023868,0.021563,0.999483,0.000000,27.416210,8.708953,-0.664299,1.000000;;, + 4240;16;0.998592,0.047204,-0.024190,0.000000,-0.048254,0.997827,-0.044860,0.000000,0.022020,0.045964,0.998700,0.000000,27.415644,8.708937,-0.688669,1.000000;;, + 4320;16;0.998681,0.046287,-0.022210,0.000000,-0.047729,0.996437,-0.069543,0.000000,0.018912,0.070512,0.997332,0.000000,27.415854,8.709007,-0.678236,1.000000;;, + 4400;16;0.998784,0.045413,-0.019169,0.000000,-0.047025,0.994433,-0.094300,0.000000,0.014780,0.095087,0.995359,0.000000,27.416765,8.709054,-0.639246,1.000000;;, + 4480;16;0.998887,0.044578,-0.015395,0.000000,-0.046097,0.991824,-0.118995,0.000000,0.009964,0.119572,0.992776,0.000000,27.418045,8.709128,-0.580761,1.000000;;, + 4560;16;0.998979,0.043778,-0.011190,0.000000,-0.044932,0.988630,-0.143495,0.000000,0.004781,0.143852,0.989588,0.000000,27.419416,8.709133,-0.511128,1.000000;;, + 4640;16;0.999051,0.043007,-0.006858,0.000000,-0.043547,0.984881,-0.167671,0.000000,-0.000457,0.167810,0.985819,0.000000,27.420631,8.709249,-0.438722,1.000000;;, + 4720;16;0.999103,0.042252,-0.002899,0.000000,-0.042026,0.980641,-0.191252,0.000000,-0.005238,0.191202,0.981537,0.000000,27.421503,8.709340,-0.377466,1.000000;;, + 4800;16;0.999137,0.041531,0.000982,0.000000,-0.040353,0.975880,-0.214545,0.000000,-0.009868,0.214320,0.976714,0.000000,27.422213,8.709480,-0.319006,1.000000;;, + 4960;16;0.999123,0.041767,0.002963,0.000000,-0.039832,0.969877,-0.240317,0.000000,-0.012911,0.239988,0.970690,0.000000,27.423990,8.709621,-0.080291,1.000000;;; + } + { Bip01_Spine } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178093,-0.022107,-0.000000,1.000000;;, + 80;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178076,-0.022107,-0.000001,1.000000;;, + 160;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178078,-0.022100,-0.000000,1.000000;;, + 240;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178055,-0.022113,-0.000001,1.000000;;, + 320;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178087,-0.022091,-0.000000,1.000000;;, + 400;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178095,-0.022106,-0.000000,1.000000;;, + 480;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178078,-0.022101,-0.000000,1.000000;;, + 560;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178080,-0.022108,-0.000001,1.000000;;, + 640;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178099,-0.022104,0.000000,1.000000;;, + 720;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178123,-0.022100,0.000001,1.000000;;, + 800;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178085,-0.022088,-0.000000,1.000000;;, + 880;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178066,-0.022108,-0.000001,1.000000;;, + 960;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178112,-0.022100,0.000001,1.000000;;, + 1040;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178099,-0.022101,0.000000,1.000000;;, + 1120;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178110,-0.022086,0.000001,1.000000;;, + 1200;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178099,-0.022109,0.000000,1.000000;;, + 1280;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178066,-0.022097,-0.000001,1.000000;;, + 1360;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178122,-0.022110,0.000001,1.000000;;, + 1440;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178076,-0.022091,-0.000000,1.000000;;, + 1520;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178099,-0.022102,0.000000,1.000000;;, + 1600;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178057,-0.022091,-0.000001,1.000000;;, + 1680;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178072,-0.022111,-0.000001,1.000000;;, + 1760;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178089,-0.022071,0.000000,1.000000;;, + 1840;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178070,-0.022096,-0.000001,1.000000;;, + 1920;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178097,-0.022103,-0.000000,1.000000;;, + 2000;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178118,-0.022102,0.000001,1.000000;;, + 2080;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178083,-0.022100,0.000000,1.000000;;, + 2160;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178091,-0.022098,0.000000,1.000000;;, + 2240;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178087,-0.022139,0.000000,1.000000;;, + 2320;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178082,-0.022113,-0.000001,1.000000;;, + 2400;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178089,-0.022089,0.000000,1.000000;;, + 2480;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178091,-0.022090,0.000000,1.000000;;, + 2560;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178083,-0.022078,0.000000,1.000000;;, + 2640;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178047,-0.022098,-0.000001,1.000000;;, + 2720;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178083,-0.022071,0.000001,1.000000;;, + 2800;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178085,-0.022123,-0.000001,1.000000;;, + 2880;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178074,-0.022096,-0.000000,1.000000;;, + 2960;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178123,-0.022122,-0.000002,1.000000;;, + 3040;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178099,-0.022103,-0.000000,1.000000;;, + 3120;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178076,-0.022107,-0.000001,1.000000;;, + 3200;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178122,-0.022106,-0.000001,1.000000;;, + 3280;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178097,-0.022081,0.000001,1.000000;;, + 3360;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178120,-0.022132,-0.000003,1.000000;;, + 3440;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178110,-0.022128,-0.000002,1.000000;;, + 3520;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178085,-0.022074,0.000002,1.000000;;, + 3600;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178089,-0.022098,0.000000,1.000000;;, + 3680;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178097,-0.022077,0.000001,1.000000;;, + 3760;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178085,-0.022123,-0.000002,1.000000;;, + 3840;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178057,-0.022095,0.000000,1.000000;;, + 3920;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178091,-0.022088,0.000001,1.000000;;, + 4000;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178080,-0.022091,0.000001,1.000000;;, + 4080;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178082,-0.022065,0.000002,1.000000;;, + 4160;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178125,-0.022127,-0.000002,1.000000;;, + 4240;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178078,-0.022039,0.000004,1.000000;;, + 4320;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178112,-0.022084,0.000001,1.000000;;, + 4400;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178114,-0.022109,-0.000001,1.000000;;, + 4480;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178070,-0.022167,-0.000004,1.000000;;, + 4560;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178085,-0.022028,0.000003,1.000000;;, + 4640;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178066,-0.022106,-0.000000,1.000000;;, + 4720;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178074,-0.022161,-0.000002,1.000000;;, + 4800;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178080,-0.022084,0.000000,1.000000;;, + 4960;16;0.984808,-0.173648,-0.000000,0.000000,0.173648,0.984808,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,28.178093,-0.022107,-0.000000,1.000000;;; + } + { Bip01_Spine1 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.999960,0.008638,0.002139,0.000000,-0.008515,0.998612,-0.051985,0.000000,-0.002585,0.051964,0.998646,0.000000,28.182180,-0.022404,0.001167,1.000000;;, + 80;16;0.999958,0.009006,0.001953,0.000000,-0.008886,0.998480,-0.054390,0.000000,-0.002440,0.054371,0.998518,0.000000,28.182199,-0.022407,0.001221,1.000000;;, + 160;16;0.999954,0.009373,0.001769,0.000000,-0.009257,0.998339,-0.056869,0.000000,-0.002300,0.056850,0.998380,0.000000,28.182215,-0.022390,0.001277,1.000000;;, + 240;16;0.999951,0.009739,0.001601,0.000000,-0.009626,0.998174,-0.059641,0.000000,-0.002179,0.059622,0.998219,0.000000,28.182205,-0.022391,0.001339,1.000000;;, + 320;16;0.999948,0.010105,0.001428,0.000000,-0.009996,0.998005,-0.062338,0.000000,-0.002055,0.062321,0.998054,0.000000,28.182203,-0.022400,0.001399,1.000000;;, + 400;16;0.999944,0.010470,0.001238,0.000000,-0.010368,0.997848,-0.064742,0.000000,-0.001913,0.064726,0.997901,0.000000,28.182194,-0.022392,0.001452,1.000000;;, + 480;16;0.999941,0.010837,0.001019,0.000000,-0.010745,0.997720,-0.066632,0.000000,-0.001739,0.066617,0.997777,0.000000,28.182243,-0.022383,0.001496,1.000000;;, + 560;16;0.999937,0.011193,0.000763,0.000000,-0.011115,0.997637,-0.067804,0.000000,-0.001520,0.067791,0.997698,0.000000,28.182243,-0.022378,0.001522,1.000000;;, + 640;16;0.999933,0.011574,0.000449,0.000000,-0.011516,0.997620,-0.067991,0.000000,-0.001235,0.067981,0.997686,0.000000,28.182236,-0.022407,0.001525,1.000000;;, + 720;16;0.999928,0.012029,0.000047,0.000000,-0.011999,0.997696,-0.066768,0.000000,-0.000850,0.066762,0.997769,0.000000,28.182245,-0.022386,0.001498,1.000000;;, + 800;16;0.999922,0.012511,-0.000419,0.000000,-0.012512,0.997845,-0.064404,0.000000,-0.000387,0.064404,0.997924,0.000000,28.182276,-0.022409,0.001445,1.000000;;, + 880;16;0.999915,0.013021,-0.000950,0.000000,-0.013055,0.998059,-0.060894,0.000000,0.000155,0.060901,0.998144,0.000000,28.182274,-0.022404,0.001366,1.000000;;, + 960;16;0.999908,0.013465,-0.001505,0.000000,-0.013529,0.998303,-0.056640,0.000000,0.000740,0.056656,0.998393,0.000000,28.182281,-0.022418,0.001271,1.000000;;, + 1040;16;0.999904,0.013741,-0.002043,0.000000,-0.013829,0.998550,-0.052024,0.000000,0.001325,0.052047,0.998644,0.000000,28.182289,-0.022406,0.001167,1.000000;;, + 1120;16;0.999900,0.013871,-0.002578,0.000000,-0.013977,0.998792,-0.047110,0.000000,0.001921,0.047141,0.998886,0.000000,28.182270,-0.022416,0.001056,1.000000;;, + 1200;16;0.999900,0.013819,-0.003104,0.000000,-0.013937,0.999015,-0.042130,0.000000,0.002518,0.042169,0.999107,0.000000,28.182281,-0.022428,0.000945,1.000000;;, + 1280;16;0.999900,0.013660,-0.003641,0.000000,-0.013785,0.999221,-0.036971,0.000000,0.003133,0.037018,0.999310,0.000000,28.182306,-0.022411,0.000830,1.000000;;, + 1360;16;0.999900,0.013461,-0.004213,0.000000,-0.013587,0.999409,-0.031574,0.000000,0.003786,0.031628,0.999492,0.000000,28.182280,-0.022422,0.000708,1.000000;;, + 1440;16;0.999901,0.013217,-0.004801,0.000000,-0.013338,0.999573,-0.026018,0.000000,0.004455,0.026080,0.999650,0.000000,28.182310,-0.022427,0.000585,1.000000;;, + 1520;16;0.999902,0.012943,-0.005396,0.000000,-0.013050,0.999708,-0.020351,0.000000,0.005131,0.020419,0.999778,0.000000,28.182245,-0.022437,0.000456,1.000000;;, + 1600;16;0.999902,0.012651,-0.005990,0.000000,-0.012738,0.999812,-0.014617,0.000000,0.005804,0.014692,0.999875,0.000000,28.182310,-0.022420,0.000330,1.000000;;, + 1680;16;0.999902,0.012355,-0.006574,0.000000,-0.012413,0.999884,-0.008863,0.000000,0.006464,0.008943,0.999939,0.000000,28.182240,-0.022410,0.000199,1.000000;;, + 1760;16;0.999902,0.012066,-0.007140,0.000000,-0.012089,0.999922,-0.003134,0.000000,0.007101,0.003220,0.999970,0.000000,28.182266,-0.022477,0.000070,1.000000;;, + 1840;16;0.999901,0.011799,-0.007677,0.000000,-0.011780,0.999927,0.002523,0.000000,0.007706,-0.002433,0.999967,0.000000,28.182272,-0.022432,-0.000056,1.000000;;, + 1920;16;0.999900,0.011565,-0.008177,0.000000,-0.011499,0.999901,0.008063,0.000000,0.008269,-0.007969,0.999934,0.000000,28.182232,-0.022423,-0.000181,1.000000;;, + 2000;16;0.999898,0.011377,-0.008631,0.000000,-0.011260,0.999846,0.013441,0.000000,0.008782,-0.013342,0.999872,0.000000,28.182209,-0.022437,-0.000302,1.000000;;, + 2080;16;0.999896,0.011247,-0.009028,0.000000,-0.011078,0.999765,0.018609,0.000000,0.009235,-0.018507,0.999786,0.000000,28.182236,-0.022451,-0.000417,1.000000;;, + 2160;16;0.999894,0.011168,-0.009374,0.000000,-0.010945,0.999664,0.023506,0.000000,0.009634,-0.023401,0.999680,0.000000,28.182228,-0.022439,-0.000527,1.000000;;, + 2240;16;0.999891,0.011212,-0.009616,0.000000,-0.010938,0.999544,0.028137,0.000000,0.009927,-0.028029,0.999558,0.000000,28.182234,-0.022405,-0.000631,1.000000;;, + 2320;16;0.999887,0.011463,-0.009695,0.000000,-0.011142,0.999410,0.032503,0.000000,0.010061,-0.032392,0.999425,0.000000,28.182226,-0.022421,-0.000730,1.000000;;, + 2400;16;0.999883,0.011880,-0.009621,0.000000,-0.011521,0.999265,0.036556,0.000000,0.010048,-0.036441,0.999285,0.000000,28.182283,-0.022441,-0.000819,1.000000;;, + 2480;16;0.999878,0.012490,-0.009366,0.000000,-0.012103,0.999115,0.040282,0.000000,0.009861,-0.040164,0.999144,0.000000,28.182253,-0.022421,-0.000904,1.000000;;, + 2560;16;0.999873,0.013177,-0.008993,0.000000,-0.012773,0.998968,0.043576,0.000000,0.009557,-0.043456,0.999010,0.000000,28.182255,-0.022452,-0.000979,1.000000;;, + 2640;16;0.999867,0.013860,-0.008544,0.000000,-0.013450,0.998835,0.046354,0.000000,0.009176,-0.046233,0.998889,0.000000,28.182299,-0.022407,-0.001040,1.000000;;, + 2720;16;0.999863,0.014461,-0.008061,0.000000,-0.014053,0.998723,0.048534,0.000000,0.008753,-0.048414,0.998789,0.000000,28.182329,-0.022429,-0.001090,1.000000;;, + 2800;16;0.999860,0.014879,-0.007608,0.000000,-0.014480,0.998643,0.050014,0.000000,0.008342,-0.049897,0.998720,0.000000,28.182306,-0.022414,-0.001123,1.000000;;, + 2880;16;0.999860,0.015098,-0.007168,0.000000,-0.014715,0.998602,0.050771,0.000000,0.007925,-0.050658,0.998685,0.000000,28.182318,-0.022442,-0.001141,1.000000;;, + 2960;16;0.999864,0.015039,-0.006756,0.000000,-0.014678,0.998605,0.050714,0.000000,0.007509,-0.050608,0.998690,0.000000,28.182287,-0.022416,-0.001138,1.000000;;, + 3040;16;0.999870,0.014793,-0.006341,0.000000,-0.014459,0.998647,0.049943,0.000000,0.007071,-0.049844,0.998732,0.000000,28.182310,-0.022401,-0.001120,1.000000;;, + 3120;16;0.999879,0.014408,-0.005889,0.000000,-0.014106,0.998723,0.048503,0.000000,0.006580,-0.048414,0.998806,0.000000,28.182297,-0.022400,-0.001087,1.000000;;, + 3200;16;0.999888,0.013933,-0.005421,0.000000,-0.013666,0.998827,0.046459,0.000000,0.006062,-0.046380,0.998905,0.000000,28.182285,-0.022428,-0.001043,1.000000;;, + 3280;16;0.999898,0.013415,-0.004945,0.000000,-0.013186,0.998950,0.043868,0.000000,0.005529,-0.043798,0.999025,0.000000,28.182266,-0.022429,-0.000985,1.000000;;, + 3360;16;0.999907,0.012904,-0.004470,0.000000,-0.012711,0.999087,0.040788,0.000000,0.004992,-0.040728,0.999158,0.000000,28.182243,-0.022399,-0.000913,1.000000;;, + 3440;16;0.999914,0.012469,-0.004007,0.000000,-0.012311,0.999229,0.037272,0.000000,0.004468,-0.037219,0.999297,0.000000,28.182274,-0.022430,-0.000837,1.000000;;, + 3520;16;0.999920,0.012094,-0.003553,0.000000,-0.011969,0.999371,0.033398,0.000000,0.003955,-0.033353,0.999436,0.000000,28.182243,-0.022438,-0.000751,1.000000;;, + 3600;16;0.999925,0.011801,-0.003112,0.000000,-0.011705,0.999504,0.029249,0.000000,0.003456,-0.029211,0.999567,0.000000,28.182255,-0.022432,-0.000657,1.000000;;, + 3680;16;0.999930,0.011546,-0.002677,0.000000,-0.011476,0.999625,0.024863,0.000000,0.002964,-0.024830,0.999687,0.000000,28.182261,-0.022451,-0.000560,1.000000;;, + 3760;16;0.999934,0.011289,-0.002241,0.000000,-0.011241,0.999731,0.020298,0.000000,0.002469,-0.020271,0.999791,0.000000,28.182238,-0.022433,-0.000455,1.000000;;, + 3840;16;0.999937,0.011041,-0.001804,0.000000,-0.011012,0.999818,0.015564,0.000000,0.001976,-0.015543,0.999877,0.000000,28.182243,-0.022441,-0.000350,1.000000;;, + 3920;16;0.999941,0.010802,-0.001368,0.000000,-0.010787,0.999885,0.010683,0.000000,0.001483,-0.010668,0.999942,0.000000,28.182222,-0.022450,-0.000240,1.000000;;, + 4000;16;0.999944,0.010572,-0.000931,0.000000,-0.010566,0.999928,0.005677,0.000000,0.000991,-0.005667,0.999984,0.000000,28.182243,-0.022468,-0.000130,1.000000;;, + 4080;16;0.999946,0.010348,-0.000494,0.000000,-0.010348,0.999946,0.000569,0.000000,0.000500,-0.000564,1.000000,0.000000,28.182241,-0.022454,-0.000014,1.000000;;, + 4160;16;0.999949,0.010130,-0.000057,0.000000,-0.010130,0.999938,-0.004620,0.000000,0.000010,0.004620,0.999989,0.000000,28.182201,-0.022432,0.000104,1.000000;;, + 4240;16;0.999951,0.009917,0.000381,0.000000,-0.009913,0.999902,-0.009867,0.000000,-0.000478,0.009863,0.999951,0.000000,28.182232,-0.022464,0.000219,1.000000;;, + 4320;16;0.999952,0.009709,0.000819,0.000000,-0.009695,0.999838,-0.015150,0.000000,-0.000966,0.015142,0.999885,0.000000,28.182169,-0.022407,0.000342,1.000000;;, + 4400;16;0.999954,0.009503,0.001259,0.000000,-0.009475,0.999746,-0.020448,0.000000,-0.001453,0.020435,0.999790,0.000000,28.182182,-0.022431,0.000459,1.000000;;, + 4480;16;0.999955,0.009299,0.001699,0.000000,-0.009253,0.999626,-0.025737,0.000000,-0.001938,0.025721,0.999667,0.000000,28.182177,-0.022365,0.000581,1.000000;;, + 4560;16;0.999956,0.009097,0.002141,0.000000,-0.009026,0.999479,-0.030997,0.000000,-0.002422,0.030976,0.999517,0.000000,28.182198,-0.022499,0.000692,1.000000;;, + 4640;16;0.999957,0.008894,0.002585,0.000000,-0.008794,0.999306,-0.036204,0.000000,-0.002905,0.036180,0.999341,0.000000,28.182184,-0.022429,0.000812,1.000000;;, + 4720;16;0.999958,0.008688,0.003030,0.000000,-0.008556,0.999110,-0.041308,0.000000,-0.003387,0.041280,0.999142,0.000000,28.182182,-0.022396,0.000928,1.000000;;, + 4800;16;0.999958,0.008483,0.003477,0.000000,-0.008313,0.998890,-0.046374,0.000000,-0.003867,0.046343,0.998918,0.000000,28.182159,-0.022430,0.001040,1.000000;;, + 4960;16;0.999960,0.008638,0.002139,0.000000,-0.008515,0.998612,-0.051985,0.000000,-0.002585,0.051964,0.998646,0.000000,28.182180,-0.022404,0.001167,1.000000;;; + } + { Bip01_Spine2 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.999844,-0.017541,0.002139,0.000000,0.017628,0.998492,-0.051985,0.000000,-0.001224,0.052014,0.998646,0.000000,28.181387,-0.033838,0.001761,1.000000;;, + 80;16;0.999851,-0.017173,0.001953,0.000000,0.017254,0.998371,-0.054390,0.000000,-0.001015,0.054416,0.998518,0.000000,28.181393,-0.033823,0.001844,1.000000;;, + 160;16;0.999857,-0.016806,0.001769,0.000000,0.016880,0.998239,-0.056869,0.000000,-0.000811,0.056891,0.998380,0.000000,28.181393,-0.033834,0.001926,1.000000;;, + 240;16;0.999864,-0.016440,0.001601,0.000000,0.016506,0.998083,-0.059641,0.000000,-0.000618,0.059659,0.998219,0.000000,28.181406,-0.033831,0.002020,1.000000;;, + 320;16;0.999870,-0.016074,0.001428,0.000000,0.016132,0.997925,-0.062339,0.000000,-0.000423,0.062353,0.998054,0.000000,28.181440,-0.033803,0.002113,1.000000;;, + 400;16;0.999876,-0.015709,0.001238,0.000000,0.015756,0.997778,-0.064742,0.000000,-0.000218,0.064754,0.997901,0.000000,28.181459,-0.033810,0.002194,1.000000;;, + 480;16;0.999882,-0.015342,0.001019,0.000000,0.015376,0.997659,-0.066632,0.000000,0.000006,0.066640,0.997777,0.000000,28.181421,-0.033817,0.002256,1.000000;;, + 560;16;0.999887,-0.014987,0.000763,0.000000,0.015004,0.997586,-0.067804,0.000000,0.000255,0.067808,0.997698,0.000000,28.181471,-0.033799,0.002297,1.000000;;, + 640;16;0.999893,-0.014606,0.000449,0.000000,0.014602,0.997579,-0.067991,0.000000,0.000545,0.067990,0.997686,0.000000,28.181479,-0.033799,0.002304,1.000000;;, + 720;16;0.999900,-0.014151,0.000047,0.000000,0.014122,0.997669,-0.066768,0.000000,0.000898,0.066762,0.997769,0.000000,28.181480,-0.033816,0.002261,1.000000;;, + 800;16;0.999906,-0.013669,-0.000419,0.000000,0.013613,0.997831,-0.064404,0.000000,0.001299,0.064393,0.997924,0.000000,28.181528,-0.033810,0.002183,1.000000;;, + 880;16;0.999913,-0.013158,-0.000950,0.000000,0.013076,0.998059,-0.060894,0.000000,0.001749,0.060876,0.998144,0.000000,28.181520,-0.033831,0.002062,1.000000;;, + 960;16;0.999918,-0.012714,-0.001505,0.000000,0.012608,0.998315,-0.056640,0.000000,0.002222,0.056617,0.998394,0.000000,28.181570,-0.033827,0.001920,1.000000;;, + 1040;16;0.999921,-0.012438,-0.002043,0.000000,0.012315,0.998570,-0.052024,0.000000,0.002687,0.051994,0.998644,0.000000,28.181555,-0.033841,0.001762,1.000000;;, + 1120;16;0.999921,-0.012308,-0.002578,0.000000,0.012173,0.998815,-0.047110,0.000000,0.003154,0.047075,0.998886,0.000000,28.181576,-0.033837,0.001598,1.000000;;, + 1200;16;0.999919,-0.012361,-0.003104,0.000000,0.012219,0.999037,-0.042129,0.000000,0.003622,0.042088,0.999107,0.000000,28.181570,-0.033847,0.001428,1.000000;;, + 1280;16;0.999915,-0.012519,-0.003641,0.000000,0.012376,0.999240,-0.036971,0.000000,0.004101,0.036923,0.999310,0.000000,28.181587,-0.033863,0.001253,1.000000;;, + 1360;16;0.999910,-0.012718,-0.004213,0.000000,0.012579,0.999422,-0.031574,0.000000,0.004612,0.031518,0.999493,0.000000,28.181551,-0.033881,0.001069,1.000000;;, + 1440;16;0.999904,-0.012962,-0.004801,0.000000,0.012832,0.999579,-0.026018,0.000000,0.005136,0.025954,0.999650,0.000000,28.181551,-0.033876,0.000882,1.000000;;, + 1520;16;0.999898,-0.013236,-0.005396,0.000000,0.013123,0.999707,-0.020351,0.000000,0.005664,0.020278,0.999778,0.000000,28.181580,-0.033861,0.000692,1.000000;;, + 1600;16;0.999891,-0.013528,-0.005990,0.000000,0.013439,0.999803,-0.014617,0.000000,0.006187,0.014535,0.999875,0.000000,28.181488,-0.033870,0.000494,1.000000;;, + 1680;16;0.999883,-0.013824,-0.006574,0.000000,0.013766,0.999866,-0.008863,0.000000,0.006696,0.008771,0.999939,0.000000,28.181526,-0.033868,0.000301,1.000000;;, + 1760;16;0.999875,-0.014112,-0.007140,0.000000,0.014090,0.999896,-0.003134,0.000000,0.007183,0.003033,0.999970,0.000000,28.181465,-0.033827,0.000105,1.000000;;, + 1840;16;0.999867,-0.014380,-0.007677,0.000000,0.014399,0.999893,0.002523,0.000000,0.007640,-0.002634,0.999968,0.000000,28.181459,-0.033858,-0.000087,1.000000;;, + 1920;16;0.999860,-0.014614,-0.008177,0.000000,0.014679,0.999860,0.008063,0.000000,0.008058,-0.008182,0.999934,0.000000,28.181480,-0.033867,-0.000273,1.000000;;, + 2000;16;0.999853,-0.014801,-0.008631,0.000000,0.014917,0.999798,0.013441,0.000000,0.008430,-0.013567,0.999872,0.000000,28.181446,-0.033858,-0.000457,1.000000;;, + 2080;16;0.999848,-0.014931,-0.009028,0.000000,0.015097,0.999713,0.018609,0.000000,0.008748,-0.018743,0.999786,0.000000,28.181459,-0.033842,-0.000631,1.000000;;, + 2160;16;0.999843,-0.015010,-0.009375,0.000000,0.015227,0.999608,0.023506,0.000000,0.009018,-0.023645,0.999680,0.000000,28.181465,-0.033830,-0.000798,1.000000;;, + 2240;16;0.999842,-0.014966,-0.009616,0.000000,0.015231,0.999488,0.028137,0.000000,0.009190,-0.028279,0.999558,0.000000,28.181452,-0.033852,-0.000955,1.000000;;, + 2320;16;0.999845,-0.014715,-0.009695,0.000000,0.015023,0.999359,0.032503,0.000000,0.009210,-0.032644,0.999425,0.000000,28.181450,-0.033814,-0.001103,1.000000;;, + 2400;16;0.999851,-0.014298,-0.009621,0.000000,0.014641,0.999224,0.036556,0.000000,0.009091,-0.036692,0.999285,0.000000,28.181465,-0.033791,-0.001241,1.000000;;, + 2480;16;0.999862,-0.013688,-0.009366,0.000000,0.014055,0.999090,0.040282,0.000000,0.008806,-0.040409,0.999144,0.000000,28.181517,-0.033817,-0.001366,1.000000;;, + 2560;16;0.999875,-0.013001,-0.008993,0.000000,0.013381,0.998960,0.043576,0.000000,0.008417,-0.043691,0.999010,0.000000,28.181549,-0.033836,-0.001476,1.000000;;, + 2640;16;0.999888,-0.012318,-0.008544,0.000000,0.012701,0.998844,0.046354,0.000000,0.007963,-0.046458,0.998889,0.000000,28.181564,-0.033836,-0.001570,1.000000;;, + 2720;16;0.999899,-0.011717,-0.008061,0.000000,0.012095,0.998748,0.048534,0.000000,0.007483,-0.048627,0.998789,0.000000,28.181547,-0.033857,-0.001645,1.000000;;, + 2800;16;0.999907,-0.011300,-0.007608,0.000000,0.011666,0.998680,0.050014,0.000000,0.007033,-0.050098,0.998720,0.000000,28.181583,-0.033833,-0.001695,1.000000;;, + 2880;16;0.999913,-0.011081,-0.007168,0.000000,0.011430,0.998645,0.050771,0.000000,0.006596,-0.050848,0.998685,0.000000,28.181591,-0.033802,-0.001721,1.000000;;, + 2960;16;0.999915,-0.011139,-0.006756,0.000000,0.011468,0.998647,0.050714,0.000000,0.006182,-0.050787,0.998690,0.000000,28.181618,-0.033829,-0.001718,1.000000;;, + 3040;16;0.999915,-0.011385,-0.006341,0.000000,0.011688,0.998684,0.049943,0.000000,0.005764,-0.050012,0.998732,0.000000,28.181599,-0.033857,-0.001693,1.000000;;, + 3120;16;0.999913,-0.011770,-0.005889,0.000000,0.012042,0.998750,0.048503,0.000000,0.005310,-0.048570,0.998806,0.000000,28.181557,-0.033831,-0.001643,1.000000;;, + 3200;16;0.999910,-0.012246,-0.005421,0.000000,0.012485,0.998842,0.046459,0.000000,0.004846,-0.046522,0.998905,0.000000,28.181559,-0.033862,-0.001575,1.000000;;, + 3280;16;0.999906,-0.012764,-0.004945,0.000000,0.012968,0.998953,0.043868,0.000000,0.004380,-0.043928,0.999025,0.000000,28.181566,-0.033826,-0.001487,1.000000;;, + 3360;16;0.999902,-0.013275,-0.004470,0.000000,0.013446,0.999077,0.040788,0.000000,0.003924,-0.040844,0.999158,0.000000,28.181530,-0.033886,-0.001383,1.000000;;, + 3440;16;0.999898,-0.013710,-0.004007,0.000000,0.013850,0.999209,0.037272,0.000000,0.003493,-0.037324,0.999297,0.000000,28.181486,-0.033862,-0.001263,1.000000;;, + 3520;16;0.999895,-0.014085,-0.003553,0.000000,0.014195,0.999341,0.033398,0.000000,0.003080,-0.033445,0.999436,0.000000,28.181517,-0.033820,-0.001130,1.000000;;, + 3600;16;0.999892,-0.014378,-0.003112,0.000000,0.014463,0.999467,0.029249,0.000000,0.002690,-0.029291,0.999567,0.000000,28.181490,-0.033846,-0.000991,1.000000;;, + 3680;16;0.999889,-0.014633,-0.002678,0.000000,0.014695,0.999583,0.024863,0.000000,0.002313,-0.024899,0.999687,0.000000,28.181467,-0.033848,-0.000841,1.000000;;, + 3760;16;0.999887,-0.014890,-0.002241,0.000000,0.014933,0.999682,0.020298,0.000000,0.001938,-0.020329,0.999792,0.000000,28.181490,-0.033844,-0.000687,1.000000;;, + 3840;16;0.999884,-0.015138,-0.001804,0.000000,0.015164,0.999764,0.015564,0.000000,0.001568,-0.015589,0.999877,0.000000,28.181444,-0.033860,-0.000526,1.000000;;, + 3920;16;0.999881,-0.015377,-0.001368,0.000000,0.015390,0.999825,0.010683,0.000000,0.001203,-0.010703,0.999942,0.000000,28.181479,-0.033850,-0.000361,1.000000;;, + 4000;16;0.999878,-0.015607,-0.000931,0.000000,0.015612,0.999862,0.005677,0.000000,0.000842,-0.005691,0.999983,0.000000,28.181408,-0.033862,-0.000190,1.000000;;, + 4080;16;0.999875,-0.015831,-0.000494,0.000000,0.015832,0.999874,0.000569,0.000000,0.000485,-0.000577,1.000000,0.000000,28.181391,-0.033842,-0.000016,1.000000;;, + 4160;16;0.999871,-0.016049,-0.000057,0.000000,0.016049,0.999861,-0.004620,0.000000,0.000131,0.004618,0.999989,0.000000,28.181423,-0.033896,0.000155,1.000000;;, + 4240;16;0.999868,-0.016262,0.000381,0.000000,0.016265,0.999819,-0.009867,0.000000,-0.000220,0.009872,0.999951,0.000000,28.181391,-0.033872,0.000335,1.000000;;, + 4320;16;0.999864,-0.016470,0.000819,0.000000,0.016481,0.999749,-0.015150,0.000000,-0.000569,0.015162,0.999885,0.000000,28.181414,-0.033918,0.000510,1.000000;;, + 4400;16;0.999860,-0.016676,0.001259,0.000000,0.016698,0.999652,-0.020448,0.000000,-0.000917,0.020466,0.999790,0.000000,28.181410,-0.033869,0.000693,1.000000;;, + 4480;16;0.999856,-0.016880,0.001699,0.000000,0.016918,0.999526,-0.025737,0.000000,-0.001264,0.025763,0.999667,0.000000,28.181383,-0.033883,0.000871,1.000000;;, + 4560;16;0.999852,-0.017082,0.002141,0.000000,0.017141,0.999372,-0.030997,0.000000,-0.001611,0.031029,0.999517,0.000000,28.181395,-0.033810,0.001054,1.000000;;, + 4640;16;0.999847,-0.017285,0.002585,0.000000,0.017367,0.999193,-0.036204,0.000000,-0.001957,0.036244,0.999341,0.000000,28.181389,-0.033833,0.001229,1.000000;;, + 4720;16;0.999842,-0.017491,0.003030,0.000000,0.017601,0.998991,-0.041308,0.000000,-0.002305,0.041355,0.999142,0.000000,28.181398,-0.033816,0.001402,1.000000;;, + 4800;16;0.999837,-0.017696,0.003477,0.000000,0.017838,0.998765,-0.046374,0.000000,-0.002652,0.046428,0.998918,0.000000,28.181417,-0.033880,0.001568,1.000000;;, + 4960;16;0.999844,-0.017541,0.002139,0.000000,0.017628,0.998492,-0.051985,0.000000,-0.001224,0.052014,0.998646,0.000000,28.181387,-0.033838,0.001761,1.000000;;; + } + { Bip01_Spine3 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566051,-0.019152,-0.000001,1.000000;;, + 80;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566063,-0.019157,-0.000001,1.000000;;, + 160;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566074,-0.019146,-0.000000,1.000000;;, + 240;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566082,-0.019151,-0.000001,1.000000;;, + 320;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566093,-0.019149,-0.000000,1.000000;;, + 400;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566093,-0.019138,0.000001,1.000000;;, + 480;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566078,-0.019146,-0.000000,1.000000;;, + 560;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566078,-0.019152,-0.000001,1.000000;;, + 640;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566071,-0.019145,0.000000,1.000000;;, + 720;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566078,-0.019133,0.000002,1.000000;;, + 800;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566055,-0.019141,0.000000,1.000000;;, + 880;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566093,-0.019140,0.000001,1.000000;;, + 960;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566048,-0.019155,-0.000003,1.000000;;, + 1040;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566097,-0.019147,0.000001,1.000000;;, + 1120;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566082,-0.019140,0.000001,1.000000;;, + 1200;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566078,-0.019156,-0.000001,1.000000;;, + 1280;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566055,-0.019162,-0.000003,1.000000;;, + 1360;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566086,-0.019146,0.000000,1.000000;;, + 1440;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566071,-0.019169,-0.000002,1.000000;;, + 1520;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566051,-0.019159,-0.000002,1.000000;;, + 1600;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566067,-0.019163,-0.000001,1.000000;;, + 1680;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566071,-0.019174,-0.000001,1.000000;;, + 1760;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566082,-0.019169,-0.000000,1.000000;;, + 1840;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566093,-0.019141,0.000001,1.000000;;, + 1920;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566051,-0.019146,-0.000001,1.000000;;, + 2000;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566090,-0.019145,0.000001,1.000000;;, + 2080;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566048,-0.019155,-0.000001,1.000000;;, + 2160;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566059,-0.019159,-0.000001,1.000000;;, + 2240;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566086,-0.019147,0.000001,1.000000;;, + 2320;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566067,-0.019134,-0.000002,1.000000;;, + 2400;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566071,-0.019154,0.000000,1.000000;;, + 2480;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566097,-0.019141,0.000000,1.000000;;, + 2560;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566093,-0.019137,-0.000000,1.000000;;, + 2640;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566067,-0.019130,-0.000002,1.000000;;, + 2720;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566063,-0.019083,-0.000004,1.000000;;, + 2800;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566048,-0.019105,-0.000003,1.000000;;, + 2880;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566074,-0.019139,-0.000000,1.000000;;, + 2960;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566059,-0.019120,-0.000001,1.000000;;, + 3040;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566078,-0.019110,-0.000001,1.000000;;, + 3120;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566090,-0.019134,-0.000000,1.000000;;, + 3200;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566090,-0.019111,-0.000001,1.000000;;, + 3280;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566059,-0.019137,0.000000,1.000000;;, + 3360;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566067,-0.019102,-0.000000,1.000000;;, + 3440;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566082,-0.019094,0.000001,1.000000;;, + 3520;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566071,-0.019155,-0.000000,1.000000;;, + 3600;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566086,-0.019138,-0.000000,1.000000;;, + 3680;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566086,-0.019154,-0.000000,1.000000;;, + 3760;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566071,-0.019144,0.000000,1.000000;;, + 3840;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566093,-0.019120,0.000000,1.000000;;, + 3920;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566059,-0.019139,0.000001,1.000000;;, + 4000;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566074,-0.019157,-0.000001,1.000000;;, + 4080;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566097,-0.019134,0.000000,1.000000;;, + 4160;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566059,-0.019083,0.000005,1.000000;;, + 4240;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566097,-0.019126,0.000001,1.000000;;, + 4320;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566090,-0.019128,0.000001,1.000000;;, + 4400;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566086,-0.019094,0.000005,1.000000;;, + 4480;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566086,-0.019163,-0.000002,1.000000;;, + 4560;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566044,-0.019131,0.000002,1.000000;;, + 4640;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566113,-0.019136,0.000001,1.000000;;, + 4720;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566063,-0.019118,0.000004,1.000000;;, + 4800;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566055,-0.019138,0.000001,1.000000;;, + 4960;16;0.861629,0.507538,0.000001,0.000000,-0.507538,0.861629,-0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,42.566051,-0.019152,-0.000001,1.000000;;; + } + { Bip01_Neck } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.975145,-0.214584,-0.055187,0.000000,0.220005,0.967277,0.126384,0.000000,0.026261,-0.135385,0.990445,0.000000,27.900181,-0.000002,0.000000,1.000000;;, + 80;16;0.975197,-0.214991,-0.052635,0.000000,0.220268,0.966011,0.135298,0.000000,0.021758,-0.143536,0.989406,0.000000,27.900167,-0.000002,-0.000001,1.000000;;, + 160;16;0.975267,-0.215301,-0.049997,0.000000,0.220365,0.964664,0.144437,0.000000,0.017133,-0.151882,0.988250,0.000000,27.900175,0.000002,0.000000,1.000000;;, + 240;16;0.975441,-0.215181,-0.047029,0.000000,0.219930,0.963202,0.154506,0.000000,0.012052,-0.161054,0.986872,0.000000,27.900183,-0.000004,0.000001,1.000000;;, + 320;16;0.975573,-0.215199,-0.044121,0.000000,0.219562,0.961661,0.164319,0.000000,0.007068,-0.169992,0.985420,0.000000,27.900177,0.000001,0.000001,1.000000;;, + 400;16;0.975580,-0.215682,-0.041530,0.000000,0.219629,0.960090,0.173176,0.000000,0.002521,-0.178068,0.984015,0.000000,27.900154,-0.000002,-0.000002,1.000000;;, + 480;16;0.975383,-0.216948,-0.039524,0.000000,0.220516,0.958559,0.180383,0.000000,-0.001248,-0.184658,0.982802,0.000000,27.900179,-0.000001,0.000000,1.000000;;, + 560;16;0.975012,-0.218842,-0.038201,0.000000,0.222115,0.957236,0.185378,0.000000,-0.004001,-0.189231,0.981925,0.000000,27.900166,0.000005,-0.000000,1.000000;;, + 640;16;0.974044,-0.223089,-0.038331,0.000000,0.226300,0.955921,0.187092,0.000000,-0.005097,-0.190910,0.981594,0.000000,27.900171,-0.000009,-0.000000,1.000000;;, + 720;16;0.971828,-0.232107,-0.040951,0.000000,0.235664,0.954284,0.183861,0.000000,-0.003596,-0.188332,0.982099,0.000000,27.900181,-0.000010,-0.000001,1.000000;;, + 800;16;0.968795,-0.243752,-0.044946,0.000000,0.247861,0.952526,0.176804,0.000000,-0.000284,-0.182427,0.983219,0.000000,27.900183,-0.000007,0.000000,1.000000;;, + 880;16;0.964823,-0.258093,-0.050051,0.000000,0.262858,0.950475,0.165841,0.000000,0.004770,-0.173163,0.984882,0.000000,27.900158,-0.000001,-0.000002,1.000000;;, + 960;16;0.961036,-0.270992,-0.054531,0.000000,0.276231,0.948855,0.152875,0.000000,0.010314,-0.161981,0.986740,0.000000,27.900185,-0.000003,0.000001,1.000000;;, + 1040;16;0.958751,-0.278453,-0.057093,0.000000,0.283838,0.948626,0.139806,0.000000,0.015230,-0.150244,0.988532,0.000000,27.900154,0.000002,-0.000001,1.000000;;, + 1120;16;0.958315,-0.279751,-0.058075,0.000000,0.285039,0.950072,0.126952,0.000000,0.019660,-0.138214,0.990207,0.000000,27.900169,-0.000004,-0.000001,1.000000;;, + 1200;16;0.960714,-0.271553,-0.057341,0.000000,0.276558,0.954028,0.115524,0.000000,0.023334,-0.126844,0.991648,0.000000,27.900175,0.000008,0.000000,1.000000;;, + 1280;16;0.964677,-0.257395,-0.056096,0.000000,0.262063,0.959356,0.104684,0.000000,0.026871,-0.115686,0.992922,0.000000,27.900183,0.000001,0.000001,1.000000;;, + 1360;16;0.969418,-0.239136,-0.055161,0.000000,0.243477,0.965345,0.093953,0.000000,0.030781,-0.104510,0.994047,0.000000,27.900160,0.000011,-0.000000,1.000000;;, + 1440;16;0.974249,-0.218751,-0.054649,0.000000,0.222769,0.971291,0.083475,0.000000,0.034820,-0.093500,0.995010,0.000000,27.900187,0.000001,0.000001,1.000000;;, + 1520;16;0.978630,-0.198249,-0.054603,0.000000,0.201936,0.976656,0.073246,0.000000,0.038807,-0.082707,0.995818,0.000000,27.900177,0.000001,0.000000,1.000000;;, + 1600;16;0.982195,-0.179675,-0.054862,0.000000,0.183003,0.981076,0.063241,0.000000,0.042461,-0.072155,0.996489,0.000000,27.900177,-0.000000,0.000001,1.000000;;, + 1680;16;0.984643,-0.165625,-0.055193,0.000000,0.168535,0.984267,0.053052,0.000000,0.045538,-0.061539,0.997065,0.000000,27.900185,0.000018,0.000000,1.000000;;, + 1760;16;0.986165,-0.156511,-0.054617,0.000000,0.158953,0.986321,0.043648,0.000000,0.047039,-0.051725,0.997553,0.000000,27.900152,0.000007,-0.000001,1.000000;;, + 1840;16;0.986674,-0.154239,-0.051811,0.000000,0.156181,0.987081,0.035767,0.000000,0.045625,-0.043382,0.998016,0.000000,27.900175,-0.000011,0.000000,1.000000;;, + 1920;16;0.986546,-0.156575,-0.047031,0.000000,0.158056,0.986987,0.029593,0.000000,0.041786,-0.036628,0.998455,0.000000,27.900173,-0.000017,0.000000,1.000000;;, + 2000;16;0.985931,-0.162299,-0.039997,0.000000,0.163398,0.986220,0.025917,0.000000,0.035239,-0.032088,0.998864,0.000000,27.900160,0.000003,-0.000001,1.000000;;, + 2080;16;0.984863,-0.170390,-0.031822,0.000000,0.171175,0.984952,0.023833,0.000000,0.027282,-0.028919,0.999209,0.000000,27.900188,0.000003,0.000000,1.000000;;, + 2160;16;0.983443,-0.179718,-0.023291,0.000000,0.180245,0.983354,0.022937,0.000000,0.018781,-0.026756,0.999466,0.000000,27.900175,0.000010,-0.000000,1.000000;;, + 2240;16;0.981698,-0.189796,-0.015703,0.000000,0.190118,0.981504,0.022470,0.000000,0.011148,-0.025044,0.999624,0.000000,27.900187,0.000002,-0.000001,1.000000;;, + 2320;16;0.979787,-0.199760,-0.010657,0.000000,0.199947,0.979580,0.021069,0.000000,0.006231,-0.022774,0.999721,0.000000,27.900188,-0.000012,0.000001,1.000000;;, + 2400;16;0.977670,-0.209981,-0.008269,0.000000,0.210108,0.977475,0.019939,0.000000,0.003896,-0.021231,0.999767,0.000000,27.900152,0.000001,-0.000000,1.000000;;, + 2480;16;0.975316,-0.220598,-0.009744,0.000000,0.220752,0.975133,0.019579,0.000000,0.005183,-0.021247,0.999761,0.000000,27.900166,-0.000005,0.000000,1.000000;;, + 2560;16;0.972729,-0.231551,-0.013496,0.000000,0.231795,0.972544,0.020746,0.000000,0.008321,-0.023308,0.999694,0.000000,27.900156,0.000010,-0.000000,1.000000;;, + 2640;16;0.969809,-0.243150,-0.018652,0.000000,0.243566,0.969568,0.024771,0.000000,0.012061,-0.028566,0.999519,0.000000,27.900169,-0.000002,0.000000,1.000000;;, + 2720;16;0.966884,-0.254043,-0.024428,0.000000,0.254722,0.966532,0.030538,0.000000,0.015852,-0.035749,0.999235,0.000000,27.900152,-0.000005,0.000001,1.000000;;, + 2800;16;0.964304,-0.263100,-0.029933,0.000000,0.264120,0.963753,0.037692,0.000000,0.018932,-0.044252,0.998841,0.000000,27.900171,-0.000013,0.000001,1.000000;;, + 2880;16;0.962281,-0.269829,-0.034751,0.000000,0.271235,0.961439,0.045462,0.000000,0.021144,-0.053173,0.998361,0.000000,27.900160,0.000003,0.000000,1.000000;;, + 2960;16;0.961211,-0.273166,-0.038119,0.000000,0.274934,0.959976,0.053444,0.000000,0.021994,-0.061851,0.997843,0.000000,27.900177,0.000008,-0.000000,1.000000;;, + 3040;16;0.960963,-0.273772,-0.039975,0.000000,0.275810,0.959323,0.060235,0.000000,0.021858,-0.068909,0.997383,0.000000,27.900162,-0.000004,0.000000,1.000000;;, + 3120;16;0.961544,-0.271764,-0.039720,0.000000,0.273867,0.959642,0.063915,0.000000,0.020747,-0.072335,0.997165,0.000000,27.900173,-0.000012,0.000000,1.000000;;, + 3200;16;0.962726,-0.267803,-0.037950,0.000000,0.269818,0.960676,0.065568,0.000000,0.018898,-0.073363,0.997126,0.000000,27.900158,-0.000005,0.000000,1.000000;;, + 3280;16;0.964310,-0.262468,-0.034891,0.000000,0.264264,0.962246,0.065163,0.000000,0.016470,-0.072058,0.997264,0.000000,27.900173,-0.000016,-0.000000,1.000000;;, + 3360;16;0.966149,-0.256110,-0.031048,0.000000,0.257631,0.964118,0.064053,0.000000,0.013529,-0.069883,0.997463,0.000000,27.900162,-0.000006,0.000000,1.000000;;, + 3440;16;0.968062,-0.249274,-0.026813,0.000000,0.250507,0.966045,0.063278,0.000000,0.010129,-0.067974,0.997636,0.000000,27.900162,-0.000003,-0.000000,1.000000;;, + 3520;16;0.970018,-0.241960,-0.022798,0.000000,0.242941,0.967945,0.063730,0.000000,0.006647,-0.067358,0.997707,0.000000,27.900169,-0.000007,0.000000,1.000000;;, + 3600;16;0.971815,-0.234939,-0.019495,0.000000,0.235725,0.969518,0.066851,0.000000,0.003195,-0.069562,0.997573,0.000000,27.900171,0.000011,0.000000,1.000000;;, + 3680;16;0.973899,-0.226296,-0.017646,0.000000,0.226981,0.971228,0.072079,0.000000,0.000827,-0.074203,0.997243,0.000000,27.900162,-0.000001,-0.000000,1.000000;;, + 3760;16;0.976723,-0.213722,-0.018324,0.000000,0.214504,0.973451,0.079882,0.000000,0.000765,-0.081953,0.996636,0.000000,27.900162,-0.000009,0.000000,1.000000;;, + 3840;16;0.979840,-0.198735,-0.020458,0.000000,0.199771,0.975824,0.088652,0.000000,0.002345,-0.090952,0.995853,0.000000,27.900175,-0.000003,-0.000000,1.000000;;, + 3920;16;0.983210,-0.180917,-0.023818,0.000000,0.182388,0.978428,0.097019,0.000000,0.005752,-0.099734,0.994998,0.000000,27.900173,-0.000014,-0.000000,1.000000;;, + 4000;16;0.986085,-0.163976,-0.027349,0.000000,0.165961,0.980553,0.104746,0.000000,0.009641,-0.107828,0.994123,0.000000,27.900162,0.000001,0.000000,1.000000;;, + 4080;16;0.987968,-0.151660,-0.030298,0.000000,0.154119,0.981778,0.111169,0.000000,0.012886,-0.114501,0.993340,0.000000,27.900160,0.000008,0.000000,1.000000;;, + 4160;16;0.989028,-0.143993,-0.032998,0.000000,0.146890,0.982308,0.116169,0.000000,0.015686,-0.119741,0.992681,0.000000,27.900154,-0.000039,-0.000003,1.000000;;, + 4240;16;0.989065,-0.143150,-0.035464,0.000000,0.146405,0.982010,0.119259,0.000000,0.017754,-0.123147,0.992230,0.000000,27.900167,-0.000010,-0.000001,1.000000;;, + 4320;16;0.988482,-0.146415,-0.038289,0.000000,0.150030,0.981253,0.120965,0.000000,0.019860,-0.125316,0.991918,0.000000,27.900164,0.000004,0.000000,1.000000;;, + 4400;16;0.987508,-0.151910,-0.041857,0.000000,0.155947,0.980259,0.121543,0.000000,0.022567,-0.126552,0.991703,0.000000,27.900160,-0.000023,-0.000002,1.000000;;, + 4480;16;0.986183,-0.159134,-0.046045,0.000000,0.163642,0.979044,0.121219,0.000000,0.025790,-0.127079,0.991557,0.000000,27.900187,-0.000000,0.000001,1.000000;;, + 4560;16;0.984606,-0.167248,-0.050779,0.000000,0.172273,0.977686,0.120217,0.000000,0.029539,-0.127114,0.991448,0.000000,27.900185,-0.000018,-0.000002,1.000000;;, + 4640;16;0.982904,-0.175418,-0.055927,0.000000,0.180995,0.976288,0.118754,0.000000,0.033769,-0.126846,0.991347,0.000000,27.900181,0.000027,0.000003,1.000000;;, + 4720;16;0.981339,-0.182286,-0.061210,0.000000,0.188427,0.975080,0.117110,0.000000,0.038337,-0.126458,0.991231,0.000000,27.900169,-0.000003,-0.000001,1.000000;;, + 4800;16;0.979775,-0.188667,-0.066683,0.000000,0.195389,0.973921,0.115333,0.000000,0.043184,-0.126029,0.991086,0.000000,27.900173,0.000003,0.000000,1.000000;;, + 4960;16;0.975145,-0.214584,-0.055187,0.000000,0.220005,0.967277,0.126384,0.000000,0.026261,-0.135385,0.990445,0.000000,27.900181,-0.000002,0.000000,1.000000;;; + } + { Bip01_Head } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,59.615768,-0.000004,0.000001,1.000000;;, + 80;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,59.615772,0.000003,0.000001,1.000000;;, + 160;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615749,-0.000000,0.000001,1.000000;;, + 240;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615746,-0.000004,0.000000,1.000000;;, + 320;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,59.615734,-0.000004,-0.000001,1.000000;;, + 400;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615768,0.000001,0.000001,1.000000;;, + 480;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,59.615765,0.000003,0.000002,1.000000;;, + 560;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615765,-0.000004,0.000002,1.000000;;, + 640;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615761,-0.000003,0.000001,1.000000;;, + 720;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615761,-0.000005,0.000000,1.000000;;, + 800;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615761,-0.000002,-0.000000,1.000000;;, + 880;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,59.615749,0.000004,-0.000002,1.000000;;, + 960;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,59.615753,0.000005,-0.000000,1.000000;;, + 1040;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,59.615768,-0.000001,0.000003,1.000000;;, + 1120;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615734,0.000003,-0.000002,1.000000;;, + 1200;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615768,-0.000001,0.000001,1.000000;;, + 1280;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615742,-0.000006,-0.000001,1.000000;;, + 1360;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615749,0.000003,-0.000001,1.000000;;, + 1440;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,59.615768,0.000004,0.000002,1.000000;;, + 1520;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,59.615742,0.000006,-0.000000,1.000000;;, + 1600;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,59.615749,-0.000011,0.000001,1.000000;;, + 1680;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615746,0.000012,-0.000002,1.000000;;, + 1760;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615753,0.000001,-0.000001,1.000000;;, + 1840;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,59.615742,0.000017,-0.000003,1.000000;;, + 1920;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615761,-0.000011,0.000001,1.000000;;, + 2000;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615753,0.000013,-0.000002,1.000000;;, + 2080;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615734,-0.000007,-0.000001,1.000000;;, + 2160;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615768,0.000002,-0.000001,1.000000;;, + 2240;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615746,0.000013,-0.000001,1.000000;;, + 2320;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615746,-0.000003,-0.000000,1.000000;;, + 2400;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,59.615738,0.000004,-0.000001,1.000000;;, + 2480;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,59.615746,0.000004,-0.000000,1.000000;;, + 2560;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615757,-0.000004,0.000000,1.000000;;, + 2640;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615742,-0.000011,0.000001,1.000000;;, + 2720;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615753,-0.000009,0.000001,1.000000;;, + 2800;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615761,0.000006,-0.000000,1.000000;;, + 2880;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,59.615753,-0.000010,0.000001,1.000000;;, + 2960;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615761,0.000013,-0.000000,1.000000;;, + 3040;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615746,-0.000012,0.000001,1.000000;;, + 3120;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615757,-0.000015,0.000001,1.000000;;, + 3200;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615768,-0.000011,0.000002,1.000000;;, + 3280;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,59.615738,-0.000002,-0.000000,1.000000;;, + 3360;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615738,-0.000005,0.000001,1.000000;;, + 3440;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,59.615761,-0.000002,0.000000,1.000000;;, + 3520;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615772,0.000001,0.000000,1.000000;;, + 3600;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615757,-0.000005,0.000000,1.000000;;, + 3680;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615753,-0.000011,0.000001,1.000000;;, + 3760;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,59.615768,-0.000011,0.000001,1.000000;;, + 3840;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615757,0.000005,-0.000000,1.000000;;, + 3920;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615768,-0.000009,0.000001,1.000000;;, + 4000;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615765,0.000010,-0.000000,1.000000;;, + 4080;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,59.615749,0.000009,0.000000,1.000000;;, + 4160;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,59.615776,0.000010,0.000000,1.000000;;, + 4240;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615768,-0.000026,0.000001,1.000000;;, + 4320;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,59.615742,-0.000026,0.000000,1.000000;;, + 4400;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615765,0.000016,0.000000,1.000000;;, + 4480;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,59.615753,0.000004,0.000001,1.000000;;, + 4560;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,59.615746,0.000007,-0.000002,1.000000;;, + 4640;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615757,-0.000022,0.000001,1.000000;;, + 4720;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615765,0.000010,0.000000,1.000000;;, + 4800;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,59.615768,0.000027,0.000002,1.000000;;, + 4960;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,59.615768,-0.000004,0.000001,1.000000;;; + } + { Dummy21 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;-0.167240,0.313773,0.934654,0.000000,-0.498528,-0.844794,0.194403,0.000000,0.850588,-0.433439,0.297708,0.000000,-12.374964,4.006889,8.346216,1.000000;;, + 80;16;-0.169076,0.312790,0.934653,0.000000,-0.498708,-0.845100,0.192605,0.000000,0.850120,-0.433554,0.298877,0.000000,-12.374962,4.006893,8.346217,1.000000;;, + 160;16;-0.170912,0.311807,0.934647,0.000000,-0.498887,-0.845402,0.190807,0.000000,0.849648,-0.433672,0.300046,0.000000,-12.374972,4.006898,8.346217,1.000000;;, + 240;16;-0.172799,0.310943,0.934588,0.000000,-0.499055,-0.845688,0.189093,0.000000,0.849167,-0.433736,0.301312,0.000000,-12.374967,4.006896,8.346217,1.000000;;, + 320;16;-0.174582,0.309843,0.934622,0.000000,-0.499239,-0.845999,0.187208,0.000000,0.848694,-0.433917,0.302382,0.000000,-12.374953,4.006895,8.346217,1.000000;;, + 400;16;-0.176219,0.308312,0.934821,0.000000,-0.499453,-0.846361,0.184988,0.000000,0.848230,-0.434300,0.303132,0.000000,-12.374983,4.006896,8.346216,1.000000;;, + 480;16;-0.177428,0.305993,0.935354,0.000000,-0.499714,-0.846804,0.182233,0.000000,0.847824,-0.435076,0.303156,0.000000,-12.374947,4.006888,8.346217,1.000000;;, + 560;16;-0.177768,0.302247,0.936507,0.000000,-0.500056,-0.847384,0.178562,0.000000,0.847551,-0.436563,0.301778,0.000000,-12.374949,4.006895,8.346218,1.000000;;, + 640;16;-0.177685,0.297702,0.937977,0.000000,-0.500440,-0.848033,0.174354,0.000000,0.847342,-0.438421,0.299665,0.000000,-12.374961,4.006884,8.346216,1.000000;;, + 720;16;-0.177231,0.292471,0.939707,0.000000,-0.500853,-0.848734,0.169695,0.000000,0.847193,-0.440580,0.296907,0.000000,-12.374961,4.006879,8.346214,1.000000;;, + 800;16;-0.177138,0.287473,0.941266,0.000000,-0.501251,-0.849408,0.165087,0.000000,0.846977,-0.442567,0.294558,0.000000,-12.374962,4.006883,8.346215,1.000000;;, + 880;16;-0.178220,0.283768,0.942186,0.000000,-0.501584,-0.849973,0.161118,0.000000,0.846552,-0.443871,0.293815,0.000000,-12.374976,4.006899,8.346215,1.000000;;, + 960;16;-0.180269,0.281098,0.942596,0.000000,-0.501870,-0.850457,0.157639,0.000000,0.845949,-0.444643,0.294385,0.000000,-12.374944,4.006894,8.346219,1.000000;;, + 1040;16;-0.183495,0.279724,0.942382,0.000000,-0.502099,-0.850845,0.154788,0.000000,0.845119,-0.444766,0.296575,0.000000,-12.374985,4.006907,8.346216,1.000000;;, + 1120;16;-0.187458,0.279129,0.941779,0.000000,-0.502296,-0.851179,0.152296,0.000000,0.844132,-0.444502,0.299765,0.000000,-12.374974,4.006891,8.346215,1.000000;;, + 1200;16;-0.191709,0.278753,0.941034,0.000000,-0.502485,-0.851499,0.149864,0.000000,0.843064,-0.444125,0.303308,0.000000,-12.374945,4.006901,8.346218,1.000000;;, + 1280;16;-0.196491,0.278971,0.939982,0.000000,-0.502648,-0.851776,0.147721,0.000000,0.841865,-0.443455,0.307590,0.000000,-12.374948,4.006887,8.346218,1.000000;;, + 1360;16;-0.201873,0.279924,0.938557,0.000000,-0.502781,-0.852001,0.145966,0.000000,0.840511,-0.442422,0.312736,0.000000,-12.374995,4.006908,8.346215,1.000000;;, + 1440;16;-0.207923,0.281749,0.936689,0.000000,-0.502876,-0.852161,0.144697,0.000000,0.838978,-0.440952,0.318869,0.000000,-12.374962,4.006903,8.346218,1.000000;;, + 1520;16;-0.214508,0.284228,0.934452,0.000000,-0.502944,-0.852276,0.143780,0.000000,0.837278,-0.439135,0.325771,0.000000,-12.374935,4.006886,8.346218,1.000000;;, + 1600;16;-0.222300,0.288549,0.931301,0.000000,-0.502927,-0.852248,0.144009,0.000000,0.835253,-0.436363,0.334574,0.000000,-12.374966,4.006901,8.346218,1.000000;;, + 1680;16;-0.232111,0.296207,0.926491,0.000000,-0.502747,-0.851943,0.146421,0.000000,0.832689,-0.431804,0.346662,0.000000,-12.374960,4.006915,8.346217,1.000000;;, + 1760;16;-0.243355,0.305918,0.920431,0.000000,-0.502463,-0.851462,0.150147,0.000000,0.829644,-0.425943,0.360920,0.000000,-12.374978,4.006920,8.346216,1.000000;;, + 1840;16;-0.256168,0.317769,0.912908,0.000000,-0.502061,-0.850781,0.155262,0.000000,0.826022,-0.418562,0.377483,0.000000,-12.374993,4.006886,8.346215,1.000000;;, + 1920;16;-0.269189,0.329157,0.905093,0.000000,-0.501680,-0.850135,0.159963,0.000000,0.822104,-0.411007,0.393978,0.000000,-12.374964,4.006881,8.346217,1.000000;;, + 2000;16;-0.281039,0.337658,0.898334,0.000000,-0.501467,-0.849774,0.162525,0.000000,0.818259,-0.404809,0.408144,0.000000,-12.374958,4.006900,8.346216,1.000000;;, + 2080;16;-0.291958,0.343326,0.892686,0.000000,-0.501443,-0.849734,0.162807,0.000000,0.814442,-0.400099,0.420245,0.000000,-12.374943,4.006909,8.346217,1.000000;;, + 2160;16;-0.301518,0.344840,0.888916,0.000000,-0.501707,-0.850181,0.159636,0.000000,0.810788,-0.397842,0.429353,0.000000,-12.374960,4.006894,8.346217,1.000000;;, + 2240;16;-0.310373,0.343935,0.886215,0.000000,-0.502132,-0.850901,0.154371,0.000000,0.807175,-0.397084,0.436797,0.000000,-12.374965,4.006871,8.346217,1.000000;;, + 2320;16;-0.319163,0.341745,0.883937,0.000000,-0.502641,-0.851764,0.147817,0.000000,0.803422,-0.397125,0.443627,0.000000,-12.374967,4.006865,8.346219,1.000000;;, + 2400;16;-0.327476,0.338564,0.882119,0.000000,-0.503185,-0.852686,0.140466,0.000000,0.799727,-0.397870,0.449595,0.000000,-12.374972,4.006896,8.346217,1.000000;;, + 2480;16;-0.335163,0.334888,0.880634,0.000000,-0.503717,-0.853586,0.132891,0.000000,0.796201,-0.399050,0.454779,0.000000,-12.374965,4.006886,8.346217,1.000000;;, + 2560;16;-0.342076,0.331206,0.879367,0.000000,-0.504195,-0.854397,0.125668,0.000000,0.792951,-0.400385,0.459261,0.000000,-12.374938,4.006904,8.346217,1.000000;;, + 2640;16;-0.348158,0.328208,0.878103,0.000000,-0.504580,-0.855050,0.119531,0.000000,0.790054,-0.401458,0.463300,0.000000,-12.374950,4.006896,8.346217,1.000000;;, + 2720;16;-0.352986,0.325774,0.877082,0.000000,-0.504877,-0.855552,0.114587,0.000000,0.787719,-0.402370,0.466474,0.000000,-12.374984,4.006876,8.346219,1.000000;;, + 2800;16;-0.356024,0.324125,0.876464,0.000000,-0.505064,-0.855869,0.111349,0.000000,0.786230,-0.403027,0.468414,0.000000,-12.374964,4.006858,8.346218,1.000000;;, + 2880;16;-0.357567,0.322919,0.876281,0.000000,-0.505178,-0.856062,0.109330,0.000000,0.785456,-0.403585,0.469232,0.000000,-12.374959,4.006901,8.346216,1.000000;;, + 2960;16;-0.357503,0.321827,0.876709,0.000000,-0.505237,-0.856163,0.108260,0.000000,0.785447,-0.404243,0.468680,0.000000,-12.374958,4.006893,8.346217,1.000000;;, + 3040;16;-0.356492,0.321048,0.877406,0.000000,-0.505252,-0.856187,0.107999,0.000000,0.785897,-0.404810,0.467434,0.000000,-12.374981,4.006920,8.346217,1.000000;;, + 3120;16;-0.355094,0.320544,0.878157,0.000000,-0.505240,-0.856167,0.108218,0.000000,0.786538,-0.405252,0.465971,0.000000,-12.374980,4.006894,8.346217,1.000000;;, + 3200;16;-0.353494,0.320707,0.878743,0.000000,-0.505184,-0.856073,0.109212,0.000000,0.787293,-0.405321,0.464633,0.000000,-12.374977,4.006891,8.346217,1.000000;;, + 3280;16;-0.352255,0.322102,0.878730,0.000000,-0.505069,-0.855878,0.111259,0.000000,0.787922,-0.404628,0.464171,0.000000,-12.374953,4.006900,8.346217,1.000000;;, + 3360;16;-0.350816,0.324162,0.878548,0.000000,-0.504906,-0.855602,0.114080,0.000000,0.788668,-0.403563,0.463831,0.000000,-12.374961,4.006896,8.346217,1.000000;;, + 3440;16;-0.348943,0.326855,0.878296,0.000000,-0.504688,-0.855232,0.117761,0.000000,0.789638,-0.402174,0.463387,0.000000,-12.374968,4.006890,8.346216,1.000000;;, + 3520;16;-0.346211,0.329156,0.878518,0.000000,-0.504460,-0.854846,0.121487,0.000000,0.790985,-0.401117,0.462004,0.000000,-12.374979,4.006877,8.346216,1.000000;;, + 3600;16;-0.342083,0.330111,0.879776,0.000000,-0.504266,-0.854518,0.124560,0.000000,0.792903,-0.401031,0.458780,0.000000,-12.374969,4.006895,8.346217,1.000000;;, + 3680;16;-0.336630,0.329495,0.882107,0.000000,-0.504127,-0.854282,0.126716,0.000000,0.795321,-0.402038,0.453685,0.000000,-12.374988,4.006921,8.346217,1.000000;;, + 3760;16;-0.329591,0.326439,0.885894,0.000000,-0.504094,-0.854226,0.127225,0.000000,0.798285,-0.404641,0.446101,0.000000,-12.374954,4.006886,8.346217,1.000000;;, + 3840;16;-0.321421,0.321840,0.890566,0.000000,-0.504123,-0.854276,0.126779,0.000000,0.801591,-0.408206,0.436829,0.000000,-12.374970,4.006894,8.346216,1.000000;;, + 3920;16;-0.312468,0.316118,0.895786,0.000000,-0.504197,-0.854400,0.125640,0.000000,0.805077,-0.412394,0.426359,0.000000,-12.374981,4.006866,8.346216,1.000000;;, + 4000;16;-0.302820,0.309854,0.901272,0.000000,-0.504279,-0.854540,0.124354,0.000000,0.808704,-0.416836,0.415025,0.000000,-12.374947,4.006918,8.346219,1.000000;;, + 4080;16;-0.292633,0.303606,0.906747,0.000000,-0.504340,-0.854643,0.123395,0.000000,0.812408,-0.421199,0.403217,0.000000,-12.374985,4.006909,8.346217,1.000000;;, + 4160;16;-0.282062,0.297951,0.911957,0.000000,-0.504350,-0.854660,0.123239,0.000000,0.816132,-0.425185,0.391339,0.000000,-12.374960,4.006845,8.346213,1.000000;;, + 4240;16;-0.271405,0.293515,0.916618,0.000000,-0.504281,-0.854543,0.124323,0.000000,0.819780,-0.428491,0.379941,0.000000,-12.374996,4.006858,8.346213,1.000000;;, + 4320;16;-0.260410,0.290803,0.920663,0.000000,-0.504094,-0.854225,0.127235,0.000000,0.823454,-0.430967,0.369041,0.000000,-12.374979,4.006874,8.346215,1.000000;;, + 4400;16;-0.248931,0.290808,0.923831,0.000000,-0.503712,-0.853578,0.132965,0.000000,0.827229,-0.432245,0.358965,0.000000,-12.374986,4.006876,8.346214,1.000000;;, + 4480;16;-0.236945,0.292723,0.926375,0.000000,-0.503166,-0.852654,0.140730,0.000000,0.831072,-0.432775,0.349321,0.000000,-12.374962,4.006917,8.346219,1.000000;;, + 4560;16;-0.224244,0.296375,0.928373,0.000000,-0.502439,-0.851422,0.150448,0.000000,0.835027,-0.432714,0.339837,0.000000,-12.374972,4.006852,8.346212,1.000000;;, + 4640;16;-0.211239,0.300811,0.929995,0.000000,-0.501594,-0.849990,0.161001,0.000000,0.838917,-0.432470,0.330436,0.000000,-12.374963,4.006896,8.346216,1.000000;;, + 4720;16;-0.198319,0.304878,0.931514,0.000000,-0.500729,-0.848523,0.171111,0.000000,0.842580,-0.432502,0.320939,0.000000,-12.374978,4.006879,8.346214,1.000000;;, + 4800;16;-0.185356,0.308957,0.932839,0.000000,-0.499811,-0.846968,0.181203,0.000000,0.846069,-0.432656,0.311411,0.000000,-12.374969,4.006883,8.346215,1.000000;;, + 4960;16;-0.167240,0.313773,0.934654,0.000000,-0.498528,-0.844794,0.194403,0.000000,0.850588,-0.433439,0.297708,0.000000,-12.374964,4.006889,8.346216,1.000000;;; + } + { Bip01_L_Clavicle } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.664909,0.057512,-0.744707,0.000000,0.080413,0.985725,0.147922,0.000000,0.742583,-0.158239,0.650792,0.000000,31.000193,-0.000001,0.000006,1.000000;;, + 80;16;0.677111,0.041649,-0.734701,0.000000,0.081682,0.987974,0.131286,0.000000,0.731333,-0.148907,0.665566,0.000000,31.000191,0.000002,0.000005,1.000000;;, + 160;16;0.689314,0.026352,-0.723983,0.000000,0.082675,0.989948,0.114749,0.000000,0.719730,-0.138954,0.680207,0.000000,31.000195,0.000001,0.000001,1.000000;;, + 240;16;0.702174,0.010462,-0.711928,0.000000,0.083083,0.991857,0.096521,0.000000,0.707141,-0.126924,0.695587,0.000000,31.000191,-0.000000,0.000016,1.000000;;, + 320;16;0.713950,-0.001421,-0.700196,0.000000,0.081960,0.993293,0.081554,0.000000,0.695384,-0.115614,0.709278,0.000000,31.000196,0.000010,-0.000026,1.000000;;, + 400;16;0.723141,-0.005627,-0.690678,0.000000,0.077624,0.994294,0.073172,0.000000,0.686325,-0.106527,0.719451,0.000000,31.000187,0.000001,0.000011,1.000000;;, + 480;16;0.729524,-0.001482,-0.683953,0.000000,0.071224,0.994725,0.073815,0.000000,0.680236,-0.102564,0.725782,0.000000,31.000193,-0.000003,0.000008,1.000000;;, + 560;16;0.732128,0.014851,-0.681005,0.000000,0.062323,0.994108,0.088680,0.000000,0.678310,-0.107367,0.726889,0.000000,31.000196,0.000011,-0.000018,1.000000;;, + 640;16;0.731502,0.037430,-0.680811,0.000000,0.054480,0.992091,0.113081,0.000000,0.679660,-0.119809,0.723677,0.000000,31.000193,-0.000002,0.000005,1.000000;;, + 720;16;0.728315,0.062572,-0.682379,0.000000,0.051888,0.987927,0.145971,0.000000,0.683275,-0.141720,0.716276,0.000000,31.000193,0.000001,0.000005,1.000000;;, + 800;16;0.722962,0.087923,-0.685270,0.000000,0.052813,0.981934,0.181705,0.000000,0.688866,-0.167557,0.705258,0.000000,31.000189,-0.000001,0.000021,1.000000;;, + 880;16;0.715919,0.109442,-0.689552,0.000000,0.057335,0.975086,0.214288,0.000000,0.695825,-0.192948,0.691808,0.000000,31.000189,0.000005,0.000020,1.000000;;, + 960;16;0.706804,0.129493,-0.695457,0.000000,0.063230,0.967604,0.244428,0.000000,0.704578,-0.216736,0.675718,0.000000,31.000193,0.000002,0.000012,1.000000;;, + 1040;16;0.694685,0.148445,-0.703830,0.000000,0.068273,0.960450,0.269954,0.000000,0.716067,-0.235586,0.657075,0.000000,31.000195,0.000005,-0.000002,1.000000;;, + 1120;16;0.680198,0.168418,-0.713419,0.000000,0.072459,0.953034,0.294070,0.000000,0.729439,-0.251719,0.636048,0.000000,31.000187,-0.000002,0.000021,1.000000;;, + 1200;16;0.663318,0.191979,-0.723293,0.000000,0.074914,0.944643,0.319432,0.000000,0.744578,-0.266070,0.612217,0.000000,31.000187,-0.000003,0.000004,1.000000;;, + 1280;16;0.645464,0.217336,-0.732217,0.000000,0.076240,0.935541,0.344893,0.000000,0.759976,-0.278440,0.587288,0.000000,31.000193,0.000000,-0.000009,1.000000;;, + 1360;16;0.627810,0.243434,-0.739320,0.000000,0.076846,0.925810,0.370095,0.000000,0.774564,-0.289163,0.562526,0.000000,31.000193,0.000000,0.000008,1.000000;;, + 1440;16;0.611526,0.269949,-0.743749,0.000000,0.076045,0.915594,0.394848,0.000000,0.787561,-0.298018,0.539382,0.000000,31.000185,-0.000008,0.000026,1.000000;;, + 1520;16;0.597625,0.296327,-0.745007,0.000000,0.074495,0.904654,0.419585,0.000000,0.798308,-0.306254,0.518569,0.000000,31.000196,0.000006,-0.000025,1.000000;;, + 1600;16;0.587804,0.321452,-0.742398,0.000000,0.068325,0.894666,0.441480,0.000000,0.806113,-0.310228,0.503925,0.000000,31.000189,-0.000004,0.000016,1.000000;;, + 1680;16;0.584715,0.343311,-0.735014,0.000000,0.052924,0.887966,0.456854,0.000000,0.809510,-0.306029,0.501038,0.000000,31.000196,-0.000028,-0.000003,1.000000;;, + 1760;16;0.585148,0.363285,-0.725001,0.000000,0.031238,0.883279,0.467807,0.000000,0.810325,-0.296384,0.505500,0.000000,31.000181,0.000007,0.000018,1.000000;;, + 1840;16;0.588209,0.381503,-0.713067,0.000000,0.002441,0.880894,0.473307,0.000000,0.808705,-0.280144,0.517219,0.000000,31.000193,-0.000018,-0.000001,1.000000;;, + 1920;16;0.590003,0.400505,-0.701065,0.000000,-0.026187,0.877334,0.479165,0.000000,0.806976,-0.264350,0.528118,0.000000,31.000183,-0.000005,0.000027,1.000000;;, + 2000;16;0.587083,0.422733,-0.690384,0.000000,-0.047649,0.869391,0.491823,0.000000,0.808123,-0.255845,0.530547,0.000000,31.000193,-0.000008,-0.000004,1.000000;;, + 2080;16;0.579066,0.449439,-0.680211,0.000000,-0.063170,0.856553,0.512178,0.000000,0.812830,-0.253616,0.524392,0.000000,31.000183,0.000023,-0.000003,1.000000;;, + 2160;16;0.563376,0.483771,-0.669756,0.000000,-0.069973,0.835672,0.544754,0.000000,0.823232,-0.260037,0.504648,0.000000,31.000200,-0.000022,-0.000008,1.000000;;, + 2240;16;0.543670,0.522500,-0.656823,0.000000,-0.072204,0.808801,0.583633,0.000000,0.836188,-0.269879,0.477447,0.000000,31.000198,-0.000025,0.000000,1.000000;;, + 2320;16;0.521856,0.563842,-0.640116,0.000000,-0.073318,0.777270,0.624881,0.000000,0.849877,-0.279166,0.446963,0.000000,31.000193,-0.000015,0.000014,1.000000;;, + 2400;16;0.499484,0.605335,-0.619746,0.000000,-0.072819,0.742180,0.666233,0.000000,0.863257,-0.287644,0.414787,0.000000,31.000189,0.000003,0.000012,1.000000;;, + 2480;16;0.478320,0.644525,-0.596487,0.000000,-0.071235,0.705465,0.705156,0.000000,0.875291,-0.294800,0.383350,0.000000,31.000181,0.000003,0.000021,1.000000;;, + 2560;16;0.459026,0.679997,-0.571751,0.000000,-0.069582,0.669098,0.739910,0.000000,0.885694,-0.299854,0.354448,0.000000,31.000212,0.000034,-0.000040,1.000000;;, + 2640;16;0.442866,0.709881,-0.547666,0.000000,-0.069152,0.636059,0.768536,0.000000,0.893917,-0.302486,0.330778,0.000000,31.000189,-0.000007,0.000017,1.000000;;, + 2720;16;0.428936,0.734383,-0.526020,0.000000,-0.069562,0.607432,0.791320,0.000000,0.900653,-0.302835,0.311634,0.000000,31.000189,0.000005,0.000005,1.000000;;, + 2800;16;0.416887,0.752856,-0.509327,0.000000,-0.071094,0.585631,0.807454,0.000000,0.906174,-0.300407,0.297666,0.000000,31.000204,-0.000028,-0.000015,1.000000;;, + 2880;16;0.406468,0.766636,-0.497045,0.000000,-0.072570,0.569383,0.818863,0.000000,0.910778,-0.296771,0.287071,0.000000,31.000191,-0.000002,-0.000002,1.000000;;, + 2960;16;0.396778,0.776797,-0.489034,0.000000,-0.073182,0.557841,0.826715,0.000000,0.914993,-0.292234,0.278186,0.000000,31.000198,-0.000004,-0.000009,1.000000;;, + 3040;16;0.389879,0.782941,-0.484766,0.000000,-0.072425,0.550864,0.831447,0.000000,0.918013,-0.289055,0.271475,0.000000,31.000196,0.000005,-0.000003,1.000000;;, + 3120;16;0.386919,0.785140,-0.483579,0.000000,-0.070232,0.547994,0.833529,0.000000,0.919435,-0.288546,0.267171,0.000000,31.000185,-0.000009,0.000011,1.000000;;, + 3200;16;0.389946,0.782789,-0.484958,0.000000,-0.064925,0.548710,0.833488,0.000000,0.918546,-0.293529,0.264790,0.000000,31.000206,-0.000013,-0.000020,1.000000;;, + 3280;16;0.402191,0.774994,-0.487470,0.000000,-0.054233,0.551662,0.832302,0.000000,0.913948,-0.308307,0.263904,0.000000,31.000189,0.000005,0.000007,1.000000;;, + 3360;16;0.420928,0.761746,-0.492507,0.000000,-0.039832,0.557948,0.828919,0.000000,0.906219,-0.329298,0.265198,0.000000,31.000189,0.000015,-0.000002,1.000000;;, + 3440;16;0.445819,0.742217,-0.500359,0.000000,-0.021552,0.567721,0.822939,0.000000,0.894864,-0.356098,0.269097,0.000000,31.000196,0.000023,-0.000005,1.000000;;, + 3520;16;0.472632,0.717311,-0.511941,0.000000,-0.002587,0.582046,0.813152,0.000000,0.881256,-0.382997,0.276949,0.000000,31.000185,-0.000018,0.000017,1.000000;;, + 3600;16;0.496984,0.688296,-0.528447,0.000000,0.014031,0.602525,0.797977,0.000000,0.867647,-0.403996,0.289788,0.000000,31.000195,-0.000006,-0.000004,1.000000;;, + 3680;16;0.520074,0.654703,-0.548532,0.000000,0.028011,0.628799,0.777063,0.000000,0.853662,-0.419495,0.308683,0.000000,31.000191,-0.000003,0.000003,1.000000;;, + 3760;16;0.541262,0.616501,-0.571806,0.000000,0.037364,0.661724,0.748816,0.000000,0.840023,-0.426671,0.335131,0.000000,31.000200,0.000007,-0.000021,1.000000;;, + 3840;16;0.562143,0.573838,-0.595571,0.000000,0.044106,0.698299,0.714447,0.000000,0.825863,-0.427889,0.367234,0.000000,31.000187,0.000019,-0.000002,1.000000;;, + 3920;16;0.584661,0.526231,-0.617456,0.000000,0.049698,0.736430,0.674686,0.000000,0.809754,-0.425150,0.404409,0.000000,31.000195,-0.000013,-0.000008,1.000000;;, + 4000;16;0.606639,0.476141,-0.636615,0.000000,0.054257,0.774131,0.630696,0.000000,0.793123,-0.417146,0.443784,0.000000,31.000189,0.000008,0.000006,1.000000;;, + 4080;16;0.627035,0.425517,-0.652505,0.000000,0.058091,0.809754,0.583887,0.000000,0.776822,-0.404022,0.483025,0.000000,31.000181,0.000033,0.000008,1.000000;;, + 4160;16;0.644915,0.376375,-0.665152,0.000000,0.061391,0.842003,0.535968,0.000000,0.761785,-0.386488,0.519914,0.000000,31.000193,-0.000002,-0.000007,1.000000;;, + 4240;16;0.659629,0.330881,-0.674838,0.000000,0.064313,0.869738,0.489306,0.000000,0.748834,-0.366161,0.552425,0.000000,31.000200,-0.000042,0.000002,1.000000;;, + 4320;16;0.669552,0.290112,-0.683765,0.000000,0.066772,0.893331,0.444411,0.000000,0.739758,-0.343213,0.578760,0.000000,31.000198,-0.000003,-0.000010,1.000000;;, + 4400;16;0.672038,0.256090,-0.694826,0.000000,0.068657,0.912709,0.402799,0.000000,0.737327,-0.318401,0.595793,0.000000,31.000187,0.000020,-0.000002,1.000000;;, + 4480;16;0.669411,0.226177,-0.707625,0.000000,0.069649,0.929224,0.362894,0.000000,0.739620,-0.292210,0.606279,0.000000,31.000185,0.000020,0.000001,1.000000;;, + 4560;16;0.661728,0.199092,-0.722826,0.000000,0.069524,0.943650,0.323562,0.000000,0.746513,-0.264363,0.610598,0.000000,31.000185,-0.000004,0.000019,1.000000;;, + 4640;16;0.652519,0.172744,-0.737820,0.000000,0.068460,0.956250,0.284429,0.000000,0.754673,-0.236107,0.612145,0.000000,31.000183,0.000022,0.000005,1.000000;;, + 4720;16;0.645864,0.145154,-0.749526,0.000000,0.067051,0.967181,0.245083,0.000000,0.760502,-0.208547,0.614935,0.000000,31.000189,0.000000,0.000008,1.000000;;, + 4800;16;0.640423,0.117307,-0.759011,0.000000,0.064965,0.976451,0.205728,0.000000,0.765270,-0.181062,0.617720,0.000000,31.000208,-0.000032,-0.000004,1.000000;;, + 4960;16;0.664909,0.057512,-0.744707,0.000000,0.080413,0.985725,0.147922,0.000000,0.742583,-0.158239,0.650792,0.000000,31.000193,-0.000001,0.000006,1.000000;;; + } + { Bip01_L_UpperArm } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.427260,-0.904129,0.000000,0.000000,0.904129,0.427260,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202515,-0.000002,0.000005,1.000000;;, + 80;16;0.388523,-0.921439,0.000000,0.000000,0.921439,0.388523,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202538,0.000007,-0.000007,1.000000;;, + 160;16;0.349087,-0.937091,0.000000,0.000000,0.937091,0.349087,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202530,0.000009,-0.000001,1.000000;;, + 240;16;0.307986,-0.951391,0.000000,0.000000,0.951391,0.307986,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202522,-0.000001,-0.000005,1.000000;;, + 320;16;0.268401,-0.963307,-0.000000,0.000000,0.963307,0.268401,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202538,0.000000,-0.000014,1.000000;;, + 400;16;0.234165,-0.972197,0.000000,0.000000,0.972197,0.234165,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202530,-0.000005,-0.000011,1.000000;;, + 480;16;0.202875,-0.979205,0.000000,0.000000,0.979205,0.202875,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202507,-0.000004,0.000001,1.000000;;, + 560;16;0.172560,-0.984999,0.000000,0.000000,0.984999,0.172560,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202515,-0.000012,-0.000000,1.000000;;, + 640;16;0.145352,-0.989380,0.000000,0.000000,0.989380,0.145352,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202522,-0.000008,-0.000007,1.000000;;, + 720;16;0.120234,-0.992746,0.000000,0.000000,0.992746,0.120234,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202515,-0.000005,-0.000001,1.000000;;, + 800;16;0.104677,-0.994506,0.000000,0.000000,0.994506,0.104677,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202515,-0.000008,0.000005,1.000000;;, + 880;16;0.106122,-0.994353,-0.000000,0.000000,0.994353,0.106122,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202522,0.000001,-0.000005,1.000000;;, + 960;16;0.123628,-0.992329,-0.000000,0.000000,0.992329,0.123628,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202530,-0.000003,0.000001,1.000000;;, + 1040;16;0.160645,-0.987012,-0.000000,0.000000,0.987012,0.160645,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202522,-0.000006,0.000009,1.000000;;, + 1120;16;0.210713,-0.977548,0.000000,0.000000,0.977548,0.210713,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202530,-0.000003,0.000005,1.000000;;, + 1200;16;0.268857,-0.963180,0.000000,0.000000,0.963180,0.268857,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202545,0.000005,0.000001,1.000000;;, + 1280;16;0.333371,-0.942796,0.000000,0.000000,0.942796,0.333371,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202522,0.000000,0.000003,1.000000;;, + 1360;16;0.401621,-0.915806,0.000000,0.000000,0.915806,0.401621,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202507,0.000003,-0.000005,1.000000;;, + 1440;16;0.470980,-0.882144,0.000000,0.000000,0.882144,0.470980,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202522,-0.000001,-0.000012,1.000000;;, + 1520;16;0.536024,-0.844203,0.000000,0.000000,0.844203,0.536024,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202515,-0.000002,-0.000000,1.000000;;, + 1600;16;0.603285,-0.797526,-0.000000,0.000000,0.797526,0.603285,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202530,-0.000008,-0.000010,1.000000;;, + 1680;16;0.677938,-0.735119,0.000000,0.000000,0.735119,0.677938,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202507,0.000019,-0.000015,1.000000;;, + 1760;16;0.751756,-0.659441,-0.000000,0.000000,0.659441,0.751756,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202530,0.000016,-0.000010,1.000000;;, + 1840;16;0.823370,-0.567505,-0.000000,0.000000,0.567505,0.823370,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202515,0.000029,-0.000014,1.000000;;, + 1920;16;0.879760,-0.475418,-0.000000,0.000000,0.475418,0.879760,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202530,0.000017,-0.000011,1.000000;;, + 2000;16;0.915394,-0.402559,0.000000,0.000000,0.402559,0.915394,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202507,0.000007,-0.000005,1.000000;;, + 2080;16;0.935580,-0.353115,0.000000,0.000000,0.353115,0.935580,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202530,0.000026,-0.000015,1.000000;;, + 2160;16;0.940380,-0.340125,-0.000000,0.000000,0.340125,0.940380,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202553,0.000032,-0.000015,1.000000;;, + 2240;16;0.936602,-0.350395,0.000000,0.000000,0.350395,0.936602,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202538,0.000019,-0.000012,1.000000;;, + 2320;16;0.926964,-0.375151,0.000000,0.000000,0.375151,0.926964,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202522,0.000033,-0.000012,1.000000;;, + 2400;16;0.912356,-0.409397,0.000000,0.000000,0.409397,0.912356,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202545,0.000023,-0.000015,1.000000;;, + 2480;16;0.894412,-0.447245,-0.000000,0.000000,0.447245,0.894412,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202538,0.000017,-0.000011,1.000000;;, + 2560;16;0.875553,-0.483123,-0.000000,0.000000,0.483123,0.875553,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202499,0.000028,-0.000006,1.000000;;, + 2640;16;0.859841,-0.510562,0.000000,0.000000,0.510562,0.859841,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202515,0.000021,-0.000002,1.000000;;, + 2720;16;0.848746,-0.528800,0.000000,0.000000,0.528800,0.848746,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202507,0.000019,-0.000005,1.000000;;, + 2800;16;0.846138,-0.532964,-0.000000,0.000000,0.532964,0.846138,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202538,0.000033,-0.000008,1.000000;;, + 2880;16;0.848612,-0.529015,-0.000000,0.000000,0.529015,0.848612,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202515,0.000039,-0.000009,1.000000;;, + 2960;16;0.854227,-0.519900,0.000000,0.000000,0.519900,0.854227,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202507,0.000020,-0.000006,1.000000;;, + 3040;16;0.860870,-0.508824,0.000000,0.000000,0.508824,0.860870,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202530,0.000027,-0.000011,1.000000;;, + 3120;16;0.866011,-0.500024,0.000000,0.000000,0.500024,0.866011,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202538,0.000019,-0.000009,1.000000;;, + 3200;16;0.869604,-0.493750,0.000000,0.000000,0.493751,0.869603,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202522,0.000016,-0.000008,1.000000;;, + 3280;16;0.870315,-0.492495,0.000000,0.000000,0.492495,0.870315,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202553,0.000015,-0.000006,1.000000;;, + 3360;16;0.869566,-0.493816,0.000000,0.000000,0.493816,0.869566,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202538,-0.000001,-0.000005,1.000000;;, + 3440;16;0.868279,-0.496077,0.000000,0.000000,0.496076,0.868279,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202530,0.000022,-0.000017,1.000000;;, + 3520;16;0.866450,-0.499264,0.000000,0.000000,0.499264,0.866450,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202545,0.000032,-0.000020,1.000000;;, + 3600;16;0.864007,-0.503480,0.000000,0.000000,0.503480,0.864007,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202522,0.000022,-0.000017,1.000000;;, + 3680;16;0.862093,-0.506750,-0.000000,0.000000,0.506750,0.862093,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202545,0.000024,-0.000015,1.000000;;, + 3760;16;0.862146,-0.506659,-0.000000,0.000000,0.506659,0.862146,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202538,0.000027,-0.000014,1.000000;;, + 3840;16;0.863305,-0.504683,0.000000,0.000000,0.504683,0.863304,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202530,0.000016,-0.000012,1.000000;;, + 3920;16;0.865849,-0.500306,0.000000,0.000000,0.500306,0.865849,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202515,0.000034,-0.000013,1.000000;;, + 4000;16;0.867722,-0.497049,-0.000000,0.000000,0.497049,0.867722,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202538,0.000038,-0.000021,1.000000;;, + 4080;16;0.867493,-0.497450,-0.000000,0.000000,0.497450,0.867493,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202522,-0.000010,0.000002,1.000000;;, + 4160;16;0.863690,-0.504024,0.000000,0.000000,0.504024,0.863690,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202538,0.000012,-0.000008,1.000000;;, + 4240;16;0.855068,-0.518517,-0.000000,0.000000,0.518517,0.855067,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202515,0.000002,0.000004,1.000000;;, + 4320;16;0.838383,-0.545081,-0.000000,0.000000,0.545081,0.838383,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202515,0.000005,0.000005,1.000000;;, + 4400;16;0.807911,-0.589304,-0.000000,0.000000,0.589304,0.807911,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202545,-0.000025,0.000009,1.000000;;, + 4480;16;0.764459,-0.644672,-0.000000,0.000000,0.644672,0.764459,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202545,0.000013,-0.000012,1.000000;;, + 4560;16;0.705366,-0.708843,0.000000,0.000000,0.708843,0.705366,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202515,-0.000013,0.000003,1.000000;;, + 4640;16;0.635360,-0.772216,0.000000,0.000000,0.772216,0.635360,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202515,0.000007,0.000003,1.000000;;, + 4720;16;0.562668,-0.826683,0.000000,0.000000,0.826683,0.562668,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202515,-0.000007,0.000003,1.000000;;, + 4800;16;0.485335,-0.874328,-0.000000,0.000000,0.874328,0.485335,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202522,-0.000023,0.000014,1.000000;;, + 4960;16;0.427260,-0.904129,0.000000,0.000000,0.904129,0.427260,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202515,-0.000002,0.000005,1.000000;;; + } + { Bip01_L_Forearm } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.999573,-0.023764,-0.016974,0.000000,-0.017488,-0.021598,-0.999614,0.000000,0.023388,0.999484,-0.022005,0.000000,61.671474,0.000008,-0.000005,1.000000;;, + 80;16;0.999618,-0.021237,-0.017707,0.000000,-0.018209,-0.023697,-0.999553,0.000000,0.020808,0.999494,-0.024075,0.000000,61.671478,-0.000011,0.000011,1.000000;;, + 160;16;0.999655,-0.018710,-0.018445,0.000000,-0.018925,-0.025798,-0.999488,0.000000,0.018225,0.999492,-0.026143,0.000000,61.671490,-0.000017,0.000006,1.000000;;, + 240;16;0.999685,-0.016109,-0.019257,0.000000,-0.019703,-0.028003,-0.999414,0.000000,0.015560,0.999478,-0.028312,0.000000,61.671482,0.000006,-0.000002,1.000000;;, + 320;16;0.999708,-0.013662,-0.019937,0.000000,-0.020340,-0.030005,-0.999343,0.000000,0.013055,0.999456,-0.030274,0.000000,61.671474,0.000001,0.000008,1.000000;;, + 400;16;0.999726,-0.011611,-0.020306,0.000000,-0.020664,-0.031527,-0.999289,0.000000,0.010963,0.999435,-0.031758,0.000000,61.671471,-0.000014,0.000015,1.000000;;, + 480;16;0.999745,-0.009844,-0.020335,0.000000,-0.020646,-0.032575,-0.999256,0.000000,0.009175,0.999421,-0.032770,0.000000,61.671478,0.000013,-0.000008,1.000000;;, + 560;16;0.999767,-0.008317,-0.019892,0.000000,-0.020157,-0.033022,-0.999251,0.000000,0.007654,0.999420,-0.033182,0.000000,61.671467,-0.000009,0.000005,1.000000;;, + 640;16;0.999792,-0.007073,-0.019106,0.000000,-0.019329,-0.032993,-0.999269,0.000000,0.006438,0.999431,-0.033122,0.000000,61.671474,0.000008,-0.000005,1.000000;;, + 720;16;0.999819,-0.006037,-0.018044,0.000000,-0.018232,-0.032591,-0.999303,0.000000,0.005445,0.999451,-0.032695,0.000000,61.671482,0.000002,0.000002,1.000000;;, + 800;16;0.999844,-0.005529,-0.016759,0.000000,-0.016927,-0.031764,-0.999352,0.000000,0.004993,0.999480,-0.031852,0.000000,61.671478,0.000022,-0.000012,1.000000;;, + 880;16;0.999865,-0.005827,-0.015342,0.000000,-0.015513,-0.030516,-0.999414,0.000000,0.005356,0.999517,-0.030602,0.000000,61.671474,-0.000009,0.000006,1.000000;;, + 960;16;0.999881,-0.006978,-0.013745,0.000000,-0.013940,-0.028786,-0.999488,0.000000,0.006579,0.999561,-0.028880,0.000000,61.671440,0.000002,-0.000012,1.000000;;, + 1040;16;0.999886,-0.009231,-0.011941,0.000000,-0.012182,-0.026468,-0.999575,0.000000,0.008911,0.999607,-0.026578,0.000000,61.671455,0.000011,-0.000019,1.000000;;, + 1120;16;0.999875,-0.012249,-0.009967,0.000000,-0.010255,-0.023710,-0.999666,0.000000,0.012009,0.999644,-0.023833,0.000000,61.671463,0.000013,-0.000017,1.000000;;, + 1200;16;0.999844,-0.015858,-0.007800,0.000000,-0.008125,-0.020548,-0.999756,0.000000,0.015694,0.999663,-0.020674,0.000000,61.671467,-0.000010,-0.000003,1.000000;;, + 1280;16;0.999788,-0.019821,-0.005588,0.000000,-0.005930,-0.017209,-0.999834,0.000000,0.019722,0.999655,-0.017323,0.000000,61.671455,-0.000011,0.000003,1.000000;;, + 1360;16;0.999708,-0.023916,-0.003435,0.000000,-0.003768,-0.013871,-0.999897,0.000000,0.023866,0.999618,-0.013957,0.000000,61.671463,-0.000001,0.000006,1.000000;;, + 1440;16;0.999609,-0.027921,-0.001439,0.000000,-0.001739,-0.010711,-0.999941,0.000000,0.027904,0.999553,-0.010756,0.000000,61.671452,0.000016,-0.000007,1.000000;;, + 1520;16;0.999503,-0.031527,0.000322,0.000000,0.000073,-0.007923,-0.999969,0.000000,0.031529,0.999471,-0.007917,0.000000,61.671452,0.000007,-0.000004,1.000000;;, + 1600;16;0.999395,-0.034756,0.001694,0.000000,0.001499,-0.005621,-0.999983,0.000000,0.034765,0.999380,-0.005565,0.000000,61.671459,0.000020,-0.000004,1.000000;;, + 1680;16;0.999294,-0.037481,0.002418,0.000000,0.002268,-0.004058,-0.999989,0.000000,0.037491,0.999289,-0.003970,0.000000,61.671463,0.000009,0.000003,1.000000;;, + 1760;16;0.999203,-0.039831,0.002724,0.000000,0.002606,-0.003006,-0.999992,0.000000,0.039839,0.999202,-0.002899,0.000000,61.671497,0.000015,-0.000007,1.000000;;, + 1840;16;0.999117,-0.041923,0.002635,0.000000,0.002537,-0.002396,-0.999994,0.000000,0.041929,0.999118,-0.002288,0.000000,61.671513,0.000010,0.000000,1.000000;;, + 1920;16;0.999043,-0.043674,0.002502,0.000000,0.002417,-0.002001,-0.999995,0.000000,0.043679,0.999044,-0.001893,0.000000,61.671482,0.000012,0.000002,1.000000;;, + 2000;16;0.998982,-0.045038,0.002676,0.000000,0.002608,-0.001574,-0.999995,0.000000,0.045042,0.998984,-0.001455,0.000000,61.671486,0.000014,-0.000004,1.000000;;, + 2080;16;0.998935,-0.046025,0.003169,0.000000,0.003122,-0.001107,-0.999995,0.000000,0.046028,0.998940,-0.000962,0.000000,61.671474,-0.000015,0.000004,1.000000;;, + 2160;16;0.998905,-0.046596,0.004187,0.000000,0.004170,-0.000469,-0.999991,0.000000,0.046597,0.998914,-0.000274,0.000000,61.671474,-0.000006,0.000004,1.000000;;, + 2240;16;0.998887,-0.046849,0.005496,0.000000,0.005513,0.000217,-0.999985,0.000000,0.046847,0.998902,0.000476,0.000000,61.671474,0.000005,-0.000002,1.000000;;, + 2320;16;0.998878,-0.046845,0.006944,0.000000,0.006992,0.000864,-0.999975,0.000000,0.046838,0.998902,0.001191,0.000000,61.671505,-0.000005,0.000003,1.000000;;, + 2400;16;0.998875,-0.046655,0.008496,0.000000,0.008575,0.001494,-0.999962,0.000000,0.046640,0.998910,0.001893,0.000000,61.671490,-0.000015,0.000006,1.000000;;, + 2480;16;0.998874,-0.046347,0.010088,0.000000,0.010197,0.002102,-0.999946,0.000000,0.046324,0.998923,0.002572,0.000000,61.671482,0.000009,-0.000002,1.000000;;, + 2560;16;0.998874,-0.045992,0.011658,0.000000,0.011794,0.002682,-0.999927,0.000000,0.045958,0.998938,0.003221,0.000000,61.671490,0.000016,-0.000006,1.000000;;, + 2640;16;0.998869,-0.045702,0.013111,0.000000,0.013273,0.003228,-0.999907,0.000000,0.045656,0.998950,0.003831,0.000000,61.671482,-0.000001,-0.000003,1.000000;;, + 2720;16;0.998863,-0.045412,0.014473,0.000000,0.014658,0.003735,-0.999886,0.000000,0.045353,0.998961,0.004396,0.000000,61.671482,0.000007,-0.000003,1.000000;;, + 2800;16;0.998859,-0.045096,0.015734,0.000000,0.015939,0.004194,-0.999864,0.000000,0.045024,0.998974,0.004908,0.000000,61.671486,-0.000004,-0.000001,1.000000;;, + 2880;16;0.998855,-0.044747,0.016908,0.000000,0.017131,0.004603,-0.999843,0.000000,0.044662,0.998988,0.005364,0.000000,61.671505,-0.000025,0.000007,1.000000;;, + 2960;16;0.998855,-0.044304,0.018029,0.000000,0.018266,0.004958,-0.999821,0.000000,0.044207,0.999006,0.005761,0.000000,61.671490,0.000004,0.000001,1.000000;;, + 3040;16;0.998855,-0.043896,0.019027,0.000000,0.019276,0.005258,-0.999800,0.000000,0.043788,0.999022,0.006098,0.000000,61.671463,-0.000010,0.000007,1.000000;;, + 3120;16;0.998852,-0.043610,0.019806,0.000000,0.020064,0.005482,-0.999784,0.000000,0.043492,0.999034,0.006350,0.000000,61.671452,-0.000006,-0.000001,1.000000;;, + 3200;16;0.998843,-0.043512,0.020470,0.000000,0.020737,0.005683,-0.999769,0.000000,0.043386,0.999037,0.006579,0.000000,61.671486,0.000021,-0.000006,1.000000;;, + 3280;16;0.998819,-0.043751,0.021126,0.000000,0.021406,0.005931,-0.999753,0.000000,0.043615,0.999025,0.006861,0.000000,61.671448,-0.000005,0.000003,1.000000;;, + 3360;16;0.998789,-0.044179,0.021667,0.000000,0.021960,0.006157,-0.999740,0.000000,0.044034,0.999005,0.007119,0.000000,61.671432,0.000015,-0.000005,1.000000;;, + 3440;16;0.998753,-0.044756,0.022114,0.000000,0.022421,0.006360,-0.999728,0.000000,0.044603,0.998978,0.007355,0.000000,61.671459,-0.000006,0.000007,1.000000;;, + 3520;16;0.998727,-0.045310,0.022186,0.000000,0.022499,0.006399,-0.999726,0.000000,0.045156,0.998952,0.007410,0.000000,61.671459,-0.000027,0.000011,1.000000;;, + 3600;16;0.998724,-0.045639,0.021621,0.000000,0.021923,0.006126,-0.999741,0.000000,0.045494,0.998939,0.007118,0.000000,61.671440,-0.000006,0.000003,1.000000;;, + 3680;16;0.998743,-0.045803,0.020381,0.000000,0.020657,0.005559,-0.999771,0.000000,0.045680,0.998935,0.006498,0.000000,61.671474,-0.000009,0.000002,1.000000;;, + 3760;16;0.998785,-0.045772,0.018247,0.000000,0.018478,0.004627,-0.999819,0.000000,0.045679,0.998941,0.005467,0.000000,61.671463,-0.000003,-0.000004,1.000000;;, + 3840;16;0.998838,-0.045632,0.015506,0.000000,0.015680,0.003447,-0.999871,0.000000,0.045572,0.998952,0.004158,0.000000,61.671455,0.000009,-0.000002,1.000000;;, + 3920;16;0.998889,-0.045491,0.012314,0.000000,0.012423,0.002109,-0.999921,0.000000,0.045461,0.998963,0.002671,0.000000,61.671463,-0.000002,0.000000,1.000000;;, + 4000;16;0.998936,-0.045249,0.008852,0.000000,0.008890,0.000629,-0.999960,0.000000,0.045242,0.998976,0.001031,0.000000,61.671463,-0.000013,0.000009,1.000000;;, + 4080;16;0.998979,-0.044860,0.005298,0.000000,0.005260,-0.000958,-0.999986,0.000000,0.044864,0.998993,-0.000721,0.000000,61.671482,0.000021,-0.000016,1.000000;;, + 4160;16;0.999018,-0.044272,0.001824,0.000000,0.001710,-0.002616,-0.999995,0.000000,0.044277,0.999016,-0.002538,0.000000,61.671467,-0.000028,0.000018,1.000000;;, + 4240;16;0.999054,-0.043471,-0.001353,0.000000,-0.001541,-0.004284,-0.999990,0.000000,0.043465,0.999046,-0.004347,0.000000,61.671459,0.000024,-0.000003,1.000000;;, + 4320;16;0.999096,-0.042305,-0.004176,0.000000,-0.004434,-0.006014,-0.999972,0.000000,0.042278,0.999087,-0.006196,0.000000,61.671509,-0.000014,0.000009,1.000000;;, + 4400;16;0.999156,-0.040575,-0.006446,0.000000,-0.006770,-0.007837,-0.999946,0.000000,0.040522,0.999146,-0.008105,0.000000,61.671440,0.000019,-0.000019,1.000000;;, + 4480;16;0.999227,-0.038410,-0.008369,0.000000,-0.008750,-0.009759,-0.999914,0.000000,0.038325,0.999214,-0.010087,0.000000,61.671467,-0.000005,0.000003,1.000000;;, + 4560;16;0.999309,-0.035783,-0.010036,0.000000,-0.010465,-0.011824,-0.999875,0.000000,0.035660,0.999290,-0.012191,0.000000,61.671474,0.000002,-0.000002,1.000000;;, + 4640;16;0.999389,-0.032964,-0.011585,0.000000,-0.012050,-0.013947,-0.999830,0.000000,0.032797,0.999359,-0.014336,0.000000,61.671474,-0.000013,0.000012,1.000000;;, + 4720;16;0.999455,-0.030246,-0.013202,0.000000,-0.013692,-0.016048,-0.999777,0.000000,0.030027,0.999414,-0.016454,0.000000,61.671448,0.000005,-0.000013,1.000000;;, + 4800;16;0.999511,-0.027531,-0.014824,0.000000,-0.015327,-0.018154,-0.999718,0.000000,0.027254,0.999456,-0.018567,0.000000,61.671467,0.000001,-0.000001,1.000000;;, + 4960;16;0.999573,-0.023764,-0.016974,0.000000,-0.017488,-0.021598,-0.999614,0.000000,0.023388,0.999484,-0.022005,0.000000,61.671474,0.000008,-0.000005,1.000000;;; + } + { Bip01_L_Hand } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410508,3.054968,-10.755419,1.000000;;, + 80;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410498,3.054974,-10.755421,1.000000;;, + 160;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410497,3.054968,-10.755431,1.000000;;, + 240;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410508,3.054964,-10.755431,1.000000;;, + 320;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410500,3.054960,-10.755434,1.000000;;, + 400;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410508,3.054971,-10.755414,1.000000;;, + 480;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410508,3.054960,-10.755432,1.000000;;, + 560;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410506,3.054965,-10.755426,1.000000;;, + 640;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410497,3.054977,-10.755417,1.000000;;, + 720;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410471,3.054978,-10.755437,1.000000;;, + 800;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410487,3.054967,-10.755437,1.000000;;, + 880;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410501,3.054976,-10.755417,1.000000;;, + 960;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410521,3.054957,-10.755430,1.000000;;, + 1040;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410499,3.054966,-10.755423,1.000000;;, + 1120;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410509,3.054960,-10.755429,1.000000;;, + 1200;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410503,3.054964,-10.755425,1.000000;;, + 1280;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410506,3.054965,-10.755434,1.000000;;, + 1360;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410516,3.054975,-10.755422,1.000000;;, + 1440;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410494,3.054971,-10.755426,1.000000;;, + 1520;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410505,3.054976,-10.755416,1.000000;;, + 1600;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410496,3.054975,-10.755421,1.000000;;, + 1680;16;0.713248,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410503,3.054969,-10.755434,1.000000;;, + 1760;16;0.713248,-0.002867,-0.700907,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410509,3.054973,-10.755425,1.000000;;, + 1840;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410497,3.054973,-10.755424,1.000000;;, + 1920;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410506,3.054967,-10.755421,1.000000;;, + 2000;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410499,3.054975,-10.755417,1.000000;;, + 2080;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410491,3.054975,-10.755412,1.000000;;, + 2160;16;0.713247,-0.002867,-0.700907,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410501,3.054973,-10.755416,1.000000;;, + 2240;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410501,3.054976,-10.755409,1.000000;;, + 2320;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410510,3.054970,-10.755433,1.000000;;, + 2400;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410506,3.054970,-10.755426,1.000000;;, + 2480;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410507,3.054971,-10.755430,1.000000;;, + 2560;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410508,3.054976,-10.755413,1.000000;;, + 2640;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410507,3.054967,-10.755429,1.000000;;, + 2720;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410498,3.054969,-10.755423,1.000000;;, + 2800;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410500,3.054970,-10.755417,1.000000;;, + 2880;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410507,3.054965,-10.755431,1.000000;;, + 2960;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410504,3.054980,-10.755417,1.000000;;, + 3040;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410500,3.054974,-10.755425,1.000000;;, + 3120;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410500,3.054966,-10.755434,1.000000;;, + 3200;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410495,3.054964,-10.755433,1.000000;;, + 3280;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410502,3.054964,-10.755434,1.000000;;, + 3360;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410505,3.054978,-10.755419,1.000000;;, + 3440;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410506,3.054974,-10.755412,1.000000;;, + 3520;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410496,3.054967,-10.755432,1.000000;;, + 3600;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410502,3.054972,-10.755426,1.000000;;, + 3680;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410500,3.054976,-10.755416,1.000000;;, + 3760;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410504,3.054980,-10.755415,1.000000;;, + 3840;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410511,3.054967,-10.755432,1.000000;;, + 3920;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410498,3.054977,-10.755418,1.000000;;, + 4000;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410497,3.054971,-10.755430,1.000000;;, + 4080;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410501,3.054986,-10.755408,1.000000;;, + 4160;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410512,3.054956,-10.755445,1.000000;;, + 4240;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410506,3.054977,-10.755414,1.000000;;, + 4320;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410501,3.054983,-10.755426,1.000000;;, + 4400;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410499,3.054965,-10.755426,1.000000;;, + 4480;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410507,3.054966,-10.755425,1.000000;;, + 4560;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410522,3.054971,-10.755424,1.000000;;, + 4640;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410505,3.054967,-10.755433,1.000000;;, + 4720;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410533,3.054963,-10.755422,1.000000;;, + 4800;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410522,3.054963,-10.755418,1.000000;;, + 4960;16;0.713247,-0.002867,-0.700906,0.000000,-0.700353,-0.042855,-0.712509,0.000000,-0.027995,0.999077,-0.032574,0.000000,12.410508,3.054968,-10.755419,1.000000;;; + } + { Bip01_L_Finger0 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075042,-0.000009,0.000013,1.000000;;, + 80;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075057,0.000004,0.000005,1.000000;;, + 160;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075050,-0.000016,0.000012,1.000000;;, + 240;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075056,-0.000019,0.000006,1.000000;;, + 320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075058,-0.000006,0.000002,1.000000;;, + 400;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075063,-0.000001,-0.000003,1.000000;;, + 480;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075071,0.000015,-0.000016,1.000000;;, + 560;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075075,0.000002,-0.000006,1.000000;;, + 640;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075053,0.000015,0.000006,1.000000;;, + 720;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075067,-0.000004,-0.000010,1.000000;;, + 800;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075047,0.000006,0.000007,1.000000;;, + 880;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075071,0.000010,-0.000015,1.000000;;, + 960;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075048,0.000030,0.000001,1.000000;;, + 1040;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075065,0.000007,-0.000005,1.000000;;, + 1120;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075040,-0.000001,0.000021,1.000000;;, + 1200;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075075,0.000018,-0.000009,1.000000;;, + 1280;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075082,0.000004,-0.000016,1.000000;;, + 1360;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075045,0.000004,0.000013,1.000000;;, + 1440;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075075,-0.000006,-0.000005,1.000000;;, + 1520;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075055,-0.000013,0.000004,1.000000;;, + 1600;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075053,-0.000007,0.000004,1.000000;;, + 1680;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075068,-0.000000,-0.000004,1.000000;;, + 1760;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075050,0.000011,-0.000002,1.000000;;, + 1840;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075065,-0.000005,0.000013,1.000000;;, + 1920;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075034,-0.000003,-0.000003,1.000000;;, + 2000;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075072,0.000011,-0.000006,1.000000;;, + 2080;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075059,0.000003,0.000002,1.000000;;, + 2160;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075062,-0.000007,0.000004,1.000000;;, + 2240;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075060,-0.000000,-0.000001,1.000000;;, + 2320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075060,0.000011,-0.000003,1.000000;;, + 2400;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075072,0.000001,0.000001,1.000000;;, + 2480;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075070,-0.000006,-0.000003,1.000000;;, + 2560;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075075,0.000011,-0.000008,1.000000;;, + 2640;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075055,-0.000009,0.000005,1.000000;;, + 2720;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075059,0.000000,-0.000001,1.000000;;, + 2800;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075051,-0.000017,0.000008,1.000000;;, + 2880;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075068,0.000004,0.000001,1.000000;;, + 2960;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075055,0.000011,-0.000002,1.000000;;, + 3040;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075054,-0.000001,-0.000001,1.000000;;, + 3120;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075063,0.000012,-0.000007,1.000000;;, + 3200;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075068,0.000006,-0.000006,1.000000;;, + 3280;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075062,-0.000019,0.000008,1.000000;;, + 3360;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075058,-0.000014,0.000005,1.000000;;, + 3440;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075047,-0.000004,0.000006,1.000000;;, + 3520;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075062,0.000001,-0.000004,1.000000;;, + 3600;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075053,0.000004,0.000005,1.000000;;, + 3680;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075042,-0.000006,0.000009,1.000000;;, + 3760;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075075,0.000004,-0.000009,1.000000;;, + 3840;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075061,-0.000009,0.000004,1.000000;;, + 3920;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075051,-0.000001,0.000008,1.000000;;, + 4000;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075066,-0.000004,-0.000001,1.000000;;, + 4080;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075035,-0.000012,0.000010,1.000000;;, + 4160;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075076,0.000012,-0.000010,1.000000;;, + 4240;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075080,-0.000000,-0.000001,1.000000;;, + 4320;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075083,-0.000006,-0.000003,1.000000;;, + 4400;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075057,-0.000004,-0.000002,1.000000;;, + 4480;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075103,-0.000009,-0.000019,1.000000;;, + 4560;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075098,-0.000006,-0.000016,1.000000;;, + 4640;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075061,-0.000013,0.000003,1.000000;;, + 4720;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075089,-0.000012,-0.000014,1.000000;;, + 4800;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075084,0.000006,-0.000007,1.000000;;, + 4960;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075042,-0.000009,0.000013,1.000000;;; + } + { Bip01_L_Finger01 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961583,0.000010,-0.000006,1.000000;;, + 80;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961592,0.000005,-0.000016,1.000000;;, + 160;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961579,0.000013,-0.000008,1.000000;;, + 240;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961580,0.000013,-0.000006,1.000000;;, + 320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961563,-0.000004,0.000012,1.000000;;, + 400;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961575,0.000008,-0.000006,1.000000;;, + 480;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961571,-0.000003,0.000006,1.000000;;, + 560;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961547,0.000037,0.000017,1.000000;;, + 640;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961574,0.000004,-0.000008,1.000000;;, + 720;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961565,0.000021,0.000006,1.000000;;, + 800;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961578,-0.000000,-0.000003,1.000000;;, + 880;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961573,-0.000007,0.000007,1.000000;;, + 960;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961574,-0.000013,-0.000001,1.000000;;, + 1040;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961557,-0.000014,0.000018,1.000000;;, + 1120;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961590,-0.000004,-0.000009,1.000000;;, + 1200;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961573,-0.000009,0.000002,1.000000;;, + 1280;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961561,0.000001,0.000004,1.000000;;, + 1360;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961581,-0.000005,-0.000008,1.000000;;, + 1440;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961569,0.000008,0.000004,1.000000;;, + 1520;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961579,0.000011,-0.000010,1.000000;;, + 1600;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961600,-0.000001,-0.000014,1.000000;;, + 1680;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961573,-0.000002,0.000006,1.000000;;, + 1760;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961561,-0.000008,0.000007,1.000000;;, + 1840;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961572,0.000001,-0.000005,1.000000;;, + 1920;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961586,0.000006,0.000004,1.000000;;, + 2000;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961570,-0.000011,0.000019,1.000000;;, + 2080;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961590,0.000008,0.000001,1.000000;;, + 2160;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961572,0.000008,0.000004,1.000000;;, + 2240;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961582,0.000020,-0.000002,1.000000;;, + 2320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961582,-0.000001,0.000001,1.000000;;, + 2400;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961583,0.000017,-0.000006,1.000000;;, + 2480;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961566,0.000003,0.000003,1.000000;;, + 2560;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961568,-0.000006,-0.000001,1.000000;;, + 2640;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961571,0.000001,-0.000004,1.000000;;, + 2720;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961561,-0.000014,0.000009,1.000000;;, + 2800;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961579,0.000009,-0.000003,1.000000;;, + 2880;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961574,-0.000007,0.000002,1.000000;;, + 2960;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961576,-0.000004,0.000002,1.000000;;, + 3040;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961565,-0.000002,0.000004,1.000000;;, + 3120;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961581,-0.000019,0.000004,1.000000;;, + 3200;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961570,-0.000012,0.000005,1.000000;;, + 3280;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961571,0.000010,-0.000000,1.000000;;, + 3360;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961576,0.000006,-0.000005,1.000000;;, + 3440;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961583,-0.000005,-0.000003,1.000000;;, + 3520;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961581,0.000019,-0.000012,1.000000;;, + 3600;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961582,-0.000001,-0.000007,1.000000;;, + 3680;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961586,0.000006,-0.000009,1.000000;;, + 3760;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961561,0.000005,0.000009,1.000000;;, + 3840;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961577,0.000002,-0.000007,1.000000;;, + 3920;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961557,-0.000012,0.000012,1.000000;;, + 4000;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961568,-0.000011,0.000004,1.000000;;, + 4080;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961595,0.000018,-0.000016,1.000000;;, + 4160;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961530,-0.000013,0.000027,1.000000;;, + 4240;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961580,0.000006,-0.000002,1.000000;;, + 4320;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961552,0.000002,0.000005,1.000000;;, + 4400;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961567,0.000004,0.000002,1.000000;;, + 4480;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961559,-0.000005,0.000011,1.000000;;, + 4560;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961559,-0.000019,0.000015,1.000000;;, + 4640;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961563,0.000016,0.000006,1.000000;;, + 4720;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961565,0.000025,0.000000,1.000000;;, + 4800;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961566,-0.000008,0.000006,1.000000;;, + 4960;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961583,0.000010,-0.000006,1.000000;;; + } + { Bip01_L_Finger02 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961576,0.000009,-0.000003,1.000000;;, + 80;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961568,-0.000009,0.000011,1.000000;;, + 160;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961581,0.000011,-0.000008,1.000000;;, + 240;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961579,0.000013,-0.000003,1.000000;;, + 320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961580,0.000014,-0.000009,1.000000;;, + 400;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961574,0.000009,-0.000001,1.000000;;, + 480;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961569,-0.000002,0.000006,1.000000;;, + 560;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961576,-0.000011,-0.000001,1.000000;;, + 640;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961578,0.000005,-0.000002,1.000000;;, + 720;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961578,-0.000002,-0.000003,1.000000;;, + 800;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961576,-0.000000,-0.000005,1.000000;;, + 880;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961572,-0.000007,0.000004,1.000000;;, + 960;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961579,-0.000012,0.000002,1.000000;;, + 1040;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961574,0.000008,0.000002,1.000000;;, + 1120;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961586,-0.000004,-0.000012,1.000000;;, + 1200;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961573,-0.000009,0.000007,1.000000;;, + 1280;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961569,-0.000003,0.000001,1.000000;;, + 1360;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961571,0.000000,0.000001,1.000000;;, + 1440;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961565,0.000009,-0.000000,1.000000;;, + 1520;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961580,0.000012,-0.000009,1.000000;;, + 1600;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961571,0.000002,0.000002,1.000000;;, + 1680;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961573,-0.000002,0.000001,1.000000;;, + 1760;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961590,-0.000005,-0.000004,1.000000;;, + 1840;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961571,-0.000000,0.000000,1.000000;;, + 1920;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961586,0.000002,0.000003,1.000000;;, + 2000;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961561,-0.000004,-0.000000,1.000000;;, + 2080;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961565,-0.000010,0.000003,1.000000;;, + 2160;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961571,0.000005,-0.000002,1.000000;;, + 2240;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961568,-0.000010,0.000002,1.000000;;, + 2320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961582,-0.000001,0.000000,1.000000;;, + 2400;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961562,-0.000001,0.000003,1.000000;;, + 2480;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961565,0.000005,0.000001,1.000000;;, + 2560;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961569,0.000001,0.000004,1.000000;;, + 2640;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961572,0.000005,-0.000000,1.000000;;, + 2720;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961578,0.000008,-0.000005,1.000000;;, + 2800;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961580,0.000013,-0.000000,1.000000;;, + 2880;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961571,-0.000005,0.000003,1.000000;;, + 2960;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961578,-0.000008,0.000000,1.000000;;, + 3040;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961578,-0.000012,0.000004,1.000000;;, + 3120;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961567,-0.000010,0.000005,1.000000;;, + 3200;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961571,-0.000007,0.000005,1.000000;;, + 3280;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961579,0.000017,-0.000002,1.000000;;, + 3360;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961581,0.000006,-0.000003,1.000000;;, + 3440;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961584,0.000001,-0.000004,1.000000;;, + 3520;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961576,-0.000014,0.000005,1.000000;;, + 3600;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961581,0.000002,-0.000007,1.000000;;, + 3680;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961588,0.000002,-0.000007,1.000000;;, + 3760;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961570,-0.000007,0.000005,1.000000;;, + 3840;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961579,0.000004,-0.000002,1.000000;;, + 3920;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961581,0.000002,-0.000001,1.000000;;, + 4000;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961569,-0.000010,0.000008,1.000000;;, + 4080;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961600,0.000003,-0.000014,1.000000;;, + 4160;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961583,0.000002,-0.000000,1.000000;;, + 4240;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961576,0.000004,-0.000008,1.000000;;, + 4320;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961551,0.000002,0.000005,1.000000;;, + 4400;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961569,0.000004,0.000001,1.000000;;, + 4480;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961553,0.000008,0.000013,1.000000;;, + 4560;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961561,0.000010,0.000003,1.000000;;, + 4640;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961563,0.000016,0.000001,1.000000;;, + 4720;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961555,0.000000,0.000016,1.000000;;, + 4800;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961566,-0.000008,0.000003,1.000000;;, + 4960;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961576,0.000009,-0.000003,1.000000;;; + } + { Dummy06 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.088003,0.354686,-0.505020,1.000000;;, + 80;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088007,0.354687,-0.505029,1.000000;;, + 160;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088003,0.354683,-0.505037,1.000000;;, + 240;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087999,0.354689,-0.505027,1.000000;;, + 320;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087999,0.354678,-0.505037,1.000000;;, + 400;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088018,0.354682,-0.505016,1.000000;;, + 480;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087997,0.354684,-0.505036,1.000000;;, + 560;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087997,0.354680,-0.505038,1.000000;;, + 640;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087982,0.354697,-0.505025,1.000000;;, + 720;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087984,0.354686,-0.505039,1.000000;;, + 800;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087999,0.354695,-0.505016,1.000000;;, + 880;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087994,0.354693,-0.505023,1.000000;;, + 960;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088020,0.354688,-0.505014,1.000000;;, + 1040;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088017,0.354669,-0.505036,1.000000;;, + 1120;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087996,0.354682,-0.505036,1.000000;;, + 1200;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087994,0.354682,-0.505039,1.000000;;, + 1280;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.087999,0.354684,-0.505032,1.000000;;, + 1360;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087997,0.354686,-0.505034,1.000000;;, + 1440;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088001,0.354692,-0.505020,1.000000;;, + 1520;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.088009,0.354688,-0.505025,1.000000;;, + 1600;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088003,0.354678,-0.505034,1.000000;;, + 1680;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.087992,0.354686,-0.505022,1.000000;;, + 1760;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.087994,0.354689,-0.505026,1.000000;;, + 1840;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.088005,0.354687,-0.505022,1.000000;;, + 1920;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087996,0.354682,-0.505020,1.000000;;, + 2000;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087999,0.354694,-0.505015,1.000000;;, + 2080;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088005,0.354690,-0.505026,1.000000;;, + 2160;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088007,0.354689,-0.505020,1.000000;;, + 2240;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088007,0.354691,-0.505020,1.000000;;, + 2320;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088007,0.354685,-0.505026,1.000000;;, + 2400;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088003,0.354688,-0.505016,1.000000;;, + 2480;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088007,0.354692,-0.505024,1.000000;;, + 2560;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088001,0.354689,-0.505018,1.000000;;, + 2640;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088001,0.354689,-0.505016,1.000000;;, + 2720;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.087994,0.354685,-0.505033,1.000000;;, + 2800;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.088005,0.354682,-0.505036,1.000000;;, + 2880;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.087996,0.354688,-0.505025,1.000000;;, + 2960;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087997,0.354684,-0.505037,1.000000;;, + 3040;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088001,0.354691,-0.505015,1.000000;;, + 3120;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087999,0.354692,-0.505020,1.000000;;, + 3200;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.088005,0.354682,-0.505040,1.000000;;, + 3280;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.088001,0.354681,-0.505039,1.000000;;, + 3360;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088001,0.354691,-0.505018,1.000000;;, + 3440;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.088003,0.354685,-0.505025,1.000000;;, + 3520;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088007,0.354681,-0.505039,1.000000;;, + 3600;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.087997,0.354683,-0.505033,1.000000;;, + 3680;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.088005,0.354683,-0.505036,1.000000;;, + 3760;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.087997,0.354693,-0.505018,1.000000;;, + 3840;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.088005,0.354691,-0.505020,1.000000;;, + 3920;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088005,0.354683,-0.505038,1.000000;;, + 4000;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087996,0.354698,-0.505015,1.000000;;, + 4080;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087996,0.354699,-0.505005,1.000000;;, + 4160;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088001,0.354686,-0.505031,1.000000;;, + 4240;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088005,0.354692,-0.505021,1.000000;;, + 4320;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087988,0.354712,-0.505011,1.000000;;, + 4400;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.087994,0.354686,-0.505024,1.000000;;, + 4480;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.088018,0.354674,-0.505038,1.000000;;, + 4560;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.088011,0.354684,-0.505024,1.000000;;, + 4640;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.087997,0.354688,-0.505028,1.000000;;, + 4720;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.088015,0.354667,-0.505041,1.000000;;, + 4800;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,0.000000,0.000796,1.000000,0.000000,24.087988,0.354694,-0.505022,1.000000;;, + 4960;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000796,0.000000,-0.000000,0.000796,1.000000,0.000000,24.088003,0.354686,-0.505020,1.000000;;; + } + { Bip01_L_Finger1 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300064,0.000003,0.000006,1.000000;;, + 80;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300063,0.000007,0.000011,1.000000;;, + 160;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300055,0.000007,0.000007,1.000000;;, + 240;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300056,-0.000004,-0.000002,1.000000;;, + 320;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300056,0.000004,0.000004,1.000000;;, + 400;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300014,0.000025,0.000014,1.000000;;, + 480;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300039,-0.000004,-0.000015,1.000000;;, + 560;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300041,0.000005,0.000004,1.000000;;, + 640;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300058,-0.000005,-0.000002,1.000000;;, + 720;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300057,0.000007,0.000014,1.000000;;, + 800;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300075,0.000004,0.000018,1.000000;;, + 880;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300048,-0.000009,-0.000014,1.000000;;, + 960;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300048,-0.000006,-0.000015,1.000000;;, + 1040;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300055,-0.000009,-0.000013,1.000000;;, + 1120;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300047,-0.000007,-0.000015,1.000000;;, + 1200;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300065,-0.000006,0.000000,1.000000;;, + 1280;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300060,0.000002,0.000007,1.000000;;, + 1360;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300070,0.000006,0.000019,1.000000;;, + 1440;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300065,-0.000004,-0.000004,1.000000;;, + 1520;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300047,0.000002,0.000002,1.000000;;, + 1600;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300076,0.000005,-0.000013,1.000000;;, + 1680;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300056,0.000000,-0.000000,1.000000;;, + 1760;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300069,0.000001,0.000005,1.000000;;, + 1840;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300046,-0.000004,0.000008,1.000000;;, + 1920;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300068,-0.000004,0.000000,1.000000;;, + 2000;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300057,0.000006,0.000016,1.000000;;, + 2080;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300053,0.000001,0.000011,1.000000;;, + 2160;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300057,-0.000007,0.000001,1.000000;;, + 2240;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300064,-0.000003,-0.000011,1.000000;;, + 2320;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300056,-0.000001,-0.000002,1.000000;;, + 2400;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300053,-0.000002,-0.000014,1.000000;;, + 2480;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300054,0.000002,0.000003,1.000000;;, + 2560;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300058,-0.000009,-0.000011,1.000000;;, + 2640;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300057,-0.000009,-0.000017,1.000000;;, + 2720;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300058,-0.000002,-0.000006,1.000000;;, + 2800;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300055,-0.000003,-0.000003,1.000000;;, + 2880;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300047,0.000005,0.000011,1.000000;;, + 2960;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300066,-0.000004,-0.000015,1.000000;;, + 3040;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300047,-0.000005,-0.000022,1.000000;;, + 3120;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300045,-0.000003,-0.000006,1.000000;;, + 3200;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300055,-0.000001,0.000005,1.000000;;, + 3280;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300045,-0.000015,-0.000028,1.000000;;, + 3360;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300060,0.000003,0.000007,1.000000;;, + 3440;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300044,-0.000006,-0.000009,1.000000;;, + 3520;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300054,0.000006,0.000008,1.000000;;, + 3600;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300052,-0.000004,-0.000001,1.000000;;, + 3680;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300062,-0.000000,0.000005,1.000000;;, + 3760;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300060,0.000009,0.000010,1.000000;;, + 3840;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300045,0.000013,0.000027,1.000000;;, + 3920;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300067,-0.000013,-0.000011,1.000000;;, + 4000;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300056,-0.000005,0.000000,1.000000;;, + 4080;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300039,0.000021,0.000035,1.000000;;, + 4160;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300084,-0.000016,-0.000027,1.000000;;, + 4240;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300084,-0.000017,-0.000021,1.000000;;, + 4320;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300045,0.000006,0.000015,1.000000;;, + 4400;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300069,-0.000006,-0.000006,1.000000;;, + 4480;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300056,0.000011,0.000010,1.000000;;, + 4560;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300076,-0.000007,-0.000010,1.000000;;, + 4640;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300057,-0.000006,-0.000009,1.000000;;, + 4720;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300072,-0.000010,-0.000010,1.000000;;, + 4800;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300090,-0.000022,-0.000024,1.000000;;, + 4960;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300064,0.000003,0.000006,1.000000;;; + } + { Bip01_L_Finger11 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850065,0.000001,-0.000008,1.000000;;, + 80;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850067,-0.000012,-0.000005,1.000000;;, + 160;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850059,-0.000008,-0.000011,1.000000;;, + 240;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850067,0.000001,0.000003,1.000000;;, + 320;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850051,0.000009,0.000004,1.000000;;, + 400;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850072,-0.000023,-0.000038,1.000000;;, + 480;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850061,0.000006,0.000004,1.000000;;, + 560;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850071,-0.000013,-0.000012,1.000000;;, + 640;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850073,-0.000001,-0.000002,1.000000;;, + 720;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850061,-0.000004,-0.000007,1.000000;;, + 800;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850033,-0.000012,-0.000037,1.000000;;, + 880;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850089,-0.000003,0.000006,1.000000;;, + 960;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850071,0.000006,0.000006,1.000000;;, + 1040;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850063,0.000002,0.000003,1.000000;;, + 1120;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850079,-0.000002,0.000002,1.000000;;, + 1200;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850054,0.000004,-0.000002,1.000000;;, + 1280;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850033,0.000003,-0.000019,1.000000;;, + 1360;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850060,-0.000001,0.000000,1.000000;;, + 1440;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850060,-0.000002,0.000002,1.000000;;, + 1520;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850078,-0.000007,-0.000004,1.000000;;, + 1600;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850050,-0.000006,0.000007,1.000000;;, + 1680;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850048,0.000007,0.000000,1.000000;;, + 1760;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850069,0.000001,-0.000017,1.000000;;, + 1840;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850089,0.000007,-0.000004,1.000000;;, + 1920;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850056,0.000012,0.000020,1.000000;;, + 2000;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850053,-0.000007,-0.000005,1.000000;;, + 2080;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850065,-0.000002,-0.000010,1.000000;;, + 2160;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850060,0.000009,-0.000003,1.000000;;, + 2240;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850053,0.000000,-0.000000,1.000000;;, + 2320;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850065,0.000006,0.000002,1.000000;;, + 2400;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850070,0.000000,0.000011,1.000000;;, + 2480;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850060,-0.000006,-0.000010,1.000000;;, + 2560;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850062,0.000004,0.000002,1.000000;;, + 2640;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850082,0.000004,0.000002,1.000000;;, + 2720;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850064,0.000001,-0.000002,1.000000;;, + 2800;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850072,0.000007,0.000007,1.000000;;, + 2880;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850075,-0.000000,-0.000010,1.000000;;, + 2960;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850063,0.000002,0.000011,1.000000;;, + 3040;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850078,0.000013,0.000042,1.000000;;, + 3120;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850089,-0.000001,-0.000006,1.000000;;, + 3200;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850073,0.000010,0.000013,1.000000;;, + 3280;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850079,0.000021,0.000042,1.000000;;, + 3360;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850069,-0.000005,-0.000008,1.000000;;, + 3440;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850072,0.000013,0.000025,1.000000;;, + 3520;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850064,-0.000001,0.000000,1.000000;;, + 3600;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850068,-0.000004,-0.000008,1.000000;;, + 3680;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850067,-0.000010,-0.000026,1.000000;;, + 3760;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850063,-0.000014,-0.000005,1.000000;;, + 3840;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850078,-0.000021,-0.000040,1.000000;;, + 3920;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850061,0.000001,-0.000003,1.000000;;, + 4000;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850081,-0.000003,-0.000007,1.000000;;, + 4080;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850072,-0.000017,-0.000023,1.000000;;, + 4160;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850025,0.000036,0.000062,1.000000;;, + 4240;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850046,0.000018,0.000011,1.000000;;, + 4320;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850097,-0.000030,-0.000042,1.000000;;, + 4400;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850051,0.000014,0.000013,1.000000;;, + 4480;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850077,-0.000010,-0.000012,1.000000;;, + 4560;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850067,-0.000007,-0.000006,1.000000;;, + 4640;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850060,0.000006,0.000009,1.000000;;, + 4720;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850066,0.000001,-0.000007,1.000000;;, + 4800;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850065,0.000028,0.000040,1.000000;;, + 4960;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850065,0.000001,-0.000008,1.000000;;; + } + { Bip01_L_Finger12 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207764,0.000008,0.000012,1.000000;;, + 80;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,11.207752,0.000001,-0.000009,1.000000;;, + 160;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,11.207758,-0.000006,-0.000005,1.000000;;, + 240;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,11.207754,0.000013,0.000008,1.000000;;, + 320;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,11.207761,-0.000003,-0.000001,1.000000;;, + 400;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,11.207761,0.000004,0.000010,1.000000;;, + 480;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,11.207757,-0.000003,0.000000,1.000000;;, + 560;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,11.207770,-0.000005,-0.000006,1.000000;;, + 640;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207747,0.000006,-0.000002,1.000000;;, + 720;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,11.207773,0.000003,-0.000002,1.000000;;, + 800;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,11.207769,0.000006,0.000008,1.000000;;, + 880;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,11.207754,0.000004,0.000008,1.000000;;, + 960;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,11.207753,0.000009,0.000010,1.000000;;, + 1040;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,11.207757,0.000009,0.000006,1.000000;;, + 1120;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,11.207743,0.000002,-0.000000,1.000000;;, + 1200;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,11.207767,-0.000013,-0.000008,1.000000;;, + 1280;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,11.207783,0.000011,0.000022,1.000000;;, + 1360;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207764,-0.000002,0.000000,1.000000;;, + 1440;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,11.207756,-0.000002,-0.000000,1.000000;;, + 1520;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207762,0.000002,0.000001,1.000000;;, + 1600;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,11.207761,0.000001,-0.000005,1.000000;;, + 1680;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207769,-0.000003,0.000000,1.000000;;, + 1760;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,11.207753,0.000002,0.000003,1.000000;;, + 1840;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,11.207752,0.000005,-0.000002,1.000000;;, + 1920;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,11.207760,-0.000011,-0.000011,1.000000;;, + 2000;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,11.207770,-0.000000,-0.000003,1.000000;;, + 2080;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,11.207766,0.000006,0.000004,1.000000;;, + 2160;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,11.207768,-0.000001,-0.000000,1.000000;;, + 2240;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,11.207764,-0.000002,0.000002,1.000000;;, + 2320;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,11.207757,-0.000010,-0.000012,1.000000;;, + 2400;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,11.207762,0.000002,0.000014,1.000000;;, + 2480;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207767,-0.000003,0.000003,1.000000;;, + 2560;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,11.207757,0.000005,0.000015,1.000000;;, + 2640;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207755,0.000002,0.000006,1.000000;;, + 2720;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,11.207770,-0.000002,-0.000001,1.000000;;, + 2800;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207756,-0.000006,-0.000010,1.000000;;, + 2880;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,11.207760,-0.000000,0.000002,1.000000;;, + 2960;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,11.207756,0.000005,0.000012,1.000000;;, + 3040;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207765,-0.000007,-0.000011,1.000000;;, + 3120;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,11.207755,0.000004,0.000013,1.000000;;, + 3200;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,11.207761,-0.000004,-0.000010,1.000000;;, + 3280;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,11.207756,-0.000007,-0.000016,1.000000;;, + 3360;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,11.207761,-0.000004,-0.000012,1.000000;;, + 3440;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,11.207767,-0.000005,-0.000007,1.000000;;, + 3520;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,11.207764,-0.000003,-0.000005,1.000000;;, + 3600;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,11.207770,0.000003,0.000006,1.000000;;, + 3680;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,11.207760,0.000007,0.000009,1.000000;;, + 3760;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207760,0.000005,0.000003,1.000000;;, + 3840;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207765,0.000008,0.000006,1.000000;;, + 3920;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,11.207769,0.000001,-0.000002,1.000000;;, + 4000;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207773,0.000001,-0.000000,1.000000;;, + 4080;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,11.207779,-0.000013,-0.000017,1.000000;;, + 4160;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,11.207768,-0.000015,-0.000020,1.000000;;, + 4240;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207767,-0.000003,-0.000003,1.000000;;, + 4320;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,11.207754,0.000010,0.000015,1.000000;;, + 4400;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,11.207767,-0.000011,-0.000015,1.000000;;, + 4480;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207764,-0.000007,-0.000010,1.000000;;, + 4560;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,11.207754,0.000014,0.000006,1.000000;;, + 4640;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207787,-0.000006,-0.000010,1.000000;;, + 4720;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,11.207737,0.000012,0.000015,1.000000;;, + 4800;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207734,-0.000002,-0.000004,1.000000;;, + 4960;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,11.207764,0.000008,0.000012,1.000000;;; + } + { Dummy03 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;-0.407607,0.378871,-0.830851,0.000000,-0.503079,-0.852505,-0.141940,0.000000,-0.762081,0.360128,0.538089,0.000000,-12.374953,4.006935,-8.346194,1.000000;;, + 80;16;-0.416514,0.377872,-0.826879,0.000000,-0.503483,-0.853189,-0.136282,0.000000,-0.756981,0.359556,0.545618,0.000000,-12.374949,4.006937,-8.346193,1.000000;;, + 160;16;-0.425366,0.376888,-0.822812,0.000000,-0.503870,-0.853846,-0.130619,0.000000,-0.751784,0.359030,0.553099,0.000000,-12.374967,4.006944,-8.346194,1.000000;;, + 240;16;-0.434586,0.375814,-0.818474,0.000000,-0.504263,-0.854512,-0.124612,0.000000,-0.746227,0.358572,0.560867,0.000000,-12.374971,4.006948,-8.346193,1.000000;;, + 320;16;-0.442896,0.374968,-0.814397,0.000000,-0.504596,-0.855076,-0.119281,0.000000,-0.741098,0.358112,0.567917,0.000000,-12.374956,4.006941,-8.346194,1.000000;;, + 400;16;-0.449149,0.374601,-0.811134,0.000000,-0.504821,-0.855457,-0.115536,0.000000,-0.737171,0.357585,0.573335,0.000000,-12.374967,4.006938,-8.346195,1.000000;;, + 480;16;-0.453500,0.374765,-0.808634,0.000000,-0.504947,-0.855671,-0.113379,0.000000,-0.734415,0.356900,0.577284,0.000000,-12.374941,4.006937,-8.346192,1.000000;;, + 560;16;-0.455431,0.375689,-0.807118,0.000000,-0.504948,-0.855673,-0.113364,0.000000,-0.733219,0.355924,0.579404,0.000000,-12.374949,4.006939,-8.346192,1.000000;;, + 640;16;-0.455793,0.377101,-0.806255,0.000000,-0.504868,-0.855537,-0.114738,0.000000,-0.733049,0.354756,0.580334,0.000000,-12.374961,4.006935,-8.346194,1.000000;;, + 720;16;-0.455233,0.378873,-0.805741,0.000000,-0.504733,-0.855308,-0.117013,0.000000,-0.733490,0.353416,0.580594,0.000000,-12.374965,4.006937,-8.346196,1.000000;;, + 800;16;-0.453797,0.380821,-0.805633,0.000000,-0.504555,-0.855006,-0.119953,0.000000,-0.734501,0.352051,0.580144,0.000000,-12.374959,4.006924,-8.346196,1.000000;;, + 880;16;-0.451680,0.382774,-0.805897,0.000000,-0.504349,-0.854657,-0.123262,0.000000,-0.735947,0.350778,0.579083,0.000000,-12.374973,4.006937,-8.346195,1.000000;;, + 960;16;-0.449073,0.384565,-0.806500,0.000000,-0.504132,-0.854290,-0.126643,0.000000,-0.737688,0.349711,0.577511,0.000000,-12.374933,4.006945,-8.346191,1.000000;;, + 1040;16;-0.446313,0.385962,-0.807365,0.000000,-0.503934,-0.853955,-0.129659,0.000000,-0.739496,0.348991,0.575631,0.000000,-12.374995,4.006943,-8.346198,1.000000;;, + 1120;16;-0.443171,0.386969,-0.808612,0.000000,-0.503748,-0.853639,-0.132431,0.000000,-0.741510,0.348647,0.573244,0.000000,-12.374972,4.006928,-8.346197,1.000000;;, + 1200;16;-0.439593,0.387489,-0.810315,0.000000,-0.503580,-0.853355,-0.134880,0.000000,-0.743751,0.348767,0.570260,0.000000,-12.374940,4.006937,-8.346193,1.000000;;, + 1280;16;-0.435395,0.387588,-0.812532,0.000000,-0.503420,-0.853083,-0.137174,0.000000,-0.746324,0.349320,0.566547,0.000000,-12.374939,4.006934,-8.346193,1.000000;;, + 1360;16;-0.430296,0.387329,-0.815366,0.000000,-0.503253,-0.852800,-0.139529,0.000000,-0.749388,0.350297,0.561881,0.000000,-12.374988,4.006957,-8.346195,1.000000;;, + 1440;16;-0.424518,0.386623,-0.818723,0.000000,-0.503094,-0.852531,-0.141727,0.000000,-0.752782,0.351729,0.556423,0.000000,-12.374943,4.006949,-8.346193,1.000000;;, + 1520;16;-0.418227,0.385487,-0.822488,0.000000,-0.502949,-0.852285,-0.143708,0.000000,-0.756392,0.353567,0.550329,0.000000,-12.374943,4.006932,-8.346193,1.000000;;, + 1600;16;-0.411315,0.383640,-0.826825,0.000000,-0.502837,-0.852095,-0.145222,0.000000,-0.760247,0.356026,0.543388,0.000000,-12.374963,4.006937,-8.346194,1.000000;;, + 1680;16;-0.403712,0.380662,-0.831933,0.000000,-0.502789,-0.852014,-0.145862,0.000000,-0.764343,0.359401,0.535361,0.000000,-12.374950,4.006958,-8.346194,1.000000;;, + 1760;16;-0.395471,0.376937,-0.837569,0.000000,-0.502776,-0.851992,-0.146034,0.000000,-0.768647,0.363357,0.526453,0.000000,-12.374956,4.006951,-8.346193,1.000000;;, + 1840;16;-0.386531,0.372472,-0.843717,0.000000,-0.502794,-0.852022,-0.145794,0.000000,-0.773170,0.367862,0.516610,0.000000,-12.374984,4.006931,-8.346196,1.000000;;, + 1920;16;-0.377170,0.368002,-0.849892,0.000000,-0.502794,-0.852023,-0.145791,0.000000,-0.777779,0.372333,0.506387,0.000000,-12.374930,4.006939,-8.346193,1.000000;;, + 2000;16;-0.367752,0.364251,-0.855616,0.000000,-0.502734,-0.851920,-0.146598,0.000000,-0.782315,0.376236,0.496417,0.000000,-12.374946,4.006942,-8.346193,1.000000;;, + 2080;16;-0.357990,0.361378,-0.860958,0.000000,-0.502589,-0.851675,-0.148502,0.000000,-0.786922,0.379546,0.486516,0.000000,-12.374934,4.006934,-8.346194,1.000000;;, + 2160;16;-0.347639,0.359976,-0.865774,0.000000,-0.502302,-0.851189,-0.152220,0.000000,-0.791732,0.381963,0.476723,0.000000,-12.374949,4.006957,-8.346195,1.000000;;, + 2240;16;-0.336935,0.359491,-0.870196,0.000000,-0.501919,-0.850540,-0.157031,0.000000,-0.796588,0.383859,0.467012,0.000000,-12.374945,4.006944,-8.346195,1.000000;;, + 2320;16;-0.325771,0.359640,-0.874375,0.000000,-0.501454,-0.849752,-0.162683,0.000000,-0.801509,0.385462,0.457168,0.000000,-12.374968,4.006936,-8.346194,1.000000;;, + 2400;16;-0.314956,0.360150,-0.878120,0.000000,-0.500958,-0.848912,-0.168492,0.000000,-0.806129,0.386834,0.447790,0.000000,-12.374965,4.006927,-8.346193,1.000000;;, + 2480;16;-0.305369,0.360675,-0.881285,0.000000,-0.500500,-0.848135,-0.173683,0.000000,-0.810092,0.388046,0.439513,0.000000,-12.374954,4.006912,-8.346193,1.000000;;, + 2560;16;-0.296753,0.361113,-0.884045,0.000000,-0.500082,-0.847426,-0.178289,0.000000,-0.813545,0.389187,0.432063,0.000000,-12.374963,4.006956,-8.346196,1.000000;;, + 2640;16;-0.289142,0.361135,-0.886554,0.000000,-0.499739,-0.846845,-0.181974,0.000000,-0.816491,0.390429,0.425332,0.000000,-12.374942,4.006930,-8.346194,1.000000;;, + 2720;16;-0.282525,0.361066,-0.888713,0.000000,-0.499444,-0.846346,-0.185078,0.000000,-0.818984,0.391574,0.419446,0.000000,-12.374970,4.006927,-8.346194,1.000000;;, + 2800;16;-0.276615,0.361050,-0.890577,0.000000,-0.499173,-0.845887,-0.187887,0.000000,-0.821164,0.392580,0.414212,0.000000,-12.374959,4.006913,-8.346193,1.000000;;, + 2880;16;-0.272267,0.361310,-0.891810,0.000000,-0.498945,-0.845500,-0.190221,0.000000,-0.822754,0.393174,0.410475,0.000000,-12.374945,4.006962,-8.346195,1.000000;;, + 2960;16;-0.269968,0.362030,-0.892217,0.000000,-0.498766,-0.845196,-0.192033,0.000000,-0.823620,0.393164,0.408744,0.000000,-12.374956,4.006938,-8.346194,1.000000;;, + 3040;16;-0.270530,0.363477,-0.891458,0.000000,-0.498648,-0.844997,-0.193209,0.000000,-0.823507,0.392256,0.409844,0.000000,-12.374985,4.006958,-8.346195,1.000000;;, + 3120;16;-0.275395,0.366133,-0.888878,0.000000,-0.498614,-0.844939,-0.193552,0.000000,-0.821913,0.389904,0.415251,0.000000,-12.374957,4.006952,-8.346194,1.000000;;, + 3200;16;-0.283099,0.369485,-0.885062,0.000000,-0.498643,-0.844989,-0.193258,0.000000,-0.819274,0.386619,0.423457,0.000000,-12.374984,4.006936,-8.346194,1.000000;;, + 3280;16;-0.293334,0.373412,-0.880067,0.000000,-0.498733,-0.845141,-0.192360,0.000000,-0.815610,0.382493,0.434142,0.000000,-12.374942,4.006941,-8.346195,1.000000;;, + 3360;16;-0.304042,0.377235,-0.874787,0.000000,-0.498853,-0.845343,-0.191156,0.000000,-0.811606,0.378270,0.445204,0.000000,-12.374965,4.006917,-8.346193,1.000000;;, + 3440;16;-0.313157,0.380268,-0.870246,0.000000,-0.498974,-0.845550,-0.189922,0.000000,-0.808058,0.374755,0.454534,0.000000,-12.374965,4.006925,-8.346195,1.000000;;, + 3520;16;-0.320549,0.382559,-0.866543,0.000000,-0.499089,-0.845743,-0.188755,0.000000,-0.805083,0.371977,0.462034,0.000000,-12.374962,4.006930,-8.346194,1.000000;;, + 3600;16;-0.324950,0.383778,-0.864362,0.000000,-0.499171,-0.845882,-0.187914,0.000000,-0.803266,0.370402,0.466440,0.000000,-12.374987,4.006938,-8.346194,1.000000;;, + 3680;16;-0.327753,0.384378,-0.863036,0.000000,-0.499241,-0.846000,-0.187195,0.000000,-0.802083,0.369509,0.469176,0.000000,-12.374971,4.006967,-8.346194,1.000000;;, + 3760;16;-0.329814,0.384682,-0.862115,0.000000,-0.499305,-0.846110,-0.186524,0.000000,-0.801197,0.368940,0.471133,0.000000,-12.374954,4.006938,-8.346195,1.000000;;, + 3840;16;-0.331424,0.384701,-0.861489,0.000000,-0.499378,-0.846233,-0.185773,0.000000,-0.800488,0.368639,0.472573,0.000000,-12.374972,4.006914,-8.346196,1.000000;;, + 3920;16;-0.333010,0.384524,-0.860956,0.000000,-0.499468,-0.846387,-0.184826,0.000000,-0.799772,0.368471,0.473913,0.000000,-12.374987,4.006909,-8.346196,1.000000;;, + 4000;16;-0.335002,0.384236,-0.860312,0.000000,-0.499588,-0.846590,-0.183569,0.000000,-0.798865,0.368306,0.475568,0.000000,-12.374951,4.006948,-8.346193,1.000000;;, + 4080;16;-0.337949,0.383968,-0.859279,0.000000,-0.499749,-0.846861,-0.181872,0.000000,-0.797522,0.367960,0.478083,0.000000,-12.374978,4.006943,-8.346195,1.000000;;, + 4160;16;-0.341894,0.383677,-0.857847,0.000000,-0.499955,-0.847211,-0.179663,0.000000,-0.795709,0.367459,0.481477,0.000000,-12.374969,4.006939,-8.346195,1.000000;;, + 4240;16;-0.347213,0.383380,-0.855840,0.000000,-0.500220,-0.847661,-0.176777,0.000000,-0.793235,0.366729,0.486094,0.000000,-12.374987,4.006929,-8.346196,1.000000;;, + 4320;16;-0.353440,0.383022,-0.853448,0.000000,-0.500528,-0.848182,-0.173374,0.000000,-0.790286,0.365897,0.491495,0.000000,-12.374973,4.006942,-8.346195,1.000000;;, + 4400;16;-0.360300,0.382532,-0.850795,0.000000,-0.500870,-0.848762,-0.169506,0.000000,-0.786964,0.365065,0.497408,0.000000,-12.374979,4.006924,-8.346196,1.000000;;, + 4480;16;-0.367604,0.381976,-0.847916,0.000000,-0.501231,-0.849373,-0.165330,0.000000,-0.783349,0.364226,0.503691,0.000000,-12.374952,4.006930,-8.346195,1.000000;;, + 4560;16;-0.375143,0.381385,-0.844874,0.000000,-0.501596,-0.849993,-0.160976,0.000000,-0.779531,0.363397,0.510171,0.000000,-12.374953,4.006931,-8.346195,1.000000;;, + 4640;16;-0.382715,0.380790,-0.841741,0.000000,-0.501956,-0.850602,-0.156574,0.000000,-0.775609,0.362594,0.516678,0.000000,-12.374963,4.006971,-8.346191,1.000000;;, + 4720;16;-0.389985,0.380241,-0.838647,0.000000,-0.502292,-0.851172,-0.152345,0.000000,-0.771760,0.361833,0.522937,0.000000,-12.374979,4.006922,-8.346197,1.000000;;, + 4800;16;-0.397155,0.379708,-0.835518,0.000000,-0.502616,-0.851720,-0.148157,0.000000,-0.767883,0.361103,0.529112,0.000000,-12.374941,4.006959,-8.346190,1.000000;;, + 4960;16;-0.407607,0.378871,-0.830851,0.000000,-0.503079,-0.852505,-0.141940,0.000000,-0.762081,0.360128,0.538089,0.000000,-12.374953,4.006935,-8.346194,1.000000;;; + } + { Bip01_R_Clavicle } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.452612,0.717604,0.529327,0.000000,-0.426220,0.695510,-0.578448,0.000000,-0.783248,0.036203,0.620654,0.000000,31.000202,0.000005,0.000011,1.000000;;, + 80;16;0.440682,0.740856,0.506885,0.000000,-0.451457,0.670977,-0.588197,0.000000,-0.775877,0.030371,0.630152,0.000000,31.000204,0.000006,0.000021,1.000000;;, + 160;16;0.428367,0.763154,0.483836,0.000000,-0.476352,0.645727,-0.596763,0.000000,-0.767848,0.025157,0.640138,0.000000,31.000195,0.000000,0.000005,1.000000;;, + 240;16;0.415061,0.785612,0.458845,0.000000,-0.502242,0.618382,-0.604447,0.000000,-0.758602,0.020432,0.651234,0.000000,31.000191,0.000002,-0.000009,1.000000;;, + 320;16;0.403766,0.804658,0.435315,0.000000,-0.523951,0.593447,-0.610980,0.000000,-0.749966,0.018609,0.661214,0.000000,31.000191,-0.000002,-0.000000,1.000000;;, + 400;16;0.398536,0.817319,0.416123,0.000000,-0.536147,0.575729,-0.617319,0.000000,-0.744121,0.022920,0.667651,0.000000,31.000198,0.000007,0.000008,1.000000;;, + 480;16;0.397056,0.825128,0.401882,0.000000,-0.541189,0.564142,-0.623584,0.000000,-0.741256,0.030103,0.670547,0.000000,31.000196,0.000003,-0.000004,1.000000;;, + 560;16;0.399127,0.827686,0.394503,0.000000,-0.537802,0.559803,-0.630388,0.000000,-0.742608,0.039440,0.668564,0.000000,31.000212,0.000006,0.000019,1.000000;;, + 640;16;0.401665,0.827066,0.393225,0.000000,-0.530635,0.560148,-0.636129,0.000000,-0.746385,0.046852,0.663863,0.000000,31.000185,-0.000010,-0.000016,1.000000;;, + 720;16;0.400325,0.825301,0.398269,0.000000,-0.524681,0.562755,-0.638762,0.000000,-0.751298,0.046748,0.658305,0.000000,31.000183,-0.000005,-0.000014,1.000000;;, + 800;16;0.398441,0.821326,0.408251,0.000000,-0.517931,0.568828,-0.638891,0.000000,-0.756962,0.043114,0.652034,0.000000,31.000177,-0.000015,-0.000009,1.000000;;, + 880;16;0.397144,0.814737,0.422469,0.000000,-0.510570,0.578657,-0.635983,0.000000,-0.762623,0.036877,0.645791,0.000000,31.000189,-0.000002,-0.000010,1.000000;;, + 960;16;0.398858,0.805317,0.438607,0.000000,-0.501479,0.591997,-0.630920,0.000000,-0.767744,0.031695,0.639972,0.000000,31.000191,0.000008,-0.000007,1.000000;;, + 1040;16;0.404275,0.793806,0.454349,0.000000,-0.490979,0.607461,-0.624444,0.000000,-0.771687,0.029371,0.635324,0.000000,31.000198,-0.000008,0.000000,1.000000;;, + 1120;16;0.419312,0.777423,0.468819,0.000000,-0.474527,0.627936,-0.616863,0.000000,-0.773952,0.036190,0.632209,0.000000,31.000189,-0.000005,-0.000004,1.000000;;, + 1200;16;0.451385,0.752533,0.479527,0.000000,-0.446152,0.655725,-0.609076,0.000000,-0.772787,0.060986,0.631728,0.000000,31.000206,0.000001,0.000017,1.000000;;, + 1280;16;0.494407,0.719313,0.488007,0.000000,-0.408289,0.687812,-0.600179,0.000000,-0.767373,0.097484,0.633746,0.000000,31.000200,-0.000005,0.000008,1.000000;;, + 1360;16;0.547995,0.674778,0.494344,0.000000,-0.358778,0.723465,-0.589811,0.000000,-0.755632,0.145854,0.638550,0.000000,31.000196,0.000009,0.000008,1.000000;;, + 1440;16;0.600843,0.623908,0.499727,0.000000,-0.305625,0.756956,-0.577591,0.000000,-0.738634,0.194312,0.645493,0.000000,31.000193,0.000008,-0.000003,1.000000;;, + 1520;16;0.644029,0.573665,0.506098,0.000000,-0.257437,0.785502,-0.562773,0.000000,-0.720384,0.232153,0.653569,0.000000,31.000195,0.000002,0.000005,1.000000;;, + 1600;16;0.677819,0.525861,0.513841,0.000000,-0.215097,0.810139,-0.545351,0.000000,-0.703061,0.259123,0.662239,0.000000,31.000196,-0.000014,0.000000,1.000000;;, + 1680;16;0.698452,0.486218,0.525127,0.000000,-0.184156,0.831166,-0.524642,0.000000,-0.691557,0.269732,0.670069,0.000000,31.000195,-0.000029,-0.000009,1.000000;;, + 1760;16;0.712112,0.450626,0.538362,0.000000,-0.159496,0.850613,-0.501018,0.000000,-0.683709,0.270914,0.677605,0.000000,31.000202,-0.000005,0.000012,1.000000;;, + 1840;16;0.722193,0.416114,0.552528,0.000000,-0.137589,0.869265,-0.474813,0.000000,-0.677869,0.266885,0.685029,0.000000,31.000195,-0.000011,-0.000001,1.000000;;, + 1920;16;0.729968,0.381999,0.566766,0.000000,-0.117977,0.887209,-0.446028,0.000000,-0.673222,0.258721,0.692701,0.000000,31.000196,0.000019,0.000001,1.000000;;, + 2000;16;0.737439,0.347148,0.579373,0.000000,-0.099271,0.904197,-0.415420,0.000000,-0.668079,0.248832,0.701251,0.000000,31.000193,0.000022,0.000011,1.000000;;, + 2080;16;0.744879,0.309606,0.591015,0.000000,-0.080023,0.920878,-0.381550,0.000000,-0.662383,0.236914,0.710718,0.000000,31.000204,0.000002,0.000018,1.000000;;, + 2160;16;0.753388,0.266011,0.601369,0.000000,-0.057593,0.937702,-0.342634,0.000000,-0.655049,0.223501,0.721774,0.000000,31.000202,0.000016,0.000013,1.000000;;, + 2240;16;0.761671,0.219100,0.609798,0.000000,-0.033967,0.953304,-0.300095,0.000000,-0.647073,0.207861,0.733546,0.000000,31.000189,0.000026,0.000009,1.000000;;, + 2320;16;0.768939,0.168925,0.616601,0.000000,-0.009481,0.967368,-0.253198,0.000000,-0.639252,0.188848,0.745449,0.000000,31.000189,0.000003,-0.000001,1.000000;;, + 2400;16;0.775192,0.120581,0.620112,0.000000,0.013302,0.978281,-0.206857,0.000000,-0.631586,0.168603,0.756751,0.000000,31.000202,-0.000012,0.000010,1.000000;;, + 2480;16;0.780357,0.079030,0.620320,0.000000,0.031675,0.985713,-0.165428,0.000000,-0.624531,0.148741,0.766705,0.000000,31.000210,0.000004,0.000042,1.000000;;, + 2560;16;0.784730,0.044929,0.618207,0.000000,0.046236,0.990348,-0.130665,0.000000,-0.618110,0.131121,0.775079,0.000000,31.000202,0.000013,0.000026,1.000000;;, + 2640;16;0.788437,0.021205,0.614750,0.000000,0.056258,0.992731,-0.106395,0.000000,-0.612538,0.118470,0.781513,0.000000,31.000198,0.000002,0.000004,1.000000;;, + 2720;16;0.791435,0.005262,0.611231,0.000000,0.063142,0.993910,-0.090314,0.000000,-0.607984,0.110072,0.786282,0.000000,31.000195,0.000010,0.000002,1.000000;;, + 2800;16;0.793721,-0.004627,0.608264,0.000000,0.068325,0.994321,-0.081594,0.000000,-0.604432,0.106323,0.789530,0.000000,31.000202,-0.000019,0.000014,1.000000;;, + 2880;16;0.795044,-0.008385,0.606494,0.000000,0.071013,0.994315,-0.079343,0.000000,-0.602381,0.106150,0.791119,0.000000,31.000189,0.000019,0.000005,1.000000;;, + 2960;16;0.795173,-0.006850,0.606343,0.000000,0.071316,0.994053,-0.082297,0.000000,-0.602174,0.108682,0.790933,0.000000,31.000193,0.000009,0.000000,1.000000;;, + 3040;16;0.794147,0.001327,0.607724,0.000000,0.067899,0.993543,-0.090897,0.000000,-0.603920,0.113449,0.788929,0.000000,31.000198,-0.000002,0.000006,1.000000;;, + 3120;16;0.791804,0.018068,0.610508,0.000000,0.058857,0.992653,-0.105712,0.000000,-0.607933,0.119636,0.784924,0.000000,31.000198,-0.000002,0.000010,1.000000;;, + 3200;16;0.788313,0.041502,0.613873,0.000000,0.045577,0.991043,-0.125530,0.000000,-0.613584,0.126935,0.779360,0.000000,31.000193,-0.000014,-0.000006,1.000000;;, + 3280;16;0.783706,0.071876,0.616960,0.000000,0.027939,0.988198,-0.150616,0.000000,-0.620504,0.135275,0.772448,0.000000,31.000196,0.000021,0.000017,1.000000;;, + 3360;16;0.778145,0.104767,0.619285,0.000000,0.008416,0.984162,-0.177070,0.000000,-0.628028,0.142999,0.764939,0.000000,31.000200,-0.000020,0.000008,1.000000;;, + 3440;16;0.771949,0.135668,0.621038,0.000000,-0.010331,0.979509,-0.201136,0.000000,-0.635600,0.148851,0.757533,0.000000,31.000202,-0.000004,0.000017,1.000000;;, + 3520;16;0.765550,0.164315,0.622040,0.000000,-0.028308,0.974503,-0.222581,0.000000,-0.642753,0.152789,0.750682,0.000000,31.000198,0.000012,0.000010,1.000000;;, + 3600;16;0.759653,0.187891,0.622595,0.000000,-0.044033,0.970018,-0.239012,0.000000,-0.648836,0.154151,0.745150,0.000000,31.000191,-0.000024,-0.000017,1.000000;;, + 3680;16;0.753917,0.209216,0.622767,0.000000,-0.059075,0.965687,-0.252902,0.000000,-0.654308,0.153877,0.740407,0.000000,31.000185,0.000021,-0.000005,1.000000;;, + 3760;16;0.748277,0.230114,0.622197,0.000000,-0.074616,0.961153,-0.265739,0.000000,-0.659177,0.152421,0.736379,0.000000,31.000195,0.000003,-0.000001,1.000000;;, + 3840;16;0.742244,0.250932,0.621375,0.000000,-0.090540,0.956296,-0.278031,0.000000,-0.663985,0.150108,0.732524,0.000000,31.000195,-0.000019,-0.000002,1.000000;;, + 3920;16;0.735410,0.272427,0.620448,0.000000,-0.107080,0.950841,-0.290576,0.000000,-0.669109,0.147255,0.728430,0.000000,31.000191,-0.000032,-0.000008,1.000000;;, + 4000;16;0.727352,0.295395,0.619436,0.000000,-0.124487,0.944437,-0.304206,0.000000,-0.674879,0.144153,0.723711,0.000000,31.000198,-0.000002,0.000011,1.000000;;, + 4080;16;0.717608,0.320769,0.618180,0.000000,-0.142928,0.936556,-0.320054,0.000000,-0.681623,0.141318,0.717927,0.000000,31.000189,-0.000014,0.000006,1.000000;;, + 4160;16;0.705739,0.349021,0.616537,0.000000,-0.162977,0.926874,-0.338146,0.000000,-0.689472,0.138162,0.711013,0.000000,31.000168,0.000051,-0.000034,1.000000;;, + 4240;16;0.690887,0.381217,0.614287,0.000000,-0.185335,0.914677,-0.359188,0.000000,-0.698803,0.134310,0.702591,0.000000,31.000187,0.000017,-0.000017,1.000000;;, + 4320;16;0.673460,0.416351,0.610823,0.000000,-0.209720,0.899963,-0.382210,0.000000,-0.708851,0.129301,0.693406,0.000000,31.000189,-0.000003,-0.000010,1.000000;;, + 4400;16;0.653362,0.453959,0.605837,0.000000,-0.236263,0.882566,-0.406518,0.000000,-0.719234,0.122466,0.683889,0.000000,31.000198,-0.000005,-0.000002,1.000000;;, + 4480;16;0.631189,0.493016,0.598779,0.000000,-0.264244,0.862493,-0.431603,0.000000,-0.729230,0.114199,0.674672,0.000000,31.000196,-0.000002,0.000017,1.000000;;, + 4560;16;0.607438,0.532598,0.589371,0.000000,-0.293147,0.839865,-0.456828,0.000000,-0.738298,0.104722,0.666296,0.000000,31.000189,0.000009,-0.000021,1.000000;;, + 4640;16;0.582691,0.571791,0.577517,0.000000,-0.322475,0.814958,-0.481513,0.000000,-0.745976,0.094339,0.659257,0.000000,31.000195,0.000002,0.000001,1.000000;;, + 4720;16;0.558018,0.609306,0.563349,0.000000,-0.351534,0.788520,-0.504639,0.000000,-0.751692,0.083562,0.654199,0.000000,31.000191,-0.000009,-0.000010,1.000000;;, + 4800;16;0.532891,0.645602,0.547015,0.000000,-0.380503,0.760229,-0.526564,0.000000,-0.755807,0.072461,0.650772,0.000000,31.000195,-0.000004,0.000004,1.000000;;, + 4960;16;0.452612,0.717604,0.529327,0.000000,-0.426220,0.695510,-0.578448,0.000000,-0.783248,0.036203,0.620654,0.000000,31.000202,0.000005,0.000011,1.000000;;; + } + { Bip01_R_UpperArm } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.839302,-0.543666,-0.000000,0.000000,0.543666,0.839302,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202522,0.000004,-0.000000,1.000000;;, + 80;16;0.845569,-0.533866,0.000000,0.000000,0.533866,0.845569,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202530,-0.000005,-0.000000,1.000000;;, + 160;16;0.851723,-0.523993,0.000000,0.000000,0.523993,0.851723,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202515,-0.000010,0.000002,1.000000;;, + 240;16;0.858073,-0.513528,-0.000000,0.000000,0.513528,0.858073,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202507,0.000006,-0.000001,1.000000;;, + 320;16;0.863682,-0.504036,0.000000,0.000000,0.504036,0.863682,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202522,0.000010,-0.000001,1.000000;;, + 400;16;0.867822,-0.496876,-0.000000,0.000000,0.496876,0.867822,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202507,0.000001,0.000001,1.000000;;, + 480;16;0.870432,-0.492288,0.000000,0.000000,0.492288,0.870432,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202515,-0.000002,0.000001,1.000000;;, + 560;16;0.870943,-0.491383,-0.000000,0.000000,0.491383,0.870943,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202522,-0.000003,-0.000000,1.000000;;, + 640;16;0.870105,-0.492867,0.000000,0.000000,0.492866,0.870105,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202499,-0.000002,-0.000003,1.000000;;, + 720;16;0.868300,-0.496040,-0.000000,0.000000,0.496040,0.868300,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202530,-0.000012,-0.000001,1.000000;;, + 800;16;0.865941,-0.500146,0.000000,0.000000,0.500146,0.865941,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202515,-0.000000,0.000000,1.000000;;, + 880;16;0.863442,-0.504447,-0.000000,0.000000,0.504447,0.863442,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202507,-0.000005,0.000001,1.000000;;, + 960;16;0.861232,-0.508212,0.000000,0.000000,0.508212,0.861232,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202499,-0.000008,-0.000000,1.000000;;, + 1040;16;0.859419,-0.511272,0.000000,0.000000,0.511272,0.859419,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202507,-0.000001,-0.000001,1.000000;;, + 1120;16;0.859435,-0.511245,-0.000000,0.000000,0.511245,0.859435,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202507,-0.000007,-0.000002,1.000000;;, + 1200;16;0.863427,-0.504474,-0.000000,0.000000,0.504474,0.863427,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202522,0.000007,-0.000000,1.000000;;, + 1280;16;0.869177,-0.494501,-0.000000,0.000000,0.494501,0.869177,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202530,0.000000,-0.000002,1.000000;;, + 1360;16;0.876396,-0.481592,0.000000,0.000000,0.481592,0.876396,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202515,0.000005,-0.000003,1.000000;;, + 1440;16;0.881597,-0.472003,0.000000,0.000000,0.472003,0.881597,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202507,0.000001,-0.000001,1.000000;;, + 1520;16;0.881905,-0.471427,0.000000,0.000000,0.471427,0.881905,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202522,-0.000016,-0.000005,1.000000;;, + 1600;16;0.876021,-0.482273,-0.000000,0.000000,0.482273,0.876021,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202515,-0.000007,-0.000007,1.000000;;, + 1680;16;0.859824,-0.510590,0.000000,0.000000,0.510590,0.859824,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202507,0.000013,-0.000002,1.000000;;, + 1760;16;0.835646,-0.549268,-0.000000,0.000000,0.549268,0.835646,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202515,0.000009,-0.000001,1.000000;;, + 1840;16;0.803666,-0.595080,0.000000,0.000000,0.595080,0.803666,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202530,0.000029,0.000012,1.000000;;, + 1920;16;0.766699,-0.642007,-0.000000,0.000000,0.642007,0.766699,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202515,0.000022,0.000007,1.000000;;, + 2000;16;0.729471,-0.684011,-0.000000,0.000000,0.684011,0.729471,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202530,0.000014,0.000011,1.000000;;, + 2080;16;0.692161,-0.721744,-0.000000,0.000000,0.721744,0.692161,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202538,0.000032,0.000015,1.000000;;, + 2160;16;0.657421,-0.753524,0.000000,0.000000,0.753524,0.657421,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202530,0.000011,0.000011,1.000000;;, + 2240;16;0.623622,-0.781726,-0.000000,0.000000,0.781726,0.623622,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202530,0.000032,0.000010,1.000000;;, + 2320;16;0.588879,-0.808221,-0.000000,0.000000,0.808221,0.588879,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202530,0.000034,0.000008,1.000000;;, + 2400;16;0.555261,-0.831676,0.000000,0.000000,0.831676,0.555261,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202560,0.000015,0.000014,1.000000;;, + 2480;16;0.524198,-0.851596,-0.000000,0.000000,0.851596,0.524198,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202538,0.000019,0.000010,1.000000;;, + 2560;16;0.496174,-0.868223,-0.000000,0.000000,0.868223,0.496174,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202507,0.000032,0.000006,1.000000;;, + 2640;16;0.472349,-0.881412,-0.000000,0.000000,0.881412,0.472349,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202507,0.000040,0.000004,1.000000;;, + 2720;16;0.452028,-0.892004,-0.000000,0.000000,0.892004,0.452028,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202507,0.000024,0.000005,1.000000;;, + 2800;16;0.434868,-0.900494,0.000000,0.000000,0.900494,0.434868,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202492,0.000019,-0.000003,1.000000;;, + 2880;16;0.420585,-0.907253,0.000000,0.000000,0.907253,0.420585,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202515,0.000016,-0.000004,1.000000;;, + 2960;16;0.409422,-0.912345,-0.000000,0.000000,0.912345,0.409422,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202499,0.000036,-0.000002,1.000000;;, + 3040;16;0.399246,-0.916844,-0.000000,0.000000,0.916844,0.399247,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202515,0.000042,0.000018,1.000000;;, + 3120;16;0.386862,-0.922137,-0.000000,0.000000,0.922137,0.386862,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202522,0.000018,0.000006,1.000000;;, + 3200;16;0.375469,-0.926835,0.000000,0.000000,0.926835,0.375469,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202515,0.000028,0.000002,1.000000;;, + 3280;16;0.365296,-0.930891,0.000000,0.000000,0.930891,0.365296,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202515,0.000032,0.000009,1.000000;;, + 3360;16;0.362235,-0.932087,0.000000,0.000000,0.932087,0.362235,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,89.202507,0.000022,0.000010,1.000000;;, + 3440;16;0.371763,-0.928328,0.000000,0.000000,0.928328,0.371763,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202515,0.000029,0.000013,1.000000;;, + 3520;16;0.395109,-0.918634,0.000000,0.000000,0.918634,0.395109,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202530,0.000035,0.000017,1.000000;;, + 3600;16;0.437008,-0.899457,-0.000000,0.000000,0.899458,0.437008,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202507,0.000014,0.000007,1.000000;;, + 3680;16;0.490136,-0.871646,0.000000,0.000000,0.871646,0.490136,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202515,0.000030,0.000005,1.000000;;, + 3760;16;0.550422,-0.834887,0.000000,0.000000,0.834887,0.550422,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202538,0.000013,0.000007,1.000000;;, + 3840;16;0.612258,-0.790658,-0.000000,0.000000,0.790658,0.612258,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202507,0.000040,0.000007,1.000000;;, + 3920;16;0.671066,-0.741397,0.000000,0.000000,0.741397,0.671066,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202515,0.000025,-0.000001,1.000000;;, + 4000;16;0.723139,-0.690702,-0.000000,0.000000,0.690702,0.723139,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202507,0.000035,0.000003,1.000000;;, + 4080;16;0.764850,-0.644208,0.000000,0.000000,0.644208,0.764850,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202545,0.000027,0.000003,1.000000;;, + 4160;16;0.797213,-0.603698,-0.000000,0.000000,0.603698,0.797213,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202530,0.000025,0.000005,1.000000;;, + 4240;16;0.819067,-0.573698,-0.000000,0.000000,0.573698,0.819067,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202522,-0.000017,0.000003,1.000000;;, + 4320;16;0.834464,-0.551062,0.000000,0.000000,0.551062,0.834464,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202499,-0.000014,-0.000004,1.000000;;, + 4400;16;0.845668,-0.533709,-0.000000,0.000000,0.533709,0.845668,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202515,-0.000017,-0.000003,1.000000;;, + 4480;16;0.853964,-0.520332,-0.000000,0.000000,0.520332,0.853964,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202515,0.000008,0.000000,1.000000;;, + 4560;16;0.860620,-0.509247,-0.000000,0.000000,0.509247,0.860620,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,89.202522,-0.000018,0.000003,1.000000;;, + 4640;16;0.866783,-0.498686,0.000000,0.000000,0.498686,0.866783,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202522,-0.000006,0.000003,1.000000;;, + 4720;16;0.874184,-0.485595,0.000000,0.000000,0.485595,0.874184,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202507,-0.000021,-0.000002,1.000000;;, + 4800;16;0.881719,-0.471776,0.000000,0.000000,0.471776,0.881718,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,89.202530,-0.000026,0.000000,1.000000;;, + 4960;16;0.839302,-0.543666,-0.000000,0.000000,0.543666,0.839302,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,89.202522,0.000004,-0.000000,1.000000;;; + } + { Bip01_R_Forearm } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.999842,-0.009430,0.015054,0.000000,-0.015226,-0.018419,0.999714,0.000000,-0.009150,-0.999786,-0.018560,0.000000,61.671482,-0.000006,0.000000,1.000000;;, + 80;16;0.999827,-0.009472,0.015985,0.000000,-0.016159,-0.018507,0.999698,0.000000,-0.009174,-0.999784,-0.018657,0.000000,61.671463,-0.000007,-0.000003,1.000000;;, + 160;16;0.999812,-0.009515,0.016916,0.000000,-0.017091,-0.018595,0.999681,0.000000,-0.009198,-0.999782,-0.018754,0.000000,61.671459,0.000001,-0.000001,1.000000;;, + 240;16;0.999794,-0.009563,0.017906,0.000000,-0.018082,-0.018690,0.999662,0.000000,-0.009225,-0.999780,-0.018859,0.000000,61.671490,-0.000008,-0.000001,1.000000;;, + 320;16;0.999778,-0.009601,0.018778,0.000000,-0.018955,-0.018770,0.999644,0.000000,-0.009246,-0.999778,-0.018948,0.000000,61.671490,-0.000002,-0.000000,1.000000;;, + 400;16;0.999766,-0.009616,0.019365,0.000000,-0.019544,-0.018816,0.999632,0.000000,-0.009248,-0.999777,-0.019000,0.000000,61.671474,0.000002,0.000001,1.000000;;, + 480;16;0.999760,-0.009618,0.019699,0.000000,-0.019878,-0.018829,0.999625,0.000000,-0.009243,-0.999776,-0.019015,0.000000,61.671467,0.000002,0.000003,1.000000;;, + 560;16;0.999759,-0.009612,0.019718,0.000000,-0.019896,-0.018796,0.999625,0.000000,-0.009238,-0.999777,-0.018982,0.000000,61.671505,0.000017,0.000003,1.000000;;, + 640;16;0.999763,-0.009602,0.019530,0.000000,-0.019707,-0.018733,0.999630,0.000000,-0.009233,-0.999778,-0.018918,0.000000,61.671486,0.000014,0.000004,1.000000;;, + 720;16;0.999769,-0.009597,0.019230,0.000000,-0.019407,-0.018651,0.999638,0.000000,-0.009235,-0.999780,-0.018833,0.000000,61.671482,0.000011,0.000002,1.000000;;, + 800;16;0.999777,-0.009578,0.018802,0.000000,-0.018978,-0.018555,0.999648,0.000000,-0.009226,-0.999782,-0.018732,0.000000,61.671482,0.000007,-0.000003,1.000000;;, + 880;16;0.999788,-0.009534,0.018257,0.000000,-0.018430,-0.018450,0.999660,0.000000,-0.009194,-0.999784,-0.018622,0.000000,61.671471,0.000007,-0.000002,1.000000;;, + 960;16;0.999800,-0.009453,0.017605,0.000000,-0.017776,-0.018343,0.999674,0.000000,-0.009127,-0.999787,-0.018508,0.000000,61.671471,0.000002,-0.000001,1.000000;;, + 1040;16;0.999813,-0.009346,0.016926,0.000000,-0.017095,-0.018262,0.999687,0.000000,-0.009034,-0.999790,-0.018418,0.000000,61.671482,0.000002,0.000003,1.000000;;, + 1120;16;0.999830,-0.009133,0.016027,0.000000,-0.016191,-0.018147,0.999704,0.000000,-0.008839,-0.999794,-0.018292,0.000000,61.671497,-0.000000,0.000002,1.000000;;, + 1200;16;0.999854,-0.008707,0.014680,0.000000,-0.014835,-0.017926,0.999729,0.000000,-0.008441,-0.999801,-0.018053,0.000000,61.671471,-0.000005,-0.000001,1.000000;;, + 1280;16;0.999881,-0.008164,0.013070,0.000000,-0.013213,-0.017669,0.999757,0.000000,-0.007931,-0.999811,-0.017775,0.000000,61.671494,-0.000007,0.000003,1.000000;;, + 1360;16;0.999910,-0.007500,0.011158,0.000000,-0.011287,-0.017372,0.999785,0.000000,-0.007305,-0.999821,-0.017455,0.000000,61.671497,-0.000011,-0.000001,1.000000;;, + 1440;16;0.999932,-0.006905,0.009383,0.000000,-0.009501,-0.017186,0.999807,0.000000,-0.006743,-0.999828,-0.017250,0.000000,61.671490,-0.000003,0.000006,1.000000;;, + 1520;16;0.999945,-0.006558,0.008132,0.000000,-0.008244,-0.017252,0.999817,0.000000,-0.006417,-0.999830,-0.017305,0.000000,61.671482,0.000011,0.000003,1.000000;;, + 1600;16;0.999951,-0.006482,0.007524,0.000000,-0.007637,-0.017610,0.999816,0.000000,-0.006349,-0.999824,-0.017658,0.000000,61.671501,-0.000002,-0.000003,1.000000;;, + 1680;16;0.999945,-0.006802,0.007930,0.000000,-0.008054,-0.018389,0.999799,0.000000,-0.006654,-0.999808,-0.018443,0.000000,61.671494,0.000021,0.000014,1.000000;;, + 1760;16;0.999932,-0.007393,0.008977,0.000000,-0.009119,-0.019460,0.999769,0.000000,-0.007217,-0.999783,-0.019526,0.000000,61.671486,0.000015,0.000004,1.000000;;, + 1840;16;0.999911,-0.008187,0.010506,0.000000,-0.010674,-0.020765,0.999727,0.000000,-0.007967,-0.999751,-0.020850,0.000000,61.671494,-0.000007,0.000002,1.000000;;, + 1920;16;0.999883,-0.009146,0.012254,0.000000,-0.012455,-0.022217,0.999676,0.000000,-0.008871,-0.999711,-0.022328,0.000000,61.671494,0.000001,0.000009,1.000000;;, + 2000;16;0.999852,-0.010190,0.013890,0.000000,-0.014128,-0.023693,0.999619,0.000000,-0.009857,-0.999667,-0.023834,0.000000,61.671455,0.000022,0.000007,1.000000;;, + 2080;16;0.999816,-0.011372,0.015462,0.000000,-0.015745,-0.025248,0.999557,0.000000,-0.010977,-0.999617,-0.025422,0.000000,61.671490,-0.000011,-0.000000,1.000000;;, + 2160;16;0.999777,-0.012730,0.016875,0.000000,-0.017213,-0.026899,0.999490,0.000000,-0.012269,-0.999557,-0.027112,0.000000,61.671467,0.000003,-0.000003,1.000000;;, + 2240;16;0.999733,-0.014224,0.018223,0.000000,-0.018625,-0.028628,0.999417,0.000000,-0.013694,-0.999489,-0.028886,0.000000,61.671478,-0.000009,-0.000003,1.000000;;, + 2320;16;0.999681,-0.015881,0.019623,0.000000,-0.020101,-0.030473,0.999334,0.000000,-0.015272,-0.999409,-0.030783,0.000000,61.671467,0.000001,0.000011,1.000000;;, + 2400;16;0.999627,-0.017550,0.020908,0.000000,-0.021467,-0.032279,0.999248,0.000000,-0.016862,-0.999325,-0.032644,0.000000,61.671471,0.000003,0.000004,1.000000;;, + 2480;16;0.999577,-0.019084,0.021961,0.000000,-0.022599,-0.033901,0.999170,0.000000,-0.018323,-0.999243,-0.034318,0.000000,61.671463,-0.000016,-0.000008,1.000000;;, + 2560;16;0.999531,-0.020501,0.022751,0.000000,-0.023466,-0.035354,0.999099,0.000000,-0.019679,-0.999165,-0.035819,0.000000,61.671486,0.000012,0.000005,1.000000;;, + 2640;16;0.999495,-0.021759,0.023170,0.000000,-0.023956,-0.036589,0.999043,0.000000,-0.020891,-0.999094,-0.037092,0.000000,61.671482,-0.000005,-0.000001,1.000000;;, + 2720;16;0.999466,-0.022900,0.023327,0.000000,-0.024179,-0.037656,0.998998,0.000000,-0.021999,-0.999028,-0.038190,0.000000,61.671471,0.000016,0.000004,1.000000;;, + 2800;16;0.999442,-0.023976,0.023270,0.000000,-0.024185,-0.038610,0.998962,0.000000,-0.023053,-0.998967,-0.039168,0.000000,61.671474,0.000007,-0.000001,1.000000;;, + 2880;16;0.999423,-0.024915,0.023070,0.000000,-0.024041,-0.039392,0.998935,0.000000,-0.023979,-0.998913,-0.039969,0.000000,61.671463,0.000002,-0.000002,1.000000;;, + 2960;16;0.999411,-0.025649,0.022815,0.000000,-0.023829,-0.039954,0.998917,0.000000,-0.024709,-0.998872,-0.040542,0.000000,61.671497,0.000005,0.000003,1.000000;;, + 3040;16;0.999403,-0.026214,0.022511,0.000000,-0.023557,-0.040321,0.998909,0.000000,-0.025277,-0.998843,-0.040915,0.000000,61.671467,-0.000020,-0.000016,1.000000;;, + 3120;16;0.999399,-0.026629,0.022214,0.000000,-0.023283,-0.040508,0.998908,0.000000,-0.025700,-0.998824,-0.041104,0.000000,61.671455,-0.000006,0.000003,1.000000;;, + 3200;16;0.999399,-0.026876,0.021870,0.000000,-0.022949,-0.040500,0.998916,0.000000,-0.025961,-0.998818,-0.041092,0.000000,61.671474,-0.000005,-0.000005,1.000000;;, + 3280;16;0.999406,-0.026975,0.021446,0.000000,-0.022524,-0.040312,0.998933,0.000000,-0.026081,-0.998823,-0.040896,0.000000,61.671497,-0.000002,-0.000003,1.000000;;, + 3360;16;0.999421,-0.026824,0.020931,0.000000,-0.021991,-0.039871,0.998963,0.000000,-0.025962,-0.998845,-0.040438,0.000000,61.671486,-0.000007,-0.000006,1.000000;;, + 3440;16;0.999446,-0.026350,0.020320,0.000000,-0.021343,-0.039125,0.999006,0.000000,-0.025529,-0.998887,-0.039666,0.000000,61.671463,-0.000008,-0.000006,1.000000;;, + 3520;16;0.999483,-0.025496,0.019563,0.000000,-0.020524,-0.038022,0.999066,0.000000,-0.024729,-0.998952,-0.038526,0.000000,61.671463,-0.000012,-0.000017,1.000000;;, + 3600;16;0.999536,-0.024132,0.018581,0.000000,-0.019454,-0.036450,0.999146,0.000000,-0.023434,-0.999044,-0.036903,0.000000,61.671471,-0.000009,-0.000004,1.000000;;, + 3680;16;0.999597,-0.022410,0.017443,0.000000,-0.018211,-0.034542,0.999237,0.000000,-0.021791,-0.999152,-0.034936,0.000000,61.671455,0.000011,-0.000003,1.000000;;, + 3760;16;0.999662,-0.020385,0.016149,0.000000,-0.016803,-0.032340,0.999336,0.000000,-0.019849,-0.999269,-0.032671,0.000000,61.671494,0.000001,-0.000004,1.000000;;, + 3840;16;0.999724,-0.018232,0.014819,0.000000,-0.015362,-0.030006,0.999432,0.000000,-0.017777,-0.999383,-0.030278,0.000000,61.671478,0.000009,-0.000003,1.000000;;, + 3920;16;0.999779,-0.016095,0.013546,0.000000,-0.013988,-0.027677,0.999519,0.000000,-0.015712,-0.999487,-0.027896,0.000000,61.671463,0.000024,0.000011,1.000000;;, + 4000;16;0.999823,-0.014117,0.012423,0.000000,-0.012780,-0.025486,0.999593,0.000000,-0.013794,-0.999575,-0.025662,0.000000,61.671501,-0.000024,0.000006,1.000000;;, + 4080;16;0.999855,-0.012481,0.011565,0.000000,-0.011857,-0.023609,0.999651,0.000000,-0.012204,-0.999643,-0.023753,0.000000,61.671471,-0.000031,-0.000007,1.000000;;, + 4160;16;0.999877,-0.011208,0.011004,0.000000,-0.011249,-0.022065,0.999693,0.000000,-0.010962,-0.999694,-0.022188,0.000000,61.671509,-0.000053,-0.000012,1.000000;;, + 4240;16;0.999887,-0.010432,0.010846,0.000000,-0.011063,-0.020981,0.999719,0.000000,-0.010202,-0.999725,-0.021094,0.000000,61.671482,0.000002,-0.000003,1.000000;;, + 4320;16;0.999890,-0.009995,0.010980,0.000000,-0.011180,-0.020212,0.999733,0.000000,-0.009771,-0.999746,-0.020321,0.000000,61.671471,0.000013,0.000006,1.000000;;, + 4400;16;0.999887,-0.009808,0.011352,0.000000,-0.011543,-0.019672,0.999740,0.000000,-0.009583,-0.999758,-0.019783,0.000000,61.671455,0.000016,0.000008,1.000000;;, + 4480;16;0.999881,-0.009799,0.011888,0.000000,-0.012076,-0.019296,0.999741,0.000000,-0.009568,-0.999766,-0.019412,0.000000,61.671490,-0.000029,-0.000001,1.000000;;, + 4560;16;0.999873,-0.009892,0.012518,0.000000,-0.012704,-0.019013,0.999739,0.000000,-0.009651,-0.999770,-0.019136,0.000000,61.671459,0.000019,0.000000,1.000000;;, + 4640;16;0.999863,-0.010010,0.013171,0.000000,-0.013357,-0.018754,0.999735,0.000000,-0.009760,-0.999774,-0.018885,0.000000,61.671463,-0.000028,-0.000006,1.000000;;, + 4720;16;0.999855,-0.010026,0.013731,0.000000,-0.013913,-0.018401,0.999734,0.000000,-0.009770,-0.999780,-0.018538,0.000000,61.671471,0.000000,0.000002,1.000000;;, + 4800;16;0.999848,-0.010016,0.014267,0.000000,-0.014446,-0.018025,0.999733,0.000000,-0.009756,-0.999787,-0.018167,0.000000,61.671482,0.000009,-0.000000,1.000000;;, + 4960;16;0.999842,-0.009430,0.015054,0.000000,-0.015226,-0.018419,0.999714,0.000000,-0.009150,-0.999786,-0.018560,0.000000,61.671482,-0.000006,0.000000,1.000000;;; + } + { Bip01_R_Hand } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410504,3.054970,10.755419,1.000000;;, + 80;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410502,3.054969,10.755422,1.000000;;, + 160;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410496,3.054973,10.755424,1.000000;;, + 240;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410510,3.054973,10.755419,1.000000;;, + 320;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410503,3.054971,10.755418,1.000000;;, + 400;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410501,3.054970,10.755423,1.000000;;, + 480;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410504,3.054974,10.755414,1.000000;;, + 560;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410506,3.054973,10.755427,1.000000;;, + 640;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410496,3.054969,10.755433,1.000000;;, + 720;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410497,3.054971,10.755427,1.000000;;, + 800;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410497,3.054971,10.755422,1.000000;;, + 880;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410493,3.054971,10.755424,1.000000;;, + 960;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410510,3.054967,10.755420,1.000000;;, + 1040;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410503,3.054971,10.755429,1.000000;;, + 1120;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410495,3.054971,10.755433,1.000000;;, + 1200;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410502,3.054972,10.755430,1.000000;;, + 1280;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410520,3.054972,10.755430,1.000000;;, + 1360;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410509,3.054971,10.755430,1.000000;;, + 1440;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410509,3.054970,10.755424,1.000000;;, + 1520;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410499,3.054962,10.755417,1.000000;;, + 1600;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410498,3.054971,10.755423,1.000000;;, + 1680;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410508,3.054972,10.755428,1.000000;;, + 1760;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410496,3.054977,10.755415,1.000000;;, + 1840;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410498,3.054973,10.755422,1.000000;;, + 1920;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410505,3.054962,10.755414,1.000000;;, + 2000;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410492,3.054979,10.755416,1.000000;;, + 2080;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410499,3.054971,10.755430,1.000000;;, + 2160;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410506,3.054967,10.755430,1.000000;;, + 2240;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410517,3.054963,10.755426,1.000000;;, + 2320;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410503,3.054976,10.755416,1.000000;;, + 2400;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410486,3.054972,10.755421,1.000000;;, + 2480;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410499,3.054968,10.755430,1.000000;;, + 2560;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410509,3.054973,10.755420,1.000000;;, + 2640;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410502,3.054973,10.755420,1.000000;;, + 2720;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410489,3.054962,10.755431,1.000000;;, + 2800;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410504,3.054969,10.755413,1.000000;;, + 2880;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410510,3.054960,10.755435,1.000000;;, + 2960;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410513,3.054971,10.755418,1.000000;;, + 3040;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410494,3.054973,10.755432,1.000000;;, + 3120;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410505,3.054975,10.755428,1.000000;;, + 3200;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410489,3.054979,10.755415,1.000000;;, + 3280;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410505,3.054979,10.755413,1.000000;;, + 3360;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410506,3.054971,10.755419,1.000000;;, + 3440;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410515,3.054965,10.755436,1.000000;;, + 3520;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410480,3.054987,10.755407,1.000000;;, + 3600;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410487,3.054979,10.755419,1.000000;;, + 3680;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410525,3.054966,10.755445,1.000000;;, + 3760;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410490,3.054978,10.755404,1.000000;;, + 3840;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410493,3.054979,10.755408,1.000000;;, + 3920;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410492,3.054971,10.755415,1.000000;;, + 4000;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410519,3.054965,10.755444,1.000000;;, + 4080;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410522,3.054968,10.755445,1.000000;;, + 4160;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410519,3.054975,10.755439,1.000000;;, + 4240;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410499,3.054971,10.755405,1.000000;;, + 4320;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410506,3.054970,10.755424,1.000000;;, + 4400;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410498,3.054973,10.755425,1.000000;;, + 4480;16;0.713247,-0.002867,0.700907,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410496,3.054969,10.755423,1.000000;;, + 4560;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410496,3.054974,10.755420,1.000000;;, + 4640;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410505,3.054972,10.755441,1.000000;;, + 4720;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410500,3.054973,10.755397,1.000000;;, + 4800;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410507,3.054970,10.755430,1.000000;;, + 4960;16;0.713247,-0.002867,0.700906,0.000000,-0.700353,-0.042855,0.712509,0.000000,0.027995,-0.999077,-0.032574,0.000000,12.410504,3.054970,10.755419,1.000000;;; + } + { Bip01_R_Finger0 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075052,0.000002,0.000001,1.000000;;, + 80;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075058,-0.000000,0.000002,1.000000;;, + 160;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075060,0.000007,-0.000002,1.000000;;, + 240;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075061,0.000001,0.000002,1.000000;;, + 320;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075058,-0.000003,0.000001,1.000000;;, + 400;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075050,0.000010,0.000004,1.000000;;, + 480;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075057,-0.000000,0.000002,1.000000;;, + 560;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075052,-0.000008,0.000006,1.000000;;, + 640;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075049,-0.000002,-0.000000,1.000000;;, + 720;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075055,-0.000000,0.000001,1.000000;;, + 800;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075058,0.000006,-0.000003,1.000000;;, + 880;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075056,0.000002,0.000001,1.000000;;, + 960;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075064,0.000012,-0.000004,1.000000;;, + 1040;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075058,0.000012,-0.000001,1.000000;;, + 1120;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075068,-0.000011,-0.000001,1.000000;;, + 1200;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075061,0.000005,0.000002,1.000000;;, + 1280;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075065,0.000005,0.000002,1.000000;;, + 1360;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075057,-0.000009,-0.000001,1.000000;;, + 1440;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075051,0.000008,0.000002,1.000000;;, + 1520;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075061,-0.000001,-0.000004,1.000000;;, + 1600;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075050,-0.000008,-0.000012,1.000000;;, + 1680;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075062,-0.000003,0.000002,1.000000;;, + 1760;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075061,0.000004,0.000001,1.000000;;, + 1840;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075066,-0.000003,0.000002,1.000000;;, + 1920;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075069,0.000007,-0.000002,1.000000;;, + 2000;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075076,0.000014,0.000012,1.000000;;, + 2080;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075056,0.000002,-0.000004,1.000000;;, + 2160;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075055,-0.000008,-0.000001,1.000000;;, + 2240;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075054,-0.000003,-0.000007,1.000000;;, + 2320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075050,0.000007,-0.000004,1.000000;;, + 2400;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075045,-0.000015,-0.000011,1.000000;;, + 2480;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075078,0.000018,0.000016,1.000000;;, + 2560;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075087,0.000001,0.000011,1.000000;;, + 2640;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075067,0.000012,0.000005,1.000000;;, + 2720;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075042,0.000007,-0.000007,1.000000;;, + 2800;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075064,0.000019,0.000008,1.000000;;, + 2880;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075041,0.000003,-0.000016,1.000000;;, + 2960;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075039,0.000007,-0.000012,1.000000;;, + 3040;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075060,0.000024,0.000005,1.000000;;, + 3120;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075059,-0.000010,-0.000001,1.000000;;, + 3200;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075027,0.000053,-0.000005,1.000000;;, + 3280;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075060,-0.000006,-0.000005,1.000000;;, + 3360;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075058,0.000014,0.000003,1.000000;;, + 3440;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075065,-0.000020,-0.000003,1.000000;;, + 3520;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075032,0.000007,-0.000006,1.000000;;, + 3600;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075042,0.000017,0.000001,1.000000;;, + 3680;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075056,-0.000013,-0.000005,1.000000;;, + 3760;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075061,0.000009,0.000004,1.000000;;, + 3840;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075056,-0.000006,-0.000002,1.000000;;, + 3920;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075090,0.000000,0.000008,1.000000;;, + 4000;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075047,0.000004,0.000001,1.000000;;, + 4080;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075047,-0.000000,-0.000001,1.000000;;, + 4160;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075092,0.000014,0.000012,1.000000;;, + 4240;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075029,-0.000006,-0.000009,1.000000;;, + 4320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075057,-0.000005,-0.000004,1.000000;;, + 4400;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075061,-0.000004,-0.000000,1.000000;;, + 4480;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.075070,0.000014,0.000009,1.000000;;, + 4560;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075041,-0.000008,-0.000004,1.000000;;, + 4640;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075053,0.000000,-0.000002,1.000000;;, + 4720;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.075084,0.000022,-0.000000,1.000000;;, + 4800;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.075073,0.000020,-0.000001,1.000000;;, + 4960;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.075052,0.000002,0.000001,1.000000;;; + } + { Bip01_R_Finger01 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961570,0.000006,0.000001,1.000000;;, + 80;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961572,-0.000003,0.000001,1.000000;;, + 160;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961579,-0.000014,-0.000005,1.000000;;, + 240;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961579,0.000003,-0.000004,1.000000;;, + 320;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961572,-0.000001,-0.000001,1.000000;;, + 400;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961577,-0.000006,-0.000002,1.000000;;, + 480;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961569,0.000007,-0.000003,1.000000;;, + 560;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961569,0.000006,-0.000003,1.000000;;, + 640;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961580,-0.000004,0.000001,1.000000;;, + 720;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961580,0.000001,0.000001,1.000000;;, + 800;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961578,-0.000004,0.000001,1.000000;;, + 880;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961586,-0.000004,0.000002,1.000000;;, + 960;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961578,0.000002,0.000001,1.000000;;, + 1040;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961571,-0.000016,-0.000002,1.000000;;, + 1120;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961569,-0.000003,-0.000004,1.000000;;, + 1200;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961572,-0.000011,0.000003,1.000000;;, + 1280;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961568,0.000003,-0.000002,1.000000;;, + 1360;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961584,-0.000004,-0.000001,1.000000;;, + 1440;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961586,0.000001,0.000002,1.000000;;, + 1520;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961574,-0.000001,-0.000001,1.000000;;, + 1600;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961571,-0.000003,0.000000,1.000000;;, + 1680;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961561,-0.000015,-0.000013,1.000000;;, + 1760;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961587,0.000014,0.000007,1.000000;;, + 1840;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961578,0.000000,0.000005,1.000000;;, + 1920;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961569,-0.000001,-0.000000,1.000000;;, + 2000;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961568,-0.000005,-0.000007,1.000000;;, + 2080;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961582,-0.000002,0.000007,1.000000;;, + 2160;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961592,0.000002,0.000007,1.000000;;, + 2240;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961571,0.000001,0.000002,1.000000;;, + 2320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961581,-0.000002,0.000007,1.000000;;, + 2400;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961587,0.000007,0.000005,1.000000;;, + 2480;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961561,-0.000005,-0.000009,1.000000;;, + 2560;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961563,-0.000000,-0.000002,1.000000;;, + 2640;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961570,0.000003,-0.000004,1.000000;;, + 2720;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961582,-0.000004,0.000006,1.000000;;, + 2800;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961578,-0.000005,-0.000001,1.000000;;, + 2880;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961594,0.000013,0.000015,1.000000;;, + 2960;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961571,-0.000003,0.000001,1.000000;;, + 3040;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961572,-0.000013,-0.000007,1.000000;;, + 3120;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961565,-0.000008,-0.000008,1.000000;;, + 3200;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961592,-0.000029,0.000004,1.000000;;, + 3280;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961550,0.000049,0.000002,1.000000;;, + 3360;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961544,0.000018,-0.000008,1.000000;;, + 3440;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961576,0.000012,0.000001,1.000000;;, + 3520;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961610,0.000008,0.000017,1.000000;;, + 3600;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961546,0.000012,-0.000004,1.000000;;, + 3680;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961613,-0.000003,0.000015,1.000000;;, + 3760;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961617,0.000004,0.000010,1.000000;;, + 3840;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961557,-0.000016,-0.000011,1.000000;;, + 3920;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961516,-0.000004,-0.000013,1.000000;;, + 4000;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961571,-0.000010,-0.000010,1.000000;;, + 4080;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961620,0.000005,0.000005,1.000000;;, + 4160;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961563,-0.000004,-0.000014,1.000000;;, + 4240;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961597,0.000014,0.000007,1.000000;;, + 4320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961577,0.000003,0.000003,1.000000;;, + 4400;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961582,0.000008,-0.000003,1.000000;;, + 4480;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,5.961578,0.000009,0.000002,1.000000;;, + 4560;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961586,0.000002,-0.000004,1.000000;;, + 4640;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961611,0.000023,0.000002,1.000000;;, + 4720;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,5.961559,-0.000019,-0.000006,1.000000;;, + 4800;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,5.961570,-0.000010,-0.000003,1.000000;;, + 4960;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,5.961570,0.000006,0.000001,1.000000;;; + } + { Bip01_R_Finger02 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961581,-0.000005,-0.000000,1.000000;;, + 80;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961575,0.000001,0.000000,1.000000;;, + 160;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,5.961576,0.000007,-0.000000,1.000000;;, + 240;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961576,0.000002,-0.000002,1.000000;;, + 320;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,5.961573,-0.000000,-0.000002,1.000000;;, + 400;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961582,-0.000001,-0.000004,1.000000;;, + 480;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961582,-0.000001,0.000002,1.000000;;, + 560;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,5.961582,-0.000003,-0.000002,1.000000;;, + 640;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,5.961580,-0.000005,0.000002,1.000000;;, + 720;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961580,0.000001,0.000001,1.000000;;, + 800;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961578,0.000001,0.000002,1.000000;;, + 880;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961575,0.000007,0.000002,1.000000;;, + 960;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961577,0.000006,0.000002,1.000000;;, + 1040;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961578,-0.000004,0.000001,1.000000;;, + 1120;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961572,0.000001,-0.000000,1.000000;;, + 1200;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,5.961593,-0.000010,0.000001,1.000000;;, + 1280;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,5.961579,-0.000002,0.000000,1.000000;;, + 1360;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961573,0.000011,0.000003,1.000000;;, + 1440;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,5.961576,-0.000006,-0.000001,1.000000;;, + 1520;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961574,-0.000000,-0.000001,1.000000;;, + 1600;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961571,-0.000001,0.000001,1.000000;;, + 1680;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961578,0.000010,0.000006,1.000000;;, + 1760;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,5.961567,-0.000012,-0.000007,1.000000;;, + 1840;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961578,0.000001,0.000001,1.000000;;, + 1920;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961568,-0.000001,-0.000003,1.000000;;, + 2000;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,5.961567,-0.000005,-0.000003,1.000000;;, + 2080;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961581,-0.000001,-0.000001,1.000000;;, + 2160;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961565,0.000005,-0.000004,1.000000;;, + 2240;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961573,0.000003,-0.000001,1.000000;;, + 2320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961581,-0.000002,0.000000,1.000000;;, + 2400;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961590,0.000008,0.000005,1.000000;;, + 2480;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,5.961561,-0.000005,-0.000011,1.000000;;, + 2560;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961563,-0.000000,-0.000004,1.000000;;, + 2640;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,5.961572,0.000001,0.000002,1.000000;;, + 2720;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961587,-0.000002,0.000000,1.000000;;, + 2800;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961576,-0.000006,-0.000003,1.000000;;, + 2880;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,5.961582,-0.000011,0.000001,1.000000;;, + 2960;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,5.961596,-0.000020,0.000010,1.000000;;, + 3040;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961575,-0.000013,-0.000003,1.000000;;, + 3120;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,5.961577,0.000014,0.000005,1.000000;;, + 3200;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961589,-0.000028,-0.000002,1.000000;;, + 3280;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961583,-0.000012,0.000003,1.000000;;, + 3360;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961590,-0.000017,0.000003,1.000000;;, + 3440;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961579,0.000012,0.000004,1.000000;;, + 3520;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961597,-0.000018,0.000009,1.000000;;, + 3600;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961603,-0.000013,0.000008,1.000000;;, + 3680;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961560,0.000020,0.000000,1.000000;;, + 3760;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,5.961558,-0.000007,-0.000006,1.000000;;, + 3840;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961568,0.000012,-0.000001,1.000000;;, + 3920;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,5.961574,0.000002,0.000012,1.000000;;, + 4000;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,5.961567,-0.000001,0.000005,1.000000;;, + 4080;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961557,-0.000003,0.000003,1.000000;;, + 4160;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961563,-0.000009,0.000006,1.000000;;, + 4240;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,5.961600,-0.000002,0.000010,1.000000;;, + 4320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961576,0.000003,0.000009,1.000000;;, + 4400;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,5.961584,0.000005,0.000009,1.000000;;, + 4480;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,5.961586,-0.000003,0.000008,1.000000;;, + 4560;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,5.961587,0.000002,0.000010,1.000000;;, + 4640;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961561,-0.000013,0.000004,1.000000;;, + 4720;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,5.961559,-0.000019,0.000011,1.000000;;, + 4800;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,5.961568,-0.000011,0.000000,1.000000;;, + 4960;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,5.961581,-0.000005,-0.000000,1.000000;;; + } + { Dummy01 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087999,0.354686,0.505020,1.000000;;, + 80;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088005,0.354684,0.505019,1.000000;;, + 160;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087999,0.354688,0.505024,1.000000;;, + 240;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088009,0.354687,0.505020,1.000000;;, + 320;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088003,0.354686,0.505027,1.000000;;, + 400;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087999,0.354684,0.505021,1.000000;;, + 480;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088009,0.354687,0.505025,1.000000;;, + 560;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.088003,0.354688,0.505028,1.000000;;, + 640;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087997,0.354688,0.505030,1.000000;;, + 720;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.087994,0.354686,0.505022,1.000000;;, + 800;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087999,0.354685,0.505018,1.000000;;, + 880;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.087994,0.354686,0.505031,1.000000;;, + 960;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088005,0.354684,0.505028,1.000000;;, + 1040;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.088007,0.354689,0.505018,1.000000;;, + 1120;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088001,0.354687,0.505025,1.000000;;, + 1200;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087996,0.354690,0.505031,1.000000;;, + 1280;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.087994,0.354685,0.505033,1.000000;;, + 1360;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.088009,0.354686,0.505025,1.000000;;, + 1440;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.088003,0.354692,0.505019,1.000000;;, + 1520;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.087997,0.354684,0.505028,1.000000;;, + 1600;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.088011,0.354688,0.505035,1.000000;;, + 1680;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.088003,0.354685,0.505040,1.000000;;, + 1760;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.088001,0.354688,0.505032,1.000000;;, + 1840;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088013,0.354688,0.505036,1.000000;;, + 1920;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087994,0.354683,0.505022,1.000000;;, + 2000;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.088003,0.354689,0.505030,1.000000;;, + 2080;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.087988,0.354692,0.505028,1.000000;;, + 2160;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.087992,0.354689,0.505020,1.000000;;, + 2240;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.088015,0.354682,0.505032,1.000000;;, + 2320;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087988,0.354681,0.505026,1.000000;;, + 2400;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.087994,0.354679,0.505042,1.000000;;, + 2480;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087996,0.354681,0.505034,1.000000;;, + 2560;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.088009,0.354687,0.505028,1.000000;;, + 2640;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088013,0.354678,0.505034,1.000000;;, + 2720;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.088007,0.354680,0.505031,1.000000;;, + 2800;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.087994,0.354681,0.505026,1.000000;;, + 2880;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.087967,0.354697,0.505018,1.000000;;, + 2960;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088001,0.354682,0.505031,1.000000;;, + 3040;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087996,0.354690,0.505022,1.000000;;, + 3120;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088024,0.354678,0.505043,1.000000;;, + 3200;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087999,0.354694,0.505016,1.000000;;, + 3280;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088015,0.354683,0.505044,1.000000;;, + 3360;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088017,0.354681,0.505035,1.000000;;, + 3440;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088024,0.354685,0.505028,1.000000;;, + 3520;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088020,0.354692,0.505020,1.000000;;, + 3600;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.087996,0.354696,0.505013,1.000000;;, + 3680;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.087994,0.354693,0.505020,1.000000;;, + 3760;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.087996,0.354686,0.505022,1.000000;;, + 3840;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.088005,0.354690,0.505030,1.000000;;, + 3920;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088001,0.354686,0.505025,1.000000;;, + 4000;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.087980,0.354687,0.505010,1.000000;;, + 4080;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088009,0.354684,0.505041,1.000000;;, + 4160;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087996,0.354690,0.505006,1.000000;;, + 4240;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.087988,0.354687,0.505018,1.000000;;, + 4320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087992,0.354683,0.505023,1.000000;;, + 4400;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.087997,0.354690,0.505014,1.000000;;, + 4480;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.088001,0.354687,0.505015,1.000000;;, + 4560;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.088013,0.354685,0.505053,1.000000;;, + 4640;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,-0.000000,-0.000796,1.000000,0.000000,24.088007,0.354691,0.505029,1.000000;;, + 4720;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087994,0.354688,0.505030,1.000000;;, + 4800;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087997,0.354687,0.504994,1.000000;;, + 4960;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000796,0.000000,0.000000,-0.000796,1.000000,0.000000,24.087999,0.354686,0.505020,1.000000;;; + } + { Bip01_R_Finger1 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300053,-0.000001,-0.000002,1.000000;;, + 80;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300060,0.000002,-0.000000,1.000000;;, + 160;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300057,-0.000002,-0.000002,1.000000;;, + 240;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300056,0.000004,0.000001,1.000000;;, + 320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300049,0.000001,-0.000006,1.000000;;, + 400;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300044,0.000001,-0.000001,1.000000;;, + 480;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300066,0.000002,0.000005,1.000000;;, + 560;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300056,0.000002,0.000000,1.000000;;, + 640;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300058,0.000001,0.000002,1.000000;;, + 720;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300049,0.000002,-0.000004,1.000000;;, + 800;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300060,-0.000003,-0.000002,1.000000;;, + 880;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300063,0.000001,-0.000012,1.000000;;, + 960;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300061,-0.000000,-0.000003,1.000000;;, + 1040;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300055,-0.000001,0.000002,1.000000;;, + 1120;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300057,0.000000,0.000003,1.000000;;, + 1200;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300050,0.000003,0.000002,1.000000;;, + 1280;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300063,0.000001,0.000010,1.000000;;, + 1360;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300057,0.000005,-0.000010,1.000000;;, + 1440;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300047,-0.000002,0.000016,1.000000;;, + 1520;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300065,-0.000002,-0.000005,1.000000;;, + 1600;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300051,0.000005,0.000003,1.000000;;, + 1680;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300046,0.000004,-0.000021,1.000000;;, + 1760;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300056,-0.000003,0.000006,1.000000;;, + 1840;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300049,-0.000001,0.000003,1.000000;;, + 1920;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300052,0.000002,-0.000008,1.000000;;, + 2000;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300055,-0.000001,0.000007,1.000000;;, + 2080;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300063,0.000004,0.000005,1.000000;;, + 2160;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300055,-0.000006,0.000004,1.000000;;, + 2240;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300035,-0.000005,-0.000005,1.000000;;, + 2320;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300053,-0.000001,0.000010,1.000000;;, + 2400;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300064,0.000002,0.000004,1.000000;;, + 2480;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300051,-0.000006,0.000011,1.000000;;, + 2560;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300082,-0.000002,-0.000012,1.000000;;, + 2640;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300029,-0.000001,0.000011,1.000000;;, + 2720;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300046,-0.000002,0.000013,1.000000;;, + 2800;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300031,-0.000002,0.000014,1.000000;;, + 2880;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300129,-0.000010,-0.000001,1.000000;;, + 2960;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300054,0.000002,-0.000004,1.000000;;, + 3040;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300058,0.000006,-0.000007,1.000000;;, + 3120;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300048,-0.000009,0.000023,1.000000;;, + 3200;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300021,0.000013,-0.000009,1.000000;;, + 3280;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300056,-0.000000,-0.000001,1.000000;;, + 3360;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300068,0.000002,0.000001,1.000000;;, + 3440;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300078,-0.000014,0.000021,1.000000;;, + 3520;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300060,-0.000001,-0.000000,1.000000;;, + 3600;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300076,-0.000000,0.000011,1.000000;;, + 3680;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300021,0.000012,-0.000014,1.000000;;, + 3760;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300063,0.000003,-0.000001,1.000000;;, + 3840;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300073,-0.000002,0.000013,1.000000;;, + 3920;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300053,0.000004,-0.000008,1.000000;;, + 4000;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300080,-0.000001,0.000014,1.000000;;, + 4080;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300086,-0.000009,0.000042,1.000000;;, + 4160;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300044,0.000002,-0.000028,1.000000;;, + 4240;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300059,-0.000001,-0.000010,1.000000;;, + 4320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300069,-0.000008,0.000042,1.000000;;, + 4400;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300056,-0.000006,0.000022,1.000000;;, + 4480;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,9.300056,0.000002,-0.000013,1.000000;;, + 4560;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300052,-0.000000,-0.000015,1.000000;;, + 4640;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,9.300047,-0.000003,-0.000012,1.000000;;, + 4720;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300055,-0.000005,0.000008,1.000000;;, + 4800;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,9.300055,-0.000003,-0.000036,1.000000;;, + 4960;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,9.300053,-0.000001,-0.000002,1.000000;;; + } + { Bip01_R_Finger11 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850059,0.000001,-0.000003,1.000000;;, + 80;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850061,-0.000004,0.000004,1.000000;;, + 160;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850073,0.000004,0.000004,1.000000;;, + 240;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850068,-0.000001,0.000002,1.000000;;, + 320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850068,0.000000,0.000004,1.000000;;, + 400;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850073,0.000004,0.000001,1.000000;;, + 480;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850047,-0.000004,-0.000011,1.000000;;, + 560;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850059,-0.000003,0.000004,1.000000;;, + 640;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850069,0.000001,0.000000,1.000000;;, + 720;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850069,-0.000003,-0.000000,1.000000;;, + 800;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850062,0.000003,-0.000000,1.000000;;, + 880;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850066,-0.000001,0.000004,1.000000;;, + 960;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850061,-0.000002,-0.000004,1.000000;;, + 1040;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850067,0.000000,0.000001,1.000000;;, + 1120;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850071,0.000001,0.000002,1.000000;;, + 1200;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850074,-0.000001,0.000011,1.000000;;, + 1280;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850064,0.000000,-0.000003,1.000000;;, + 1360;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850067,-0.000003,0.000001,1.000000;;, + 1440;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850084,0.000001,-0.000006,1.000000;;, + 1520;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850065,0.000003,0.000004,1.000000;;, + 1600;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850064,-0.000001,-0.000003,1.000000;;, + 1680;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850087,-0.000010,0.000038,1.000000;;, + 1760;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850060,-0.000001,0.000010,1.000000;;, + 1840;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850059,0.000010,-0.000017,1.000000;;, + 1920;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850066,0.000002,0.000002,1.000000;;, + 2000;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850079,-0.000004,0.000000,1.000000;;, + 2080;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850064,-0.000008,0.000001,1.000000;;, + 2160;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850057,0.000004,-0.000001,1.000000;;, + 2240;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850079,0.000004,0.000005,1.000000;;, + 2320;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850055,0.000003,-0.000010,1.000000;;, + 2400;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850050,0.000010,-0.000009,1.000000;;, + 2480;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850052,0.000010,-0.000012,1.000000;;, + 2560;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850057,-0.000001,0.000003,1.000000;;, + 2640;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850087,0.000005,-0.000009,1.000000;;, + 2720;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850062,0.000001,-0.000002,1.000000;;, + 2800;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850121,-0.000019,-0.000002,1.000000;;, + 2880;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.849994,0.000003,0.000005,1.000000;;, + 2960;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850060,0.000000,0.000005,1.000000;;, + 3040;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850060,-0.000005,0.000007,1.000000;;, + 3120;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850054,0.000008,-0.000009,1.000000;;, + 3200;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850092,-0.000008,0.000003,1.000000;;, + 3280;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850080,-0.000001,0.000001,1.000000;;, + 3360;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850073,0.000003,-0.000010,1.000000;;, + 3440;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850039,0.000007,-0.000015,1.000000;;, + 3520;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850013,0.000004,-0.000013,1.000000;;, + 3600;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850048,-0.000008,0.000004,1.000000;;, + 3680;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850091,-0.000011,0.000002,1.000000;;, + 3760;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850017,0.000005,-0.000012,1.000000;;, + 3840;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850051,-0.000000,-0.000004,1.000000;;, + 3920;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850064,-0.000007,-0.000001,1.000000;;, + 4000;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850058,-0.000002,-0.000005,1.000000;;, + 4080;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850063,0.000002,-0.000028,1.000000;;, + 4160;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850079,0.000001,0.000024,1.000000;;, + 4240;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850040,0.000002,-0.000030,1.000000;;, + 4320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850048,0.000017,-0.000079,1.000000;;, + 4400;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850065,0.000008,-0.000017,1.000000;;, + 4480;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,10.850068,0.000002,0.000024,1.000000;;, + 4560;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850074,-0.000003,0.000020,1.000000;;, + 4640;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,10.850078,-0.000001,0.000023,1.000000;;, + 4720;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850074,-0.000001,0.000017,1.000000;;, + 4800;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,10.850063,0.000009,0.000012,1.000000;;, + 4960;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,10.850059,0.000001,-0.000003,1.000000;;; + } + { Bip01_R_Finger12 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207767,0.000001,-0.000003,1.000000;;, + 80;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207771,0.000001,-0.000006,1.000000;;, + 160;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,11.207757,-0.000001,-0.000003,1.000000;;, + 240;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207756,-0.000003,-0.000002,1.000000;;, + 320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,11.207762,0.000000,-0.000007,1.000000;;, + 400;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207765,-0.000001,0.000005,1.000000;;, + 480;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,11.207770,0.000001,0.000002,1.000000;;, + 560;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,11.207768,0.000000,-0.000007,1.000000;;, + 640;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207765,0.000001,0.000000,1.000000;;, + 720;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207763,0.000001,0.000001,1.000000;;, + 800;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207768,-0.000003,0.000004,1.000000;;, + 880;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,11.207760,-0.000002,-0.000001,1.000000;;, + 960;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207767,0.000003,0.000003,1.000000;;, + 1040;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,11.207764,0.000003,0.000001,1.000000;;, + 1120;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207767,0.000001,-0.000007,1.000000;;, + 1200;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207765,-0.000001,-0.000018,1.000000;;, + 1280;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207752,0.000002,-0.000019,1.000000;;, + 1360;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207767,0.000003,-0.000009,1.000000;;, + 1440;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207752,0.000006,-0.000018,1.000000;;, + 1520;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,11.207759,0.000003,-0.000014,1.000000;;, + 1600;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207762,0.000001,-0.000006,1.000000;;, + 1680;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207762,0.000009,-0.000012,1.000000;;, + 1760;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207764,0.000005,-0.000008,1.000000;;, + 1840;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207767,-0.000012,0.000006,1.000000;;, + 1920;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,11.207767,-0.000005,0.000009,1.000000;;, + 2000;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207761,0.000007,-0.000007,1.000000;;, + 2080;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,11.207759,0.000001,0.000001,1.000000;;, + 2160;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207764,-0.000011,-0.000003,1.000000;;, + 2240;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207760,-0.000006,0.000002,1.000000;;, + 2320;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207768,0.000004,-0.000001,1.000000;;, + 2400;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207767,-0.000001,0.000005,1.000000;;, + 2480;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207771,-0.000007,0.000007,1.000000;;, + 2560;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,11.207754,-0.000008,0.000019,1.000000;;, + 2640;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,11.207768,-0.000000,-0.000003,1.000000;;, + 2720;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,11.207767,0.000001,-0.000006,1.000000;;, + 2800;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207760,0.000006,-0.000012,1.000000;;, + 2880;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,11.207788,-0.000004,0.000004,1.000000;;, + 2960;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,11.207781,-0.000001,-0.000003,1.000000;;, + 3040;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207762,0.000004,0.000001,1.000000;;, + 3120;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207790,0.000001,-0.000008,1.000000;;, + 3200;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207770,-0.000011,0.000011,1.000000;;, + 3280;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207776,-0.000010,0.000005,1.000000;;, + 3360;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,11.207766,-0.000003,0.000010,1.000000;;, + 3440;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207795,-0.000000,-0.000005,1.000000;;, + 3520;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207788,-0.000011,0.000012,1.000000;;, + 3600;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,11.207775,0.000002,-0.000003,1.000000;;, + 3680;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,11.207780,-0.000013,0.000009,1.000000;;, + 3760;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,11.207794,-0.000012,0.000004,1.000000;;, + 3840;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207778,-0.000008,-0.000001,1.000000;;, + 3920;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207764,-0.000002,0.000000,1.000000;;, + 4000;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207761,-0.000006,0.000001,1.000000;;, + 4080;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,11.207756,-0.000004,0.000003,1.000000;;, + 4160;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207771,0.000003,0.000013,1.000000;;, + 4240;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207773,0.000003,0.000022,1.000000;;, + 4320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207767,-0.000001,0.000026,1.000000;;, + 4400;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,11.207769,-0.000001,0.000002,1.000000;;, + 4480;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,11.207768,-0.000001,0.000013,1.000000;;, + 4560;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,11.207754,-0.000001,-0.000008,1.000000;;, + 4640;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,11.207759,-0.000003,0.000012,1.000000;;, + 4720;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,11.207764,0.000004,-0.000020,1.000000;;, + 4800;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,11.207763,0.000001,-0.000002,1.000000;;, + 4960;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,11.207767,0.000001,-0.000003,1.000000;;; + } + { Dummy02 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;-0.928221,-0.372022,0.002089,0.000000,-0.371612,0.927434,0.042085,0.000000,-0.017595,0.038288,-0.999112,0.000000,-27.673786,-14.652106,27.738972,1.000000;;, + 80;16;-0.911893,-0.410423,0.001942,0.000000,-0.410014,0.911176,0.040585,0.000000,-0.018426,0.036213,-0.999174,0.000000,-27.803984,-14.906741,27.552347,1.000000;;, + 160;16;-0.894068,-0.447927,0.002030,0.000000,-0.447515,0.893423,0.039060,0.000000,-0.019310,0.034014,-0.999235,0.000000,-27.937048,-15.168123,27.357708,1.000000;;, + 240;16;-0.876729,-0.480982,0.001449,0.000000,-0.480732,0.876364,0.029699,0.000000,-0.015554,0.025342,-0.999558,0.000000,-28.077749,-15.463904,27.139896,1.000000;;, + 320;16;-0.858316,-0.513121,0.000186,0.000000,-0.513017,0.858149,0.019868,0.000000,-0.010355,0.016958,-0.999803,0.000000,-28.222052,-15.746859,26.922985,1.000000;;, + 400;16;-0.844044,-0.536271,-0.001682,0.000000,-0.536212,0.843896,0.017797,0.000000,-0.008125,0.015924,-0.999840,0.000000,-28.368185,-15.989561,26.722809,1.000000;;, + 480;16;-0.829903,-0.557881,-0.005424,0.000000,-0.557898,0.829793,0.013899,0.000000,-0.003253,0.014560,-0.999889,0.000000,-28.514095,-16.165241,26.556234,1.000000;;, + 560;16;-0.824385,-0.566006,-0.005093,0.000000,-0.565667,0.823504,0.043151,0.000000,-0.020230,0.038454,-0.999056,0.000000,-28.656796,-16.251249,26.439451,1.000000;;, + 640;16;-0.821005,-0.570894,-0.005540,0.000000,-0.569853,0.818838,0.069083,0.000000,-0.034903,0.059874,-0.997595,0.000000,-28.797022,-16.210737,26.392929,1.000000;;, + 720;16;-0.823503,-0.567299,-0.003918,0.000000,-0.564112,0.818106,0.111716,0.000000,-0.060171,0.094209,-0.993732,0.000000,-28.936790,-15.984868,26.446907,1.000000;;, + 800;16;-0.830397,-0.557166,-0.002518,0.000000,-0.551123,0.820709,0.150666,0.000000,-0.081880,0.126500,-0.988582,0.000000,-29.068157,-15.612783,26.578825,1.000000;;, + 880;16;-0.837220,-0.546855,-0.003339,0.000000,-0.539885,0.825545,0.164316,0.000000,-0.087101,0.139372,-0.986402,0.000000,-29.186691,-15.091745,26.783831,1.000000;;, + 960;16;-0.851299,-0.524663,-0.004269,0.000000,-0.517113,0.837616,0.176049,0.000000,-0.088790,0.152078,-0.984372,0.000000,-29.284082,-14.482901,27.028332,1.000000;;, + 1040;16;-0.881730,-0.471150,0.023876,0.000000,-0.460801,0.870997,0.170374,0.000000,-0.101067,0.139222,-0.985090,0.000000,-29.349228,-13.847182,27.284319,1.000000;;, + 1120;16;-0.924826,-0.375312,0.061950,0.000000,-0.359915,0.916074,0.176831,0.000000,-0.123117,0.141241,-0.982290,0.000000,-29.390091,-13.188616,27.543690,1.000000;;, + 1200;16;-0.953882,-0.285967,0.091281,0.000000,-0.264746,0.944765,0.193205,0.000000,-0.141489,0.160129,-0.976903,0.000000,-29.408573,-12.541369,27.790316,1.000000;;, + 1280;16;-0.973788,-0.194748,0.117513,0.000000,-0.166942,0.962843,0.212280,0.000000,-0.154488,0.187098,-0.970117,0.000000,-29.412472,-11.880296,28.029623,1.000000;;, + 1360;16;-0.984386,-0.107567,0.139334,0.000000,-0.074127,0.971274,0.226124,0.000000,-0.159654,0.212265,-0.964082,0.000000,-29.409801,-11.187845,28.261599,1.000000;;, + 1440;16;-0.987640,-0.032138,0.153410,0.000000,0.005524,0.971008,0.238984,0.000000,-0.156642,0.236878,-0.958828,0.000000,-29.400465,-10.475192,28.482176,1.000000;;, + 1520;16;-0.987774,0.018235,0.154822,0.000000,0.057435,0.965843,0.252683,0.000000,-0.144926,0.258485,-0.955082,0.000000,-29.386217,-9.746704,28.688866,1.000000;;, + 1600;16;-0.987223,0.055913,0.149211,0.000000,0.094826,0.958698,0.268152,0.000000,-0.128055,0.278875,-0.951751,0.000000,-29.368801,-9.006860,28.879656,1.000000;;, + 1680;16;-0.986282,0.088304,0.139466,0.000000,0.125685,0.949444,0.287680,0.000000,-0.107012,0.301263,-0.947517,0.000000,-29.349707,-8.260389,29.053083,1.000000;;, + 1760;16;-0.984677,0.118243,0.128176,0.000000,0.152614,0.939945,0.305308,0.000000,-0.084378,0.320191,-0.943588,0.000000,-29.330469,-7.512198,29.208227,1.000000;;, + 1840;16;-0.981517,0.150351,0.118402,0.000000,0.180808,0.931279,0.316272,0.000000,-0.062714,0.331834,-0.941251,0.000000,-29.312498,-6.767277,29.344717,1.000000;;, + 1920;16;-0.976290,0.186521,0.109854,0.000000,0.212371,0.923573,0.319234,0.000000,-0.041914,0.334995,-0.941287,0.000000,-29.296946,-6.030762,29.462757,1.000000;;, + 2000;16;-0.967245,0.231887,0.103275,0.000000,0.252812,0.916654,0.309568,0.000000,-0.022883,0.325537,-0.945252,0.000000,-29.285093,-5.307709,29.563105,1.000000;;, + 2080;16;-0.954827,0.281060,0.096486,0.000000,0.297109,0.908985,0.292358,0.000000,-0.005534,0.307818,-0.951429,0.000000,-29.278000,-4.603338,29.647009,1.000000;;, + 2160;16;-0.939254,0.331755,0.087974,0.000000,0.343063,0.899678,0.269978,0.000000,0.010418,0.283758,-0.958839,0.000000,-29.269199,-3.928405,29.714540,1.000000;;, + 2240;16;-0.921715,0.379808,0.078662,0.000000,0.387158,0.888636,0.245836,0.000000,0.023468,0.257045,-0.966114,0.000000,-29.282276,-3.270983,29.772947,1.000000;;, + 2320;16;-0.904576,0.420547,0.069868,0.000000,0.425042,0.877045,0.223901,0.000000,0.032884,0.232233,-0.972104,0.000000,-29.346003,-2.617593,29.828417,1.000000;;, + 2400;16;-0.888278,0.455005,0.062707,0.000000,0.457681,0.865378,0.204078,0.000000,0.038591,0.209978,-0.976944,0.000000,-29.436523,-1.981518,29.881910,1.000000;;, + 2480;16;-0.871675,0.486327,0.060564,0.000000,0.488470,0.852122,0.187846,0.000000,0.039746,0.193324,-0.980329,0.000000,-29.557138,-1.359871,29.937998,1.000000;;, + 2560;16;-0.861675,0.504099,0.058305,0.000000,0.505993,0.844767,0.174182,0.000000,0.038550,0.179590,-0.982986,0.000000,-29.655882,-0.786586,29.994652,1.000000;;, + 2640;16;-0.850559,0.522404,0.060360,0.000000,0.524798,0.835842,0.161105,0.000000,0.033710,0.168706,-0.985090,0.000000,-29.685301,-0.287678,30.054073,1.000000;;, + 2720;16;-0.839227,0.540056,0.063543,0.000000,0.543025,0.826154,0.150310,0.000000,0.028680,0.160649,-0.986595,0.000000,-29.639238,0.112493,30.116144,1.000000;;, + 2800;16;-0.831739,0.550993,0.067944,0.000000,0.554706,0.819822,0.142099,0.000000,0.022593,0.155878,-0.987518,0.000000,-29.481970,0.381362,30.180090,1.000000;;, + 2880;16;-0.824607,0.560841,0.074037,0.000000,0.565469,0.813379,0.136600,0.000000,0.016391,0.154507,-0.987856,0.000000,-29.257454,0.515694,30.246803,1.000000;;, + 2960;16;-0.823079,0.564125,0.065599,0.000000,0.567362,0.811610,0.139247,0.000000,0.025312,0.151829,-0.988082,0.000000,-28.989264,0.492861,30.314617,1.000000;;, + 3040;16;-0.821983,0.566438,0.059090,0.000000,0.568494,0.809885,0.144570,0.000000,0.034034,0.152426,-0.987728,0.000000,-28.700897,0.341238,30.383587,1.000000;;, + 3120;16;-0.826104,0.559909,0.063667,0.000000,0.562920,0.814747,0.138952,0.000000,0.025928,0.150629,-0.988250,0.000000,-28.413420,0.076273,30.454477,1.000000;;, + 3200;16;-0.836777,0.543459,0.066758,0.000000,0.547203,0.825715,0.136979,0.000000,0.019320,0.151151,-0.988322,0.000000,-28.155458,-0.285411,30.520918,1.000000;;, + 3280;16;-0.851590,0.520256,0.064253,0.000000,0.524081,0.842254,0.126286,0.000000,0.011583,0.141218,-0.989911,0.000000,-27.962389,-0.726958,30.578775,1.000000;;, + 3360;16;-0.869128,0.490799,0.061101,0.000000,0.494557,0.861031,0.118490,0.000000,0.005545,0.133201,-0.991073,0.000000,-27.836496,-1.234247,30.624882,1.000000;;, + 3440;16;-0.887892,0.456440,0.057541,0.000000,0.460052,0.880657,0.113116,0.000000,0.000957,0.126907,-0.991914,0.000000,-27.802397,-1.789792,30.654890,1.000000;;, + 3520;16;-0.907077,0.417519,0.053751,0.000000,0.420957,0.900416,0.109757,0.000000,-0.002573,0.122185,-0.992504,0.000000,-27.830305,-2.386317,30.668243,1.000000;;, + 3600;16;-0.925802,0.374125,0.054043,0.000000,0.377976,0.918066,0.119538,0.000000,-0.004893,0.131095,-0.991358,0.000000,-27.902847,-3.010064,30.663122,1.000000;;, + 3680;16;-0.943410,0.327208,0.053964,0.000000,0.331539,0.934358,0.130601,0.000000,-0.007688,0.141101,-0.989965,0.000000,-28.007349,-3.661772,30.639570,1.000000;;, + 3760;16;-0.959327,0.277680,0.050859,0.000000,0.282077,0.950027,0.133722,0.000000,-0.011186,0.142630,-0.989713,0.000000,-28.129053,-4.338365,30.598248,1.000000;;, + 3840;16;-0.973079,0.225510,0.047554,0.000000,0.229995,0.963420,0.137565,0.000000,-0.014792,0.144799,-0.989350,0.000000,-28.256105,-5.037010,30.537418,1.000000;;, + 3920;16;-0.984303,0.172439,0.037585,0.000000,0.175741,0.977218,0.118996,0.000000,-0.016209,0.123734,-0.992183,0.000000,-28.375837,-5.754852,30.456379,1.000000;;, + 4000;16;-0.992648,0.117681,0.028285,0.000000,0.119956,0.987680,0.100497,0.000000,-0.016110,0.103151,-0.994535,0.000000,-28.475786,-6.488847,30.354843,1.000000;;, + 4080;16;-0.997899,0.061722,0.019677,0.000000,0.063128,0.994679,0.081416,0.000000,-0.014548,0.082487,-0.996486,0.000000,-28.540384,-7.235955,30.232977,1.000000;;, + 4160;16;-0.999906,0.006143,0.012246,0.000000,0.006892,0.998048,0.062063,0.000000,-0.011841,0.062142,-0.997997,0.000000,-28.565617,-7.992917,30.090918,1.000000;;, + 4240;16;-0.998890,-0.045932,0.010470,0.000000,-0.045145,0.996802,0.065936,0.000000,-0.013465,0.065390,-0.997769,0.000000,-28.537481,-8.756502,29.929228,1.000000;;, + 4320;16;-0.995413,-0.095229,0.009188,0.000000,-0.094366,0.993104,0.069573,0.000000,-0.015750,0.068387,-0.997534,0.000000,-28.470556,-9.522673,29.747852,1.000000;;, + 4400;16;-0.991651,-0.128660,0.008704,0.000000,-0.127798,0.989535,0.066988,0.000000,-0.017232,0.065316,-0.997716,0.000000,-28.371780,-10.287396,29.547218,1.000000;;, + 4480;16;-0.986949,-0.160784,0.008958,0.000000,-0.159894,0.985052,0.064088,0.000000,-0.019128,0.061819,-0.997904,0.000000,-28.251011,-11.046824,29.328005,1.000000;;, + 4560;16;-0.980691,-0.195325,0.009659,0.000000,-0.194402,0.979051,0.060564,0.000000,-0.021286,0.057517,-0.998118,0.000000,-28.117359,-11.797178,29.091358,1.000000;;, + 4640;16;-0.971493,-0.236834,0.010537,0.000000,-0.235888,0.970131,0.056592,0.000000,-0.023625,0.052493,-0.998342,0.000000,-27.979946,-12.534884,28.838869,1.000000;;, + 4720;16;-0.965536,-0.259803,0.015587,0.000000,-0.258707,0.964567,0.051776,0.000000,-0.028486,0.045959,-0.998537,0.000000,-27.853834,-13.252464,28.574549,1.000000;;, + 4800;16;-0.959397,-0.281208,0.021883,0.000000,-0.279994,0.958874,0.046525,0.000000,-0.034066,0.038509,-0.998677,0.000000,-27.730272,-13.958670,28.295168,1.000000;;, + 4960;16;-0.928221,-0.372022,0.002089,0.000000,-0.371612,0.927434,0.042085,0.000000,-0.017595,0.038288,-0.999112,0.000000,-27.673786,-14.652106,27.738972,1.000000;;; + } + { Bip01_L_Thigh } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.942163,-0.335154,0.000000,0.000000,0.335154,0.942163,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231491,0.000003,-0.000001,1.000000;;, + 80;16;0.946470,-0.322791,0.000000,0.000000,0.322791,0.946470,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231499,0.000009,-0.000001,1.000000;;, + 160;16;0.950613,-0.310379,0.000000,0.000000,0.310379,0.950613,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231491,0.000003,-0.000001,1.000000;;, + 240;16;0.952025,-0.306021,-0.000000,0.000000,0.306021,0.952025,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231506,0.000002,-0.000002,1.000000;;, + 320;16;0.953424,-0.301634,-0.000000,0.000000,0.301634,0.953424,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231491,-0.000004,0.000001,1.000000;;, + 400;16;0.949301,-0.314369,0.000000,0.000000,0.314369,0.949301,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231499,-0.000008,-0.000000,1.000000;;, + 480;16;0.944996,-0.327081,0.000000,0.000000,0.327081,0.944996,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231499,-0.000004,-0.000001,1.000000;;, + 560;16;0.930883,-0.365318,-0.000000,0.000000,0.365318,0.930883,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231499,-0.000003,0.000003,1.000000;;, + 640;16;0.915212,-0.402971,0.000000,0.000000,0.402971,0.915212,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231499,-0.000010,-0.000001,1.000000;;, + 720;16;0.894055,-0.447956,0.000000,0.000000,0.447956,0.894055,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231522,0.000003,-0.000001,1.000000;;, + 800;16;0.870688,-0.491835,-0.000000,0.000000,0.491835,0.870688,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231522,-0.000005,0.000002,1.000000;;, + 880;16;0.855169,-0.518349,-0.000000,0.000000,0.518349,0.855169,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231506,-0.000015,-0.000003,1.000000;;, + 960;16;0.838845,-0.544371,-0.000000,0.000000,0.544371,0.838845,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231514,-0.000029,-0.000002,1.000000;;, + 1040;16;0.805776,-0.592221,-0.000000,0.000000,0.592221,0.805776,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231499,-0.000011,-0.000003,1.000000;;, + 1120;16;0.739182,-0.673506,0.000000,0.000000,0.673506,0.739182,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231499,-0.000016,-0.000002,1.000000;;, + 1200;16;0.662180,-0.749345,-0.000000,0.000000,0.749345,0.662180,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231506,-0.000011,-0.000002,1.000000;;, + 1280;16;0.580639,-0.814161,0.000000,0.000000,0.814161,0.580639,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231499,-0.000018,-0.000005,1.000000;;, + 1360;16;0.512479,-0.858699,0.000000,0.000000,0.858699,0.512479,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231483,-0.000010,-0.000001,1.000000;;, + 1440;16;0.468474,-0.883477,0.000000,0.000000,0.883477,0.468474,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231483,-0.000011,-0.000002,1.000000;;, + 1520;16;0.470332,-0.882490,-0.000000,0.000000,0.882490,0.470332,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231499,-0.000007,-0.000001,1.000000;;, + 1600;16;0.499227,-0.866471,0.000000,0.000000,0.866471,0.499227,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231506,0.000019,0.000001,1.000000;;, + 1680;16;0.544114,-0.839011,0.000000,0.000000,0.839011,0.544114,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231483,-0.000001,-0.000007,1.000000;;, + 1760;16;0.595785,-0.803144,0.000000,0.000000,0.803144,0.595785,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231499,-0.000007,0.000001,1.000000;;, + 1840;16;0.642066,-0.766650,0.000000,0.000000,0.766650,0.642066,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231491,0.000007,0.000005,1.000000;;, + 1920;16;0.685771,-0.727817,0.000000,0.000000,0.727817,0.685771,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231499,0.000002,-0.000004,1.000000;;, + 2000;16;0.725507,-0.688215,-0.000000,0.000000,0.688215,0.725507,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231514,0.000007,0.000003,1.000000;;, + 2080;16;0.762653,-0.646808,-0.000000,0.000000,0.646808,0.762653,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231522,0.000012,0.000005,1.000000;;, + 2160;16;0.800105,-0.599860,0.000000,0.000000,0.599860,0.800105,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231491,-0.000002,-0.000001,1.000000;;, + 2240;16;0.831071,-0.556167,-0.000000,0.000000,0.556167,0.831071,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231506,-0.000007,0.000002,1.000000;;, + 2320;16;0.851740,-0.523965,-0.000000,0.000000,0.523965,0.851740,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231499,0.000009,0.000002,1.000000;;, + 2400;16;0.862764,-0.505606,0.000000,0.000000,0.505606,0.862764,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231514,0.000021,0.000003,1.000000;;, + 2480;16;0.858597,-0.512651,0.000000,0.000000,0.512651,0.858597,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231506,-0.000001,0.000002,1.000000;;, + 2560;16;0.851861,-0.523767,-0.000000,0.000000,0.523767,0.851861,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231514,-0.000004,0.000000,1.000000;;, + 2640;16;0.834410,-0.551144,0.000000,0.000000,0.551144,0.834410,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231491,0.000018,0.000002,1.000000;;, + 2720;16;0.816079,-0.577940,-0.000000,0.000000,0.577940,0.816079,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231506,0.000016,-0.000001,1.000000;;, + 2800;16;0.795822,-0.605531,0.000000,0.000000,0.605531,0.795822,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231499,0.000002,0.000004,1.000000;;, + 2880;16;0.774632,-0.632412,-0.000000,0.000000,0.632413,0.774632,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231514,-0.000004,-0.000000,1.000000;;, + 2960;16;0.794443,-0.607340,-0.000000,0.000000,0.607339,0.794442,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231514,-0.000008,0.000003,1.000000;;, + 3040;16;0.813442,-0.581647,-0.000000,0.000000,0.581647,0.813442,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231529,0.000008,-0.000002,1.000000;;, + 3120;16;0.778247,-0.627958,0.000000,0.000000,0.627958,0.778247,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231506,0.000010,-0.000002,1.000000;;, + 3200;16;0.754281,-0.656552,-0.000000,0.000000,0.656552,0.754281,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231537,0.000012,0.000006,1.000000;;, + 3280;16;0.743273,-0.668988,-0.000000,0.000000,0.668988,0.743273,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231522,0.000008,0.000001,1.000000;;, + 3360;16;0.740677,-0.671861,0.000000,0.000000,0.671862,0.740677,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231514,0.000010,0.000003,1.000000;;, + 3440;16;0.745040,-0.667020,0.000000,0.000000,0.667020,0.745040,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231514,-0.000006,-0.000000,1.000000;;, + 3520;16;0.755634,-0.654994,0.000000,0.000000,0.654994,0.755634,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231529,0.000022,0.000002,1.000000;;, + 3600;16;0.767893,-0.640578,-0.000000,0.000000,0.640578,0.767893,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231529,-0.000014,-0.000002,1.000000;;, + 3680;16;0.784524,-0.620099,-0.000000,0.000000,0.620099,0.784524,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231529,0.000019,0.000003,1.000000;;, + 3760;16;0.802723,-0.596352,0.000000,0.000000,0.596352,0.802724,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231522,0.000000,-0.000002,1.000000;;, + 3840;16;0.823599,-0.567172,0.000000,0.000000,0.567172,0.823599,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231514,-0.000001,0.000000,1.000000;;, + 3920;16;0.847102,-0.531430,-0.000000,0.000000,0.531430,0.847102,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231529,0.000020,-0.000001,1.000000;;, + 4000;16;0.871324,-0.490708,0.000000,0.000000,0.490708,0.871324,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231499,-0.000010,-0.000002,1.000000;;, + 4080;16;0.895648,-0.444764,-0.000000,0.000000,0.444764,0.895648,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231522,0.000034,-0.000001,1.000000;;, + 4160;16;0.918115,-0.396313,-0.000000,0.000000,0.396313,0.918115,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231506,-0.000014,0.000001,1.000000;;, + 4240;16;0.935408,-0.353571,0.000000,0.000000,0.353571,0.935408,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231514,-0.000005,0.000003,1.000000;;, + 4320;16;0.949647,-0.313321,0.000000,0.000000,0.313321,0.949647,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231506,-0.000011,-0.000001,1.000000;;, + 4400;16;0.953711,-0.300723,0.000000,0.000000,0.300723,0.953711,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231483,-0.000000,0.000001,1.000000;;, + 4480;16;0.957058,-0.289897,0.000000,0.000000,0.289897,0.957058,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231499,-0.000009,-0.000003,1.000000;;, + 4560;16;0.961769,-0.273862,0.000000,0.000000,0.273862,0.961769,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231483,-0.000011,-0.000001,1.000000;;, + 4640;16;0.969896,-0.243518,0.000000,0.000000,0.243518,0.969896,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231491,0.000011,-0.000001,1.000000;;, + 4720;16;0.944640,-0.328109,0.000000,0.000000,0.328109,0.944640,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231514,0.000017,0.000000,1.000000;;, + 4800;16;0.912034,-0.410114,-0.000000,0.000000,0.410114,0.912034,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231491,-0.000008,-0.000001,1.000000;;, + 4960;16;0.942163,-0.335154,0.000000,0.000000,0.335154,0.942163,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231491,0.000003,-0.000001,1.000000;;; + } + { Bip01_L_Calf } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.819935,0.566355,0.083354,0.000000,-0.566770,0.823611,-0.020897,0.000000,-0.080486,-0.030108,0.996301,0.000000,119.231514,0.000010,0.000002,1.000000;;, + 80;16;0.819133,0.567125,0.085960,0.000000,-0.567930,0.822898,-0.017163,0.000000,-0.080470,-0.034761,0.996151,0.000000,119.231506,-0.000013,-0.000002,1.000000;;, + 160;16;0.820633,0.564575,0.088416,0.000000,-0.565741,0.824469,-0.013669,0.000000,-0.080614,-0.038804,0.995990,0.000000,119.231506,0.000009,-0.000000,1.000000;;, + 240;16;0.821535,0.563385,0.087619,0.000000,-0.564252,0.825429,-0.016908,0.000000,-0.081849,-0.035548,0.996011,0.000000,119.231499,-0.000001,-0.000001,1.000000;;, + 320;16;0.826038,0.557042,0.085821,0.000000,-0.557428,0.829943,-0.021626,0.000000,-0.083273,-0.029975,0.996076,0.000000,119.231529,0.000014,-0.000001,1.000000;;, + 400;16;0.834533,0.544288,0.085466,0.000000,-0.544571,0.838426,-0.022024,0.000000,-0.083644,-0.028163,0.996098,0.000000,119.231514,0.000008,0.000000,1.000000;;, + 480;16;0.850094,0.520000,0.083306,0.000000,-0.519840,0.853889,-0.025319,0.000000,-0.084300,-0.021782,0.996202,0.000000,119.231506,0.000009,0.000001,1.000000;;, + 560;16;0.875466,0.479959,0.056556,0.000000,-0.481614,0.876161,0.019734,0.000000,-0.040081,-0.044515,0.998204,0.000000,119.231499,0.000006,-0.000002,1.000000;;, + 640;16;0.906159,0.422411,0.021083,0.000000,-0.422892,0.904206,0.059780,0.000000,0.006188,-0.063086,0.997989,0.000000,119.231506,0.000006,0.000002,1.000000;;, + 720;16;0.936240,0.345371,-0.064606,0.000000,-0.336500,0.934263,0.117986,0.000000,0.101108,-0.088723,0.990911,0.000000,119.231529,-0.000006,-0.000001,1.000000;;, + 800;16;0.955721,0.242467,-0.166756,0.000000,-0.216573,0.963188,0.159265,0.000000,0.199234,-0.116098,0.973050,0.000000,119.231514,-0.000003,-0.000002,1.000000;;, + 880;16;0.966320,0.105838,-0.234571,0.000000,-0.068425,0.984372,0.162267,0.000000,0.248079,-0.140751,0.958460,0.000000,119.231522,0.000002,-0.000000,1.000000;;, + 960;16;0.948597,-0.080312,-0.306127,0.000000,0.130235,0.980631,0.146295,0.000000,0.288448,-0.178643,0.940683,0.000000,119.231499,0.000012,0.000000,1.000000;;, + 1040;16;0.955816,-0.074898,-0.284263,0.000000,0.118281,0.983254,0.138643,0.000000,0.269118,-0.166140,0.948669,0.000000,119.231499,0.000002,0.000001,1.000000;;, + 1120;16;0.969026,-0.051502,-0.241531,0.000000,0.081517,0.989903,0.115966,0.000000,0.233120,-0.132063,0.963439,0.000000,119.231522,0.000004,-0.000005,1.000000;;, + 1200;16;0.981818,0.002370,-0.189811,0.000000,0.011582,0.997311,0.072359,0.000000,0.189472,-0.073242,0.979151,0.000000,119.231506,0.000005,0.000003,1.000000;;, + 1280;16;0.987825,0.070976,-0.138435,0.000000,-0.068788,0.997420,0.020535,0.000000,0.139535,-0.010763,0.990159,0.000000,119.231514,0.000006,-0.000002,1.000000;;, + 1360;16;0.985606,0.137460,-0.098419,0.000000,-0.140534,0.989760,-0.024988,0.000000,0.093977,0.038460,0.994831,0.000000,119.231499,0.000006,0.000002,1.000000;;, + 1440;16;0.976475,0.203883,-0.070209,0.000000,-0.208187,0.976208,-0.060640,0.000000,0.056176,0.073830,0.995687,0.000000,119.231514,0.000014,-0.000001,1.000000;;, + 1520;16;0.962520,0.265033,-0.057563,0.000000,-0.268819,0.960425,-0.072939,0.000000,0.035953,0.085679,0.995674,0.000000,119.231514,0.000005,0.000001,1.000000;;, + 1600;16;0.944932,0.323352,-0.050465,0.000000,-0.326285,0.942765,-0.068793,0.000000,0.025332,0.081471,0.996354,0.000000,119.231529,-0.000013,-0.000005,1.000000;;, + 1680;16;0.922942,0.382664,-0.041779,0.000000,-0.384487,0.921669,-0.051931,0.000000,0.018635,0.063993,0.997776,0.000000,119.231483,0.000003,0.000014,1.000000;;, + 1760;16;0.899830,0.435313,-0.028432,0.000000,-0.436035,0.899495,-0.027961,0.000000,0.013403,0.037557,0.999205,0.000000,119.231468,0.000009,0.000009,1.000000;;, + 1840;16;0.878910,0.476864,-0.010806,0.000000,-0.476944,0.878910,-0.006518,0.000000,0.006389,0.010883,0.999920,0.000000,119.231483,-0.000007,-0.000001,1.000000;;, + 1920;16;0.861739,0.507287,0.008100,0.000000,-0.507347,0.861688,0.009672,0.000000,-0.002073,-0.012445,0.999920,0.000000,119.231506,0.000019,0.000005,1.000000;;, + 2000;16;0.850935,0.524778,0.022754,0.000000,-0.525134,0.850905,0.013979,0.000000,-0.012025,-0.023844,0.999643,0.000000,119.231506,-0.000006,-0.000003,1.000000;;, + 2080;16;0.845055,0.533679,0.032674,0.000000,-0.534274,0.845214,0.012795,0.000000,-0.020789,-0.028269,0.999384,0.000000,119.231529,-0.000003,-0.000003,1.000000;;, + 2160;16;0.843436,0.535881,0.038038,0.000000,-0.536569,0.843795,0.010216,0.000000,-0.026622,-0.029027,0.999224,0.000000,119.231483,0.000012,0.000003,1.000000;;, + 2240;16;0.845095,0.533109,0.040127,0.000000,-0.533791,0.845579,0.007924,0.000000,-0.029706,-0.028116,0.999163,0.000000,119.231514,0.000031,0.000008,1.000000;;, + 2320;16;0.848386,0.527731,0.041726,0.000000,-0.528451,0.848928,0.007796,0.000000,-0.031308,-0.028665,0.999099,0.000000,119.231499,-0.000006,0.000001,1.000000;;, + 2400;16;0.853963,0.518533,0.043240,0.000000,-0.519361,0.854496,0.009968,0.000000,-0.031780,-0.030969,0.999015,0.000000,119.231499,0.000006,-0.000000,1.000000;;, + 2480;16;0.864707,0.500080,0.046927,0.000000,-0.501277,0.865103,0.017833,0.000000,-0.031679,-0.038943,0.998739,0.000000,119.231514,0.000021,0.000004,1.000000;;, + 2560;16;0.871883,0.487224,0.049326,0.000000,-0.488704,0.872126,0.023758,0.000000,-0.031443,-0.044820,0.998500,0.000000,119.231491,0.000017,0.000005,1.000000;;, + 2640;16;0.884353,0.464053,0.050747,0.000000,-0.465906,0.884188,0.033806,0.000000,-0.029182,-0.053540,0.998139,0.000000,119.231514,0.000005,0.000001,1.000000;;, + 2720;16;0.896219,0.440584,0.051742,0.000000,-0.442796,0.895536,0.044134,0.000000,-0.026892,-0.062465,0.997685,0.000000,119.231506,0.000008,0.000002,1.000000;;, + 2800;16;0.906430,0.419224,0.051341,0.000000,-0.421676,0.905154,0.053716,0.000000,-0.023953,-0.070339,0.997236,0.000000,119.231491,-0.000000,0.000001,1.000000;;, + 2880;16;0.916137,0.397674,0.050472,0.000000,-0.400321,0.914169,0.063547,0.000000,-0.020869,-0.078422,0.996702,0.000000,119.231491,0.000012,0.000003,1.000000;;, + 2960;16;0.937630,0.345753,0.036129,0.000000,-0.347484,0.935211,0.068081,0.000000,-0.010249,-0.076389,0.997025,0.000000,119.231522,0.000028,-0.000003,1.000000;;, + 3040;16;0.955974,0.292651,0.021675,0.000000,-0.293452,0.953258,0.072014,0.000000,0.000413,-0.075204,0.997168,0.000000,119.231514,-0.000004,0.000002,1.000000;;, + 3120;16;0.942333,0.333838,0.023695,0.000000,-0.334677,0.940153,0.064063,0.000000,-0.000890,-0.068299,0.997665,0.000000,119.231514,-0.000003,0.000001,1.000000;;, + 3200;16;0.930563,0.365233,0.025652,0.000000,-0.366128,0.928602,0.060407,0.000000,-0.001758,-0.065605,0.997844,0.000000,119.231499,-0.000005,-0.000004,1.000000;;, + 3280;16;0.931320,0.363275,0.025978,0.000000,-0.364137,0.930129,0.047574,0.000000,-0.006880,-0.053766,0.998530,0.000000,119.231514,-0.000016,-0.000003,1.000000;;, + 3360;16;0.934368,0.355316,0.026583,0.000000,-0.356132,0.933653,0.038251,0.000000,-0.011228,-0.045208,0.998915,0.000000,119.231506,0.000000,-0.000001,1.000000;;, + 3440;16;0.939233,0.342190,0.027342,0.000000,-0.342963,0.938808,0.031861,0.000000,-0.014766,-0.039302,0.999118,0.000000,119.231491,0.000022,0.000001,1.000000;;, + 3520;16;0.945582,0.324161,0.028189,0.000000,-0.324910,0.945330,0.028018,0.000000,-0.017565,-0.035652,0.999210,0.000000,119.231483,-0.000023,-0.000004,1.000000;;, + 3600;16;0.944105,0.328308,0.029650,0.000000,-0.329292,0.943430,0.038819,0.000000,-0.015227,-0.046413,0.998806,0.000000,119.231491,0.000031,0.000003,1.000000;;, + 3680;16;0.944000,0.328443,0.031452,0.000000,-0.329694,0.942706,0.051065,0.000000,-0.012878,-0.058575,0.998200,0.000000,119.231499,-0.000021,-0.000000,1.000000;;, + 3760;16;0.940374,0.338217,0.036142,0.000000,-0.339794,0.938901,0.054819,0.000000,-0.015393,-0.063831,0.997842,0.000000,119.231499,-0.000012,0.000000,1.000000;;, + 3840;16;0.937802,0.344730,0.041095,0.000000,-0.346695,0.936131,0.058841,0.000000,-0.018186,-0.069429,0.997421,0.000000,119.231499,0.000010,-0.000001,1.000000;;, + 3920;16;0.939902,0.338297,0.046256,0.000000,-0.340073,0.939626,0.038111,0.000000,-0.030570,-0.051551,0.998203,0.000000,119.231522,-0.000021,0.000001,1.000000;;, + 4000;16;0.942779,0.329510,0.050891,0.000000,-0.330734,0.943560,0.017611,0.000000,-0.042216,-0.033434,0.998549,0.000000,119.231476,0.000003,0.000002,1.000000;;, + 4080;16;0.946381,0.318334,0.055010,0.000000,-0.318669,0.947862,-0.002804,0.000000,-0.053034,-0.014877,0.998482,0.000000,119.231506,-0.000026,0.000003,1.000000;;, + 4160;16;0.950159,0.306179,0.058753,0.000000,-0.305398,0.951969,-0.022063,0.000000,-0.062687,0.003020,0.998029,0.000000,119.231491,0.000031,0.000001,1.000000;;, + 4240;16;0.949908,0.306152,0.062812,0.000000,-0.305789,0.951972,-0.015556,0.000000,-0.064557,-0.004431,0.997904,0.000000,119.231514,0.000023,0.000002,1.000000;;, + 4320;16;0.949171,0.307449,0.067452,0.000000,-0.307626,0.951474,-0.008013,0.000000,-0.066642,-0.013145,0.997690,0.000000,119.231491,0.000027,0.000001,1.000000;;, + 4400;16;0.943648,0.323457,0.070034,0.000000,-0.323349,0.946188,-0.013198,0.000000,-0.070534,-0.010191,0.997457,0.000000,119.231491,0.000006,-0.000000,1.000000;;, + 4480;16;0.937464,0.340343,0.072989,0.000000,-0.339952,0.940268,-0.018100,0.000000,-0.074789,-0.007844,0.997169,0.000000,119.231483,0.000030,0.000001,1.000000;;, + 4560;16;0.931869,0.354706,0.076179,0.000000,-0.353973,0.934963,-0.023376,0.000000,-0.079516,-0.005182,0.996820,0.000000,119.231483,-0.000005,0.000001,1.000000;;, + 4640;16;0.928705,0.362194,0.079510,0.000000,-0.361018,0.932101,-0.029214,0.000000,-0.084692,-0.001573,0.996406,0.000000,119.231506,-0.000001,0.000004,1.000000;;, + 4720;16;0.876284,0.474843,0.081553,0.000000,-0.475470,0.879639,-0.012791,0.000000,-0.077811,-0.027567,0.996587,0.000000,119.231522,-0.000039,-0.000003,1.000000;;, + 4800;16;0.832169,0.546757,0.092472,0.000000,-0.549113,0.835748,0.000044,0.000000,-0.077259,-0.050814,0.995715,0.000000,119.231468,-0.000006,0.000000,1.000000;;, + 4960;16;0.819935,0.566355,0.083354,0.000000,-0.566770,0.823611,-0.020897,0.000000,-0.080486,-0.030108,0.996301,0.000000,119.231514,0.000010,0.000002,1.000000;;; + } + { Bip01_L_Foot } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423233,34.577133,0.000000,1.000000;;, + 80;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423252,34.577145,-0.000001,1.000000;;, + 160;16;-0.000000,1.000000,0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423252,34.577126,0.000001,1.000000;;, + 240;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423248,34.577133,0.000002,1.000000;;, + 320;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423239,34.577137,-0.000002,1.000000;;, + 400;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423252,34.577129,-0.000002,1.000000;;, + 480;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423250,34.577129,-0.000000,1.000000;;, + 560;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423246,34.577141,-0.000001,1.000000;;, + 640;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423258,34.577145,-0.000001,1.000000;;, + 720;16;-0.000000,1.000000,0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423256,34.577141,-0.000000,1.000000;;, + 800;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423233,34.577141,-0.000003,1.000000;;, + 880;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423244,34.577141,0.000001,1.000000;;, + 960;16;0.000000,1.000000,0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423248,34.577122,0.000002,1.000000;;, + 1040;16;-0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423252,34.577137,0.000001,1.000000;;, + 1120;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423254,34.577129,0.000004,1.000000;;, + 1200;16;-0.000000,1.000000,0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423241,34.577129,0.000001,1.000000;;, + 1280;16;0.000000,1.000000,0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423254,34.577145,0.000002,1.000000;;, + 1360;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423235,34.577141,-0.000001,1.000000;;, + 1440;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423248,34.577137,-0.000001,1.000000;;, + 1520;16;-0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423246,34.577137,-0.000001,1.000000;;, + 1600;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423252,34.577145,0.000002,1.000000;;, + 1680;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423256,34.577141,-0.000003,1.000000;;, + 1760;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423248,34.577129,-0.000001,1.000000;;, + 1840;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423246,34.577129,-0.000005,1.000000;;, + 1920;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423241,34.577141,0.000002,1.000000;;, + 2000;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423250,34.577148,-0.000004,1.000000;;, + 2080;16;-0.000000,1.000000,0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423260,34.577133,-0.000002,1.000000;;, + 2160;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423248,34.577152,0.000005,1.000000;;, + 2240;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423265,34.577129,-0.000001,1.000000;;, + 2320;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423248,34.577137,0.000001,1.000000;;, + 2400;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423250,34.577148,0.000004,1.000000;;, + 2480;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423260,34.577156,0.000003,1.000000;;, + 2560;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423262,34.577137,-0.000002,1.000000;;, + 2640;16;-0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423246,34.577126,0.000000,1.000000;;, + 2720;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423256,34.577145,0.000001,1.000000;;, + 2800;16;0.000000,1.000000,0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423262,34.577152,-0.000001,1.000000;;, + 2880;16;-0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423254,34.577122,0.000002,1.000000;;, + 2960;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423243,34.577114,-0.000001,1.000000;;, + 3040;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423254,34.577148,0.000003,1.000000;;, + 3120;16;-0.000000,1.000000,0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423237,34.577110,-0.000001,1.000000;;, + 3200;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423252,34.577164,-0.000002,1.000000;;, + 3280;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423246,34.577133,0.000000,1.000000;;, + 3360;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423244,34.577129,0.000000,1.000000;;, + 3440;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423239,34.577133,0.000002,1.000000;;, + 3520;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423237,34.577118,0.000001,1.000000;;, + 3600;16;0.000000,1.000000,0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423250,34.577106,0.000001,1.000000;;, + 3680;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423250,34.577160,0.000002,1.000000;;, + 3760;16;-0.000000,1.000000,0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423243,34.577160,-0.000000,1.000000;;, + 3840;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423256,34.577129,-0.000001,1.000000;;, + 3920;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423256,34.577160,-0.000001,1.000000;;, + 4000;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423258,34.577137,-0.000001,1.000000;;, + 4080;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423260,34.577156,-0.000002,1.000000;;, + 4160;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423262,34.577137,-0.000001,1.000000;;, + 4240;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423237,34.577126,-0.000003,1.000000;;, + 4320;16;-0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423239,34.577114,-0.000001,1.000000;;, + 4400;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423233,34.577114,0.000001,1.000000;;, + 4480;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423250,34.577129,-0.000000,1.000000;;, + 4560;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423254,34.577110,-0.000006,1.000000;;, + 4640;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423250,34.577141,-0.000003,1.000000;;, + 4720;16;0.019225,0.999811,-0.002960,0.000000,-0.999808,0.019213,-0.003948,0.000000,-0.003890,0.003035,0.999988,0.000000,27.423246,34.577110,-0.000000,1.000000;;, + 4800;16;0.000000,1.000000,0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,27.423262,34.577110,0.000002,1.000000;;, + 4960;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,27.423233,34.577133,0.000000,1.000000;;; + } + { Bip01_L_Toe0 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738561,-0.000003,0.000000,1.000000;;, + 80;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,15.738552,-0.000004,0.000001,1.000000;;, + 160;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,15.738560,-0.000006,0.000001,1.000000;;, + 240;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738562,-0.000002,-0.000000,1.000000;;, + 320;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,15.738562,-0.000007,-0.000000,1.000000;;, + 400;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,15.738553,0.000008,0.000002,1.000000;;, + 480;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,15.738570,-0.000012,0.000002,1.000000;;, + 560;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,15.738561,-0.000000,0.000001,1.000000;;, + 640;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,15.738554,0.000003,0.000001,1.000000;;, + 720;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,15.738559,0.000018,-0.000001,1.000000;;, + 800;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,15.738567,-0.000023,0.000003,1.000000;;, + 880;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,15.738561,0.000015,-0.000001,1.000000;;, + 960;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738577,0.000009,0.000000,1.000000;;, + 1040;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,15.738572,0.000005,-0.000002,1.000000;;, + 1120;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,15.738572,0.000003,-0.000002,1.000000;;, + 1200;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,15.738558,0.000002,0.000000,1.000000;;, + 1280;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,15.738563,0.000006,-0.000003,1.000000;;, + 1360;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,15.738564,-0.000010,0.000000,1.000000;;, + 1440;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,15.738564,-0.000011,0.000004,1.000000;;, + 1520;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,15.738545,-0.000000,-0.000006,1.000000;;, + 1600;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,15.738548,-0.000011,-0.000001,1.000000;;, + 1680;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738566,-0.000008,0.000001,1.000000;;, + 1760;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,15.738560,0.000012,-0.000003,1.000000;;, + 1840;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738552,-0.000004,-0.000001,1.000000;;, + 1920;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738549,-0.000001,-0.000006,1.000000;;, + 2000;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738556,-0.000001,0.000003,1.000000;;, + 2080;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,15.738564,0.000012,-0.000001,1.000000;;, + 2160;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,15.738553,-0.000004,-0.000002,1.000000;;, + 2240;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,15.738557,0.000012,-0.000001,1.000000;;, + 2320;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,15.738566,-0.000005,-0.000001,1.000000;;, + 2400;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,15.738562,0.000005,0.000004,1.000000;;, + 2480;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,15.738552,0.000007,-0.000000,1.000000;;, + 2560;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738543,0.000018,-0.000003,1.000000;;, + 2640;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738567,-0.000004,0.000004,1.000000;;, + 2720;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,15.738589,-0.000015,0.000006,1.000000;;, + 2800;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738543,0.000010,-0.000005,1.000000;;, + 2880;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,15.738537,0.000003,-0.000002,1.000000;;, + 2960;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738583,0.000002,-0.000001,1.000000;;, + 3040;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738555,0.000015,-0.000003,1.000000;;, + 3120;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,15.738544,0.000016,-0.000002,1.000000;;, + 3200;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,15.738552,0.000001,-0.000004,1.000000;;, + 3280;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738568,0.000010,-0.000000,1.000000;;, + 3360;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,15.738545,0.000010,-0.000002,1.000000;;, + 3440;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738567,-0.000012,0.000003,1.000000;;, + 3520;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738564,-0.000007,0.000000,1.000000;;, + 3600;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,15.738573,-0.000008,0.000002,1.000000;;, + 3680;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738562,-0.000005,0.000002,1.000000;;, + 3760;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,15.738544,-0.000008,-0.000000,1.000000;;, + 3840;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738535,0.000001,0.000001,1.000000;;, + 3920;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738588,-0.000004,0.000001,1.000000;;, + 4000;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738590,0.000003,0.000001,1.000000;;, + 4080;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,15.738544,0.000012,-0.000002,1.000000;;, + 4160;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,15.738582,-0.000001,-0.000001,1.000000;;, + 4240;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,15.738545,-0.000004,-0.000001,1.000000;;, + 4320;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,15.738585,-0.000005,0.000001,1.000000;;, + 4400;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,15.738574,-0.000012,0.000001,1.000000;;, + 4480;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738592,-0.000014,0.000002,1.000000;;, + 4560;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,15.738579,-0.000008,0.000006,1.000000;;, + 4640;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,15.738531,-0.000003,0.000001,1.000000;;, + 4720;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738544,-0.000011,0.000005,1.000000;;, + 4800;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,15.738586,0.000005,-0.000001,1.000000;;, + 4960;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,15.738561,-0.000003,0.000000,1.000000;;; + } + { Dummy16 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;-0.950769,0.300574,-0.075459,0.000000,0.309313,0.905410,-0.290788,0.000000,-0.019082,-0.299812,-0.953807,0.000000,-27.853168,-0.096285,-31.055355,1.000000;;, + 80;16;-0.935626,0.342228,-0.086515,0.000000,0.352570,0.894002,-0.276506,0.000000,-0.017284,-0.289208,-0.957110,0.000000,-27.748009,0.301211,-31.076935,1.000000;;, + 160;16;-0.925290,0.368153,-0.091117,0.000000,0.378918,0.887164,-0.263366,0.000000,-0.016123,-0.278216,-0.960383,0.000000,-27.639570,0.709021,-31.093178,1.000000;;, + 240;16;-0.909113,0.404857,-0.098005,0.000000,0.416296,0.874843,-0.247683,0.000000,-0.014536,-0.265971,-0.963872,0.000000,-27.523199,1.158613,-31.101513,1.000000;;, + 320;16;-0.891424,0.441083,-0.103967,0.000000,0.452986,0.860751,-0.232186,0.000000,-0.012924,-0.254072,-0.967099,0.000000,-27.402622,1.597056,-31.104548,1.000000;;, + 400;16;-0.875825,0.470459,-0.107694,0.000000,0.482491,0.848173,-0.218644,0.000000,-0.011520,-0.243455,-0.969844,0.000000,-27.279839,1.992580,-31.105698,1.000000;;, + 480;16;-0.859232,0.499192,-0.111928,0.000000,0.511488,0.833964,-0.207084,0.000000,-0.010031,-0.235183,-0.971899,0.000000,-27.156675,2.313535,-31.109781,1.000000;;, + 560;16;-0.855702,0.505905,-0.108783,0.000000,0.517335,0.831586,-0.202064,0.000000,-0.011763,-0.229184,-0.973312,0.000000,-27.035406,2.529122,-31.122227,1.000000;;, + 640;16;-0.852038,0.512206,-0.108054,0.000000,0.523309,0.828144,-0.200814,0.000000,-0.013374,-0.227647,-0.973652,0.000000,-26.917717,2.605358,-31.149225,1.000000;;, + 720;16;-0.848776,0.515387,-0.118137,0.000000,0.528752,0.826851,-0.191672,0.000000,-0.001103,-0.225152,-0.974323,0.000000,-26.804501,2.486619,-31.197994,1.000000;;, + 800;16;-0.852712,0.506694,-0.127061,0.000000,0.522288,0.831574,-0.188944,0.000000,0.009923,-0.227477,-0.973733,0.000000,-26.700985,2.205780,-31.262104,1.000000;;, + 880;16;-0.859492,0.494064,-0.131048,0.000000,0.510717,0.840591,-0.180485,0.000000,0.020987,-0.222054,-0.974809,0.000000,-26.611767,1.761564,-31.336849,1.000000;;, + 960;16;-0.869096,0.476071,-0.134272,0.000000,0.493710,0.851557,-0.176354,0.000000,0.030383,-0.219560,-0.975126,0.000000,-26.539392,1.200514,-31.411163,1.000000;;, + 1040;16;-0.880700,0.453676,-0.136183,0.000000,0.472124,0.863998,-0.174947,0.000000,0.038293,-0.218371,-0.975114,0.000000,-26.489084,0.565444,-31.475983,1.000000;;, + 1120;16;-0.893894,0.426739,-0.137284,0.000000,0.445963,0.877632,-0.175723,0.000000,0.045497,-0.218302,-0.974820,0.000000,-26.454227,-0.131122,-31.528803,1.000000;;, + 1200;16;-0.908056,0.393894,-0.142415,0.000000,0.415567,0.889745,-0.188830,0.000000,0.052334,-0.230652,-0.971628,0.000000,-26.430658,-0.859936,-31.567528,1.000000;;, + 1280;16;-0.922470,0.357039,-0.146872,0.000000,0.381403,0.901761,-0.203369,0.000000,0.059832,-0.243619,-0.968024,0.000000,-26.415157,-1.627756,-31.590664,1.000000;;, + 1360;16;-0.936632,0.316821,-0.149480,0.000000,0.343409,0.914687,-0.213116,0.000000,0.069207,-0.250944,-0.965524,0.000000,-26.403652,-2.435472,-31.596870,1.000000;;, + 1440;16;-0.949930,0.273334,-0.151398,0.000000,0.302307,0.926494,-0.224097,0.000000,0.079016,-0.258645,-0.962735,0.000000,-26.396225,-3.271423,-31.582434,1.000000;;, + 1520;16;-0.962460,0.228345,-0.146729,0.000000,0.256494,0.941984,-0.216509,0.000000,0.088778,-0.246016,-0.965191,0.000000,-26.391926,-4.126998,-31.545103,1.000000;;, + 1600;16;-0.973279,0.180599,-0.141817,0.000000,0.207809,0.955496,-0.209388,0.000000,0.097690,-0.233264,-0.967494,0.000000,-26.390018,-4.993391,-31.483387,1.000000;;, + 1680;16;-0.982018,0.130495,-0.136426,0.000000,0.156468,0.966935,-0.201384,0.000000,0.105636,-0.219109,-0.969965,0.000000,-26.389751,-5.861845,-31.396585,1.000000;;, + 1760;16;-0.988295,0.078361,-0.130889,0.000000,0.102952,0.975744,-0.193194,0.000000,0.112575,-0.204408,-0.972391,0.000000,-26.390581,-6.723475,-31.284851,1.000000;;, + 1840;16;-0.991307,0.024053,-0.129348,0.000000,0.050465,0.977461,-0.204997,0.000000,0.121502,-0.209743,-0.970178,0.000000,-26.392103,-7.569542,-31.149120,1.000000;;, + 1920;16;-0.991445,-0.030234,-0.126977,0.000000,-0.002105,0.976380,-0.216048,0.000000,0.130510,-0.213933,-0.968091,0.000000,-26.393761,-8.391356,-30.991154,1.000000;;, + 2000;16;-0.989601,-0.065657,-0.127977,0.000000,-0.035271,0.973343,-0.226624,0.000000,0.139445,-0.219754,-0.965538,0.000000,-26.395369,-9.180367,-30.813459,1.000000;;, + 2080;16;-0.986798,-0.097252,-0.129503,0.000000,-0.064643,0.969690,-0.235632,0.000000,0.148494,-0.224150,-0.963175,0.000000,-26.396614,-9.928298,-30.619232,1.000000;;, + 2160;16;-0.984868,-0.112194,-0.132090,0.000000,-0.079888,0.970267,-0.228473,0.000000,0.153796,-0.214463,-0.964548,0.000000,-26.403309,-10.627003,-30.415258,1.000000;;, + 2240;16;-0.982743,-0.127398,-0.134113,0.000000,-0.095799,0.970749,-0.220155,0.000000,0.158237,-0.203508,-0.966201,0.000000,-26.397121,-11.268909,-30.196938,1.000000;;, + 2320;16;-0.978546,-0.154778,-0.135980,0.000000,-0.121814,0.966943,-0.224014,0.000000,0.166158,-0.202644,-0.965053,0.000000,-26.355202,-11.844269,-29.959543,1.000000;;, + 2400;16;-0.973358,-0.183789,-0.137096,0.000000,-0.149820,0.962418,-0.226507,0.000000,0.173573,-0.199933,-0.964313,0.000000,-26.298077,-12.350889,-29.710909,1.000000;;, + 2480;16;-0.967874,-0.207464,-0.142053,0.000000,-0.169510,0.955665,-0.240771,0.000000,0.185706,-0.208956,-0.960130,0.000000,-26.223885,-12.783846,-29.451048,1.000000;;, + 2560;16;-0.961966,-0.230255,-0.146982,0.000000,-0.188517,0.948972,-0.252811,0.000000,0.197693,-0.215486,-0.956286,0.000000,-26.175800,-13.142502,-29.199085,1.000000;;, + 2640;16;-0.958528,-0.239279,-0.154823,0.000000,-0.193917,0.945671,-0.260966,0.000000,0.208855,-0.220120,-0.952852,0.000000,-26.195387,-13.424680,-28.970636,1.000000;;, + 2720;16;-0.954978,-0.248082,-0.162707,0.000000,-0.199542,0.942941,-0.266544,0.000000,0.219548,-0.222077,-0.949990,0.000000,-26.283360,-13.630479,-28.778227,1.000000;;, + 2800;16;-0.953561,-0.246858,-0.172576,0.000000,-0.195597,0.943225,-0.268456,0.000000,0.229048,-0.222234,-0.947707,0.000000,-26.469358,-13.758628,-28.638807,1.000000;;, + 2880;16;-0.952465,-0.244663,-0.181521,0.000000,-0.191561,0.944292,-0.267614,0.000000,0.236884,-0.220121,-0.946273,0.000000,-26.708914,-13.811164,-28.548800,1.000000;;, + 2960;16;-0.951625,-0.242593,-0.188569,0.000000,-0.188648,0.945716,-0.264638,0.000000,0.242532,-0.216263,-0.945732,0.000000,-26.973581,-13.789098,-28.512592,1.000000;;, + 3040;16;-0.952264,-0.236555,-0.192962,0.000000,-0.183013,0.948285,-0.259349,0.000000,0.244333,-0.211654,-0.946311,0.000000,-27.246073,-13.695509,-28.519129,1.000000;;, + 3120;16;-0.951630,-0.238703,-0.193446,0.000000,-0.186562,0.949180,-0.253479,0.000000,0.244121,-0.205129,-0.947801,0.000000,-27.508265,-13.531747,-28.559759,1.000000;;, + 3200;16;-0.954384,-0.230068,-0.190314,0.000000,-0.180596,0.952381,-0.245673,0.000000,0.237773,-0.200096,-0.950487,0.000000,-27.734383,-13.301747,-28.632072,1.000000;;, + 3280;16;-0.945656,-0.267764,-0.184489,0.000000,-0.218163,0.943176,-0.250646,0.000000,0.241120,-0.196776,-0.950337,0.000000,-27.892500,-13.008595,-28.732557,1.000000;;, + 3360;16;-0.935553,-0.302299,-0.182634,0.000000,-0.248927,0.931215,-0.266222,0.000000,0.250550,-0.203603,-0.946452,0.000000,-27.983364,-12.653031,-28.858446,1.000000;;, + 3440;16;-0.942919,-0.265237,-0.201378,0.000000,-0.204891,0.938750,-0.277069,0.000000,0.262533,-0.219993,-0.939510,0.000000,-27.987085,-12.232808,-29.007380,1.000000;;, + 3520;16;-0.952445,-0.206811,-0.223779,0.000000,-0.138372,0.947867,-0.287057,0.000000,0.271480,-0.242442,-0.931408,0.000000,-27.932764,-11.757487,-29.171944,1.000000;;, + 3600;16;-0.958256,-0.157993,-0.238293,0.000000,-0.082825,0.951111,-0.297537,0.000000,0.273652,-0.265380,-0.924493,0.000000,-27.839216,-11.233636,-29.345602,1.000000;;, + 3680;16;-0.962652,-0.111330,-0.246793,0.000000,-0.030878,0.950742,-0.308443,0.000000,0.268975,-0.289303,-0.918671,0.000000,-27.716318,-10.670435,-29.522480,1.000000;;, + 3760;16;-0.966618,-0.071139,-0.246146,0.000000,0.011804,0.947299,-0.320135,0.000000,0.255948,-0.312354,-0.914836,0.000000,-27.576151,-10.080297,-29.696045,1.000000;;, + 3840;16;-0.970162,-0.033133,-0.240184,0.000000,0.050431,0.941378,-0.333563,0.000000,0.237155,-0.335723,-0.911618,0.000000,-27.431482,-9.461965,-29.864712,1.000000;;, + 3920;16;-0.972774,0.006360,-0.231670,0.000000,0.089438,0.932489,-0.349949,0.000000,0.213804,-0.361141,-0.907670,0.000000,-27.294771,-8.817940,-30.026068,1.000000;;, + 4000;16;-0.974295,0.045173,-0.220698,0.000000,0.125929,0.921535,-0.367307,0.000000,0.186789,-0.385658,-0.903536,0.000000,-27.178677,-8.150883,-30.178059,1.000000;;, + 4080;16;-0.974651,0.082562,-0.207939,0.000000,0.159039,0.909370,-0.384385,0.000000,0.157358,-0.407712,-0.899449,0.000000,-27.098522,-7.463268,-30.319038,1.000000;;, + 4160;16;-0.973899,0.117778,-0.194033,0.000000,0.188152,0.897050,-0.399875,0.000000,0.126961,-0.425945,-0.895797,0.000000,-27.058285,-6.758516,-30.447344,1.000000;;, + 4240;16;-0.972112,0.150360,-0.179973,0.000000,0.213336,0.885692,-0.412356,0.000000,0.097399,-0.439251,-0.893069,0.000000,-27.072193,-6.039464,-30.561668,1.000000;;, + 4320;16;-0.969962,0.178673,-0.165076,0.000000,0.233094,0.876778,-0.420627,0.000000,0.069581,-0.446471,-0.892089,0.000000,-27.125252,-5.310541,-30.660139,1.000000;;, + 4400;16;-0.968280,0.200485,-0.149129,0.000000,0.245693,0.872583,-0.422178,0.000000,0.045487,-0.445426,-0.894162,0.000000,-27.210672,-4.575768,-30.741310,1.000000;;, + 4480;16;-0.967196,0.217127,-0.131860,0.000000,0.252894,0.872030,-0.419057,0.000000,0.023998,-0.438658,-0.898334,0.000000,-27.318468,-3.839471,-30.804024,1.000000;;, + 4560;16;-0.967051,0.228251,-0.112754,0.000000,0.254538,0.875105,-0.411585,0.000000,0.004727,-0.426724,-0.904370,0.000000,-27.439497,-3.105746,-30.847593,1.000000;;, + 4640;16;-0.967164,0.236582,-0.092861,0.000000,0.253796,0.879644,-0.402262,0.000000,-0.013484,-0.412621,-0.910803,0.000000,-27.564468,-2.379188,-30.871828,1.000000;;, + 4720;16;-0.966712,0.245232,-0.073003,0.000000,0.253826,0.883169,-0.394442,0.000000,-0.032256,-0.399841,-0.916017,0.000000,-27.678188,-1.668544,-30.876764,1.000000;;, + 4800;16;-0.965965,0.253205,-0.052900,0.000000,0.253587,0.886612,-0.386799,0.000000,-0.051038,-0.387049,-0.920645,0.000000,-27.789658,-0.963900,-30.864017,1.000000;;, + 4960;16;-0.950769,0.300574,-0.075459,0.000000,0.309313,0.905410,-0.290788,0.000000,-0.019082,-0.299812,-0.953807,0.000000,-27.853168,-0.096285,-31.055355,1.000000;;; + } + { Bip01_R_Thigh } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,-0.000691,-0.000000,0.000000,0.000691,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231514,-0.000005,0.000001,1.000000;;, + 80;16;0.992696,-0.120646,-0.000000,0.000000,0.120646,0.992696,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231514,0.000002,-0.000002,1.000000;;, + 160;16;0.981416,-0.191892,-0.000000,0.000000,0.191892,0.981416,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231522,-0.000015,0.000003,1.000000;;, + 240;16;0.955509,-0.294962,-0.000000,0.000000,0.294962,0.955509,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231506,-0.000021,0.000008,1.000000;;, + 320;16;0.918810,-0.394701,-0.000000,0.000000,0.394701,0.918810,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231514,-0.000011,-0.000001,1.000000;;, + 400;16;0.881477,-0.472227,0.000000,0.000000,0.472227,0.881477,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231529,-0.000002,0.000000,1.000000;;, + 480;16;0.837618,-0.546256,-0.000000,0.000000,0.546256,0.837618,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231506,-0.000013,-0.000001,1.000000;;, + 560;16;0.859904,-0.510455,-0.000000,0.000000,0.510456,0.859904,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231506,-0.000008,0.000003,1.000000;;, + 640;16;0.880661,-0.473747,0.000000,0.000000,0.473747,0.880661,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231522,-0.000020,0.000005,1.000000;;, + 720;16;0.841689,-0.539962,0.000000,0.000000,0.539962,0.841689,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231514,-0.000014,0.000004,1.000000;;, + 800;16;0.814050,-0.580795,0.000000,0.000000,0.580795,0.814050,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231499,-0.000020,0.000008,1.000000;;, + 880;16;0.797222,-0.603687,-0.000000,0.000000,0.603687,0.797222,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231483,-0.000022,0.000007,1.000000;;, + 960;16;0.788129,-0.615510,-0.000000,0.000000,0.615510,0.788129,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231506,-0.000014,0.000006,1.000000;;, + 1040;16;0.785779,-0.618507,-0.000000,0.000000,0.618507,0.785779,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231499,-0.000006,0.000003,1.000000;;, + 1120;16;0.789502,-0.613748,-0.000000,0.000000,0.613748,0.789502,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231499,-0.000023,0.000006,1.000000;;, + 1200;16;0.794340,-0.607473,-0.000000,0.000000,0.607473,0.794340,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231499,-0.000002,-0.000001,1.000000;;, + 1280;16;0.803662,-0.595085,0.000000,0.000000,0.595085,0.803663,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231506,-0.000020,0.000005,1.000000;;, + 1360;16;0.814971,-0.579501,0.000000,0.000000,0.579501,0.814971,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231499,-0.000012,0.000003,1.000000;;, + 1440;16;0.829500,-0.558507,0.000000,0.000000,0.558507,0.829500,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231514,-0.000009,0.000001,1.000000;;, + 1520;16;0.847784,-0.530342,-0.000000,0.000000,0.530342,0.847784,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231506,0.000008,-0.000001,1.000000;;, + 1600;16;0.867527,-0.497391,-0.000000,0.000000,0.497391,0.867527,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231514,-0.000005,0.000004,1.000000;;, + 1680;16;0.887900,-0.460037,0.000000,0.000000,0.460037,0.887900,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231522,0.000010,-0.000002,1.000000;;, + 1760;16;0.908067,-0.418825,-0.000000,0.000000,0.418825,0.908067,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231506,-0.000008,0.000003,1.000000;;, + 1840;16;0.926226,-0.376969,0.000000,0.000000,0.376968,0.926226,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231491,0.000014,0.000001,1.000000;;, + 1920;16;0.942370,-0.334573,0.000000,0.000000,0.334573,0.942370,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231506,0.000007,0.000003,1.000000;;, + 2000;16;0.944301,-0.329084,0.000000,0.000000,0.329084,0.944301,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231506,-0.000000,0.000002,1.000000;;, + 2080;16;0.943450,-0.331516,-0.000000,0.000000,0.331516,0.943450,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231499,0.000019,-0.000003,1.000000;;, + 2160;16;0.931197,-0.364515,-0.000000,0.000000,0.364515,0.931197,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231499,-0.000000,0.000000,1.000000;;, + 2240;16;0.918168,-0.396191,-0.000000,0.000000,0.396191,0.918168,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231499,0.000011,-0.000004,1.000000;;, + 2320;16;0.914538,-0.404499,0.000000,0.000000,0.404499,0.914538,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231514,-0.000010,-0.000001,1.000000;;, + 2400;16;0.913027,-0.407898,-0.000000,0.000000,0.407898,0.913028,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231506,0.000013,-0.000001,1.000000;;, + 2480;16;0.908578,-0.417715,-0.000000,0.000000,0.417715,0.908578,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231491,0.000001,-0.000001,1.000000;;, + 2560;16;0.904021,-0.427488,0.000000,0.000000,0.427488,0.904021,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231491,-0.000007,0.000003,1.000000;;, + 2640;16;0.887853,-0.460127,0.000000,0.000000,0.460127,0.887853,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231522,0.000017,-0.000005,1.000000;;, + 2720;16;0.870501,-0.492167,0.000000,0.000000,0.492167,0.870501,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231499,-0.000000,0.000000,1.000000;;, + 2800;16;0.841677,-0.539981,-0.000000,0.000000,0.539981,0.841677,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231499,-0.000001,0.000001,1.000000;;, + 2880;16;0.810227,-0.586117,0.000000,0.000000,0.586117,0.810227,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231499,0.000018,-0.000004,1.000000;;, + 2960;16;0.778798,-0.627275,0.000000,0.000000,0.627275,0.778798,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231506,0.000008,-0.000006,1.000000;;, + 3040;16;0.745275,-0.666757,-0.000000,0.000000,0.666757,0.745275,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231514,-0.000001,0.000000,1.000000;;, + 3120;16;0.728440,-0.685110,0.000000,0.000000,0.685110,0.728439,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231499,-0.000004,0.000003,1.000000;;, + 3200;16;0.711169,-0.703021,0.000000,0.000000,0.703021,0.711169,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231506,-0.000007,0.000002,1.000000;;, + 3280;16;0.735082,-0.677978,-0.000000,0.000000,0.677978,0.735082,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231506,-0.000010,0.000000,1.000000;;, + 3360;16;0.747912,-0.663797,-0.000000,0.000000,0.663798,0.747912,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231514,0.000017,-0.000007,1.000000;;, + 3440;16;0.692942,-0.720993,-0.000000,0.000000,0.720993,0.692942,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231499,0.000020,-0.000003,1.000000;;, + 3520;16;0.618723,-0.785609,0.000000,0.000000,0.785609,0.618723,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231514,0.000003,-0.000002,1.000000;;, + 3600;16;0.568878,-0.822422,0.000000,0.000000,0.822422,0.568878,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231514,0.000002,-0.000004,1.000000;;, + 3680;16;0.538025,-0.842929,0.000000,0.000000,0.842929,0.538025,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231514,-0.000004,0.000002,1.000000;;, + 3760;16;0.538263,-0.842777,0.000000,0.000000,0.842777,0.538264,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231491,0.000011,-0.000005,1.000000;;, + 3840;16;0.556128,-0.831097,0.000000,0.000000,0.831097,0.556128,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231514,0.000010,-0.000007,1.000000;;, + 3920;16;0.580332,-0.814380,0.000000,0.000000,0.814380,0.580332,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231514,-0.000009,0.000003,1.000000;;, + 4000;16;0.612475,-0.790490,0.000000,0.000000,0.790490,0.612475,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231514,-0.000020,0.000009,1.000000;;, + 4080;16;0.650734,-0.759306,0.000000,0.000000,0.759306,0.650734,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231506,-0.000007,0.000001,1.000000;;, + 4160;16;0.693185,-0.720759,-0.000000,0.000000,0.720760,0.693185,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231506,0.000024,-0.000009,1.000000;;, + 4240;16;0.736246,-0.676714,0.000000,0.000000,0.676714,0.736246,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231514,0.000018,-0.000011,1.000000;;, + 4320;16;0.782863,-0.622194,-0.000000,0.000000,0.622194,0.782863,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231514,0.000011,-0.000009,1.000000;;, + 4400;16;0.834057,-0.551678,-0.000000,0.000000,0.551678,0.834057,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231499,0.000028,-0.000016,1.000000;;, + 4480;16;0.885285,-0.465049,0.000000,0.000000,0.465049,0.885285,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,119.231522,0.000006,-0.000006,1.000000;;, + 4560;16;0.933661,-0.358157,-0.000000,0.000000,0.358157,0.933661,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231491,0.000025,-0.000013,1.000000;;, + 4640;16;0.970815,-0.239830,-0.000000,0.000000,0.239830,0.970815,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,119.231476,-0.000004,0.000002,1.000000;;, + 4720;16;0.992635,-0.121142,0.000000,0.000000,0.121142,0.992635,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231483,0.000008,-0.000000,1.000000;;, + 4800;16;1.000000,-0.000691,-0.000000,0.000000,0.000691,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,119.231522,0.000021,-0.000011,1.000000;;, + 4960;16;1.000000,-0.000691,-0.000000,0.000000,0.000691,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,119.231514,-0.000005,0.000001,1.000000;;; + } + { Bip01_R_Calf } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.968778,0.242973,0.049336,0.000000,-0.242361,0.970017,-0.018119,0.000000,-0.052260,0.005597,0.998618,0.000000,119.231522,-0.000002,0.000002,1.000000;;, + 80;16;0.961616,0.269772,0.050179,0.000000,-0.268547,0.962804,-0.029856,0.000000,-0.056367,0.015235,0.998294,0.000000,119.231529,-0.000013,0.000004,1.000000;;, + 160;16;0.956946,0.285763,0.050931,0.000000,-0.284133,0.958073,-0.036938,0.000000,-0.059351,0.020876,0.998019,0.000000,119.231491,0.000001,-0.000003,1.000000;;, + 240;16;0.949554,0.309198,0.052383,0.000000,-0.306909,0.950557,-0.047416,0.000000,-0.064454,0.028947,0.997501,0.000000,119.231491,0.000013,-0.000003,1.000000;;, + 320;16;0.941553,0.332466,0.054256,0.000000,-0.329428,0.942402,-0.057929,0.000000,-0.070390,0.036669,0.996845,0.000000,119.231491,0.000004,0.000001,1.000000;;, + 400;16;0.934630,0.351170,0.056087,0.000000,-0.347449,0.935341,-0.066452,0.000000,-0.075797,0.042621,0.996212,0.000000,119.231522,-0.000004,-0.000001,1.000000;;, + 480;16;0.927307,0.369747,0.058206,0.000000,-0.365269,0.927878,-0.074976,0.000000,-0.081730,0.048265,0.995485,0.000000,119.231514,0.000006,0.000000,1.000000;;, + 560;16;0.947979,0.312243,0.061972,0.000000,-0.307242,0.948384,-0.078548,0.000000,-0.083299,0.055421,0.994982,0.000000,119.231483,0.000002,0.000000,1.000000;;, + 640;16;0.965072,0.253591,0.065789,0.000000,-0.248051,0.965269,-0.082018,0.000000,-0.084303,0.062834,0.994457,0.000000,119.231514,0.000025,-0.000004,1.000000;;, + 720;16;0.952754,0.296732,0.064877,0.000000,-0.291600,0.953349,-0.078073,0.000000,-0.085017,0.055466,0.994834,0.000000,119.231506,0.000021,-0.000005,1.000000;;, + 800;16;0.942792,0.327248,0.063655,0.000000,-0.322237,0.943467,-0.077679,0.000000,-0.085477,0.052723,0.994944,0.000000,119.231491,0.000017,-0.000006,1.000000;;, + 880;16;0.945118,0.318768,0.071687,0.000000,-0.314227,0.946918,-0.067881,0.000000,-0.089520,0.041629,0.995115,0.000000,119.231499,0.000032,-0.000006,1.000000;;, + 960;16;0.949310,0.304217,0.079135,0.000000,-0.300018,0.952000,-0.060710,0.000000,-0.093805,0.033891,0.995014,0.000000,119.231506,0.000007,-0.000003,1.000000;;, + 1040;16;0.954730,0.284711,0.086197,0.000000,-0.280703,0.958173,-0.055767,0.000000,-0.098469,0.029047,0.994716,0.000000,119.231529,0.000002,0.000001,1.000000;;, + 1120;16;0.960945,0.260642,0.093010,0.000000,-0.256682,0.965070,-0.052479,0.000000,-0.103440,0.026555,0.994281,0.000000,119.231514,0.000020,-0.000003,1.000000;;, + 1200;16;0.959528,0.266249,0.091746,0.000000,-0.261187,0.963192,-0.063574,0.000000,-0.105295,0.037039,0.993751,0.000000,119.231499,0.000007,-0.000002,1.000000;;, + 1280;16;0.959127,0.268209,0.090224,0.000000,-0.261922,0.962114,-0.075715,0.000000,-0.107113,0.048988,0.993039,0.000000,119.231506,0.000018,-0.000007,1.000000;;, + 1360;16;0.955512,0.283673,0.080786,0.000000,-0.277209,0.957255,-0.082575,0.000000,-0.100757,0.056507,0.993305,0.000000,119.231506,-0.000005,0.000000,1.000000;;, + 1440;16;0.952631,0.295732,0.070969,0.000000,-0.289172,0.953054,-0.089822,0.000000,-0.094201,0.065045,0.993426,0.000000,119.231499,-0.000014,0.000009,1.000000;;, + 1520;16;0.954221,0.292597,0.062040,0.000000,-0.287759,0.954648,-0.076430,0.000000,-0.081589,0.055078,0.995143,0.000000,119.231499,0.000002,-0.000004,1.000000;;, + 1600;16;0.956422,0.287048,0.053486,0.000000,-0.283651,0.956852,-0.063058,0.000000,-0.069279,0.045138,0.996576,0.000000,119.231491,0.000001,-0.000005,1.000000;;, + 1680;16;0.959114,0.279358,0.045371,0.000000,-0.277210,0.959592,-0.048358,0.000000,-0.057047,0.033803,0.997799,0.000000,119.231499,-0.000008,-0.000001,1.000000;;, + 1760;16;0.962123,0.269997,0.037695,0.000000,-0.268835,0.962615,-0.033178,0.000000,-0.045244,0.021788,0.998738,0.000000,119.231499,0.000015,-0.000006,1.000000;;, + 1840;16;0.962117,0.271123,0.028679,0.000000,-0.269985,0.962110,-0.038108,0.000000,-0.037925,0.028921,0.998862,0.000000,119.231491,-0.000004,-0.000002,1.000000;;, + 1920;16;0.962055,0.272157,0.019505,0.000000,-0.271184,0.961617,-0.041862,0.000000,-0.030149,0.034984,0.998933,0.000000,119.231499,-0.000008,-0.000001,1.000000;;, + 2000;16;0.954595,0.297496,0.015627,0.000000,-0.296517,0.953896,-0.046475,0.000000,-0.028733,0.039731,0.998797,0.000000,119.231491,0.000012,-0.000003,1.000000;;, + 2080;16;0.945039,0.326757,0.011431,0.000000,-0.325822,0.944092,-0.050296,0.000000,-0.027226,0.043807,0.998669,0.000000,119.231476,-0.000017,0.000006,1.000000;;, + 2160;16;0.929391,0.368812,0.014497,0.000000,-0.367984,0.928921,-0.041145,0.000000,-0.028641,0.032905,0.999048,0.000000,119.231499,-0.000003,0.000002,1.000000;;, + 2240;16;0.911959,0.409892,0.017853,0.000000,-0.409216,0.911864,-0.032326,0.000000,-0.029530,0.022175,0.999318,0.000000,119.231506,-0.000002,0.000003,1.000000;;, + 2320;16;0.897343,0.441136,0.013243,0.000000,-0.440449,0.897039,-0.036404,0.000000,-0.027938,0.026834,0.999249,0.000000,119.231506,0.000025,-0.000004,1.000000;;, + 2400;16;0.882926,0.469438,0.008413,0.000000,-0.468778,0.882405,-0.040114,0.000000,-0.026255,0.031473,0.999160,0.000000,119.231514,0.000007,-0.000002,1.000000;;, + 2480;16;0.871719,0.490003,0.001830,0.000000,-0.488862,0.869932,-0.065059,0.000000,-0.033471,0.055819,0.997880,0.000000,119.231491,0.000006,0.000001,1.000000;;, + 2560;16;0.862916,0.505338,-0.002894,0.000000,-0.503552,0.859356,-0.089117,0.000000,-0.042548,0.078358,0.996017,0.000000,119.231476,0.000015,-0.000005,1.000000;;, + 2640;16;0.851604,0.524175,0.003224,0.000000,-0.520013,0.845585,-0.120719,0.000000,-0.066004,0.101128,0.992682,0.000000,119.231514,-0.000008,-0.000003,1.000000;;, + 2720;16;0.844668,0.535099,0.014346,0.000000,-0.527177,0.836215,-0.151094,0.000000,-0.092846,0.120062,0.988415,0.000000,119.231491,0.000021,-0.000007,1.000000;;, + 2800;16;0.842347,0.537394,0.040743,0.000000,-0.522436,0.832783,-0.183122,0.000000,-0.132338,0.132967,0.982246,0.000000,119.231491,0.000019,-0.000007,1.000000;;, + 2880;16;0.847564,0.524947,0.077888,0.000000,-0.500331,0.839350,-0.212510,0.000000,-0.176932,0.141146,0.974050,0.000000,119.231491,0.000008,-0.000007,1.000000;;, + 2960;16;0.862664,0.489335,0.127914,0.000000,-0.452684,0.859806,-0.236242,0.000000,-0.225583,0.145893,0.963238,0.000000,119.231506,0.000004,0.000001,1.000000;;, + 3040;16;0.883839,0.425545,0.194266,0.000000,-0.374392,0.892473,-0.251640,0.000000,-0.280461,0.149678,0.948124,0.000000,119.231506,-0.000006,-0.000000,1.000000;;, + 3120;16;0.912598,0.319880,0.254641,0.000000,-0.255694,0.932509,-0.255046,0.000000,-0.319039,0.167644,0.932797,0.000000,119.231506,0.000024,-0.000009,1.000000;;, + 3200;16;0.928966,0.153149,0.336999,0.000000,-0.073022,0.968328,-0.238766,0.000000,-0.362892,0.197198,0.910726,0.000000,119.231483,0.000025,-0.000008,1.000000;;, + 3280;16;0.937054,0.115470,0.329539,0.000000,-0.042454,0.974414,-0.220714,0.000000,-0.346593,0.192831,0.917981,0.000000,119.231491,0.000020,-0.000004,1.000000;;, + 3360;16;0.949507,0.045192,0.310475,0.000000,0.012573,0.983296,-0.181577,0.000000,-0.313494,0.176312,0.933079,0.000000,119.231514,0.000004,-0.000000,1.000000;;, + 3440;16;0.959181,-0.032297,0.280942,0.000000,0.070203,0.989553,-0.125924,0.000000,-0.273940,0.140507,0.951428,0.000000,119.231506,-0.000007,-0.000002,1.000000;;, + 3520;16;0.963427,-0.104243,0.246864,0.000000,0.123716,0.990207,-0.064688,0.000000,-0.237704,0.092863,0.966889,0.000000,119.231506,-0.000002,-0.000002,1.000000;;, + 3600;16;0.964323,-0.151520,0.217080,0.000000,0.157682,0.987426,-0.011249,0.000000,-0.212646,0.045077,0.976089,0.000000,119.231499,0.000002,0.000002,1.000000;;, + 3680;16;0.965890,-0.170849,0.194596,0.000000,0.167334,0.985297,0.034484,0.000000,-0.197626,-0.000745,0.980277,0.000000,119.231468,0.000007,-0.000011,1.000000;;, + 3760;16;0.970914,-0.148335,0.187941,0.000000,0.138962,0.988344,0.062179,0.000000,-0.194974,-0.034254,0.980210,0.000000,119.231522,0.000009,0.000002,1.000000;;, + 3840;16;0.976399,-0.100533,0.191150,0.000000,0.087220,0.993221,0.076851,0.000000,-0.197580,-0.058365,0.978548,0.000000,119.231514,0.000010,0.000001,1.000000;;, + 3920;16;0.979355,-0.036699,0.198787,0.000000,0.020678,0.996411,0.082076,0.000000,-0.201086,-0.076271,0.976600,0.000000,119.231483,0.000022,-0.000013,1.000000;;, + 4000;16;0.977445,0.036592,0.207995,0.000000,-0.053320,0.995727,0.075395,0.000000,-0.204348,-0.084785,0.975220,0.000000,119.231491,0.000020,-0.000018,1.000000;;, + 4080;16;0.970276,0.111665,0.214698,0.000000,-0.126820,0.990222,0.058118,0.000000,-0.206109,-0.083619,0.974950,0.000000,119.231483,0.000014,-0.000012,1.000000;;, + 4160;16;0.959692,0.180561,0.215382,0.000000,-0.192249,0.980742,0.034431,0.000000,-0.205018,-0.074450,0.975923,0.000000,119.231522,-0.000024,0.000010,1.000000;;, + 4240;16;0.949330,0.234824,0.208878,0.000000,-0.242488,0.970086,0.011497,0.000000,-0.199930,-0.061565,0.977874,0.000000,119.231514,-0.000033,0.000018,1.000000;;, + 4320;16;0.942611,0.270034,0.196382,0.000000,-0.273834,0.961743,-0.008064,0.000000,-0.191047,-0.046175,0.980494,0.000000,119.231483,-0.000004,-0.000003,1.000000;;, + 4400;16;0.943918,0.276524,0.180428,0.000000,-0.277778,0.960461,-0.018793,0.000000,-0.178491,-0.032379,0.983409,0.000000,119.231506,-0.000021,0.000012,1.000000;;, + 4480;16;0.950802,0.263535,0.162863,0.000000,-0.263183,0.964444,-0.024133,0.000000,-0.163432,-0.019916,0.986354,0.000000,119.231476,-0.000019,0.000005,1.000000;;, + 4560;16;0.961555,0.233630,0.144324,0.000000,-0.232262,0.972292,-0.026493,0.000000,-0.146514,-0.008047,0.989176,0.000000,119.231476,-0.000045,0.000023,1.000000;;, + 4640;16;0.972677,0.195524,0.125179,0.000000,-0.193671,0.980697,-0.026926,0.000000,-0.128027,0.001947,0.991769,0.000000,119.231506,0.000011,-0.000006,1.000000;;, + 4720;16;0.981532,0.160253,0.104474,0.000000,-0.158198,0.987018,-0.027719,0.000000,-0.107560,0.010679,0.994141,0.000000,119.231483,0.000002,-0.000002,1.000000;;, + 4800;16;0.988831,0.124156,0.082452,0.000000,-0.122246,0.992109,-0.027835,0.000000,-0.085257,0.017445,0.996206,0.000000,119.231476,-0.000039,0.000023,1.000000;;, + 4960;16;0.968778,0.242973,0.049336,0.000000,-0.242361,0.970017,-0.018119,0.000000,-0.052260,0.005597,0.998618,0.000000,119.231522,-0.000002,0.000002,1.000000;;; + } + { Bip01_R_Foot } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423256,34.577141,-0.000001,1.000000;;, + 80;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423260,34.577141,-0.000001,1.000000;;, + 160;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423243,34.577141,-0.000002,1.000000;;, + 240;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423237,34.577122,0.000005,1.000000;;, + 320;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423248,34.577145,-0.000002,1.000000;;, + 400;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423233,34.577118,0.000006,1.000000;;, + 480;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423246,34.577118,0.000003,1.000000;;, + 560;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423237,34.577145,0.000000,1.000000;;, + 640;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423241,34.577129,0.000002,1.000000;;, + 720;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423254,34.577126,-0.000001,1.000000;;, + 800;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423248,34.577126,0.000004,1.000000;;, + 880;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423239,34.577137,-0.000002,1.000000;;, + 960;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423252,34.577133,-0.000001,1.000000;;, + 1040;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423252,34.577129,0.000002,1.000000;;, + 1120;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423243,34.577133,0.000004,1.000000;;, + 1200;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423243,34.577137,0.000003,1.000000;;, + 1280;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423254,34.577126,0.000000,1.000000;;, + 1360;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423246,34.577145,0.000000,1.000000;;, + 1440;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423246,34.577141,-0.000001,1.000000;;, + 1520;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423250,34.577145,0.000000,1.000000;;, + 1600;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423252,34.577126,0.000005,1.000000;;, + 1680;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423244,34.577145,-0.000002,1.000000;;, + 1760;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423264,34.577141,-0.000001,1.000000;;, + 1840;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423239,34.577133,0.000002,1.000000;;, + 1920;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423254,34.577148,0.000000,1.000000;;, + 2000;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423231,34.577152,-0.000002,1.000000;;, + 2080;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423248,34.577145,-0.000002,1.000000;;, + 2160;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423264,34.577126,0.000001,1.000000;;, + 2240;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423244,34.577145,0.000000,1.000000;;, + 2320;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423246,34.577126,0.000003,1.000000;;, + 2400;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423254,34.577122,0.000004,1.000000;;, + 2480;16;0.024776,0.999689,-0.002694,0.000000,-0.999680,0.024761,-0.005212,0.000000,-0.005144,0.002822,0.999983,0.000000,27.423239,34.577126,0.000006,1.000000;;, + 2560;16;0.044065,0.999017,-0.004895,0.000000,-0.998990,0.044020,-0.008951,0.000000,-0.008727,0.005284,0.999948,0.000000,27.423248,34.577118,0.000004,1.000000;;, + 2640;16;0.115791,0.993154,-0.015418,0.000000,-0.993024,0.115400,-0.024201,0.000000,-0.022256,0.018112,0.999588,0.000000,27.423241,34.577133,-0.000000,1.000000;;, + 2720;16;0.177487,0.983804,-0.025052,0.000000,-0.983603,0.176508,-0.037004,0.000000,-0.031983,0.031208,0.999001,0.000000,27.423243,34.577141,0.000001,1.000000;;, + 2800;16;0.240793,0.969825,-0.038193,0.000000,-0.969821,0.238867,-0.048881,0.000000,-0.038283,0.048810,0.998074,0.000000,27.423264,34.577126,0.000001,1.000000;;, + 2880;16;0.286167,0.956856,-0.050355,0.000000,-0.957322,0.283293,-0.057265,0.000000,-0.040530,0.064593,0.997088,0.000000,27.423264,34.577122,0.000002,1.000000;;, + 2960;16;0.286216,0.956506,-0.056368,0.000000,-0.957519,0.283368,-0.053482,0.000000,-0.035183,0.069281,0.996977,0.000000,27.423243,34.577133,0.000004,1.000000;;, + 3040;16;0.260367,0.963717,-0.058811,0.000000,-0.965111,0.258026,-0.044523,0.000000,-0.027733,0.068352,0.997276,0.000000,27.423264,34.577133,-0.000003,1.000000;;, + 3120;16;0.155009,0.987246,-0.036283,0.000000,-0.987737,0.154184,-0.024549,0.000000,-0.018642,0.039643,0.999040,0.000000,27.423260,34.577133,-0.000001,1.000000;;, + 3200;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423254,34.577126,-0.000004,1.000000;;, + 3280;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423252,34.577156,0.000000,1.000000;;, + 3360;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423235,34.577148,0.000001,1.000000;;, + 3440;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423250,34.577133,-0.000003,1.000000;;, + 3520;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423254,34.577137,-0.000004,1.000000;;, + 3600;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423254,34.577141,0.000003,1.000000;;, + 3680;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423246,34.577141,0.000001,1.000000;;, + 3760;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423243,34.577137,0.000006,1.000000;;, + 3840;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423250,34.577126,0.000009,1.000000;;, + 3920;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423264,34.577133,0.000002,1.000000;;, + 4000;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423225,34.577141,-0.000002,1.000000;;, + 4080;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423256,34.577133,-0.000001,1.000000;;, + 4160;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423248,34.577114,0.000016,1.000000;;, + 4240;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423229,34.577160,-0.000016,1.000000;;, + 4320;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423254,34.577152,-0.000008,1.000000;;, + 4400;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423243,34.577137,0.000001,1.000000;;, + 4480;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423248,34.577156,-0.000007,1.000000;;, + 4560;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423246,34.577122,0.000004,1.000000;;, + 4640;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423243,34.577122,0.000004,1.000000;;, + 4720;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423264,34.577164,-0.000009,1.000000;;, + 4800;16;0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,27.423260,34.577152,-0.000010,1.000000;;, + 4960;16;0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,27.423256,34.577141,-0.000001,1.000000;;; + } + { Bip01_R_Toe0 } + } + + Animation { + + + AnimationKey { + 4; + 62; + 0;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,15.738550,-0.000017,-0.000003,1.000000;;, + 80;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738570,0.000009,0.000001,1.000000;;, + 160;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738559,-0.000016,0.000003,1.000000;;, + 240;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,15.738566,-0.000021,-0.000003,1.000000;;, + 320;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,15.738569,-0.000017,-0.000004,1.000000;;, + 400;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,15.738562,0.000016,-0.000001,1.000000;;, + 480;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738554,-0.000006,0.000001,1.000000;;, + 560;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738573,-0.000013,-0.000002,1.000000;;, + 640;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,15.738546,0.000014,0.000001,1.000000;;, + 720;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738572,-0.000015,-0.000003,1.000000;;, + 800;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,15.738565,-0.000003,-0.000002,1.000000;;, + 880;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738555,-0.000002,-0.000002,1.000000;;, + 960;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,15.738550,0.000001,0.000002,1.000000;;, + 1040;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,15.738564,-0.000014,-0.000003,1.000000;;, + 1120;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738560,-0.000017,-0.000002,1.000000;;, + 1200;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738569,0.000010,-0.000004,1.000000;;, + 1280;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,15.738572,0.000021,-0.000003,1.000000;;, + 1360;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738555,0.000018,0.000000,1.000000;;, + 1440;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738553,0.000010,-0.000001,1.000000;;, + 1520;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738554,-0.000013,-0.000002,1.000000;;, + 1600;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,15.738569,0.000017,-0.000002,1.000000;;, + 1680;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738546,0.000001,0.000001,1.000000;;, + 1760;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,15.738545,-0.000005,0.000004,1.000000;;, + 1840;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738573,0.000006,-0.000004,1.000000;;, + 1920;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738564,0.000001,0.000000,1.000000;;, + 2000;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738553,-0.000003,-0.000000,1.000000;;, + 2080;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738568,-0.000013,-0.000007,1.000000;;, + 2160;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738563,0.000001,-0.000003,1.000000;;, + 2240;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,15.738546,-0.000010,0.000004,1.000000;;, + 2320;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738555,0.000009,0.000001,1.000000;;, + 2400;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,15.738561,-0.000011,-0.000002,1.000000;;, + 2480;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,15.738555,0.000004,-0.000001,1.000000;;, + 2560;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,15.738554,-0.000003,-0.000003,1.000000;;, + 2640;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738580,-0.000005,-0.000007,1.000000;;, + 2720;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738547,0.000002,-0.000000,1.000000;;, + 2800;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738557,0.000008,-0.000001,1.000000;;, + 2880;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,15.738566,-0.000006,-0.000001,1.000000;;, + 2960;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738572,0.000009,-0.000003,1.000000;;, + 3040;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738565,-0.000010,-0.000004,1.000000;;, + 3120;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738559,0.000005,-0.000002,1.000000;;, + 3200;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,15.738583,0.000002,-0.000004,1.000000;;, + 3280;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,15.738565,0.000011,-0.000003,1.000000;;, + 3360;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738559,-0.000004,-0.000001,1.000000;;, + 3440;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,15.738562,0.000010,-0.000000,1.000000;;, + 3520;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,15.738569,0.000010,0.000005,1.000000;;, + 3600;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,15.738554,0.000004,-0.000001,1.000000;;, + 3680;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,15.738561,-0.000015,-0.000001,1.000000;;, + 3760;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738567,-0.000010,-0.000000,1.000000;;, + 3840;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,15.738560,-0.000001,-0.000002,1.000000;;, + 3920;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,15.738556,0.000008,-0.000003,1.000000;;, + 4000;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,15.738570,0.000005,-0.000004,1.000000;;, + 4080;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,15.738561,-0.000005,-0.000003,1.000000;;, + 4160;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738545,-0.000018,0.000004,1.000000;;, + 4240;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,15.738561,0.000007,0.000004,1.000000;;, + 4320;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,15.738585,0.000006,-0.000014,1.000000;;, + 4400;16;1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738553,-0.000006,0.000002,1.000000;;, + 4480;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738564,0.000006,-0.000004,1.000000;;, + 4560;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738543,0.000010,0.000013,1.000000;;, + 4640;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738590,-0.000006,-0.000010,1.000000;;, + 4720;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,15.738582,-0.000003,-0.000011,1.000000;;, + 4800;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,15.738579,0.000004,-0.000012,1.000000;;, + 4960;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,15.738550,-0.000017,-0.000003,1.000000;;; + } + { Dummy11 } + } +} \ No newline at end of file diff --git a/Demos/DX11ClothDemo/Media/UI/DXUTShared.fx b/Demos/DX11ClothDemo/Media/UI/DXUTShared.fx new file mode 100644 index 0000000..0da2c6b --- /dev/null +++ b/Demos/DX11ClothDemo/Media/UI/DXUTShared.fx @@ -0,0 +1,69 @@ +//-------------------------------------------------------------------------------------- +// File: DXUTShared.fx +// +// +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------------------- +// Global variables +//-------------------------------------------------------------------------------------- +float4 g_MaterialDiffuseColor; // Material's diffuse color +float3 g_LightDir; // Light's direction in world space +float4x4 g_mWorld; // World matrix for object +float4x4 g_mWorldViewProjection; // World * View * Projection matrix + + + +//-------------------------------------------------------------------------------------- +// Vertex shader output structure +//-------------------------------------------------------------------------------------- +struct VS_OUTPUT +{ + float4 Position : POSITION; // vertex position + float4 Diffuse : COLOR0; // vertex diffuse color +}; + + +//-------------------------------------------------------------------------------------- +// This shader computes standard transform and lighting +//-------------------------------------------------------------------------------------- +VS_OUTPUT RenderWith1LightNoTextureVS( float4 vPos : POSITION, + float3 vNormal : NORMAL ) +{ + VS_OUTPUT Output; + + // Transform the position from object space to homogeneous projection space + Output.Position = mul(vPos, g_mWorldViewProjection); + + // Transform the normal from object space to world space + float3 vNormalWorldSpace; + vNormalWorldSpace = normalize(mul(vNormal, (float3x3)g_mWorld)); // normal (world space) + + // Compute simple directional lighting equation + Output.Diffuse.rgb = g_MaterialDiffuseColor * max(0,dot(vNormalWorldSpace, g_LightDir)); + Output.Diffuse.a = 1.0f; + + return Output; +} + + +//-------------------------------------------------------------------------------------- +float4 RenderWith1LightNoTexturePS( float4 Diffuse : COLOR0 ) : COLOR0 +{ + return Diffuse; +} + + +//-------------------------------------------------------------------------------------- +technique RenderWith1LightNoTexture +{ + pass P0 + { + VertexShader = compile vs_1_1 RenderWith1LightNoTextureVS(); + PixelShader = compile ps_1_1 RenderWith1LightNoTexturePS(); + } +} + diff --git a/Demos/DX11ClothDemo/Media/UI/Font.dds b/Demos/DX11ClothDemo/Media/UI/Font.dds new file mode 100644 index 0000000000000000000000000000000000000000..37514f5bf7fdb81efc52766d02bdaec0fecd3061 GIT binary patch literal 76128 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 B8 + WORD nMaxSkinWeightsPerVertex; + WORD nMaxSkinWeightsPerFace; + WORD nBones; +} + +template VertexDuplicationIndices { + + DWORD nIndices; + DWORD nOriginalVertices; + array DWORD indices[nIndices]; +} + +template SkinWeights { + <6f0d123b-bad2-4167-a0d0-80224f25fabb> + STRING transformNodeName; + DWORD nWeights; + array DWORD vertexIndices[nWeights]; + array FLOAT weights[nWeights]; + Matrix4x4 matrixOffset; +} + + +Frame Scene_Root { + + + FrameTransformMatrix { + 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000;; + } + + Frame Arrow { + + + FrameTransformMatrix { + 0.004058,0.000000,0.000000,0.000000,0.000000,0.000000,0.004058,0.000000,0.000000,-0.004058,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000;; + } + + Frame Cylinder01 { + + + FrameTransformMatrix { + 1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000002,116.363640,0.000002,1.000000;; + } + + Frame { + + + FrameTransformMatrix { + 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,-0.000000,0.000000,0.000003,1.000000;; + } + + Mesh { + 58; + 0.000000;0.000000;0.000000;, + 24.461134;0.000000;0.000000;, + 22.038719;-10.613288;0.000000;, + 15.251267;-19.124485;0.000000;, + 5.443114;-23.847843;0.000000;, + -5.443115;-23.847841;0.000000;, + -15.251268;-19.124485;0.000000;, + -22.038721;-10.613288;0.000000;, + -24.461134;0.000001;0.000000;, + -22.038719;10.613289;0.000000;, + -15.251266;19.124485;0.000000;, + -5.443113;23.847843;0.000000;, + 5.443115;23.847841;0.000000;, + 15.251268;19.124483;0.000000;, + 22.038721;10.613287;0.000000;, + 24.461134;0.000000;-140.000000;, + 22.038719;-10.613288;-140.000000;, + 15.251267;-19.124485;-140.000000;, + 5.443114;-23.847843;-140.000000;, + -5.443115;-23.847841;-140.000000;, + -15.251268;-19.124485;-140.000000;, + -22.038721;-10.613288;-140.000000;, + -24.461134;0.000001;-140.000000;, + -22.038719;10.613289;-140.000000;, + -15.251266;19.124485;-140.000000;, + -5.443113;23.847843;-140.000000;, + 5.443115;23.847841;-140.000000;, + 15.251268;19.124483;-140.000000;, + 22.038721;10.613287;-140.000000;, + 0.000000;0.000000;-140.000000;, + 24.461134;0.000000;0.000000;, + 22.038719;-10.613288;0.000000;, + 15.251267;-19.124485;0.000000;, + 5.443114;-23.847843;0.000000;, + -5.443115;-23.847841;0.000000;, + -15.251268;-19.124485;0.000000;, + -22.038721;-10.613288;0.000000;, + -24.461134;0.000001;0.000000;, + -22.038719;10.613289;0.000000;, + -15.251266;19.124485;0.000000;, + -5.443113;23.847843;0.000000;, + 5.443115;23.847841;0.000000;, + 15.251268;19.124483;0.000000;, + 22.038721;10.613287;0.000000;, + 24.461134;0.000000;-140.000000;, + 22.038719;-10.613288;-140.000000;, + 15.251267;-19.124485;-140.000000;, + 5.443114;-23.847843;-140.000000;, + -5.443115;-23.847841;-140.000000;, + -15.251268;-19.124485;-140.000000;, + -22.038721;-10.613288;-140.000000;, + -24.461134;0.000001;-140.000000;, + -22.038719;10.613289;-140.000000;, + -15.251266;19.124485;-140.000000;, + -5.443113;23.847843;-140.000000;, + 5.443115;23.847841;-140.000000;, + 15.251268;19.124483;-140.000000;, + 22.038721;10.613287;-140.000000;; + 56; + 3;0,2,1;, + 3;0,3,2;, + 3;0,4,3;, + 3;0,5,4;, + 3;0,6,5;, + 3;0,7,6;, + 3;0,8,7;, + 3;0,9,8;, + 3;0,10,9;, + 3;0,11,10;, + 3;0,12,11;, + 3;0,13,12;, + 3;0,14,13;, + 3;0,1,14;, + 3;30,16,15;, + 3;30,31,16;, + 3;31,17,16;, + 3;31,32,17;, + 3;32,18,17;, + 3;32,33,18;, + 3;33,19,18;, + 3;33,34,19;, + 3;34,20,19;, + 3;34,35,20;, + 3;35,21,20;, + 3;35,36,21;, + 3;36,22,21;, + 3;36,37,22;, + 3;37,23,22;, + 3;37,38,23;, + 3;38,24,23;, + 3;38,39,24;, + 3;39,25,24;, + 3;39,40,25;, + 3;40,26,25;, + 3;40,41,26;, + 3;41,27,26;, + 3;41,42,27;, + 3;42,28,27;, + 3;42,43,28;, + 3;43,15,28;, + 3;43,30,15;, + 3;29,44,45;, + 3;29,45,46;, + 3;29,46,47;, + 3;29,47,48;, + 3;29,48,49;, + 3;29,49,50;, + 3;29,50,51;, + 3;29,51,52;, + 3;29,52,53;, + 3;29,53,54;, + 3;29,54,55;, + 3;29,55,56;, + 3;29,56,57;, + 3;29,57,44;; + + MeshNormals { + 58; + 0.000000;0.000000;1.000000;, + 0.000000;0.000000;1.000000;, + 0.000000;0.000000;1.000000;, + 0.000000;0.000000;1.000000;, + 0.000000;0.000000;1.000000;, + 0.000000;0.000000;1.000000;, + 0.000000;0.000000;1.000000;, + 0.000000;0.000000;1.000000;, + 0.000000;0.000000;1.000000;, + 0.000000;0.000000;1.000000;, + 0.000000;0.000000;1.000000;, + 0.000000;0.000000;1.000000;, + 0.000000;0.000000;1.000000;, + 0.000000;0.000000;1.000000;, + 0.000000;0.000000;1.000000;, + 0.997118;0.075862;0.000000;, + 0.931288;-0.364284;0.000000;, + 0.681004;-0.732279;0.000000;, + 0.295840;-0.955238;0.000000;, + -0.147920;-0.988999;0.000000;, + -0.562382;-0.826878;0.000000;, + -0.865457;-0.500983;0.000000;, + -0.997118;-0.075862;0.000000;, + -0.931288;0.364284;0.000000;, + -0.681004;0.732279;0.000000;, + -0.295840;0.955238;0.000000;, + 0.147920;0.988999;0.000000;, + 0.562382;0.826878;0.000000;, + 0.865457;0.500983;0.000000;, + 0.000000;0.000000;-1.000000;, + 0.997118;-0.075862;0.000000;, + 0.865457;-0.500983;0.000000;, + 0.562382;-0.826878;0.000000;, + 0.147920;-0.988999;0.000000;, + -0.295840;-0.955238;0.000000;, + -0.681004;-0.732279;0.000000;, + -0.931288;-0.364284;0.000000;, + -0.997118;0.075862;0.000000;, + -0.865457;0.500983;0.000000;, + -0.562382;0.826878;0.000000;, + -0.147920;0.988999;0.000000;, + 0.295840;0.955238;0.000000;, + 0.681004;0.732279;0.000000;, + 0.931288;0.364284;0.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;; + 56; + 3;0,2,1;, + 3;0,3,2;, + 3;0,4,3;, + 3;0,5,4;, + 3;0,6,5;, + 3;0,7,6;, + 3;0,8,7;, + 3;0,9,8;, + 3;0,10,9;, + 3;0,11,10;, + 3;0,12,11;, + 3;0,13,12;, + 3;0,14,13;, + 3;0,1,14;, + 3;30,16,15;, + 3;30,31,16;, + 3;31,17,16;, + 3;31,32,17;, + 3;32,18,17;, + 3;32,33,18;, + 3;33,19,18;, + 3;33,34,19;, + 3;34,20,19;, + 3;34,35,20;, + 3;35,21,20;, + 3;35,36,21;, + 3;36,22,21;, + 3;36,37,22;, + 3;37,23,22;, + 3;37,38,23;, + 3;38,24,23;, + 3;38,39,24;, + 3;39,25,24;, + 3;39,40,25;, + 3;40,26,25;, + 3;40,41,26;, + 3;41,27,26;, + 3;41,42,27;, + 3;42,28,27;, + 3;42,43,28;, + 3;43,15,28;, + 3;43,30,15;, + 3;29,44,45;, + 3;29,45,46;, + 3;29,46,47;, + 3;29,47,48;, + 3;29,48,49;, + 3;29,49,50;, + 3;29,50,51;, + 3;29,51,52;, + 3;29,52,53;, + 3;29,53,54;, + 3;29,54,55;, + 3;29,55,56;, + 3;29,56,57;, + 3;29,57,44;; + } + + VertexDuplicationIndices { + 58; + 30; + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28; + } + + MeshMaterialList { + 1; + 56; + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0; + + Material { + 1.000000;1.000000;1.000000;1.000000;; + 0.000000; + 1.000000;1.000000;1.000000;; + 0.000000;0.000000;0.000000;; + } + } + } + } + } + + Frame Cone01 { + + + FrameTransformMatrix { + 1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,116.363640,0.000000,1.000000;; + } + + Frame { + + + FrameTransformMatrix { + 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000003,1.000000;; + } + + Mesh { + 98; + 0.000000;0.000000;0.000000;, + 58.922840;0.000000;0.000000;, + 56.915092;15.250354;0.000000;, + 51.028675;29.461420;0.000000;, + 41.664738;41.664742;0.000000;, + 29.461418;51.028679;0.000000;, + 15.250351;56.915092;0.000000;, + -0.000003;58.922840;0.000000;, + -15.250356;56.915092;0.000000;, + -29.461424;51.028675;0.000000;, + -41.664742;41.664738;0.000000;, + -51.028679;29.461416;0.000000;, + -56.915092;15.250349;0.000000;, + -58.922840;-0.000005;0.000000;, + -56.915092;-15.250359;0.000000;, + -51.028675;-29.461426;0.000000;, + -41.664734;-41.664745;0.000000;, + -29.461414;-51.028679;0.000000;, + -15.250346;-56.915096;0.000000;, + 0.000008;-58.922840;0.000000;, + 15.250361;-56.915092;0.000000;, + 29.461428;-51.028671;0.000000;, + 41.664745;-41.664734;0.000000;, + 51.028683;-29.461412;0.000000;, + 56.915096;-15.250343;0.000000;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 58.922840;0.000000;0.000000;, + 56.915092;15.250354;0.000000;, + 51.028675;29.461420;0.000000;, + 41.664738;41.664742;0.000000;, + 29.461418;51.028679;0.000000;, + 15.250351;56.915092;0.000000;, + -0.000003;58.922840;0.000000;, + -15.250356;56.915092;0.000000;, + -29.461424;51.028675;0.000000;, + -41.664742;41.664738;0.000000;, + -51.028679;29.461416;0.000000;, + -56.915092;15.250349;0.000000;, + -58.922840;-0.000005;0.000000;, + -56.915092;-15.250359;0.000000;, + -51.028675;-29.461426;0.000000;, + -41.664734;-41.664745;0.000000;, + -29.461414;-51.028679;0.000000;, + -15.250346;-56.915096;0.000000;, + 0.000008;-58.922840;0.000000;, + 15.250361;-56.915092;0.000000;, + 29.461428;-51.028671;0.000000;, + 41.664745;-41.664734;0.000000;, + 51.028683;-29.461412;0.000000;, + 56.915096;-15.250343;0.000000;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;, + 0.000000;0.000000;116.363632;; + 96; + 3;0,2,1;, + 3;0,3,2;, + 3;0,4,3;, + 3;0,5,4;, + 3;0,6,5;, + 3;0,7,6;, + 3;0,8,7;, + 3;0,9,8;, + 3;0,10,9;, + 3;0,11,10;, + 3;0,12,11;, + 3;0,13,12;, + 3;0,14,13;, + 3;0,15,14;, + 3;0,16,15;, + 3;0,17,16;, + 3;0,18,17;, + 3;0,19,18;, + 3;0,20,19;, + 3;0,21,20;, + 3;0,22,21;, + 3;0,23,22;, + 3;0,24,23;, + 3;0,1,24;, + 3;50,26,25;, + 3;50,51,26;, + 3;51,27,26;, + 3;51,52,27;, + 3;52,28,27;, + 3;52,53,28;, + 3;53,29,28;, + 3;53,54,29;, + 3;54,30,29;, + 3;54,55,30;, + 3;55,31,30;, + 3;55,56,31;, + 3;56,32,31;, + 3;56,57,32;, + 3;57,33,32;, + 3;57,58,33;, + 3;58,34,33;, + 3;58,59,34;, + 3;59,35,34;, + 3;59,60,35;, + 3;60,36,35;, + 3;60,61,36;, + 3;61,37,36;, + 3;61,62,37;, + 3;62,38,37;, + 3;62,63,38;, + 3;63,39,38;, + 3;63,64,39;, + 3;64,40,39;, + 3;64,65,40;, + 3;65,41,40;, + 3;65,66,41;, + 3;66,42,41;, + 3;66,67,42;, + 3;67,43,42;, + 3;67,68,43;, + 3;68,44,43;, + 3;68,69,44;, + 3;69,45,44;, + 3;69,70,45;, + 3;70,46,45;, + 3;70,71,46;, + 3;71,47,46;, + 3;71,72,47;, + 3;72,48,47;, + 3;72,73,48;, + 3;73,25,48;, + 3;73,50,25;, + 3;49,74,75;, + 3;49,75,76;, + 3;49,76,77;, + 3;49,77,78;, + 3;49,78,79;, + 3;49,79,80;, + 3;49,80,81;, + 3;49,81,82;, + 3;49,82,83;, + 3;49,83,84;, + 3;49,84,85;, + 3;49,85,86;, + 3;49,86,87;, + 3;49,87,88;, + 3;49,88,89;, + 3;49,89,90;, + 3;49,90,91;, + 3;49,91,92;, + 3;49,92,93;, + 3;49,93,94;, + 3;49,94,95;, + 3;49,95,96;, + 3;49,96,97;, + 3;49,97,74;; + + MeshNormals { + 98; + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.000000;0.000000;-1.000000;, + 0.886052;-0.116651;0.448669;, + 0.886052;0.116651;0.448669;, + 0.825669;0.342004;0.448669;, + 0.709018;0.544049;0.448669;, + 0.544049;0.709018;0.448669;, + 0.342003;0.825669;0.448669;, + 0.116651;0.886052;0.448669;, + -0.116651;0.886052;0.448669;, + -0.342003;0.825669;0.448669;, + -0.544049;0.709018;0.448669;, + -0.709018;0.544049;0.448669;, + -0.825669;0.342003;0.448669;, + -0.886052;0.116651;0.448669;, + -0.886052;-0.116651;0.448669;, + -0.825669;-0.342003;0.448669;, + -0.709018;-0.544049;0.448669;, + -0.544049;-0.709018;0.448669;, + -0.342003;-0.825669;0.448669;, + -0.116651;-0.886052;0.448669;, + 0.116651;-0.886052;0.448669;, + 0.342004;-0.825669;0.448669;, + 0.544049;-0.709018;0.448669;, + 0.709018;-0.544049;0.448669;, + 0.825669;-0.342003;0.448669;, + 1.000000;0.000000;0.000000;, + 0.892143;0.000000;0.451753;, + 0.861744;0.230904;0.451753;, + 0.772619;0.446072;0.451753;, + 0.630840;0.630840;0.451753;, + 0.446072;0.772619;0.451753;, + 0.230904;0.861744;0.451753;, + 0.000000;0.892143;0.451753;, + -0.230904;0.861744;0.451753;, + -0.446072;0.772619;0.451753;, + -0.630840;0.630840;0.451753;, + -0.772619;0.446071;0.451753;, + -0.861744;0.230904;0.451753;, + -0.892143;-0.000000;0.451753;, + -0.861744;-0.230904;0.451753;, + -0.772619;-0.446072;0.451753;, + -0.630840;-0.630841;0.451753;, + -0.446072;-0.772619;0.451753;, + -0.230904;-0.861744;0.451753;, + 0.000000;-0.892143;0.451753;, + 0.230904;-0.861744;0.451753;, + 0.446072;-0.772619;0.451753;, + 0.630840;-0.630840;0.451753;, + 0.772619;-0.446071;0.451753;, + 0.861744;-0.230903;0.451753;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;, + 1.000000;0.000000;0.000000;; + 96; + 3;0,2,1;, + 3;0,3,2;, + 3;0,4,3;, + 3;0,5,4;, + 3;0,6,5;, + 3;0,7,6;, + 3;0,8,7;, + 3;0,9,8;, + 3;0,10,9;, + 3;0,11,10;, + 3;0,12,11;, + 3;0,13,12;, + 3;0,14,13;, + 3;0,15,14;, + 3;0,16,15;, + 3;0,17,16;, + 3;0,18,17;, + 3;0,19,18;, + 3;0,20,19;, + 3;0,21,20;, + 3;0,22,21;, + 3;0,23,22;, + 3;0,24,23;, + 3;0,1,24;, + 3;50,26,25;, + 3;50,51,26;, + 3;51,27,26;, + 3;51,52,27;, + 3;52,28,27;, + 3;52,53,28;, + 3;53,29,28;, + 3;53,54,29;, + 3;54,30,29;, + 3;54,55,30;, + 3;55,31,30;, + 3;55,56,31;, + 3;56,32,31;, + 3;56,57,32;, + 3;57,33,32;, + 3;57,58,33;, + 3;58,34,33;, + 3;58,59,34;, + 3;59,35,34;, + 3;59,60,35;, + 3;60,36,35;, + 3;60,61,36;, + 3;61,37,36;, + 3;61,62,37;, + 3;62,38,37;, + 3;62,63,38;, + 3;63,39,38;, + 3;63,64,39;, + 3;64,40,39;, + 3;64,65,40;, + 3;65,41,40;, + 3;65,66,41;, + 3;66,42,41;, + 3;66,67,42;, + 3;67,43,42;, + 3;67,68,43;, + 3;68,44,43;, + 3;68,69,44;, + 3;69,45,44;, + 3;69,70,45;, + 3;70,46,45;, + 3;70,71,46;, + 3;71,47,46;, + 3;71,72,47;, + 3;72,48,47;, + 3;72,73,48;, + 3;73,25,48;, + 3;73,50,25;, + 3;49,74,75;, + 3;49,75,76;, + 3;49,76,77;, + 3;49,77,78;, + 3;49,78,79;, + 3;49,79,80;, + 3;49,80,81;, + 3;49,81,82;, + 3;49,82,83;, + 3;49,83,84;, + 3;49,84,85;, + 3;49,85,86;, + 3;49,86,87;, + 3;49,87,88;, + 3;49,88,89;, + 3;49,89,90;, + 3;49,90,91;, + 3;49,91,92;, + 3;49,92,93;, + 3;49,93,94;, + 3;49,94,95;, + 3;49,95,96;, + 3;49,96,97;, + 3;49,97,74;; + } + + VertexDuplicationIndices { + 98; + 50; + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48; + } + + MeshMaterialList { + 1; + 96; + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0; + + Material { + 1.000000;1.000000;1.000000;1.000000;; + 0.000000; + 1.000000;1.000000;1.000000;; + 0.000000;0.000000;0.000000;; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Demos/DX11ClothDemo/Media/UI/dxutcontrols.dds b/Demos/DX11ClothDemo/Media/UI/dxutcontrols.dds new file mode 100644 index 0000000000000000000000000000000000000000..b5f52e10af505a56f0f4850202e7c5da27c571dc GIT binary patch literal 262272 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ⅇ-=EcR-gA#H-s|5f?(5pYwb#e_ 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 literal 0 HcmV?d00001 diff --git a/Demos/DX11ClothDemo/amdFlag.bmp b/Demos/DX11ClothDemo/amdFlag.bmp new file mode 100644 index 0000000000000000000000000000000000000000..dd1d394ec7ef603cd68b9956780c5430106dc9f8 GIT binary patch literal 1396038 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 CQsM#t literal 0 HcmV?d00001 diff --git a/Demos/DX11ClothDemo/atiFlag.bmp b/Demos/DX11ClothDemo/atiFlag.bmp new file mode 100644 index 0000000000000000000000000000000000000000..2be4847dd830b84f51b3a3fdd07f6e0d98a5315c GIT binary patch literal 1396038 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 +#include +#include +#include +#include + +#ifndef SAFE_RELEASE +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } +#endif + +namespace BTAcceleratedSoftBody +{ + + /** + * Class to provide basic DX11 support to an application, wrapping the device creation functionality and necessary pointers. + */ + class DX11SupportHelper + { + private: + + ID3D11Device* m_pd3dDevice; + ID3D11DeviceContext* m_pd3dImmediateContext; + typedef HRESULT (WINAPI * LPD3D11CREATEDEVICE)( IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT32, D3D_FEATURE_LEVEL*, UINT, UINT32, ID3D11Device**, D3D_FEATURE_LEVEL*, ID3D11DeviceContext** ); + HMODULE m_s_hModD3D11; + LPD3D11CREATEDEVICE m_s_DynamicD3D11CreateDevice; + + + bool Dynamic_EnsureD3D11APIs( void ) + { + // If both modules are non-NULL, this function has already been called. Note + // that this doesn't guarantee that all ProcAddresses were found. + if( m_s_hModD3D11 != NULL ) + return true; + + // This may fail if Direct3D 11 isn't installed + m_s_hModD3D11 = LoadLibraryA( "d3d11.dll" ); + if( m_s_hModD3D11 != NULL ) + { + m_s_DynamicD3D11CreateDevice = ( LPD3D11CREATEDEVICE )GetProcAddress( m_s_hModD3D11, "D3D11CreateDevice" ); + } + + return ( m_s_hModD3D11 != NULL ); + } + + // Helper to call D3D11CreateDevice from d3d11.dll + HRESULT WINAPI Dynamic_D3D11CreateDevice( IDXGIAdapter* pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT32 Flags, + D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + UINT32 SDKVersion, + ID3D11Device** ppDevice, + D3D_FEATURE_LEVEL* pFeatureLevel, + ID3D11DeviceContext** ppImmediateContext ) + { + if( Dynamic_EnsureD3D11APIs() && m_s_DynamicD3D11CreateDevice != NULL ) + { + return m_s_DynamicD3D11CreateDevice( + pAdapter, + DriverType, + Software, + Flags, + pFeatureLevels, + FeatureLevels, + SDKVersion, + ppDevice, + pFeatureLevel, + ppImmediateContext ); + } + else + { + MessageBoxA( 0, "Could not locate resources need by d3d11."\ + " Please install the latest DirectX SDK.", "Error", MB_ICONEXCLAMATION ); + return E_FAIL; + } + } + + public: + DX11SupportHelper() + { + m_s_hModD3D11 = 0; + m_s_DynamicD3D11CreateDevice = 0; + m_pd3dDevice = 0; + m_pd3dImmediateContext = 0; + } + + virtual ~DX11SupportHelper() + { + SAFE_RELEASE( m_pd3dDevice ); + SAFE_RELEASE( m_pd3dImmediateContext ); + } + + ID3D11Device* getDevice() + { + return m_pd3dDevice; + } + + ID3D11DeviceContext* getContext() + { + return m_pd3dImmediateContext; + } + + /** + * Do a simplistic initialisation of the first DirectCompute device in the system. + * Clearly the user can do their own version for more flexibility. + */ + bool InitComputeShaderDevice() + { + HRESULT hr = S_OK; + + UINT createDeviceFlags = 0; + #ifdef _DEBUG + createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; + #endif + + D3D_FEATURE_LEVEL fl[] = { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0 + }; + + // Create a hardware Direct3D 11 device + hr = Dynamic_D3D11CreateDevice( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, + fl, _countof(fl), D3D11_SDK_VERSION, &m_pd3dDevice, NULL, &m_pd3dImmediateContext ); + + // Check if the hardware device supports Compute Shader 4.0 + D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS hwopts; + m_pd3dDevice->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts)); + if( !hwopts.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x ) { + SAFE_RELEASE( m_pd3dImmediateContext ); + SAFE_RELEASE( m_pd3dDevice ); + + int result = MessageBoxA(0, "This program needs to use the Direct3D 11 reference device. This device implements the entire Direct3D 11 feature set, but runs very slowly. Do you wish to continue?", "Compute Shader Sort", MB_ICONINFORMATION | MB_YESNO); + if( result == IDNO ) + return false;//E_FAIL; + + // Create a reference device if hardware is not available + hr = Dynamic_D3D11CreateDevice( NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, createDeviceFlags, + fl, _countof(fl), D3D11_SDK_VERSION, &m_pd3dDevice, NULL, &m_pd3dImmediateContext ); + if( FAILED( hr ) ) + return (hr==S_OK); + + printf("Using Direct3D 11 Reference Device\n"); + } + + bool returnVal = (hr==S_OK); + + + return returnVal; + + } // InitComputeShaderDevice + + }; // DX11SupportHelper + +} // namespace BTAcceleratedSoftBody + + +#endif // #ifndef BT_DIRECT_COMPUTE_SUPPORT_HPP \ No newline at end of file diff --git a/Demos/DX11ClothDemo/cap.h b/Demos/DX11ClothDemo/cap.h new file mode 100644 index 0000000..c4a90b2 --- /dev/null +++ b/Demos/DX11ClothDemo/cap.h @@ -0,0 +1,298 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2010 Advanced Micro Devices + +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 CAP_H +#define CAP_H + +class cap +{ + public: + + ID3D11Buffer* g_pIndexBuffer; + ID3D11Buffer* pVB[1]; + UINT Strides[1]; + UINT Offsets[1]; + + double x_offset, y_offset, z_offset; + + int width,height; + bool top; + + ID3D11Texture2D *texture2D; + ID3D11ShaderResourceView *texture2D_view; + btCollisionShape *collisionShape; + btCollisionObject *collisionObject; + + void set_collision_object(btCollisionObject* co) + { + collisionObject = co; + } + + void set_collision_shape(btCollisionShape* cs) + { + collisionShape = cs; + } + + void create_texture(void) + { + D3DX11_IMAGE_LOAD_INFO loadInfo; + ZeroMemory(&loadInfo, sizeof(D3DX11_IMAGE_LOAD_INFO) ); + loadInfo.BindFlags = D3D11_BIND_SHADER_RESOURCE; + loadInfo.Format = DXGI_FORMAT_BC1_UNORM; + + HRESULT hr = D3DX11CreateShaderResourceViewFromFile(g_pd3dDevice, L"texture.bmp", &loadInfo, NULL, &texture2D_view, NULL); + hr = hr; + } + + void destroy() + { + SAFE_RELEASE( g_pIndexBuffer ); + SAFE_RELEASE( pVB[0] ); + SAFE_RELEASE( texture2D ); + SAFE_RELEASE( texture2D_view ); + } + + void draw(void) + { + + + if (!collisionObject) + return; + + + ID3D11DeviceContext* pd3dImmediateContext = DXUTGetD3D11DeviceContext(); + + D3DXMATRIX mWorldViewProjection; + D3DXVECTOR3 vLightDir; + D3DXMATRIX mWorld; + D3DXMATRIX mView; + D3DXMATRIX mProj; + + // Get the projection & view matrix from the camera class + mProj = *g_Camera.GetProjMatrix(); + mView = *g_Camera.GetViewMatrix(); + + // Get the light direction + vLightDir = g_LightControl.GetLightDirection(); + + // Per frame cb update + D3D11_MAPPED_SUBRESOURCE MappedResource; + + HRESULT hr; + + V( pd3dImmediateContext->Map( g_pcbPSPerFrame, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) ); + CB_PS_PER_FRAME* pPerFrame = ( CB_PS_PER_FRAME* )MappedResource.pData; + float fAmbient = 0.1f; + pPerFrame->m_vLightDirAmbient = D3DXVECTOR4( vLightDir.x, vLightDir.y, vLightDir.z, fAmbient ); + pd3dImmediateContext->Unmap( g_pcbPSPerFrame, 0 ); + + pd3dImmediateContext->PSSetConstantBuffers( g_iCBPSPerFrameBind, 1, &g_pcbPSPerFrame ); + + + ///////////////////////////////////////Modify below////////////////////////////////////////////////////// + + //Get the mesh + //IA setup + pd3dImmediateContext->IASetInputLayout( g_pVertexLayout11 ); + + //This is where we pass the vertex buffer to DX + pd3dImmediateContext->IASetVertexBuffers( 0, 1, pVB, Strides, Offsets ); + + //This is where we pass the index buffer to DX + pd3dImmediateContext->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 ); + + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + // Set the shaders + pd3dImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 ); + pd3dImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 ); + pd3dImmediateContext->GSSetShader( g_pGeometryShader, NULL, 0); + + // Set the per object constant data + + + + + btTransform trans = collisionObject->getWorldTransform(); + + + + btVector3 origin = trans.getOrigin(); + btMatrix3x3 btM = trans.getBasis(); + + btScalar* scalar_matrix = new btScalar[16];; + trans.getOpenGLMatrix(scalar_matrix); + + D3DXMATRIXA16 m_trans(scalar_matrix[0],scalar_matrix[1],scalar_matrix[2],scalar_matrix[3], + scalar_matrix[4],scalar_matrix[5],scalar_matrix[6],scalar_matrix[7], + scalar_matrix[8],scalar_matrix[9],scalar_matrix[10],scalar_matrix[11], + scalar_matrix[12],scalar_matrix[13],scalar_matrix[14],scalar_matrix[15]); + + D3DXMATRIXA16 m_scale; + float sc = 10; + D3DXMatrixScaling(&m_scale,sc,sc,sc); + + + D3DXVECTOR3 vCenter( global_shift_x, global_shift_y, global_shift_z); + + D3DXMatrixTranslation( &g_mCenterMesh, -vCenter.x+x_offset, -vCenter.y+y_offset, -vCenter.z+z_offset ); + + + D3DXMATRIXA16 m_trans_transpose; + D3DXMatrixTranspose(&m_trans_transpose,&m_trans); + + mWorld = *g_Camera.GetWorldMatrix() ; + mProj = *g_Camera.GetProjMatrix(); + mView = m_trans * *g_Camera.GetViewMatrix(); + + mWorldViewProjection = mView * mProj; + + + // VS Per object + V( pd3dImmediateContext->Map( g_pcbVSPerObject, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) ); + CB_VS_PER_OBJECT* pVSPerObject = ( CB_VS_PER_OBJECT* )MappedResource.pData; + D3DXMatrixTranspose( &pVSPerObject->m_WorldViewProj, &mWorldViewProjection ); + D3DXMatrixTranspose( &pVSPerObject->m_World, &mWorld ); + pd3dImmediateContext->Unmap( g_pcbVSPerObject, 0 ); + + pd3dImmediateContext->VSSetConstantBuffers( g_iCBVSPerObjectBind, 1, &g_pcbVSPerObject ); + + // PS Per object + V( pd3dImmediateContext->Map( g_pcbPSPerObject, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) ); + CB_PS_PER_OBJECT* pPSPerObject = ( CB_PS_PER_OBJECT* )MappedResource.pData; + pPSPerObject->m_vObjectColor = D3DXVECTOR4( 1, 1, 1, 1 ); + pd3dImmediateContext->Unmap( g_pcbPSPerObject, 0 ); + + pd3dImmediateContext->PSSetConstantBuffers( g_iCBPSPerObjectBind, 1, &g_pcbPSPerObject ); + + //Render + SDKMESH_SUBSET* pSubset = NULL; + D3D11_PRIMITIVE_TOPOLOGY PrimType; + + pd3dImmediateContext->PSSetSamplers( 0, 1, &g_pSamLinear ); + + { + // Get the subset + pSubset = g_Mesh11.GetSubset( 0, 0 ); + + pd3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + pd3dImmediateContext->PSSetShaderResources(0,1,&texture2D_view); + + pd3dImmediateContext->DrawIndexed( (width*3*2+2 + height*width*3*2), 0, ( UINT )pSubset->VertexStart ); + } + + SAFE_RELEASE(pd3dImmediateContext); + } + + + void create_buffers(int width_, int height_, bool top_) + { + + top = top_; + width = width_; + height = height_; + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.Usage = D3D11_USAGE_DEFAULT; + bufferDesc.ByteWidth = sizeof(vertex_struct)*width*height; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.CPUAccessFlags = 0; + bufferDesc.MiscFlags = 0; + + + vertex_struct *vertices = new vertex_struct[width*height]; + + btCapsuleShape* cs = static_cast(collisionShape); + if (cs) + { + float radius = cs->getRadius(); + float halfHeight = cs->getHalfHeight(); + + + if (top) + { + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + float X = (x/((float)(width-1)))*3.14159; + float Y = (y/((float)(height-1)))*3.14159; + float z_coord = radius*cos(X)*sin(Y); + float y_coord = radius*sin(X)*sin(Y) + halfHeight; + float x_coord = radius*cos(Y); + vertices[y*width+x].Pos = D3DXVECTOR3(x_coord, y_coord, z_coord); + vertices[y*width+x].Normal = D3DXVECTOR3(x_coord,y_coord-halfHeight,z_coord); + vertices[y*width+x].Texcoord = D3DXVECTOR2(x/( (float)(width-1)), y/((float)(height-1))); + } + } + } else { + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + float X = (x/((float)(width-1)))*3.14159; + float Y = (y/((float)(height-1)))*3.14159; + float z_coord = radius*cos(X)*sin(Y); + float y_coord = -radius*sin(X)*sin(Y) - halfHeight; + float x_coord = radius*cos(Y); + vertices[y*width+x].Pos = D3DXVECTOR3(x_coord, y_coord, z_coord); + vertices[y*width+x].Normal = D3DXVECTOR3(x_coord,y_coord+halfHeight,z_coord); + vertices[y*width+x].Texcoord = D3DXVECTOR2(x/( (float)(width-1)), y/((float)(height-1))); + } + } + } + + D3D11_SUBRESOURCE_DATA InitData; + InitData.pSysMem = vertices; + InitData.SysMemPitch = 0; + InitData.SysMemSlicePitch = 0; + + HRESULT hr = g_pd3dDevice->CreateBuffer(&bufferDesc, &InitData, &pVB[0]); + + + + //What is this vertex stride thing all about? + Strides[0] = ( UINT )g_Mesh11.GetVertexStride( 0, 0 ); + Offsets[0] = 0; + + unsigned int* indices = new unsigned int[width*3*2+2 + height*width*3*2]; + + for(int y = 0; y < height-1; y++) + { + for(int x = 0; x < width-1; x++) + { + indices[x*3*2 + y*width*3*2] = x + y*width; + indices[x*3*2+1 + y*width*3*2] = x+1 + y*width; + indices[x*3*2+2 + y*width*3*2] = x+width + y*width; + + indices[x*3*2 + 3 + y*width*3*2] = x + 1 + y*width; + indices[x*3*2 + 4 + y*width*3*2] = x+(width+1) + y*width; + indices[x*3*2 + 5 + y*width*3*2] = x+width + y*width; + + } + } + + bufferDesc.ByteWidth = sizeof(unsigned int)*(width*3*2+2 + height*width*3*2); + bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + + InitData.pSysMem = indices; + + hr = g_pd3dDevice->CreateBuffer(&bufferDesc, &InitData, &g_pIndexBuffer); + hr = hr; + } + } +}; + +#endif CAP_H diff --git a/Demos/DX11ClothDemo/capsule.h b/Demos/DX11ClothDemo/capsule.h new file mode 100644 index 0000000..32482dc --- /dev/null +++ b/Demos/DX11ClothDemo/capsule.h @@ -0,0 +1,67 @@ +#include "cap.h" +#include "cylinder.h" + + +class capsule +{ + public: + + cap topCap; + cap bottomCap; + cylinder coreCylinder; + + double x_offset, y_offset, z_offset; + + int width; + int height; + bool top; + + btCollisionShape *collisionShape; + btCollisionObject *collisionObject; + + void set_collision_object(btCollisionObject* co) + { + collisionObject = co; + topCap.set_collision_object( co ); + bottomCap.set_collision_object( co ); + coreCylinder.set_collision_object( co ); + } + + void set_collision_shape(btCollisionShape* cs) + { + collisionShape = cs; + topCap.set_collision_shape( cs ); + bottomCap.set_collision_shape( cs ); + coreCylinder.set_collision_shape( cs ); + } + + void create_texture(void) + { + topCap.create_texture(); + bottomCap.create_texture(); + coreCylinder.create_texture(); + } + + void destroy() + { + topCap.destroy(); + bottomCap.destroy(); + coreCylinder.destroy(); + } + + void draw(void) + { + topCap.draw(); + bottomCap.draw(); + coreCylinder.draw(); + } + + + // paddingFactor is the amount of padding to allow the capsule collider around the + void create_buffers(int width_, int height_) + { + topCap.create_buffers(width_, height_, true); + bottomCap.create_buffers(width_, height_, false); + coreCylinder.create_buffers(width_, height_); + } +}; diff --git a/Demos/DX11ClothDemo/cloth.h b/Demos/DX11ClothDemo/cloth.h new file mode 100644 index 0000000..47781d7 --- /dev/null +++ b/Demos/DX11ClothDemo/cloth.h @@ -0,0 +1,312 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2010 Advanced Micro Devices + +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 CLOTH_H +#define CLOTH_H + +#include +#include +#include + +class piece_of_cloth +{ +public: + + + void destroy(void) + { + + if(created) + { + SAFE_RELEASE(g_pIndexBuffer); + SAFE_RELEASE(pVB[0]); + SAFE_RELEASE(g_pVB_UAV); + SAFE_RELEASE(pVB_staging); + SAFE_RELEASE(texture2D_view); + if(m_vertexBufferDescriptor) delete [] m_vertexBufferDescriptor; + if(cpu_buffer) delete [] cpu_buffer; + } + } + + piece_of_cloth() + { + created = false; + m_vertexBufferDescriptor = NULL; + cpu_buffer = NULL; + } + bool created; + + ID3D11Buffer* g_pIndexBuffer; + ID3D11Buffer* pVB[1]; + ID3D11Buffer* pVB_staging; + + float* cpu_buffer; + + ID3D11UnorderedAccessView* g_pVB_UAV; + UINT Strides[1]; + UINT Offsets[1]; + + double x_offset, y_offset, z_offset; + + + ID3D11ShaderResourceView *texture2D_view; + + int width; + int height; + + btVertexBufferDescriptor *m_vertexBufferDescriptor; + + void create_texture(std::wstring filename) + { + D3DX11_IMAGE_LOAD_INFO loadInfo; + ZeroMemory(&loadInfo, sizeof(D3DX11_IMAGE_LOAD_INFO) ); + loadInfo.BindFlags = D3D11_BIND_SHADER_RESOURCE; + loadInfo.Format = DXGI_FORMAT_BC1_UNORM; + + HRESULT hr = D3DX11CreateShaderResourceViewFromFile(g_pd3dDevice, filename.c_str(), &loadInfo, NULL, &texture2D_view, NULL); + hr = hr; + + } + + + void draw(void) + { + + ID3D11DeviceContext* pd3dImmediateContext = DXUTGetD3D11DeviceContext(); + + D3DXMATRIX mWorldViewProjection; + D3DXVECTOR3 vLightDir; + D3DXMATRIX mWorld; + D3DXMATRIX mView; + D3DXMATRIX mProj; + + // Get the projection & view matrix from the camera class + mProj = *g_Camera.GetProjMatrix(); + mView = *g_Camera.GetViewMatrix(); + + // Get the light direction + vLightDir = g_LightControl.GetLightDirection(); + + // Per frame cb update + D3D11_MAPPED_SUBRESOURCE MappedResource; + + HRESULT hr; +#ifndef USE_GPU_COPY + pd3dImmediateContext->Map( pVB_staging, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, cpu_buffer, 4*width*height*8 ); + pd3dImmediateContext->Unmap(pVB_staging, 0 ); + pd3dImmediateContext->CopyResource(pVB[0], pVB_staging); +#endif // #ifndef USE_GPU_COPY + + V( pd3dImmediateContext->Map( g_pcbPSPerFrame, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) ); + CB_PS_PER_FRAME* pPerFrame = ( CB_PS_PER_FRAME* )MappedResource.pData; + float fAmbient = 0.1f; + pPerFrame->m_vLightDirAmbient = D3DXVECTOR4( vLightDir.x, vLightDir.y, vLightDir.z, fAmbient ); + pd3dImmediateContext->Unmap( g_pcbPSPerFrame, 0 ); + + pd3dImmediateContext->PSSetConstantBuffers( g_iCBPSPerFrameBind, 1, &g_pcbPSPerFrame ); + + + ///////////////////////////////////////Modify below////////////////////////////////////////////////////// + + //Get the mesh + //IA setup + pd3dImmediateContext->IASetInputLayout( g_pVertexLayout11 ); + + //This is where we pass the vertex buffer to DX + pd3dImmediateContext->IASetVertexBuffers( 0, 1, pVB, Strides, Offsets ); + + //This is where we pass the index buffer to DX + pd3dImmediateContext->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 ); + + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + // Set the shaders + pd3dImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 ); + pd3dImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 ); + pd3dImmediateContext->GSSetShader( g_pGeometryShader, NULL, 0); + + // Set the per object constant data + + D3DXMATRIXA16 m_scale; + float sc = 10; + D3DXMatrixScaling(&m_scale,sc,sc,sc); + + + D3DXVECTOR3 vCenter( global_shift_x, global_shift_y, global_shift_z); + + D3DXMatrixTranslation( &g_mCenterMesh, -vCenter.x+x_offset, -vCenter.y+y_offset, -vCenter.z+z_offset ); + + + mWorld = *g_Camera.GetWorldMatrix(); + mProj = *g_Camera.GetProjMatrix(); + mView = *g_Camera.GetViewMatrix(); + + mWorldViewProjection = mView * mProj; + + + // VS Per object + V( pd3dImmediateContext->Map( g_pcbVSPerObject, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) ); + CB_VS_PER_OBJECT* pVSPerObject = ( CB_VS_PER_OBJECT* )MappedResource.pData; + D3DXMatrixTranspose( &pVSPerObject->m_WorldViewProj, &mWorldViewProjection ); + D3DXMatrixTranspose( &pVSPerObject->m_World, &mWorld ); + pd3dImmediateContext->Unmap( g_pcbVSPerObject, 0 ); + + pd3dImmediateContext->VSSetConstantBuffers( g_iCBVSPerObjectBind, 1, &g_pcbVSPerObject ); + + // PS Per object + V( pd3dImmediateContext->Map( g_pcbPSPerObject, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) ); + CB_PS_PER_OBJECT* pPSPerObject = ( CB_PS_PER_OBJECT* )MappedResource.pData; + pPSPerObject->m_vObjectColor = D3DXVECTOR4( 1, 1, 1, 1 ); + pd3dImmediateContext->Unmap( g_pcbPSPerObject, 0 ); + + pd3dImmediateContext->PSSetConstantBuffers( g_iCBPSPerObjectBind, 1, &g_pcbPSPerObject ); + + //Render + SDKMESH_SUBSET* pSubset = NULL; + D3D11_PRIMITIVE_TOPOLOGY PrimType; + + if( g_wireFrame ) + pd3dImmediateContext->RSSetState(g_pRasterizerStateWF); + else + pd3dImmediateContext->RSSetState(g_pRasterizerState); + + pd3dImmediateContext->PSSetSamplers( 0, 1, &g_pSamLinear ); + + { + // Get the subset + pSubset = g_Mesh11.GetSubset( 0, 0 ); + + pd3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + pd3dImmediateContext->PSSetShaderResources(0,1,&texture2D_view); + + //pd3dImmediateContext->DrawIndexed( (width*3*2+2 + height*width*3*2), 0, ( UINT )pSubset->VertexStart ); + pd3dImmediateContext->DrawIndexed( ((height-1)*(width-1)*3*2), 0, ( UINT )pSubset->VertexStart ); + } + + SAFE_RELEASE(pd3dImmediateContext); + } + + void create_buffers(int width_, int height_) + { + width = width_; + height = height_; + + created = true; + + + cpu_buffer = new float[width*height*8]; + memset(cpu_buffer,0,width*height*8*4); + + // Set texture coordinates in output buffers + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + cpu_buffer[y*8*width + x*8 + 6] = x/( (float)(width-1)); + cpu_buffer[y*8*width + x*8 + 7] = 1-y/((float)(height-1)); + } + } + + + + D3D11_BUFFER_DESC bufferDesc; + ZeroMemory(&bufferDesc, sizeof(bufferDesc)); + bufferDesc.Usage = D3D11_USAGE_DEFAULT; + bufferDesc.ByteWidth = sizeof(vertex_struct)*width*height; + bufferDesc.StructureByteStride = 0;//sizeof(vertex_struct); + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_UNORDERED_ACCESS; + bufferDesc.MiscFlags = 0;//D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + bufferDesc.CPUAccessFlags = 0; + + vertex_struct *vertices = new vertex_struct[width*height]; + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + double coord = sin(x/5.0)*50; + //coord = sin(y/); + + vertices[y*width+x].Pos = D3DXVECTOR3( (x/((float)(width-1)))*1000, coord, (y/((float)(height-1)))*1000); + vertices[y*width+x].Normal = D3DXVECTOR3(1,0,0); + vertices[y*width+x].Texcoord = D3DXVECTOR2(x/( (float)(width-1)), 1.f-y/((float)(height-1))); + } + } + + D3D11_SUBRESOURCE_DATA InitData; + InitData.pSysMem = vertices; + InitData.SysMemPitch = 0; + InitData.SysMemSlicePitch = 0; + + HRESULT hr = g_pd3dDevice->CreateBuffer(&bufferDesc, &InitData, &pVB[0]); + + + D3D11_UNORDERED_ACCESS_VIEW_DESC uavbuffer_desc; + ZeroMemory(&uavbuffer_desc, sizeof(uavbuffer_desc)); + uavbuffer_desc.Format = DXGI_FORMAT_R32_FLOAT; + uavbuffer_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + + uavbuffer_desc.Buffer.NumElements = width*height*sizeof(vertex_struct)/4; + hr = g_pd3dDevice->CreateUnorderedAccessView(pVB[0], &uavbuffer_desc, &g_pVB_UAV); + + + //What is this vertex stride thing all about? + Strides[0] = ( UINT )g_Mesh11.GetVertexStride( 0, 0 ); + Offsets[0] = 0; + + + //unsigned int indices[] = {0,1,2, 1,3,2}; + unsigned int* indices = new unsigned int[(height-1)*(width-1)*3*2]; + + for(int y = 0; y < height-1; y++) + { + for(int x = 0; x < width-1; x++) + { + // *3 indices/triangle, *2 triangles/quad + int baseIndex = (x + y*(width-1))*3*2; + indices[baseIndex] = x + y*width; + indices[baseIndex+1] = x+1 + y*width; + indices[baseIndex+2] = x+width + y*width; + + + indices[baseIndex+3] = x + 1 + y*width; + indices[baseIndex+4] = x+(width+1) + y*width; + indices[baseIndex+5] = x+width + y*width; + } + } + + + bufferDesc.ByteWidth = sizeof(unsigned int)*((height-1)*(width-1)*3*2); + bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + + InitData.pSysMem = indices; + + hr = g_pd3dDevice->CreateBuffer(&bufferDesc, &InitData, &g_pIndexBuffer); + + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + bufferDesc.ByteWidth = sizeof(vertex_struct)*width*height; + + hr = g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &pVB_staging); + + delete [] indices; + delete [] vertices; + } + +}; +#endif //CLOTH_H + + diff --git a/Demos/DX11ClothDemo/cloth_renderer.cpp b/Demos/DX11ClothDemo/cloth_renderer.cpp new file mode 100644 index 0000000..afd9db2 --- /dev/null +++ b/Demos/DX11ClothDemo/cloth_renderer.cpp @@ -0,0 +1,1356 @@ +//-------------------------------------------------------------------------------------- +// File: BasicHLSL10.cpp +// +// This sample shows a simple example of the Microsoft Direct3D's High-Level +// Shader Language (HLSL) using the Effect interface. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +#include "DXUT.h" +#include "DXUTcamera.h" +#include "DXUTgui.h" +#include "DXUTsettingsDlg.h" +#include "SDKmisc.h" +#include "SDKMesh.h" +#include "resource.h" + +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btHashMap.h" +#include "btDirectComputeSupport.h" +#include "BulletSoftBody/btSoftRigidDynamicsWorld.h" +#include "BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h" +#include "BulletSoftBody/btSoftBodyHelpers.h" +#include "vectormath/vmInclude.h" + +class btDefaultSoftBodySolver; +class btCPUSoftBodySolver; +class btCPUSoftBodyVertexSolver; +class btDX11SoftBodySolver; +class btDX11SIMDAwareSoftBodySolver; + +#include "BulletSoftBody/btSoftBodySolvers.h" +#include "BulletSoftBody/btDefaultSoftBodySolver.h" + +#include "BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h" +#include "BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h" + +#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h" + +#define USE_SIMDAWARE_SOLVER +//#define USE_GPU_SOLVER +#define USE_GPU_COPY +const int numFlags = 5; +const int clothWidth = 40; +const int clothHeight = 60; +float _windAngle = 1.0;//0.4; +float _windStrength = 15; + + +//#define TABLETEST + + +#include + +#include + +using Vectormath::Aos::Vector3; + + +class piece_of_cloth; +class btBroadphaseInterface; +class btCollisionShape; +class btOverlappingPairCache; +class btCollisionDispatcher; +class btConstraintSolver; +struct btCollisionAlgorithmCreateFunc; +class btDefaultCollisionConfiguration; + +int paused = 0; + +float global_shift_x = 0; +float global_shift_y = 0; +float global_shift_z = 0; + +namespace BTAcceleratedSoftBody +{ + class BulletPhysicsDevice; + class CPUDevice; + class DX11Device; +} +namespace Vectormath +{ + namespace Aos + { + class Transform3; + } +} + + + +const float flagSpacing = 30.f; + +#include +using namespace std; + +//-------------------------------------------------------------------------------------- +// Global variables +//-------------------------------------------------------------------------------------- +CDXUTDialogResourceManager g_DialogResourceManager; // manager for shared resources of dialogs +//CModelViewerCamera g_Camera; // A model viewing camera +CFirstPersonCamera g_Camera; // A model viewing camera +CDXUTDirectionWidget g_LightControl; +CD3DSettingsDlg g_D3DSettingsDlg; // Device settings dialog +CDXUTDialog g_HUD; // manages the 3D +CDXUTDialog g_SampleUI; // dialog for sample specific controls +D3DXMATRIXA16 g_mCenterMesh; +float g_fLightScale; +int g_nNumActiveLights; +int g_nActiveLight; +bool g_bShowHelp = false; // If true, it renders the UI control text + +// Direct3D9 resources +CDXUTTextHelper* g_pTxtHelper = NULL; + +CDXUTSDKMesh g_Mesh11; + +ID3D11InputLayout* g_pVertexLayout11 = NULL; +ID3D11Buffer* g_pVertexBuffer = NULL; +//ID3D11Buffer* g_pIndexBuffer = NULL; +ID3D11VertexShader* g_pVertexShader = NULL; +ID3D11GeometryShader* g_pGeometryShader = NULL; +ID3D11PixelShader* g_pPixelShader = NULL; +ID3D11SamplerState* g_pSamLinear = NULL; + +ID3D11RasterizerState *g_pRasterizerState = NULL; +ID3D11RasterizerState *g_pRasterizerStateWF = NULL; + +bool g_wireFrame = false; + +struct CB_VS_PER_OBJECT +{ + D3DXMATRIX m_WorldViewProj; + D3DXMATRIX m_World; +}; +UINT g_iCBVSPerObjectBind = 0; + +struct CB_PS_PER_OBJECT +{ + D3DXVECTOR4 m_vObjectColor; +}; +UINT g_iCBPSPerObjectBind = 0; + +struct CB_PS_PER_FRAME +{ + D3DXVECTOR4 m_vLightDirAmbient; +}; +UINT g_iCBPSPerFrameBind = 1; + +ID3D11Buffer* g_pcbVSPerObject = NULL; +ID3D11Buffer* g_pcbPSPerObject = NULL; +ID3D11Buffer* g_pcbPSPerFrame = NULL; + +ID3D11Device* g_pd3dDevice; + + + + +// Create our vertex input layout +const D3D11_INPUT_ELEMENT_DESC layout[] = +{ + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }, +}; + +struct vertex_struct +{ + D3DXVECTOR3 Pos; + D3DXVECTOR3 Normal; + D3DXVECTOR2 Texcoord; +}; + + + + + +#include "capsule.h" +#include "cap.h" +#include "cylinder.h" +#include "cloth.h" + + + +//cylinder cyl_1; +//cap cap_1; +btRigidBody *capCollider; +capsule my_capsule; + + +btAlignedObjectArray cloths; + +////////////////////////////////////////// +// Bullet globals + +btAlignedObjectArray m_collisionShapes; +btBroadphaseInterface* m_broadphase; +btCollisionDispatcher* m_dispatcher; +btConstraintSolver* m_solver; +btDefaultCollisionConfiguration* m_collisionConfiguration; +BTAcceleratedSoftBody::DX11SupportHelper m_dxSupport; + +btAlignedObjectArray m_flags; +btSoftRigidDynamicsWorld* m_dynamicsWorld; + +btDefaultSoftBodySolver *g_defaultSolver = NULL; +btCPUSoftBodySolver *g_cpuSolver = NULL; +btDX11SoftBodySolver *g_dx11Solver = NULL; +btDX11SIMDAwareSoftBodySolver *g_dx11SIMDSolver = NULL; + +btSoftBodySolverOutput *g_softBodyOutput = NULL; + +btSoftBodySolver *g_solver = NULL; + +// End bullet globals +////////////////////////////////////////// + +// Helper to test and add links correctly. +// Records links that have already been generated +static bool testAndAddLink( btAlignedObjectArray &trianglesForLinks, btSoftBody *softBody, int triangle, int *triangleVertexIndexArray, int numVertices, int vertex0, int vertex1, int nonLinkVertex, btSoftBody::Material *structuralMaterial, bool createBendLinks, btSoftBody::Material *bendMaterial ) +{ + if( trianglesForLinks[ numVertices * vertex0 + vertex1 ] >= 0 && createBendLinks) + { + // Already have link so find other triangle and generate cross link + + int otherTriangle = trianglesForLinks[numVertices * vertex0 + vertex1]; + int otherIndices[3] = {triangleVertexIndexArray[otherTriangle * 3], triangleVertexIndexArray[otherTriangle * 3 + 1], triangleVertexIndexArray[otherTriangle * 3 + 2]}; + + int nodeA; + // Test all links of the other triangle against this link. The one that's not part of it is what we want. + if( otherIndices[0] != vertex0 && otherIndices[0] != vertex1 ) + nodeA = otherIndices[0]; + if( otherIndices[1] != vertex0 && otherIndices[1] != vertex1 ) + nodeA = otherIndices[1]; + if( otherIndices[2] != vertex0 && otherIndices[2] != vertex1 ) + nodeA = otherIndices[2]; + + softBody->appendLink( nodeA, nonLinkVertex, bendMaterial ); + + return true; + } else { + // Don't yet have link so create it + softBody->appendLink( vertex0, vertex1, structuralMaterial ); + + // If we added a new link, set the triangle array + trianglesForLinks[numVertices * vertex0 + vertex1] = triangle; + trianglesForLinks[numVertices * vertex1 + vertex0] = triangle; + return true; + } +} + +btSoftBody *createFromIndexedMesh( btVector3 *vertexArray, int numVertices, int *triangleVertexIndexArray, int numTriangles, bool createBendLinks ) +{ + btSoftBody* softBody = new btSoftBody(&(m_dynamicsWorld->getWorldInfo()), numVertices, vertexArray, 0); + btSoftBody::Material * structuralMaterial = softBody->appendMaterial(); + btSoftBody::Material * bendMaterial; + if( createBendLinks ) + { + bendMaterial = softBody->appendMaterial(); + bendMaterial->m_kLST = 0.7; + } else { + bendMaterial = NULL; + } + structuralMaterial->m_kLST = 1.0; + + + // List of values for each link saying which triangle is associated with that link + // -1 to start. Once a value is entered we know the "other" triangle + // and can add a link across the link + btAlignedObjectArray triangleForLinks; + triangleForLinks.resize( numVertices * numVertices, -1 ); + for( int triangle = 0; triangle < numTriangles; ++triangle ) + { + int index[3] = {triangleVertexIndexArray[triangle * 3], triangleVertexIndexArray[triangle * 3 + 1], triangleVertexIndexArray[triangle * 3 + 2]}; + softBody->appendFace( index[0], index[1], index[2] ); + + // Generate the structural links directly from the triangles + testAndAddLink( triangleForLinks, softBody, triangle, triangleVertexIndexArray, numVertices, index[0], index[1], index[2], structuralMaterial, createBendLinks, bendMaterial ); + testAndAddLink( triangleForLinks, softBody, triangle, triangleVertexIndexArray, numVertices, index[1], index[2], index[0], structuralMaterial, createBendLinks, bendMaterial ); + testAndAddLink( triangleForLinks, softBody, triangle, triangleVertexIndexArray, numVertices, index[2], index[0], index[1], structuralMaterial, createBendLinks, bendMaterial); + } + + return softBody; +} + +/** + * Create a sequence of flag objects and add them to the world. + */ +void createFlag( int width, int height, btAlignedObjectArray &flags ) +{ + // First create a triangle mesh to represent a flag + + using namespace BTAcceleratedSoftBody; + using Vectormath::Aos::Matrix3; + using Vectormath::Aos::Vector3; + + // Allocate a simple mesh consisting of a vertex array and a triangle index array + btIndexedMesh mesh; + mesh.m_numVertices = width*height; + mesh.m_numTriangles = 2*(width-1)*(height-1); + + btVector3 *vertexArray = new btVector3[mesh.m_numVertices]; + + mesh.m_vertexBase = reinterpret_cast(vertexArray); + int *triangleVertexIndexArray = new int[3*mesh.m_numTriangles]; + mesh.m_triangleIndexBase = reinterpret_cast(triangleVertexIndexArray); + mesh.m_triangleIndexStride = sizeof(int)*3; + mesh.m_vertexStride = sizeof(Vector3); + + // Generate normalised object space vertex coordinates for a rectangular flag + float zCoordinate = 0.0f; + + Matrix3 defaultScale(Vector3(5.f, 0.f, 0.f), Vector3(0.f, 20.f, 0.f), Vector3(0.f, 0.f, 1.f)); + for( int y = 0; y < height; ++y ) + { + float yCoordinate = y*2.0f/float(height) - 1.0f; + for( int x = 0; x < width; ++x ) + { + float xCoordinate = x*2.0f/float(width) - 1.0f; + + Vector3 vertex(xCoordinate, yCoordinate, zCoordinate); + Vector3 transformedVertex = defaultScale*vertex; + + vertexArray[y*width + x] = btVector3(transformedVertex.getX(), transformedVertex.getY(), transformedVertex.getZ() ); + + } + } + + // Generate vertex indices for triangles + for( int y = 0; y < (height-1); ++y ) + { + for( int x = 0; x < (width-1); ++x ) + { + // Triangle 0 + // Top left of square on mesh + { + int vertex0 = y*width + x; + int vertex1 = vertex0 + 1; + int vertex2 = vertex0 + width; + int triangleIndex = 2*y*(width-1) + 2*x; + triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex)/sizeof(int)] = vertex0; + triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex+1)/sizeof(int)+1] = vertex1; + triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex+2)/sizeof(int)+2] = vertex2; + } + + // Triangle 1 + // Bottom right of square on mesh + { + int vertex0 = y*width + x + 1; + int vertex1 = vertex0 + width; + int vertex2 = vertex1 - 1; + int triangleIndex = 2*y*(width-1) + 2*x + 1; + triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex)/sizeof(int)] = vertex0; + triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex)/sizeof(int)+1] = vertex1; + triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex)/sizeof(int)+2] = vertex2; + } + } + } + + + float rotateAngleRoundZ = 0.5; + float rotateAngleRoundX = 0.5; + btMatrix3x3 defaultRotate; + defaultRotate[0] = btVector3(cos(rotateAngleRoundZ), sin(rotateAngleRoundZ), 0.f); + defaultRotate[1] = btVector3(-sin(rotateAngleRoundZ), cos(rotateAngleRoundZ), 0.f); + defaultRotate[2] = btVector3(0.f, 0.f, 1.f); + + + //btMatrix3x3 defaultRotateAndScale( (defaultRotateX*defaultRotate) ); +#ifdef TABLETEST + btMatrix3x3 defaultRotateX; + rotateAngleRoundX = 3.141592654/2; + defaultRotateX[0] = btVector3(1.f, 0.f, 0.f); + defaultRotateX[1] = btVector3( 0.f, cos(rotateAngleRoundX), sin(rotateAngleRoundX)); + defaultRotateX[2] = btVector3(0.f, -sin(rotateAngleRoundX), cos(rotateAngleRoundX)); + btMatrix3x3 defaultRotateAndScale( (defaultRotateX) ); +#else + btMatrix3x3 defaultRotateX; + defaultRotateX[0] = btVector3(1.f, 0.f, 0.f); + defaultRotateX[1] = btVector3( 0.f, cos(rotateAngleRoundX), sin(rotateAngleRoundX)); + defaultRotateX[2] = btVector3(0.f, -sin(rotateAngleRoundX), cos(rotateAngleRoundX)); + btMatrix3x3 defaultRotateAndScale( (defaultRotateX) ); +#endif + + + // Construct the sequence flags applying a slightly different translation to each one to arrange them + // appropriately in the scene. + for( int i = 0; i < numFlags; ++i ) + { + float zTranslate = flagSpacing * (i-numFlags/2); + + btVector3 defaultTranslate(0.f, 20.f, zTranslate); + + btTransform transform( defaultRotateAndScale, defaultTranslate ); + + + btSoftBody *softBody = createFromIndexedMesh( vertexArray, mesh.m_numVertices, triangleVertexIndexArray, mesh.m_numTriangles, true ); + + + for( int i = 0; i < mesh.m_numVertices; ++i ) + { + softBody->setMass(i, 10.f/mesh.m_numVertices); + } + +#ifndef TABLETEST + // Set the fixed points + softBody->setMass((height-1)*(width), 0.f); + softBody->setMass((height-1)*(width) + width - 1, 0.f); + softBody->setMass((height-1)*width + width/2, 0.f); +#endif + + softBody->m_cfg.collisions = btSoftBody::fCollision::CL_SS+btSoftBody::fCollision::CL_RS; + softBody->m_cfg.kLF = 0.0005f; + softBody->m_cfg.kVCF = 0.001f; + softBody->m_cfg.kDP = 0.f; + softBody->m_cfg.kDG = 0.f; + + flags.push_back( softBody ); + + softBody->transform( transform ); + softBody->setFriction( 0.8f ); + m_dynamicsWorld->addSoftBody( softBody ); + } + + delete [] vertexArray; + delete [] triangleVertexIndexArray; +} + + + + + +void updatePhysicsWorld() +{ + static int counter = 0; + + // Change wind velocity a bit based on a frame counter + if( (counter % 400) == 0 ) + { + _windAngle = (_windAngle + 0.05f); + if( _windAngle > (2*3.141) ) + _windAngle = 0; + + for( int flagIndex = 0; flagIndex < m_flags.size(); ++flagIndex ) + { + btSoftBody *cloth = 0; + + cloth = m_flags[flagIndex]; + + float localWind = _windAngle + 0.5*(((float(rand())/RAND_MAX))-0.1); + float xCoordinate = cos(localWind)*_windStrength; + float zCoordinate = sin(localWind)*_windStrength; + + cloth->setWindVelocity( btVector3(xCoordinate, 0, zCoordinate) ); + } + } +#ifndef TABLETEST + if (capCollider) + { + btVector3 origin( capCollider->getWorldTransform().getOrigin() ); + origin.setZ( origin.getZ() + 0.01 ); + capCollider->getWorldTransform().setOrigin( origin ); + } +#endif + + counter++; +} + +void initBullet(void) +{ + + +#ifdef USE_GPU_SOLVER + g_dx11Solver = new btDX11SoftBodySolver( g_pd3dDevice, DXUTGetD3D11DeviceContext() ); + g_solver = g_dx11Solver; +#ifdef USE_GPU_COPY + g_softBodyOutput = new btSoftBodySolverOutputDXtoDX( g_pd3dDevice, DXUTGetD3D11DeviceContext() ); +#else // #ifdef USE_GPU_COPY + g_softBodyOutput = new btSoftBodySolverOutputDXtoCPU; +#endif // #ifdef USE_GPU_COPY +#else +#ifdef USE_SIMDAWARE_SOLVER + g_dx11SIMDSolver = new btDX11SIMDAwareSoftBodySolver( g_pd3dDevice, DXUTGetD3D11DeviceContext() ); + g_solver = g_dx11SIMDSolver; + g_softBodyOutput = new btSoftBodySolverOutputDXtoCPU; +#ifdef USE_GPU_COPY + g_softBodyOutput = new btSoftBodySolverOutputDXtoDX( g_pd3dDevice, DXUTGetD3D11DeviceContext() ); +#else // #ifdef USE_GPU_COPY + g_softBodyOutput = new btSoftBodySolverOutputDXtoCPU; +#endif // #ifdef USE_GPU_COPY +#else + g_cpuSolver = new btCPUSoftBodySolver; + g_solver = g_cpuSolver; + g_softBodyOutput = new btSoftBodySolverOutputCPUtoCPU; + //g_defaultSolver = new btDefaultSoftBodySolver; + //g_solver = g_defaultSolver; +#endif +#endif + + if (g_dx11SIMDSolver) + g_dx11SIMDSolver->setEnableUpdateBounds(true); + + if (g_dx11Solver) + g_dx11Solver->setEnableUpdateBounds(true); + + // Initialise CPU physics device + //m_collisionConfiguration = new btDefaultCollisionConfiguration(); + m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration(); + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + m_broadphase = new btDbvtBroadphase(); + btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; + m_solver = sol; + + m_dynamicsWorld = new btSoftRigidDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration, g_solver); + + m_dynamicsWorld->setGravity(btVector3(0,-10,0)); + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); + m_collisionShapes.push_back(groundShape); + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + + m_dynamicsWorld->getWorldInfo().air_density = (btScalar)1.2; + m_dynamicsWorld->getWorldInfo().water_density = 0; + m_dynamicsWorld->getWorldInfo().water_offset = 0; + m_dynamicsWorld->getWorldInfo().water_normal = btVector3(0,0,0); + m_dynamicsWorld->getWorldInfo().m_gravity.setValue(0,-10,0); + +#if 0 + { + btScalar mass(0.); + + //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) + groundShape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + //add the body to the dynamics world + m_dynamicsWorld->addRigidBody(body); + } + +#endif +#if 0 + { + btScalar mass(0.); + + //btScalar mass(1.); + + //rigidbody is dynamic if and only if mass is non zero, otherwise static + bool isDynamic = (mass != 0.f); + + btCollisionShape *capsuleShape = new btCapsuleShape(5, 10); + capsuleShape->setMargin( 0.5 ); + + + + my_capsule.set_collision_shape(capsuleShape); + + btVector3 localInertia(0,0,0); + if (isDynamic) + capsuleShape->calculateLocalInertia(mass,localInertia); + + m_collisionShapes.push_back(capsuleShape); + btTransform capsuleTransform; + capsuleTransform.setIdentity(); +#ifdef TABLETEST + capsuleTransform.setOrigin(btVector3(0, 10, -11)); + const btScalar pi = 3.141592654; + capsuleTransform.setRotation(btQuaternion(0, 0, pi/2)); +#else + capsuleTransform.setOrigin(btVector3(0, 20, -10)); + + const btScalar pi = 3.141592654; + //capsuleTransform.setRotation(btQuaternion(0, 0, pi/2)); + capsuleTransform.setRotation(btQuaternion(0, 0, 0)); +#endif + btDefaultMotionState* myMotionState = new btDefaultMotionState(capsuleTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,capsuleShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + body->setFriction( 0.8f ); + my_capsule.set_collision_object(body); + + m_dynamicsWorld->addRigidBody(body); + //cap_1.collisionShape = body; + capCollider = body; + } +#endif + + + createFlag( clothWidth, clothHeight, m_flags ); + + // Create output buffer descriptions for ecah flag + // These describe where the simulation should send output data to + for( int flagIndex = 0; flagIndex < m_flags.size(); ++flagIndex ) + { + // In this case we have a DX11 output buffer with a vertex at index 0, 8, 16 and so on as well as a normal at 3, 11, 19 etc. + // Copies will be performed GPU-side directly into the output buffer +#ifdef USE_GPU_COPY + btDX11VertexBufferDescriptor *vertexBufferDescriptor = new btDX11VertexBufferDescriptor(DXUTGetD3D11DeviceContext(), cloths[flagIndex].pVB[0], cloths[flagIndex].g_pVB_UAV, 0, 8, 3, 8); + cloths[flagIndex].m_vertexBufferDescriptor = vertexBufferDescriptor; +#else // #ifdef USE_GPU_COPY + btCPUVertexBufferDescriptor *vertexBufferDescriptor = new btCPUVertexBufferDescriptor(cloths[flagIndex].cpu_buffer, 0, 8, 3, 8); + cloths[flagIndex].m_vertexBufferDescriptor = vertexBufferDescriptor; +#endif // #ifdef USE_GPU_COPY + } + + g_solver->optimize( m_dynamicsWorld->getSoftBodyArray() ); + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +//-------------------------------------------------------------------------------------- +// UI control IDs +//-------------------------------------------------------------------------------------- +#define IDC_TOGGLEFULLSCREEN 1 +#define IDC_TOGGLEREF 3 +#define IDC_CHANGEDEVICE 4 +#define IDC_PAUSE 5 +#define IDC_WIREFRAME 6 + +//-------------------------------------------------------------------------------------- +// Forward declarations +//-------------------------------------------------------------------------------------- +bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext ); +void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext ); +LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, + void* pUserContext ); +void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext ); +void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext ); + +bool CALLBACK IsD3D11DeviceAcceptable(const CD3D11EnumAdapterInfo *AdapterInfo, UINT Output, const CD3D11EnumDeviceInfo *DeviceInfo, + DXGI_FORMAT BackBufferFormat, bool bWindowed, void* pUserContext ); +HRESULT CALLBACK OnD3D11CreateDevice( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, + void* pUserContext ); +HRESULT CALLBACK OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, IDXGISwapChain* pSwapChain, + const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ); +void CALLBACK OnD3D11ReleasingSwapChain( void* pUserContext ); +void CALLBACK OnD3D11DestroyDevice( void* pUserContext ); +void CALLBACK OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime, + float fElapsedTime, void* pUserContext ); + +void InitApp(); +void RenderText(); + + +//-------------------------------------------------------------------------------------- +// Entry point to the program. Initializes everything and goes into a message processing +// loop. Idle time is used to render the scene. +//-------------------------------------------------------------------------------------- +int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ) +{ + // Enable run-time memory check for debug builds. +#if defined(DEBUG) | defined(_DEBUG) + _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); + _CrtSetReportMode ( _CRT_ERROR, _CRTDBG_MODE_DEBUG); +#endif + + // DXUT will create and use the best device (either D3D9 or D3D11) + // that is available on the system depending on which D3D callbacks are set below + + // Set DXUT callbacks + DXUTSetCallbackDeviceChanging( ModifyDeviceSettings ); + DXUTSetCallbackMsgProc( MsgProc ); + DXUTSetCallbackKeyboard( OnKeyboard ); + DXUTSetCallbackFrameMove( OnFrameMove ); + + + DXUTSetCallbackD3D11DeviceAcceptable( IsD3D11DeviceAcceptable ); + DXUTSetCallbackD3D11DeviceCreated( OnD3D11CreateDevice ); + + DXUTSetCallbackD3D11SwapChainResized( OnD3D11ResizedSwapChain ); + DXUTSetCallbackD3D11FrameRender( OnD3D11FrameRender ); + DXUTSetCallbackD3D11SwapChainReleasing( OnD3D11ReleasingSwapChain ); + + DXUTSetCallbackD3D11DeviceDestroyed( OnD3D11DestroyDevice ); + + + InitApp(); + DXUTInit( true, true, NULL ); // Parse the command line, show msgboxes on error, no extra command line params + DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen + DXUTCreateWindow( L"Cloth Renderer" ); + DXUTCreateDevice (D3D_FEATURE_LEVEL_11_0, true, 800, 600 ); + DXUTSetMultimonSettings(false); + //DXUTCreateDevice(true, 640, 480); + DXUTMainLoop(); // Enter into the DXUT render loop + + return DXUTGetExitCode(); +} + + +//-------------------------------------------------------------------------------------- +// Initialize the app +//-------------------------------------------------------------------------------------- +void InitApp() +{ + D3DXVECTOR3 vLightDir( 1, 0, 0 ); + D3DXVec3Normalize( &vLightDir, &vLightDir ); + g_LightControl.SetLightDirection( vLightDir ); + + // Initialize dialogs + g_D3DSettingsDlg.Init( &g_DialogResourceManager ); + g_HUD.Init( &g_DialogResourceManager ); + g_SampleUI.Init( &g_DialogResourceManager ); + + g_HUD.SetCallback( OnGUIEvent ); int iY = 10; + g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 0, iY, 170, 23 ); + + g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 0, iY += 26, 170, 23, VK_F3 ); + g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 0, iY += 26, 170, 23, VK_F2 ); + g_HUD.AddButton( IDC_PAUSE, L"Pause", 0, iY += 26, 170, 23 ); + g_HUD.AddButton( IDC_WIREFRAME, L"Wire frame", 0, iY += 26, 170, 23 ); + + g_SampleUI.SetCallback( OnGUIEvent ); iY = 10; +} + + +//-------------------------------------------------------------------------------------- +// Called right before creating a D3D9 or D3D11 device, allowing the app to modify the device settings as needed +//-------------------------------------------------------------------------------------- +bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext ) +{ + // Uncomment this to get debug information from D3D11 + //pDeviceSettings->d3d11.CreateFlags |= D3D11_CREATE_DEVICE_DEBUG; + + // For the first device created if its a REF device, optionally display a warning dialog box + static bool s_bFirstTime = true; + if( s_bFirstTime ) + { + s_bFirstTime = false; + if( ( DXUT_D3D11_DEVICE == pDeviceSettings->ver && + pDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE ) ) + { + DXUTDisplaySwitchingToREFWarning( pDeviceSettings->ver ); + } + } + + return true; +} + + +//-------------------------------------------------------------------------------------- +// Handle updates to the scene. This is called regardless of which D3D API is used +//-------------------------------------------------------------------------------------- +void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext ) +{ + // Update the camera's position based on user input + g_Camera.FrameMove( fElapsedTime ); +} + + +//-------------------------------------------------------------------------------------- +// Render the help and statistics text +//-------------------------------------------------------------------------------------- +void RenderText() +{ + UINT nBackBufferHeight = ( DXUTIsAppRenderingWithD3D9() ) ? DXUTGetD3D9BackBufferSurfaceDesc()->Height : + DXUTGetDXGIBackBufferSurfaceDesc()->Height; + + g_pTxtHelper->Begin(); + g_pTxtHelper->SetInsertionPos( 2, 0 ); + g_pTxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) ); + g_pTxtHelper->DrawTextLine( DXUTGetFrameStats( DXUTIsVsyncEnabled() ) ); + g_pTxtHelper->DrawTextLine( DXUTGetDeviceStats() ); + + // Draw help + if( g_bShowHelp ) + { + g_pTxtHelper->SetInsertionPos( 2, nBackBufferHeight - 20 * 6 ); + g_pTxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 0.75f, 0.0f, 1.0f ) ); + g_pTxtHelper->DrawTextLine( L"Controls:" ); + + g_pTxtHelper->SetInsertionPos( 20, nBackBufferHeight - 20 * 5 ); + g_pTxtHelper->DrawTextLine( L"Rotate view: Left mouse button\n" + L"Move camera: W, A, S, and D\n" + L"Rotate light: Right mouse button\n" + L"Zoom camera: Mouse wheel scroll\n" ); + + g_pTxtHelper->SetInsertionPos( 550, nBackBufferHeight - 20 * 5 ); + g_pTxtHelper->DrawTextLine( L"Hide help: F1\n" + L"Quit: ESC\n" ); + } + else + { + g_pTxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) ); + g_pTxtHelper->DrawTextLine( L"Press F1 for help" ); + } + + g_pTxtHelper->End(); +} + + +//-------------------------------------------------------------------------------------- +// Handle messages to the application +//-------------------------------------------------------------------------------------- +LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, + void* pUserContext ) +{ + // Pass messages to dialog resource manager calls so GUI state is updated correctly + *pbNoFurtherProcessing = g_DialogResourceManager.MsgProc( hWnd, uMsg, wParam, lParam ); + if( *pbNoFurtherProcessing ) + return 0; + + // Pass messages to settings dialog if its active + if( g_D3DSettingsDlg.IsActive() ) + { + g_D3DSettingsDlg.MsgProc( hWnd, uMsg, wParam, lParam ); + return 0; + } + + // Give the dialogs a chance to handle the message first + *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam ); + if( *pbNoFurtherProcessing ) + return 0; + *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam ); + if( *pbNoFurtherProcessing ) + return 0; + + g_LightControl.HandleMessages( hWnd, uMsg, wParam, lParam ); + + // Pass all remaining windows messages to camera so it can respond to user input + g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam ); + + return 0; +} + + +//-------------------------------------------------------------------------------------- +// Handle key presses +//-------------------------------------------------------------------------------------- +void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext ) +{ + if( bKeyDown ) + { + switch( nChar ) + { + case VK_F1: + g_bShowHelp = !g_bShowHelp; break; + } + } +} + + +//-------------------------------------------------------------------------------------- +// Handles the GUI events +//-------------------------------------------------------------------------------------- +void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext ) +{ + switch( nControlID ) + { + case IDC_TOGGLEFULLSCREEN: + DXUTToggleFullScreen(); break; + case IDC_TOGGLEREF: + DXUTToggleREF(); break; + case IDC_CHANGEDEVICE: + g_D3DSettingsDlg.SetActive( !g_D3DSettingsDlg.IsActive() ); break; + case IDC_PAUSE: + paused = !paused; + break; + case IDC_WIREFRAME: + g_wireFrame = !g_wireFrame; + break; + } + +} + + +//-------------------------------------------------------------------------------------- +// Reject any D3D11 devices that aren't acceptable by returning false +//-------------------------------------------------------------------------------------- +bool CALLBACK IsD3D11DeviceAcceptable( const CD3D11EnumAdapterInfo *AdapterInfo, UINT Output, const CD3D11EnumDeviceInfo *DeviceInfo, + DXGI_FORMAT BackBufferFormat, bool bWindowed, void* pUserContext ) +{ + return true; +} + +//-------------------------------------------------------------------------------------- +// Use this until D3DX11 comes online and we get some compilation helpers +//-------------------------------------------------------------------------------------- +HRESULT CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut ) +{ + HRESULT hr = S_OK; + + // find the file + WCHAR str[MAX_PATH]; + V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, szFileName ) ); + + // open the file + HANDLE hFile = CreateFile( str, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, NULL ); + if( INVALID_HANDLE_VALUE == hFile ) + return E_FAIL; + + // Get the file size + LARGE_INTEGER FileSize; + GetFileSizeEx( hFile, &FileSize ); + + // create enough space for the file data + BYTE* pFileData = new BYTE[ FileSize.LowPart ]; + if( !pFileData ) + return E_OUTOFMEMORY; + + // read the data in + DWORD BytesRead; + if( !ReadFile( hFile, pFileData, FileSize.LowPart, &BytesRead, NULL ) ) + return E_FAIL; + + CloseHandle( hFile ); + + // Compile the shader + ID3DBlob* pErrorBlob; + hr = D3DCompile( pFileData, FileSize.LowPart, "none", NULL, NULL, szEntryPoint, szShaderModel, D3D10_SHADER_ENABLE_STRICTNESS, 0, ppBlobOut, &pErrorBlob ); + + delete []pFileData; + + if( FAILED(hr) ) + { + OutputDebugStringA( (char*)pErrorBlob->GetBufferPointer() ); + SAFE_RELEASE( pErrorBlob ); + return hr; + } + SAFE_RELEASE( pErrorBlob ); + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Create any D3D11 resources that aren't dependant on the back buffer +//-------------------------------------------------------------------------------------- +HRESULT CALLBACK OnD3D11CreateDevice( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, + void* pUserContext ) +{ + + g_pd3dDevice = pd3dDevice; + + HRESULT hr; + + ID3D11DeviceContext* pd3dImmediateContext = DXUTGetD3D11DeviceContext(); + + V_RETURN( g_DialogResourceManager.OnD3D11CreateDevice( pd3dDevice, pd3dImmediateContext ) ); + V_RETURN( g_D3DSettingsDlg.OnD3D11CreateDevice( pd3dDevice ) ); + g_pTxtHelper = new CDXUTTextHelper( pd3dDevice, pd3dImmediateContext, &g_DialogResourceManager, 15 ); + + D3DXVECTOR3 vCenter( 0.25767413f, -28.503521f, 111.00689f); + FLOAT fObjectRadius = 378.15607f; + + D3DXMatrixTranslation( &g_mCenterMesh, -vCenter.x, -vCenter.y, -vCenter.z ); + D3DXMATRIXA16 m; + D3DXMatrixRotationY( &m, D3DX_PI ); + g_mCenterMesh *= m; + D3DXMatrixRotationX( &m, D3DX_PI / 2.0f ); + g_mCenterMesh *= m; + + // Compile the shaders to a model based on the feature level we acquired + ID3DBlob* pVertexShaderBuffer = NULL; + ID3DBlob* pGeometryShaderBuffer = NULL; + ID3DBlob* pPixelShaderBuffer = NULL; + + switch( DXUTGetD3D11DeviceFeatureLevel() ) + { + case D3D_FEATURE_LEVEL_11_0: + V_RETURN( CompileShaderFromFile( L"cloth_renderer_VS.hlsl", "VSMain", "vs_5_0" , &pVertexShaderBuffer ) ); + V_RETURN( CompileShaderFromFile( L"cloth_renderer_PS.hlsl", "GSMain", "gs_5_0" , &pGeometryShaderBuffer ) ); + V_RETURN( CompileShaderFromFile( L"cloth_renderer_PS.hlsl", "PSMain", "ps_5_0" , &pPixelShaderBuffer ) ); + break; + } + + // Create the shaders + V_RETURN( pd3dDevice->CreateVertexShader( pVertexShaderBuffer->GetBufferPointer(), + pVertexShaderBuffer->GetBufferSize(), NULL, &g_pVertexShader ) ); + + + V_RETURN( pd3dDevice->CreateGeometryShader( pGeometryShaderBuffer->GetBufferPointer(), + pGeometryShaderBuffer->GetBufferSize(), NULL, &g_pGeometryShader ) ); + + + V_RETURN( pd3dDevice->CreatePixelShader( pPixelShaderBuffer->GetBufferPointer(), + pPixelShaderBuffer->GetBufferSize(), NULL, &g_pPixelShader ) ); + + + + V_RETURN( pd3dDevice->CreateInputLayout( layout, ARRAYSIZE( layout ), pVertexShaderBuffer->GetBufferPointer(), + pVertexShaderBuffer->GetBufferSize(), &g_pVertexLayout11 ) ); + + SAFE_RELEASE( pVertexShaderBuffer ); + SAFE_RELEASE( pPixelShaderBuffer ); + SAFE_RELEASE( pGeometryShaderBuffer ); + + + // Load the mesh + V_RETURN( g_Mesh11.Create( pd3dDevice, L"tiny\\tiny.sdkmesh", true ) ); + + + + + // Create a sampler state + D3D11_SAMPLER_DESC SamDesc; + SamDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + SamDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + SamDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + SamDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + SamDesc.MipLODBias = 0.0f; + SamDesc.MaxAnisotropy = 1; + SamDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + SamDesc.BorderColor[0] = SamDesc.BorderColor[1] = SamDesc.BorderColor[2] = SamDesc.BorderColor[3] = 0; + SamDesc.MinLOD = 0; + SamDesc.MaxLOD = D3D11_FLOAT32_MAX; + V_RETURN( pd3dDevice->CreateSamplerState( &SamDesc, &g_pSamLinear ) ); + + + + + // Setup constant buffers + D3D11_BUFFER_DESC Desc; + Desc.Usage = D3D11_USAGE_DYNAMIC; + Desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + Desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + Desc.MiscFlags = 0; + + Desc.ByteWidth = sizeof( CB_VS_PER_OBJECT ); + V_RETURN( pd3dDevice->CreateBuffer( &Desc, NULL, &g_pcbVSPerObject ) ); + + Desc.ByteWidth = sizeof( CB_PS_PER_OBJECT ); + V_RETURN( pd3dDevice->CreateBuffer( &Desc, NULL, &g_pcbPSPerObject ) ); + + Desc.ByteWidth = sizeof( CB_PS_PER_FRAME ); + V_RETURN( pd3dDevice->CreateBuffer( &Desc, NULL, &g_pcbPSPerFrame ) ); + + // Setup the camera's view parameters + + + D3DXVECTOR3 vecEye( 30.0f, 30.0f, -80.0f ); + D3DXVECTOR3 vecAt ( 10.0f, 20.0f, -0.0f ); + + + g_Camera.SetViewParams( &vecEye, &vecAt ); + + cloths.resize(numFlags); + + for( int flagIndex = 0; flagIndex < numFlags; ++flagIndex ) + { + cloths[flagIndex].create_buffers(clothWidth, clothHeight); + } + + initBullet(); + +std::wstring flagTexsName[] = { + L"atiFlag.bmp", + L"amdFlag.bmp", + }; + int numFlagTexs = 2; + + + + WCHAR flagTexs[2][MAX_PATH]; + + HRESULT res = DXUTFindDXSDKMediaFileCch(flagTexs[0],MAX_PATH, flagTexsName[0].c_str()); + res = DXUTFindDXSDKMediaFileCch(flagTexs[1],MAX_PATH, flagTexsName[1].c_str()); + + + for( int flagIndex = 0; flagIndex < numFlags; ++flagIndex ) + { + cloths[flagIndex].create_texture(flagTexs[flagIndex % numFlagTexs]); + cloths[flagIndex].x_offset = 0; + cloths[flagIndex].y_offset = 0; + cloths[flagIndex].z_offset = 0; + } + + + + my_capsule.create_buffers(50,40); + my_capsule.create_texture(); + + //Turn off backface culling + D3D11_RASTERIZER_DESC rsDesc; + ZeroMemory(&rsDesc,sizeof(D3D11_RASTERIZER_DESC) ); + rsDesc.CullMode = D3D11_CULL_NONE; + rsDesc.FillMode = D3D11_FILL_SOLID; + + hr = pd3dDevice->CreateRasterizerState(&rsDesc, &g_pRasterizerState); + + rsDesc.FillMode = D3D11_FILL_WIREFRAME; + hr = pd3dDevice->CreateRasterizerState(&rsDesc, &g_pRasterizerStateWF); + + SAFE_RELEASE(pd3dImmediateContext); + + + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Create any D3D11 resources that depend on the back buffer +//-------------------------------------------------------------------------------------- +HRESULT CALLBACK OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, IDXGISwapChain* pSwapChain, + const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) +{ + HRESULT hr; + + V_RETURN( g_DialogResourceManager.OnD3D11ResizedSwapChain( pd3dDevice, pBackBufferSurfaceDesc ) ); + V_RETURN( g_D3DSettingsDlg.OnD3D11ResizedSwapChain( pd3dDevice, pBackBufferSurfaceDesc ) ); + + // Setup the camera's projection parameters + float fAspectRatio = pBackBufferSurfaceDesc->Width / ( FLOAT )pBackBufferSurfaceDesc->Height; + g_Camera.SetProjParams( D3DX_PI / 4, fAspectRatio, 2.0f, 4000.0f ); + // g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height ); + // g_Camera.SetButtonMasks( MOUSE_MIDDLE_BUTTON, MOUSE_WHEEL, MOUSE_LEFT_BUTTON ); + + + D3DXVECTOR3 vMin = D3DXVECTOR3( -1000.0f, -1000.0f, -1000.0f ); + D3DXVECTOR3 vMax = D3DXVECTOR3( 1000.0f, 1000.0f, 1000.0f ); + g_Camera.SetRotateButtons(TRUE, FALSE, FALSE); + + + g_Camera.SetScalers( 0.01f, 30.0f ); + g_Camera.SetDrag( true ); + g_Camera.SetEnableYAxisMovement( true ); + g_Camera.SetClipToBoundary( TRUE, &vMin, &vMax ); + g_Camera.FrameMove( 0 ); + + + g_HUD.SetLocation( pBackBufferSurfaceDesc->Width - 170, 0 ); + g_HUD.SetSize( 170, 170 ); + g_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width - 170, pBackBufferSurfaceDesc->Height - 300 ); + g_SampleUI.SetSize( 170, 300 ); + + //Turn off backface culling + D3D11_RASTERIZER_DESC rsDesc; + ZeroMemory(&rsDesc,sizeof(D3D11_RASTERIZER_DESC) ); + rsDesc.CullMode = D3D11_CULL_NONE; + rsDesc.FillMode = D3D11_FILL_SOLID; + //rsDesc.FillMode = D3D11_FILL_WIREFRAME; + + + ID3D11RasterizerState *pRasterizerState = NULL; + pd3dDevice->CreateRasterizerState(&rsDesc, &pRasterizerState); + + DXUTGetD3D11DeviceContext()->RSSetState(pRasterizerState); + + SAFE_RELEASE(pRasterizerState); + + return S_OK; +} + + +btClock m_clock; +//-------------------------------------------------------------------------------------- +// Render the scene using the D3D11 device +//-------------------------------------------------------------------------------------- +void CALLBACK OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime, + float fElapsedTime, void* pUserContext ) +{ + + + + + //float ms = getDeltaTimeMicroseconds(); + btScalar dt = (btScalar)m_clock.getTimeMicroseconds(); + m_clock.reset(); + + ///step the simulation + if (m_dynamicsWorld && !paused) + { + + m_dynamicsWorld->stepSimulation(dt / 1000000.f); + + updatePhysicsWorld(); + } + + //paused = 1; + + + + /////////////////////////////////////////////////////// + + HRESULT hr; + + // If the settings dialog is being shown, then render it instead of rendering the app's scene + if( g_D3DSettingsDlg.IsActive() ) + { + g_D3DSettingsDlg.OnRender( fElapsedTime ); + return; + } + + // Clear the render target and depth stencil + float ClearColor[4] = { 0.0f, 0.25f, 0.25f, 0.55f }; + ID3D11RenderTargetView* pRTV = DXUTGetD3D11RenderTargetView(); + pd3dImmediateContext->ClearRenderTargetView( pRTV, ClearColor ); + ID3D11DepthStencilView* pDSV = DXUTGetD3D11DepthStencilView(); + pd3dImmediateContext->ClearDepthStencilView( pDSV, D3D11_CLEAR_DEPTH, 1.0, 0 ); + + + for( int flagIndex = 0; flagIndex < m_flags.size(); ++flagIndex ) + { + g_softBodyOutput->copySoftBodyToVertexBuffer( m_flags[flagIndex], cloths[flagIndex].m_vertexBufferDescriptor ); + cloths[flagIndex].draw(); + } + + my_capsule.draw(); + + + DXUT_BeginPerfEvent( DXUT_PERFEVENTCOLOR, L"HUD / Stats" ); + g_HUD.OnRender( fElapsedTime ); + g_SampleUI.OnRender( fElapsedTime ); + RenderText(); + DXUT_EndPerfEvent(); + + +/* + SAFE_RELEASE(pRTV); + SAFE_RELEASE(pDSV); +*/ + + +} + + +//-------------------------------------------------------------------------------------- +// Release D3D11 resources created in OnD3D11ResizedSwapChain +//-------------------------------------------------------------------------------------- +void CALLBACK OnD3D11ReleasingSwapChain( void* pUserContext ) +{ + g_DialogResourceManager.OnD3D11ReleasingSwapChain(); + DXUTGetD3D11DeviceContext()->ClearState(); +} + + +//-------------------------------------------------------------------------------------- +// Release D3D11 resources created in OnD3D11CreateDevice +//-------------------------------------------------------------------------------------- +void CALLBACK OnD3D11DestroyDevice( void* pUserContext ) +{ + g_DialogResourceManager.OnD3D11DestroyDevice(); + g_D3DSettingsDlg.OnD3D11DestroyDevice(); + DXUTGetGlobalResourceCache().OnDestroyDevice(); + SAFE_DELETE( g_pTxtHelper ); + + g_Mesh11.Destroy(); + + + SAFE_RELEASE(g_pGeometryShader); + SAFE_RELEASE( g_pVertexLayout11 ); + SAFE_RELEASE( g_pVertexBuffer ); + SAFE_RELEASE( g_pVertexShader ); + SAFE_RELEASE( g_pPixelShader ); + SAFE_RELEASE( g_pSamLinear ); + + SAFE_RELEASE( g_pcbVSPerObject ); + SAFE_RELEASE( g_pcbPSPerObject ); + SAFE_RELEASE( g_pcbPSPerFrame ); + + SAFE_RELEASE( g_pRasterizerState ); + SAFE_RELEASE( g_pRasterizerStateWF ); + + + for( int flagIndex = 0; flagIndex < numFlags; ++flagIndex ) + { + cloths[flagIndex].destroy(); + } + + my_capsule.destroy(); + + // Shouldn't need to delete this as it's just a soft body and will be deleted later by the collision object cleanup. + //for( int flagIndex = 0; flagIndex < m_flags.size(); ++flagIndex ) + //{ + //delete m_flags[flagIndex]; + //} + + //cleanup in the reverse order of creation/initialization + if( g_defaultSolver ) + delete g_defaultSolver; + if( g_cpuSolver ) + delete g_cpuSolver; + if( g_dx11Solver ) + delete g_dx11Solver; + if( g_dx11SIMDSolver ) + delete g_dx11SIMDSolver; + if( g_softBodyOutput ) + delete g_softBodyOutput; + + + for(int i=0; i< m_collisionShapes.size(); i++) + delete m_collisionShapes[i]; + + //remove the rigidbodies from the dynamics world and delete them + int 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 m_dynamicsWorld; + delete m_solver; + delete m_broadphase; + delete m_dispatcher; + delete m_collisionConfiguration; + + +} + + + + + + + + + + diff --git a/Demos/DX11ClothDemo/cloth_renderer.fx b/Demos/DX11ClothDemo/cloth_renderer.fx new file mode 100644 index 0000000..2b8f318 --- /dev/null +++ b/Demos/DX11ClothDemo/cloth_renderer.fx @@ -0,0 +1,157 @@ +//-------------------------------------------------------------------------------------- +// File: BasicHLSL.fx +// +// The effect file for the BasicHLSL sample. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------------------- +// Global variables +//-------------------------------------------------------------------------------------- +float4 g_MaterialAmbientColor; // Material's ambient color +float4 g_MaterialDiffuseColor; // Material's diffuse color +int g_nNumLights; + +float3 g_LightDir; // Light's direction in world space +float4 g_LightDiffuse; // Light's diffuse color +float4 g_LightAmbient; // Light's ambient color + +texture g_MeshTexture; // Color texture for mesh + +float g_fTime; // App's time in seconds +float4x4 g_mWorld; // World matrix for object +float4x4 g_mWorldViewProjection; // World * View * Projection matrix + + + +//-------------------------------------------------------------------------------------- +// Texture samplers +//-------------------------------------------------------------------------------------- +sampler MeshTextureSampler = +sampler_state +{ + Texture = ; + MipFilter = LINEAR; + MinFilter = LINEAR; + MagFilter = LINEAR; +}; + + +//-------------------------------------------------------------------------------------- +// Vertex shader output structure +//-------------------------------------------------------------------------------------- +struct VS_OUTPUT +{ + float4 Position : POSITION; // vertex position + float4 Diffuse : COLOR0; // vertex diffuse color (note that COLOR0 is clamped from 0..1) + float2 TextureUV : TEXCOORD0; // vertex texture coords +}; + + +//-------------------------------------------------------------------------------------- +// This shader computes standard transform and lighting +//-------------------------------------------------------------------------------------- +VS_OUTPUT RenderSceneVS( float4 vPos : POSITION, + float3 vNormal : NORMAL, + float2 vTexCoord0 : TEXCOORD0, + uniform int nNumLights, + uniform bool bTexture, + uniform bool bAnimate ) +{ + + VS_OUTPUT Output; + float3 vNormalWorldSpace; + + // Transform the position from object space to homogeneous projection space + Output.Position = mul(vPos, g_mWorldViewProjection); + + // Transform the normal from object space to world space + vNormalWorldSpace = normalize(mul(vNormal, (float3x3)g_mWorld)); // normal (world space) + + // Compute simple directional lighting equation + float3 vTotalLightDiffuse = float3(0,0,0); + for(int i=0; i + + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAIN_ICON ICON "DXUT\Optional\\directx.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define IDC_STATIC -1\r\n" + "#include \r\n" + "\r\n" + "\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Demos/DX11ClothDemo/cloth_renderer_PS.hlsl b/Demos/DX11ClothDemo/cloth_renderer_PS.hlsl new file mode 100644 index 0000000..553a546 --- /dev/null +++ b/Demos/DX11ClothDemo/cloth_renderer_PS.hlsl @@ -0,0 +1,90 @@ +//-------------------------------------------------------------------------------------- +// File: BasicHLSL11_PS.hlsl +// +// The pixel shader file for the BasicHLSL11 sample. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------------- +// Globals +//-------------------------------------------------------------------------------------- +cbuffer cbPerObject : register( b0 ) +{ + float4 g_vObjectColor : packoffset( c0 ); +}; + +cbuffer cbPerFrame : register( b1 ) +{ + float3 g_vLightDir : packoffset( c0 ); + float g_fAmbient : packoffset( c0.w ); +}; + +//-------------------------------------------------------------------------------------- +// Textures and Samplers +//-------------------------------------------------------------------------------------- +Texture2D g_txDiffuse : register( t0 ); +SamplerState g_samLinear : register( s0 ); + +//-------------------------------------------------------------------------------------- +// Input / Output structures +//-------------------------------------------------------------------------------------- +struct PS_INPUT +{ + float3 vNormal : NORMAL; + float2 vTexcoord : TEXCOORD0; + float4 vPosition : SV_POSITION; +}; + +//-------------------------------------------------------------------------------------- +// Pixel Shader +//-------------------------------------------------------------------------------------- +float4 PSMain( PS_INPUT Input ) : SV_TARGET +{ + float4 vDiffuse = g_txDiffuse.Sample( g_samLinear, Input.vTexcoord ); + + + float fLighting = saturate( dot( g_vLightDir, (Input.vNormal)/length(Input.vNormal) ) ); + //float fLighting = saturate( dot( g_vLightDir, float3(Input.vTexcoord.x,0,0) ) ); + fLighting = max( fLighting, g_fAmbient ); + + //fLighting = dot(g_vLightDir,float3(0,1,0)); + + return vDiffuse * fLighting; +} + + +struct VS_OUTPUT +{ + float3 vNormal : NORMAL; + float2 vTexcoord : TEXCOORD0; + float4 vPosition : SV_POSITION; +}; + +[maxvertexcount(3)] +void GSMain(triangle VS_OUTPUT input[3], inout TriangleStream OutputStream) +{ +PS_INPUT output = (PS_INPUT)0; + + +/* +float3 v1 = input[1].vPosition - input[0].vPosition; +float3 v2 = input[2].vPosition - input[0].vPosition; +float3 normal = cross(v1,v2); + +normal = normalize(normal); +*/ + + +for(int i = 0; i < 3; i++) +{ + +output.vNormal = input[i].vNormal; +output.vTexcoord = input[i].vTexcoord; +output.vPosition = input[i].vPosition; +OutputStream.Append(output); +} + +OutputStream.RestartStrip(); + +} \ No newline at end of file diff --git a/Demos/DX11ClothDemo/cloth_renderer_VS.hlsl b/Demos/DX11ClothDemo/cloth_renderer_VS.hlsl new file mode 100644 index 0000000..331e2f8 --- /dev/null +++ b/Demos/DX11ClothDemo/cloth_renderer_VS.hlsl @@ -0,0 +1,48 @@ +//-------------------------------------------------------------------------------------- +// File: BasicHLSL11_VS.hlsl +// +// The vertex shader file for the BasicHLSL11 sample. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------------- +// Globals +//-------------------------------------------------------------------------------------- +cbuffer cbPerObject : register( b0 ) +{ + matrix g_mWorldViewProjection : packoffset( c0 ); + matrix g_mWorld : packoffset( c4 ); +}; + +//-------------------------------------------------------------------------------------- +// Input / Output structures +//-------------------------------------------------------------------------------------- +struct VS_INPUT +{ + float4 vPosition : POSITION; + float3 vNormal : NORMAL; + float2 vTexcoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float3 vNormal : NORMAL; + float2 vTexcoord : TEXCOORD0; + float4 vPosition : SV_POSITION; +}; + +//-------------------------------------------------------------------------------------- +// Vertex Shader +//-------------------------------------------------------------------------------------- +VS_OUTPUT VSMain( VS_INPUT Input ) +{ + VS_OUTPUT Output; + + Output.vPosition = mul( Input.vPosition, g_mWorldViewProjection ); + Output.vNormal = mul( Input.vNormal, (float3x3)g_mWorld ); + Output.vTexcoord = Input.vTexcoord; + + return Output; +} + diff --git a/Demos/DX11ClothDemo/cylinder.h b/Demos/DX11ClothDemo/cylinder.h new file mode 100644 index 0000000..225cb20 --- /dev/null +++ b/Demos/DX11ClothDemo/cylinder.h @@ -0,0 +1,297 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2010 Advanced Micro Devices + +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 CYLINDER_H +#define CYLINDER_H + +class cylinder +{ + public: + + ID3D11Buffer* g_pIndexBuffer; + ID3D11Buffer* pVB[1]; + UINT Strides[1]; + UINT Offsets[1]; + + double x_offset, y_offset, z_offset; + + int width; + int height; + + ID3D11Texture2D *texture2D; + ID3D11ShaderResourceView *texture2D_view; + + btCollisionShape *collisionShape; + + //static_cast(capsuleShape) + + + btCollisionObject *collisionObject; + + void set_collision_object(btCollisionObject* co) + { + collisionObject = co; + } + + void set_collision_shape(btCollisionShape* cs) + { + collisionShape = cs; + } + + + void destroy() + { + SAFE_RELEASE( g_pIndexBuffer ); + SAFE_RELEASE( pVB[0] ); + + SAFE_RELEASE( texture2D ); + SAFE_RELEASE( texture2D_view ); + } + + void create_texture(void) + { + D3DX11_IMAGE_LOAD_INFO loadInfo; + ZeroMemory(&loadInfo, sizeof(D3DX11_IMAGE_LOAD_INFO) ); + loadInfo.BindFlags = D3D11_BIND_SHADER_RESOURCE; + loadInfo.Format = DXGI_FORMAT_BC1_UNORM; + + HRESULT hr = D3DX11CreateShaderResourceViewFromFile(g_pd3dDevice, L"texture.bmp", &loadInfo, NULL, &texture2D_view, NULL); + } + + void draw(void) + { + + if (!collisionObject) + return; + + ID3D11DeviceContext* pd3dImmediateContext = DXUTGetD3D11DeviceContext(); + + D3DXMATRIX mWorldViewProjection; + D3DXVECTOR3 vLightDir; + D3DXMATRIX mWorld; + D3DXMATRIX mView; + D3DXMATRIX mProj; + + // Get the projection & view matrix from the camera class + mProj = *g_Camera.GetProjMatrix(); + mView = *g_Camera.GetViewMatrix(); + + // Get the light direction + vLightDir = g_LightControl.GetLightDirection(); + + // Per frame cb update + D3D11_MAPPED_SUBRESOURCE MappedResource; + + HRESULT hr; + + V( pd3dImmediateContext->Map( g_pcbPSPerFrame, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) ); + CB_PS_PER_FRAME* pPerFrame = ( CB_PS_PER_FRAME* )MappedResource.pData; + float fAmbient = 0.1f; + pPerFrame->m_vLightDirAmbient = D3DXVECTOR4( vLightDir.x, vLightDir.y, vLightDir.z, fAmbient ); + pd3dImmediateContext->Unmap( g_pcbPSPerFrame, 0 ); + + pd3dImmediateContext->PSSetConstantBuffers( g_iCBPSPerFrameBind, 1, &g_pcbPSPerFrame ); + + + ///////////////////////////////////////Modify below////////////////////////////////////////////////////// + + //Get the mesh + //IA setup + pd3dImmediateContext->IASetInputLayout( g_pVertexLayout11 ); + + //This is where we pass the vertex buffer to DX + pd3dImmediateContext->IASetVertexBuffers( 0, 1, pVB, Strides, Offsets ); + + //This is where we pass the index buffer to DX + pd3dImmediateContext->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 ); + + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + // Set the shaders + pd3dImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 ); + pd3dImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 ); + pd3dImmediateContext->GSSetShader( g_pGeometryShader, NULL, 0); + + // Set the per object constant data + + + + btTransform trans = collisionObject->getWorldTransform(); + + + + btVector3 origin = trans.getOrigin(); + btMatrix3x3 btM = trans.getBasis(); + + btScalar* scalar_matrix = new btScalar[16];; + trans.getOpenGLMatrix(scalar_matrix); + + D3DXMATRIXA16 m_trans(scalar_matrix[0],scalar_matrix[1],scalar_matrix[2],scalar_matrix[3], + scalar_matrix[4],scalar_matrix[5],scalar_matrix[6],scalar_matrix[7], + scalar_matrix[8],scalar_matrix[9],scalar_matrix[10],scalar_matrix[11], + scalar_matrix[12],scalar_matrix[13],scalar_matrix[14],scalar_matrix[15]); + + D3DXMATRIXA16 m_scale; + float sc = 10; + D3DXMatrixScaling(&m_scale,sc,sc,sc); + + + D3DXVECTOR3 vCenter( global_shift_x, global_shift_y, global_shift_z); + + D3DXMatrixTranslation( &g_mCenterMesh, -vCenter.x+x_offset, -vCenter.y+y_offset, -vCenter.z+z_offset ); + + + D3DXMATRIXA16 m_trans_transpose; + D3DXMatrixTranspose(&m_trans_transpose,&m_trans); + + mWorld = *g_Camera.GetWorldMatrix() ; + mProj = *g_Camera.GetProjMatrix(); + mView = m_trans * *g_Camera.GetViewMatrix(); + + mWorldViewProjection = mView * mProj; + + + // VS Per object + V( pd3dImmediateContext->Map( g_pcbVSPerObject, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) ); + CB_VS_PER_OBJECT* pVSPerObject = ( CB_VS_PER_OBJECT* )MappedResource.pData; + D3DXMatrixTranspose( &pVSPerObject->m_WorldViewProj, &mWorldViewProjection ); + D3DXMatrixTranspose( &pVSPerObject->m_World, &mWorld ); + pd3dImmediateContext->Unmap( g_pcbVSPerObject, 0 ); + + pd3dImmediateContext->VSSetConstantBuffers( g_iCBVSPerObjectBind, 1, &g_pcbVSPerObject ); + + // PS Per object + V( pd3dImmediateContext->Map( g_pcbPSPerObject, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) ); + CB_PS_PER_OBJECT* pPSPerObject = ( CB_PS_PER_OBJECT* )MappedResource.pData; + pPSPerObject->m_vObjectColor = D3DXVECTOR4( 1, 1, 1, 1 ); + pd3dImmediateContext->Unmap( g_pcbPSPerObject, 0 ); + + pd3dImmediateContext->PSSetConstantBuffers( g_iCBPSPerObjectBind, 1, &g_pcbPSPerObject ); + + //Render + SDKMESH_SUBSET* pSubset = NULL; + D3D11_PRIMITIVE_TOPOLOGY PrimType; + + pd3dImmediateContext->PSSetSamplers( 0, 1, &g_pSamLinear ); + + { + // Get the subset + pSubset = g_Mesh11.GetSubset( 0, 0 ); + + pd3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + pd3dImmediateContext->PSSetShaderResources(0,1,&texture2D_view); + + pd3dImmediateContext->DrawIndexed( (width*3*2+2 + height*width*3*2), 0, ( UINT )pSubset->VertexStart ); + } + + SAFE_RELEASE(pd3dImmediateContext); + } + + void create_buffers(int width_, int height_) + { + width = width_; + height = height_; + + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.Usage = D3D11_USAGE_DEFAULT; + bufferDesc.ByteWidth = sizeof(vertex_struct)*width*height; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.CPUAccessFlags = 0; + bufferDesc.MiscFlags = 0; + + vertex_struct *vertices = new vertex_struct[width*height]; + + btCapsuleShape* cs = static_cast(collisionShape); + if (cs) + { + float radius = cs->getRadius(); + float halfHeight = cs->getHalfHeight(); + + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + double coord_2 = sin(2.2*3.141159*y/(float)height)*radius; + double coord_1 = cos(2.2*3.141159*y/(float)height)*radius; + //double coord_2 = (y/((float)(height-1)))*1000; + + //coord = sin(y/); + + vertices[y*width+x].Pos = D3DXVECTOR3(coord_1, ((x/((float)(width-1)))-.5)*halfHeight*2, coord_2); + vertices[y*width+x].Normal = D3DXVECTOR3(coord_1,0,coord_2); + vertices[y*width+x].Texcoord = D3DXVECTOR2(x/( (float)(width-1)), y/((float)(height-1))); + } + } + + + /* + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + double coord = sin(x/5.0)*50; + //coord = sin(y/); + + vertices[y*width+x].Pos = D3DXVECTOR3( (x/((float)(width-1)))*1000, coord, (y/((float)(height-1)))*1000); + vertices[y*width+x].Normal = D3DXVECTOR3(1,0,0); + vertices[y*width+x].Texcoord = D3DXVECTOR2(x/( (float)(width-1)), y/((float)(height-1))); + } + } + */ + + D3D11_SUBRESOURCE_DATA InitData; + InitData.pSysMem = vertices; + InitData.SysMemPitch = 0; + InitData.SysMemSlicePitch = 0; + + HRESULT hr = g_pd3dDevice->CreateBuffer(&bufferDesc, &InitData, &pVB[0]); + + + //What is this vertex stride thing all about? + Strides[0] = ( UINT )g_Mesh11.GetVertexStride( 0, 0 ); + Offsets[0] = 0; + + //unsigned int indices[] = {0,1,2, 1,3,2}; + unsigned int* indices = new unsigned int[width*3*2+2 + height*width*3*2]; + + for(int y = 0; y < height-1; y++) + { + for(int x = 0; x < width-1; x++) + { + indices[x*3*2 + y*width*3*2] = x + y*width; + indices[x*3*2+1 + y*width*3*2] = x+1 + y*width; + indices[x*3*2+2 + y*width*3*2] = x+width + y*width; + + indices[x*3*2 + 3 + y*width*3*2] = x + 1 + y*width; + indices[x*3*2 + 4 + y*width*3*2] = x+(width+1) + y*width; + indices[x*3*2 + 5 + y*width*3*2] = x+width + y*width; + } + } + + bufferDesc.ByteWidth = sizeof(unsigned int)*(width*3*2+2 + height*width*3*2); + bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + + InitData.pSysMem = indices; + + hr = g_pd3dDevice->CreateBuffer(&bufferDesc, &InitData, &g_pIndexBuffer); + hr = hr; + } + } + + +}; + +#endif CYLINDER_H diff --git a/Demos/DX11ClothDemo/premake4.lua b/Demos/DX11ClothDemo/premake4.lua new file mode 100644 index 0000000..bb21f6a --- /dev/null +++ b/Demos/DX11ClothDemo/premake4.lua @@ -0,0 +1,41 @@ + + hasDX11 = findDirectX11() + + if (hasDX11) then + + project "App_DX11ClothDemo" + + initDirectX11() + + language "C++" + + defines { "UNICODE","_UNICODE"} + + kind "WindowedApp" + flags { "WinMain" } + + targetdir "../.." + includedirs { + "../../src", + "DXUT/Core", + "DXUT/Optional" + } + + links { + "LinearMath","BulletCollision","BulletDynamics", "BulletSoftBody", "BulletSoftBodyDX11Solvers" + } + files { + "DXUT/Core/DXUT.cpp", + "DXUT/Optional/DXUTcamera.cpp", + "DXUT/Core/DXUTDevice11.cpp", + "DXUT/Core/DXUTDevice9.cpp", + "DXUT/Optional/DXUTgui.cpp", + "DXUT/Core/DXUTmisc.cpp", + "DXUT/Optional/DXUTres.cpp", + "DXUT/Optional/DXUTsettingsdlg.cpp", + "DXUT/Optional/SDKmesh.cpp", + "DXUT/Optional/SDKmisc.cpp", + "cloth_renderer.cpp" + } + + end \ No newline at end of file diff --git a/Demos/DX11ClothDemo/resource.h b/Demos/DX11ClothDemo/resource.h new file mode 100644 index 0000000..9807fb1 --- /dev/null +++ b/Demos/DX11ClothDemo/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by BasicHLSL10.rc +// +#define IDI_MAIN_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 113 +#define _APS_NEXT_COMMAND_VALUE 40029 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Demos/DX11ClothDemo/texture.bmp b/Demos/DX11ClothDemo/texture.bmp new file mode 100644 index 0000000000000000000000000000000000000000..5bd5e762a6d47f5edbf49a33e3df1dbb6b9dd979 GIT binary patch literal 263222 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 Kt2FVu@IL_Xv7VR! literal 0 HcmV?d00001 diff --git a/Demos/DoublePrecisionDemo/CMakeLists.txt b/Demos/DoublePrecisionDemo/CMakeLists.txt new file mode 100644 index 0000000..cda49cb --- /dev/null +++ b/Demos/DoublePrecisionDemo/CMakeLists.txt @@ -0,0 +1,49 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppDoublePrecisionDemo + DoublePrecisionDemo.cpp +) + +IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppDoublePrecisionDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppDoublePrecisionDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF(WIN32) + + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppDoublePrecisionDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppDoublePrecisionDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppDoublePrecisionDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/DoublePrecisionDemo/DoublePrecisionDemo.cpp b/Demos/DoublePrecisionDemo/DoublePrecisionDemo.cpp new file mode 100644 index 0000000..6ba380d --- /dev/null +++ b/Demos/DoublePrecisionDemo/DoublePrecisionDemo.cpp @@ -0,0 +1,280 @@ +/* +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. +*/ + + +/// +/// DoublePrecisionDemo shows high level usage of the Collision Detection. +/// + +#include "GL_Simplex1to4.h" + +//include common Bullet Collision Detection headerfiles +#include "btBulletCollisionCommon.h" + +#include "LinearMath/btIDebugDraw.h" +#include "GLDebugFont.h" + + +#include "GL_ShapeDrawer.h" +#include "DoublePrecisionDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" + +btScalar yaw=btScalar(0.); +btScalar pitch=btScalar(0.); +btScalar roll=btScalar(0.); +const int maxNumObjects = 4; +const int numObjects = 2; + +GL_Simplex1to4 simplex; + + +btCollisionObject objects[maxNumObjects]; +btCollisionWorld* collisionWorld = 0; + +// so pixel ratio is 1:1 +int screenWidth = 640; +int screenHeight = 640; +GLDebugDrawer debugDrawer; + +const btScalar LARGE_DISTANCE_FROM_ORIGIN = btScalar(999999.0); +const btScalar VERY_SMALL_INCREMENT = btScalar(0.000009); + +int main(int argc,char** argv) +{ + DoublePrecisionDemo* doublePrecisionDemo = new DoublePrecisionDemo(); + + doublePrecisionDemo->initPhysics(); + doublePrecisionDemo->setCameraDistance(btScalar(2.0)); + + doublePrecisionDemo->clientResetScene(); + + return glutmain(argc, argv,screenWidth,screenHeight,"Double Precision Demo",doublePrecisionDemo); +} + +void DoublePrecisionDemo::initPhysics() +{ + m_debugMode |= btIDebugDraw::DBG_DrawWireframe; + + btMatrix3x3 basisA; + basisA.setIdentity(); + + btMatrix3x3 basisB; + basisB.setIdentity(); + + objects[0].getWorldTransform().setBasis(basisA); + objects[1].getWorldTransform().setBasis(basisB); + + + btBoxShape* boxA = new btBoxShape(btVector3(0.5,0.5,0.5)); + btBoxShape* boxB = new btBoxShape(btVector3(0.5,0.5,0.5)); + + objects[0].setCollisionShape(boxA);//&hullA; + objects[1].setCollisionShape(boxB);//&hullB; + + btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration(); + btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration); + btVector3 worldAabbMin(80000,80000,80000); + btVector3 worldAabbMax(120000,120000,120000); + + btAxisSweep3* broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax); + + collisionWorld = new btCollisionWorld(dispatcher,broadphase,collisionConfiguration); + + collisionWorld->addCollisionObject(&objects[0]); + collisionWorld->addCollisionObject(&objects[1]); + +} + + +//to be implemented by the demo + +void DoublePrecisionDemo::clientMoveAndDisplay() +{ + + displayCallback(); +} + + +static btVoronoiSimplexSolver sGjkSimplexSolver; +btSimplexSolverInterface& gGjkSimplexSolver = sGjkSimplexSolver; + +void DoublePrecisionDemo::displayCallback(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glDisable(GL_LIGHTING); + + collisionWorld->getDispatchInfo().m_debugDraw = &debugDrawer; + + if (collisionWorld) + collisionWorld->performDiscreteCollisionDetection(); + + int i; + + btVector3 worldBoundsMin,worldBoundsMax; + collisionWorld->getBroadphase()->getBroadphaseAabb(worldBoundsMin,worldBoundsMax); + + + ///one way to draw all the contact points is iterating over contact manifolds / points: + int numManifolds = collisionWorld->getDispatcher()->getNumManifolds(); + for (i=0;igetDispatcher()->getManifoldByIndexInternal(i); + btCollisionObject* obA = static_cast(contactManifold->getBody0()); + btCollisionObject* obB = static_cast(contactManifold->getBody1()); + contactManifold->refreshContactPoints(obA->getWorldTransform(),obB->getWorldTransform()); + + int numContacts = contactManifold->getNumContacts(); + for (int j=0;jgetContactPoint(j); + + glBegin(GL_LINES); + glColor3f(1, 1, 1); + + btVector3 ptA = pt.getPositionWorldOnA() - m_cameraPosition; + btVector3 ptB = pt.getPositionWorldOnB() - m_cameraPosition; + + glVertex3d(ptA.x(),ptA.y(),ptA.z()); + glVertex3d(ptB.x(),ptB.y(),ptB.z()); + glEnd(); + } + + //you can un-comment out this line, and then all points are removed + //contactManifold->clearManifold(); + } + + btScalar m[16]; + btTransform temp; + + + btVector3 color; + //int i; + for (i=0;idrawOpenGL(m,objects[i].getCollisionShape(),color,getDebugMode(),worldBoundsMin,worldBoundsMax); + } + + objects[1].getWorldTransform().setOrigin(objects[1].getWorldTransform().getOrigin()+btVector3(-VERY_SMALL_INCREMENT,-VERY_SMALL_INCREMENT,0)); + objects[0].getWorldTransform().setOrigin(objects[0].getWorldTransform().getOrigin()+btVector3(VERY_SMALL_INCREMENT,VERY_SMALL_INCREMENT,0)); + + float yStart = 20.f; + float yIncr = 20.f; + char buf[124]; + + glColor3f(0, 0, 0); + + setOrthographicProjection(); + + glRasterPos3f(10.0f,yStart,0); + #ifdef BT_USE_DOUBLE_PRECISION + GLDebugDrawString(10.f,yStart,"Double Precision Mode"); + #else + GLDebugDrawString(10.f,yStart,"Single Precision Mode"); + #endif + yStart += yIncr; + + glRasterPos3f(10.0f,yStart,0); + sprintf(buf,"Movement distance in x and y axis = %lf", VERY_SMALL_INCREMENT); + + GLDebugDrawString(10.f,yStart,buf); + yStart += yIncr; + + glRasterPos3f(10.0f,yStart,0); + btScalar xValue = objects[0].getWorldTransform().getOrigin().x(); + btScalar yValue = objects[0].getWorldTransform().getOrigin().y(); + btScalar zValue = objects[0].getWorldTransform().getOrigin().z(); + sprintf(buf,"Cube 0 location = ( %lf, %lf, %lf )", xValue, yValue, zValue); + GLDebugDrawString(10.f,yStart,buf); + yStart += yIncr; + + xValue = objects[1].getWorldTransform().getOrigin().x(); + yValue = objects[1].getWorldTransform().getOrigin().y(); + zValue = objects[1].getWorldTransform().getOrigin().z(); + glRasterPos3f(10.0f,yStart,0); + sprintf(buf,"Cube 1 location = ( %lf, %lf, %lf )", xValue, yValue, zValue); + GLDebugDrawString(10.f,yStart,buf); + yStart += yIncr; + + glRasterPos3f(10.0f,yStart,0); + GLDebugDrawString(10.f,yStart,"w=toggle wireframe/solid"); + + resetPerspectiveProjection(); + + glFlush(); + glutSwapBuffers(); +} + +void DoublePrecisionDemo::clientResetScene() +{ + objects[0].getWorldTransform().setOrigin(btVector3(LARGE_DISTANCE_FROM_ORIGIN,LARGE_DISTANCE_FROM_ORIGIN,LARGE_DISTANCE_FROM_ORIGIN)); + objects[1].getWorldTransform().setOrigin(btVector3(LARGE_DISTANCE_FROM_ORIGIN-VERY_SMALL_INCREMENT,LARGE_DISTANCE_FROM_ORIGIN-VERY_SMALL_INCREMENT,LARGE_DISTANCE_FROM_ORIGIN)); +} + + + +void DoublePrecisionDemo::updateCamera() +{ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + // look at the stationary cube + m_cameraTargetPosition = objects[0].getWorldTransform().getOrigin(); + + m_cameraPosition = m_cameraTargetPosition; + m_cameraPosition[2] = m_cameraTargetPosition[2] - m_cameraDistance; + + //update OpenGL camera settings + glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10000.0); + + // To not loose precision in the rendering process, we shift the object to the origin + gluLookAt(0.0, 0.0, 0.0, + m_cameraTargetPosition[0]-m_cameraPosition[0],m_cameraTargetPosition[1]-m_cameraPosition[1], m_cameraTargetPosition[2]-m_cameraPosition[2], + m_cameraUp.getX(),m_cameraUp.getY(),m_cameraUp.getZ()); + glMatrixMode(GL_MODELVIEW); +} + +void DoublePrecisionDemo::keyboardCallback(unsigned char key, int x, int y) +{ + if (key == 'w') + { + if (m_debugMode & btIDebugDraw::DBG_DrawWireframe) + { + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawWireframe); + m_debugMode |= btIDebugDraw::DBG_DrawAabb; + } + else + { + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawAabb); + m_debugMode |= btIDebugDraw::DBG_DrawWireframe; + } + return; + } + + DemoApplication::keyboardCallback(key, x, y); +} + + diff --git a/Demos/DoublePrecisionDemo/DoublePrecisionDemo.h b/Demos/DoublePrecisionDemo/DoublePrecisionDemo.h new file mode 100644 index 0000000..7de07fd --- /dev/null +++ b/Demos/DoublePrecisionDemo/DoublePrecisionDemo.h @@ -0,0 +1,41 @@ +/* +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 COLLISION_INTERFACE_DEMO_H +#define COLLISION_INTERFACE_DEMO_H + +#include "GlutDemoApplication.h" + +///DoublePrecisionDemo shows how to use the collision detection without dynamics (btCollisionWorld/CollisionObject) +class DoublePrecisionDemo : public GlutDemoApplication +{ + public: + + void initPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + virtual void clientResetScene(); + + virtual void updateCamera(); + + virtual void keyboardCallback(unsigned char key, int x, int y); + +}; + +#endif //COLLISION_INTERFACE_DEMO_H + + diff --git a/Demos/DynamicControlDemo/CMakeLists.txt b/Demos/DynamicControlDemo/CMakeLists.txt new file mode 100644 index 0000000..2fc7fda --- /dev/null +++ b/Demos/DynamicControlDemo/CMakeLists.txt @@ -0,0 +1,49 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppMotorDemo + MotorDemo.cpp + main.cpp +) + +IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppMotorDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppMotorDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF(WIN32) + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppMotorDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppMotorDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppMotorDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/DynamicControlDemo/MotorDemo.cpp b/Demos/DynamicControlDemo/MotorDemo.cpp new file mode 100644 index 0000000..ee2184e --- /dev/null +++ b/Demos/DynamicControlDemo/MotorDemo.cpp @@ -0,0 +1,468 @@ +/* +Bullet Continuous Collision Detection and Physics Library Copyright (c) 2007 Erwin Coumans +Motor Demo + +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 "GlutStuff.h" +#include "GL_ShapeDrawer.h" + +#include "LinearMath/btIDebugDraw.h" + +#include "GLDebugDrawer.h" +#include "MotorDemo.h" + + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923 +#endif + +#ifndef M_PI_4 +#define M_PI_4 0.785398163397448309616 +#endif + +#ifndef M_PI_8 +#define M_PI_8 0.5 * M_PI_4 +#endif + + +// LOCAL FUNCTIONS + +void vertex(btVector3 &v) +{ + glVertex3d(v.getX(), v.getY(), v.getZ()); +} + +void drawFrame(btTransform &tr) +{ + const float fSize = 1.f; + + glBegin(GL_LINES); + + // x + glColor3f(255.f,0,0); + btVector3 vX = tr*btVector3(fSize,0,0); + vertex(tr.getOrigin()); vertex(vX); + + // y + glColor3f(0,255.f,0); + btVector3 vY = tr*btVector3(0,fSize,0); + vertex(tr.getOrigin()); vertex(vY); + + // z + glColor3f(0,0,255.f); + btVector3 vZ = tr*btVector3(0,0,fSize); + vertex(tr.getOrigin()); vertex(vZ); + + glEnd(); +} + +// /LOCAL FUNCTIONS + + + +#define NUM_LEGS 6 +#define BODYPART_COUNT 2 * NUM_LEGS + 1 +#define JOINT_COUNT BODYPART_COUNT - 1 + +class TestRig +{ + btDynamicsWorld* m_ownerWorld; + btCollisionShape* m_shapes[BODYPART_COUNT]; + btRigidBody* m_bodies[BODYPART_COUNT]; + btTypedConstraint* m_joints[JOINT_COUNT]; + + btRigidBody* localCreateRigidBody (btScalar mass, const btTransform& startTransform, btCollisionShape* shape) + { + bool isDynamic = (mass != 0.f); + + btVector3 localInertia(0,0,0); + if (isDynamic) + shape->calculateLocalInertia(mass,localInertia); + + btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + m_ownerWorld->addRigidBody(body); + + return body; + } + + +public: + TestRig (btDynamicsWorld* ownerWorld, const btVector3& positionOffset, bool bFixed) + : m_ownerWorld (ownerWorld) + { + btVector3 vUp(0, 1, 0); + + // + // Setup geometry + // + float fBodySize = 0.25f; + float fLegLength = 0.45f; + float fForeLegLength = 0.75f; + m_shapes[0] = new btCapsuleShape(btScalar(fBodySize), btScalar(0.10)); + int i; + for ( i=0; isetDamping(0.05, 0.85); + m_bodies[i]->setDeactivationTime(0.8); + //m_bodies[i]->setSleepingThresholds(1.6, 2.5); + m_bodies[i]->setSleepingThresholds(0.5f, 0.5f); + } + + + // + // Setup the constraints + // + btHingeConstraint* hingeC; + //btConeTwistConstraint* coneC; + + btTransform localA, localB, localC; + + for ( i=0; igetWorldTransform().inverse() * m_bodies[0]->getWorldTransform() * localA; + hingeC = new btHingeConstraint(*m_bodies[0], *m_bodies[1+2*i], localA, localB); + hingeC->setLimit(btScalar(-0.75 * M_PI_4), btScalar(M_PI_8)); + //hingeC->setLimit(btScalar(-0.1), btScalar(0.1)); + m_joints[2*i] = hingeC; + m_ownerWorld->addConstraint(m_joints[2*i], true); + + // knee joints + localA.setIdentity(); localB.setIdentity(); localC.setIdentity(); + localA.getBasis().setEulerZYX(0,-fAngle,0); localA.setOrigin(btVector3(btScalar(fCos*(fBodySize+fLegLength)), btScalar(0.), btScalar(fSin*(fBodySize+fLegLength)))); + localB = m_bodies[1+2*i]->getWorldTransform().inverse() * m_bodies[0]->getWorldTransform() * localA; + localC = m_bodies[2+2*i]->getWorldTransform().inverse() * m_bodies[0]->getWorldTransform() * localA; + hingeC = new btHingeConstraint(*m_bodies[1+2*i], *m_bodies[2+2*i], localB, localC); + //hingeC->setLimit(btScalar(-0.01), btScalar(0.01)); + hingeC->setLimit(btScalar(-M_PI_8), btScalar(0.2)); + m_joints[1+2*i] = hingeC; + m_ownerWorld->addConstraint(m_joints[1+2*i], true); + } + } + + virtual ~TestRig () + { + int i; + + // Remove all constraints + for ( i = 0; i < JOINT_COUNT; ++i) + { + m_ownerWorld->removeConstraint(m_joints[i]); + delete m_joints[i]; m_joints[i] = 0; + } + + // Remove all bodies and shapes + for ( i = 0; i < BODYPART_COUNT; ++i) + { + m_ownerWorld->removeRigidBody(m_bodies[i]); + + delete m_bodies[i]->getMotionState(); + + delete m_bodies[i]; m_bodies[i] = 0; + delete m_shapes[i]; m_shapes[i] = 0; + } + } + + btTypedConstraint** GetJoints() {return &m_joints[0];} + +}; + + + +void motorPreTickCallback (btDynamicsWorld *world, btScalar timeStep) +{ + MotorDemo* motorDemo = (MotorDemo*)world->getWorldUserInfo(); + + motorDemo->setMotorTargets(timeStep); + +} + + + +void MotorDemo::initPhysics() +{ + setTexturing(true); + setShadows(true); + + // Setup the basic world + + m_Time = 0; + m_fCyclePeriod = 2000.f; // in milliseconds + +// m_fMuscleStrength = 0.05f; + // new SIMD solver for joints clips accumulated impulse, so the new limits for the motor + // should be (numberOfsolverIterations * oldLimits) + // currently solver uses 10 iterations, so: + m_fMuscleStrength = 0.5f; + + setCameraDistance(btScalar(5.)); + + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + + btVector3 worldAabbMin(-10000,-10000,-10000); + btVector3 worldAabbMax(10000,10000,10000); + m_broadphase = new btAxisSweep3 (worldAabbMin, worldAabbMax); + + m_solver = new btSequentialImpulseConstraintSolver; + + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + + m_dynamicsWorld->setInternalTickCallback(motorPreTickCallback,this,true); + + + // Setup a big ground box + { + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(200.),btScalar(10.),btScalar(200.))); + m_collisionShapes.push_back(groundShape); + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-10,0)); + localCreateRigidBody(btScalar(0.),groundTransform,groundShape); + } + + // Spawn one ragdoll + btVector3 startOffset(1,0.5,0); + spawnTestRig(startOffset, false); + startOffset.setValue(-2,0.5,0); + spawnTestRig(startOffset, true); + + clientResetScene(); +} + + +void MotorDemo::spawnTestRig(const btVector3& startOffset, bool bFixed) +{ + TestRig* rig = new TestRig(m_dynamicsWorld, startOffset, bFixed); + m_rigs.push_back(rig); +} + +void PreStep() +{ + +} + + + + +void MotorDemo::setMotorTargets(btScalar deltaTime) +{ + + float ms = deltaTime*1000000.; + float minFPS = 1000000.f/60.f; + if (ms > minFPS) + ms = minFPS; + + m_Time += ms; + + // + // set per-frame sinusoidal position targets using angular motor (hacky?) + // + for (int r=0; r(m_rigs[r]->GetJoints()[i]); + btScalar fCurAngle = hingeC->getHingeAngle(); + + btScalar fTargetPercent = (int(m_Time / 1000) % int(m_fCyclePeriod)) / m_fCyclePeriod; + btScalar fTargetAngle = 0.5 * (1 + sin(2 * M_PI * fTargetPercent)); + btScalar fTargetLimitAngle = hingeC->getLowerLimit() + fTargetAngle * (hingeC->getUpperLimit() - hingeC->getLowerLimit()); + btScalar fAngleError = fTargetLimitAngle - fCurAngle; + btScalar fDesiredAngularVel = 1000000.f * fAngleError/ms; + hingeC->enableAngularMotor(true, fDesiredAngularVel, m_fMuscleStrength); + } + } + + +} + +void MotorDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //simple dynamics world doesn't handle fixed-time-stepping + float deltaTime = getDeltaTimeMicroseconds()/1000000.f; + + + if (m_dynamicsWorld) + { + m_dynamicsWorld->stepSimulation(deltaTime); + m_dynamicsWorld->debugDrawWorld(); + } + + renderme(); + + for (int i=2; i>=0 ;i--) + { + btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i]; + btRigidBody* body = btRigidBody::upcast(obj); + drawFrame(body->getWorldTransform()); + } + + glFlush(); + + glutSwapBuffers(); +} + +void MotorDemo::displayCallback() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + renderme(); + + glFlush(); + glutSwapBuffers(); +} + +void MotorDemo::keyboardCallback(unsigned char key, int x, int y) +{ + switch (key) + { + case '+': case '=': + m_fCyclePeriod /= 1.1f; + if (m_fCyclePeriod < 1.f) + m_fCyclePeriod = 1.f; + break; + case '-': case '_': + m_fCyclePeriod *= 1.1f; + break; + case '[': + m_fMuscleStrength /= 1.1f; + break; + case ']': + m_fMuscleStrength *= 1.1f; + break; + default: + DemoApplication::keyboardCallback(key, x, y); + } +} + + + +void MotorDemo::exitPhysics() +{ + + int i; + + for (i=0;igetNumCollisionObjects()-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;j m_rigs; + + //keep the collision shapes, for deletion/cleanup + btAlignedObjectArray m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + +public: + void initPhysics(); + + void exitPhysics(); + + virtual ~MotorDemo() + { + exitPhysics(); + } + + void spawnTestRig(const btVector3& startOffset, bool bFixed); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + virtual void keyboardCallback(unsigned char key, int x, int y); + + static DemoApplication* Create() + { + MotorDemo* demo = new MotorDemo(); + demo->myinit(); + demo->initPhysics(); + return demo; + } + + void setMotorTargets(btScalar deltaTime); + +}; + + +#endif diff --git a/Demos/DynamicControlDemo/main.cpp b/Demos/DynamicControlDemo/main.cpp new file mode 100644 index 0000000..188c88d --- /dev/null +++ b/Demos/DynamicControlDemo/main.cpp @@ -0,0 +1,28 @@ +/* +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 "MotorDemo.h" +#include "GlutStuff.h" + +int main(int argc,char* argv[]) +{ + MotorDemo demoApp; + + demoApp.initPhysics(); + + + return glutmain(argc, argv,640,480,"Bullet Physics Demo. http://bullet.sf.net",&demoApp); +} diff --git a/Demos/EPAPenDepthDemo/PenetrationTestBullet.cpp b/Demos/EPAPenDepthDemo/PenetrationTestBullet.cpp new file mode 100644 index 0000000..319e01b --- /dev/null +++ b/Demos/EPAPenDepthDemo/PenetrationTestBullet.cpp @@ -0,0 +1,855 @@ + +///contribution by Pierre Terdiman to check penetration depth solvers +///see http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=638 + +#ifdef WIN32//for glut.h +#include +#endif + + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#else +#include +#endif + + +#include +#include +#include + +#define VERBOSE_TEXT_ONSCREEN 1 +#ifdef VERBOSE_TEXT_ONSCREEN +#include "GLDebugFont.h" +#endif + +#include "btBulletCollisionCommon.h" + +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" +#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" +#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "LinearMath/btStackAlloc.h" + +//We can use the Bullet EPA or sampling penetration depth solver, but comparison might be useful +//#define COMPARE_WITH_SOLID35_AND_OTHER_EPA 1 +#ifdef COMPARE_WITH_SOLID35_AND_OTHER_EPA +#include "../Extras/ExtraSolid35/Solid3EpaPenetrationDepth.h" +#include "../Extras/ExtraSolid35/Solid3JohnsonSimplexSolver.h" +#include "../Extras/EPA/EpaPenetrationDepthSolver.h" +#endif //COMPARE_WITH_SOLID35_AND_OTHER_EPA + +#define USE_ORIGINAL 1 +#ifndef USE_ORIGINAL +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" +#endif //USE_ORIGINAL + +static bool gRefMode = false; +static int gMethod = 0; +static int gLastUsedMethod = -1; +static int gNumGjkIterations = -1; +static int gLastDegenerateSimplex = -1; + +static const float gDisp = 0.01f; +static const float gCamSpeed = 0.1f; +static btVector3 Eye(3.0616338f, 1.1985892f, 2.5769043f); +static btVector3 Dir(-0.66853905,-0.14004262,-0.73037237); +static btVector3 N; +static int mx = 0; +static int my = 0; +static int glutScreenHeight = 512; +static int glutScreenWidth = 512; + +static void DrawLine(const btVector3& p0, const btVector3& p1, const btVector3& color, float line_width) +{ + glDisable(GL_LIGHTING); + glLineWidth(line_width); + glColor4f(color.x(), color.y(), color.z(), 1.0f); + btVector3 tmp[] = {p0, p1}; + glEnableClientState(GL_VERTEX_ARRAY); +#ifndef BT_USE_DOUBLE_PRECISION + glVertexPointer(3, GL_FLOAT, sizeof(btVector3), &tmp[0].x()); +#else + glVertexPointer(3, GL_DOUBLE, sizeof(btVector3), &tmp[0].x()); +#endif + glDrawArrays(GL_LINES, 0, 2); + glDisableClientState(GL_VERTEX_ARRAY); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glEnable(GL_LIGHTING); +} + +void DrawTriangle(const btVector3& p0, const btVector3& p1, const btVector3& p2, const btVector3& color) +{ +// glDisable(GL_LIGHTING); + glColor4f(color.x(), color.y(), color.z(), 1.0f); + btVector3 tmp[] = {p0, p1, p2}; + glEnableClientState(GL_VERTEX_ARRAY); +#ifndef BT_USE_DOUBLE_PRECISION + glVertexPointer(3, GL_FLOAT, sizeof(btVector3), &tmp[0].x()); +#else + glVertexPointer(3, GL_DOUBLE, sizeof(btVector3), &tmp[0].x()); +#endif + glDrawArrays(GL_TRIANGLES, 0, 3); + glDisableClientState(GL_VERTEX_ARRAY); +// glColor4f(1.0f, 1.0f, 1.0f, 1.0f); +// glEnable(GL_LIGHTING); +} + +class MyPoly +{ + public: + MyPoly() : mNbVerts(0), mIndices(NULL) {} + ~MyPoly() { delete[]mIndices; } + + short mNbVerts; + char* mIndices; + float mPlane[4]; +}; + +class MyConvex +{ + public: + MyConvex(); + ~MyConvex(); + + bool LoadFromFile(const char* filename); + void Render(bool only_wireframe, const btVector3& wire_color) const; + void Project(const btVector3& dir, float& min, float& max) const; + + int mNbVerts; + btVector3* mVerts; + int mNbPolys; + MyPoly* mPolys; + btTransform mTransform; +}; + +MyConvex::MyConvex() : + mNbVerts (0), + mVerts (NULL), + mNbPolys (0), + mPolys (NULL) +{ + mTransform.setIdentity(); +} + +MyConvex::~MyConvex() +{ + delete[]mPolys; + delete[]mVerts; +} + +bool MyConvex::LoadFromFile(const char* filename) +{ + FILE* fp = fopen(filename, "rb"); + if(!fp) return false; + + fread(&mNbVerts, sizeof(int), 1, fp); + + int i; + + mVerts = new btVector3[mNbVerts]; + for( i=0;i max) max = dp; + } + if(min>max) + { + float tmp = min; + min = max; + max = tmp; + } +} + +static btVector3 gNormal; +static btVector3 gPoint; +static float gDepth; + + struct MyResult : public btDiscreteCollisionDetectorInterface::Result + { + virtual void setShapeIdentifiersA(int partId0, int index0) + { + } + virtual void setShapeIdentifiersB(int partId1, int index1) + { + } + + virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth) + { + gNormal = normalOnBInWorld; + gPoint = pointInWorld; + gDepth = depth; + } + }; + +//2 Mb by default, could be made smaller +btStackAlloc gStackAlloc(1024*1024*2); + +static bool TestEPA(const MyConvex& hull0, const MyConvex& hull1) +{ + static btSimplexSolverInterface simplexSolver; +#ifdef COMPARE_WITH_SOLID35_AND_OTHER_EPA +// static Solid3JohnsonSimplexSolver simplexSolver2; +#endif //COMPARE_WITH_SOLID35_AND_OTHER_EPA + + simplexSolver.reset(); + + btConvexHullShape convexA((btScalar*)hull0.mVerts, hull0.mNbVerts, sizeof(btVector3)); + btConvexHullShape convexB((btScalar*)hull1.mVerts, hull1.mNbVerts, sizeof(btVector3)); + + static btGjkEpaPenetrationDepthSolver Solver0; + static btMinkowskiPenetrationDepthSolver Solver1; + +#ifdef COMPARE_WITH_SOLID35_AND_OTHER_EPA + static Solid3EpaPenetrationDepth Solver2; + static EpaPenetrationDepthSolver Solver3; +#endif + + + btConvexPenetrationDepthSolver* Solver = NULL ; + if(gMethod==0) + Solver = &Solver0; + else if(gMethod==1) + Solver = &Solver1; +#ifdef COMPARE_WITH_SOLID35_AND_OTHER_EPA + else if(gMethod==2) + Solver = &Solver2; + else + Solver = &Solver3; +#endif //COMPARE_WITH_SOLID35_AND_OTHER_EPA + + +#ifdef USE_ORIGINAL + + btGjkPairDetector GJK(&convexA, &convexB, &simplexSolver, Solver); + GJK.m_catchDegeneracies = 1; + convexA.setMargin(0.01f); + convexB.setMargin(0.01f); + + btDiscreteCollisionDetectorInterface::ClosestPointInput input; + input.m_transformA = hull0.mTransform; + input.m_transformB = hull1.mTransform; + input.m_stackAlloc = &gStackAlloc; + + MyResult output; + GJK.getClosestPoints(input, output, 0); + gLastUsedMethod = GJK.m_lastUsedMethod; + gNumGjkIterations = GJK.m_curIter; + gLastDegenerateSimplex= GJK.m_degenerateSimplex; +#else + MyResult output; + btVector3 witnesses[2]; + btVector3 normal; + btScalar depth; + + btGjkEpaSolver::sResults results; + btScalar radialMargin = 0.01f; + + btGjkEpaSolver::Collide(&convexA,hull0.mTransform, + &convexB,hull1.mTransform, + radialMargin, + results); + if (results.depth>0) + { + output.addContactPoint(results.normal,results.witnesses[1],-results.depth); + } +#endif + return true; +} + +static bool TestSepAxis(const btVector3& sep_axis, const MyConvex& hull0, const MyConvex& hull1, float& depth) +{ + float Min0,Max0; + float Min1,Max1; + hull0.Project(sep_axis, Min0, Max0); + hull1.Project(sep_axis, Min1, Max1); + + if(Max0=0.0f); + float d1 = Max1 - Min0; + assert(d1>=0.0f); + depth = d01e-6 || fabsf(v.y())>1e-6 || fabsf(v.z())>1e-6) return false; + return true; +} + +static bool ReferenceCode(const MyConvex& hull0, const MyConvex& hull1, float& dmin, btVector3& sep) +{ + dmin = FLT_MAX; + + int i; + + // Test normals from hull0 + for( i=0;i0.0f) sep = -sep; + + return true; +} + + + +static MyConvex gConvex0; +static MyConvex gConvex1; + +static void KeyboardCallback(unsigned char key, int x, int y) +{ + switch (key) + { + case 27: exit(0); break; + + case 'R': + case 'r': + gRefMode = !gRefMode; + break; + + case ' ': + gMethod++; +#ifdef COMPARE_WITH_SOLID35_AND_OTHER_EPA + if(gMethod==4) gMethod=0; +#else + if(gMethod==2) gMethod=0; +#endif + break; + + case '4': + gConvex0.mTransform.setOrigin(gConvex0.mTransform.getOrigin() + btVector3(-gDisp,0,0)); + break; + case '7': + gConvex0.mTransform.setRotation(gConvex0.mTransform.getRotation()*btQuaternion(btVector3(1,0,0),0.01)); + break; + case '9': + gConvex0.mTransform.setRotation(gConvex0.mTransform.getRotation()*btQuaternion(btVector3(1,0,0),-0.01)); + break; + case '1': + gConvex0.mTransform.setRotation(gConvex0.mTransform.getRotation()*btQuaternion(btVector3(0,1,0),0.01)); + break; + case '3': + gConvex0.mTransform.setRotation(gConvex0.mTransform.getRotation()*btQuaternion(btVector3(0,1,0),-0.01)); + break; + case '5': + gConvex0.mTransform.setRotation(gConvex0.mTransform.getRotation()*btQuaternion(btVector3(0,0,1),0.01)); + break; + + case '6': + gConvex0.mTransform.setOrigin(gConvex0.mTransform.getOrigin() + btVector3(gDisp,0,0)); + break; + case '8': + gConvex0.mTransform.setOrigin(gConvex0.mTransform.getOrigin() + btVector3(0,gDisp,0)); + break; + case '2': + gConvex0.mTransform.setOrigin(gConvex0.mTransform.getOrigin() + btVector3(0,-gDisp,0)); + break; + + case 101: Eye += Dir * gCamSpeed; break; + case 103: Eye -= Dir * gCamSpeed; break; + case 100: Eye -= N * gCamSpeed; break; + case 102: Eye += N * gCamSpeed; break; + } +} + +static void ArrowKeyCallback(int key, int x, int y) +{ + KeyboardCallback(key,x,y); +} + +static void MouseCallback(int button, int state, int x, int y) +{ + mx = x; + my = y; +} + +static const float NxPiF32 = 3.141592653589793f; + +float degToRad(float a) + { + return (float)0.01745329251994329547 * a; + } + +class NxQuat + { + public: + NxQuat(){} + + NxQuat(const float angle, const btVector3 & axis) + { + x = axis.x(); + y = axis.y(); + z = axis.z(); + + const float i_length = 1.0f / sqrtf( x*x + y*y + z*z ); + x = x * i_length; + y = y * i_length; + z = z * i_length; + + float Half = degToRad(angle * 0.5f); + + w = cosf(Half); + const float sin_theta_over_two = sinf(Half ); + x = x * sin_theta_over_two; + y = y * sin_theta_over_two; + z = z * sin_theta_over_two; + } + + void multiply(const NxQuat& left, const btVector3& right) + { + float a,b,c,d; + + a = - left.x*right.x() - left.y*right.y() - left.z *right.z(); + b = left.w*right.x() + left.y*right.z() - right.y()*left.z; + c = left.w*right.y() + left.z*right.x() - right.z()*left.x; + d = left.w*right.z() + left.x*right.y() - right.x()*left.y; + + w = a; + x = b; + y = c; + z = d; + } + + void rotate(btVector3 & v) const + { + NxQuat myInverse; + myInverse.x = -x; + myInverse.y = -y; + myInverse.z = -z; + myInverse.w = w; + + NxQuat left; + left.multiply(*this,v); + float vx = left.w*myInverse.x + myInverse.w*left.x + left.y*myInverse.z - myInverse.y*left.z; + float vy = left.w*myInverse.y + myInverse.w*left.y + left.z*myInverse.x - myInverse.z*left.x; + float vz = left.w*myInverse.z + myInverse.w*left.z + left.x*myInverse.y - myInverse.x*left.y; + v.setValue(vx, vy, vz); + } + + float x,y,z,w; +}; + + +static void MotionCallback(int x, int y) +{ + int dx = mx - x; + int dy = my - y; + + Dir = Dir.normalize(); + N = Dir.cross(btVector3(0,1,0)); + + NxQuat qx(NxPiF32 * dx * 20/ 180.0f, btVector3(0,1,0)); + qx.rotate(Dir); + NxQuat qy(NxPiF32 * dy * 20/ 180.0f, N); + qy.rotate(Dir); + + mx = x; + my = y; +} + +static void RenderCallback() +{ + // Clear buffers + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Setup camera + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(60.0f, ((float)glutGet(GLUT_WINDOW_WIDTH))/((float)glutGet(GLUT_WINDOW_HEIGHT)), 1.0f, 10000.0f); + gluLookAt(Eye.x(), Eye.y(), Eye.z(), Eye.x() + Dir.x(), Eye.y() + Dir.y(), Eye.z() + Dir.z(), 0.0f, 1.0f, 0.0f); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glEnable(GL_LIGHTING); + + //clear previous frames result + gNormal.setValue(10,0,0); + gPoint.setValue(0,0,0); + gDepth = 999.999; + gLastUsedMethod = -1; + gNumGjkIterations = -1; + + + TestEPA(gConvex0, gConvex1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + btVector3 RefSep(btScalar(0.), btScalar(0.), btScalar(0.)); + float RefDMin=0.f; + bool RefResult = false; + if(gRefMode) + RefResult = ReferenceCode(gConvex0, gConvex1, RefDMin, RefSep); + +// DrawLine(gPoint, gPoint + gNormal*20.0f, btVector3(1,0,0), 2.0f); +// printf("%f: %f %f %f\n", gDepth, gNormal.x(), gNormal.y(), gNormal.z()); + +#ifdef VERBOSE_TEXT_ONSCREEN + glColor3f(255.f, 255.f, 255.f); + + setOrthographicProjection(); + float xOffset = 10.f; + float yStart = 20.f; + float yIncr = 20.f; + char buf[124]; + + sprintf(buf,"gDepth=%f: gNormal=(%f %f %f)\n", gDepth, gNormal.x(), gNormal.y(), gNormal.z()); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + sprintf(buf,"num GJK iterations =%d\n", gNumGjkIterations); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + sprintf(buf,"gLastUsedMethod=%d\n", gLastUsedMethod); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + + + + if (gLastUsedMethod >= 3) + { + switch ( gMethod) + { + case 0: + sprintf(buf,"Bullet GjkEpa Penetration depth solver (zlib free\n" ); + break; + case 1: + sprintf(buf,"Bullet Minkowski sampling Penetration depth solver\n" ); + break; + case 2: + sprintf(buf,"Solid35 EPA Penetration depth solver\n" ); + break; + case 3: + sprintf(buf,"EPA Penetration depth solver (Experimental/WorkInProgress, zlib free\n" ); + break; + default: + sprintf(buf,"Unknown Penetration Depth\n" ); + } + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + } else + { + sprintf(buf,"Hybrid GJK method %d\n", gLastUsedMethod); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + } + + if (gLastDegenerateSimplex) + { + sprintf(buf,"DegenerateSimplex %d\n", gLastDegenerateSimplex); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + } + + + + + resetPerspectiveProjection(); +#endif //VERBOSE_TEXT_ONSCREEN + + btVector3 color(0,0,0); + gConvex0.Render(false, color); + gConvex1.Render(false, color); + + if(gDepth<0.0f) + { + btTransform Saved = gConvex0.mTransform; + gConvex0.mTransform.setOrigin(gConvex0.mTransform.getOrigin() - btVector3(gNormal*gDepth)); + gConvex0.Render(true, btVector3(1.0f, 0.5f, 0.0f)); + gConvex0.mTransform = Saved; + } + else + { + DrawLine(gPoint, gPoint + gNormal, btVector3(0,1,0), 2.0f); + } + + if(RefResult & gRefMode) + { + btTransform Saved = gConvex0.mTransform; + gConvex0.mTransform.setOrigin(gConvex0.mTransform.getOrigin() + btVector3(RefSep*RefDMin)); + gConvex0.Render(true, btVector3(0.0f, 0.5f, 1.0f)); + gConvex0.mTransform = Saved; + } + + glutSwapBuffers(); +} + +static void ReshapeCallback(int width, int height) +{ + glViewport(0, 0, width, height); +} + +static void IdleCallback() +{ + glutPostRedisplay(); +} + +int main(int argc, char** argv) +{ + // Initialize Glut + glutInit(&argc, argv); + glutInitWindowSize(glutScreenWidth, glutScreenHeight); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); + int mainHandle = glutCreateWindow("TestBullet"); + glutSetWindow(mainHandle); + glutDisplayFunc(RenderCallback); + glutReshapeFunc(ReshapeCallback); + glutIdleFunc(IdleCallback); + glutKeyboardFunc(KeyboardCallback); + glutSpecialFunc(ArrowKeyCallback); + glutMouseFunc(MouseCallback); + glutMotionFunc(MotionCallback); + MotionCallback(0,0); + + // Setup default render states + glClearColor(0.3f, 0.4f, 0.5f, 1.0); + glEnable(GL_DEPTH_TEST); + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_CULL_FACE); + + // Setup lighting + glEnable(GL_LIGHTING); + float AmbientColor[] = { 0.0f, 0.1f, 0.2f, 0.0f }; glLightfv(GL_LIGHT0, GL_AMBIENT, AmbientColor); + float DiffuseColor[] = { 1.0f, 1.0f, 1.0f, 0.0f }; glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseColor); + float SpecularColor[] = { 0.0f, 0.0f, 0.0f, 0.0f }; glLightfv(GL_LIGHT0, GL_SPECULAR, SpecularColor); + float Position[] = { -10.0f, 1000.0f, -4.0f, 1.0f }; glLightfv(GL_LIGHT0, GL_POSITION, Position); + glEnable(GL_LIGHT0); + + // + bool Status = gConvex0.LoadFromFile("convex0.bin"); + if(!Status) + { + Status = gConvex0.LoadFromFile("../../convex0.bin"); + if(!Status) + { + printf("Failed to load object!\n"); + exit(0); + } + } + Status = gConvex1.LoadFromFile("convex0.bin"); + if(!Status) + { + Status = gConvex1.LoadFromFile("../../convex0.bin"); + if(!Status) + { + printf("Failed to load object!\n"); + exit(0); + } + } + +// gConvex0.mTransform.setOrigin(btVector3(1.0f, 1.0f, 0.0f)); + gConvex0.mTransform.setOrigin(btVector3(0.20000069f, 0.95000005f, 0.0f)); + + // Run + glutMainLoop(); + + return 0; +} diff --git a/Demos/ForkLiftDemo/CMakeLists.txt b/Demos/ForkLiftDemo/CMakeLists.txt new file mode 100644 index 0000000..f0c5667 --- /dev/null +++ b/Demos/ForkLiftDemo/CMakeLists.txt @@ -0,0 +1,59 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# This is the variable for Windows. I use this to define the root of my directory structure. +SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/Glut) + +# You shouldn't have to modify anything below this line +######################################################## + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +IF (WIN32) + ADD_EXECUTABLE(AppForkLiftDemo + ForkLiftDemo.cpp + main.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) + + IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppForkLiftDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppForkLiftDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ENDIF(WIN32) + +ELSE() + ADD_EXECUTABLE(AppForkLiftDemo + ForkLiftDemo.cpp + main.cpp + ) +ENDIF() + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppForkLiftDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppForkLiftDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppForkLiftDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/ForkLiftDemo/ForkLiftDemo.cpp b/Demos/ForkLiftDemo/ForkLiftDemo.cpp new file mode 100644 index 0000000..cc761d9 --- /dev/null +++ b/Demos/ForkLiftDemo/ForkLiftDemo.cpp @@ -0,0 +1,865 @@ +/* +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. +*/ + +///September 2006: VehicleDemo is work in progress, this file is mostly just a placeholder +///This VehicleDemo file is very early in development, please check it later +///@todo is a basic engine model: +///A function that maps user input (throttle) into torque/force applied on the wheels +///with gears etc. +#include "btBulletDynamicsCommon.h" +#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h" +#include "GLDebugFont.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923 +#endif + +#ifndef M_PI_4 +#define M_PI_4 0.785398163397448309616 +#endif + +//#define LIFT_EPS 0.0000001f +// +// By default, Bullet Vehicle uses Y as up axis. +// You can override the up axis, for example Z-axis up. Enable this define to see how to: +//#define FORCE_ZAXIS_UP 1 +// + +#ifdef FORCE_ZAXIS_UP + int rightIndex = 0; + int upIndex = 2; + int forwardIndex = 1; + btVector3 wheelDirectionCS0(0,0,-1); + btVector3 wheelAxleCS(1,0,0); +#else + int rightIndex = 0; + int upIndex = 1; + int forwardIndex = 2; + btVector3 wheelDirectionCS0(0,-1,0); + btVector3 wheelAxleCS(-1,0,0); +#endif + +#include "GLDebugDrawer.h" +#include //printf debugging + +#include "GL_ShapeDrawer.h" + +#include "GlutStuff.h" +#include "ForkLiftDemo.h" + + +const int maxProxies = 32766; +const int maxOverlap = 65535; + +///btRaycastVehicle is the interface for the constraint that implements the raycast vehicle +///notice that for higher-quality slow-moving vehicles, another approach might be better +///implementing explicit hinged-wheel constraints with cylinder collision, rather then raycasts +float gEngineForce = 0.f; + +float defaultBreakingForce = 10.f; +float gBreakingForce = 100.f; + +float maxEngineForce = 1000.f;//this should be engine/velocity dependent +float maxBreakingForce = 100.f; + +float gVehicleSteering = 0.f; +float steeringIncrement = 0.04f; +float steeringClamp = 0.3f; +float wheelRadius = 0.5f; +float wheelWidth = 0.4f; +float wheelFriction = 1000;//BT_LARGE_FLOAT; +float suspensionStiffness = 20.f; +float suspensionDamping = 2.3f; +float suspensionCompression = 4.4f; +float rollInfluence = 0.1f;//1.0f; + + +btScalar suspensionRestLength(0.6); + +#define CUBE_HALF_EXTENTS 1 + + + +//////////////////////////////////// + + + + +ForkLiftDemo::ForkLiftDemo() +: +m_carChassis(0), +m_liftBody(0), +m_forkBody(0), +m_loadBody(0), +m_cameraHeight(4.f), +m_minCameraDistance(3.f), +m_maxCameraDistance(10.f), +m_indexVertexArrays(0), +m_vertices(0) +{ + m_vehicle = 0; + m_wheelShape = 0; + m_cameraPosition = btVector3(30,30,30); + m_useDefaultCamera = false; + setTexturing(true); + setShadows(true); + +} + + +void ForkLiftDemo::termPhysics() +{ + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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()) + { + + while (body->getNumConstraintRefs()) + { + btTypedConstraint* constraint = body->getConstraintRef(0); + m_dynamicsWorld->removeConstraint(constraint); + delete constraint; + } + delete body->getMotionState(); + m_dynamicsWorld->removeRigidBody(body); + } else + { + m_dynamicsWorld->removeCollisionObject( obj ); + } + delete obj; + } + + //delete collision shapes + for (int j=0;jsetGravity(btVector3(0,0,-10)); +#endif + + //m_dynamicsWorld->setGravity(btVector3(0,0,0)); +btTransform tr; +tr.setIdentity(); +tr.setOrigin(btVector3(0,-10,0)); + +//either use heightfield or triangle mesh + + + //create ground object + localCreateRigidBody(0,tr,groundShape); + +#ifdef FORCE_ZAXIS_UP +// indexRightAxis = 0; +// indexUpAxis = 2; +// indexForwardAxis = 1; + btCollisionShape* chassisShape = new btBoxShape(btVector3(1.f,2.f, 0.5f)); + btCompoundShape* compound = new btCompoundShape(); + btTransform localTrans; + localTrans.setIdentity(); + //localTrans effectively shifts the center of mass with respect to the chassis + localTrans.setOrigin(btVector3(0,0,1)); +#else + btCollisionShape* chassisShape = new btBoxShape(btVector3(1.f,0.5f,2.f)); + m_collisionShapes.push_back(chassisShape); + + btCompoundShape* compound = new btCompoundShape(); + m_collisionShapes.push_back(compound); + btTransform localTrans; + localTrans.setIdentity(); + //localTrans effectively shifts the center of mass with respect to the chassis + localTrans.setOrigin(btVector3(0,1,0)); +#endif + + compound->addChildShape(localTrans,chassisShape); + + { + btCollisionShape* suppShape = new btBoxShape(btVector3(0.5f,0.1f,0.5f)); + btTransform suppLocalTrans; + suppLocalTrans.setIdentity(); + //localTrans effectively shifts the center of mass with respect to the chassis + suppLocalTrans.setOrigin(btVector3(0,1.0,2.5)); + compound->addChildShape(suppLocalTrans, suppShape); + } + + tr.setOrigin(btVector3(0,0.f,0)); + + m_carChassis = localCreateRigidBody(800,tr,compound);//chassisShape); + //m_carChassis->setDamping(0.2,0.2); + + m_wheelShape = new btCylinderShapeX(btVector3(wheelWidth,wheelRadius,wheelRadius)); + + { + btCollisionShape* liftShape = new btBoxShape(btVector3(0.5f,2.0f,0.05f)); + m_collisionShapes.push_back(liftShape); + btTransform liftTrans; + m_liftStartPos = btVector3(0.0f, 2.5f, 3.05f); + liftTrans.setIdentity(); + liftTrans.setOrigin(m_liftStartPos); + m_liftBody = localCreateRigidBody(10,liftTrans, liftShape); + + btTransform localA, localB; + localA.setIdentity(); + localB.setIdentity(); + localA.getBasis().setEulerZYX(0, M_PI_2, 0); + localA.setOrigin(btVector3(0.0, 1.0, 3.05)); + localB.getBasis().setEulerZYX(0, M_PI_2, 0); + localB.setOrigin(btVector3(0.0, -1.5, -0.05)); + m_liftHinge = new btHingeConstraint(*m_carChassis,*m_liftBody, localA, localB); +// m_liftHinge->setLimit(-LIFT_EPS, LIFT_EPS); + m_liftHinge->setLimit(0.0f, 0.0f); + m_dynamicsWorld->addConstraint(m_liftHinge, true); + + btCollisionShape* forkShapeA = new btBoxShape(btVector3(1.0f,0.1f,0.1f)); + m_collisionShapes.push_back(forkShapeA); + btCompoundShape* forkCompound = new btCompoundShape(); + m_collisionShapes.push_back(forkCompound); + btTransform forkLocalTrans; + forkLocalTrans.setIdentity(); + forkCompound->addChildShape(forkLocalTrans, forkShapeA); + + btCollisionShape* forkShapeB = new btBoxShape(btVector3(0.1f,0.02f,0.6f)); + m_collisionShapes.push_back(forkShapeB); + forkLocalTrans.setIdentity(); + forkLocalTrans.setOrigin(btVector3(-0.9f, -0.08f, 0.7f)); + forkCompound->addChildShape(forkLocalTrans, forkShapeB); + + btCollisionShape* forkShapeC = new btBoxShape(btVector3(0.1f,0.02f,0.6f)); + m_collisionShapes.push_back(forkShapeC); + forkLocalTrans.setIdentity(); + forkLocalTrans.setOrigin(btVector3(0.9f, -0.08f, 0.7f)); + forkCompound->addChildShape(forkLocalTrans, forkShapeC); + + btTransform forkTrans; + m_forkStartPos = btVector3(0.0f, 0.6f, 3.2f); + forkTrans.setIdentity(); + forkTrans.setOrigin(m_forkStartPos); + m_forkBody = localCreateRigidBody(5, forkTrans, forkCompound); + + localA.setIdentity(); + localB.setIdentity(); + localA.getBasis().setEulerZYX(0, 0, M_PI_2); + localA.setOrigin(btVector3(0.0f, -1.9f, 0.05f)); + localB.getBasis().setEulerZYX(0, 0, M_PI_2); + localB.setOrigin(btVector3(0.0, 0.0, -0.1)); + m_forkSlider = new btSliderConstraint(*m_liftBody, *m_forkBody, localA, localB, true); + m_forkSlider->setLowerLinLimit(0.1f); + m_forkSlider->setUpperLinLimit(0.1f); +// m_forkSlider->setLowerAngLimit(-LIFT_EPS); +// m_forkSlider->setUpperAngLimit(LIFT_EPS); + m_forkSlider->setLowerAngLimit(0.0f); + m_forkSlider->setUpperAngLimit(0.0f); + m_dynamicsWorld->addConstraint(m_forkSlider, true); + + + btCompoundShape* loadCompound = new btCompoundShape(); + m_collisionShapes.push_back(loadCompound); + btCollisionShape* loadShapeA = new btBoxShape(btVector3(2.0f,0.5f,0.5f)); + m_collisionShapes.push_back(loadShapeA); + btTransform loadTrans; + loadTrans.setIdentity(); + loadCompound->addChildShape(loadTrans, loadShapeA); + btCollisionShape* loadShapeB = new btBoxShape(btVector3(0.1f,1.0f,1.0f)); + m_collisionShapes.push_back(loadShapeB); + loadTrans.setIdentity(); + loadTrans.setOrigin(btVector3(2.1f, 0.0f, 0.0f)); + loadCompound->addChildShape(loadTrans, loadShapeB); + btCollisionShape* loadShapeC = new btBoxShape(btVector3(0.1f,1.0f,1.0f)); + m_collisionShapes.push_back(loadShapeC); + loadTrans.setIdentity(); + loadTrans.setOrigin(btVector3(-2.1f, 0.0f, 0.0f)); + loadCompound->addChildShape(loadTrans, loadShapeC); + loadTrans.setIdentity(); + m_loadStartPos = btVector3(0.0f, -3.5f, 7.0f); + loadTrans.setOrigin(m_loadStartPos); + m_loadBody = localCreateRigidBody(4, loadTrans, loadCompound); + } + + + + clientResetScene(); + + /// create vehicle + { + + m_vehicleRayCaster = new btDefaultVehicleRaycaster(m_dynamicsWorld); + m_vehicle = new btRaycastVehicle(m_tuning,m_carChassis,m_vehicleRayCaster); + + ///never deactivate the vehicle + m_carChassis->setActivationState(DISABLE_DEACTIVATION); + + m_dynamicsWorld->addVehicle(m_vehicle); + + float connectionHeight = 1.2f; + + + bool isFrontWheel=true; + + //choose coordinate system + m_vehicle->setCoordinateSystem(rightIndex,upIndex,forwardIndex); + +#ifdef FORCE_ZAXIS_UP + btVector3 connectionPointCS0(CUBE_HALF_EXTENTS-(0.3*wheelWidth),2*CUBE_HALF_EXTENTS-wheelRadius, connectionHeight); +#else + btVector3 connectionPointCS0(CUBE_HALF_EXTENTS-(0.3*wheelWidth),connectionHeight,2*CUBE_HALF_EXTENTS-wheelRadius); +#endif + + m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel); +#ifdef FORCE_ZAXIS_UP + connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),2*CUBE_HALF_EXTENTS-wheelRadius, connectionHeight); +#else + connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),connectionHeight,2*CUBE_HALF_EXTENTS-wheelRadius); +#endif + + m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel); +#ifdef FORCE_ZAXIS_UP + connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),-2*CUBE_HALF_EXTENTS+wheelRadius, connectionHeight); +#else + connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),connectionHeight,-2*CUBE_HALF_EXTENTS+wheelRadius); +#endif //FORCE_ZAXIS_UP + isFrontWheel = false; + m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel); +#ifdef FORCE_ZAXIS_UP + connectionPointCS0 = btVector3(CUBE_HALF_EXTENTS-(0.3*wheelWidth),-2*CUBE_HALF_EXTENTS+wheelRadius, connectionHeight); +#else + connectionPointCS0 = btVector3(CUBE_HALF_EXTENTS-(0.3*wheelWidth),connectionHeight,-2*CUBE_HALF_EXTENTS+wheelRadius); +#endif + m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel); + + for (int i=0;igetNumWheels();i++) + { + btWheelInfo& wheel = m_vehicle->getWheelInfo(i); + wheel.m_suspensionStiffness = suspensionStiffness; + wheel.m_wheelsDampingRelaxation = suspensionDamping; + wheel.m_wheelsDampingCompression = suspensionCompression; + wheel.m_frictionSlip = wheelFriction; + wheel.m_rollInfluence = rollInfluence; + } + } + + + setCameraDistance(26.f); + +} + + +//to be implemented by the demo +void ForkLiftDemo::renderme() +{ + + updateCamera(); + + btScalar m[16]; + int i; + + btVector3 wheelColor(1,0,0); + + btVector3 worldBoundsMin,worldBoundsMax; + getDynamicsWorld()->getBroadphase()->getBroadphaseAabb(worldBoundsMin,worldBoundsMax); + + + + for (i=0;igetNumWheels();i++) + { + //synchronize the wheels with the (interpolated) chassis worldtransform + m_vehicle->updateWheelTransform(i,true); + //draw wheels (cylinders) + m_vehicle->getWheelInfo(i).m_worldTransform.getOpenGLMatrix(m); + m_shapeDrawer->drawOpenGL(m,m_wheelShape,wheelColor,getDebugMode(),worldBoundsMin,worldBoundsMax); + } + + + int lineWidth=250; + int xStart = m_glutScreenWidth - lineWidth; + int yStart = 20; + + if((getDebugMode() & btIDebugDraw::DBG_NoHelpText)==0) + { + setOrthographicProjection(); + glDisable(GL_LIGHTING); + glColor3f(0, 0, 0); + char buf[124]; + + glRasterPos3f(xStart, yStart, 0); + sprintf(buf,"SHIFT+Cursor Left/Right - rotate lift"); + GLDebugDrawString(xStart,20,buf); + yStart+=20; + glRasterPos3f(xStart, yStart, 0); + sprintf(buf,"SHIFT+Cursor UP/Down - move fork up/down"); + yStart+=20; + GLDebugDrawString(xStart,yStart,buf); + glRasterPos3f(xStart, yStart, 0); + sprintf(buf,"F5 - toggle camera mode"); + yStart+=20; + GLDebugDrawString(xStart,yStart,buf); + glRasterPos3f(xStart, yStart, 0); + sprintf(buf,"Click inside this window for keyboard focus"); + yStart+=20; + GLDebugDrawString(xStart,yStart,buf); + + + resetPerspectiveProjection(); + glEnable(GL_LIGHTING); + } + DemoApplication::renderme(); +} + +void ForkLiftDemo::clientMoveAndDisplay() +{ + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + + { + int wheelIndex = 2; + m_vehicle->applyEngineForce(gEngineForce,wheelIndex); + m_vehicle->setBrake(gBreakingForce,wheelIndex); + wheelIndex = 3; + m_vehicle->applyEngineForce(gEngineForce,wheelIndex); + m_vehicle->setBrake(gBreakingForce,wheelIndex); + + + wheelIndex = 0; + m_vehicle->setSteeringValue(gVehicleSteering,wheelIndex); + wheelIndex = 1; + m_vehicle->setSteeringValue(gVehicleSteering,wheelIndex); + + } + + + float dt = getDeltaTimeMicroseconds() * 0.000001f; + + if (m_dynamicsWorld) + { + //during idle mode, just run 1 simulation step maximum + int maxSimSubSteps = m_idle ? 1 : 2; + if (m_idle) + dt = 1.0/420.f; + + int numSimSteps = m_dynamicsWorld->stepSimulation(dt,maxSimSubSteps); + + +//#define VERBOSE_FEEDBACK +#ifdef VERBOSE_FEEDBACK + if (!numSimSteps) + printf("Interpolated transforms\n"); + else + { + if (numSimSteps > maxSimSubSteps) + { + //detect dropping frames + printf("Dropped (%i) simulation steps out of %i\n",numSimSteps - maxSimSubSteps,numSimSteps); + } else + { + printf("Simulated (%i) steps\n",numSimSteps); + } + } +#endif //VERBOSE_FEEDBACK + + } + + + + + + + +#ifdef USE_QUICKPROF + btProfiler::beginBlock("render"); +#endif //USE_QUICKPROF + + + renderme(); + + //optional but useful: debug drawing + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + +#ifdef USE_QUICKPROF + btProfiler::endBlock("render"); +#endif + + + glFlush(); + glutSwapBuffers(); + +} + + + +void ForkLiftDemo::displayCallback(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + +//optional but useful: debug drawing + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + glFlush(); + glutSwapBuffers(); +} + + + +void ForkLiftDemo::clientResetScene() +{ + gVehicleSteering = 0.f; + gBreakingForce = defaultBreakingForce; + gEngineForce = 0.f; + + m_carChassis->setCenterOfMassTransform(btTransform::getIdentity()); + m_carChassis->setLinearVelocity(btVector3(0,0,0)); + m_carChassis->setAngularVelocity(btVector3(0,0,0)); + m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_carChassis->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher()); + if (m_vehicle) + { + m_vehicle->resetSuspension(); + for (int i=0;igetNumWheels();i++) + { + //synchronize the wheels with the (interpolated) chassis worldtransform + m_vehicle->updateWheelTransform(i,true); + } + } + btTransform liftTrans; + liftTrans.setIdentity(); + liftTrans.setOrigin(m_liftStartPos); + m_liftBody->activate(); + m_liftBody->setCenterOfMassTransform(liftTrans); + m_liftBody->setLinearVelocity(btVector3(0,0,0)); + m_liftBody->setAngularVelocity(btVector3(0,0,0)); + + btTransform forkTrans; + forkTrans.setIdentity(); + forkTrans.setOrigin(m_forkStartPos); + m_forkBody->activate(); + m_forkBody->setCenterOfMassTransform(forkTrans); + m_forkBody->setLinearVelocity(btVector3(0,0,0)); + m_forkBody->setAngularVelocity(btVector3(0,0,0)); + +// m_liftHinge->setLimit(-LIFT_EPS, LIFT_EPS); + m_liftHinge->setLimit(0.0f, 0.0f); + m_liftHinge->enableAngularMotor(false, 0, 0); + + + m_forkSlider->setLowerLinLimit(0.1f); + m_forkSlider->setUpperLinLimit(0.1f); + m_forkSlider->setPoweredLinMotor(false); + + btTransform loadTrans; + loadTrans.setIdentity(); + loadTrans.setOrigin(m_loadStartPos); + m_loadBody->activate(); + m_loadBody->setCenterOfMassTransform(loadTrans); + m_loadBody->setLinearVelocity(btVector3(0,0,0)); + m_loadBody->setAngularVelocity(btVector3(0,0,0)); + +} + + + +void ForkLiftDemo::specialKeyboardUp(int key, int x, int y) +{ + switch (key) + { + case GLUT_KEY_UP : + { + lockForkSlider(); + gEngineForce = 0.f; + gBreakingForce = defaultBreakingForce; + break; + } + case GLUT_KEY_DOWN : + { + lockForkSlider(); + gEngineForce = 0.f; + gBreakingForce = defaultBreakingForce; + break; + } + case GLUT_KEY_LEFT: + case GLUT_KEY_RIGHT: + { + lockLiftHinge(); + break; + } + default: + DemoApplication::specialKeyboardUp(key,x,y); + break; + } +} + + +void ForkLiftDemo::specialKeyboard(int key, int x, int y) +{ + + if (key==GLUT_KEY_END) + return; + + // printf("key = %i x=%i y=%i\n",key,x,y); + + int state; + state=glutGetModifiers(); + if (state & GLUT_ACTIVE_SHIFT) + { + switch (key) + { + case GLUT_KEY_LEFT : + { + + m_liftHinge->setLimit(-M_PI/16.0f, M_PI/8.0f); + m_liftHinge->enableAngularMotor(true, -0.1, 10.0); + break; + } + case GLUT_KEY_RIGHT : + { + + m_liftHinge->setLimit(-M_PI/16.0f, M_PI/8.0f); + m_liftHinge->enableAngularMotor(true, 0.1, 10.0); + break; + } + case GLUT_KEY_UP : + { + m_forkSlider->setLowerLinLimit(0.1f); + m_forkSlider->setUpperLinLimit(3.9f); + m_forkSlider->setPoweredLinMotor(true); + m_forkSlider->setMaxLinMotorForce(10.0); + m_forkSlider->setTargetLinMotorVelocity(1.0); + break; + } + case GLUT_KEY_DOWN : + { + m_forkSlider->setLowerLinLimit(0.1f); + m_forkSlider->setUpperLinLimit(3.9f); + m_forkSlider->setPoweredLinMotor(true); + m_forkSlider->setMaxLinMotorForce(10.0); + m_forkSlider->setTargetLinMotorVelocity(-1.0); + break; + } + + default: + DemoApplication::specialKeyboard(key,x,y); + break; + } + + } else + { + switch (key) + { + case GLUT_KEY_LEFT : + { + gVehicleSteering += steeringIncrement; + if ( gVehicleSteering > steeringClamp) + gVehicleSteering = steeringClamp; + + break; + } + case GLUT_KEY_RIGHT : + { + gVehicleSteering -= steeringIncrement; + if ( gVehicleSteering < -steeringClamp) + gVehicleSteering = -steeringClamp; + + break; + } + case GLUT_KEY_UP : + { + gEngineForce = maxEngineForce; + gBreakingForce = 0.f; + break; + } + case GLUT_KEY_DOWN : + { + gEngineForce = -maxEngineForce; + gBreakingForce = 0.f; + break; + } + + case GLUT_KEY_F5: + m_useDefaultCamera = !m_useDefaultCamera; + break; + default: + DemoApplication::specialKeyboard(key,x,y); + break; + } + + } + // glutPostRedisplay(); + + +} + +void ForkLiftDemo::updateCamera() +{ + +//#define DISABLE_CAMERA 1 + if(m_useDefaultCamera) + { + DemoApplication::updateCamera(); + return; + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + btTransform chassisWorldTrans; + + //look at the vehicle + m_carChassis->getMotionState()->getWorldTransform(chassisWorldTrans); + m_cameraTargetPosition = chassisWorldTrans.getOrigin(); + + //interpolate the camera height +#ifdef FORCE_ZAXIS_UP + m_cameraPosition[2] = (15.0*m_cameraPosition[2] + m_cameraTargetPosition[2] + m_cameraHeight)/16.0; +#else + m_cameraPosition[1] = (15.0*m_cameraPosition[1] + m_cameraTargetPosition[1] + m_cameraHeight)/16.0; +#endif + + btVector3 camToObject = m_cameraTargetPosition - m_cameraPosition; + + //keep distance between min and max distance + float cameraDistance = camToObject.length(); + float correctionFactor = 0.f; + if (cameraDistance < m_minCameraDistance) + { + correctionFactor = 0.15*(m_minCameraDistance-cameraDistance)/cameraDistance; + } + if (cameraDistance > m_maxCameraDistance) + { + correctionFactor = 0.15*(m_maxCameraDistance-cameraDistance)/cameraDistance; + } + m_cameraPosition -= correctionFactor*camToObject; + + //update OpenGL camera settings + btScalar aspect = m_glutScreenWidth / (btScalar)m_glutScreenHeight; + glFrustum (-aspect, aspect, -1.0, 1.0, 1.0, 10000.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + gluLookAt(m_cameraPosition[0],m_cameraPosition[1],m_cameraPosition[2], + m_cameraTargetPosition[0],m_cameraTargetPosition[1], m_cameraTargetPosition[2], + m_cameraUp.getX(),m_cameraUp.getY(),m_cameraUp.getZ()); + + + +} + +void ForkLiftDemo::lockLiftHinge(void) +{ + btScalar hingeAngle = m_liftHinge->getHingeAngle(); + btScalar lowLim = m_liftHinge->getLowerLimit(); + btScalar hiLim = m_liftHinge->getUpperLimit(); + m_liftHinge->enableAngularMotor(false, 0, 0); + if(hingeAngle < lowLim) + { +// m_liftHinge->setLimit(lowLim, lowLim + LIFT_EPS); + m_liftHinge->setLimit(lowLim, lowLim); + } + else if(hingeAngle > hiLim) + { +// m_liftHinge->setLimit(hiLim - LIFT_EPS, hiLim); + m_liftHinge->setLimit(hiLim, hiLim); + } + else + { +// m_liftHinge->setLimit(hingeAngle - LIFT_EPS, hingeAngle + LIFT_EPS); + m_liftHinge->setLimit(hingeAngle, hingeAngle); + } + return; +} // ForkLiftDemo::lockLiftHinge() + +void ForkLiftDemo::lockForkSlider(void) +{ + btScalar linDepth = m_forkSlider->getLinearPos(); + btScalar lowLim = m_forkSlider->getLowerLinLimit(); + btScalar hiLim = m_forkSlider->getUpperLinLimit(); + m_forkSlider->setPoweredLinMotor(false); + if(linDepth <= lowLim) + { + m_forkSlider->setLowerLinLimit(lowLim); + m_forkSlider->setUpperLinLimit(lowLim); + } + else if(linDepth > hiLim) + { + m_forkSlider->setLowerLinLimit(hiLim); + m_forkSlider->setUpperLinLimit(hiLim); + } + else + { + m_forkSlider->setLowerLinLimit(linDepth); + m_forkSlider->setUpperLinLimit(linDepth); + } + return; +} // ForkLiftDemo::lockForkSlider() diff --git a/Demos/ForkLiftDemo/ForkLiftDemo.h b/Demos/ForkLiftDemo/ForkLiftDemo.h new file mode 100644 index 0000000..6d0c825 --- /dev/null +++ b/Demos/ForkLiftDemo/ForkLiftDemo.h @@ -0,0 +1,113 @@ +/* +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 FORKLIFT_DEMO_H +#define FORKLIFT_DEMO_H + +class btVehicleTuning; +struct btVehicleRaycaster; +class btCollisionShape; + +#include "BulletDynamics/Vehicle/btRaycastVehicle.h" +#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h" +#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h" + +#include "GlutDemoApplication.h" + +///VehicleDemo shows how to setup and use the built-in raycast vehicle +class ForkLiftDemo : public GlutDemoApplication +{ + public: + + btRigidBody* m_carChassis; + +//---------------------------- + btRigidBody* m_liftBody; + btVector3 m_liftStartPos; + btHingeConstraint* m_liftHinge; + + btRigidBody* m_forkBody; + btVector3 m_forkStartPos; + btSliderConstraint* m_forkSlider; + + btRigidBody* m_loadBody; + btVector3 m_loadStartPos; + + void lockLiftHinge(void); + void lockForkSlider(void); + + bool m_useDefaultCamera; +//---------------------------- + + + btAlignedObjectArray m_collisionShapes; + + class btBroadphaseInterface* m_overlappingPairCache; + + class btCollisionDispatcher* m_dispatcher; + + class btConstraintSolver* m_constraintSolver; + + class btDefaultCollisionConfiguration* m_collisionConfiguration; + + class btTriangleIndexVertexArray* m_indexVertexArrays; + + btVector3* m_vertices; + + + btRaycastVehicle::btVehicleTuning m_tuning; + btVehicleRaycaster* m_vehicleRayCaster; + btRaycastVehicle* m_vehicle; + btCollisionShape* m_wheelShape; + + float m_cameraHeight; + + float m_minCameraDistance; + float m_maxCameraDistance; + + + ForkLiftDemo(); + + virtual ~ForkLiftDemo(); + + virtual void clientMoveAndDisplay(); + + virtual void clientResetScene(); + + virtual void displayCallback(); + + ///a very basic camera following the vehicle + virtual void updateCamera(); + + virtual void specialKeyboard(int key, int x, int y); + + virtual void specialKeyboardUp(int key, int x, int y); + + void renderme(); + + void initPhysics(); + void termPhysics(); + + static DemoApplication* Create() + { + ForkLiftDemo* demo = new ForkLiftDemo(); + demo->myinit(); + demo->initPhysics(); + return demo; + } +}; + +#endif // FORKLIFT_DEMO_H + + diff --git a/Demos/ForkLiftDemo/main.cpp b/Demos/ForkLiftDemo/main.cpp new file mode 100644 index 0000000..42b8b06 --- /dev/null +++ b/Demos/ForkLiftDemo/main.cpp @@ -0,0 +1,18 @@ + +#include "ForkLiftDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" +GLDebugDrawer gDebugDrawer; + +int main(int argc,char** argv) +{ + + ForkLiftDemo* pForkLiftDemo = new ForkLiftDemo; + + pForkLiftDemo->initPhysics(); + pForkLiftDemo->getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + return glutmain(argc, argv,1024,768,"Bullet ForkLift Demo. http://www.continuousphysics.com/Bullet/phpBB2/", pForkLiftDemo); +} + diff --git a/Demos/FractureDemo/CMakeLists.txt b/Demos/FractureDemo/CMakeLists.txt new file mode 100644 index 0000000..eae9acd --- /dev/null +++ b/Demos/FractureDemo/CMakeLists.txt @@ -0,0 +1,95 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# This is the variable for Windows. I use this to define the root of my directory structure. +SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/Glut) + +# You shouldn't have to modify anything below this line +######################################################## + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + + + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + +IF (WIN32) +ADD_EXECUTABLE(AppFractureDemo + main.cpp + FractureDemo.cpp + FractureDemo.h + btFractureBody.h + btFractureBody.cpp + btFractureDynamicsWorld.cpp + btFractureDynamicsWorld.h + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) +ELSE() + ADD_EXECUTABLE(AppFractureDemo + main.cpp + FractureDemo.cpp + FractureDemo.h + btFractureBody.h + btFractureBody.cpp + btFractureDynamicsWorld.cpp + btFractureDynamicsWorld.h + ) +ENDIF() + + + + + IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppFractureDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppFractureDemo + POST_BUILD +# COMMAND copy /Y ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + + ENDIF(WIN32) +ELSE (USE_GLUT) + + + + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + + ADD_EXECUTABLE(AppFractureDemo + WIN32 + ../OpenGL/Win32AppMain.cpp + Win32FractureDemo.cpp + FractureDemo.cpp + FractureDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) + + +ENDIF (USE_GLUT) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppFractureDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppFractureDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppFractureDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/FractureDemo/FractureDemo.cpp b/Demos/FractureDemo/FractureDemo.cpp new file mode 100644 index 0000000..16b7396 --- /dev/null +++ b/Demos/FractureDemo/FractureDemo.cpp @@ -0,0 +1,362 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2011 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. +*/ + + +///FractureDemo shows how to break objects. +///It assumes a btCompoundShaps (where the childshapes are the pre-fractured pieces) +///The btFractureBody is a class derived from btRigidBody, dealing with the collision impacts. +///Press the F key to toggle between fracture and glue mode +///This is preliminary work + + +#define CUBE_HALF_EXTENTS 1.f +#define EXTRA_HEIGHT 1.f +///scaling of the objects (0.1 = 20 centimeter boxes ) +#define SCALING 1. +#define START_POS_X -5 +#define START_POS_Y -5 +#define START_POS_Z -3 + +#include "FractureDemo.h" +#include "GlutStuff.h" +#include "GLDebugFont.h" +///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files. +#include "btBulletDynamicsCommon.h" + + +#include //printf debugging + + +int sFrameNumber = 0; + +#include "btFractureBody.h" +#include "btFractureDynamicsWorld.h" + + + + + +void FractureDemo::initPhysics() +{ + + setTexturing(true); + setShadows(true); + + setDebugMode(btIDebugDraw::DBG_DrawText|btIDebugDraw::DBG_NoHelpText); + + setCameraDistance(btScalar(SCALING*20.)); + + ///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); + + btFractureDynamicsWorld* fractureWorld = new btFractureDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + m_dynamicsWorld = fractureWorld; + + m_ShootBoxInitialSpeed=100; + + //m_splitImpulse removes the penetration resolution from the applied impulse, otherwise objects might fracture due to deep penetrations. + m_dynamicsWorld->getSolverInfo().m_splitImpulse = true; + + { + ///create a few basic rigid bodies + btCollisionShape* groundShape = new btBoxShape(btVector3(50,1,50)); + /// btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),0); + m_collisionShapes.push_back(groundShape); + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,0,0)); + localCreateRigidBody(0.f,groundTransform,groundShape); + } + + { + ///create a few basic rigid bodies + btCollisionShape* shape = new btBoxShape(btVector3(1,1,1)); + m_collisionShapes.push_back(shape); + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(5,2,0)); + localCreateRigidBody(0.f,tr,shape); + } + + + + { + //create a few dynamic rigidbodies + // Re-using the same collision is better for memory usage and performance + + btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,SCALING*1)); + //btCollisionShape* colShape = new btCapsuleShape(SCALING*0.4,SCALING*1); + //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); + m_collisionShapes.push_back(colShape); + + /// Create Dynamic Objects + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + + //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) + colShape->calculateLocalInertia(mass,localInertia); + + + int gNumObjects = 10; + + for (int i=0;isetLinearVelocity(btVector3(0,-10,0)); + + m_dynamicsWorld->addRigidBody(body); + + + } + + } + + + + fractureWorld->stepSimulation(1./60.,0); + fractureWorld->glueCallback(); + + + +} + +void FractureDemo::clientResetScene() +{ + exitPhysics(); + initPhysics(); +} + + +void FractureDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //simple dynamics world doesn't handle fixed-time-stepping + float ms = getDeltaTimeMicroseconds(); + + ///step the simulation + if (m_dynamicsWorld) + { + m_dynamicsWorld->stepSimulation(ms / 1000000.f); + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + } + + + + renderme(); + + showMessage(); + + glFlush(); + + swapBuffers(); + +} + +void FractureDemo::showMessage() +{ + if((getDebugMode() & btIDebugDraw::DBG_DrawText)) + { + setOrthographicProjection(); + glDisable(GL_LIGHTING); + glColor3f(0, 0, 0); + char buf[124]; + + int lineWidth=380; + int xStart = m_glutScreenWidth - lineWidth; + int yStart = 20; + + btFractureDynamicsWorld* world = (btFractureDynamicsWorld*)m_dynamicsWorld; + if (world->getFractureMode()) + { + sprintf(buf,"Fracture mode"); + } else + { + sprintf(buf,"Glue mode"); + } + GLDebugDrawString(xStart,yStart,buf); + sprintf(buf,"f to toggle fracture/glue mode"); + yStart+=20; + GLDebugDrawString(xStart,yStart,buf); + sprintf(buf,"space to restart, mouse to pick/shoot"); + yStart+=20; + GLDebugDrawString(xStart,yStart,buf); + + resetPerspectiveProjection(); + glEnable(GL_LIGHTING); + } + +} + + +void FractureDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + showMessage(); + + //optional but useful: debug drawing to detect problems + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + glFlush(); + swapBuffers(); +} + + +void FractureDemo::keyboardUpCallback(unsigned char key, int x, int y) +{ + if (key=='f') + { + btFractureDynamicsWorld* world = (btFractureDynamicsWorld*)m_dynamicsWorld; + world->setFractureMode(!world->getFractureMode()); + } + + PlatformDemoApplication::keyboardUpCallback(key,x,y); + +} + + +void FractureDemo::shootBox(const btVector3& destination) +{ + + if (m_dynamicsWorld) + { + btScalar mass = 1.f; + btTransform startTransform; + startTransform.setIdentity(); + btVector3 camPos = getCameraPosition(); + startTransform.setOrigin(camPos); + + setShootBoxShape (); + + btAssert((!m_shootBoxShape || m_shootBoxShape->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) + m_shootBoxShape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + + btFractureBody* body = new btFractureBody(mass,0,m_shootBoxShape,localInertia,&mass,1,m_dynamicsWorld); + + body->setWorldTransform(startTransform); + + m_dynamicsWorld->addRigidBody(body); + + + body->setLinearFactor(btVector3(1,1,1)); + //body->setRestitution(1); + + btVector3 linVel(destination[0]-camPos[0],destination[1]-camPos[1],destination[2]-camPos[2]); + linVel.normalize(); + linVel*=m_ShootBoxInitialSpeed; + + body->getWorldTransform().setOrigin(camPos); + body->getWorldTransform().setRotation(btQuaternion(0,0,0,1)); + body->setLinearVelocity(linVel); + body->setAngularVelocity(btVector3(0,0,0)); + body->setCcdMotionThreshold(1.); + body->setCcdSweptSphereRadius(0.2f); + + } +} + + + + + + +void FractureDemo::exitPhysics() +{ + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;j m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + void showMessage(); + + public: + + FractureDemo() + { + } + virtual ~FractureDemo() + { + exitPhysics(); + } + void initPhysics(); + + void exitPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + virtual void keyboardUpCallback(unsigned char key, int x, int y); + + virtual void clientResetScene(); + + static DemoApplication* Create() + { + FractureDemo* demo = new FractureDemo; + demo->myinit(); + demo->initPhysics(); + return demo; + } + + void shootBox(const btVector3& destination); + +}; + +#endif //FRACTURE_DEMO_H + diff --git a/Demos/FractureDemo/Win32FractureDemo.cpp b/Demos/FractureDemo/Win32FractureDemo.cpp new file mode 100644 index 0000000..c7b363b --- /dev/null +++ b/Demos/FractureDemo/Win32FractureDemo.cpp @@ -0,0 +1,25 @@ +#ifdef _WINDOWS +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2011 Erwin Coumans http://bulletphysics.org + +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 "FractureDemo.h" + +///The 'createDemo' function is called from Bullet/Demos/OpenGL/Win32AppMain.cpp to instantiate this particular demo +DemoApplication* createDemo() +{ + return new FractureDemo(); +} + +#endif diff --git a/Demos/FractureDemo/btFractureBody.cpp b/Demos/FractureDemo/btFractureBody.cpp new file mode 100644 index 0000000..b7a5289 --- /dev/null +++ b/Demos/FractureDemo/btFractureBody.cpp @@ -0,0 +1,138 @@ + +#include "btFractureBody.h" +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletDynamics/Dynamics/btDynamicsWorld.h" + + + +void btFractureBody::recomputeConnectivity(btCollisionWorld* world) +{ + m_connections.clear(); + //@todo use the AABB tree to avoid N^2 checks + + if (getCollisionShape()->isCompound()) + { + btCompoundShape* compound = (btCompoundShape*)getCollisionShape(); + for (int i=0;igetNumChildShapes();i++) + { + for (int j=i+1;jgetNumChildShapes();j++) + { + + struct MyContactResultCallback : public btCollisionWorld::ContactResultCallback + { + bool m_connected; + MyContactResultCallback() :m_connected(false) + { + } + virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1) + { + if (cp.getDistance()<=0) + m_connected = true; + return 1.f; + } + }; + + MyContactResultCallback result; + + btCollisionObject obA; + obA.setWorldTransform(compound->getChildTransform(i)); + obA.setCollisionShape(compound->getChildShape(i)); + btCollisionObject obB; + obB.setWorldTransform(compound->getChildTransform(j)); + obB.setCollisionShape(compound->getChildShape(j)); + world->contactPairTest(&obA,&obB,result); + if (result.m_connected) + { + btConnection tmp; + tmp.m_childIndex0 = i; + tmp.m_childIndex1 = j; + tmp.m_childShape0 = compound->getChildShape(i); + tmp.m_childShape1 = compound->getChildShape(j); + tmp.m_strength = 1.f;//?? + m_connections.push_back(tmp); + } + } + } + } + + +} + +btCompoundShape* btFractureBody::shiftTransformDistributeMass(btCompoundShape* boxCompound,btScalar mass,btTransform& shift) +{ + + btVector3 principalInertia; + + btScalar* masses = new btScalar[boxCompound->getNumChildShapes()]; + for (int j=0;jgetNumChildShapes();j++) + { + //evenly distribute mass + masses[j]=mass/boxCompound->getNumChildShapes(); + } + + return shiftTransform(boxCompound,masses,shift,principalInertia); + +} + + +btCompoundShape* btFractureBody::shiftTransform(btCompoundShape* boxCompound,btScalar* masses,btTransform& shift, btVector3& principalInertia) +{ + btTransform principal; + + boxCompound->calculatePrincipalAxisTransform(masses,principal,principalInertia); + + + ///create a new compound with world transform/center of mass properly aligned with the principal axis + + ///non-recursive compound shapes perform better + +#ifdef USE_RECURSIVE_COMPOUND + + btCompoundShape* newCompound = new btCompoundShape(); + newCompound->addChildShape(principal.inverse(),boxCompound); + newBoxCompound = newCompound; + //m_collisionShapes.push_back(newCompound); + + //btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + //btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,newCompound,principalInertia); + +#else +#ifdef CHANGE_COMPOUND_INPLACE + newBoxCompound = boxCompound; + for (int i=0;igetNumChildShapes();i++) + { + btTransform newChildTransform = principal.inverse()*boxCompound->getChildTransform(i); + ///updateChildTransform is really slow, because it re-calculates the AABB each time. todo: add option to disable this update + boxCompound->updateChildTransform(i,newChildTransform); + } + bool isDynamic = (mass != 0.f); + btVector3 localInertia(0,0,0); + if (isDynamic) + boxCompound->calculateLocalInertia(mass,localInertia); + +#else + ///creation is faster using a new compound to store the shifted children + btCompoundShape* newBoxCompound = new btCompoundShape(); + for (int i=0;igetNumChildShapes();i++) + { + btTransform newChildTransform = principal.inverse()*boxCompound->getChildTransform(i); + ///updateChildTransform is really slow, because it re-calculates the AABB each time. todo: add option to disable this update + newBoxCompound->addChildShape(newChildTransform,boxCompound->getChildShape(i)); + } + + + +#endif + +#endif//USE_RECURSIVE_COMPOUND + + shift = principal; + return newBoxCompound; +} + + + + + + diff --git a/Demos/FractureDemo/btFractureBody.h b/Demos/FractureDemo/btFractureBody.h new file mode 100644 index 0000000..a21d992 --- /dev/null +++ b/Demos/FractureDemo/btFractureBody.h @@ -0,0 +1,78 @@ + +#ifndef BT_FRACTURE_BODY +#define BT_FRACTURE_BODY + +class btCollisionShape; +class btDynamicsWorld; +class btCollisionWorld; +class btCompoundShape; +class btManifoldPoint; + +#include "LinearMath/btAlignedObjectArray.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" + +#define CUSTOM_FRACTURE_TYPE (btRigidBody::CO_USER_TYPE+1) + + +struct btConnection +{ + + btCollisionShape* m_childShape0; + btCollisionShape* m_childShape1; + int m_childIndex0; + int m_childIndex1; + btScalar m_strength; +}; + +class btFractureBody : public btRigidBody +{ + //connections +public: + + btDynamicsWorld* m_world; + btAlignedObjectArray m_masses; + btAlignedObjectArray m_connections; + + + + btFractureBody( const btRigidBodyConstructionInfo& constructionInfo, btDynamicsWorld* world) + :btRigidBody(constructionInfo), + m_world(world) + { + m_masses.push_back(constructionInfo.m_mass); + m_internalType=CUSTOM_FRACTURE_TYPE+CO_RIGID_BODY; + } + + + + ///btRigidBody constructor for backwards compatibility. + ///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo) + btFractureBody( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia, btScalar* masses, int numMasses, btDynamicsWorld* world) + :btRigidBody(mass,motionState,collisionShape,localInertia), + m_world(world) + { + + for (int i=0;igetNumManifolds(); + + ///first build the islands based on axis aligned bounding box overlap + + btUnionFind unionFind; + + int index = 0; + { + + int i; + for (i=0;iisStaticOrKinematicObject()) + { + collisionObject->setIslandTag(index++); + } else + { + collisionObject->setIslandTag(-1); + } +#else + collisionObject->setIslandTag(i); + index=i+1; +#endif + } + } + + unionFind.reset(index); + + int numElem = unionFind.getNumElements(); + + for (int i=0;igetManifoldByIndexInternal(i); + if (!manifold->getNumContacts()) + continue; + + btScalar minDist = 1e30f; + for (int v=0;vgetNumContacts();v++) + { + minDist = btMin(minDist,manifold->getContactPoint(v).getDistance()); + } + if (minDist>0.) + continue; + + btCollisionObject* colObj0 = (btCollisionObject*)manifold->getBody0(); + btCollisionObject* colObj1 = (btCollisionObject*)manifold->getBody1(); + int tag0 = (colObj0)->getIslandTag(); + int tag1 = (colObj1)->getIslandTag(); + btRigidBody* body0 = btRigidBody::upcast(colObj0); + btRigidBody* body1 = btRigidBody::upcast(colObj1); + + + if (!colObj0->isStaticOrKinematicObject() && !colObj1->isStaticOrKinematicObject()) + { + unionFind.unite(tag0, tag1); + } + } + + + + + numElem = unionFind.getNumElements(); + + + + index=0; + for (int ai=0;aiisStaticOrKinematicObject()) + { + int tag = unionFind.find(index); + + collisionObject->setIslandTag( tag); + + //Set the correct object offset in Collision Object Array +#if STATIC_SIMULATION_ISLAND_OPTIMIZATION + unionFind.getElement(index).m_sz = ai; +#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION + + index++; + } + } + unionFind.sortIslands(); + + + + int endIslandIndex=1; + int startIslandIndex; + + btAlignedObjectArray removedObjects; + + ///iterate over all islands + for ( startIslandIndex=0;startIslandIndexgetInternalType()& CUSTOM_FRACTURE_TYPE) + { + fractureObjectIndex = i; + } + btRigidBody* otherObject = btRigidBody::upcast(colObj0); + if (!otherObject || !otherObject->getInvMass()) + continue; + numObjects++; + } + + ///Then for each island that contains at least two objects and one fracture object + if (fractureObjectIndex>=0 && numObjects>1) + { + + btFractureBody* fracObj = (btFractureBody*)getCollisionObjectArray()[fractureObjectIndex]; + + ///glueing objects means creating a new compound and removing the old objects + ///delay the removal of old objects to avoid array indexing problems + removedObjects.push_back(fracObj); + m_fractureBodies.remove(fracObj); + + btAlignedObjectArray massArray; + + btAlignedObjectArray oldImpulses; + btAlignedObjectArray oldCenterOfMassesWS; + + oldImpulses.push_back(fracObj->getLinearVelocity()/1./fracObj->getInvMass()); + oldCenterOfMassesWS.push_back(fracObj->getCenterOfMassPosition()); + + btScalar totalMass = 0.f; + + + btCompoundShape* compound = new btCompoundShape(); + if (fracObj->getCollisionShape()->isCompound()) + { + btTransform tr; + tr.setIdentity(); + btCompoundShape* oldCompound = (btCompoundShape*)fracObj->getCollisionShape(); + for (int c=0;cgetNumChildShapes();c++) + { + compound->addChildShape(oldCompound->getChildTransform(c),oldCompound->getChildShape(c)); + massArray.push_back(fracObj->m_masses[c]); + totalMass+=fracObj->m_masses[c]; + } + + } else + { + btTransform tr; + tr.setIdentity(); + compound->addChildShape(tr,fracObj->getCollisionShape()); + massArray.push_back(fracObj->m_masses[0]); + totalMass+=fracObj->m_masses[0]; + } + + for (idx=startIslandIndex;idxgetInvMass()) + continue; + + + oldImpulses.push_back(otherObject->getLinearVelocity()*(1.f/otherObject->getInvMass())); + oldCenterOfMassesWS.push_back(otherObject->getCenterOfMassPosition()); + + removedObjects.push_back(otherObject); + m_fractureBodies.remove((btFractureBody*)otherObject); + + btScalar curMass = 1.f/otherObject->getInvMass(); + + + if (otherObject->getCollisionShape()->isCompound()) + { + btTransform tr; + btCompoundShape* oldCompound = (btCompoundShape*)otherObject->getCollisionShape(); + for (int c=0;cgetNumChildShapes();c++) + { + tr = fracObj->getWorldTransform().inverseTimes(otherObject->getWorldTransform()*oldCompound->getChildTransform(c)); + compound->addChildShape(tr,oldCompound->getChildShape(c)); + massArray.push_back(curMass/(btScalar)oldCompound->getNumChildShapes()); + + } + } else + { + btTransform tr; + tr = fracObj->getWorldTransform().inverseTimes(otherObject->getWorldTransform()); + compound->addChildShape(tr,otherObject->getCollisionShape()); + massArray.push_back(curMass); + } + totalMass+=curMass; + } + + + + btTransform shift; + shift.setIdentity(); + btCompoundShape* newCompound = btFractureBody::shiftTransformDistributeMass(compound,totalMass,shift); + int numChildren = newCompound->getNumChildShapes(); + btAssert(numChildren == massArray.size()); + + btVector3 localInertia; + newCompound->calculateLocalInertia(totalMass,localInertia); + btFractureBody* newBody = new btFractureBody(totalMass,0,newCompound,localInertia, &massArray[0], numChildren,this); + newBody->recomputeConnectivity(this); + newBody->setWorldTransform(fracObj->getWorldTransform()*shift); + + //now the linear/angular velocity is still zero, apply the impulses + + for (int i=0;igetCenterOfMassPosition(); + const btVector3& imp = oldImpulses[i]; + newBody->applyImpulse(imp, rel_pos); + } + + addRigidBody(newBody); + + + } + + + } + + //remove the objects from the world at the very end, + //otherwise the island tags would not match the world collision object array indices anymore + while (removedObjects.size()) + { + btCollisionObject* otherCollider = removedObjects[removedObjects.size()-1]; + removedObjects.pop_back(); + + btRigidBody* otherObject = btRigidBody::upcast(otherCollider); + if (!otherObject || !otherObject->getInvMass()) + continue; + removeRigidBody(otherObject); + } + +} + + +struct btFracturePair +{ + btFractureBody* m_fracObj; + btAlignedObjectArray m_contactManifolds; +}; + + + +void btFractureDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) +{ + // todo: after fracture we should run the solver again for better realism + // for example + // save all velocities and if one or more objects fracture: + // 1) revert all velocties + // 2) apply impulses for the fracture bodies at the contact locations + // 3)and run the constaint solver again + + btDiscreteDynamicsWorld::solveConstraints(solverInfo); + + fractureCallback(); +} + +btFractureBody* btFractureDynamicsWorld::addNewBody(const btTransform& oldTransform,btScalar* masses, btCompoundShape* oldCompound) +{ + int i; + + btTransform shift; + shift.setIdentity(); + btVector3 localInertia; + btCompoundShape* newCompound = btFractureBody::shiftTransform(oldCompound,masses,shift,localInertia); + btScalar totalMass = 0; + for (i=0;igetNumChildShapes();i++) + totalMass += masses[i]; + //newCompound->calculateLocalInertia(totalMass,localInertia); + + btFractureBody* newBody = new btFractureBody(totalMass,0,newCompound,localInertia, masses,newCompound->getNumChildShapes(), this); + newBody->recomputeConnectivity(this); + + newBody->setCollisionFlags(newBody->getCollisionFlags()|btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + newBody->setWorldTransform(oldTransform*shift); + addRigidBody(newBody); + return newBody; +} + +void btFractureDynamicsWorld::addRigidBody(btRigidBody* body) +{ + if (body->getInternalType() & CUSTOM_FRACTURE_TYPE) + { + btFractureBody* fbody = (btFractureBody*)body; + m_fractureBodies.push_back(fbody); + } + btDiscreteDynamicsWorld::addRigidBody(body); +} + +void btFractureDynamicsWorld::removeRigidBody(btRigidBody* body) +{ + if (body->getInternalType() & CUSTOM_FRACTURE_TYPE) + { + btFractureBody* fbody = (btFractureBody*)body; + m_fractureBodies.remove(fbody); + } + btDiscreteDynamicsWorld::removeRigidBody(body); +} + +void btFractureDynamicsWorld::breakDisconnectedParts( btFractureBody* fracObj) +{ + + if (!fracObj->getCollisionShape()->isCompound()) + return; + + btCompoundShape* compound = (btCompoundShape*)fracObj->getCollisionShape(); + int numChildren = compound->getNumChildShapes(); + + if (numChildren<=1) + return; + + //compute connectivity + btUnionFind unionFind; + + btAlignedObjectArray tags; + tags.resize(numChildren); + int i, index = 0; + for ( i=0;im_connections.size();i++) + { + btConnection& connection = fracObj->m_connections[i]; + if (connection.m_strength > 0.) + { + int tag0 = tags[connection.m_childIndex0]; + int tag1 = tags[connection.m_childIndex1]; + unionFind.unite(tag0, tag1); + } + } + numElem = unionFind.getNumElements(); + + index=0; + for (int ai=0;ai removedObjects; + + int numIslands = 0; + + for ( startIslandIndex=0;startIslandIndex masses; + + int idx; + for (idx=startIslandIndex;idxgetChildShape(i); + newCompound->addChildShape(compound->getChildTransform(i),compound->getChildShape(i)); + masses.push_back(fracObj->m_masses[i]); + numShapes++; + } + if (numShapes) + { + btFractureBody* newBody = addNewBody(fracObj->getWorldTransform(),&masses[0],newCompound); + newBody->setLinearVelocity(fracObj->getLinearVelocity()); + newBody->setAngularVelocity(fracObj->getAngularVelocity()); + + numIslands++; + } + } + + + + + + removeRigidBody(fracObj);//should it also be removed from the array? + + +} + +#include + + +void btFractureDynamicsWorld::fractureCallback( ) +{ + + btAlignedObjectArray sFracturePairs; + + if (!m_fracturingMode) + { + glueCallback(); + return; + } + + int numManifolds = getDispatcher()->getNumManifolds(); + + sFracturePairs.clear(); + + + for (int i=0;igetManifoldByIndexInternal(i); + if (!manifold->getNumContacts()) + continue; + + btScalar totalImpact = 0.f; + for (int p=0;pgetNumContacts();p++) + { + totalImpact += manifold->getContactPoint(p).m_appliedImpulse; + } + + +// printf("totalImpact=%f\n",totalImpact); + + static float maxImpact = 0; + if (totalImpact>maxImpact) + maxImpact = totalImpact; + + //some threshold otherwise resting contact would break objects after a while + if (totalImpact < 40.f) + continue; + + // printf("strong impact\n"); + + + //@todo: add better logic to decide what parts to fracture + //For example use the idea from the SIGGRAPH talk about the fracture in the movie 2012: + // + //Breaking thresholds can be stored as connectivity information between child shapes in the fracture object + // + //You can calculate some "impact value" by simulating all the individual child shapes + //as rigid bodies, without constraints, running it in a separate simulation world + //(or by running the constraint solver without actually modifying the dynamics world) + //Then measure some "impact value" using the offset and applied impulse for each child shape + //weaken the connections based on this "impact value" and only break + //if this impact value exceeds the breaking threshold. + //you can propagate the weakening and breaking of connections using the connectivity information + + int f0 = m_fractureBodies.findLinearSearch((btFractureBody*)manifold->getBody0()); + int f1 = m_fractureBodies.findLinearSearch((btFractureBody*)manifold->getBody1()); + + if (f0 == f1 == m_fractureBodies.size()) + continue; + + + if (f0getBody1(); + btRigidBody* otherOb = btRigidBody::upcast(colOb); + // if (!otherOb->getInvMass()) + // continue; + + int pi=-1; + + for (int p=0;pgetBody0(); + btRigidBody* otherOb = btRigidBody::upcast(colOb); + // if (!otherOb->getInvMass()) + // continue; + + + int pi=-1; + + for (int p=0;pgetCollisionShape()->isCompound()) + { + btTransform tr; + tr.setIdentity(); + btCompoundShape* oldCompound = (btCompoundShape*)sFracturePairs[i].m_fracObj->getCollisionShape(); + if (oldCompound->getNumChildShapes()>1) + { + bool needsBreakingCheck = false; + + + //weaken/break the connections + + //@todo: propagate along the connection graph + for (int j=0;jgetNumContacts();k++) + { + btManifoldPoint& pt = manifold->getContactPoint(k); + if (manifold->getBody0()==sFracturePairs[i].m_fracObj) + { + for (int f=0;fm_connections.size();f++) + { + btConnection& connection = sFracturePairs[i].m_fracObj->m_connections[f]; + if ( (connection.m_childIndex0 == pt.m_index0) || + (connection.m_childIndex1 == pt.m_index0) + ) + { + connection.m_strength -= pt.m_appliedImpulse; + if (connection.m_strength<0) + { + //remove or set to zero + connection.m_strength=0.f; + needsBreakingCheck = true; + } + } + } + } else + { + for (int f=0;fm_connections.size();f++) + { + btConnection& connection = sFracturePairs[i].m_fracObj->m_connections[f]; + if ( (connection.m_childIndex0 == pt.m_index1) || + (connection.m_childIndex1 == pt.m_index1) + ) + { + connection.m_strength -= pt.m_appliedImpulse; + if (connection.m_strength<0) + { + //remove or set to zero + connection.m_strength=0.f; + needsBreakingCheck = true; + } + } + } + } + } + } + + if (needsBreakingCheck) + { + breakDisconnectedParts(sFracturePairs[i].m_fracObj); + } + } + + } + + } + } + + sFracturePairs.clear(); + +} + diff --git a/Demos/FractureDemo/btFractureDynamicsWorld.h b/Demos/FractureDemo/btFractureDynamicsWorld.h new file mode 100644 index 0000000..ad7e821 --- /dev/null +++ b/Demos/FractureDemo/btFractureDynamicsWorld.h @@ -0,0 +1,51 @@ +#ifndef _BT_FRACTURE_DYNAMICS_WORLD_H +#define _BT_FRACTURE_DYNAMICS_WORLD_H + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +#include "LinearMath/btAlignedObjectArray.h" + +class btFractureBody; +class btCompoundShape; +class btTransform; + + +///The btFractureDynamicsWorld class enabled basic glue and fracture of objects. +///If/once this implementation is stablized/tested we might merge it into btDiscreteDynamicsWorld and remove the class. +class btFractureDynamicsWorld : public btDiscreteDynamicsWorld +{ + btAlignedObjectArray m_fractureBodies; + + bool m_fracturingMode; + + btFractureBody* addNewBody(const btTransform& oldTransform,btScalar* masses, btCompoundShape* oldCompound); + + void breakDisconnectedParts( btFractureBody* fracObj); + +public: + + btFractureDynamicsWorld ( btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); + + virtual void addRigidBody(btRigidBody* body); + + virtual void removeRigidBody(btRigidBody* body); + + void solveConstraints(btContactSolverInfo& solverInfo); + + ///either fracture or glue (!fracture) + void setFractureMode(bool fracture) + { + m_fracturingMode = fracture; + } + + bool getFractureMode() const { return m_fracturingMode;} + + ///normally those callbacks are called internally by the 'solveConstraints' + void glueCallback(); + + ///normally those callbacks are called internally by the 'solveConstraints' + void fractureCallback(); + +}; + +#endif //_BT_FRACTURE_DYNAMICS_WORLD_H + diff --git a/Demos/FractureDemo/main.cpp b/Demos/FractureDemo/main.cpp new file mode 100644 index 0000000..7486bc5 --- /dev/null +++ b/Demos/FractureDemo/main.cpp @@ -0,0 +1,42 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "FractureDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btHashMap.h" + + +int main(int argc,char** argv) +{ + GLDebugDrawer gDebugDrawer; + + + FractureDemo ccdDemo; + ccdDemo.initPhysics(); + ccdDemo.getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + +#ifdef CHECK_MEMORY_LEAKS + ccdDemo.exitPhysics(); +#else + return glutmain(argc, argv,640,480,"Bullet Physics Demo. http://bulletphysics.com",&ccdDemo); +#endif + + //default glut doesn't return from mainloop + return 0; +} + diff --git a/Demos/GenericJointDemo/CMakeLists.txt b/Demos/GenericJointDemo/CMakeLists.txt new file mode 100644 index 0000000..02d4cfb --- /dev/null +++ b/Demos/GenericJointDemo/CMakeLists.txt @@ -0,0 +1,82 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + +IF (USE_GLUT) + + INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL + ) + + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + IF (WIN32) + ADD_EXECUTABLE(AppGenericJointDemo + GenericJointDemo.cpp + GenericJointDemo.h + Ragdoll.cpp + main.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) + ELSE() + ADD_EXECUTABLE(AppGenericJointDemo + GenericJointDemo.cpp + GenericJointDemo.h + Ragdoll.cpp + main.cpp + ) + ENDIF() + IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppGenericJointDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppGenericJointDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ENDIF(WIN32) + +ELSE(USE_GLUT) + + INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL + ) + + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + ADD_EXECUTABLE(AppGenericJointDemo + WIN32 + ../OpenGL/Win32AppMain.cpp + Win32GenericJointDemo.cpp + GenericJointDemo.cpp + GenericJointDemo.h + Ragdoll.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + + ) +ENDIF (USE_GLUT) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppGenericJointDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppGenericJointDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppGenericJointDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/GenericJointDemo/GenericJointDemo.cpp b/Demos/GenericJointDemo/GenericJointDemo.cpp new file mode 100644 index 0000000..35e24c1 --- /dev/null +++ b/Demos/GenericJointDemo/GenericJointDemo.cpp @@ -0,0 +1,135 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Ragdoll Demo +Copyright (c) 2007 Starbreeze Studios + +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. + +Originally Written by: Marten Svanfeldt +ReWritten by: Francisco León +*/ + + + +#include "btBulletDynamicsCommon.h" +#include "GlutStuff.h" +#include "GL_ShapeDrawer.h" + +#include "LinearMath/btIDebugDraw.h" + +#include "GLDebugDrawer.h" +#include "GenericJointDemo.h" + + + +GLDebugDrawer debugDrawer; + + + + + + +void GenericJointDemo::initPhysics() +{ + setTexturing(true); + setShadows(true); + + // Setup the basic world + + btDefaultCollisionConfiguration * collision_config = new btDefaultCollisionConfiguration(); + + btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collision_config); + + btVector3 worldAabbMin(-10000,-10000,-10000); + btVector3 worldAabbMax(10000,10000,10000); + btBroadphaseInterface* overlappingPairCache = new btAxisSweep3 (worldAabbMin, worldAabbMax); + + btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver; + + + m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,overlappingPairCache,constraintSolver,collision_config); + + m_dynamicsWorld->setGravity(btVector3(0,-30,0)); + + m_dynamicsWorld->setDebugDrawer(&debugDrawer); + + // Setup a big ground box + { + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(200.),btScalar(10.),btScalar(200.))); + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-15,0)); + localCreateRigidBody(btScalar(0.),groundTransform,groundShape); + } + + // Spawn one ragdoll + spawnRagdoll(); + + clientResetScene(); +} + +void GenericJointDemo::spawnRagdoll(bool random) +{ + RagDoll* ragDoll = new RagDoll (m_dynamicsWorld, btVector3 (0,0,10),5.f); + m_ragdolls.push_back(ragDoll); +} + +void GenericJointDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //simple dynamics world doesn't handle fixed-time-stepping + float ms = getDeltaTimeMicroseconds(); + + float minFPS = 1000000.f/60.f; + if (ms > minFPS) + ms = minFPS; + + if (m_dynamicsWorld) + { + m_dynamicsWorld->stepSimulation(ms / 1000000.f); + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + } + + renderme(); + + glFlush(); + + swapBuffers(); +} + +void GenericJointDemo::displayCallback() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + renderme(); + + glFlush(); + swapBuffers(); +} + +void GenericJointDemo::keyboardCallback(unsigned char key, int x, int y) +{ + switch (key) + { + case 'e': + spawnRagdoll(true); + break; + default: + DemoApplication::keyboardCallback(key, x, y); + } + + +} diff --git a/Demos/GenericJointDemo/GenericJointDemo.h b/Demos/GenericJointDemo/GenericJointDemo.h new file mode 100644 index 0000000..68a11c0 --- /dev/null +++ b/Demos/GenericJointDemo/GenericJointDemo.h @@ -0,0 +1,51 @@ +/* +Bullet Continuous Collision Detection and Physics Library +GenericJointDemo +Copyright (c) 2007 Starbreeze Studios + +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. + +Written by: Marten Svanfeldt +*/ + +#ifndef GENERIGJOINTDEMO_H +#define GENERIGJOINTDEMO_H + +#ifdef _WINDOWS +#include "Win32DemoApplication.h" +#define PlatformDemoApplication Win32DemoApplication +#else +#include "GlutDemoApplication.h" +#define PlatformDemoApplication GlutDemoApplication +#endif + +#include "LinearMath/btAlignedObjectArray.h" +#include "Ragdoll.h" + +class GenericJointDemo : public PlatformDemoApplication +{ + + btAlignedObjectArray m_ragdolls; + +public: + void initPhysics(); + + void spawnRagdoll(bool random = false); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + virtual void keyboardCallback(unsigned char key, int x, int y); +}; + + +#endif diff --git a/Demos/GenericJointDemo/Ragdoll.cpp b/Demos/GenericJointDemo/Ragdoll.cpp new file mode 100644 index 0000000..0229f5a --- /dev/null +++ b/Demos/GenericJointDemo/Ragdoll.cpp @@ -0,0 +1,373 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Ragdoll Demo +Copyright (c) 2007 Starbreeze Studios + +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. + +Written by: Marten Svanfeldt +*/ + +#include "Ragdoll.h" + +//#define RIGID 1 + +RagDoll::RagDoll (btDynamicsWorld* ownerWorld, const btVector3& positionOffset, + btScalar scale_ragdoll) : m_ownerWorld (ownerWorld) +{ + + + // Setup the geometry + m_shapes[BODYPART_PELVIS] = new btCapsuleShape( + btScalar(scale_ragdoll*0.15), btScalar(scale_ragdoll*0.20)); + m_shapes[BODYPART_SPINE] = new btCapsuleShape( + btScalar(scale_ragdoll*0.15), btScalar(scale_ragdoll*0.28)); + m_shapes[BODYPART_HEAD] = new btCapsuleShape(btScalar(scale_ragdoll*0.10), btScalar(scale_ragdoll*0.05)); + m_shapes[BODYPART_LEFT_UPPER_LEG] = new btCapsuleShape(btScalar(scale_ragdoll*0.07), btScalar(scale_ragdoll*0.45)); + m_shapes[BODYPART_LEFT_LOWER_LEG] = new btCapsuleShape(btScalar(scale_ragdoll*0.05), btScalar(scale_ragdoll*0.37)); + m_shapes[BODYPART_RIGHT_UPPER_LEG] = new btCapsuleShape(btScalar(scale_ragdoll*0.07), btScalar(scale_ragdoll*0.45)); + m_shapes[BODYPART_RIGHT_LOWER_LEG] = new btCapsuleShape(btScalar(scale_ragdoll*0.05), btScalar(scale_ragdoll*0.37)); + m_shapes[BODYPART_LEFT_UPPER_ARM] = new btCapsuleShape(btScalar(scale_ragdoll*0.05), btScalar(scale_ragdoll*0.33)); + m_shapes[BODYPART_LEFT_LOWER_ARM] = new btCapsuleShape(btScalar(scale_ragdoll*0.04), btScalar(scale_ragdoll*0.25)); + m_shapes[BODYPART_RIGHT_UPPER_ARM] = new btCapsuleShape(btScalar(scale_ragdoll*0.05), btScalar(scale_ragdoll*0.33)); + m_shapes[BODYPART_RIGHT_LOWER_ARM] = new btCapsuleShape(btScalar(scale_ragdoll*0.04), btScalar(scale_ragdoll*0.25)); + + // Setup all the rigid bodies + btTransform offset; offset.setIdentity(); + offset.setOrigin(positionOffset); + + btTransform transform; + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(0.), btScalar(scale_ragdoll*1.), btScalar(0.))); + m_bodies[BODYPART_PELVIS] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_PELVIS]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(0.), btScalar(scale_ragdoll*1.2), btScalar(0.))); + m_bodies[BODYPART_SPINE] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_SPINE]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(0.), btScalar(scale_ragdoll*1.6), btScalar(0.))); + m_bodies[BODYPART_HEAD] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_HEAD]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(-0.18*scale_ragdoll), btScalar(0.65*scale_ragdoll), +btScalar(0.))); + m_bodies[BODYPART_LEFT_UPPER_LEG] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_LEFT_UPPER_LEG]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(-0.18*scale_ragdoll), btScalar(0.2*scale_ragdoll), btScalar(0.))); + m_bodies[BODYPART_LEFT_LOWER_LEG] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_LEFT_LOWER_LEG]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(0.18*scale_ragdoll), btScalar(0.65*scale_ragdoll), btScalar(0.))); + m_bodies[BODYPART_RIGHT_UPPER_LEG] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_RIGHT_UPPER_LEG]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(0.18*scale_ragdoll), btScalar(0.2*scale_ragdoll), btScalar(0.))); + m_bodies[BODYPART_RIGHT_LOWER_LEG] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_RIGHT_LOWER_LEG]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(-0.35*scale_ragdoll), btScalar(1.45*scale_ragdoll), btScalar(0.))); + transform.getBasis().setEulerZYX(0,0,SIMD_HALF_PI); + m_bodies[BODYPART_LEFT_UPPER_ARM] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_LEFT_UPPER_ARM]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(-0.7*scale_ragdoll), btScalar(1.45*scale_ragdoll), btScalar(0.))); + transform.getBasis().setEulerZYX(0,0,SIMD_HALF_PI); + m_bodies[BODYPART_LEFT_LOWER_ARM] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_LEFT_LOWER_ARM]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(0.35*scale_ragdoll), btScalar(1.45*scale_ragdoll), btScalar(0.))); + transform.getBasis().setEulerZYX(0,0,-SIMD_HALF_PI); + m_bodies[BODYPART_RIGHT_UPPER_ARM] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_RIGHT_UPPER_ARM]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(0.7*scale_ragdoll), btScalar(1.45*scale_ragdoll), btScalar(0.))); + transform.getBasis().setEulerZYX(0,0,-SIMD_HALF_PI); + m_bodies[BODYPART_RIGHT_LOWER_ARM] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_RIGHT_LOWER_ARM]); + + // Setup some damping on the m_bodies + for (int i = 0; i < BODYPART_COUNT; ++i) + { + m_bodies[i]->setDamping(0.05f, 0.85f); + m_bodies[i]->setDeactivationTime(0.8f); + m_bodies[i]->setSleepingThresholds(1.6f, 2.5f); + } + +///////////////////////////// SETTING THE CONSTRAINTS /////////////////////////////////////////////7777 + // Now setup the constraints + btGeneric6DofConstraint * joint6DOF; + btTransform localA, localB; + bool useLinearReferenceFrameA = true; +/// ******* SPINE HEAD ******** /// + { + localA.setIdentity(); localB.setIdentity(); + + localA.setOrigin(btVector3(btScalar(0.), btScalar(0.30*scale_ragdoll), btScalar(0.))); + + localB.setOrigin(btVector3(btScalar(0.), btScalar(-0.14*scale_ragdoll), btScalar(0.))); + + joint6DOF = new btGeneric6DofConstraint(*m_bodies[BODYPART_SPINE], *m_bodies[BODYPART_HEAD], localA, localB,useLinearReferenceFrameA); + +#ifdef RIGID + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_EPSILON,-SIMD_EPSILON,-SIMD_EPSILON)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_EPSILON,SIMD_EPSILON,SIMD_EPSILON)); +#else + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_PI*0.3f,-SIMD_EPSILON,-SIMD_PI*0.3f)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_PI*0.5f,SIMD_EPSILON,SIMD_PI*0.3f)); +#endif + m_joints[JOINT_SPINE_HEAD] = joint6DOF; + m_ownerWorld->addConstraint(m_joints[JOINT_SPINE_HEAD], true); + } +/// *************************** /// + + + + +/// ******* LEFT SHOULDER ******** /// + { + localA.setIdentity(); localB.setIdentity(); + + localA.setOrigin(btVector3(btScalar(-0.2*scale_ragdoll), btScalar(0.15*scale_ragdoll), btScalar(0.))); + + localB.getBasis().setEulerZYX(SIMD_HALF_PI,0,-SIMD_HALF_PI); + localB.setOrigin(btVector3(btScalar(0.), btScalar(-0.18*scale_ragdoll), btScalar(0.))); + + joint6DOF = new btGeneric6DofConstraint(*m_bodies[BODYPART_SPINE], *m_bodies[BODYPART_LEFT_UPPER_ARM], localA, localB,useLinearReferenceFrameA); + +#ifdef RIGID + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_EPSILON,-SIMD_EPSILON,-SIMD_EPSILON)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_EPSILON,SIMD_EPSILON,SIMD_EPSILON)); +#else + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_PI*0.8f,-SIMD_EPSILON,-SIMD_PI*0.5f)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_PI*0.8f,SIMD_EPSILON,SIMD_PI*0.5f)); +#endif + m_joints[JOINT_LEFT_SHOULDER] = joint6DOF; + m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_SHOULDER], true); + } +/// *************************** /// + + +/// ******* RIGHT SHOULDER ******** /// + { + localA.setIdentity(); localB.setIdentity(); + + localA.setOrigin(btVector3(btScalar(0.2*scale_ragdoll), btScalar(0.15*scale_ragdoll), btScalar(0.))); + localB.getBasis().setEulerZYX(0,0,SIMD_HALF_PI); + localB.setOrigin(btVector3(btScalar(0.), btScalar(-0.18*scale_ragdoll), btScalar(0.))); + joint6DOF = new btGeneric6DofConstraint(*m_bodies[BODYPART_SPINE], *m_bodies[BODYPART_RIGHT_UPPER_ARM], localA, localB,useLinearReferenceFrameA); + +#ifdef RIGID + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_EPSILON,-SIMD_EPSILON,-SIMD_EPSILON)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_EPSILON,SIMD_EPSILON,SIMD_EPSILON)); +#else + + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_PI*0.8f,-SIMD_EPSILON,-SIMD_PI*0.5f)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_PI*0.8f,SIMD_EPSILON,SIMD_PI*0.5f)); +#endif + m_joints[JOINT_RIGHT_SHOULDER] = joint6DOF; + m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_SHOULDER], true); + } +/// *************************** /// + +/// ******* LEFT ELBOW ******** /// + { + localA.setIdentity(); localB.setIdentity(); + + localA.setOrigin(btVector3(btScalar(0.), btScalar(0.18*scale_ragdoll), btScalar(0.))); + localB.setOrigin(btVector3(btScalar(0.), btScalar(-0.14*scale_ragdoll), btScalar(0.))); + joint6DOF = new btGeneric6DofConstraint (*m_bodies[BODYPART_LEFT_UPPER_ARM], *m_bodies[BODYPART_LEFT_LOWER_ARM], localA, localB,useLinearReferenceFrameA); + +#ifdef RIGID + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_EPSILON,-SIMD_EPSILON,-SIMD_EPSILON)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_EPSILON,SIMD_EPSILON,SIMD_EPSILON)); +#else + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_EPSILON,-SIMD_EPSILON,-SIMD_EPSILON)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_PI*0.7f,SIMD_EPSILON,SIMD_EPSILON)); +#endif + m_joints[JOINT_LEFT_ELBOW] = joint6DOF; + m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_ELBOW], true); + } +/// *************************** /// + +/// ******* RIGHT ELBOW ******** /// + { + localA.setIdentity(); localB.setIdentity(); + + localA.setOrigin(btVector3(btScalar(0.), btScalar(0.18*scale_ragdoll), btScalar(0.))); + localB.setOrigin(btVector3(btScalar(0.), btScalar(-0.14*scale_ragdoll), btScalar(0.))); + joint6DOF = new btGeneric6DofConstraint (*m_bodies[BODYPART_RIGHT_UPPER_ARM], *m_bodies[BODYPART_RIGHT_LOWER_ARM], localA, localB,useLinearReferenceFrameA); + +#ifdef RIGID + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_EPSILON,-SIMD_EPSILON,-SIMD_EPSILON)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_EPSILON,SIMD_EPSILON,SIMD_EPSILON)); +#else + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_EPSILON,-SIMD_EPSILON,-SIMD_EPSILON)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_PI*0.7,SIMD_EPSILON,SIMD_EPSILON)); +#endif + + m_joints[JOINT_RIGHT_ELBOW] = joint6DOF; + m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_ELBOW], true); + } +/// *************************** /// + + +/// ******* PELVIS ******** /// + { + localA.setIdentity(); localB.setIdentity(); + + localA.getBasis().setEulerZYX(0,SIMD_HALF_PI,0); + localA.setOrigin(btVector3(btScalar(0.), btScalar(0.15*scale_ragdoll), btScalar(0.))); + localB.getBasis().setEulerZYX(0,SIMD_HALF_PI,0); + localB.setOrigin(btVector3(btScalar(0.), btScalar(-0.15*scale_ragdoll), btScalar(0.))); + joint6DOF = new btGeneric6DofConstraint (*m_bodies[BODYPART_PELVIS], *m_bodies[BODYPART_SPINE], localA, localB,useLinearReferenceFrameA); + +#ifdef RIGID + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_EPSILON,-SIMD_EPSILON,-SIMD_EPSILON)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_EPSILON,SIMD_EPSILON,SIMD_EPSILON)); +#else + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_PI*0.2,-SIMD_EPSILON,-SIMD_PI*0.3)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_PI*0.2,SIMD_EPSILON,SIMD_PI*0.6)); +#endif + m_joints[JOINT_PELVIS_SPINE] = joint6DOF; + m_ownerWorld->addConstraint(m_joints[JOINT_PELVIS_SPINE], true); + } +/// *************************** /// + +/// ******* LEFT HIP ******** /// + { + localA.setIdentity(); localB.setIdentity(); + + localA.setOrigin(btVector3(btScalar(-0.18*scale_ragdoll), btScalar(-0.10*scale_ragdoll), btScalar(0.))); + + localB.setOrigin(btVector3(btScalar(0.), btScalar(0.225*scale_ragdoll), btScalar(0.))); + + joint6DOF = new btGeneric6DofConstraint(*m_bodies[BODYPART_PELVIS], *m_bodies[BODYPART_LEFT_UPPER_LEG], localA, localB,useLinearReferenceFrameA); + +#ifdef RIGID + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_EPSILON,-SIMD_EPSILON,-SIMD_EPSILON)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_EPSILON,SIMD_EPSILON,SIMD_EPSILON)); +#else + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_HALF_PI*0.5,-SIMD_EPSILON,-SIMD_EPSILON)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_HALF_PI*0.8,SIMD_EPSILON,SIMD_HALF_PI*0.6f)); +#endif + m_joints[JOINT_LEFT_HIP] = joint6DOF; + m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_HIP], true); + } +/// *************************** /// + + +/// ******* RIGHT HIP ******** /// + { + localA.setIdentity(); localB.setIdentity(); + + localA.setOrigin(btVector3(btScalar(0.18*scale_ragdoll), btScalar(-0.10*scale_ragdoll), btScalar(0.))); + localB.setOrigin(btVector3(btScalar(0.), btScalar(0.225*scale_ragdoll), btScalar(0.))); + + joint6DOF = new btGeneric6DofConstraint(*m_bodies[BODYPART_PELVIS], *m_bodies[BODYPART_RIGHT_UPPER_LEG], localA, localB,useLinearReferenceFrameA); + +#ifdef RIGID + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_EPSILON,-SIMD_EPSILON,-SIMD_EPSILON)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_EPSILON,SIMD_EPSILON,SIMD_EPSILON)); +#else + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_HALF_PI*0.5,-SIMD_EPSILON,-SIMD_HALF_PI*0.6f)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_HALF_PI*0.8,SIMD_EPSILON,SIMD_EPSILON)); +#endif + m_joints[JOINT_RIGHT_HIP] = joint6DOF; + m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_HIP], true); + } +/// *************************** /// + + +/// ******* LEFT KNEE ******** /// + { + localA.setIdentity(); localB.setIdentity(); + + localA.setOrigin(btVector3(btScalar(0.), btScalar(-0.225*scale_ragdoll), btScalar(0.))); + localB.setOrigin(btVector3(btScalar(0.), btScalar(0.185*scale_ragdoll), btScalar(0.))); + joint6DOF = new btGeneric6DofConstraint (*m_bodies[BODYPART_LEFT_UPPER_LEG], *m_bodies[BODYPART_LEFT_LOWER_LEG], localA, localB,useLinearReferenceFrameA); +// +#ifdef RIGID + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_EPSILON,-SIMD_EPSILON,-SIMD_EPSILON)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_EPSILON,SIMD_EPSILON,SIMD_EPSILON)); +#else + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_EPSILON,-SIMD_EPSILON,-SIMD_EPSILON)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_PI*0.7f,SIMD_EPSILON,SIMD_EPSILON)); +#endif + m_joints[JOINT_LEFT_KNEE] = joint6DOF; + m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_KNEE], true); + } +/// *************************** /// + +/// ******* RIGHT KNEE ******** /// + { + localA.setIdentity(); localB.setIdentity(); + + localA.setOrigin(btVector3(btScalar(0.), btScalar(-0.225*scale_ragdoll), btScalar(0.))); + localB.setOrigin(btVector3(btScalar(0.), btScalar(0.185*scale_ragdoll), btScalar(0.))); + joint6DOF = new btGeneric6DofConstraint (*m_bodies[BODYPART_RIGHT_UPPER_LEG], *m_bodies[BODYPART_RIGHT_LOWER_LEG], localA, localB,useLinearReferenceFrameA); + +#ifdef RIGID + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_EPSILON,-SIMD_EPSILON,-SIMD_EPSILON)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_EPSILON,SIMD_EPSILON,SIMD_EPSILON)); +#else + joint6DOF->setAngularLowerLimit(btVector3(-SIMD_EPSILON,-SIMD_EPSILON,-SIMD_EPSILON)); + joint6DOF->setAngularUpperLimit(btVector3(SIMD_PI*0.7f,SIMD_EPSILON,SIMD_EPSILON)); +#endif + m_joints[JOINT_RIGHT_KNEE] = joint6DOF; + m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_KNEE], true); + } +/// *************************** /// + +} + + +RagDoll::~RagDoll() +{ + int i; + + // Remove all constraints + for (i = 0; i < JOINT_COUNT; ++i) + { + m_ownerWorld->removeConstraint(m_joints[i]); + delete m_joints[i]; m_joints[i] = 0; + } + + // Remove all bodies and shapes + for (i = 0; i < BODYPART_COUNT; ++i) + { + m_ownerWorld->removeRigidBody(m_bodies[i]); + + delete m_bodies[i]->getMotionState(); + + delete m_bodies[i]; m_bodies[i] = 0; + delete m_shapes[i]; m_shapes[i] = 0; + } +} + + +btRigidBody* RagDoll::localCreateRigidBody (btScalar mass, const btTransform& startTransform, btCollisionShape* shape) +{ + bool isDynamic = (mass != 0.f); + + btVector3 localInertia(0,0,0); + if (isDynamic) + shape->calculateLocalInertia(mass,localInertia); + + btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia); + rbInfo.m_additionalDamping = true; + btRigidBody* body = new btRigidBody(rbInfo); + + m_ownerWorld->addRigidBody(body); + + return body; +} diff --git a/Demos/GenericJointDemo/Ragdoll.h b/Demos/GenericJointDemo/Ragdoll.h new file mode 100644 index 0000000..29a9cbd --- /dev/null +++ b/Demos/GenericJointDemo/Ragdoll.h @@ -0,0 +1,71 @@ +#ifndef RAGDOLL_H_INCLUDED +#define RAGDOLL_H_INCLUDED + +#include "DemoApplication.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "btBulletDynamicsCommon.h" + + + + +class RagDoll +{ + enum + { + BODYPART_PELVIS = 0, + BODYPART_SPINE, + BODYPART_HEAD, + + BODYPART_LEFT_UPPER_LEG, + BODYPART_LEFT_LOWER_LEG, + + BODYPART_RIGHT_UPPER_LEG, + BODYPART_RIGHT_LOWER_LEG, + + BODYPART_LEFT_UPPER_ARM, + BODYPART_LEFT_LOWER_ARM, + + BODYPART_RIGHT_UPPER_ARM, + BODYPART_RIGHT_LOWER_ARM, + + BODYPART_COUNT + }; + + enum + { + JOINT_PELVIS_SPINE = 0, + JOINT_SPINE_HEAD, + + JOINT_LEFT_HIP, + JOINT_LEFT_KNEE, + + JOINT_RIGHT_HIP, + JOINT_RIGHT_KNEE, + + JOINT_LEFT_SHOULDER, + JOINT_LEFT_ELBOW, + + JOINT_RIGHT_SHOULDER, + JOINT_RIGHT_ELBOW, + + JOINT_COUNT + }; + + btDynamicsWorld* m_ownerWorld; + btCollisionShape* m_shapes[BODYPART_COUNT]; + btRigidBody* m_bodies[BODYPART_COUNT]; + btTypedConstraint* m_joints[JOINT_COUNT]; + + btRigidBody* localCreateRigidBody (btScalar mass, const btTransform& startTransform, btCollisionShape* shape); + +public: + RagDoll (btDynamicsWorld* ownerWorld, + const btVector3& positionOffset, + btScalar scale_ragdoll = btScalar(1.0)); + + ~RagDoll (); +}; + + + +#endif // RAGDOLL_H_INCLUDED diff --git a/Demos/GenericJointDemo/Win32GenericJointDemo.cpp b/Demos/GenericJointDemo/Win32GenericJointDemo.cpp new file mode 100644 index 0000000..990b1fa --- /dev/null +++ b/Demos/GenericJointDemo/Win32GenericJointDemo.cpp @@ -0,0 +1,25 @@ +#ifdef _WINDOWS +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "GenericJointDemo.h" + +///The 'createDemo' function is called from Bullet/Demos/OpenGL/Win32AppMain.cpp to instantiate this particular demo +DemoApplication* createDemo() +{ + return new GenericJointDemo(); +} + +#endif diff --git a/Demos/GenericJointDemo/main.cpp b/Demos/GenericJointDemo/main.cpp new file mode 100644 index 0000000..4dd56b8 --- /dev/null +++ b/Demos/GenericJointDemo/main.cpp @@ -0,0 +1,28 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2010 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 "GenericJointDemo.h" + +int main(int argc,char* argv[]) +{ + GenericJointDemo demoApp; +// demoApp.configDebugDrawer(&debugDrawer); + + demoApp.initPhysics(); + demoApp.setCameraDistance(btScalar(10.)); + + return glutmain(argc, argv,640,480,"Joint 6DOF - Sequencial Impulse Solver",&demoApp); + +} diff --git a/Demos/GimpactTestDemo/BunnyMesh.h b/Demos/GimpactTestDemo/BunnyMesh.h new file mode 100644 index 0000000..818bd02 --- /dev/null +++ b/Demos/GimpactTestDemo/BunnyMesh.h @@ -0,0 +1,1379 @@ +#ifndef BUNNY_MESH_H_ +#define BUNNY_MESH_H_ + + + +//***************************THE FAMOUS BUNNY TRIMESH********************************************// + +#define REAL btScalar +const int BUNNY_NUM_TRIANGLES =902; +const int BUNNY_NUM_VERTICES = 453; +const int BUNNY_NUM_INDICES = BUNNY_NUM_TRIANGLES * 3; + + +static REAL gVerticesBunny[BUNNY_NUM_VERTICES * 3] = { + REAL(-0.334392), REAL(0.133007), REAL(0.062259), + REAL(-0.350189), REAL(0.150354), REAL(-0.147769), + REAL(-0.234201), REAL(0.343811), REAL(-0.174307), + REAL(-0.200259), REAL(0.285207), REAL(0.093749), + REAL(0.003520), REAL(0.475208), REAL(-0.159365), + REAL(0.001856), REAL(0.419203), REAL(0.098582), + REAL(-0.252802), REAL(0.093666), REAL(0.237538), + REAL(-0.162901), REAL(0.237984), REAL(0.206905), + REAL(0.000865), REAL(0.318141), REAL(0.235370), + REAL(-0.414624), REAL(0.164083), REAL(-0.278254), + REAL(-0.262213), REAL(0.357334), REAL(-0.293246), + REAL(0.004628), REAL(0.482694), REAL(-0.338626), + REAL(-0.402162), REAL(0.133528), REAL(-0.443247), + REAL(-0.243781), REAL(0.324275), REAL(-0.436763), + REAL(0.005293), REAL(0.437592), REAL(-0.458332), + REAL(-0.339884), REAL(-0.041150), REAL(-0.668211), + REAL(-0.248382), REAL(0.255825), REAL(-0.627493), + REAL(0.006261), REAL(0.376103), REAL(-0.631506), + REAL(-0.216201), REAL(-0.126776), REAL(-0.886936), + REAL(-0.171075), REAL(0.011544), REAL(-0.881386), + REAL(-0.181074), REAL(0.098223), REAL(-0.814779), + REAL(-0.119891), REAL(0.218786), REAL(-0.760153), + REAL(-0.078895), REAL(0.276780), REAL(-0.739281), + REAL(0.006801), REAL(0.310959), REAL(-0.735661), + REAL(-0.168842), REAL(0.102387), REAL(-0.920381), + REAL(-0.104072), REAL(0.177278), REAL(-0.952530), + REAL(-0.129704), REAL(0.211848), REAL(-0.836678), + REAL(-0.099875), REAL(0.310931), REAL(-0.799381), + REAL(0.007237), REAL(0.361687), REAL(-0.794439), + REAL(-0.077913), REAL(0.258753), REAL(-0.921640), + REAL(0.007957), REAL(0.282241), REAL(-0.931680), + REAL(-0.252222), REAL(-0.550401), REAL(-0.557810), + REAL(-0.267633), REAL(-0.603419), REAL(-0.655209), + REAL(-0.446838), REAL(-0.118517), REAL(-0.466159), + REAL(-0.459488), REAL(-0.093017), REAL(-0.311341), + REAL(-0.370645), REAL(-0.100108), REAL(-0.159454), + REAL(-0.371984), REAL(-0.091991), REAL(-0.011044), + REAL(-0.328945), REAL(-0.098269), REAL(0.088659), + REAL(-0.282452), REAL(-0.018862), REAL(0.311501), + REAL(-0.352403), REAL(-0.131341), REAL(0.144902), + REAL(-0.364126), REAL(-0.200299), REAL(0.202388), + REAL(-0.283965), REAL(-0.231869), REAL(0.023668), + REAL(-0.298943), REAL(-0.155218), REAL(0.369716), + REAL(-0.293787), REAL(-0.121856), REAL(0.419097), + REAL(-0.290163), REAL(-0.290797), REAL(0.107824), + REAL(-0.264165), REAL(-0.272849), REAL(0.036347), + REAL(-0.228567), REAL(-0.372573), REAL(0.290309), + REAL(-0.190431), REAL(-0.286997), REAL(0.421917), + REAL(-0.191039), REAL(-0.240973), REAL(0.507118), + REAL(-0.287272), REAL(-0.276431), REAL(-0.065444), + REAL(-0.295675), REAL(-0.280818), REAL(-0.174200), + REAL(-0.399537), REAL(-0.313131), REAL(-0.376167), + REAL(-0.392666), REAL(-0.488581), REAL(-0.427494), + REAL(-0.331669), REAL(-0.570185), REAL(-0.466054), + REAL(-0.282290), REAL(-0.618140), REAL(-0.589220), + REAL(-0.374238), REAL(-0.594882), REAL(-0.323298), + REAL(-0.381071), REAL(-0.629723), REAL(-0.350777), + REAL(-0.382112), REAL(-0.624060), REAL(-0.221577), + REAL(-0.272701), REAL(-0.566522), REAL(0.259157), + REAL(-0.256702), REAL(-0.663406), REAL(0.286079), + REAL(-0.280948), REAL(-0.428359), REAL(0.055790), + REAL(-0.184974), REAL(-0.508894), REAL(0.326265), + REAL(-0.279971), REAL(-0.526918), REAL(0.395319), + REAL(-0.282599), REAL(-0.663393), REAL(0.412411), + REAL(-0.188329), REAL(-0.475093), REAL(0.417954), + REAL(-0.263384), REAL(-0.663396), REAL(0.466604), + REAL(-0.209063), REAL(-0.663393), REAL(0.509344), + REAL(-0.002044), REAL(-0.319624), REAL(0.553078), + REAL(-0.001266), REAL(-0.371260), REAL(0.413296), + REAL(-0.219753), REAL(-0.339762), REAL(-0.040921), + REAL(-0.256986), REAL(-0.282511), REAL(-0.006349), + REAL(-0.271706), REAL(-0.260881), REAL(0.001764), + REAL(-0.091191), REAL(-0.419184), REAL(-0.045912), + REAL(-0.114944), REAL(-0.429752), REAL(-0.124739), + REAL(-0.113970), REAL(-0.382987), REAL(-0.188540), + REAL(-0.243012), REAL(-0.464942), REAL(-0.242850), + REAL(-0.314815), REAL(-0.505402), REAL(-0.324768), + REAL(0.002774), REAL(-0.437526), REAL(-0.262766), + REAL(-0.072625), REAL(-0.417748), REAL(-0.221440), + REAL(-0.160112), REAL(-0.476932), REAL(-0.293450), + REAL(0.003859), REAL(-0.453425), REAL(-0.443916), + REAL(-0.120363), REAL(-0.581567), REAL(-0.438689), + REAL(-0.091499), REAL(-0.584191), REAL(-0.294511), + REAL(-0.116469), REAL(-0.599861), REAL(-0.188308), + REAL(-0.208032), REAL(-0.513640), REAL(-0.134649), + REAL(-0.235749), REAL(-0.610017), REAL(-0.040939), + REAL(-0.344916), REAL(-0.622487), REAL(-0.085380), + REAL(-0.336401), REAL(-0.531864), REAL(-0.212298), + REAL(0.001961), REAL(-0.459550), REAL(-0.135547), + REAL(-0.058296), REAL(-0.430536), REAL(-0.043440), + REAL(0.001378), REAL(-0.449511), REAL(-0.037762), + REAL(-0.130135), REAL(-0.510222), REAL(0.079144), + REAL(0.000142), REAL(-0.477549), REAL(0.157064), + REAL(-0.114284), REAL(-0.453206), REAL(0.304397), + REAL(-0.000592), REAL(-0.443558), REAL(0.285401), + REAL(-0.056215), REAL(-0.663402), REAL(0.326073), + REAL(-0.026248), REAL(-0.568010), REAL(0.273318), + REAL(-0.049261), REAL(-0.531064), REAL(0.389854), + REAL(-0.127096), REAL(-0.663398), REAL(0.479316), + REAL(-0.058384), REAL(-0.663401), REAL(0.372891), + REAL(-0.303961), REAL(0.054199), REAL(0.625921), + REAL(-0.268594), REAL(0.193403), REAL(0.502766), + REAL(-0.277159), REAL(0.126123), REAL(0.443289), + REAL(-0.287605), REAL(-0.005722), REAL(0.531844), + REAL(-0.231396), REAL(-0.121289), REAL(0.587387), + REAL(-0.253475), REAL(-0.081797), REAL(0.756541), + REAL(-0.195164), REAL(-0.137969), REAL(0.728011), + REAL(-0.167673), REAL(-0.156573), REAL(0.609388), + REAL(-0.145917), REAL(-0.169029), REAL(0.697600), + REAL(-0.077776), REAL(-0.214247), REAL(0.622586), + REAL(-0.076873), REAL(-0.214971), REAL(0.696301), + REAL(-0.002341), REAL(-0.233135), REAL(0.622859), + REAL(-0.002730), REAL(-0.213526), REAL(0.691267), + REAL(-0.003136), REAL(-0.192628), REAL(0.762731), + REAL(-0.056136), REAL(-0.201222), REAL(0.763806), + REAL(-0.114589), REAL(-0.166192), REAL(0.770723), + REAL(-0.155145), REAL(-0.129632), REAL(0.791738), + REAL(-0.183611), REAL(-0.058705), REAL(0.847012), + REAL(-0.165562), REAL(0.001980), REAL(0.833386), + REAL(-0.220084), REAL(0.019914), REAL(0.768935), + REAL(-0.255730), REAL(0.090306), REAL(0.670782), + REAL(-0.255594), REAL(0.113833), REAL(0.663389), + REAL(-0.226380), REAL(0.212655), REAL(0.617740), + REAL(-0.003367), REAL(-0.195342), REAL(0.799680), + REAL(-0.029743), REAL(-0.210508), REAL(0.827180), + REAL(-0.003818), REAL(-0.194783), REAL(0.873636), + REAL(-0.004116), REAL(-0.157907), REAL(0.931268), + REAL(-0.031280), REAL(-0.184555), REAL(0.889476), + REAL(-0.059885), REAL(-0.184448), REAL(0.841330), + REAL(-0.135333), REAL(-0.164332), REAL(0.878200), + REAL(-0.085574), REAL(-0.170948), REAL(0.925547), + REAL(-0.163833), REAL(-0.094170), REAL(0.897114), + REAL(-0.138444), REAL(-0.104250), REAL(0.945975), + REAL(-0.083497), REAL(-0.084934), REAL(0.979607), + REAL(-0.004433), REAL(-0.146642), REAL(0.985872), + REAL(-0.150715), REAL(0.032650), REAL(0.884111), + REAL(-0.135892), REAL(-0.035520), REAL(0.945455), + REAL(-0.070612), REAL(0.036849), REAL(0.975733), + REAL(-0.004458), REAL(-0.042526), REAL(1.015670), + REAL(-0.004249), REAL(0.046042), REAL(1.003240), + REAL(-0.086969), REAL(0.133224), REAL(0.947633), + REAL(-0.003873), REAL(0.161605), REAL(0.970499), + REAL(-0.125544), REAL(0.140012), REAL(0.917678), + REAL(-0.125651), REAL(0.250246), REAL(0.857602), + REAL(-0.003127), REAL(0.284070), REAL(0.878870), + REAL(-0.159174), REAL(0.125726), REAL(0.888878), + REAL(-0.183807), REAL(0.196970), REAL(0.844480), + REAL(-0.159890), REAL(0.291736), REAL(0.732480), + REAL(-0.199495), REAL(0.207230), REAL(0.779864), + REAL(-0.206182), REAL(0.164608), REAL(0.693257), + REAL(-0.186315), REAL(0.160689), REAL(0.817193), + REAL(-0.192827), REAL(0.166706), REAL(0.782271), + REAL(-0.175112), REAL(0.110008), REAL(0.860621), + REAL(-0.161022), REAL(0.057420), REAL(0.855111), + REAL(-0.172319), REAL(0.036155), REAL(0.816189), + REAL(-0.190318), REAL(0.064083), REAL(0.760605), + REAL(-0.195072), REAL(0.129179), REAL(0.731104), + REAL(-0.203126), REAL(0.410287), REAL(0.680536), + REAL(-0.216677), REAL(0.309274), REAL(0.642272), + REAL(-0.241515), REAL(0.311485), REAL(0.587832), + REAL(-0.002209), REAL(0.366663), REAL(0.749413), + REAL(-0.088230), REAL(0.396265), REAL(0.678635), + REAL(-0.170147), REAL(0.109517), REAL(0.840784), + REAL(-0.160521), REAL(0.067766), REAL(0.830650), + REAL(-0.181546), REAL(0.139805), REAL(0.812146), + REAL(-0.180495), REAL(0.148568), REAL(0.776087), + REAL(-0.180255), REAL(0.129125), REAL(0.744192), + REAL(-0.186298), REAL(0.078308), REAL(0.769352), + REAL(-0.167622), REAL(0.060539), REAL(0.806675), + REAL(-0.189876), REAL(0.102760), REAL(0.802582), + REAL(-0.108340), REAL(0.455446), REAL(0.657174), + REAL(-0.241585), REAL(0.527592), REAL(0.669296), + REAL(-0.265676), REAL(0.513366), REAL(0.634594), + REAL(-0.203073), REAL(0.478550), REAL(0.581526), + REAL(-0.266772), REAL(0.642330), REAL(0.602061), + REAL(-0.216961), REAL(0.564846), REAL(0.535435), + REAL(-0.202210), REAL(0.525495), REAL(0.475944), + REAL(-0.193888), REAL(0.467925), REAL(0.520606), + REAL(-0.265837), REAL(0.757267), REAL(0.500933), + REAL(-0.240306), REAL(0.653440), REAL(0.463215), + REAL(-0.309239), REAL(0.776868), REAL(0.304726), + REAL(-0.271009), REAL(0.683094), REAL(0.382018), + REAL(-0.312111), REAL(0.671099), REAL(0.286687), + REAL(-0.268791), REAL(0.624342), REAL(0.377231), + REAL(-0.302457), REAL(0.533996), REAL(0.360289), + REAL(-0.263656), REAL(0.529310), REAL(0.412564), + REAL(-0.282311), REAL(0.415167), REAL(0.447666), + REAL(-0.239201), REAL(0.442096), REAL(0.495604), + REAL(-0.220043), REAL(0.569026), REAL(0.445877), + REAL(-0.001263), REAL(0.395631), REAL(0.602029), + REAL(-0.057345), REAL(0.442535), REAL(0.572224), + REAL(-0.088927), REAL(0.506333), REAL(0.529106), + REAL(-0.125738), REAL(0.535076), REAL(0.612913), + REAL(-0.126251), REAL(0.577170), REAL(0.483159), + REAL(-0.149594), REAL(0.611520), REAL(0.557731), + REAL(-0.163188), REAL(0.660791), REAL(0.491080), + REAL(-0.172482), REAL(0.663387), REAL(0.415416), + REAL(-0.160464), REAL(0.591710), REAL(0.370659), + REAL(-0.156445), REAL(0.536396), REAL(0.378302), + REAL(-0.136496), REAL(0.444358), REAL(0.425226), + REAL(-0.095564), REAL(0.373768), REAL(0.473659), + REAL(-0.104146), REAL(0.315912), REAL(0.498104), + REAL(-0.000496), REAL(0.384194), REAL(0.473817), + REAL(-0.000183), REAL(0.297770), REAL(0.401486), + REAL(-0.129042), REAL(0.270145), REAL(0.434495), + REAL(0.000100), REAL(0.272963), REAL(0.349138), + REAL(-0.113060), REAL(0.236984), REAL(0.385554), + REAL(0.007260), REAL(0.016311), REAL(-0.883396), + REAL(0.007865), REAL(0.122104), REAL(-0.956137), + REAL(-0.032842), REAL(0.115282), REAL(-0.953252), + REAL(-0.089115), REAL(0.108449), REAL(-0.950317), + REAL(-0.047440), REAL(0.014729), REAL(-0.882756), + REAL(-0.104458), REAL(0.013137), REAL(-0.882070), + REAL(-0.086439), REAL(-0.584866), REAL(-0.608343), + REAL(-0.115026), REAL(-0.662605), REAL(-0.436732), + REAL(-0.071683), REAL(-0.665372), REAL(-0.606385), + REAL(-0.257884), REAL(-0.665381), REAL(-0.658052), + REAL(-0.272542), REAL(-0.665381), REAL(-0.592063), + REAL(-0.371322), REAL(-0.665382), REAL(-0.353620), + REAL(-0.372362), REAL(-0.665381), REAL(-0.224420), + REAL(-0.335166), REAL(-0.665380), REAL(-0.078623), + REAL(-0.225999), REAL(-0.665375), REAL(-0.038981), + REAL(-0.106719), REAL(-0.665374), REAL(-0.186351), + REAL(-0.081749), REAL(-0.665372), REAL(-0.292554), + REAL(0.006943), REAL(-0.091505), REAL(-0.858354), + REAL(0.006117), REAL(-0.280985), REAL(-0.769967), + REAL(0.004495), REAL(-0.502360), REAL(-0.559799), + REAL(-0.198638), REAL(-0.302135), REAL(-0.845816), + REAL(-0.237395), REAL(-0.542544), REAL(-0.587188), + REAL(-0.270001), REAL(-0.279489), REAL(-0.669861), + REAL(-0.134547), REAL(-0.119852), REAL(-0.959004), + REAL(-0.052088), REAL(-0.122463), REAL(-0.944549), + REAL(-0.124463), REAL(-0.293508), REAL(-0.899566), + REAL(-0.047616), REAL(-0.289643), REAL(-0.879292), + REAL(-0.168595), REAL(-0.529132), REAL(-0.654931), + REAL(-0.099793), REAL(-0.515719), REAL(-0.645873), + REAL(-0.186168), REAL(-0.605282), REAL(-0.724690), + REAL(-0.112970), REAL(-0.583097), REAL(-0.707469), + REAL(-0.108152), REAL(-0.665375), REAL(-0.700408), + REAL(-0.183019), REAL(-0.665378), REAL(-0.717630), + REAL(-0.349529), REAL(-0.334459), REAL(-0.511985), + REAL(-0.141182), REAL(-0.437705), REAL(-0.798194), + REAL(-0.212670), REAL(-0.448725), REAL(-0.737447), + REAL(-0.261111), REAL(-0.414945), REAL(-0.613835), + REAL(-0.077364), REAL(-0.431480), REAL(-0.778113), + REAL(0.005174), REAL(-0.425277), REAL(-0.651592), + REAL(0.089236), REAL(-0.431732), REAL(-0.777093), + REAL(0.271006), REAL(-0.415749), REAL(-0.610577), + REAL(0.223981), REAL(-0.449384), REAL(-0.734774), + REAL(0.153275), REAL(-0.438150), REAL(-0.796391), + REAL(0.358414), REAL(-0.335529), REAL(-0.507649), + REAL(0.193434), REAL(-0.665946), REAL(-0.715325), + REAL(0.118363), REAL(-0.665717), REAL(-0.699021), + REAL(0.123515), REAL(-0.583454), REAL(-0.706020), + REAL(0.196851), REAL(-0.605860), REAL(-0.722345), + REAL(0.109788), REAL(-0.516035), REAL(-0.644590), + REAL(0.178656), REAL(-0.529656), REAL(-0.652804), + REAL(0.061157), REAL(-0.289807), REAL(-0.878626), + REAL(0.138234), REAL(-0.293905), REAL(-0.897958), + REAL(0.066933), REAL(-0.122643), REAL(-0.943820), + REAL(0.149571), REAL(-0.120281), REAL(-0.957264), + REAL(0.280989), REAL(-0.280321), REAL(-0.666487), + REAL(0.246581), REAL(-0.543275), REAL(-0.584224), + REAL(0.211720), REAL(-0.302754), REAL(-0.843303), + REAL(0.086966), REAL(-0.665627), REAL(-0.291520), + REAL(0.110634), REAL(-0.665702), REAL(-0.185021), + REAL(0.228099), REAL(-0.666061), REAL(-0.036201), + REAL(0.337743), REAL(-0.666396), REAL(-0.074503), + REAL(0.376722), REAL(-0.666513), REAL(-0.219833), + REAL(0.377265), REAL(-0.666513), REAL(-0.349036), + REAL(0.281411), REAL(-0.666217), REAL(-0.588670), + REAL(0.267564), REAL(-0.666174), REAL(-0.654834), + REAL(0.080745), REAL(-0.665602), REAL(-0.605452), + REAL(0.122016), REAL(-0.662963), REAL(-0.435280), + REAL(0.095767), REAL(-0.585141), REAL(-0.607228), + REAL(0.118944), REAL(0.012799), REAL(-0.880702), + REAL(0.061944), REAL(0.014564), REAL(-0.882086), + REAL(0.104725), REAL(0.108156), REAL(-0.949130), + REAL(0.048513), REAL(0.115159), REAL(-0.952753), + REAL(0.112696), REAL(0.236643), REAL(0.386937), + REAL(0.128177), REAL(0.269757), REAL(0.436071), + REAL(0.102643), REAL(0.315600), REAL(0.499370), + REAL(0.094535), REAL(0.373481), REAL(0.474824), + REAL(0.136270), REAL(0.443946), REAL(0.426895), + REAL(0.157071), REAL(0.535923), REAL(0.380222), + REAL(0.161350), REAL(0.591224), REAL(0.372630), + REAL(0.173035), REAL(0.662865), REAL(0.417531), + REAL(0.162808), REAL(0.660299), REAL(0.493077), + REAL(0.148250), REAL(0.611070), REAL(0.559555), + REAL(0.125719), REAL(0.576790), REAL(0.484702), + REAL(0.123489), REAL(0.534699), REAL(0.614440), + REAL(0.087621), REAL(0.506066), REAL(0.530188), + REAL(0.055321), REAL(0.442365), REAL(0.572915), + REAL(0.219936), REAL(0.568361), REAL(0.448571), + REAL(0.238099), REAL(0.441375), REAL(0.498528), + REAL(0.281711), REAL(0.414315), REAL(0.451121), + REAL(0.263833), REAL(0.528513), REAL(0.415794), + REAL(0.303284), REAL(0.533081), REAL(0.363998), + REAL(0.269687), REAL(0.623528), REAL(0.380528), + REAL(0.314255), REAL(0.670153), REAL(0.290524), + REAL(0.272023), REAL(0.682273), REAL(0.385343), + REAL(0.311480), REAL(0.775931), REAL(0.308527), + REAL(0.240239), REAL(0.652714), REAL(0.466159), + REAL(0.265619), REAL(0.756464), REAL(0.504187), + REAL(0.192562), REAL(0.467341), REAL(0.522972), + REAL(0.201605), REAL(0.524885), REAL(0.478417), + REAL(0.215743), REAL(0.564193), REAL(0.538084), + REAL(0.264969), REAL(0.641527), REAL(0.605317), + REAL(0.201031), REAL(0.477940), REAL(0.584002), + REAL(0.263086), REAL(0.512567), REAL(0.637832), + REAL(0.238615), REAL(0.526867), REAL(0.672237), + REAL(0.105309), REAL(0.455123), REAL(0.658482), + REAL(0.183993), REAL(0.102195), REAL(0.804872), + REAL(0.161563), REAL(0.060042), REAL(0.808692), + REAL(0.180748), REAL(0.077754), REAL(0.771600), + REAL(0.175168), REAL(0.128588), REAL(0.746368), + REAL(0.175075), REAL(0.148030), REAL(0.778264), + REAL(0.175658), REAL(0.139265), REAL(0.814333), + REAL(0.154191), REAL(0.067291), REAL(0.832578), + REAL(0.163818), REAL(0.109013), REAL(0.842830), + REAL(0.084760), REAL(0.396004), REAL(0.679695), + REAL(0.238888), REAL(0.310760), REAL(0.590775), + REAL(0.213380), REAL(0.308625), REAL(0.644905), + REAL(0.199666), REAL(0.409678), REAL(0.683003), + REAL(0.190143), REAL(0.128597), REAL(0.733463), + REAL(0.184833), REAL(0.063516), REAL(0.762902), + REAL(0.166070), REAL(0.035644), REAL(0.818261), + REAL(0.154361), REAL(0.056943), REAL(0.857042), + REAL(0.168542), REAL(0.109489), REAL(0.862725), + REAL(0.187387), REAL(0.166131), REAL(0.784599), + REAL(0.180428), REAL(0.160135), REAL(0.819438), + REAL(0.201823), REAL(0.163991), REAL(0.695756), + REAL(0.194206), REAL(0.206635), REAL(0.782275), + REAL(0.155438), REAL(0.291260), REAL(0.734412), + REAL(0.177696), REAL(0.196424), REAL(0.846693), + REAL(0.152305), REAL(0.125256), REAL(0.890786), + REAL(0.119546), REAL(0.249876), REAL(0.859104), + REAL(0.118369), REAL(0.139643), REAL(0.919173), + REAL(0.079410), REAL(0.132973), REAL(0.948652), + REAL(0.062419), REAL(0.036648), REAL(0.976547), + REAL(0.127847), REAL(-0.035919), REAL(0.947070), + REAL(0.143624), REAL(0.032206), REAL(0.885913), + REAL(0.074888), REAL(-0.085173), REAL(0.980577), + REAL(0.130184), REAL(-0.104656), REAL(0.947620), + REAL(0.156201), REAL(-0.094653), REAL(0.899074), + REAL(0.077366), REAL(-0.171194), REAL(0.926545), + REAL(0.127722), REAL(-0.164729), REAL(0.879810), + REAL(0.052670), REAL(-0.184618), REAL(0.842019), + REAL(0.023477), REAL(-0.184638), REAL(0.889811), + REAL(0.022626), REAL(-0.210587), REAL(0.827500), + REAL(0.223089), REAL(0.211976), REAL(0.620493), + REAL(0.251444), REAL(0.113067), REAL(0.666494), + REAL(0.251419), REAL(0.089540), REAL(0.673887), + REAL(0.214360), REAL(0.019258), REAL(0.771595), + REAL(0.158999), REAL(0.001490), REAL(0.835374), + REAL(0.176696), REAL(-0.059249), REAL(0.849218), + REAL(0.148696), REAL(-0.130091), REAL(0.793599), + REAL(0.108290), REAL(-0.166528), REAL(0.772088), + REAL(0.049820), REAL(-0.201382), REAL(0.764454), + REAL(0.071341), REAL(-0.215195), REAL(0.697209), + REAL(0.073148), REAL(-0.214475), REAL(0.623510), + REAL(0.140502), REAL(-0.169461), REAL(0.699354), + REAL(0.163374), REAL(-0.157073), REAL(0.611416), + REAL(0.189466), REAL(-0.138550), REAL(0.730366), + REAL(0.247593), REAL(-0.082554), REAL(0.759610), + REAL(0.227468), REAL(-0.121982), REAL(0.590197), + REAL(0.284702), REAL(-0.006586), REAL(0.535347), + REAL(0.275741), REAL(0.125287), REAL(0.446676), + REAL(0.266650), REAL(0.192594), REAL(0.506044), + REAL(0.300086), REAL(0.053287), REAL(0.629620), + REAL(0.055450), REAL(-0.663935), REAL(0.375065), + REAL(0.122854), REAL(-0.664138), REAL(0.482323), + REAL(0.046520), REAL(-0.531571), REAL(0.391918), + REAL(0.024824), REAL(-0.568450), REAL(0.275106), + REAL(0.053855), REAL(-0.663931), REAL(0.328224), + REAL(0.112829), REAL(-0.453549), REAL(0.305788), + REAL(0.131265), REAL(-0.510617), REAL(0.080746), + REAL(0.061174), REAL(-0.430716), REAL(-0.042710), + REAL(0.341019), REAL(-0.532887), REAL(-0.208150), + REAL(0.347705), REAL(-0.623533), REAL(-0.081139), + REAL(0.238040), REAL(-0.610732), REAL(-0.038037), + REAL(0.211764), REAL(-0.514274), REAL(-0.132078), + REAL(0.120605), REAL(-0.600219), REAL(-0.186856), + REAL(0.096985), REAL(-0.584476), REAL(-0.293357), + REAL(0.127621), REAL(-0.581941), REAL(-0.437170), + REAL(0.165902), REAL(-0.477425), REAL(-0.291453), + REAL(0.077720), REAL(-0.417975), REAL(-0.220519), + REAL(0.320892), REAL(-0.506363), REAL(-0.320874), + REAL(0.248214), REAL(-0.465684), REAL(-0.239842), + REAL(0.118764), REAL(-0.383338), REAL(-0.187114), + REAL(0.118816), REAL(-0.430106), REAL(-0.123307), + REAL(0.094131), REAL(-0.419464), REAL(-0.044777), + REAL(0.274526), REAL(-0.261706), REAL(0.005110), + REAL(0.259842), REAL(-0.283292), REAL(-0.003185), + REAL(0.222861), REAL(-0.340431), REAL(-0.038210), + REAL(0.204445), REAL(-0.664380), REAL(0.513353), + REAL(0.259286), REAL(-0.664547), REAL(0.471281), + REAL(0.185402), REAL(-0.476020), REAL(0.421718), + REAL(0.279163), REAL(-0.664604), REAL(0.417328), + REAL(0.277157), REAL(-0.528122), REAL(0.400208), + REAL(0.183069), REAL(-0.509812), REAL(0.329995), + REAL(0.282599), REAL(-0.429210), REAL(0.059242), + REAL(0.254816), REAL(-0.664541), REAL(0.290687), + REAL(0.271436), REAL(-0.567707), REAL(0.263966), + REAL(0.386561), REAL(-0.625221), REAL(-0.216870), + REAL(0.387086), REAL(-0.630883), REAL(-0.346073), + REAL(0.380021), REAL(-0.596021), REAL(-0.318679), + REAL(0.291269), REAL(-0.619007), REAL(-0.585707), + REAL(0.339280), REAL(-0.571198), REAL(-0.461946), + REAL(0.400045), REAL(-0.489778), REAL(-0.422640), + REAL(0.406817), REAL(-0.314349), REAL(-0.371230), + REAL(0.300588), REAL(-0.281718), REAL(-0.170549), + REAL(0.290866), REAL(-0.277304), REAL(-0.061905), + REAL(0.187735), REAL(-0.241545), REAL(0.509437), + REAL(0.188032), REAL(-0.287569), REAL(0.424234), + REAL(0.227520), REAL(-0.373262), REAL(0.293102), + REAL(0.266526), REAL(-0.273650), REAL(0.039597), + REAL(0.291592), REAL(-0.291676), REAL(0.111386), + REAL(0.291914), REAL(-0.122741), REAL(0.422683), + REAL(0.297574), REAL(-0.156119), REAL(0.373368), + REAL(0.286603), REAL(-0.232731), REAL(0.027162), + REAL(0.364663), REAL(-0.201399), REAL(0.206850), + REAL(0.353855), REAL(-0.132408), REAL(0.149228), + REAL(0.282208), REAL(-0.019715), REAL(0.314960), + REAL(0.331187), REAL(-0.099266), REAL(0.092701), + REAL(0.375463), REAL(-0.093120), REAL(-0.006467), + REAL(0.375917), REAL(-0.101236), REAL(-0.154882), + REAL(0.466635), REAL(-0.094416), REAL(-0.305669), + REAL(0.455805), REAL(-0.119881), REAL(-0.460632), + REAL(0.277465), REAL(-0.604242), REAL(-0.651871), + REAL(0.261022), REAL(-0.551176), REAL(-0.554667), + REAL(0.093627), REAL(0.258494), REAL(-0.920589), + REAL(0.114248), REAL(0.310608), REAL(-0.798070), + REAL(0.144232), REAL(0.211434), REAL(-0.835001), + REAL(0.119916), REAL(0.176940), REAL(-0.951159), + REAL(0.184061), REAL(0.101854), REAL(-0.918220), + REAL(0.092431), REAL(0.276521), REAL(-0.738231), + REAL(0.133504), REAL(0.218403), REAL(-0.758602), + REAL(0.194987), REAL(0.097655), REAL(-0.812476), + REAL(0.185542), REAL(0.011005), REAL(-0.879202), + REAL(0.230315), REAL(-0.127450), REAL(-0.884202), + REAL(0.260471), REAL(0.255056), REAL(-0.624378), + REAL(0.351567), REAL(-0.042194), REAL(-0.663976), + REAL(0.253742), REAL(0.323524), REAL(-0.433716), + REAL(0.411612), REAL(0.132299), REAL(-0.438264), + REAL(0.270513), REAL(0.356530), REAL(-0.289984), + REAL(0.422146), REAL(0.162819), REAL(-0.273130), + REAL(0.164724), REAL(0.237490), REAL(0.208912), + REAL(0.253806), REAL(0.092900), REAL(0.240640), + REAL(0.203608), REAL(0.284597), REAL(0.096223), + REAL(0.241006), REAL(0.343093), REAL(-0.171396), + REAL(0.356076), REAL(0.149288), REAL(-0.143443), + REAL(0.337656), REAL(0.131992), REAL(0.066374) +}; + +static int gIndicesBunny[BUNNY_NUM_TRIANGLES][3] = { + {126,134,133}, + {342,138,134}, + {133,134,138}, + {126,342,134}, + {312,316,317}, + {169,163,162}, + {312,317,319}, + {312,319,318}, + {169,162,164}, + {169,168,163}, + {312,314,315}, + {169,164,165}, + {169,167,168}, + {312,315,316}, + {312,313,314}, + {169,165,166}, + {169,166,167}, + {312,318,313}, + {308,304,305}, + {308,305,306}, + {179,181,188}, + {177,173,175}, + {177,175,176}, + {302,293,300}, + {322,294,304}, + {188,176,175}, + {188,175,179}, + {158,177,187}, + {305,293,302}, + {305,302,306}, + {322,304,308}, + {188,181,183}, + {158,173,177}, + {293,298,300}, + {304,294,296}, + {304,296,305}, + {185,176,188}, + {185,188,183}, + {187,177,176}, + {187,176,185}, + {305,296,298}, + {305,298,293}, + {436,432, 28}, + {436, 28, 23}, + {434,278,431}, + { 30,208,209}, + { 30,209, 29}, + { 19, 20, 24}, + {208,207,211}, + {208,211,209}, + { 19,210,212}, + {433,434,431}, + {433,431,432}, + {433,432,436}, + {436,437,433}, + {277,275,276}, + {277,276,278}, + {209,210, 25}, + { 21, 26, 24}, + { 21, 24, 20}, + { 25, 26, 27}, + { 25, 27, 29}, + {435,439,277}, + {439,275,277}, + {432,431, 30}, + {432, 30, 28}, + {433,437,438}, + {433,438,435}, + {434,277,278}, + { 24, 25,210}, + { 24, 26, 25}, + { 29, 27, 28}, + { 29, 28, 30}, + { 19, 24,210}, + {208, 30,431}, + {208,431,278}, + {435,434,433}, + {435,277,434}, + { 25, 29,209}, + { 27, 22, 23}, + { 27, 23, 28}, + { 26, 22, 27}, + { 26, 21, 22}, + {212,210,209}, + {212,209,211}, + {207,208,278}, + {207,278,276}, + {439,435,438}, + { 12, 9, 10}, + { 12, 10, 13}, + { 2, 3, 5}, + { 2, 5, 4}, + { 16, 13, 14}, + { 16, 14, 17}, + { 22, 21, 16}, + { 13, 10, 11}, + { 13, 11, 14}, + { 1, 0, 3}, + { 1, 3, 2}, + { 15, 12, 16}, + { 19, 18, 15}, + { 19, 15, 16}, + { 19, 16, 20}, + { 9, 1, 2}, + { 9, 2, 10}, + { 3, 7, 8}, + { 3, 8, 5}, + { 16, 17, 23}, + { 16, 23, 22}, + { 21, 20, 16}, + { 10, 2, 4}, + { 10, 4, 11}, + { 0, 6, 7}, + { 0, 7, 3}, + { 12, 13, 16}, + {451,446,445}, + {451,445,450}, + {442,440,439}, + {442,439,438}, + {442,438,441}, + {421,420,422}, + {412,411,426}, + {412,426,425}, + {408,405,407}, + {413, 67, 68}, + {413, 68,414}, + {391,390,412}, + { 80,384,386}, + {404,406,378}, + {390,391,377}, + {390,377, 88}, + {400,415,375}, + {398,396,395}, + {398,395,371}, + {398,371,370}, + {112,359,358}, + {112,358,113}, + {351,352,369}, + {125,349,348}, + {345,343,342}, + {342,340,339}, + {341,335,337}, + {328,341,327}, + {331,323,333}, + {331,322,323}, + {327,318,319}, + {327,319,328}, + {315,314,324}, + {302,300,301}, + {302,301,303}, + {320,311,292}, + {285,284,289}, + {310,307,288}, + {310,288,290}, + {321,350,281}, + {321,281,282}, + {423,448,367}, + {272,273,384}, + {272,384,274}, + {264,265,382}, + {264,382,383}, + {440,442,261}, + {440,261,263}, + {252,253,254}, + {252,254,251}, + {262,256,249}, + {262,249,248}, + {228,243,242}, + {228, 31,243}, + {213,215,238}, + {213,238,237}, + { 19,212,230}, + {224,225,233}, + {224,233,231}, + {217,218, 56}, + {217, 56, 54}, + {217,216,239}, + {217,239,238}, + {217,238,215}, + {218,217,215}, + {218,215,214}, + { 6,102,206}, + {186,199,200}, + {197,182,180}, + {170,171,157}, + {201,200,189}, + {170,190,191}, + {170,191,192}, + {175,174,178}, + {175,178,179}, + {168,167,155}, + {122,149,158}, + {122,158,159}, + {135,153,154}, + {135,154,118}, + {143,140,141}, + {143,141,144}, + {132,133,136}, + {130,126,133}, + {124,125,127}, + {122,101,100}, + {122,100,121}, + {110,108,107}, + {110,107,109}, + { 98, 99, 97}, + { 98, 97, 64}, + { 98, 64, 66}, + { 87, 55, 57}, + { 83, 82, 79}, + { 83, 79, 84}, + { 78, 74, 50}, + { 49, 71, 41}, + { 49, 41, 37}, + { 49, 37, 36}, + { 58, 44, 60}, + { 60, 59, 58}, + { 51, 34, 33}, + { 39, 40, 42}, + { 39, 42, 38}, + {243,240, 33}, + {243, 33,229}, + { 39, 38, 6}, + { 44, 46, 40}, + { 55, 56, 57}, + { 64, 62, 65}, + { 64, 65, 66}, + { 41, 71, 45}, + { 75, 50, 51}, + { 81, 79, 82}, + { 77, 88, 73}, + { 93, 92, 94}, + { 68, 47, 46}, + { 96, 97, 99}, + { 96, 99, 95}, + {110,109,111}, + {111,112,110}, + {114,113,123}, + {114,123,124}, + {132,131,129}, + {133,137,136}, + {135,142,145}, + {145,152,135}, + {149,147,157}, + {157,158,149}, + {164,150,151}, + {153,163,168}, + {153,168,154}, + {185,183,182}, + {185,182,184}, + {161,189,190}, + {200,199,191}, + {200,191,190}, + {180,178,195}, + {180,195,196}, + {102,101,204}, + {102,204,206}, + { 43, 48,104}, + { 43,104,103}, + {216,217, 54}, + {216, 54, 32}, + {207,224,231}, + {230,212,211}, + {230,211,231}, + {227,232,241}, + {227,241,242}, + {235,234,241}, + {235,241,244}, + {430,248,247}, + {272,274,253}, + {272,253,252}, + {439,260,275}, + {225,224,259}, + {225,259,257}, + {269,270,407}, + {269,407,405}, + {270,269,273}, + {270,273,272}, + {273,269,268}, + {273,268,267}, + {273,267,266}, + {273,266,265}, + {273,265,264}, + {448,279,367}, + {281,350,368}, + {285,286,301}, + {290,323,310}, + {290,311,323}, + {282,281,189}, + {292,311,290}, + {292,290,291}, + {307,306,302}, + {307,302,303}, + {316,315,324}, + {316,324,329}, + {331,351,350}, + {330,334,335}, + {330,335,328}, + {341,337,338}, + {344,355,354}, + {346,345,348}, + {346,348,347}, + {364,369,352}, + {364,352,353}, + {365,363,361}, + {365,361,362}, + {376,401,402}, + {373,372,397}, + {373,397,400}, + {376, 92,377}, + {381,378,387}, + {381,387,385}, + {386, 77, 80}, + {390,389,412}, + {416,417,401}, + {403,417,415}, + {408,429,430}, + {419,423,418}, + {427,428,444}, + {427,444,446}, + {437,436,441}, + {450,445, 11}, + {450, 11, 4}, + {447,449, 5}, + {447, 5, 8}, + {441,438,437}, + {425,426,451}, + {425,451,452}, + {417,421,415}, + {408,407,429}, + {399,403,400}, + {399,400,397}, + {394,393,416}, + {389,411,412}, + {386,383,385}, + {408,387,378}, + {408,378,406}, + {377,391,376}, + { 94,375,415}, + {372,373,374}, + {372,374,370}, + {359,111,360}, + {359,112,111}, + {113,358,349}, + {113,349,123}, + {346,343,345}, + {343,340,342}, + {338,336,144}, + {338,144,141}, + {327,341,354}, + {327,354,326}, + {331,350,321}, + {331,321,322}, + {314,313,326}, + {314,326,325}, + {300,298,299}, + {300,299,301}, + {288,287,289}, + {189,292,282}, + {287,288,303}, + {284,285,297}, + {368,280,281}, + {448,447,279}, + {274,226,255}, + {267,268,404}, + {267,404,379}, + {429,262,430}, + {439,440,260}, + {257,258,249}, + {257,249,246}, + {430,262,248}, + {234,228,242}, + {234,242,241}, + {237,238,239}, + {237,239,236}, + { 15, 18,227}, + { 15,227,229}, + {222,223, 82}, + {222, 82, 83}, + {214,215,213}, + {214,213, 81}, + { 38,102, 6}, + {122,159,200}, + {122,200,201}, + {174,171,192}, + {174,192,194}, + {197,193,198}, + {190,170,161}, + {181,179,178}, + {181,178,180}, + {166,156,155}, + {163,153,152}, + {163,152,162}, + {120,156,149}, + {120,149,121}, + {152,153,135}, + {140,143,142}, + {135,131,132}, + {135,132,136}, + {130,129,128}, + {130,128,127}, + {100,105,119}, + {100,119,120}, + {106,104,107}, + {106,107,108}, + { 91, 95, 59}, + { 93, 94, 68}, + { 91, 89, 92}, + { 76, 53, 55}, + { 76, 55, 87}, + { 81, 78, 79}, + { 74, 73, 49}, + { 69, 60, 45}, + { 58, 62, 64}, + { 58, 64, 61}, + { 53, 31, 32}, + { 32, 54, 53}, + { 42, 43, 38}, + { 35, 36, 0}, + { 35, 0, 1}, + { 34, 35, 1}, + { 34, 1, 9}, + { 44, 40, 41}, + { 44, 41, 45}, + { 33,240, 51}, + { 63, 62, 58}, + { 63, 58, 59}, + { 45, 71, 70}, + { 76, 75, 51}, + { 76, 51, 52}, + { 86, 85, 84}, + { 86, 84, 87}, + { 89, 72, 73}, + { 89, 73, 88}, + { 91, 92, 96}, + { 91, 96, 95}, + { 72, 91, 60}, + { 72, 60, 69}, + {104,106,105}, + {119,105,117}, + {119,117,118}, + {124,127,128}, + {117,116,129}, + {117,129,131}, + {118,117,131}, + {135,140,142}, + {146,150,152}, + {146,152,145}, + {149,122,121}, + {166,165,151}, + {166,151,156}, + {158,172,173}, + {161,160,189}, + {199,198,193}, + {199,193,191}, + {204,201,202}, + {178,174,194}, + {200,159,186}, + {109, 48, 67}, + { 48,107,104}, + {216, 32,236}, + {216,236,239}, + {223,214, 81}, + {223, 81, 82}, + { 33, 12, 15}, + { 32,228,234}, + { 32,234,236}, + {240, 31, 52}, + {256,255,246}, + {256,246,249}, + {258,263,248}, + {258,248,249}, + {275,260,259}, + {275,259,276}, + {207,276,259}, + {270,271,429}, + {270,429,407}, + {413,418,366}, + {413,366,365}, + {368,367,279}, + {368,279,280}, + {303,301,286}, + {303,286,287}, + {283,282,292}, + {283,292,291}, + {320,292,189}, + {298,296,297}, + {298,297,299}, + {318,327,326}, + {318,326,313}, + {329,330,317}, + {336,333,320}, + {326,354,353}, + {334,332,333}, + {334,333,336}, + {342,339,139}, + {342,139,138}, + {345,342,126}, + {347,357,356}, + {369,368,351}, + {363,356,357}, + {363,357,361}, + {366,367,368}, + {366,368,369}, + {375,373,400}, + { 92, 90,377}, + {409,387,408}, + {386,385,387}, + {386,387,388}, + {412,394,391}, + {396,398,399}, + {408,406,405}, + {415,421,419}, + {415,419,414}, + {425,452,448}, + {425,448,424}, + {444,441,443}, + {448,452,449}, + {448,449,447}, + {446,444,443}, + {446,443,445}, + {250,247,261}, + {250,261,428}, + {421,422,423}, + {421,423,419}, + {427,410,250}, + {417,403,401}, + {403,402,401}, + {420,392,412}, + {420,412,425}, + {420,425,424}, + {386,411,389}, + {383,382,381}, + {383,381,385}, + {378,379,404}, + {372,371,395}, + {372,395,397}, + {371,372,370}, + {361,359,360}, + {361,360,362}, + {368,350,351}, + {349,347,348}, + {356,355,344}, + {356,344,346}, + {344,341,340}, + {344,340,343}, + {338,337,336}, + {328,335,341}, + {324,352,351}, + {324,351,331}, + {320,144,336}, + {314,325,324}, + {322,308,309}, + {310,309,307}, + {287,286,289}, + {203,280,279}, + {203,279,205}, + {297,295,283}, + {297,283,284}, + {447,205,279}, + {274,384, 80}, + {274, 80,226}, + {266,267,379}, + {266,379,380}, + {225,257,246}, + {225,246,245}, + {256,254,253}, + {256,253,255}, + {430,247,250}, + {226,235,244}, + {226,244,245}, + {232,233,244}, + {232,244,241}, + {230, 18, 19}, + { 32, 31,228}, + {219,220, 86}, + {219, 86, 57}, + {226,213,235}, + {206, 7, 6}, + {122,201,101}, + {201,204,101}, + {180,196,197}, + {170,192,171}, + {200,190,189}, + {194,193,195}, + {183,181,180}, + {183,180,182}, + {155,154,168}, + {149,156,151}, + {149,151,148}, + {155,156,120}, + {145,142,143}, + {145,143,146}, + {136,137,140}, + {133,132,130}, + {128,129,116}, + {100,120,121}, + {110,112,113}, + {110,113,114}, + { 66, 65, 63}, + { 66, 63, 99}, + { 66, 99, 98}, + { 96, 46, 61}, + { 89, 88, 90}, + { 86, 87, 57}, + { 80, 78, 81}, + { 72, 69, 49}, + { 67, 48, 47}, + { 67, 47, 68}, + { 56, 55, 53}, + { 50, 49, 36}, + { 50, 36, 35}, + { 40, 39, 41}, + {242,243,229}, + {242,229,227}, + { 6, 37, 39}, + { 42, 47, 48}, + { 42, 48, 43}, + { 61, 46, 44}, + { 45, 70, 69}, + { 69, 70, 71}, + { 69, 71, 49}, + { 74, 78, 77}, + { 83, 84, 85}, + { 73, 74, 77}, + { 93, 96, 92}, + { 68, 46, 93}, + { 95, 99, 63}, + { 95, 63, 59}, + {115,108,110}, + {115,110,114}, + {125,126,127}, + {129,130,132}, + {137,133,138}, + {137,138,139}, + {148,146,143}, + {148,143,147}, + {119,118,154}, + {161,147,143}, + {165,164,151}, + {158,157,171}, + {158,171,172}, + {159,158,187}, + {159,187,186}, + {194,192,191}, + {194,191,193}, + {189,202,201}, + {182,197,184}, + {205, 8, 7}, + { 48,109,107}, + {218,219, 57}, + {218, 57, 56}, + {207,231,211}, + {232,230,231}, + {232,231,233}, + { 53, 52, 31}, + {388,411,386}, + {409,430,250}, + {262,429,254}, + {262,254,256}, + {442,444,428}, + {273,264,383}, + {273,383,384}, + {429,271,251}, + {429,251,254}, + {413,365,362}, + { 67,413,360}, + {282,283,295}, + {285,301,299}, + {202,281,280}, + {284,283,291}, + {284,291,289}, + {320,189,160}, + {308,306,307}, + {307,309,308}, + {319,317,330}, + {319,330,328}, + {353,352,324}, + {332,331,333}, + {340,341,338}, + {354,341,344}, + {349,358,357}, + {349,357,347}, + {364,355,356}, + {364,356,363}, + {364,365,366}, + {364,366,369}, + {374,376,402}, + {375, 92,373}, + { 77,389,390}, + {382,380,381}, + {389, 77,386}, + {393,394,412}, + {393,412,392}, + {401,394,416}, + {415,400,403}, + {411,410,427}, + {411,427,426}, + {422,420,424}, + {247,248,263}, + {247,263,261}, + {445,443, 14}, + {445, 14, 11}, + {449,450, 4}, + {449, 4, 5}, + {443,441, 17}, + {443, 17, 14}, + {436, 23, 17}, + {436, 17,441}, + {424,448,422}, + {448,423,422}, + {414,419,418}, + {414,418,413}, + {406,404,405}, + {399,397,395}, + {399,395,396}, + {420,416,392}, + {388,410,411}, + {386,384,383}, + {390, 88, 77}, + {375, 94, 92}, + {415,414, 68}, + {415, 68, 94}, + {370,374,402}, + {370,402,398}, + {361,357,358}, + {361,358,359}, + {125,348,126}, + {346,344,343}, + {340,338,339}, + {337,335,334}, + {337,334,336}, + {325,353,324}, + {324,331,332}, + {324,332,329}, + {323,322,309}, + {323,309,310}, + {294,295,297}, + {294,297,296}, + {289,286,285}, + {202,280,203}, + {288,307,303}, + {282,295,321}, + { 67,360,111}, + {418,423,367}, + {418,367,366}, + {272,252,251}, + {272,251,271}, + {272,271,270}, + {255,253,274}, + {265,266,380}, + {265,380,382}, + {442,428,261}, + {440,263,258}, + {440,258,260}, + {409,250,410}, + {255,226,245}, + {255,245,246}, + { 31,240,243}, + {236,234,235}, + {236,235,237}, + {233,225,245}, + {233,245,244}, + {220,221, 85}, + {220, 85, 86}, + { 81,213,226}, + { 81,226, 80}, + { 7,206,205}, + {186,184,198}, + {186,198,199}, + {204,203,205}, + {204,205,206}, + {195,193,196}, + {171,174,172}, + {173,174,175}, + {173,172,174}, + {155,167,166}, + {160,161,143}, + {160,143,144}, + {119,154,155}, + {148,151,150}, + {148,150,146}, + {140,137,139}, + {140,139,141}, + {127,126,130}, + {114,124,128}, + {114,128,115}, + {117,105,106}, + {117,106,116}, + {104,105,100}, + {104,100,103}, + { 59, 60, 91}, + { 97, 96, 61}, + { 97, 61, 64}, + { 91, 72, 89}, + { 87, 84, 79}, + { 87, 79, 76}, + { 78, 80, 77}, + { 49, 50, 74}, + { 60, 44, 45}, + { 61, 44, 58}, + { 51, 50, 35}, + { 51, 35, 34}, + { 39, 37, 41}, + { 33, 34, 9}, + { 33, 9, 12}, + { 0, 36, 37}, + { 0, 37, 6}, + { 40, 46, 47}, + { 40, 47, 42}, + { 53, 54, 56}, + { 65, 62, 63}, + { 72, 49, 73}, + { 79, 78, 75}, + { 79, 75, 76}, + { 52, 53, 76}, + { 92, 89, 90}, + { 96, 93, 46}, + {102,103,100}, + {102,100,101}, + {116,106,108}, + {116,108,115}, + {123,125,124}, + {116,115,128}, + {118,131,135}, + {140,135,136}, + {148,147,149}, + {120,119,155}, + {164,162,152}, + {164,152,150}, + {157,147,161}, + {157,161,170}, + {186,187,185}, + {186,185,184}, + {193,197,196}, + {202,203,204}, + {194,195,178}, + {198,184,197}, + { 67,111,109}, + { 38, 43,103}, + { 38,103,102}, + {214,223,222}, + {214,222,221}, + {214,221,220}, + {214,220,219}, + {214,219,218}, + {213,237,235}, + {221,222, 83}, + {221, 83, 85}, + { 15,229, 33}, + {227, 18,230}, + {227,230,232}, + { 52, 51,240}, + { 75, 78, 50}, + {408,430,409}, + {260,258,257}, + {260,257,259}, + {224,207,259}, + {268,269,405}, + {268,405,404}, + {413,362,360}, + {447, 8,205}, + {299,297,285}, + {189,281,202}, + {290,288,289}, + {290,289,291}, + {322,321,295}, + {322,295,294}, + {333,323,311}, + {333,311,320}, + {317,316,329}, + {320,160,144}, + {353,325,326}, + {329,332,334}, + {329,334,330}, + {339,338,141}, + {339,141,139}, + {348,345,126}, + {347,356,346}, + {123,349,125}, + {364,353,354}, + {364,354,355}, + {365,364,363}, + {376,391,394}, + {376,394,401}, + { 92,376,374}, + { 92,374,373}, + {377, 90, 88}, + {380,379,378}, + {380,378,381}, + {388,387,409}, + {388,409,410}, + {416,393,392}, + {399,398,402}, + {399,402,403}, + {250,428,427}, + {421,417,416}, + {421,416,420}, + {426,427,446}, + {426,446,451}, + {444,442,441}, + {452,451,450}, + {452,450,449} +}; + + +//***************************THE END OF FAMOUS BUNNY TRIMESH********************************************// + + +#endif //BUNNY_MESH_H_ diff --git a/Demos/GimpactTestDemo/CMakeLists.txt b/Demos/GimpactTestDemo/CMakeLists.txt new file mode 100644 index 0000000..31ed8fd --- /dev/null +++ b/Demos/GimpactTestDemo/CMakeLists.txt @@ -0,0 +1,58 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + +IF (USE_GLUT) + INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL + ) + + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath GIMPACTUtils ConvexDecomposition ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + ADD_EXECUTABLE(AppGimpactTestDemo + GimpactTestDemo.cpp + GimpactTestDemo.h + main.cpp + ) + IF (WIN32) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppGimpactTestDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppGimpactTestDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF(WIN32) +ELSE(USE_GLUT) + + INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL + ) + + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath GIMPACTUtils ConvexDecomposition ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + ADD_EXECUTABLE(AppGimpactTestDemo + WIN32 + GimpactTestDemo.cpp + GimpactTestDemo.h + ../OpenGL/Win32AppMain.cpp + Win32GimpactDemo.cpp + ) +ENDIF(USE_GLUT) diff --git a/Demos/GimpactTestDemo/GimpactTestDemo.cpp b/Demos/GimpactTestDemo/GimpactTestDemo.cpp new file mode 100644 index 0000000..9e54273 --- /dev/null +++ b/Demos/GimpactTestDemo/GimpactTestDemo.cpp @@ -0,0 +1,688 @@ +/* +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 "GimpactTestDemo.h" + +#define SHOW_NUM_DEEP_PENETRATIONS + +#include "LinearMath/btDefaultMotionState.h" +#include "LinearMath/btIDebugDraw.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btDefaultMotionState.h" +#include "GLDebugFont.h" +/// Including GIMPACT here + + + +#include "GLDebugDrawer.h" + +#include "GL_ShapeDrawer.h" +#include "GlutStuff.h" + +/// Include Torus Mesh here +#include "TorusMesh.h" +#include "BunnyMesh.h" + +#ifdef SHOW_NUM_DEEP_PENETRATIONS +extern int gNumDeepPenetrationChecks; +extern int gNumSplitImpulseRecoveries; +extern int gNumGjkChecks; +#endif // + + + +//Real dts = 0.000001f; +Real dts = 1.0 / 60.0; + + +///************************************************************************************** +/// GIMPACT Test Demo made by DevO +/// +///************************************************************************************** + + + +GimpactConcaveDemo::~GimpactConcaveDemo() +{ + + int 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 m_dynamicsWorld; + + delete m_indexVertexArrays; + delete m_trimeshShape; + + delete m_indexVertexArrays2; + delete m_trimeshShape2; + + for (i=0;igetBroadphase()->getBroadphaseAabb(worldBoundsMin,worldBoundsMax); + + + int numObjects = m_dynamicsWorld->getNumCollisionObjects(); + btVector3 wireColor(1,0,0); + for (int i=0;igetCollisionObjectArray()[i]; + btRigidBody* body = btRigidBody::upcast(colObj); + + if (body && body->getMotionState()) + { + btDefaultMotionState* myMotionState = (btDefaultMotionState*)body->getMotionState(); + myMotionState->m_graphicsWorldTrans.getOpenGLMatrix(m); + } else + { + colObj->getWorldTransform().getOpenGLMatrix(m); + } + + btVector3 wireColor(1.f,1.0f,0.5f); //wants deactivation + if (i & 1) + { + wireColor = btVector3(0.f,0.0f,1.f); + } + ///color differently for active, sleeping, wantsdeactivation states + if (colObj->getActivationState() == 1) //active + { + if (i & 1) + { + wireColor += btVector3 (0.8f,0.1f,0.1f); + } else + { + wireColor += btVector3 (0.5f,0.f,0.f); + } + } + if (colObj->getActivationState() == 2) //ISLAND_SLEEPING + { + if (i & 1) + { + wireColor += btVector3 (0.5f,0.8f, 0.5f); + } else + { + wireColor += btVector3 (0.f,0.5f,0.f); + } + } + + m_shapeDrawer->drawOpenGL(m,colObj->getCollisionShape(),wireColor,getDebugMode(),worldBoundsMin,worldBoundsMax); + } + + + float xOffset = 10.f; + float yStart = 20.f; + float yIncr = 20.f; + char buf[124]; + + glColor3f(0, 0, 0); + + setOrthographicProjection(); + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"mouse to interact"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + /* glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"space to reset"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + */ + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"cursor keys and z,x to navigate"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"i to toggle simulation, s single step"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"q to quit"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,". to shoot TRIMESH (dot)"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + // not yet hooked up again after refactoring... + +/* glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"d to toggle deactivation"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; +*/ + + /* + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"a to draw temporal AABBs"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + */ + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"h to toggle help text"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + //bool useBulletLCP = !(getDebugMode() & btIDebugDraw::DBG_DisableBulletLCP); + + bool useCCD = ((getDebugMode() & btIDebugDraw::DBG_EnableCCD) != 0); + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"1 CCD mode (adhoc) = %i",useCCD); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"+- shooting speed = %10.2f",m_ShootBoxInitialSpeed); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + #ifdef SHOW_NUM_DEEP_PENETRATIONS + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"gNumDeepPenetrationChecks = %d",gNumDeepPenetrationChecks); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"gNumSplitImpulseRecoveries= %d",gNumSplitImpulseRecoveries); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"gNumGjkChecks= %d",gNumGjkChecks); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + #endif //SHOW_NUM_DEEP_PENETRATIONS + + + resetPerspectiveProjection(); + + + } + +} + +//------------------------------------------------------------------------------ +void GimpactConcaveDemo::initGImpactCollision() +{ + /// Create Torus Shape + { + m_indexVertexArrays = new btTriangleIndexVertexArray + (NUM_TRIANGLES, + &gIndices[0][0], + 3*sizeof(int), + NUM_VERTICES, + (Real*) &gVertices[0],sizeof(Real)*3); + + +#ifdef BULLET_GIMPACT + #ifdef BULLET_GIMPACT_CONVEX_DECOMPOSITION + btGImpactConvexDecompositionShape * trimesh = new + btGImpactConvexDecompositionShape( + m_indexVertexArrays, btVector3(1.f,1.f,1.f),btScalar(0.01)); + trimesh->setMargin(0.07); + trimesh->updateBound(); + + + #else + btGImpactMeshShape * trimesh = new btGImpactMeshShape(m_indexVertexArrays); + trimesh->setLocalScaling(btVector3(1.f,1.f,1.f)); + #ifdef BULLET_TRIANGLE_COLLISION + trimesh->setMargin(0.07f); ///????? + #else + trimesh->setMargin(0.0f); + #endif + trimesh->updateBound(); + #endif + + m_trimeshShape = trimesh; + +#else + m_trimeshShape = new btGIMPACTMeshData(m_indexVertexArrays); +#endif + + } + + /// Create Bunny Shape + { + m_indexVertexArrays2 = new btTriangleIndexVertexArray + (BUNNY_NUM_TRIANGLES, + &gIndicesBunny[0][0], + 3*sizeof(int), + BUNNY_NUM_VERTICES, + (Real*) &gVerticesBunny[0],sizeof(Real)*3); +#ifdef BULLET_GIMPACT + + #ifdef BULLET_GIMPACT_CONVEX_DECOMPOSITION + btGImpactConvexDecompositionShape * trimesh2 = new + btGImpactConvexDecompositionShape( + m_indexVertexArrays2, btVector3(4.f,4.f,4.f),btScalar(0.01)); + trimesh2->setMargin(0.07); + trimesh2->updateBound(); + #else + btGImpactMeshShape * trimesh2 = new btGImpactMeshShape(m_indexVertexArrays2); + trimesh2->setLocalScaling(btVector3(4.f,4.f,4.f)); + #ifdef BULLET_TRIANGLE_COLLISION + trimesh2->setMargin(0.07f); ///????? + #else + trimesh2->setMargin(0.0f); + #endif + trimesh2->updateBound(); + #endif + + + + m_trimeshShape2 = trimesh2; +#else + m_trimeshShape2 = new btGIMPACTMeshData(m_indexVertexArrays2); + +#endif + + } + + + ///register GIMPACT algorithm + btCollisionDispatcher * dispatcher = static_cast(m_dynamicsWorld ->getDispatcher()); + +#ifdef BULLET_GIMPACT + btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher); +#else + btConcaveConcaveCollisionAlgorithm::registerAlgorithm(dispatcher); +#endif + + +} + +#ifndef BULLET_GIMPACT +btCollisionShape * GimpactConcaveDemo::createTorusShape() +{ + btGIMPACTMeshShape * newtrimeshShape = new btGIMPACTMeshShape(m_trimeshShape); + newtrimeshShape->setLocalScaling(btVector3(1.f,1.f,1.f)); + return newtrimeshShape; +} +btCollisionShape * GimpactConcaveDemo::createBunnyShape() +{ + btGIMPACTMeshShape * newtrimeshShape = new btGIMPACTMeshShape(m_trimeshShape2); + newtrimeshShape->setLocalScaling(btVector3(4.f,4.f,4.f)); + return newtrimeshShape; +} +#endif +//------------------------------------------------------------------------------ +void GimpactConcaveDemo::initPhysics() +{ + setTexturing(true); + setShadows(false); + + setCameraDistance(45.f); + + + /// Init Bullet + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + //btOverlappingPairCache* broadphase = new btSimpleBroadphase(); + //m_broadphase = new btSimpleBroadphase(); + + int maxProxies = 1024; + btVector3 worldAabbMin(-10000,-10000,-10000); + btVector3 worldAabbMax( 10000, 10000, 10000); + m_broadphase = new bt32BitAxisSweep3(worldAabbMin,worldAabbMax,maxProxies); + + m_constraintSolver = new btSequentialImpulseConstraintSolver(); + + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_constraintSolver,m_collisionConfiguration); + + //create trimesh model and shape + initGImpactCollision(); + + + + /// Create Scene + float mass = 0.f; + btTransform startTransform; + startTransform.setIdentity(); + + + btCollisionShape* staticboxShape1 = new btBoxShape(btVector3(200,1,200));//floor + m_collisionShapes.push_back(staticboxShape1); + startTransform.setOrigin(btVector3(0,-10,0)); + localCreateRigidBody(mass, startTransform,staticboxShape1); + + btCollisionShape* staticboxShape2 = new btBoxShape(btVector3(1,50,200));//left wall + m_collisionShapes.push_back(staticboxShape2); + startTransform.setOrigin(btVector3(-200,15,0)); + localCreateRigidBody(mass, startTransform,staticboxShape2); + + btCollisionShape* staticboxShape3 = new btBoxShape(btVector3(1,50,200));//right wall + m_collisionShapes.push_back(staticboxShape3); + startTransform.setOrigin(btVector3(200,15,0)); + localCreateRigidBody(mass, startTransform,staticboxShape3); + + btCollisionShape* staticboxShape4 = new btBoxShape(btVector3(200,50,1));//front wall + m_collisionShapes.push_back(staticboxShape4); + startTransform.setOrigin(btVector3(0,15,200)); + localCreateRigidBody(mass, startTransform,staticboxShape4); + + btCollisionShape* staticboxShape5 = new btBoxShape(btVector3(200,50,1));//back wall + m_collisionShapes.push_back(staticboxShape5); + startTransform.setOrigin(btVector3(0,15,-200)); + localCreateRigidBody(mass, startTransform,staticboxShape5); + + + //static plane + + btVector3 normal(-0.5,0.5,0.0); + normal.normalize(); + btCollisionShape* staticplaneShape6 = new btStaticPlaneShape(normal,0.0);// A plane + m_collisionShapes.push_back(staticplaneShape6); + startTransform.setOrigin(btVector3(0,-9,0)); + + btRigidBody* staticBody2 = localCreateRigidBody(mass, startTransform,staticplaneShape6 ); + + //another static plane + + normal.setValue(0.5,0.7,0.0); + //normal.normalize(); + btCollisionShape* staticplaneShape7 = new btStaticPlaneShape(normal,0.0);// A plane + m_collisionShapes.push_back(staticplaneShape7); + startTransform.setOrigin(btVector3(0,-10,0)); + + staticBody2 = localCreateRigidBody(mass, startTransform,staticplaneShape7 ); + + /// Create Static Torus + float height = 28; + float step = 2.5; + float massT = 1.0; + + startTransform.setOrigin(btVector3(0,height,-5)); + startTransform.setRotation(btQuaternion(3.14159265*0.5,0,3.14159265*0.5)); +#ifdef BULLET_GIMPACT + kinematicTorus = localCreateRigidBody(0.0, startTransform,m_trimeshShape); + +#else + kinematicTorus = localCreateRigidBody(0.0, startTransform,createTorusShape()); + +#endif //kinematicTorus->setCollisionFlags(kinematicTorus->getCollisionFlags()|btCollisionObject::CF_STATIC_OBJECT); + //kinematicTorus->setActivationState(ISLAND_SLEEPING); + + kinematicTorus->setCollisionFlags( kinematicTorus->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + kinematicTorus->setActivationState(DISABLE_DEACTIVATION); + + /// Kinematic + kinTorusTran = btVector3(-0.1,0,0); + kinTorusRot = btQuaternion(0,3.14159265*0.01,0); + +#ifdef TEST_GIMPACT_TORUS + +#ifdef BULLET_GIMPACT + /// Create dynamic Torus + for (int i=0;i<6;i++) + { + height -= step; + startTransform.setOrigin(btVector3(0,height,-5)); + startTransform.setRotation(btQuaternion(0,0,3.14159265*0.5)); + + btRigidBody* bodyA; + bodyA= localCreateRigidBody(massT, startTransform,m_trimeshShape); + + height -= step; + startTransform.setOrigin(btVector3(0,height,-5)); + startTransform.setRotation(btQuaternion(3.14159265*0.5,0,3.14159265*0.5)); + btRigidBody* bodyB; + bodyB= localCreateRigidBody(massT, startTransform,m_trimeshShape); + + } +#else + +/// Create dynamic Torus + for (int i=0;i<6;i++) + { + height -= step; + startTransform.setOrigin(btVector3(0,height,-5)); + startTransform.setRotation(btQuaternion(0,0,3.14159265*0.5)); + + btRigidBody* bodyA = localCreateRigidBody(massT, startTransform,createTorusShape()); + + height -= step; + startTransform.setOrigin(btVector3(0,height,-5)); + startTransform.setRotation(btQuaternion(3.14159265*0.5,0,3.14159265*0.5)); + btRigidBody* bodyB = localCreateRigidBody(massT, startTransform,createTorusShape()); + + } +#endif //no BULLET_GIMPACT +#endif + + startTransform.setIdentity(); + + + /// Create Dynamic Boxes + { + for (int i=0;i<8;i++) + { + btCollisionShape* boxShape = new btBoxShape(btVector3(1,1,1)); + m_collisionShapes.push_back(boxShape); + + startTransform.setOrigin(btVector3(2*i-5,2,-3)); + localCreateRigidBody(1, startTransform,boxShape); + } + } + + + //m_debugMode |= btIDebugDraw::DBG_DrawWireframe; + +} + +//------------------------------------------------------------------------------ +void GimpactConcaveDemo::shootTrimesh(const btVector3& destination) +{ + + if (m_dynamicsWorld) + { + float mass = 4.f; + btTransform startTransform; + startTransform.setIdentity(); + btVector3 camPos = getCameraPosition(); + startTransform.setOrigin(camPos); +#ifdef BULLET_GIMPACT + btRigidBody* body = this->localCreateRigidBody(mass, startTransform,m_trimeshShape2); +#else + btRigidBody* body = this->localCreateRigidBody(mass, startTransform,createBunnyShape()); +#endif + btVector3 linVel(destination[0]-camPos[0],destination[1]-camPos[1],destination[2]-camPos[2]); + linVel.normalize(); + linVel*=m_ShootBoxInitialSpeed*0.25; + + body->getWorldTransform().setOrigin(camPos); + body->getWorldTransform().setRotation(btQuaternion(0,0,0,1)); + body->setLinearVelocity(linVel); + body->setAngularVelocity(btVector3(0,0,0)); + } +} + +//------------------------------------------------------------------------------ +void GimpactConcaveDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + +#define USE_KINEMATIC_GROUND +#ifdef USE_KINEMATIC_GROUND + //kinTorusTran = btVector3(-0.05,0,0); + //kinTorusRot = btQuaternion(0,3.14159265*0.1,0); + + //kinematic object + btCollisionObject* colObj = kinematicTorus; + //is this a rigidbody with a motionstate? then use the motionstate to update positions! + if (colObj && btRigidBody::upcast(colObj) && btRigidBody::upcast(colObj)->getMotionState()) + { + btTransform newTrans; + btRigidBody::upcast(colObj)->getMotionState()->getWorldTransform(newTrans); + + newTrans.getOrigin() += kinTorusTran; + newTrans.getBasis() = newTrans.getBasis() * btMatrix3x3(kinTorusRot); + if(newTrans.getOrigin().getX() > 6.0){ + newTrans.getOrigin().setX(6.0); + kinTorusTran = -kinTorusTran; + } + if(newTrans.getOrigin().getX() < -6.0){ + newTrans.getOrigin().setX(-6.0); + kinTorusTran = -kinTorusTran; + } + + btRigidBody::upcast(colObj)->getMotionState()->setWorldTransform(newTrans); + } else + { + /* + btTransform &newTrans = m_dynamicsWorld->getCollisionObjectArray()[0]->getWorldTransform(); + newTrans.getOrigin() += kinTorusTran; + if(newTrans.getOrigin().getX() > 0.1) kinTorusTran = -kinTorusTran; + if(newTrans.getOrigin().getX() < 0.1) kinTorusTran = -kinTorusTran; + */ + } + +#endif //USE_KINEMATIC_GROUND + + + unsigned long int time = getDeltaTimeMicroseconds()/btScalar(1000); + printf("%i time %i ms \n",m_steps_done,int(time)); + +//#ifdef BULLET_GIMPACT +// printf("%i time %.1f ms \n",m_steps_done,btGImpactCollisionAlgorithm::getAverageTreeCollisionTime()); +//#else +// printf("%i time %.1f ms \n",m_steps_done,btConcaveConcaveCollisionAlgorithm::getAverageTreeCollisionTime()); +//#endif + + //float dt = float(m_clock.getTimeMicroseconds()) * dts; //0.000001f; + float dt = btScalar(1./60.); + + + + m_dynamicsWorld->stepSimulation(dt); + + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + + m_steps_done++; + + //m_dynamicsWorld->stepSimulation(dts); + + renderme(); + + glFlush(); + swapBuffers(); + +} + +//------------------------------------------------------------------------------ +void GimpactConcaveDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + //optional but useful: debug drawing + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + glFlush(); + swapBuffers(); +} + +//------------------------------------------------------------------------------ +void GimpactConcaveDemo::clientResetScene() +{ + m_steps_done = 0; + DemoApplication::clientResetScene(); +} + +#define KEY_ESCAPE 0x1B + + +//------------------------------------------------------------------------------ +void GimpactConcaveDemo::keyboardCallback(unsigned char key, int x, int y) +{ + switch (key) + { + case '.': + { + shootTrimesh(getCameraTargetPosition()); + break; + } + + case '2': + { + dts += 0.000001f; + break; + } + case '3': + { + dts -= 0.000001f; if(dts<0.000001f) dts = 0.000001f; + break; + } + + default: + DemoApplication::keyboardCallback(key, x, y); + } +} + + + diff --git a/Demos/GimpactTestDemo/GimpactTestDemo.h b/Demos/GimpactTestDemo/GimpactTestDemo.h new file mode 100644 index 0000000..0b83e49 --- /dev/null +++ b/Demos/GimpactTestDemo/GimpactTestDemo.h @@ -0,0 +1,145 @@ +/* +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 TEST_CONCAVE_DEMO_H +#define TEST_CONCAVE_DEMO_H + + +#ifdef _WINDOWS +#include "Win32DemoApplication.h" +#define PlatformDemoApplication Win32DemoApplication +#else +#include "GlutDemoApplication.h" +#define PlatformDemoApplication GlutDemoApplication +#endif + +class btTriangleIndexVertexArray; +class btDefaultCollisionConfiguration; + +//#define BULLET_TRIANGLE_COLLISION 1 +#define BULLET_GIMPACT 1 +//#define BULLET_GIMPACT_CONVEX_DECOMPOSITION 1 + +#define TEST_GIMPACT_TORUS + +#ifdef BULLET_GIMPACT + +#include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h" + #ifdef BULLET_GIMPACT_CONVEX_DECOMPOSITION + #include "../Extras/GIMPACTUtils/btGImpactConvexDecompositionShape.h" + #endif + + +#else + +#include "BulletCollision/Gimpact/btConcaveConcaveCollisionAlgorithm.h" +#include "BulletCollision/Gimpact/btGIMPACTMeshShape.h" + +#endif + + + +class btConstraintSolver; +struct btCollisionAlgorithmCreateFunc; + +///GimpactConcaveDemo shows usage of static concave triangle meshes +///It also shows per-triangle material (friction/restitution) through CustomMaterialCombinerCallback +class GimpactConcaveDemo : public PlatformDemoApplication +{ + +public: + GimpactConcaveDemo() + : m_steps_done(0), + m_trimeshShape(NULL), + m_trimeshShape2(NULL), + m_indexVertexArrays(NULL), + m_indexVertexArrays2(NULL), + + + kinematicTorus(NULL), + + + m_gimpactCollisionCreateFunc(NULL), + m_collisionConfiguration(NULL), + + m_dispatcher(NULL), + + m_broadphase(NULL), + m_constraintSolver(NULL) + { + } + + virtual ~GimpactConcaveDemo(); + + + void initGImpactCollision(); + void initPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + virtual void clientResetScene(); + + virtual void renderme(); + virtual void keyboardCallback(unsigned char key, int x, int y); + + ///Demo functions + void shootTrimesh(const btVector3& destination); + +public: ///data + unsigned int m_steps_done; + +#ifdef BULLET_GIMPACT + btCollisionShape *m_trimeshShape; + btCollisionShape *m_trimeshShape2; +#else + + btGIMPACTMeshData * m_trimeshShape; + btGIMPACTMeshData * m_trimeshShape2; + + btCollisionShape * createTorusShape(); + btCollisionShape * createBunnyShape(); + +#endif + + //keep the collision shapes, for deletion/cleanup + btAlignedObjectArray m_collisionShapes; + + btTriangleIndexVertexArray *m_indexVertexArrays; + btTriangleIndexVertexArray *m_indexVertexArrays2; + + btVector3 kinTorusTran; + btQuaternion kinTorusRot; + btRigidBody *kinematicTorus; + + + btCollisionAlgorithmCreateFunc* m_gimpactCollisionCreateFunc; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + btCollisionDispatcher* m_dispatcher; + btBroadphaseInterface* m_broadphase; + btConstraintSolver* m_constraintSolver; + + static DemoApplication* Create() + { + GimpactConcaveDemo* demo = new GimpactConcaveDemo(); + demo->myinit(); + demo->initPhysics(); + return demo; + } +}; + +#endif //CONCAVE_DEMO_H + diff --git a/Demos/GimpactTestDemo/TorusMesh.h b/Demos/GimpactTestDemo/TorusMesh.h new file mode 100644 index 0000000..6919041 --- /dev/null +++ b/Demos/GimpactTestDemo/TorusMesh.h @@ -0,0 +1,921 @@ +#ifndef TORUS_MESH_H_ +#define TORUS_MESH_H_ + + +//*************************** NOT REALLY FAMOUS TORUS ********************************************// + +#define Real btScalar +const int NUM_TRIANGLES =600; +const int NUM_VERTICES = 300; +const int NUM_INDICES = NUM_TRIANGLES * 3; + + +static Real gVertices[NUM_VERTICES * 3] = { + Real(2.5), Real(0), Real(0), + Real(2.405), Real(0.294), Real(0), + Real(2.155), Real(0.476), Real(0), + Real(1.845), Real(0.476), Real(0), + Real(1.595), Real(0.294), Real(0), + Real(1.5), Real(0 ), Real(0), + Real(1.595), Real(-0.294), Real(0), + Real(1.845), Real(-0.476), Real(0), + Real(2.155), Real(-0.476), Real(0), + Real(2.405), Real(-0.294), Real(0), + Real(2.445), Real(0 ), Real(0.52 ), + Real(2.352), Real(0.294), Real(0.5 ), + Real(2.107), Real(0.476), Real(0.448), + Real(1.805), Real(0.476), Real(0.384), + Real(1.561), Real(0.294), Real(0.332), + Real(1.467), Real(0 ), Real(0.312), + Real(1.561), Real(-0.294), Real(0.332), + Real(1.805), Real(-0.476), Real(0.384), + Real(2.107), Real(-0.476), Real(0.448), + Real(2.352), Real(-0.294), Real(0.5 ), + Real(2.284), Real(0), Real(1.017), + Real(2.197), Real(0.294), Real(0.978), + Real(1.968), Real(0.476), Real(0.876), + Real(1.686), Real(0.476), Real(0.751), + Real(1.458), Real(0.294), Real(0.649), + Real(1.37), Real(0), Real(0.61 ), + Real(1.458), Real(-0.294), Real(0.649), + Real(1.686), Real(-0.476), Real(0.751), + Real(1.968), Real(-0.476), Real(0.876), + Real(2.197), Real(-0.294), Real(0.978), + Real(2.023), Real(0), Real(1.469), + Real(1.945), Real(0.294), Real(1.413), + Real(1.743), Real(0.476), Real(1.266), + Real(1.493), Real(0.476), Real(1.085), + Real(1.291), Real(0.294), Real(0.938), + Real(1.214), Real(0), Real(0.882), + Real(1.291), Real(-0.294), Real(0.938), + Real(1.493), Real(-0.476), Real(1.085), + Real(1.743), Real(-0.476), Real(1.266), + Real(1.945), Real(-0.294), Real(1.413), + Real(1.673), Real(0), Real(1.858), + Real(1.609), Real(0.294), Real(1.787), + Real(1.442), Real(0.476), Real(1.601), + Real(1.235), Real(0.476), Real(1.371), + Real(1.068), Real(0.294), Real(1.186), + Real(1.004), Real(0), Real(1.115), + Real(1.068), Real(-0.294), Real(1.186), + Real(1.235), Real(-0.476), Real(1.371), + Real(1.442), Real(-0.476), Real(1.601), + Real(1.609), Real(-0.294), Real(1.787), + Real(1.25), Real(0), Real(2.165), + Real(1.202), Real(0.294), Real(2.082), + Real(1.077), Real(0.476), Real(1.866), + Real(0.923), Real(0.476), Real(1.598), + Real(0.798), Real(0.294), Real(1.382), + Real(0.75), Real(0), Real(1.299), + Real(0.798), Real(-0.294), Real(1.382), + Real(0.923), Real(-0.476), Real(1.598), + Real(1.077), Real(-0.476), Real(1.866), + Real(1.202), Real(-0.294), Real(2.082), + Real(0.773), Real(0), Real(2.378), + Real(0.743), Real(0.294), Real(2.287), + Real(0.666), Real(0.476), Real(2.049), + Real(0.57), Real(0.476), Real(1.755), + Real(0.493), Real(0.294), Real(1.517), + Real(0.464), Real(0), Real(1.427), + Real(0.493), Real(-0.294), Real(1.517), + Real(0.57), Real(-0.476), Real(1.755), + Real(0.666), Real(-0.476), Real(2.049), + Real(0.743), Real(-0.294), Real(2.287), + Real(0.261), Real(0), Real(2.486), + Real(0.251), Real(0.294), Real(2.391), + Real(0.225), Real(0.476), Real(2.143), + Real(0.193), Real(0.476), Real(1.835), + Real(0.167), Real(0.294), Real(1.587), + Real(0.157), Real(0), Real(1.492), + Real(0.167), Real(-0.294), Real(1.587), + Real(0.193), Real(-0.476), Real(1.835), + Real(0.225), Real(-0.476), Real(2.143), + Real(0.251), Real(-0.294), Real(2.391), + Real(-0.261), Real(0), Real(2.486), + Real(-0.251), Real(0.294), Real(2.391), + Real(-0.225), Real(0.476), Real(2.143), + Real(-0.193), Real(0.476), Real(1.835), + Real(-0.167), Real(0.294), Real(1.587), + Real(-0.157), Real(0), Real(1.492), + Real(-0.167), Real(-0.294), Real(1.587), + Real(-0.193), Real(-0.476), Real(1.835), + Real(-0.225), Real(-0.476), Real(2.143), + Real(-0.251), Real(-0.294), Real(2.391), + Real(-0.773), Real(0), Real(2.378), + Real(-0.743), Real(0.294), Real(2.287), + Real(-0.666), Real(0.476), Real(2.049), + Real(-0.57), Real(0.476), Real(1.755), + Real(-0.493), Real(0.294), Real(1.517), + Real(-0.464), Real(0), Real(1.427), + Real(-0.493), Real(-0.294), Real(1.517), + Real(-0.57), Real(-0.476), Real(1.755), + Real(-0.666), Real(-0.476), Real(2.049), + Real(-0.743), Real(-0.294), Real(2.287), + Real(-1.25 ), Real(0), Real(2.165), + Real(-1.202), Real(0.294), Real(2.082), + Real(-1.077), Real(0.476), Real(1.866), + Real(-0.923), Real(0.476), Real(1.598), + Real(-0.798), Real(0.294), Real(1.382), + Real(-0.75), Real(0), Real(1.299), + Real(-0.798), Real(-0.294), Real(1.382), + Real(-0.923), Real(-0.476), Real(1.598), + Real(-1.077), Real(-0.476), Real(1.866), + Real(-1.202), Real(-0.294), Real(2.082), + Real(-1.673), Real(0), Real(1.858), + Real(-1.609), Real(0.294), Real(1.787), + Real(-1.442), Real(0.476), Real(1.601), + Real(-1.235), Real(0.476), Real(1.371), + Real(-1.068), Real(0.294), Real(1.186), + Real(-1.004), Real(0), Real(1.115), + Real(-1.068), Real(-0.294), Real(1.186), + Real(-1.235), Real(-0.476), Real(1.371), + Real(-1.442), Real(-0.476), Real(1.601), + Real(-1.609), Real(-0.294), Real(1.787), + Real(-2.023), Real(0), Real(1.469), + Real(-1.945), Real(0.294), Real(1.413), + Real(-1.743), Real(0.476), Real(1.266), + Real(-1.493), Real(0.476), Real(1.085), + Real(-1.291), Real(0.294), Real(0.938), + Real(-1.214), Real(0), Real(0.882), + Real(-1.291), Real(-0.294), Real(0.938), + Real(-1.493), Real(-0.476), Real(1.085), + Real(-1.743), Real(-0.476), Real(1.266), + Real(-1.945), Real(-0.294), Real(1.413), + Real(-2.284), Real(0), Real(1.017), + Real(-2.197), Real(0.294), Real(0.978), + Real(-1.968), Real(0.476), Real(0.876), + Real(-1.686), Real(0.476), Real(0.751), + Real(-1.458), Real(0.294), Real(0.649), + Real(-1.37), Real(0), Real(0.61 ), + Real(-1.458), Real(-0.294), Real(0.649), + Real(-1.686), Real(-0.476), Real(0.751), + Real(-1.968), Real(-0.476), Real(0.876), + Real(-2.197), Real(-0.294), Real(0.978), + Real(-2.445), Real(0), Real(0.52), + Real(-2.352), Real(0.294), Real(0.5), + Real(-2.107), Real(0.476), Real(0.448), + Real(-1.805), Real(0.476), Real(0.384), + Real(-1.561), Real(0.294), Real(0.332), + Real(-1.467), Real(0), Real(0.312), + Real(-1.561), Real(-0.294), Real(0.332), + Real(-1.805), Real(-0.476), Real(0.384), + Real(-2.107), Real(-0.476), Real(0.448), + Real(-2.352), Real(-0.294), Real(0.5), + Real(-2.5 ), Real(0), Real(0), + Real(-2.405), Real(0.294), Real(0), + Real(-2.155), Real(0.476), Real(0), + Real(-1.845), Real(0.476), Real(0), + Real(-1.595), Real(0.294), Real(0), + Real(-1.5), Real(0), Real(0), + Real(-1.595), Real(-0.294), Real(0), + Real(-1.845), Real(-0.476), Real(0), + Real(-2.155), Real(-0.476), Real(0), + Real(-2.405), Real(-0.294), Real(0), + Real(-2.445), Real(0), Real(-0.52), + Real(-2.352), Real(0.294), Real(-0.5), + Real(-2.107), Real(0.476), Real(-0.448), + Real(-1.805), Real(0.476), Real(-0.384), + Real(-1.561), Real(0.294), Real(-0.332), + Real(-1.467), Real(0), Real(-0.312), + Real(-1.561), Real(-0.294), Real(-0.332), + Real(-1.805), Real(-0.476), Real(-0.384), + Real(-2.107), Real(-0.476), Real(-0.448), + Real(-2.352), Real(-0.294), Real(-0.5), + Real(-2.284), Real(0), Real(-1.017), + Real(-2.197), Real(0.294), Real(-0.978), + Real(-1.968), Real(0.476), Real(-0.876), + Real(-1.686), Real(0.476), Real(-0.751), + Real(-1.458), Real(0.294), Real(-0.649), + Real(-1.37), Real(0), Real(-0.61), + Real(-1.458), Real(-0.294), Real(-0.649), + Real(-1.686), Real(-0.476), Real(-0.751), + Real(-1.968), Real(-0.476), Real(-0.876), + Real(-2.197), Real(-0.294), Real(-0.978), + Real(-2.023), Real(0), Real(-1.469), + Real(-1.945), Real(0.294), Real(-1.413), + Real(-1.743), Real(0.476), Real(-1.266), + Real(-1.493), Real(0.476), Real(-1.085), + Real(-1.291), Real(0.294), Real(-0.938), + Real(-1.214), Real(0), Real(-0.882), + Real(-1.291), Real(-0.294), Real(-0.938), + Real(-1.493), Real(-0.476), Real(-1.085), + Real(-1.743), Real(-0.476), Real(-1.266), + Real(-1.945), Real(-0.294), Real(-1.413), + Real(-1.673), Real(0), Real(-1.858), + Real(-1.609), Real(0.294), Real(-1.787), + Real(-1.442), Real(0.476), Real(-1.601), + Real(-1.235), Real(0.476), Real(-1.371), + Real(-1.068), Real(0.294), Real(-1.186), + Real(-1.004), Real(0), Real(-1.115), + Real(-1.068), Real(-0.294), Real(-1.186), + Real(-1.235), Real(-0.476), Real(-1.371), + Real(-1.442), Real(-0.476), Real(-1.601), + Real(-1.609), Real(-0.294), Real(-1.787), + Real(-1.25 ), Real(0), Real(-2.165), + Real(-1.202), Real(0.294), Real(-2.082), + Real(-1.077), Real(0.476), Real(-1.866), + Real(-0.923), Real(0.476), Real(-1.598), + Real(-0.798), Real(0.294), Real(-1.382), + Real(-0.75), Real(0), Real(-1.299), + Real(-0.798), Real(-0.294), Real(-1.382), + Real(-0.923), Real(-0.476), Real(-1.598), + Real(-1.077), Real(-0.476), Real(-1.866), + Real(-1.202), Real(-0.294), Real(-2.082), + Real(-0.773), Real(0), Real(-2.378), + Real(-0.743), Real(0.294), Real(-2.287), + Real(-0.666), Real(0.476), Real(-2.049), + Real(-0.57), Real(0.476), Real(-1.755), + Real(-0.493), Real(0.294), Real(-1.517), + Real(-0.464), Real(0), Real(-1.427), + Real(-0.493), Real(-0.294), Real(-1.517), + Real(-0.57), Real(-0.476), Real(-1.755), + Real(-0.666), Real(-0.476), Real(-2.049), + Real(-0.743), Real(-0.294), Real(-2.287), + Real(-0.261), Real(0), Real(-2.486), + Real(-0.251), Real(0.294), Real(-2.391), + Real(-0.225), Real(0.476), Real(-2.143), + Real(-0.193), Real(0.476), Real(-1.835), + Real(-0.167), Real(0.294), Real(-1.587), + Real(-0.157), Real(0), Real(-1.492), + Real(-0.167), Real(-0.294), Real(-1.587), + Real(-0.193), Real(-0.476), Real(-1.835), + Real(-0.225), Real(-0.476), Real(-2.143), + Real(-0.251), Real(-0.294), Real(-2.391), + Real(0.261), Real(0), Real(-2.486), + Real(0.251), Real(0.294), Real(-2.391), + Real(0.225), Real(0.476), Real(-2.143), + Real(0.193), Real(0.476), Real(-1.835), + Real(0.167), Real(0.294), Real(-1.587), + Real(0.157), Real(0), Real(-1.492), + Real(0.167), Real(-0.294), Real(-1.587), + Real(0.193), Real(-0.476), Real(-1.835), + Real(0.225), Real(-0.476), Real(-2.143), + Real(0.251), Real(-0.294), Real(-2.391), + Real(0.773), Real(0), Real(-2.378), + Real(0.743), Real(0.294), Real(-2.287), + Real(0.666), Real(0.476), Real(-2.049), + Real(0.57), Real(0.476), Real(-1.755), + Real(0.493), Real(0.294), Real(-1.517), + Real(0.464), Real(0), Real(-1.427), + Real(0.493), Real(-0.294), Real(-1.517), + Real(0.57), Real(-0.476), Real(-1.755), + Real(0.666), Real(-0.476), Real(-2.049), + Real(0.743), Real(-0.294), Real(-2.287), + Real(1.25), Real(0), Real(-2.165), + Real(1.202), Real(0.294), Real(-2.082), + Real(1.077), Real(0.476), Real(-1.866), + Real(0.923), Real(0.476), Real(-1.598), + Real(0.798), Real(0.294), Real(-1.382), + Real(0.75), Real(0), Real(-1.299), + Real(0.798), Real(-0.294), Real(-1.382), + Real(0.923), Real(-0.476), Real(-1.598), + Real(1.077), Real(-0.476), Real(-1.866), + Real(1.202), Real(-0.294), Real(-2.082), + Real(1.673), Real(0), Real(-1.858), + Real(1.609), Real(0.294), Real(-1.787), + Real(1.442), Real(0.476), Real(-1.601), + Real(1.235), Real(0.476), Real(-1.371), + Real(1.068), Real(0.294), Real(-1.186), + Real(1.004), Real(0), Real(-1.115), + Real(1.068), Real(-0.294), Real(-1.186), + Real(1.235), Real(-0.476), Real(-1.371), + Real(1.442), Real(-0.476), Real(-1.601), + Real(1.609), Real(-0.294), Real(-1.787), + Real(2.023), Real(0), Real(-1.469), + Real(1.945), Real(0.294), Real(-1.413), + Real(1.743), Real(0.476), Real(-1.266), + Real(1.493), Real(0.476), Real(-1.085), + Real(1.291), Real(0.294), Real(-0.938), + Real(1.214), Real(0), Real(-0.882), + Real(1.291), Real(-0.294), Real(-0.938), + Real(1.493), Real(-0.476), Real(-1.085), + Real(1.743), Real(-0.476), Real(-1.266), + Real(1.945), Real(-0.294), Real(-1.413), + Real(2.284), Real(0), Real(-1.017), + Real(2.197), Real(0.294), Real(-0.978), + Real(1.968), Real(0.476), Real(-0.876), + Real(1.686), Real(0.476), Real(-0.751), + Real(1.458), Real(0.294), Real(-0.649), + Real(1.37), Real(0), Real(-0.61 ), + Real(1.458), Real(-0.294), Real(-0.649), + Real(1.686), Real(-0.476), Real(-0.751), + Real(1.968), Real(-0.476), Real(-0.876), + Real(2.197), Real(-0.294), Real(-0.978), + Real(2.445), Real(0), Real(-0.52 ), + Real(2.352), Real(0.294), Real(-0.5 ), + Real(2.107), Real(0.476), Real(-0.448), + Real(1.805), Real(0.476), Real(-0.384), + Real(1.561), Real(0.294), Real(-0.332), + Real(1.467), Real(0), Real(-0.312), + Real(1.561), Real(-0.294), Real(-0.332), + Real(1.805), Real(-0.476), Real(-0.384), + Real(2.107), Real(-0.476), Real(-0.448), + Real(2.352), Real(-0.294), Real(-0.5) +}; + + +static int gIndices[NUM_TRIANGLES][3] = { + {0, 1, 11}, + {1, 2, 12}, + {2, 3, 13}, + {3, 4, 14}, + {4, 5, 15}, + {5, 6, 16}, + {6, 7, 17}, + {7, 8, 18}, + {8, 9, 19}, + {9, 0, 10}, + {10, 11, 21}, + {11, 12, 22}, + {12, 13, 23}, + {13, 14, 24}, + {14, 15, 25}, + {15, 16, 26}, + {16, 17, 27}, + {17, 18, 28}, + {18, 19, 29}, + {19, 10, 20}, + {20, 21, 31}, + {21, 22, 32}, + {22, 23, 33}, + {23, 24, 34}, + {24, 25, 35}, + {25, 26, 36}, + {26, 27, 37}, + {27, 28, 38}, + {28, 29, 39}, + {29, 20, 30}, + {30, 31, 41}, + {31, 32, 42}, + {32, 33, 43}, + {33, 34, 44}, + {34, 35, 45}, + {35, 36, 46}, + {36, 37, 47}, + {37, 38, 48}, + {38, 39, 49}, + {39, 30, 40}, + {40, 41, 51}, + {41, 42, 52}, + {42, 43, 53}, + {43, 44, 54}, + {44, 45, 55}, + {45, 46, 56}, + {46, 47, 57}, + {47, 48, 58}, + {48, 49, 59}, + {49, 40, 50}, + {50, 51, 61}, + {51, 52, 62}, + {52, 53, 63}, + {53, 54, 64}, + {54, 55, 65}, + {55, 56, 66}, + {56, 57, 67}, + {57, 58, 68}, + {58, 59, 69}, + {59, 50, 60}, + {60, 61, 71}, + {61, 62, 72}, + {62, 63, 73}, + {63, 64, 74}, + {64, 65, 75}, + {65, 66, 76}, + {66, 67, 77}, + {67, 68, 78}, + {68, 69, 79}, + {69, 60, 70}, + {70, 71, 81}, + {71, 72, 82}, + {72, 73, 83}, + {73, 74, 84}, + {74, 75, 85}, + {75, 76, 86}, + {76, 77, 87}, + {77, 78, 88}, + {78, 79, 89}, + {79, 70, 80}, + {80, 81, 91}, + {81, 82, 92}, + {82, 83, 93}, + {83, 84, 94}, + {84, 85, 95}, + {85, 86, 96}, + {86, 87, 97}, + {87, 88, 98}, + {88, 89, 99}, + {89, 80, 90}, + {90, 91, 101}, + {91, 92, 102}, + {92, 93, 103}, + {93, 94, 104}, + {94, 95, 105}, + {95, 96, 106}, + {96, 97, 107}, + {97, 98, 108}, + {98, 99, 109}, + {99, 90, 100}, + {100, 101, 111}, + {101, 102, 112}, + {102, 103, 113}, + {103, 104, 114}, + {104, 105, 115}, + {105, 106, 116}, + {106, 107, 117}, + {107, 108, 118}, + {108, 109, 119}, + {109, 100, 110}, + {110, 111, 121}, + {111, 112, 122}, + {112, 113, 123}, + {113, 114, 124}, + {114, 115, 125}, + {115, 116, 126}, + {116, 117, 127}, + {117, 118, 128}, + {118, 119, 129}, + {119, 110, 120}, + {120, 121, 131}, + {121, 122, 132}, + {122, 123, 133}, + {123, 124, 134}, + {124, 125, 135}, + {125, 126, 136}, + {126, 127, 137}, + {127, 128, 138}, + {128, 129, 139}, + {129, 120, 130}, + {130, 131, 141}, + {131, 132, 142}, + {132, 133, 143}, + {133, 134, 144}, + {134, 135, 145}, + {135, 136, 146}, + {136, 137, 147}, + {137, 138, 148}, + {138, 139, 149}, + {139, 130, 140}, + {140, 141, 151}, + {141, 142, 152}, + {142, 143, 153}, + {143, 144, 154}, + {144, 145, 155}, + {145, 146, 156}, + {146, 147, 157}, + {147, 148, 158}, + {148, 149, 159}, + {149, 140, 150}, + {150, 151, 161}, + {151, 152, 162}, + {152, 153, 163}, + {153, 154, 164}, + {154, 155, 165}, + {155, 156, 166}, + {156, 157, 167}, + {157, 158, 168}, + {158, 159, 169}, + {159, 150, 160}, + {160, 161, 171}, + {161, 162, 172}, + {162, 163, 173}, + {163, 164, 174}, + {164, 165, 175}, + {165, 166, 176}, + {166, 167, 177}, + {167, 168, 178}, + {168, 169, 179}, + {169, 160, 170}, + {170, 171, 181}, + {171, 172, 182}, + {172, 173, 183}, + {173, 174, 184}, + {174, 175, 185}, + {175, 176, 186}, + {176, 177, 187}, + {177, 178, 188}, + {178, 179, 189}, + {179, 170, 180}, + {180, 181, 191}, + {181, 182, 192}, + {182, 183, 193}, + {183, 184, 194}, + {184, 185, 195}, + {185, 186, 196}, + {186, 187, 197}, + {187, 188, 198}, + {188, 189, 199}, + {189, 180, 190}, + {190, 191, 201}, + {191, 192, 202}, + {192, 193, 203}, + {193, 194, 204}, + {194, 195, 205}, + {195, 196, 206}, + {196, 197, 207}, + {197, 198, 208}, + {198, 199, 209}, + {199, 190, 200}, + {200, 201, 211}, + {201, 202, 212}, + {202, 203, 213}, + {203, 204, 214}, + {204, 205, 215}, + {205, 206, 216}, + {206, 207, 217}, + {207, 208, 218}, + {208, 209, 219}, + {209, 200, 210}, + {210, 211, 221}, + {211, 212, 222}, + {212, 213, 223}, + {213, 214, 224}, + {214, 215, 225}, + {215, 216, 226}, + {216, 217, 227}, + {217, 218, 228}, + {218, 219, 229}, + {219, 210, 220}, + {220, 221, 231}, + {221, 222, 232}, + {222, 223, 233}, + {223, 224, 234}, + {224, 225, 235}, + {225, 226, 236}, + {226, 227, 237}, + {227, 228, 238}, + {228, 229, 239}, + {229, 220, 230}, + {230, 231, 241}, + {231, 232, 242}, + {232, 233, 243}, + {233, 234, 244}, + {234, 235, 245}, + {235, 236, 246}, + {236, 237, 247}, + {237, 238, 248}, + {238, 239, 249}, + {239, 230, 240}, + {240, 241, 251}, + {241, 242, 252}, + {242, 243, 253}, + {243, 244, 254}, + {244, 245, 255}, + {245, 246, 256}, + {246, 247, 257}, + {247, 248, 258}, + {248, 249, 259}, + {249, 240, 250}, + {250, 251, 261}, + {251, 252, 262}, + {252, 253, 263}, + {253, 254, 264}, + {254, 255, 265}, + {255, 256, 266}, + {256, 257, 267}, + {257, 258, 268}, + {258, 259, 269}, + {259, 250, 260}, + {260, 261, 271}, + {261, 262, 272}, + {262, 263, 273}, + {263, 264, 274}, + {264, 265, 275}, + {265, 266, 276}, + {266, 267, 277}, + {267, 268, 278}, + {268, 269, 279}, + {269, 260, 270}, + {270, 271, 281}, + {271, 272, 282}, + {272, 273, 283}, + {273, 274, 284}, + {274, 275, 285}, + {275, 276, 286}, + {276, 277, 287}, + {277, 278, 288}, + {278, 279, 289}, + {279, 270, 280}, + {280, 281, 291}, + {281, 282, 292}, + {282, 283, 293}, + {283, 284, 294}, + {284, 285, 295}, + {285, 286, 296}, + {286, 287, 297}, + {287, 288, 298}, + {288, 289, 299}, + {289, 280, 290}, + {290, 291, 1}, + {291, 292, 2}, + {292, 293, 3}, + {293, 294, 4}, + {294, 295, 5}, + {295, 296, 6}, + {296, 297, 7}, + {297, 298, 8}, + {298, 299, 9}, + {299, 290, 0}, + {0, 11, 10}, + {1, 12, 11}, + {2, 13, 12}, + {3, 14, 13}, + {4, 15, 14}, + {5, 16, 15}, + {6, 17, 16}, + {7, 18, 17}, + {8, 19, 18}, + {9, 10, 19}, + {10, 21, 20}, + {11, 22, 21}, + {12, 23, 22}, + {13, 24, 23}, + {14, 25, 24}, + {15, 26, 25}, + {16, 27, 26}, + {17, 28, 27}, + {18, 29, 28}, + {19, 20, 29}, + {20, 31, 30}, + {21, 32, 31}, + {22, 33, 32}, + {23, 34, 33}, + {24, 35, 34}, + {25, 36, 35}, + {26, 37, 36}, + {27, 38, 37}, + {28, 39, 38}, + {29, 30, 39}, + {30, 41, 40}, + {31, 42, 41}, + {32, 43, 42}, + {33, 44, 43}, + {34, 45, 44}, + {35, 46, 45}, + {36, 47, 46}, + {37, 48, 47}, + {38, 49, 48}, + {39, 40, 49}, + {40, 51, 50}, + {41, 52, 51}, + {42, 53, 52}, + {43, 54, 53}, + {44, 55, 54}, + {45, 56, 55}, + {46, 57, 56}, + {47, 58, 57}, + {48, 59, 58}, + {49, 50, 59}, + {50, 61, 60}, + {51, 62, 61}, + {52, 63, 62}, + {53, 64, 63}, + {54, 65, 64}, + {55, 66, 65}, + {56, 67, 66}, + {57, 68, 67}, + {58, 69, 68}, + {59, 60, 69}, + {60, 71, 70}, + {61, 72, 71}, + {62, 73, 72}, + {63, 74, 73}, + {64, 75, 74}, + {65, 76, 75}, + {66, 77, 76}, + {67, 78, 77}, + {68, 79, 78}, + {69, 70, 79}, + {70, 81, 80}, + {71, 82, 81}, + {72, 83, 82}, + {73, 84, 83}, + {74, 85, 84}, + {75, 86, 85}, + {76, 87, 86}, + {77, 88, 87}, + {78, 89, 88}, + {79, 80, 89}, + {80, 91, 90}, + {81, 92, 91}, + {82, 93, 92}, + {83, 94, 93}, + {84, 95, 94}, + {85, 96, 95}, + {86, 97, 96}, + {87, 98, 97}, + {88, 99, 98}, + {89, 90, 99}, + {90, 101, 100}, + {91, 102, 101}, + {92, 103, 102}, + {93, 104, 103}, + {94, 105, 104}, + {95, 106, 105}, + {96, 107, 106}, + {97, 108, 107}, + {98, 109, 108}, + {99, 100, 109}, + {100, 111, 110}, + {101, 112, 111}, + {102, 113, 112}, + {103, 114, 113}, + {104, 115, 114}, + {105, 116, 115}, + {106, 117, 116}, + {107, 118, 117}, + {108, 119, 118}, + {109, 110, 119}, + {110, 121, 120}, + {111, 122, 121}, + {112, 123, 122}, + {113, 124, 123}, + {114, 125, 124}, + {115, 126, 125}, + {116, 127, 126}, + {117, 128, 127}, + {118, 129, 128}, + {119, 120, 129}, + {120, 131, 130}, + {121, 132, 131}, + {122, 133, 132}, + {123, 134, 133}, + {124, 135, 134}, + {125, 136, 135}, + {126, 137, 136}, + {127, 138, 137}, + {128, 139, 138}, + {129, 130, 139}, + {130, 141, 140}, + {131, 142, 141}, + {132, 143, 142}, + {133, 144, 143}, + {134, 145, 144}, + {135, 146, 145}, + {136, 147, 146}, + {137, 148, 147}, + {138, 149, 148}, + {139, 140, 149}, + {140, 151, 150}, + {141, 152, 151}, + {142, 153, 152}, + {143, 154, 153}, + {144, 155, 154}, + {145, 156, 155}, + {146, 157, 156}, + {147, 158, 157}, + {148, 159, 158}, + {149, 150, 159}, + {150, 161, 160}, + {151, 162, 161}, + {152, 163, 162}, + {153, 164, 163}, + {154, 165, 164}, + {155, 166, 165}, + {156, 167, 166}, + {157, 168, 167}, + {158, 169, 168}, + {159, 160, 169}, + {160, 171, 170}, + {161, 172, 171}, + {162, 173, 172}, + {163, 174, 173}, + {164, 175, 174}, + {165, 176, 175}, + {166, 177, 176}, + {167, 178, 177}, + {168, 179, 178}, + {169, 170, 179}, + {170, 181, 180}, + {171, 182, 181}, + {172, 183, 182}, + {173, 184, 183}, + {174, 185, 184}, + {175, 186, 185}, + {176, 187, 186}, + {177, 188, 187}, + {178, 189, 188}, + {179, 180, 189}, + {180, 191, 190}, + {181, 192, 191}, + {182, 193, 192}, + {183, 194, 193}, + {184, 195, 194}, + {185, 196, 195}, + {186, 197, 196}, + {187, 198, 197}, + {188, 199, 198}, + {189, 190, 199}, + {190, 201, 200}, + {191, 202, 201}, + {192, 203, 202}, + {193, 204, 203}, + {194, 205, 204}, + {195, 206, 205}, + {196, 207, 206}, + {197, 208, 207}, + {198, 209, 208}, + {199, 200, 209}, + {200, 211, 210}, + {201, 212, 211}, + {202, 213, 212}, + {203, 214, 213}, + {204, 215, 214}, + {205, 216, 215}, + {206, 217, 216}, + {207, 218, 217}, + {208, 219, 218}, + {209, 210, 219}, + {210, 221, 220}, + {211, 222, 221}, + {212, 223, 222}, + {213, 224, 223}, + {214, 225, 224}, + {215, 226, 225}, + {216, 227, 226}, + {217, 228, 227}, + {218, 229, 228}, + {219, 220, 229}, + {220, 231, 230}, + {221, 232, 231}, + {222, 233, 232}, + {223, 234, 233}, + {224, 235, 234}, + {225, 236, 235}, + {226, 237, 236}, + {227, 238, 237}, + {228, 239, 238}, + {229, 230, 239}, + {230, 241, 240}, + {231, 242, 241}, + {232, 243, 242}, + {233, 244, 243}, + {234, 245, 244}, + {235, 246, 245}, + {236, 247, 246}, + {237, 248, 247}, + {238, 249, 248}, + {239, 240, 249}, + {240, 251, 250}, + {241, 252, 251}, + {242, 253, 252}, + {243, 254, 253}, + {244, 255, 254}, + {245, 256, 255}, + {246, 257, 256}, + {247, 258, 257}, + {248, 259, 258}, + {249, 250, 259}, + {250, 261, 260}, + {251, 262, 261}, + {252, 263, 262}, + {253, 264, 263}, + {254, 265, 264}, + {255, 266, 265}, + {256, 267, 266}, + {257, 268, 267}, + {258, 269, 268}, + {259, 260, 269}, + {260, 271, 270}, + {261, 272, 271}, + {262, 273, 272}, + {263, 274, 273}, + {264, 275, 274}, + {265, 276, 275}, + {266, 277, 276}, + {267, 278, 277}, + {268, 279, 278}, + {269, 270, 279}, + {270, 281, 280}, + {271, 282, 281}, + {272, 283, 282}, + {273, 284, 283}, + {274, 285, 284}, + {275, 286, 285}, + {276, 287, 286}, + {277, 288, 287}, + {278, 289, 288}, + {279, 280, 289}, + {280, 291, 290}, + {281, 292, 291}, + {282, 293, 292}, + {283, 294, 293}, + {284, 295, 294}, + {285, 296, 295}, + {286, 297, 296}, + {287, 298, 297}, + {288, 299, 298}, + {289, 290, 299}, + {290, 1, 0}, + {291, 2, 1}, + {292, 3, 2}, + {293, 4, 3}, + {294, 5, 4}, + {295, 6, 5}, + {296, 7, 6}, + {297, 8, 7}, + {298, 9, 8}, + {299, 0, 9}, +}; + + +#endif diff --git a/Demos/GimpactTestDemo/Win32GimpactDemo.cpp b/Demos/GimpactTestDemo/Win32GimpactDemo.cpp new file mode 100644 index 0000000..57cc15d --- /dev/null +++ b/Demos/GimpactTestDemo/Win32GimpactDemo.cpp @@ -0,0 +1,25 @@ +#ifdef _WINDOWS +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "GimpactTestDemo.h" + +///The 'createDemo' function is called from Bullet/Demos/OpenGL/Win32AppMain.cpp to instantiate this particular demo +DemoApplication* createDemo() +{ + return new GimpactConcaveDemo(); +} + +#endif diff --git a/Demos/GimpactTestDemo/main.cpp b/Demos/GimpactTestDemo/main.cpp new file mode 100644 index 0000000..2deb726 --- /dev/null +++ b/Demos/GimpactTestDemo/main.cpp @@ -0,0 +1,13 @@ + +#include "GimpactTestDemo.h" +#include "GlutStuff.h" + +//################################## main ##################################### +int main(int argc,char** argv) +{ + + GimpactConcaveDemo* concaveDemo = new GimpactConcaveDemo(); /// This will not be Deleted!!! + concaveDemo->initPhysics(); + + return glutmain(argc, argv,640,480,"DevO,s GIMPACT Test Demo",concaveDemo); +} diff --git a/Demos/GjkConvexCastDemo/CMakeLists.txt b/Demos/GjkConvexCastDemo/CMakeLists.txt new file mode 100644 index 0000000..c053ac7 --- /dev/null +++ b/Demos/GjkConvexCastDemo/CMakeLists.txt @@ -0,0 +1,48 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppLinearConvexCastDemo + LinearConvexCastDemo.cpp + main.cpp +) + +IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppLinearConvexCastDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppLinearConvexCastDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF(WIN32) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppLinearConvexCastDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppLinearConvexCastDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppLinearConvexCastDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/GjkConvexCastDemo/LinearConvexCastDemo.cpp b/Demos/GjkConvexCastDemo/LinearConvexCastDemo.cpp new file mode 100644 index 0000000..a1733d0 --- /dev/null +++ b/Demos/GjkConvexCastDemo/LinearConvexCastDemo.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. + */ + + + +/* + LinearConvexCastDemo implements an efficient continuous collision detection algorithm. + Both linear and angular velocities are supported. Gjk or Simplex based methods. + Motion using Exponential Map. + Comparison with Screwing Motion. + Also comparision with Algebraic CCD and Interval Arithmetic methods (Stephane Redon) +*/ + + +///Low level demo, doesn't include btBulletCollisionCommon.h +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btTransform.h" + +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionShapes/btConvexHullShape.h" +#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" + +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" + + + +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" + +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" + + + +#include "GL_ShapeDrawer.h" +#include "LinearConvexCastDemo.h" +#include "GlutStuff.h" + +static btVoronoiSimplexSolver sVoronoiSimplexSolver; +btSimplexSolverInterface& gGjkSimplexSolver = sVoronoiSimplexSolver; + +static float yaw=0.f,pitch=0.f,roll=0.f; +static const int maxNumObjects = 4; +static const int numObjects = 2; + +static btPolyhedralConvexShape* shapePtr[maxNumObjects]; + +static btTransform tr[numObjects]; + + + +void LinearConvexCastDemo::initPhysics() +{ + + setCameraDistance(10.f); + + tr[0].setIdentity(); + tr[0].setOrigin( btVector3( 0.0f, 5.5f, 0.0f ) ); + + tr[1].setIdentity(); + tr[1].setOrigin( btVector3( 0.0f, 0.0f, 0.0f ) ); + + // Pyramide + float r = 1.0f; + float h = 2.0f; + + btConvexHullShape* shapeA = new btConvexHullShape; + shapeA->addPoint( btVector3( 0.0f, 0.75f * h, 0.0f ) ); + shapeA->addPoint( btVector3( -r, -0.25f * h, r ) ); + shapeA->addPoint( btVector3( r, -0.25f * h, r ) ); + shapeA->addPoint( btVector3( r, -0.25f * h, -r ) ); + shapeA->addPoint( btVector3( -r, -0.25f * h, -r ) ); + + + + // Triangle + btConvexHullShape* shapeB = new btConvexHullShape; + shapeB->addPoint( btVector3( 0.0f, 1.0f, 0.0f ) ); + shapeB->addPoint( btVector3( 1.0f, -1.0f, 0.0f ) ); + shapeB->addPoint( btVector3( -1.0f, -1.0f, 0.0f ) ); + + shapePtr[0] = shapeA; + shapePtr[1] = shapeB; + + shapePtr[0]->setMargin( 0.01f ); + shapePtr[1]->setMargin( 0.01f ); +} + +//to be implemented by the demo +void LinearConvexCastDemo::clientMoveAndDisplay() +{ + displayCallback(); +} + +LinearConvexCastDemo::~LinearConvexCastDemo() +{ + delete shapePtr[0]; + delete shapePtr[1]; +} + +void LinearConvexCastDemo::displayCallback(void) +{ + updateCamera(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glDisable(GL_LIGHTING); + + GL_ShapeDrawer::drawCoordSystem(); + + + + static btScalar angle = 0.f; + angle+=getDeltaTimeMicroseconds()/1000000.0; + + tr[1].setRotation(btQuaternion(btVector3(1,0,0),angle)); + + btTransform toA, toB; + toA = tr[0]; + toA.setOrigin( btVector3( 0.0f, 0.f, 0.0f ) ); + toB = tr[1]; + toB.setOrigin( btVector3( 0.0f, 0.0f, 0.0f ) ); + + + gGjkSimplexSolver.reset(); + + + btVector3 worldBoundsMin(-1000,-1000,-1000); + btVector3 worldBoundsMax(1000,1000,1000); + + + //btGjkConvexCast convexCaster(shapePtr[ 0 ], shapePtr[ 1 ], &gGjkSimplexSolver ); + btSubsimplexConvexCast convexCaster( shapePtr[ 0 ], shapePtr[ 1 ], &gGjkSimplexSolver ); + + btConvexCast::CastResult result; + + result.m_hitPoint.setValue(0,0,0); + + convexCaster.calcTimeOfImpact( tr[ 0 ], toA, tr[ 1 ], toB, result ); + + btScalar m1[16], m2[16],m3[16]; + tr[ 0 ].getOpenGLMatrix( m1 ); + tr[ 1 ].getOpenGLMatrix( m2 ); + + btSphereShape sphere(0.2); + + btTransform tmp = tr[0]; + tmp.setOrigin(result.m_hitPoint); + tmp.getOpenGLMatrix(m3); + m_shapeDrawer->drawOpenGL( m3, &sphere, btVector3( 1, 0, 1 ), getDebugMode() ,worldBoundsMin,worldBoundsMax); + + + m_shapeDrawer->drawOpenGL( m1, shapePtr[ 0 ], btVector3( 1, 0, 0 ), getDebugMode() ,worldBoundsMin,worldBoundsMax); + m_shapeDrawer->drawOpenGL( m2, shapePtr[ 1 ], btVector3( 1, 0, 0 ), getDebugMode() ,worldBoundsMin,worldBoundsMax); + + btVector3 originA, originB; + originA.setInterpolate3( tr[ 0 ].getOrigin(), toA.getOrigin(), result.m_fraction ); + originB.setInterpolate3( tr[ 1 ].getOrigin(), toB.getOrigin(), result.m_fraction ); + + btTransform A = tr[ 0 ]; + A.setOrigin( originA ); + + btTransform B = tr[ 1 ]; + B.setOrigin( originB ); + + A.getOpenGLMatrix( m1 ); + B.getOpenGLMatrix( m2 ); + + m_shapeDrawer->drawOpenGL( m1, shapePtr[ 0 ], btVector3( 1, 1, 0 ), getDebugMode() ,worldBoundsMin,worldBoundsMax); + m_shapeDrawer->drawOpenGL( m2, shapePtr[ 1 ], btVector3( 1, 1, 0 ), getDebugMode() ,worldBoundsMin,worldBoundsMax); + + glFlush(); + glutSwapBuffers(); +} diff --git a/Demos/GjkConvexCastDemo/LinearConvexCastDemo.h b/Demos/GjkConvexCastDemo/LinearConvexCastDemo.h new file mode 100644 index 0000000..9b64d28 --- /dev/null +++ b/Demos/GjkConvexCastDemo/LinearConvexCastDemo.h @@ -0,0 +1,44 @@ +/* +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 LINEAR_CONVEX_CAST_DEMO_H +#define LINEAR_CONVEX_CAST_DEMO_H + +#include "GlutDemoApplication.h" + +///LinearConvexCastDemo shows the working of the object sweep / pure-linear continuous collision detection query +class LinearConvexCastDemo : public GlutDemoApplication +{ + public: + + virtual ~LinearConvexCastDemo(); + + void initPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + static DemoApplication* Create() + { + LinearConvexCastDemo* demo = new LinearConvexCastDemo(); + demo->myinit(); + demo->initPhysics(); + return demo; + } + +}; + +#endif //LINEAR_CONVEX_CAST_DEMO_H + diff --git a/Demos/GjkConvexCastDemo/main.cpp b/Demos/GjkConvexCastDemo/main.cpp new file mode 100644 index 0000000..3c2748a --- /dev/null +++ b/Demos/GjkConvexCastDemo/main.cpp @@ -0,0 +1,17 @@ + +#include "LinearConvexCastDemo.h" +#include "GlutStuff.h" + +int screenWidth = 640; +int screenHeight = 480; + +int main(int argc,char** argv) +{ + + LinearConvexCastDemo* linearCastDemo = new LinearConvexCastDemo(); + + linearCastDemo->initPhysics(); + + + return glutmain(argc, argv,screenWidth,screenHeight,"Linear Convex Cast Demo",linearCastDemo); +} diff --git a/Demos/Gpu2dDemo/BasicDemo.cpp b/Demos/Gpu2dDemo/BasicDemo.cpp new file mode 100644 index 0000000..47f9dc2 --- /dev/null +++ b/Demos/Gpu2dDemo/BasicDemo.cpp @@ -0,0 +1,808 @@ +/* +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. +*/ + +///The 3 following lines include the CPU implementation of the kernels, keep them in this order. +#include "BulletMultiThreaded/btGpuDefines.h" +#include "BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#include "BulletMultiThreaded/btGpuUtilsSharedCode.h" + + + +#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" + +#include "btGpuDemoPairCache.h" + +#include "btGpuDemoDynamicsWorld.h" +#include "GLDebugFont.h" + +#define USE_CUDA_DEMO_PAIR_CASHE 0 + +#define SPEC_TEST 0 +#define OECAKE_LOADER 1 + +#ifdef _DEBUG +// #define LARGE_DEMO 0 + #define LARGE_DEMO 1 +#else + #define LARGE_DEMO 1 +#endif + +#if LARGE_DEMO + ///create 512 (8x8x8) dynamic object +// #define ARRAY_SIZE_X 116 +// #define ARRAY_SIZE_Y 116 + +// #define ARRAY_SIZE_X 228 +// #define ARRAY_SIZE_Y 228 +// #define ARRAY_SIZE_X 256 +// #define ARRAY_SIZE_Y 156 + #define ARRAY_SIZE_X 50 + #define ARRAY_SIZE_Y 100 + #define ARRAY_SIZE_Z 1 +#else + ///create 125 (5x5x5) dynamic object + #define ARRAY_SIZE_X 5 + #define ARRAY_SIZE_Y 5 +// #define ARRAY_SIZE_Z 5 + #define ARRAY_SIZE_Z 1 +#endif + + +//maximum number of objects (and allow user to shoot additional boxes) +#define NUM_SMALL_PROXIES (ARRAY_SIZE_X*ARRAY_SIZE_Y*ARRAY_SIZE_Z) +#define MAX_PROXIES (NUM_SMALL_PROXIES + 1024) +#define MAX_LARGE_PROXIES 0 +#define MAX_SMALL_PROXIES (MAX_PROXIES - MAX_LARGE_PROXIES) + +///scaling of the objects (0.1 = 20 centimeter boxes ) +//#define SCALING 0.1 +#define SCALING 1 +#define START_POS_X 0 +#define START_POS_Y 0 +#define START_POS_Z 0 + +#include "BasicDemo.h" +#include "GlutStuff.h" +///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files. +#include "btBulletDynamicsCommon.h" +#include //printf debugging + +#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" + +#ifdef BT_USE_CUDA +#include "../Extras/CUDA/btCudaBroadphase.h" +#else +#include "BulletMultiThreaded/btGpu3DGridBroadphase.h" +#endif + +btScalar gTimeStep = btScalar(1./60.); + +bool gbDrawBatches = false; +int gSelectedBatch = CUDA_DEMO_DYNAMICS_WORLD_MAX_BATCHES; +#ifdef BT_USE_CUDA +bool gUseCPUSolver = false; +#else +bool gUseCPUSolver = true; +#endif //BT_USE_CUDA + +bool gUseBulletNarrowphase = false; + +#include "oecakeLoader.h" + + +class BasicDemoOecakeLoader : public BasicOECakeReader +{ + + BasicDemo* m_demo; + +public: + + BasicDemoOecakeLoader(BasicDemo* demo) + :m_demo(demo) + { + + } + + virtual void createBodyForCompoundShape(btCompoundShape* compoundTmpShape,bool addConstraint, const btTransform& worldTransform, btScalar mass) + { + + btDefaultMotionState* myMotionState= 0; + + btVector3 aabbMin,aabbMax; + compoundTmpShape->getAabb(btTransform::getIdentity(),aabbMin,aabbMax); + int numSpheres = compoundTmpShape->getNumChildShapes(); + btAssert(numSpheres>0); + if (numSpheres>8) + { + printf("error: exceeded 8 spheres\n"); + return; + } + + btVector3* positions = new btVector3[numSpheres]; + btScalar* radii = new btScalar[numSpheres]; + + for (int i=0;igetChildShape(i)->getShapeType()== SPHERE_SHAPE_PROXYTYPE); + btSphereShape* sphereShape = (btSphereShape*)compoundTmpShape->getChildShape(i); + radii[i]=sphereShape->getRadius(); + positions[i] = compoundTmpShape->getChildTransform(i).getOrigin(); + } + + btMultiSphereShape* multiSphere = new btMultiSphereShape(positions,radii,numSpheres); + m_demo->addCollisionShape(multiSphere); + + btVector3 localInertia(0,0,0); + if (mass) + { + myMotionState = new btDefaultMotionState(worldTransform); + multiSphere->calculateLocalInertia(mass,localInertia); + } + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btRigidBody* body = new btRigidBody(mass,myMotionState,multiSphere,localInertia); + body->setLinearFactor(btVector3(1,1,0)); + body->setAngularFactor(btVector3(0,0,1)); + + body->setWorldTransform(worldTransform); + + + m_demo->getDynamicsWorld()->addRigidBody(body); + + if (addConstraint) + { + btVector3 pivotInA(0,0,0); + btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*body,pivotInA); + m_demo->getDynamicsWorld()->addConstraint(p2p); + } + } + +}; + + +void BasicDemo::clientMoveAndDisplay() +{ + updateCamera(); + glDisable(GL_LIGHTING); + glColor3f(1.f, 1.f, 1.f); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glDisable(GL_TEXTURE_2D); // we always draw wireframe in this demo + + //simple dynamics world doesn't handle fixed-time-stepping + float ms = getDeltaTimeMicroseconds(); + + ///step the simulation + if (m_dynamicsWorld) + { +#if USE_CUDA_DEMO_PAIR_CASHE + btGpuDemoPairCache* pc = (btGpuDemoPairCache*)m_dynamicsWorld->getPairCache(); + pc->m_numSmallProxies = m_dynamicsWorld->getNumCollisionObjects(); // - 1; // exclude floor +#endif + m_dynamicsWorld->stepSimulation(gTimeStep,0);//ms / 1000000.f); + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + } + renderme(); + + ms = getDeltaTimeMicroseconds(); + + glFlush(); + + glutSwapBuffers(); + +} + + + +void BasicDemo::displayCallback(void) { + + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + //optional but useful: debug drawing to detect problems + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + glFlush(); + glutSwapBuffers(); +} + + +#define POS_OFFS_X (ARRAY_SIZE_X * SCALING + 20) +#define POS_OFFS_Y (ARRAY_SIZE_Y * SCALING + 10) +#define POS_OFFS_Z (ARRAY_SIZE_Z * SCALING) + +#if OECAKE_LOADER + btVector3 gWorldMin(-200, 0, 0); + btVector3 gWorldMax( 200, 200, 0); +#else + btVector3 gWorldMin(-POS_OFFS_X, -POS_OFFS_Y, -POS_OFFS_Z); + btVector3 gWorldMax( POS_OFFS_X, POS_OFFS_Y, POS_OFFS_Z); +#endif + +//btGpuDemoPairCache* gPairCache; +btOverlappingPairCache* gPairCache; + + +static btScalar fRandMinMax(btScalar fMin, btScalar fMax) +{ + btScalar fr = btScalar(rand()) / btScalar(RAND_MAX); + return fMax - (fMax - fMin) * fr; +} + + +void BasicDemo::initPhysics() +{ + setTexturing(false); + setShadows(false); + +#if OECAKE_LOADER + setCameraDistance(80.); + m_cameraTargetPosition.setValue(50, 10, 0); +#else + #if LARGE_DEMO + setCameraDistance(btScalar(SCALING*100.)); + #else + setCameraDistance(btScalar(SCALING*20.)); + #endif + m_cameraTargetPosition.setValue(START_POS_X, -START_POS_Y-20, START_POS_Z); +#endif + m_azi = btScalar(0.f); + m_ele = btScalar(0.f); + + ///collision configuration contains default setup for memory, collision setup + + btDefaultCollisionConstructionInfo dci; + dci.m_defaultMaxPersistentManifoldPoolSize=50000; + dci.m_defaultMaxCollisionAlgorithmPoolSize=50000; + + m_collisionConfiguration = new btDefaultCollisionConfiguration(dci); + + ///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->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE,BOX_SHAPE_PROXYTYPE,new btEmptyAlgorithm::CreateFunc); + + m_dispatcher->setNearCallback(cudaDemoNearCallback); + + +#if USE_CUDA_DEMO_PAIR_CASHE + gPairCache = new (btAlignedAlloc(sizeof(btGpuDemoPairCache),16)) btGpuDemoPairCache(MAX_PROXIES, 24, MAX_SMALL_PROXIES); +#else + gPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16))btHashedOverlappingPairCache(); +#endif + + + btVector3 numOfCells = (gWorldMax - gWorldMin) / (2. * SCALING); + int numOfCellsX = (int)numOfCells[0]; + int numOfCellsY = (int)numOfCells[1]; + int numOfCellsZ = (int)numOfCells[2]; + +// m_broadphase = new btAxisSweep3(gWorldMin, gWorldMax, MAX_PROXIES,gPairCache); + m_broadphase = new btDbvtBroadphase(gPairCache); +// m_broadphase = new btGpu3DGridBroadphase(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,24,24); +// m_broadphase = new btCudaBroadphase(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,24,24); + + + ///the default constraint solver + m_solver = new btSequentialImpulseConstraintSolver(); + + btGpuDemoDynamicsWorld* pDdw = new btGpuDemoDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration, MAX_PROXIES); + m_dynamicsWorld = pDdw; + pDdw->getSimulationIslandManager()->setSplitIslands(true); + pDdw->setObjRad(SCALING); + pDdw->setWorldMin(gWorldMin); + pDdw->setWorldMax(gWorldMax); +// gUseCPUSolver = true; + pDdw->setUseCPUSolver(gUseCPUSolver); + gUseBulletNarrowphase = false; + pDdw->setUseBulletNarrowphase(gUseBulletNarrowphase); + +// m_dynamicsWorld->setGravity(btVector3(0,0,0)); + m_dynamicsWorld->setGravity(btVector3(0,-10.,0)); + m_dynamicsWorld->getSolverInfo().m_numIterations = 4; + + { + //create a few dynamic rigidbodies + // Re-using the same collision is better for memory usage and performance + + + +#if 1 + #define SPRADIUS btScalar(SCALING*0.1f) + #define SPRPOS btScalar(SCALING*0.05f) + static btVector3 sSphPos[8]; + + for (int k=0;k<8;k++) + { + sSphPos[k].setValue((k-4)*0.25*SCALING,0,0); + } + + btVector3 inertiaHalfExtents(SPRADIUS, SPRADIUS, SPRADIUS); + static btScalar sSphRad[8] = + { +// SPRADIUS, SPRADIUS, SPRADIUS, SPRADIUS,SPRADIUS, SPRADIUS, SPRADIUS, 0.3 + SPRADIUS, SPRADIUS, SPRADIUS, SPRADIUS,SPRADIUS, SPRADIUS, SPRADIUS, SPRADIUS + }; +// sSphPos[0].setX(sSphPos[0].getX()-0.15); + #undef SPR + btMultiSphereShape* colShape[2]; + colShape[0] = new btMultiSphereShape( sSphPos, sSphRad, 8); + colShape[1] = new btMultiSphereShape( sSphPos, sSphRad, 2); + + //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); + m_collisionShapes.push_back(colShape[0]); + m_collisionShapes.push_back(colShape[1]); +#endif + + /// Create Dynamic Objects + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(0.f); + + //rigidbody is dynamic if and only if mass is non zero, otherwise static + bool isDynamic = (mass != 0.f); + + btVector3 localInertia(0,0,0); + +#if OECAKE_LOADER + BasicDemoOecakeLoader loader(this); + if (!loader.processFile("test1.oec")) + { + loader.processFile("../../test1.oec"); + } +#if 0 // perfomance test : work-in-progress + { // add more object, but share their shapes + int numNewObjects = 500; + mass = 1.f; + for(int n_obj = 0; n_obj < numNewObjects; n_obj++) + { + btDefaultMotionState* myMotionState= 0; + btVector3 localInertia(0,0,0); + btTransform worldTransform; + worldTransform.setIdentity(); + btScalar fx = fRandMinMax(-30., 30.); + btScalar fy = fRandMinMax(5., 30.); + worldTransform.setOrigin(btVector3(fx, fy, 0.f)); + int sz = m_collisionShapes.size(); + btMultiSphereShape* multiSphere = (btMultiSphereShape*)m_collisionShapes[1]; + myMotionState = new btDefaultMotionState(worldTransform); + multiSphere->calculateLocalInertia(mass, localInertia); + btRigidBody* body = new btRigidBody(mass,myMotionState,multiSphere,localInertia); + body->setLinearFactor(btVector3(1,1,0)); + body->setAngularFactor(btVector3(0,0,1)); + body->setWorldTransform(worldTransform); + getDynamicsWorld()->addRigidBody(body); + } + } +#endif + +#else +#if (!SPEC_TEST) + float start_x = START_POS_X - ARRAY_SIZE_X * SCALING; + float start_y = START_POS_Y - ARRAY_SIZE_Y * SCALING; + float start_z = START_POS_Z - ARRAY_SIZE_Z * SCALING; + + int collisionShapeIndex = 0; + for (int k=0;kcalculateLocalInertia(mass,localInertia); + + + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + //btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape[collisionShapeIndex],localInertia); + collisionShapeIndex = 1 - collisionShapeIndex; + rbInfo.m_startWorldTransform=startTransform; + btRigidBody* body = new btRigidBody(rbInfo); + m_dynamicsWorld->addRigidBody(body); + } + } + } +#else//SPEC_TEST + // narrowphase test - 2 bodies at the same position + float start_x = START_POS_X; +// float start_y = START_POS_Y; + float start_y = gWorldMin[1] + SCALING * 0.7f + 5.f; + float start_z = START_POS_Z; + startTransform.setOrigin(SCALING*btVector3(start_x,start_y,start_z)); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape[0],localInertia); + rbInfo.m_startWorldTransform=startTransform; + btRigidBody* body = new btRigidBody(rbInfo); + m_dynamicsWorld->addRigidBody(body); + + btPoint2PointConstraint * p2pConstr = new btPoint2PointConstraint(*body, btVector3(1., 0., 0.)); + m_dynamicsWorld->addConstraint(p2pConstr); + + startTransform.setOrigin(SCALING*btVector3(start_x-2.f, start_y,start_z)); + rbInfo.m_startWorldTransform=startTransform; + btRigidBody* body1 = new btRigidBody(rbInfo); + m_dynamicsWorld->addRigidBody(body1); + + p2pConstr = new btPoint2PointConstraint(*body, *body1, btVector3(-1., 0., 0.), btVector3(1., 0., 0.)); + m_dynamicsWorld->addConstraint(p2pConstr); + + +#endif//SPEC_TEST +#endif //OE_CAKE_LOADER + } + // now set Ids used by collision detector and constraint solver + int numObjects = m_dynamicsWorld->getNumCollisionObjects(); + btCollisionObjectArray& collisionObjects = m_dynamicsWorld->getCollisionObjectArray(); + for(int i = 0; i < numObjects; i++) + { + btCollisionObject* colObj = collisionObjects[i]; + colObj->setCompanionId(i+1); // 0 reserved for the "world" object + btCollisionShape* pShape = colObj->getCollisionShape(); + int shapeType = pShape->getShapeType(); + if(shapeType == MULTI_SPHERE_SHAPE_PROXYTYPE) + { + btMultiSphereShape* pMs = (btMultiSphereShape*)pShape; + int numSpheres = pMs->getSphereCount(); + pDdw->addMultiShereObject(numSpheres, i + 1); + for(int j = 0; j < numSpheres; j++) + { + btVector3 sphPos = pMs->getSpherePosition(j); + float sphRad = pMs->getSphereRadius(j); + pDdw->addSphere(sphPos, sphRad); + } + } + else + { + btAssert(0); + } + } +#if OECAKE_LOADER + clientResetScene(); +#endif +} + +void BasicDemo::clientResetScene() +{ + DemoApplication::clientResetScene(); +#if OECAKE_LOADER + return; +#endif +#if SPEC_TEST + { + float start_x = START_POS_X; +// float start_y = START_POS_Y; + float start_y = gWorldMin[1] + SCALING * 0.7f + 5.f; + float start_z = START_POS_Z; + int numObjects = m_dynamicsWorld->getNumCollisionObjects(); + btCollisionObjectArray& collisionObjects = m_dynamicsWorld->getCollisionObjectArray(); + btTransform startTransform; + startTransform.setIdentity(); + for(int n = 0; n < numObjects; n++) + { + btCollisionObject* colObj = collisionObjects[n]; + btRigidBody* rb = btRigidBody::upcast(colObj); + if(!n) + { + startTransform.setOrigin(SCALING*btVector3(start_x,start_y,start_z)); + } + else + { +// startTransform.setOrigin(SCALING*btVector3(start_x+0.1f,start_y+SCALING * 0.7f * 2.f, start_z)); + startTransform.setOrigin(SCALING*btVector3(start_x-2.f,start_y, start_z)); + } + rb->setCenterOfMassTransform(startTransform); + } + return; + } +#endif +// we don't use motionState, so reset transforms here + int numObjects = m_dynamicsWorld->getNumCollisionObjects(); + btCollisionObjectArray& collisionObjects = m_dynamicsWorld->getCollisionObjectArray(); + + float start_x = START_POS_X - ARRAY_SIZE_X * SCALING; + float start_y = START_POS_Y - ARRAY_SIZE_Y * SCALING; + float start_z = START_POS_Z - ARRAY_SIZE_Z * SCALING; + btTransform startTransform; + startTransform.setIdentity(); + + for(int n = 0; n < numObjects; n++) + { + btCollisionObject* colObj = collisionObjects[n]; + colObj->setCompanionId(n); + btRigidBody* rb = btRigidBody::upcast(colObj); + int offs = ARRAY_SIZE_X * ARRAY_SIZE_Z; + int indx = n; + int ky = indx / offs; + indx -= ky * offs; + int kx = indx / ARRAY_SIZE_Z; + indx -= kx * ARRAY_SIZE_Z; + int kz = indx; + startTransform.setOrigin(SCALING*btVector3( + 2.0*SCALING*kx + start_x, + 2.0*SCALING*ky + start_y, + 2.0*SCALING*kz + start_z)); + rb->setCenterOfMassTransform(startTransform); + } +} + + + +void BasicDemo::exitPhysics() +{ + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;jsetUseCPUSolver(gUseCPUSolver); + break; + } + case 'j' : + { + btGpuDemoDynamicsWorld* pDdw = (btGpuDemoDynamicsWorld*)m_dynamicsWorld; + gUseBulletNarrowphase = !gUseBulletNarrowphase; + pDdw->setUseBulletNarrowphase(gUseBulletNarrowphase); + if(gUseBulletNarrowphase) + { + m_dispatcher->setNearCallback(btCollisionDispatcher::defaultNearCallback); + } + else + { + m_dispatcher->setNearCallback(cudaDemoNearCallback); + } + break; + } + default : + { + DemoApplication::keyboardCallback(key, x, y); + } + break; + } + + if(key == ' ') + { +#if USE_CUDA_DEMO_PAIR_CASHE + ((btGpuDemoPairCache*)gPairCache)->reset(); +#endif + } +} + + + + +#define BATCH_NUM_COLORS 12 + +const float cBatchColorTab[BATCH_NUM_COLORS * 3] = + { + 1.f, 0.f, 0.f, + 0.f, 1.f, 0.f, + 0.f, 0.f, 1.f, + 1.f, 1.f, 0.f, + 0.f, 1.f, 1.f, + 1.f, 0.f, 1.f, + 1.f, .5f, 0.f, + .5f, 1.f, 0.f, + 0.f, 1.f, .5f, + 0.f, .5f, 1.f, + .5f, 0.f, 1.f, + 1.f, 0.f, .5f + }; + + +void BasicDemo::DrawConstraintInfo() +{ + int fontW = 10; // hack, could be changed + int fontH = 14; // hack, could be changed + char buf[32]; + float xOffs; + float yOffs = fontH * 2; + glDisable(GL_LIGHTING); + glColor3f(1, 1, 1); + sprintf(buf,"solver on %s", gUseCPUSolver ? "CPU" : "CUDA"); + xOffs = m_glutScreenWidth - (strlen(buf) + 1) * fontW; + GLDebugDrawString(xOffs, yOffs,buf); + yOffs += fontH; + btGpuDemoDynamicsWorld* cddw = (btGpuDemoDynamicsWorld*)m_dynamicsWorld; + for(int i = 0; i < CUDA_DEMO_DYNAMICS_WORLD_MAX_BATCHES; i++) + { + const float* pCol = cBatchColorTab + i * 3; + glColor3f(pCol[0], pCol[1], pCol[2]); + sprintf(buf,"%2d : %5d", i, cddw->m_numInBatches[i]); + xOffs = m_glutScreenWidth - (strlen(buf) + 1) * fontW; + GLDebugDrawString(xOffs, yOffs,buf); + yOffs += fontH; + } +} + + +void BasicDemo::renderme() +{ + renderscene(0); + if(gbDrawBatches) + { + ((btGpuDemoDynamicsWorld*)m_dynamicsWorld)->debugDrawConstraints(gSelectedBatch, cBatchColorTab); + } + +// if (0) + if ((m_debugMode & btIDebugDraw::DBG_NoHelpText)==0) + { + setOrthographicProjection(); + int xOffset = 10.f; + int yStart = 20.f; + int yIncr = 20.f; + showProfileInfo(xOffset, yStart, yIncr); + DrawConstraintInfo(); + outputDebugInfo(xOffset, yStart, yIncr); + resetPerspectiveProjection(); + } +} + + + +extern int gNumClampedCcdMotions; +#define SHOW_NUM_DEEP_PENETRATIONS 1 +#ifdef SHOW_NUM_DEEP_PENETRATIONS + extern int gNumDeepPenetrationChecks; + extern int gNumSplitImpulseRecoveries; + extern int gNumGjkChecks; + extern int gNumAlignedAllocs; + extern int gNumAlignedFree; + extern int gTotalBytesAlignedAllocs; +#endif // + + +void BasicDemo::outputDebugInfo(int & xOffset,int & yStart, int yIncr) +{ + char buf[124]; + glDisable(GL_LIGHTING); + glColor3f(0, 0, 0); + + sprintf(buf,"mouse move+buttons to interact"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + sprintf(buf,"space to reset"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + sprintf(buf,"cursor keys and z,x to navigate"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + sprintf(buf,"i to toggle simulation, s single step"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + sprintf(buf,"q to quit"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + sprintf(buf,"h to toggle help text"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + sprintf(buf,"p to toggle profiling (+results to file)"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + sprintf(buf,"c to toggle constraint drawing"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + sprintf(buf,"b to draw single constraint batch"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + sprintf(buf,"u to toggle between CPU and CUDA solvers"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + sprintf(buf,"d to toggle between different batch builders"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + if (getDynamicsWorld()) + { + + sprintf(buf,"# objects = %d",getDynamicsWorld()->getNumCollisionObjects()); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + sprintf(buf,"# pairs = %d",getDynamicsWorld()->getBroadphase()->getOverlappingPairCache()->getNumOverlappingPairs()); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + } +} // BasicDemo::outputDebugInfo() diff --git a/Demos/Gpu2dDemo/BasicDemo.h b/Demos/Gpu2dDemo/BasicDemo.h new file mode 100644 index 0000000..5596ba6 --- /dev/null +++ b/Demos/Gpu2dDemo/BasicDemo.h @@ -0,0 +1,99 @@ +/* +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 BASIC_DEMO_H +#define BASIC_DEMO_H + +#include "DemoApplication.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" + + +#ifdef BT_USE_CUDA +//#include "btCudaDemoPairCache.h" +//#include +#endif //BT_USE_CUDA + +class btBroadphaseInterface; +class btCollisionShape; +class btOverlappingPairCache; +class btCollisionDispatcher; +class btConstraintSolver; +struct btCollisionAlgorithmCreateFunc; +class btDefaultCollisionConfiguration; +#include "GlutDemoApplication.h" + +///BasicDemo is good starting point for learning the code base and porting. +class BasicDemo : public GlutDemoApplication +{ + + //keep the collision shapes, for deletion/cleanup + btAlignedObjectArray m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + int m_mouseButtons; + int m_mouseOldX; + int m_mouseOldY; + + public: + + BasicDemo() + { + } + virtual ~BasicDemo() + { + exitPhysics(); + } + void initPhysics(); + + void exitPhysics(); + + ///don't shoot a box in this demo ;-) + virtual void shootBox(const btVector3& dest) {} + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + virtual void keyboardCallback(unsigned char key, int x, int y); + + virtual void clientResetScene(); + + static DemoApplication* Create() + { + BasicDemo* demo = new BasicDemo; + demo->myinit(); + demo->initPhysics(); + demo->m_mouseButtons = 0; + demo->m_mouseOldX = 0; + demo->m_mouseOldY = 0; + return demo; + } + + void DrawConstraintInfo(); + void outputDebugInfo(int & xOffset,int & yStart, int yIncr); + virtual void renderme(); + void addCollisionShape(btCollisionShape* pShape) { m_collisionShapes.push_back(pShape); } +}; + + +#endif //BASIC_DEMO_H + diff --git a/Demos/Gpu2dDemo/CMakeLists.txt b/Demos/Gpu2dDemo/CMakeLists.txt new file mode 100644 index 0000000..55ebb52 --- /dev/null +++ b/Demos/Gpu2dDemo/CMakeLists.txt @@ -0,0 +1,38 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# This is the variable for Windows. I use this to define the root of my directory structure. +SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/Glut) + +# You shouldn't have to modify anything below this line +######################################################## + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppGpu2dDemo + main.cpp + BasicDemo.cpp + BasicDemo.h + btGpuDemoPairCache.cpp + btGpuDemoPairCache.h + btGpuDemo2dSharedTypes.h + btGpuDemo2dCpuFunc.cpp + btGpuDemoDynamicsWorld.cpp + btGpuDemoDynamicsWorld.h + oecakeLoader.cpp + oecakeLoader.h + btGpuDemo2dSharedCode.h + btGpuDemo2dSharedDefs.h +) + + diff --git a/Demos/Gpu2dDemo/Makefile.am b/Demos/Gpu2dDemo/Makefile.am new file mode 100644 index 0000000..71a2a28 --- /dev/null +++ b/Demos/Gpu2dDemo/Makefile.am @@ -0,0 +1,5 @@ +noinst_PROGRAMS=BasicDemo + +BasicDemo_SOURCES=BasicDemo.cpp BasicDemo.h main.cpp +BasicDemo_CXXFLAGS=-I@top_builddir@/src -I@top_builddir@/Demos/OpenGL $(CXXFLAGS) +BasicDemo_LDADD=-L../OpenGL -lbulletopenglsupport -L../../src -lbulletdynamics -lbulletcollision -lbulletmath @opengl_LIBS@ diff --git a/Demos/Gpu2dDemo/btGpuDemo2dCpuFunc.cpp b/Demos/Gpu2dDemo/btGpuDemo2dCpuFunc.cpp new file mode 100644 index 0000000..879375c --- /dev/null +++ b/Demos/Gpu2dDemo/btGpuDemo2dCpuFunc.cpp @@ -0,0 +1,30 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#include "LinearMath/btQuickprof.h" + + +#include "LinearMath/btScalar.h" + +#include "btGpuDemo2dSharedTypes.h" + + + +#include "BulletMultiThreaded/btGpuDefines.h" +#include "BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#include "btGpuDemo2dSharedCode.h" + diff --git a/Demos/Gpu2dDemo/btGpuDemo2dSharedCode.h b/Demos/Gpu2dDemo/btGpuDemo2dSharedCode.h new file mode 100644 index 0000000..7a82906 --- /dev/null +++ b/Demos/Gpu2dDemo/btGpuDemo2dSharedCode.h @@ -0,0 +1,497 @@ +/* +Impulse based Rigid body simulation using CUDA +Copyright (c) 2007 Takahiro Harada http://www.iii.u-tokyo.ac.jp/~takahiroharada/projects/impulseCUDA.html + +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. +*/ + + + +#define USE_FRICTION 1 +#define FRICTION_BOX_GROUND_FACT 0.05f +#define FRICTION_BOX_BOX_FACT 0.05f +#define USE_CENTERS 1 +//#include "LinearMath/btMinMax.h" + +//---------- C o n s t r a i n t s o l v e r d e m o ---------------------------- + +#define MAX_VTX_PER_OBJ 8 + +/* +BT_GPU___device__ void kill_me() +{ + char* badPtr = (char*)0xFFFFFFFF; + *badPtr = 10; +} +*/ + + +BT_GPU___global__ void clearAccumulationOfLambdaDtD(float* lambdaDtBox, int numConstraints, int numContPoints) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index < numConstraints) + { + for(int i=0; i < numContPoints; i++) + lambdaDtBox[numContPoints * index + i] = 0; + } +} + +#define SPHERE_FACT 1.0f + +BT_GPU___device__ void testSphSph(float3 aPos, float3 bPos, float radA, float radB, float4* pOut) +{ + float3 del = bPos - aPos; + float dist = BT_GPU_dot(del, del); + dist = sqrtf(dist); + float maxD = radA + radB; + + if(dist > maxD) + { + return; + } + float penetration = (radA + radB - dist) * SPHERE_FACT; +// float penetration = (dist - radA - radB) * SPHERE_FACT; + float3 normal; + if(dist > 0.f) + { + float fact = -1.0f/dist; +// float fact = 1.0f/dist; + normal = del * fact; + } + else + { + normal = BT_GPU_make_float3(1.f, 0.f, 0.f); + } +// float3 contact = (bPos + aPos + normal * (radB - radA)) * 0.5f; + float3 tmp = (normal * radA); + float3 contact = aPos - tmp; + + // now add point + int numPoints = 0; + for(int i = 0; i < MAX_VTX_PER_OBJ; i++) + { + if(pOut[i*2].w >= 0.f) + { + numPoints++; + } + } + if(numPoints < MAX_VTX_PER_OBJ) + { + pOut[numPoints * 2] = BT_GPU_make_float42(contact, penetration); + pOut[numPoints * 2 + 1] = BT_GPU_make_float42(normal, 0.f); + } +} // testSphSph() + + + +BT_GPU___global__ void setConstraintDataD(int2 *constraints, + int numConstraints, + float4 *pos, + float *rotation, + char* shapes, + int2* shapeIds, + btCudaPartProps pProp, + float4 *contact) +{ + int idx = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + int aId,bId; + float3 aPos,bPos; +// float positionConstraint; +// float3 normal; + float aRot,bRot; + float sideLength2 = pProp.m_diameter*0.5f/sqrt(2.0f); + + if(idx < numConstraints) + { + aId=constraints[idx].x; + bId=constraints[idx].y; + + aPos=BT_GPU_make_float34(BT_GPU_FETCH4(pos,aId)); + bPos=BT_GPU_make_float34(BT_GPU_FETCH4(pos,bId)); + aRot= rotation[aId]; + bRot= rotation[bId]; + float cosA = cosf(aRot); + float sinA = sinf(aRot); + float cosB = cosf(bRot); + float sinB = sinf(bRot); + float4* shapeA = (float4*)(shapes + shapeIds[aId].x); + int numSphA = shapeIds[aId].y; + float4* shapeB = (float4*)(shapes + shapeIds[bId].x); + int numSphB = shapeIds[bId].y; + int i, j; + float3 ai = BT_GPU_make_float3(cosA, sinA, 0.f); + float3 aj = BT_GPU_make_float3(-sinA, cosA, 0.f); + float3 bi = BT_GPU_make_float3(cosB, sinB, 0.f); + float3 bj = BT_GPU_make_float3(-sinB, cosB, 0.f); + float4* pOut = contact + idx * MAX_VTX_PER_OBJ * 2; + for(i = 0; i < MAX_VTX_PER_OBJ; i++) + { + pOut[i * 2].w = -1.f; + pOut[i * 2 + 1].w = 0.f; + } + for(i = 0; i < numSphA; i++) + { + float3 va = aPos; + float3 tmp = ai * shapeA[i].x; + float3 tmp2 = aj * shapeA[i].y; + + va += tmp; + va += tmp2; + + float radA = shapeA[i].w; + for(j = 0; j < numSphB; j++) + { + float3 vb = bPos; + float3 tmp =bi * shapeB[j].x; + float3 tmp2 = bj * shapeB[j].y; + vb += tmp; + vb += tmp2; + float radB = shapeB[j].w; + testSphSph(va, vb, radA, radB, pOut); + } + } + } +} + + +BT_GPU___device__ float computeImpulse1(float3 rVel, + float positionConstraint, + float3 cNormal, + float dt) +{ +// const float collisionConstant = 0.1f; +// const float baumgarteConstant = 0.5f; +// const float penetrationError = 0.02f; + const float collisionConstant = -0.1f; + const float baumgarteConstant = 0.3f; + const float penetrationError = 0.02f; + + float lambdaDt=0; + float3 impulse=BT_GPU_make_float3(0.f,0.f,0.f); + + if(positionConstraint > 0) + return lambdaDt; + +// positionConstraint = btMin(0.0f,positionConstraint+penetrationError); + positionConstraint = (positionConstraint+penetrationError) < 0.f ? (positionConstraint+penetrationError) : 0.0f; + + lambdaDt = -(BT_GPU_dot(cNormal,rVel)*(1+collisionConstant)); + lambdaDt -= (baumgarteConstant/dt*positionConstraint); + + return lambdaDt; +} + + +BT_GPU___global__ void collisionWithWallBoxD(float4 *pos, + float4 *vel, + float *rotation, + float *angVel, + char* shapes, + int2* shapeIds, + float* invMass, + btCudaPartProps pProp, + btCudaBoxProps gProp, + int nParticles, + float dt) +{ + int idx = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + float3 aPos; + float aRot; + float positionConstraint; + float3 impulse; + + + if((idx > 0) && (idx < nParticles)) + { + float inv_mass = invMass[idx]; + if(inv_mass <= 0.f) + { + return; + } + aPos=BT_GPU_make_float34(BT_GPU_FETCH4(pos,idx)); + aRot=rotation[idx]; + float4* shape = (float4*)(shapes + shapeIds[idx].x); + int numSph = shapeIds[idx].y; + float cosA = cosf(aRot); + float sinA = sinf(aRot); + float3 ai = BT_GPU_make_float3(cosA, sinA, 0.f); + float3 aj = BT_GPU_make_float3(-sinA, cosA, 0.f); + + for(int iVtx=0;iVtx < numSph; iVtx++){ + float3 aVel = BT_GPU_make_float3(vel[idx].x, vel[idx].y, vel[idx].z); + float aAngVel = angVel[idx]; + float3 rerVertex = ai * shape[iVtx].x; + float3 tmp = aj * shape[iVtx].y; + rerVertex += tmp; + float3 vPos = aPos + rerVertex; + float rad = shape[iVtx].w; + float3 vVel =aVel+BT_GPU_cross(BT_GPU_make_float3(0.0f,0.0f,aAngVel),rerVertex); +// float restitution=1.0; + float restitution=0.3f; + { + positionConstraint =vPos.y - rad - gProp.minY; + impulse =BT_GPU_make_float31(0.0f); + + if(positionConstraint < 0) + { + float3 groundNormal; + groundNormal = BT_GPU_make_float3(0.0f,1.0f,0.0f); + impulse =groundNormal* + restitution * computeImpulse1(vVel,positionConstraint, + groundNormal, + dt); +#if USE_FRICTION // only with ground for now + float3 lat_vel = vVel - groundNormal * BT_GPU_dot(groundNormal,vVel); + float lat_vel_len = BT_GPU_dot(lat_vel, lat_vel); + if (lat_vel_len > 0) + { + lat_vel_len = sqrtf(lat_vel_len); + lat_vel *= 1.f/lat_vel_len; + float3 tmp = lat_vel * BT_GPU_dot(lat_vel, vVel) * FRICTION_BOX_GROUND_FACT; + impulse -= tmp; + } +#endif //USE_FRICTION + float4 tmp = BT_GPU_make_float42(impulse,0.0f); + vel[idx] += tmp; + float tmp2 = BT_GPU_cross(rerVertex,impulse).z; + angVel[idx] += tmp2; + } + } + + { + positionConstraint =vPos.x - rad - gProp.minX; + impulse =BT_GPU_make_float31(0.0f); + + if(positionConstraint < 0){ + impulse =BT_GPU_make_float3(1.0f,0.0f,0.0f)* restitution * + computeImpulse1(vVel,positionConstraint, + BT_GPU_make_float3(1.0f,0.0f,0.0f), + dt); + + float4 tmp = BT_GPU_make_float42(impulse,0.0f); + vel[idx] += tmp; + angVel[idx] += BT_GPU_cross(rerVertex,impulse).z; + } + } + + { + positionConstraint = gProp.maxX - vPos.x - rad; + impulse =BT_GPU_make_float31(0.0f); + + if(positionConstraint < 0){ + impulse =BT_GPU_make_float3(-1.0f,0.0f,0.0f)* restitution * + computeImpulse1(vVel,positionConstraint, + BT_GPU_make_float3(-1.0f,0.0f,0.0f), + dt); + + float4 tmp = BT_GPU_make_float42(impulse,0.0f); + vel[idx] += tmp; + angVel[idx] += BT_GPU_cross(rerVertex,impulse).z; + } + } + } + } +} + +BT_GPU___device__ void collisionResolutionBox( int constrId, + int2* constraints, + float4 *pos, + float4 *vel, + float *rotation, + float *angularVel, + float *lambdaDtBox, + float4* contact, + float* invMass, + btCudaPartProps pProp, + float dt) +{ +#if 1 + float3 relVel; + float3 impulse; + float lambdaDt; + float positionConstraint; + int aId=constraints[constrId].x; + int bId=constraints[constrId].y; + float3 aPos=BT_GPU_make_float34(BT_GPU_FETCH4(pos,aId)); + float3 bPos=BT_GPU_make_float34(BT_GPU_FETCH4(pos,bId)); + float3 aVel=BT_GPU_make_float34(vel[aId]); + float3 bVel=BT_GPU_make_float34(vel[bId]); + float aAngVel=angularVel[aId]; + float bAngVel=angularVel[bId]; + float4* pCont = contact + constrId * MAX_VTX_PER_OBJ * 2; + // test Vertices in A to Box B + for(int iVtx=0;iVtx= 0) + { + float3 contactNormal = BT_GPU_make_float34(pCont[iVtx * 2 + 1]); + relVel=(aVel+BT_GPU_cross(BT_GPU_make_float3(0.0f,0.0f,aAngVel), + contactPoint)) + -(bVel+BT_GPU_cross(BT_GPU_make_float3(0.0f,0.0f,bAngVel), + contactPoint+aPos-bPos)); + + lambdaDt= computeImpulse1(relVel,-positionConstraint, + contactNormal,dt); + + { + float rLambdaDt=lambdaDtBox[(MAX_VTX_PER_OBJ)*(2*constrId)+iVtx]; + float pLambdaDt=rLambdaDt; +// rLambdaDt=btMax(pLambdaDt+lambdaDt,0.0f); + rLambdaDt=(pLambdaDt+lambdaDt) > 0.0f ? (pLambdaDt+lambdaDt) : 0.0f; + lambdaDt=rLambdaDt-pLambdaDt; + lambdaDtBox[(MAX_VTX_PER_OBJ)*(2*constrId)+iVtx]=rLambdaDt; + } + impulse= contactNormal*lambdaDt*0.5; +#if USE_FRICTION + if(pCont[iVtx * 2 + 1].w <= 0) + { + float3 lat_vel = relVel - contactNormal * BT_GPU_dot(contactNormal, relVel); + float lat_vel_len = BT_GPU_dot(lat_vel, lat_vel); + if (lat_vel_len > 0) + { + lat_vel_len = sqrtf(lat_vel_len); + lat_vel *= 1.f/lat_vel_len; + float3 tmp = lat_vel * BT_GPU_dot(lat_vel , relVel) * FRICTION_BOX_BOX_FACT; + impulse -= tmp; + } + } +#endif //USE_FRICTION + if(aId && (invMass[aId] > 0.f)) + { + aVel+= impulse; + aAngVel+= BT_GPU_cross(contactPoint, impulse).z; + } + if(bId && (invMass[bId] > 0.f)) + { + bVel-= impulse; + bAngVel-= BT_GPU_cross(contactPoint+aPos-bPos, impulse).z; + } + } + } + vel[aId]=BT_GPU_make_float42(aVel,0.0f); + vel[bId]=BT_GPU_make_float42(bVel,0.0f); + angularVel[aId]=aAngVel; + angularVel[bId]=bAngVel; +#endif +} + +BT_GPU___global__ void collisionBatchResolutionBoxD(int2 *constraints, + int *batch, + int nConstraints, + float4 *pos, + float4 *vel, + float *rotation, + float *angularVel, + float *lambdaDtBox, + float4* contact, + float* invMass, + btCudaPartProps pProp, + int iBatch, + float dt) +{ + int k_idx = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(k_idx < nConstraints) + { + int idx = batch[k_idx]; + collisionResolutionBox( idx, constraints, pos, vel, rotation, angularVel, lambdaDtBox, + contact, invMass, pProp, dt); + } +} + + +extern "C" +{ + +void BT_GPU_PREF(clearAccumulationOfLambdaDt(float* lambdaDtBox, int numConstraints, int numContPoints)) +{ + if(!numConstraints) + { + return; + } + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numConstraints, 256, numBlocks, numThreads); + // execute the kernel + BT_GPU_EXECKERNEL(numBlocks, numThreads, clearAccumulationOfLambdaDtD, (lambdaDtBox, numConstraints, numContPoints)); + // check if kernel invocation generated an error + BT_GPU_CHECK_ERROR("clearAccumulationOfLambdaDtD kernel execution failed"); + +} + +void BT_GPU_PREF(setConstraintData(void* constraints,int numConstraints,int numObjs,void* pos,float *rotation,char* shapes,void* shapeIds,btCudaPartProps pProp,void* contact)) +{ + if(!numConstraints) + { + return; + } + int2* pConst = (int2*)constraints; + float4* pPos = (float4*)pos; + float4* pCont = (float4*)contact; + int2* pShapeIds = (int2*)shapeIds; + + BT_GPU_SAFE_CALL(BT_GPU_BindTexture(0, posTex, pPos, numObjs * sizeof(float4))); + + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numConstraints, 256, numBlocks, numThreads); + // execute the kernel + BT_GPU_EXECKERNEL(numBlocks, numThreads, setConstraintDataD, (pConst,numConstraints,pPos,rotation,shapes,pShapeIds,pProp,pCont)); + BT_GPU_SAFE_CALL(BT_GPU_UnbindTexture(posTex)); + // check if kernel invocation generated an error + BT_GPU_CHECK_ERROR("setConstraintDataD kernel execution failed"); +} + +void BT_GPU_PREF(collisionWithWallBox(void* pos,void* vel,float *rotation,float *angVel,char* shapes,void* shapeIds,void* invMass,btCudaPartProps pProp, btCudaBoxProps gProp,int numObjs,float dt)) +{ + if(!numObjs) + { + return; + } + float4* pPos = (float4*)pos; + float4* pVel = (float4*)vel; + int2* pShapeIds = (int2*)shapeIds; + float* pInvMass = (float*)invMass; + BT_GPU_SAFE_CALL(BT_GPU_BindTexture(0, posTex, pPos, numObjs * sizeof(float4))); + + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numObjs, 256, numBlocks, numThreads); + // execute the kernel + BT_GPU_EXECKERNEL(numBlocks, numThreads, collisionWithWallBoxD, (pPos,pVel,rotation,angVel,shapes, pShapeIds,pInvMass,pProp,gProp,numObjs,dt)); + + BT_GPU_SAFE_CALL(BT_GPU_UnbindTexture(posTex)); + // check if kernel invocation generated an error + BT_GPU_CHECK_ERROR("collisionWithWallBoxD kernel execution failed"); +} + +void BT_GPU_PREF(collisionBatchResolutionBox(void* constraints,int *batch,int numConstraints,int numObjs,void *pos,void *vel,float *rotation,float *angularVel,float *lambdaDtBox,void* contact,void* invMass,btCudaPartProps pProp,int iBatch,float dt)) +{ + if(!numConstraints) + { + return; + } + int2* pConstr = (int2*)constraints; + float4* pPos = (float4*)pos; + float4* pVel = (float4*)vel; + float4* pCont = (float4*)contact; + float* pInvMass = (float*)invMass; + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numConstraints, 128, numBlocks, numThreads); + BT_GPU_SAFE_CALL(BT_GPU_BindTexture(0, posTex, pPos, numObjs * sizeof(float4))); + // execute the kernel + BT_GPU_EXECKERNEL(numBlocks, numThreads, collisionBatchResolutionBoxD, (pConstr,batch,numConstraints,pPos,pVel,rotation,angularVel,lambdaDtBox,pCont,pInvMass,pProp,iBatch,dt)); + // check if kernel invocation generated an error + BT_GPU_CHECK_ERROR("collisionBatchResolutionBox2D kernel execution failed"); + BT_GPU_SAFE_CALL(BT_GPU_UnbindTexture(posTex)); + +} + + +} // extern "C" diff --git a/Demos/Gpu2dDemo/btGpuDemo2dSharedDefs.h b/Demos/Gpu2dDemo/btGpuDemo2dSharedDefs.h new file mode 100644 index 0000000..36bfe41 --- /dev/null +++ b/Demos/Gpu2dDemo/btGpuDemo2dSharedDefs.h @@ -0,0 +1,33 @@ +/* +Impulse based Rigid body simulation using CUDA +Copyright (c) 2007 Takahiro Harada http://www.iii.u-tokyo.ac.jp/~takahiroharada/projects/impulseCUDA.html + +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. +*/ + + + +//---------- C o n s t r a i n t s o l v e r d e m o ---------------------------- + + + + +extern "C" +{ + +void BT_GPU_PREF(clearAccumulationOfLambdaDt(float* lambdaDtBox, int numConstraints, int numContPoints)); +void BT_GPU_PREF(setConstraintData(void* constraints,int numConstraints,int numObjs,void* pos,float *rotation,char* shapes,void* shapeIds,btCudaPartProps pProp,void* oContact)); +void BT_GPU_PREF(collisionWithWallBox(void* pos,void* vel,float *rotation,float *angVel,char* shapes,void* shapeIds,void* invMass,btCudaPartProps pProp,btCudaBoxProps gProp,int numObjs,float dt)); +void BT_GPU_PREF(collisionBatchResolutionBox(void* constraints,int *batch,int numConstraints,int numObjs,void *pos,void *vel,float *rotation,float *angularVel,float *lambdaDtBox,void* contact,void* invMass,btCudaPartProps pProp,int iBatch,float dt)); + +} // extern "C" + + diff --git a/Demos/Gpu2dDemo/btGpuDemo2dSharedTypes.h b/Demos/Gpu2dDemo/btGpuDemo2dSharedTypes.h new file mode 100644 index 0000000..469e949 --- /dev/null +++ b/Demos/Gpu2dDemo/btGpuDemo2dSharedTypes.h @@ -0,0 +1,35 @@ +/* +Impulse based Rigid body simulation using CUDA +Copyright (c) 2007 Takahiro Harada http://www.iii.u-tokyo.ac.jp/~takahiroharada/projects/impulseCUDA.html + +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. +*/ + +//---------- C o n s t r a i n t s o l v e r d e m o ---------------------------- + +struct btCudaPartProps +{ + float m_mass; + float m_diameter; + float m_restCoeff; +}; + +struct btCudaBoxProps +{ + float minX; + float maxX; + float minY; + float maxY; + float minZ; + float maxZ; +}; + + diff --git a/Demos/Gpu2dDemo/btGpuDemoDynamicsWorld.cpp b/Demos/Gpu2dDemo/btGpuDemoDynamicsWorld.cpp new file mode 100644 index 0000000..9d9f208 --- /dev/null +++ b/Demos/Gpu2dDemo/btGpuDemoDynamicsWorld.cpp @@ -0,0 +1,592 @@ +/* +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 "btGpuDemoDynamicsWorld.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" +#include "LinearMath/btQuickprof.h" +#include "GlutStuff.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h" + + + + +#define BT_GPU_PREF(func) btCuda_##func + +#include "../../src/BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#include "btGpuDemo2dSharedDefs.h" +#undef BT_GPU_PREF + +#define BT_GPU_PREF(func) btGpu_##func +#include "btGpuDemo2dSharedDefs.h" +#undef BT_GPU_PREF + + + +btGpuDemoDynamicsWorld* gpCudaDemoDynamicsWorld = NULL; + + + +void btGpuDemoDynamicsWorld::grabNonContactConstraintData() +{ + m_numNonContactConstraints = 0; + int numNonContactConstraints = getNumConstraints(); + for(int i = 0; i < numNonContactConstraints; i++) + { + btTypedConstraint* ct = m_constraints[i]; + int ctype = ct->getConstraintType(); + switch(ctype) + { + case POINT2POINT_CONSTRAINT_TYPE : + grabP2PConstraintData((btPoint2PointConstraint*)ct); + break; + default : + // warning (not supported) here? + break; + } + } +} + + + +void btGpuDemoDynamicsWorld::grabContactData() +{ + int i; + btDispatcher* dispatcher = getDispatcher(); + btPersistentManifold** manifoldPtr = dispatcher->getInternalManifoldPointer(); + int numManifolds = dispatcher->getNumManifolds(); + btPersistentManifold* manifold = 0; + m_totalNumConstraints = 0; + for(i = 0; i < numManifolds; i++) + { + manifold = manifoldPtr[i]; + int numPoints = manifold->getNumContacts(); + if(!numPoints) + { + continue; + } + int numActualPoints = 0; + for(int n = 0; n < numPoints; n++) + { + btManifoldPoint& cp = manifold->getContactPoint(n); + if (cp.m_distance1<=0) + { + numActualPoints++; + } + } + if (!numActualPoints) + continue; + + btRigidBody *rbA, *rbB; + rbA = (btRigidBody*)manifold->getBody0(); + rbB = (btRigidBody*)manifold->getBody1(); + int idA = rbA->getCompanionId(); + int idB = rbB->getCompanionId(); + btVector3* pConstrData = (btVector3*)(m_hContact + m_totalNumConstraints * 2 * m_maxVtxPerObj); + if(idA < idB) + { + m_hIds[m_totalNumConstraints].x = idA; + m_hIds[m_totalNumConstraints].y = idB; + + for(int n = 0; n < numPoints; n++) + { + btManifoldPoint& cp = manifold->getContactPoint(n); + btVector3 v = cp.getPositionWorldOnA(); + pConstrData[0] = cp.getPositionWorldOnA(); + float dist = cp.getDistance(); + if(dist > 0.f) + { + pConstrData[0][3] = -1.f; + } + else + { + pConstrData[0][3] = -dist; + } + pConstrData[1] = cp.m_normalWorldOnB; + pConstrData[1][3] = 0.f; + pConstrData += 2; + } + } + else + { // should never happen + btAssert(0); + } + for(int n = numPoints; n < m_maxVtxPerObj; n++) + { + pConstrData[0][3] = -1.f; + pConstrData += 2; + } + m_totalNumConstraints++; + } +} + + + +void btGpuDemoDynamicsWorld::grabP2PConstraintData(btPoint2PointConstraint* ct) +{ + btRigidBody& bodyA = ct->getRigidBodyA(); + btTransform trA = bodyA.getCenterOfMassTransform(); + btVector3 pivotA = trA.getBasis() * ct->getPivotInA(); + btRigidBody& bodyB = ct->getRigidBodyB(); + btTransform trB = bodyB.getCenterOfMassTransform(); + btVector3 pivotB = trB.getBasis() * ct->getPivotInB(); + btVector3 pivotA_W = pivotA + trA.getOrigin(); + btVector3 pivotB_W = pivotB + trB.getOrigin(); + btVector3 delta = pivotB_W - pivotA_W; + int idA = bodyA.getCompanionId(); + int idB = bodyB.getCompanionId(); + m_hIds[m_totalNumConstraints].x = idA; + m_hIds[m_totalNumConstraints].y = (idB > 0) ? idB : 0; + btVector3* pConstrData = (btVector3*)(m_hContact + m_totalNumConstraints * 2 * m_maxVtxPerObj); + for(int k = 0; k < 2; k++) + { + btScalar penetration = delta[k]; + btScalar sign = (penetration < 0) ? btScalar(-1.f) : btScalar(1.f); + btVector3 normal = btVector3(0., 0., 0.); + normal[k] = sign; + penetration *= sign; + pConstrData[0] = pivotA_W; + pConstrData[0][3] = penetration; + pConstrData[1] = normal; + pConstrData[1][3] = btScalar(1.f); + pConstrData += 2; + } + for(int n = 2; n < m_maxVtxPerObj; n++) + { + pConstrData[0][3] = -1.f; + pConstrData += 2; + } + m_totalNumConstraints++; + m_numNonContactConstraints++; +} + + + +void btGpuDemoDynamicsWorld::grabData() +{ + BT_PROFILE("grab data"); + m_numObj = getNumCollisionObjects(); + m_hPos[0].x = m_hPos[0].y = m_hPos[0].z = m_hPos[0].w = 0.f; + m_hRot[0] = 0.f; + m_hVel[0].x = m_hVel[0].y = m_hVel[0].z = m_hVel[0].w = 0.f; + m_hAngVel[0] = 0.f; + for(int i = 0; i < m_numObj; i++) + { + btCollisionObject* colObj = m_collisionObjects[i]; + btRigidBody* rb = btRigidBody::upcast(colObj); + btVector3 v; + v = rb->getCenterOfMassPosition(); + m_hPos[i+1] = *((float4*)&v); + const btTransform& tr = rb->getCenterOfMassTransform(); + v = tr.getBasis().getColumn(0); + float rot = btAtan2(v[1], v[0]); + m_hRot[i+1] = rot; + v = rb->getLinearVelocity(); + m_hVel[i+1] = *((float4*)&v); + v = rb->getAngularVelocity(); + m_hAngVel[i+1] = v[2]; + if(m_copyMassDataToGPU) + { + m_hInvMass[i+1] = rb->getInvMass(); + } + } + if(m_useBulletNarrowphase) + { + grabContactData(); + } + grabNonContactConstraintData(); +} + + + +void btGpuDemoDynamicsWorld::createBatches2() +{ + BT_PROFILE("create batches"); + int sz = m_maxObjs * m_maxNeighbors; + for(int idx = 0; idx < sz; idx++) + { + m_hBatchIds[idx] = -1; + } + for(int i = 0; i < m_totalNumConstraints; i++) + { + m_hConstraintUsed[i] = 0; + } + int curBatchId=0; + int* pBatchIds = m_hBatchIds; + for(int stage = 0; stage < m_maxBatches; stage++) + { + bool isLast = (stage == m_maxBatches-1); + for(int j = 0; j < m_numObj + 1; j++) + { + m_hConstraintCounter[j] = 0; + } + int numInBatch = 0; + for(int i = 0; i < m_totalNumConstraints; i++) + { + if(m_hConstraintUsed[i]) + { + continue; + } + int2 ids = m_hIds[i]; + if(!isLast) + { + if((m_hConstraintCounter[ids.x] == 0) && (m_hConstraintCounter[ids.y] == 0)) + { + m_hConstraintCounter[ids.x]=1; + m_hConstraintCounter[ids.y]=1; + pBatchIds[numInBatch]=i; + numInBatch++; + m_hConstraintUsed[i] = 1; + } + } + else + { + pBatchIds[numInBatch]=i; + numInBatch++; + m_hConstraintUsed[i] = 1; + } + } + m_numInBatches[stage] = numInBatch; + pBatchIds += numInBatch; + } +} + + + +void btGpuDemoDynamicsWorld::writebackData() +{ + BT_PROFILE("copy velocity into btRigidBody"); + for(int i = 0; i < m_numObj; i++) + { + btCollisionObject* colObj = m_collisionObjects[i]; + btRigidBody* rb = btRigidBody::upcast(colObj); + btVector3 v; + v = *((btVector3*)(m_hVel + i + 1)); + v[2] = 0.f; + rb->setLinearVelocity(v); + v[0] = btScalar(0.f); + v[1] = btScalar(0.f); + v[2] = m_hAngVel[i + 1]; + rb->setAngularVelocity(v); + } +} + + + +void btGpuDemoDynamicsWorld::copyDataToGPU() +{ + BT_PROFILE("copyDataToGPU"); + +#ifdef BT_USE_CUDA + + btCuda_copyArrayToDevice(m_dIds, m_hIds, sizeof(int2) * m_totalNumConstraints); + btCuda_copyArrayToDevice(m_dBatchIds, m_hBatchIds, sizeof(int) * m_totalNumConstraints); + + if(m_numNonContactConstraints) + { // non-contact constraints are set up by CPU, so copy data to GPU + int nonContConstrOffs = (m_totalNumConstraints - m_numNonContactConstraints) * 2 * m_maxVtxPerObj; + int nonContConstrSize = 2 * m_numNonContactConstraints * m_maxVtxPerObj; + btCuda_copyArrayToDevice(m_dContact + nonContConstrOffs, m_hContact + nonContConstrOffs, sizeof(float4) * nonContConstrSize); + } + + if(m_numSimStep & 1) + { + m_dcPos = m_dpPos; + m_dcVel = m_dpVel; + m_dcRot = m_dpRot; + m_dcAngVel = m_dpAngVel; + } + else + { + m_dcPos = m_dPos; + m_dcVel = m_dVel; + m_dcRot = m_dRot; + m_dcAngVel = m_dAngVel; + } + btCuda_copyArrayToDevice(m_dcPos, m_hPos, (m_numObj + 1) * sizeof(float4)); + btCuda_copyArrayToDevice(m_dcVel, m_hVel, (m_numObj + 1) * sizeof(float4)); + btCuda_copyArrayToDevice(m_dcRot, m_hRot, (m_numObj + 1) * sizeof(float)); + btCuda_copyArrayToDevice(m_dcAngVel, m_hAngVel, (m_numObj + 1) * sizeof(float)); + if(m_copyShapeDataToGPU) + { + btCuda_copyArrayToDevice(m_dShapeBuffer, m_hShapeBuffer, m_firstFreeShapeBufferOffset); + btCuda_copyArrayToDevice(m_dShapeIds, m_hShapeIds, (m_numObj + 1) * sizeof(int2)); + m_copyShapeDataToGPU = false; + } + if(m_copyMassDataToGPU) + { + btCuda_copyArrayToDevice(m_dInvMass, m_hInvMass, (m_numObj + 1) * sizeof(float)); + m_copyMassDataToGPU = false; + } +#endif //BT_USE_CUDA + +} + + + +void btGpuDemoDynamicsWorld::setConstraintData(btCudaPartProps& partProps) +{ + BT_PROFILE("set constraint data"); + partProps.m_mass = 1.0f; + partProps.m_diameter = m_objRad * 2.0f; + partProps.m_restCoeff = 1.0f; +#ifdef BT_USE_CUDA + btCuda_clearAccumulationOfLambdaDt(m_dLambdaDtBox, m_totalNumConstraints, m_maxVtxPerObj * 2); + if(!m_useBulletNarrowphase) + { + btCuda_setConstraintData(m_dIds, m_totalNumConstraints - m_numNonContactConstraints, m_numObj + 1, m_dcPos, m_dcRot, m_dShapeBuffer, m_dShapeIds, + partProps, m_dContact); + } +#endif //BT_USE_CUDA + +} + + + +void btGpuDemoDynamicsWorld::copyDataFromGPU() +{ + BT_PROFILE("copy velocity data from device"); +#ifdef BT_USE_CUDA + btCuda_copyArrayFromDevice(m_hVel, m_dcVel, (m_numObj + 1) * sizeof(float4)); + btCuda_copyArrayFromDevice(m_hAngVel, m_dcAngVel, (m_numObj + 1) * sizeof(float)); +#endif //BT_USE_CUDA +} + + + +void btGpuDemoDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) +{ + if(m_useCPUSolver) + { + solveConstraintsCPU2(solverInfo); + } + else + { + solveConstraints2(solverInfo); + } + m_totalNumConstraints = 0; +} + + + +void btGpuDemoDynamicsWorld::solveConstraints2(btContactSolverInfo& solverInfo) +{ +#ifdef BT_USE_CUDA + BT_PROFILE("solveConstraints"); + grabData(); + createBatches2(); + copyDataToGPU(); + + btCudaPartProps partProps; + setConstraintData(partProps); + + btCudaBoxProps boxProps; + boxProps.minX = m_worldMin[0]; + boxProps.maxX = m_worldMax[0]; + boxProps.minY = m_worldMin[1]; + boxProps.maxY = m_worldMax[1]; + { + BT_PROFILE("btCuda_collisionBatchResolutionBox"); + + int nIter=getSolverInfo().m_numIterations; + btDispatcherInfo& dispatchInfo = getDispatchInfo(); + btScalar timeStep = dispatchInfo.m_timeStep; + + for(int i=0;i 0) && (idB > 0)) + { + btCollisionObject* colObjA = m_collisionObjects[idA]; + btCollisionObject* colObjB = m_collisionObjects[idB]; + btVector3 vA = colObjA->getWorldTransform().getOrigin(); + btVector3 vB = colObjB->getWorldTransform().getOrigin(); + glVertex3f(vA[0], vA[1], vA[2]); + glVertex3f(vB[0], vB[1], vB[2]); + } + } + pBatchIds += numConstraints; + glEnd(); + } +} + + + +void btGpuDemoDynamicsWorld::initShapeBuffer(int maxShapeBufferSize) +{ + m_maxShapeBufferSize = maxShapeBufferSize; + m_firstFreeShapeBufferOffset = 0; + m_hShapeBuffer = new char[m_maxShapeBufferSize]; + m_hShapeIds = new int2[m_maxObjs]; + +#ifdef BT_USE_CUDA + btCuda_allocateArray((void**)&m_dShapeBuffer, m_maxShapeBufferSize); + btCuda_allocateArray((void**)&m_dShapeIds, sizeof(int) * 2 * m_maxObjs); +#endif //BT_USE_CUDA + + m_copyShapeDataToGPU = true; +} + + + +void btGpuDemoDynamicsWorld::freeShapeBuffer() +{ + delete [] m_hShapeBuffer; + delete [] m_hShapeIds; +#ifdef BT_USE_CUDA + btCuda_freeArray(m_dShapeBuffer); + btCuda_freeArray(m_dShapeIds); +#endif //BT_USE_CUDA +} + + + +void btGpuDemoDynamicsWorld::addSphere(btVector3& pos, btScalar rad) +{ + btVector3* pBuf = (btVector3*)(m_hShapeBuffer + m_firstFreeShapeBufferOffset); + *pBuf = pos; + pBuf->setW(rad); + m_firstFreeShapeBufferOffset += sizeof(btVector3); +} + + + +void btGpuDemoDynamicsWorld::addMultiShereObject(int numSpheres, int objIndex) +{ + m_hShapeIds[objIndex].x = m_firstFreeShapeBufferOffset; + m_hShapeIds[objIndex].y = numSpheres; + return; +} + + diff --git a/Demos/Gpu2dDemo/btGpuDemoDynamicsWorld.h b/Demos/Gpu2dDemo/btGpuDemoDynamicsWorld.h new file mode 100644 index 0000000..bc820c4 --- /dev/null +++ b/Demos/Gpu2dDemo/btGpuDemoDynamicsWorld.h @@ -0,0 +1,291 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_CUDA_DEMO_DYNAMICS_WORLD_H +#define BT_CUDA_DEMO_DYNAMICS_WORLD_H + + + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h" + + +//#define BT_USE_CUDA 1 +// To enable CUDA : +// 1. Uncomment //#define BT_USE_CUDA 1 +// 2. Build and add libbulletcuda (Extras/CUDA) to project +// 3. Add $(CUDA_LIB_PATH) and cudart.lib to linker properties + +#ifdef BT_USE_CUDA +// #include "btCudaDemoPairCache.h" +// #include + #include "BulletMultiThreaded/btGpuDefines.h" + #undef BT_GPU_PREF + #define BT_GPU_PREF(func) btCuda_##func + #include "BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#else + #include "BulletMultiThreaded/btGpuDefines.h" + #include "../../src/BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#endif + +#undef BT_GPU_PREF + + +#include "btGpuDemo2dSharedTypes.h" + + + +#define CUDA_DEMO_DYNAMICS_WORLD_MAX_BATCHES 20 + +#define CUDA_DEMO_DYNAMICS_WORLD_MAX_OBJS 1024 +#define CUDA_DEMO_DYNAMICS_WORLD_MAX_NEIGHBORS 24 + +#define CUDA_DEMO_DYNAMICS_WORLD_MAX_SPHERES_PER_OBJ 8 + +class btGpuDemoDynamicsWorld; + +extern btGpuDemoDynamicsWorld* gpCudaDemoDynamicsWorld; // to access world members from pair cache + +class btGpuDemoDynamicsWorld : public btDiscreteDynamicsWorld +{ +protected: + int m_maxObjs; + int m_maxNeighbors; + + int m_numObj; + int m_numSimStep; + bool m_useCPUSolver; + bool m_useBulletNarrowphase; + + float4* m_hPos; + float* m_hRot; + float4* m_hVel; + float* m_hAngVel; + + float* m_hInvMass; + float* m_dInvMass; + bool m_copyMassDataToGPU; + +#ifdef BT_USE_CUDA + float4* m_dPos; + float* m_dRot; + float4* m_dVel; + float* m_dAngVel; + float4* m_dpPos; + float* m_dpRot; + float4* m_dpVel; + float* m_dpAngVel; + + float4* m_dcPos; + float* m_dcRot; + float4* m_dcVel; + float* m_dcAngVel; +#endif //BT_USE_CUDA + + + btOverlappingPairCache* m_pairCache; + int* m_hConstraintBuffer; + int* m_hConstraintCounter; + int m_maxBatches; + int m_numBatches; + int m_totalNumConstraints; + int2* m_hIds; + int* m_hBatchIds; + + int m_maxVtxPerObj; + + int2* m_dIds; + int* m_dBatchIds; + + float* m_dLambdaDtBox; + float4* m_dContact; // 8 floats : pos.x, pos.y, pos.z, penetration, norm.x, norm.y, norm.z, reserved + + // ------------- these are only needed for CPU version and for debugging + float* m_hLambdaDtBox; + float4* m_hContact; // 8 floats : pos.x, pos.y, pos.z, penetration, norm.x, norm.y, norm.z, reserved + // ------------- + + btScalar m_objRad; + btVector3 m_worldMin; + btVector3 m_worldMax; + + + int* m_hConstraintUsed; + + + // shape buffer + int m_maxShapeBufferSize; + int m_firstFreeShapeBufferOffset; + char* m_hShapeBuffer; // (pos.x, pos.y, pos.z, radius) + char* m_dShapeBuffer;//pointer in device memory + int2* m_hShapeIds; + int2* m_dShapeIds; + bool m_copyShapeDataToGPU; + void initShapeBuffer(int maxShapeBufferSize); + void freeShapeBuffer(); + void sendShapeDataToGpu(); + + + int m_numNonContactConstraints; + void grabNonContactConstraintData(); + void grabP2PConstraintData(btPoint2PointConstraint* ct); + +public: + int m_numInBatches[CUDA_DEMO_DYNAMICS_WORLD_MAX_BATCHES]; + void addSphere(btVector3& pos, btScalar rad); + void addMultiShereObject(int numSpheres, int objIndex); + + + btGpuDemoDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration, + int maxObjs = CUDA_DEMO_DYNAMICS_WORLD_MAX_OBJS, int maxNeighbors = CUDA_DEMO_DYNAMICS_WORLD_MAX_NEIGHBORS) + : btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration) + { + m_maxObjs = maxObjs; + m_maxNeighbors = maxNeighbors; + m_useCPUSolver = false; + m_pairCache = pairCache->getOverlappingPairCache(); + int sz = m_maxObjs * m_maxNeighbors; + m_hConstraintBuffer = new int[sz]; + m_hConstraintCounter = new int[m_maxObjs]; + m_maxBatches = CUDA_DEMO_DYNAMICS_WORLD_MAX_BATCHES; + m_hIds = new int2[sz]; + m_hBatchIds = new int[sz]; + for(int i = 0; i < sz; i++) + { + m_hBatchIds[i] = -1; + } + m_hPos = new float4[m_maxObjs]; + m_hVel = new float4[m_maxObjs]; + m_hRot = new float[m_maxObjs]; + m_hAngVel = new float[m_maxObjs]; + + m_hInvMass = new float[m_maxObjs]; + + m_maxVtxPerObj = 8; + +#ifdef BT_USE_CUDA + btCuda_allocateArray((void**)&m_dPos, sizeof(float4) * m_maxObjs); + btCuda_allocateArray((void**)&m_dRot, sizeof(float) * m_maxObjs); + btCuda_allocateArray((void**)&m_dVel, sizeof(float4) * m_maxObjs); + btCuda_allocateArray((void**)&m_dAngVel, sizeof(float) * m_maxObjs); + btCuda_allocateArray((void**)&m_dpPos, sizeof(float4) * m_maxObjs); + btCuda_allocateArray((void**)&m_dpRot, sizeof(float) * m_maxObjs); + btCuda_allocateArray((void**)&m_dpVel, sizeof(float4) * m_maxObjs); + btCuda_allocateArray((void**)&m_dpAngVel, sizeof(float) * m_maxObjs); + + btCuda_allocateArray((void**)&m_dInvMass, sizeof(float) * m_maxObjs); + + btCuda_allocateArray((void**)&m_dIds, sizeof(int2) * sz); + btCuda_allocateArray((void**)&m_dBatchIds, sizeof(int) * sz); + + btCuda_allocateArray((void**)&m_dLambdaDtBox, sizeof(float) * sz * m_maxVtxPerObj); + btCuda_allocateArray((void**)&m_dContact, sizeof(float) * sz * m_maxVtxPerObj * 8); +// btCuda_allocateArray((void**)&m_dPositionConstraint, sizeof(float) * sz * m_maxVtxPerObj * 2); +// btCuda_allocateArray((void**)&m_dNormal, sizeof(float3) * sz * m_maxVtxPerObj * 2); +#endif //BT_USE_CUDA + + + m_hLambdaDtBox = new float[sz * m_maxVtxPerObj]; + m_hContact = new float4[sz * m_maxVtxPerObj * 2]; +// m_hPositionConstraint = new float[sz * m_maxVtxPerObj * 2]; +// m_hNormal = new float3[sz * m_maxVtxPerObj * 2]; + + m_numSimStep = 0; + + m_objRad = 1.0f; + + m_hConstraintUsed = new int[sz]; + + + gpCudaDemoDynamicsWorld = this; + m_totalNumConstraints = 0; + + initShapeBuffer(m_maxObjs * CUDA_DEMO_DYNAMICS_WORLD_MAX_SPHERES_PER_OBJ * sizeof(float) * 4); + + m_copyMassDataToGPU = true; + + } + virtual ~btGpuDemoDynamicsWorld() + { + delete [] m_hConstraintBuffer; + delete [] m_hConstraintCounter; + delete [] m_hIds; + delete [] m_hBatchIds; + delete [] m_hPos; + delete [] m_hRot; + delete [] m_hVel; + delete [] m_hAngVel; + delete [] m_hInvMass; +#ifdef BT_USE_CUDA + btCuda_freeArray(m_dPos); + btCuda_freeArray(m_dRot); + btCuda_freeArray(m_dVel); + btCuda_freeArray(m_dAngVel); + btCuda_freeArray(m_dpPos); + btCuda_freeArray(m_dpRot); + btCuda_freeArray(m_dpVel); + btCuda_freeArray(m_dpAngVel); + btCuda_freeArray(m_dInvMass); + + btCuda_freeArray(m_dIds); + btCuda_freeArray(m_dBatchIds); + btCuda_freeArray(m_dLambdaDtBox); + btCuda_freeArray(m_dContact); +#endif //BT_USE_CUDA + + delete [] m_hLambdaDtBox; + delete [] m_hContact; + delete [] m_hConstraintUsed; + + gpCudaDemoDynamicsWorld = NULL; + + freeShapeBuffer(); + } + + virtual void calculateSimulationIslands() + { + } + virtual void solveConstraints(btContactSolverInfo& solverInfo); + void solveConstraints2(btContactSolverInfo& solverInfo); + void solveConstraintsCPU2(btContactSolverInfo& solverInfo); + + void debugDrawConstraints(int selectedBatch, const float* pColorTab); + + void setObjRad(btScalar rad) { m_objRad = rad; } + void setWorldMin(const btVector3& worldMin) { m_worldMin = worldMin; } + void setWorldMax(const btVector3& worldMax) { m_worldMax = worldMax; } + + void grabData(); + void grabContactData(); + void copyDataToGPU(); + void setConstraintData(btCudaPartProps& partProps); + void copyDataFromGPU(); + void writebackData(); + void setUseCPUSolver(bool useCPU) { m_useCPUSolver = useCPU; } + void setUseBulletNarrowphase(bool useBulletNarrowphase) {m_useBulletNarrowphase = useBulletNarrowphase; } + + void createBatches2(); + + int2* getIdsPtr() { return m_hIds; } + void setTotalNumConstraints(int totalNumConstraints) { m_totalNumConstraints = totalNumConstraints; } + int getTotalNumConstraints() { return m_totalNumConstraints; } + +}; + + +#endif //BT_CUDA_DEMO_DYNAMICS_WORLD_H diff --git a/Demos/Gpu2dDemo/btGpuDemoPairCache.cpp b/Demos/Gpu2dDemo/btGpuDemoPairCache.cpp new file mode 100644 index 0000000..3fa0fa1 --- /dev/null +++ b/Demos/Gpu2dDemo/btGpuDemoPairCache.cpp @@ -0,0 +1,76 @@ +/* +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 "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" + +#include "btGpuDemoPairCache.h" + +#include "btGpuDemoDynamicsWorld.h" + + + +void btGpuDemoPairCache::processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher) +{ + int sz = m_maxProxies * m_maxNeighbors; + int numContConstraints = 0; + int2* pIds = gpCudaDemoDynamicsWorld->getIdsPtr(); + for(int idx = 0; idx < sz; idx++) + { + int neigh = m_hNeighbors[idx]; + if(neigh >= 0) + { + int i=idx / m_maxNeighbors; + int j=idx % m_maxNeighbors; + pIds[numContConstraints].x = i; + pIds[numContConstraints].y = m_hNeighbors[i * m_maxNeighbors + j]; + numContConstraints++; + } + } + gpCudaDemoDynamicsWorld->setTotalNumConstraints(numContConstraints); +} + + + +// this will be called for each overlapping pair if collision detection uses pairCache other than btGpuDemoPairCache +// IMPORTANT : m_numConstraints in gpCudaDemoDynamicsWorld is set to 0 at start of simulation step +// IMPORTANT : companionIds for all objects should be properly set at start of simulation step +void cudaDemoNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo) +{ + btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; + if (dispatcher.needsCollision(colObj0,colObj1)) + { + // int id0 = collisionPair.m_pProxy0->m_uniqueId - 2; + // int id1 = collisionPair.m_pProxy1->m_uniqueId - 2; + // cannot use m_uniqueId : it may be altered by broadphase code + // so we'll use companionIds set on the initialization stage + unsigned int id0 = colObj0->getCompanionId(); + unsigned int id1 = colObj1->getCompanionId(); + if(id0 > id1) + { + int tmp = id0; id0 = id1; id1 = tmp; + } + int totalNumConstraints = gpCudaDemoDynamicsWorld->getTotalNumConstraints(); + int2* pIds = gpCudaDemoDynamicsWorld->getIdsPtr(); + pIds += totalNumConstraints; + pIds->x = id0; + pIds->y = id1; + totalNumConstraints++; + gpCudaDemoDynamicsWorld->setTotalNumConstraints(totalNumConstraints); + } +} // cudaDemoNearCallback() + diff --git a/Demos/Gpu2dDemo/btGpuDemoPairCache.h b/Demos/Gpu2dDemo/btGpuDemoPairCache.h new file mode 100644 index 0000000..6b9503b --- /dev/null +++ b/Demos/Gpu2dDemo/btGpuDemoPairCache.h @@ -0,0 +1,136 @@ +/* +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 CUDA_DEMO_PAIR_CACHE_H +#define CUDA_DEMO_PAIR_CACHE_H + + +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "LinearMath/btAlignedObjectArray.h" + +class btGpuDemoPairCache : public btNullPairCache +{ +public: + int m_maxProxies; + int m_maxNeighbors; + int* m_hNeighbors; + int m_numPairs; + int m_numSmallProxies; + int m_maxSmallProxies; + + btGpuDemoPairCache(int maxProxies, int maxNeighbors, int maxSmallProxies) + { + m_maxProxies = maxProxies; + m_maxNeighbors = maxNeighbors; + m_maxSmallProxies = maxSmallProxies; + int sz = maxProxies * maxNeighbors; + m_hNeighbors = new int [sz]; + reset(); + } + + ~btGpuDemoPairCache() + { + delete [] m_hNeighbors; + } + + void reset(void) + { + int sz = m_maxProxies * m_maxNeighbors; + for(int i = 0; i < sz; i++) + { + m_hNeighbors[i] = -1; + } + m_numPairs = 0; + } + + virtual int getNumOverlappingPairs() const + { + return m_numPairs; + //return 0; // to skip btSimulationIslandManager::findUnions() + } + + virtual void processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher); + + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) + { + int id0 = proxy0->m_uniqueId - 2; + int id1 = proxy1->m_uniqueId - 2; + if(id0 >= m_maxSmallProxies) + { + id0 -= m_maxSmallProxies - m_numSmallProxies; + } + if(id1 >= m_maxSmallProxies) + { + id1 -= m_maxSmallProxies - m_numSmallProxies; + } + if(id0 > id1) + { + int tmp = id0; id0 = id1; id1 = tmp; + } + int offs = id0 * m_maxNeighbors; + int i; + for(i = 0; i < m_maxNeighbors; i++) + { + if(m_hNeighbors[offs + i] < 0) + { + m_hNeighbors[offs + i] = id1; + m_numPairs++; + break; + } + } + // btAssert(i < m_maxNeighbors); + return 0; + } + + virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* /*dispatcher*/) + { + int id0 = proxy0->m_uniqueId - 2; + int id1 = proxy1->m_uniqueId - 2; + if(id0 >= m_maxSmallProxies) + { + id0 -= m_maxSmallProxies - m_numSmallProxies; + } + if(id1 >= m_maxSmallProxies) + { + id1 -= m_maxSmallProxies - m_numSmallProxies; + } + if(id0 > id1) + { + int tmp = id0; id0 = id1; id1 = tmp; + } + int offs = id0 * m_maxNeighbors; + int i; + for(i = 0; i < m_maxNeighbors; i++) + { + if(m_hNeighbors[offs + i] == id1) + { + m_hNeighbors[offs + i] = -1; + m_numPairs--; + break; + } + } +// btAssert(i < m_maxNeighbors); + return 0; + } +}; + +extern void cudaDemoNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo); + +#endif //CUDA_DEMO_PAIR_CACHE_H + + diff --git a/Demos/Gpu2dDemo/main.cpp b/Demos/Gpu2dDemo/main.cpp new file mode 100644 index 0000000..70f8a90 --- /dev/null +++ b/Demos/Gpu2dDemo/main.cpp @@ -0,0 +1,62 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "BasicDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" + +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btHashMap.h" + +class OurValue + { + int m_uid; + + public: + OurValue(const btVector3& initialPos) + :m_position(initialPos) + { + static int gUid=0; + m_uid=gUid; + gUid++; + } + + btVector3 m_position; + int getUid() const + { + return m_uid; + } + }; + +GLDebugDrawer gDebugDrawer; + +int main(int argc,char** argv) +{ + + + BasicDemo ccdDemo; + ccdDemo.initPhysics(); + ccdDemo.getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + +#ifdef CHECK_MEMORY_LEAKS + ccdDemo.exitPhysics(); +#else + return glutmain(argc, argv,640,480,"Bullet Physics Demo. http://bulletphysics.com",&ccdDemo); +#endif + + //default glut doesn't return from mainloop + return 0; +} \ No newline at end of file diff --git a/Demos/Gpu2dDemo/oecakeLoader.cpp b/Demos/Gpu2dDemo/oecakeLoader.cpp new file mode 100644 index 0000000..3158dea --- /dev/null +++ b/Demos/Gpu2dDemo/oecakeLoader.cpp @@ -0,0 +1,264 @@ +#include "oecakeLoader.h" +#include //printf debugging +#include + + + + +btCompoundShape* shiftTransform(btCompoundShape* boxCompound,btScalar mass,btTransform& shift) +{ + btTransform principal; + btVector3 principalInertia; + btScalar* masses = new btScalar[boxCompound->getNumChildShapes()]; + for (int j=0;jgetNumChildShapes();j++) + { + //evenly distribute mass + masses[j]=mass/boxCompound->getNumChildShapes(); + } + + + boxCompound->calculatePrincipalAxisTransform(masses,principal,principalInertia); + + + ///create a new compound with world transform/center of mass properly aligned with the principal axis + + ///non-recursive compound shapes perform better + //#define USE_RECURSIVE_COMPOUND 1 +#ifdef USE_RECURSIVE_COMPOUND + + btCompoundShape* newCompound = new btCompoundShape(); + newCompound->addChildShape(principal.inverse(),boxCompound); + m_collisionShapes.push_back(newCompound); + + btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,newCompound,principalInertia); + +#else +#ifdef CHANGE_COMPOUND_INPLACE + for (int i=0;igetNumChildShapes();i++) + { + btTransform newChildTransform = principal.inverse()*boxCompound->getChildTransform(i); + ///updateChildTransform is really slow, because it re-calculates the AABB each time. todo: add option to disable this update + boxCompound->updateChildTransform(i,newChildTransform); + } + if (isDynamic) + boxCompound->calculateLocalInertia(mass,localInertia); + btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,boxCompound,localInertia); +#else + ///creation is faster using a new compound to store the shifted children + btCompoundShape* newBoxCompound = new btCompoundShape(); + for (int i=0;igetNumChildShapes();i++) + { + btTransform newChildTransform = principal.inverse()*boxCompound->getChildTransform(i); + ///updateChildTransform is really slow, because it re-calculates the AABB each time. todo: add option to disable this update + newBoxCompound->addChildShape(newChildTransform,boxCompound->getChildShape(i)); + } + + + +#endif + +#endif//USE_RECURSIVE_COMPOUND + + shift = principal; + return newBoxCompound; +} + + +void BasicOECakeReader::addParticle(int materialType, int pIndex, int pColor, float pPosX, float pPosY,float radius) +{ + //determine that we have a new shape? + if (m_particlePositions.size()) + { + if ( + (materialType != m_materialType) + || + (pIndex != m_particleObjectIndex) + ) + { + convertParticleGroup(); + } + } + + + //add to array + m_materialType = materialType; + m_particleObjectIndex = pIndex; + m_particleColor = pColor; + m_particlePositions.push_back(btVector3(pPosX,pPosY,0.)); + m_particleRadii.push_back(radius); + +} + +void BasicOECakeReader::convertParticleGroup() +{ + printf("found a particle group of %d particles\n",m_particlePositions.size()); + if (m_particlePositions.size()>0) + { + addNewCollisionShape(m_particlePositions.size(),&m_particlePositions[0],&m_particleRadii[0],m_materialType,m_particleObjectIndex,m_particleColor); + m_particlePositions.clear(); + m_particleRadii.clear(); + } +} + +void BasicOECakeReader::addNewCollisionShape(int numParticles, btVector3* particlePositions, btScalar* radii, int materialType, int objectIndex,int color ) +{ + //create Bullet stuff + btCompoundShape* colShape = 0; + btScalar mass; + + bool addConstraint = false; + + + if (materialType&0x800000) + { + addConstraint = true; + } + + if ((materialType & 0x20000) ||(materialType & 0x12)) + { + mass = 1.f; + } else + { + mass = 0.f; + } + btTransform startTransform; + startTransform.setIdentity(); + + int numCurSpheres = 0; + + { + + + btTransform localTrans; + localTrans.setIdentity(); + + //static + btCompoundShape* compound = new btCompoundShape(); + + for (int i=0;iaddChildShape(localTrans,particle); + if (mass==0.f && (numCurSpheres>=7)) + { + createBodyForCompoundShape(compound,false,startTransform,mass); + compound = new btCompoundShape(); + numCurSpheres = 0; + } + } + if (mass) + { + //shift the center of mass, based on all spheres + btCompoundShape* newCompound = shiftTransform(compound,mass,startTransform); + colShape = newCompound; + } else + { + //use unmodified + colShape = compound; + } + } + + btDefaultMotionState* myMotionState = 0; + + if (colShape && numCurSpheres) + { + createBodyForCompoundShape(colShape,addConstraint,startTransform,mass); + } +} + + + +int BasicOECakeReader::processLine(char * buffer, int size) +{ + int numBytesRead = 0; + + if (buffer[0] == 'p') + { + int materialType; + int particleObjectIndex; + int particleColor; + int dummy1; + float particlePosX; + float particlePosY; + + if (sscanf (buffer, "p %x %x %x %x %f %f", &materialType,&particleObjectIndex,&dummy1, &particleColor, &particlePosX, &particlePosY) == 6) + { + addParticle(materialType,particleObjectIndex,particleColor,particlePosX,particlePosY); + } + else + { + printf("ERROR: invalid line (%s)\n", buffer); + } + } + + while (*buffer != '\n' && size != 0) + { + buffer++; + numBytesRead++; + } + + + if (buffer[0]==0x0a) + { + buffer++; + numBytesRead++; + } + + + return numBytesRead; +} + +bool BasicOECakeReader::processFile(char * fileName) +{ + FILE * fp = fopen(fileName, "rb"); + if (fp == NULL) + { + printf("ERROR: file(%s) not found", fileName); + return false; + } + + int size; + if (fseek(fp, 0, SEEK_END) || (size = ftell(fp)) == EOF || fseek(fp, 0, SEEK_SET)) + { + printf("ERROR: problem reading file(%s)", fileName); + fclose(fp); + return false; + } + else + { + rewind (fp); + char * buffer = (char *) malloc(size+1); + memset(buffer,0,size); + + if (fread(buffer,1,size,fp) != size) + { + printf("Error reading file %s!\n",fileName); + fclose(fp); + return false; + } + + int totalBytesRead = 0; + + while(totalBytesRead m_particlePositions; + btAlignedObjectArray m_particleRadii; + + void addParticle(int materialType, int pIndex, int pColor, float pPosX, float pPosY, float radius=1); + + virtual void addNewCollisionShape(int numParticles, btVector3* particlePositions, btScalar* radii, int materialType, int objectIndex,int color ); + + int processLine(char * buffer, int size); + + void convertParticleGroup(); + +public: + + BasicOECakeReader() + { + } + + bool processFile(char * fileName); + + virtual void createBodyForCompoundShape(btCompoundShape* compound,bool addConstraint,const btTransform& worldTransform, btScalar mass) = 0; + +}; +#endif //OE_CAKE_LOADER_H diff --git a/Demos/Gpu3dDemo/BasicDemo3d.cpp b/Demos/Gpu3dDemo/BasicDemo3d.cpp new file mode 100644 index 0000000..5e99703 --- /dev/null +++ b/Demos/Gpu3dDemo/BasicDemo3d.cpp @@ -0,0 +1,852 @@ +/* +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 "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" +#include "BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h" + +#include "btGpuDemoDynamicsWorld3D.h" + +#include "BulletMultiThreaded/SpuGatheringCollisionDispatcher.h" +#include "BulletMultiThreaded/Win32ThreadSupport.h" +#include "GLDebugFont.h" +extern int gSkippedCol; +extern int gProcessedCol; + + + +#define SPEC_TEST 0 + +#ifdef _DEBUG + #define LARGE_DEMO 1 +// #define LARGE_DEMO 1 +#else + #define LARGE_DEMO 1 +#endif + +#if LARGE_DEMO + ///create 512 (8x8x8) dynamic object +// #define ARRAY_SIZE_X 100 +// #define ARRAY_SIZE_Y 100 +// #define ARRAY_SIZE_Z 1 +// #define ARRAY_SIZE_X 228 +// #define ARRAY_SIZE_Y 228 +// #define ARRAY_SIZE_X 30 +// #define ARRAY_SIZE_Y 100 + +#define ARRAY_SIZE_X 8 +#define ARRAY_SIZE_Y 47 +#define ARRAY_SIZE_Z 8 +#else + ///create 125 (5x5x5) dynamic object + #define ARRAY_SIZE_X 45 + #define ARRAY_SIZE_Y 45 +// #define ARRAY_SIZE_Z 5 + #define ARRAY_SIZE_Z 1 +#endif + + +//maximum number of objects (and allow user to shoot additional boxes) +#define NUM_SMALL_PROXIES (ARRAY_SIZE_X*ARRAY_SIZE_Y*ARRAY_SIZE_Z) +#define MAX_PROXIES (NUM_SMALL_PROXIES + 1024) +#define MAX_LARGE_PROXIES 10 +#define MAX_SMALL_PROXIES (MAX_PROXIES - MAX_LARGE_PROXIES) + +///scaling of the objects (0.1 = 20 centimeter boxes ) +//#define SCALING 0.1 +#define SCALING 1 +#define START_POS_X 0 +#define START_POS_Y 5 +#define START_POS_Z 0 + +#include "BasicDemo3d.h" +#include "GlutStuff.h" +///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files. +#include "btBulletDynamicsCommon.h" +#include //printf debugging + +#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" + +#include "../Extras/CUDA/btCudaBroadphase.h" + +btScalar gTimeStep = btScalar(1./60.); + +bool gbDrawBatches = false; +int gSelectedBatch = CUDA_DEMO_DYNAMICS_WORLD3D_MAX_BATCHES; +bool gUseCPUSolver = false; +bool gUseSolver2 = true; +bool gDrawWire = false; +bool gUseCudaMotIntegr = true; + + +void BasicDemo3D::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //simple dynamics world doesn't handle fixed-time-stepping + float ms = getDeltaTimeMicroseconds(); + + ///step the simulation + if (m_dynamicsWorld) + { +// btCudaDemoPairCache* pc = (btCudaDemoPairCache*)m_dynamicsWorld->getPairCache(); +// pc->m_numSmallProxies = m_dynamicsWorld->getNumCollisionObjects(); // - 1; // exclude floor + m_dynamicsWorld->stepSimulation(gTimeStep,0);//ms / 1000000.f); + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + } + renderme(); + + ms = getDeltaTimeMicroseconds(); + + glFlush(); + + glutSwapBuffers(); + +} + + + +void BasicDemo3D::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + //optional but useful: debug drawing to detect problems + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + glFlush(); + glutSwapBuffers(); +} + +#define NUM_SOLVERS 11 +static btConstraintSolver* sConstraintSolvers[NUM_SOLVERS]; +static int sCurrSolverIndex = 9; +static char* sConstraintSolverNames[NUM_SOLVERS] = +{ + "btSequentialImpulseConstraintSolver", + "btParallelBatchConstraintSolver", + "btCudaConstraintSolver", + "btParallelBatchConstraintSolver2", + "btParallelBatchConstraintSolver3", + "btCudaConstraintSolver3", + "btParallelBatchConstraintSolver4", + "btCudaConstraintSolver4", + "btParallelBatchConstraintSolver5", + "btParallelBatchConstraintSolver6", + "btCudaConstraintSolver6", +}; + +//btVector3 gWorldMin(-228,-228,-32); +//btVector3 gWorldMin(-228,0,-32); +//btVector3 gWorldMax(228,228,32); + +//btVector3 gWorldMin(-150,-228,-32); +//btVector3 gWorldMax(150,228,32); + +#define POS_OFFS_X (ARRAY_SIZE_X * SCALING + 50) +#define POS_OFFS_Y (ARRAY_SIZE_Y * SCALING ) +#define POS_OFFS_Z (ARRAY_SIZE_Z * SCALING + 5) + +btVector3 gWorldMin(-POS_OFFS_X, -ARRAY_SIZE_Y*SCALING, -80-POS_OFFS_Z); +btVector3 gWorldMax( POS_OFFS_X, POS_OFFS_Y, 80+POS_OFFS_Z); + +//btCudaDemoPairCache* gPairCache; +btHashedOverlappingPairCache* gPairCache; + +void BasicDemo3D::initPhysics() +{ + setTexturing(true); + setShadows(false); + +// setCameraDistance(btScalar(SCALING*50.)); +#if LARGE_DEMO + setCameraDistance(btScalar(SCALING*50.)); +#else + setCameraDistance(btScalar(SCALING*20.)); +#endif + + m_cameraTargetPosition.setValue(START_POS_X, -START_POS_Y-20, START_POS_Z); + m_azi = btScalar(0.f); + m_ele = btScalar(0.f); + + ///collision configuration contains default setup for memory, collision setup + + btDefaultCollisionConstructionInfo dci; + dci.m_defaultMaxPersistentManifoldPoolSize=100000; + dci.m_defaultMaxCollisionAlgorithmPoolSize=100000; + dci.m_customCollisionAlgorithmMaxElementSize = sizeof(SpuContactManifoldCollisionAlgorithm); + + + ///SpuContactManifoldCollisionAlgorithm is larger than any of the other collision algorithms +//@@ dci.m_customMaxCollisionAlgorithmSize = sizeof(SpuContactManifoldCollisionAlgorithm); + + m_collisionConfiguration = new btDefaultCollisionConfiguration(dci); + + ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) + //m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); +#ifndef WIN32 + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); +#else + unsigned int maxNumOutstandingTasks =4; + //createCollisionLocalStoreMemory(); + //processSolverTask + Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("narrowphase_multi",processCollisionTask,createCollisionLocalStoreMemory,maxNumOutstandingTasks); + class btThreadSupportInterface* threadInterface = new Win32ThreadSupport(threadConstructionInfo); + m_dispatcher = new SpuGatheringCollisionDispatcher(threadInterface,maxNumOutstandingTasks,m_collisionConfiguration); +#endif //SINGLE_THREADED_NARROWPHASE + + +//## m_dispatcher->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE,BOX_SHAPE_PROXYTYPE,new btEmptyAlgorithm::CreateFunc); +//## m_dispatcher->registerCollisionCreateFunc(CUSTOM_CONVEX_SHAPE_TYPE,CUSTOM_CONVEX_SHAPE_TYPE,new btBox2dBox2dCollisionAlgorithm::CreateFunc); + +// m_broadphase = new btDbvtBroadphase(); + + +//## gPairCache = new (btAlignedAlloc(sizeof(btCudaDemoPairCache),16)) btCudaDemoPairCache(MAX_PROXIES, 24, MAX_SMALL_PROXIES); +// gPairCache = NULL; + gPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); + + //m_broadphase = new btSimpleBroadphase(16384, gPairCache); + +/* +btCudaBroadphase::btCudaBroadphase( btOverlappingPairCache* overlappingPairCache, + const btVector3& worldAabbMin,const btVector3& worldAabbMax, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + int maxBodiesPerCell, + btScalar cellFactorAABB) +*/ +// btVector3 numOfCells = (gWorldMax - gWorldMin) / (2. * SCALING * 0.7); + btVector3 numOfCells = (gWorldMax - gWorldMin) / (2. * SCALING); + int numOfCellsX = (int)numOfCells[0]; + int numOfCellsY = (int)numOfCells[1]; + int numOfCellsZ = (int)numOfCells[2]; + +// m_broadphase = new bt3DGridBroadphase(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,8,8,1./1.5); +//#define USE_CUDA_BROADPHASE 1 +#ifdef USE_CUDA_BROADPHASE + m_broadphase = new btCudaBroadphase(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,20,18,8,1./1.5); +#else + +#if DBVT + btDbvtBroadphase* dbvt = new btDbvtBroadphase(gPairCache); + m_broadphase = dbvt; + dbvt->m_deferedcollide=false; + dbvt->m_prediction = 0.f; +#else + m_broadphase = new btAxisSweep3(gWorldMin,gWorldMax,32000,gPairCache,true);//(btDbvtBroadphase(gPairCache); +#endif //DBVT + +#endif + + + // create solvers for tests + ///the default constraint solver + sConstraintSolvers[0] = new btSequentialImpulseConstraintSolver(); +/* + sConstraintSolvers[1] = new btParallelBatchConstraintSolver(); + sConstraintSolvers[2] = new btCudaConstraintSolver(); + sConstraintSolvers[3] = new btParallelBatchConstraintSolver2(); + sConstraintSolvers[4] = new btParallelBatchConstraintSolver3(); + sConstraintSolvers[5] = new btCudaConstraintSolver3(); + sConstraintSolvers[6] = new btParallelBatchConstraintSolver4(); + sConstraintSolvers[7] = new btCudaConstraintSolver4(); + sConstraintSolvers[8] = new btParallelBatchConstraintSolver5(); + sConstraintSolvers[9] = new btParallelBatchConstraintSolver6(); + sConstraintSolvers[10] = new btCudaConstraintSolver6(); +*/ + sCurrSolverIndex = 0; + m_solver = sConstraintSolvers[sCurrSolverIndex]; + printf("\nUsing %s\n", sConstraintSolverNames[sCurrSolverIndex]); + +// sCudaMotionInterface = new btCudaMotionInterface(MAX_PROXIES); +// m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration, sCudaMotionInterface); +// m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); +//## btCudaDemoDynamicsWorld* pDdw = new btCudaDemoDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + btCudaDemoDynamicsWorld3D* pDdw = new btCudaDemoDynamicsWorld3D(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + m_dynamicsWorld = pDdw; + pDdw->getDispatchInfo().m_enableSPU=true; + pDdw->getSimulationIslandManager()->setSplitIslands(sCurrSolverIndex == 0); + pDdw->setObjRad(SCALING); + pDdw->setWorldMin(gWorldMin); + pDdw->setWorldMax(gWorldMax); +#ifdef BT_USE_CUDA + gUseCPUSolver = false; +#else + gUseCPUSolver = true; +#endif + pDdw->setUseCPUSolver(gUseCPUSolver); +// pDdw->setUseSolver2(gUseSolver2); + +// m_dynamicsWorld->setGravity(btVector3(0,0,0)); + m_dynamicsWorld->setGravity(btVector3(0.f,-10.f,0.f)); + m_dynamicsWorld->getSolverInfo().m_numIterations = 4; + + + { + //create a few dynamic rigidbodies + // Re-using the same collision is better for memory usage and performance + + + //btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,0.1));//SCALING*1)); +//## btCollisionShape* colShape = new btBox2dShape(btVector3(SCALING*.7,SCALING*.7,0.1));//SCALING*1)); + btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*.7,SCALING*.7, SCALING*.7)); + + //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); + m_collisionShapes.push_back(colShape); + + /// Create Dynamic Objects + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + + //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) + colShape->calculateLocalInertia(mass,localInertia); +#if (!SPEC_TEST) + float start_x = START_POS_X - ARRAY_SIZE_X * SCALING; + float start_y = START_POS_Y - ARRAY_SIZE_Y * SCALING; + float start_z = START_POS_Z - ARRAY_SIZE_Z * SCALING; + + for (int k=0;kaddRigidBody(body); + } + } + } +#else + // narrowphase test - 2 bodies at the same position + float start_x = START_POS_X; + float start_y = START_POS_Y; + float start_z = START_POS_Z; +// startTransform.setOrigin(SCALING*btVector3(start_x,start_y-14.f,start_z)); + startTransform.setOrigin(SCALING*btVector3(start_x,start_y-11.f,start_z)); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape,localInertia); + rbInfo.m_startWorldTransform=startTransform; + btRigidBody* body = new btRigidBody(rbInfo); + m_dynamicsWorld->addRigidBody(body); +// startTransform.setOrigin(SCALING*btVector3(start_x+1.2f,start_y+1.4f-14.f,start_z)); + startTransform.setOrigin(SCALING*btVector3(start_x,start_y + 1.5f -11.f, start_z)); + rbInfo.m_startWorldTransform=startTransform; + body = new btRigidBody(rbInfo); + m_dynamicsWorld->addRigidBody(body); +#endif + } + + +#if 0 + ///create a few basic rigid bodies +// btCollisionShape* groundShape = new btBox2dShape(btVector3(btScalar(50.),btScalar(1.),btScalar(50.))); +// btCollisionShape* groundShape = new btBox2dShape(btVector3(btScalar(228.),btScalar(1.),btScalar(228.))); +// btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(228.),btScalar(1.),btScalar(228.))); +// btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); +// btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); + btCollisionShape* groundShape = new btBoxShape(btVector3(POS_OFFS_X, btScalar(1.), POS_OFFS_Z)); + + m_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0, gWorldMin[1], 0)); + +// groundTransform.setOrigin(btVector3(0,-5,0)); +// groundTransform.setOrigin(btVector3(0,-50,0)); + + //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here: + { + btScalar mass(0.); + + //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) + groundShape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + //add the body to the dynamics world + m_dynamicsWorld->addRigidBody(body); + } +#endif + //clientResetScene(); +} + +void BasicDemo3D::clientResetScene() +{ + DemoApplication::clientResetScene(); + btCudaDemoDynamicsWorld3D* pDdw = (btCudaDemoDynamicsWorld3D*)m_dynamicsWorld; + pDdw->resetScene(); +#if SPEC_TEST + { + float start_x = START_POS_X; + float start_y = START_POS_Y; + float start_z = START_POS_Z; + int numObjects = m_dynamicsWorld->getNumCollisionObjects(); + btCollisionObjectArray& collisionObjects = m_dynamicsWorld->getCollisionObjectArray(); + btTransform startTransform; + startTransform.setIdentity(); + for(int n = 0; n < numObjects; n++) + { + btCollisionObject* colObj = collisionObjects[n]; + btRigidBody* rb = btRigidBody::upcast(colObj); + if(!n) + { +// startTransform.setOrigin(SCALING*btVector3(start_x,start_y-14.f,start_z)); + startTransform.setOrigin(SCALING*btVector3(start_x,start_y-11.f,start_z)); + } + else + { +// startTransform.setOrigin(SCALING*btVector3(start_x+1.2f,start_y+1.4f-14.f,start_z)); + startTransform.setOrigin(SCALING*btVector3(start_x, start_y+1.5f-11.f,start_z)); + } + rb->setCenterOfMassTransform(startTransform); + } + return; + } +#endif +// we don't use motionState, so reset transforms here + int numObjects = m_dynamicsWorld->getNumCollisionObjects(); + btCollisionObjectArray& collisionObjects = m_dynamicsWorld->getCollisionObjectArray(); + + float start_x = START_POS_X - ARRAY_SIZE_X * SCALING; + float start_y = START_POS_Y - ARRAY_SIZE_Y * SCALING; + float start_z = START_POS_Z - ARRAY_SIZE_Z * SCALING; + btTransform startTransform; + startTransform.setIdentity(); + + for(int n = 0; n < numObjects; n++) + { + btCollisionObject* colObj = collisionObjects[n]; + btRigidBody* rb = btRigidBody::upcast(colObj); + int offs = ARRAY_SIZE_X * ARRAY_SIZE_Z; + int indx = n; + int ky = indx / offs; + indx -= ky * offs; + int kx = indx / ARRAY_SIZE_Z; + indx -= kx * ARRAY_SIZE_Z; + int kz = indx; + startTransform.setOrigin(SCALING*btVector3( + 2.0*SCALING*kx + start_x, + 2.0*SCALING*ky + start_y, + 2.0*SCALING*kz + start_z)); + rb->setCenterOfMassTransform(startTransform); + } +} + + + +void BasicDemo3D::exitPhysics() +{ + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;jgetSimulationIslandManager()->setSplitIslands(sCurrSolverIndex == 0); + pDdw->setConstraintSolver(sConstraintSolvers[sCurrSolverIndex]); + printf("\nUsing %s\n", sConstraintSolverNames[sCurrSolverIndex]); + } + break; +#endif + case 'c' : + { + gbDrawBatches = !gbDrawBatches; + break; + } + case 'b' : + { + gSelectedBatch++; + gSelectedBatch %= (CUDA_DEMO_DYNAMICS_WORLD3D_MAX_BATCHES + 1); + break; + } + case 'u' : + { +#ifdef BT_USE_CUDA + btCudaDemoDynamicsWorld3D* pDdw = (btCudaDemoDynamicsWorld3D*)m_dynamicsWorld; + gUseCPUSolver = !gUseCPUSolver; + pDdw->setUseCPUSolver(gUseCPUSolver); +#endif + break; + } + case 'w' : + { + gDrawWire = !gDrawWire; + setWireMode(gDrawWire); + break; + } + case 'm' : + { + btCudaDemoDynamicsWorld3D* pDdw = (btCudaDemoDynamicsWorld3D*)m_dynamicsWorld; + gUseCudaMotIntegr = !gUseCudaMotIntegr; + pDdw->setUseCudaMotIntegr(gUseCudaMotIntegr); + break; + } + + default : + { + DemoApplication::keyboardCallback(key, x, y); + } + break; + } + + if(key == ' ') + { + //gPairCache->reset(); + } +} + + +void BasicDemo3D::mouseFunc(int button, int state, int x, int y) +{ + if (state == GLUT_DOWN) { + m_mouseButtons |= 1<m_numInBatches[i]); + GLDebugDrawString(xOffs-80, yOffs,buf); + yOffs += 15.f; + } +} + + +void BasicDemo3D::renderme() +{ + updateCamera(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if(gDrawWire) + { + glColor3f(1.f, 1.f, 1.f); + glDisable(GL_LIGHTING); + setTexturing(false); + } + else + { + myinit(); + setTexturing(true); + } + + renderscene(0); + + if(gbDrawBatches) + { + ((btCudaDemoDynamicsWorld3D*)m_dynamicsWorld)->debugDrawConstraints(gSelectedBatch, cBatchColorTab); + } + glColor3f(0, 0, 0); + if ((m_debugMode & btIDebugDraw::DBG_NoHelpText)==0) + { + setOrthographicProjection(); + int xOffset = 10.f; + int yStart = 20.f; + int yIncr = 20.f; + showProfileInfo(xOffset, yStart, yIncr); + DrawConstraintInfo(); + outputDebugInfo(xOffset, yStart, yIncr); + resetPerspectiveProjection(); + } +} + + + +extern int gNumClampedCcdMotions; +#define SHOW_NUM_DEEP_PENETRATIONS 1 +#ifdef SHOW_NUM_DEEP_PENETRATIONS + extern int gNumDeepPenetrationChecks; + extern int gNumSplitImpulseRecoveries; + extern int gNumGjkChecks; + extern int gNumAlignedAllocs; + extern int gNumAlignedFree; + extern int gTotalBytesAlignedAllocs; +#endif // + + +void BasicDemo3D::outputDebugInfo(int & xOffset,int & yStart, int yIncr) +{ + char buf[124]; + glDisable(GL_LIGHTING); + glColor3f(0, 0, 0); + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"mouse to interact"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"space to reset"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"cursor keys and z,x to navigate"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"i to toggle simulation, s single step"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"q to quit"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"h to toggle help text"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"p to toggle profiling (+results to file)"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"w to toggle wireframe/solid rendering"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"c to toggle constraint drawing"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"b to draw single constraint batch"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"u to toggle between CPU and CUDA solvers"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"d to toggle between different batch builders"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"m to toggle between CUDA / CPU motion integrators"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + if (getDynamicsWorld()) + { + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"# objects = %d",getDynamicsWorld()->getNumCollisionObjects()); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"# pairs = %d",getDynamicsWorld()->getBroadphase()->getOverlappingPairCache()->getNumOverlappingPairs()); + GLDebugDrawString(xOffset,yStart,buf); + + + yStart += yIncr; + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"# skipped collisions=%d",gSkippedCol); + GLDebugDrawString(xOffset,yStart,buf); + + yStart += yIncr; + glRasterPos3f(xOffset,yStart,0); + sprintf(buf,"# processed collisions=%d",gProcessedCol); + GLDebugDrawString(xOffset,yStart,buf); + + yStart += yIncr; + glRasterPos3f(xOffset,yStart,0); + btScalar fract = (gProcessedCol+gSkippedCol)? btScalar(gSkippedCol)/(gProcessedCol+gSkippedCol) : 0.f; + sprintf(buf,"culled narrowphase collisions=%f",fract); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + gProcessedCol = 0; + gSkippedCol = 0; + + } +} // BasicDemo3D::outputDebugInfo() + +void BasicDemo3D::setWireMode(bool wireOnOff) +{ + int dbgDrawMode = m_dynamicsWorld->getDebugDrawer()->getDebugMode(); + if(wireOnOff) + { + dbgDrawMode |= btIDebugDraw::DBG_FastWireframe; + } + else + { + dbgDrawMode &= ~btIDebugDraw::DBG_FastWireframe; + } + m_dynamicsWorld->getDebugDrawer()->setDebugMode(dbgDrawMode); + m_debugMode = dbgDrawMode; +} // BasicDemo3D::setWireMode() diff --git a/Demos/Gpu3dDemo/BasicDemo3d.h b/Demos/Gpu3dDemo/BasicDemo3d.h new file mode 100644 index 0000000..7600e27 --- /dev/null +++ b/Demos/Gpu3dDemo/BasicDemo3d.h @@ -0,0 +1,93 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +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 BASIC_DEMO3D_H +#define BASIC_DEMO3D_H + +#include "GlutDemoApplication.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" + +class btBroadphaseInterface; +class btCollisionShape; +class btOverlappingPairCache; +class btCollisionDispatcher; +class btConstraintSolver; +struct btCollisionAlgorithmCreateFunc; +class btDefaultCollisionConfiguration; + +///BasicDemo is good starting point for learning the code base and porting. +class BasicDemo3D : public GlutDemoApplication +{ + + //keep the collision shapes, for deletion/cleanup + btAlignedObjectArray m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + int m_mouseButtons; + int m_mouseOldX; + int m_mouseOldY; + + public: + + BasicDemo3D() + { + } + virtual ~BasicDemo3D() + { + exitPhysics(); + } + void initPhysics(); + + void exitPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + virtual void keyboardCallback(unsigned char key, int x, int y); + virtual void mouseFunc(int button, int state, int x, int y); + virtual void mouseMotionFunc(int x,int y); + + virtual void clientResetScene(); + + static DemoApplication* Create() + { + BasicDemo3D* demo = new BasicDemo3D; + demo->myinit(); + demo->initPhysics(); + demo->m_mouseButtons = 0; + demo->m_mouseOldX = 0; + demo->m_mouseOldY = 0; + return demo; + } + + void DrawConstraintInfo(); + void outputDebugInfo(int & xOffset,int & yStart, int yIncr); + virtual void renderme(); + + void setWireMode(bool wireOnOff); +}; + + +#endif //BASIC_DEMO3D_H + diff --git a/Demos/Gpu3dDemo/CMakeLists.txt b/Demos/Gpu3dDemo/CMakeLists.txt new file mode 100644 index 0000000..e7e2a02 --- /dev/null +++ b/Demos/Gpu3dDemo/CMakeLists.txt @@ -0,0 +1,34 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# This is the variable for Windows. I use this to define the root of my directory structure. +SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/Glut) + +# You shouldn't have to modify anything below this line +######################################################## + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletMultiThreaded BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppGpu3dDemo + main.cpp + BasicDemo3d.cpp + BasicDemo3d.h + btGpuDemo3dSharedTypes.h + btGpuDemo3dCpuFunc.cpp + btGpuDemoDynamicsWorld3D.cpp + btGpuDemoDynamicsWorld3D.h + btGpuDemo3dSharedCode.h + btGpuDemo3dSharedDefs.h +) + + diff --git a/Demos/Gpu3dDemo/btGpuDemo3dCpuFunc.cpp b/Demos/Gpu3dDemo/btGpuDemo3dCpuFunc.cpp new file mode 100644 index 0000000..9c956d4 --- /dev/null +++ b/Demos/Gpu3dDemo/btGpuDemo3dCpuFunc.cpp @@ -0,0 +1,32 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +//---------------------------------------------------------------------------------------- + +#include "LinearMath/btQuickprof.h" + +//---------------------------------------------------------------------------------------- + +#include "btGpuDemo3dSharedTypes.h" + +//---------------------------------------------------------------------------------------- + +#include "BulletMultiThreaded/btGpuDefines.h" +#include "BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#include "btGpuDemo3dSharedCode.h" + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- diff --git a/Demos/Gpu3dDemo/btGpuDemo3dSharedCode.h b/Demos/Gpu3dDemo/btGpuDemo3dSharedCode.h new file mode 100644 index 0000000..487b60f --- /dev/null +++ b/Demos/Gpu3dDemo/btGpuDemo3dSharedCode.h @@ -0,0 +1,545 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "LinearMath/btMinMax.h" + +//---------------------------------------------------------------------------------------- + +#define USE_FRICTION 1 +#define FRICTION_BOX_GROUND_FACT 0.01f +#define FRICTION_BOX_BOX_FACT 0.01f +//#define FRICTION_BOX_BOX_FACT 0.05f +#define USE_CENTERS 1 + +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------- C o n s t r a i n t s o l v e r d e m o 3D -------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- + +// kernel functions + + +BT_GPU___global__ void clearAccumulationOfLambdaDtD(float* lambdaDtBox, int numConstraints, int numContPoints) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index < numConstraints) + { + for(int i=0; i < numContPoints; i++) + lambdaDtBox[numContPoints * index + i] = 0; + } +} // clearAccumulationOfLambdaDtD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___device__ float computeImpulse3D(float3 rVel, + float positionConstraint, + float3 cNormal, + float dt) +{ + const float collisionConstant = 0.1f; + const float baumgarteConstant = 0.1f; + const float penetrationError = 0.02f; + + float lambdaDt=0; + float3 impulse=BT_GPU_make_float3(0.f,0.f,0.f); + + if(positionConstraint >= 0) + return lambdaDt; + + positionConstraint = btMin(0.0f,positionConstraint+penetrationError); + + lambdaDt = -(BT_GPU_dot(cNormal,rVel)*(collisionConstant)); + lambdaDt -= (baumgarteConstant/dt*positionConstraint); + + return lambdaDt; +} // computeImpulse3D() + +//---------------------------------------------------------------------------------------- + +#if 0 +#define VLIM 1000.f +void BT_GPU___device__ chk_vect(float4* v) +{ + if(v->x < -VLIM) v->x = 0.f; + if(v->x > VLIM) v->x = 0.f; + if(v->y < -VLIM) v->y = 0.f; + if(v->y > VLIM) v->y = 0.f; + if(v->z < -VLIM) v->z = 0.f; + if(v->z > VLIM) v->z = 0.f; +} // chk_vect() +#endif + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void collisionWithWallBox3DD(float4 *trans, + float4 *vel, + float4* angVel, + btCudaPartProps pProp, + btCudaBoxProps gProp, + int nParticles, + float dt) +{ + int idx = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + float3 aPos; + float positionConstraint; + float3 impulse; + + if(idx < nParticles) + { + aPos = BT_GPU_make_float34(trans[idx * 4 + 3]); + for(int iVtx=0; iVtx < 8; iVtx++) + { + float3 dx = BT_GPU_make_float34(trans[idx * 4 + 0]); + float3 dy = BT_GPU_make_float34(trans[idx * 4 + 1]); + float3 dz = BT_GPU_make_float34(trans[idx * 4 + 2]); + float3 rerVertex = ((iVtx & 1) ? dx : dx * (-1.f)); + + rerVertex += ((iVtx & 2) ? dy : dy * (-1.f)); + rerVertex += ((iVtx & 4) ? dz : dz * (-1.f)); + float3 vPos = aPos + rerVertex; + float3 aVel = BT_GPU_make_float3(vel[idx].x, vel[idx].y, vel[idx].z); + float3 aAngVel = BT_GPU_make_float34(angVel[idx]); + float3 vVel =aVel+BT_GPU_cross(aAngVel, rerVertex); + float restitution=0.5; + { + positionConstraint = vPos.y - gProp.minY; + impulse = BT_GPU_make_float31(0.0f); + if(positionConstraint < 0) + { + float3 groundNormal; + groundNormal = BT_GPU_make_float3(0.0f,1.0f,0.0f); + impulse = groundNormal * restitution * computeImpulse3D(vVel, positionConstraint, groundNormal, dt); +#if USE_FRICTION // only with ground for now + float3 lat_vel = vVel - groundNormal * BT_GPU_dot(groundNormal,vVel); + float lat_vel_len = BT_GPU_dot(lat_vel, lat_vel); + if (lat_vel_len > 0) + { + lat_vel_len = sqrtf(lat_vel_len); + lat_vel *= 1.f/lat_vel_len; + impulse -= lat_vel * BT_GPU_dot(lat_vel, vVel) * FRICTION_BOX_GROUND_FACT; + } +#endif //USE_FRICTION + vel[idx] += BT_GPU_make_float42(impulse,0.0f); + angVel[idx] += BT_GPU_make_float42(BT_GPU_cross(rerVertex,impulse), 0.0f); + } + } + { + positionConstraint = vPos.x - gProp.minX; + impulse = BT_GPU_make_float31(0.0f); + if(positionConstraint < 0) + { + float3 normal = BT_GPU_make_float3(1.0f,0.0f,0.0f); + impulse = normal * restitution * computeImpulse3D(vVel,positionConstraint,normal,dt); + vel[idx] += BT_GPU_make_float42(impulse,0.0f); + angVel[idx] += BT_GPU_make_float42(BT_GPU_cross(rerVertex,impulse), 0.0f); + } + } + { + positionConstraint = gProp.maxX - vPos.x; + impulse = BT_GPU_make_float31(0.0f); + if(positionConstraint < 0) + { + float3 normal = BT_GPU_make_float3(-1.0f,0.0f,0.0f); + impulse = normal * restitution * computeImpulse3D(vVel,positionConstraint,normal,dt); + vel[idx] += BT_GPU_make_float42(impulse,0.0f); + angVel[idx] += BT_GPU_make_float42(BT_GPU_cross(rerVertex,impulse), 0.0f); + } + } + { + positionConstraint = vPos.z - gProp.minZ; + impulse = BT_GPU_make_float31(0.0f); + if(positionConstraint < 0) + { + float3 normal = BT_GPU_make_float3(0.0f,0.0f,1.0f); + impulse = normal * restitution * computeImpulse3D(vVel,positionConstraint,normal,dt); + vel[idx] += BT_GPU_make_float42(impulse,0.0f); + angVel[idx] += BT_GPU_make_float42(BT_GPU_cross(rerVertex,impulse), 0.0f); + } + } + { + positionConstraint = gProp.maxZ - vPos.z; + impulse = BT_GPU_make_float31(0.0f); + if(positionConstraint < 0) + { + float3 normal = BT_GPU_make_float3(0.0f,0.0f,-1.0f); + impulse = normal * restitution * computeImpulse3D(vVel,positionConstraint,normal,dt); + vel[idx] += BT_GPU_make_float42(impulse,0.0f); + angVel[idx] += BT_GPU_make_float42(BT_GPU_cross(rerVertex,impulse), 0.0f); + } + } + } + } +} // collisionWithWallBox3DD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void collisionBatchResolutionBox3DD(int2 *constraints, + int *batch, + int nConstraints, + float4 *trans, + float4 *vel, + float4 *angularVel, + float *lambdaDtBox, + float *iPositionConstraint, + float3 *normal, + float3 *contact, + btCudaPartProps pProp, + int iBatch, + float dt) +{ + float3 relVel; + float3 impulse; + float lambdaDt; + float positionConstraint; + int k_idx = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(k_idx < nConstraints) + { + int idx = batch[k_idx]; + int aId=constraints[idx].x; + int bId=constraints[idx].y; + float3 aPos = BT_GPU_make_float34(trans[aId * 4 + 3]); + float3 bPos = BT_GPU_make_float34(trans[bId * 4 + 3]); + float3 aVel = BT_GPU_make_float34(vel[aId]); + float3 bVel = BT_GPU_make_float34(vel[bId]); + float3 aAngVel = BT_GPU_make_float34(angularVel[aId]); + float3 bAngVel = BT_GPU_make_float34(angularVel[bId]); + for(int iVtx = 0; iVtx < 4; iVtx++) + { + float3 contactPoint = contact[idx * 4 + iVtx] - aPos; + positionConstraint = iPositionConstraint[idx * 4 + iVtx]; + if(positionConstraint > 0) + { + float3 contactNormal = normal[idx * 4 + iVtx]; + relVel = (aVel + BT_GPU_cross(aAngVel, contactPoint)) + -(bVel + BT_GPU_cross(bAngVel, contactPoint+aPos-bPos)); + + lambdaDt= computeImpulse3D(relVel, -positionConstraint, contactNormal, dt); + { + float rLambdaDt=lambdaDtBox[idx * 4 + iVtx]; + float pLambdaDt=rLambdaDt; + rLambdaDt=btMax(pLambdaDt+lambdaDt,0.0f); + lambdaDt=rLambdaDt-pLambdaDt; + lambdaDtBox[idx * 4 + iVtx]=rLambdaDt; + } + impulse = contactNormal*lambdaDt*0.5; +#if USE_FRICTION + float3 lat_vel = relVel - contactNormal * BT_GPU_dot(contactNormal, relVel); + float lat_vel_len = BT_GPU_dot(lat_vel, lat_vel); + if (lat_vel_len > 0) + { + lat_vel_len = sqrtf(lat_vel_len); + lat_vel *= 1.f/lat_vel_len; + impulse -= lat_vel * BT_GPU_dot(lat_vel , relVel) * FRICTION_BOX_BOX_FACT; + } +#endif //USE_FRICTION + aVel+= impulse; + bVel-= impulse; + aAngVel += BT_GPU_cross(contactPoint, impulse); + bAngVel -= BT_GPU_cross(contactPoint+aPos-bPos, impulse); + } + } + vel[aId]=BT_GPU_make_float42(aVel,0.0f); + vel[bId]=BT_GPU_make_float42(bVel,0.0f); + angularVel[aId]=BT_GPU_make_float42(aAngVel,0.0f); + angularVel[bId]=BT_GPU_make_float42(bAngVel,0.0f); + } +} // collisionBatchResolutionBox3DD() + +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- + + +extern "C" +{ + +// global functions + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(clearAccumulationOfLambdaDt(float* lambdaDtBox, int numConstraints, int numContPoints)) +{ + if(!numConstraints) + { + return; + } + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numConstraints, 256, numBlocks, numThreads); + // execute the kernel + BT_GPU_EXECKERNEL(numBlocks, numThreads, clearAccumulationOfLambdaDtD, (lambdaDtBox, numConstraints, numContPoints)); + // check if kernel invocation generated an error + BT_GPU_CHECK_ERROR("clearAccumulationOfLambdaDtD kernel execution failed"); + +} // clearAccumulationOfLambdaDt() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(collisionWithWallBox3D(void* trans,void* vel,void* angVel,btCudaPartProps pProp, btCudaBoxProps gProp,int numObjs,float dt)) +{ + if(!numObjs) + { + return; + } + float4* pTrans = (float4*)trans; + float4* pVel = (float4*)vel; + float4* pAngVel = (float4*)angVel; + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numObjs, 256, numBlocks, numThreads); + // execute the kernel + BT_GPU_EXECKERNEL(numBlocks, numThreads, collisionWithWallBox3DD, (pTrans,pVel,pAngVel,pProp,gProp,numObjs,dt)); + // check if kernel invocation generated an error + BT_GPU_CHECK_ERROR("collisionWithWallBox3DD kernel execution failed"); +} // collisionWithWallBox3D() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(collisionBatchResolutionBox3D(void* constraints,int *batch,int numConstraints,void *trans,void *vel, + void *angularVel,float *lambdaDtBox,float *positionConstraint,void* normal,void* contact, + btCudaPartProps pProp,int iBatch,float dt)) +{ + if(!numConstraints) + { + return; + } + int2* pConstr = (int2*)constraints; + float4* pTrans = (float4*)trans; + float4* pVel = (float4*)vel; + float4* pAngVel = (float4*)angularVel; + float3* pNorm = (float3*)normal; + float3* pContact = (float3*)contact; + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numConstraints, 128, numBlocks, numThreads); + // execute the kernel + BT_GPU_EXECKERNEL(numBlocks, numThreads, collisionBatchResolutionBox3DD, (pConstr,batch,numConstraints,pTrans,pVel,pAngVel,lambdaDtBox,positionConstraint,pNorm,pContact,pProp,iBatch,dt)); + // check if kernel invocation generated an error + BT_GPU_CHECK_ERROR("collisionBatchResolutionBox3DD kernel execution failed"); +} // collisionBatchResolutionBox3D() + +//---------------------------------------------------------------------------------------- + +} // extern "C" + +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------- M o t i o n i n t e g r a t o r d e m o ----------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- + +// kernel functions + +BT_GPU___global__ void integrVelD(float4* pForceTorqueDamp, float4* pInvInertiaMass, float4* pVel, float4* pAngVel, float timeStep, unsigned int numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + // unpack input data + float3 force = BT_GPU_make_float34(pForceTorqueDamp[index * 2]); + float lin_damp = pForceTorqueDamp[index * 2].w; + float3 torque = BT_GPU_make_float34(pForceTorqueDamp[index * 2 + 1]); + float ang_damp = pForceTorqueDamp[index * 2 + 1].w; + float3 linVel = BT_GPU_make_float34(pVel[index]); + float3 angVel = BT_GPU_make_float34(pAngVel[index]); + float3 in_mass_0 = BT_GPU_make_float34(pInvInertiaMass[index * 3]); + float3 in_mass_1 = BT_GPU_make_float34(pInvInertiaMass[index * 3 + 1]); + float3 in_mass_2 = BT_GPU_make_float34(pInvInertiaMass[index * 3 + 2]); + float mass = pInvInertiaMass[index * 3].w; + // integrate linear velocity + float3 outLinVel, outAngVel; + outLinVel = linVel + force * mass * timeStep; + // integrate angular velocity + outAngVel.x = BT_GPU_dot(in_mass_0, torque); + outAngVel.y = BT_GPU_dot(in_mass_1, torque); + outAngVel.z = BT_GPU_dot(in_mass_2, torque); + outAngVel += angVel; + /// clamp angular velocity. collision calculations will fail on higher angular velocities + #if(!defined(M_PI)) + #define M_PI 3.1415926f + #endif + #define BT_CUDA_MAX_SQ_ANGVEL (M_PI*M_PI) + float sq_angvel = BT_GPU_dot(outAngVel, outAngVel); + sq_angvel *= timeStep * timeStep; + float fact; + if(sq_angvel > BT_CUDA_MAX_SQ_ANGVEL) + { + fact = sqrtf(BT_CUDA_MAX_SQ_ANGVEL/sq_angvel) / timeStep; + outAngVel *= fact; + } + // now apply damping + fact = powf(1.0f - lin_damp, timeStep); + outLinVel *= fact; + fact = powf(1.0f - ang_damp, timeStep); + outAngVel *= fact; + // pack results + pVel[index] = BT_GPU_make_float42(outLinVel, 0.f); + pAngVel[index] = BT_GPU_make_float42(outAngVel, 0.f); +} // integrVelD() + +#define BT_GPU__ANGULAR_MOTION_THRESHOLD (0.25f * M_PI) + +//---------------------------------------------------------------------------------------- + +BT_GPU___device__ float4 getRotation(float4* trans) +{ + float trace = trans[0].x + trans[1].y + trans[2].z; + float temp[4]; + if(trace > 0.0f) + { + float s = sqrtf(trace + 1.0f); + temp[3] = s * 0.5f; + s = 0.5f / s; + temp[0] = (trans[1].z - trans[2].y) * s; + temp[1] = (trans[2].x - trans[0].z) * s; + temp[2] = (trans[0].y - trans[1].x) * s; + } + else + { + typedef float btMatrRow[4]; + btMatrRow* m_el = (btMatrRow*)trans; + int i = m_el[0][0] < m_el[1][1] ? + (m_el[1][1] < m_el[2][2] ? 2 : 1) : + (m_el[0][0] < m_el[2][2] ? 2 : 0); + int j = (i + 1) % 3; + int k = (i + 2) % 3; + float s = sqrtf(m_el[i][i] - m_el[j][j] - m_el[k][k] + 1.0f); + temp[i] = s * 0.5f; + s = 0.5f / s; + temp[3] = (m_el[j][k] - m_el[k][j]) * s; + temp[j] = (m_el[i][j] + m_el[j][i]) * s; + temp[k] = (m_el[i][k] + m_el[k][i]) * s; + } + float4 q = BT_GPU_make_float44(temp[0],temp[1],temp[2],temp[3]); + return q; +} // getRotation() + +//---------------------------------------------------------------------------------------- + +BT_GPU___device__ float4 quatMult(float4& q1, float4& q2) +{ + return BT_GPU_make_float44(q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y, + q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z, + q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x, + q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z); +} // quatMult() + +//---------------------------------------------------------------------------------------- + +BT_GPU___device__ void quatNorm(float4& q) +{ + float len = sqrtf(BT_GPU_dot4(q, q)); + q *= 1.f / len; +} // quatNorm() + +//---------------------------------------------------------------------------------------- + +BT_GPU___device__ void setRotation(float4& q, float4* trans) +{ + float d = BT_GPU_dot4(q, q); + float s = 2.0f / d; + float xs = q.x * s, ys = q.y * s, zs = q.z * s; + float wx = q.w * xs, wy = q.w * ys, wz = q.w * zs; + float xx = q.x * xs, xy = q.x * ys, xz = q.x * zs; + float yy = q.y * ys, yz = q.y * zs, zz = q.z * zs; + trans[0].x = 1.0f - (yy + zz); + trans[1].x = xy - wz; + trans[2].x = xz + wy; + trans[0].y = xy + wz; + trans[1].y = 1.0f - (xx + zz); + trans[2].y = yz - wx; + trans[0].z = xz - wy; + trans[1].z = yz + wx; + trans[2].z = 1.0f - (xx + yy); + trans[0].w = trans[1].w = trans[2].w = 0.0f; +} // setRotation() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void integrTransD(float4* pTrans, float4* pVel, float4* pAngVel, float timeStep, unsigned int numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + float3 pos = BT_GPU_make_float34(pTrans[index * 4 + 3]); + float3 linvel = BT_GPU_make_float34(pVel[index]); + pos += linvel * timeStep; + + float3 axis; + float3 angvel = BT_GPU_make_float34(pAngVel[index]); + float fAngle = sqrtf(BT_GPU_dot(angvel, angvel)); + //limit the angular motion + if(fAngle*timeStep > BT_GPU__ANGULAR_MOTION_THRESHOLD) + { + fAngle = BT_GPU__ANGULAR_MOTION_THRESHOLD / timeStep; + } + if(fAngle < 0.001f) + { + // use Taylor's expansions of sync function + axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle); + } + else + { + // sync(fAngle) = sin(c*fAngle)/t + axis = angvel * ( sinf(0.5f * fAngle * timeStep) / fAngle); + } + float4 dorn = BT_GPU_make_float42(axis, cosf(fAngle * timeStep * 0.5f)); + float4 orn0 = getRotation(pTrans + index * 4); + float4 predictedOrn = quatMult(dorn, orn0); + quatNorm(predictedOrn); + setRotation(predictedOrn, pTrans + index * 4); + pTrans[index * 4 + 3] = BT_GPU_make_float42(pos, 0.f); +} // integrTransD() + + +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- + +// global functions + +extern "C" +{ + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(integrVel(float* pForceTorqueDamp, float* pInvInertiaMass, void* pVel, void* pAngVel, float timeStep, unsigned int numBodies)) +{ + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); + BT_GPU_EXECKERNEL(numBlocks, numThreads, integrVelD, ((float4*)pForceTorqueDamp, (float4*)pInvInertiaMass, (float4*)pVel, (float4*)pAngVel, timeStep, numBodies)); + BT_GPU_CHECK_ERROR("Kernel execution failed: btCuda_integrVelD"); +} // integrVel() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(integrTrans(void* trans, void* vel, void* angVel, float timeStep, int numBodies)) +{ + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); + BT_GPU_EXECKERNEL(numBlocks, numThreads, integrTransD, ((float4*)trans, (float4*)vel, (float4*)angVel, timeStep, numBodies)); + BT_GPU_CHECK_ERROR("Kernel execution failed: btCuda_integrTransD"); +} // integrTrans() + +//---------------------------------------------------------------------------------------- + +} // extern "C" + +//------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------ +//---------------------------------------------------------------------------------------- diff --git a/Demos/Gpu3dDemo/btGpuDemo3dSharedDefs.h b/Demos/Gpu3dDemo/btGpuDemo3dSharedDefs.h new file mode 100644 index 0000000..d0abea4 --- /dev/null +++ b/Demos/Gpu3dDemo/btGpuDemo3dSharedDefs.h @@ -0,0 +1,38 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +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. +*/ + +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------- C o n s t r a i n t s o l v e r d e m o ---------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- + + +extern "C" +{ + +void BT_GPU_PREF(clearAccumulationOfLambdaDt(float* lambdaDtBox, int numConstraints, int numContPoints)); +void BT_GPU_PREF(collisionWithWallBox3D(void* trans,void* vel,void* angVel,btCudaPartProps pProp, btCudaBoxProps gProp,int numObjs,float dt)); +void BT_GPU_PREF(collisionBatchResolutionBox3D(void* constraints,int *batch,int numConstraints,void *trans,void *vel, + void *angularVel,float *lambdaDtBox,float *positionConstraint,void* normal,void* contact, + btCudaPartProps pProp,int iBatch,float dt)); + +void BT_GPU_PREF(integrVel(float* pForceTorqueDamp, float* pInvInertiaMass, void* pVel, void* pAngVel, float timeStep, unsigned int numBodies)); +void BT_GPU_PREF(integrTrans(void* trans, void* vel, void* angVel, float timeStep, int numBodies)); + + +} // extern "C" + +//---------------------------------------------------------------------------------------- diff --git a/Demos/Gpu3dDemo/btGpuDemo3dSharedTypes.h b/Demos/Gpu3dDemo/btGpuDemo3dSharedTypes.h new file mode 100644 index 0000000..2d6400e --- /dev/null +++ b/Demos/Gpu3dDemo/btGpuDemo3dSharedTypes.h @@ -0,0 +1,39 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +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. +*/ + +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------- C o n s t r a i n t s o l v e r d e m o ---------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- + +struct btCudaPartProps +{ + float m_mass; + float m_diameter; + float m_restCoeff; +}; + +struct btCudaBoxProps +{ + float minX; + float maxX; + float minY; + float maxY; + float minZ; + float maxZ; +}; + +//---------------------------------------------------------------------------------------- diff --git a/Demos/Gpu3dDemo/btGpuDemoDynamicsWorld3D.cpp b/Demos/Gpu3dDemo/btGpuDemoDynamicsWorld3D.cpp new file mode 100644 index 0000000..3398c96 --- /dev/null +++ b/Demos/Gpu3dDemo/btGpuDemoDynamicsWorld3D.cpp @@ -0,0 +1,593 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +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 "btGpuDemoDynamicsWorld3D.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" +#include "LinearMath/btQuickprof.h" +#include "GlutStuff.h" + +#include + +//-------------------------------------------------------------------------- + +#define BT_GPU_PREF(func) btCuda_##func +#include "../../src/BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#include "btGpuDemo3dSharedDefs.h" +#undef BT_GPU_PREF + +#define BT_GPU_PREF(func) btGpu_##func +#include "btGpuDemo3dSharedDefs.h" +#undef BT_GPU_PREF + +//-------------------------------------------------------------------------- + +#if 0 +static void check_vel(btVector3& v, int id, char* tag) +{ + int i; + for(i = 0; i < 3; i++) + { + btScalar a = v[i]; + a = btFabs(a); + if(a > 1000.f) + { + break; + } + } + if(i < 3) + { + printf("\nERROR in %s (%4d) : %7.2f %7.2f %7.2f\n", tag, id, v[0], v[1], v[2]); + v[0] = v[1] = v[2] = 0.f; + } +} +#endif + +//-------------------------------------------------------------------------- + +void btCudaDemoDynamicsWorld3D::grabObjData() +{ + int i; + m_numObj = getNumCollisionObjects(); + for(i = 0; i < m_numObj; i++) + { + btCollisionObject* colObj = m_collisionObjects[i]; + colObj->setCompanionId(i); + btRigidBody* rb = btRigidBody::upcast(colObj); + btVector3 v; + if(m_copyIntegrDataToGPU) + { + const btTransform& tr = rb->getCenterOfMassTransform(); + v = tr.getBasis().getColumn(0); + m_hTrans[i * 4 + 0] = *((float4*)&v); + v = tr.getBasis().getColumn(1); + m_hTrans[i * 4 + 1] = *((float4*)&v); + v = tr.getBasis().getColumn(2); + m_hTrans[i * 4 + 2] = *((float4*)&v); + v = rb->getCenterOfMassPosition(); + m_hTrans[i * 4 + 3] = *((float4*)&v); + } + if(!m_useCudaMotIntegr) + { + v = rb->getLinearVelocity(); + m_hVel[i] = *((float4*)&v); + v = rb->getAngularVelocity(); + m_hAngVel[i] = *((float4*)&v); + } + } +} // btCudaDemoDynamicsWorld3D::grabObjData() + +//-------------------------------------------------------------------------- + +void btCudaDemoDynamicsWorld3D::grabConstrData() +{ + int i; + btDispatcher* dispatcher = getDispatcher(); + btPersistentManifold** manifoldPtr = dispatcher->getInternalManifoldPointer(); + int numManifolds = dispatcher->getNumManifolds(); + btPersistentManifold* manifold = 0; + m_numConstraints = 0; + +/* // paranoia + for(int j = 0; j < m_numObj; j++) + { + m_hConstraintCounter[j] = 0; + } +*/ + for(i = 0; i < numManifolds; i++) + { + manifold = manifoldPtr[i]; + int numPoints = manifold->getNumContacts(); + if(!numPoints) + { + continue; + } + + int numActualPoints = 0; + for(int n = 0; n < numPoints; n++) + { + btManifoldPoint& cp = manifold->getContactPoint(n); + if (cp.m_distance1<=0) + { + numActualPoints++; + } + + } + if (!numActualPoints) + continue; + + btRigidBody *rbA, *rbB; + rbA = (btRigidBody*)manifold->getBody0(); + rbB = (btRigidBody*)manifold->getBody1(); + int idA = rbA->getCompanionId(); + int idB = rbB->getCompanionId(); + m_hConstraintCounter[idA]++; + m_hConstraintCounter[idB]++; + if(idA < idB) + { + m_hIds[m_numConstraints].x = idA; + m_hIds[m_numConstraints].y = idB; + + for(int n = 0; n < numPoints; n++) + { + btManifoldPoint& cp = manifold->getContactPoint(n); + btVector3 v = cp.getPositionWorldOnA(); + m_hContact[m_numConstraints * m_maxPointsPerConstr + n] = *((float3*)&v); + v = cp.m_normalWorldOnB; + m_hNormal[m_numConstraints * m_maxPointsPerConstr + n] = *((float3*)&v); + float dist = cp.getDistance(); + if(dist > 0.f) + { + dist = 0.f; + } + m_hPositionConstraint[m_numConstraints * m_maxPointsPerConstr + n] = -dist; + } + } + else + { // should never happen + btAssert(0); + } + for(int n = numPoints; n < m_maxPointsPerConstr; n++) + { + m_hPositionConstraint[m_numConstraints * m_maxPointsPerConstr + n] = 0.f; + } + m_numConstraints++; + } +/* + // paranoia + for(int j = 0; j < m_numObj; j++) + { + if(m_hConstraintCounter[j] > m_maxNeihbors) + { + printf("WARN : constraint connter is %d for object %d\n", m_hConstraintCounter[j], j); + } + } +*/ +} // btCudaDemoDynamicsWorld3D::grabConstrData() + +//-------------------------------------------------------------------------- + +void btCudaDemoDynamicsWorld3D::grabData() +{ + BT_PROFILE("grab data from rigidbody and manifold"); + grabObjData(); + // constraints + grabConstrData(); +} // btCudaDemoDynamicsWorld3D::grabGata() + +//-------------------------------------------------------------------------- + +void btCudaDemoDynamicsWorld3D::createBatches() +{ + BT_PROFILE("create batches"); + int sz = m_numConstraints; + for(int i = 0; i < m_numConstraints; i++) + { + m_hBatchIds[i] = -1; + m_hConstraintUsed[i] = 0; + } + int curBatchId=0; + int* pBatchIds = m_hBatchIds; + int stage; + for(stage = 0; stage < m_maxBatches; stage++) + { // don't print junk on demo screen :-) + m_numInBatches[stage] = 0; + } + for(stage = 0; stage < m_maxBatches; stage++) + { + bool isLast = (stage == m_maxBatches-1); + for(int j = 0; j < m_numObj; j++) + { + m_hConstraintCounter[j] = 0; + } + int numInBatch = 0; + for(int i = 0; i < m_numConstraints; i++) + { + if(m_hConstraintUsed[i]) + { + continue; + } + int2 ids = m_hIds[i]; + if(!isLast) + { + if((m_hConstraintCounter[ids.x] == 0) && (m_hConstraintCounter[ids.y] == 0)) + { + m_hConstraintCounter[ids.x]=1; + m_hConstraintCounter[ids.y]=1; + pBatchIds[numInBatch]=i; + numInBatch++; + m_hConstraintUsed[i] = 1; + } + } + else + { + pBatchIds[numInBatch]=i; + numInBatch++; + m_hConstraintUsed[i] = 1; + } + } + m_numInBatches[stage] = numInBatch; + pBatchIds += numInBatch; + if(!numInBatch) break; + } +} // btCudaDemoDynamicsWorld3D::createBatches() + +//-------------------------------------------------------------------------- + + +void btCudaDemoDynamicsWorld3D::writebackData() +{ + BT_PROFILE("copy velocity into btRigidBody"); + for(int i = 0; i < m_numObj; i++) + { + btCollisionObject* colObj = m_collisionObjects[i]; + btRigidBody* rb = btRigidBody::upcast(colObj); + btVector3 v; + v = *((btVector3*)(m_hVel + i)); + rb->setLinearVelocity(v); + v = *((btVector3*)(m_hAngVel + i)); + rb->setAngularVelocity(v); + } +} // btCudaDemoDynamicsWorld3D::writebackData() + +//-------------------------------------------------------------------------- + +void btCudaDemoDynamicsWorld3D::copyDataToGPU() +{ + BT_PROFILE("copyDataToGPU"); +#ifdef BT_USE_CUDA + btCuda_copyArrayToDevice(m_dIds, m_hIds, sizeof(int2) * m_numConstraints); + btCuda_copyArrayToDevice(m_dBatchIds, m_hBatchIds, sizeof(int) * m_numConstraints); + btCuda_copyArrayToDevice(m_dContact, m_hContact, m_numConstraints * m_maxPointsPerConstr * sizeof(float3)); + btCuda_copyArrayToDevice(m_dNormal, m_hNormal, m_numConstraints * m_maxPointsPerConstr * sizeof(float3)); + btCuda_copyArrayToDevice(m_dPositionConstraint, m_hPositionConstraint, m_numConstraints * m_maxPointsPerConstr * sizeof(float)); + + if(m_copyIntegrDataToGPU) + { + btCuda_copyArrayToDevice(m_dTrans, m_hTrans, m_numObj * sizeof(float4) * 4); + if(m_useCudaMotIntegr) + { + m_copyIntegrDataToGPU = false; + } + } + + if(!m_useCudaMotIntegr) + { + btCuda_copyArrayToDevice(m_dVel, m_hVel, m_numObj * sizeof(float4)); + btCuda_copyArrayToDevice(m_dAngVel, m_hAngVel, m_numObj * sizeof(float4)); + } +#endif +} // btCudaDemoDynamicsWorld3D::copyDataToGPU() + +//-------------------------------------------------------------------------- + +void btCudaDemoDynamicsWorld3D::copyDataFromGPU() +{ + BT_PROFILE("copy velocity data from device"); +#ifdef BT_USE_CUDA + btCuda_copyArrayFromDevice(m_hVel, m_dVel, m_numObj * sizeof(float4)); + btCuda_copyArrayFromDevice(m_hAngVel, m_dAngVel, m_numObj * sizeof(float4)); +#endif +} // btCudaDemoDynamicsWorld3D::copyDataFromGPU() + +//-------------------------------------------------------------------------- + +void btCudaDemoDynamicsWorld3D::solveConstraints(btContactSolverInfo& solverInfo) +{ + if(m_useSeqImpSolver) + { + btDiscreteDynamicsWorld::solveConstraints(solverInfo); + return; + } + if(m_useCPUSolver) + { + solveConstraintsCPU(solverInfo); + return; + } +#ifdef BT_USE_CUDA + BT_PROFILE("solveConstraints"); + grabData(); + createBatches(); + copyDataToGPU(); + + btCudaPartProps partProps; + partProps.m_mass = 1.0f; + partProps.m_diameter = m_objRad * 2.0f; + partProps.m_restCoeff = 1.0f; + + btCudaBoxProps boxProps; + boxProps.minX = m_worldMin[0]; + boxProps.maxX = m_worldMax[0]; + boxProps.minY = m_worldMin[1]; + boxProps.maxY = m_worldMax[1]; + boxProps.minZ = m_worldMin[2]; + boxProps.maxZ = m_worldMax[2]; + { + BT_PROFILE("btCuda_collisionBatchResolutionBox"); + + int nIter=getSolverInfo().m_numIterations; + btDispatcherInfo& dispatchInfo = getDispatchInfo(); + btScalar timeStep = dispatchInfo.m_timeStep; + + btCuda_clearAccumulationOfLambdaDt(m_dLambdaDtBox, m_numConstraints, m_maxPointsPerConstr); + + for(int i=0;igetWorldTransform().getOrigin(); + btVector3 vB = colObjB->getWorldTransform().getOrigin(); + glVertex3f(vA[0], vA[1], vA[2]); + glVertex3f(vB[0], vB[1], vB[2]); + } + pBatchIds += numConstraints; + glEnd(); + } +} // btCudaDemoDynamicsWorld3D::debugDrawConstraints() + +//-------------------------------------------------------------------------- + +void btCudaDemoDynamicsWorld3D::predictUnconstraintMotion(btScalar timeStep) +{ + if(m_useCudaMotIntegr) + { + BT_PROFILE("motIntegr -- predictUnconstraintMotion"); + int i; + { + m_numObj = getNumCollisionObjects(); + float* p_fbuf = m_hForceTorqueDamp; + float* p_mbuf = m_hInvInertiaMass; + for(i = 0; i < m_numObj; i++) + { + btCollisionObject* colObj = m_collisionObjects[i]; + btRigidBody* rb = btRigidBody::upcast(colObj); + btVector3* pForce = (btVector3*)p_fbuf; + *pForce = rb->getTotalForce(); + p_fbuf[3] = rb->getLinearDamping(); + p_fbuf += 4; + btVector3* pTorque = (btVector3*)p_fbuf; + *pTorque = rb->getTotalTorque(); + p_fbuf[3] = rb->getAngularDamping(); + p_fbuf += 4; + if(m_copyIntegrDataToGPU) + { + for(int k = 0; k < 3; k++) + { + btVector3* pInert = (btVector3*)(p_mbuf + k * 4); + *pInert = rb->getInvInertiaTensorWorld().getRow(k); + } + p_mbuf[3] = rb->getInvMass(); + p_mbuf += 12; + } + btVector3 v = rb->getLinearVelocity(); + m_hVel[i] = *((float4*)&v); + v = rb->getAngularVelocity(); + m_hAngVel[i] = *((float4*)&v); + } + } + if(m_useCPUSolver) + { + //BT_PROFILE("motIntegr -- integrate on CPU"); + btGpu_integrVel(m_hForceTorqueDamp, m_hInvInertiaMass, m_hVel, m_hAngVel, timeStep, m_numObj); + writebackData(); + } + else + { +#ifdef BT_USE_CUDA + //BT_PROFILE("CUDA motIntegr -- integrate on CUDA"); + btCuda_copyArrayToDevice(m_dForceTorqueDamp, m_hForceTorqueDamp, sizeof(float) * m_numObj * 4 * 2); + if(m_copyIntegrDataToGPU) + { + btCuda_copyArrayToDevice(m_dInvInertiaMass, m_hInvInertiaMass, sizeof(float) * m_numObj * 4 * 3); + } + btCuda_copyArrayToDevice(m_dVel, m_hVel, m_numObj * sizeof(float4)); + btCuda_copyArrayToDevice(m_dAngVel, m_hAngVel, m_numObj * sizeof(float4)); + btCuda_integrVel(m_dForceTorqueDamp, m_dInvInertiaMass, m_dVel, m_dAngVel, timeStep, m_numObj); + copyDataFromGPU(); + writebackData(); +#endif + } + } + else + { + btDiscreteDynamicsWorld::predictUnconstraintMotion(timeStep); + m_copyIntegrDataToGPU = true; + } +} // btCudaDemoDynamicsWorld3D::predictUnconstraintMotion() + +//-------------------------------------------------------------------------- + +void btCudaDemoDynamicsWorld3D::integrateTransforms(btScalar timeStep) +{ + if(m_useCudaMotIntegr) + { + BT_PROFILE("motIntegr -- integrateTransforms"); + if(m_useCPUSolver) + { + btGpu_integrTrans(m_hTrans, m_hVel, m_hAngVel, timeStep, m_numObj); + } + else + { +#ifdef BT_USE_CUDA + btCuda_integrTrans(m_dTrans, m_dVel, m_dAngVel, timeStep, m_numObj); + btCuda_copyArrayFromDevice(m_hTrans, m_dTrans, m_numObj * sizeof(float4) * 4); +#endif + } + m_numObj = getNumCollisionObjects(); + for(int i = 0; i < m_numObj; i++) + { + btCollisionObject* colObj = m_collisionObjects[i]; + btRigidBody* rb = btRigidBody::upcast(colObj); + btVector3 v; + btTransform tr; + const btVector3& v0 = *((btVector3*)&m_hTrans[i * 4 + 0]); + const btVector3& v1 = *((btVector3*)&m_hTrans[i * 4 + 1]); + const btVector3& v2 = *((btVector3*)&m_hTrans[i * 4 + 2]); + const btVector3& v3 = *((btVector3*)&m_hTrans[i * 4 + 3]); + tr.getBasis().setValue(v0[0], v1[0], v2[0], v0[1], v1[1], v2[1], v0[2], v1[2], v2[2]); + tr.getOrigin().setValue(v3[0], v3[1], v3[2]); + rb->proceedToTransform(tr); + } + } + else + { + btDiscreteDynamicsWorld::integrateTransforms(timeStep); + } +} // btCudaDemoDynamicsWorld3D::integrateTransforms() + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- diff --git a/Demos/Gpu3dDemo/btGpuDemoDynamicsWorld3D.h b/Demos/Gpu3dDemo/btGpuDemoDynamicsWorld3D.h new file mode 100644 index 0000000..845e8f7 --- /dev/null +++ b/Demos/Gpu3dDemo/btGpuDemoDynamicsWorld3D.h @@ -0,0 +1,252 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CUDA_DEMO_DYNAMICS_WORLD3D_H +#define BT_CUDA_DEMO_DYNAMICS_WORLD3D_H + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" + +//#define BT_USE_CUDA 1 +// To enable CUDA : +// 1. Uncomment //#define BT_USE_CUDA 1 +// 2. Build and add libbulletcuda (Extras/CUDA) to project +// 3. Add $(CUDA_LIB_PATH) and cudart.lib to linker properties + + +#ifdef BT_USE_CUDA + #include "BulletMultiThreaded/btGpuDefines.h" + #undef BT_GPU_PREF + #define BT_GPU_PREF(func) btCuda_##func + #include "BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#else + #include "BulletMultiThreaded/btGpuDefines.h" + #include "../../src/BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#endif + +#undef BT_GPU_PREF + + +#if 0 // ### +#include +#define BT_GPU_PREF(func) btCuda_##func +#include "../../src/BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#undef BT_GPU_PREF +#endif + +#include "btGpuDemo3dSharedTypes.h" + +//#define CUDA_DEMO_DYNAMICS_WORLD3D_MAX_BATCHES 20 +#define CUDA_DEMO_DYNAMICS_WORLD3D_MAX_BATCHES 15 + +class btCudaDemoDynamicsWorld3D : public btDiscreteDynamicsWorld +{ +protected: + int m_maxObj; + int m_maxNeihbors; + int m_maxConstr; + int m_maxPointsPerConstr; + + int m_numObj; + int m_numSimStep; + bool m_useCPUSolver; + bool m_useSeqImpSolver; + bool m_useCudaMotIntegr; + bool m_copyIntegrDataToGPU; + + +#ifdef BT_USE_CUDA + float4* m_dTrans; + float4* m_dVel; + float4* m_dAngVel; + int2* m_dIds; + int* m_dBatchIds; + float* m_dLambdaDtBox; + float* m_dPositionConstraint; + float3* m_dNormal; + float3* m_dContact; + float* m_dForceTorqueDamp; + float* m_dInvInertiaMass; +#endif + + float4* m_hTrans; + float4* m_hVel; + float4* m_hAngVel; + int* m_hConstraintBuffer; + int* m_hConstraintCounter; + int m_maxBatches; + int m_numBatches; + int m_numConstraints; + int2* m_hIds; + int* m_hBatchIds; + + int m_maxVtxPerObj; + + + // ------------- these are only needed for CPU version and for debugging + float* m_hLambdaDtBox; + float* m_hPositionConstraint; + float3* m_hNormal; + float3* m_hContact; + // ------------- + + btScalar m_objRad; + btVector3 m_worldMin; + btVector3 m_worldMax; + + //------------------------------- + int* m_hConstraintUsed; + + //------------------------------- + + float* m_hForceTorqueDamp; + float* m_hInvInertiaMass; + +public: + int m_numInBatches[CUDA_DEMO_DYNAMICS_WORLD3D_MAX_BATCHES]; + + + btCudaDemoDynamicsWorld3D(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration, int maxPointsPerConstr = 4) + : btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration) + { + m_useCPUSolver = false; + m_useSeqImpSolver = false; + m_useCudaMotIntegr = true; + m_copyIntegrDataToGPU = true; + m_maxObj = 32768; + m_maxNeihbors = 26; + m_maxConstr = m_maxObj * m_maxNeihbors; + int sz = m_maxConstr; + m_hConstraintBuffer = new int[sz]; + m_hConstraintCounter = new int[m_maxObj]; + m_maxBatches = CUDA_DEMO_DYNAMICS_WORLD3D_MAX_BATCHES; + m_hIds = new int2[sz]; + m_hBatchIds = new int[sz]; + for(int i = 0; i < sz; i++) + { + m_hBatchIds[i] = -1; + } + m_hTrans = new float4[m_maxObj * 4]; + m_hVel = new float4[m_maxObj]; + m_hAngVel = new float4[m_maxObj]; + + m_maxPointsPerConstr = maxPointsPerConstr; + +#ifdef BT_USE_CUDA + btCuda_allocateArray((void**)&m_dTrans, sizeof(float4) * m_maxObj * 4); + btCuda_allocateArray((void**)&m_dVel, sizeof(float4) * m_maxObj); + btCuda_allocateArray((void**)&m_dAngVel, sizeof(float4) * m_maxObj); + + btCuda_allocateArray((void**)&m_dIds, sizeof(int2) * sz); + btCuda_allocateArray((void**)&m_dBatchIds, sizeof(int) * sz); + + + btCuda_allocateArray((void**)&m_dLambdaDtBox, sizeof(float) * sz * m_maxPointsPerConstr); + btCuda_allocateArray((void**)&m_dPositionConstraint, sizeof(float) * sz * m_maxPointsPerConstr); + btCuda_allocateArray((void**)&m_dNormal, sizeof(float3) * sz * m_maxPointsPerConstr); + btCuda_allocateArray((void**)&m_dContact, sizeof(float3) * sz * m_maxPointsPerConstr); + + btCuda_allocateArray((void**)&m_dForceTorqueDamp, sizeof(float) * m_maxObj * 4 * 2); + btCuda_allocateArray((void**)&m_dInvInertiaMass, sizeof(float) * m_maxObj * 4 * 3); +#endif + + m_hLambdaDtBox = new float[sz * m_maxPointsPerConstr]; + m_hPositionConstraint = new float[sz * m_maxPointsPerConstr]; + m_hNormal = new float3[sz * m_maxPointsPerConstr]; + m_hContact = new float3[sz * m_maxPointsPerConstr]; + + m_numSimStep = 0; + + m_objRad = 1.0f; + + m_hConstraintUsed = new int[sz]; + + m_hForceTorqueDamp = new float[m_maxObj * 4 * 2]; + m_hInvInertiaMass = new float[4 * m_maxObj * 3]; + + } + virtual ~btCudaDemoDynamicsWorld3D() + { + delete [] m_hConstraintBuffer; + delete [] m_hConstraintCounter; + delete [] m_hIds; + delete [] m_hBatchIds; + delete [] m_hTrans; + delete [] m_hVel; + delete [] m_hAngVel; + + delete [] m_hLambdaDtBox; + delete [] m_hPositionConstraint; + delete [] m_hNormal; + delete [] m_hContact; + delete [] m_hConstraintUsed; + + delete [] m_hForceTorqueDamp; + delete [] m_hInvInertiaMass; + + +#ifdef BT_USE_CUDA + btCuda_freeArray(m_dTrans); + btCuda_freeArray(m_dVel); + btCuda_freeArray(m_dAngVel); + + btCuda_freeArray(m_dIds); + btCuda_freeArray(m_dBatchIds); + btCuda_freeArray(m_dLambdaDtBox); + btCuda_freeArray(m_dPositionConstraint); + btCuda_freeArray(m_dNormal); + btCuda_freeArray(m_dContact); + btCuda_freeArray(m_dForceTorqueDamp); + btCuda_freeArray(m_dInvInertiaMass); +#endif + + } + virtual void calculateSimulationIslands() + { + if(m_useSeqImpSolver) + { + btDiscreteDynamicsWorld::calculateSimulationIslands(); + } + } + virtual void solveConstraints(btContactSolverInfo& solverInfo); + + virtual void predictUnconstraintMotion(btScalar timeStep); + virtual void integrateTransforms(btScalar timeStep); + + + + + void solveConstraintsCPU(btContactSolverInfo& solverInfo); + + void debugDrawConstraints(int selectedBatch, const float* pColorTab); + + void setObjRad(btScalar rad) { m_objRad = rad; } + void setWorldMin(const btVector3& worldMin) { m_worldMin = worldMin; } + void setWorldMax(const btVector3& worldMax) { m_worldMax = worldMax; } + + void grabData(); + void grabObjData(); + void grabConstrData(); + void createBatches(); + void copyDataToGPU(); + void copyDataFromGPU(); + void writebackData(); + void setUseCPUSolver(bool useCPU) { m_useCPUSolver = useCPU; } + void setUseSeqImpSolver(bool useSeqImpSolver) { m_useSeqImpSolver = useSeqImpSolver; } + void setUseCudaMotIntegr(bool useCudaMotIntegr) { m_useCudaMotIntegr = useCudaMotIntegr; } + void resetScene(void) { m_copyIntegrDataToGPU = true; } +}; + + +#endif //BT_CUDA_DEMO_DYNAMICS_WORLD3D_H diff --git a/Demos/Gpu3dDemo/main.cpp b/Demos/Gpu3dDemo/main.cpp new file mode 100644 index 0000000..f5eea80 --- /dev/null +++ b/Demos/Gpu3dDemo/main.cpp @@ -0,0 +1,61 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "BasicDemo3d.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btHashMap.h" + +class OurValue + { + int m_uid; + + public: + OurValue(const btVector3& initialPos) + :m_position(initialPos) + { + static int gUid=0; + m_uid=gUid; + gUid++; + } + + btVector3 m_position; + int getUid() const + { + return m_uid; + } + }; + + +int main(int argc,char** argv) +{ + GLDebugDrawer gDebugDrawer; + + BasicDemo3D ccdDemo; + ccdDemo.initPhysics(); + ccdDemo.getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + ccdDemo.setWireMode(false); + + +#ifdef CHECK_MEMORY_LEAKS + ccdDemo.exitPhysics(); +#else + return glutmain(argc, argv,640,480,"Bullet Physics Demo. http://bulletphysics.com",&ccdDemo); +#endif + + //default glut doesn't return from mainloop + return 0; +} diff --git a/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluid.cpp b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluid.cpp new file mode 100644 index 0000000..77976d0 --- /dev/null +++ b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluid.cpp @@ -0,0 +1,1045 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ + +#include +#include "btHfFluid.h" +#include "btHfFluidCollisionShape.h" +#include "btHfFluidBuoyantConvexShape.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "../../OpenGL/GLDebugDrawer.h" + +btHfFluid::btHfFluid (btScalar gridCellWidth, int numNodesWidth, int numNodesLength) +{ + m_eta = NULL; + m_temp = NULL; + m_ground = NULL; + m_height[0] = NULL; + m_height[1] = NULL; + m_u[0] = NULL; + m_u[1] = NULL; + m_v[0] = NULL; + m_v[1] = NULL; + m_r[0] = NULL; + m_r[1] = NULL; + m_flags = NULL; + m_fillRatio = NULL; + m_internalType = CO_HF_FLUID; + m_heightIndex = 0; + m_velocityIndex = 0; + m_rIndex = 0; + setGridDimensions (gridCellWidth, numNodesWidth, numNodesLength); + + btScalar maxHeight = 20.0; + m_aabbMin = btVector3 (0.0, 0.0, 0.0); + m_aabbMax = btVector3 (m_gridWidth, maxHeight, m_gridLength); + + setCollisionShape (new btHfFluidCollisionShape (this)); + + m_globalVelocityU = btScalar(0.0f); + m_globalVelocityV = btScalar(0.0f); + m_gravity = btScalar(-10.0f); + + m_volumeDisplacementScale = btScalar(0.5f); + m_horizontalVelocityScale = btScalar(0.5f); + + m_epsEta = btScalar(0.01f); + m_epsHeight = btScalar(0.001f); +} + +btHfFluid::~btHfFluid () +{ + btCollisionShape* collisionShape = getCollisionShape (); + delete collisionShape; + btAlignedFree (m_temp); + btAlignedFree (m_height[0]); + btAlignedFree (m_height[1]); + btAlignedFree (m_ground); + btAlignedFree (m_eta); + btAlignedFree (m_u[0]); + btAlignedFree (m_u[1]); + btAlignedFree (m_v[0]); + btAlignedFree (m_v[1]); + btAlignedFree (m_flags); + btAlignedFree (m_fillRatio); +} + +void btHfFluid::predictMotion(btScalar dt) +{ + transferDisplaced (dt); + + advectEta (dt); + advectVelocityU (dt); + advectVelocityV (dt); + updateHeight (dt); + computeFlagsAndFillRatio (); + updateVelocity (dt); + setReflectBoundaryLeft (); + setReflectBoundaryRight (); + setReflectBoundaryTop (); + setReflectBoundaryBottom (); + debugTests(); + //m_heightIndex = (m_heightIndex + 1) % 2; + //m_velocityIndex = (m_velocityIndex + 1) % 2; +} + +void btHfFluid::prep () +{ + for (int i = 0; i < m_numNodesLength*m_numNodesWidth;i++) + { + m_height[0][i] = m_eta[i] + m_ground[i]; + m_height[1][i] = m_eta[i] + m_ground[i]; + } + computeFlagsAndFillRatio (); +} + +btScalar btHfFluid::widthPos (int i) const +{ + return m_gridCellWidth * i; +} + +btScalar btHfFluid::lengthPos (int j) const +{ +return m_gridCellWidth * j; +} + +int btHfFluid::arrayIndex (int i, int j) const +{ + btAssert (i >= 0); + btAssert (i < m_numNodesWidth); + btAssert (j >= 0); + btAssert (j < m_numNodesLength); + int index = i + (j * m_numNodesWidth); + return index; +} + +int btHfFluid::arrayIndex (btScalar i, btScalar j) const +{ + int ii = (int)i; // truncate / floor + int ij = (int)j; // truncate / floor + + return arrayIndex (ii, ij); +} + +const btScalar* btHfFluid::getHeightArray () const +{ + return m_height[m_heightIndex]; +} + +const btScalar* btHfFluid::getGroundArray () const +{ + return m_ground; +} +const btScalar* btHfFluid::getEtaArray () const +{ + return m_eta; +} +const btScalar* btHfFluid::getVelocityUArray () const +{ + return m_u[m_velocityIndex]; +} +const btScalar* btHfFluid::getVelocityVArray () const +{ + return m_v[m_velocityIndex]; +} + +const bool* btHfFluid::getFlagsArray () const +{ + return m_flags; +} + + btScalar* btHfFluid::getHeightArray () +{ + return m_height[m_heightIndex]; +} + btScalar* btHfFluid::getGroundArray () +{ + return m_ground; +} + btScalar* btHfFluid::getEtaArray () +{ + return m_eta; +} + btScalar* btHfFluid::getVelocityUArray () +{ + return m_u[m_velocityIndex]; +} + btScalar* btHfFluid::getVelocityVArray () +{ + return m_v[m_velocityIndex]; +} + +bool* btHfFluid::getFlagsArray () +{ + return m_flags; +} + +void btHfFluid::setFluidHeight (int x, int y, btScalar height) +{ + int index = arrayIndex (x,y); + setFluidHeight (index, height); +} + +void btHfFluid::setFluidHeight (int index, btScalar height) +{ + m_eta[index] = height; + m_height[m_heightIndex][index] = m_ground[index] + m_eta[index]; + m_flags[index] = true; +} + +void btHfFluid::addFluidHeight (int x, int y, btScalar height) +{ + int index = arrayIndex (x,y); + m_eta[index] += height; + m_height[m_heightIndex][index] = m_ground[index] + m_eta[index]; + m_flags[index] = true; +} + +void btHfFluid::getAabbForColumn (int i, int j, btVector3& aabbMin, btVector3& aabbMax) +{ + btVector3 com = getWorldTransform().getOrigin(); + int sw = arrayIndex (i, j); + int se = arrayIndex (i+1, j); + int nw = arrayIndex (i, j+1); + int ne = arrayIndex (i+1, j+1); + + btScalar h = m_height[m_heightIndex][sw]; + btScalar g = m_ground[sw]; + + aabbMin = btVector3(widthPos (i), g, lengthPos (j)); + aabbMax = btVector3(widthPos (i+1), h, lengthPos (j+1)); + aabbMin += com; + aabbMax += com; +} + +void btHfFluid::foreachGroundTriangle(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) +{ + btVector3 verts[3]; + + btScalar minX, minZ, maxX, maxZ; + int startNodeX, startNodeZ, endNodeX, endNodeZ; + + minX = aabbMin.getX(); + minZ = aabbMin.getZ(); + maxX = aabbMax.getX(); + maxZ = aabbMax.getZ(); + + startNodeX = (int)(minX * m_gridCellWidthInv); + startNodeZ = (int)(minZ * m_gridCellWidthInv); + + endNodeX = (int)(maxX * m_gridCellWidthInv); + endNodeZ = (int)(maxZ * m_gridCellWidthInv); + + endNodeX++; + endNodeZ++; + + startNodeX = btMax (1, startNodeX); + startNodeZ = btMax (1, startNodeZ); + endNodeX = btMin (m_numNodesWidth-1, endNodeX); + endNodeZ = btMin (m_numNodesLength-1, endNodeZ); + +#ifdef __BRUTE__ + for (int i = 1; i < m_numNodesWidth-1; i++) + { + for (int j = 1; j < m_numNodesLength-1; j++) + { + // triangle 1 + verts[0] = btVector3(widthPos(i), m_ground[arrayIndex(i,j)], lengthPos(j)); + verts[1] = btVector3(widthPos(i), m_ground[arrayIndex(i,j+1)], lengthPos(j+1)); + verts[2] = btVector3(widthPos(i+1), m_ground[arrayIndex(i+1,j)], lengthPos(j)); + callback->processTriangle(verts,i,j); + // triangle 2 + verts[0] = btVector3(widthPos(i+1), m_ground[arrayIndex(i+1,j)], lengthPos(j)); + verts[1] = btVector3(widthPos(i), m_ground[arrayIndex(i,j+1)], lengthPos(j+1)); + verts[2] = btVector3(widthPos(i+1), m_ground[arrayIndex(i+1,j+1)], lengthPos(j+1)); + callback->processTriangle(verts,i,j); + } + } +#else + + for (int i = startNodeX; i < endNodeX; i++) + { + for (int j = startNodeZ; j < endNodeZ; j++) + { + // triangle 1 + verts[0] = btVector3(widthPos(i), m_ground[arrayIndex(i,j)], lengthPos(j)); + verts[1] = btVector3(widthPos(i), m_ground[arrayIndex(i,j+1)], lengthPos(j+1)); + verts[2] = btVector3(widthPos(i+1), m_ground[arrayIndex(i+1,j)], lengthPos(j)); + callback->processTriangle(verts,i,j); + // triangle 2 + verts[0] = btVector3(widthPos(i+1), m_ground[arrayIndex(i+1,j)], lengthPos(j)); + verts[1] = btVector3(widthPos(i), m_ground[arrayIndex(i,j+1)], lengthPos(j+1)); + verts[2] = btVector3(widthPos(i+1), m_ground[arrayIndex(i+1,j+1)], lengthPos(j+1)); + callback->processTriangle(verts,i,j); + } + } +#endif +} + +void btHfFluid::foreachFluidColumn (btHfFluidColumnCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) +{ + btScalar minX, minZ, maxX, maxZ; + int startNodeX, startNodeZ, endNodeX, endNodeZ; + + minX = aabbMin.getX(); + minZ = aabbMin.getZ(); + maxX = aabbMax.getX(); + maxZ = aabbMax.getZ(); + + startNodeX = (int)(minX * m_gridCellWidthInv); + startNodeZ = (int)(minZ * m_gridCellWidthInv); + + endNodeX = (int)(maxX * m_gridCellWidthInv); + endNodeZ = (int)(maxZ * m_gridCellWidthInv); + + endNodeX++; + endNodeZ++; + + startNodeX = btMax (1, startNodeX); + startNodeZ = btMax (1, startNodeZ); + endNodeX = btMin (m_numNodesWidth-2, endNodeX); + endNodeZ = btMin (m_numNodesLength-2, endNodeZ); + + bool r; + for (int i = startNodeX; i < endNodeX; i++) + { + for (int j = startNodeZ; j < endNodeZ; j++) + { + if (m_flags[arrayIndex (i, j)] == false) + continue; + + r = callback->processColumn (this, i, j); + if (!r) + return; + } + } +} + +void btHfFluid::foreachSurfaceTriangle (btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) +{ + btVector3 verts[3]; + + btScalar minX, minZ, maxX, maxZ; + int startNodeX, startNodeZ, endNodeX, endNodeZ; + + minX = aabbMin.getX(); + minZ = aabbMin.getZ(); + maxX = aabbMax.getX(); + maxZ = aabbMax.getZ(); + + startNodeX = (int)(minX * m_gridCellWidthInv); + startNodeZ = (int)(minZ * m_gridCellWidthInv); + + endNodeX = (int)(maxX * m_gridCellWidthInv); + endNodeZ = (int)(maxZ * m_gridCellWidthInv); + + endNodeX++; + endNodeZ++; + + startNodeX = btMax (1, startNodeX); + startNodeZ = btMax (1, startNodeZ); + endNodeX = m_numNodesWidth-1; + endNodeZ = m_numNodesLength-1; + + for (int i = startNodeX; i < endNodeX; i++) + { + for (int j = startNodeZ; j < endNodeZ; j++) + { + if (!m_flags[arrayIndex(i,j)]) + continue; + // triangle 1 + verts[0] = btVector3(widthPos(i), m_height[m_heightIndex][arrayIndex(i,j)], lengthPos(j)); + verts[1] = btVector3(widthPos(i), m_height[m_heightIndex][arrayIndex(i,j+1)], lengthPos(j+1)); + verts[2] = btVector3(widthPos(i+1), m_height[m_heightIndex][arrayIndex(i+1,j)], lengthPos(j)); + callback->processTriangle(verts,i,j); + // triangle 2 + verts[0] = btVector3(widthPos(i+1), m_height[m_heightIndex][arrayIndex(i+1,j)], lengthPos(j)); + verts[1] = btVector3(widthPos(i), m_height[m_heightIndex][arrayIndex(i,j+1)], lengthPos(j+1)); + verts[2] = btVector3(widthPos(i+1), m_height[m_heightIndex][arrayIndex(i+1,j+1)], lengthPos(j+1)); + callback->processTriangle(verts,i,j); + } + } +} + +void btHfFluid::setGridDimensions (btScalar gridCellWidth, + int numNodesWidth, int numNodesLength) +{ + m_gridWidth = gridCellWidth * numNodesWidth; + m_gridLength = gridCellWidth * numNodesLength; + m_gridCellWidth = gridCellWidth; + m_numNodesWidth = numNodesWidth; + m_numNodesLength = numNodesLength; + m_gridCellWidthInv = btScalar(1.0) / gridCellWidth; + + allocateArrays (); +} + +btScalar btHfFluid::bilinearInterpolate (const btScalar* array, btScalar iPos, btScalar jPos) +{ + int i = (int)iPos; + int j = (int)jPos; + + btScalar iParam1 = iPos - btScalar(i); + btScalar iParam0 = btScalar(1.0) - iParam1; + + btScalar jParam1 = jPos - btScalar(j); + btScalar jParam0 = btScalar(1.0) - jParam1; + + btScalar SW = array[arrayIndex(i, j)]; + btScalar SE = array[arrayIndex(i+1, j)]; + btScalar NW = array[arrayIndex(i, j+1)]; + btScalar NE = array[arrayIndex(i+1, j+1)]; + + btScalar a = jParam0 * SW + jParam1 * NW; + btScalar b = jParam0 * SE + jParam1 * NE; + return iParam0 * a + iParam1 * b; +} + +btScalar btHfFluid::advect (const btScalar* array, btScalar i, btScalar j, btScalar di, btScalar dj,btScalar dt) +{ + // trace particle backwards in time + btScalar srcI = i - di * dt * m_gridCellWidthInv; + btScalar srcJ = j - dj * dt * m_gridCellWidthInv; + + // srcI and srcJ are indices into the array, + // we need to clamp them to within the domain + srcI = btMax (srcI, btScalar(0.0)); + srcI = btMin (srcI, btScalar(m_numNodesWidth-1)); + srcJ = btMax (srcJ, btScalar(0.0)); + srcJ = btMin (srcJ, btScalar(m_numNodesLength-1)); + + return bilinearInterpolate (array, srcI, srcJ); +} + +void btHfFluid::advectEta (btScalar dt) +{ + for (int i = 1; i < m_numNodesWidth-1; i++) + { + for (int j = 1; j < m_numNodesLength-1; j++) + { + int index = arrayIndex (i, j); + + if (!m_flags[index]) + continue; + + btScalar u = m_globalVelocityU; + btScalar v = m_globalVelocityV; + + u += (m_u[m_velocityIndex][index]+m_u[m_velocityIndex][index+1]) * btScalar(0.5); + v += (m_v[m_velocityIndex][index]+m_v[m_velocityIndex][index+m_numNodesWidth]) * btScalar(0.5); + + m_temp[index] = advect (m_eta, btScalar(i), btScalar(j), u, v, dt); + } + } + for (int i = 1; i < m_numNodesWidth-1; i++) + { + for (int j = 1; j < m_numNodesLength-1; j++) + { + int index = arrayIndex (i, j); + m_eta[index] = m_temp[index]; + } + } +} + +void btHfFluid::updateHeight (btScalar dt) +{ + for (int j = 1; j < m_numNodesLength-1; j++) + { + for (int i = 1; i < m_numNodesWidth-1; i++) + { + int index = arrayIndex (i, j); + if (!m_flags[index]) + { + m_height[m_heightIndex][index] = m_ground[index] + m_eta[index]; + continue; + } + btScalar deta = -btScalar(0.5f) * m_eta[index] * dt * m_gridCellWidthInv * ( (m_u[m_velocityIndex][index+1] - m_u[m_velocityIndex][index]) + (m_v[m_velocityIndex][index+m_numNodesWidth] - m_v[m_velocityIndex][index])); + m_eta[index] += deta; + m_height[m_heightIndex][index] = m_ground[index] + btMax(m_eta[index],btScalar(0.0f)); + } + } +} + +void btHfFluid::advectVelocityU (btScalar dt) +{ + for (int i = 1; i < m_numNodesWidth-1; i++) + { + for (int j = 1; j < m_numNodesLength-1; j++) + { + int index = arrayIndex (i, j); + if (!m_flags[index]) + { + continue; + } + btScalar u = m_globalVelocityU; + btScalar v = m_globalVelocityV; + + u += m_u[m_velocityIndex][index]; + v += (m_v[m_velocityIndex][index]+m_v[m_velocityIndex][index+1]+m_v[m_velocityIndex][index+m_numNodesWidth]+m_v[m_velocityIndex][index+m_numNodesWidth+1]) * btScalar(0.25); + + m_temp[index] = advect (m_u[m_velocityIndex], btScalar(i), btScalar(j), u, v, dt); + } + } + + for (int i = 1; i < m_numNodesWidth-1; i++) + { + for (int j = 1; j < m_numNodesLength-1; j++) + { + int index = arrayIndex (i, j); + m_u[m_velocityIndex][index] = m_temp[index]; + } + } +} + +void btHfFluid::advectVelocityV (btScalar dt) +{ + for (int i = 1; i < m_numNodesWidth-1; i++) + { + for (int j = 1; j < m_numNodesLength-1; j++) + { + int index = arrayIndex (i, j); + if (!m_flags[index]) + { + continue; + } + btScalar u = m_globalVelocityU; + btScalar v = m_globalVelocityV; + + u += (m_u[m_velocityIndex][index]+m_u[m_velocityIndex][index+1]+m_u[m_velocityIndex][index+m_numNodesWidth]+m_u[m_velocityIndex][index+m_numNodesWidth+1]) * btScalar(0.25); + v += m_v[m_velocityIndex][index]; + + + m_temp[index] = advect (m_v[m_velocityIndex], btScalar(i), btScalar(j), u, v, dt); + } + } + for (int i = 1; i < m_numNodesWidth-1; i++) + { + for (int j = 1; j < m_numNodesLength-1; j++) + { + int index = arrayIndex (i, j); + m_v[m_velocityIndex][index] = m_temp[index]; + } + } +} + +void btHfFluid::addDisplaced (int i, int j, btScalar r) +{ + m_r[m_rIndex][arrayIndex(i,j)] += r; +} + +void btHfFluid::transferDisplaced (btScalar dt) +{ + for (int i = 2; i < m_numNodesWidth - 2; i++) + { + for (int j = 2; j < m_numNodesLength - 2; j++) + { + btScalar deltaR = m_r[m_rIndex][arrayIndex(i,j)] - m_r[(m_rIndex+1)%2][arrayIndex(i,j)]; + // deltaR is in volume, but we want to change the height.. + deltaR = deltaR / (m_gridCellWidth * m_gridCellWidth); + deltaR *= m_volumeDisplacementScale; + btScalar qdeltaR = deltaR / btScalar(4.0f); + m_eta[arrayIndex(i-1,j-1)] += qdeltaR; + m_eta[arrayIndex(i-1,j+1)] += qdeltaR; + m_eta[arrayIndex(i+1,j-1)] += qdeltaR; + m_eta[arrayIndex(i+1,j+1)] += qdeltaR; + m_eta[arrayIndex(i,j)] -= deltaR; + // OPTIMIZATION: zero out next frames r value + m_r[(m_rIndex+1)%2][arrayIndex(i,j)] = btScalar(0.0); + } + } + m_rIndex = (m_rIndex + 1) % 2; // flip frame +} + +void btHfFluid::updateVelocity (btScalar dt) +{ + for (int j = 1; j < m_numNodesLength-1; j++) + { + for (int i = 2; i < m_numNodesWidth-1; i++) + { + int index = arrayIndex (i, j); + if (!m_flags[index]) + { + continue; + } + m_u[m_velocityIndex][index] += m_gravity * dt * m_gridCellWidthInv * (m_height[m_heightIndex][index]-m_height[m_heightIndex][index-1]); + } + } + + for (int j = 2; j < m_numNodesLength-1; j++) + { + for (int i = 1; i < m_numNodesWidth-1; i++) + { + int index = arrayIndex (i, j); + if (!m_flags[index]) + { + continue; + } + m_v[m_velocityIndex][index] += m_gravity * dt * m_gridCellWidthInv * (m_height[m_heightIndex][index]-m_height[m_heightIndex][index-m_numNodesWidth]); + } + } +} + +void btHfFluid::setReflectBoundaryLeft () +{ + for (int j = 0; j < m_numNodesLength; j++) + { + int indexL = arrayIndex (0, j); + + m_height[m_heightIndex][indexL] = m_height[m_heightIndex][indexL+1]; + m_u[m_velocityIndex][indexL+1] = btScalar(0.0); + m_v[m_velocityIndex][indexL] = btScalar(0.0); + } +} + +void btHfFluid::setReflectBoundaryRight () +{ + for (int j = 0; j < m_numNodesLength; j++) + { + int indexR = arrayIndex (m_numNodesWidth-1, j); + + m_height[m_heightIndex][indexR] = m_height[m_heightIndex][indexR-1]; + m_u[m_velocityIndex][indexR-1] = btScalar(0.0); + m_v[m_velocityIndex][indexR] = btScalar(0.0); + } +} + +void btHfFluid::setReflectBoundaryBottom () +{ + for (int i = 0; i < m_numNodesWidth; i++) + { + int indexT = arrayIndex (i, 0); + + m_height[m_heightIndex][indexT] = m_height[m_heightIndex][indexT+m_numNodesWidth]; + m_v[m_velocityIndex][indexT+m_numNodesWidth] = btScalar(0.0); + m_u[m_velocityIndex][indexT] = btScalar(0.0); + } +} + +void btHfFluid::setReflectBoundaryTop () +{ + for (int i = 0; i < m_numNodesWidth; i++) + { + int indexB = arrayIndex (i, m_numNodesLength-1); + + m_height[m_heightIndex][indexB] = m_height[m_heightIndex][indexB-m_numNodesWidth]; + m_v[m_velocityIndex][indexB-m_numNodesWidth] = btScalar(0.0); + m_u[m_velocityIndex][indexB] = btScalar(0.0); + } +} + +void btHfFluid::setAbsorbBoundaryLeft (btScalar dt) +{ + for (int j = 0; j < m_numNodesLength; j++) + { + int indexL = arrayIndex (0, j); + + btScalar c = btSqrt(m_eta[indexL+1]*m_gravity); + m_height[m_heightIndex][indexL] = ((m_gridCellWidthInv * m_height[(m_heightIndex+1)%2][indexL+1])+(dt*c*m_height[m_heightIndex][indexL+1]))/(m_gridCellWidthInv + dt * c); + m_u[m_velocityIndex][indexL+1] = btScalar(0.0f); + m_v[m_velocityIndex][indexL+1] = btScalar(0.0); + } +} + +void btHfFluid::setAbsorbBoundaryRight (btScalar dt) +{ +} + +void btHfFluid::setAbsorbBoundaryTop (btScalar dt) +{ +} + +void btHfFluid::setAbsorbBoundaryBottom (btScalar dt) +{ +} + +void btHfFluid::computeFlagsAndFillRatio () +{ + for (int i = 1; i < m_numNodesWidth-1; i++) + { + for (int j = 1; j < m_numNodesLength-1; j++) + { + btScalar h = m_height[m_heightIndex][arrayIndex(i,j)]; + btScalar hMin = computeHmin(i,j); + btScalar hMax = computeHmax(i,j); + btScalar etaMax = computeEtaMax(i,j); + if (h <= hMin && etaMax < m_epsEta) + { + m_flags[arrayIndex(i,j)] = false; + m_fillRatio[arrayIndex(i,j)] = btScalar(0.0f); + } else if (h > hMax) { + m_flags[arrayIndex(i,j)] = true; + m_fillRatio[arrayIndex(i,j)] = btScalar(1.0f); + } else { + m_flags[arrayIndex(i,j)] = true; + m_fillRatio[arrayIndex(i,j)] = (h - hMin)/(hMax - hMin); + } + + } + } +} + +btScalar btHfFluid::computeHmin (int i, int j) +{ + btAssert (i > 0); + btAssert (i < m_numNodesWidth-1); + btAssert (j > 0); + btAssert (j < m_numNodesLength-1); + + btScalar h1 = m_height[m_heightIndex][arrayIndex(i-1,j-1)]; + btScalar h2 = m_height[m_heightIndex][arrayIndex(i-1,j+1)]; + btScalar h3 = m_height[m_heightIndex][arrayIndex(i+1,j-1)]; + btScalar h4 = m_height[m_heightIndex][arrayIndex(i+1,j+1)]; + btScalar h = m_height[m_heightIndex][arrayIndex(i,j)]; + btScalar minh = btMin(h1, btMin(h2, btMin(h3,h4))); + + return (minh + h) * btScalar(0.5f); +} + +btScalar btHfFluid::computeHmax (int i, int j) +{ + btAssert (i > 0); + btAssert (i < m_numNodesWidth-1); + btAssert (j > 0); + btAssert (j < m_numNodesLength-1); + + btScalar h1 = m_height[m_heightIndex][arrayIndex(i-1,j-1)]; + btScalar h2 = m_height[m_heightIndex][arrayIndex(i-1,j+1)]; + btScalar h3 = m_height[m_heightIndex][arrayIndex(i+1,j-1)]; + btScalar h4 = m_height[m_heightIndex][arrayIndex(i+1,j+1)]; + btScalar h = m_height[m_heightIndex][arrayIndex(i,j)]; + btScalar maxh = btMax(h1, btMax(h2, btMax(h3,h4))); + + return (maxh + h) * btScalar(0.5f) + m_epsHeight; +} + +btScalar btHfFluid::computeEtaMax (int i, int j) +{ + btAssert (i > 0); + btAssert (i < m_numNodesWidth-1); + btAssert (j > 0); + btAssert (j < m_numNodesLength-1); + + btScalar eta1 = m_eta[arrayIndex(i-1,j-1)]; + btScalar eta2 = m_eta[arrayIndex(i-1,j+1)]; + btScalar eta3 = m_eta[arrayIndex(i+1,j-1)]; + btScalar eta4 = m_eta[arrayIndex(i+1,j+1)]; + btScalar eta = m_eta[arrayIndex(i,j)]; + btScalar maxeta = btMax(eta1, btMax(eta2, btMax(eta3,eta4))); + + return (maxeta + eta) * btScalar(0.5f); +} + +void btHfFluid::allocateArrays () +{ + if (m_temp) + btAlignedFree (m_temp); + if (m_height[0]) + { + btAlignedFree (m_height[0]); + btAlignedFree (m_height[1]); + } + if (m_ground) + btAlignedFree (m_ground); + if (m_eta) + btAlignedFree (m_eta); + if (m_u[0]) + { + btAlignedFree (m_u[0]); + btAlignedFree (m_u[1]); + } + if (m_v) + { + btAlignedFree (m_v[0]); + btAlignedFree (m_v[1]); + } + if (m_r) + { + btAlignedFree (m_r[0]); + btAlignedFree (m_r[1]); + } + if (m_flags) + btAlignedFree (m_flags); + if (m_fillRatio) + btAlignedFree (m_fillRatio); + + m_heightIndex = 0; + m_velocityIndex = 0; + m_temp = (btScalar*)btAlignedAlloc (sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16); + m_height[0] = (btScalar*)btAlignedAlloc (sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16); + m_height[1] = (btScalar*)btAlignedAlloc (sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16); + m_ground = (btScalar*)btAlignedAlloc (sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16); + m_eta = (btScalar*)btAlignedAlloc (sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16); + m_u[0] = (btScalar*)btAlignedAlloc (sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16); + m_u[1] = (btScalar*)btAlignedAlloc (sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16); + m_v[0] = (btScalar*)btAlignedAlloc (sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16); + m_v[1] = (btScalar*)btAlignedAlloc (sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16); + m_r[0] = (btScalar*)btAlignedAlloc (sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16); + m_r[1] = (btScalar*)btAlignedAlloc (sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16); + m_fillRatio = (btScalar*)btAlignedAlloc (sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16); + m_flags = (bool*)btAlignedAlloc (sizeof(bool) * m_numNodesWidth * m_numNodesLength, 16); + + { + int bufferSize = sizeof(btScalar) * m_numNodesWidth * m_numNodesLength; + printf("[HfFluid] Fluid buffer size %d bytes\n", bufferSize); + printf("[HfFluid] Temp %d buffers\n", 1); + printf("[HfFluid] Height %d buffers\n", 2); + printf("[HfFluid] Velocity %d buffers\n", 4); + printf("[HfFluid] Eta %d buffers\n", 1); + printf("[HfFluid] Fill Ratio %d buffers\n", 1); + printf("[HfFluid] ===============================\n"); + printf("[HfFluid] Total %d buffers\n", 9); + printf("[HfFluid] Total %d KB\n", (9 * bufferSize)/1024); + } + for (int i = 0; i < m_numNodesWidth*m_numNodesLength; i++) + { + m_eta[i] = btScalar(0.0); + m_u[0][i] = btScalar(0.0); + m_u[1][i] = btScalar(0.0); + m_v[0][i] = btScalar(0.0); + m_v[1][i] = btScalar(0.0); + m_r[0][i] = btScalar(0.0); + m_r[1][i] = btScalar(0.0); + m_height[0][i] = btScalar(0.0); + m_height[1][i] = btScalar(0.0); + m_ground[i] = btScalar(0.0); + m_flags[i] = false; + m_fillRatio[i] = btScalar(0.0); + m_temp[i] = btScalar(0.0); + } +} + + +void btHfFluid::debugTests () +{ + static btScalar total_volume = btScalar(0.0f); + btScalar new_total_volume = btScalar(0.0f); + for (int i = 0; i < m_numNodesWidth*m_numNodesLength; i++) + { + new_total_volume += m_eta[i] * m_gridCellWidth * m_gridCellWidth; + } + printf("volume = %f volume delta = %f\n", new_total_volume, new_total_volume - total_volume); + total_volume = new_total_volume; +} + +// You can enforce a global velocity at the surface of the fluid +// default: 0.0 and 0.0 +void btHfFluid::setGlobaVelocity (btScalar globalVelocityU, btScalar globalVelocityV) +{ + m_globalVelocityU = globalVelocityU; + m_globalVelocityV = globalVelocityV; +} + +void btHfFluid::getGlobalVelocity (btScalar& globalVelocityU, btScalar& globalVelocityV) const +{ + globalVelocityU = m_globalVelocityU; + globalVelocityV = m_globalVelocityV; +} + +// Control force of gravity, should match physics world +// default: -10.0 +void btHfFluid::setGravity (btScalar gravity) +{ + m_gravity = gravity; +} +btScalar btHfFluid::getGravity () const +{ + return m_gravity; +} + +// When a body is submerged into the fluid, the displaced fluid +// is spread to adjacent cells. You can control the percentage of this +// by setting this value between 0.0 and 1.0 +// default: 0.5 +void btHfFluid::setVolumeDisplacementScale (btScalar volumeDisplacementScale) +{ + m_volumeDisplacementScale = volumeDisplacementScale; +} + +btScalar btHfFluid::getVolumeDisplacementScale () const +{ + return m_volumeDisplacementScale; +} + +// The horizontal velocity of the fluid can influence bodies submerged +// in the fluid. You can control how much influence by setting this +// between 0.0 and 1.0 +// default: 0.5 +void btHfFluid::setHorizontalVelocityScale (btScalar horizontalVelocityScale) +{ + m_horizontalVelocityScale = horizontalVelocityScale; +} + +btScalar btHfFluid::getHorizontalVelocityScale () const +{ + return m_horizontalVelocityScale; +} + +static btScalar rangeOverlap (btScalar lo1, btScalar hi1, btScalar lo2, btScalar hi2, btScalar& loOut, btScalar& hiOut) +{ + if (!(lo1 <= hi2 && lo2 <= hi1)) + return btScalar(0.0f); + + if (lo1 >= lo2 && lo1 <= hi2 && + hi1 >= lo2 && hi1 <= hi2) + { + hiOut = hi1; + loOut = lo1; + return hi1 - lo1; + } else if (lo2 >= lo1 && lo2 <= hi1 && + hi2 >= lo1 && hi2 <= hi1) + { + hiOut = hi2; + loOut = lo2; + return hi2 - lo2; + } else if (hi1 >= lo2 && lo1 <= lo2) { + hiOut = hi1; + loOut = lo2; + return hi1 - lo2; + } else { + hiOut = hi2; + loOut = lo1; + return hi2 - lo1; + } +} + +btHfFluidColumnRigidBodyCallback::btHfFluidColumnRigidBodyCallback (btRigidBody* rigidBody, btIDebugDraw* debugDraw, btScalar density, btScalar floatyness) +{ + m_rigidBody = rigidBody; + m_buoyantShape = (btHfFluidBuoyantConvexShape*)rigidBody->getCollisionShape(); + m_debugDraw = debugDraw; + m_rigidBody->getAabb (m_aabbMin, m_aabbMax); + m_volume = btScalar(0.0f); + m_density = density; + m_floatyness = floatyness; + m_numVoxels = m_buoyantShape->getNumVoxels (); + m_voxelPositionsXformed = (btVector3*)btAlignedAlloc(sizeof(btVector3)*m_numVoxels, 16); + m_voxelSubmerged = (bool*)btAlignedAlloc(sizeof(bool)*m_numVoxels, 16); + for (int i = 0; i < m_numVoxels; i++) + { + btVector3 p = m_buoyantShape->getVoxelPositionsArray()[i]; + p = m_rigidBody->getWorldTransform().getBasis() * p; + p += m_rigidBody->getWorldTransform().getOrigin(); + m_voxelPositionsXformed[i] = p; + m_voxelSubmerged[i] = false; + } +} + +btHfFluidColumnRigidBodyCallback::~btHfFluidColumnRigidBodyCallback () +{ + if (m_voxelPositionsXformed) + btAlignedFree (m_voxelPositionsXformed); + if (m_voxelSubmerged) + btAlignedFree (m_voxelSubmerged); +} + +static bool sphereVsAABB (const btVector3& aabbMin, const btVector3& aabbMax, const btVector3& sphereCenter, const btScalar sphereRadius) +{ + btScalar totalDistance = 0; + + // Accumulate the distance of the sphere's center on each axis + for(int i = 0; i < 3; ++i) { + + // If the sphere's center is outside the aabb, we've got distance on this axis + if(sphereCenter[i] < aabbMin[i]) { + btScalar borderDistance = aabbMin[i] - sphereCenter[i]; + totalDistance += borderDistance * borderDistance; + + } else if(sphereCenter[i] > aabbMax[i]) { + btScalar borderDistance = sphereCenter[i] - aabbMax[i]; + totalDistance += borderDistance * borderDistance; + + } + // Otherwise the sphere's center is within the box on this axis, so the + // distance will be 0 and we do not need to accumulate anything at all + + } + + // If the distance to the box is lower than the sphere's radius, both are overlapping + return (totalDistance <= (sphereRadius * sphereRadius)); +} + +bool btHfFluidColumnRigidBodyCallback::processColumn (btHfFluid* fluid, int w, int l) +{ + btVector3 columnAabbMin,columnAabbMax; + + fluid->getAabbForColumn (w, l, columnAabbMin, columnAabbMax); + + bool applyBuoyancyImpulse = true; + bool applyFluidVelocityImpulse = true; + bool applyFluidDisplace = true; + + btScalar dt = btScalar(1.0f/60.0f); + + btScalar columnVolume = btScalar(0.0f); + + for (int i = 0; i < m_buoyantShape->getNumVoxels(); i++) + { + if (m_voxelSubmerged[i]) + continue; + + if (sphereVsAABB(columnAabbMin, columnAabbMax, m_voxelPositionsXformed[i], m_buoyantShape->getVoxelRadius())) + { + m_voxelSubmerged[i] = true; + btScalar voxelVolume = m_buoyantShape->getVolumePerVoxel(); + columnVolume += voxelVolume; + + btVector3 application_point = m_voxelPositionsXformed[i]; + btVector3 relative_position = application_point - m_rigidBody->getCenterOfMassPosition(); + + if (applyBuoyancyImpulse) + { + btScalar massDisplacedWater = voxelVolume * m_density * m_floatyness; + btScalar force = massDisplacedWater * -fluid->getGravity(); + btScalar impulseMag = force * dt; + btVector3 impulseVec = btVector3(btScalar(0.0f), btScalar(1.0f), btScalar(0.0f)) * impulseMag; +//#define CENTER_IMPULSE_ONLY 1 +#ifdef CENTER_IMPULSE_ONLY + m_rigidBody->applyCentralImpulse (impulseVec); +#else + m_rigidBody->applyImpulse (impulseVec, relative_position); +#endif + } + } + } + + if (columnVolume > btScalar(0.0)) + { + m_volume += columnVolume; + + if (applyFluidDisplace) + { + fluid->addDisplaced (w, l, columnVolume); + } + + if (applyFluidVelocityImpulse) + { + int index = fluid->arrayIndex (w,l); + btScalar u = fluid->getVelocityUArray()[index]; + btScalar v = fluid->getVelocityVArray()[index]; + btVector3 vd = btVector3(u, btScalar(0.0f), v); + btVector3 impulse = vd * dt * fluid->getHorizontalVelocityScale(); + m_rigidBody->applyCentralImpulse (impulse); + } + } + + return true; +} + diff --git a/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluid.h b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluid.h new file mode 100644 index 0000000..0017c07 --- /dev/null +++ b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluid.h @@ -0,0 +1,243 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ + +#ifndef __HFFLUID_H +#define __HFFLUID_H + +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" + +class btPersistentManifold; +class btManifoldResult; + +// FIX AABB calculation for whole btHfFluid shape +// Fix flags and fill ratio +// -> Figure out the constants used in flags and fill ratio code +// Fix volume removal +// add buoyant convex vs. convex / concave +// add buoyant concave support (try bunny model) + +///experimental buyancy fluid demo +class btHfFluid : public btCollisionObject +{ +public: + btHfFluid (btScalar gridCellWidth, int numNodesWidth, int numNodesLength); + + ~btHfFluid (); + + void predictMotion(btScalar dt); + + /* Prep does some initial setup of the height field fluid. + * You should call this at initialization time. + */ + void prep (); + + static const btHfFluid* upcast(const btCollisionObject* colObj) + { + if (colObj->getInternalType()==CO_HF_FLUID) + return (const btHfFluid*)colObj; + return 0; + } + static btHfFluid* upcast(btCollisionObject* colObj) + { + if (colObj->getInternalType()==CO_HF_FLUID) + return (btHfFluid*)colObj; + return 0; + } + + // + // ::btCollisionObject + // + + virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin = m_aabbMin; + aabbMax = m_aabbMax; + } + + int getNumNodesWidth () const { return m_numNodesWidth; } + int getNumNodesLength () const { return m_numNodesLength; } + + btScalar getGridCellWidth () const { return m_gridCellWidth; } + btScalar widthPos (int i) const; + btScalar lengthPos (int j) const; + + int arrayIndex (int i, int j) const; + int arrayIndex (btScalar i, btScalar j) const; + int arrayIndex (unsigned int i, unsigned int j) const; + const btScalar* getHeightArray () const; + const btScalar* getGroundArray () const; + const btScalar* getEtaArray () const; + const btScalar* getVelocityUArray () const; + const btScalar* getVelocityVArray () const; + const bool* getFlagsArray () const; + + void setFluidHeight (int x, int y, btScalar height); + void setFluidHeight (int index, btScalar height); + + void addFluidHeight (int x, int y, btScalar height); + void addDisplaced (int i, int j, btScalar r); + + void getAabbForColumn (int x, int y, btVector3& aabbMin, btVector3& aabbMax); + + btScalar* getHeightArray (); + btScalar* getGroundArray (); + btScalar* getEtaArray (); + btScalar* getVelocityUArray (); + btScalar* getVelocityVArray (); + bool* getFlagsArray (); + + void foreachGroundTriangle(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax); + class btHfFluidColumnCallback + { + public: + btHfFluidColumnCallback () {} + + virtual ~btHfFluidColumnCallback () {} + + virtual bool processColumn (btHfFluid* fluid, int w, int l) + { + return true; // keep going + } + }; + + void foreachFluidColumn (btHfFluidColumnCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax); + + void foreachSurfaceTriangle (btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax); +protected: + int m_numNodesWidth; + int m_numNodesLength; + + btScalar m_gridCellWidth; + btScalar m_gridWidth; + btScalar m_gridLength; + + btScalar m_gridCellWidthInv; + + btVector3 m_aabbMin; + btVector3 m_aabbMax; + + void setGridDimensions (btScalar gridCellWidth, + int numNodesWidth, int numNodesLength); + + btScalar bilinearInterpolate (const btScalar* array, btScalar i, btScalar j); + + btScalar advect (const btScalar* array, btScalar i, btScalar j, btScalar di, btScalar dj, btScalar dt); + + void advectEta (btScalar dt); + void updateHeight (btScalar dt); + + void advectVelocityU (btScalar dt); + void advectVelocityV (btScalar dt); + void updateVelocity (btScalar dt); + + void transferDisplaced (btScalar dt); + + void setReflectBoundaryLeft (); + void setReflectBoundaryRight (); + void setReflectBoundaryTop (); + void setReflectBoundaryBottom (); + + void setAbsorbBoundaryLeft (btScalar dt); + void setAbsorbBoundaryRight (btScalar dt); + void setAbsorbBoundaryTop (btScalar dt); + void setAbsorbBoundaryBottom (btScalar dt); + + void computeFlagsAndFillRatio (); + btScalar computeHmin (int i, int j); + btScalar computeHmax (int i, int j); + btScalar computeEtaMax (int i, int j); + + void allocateArrays (); + + void debugTests (); + + btScalar* m_temp; // temp + int m_heightIndex; + btScalar* m_height[2]; + btScalar* m_ground; + btScalar* m_eta; // height - ground + btScalar* m_u[2]; + btScalar* m_v[2]; + int m_rIndex; + btScalar* m_r[2]; + int m_velocityIndex; + bool* m_flags; + btScalar* m_fillRatio; + + // tweakables + btScalar m_globalVelocityU; + btScalar m_globalVelocityV; + btScalar m_gravity; + btScalar m_volumeDisplacementScale; + btScalar m_horizontalVelocityScale; + + btScalar m_epsHeight; + btScalar m_epsEta; +public: + // You can enforce a global velocity at the surface of the fluid + // default: 0.0 and 0.0 + void setGlobaVelocity (btScalar globalVelocityU, btScalar globalVelocityV); + void getGlobalVelocity (btScalar& globalVelocityU, btScalar& globalVelocityV) const; + + // Control force of gravity, should match physics world + // default: -10.0 + void setGravity (btScalar gravity); + btScalar getGravity () const; + + // When a body is submerged into the fluid, the displaced fluid + // is spread to adjacent cells. You can control the percentage of this + // by setting this value between 0.0 and 1.0 + // default: 0.5 + void setVolumeDisplacementScale (btScalar volumeDisplacementScale); + btScalar getVolumeDisplacementScale () const; + + // The horizontal velocity of the fluid can influence bodies submerged + // in the fluid. You can control how much influence by setting this + // between 0.0 and 1.0 + // default: 0.5 + void setHorizontalVelocityScale (btScalar horizontalVelocityScale); + btScalar getHorizontalVelocityScale () const; +}; + +class btRigidBody; +class btIDebugDraw; +class btHfFluidBuoyantConvexShape; + +class btHfFluidColumnRigidBodyCallback : public btHfFluid::btHfFluidColumnCallback +{ +protected: + btRigidBody* m_rigidBody; + btHfFluidBuoyantConvexShape* m_buoyantShape; + btIDebugDraw* m_debugDraw; + int m_numVoxels; + btVector3* m_voxelPositionsXformed; + bool* m_voxelSubmerged; + btVector3 m_aabbMin; + btVector3 m_aabbMax; + btScalar m_volume; + btScalar m_density; + btScalar m_floatyness; +public: + btHfFluidColumnRigidBodyCallback (btRigidBody* rigidBody, btIDebugDraw* debugDraw, btScalar density, btScalar floatyness); + ~btHfFluidColumnRigidBodyCallback (); + bool processColumn (btHfFluid* fluid, int w, int l); + btScalar getVolume () const { return m_volume; } +}; + +#endif + diff --git a/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidBuoyantConvexShape.cpp b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidBuoyantConvexShape.cpp new file mode 100644 index 0000000..e222bd6 --- /dev/null +++ b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidBuoyantConvexShape.cpp @@ -0,0 +1,195 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ +#include + +#include "LinearMath/btAabbUtil2.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" + +#include "btHfFluidBuoyantConvexShape.h" + +btHfFluidBuoyantConvexShape::btHfFluidBuoyantConvexShape (btConvexShape* convexShape) +{ + m_convexShape = convexShape; + m_shapeType = HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE; + m_radius = btScalar(0.f); + m_numVoxels = 0; + m_voxelPositions = NULL; + m_totalVolume = btScalar(0.0f); + m_floatyness = btScalar(1.5f); +} + +btHfFluidBuoyantConvexShape::~btHfFluidBuoyantConvexShape () +{ + if (m_voxelPositions) + btAlignedFree (m_voxelPositions); +} + +void btHfFluidBuoyantConvexShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + return m_convexShape->getAabb (t, aabbMin, aabbMax); +} + +void btHfFluidBuoyantConvexShape::setMargin(btScalar margin) +{ + m_convexShape->setMargin (margin); +} + +void btHfFluidBuoyantConvexShape::setLocalScaling(const btVector3& scaling) +{ + m_convexShape->setLocalScaling (scaling); +} + +const char* btHfFluidBuoyantConvexShape::getName() const +{ + return "HF_FLUID_BUOYANT_CONVEX_SHAPE"; +} + +const btVector3& btHfFluidBuoyantConvexShape::getLocalScaling() const +{ + return m_convexShape->getLocalScaling(); +} + +void btHfFluidBuoyantConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + m_convexShape->calculateLocalInertia (mass, inertia); +} + +btScalar btHfFluidBuoyantConvexShape::getMargin() const +{ + return m_convexShape->getMargin(); +} + +//must be above the machine epsilon +#define REL_ERROR2 btScalar(1.0e-6) +static bool intersect(btVoronoiSimplexSolver* simplexSolver, + const btTransform& transformA, + const btTransform& transformB, + btConvexShape* a, + btConvexShape* b) +{ + + btScalar squaredDistance = SIMD_INFINITY; + btTransform localTransA = transformA; + btTransform localTransB = transformB; + btVector3 positionOffset = (localTransA.getOrigin() + localTransB.getOrigin()) * btScalar(0.5); + localTransA.getOrigin() -= positionOffset; + localTransB.getOrigin() -= positionOffset; + btScalar delta = btScalar(0.); + btVector3 v = btVector3(1.0f, 0.0f, 0.0f); + simplexSolver->reset (); + do + { + btVector3 seperatingAxisInA = (-v)* transformA.getBasis(); + btVector3 seperatingAxisInB = v* transformB.getBasis(); + + btVector3 pInA = a->localGetSupportVertexNonVirtual(seperatingAxisInA); + btVector3 qInB = b->localGetSupportVertexNonVirtual(seperatingAxisInB); + + btVector3 pWorld = localTransA(pInA); + btVector3 qWorld = localTransB(qInB); + + btVector3 w = pWorld - qWorld; + delta = v.dot(w); + + // potential exit, they don't overlap + if ((delta > btScalar(0.0))) + { + return false; + } + + if (simplexSolver->inSimplex (w)) + { + return false; + } + + simplexSolver->addVertex (w, pWorld, qWorld); + + if (!simplexSolver->closest(v)) + { + return false; + } + + btScalar previousSquaredDistance = squaredDistance; + squaredDistance = v.length2(); + + if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance) + { + return false; + } + } while (!simplexSolver->fullSimplex() && squaredDistance > REL_ERROR2 * simplexSolver->maxVertex()); + + return true; +} + +void btHfFluidBuoyantConvexShape::generateShape (btScalar radius, btScalar gap) +{ + btTransform T; + T.setIdentity (); + btVector3 aabbMin, aabbMax; + getAabb (T, aabbMin, aabbMax); + + m_radius = radius; + m_numVoxels = 0; + + btVoronoiSimplexSolver simplexSolver; + btSphereShape sphereShape(radius); + btVector3* voxelPositions = (btVector3*)btAlignedAlloc (sizeof(btVector3)*MAX_VOXEL_DIMENSION*MAX_VOXEL_DIMENSION*MAX_VOXEL_DIMENSION,16); + for (int i = 0; i < MAX_VOXEL_DIMENSION; i++) + { + for (int j = 0; j < MAX_VOXEL_DIMENSION; j++) + { + for (int k = 0; k < MAX_VOXEL_DIMENSION; k++) + { + btVector3 point; + btTransform sT; + sT.setIdentity (); + + point.setX(aabbMin.getX() + (i * btScalar(2.0f) * radius) + (i * gap)); + point.setY(aabbMin.getY() + (j * btScalar(2.0f) * radius) + (j * gap)); + point.setZ(aabbMin.getZ() + (k * btScalar(2.0f) * radius) + (k * gap)); + + if (TestPointAgainstAabb2(aabbMin, aabbMax, point)) + { + btTransform sT; + sT.setIdentity (); + sT.setOrigin (point); + + if (intersect (&simplexSolver, T, sT, m_convexShape, &sphereShape)) + { + voxelPositions[m_numVoxels] = point; + m_numVoxels++; + } + } + } + } + } + m_voxelPositions = (btVector3*)btAlignedAlloc (sizeof(btVector3)*m_numVoxels, 16); + for (int i = 0; i < m_numVoxels;i++) + { + m_voxelPositions[i] = voxelPositions[i]; + } + btAlignedFree (voxelPositions); + m_volumePerVoxel = btScalar(4.0f)/btScalar(3.0f)*SIMD_PI*radius*radius*radius; + m_totalVolume = m_numVoxels * m_volumePerVoxel; + m_radius = radius; +} + diff --git a/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidBuoyantConvexShape.h b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidBuoyantConvexShape.h new file mode 100644 index 0000000..13948ca --- /dev/null +++ b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidBuoyantConvexShape.h @@ -0,0 +1,62 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ +#ifndef __BT_HFFLUID_BUOYANT_CONVEX_SHAPE_H +#define __BT_HFFLUID_BUOYANT_CONVEX_SHAPE_H + +#include "LinearMath/btVector3.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" + +#define MAX_VOXEL_DIMENSION 32 + +class btConvexShape; +///experimental buyancy fluid demo +class btHfFluidBuoyantConvexShape : public btCollisionShape +{ +public: + btHfFluidBuoyantConvexShape (btConvexShape* convexShape); + ~btHfFluidBuoyantConvexShape (); + void generateShape (btScalar radius, btScalar gap); + + btConvexShape* getConvexShape () { return m_convexShape; } + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + virtual void setMargin(btScalar margin); + virtual btScalar getMargin() const; + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + virtual const char* getName()const; + + btScalar getVoxelRadius () const { return m_radius; } + btScalar getTotalVolume () const { return m_totalVolume; } + btScalar getVolumePerVoxel () const { return m_volumePerVoxel; } + btScalar getFloatyness () const { return m_floatyness; } + void setFloatyness (btScalar floatyness) { m_floatyness = floatyness; } + int getNumVoxels () const { return m_numVoxels; } + const btVector3* getVoxelPositionsArray() { return m_voxelPositions; } + +protected: + btScalar m_floatyness; + btScalar m_radius; + btScalar m_totalVolume; + btScalar m_volumePerVoxel; + int m_numVoxels; + btVector3* m_voxelPositions; + btConvexShape* m_convexShape; +}; + +#endif diff --git a/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidBuoyantShapeCollisionAlgorithm.cpp b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidBuoyantShapeCollisionAlgorithm.cpp new file mode 100644 index 0000000..6273b46 --- /dev/null +++ b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidBuoyantShapeCollisionAlgorithm.cpp @@ -0,0 +1,74 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ +#include + +#include "btHfFluidBuoyantShapeCollisionAlgorithm.h" +#include "btHfFluidBuoyantConvexShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" + +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "btHfFluid.h" + +btHfFluidBuoyantShapeCollisionAlgorithm::btHfFluidBuoyantShapeCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) +: btCollisionAlgorithm(ci), m_convexConvexAlgorithm(NULL, ci, col0, col1, simplexSolver, pdSolver,0,0) +{ + m_collisionObject0 = col0; + m_collisionObject1 = col1; +} + +btHfFluidBuoyantShapeCollisionAlgorithm::~btHfFluidBuoyantShapeCollisionAlgorithm() +{ +} + +void btHfFluidBuoyantShapeCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + btHfFluidBuoyantConvexShape* tmpShape0 = (btHfFluidBuoyantConvexShape*)body0->getCollisionShape(); + btHfFluidBuoyantConvexShape* tmpShape1 = (btHfFluidBuoyantConvexShape*)body1->getCollisionShape(); + btConvexShape* convexShape0 = tmpShape0->getConvexShape(); + btConvexShape* convexShape1 = tmpShape1->getConvexShape(); + + body0->setCollisionShape (convexShape0); + body1->setCollisionShape (convexShape1); + + m_convexConvexAlgorithm.processCollision (body0, body1, dispatchInfo,resultOut); + + body0->setCollisionShape (tmpShape0); + body1->setCollisionShape (tmpShape1); +} + +btScalar btHfFluidBuoyantShapeCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + btHfFluidBuoyantConvexShape* tmpShape0 = (btHfFluidBuoyantConvexShape*)body0->getCollisionShape(); + btHfFluidBuoyantConvexShape* tmpShape1 = (btHfFluidBuoyantConvexShape*)body1->getCollisionShape(); + btConvexShape* convexShape0 = tmpShape0->getConvexShape(); + btConvexShape* convexShape1 = tmpShape1->getConvexShape(); + + body0->setCollisionShape (convexShape0); + body1->setCollisionShape (convexShape1); + + btScalar toi = btScalar(0.0f); + + toi = m_convexConvexAlgorithm.calculateTimeOfImpact (body0, body1, dispatchInfo, resultOut); + + body0->setCollisionShape (tmpShape0); + body1->setCollisionShape (tmpShape1); + + return toi; +} diff --git a/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidBuoyantShapeCollisionAlgorithm.h b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidBuoyantShapeCollisionAlgorithm.h new file mode 100644 index 0000000..a744dc0 --- /dev/null +++ b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidBuoyantShapeCollisionAlgorithm.h @@ -0,0 +1,87 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ + +#ifndef HF_FLUID_BUOYANT_SHAPE_COLLISION_ALGORITHM_H +#define HF_FLUID_BUOYANT_SHAPE_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h" + +#include "LinearMath/btVector3.h" +class btHfFluid; + +class btConvexConvexAlgorithm; +class btConvexPenetrationDepthSolver; +class btSimplexSolverInterface; + +///experimental buyancy fluid demo +/// btHfFluidBuoyantShapeCollisionAlgorithm provides collision detection between btHfFluidBuoyantConvexShape and btHfFluidBuoyantConvexShape +class btHfFluidBuoyantShapeCollisionAlgorithm : public btCollisionAlgorithm +{ + btCollisionObject* m_collisionObject0; + btCollisionObject* m_collisionObject1; + + btConvexConvexAlgorithm m_convexConvexAlgorithm; +public: + + btHfFluidBuoyantShapeCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); + + virtual ~btHfFluidBuoyantShapeCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + m_convexConvexAlgorithm.getAllContactManifolds (manifoldArray); + } + + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + btConvexPenetrationDepthSolver* m_pdSolver; + btSimplexSolverInterface* m_simplexSolver; + + CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) + { + m_simplexSolver = simplexSolver; + m_pdSolver = pdSolver; + } + + virtual ~CreateFunc() {} + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btHfFluidBuoyantShapeCollisionAlgorithm)); + if (!m_swapped) + { + return new(mem) btHfFluidBuoyantShapeCollisionAlgorithm(ci,body0,body1, m_simplexSolver, m_pdSolver); + } else + { + return new(mem) btHfFluidBuoyantShapeCollisionAlgorithm(ci,body0,body1, m_simplexSolver, m_pdSolver); + } + } + }; +}; + +#endif //HF_FLUID_BUOYANT_SHAPE_COLLISION_ALGORITHM_H diff --git a/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidCollisionShape.cpp b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidCollisionShape.cpp new file mode 100644 index 0000000..7182092 --- /dev/null +++ b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidCollisionShape.cpp @@ -0,0 +1,18 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ +#include "btHfFluidCollisionShape.h" + diff --git a/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidCollisionShape.h b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidCollisionShape.h new file mode 100644 index 0000000..bf24670 --- /dev/null +++ b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidCollisionShape.h @@ -0,0 +1,94 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ +#ifndef BT_HF_FLUID_COLLISION_SHAPE_H +#define BT_HF_FLUID_COLLISION_SHAPE_H + +#include "btHfFluid.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btConvexInternalShape.h" +#include "BulletCollision/CollisionShapes/btConcaveShape.h" + +class btHfFluidCollisionShape : public btConcaveShape +{ + public: + btHfFluid* m_fluid; + + btHfFluidCollisionShape(btHfFluid* backptr) : btConcaveShape () + { + m_shapeType = HFFLUID_SHAPE_PROXYTYPE; + m_fluid=backptr; + } + + virtual ~btHfFluidCollisionShape() + { + + } + + void processAllTriangles(btTriangleCallback* /*callback*/,const btVector3& /*aabbMin*/,const btVector3& /*aabbMax*/) const + { + //not yet + btAssert(0); + } + + ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t. + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + /* t should be identity, but better be safe than...fast? */ + btVector3 mins; + btVector3 maxs; + + m_fluid->getAabb (mins, maxs); + + const btVector3 crns[]={t*btVector3(mins.x(),mins.y(),mins.z()), + t*btVector3(maxs.x(),mins.y(),mins.z()), + t*btVector3(maxs.x(),maxs.y(),mins.z()), + t*btVector3(mins.x(),maxs.y(),mins.z()), + t*btVector3(mins.x(),mins.y(),maxs.z()), + t*btVector3(maxs.x(),mins.y(),maxs.z()), + t*btVector3(maxs.x(),maxs.y(),maxs.z()), + t*btVector3(mins.x(),maxs.y(),maxs.z())}; + aabbMin=aabbMax=crns[0]; + for(int i=1;i<8;++i) + { + aabbMin.setMin(crns[i]); + aabbMax.setMax(crns[i]); + } + } + + virtual void setLocalScaling(const btVector3& /*scaling*/) + { + ///na + btAssert(0); + } + virtual const btVector3& getLocalScaling() const + { + static const btVector3 dummy(1,1,1); + return dummy; + } + virtual void calculateLocalInertia(btScalar /*mass*/,btVector3& /*inertia*/) const + { + ///not yet + btAssert(0); + } + virtual const char* getName()const + { + return "HfFluid"; + } +}; + +#endif diff --git a/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidCollisionAlgorithm.cpp b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidCollisionAlgorithm.cpp new file mode 100644 index 0000000..7584fff --- /dev/null +++ b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidCollisionAlgorithm.cpp @@ -0,0 +1,133 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ + +#include + +#include "btHfFluidRigidCollisionAlgorithm.h" +#include "btHfFluidBuoyantConvexShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "btHfFluid.h" + +btHfFluidRigidCollisionAlgorithm::~btHfFluidRigidCollisionAlgorithm() +{ +} + +btHfFluidRigidCollisionAlgorithm::btHfFluidRigidCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped) +: btCollisionAlgorithm(ci), m_isSwapped(isSwapped), + m_convexTrianglecallback(ci.m_dispatcher1, col0, col1, !isSwapped) // we flip the isSwapped because we are hf fluid vs. convex and callback expects convex vs. concave +{ + m_manifoldPtr = m_convexTrianglecallback.m_manifoldPtr; + if (m_isSwapped) + { + m_hfFluid = static_cast(col1); + m_rigidCollisionObject = static_cast(col0); + m_manifoldPtr->setBodies(m_hfFluid,m_rigidCollisionObject); + } else { + m_hfFluid = static_cast(col0); + m_rigidCollisionObject = static_cast(col1); + m_manifoldPtr->setBodies(m_rigidCollisionObject,m_hfFluid); + } +} + +void btHfFluidRigidCollisionAlgorithm::processGround (const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + btScalar triangleMargin = m_rigidCollisionObject->getCollisionShape()->getMargin(); + resultOut->setPersistentManifold(m_manifoldPtr); + // to perform the convex shape vs. ground terrain: + // we pull the convex shape out of the buoyant shape and replace it temporarily + btHfFluidBuoyantConvexShape* tmpShape = (btHfFluidBuoyantConvexShape*)m_rigidCollisionObject->getCollisionShape(); + btConvexShape* convexShape = ((btHfFluidBuoyantConvexShape*)tmpShape)->getConvexShape(); + m_rigidCollisionObject->setCollisionShape (convexShape); + m_convexTrianglecallback.setTimeStepAndCounters (triangleMargin, dispatchInfo, resultOut); + m_hfFluid->foreachGroundTriangle (&m_convexTrianglecallback, m_convexTrianglecallback.getAabbMin(),m_convexTrianglecallback.getAabbMax()); + resultOut->refreshContactPoints(); + // restore the buoyant shape + m_rigidCollisionObject->setCollisionShape (tmpShape); +} + +btScalar btHfFluidRigidCollisionAlgorithm::processFluid (const btDispatcherInfo& dispatchInfo, btScalar density, btScalar floatyness) +{ + btRigidBody* rb = btRigidBody::upcast(m_rigidCollisionObject); + btHfFluidColumnRigidBodyCallback columnCallback (rb, dispatchInfo.m_debugDraw, density, floatyness); + m_hfFluid->foreachFluidColumn (&columnCallback, m_convexTrianglecallback.getAabbMin(), m_convexTrianglecallback.getAabbMax()); + return columnCallback.getVolume (); +} + +void btHfFluidRigidCollisionAlgorithm::applyFluidFriction (btScalar mu, btScalar submerged_percentage) +{ + btRigidBody* rb = btRigidBody::upcast(m_rigidCollisionObject); + btScalar dt = btScalar(1.0f/60.0f); + +//#define OLD_WAY +#ifdef OLD_WAY + btScalar radius = btScalar(0.0f); + { + btVector3 aabbMin, aabbMax; + btTransform T; + T.setIdentity(); + rb->getCollisionShape()->getAabb (T, aabbMin, aabbMax); + radius = (aabbMax-aabbMin).length()*btScalar(0.5); + } + btScalar viscosity = btScalar(0.05); + btVector3 force = btScalar(6.0f) * SIMD_PI * viscosity * radius * -rb->getLinearVelocity(); + + btVector3 impulse = force * dt; + rb->applyCentralImpulse (impulse); + + if (true) + { + btVector3 av = rb->getAngularVelocity(); + av *= btScalar(0.99); + rb->setAngularVelocity (av); + } +#else + btScalar scaled_mu = mu * submerged_percentage * btScalar(0.4f); + rb->applyCentralImpulse (dt * scaled_mu * -rb->getLinearVelocity()); + rb->applyTorqueImpulse (dt * scaled_mu * -rb->getAngularVelocity()); +#endif +} + +void btHfFluidRigidCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + processGround (dispatchInfo, resultOut); + btHfFluidBuoyantConvexShape* buoyantShape = (btHfFluidBuoyantConvexShape*)m_rigidCollisionObject->getCollisionShape(); + btRigidBody* rb = btRigidBody::upcast(m_rigidCollisionObject); + if (rb) + { + btScalar mass = btScalar(1.0f) / rb->getInvMass (); + btScalar volume = buoyantShape->getTotalVolume (); + btScalar density = mass / volume; + btScalar floatyness = buoyantShape->getFloatyness (); + btScalar submerged_volume = processFluid (dispatchInfo, density, floatyness); + if (submerged_volume > btScalar(0.0)) + { + btScalar submerged_percentage = submerged_volume/buoyantShape->getTotalVolume(); + //printf("%f\n", submerged_percentage); + btScalar mu = btScalar(6.0f); + applyFluidFriction (mu, submerged_percentage); + } + } +} + +btScalar btHfFluidRigidCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + return btScalar(1.0); +} diff --git a/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidCollisionAlgorithm.h b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidCollisionAlgorithm.h new file mode 100644 index 0000000..a72eb34 --- /dev/null +++ b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidCollisionAlgorithm.h @@ -0,0 +1,81 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ + +#ifndef HF_FLUID_RIGID_COLLISION_ALGORITHM_H +#define HF_FLUID_RIGID_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h" + +#include "LinearMath/btVector3.h" +class btHfFluid; + +///experimental buyancy fluid demo +/// btHfFluidRigidCollisionAlgorithm provides collision detection between btHfFluid and btRigidBody +class btHfFluidRigidCollisionAlgorithm : public btCollisionAlgorithm +{ + btPersistentManifold* m_manifoldPtr; + + btHfFluid* m_hfFluid; + btCollisionObject* m_rigidCollisionObject; + + ///for rigid versus fluid (instead of fluid versus rigid), we use this swapped boolean + bool m_isSwapped; + + btConvexTriangleCallback m_convexTrianglecallback; + + void processGround (const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + void applyFluidFriction (btScalar mu, btScalar submerged_percentage); + btScalar processFluid (const btDispatcherInfo& dispatchInfo, btScalar density, btScalar floatyness); +public: + + btHfFluidRigidCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped); + + virtual ~btHfFluidRigidCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + manifoldArray.push_back (m_manifoldPtr); + } + + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btHfFluidRigidCollisionAlgorithm)); + if (!m_swapped) + { + return new(mem) btHfFluidRigidCollisionAlgorithm(ci,body0,body1,false); + } else + { + return new(mem) btHfFluidRigidCollisionAlgorithm(ci,body0,body1,true); + } + } + }; +}; + +#endif //HF_FLUID_RIGID_COLLISION_ALGORITHM_H diff --git a/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidCollisionConfiguration.cpp b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidCollisionConfiguration.cpp new file mode 100644 index 0000000..f828ec1 --- /dev/null +++ b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidCollisionConfiguration.cpp @@ -0,0 +1,88 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ + +#include "btHfFluidRigidCollisionConfiguration.h" +#include "btHfFluidRigidCollisionAlgorithm.h" +#include "btHfFluidBuoyantShapeCollisionAlgorithm.h" +#include "LinearMath/btPoolAllocator.h" + +btHfFluidRigidCollisionConfiguration::btHfFluidRigidCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo) +:btDefaultCollisionConfiguration(constructionInfo) +{ + void* mem; + + mem = btAlignedAlloc(sizeof(btHfFluidRigidCollisionAlgorithm::CreateFunc),16); + m_hfFluidRigidConvexCreateFunc = new(mem) btHfFluidRigidCollisionAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btHfFluidRigidCollisionAlgorithm::CreateFunc),16); + m_swappedHfFluidRigidConvexCreateFunc = new(mem) btHfFluidRigidCollisionAlgorithm::CreateFunc; + m_swappedHfFluidRigidConvexCreateFunc->m_swapped = true; + + mem = btAlignedAlloc(sizeof(btHfFluidBuoyantShapeCollisionAlgorithm::CreateFunc),16); + m_hfFluidBuoyantShapeCollisionCreateFunc = new(mem) btHfFluidBuoyantShapeCollisionAlgorithm::CreateFunc(m_simplexSolver, m_pdSolver); + + if (m_ownsCollisionAlgorithmPool && m_collisionAlgorithmPool) + { + int curElemSize = m_collisionAlgorithmPool->getElementSize(); + ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool + + int maxSize0 = sizeof(btHfFluidRigidCollisionAlgorithm); + int maxSize1 = 0; + int maxSize2 = 0; + + int collisionAlgorithmMaxElementSize = btMax(maxSize0,maxSize1); + collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2); + + if (collisionAlgorithmMaxElementSize > curElemSize) + { + m_collisionAlgorithmPool->~btPoolAllocator(); + btAlignedFree(m_collisionAlgorithmPool); + void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); + m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize); + } + } +} + +btHfFluidRigidCollisionConfiguration::~btHfFluidRigidCollisionConfiguration() +{ + m_hfFluidRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); + m_swappedHfFluidRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree(m_hfFluidRigidConvexCreateFunc); + btAlignedFree(m_swappedHfFluidRigidConvexCreateFunc); +} + +btCollisionAlgorithmCreateFunc* btHfFluidRigidCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) +{ + if ((proxyType0 == HFFLUID_SHAPE_PROXYTYPE) && (proxyType1 == HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE)) + { + return m_hfFluidRigidConvexCreateFunc; + } + + if ((proxyType0 == HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE) && (proxyType1 == HFFLUID_SHAPE_PROXYTYPE)) + { + return m_swappedHfFluidRigidConvexCreateFunc; + } + + if ((proxyType0 == HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE) && (proxyType1 == HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE)) + { + return m_hfFluidBuoyantShapeCollisionCreateFunc; + } + + ///fallback to the regular rigid collision shape + return btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0,proxyType1); +} + diff --git a/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidCollisionConfiguration.h b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidCollisionConfiguration.h new file mode 100644 index 0000000..7860d58 --- /dev/null +++ b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidCollisionConfiguration.h @@ -0,0 +1,47 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ + +#ifndef BT_HFFLUID_RIGID_COLLISION_CONFIGURATION +#define BT_HFFLUID_RIGID_COLLISION_CONFIGURATION + +#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h" + +class btVoronoiSimplexSolver; +class btGjkEpaPenetrationDepthSolver; + +///experimental buyancy fluid demo +///btSoftBodyRigidBodyCollisionConfiguration add softbody interaction on top of btDefaultCollisionConfiguration +class btHfFluidRigidCollisionConfiguration : public btDefaultCollisionConfiguration +{ + //default CreationFunctions, filling the m_doubleDispatch table + btCollisionAlgorithmCreateFunc* m_hfFluidRigidConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedHfFluidRigidConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_hfFluidBuoyantShapeCollisionCreateFunc; + +public: + + btHfFluidRigidCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo()); + + virtual ~btHfFluidRigidCollisionConfiguration(); + + ///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation + virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); + +}; + +#endif //BT_HFFLUID_RIGID_COLLISION_CONFIGURATION + diff --git a/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidDynamicsWorld.cpp b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidDynamicsWorld.cpp new file mode 100644 index 0000000..79d44b8 --- /dev/null +++ b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidDynamicsWorld.cpp @@ -0,0 +1,273 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ + +#include +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" + +// height field fluid +#include "btHfFluid.h" +#include "btHfFluidBuoyantConvexShape.h" +#include "btHfFluidRigidDynamicsWorld.h" + + + + +btHfFluidRigidDynamicsWorld::btHfFluidRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) +:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration) +{ + m_drawMode = DRAWMODE_NORMAL; + m_bodyDrawMode = BODY_DRAWMODE_NORMAL; +} + +btHfFluidRigidDynamicsWorld::~btHfFluidRigidDynamicsWorld() +{ + +} + +void btHfFluidRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) +{ + btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep); + + for ( int i=0;ipredictMotion(timeStep); + } +} + +void btHfFluidRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep) +{ + btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep ); + + updateFluids (timeStep); + + solveFluidConstraints (timeStep); +} + +void btHfFluidRigidDynamicsWorld::updateFluids(btScalar timeStep) +{ + BT_PROFILE("updateFluids"); + + for ( int i=0;ipredictMotion (timeStep); + } +} + +void btHfFluidRigidDynamicsWorld::solveFluidConstraints(btScalar timeStep) +{ + BT_PROFILE("solve Fluid Contacts"); + +#if 0 + if(m_hfFluids.size()) + { + btHfFluid::solveClusters(m_hfFluids); + } + + for(int i=0;isolveConstraints(); + } +#endif +} + +void btHfFluidRigidDynamicsWorld::addHfFluid(btHfFluid* body) +{ + m_hfFluids.push_back(body); + + btCollisionWorld::addCollisionObject(body, + btBroadphaseProxy::DefaultFilter, + btBroadphaseProxy::AllFilter); + +} + +void btHfFluidRigidDynamicsWorld::removeHfFluid(btHfFluid* body) +{ + m_hfFluids.remove(body); + + btCollisionWorld::removeCollisionObject(body); +} + +void btHfFluidRigidDynamicsWorld::drawHfFluidGround (btIDebugDraw* debugDraw, btHfFluid* fluid) +{ + const btScalar* ground = fluid->getGroundArray (); + btVector3 com = fluid->getWorldTransform().getOrigin(); + btVector3 color = btVector3(btScalar(0.13f), btScalar(0.13f), btScalar(0.0)); + for (int i = 1; i < fluid->getNumNodesWidth()-1; i++) + { + for (int j = 1; j < fluid->getNumNodesLength()-1; j++) + { + int sw = fluid->arrayIndex (i, j); + int se = fluid->arrayIndex (i+1, j); + int nw = fluid->arrayIndex (i, j+1); + int ne = fluid->arrayIndex (i+1, j+1); + btVector3 swV = btVector3 (fluid->widthPos (i), ground[sw], fluid->lengthPos (j)); + btVector3 seV = btVector3 (fluid->widthPos (i+1), ground[se], fluid->lengthPos (j)); + btVector3 nwV = btVector3 (fluid->widthPos (i), ground[nw], fluid->lengthPos (j+1)); + btVector3 neV = btVector3 (fluid->widthPos (i+1), ground[ne], fluid->lengthPos (j+1)); + debugDraw->drawTriangle (swV+com, seV+com, nwV+com, color, btScalar(1.0f)); + debugDraw->drawTriangle (seV+com, neV+com, nwV+com, color, btScalar(1.0f)); + } + } +} + +void btHfFluidRigidDynamicsWorld::drawHfFluidVelocity (btIDebugDraw* debugDraw, btHfFluid* fluid) +{ + btScalar alpha(0.7f); + const btScalar* height = fluid->getHeightArray (); + btVector3 com = fluid->getWorldTransform().getOrigin(); + btVector3 red = btVector3(btScalar(1.0f), btScalar(0.0f), btScalar(0.0)); + btVector3 green = btVector3(btScalar(0.0f), btScalar(1.0f), btScalar(0.0)); + const bool* flags = fluid->getFlagsArray (); + for (int i = 1; i < fluid->getNumNodesWidth()-1; i++) + { + for (int j = 1; j < fluid->getNumNodesLength()-1; j++) + { + int index = fluid->arrayIndex (i, j); + if (!flags[index]) + continue; + btVector3 from = btVector3 (fluid->widthPos (i), height[index]+btScalar(0.1f), fluid->lengthPos (j)); + btVector3 velocity; + velocity.setX (fluid->getVelocityUArray()[index]); + velocity.setY (btScalar(0.0f)); + velocity.setZ (fluid->getVelocityVArray()[index]); + velocity.normalize(); + btVector3 to = from + velocity; + + debugDraw->drawLine (from+com, to+com, red, green); + } + } +} + +void btHfFluidRigidDynamicsWorld::drawHfFluidBuoyantConvexShape (btIDebugDraw* debugDrawer, btCollisionObject* object, btHfFluidBuoyantConvexShape* buoyantShape, int voxelDraw) +{ + if (voxelDraw) + { + btTransform xform = object->getWorldTransform(); + for (int i = 0; i < buoyantShape->getNumVoxels(); i++) + { + btVector3 p = buoyantShape->getVoxelPositionsArray()[i]; + p = xform.getBasis() * p; + p += xform.getOrigin(); + debugDrawer->drawSphere (p, buoyantShape->getVoxelRadius(), btVector3(1.0, 0.0, 0.0)); + } + } else { + btVector3 color(btScalar(255.),btScalar(255.),btScalar(255.)); + switch(object->getActivationState()) + { + case ACTIVE_TAG: + color = btVector3(btScalar(255.),btScalar(255.),btScalar(255.)); break; + case ISLAND_SLEEPING: + color = btVector3(btScalar(0.),btScalar(255.),btScalar(0.));break; + case WANTS_DEACTIVATION: + color = btVector3(btScalar(0.),btScalar(255.),btScalar(255.));break; + case DISABLE_DEACTIVATION: + color = btVector3(btScalar(255.),btScalar(0.),btScalar(0.));break; + case DISABLE_SIMULATION: + color = btVector3(btScalar(255.),btScalar(255.),btScalar(0.));break; + default: + { + color = btVector3(btScalar(255.),btScalar(0.),btScalar(0.)); + } + }; + + btConvexShape* convexShape = ((btHfFluidBuoyantConvexShape*)object->getCollisionShape())->getConvexShape(); + debugDrawObject(object->getWorldTransform(),(btCollisionShape*)convexShape,color); + } +} + +void btHfFluidRigidDynamicsWorld::drawHfFluidNormal (btIDebugDraw* debugDraw, btHfFluid* fluid) +{ + int colIndex = 0; + btVector3 col[2]; + col[0] = btVector3(btScalar(0.0f), btScalar(0.0f), btScalar(1.0)); + col[1] = btVector3(btScalar(0.0f), btScalar(0.5f), btScalar(0.5)); + btScalar alpha(0.7f); + const btScalar* height = fluid->getHeightArray (); + const btScalar* eta = fluid->getEtaArray (); + const btScalar* ground = fluid->getGroundArray (); + btVector3 com = fluid->getWorldTransform().getOrigin(); + const bool* flags = fluid->getFlagsArray (); + for (int i = 0; i < fluid->getNumNodesWidth()-1; i++) + { + for (int j = 0; j < fluid->getNumNodesLength()-1; j++) + { + int sw = fluid->arrayIndex (i, j); + int se = fluid->arrayIndex (i+1, j); + int nw = fluid->arrayIndex (i, j+1); + int ne = fluid->arrayIndex (i+1, j+1); + + btScalar h = eta[sw]; + btScalar g = ground[sw]; + + if (h < btScalar(0.05f)) + continue; + + if (h <= btScalar(0.01f)) + continue; + + btVector3 boxMin = btVector3(fluid->widthPos (i), g, fluid->lengthPos(j)); + btVector3 boxMax = btVector3(fluid->widthPos(i+1), g+h, fluid->lengthPos(j+1)); + boxMin += com; + boxMax += com; + + debugDraw->drawBox (boxMin, boxMax, btVector3(btScalar(0.0f), btScalar(0.0f), btScalar(1.0f))); + } + } +} + +void btHfFluidRigidDynamicsWorld::debugDrawWorld() +{ + if (getDebugDrawer()) + { + int i; + for ( i=0;im_hfFluids.size();i++) + { + btHfFluid* phh=(btHfFluid*)this->m_hfFluids[i]; + switch (m_drawMode) + { + case DRAWMODE_NORMAL: + drawHfFluidGround (m_debugDrawer, phh); + //drawHfFluidNormal (m_debugDrawer, phh); + break; + case DRAWMODE_VELOCITY: + drawHfFluidGround (m_debugDrawer, phh); + //drawHfFluidNormal (m_debugDrawer, phh); + drawHfFluidVelocity (m_debugDrawer, phh); + break; + default: + btAssert (0); + break; + } + } + for (i = 0; i < this->m_collisionObjects.size(); i++) + { + btCollisionShape* shape = m_collisionObjects[i]->getCollisionShape(); + if (shape->getShapeType() == HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE) + { + btHfFluidBuoyantConvexShape* buoyantShape = (btHfFluidBuoyantConvexShape*)shape; + drawHfFluidBuoyantConvexShape (m_debugDrawer, m_collisionObjects[i], buoyantShape, m_bodyDrawMode); + } + } + } + btDiscreteDynamicsWorld::debugDrawWorld(); +} diff --git a/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidDynamicsWorld.h b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidDynamicsWorld.h new file mode 100644 index 0000000..39fb2eb --- /dev/null +++ b/Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluidRigidDynamicsWorld.h @@ -0,0 +1,92 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" + +#ifndef BT_HFFLUID_RIGID_DYNAMICS_WORLD_H +#define BT_HFFLUID_RIGID_DYNAMICS_WORLD_H + +class btHfFluid; +typedef btAlignedObjectArray btHfFluidArray; + +#define DRAWMODE_NORMAL 0 +#define DRAWMODE_VELOCITY 1 +#define DRAWMODE_MAX 2 + +#define BODY_DRAWMODE_NORMAL 0 +#define BODY_DRAWMODE_VOXEL 1 +#define BODY_DRAWMODE_MAX 2 + +class btHfFluidBuoyantConvexShape; + +///experimental buyancy fluid demo +class btHfFluidRigidDynamicsWorld : public btDiscreteDynamicsWorld +{ + + btHfFluidArray m_hfFluids; + int m_drawMode; + int m_bodyDrawMode; +protected: + + virtual void predictUnconstraintMotion(btScalar timeStep); + + virtual void internalSingleStepSimulation( btScalar timeStep); + + void updateFluids(btScalar timeStep); + + void solveFluidConstraints(btScalar timeStep); + + virtual void debugDrawWorld(); + + void drawHfFluidGround (btIDebugDraw* debugDraw, btHfFluid* fluid); + void drawHfFluidVelocity (btIDebugDraw* debugDraw, btHfFluid* fluid); + void drawHfFluidBuoyantConvexShape (btIDebugDraw* debugDrawer, btCollisionObject* object, btHfFluidBuoyantConvexShape* buoyantShape, int voxelDraw); + void drawHfFluidNormal (btIDebugDraw* debugDraw, btHfFluid* fluid); +public: + + btHfFluidRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); + + virtual ~btHfFluidRigidDynamicsWorld(); + + + void addHfFluid(btHfFluid* fluid); + + void removeHfFluid(btHfFluid* fluid); + + void setDrawMode (int drawMode) + { + m_drawMode = drawMode; + } + + void setBodyDrawMode (int bodyDrawMode) + { + m_bodyDrawMode = bodyDrawMode; + } + + btHfFluidArray& getHfFluidArray() + { + return m_hfFluids; + } + + const btHfFluidArray& getHfFluidArray() const + { + return m_hfFluids; + } + +}; + +#endif //BT_HFFLUID_RIGID_DYNAMICS_WORLD_H diff --git a/Demos/HeightFieldFluidDemo/CMakeLists.txt b/Demos/HeightFieldFluidDemo/CMakeLists.txt new file mode 100644 index 0000000..2a28550 --- /dev/null +++ b/Demos/HeightFieldFluidDemo/CMakeLists.txt @@ -0,0 +1,35 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + + +# You shouldn't have to modify anything below this line +######################################################## + + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppHfFluidDemo + HfFluidDemo_GL_ShapeDrawer.cpp + BulletHfFluid/btHfFluid.cpp + BulletHfFluid/btHfFluidBuoyantConvexShape.cpp + BulletHfFluid/btHfFluidBuoyantShapeCollisionAlgorithm.cpp + BulletHfFluid/btHfFluidCollisionShape.cpp + BulletHfFluid/btHfFluidRigidCollisionAlgorithm.cpp + BulletHfFluid/btHfFluidRigidCollisionConfiguration.cpp + BulletHfFluid/btHfFluidRigidDynamicsWorld.cpp + main.cpp + HfFluidDemo.cpp +) + diff --git a/Demos/HeightFieldFluidDemo/HfFluidDemo.cpp b/Demos/HeightFieldFluidDemo/HfFluidDemo.cpp new file mode 100644 index 0000000..1c07777 --- /dev/null +++ b/Demos/HeightFieldFluidDemo/HfFluidDemo.cpp @@ -0,0 +1,1457 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ + +#include "btBulletDynamicsCommon.h" + +#include "BulletHfFluid/btHfFluidRigidDynamicsWorld.h" +#include "BulletHfFluid/btHfFluid.h" +#include "BulletHfFluid/btHfFluidRigidCollisionConfiguration.h" +#include "BulletHfFluid/btHfFluidBuoyantConvexShape.h" +#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btIDebugDraw.h" +#include "LinearMath/btRandom.h" +#include //printf debugging +#include "LinearMath/btConvexHull.h" + +#include "HfFluidDemo.h" +#include "GL_ShapeDrawer.h" +#include "HfFluidDemo_GL_ShapeDrawer.h" + +#include "GlutStuff.h" + +extern float eye[3]; +extern int glutScreenWidth; +extern int glutScreenHeight; + +const int maxProxies = 32766; +const int maxOverlap = 65535; + +static btVector3* gGroundVertices=0; +static int* gGroundIndices=0; +static btBvhTriangleMeshShape* trimeshShape =0; +static btRigidBody* staticBody = 0; +static float waveheight = 5.f; + +const float TRIANGLE_SIZE=8.f; + +#define ARRAY_SIZE_X 1 +#define ARRAY_SIZE_Y 1 +#define ARRAY_SIZE_Z 1 + +//maximum number of objects (and allow user to shoot additional boxes) +#define MAX_PROXIES (ARRAY_SIZE_X*ARRAY_SIZE_Y*ARRAY_SIZE_Z + 1024) + +#define START_POS_X 5 +#define START_POS_Y -5 +#define START_POS_Z 3 + +unsigned int current_draw_mode=DRAWMODE_NORMAL; +unsigned int current_body_draw_mode = 0; +unsigned current_demo=0; + +void Init_Floatyness (HfFluidDemo* fluidDemo) +{ + btHfFluid* fluid = NULL; + + fluid = new btHfFluid (btScalar(0.25), 100, 100); + btTransform xform; + xform.setIdentity (); + xform.getOrigin() = btVector3(btScalar(-10.0), btScalar(-5.0), btScalar(-10.0)); + fluid->setWorldTransform (xform); + fluid->setHorizontalVelocityScale (btScalar(0.0f)); + fluid->setVolumeDisplacementScale (btScalar(0.0f)); + fluidDemo->getHfFluidDynamicsWorld()->addHfFluid (fluid); + + for (int i = 0; i < fluid->getNumNodesLength()*fluid->getNumNodesWidth(); i++) + { + fluid->setFluidHeight(i, btScalar(5.0f)); + } + + fluid->prep (); + + const int numObjects = 5; + btScalar floatyness = btScalar(1.0f); + btScalar dfloatyness = btScalar(0.25f); + btScalar start_x = btScalar(-5.0f); + btScalar step_x = btScalar(3.0f); + btScalar start_z = btScalar(-5.0f); + for (int i = 0; i < numObjects; i++) + { + //btConvexShape* colShape = new btBoxShape(btVector3(1.0, 1.0, 1.0)); + btConvexShape* colShape = new btSphereShape(btScalar(1.)); + btHfFluidBuoyantConvexShape* buoyantShape = new btHfFluidBuoyantConvexShape(colShape); + buoyantShape->generateShape (btScalar(0.25f), btScalar(0.05f)); + buoyantShape->setFloatyness (floatyness + dfloatyness * i); + fluidDemo->m_collisionShapes.push_back (buoyantShape); + + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + + btVector3 localInertia(0,0,0); + colShape->calculateLocalInertia(mass,localInertia); + + btVector3 origin = btVector3(step_x * i + start_x, 7.5f, start_z); + startTransform.setOrigin(origin); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,buoyantShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + fluidDemo->getHfFluidDynamicsWorld()->addRigidBody(body); + } + floatyness = btScalar(2.0f); + start_z = btScalar(5.0f); + for (int i = 0; i < numObjects; i++) + { + //btConvexShape* colShape = new btBoxShape(btVector3(1.0, 1.0, 1.0)); + btConvexShape* colShape = new btSphereShape(btScalar(1.)); + btHfFluidBuoyantConvexShape* buoyantShape = new btHfFluidBuoyantConvexShape(colShape); + buoyantShape->generateShape (btScalar(0.25f), btScalar(0.05f)); + buoyantShape->setFloatyness (floatyness + dfloatyness * i); + fluidDemo->m_collisionShapes.push_back (buoyantShape); + + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + + btVector3 localInertia(0,0,0); + colShape->calculateLocalInertia(mass,localInertia); + + btVector3 origin = btVector3(step_x * i + start_x, -4.0f, start_z); + startTransform.setOrigin(origin); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,buoyantShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + fluidDemo->getHfFluidDynamicsWorld()->addRigidBody(body); + } +} + +void Init_Bowl (HfFluidDemo* fluidDemo) +{ + btHfFluid* fluid = NULL; + + fluid = new btHfFluid (btScalar(1.0), 50, 50); + btTransform xform; + xform.setIdentity (); + xform.getOrigin() = btVector3(btScalar(-10.0), btScalar(-5.0), btScalar(-10.0)); + fluid->setWorldTransform (xform); + fluidDemo->getHfFluidDynamicsWorld()->addHfFluid (fluid); + + btScalar* ground = fluid->getGroundArray(); + btScalar* eta = fluid->getEtaArray(); + btScalar amplitude = btScalar(200.0); + for (int i = 0; i < fluid->getNumNodesWidth(); i++) + { + btScalar x = btScalar(i - fluid->getNumNodesWidth()/2)/btScalar(fluid->getNumNodesWidth()*2); + btScalar xh = amplitude * (x * x) + btScalar(5.0); + for (int j = 0; j < fluid->getNumNodesLength(); j++) + { + btScalar y = btScalar(j - fluid->getNumNodesLength()/2)/btScalar(fluid->getNumNodesLength()*2); + btScalar yh = amplitude * (y * y) + btScalar(5.0); + btScalar gHeight = btMax(xh,yh); + int index = fluid->arrayIndex (i, j); + ground[index] = gHeight; + btScalar wHeight = btScalar(0.0f); + if (gHeight > 14.0) + { + wHeight = btScalar(0.0f); + } else { + wHeight = btScalar(14.0f) - gHeight; + } + eta[index] = wHeight; } + } + + fluid->prep (); + + { + //create a few dynamic rigidbodies + // Re-using the same collision is better for memory usage and performance + + btConvexShape* colShape = new btBoxShape(btVector3(1,1,1)); + btHfFluidBuoyantConvexShape* buoyantShape = new btHfFluidBuoyantConvexShape(colShape); + buoyantShape->generateShape (btScalar(0.25f), btScalar(0.05f)); + //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); + fluidDemo->m_collisionShapes.push_back(colShape); + fluidDemo->m_collisionShapes.push_back (buoyantShape); + + /// Create Dynamic Objects + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + + //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) + colShape->calculateLocalInertia(mass,localInertia); + + float start_x = START_POS_X - ARRAY_SIZE_X/2; + float start_y = START_POS_Y; + float start_z = START_POS_Z - ARRAY_SIZE_Z/2; + + for (int k=0;kgetHfFluidDynamicsWorld()->addRigidBody(body); + } + } + } + } +} + +void Init_Drops (HfFluidDemo* fluidDemo) +{ + btHfFluid* fluid = NULL; + + fluid = new btHfFluid (btScalar(0.5), 50, 50); + btTransform xform; + xform.setIdentity (); + xform.getOrigin() = btVector3(btScalar(-10.0), btScalar(-5.0), btScalar(-10.0)); + fluid->setWorldTransform (xform); + fluidDemo->getHfFluidDynamicsWorld()->addHfFluid (fluid); + + for (int i = 0; i < fluid->getNumNodesLength()*fluid->getNumNodesWidth(); i++) + { + fluid->setFluidHeight(i, btScalar(5.0f)); + } + + fluid->prep (); + { + //create a few dynamic rigidbodies + // Re-using the same collision is better for memory usage and performance + + btConvexShape* colShape = new btBoxShape(btVector3(5,0.5,5)); + btHfFluidBuoyantConvexShape* buoyantShape = new btHfFluidBuoyantConvexShape(colShape); + buoyantShape->generateShape (btScalar(0.25f), btScalar(0.05f)); + //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); + fluidDemo->m_collisionShapes.push_back(colShape); + fluidDemo->m_collisionShapes.push_back (buoyantShape); + + /// Create Dynamic Objects + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + + //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) + colShape->calculateLocalInertia(mass,localInertia); + + float start_x = START_POS_X - ARRAY_SIZE_X/2; + float start_y = START_POS_Y; + float start_z = START_POS_Z - ARRAY_SIZE_Z/2; + + for (int k=0;kgetHfFluidDynamicsWorld()->addRigidBody(body); + } + } + } + } +} + +void Init_Wave (HfFluidDemo* fluidDemo) +{ + btHfFluid* fluid = NULL; + + fluid = new btHfFluid (btScalar(1.0f), 75, 50); + btTransform xform; + xform.setIdentity (); + xform.getOrigin() = btVector3(btScalar(-50.0), btScalar(-5.0), btScalar(-50.0)); + fluid->setWorldTransform (xform); + fluidDemo->getHfFluidDynamicsWorld()->addHfFluid (fluid); + + for (int i = 0; i < fluid->getNumNodesLength()*fluid->getNumNodesWidth(); i++) + { + fluid->getEtaArray()[i] = btScalar(10.0f); + } + + for (int i = 1; i < fluid->getNumNodesWidth()-1; i++) + { + fluid->getEtaArray()[fluid->arrayIndex (i, fluid->getNumNodesLength()/2-1)] = btScalar (2.0); + fluid->getEtaArray()[fluid->arrayIndex (i, fluid->getNumNodesLength()/2)] = btScalar (2.0); + fluid->getEtaArray()[fluid->arrayIndex (i, fluid->getNumNodesLength()/2+1)] = btScalar (2.0); + } + + fluid->prep (); +} + +void Init_RandomDrops (HfFluidDemo* fluidDemo) +{ + btHfFluid* fluid = NULL; + + fluid = new btHfFluid (btScalar(1.0),75, 50); + btTransform xform; + xform.setIdentity (); + xform.getOrigin() = btVector3(btScalar(-50.0), btScalar(-5.0), btScalar(-50.0)); + fluid->setWorldTransform (xform); + fluidDemo->getHfFluidDynamicsWorld()->addHfFluid (fluid); + for (int i = 0; i < fluid->getNumNodesLength()*fluid->getNumNodesWidth(); i++) + { + fluid->getEtaArray()[i] = btScalar(0.0f); + } + fluid->prep (); +} + +void Init_FillPool (HfFluidDemo* fluidDemo) +{ + btHfFluid* fluid = NULL; + const int gridLength = 50; + const int gridWidth = 50; + fluid = new btHfFluid (btScalar(1.0), gridLength, gridWidth); + btTransform xform; + xform.setIdentity (); + xform.getOrigin() = btVector3(btScalar(-20.0), btScalar(-5.0), btScalar(-20.0)); + fluid->setWorldTransform (xform); + fluidDemo->getHfFluidDynamicsWorld()->addHfFluid (fluid); + + btScalar* ground = fluid->getGroundArray(); + btScalar* eta = fluid->getEtaArray(); + + const btScalar poolEdgeHeight = btScalar(10.0f); + const btScalar poolBottomHeight = btScalar(1.0f); + const btScalar poolPourerHeight = btScalar(6.0f); + for (int j = 1; j < fluid->getNumNodesLength()-1; j++) + { + for (int i = 1; i < fluid->getNumNodesWidth()-1; i++) + { + int index = fluid->arrayIndex (i, j); + // pool edge + if (j == 1 || i == 1 || j == fluid->getNumNodesLength()-2 || i == fluid->getNumNodesWidth()-2) + { + ground[index] = poolEdgeHeight; + continue; + } + if (j > 35) + { + if (i <= 25 || i >= 30) + { + ground[index] = poolEdgeHeight; + } else { + ground[index] = poolPourerHeight; + } + continue; + } + ground[index] = poolBottomHeight; + //eta[index] = btScalar(3.0f); + } + } + fluid->prep (); + + { + btConvexShape* colShape = new btBoxShape(btVector3(btScalar(1.), btScalar(1.), btScalar(1.))); + btHfFluidBuoyantConvexShape* buoyantShape = new btHfFluidBuoyantConvexShape(colShape); + buoyantShape->generateShape (btScalar(0.25f), btScalar(0.05f)); + fluidDemo->m_collisionShapes.push_back(colShape); + fluidDemo->m_collisionShapes.push_back(buoyantShape); + + /// Create Dynamic Objects + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + + //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) + colShape->calculateLocalInertia(mass,localInertia); + + int gridSize = 2; + btScalar startPosX = btScalar(-10.0f); + btScalar startPosY = btScalar(2.0f); + btScalar startPosZ = btScalar(-10.f); + float start_x = startPosX - gridSize/2; + float start_y = startPosY; + float start_z = startPosZ - gridSize/2; + + for (int k=0;kgetHfFluidDynamicsWorld()->addRigidBody(body); + } + } + } + } +} + +void Run_FillPool (HfFluidDemo* fluidDemo) +{ + static btScalar dtSinceLastDrop = btScalar(0.0f); + btScalar dt = btScalar(1.0/60.); + btHfFluidArray& fluids = fluidDemo->getHfFluidDynamicsWorld ()->getHfFluidArray (); + btHfFluid* fluid = fluids[0]; + + for (int i = 26; i < 30; i++) + { + fluid->setFluidHeight (i, fluid->getNumNodesLength()-3, btScalar(3.0f)); + } +} + + +void Run_RandomDrops (HfFluidDemo* fluidDemo) +{ + static btScalar dtSinceLastDrop = btScalar(0.0f); + btScalar dt = btScalar(1.0/60.); + + + btHfFluidArray& fluids = fluidDemo->getHfFluidDynamicsWorld ()->getHfFluidArray (); + btHfFluid* fluid = fluids[0]; + + if (dtSinceLastDrop > btScalar(0.5f)) + { + dtSinceLastDrop = btScalar(0.0f); + int randomXNode = GEN_rand () % (fluid->getNumNodesWidth()-2); + int randomZNode = GEN_rand () % (fluid->getNumNodesLength()-2); + if (randomXNode <= 1) + randomXNode = 2; + if (randomZNode <= 1) + randomZNode = 2; + + btScalar* eta = fluid->getEtaArray (); + btScalar* height = fluid->getHeightArray (); + const btScalar* ground = fluid->getGroundArray (); + bool* flags = fluid->getFlagsArray(); + int index = fluid->arrayIndex (randomXNode, randomZNode); + eta[index] += btScalar(4.5f); + eta[index-1] += btScalar(2.25f); + eta[index+1] += btScalar(2.25f); + eta[index+fluid->getNumNodesWidth()] += btScalar(2.25f); + eta[index-fluid->getNumNodesWidth()] += btScalar(2.25f); + height[index] = eta[index] + ground[index]; + height[index-1] = eta[index-1] + ground[index-1]; + height[index+1] = eta[index+1] + ground[index+1]; + height[index+fluid->getNumNodesWidth()] = eta[index+fluid->getNumNodesWidth()] + ground[index+fluid->getNumNodesWidth()]; + height[index-fluid->getNumNodesWidth()] = eta[index-fluid->getNumNodesWidth()] + ground[index-fluid->getNumNodesWidth()]; + flags[index] = true; + flags[index-1] = true; + flags[index+1] = true; + flags[index+fluid->getNumNodesWidth()] = true; + flags[index-fluid->getNumNodesWidth()] = true; + } else { + dtSinceLastDrop += dt; + } +} + +void Init_Fill (HfFluidDemo* fluidDemo) +{ + btHfFluid* fluid = NULL; + + fluid = new btHfFluid (btScalar(1.0f), 75, 50); + btTransform xform; + xform.setIdentity (); + xform.getOrigin() = btVector3(btScalar(-50.0), btScalar(-5.0), btScalar(-50.0)); + fluid->setWorldTransform (xform); + fluidDemo->getHfFluidDynamicsWorld()->addHfFluid (fluid); + for (int i = 0; i < fluid->getNumNodesLength()*fluid->getNumNodesWidth(); i++) + { + fluid->getEtaArray()[i] = btScalar(0.0f); + } + fluid->prep (); +} + +void Run_Fill (HfFluidDemo* fluidDemo) +{ + static btScalar dtSinceLastDrop = btScalar(0.0f); + btScalar dt = btScalar(1.0/60.); + + btHfFluidArray& fluids = fluidDemo->getHfFluidDynamicsWorld ()->getHfFluidArray (); + btHfFluid* fluid = fluids[0]; + + if (dtSinceLastDrop > btScalar(0.25f)) + { + dtSinceLastDrop = btScalar(0.0f); + + btScalar* eta = fluid->getEtaArray (); + btScalar* velocityU = fluid->getVelocityUArray (); + btScalar* velocityV = fluid->getVelocityVArray (); + btScalar* height = fluid->getHeightArray (); + const btScalar* ground = fluid->getGroundArray (); + bool* flags = fluid->getFlagsArray(); + int index = fluid->arrayIndex (fluid->getNumNodesWidth()/2, fluid->getNumNodesLength()/2); + eta[index] += btScalar(4.5f); + eta[index-1] += btScalar(2.25f); + eta[index+1] += btScalar(2.25f); + eta[index+fluid->getNumNodesWidth()] += btScalar(2.25f); + eta[index-fluid->getNumNodesWidth()] += btScalar(2.25f); + + velocityU[index] = btScalar(0.0f); + velocityU[index-1] = btScalar(-10.0f); + velocityU[index+1] = btScalar(10.0f); + velocityU[index+fluid->getNumNodesWidth()] = btScalar(0.0f); + velocityU[index-fluid->getNumNodesWidth()] = btScalar(0.0f); + + velocityV[index] = btScalar(0.0f); + velocityV[index-1] = btScalar(0.0f); + velocityV[index+1] = btScalar(0.0f); + velocityV[index+fluid->getNumNodesWidth()] = btScalar(10.0f); + velocityV[index-fluid->getNumNodesWidth()] = btScalar(-10.0f); + + height[index] = eta[index] + ground[index]; + height[index-1] = eta[index-1] + ground[index-1]; + height[index+1] = eta[index+1] + ground[index+1]; + height[index+fluid->getNumNodesWidth()] = eta[index+fluid->getNumNodesWidth()] + ground[index+fluid->getNumNodesWidth()]; + height[index-fluid->getNumNodesWidth()] = eta[index-fluid->getNumNodesWidth()] + ground[index-fluid->getNumNodesWidth()]; + flags[index] = true; + flags[index-1] = true; + flags[index+1] = true; + flags[index+fluid->getNumNodesWidth()] = true; + flags[index-fluid->getNumNodesWidth()] = true; + } else { + dtSinceLastDrop += dt; + } + +} + +void Init_BlockWave (HfFluidDemo* fluidDemo) +{ + btHfFluid* fluid = NULL; + + fluid = new btHfFluid (btScalar(1.0), 75, 50); + btTransform xform; + xform.setIdentity (); + xform.getOrigin() = btVector3(btScalar(-50.0), btScalar(-5.0), btScalar(-50.0)); + fluid->setWorldTransform (xform); + fluidDemo->getHfFluidDynamicsWorld()->addHfFluid (fluid); + + btScalar* eta = fluid->getEtaArray (); + + for (int i = 0; i < fluid->getNumNodesLength() * fluid->getNumNodesWidth(); i++) + { + eta[i] = btScalar(12.0f); + } + + for (int i = fluid->getNumNodesWidth()/8; i < fluid->getNumNodesWidth()/4; i++) + { + for (int j = fluid->getNumNodesLength()/8; j < fluid->getNumNodesLength()/4; j++) + { + int index = fluid->arrayIndex(i, j); + eta[index] = btScalar(4.0f); + } + } + fluid->prep (); + + { + btConvexShape* colShape = new btSphereShape(btScalar(1.)); + btHfFluidBuoyantConvexShape* buoyantShape = new btHfFluidBuoyantConvexShape(colShape); + buoyantShape->generateShape (btScalar(0.25f), btScalar(0.05f)); + fluidDemo->m_collisionShapes.push_back(buoyantShape); + fluidDemo->m_collisionShapes.push_back(colShape); + + /// Create Dynamic Objects + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + + //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) + colShape->calculateLocalInertia(mass,localInertia); + + int gridSize = 2; + btScalar startPosX = btScalar(-10.0f); + btScalar startPosY = btScalar(2.0f); + btScalar startPosZ = btScalar(-10.f); + float start_x = startPosX - gridSize/2; + float start_y = startPosY; + float start_z = startPosZ - gridSize/2; + + for (int k=0;kgetHfFluidDynamicsWorld()->addRigidBody(body); + } + } + } + } +} + +void Init_Ground (HfFluidDemo* fluidDemo) +{ + btHfFluid* fluid = NULL; + + fluid = new btHfFluid (btScalar(1.0f),75, 50); + btTransform xform; + xform.setIdentity (); + xform.getOrigin() = btVector3(btScalar(-50.0), btScalar(5.0), btScalar(-50.0)); + fluid->setWorldTransform (xform); + fluidDemo->getHfFluidDynamicsWorld()->addHfFluid (fluid); + + btScalar* eta = fluid->getEtaArray (); + + for (int i = 0; i < fluid->getNumNodesLength() * fluid->getNumNodesWidth(); i++) + { + eta[i] = btScalar(4.0f); + } + + btScalar* ground = fluid->getGroundArray (); + for (int i = 0; i < fluid->getNumNodesWidth(); i++) + { + for (int j = 0; j < fluid->getNumNodesLength(); j++) + { + int index = fluid->arrayIndex (i, j); + + if (j <= fluid->getNumNodesLength()/2) + { + + ground[index] = btScalar(5.0f); + } else if (j > (fluid->getNumNodesLength()/8*6)) { + ground[index] = btScalar(0.0f); + } else { + ground[index] = btScalar(6.5f); + } + + if (j <= fluid->getNumNodesLength()/4 && j > fluid->getNumNodesLength()/8) + { + eta[index] = btScalar(8.0f); + } else if (j <= fluid->getNumNodesLength()/8) + { + eta[index] = btScalar(20.0f); + } else { + eta[index] = btScalar(0.0f); + } + + } + } + fluid->prep (); +} + +void Init_Ground2 (HfFluidDemo* fluidDemo) +{ + btHfFluid* fluid = NULL; + + fluid = new btHfFluid (btScalar(1.0f), 75, 50); + btTransform xform; + xform.setIdentity (); + xform.getOrigin() = btVector3(btScalar(-50.0), btScalar(5.0), btScalar(-50.0)); + fluid->setWorldTransform (xform); + fluidDemo->getHfFluidDynamicsWorld()->addHfFluid (fluid); + + btScalar* eta = fluid->getEtaArray (); + + for (int i = 0; i < fluid->getNumNodesLength() * fluid->getNumNodesWidth(); i++) + { + eta[i] = btScalar(4.0f); + } + + btScalar* ground = fluid->getGroundArray (); + for (int i = 0; i < fluid->getNumNodesWidth(); i++) + { + for (int j = 0; j < fluid->getNumNodesLength(); j++) + { + int index = fluid->arrayIndex (i, j); + + ground[index] = (btScalar(j)/fluid->getNumNodesLength()-1)*btScalar(8.0f); + } + } + + for (int i = 0; i < fluid->getNumNodesLength() * fluid->getNumNodesWidth(); i++) + { + eta[i] = btScalar(2.0f); + } + + for (int i = fluid->getNumNodesWidth()/8; i < fluid->getNumNodesWidth()/4; i++) + { + for (int j = fluid->getNumNodesLength()/8; j < fluid->getNumNodesLength()/4; j++) + { + int index = fluid->arrayIndex(i, j); + eta[index] = btScalar(8.0f); + } + } + fluid->prep (); +} + +void Init_Fill2 (HfFluidDemo* fluidDemo) +{ + btHfFluid* fluid = NULL; + + fluid = new btHfFluid (btScalar(1.0), 100, 100); + btTransform xform; + xform.setIdentity (); + xform.getOrigin() = btVector3(btScalar(-50.0), btScalar(-5.0), btScalar(-50.0)); + fluid->setWorldTransform (xform); + fluidDemo->getHfFluidDynamicsWorld()->addHfFluid (fluid); + for (int i = 0; i < fluid->getNumNodesLength()*fluid->getNumNodesWidth(); i++) + { + fluid->getEtaArray()[i] = btScalar(0.0f); + } + fluid->prep (); +} + +void Run_Fill2 (HfFluidDemo* fluidDemo) +{ + static btScalar dtSinceLastDrop = btScalar(0.0f); + btScalar dt = btScalar(1.0/60.); + + btHfFluidArray& fluids = fluidDemo->getHfFluidDynamicsWorld ()->getHfFluidArray (); + btHfFluid* fluid = fluids[0]; + + if (dtSinceLastDrop > btScalar(0.25f)) + { + dtSinceLastDrop = btScalar(0.0f); + + btScalar* eta = fluid->getEtaArray (); + btScalar* velocityU = fluid->getVelocityUArray (); + btScalar* velocityV = fluid->getVelocityVArray (); + btScalar* height = fluid->getHeightArray (); + const btScalar* ground = fluid->getGroundArray (); + bool* flags = fluid->getFlagsArray(); + + for (int i = 1; i < fluid->getNumNodesWidth()-1; i++) + { + int index = fluid->arrayIndex (i, 1); + eta[index] += btScalar(3.0f); + velocityU[index] = btScalar(4.0f); + height[index] = ground[index] + eta[index]; + flags[index] = true; + } + } else { + dtSinceLastDrop += dt; + } + +} + +void Init_MovingPour (HfFluidDemo* fluidDemo) +{ + btHfFluid* fluid = NULL; + + fluid = new btHfFluid (btScalar(1.0),75, 50); + btTransform xform; + xform.setIdentity (); + xform.getOrigin() = btVector3(btScalar(-50.0), btScalar(-5.0), btScalar(-50.0)); + fluid->setWorldTransform (xform); + fluidDemo->getHfFluidDynamicsWorld()->addHfFluid (fluid); + + for (int i = 0; i < fluid->getNumNodesLength()*fluid->getNumNodesWidth(); i++) + { + fluid->getEtaArray()[i] = btScalar(5.0f); + } + + + fluid->prep (); + { + //create a few dynamic rigidbodies + // Re-using the same collision is better for memory usage and performance + + btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1)); + //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); + fluidDemo->m_collisionShapes.push_back(colShape); + + /// Create Dynamic Objects + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + + //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) + colShape->calculateLocalInertia(mass,localInertia); + + float start_x = START_POS_X - ARRAY_SIZE_X/2; + float start_y = START_POS_Y; + float start_z = START_POS_Z - ARRAY_SIZE_Z/2; + + for (int k=0;kgetHfFluidDynamicsWorld()->addRigidBody(body); + } + } + } + } +} + +void Run_MovingPour(HfFluidDemo* fluidDemo) +{ + static btScalar dtSinceLastDrop = btScalar(0.0f); + static btScalar x = 4; + static btScalar z = 4; + static btScalar dx = btScalar(20.0f); + static btScalar dz = btScalar(30.0f); + btScalar dt = btScalar(1.0/60.); + + btHfFluidArray& fluids = fluidDemo->getHfFluidDynamicsWorld ()->getHfFluidArray (); + btHfFluid* fluid = fluids[0]; + + int minX = 2; + int minZ = 2; + int maxX = fluid->getNumNodesWidth() - 2; + int maxZ = fluid->getNumNodesLength() - 2; + + x += dx * dt; + + if (x <= minX) + { + dx *= btScalar(-1.0f); + x = minX; + } else if (x >= maxX) { + dx *= btScalar(-1.0f); + x = maxX; + } + z += dz * dt; + + if (z <= minZ) + { + dz *= btScalar(-1.0f); + z = minZ; + } else if (z >= maxZ) { + dz *= btScalar(-1.0f); + z = maxZ; + } + + const btScalar dropHeight = btScalar(3.0f); + + { + int iX = (int)x; + int iZ = (int)z; + fluid->addFluidHeight (iX,iZ, dropHeight); + //fluid->addFluidHeight (x, z+1, dropHeight); + //fluid->addFluidHeight (x+1, z, dropHeight); + //fluid->addFluidHeight (x+1, z+1, dropHeight); + } +} + +#define NUM_DEMOS 12 + +void (*demo_run_functions[NUM_DEMOS])(HfFluidDemo*)= +{ + NULL, // Run_Floatyness + NULL, // Run_Bowl + Run_FillPool, //Run_FillPool + NULL, // Run_Drops + NULL, // Run_Wave + Run_RandomDrops, + Run_Fill, + Run_Fill2, + NULL, // Run_BlockWave + NULL, // Run_Ground + NULL, // Run_Ground2 + Run_MovingPour, +}; +void (*demo_init_functions[NUM_DEMOS])(HfFluidDemo*)= +{ + Init_Floatyness, + Init_Bowl, + Init_FillPool, + Init_Drops, + Init_Wave, + Init_RandomDrops, + Init_Fill, + Init_Fill2, + Init_BlockWave, + Init_Ground, + Init_Ground2, + Init_MovingPour, +}; + +btScalar g_ele_array[NUM_DEMOS] = { + btScalar(10), + btScalar(45), + btScalar(35), + btScalar(35), + btScalar(10), + btScalar(10), + btScalar(35), + btScalar(45), + btScalar(35), + btScalar(20), + btScalar(20), +}; + +btScalar g_azi_array[NUM_DEMOS] = { + btScalar(0), + btScalar(55), + btScalar(245), + btScalar(270), + btScalar(55), + btScalar(55), + btScalar(180), + btScalar(205), + btScalar(255), + btScalar(305), + btScalar(305), +}; + +btScalar g_cameraDistance_array[NUM_DEMOS] = { + btScalar(20), + btScalar(29), + btScalar(43), + btScalar(26), + btScalar(77), + btScalar(77), + btScalar(77), + btScalar(32), + btScalar(62), + btScalar(70), + btScalar(70), +}; + +#ifdef _DEBUG +const int gNumObjects = 1; +#else +const int gNumObjects = 1;//try this in release mode: 3000. never go above 16384, unless you increate maxNumObjects value in DemoApplication.cp +#endif + +const int maxNumObjects = 32760; + +#define CUBE_HALF_EXTENTS 1.5 +#define EXTRA_HEIGHT -10.f + +// +void HfFluidDemo::createStack( btCollisionShape* boxShape, float halfCubeSize, int size, float zPos ) +{ + btTransform trans; + trans.setIdentity(); + + for(int i=0; igenerateShape (btScalar(0.25f), btScalar(0.05f)); + m_shootBoxShape = buoyantShape; + } +} + +//////////////////////////////////// + +extern int gNumManifold; +extern int gOverlappingPairs; + +void HfFluidDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); + + + float dt = 1.0/60.; + + if (m_dynamicsWorld) + { + if (demo_run_functions[current_demo]) + { + demo_run_functions[current_demo](this); + } + } + + if (m_dynamicsWorld) + { + if(m_drag) + { + const int x=m_lastmousepos[0]; + const int y=m_lastmousepos[1]; + const btVector3 rayFrom=m_cameraPosition; + const btVector3 rayTo=getRayTo(x,y); + const btVector3 rayDir=(rayTo-rayFrom).normalized(); + const btVector3 N=(m_cameraTargetPosition-m_cameraPosition).normalized(); + const btScalar O=btDot(m_impact,N); + const btScalar den=btDot(N,rayDir); + if((den*den)>0) + { + const btScalar num=O-btDot(N,rayFrom); + const btScalar hit=num/den; + if((hit>0)&&(hit<1500)) + { + m_goal=rayFrom+rayDir*hit; + } + } + btVector3 delta; + static const btScalar maxdrag=10; + if(delta.length2()>(maxdrag*maxdrag)) + { + delta=delta.normalized()*maxdrag; + } + } + +#define FIXED_STEP +#ifdef FIXED_STEP + m_dynamicsWorld->stepSimulation(dt=1.0f/60.f,0); + +#else + //during idle mode, just run 1 simulation step maximum, otherwise 4 at max + int maxSimSubSteps = m_idle ? 1 : 4; + //if (m_idle) + // dt = 1.0/420.f; + + int numSimSteps; + numSimSteps = m_dynamicsWorld->stepSimulation(dt); + +#ifdef VERBOSE_TIMESTEPPING_CONSOLEOUTPUT + if (!numSimSteps) + printf("Interpolated transforms\n"); + else + { + if (numSimSteps > maxSimSubSteps) + { + //detect dropping frames + printf("Dropped (%i) simulation steps out of %i\n",numSimSteps - maxSimSubSteps,numSimSteps); + } else + { + printf("Simulated (%i) steps\n",numSimSteps); + } + } +#endif //VERBOSE_TIMESTEPPING_CONSOLEOUTPUT + +#endif + + //optional but useful: debug drawing + + } + +#ifdef USE_QUICKPROF + btProfiler::beginBlock("render"); +#endif //USE_QUICKPROF + + renderme(); + + //render the graphics objects, with center of mass shift + + updateCamera(); + + + +#ifdef USE_QUICKPROF + btProfiler::endBlock("render"); +#endif + glFlush(); + //some additional debugging info +#ifdef PRINT_CONTACT_STATISTICS + printf("num manifolds: %i\n",gNumManifold); + printf("num gOverlappingPairs: %i\n",gOverlappingPairs); + printf("num gTotalContactPoints : %i\n",gTotalContactPoints ); +#endif //PRINT_CONTACT_STATISTICS + + //gTotalContactPoints = 0; + glutSwapBuffers(); + +} + + + +void HfFluidDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + + renderme(); + + glFlush(); + glutSwapBuffers(); +} + + + + +void HfFluidDemo::clientResetScene() +{ + DemoApplication::clientResetScene(); + /* Clean up */ + for(int 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(); + } + while(m_dynamicsWorld->getNumConstraints()) + { + btTypedConstraint* pc=m_dynamicsWorld->getConstraint(0); + m_dynamicsWorld->removeConstraint(pc); + delete pc; + } + btHfFluid* hfFluid = btHfFluid::upcast(obj); + if (hfFluid) + { + getHfFluidDynamicsWorld()->removeHfFluid(hfFluid); + } else + { + m_dynamicsWorld->removeCollisionObject(obj); + } + delete obj; + } + + /* Init */ + + + m_autocam = false; + m_raycast = false; + m_cutting = false; + printf("current_demo = %d\n", current_demo); + m_azi = g_azi_array[current_demo]; + m_ele = g_ele_array[current_demo]; + m_cameraDistance = g_cameraDistance_array[current_demo]; + updateCamera(); + demo_init_functions[current_demo](this); +} + +void HfFluidDemo::renderme() +{ + btIDebugDraw* idraw=m_dynamicsWorld->getDebugDrawer(); + + m_dynamicsWorld->debugDrawWorld(); + + /* Bodies */ + btVector3 ps(0,0,0); + int nps=0; + + DemoApplication::renderme(); +} + + +void HfFluidDemo::keyboardCallback(unsigned char key, int x, int y) +{ + switch(key) + { + case ']': + current_demo = (current_demo+1)%NUM_DEMOS; + clientResetScene(); + break; + case '[': + current_demo = (current_demo-1)%NUM_DEMOS; + clientResetScene(); + break; + case '.': + current_draw_mode = (current_draw_mode+1) % DRAWMODE_MAX; + getHfFluidDynamicsWorld()->setDrawMode (current_draw_mode); + break; + case 'v': + current_body_draw_mode = (current_body_draw_mode+1) % BODY_DRAWMODE_MAX; + getHfFluidDynamicsWorld()->setBodyDrawMode (current_body_draw_mode); + break; + default: + DemoApplication::keyboardCallback(key,x,y); + break; + } +} + +// +void HfFluidDemo::mouseMotionFunc(int x,int y) +{ + DemoApplication::mouseMotionFunc(x,y); +} + +// +void HfFluidDemo::mouseFunc(int button, int state, int x, int y) +{ +if(button==0) + { + switch(state) + { + case 0: + { + DemoApplication::mouseFunc(button,state,x,y); + } + break; + case 1: + DemoApplication::mouseFunc(button,state,x,y); + break; + } + } + else + { + DemoApplication::mouseFunc(button,state,x,y); + } +} + + +void HfFluidDemo::initPhysics() +{ +///create concave ground mesh + + btCollisionShape* groundShape = 0; + bool useConcaveMesh = false;//not ready yet true; + + if (useConcaveMesh) + { + int i; + int j; + + const int NUM_VERTS_X = 30; + const int NUM_VERTS_Y = 30; + const int totalVerts = NUM_VERTS_X*NUM_VERTS_Y; + const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1); + + gGroundVertices = new btVector3[totalVerts]; + gGroundIndices = new int[totalTriangles*3]; + + btScalar offset(-50); + + for ( i=0;iaddChildShape(localTransform,cylinderShape); + btQuaternion orn(btVector3(0,1,0),SIMD_PI); + localTransform.setRotation(orn); + cylinderCompound->addChildShape(localTransform,cylinderShape); + + m_collisionShapes.push_back(cylinderCompound); + + + m_dispatcher=0; + + /* FIXME: Register new collision algorithm */ + ///register some softbody collision algorithms on top of the default btDefaultCollisionConfiguration + m_collisionConfiguration = new btHfFluidRigidCollisionConfiguration(); + + + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + + //////////////////////////// + ///Register HfFluid versus rigidbody collision algorithm + + + btVector3 worldAabbMin(-1000,-1000,-1000); + btVector3 worldAabbMax(1000,1000,1000); + + m_broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies); + + btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver(); + + m_solver = solver; + + btDiscreteDynamicsWorld* world = new btHfFluidRigidDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + m_dynamicsWorld = world; + + + m_dynamicsWorld->getDispatchInfo().m_enableSPU = true; + m_dynamicsWorld->setGravity(btVector3(0,-10,0)); + + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(0,-12,0)); + + + + localCreateRigidBody(0.f,tr,m_collisionShapes[0]); + + + // clientResetScene(); + + clientResetScene(); +} + + + + + + +void HfFluidDemo::exitPhysics() +{ + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;j m_FluidRigidCollisionAlgorithms; + + + bool m_autocam; + bool m_cutting; + bool m_raycast; + btScalar m_animtime; + btClock m_clock; + int m_lastmousepos[2]; + btVector3 m_impact; + btVector3 m_goal; + bool m_drag; + + + //keep the collision shapes, for deletion/cleanup + btAlignedObjectArray m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + + btConstraintSolver* m_solver; + + btCollisionAlgorithmCreateFunc* m_boxBoxCF; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + +public: + + void initPhysics(); + + void exitPhysics(); + + HfFluidDemo (); + + virtual ~HfFluidDemo() + { + exitPhysics(); + } + + virtual void setDrawClusters(bool drawClusters) + { + + } + + virtual void setShootBoxShape (); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + void createStack( btCollisionShape* boxShape, float halfCubeSize, int size, float zPos ); + + static DemoApplication* Create() + { + HfFluidDemo* demo = new HfFluidDemo; + demo->myinit(); + demo->initPhysics(); + return demo; + } + + virtual const btHfFluidRigidDynamicsWorld* getHfFluidDynamicsWorld() const + { + ///just make it a btSoftRigidDynamicsWorld please + ///or we will add type checking + return (btHfFluidRigidDynamicsWorld*) m_dynamicsWorld; + } + + virtual btHfFluidRigidDynamicsWorld* getHfFluidDynamicsWorld() + { + ///just make it a btSoftRigidDynamicsWorld please + ///or we will add type checking + return (btHfFluidRigidDynamicsWorld*) m_dynamicsWorld; + } + + // + void clientResetScene(); + void renderme(); + void keyboardCallback(unsigned char key, int x, int y); + void mouseFunc(int button, int state, int x, int y); + void mouseMotionFunc(int x,int y); + +}; + +#define MACRO_SOFT_DEMO(a) class HfFluidDemo##a : public HfFluidDemo\ +{\ +public:\ + static DemoApplication* Create()\ + {\ + HfFluidDemo* demo = new HfFluidDemo##a;\ + extern unsigned int current_demo;\ + current_demo=a;\ + demo->myinit();\ + demo->initPhysics();\ + return demo;\ + }\ +}; + + +MACRO_SOFT_DEMO(0) //Init_Drops +MACRO_SOFT_DEMO(1) //Init_Wave +MACRO_SOFT_DEMO(2) //Init_RandomDrops +MACRO_SOFT_DEMO(3) + +#endif //CCD_PHYSICS_DEMO_H + + + + + diff --git a/Demos/HeightFieldFluidDemo/HfFluidDemo_GL_ShapeDrawer.cpp b/Demos/HeightFieldFluidDemo/HfFluidDemo_GL_ShapeDrawer.cpp new file mode 100644 index 0000000..33f2e03 --- /dev/null +++ b/Demos/HeightFieldFluidDemo/HfFluidDemo_GL_ShapeDrawer.cpp @@ -0,0 +1,606 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ + +#ifdef _WIN32 //needed for glut.h +#include +#endif + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#else +#include +#endif + +#include "GlutStuff.h" +#include "HfFluidDemo_GL_ShapeDrawer.h" + +#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" +#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btConeShape.h" +#include "BulletCollision/CollisionShapes/btCylinderShape.h" +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btUniformScalingShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" +/// +#include "BulletCollision/CollisionShapes/btShapeHull.h" +#include "BulletHfFluid/btHfFluidBuoyantConvexShape.h" +#include "BulletHfFluid/btHfFluid.h" +#include "BulletHfFluid/btHfFluidCollisionShape.h" + +#include "LinearMath/btTransformUtil.h" + + +#include "LinearMath/btIDebugDraw.h" +//for debugmodes +#include //printf debugging + +#include + +using namespace std; + + +class GlDrawcallback : public btTriangleCallback +{ + +public: + + bool m_wireframe; + + GlDrawcallback() + :m_wireframe(false) + { + } + + virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex) + { + + (void)triangleIndex; + (void)partId; + + + if (m_wireframe) + { + glBegin(GL_LINES); + glColor3f(1, 0, 0); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glColor3f(0, 1, 0); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glColor3f(0, 0, 1); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glEnd(); + } else + { + glBegin(GL_TRIANGLES); + //glColor3f(1, 1, 1); + + + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glEnd(); + } + } +}; + +class TriangleGlDrawcallback : public btInternalTriangleIndexCallback +{ +public: + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + (void)triangleIndex; + (void)partId; + + + glBegin(GL_TRIANGLES);//LINES); + glColor3f(1, 0, 0); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glColor3f(0, 1, 0); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glColor3f(0, 0, 1); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glEnd(); + } +}; + + + +void HfFluidDemo_GL_ShapeDrawer::drawOpenGL(btScalar* m, const btCollisionShape* shape, const btVector3& color,int debugMode,const btVector3& worldBoundsMin,const btVector3& worldBoundsMax) +{ + + + glPushMatrix(); + btglMultMatrix(m); + + if (shape->getShapeType() == UNIFORM_SCALING_SHAPE_PROXYTYPE) + { + const btUniformScalingShape* scalingShape = static_cast(shape); + const btConvexShape* convexShape = scalingShape->getChildShape(); + float scalingFactor = (float)scalingShape->getUniformScalingFactor(); + { + btScalar tmpScaling[4][4]={{scalingFactor,0,0,0}, + {0,scalingFactor,0,0}, + {0,0,scalingFactor,0}, + {0,0,0,1}}; + + drawOpenGL( (btScalar*)tmpScaling,convexShape,color,debugMode,worldBoundsMin,worldBoundsMax); + } + glPopMatrix(); + return; + } + + if (shape->getShapeType() == HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE) + { + btConvexShape* convexShape = ((btHfFluidBuoyantConvexShape*)shape)->getConvexShape(); + btTransform I; + I.setIdentity(); + btScalar mat[16]; + I.getOpenGLMatrix (&mat[0]); + drawOpenGL (mat, convexShape, color, debugMode, worldBoundsMin, worldBoundsMax); + return; + } + + if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) + { + const btCompoundShape* compoundShape = static_cast(shape); + for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* colShape = compoundShape->getChildShape(i); + btScalar childMat[16]; + childTrans.getOpenGLMatrix(childMat); + drawOpenGL(childMat,colShape,color,debugMode,worldBoundsMin,worldBoundsMax); + + } + + } else + { + if(m_textureenabled&&(!m_textureinitialized)) + { + GLubyte* image=new GLubyte[256*256*3]; + for(int y=0;y<256;++y) + { + const int t=y>>4; + GLubyte* pi=image+y*256*3; + for(int x=0;x<256;++x) + { + const int s=x>>4; + const GLubyte b=180; + GLubyte c=b+((s+t&1)&1)*(255-b); + pi[0]=pi[1]=pi[2]=c;pi+=3; + } + } + glGenTextures(1,(GLuint*)&m_texturehandle); + glBindTexture(GL_TEXTURE_2D,m_texturehandle); + glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); + gluBuild2DMipmaps(GL_TEXTURE_2D,3,256,256,GL_RGB,GL_UNSIGNED_BYTE,image); + delete[] image; + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glScalef(0.025,0.025,0.025); + + static const GLfloat planex[]={1,0,0,0}; + static const GLfloat planey[]={0,1,0,0}; + static const GLfloat planez[]={0,0,1,0}; + glTexGenfv(GL_S,GL_OBJECT_PLANE,planex); + glTexGenfv(GL_T,GL_OBJECT_PLANE,planez); + glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR); + glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + m_textureinitialized=true; + } + //drawCoordSystem(); + + //glPushMatrix(); + glEnable(GL_COLOR_MATERIAL); + if(m_textureenabled) + { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,m_texturehandle); + } else + { + glDisable(GL_TEXTURE_2D); + } + + + glColor3f(color.x(),color.y(), color.z()); + + bool useWireframeFallback = true; + + if (!(debugMode & btIDebugDraw::DBG_DrawWireframe)) + { + ///you can comment out any of the specific cases, and use the default + ///the benefit of 'default' is that it approximates the actual collision shape including collision margin + int shapetype=m_textureenabled?MAX_BROADPHASE_COLLISION_TYPES:shape->getShapeType(); + switch (shapetype) + { + case BOX_SHAPE_PROXYTYPE: + { + const btBoxShape* boxShape = static_cast(shape); + btVector3 halfExtent = boxShape->getHalfExtentsWithMargin(); + glScaled(2*halfExtent[0], 2*halfExtent[1], 2*halfExtent[2]); + glutSolidCube(1.0); + useWireframeFallback = false; + break; + } + + + case SPHERE_SHAPE_PROXYTYPE: + { + const btSphereShape* sphereShape = static_cast(shape); + float radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin + glutSolidSphere(radius,10,10); + useWireframeFallback = false; + break; + } + + case CONE_SHAPE_PROXYTYPE: + { + const btConeShape* coneShape = static_cast(shape); + int upIndex = coneShape->getConeUpIndex(); + float radius = coneShape->getRadius();//+coneShape->getMargin(); + float height = coneShape->getHeight();//+coneShape->getMargin(); + switch (upIndex) + { + case 0: + glRotatef(90.0, 0.0, 1.0, 0.0); + break; + case 1: + glRotatef(-90.0, 1.0, 0.0, 0.0); + break; + case 2: + break; + default: + { + } + }; + + glTranslatef(0.0, 0.0, -0.5*height); + glutSolidCone(radius,height,10,10); + useWireframeFallback = false; + break; + + } + + + case STATIC_PLANE_PROXYTYPE: + { + const btStaticPlaneShape* staticPlaneShape = static_cast(shape); + btScalar planeConst = staticPlaneShape->getPlaneConstant(); + const btVector3& planeNormal = staticPlaneShape->getPlaneNormal(); + btVector3 planeOrigin = planeNormal * planeConst; + btVector3 vec0,vec1; + btPlaneSpace1(planeNormal,vec0,vec1); + btScalar vecLen = 100.f; + btVector3 pt0 = planeOrigin + vec0*vecLen; + btVector3 pt1 = planeOrigin - vec0*vecLen; + btVector3 pt2 = planeOrigin + vec1*vecLen; + btVector3 pt3 = planeOrigin - vec1*vecLen; + glBegin(GL_LINES); + glVertex3f(pt0.getX(),pt0.getY(),pt0.getZ()); + glVertex3f(pt1.getX(),pt1.getY(),pt1.getZ()); + glVertex3f(pt2.getX(),pt2.getY(),pt2.getZ()); + glVertex3f(pt3.getX(),pt3.getY(),pt3.getZ()); + glEnd(); + + + break; + + } + + case CYLINDER_SHAPE_PROXYTYPE: + { + const btCylinderShape* cylinder = static_cast(shape); + int upAxis = cylinder->getUpAxis(); + + + float radius = cylinder->getRadius(); + float halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis]; + + drawCylinder(radius,halfHeight,upAxis); + + break; + } + + default: + { + + + if (shape->isConvex()) + { + ShapeCache* sc=cache((btConvexShape*)shape); + + //if (shape->getUserPointer()) + { + //glutSolidCube(1.0); + btShapeHull* hull = &sc->m_shapehull/*(btShapeHull*)shape->getUserPointer()*/; + + + if (hull->numTriangles () > 0) + { + int index = 0; + const unsigned int* idx = hull->getIndexPointer(); + const btVector3* vtx = hull->getVertexPointer(); + + glBegin (GL_TRIANGLES); + + for (int i = 0; i < hull->numTriangles (); i++) + { + int i1 = index++; + int i2 = index++; + int i3 = index++; + btAssert(i1 < hull->numIndices () && + i2 < hull->numIndices () && + i3 < hull->numIndices ()); + + int index1 = idx[i1]; + int index2 = idx[i2]; + int index3 = idx[i3]; + btAssert(index1 < hull->numVertices () && + index2 < hull->numVertices () && + index3 < hull->numVertices ()); + + btVector3 v1 = vtx[index1]; + btVector3 v2 = vtx[index2]; + btVector3 v3 = vtx[index3]; + btVector3 normal = (v3-v1).cross(v2-v1); + normal.normalize (); + + glNormal3f(normal.getX(),normal.getY(),normal.getZ()); + glVertex3f (v1.x(), v1.y(), v1.z()); + glVertex3f (v2.x(), v2.y(), v2.z()); + glVertex3f (v3.x(), v3.y(), v3.z()); + + } + glEnd (); + + } + } + } + } + } + + } + + + + + /// for polyhedral shapes + if (debugMode==btIDebugDraw::DBG_DrawFeaturesText && (shape->isPolyhedral())) + { + btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape; + + { + glRasterPos3f(0.0, 0.0, 0.0); + //BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),polyshape->getExtraDebugInfo()); + + glColor3f(1.f, 1.f, 1.f); + int i; + for (i=0;igetNumVertices();i++) + { + btVector3 vtx; + polyshape->getVertex(i,vtx); + glRasterPos3f(vtx.x(), vtx.y(), vtx.z()); + char buf[12]; + sprintf(buf," %d",i); +// BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); + } + + for (i=0;igetNumPlanes();i++) + { + btVector3 normal; + btVector3 vtx; + polyshape->getPlane(normal,vtx,i); + btScalar d = vtx.dot(normal); + + glRasterPos3f(normal.x()*d, normal.y()*d, normal.z()*d); + char buf[12]; + sprintf(buf," plane %d",i); +// BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); + + } + } + + } + + +#ifdef USE_DISPLAY_LISTS + + if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE||shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE) + { + GLuint dlist = OGL_get_displaylist_for_shape((btCollisionShape * )shape); + if (dlist) + { + glCallList(dlist); + } + else + { +#else + if (shape->isConcave())//>getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE||shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE) + // if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + btConcaveShape* concaveMesh = (btConcaveShape*) shape; + + GlDrawcallback drawCallback; + drawCallback.m_wireframe = (debugMode & btIDebugDraw::DBG_DrawWireframe)!=0; + + concaveMesh->processAllTriangles(&drawCallback,worldBoundsMin,worldBoundsMax); + + } + if (shape->getShapeType() == HFFLUID_SHAPE_PROXYTYPE) + { + btHfFluidCollisionShape* hfFluidShape = (btHfFluidCollisionShape*)shape; + btHfFluid* fluid = hfFluidShape->m_fluid; + + GlDrawcallback drawCallback; + drawCallback.m_wireframe = (debugMode & btIDebugDraw::DBG_DrawWireframe) != 0; + fluid->foreachSurfaceTriangle (&drawCallback, worldBoundsMin, worldBoundsMax); + } +#endif + +#ifdef USE_DISPLAY_LISTS + } +} +#endif + +/* +if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE) +{ +btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*) shape; + +//todo: pass camera for some culling +btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); +btVector3 aabbMin(-btScalar(BT_LARGE_FLOAT),-btScalar(BT_LARGE_FLOAT),-btScalar(BT_LARGE_FLOAT)); +TriangleGlDrawcallback drawCallback; +convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); + +} +*/ + + + +glDisable(GL_DEPTH_TEST); +glRasterPos3f(0,0,0);//mvtx.x(), vtx.y(), vtx.z()); +if (debugMode&btIDebugDraw::DBG_DrawText) +{ +// BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),shape->getName()); +} + +if (debugMode& btIDebugDraw::DBG_DrawFeaturesText) +{ + //BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),shape->getExtraDebugInfo()); +} +glEnable(GL_DEPTH_TEST); + +// glPopMatrix(); +if(m_textureenabled) glDisable(GL_TEXTURE_2D); + } + glPopMatrix(); + +} + +// +void HfFluidDemo_GL_ShapeDrawer::drawShadow(btScalar* m,const btVector3& extrusion,const btCollisionShape* shape,const btVector3& worldBoundsMin,const btVector3& worldBoundsMax) +{ + glPushMatrix(); + btglMultMatrix(m); + if(shape->getShapeType() == UNIFORM_SCALING_SHAPE_PROXYTYPE) + { + const btUniformScalingShape* scalingShape = static_cast(shape); + const btConvexShape* convexShape = scalingShape->getChildShape(); + float scalingFactor = (float)scalingShape->getUniformScalingFactor(); + btScalar tmpScaling[4][4]={ {scalingFactor,0,0,0}, + {0,scalingFactor,0,0}, + {0,0,scalingFactor,0}, + {0,0,0,1}}; + drawShadow((btScalar*)tmpScaling,extrusion,convexShape,worldBoundsMin,worldBoundsMax); + glPopMatrix(); + return; + } + else if(shape->getShapeType()==COMPOUND_SHAPE_PROXYTYPE) + { + const btCompoundShape* compoundShape = static_cast(shape); + for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* colShape = compoundShape->getChildShape(i); + btScalar childMat[16]; + childTrans.getOpenGLMatrix(childMat); + drawShadow(childMat,extrusion*childTrans.getBasis(),colShape,worldBoundsMin,worldBoundsMax); + } + } + else + { + bool useWireframeFallback = true; + if (shape->isConvex()) + { + ShapeCache* sc=cache((btConvexShape*)shape); + btShapeHull* hull =&sc->m_shapehull; + glBegin(GL_QUADS); + for(int i=0;im_edges.size();++i) + { + const btScalar d=btDot(sc->m_edges[i].n[0],extrusion); + if((d*btDot(sc->m_edges[i].n[1],extrusion))<0) + { + const int q= d<0?1:0; + const btVector3& a= hull->getVertexPointer()[sc->m_edges[i].v[q]]; + const btVector3& b= hull->getVertexPointer()[sc->m_edges[i].v[1-q]]; + glVertex3f(a[0],a[1],a[2]); + glVertex3f(b[0],b[1],b[2]); + glVertex3f(b[0]+extrusion[0],b[1]+extrusion[1],b[2]+extrusion[2]); + glVertex3f(a[0]+extrusion[0],a[1]+extrusion[1],a[2]+extrusion[2]); + } + } + glEnd(); + } + + } + + + + + if (shape->isConcave())//>getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE||shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE) + // if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + btConcaveShape* concaveMesh = (btConcaveShape*) shape; + + GlDrawcallback drawCallback; + drawCallback.m_wireframe = false; + + concaveMesh->processAllTriangles(&drawCallback,worldBoundsMin,worldBoundsMax); + + } + glPopMatrix(); + +} + +// +HfFluidDemo_GL_ShapeDrawer::HfFluidDemo_GL_ShapeDrawer() +{ + m_texturehandle = 0; + m_textureenabled = true; + m_textureinitialized = false; +} + +HfFluidDemo_GL_ShapeDrawer::~HfFluidDemo_GL_ShapeDrawer() +{ +} + diff --git a/Demos/HeightFieldFluidDemo/HfFluidDemo_GL_ShapeDrawer.h b/Demos/HeightFieldFluidDemo/HfFluidDemo_GL_ShapeDrawer.h new file mode 100644 index 0000000..6d4a2a0 --- /dev/null +++ b/Demos/HeightFieldFluidDemo/HfFluidDemo_GL_ShapeDrawer.h @@ -0,0 +1,37 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ + +#ifndef HFFLUID_GL_SHAPE_DRAWER_H +#define HFFLUID_GL_SHAPE_DRAWER_H + +#include "GL_ShapeDrawer.h" + +///experimental buyancy fluid demo +/// OpenGL shape drawing +class HfFluidDemo_GL_ShapeDrawer : public GL_ShapeDrawer +{ + public: + HfFluidDemo_GL_ShapeDrawer(); + + virtual ~HfFluidDemo_GL_ShapeDrawer(); + + ///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); + virtual void drawShadow(btScalar* m, const btVector3& extrusion,const btCollisionShape* shape,const btVector3& worldBoundsMin,const btVector3& worldBoundsMax); +}; + +#endif //HFFLUID_GL_SHAPE_DRAWER_H diff --git a/Demos/HeightFieldFluidDemo/main.cpp b/Demos/HeightFieldFluidDemo/main.cpp new file mode 100644 index 0000000..eb72aad --- /dev/null +++ b/Demos/HeightFieldFluidDemo/main.cpp @@ -0,0 +1,39 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.com + +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. + +Experimental Buoyancy fluid demo written by John McCutchan +*/ + +#include "HfFluidDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" + +GLDebugDrawer gDebugDrawer; + +int main(int argc,char** argv) +{ + + HfFluidDemo* fluidDemo = new HfFluidDemo(); + + fluidDemo->initPhysics(); + fluidDemo->getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + + glutmain(argc, argv,640,480,"Bullet Physics Demo. http://bulletphysics.com",fluidDemo); + + delete fluidDemo; + return 0; + +} diff --git a/Demos/HelloWorld/CMakeLists.txt b/Demos/HelloWorld/CMakeLists.txt new file mode 100644 index 0000000..59eee2d --- /dev/null +++ b/Demos/HelloWorld/CMakeLists.txt @@ -0,0 +1,29 @@ +# HelloWorld is a minimal sample creating, stepping and deleting a Bullet dynamics world + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +) + +LINK_LIBRARIES( + BulletDynamics BulletCollision LinearMath +) + +IF (WIN32) + ADD_EXECUTABLE(AppHelloWorld + HelloWorld.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) +ELSE() + ADD_EXECUTABLE(AppHelloWorld + HelloWorld.cpp + ) +ENDIF() + + + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppHelloWorld PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppHelloWorld PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppHelloWorld PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/HelloWorld/HelloWorld.cpp b/Demos/HelloWorld/HelloWorld.cpp new file mode 100644 index 0000000..c312667 --- /dev/null +++ b/Demos/HelloWorld/HelloWorld.cpp @@ -0,0 +1,172 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btBulletDynamicsCommon.h" +#include + +/// This is a Hello World program for running a basic Bullet physics simulation + +int main(int argc, char** argv) +{ + + int i; + + ///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration. + btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration(); + + ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) + btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration); + + ///btDbvtBroadphase is a good general purpose broadphase. You can also try out btAxis3Sweep. + btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase(); + + ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) + btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver; + + btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,overlappingPairCache,solver,collisionConfiguration); + + dynamicsWorld->setGravity(btVector3(0,-10,0)); + + ///create a few basic rigid bodies + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); + + //keep track of the shapes, we release memory at exit. + //make sure to re-use collision shapes among rigid bodies whenever possible! + btAlignedObjectArray collisionShapes; + + collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-56,0)); + + { + btScalar mass(0.); + + //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) + groundShape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + //add the body to the dynamics world + dynamicsWorld->addRigidBody(body); + } + + + { + //create a dynamic rigidbody + + //btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1)); + btCollisionShape* colShape = new btSphereShape(btScalar(1.)); + collisionShapes.push_back(colShape); + + /// Create Dynamic Objects + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + + //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) + colShape->calculateLocalInertia(mass,localInertia); + + startTransform.setOrigin(btVector3(2,10,0)); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + dynamicsWorld->addRigidBody(body); + } + + + +/// Do some simulation + + + + for (i=0;i<100;i++) + { + dynamicsWorld->stepSimulation(1.f/60.f,10); + + //print positions of all objects + for (int j=dynamicsWorld->getNumCollisionObjects()-1; j>=0 ;j--) + { + btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[j]; + btRigidBody* body = btRigidBody::upcast(obj); + if (body && body->getMotionState()) + { + btTransform trans; + body->getMotionState()->getWorldTransform(trans); + printf("world pos = %f,%f,%f\n",float(trans.getOrigin().getX()),float(trans.getOrigin().getY()),float(trans.getOrigin().getZ())); + } + } + } + + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + for (i=dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--) + { + btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[i]; + btRigidBody* body = btRigidBody::upcast(obj); + if (body && body->getMotionState()) + { + delete body->getMotionState(); + } + dynamicsWorld->removeCollisionObject( obj ); + delete obj; + } + + //delete collision shapes + for (int j=0;jm_collisionFlags |= btCollisionObject::customMaterialCallback; +inline btScalar calculateCombinedFriction(float friction0,float friction1) +{ + return 0.f; + btScalar friction = friction0 * friction1; + + const btScalar MAX_FRICTION = 10.f; + if (friction < -MAX_FRICTION) + friction = -MAX_FRICTION; + if (friction > MAX_FRICTION) + friction = MAX_FRICTION; + return friction; + +} + +inline btScalar calculateCombinedRestitution(float restitution0,float restitution1) +{ + return restitution0 * restitution1; +} + + +/////////////////////////////////////////////////////////////// + + +static bool CustomMaterialCombinerCallback(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1) +{ + + if (enable) + { + btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1); + //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_BACKFACE_MODE); + //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_DOUBLE_SIDED+BT_TRIANGLE_CONCAVE_DOUBLE_SIDED); + } + + float friction0 = colObj0->getFriction(); + float friction1 = colObj1->getFriction(); + float restitution0 = colObj0->getRestitution(); + float restitution1 = colObj1->getRestitution(); + + if (colObj0->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) + { + friction0 = 1.0;//partId0,index0 + restitution0 = 0.f; + } + if (colObj1->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) + { + if (index1&1) + { + friction1 = 1.0f;//partId1,index1 + } else + { + friction1 = 0.f; + } + restitution1 = 0.f; + } + + cp.m_combinedFriction = calculateCombinedFriction(friction0,friction1); + cp.m_combinedRestitution = calculateCombinedRestitution(restitution0,restitution1); + + //this return value is currently ignored, but to be on the safe side: return false if you don't calculate friction + return true; +} + +extern ContactAddedCallback gContactAddedCallback; + + const int NUM_VERTS_X = 2; + const int NUM_VERTS_Y = 2; + const int totalVerts = NUM_VERTS_X*NUM_VERTS_Y; + +void InternalEdgeDemo::setVertexPositions(float waveheight, float offset) +{ + int i; + int j; + + for ( i=0;isetCollisionFlags( staticBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + staticBody->setActivationState(DISABLE_DEACTIVATION); + } else + { + staticBody->setCollisionFlags( staticBody->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT); + staticBody->forceActivationState(ACTIVE_TAG); + } + } + + DemoApplication::keyboardCallback(key,x,y); + +} + + + +void InternalEdgeDemo::initPhysics() +{ + + setTexturing(true); + setShadows(false);//true); + + #define TRISIZE 10.f + + gContactAddedCallback = CustomMaterialCombinerCallback; + +#define USE_TRIMESH_SHAPE 1 +#ifdef USE_TRIMESH_SHAPE + + int vertStride = sizeof(btVector3); + int indexStride = 3*sizeof(int); + + + const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1); + + gVertices = new btVector3[totalVerts]; + gIndices = new int[totalTriangles*3]; + + int i; + + + setVertexPositions(waveheight,0.f); + + + //gVertices[1].setY(21.1); + //gVertices[1].setY(121.1); + gVertices[1].setY(.1f); + +#ifdef ROTATE_GROUND + //gVertices[1].setY(-1.1); +#else + //gVertices[1].setY(0.1); + //gVertices[1].setY(-0.1); + //gVertices[1].setY(-20.1); + //gVertices[1].setY(-20); +#endif + + int index=0; + for ( i=0;igetOptimizedBvh()->calculateSerializeBufferSize(); + buffer = btAlignedAlloc(numBytes,16); + bool swapEndian = false; + trimeshShape->getOptimizedBvh()->serialize(buffer,numBytes,swapEndian); + FILE* file = fopen("bvh.bin","wb"); + fwrite(buffer,1,numBytes,file); + fclose(file); + btAlignedFree(buffer); + + + +#else + + trimeshShape = new btBvhTriangleMeshShape(m_indexVertexArrays,useQuantizedAabbCompression,false); + + char* fileName = "bvh.bin"; + + FILE* file = fopen(fileName,"rb"); + int size=0; + btOptimizedBvh* bvh = 0; + + if (fseek(file, 0, SEEK_END) || (size = ftell(file)) == EOF || fseek(file, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */ + printf("Error: cannot get filesize from %s\n", fileName); + exit(0); + } else + { + + fseek(file, 0, SEEK_SET); + + int buffersize = size+btOptimizedBvh::getAlignmentSerializationPadding(); + + void* buffer = btAlignedAlloc(buffersize,16); + int read = fread(buffer,1,size,file); + fclose(file); + bool swapEndian = false; + bvh = btOptimizedBvh::deSerializeInPlace(buffer,buffersize,swapEndian); + } + + trimeshShape->setOptimizedBvh(bvh); + +#endif + + btCollisionShape* groundShape = trimeshShape; + + btTriangleInfoMap* triangleInfoMap = new btTriangleInfoMap(); + + + btGenerateInternalEdgeInfo(trimeshShape,triangleInfoMap); + + + +#else + btCollisionShape* groundShape = new btBoxShape(btVector3(50,3,50)); + + m_collisionShapes.push_back(groundShape); + +#endif //USE_TRIMESH_SHAPE + + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + + + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + + + + m_broadphase = new btDbvtBroadphase(); + m_solver = new btSequentialImpulseConstraintSolver(); + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); +/* +m_dynamicsWorld->getSolverInfo().m_splitImpulse = true; + m_dynamicsWorld->getSolverInfo().m_splitImpulsePenetrationThreshold = 1e30f; + m_dynamicsWorld->getSolverInfo().m_maxErrorReduction = 1e30f; + m_dynamicsWorld->getSolverInfo().m_erp =1.f; + m_dynamicsWorld->getSolverInfo().m_erp2 = 1.f; +*/ + + m_dynamicsWorld->setGravity(btVector3(0,-10,0)); + + + float mass = 0.f; + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(0,-2,0)); + + + btConvexHullShape* colShape = new btConvexHullShape(); + for (int i=0;iaddPoint(vtx); + } + //this will enable polyhedral contact clipping, better quality, slightly slower + colShape->initializePolyhedralFeatures(); + + //the polyhedral contact clipping can use either GJK or SAT test to find the separating axis + m_dynamicsWorld->getDispatchInfo().m_enableSatConvex=false; + + m_collisionShapes.push_back(colShape); + + { + for (int i=0;i<1;i++) + { + startTransform.setOrigin(btVector3(-10.f+i*3.f,2.2f+btScalar(i)*0.1f,-1.3f)); + btRigidBody* body = localCreateRigidBody(10, startTransform,colShape); + body->setActivationState(DISABLE_DEACTIVATION); + body->setLinearVelocity(btVector3(0,0,-1)); + //body->setContactProcessingThreshold(0.f); + } + } + { + btBoxShape* colShape = new btBoxShape(btVector3(1,1,1)); + colShape->initializePolyhedralFeatures(); + m_collisionShapes.push_back(colShape); + startTransform.setOrigin(btVector3(-16.f+i*3.f,1.f+btScalar(i)*0.1f,-1.3f)); + btRigidBody* body = localCreateRigidBody(10, startTransform,colShape); + body->setActivationState(DISABLE_DEACTIVATION); + body->setLinearVelocity(btVector3(0,0,-1)); + } + + startTransform.setIdentity(); +#ifdef ROTATE_GROUND + btQuaternion orn(btVector3(0,0,1),SIMD_PI); + startTransform.setOrigin(btVector3(-20,0,0)); + startTransform.setRotation(orn); +#endif //ROTATE_GROUND + + staticBody = localCreateRigidBody(mass, startTransform,groundShape); + //staticBody->setContactProcessingThreshold(-0.031f); + staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);//STATIC_OBJECT); + + //enable custom material callback + staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + + getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + setDebugMode(btIDebugDraw::DBG_DrawText|btIDebugDraw::DBG_NoHelpText+btIDebugDraw::DBG_DrawWireframe+btIDebugDraw::DBG_DrawContactPoints); + + +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btSetDebugDrawer(&gDebugDrawer); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + +} + + +void InternalEdgeDemo::clientResetScene() +{ + DemoApplication::clientResetScene(); + for (int i=0;igetNumCollisionObjects();i++) + { + btCollisionObject* colobj = m_dynamicsWorld->getCollisionObjectArray()[i]; + btRigidBody* body = btRigidBody::upcast(colobj); + if (body && body->getInvMass() != 0.f) + { + + body->setLinearVelocity(btVector3(0,0,-1)); + } + + } +} + +void InternalEdgeDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + float dt = getDeltaTimeMicroseconds() * 0.000001f; + + if (m_animatedMesh) + { + static float offset=0.f; + offset+=0.01f; + + // setVertexPositions(waveheight,offset); +#if 0 ///not currently supported, we need to update the btInternalTriangleInfoMap + int i; + int j; + btVector3 aabbMin(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); + btVector3 aabbMax(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT); + + for ( i=NUM_VERTS_X/2-3;ipartialRefitTree(aabbMin,aabbMax); +#else + btVector3 aabbMin,aabbMax; + trimeshShape->getMeshInterface()->calculateAabbBruteForce(aabbMin,aabbMax); + trimeshShape->refitTree(aabbMin,aabbMax); + +#endif + + + //for debugging: clear all contact points involving mesh proxy. Note: this is a slow/unoptimized operation. + //m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(staticBody->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher()); + } + + + + m_dynamicsWorld->stepSimulation(dt); + ///enable one of the following to debug (render debug lines each frame) + //m_dynamicsWorld->stepSimulation(1./800.,0); + //m_dynamicsWorld->stepSimulation(1./60.,100,1./800.); + //m_dynamicsWorld->stepSimulation(1./60.,0); + + + int lineWidth=450; + int xStart = m_glutScreenWidth - lineWidth; + int yStart = 20; + + if((getDebugMode() & btIDebugDraw::DBG_DrawText)!=0) + { + setOrthographicProjection(); + glDisable(GL_LIGHTING); + glColor3f(0, 0, 0); + char buf[124]; + + glRasterPos3f(xStart, yStart, 0); + if (enable) + { + sprintf(buf,"InternalEdgeUtility enabled"); + } else + { + sprintf(buf,"InternalEdgeUtility disabled"); + } + GLDebugDrawString(xStart,20,buf); + yStart+=20; + glRasterPos3f(xStart, yStart, 0); + sprintf(buf,"Press 'n' to toggle InternalEdgeUtility"); + yStart+=20; + GLDebugDrawString(xStart,yStart,buf); + glRasterPos3f(xStart, yStart, 0); + + resetPerspectiveProjection(); + glEnable(GL_LIGHTING); + } + + + renderme(); + + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + + + glFlush(); + swapBuffers(); + +} + + + + +void InternalEdgeDemo::displayCallback(void) { + + clientMoveAndDisplay(); + /* + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + //optional but useful: debug drawing + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + + glFlush(); + glutSwapBuffers(); + */ + +} + + + +void InternalEdgeDemo::exitPhysics() +{ + + + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;j m_collisionShapes; + + btTriangleIndexVertexArray* m_indexVertexArrays; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + bool m_animatedMesh; + + public: + + InternalEdgeDemo() : m_animatedMesh(true) + { + + } + void initPhysics(); + + void exitPhysics(); + + virtual ~InternalEdgeDemo() + { + exitPhysics(); + } + + virtual void clientResetScene(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + //to show refit works + void setVertexPositions(float waveheight, float offset); + + virtual void keyboardCallback(unsigned char key, int x, int y); + + static DemoApplication* Create() + { + InternalEdgeDemo* demo = new InternalEdgeDemo(); + demo->myinit(); + demo->initPhysics(); + return demo; + }; +}; + +#endif //CONCAVE_DEMO_H + diff --git a/Demos/InternalEdgeDemo/Taru.mdl b/Demos/InternalEdgeDemo/Taru.mdl new file mode 100644 index 0000000..4ebc503 --- /dev/null +++ b/Demos/InternalEdgeDemo/Taru.mdl @@ -0,0 +1,49 @@ +#define TaruVtxCount 43 +#define TaruIdxCount 132 + +static float TaruVtx[] = { +1.08664f,-1.99237f,0.0f, +0.768369f,-1.99237f,-0.768369f, +1.28852f,1.34412e-007f,-1.28852f, +1.82224f,1.90735e-007f,0.0f, +0.0f,-1.99237f,-1.08664f, +0.0f,0.0f,-1.82224f, +0.0f,-1.99237f,-1.08664f, +-0.768369f,-1.99237f,-0.768369f, +-1.28852f,1.34412e-007f,-1.28852f, +0.0f,0.0f,-1.82224f, +-1.08664f,-1.99237f,1.82086e-007f, +-1.82224f,1.90735e-007f,1.59305e-007f, +-0.768369f,-1.99237f,0.76837f, +-1.28852f,2.47058e-007f,1.28852f, +1.42495e-007f,-1.99237f,1.08664f, +2.38958e-007f,2.70388e-007f,1.82224f, +0.768369f,-1.99237f,0.768369f, +1.28852f,2.47058e-007f,1.28852f, +0.768369f,1.99237f,-0.768369f, +1.08664f,1.99237f,0.0f, +0.0f,1.99237f,-1.08664f, +-0.768369f,1.99237f,-0.768369f, +0.0f,1.99237f,-1.08664f, +-1.08664f,1.99237f,0.0f, +-0.768369f,1.99237f,0.768369f, +1.42495e-007f,1.99237f,1.08664f, +0.768369f,1.99237f,0.768369f, +1.42495e-007f,-1.99237f,1.08664f, +-0.768369f,-1.99237f,0.76837f, +-1.08664f,-1.99237f,1.82086e-007f, +-0.768369f,-1.99237f,-0.768369f, +0.0f,-1.99237f,-1.08664f, +0.768369f,-1.99237f,-0.768369f, +1.08664f,-1.99237f,0.0f, +0.768369f,-1.99237f,0.768369f, +0.768369f,1.99237f,-0.768369f, +0.0f,1.99237f,-1.08664f, +-0.768369f,1.99237f,-0.768369f, +-1.08664f,1.99237f,0.0f, +-0.768369f,1.99237f,0.768369f, +1.42495e-007f,1.99237f,1.08664f, +0.768369f,1.99237f,0.768369f, +1.08664f,1.99237f,0.0f, +}; + diff --git a/Demos/InternalEdgeDemo/Win32InternalEdgeDemo.cpp b/Demos/InternalEdgeDemo/Win32InternalEdgeDemo.cpp new file mode 100644 index 0000000..f550713 --- /dev/null +++ b/Demos/InternalEdgeDemo/Win32InternalEdgeDemo.cpp @@ -0,0 +1,25 @@ +#ifdef _WINDOWS +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "InternalEdgeDemo.h" + +///The 'createDemo' function is called from Bullet/Demos/OpenGL/Win32AppMain.cpp to instantiate this particular demo +DemoApplication* createDemo() +{ + return new InternalEdgeDemo(); +} + +#endif diff --git a/Demos/InternalEdgeDemo/main.cpp b/Demos/InternalEdgeDemo/main.cpp new file mode 100644 index 0000000..596ecb3 --- /dev/null +++ b/Demos/InternalEdgeDemo/main.cpp @@ -0,0 +1,19 @@ + +#include "InternalEdgeDemo.h" +#include "GlutStuff.h" + +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" + + +int main(int argc,char** argv) +{ + + InternalEdgeDemo* internalEdgeDemo = new InternalEdgeDemo(); + internalEdgeDemo->initPhysics(); + internalEdgeDemo->setCameraDistance(30.f); + + + return glutmain(argc, argv,640,480,"Internal Edge Demo",internalEdgeDemo); +} + diff --git a/Demos/Makefile.am b/Demos/Makefile.am new file mode 100644 index 0000000..cb7f841 --- /dev/null +++ b/Demos/Makefile.am @@ -0,0 +1,5 @@ +if CONDITIONAL_BUILD_MULTITHREADED +SUBDIRS=OpenGL BasicDemo TerrainDemo VehicleDemo CcdPhysicsDemo MultiThreadedDemo SoftDemo AllBulletDemos +else +SUBDIRS=OpenGL BasicDemo TerrainDemo VehicleDemo CcdPhysicsDemo SoftDemo AllBulletDemos +endif diff --git a/Demos/MovingConcaveDemo/CMakeLists.txt b/Demos/MovingConcaveDemo/CMakeLists.txt new file mode 100644 index 0000000..02f0768 --- /dev/null +++ b/Demos/MovingConcaveDemo/CMakeLists.txt @@ -0,0 +1,32 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# This is the variable for Windows. I use this to define the root of my directory structure. +SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/Glut) + +# You shouldn't have to modify anything below this line +######################################################## + + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppMovingConcaveDemo +ConcavePhysicsDemo.cpp +) + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppMovingConcaveDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppMovingConcaveDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppMovingConcaveDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/MovingConcaveDemo/ConcaveDemo.h b/Demos/MovingConcaveDemo/ConcaveDemo.h new file mode 100644 index 0000000..0a7e31b --- /dev/null +++ b/Demos/MovingConcaveDemo/ConcaveDemo.h @@ -0,0 +1,48 @@ +/* +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 CONCAVE_DEMO_H +#define CONCAVE_DEMO_H + +#include "GlutDemoApplication.h" + +struct btCollisionAlgorithmCreateFunc; + +///ConcaveDemo shows usage of static concave triangle meshes +///It also shows per-triangle material (friction/restitution) through CustomMaterialCombinerCallback +class ConcaveDemo : public GlutDemoApplication +{ + + btCollisionShape * m_trimeshShape; + + public: + + void initGImpactCollision(); + void initPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + virtual void renderme(); + virtual void keyboardCallback(unsigned char key, int x, int y); + + ///Demo functions + void shootTrimesh(const btVector3& startPosition,const btVector3& destination); + + +}; + +#endif //CONCAVE_DEMO_H + diff --git a/Demos/MovingConcaveDemo/ConcavePhysicsDemo.cpp b/Demos/MovingConcaveDemo/ConcavePhysicsDemo.cpp new file mode 100644 index 0000000..40cc3e1 --- /dev/null +++ b/Demos/MovingConcaveDemo/ConcavePhysicsDemo.cpp @@ -0,0 +1,1925 @@ +/* +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 "ConcaveDemo.h" + +#include "LinearMath/btDefaultMotionState.h" +#include "LinearMath/btIDebugDraw.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btDefaultMotionState.h" +#include "BulletCollision/Gimpact/btGImpactShape.h" +#include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h" +#include "GLDebugFont.h" + + + +#include "GLDebugDrawer.h" + +#include "GL_ShapeDrawer.h" +#include "GlutStuff.h" + + +GLDebugDrawer debugDrawer; + +//***************************THE FAMOUS BUNNY TRIMESH********************************************// + +#define REAL btScalar +const int NUM_TRIANGLES =902; +const int NUM_VERTICES = 453; +const int NUM_INDICES = NUM_TRIANGLES * 3; + + +REAL gVertices[NUM_VERTICES * 3] = { + REAL(-0.334392), REAL(0.133007), REAL(0.062259), + REAL(-0.350189), REAL(0.150354), REAL(-0.147769), + REAL(-0.234201), REAL(0.343811), REAL(-0.174307), + REAL(-0.200259), REAL(0.285207), REAL(0.093749), + REAL(0.003520), REAL(0.475208), REAL(-0.159365), + REAL(0.001856), REAL(0.419203), REAL(0.098582), + REAL(-0.252802), REAL(0.093666), REAL(0.237538), + REAL(-0.162901), REAL(0.237984), REAL(0.206905), + REAL(0.000865), REAL(0.318141), REAL(0.235370), + REAL(-0.414624), REAL(0.164083), REAL(-0.278254), + REAL(-0.262213), REAL(0.357334), REAL(-0.293246), + REAL(0.004628), REAL(0.482694), REAL(-0.338626), + REAL(-0.402162), REAL(0.133528), REAL(-0.443247), + REAL(-0.243781), REAL(0.324275), REAL(-0.436763), + REAL(0.005293), REAL(0.437592), REAL(-0.458332), + REAL(-0.339884), REAL(-0.041150), REAL(-0.668211), + REAL(-0.248382), REAL(0.255825), REAL(-0.627493), + REAL(0.006261), REAL(0.376103), REAL(-0.631506), + REAL(-0.216201), REAL(-0.126776), REAL(-0.886936), + REAL(-0.171075), REAL(0.011544), REAL(-0.881386), + REAL(-0.181074), REAL(0.098223), REAL(-0.814779), + REAL(-0.119891), REAL(0.218786), REAL(-0.760153), + REAL(-0.078895), REAL(0.276780), REAL(-0.739281), + REAL(0.006801), REAL(0.310959), REAL(-0.735661), + REAL(-0.168842), REAL(0.102387), REAL(-0.920381), + REAL(-0.104072), REAL(0.177278), REAL(-0.952530), + REAL(-0.129704), REAL(0.211848), REAL(-0.836678), + REAL(-0.099875), REAL(0.310931), REAL(-0.799381), + REAL(0.007237), REAL(0.361687), REAL(-0.794439), + REAL(-0.077913), REAL(0.258753), REAL(-0.921640), + REAL(0.007957), REAL(0.282241), REAL(-0.931680), + REAL(-0.252222), REAL(-0.550401), REAL(-0.557810), + REAL(-0.267633), REAL(-0.603419), REAL(-0.655209), + REAL(-0.446838), REAL(-0.118517), REAL(-0.466159), + REAL(-0.459488), REAL(-0.093017), REAL(-0.311341), + REAL(-0.370645), REAL(-0.100108), REAL(-0.159454), + REAL(-0.371984), REAL(-0.091991), REAL(-0.011044), + REAL(-0.328945), REAL(-0.098269), REAL(0.088659), + REAL(-0.282452), REAL(-0.018862), REAL(0.311501), + REAL(-0.352403), REAL(-0.131341), REAL(0.144902), + REAL(-0.364126), REAL(-0.200299), REAL(0.202388), + REAL(-0.283965), REAL(-0.231869), REAL(0.023668), + REAL(-0.298943), REAL(-0.155218), REAL(0.369716), + REAL(-0.293787), REAL(-0.121856), REAL(0.419097), + REAL(-0.290163), REAL(-0.290797), REAL(0.107824), + REAL(-0.264165), REAL(-0.272849), REAL(0.036347), + REAL(-0.228567), REAL(-0.372573), REAL(0.290309), + REAL(-0.190431), REAL(-0.286997), REAL(0.421917), + REAL(-0.191039), REAL(-0.240973), REAL(0.507118), + REAL(-0.287272), REAL(-0.276431), REAL(-0.065444), + REAL(-0.295675), REAL(-0.280818), REAL(-0.174200), + REAL(-0.399537), REAL(-0.313131), REAL(-0.376167), + REAL(-0.392666), REAL(-0.488581), REAL(-0.427494), + REAL(-0.331669), REAL(-0.570185), REAL(-0.466054), + REAL(-0.282290), REAL(-0.618140), REAL(-0.589220), + REAL(-0.374238), REAL(-0.594882), REAL(-0.323298), + REAL(-0.381071), REAL(-0.629723), REAL(-0.350777), + REAL(-0.382112), REAL(-0.624060), REAL(-0.221577), + REAL(-0.272701), REAL(-0.566522), REAL(0.259157), + REAL(-0.256702), REAL(-0.663406), REAL(0.286079), + REAL(-0.280948), REAL(-0.428359), REAL(0.055790), + REAL(-0.184974), REAL(-0.508894), REAL(0.326265), + REAL(-0.279971), REAL(-0.526918), REAL(0.395319), + REAL(-0.282599), REAL(-0.663393), REAL(0.412411), + REAL(-0.188329), REAL(-0.475093), REAL(0.417954), + REAL(-0.263384), REAL(-0.663396), REAL(0.466604), + REAL(-0.209063), REAL(-0.663393), REAL(0.509344), + REAL(-0.002044), REAL(-0.319624), REAL(0.553078), + REAL(-0.001266), REAL(-0.371260), REAL(0.413296), + REAL(-0.219753), REAL(-0.339762), REAL(-0.040921), + REAL(-0.256986), REAL(-0.282511), REAL(-0.006349), + REAL(-0.271706), REAL(-0.260881), REAL(0.001764), + REAL(-0.091191), REAL(-0.419184), REAL(-0.045912), + REAL(-0.114944), REAL(-0.429752), REAL(-0.124739), + REAL(-0.113970), REAL(-0.382987), REAL(-0.188540), + REAL(-0.243012), REAL(-0.464942), REAL(-0.242850), + REAL(-0.314815), REAL(-0.505402), REAL(-0.324768), + REAL(0.002774), REAL(-0.437526), REAL(-0.262766), + REAL(-0.072625), REAL(-0.417748), REAL(-0.221440), + REAL(-0.160112), REAL(-0.476932), REAL(-0.293450), + REAL(0.003859), REAL(-0.453425), REAL(-0.443916), + REAL(-0.120363), REAL(-0.581567), REAL(-0.438689), + REAL(-0.091499), REAL(-0.584191), REAL(-0.294511), + REAL(-0.116469), REAL(-0.599861), REAL(-0.188308), + REAL(-0.208032), REAL(-0.513640), REAL(-0.134649), + REAL(-0.235749), REAL(-0.610017), REAL(-0.040939), + REAL(-0.344916), REAL(-0.622487), REAL(-0.085380), + REAL(-0.336401), REAL(-0.531864), REAL(-0.212298), + REAL(0.001961), REAL(-0.459550), REAL(-0.135547), + REAL(-0.058296), REAL(-0.430536), REAL(-0.043440), + REAL(0.001378), REAL(-0.449511), REAL(-0.037762), + REAL(-0.130135), REAL(-0.510222), REAL(0.079144), + REAL(0.000142), REAL(-0.477549), REAL(0.157064), + REAL(-0.114284), REAL(-0.453206), REAL(0.304397), + REAL(-0.000592), REAL(-0.443558), REAL(0.285401), + REAL(-0.056215), REAL(-0.663402), REAL(0.326073), + REAL(-0.026248), REAL(-0.568010), REAL(0.273318), + REAL(-0.049261), REAL(-0.531064), REAL(0.389854), + REAL(-0.127096), REAL(-0.663398), REAL(0.479316), + REAL(-0.058384), REAL(-0.663401), REAL(0.372891), + REAL(-0.303961), REAL(0.054199), REAL(0.625921), + REAL(-0.268594), REAL(0.193403), REAL(0.502766), + REAL(-0.277159), REAL(0.126123), REAL(0.443289), + REAL(-0.287605), REAL(-0.005722), REAL(0.531844), + REAL(-0.231396), REAL(-0.121289), REAL(0.587387), + REAL(-0.253475), REAL(-0.081797), REAL(0.756541), + REAL(-0.195164), REAL(-0.137969), REAL(0.728011), + REAL(-0.167673), REAL(-0.156573), REAL(0.609388), + REAL(-0.145917), REAL(-0.169029), REAL(0.697600), + REAL(-0.077776), REAL(-0.214247), REAL(0.622586), + REAL(-0.076873), REAL(-0.214971), REAL(0.696301), + REAL(-0.002341), REAL(-0.233135), REAL(0.622859), + REAL(-0.002730), REAL(-0.213526), REAL(0.691267), + REAL(-0.003136), REAL(-0.192628), REAL(0.762731), + REAL(-0.056136), REAL(-0.201222), REAL(0.763806), + REAL(-0.114589), REAL(-0.166192), REAL(0.770723), + REAL(-0.155145), REAL(-0.129632), REAL(0.791738), + REAL(-0.183611), REAL(-0.058705), REAL(0.847012), + REAL(-0.165562), REAL(0.001980), REAL(0.833386), + REAL(-0.220084), REAL(0.019914), REAL(0.768935), + REAL(-0.255730), REAL(0.090306), REAL(0.670782), + REAL(-0.255594), REAL(0.113833), REAL(0.663389), + REAL(-0.226380), REAL(0.212655), REAL(0.617740), + REAL(-0.003367), REAL(-0.195342), REAL(0.799680), + REAL(-0.029743), REAL(-0.210508), REAL(0.827180), + REAL(-0.003818), REAL(-0.194783), REAL(0.873636), + REAL(-0.004116), REAL(-0.157907), REAL(0.931268), + REAL(-0.031280), REAL(-0.184555), REAL(0.889476), + REAL(-0.059885), REAL(-0.184448), REAL(0.841330), + REAL(-0.135333), REAL(-0.164332), REAL(0.878200), + REAL(-0.085574), REAL(-0.170948), REAL(0.925547), + REAL(-0.163833), REAL(-0.094170), REAL(0.897114), + REAL(-0.138444), REAL(-0.104250), REAL(0.945975), + REAL(-0.083497), REAL(-0.084934), REAL(0.979607), + REAL(-0.004433), REAL(-0.146642), REAL(0.985872), + REAL(-0.150715), REAL(0.032650), REAL(0.884111), + REAL(-0.135892), REAL(-0.035520), REAL(0.945455), + REAL(-0.070612), REAL(0.036849), REAL(0.975733), + REAL(-0.004458), REAL(-0.042526), REAL(1.015670), + REAL(-0.004249), REAL(0.046042), REAL(1.003240), + REAL(-0.086969), REAL(0.133224), REAL(0.947633), + REAL(-0.003873), REAL(0.161605), REAL(0.970499), + REAL(-0.125544), REAL(0.140012), REAL(0.917678), + REAL(-0.125651), REAL(0.250246), REAL(0.857602), + REAL(-0.003127), REAL(0.284070), REAL(0.878870), + REAL(-0.159174), REAL(0.125726), REAL(0.888878), + REAL(-0.183807), REAL(0.196970), REAL(0.844480), + REAL(-0.159890), REAL(0.291736), REAL(0.732480), + REAL(-0.199495), REAL(0.207230), REAL(0.779864), + REAL(-0.206182), REAL(0.164608), REAL(0.693257), + REAL(-0.186315), REAL(0.160689), REAL(0.817193), + REAL(-0.192827), REAL(0.166706), REAL(0.782271), + REAL(-0.175112), REAL(0.110008), REAL(0.860621), + REAL(-0.161022), REAL(0.057420), REAL(0.855111), + REAL(-0.172319), REAL(0.036155), REAL(0.816189), + REAL(-0.190318), REAL(0.064083), REAL(0.760605), + REAL(-0.195072), REAL(0.129179), REAL(0.731104), + REAL(-0.203126), REAL(0.410287), REAL(0.680536), + REAL(-0.216677), REAL(0.309274), REAL(0.642272), + REAL(-0.241515), REAL(0.311485), REAL(0.587832), + REAL(-0.002209), REAL(0.366663), REAL(0.749413), + REAL(-0.088230), REAL(0.396265), REAL(0.678635), + REAL(-0.170147), REAL(0.109517), REAL(0.840784), + REAL(-0.160521), REAL(0.067766), REAL(0.830650), + REAL(-0.181546), REAL(0.139805), REAL(0.812146), + REAL(-0.180495), REAL(0.148568), REAL(0.776087), + REAL(-0.180255), REAL(0.129125), REAL(0.744192), + REAL(-0.186298), REAL(0.078308), REAL(0.769352), + REAL(-0.167622), REAL(0.060539), REAL(0.806675), + REAL(-0.189876), REAL(0.102760), REAL(0.802582), + REAL(-0.108340), REAL(0.455446), REAL(0.657174), + REAL(-0.241585), REAL(0.527592), REAL(0.669296), + REAL(-0.265676), REAL(0.513366), REAL(0.634594), + REAL(-0.203073), REAL(0.478550), REAL(0.581526), + REAL(-0.266772), REAL(0.642330), REAL(0.602061), + REAL(-0.216961), REAL(0.564846), REAL(0.535435), + REAL(-0.202210), REAL(0.525495), REAL(0.475944), + REAL(-0.193888), REAL(0.467925), REAL(0.520606), + REAL(-0.265837), REAL(0.757267), REAL(0.500933), + REAL(-0.240306), REAL(0.653440), REAL(0.463215), + REAL(-0.309239), REAL(0.776868), REAL(0.304726), + REAL(-0.271009), REAL(0.683094), REAL(0.382018), + REAL(-0.312111), REAL(0.671099), REAL(0.286687), + REAL(-0.268791), REAL(0.624342), REAL(0.377231), + REAL(-0.302457), REAL(0.533996), REAL(0.360289), + REAL(-0.263656), REAL(0.529310), REAL(0.412564), + REAL(-0.282311), REAL(0.415167), REAL(0.447666), + REAL(-0.239201), REAL(0.442096), REAL(0.495604), + REAL(-0.220043), REAL(0.569026), REAL(0.445877), + REAL(-0.001263), REAL(0.395631), REAL(0.602029), + REAL(-0.057345), REAL(0.442535), REAL(0.572224), + REAL(-0.088927), REAL(0.506333), REAL(0.529106), + REAL(-0.125738), REAL(0.535076), REAL(0.612913), + REAL(-0.126251), REAL(0.577170), REAL(0.483159), + REAL(-0.149594), REAL(0.611520), REAL(0.557731), + REAL(-0.163188), REAL(0.660791), REAL(0.491080), + REAL(-0.172482), REAL(0.663387), REAL(0.415416), + REAL(-0.160464), REAL(0.591710), REAL(0.370659), + REAL(-0.156445), REAL(0.536396), REAL(0.378302), + REAL(-0.136496), REAL(0.444358), REAL(0.425226), + REAL(-0.095564), REAL(0.373768), REAL(0.473659), + REAL(-0.104146), REAL(0.315912), REAL(0.498104), + REAL(-0.000496), REAL(0.384194), REAL(0.473817), + REAL(-0.000183), REAL(0.297770), REAL(0.401486), + REAL(-0.129042), REAL(0.270145), REAL(0.434495), + REAL(0.000100), REAL(0.272963), REAL(0.349138), + REAL(-0.113060), REAL(0.236984), REAL(0.385554), + REAL(0.007260), REAL(0.016311), REAL(-0.883396), + REAL(0.007865), REAL(0.122104), REAL(-0.956137), + REAL(-0.032842), REAL(0.115282), REAL(-0.953252), + REAL(-0.089115), REAL(0.108449), REAL(-0.950317), + REAL(-0.047440), REAL(0.014729), REAL(-0.882756), + REAL(-0.104458), REAL(0.013137), REAL(-0.882070), + REAL(-0.086439), REAL(-0.584866), REAL(-0.608343), + REAL(-0.115026), REAL(-0.662605), REAL(-0.436732), + REAL(-0.071683), REAL(-0.665372), REAL(-0.606385), + REAL(-0.257884), REAL(-0.665381), REAL(-0.658052), + REAL(-0.272542), REAL(-0.665381), REAL(-0.592063), + REAL(-0.371322), REAL(-0.665382), REAL(-0.353620), + REAL(-0.372362), REAL(-0.665381), REAL(-0.224420), + REAL(-0.335166), REAL(-0.665380), REAL(-0.078623), + REAL(-0.225999), REAL(-0.665375), REAL(-0.038981), + REAL(-0.106719), REAL(-0.665374), REAL(-0.186351), + REAL(-0.081749), REAL(-0.665372), REAL(-0.292554), + REAL(0.006943), REAL(-0.091505), REAL(-0.858354), + REAL(0.006117), REAL(-0.280985), REAL(-0.769967), + REAL(0.004495), REAL(-0.502360), REAL(-0.559799), + REAL(-0.198638), REAL(-0.302135), REAL(-0.845816), + REAL(-0.237395), REAL(-0.542544), REAL(-0.587188), + REAL(-0.270001), REAL(-0.279489), REAL(-0.669861), + REAL(-0.134547), REAL(-0.119852), REAL(-0.959004), + REAL(-0.052088), REAL(-0.122463), REAL(-0.944549), + REAL(-0.124463), REAL(-0.293508), REAL(-0.899566), + REAL(-0.047616), REAL(-0.289643), REAL(-0.879292), + REAL(-0.168595), REAL(-0.529132), REAL(-0.654931), + REAL(-0.099793), REAL(-0.515719), REAL(-0.645873), + REAL(-0.186168), REAL(-0.605282), REAL(-0.724690), + REAL(-0.112970), REAL(-0.583097), REAL(-0.707469), + REAL(-0.108152), REAL(-0.665375), REAL(-0.700408), + REAL(-0.183019), REAL(-0.665378), REAL(-0.717630), + REAL(-0.349529), REAL(-0.334459), REAL(-0.511985), + REAL(-0.141182), REAL(-0.437705), REAL(-0.798194), + REAL(-0.212670), REAL(-0.448725), REAL(-0.737447), + REAL(-0.261111), REAL(-0.414945), REAL(-0.613835), + REAL(-0.077364), REAL(-0.431480), REAL(-0.778113), + REAL(0.005174), REAL(-0.425277), REAL(-0.651592), + REAL(0.089236), REAL(-0.431732), REAL(-0.777093), + REAL(0.271006), REAL(-0.415749), REAL(-0.610577), + REAL(0.223981), REAL(-0.449384), REAL(-0.734774), + REAL(0.153275), REAL(-0.438150), REAL(-0.796391), + REAL(0.358414), REAL(-0.335529), REAL(-0.507649), + REAL(0.193434), REAL(-0.665946), REAL(-0.715325), + REAL(0.118363), REAL(-0.665717), REAL(-0.699021), + REAL(0.123515), REAL(-0.583454), REAL(-0.706020), + REAL(0.196851), REAL(-0.605860), REAL(-0.722345), + REAL(0.109788), REAL(-0.516035), REAL(-0.644590), + REAL(0.178656), REAL(-0.529656), REAL(-0.652804), + REAL(0.061157), REAL(-0.289807), REAL(-0.878626), + REAL(0.138234), REAL(-0.293905), REAL(-0.897958), + REAL(0.066933), REAL(-0.122643), REAL(-0.943820), + REAL(0.149571), REAL(-0.120281), REAL(-0.957264), + REAL(0.280989), REAL(-0.280321), REAL(-0.666487), + REAL(0.246581), REAL(-0.543275), REAL(-0.584224), + REAL(0.211720), REAL(-0.302754), REAL(-0.843303), + REAL(0.086966), REAL(-0.665627), REAL(-0.291520), + REAL(0.110634), REAL(-0.665702), REAL(-0.185021), + REAL(0.228099), REAL(-0.666061), REAL(-0.036201), + REAL(0.337743), REAL(-0.666396), REAL(-0.074503), + REAL(0.376722), REAL(-0.666513), REAL(-0.219833), + REAL(0.377265), REAL(-0.666513), REAL(-0.349036), + REAL(0.281411), REAL(-0.666217), REAL(-0.588670), + REAL(0.267564), REAL(-0.666174), REAL(-0.654834), + REAL(0.080745), REAL(-0.665602), REAL(-0.605452), + REAL(0.122016), REAL(-0.662963), REAL(-0.435280), + REAL(0.095767), REAL(-0.585141), REAL(-0.607228), + REAL(0.118944), REAL(0.012799), REAL(-0.880702), + REAL(0.061944), REAL(0.014564), REAL(-0.882086), + REAL(0.104725), REAL(0.108156), REAL(-0.949130), + REAL(0.048513), REAL(0.115159), REAL(-0.952753), + REAL(0.112696), REAL(0.236643), REAL(0.386937), + REAL(0.128177), REAL(0.269757), REAL(0.436071), + REAL(0.102643), REAL(0.315600), REAL(0.499370), + REAL(0.094535), REAL(0.373481), REAL(0.474824), + REAL(0.136270), REAL(0.443946), REAL(0.426895), + REAL(0.157071), REAL(0.535923), REAL(0.380222), + REAL(0.161350), REAL(0.591224), REAL(0.372630), + REAL(0.173035), REAL(0.662865), REAL(0.417531), + REAL(0.162808), REAL(0.660299), REAL(0.493077), + REAL(0.148250), REAL(0.611070), REAL(0.559555), + REAL(0.125719), REAL(0.576790), REAL(0.484702), + REAL(0.123489), REAL(0.534699), REAL(0.614440), + REAL(0.087621), REAL(0.506066), REAL(0.530188), + REAL(0.055321), REAL(0.442365), REAL(0.572915), + REAL(0.219936), REAL(0.568361), REAL(0.448571), + REAL(0.238099), REAL(0.441375), REAL(0.498528), + REAL(0.281711), REAL(0.414315), REAL(0.451121), + REAL(0.263833), REAL(0.528513), REAL(0.415794), + REAL(0.303284), REAL(0.533081), REAL(0.363998), + REAL(0.269687), REAL(0.623528), REAL(0.380528), + REAL(0.314255), REAL(0.670153), REAL(0.290524), + REAL(0.272023), REAL(0.682273), REAL(0.385343), + REAL(0.311480), REAL(0.775931), REAL(0.308527), + REAL(0.240239), REAL(0.652714), REAL(0.466159), + REAL(0.265619), REAL(0.756464), REAL(0.504187), + REAL(0.192562), REAL(0.467341), REAL(0.522972), + REAL(0.201605), REAL(0.524885), REAL(0.478417), + REAL(0.215743), REAL(0.564193), REAL(0.538084), + REAL(0.264969), REAL(0.641527), REAL(0.605317), + REAL(0.201031), REAL(0.477940), REAL(0.584002), + REAL(0.263086), REAL(0.512567), REAL(0.637832), + REAL(0.238615), REAL(0.526867), REAL(0.672237), + REAL(0.105309), REAL(0.455123), REAL(0.658482), + REAL(0.183993), REAL(0.102195), REAL(0.804872), + REAL(0.161563), REAL(0.060042), REAL(0.808692), + REAL(0.180748), REAL(0.077754), REAL(0.771600), + REAL(0.175168), REAL(0.128588), REAL(0.746368), + REAL(0.175075), REAL(0.148030), REAL(0.778264), + REAL(0.175658), REAL(0.139265), REAL(0.814333), + REAL(0.154191), REAL(0.067291), REAL(0.832578), + REAL(0.163818), REAL(0.109013), REAL(0.842830), + REAL(0.084760), REAL(0.396004), REAL(0.679695), + REAL(0.238888), REAL(0.310760), REAL(0.590775), + REAL(0.213380), REAL(0.308625), REAL(0.644905), + REAL(0.199666), REAL(0.409678), REAL(0.683003), + REAL(0.190143), REAL(0.128597), REAL(0.733463), + REAL(0.184833), REAL(0.063516), REAL(0.762902), + REAL(0.166070), REAL(0.035644), REAL(0.818261), + REAL(0.154361), REAL(0.056943), REAL(0.857042), + REAL(0.168542), REAL(0.109489), REAL(0.862725), + REAL(0.187387), REAL(0.166131), REAL(0.784599), + REAL(0.180428), REAL(0.160135), REAL(0.819438), + REAL(0.201823), REAL(0.163991), REAL(0.695756), + REAL(0.194206), REAL(0.206635), REAL(0.782275), + REAL(0.155438), REAL(0.291260), REAL(0.734412), + REAL(0.177696), REAL(0.196424), REAL(0.846693), + REAL(0.152305), REAL(0.125256), REAL(0.890786), + REAL(0.119546), REAL(0.249876), REAL(0.859104), + REAL(0.118369), REAL(0.139643), REAL(0.919173), + REAL(0.079410), REAL(0.132973), REAL(0.948652), + REAL(0.062419), REAL(0.036648), REAL(0.976547), + REAL(0.127847), REAL(-0.035919), REAL(0.947070), + REAL(0.143624), REAL(0.032206), REAL(0.885913), + REAL(0.074888), REAL(-0.085173), REAL(0.980577), + REAL(0.130184), REAL(-0.104656), REAL(0.947620), + REAL(0.156201), REAL(-0.094653), REAL(0.899074), + REAL(0.077366), REAL(-0.171194), REAL(0.926545), + REAL(0.127722), REAL(-0.164729), REAL(0.879810), + REAL(0.052670), REAL(-0.184618), REAL(0.842019), + REAL(0.023477), REAL(-0.184638), REAL(0.889811), + REAL(0.022626), REAL(-0.210587), REAL(0.827500), + REAL(0.223089), REAL(0.211976), REAL(0.620493), + REAL(0.251444), REAL(0.113067), REAL(0.666494), + REAL(0.251419), REAL(0.089540), REAL(0.673887), + REAL(0.214360), REAL(0.019258), REAL(0.771595), + REAL(0.158999), REAL(0.001490), REAL(0.835374), + REAL(0.176696), REAL(-0.059249), REAL(0.849218), + REAL(0.148696), REAL(-0.130091), REAL(0.793599), + REAL(0.108290), REAL(-0.166528), REAL(0.772088), + REAL(0.049820), REAL(-0.201382), REAL(0.764454), + REAL(0.071341), REAL(-0.215195), REAL(0.697209), + REAL(0.073148), REAL(-0.214475), REAL(0.623510), + REAL(0.140502), REAL(-0.169461), REAL(0.699354), + REAL(0.163374), REAL(-0.157073), REAL(0.611416), + REAL(0.189466), REAL(-0.138550), REAL(0.730366), + REAL(0.247593), REAL(-0.082554), REAL(0.759610), + REAL(0.227468), REAL(-0.121982), REAL(0.590197), + REAL(0.284702), REAL(-0.006586), REAL(0.535347), + REAL(0.275741), REAL(0.125287), REAL(0.446676), + REAL(0.266650), REAL(0.192594), REAL(0.506044), + REAL(0.300086), REAL(0.053287), REAL(0.629620), + REAL(0.055450), REAL(-0.663935), REAL(0.375065), + REAL(0.122854), REAL(-0.664138), REAL(0.482323), + REAL(0.046520), REAL(-0.531571), REAL(0.391918), + REAL(0.024824), REAL(-0.568450), REAL(0.275106), + REAL(0.053855), REAL(-0.663931), REAL(0.328224), + REAL(0.112829), REAL(-0.453549), REAL(0.305788), + REAL(0.131265), REAL(-0.510617), REAL(0.080746), + REAL(0.061174), REAL(-0.430716), REAL(-0.042710), + REAL(0.341019), REAL(-0.532887), REAL(-0.208150), + REAL(0.347705), REAL(-0.623533), REAL(-0.081139), + REAL(0.238040), REAL(-0.610732), REAL(-0.038037), + REAL(0.211764), REAL(-0.514274), REAL(-0.132078), + REAL(0.120605), REAL(-0.600219), REAL(-0.186856), + REAL(0.096985), REAL(-0.584476), REAL(-0.293357), + REAL(0.127621), REAL(-0.581941), REAL(-0.437170), + REAL(0.165902), REAL(-0.477425), REAL(-0.291453), + REAL(0.077720), REAL(-0.417975), REAL(-0.220519), + REAL(0.320892), REAL(-0.506363), REAL(-0.320874), + REAL(0.248214), REAL(-0.465684), REAL(-0.239842), + REAL(0.118764), REAL(-0.383338), REAL(-0.187114), + REAL(0.118816), REAL(-0.430106), REAL(-0.123307), + REAL(0.094131), REAL(-0.419464), REAL(-0.044777), + REAL(0.274526), REAL(-0.261706), REAL(0.005110), + REAL(0.259842), REAL(-0.283292), REAL(-0.003185), + REAL(0.222861), REAL(-0.340431), REAL(-0.038210), + REAL(0.204445), REAL(-0.664380), REAL(0.513353), + REAL(0.259286), REAL(-0.664547), REAL(0.471281), + REAL(0.185402), REAL(-0.476020), REAL(0.421718), + REAL(0.279163), REAL(-0.664604), REAL(0.417328), + REAL(0.277157), REAL(-0.528122), REAL(0.400208), + REAL(0.183069), REAL(-0.509812), REAL(0.329995), + REAL(0.282599), REAL(-0.429210), REAL(0.059242), + REAL(0.254816), REAL(-0.664541), REAL(0.290687), + REAL(0.271436), REAL(-0.567707), REAL(0.263966), + REAL(0.386561), REAL(-0.625221), REAL(-0.216870), + REAL(0.387086), REAL(-0.630883), REAL(-0.346073), + REAL(0.380021), REAL(-0.596021), REAL(-0.318679), + REAL(0.291269), REAL(-0.619007), REAL(-0.585707), + REAL(0.339280), REAL(-0.571198), REAL(-0.461946), + REAL(0.400045), REAL(-0.489778), REAL(-0.422640), + REAL(0.406817), REAL(-0.314349), REAL(-0.371230), + REAL(0.300588), REAL(-0.281718), REAL(-0.170549), + REAL(0.290866), REAL(-0.277304), REAL(-0.061905), + REAL(0.187735), REAL(-0.241545), REAL(0.509437), + REAL(0.188032), REAL(-0.287569), REAL(0.424234), + REAL(0.227520), REAL(-0.373262), REAL(0.293102), + REAL(0.266526), REAL(-0.273650), REAL(0.039597), + REAL(0.291592), REAL(-0.291676), REAL(0.111386), + REAL(0.291914), REAL(-0.122741), REAL(0.422683), + REAL(0.297574), REAL(-0.156119), REAL(0.373368), + REAL(0.286603), REAL(-0.232731), REAL(0.027162), + REAL(0.364663), REAL(-0.201399), REAL(0.206850), + REAL(0.353855), REAL(-0.132408), REAL(0.149228), + REAL(0.282208), REAL(-0.019715), REAL(0.314960), + REAL(0.331187), REAL(-0.099266), REAL(0.092701), + REAL(0.375463), REAL(-0.093120), REAL(-0.006467), + REAL(0.375917), REAL(-0.101236), REAL(-0.154882), + REAL(0.466635), REAL(-0.094416), REAL(-0.305669), + REAL(0.455805), REAL(-0.119881), REAL(-0.460632), + REAL(0.277465), REAL(-0.604242), REAL(-0.651871), + REAL(0.261022), REAL(-0.551176), REAL(-0.554667), + REAL(0.093627), REAL(0.258494), REAL(-0.920589), + REAL(0.114248), REAL(0.310608), REAL(-0.798070), + REAL(0.144232), REAL(0.211434), REAL(-0.835001), + REAL(0.119916), REAL(0.176940), REAL(-0.951159), + REAL(0.184061), REAL(0.101854), REAL(-0.918220), + REAL(0.092431), REAL(0.276521), REAL(-0.738231), + REAL(0.133504), REAL(0.218403), REAL(-0.758602), + REAL(0.194987), REAL(0.097655), REAL(-0.812476), + REAL(0.185542), REAL(0.011005), REAL(-0.879202), + REAL(0.230315), REAL(-0.127450), REAL(-0.884202), + REAL(0.260471), REAL(0.255056), REAL(-0.624378), + REAL(0.351567), REAL(-0.042194), REAL(-0.663976), + REAL(0.253742), REAL(0.323524), REAL(-0.433716), + REAL(0.411612), REAL(0.132299), REAL(-0.438264), + REAL(0.270513), REAL(0.356530), REAL(-0.289984), + REAL(0.422146), REAL(0.162819), REAL(-0.273130), + REAL(0.164724), REAL(0.237490), REAL(0.208912), + REAL(0.253806), REAL(0.092900), REAL(0.240640), + REAL(0.203608), REAL(0.284597), REAL(0.096223), + REAL(0.241006), REAL(0.343093), REAL(-0.171396), + REAL(0.356076), REAL(0.149288), REAL(-0.143443), + REAL(0.337656), REAL(0.131992), REAL(0.066374) +}; + +int gIndices[NUM_TRIANGLES][3] = { + {126,134,133}, + {342,138,134}, + {133,134,138}, + {126,342,134}, + {312,316,317}, + {169,163,162}, + {312,317,319}, + {312,319,318}, + {169,162,164}, + {169,168,163}, + {312,314,315}, + {169,164,165}, + {169,167,168}, + {312,315,316}, + {312,313,314}, + {169,165,166}, + {169,166,167}, + {312,318,313}, + {308,304,305}, + {308,305,306}, + {179,181,188}, + {177,173,175}, + {177,175,176}, + {302,293,300}, + {322,294,304}, + {188,176,175}, + {188,175,179}, + {158,177,187}, + {305,293,302}, + {305,302,306}, + {322,304,308}, + {188,181,183}, + {158,173,177}, + {293,298,300}, + {304,294,296}, + {304,296,305}, + {185,176,188}, + {185,188,183}, + {187,177,176}, + {187,176,185}, + {305,296,298}, + {305,298,293}, + {436,432, 28}, + {436, 28, 23}, + {434,278,431}, + { 30,208,209}, + { 30,209, 29}, + { 19, 20, 24}, + {208,207,211}, + {208,211,209}, + { 19,210,212}, + {433,434,431}, + {433,431,432}, + {433,432,436}, + {436,437,433}, + {277,275,276}, + {277,276,278}, + {209,210, 25}, + { 21, 26, 24}, + { 21, 24, 20}, + { 25, 26, 27}, + { 25, 27, 29}, + {435,439,277}, + {439,275,277}, + {432,431, 30}, + {432, 30, 28}, + {433,437,438}, + {433,438,435}, + {434,277,278}, + { 24, 25,210}, + { 24, 26, 25}, + { 29, 27, 28}, + { 29, 28, 30}, + { 19, 24,210}, + {208, 30,431}, + {208,431,278}, + {435,434,433}, + {435,277,434}, + { 25, 29,209}, + { 27, 22, 23}, + { 27, 23, 28}, + { 26, 22, 27}, + { 26, 21, 22}, + {212,210,209}, + {212,209,211}, + {207,208,278}, + {207,278,276}, + {439,435,438}, + { 12, 9, 10}, + { 12, 10, 13}, + { 2, 3, 5}, + { 2, 5, 4}, + { 16, 13, 14}, + { 16, 14, 17}, + { 22, 21, 16}, + { 13, 10, 11}, + { 13, 11, 14}, + { 1, 0, 3}, + { 1, 3, 2}, + { 15, 12, 16}, + { 19, 18, 15}, + { 19, 15, 16}, + { 19, 16, 20}, + { 9, 1, 2}, + { 9, 2, 10}, + { 3, 7, 8}, + { 3, 8, 5}, + { 16, 17, 23}, + { 16, 23, 22}, + { 21, 20, 16}, + { 10, 2, 4}, + { 10, 4, 11}, + { 0, 6, 7}, + { 0, 7, 3}, + { 12, 13, 16}, + {451,446,445}, + {451,445,450}, + {442,440,439}, + {442,439,438}, + {442,438,441}, + {421,420,422}, + {412,411,426}, + {412,426,425}, + {408,405,407}, + {413, 67, 68}, + {413, 68,414}, + {391,390,412}, + { 80,384,386}, + {404,406,378}, + {390,391,377}, + {390,377, 88}, + {400,415,375}, + {398,396,395}, + {398,395,371}, + {398,371,370}, + {112,359,358}, + {112,358,113}, + {351,352,369}, + {125,349,348}, + {345,343,342}, + {342,340,339}, + {341,335,337}, + {328,341,327}, + {331,323,333}, + {331,322,323}, + {327,318,319}, + {327,319,328}, + {315,314,324}, + {302,300,301}, + {302,301,303}, + {320,311,292}, + {285,284,289}, + {310,307,288}, + {310,288,290}, + {321,350,281}, + {321,281,282}, + {423,448,367}, + {272,273,384}, + {272,384,274}, + {264,265,382}, + {264,382,383}, + {440,442,261}, + {440,261,263}, + {252,253,254}, + {252,254,251}, + {262,256,249}, + {262,249,248}, + {228,243,242}, + {228, 31,243}, + {213,215,238}, + {213,238,237}, + { 19,212,230}, + {224,225,233}, + {224,233,231}, + {217,218, 56}, + {217, 56, 54}, + {217,216,239}, + {217,239,238}, + {217,238,215}, + {218,217,215}, + {218,215,214}, + { 6,102,206}, + {186,199,200}, + {197,182,180}, + {170,171,157}, + {201,200,189}, + {170,190,191}, + {170,191,192}, + {175,174,178}, + {175,178,179}, + {168,167,155}, + {122,149,158}, + {122,158,159}, + {135,153,154}, + {135,154,118}, + {143,140,141}, + {143,141,144}, + {132,133,136}, + {130,126,133}, + {124,125,127}, + {122,101,100}, + {122,100,121}, + {110,108,107}, + {110,107,109}, + { 98, 99, 97}, + { 98, 97, 64}, + { 98, 64, 66}, + { 87, 55, 57}, + { 83, 82, 79}, + { 83, 79, 84}, + { 78, 74, 50}, + { 49, 71, 41}, + { 49, 41, 37}, + { 49, 37, 36}, + { 58, 44, 60}, + { 60, 59, 58}, + { 51, 34, 33}, + { 39, 40, 42}, + { 39, 42, 38}, + {243,240, 33}, + {243, 33,229}, + { 39, 38, 6}, + { 44, 46, 40}, + { 55, 56, 57}, + { 64, 62, 65}, + { 64, 65, 66}, + { 41, 71, 45}, + { 75, 50, 51}, + { 81, 79, 82}, + { 77, 88, 73}, + { 93, 92, 94}, + { 68, 47, 46}, + { 96, 97, 99}, + { 96, 99, 95}, + {110,109,111}, + {111,112,110}, + {114,113,123}, + {114,123,124}, + {132,131,129}, + {133,137,136}, + {135,142,145}, + {145,152,135}, + {149,147,157}, + {157,158,149}, + {164,150,151}, + {153,163,168}, + {153,168,154}, + {185,183,182}, + {185,182,184}, + {161,189,190}, + {200,199,191}, + {200,191,190}, + {180,178,195}, + {180,195,196}, + {102,101,204}, + {102,204,206}, + { 43, 48,104}, + { 43,104,103}, + {216,217, 54}, + {216, 54, 32}, + {207,224,231}, + {230,212,211}, + {230,211,231}, + {227,232,241}, + {227,241,242}, + {235,234,241}, + {235,241,244}, + {430,248,247}, + {272,274,253}, + {272,253,252}, + {439,260,275}, + {225,224,259}, + {225,259,257}, + {269,270,407}, + {269,407,405}, + {270,269,273}, + {270,273,272}, + {273,269,268}, + {273,268,267}, + {273,267,266}, + {273,266,265}, + {273,265,264}, + {448,279,367}, + {281,350,368}, + {285,286,301}, + {290,323,310}, + {290,311,323}, + {282,281,189}, + {292,311,290}, + {292,290,291}, + {307,306,302}, + {307,302,303}, + {316,315,324}, + {316,324,329}, + {331,351,350}, + {330,334,335}, + {330,335,328}, + {341,337,338}, + {344,355,354}, + {346,345,348}, + {346,348,347}, + {364,369,352}, + {364,352,353}, + {365,363,361}, + {365,361,362}, + {376,401,402}, + {373,372,397}, + {373,397,400}, + {376, 92,377}, + {381,378,387}, + {381,387,385}, + {386, 77, 80}, + {390,389,412}, + {416,417,401}, + {403,417,415}, + {408,429,430}, + {419,423,418}, + {427,428,444}, + {427,444,446}, + {437,436,441}, + {450,445, 11}, + {450, 11, 4}, + {447,449, 5}, + {447, 5, 8}, + {441,438,437}, + {425,426,451}, + {425,451,452}, + {417,421,415}, + {408,407,429}, + {399,403,400}, + {399,400,397}, + {394,393,416}, + {389,411,412}, + {386,383,385}, + {408,387,378}, + {408,378,406}, + {377,391,376}, + { 94,375,415}, + {372,373,374}, + {372,374,370}, + {359,111,360}, + {359,112,111}, + {113,358,349}, + {113,349,123}, + {346,343,345}, + {343,340,342}, + {338,336,144}, + {338,144,141}, + {327,341,354}, + {327,354,326}, + {331,350,321}, + {331,321,322}, + {314,313,326}, + {314,326,325}, + {300,298,299}, + {300,299,301}, + {288,287,289}, + {189,292,282}, + {287,288,303}, + {284,285,297}, + {368,280,281}, + {448,447,279}, + {274,226,255}, + {267,268,404}, + {267,404,379}, + {429,262,430}, + {439,440,260}, + {257,258,249}, + {257,249,246}, + {430,262,248}, + {234,228,242}, + {234,242,241}, + {237,238,239}, + {237,239,236}, + { 15, 18,227}, + { 15,227,229}, + {222,223, 82}, + {222, 82, 83}, + {214,215,213}, + {214,213, 81}, + { 38,102, 6}, + {122,159,200}, + {122,200,201}, + {174,171,192}, + {174,192,194}, + {197,193,198}, + {190,170,161}, + {181,179,178}, + {181,178,180}, + {166,156,155}, + {163,153,152}, + {163,152,162}, + {120,156,149}, + {120,149,121}, + {152,153,135}, + {140,143,142}, + {135,131,132}, + {135,132,136}, + {130,129,128}, + {130,128,127}, + {100,105,119}, + {100,119,120}, + {106,104,107}, + {106,107,108}, + { 91, 95, 59}, + { 93, 94, 68}, + { 91, 89, 92}, + { 76, 53, 55}, + { 76, 55, 87}, + { 81, 78, 79}, + { 74, 73, 49}, + { 69, 60, 45}, + { 58, 62, 64}, + { 58, 64, 61}, + { 53, 31, 32}, + { 32, 54, 53}, + { 42, 43, 38}, + { 35, 36, 0}, + { 35, 0, 1}, + { 34, 35, 1}, + { 34, 1, 9}, + { 44, 40, 41}, + { 44, 41, 45}, + { 33,240, 51}, + { 63, 62, 58}, + { 63, 58, 59}, + { 45, 71, 70}, + { 76, 75, 51}, + { 76, 51, 52}, + { 86, 85, 84}, + { 86, 84, 87}, + { 89, 72, 73}, + { 89, 73, 88}, + { 91, 92, 96}, + { 91, 96, 95}, + { 72, 91, 60}, + { 72, 60, 69}, + {104,106,105}, + {119,105,117}, + {119,117,118}, + {124,127,128}, + {117,116,129}, + {117,129,131}, + {118,117,131}, + {135,140,142}, + {146,150,152}, + {146,152,145}, + {149,122,121}, + {166,165,151}, + {166,151,156}, + {158,172,173}, + {161,160,189}, + {199,198,193}, + {199,193,191}, + {204,201,202}, + {178,174,194}, + {200,159,186}, + {109, 48, 67}, + { 48,107,104}, + {216, 32,236}, + {216,236,239}, + {223,214, 81}, + {223, 81, 82}, + { 33, 12, 15}, + { 32,228,234}, + { 32,234,236}, + {240, 31, 52}, + {256,255,246}, + {256,246,249}, + {258,263,248}, + {258,248,249}, + {275,260,259}, + {275,259,276}, + {207,276,259}, + {270,271,429}, + {270,429,407}, + {413,418,366}, + {413,366,365}, + {368,367,279}, + {368,279,280}, + {303,301,286}, + {303,286,287}, + {283,282,292}, + {283,292,291}, + {320,292,189}, + {298,296,297}, + {298,297,299}, + {318,327,326}, + {318,326,313}, + {329,330,317}, + {336,333,320}, + {326,354,353}, + {334,332,333}, + {334,333,336}, + {342,339,139}, + {342,139,138}, + {345,342,126}, + {347,357,356}, + {369,368,351}, + {363,356,357}, + {363,357,361}, + {366,367,368}, + {366,368,369}, + {375,373,400}, + { 92, 90,377}, + {409,387,408}, + {386,385,387}, + {386,387,388}, + {412,394,391}, + {396,398,399}, + {408,406,405}, + {415,421,419}, + {415,419,414}, + {425,452,448}, + {425,448,424}, + {444,441,443}, + {448,452,449}, + {448,449,447}, + {446,444,443}, + {446,443,445}, + {250,247,261}, + {250,261,428}, + {421,422,423}, + {421,423,419}, + {427,410,250}, + {417,403,401}, + {403,402,401}, + {420,392,412}, + {420,412,425}, + {420,425,424}, + {386,411,389}, + {383,382,381}, + {383,381,385}, + {378,379,404}, + {372,371,395}, + {372,395,397}, + {371,372,370}, + {361,359,360}, + {361,360,362}, + {368,350,351}, + {349,347,348}, + {356,355,344}, + {356,344,346}, + {344,341,340}, + {344,340,343}, + {338,337,336}, + {328,335,341}, + {324,352,351}, + {324,351,331}, + {320,144,336}, + {314,325,324}, + {322,308,309}, + {310,309,307}, + {287,286,289}, + {203,280,279}, + {203,279,205}, + {297,295,283}, + {297,283,284}, + {447,205,279}, + {274,384, 80}, + {274, 80,226}, + {266,267,379}, + {266,379,380}, + {225,257,246}, + {225,246,245}, + {256,254,253}, + {256,253,255}, + {430,247,250}, + {226,235,244}, + {226,244,245}, + {232,233,244}, + {232,244,241}, + {230, 18, 19}, + { 32, 31,228}, + {219,220, 86}, + {219, 86, 57}, + {226,213,235}, + {206, 7, 6}, + {122,201,101}, + {201,204,101}, + {180,196,197}, + {170,192,171}, + {200,190,189}, + {194,193,195}, + {183,181,180}, + {183,180,182}, + {155,154,168}, + {149,156,151}, + {149,151,148}, + {155,156,120}, + {145,142,143}, + {145,143,146}, + {136,137,140}, + {133,132,130}, + {128,129,116}, + {100,120,121}, + {110,112,113}, + {110,113,114}, + { 66, 65, 63}, + { 66, 63, 99}, + { 66, 99, 98}, + { 96, 46, 61}, + { 89, 88, 90}, + { 86, 87, 57}, + { 80, 78, 81}, + { 72, 69, 49}, + { 67, 48, 47}, + { 67, 47, 68}, + { 56, 55, 53}, + { 50, 49, 36}, + { 50, 36, 35}, + { 40, 39, 41}, + {242,243,229}, + {242,229,227}, + { 6, 37, 39}, + { 42, 47, 48}, + { 42, 48, 43}, + { 61, 46, 44}, + { 45, 70, 69}, + { 69, 70, 71}, + { 69, 71, 49}, + { 74, 78, 77}, + { 83, 84, 85}, + { 73, 74, 77}, + { 93, 96, 92}, + { 68, 46, 93}, + { 95, 99, 63}, + { 95, 63, 59}, + {115,108,110}, + {115,110,114}, + {125,126,127}, + {129,130,132}, + {137,133,138}, + {137,138,139}, + {148,146,143}, + {148,143,147}, + {119,118,154}, + {161,147,143}, + {165,164,151}, + {158,157,171}, + {158,171,172}, + {159,158,187}, + {159,187,186}, + {194,192,191}, + {194,191,193}, + {189,202,201}, + {182,197,184}, + {205, 8, 7}, + { 48,109,107}, + {218,219, 57}, + {218, 57, 56}, + {207,231,211}, + {232,230,231}, + {232,231,233}, + { 53, 52, 31}, + {388,411,386}, + {409,430,250}, + {262,429,254}, + {262,254,256}, + {442,444,428}, + {273,264,383}, + {273,383,384}, + {429,271,251}, + {429,251,254}, + {413,365,362}, + { 67,413,360}, + {282,283,295}, + {285,301,299}, + {202,281,280}, + {284,283,291}, + {284,291,289}, + {320,189,160}, + {308,306,307}, + {307,309,308}, + {319,317,330}, + {319,330,328}, + {353,352,324}, + {332,331,333}, + {340,341,338}, + {354,341,344}, + {349,358,357}, + {349,357,347}, + {364,355,356}, + {364,356,363}, + {364,365,366}, + {364,366,369}, + {374,376,402}, + {375, 92,373}, + { 77,389,390}, + {382,380,381}, + {389, 77,386}, + {393,394,412}, + {393,412,392}, + {401,394,416}, + {415,400,403}, + {411,410,427}, + {411,427,426}, + {422,420,424}, + {247,248,263}, + {247,263,261}, + {445,443, 14}, + {445, 14, 11}, + {449,450, 4}, + {449, 4, 5}, + {443,441, 17}, + {443, 17, 14}, + {436, 23, 17}, + {436, 17,441}, + {424,448,422}, + {448,423,422}, + {414,419,418}, + {414,418,413}, + {406,404,405}, + {399,397,395}, + {399,395,396}, + {420,416,392}, + {388,410,411}, + {386,384,383}, + {390, 88, 77}, + {375, 94, 92}, + {415,414, 68}, + {415, 68, 94}, + {370,374,402}, + {370,402,398}, + {361,357,358}, + {361,358,359}, + {125,348,126}, + {346,344,343}, + {340,338,339}, + {337,335,334}, + {337,334,336}, + {325,353,324}, + {324,331,332}, + {324,332,329}, + {323,322,309}, + {323,309,310}, + {294,295,297}, + {294,297,296}, + {289,286,285}, + {202,280,203}, + {288,307,303}, + {282,295,321}, + { 67,360,111}, + {418,423,367}, + {418,367,366}, + {272,252,251}, + {272,251,271}, + {272,271,270}, + {255,253,274}, + {265,266,380}, + {265,380,382}, + {442,428,261}, + {440,263,258}, + {440,258,260}, + {409,250,410}, + {255,226,245}, + {255,245,246}, + { 31,240,243}, + {236,234,235}, + {236,235,237}, + {233,225,245}, + {233,245,244}, + {220,221, 85}, + {220, 85, 86}, + { 81,213,226}, + { 81,226, 80}, + { 7,206,205}, + {186,184,198}, + {186,198,199}, + {204,203,205}, + {204,205,206}, + {195,193,196}, + {171,174,172}, + {173,174,175}, + {173,172,174}, + {155,167,166}, + {160,161,143}, + {160,143,144}, + {119,154,155}, + {148,151,150}, + {148,150,146}, + {140,137,139}, + {140,139,141}, + {127,126,130}, + {114,124,128}, + {114,128,115}, + {117,105,106}, + {117,106,116}, + {104,105,100}, + {104,100,103}, + { 59, 60, 91}, + { 97, 96, 61}, + { 97, 61, 64}, + { 91, 72, 89}, + { 87, 84, 79}, + { 87, 79, 76}, + { 78, 80, 77}, + { 49, 50, 74}, + { 60, 44, 45}, + { 61, 44, 58}, + { 51, 50, 35}, + { 51, 35, 34}, + { 39, 37, 41}, + { 33, 34, 9}, + { 33, 9, 12}, + { 0, 36, 37}, + { 0, 37, 6}, + { 40, 46, 47}, + { 40, 47, 42}, + { 53, 54, 56}, + { 65, 62, 63}, + { 72, 49, 73}, + { 79, 78, 75}, + { 79, 75, 76}, + { 52, 53, 76}, + { 92, 89, 90}, + { 96, 93, 46}, + {102,103,100}, + {102,100,101}, + {116,106,108}, + {116,108,115}, + {123,125,124}, + {116,115,128}, + {118,131,135}, + {140,135,136}, + {148,147,149}, + {120,119,155}, + {164,162,152}, + {164,152,150}, + {157,147,161}, + {157,161,170}, + {186,187,185}, + {186,185,184}, + {193,197,196}, + {202,203,204}, + {194,195,178}, + {198,184,197}, + { 67,111,109}, + { 38, 43,103}, + { 38,103,102}, + {214,223,222}, + {214,222,221}, + {214,221,220}, + {214,220,219}, + {214,219,218}, + {213,237,235}, + {221,222, 83}, + {221, 83, 85}, + { 15,229, 33}, + {227, 18,230}, + {227,230,232}, + { 52, 51,240}, + { 75, 78, 50}, + {408,430,409}, + {260,258,257}, + {260,257,259}, + {224,207,259}, + {268,269,405}, + {268,405,404}, + {413,362,360}, + {447, 8,205}, + {299,297,285}, + {189,281,202}, + {290,288,289}, + {290,289,291}, + {322,321,295}, + {322,295,294}, + {333,323,311}, + {333,311,320}, + {317,316,329}, + {320,160,144}, + {353,325,326}, + {329,332,334}, + {329,334,330}, + {339,338,141}, + {339,141,139}, + {348,345,126}, + {347,356,346}, + {123,349,125}, + {364,353,354}, + {364,354,355}, + {365,364,363}, + {376,391,394}, + {376,394,401}, + { 92,376,374}, + { 92,374,373}, + {377, 90, 88}, + {380,379,378}, + {380,378,381}, + {388,387,409}, + {388,409,410}, + {416,393,392}, + {399,398,402}, + {399,402,403}, + {250,428,427}, + {421,417,416}, + {421,416,420}, + {426,427,446}, + {426,446,451}, + {444,442,441}, + {452,451,450}, + {452,450,449} +}; + + +//***************************THE END OF FAMOUS BUNNY TRIMESH********************************************// + +//****GLOBALS + +//****GLOBALS + +///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; +inline btScalar calculateCombinedFriction(float friction0,float friction1) +{ + btScalar friction = friction0 * friction1; + + const btScalar MAX_FRICTION = 10.f; + if (friction < -MAX_FRICTION) + friction = -MAX_FRICTION; + if (friction > MAX_FRICTION) + friction = MAX_FRICTION; + return friction; + +} + +inline btScalar calculateCombinedRestitution(float restitution0,float restitution1) +{ + return restitution0 * restitution1; +} + + + +bool CustomMaterialCombinerCallback(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1) +{ + + float friction0 = colObj0->getFriction(); + float friction1 = colObj1->getFriction(); + float restitution0 = colObj0->getRestitution(); + float restitution1 = colObj1->getRestitution(); + + if (colObj0->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) + { + friction0 = 1.0;//partId0,index0 + restitution0 = 0.f; + } + if (colObj1->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) + { + if (index1&1) + { + friction1 = 1.0f;//partId1,index1 + } else + { + friction1 = 0.f; + } + restitution1 = 0.f; + } + + cp.m_combinedFriction = calculateCombinedFriction(friction0,friction1); + cp.m_combinedRestitution = calculateCombinedRestitution(restitution0,restitution1); + + //this return value is currently ignored, but to be on the safe side: return false if you don't calculate friction + return true; +} + +extern ContactAddedCallback gContactAddedCallback; + + + +int main(int argc,char** argv) +{ + gContactAddedCallback = CustomMaterialCombinerCallback; + + ConcaveDemo* concaveDemo = new ConcaveDemo(); + concaveDemo->initPhysics(); + concaveDemo->setCameraDistance(30.f); +//cannot run stepFront yet, the OpenGL context is not opened (stepFront updates camera...) +// concaveDemo->stepFront(); +// concaveDemo->stepFront(); +// concaveDemo->stepFront(); +// concaveDemo->stepFront(); + + return glutmain(argc, argv,640,480,"Moving Concave Mesh Demo",concaveDemo); +} + +void ConcaveDemo::renderme() +{ + updateCamera(); + + btScalar m[16]; + + if (m_dynamicsWorld) + { + btVector3 worldBoundsMin,worldBoundsMax; + getDynamicsWorld()->getBroadphase()->getBroadphaseAabb(worldBoundsMin,worldBoundsMax); + + + int numObjects = m_dynamicsWorld->getNumCollisionObjects(); + btVector3 wireColor(1,0,0); + for (int i=0;igetCollisionObjectArray()[i]; + btRigidBody* body = btRigidBody::upcast(colObj); + + if (body && body->getMotionState()) + { + btDefaultMotionState* myMotionState = (btDefaultMotionState*)body->getMotionState(); + myMotionState->m_graphicsWorldTrans.getOpenGLMatrix(m); + } else + { + colObj->getWorldTransform().getOpenGLMatrix(m); + } + + btVector3 wireColor(1.f,1.0f,0.5f); //wants deactivation + if (i & 1) + { + wireColor = btVector3(0.f,0.0f,1.f); + } + ///color differently for active, sleeping, wantsdeactivation states + if (colObj->getActivationState() == 1) //active + { + if (i & 1) + { + wireColor += btVector3 (1.f,0.f,0.f); + } else + { + wireColor += btVector3 (.5f,0.f,0.f); + } + } + if (colObj->getActivationState() == 2) //ISLAND_SLEEPING + { + if (i & 1) + { + wireColor += btVector3 (0.f,1.f, 0.f); + } else + { + wireColor += btVector3 (0.f,0.5f,0.f); + } + } + + m_shapeDrawer->drawOpenGL(m,colObj->getCollisionShape(),wireColor,getDebugMode(),worldBoundsMin,worldBoundsMax); + } + + + float xOffset = 10.f; + float yStart = 20.f; + float yIncr = 20.f; + char buf[124]; + + glColor3f(0, 0, 0); + + setOrthographicProjection(); + + sprintf(buf,"mouse to interact"); + GLDebugDrawString(xOffset,xOffset,buf); + xOffset += yIncr; + + /* glRasterPos3f(xOffset,xOffset,0); + sprintf(buf,"space to reset"); + GLDebugDrawString(xOffset,xOffset,buf); + xOffset += yIncr; + */ + + sprintf(buf,"cursor keys and z,x to navigate"); + GLDebugDrawString(xOffset,xOffset,buf); + xOffset += yIncr; + + + sprintf(buf,"i to toggle simulation, s single step"); + GLDebugDrawString(xOffset,xOffset,buf); + xOffset += yIncr; + + + sprintf(buf,"q to quit"); + GLDebugDrawString(xOffset,xOffset,buf); + xOffset += yIncr; + + + sprintf(buf,". to shoot TRIMESH (dot)"); + GLDebugDrawString(xOffset,xOffset,buf); + xOffset += yIncr; + + // not yet hooked up again after refactoring... + +/* glRasterPos3f(xOffset,xOffset,0); + sprintf(buf,"d to toggle deactivation"); + GLDebugDrawString(xOffset,xOffset,buf); + xOffset += yIncr; +*/ + + /* + glRasterPos3f(xOffset,xOffset,0); + sprintf(buf,"a to draw temporal AABBs"); + GLDebugDrawString(xOffset,xOffset,buf); + xOffset += yIncr; + */ + + + sprintf(buf,"h to toggle help text"); + GLDebugDrawString(xOffset,xOffset,buf); + xOffset += yIncr; + + //bool useBulletLCP = !(getDebugMode() & btIDebugDraw::DBG_DisableBulletLCP); + + bool useCCD = ((getDebugMode() & btIDebugDraw::DBG_EnableCCD) != 0); + + + sprintf(buf,"1 CCD mode (adhoc) = %i",useCCD); + GLDebugDrawString(xOffset,xOffset,buf); + xOffset += yIncr; + + + sprintf(buf,"+- shooting speed = %10.2f",m_ShootBoxInitialSpeed); + GLDebugDrawString(xOffset,xOffset,buf); + xOffset += yIncr; + + resetPerspectiveProjection(); + + + } + +} + + + +void ConcaveDemo::initGImpactCollision() +{ + // create trimesh + btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray(NUM_TRIANGLES, + &gIndices[0][0], + 3*sizeof(int), + NUM_VERTICES,(REAL*) &gVertices[0],sizeof(REAL)*3); + + btGImpactMeshShape * trimesh = new btGImpactMeshShape(indexVertexArrays); + trimesh->setLocalScaling(btVector3(4.f,4.f,4.f)); + trimesh->updateBound(); + m_trimeshShape = trimesh; + + //register algorithm + + btCollisionDispatcher * dispatcher = static_cast(m_dynamicsWorld ->getDispatcher()); + btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher); + +} + +void ConcaveDemo::initPhysics() +{ + + btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration(); + + //btConstraintSolver* solver = new btSequentialImpulseConstraintSolver; + btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration); + //btOverlappingPairCache* broadphase = new btSimpleBroadphase(); + btBroadphaseInterface* broadphase = new btSimpleBroadphase(); + + btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver(); + m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,constraintSolver,collisionConfiguration); + + + //create trimesh model and shape + initGImpactCollision(); + + + + float mass = 0.f; + btTransform startTransform; + startTransform.setIdentity(); + + btCollisionShape* staticboxShape1 = new btBoxShape(btVector3(200,1,200));//floor + btCollisionShape* staticboxShape2 = new btBoxShape(btVector3(1,50,200));//left wall + btCollisionShape* staticboxShape3 = new btBoxShape(btVector3(1,50,200));//right wall + btCollisionShape* staticboxShape4 = new btBoxShape(btVector3(200,50,1));//front wall + btCollisionShape* staticboxShape5 = new btBoxShape(btVector3(200,50,1));//back wall + + btCompoundShape* staticScenario = new btCompoundShape();//static scenario + + startTransform.setOrigin(btVector3(0,0,0)); + staticScenario->addChildShape(startTransform,staticboxShape1); + startTransform.setOrigin(btVector3(-200,25,0)); + staticScenario->addChildShape(startTransform,staticboxShape2); + startTransform.setOrigin(btVector3(200,25,0)); + staticScenario->addChildShape(startTransform,staticboxShape3); + startTransform.setOrigin(btVector3(0,25,200)); + staticScenario->addChildShape(startTransform,staticboxShape4); + startTransform.setOrigin(btVector3(0,25,-200)); + staticScenario->addChildShape(startTransform,staticboxShape5); + + startTransform.setOrigin(btVector3(0,0,0)); + + btRigidBody* staticBody = localCreateRigidBody(mass, startTransform,staticScenario); + + staticBody->setCollisionFlags(staticBody->getCollisionFlags()|btCollisionObject::CF_STATIC_OBJECT); + + //enable custom material callback + staticBody->setCollisionFlags(staticBody->getCollisionFlags()|btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + + + //static plane + btVector3 normal(0.4,1.5,-0.4); + normal.normalize(); + btCollisionShape* staticplaneShape6 = new btStaticPlaneShape(normal,0.0);// A plane + + startTransform.setOrigin(btVector3(0,0,0)); + + btRigidBody* staticBody2 = localCreateRigidBody(mass, startTransform,staticplaneShape6 ); + + staticBody2->setCollisionFlags(staticBody2->getCollisionFlags()|btCollisionObject::CF_STATIC_OBJECT); + + { + for (int i=0;i<9;i++) + { + btCollisionShape* boxShape = new btBoxShape(btVector3(1,1,1)); + startTransform.setOrigin(btVector3(2*i-5,2,-3)); + localCreateRigidBody(1, startTransform,boxShape); + } + } + + shootTrimesh(btVector3(0,10,0),btVector3(0,0,0)); + + shootTrimesh(btVector3(0,20,0),btVector3(0,10,0)); + + //m_debugMode |= btIDebugDraw::DBG_DrawWireframe; + +} + +void ConcaveDemo::keyboardCallback(unsigned char key, int x, int y) +{ + m_lastKey = 0; + + switch (key) + { + case 'q' : exit(0); break; + + case 'l' : stepLeft(); break; + case 'r' : stepRight(); break; + case 'f' : stepFront(); break; + case 'b' : stepBack(); break; + case 'z' : zoomIn(); break; + case 'x' : zoomOut(); break; + case 'i' : toggleIdle(); break; + case 'h': + if (m_debugMode & btIDebugDraw::DBG_NoHelpText) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_NoHelpText); + else + m_debugMode |= btIDebugDraw::DBG_NoHelpText; + break; + + case 'w': + if (m_debugMode & btIDebugDraw::DBG_DrawWireframe) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawWireframe); + else + m_debugMode |= btIDebugDraw::DBG_DrawWireframe; + break; + + case 'p': + if (m_debugMode & btIDebugDraw::DBG_ProfileTimings) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_ProfileTimings); + else + m_debugMode |= btIDebugDraw::DBG_ProfileTimings; + break; + + case 'm': + if (m_debugMode & btIDebugDraw::DBG_EnableSatComparison) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_EnableSatComparison); + else + m_debugMode |= btIDebugDraw::DBG_EnableSatComparison; + break; + + case 'n': + if (m_debugMode & btIDebugDraw::DBG_DisableBulletLCP) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DisableBulletLCP); + else + m_debugMode |= btIDebugDraw::DBG_DisableBulletLCP; + break; + + case 't' : + if (m_debugMode & btIDebugDraw::DBG_DrawText) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawText); + else + m_debugMode |= btIDebugDraw::DBG_DrawText; + break; + case 'y': + if (m_debugMode & btIDebugDraw::DBG_DrawFeaturesText) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawFeaturesText); + else + m_debugMode |= btIDebugDraw::DBG_DrawFeaturesText; + break; + case 'a': + if (m_debugMode & btIDebugDraw::DBG_DrawAabb) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawAabb); + else + m_debugMode |= btIDebugDraw::DBG_DrawAabb; + break; + case 'c' : + if (m_debugMode & btIDebugDraw::DBG_DrawContactPoints) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawContactPoints); + else + m_debugMode |= btIDebugDraw::DBG_DrawContactPoints; + break; + + case 'd' : + if (m_debugMode & btIDebugDraw::DBG_NoDeactivation) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_NoDeactivation); + else + m_debugMode |= btIDebugDraw::DBG_NoDeactivation; + if (m_debugMode | btIDebugDraw::DBG_NoDeactivation) + { + gDisableDeactivation = true; + } else + { + gDisableDeactivation = false; + } + break; + + + + + case 'o' : + { + m_stepping = !m_stepping; + break; + } + case 's' : clientMoveAndDisplay(); break; +// case ' ' : newRandom(); break; + case ' ': + clientResetScene(); + break; + case '1': + { + if (m_debugMode & btIDebugDraw::DBG_EnableCCD) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_EnableCCD); + else + m_debugMode |= btIDebugDraw::DBG_EnableCCD; + break; + } + + case '.': + { + shootTrimesh(getCameraPosition(),getCameraTargetPosition()); + break; + } + + case '+': + { + m_ShootBoxInitialSpeed += 10.f; + break; + } + case '-': + { + m_ShootBoxInitialSpeed -= 10.f; + break; + } + + default: +// std::cout << "unused key : " << key << std::endl; + break; + } + + if (getDynamicsWorld() && getDynamicsWorld()->getDebugDrawer()) + getDynamicsWorld()->getDebugDrawer()->setDebugMode(m_debugMode); + + glutPostRedisplay(); + +} + + +void ConcaveDemo::shootTrimesh(const btVector3& startPosition,const btVector3& destination) +{ + + if (m_dynamicsWorld) + { + float mass = 4.f; + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(startPosition); + + btRigidBody* body = this->localCreateRigidBody(mass, startTransform,m_trimeshShape); + + btVector3 linVel(destination[0]-startPosition[0],destination[1]-startPosition[1],destination[2]-startPosition[2]); + linVel.normalize(); + linVel*=m_ShootBoxInitialSpeed*0.25; + + body->getWorldTransform().setOrigin(startPosition); + body->getWorldTransform().setRotation(btQuaternion(0,0,0,1)); + body->setLinearVelocity(linVel); + body->setAngularVelocity(btVector3(0,0,0)); + } +} + +void ConcaveDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + float dt = float(getDeltaTimeMicroseconds()) * 0.000001f; + + m_dynamicsWorld->stepSimulation(dt); + + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + + renderme(); + + glFlush(); + glutSwapBuffers(); + +} + + + + +void ConcaveDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + //optional but useful: debug drawing + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + glFlush(); + glutSwapBuffers(); +} + + diff --git a/Demos/MultiMaterialDemo/CMakeLists.txt b/Demos/MultiMaterialDemo/CMakeLists.txt new file mode 100644 index 0000000..b995b88 --- /dev/null +++ b/Demos/MultiMaterialDemo/CMakeLists.txt @@ -0,0 +1,31 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppMultiMaterialDemo + MultiMaterialDemo.cpp + main.cpp +) + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppMultiMaterialDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppMultiMaterialDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppMultiMaterialDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/MultiMaterialDemo/MultiMaterialDemo.cpp b/Demos/MultiMaterialDemo/MultiMaterialDemo.cpp new file mode 100644 index 0000000..6c748d8 --- /dev/null +++ b/Demos/MultiMaterialDemo/MultiMaterialDemo.cpp @@ -0,0 +1,382 @@ +/* +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 "GLDebugDrawer.h" +#include "MultiMaterialDemo.h" +#include "GL_ShapeDrawer.h" +#include "GlutStuff.h" + +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h" +#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btMaterial.h" + +// Create a custom material, just because we can +class CustomMaterial : public btMaterial +{ +public: + int foo1; + int foo2; + CustomMaterial(){} + CustomMaterial(int a, int b) {foo1 = a; foo2 = b;} +}; + +// Storage for the vertex data +static btVector3* gVertices = 0; +// Storage for the face data +static int* gIndices = 0; +// Storage for the material data +static CustomMaterial* gMaterials = 0; +// Storage for the face -> material index data +static int* gFaceMaterialIndices = 0; + +static btBvhTriangleMeshShape* trimeshShape =0; +static btRigidBody* staticBody = 0; +static float waveheight = 0.f; + +const float TRIANGLE_SIZE=1.f; + + +///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; +inline btScalar calculateCombinedFriction(float friction0,float friction1) +{ + btScalar friction = friction0 * friction1; + + const btScalar MAX_FRICTION = 10.f; + if (friction < -MAX_FRICTION) + friction = -MAX_FRICTION; + if (friction > MAX_FRICTION) + friction = MAX_FRICTION; + return friction; + +} + +inline btScalar calculateCombinedRestitution(float restitution0,float restitution1) +{ + return restitution0 * restitution1; +} + + + +static bool CustomMaterialCombinerCallback(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1) +{ + + // Apply material properties + if (colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE) + { + const btCollisionShape* parent0 = colObj0->getRootCollisionShape(); + if(parent0 != 0 && parent0->getShapeType() == MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE) + { + btMultimaterialTriangleMeshShape* shape = (btMultimaterialTriangleMeshShape*)parent0; + const btMaterial * props = shape->getMaterialProperties(partId0, index0); + cp.m_combinedFriction = calculateCombinedFriction(props->m_friction, colObj1->getFriction()); + cp.m_combinedRestitution = props->m_restitution * colObj1->getRestitution(); + } + } + else if (colObj1->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE) + { + const btCollisionShape* parent1 = colObj1->getRootCollisionShape(); + if(parent1 != 0 && parent1->getShapeType() == MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE) + { + btMultimaterialTriangleMeshShape* shape = (btMultimaterialTriangleMeshShape*)parent1; + const btMaterial * props = shape->getMaterialProperties(partId1, index1); + cp.m_combinedFriction = calculateCombinedFriction(props->m_friction, colObj0->getFriction()); + cp.m_combinedRestitution = props->m_restitution * colObj0->getRestitution(); + } + } + + //this return value is currently ignored, but to be on the safe side: return false if you don't calculate friction + return true; +} + +extern ContactAddedCallback gContactAddedCallback; + +const int NUM_VERTS_X = 20; +const int NUM_VERTS_Y = 50; +const int totalVerts = NUM_VERTS_X*NUM_VERTS_Y; + +void MultiMaterialDemo::setVertexPositions(float waveheight, float offset) +{ + int i; + int j; + + for ( i=0;isetCollisionFlags( staticBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + staticBody->setActivationState(DISABLE_DEACTIVATION); + } else + { + staticBody->setCollisionFlags( staticBody->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT); + staticBody->forceActivationState(ACTIVE_TAG); + } + } + + DemoApplication::keyboardCallback(key,x,y); + +} + +void MultiMaterialDemo::initPhysics() +{ +#define TRISIZE 50.f + + gContactAddedCallback = CustomMaterialCombinerCallback; + + // The number of triangles + const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1); + // The number of materials + const int totalMaterials = 2; + + int vertStride = sizeof(btVector3); + int indexStride = 3*sizeof(int); + int materialStride = sizeof(CustomMaterial); + int triangleMaterialStride = sizeof(int); + + gVertices = new btVector3[totalVerts]; + gIndices = new int[totalTriangles*3]; + gMaterials = new CustomMaterial[totalMaterials]; + gFaceMaterialIndices = new int[totalTriangles]; + + // Explicitly set up the materials. It's a small array so let's do it bit by bit. + gMaterials[0].m_friction = 0; + gMaterials[0].m_restitution = 0.9; + gMaterials[0].foo1 = 5; + gMaterials[0].foo2 = 7; + gMaterials[1].m_friction = 0.9; + gMaterials[1].m_restitution = 0.1; + gMaterials[1].foo1 = 53; + gMaterials[1].foo2 = 15; + + int i; + // Set up the vertex data + setVertexPositions(waveheight,0.f); + int index=0; + // Set up the face data + for ( i=0;imaterial index data + for(int a = 0; a < totalTriangles; a++) + { + // This will give the first half of the faces low friction and high restitution + // and the second half of the faces high friction and low restitution + if(a > totalTriangles*0.5f) + gFaceMaterialIndices[a] = 0; + else + gFaceMaterialIndices[a] = 1; + } + + // Create the array structure + m_indexVertexArrays = new btTriangleIndexVertexMaterialArray( + totalTriangles, gIndices, indexStride, + totalVerts,(btScalar*) &gVertices[0].x(),vertStride, + totalMaterials, (unsigned char *)gMaterials, sizeof(CustomMaterial), + gFaceMaterialIndices, sizeof(int)); + + bool useQuantizedAabbCompression = true; + // Create the multimaterial mesh shape + trimeshShape = new btMultimaterialTriangleMeshShape((btTriangleIndexVertexMaterialArray*)m_indexVertexArrays,useQuantizedAabbCompression); + m_collisionShapes.push_back(trimeshShape); + + btCollisionShape* groundShape = trimeshShape; + + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + + btVector3 worldMin(-1000,-1000,-1000); + btVector3 worldMax(1000,1000,1000); + m_broadphase = new btAxisSweep3(worldMin,worldMax); + m_solver = new btSequentialImpulseConstraintSolver(); + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + + float mass = 0.f; + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(0,-2,0)); + + btCollisionShape* colShape = new btBoxShape(btVector3(0.5f,0.5f,0.5f)); + m_collisionShapes.push_back(colShape); + + { + for (int i=0;i<1;i++) + { + startTransform.setOrigin(btVector3(10,10,-20)); + btRigidBody* body = localCreateRigidBody(1, startTransform,colShape); + body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + body->setFriction(0.9f); + body->setGravity(btVector3(0,-20.f,0)); + body->applyCentralImpulse(btVector3(-7.7f,0,0)); + } + } + + startTransform.setIdentity(); + staticBody = localCreateRigidBody(mass, startTransform,groundShape); + + staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT); + + //enable custom material callback + staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); +} + +void MultiMaterialDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + float dt = getDeltaTimeMicroseconds() * 0.000001f; + + if (m_animatedMesh) + { + static float offset=0.f; + offset+=0.01f; + + // setVertexPositions(waveheight,offset); + + int i; + int j; + btVector3 aabbMin(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); + btVector3 aabbMax(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT); + + for ( i=NUM_VERTS_X/2-3;ipartialRefitTree(aabbMin,aabbMax); + + //clear all contact points involving mesh proxy. Note: this is a slow/unoptimized operation. + m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(staticBody->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher()); + } + + m_dynamicsWorld->stepSimulation(dt); + + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + + renderme(); + + glFlush(); + glutSwapBuffers(); + +} + + + + +void MultiMaterialDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + glFlush(); + glutSwapBuffers(); +} + + + +void MultiMaterialDemo::exitPhysics() +{ + + + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;j m_collisionShapes; + + btTriangleIndexVertexArray* m_indexVertexArrays; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + bool m_animatedMesh; + + public: + + MultiMaterialDemo() : m_animatedMesh(true) + { + + } + void initPhysics(); + + void exitPhysics(); + + virtual ~MultiMaterialDemo() + { + exitPhysics(); + } + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + //to show refit works + void setVertexPositions(float waveheight, float offset); + + virtual void keyboardCallback(unsigned char key, int x, int y); + + static DemoApplication* Create() + { + MultiMaterialDemo* demo = new MultiMaterialDemo(); + demo->myinit(); + demo->initPhysics(); + return demo; + }; +}; + +#endif //CONCAVE_DEMO_H + diff --git a/Demos/MultiMaterialDemo/main.cpp b/Demos/MultiMaterialDemo/main.cpp new file mode 100644 index 0000000..9b8d35b --- /dev/null +++ b/Demos/MultiMaterialDemo/main.cpp @@ -0,0 +1,22 @@ + +#include "MultiMaterialDemo.h" +#include "GlutStuff.h" + +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" + +GLDebugDrawer gDebugDrawer; + +int main(int argc,char** argv) +{ + + MultiMaterialDemo* multiMaterialDemo = new MultiMaterialDemo(); + multiMaterialDemo->initPhysics(); + multiMaterialDemo->setCameraDistance(30.f); + + multiMaterialDemo->getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + return glutmain(argc, argv,640,480,"Multimaterial Mesh Demo",multiMaterialDemo); +} + diff --git a/Demos/MultiThreadedDemo/CMakeLists.txt b/Demos/MultiThreadedDemo/CMakeLists.txt new file mode 100644 index 0000000..75da820 --- /dev/null +++ b/Demos/MultiThreadedDemo/CMakeLists.txt @@ -0,0 +1,55 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +${VECTOR_MATH_INCLUDE} +) + +IF(WIN32) + ADD_DEFINITIONS(-DGLEW_STATIC) +ENDIF(WIN32) + +LINK_LIBRARIES( +OpenGLSupport BulletMultiThreaded BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppMultiThreadedDemo + main.cpp + MultiThreadedDemo.cpp + MultiThreadedDemo.h +) +IF (UNIX) + TARGET_LINK_LIBRARIES(AppMultiThreadedDemo pthread) +ENDIF(UNIX) + +IF(WIN32) +IF (CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppMultiThreadedDemo POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} ) + ENDIF() +ELSE(CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppMultiThreadedDemo POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR}) + ENDIF() +ENDIF(CMAKE_CL_64) +ENDIF(WIN32) + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppMultiThreadedDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppMultiThreadedDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppMultiThreadedDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/MultiThreadedDemo/Makefile.am b/Demos/MultiThreadedDemo/Makefile.am new file mode 100644 index 0000000..71d8dd3 --- /dev/null +++ b/Demos/MultiThreadedDemo/Makefile.am @@ -0,0 +1,5 @@ +noinst_PROGRAMS=MultiThreadedDemo + +MultiThreadedDemo_SOURCES=MultiThreadedDemo.cpp MultiThreadedDemo.h main.cpp +MultiThreadedDemo_CXXFLAGS=-I@top_builddir@/src -I@top_builddir@/Demos/OpenGL -I@top_builddir@/Extras $(CXXFLAGS) +MultiThreadedDemo_LDADD=-L../OpenGL -L../../Extras -L../../src -lbulletmultithreaded -lbulletopenglsupport -lbulletdynamics -lbulletcollision -lbulletmath @opengl_LIBS@ -lpthread diff --git a/Demos/MultiThreadedDemo/MultiThreadedDemo.cpp b/Demos/MultiThreadedDemo/MultiThreadedDemo.cpp new file mode 100644 index 0000000..521fd81 --- /dev/null +++ b/Demos/MultiThreadedDemo/MultiThreadedDemo.cpp @@ -0,0 +1,504 @@ +/* +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. +*/ + +#define USE_PARALLEL_SOLVER 1 //experimental parallel solver +#define USE_PARALLEL_DISPATCHER 1 + +#include "btBulletDynamicsCommon.h" +#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" + +#ifdef USE_PARALLEL_DISPATCHER +#include "BulletMultiThreaded/SpuGatheringCollisionDispatcher.h" +#include "BulletMultiThreaded/PlatformDefinitions.h" + +#ifdef USE_LIBSPE2 +#include "BulletMultiThreaded/SpuLibspe2Support.h" +#elif defined (_WIN32) +#include "BulletMultiThreaded/Win32ThreadSupport.h" +#include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" + +#elif defined (USE_PTHREADS) + +#include "BulletMultiThreaded/PosixThreadSupport.h" +#include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" + +#else +//other platforms run the parallel code sequentially (until pthread support or other parallel implementation is added) + +#include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" +#endif //USE_LIBSPE2 + +#ifdef USE_PARALLEL_SOLVER +#include "BulletMultiThreaded/btParallelConstraintSolver.h" +#include "BulletMultiThreaded/SequentialThreadSupport.h" + + +btThreadSupportInterface* createSolverThreadSupport(int maxNumThreads) +{ +//#define SEQUENTIAL +#ifdef SEQUENTIAL + SequentialThreadSupport::SequentialThreadConstructionInfo tci("solverThreads",SolverThreadFunc,SolverlsMemoryFunc); + SequentialThreadSupport* threadSupport = new SequentialThreadSupport(tci); + threadSupport->startSPU(); +#else + +#ifdef _WIN32 + Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("solverThreads",SolverThreadFunc,SolverlsMemoryFunc,maxNumThreads); + Win32ThreadSupport* threadSupport = new Win32ThreadSupport(threadConstructionInfo); + threadSupport->startSPU(); +#elif defined (USE_PTHREADS) + PosixThreadSupport::ThreadConstructionInfo solverConstructionInfo("solver", SolverThreadFunc, + SolverlsMemoryFunc, maxNumThreads); + + PosixThreadSupport* threadSupport = new PosixThreadSupport(solverConstructionInfo); + +#else + SequentialThreadSupport::SequentialThreadConstructionInfo tci("solverThreads",SolverThreadFunc,SolverlsMemoryFunc); + SequentialThreadSupport* threadSupport = new SequentialThreadSupport(tci); + threadSupport->startSPU(); +#endif + +#endif + + return threadSupport; +} + +#endif //USE_PARALLEL_SOLVER + +#endif//USE_PARALLEL_DISPATCHER + + + + +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btIDebugDraw.h" + + + +#include //printf debugging + +#include "MultiThreadedDemo.h" +#include "GL_ShapeDrawer.h" + +#include "GlutStuff.h" + + +extern float eye[3]; +extern int glutScreenWidth; +extern int glutScreenHeight; + +const int maxProxies = 32766; +const int maxOverlap = 65535; + + + + +#ifdef _DEBUG +const int gNumObjects = 120; +#else +const int gNumObjects = 120;//try this in release mode: 3000. never go above 16384, unless you increate maxNumObjects value in DemoApplication.cp +#endif + + +const int maxNumObjects = 32760; + +static int shapeIndex[maxNumObjects]; + + +#define CUBE_HALF_EXTENTS 0.5 + +#define EXTRA_HEIGHT -10.f +//GL_LineSegmentShape shapeE(btVector3(-50,0,0), +// btVector3(50,0,0)); + + +void MultiThreadedDemo::createStack( btCollisionShape* boxShape, float halfCubeSize, int size, float zPos ) +{ + btTransform trans; + trans.setIdentity(); + + for(int i=0; istepSimulation(1.0f/60.f,0); + //CProfileManager::dumpAll(); + +#else + //during idle mode, just run 1 simulation step maximum + int maxSimSubSteps = m_idle ? 1 : 1; + if (m_idle) + dt = 1.0/420.f; + + int numSimSteps = 0; + numSimSteps = m_dynamicsWorld->stepSimulation(dt,maxSimSubSteps); + + +#ifdef VERBOSE_TIMESTEPPING_CONSOLEOUTPUT + if (!numSimSteps) + printf("Interpolated transforms\n"); + else + { + if (numSimSteps > maxSimSubSteps) + { + //detect dropping frames + printf("Dropped (%i) simulation steps out of %i\n",numSimSteps - maxSimSubSteps,numSimSteps); + } else + { + printf("Simulated (%i) steps\n",numSimSteps); + } + } +#endif //VERBOSE_TIMESTEPPING_CONSOLEOUTPUT + +#endif + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + + } + +#ifdef USE_QUICKPROF + btProfiler::beginBlock("render"); +#endif //USE_QUICKPROF + + renderme(); + + + //render the graphics objects, with center of mass shift + + updateCamera(); + + + +#ifdef USE_QUICKPROF + btProfiler::endBlock("render"); +#endif + glFlush(); + + + glutSwapBuffers(); + +} + + + +void MultiThreadedDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //optional but useful: debug drawing + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + + renderme(); + + glFlush(); + glutSwapBuffers(); +} + + + + + +void MultiThreadedDemo::initPhysics() +{ +#ifdef USE_PARALLEL_DISPATCHER + m_threadSupportSolver = 0; + m_threadSupportCollision = 0; +#endif + +//#define USE_GROUND_PLANE 1 +#ifdef USE_GROUND_PLANE + m_collisionShapes.push_back(new btStaticPlaneShape(btVector3(0,1,0),0.5)); +#else + + ///Please don't make the box sizes larger then 1000: the collision detection will be inaccurate. + ///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=346 + m_collisionShapes.push_back(new btBoxShape (btVector3(200,CUBE_HALF_EXTENTS,200))); +#endif + + m_collisionShapes.push_back(new btBoxShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS))); + + + + setCameraDistance(32.5f); + + m_azi = 90.f; + + m_dispatcher=0; + btDefaultCollisionConstructionInfo cci; + cci.m_defaultMaxPersistentManifoldPoolSize = 32768; + m_collisionConfiguration = new btDefaultCollisionConfiguration(cci); + +#ifdef USE_PARALLEL_DISPATCHER + int maxNumOutstandingTasks = 4; + +#ifdef USE_WIN32_THREADING + +m_threadSupportCollision = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo( + "collision", + processCollisionTask, + createCollisionLocalStoreMemory, + maxNumOutstandingTasks)); +#else + +#ifdef USE_LIBSPE2 + + spe_program_handle_t * program_handle; +#ifndef USE_CESOF + program_handle = spe_image_open ("./spuCollision.elf"); + if (program_handle == NULL) + { + perror( "SPU OPEN IMAGE ERROR\n"); + } + else + { + printf( "IMAGE OPENED\n"); + } +#else + extern spe_program_handle_t spu_program; + program_handle = &spu_program; +#endif + SpuLibspe2Support* threadSupportCollision = new SpuLibspe2Support( program_handle, maxNumOutstandingTasks); +#elif defined (USE_PTHREADS) + PosixThreadSupport::ThreadConstructionInfo constructionInfo("collision", + processCollisionTask, + createCollisionLocalStoreMemory, + maxNumOutstandingTasks); + m_threadSupportCollision = new PosixThreadSupport(constructionInfo); +#else + + SequentialThreadSupport::SequentialThreadConstructionInfo colCI("collision",processCollisionTask,createCollisionLocalStoreMemory); + SequentialThreadSupport* m_threadSupportCollision = new SequentialThreadSupport(colCI); + +#endif //USE_LIBSPE2 + +///Playstation 3 SPU (SPURS) version is available through PS3 Devnet +/// For Unix/Mac someone could implement a pthreads version of btThreadSupportInterface? +///you can hook it up to your custom task scheduler by deriving from btThreadSupportInterface +#endif + + + m_dispatcher = new SpuGatheringCollisionDispatcher(m_threadSupportCollision,maxNumOutstandingTasks,m_collisionConfiguration); +// m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); +#else + + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); +#endif //USE_PARALLEL_DISPATCHER + + + btVector3 worldAabbMin(-1000,-1000,-1000); + btVector3 worldAabbMax(1000,1000,1000); + + + + m_broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies); + + + +#ifdef USE_PARALLEL_SOLVER + m_threadSupportSolver = createSolverThreadSupport(maxNumOutstandingTasks); + m_solver = new btParallelConstraintSolver(m_threadSupportSolver); + //this solver requires the contacts to be in a contiguous pool, so avoid dynamic allocation + m_dispatcher->setDispatcherFlags(btCollisionDispatcher::CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION); +#else + + btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver(); + m_solver = solver; + //default solverMode is SOLVER_RANDMIZE_ORDER. Warmstarting seems not to improve convergence, see + //solver->setSolverMode(0);//btSequentialImpulseConstraintSolver::SOLVER_USE_WARMSTARTING | btSequentialImpulseConstraintSolver::SOLVER_RANDMIZE_ORDER); +#endif //USE_PARALLEL_SOLVER + + + btDiscreteDynamicsWorld* world = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + m_dynamicsWorld = world; + + world->getSimulationIslandManager()->setSplitIslands(false); + world->getSolverInfo().m_numIterations = 4; + world->getSolverInfo().m_solverMode = SOLVER_SIMD+SOLVER_USE_WARMSTARTING;//+SOLVER_RANDMIZE_ORDER; + + m_dynamicsWorld->getDispatchInfo().m_enableSPU = true; + m_dynamicsWorld->setGravity(btVector3(0,-10,0)); + + + + int i; + + btTransform tr; + tr.setIdentity(); + + + for (i=0;i0) + { + shapeIndex[i] = 1;//sphere + } + else + shapeIndex[i] = 0; + } + + + btTransform trans; + trans.setIdentity(); + + btScalar halfExtents = CUBE_HALF_EXTENTS; + + trans.setOrigin(btVector3(0,-halfExtents,0)); + + + + localCreateRigidBody(0.f,trans,m_collisionShapes[shapeIndex[0]]); + + int numWalls = 15; + int wallHeight = 15; + float wallDistance = 3; + + + for ( i=0;isetLinearVelocity(btVector3(0,0,-10)); +#endif +// clientResetScene(); + + +} + + + + + + +void MultiThreadedDemo::exitPhysics() +{ + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;j m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + class btThreadSupportInterface* m_threadSupportCollision; + class btThreadSupportInterface* m_threadSupportSolver; + + btConstraintSolver* m_solver; + + btCollisionAlgorithmCreateFunc* m_boxBoxCF; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + + public: + + void initPhysics(); + + void exitPhysics(); + + virtual ~MultiThreadedDemo() + { + exitPhysics(); + } + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + void createStack( btCollisionShape* boxShape, float halfCubeSize, int size, float zPos ); + + static DemoApplication* Create() + { + MultiThreadedDemo* demo = new MultiThreadedDemo; + demo->myinit(); + demo->initPhysics(); + return demo; + } + +}; + +#endif //MULTI_THREADED_DEMO_H + diff --git a/Demos/MultiThreadedDemo/main.cpp b/Demos/MultiThreadedDemo/main.cpp new file mode 100644 index 0000000..36b56de --- /dev/null +++ b/Demos/MultiThreadedDemo/main.cpp @@ -0,0 +1,36 @@ +/* +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 +#include "MultiThreadedDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" + +GLDebugDrawer gDebugDrawer; + +int main(int argc,char** argv) +{ + MultiThreadedDemo* demo = new MultiThreadedDemo(); + + demo->initPhysics(); + demo->getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + + glutmain(argc, argv,640,480,"Bullet Physics Demo. http://bulletphysics.com",demo); + + delete demo; + + return EXIT_SUCCESS; +} diff --git a/Demos/NativeClient/bin_html/bind.js b/Demos/NativeClient/bin_html/bind.js new file mode 100644 index 0000000..92fbbd2 --- /dev/null +++ b/Demos/NativeClient/bin_html/bind.js @@ -0,0 +1,22 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview This class implements an extension to Function object that + * lets you bind a scope for |this| to a function. + */ + +/** + * Bind a scope to a function. Used to bind an object to |this| for event + * handlers. + * @param {!Object} scope The scope in which the function executes. |scope| + * becomes |this| during function execution. + * @return {function} the bound version of the original function. + */ +Function.prototype.bind = function(scope) { + var boundContext = this; + return function() { + return boundContext.apply(scope, arguments); + } +} diff --git a/Demos/NativeClient/bin_html/dragger.js b/Demos/NativeClient/bin_html/dragger.js new file mode 100644 index 0000000..232d8b5 --- /dev/null +++ b/Demos/NativeClient/bin_html/dragger.js @@ -0,0 +1,134 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview This class implements a mouse-drag event. It registers for + * mousedown events, and when it sees one, starts capturing mousemove events + * until it gets a mousup event. It manufactures three drag events: the + * DRAG_START, DRAG and DRAG_END. + */ + +// Requires bind + +/** + * Constructor for the Dragger. Register for mousedown events that happen on + * |opt_target|. If |opt_target| is null or undefined, then this object + * observes mousedown on the whole document. + * @param {?Element} opt_target The event target. Defaults to the whole + * document. + * @constructor + */ +tumbler.Dragger = function(opt_target) { + /** + * The event target. + * @type {Element} + * @private + */ + this.target_ = opt_target || document; + + /** + * The array of objects that get notified of drag events. Each object in + * this array get sent a handleStartDrag(), handleDrag() and handleEndDrag() + * message. + * @type {Array.} + * @private + */ + this.listeners_ = []; + + /** + * Flag to indicate whether the object is in a drag sequence or not. + * @type {boolean} + * @private + */ + this.isDragging_ = false; + + /** + * The function objects that get attached as event handlers. These are + * cached so that they can be removed on mouse up. + * @type {function} + * @private + */ + this.boundMouseMove_ = null; + this.boundMouseUp_ = null; + + this.target_.addEventListener('mousedown', + this.onMouseDown.bind(this), + false); +} + +/** + * The ids used for drag event types. + * @enum {string} + */ +tumbler.Dragger.DragEvents = { + DRAG_START: 'dragstart', // Start a drag sequence + DRAG: 'drag', // Mouse moved during a drag sequence. + DRAG_END: 'dragend' // End a drag sewquence. +}; + +/** + * Add a drag listener. Each listener should respond to thhree methods: + * handleStartDrag(), handleDrag() and handleEndDrag(). This method assumes + * that |listener| does not already exist in the array of listeners. + * @param {!Object} listener The object that will listen to drag events. + */ +tumbler.Dragger.prototype.addDragListener = function(listener) { + this.listeners_.push(listener); +} + +/** + * Handle a mousedown event: register for mousemove and mouseup, then tell + * the target that is has a DRAG_START event. + * @param {Event} event The mousedown event that triggered this method. + */ +tumbler.Dragger.prototype.onMouseDown = function(event) { + this.boundMouseMove_ = this.onMouseMove.bind(this); + this.boundMouseUp_ = this.onMouseUp.bind(this); + this.target_.addEventListener('mousemove', this.boundMouseMove_); + this.target_.addEventListener('mouseup', this.boundMouseUp_); + this.isDragging_ = true; + var dragStartEvent = { type: tumbler.Dragger.DragEvents.DRAG_START, + clientX: event.offsetX, + clientY: event.offsetY }; + var i; + for (i = 0; i < this.listeners_.length; ++i) { + this.listeners_[i].handleStartDrag(this.target_, dragStartEvent); + } +} + +/** + * Handle a mousemove event: tell the target that is has a DRAG event. + * @param {Event} event The mousemove event that triggered this method. + */ +tumbler.Dragger.prototype.onMouseMove = function(event) { + if (!this.isDragging_) + return; + var dragEvent = { type: tumbler.Dragger.DragEvents.DRAG, + clientX: event.offsetX, + clientY: event.offsetY}; + var i; + for (i = 0; i < this.listeners_.length; ++i) { + this.listeners_[i].handleDrag(this.target_, dragEvent); + } +} + +/** + * Handle a mouseup event: un-register for mousemove and mouseup, then tell + * the target that is has a DRAG_END event. + * @param {Event} event The mouseup event that triggered this method. + */ +tumbler.Dragger.prototype.onMouseUp = function(event) { + this.target_.removeEventListener('mouseup', this.boundMouseUp_, false); + this.target_.removeEventListener('mousemove', this.boundMouseMove_, false); + this.boundMouseUp_ = null; + this.boundMouseMove_ = null; + this.isDragging_ = false; + var dragEndEvent = { type: tumbler.Dragger.DragEvents.DRAG_END, + clientX: event.offsetX, + clientY: event.offsetY}; + var i; + for (i = 0; i < this.listeners_.length; ++i) { + this.listeners_[i].handleEndDrag(this.target_, dragEndEvent); + } +} diff --git a/Demos/NativeClient/bin_html/httpd.cmd b/Demos/NativeClient/bin_html/httpd.cmd new file mode 100644 index 0000000..5a31ae7 --- /dev/null +++ b/Demos/NativeClient/bin_html/httpd.cmd @@ -0,0 +1,9 @@ +@echo off +setlocal + +REM Relative path of CygWin +set CYGWIN=%~dp0%..\third_party\cygwin\bin + +PATH=%CYGWIN%;%PATH% + +python httpd.py diff --git a/Demos/NativeClient/bin_html/httpd.py b/Demos/NativeClient/bin_html/httpd.py new file mode 100644 index 0000000..65434a8 --- /dev/null +++ b/Demos/NativeClient/bin_html/httpd.py @@ -0,0 +1,114 @@ +#!/usr/bin/python +# +# Copyright (c) 2011, The Native Client Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# + +"""A tiny web server. + +This is intended to be used for testing, and only run from within the examples +directory. +""" + +import BaseHTTPServer +import logging +import os +import SimpleHTTPServer +import SocketServer +import sys +import urlparse + +logging.getLogger().setLevel(logging.INFO) + +# Using 'localhost' means that we only accept connections +# via the loop back interface. +SERVER_PORT = 5103 +SERVER_HOST = '' + +# We only run from the examples directory (the one that contains scons-out), so +# that not too much is exposed via this HTTP server. Everything in the +# directory is served, so there should never be anything potentially sensitive +# in the serving directory, especially if the machine might be a +# multi-user machine and not all users are trusted. We only serve via +# the loopback interface. + +SAFE_DIR_COMPONENTS = ['bin_html'] +SAFE_DIR_SUFFIX = apply(os.path.join, SAFE_DIR_COMPONENTS) + +def SanityCheckDirectory(): + if os.getcwd().endswith(SAFE_DIR_SUFFIX): + return + logging.error('httpd.py should only be run from the %s', SAFE_DIR_SUFFIX) + logging.error('directory for testing purposes.') + logging.error('We are currently in %s', os.getcwd()) + sys.exit(1) + + +# An HTTP server that will quit when |is_running| is set to False. We also use +# SocketServer.ThreadingMixIn in order to handle requests asynchronously for +# faster responses. +class QuittableHTTPServer(SocketServer.ThreadingMixIn, + BaseHTTPServer.HTTPServer): + def serve_forever(self, timeout=0.5): + self.is_running = True + self.timeout = timeout + while self.is_running: + self.handle_request() + + def shutdown(self): + self.is_running = False + return 1 + + +# "Safely" split a string at |sep| into a [key, value] pair. If |sep| does not +# exist in |str|, then the entire |str| is the key and the value is set to an +# empty string. +def KeyValuePair(str, sep='='): + if sep in str: + return str.split(sep) + else: + return [str, ''] + + +# A small handler that looks for '?quit=1' query in the path and shuts itself +# down if it finds that parameter. +class QuittableHTTPHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): + def do_GET(self): + (_, _, _, query, _) = urlparse.urlsplit(self.path) + url_params = dict([KeyValuePair(key_value) + for key_value in query.split('&')]) + if 'quit' in url_params and '1' in url_params['quit']: + self.send_response(200, 'OK') + self.send_header('Content-type', 'text/html') + self.send_header('Content-length', '0') + self.end_headers() + self.server.shutdown() + return + + SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self) + + +def Run(server_address, + server_class=QuittableHTTPServer, + handler_class=QuittableHTTPHandler): + httpd = server_class(server_address, handler_class) + logging.info("Starting local server on port %d", server_address[1]) + logging.info("To shut down send http://localhost:%d?quit=1", + server_address[1]) + try: + httpd.serve_forever() + except KeyboardInterrupt: + logging.info("Received keyboard interrupt.") + httpd.server_close() + + logging.info("Shutting down local server on port %d", server_address[1]) + + +if __name__ == '__main__': + SanityCheckDirectory() + if len(sys.argv) > 1: + Run((SERVER_HOST, int(sys.argv[1]))) + else: + Run((SERVER_HOST, SERVER_PORT)) + sys.exit(0) diff --git a/Demos/NativeClient/bin_html/index.html b/Demos/NativeClient/bin_html/index.html new file mode 100644 index 0000000..a3002da --- /dev/null +++ b/Demos/NativeClient/bin_html/index.html @@ -0,0 +1,33 @@ + + + + + Interactive Cube Example + + + + + + + + +

    Interactive Cube Example

    +

    + The Native Client module executed in this page draws a 3D cube + and allows you to rotate it using a virtual trackball method. +

    +
    + + + diff --git a/Demos/NativeClient/bin_html/trackball.js b/Demos/NativeClient/bin_html/trackball.js new file mode 100644 index 0000000..88b9a62 --- /dev/null +++ b/Demos/NativeClient/bin_html/trackball.js @@ -0,0 +1,296 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Implement a virtual trackball in the tumbler.Trackball + * class. This class maps 2D mouse events to 3D rotations by simulating a + * trackball that you roll by dragging the mouse. There are two principle + * methods in the class: startAtPointInFrame which you use to begin a trackball + * simulation and rollToPoint, which you use while dragging the mouse. The + * rollToPoint method returns a rotation expressed as a quaternion. + */ + + +// Requires tumbler.Application +// Requires tumbler.DragEvent +// Requires tumbler.Vector3 + +/** + * Constructor for the Trackball object. This class maps 2D mouse drag events + * into 3D rotations by simulating a trackball. The idea is to simulate + * clicking on the trackball, and then rolling it as you drag the mouse. + * The math behind the trackball is simple: start with a vector from the first + * mouse-click on the ball to the center of the 3D view. At the same time, set + * the radius of the ball to be the smaller dimension of the 3D view. As you + * drag the mouse around in the 3D view, a second vector is computed from the + * surface of the ball to the center. The axis of rotation is the cross + * product of these two vectors, and the angle of rotation is the angle between + * the two vectors. + * @constructor + */ +tumbler.Trackball = function() { + /** + * The square of the trackball's radius. The math never looks at the radius, + * but looks at the radius squared. + * @type {number} + * @private + */ + this.sqrRadius_ = 0; + + /** + * The 3D vector representing the point on the trackball where the mouse + * was clicked. Default is pointing stright through the center of the ball. + * @type {Object} + * @private + */ + this.rollStart_ = new tumbler.Vector3(0, 0, 1); + + /** + * The 2D center of the frame that encloses the trackball. + * @type {!Object} + * @private + */ + this.center_ = { x: 0, y: 0 }; + + /** + * Cached camera orientation. When a drag START event happens this is set to + * the current orientation in the calling view's plugin. The default is the + * identity quaternion. + * @type {Array.} + * @private + */ + this.cameraOrientation_ = [0, 0, 0, 1]; +}; + +/** + * Compute the dimensions of the virtual trackball to fit inside |frameSize|. + * The radius of the trackball is set to be 1/2 of the smaller of the two frame + * dimensions, the center point is at the midpoint of each side. + * @param {!goog.math.Size} frameSize 2D-point representing the size of the + * element that encloses the virtual trackball. + * @private + */ +tumbler.Trackball.prototype.initInFrame_ = function(frameSize) { + // Compute the radius of the virtual trackball. This is 1/2 of the smaller + // of the frame's width and height. + var halfFrameSize = 0.5 * Math.min(frameSize.width, frameSize.height); + // Cache the square of the trackball's radius. + this.sqrRadius_ = halfFrameSize * halfFrameSize; + // Figure the center of the view. + this.center_.x = frameSize.width * 0.5; + this.center_.y = frameSize.height * 0.5; +}; + +/** + * Method to convert (by translation) a 2D client point from a coordinate space + * with origin in the lower-left corner of the client view to a space with + * origin in the center of the client view. Use this method before mapping the + * 2D point to he 3D tackball point (see also the projectOnTrackball_() method). + * Call the startAtPointInFrame before calling this method so that the + * |center_| property is correctly initialized. + * @param {!Object} clientPoint map this point to the coordinate space with + * origin in thecenter of the client view. + * @return {Object} the converted point. + * @private + */ +tumbler.Trackball.prototype.convertClientPoint_ = function(clientPoint) { + var difference = { x: clientPoint.x - this.center_.x, + y: clientPoint.y - this.center_.y } + return difference; +}; + +/** + * Method to map a 2D point to a 3D point on the virtual trackball that was set + * up using the startAtPointInFrame method. If the point lies outside of the + * radius of the virtual trackball, then the z-coordinate of the 3D point + * is set to 0. + * @param {!Object.} point 2D-point in the coordinate space with origin + * in the center of the client view. + * @return {tumbler.Vector3} the 3D point on the virtual trackball. + * @private + */ +tumbler.Trackball.prototype.projectOnTrackball_ = function(point) { + var sqrRadius2D = point.x * point.x + point.y * point.y; + var zValue; + if (sqrRadius2D > this.sqrRadius_) { + // |point| lies outside the virtual trackball's sphere, so use a virtual + // z-value of 0. This is equivalent to clicking on the horizontal equator + // of the trackball. + zValue = 0; + } else { + // A sphere can be defined as: r^2 = x^2 + y^2 + z^2, so z = + // sqrt(r^2 - (x^2 + y^2)). + zValue = Math.sqrt(this.sqrRadius_ - sqrRadius2D); + } + var trackballPoint = new tumbler.Vector3(point.x, point.y, zValue); + return trackballPoint; +}; + +/** + * Method to start up the trackball. The trackball works by pretending that a + * ball encloses the 3D view. You roll this pretend ball with the mouse. For + * example, if you click on the center of the ball and move the mouse straight + * to the right, you roll the ball around its Y-axis. This produces a Y-axis + * rotation. You can click on the "edge" of the ball and roll it around + * in a circle to get a Z-axis rotation. + * @param {!Object.} startPoint 2D-point, usually the mouse-down + * point. + * @param {!Object.} frameSize 2D-point representing the size of + * the element that encloses the virtual trackball. + */ +tumbler.Trackball.prototype.startAtPointInFrame = + function(startPoint, frameSize) { + this.initInFrame_(frameSize); + // Compute the starting vector from the surface of the ball to its center. + this.rollStart_ = this.projectOnTrackball_( + this.convertClientPoint_(startPoint)); +}; + +/** + * Method to roll the virtual trackball; call this in response to a mouseDrag + * event. Takes |dragPoint| and projects it from 2D mouse coordinates onto the + * virtual track ball that was set up in startAtPointInFrame method. + * Returns a quaternion that represents the rotation from |rollStart_| to + * |rollEnd_|. + * @param {!Object.} dragPoint 2D-point representing the + * destination mouse point. + * @return {Array.} a quaternion that represents the rotation from + * the point wnere the mouse was clicked on the trackball to this point. + * The quaternion looks like this: [[v], cos(angle/2)], where [v] is the + * imaginary part of the quaternion and is computed as [x, y, z] * + * sin(angle/2). + */ +tumbler.Trackball.prototype.rollToPoint = function(dragPoint) { + var rollTo = this.convertClientPoint_(dragPoint); + if ((Math.abs(this.rollStart_.x - rollTo.x) < + tumbler.Trackball.DOUBLE_EPSILON) && + (Math.abs(this.rollStart_.y, rollTo.y) < + tumbler.Trackball.DOUBLE_EPSILON)) { + // Not enough change in the vectors to roll the ball, return the identity + // quaternion. + return [0, 0, 0, 1]; + } + + // Compute the ending vector from the surface of the ball to its center. + var rollEnd = this.projectOnTrackball_(rollTo); + + // Take the cross product of the two vectors. r = s X e + var rollVector = this.rollStart_.cross(rollEnd); + var invStartMag = 1.0 / this.rollStart_.magnitude(); + var invEndMag = 1.0 / rollEnd.magnitude(); + + // cos(a) = (s . e) / (||s|| ||e||) + var cosAng = this.rollStart_.dot(rollEnd) * invStartMag * invEndMag; + // sin(a) = ||(s X e)|| / (||s|| ||e||) + var sinAng = rollVector.magnitude() * invStartMag * invEndMag; + // Build a quaternion that represents the rotation about |rollVector|. + // Use atan2 for a better angle. If you use only cos or sin, you only get + // half the possible angles, and you can end up with rotations that flip + // around near the poles. + var rollHalfAngle = Math.atan2(sinAng, cosAng) * 0.5; + rollVector.normalize(); + // The quaternion looks like this: [[v], cos(angle/2)], where [v] is the + // imaginary part of the quaternion and is computed as [x, y, z] * + // sin(angle/2). + rollVector.scale(Math.sin(rollHalfAngle)); + var ballQuaternion = [rollVector.x, + rollVector.y, + rollVector.z, + Math.cos(rollHalfAngle)]; + return ballQuaternion; +}; + +/** + * Handle the drag START event: grab the current camera orientation from the + * sending view and set up the virtual trackball. + * @param {!tumbler.Application} view The view controller that called this + * method. + * @param {!tumbler.DragEvent} dragStartEvent The DRAG_START event that + * triggered this handler. + */ +tumbler.Trackball.prototype.handleStartDrag = + function(controller, dragStartEvent) { + // Cache the camera orientation. The orientations from the trackball as it + // rolls are concatenated to this orientation and pushed back into the + // plugin on the other side of the JavaScript bridge. + controller.setCameraOrientation(this.cameraOrientation_); + // Invert the y-coordinate for the trackball computations. + var frameSize = { width: controller.offsetWidth, + height: controller.offsetHeight }; + var flippedY = { x: dragStartEvent.clientX, + y: frameSize.height - dragStartEvent.clientY }; + this.startAtPointInFrame(flippedY, frameSize); +}; + +/** + * Handle the drag DRAG event: concatenate the current orientation to the + * cached orientation. Send this final value through to the GSPlugin via the + * setValueForKey() method. + * @param {!tumbler.Application} view The view controller that called this + * method. + * @param {!tumbler.DragEvent} dragEvent The DRAG event that triggered this + * handler. + */ +tumbler.Trackball.prototype.handleDrag = + function(controller, dragEvent) { + // Flip the y-coordinate so that the 2D origin is in the lower-left corner. + var frameSize = { width: controller.offsetWidth, + height: controller.offsetHeight }; + var flippedY = { x: dragEvent.clientX, + y: frameSize.height - dragEvent.clientY }; + controller.setCameraOrientation( + tumbler.multQuaternions(this.rollToPoint(flippedY), + this.cameraOrientation_)); +}; + +/** + * Handle the drag END event: get the final orientation and concatenate it to + * the cached orientation. + * @param {!tumbler.Application} view The view controller that called this + * method. + * @param {!tumbler.DragEvent} dragEndEvent The DRAG_END event that triggered + * this handler. + */ +tumbler.Trackball.prototype.handleEndDrag = + function(controller, dragEndEvent) { + // Flip the y-coordinate so that the 2D origin is in the lower-left corner. + var frameSize = { width: controller.offsetWidth, + height: controller.offsetHeight }; + var flippedY = { x: dragEndEvent.clientX, + y: frameSize.height - dragEndEvent.clientY }; + this.cameraOrientation_ = tumbler.multQuaternions(this.rollToPoint(flippedY), + this.cameraOrientation_); + controller.setCameraOrientation(this.cameraOrientation_); +}; + +/** + * A utility function to multiply two quaterions. Returns the product q0 * q1. + * This is effectively the same thing as concatenating the two rotations + * represented in each quaternion together. Note that quaternion multiplication + * is NOT commutative: q0 * q1 != q1 * q0. + * @param {!Array.} q0 A 4-element array representing the first + * quaternion. + * @param {!Array.} q1 A 4-element array representing the second + * quaternion. + * @return {Array.} A 4-element array representing the product q0 * q1. + */ +tumbler.multQuaternions = function(q0, q1) { + // Return q0 * q1 (note the order). + var qMult = [ + q0[3] * q1[0] + q0[0] * q1[3] + q0[1] * q1[2] - q0[2] * q1[1], + q0[3] * q1[1] - q0[0] * q1[2] + q0[1] * q1[3] + q0[2] * q1[0], + q0[3] * q1[2] + q0[0] * q1[1] - q0[1] * q1[0] + q0[2] * q1[3], + q0[3] * q1[3] - q0[0] * q1[0] - q0[1] * q1[1] - q0[2] * q1[2] + ]; + return qMult; +}; + +/** + * Real numbers that are less than this distance apart are considered + * equivalent. + * TODO(dspringer): It seems as though there should be a const like this + * in Closure somewhere (goog.math?). + * @type {number} + */ +tumbler.Trackball.DOUBLE_EPSILON = 1.0e-16; diff --git a/Demos/NativeClient/bin_html/tumbler.js b/Demos/NativeClient/bin_html/tumbler.js new file mode 100644 index 0000000..e8e42eb --- /dev/null +++ b/Demos/NativeClient/bin_html/tumbler.js @@ -0,0 +1,133 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview The tumbler Application object. This object instantiates a + * Trackball object and connects it to the element named |tumbler_content|. + * It also conditionally embeds a debuggable module or a release module into + * the |tumbler_content| element. + */ + +// Requires tumbler +// Requires tumbler.Dragger +// Requires tumbler.Trackball + +/** + * Constructor for the Application class. Use the run() method to populate + * the object with controllers and wire up the events. + * @constructor + */ +tumbler.Application = function() { + /** + * The native module for the application. This refers to the module loaded + * via the tag. + * @type {Element} + * @private + */ + this.module_ = null; + + /** + * The trackball object. + * @type {tumbler.Trackball} + * @private + */ + this.trackball_ = null; + + /** + * The mouse-drag event object. + * @type {tumbler.Dragger} + * @private + */ + this.dragger_ = null; + + /** + * The function objects that get attached as event handlers. These are + * cached so that they can be removed when they are no longer needed. + * @type {function} + * @private + */ + this.boundModuleDidLoad_ = null; +} + +/** + * The ids used for elements in the DOM. The Tumlber Application expects these + * elements to exist. + * @enum {string} + * @private + */ +tumbler.Application.DomIds_ = { + MODULE: 'tumbler', // The element representing the NaCl module + VIEW: 'tumbler_view' // The
    containing the NaCl element. +} + +/** + * Called by the module loading function once the module has been loaded. + * @param {?Element} nativeModule The instance of the native module. + */ +tumbler.Application.prototype.moduleDidLoad = function() { + this.module_ = document.getElementById(tumbler.Application.DomIds_.MODULE); + // Unbind the load function. + this.boundModuleDidLoad_ = null; + + /** + * Set the camera orientation property on the NaCl module. + * @param {Array.} orientation A 4-element array representing the + * camera orientation as a quaternion. + */ + this.module_.setCameraOrientation = function(orientation) { + var methodString = 'setCameraOrientation ' + + 'orientation:' + + JSON.stringify(orientation); + this.postMessage(methodString); + } + + this.trackball_ = new tumbler.Trackball(); + this.dragger_ = new tumbler.Dragger(this.module_); + this.dragger_.addDragListener(this.trackball_); +} + +/** + * Asserts that cond is true; issues an alert and throws an Error otherwise. + * @param {bool} cond The condition. + * @param {String} message The error message issued if cond is false. + */ +tumbler.Application.prototype.assert = function(cond, message) { + if (!cond) { + message = "Assertion failed: " + message; + alert(message); + throw new Error(message); + } +} + +/** + * The run() method starts and 'runs' the application. The trackball object + * is allocated and all the events get wired up. + * @param {?String} opt_contentDivName The id of a DOM element in which to + * embed the Native Client module. If unspecified, defaults to + * VIEW. The DOM element must exist. + */ +tumbler.Application.prototype.run = function(opt_contentDivName) { + contentDivName = opt_contentDivName || tumbler.Application.DomIds_.VIEW; + var contentDiv = document.getElementById(contentDivName); + this.assert(contentDiv, "Missing DOM element '" + contentDivName + "'"); + + // Note that the element is wrapped inside a
    , which has a 'load' + // event listener attached. This method is used instead of attaching the + // 'load' event listener directly to the element to ensure that the + // listener is active before the NaCl module 'load' event fires. + this.boundModuleDidLoad_ = this.moduleDidLoad.bind(this); + contentDiv.addEventListener('load', this.boundModuleDidLoad_, true); + + // Load the published .nexe. This includes the 'nacl' attribute which + // shows how to load multi-architecture modules. Each entry in the "nexes" + // object in the .nmf manifest file is a key-value pair: the key is the + // runtime ('x86-32', 'x86-64', etc.); the value is a URL for the desired + // NaCl module. To load the debug versions of your .nexes, set the 'nacl' + // attribute to the _dbg.nmf version of the manifest file. + contentDiv.innerHTML = '' +} diff --git a/Demos/NativeClient/bin_html/tumbler.nmf b/Demos/NativeClient/bin_html/tumbler.nmf new file mode 100644 index 0000000..1c5b495 --- /dev/null +++ b/Demos/NativeClient/bin_html/tumbler.nmf @@ -0,0 +1,6 @@ +{ + "program": { + "x86-64": {"url": "NativeClientTumbler_x64.exe"}, + "x86-32": {"url": "NativeClientTumbler.exe"} + } +} diff --git a/Demos/NativeClient/bin_html/vector3.js b/Demos/NativeClient/bin_html/vector3.js new file mode 100644 index 0000000..a79f781 --- /dev/null +++ b/Demos/NativeClient/bin_html/vector3.js @@ -0,0 +1,91 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview A 3D vector class. Proviudes some utility functions on + * 3-dimentional vectors. + */ + +// Requires tumbler + +/** + * Constructor for the Vector3 object. This class contains a 3-tuple that + * represents a vector in 3D space. + * @param {?number} opt_x The x-coordinate for this vector. If null or + * undefined, the x-coordinate value is set to 0. + * @param {?number} opt_y The y-coordinate for this vector. If null or + * undefined, the y-coordinate value is set to 0. + * @param {?number} opt_z The z-coordinate for this vector. If null or + * undefined, the z-coordinate value is set to 0. + * @constructor + */ +tumbler.Vector3 = function(opt_x, opt_y, opt_z) { + /** + * The vector's 3-tuple. + * @type {number} + */ + this.x = opt_x || 0; + this.y = opt_y || 0; + this.z = opt_z || 0; +} + +/** + * Method to return the magnitude of a Vector3. + * @return {number} the magnitude of the vector. + */ +tumbler.Vector3.prototype.magnitude = function() { + return Math.sqrt(this.dot(this)); +} + +/** + * Normalize the vector in-place. + * @return {number} the magnitude of the vector. + */ +tumbler.Vector3.prototype.normalize = function() { + var mag = this.magnitude(); + if (mag < tumbler.Vector3.DOUBLE_EPSILON) + return 0.0; // |this| is equivalent to the 0-vector, don't normalize. + this.scale(1.0 / mag); + return mag; +} + +/** + * Scale the vector in-place by |s|. + * @param {!number} s The scale factor. + */ +tumbler.Vector3.prototype.scale = function(s) { + this.x *= s; + this.y *= s; + this.z *= s; +} + +/** + * Compute the dot product: |this| . v. + * @param {!tumbler.Vector3} v The vector to dot. + * @return {number} the result of |this| . v. + */ +tumbler.Vector3.prototype.dot = function(v) { + return this.x * v.x + this.y * v.y + this.z * v.z; +} + +/** + * Compute the cross product: |this| X v. + * @param {!tumbler.Vector3} v The vector to cross with. + * @return {tumbler.Vector3} the result of |this| X v. + */ +tumbler.Vector3.prototype.cross = function(v) { + var vCross = new tumbler.Vector3(this.y * v.z - this.z * v.y, + this.z * v.x - this.x * v.z, + this.x * v.y - this.y * v.x); + return vCross; +} + +/** + * Real numbers that are less than this distance apart are considered + * equivalent. + * TODO(dspringer): It seems as though there should be a const like this + * in generally available somewhere. + * @type {number} + */ +tumbler.Vector3.DOUBLE_EPSILON = 1.0e-16; diff --git a/Demos/NativeClient/callback.h b/Demos/NativeClient/callback.h new file mode 100644 index 0000000..4d67262 --- /dev/null +++ b/Demos/NativeClient/callback.h @@ -0,0 +1,92 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXAMPLES_TUMBLER_CALLBACK_H_ +#define EXAMPLES_TUMBLER_CALLBACK_H_ + +#include +#include +#include + +namespace tumbler { + +class ScriptingBridge; + +// Templates used to support method call-backs when a method or property is +// accessed from the browser code. + +// Class suite used to publish a method name to Javascript. Typical use is +// like this: +// photo::MethodCallback* calculate_callback_; +// calculate_callback_ = +// new scripting::MethodCallback(this, +// &Calculator::Calculate); +// bridge->AddMethodNamed("calculate", calculate_callback_); +// ... +// delete calculate_callback_; +// +// The caller must delete the callback. + +// Methods get parameters as a dictionary that maps parameter names to values. +typedef std::map MethodParameter; + +// Pure virtual class used in STL containers. +class MethodCallbackExecutor { + public: + virtual ~MethodCallbackExecutor() {} + virtual void Execute( + const ScriptingBridge& bridge, + const MethodParameter& parameters) = 0; +}; + +template +class MethodCallback : public MethodCallbackExecutor { + public: + typedef void (T::*Method)( + const ScriptingBridge& bridge, + const MethodParameter& parameters); + + MethodCallback(T* instance, Method method) + : instance_(instance), method_(method) {} + virtual ~MethodCallback() {} + virtual void Execute( + const ScriptingBridge& bridge, + const MethodParameter& parameters) { + // Use "this->" to force C++ to look inside our templatized base class; see + // Effective C++, 3rd Ed, item 43, p210 for details. + ((this->instance_)->*(this->method_))(bridge, parameters); + } + + private: + T* instance_; + Method method_; +}; + +template +class ConstMethodCallback : public MethodCallbackExecutor { + public: + typedef void (T::*ConstMethod)( + const ScriptingBridge& bridge, + const MethodParameter& parameters) const; + + ConstMethodCallback(const T* instance, ConstMethod method) + : instance_(instance), const_method_(method) {} + virtual ~ConstMethodCallback() {} + virtual void Execute( + const ScriptingBridge& bridge, + const MethodParameter& parameters) { + // Use "this->" to force C++ to look inside our templatized base class; see + // Effective C++, 3rd Ed, item 43, p210 for details. + ((this->instance_)->*(this->const_method_))(bridge, parameters); + } + + private: + const T* instance_; + ConstMethod const_method_; +}; + +} // namespace tumbler + +#endif // EXAMPLES_TUMBLER_CALLBACK_H_ + diff --git a/Demos/NativeClient/cube.cc b/Demos/NativeClient/cube.cc new file mode 100644 index 0000000..777e6eb --- /dev/null +++ b/Demos/NativeClient/cube.cc @@ -0,0 +1,267 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cube.h" + +#include + +#include "shader_util.h" +#include "transforms.h" + +namespace tumbler { + +static const size_t kVertexCount = 24; +static const int kIndexCount = 36; + +Cube::Cube(SharedOpenGLContext opengl_context) + : opengl_context_(opengl_context), + width_(1), + height_(1) { + eye_[0] = eye_[1] = 0.0f; + eye_[2] = 2.0f; + orientation_[0] = 0.0f; + orientation_[1] = 0.0f; + orientation_[2] = 0.0f; + orientation_[3] = 1.0f; +} + +Cube::~Cube() { + glDeleteBuffers(3, cube_vbos_); + glDeleteProgram(shader_program_object_); +} + +void Cube::PrepareOpenGL() { + CreateShaders(); + CreateCube(); + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glEnable(GL_DEPTH_TEST); +} + +void Cube::Resize(int width, int height) { + width_ = std::max(width, 1); + height_ = std::max(height, 1); + // Set the viewport + glViewport(0, 0, width_, height_); + // Compute the perspective projection matrix with a 60 degree FOV. + GLfloat aspect = static_cast(width_) / static_cast(height_); + transform_4x4::LoadIdentity(perspective_proj_); + transform_4x4::Perspective(perspective_proj_, 60.0f, aspect, 1.0f, 20.0f); +} + +void Cube::Draw() { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Compute a new model-view matrix, then use that to make the composite + // model-view-projection matrix: MVP = MV . P. + GLfloat model_view[16]; + ComputeModelViewTransform(model_view); + transform_4x4::Multiply(mvp_matrix_, model_view, perspective_proj_); + + glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[0]); + glUseProgram(shader_program_object_); + glEnableVertexAttribArray(position_location_); + glVertexAttribPointer(position_location_, + 3, + GL_FLOAT, + GL_FALSE, + 3 * sizeof(GLfloat), + NULL); + glEnableVertexAttribArray(color_location_); + glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[1]); + glVertexAttribPointer(color_location_, + 3, + GL_FLOAT, + GL_FALSE, + 3 * sizeof(GLfloat), + NULL); + glUniformMatrix4fv(mvp_location_, 1, GL_FALSE, mvp_matrix_); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cube_vbos_[2]); + glDrawElements(GL_TRIANGLES, kIndexCount, GL_UNSIGNED_SHORT, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + +bool Cube::CreateShaders() { + const char vertex_shader_src[] = + "uniform mat4 u_mvpMatrix; \n" + "attribute vec4 a_position; \n" + "attribute vec3 a_color; \n" + "varying lowp vec4 v_color; \n" + "void main() \n" + "{ \n" + " v_color.xyz = a_color; \n" + " v_color.w = 1.0; \n" + " gl_Position = u_mvpMatrix * a_position; \n" + "} \n"; + + const char fragment_shader_src[] = + "varying lowp vec4 v_color; \n" + "void main() \n" + "{ \n" + " gl_FragColor = v_color; \n" + "} \n"; + + // Load the shaders and get a linked program object + shader_program_object_ = + shader_util::CreateProgramFromVertexAndFragmentShaders( + vertex_shader_src, fragment_shader_src); + if (shader_program_object_ == 0) + return false; + position_location_ = glGetAttribLocation(shader_program_object_, + "a_position"); + color_location_ = glGetAttribLocation(shader_program_object_, "a_color"); + mvp_location_ = glGetUniformLocation(shader_program_object_, "u_mvpMatrix"); + return true; +} + +void Cube::CreateCube() { + static const GLfloat cube_vertices[] = { + // Vertex coordinates interleaved with color values + // Bottom + -0.5f, -0.5f, -0.5f, + -0.5f, -0.5f, 0.5f, + 0.5f, -0.5f, 0.5f, + 0.5f, -0.5f, -0.5f, + // Top + -0.5f, 0.5f, -0.5f, + -0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, -0.5f, + // Back + -0.5f, -0.5f, -0.5f, + -0.5f, 0.5f, -0.5f, + 0.5f, 0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, + // Front + -0.5f, -0.5f, 0.5f, + -0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, + 0.5f, -0.5f, 0.5f, + // Left + -0.5f, -0.5f, -0.5f, + -0.5f, -0.5f, 0.5f, + -0.5f, 0.5f, 0.5f, + -0.5f, 0.5f, -0.5f, + // Right + 0.5f, -0.5f, -0.5f, + 0.5f, -0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, -0.5f + }; + + static const GLfloat cube_colors[] = { + // Vertex coordinates interleaved with color values + // Bottom + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + // Top + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + // Back + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + // Front + 1.0, 0.0, 1.0, + 1.0, 0.0, 1.0, + 1.0, 0.0, 1.0, + 1.0, 0.0, 1.0, + // Left + 1.0, 1.0, 0.0, + 1.0, 1.0, 0.0, + 1.0, 1.0, 0.0, + 1.0, 1.0, 0.0, + // Right + 0.0, 1.0, 1.0, + 0.0, 1.0, 1.0, + 0.0, 1.0, 1.0, + 0.0, 1.0, 1.0 + }; + + static const GLushort cube_indices[] = { + // Bottom + 0, 2, 1, + 0, 3, 2, + // Top + 4, 5, 6, + 4, 6, 7, + // Back + 8, 9, 10, + 8, 10, 11, + // Front + 12, 15, 14, + 12, 14, 13, + // Left + 16, 17, 18, + 16, 18, 19, + // Right + 20, 23, 22, + 20, 22, 21 + }; + + // Generate the VBOs and upload them to the graphics context. + glGenBuffers(3, cube_vbos_); + glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[0]); + glBufferData(GL_ARRAY_BUFFER, + kVertexCount * sizeof(GLfloat) * 3, + cube_vertices, + GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[1]); + glBufferData(GL_ARRAY_BUFFER, + kVertexCount * sizeof(GLfloat) * 3, + cube_colors, + GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cube_vbos_[2]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, + kIndexCount * sizeof(GL_UNSIGNED_SHORT), + cube_indices, + GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + +void Cube::ComputeModelViewTransform(GLfloat* model_view) { + // This method takes into account the possiblity that |orientation_| + // might not be normalized. + double sqrx = orientation_[0] * orientation_[0]; + double sqry = orientation_[1] * orientation_[1]; + double sqrz = orientation_[2] * orientation_[2]; + double sqrw = orientation_[3] * orientation_[3]; + double sqrLength = 1.0 / (sqrx + sqry + sqrz + sqrw); + + transform_4x4::LoadIdentity(model_view); + model_view[0] = (sqrx - sqry - sqrz + sqrw) * sqrLength; + model_view[5] = (-sqrx + sqry - sqrz + sqrw) * sqrLength; + model_view[10] = (-sqrx - sqry + sqrz + sqrw) * sqrLength; + + double temp1 = orientation_[0] * orientation_[1]; + double temp2 = orientation_[2] * orientation_[3]; + model_view[1] = 2.0 * (temp1 + temp2) * sqrLength; + model_view[4] = 2.0 * (temp1 - temp2) * sqrLength; + + temp1 = orientation_[0] * orientation_[2]; + temp2 = orientation_[1] * orientation_[3]; + model_view[2] = 2.0 * (temp1 - temp2) * sqrLength; + model_view[8] = 2.0 * (temp1 + temp2) * sqrLength; + temp1 = orientation_[1] * orientation_[2]; + temp2 = orientation_[0] * orientation_[3]; + model_view[6] = 2.0 * (temp1 + temp2) * sqrLength; + model_view[9] = 2.0 * (temp1 - temp2) * sqrLength; + model_view[3] = 0.0; + model_view[7] = 0.0; + model_view[11] = 0.0; + + // Concatenate the translation to the eye point. + model_view[12] = -eye_[0]; + model_view[13] = -eye_[1]; + model_view[14] = -eye_[2]; + model_view[15] = 1.0; +} + +} // namespace tumbler diff --git a/Demos/NativeClient/cube.h b/Demos/NativeClient/cube.h new file mode 100644 index 0000000..1c3b62b --- /dev/null +++ b/Demos/NativeClient/cube.h @@ -0,0 +1,97 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXAMPLES_TUMBLER_CUBE_H_ +#define EXAMPLES_TUMBLER_CUBE_H_ + +#include +#include +#include "opengl_context.h" +#include "opengl_context_ptrs.h" + +namespace tumbler { + +// The Cube class provides a place to implement 3D rendering. It has a +// frame that it occupies in a browser window. +class Cube { + public: + explicit Cube(SharedOpenGLContext opengl_context); + ~Cube(); + + // Called once when a new RenderContext is first bound to the view. The + // bound context is guaranteed to be current and valid before calling this + // method. + void PrepareOpenGL(); + + // Called whenever the size of the browser view changes. This method is + // called at least once when the view is first made visible. Clamps the + // sizes to 1. + void Resize(int width, int height); + + // Called every time the view need to be drawn. The bound context is + // guaranteed to be current and valid before this method is called. The + // visible portion of the context is flushed to the browser after this + // method returns. + void Draw(); + + // Accessor for width and height. To change these, call Resize. + const int width() const { + return width_; + } + + const int height() const { + return height_; + } + + // Accessor/mutator for the camera orientation. + void GetOrientation(std::vector* orientation) const { + if (!orientation) + return; + (*orientation)[0] = static_cast(orientation_[0]); + (*orientation)[1] = static_cast(orientation_[1]); + (*orientation)[2] = static_cast(orientation_[2]); + (*orientation)[3] = static_cast(orientation_[3]); + } + void SetOrientation(const std::vector& orientation) { + orientation_[0] = static_cast(orientation[0]); + orientation_[1] = static_cast(orientation[1]); + orientation_[2] = static_cast(orientation[2]); + orientation_[3] = static_cast(orientation[3]); + } + + private: + // Create the shaders used to draw the cube, and link them into a program. + // Initializes |shader_progam_object_|, |position_loction_| and + // |mvp_location_|. + bool CreateShaders(); + + // Generates a cube as a series of GL_TRIANGLE_STRIPs, and initializes + // |index_count_| to the number of indices in the index list used as a VBO. + // Creates the |vbo_ids_| required for the vertex and index data and uploads + // the the VBO data. + void CreateCube(); + + // Build up the model-view transform from the eye and orienation properties. + // Assumes that |model_view| is a 4x4 matrix. + void ComputeModelViewTransform(GLfloat* model_view); + + SharedOpenGLContext opengl_context_; + int width_; + int height_; + GLuint shader_program_object_; // The compiled shaders. + GLint position_location_; // The position attribute location. + GLint color_location_; // The color attribute location. + GLint mvp_location_; // The Model-View-Projection composite matrix. + GLuint cube_vbos_[3]; + GLfloat eye_[3]; // The eye point of the virtual camera. + // The orientation of the virtual camera stored as a quaternion. The + // quaternion is laid out as {{x, y, z}, w}. + GLfloat orientation_[4]; + GLfloat perspective_proj_[16]; + GLfloat mvp_matrix_[16]; +}; + +} // namespace tumbler + +#endif // EXAMPLES_TUMBLER_CUBE_H_ diff --git a/Demos/NativeClient/opengl_context.cc b/Demos/NativeClient/opengl_context.cc new file mode 100644 index 0000000..1c0afa7 --- /dev/null +++ b/Demos/NativeClient/opengl_context.cc @@ -0,0 +1,72 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "opengl_context.h" + +#include +#include "ppapi/gles2/gl2ext_ppapi.h" + +namespace { +// This is called by the brower when the 3D context has been flushed to the +// browser window. +void FlushCallback(void* data, int32_t result) { + static_cast(data)->set_flush_pending(false); +} +} // namespace + +namespace tumbler { + +OpenGLContext::OpenGLContext(pp::Instance* instance) + : pp::Graphics3DClient_Dev(instance), + flush_pending_(false) { + pp::Module* module = pp::Module::Get(); + assert(module); + gles2_interface_ = static_cast( + module->GetBrowserInterface(PPB_OPENGLES2_DEV_INTERFACE)); + assert(gles2_interface_); +} + +OpenGLContext::~OpenGLContext() { + glSetCurrentContextPPAPI(0); +} + +bool OpenGLContext::MakeContextCurrent(pp::Instance* instance) { + if (instance == NULL) { + glSetCurrentContextPPAPI(0); + return false; + } + // Lazily create the Pepper context. + if (context_.is_null()) { + context_ = pp::Context3D_Dev(*instance, 0, pp::Context3D_Dev(), NULL); + if (context_.is_null()) { + glSetCurrentContextPPAPI(0); + return false; + } + surface_ = pp::Surface3D_Dev(*instance, 0, NULL); + context_.BindSurfaces(surface_, surface_); + instance->BindGraphics(surface_); + } + glSetCurrentContextPPAPI(context_.pp_resource()); + return true; +} + +void OpenGLContext::InvalidateContext(pp::Instance* instance) { + if (instance == NULL) + return; + // Unbind the existing surface and re-bind to null surfaces. + instance->BindGraphics(pp::Surface3D_Dev()); + context_.BindSurfaces(pp::Surface3D_Dev(), pp::Surface3D_Dev()); + glSetCurrentContextPPAPI(0); +} + +void OpenGLContext::FlushContext() { + if (flush_pending()) { + // A flush is pending so do nothing; just drop this flush on the floor. + return; + } + set_flush_pending(true); + surface_.SwapBuffers(pp::CompletionCallback(&FlushCallback, this)); +} +} // namespace tumbler + diff --git a/Demos/NativeClient/opengl_context.h b/Demos/NativeClient/opengl_context.h new file mode 100644 index 0000000..851b9db --- /dev/null +++ b/Demos/NativeClient/opengl_context.h @@ -0,0 +1,90 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXAMPLES_TUMBLER_OPENGL_CONTEXT_H_ +#define EXAMPLES_TUMBLER_OPENGL_CONTEXT_H_ + +/// +/// @file +/// OpenGLContext manages the OpenGL context in the browser that is associated +/// with a @a pp::Instance instance. +/// + +#include + +#include +#include + +#include "opengl_context_ptrs.h" +#include "ppapi/c/dev/ppb_opengles_dev.h" +#include "ppapi/cpp/dev/context_3d_dev.h" +#include "ppapi/cpp/dev/graphics_3d_client_dev.h" +#include "ppapi/cpp/dev/graphics_3d_dev.h" +#include "ppapi/cpp/dev/surface_3d_dev.h" +#include "ppapi/cpp/instance.h" + +namespace tumbler { + +/// OpenGLContext manages an OpenGL rendering context in the browser. +/// +class OpenGLContext : public pp::Graphics3DClient_Dev { + public: + explicit OpenGLContext(pp::Instance* instance); + + /// Release all the in-browser resources used by this context, and make this + /// context invalid. + virtual ~OpenGLContext(); + + /// The Graphics3DClient interfcace. + virtual void Graphics3DContextLost() { + assert(!"Unexpectedly lost graphics context"); + } + + /// Make @a this the current 3D context in @a instance. + /// @param instance The instance of the NaCl module that will receive the + /// the current 3D context. + /// @return success. + bool MakeContextCurrent(pp::Instance* instance); + + /// Flush the contents of this context to the browser's 3D device. + void FlushContext(); + + /// Make the underlying 3D device invalid, so that any subsequent rendering + /// commands will have no effect. The next call to MakeContextCurrent() will + /// cause the underlying 3D device to get rebound and start receiving + /// receiving rendering commands again. Use InvalidateContext(), for + /// example, when resizing the context's viewing area. + void InvalidateContext(pp::Instance* instance); + + /// The OpenGL ES 2.0 interface. + const struct PPB_OpenGLES2_Dev* gles2() const { + return gles2_interface_; + } + + /// The PP_Resource needed to make GLES2 calls through the Pepper interface. + const PP_Resource gl_context() const { + return context_.pp_resource(); + } + + /// Indicate whether a flush is pending. This can only be called from the + /// main thread; it is not thread safe. + bool flush_pending() const { + return flush_pending_; + } + void set_flush_pending(bool flag) { + flush_pending_ = flag; + } + + private: + pp::Context3D_Dev context_; + pp::Surface3D_Dev surface_; + bool flush_pending_; + + const struct PPB_OpenGLES2_Dev* gles2_interface_; +}; + +} // namespace tumbler + +#endif // EXAMPLES_TUMBLER_OPENGL_CONTEXT_H_ + diff --git a/Demos/NativeClient/opengl_context_ptrs.h b/Demos/NativeClient/opengl_context_ptrs.h new file mode 100644 index 0000000..3478521 --- /dev/null +++ b/Demos/NativeClient/opengl_context_ptrs.h @@ -0,0 +1,22 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXAMPLES_TUMBLER_OPENGL_CONTEXT_PTRS_H_ +#define EXAMPLES_TUMBLER_OPENGL_CONTEXT_PTRS_H_ + +// A convenience wrapper for a shared OpenGLContext pointer type. As other +// smart pointer types are needed, add them here. + +#include + +namespace tumbler { + +class OpenGLContext; + +typedef std::tr1::shared_ptr SharedOpenGLContext; + +} // namespace tumbler + +#endif // EXAMPLES_TUMBLER_OPENGL_CONTEXT_PTRS_H_ + diff --git a/Demos/NativeClient/premake4.lua b/Demos/NativeClient/premake4.lua new file mode 100644 index 0000000..2090597 --- /dev/null +++ b/Demos/NativeClient/premake4.lua @@ -0,0 +1,27 @@ + project "NativeClientTumbler" + + kind "ConsoleApp" + + targetdir "bin_html" + + includedirs { "." } + + --libdirs {} + + links { + "ppapi_gles2", + "ppapi", + "ppapi_cpp", + "ppruntime" + } + + + files { + "cube.cc", + "opengl_context.cc", + "scripting_bridge.cc", + "shader_util.cc", + "transforms.cc", + "tumbler.cc", + "tumbler_module.cc" + } \ No newline at end of file diff --git a/Demos/NativeClient/scripting_bridge.cc b/Demos/NativeClient/scripting_bridge.cc new file mode 100644 index 0000000..abc67ca --- /dev/null +++ b/Demos/NativeClient/scripting_bridge.cc @@ -0,0 +1,95 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "scripting_bridge.h" + +namespace { +const char* const kWhiteSpaceCharacters = " \t"; + +// Helper function to pull out the next token in |token_string|. A token is +// delimited by whitespace. Scanning begins at |*pos|, if pos goes beyond the +// end of |token_string|, it is set to std::string::npos and an empty string +// is returned. On return, |*pos| will point to the beginning of the next +// token. |pos| must not be NULL. +const std::string ScanToken(const std::string& token_string, size_t* pos) { + std::string token; + if (*pos == std::string::npos) { + return token; + } + size_t token_start_pos = token_string.find_first_not_of(kWhiteSpaceCharacters, + *pos); + size_t token_end_pos = token_string.find_first_of(kWhiteSpaceCharacters, + token_start_pos); + if (token_start_pos != std::string::npos) { + token = token_string.substr(token_start_pos, token_end_pos); + } + *pos = token_end_pos; + return token; +} + +// Take a string of the form 'name:value' and split it into two strings, one +// containing 'name' and the other 'value'. If the ':' separator is missing, +// or is the last character in |parameter|, |parameter| is copied to +// |param_name|, |param_value| is left unchanged and false is returned. +bool ParseParameter(const std::string& parameter, + std::string* param_name, + std::string* param_value) { + bool success = false; + size_t sep_pos = parameter.find_first_of(':'); + if (sep_pos != std::string::npos) { + *param_name = parameter.substr(0, sep_pos); + if (sep_pos < parameter.length() - 1) { + *param_value = parameter.substr(sep_pos + 1); + success = true; + } else { + success = false; + } + } else { + *param_name = parameter; + success = false; + } + return success; +} +} // namespace + +namespace tumbler { + +bool ScriptingBridge::AddMethodNamed(const std::string& method_name, + SharedMethodCallbackExecutor method) { + if (method_name.size() == 0 || method == NULL) + return false; + method_dictionary_.insert( + std::pair(method_name, + method)); + return true; +} + +bool ScriptingBridge::InvokeMethod(const std::string& method) { + size_t current_pos = 0; + const std::string method_name = ScanToken(method, ¤t_pos); + MethodDictionary::iterator method_iter; + method_iter = method_dictionary_.find(method_name); + if (method_iter != method_dictionary_.end()) { + // Pull out the method parameters and build a dictionary that maps + // parameter names to values. + std::map param_dict; + while (current_pos != std::string::npos) { + const std::string parameter = ScanToken(method, ¤t_pos); + if (parameter.length()) { + std::string param_name; + std::string param_value; + if (ParseParameter(parameter, ¶m_name, ¶m_value)) { + // Note that duplicate parameter names will override each other. The + // last one in the method string will be used. + param_dict[param_name] = param_value; + } + } + } + (*method_iter->second).Execute(*this, param_dict); + return true; + } + return false; +} + +} // namespace tumbler diff --git a/Demos/NativeClient/scripting_bridge.h b/Demos/NativeClient/scripting_bridge.h new file mode 100644 index 0000000..f6a366c --- /dev/null +++ b/Demos/NativeClient/scripting_bridge.h @@ -0,0 +1,52 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXAMPLES_TUMBLER_SCRIPTING_BRIDGE_H_ +#define EXAMPLES_TUMBLER_SCRIPTING_BRIDGE_H_ + +#include +#include +#include +#include + +#include "callback.h" +#include "ppapi/cpp/var.h" + +namespace tumbler { + +class MethodCallbackExecutor; + +// This class handles the interface between the browser and the NaCl module. +// There is a single point of entry from the browser: postMessage(). The +// string passed to postMessage() has this format: +// 'function_name arg_name0:arg_0 arg_name1:arg1 ...' +// The arguments have undetermined type; they are placed in a map of argument +// names and values. Values are all strings, it is up to the target code to +// do any type coercion. +// Methods called by the scripting bridge must have a signature like this: +// void Method(const ScriptingBridge& bridge, +// const ParameterDictionary&); +class ScriptingBridge { + public: + // Shared pointer type used in the method map. + typedef std::tr1::shared_ptr + SharedMethodCallbackExecutor; + + virtual ~ScriptingBridge() {} + + // Causes |method_name| to be published as a method that can be called via + // postMessage() from the browser. Associates this method with |method|. + bool AddMethodNamed(const std::string& method_name, + SharedMethodCallbackExecutor method); + + bool InvokeMethod(const std::string& method); + + private: + typedef std::map MethodDictionary; + + MethodDictionary method_dictionary_; +}; + +} // namespace tumbler +#endif // EXAMPLES_TUMBLER_SCRIPTING_BRIDGE_H_ diff --git a/Demos/NativeClient/shader_util.cc b/Demos/NativeClient/shader_util.cc new file mode 100644 index 0000000..802955b --- /dev/null +++ b/Demos/NativeClient/shader_util.cc @@ -0,0 +1,95 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "shader_util.h" + +#include +#include + +namespace shader_util { + +GLuint CreateShaderOfType(GLenum type, const char *shader_src) { + GLuint shader; + GLint compiled; + + // Create the shader object + shader = glCreateShader(type); + + if (shader == 0) + return 0; + + // Load and compile the shader source + glShaderSource(shader, 1, &shader_src, NULL); + glCompileShader(shader); + + // Check the compile status + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (compiled == 0) { + GLint info_len = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len); + if (info_len > 1) { + char* info_log = reinterpret_cast(malloc(sizeof(char) * info_len)); + glGetShaderInfoLog(shader, info_len, NULL, info_log); + // TODO(dspringer): We could really use a logging API. + printf("Error compiling shader:\n%s\n", info_log); + free(info_log); + } + glDeleteShader(shader); + return 0; + } + + return shader; +} + +GLuint CreateProgramFromVertexAndFragmentShaders( + const char *vertex_shader_src, const char *fragment_shader_src) { + GLuint vertex_shader; + GLuint fragment_shader; + GLuint program_object; + GLint linked; + + // Load the vertex/fragment shaders + vertex_shader = CreateShaderOfType(GL_VERTEX_SHADER, vertex_shader_src); + if (vertex_shader == 0) + return 0; + fragment_shader = CreateShaderOfType(GL_FRAGMENT_SHADER, fragment_shader_src); + if (fragment_shader == 0) { + glDeleteShader(vertex_shader); + return 0; + } + + // Create the program object and attach the shaders. + program_object = glCreateProgram(); + if (program_object == 0) + return 0; + glAttachShader(program_object, vertex_shader); + glAttachShader(program_object, fragment_shader); + + // Link the program + glLinkProgram(program_object); + + // Check the link status + glGetProgramiv(program_object, GL_LINK_STATUS, &linked); + if (linked == 0) { + GLint info_len = 0; + glGetProgramiv(program_object, GL_INFO_LOG_LENGTH, &info_len); + if (info_len > 1) { + char* info_log = reinterpret_cast(malloc(info_len)); + glGetProgramInfoLog(program_object, info_len, NULL, info_log); + // TODO(dspringer): We could really use a logging API. + printf("Error linking program:\n%s\n", info_log); + free(info_log); + } + glDeleteProgram(program_object); + return 0; + } + + // Delete these here because they are attached to the program object. + glDeleteShader(vertex_shader); + glDeleteShader(fragment_shader); + + return program_object; +} + +} // namespace shader_util diff --git a/Demos/NativeClient/shader_util.h b/Demos/NativeClient/shader_util.h new file mode 100644 index 0000000..635b16b --- /dev/null +++ b/Demos/NativeClient/shader_util.h @@ -0,0 +1,29 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Some simple helper functions that load shaders and create program objects. + +#ifndef EXAMPLES_TUMBLER_SHADER_UTIL_H_ +#define EXAMPLES_TUMBLER_SHADER_UTIL_H_ + +#include + +namespace shader_util { + +// Load and compile a shader. |type| can be one of GL_VERTEX_SHADER or +// GL_FRAGMENT_SHADER. Returns a non-0 value representing the compiled +// shader on success, 0 on failure. The caller is responsible for deleting +// the returned shader using glDeleteShader(). +GLuint CreateShaderOfType(GLenum type, const char *shader_src); + +// Load and compile the vertex and fragment shaders, then link these together +// into a complete program. Returns a non-0 value representing the program on, +// success or 0 on failure. The caller is responsible for deleting the +// returned program using glDeleteProgram(). +GLuint CreateProgramFromVertexAndFragmentShaders( + const char *vertex_shader_src, const char *fragment_shader_src); + +} // namespace shader_util + +#endif // EXAMPLES_TUMBLER_SHADER_UTIL_H_ diff --git a/Demos/NativeClient/transforms.cc b/Demos/NativeClient/transforms.cc new file mode 100644 index 0000000..10ab16c --- /dev/null +++ b/Demos/NativeClient/transforms.cc @@ -0,0 +1,116 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "transforms.h" + +#include +#include +#include + +namespace transform_4x4 { + +static const GLfloat kPI = 3.1415926535897932384626433832795f; + +void Translate(GLfloat* m, GLfloat tx, GLfloat ty, GLfloat tz) { + m[12] += (m[0] * tx + m[4] * ty + m[8] * tz); + m[13] += (m[1] * tx + m[5] * ty + m[9] * tz); + m[14] += (m[2] * tx + m[6] * ty + m[10] * tz); + m[15] += (m[3] * tx + m[7] * ty + m[11] * tz); +} + +void Frustum(GLfloat* m, + GLfloat left, + GLfloat right, + GLfloat bottom, + GLfloat top, + GLfloat near_z, + GLfloat far_z) { + GLfloat delta_x = right - left; + GLfloat delta_y = top - bottom; + GLfloat delta_z = far_z - near_z; + GLfloat frustum[16]; + + if ((near_z <= 0.0f) || (far_z <= 0.0f) || + (delta_x <= 0.0f) || (delta_y <= 0.0f) || (delta_z <= 0.0f)) + return; + + frustum[0] = 2.0f * near_z / delta_x; + frustum[1] = frustum[2] = frustum[3] = 0.0f; + + frustum[5] = 2.0f * near_z / delta_y; + frustum[4] = frustum[6] = frustum[7] = 0.0f; + + frustum[8] = (right + left) / delta_x; + frustum[9] = (top + bottom) / delta_y; + frustum[10] = -(near_z + far_z) / delta_z; + frustum[11] = -1.0f; + + frustum[14] = -2.0f * near_z * far_z / delta_z; + frustum[12] = frustum[13] = frustum[15] = 0.0f; + + transform_4x4::Multiply(m, frustum, m); +} + + +void Perspective(GLfloat* m, + GLfloat fovy, + GLfloat aspect, + GLfloat near_z, + GLfloat far_z) { + GLfloat frustum_w, frustum_h; + + frustum_h = tanf((fovy * 0.5f) / 180.0f * kPI) * near_z; + frustum_w = frustum_h * aspect; + transform_4x4::Frustum(m, -frustum_w, frustum_w, -frustum_h, frustum_h, + near_z, far_z); +} + +void Multiply(GLfloat *m, GLfloat *a, GLfloat* b) { + GLfloat tmp[16]; + // tmp = a . b + GLfloat a0, a1, a2, a3; + a0 = a[0]; + a1 = a[1]; + a2 = a[2]; + a3 = a[3]; + tmp[0] = a0 * b[0] + a1 * b[4] + a2 * b[8] + a3 * b[12]; + tmp[1] = a0 * b[1] + a1 * b[5] + a2 * b[9] + a3 * b[13]; + tmp[2] = a0 * b[2] + a1 * b[6] + a2 * b[10] + a3 * b[14]; + tmp[3] = a0 * b[3] + a1 * b[7] + a2 * b[11] + a3 * b[15]; + + a0 = a[4]; + a1 = a[5]; + a2 = a[6]; + a3 = a[7]; + tmp[4] = a0 * b[0] + a1 * b[4] + a2 * b[8] + a3 * b[12]; + tmp[5] = a0 * b[1] + a1 * b[5] + a2 * b[9] + a3 * b[13]; + tmp[6] = a0 * b[2] + a1 * b[6] + a2 * b[10] + a3 * b[14]; + tmp[7] = a0 * b[3] + a1 * b[7] + a2 * b[11] + a3 * b[15]; + + a0 = a[8]; + a1 = a[9]; + a2 = a[10]; + a3 = a[11]; + tmp[8] = a0 * b[0] + a1 * b[4] + a2 * b[8] + a3 * b[12]; + tmp[9] = a0 * b[1] + a1 * b[5] + a2 * b[9] + a3 * b[13]; + tmp[10] = a0 * b[2] + a1 * b[6] + a2 * b[10] + a3 * b[14]; + tmp[11] = a0 * b[3] + a1 * b[7] + a2 * b[11] + a3 * b[15]; + + a0 = a[12]; + a1 = a[13]; + a2 = a[14]; + a3 = a[15]; + tmp[12] = a0 * b[0] + a1 * b[4] + a2 * b[8] + a3 * b[12]; + tmp[13] = a0 * b[1] + a1 * b[5] + a2 * b[9] + a3 * b[13]; + tmp[14] = a0 * b[2] + a1 * b[6] + a2 * b[10] + a3 * b[14]; + tmp[15] = a0 * b[3] + a1 * b[7] + a2 * b[11] + a3 * b[15]; + memcpy(m, tmp, sizeof(GLfloat) * 4 * 4); +} + +void LoadIdentity(GLfloat* m) { + memset(m, 0, sizeof(GLfloat) * 4 * 4); + m[0] = m[5] = m[10] = m[15] = 1.0f; +} + +} // namespace transform_4x4 diff --git a/Demos/NativeClient/transforms.h b/Demos/NativeClient/transforms.h new file mode 100644 index 0000000..5ac3d6e --- /dev/null +++ b/Demos/NativeClient/transforms.h @@ -0,0 +1,45 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXAMPLES_TUMBLER_TRANSFORMS_H_ +#define EXAMPLES_TUMBLER_TRANSFORMS_H_ + +#include + +// A very simple set of 4x4 matrix routines. In all these routines, the input +// matrix is assumed to be a 4x4 of GLfloats. + +namespace transform_4x4 { + +// Pre-multply |m| with a projection transformation 4x4 matrix from a +// truncated pyramid viewing frustum. +void Frustum(GLfloat* m, + GLfloat left, + GLfloat right, + GLfloat bottom, + GLfloat top, + GLfloat near_z, + GLfloat far_z); + +// Replace |m| with the 4x4 identity matrix. +void LoadIdentity(GLfloat* m); + +// |m| <- |a| . |b|. |m| can point at the same memory as either |a| or |b|. +void Multiply(GLfloat *m, GLfloat *a, GLfloat* b); + +// Pre-multiply |m| with a single-point perspective matrix based on the viewing +// frustum whose view angle is |fovy|. +void Perspective(GLfloat* m, + GLfloat fovy, + GLfloat aspect, + GLfloat near_z, + GLfloat far_z); + +// Pre-multiply |m| with a matrix that represents a translation by |tx|, |ty|, +// |tz|. +void Translate(GLfloat* m, GLfloat tx, GLfloat ty, GLfloat tz); +} // namespace transform_4x4 + +#endif // EXAMPLES_TUMBLER_TRANSFORMS_H_ + diff --git a/Demos/NativeClient/tumbler.cc b/Demos/NativeClient/tumbler.cc new file mode 100644 index 0000000..1beecd3 --- /dev/null +++ b/Demos/NativeClient/tumbler.cc @@ -0,0 +1,136 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "tumbler.h" + +#include +#include +#include +#include + +#include "cube.h" +#include "opengl_context.h" +#include "scripting_bridge.h" +#include "ppapi/cpp/rect.h" +#include "ppapi/cpp/size.h" +#include "ppapi/cpp/var.h" + +namespace { +const size_t kQuaternionElementCount = 4; +const char* const kArrayStartCharacter = "["; +const char* const kArrayEndCharacter = "]"; +const char* const kArrayDelimiter = ","; + +// Return the value of parameter named |param_name| from |parameters|. If +// |param_name| doesn't exist, then return an empty string. +std::string GetParameterNamed( + const std::string& param_name, + const tumbler::MethodParameter& parameters) { + tumbler::MethodParameter::const_iterator i = + parameters.find(param_name); + if (i == parameters.end()) { + return ""; + } + return i->second; +} + +// Convert the JSON string |array| into a vector of floats. |array| is +// expected to be a string bounded by '[' and ']', and a comma-delimited list +// of numbers. Any errors result in the return of an empty array. +std::vector CreateArrayFromJSON(const std::string& json_array) { + std::vector float_array; + size_t array_start_pos = json_array.find_first_of(kArrayStartCharacter); + size_t array_end_pos = json_array.find_last_of(kArrayEndCharacter); + if (array_start_pos == std::string::npos || + array_end_pos == std::string::npos) + return float_array; // Malformed JSON: missing '[' or ']'. + // Pull out the array elements. + size_t token_pos = array_start_pos + 1; + while (token_pos < array_end_pos) { + float_array.push_back(strtof(json_array.data() + token_pos, NULL)); + size_t delim_pos = json_array.find_first_of(kArrayDelimiter, token_pos); + if (delim_pos == std::string::npos) + break; + token_pos = delim_pos + 1; + } + return float_array; +} +} // namespace + +namespace tumbler { + +Tumbler::Tumbler(PP_Instance instance) + : pp::Instance(instance), + cube_(NULL) { +} + +Tumbler::~Tumbler() { + // Destroy the cube view while GL context is current. + opengl_context_->MakeContextCurrent(this); + delete cube_; +} + +bool Tumbler::Init(uint32_t /* argc */, + const char* /* argn */[], + const char* /* argv */[]) { + // Add all the methods to the scripting bridge. + ScriptingBridge::SharedMethodCallbackExecutor set_orientation_method( + new tumbler::MethodCallback( + this, &Tumbler::SetCameraOrientation)); + scripting_bridge_.AddMethodNamed("setCameraOrientation", + set_orientation_method); + return true; +} + +void Tumbler::HandleMessage(const pp::Var& message) { + if (!message.is_string()) + return; + scripting_bridge_.InvokeMethod(message.AsString()); +} + +void Tumbler::DidChangeView(const pp::Rect& position, const pp::Rect& clip) { + int cube_width = cube_ ? cube_->width() : 0; + int cube_height = cube_ ? cube_->height() : 0; + if (position.size().width() == cube_width && + position.size().height() == cube_height) + return; // Size didn't change, no need to update anything. + + if (opengl_context_ == NULL) + opengl_context_.reset(new OpenGLContext(this)); + opengl_context_->InvalidateContext(this); + if (!opengl_context_->MakeContextCurrent(this)) + return; + if (cube_ == NULL) { + cube_ = new Cube(opengl_context_); + cube_->PrepareOpenGL(); + } + cube_->Resize(position.size().width(), position.size().height()); + DrawSelf(); +} + +void Tumbler::DrawSelf() { + if (cube_ == NULL || opengl_context_ == NULL) + return; + opengl_context_->MakeContextCurrent(this); + cube_->Draw(); + opengl_context_->FlushContext(); +} + +void Tumbler::SetCameraOrientation( + const tumbler::ScriptingBridge& bridge, + const tumbler::MethodParameter& parameters) { + // |parameters| is expected to contain one object named "orientation", whose + // value is a JSON string that represents an array of four floats. + if (parameters.size() != 1 || cube_ == NULL) + return; + std::string orientation_desc = GetParameterNamed("orientation", parameters); + std::vector orientation = CreateArrayFromJSON(orientation_desc); + if (orientation.size() != kQuaternionElementCount) { + return; + } + cube_->SetOrientation(orientation); + DrawSelf(); +} +} // namespace tumbler + diff --git a/Demos/NativeClient/tumbler.h b/Demos/NativeClient/tumbler.h new file mode 100644 index 0000000..e29d353 --- /dev/null +++ b/Demos/NativeClient/tumbler.h @@ -0,0 +1,64 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXAMPLES_TUMBLER_TUMBLER_H_ +#define EXAMPLES_TUMBLER_TUMBLER_H_ + +#include +#include +#include + +#include "cube.h" +#include "opengl_context.h" +#include "opengl_context_ptrs.h" +#include "scripting_bridge.h" +#include "ppapi/cpp/instance.h" + +namespace tumbler { + +class Tumbler : public pp::Instance { + public: + explicit Tumbler(PP_Instance instance); + + // The dtor makes the 3D context current before deleting the cube view, then + // destroys the 3D context both in the module and in the browser. + virtual ~Tumbler(); + + // Called by the browser when the NaCl module is loaded and all ready to go. + virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]); + + // Called whenever the in-browser window changes size. + virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip); + + // Called by the browser to handle the postMessage() call in Javascript. + virtual void HandleMessage(const pp::Var& message); + + // Bind and publish the module's methods to JavaScript. + void InitializeMethods(ScriptingBridge* bridge); + + // Set the camera orientation to the quaternion in |args[0]|. |args| must + // have length at least 1; the first element is expeted to be an Array + // object containing 4 floating point number elements (the quaternion). + // This method is bound to the JavaScript "setCameraOrientation" method and + // is called like this: + // module.setCameraOrientation([0.0, 1.0, 0.0, 0.0]); + void SetCameraOrientation( + const tumbler::ScriptingBridge& bridge, + const tumbler::MethodParameter& parameters); + + // Called to draw the contents of the module's browser area. + void DrawSelf(); + + private: + // Browser connectivity and scripting support. + ScriptingBridge scripting_bridge_; + + SharedOpenGLContext opengl_context_; + // Wouldn't it be awesome if we had boost::scoped_ptr<>? + Cube* cube_; +}; + +} // namespace tumbler + +#endif // EXAMPLES_TUMBLER_TUMBLER_H_ diff --git a/Demos/NativeClient/tumbler_module.cc b/Demos/NativeClient/tumbler_module.cc new file mode 100644 index 0000000..e58d73e --- /dev/null +++ b/Demos/NativeClient/tumbler_module.cc @@ -0,0 +1,45 @@ +// Copyright (c) 2011 The Native Client Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "tumbler.h" +#include "ppapi/cpp/instance.h" +#include "ppapi/cpp/module.h" +#include "ppapi/gles2/gl2ext_ppapi.h" + +/// The Module class. The browser calls the CreateInstance() method to create +/// an instance of your NaCl module on the web page. The browser creates a new +/// instance for each tag with type="application/x-nacl". +class TumberModule : public pp::Module { + public: + TumberModule() : pp::Module() {} + virtual ~TumberModule() { + glTerminatePPAPI(); + } + + /// Called by the browser when the module is first loaded and ready to run. + /// This is called once per module, not once per instance of the module on + /// the page. + virtual bool Init() { + return glInitializePPAPI(get_browser_interface()) == GL_TRUE; + } + + /// Create and return a Tumbler instance object. + /// @param[in] instance The browser-side instance. + /// @return the plugin-side instance. + virtual pp::Instance* CreateInstance(PP_Instance instance) { + return new tumbler::Tumbler(instance); + } +}; + +namespace pp { +/// Factory function called by the browser when the module is first loaded. +/// The browser keeps a singleton of this module. It calls the +/// CreateInstance() method on the object you return to make instances. There +/// is one instance per tag on the page. This is the main binding +/// point for your NaCl module with the browser. +Module* CreateModule() { + return new TumberModule(); +} +} // namespace pp + diff --git a/Demos/OpenCLClothDemo/AMD/CMakeLists.txt b/Demos/OpenCLClothDemo/AMD/CMakeLists.txt new file mode 100644 index 0000000..dcba3c8 --- /dev/null +++ b/Demos/OpenCLClothDemo/AMD/CMakeLists.txt @@ -0,0 +1,86 @@ + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL +${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +${AMD_OPENCL_INCLUDES} +) + +ADD_DEFINITIONS(-DUSE_AMD_OPENCL) +ADD_DEFINITIONS(-DCL_PLATFORM_AMD) + +IF(WIN32) +ADD_DEFINITIONS(-DGLEW_STATIC) +ENDIF(WIN32) + +IF (CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY + ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew64s.lib ) +ELSE(CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew32s.lib ) +ENDIF(CMAKE_CL_64) + + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport + BulletSoftBodySolvers_OpenCL_AMD + BulletMultiThreaded + BulletSoftBody + BulletDynamics + BulletCollision + LinearMath + ${GLUT_glut_LIBRARY} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${CMAK_GLEW_LIBRARY} + ${CMAKE_ATISTREAMSDK_LIBPATH}/OpenCL.lib + ) + + + ADD_EXECUTABLE(AppOpenCLClothDemo_AMD + ../cl_cloth_demo.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLInclude.h +# ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL/GLDebugDrawer.cpp + ../gl_win.cpp + ../clstuff.cpp + + + ../clstuff.h + ../gl_win.h + ../cloth.h + + ) +ELSE (USE_GLUT) +ENDIF (USE_GLUT) + +IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF(WIN32) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( TARGET AppOpenCLClothDemo_AMD POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + + ADD_CUSTOM_COMMAND( TARGET AppOpenCLClothDemo_AMD POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF(WIN32) + ADD_CUSTOM_COMMAND( TARGET AppOpenCLClothDemo_AMD POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/bullet_logo.png ${CMAKE_CURRENT_BINARY_DIR} + ) +ENDIF(NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + +IF (UNIX) + TARGET_LINK_LIBRARIES(AppOpenCLClothDemo_AMD pthread) +ENDIF(UNIX) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppOpenCLClothDemo_AMD PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppOpenCLClothDemo_AMD PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppOpenCLClothDemo_AMD PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/OpenCLClothDemo/AMD/premake4.lua b/Demos/OpenCLClothDemo/AMD/premake4.lua new file mode 100644 index 0000000..6d78362 --- /dev/null +++ b/Demos/OpenCLClothDemo/AMD/premake4.lua @@ -0,0 +1,67 @@ + + hasCL = findOpenCL_AMD() + + if (hasCL) then + + project "AppOpenCLClothDemo_AMD" + + defines { "USE_AMD_OPENCL","CL_PLATFORM_AMD"} + + initOpenCL_AMD() + + language "C++" + + kind "ConsoleApp" + targetdir "../../.." + + libdirs {"../../../Glut"} + + links { + "LinearMath", + "BulletCollision", + "BulletDynamics", + "BulletSoftBody", + "BulletSoftBodySolvers_OpenCL_AMD", + "opengl32" + } + + configuration { "Windows" } + defines { "GLEW_STATIC"} + + configuration "x64" + links { + "glut64", + "glew64s" + } + configuration "x32" + links { + "glut32", + "glew32s" + } + + configuration{} + + + includedirs { + "../../../src", + "../../../Glut", + "../../SharedOpenCL", + "../../OpenGL" + } + + files { + "../cl_cloth_demo.cpp", + "../../SharedOpenCL/btOpenCLUtils.cpp", + "../../SharedOpenCL/btOpenCLUtils.h", + "../../SharedOpenCL/btOpenCLInclude.h", + "../../OpenGL/GLDebugDrawer.cpp", + "../../OpenGL/stb_image.cpp", + "../../OpenGL/stb_image.h", + "../gl_win.cpp", + "../clstuff.cpp", + "../clstuff.h", + "../gl_win.h", + "../cloth.h" + } + + end \ No newline at end of file diff --git a/Demos/OpenCLClothDemo/Apple/CMakeLists.txt b/Demos/OpenCLClothDemo/Apple/CMakeLists.txt new file mode 100644 index 0000000..18a10d4 --- /dev/null +++ b/Demos/OpenCLClothDemo/Apple/CMakeLists.txt @@ -0,0 +1,55 @@ + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL +${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + + +IF (APPLE) + FIND_LIBRARY(OPENCL_LIBRARY OpenCL DOC "OpenCL lib for OSX") + FIND_PATH(OPENCL_INCLUDE_DIR OpenCL/cl.h DOC "Include for OpenCL on OSX") +ENDIF (APPLE) + + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport + BulletSoftBodySolvers_OpenCL_Apple + BulletMultiThreaded + BulletSoftBody + BulletDynamics + BulletCollision + LinearMath + ${OPENCL_LIBRARY} + ${GLUT_glut_LIBRARY} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${CMAK_GLEW_LIBRARY} + ) + + + ADD_EXECUTABLE(AppOpenCLClothDemo_Apple + ../cl_cloth_demo.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLInclude.h + ../gl_win.cpp + ../clstuff.cpp + ../clstuff.h + ../gl_win.h + + ) +ELSE (USE_GLUT) +ENDIF (USE_GLUT) + + +ADD_CUSTOM_COMMAND( TARGET AppOpenCLClothDemo_Apple POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/bullet_logo.png ${CMAKE_CURRENT_BINARY_DIR} + ) + +IF (UNIX) + TARGET_LINK_LIBRARIES(AppOpenCLClothDemo_Apple pthread) +ENDIF(UNIX) + diff --git a/Demos/OpenCLClothDemo/CLClothDemo.sln b/Demos/OpenCLClothDemo/CLClothDemo.sln new file mode 100644 index 0000000..48af26c --- /dev/null +++ b/Demos/OpenCLClothDemo/CLClothDemo.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CLClothDemo", "CLClothDemo.vcproj", "{A61906AF-B5DE-454E-99F6-B653C250D221}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A61906AF-B5DE-454E-99F6-B653C250D221}.Debug|Win32.ActiveCfg = Debug|Win32 + {A61906AF-B5DE-454E-99F6-B653C250D221}.Debug|Win32.Build.0 = Debug|Win32 + {A61906AF-B5DE-454E-99F6-B653C250D221}.Release|Win32.ActiveCfg = Release|Win32 + {A61906AF-B5DE-454E-99F6-B653C250D221}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Demos/OpenCLClothDemo/CLClothDemo.vcproj b/Demos/OpenCLClothDemo/CLClothDemo.vcproj new file mode 100644 index 0000000..1023daf --- /dev/null +++ b/Demos/OpenCLClothDemo/CLClothDemo.vcproj @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Demos/OpenCLClothDemo/CMakeLists.txt b/Demos/OpenCLClothDemo/CMakeLists.txt new file mode 100644 index 0000000..03cf16a --- /dev/null +++ b/Demos/OpenCLClothDemo/CMakeLists.txt @@ -0,0 +1,17 @@ + SUBDIRS( MiniCL ) + +IF(BUILD_INTEL_OPENCL_DEMOS) + SUBDIRS(Intel) +ENDIF() + +IF(BUILD_AMD_OPENCL_DEMOS) + SUBDIRS(AMD) +ENDIF() + +IF(BUILD_NVIDIA_OPENCL_DEMOS) + SUBDIRS(NVidia) +ENDIF() + +IF(APPLE) + SUBDIRS(Apple) +ENDIF() diff --git a/Demos/OpenCLClothDemo/Intel/CMakeLists.txt b/Demos/OpenCLClothDemo/Intel/CMakeLists.txt new file mode 100644 index 0000000..0acc2c5 --- /dev/null +++ b/Demos/OpenCLClothDemo/Intel/CMakeLists.txt @@ -0,0 +1,85 @@ + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL +${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +${INTEL_OPENCL_INCLUDES} +) + +ADD_DEFINITIONS(-DUSE_INTEL_OPENCL) +ADD_DEFINITIONS(-DCL_PLATFORM_INTEL) + + +IF (CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY + ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew64.lib ) +ELSE(CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew32.lib ) +ENDIF(CMAKE_CL_64) + + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport + BulletSoftBodySolvers_OpenCL_Intel + BulletMultiThreaded + BulletSoftBody + BulletDynamics + BulletCollision + LinearMath + ${GLUT_glut_LIBRARY} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${CMAK_GLEW_LIBRARY} + ${INTEL_OPENCL_LIBRARIES} + ) + + + ADD_EXECUTABLE(AppOpenCLClothDemo_Intel + ../cl_cloth_demo.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLInclude.h +# ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL/GLDebugDrawer.cpp + ../gl_win.cpp + ../clstuff.cpp + ../clstuff.h + ../gl_win.h + ../cloth.h + + ) +ELSE (USE_GLUT) +ENDIF (USE_GLUT) + +IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF(WIN32) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( TARGET AppOpenCLClothDemo_Intel POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ADD_CUSTOM_COMMAND( TARGET AppOpenCLClothDemo_Intel POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLEW64.DLL ${CMAKE_CURRENT_BINARY_DIR}) + ELSE(CMAKE_CL_64) + + ADD_CUSTOM_COMMAND( TARGET AppOpenCLClothDemo_Intel POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ADD_CUSTOM_COMMAND( TARGET AppOpenCLClothDemo_Intel POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLEW32.DLL ${CMAKE_CURRENT_BINARY_DIR}) + ENDIF(CMAKE_CL_64) + ENDIF(WIN32) + ADD_CUSTOM_COMMAND( TARGET AppOpenCLClothDemo_Intel POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/bullet_logo.png ${CMAKE_CURRENT_BINARY_DIR} + ) +ENDIF(NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + +IF (UNIX) + TARGET_LINK_LIBRARIES(AppOpenCLClothDemo_Intel pthread) +ENDIF(UNIX) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppOpenCLClothDemo_Intel PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppOpenCLClothDemo_Intel PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppOpenCLClothDemo_Intel PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) diff --git a/Demos/OpenCLClothDemo/Intel/premake4.lua b/Demos/OpenCLClothDemo/Intel/premake4.lua new file mode 100644 index 0000000..930f8e7 --- /dev/null +++ b/Demos/OpenCLClothDemo/Intel/premake4.lua @@ -0,0 +1,68 @@ + + hasCL = findOpenCL_Intel() + + if (hasCL) then + + project "AppOpenCLClothDemo_Intel" + + defines { "USE_INTEL_OPENCL","CL_PLATFORM_INTEL"} + + initOpenCL_Intel() + + language "C++" + + kind "ConsoleApp" + targetdir "../../.." + + libdirs {"../../../Glut"} + + links { + "LinearMath", + "BulletCollision", + "BulletDynamics", + "BulletSoftBody", + "BulletSoftBodySolvers_OpenCL_Intel", + "opengl32" + } + + configuration { "Windows" } + defines { "GLEW_STATIC"} + + + configuration "x64" + links { + "glut64", + "glew64s" + } + configuration "x32" + links { + "glut32", + "glew32s" + } + + configuration{} + + + includedirs { + "../../../src", + "../../../Glut", + "../../SharedOpenCL", + "../../OpenGL" + } + + files { + "../cl_cloth_demo.cpp", + "../../SharedOpenCL/btOpenCLUtils.cpp", + "../../SharedOpenCL/btOpenCLUtils.h", + "../../SharedOpenCL/btOpenCLInclude.h", + "../../OpenGL/GLDebugDrawer.cpp", + "../../OpenGL/stb_image.cpp", + "../../OpenGL/stb_image.h", + "../gl_win.cpp", + "../clstuff.cpp", + "../clstuff.h", + "../gl_win.h", + "../cloth.h" + } + + end \ No newline at end of file diff --git a/Demos/OpenCLClothDemo/MiniCL/CMakeLists.txt b/Demos/OpenCLClothDemo/MiniCL/CMakeLists.txt new file mode 100644 index 0000000..608b16e --- /dev/null +++ b/Demos/OpenCLClothDemo/MiniCL/CMakeLists.txt @@ -0,0 +1,88 @@ + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL +${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +ADD_DEFINITIONS(-DUSE_MINICL) + +IF(WIN32) +ADD_DEFINITIONS(-DGLEW_STATIC) +ENDIF(WIN32) + +IF (WIN32) + IF (CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY + ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew64s.lib ) + ELSE(CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew32s.lib ) + ENDIF(CMAKE_CL_64) +ENDIF() + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport + BulletSoftBodySolvers_OpenCL_Mini + MiniCL + BulletMultiThreaded + BulletSoftBody + BulletDynamics + BulletCollision + LinearMath + ${GLUT_glut_LIBRARY} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${CMAK_GLEW_LIBRARY} + + ) + + + ADD_EXECUTABLE(AppOpenCLClothDemo_Mini + ../cl_cloth_demo.cpp + ../gl_win.cpp + ../clstuff.cpp + ../clstuff.h + ../gl_win.h + ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLInclude.h + + ) +ELSE (USE_GLUT) +ENDIF (USE_GLUT) + +IF(WIN32) +IF (CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppOpenCLClothDemo_Mini POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF() +ELSE(CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppOpenCLClothDemo_Mini POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + + ENDIF() +ENDIF(CMAKE_CL_64) +ENDIF(WIN32) + +IF(NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppOpenCLClothDemo_Mini POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/bullet_logo.png ${CMAKE_CURRENT_BINARY_DIR} + ) +ENDIF() +IF (UNIX) + TARGET_LINK_LIBRARIES(AppOpenCLClothDemo_Mini pthread) +ENDIF(UNIX) + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppOpenCLClothDemo_Mini PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppOpenCLClothDemo_Mini PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppOpenCLClothDemo_Mini PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/OpenCLClothDemo/NVidia/CMakeLists.txt b/Demos/OpenCLClothDemo/NVidia/CMakeLists.txt new file mode 100644 index 0000000..fab2f0b --- /dev/null +++ b/Demos/OpenCLClothDemo/NVidia/CMakeLists.txt @@ -0,0 +1,86 @@ + + +ADD_DEFINITIONS(-DUSE_NVIDIA_OPENCL) +ADD_DEFINITIONS(-DCL_PLATFORM_NVIDIA) + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL +${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +${NVIDIA_OPENCL_INCLUDES} +) + +IF(WIN32) +ADD_DEFINITIONS(-DGLEW_STATIC) +ENDIF(WIN32) + + +IF (CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY + ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew64s.lib ) +ELSE(CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew32s.lib ) +ENDIF(CMAKE_CL_64) + + +IF (USE_GLUT) + + LINK_LIBRARIES( + OpenGLSupport + BulletSoftBodySolvers_OpenCL_NVidia + BulletMultiThreaded + BulletSoftBody + BulletDynamics + BulletCollision + LinearMath + ${GLUT_glut_LIBRARY} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${CMAK_GLEW_LIBRARY} + ${NVIDIA_OPENCL_LIBRARIES} + ) + + ADD_EXECUTABLE(AppOpenCLClothDemo_NVidia + ../cl_cloth_demo.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLInclude.h + ../gl_win.cpp + ../clstuff.cpp + ../clstuff.h + ../gl_win.h + + ) +ELSE (USE_GLUT) +ENDIF (USE_GLUT) + +IF(WIN32) +IF (CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppOpenCLClothDemo_NVidia POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF() +ELSE(CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppOpenCLClothDemo_NVidia POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + + ENDIF() +ENDIF(CMAKE_CL_64) +ENDIF(WIN32) +IF(NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppOpenCLClothDemo_NVidia POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/bullet_logo.png ${CMAKE_CURRENT_BINARY_DIR} + ) +ENDIF() +IF (UNIX) + TARGET_LINK_LIBRARIES(AppOpenCLClothDemo_NVidia pthread) +ENDIF(UNIX) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppOpenCLClothDemo_NVidia PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppOpenCLClothDemo_NVidia PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppOpenCLClothDemo_NVidia PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) diff --git a/Demos/OpenCLClothDemo/NVidia/premake4.lua b/Demos/OpenCLClothDemo/NVidia/premake4.lua new file mode 100644 index 0000000..00ae412 --- /dev/null +++ b/Demos/OpenCLClothDemo/NVidia/premake4.lua @@ -0,0 +1,68 @@ + + hasCL = findOpenCL_NVIDIA() + + if (hasCL) then + + project "AppOpenCLClothDemo_NVIDIA" + + defines { "USE_NVIDIA_OPENCL","CL_PLATFORM_NVIDIA"} + + initOpenCL_NVIDIA() + + language "C++" + + kind "ConsoleApp" + targetdir "../../.." + + libdirs {"../../../Glut"} + + links { + "LinearMath", + "BulletCollision", + "BulletDynamics", + "BulletSoftBody", + "BulletSoftBodySolvers_OpenCL_NVIDIA", + "opengl32" + } + + configuration { "Windows" } + defines { "GLEW_STATIC"} + + + configuration "x64" + links { + "glut64", + "glew64s" + } + configuration "x32" + links { + "glut32", + "glew32s" + } + + configuration{} + + + includedirs { + "../../../src", + "../../../Glut", + "../../SharedOpenCL", + "../../OpenGL" + } + + files { + "../cl_cloth_demo.cpp", + "../../SharedOpenCL/btOpenCLUtils.cpp", + "../../SharedOpenCL/btOpenCLUtils.h", + "../../SharedOpenCL/btOpenCLInclude.h", + "../../OpenGL/GLDebugDrawer.cpp", + "../../OpenGL/stb_image.cpp", + "../../OpenGL/stb_image.h", + "../gl_win.cpp", + "../clstuff.cpp", + "../clstuff.h", + "../gl_win.h", + "../cloth.h" + } + + end \ No newline at end of file diff --git a/Demos/OpenCLClothDemo/btOpenCLSupport.h b/Demos/OpenCLClothDemo/btOpenCLSupport.h new file mode 100644 index 0000000..5b03e14 --- /dev/null +++ b/Demos/OpenCLClothDemo/btOpenCLSupport.h @@ -0,0 +1,84 @@ +#ifndef BT_OPENCL_SUPPORT_HPP +#define BT_OPENCL_SUPPORT_HPP + +// OpenCL support +#include + +namespace BTAcceleratedSoftBody +{ + class OpenCLSupportHelper + { + private: + cl::Context m_context; + std::vector m_devices; + cl::CommandQueue m_queue; + public: + OpenCLSupportHelper() + { + } + + virtual ~OpenCLSupportHelper() + { + } + + cl::Device getDevice() + { + return m_devices[0]; + } + + cl::CommandQueue getCommandQueue() + { + return m_queue; + } + + cl::Context getContext() + { + return m_context; + } + + bool InitOpenCLDevice() + { + cl_int err; + + std::vector platforms; + err = cl::Platform::get(&platforms); + checkErr(platforms.size() != 0 ? CL_SUCCESS : -1, "Platform::get()"); + + std::string platformVendor; + platforms[0].getInfo(CL_PLATFORM_VENDOR, &platformVendor); + //std::cout << "Platform is by: " << platformVendor << "\n"; + + intptr_t properties[] = { + CL_CONTEXT_PLATFORM, (intptr_t)platforms[0](), + 0, 0 + }; + m_context = cl::Context( + CL_DEVICE_TYPE_GPU, + properties, + NULL, + NULL, + &err); + + if (err != CL_SUCCESS) + { + btAssert( "Context::Context()" ); + } + + m_devices = m_context.getInfo(); + if( m_devices.size() <= 0 ) + { + btAssert( "devices.size() > 0" ); + } + + m_queue = cl::CommandQueue(m_context, m_devices[0], 0, &err); + if (err != CL_SUCCESS) + { + btAssert( "CommandQueue::CommandQueue()"); + } + } + }; + + +} // namespace BTAcceleratedSoftBody + +#endif // #ifndef BT_OPENCL_SUPPORT_HPP \ No newline at end of file diff --git a/Demos/OpenCLClothDemo/cl_cloth_demo.cpp b/Demos/OpenCLClothDemo/cl_cloth_demo.cpp new file mode 100644 index 0000000..5a48709 --- /dev/null +++ b/Demos/OpenCLClothDemo/cl_cloth_demo.cpp @@ -0,0 +1,613 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2008 Advanced Micro Devices + +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. +*/ + +#ifdef _WIN32 +#include +#endif + + + +#ifndef USE_MINICL +#define USE_SIMDAWARE_SOLVER +#endif + +#if !defined (__APPLE__) +#define USE_GPU_SOLVER +#if defined (_WIN32) && !defined(USE_MINICL) + #define USE_GPU_COPY //only tested on Windows +#endif //_WIN32 && !USE_MINICL +#endif //!__APPLE__ + + + + + +#include "clstuff.h" +#include "gl_win.h" +#include "cloth.h" + +#include "../OpenGL/GLDebugDrawer.h" + +GLDebugDrawer debugDraw; + +const int numFlags = 5; +const int clothWidth = 40; +const int clothHeight = 60;//60; +float _windAngle = 1.0;//0.4; +float _windStrength = 0.; + + + +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btHashMap.h" +#include "BulletSoftBody/btSoftRigidDynamicsWorld.h" +#include "vectormath/vmInclude.h" +#include "BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h" +#include "BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h" +#include "BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h" +#include "BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h" + + +btRigidBody *capCollider; + + +using Vectormath::Aos::Vector3; + +class piece_of_cloth; +class btBroadphaseInterface; +class btCollisionShape; +class btOverlappingPairCache; +class btCollisionDispatcher; +class btConstraintSolver; +struct btCollisionAlgorithmCreateFunc; +class btDefaultCollisionConfiguration; + +#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h" + +namespace Vectormath +{ + namespace Aos + { + class Transform3; + } +} + + +btAlignedObjectArray m_collisionShapes; +btBroadphaseInterface* m_broadphase; +btCollisionDispatcher* m_dispatcher; +btConstraintSolver* m_solver; +btDefaultCollisionConfiguration* m_collisionConfiguration; + +btOpenCLSoftBodySolver *g_openCLSolver = NULL; +btOpenCLSoftBodySolverSIMDAware *g_openCLSIMDSolver = NULL; + +btSoftBodySolver *g_solver = NULL; + +btSoftBodySolverOutput *g_softBodyOutput = NULL; + +btAlignedObjectArray m_flags; +btSoftRigidDynamicsWorld* m_dynamicsWorld; +btAlignedObjectArray cloths; + +extern cl_context g_cxMainContext; +extern cl_device_id g_cdDevice; +extern cl_command_queue g_cqCommandQue; + + +const float flagSpacing = 30.f; + + +// Helper to test and add links correctly. +// Records links that have already been generated +static bool testAndAddLink( btAlignedObjectArray &trianglesForLinks, btSoftBody *softBody, int triangle, int *triangleVertexIndexArray, int numVertices, int vertex0, int vertex1, int nonLinkVertex, btSoftBody::Material *structuralMaterial, bool createBendLinks, btSoftBody::Material *bendMaterial ) +{ + if( trianglesForLinks[ numVertices * vertex0 + vertex1 ] >= 0 && createBendLinks) + { + // Already have link so find other triangle and generate cross link + + int otherTriangle = trianglesForLinks[numVertices * vertex0 + vertex1]; + int otherIndices[3] = {triangleVertexIndexArray[otherTriangle * 3], triangleVertexIndexArray[otherTriangle * 3 + 1], triangleVertexIndexArray[otherTriangle * 3 + 2]}; + + int nodeA; + // Test all links of the other triangle against this link. The one that's not part of it is what we want. + if( otherIndices[0] != vertex0 && otherIndices[0] != vertex1 ) + nodeA = otherIndices[0]; + if( otherIndices[1] != vertex0 && otherIndices[1] != vertex1 ) + nodeA = otherIndices[1]; + if( otherIndices[2] != vertex0 && otherIndices[2] != vertex1 ) + nodeA = otherIndices[2]; + + softBody->appendLink( nodeA, nonLinkVertex, bendMaterial ); + } else { + // Don't yet have link so create it + softBody->appendLink( vertex0, vertex1, structuralMaterial ); + + // If we added a new link, set the triangle array + trianglesForLinks[numVertices * vertex0 + vertex1] = triangle; + trianglesForLinks[numVertices * vertex1 + vertex0] = triangle; + + } + + return true; +} + +btSoftBody *createFromIndexedMesh( btVector3 *vertexArray, int numVertices, int *triangleVertexIndexArray, int numTriangles, bool createBendLinks ) +{ + btSoftBody* softBody = new btSoftBody(&(m_dynamicsWorld->getWorldInfo()), numVertices, vertexArray, 0); + btSoftBody::Material * structuralMaterial = softBody->appendMaterial(); + btSoftBody::Material * bendMaterial; + if( createBendLinks ) + { + bendMaterial = softBody->appendMaterial(); + bendMaterial->m_kLST = 0.7; + } else { + bendMaterial = NULL; + } + structuralMaterial->m_kLST = 1.0; + + + // List of values for each link saying which triangle is associated with that link + // -1 to start. Once a value is entered we know the "other" triangle + // and can add a link across the link + btAlignedObjectArray triangleForLinks; + triangleForLinks.resize( numVertices * numVertices, -1 ); + int numLinks = 0; + for( int triangle = 0; triangle < numTriangles; ++triangle ) + { + int index[3] = {triangleVertexIndexArray[triangle * 3], triangleVertexIndexArray[triangle * 3 + 1], triangleVertexIndexArray[triangle * 3 + 2]}; + softBody->appendFace( index[0], index[1], index[2] ); + + // Generate the structural links directly from the triangles + testAndAddLink( triangleForLinks, softBody, triangle, triangleVertexIndexArray, numVertices, index[0], index[1], index[2], structuralMaterial, createBendLinks, bendMaterial ); + testAndAddLink( triangleForLinks, softBody, triangle, triangleVertexIndexArray, numVertices, index[1], index[2], index[0], structuralMaterial, createBendLinks, bendMaterial ); + testAndAddLink( triangleForLinks, softBody, triangle, triangleVertexIndexArray, numVertices, index[2], index[0], index[1], structuralMaterial, createBendLinks, bendMaterial); + } + + return softBody; +} + +/** + * Create a sequence of flag objects and add them to the world. + */ +void createFlag( btSoftBodySolver &solver, int width, int height, btAlignedObjectArray &flags ) +{ + // First create a triangle mesh to represent a flag + + using Vectormath::Aos::Matrix3; + using Vectormath::Aos::Vector3; + + // Allocate a simple mesh consisting of a vertex array and a triangle index array + btIndexedMesh mesh; + mesh.m_numVertices = width*height; + mesh.m_numTriangles = 2*(width-1)*(height-1); + + btVector3 *vertexArray = new btVector3[mesh.m_numVertices]; + + mesh.m_vertexBase = reinterpret_cast(vertexArray); + int *triangleVertexIndexArray = new int[3*mesh.m_numTriangles]; + mesh.m_triangleIndexBase = reinterpret_cast(triangleVertexIndexArray); + mesh.m_triangleIndexStride = sizeof(int)*3; + mesh.m_vertexStride = sizeof(Vector3); + + // Generate normalised object space vertex coordinates for a rectangular flag + float zCoordinate = 0.0f; + + Matrix3 defaultScale(Vector3(5.f, 0.f, 0.f), Vector3(0.f, 20.f, 0.f), Vector3(0.f, 0.f, 1.f)); + for( int y = 0; y < height; ++y ) + { + float yCoordinate = y*2.0f/float(height) - 1.0f; + for( int x = 0; x < width; ++x ) + { + float xCoordinate = x*2.0f/float(width) - 1.0f; + + Vector3 vertex(xCoordinate, yCoordinate, zCoordinate); + Vector3 transformedVertex = defaultScale*vertex; + + vertexArray[y*width + x] = btVector3(transformedVertex.getX(), transformedVertex.getY(), transformedVertex.getZ() ); + + } + } + + // Generate vertex indices for triangles + for( int y = 0; y < (height-1); ++y ) + { + for( int x = 0; x < (width-1); ++x ) + { + // Triangle 0 + // Top left of square on mesh + { + int vertex0 = y*width + x; + int vertex1 = vertex0 + 1; + int vertex2 = vertex0 + width; + int triangleIndex = 2*y*(width-1) + 2*x; + triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex)/sizeof(int)] = vertex0; + triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex+1)/sizeof(int)+1] = vertex1; + triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex+2)/sizeof(int)+2] = vertex2; + } + + // Triangle 1 + // Bottom right of square on mesh + { + int vertex0 = y*width + x + 1; + int vertex1 = vertex0 + width; + int vertex2 = vertex1 - 1; + int triangleIndex = 2*y*(width-1) + 2*x + 1; + triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex)/sizeof(int)] = vertex0; + triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex)/sizeof(int)+1] = vertex1; + triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex)/sizeof(int)+2] = vertex2; + } + } + } + + + float rotateAngleRoundZ = 0.0; + float rotateAngleRoundX = 0.5; + btMatrix3x3 defaultRotate; + defaultRotate[0] = btVector3(cos(rotateAngleRoundZ), sin(rotateAngleRoundZ), 0.f); + defaultRotate[1] = btVector3(-sin(rotateAngleRoundZ), cos(rotateAngleRoundZ), 0.f); + defaultRotate[2] = btVector3(0.f, 0.f, 1.f); + btMatrix3x3 defaultRotateX; + defaultRotateX[0] = btVector3(1.f, 0.f, 0.f); + defaultRotateX[1] = btVector3( 0.f, cos(rotateAngleRoundX), sin(rotateAngleRoundX)); + defaultRotateX[2] = btVector3(0.f, -sin(rotateAngleRoundX), cos(rotateAngleRoundX)); + + btMatrix3x3 defaultRotateAndScale( (defaultRotateX*defaultRotate) ); + + + // Construct the sequence flags applying a slightly different translation to each one to arrange them + // appropriately in the scene. + for( int i = 0; i < numFlags; ++i ) + { + float zTranslate = flagSpacing * (i-numFlags/2); + + btVector3 defaultTranslate(0.f, 20.f, zTranslate); + + btTransform transform( defaultRotateAndScale, defaultTranslate ); + transform.setOrigin(defaultTranslate); + + + btSoftBody *softBody = createFromIndexedMesh( vertexArray, mesh.m_numVertices, triangleVertexIndexArray, mesh.m_numTriangles, true ); + + + for( int i = 0; i < mesh.m_numVertices; ++i ) + { + softBody->setMass(i, 10.f/mesh.m_numVertices); + } + softBody->setMass((height-1)*(width), 0.f); + softBody->setMass((height-1)*(width) + width - 1, 0.f); + softBody->setMass((height-1)*width + width/2, 0.f); + softBody->m_cfg.collisions = btSoftBody::fCollision::CL_SS+btSoftBody::fCollision::CL_RS; + + softBody->m_cfg.kLF = 0.0005f; + softBody->m_cfg.kVCF = 0.001f; + softBody->m_cfg.kDP = 0.f; + softBody->m_cfg.kDG = 0.f; + + + flags.push_back( softBody ); + + softBody->transform( transform ); + + m_dynamicsWorld->addSoftBody( softBody ); + } + + delete [] vertexArray; + delete [] triangleVertexIndexArray; +} + + +void updatePhysicsWorld() +{ + static int counter = 1; + + // Change wind velocity a bit based on a frame counter + if( (counter % 400) == 0 ) + { + _windAngle = (_windAngle + 0.05f); + if( _windAngle > (2*3.141) ) + _windAngle = 0; + + for( int flagIndex = 0; flagIndex < m_flags.size(); ++flagIndex ) + { + btSoftBody *cloth = 0; + + cloth = m_flags[flagIndex]; + + float localWind = _windAngle + 0.5*(((float(rand())/RAND_MAX))-0.1); + float xCoordinate = cos(localWind)*_windStrength; + float zCoordinate = sin(localWind)*_windStrength; + + cloth->setWindVelocity( btVector3(xCoordinate, 0, zCoordinate) ); + } + } + + //btVector3 origin( capCollider->getWorldTransform().getOrigin() ); + //origin.setX( origin.getX() + 0.05 ); + //capCollider->getWorldTransform().setOrigin( origin ); + + counter++; +} + +void initBullet(void) +{ + +#ifdef USE_GPU_SOLVER +#ifdef USE_SIMDAWARE_SOLVER + g_openCLSIMDSolver = new btOpenCLSoftBodySolverSIMDAware( g_cqCommandQue, g_cxMainContext); + g_solver = g_openCLSIMDSolver; +#ifdef USE_GPU_COPY + g_softBodyOutput = new btSoftBodySolverOutputCLtoGL(g_cqCommandQue, g_cxMainContext); +#else // #ifdef USE_GPU_COPY + g_softBodyOutput = new btSoftBodySolverOutputCLtoCPU; +#endif // #ifdef USE_GPU_COPY +#else + g_openCLSolver = new btOpenCLSoftBodySolver( g_cqCommandQue, g_cxMainContext ); + g_solver = g_openCLSolver; +#ifdef USE_GPU_COPY + g_softBodyOutput = new btSoftBodySolverOutputCLtoGL(g_cqCommandQue, g_cxMainContext); +#else // #ifdef USE_GPU_COPY + g_softBodyOutput = new btSoftBodySolverOutputCLtoCPU; +#endif // #ifdef USE_GPU_COPY +#endif +#else + g_openCLSolver = new btOpenCLSoftBodySolver( g_cqCommandQue, g_cxMainContext ); + g_solver = g_openCLSolver; +#endif + + //m_collisionConfiguration = new btDefaultCollisionConfiguration(); + m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration(); + + + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + m_broadphase = new btDbvtBroadphase(); + btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; + m_solver = sol; + + m_dynamicsWorld = new btSoftRigidDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration, g_solver); + + m_dynamicsWorld->setGravity(btVector3(0,-10,0)); + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); + m_collisionShapes.push_back(groundShape); + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + + + + + + + m_dynamicsWorld->getWorldInfo().air_density = (btScalar)1.2; + m_dynamicsWorld->getWorldInfo().water_density = 0; + m_dynamicsWorld->getWorldInfo().water_offset = 0; + m_dynamicsWorld->getWorldInfo().water_normal = btVector3(0,0,0); + m_dynamicsWorld->getWorldInfo().m_gravity.setValue(0,-10,0); + + + +#if 0 + { + btScalar mass(0.); + + //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) + groundShape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + //add the body to the dynamics world + m_dynamicsWorld->addRigidBody(body); + } + +#endif + + #if 1 + { + btScalar mass(0.); + + //btScalar mass(1.); + + //rigidbody is dynamic if and only if mass is non zero, otherwise static + bool isDynamic = (mass != 0.f); + + btCollisionShape *capsuleShape = new btCapsuleShape(5, 10); + capsuleShape->setMargin( 0.5 ); + + + + + btVector3 localInertia(0,0,0); + if (isDynamic) + capsuleShape->calculateLocalInertia(mass,localInertia); + + m_collisionShapes.push_back(capsuleShape); + btTransform capsuleTransform; + capsuleTransform.setIdentity(); +#ifdef TABLETEST + capsuleTransform.setOrigin(btVector3(0, 10, -11)); + const btScalar pi = 3.141592654; + capsuleTransform.setRotation(btQuaternion(0, 0, pi/2)); +#else + capsuleTransform.setOrigin(btVector3(0, 0, 0)); + + const btScalar pi = 3.141592654; + //capsuleTransform.setRotation(btQuaternion(0, 0, pi/2)); + capsuleTransform.setRotation(btQuaternion(0, 0, 0)); +#endif + btDefaultMotionState* myMotionState = new btDefaultMotionState(capsuleTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,capsuleShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + body->setFriction( 0.8f ); + + m_dynamicsWorld->addRigidBody(body); + //cap_1.collisionShape = body; + capCollider = body; + } +#endif + + +//#ifdef USE_GPU_SOLVER + createFlag( *g_openCLSolver, clothWidth, clothHeight, m_flags ); +//#else + +//#endif + + // Create output buffer descriptions for ecah flag + // These describe where the simulation should send output data to + for( int flagIndex = 0; flagIndex < m_flags.size(); ++flagIndex ) + { +// m_flags[flagIndex]->setWindVelocity( Vectormath::Aos::Vector3( 0.f, 0.f, 15.f ) ); + + // In this case we have a DX11 output buffer with a vertex at index 0, 8, 16 and so on as well as a normal at 3, 11, 19 etc. + // Copies will be performed GPU-side directly into the output buffer + +#ifdef USE_GPU_COPY + GLuint targetVBO = cloths[flagIndex].getVBO(); + btOpenGLInteropVertexBufferDescriptor *vertexBufferDescriptor = new btOpenGLInteropVertexBufferDescriptor(g_cqCommandQue, g_cxMainContext, targetVBO, 0, 8, 3, 8); +#else + btCPUVertexBufferDescriptor *vertexBufferDescriptor = new btCPUVertexBufferDescriptor(reinterpret_cast< float* >(cloths[flagIndex].cpu_buffer), 0, 8, 3, 8); +#endif + cloths[flagIndex].m_vertexBufferDescriptor = vertexBufferDescriptor; + } + + + g_solver->optimize( m_dynamicsWorld->getSoftBodyArray() ); + + if (!g_solver->checkInitialized()) + { + printf("OpenCL kernel initialization ?failed\n"); + btAssert(0); + exit(0); + } + +} + + + + +btClock m_clock; + +void doFlags() +{ + //float ms = getDeltaTimeMicroseconds(); + btScalar dt = (btScalar)m_clock.getTimeMicroseconds(); + m_clock.reset(); + + ///step the simulation + if( m_dynamicsWorld ) + { + m_dynamicsWorld->stepSimulation(dt/1000000.); + + static int frameCount = 0; + frameCount++; + if (frameCount==100) + { + m_dynamicsWorld->stepSimulation(1./60.,0); + + // Option to save a .bullet file + // btDefaultSerializer* serializer = new btDefaultSerializer(); + // m_dynamicsWorld->serialize(serializer); + // FILE* file = fopen("testFile.bullet","wb"); + // fwrite(serializer->getBufferPointer(),serializer->getCurrentBufferSize(),1, file); + // fclose(file); + + CProfileManager::dumpAll(); + } + updatePhysicsWorld(); + + //m_dynamicsWorld->setDebugDrawer(&debugDraw); + //debugDraw.setDebugMode(btIDebugDraw::DBG_DrawWireframe); + //g_solver->copyBackToSoftBodies(); + + m_dynamicsWorld->debugDrawWorld(); + + } + + + for( int flagIndex = 0; flagIndex < m_flags.size(); ++flagIndex ) + { + g_softBodyOutput->copySoftBodyToVertexBuffer( m_flags[flagIndex], cloths[flagIndex].m_vertexBufferDescriptor ); + cloths[flagIndex].draw(); + } +} + + +int main(int argc, char *argv[]) +{ + + + preInitGL(argc, argv); +#ifdef _WIN32 + glewInit(); +#endif + +#ifdef USE_GPU_COPY +#ifdef _WIN32 + HGLRC glCtx = wglGetCurrentContext(); +#else //!_WIN32 + GLXContext glCtx = glXGetCurrentContext(); +#endif //!_WIN32 + HDC glDC = wglGetCurrentDC(); + + initCL(glCtx, glDC); +#else + + initCL(); + +#endif + + cloths.resize(numFlags); + + for( int flagIndex = 0; flagIndex < numFlags; ++flagIndex ) + { + cloths[flagIndex].create_buffers(clothWidth, clothHeight); + } + + initBullet(); + m_dynamicsWorld->stepSimulation(1./60.,0); + + std::string flagTexs[] = { + "bullet_logo.png", + "bullet_logo.png", + }; + int numFlagTexs = 2; + + for( int flagIndex = 0; flagIndex < numFlags; ++flagIndex ) + { + cloths[flagIndex].create_texture(flagTexs[flagIndex % numFlagTexs]); + cloths[flagIndex].x_offset = 0; + cloths[flagIndex].y_offset = 0; + cloths[flagIndex].z_offset = 0; + } + + goGL(); + + if( g_openCLSolver ) + delete g_openCLSolver; + if( g_openCLSIMDSolver ) + delete g_openCLSIMDSolver; + if( g_softBodyOutput ) + delete g_softBodyOutput; + + return 0; +} + diff --git a/Demos/OpenCLClothDemo/cloth.h b/Demos/OpenCLClothDemo/cloth.h new file mode 100644 index 0000000..e3a0216 --- /dev/null +++ b/Demos/OpenCLClothDemo/cloth.h @@ -0,0 +1,258 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2008 Advanced Micro Devices + +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 "gl_win.h" //for OpenGL stuff + +#include "stb_image.h" + +#include +#include +#include "LinearMath/btScalar.h" +#include + + +struct vertex_struct +{ + float pos[3]; + float normal[3]; + float texcoord[2]; + +}; + +class btVertexBufferDescriptor; + +class piece_of_cloth +{ + public: + + void destroy(void) + { + if(created) + { + if(cpu_buffer) delete [] cpu_buffer; + } + } + + piece_of_cloth() + { + created = false; + cpu_buffer = NULL; + m_vertexBufferDescriptor = NULL; +#ifdef USE_GPU_COPY + clothVBO = 0; +#endif + } + + bool created; + + vertex_struct* cpu_buffer; + unsigned int* indices; + btVertexBufferDescriptor *m_vertexBufferDescriptor; + + double x_offset, y_offset, z_offset; + + int width; + int height; + + GLuint m_texture; +#ifdef USE_GPU_COPY + + GLuint clothVBO; + + GLuint getVBO() + { + return clothVBO; + } +#endif //USE_GPU_COPY + + void draw(void) + { + glEnable(GL_TEXTURE_2D); + glBindTexture (GL_TEXTURE_2D, m_texture); + + glEnable(GL_DEPTH_TEST); + + glColor3f(1.0f, 1.0f, 1.0f); +#ifdef USE_GPU_COPY + int error = 0; + glBindBuffer(GL_ARRAY_BUFFER, clothVBO); +#ifndef USE_GPU_COPY + // Upload data to VBO + // Needed while we're not doing interop + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_struct)*width*height, &(cpu_buffer[0]), GL_DYNAMIC_DRAW); +#endif +#endif + glEnableClientState(GL_VERTEX_ARRAY); +#ifdef USE_GPU_COPY + glEnableClientState(GL_NORMAL_ARRAY); +#endif + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + glBindTexture(GL_TEXTURE_2D, m_texture); +#ifdef USE_GPU_COPY + error = glGetError(); + + // VBO version + glVertexPointer( 3, GL_FLOAT, sizeof(vertex_struct), (const GLvoid *)0 ); + error = glGetError(); + glNormalPointer( GL_FLOAT, sizeof(vertex_struct), (const GLvoid *)(sizeof(float)*3) ); + error = glGetError(); + glTexCoordPointer( 2, GL_FLOAT, sizeof(vertex_struct), (const GLvoid *)(sizeof(float)*6) ); + error = glGetError(); + + +#else + glVertexPointer( 3, GL_FLOAT, sizeof(vertex_struct), reinterpret_cast< GLvoid* >(&(cpu_buffer[0].pos[0])) ); + //glNormalPointer( 3, sizeof(vertex_struct), reinterpret_cast< GLvoid* >(&(cpu_buffer[0].normal[0])) ); + glTexCoordPointer( 2, GL_FLOAT, sizeof(vertex_struct), reinterpret_cast< GLvoid* >(&(cpu_buffer[0].texcoord[0])) ); +#endif + + glDrawElements(GL_TRIANGLES, (height-1 )*(width-1)*3*2, GL_UNSIGNED_INT, indices); +// glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glBindTexture(GL_TEXTURE_2D, 0); +#ifdef USE_GPU_COPY + error = glGetError(); + glBindBuffer(GL_ARRAY_BUFFER, 0); + error = glGetError(); +#endif + + } + + void create_texture(std::string filename) + { + int width,height,n; + unsigned char *data = stbi_load(filename.c_str(), &width, &height, &n, 0); + if (!data) + { + //premake project happens to be 2 levels above the root of Bullet, so try this instead: + std::string newname = "../../"+filename; + data = stbi_load(newname.c_str(), &width, &height, &n, 0); + } + + GLubyte* image=new GLubyte[512*256*4]; + for(int y=0;y<256;++y) + { + const int t=y>>4; + GLubyte* pi=image+y*512*4; + for(int x=0;x<512;++x) + { + const int s=x>>5; + const GLubyte b=180; + GLubyte c=b+((s+t&1)&1)*(255-b); + pi[0]=pi[1]=pi[2]=c;pi[3]=1;pi+=4; + } + } + + if ( data ) + { + + for (int i=0;i + +cl_context g_cxMainContext; +cl_device_id g_cdDevice; +cl_command_queue g_cqCommandQue; + +void initCL( void* glCtx, void* glDC ) +{ + int ciErrNum = 0; + +#if defined(CL_PLATFORM_MINI_CL) + cl_device_type deviceType = CL_DEVICE_TYPE_CPU;//or use CL_DEVICE_TYPE_DEBUG to debug MiniCL +#elif defined(CL_PLATFORM_INTEL) + cl_device_type deviceType = CL_DEVICE_TYPE_CPU; +#elif defined(CL_PLATFORM_AMD) + cl_device_type deviceType = CL_DEVICE_TYPE_GPU; +#elif defined(CL_PLATFORM_NVIDIA) + cl_device_type deviceType = CL_DEVICE_TYPE_GPU; +#else +#ifdef __APPLE__ + cl_device_type deviceType = CL_DEVICE_TYPE_ALL;//GPU; +#else + cl_device_type deviceType = CL_DEVICE_TYPE_CPU;//CL_DEVICE_TYPE_ALL +#endif//__APPLE__ +#endif + + g_cxMainContext = btOpenCLUtils::createContextFromType(deviceType, &ciErrNum, glCtx, glDC); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + + int numDev = btOpenCLUtils::getNumDevices(g_cxMainContext); + if (!numDev) + { + btAssert(0); + exit(0);//this is just a demo, exit now + } + + g_cdDevice = btOpenCLUtils::getDevice(g_cxMainContext,0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + btOpenCLDeviceInfo clInfo; + btOpenCLUtils::getDeviceInfo(g_cdDevice,clInfo); + btOpenCLUtils::printDeviceInfo(g_cdDevice); + + // create a command-queue + g_cqCommandQue = clCreateCommandQueue(g_cxMainContext, g_cdDevice, 0, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); +} diff --git a/Demos/OpenCLClothDemo/clstuff.h b/Demos/OpenCLClothDemo/clstuff.h new file mode 100644 index 0000000..83b0bbc --- /dev/null +++ b/Demos/OpenCLClothDemo/clstuff.h @@ -0,0 +1,11 @@ +#ifndef __CLSTUFF_HDR__ +#define __CLSTUFF_HDR__ + + + + +// OpenCL initialization. +// Takes an optional GL context which, if passed, will create an interop-enabled CL context. +void initCL( void* glContext = 0, void* glDC = 0 ); + +#endif //__CLSTUFF_HDR__ \ No newline at end of file diff --git a/Demos/OpenCLClothDemo/clstuff.hpp b/Demos/OpenCLClothDemo/clstuff.hpp new file mode 100644 index 0000000..09f6313 --- /dev/null +++ b/Demos/OpenCLClothDemo/clstuff.hpp @@ -0,0 +1,10 @@ +#ifndef __CLSTUFF_HDR__ +#define __CLSTUFF_HDR__ + + + + + +void initCL(void); + +#endif //__CLSTUFF_HDR__ \ No newline at end of file diff --git a/Demos/OpenCLClothDemo/fragment.glsl b/Demos/OpenCLClothDemo/fragment.glsl new file mode 100644 index 0000000..6a265d3 --- /dev/null +++ b/Demos/OpenCLClothDemo/fragment.glsl @@ -0,0 +1,7 @@ +uniform sampler2D tex; + +void main() +{ + vec4 color = texture2D(tex,gl_TexCoord[0].st); + gl_FragColor = color; +} \ No newline at end of file diff --git a/Demos/OpenCLClothDemo/gl_win.cpp b/Demos/OpenCLClothDemo/gl_win.cpp new file mode 100644 index 0000000..b1143ff --- /dev/null +++ b/Demos/OpenCLClothDemo/gl_win.cpp @@ -0,0 +1,268 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2008 Advanced Micro Devices + +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 "clstuff.h" +#include "gl_win.h" + +#include +#include +#include +#include + + +//#ifndef _WIN32 && !defined(__APPLE__) +//#include +//#endif //!_WIN32 + + + +static GLuint vbo = 0; + +#ifdef _WIN32 +#include +#endif + + +static unsigned int windowWidth = 1280; +static unsigned int windowHeight = 1024; + +// mouse controls +int mouseOldX; +int mouseOldY; +int mouseButtons = 0; + +float rotateX; +float rotateY; + +float translateZ; +float translateX; +float translateY; + +static GLuint glProgram; + + +void doFlags(); + + +void render( void) +{ + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); +// glDisable ( GL_CULL_FACE ); + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + + glTranslatef( translateX, translateY, translateZ ); + glRotatef( rotateX, 0.5f , 0.0f, 0.0f ); + glRotatef( rotateY, 0.0f, 0.5f, 0.0f ); + +// glDisable (GL_BLEND); + + doFlags(); + // TODO: + //glBindBuffer(GL_ARRAY_BUFFER, vbo); + //glVertexPointer(4, GL_FLOAT, 0, NULL); + //glEnableClientState(GL_VERTEX_ARRAY); + + //glDrawArrays(GL_POINTS, 0, 4*4); + +// glDisableClientState(GL_VERTEX_ARRAY); + // glBindBuffer(GL_ARRAY_BUFFER, 0); + + +// glUseProgram(0); +} + +static void initGL(void) +{ + //glClearColor( 0.05f, 0.0f, 0.1f, 0.1f ); + glClearColor( 0.0f, 0.45f, 0.45f, 1.f); + +#if 0 + GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; + GLfloat mat_shininess[] = { 50.0f }; + GLfloat light_position[] = { + -10.f, + 5.f, + -1.f, + 1.0f }; + + glEnable ( GL_COLOR_MATERIAL ); + glShadeModel( GL_SMOOTH ); + glEnable( GL_LINE_SMOOTH ); + + + glMaterialfv( GL_FRONT, GL_SPECULAR, mat_specular ); + glMaterialfv( GL_FRONT, GL_SHININESS, mat_shininess ); + glLightfv( GL_LIGHT0, GL_POSITION, light_position ); + + //glEnable( GL_LIGHTING ); + //glEnable( GL_LIGHT0 ); // Switch on and crashes! + glEnable( GL_DEPTH_TEST ); +#endif +#if 0 + + + glEnable ( GL_COLOR_MATERIAL ); + glShadeModel( GL_SMOOTH ); + glEnable( GL_LINE_SMOOTH ); + + glMaterialfv( GL_FRONT, GL_SPECULAR, mat_specular ); + glMaterialfv( GL_FRONT, GL_SHININESS, mat_shininess ); + glLightfv( GL_LIGHT0, GL_POSITION, light_position ); + + glEnable( GL_LIGHTING ); + glEnable( GL_LIGHT0 ); + glEnable( GL_DEPTH_TEST ); +#endif + rotateX = 0; + rotateY = 30; + translateX = 0.0f; + translateY = -30.0f; + translateZ = -120.0; +} + +void display(void) +{ + render(); + + glutSwapBuffers(); + glutPostRedisplay(); +} + +void keyboard( unsigned char key, int /*x*/, int /*y*/) +{ + switch( key) { + case('q') : +#ifdef _WIN32 + case VK_ESCAPE: +#endif //_WIN32 + exit(0); + break; + case('a'): + translateY += 0.1f; + break; + case('z'): + translateY -= 0.1f; + break; + case('d'): + translateX += 0.1f; + break; + case('s'): + translateX -= 0.1f; + break; + case('f'): + translateZ += 0.1f; + break; + case('g'): + translateZ -= 0.1f; + break; + } +} + +void mouse(int button, int state, int x, int y) +{ + if (state == GLUT_DOWN) { + mouseButtons |= 1< +#endif + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#include +#else + + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#endif //_WINDOWS +#endif //APPLE + + +#include + +void goGL(void); +void preInitGL(int argc, char ** argv); + +//int getVBO( std::string, int size ); + +#endif //__GL_WIN_HDR__ diff --git a/Demos/OpenCLClothDemo/gl_win.hpp b/Demos/OpenCLClothDemo/gl_win.hpp new file mode 100644 index 0000000..e7d3f93 --- /dev/null +++ b/Demos/OpenCLClothDemo/gl_win.hpp @@ -0,0 +1,34 @@ +#ifndef __GL_WIN_HDR__ +#define __GL_WIN_HDR__ + +#ifdef _WIN32//for glut.h +#include +#endif + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#include +#else + + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#endif //_WINDOWS +#endif //APPLE + + +#include + +void goGL(void); +void preInitGL(int argc, char ** argv); + +int getVBO( std::string, int size ); + +#endif //__GL_WIN_HDR__ diff --git a/Demos/OpenCLClothDemo/shaders.cl b/Demos/OpenCLClothDemo/shaders.cl new file mode 100644 index 0000000..27e2d21 --- /dev/null +++ b/Demos/OpenCLClothDemo/shaders.cl @@ -0,0 +1,535 @@ +#pragma OPENCL EXTENSION cl_amd_printf : enable + +#define float3 float4 +#define uint3 uint4 + +#define PARTICLE_RADIUS 0.05; + +#define width 1280 +#define height 1024 + +#define B 0 +#define T height +#define L 0 +#define R width + +#define shiftNumber 4 +#define shiftMask 0xF +#define shiftValue 16.0f +#define stride 4 + +#define screenWidth1 width +#define screenHeight1 height +#define halfScreenWidth1 screenWidth1/2 +#define halfScreenHeight1 screenHeight1/2 +#define screenWidth1SubOne (screenWidth1-1) +#define screenHeight1SubOne (screenHeight1-1) +#define stride screenWidth1 +#define screenPixelNumber screenWidth1*screenHeight1 +#define depthBufferSize screenPixelNumber*depthComplexity + +#define WGS 1 + +//--------------------------------------------------------------- + +struct __VSSpriteOut +{ + float4 position; + float4 particlePosition; +}; + +typedef struct __VSSpriteout VSSpriteOut; + +struct __GSSpriteOut +{ + float4 position; + float2 textureUV; +// float4 viewSpacePosition; +// float4 particlePosition; +}; + +typedef struct __GSSpriteout GSSpriteOut; + +//------------------------------------------------------------------------------ + +__constant float4 g_positions[4] = +{ + (float4)(-1.0f, 1.0f, 0.0f, 0.0f), + (float4)( 1.0f, 1.0f, 0.0f, 0.0f), + (float4)( -1.0f, -1.0f, 0.0f, 0.0f), + (float4)( 1.0f, -1.0f, 0.0f, 0.0f) +}; + +__constant float2 g_texcoords[4] = +{ + (float2)(0.0f,0.0f), + (float2)(1.0f,0.0f), + (float2)(0.0f,1.0f), + (float2)(1.0f,1.0f) +}; + +//------------------------------------------------------------------------------ + +void copyMatrix( + float matrix[16], + __constant float matrix0[16]) +{ + uint i; + + for (i = 0; i < 16; i++) { + matrix[i] = matrix0[i]; + } +} + +void matrixMulLoopBody( + uint i, + float matrix[16], + __constant float matrix0[16], + __constant float matrix1[16]) +{ + matrix[i] = 0.0f; + matrix[i] += matrix0[(i%4) + (0*4)] * matrix1[(0) + ((i/4)*4)]; + matrix[i] += matrix0[(i%4) + (1*4)] * matrix1[(1) + ((i/4)*4)]; + matrix[i] += matrix0[(i%4) + (2*4)] * matrix1[(2) + ((i/4)*4)]; + matrix[i] += matrix0[(i%4) + (3*4)] * matrix1[(3) + ((i/4)*4)]; +} + +void matrixMul( + float matrix[16], + __constant float matrix0[16], + __constant float matrix1[16]) +{ + matrixMulLoopBody(0, matrix, matrix0, matrix1); + matrixMulLoopBody(1, matrix, matrix0, matrix1); + matrixMulLoopBody(2, matrix, matrix0, matrix1); + matrixMulLoopBody(3, matrix, matrix0, matrix1); + matrixMulLoopBody(4, matrix, matrix0, matrix1); + matrixMulLoopBody(5, matrix, matrix0, matrix1); + matrixMulLoopBody(6, matrix, matrix0, matrix1); + matrixMulLoopBody(7, matrix, matrix0, matrix1); + matrixMulLoopBody(8, matrix, matrix0, matrix1); + matrixMulLoopBody(9, matrix, matrix0, matrix1); + matrixMulLoopBody(10, matrix, matrix0, matrix1); + matrixMulLoopBody(11, matrix, matrix0, matrix1); + matrixMulLoopBody(12, matrix, matrix0, matrix1); + matrixMulLoopBody(13, matrix, matrix0, matrix1); + matrixMulLoopBody(14, matrix, matrix0, matrix1); + matrixMulLoopBody(15, matrix, matrix0, matrix1); +} + +float4 matrixVectorMul(float matrix[16], float4 vector) +{ + float4 result; + + result.x = matrix[0]*vector.x + matrix[4+0]*vector.y + matrix[8+0]*vector.z + matrix[12+0]*vector.w; + result.y = matrix[1]*vector.x + matrix[4+1]*vector.y + matrix[8+1]*vector.z + matrix[12+1]*vector.w; + result.z = matrix[2]*vector.x + matrix[4+2]*vector.y + matrix[8+2]*vector.z + matrix[12+2]*vector.w; + result.w = matrix[3]*vector.x + matrix[4+3]*vector.y + matrix[8+3]*vector.z + matrix[12+3]*vector.w; + + return result; +} + +float3 matrixVector3Mul(__constant float matrix[9], float3 vector) +{ + float3 result; + + result.x = matrix[0]*vector.x + matrix[3+0]*vector.y + matrix[6+0]*vector.z; + result.y = matrix[1]*vector.x + matrix[3+1]*vector.y + matrix[6+1]*vector.z; + result.z = matrix[2]*vector.x + matrix[3+2]*vector.y + matrix[6+2]*vector.z; + + return result; +} + +//------------------------------------------------------------------------------ + +//#define DEVICE_CPU 1 +#if defined(DEVICE_CPU) +void printMatrix(char * name, __constant float matrix[16]) +{ + printf("%s[0] = %f, %f, %f, %f\n", name, matrix[0], matrix[1], matrix[2], matrix[3]); + printf("%s[1] = %f, %f, %f, %f\n", name, matrix[4], matrix[5], matrix[6], matrix[7]); + printf("%s[2] = %f, %f, %f, %f\n", name, matrix[8], matrix[9], matrix[10], matrix[11]); + printf("%s[3] = %f, %f, %f, %f\n", name, matrix[12], matrix[13], matrix[14], matrix[15]); +} +#endif + +#if 1 +__kernel void vertexShader( + __constant float modelview[16], + __constant float projection[16], + __global float4 * inputPrimitives, + __global float4 * outputPrimitives) +{ + float matrix[16]; + float4 gl_Vertex; + float4 gl_Position; + + uint id = get_global_id(0); + + gl_Vertex = inputPrimitives[id]; + + // gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex + matrixMul(matrix, projection, modelview); + + gl_Position = matrixVectorMul(matrix, gl_Vertex); + + outputPrimitives[id] = gl_Position; +} + +#else + +__kernel void vertexShader( + __constant float modelview[16], + __constant float projection[16], + __global float4 * inputPrimitives, + __global float4 * outputPrimitives) +{ + uint id = get_global_id(0); + + outputPrimitives[id] = inputPrimitives[id]; +} + +#endif + +//----------------------------------------------------------------------------------- + +__kernel void +clearImage( + __write_only image2d_t image, + float4 color) +{ + + int2 coords = (int2)(get_global_id(0), get_global_id(1)); + write_imagef(image, coords, color); +} + +// OpenGL viewport transformation +// The site http://research.cs.queensu.ca/~jstewart/454/notes/pipeline/ +// contains a description of this process +void +viewportTransform(float4 v, __constant int4 viewport[1], float2 * output) +{ + int4 vp = viewport[0]; + *output + = 0.5f * + (float2)(v.x+1,v.y+1) * + (float2)((vp.s2-vp.s0) + vp.s0, + (vp.s3-vp.s1) + vp.s1); +} + +#define PARTICLE_WIDTH 32.0f +#define PARTICLE_HEIGHT 32.0f + +// Unoptimized triangle rasterizer function +// Details of the algorithm can be found here: +// http://www.devmaster.net/forums/showthread.php?t=1884 +// +void +rasterizerUnOpt( + __global struct __GSSpriteOut * outputPrimitives, +// __global float4 * outputPrimitives, + __constant int4 viewport[1], + __write_only image2d_t screen, + __read_only image2d_t particle, + uint v1Offset, + uint v2Offset, + uint v3Offset, + __global float4 * debugOut1) +{ + sampler_t sampler = + CLK_NORMALIZED_COORDS_TRUE | CLK_ADDRESS_CLAMP | CLK_FILTER_NEAREST; + + uint id = get_global_id(0); + + struct __GSSpriteOut output; + float2 v1, v2, v3; + float2 uv1, uv2, uv3; + + output = outputPrimitives[id*4+v1Offset]; + uv1 = output.textureUV; + viewportTransform(output.position, viewport, &v1); + + output = outputPrimitives[id*4+v2Offset]; + uv2 = output.textureUV; + viewportTransform(output.position, viewport, &v2); + + output = outputPrimitives[id*4+v3Offset]; + uv3 = output.textureUV; + viewportTransform(output.position, viewport, &v3); + + // Bounding rectangle + int2 min_ = convert_int2(min(v1, min(v2, v3))); + int2 max_ = convert_int2(max(v1, max(v2, v3))); + + // naive bi-linear interploation for texture coords, note this is + // broken with respect to OpenGL and needs to be fixed for the + // general case. + float p1x = v2.x - v1.x; + float p1y = v2.y - v1.y; + + float p2x = v3.x - v1.x; + float p2y = v3.y - v1.y; + + // Scan through bounding rectangle + for(int y = min_.y; y < max_.y; y++) { + for(int x = min_.x; x < max_.x; x++) { + // When all half-space functions positive, pixel is in triangle + if((v1.x - v2.x) * (y - v1.y) - (v1.y - v2.y) * (x - v1.x) > 0 && + (v2.x - v3.x) * (y - v2.y) - (v2.y - v3.y) * (x - v2.x) > 0 && + (v3.x - v1.x) * (y - v3.y) - (v3.y - v1.y) * (x - v3.x) > 0) { + + float px = x - v1.x; + float py = y - v1.y; + + write_imagef( + screen, + (int2)(x,y), + // texel); + (float4)(1.0f,1.0f,1.0f,1.0f)); + } + } + } +} + +// Optimized rasterizer function +// Details of the algorithm can be found here: +// http://www.devmaster.net/forums/showthread.php?t=1884 +// +// Currently has a bug, still work in progess +__kernel void +rasterizerXX( + __global float4 * outputPrimitives, + __write_only image2d_t screen, + __global float4 * debugOut1, + __global int2 * debugOut2) +{ + uint id = get_global_id(0); + +// printf("ras\n"); + + float4 v1 = outputPrimitives[id*4+0]; + float4 v2 = outputPrimitives[id*4+1]; + float4 v3 = outputPrimitives[id*4+2]; + + float y1 = 0.5f* (v1.y+1) * (T - B) + B; + float y2 = 0.5f* (v2.y+1) * (T - B) + B; + float y3 = 0.5f* (v3.y+1) * (T - B) + B; + + float x1 = 0.5f * (v1.x+1) * (R - L) + L; + float x2 = 0.5f * (v2.x+1) * (R - L) + L; + float x3 = 0.5f * (v3.x+1) * (R - L) + L; + + const int Y1 = convert_int(shiftValue * y1); + const int Y2 = convert_int(shiftValue * y2); + const int Y3 = convert_int(shiftValue * y3); + + const int X1 = convert_int(shiftValue * x1); + const int X2 = convert_int(shiftValue * x2); + const int X3 = convert_int(shiftValue * x3); + + debugOut1[id*4+0] = v1; + debugOut1[id*4+1] = v2; + debugOut1[id*4+2] = v3; + + debugOut2[id*3+0] = (int2)(X1, Y1); + debugOut2[id*3+1] = (int2)(X2, Y2); + debugOut2[id*3+2] = (int2)(X3, Y3); + + // Deltas + const int DX12 = X1 - X2; + const int DX23 = X2 - X3; + const int DX31 = X3 - X1; + + const int DY12 = Y1 - Y2; + const int DY23 = Y2 - Y3; + const int DY31 = Y3 - Y1; + + // Fixed-point deltas + const int FDX12 = DX12 << shiftNumber; + const int FDX23 = DX23 << shiftNumber; + const int FDX31 = DX31 << shiftNumber; + + const int FDY12 = DY12 << shiftNumber; + const int FDY23 = DY23 << shiftNumber; + const int FDY31 = DY31 << shiftNumber; + + // Bounding rectangle + int minx = (min(X1, min(X2, X3)) + shiftMask) >> shiftNumber; + //minx = max(0,minx); + + int maxx = (max(X1, min(X2, X3)) + shiftMask) >> shiftNumber; + //min(maxx , screenWidth1SubOne); + + int miny = (min(Y1, min(Y2, Y3)) + shiftMask) >> shiftNumber; + //max(0,miny); + + int maxy = (max(Y1, min(Y2, Y3)) + shiftMask) >> shiftNumber; + //min(maxy , screenHeight1SubOne); + + //(char*&)colorBuffer += miny * stride; + int offset = miny * stride; + + // Half-edge constants + int C1 = DY12 * X1 - DX12 * Y1; + int C2 = DY23 * X2 - DX23 * Y2; + int C3 = DY31 * X3 - DX31 * Y3; + + // Correct for fill convention + if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++; + if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++; + if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++; + + int CY1 = C1 + DX12 * (miny << shiftNumber) - DY12 * (minx << shiftNumber); + int CY2 = C2 + DX23 * (miny << shiftNumber) - DY23 * (minx << shiftNumber); + int CY3 = C3 + DX31 * (miny << shiftNumber) - DY31 * (minx << shiftNumber); + + for(int y = miny; y < maxy; y++) { + int CX1 = CY1; + int CX2 = CY2; + int CX3 = CY3; + + debugOut2[id*3+0] = (int2)(minx, maxx); + + for(int x = minx; x < maxx; x++) { + debugOut2[id*3+0] = (int2)(CX1, CX2); + + if(CX1 > 0 && CX2 > 0 && CX3 > 0) { + debugOut2[id*3+0] = (int2)(1, 1); + write_imagef( + screen, + (int2)(x,y), + (float4)(1.0f,1.0f,1.0f,1.0f)); + } + + CX1 -= FDY12; + CX2 -= FDY23; + CX3 -= FDY31; + } + + CY1 += FDX12; + CY2 += FDX23; + CY3 += FDX31; + + //(char*&)colorBuffer += stride; + offset += stride; + } +} + +//------------------------------------------------------------------------------ + +void geometryShader( + __constant float modelview[16], + __constant float projection[16], + __constant float inverseView[9], + __constant int4 viewport[1], + __local struct __VSSpriteOut * vsOutputPrimitives, + __global struct __GSSpriteOut * outputPrimitives, +// __global float4 * outputPrimitives, + __write_only image2d_t screen, + __read_only image2d_t particle, + __global float4 * debugOut1, + __global int * debugOut2) +{ + float2 texcoords[4] = + { + (float2)(0.0f,0.0f), + (float2)(1.0f,0.0f), + (float2)(0.0f,1.0f), + (float2)(1.0f,1.0f) + }; + + float matrix[16]; + + uint id = get_global_id(0); + uint lid = get_local_id(0); + + float4 vsPosition = vsOutputPrimitives[lid].position; + + matrixMul(matrix, projection, modelview); + // + // Emit two new triangles + // + for (uint i = 0; i<4; i++) { + float3 position = g_positions[i] * PARTICLE_RADIUS; + position = matrixVector3Mul(inverseView, position) + vsPosition; + float3 particlePosition = + matrixVector3Mul( + inverseView, + (float4)(0.0f,0.0f,0.0f,0.0f)) + vsPosition; // world space + + // Compute view space position + position.w = 1.0f; + position = matrixVectorMul(matrix, position); + + //perspective division + position /= position.w; + + struct __GSSpriteOut output; + output.position = position; + //output.textureUV = g_texcoords[i]; + output.textureUV = texcoords[i]; + outputPrimitives[id*4+i] = output; + } + + // Render QUAD - Triangle 1 + rasterizerUnOpt( + outputPrimitives, + viewport, + screen, + particle, + 0, + 1, + 2, + debugOut1); + + // Render QUAD - Triangle 2 + rasterizerUnOpt( + outputPrimitives, + viewport, + screen, + particle, + 2, + 1, + 3, + debugOut1); +} + +__kernel void vertexShaderSprite( + __constant float modelview[16], + __constant float projection[16], + __constant float inverseView[9], + __constant int4 viewport[1], + __local struct __VSSpriteOut * vsOutputPrimitives, + __global float4 * inputPrimitives, + __global struct __GSSpriteOut * outputPrimitives, +// __global float4 * outputPrimitives, + __write_only image2d_t screen, + __read_only image2d_t particle, + __global float4 * debugOut1, + __global int * debugOut2) +{ + float matrix[16]; + + uint id = get_global_id(0); + uint lid = get_local_id(0); + + // gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex + matrixMul(matrix, projection, modelview); + + float4 position = inputPrimitives[id]; + vsOutputPrimitives[lid].position = position; + vsOutputPrimitives[lid].particlePosition = + matrixVectorMul(matrix, position); + + geometryShader( + modelview, + projection, + inverseView, + viewport, + vsOutputPrimitives, + outputPrimitives, + screen, + particle, + debugOut1, + debugOut2); +} \ No newline at end of file diff --git a/Demos/OpenCLClothDemo/vertex.glsl b/Demos/OpenCLClothDemo/vertex.glsl new file mode 100644 index 0000000..5169830 --- /dev/null +++ b/Demos/OpenCLClothDemo/vertex.glsl @@ -0,0 +1,7 @@ +void main() +{ + //gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; + + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_Position = gl_Vertex; +} \ No newline at end of file diff --git a/Demos/OpenGL/CMakeLists.txt b/Demos/OpenGL/CMakeLists.txt new file mode 100644 index 0000000..067b099 --- /dev/null +++ b/Demos/OpenGL/CMakeLists.txt @@ -0,0 +1,67 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + + +# You shouldn't have to modify anything below this line +######################################################## + + + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Extras/ConvexHull +) + + +ADD_LIBRARY(OpenGLSupport + GLDebugFont.cpp + GLDebugFont.h + GL_DialogDynamicsWorld.cpp + GL_DialogDynamicsWorld.h + GL_DialogWindow.cpp + GL_DialogWindow.h + GL_ShapeDrawer.cpp + GL_ShapeDrawer.h + GL_Simplex1to4.cpp + GL_Simplex1to4.h + GLDebugDrawer.cpp + GLDebugDrawer.h + + RenderTexture.cpp + RenderTexture.h + DemoApplication.cpp + DemoApplication.h + + GlutDemoApplication.cpp + GlutDemoApplication.h + GlutStuff.cpp + GlutStuff.h + + stb_image.cpp + stb_image.h + + Win32DemoApplication.cpp + Win32DemoApplication.h +) + + +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(OpenGLSupport BulletDynamics BulletCollision ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}) +ENDIF (BUILD_SHARED_LIBS) + +#INSTALL of other files requires CMake 2.6 +IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF(INSTALL_EXTRA_LIBS) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS OpenGLSupport DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS OpenGLSupport DESTINATION lib) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include FILES_MATCHING PATTERN "*.h") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (INSTALL_EXTRA_LIBS) +ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) diff --git a/Demos/OpenGL/DebugCastResult.h b/Demos/OpenGL/DebugCastResult.h new file mode 100644 index 0000000..ef3befe --- /dev/null +++ b/Demos/OpenGL/DebugCastResult.h @@ -0,0 +1,88 @@ +/* +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 DEBUG_CAST_RESULT_H +#define DEBUG_CAST_RESULT_H + +#include "BulletCollision/NarrowPhaseCollision/btConvexCast.h" +#include "LinearMath/btTransform.h" +#include "GL_ShapeDrawer.h" +#include "GlutStuff.h" +#ifdef WIN32 +#include +#endif +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#else +#include +#endif +struct btDebugCastResult : public btConvexCast::CastResult +{ + + btTransform m_fromTrans; + const btPolyhedralConvexShape* m_shape; + btVector3 m_linVel; + btVector3 m_angVel; + GL_ShapeDrawer* m_shapeDrawer; + + btDebugCastResult(const btTransform& fromTrans,const btPolyhedralConvexShape* shape, + const btVector3& linVel,const btVector3& angVel,GL_ShapeDrawer* drawer) + :m_fromTrans(fromTrans), + m_shape(shape), + m_linVel(linVel), + m_angVel(angVel), + m_shapeDrawer(drawer) + { + } + + virtual void drawCoordSystem(const btTransform& tr) + { + btScalar m[16]; + tr.getOpenGLMatrix(m); + glPushMatrix(); + btglLoadMatrix(m); + glBegin(GL_LINES); + btglColor3(1, 0, 0); + btglVertex3(0, 0, 0); + btglVertex3(1, 0, 0); + btglColor3(0, 1, 0); + btglVertex3(0, 0, 0); + btglVertex3(0, 1, 0); + btglColor3(0, 0, 1); + btglVertex3(0, 0, 0); + btglVertex3(0, 0, 1); + glEnd(); + glPopMatrix(); + } + + virtual void DebugDraw(btScalar fraction) + { + btVector3 worldBoundsMin(-1000,-1000,-1000); + btVector3 worldBoundsMax(1000,1000,1000); + + + btScalar m[16]; + btTransform hitTrans; + btTransformUtil::integrateTransform(m_fromTrans,m_linVel,m_angVel,fraction,hitTrans); + hitTrans.getOpenGLMatrix(m); + if (m_shapeDrawer) + m_shapeDrawer->drawOpenGL(m,m_shape,btVector3(1,0,0),btIDebugDraw::DBG_NoDebug,worldBoundsMin,worldBoundsMax); + } +}; + + +#endif //DEBUG_CAST_RESULT_H diff --git a/Demos/OpenGL/DemoApplication.cpp b/Demos/OpenGL/DemoApplication.cpp new file mode 100644 index 0000000..8b07cf9 --- /dev/null +++ b/Demos/OpenGL/DemoApplication.cpp @@ -0,0 +1,1383 @@ +/* +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 "DemoApplication.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletDynamics/Dynamics/btDynamicsWorld.h" + +#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"//picking +#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"//picking + +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/CollisionShapes/btUniformScalingShape.h" +#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h" +#include "GL_ShapeDrawer.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btDefaultMotionState.h" +#include "LinearMath/btSerializer.h" +#include "GLDebugFont.h" + +static bool use6Dof = false; +extern bool gDisableDeactivation; +int numObjects = 0; +const int maxNumObjects = 16384; +btTransform startTransforms[maxNumObjects]; +btCollisionShape* gShapePtr[maxNumObjects];//1 rigidbody has 1 shape (no re-use of shapes) +#define SHOW_NUM_DEEP_PENETRATIONS 1 + +extern int gNumClampedCcdMotions; + +#ifdef SHOW_NUM_DEEP_PENETRATIONS +extern int gNumDeepPenetrationChecks; + +extern int gNumSplitImpulseRecoveries; +extern int gNumGjkChecks; +extern int gNumAlignedAllocs; +extern int gNumAlignedFree; +extern int gTotalBytesAlignedAllocs; + +#endif // + + +DemoApplication::DemoApplication() +//see btIDebugDraw.h for modes +: +m_dynamicsWorld(0), +m_pickConstraint(0), +m_shootBoxShape(0), +m_cameraDistance(15.0), +m_debugMode(0), +m_ele(20.f), +m_azi(0.f), +m_cameraPosition(0.f,0.f,0.f), +m_cameraTargetPosition(0.f,0.f,0.f), +m_mouseOldX(0), +m_mouseOldY(0), +m_mouseButtons(0), +m_modifierKeys(0), +m_scaleBottom(0.5f), +m_scaleFactor(2.f), +m_cameraUp(0,1,0), +m_forwardAxis(2), +m_zoomStepSize(0.4), +m_glutScreenWidth(0), +m_glutScreenHeight(0), +m_frustumZNear(1.f), +m_frustumZFar(10000.f), +m_ortho(0), +m_ShootBoxInitialSpeed(40.f), +m_stepping(true), +m_singleStep(false), +m_idle(false), + +m_enableshadows(false), +m_sundirection(btVector3(1,-2,1)*1000), +m_defaultContactProcessingThreshold(BT_LARGE_FLOAT) +{ +#ifndef BT_NO_PROFILE + m_profileIterator = CProfileManager::Get_Iterator(); +#endif //BT_NO_PROFILE + + m_shapeDrawer = new GL_ShapeDrawer (); + m_shapeDrawer->enableTexture(true); + m_enableshadows = false; +} + + + +DemoApplication::~DemoApplication() +{ +#ifndef BT_NO_PROFILE + CProfileManager::Release_Iterator(m_profileIterator); +#endif //BT_NO_PROFILE + + if (m_shootBoxShape) + delete m_shootBoxShape; + + if (m_shapeDrawer) + delete m_shapeDrawer; +} + + +void DemoApplication::overrideGLShapeDrawer (GL_ShapeDrawer* shapeDrawer) +{ + shapeDrawer->enableTexture (m_shapeDrawer->hasTextureEnabled()); + delete m_shapeDrawer; + m_shapeDrawer = shapeDrawer; +} + +void DemoApplication::myinit(void) +{ + + 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 )}; + /* light_position is NOT default value */ + GLfloat light_position0[] = { btScalar(1.0), btScalar(10.0), btScalar(1.0), btScalar(0.0 )}; + GLfloat light_position1[] = { btScalar(-1.0), btScalar(-10.0), btScalar(-1.0), btScalar(0.0) }; + + glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT0, GL_POSITION, light_position0); + + glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT1, GL_POSITION, light_position1); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + + + glShadeModel(GL_SMOOTH); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + glClearColor(btScalar(0.7),btScalar(0.7),btScalar(0.7),btScalar(0)); + + // glEnable(GL_CULL_FACE); + // glCullFace(GL_BACK); +} + + +void DemoApplication::setCameraDistance(float dist) +{ + m_cameraDistance = dist; +} + +float DemoApplication::getCameraDistance() +{ + return m_cameraDistance; +} + + + +void DemoApplication::toggleIdle() { + if (m_idle) { + m_idle = false; + } + else { + m_idle = true; + } +} + + + + +void DemoApplication::updateCamera() { + + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + btScalar rele = m_ele * btScalar(0.01745329251994329547);// rads per deg + btScalar razi = m_azi * btScalar(0.01745329251994329547);// rads per deg + + + btQuaternion rot(m_cameraUp,razi); + + + btVector3 eyePos(0,0,0); + eyePos[m_forwardAxis] = -m_cameraDistance; + + btVector3 forward(eyePos[0],eyePos[1],eyePos[2]); + if (forward.length2() < SIMD_EPSILON) + { + forward.setValue(1.f,0.f,0.f); + } + btVector3 right = m_cameraUp.cross(forward); + btQuaternion roll(right,-rele); + + eyePos = btMatrix3x3(rot) * btMatrix3x3(roll) * eyePos; + + m_cameraPosition[0] = eyePos.getX(); + m_cameraPosition[1] = eyePos.getY(); + m_cameraPosition[2] = eyePos.getZ(); + m_cameraPosition += m_cameraTargetPosition; + + if (m_glutScreenWidth == 0 && m_glutScreenHeight == 0) + return; + + btScalar aspect; + btVector3 extents; + + aspect = m_glutScreenWidth / (btScalar)m_glutScreenHeight; + extents.setValue(aspect * 1.0f, 1.0f,0); + + + if (m_ortho) + { + // reset matrix + glLoadIdentity(); + + + extents *= m_cameraDistance; + btVector3 lower = m_cameraTargetPosition - extents; + btVector3 upper = m_cameraTargetPosition + extents; + //gluOrtho2D(lower.x, upper.x, lower.y, upper.y); + glOrtho(lower.getX(), upper.getX(), lower.getY(), upper.getY(),-1000,1000); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + //glTranslatef(100,210,0); + } else + { +// glFrustum (-aspect, aspect, -1.0, 1.0, 1.0, 10000.0); + glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(m_cameraPosition[0], m_cameraPosition[1], m_cameraPosition[2], + m_cameraTargetPosition[0], m_cameraTargetPosition[1], m_cameraTargetPosition[2], + m_cameraUp.getX(),m_cameraUp.getY(),m_cameraUp.getZ()); + } + +} + + + +const float STEPSIZE = 5; + +void DemoApplication::stepLeft() +{ + m_azi -= STEPSIZE; if (m_azi < 0) m_azi += 360; updateCamera(); +} +void DemoApplication::stepRight() +{ + m_azi += STEPSIZE; if (m_azi >= 360) m_azi -= 360; updateCamera(); +} +void DemoApplication::stepFront() +{ + m_ele += STEPSIZE; if (m_ele >= 360) m_ele -= 360; updateCamera(); +} +void DemoApplication::stepBack() +{ + m_ele -= STEPSIZE; if (m_ele < 0) m_ele += 360; updateCamera(); +} +void DemoApplication::zoomIn() +{ + m_cameraDistance -= btScalar(m_zoomStepSize); updateCamera(); + if (m_cameraDistance < btScalar(0.1)) + m_cameraDistance = btScalar(0.1); + +} +void DemoApplication::zoomOut() +{ + m_cameraDistance += btScalar(m_zoomStepSize); updateCamera(); + +} + + + + + + + + + + +void DemoApplication::reshape(int w, int h) +{ + GLDebugResetFont(w,h); + + m_glutScreenWidth = w; + m_glutScreenHeight = h; + + glViewport(0, 0, w, h); + updateCamera(); +} + + + +void DemoApplication::keyboardCallback(unsigned char key, int x, int y) +{ + (void)x; + (void)y; + + m_lastKey = 0; + +#ifndef BT_NO_PROFILE + if (key >= 0x31 && key <= 0x39) + { + int child = key-0x31; + m_profileIterator->Enter_Child(child); + } + if (key==0x30) + { + m_profileIterator->Enter_Parent(); + } +#endif //BT_NO_PROFILE + + switch (key) + { + case 'q' : +#ifdef BT_USE_FREEGLUT + //return from glutMainLoop(), detect memory leaks etc. + glutLeaveMainLoop(); +#else + exit(0); +#endif + break; + + case 'l' : stepLeft(); break; + case 'r' : stepRight(); break; + case 'f' : stepFront(); break; + case 'b' : stepBack(); break; + case 'z' : zoomIn(); break; + case 'x' : zoomOut(); break; + case 'i' : toggleIdle(); break; + case 'g' : m_enableshadows=!m_enableshadows;break; + case 'u' : m_shapeDrawer->enableTexture(!m_shapeDrawer->enableTexture(false));break; + case 'h': + if (m_debugMode & btIDebugDraw::DBG_NoHelpText) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_NoHelpText); + else + m_debugMode |= btIDebugDraw::DBG_NoHelpText; + break; + + case 'w': + if (m_debugMode & btIDebugDraw::DBG_DrawWireframe) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawWireframe); + else + m_debugMode |= btIDebugDraw::DBG_DrawWireframe; + break; + + case 'p': + if (m_debugMode & btIDebugDraw::DBG_ProfileTimings) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_ProfileTimings); + else + m_debugMode |= btIDebugDraw::DBG_ProfileTimings; + break; + + case '=': + { + int maxSerializeBufferSize = 1024*1024*5; + btDefaultSerializer* serializer = new btDefaultSerializer(maxSerializeBufferSize); + //serializer->setSerializationFlags(BT_SERIALIZE_NO_DUPLICATE_ASSERT); + m_dynamicsWorld->serialize(serializer); + FILE* f2 = fopen("testFile.bullet","wb"); + fwrite(serializer->getBufferPointer(),serializer->getCurrentBufferSize(),1,f2); + fclose(f2); + delete serializer; + break; + + } + + case 'm': + if (m_debugMode & btIDebugDraw::DBG_EnableSatComparison) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_EnableSatComparison); + else + m_debugMode |= btIDebugDraw::DBG_EnableSatComparison; + break; + + case 'n': + if (m_debugMode & btIDebugDraw::DBG_DisableBulletLCP) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DisableBulletLCP); + else + m_debugMode |= btIDebugDraw::DBG_DisableBulletLCP; + break; + case 'N': + if (m_debugMode & btIDebugDraw::DBG_DrawNormals) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawNormals); + else + m_debugMode |= btIDebugDraw::DBG_DrawNormals; + break; + + case 't' : + if (m_debugMode & btIDebugDraw::DBG_DrawText) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawText); + else + m_debugMode |= btIDebugDraw::DBG_DrawText; + break; + case 'y': + if (m_debugMode & btIDebugDraw::DBG_DrawFeaturesText) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawFeaturesText); + else + m_debugMode |= btIDebugDraw::DBG_DrawFeaturesText; + break; + case 'a': + if (m_debugMode & btIDebugDraw::DBG_DrawAabb) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawAabb); + else + m_debugMode |= btIDebugDraw::DBG_DrawAabb; + break; + case 'c' : + if (m_debugMode & btIDebugDraw::DBG_DrawContactPoints) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawContactPoints); + else + m_debugMode |= btIDebugDraw::DBG_DrawContactPoints; + break; + case 'C' : + if (m_debugMode & btIDebugDraw::DBG_DrawConstraints) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawConstraints); + else + m_debugMode |= btIDebugDraw::DBG_DrawConstraints; + break; + case 'L' : + if (m_debugMode & btIDebugDraw::DBG_DrawConstraintLimits) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawConstraintLimits); + else + m_debugMode |= btIDebugDraw::DBG_DrawConstraintLimits; + break; + + case 'd' : + if (m_debugMode & btIDebugDraw::DBG_NoDeactivation) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_NoDeactivation); + else + m_debugMode |= btIDebugDraw::DBG_NoDeactivation; + if (m_debugMode & btIDebugDraw::DBG_NoDeactivation) + { + gDisableDeactivation = true; + } else + { + gDisableDeactivation = false; + } + break; + + + + + case 'o' : + { + m_ortho = !m_ortho;//m_stepping = !m_stepping; + break; + } + case 's' : clientMoveAndDisplay(); break; + // case ' ' : newRandom(); break; + case ' ': + clientResetScene(); + break; + case '1': + { + if (m_debugMode & btIDebugDraw::DBG_EnableCCD) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_EnableCCD); + else + m_debugMode |= btIDebugDraw::DBG_EnableCCD; + break; + } + + case '.': + { + shootBox(getRayTo(x,y));//getCameraTargetPosition()); + break; + } + + case '+': + { + m_ShootBoxInitialSpeed += 10.f; + break; + } + case '-': + { + m_ShootBoxInitialSpeed -= 10.f; + break; + } + + default: + // std::cout << "unused key : " << key << std::endl; + break; + } + + if (getDynamicsWorld() && getDynamicsWorld()->getDebugDrawer()) + getDynamicsWorld()->getDebugDrawer()->setDebugMode(m_debugMode); + + + +} + +void DemoApplication::setDebugMode(int mode) +{ + m_debugMode = mode; + if (getDynamicsWorld() && getDynamicsWorld()->getDebugDrawer()) + getDynamicsWorld()->getDebugDrawer()->setDebugMode(mode); +} + + + + + + +void DemoApplication::moveAndDisplay() +{ + if (!m_idle) + clientMoveAndDisplay(); + else + displayCallback(); +} + + + + +void DemoApplication::displayCallback() +{ +} + +#define NUM_SPHERES_ON_DIAGONAL 9 + +void DemoApplication::setShootBoxShape () +{ + if (!m_shootBoxShape) + { + btBoxShape* box = new btBoxShape(btVector3(.5f,.5f,.5f)); + box->initializePolyhedralFeatures(); + m_shootBoxShape = box; + } +} + +void DemoApplication::shootBox(const btVector3& destination) +{ + + if (m_dynamicsWorld) + { + float mass = 1.f; + btTransform startTransform; + startTransform.setIdentity(); + btVector3 camPos = getCameraPosition(); + startTransform.setOrigin(camPos); + + setShootBoxShape (); + + btRigidBody* body = this->localCreateRigidBody(mass, startTransform,m_shootBoxShape); + body->setLinearFactor(btVector3(1,1,1)); + //body->setRestitution(1); + + btVector3 linVel(destination[0]-camPos[0],destination[1]-camPos[1],destination[2]-camPos[2]); + linVel.normalize(); + linVel*=m_ShootBoxInitialSpeed; + + body->getWorldTransform().setOrigin(camPos); + body->getWorldTransform().setRotation(btQuaternion(0,0,0,1)); + body->setLinearVelocity(linVel); + body->setAngularVelocity(btVector3(0,0,0)); + body->setCcdMotionThreshold(0.5); + body->setCcdSweptSphereRadius(0.9f); +// printf("shootBox uid=%d\n", body->getBroadphaseHandle()->getUid()); +// printf("camPos=%f,%f,%f\n",camPos.getX(),camPos.getY(),camPos.getZ()); +// printf("destination=%f,%f,%f\n",destination.getX(),destination.getY(),destination.getZ()); + + } +} + + +int gPickingConstraintId = 0; +btVector3 gOldPickingPos; +btVector3 gHitPos(-1,-1,-1); +float gOldPickingDist = 0.f; +btRigidBody* pickedBody = 0;//for deactivation state + + +btVector3 DemoApplication::getRayTo(int x,int y) +{ + + + + if (m_ortho) + { + + btScalar aspect; + btVector3 extents; + aspect = m_glutScreenWidth / (btScalar)m_glutScreenHeight; + extents.setValue(aspect * 1.0f, 1.0f,0); + + extents *= m_cameraDistance; + btVector3 lower = m_cameraTargetPosition - extents; + btVector3 upper = m_cameraTargetPosition + extents; + + btScalar u = x / btScalar(m_glutScreenWidth); + btScalar v = (m_glutScreenHeight - y) / btScalar(m_glutScreenHeight); + + btVector3 p(0,0,0); + p.setValue((1.0f - u) * lower.getX() + u * upper.getX(),(1.0f - v) * lower.getY() + v * upper.getY(),m_cameraTargetPosition.getZ()); + return p; + } + + 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 rayFrom = getCameraPosition(); + btVector3 rayForward = (getCameraTargetPosition()-getCameraPosition()); + rayForward.normalize(); + float farPlane = 10000.f; + rayForward*= farPlane; + + btVector3 rightOffset; + btVector3 vertical = m_cameraUp; + + btVector3 hor; + hor = rayForward.cross(vertical); + hor.normalize(); + vertical = hor.cross(rayForward); + vertical.normalize(); + + float tanfov = tanf(0.5f*fov); + + + hor *= 2.f * farPlane * tanfov; + vertical *= 2.f * farPlane * tanfov; + + btScalar aspect; + + aspect = m_glutScreenWidth / (btScalar)m_glutScreenHeight; + + hor*=aspect; + + + btVector3 rayToCenter = rayFrom + rayForward; + btVector3 dHor = hor * 1.f/float(m_glutScreenWidth); + btVector3 dVert = vertical * 1.f/float(m_glutScreenHeight); + + + btVector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical; + rayTo += btScalar(x) * dHor; + rayTo -= btScalar(y) * dVert; + return rayTo; +} + +btScalar mousePickClamping = 30.f; + + +void DemoApplication::mouseFunc(int button, int state, int x, int y) +{ + if (state == 0) + { + m_mouseButtons |= 1<rayTest(m_cameraPosition,rayTo,rayCallback); + if (rayCallback.hasHit()) + { + + btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject); + if (body) + { + body->setActivationState(ACTIVE_TAG); + btVector3 impulse = rayTo; + impulse.normalize(); + float impulseStrength = 10.f; + impulse *= impulseStrength; + btVector3 relPos = rayCallback.m_hitPointWorld - body->getCenterOfMassPosition(); + body->applyImpulse(impulse,relPos); + } + } + } +#endif + + + + } else + { + + } + break; + } + case 0: + { + if (state==0) + { + + + //add a point to point constraint for picking + if (m_dynamicsWorld) + { + + btVector3 rayFrom; + if (m_ortho) + { + rayFrom = rayTo; + rayFrom.setZ(-100.f); + } else + { + rayFrom = m_cameraPosition; + } + + btCollisionWorld::ClosestRayResultCallback rayCallback(rayFrom,rayTo); + m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback); + if (rayCallback.hasHit()) + { + + + btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject); + if (body) + { + //other exclusions? + if (!(body->isStaticObject() || body->isKinematicObject())) + { + pickedBody = body; + pickedBody->setActivationState(DISABLE_DEACTIVATION); + + + btVector3 pickPos = rayCallback.m_hitPointWorld; + //printf("pickPos=%f,%f,%f\n",pickPos.getX(),pickPos.getY(),pickPos.getZ()); + + + btVector3 localPivot = body->getCenterOfMassTransform().inverse() * pickPos; + + + + + + + if (use6Dof) + { + btTransform tr; + tr.setIdentity(); + tr.setOrigin(localPivot); + btGeneric6DofConstraint* dof6 = new btGeneric6DofConstraint(*body, tr,false); + dof6->setLinearLowerLimit(btVector3(0,0,0)); + dof6->setLinearUpperLimit(btVector3(0,0,0)); + dof6->setAngularLowerLimit(btVector3(0,0,0)); + dof6->setAngularUpperLimit(btVector3(0,0,0)); + + m_dynamicsWorld->addConstraint(dof6); + m_pickConstraint = dof6; + + dof6->setParam(BT_CONSTRAINT_STOP_CFM,0.8,0); + dof6->setParam(BT_CONSTRAINT_STOP_CFM,0.8,1); + dof6->setParam(BT_CONSTRAINT_STOP_CFM,0.8,2); + dof6->setParam(BT_CONSTRAINT_STOP_CFM,0.8,3); + dof6->setParam(BT_CONSTRAINT_STOP_CFM,0.8,4); + dof6->setParam(BT_CONSTRAINT_STOP_CFM,0.8,5); + + dof6->setParam(BT_CONSTRAINT_STOP_ERP,0.1,0); + dof6->setParam(BT_CONSTRAINT_STOP_ERP,0.1,1); + dof6->setParam(BT_CONSTRAINT_STOP_ERP,0.1,2); + dof6->setParam(BT_CONSTRAINT_STOP_ERP,0.1,3); + dof6->setParam(BT_CONSTRAINT_STOP_ERP,0.1,4); + dof6->setParam(BT_CONSTRAINT_STOP_ERP,0.1,5); + } else + { + btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*body,localPivot); + m_dynamicsWorld->addConstraint(p2p); + m_pickConstraint = p2p; + p2p->m_setting.m_impulseClamp = mousePickClamping; + //very weak constraint for picking + p2p->m_setting.m_tau = 0.001f; +/* + p2p->setParam(BT_CONSTRAINT_CFM,0.8,0); + p2p->setParam(BT_CONSTRAINT_CFM,0.8,1); + p2p->setParam(BT_CONSTRAINT_CFM,0.8,2); + p2p->setParam(BT_CONSTRAINT_ERP,0.1,0); + p2p->setParam(BT_CONSTRAINT_ERP,0.1,1); + p2p->setParam(BT_CONSTRAINT_ERP,0.1,2); + */ + + + } + use6Dof = !use6Dof; + + //save mouse position for dragging + gOldPickingPos = rayTo; + gHitPos = pickPos; + + gOldPickingDist = (pickPos-rayFrom).length(); + } + } + } + } + + } else + { + removePickingConstraint(); + } + + break; + + } + default: + { + } + } + +} + +void DemoApplication::removePickingConstraint() +{ + if (m_pickConstraint && m_dynamicsWorld) + { + m_dynamicsWorld->removeConstraint(m_pickConstraint); + delete m_pickConstraint; + //printf("removed constraint %i",gPickingConstraintId); + m_pickConstraint = 0; + pickedBody->forceActivationState(ACTIVE_TAG); + pickedBody->setDeactivationTime( 0.f ); + pickedBody = 0; + } +} + +void DemoApplication::mouseMotionFunc(int x,int y) +{ + + if (m_pickConstraint) + { + //move the constraint pivot + + if (m_pickConstraint->getConstraintType() == D6_CONSTRAINT_TYPE) + { + btGeneric6DofConstraint* pickCon = static_cast(m_pickConstraint); + if (pickCon) + { + //keep it at the same picking distance + + btVector3 newRayTo = getRayTo(x,y); + btVector3 rayFrom; + btVector3 oldPivotInB = pickCon->getFrameOffsetA().getOrigin(); + + btVector3 newPivotB; + if (m_ortho) + { + newPivotB = oldPivotInB; + newPivotB.setX(newRayTo.getX()); + newPivotB.setY(newRayTo.getY()); + } else + { + rayFrom = m_cameraPosition; + btVector3 dir = newRayTo-rayFrom; + dir.normalize(); + dir *= gOldPickingDist; + + newPivotB = rayFrom + dir; + } + pickCon->getFrameOffsetA().setOrigin(newPivotB); + } + + } else + { + btPoint2PointConstraint* pickCon = static_cast(m_pickConstraint); + if (pickCon) + { + //keep it at the same picking distance + + btVector3 newRayTo = getRayTo(x,y); + btVector3 rayFrom; + btVector3 oldPivotInB = pickCon->getPivotInB(); + btVector3 newPivotB; + if (m_ortho) + { + newPivotB = oldPivotInB; + newPivotB.setX(newRayTo.getX()); + newPivotB.setY(newRayTo.getY()); + } else + { + rayFrom = m_cameraPosition; + btVector3 dir = newRayTo-rayFrom; + dir.normalize(); + dir *= gOldPickingDist; + + newPivotB = rayFrom + dir; + } + pickCon->setPivotB(newPivotB); + } + } + } + + float dx, dy; + dx = btScalar(x) - m_mouseOldX; + dy = btScalar(y) - m_mouseOldY; + + + ///only if ALT key is pressed (Maya style) + if (m_modifierKeys& BT_ACTIVE_ALT) + { + if(m_mouseButtons & 2) + { + btVector3 hor = getRayTo(0,0)-getRayTo(1,0); + btVector3 vert = getRayTo(0,0)-getRayTo(0,1); + btScalar multiplierX = btScalar(0.001); + btScalar multiplierY = btScalar(0.001); + if (m_ortho) + { + multiplierX = 1; + multiplierY = 1; + } + + + m_cameraTargetPosition += hor* dx * multiplierX; + m_cameraTargetPosition += vert* dy * multiplierY; + } + + if(m_mouseButtons & (2 << 2) && m_mouseButtons & 1) + { + } + else if(m_mouseButtons & 1) + { + m_azi += dx * btScalar(0.2); + m_azi = fmodf(m_azi, btScalar(360.f)); + m_ele += dy * btScalar(0.2); + m_ele = fmodf(m_ele, btScalar(180.f)); + } + else if(m_mouseButtons & 4) + { + m_cameraDistance -= dy * btScalar(0.02f); + if (m_cameraDistancegetShapeType() != 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// + + m_dynamicsWorld->addRigidBody(body); + + return body; +} + +//See http://www.lighthouse3d.com/opengl/glut/index.php?bmpfontortho +void DemoApplication::setOrthographicProjection() +{ + + // switch to projection mode + glMatrixMode(GL_PROJECTION); + + // save previous matrix which contains the + //settings for the perspective projection + glPushMatrix(); + // reset matrix + glLoadIdentity(); + // set a 2D orthographic projection + gluOrtho2D(0, m_glutScreenWidth, 0, m_glutScreenHeight); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // invert the y axis, down is positive + glScalef(1, -1, 1); + // mover the origin from the bottom left corner + // to the upper left corner + glTranslatef(btScalar(0), btScalar(-m_glutScreenHeight), btScalar(0)); + +} + +void DemoApplication::resetPerspectiveProjection() +{ + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + updateCamera(); +} + + + + +extern CProfileIterator * m_profileIterator; + +void DemoApplication::displayProfileString(int xOffset,int yStart,char* message) +{ + glRasterPos3f(btScalar(xOffset),btScalar(yStart),btScalar(0)); + GLDebugDrawString(xOffset,yStart,message); +} + + +void DemoApplication::showProfileInfo(int& xOffset,int& yStart, int yIncr) +{ +#ifndef BT_NO_PROFILE + + static double time_since_reset = 0.f; + if (!m_idle) + { + time_since_reset = CProfileManager::Get_Time_Since_Reset(); + } + + + { + //recompute profiling data, and store profile strings + + char blockTime[128]; + + double totalTime = 0; + + int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset(); + + m_profileIterator->First(); + + double parent_time = m_profileIterator->Is_Root() ? time_since_reset : m_profileIterator->Get_Current_Parent_Total_Time(); + + { + sprintf(blockTime,"--- Profiling: %s (total running time: %.3f ms) ---", m_profileIterator->Get_Current_Parent_Name(), parent_time ); + displayProfileString(xOffset,yStart,blockTime); + yStart += yIncr; + sprintf(blockTime,"press (1,2...) to display child timings, or 0 for parent" ); + displayProfileString(xOffset,yStart,blockTime); + yStart += yIncr; + + } + + + double accumulated_time = 0.f; + + for (int i = 0; !m_profileIterator->Is_Done(); m_profileIterator->Next()) + { + double current_total_time = m_profileIterator->Get_Current_Total_Time(); + accumulated_time += current_total_time; + double fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f; + + sprintf(blockTime,"%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)", + ++i, m_profileIterator->Get_Current_Name(), fraction, + (current_total_time / (double)frames_since_reset),m_profileIterator->Get_Current_Total_Calls()); + displayProfileString(xOffset,yStart,blockTime); + yStart += yIncr; + totalTime += current_total_time; + } + + sprintf(blockTime,"%s (%.3f %%) :: %.3f ms", "Unaccounted", + // (min(0, time_since_reset - totalTime) / time_since_reset) * 100); + parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time); + + displayProfileString(xOffset,yStart,blockTime); + yStart += yIncr; + + + + sprintf(blockTime,"-------------------------------------------------"); + displayProfileString(xOffset,yStart,blockTime); + yStart += yIncr; + + } +#endif//BT_NO_PROFILE + + + + +} + + +// +void DemoApplication::renderscene(int pass) +{ + btScalar m[16]; + btMatrix3x3 rot;rot.setIdentity(); + const int numObjects=m_dynamicsWorld->getNumCollisionObjects(); + btVector3 wireColor(1,0,0); + for(int i=0;igetCollisionObjectArray()[i]; + btRigidBody* body=btRigidBody::upcast(colObj); + if(body&&body->getMotionState()) + { + btDefaultMotionState* myMotionState = (btDefaultMotionState*)body->getMotionState(); + myMotionState->m_graphicsWorldTrans.getOpenGLMatrix(m); + rot=myMotionState->m_graphicsWorldTrans.getBasis(); + } + else + { + colObj->getWorldTransform().getOpenGLMatrix(m); + rot=colObj->getWorldTransform().getBasis(); + } + btVector3 wireColor(1.f,1.0f,0.5f); //wants deactivation + if(i&1) wireColor=btVector3(0.f,0.0f,1.f); + ///color differently for active, sleeping, wantsdeactivation states + if (colObj->getActivationState() == 1) //active + { + if (i & 1) + { + wireColor += btVector3 (1.f,0.f,0.f); + } + else + { + wireColor += btVector3 (.5f,0.f,0.f); + } + } + if(colObj->getActivationState()==2) //ISLAND_SLEEPING + { + if(i&1) + { + wireColor += btVector3 (0.f,1.f, 0.f); + } + else + { + wireColor += btVector3 (0.f,0.5f,0.f); + } + } + + btVector3 aabbMin,aabbMax; + m_dynamicsWorld->getBroadphase()->getBroadphaseAabb(aabbMin,aabbMax); + + aabbMin-=btVector3(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); + aabbMax+=btVector3(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); +// printf("aabbMin=(%f,%f,%f)\n",aabbMin.getX(),aabbMin.getY(),aabbMin.getZ()); +// printf("aabbMax=(%f,%f,%f)\n",aabbMax.getX(),aabbMax.getY(),aabbMax.getZ()); +// m_dynamicsWorld->getDebugDrawer()->drawAabb(aabbMin,aabbMax,btVector3(1,1,1)); + + + if (!(getDebugMode()& btIDebugDraw::DBG_DrawWireframe)) + { + switch(pass) + { + case 0: m_shapeDrawer->drawOpenGL(m,colObj->getCollisionShape(),wireColor,getDebugMode(),aabbMin,aabbMax);break; + case 1: m_shapeDrawer->drawShadow(m,m_sundirection*rot,colObj->getCollisionShape(),aabbMin,aabbMax);break; + case 2: m_shapeDrawer->drawOpenGL(m,colObj->getCollisionShape(),wireColor*btScalar(0.3),0,aabbMin,aabbMax);break; + } + } + } +} + +// +void DemoApplication::renderme() +{ + myinit(); + + updateCamera(); + + if (m_dynamicsWorld) + { + if(m_enableshadows) + { + glClear(GL_STENCIL_BUFFER_BIT); + glEnable(GL_CULL_FACE); + renderscene(0); + + glDisable(GL_LIGHTING); + glDepthMask(GL_FALSE); + glDepthFunc(GL_LEQUAL); + glEnable(GL_STENCIL_TEST); + glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); + glStencilFunc(GL_ALWAYS,1,0xFFFFFFFFL); + glFrontFace(GL_CCW); + glStencilOp(GL_KEEP,GL_KEEP,GL_INCR); + renderscene(1); + glFrontFace(GL_CW); + glStencilOp(GL_KEEP,GL_KEEP,GL_DECR); + renderscene(1); + glFrontFace(GL_CCW); + + glPolygonMode(GL_FRONT,GL_FILL); + glPolygonMode(GL_BACK,GL_FILL); + glShadeModel(GL_SMOOTH); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_LIGHTING); + glDepthMask(GL_TRUE); + glCullFace(GL_BACK); + glFrontFace(GL_CCW); + glEnable(GL_CULL_FACE); + glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); + + glDepthFunc(GL_LEQUAL); + glStencilFunc( GL_NOTEQUAL, 0, 0xFFFFFFFFL ); + glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); + glDisable(GL_LIGHTING); + renderscene(2); + glEnable(GL_LIGHTING); + glDepthFunc(GL_LESS); + glDisable(GL_STENCIL_TEST); + glDisable(GL_CULL_FACE); + } + else + { + glDisable(GL_CULL_FACE); + renderscene(0); + } + + int xOffset = 10; + int yStart = 20; + int yIncr = 20; + + + glDisable(GL_LIGHTING); + glColor3f(0, 0, 0); + + if ((m_debugMode & btIDebugDraw::DBG_NoHelpText)==0) + { + setOrthographicProjection(); + + showProfileInfo(xOffset,yStart,yIncr); + +#ifdef USE_QUICKPROF + + + if ( getDebugMode() & btIDebugDraw::DBG_ProfileTimings) + { + static int counter = 0; + counter++; + std::map::iterator iter; + for (iter = btProfiler::mProfileBlocks.begin(); iter != btProfiler::mProfileBlocks.end(); ++iter) + { + char blockTime[128]; + sprintf(blockTime, "%s: %lf",&((*iter).first[0]),btProfiler::getBlockTime((*iter).first, btProfiler::BLOCK_CYCLE_SECONDS));//BLOCK_TOTAL_PERCENT)); + glRasterPos3f(xOffset,yStart,0); + GLDebugDrawString(BMF_GetFont(BMF_kHelvetica10),blockTime); + yStart += yIncr; + + } + + } +#endif //USE_QUICKPROF + + + + + resetPerspectiveProjection(); + } + + glDisable(GL_LIGHTING); + + + } + + updateCamera(); + +} + +#include "BulletCollision/BroadphaseCollision/btAxisSweep3.h" + + +void DemoApplication::clientResetScene() +{ + removePickingConstraint(); + +#ifdef SHOW_NUM_DEEP_PENETRATIONS + gNumDeepPenetrationChecks = 0; + gNumGjkChecks = 0; +#endif //SHOW_NUM_DEEP_PENETRATIONS + + gNumClampedCcdMotions = 0; + int numObjects = 0; + int i; + + if (m_dynamicsWorld) + { + int numConstraints = m_dynamicsWorld->getNumConstraints(); + for (i=0;igetConstraint(0)->setEnabled(true); + } + numObjects = m_dynamicsWorld->getNumCollisionObjects(); + + ///create a copy of the array, not a reference! + btCollisionObjectArray copyArray = m_dynamicsWorld->getCollisionObjectArray(); + + + + + for (i=0;igetMotionState()) + { + btDefaultMotionState* myMotionState = (btDefaultMotionState*)body->getMotionState(); + myMotionState->m_graphicsWorldTrans = myMotionState->m_startWorldTrans; + body->setCenterOfMassTransform( myMotionState->m_graphicsWorldTrans ); + colObj->setInterpolationWorldTransform( myMotionState->m_startWorldTrans ); + colObj->forceActivationState(ACTIVE_TAG); + colObj->activate(); + colObj->setDeactivationTime(0); + //colObj->setActivationState(WANTS_DEACTIVATION); + } + //removed cached contact points (this is not necessary if all objects have been removed from the dynamics world) + if (m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()) + m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(colObj->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher()); + + btRigidBody* body = btRigidBody::upcast(colObj); + if (body && !body->isStaticObject()) + { + btRigidBody::upcast(colObj)->setLinearVelocity(btVector3(0,0,0)); + btRigidBody::upcast(colObj)->setAngularVelocity(btVector3(0,0,0)); + } + } + + } + + ///reset some internal cached data in the broadphase + m_dynamicsWorld->getBroadphase()->resetPool(getDynamicsWorld()->getDispatcher()); + m_dynamicsWorld->getConstraintSolver()->reset(); + + } + +} diff --git a/Demos/OpenGL/DemoApplication.h b/Demos/OpenGL/DemoApplication.h new file mode 100644 index 0000000..85a4f69 --- /dev/null +++ b/Demos/OpenGL/DemoApplication.h @@ -0,0 +1,258 @@ +/* +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 DEMO_APPLICATION_H +#define DEMO_APPLICATION_H + + +#include "GlutStuff.h" +#include "GL_ShapeDrawer.h" + +#include +#include +#include + + +#include "LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btAlignedObjectArray.h" + +class btCollisionShape; +class btDynamicsWorld; +class btRigidBody; +class btTypedConstraint; + + + +class DemoApplication +{ +protected: + void displayProfileString(int xOffset,int yStart,char* message); + class CProfileIterator* m_profileIterator; + + protected: +#ifdef USE_BT_CLOCK + btClock m_clock; +#endif //USE_BT_CLOCK + + ///this is the most important class + btDynamicsWorld* m_dynamicsWorld; + + ///constraint for mouse picking + btTypedConstraint* m_pickConstraint; + + virtual void removePickingConstraint(); + + btCollisionShape* m_shootBoxShape; + + float m_cameraDistance; + int m_debugMode; + + float m_ele; + float m_azi; + btVector3 m_cameraPosition; + btVector3 m_cameraTargetPosition;//look at + + int m_mouseOldX; + int m_mouseOldY; + int m_mouseButtons; +public: + int m_modifierKeys; +protected: + + float m_scaleBottom; + float m_scaleFactor; + btVector3 m_cameraUp; + int m_forwardAxis; + float m_zoomStepSize; + + int m_glutScreenWidth; + int m_glutScreenHeight; + + float m_frustumZNear; + float m_frustumZFar; + + int m_ortho; + + float m_ShootBoxInitialSpeed; + + bool m_stepping; + bool m_singleStep; + bool m_idle; + int m_lastKey; + + void showProfileInfo(int& xOffset,int& yStart, int yIncr); + void renderscene(int pass); + + GL_ShapeDrawer* m_shapeDrawer; + bool m_enableshadows; + btVector3 m_sundirection; + btScalar m_defaultContactProcessingThreshold; + +public: + + DemoApplication(); + + virtual ~DemoApplication(); + + btDynamicsWorld* getDynamicsWorld() + { + return m_dynamicsWorld; + } + + virtual void initPhysics() = 0; + + virtual void setDrawClusters(bool drawClusters) + { + + } + + void overrideGLShapeDrawer (GL_ShapeDrawer* shapeDrawer); + + void setOrthographicProjection(); + void resetPerspectiveProjection(); + + bool setTexturing(bool enable) { return(m_shapeDrawer->enableTexture(enable)); } + bool setShadows(bool enable) { bool p=m_enableshadows;m_enableshadows=enable;return(p); } + bool getTexturing() const + { + return m_shapeDrawer->hasTextureEnabled(); + } + bool getShadows() const + { + return m_enableshadows; + } + + + int getDebugMode() + { + return m_debugMode ; + } + + void setDebugMode(int mode); + + void setAzi(float azi) + { + m_azi = azi; + } + + void setCameraUp(const btVector3& camUp) + { + m_cameraUp = camUp; + } + void setCameraForwardAxis(int axis) + { + m_forwardAxis = axis; + } + + virtual void myinit(); + + void toggleIdle(); + + virtual void updateCamera(); + + btVector3 getCameraPosition() + { + return m_cameraPosition; + } + btVector3 getCameraTargetPosition() + { + return m_cameraTargetPosition; + } + + btScalar getDeltaTimeMicroseconds() + { +#ifdef USE_BT_CLOCK + btScalar dt = (btScalar)m_clock.getTimeMicroseconds(); + m_clock.reset(); + return dt; +#else + return btScalar(16666.); +#endif + } + void setFrustumZPlanes(float zNear, float zFar) + { + m_frustumZNear = zNear; + m_frustumZFar = zFar; + } + + ///glut callbacks + + float getCameraDistance(); + void setCameraDistance(float dist); + void moveAndDisplay(); + + virtual void clientMoveAndDisplay() = 0; + + virtual void clientResetScene(); + + ///Demo functions + virtual void setShootBoxShape (); + virtual void shootBox(const btVector3& destination); + + + btVector3 getRayTo(int x,int y); + + btRigidBody* localCreateRigidBody(float mass, const btTransform& startTransform,btCollisionShape* shape); + + ///callback methods by glut + + virtual void keyboardCallback(unsigned char key, int x, int y); + + virtual void keyboardUpCallback(unsigned char key, int x, int y) {} + + virtual void specialKeyboard(int key, int x, int y){} + + virtual void specialKeyboardUp(int key, int x, int y){} + + virtual void reshape(int w, int h); + + virtual void mouseFunc(int button, int state, int x, int y); + + virtual void mouseMotionFunc(int x,int y); + + virtual void displayCallback(); + + virtual void renderme(); + + virtual void swapBuffers() = 0; + + virtual void updateModifierKeys() = 0; + + void stepLeft(); + void stepRight(); + void stepFront(); + void stepBack(); + void zoomIn(); + void zoomOut(); + + bool isIdle() const + { + return m_idle; + } + + void setIdle(bool idle) + { + m_idle = idle; + } + + +}; + +#endif //DEMO_APPLICATION_H + + diff --git a/Demos/OpenGL/GLDebugDrawer.cpp b/Demos/OpenGL/GLDebugDrawer.cpp new file mode 100644 index 0000000..79758df --- /dev/null +++ b/Demos/OpenGL/GLDebugDrawer.cpp @@ -0,0 +1,139 @@ + +#include "GLDebugDrawer.h" +#include "GLDebugFont.h" +#include "GlutStuff.h" + + + +#include //printf debugging +GLDebugDrawer::GLDebugDrawer() +:m_debugMode(0) +{ + +} + +void GLDebugDrawer::drawLine(const btVector3& from,const btVector3& to,const btVector3& fromColor, const btVector3& toColor) +{ + glBegin(GL_LINES); + glColor3f(fromColor.getX(), fromColor.getY(), fromColor.getZ()); + glVertex3d(from.getX(), from.getY(), from.getZ()); + glColor3f(toColor.getX(), toColor.getY(), toColor.getZ()); + glVertex3d(to.getX(), to.getY(), to.getZ()); + glEnd(); +} + +void GLDebugDrawer::drawLine(const btVector3& from,const btVector3& to,const btVector3& color) +{ + drawLine(from,to,color,color); +} + +void GLDebugDrawer::drawSphere (const btVector3& p, btScalar radius, const btVector3& color) +{ + glColor4f (color.getX(), color.getY(), color.getZ(), btScalar(1.0f)); + glPushMatrix (); + glTranslatef (p.getX(), p.getY(), p.getZ()); + + int lats = 5; + int longs = 5; + + int i, j; + for(i = 0; i <= lats; i++) { + btScalar lat0 = SIMD_PI * (-btScalar(0.5) + (btScalar) (i - 1) / lats); + btScalar z0 = radius*sin(lat0); + btScalar zr0 = radius*cos(lat0); + + btScalar lat1 = SIMD_PI * (-btScalar(0.5) + (btScalar) i / lats); + btScalar z1 = radius*sin(lat1); + btScalar zr1 = radius*cos(lat1); + + glBegin(GL_QUAD_STRIP); + for(j = 0; j <= longs; j++) { + btScalar lng = 2 * SIMD_PI * (btScalar) (j - 1) / longs; + btScalar x = cos(lng); + btScalar y = sin(lng); + + glNormal3f(x * zr0, y * zr0, z0); + glVertex3f(x * zr0, y * zr0, z0); + glNormal3f(x * zr1, y * zr1, z1); + glVertex3f(x * zr1, y * zr1, z1); + } + glEnd(); + } + + glPopMatrix(); +} + +void GLDebugDrawer::drawBox (const btVector3& boxMin, const btVector3& boxMax, const btVector3& color, btScalar alpha) +{ + btVector3 halfExtent = (boxMax - boxMin) * btScalar(0.5f); + btVector3 center = (boxMax + boxMin) * btScalar(0.5f); + //glEnable(GL_BLEND); // Turn blending On + //glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glColor4f (color.getX(), color.getY(), color.getZ(), alpha); + glPushMatrix (); + glTranslatef (center.getX(), center.getY(), center.getZ()); + glScaled(2*halfExtent[0], 2*halfExtent[1], 2*halfExtent[2]); +// glutSolidCube(1.0); + glPopMatrix (); + //glDisable(GL_BLEND); +} + +void GLDebugDrawer::drawTriangle(const btVector3& a,const btVector3& b,const btVector3& c,const btVector3& color,btScalar alpha) +{ +// if (m_debugMode > 0) + { + const btVector3 n=btCross(b-a,c-a).normalized(); + glBegin(GL_TRIANGLES); + glColor4f(color.getX(), color.getY(), color.getZ(),alpha); + glNormal3d(n.getX(),n.getY(),n.getZ()); + glVertex3d(a.getX(),a.getY(),a.getZ()); + glVertex3d(b.getX(),b.getY(),b.getZ()); + glVertex3d(c.getX(),c.getY(),c.getZ()); + glEnd(); + } +} + +void GLDebugDrawer::setDebugMode(int debugMode) +{ + m_debugMode = debugMode; + +} + +void GLDebugDrawer::draw3dText(const btVector3& location,const char* textString) +{ + glRasterPos3f(location.x(), location.y(), location.z()); + //BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),textString); +} + +void GLDebugDrawer::reportErrorWarning(const char* warningString) +{ + printf("%s\n",warningString); +} + +void GLDebugDrawer::drawContactPoint(const btVector3& pointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color) +{ + + { + btVector3 to=pointOnB+normalOnB*1;//distance; + const btVector3&from = pointOnB; + glColor4f(color.getX(), color.getY(), color.getZ(),1.f); + //glColor4f(0,0,0,1.f); + glBegin(GL_LINES); + glVertex3d(from.getX(), from.getY(), from.getZ()); + glVertex3d(to.getX(), to.getY(), to.getZ()); + glEnd(); + + +// glRasterPos3f(from.x(), from.y(), from.z()); +// char buf[12]; +// sprintf(buf," %d",lifeTime); + //BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); + + + } +} + + + + + diff --git a/Demos/OpenGL/GLDebugDrawer.h b/Demos/OpenGL/GLDebugDrawer.h new file mode 100644 index 0000000..2a05405 --- /dev/null +++ b/Demos/OpenGL/GLDebugDrawer.h @@ -0,0 +1,38 @@ +#ifndef GL_DEBUG_DRAWER_H +#define GL_DEBUG_DRAWER_H + +#include "LinearMath/btIDebugDraw.h" + + + +class GLDebugDrawer : public btIDebugDraw +{ + int m_debugMode; + +public: + + GLDebugDrawer(); + + + virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& fromColor, const btVector3& toColor); + + virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color); + + virtual void drawSphere (const btVector3& p, btScalar radius, const btVector3& color); + virtual void drawBox (const btVector3& boxMin, const btVector3& boxMax, const btVector3& color, btScalar alpha); + + virtual void drawTriangle(const btVector3& a,const btVector3& b,const btVector3& c,const btVector3& color,btScalar alpha); + + virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color); + + virtual void reportErrorWarning(const char* warningString); + + virtual void draw3dText(const btVector3& location,const char* textString); + + virtual void setDebugMode(int debugMode); + + virtual int getDebugMode() const { return m_debugMode;} + +}; + +#endif//GL_DEBUG_DRAWER_H diff --git a/Demos/OpenGL/GLDebugFont.cpp b/Demos/OpenGL/GLDebugFont.cpp new file mode 100644 index 0000000..b629731 --- /dev/null +++ b/Demos/OpenGL/GLDebugFont.cpp @@ -0,0 +1,1000 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "GLDebugFont.h" + + +#ifdef _WIN32//for glut.h +#include +#endif + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#if (defined (TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || (defined (TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR) +#import +#define glOrtho glOrthof +#else +#include +#include +#include +#endif +#else + + + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif +#endif + +#include +#include //for memset + +extern unsigned char sFontData[]; +static bool sTexturesInitialized = false; + +static GLuint sTexture = -1; +static int sScreenWidth = -1; +static int sScreenHeight = -1; + + +void GLDebugResetFont(int screenWidth,int screenHeight) +{ + + if ((sScreenWidth == screenWidth) && (sScreenHeight == screenHeight)) + return; + + sScreenWidth = screenWidth; + sScreenHeight = screenHeight; + + if (!sTexturesInitialized) + { + sTexturesInitialized = true; + glGenTextures(1, &sTexture); + glBindTexture(GL_TEXTURE_2D, sTexture); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, 3, 256 , 256 , 0, GL_RGB, GL_UNSIGNED_BYTE, &sFontData[0]); + } + + printf("generating font at resolution %d,%d\n",screenWidth,screenHeight); + +} + +#define USE_ARRAYS 1 + +void GLDebugDrawStringInternal(int x,int y,const char* string, const btVector3& rgb) +{ + GLDebugDrawStringInternal(x,y,string,rgb,true,10); +} + +void GLDebugDrawStringInternal(int x,int y,const char* string, const btVector3& rgb, bool enableBlend, int spacing) +{ + + if (!sTexturesInitialized) + { + GLDebugResetFont(sScreenWidth,sScreenHeight); + } + if (strlen(string)) + { + + glColor4f(rgb.getX(),rgb.getY(),rgb.getZ(),1.f); + float cx; + float cy; + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); + + glEnable(GL_TEXTURE_2D); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + glDepthFunc (GL_LEQUAL); + + if (enableBlend) + { + glEnable(GL_BLEND); + } else + { + glDisable(GL_BLEND); + } + glEnable (GL_DEPTH_TEST); + glBindTexture(GL_TEXTURE_2D, sTexture); + glDisable(GL_DEPTH_TEST); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glOrtho(0,sScreenWidth,0,sScreenHeight,-1,1); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glTranslatef(btScalar(x),btScalar(sScreenHeight - y),btScalar(0)); + +#if USE_ARRAYS + + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState (GL_TEXTURE_COORD_ARRAY); +#endif + + GLfloat verts[] ={ + 0.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, + 0.f,0.f,0.f + }; + + GLfloat uv_texcoords[] = { + 0,0, + 0,0, + 0,0, + 0,0 + }; + verts[0] = 0; verts[1] = 0; verts[2] = 0; + verts[3] = 16-1; verts[4] = 0; verts[5] = 0; + verts[6] = 16-1; verts[7] = 16-1; verts[8] = 0; + verts[9] = 0; verts[10] = 16-1; verts[11] = 0; + + for (int i=0;i=0) + { + cx=float(ch%16) * btScalar(1./16.f); + cy=float(ch/16) * btScalar(1./16.f); + + uv_texcoords[0] = cx; uv_texcoords[1] = btScalar(1-cy-1./16.f); + uv_texcoords[2] = btScalar(cx+1./16.f); uv_texcoords[3] = btScalar(1-cy-1./16.f); + uv_texcoords[4] = btScalar(cx+1./16.f); uv_texcoords[5] = btScalar(1-cy); + uv_texcoords[6] = cx; uv_texcoords[7] = btScalar(1-cy); +#if USE_ARRAYS + glTexCoordPointer(2,GL_FLOAT,0,uv_texcoords); + glVertexPointer(3, GL_FLOAT, 0, verts); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +#else + glBegin(GL_QUADS); + glTexCoord2f(cx,1-cy-1./16.f); + + glVertex2i(0,0); + glTexCoord2f(cx+1./16.f,1-cy-1./16.f); + + glVertex2i(16 - 1,0); + glTexCoord2f(cx+1./16.f,1-cy); + + glVertex2i(16 - 1,16 -1); + glTexCoord2f(cx,1-cy); + + glVertex2i(0,16 -1); + glEnd(); +#endif + + glTranslatef(spacing,0,0); + } + } + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +#if 1 + glEnable(GL_DEPTH_TEST); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + glDepthFunc (GL_LEQUAL); + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glScalef(btScalar(0.025),btScalar(0.025),btScalar(0.025)); +#endif + glMatrixMode(GL_MODELVIEW); +#if USE_ARRAYS + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState (GL_TEXTURE_COORD_ARRAY); +#endif + //glDisable(GL_TEXTURE_2D); + } +} + +void GLDebugDrawString(int x,int y,const char* string) +{ + + btVector3 rgb(1,1,1); + GLDebugDrawStringInternal(x,y,string,rgb); +} + + +unsigned char sFontData[] = +{ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,145,145,145,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,213,213,213,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,103,103,103,2,2,2,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213, + 213,213,255,255,255,255,255,255,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,213,213,213,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,213,213,213,255,255,255,255,255,255,255,255,255,213,213,213,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,178,178,178,178,178,178,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,0,0,0,0,0,0,0,0,0,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,103,103,103,103,103,103,178,178,178,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,145,145,145,178,178,178,255,255,255,255,255,255,255,255,255,145,145,145,103,103,103,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,2,2,2,255,255,255,178,178,178,103,103,103,145,145,145,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,103,103,103,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,103,103,103,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255, + 255,255,145,145,145,103,103,103,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,178,178,178,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,178,178,178,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,145,145,145,255,255,255,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,103,103,103,103,103,103,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,145,145,145,178,178,178,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,103,103,103,145,145,145,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,0,0,0,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,70,70,70,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70, + 70,70,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,255,255,255,70,70, + 70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,213,213,213,255,255,255,255,255,255,0,0,0,0,0,0,70,70,70,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,103,103,103,255,255,255,213,213,213,70,70,70,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,255,255,255,246,246,246,178,178,178,246,246,246,70,70,70,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37, + 37,37,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,178,178,178,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,255,255,255,213,213, + 213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,255,255,255,255,255,255,103,103,103,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,255,255,255,103,103,103,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,178,178,178,255,255,255,37,37,37,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,255,255,255,255,255,255,145,145,145,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2,2,2,145,145,145,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255, + 255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,103,103,103,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,145,145,145,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,70,70,70,255,255,255,70,70,70,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,213,213,213,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,70,70,70,255,255,255,37,37,37,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,103,103,103,246,246,246,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,70,70,70,255,255,255,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,255,255,255,145,145,145,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,0,0,0,37,37,37,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,0,0,0,37,37,37,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,70,70,70,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,103,103,103,213,213,213,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,37,37,37,255,255,255,178,178,178,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,70,70,70,0,0,0,70,70,70,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,145,145,145,213,213,213,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,70,70,70,255,255,255,37,37,37,0,0,0,145,145,145,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,178,178,178,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,0,0,0,103,103,103,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,0,0,0,103,103,103,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255, + 255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,255,255,255,213,213,213,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,103,103,103,103,103,103,103,103,103,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,246,246,246,103,103,103,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,37,37,37,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,246,246,246,103,103,103,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,103,103,103,70,70,70,0,0,0,103,103,103,255,255, + 255,246,246,246,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,145,145,145,103,103,103,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,2,2,2,255,255,255,255,255, + 255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,178,178,178,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,255,255,255,246,246, + 246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,103,103,103,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,213,213,213,213,213,213,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,213,213,213,213,213,213,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255, + 255,255,255,255,255,213,213,213,213,213,213,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,178,178,178,213,213,213,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,103,103,103,145,145,145,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,178,178,178,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,103,103,103,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178, + 178,178,103,103,103,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,145,145,145,145,145,145,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,145,145,145,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,103,103,103,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,103,103,103,103,103,103,178,178,178,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,103,103,103,178,178,178,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,255,255,255,145,145,145,0,0,0,37,37,37,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,145,145,145,0,0,0,37,37,37,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2, + 2,2,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2,2,2,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103, + 103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,103,103,103,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,103,103,103,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,103,103,103,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,103,103,103,103,103,103,255,255,255,178,178, + 178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,103,103,103,103,103,103,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,103,103,103,103,103,103,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37, + 37,37,103,103,103,103,103,103,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,103,103,103,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246, + 246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,0,0,0,37,37,37,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,246,246,246,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,103,103,103,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,103,103, + 103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,0,0,0,103,103,103,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103, + 103,103,246,246,246,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,103,103,103,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,103,103,103,145,145,145,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,213,213,213,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,213,213,213,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,70,70,70,70,70,70,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,37,37,37,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,37,37,37,70,70,70,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,178,178,178,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,246,246,246,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,145,145,145,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,213,213,213,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,213,213,213,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,213,213,213,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246, + 246,246,255,255,255,255,255,255,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,145,145,145,178,178,178,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,178,178,178,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,246,246,246,103,103,103,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,103,103,103,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255, + 255,255,213,213,213,178,178,178,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,178,178,178,0,0,0,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,178,178,178,255,255,255,255,255,255,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,103,103,103,103,103,103,178,178,178,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,70,70,70,0,0,0,0,0,0,37,37,37,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,0,0,0,2,2,2,37,37,37,145,145,145,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255, + 255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,70,70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,145,145,145,255,255,255,103,103,103,255,255,255,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,178,178,178,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,246,246,246,0,0,0,0,0,0,246,246,246,70,70, + 70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,2,2,2,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,2,2,2,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,178,178,178,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,70,70,70,2,2,2,2,2,2,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,103,103,103,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,255,255,255,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,178,178,178,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,103,103,103,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,145,145,145,255,255,255,103,103,103,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,178,178,178,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,246,246,246,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,255,255,255,246,246,246,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,145,145,145,103,103,103,178,178,178,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,103,103,103,103,103,103,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255, + 255,255,213,213,213,0,0,0,37,37,37,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,213,213,213,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,246,246,246,70,70,70,103,103,103,246,246,246,0,0,0,213,213,213,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,103,103,103,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,103,103,103,103,103,103,255,255,255,255,255,255,246,246, + 246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,213,213,213,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,145,145,145,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,70,70,70,178,178,178,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255, + 255,255,255,255,255,0,0,0,103,103,103,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,145,145,145,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,103,103,103,103,103,103,145,145,145,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,178,178,178,103,103,103,178,178,178,255,255,255,145,145,145,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,213,213,213,213,213,213,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,213,213,213,213,213,213,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,213,213,213,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,213,213,213,213,213,213,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213, + 213,213,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,213,213,213,145,145,145,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,213,213,213,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,255,255,255,145,145,145,178,178,178,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,178,178,178,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246, + 246,246,103,103,103,103,103,103,103,103,103,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,178,178,178,255,255,255,178,178,178,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,178,178,178,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,0,0,0,178,178,178,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,0,0,0,70,70,70,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,37,37,37,178,178,178,255,255,255,37,37,37,178,178,178,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,0,0,0,70,70,70,178,178,178,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,213,213,213,103,103,103,103,103,103,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,70,70,70,0,0,0,0,0,0,37,37,37,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,103,103,103,255,255,255,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246, + 246,246,103,103,103,103,103,103,103,103,103,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,255,255,255,2,2,2,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,103,103,103,103,103,103,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255, + 255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,103,103,103,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,103,103,103,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,103,103,103,213,213,213,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,246,246,246,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,213,213,213,255,255,255,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,37,37,37,255,255,255,255,255,255,70,70,70,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,103,103,103,145,145,145,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,178,178,178,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,213,213,213,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,145,145,145,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,145,145,145,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,178,178,178,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,178,178,178,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,37,37, + 37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,246,246,246,255,255,255,145,145,145,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,213,213,213,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246, + 246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,246,246,246,178,178,178,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,103,103,103,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255, + 255,255,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,0,0,0,103,103,103,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,103,103,103,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255, + 255,255,145,145,145,103,103,103,178,178,178,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,213,213,213,255,255,255,246,246,246,2,2,2,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,103,103,103,103,103,103,178,178,178,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37, + 37,37,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,2,2,2,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,145,145,145,0,0,0,0,0,0,255,255,255,103,103, + 103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,103,103,103,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2, + 2,2,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,37,37,37,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,255,255,255,2,2,2,246,246,246,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,70,70,70,0,0,0,145,145,145,103,103, + 103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,213,213,213,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,246,246,246,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103, + 103,103,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,103,103,103,246,246,246,255,255,255,103,103,103,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,70,70,70,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,2,2,2,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,145,145,145,2,2,2,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,70,70,70,255,255,255,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213, + 213,213,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,255,255,255,255,255,255,2,2,2,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,70,70,70,0,0,0,255,255,255,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,37,37,37,0,0,0,255,255,255,37,37,37,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255, + 255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,103,103,103,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,37,37,37,0,0,0,103,103,103,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,255,255,255,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,103,103,103,103,103,103,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,246,246,246,103,103,103,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,103,103,103,103,103,103,103,103,103,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,103,103,103,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,255,255,255,246,246,246,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255, + 255,255,103,103,103,103,103,103,0,0,0,70,70,70,103,103,103,255,255,255,246,246,246,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,246,246,246,2,2,2,0,0,0,0,0,0,213,213,213,255,255,255,213,213,213,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,0,0,0,213,213,213,255,255,255,145,145,145,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,145,145,145,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,103,103,103,213,213,213,255,255,255,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255, + 255,255,255,255,255,255,255,255,2,2,2,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,178,178,178,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,213,213,213,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,213,213,213,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,213,213,213,103,103,103,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,103,103,103,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,145,145,145,0,0,0,0,0,0,37,37,37,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,178,178,178,103,103,103,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,103,103,103,145,145,145,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255, + 255,255,103,103,103,103,103,103,103,103,103,178,178,178,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,103,103,103,103,103,103,213,213,213,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,103,103,103,0,0,0,178,178,178,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,145,145,145,103,103,103,255,255,255,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,70,70,70,0,0,0,37,37,37,255,255,255,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,103,103,103,103,103,103,178,178,178,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,255,255,255,103,103,103,0,0,0,2,2,2,178,178,178,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,255,255,255,103,103,103,0,0,0,70,70,70,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,103,103,103,145,145,145,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,103,103,103,255,255,255,255,255,255,178,178,178,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255, + 255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,145,145,145,178,178,178,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,246,246,246,255,255,255,2,2,2,213,213,213,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,103,103,103,103,103,103,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,178,178,178,103,103,103,255,255,255,213,213,213,70,70,70,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,103,103,103,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,103,103,103,103,103,103,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,2,2,2,178,178,178,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,246,246,246,255,255,255,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,255,255,255,213,213,213,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,37,37,37,255,255,255,178,178,178,37,37,37,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,246,246,246,255,255,255,178,178,178,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,70,70,70,255,255,255,70,70,70,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,145,145,145,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246, + 246,246,213,213,213,0,0,0,70,70,70,255,255,255,37,37,37,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,70,70,70,255,255,255,37,37,37,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,246,246,246,103,103,103,255,255,255,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,213,213,213,255,255,255,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145, + 145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37, + 37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,2,2,2,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,246,246,246,2,2,2,103,103,103,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,246,246,246,103,103,103,103,103,103,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,213,213,213,255,255,255,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,103,103,103,103,103,103,103,103,103,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,103,103,103,103,103,103,103,103,103,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213, + 213,213,255,255,255,103,103,103,103,103,103,103,103,103,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,103,103,103,103,103,103,103,103,103,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,103,103,103,0,0,0,103,103,103,255,255,255,246,246,246,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,103,103,103,255,255,255,246,246,246,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,255,255,255,246,246, + 246,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,103,103,103,103,103,103,0,0,0,255,255,255,255,255,255,145,145,145,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,213,213,213,255,255,255,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,2,2,2,0,0,0,255,255,255,255,255,255,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,70,70,70,0,0,0,103,103,103,255,255,255,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,145,145,145,103,103,103,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,70,70,70,246,246,246,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,2,2,2,0,0,0,103,103,103,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255, + 255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,103,103,103,178,178,178,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213, + 213,213,103,103,103,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,103,103,103,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,246,246,246,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,213,213,213,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,103,103,103,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,37,37,37,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,213,213,213,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,213,213,213,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,178,178,178,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246, + 246,246,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,246,246,246,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,178,178,178,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145, + 145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,37,37,37,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,37,37,37,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,246,246,246,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37, + 37,37,255,255,255,103,103,103,103,103,103,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,103,103,103,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,213,213,213,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,213,213,213,103,103,103,103,103,103,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,246,246,246,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,178,178,178,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,246,246,246,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,246,246,246,213,213,213,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,145,145,145,213,213,213,255,255,255,255,255,255,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,178, + 178,178,0,0,0,0,0,0,213,213,213,213,213,213,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2,2,2,178,178,178,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,178,178,178,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,145,145,145,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103, + 103,103,255,255,255,178,178,178,0,0,0,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,103,103,103,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,246,246,246,255,255,255,255,255,255,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,2,2,2,178,178,178,255,255,255,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,213,213,213,37,37,37,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,213,213,213,255,255,255,37,37, + 37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,103,103,103,213,213,213,255,255,255,145,145,145,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255, + 255,255,255,255,255,145,145,145,0,0,0,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,37,37,37,103,103,103,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,145,145,145,70,70,70,2,2,2,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255, + 255,255,0,0,0,255,255,255,2,2,2,0,0,0,2,2,2,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,145,145,145,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255, + 255,255,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,2,2,2,255,255,255,145,145,145,70,70, + 70,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,2,2,2,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70, + 70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,145,145,145,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,37,37,37,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,255,255, + 255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,246,246,246,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37, + 37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,37,37,37,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,37,37,37,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0, + 0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,213,213,213,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,2,2,2,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,213,213,213,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,37,37,37,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,2,2,2,255,255,255,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,246,246,246,103,103,103,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,103,103,103,246,246,246,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,246,246,246,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,2,2,2,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,103,103,103,255,255,255,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,213,213,213,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,145,145,145,246,246,246,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,103,103,103,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,103,103,103,255,255,255,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37, + 37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,37,37,37,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,145,145,145,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,37,37,37,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,37,37,37,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,70,70,70,0,0,0,2,2,2,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,37,37,37,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,145,145,145,0,0,0,70,70,70,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,178,178,178,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0, + 0,145,145,145,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,213,213,213,145,145,145,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,70,70,70,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,255,255, + 255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,159,159,159,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,246,246,246,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,255,255,255,255,255,255,37,37,37,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,255,255,255,255,255,255,255,255, + 255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,37,37,37,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,213,213,213,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,213,213,213,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,246,246,246,0,0,0,0,0,0,213,213,213,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,213,213,213,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,178,178,178,0,0,0,0,0,0,0,0, + 0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103, + 103,103,255,255,255,37,37,37,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,246,246,246,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,178,178,178,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,178,178,178,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,2,2,2,178,178,178,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,178,178,178,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,246,246,246,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,246,246,246,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,246,246,246,246,246,246,255,255, + 255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,0,0,0,145,145, + 145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,70,70,70,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255, + 255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,145,145,145,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,145,145,145,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,213,213,213,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,178,178, + 178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,70,70,70,0,0,0,0,0,0,2,2,2,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,37,37,37,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,70,70,70,0,0,0,2,2,2,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,37,37,37,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,2,2,2,0,0,0,70,70,70,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,37,37,37,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,145,145,145,0,0,0,70,70,70,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,246,246,246,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,70,70,70,0,0,0,145,145,145,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,145,145,145,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,213,213,213,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,70,70,70,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,37,37,37,246,246,246,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,255,255,255,37,37,37,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,70,70,70,0,0,0,37,37,37,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,213,213,213,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,145,145,145,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,213,213,213,0,0,0,145,145,145,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,213,213,213,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,255,255,255,0,0,0,255,255,255,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,145,145,145,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,246,246,246,0,0,0,255,255,255,0,0,0,213,213,213,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,213,213,213,0,0,0,103,103,103,246,246,246,255,255,255,0,0,0,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178, + 178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,255,255,255,37,37,37,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,2,2,2,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,255,255,255,70,70,70,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,2,2,2,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255, + 255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,70,70,70,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,246,246,246,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,37,37,37,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,213,213,213,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,37,37,37,246,246,246,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,70,70,70,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,246,246,246,103,103,103,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,213,213,213,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,37,37,37,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,37,37,37,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37, + 37,37,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,37,37,37,255,255,255,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,246,246,246,103,103,103,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,246,246,246,103,103,103,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,246,246,246,103,103,103,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,178,178,178,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,255,255,255,246,246,246,246,246,246,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,246,246,246,103,103,103,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213, + 213,213,178,178,178,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,213,213,213,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,37,37,37,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,246,246,246,246,246,246,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,255,255,255,37,37,37,70,70,70,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,70,70,70,0,0,0,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,2,2,2,0,0,0,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,246,246,246,2,2,2,145,145,145,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,70,70,70,255,255,255,246,246,246,178,178,178,213,213,213,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,246,246,246,2,2,2,145,145,145,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,37,37,37,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,145,145,145,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,2,2,2,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,178,178,178,145,145,145,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,37,37,37,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,246,246,246,255,255,255,0,0,0,178,178,178,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,37,37,37,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,246,246,246,103,103,103,103,103,103,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,37,37,37,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,246,246,246,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,255,255,255,255,255,255,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,145,145,145,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,103,103,103,0,0,0,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,246,246,246,0,0,0,255,255,255,213,213,213,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,37,37,37,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,255,255,255,0,0,0,255,255,255,2,2,2,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,255,255,255,103,103,103,255,255,255,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,70,70,70,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,246,246,246,255,255,255,178,178,178,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,178,178,178,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,103,103,103,255,255,255,103,103,103,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,37,37,37,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37, + 37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,70,70,70,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,2,2,2,246,246,246,0,0,0,0,0,0,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,178,178,178,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255, + 255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,103,103,103,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,37,37,37,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,213,213,213,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,178,178,178,255,255,255,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,178,178, + 178,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,213,213,213,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,145,145,145,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,246,246,246,246,246,246,246,246,246,246,246,246,246,246, + 246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,246,246,246,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,37,37, + 37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,103,103,103,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,213,213,213,0,0,0,0,0,0,103,103,103,0,0,0,70,70,70,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,255,255,255,178,178,178,178,178,178,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255, + 255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,103,103,103,255,255,255,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,2,2,2,255,255,255,0,0,0,178,178,178,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255, + 255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,246,246,246,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,2,2,2,246,246,246,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,255,255,255,246,246,246,246,246,246,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,246,246,246,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255, + 255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,213,213,213,178,178,178,255,255,255,70,70,70,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,103,103,103,255,255,255,2,2,2,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,145,145,145,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255, + 255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,255,255,255,2,2,2,103,103,103,213,213,213,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,255,255,255,178,178,178,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,103,103,103,0,0,0,145,145,145,103,103,103,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255, + 255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,255,255,255,0,0,0,0,0,0,255,255,255,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,246,246,246,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255, + 255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,37,37,37,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,70,70,70,0,0,0,0,0,0,2,2,2,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,70,70,70,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,178,178,178,255,255,255,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,103,103,103,255,255, + 255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,213,213,213,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246, + 246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,213,213,213,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,70,70,70,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,246,246,246,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,246,246,246,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,246,246,246,255,255,255,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,70,70,70,103,103,103,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,37,37,37,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,246,246,246,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,213,213,213,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,178,178,178,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,178,178,178,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,246,246,246,246,246,246,103,103,103,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,103,103,103,145,145,145,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,2,2,2,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,213,213,213,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,145,145,145,246,246,246,246,246,246,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,70,70,70,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178, + 178,178,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,103,103,103,145,145,145,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,2,2,2,0,0,0,255,255,255,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246, + 246,246,37,37,37,0,0,0,37,37,37,246,246,246,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,103,103,103,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,0,0,0,103,103,103,103,103,103,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,246,246,246,255,255,255,255,255,255,246,246,246,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,70,70,70,246,246,246,37,37,37,246,246,246,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,255,255,255,255,255,255,246,246,246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,213,213,213,103,103,103,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,70,70,70,255,255,255,2,2,2,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,255,255,255,103,103,103,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,37,37,37,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,2,2,2,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,255,255,255,246,246,246,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,246,246,246,103,103,103,255,255,255,178,178,178,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255, + 255,255,145,145,145,255,255,255,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,145,145,145,178,178, + 178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,255,255,255,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0, + 0,0,0,0,0,255,255,255,255,255,255,145,145,145,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,2,2,2,0,0,0,70,70, + 70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,2,2,2,0,0,0,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0, + 0,0,0,0,0,103,103,103,103,103,103,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,2,2,2,70,70,70,70,70, + 70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,178,178,178,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,70,70,70,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,255,255,255,2,2,2,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,103, + 103,103,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,178,178,178,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,0,0,0,103,103,103,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178, + 178,178,246,246,246,37,37,37,0,0,0,0,0,0,0,0,0,103,103,103,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,145,145,145,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,70,70,70,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; diff --git a/Demos/OpenGL/GLDebugFont.h b/Demos/OpenGL/GLDebugFont.h new file mode 100644 index 0000000..bf2c257 --- /dev/null +++ b/Demos/OpenGL/GLDebugFont.h @@ -0,0 +1,29 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_DEBUG_FONT_H +#define BT_DEBUG_FONT_H + +#include "LinearMath/btVector3.h" + + +void GLDebugDrawStringInternal(int x,int y,const char* string,const btVector3& rgb, bool enableBlend, int spacing); +void GLDebugDrawStringInternal(int x,int y,const char* string,const btVector3& rgb); +void GLDebugDrawString(int x,int y,const char* string); +void GLDebugResetFont(int screenWidth,int screenHeight); + +#endif //BT_DEBUG_FONT_H + diff --git a/Demos/OpenGL/GL_DialogDynamicsWorld.cpp b/Demos/OpenGL/GL_DialogDynamicsWorld.cpp new file mode 100644 index 0000000..0fa5b46 --- /dev/null +++ b/Demos/OpenGL/GL_DialogDynamicsWorld.cpp @@ -0,0 +1,761 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "GL_DialogDynamicsWorld.h" +#include "GL_DialogWindow.h" +#include "btBulletDynamicsCommon.h" +#include "BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h" +#include "BulletCollision/CollisionShapes/btBox2dShape.h" +#include "BulletCollision/CollisionShapes/btConvex2dShape.h" +#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" + +GL_DialogDynamicsWorld::GL_DialogDynamicsWorld() +{ + m_upperBorder = 0; + m_lowerBorder =0; + + m_pickConstraint = 0; + m_screenWidth = 0; + m_screenHeight = 0; + + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + m_broadphase = new btDbvtBroadphase(); + m_constraintSolver = new btSequentialImpulseConstraintSolver(); + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_constraintSolver,m_collisionConfiguration); + m_dynamicsWorld ->getSolverInfo().m_splitImpulse = true; + //m_dynamicsWorld->setGravity(btVector3(0,10,0)); + m_dynamicsWorld->setGravity(btVector3(0,0,0)); + + m_simplexSolver = new btVoronoiSimplexSolver(); + m_pdSolver = new btMinkowskiPenetrationDepthSolver(); + + btConvex2dConvex2dAlgorithm::CreateFunc* convexAlgo2d = new btConvex2dConvex2dAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver); + + m_dispatcher->registerCollisionCreateFunc(CONVEX_2D_SHAPE_PROXYTYPE,CONVEX_2D_SHAPE_PROXYTYPE,convexAlgo2d); + m_dispatcher->registerCollisionCreateFunc(BOX_2D_SHAPE_PROXYTYPE,CONVEX_2D_SHAPE_PROXYTYPE,convexAlgo2d); + m_dispatcher->registerCollisionCreateFunc(CONVEX_2D_SHAPE_PROXYTYPE,BOX_2D_SHAPE_PROXYTYPE,convexAlgo2d); + m_dispatcher->registerCollisionCreateFunc(BOX_2D_SHAPE_PROXYTYPE,BOX_2D_SHAPE_PROXYTYPE,new btBox2dBox2dCollisionAlgorithm::CreateFunc()); + + ///enable boarders, to avoid 'loosing' menus +#if 1 + btTransform tr; + tr.setIdentity(); + + { + btStaticPlaneShape* plane = new btStaticPlaneShape(btVector3(0,1,0),0); + m_upperBorder = new btCollisionObject(); + tr.setOrigin(btVector3(0,-BT_LARGE_FLOAT,0)); + m_upperBorder->setWorldTransform(tr); + m_upperBorder->setCollisionShape(plane); + m_dynamicsWorld->addCollisionObject(m_upperBorder); + } + + { + btStaticPlaneShape* plane = new btStaticPlaneShape(btVector3(0,-1,0),0); + m_lowerBorder = new btCollisionObject(); + + tr.setIdentity(); + tr.setOrigin(btVector3(0,BT_LARGE_FLOAT,0)); + m_lowerBorder->setWorldTransform(tr); + m_lowerBorder->setCollisionShape(plane); + m_dynamicsWorld->addCollisionObject(m_lowerBorder); + } + { + btStaticPlaneShape* plane = new btStaticPlaneShape(btVector3(1,0,0),0); + m_leftBorder = new btCollisionObject(); + tr.setIdentity(); + tr.setOrigin(btVector3(-BT_LARGE_FLOAT,0,0)); + m_leftBorder->setWorldTransform(tr); + m_leftBorder->setCollisionShape(plane); + m_dynamicsWorld->addCollisionObject(m_leftBorder); + } + { + btStaticPlaneShape* plane = new btStaticPlaneShape(btVector3(-1,0,0),0); + m_rightBorder = new btCollisionObject(); + tr.setIdentity(); + tr.setOrigin(btVector3(BT_LARGE_FLOAT,0,0)); + m_rightBorder->setWorldTransform(tr); + m_rightBorder->setCollisionShape(plane); + m_dynamicsWorld->addCollisionObject(m_rightBorder); + } +#endif + +} + +GL_DialogDynamicsWorld::~GL_DialogDynamicsWorld() +{ + delete m_dynamicsWorld; + delete m_dispatcher; + delete m_constraintSolver; + delete m_broadphase; + delete m_collisionConfiguration; +} + +void GL_DialogDynamicsWorld::setScreenSize(int width, int height) +{ + + + int i; + + for ( i=0;igetCollisionObjectArray().size();i++) + { + btCollisionObject* colObj = m_dynamicsWorld->getCollisionObjectArray()[i]; + btRigidBody* body = btRigidBody::upcast(colObj); + if (body) + { + m_dynamicsWorld->removeRigidBody(body); + btVector3 newPos = colObj->getWorldTransform().getOrigin() + btVector3(btScalar(m_screenWidth/2.),btScalar(m_screenHeight/2),btScalar(0))-btVector3(btScalar(width/2.),btScalar(height/2.),btScalar(0)); + colObj->getWorldTransform().setOrigin(newPos); + m_dynamicsWorld->addRigidBody(body); + } else + { + m_dynamicsWorld->removeCollisionObject(colObj); + btVector3 newPos = colObj->getWorldTransform().getOrigin() + btVector3(btScalar(m_screenWidth/2.),btScalar(m_screenHeight/2.),btScalar(0))-btVector3(btScalar(width/2.),btScalar(height/2.),btScalar(0)); + colObj->getWorldTransform().setOrigin(newPos); + m_dynamicsWorld->addCollisionObject(colObj); + } + } + + for ( i=0;isetScreenSize(width,height); + } + if (width && height) + { + if (m_upperBorder) + { + m_dynamicsWorld->removeCollisionObject(m_upperBorder); + + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(0),btScalar(-height/2.),btScalar(0.))); + m_upperBorder->setWorldTransform(tr); + m_dynamicsWorld->addCollisionObject(m_upperBorder); + } + + if (m_lowerBorder) + { + m_dynamicsWorld->removeCollisionObject(m_lowerBorder); + + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(0),btScalar(height/2.),btScalar(0))); + m_lowerBorder->setWorldTransform(tr); + m_dynamicsWorld->addCollisionObject(m_lowerBorder); + } + if (m_leftBorder) + { + m_dynamicsWorld->removeCollisionObject(m_leftBorder); + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(-width/2.),btScalar(0),btScalar(0))); + m_leftBorder->setWorldTransform(tr); + m_dynamicsWorld->addCollisionObject(m_leftBorder); + } + if (m_rightBorder) + { + m_dynamicsWorld->removeCollisionObject(m_rightBorder); + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(btScalar(width/2.),btScalar(0),btScalar(0))); + m_rightBorder->setWorldTransform(tr); + m_dynamicsWorld->addCollisionObject(m_rightBorder); + + } + + } + + + m_screenWidth = width; + m_screenHeight = height; +} + +GL_DialogWindow* GL_DialogDynamicsWorld::createDialog(int horPos,int vertPos,int dialogWidth,int dialogHeight, const char* dialogTitle ) +{ + btBox2dShape* boxShape = new btBox2dShape(btVector3(dialogWidth/2.f,dialogHeight/2.f,0.4f)); + btScalar mass = 100.f; + btVector3 localInertia; + boxShape->calculateLocalInertia(mass,localInertia); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,boxShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + btTransform trans; + trans.setIdentity(); +// trans.setOrigin(btVector3(btScalar(horPos-m_screenWidth/2+dialogWidth/2), btScalar(vertPos+m_screenHeight/2.+dialogHeight/2),btScalar(0.))); + trans.setOrigin(btVector3(btScalar(horPos-m_screenWidth/2+dialogWidth/2), btScalar(vertPos-m_screenHeight/2.+dialogHeight/2),btScalar(0.))); + + + + body->setWorldTransform(trans); + body->setDamping(0.999f,0.99f); + + //body->setActivationState(ISLAND_SLEEPING); + body->setLinearFactor(btVector3(1,1,0)); + //body->setAngularFactor(btVector3(0,0,1)); + body->setAngularFactor(btVector3(0,0,0)); + + GL_DialogWindow* dialogWindow = new GL_DialogWindow(horPos,vertPos,dialogWidth,dialogHeight,body,dialogTitle); + m_dialogs.push_back(dialogWindow); + m_dynamicsWorld->addRigidBody(body); + + return dialogWindow; + +} + +GL_SliderControl* GL_DialogDynamicsWorld::createSlider(GL_DialogWindow* dialog, const char* sliderText, btScalar initialFraction) +{ + btBox2dShape* boxShape = new btBox2dShape(btVector3(6.f,6.f,0.4f)); + btScalar mass = .1f; + btVector3 localInertia; + boxShape->calculateLocalInertia(mass,localInertia); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,boxShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + btTransform trans; + trans.setIdentity(); + int sliderX = dialog->getDialogHorPos() - m_screenWidth/2 + dialog->getDialogWidth()/2; +// int sliderY = dialog->getDialogVertPos() + m_screenHeight/2 + dialog->getDialogHeight()/2 + dialog->getNumControls()*20; + int sliderY = dialog->getDialogVertPos() - m_screenHeight/2 + dialog->getDialogHeight()/2 + dialog->getNumControls()*20; + trans.setOrigin(btVector3((btScalar)sliderX, (btScalar)sliderY,(btScalar)-0.2f)); + + body->setWorldTransform(trans); + //body->setDamping(0.999,0.99); + + //body->setActivationState(ISLAND_SLEEPING); + body->setLinearFactor(btVector3(1,1,0)); + //body->setAngularFactor(btVector3(0,0,1)); + body->setAngularFactor(btVector3(0,0,0)); + + m_dynamicsWorld->addRigidBody(body); + body->setCollisionFlags(body->getFlags()|btCollisionObject::CF_NO_CONTACT_RESPONSE); + + btRigidBody* dialogBody = btRigidBody::upcast(dialog->getCollisionObject()); + btAssert(dialogBody); + + + + btTransform frameInA; + frameInA.setIdentity(); + int offsX = -dialog->getDialogWidth()/2 + 16; + int offsY = -dialog->getDialogHeight()/2 + dialog->getNumControls()*20 + 36; + btVector3 offset(btVector3((btScalar)offsX, (btScalar)offsY, (btScalar)0.2f)); + frameInA.setOrigin(offset); + + + btTransform frameInB; + frameInB.setIdentity(); + //frameInB.setOrigin(-offset/2); + +// btScalar lowerLimit = 80.f; +// btScalar upperLimit = 170.f; + btScalar lowerLimit = 141.f; + btScalar upperLimit = 227.f; + + btScalar actualLimit = lowerLimit+initialFraction*(upperLimit-lowerLimit); + + +#if 0 + bool useFrameA = false; + + btGeneric6DofConstraint* constraint = new btGeneric6DofConstraint(*dialogBody,*body,frameInA,frameInB,useFrameA); + m_dynamicsWorld->addConstraint(constraint,true); + constraint->setLimit(0,lowerLimit,upperLimit); +#else + btSliderConstraint* sliderConstraint = new btSliderConstraint(*dialogBody,*body,frameInA,frameInB,true);//useFrameA); + sliderConstraint->setLowerLinLimit(actualLimit); + sliderConstraint->setUpperLinLimit(actualLimit); + m_dynamicsWorld->addConstraint(sliderConstraint,true); + +#endif + + + GL_SliderControl* slider = new GL_SliderControl(sliderText, body,dialog,lowerLimit,upperLimit, sliderConstraint); + body->setUserPointer(slider); + dialog->addControl(slider); + + slider->m_fraction = initialFraction; + + return slider; +} + + + +GL_ToggleControl* GL_DialogDynamicsWorld::createToggle(GL_DialogWindow* dialog, const char* toggleText) +{ + + + btBox2dShape* boxShape = new btBox2dShape(btVector3(6.f,6.f,0.4f)); + btScalar mass = 0.1f; + btVector3 localInertia; + boxShape->calculateLocalInertia(mass,localInertia); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,boxShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + btTransform trans; + trans.setIdentity(); + + int toggleX = dialog->getDialogHorPos() - m_screenWidth/2 + dialog->getDialogWidth()/2; +// int toggleY = dialog->getDialogVertPos() + m_screenHeight/2 + dialog->getDialogHeight()/2 + dialog->getNumControls()*20; + int toggleY = dialog->getDialogVertPos() - m_screenHeight/2 + dialog->getDialogHeight()/2 + dialog->getNumControls()*20; + trans.setOrigin(btVector3((btScalar)toggleX, (btScalar)toggleY,(btScalar) -0.2f)); + + body->setWorldTransform(trans); + body->setDamping(0.999f,0.99f); + + //body->setActivationState(ISLAND_SLEEPING); + body->setLinearFactor(btVector3(1,1,0)); + //body->setAngularFactor(btVector3(0,0,1)); + body->setAngularFactor(btVector3(0,0,0)); + + m_dynamicsWorld->addRigidBody(body); + body->setCollisionFlags(body->getFlags()|btCollisionObject::CF_NO_CONTACT_RESPONSE); + + btRigidBody* dialogBody = btRigidBody::upcast(dialog->getCollisionObject()); + btAssert(dialogBody); + + + + btTransform frameInA; + frameInA.setIdentity(); + btVector3 offset(btVector3(+dialog->getDialogWidth()/2.f-32.f,-dialog->getDialogHeight()/2.f+dialog->getNumControls()*20.f+36.f,0.2f)); + frameInA.setOrigin(offset); + + + btTransform frameInB; + frameInB.setIdentity(); + //frameInB.setOrigin(-offset/2); + bool useFrameA = true; + + btGeneric6DofConstraint* constraint = new btGeneric6DofConstraint(*dialogBody,*body,frameInA,frameInB,useFrameA); + m_dynamicsWorld->addConstraint(constraint,true); + + + GL_ToggleControl* toggle = new GL_ToggleControl(toggleText, body,dialog); + body->setUserPointer(toggle); + dialog->addControl(toggle); + return toggle; +} + +void GL_DialogDynamicsWorld::draw(btScalar timeStep) +{ + if (timeStep) + { + m_dynamicsWorld->stepSimulation(timeStep); + } + + for (int i=0;idraw(timeStep); + } +} + +static btRigidBody* pickedBody = 0;//for deactivation state +static btScalar mousePickClamping = 111130.f; + +//static int gPickingConstraintId = 0; +static btVector3 gOldPickingPos; +static btVector3 gHitPos(-1,-1,-1); + +static btScalar gOldPickingDist = 0.f; + +bool GL_DialogDynamicsWorld::mouseFunc(int button, int state, int x, int y) +{ + if (state == 0) + { + m_mouseButtons |= 1<rayTest(m_cameraPosition,rayTo,rayCallback); + if (rayCallback.hasHit()) + { + + btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject); + if (body) + { + body->setActivationState(ACTIVE_TAG); + btVector3 impulse = rayTo; + impulse.normalize(); + float impulseStrength = 10.f; + impulse *= impulseStrength; + btVector3 relPos = rayCallback.m_hitPointWorld - body->getCenterOfMassPosition(); + body->applyImpulse(impulse,relPos); + } + } + } +#endif + + + + } else + { + + } + break; + } + + case 0: + { + if (state==0) + { + + + //add a point to point constraint for picking + if (m_dynamicsWorld) + { + + btVector3 rayFrom; + if (1)//m_ortho) + { + rayFrom = rayTo; + rayFrom.setZ(-100.f); + } + //else + //{ + // rayFrom = m_cameraPosition; + //} + + btCollisionWorld::ClosestRayResultCallback rayCallback(rayFrom,rayTo); + m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback); + if (rayCallback.hasHit()) + { + + + btScalar maxPickingClamp = mousePickClamping; + + btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject); + if (body) + { + bool doPick = true; + if (body->getUserPointer()) + { + ///deal with controls in a special way + GL_DialogControl* ctrl = (GL_DialogControl*)body->getUserPointer(); + + switch(ctrl->getType()) + { + case GL_TOGGLE_CONTROL: + { + GL_ToggleControl* toggle = (GL_ToggleControl*) ctrl; + toggle->m_active = !toggle->m_active; + doPick = false; + break; + } + case GL_SLIDER_CONTROL: + { + GL_SliderControl* slider = (GL_SliderControl*) ctrl; + btTypedConstraint* constraint = slider->getConstraint(); + if (constraint->getConstraintType() == SLIDER_CONSTRAINT_TYPE) + { + btSliderConstraint* sliderConstraint = (btSliderConstraint*) constraint; + sliderConstraint->setLowerLinLimit(slider->getLowerLimit()); + sliderConstraint->setUpperLinLimit(slider->getUpperLimit()); + } + maxPickingClamp = 100; + } + default: + { + } + }; + + }; + + if (doPick) + { + //other exclusions? + if (!(body->isStaticObject() || body->isKinematicObject())) + { + pickedBody = body; + pickedBody->setActivationState(DISABLE_DEACTIVATION); + + + + btVector3 pickPos = rayCallback.m_hitPointWorld; + //printf("pickPos=%f,%f,%f\n",pickPos.getX(),pickPos.getY(),pickPos.getZ()); + + + btVector3 localPivot = body->getCenterOfMassTransform().inverse() * pickPos; + + btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*body,localPivot); + p2p->m_setting.m_impulseClamp = maxPickingClamp; + + m_dynamicsWorld->addConstraint(p2p); + m_pickConstraint = p2p; + + //save mouse position for dragging + gOldPickingPos = rayTo; + gHitPos = pickPos; + + gOldPickingDist = (pickPos-rayFrom).length(); + + //very weak constraint for picking + p2p->m_setting.m_tau = 0.1f; + } + } + return true; + } + } + } + + } else + { + + if (m_pickConstraint && m_dynamicsWorld) + { + m_dynamicsWorld->removeConstraint(m_pickConstraint); + delete m_pickConstraint; + //printf("removed constraint %i",gPickingConstraintId); + m_pickConstraint = 0; + pickedBody->forceActivationState(ACTIVE_TAG); + pickedBody->setDeactivationTime( 0.f ); + + + if (pickedBody->getUserPointer()) + { + ///deal with controls in a special way + GL_DialogControl* ctrl = (GL_DialogControl*)pickedBody->getUserPointer(); + if (ctrl->getType()==GL_SLIDER_CONTROL) + { + GL_SliderControl* sliderControl = (GL_SliderControl*) ctrl; + + btSliderConstraint* slider = 0; + btTypedConstraint* constraint = sliderControl->getConstraint(); + if (constraint->getConstraintType() == SLIDER_CONSTRAINT_TYPE) + { + slider = (btSliderConstraint*)constraint; + } + if (slider) + { + btScalar linDepth = slider->getLinearPos(); + btScalar lowLim = slider->getLowerLinLimit(); + btScalar hiLim = slider->getUpperLinLimit(); + slider->setPoweredLinMotor(false); + if(linDepth <= lowLim) + { + slider->setLowerLinLimit(lowLim); + slider->setUpperLinLimit(lowLim); + } + else if(linDepth > hiLim) + { + slider->setLowerLinLimit(hiLim); + slider->setUpperLinLimit(hiLim); + } + else + { + slider->setLowerLinLimit(linDepth); + slider->setUpperLinLimit(linDepth); + } + } + } + + } + + pickedBody = 0; + + } + + + + } + + break; + + } + + default: + { + } + } + + return false; + +} + + + +btVector3 GL_DialogDynamicsWorld::getRayTo(int x,int y) +{ + float cameraDistance = m_screenHeight/2.f;//m_screenWidth/2;//1.f; + btVector3 cameraTargetPosition(0,0,0); + btVector3 cameraUp(0,-1,0); + + if (1)//_ortho) + { + + btScalar aspect; + btVector3 extents; + if (m_screenWidth> m_screenHeight) + { + + aspect = m_screenWidth / (btScalar)m_screenHeight; + extents.setValue(aspect * 1.0f, 1.0f,0); + } else + { + cameraDistance = m_screenWidth/2.f; + aspect = m_screenHeight / (btScalar)m_screenWidth; + extents.setValue(1.0f, aspect*1.f,0); + } + + + + extents *= cameraDistance; + btVector3 lower = cameraTargetPosition - extents; + btVector3 upper = cameraTargetPosition + extents; + + btScalar u = x / btScalar(m_screenWidth); + btScalar v = (m_screenHeight - y) / btScalar(m_screenHeight); + + btVector3 p(0,0,0); + p.setValue( + (1.0f - u) * lower.getX() + u * upper.getX(), + -((1.0f - v) * lower.getY() + v * upper.getY()), + cameraTargetPosition.getZ()); + return p; + } + + float top = 1.f; + float bottom = -1.f; + float nearPlane = 1.f; + float tanFov = (top-bottom)*0.5f / nearPlane; + float fov = 2 * atanf (tanFov); + + btVector3 cameraPosition(0,0,-100); + btVector3 rayFrom = cameraPosition; + btVector3 rayForward = (cameraTargetPosition-cameraPosition); + rayForward.normalize(); + float farPlane = 10000.f; + rayForward*= farPlane; + + btVector3 rightOffset; + btVector3 vertical = cameraUp; + + btVector3 hor; + hor = rayForward.cross(vertical); + hor.normalize(); + vertical = hor.cross(rayForward); + vertical.normalize(); + + float tanfov = tanf(0.5f*fov); + + + hor *= 2.f * farPlane * tanfov; + vertical *= 2.f * farPlane * tanfov; + + btScalar aspect; + + if (m_screenWidth > m_screenHeight) + { + aspect = m_screenWidth / (btScalar)m_screenHeight; + + hor*=aspect; + } else + { + aspect = m_screenHeight / (btScalar)m_screenWidth; + vertical*=aspect; + } + + + btVector3 rayToCenter = rayFrom + rayForward; + btVector3 dHor = hor * 1.f/float(m_screenWidth); + btVector3 dVert = vertical * 1.f/float(m_screenHeight); + + + btVector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical; + rayTo += btScalar(x) * dHor; + rayTo -= btScalar(y) * dVert; + //rayTo += y * dVert; + + return rayTo; +} + + + +void GL_DialogDynamicsWorld::mouseMotionFunc(int x,int y) +{ + + if (m_pickConstraint) + { + //move the constraint pivot + btPoint2PointConstraint* p2p = static_cast(m_pickConstraint); + if (p2p) + { + //keep it at the same picking distance + + btVector3 newRayTo = getRayTo(x,y); + btVector3 rayFrom; + btVector3 oldPivotInB = p2p->getPivotInB(); + btVector3 newPivotB; + if (1)//_ortho) + { + newPivotB = oldPivotInB; + newPivotB.setX(newRayTo.getX()); + newPivotB.setY(newRayTo.getY()); + } else + { + //rayFrom = m_cameraPosition; + // btVector3 dir = newRayTo-rayFrom; + // dir.normalize(); + // dir *= gOldPickingDist; + + // newPivotB = rayFrom + dir; + } + + + + p2p->setPivotB(newPivotB); + } + + } + + btScalar dx, dy; + dx = btScalar(x) - m_mouseOldX; + dy = btScalar(y) - m_mouseOldY; + + + + + m_mouseOldX = x; + m_mouseOldY = y; +// updateCamera(); + + +} + + diff --git a/Demos/OpenGL/GL_DialogDynamicsWorld.h b/Demos/OpenGL/GL_DialogDynamicsWorld.h new file mode 100644 index 0000000..8292ae4 --- /dev/null +++ b/Demos/OpenGL/GL_DialogDynamicsWorld.h @@ -0,0 +1,91 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 GL_DIALOG_DYNAMICS_WORLD_H +#define GL_DIALOG_DYNAMICS_WORLD_H + +class btDiscreteDynamicsWorld; +class GL_DialogWindow; +class btDefaultCollisionConfiguration; +struct btDbvtBroadphase; +class btSequentialImpulseConstraintSolver; +class btCollisionDispatcher; +class btVoronoiSimplexSolver; +class btMinkowskiPenetrationDepthSolver; +class btCollisionObject; +class btTypedConstraint; +struct GL_ToggleControl; +struct GL_SliderControl; + + +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btVector3.h" + +class GL_DialogDynamicsWorld +{ + + btDefaultCollisionConfiguration* m_collisionConfiguration; + btDbvtBroadphase* m_broadphase; + btSequentialImpulseConstraintSolver* m_constraintSolver; + btCollisionDispatcher* m_dispatcher; + btVoronoiSimplexSolver* m_simplexSolver; + btMinkowskiPenetrationDepthSolver* m_pdSolver; + + btDiscreteDynamicsWorld* m_dynamicsWorld; + + btCollisionObject* m_lowerBorder; + btCollisionObject* m_upperBorder; + btCollisionObject* m_leftBorder; + btCollisionObject* m_rightBorder; + + btAlignedObjectArray m_dialogs; + + int m_screenWidth; + int m_screenHeight; + + + ///for picking + int m_mouseOldX; + int m_mouseOldY; + int m_mouseButtons; + ///constraint for mouse picking + btTypedConstraint* m_pickConstraint; + + btVector3 getRayTo(int x,int y); + +public: + + GL_DialogDynamicsWorld(); + + virtual ~GL_DialogDynamicsWorld(); + + virtual void setScreenSize(int width, int height); + + virtual GL_DialogWindow* createDialog(int horPos,int vertPos,int dialogWidth,int dialogHeight, const char* dialogTitle ); + + GL_ToggleControl* createToggle(GL_DialogWindow* dialog, const char* toggleText); + + GL_SliderControl* createSlider(GL_DialogWindow* dialog, const char* sliderText, btScalar initialFraction = btScalar(0.5f)); + + virtual void draw(btScalar timeStep); + + virtual bool mouseFunc(int button, int state, int x, int y); + + virtual void mouseMotionFunc(int x,int y); + +}; + +#endif //GL_DIALOG_DYNAMICS_WORLD_H diff --git a/Demos/OpenGL/GL_DialogWindow.cpp b/Demos/OpenGL/GL_DialogWindow.cpp new file mode 100644 index 0000000..b3ecae8 --- /dev/null +++ b/Demos/OpenGL/GL_DialogWindow.cpp @@ -0,0 +1,358 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "GL_DialogWindow.h" + + + +#include "GLDebugFont.h" +#include "btBulletDynamicsCommon.h" + +#include // for sprintf() + +#define USE_ARRAYS 1 + + +GL_DialogWindow::GL_DialogWindow(int horPos,int vertPos,int dialogWidth,int dialogHeight, btCollisionObject* collisionObject,const char* dialogTitle) +:m_dialogHorPos(horPos), +m_dialogVertPos(vertPos), +m_dialogWidth(dialogWidth), +m_dialogHeight(dialogHeight), +m_screenWidth(0), +m_screenHeight(0), +m_dialogTitle(dialogTitle), +m_MaxClipPlanes(-1), +m_collisionObject(collisionObject) + +{ +} + +void GL_DialogWindow::setScreenSize(int width, int height) +{ + m_screenWidth = width; + m_screenHeight = height; +} +GL_DialogWindow::~GL_DialogWindow() +{ + +} + + + +static void drawLine(int _X0, int _Y0, int _X1, int _Y1, unsigned int _Color0, unsigned int _Color1) +{ + const GLfloat dx = +0.5f; + const GLfloat dy = -0.5f; + + GLfloat vVertices[] = {(GLfloat)_X0+dx,(GLfloat)_Y0+dy,(GLfloat)_X1+dx,(GLfloat)_Y1+dy}; + + bool antiAliased = false; + if( antiAliased ) + glEnable(GL_LINE_SMOOTH); + else + glDisable(GL_LINE_SMOOTH); + glDisable(GL_TEXTURE_2D); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + +#ifdef USE_ARRAYS + glColor4ub(GLubyte(_Color0>>16), GLubyte(_Color0>>8), GLubyte(_Color0), GLubyte(_Color0>>24)); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glLineWidth(2.0f); + glVertexPointer(2, GL_FLOAT, 0, vVertices); + glEnableClientState(GL_VERTEX_ARRAY); + glDrawArrays(GL_LINES,0,2); +#else + glLineWidth(13.0f); + glBegin(GL_LINES); + glColor4ub(GLubyte(_Color0>>16), GLubyte(_Color0>>8), GLubyte(_Color0), GLubyte(_Color0>>24)); + glVertex2f((GLfloat)_X0+dx, (GLfloat)_Y0+dy); + glColor4ub(GLubyte(_Color1>>16), GLubyte(_Color1>>8), GLubyte(_Color1), GLubyte(_Color1>>24)); + glVertex2f((GLfloat)_X1+dx, (GLfloat)_Y1+dy); + glEnd(); +#endif + glDisable(GL_LINE_SMOOTH); +} + +static void drawRect(int horStart, int vertStart, int horEnd, int vertEnd, unsigned int argbColor00,unsigned int argbColor10,unsigned int argbColor01,unsigned int argbColor11) +{ + float dx = 0; + float dy = 0; + glDisable(GL_TEXTURE_2D); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +#ifdef USE_ARRAYS + GLfloat verts[] ={ + 0.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, + 0.f,0.f,0.f + }; + + glColor4ub(GLubyte(argbColor00>>16), GLubyte(argbColor00>>8), GLubyte(argbColor00), GLubyte(argbColor00>>24)); + verts[0] = (GLfloat)horStart+dx; verts[1] = (GLfloat)vertStart+dy; + verts[2] = (GLfloat)horEnd+dx; verts[3] = (GLfloat)vertStart+dy; + verts[4] = (GLfloat)horEnd+dx; verts[5] = (GLfloat)vertEnd+dy; + verts[6] = (GLfloat)horStart+dx; verts[7] = (GLfloat)vertEnd+dy; + + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState (GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, verts); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + +#else + glBegin(GL_QUADS); + glColor4ub(GLubyte(argbColor00>>16), GLubyte(argbColor00>>8), GLubyte(argbColor00), GLubyte(argbColor00>>24)); + glVertex2f((GLfloat)horStart+dx, (GLfloat)vertStart+dy); + glColor4ub(GLubyte(argbColor10>>16), GLubyte(argbColor10>>8), GLubyte(argbColor10), GLubyte(argbColor10>>24)); + glVertex2f((GLfloat)horEnd+dx, (GLfloat)vertStart+dy); + glColor4ub(GLubyte(argbColor11>>16), GLubyte(argbColor11>>8), GLubyte(argbColor11), GLubyte(argbColor11>>24)); + glVertex2f((GLfloat)horEnd+dx, (GLfloat)vertEnd+dy); + glColor4ub(GLubyte(argbColor01>>16), GLubyte(argbColor01>>8), GLubyte(argbColor01), GLubyte(argbColor01>>24)); + glVertex2f((GLfloat)horStart+dx, (GLfloat)vertEnd+dy); + glEnd(); +#endif + +} + +void GL_DialogWindow::draw(btScalar deltaTime) +{ + if (!m_screenWidth || !m_screenHeight) + return; + + m_dialogHorPos = int(m_collisionObject->getWorldTransform().getOrigin()[0]+m_screenWidth/2.f-m_dialogWidth/2.f); + + m_dialogVertPos = int(m_collisionObject->getWorldTransform().getOrigin()[1]+m_screenHeight/2.f-m_dialogHeight/2.f); + saveOpenGLState(); + + //drawRect(m_dialogHorPos,m_dialogVertPos,m_dialogHorPos+m_dialogWidth,m_dialogVertPos+m_dialogHeight,0xa6000000); + unsigned int argbColor = 0x86000000; + int charHeight = 16; + int charWidth = 10; + + int titleHeight = charHeight + 2; + + drawRect(m_dialogHorPos,m_dialogVertPos,m_dialogHorPos+m_dialogWidth-1,m_dialogVertPos+titleHeight,argbColor,argbColor,argbColor,argbColor); + //const unsigned int COL0 = 0x50ffffff; + const unsigned int COL0 = 0xffffffff; + const unsigned int COL1 = 0xff1f1f1f; + + drawRect(m_dialogHorPos,m_dialogVertPos,m_dialogHorPos+m_dialogWidth-1,m_dialogVertPos+1,COL0,COL0,COL1,COL1); + + argbColor = 0x864f4f4f; + drawRect(m_dialogHorPos+1,m_dialogVertPos+titleHeight,m_dialogHorPos+m_dialogWidth-1,m_dialogVertPos+m_dialogHeight,argbColor,argbColor,argbColor,argbColor); + + + int y = m_dialogVertPos+charHeight+1; + glLineWidth(3); + drawLine(m_dialogHorPos, y, m_dialogHorPos+m_dialogWidth-1, y, 0x80afafaf,0x80afafaf); + + + + unsigned int clight = 0x5FFFFFFF; // bar contour + drawLine(m_dialogHorPos, m_dialogVertPos, m_dialogHorPos, m_dialogVertPos+m_dialogHeight, clight,clight); + drawLine(m_dialogHorPos, m_dialogVertPos, m_dialogHorPos+m_dialogWidth, m_dialogVertPos, clight,clight); + drawLine(m_dialogHorPos+m_dialogWidth, m_dialogVertPos, m_dialogHorPos+m_dialogWidth, m_dialogVertPos+m_dialogHeight, clight,clight); + drawLine(m_dialogHorPos, m_dialogVertPos+m_dialogHeight, m_dialogHorPos+m_dialogWidth, m_dialogVertPos+m_dialogHeight, clight,clight); + int dshad = 3; // bar shadows + + unsigned int cshad = (((0x40000000>>24)/2)<<24) & 0xFF000000; + drawRect(m_dialogHorPos, m_dialogVertPos+m_dialogHeight, m_dialogHorPos+dshad, m_dialogVertPos+m_dialogHeight+dshad, 0, cshad, 0, 0); + drawRect(m_dialogHorPos+dshad+1, m_dialogVertPos+m_dialogHeight, m_dialogHorPos+m_dialogWidth-1, m_dialogVertPos+m_dialogHeight+dshad, cshad, cshad, 0, 0); + drawRect(m_dialogHorPos+m_dialogWidth, m_dialogVertPos+m_dialogHeight, m_dialogHorPos+m_dialogWidth+dshad, m_dialogVertPos+m_dialogHeight+dshad, cshad, 0, 0, 0); + drawRect(m_dialogHorPos+m_dialogWidth, m_dialogVertPos, m_dialogHorPos+m_dialogWidth+dshad, m_dialogVertPos+dshad, 0, 0, cshad, 0); + drawRect(m_dialogHorPos+m_dialogWidth, m_dialogVertPos+dshad+1, m_dialogHorPos+m_dialogWidth+dshad, m_dialogVertPos+m_dialogHeight-1, cshad, 0, cshad, 0); + + int yInc = 16; + int curHorPos = m_dialogHorPos+5; + int curVertPos = m_dialogVertPos; + curVertPos += yInc; + + GLDebugDrawString(m_dialogHorPos+m_dialogWidth/2-((int(strlen(m_dialogTitle)/2))*charWidth),m_dialogVertPos+yInc ,m_dialogTitle); + curVertPos += 20; + + + for (int i=0;idraw(curHorPos,curVertPos,deltaTime); + } + + restoreOpenGLState(); +} + + +void GL_DialogWindow::saveOpenGLState() +{ +#if 0 + glPushAttrib(GL_ALL_ATTRIB_BITS); + glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); +#endif + + glMatrixMode(GL_TEXTURE); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + GLint Vp[4]; + glGetIntegerv(GL_VIEWPORT, Vp); + + if( m_screenWidth>0 && m_screenHeight>0 ) + { + Vp[0] = 0; + Vp[1] = 0; + Vp[2] = m_screenWidth-1; + Vp[3] = m_screenHeight-1; + glViewport(Vp[0], Vp[1], Vp[2], Vp[3]); + } + glLoadIdentity(); + glOrtho(Vp[0], Vp[0]+Vp[2], Vp[1]+Vp[3], Vp[1], -1, 1); + glGetIntegerv(GL_VIEWPORT, m_ViewportInit); + glGetFloatv(GL_PROJECTION_MATRIX, m_ProjMatrixInit); + + glGetFloatv(GL_LINE_WIDTH, &m_PrevLineWidth); + // glDisable(GL_POLYGON_STIPPLE); + glLineWidth(1); + + glDisable(GL_LINE_SMOOTH); +// glDisable(GL_LINE_STIPPLE); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glEnable(GL_BLEND); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &m_PrevTexEnv); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glDisable(GL_TEXTURE_2D); + +} + +void GL_DialogWindow::restoreOpenGLState() +{ + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, m_PrevTexEnv); + glLineWidth(m_PrevLineWidth); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glMatrixMode(GL_TEXTURE); + glPopMatrix(); + glPopClientAttrib(); + glPopAttrib(); + +} + + +void GL_TextControl::draw(int& parentHorPos,int& parentVertPos,btScalar deltaTime) +{ + for (int i=0;igetWorldTransform().getOrigin()[0]+m_parentWindow->getScreenWidth()/2); + int controlVertPos = int(m_toggleBody->getWorldTransform().getOrigin()[1]+m_parentWindow->getScreenHeight()/2); + + int parentHorPos = controlHorPos-8; + int parentVertPos = controlVertPos-8; + + unsigned int grey = 0xff6f6f6f; + + drawRect(parentHorPos, parentVertPos, parentHorPos+16, parentVertPos+16, grey, grey, grey, grey); + + int borderSize = 2; + unsigned int white = 0xffefefef; + drawRect(parentHorPos+borderSize, parentVertPos+borderSize, parentHorPos+16-borderSize, parentVertPos+16-borderSize, white,white,white,white); + + + if (m_active) + { + //unsigned int red = 0xff8f0000; + // unsigned int white = 0xff8f0000; + unsigned int black = 0xff1f1f1f; + borderSize = 4; + drawRect(parentHorPos+borderSize, parentVertPos+borderSize, parentHorPos+16-borderSize, parentVertPos+16-borderSize, black,black,black,black); + } + + btVector3 rgb(1,1,1); + + GLDebugDrawStringInternal(parentHorPos2,parentVertPos+16,m_toggleText,rgb); + parentVertPos2+=20; + +} + +void GL_SliderControl::draw(int& parentHorPos2,int& parentVertPos2,btScalar deltaTime) +{ + + int controlHorPos = int(m_sliderBody->getWorldTransform().getOrigin()[0]+m_parentWindow->getScreenWidth()/2); + int controlVertPos = int(m_sliderBody->getWorldTransform().getOrigin()[1]+m_parentWindow->getScreenHeight()/2); + + int parentHorPos = controlHorPos-8; + int parentVertPos = controlVertPos-8; + + unsigned int grey = 0xff6f6f6f; + int borderSize = 2; + unsigned int white = 0xffefefef; + int sliderPosS = parentHorPos2+150+borderSize; + int sliderPosE = parentHorPos2+m_parentWindow->getDialogWidth()-40-borderSize; + int sliderPos = controlHorPos; + if(sliderPos < sliderPosS) sliderPos = sliderPosS; + if(sliderPos > sliderPosE) sliderPos = sliderPosE; +// drawRect(parentHorPos2+80+borderSize, parentVertPos2+borderSize, parentHorPos2+m_parentWindow->getDialogWidth()-16-borderSize, parentVertPos2+2-borderSize, white,white,white,white); + drawRect( sliderPosS, + parentVertPos2+borderSize, + sliderPosE, + parentVertPos2+2-borderSize, + white,white,white,white); + + drawRect(parentHorPos, parentVertPos, parentHorPos+16, parentVertPos+16, grey, grey, grey, grey); + + + + drawRect(parentHorPos+borderSize, parentVertPos+borderSize, parentHorPos+16-borderSize, parentVertPos+16-borderSize, white,white,white,white); + + + + btVector3 rgb(1,1,1); + +// btSliderConstraint* pSlider = (btSliderConstraint*)m_constraint; +// btScalar currPos = pSlider->getLinearPos(); +// if(currPos < pSlider->getLowerLinLimit()) currPos = pSlider->getLowerLinLimit(); +// if(currPos > pSlider->getUpperLinLimit()) currPos = pSlider->getUpperLinLimit(); +// m_fraction = (currPos - pSlider->getLowerLinLimit()) / (pSlider->getUpperLinLimit() - pSlider->getLowerLinLimit()); + m_fraction = (btScalar)(sliderPos - sliderPosS) / (btScalar)(sliderPosE - sliderPosS); + + char tmpBuf[256]; + sprintf(tmpBuf, "%s %3d%%", m_sliderText, (int)(m_fraction * 100.f)); + +// GLDebugDrawStringInternal(parentHorPos2,parentVertPos2+8,m_sliderText,rgb); + GLDebugDrawStringInternal(parentHorPos2,parentVertPos2+8, tmpBuf, rgb); + parentVertPos2+=20; + +} diff --git a/Demos/OpenGL/GL_DialogWindow.h b/Demos/OpenGL/GL_DialogWindow.h new file mode 100644 index 0000000..75cb04e --- /dev/null +++ b/Demos/OpenGL/GL_DialogWindow.h @@ -0,0 +1,285 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 GL_DIALOG_WINDOW_H +#define GL_DIALOG_WINDOW_H + +class btCollisionObject; + + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#if (defined (TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || (defined (TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR) +#import +#define glOrtho glOrthof +#else +#include +#include +#include +#endif +#else + + +#ifdef _WIN32 +#include +#include +#include +#else +#include +#include +#endif +#endif + + +#include "LinearMath/btScalar.h" +#include "LinearMath/btAlignedObjectArray.h" +class btTypedConstraint; + +class GL_DialogWindow; + +enum GL_DIALOG_CONTROL_TYPES +{ + GL_TEXT_CONTROL=1, + GL_TOGGLE_CONTROL, + GL_SLIDER_CONTROL, + GL_CONTROL_MAX_TYPE +}; + +class GL_DialogControl +{ +protected: + int m_type; + +public: + + virtual ~GL_DialogControl() + { + } + virtual void draw(int& parentHorPos,int& parentVertPos,btScalar deltaTime)=0; + + int getType() const + { + return m_type; + } +}; + +struct GL_TextControl : public GL_DialogControl +{ +public: + + btAlignedObjectArray m_textLines; + + GL_TextControl() + { + m_type = GL_TEXT_CONTROL; + } + + virtual ~GL_TextControl() {} + + virtual void draw(int& parentHorPos,int& parentVertPos,btScalar deltaTime); +}; + + +struct GL_ToggleControl : public GL_DialogControl +{ + btCollisionObject* m_toggleBody; + GL_DialogWindow* m_parentWindow; + + const char* m_toggleText; + +public: + + bool m_active; + + + GL_ToggleControl(const char* toggleText,btCollisionObject* toggleBody, GL_DialogWindow* parentWindow) + :m_toggleBody(toggleBody), + m_parentWindow(parentWindow), + m_toggleText(toggleText), + m_active(false) + { + m_type = GL_TOGGLE_CONTROL; + } + + virtual void draw(int& parentHorPos,int& parentVertPos,btScalar deltaTime); +}; + +struct GL_SliderControl : public GL_DialogControl +{ + btCollisionObject* m_sliderBody; + GL_DialogWindow* m_parentWindow; + btScalar m_lowerLimit; + btScalar m_upperLimit; + btTypedConstraint* m_constraint; + btScalar m_fraction; + + const char* m_sliderText; +public: + + GL_SliderControl(const char* sliderText,btCollisionObject* sliderBody, GL_DialogWindow* parentWindow, btScalar lowerLimit,btScalar upperLimit,btTypedConstraint* constaint) + :m_sliderBody(sliderBody), + m_parentWindow(parentWindow), + m_lowerLimit(lowerLimit), + m_upperLimit(upperLimit), + m_constraint(constaint), + m_sliderText(sliderText) + { + m_type = GL_SLIDER_CONTROL; + } + + virtual void draw(int& parentHorPos,int& parentVertPos,btScalar deltaTime); + + btScalar btGetFraction() { return m_fraction; } + + btScalar getLowerLimit() + { + return m_lowerLimit; + } + btScalar getUpperLimit() + { + return m_upperLimit; + } + btTypedConstraint* getConstraint() + { + return m_constraint; + } +}; + +///Very basic OpenGL Graphical Userinterface Window with text, toggle, slider control +class GL_DialogWindow +{ + + int m_dialogHorPos; + int m_dialogVertPos; + int m_dialogWidth; + int m_dialogHeight; + + int m_screenWidth; + int m_screenHeight; + + const char* m_dialogTitle; + + //saved OpenGL settings + GLfloat m_PrevLineWidth; + GLint m_PrevTexEnv; + GLint m_PrevPolygonMode[2]; + GLint m_MaxClipPlanes; + GLint m_PrevTexture; + GLint m_PrevArrayBufferARB; + GLint m_PrevElementArrayBufferARB; + GLboolean m_PrevVertexProgramARB; + GLboolean m_PrevFragmentProgramARB; + GLuint m_PrevProgramObjectARB; + GLboolean m_PrevTexture3D; + GLboolean m_PrevActiveTexture1D[32]; + GLboolean m_PrevActiveTexture2D[32]; + GLboolean m_PrevActiveTexture3D[32]; + GLint m_PrevActiveTextureARB; + bool m_SupportTexRect; + GLboolean m_PrevTexRectARB; + GLint m_PrevBlendEquation; + GLint m_PrevBlendEquationRGB; + GLint m_PrevBlendEquationAlpha; + GLint m_PrevBlendSrcRGB; + GLint m_PrevBlendDstRGB; + GLint m_PrevBlendSrcAlpha; + GLint m_PrevBlendDstAlpha; + GLint m_ViewportInit[4]; + GLfloat m_ProjMatrixInit[16]; + + btCollisionObject* m_collisionObject; + + btAlignedObjectArray m_controls; + +protected: + + + void saveOpenGLState(); + void restoreOpenGLState(); + +// void drawLine(int _X0, int _Y0, int _X1, int _Y1, unsigned int _Color0, unsigned int _Color1, bool antiAliased); +// void drawRect(int horStart, int vertStart, int horEnd, int vertEnd, unsigned int argbColor00,unsigned int argbColor10,unsigned int argbColor01,unsigned int argbColor11); + +public: + + + GL_DialogWindow(int horPos,int vertPos,int dialogWidth,int dialogHeight,btCollisionObject* colObject, const char* dialogTitle); + + virtual ~GL_DialogWindow(); + + void draw(btScalar deltaTime); + + void setScreenSize(int width, int height); + + void setStartPosition(int dialogHorPos,int dialogVertPos); + + void addControl(GL_DialogControl* control) + { + m_controls.push_back(control); + } + + void removeControl(GL_DialogControl* control) + { + m_controls.remove(control); + } + + btCollisionObject* getCollisionObject() + { + return m_collisionObject; + } + + int getDialogHorPos() const + { + return m_dialogHorPos; + } + int getDialogVertPos() const + { + return m_dialogVertPos; + } + int getDialogWidth() const + { + return m_dialogWidth; + } + + int getDialogHeight() const + { + return m_dialogHeight; + } + int getScreenWidth() const + { + return m_screenWidth; + } + int getScreenHeight() const + { + return m_screenHeight; + } + + int getNumControls() const + { + return m_controls.size(); + } + + const GL_DialogControl* getControl(int index) const + { + return m_controls[index]; + } + GL_DialogControl* getControl(int index) + { + return m_controls[index]; + } +}; + +#endif //GL_DIALOG_WINDOW_H diff --git a/Demos/OpenGL/GL_ShapeDrawer.cpp b/Demos/OpenGL/GL_ShapeDrawer.cpp new file mode 100644 index 0000000..bfcb5f7 --- /dev/null +++ b/Demos/OpenGL/GL_ShapeDrawer.cpp @@ -0,0 +1,987 @@ +/* +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. +*/ + +#ifdef _WIN32 //needed for glut.h +#include +#endif +#include "GLDebugFont.h" + + + +#include "GlutStuff.h" +#include "GL_ShapeDrawer.h" +#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" +#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btConeShape.h" +#include "BulletCollision/CollisionShapes/btCylinderShape.h" +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btUniformScalingShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h" + +/// +#include "BulletCollision/CollisionShapes/btShapeHull.h" + +#include "LinearMath/btTransformUtil.h" + + +#include "LinearMath/btIDebugDraw.h" +//for debugmodes + +#include //printf debugging + +//#define USE_DISPLAY_LISTS 1 +#ifdef USE_DISPLAY_LISTS + +#include + +using namespace std; + +//Set for storing Display list per trimesh +struct TRIMESH_KEY +{ + btCollisionShape* m_shape; + GLuint m_dlist;//OpenGL display list +}; + +typedef map TRIMESH_KEY_MAP; + +typedef pair TRIMESH_KEY_PAIR; + +TRIMESH_KEY_MAP g_display_lists; + +class GlDisplaylistDrawcallback : public btTriangleCallback +{ +public: + + virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex) + { + + btVector3 diff1 = triangle[1] - triangle[0]; + btVector3 diff2 = triangle[2] - triangle[0]; + btVector3 normal = diff1.cross(diff2); + + normal.normalize(); + + glBegin(GL_TRIANGLES); + glColor3f(1, 1, 1); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + + //glColor3f(0, 1, 0); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + + //glColor3f(0, 1, 0); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glEnd(); + + /*glBegin(GL_LINES); + glColor3f(1, 1, 0); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glColor3f(1, 1, 0); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glColor3f(1, 1, 0); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glEnd();*/ + + + } +}; + +GLuint OGL_get_displaylist_for_shape(btCollisionShape * shape) +{ + TRIMESH_KEY_MAP::iterator map_iter; + + unsigned long key = (unsigned long)shape; + map_iter = g_display_lists.find(key); + if(map_iter!=g_display_lists.end()) + { + return map_iter->second.m_dlist; + } + + return 0; +} + +void OGL_displaylist_clean() +{ + TRIMESH_KEY_MAP::iterator map_iter,map_itend; + + map_iter = g_display_lists.begin(); + + while(map_iter!=map_itend) + { + glDeleteLists(map_iter->second.m_dlist,1); + map_iter++; + } + + g_display_lists.clear(); +} + + +void OGL_displaylist_register_shape(btCollisionShape * shape) +{ + btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + btVector3 aabbMin(-btScalar(BT_LARGE_FLOAT),-btScalar(BT_LARGE_FLOAT),-btScalar(BT_LARGE_FLOAT)); + GlDisplaylistDrawcallback drawCallback; + TRIMESH_KEY dlist; + + dlist.m_dlist = glGenLists(1); + dlist.m_shape = shape; + + unsigned long key = (unsigned long)shape; + + g_display_lists.insert(TRIMESH_KEY_PAIR(key,dlist)); + + glNewList(dlist.m_dlist,GL_COMPILE); + +// glEnable(GL_CULL_FACE); + + glCullFace(GL_BACK); + + if (shape->isConcave()) + { + btConcaveShape* concaveMesh = (btConcaveShape*) shape; + //todo pass camera, for some culling + concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax); + } + +// glDisable(GL_CULL_FACE); + + glEndList(); +} +#endif //USE_DISPLAY_LISTS + +void GL_ShapeDrawer::drawCoordSystem() { + glBegin(GL_LINES); + glColor3f(1, 0, 0); + glVertex3d(0, 0, 0); + glVertex3d(1, 0, 0); + glColor3f(0, 1, 0); + glVertex3d(0, 0, 0); + glVertex3d(0, 1, 0); + glColor3f(0, 0, 1); + glVertex3d(0, 0, 0); + glVertex3d(0, 0, 1); + glEnd(); + +} + + + + + +class GlDrawcallback : public btTriangleCallback +{ + +public: + + bool m_wireframe; + + GlDrawcallback() + :m_wireframe(false) + { + } + + virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex) + { + + (void)triangleIndex; + (void)partId; + + + if (m_wireframe) + { + glBegin(GL_LINES); + glColor3f(1, 0, 0); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glColor3f(0, 1, 0); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glColor3f(0, 0, 1); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glEnd(); + } else + { + glBegin(GL_TRIANGLES); + //glColor3f(1, 1, 1); + + + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glEnd(); + } + } +}; + +class TriangleGlDrawcallback : public btInternalTriangleIndexCallback +{ +public: + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + (void)triangleIndex; + (void)partId; + + + glBegin(GL_TRIANGLES);//LINES); + glColor3f(1, 0, 0); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glColor3f(0, 1, 0); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glColor3f(0, 0, 1); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glEnd(); + } +}; + + +void GL_ShapeDrawer::drawSphere(btScalar radius, int lats, int longs) +{ + int i, j; + for(i = 0; i <= lats; i++) { + btScalar lat0 = SIMD_PI * (-btScalar(0.5) + (btScalar) (i - 1) / lats); + btScalar z0 = radius*sin(lat0); + btScalar zr0 = radius*cos(lat0); + + btScalar lat1 = SIMD_PI * (-btScalar(0.5) + (btScalar) i / lats); + btScalar z1 = radius*sin(lat1); + btScalar zr1 = radius*cos(lat1); + + glBegin(GL_QUAD_STRIP); + for(j = 0; j <= longs; j++) { + btScalar lng = 2 * SIMD_PI * (btScalar) (j - 1) / longs; + btScalar x = cos(lng); + btScalar y = sin(lng); + glNormal3f(x * zr1, y * zr1, z1); + glVertex3f(x * zr1, y * zr1, z1); + glNormal3f(x * zr0, y * zr0, z0); + glVertex3f(x * zr0, y * zr0, z0); + } + glEnd(); + } +} + +void GL_ShapeDrawer::drawCylinder(float radius,float halfHeight, int upAxis) +{ + + + glPushMatrix(); + switch (upAxis) + { + case 0: + glRotatef(-90.0, 0.0, 1.0, 0.0); + glTranslatef(0.0, 0.0, -halfHeight); + break; + case 1: + glRotatef(-90.0, 1.0, 0.0, 0.0); + glTranslatef(0.0, 0.0, -halfHeight); + break; + case 2: + + glTranslatef(0.0, 0.0, -halfHeight); + break; + default: + { + btAssert(0); + } + + } + + GLUquadricObj *quadObj = gluNewQuadric(); + + //The gluCylinder subroutine draws a cylinder that is oriented along the z axis. + //The base of the cylinder is placed at z = 0; the top of the cylinder is placed at z=height. + //Like a sphere, the cylinder is subdivided around the z axis into slices and along the z axis into stacks. + + gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL); + gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH); + + gluDisk(quadObj,0,radius,15, 10); + + gluCylinder(quadObj, radius, radius, 2.f*halfHeight, 15, 10); + glTranslatef(0.0f, 0.0f, 2.f*halfHeight); + glRotatef(-180.0f, 0.0f, 1.0f, 0.0f); + gluDisk(quadObj,0.f,radius,15, 10); + + glPopMatrix(); + gluDeleteQuadric(quadObj); +} + +GL_ShapeDrawer::ShapeCache* GL_ShapeDrawer::cache(btConvexShape* shape) +{ + ShapeCache* sc=(ShapeCache*)shape->getUserPointer(); + if(!sc) + { + sc=new(btAlignedAlloc(sizeof(ShapeCache),16)) ShapeCache(shape); + sc->m_shapehull.buildHull(shape->getMargin()); + m_shapecaches.push_back(sc); + shape->setUserPointer(sc); + /* Build edges */ + const int ni=sc->m_shapehull.numIndices(); + const int nv=sc->m_shapehull.numVertices(); + const unsigned int* pi=sc->m_shapehull.getIndexPointer(); + const btVector3* pv=sc->m_shapehull.getVertexPointer(); + btAlignedObjectArray edges; + sc->m_edges.reserve(ni); + edges.resize(nv*nv,0); + for(int i=0;im_edges.push_back(ShapeCache::Edge()); + e=&sc->m_edges[sc->m_edges.size()-1]; + e->n[0]=nrm;e->n[1]=-nrm; + e->v[0]=a;e->v[1]=b; + } + else + { + e->n[1]=nrm; + } + } + } + } + return(sc); +} + +void renderSquareA(float x, float y, float z) +{ + glBegin(GL_LINE_LOOP); + glVertex3f(x, y, z); + glVertex3f(x + 10.f, y, z); + glVertex3f(x + 10.f, y + 10.f, z); + glVertex3f(x, y + 10.f, z); + glEnd(); +} + +inline void glDrawVector(const btVector3& v) { glVertex3d(v[0], v[1], v[2]); } + + +void GL_ShapeDrawer::drawOpenGL(btScalar* m, const btCollisionShape* shape, const btVector3& color,int debugMode,const btVector3& worldBoundsMin,const btVector3& worldBoundsMax) +{ + + if (shape->getShapeType() == CUSTOM_CONVEX_SHAPE_TYPE) + { + btVector3 org(m[12], m[13], m[14]); + btVector3 dx(m[0], m[1], m[2]); + btVector3 dy(m[4], m[5], m[6]); +// btVector3 dz(m[8], m[9], m[10]); + const btBoxShape* boxShape = static_cast(shape); + btVector3 halfExtent = boxShape->getHalfExtentsWithMargin(); + dx *= halfExtent[0]; + dy *= halfExtent[1]; +// dz *= halfExtent[2]; + glColor3f(1,1,1); + glDisable(GL_LIGHTING); + glLineWidth(2); + + glBegin(GL_LINE_LOOP); + glDrawVector(org - dx - dy); + glDrawVector(org - dx + dy); + glDrawVector(org + dx + dy); + glDrawVector(org + dx - dy); + glEnd(); + return; + } + else if((shape->getShapeType() == BOX_SHAPE_PROXYTYPE) && (debugMode & btIDebugDraw::DBG_FastWireframe)) + { + btVector3 org(m[12], m[13], m[14]); + btVector3 dx(m[0], m[1], m[2]); + btVector3 dy(m[4], m[5], m[6]); + btVector3 dz(m[8], m[9], m[10]); + const btBoxShape* boxShape = static_cast(shape); + btVector3 halfExtent = boxShape->getHalfExtentsWithMargin(); + dx *= halfExtent[0]; + dy *= halfExtent[1]; + dz *= halfExtent[2]; + glBegin(GL_LINE_LOOP); + glDrawVector(org - dx - dy - dz); + glDrawVector(org + dx - dy - dz); + glDrawVector(org + dx + dy - dz); + glDrawVector(org - dx + dy - dz); + glDrawVector(org - dx + dy + dz); + glDrawVector(org + dx + dy + dz); + glDrawVector(org + dx - dy + dz); + glDrawVector(org - dx - dy + dz); + glEnd(); + glBegin(GL_LINES); + glDrawVector(org + dx - dy - dz); + glDrawVector(org + dx - dy + dz); + glDrawVector(org + dx + dy - dz); + glDrawVector(org + dx + dy + dz); + glDrawVector(org - dx - dy - dz); + glDrawVector(org - dx + dy - dz); + glDrawVector(org - dx - dy + dz); + glDrawVector(org - dx + dy + dz); + glEnd(); + return; + } + + glPushMatrix(); + btglMultMatrix(m); + + + if (shape->getShapeType() == UNIFORM_SCALING_SHAPE_PROXYTYPE) + { + const btUniformScalingShape* scalingShape = static_cast(shape); + const btConvexShape* convexShape = scalingShape->getChildShape(); + float scalingFactor = (float)scalingShape->getUniformScalingFactor(); + { + btScalar tmpScaling[4][4]={{scalingFactor,0,0,0}, + {0,scalingFactor,0,0}, + {0,0,scalingFactor,0}, + {0,0,0,1}}; + + drawOpenGL( (btScalar*)tmpScaling,convexShape,color,debugMode,worldBoundsMin,worldBoundsMax); + } + glPopMatrix(); + return; + } + + if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) + { + const btCompoundShape* compoundShape = static_cast(shape); + for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* colShape = compoundShape->getChildShape(i); + btScalar childMat[16]; + childTrans.getOpenGLMatrix(childMat); + drawOpenGL(childMat,colShape,color,debugMode,worldBoundsMin,worldBoundsMax); + } + + } else + { + if(m_textureenabled&&(!m_textureinitialized)) + { + GLubyte* image=new GLubyte[256*256*3]; + for(int y=0;y<256;++y) + { + const int t=y>>4; + GLubyte* pi=image+y*256*3; + for(int x=0;x<256;++x) + { + const int s=x>>4; + const GLubyte b=180; + GLubyte c=b+((s+t&1)&1)*(255-b); + pi[0]=pi[1]=pi[2]=c;pi+=3; + } + } + + glGenTextures(1,(GLuint*)&m_texturehandle); + glBindTexture(GL_TEXTURE_2D,m_texturehandle); + glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); + gluBuild2DMipmaps(GL_TEXTURE_2D,3,256,256,GL_RGB,GL_UNSIGNED_BYTE,image); + delete[] image; + + + } + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glScalef(0.025f,0.025f,0.025f); + glMatrixMode(GL_MODELVIEW); + + static const GLfloat planex[]={1,0,0,0}; + // static const GLfloat planey[]={0,1,0,0}; + static const GLfloat planez[]={0,0,1,0}; + glTexGenfv(GL_S,GL_OBJECT_PLANE,planex); + glTexGenfv(GL_T,GL_OBJECT_PLANE,planez); + glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR); + glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + m_textureinitialized=true; + + + + + //drawCoordSystem(); + + //glPushMatrix(); + glEnable(GL_COLOR_MATERIAL); + if(m_textureenabled) + { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,m_texturehandle); + } else + { + glDisable(GL_TEXTURE_2D); + } + + + glColor3f(color.x(),color.y(), color.z()); + + bool useWireframeFallback = true; + + if (!(debugMode & btIDebugDraw::DBG_DrawWireframe)) + { + ///you can comment out any of the specific cases, and use the default + + ///the benefit of 'default' is that it approximates the actual collision shape including collision margin + //int shapetype=m_textureenabled?MAX_BROADPHASE_COLLISION_TYPES:shape->getShapeType(); + int shapetype=shape->getShapeType(); + switch (shapetype) + { + + case SPHERE_SHAPE_PROXYTYPE: + { + const btSphereShape* sphereShape = static_cast(shape); + float radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin + drawSphere(radius,10,10); + useWireframeFallback = false; + break; + } + + case BOX_SHAPE_PROXYTYPE: + { + const btBoxShape* boxShape = static_cast(shape); + btVector3 halfExtent = boxShape->getHalfExtentsWithMargin(); + + static int indices[36] = { + 0,1,2, + 3,2,1, + 4,0,6, + 6,0,2, + 5,1,4, + 4,1,0, + 7,3,1, + 7,1,5, + 5,4,7, + 7,4,6, + 7,2,3, + 7,6,2}; + + btVector3 vertices[8]={ + btVector3(halfExtent[0],halfExtent[1],halfExtent[2]), + btVector3(-halfExtent[0],halfExtent[1],halfExtent[2]), + btVector3(halfExtent[0],-halfExtent[1],halfExtent[2]), + btVector3(-halfExtent[0],-halfExtent[1],halfExtent[2]), + btVector3(halfExtent[0],halfExtent[1],-halfExtent[2]), + btVector3(-halfExtent[0],halfExtent[1],-halfExtent[2]), + btVector3(halfExtent[0],-halfExtent[1],-halfExtent[2]), + btVector3(-halfExtent[0],-halfExtent[1],-halfExtent[2])}; +#if 1 + glBegin (GL_TRIANGLES); + int si=36; + for (int i=0;i(shape); + int upIndex = coneShape->getConeUpIndex(); + float radius = coneShape->getRadius();//+coneShape->getMargin(); + float height = coneShape->getHeight();//+coneShape->getMargin(); + switch (upIndex) + { + case 0: + glRotatef(90.0, 0.0, 1.0, 0.0); + break; + case 1: + glRotatef(-90.0, 1.0, 0.0, 0.0); + break; + case 2: + break; + default: + { + } + }; + + glTranslatef(0.0, 0.0, -0.5*height); + glutSolidCone(radius,height,10,10); + useWireframeFallback = false; + break; + + } +#endif + + case STATIC_PLANE_PROXYTYPE: + { + const btStaticPlaneShape* staticPlaneShape = static_cast(shape); + btScalar planeConst = staticPlaneShape->getPlaneConstant(); + const btVector3& planeNormal = staticPlaneShape->getPlaneNormal(); + btVector3 planeOrigin = planeNormal * planeConst; + btVector3 vec0,vec1; + btPlaneSpace1(planeNormal,vec0,vec1); + btScalar vecLen = 100.f; + btVector3 pt0 = planeOrigin + vec0*vecLen; + btVector3 pt1 = planeOrigin - vec0*vecLen; + btVector3 pt2 = planeOrigin + vec1*vecLen; + btVector3 pt3 = planeOrigin - vec1*vecLen; + glBegin(GL_LINES); + glVertex3f(pt0.getX(),pt0.getY(),pt0.getZ()); + glVertex3f(pt1.getX(),pt1.getY(),pt1.getZ()); + glVertex3f(pt2.getX(),pt2.getY(),pt2.getZ()); + glVertex3f(pt3.getX(),pt3.getY(),pt3.getZ()); + glEnd(); + + + break; + + } + +/* + case CYLINDER_SHAPE_PROXYTYPE: + { + const btCylinderShape* cylinder = static_cast(shape); + int upAxis = cylinder->getUpAxis(); + + + float radius = cylinder->getRadius(); + float halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis]; + + drawCylinder(radius,halfHeight,upAxis); + + break; + } +*/ + + case MULTI_SPHERE_SHAPE_PROXYTYPE: + { + const btMultiSphereShape* multiSphereShape = static_cast(shape); + + btTransform childTransform; + childTransform.setIdentity(); + + + for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--) + { + btSphereShape sc(multiSphereShape->getSphereRadius(i)); + childTransform.setOrigin(multiSphereShape->getSpherePosition(i)); + btScalar childMat[16]; + childTransform.getOpenGLMatrix(childMat); + drawOpenGL(childMat,&sc,color,debugMode,worldBoundsMin,worldBoundsMax); + } + + break; + } + + default: + { + if (shape->isConvex()) + { + const btConvexPolyhedron* poly = shape->isPolyhedral() ? ((btPolyhedralConvexShape*) shape)->getConvexPolyhedron() : 0; + if (poly) + { + int i; + glBegin (GL_TRIANGLES); + for (i=0;im_faces.size();i++) + { + btVector3 centroid(0,0,0); + int numVerts = poly->m_faces[i].m_indices.size(); + if (numVerts>2) + { + btVector3 v1 = poly->m_vertices[poly->m_faces[i].m_indices[0]]; + for (int v=0;vm_faces[i].m_indices.size()-2;v++) + { + + btVector3 v2 = poly->m_vertices[poly->m_faces[i].m_indices[v+1]]; + btVector3 v3 = poly->m_vertices[poly->m_faces[i].m_indices[v+2]]; + btVector3 normal = (v3-v1).cross(v2-v1); + normal.normalize (); + glNormal3f(normal.getX(),normal.getY(),normal.getZ()); + glVertex3f (v1.x(), v1.y(), v1.z()); + glVertex3f (v2.x(), v2.y(), v2.z()); + glVertex3f (v3.x(), v3.y(), v3.z()); + } + } + } + glEnd (); + } else + { + ShapeCache* sc=cache((btConvexShape*)shape); + //glutSolidCube(1.0); + btShapeHull* hull = &sc->m_shapehull/*(btShapeHull*)shape->getUserPointer()*/; + + if (hull->numTriangles () > 0) + { + int index = 0; + const unsigned int* idx = hull->getIndexPointer(); + const btVector3* vtx = hull->getVertexPointer(); + + glBegin (GL_TRIANGLES); + + for (int i = 0; i < hull->numTriangles (); i++) + { + int i1 = index++; + int i2 = index++; + int i3 = index++; + btAssert(i1 < hull->numIndices () && + i2 < hull->numIndices () && + i3 < hull->numIndices ()); + + int index1 = idx[i1]; + int index2 = idx[i2]; + int index3 = idx[i3]; + btAssert(index1 < hull->numVertices () && + index2 < hull->numVertices () && + index3 < hull->numVertices ()); + + btVector3 v1 = vtx[index1]; + btVector3 v2 = vtx[index2]; + btVector3 v3 = vtx[index3]; + btVector3 normal = (v3-v1).cross(v2-v1); + normal.normalize (); + glNormal3f(normal.getX(),normal.getY(),normal.getZ()); + glVertex3f (v1.x(), v1.y(), v1.z()); + glVertex3f (v2.x(), v2.y(), v2.z()); + glVertex3f (v3.x(), v3.y(), v3.z()); + + } + glEnd (); + + } + } + } + } + } + + } + + + glNormal3f(0,1,0); + + + /// for polyhedral shapes + if (debugMode==btIDebugDraw::DBG_DrawFeaturesText && (shape->isPolyhedral())) + { + btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape; + + { + + glColor3f(1.f, 1.f, 1.f); + int i; + for (i=0;igetNumVertices();i++) + { + btVector3 vtx; + polyshape->getVertex(i,vtx); + char buf[12]; + sprintf(buf," %d",i); + //btDrawString(BMF_GetFont(BMF_kHelvetica10),buf); + } + + for (i=0;igetNumPlanes();i++) + { + btVector3 normal; + btVector3 vtx; + polyshape->getPlane(normal,vtx,i); + //btScalar d = vtx.dot(normal); + + //char buf[12]; + //sprintf(buf," plane %d",i); + //btDrawString(BMF_GetFont(BMF_kHelvetica10),buf); + + } + } + + } + + +#ifdef USE_DISPLAY_LISTS + + if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE||shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE) + { + GLuint dlist = OGL_get_displaylist_for_shape((btCollisionShape * )shape); + if (dlist) + { + glCallList(dlist); + } + else + { +#else + if (shape->isConcave() && !shape->isInfinite()) + { + btConcaveShape* concaveMesh = (btConcaveShape*) shape; + + GlDrawcallback drawCallback; + drawCallback.m_wireframe = (debugMode & btIDebugDraw::DBG_DrawWireframe)!=0; + + concaveMesh->processAllTriangles(&drawCallback,worldBoundsMin,worldBoundsMax); + + } +#endif + +#ifdef USE_DISPLAY_LISTS + } +} +#endif + + + + + + } + glPopMatrix(); + +} + +// +void GL_ShapeDrawer::drawShadow(btScalar* m,const btVector3& extrusion,const btCollisionShape* shape,const btVector3& worldBoundsMin,const btVector3& worldBoundsMax) +{ + glPushMatrix(); + btglMultMatrix(m); + if(shape->getShapeType() == UNIFORM_SCALING_SHAPE_PROXYTYPE) + { + const btUniformScalingShape* scalingShape = static_cast(shape); + const btConvexShape* convexShape = scalingShape->getChildShape(); + float scalingFactor = (float)scalingShape->getUniformScalingFactor(); + btScalar tmpScaling[4][4]={ {scalingFactor,0,0,0}, + {0,scalingFactor,0,0}, + {0,0,scalingFactor,0}, + {0,0,0,1}}; + drawShadow((btScalar*)tmpScaling,extrusion,convexShape,worldBoundsMin,worldBoundsMax); + glPopMatrix(); + return; + } + else if(shape->getShapeType()==COMPOUND_SHAPE_PROXYTYPE) + { + const btCompoundShape* compoundShape = static_cast(shape); + for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* colShape = compoundShape->getChildShape(i); + btScalar childMat[16]; + childTrans.getOpenGLMatrix(childMat); + drawShadow(childMat,extrusion*childTrans.getBasis(),colShape,worldBoundsMin,worldBoundsMax); + } + } + else + { + // bool useWireframeFallback = true; + if (shape->isConvex()) + { + ShapeCache* sc=cache((btConvexShape*)shape); + btShapeHull* hull =&sc->m_shapehull; + glBegin(GL_QUADS); + for(int i=0;im_edges.size();++i) + { + const btScalar d=btDot(sc->m_edges[i].n[0],extrusion); + if((d*btDot(sc->m_edges[i].n[1],extrusion))<0) + { + const int q= d<0?1:0; + const btVector3& a= hull->getVertexPointer()[sc->m_edges[i].v[q]]; + const btVector3& b= hull->getVertexPointer()[sc->m_edges[i].v[1-q]]; + glVertex3f(a[0],a[1],a[2]); + glVertex3f(b[0],b[1],b[2]); + glVertex3f(b[0]+extrusion[0],b[1]+extrusion[1],b[2]+extrusion[2]); + glVertex3f(a[0]+extrusion[0],a[1]+extrusion[1],a[2]+extrusion[2]); + } + } + glEnd(); + } + + } + + + + + if (shape->isConcave())//>getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE||shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE) + // if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + btConcaveShape* concaveMesh = (btConcaveShape*) shape; + + GlDrawcallback drawCallback; + drawCallback.m_wireframe = false; + + concaveMesh->processAllTriangles(&drawCallback,worldBoundsMin,worldBoundsMax); + + } + glPopMatrix(); + +} + +// +GL_ShapeDrawer::GL_ShapeDrawer() +{ + m_texturehandle = 0; + m_textureenabled = false; + m_textureinitialized = false; +} + +GL_ShapeDrawer::~GL_ShapeDrawer() +{ + int i; + for (i=0;i~ShapeCache(); + btAlignedFree(m_shapecaches[i]); + } + m_shapecaches.clear(); + if(m_textureinitialized) + { + glDeleteTextures(1,(const GLuint*) &m_texturehandle); + } +} + + diff --git a/Demos/OpenGL/GL_ShapeDrawer.h b/Demos/OpenGL/GL_ShapeDrawer.h new file mode 100644 index 0000000..65bf29d --- /dev/null +++ b/Demos/OpenGL/GL_ShapeDrawer.h @@ -0,0 +1,70 @@ +/* +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 GL_SHAPE_DRAWER_H +#define GL_SHAPE_DRAWER_H + +class btCollisionShape; +class btShapeHull; +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btVector3.h" + +#include "BulletCollision/CollisionShapes/btShapeHull.h" + +/// OpenGL shape drawing +class GL_ShapeDrawer +{ +protected: + struct ShapeCache + { + struct Edge { btVector3 n[2];int v[2]; }; + ShapeCache(btConvexShape* s) : m_shapehull(s) {} + btShapeHull m_shapehull; + btAlignedObjectArray m_edges; + }; + //clean-up memory of dynamically created shape hulls + btAlignedObjectArray m_shapecaches; + unsigned int m_texturehandle; + bool m_textureenabled; + bool m_textureinitialized; + + + ShapeCache* cache(btConvexShape*); + +public: + GL_ShapeDrawer(); + + virtual ~GL_ShapeDrawer(); + + ///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); + virtual void drawShadow(btScalar* m, const btVector3& extrusion,const btCollisionShape* shape,const btVector3& worldBoundsMin,const btVector3& worldBoundsMax); + + bool enableTexture(bool enable) { bool p=m_textureenabled;m_textureenabled=enable;return(p); } + bool hasTextureEnabled() const + { + return m_textureenabled; + } + + static void drawCylinder(float radius,float halfHeight, int upAxis); + void drawSphere(btScalar r, int lats, int longs); + static void drawCoordSystem(); + +}; + +void OGL_displaylist_register_shape(btCollisionShape * shape); +void OGL_displaylist_clean(); + +#endif //GL_SHAPE_DRAWER_H + diff --git a/Demos/OpenGL/GL_Simplex1to4.cpp b/Demos/OpenGL/GL_Simplex1to4.cpp new file mode 100644 index 0000000..b364a1b --- /dev/null +++ b/Demos/OpenGL/GL_Simplex1to4.cpp @@ -0,0 +1,76 @@ +/* +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 "GL_Simplex1to4.h" +#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" +#include "GL_ShapeDrawer.h" +#ifdef _WIN32 +#include +#endif + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#else +#include +#endif +#include "GlutStuff.h" +#include "LinearMath/btTransform.h" + +GL_Simplex1to4::GL_Simplex1to4() +:m_simplexSolver(0) +{ +} + +/// +/// Debugging method calcClosest calculates the closest point to the origin, using m_simplexSolver +/// +void GL_Simplex1to4::calcClosest(btScalar* m) +{ + btTransform tr; + tr.setFromOpenGLMatrix(m); + + + + GL_ShapeDrawer::drawCoordSystem(); + + if (m_simplexSolver) + { + m_simplexSolver->reset(); + bool res; + + btVector3 v; + + for (int i=0;iaddVertex(v,v,btVector3(0.f,0.f,0.f)); + res = m_simplexSolver->closest(v); + } + + //draw v? + glDisable(GL_LIGHTING); + glBegin(GL_LINES); + btglColor3(1.f, 0.f, 0.f); + btglVertex3(0.f, 0.f, 0.f); + btglVertex3(v.x(),v.y(),v.z()); + glEnd(); + + glEnable(GL_LIGHTING); + + + } + +} diff --git a/Demos/OpenGL/GL_Simplex1to4.h b/Demos/OpenGL/GL_Simplex1to4.h new file mode 100644 index 0000000..c75e357 --- /dev/null +++ b/Demos/OpenGL/GL_Simplex1to4.h @@ -0,0 +1,40 @@ +/* +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 GL_SIMPLEX_1TO4_H +#define GL_SIMPLEX_1TO4_H + +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" + +#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" + +///GL_Simplex1to4 is a class to debug a Simplex Solver with 1 to 4 points. +///Can be used by GJK. +class GL_Simplex1to4 : public btBU_Simplex1to4 +{ + btSimplexSolverInterface* m_simplexSolver; + + public: + + GL_Simplex1to4(); + + void calcClosest(btScalar* m); + + void setSimplexSolver(btSimplexSolverInterface* simplexSolver) { + m_simplexSolver = simplexSolver; + } + +}; + +#endif //GL_SIMPLEX_1TO4_H diff --git a/Demos/OpenGL/GlutDemoApplication.cpp b/Demos/OpenGL/GlutDemoApplication.cpp new file mode 100644 index 0000000..0ceaede --- /dev/null +++ b/Demos/OpenGL/GlutDemoApplication.cpp @@ -0,0 +1,87 @@ + +#ifndef _WINDOWS + +#include "GlutDemoApplication.h" + +#include "GlutStuff.h" + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" + +void GlutDemoApplication::updateModifierKeys() +{ + m_modifierKeys = 0; + if (glutGetModifiers() & GLUT_ACTIVE_ALT) + m_modifierKeys |= BT_ACTIVE_ALT; + + if (glutGetModifiers() & GLUT_ACTIVE_CTRL) + m_modifierKeys |= BT_ACTIVE_CTRL; + + if (glutGetModifiers() & GLUT_ACTIVE_SHIFT) + m_modifierKeys |= BT_ACTIVE_SHIFT; +} + +void GlutDemoApplication::specialKeyboard(int key, int x, int y) +{ + (void)x; + (void)y; + + switch (key) + { + case GLUT_KEY_F1: + { + + break; + } + + case GLUT_KEY_F2: + { + + break; + } + + + case GLUT_KEY_END: + { + int numObj = getDynamicsWorld()->getNumCollisionObjects(); + if (numObj) + { + btCollisionObject* obj = getDynamicsWorld()->getCollisionObjectArray()[numObj-1]; + + getDynamicsWorld()->removeCollisionObject(obj); + btRigidBody* body = btRigidBody::upcast(obj); + if (body && body->getMotionState()) + { + delete body->getMotionState(); + } + delete obj; + + + } + break; + } + case GLUT_KEY_LEFT : stepLeft(); break; + case GLUT_KEY_RIGHT : stepRight(); break; + case GLUT_KEY_UP : stepFront(); break; + case GLUT_KEY_DOWN : stepBack(); break; + case GLUT_KEY_PAGE_UP : zoomIn(); break; + case GLUT_KEY_PAGE_DOWN : zoomOut(); break; + case GLUT_KEY_HOME : toggleIdle(); break; + default: + // std::cout << "unused (special) key : " << key << std::endl; + break; + } + + glutPostRedisplay(); + +} + +void GlutDemoApplication::swapBuffers() +{ + glutSwapBuffers(); + +} + +#endif //_WINDOWS + + diff --git a/Demos/OpenGL/GlutDemoApplication.h b/Demos/OpenGL/GlutDemoApplication.h new file mode 100644 index 0000000..e2727a7 --- /dev/null +++ b/Demos/OpenGL/GlutDemoApplication.h @@ -0,0 +1,34 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 GLUT_DEMO_APPLICATION_H +#define GLUT_DEMO_APPLICATION_H + +#include "DemoApplication.h" + +class GlutDemoApplication : public DemoApplication +{ +public: + + void specialKeyboard(int key, int x, int y); + + virtual void swapBuffers(); + + virtual void updateModifierKeys(); + +}; +#endif //GLUT_DEMO_APPLICATION_H + diff --git a/Demos/OpenGL/GlutStuff.cpp b/Demos/OpenGL/GlutStuff.cpp new file mode 100644 index 0000000..d8de3e7 --- /dev/null +++ b/Demos/OpenGL/GlutStuff.cpp @@ -0,0 +1,120 @@ +/* +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 _WINDOWS + +#include "DemoApplication.h" + +//glut is C code, this global gDemoApplication links glut to the C++ demo +static DemoApplication* gDemoApplication = 0; + + +#include "GlutStuff.h" + +static void glutKeyboardCallback(unsigned char key, int x, int y) +{ + gDemoApplication->keyboardCallback(key,x,y); +} + +static void glutKeyboardUpCallback(unsigned char key, int x, int y) +{ + gDemoApplication->keyboardUpCallback(key,x,y); +} + +static void glutSpecialKeyboardCallback(int key, int x, int y) +{ + gDemoApplication->specialKeyboard(key,x,y); +} + +static void glutSpecialKeyboardUpCallback(int key, int x, int y) +{ + gDemoApplication->specialKeyboardUp(key,x,y); +} + + +static void glutReshapeCallback(int w, int h) +{ + gDemoApplication->reshape(w,h); +} + +static void glutMoveAndDisplayCallback() +{ + gDemoApplication->moveAndDisplay(); +} + +static void glutMouseFuncCallback(int button, int state, int x, int y) +{ + gDemoApplication->mouseFunc(button,state,x,y); +} + + +static void glutMotionFuncCallback(int x,int y) +{ + gDemoApplication->mouseMotionFunc(x,y); +} + + +static void glutDisplayCallback(void) +{ + gDemoApplication->displayCallback(); +} + + +int glutmain(int argc, char **argv,int width,int height,const char* title,DemoApplication* demoApp) { + + gDemoApplication = demoApp; + + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL); + glutInitWindowPosition(0, 0); + glutInitWindowSize(width, height); + glutCreateWindow(title); +#ifdef BT_USE_FREEGLUT + glutSetOption (GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS); +#endif + + gDemoApplication->myinit(); + + glutKeyboardFunc(glutKeyboardCallback); + glutKeyboardUpFunc(glutKeyboardUpCallback); + glutSpecialFunc(glutSpecialKeyboardCallback); + glutSpecialUpFunc(glutSpecialKeyboardUpCallback); + + glutReshapeFunc(glutReshapeCallback); + //createMenu(); + glutIdleFunc(glutMoveAndDisplayCallback); + glutMouseFunc(glutMouseFuncCallback); + glutPassiveMotionFunc(glutMotionFuncCallback); + glutMotionFunc(glutMotionFuncCallback); + glutDisplayFunc( glutDisplayCallback ); + + glutMoveAndDisplayCallback(); + +//enable vsync to avoid tearing on Apple (todo: for Windows) + +#if defined(__APPLE__) && !defined (VMDMESA) +int swap_interval = 1; +CGLContextObj cgl_context = CGLGetCurrentContext(); +CGLSetParameter(cgl_context, kCGLCPSwapInterval, &swap_interval); +#endif + + + + glutMainLoop(); + return 0; +} + + +#endif //_WINDOWS diff --git a/Demos/OpenGL/GlutStuff.h b/Demos/OpenGL/GlutStuff.h new file mode 100644 index 0000000..0f618be --- /dev/null +++ b/Demos/OpenGL/GlutStuff.h @@ -0,0 +1,86 @@ +/* +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 GLUT_STUFF_H +#define GLUT_STUFF_H + +#ifdef _WIN32//for glut.h +#include +#endif + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#include +#else + + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif //_WINDOWS +#endif //APPLE + +#ifdef _WINDOWS +#define BT_ACTIVE_ALT VK_LMENU + +#else +#define BT_KEY_K 'k' +#define BT_KEY_LEFT GLUT_KEY_LEFT +#define BT_KEY_RIGHT GLUT_KEY_RIGHT +#define BT_KEY_UP GLUT_KEY_UP +#define BT_KEY_DOWN GLUT_KEY_DOWN +#define BT_KEY_F1 GLUT_KEY_F1 +#define BT_KEY_F2 GLUT_KEY_F2 +#define BT_KEY_F3 GLUT_KEY_F3 +#define BT_KEY_F4 GLUT_KEY_F4 +#define BT_KEY_F5 GLUT_KEY_F5 +#define BT_KEY_PAGEUP GLUT_KEY_PAGE_UP +#define BT_KEY_PAGEDOWN GLUT_KEY_PAGE_DOWN +#define BT_KEY_END GLUT_KEY_END +#define BT_KEY_HOME GLUT_KEY_HOME +#define BT_ACTIVE_ALT GLUT_ACTIVE_ALT +#define BT_ACTIVE_CTRL GLUT_ACTIVE_ALT +#define BT_ACTIVE_SHIFT GLUT_ACTIVE_SHIFT +#endif + +#if BT_USE_FREEGLUT +#include "GL/freeglut_ext.h" //to be able to return from glutMainLoop() +#endif + + + +class DemoApplication; + +int glutmain(int argc, char **argv,int width,int height,const char* title,DemoApplication* demoApp); + +#if defined(BT_USE_DOUBLE_PRECISION) +#define btglLoadMatrix glLoadMatrixd +#define btglMultMatrix glMultMatrixd +#define btglColor3 glColor3d +#define btglVertex3 glVertex3d +#else +#define btglLoadMatrix glLoadMatrixf +#define btglMultMatrix glMultMatrixf +#define btglColor3 glColor3f +#define btglVertex3 glVertex3d +#endif + +#endif //GLUT_STUFF_H diff --git a/Demos/OpenGL/Makefile.am b/Demos/OpenGL/Makefile.am new file mode 100644 index 0000000..11eeed4 --- /dev/null +++ b/Demos/OpenGL/Makefile.am @@ -0,0 +1,12 @@ +noinst_LIBRARIES = libbulletopenglsupport.a + +libbulletopenglsupport_a_SOURCES = \ + DemoApplication.cpp GLDebugDrawer.h GL_Simplex1to4.cpp \ + GLDebugFont.cpp GLDebugFont.h GlutDemoApplication.cpp GlutDemoApplication.h \ + GlutStuff.h \ + DemoApplication.h GL_ShapeDrawer.cpp \ + GL_Simplex1to4.h RenderTexture.cpp \ + DebugCastResult.h GLDebugDrawer.cpp \ + GL_ShapeDrawer.h GlutStuff.cpp RenderTexture.h + +INCLUDES=-I../../src diff --git a/Demos/OpenGL/RenderTexture.cpp b/Demos/OpenGL/RenderTexture.cpp new file mode 100644 index 0000000..2c8b88b --- /dev/null +++ b/Demos/OpenGL/RenderTexture.cpp @@ -0,0 +1,86 @@ +/* +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 "RenderTexture.h" +#include + + +renderTexture::renderTexture(int width,int height) +:m_height(height),m_width(width) +{ + m_buffer = new unsigned char[m_width*m_height*4]; + + //clear screen + memset(m_buffer,0,m_width*m_height*4); + + //clear screen version 2 + for (int x=0;x>=1; + y++; + } + x++; + } + //xx+=16; + xx+=10; + } +} + +renderTexture::~renderTexture() +{ + delete [] m_buffer; +} + + + diff --git a/Demos/OpenGL/RenderTexture.h b/Demos/OpenGL/RenderTexture.h new file mode 100644 index 0000000..1aee51d --- /dev/null +++ b/Demos/OpenGL/RenderTexture.h @@ -0,0 +1,73 @@ +/* +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 RENDER_TEXTURE_H +#define RENDER_TEXTURE_H + +#include "LinearMath/btVector3.h" +#include "GLDebugFont.h" + +/// +///renderTexture provides a software-render context (setpixel/printf) +/// +class renderTexture +{ + int m_height; + int m_width; + unsigned char* m_buffer; + +public: + + renderTexture(int width,int height); + ~renderTexture(); + + ///rgba input is in range [0..1] for each component + inline void setPixel(int x,int y,const btVector4& rgba) + { + unsigned char* pixel = &m_buffer[ (x+y*m_width) * 4]; + + pixel[0] = (unsigned char)(255.*rgba.getX()); + pixel[1] = (unsigned char)(255.*rgba.getY()); + pixel[2] = (unsigned char)(255.*rgba.getZ()); + pixel[3] = (unsigned char)(255.*rgba.getW()); + } + + inline void addPixel(int x,int y,const btVector4& rgba) + { + unsigned char* pixel = &m_buffer[ (x+y*m_width) * 4]; + pixel[0] = (unsigned char)btMin(btScalar(255.f),((btScalar)pixel[0] + btScalar(255.f)*rgba.getX())); + pixel[1] = (unsigned char)btMin(btScalar(255.f),((btScalar)pixel[1] + btScalar(255.f)*rgba.getY())); + pixel[2] = (unsigned char)btMin(btScalar(255.f),((btScalar)pixel[2] + btScalar(255.f)*rgba.getZ())); +// pixel[3] = (unsigned char)btMin(btScalar(255.f),((btScalar)pixel[3] + btScalar(255.f)*rgba.getW())); + } + + inline btVector4 getPixel(int x,int y) + { + unsigned char* pixel = &m_buffer[ (x+y*m_width) * 4]; + return btVector4(pixel[0]*1.f/255.f, + pixel[1]*1.f/255.f, + pixel[2]*1.f/255.f, + pixel[3]*1.f/255.f); + } + + const unsigned char* getBuffer() const { return m_buffer;} + int getWidth() const { return m_width;} + int getHeight() const { return m_height;} + void grapicalPrintf(char* str, void* fontData, int startx = 0,int starty=0); + +}; + +#endif //RENDER_TEXTURE_H + diff --git a/Demos/OpenGL/Win32AppMain.cpp b/Demos/OpenGL/Win32AppMain.cpp new file mode 100644 index 0000000..84f48a3 --- /dev/null +++ b/Demos/OpenGL/Win32AppMain.cpp @@ -0,0 +1,405 @@ +#ifdef _WINDOWS +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2010 Erwin Coumans http://bulletphysics.org + +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 +#include + + +#include "DemoApplication.h" + +#include "GLDebugDrawer.h" +#include "GLDebugFont.h" + +#include "BulletDynamics/Dynamics/btDynamicsWorld.h" + +/// This Win32AppMain is shared code between all demos. +/// The actual demo, derived from DemoApplication is created using 'createDemo', in a separate .cpp file +DemoApplication* gDemoApplication = 0; +DemoApplication* createDemo(); + + +// Function Declarations + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC); +void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC); +static bool sOpenGLInitialized = false; +static int sWidth = 0; +static int sHeight =0; +static int quitRequest = 0; + +// WinMain + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPSTR lpCmdLine, int iCmdShow) +{ + WNDCLASS wc; + HWND hWnd; + HDC hDC; + HGLRC hRC; + MSG msg; + BOOL quit = FALSE; + float theta = 0.0f; + + gDemoApplication = createDemo(); + + + // register window class + wc.style = CS_OWNDC; + wc.lpfnWndProc = WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); + wc.hCursor = LoadCursor( NULL, IDC_ARROW ); + wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ); + wc.lpszMenuName = NULL; + wc.lpszClassName = "BulletPhysics"; + RegisterClass( &wc ); + + // create main window + hWnd = CreateWindow( + "BulletPhysics", "Bullet Physics Sample. http://bulletphysics.org", + WS_CAPTION | WS_VISIBLE | WS_OVERLAPPEDWINDOW, +// 0, 0, 640, 480, + 0, 0, 1024, 768, + NULL, NULL, hInstance, NULL ); + + // enable OpenGL for the window + EnableOpenGL( hWnd, &hDC, &hRC ); + + + GLDebugDrawer debugDraw; + gDemoApplication->myinit(); + //gDemoApplication->reshape(1024, 768); + gDemoApplication->initPhysics(); + if (gDemoApplication->getDynamicsWorld()) + gDemoApplication->getDynamicsWorld()->setDebugDrawer(&debugDraw); + + gDemoApplication->reshape(sWidth,sHeight); + + // program main loop + while ( !quit ) + { + + // check for messages + if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) + { + + // handle or dispatch messages + if ( msg.message == WM_QUIT ) + { + quit = TRUE; + } + else + { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + +// gDemoApplication->displayCallback(); + + + }; + + // OpenGL animation code goes here + + glClearColor( .7f, 0.7f, 0.7f, 1.f ); + + gDemoApplication->moveAndDisplay(); + + + SwapBuffers( hDC ); + + theta += 1.0f; + + + } + + + + // shutdown OpenGL + DisableOpenGL( hWnd, hDC, hRC ); + + // destroy the window explicitly + DestroyWindow( hWnd ); + + delete gDemoApplication; + + return msg.wParam; + +} + +// Window Procedure + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + + + + switch (message) + { + + case WM_SYSKEYDOWN: + { + if (lParam & 1<<29) + { + gDemoApplication->m_modifierKeys = VK_LMENU; + } + break; + } + case WM_SYSKEYUP: + { + if (lParam & 1<<29) + { + gDemoApplication->m_modifierKeys = VK_LMENU; + } else + { + gDemoApplication->m_modifierKeys = 0; + } + + break; + } + + + case WM_SIZE: // Size Action Has Taken Place + + switch (wParam) // Evaluate Size Action + { + case SIZE_MINIMIZED: // Was Window Minimized? + return 0; // Return + + case SIZE_MAXIMIZED: // Was Window Maximized? + sWidth = LOWORD (lParam); + sHeight = HIWORD (lParam); + if (sOpenGLInitialized) + { + gDemoApplication->reshape(sWidth,sHeight); + } + return 0; // Return + + case SIZE_RESTORED: // Was Window Restored? + sWidth = LOWORD (lParam); + sHeight = HIWORD (lParam); + if (sOpenGLInitialized) + { + gDemoApplication->reshape(sWidth,sHeight); + } + return 0; // Return + } + break; + + case WM_CREATE: + return 0; + + case WM_MBUTTONUP: + { + int xPos = LOWORD(lParam); + int yPos = HIWORD(lParam); + gDemoApplication->mouseFunc(1,1,xPos,yPos); + break; + } + case WM_MBUTTONDOWN: + { + int xPos = LOWORD(lParam); + int yPos = HIWORD(lParam); + gDemoApplication->mouseFunc(1,0,xPos,yPos); + break; + } + + case WM_LBUTTONUP: + { + int xPos = LOWORD(lParam); + int yPos = HIWORD(lParam); + gDemoApplication->mouseFunc(0,1,xPos,yPos); + break; + } + case 0x020A://WM_MOUSEWHEEL: + { + + int zDelta = (short)HIWORD(wParam); + int xPos = LOWORD(lParam); + int yPos = HIWORD(lParam); + if (zDelta>0) + gDemoApplication->zoomIn(); + else + gDemoApplication->zoomOut(); + break; + } + + case WM_MOUSEMOVE: + { + int xPos = LOWORD(lParam); + int yPos = HIWORD(lParam); + gDemoApplication->mouseMotionFunc(xPos,yPos); + break; + } + case WM_RBUTTONUP: + { + int xPos = LOWORD(lParam); + int yPos = HIWORD(lParam); + gDemoApplication->mouseFunc(2,1,xPos,yPos); + break; + } + case WM_RBUTTONDOWN: + { + int xPos = LOWORD(lParam); + int yPos = HIWORD(lParam); + gDemoApplication->mouseFunc(2,0,xPos,yPos); + break; + } + case WM_LBUTTONDOWN: + { + int xPos = LOWORD(lParam); + int yPos = HIWORD(lParam); + gDemoApplication->mouseFunc(0,0,xPos,yPos); + break; + } +/*#define WM_LBUTTONUP 0x0202 +#define WM_LBUTTONDBLCLK 0x0203 +#define WM_RBUTTONDOWN 0x0204 +#define WM_RBUTTONUP 0x0205 +#define WM_RBUTTONDBLCLK 0x0206 +#define WM_MBUTTONDOWN 0x0207 +#define WM_MBUTTONUP 0x0208 +#define WM_MBUTTONDBLCLK 0x0209 +*/ + + + + case WM_CLOSE: + PostQuitMessage( 0 ); + return 0; + + case WM_DESTROY: + return 0; + + case WM_KEYUP: + switch ( wParam ) + { + + case VK_PRIOR: + case VK_NEXT: + case VK_END: + case VK_HOME: + case VK_LEFT: + case VK_UP: + case VK_RIGHT: + case VK_DOWN: + { + if (gDemoApplication) + gDemoApplication->specialKeyboardUp(wParam,0,0); + return 0; + } + default: + { + gDemoApplication->keyboardUpCallback(tolower(wParam),0,0); + } + return DefWindowProc( hWnd, message, wParam, lParam ); + } + + case WM_KEYDOWN: + printf("bla\n"); + switch ( wParam ) + { + case VK_CONTROL: + case VK_PRIOR: + case VK_NEXT: + case VK_END: + case VK_HOME: + case VK_LEFT: + case VK_UP: + case VK_RIGHT: + case VK_DOWN: + { + if (gDemoApplication) + gDemoApplication->specialKeyboard(wParam,0,0); + break; + } + + case ' ': + { + if (gDemoApplication) + gDemoApplication->clientResetScene(); + break; + } + case 'Q': + case VK_ESCAPE: + { + quitRequest = 1; + PostQuitMessage(0); + } + return 0; + + } + return 0; + + case WM_CHAR: + if (!quitRequest) + gDemoApplication->keyboardCallback(wParam,0,0); + break; + + default: + return DefWindowProc( hWnd, message, wParam, lParam ); + + } + return 0; +} + +// Enable OpenGL + +void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC) +{ + PIXELFORMATDESCRIPTOR pfd; + int format; + + // get the device context (DC) + *hDC = GetDC( hWnd ); + + // set the pixel format for the DC + ZeroMemory( &pfd, sizeof( pfd ) ); + pfd.nSize = sizeof( pfd ); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 24; + pfd.cDepthBits = 16; + pfd.cStencilBits = 1; + pfd.iLayerType = PFD_MAIN_PLANE; + format = ChoosePixelFormat( *hDC, &pfd ); + SetPixelFormat( *hDC, format, &pfd ); + + // create and enable the render context (RC) + *hRC = wglCreateContext( *hDC ); + wglMakeCurrent( *hDC, *hRC ); + sOpenGLInitialized = true; + + +} + +// Disable OpenGL + +void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC) +{ + sOpenGLInitialized = false; + + wglMakeCurrent( NULL, NULL ); + wglDeleteContext( hRC ); + ReleaseDC( hWnd, hDC ); +} + +#endif //_WINDOWS diff --git a/Demos/OpenGL/Win32DemoApplication.cpp b/Demos/OpenGL/Win32DemoApplication.cpp new file mode 100644 index 0000000..f959cbf --- /dev/null +++ b/Demos/OpenGL/Win32DemoApplication.cpp @@ -0,0 +1,79 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +#ifdef _WINDOWS + +#include "Win32DemoApplication.h" + + + + +#if 0 +void Win32DemoApplication::renderme() +{ +} +void Win32DemoApplication::setTexturing(bool useTexture) +{ +} + +void Win32DemoApplication::setShadows(bool useShadows) +{ +} + +void Win32DemoApplication::setCameraDistance(float camDist) +{ +} +void Win32DemoApplication::clientResetScene() +{ + +} +#endif + +void Win32DemoApplication::updateModifierKeys() +{ + //not yet +} + + + +void Win32DemoApplication::specialKeyboard(int key, int x, int y) +{ + (void)x; + (void)y; + + switch (key) + { + case VK_LEFT : stepLeft(); break; + case VK_RIGHT : stepRight(); break; + case VK_UP : stepFront(); break; + case VK_DOWN : stepBack(); break; + +// case GLUT_KEY_PAGE_UP : zoomIn(); break; +// case GLUT_KEY_PAGE_DOWN : zoomOut(); break; +// case GLUT_KEY_HOME : toggleIdle(); break; + + default: + // std::cout << "unused (special) key : " << key << std::endl; + break; + } + +} + +void Win32DemoApplication::swapBuffers() +{ +} + +#endif + diff --git a/Demos/OpenGL/Win32DemoApplication.h b/Demos/OpenGL/Win32DemoApplication.h new file mode 100644 index 0000000..0c2a1ee --- /dev/null +++ b/Demos/OpenGL/Win32DemoApplication.h @@ -0,0 +1,40 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 WIN32_DEMO_APPLICATION_H +#define WIN32_DEMO_APPLICATION_H + + +#include "DemoApplication.h" + +class Win32DemoApplication : public DemoApplication +{ +protected: + + +public: + + + virtual void swapBuffers(); + + void specialKeyboard(int key, int x, int y); + + virtual void updateModifierKeys(); + + +}; + +#endif //WIN32_DEMO_APPLICATION_H \ No newline at end of file diff --git a/Demos/OpenGL/ibmsdk/Makefile b/Demos/OpenGL/ibmsdk/Makefile new file mode 100644 index 0000000..85a19c6 --- /dev/null +++ b/Demos/OpenGL/ibmsdk/Makefile @@ -0,0 +1,45 @@ +#### Source code Dirs +VPATH = ../ + +ROOT = ../../.. +HOST = /usr/include + +#### Library +LIBRARY_ppu = bulletopenglsupport.a + +#### Compiler flags +CPPFLAGS = -DUSE_LIBSPE2 \ +-I$(ROOT)/Extras/ConvexHull \ +-I$(ROOT)/src/ \ +-I$(SDKINC) \ +-I$(HOST) + +#### Optimization level flags +#CC_OPT_LEVEL = $(CC_OPT_LEVEL_DEBUG) +CC_OPT_LEVEL = -O3 + +##### Objects to be archived in lib +OBJS = \ +BMF_Api.o \ +BMF_BitmapFont.o \ +BMF_font_helv10.o \ +DemoApplication.o \ +GLDebugDrawer.o \ +GL_ShapeDrawer.o \ +GL_Simplex1to4.o \ +GlutStuff.o \ +RenderTexture.o + +#### Install directories +INSTALL_DIR = $(ROOT)/lib/ibmsdk/ +INSTALL_FILES = $(LIBRARY) + +IBM_CELLSDK_VERSION := $(shell if [ -d /opt/cell ]; then echo "3.0"; fi) + +ifeq ("$(IBM_CELLSDK_VERSION)","3.0") + CELL_TOP ?= /opt/cell/sdk + include $(CELL_TOP)/buildutils/make.footer +else + CELL_TOP ?= /opt/ibm/cell-sdk/prototype + include $(CELL_TOP)/make.footer +endif diff --git a/Demos/OpenGL/premake4.lua b/Demos/OpenGL/premake4.lua new file mode 100644 index 0000000..3e2208e --- /dev/null +++ b/Demos/OpenGL/premake4.lua @@ -0,0 +1,18 @@ + project "OpenGLSupport" + + kind "StaticLib" + targetdir "../../lib" + includedirs { + ".", + "../../src" + } + configuration {"Windows"} + includedirs { + "../../Glut" + } + configuration{} + + files { + "**.cpp", + "**.h" + } diff --git a/Demos/OpenGL/stb_image.cpp b/Demos/OpenGL/stb_image.cpp new file mode 100644 index 0000000..fb2de7d --- /dev/null +++ b/Demos/OpenGL/stb_image.cpp @@ -0,0 +1,4342 @@ +#include "stb_image.h" + +#ifndef STBI_HEADER_FILE_ONLY + +#ifndef STBI_NO_HDR +#include // ldexp +#include // strcmp, strtok +#endif + +#ifndef STBI_NO_STDIO +#include +#endif +#include +#include +#include +#include + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + + +// implementation: +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef signed short int16; +typedef unsigned int uint32; +typedef signed int int32; +typedef unsigned int uint; + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(uint32)==4 ? 1 : -1]; + +#if defined(STBI_NO_STDIO) && !defined(STBI_NO_WRITE) +#define STBI_NO_WRITE +#endif + +#define STBI_NOTUSED(v) (void)sizeof(v) + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) +#endif + +/////////////////////////////////////////////// +// +// stbi struct and start_xxx functions + +// stbi structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + uint8 buffer_start[128]; + + uint8 *img_buffer, *img_buffer_end; + uint8 *img_buffer_original; +} stbi; + + +static void refill_buffer(stbi *s); + +// initialize a memory-decode context +static void start_mem(stbi *s, uint8 const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_original = (uint8 *) buffer; + s->img_buffer_end = (uint8 *) buffer+len; +} + +// initialize a callback-based context +static void start_callbacks(stbi *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->img_buffer_original = s->buffer_start; + refill_buffer(s); +} + +#ifndef STBI_NO_STDIO + +static int stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stdio_skip(void *user, unsigned n) +{ + fseek((FILE*) user, n, SEEK_CUR); +} + +static int stdio_eof(void *user) +{ + return feof((FILE*) user); +} + +static stbi_io_callbacks stbi_stdio_callbacks = +{ + stdio_read, + stdio_skip, + stdio_eof, +}; + +static void start_file(stbi *s, FILE *f) +{ + start_callbacks(s, &stbi_stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi_rewind(stbi *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; +} + +static int stbi_jpeg_test(stbi *s); +static stbi_uc *stbi_jpeg_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_jpeg_info(stbi *s, int *x, int *y, int *comp); +static int stbi_png_test(stbi *s); +static stbi_uc *stbi_png_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_png_info(stbi *s, int *x, int *y, int *comp); +static int stbi_bmp_test(stbi *s); +static stbi_uc *stbi_bmp_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_tga_test(stbi *s); +static stbi_uc *stbi_tga_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_tga_info(stbi *s, int *x, int *y, int *comp); +static int stbi_psd_test(stbi *s); +static stbi_uc *stbi_psd_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_hdr_test(stbi *s); +static float *stbi_hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_pic_test(stbi *s); +static stbi_uc *stbi_pic_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_gif_test(stbi *s); +static stbi_uc *stbi_gif_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_gif_info(stbi *s, int *x, int *y, int *comp); + + +// this is not threadsafe +static const char *failure_reason; + +const char *stbi_failure_reason(void) +{ + return failure_reason; +} + +static int e(const char *str) +{ + failure_reason = str; + return 0; +} + +// e - error +// epf - error returning pointer to float +// epuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define e(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define e(x,y) e(y) +#else + #define e(x,y) e(x) +#endif + +#define epf(x,y) ((float *) (e(x,y)?NULL:NULL)) +#define epuc(x,y) ((unsigned char *) (e(x,y)?NULL:NULL)) + +void stbi_image_free(void *retval_from_stbi_load) +{ + free(retval_from_stbi_load); +} + +#ifndef STBI_NO_HDR +static float *ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static unsigned char *stbi_load_main(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + if (stbi_jpeg_test(s)) return stbi_jpeg_load(s,x,y,comp,req_comp); + if (stbi_png_test(s)) return stbi_png_load(s,x,y,comp,req_comp); + if (stbi_bmp_test(s)) return stbi_bmp_load(s,x,y,comp,req_comp); + if (stbi_gif_test(s)) return stbi_gif_load(s,x,y,comp,req_comp); + if (stbi_psd_test(s)) return stbi_psd_load(s,x,y,comp,req_comp); + if (stbi_pic_test(s)) return stbi_pic_load(s,x,y,comp,req_comp); + + #ifndef STBI_NO_HDR + if (stbi_hdr_test(s)) { + float *hdr = stbi_hdr_load(s, x,y,comp,req_comp); + return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + // test tga last because it's a crappy test! + if (stbi_tga_test(s)) + return stbi_tga_load(s,x,y,comp,req_comp); + return epuc("unknown image type", "Image not of any known type, or corrupt"); +} + +#ifndef STBI_NO_STDIO +unsigned char *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = fopen(filename, "rb"); + unsigned char *result; + if (!f) return epuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +unsigned char *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_file(&s,f); + return stbi_load_main(&s,x,y,comp,req_comp); +} +#endif //!STBI_NO_STDIO + +unsigned char *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_mem(&s,buffer,len); + return stbi_load_main(&s,x,y,comp,req_comp); +} + +unsigned char *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi_load_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_HDR + +float *stbi_loadf_main(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi_hdr_test(s)) + return stbi_hdr_load(s,x,y,comp,req_comp); + #endif + data = stbi_load_main(s, x, y, comp, req_comp); + if (data) + return ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return epf("unknown image type", "Image not of any known type, or corrupt"); +} + +float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_mem(&s,buffer,len); + return stbi_loadf_main(&s,x,y,comp,req_comp); +} + +float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi_loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = fopen(filename, "rb"); + float *result; + if (!f) return epf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_file(&s,f); + return stbi_loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_HDR + +// these is-hdr-or-not is defined independent of whether STBI_NO_HDR is +// defined, for API simplicity; if STBI_NO_HDR is defined, it always +// reports false! + +int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi s; + start_mem(&s,buffer,len); + return stbi_hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +extern int stbi_is_hdr (char const *filename) +{ + FILE *f = fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +extern int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + stbi s; + start_file(&s,f); + return stbi_hdr_test(&s); + #else + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +extern int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi s; + start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi_hdr_test(&s); + #else + return 0; + #endif +} + +#ifndef STBI_NO_HDR +static float h2l_gamma_i=1.0f/2.2f, h2l_scale_i=1.0f; +static float l2h_gamma=2.2f, l2h_scale=1.0f; + +void stbi_hdr_to_ldr_gamma(float gamma) { h2l_gamma_i = 1/gamma; } +void stbi_hdr_to_ldr_scale(float scale) { h2l_scale_i = 1/scale; } + +void stbi_ldr_to_hdr_gamma(float gamma) { l2h_gamma = gamma; } +void stbi_ldr_to_hdr_scale(float scale) { l2h_scale = scale; } +#endif + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + SCAN_load=0, + SCAN_type, + SCAN_header +}; + +static void refill_buffer(stbi *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + if (n == 0) { + // at end of file, treat same as if from memory + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_end-1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static int get8(stbi *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +stbi_inline static int at_eof(stbi *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} + +stbi_inline static uint8 get8u(stbi *s) +{ + return (uint8) get8(s); +} + +static void skip(stbi *s, int n) +{ + if (s->io.read) { + int blen = s->img_buffer_end - s->img_buffer; + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} + +static int getn(stbi *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = s->img_buffer_end - s->img_buffer; + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} + +static int get16(stbi *s) +{ + int z = get8(s); + return (z << 8) + get8(s); +} + +static uint32 get32(stbi *s) +{ + uint32 z = get16(s); + return (z << 16) + get16(s); +} + +static int get16le(stbi *s) +{ + int z = get8(s); + return z + (get8(s) << 8); +} + +static uint32 get32le(stbi *s) +{ + uint32 z = get16le(s); + return z + (get16le(s) << 16); +} + +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static uint8 compute_y(int r, int g, int b) +{ + return (uint8) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static unsigned char *convert_format(unsigned char *data, int img_n, int req_comp, uint x, uint y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + assert(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) malloc(req_comp * x * y); + if (good == NULL) { + free(data); + return epuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define COMBO(a,b) ((a)*8+(b)) + #define CASE(a,b) case COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (COMBO(img_n, req_comp)) { + CASE(1,2) dest[0]=src[0], dest[1]=255; break; + CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break; + CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break; + CASE(2,1) dest[0]=src[0]; break; + CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break; + CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; + CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break; + CASE(3,1) dest[0]=compute_y(src[0],src[1],src[2]); break; + CASE(3,2) dest[0]=compute_y(src[0],src[1],src[2]), dest[1] = 255; break; + CASE(4,1) dest[0]=compute_y(src[0],src[1],src[2]); break; + CASE(4,2) dest[0]=compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; + CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; + default: assert(0); + } + #undef CASE + } + + free(data); + return good; +} + +#ifndef STBI_NO_HDR +static float *ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output = (float *) malloc(x * y * comp * sizeof(float)); + if (output == NULL) { free(data); return epf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) pow(data[i*comp+k]/255.0f, l2h_gamma) * l2h_scale; + } + if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f; + } + free(data); + return output; +} + +#define float2int(x) ((int) (x)) +static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output = (stbi_uc *) malloc(x * y * comp); + if (output == NULL) { free(data); return epuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*h2l_scale_i, h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (uint8) float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (uint8) float2int(z); + } + } + free(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder (not actually fully baseline implementation) +// +// simple implementation +// - channel subsampling of at most 2 in each dimension +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - uses a lot of intermediate memory, could cache poorly +// - load http://nothings.org/remote/anemones.jpg 3 times on 2.8Ghz P4 +// stb_jpeg: 1.34 seconds (MSVC6, default release build) +// stb_jpeg: 1.06 seconds (MSVC6, processor = Pentium Pro) +// IJL11.dll: 1.08 seconds (compiled by intel) +// IJG 1998: 0.98 seconds (MSVC6, makefile provided by IJG) +// IJG 1998: 0.95 seconds (MSVC6, makefile + proc=PPro) + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + uint8 fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + uint16 code[256]; + uint8 values[256]; + uint8 size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} huffman; + +typedef struct +{ + #ifdef STBI_SIMD + unsigned short dequant2[4][64]; + #endif + stbi *s; + huffman huff_dc[4]; + huffman huff_ac[4]; + uint8 dequant[4][64]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + uint8 *data; + void *raw_data; + uint8 *linebuf; + } img_comp[4]; + + uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int scan_n, order[4]; + int restart_interval, todo; +} jpeg; + +static int build_huffman(huffman *h, int *count) +{ + int i,j,k=0,code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) + for (j=0; j < count[i]; ++j) + h->size[k++] = (uint8) (i+1); + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (uint16) (code++); + if (code-1 >= (1 << j)) return e("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (uint8) i; + } + } + } + return 1; +} + +static void grow_buffer_unsafe(jpeg *j) +{ + do { + int b = j->nomore ? 0 : get8(j->s); + if (b == 0xff) { + int c = get8(j->s); + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static uint32 bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int decode(jpeg *j, huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & bmask[k]) + h->delta[k]; + assert((((j->code_buffer) >> (32 - h->size[c])) & bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// combined JPEG 'receive' and JPEG 'extend', since baseline +// always extends everything it receives. +stbi_inline static int extend_receive(jpeg *j, int n) +{ + unsigned int m = 1 << (n-1); + unsigned int k; + if (j->code_bits < n) grow_buffer_unsafe(j); + + #if 1 + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~bmask[n]; + k &= bmask[n]; + j->code_bits -= n; + #else + k = (j->code_buffer >> (32 - n)) & bmask[n]; + j->code_bits -= n; + j->code_buffer <<= n; + #endif + // the following test is probably a random branch that won't + // predict well. I tried to table accelerate it but failed. + // maybe it's compiling as a conditional move? + if (k < m) + return (-1 << n) + k + 1; + else + return k; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static uint8 dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int decode_block(jpeg *j, short data[64], huffman *hdc, huffman *hac, int b) +{ + int diff,dc,k; + int t = decode(j, hdc); + if (t < 0) return e("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? extend_receive(j, t) : 0; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) dc; + + // decode AC components, see JPEG spec + k = 1; + do { + int r,s; + int rs = decode(j, hac); + if (rs < 0) return e("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + data[dezigzag[k++]] = (short) extend_receive(j,s); + } + } while (k < 64); + return 1; +} + +// take a -128..127 value and clamp it and convert to 0..255 +stbi_inline static uint8 clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (uint8) x; +} + +#define f2f(x) (int) (((x) * 4096 + 0.5)) +#define fsh(x) ((x) << 12) + +// derived from jidctint -- DCT_ISLOW +#define IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * f2f(0.5411961f); \ + t2 = p1 + p3*f2f(-1.847759065f); \ + t3 = p1 + p2*f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = fsh(p2+p3); \ + t1 = fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*f2f( 1.175875602f); \ + t0 = t0*f2f( 0.298631336f); \ + t1 = t1*f2f( 2.053119869f); \ + t2 = t2*f2f( 3.072711026f); \ + t3 = t3*f2f( 1.501321110f); \ + p1 = p5 + p1*f2f(-0.899976223f); \ + p2 = p5 + p2*f2f(-2.562915447f); \ + p3 = p3*f2f(-1.961570560f); \ + p4 = p4*f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +#ifdef STBI_SIMD +typedef unsigned short stbi_dequantize_t; +#else +typedef uint8 stbi_dequantize_t; +#endif + +// .344 seconds on 3*anemones.jpg +static void idct_block(uint8 *out, int out_stride, short data[64], stbi_dequantize_t *dequantize) +{ + int i,val[64],*v=val; + stbi_dequantize_t *dq = dequantize; + uint8 *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d,++dq, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0] * dq[0] << 2; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + IDCT_1D(d[ 0]*dq[ 0],d[ 8]*dq[ 8],d[16]*dq[16],d[24]*dq[24], + d[32]*dq[32],d[40]*dq[40],d[48]*dq[48],d[56]*dq[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = clamp((x0+t3) >> 17); + o[7] = clamp((x0-t3) >> 17); + o[1] = clamp((x1+t2) >> 17); + o[6] = clamp((x1-t2) >> 17); + o[2] = clamp((x2+t1) >> 17); + o[5] = clamp((x2-t1) >> 17); + o[3] = clamp((x3+t0) >> 17); + o[4] = clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SIMD +static stbi_idct_8x8 stbi_idct_installed = idct_block; + +void stbi_install_idct(stbi_idct_8x8 func) +{ + stbi_idct_installed = func; +} +#endif + +#define MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static uint8 get_marker(jpeg *j) +{ + uint8 x; + if (j->marker != MARKER_none) { x = j->marker; j->marker = MARKER_none; return x; } + x = get8u(j->s); + if (x != 0xff) return MARKER_none; + while (x == 0xff) + x = get8u(j->s); + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, reset the entropy decoder and +// the dc prediction +static void reset(jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0; + j->marker = MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int parse_entropy_coded_data(jpeg *z) +{ + reset(z); + if (z->scan_n == 1) { + int i,j; + #ifdef STBI_SIMD + __declspec(align(16)) + #endif + short data[64]; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + if (!decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0; + #ifdef STBI_SIMD + stbi_idct_installed(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]); + #else + idct_block(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]); + #endif + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!RESTART(z->marker)) return 1; + reset(z); + } + } + } + } else { // interleaved! + int i,j,k,x,y; + short data[64]; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + if (!decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0; + #ifdef STBI_SIMD + stbi_idct_installed(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]); + #else + idct_block(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]); + #endif + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!RESTART(z->marker)) return 1; + reset(z); + } + } + } + } + return 1; +} + +static int process_marker(jpeg *z, int m) +{ + int L; + switch (m) { + case MARKER_none: // no marker found + return e("expected marker","Corrupt JPEG"); + + case 0xC2: // SOF - progressive + return e("progressive jpeg","JPEG format not supported (progressive)"); + + case 0xDD: // DRI - specify restart interval + if (get16(z->s) != 4) return e("bad DRI len","Corrupt JPEG"); + z->restart_interval = get16(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = get16(z->s)-2; + while (L > 0) { + int q = get8(z->s); + int p = q >> 4; + int t = q & 15,i; + if (p != 0) return e("bad DQT type","Corrupt JPEG"); + if (t > 3) return e("bad DQT table","Corrupt JPEG"); + for (i=0; i < 64; ++i) + z->dequant[t][dezigzag[i]] = get8u(z->s); + #ifdef STBI_SIMD + for (i=0; i < 64; ++i) + z->dequant2[t][i] = z->dequant[t][i]; + #endif + L -= 65; + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = get16(z->s)-2; + while (L > 0) { + uint8 *v; + int sizes[16],i,m=0; + int q = get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return e("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = get8(z->s); + m += sizes[i]; + } + L -= 17; + if (tc == 0) { + if (!build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < m; ++i) + v[i] = get8u(z->s); + L -= m; + } + return L==0; + } + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + skip(z->s, get16(z->s)-2); + return 1; + } + return 0; +} + +// after we see SOS +static int process_scan_header(jpeg *z) +{ + int i; + int Ls = get16(z->s); + z->scan_n = get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return e("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return e("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = get8(z->s), which; + int q = get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return e("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return e("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + if (get8(z->s) != 0) return e("bad SOS","Corrupt JPEG"); + get8(z->s); // should be 63, but might be 0 + if (get8(z->s) != 0) return e("bad SOS","Corrupt JPEG"); + + return 1; +} + +static int process_frame_header(jpeg *z, int scan) +{ + stbi *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = get16(s); if (Lf < 11) return e("bad SOF len","Corrupt JPEG"); // JPEG + p = get8(s); if (p != 8) return e("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = get16(s); if (s->img_y == 0) return e("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = get16(s); if (s->img_x == 0) return e("0 width","Corrupt JPEG"); // JPEG requires + c = get8(s); + if (c != 3 && c != 1) return e("bad component count","Corrupt JPEG"); // JFIF requires + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return e("bad SOF len","Corrupt JPEG"); + + for (i=0; i < s->img_n; ++i) { + z->img_comp[i].id = get8(s); + if (z->img_comp[i].id != i+1) // JFIF requires + if (z->img_comp[i].id != i) // some version of jpegtran outputs non-JFIF-compliant files! + return e("bad component ID","Corrupt JPEG"); + q = get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return e("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return e("bad V","Corrupt JPEG"); + z->img_comp[i].tq = get8(s); if (z->img_comp[i].tq > 3) return e("bad TQ","Corrupt JPEG"); + } + + if (scan != SCAN_load) return 1; + + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return e("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].raw_data = malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15); + if (z->img_comp[i].raw_data == NULL) { + for(--i; i >= 0; --i) { + free(z->img_comp[i].raw_data); + z->img_comp[i].data = NULL; + } + return e("outofmem", "Out of memory"); + } + // align blocks for installable-idct using mmx/sse + z->img_comp[i].data = (uint8*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + z->img_comp[i].linebuf = NULL; + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define DNL(x) ((x) == 0xdc) +#define SOI(x) ((x) == 0xd8) +#define EOI(x) ((x) == 0xd9) +#define SOF(x) ((x) == 0xc0 || (x) == 0xc1) +#define SOS(x) ((x) == 0xda) + +static int decode_jpeg_header(jpeg *z, int scan) +{ + int m; + z->marker = MARKER_none; // initialize cached marker to empty + m = get_marker(z); + if (!SOI(m)) return e("no SOI","Corrupt JPEG"); + if (scan == SCAN_type) return 1; + m = get_marker(z); + while (!SOF(m)) { + if (!process_marker(z,m)) return 0; + m = get_marker(z); + while (m == MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (at_eof(z->s)) return e("no SOF", "Corrupt JPEG"); + m = get_marker(z); + } + } + if (!process_frame_header(z, scan)) return 0; + return 1; +} + +static int decode_jpeg_image(jpeg *j) +{ + int m; + j->restart_interval = 0; + if (!decode_jpeg_header(j, SCAN_load)) return 0; + m = get_marker(j); + while (!EOI(m)) { + if (SOS(m)) { + if (!process_scan_header(j)) return 0; + if (!parse_entropy_coded_data(j)) return 0; + if (j->marker == MARKER_none ) { + // handle 0s at the end of image data from IP Kamera 9060 + while (!at_eof(j->s)) { + int x = get8(j->s); + if (x == 255) { + j->marker = get8u(j->s); + break; + } else if (x != 0) { + return 0; + } + } + // if we reach eof without hitting a marker, get_marker() below will fail and we'll eventually return 0 + } + } else { + if (!process_marker(j, m)) return 0; + } + m = get_marker(j); + } + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef uint8 *(*resample_row_func)(uint8 *out, uint8 *in0, uint8 *in1, + int w, int hs); + +#define div4(x) ((uint8) ((x) >> 2)) + +static uint8 *resample_row_1(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static uint8* resample_row_v_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static uint8* resample_row_h_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + uint8 *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = div4(n+input[i-1]); + out[i*2+1] = div4(n+input[i+1]); + } + out[i*2+0] = div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define div16(x) ((uint8) ((x) >> 4)) + +static uint8 *resample_row_hv_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = div16(3*t0 + t1 + 8); + out[i*2 ] = div16(3*t1 + t0 + 8); + } + out[w*2-1] = div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +static uint8 *resample_row_generic(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + in_far = in_far; + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +#define float2fixed(x) ((int) ((x) * 65536 + 0.5)) + +// 0.38 seconds on 3*anemones.jpg (0.25 with processor = Pro) +// VC6 without processor=Pro is generating multiple LEAs per multiply! +static void YCbCr_to_RGB_row(uint8 *out, const uint8 *y, const uint8 *pcb, const uint8 *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 16) + 32768; // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr*float2fixed(1.40200f); + g = y_fixed - cr*float2fixed(0.71414f) - cb*float2fixed(0.34414f); + b = y_fixed + cb*float2fixed(1.77200f); + r >>= 16; + g >>= 16; + b >>= 16; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (uint8)r; + out[1] = (uint8)g; + out[2] = (uint8)b; + out[3] = 255; + out += step; + } +} + +#ifdef STBI_SIMD +static stbi_YCbCr_to_RGB_run stbi_YCbCr_installed = YCbCr_to_RGB_row; + +void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func) +{ + stbi_YCbCr_installed = func; +} +#endif + + +// clean up the temporary component buffers +static void cleanup_jpeg(jpeg *j) +{ + int i; + for (i=0; i < j->s->img_n; ++i) { + if (j->img_comp[i].data) { + free(j->img_comp[i].raw_data); + j->img_comp[i].data = NULL; + } + if (j->img_comp[i].linebuf) { + free(j->img_comp[i].linebuf); + j->img_comp[i].linebuf = NULL; + } + } +} + +typedef struct +{ + resample_row_func resample; + uint8 *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi_resample; + +static uint8 *load_jpeg_image(jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n; + // validate req_comp + if (req_comp < 0 || req_comp > 4) return epuc("bad req_comp", "Internal error"); + z->s->img_n = 0; + + // load a jpeg image from whichever source + if (!decode_jpeg_image(z)) { cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n; + + if (z->s->img_n == 3 && n < 3) + decode_n = 1; + else + decode_n = z->s->img_n; + + // resample and color-convert + { + int k; + uint i,j; + uint8 *output; + uint8 *coutput[4]; + + stbi_resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi_resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (uint8 *) malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { cleanup_jpeg(z); return epuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = resample_row_hv_2; + else r->resample = resample_row_generic; + } + + // can't error after this so, this is safe + output = (uint8 *) malloc(n * z->s->img_x * z->s->img_y + 1); + if (!output) { cleanup_jpeg(z); return epuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + uint8 *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi_resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + uint8 *y = coutput[0]; + if (z->s->img_n == 3) { + #ifdef STBI_SIMD + stbi_YCbCr_installed(out, y, coutput[1], coutput[2], z->s.img_x, n); + #else + YCbCr_to_RGB_row(out, y, coutput[1], coutput[2], z->s->img_x, n); + #endif + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + uint8 *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; + } + } + cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n; // report original components, not output + return output; + } +} + +static unsigned char *stbi_jpeg_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + jpeg j; + j.s = s; + return load_jpeg_image(&j, x,y,comp,req_comp); +} + +static int stbi_jpeg_test(stbi *s) +{ + int r; + jpeg j; + j.s = s; + r = decode_jpeg_header(&j, SCAN_type); + stbi_rewind(s); + return r; +} + +static int stbi_jpeg_info_raw(jpeg *j, int *x, int *y, int *comp) +{ + if (!decode_jpeg_header(j, SCAN_header)) { + stbi_rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n; + return 1; +} + +static int stbi_jpeg_info(stbi *s, int *x, int *y, int *comp) +{ + jpeg j; + j.s = s; + return stbi_jpeg_info_raw(&j, x, y, comp); +} + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define ZFAST_BITS 9 // accelerate all cases in default tables +#define ZFAST_MASK ((1 << ZFAST_BITS) - 1) + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + uint16 fast[1 << ZFAST_BITS]; + uint16 firstcode[16]; + int maxcode[17]; + uint16 firstsymbol[16]; + uint8 size[288]; + uint16 value[288]; +} zhuffman; + +stbi_inline static int bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int bit_reverse(int v, int bits) +{ + assert(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return bitreverse16(v) >> (16-bits); +} + +static int zbuild_huffman(zhuffman *z, uint8 *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 255, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + assert(sizes[i] <= (1 << i)); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (uint16) code; + z->firstsymbol[i] = (uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return e("bad codelengths","Corrupt JPEG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + z->size[c] = (uint8)s; + z->value[c] = (uint16)i; + if (s <= ZFAST_BITS) { + int k = bit_reverse(next_code[s],s); + while (k < (1 << ZFAST_BITS)) { + z->fast[k] = (uint16) c; + k += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + uint8 *zbuffer, *zbuffer_end; + int num_bits; + uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + zhuffman z_length, z_distance; +} zbuf; + +stbi_inline static int zget8(zbuf *z) +{ + if (z->zbuffer >= z->zbuffer_end) return 0; + return *z->zbuffer++; +} + +static void fill_bits(zbuf *z) +{ + do { + assert(z->code_buffer < (1U << z->num_bits)); + z->code_buffer |= zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int zreceive(zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +stbi_inline static int zhuffman_decode(zbuf *a, zhuffman *z) +{ + int b,s,k; + if (a->num_bits < 16) fill_bits(a); + b = z->fast[a->code_buffer & ZFAST_MASK]; + if (b < 0xffff) { + s = z->size[b]; + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; + } + + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = bit_reverse(a->code_buffer, 16); + for (s=ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s == 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + assert(z->size[b] == s); + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +static int expand(zbuf *z, int n) // need to make room for n bytes +{ + char *q; + int cur, limit; + if (!z->z_expandable) return e("output buffer limit","Corrupt PNG"); + cur = (int) (z->zout - z->zout_start); + limit = (int) (z->zout_end - z->zout_start); + while (cur + n > limit) + limit *= 2; + q = (char *) realloc(z->zout_start, limit); + if (q == NULL) return e("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static int length_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static int length_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static int dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static int dist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int parse_huffman_block(zbuf *a) +{ + for(;;) { + int z = zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return e("bad huffman code","Corrupt PNG"); // error in huffman codes + if (a->zout >= a->zout_end) if (!expand(a, 1)) return 0; + *a->zout++ = (char) z; + } else { + uint8 *p; + int len,dist; + if (z == 256) return 1; + z -= 257; + len = length_base[z]; + if (length_extra[z]) len += zreceive(a, length_extra[z]); + z = zhuffman_decode(a, &a->z_distance); + if (z < 0) return e("bad huffman code","Corrupt PNG"); + dist = dist_base[z]; + if (dist_extra[z]) dist += zreceive(a, dist_extra[z]); + if (a->zout - a->zout_start < dist) return e("bad dist","Corrupt PNG"); + if (a->zout + len > a->zout_end) if (!expand(a, len)) return 0; + p = (uint8 *) (a->zout - dist); + while (len--) + *a->zout++ = *p++; + } + } +} + +static int compute_huffman_codes(zbuf *a) +{ + static uint8 length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + zhuffman z_codelength; + uint8 lencodes[286+32+137];//padding for maximum single op + uint8 codelength_sizes[19]; + int i,n; + + int hlit = zreceive(a,5) + 257; + int hdist = zreceive(a,5) + 1; + int hclen = zreceive(a,4) + 4; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (uint8) s; + } + if (!zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < hlit + hdist) { + int c = zhuffman_decode(a, &z_codelength); + assert(c >= 0 && c < 19); + if (c < 16) + lencodes[n++] = (uint8) c; + else if (c == 16) { + c = zreceive(a,2)+3; + memset(lencodes+n, lencodes[n-1], c); + n += c; + } else if (c == 17) { + c = zreceive(a,3)+3; + memset(lencodes+n, 0, c); + n += c; + } else { + assert(c == 18); + c = zreceive(a,7)+11; + memset(lencodes+n, 0, c); + n += c; + } + } + if (n != hlit+hdist) return e("bad codelengths","Corrupt PNG"); + if (!zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int parse_uncompressed_block(zbuf *a) +{ + uint8 header[4]; + int len,nlen,k; + if (a->num_bits & 7) + zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (uint8) (a->code_buffer & 255); // wtf this warns? + a->code_buffer >>= 8; + a->num_bits -= 8; + } + assert(a->num_bits == 0); + // now fill header the normal way + while (k < 4) + header[k++] = (uint8) zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return e("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return e("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!expand(a, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int parse_zlib_header(zbuf *a) +{ + int cmf = zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = zget8(a); + if ((cmf*256+flg) % 31 != 0) return e("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return e("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return e("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +// @TODO: should statically initialize these for optimal thread safety +static uint8 default_length[288], default_distance[32]; +static void init_defaults(void) +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) default_length[i] = 8; + for ( ; i <= 255; ++i) default_length[i] = 9; + for ( ; i <= 279; ++i) default_length[i] = 7; + for ( ; i <= 287; ++i) default_length[i] = 8; + + for (i=0; i <= 31; ++i) default_distance[i] = 5; +} + +int stbi_png_partial; // a quick hack to only allow decoding some of a PNG... I should implement real streaming support instead +static int parse_zlib(zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = zreceive(a,1); + type = zreceive(a,2); + if (type == 0) { + if (!parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!default_distance[31]) init_defaults(); + if (!zbuild_huffman(&a->z_length , default_length , 288)) return 0; + if (!zbuild_huffman(&a->z_distance, default_distance, 32)) return 0; + } else { + if (!compute_huffman_codes(a)) return 0; + } + if (!parse_huffman_block(a)) return 0; + } + if (stbi_png_partial && a->zout - a->zout_start > 65536) + break; + } while (!final); + return 1; +} + +static int do_zlib(zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return parse_zlib(a, parse_header); +} + +char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + zbuf a; + char *p = (char *) malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (uint8 *) buffer; + a.zbuffer_end = (uint8 *) buffer + len; + if (do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + free(a.zout_start); + return NULL; + } +} + +char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + zbuf a; + char *p = (char *) malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (uint8 *) buffer; + a.zbuffer_end = (uint8 *) buffer + len; + if (do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + free(a.zout_start); + return NULL; + } +} + +int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + zbuf a; + a.zbuffer = (uint8 *) ibuffer; + a.zbuffer_end = (uint8 *) ibuffer + ilen; + if (do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + zbuf a; + char *p = (char *) malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (uint8 *) buffer; + a.zbuffer_end = (uint8 *) buffer+len; + if (do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + free(a.zout_start); + return NULL; + } +} + +int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + zbuf a; + a.zbuffer = (uint8 *) ibuffer; + a.zbuffer_end = (uint8 *) ibuffer + ilen; + if (do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + + +typedef struct +{ + uint32 length; + uint32 type; +} chunk; + +#define PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) + +static chunk get_chunk_header(stbi *s) +{ + chunk c; + c.length = get32(s); + c.type = get32(s); + return c; +} + +static int check_png_header(stbi *s) +{ + static uint8 png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (get8u(s) != png_sig[i]) return e("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi *s; + uint8 *idata, *expanded, *out; +} png; + + +enum { + F_none=0, F_sub=1, F_up=2, F_avg=3, F_paeth=4, + F_avg_first, F_paeth_first +}; + +static uint8 first_row_filter[5] = +{ + F_none, F_sub, F_none, F_avg_first, F_paeth_first +}; + +static int paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +// create the png data from post-deflated data +static int create_png_image_raw(png *a, uint8 *raw, uint32 raw_len, int out_n, uint32 x, uint32 y) +{ + stbi *s = a->s; + uint32 i,j,stride = x*out_n; + int k; + int img_n = s->img_n; // copy it into a local for later + assert(out_n == s->img_n || out_n == s->img_n+1); + if (stbi_png_partial) y = 1; + a->out = (uint8 *) malloc(x * y * out_n); + if (!a->out) return e("outofmem", "Out of memory"); + if (!stbi_png_partial) { + if (s->img_x == x && s->img_y == y) { + if (raw_len != (img_n * x + 1) * y) return e("not enough pixels","Corrupt PNG"); + } else { // interlaced: + if (raw_len < (img_n * x + 1) * y) return e("not enough pixels","Corrupt PNG"); + } + } + for (j=0; j < y; ++j) { + uint8 *cur = a->out + stride*j; + uint8 *prior = cur - stride; + int filter = *raw++; + if (filter > 4) return e("invalid filter","Corrupt PNG"); + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + // handle first pixel explicitly + for (k=0; k < img_n; ++k) { + switch (filter) { + case F_none : cur[k] = raw[k]; break; + case F_sub : cur[k] = raw[k]; break; + case F_up : cur[k] = raw[k] + prior[k]; break; + case F_avg : cur[k] = raw[k] + (prior[k]>>1); break; + case F_paeth : cur[k] = (uint8) (raw[k] + paeth(0,prior[k],0)); break; + case F_avg_first : cur[k] = raw[k]; break; + case F_paeth_first: cur[k] = raw[k]; break; + } + } + if (img_n != out_n) cur[img_n] = 255; + raw += img_n; + cur += out_n; + prior += out_n; + // this is a little gross, so that we don't switch per-pixel or per-component + if (img_n == out_n) { + #define CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, raw+=img_n,cur+=img_n,prior+=img_n) \ + for (k=0; k < img_n; ++k) + switch (filter) { + CASE(F_none) cur[k] = raw[k]; break; + CASE(F_sub) cur[k] = raw[k] + cur[k-img_n]; break; + CASE(F_up) cur[k] = raw[k] + prior[k]; break; + CASE(F_avg) cur[k] = raw[k] + ((prior[k] + cur[k-img_n])>>1); break; + CASE(F_paeth) cur[k] = (uint8) (raw[k] + paeth(cur[k-img_n],prior[k],prior[k-img_n])); break; + CASE(F_avg_first) cur[k] = raw[k] + (cur[k-img_n] >> 1); break; + CASE(F_paeth_first) cur[k] = (uint8) (raw[k] + paeth(cur[k-img_n],0,0)); break; + } + #undef CASE + } else { + assert(img_n+1 == out_n); + #define CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \ + for (k=0; k < img_n; ++k) + switch (filter) { + CASE(F_none) cur[k] = raw[k]; break; + CASE(F_sub) cur[k] = raw[k] + cur[k-out_n]; break; + CASE(F_up) cur[k] = raw[k] + prior[k]; break; + CASE(F_avg) cur[k] = raw[k] + ((prior[k] + cur[k-out_n])>>1); break; + CASE(F_paeth) cur[k] = (uint8) (raw[k] + paeth(cur[k-out_n],prior[k],prior[k-out_n])); break; + CASE(F_avg_first) cur[k] = raw[k] + (cur[k-out_n] >> 1); break; + CASE(F_paeth_first) cur[k] = (uint8) (raw[k] + paeth(cur[k-out_n],0,0)); break; + } + #undef CASE + } + } + return 1; +} + +static int create_png_image(png *a, uint8 *raw, uint32 raw_len, int out_n, int interlaced) +{ + uint8 *final; + int p; + int save; + if (!interlaced) + return create_png_image_raw(a, raw, raw_len, out_n, a->s->img_x, a->s->img_y); + save = stbi_png_partial; + stbi_png_partial = 0; + + // de-interlacing + final = (uint8 *) malloc(a->s->img_x * a->s->img_y * out_n); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + if (!create_png_image_raw(a, raw, raw_len, out_n, x, y)) { + free(final); + return 0; + } + for (j=0; j < y; ++j) + for (i=0; i < x; ++i) + memcpy(final + (j*yspc[p]+yorig[p])*a->s->img_x*out_n + (i*xspc[p]+xorig[p])*out_n, + a->out + (j*x+i)*out_n, out_n); + free(a->out); + raw += (x*out_n+1)*y; + raw_len -= (x*out_n+1)*y; + } + } + a->out = final; + + stbi_png_partial = save; + return 1; +} + +static int compute_transparency(png *z, uint8 tc[3], int out_n) +{ + stbi *s = z->s; + uint32 i, pixel_count = s->img_x * s->img_y; + uint8 *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + assert(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int expand_palette(png *a, uint8 *palette, int len, int pal_img_n) +{ + uint32 i, pixel_count = a->s->img_x * a->s->img_y; + uint8 *p, *temp_out, *orig = a->out; + + p = (uint8 *) malloc(pixel_count * pal_img_n); + if (p == NULL) return e("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + free(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi_unpremultiply_on_load = 0; +static int stbi_de_iphone_flag = 0; + +void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi_unpremultiply_on_load = flag_true_if_should_unpremultiply; +} +void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi_de_iphone_flag = flag_true_if_should_convert; +} + +static void stbi_de_iphone(png *z) +{ + stbi *s = z->s; + uint32 i, pixel_count = s->img_x * s->img_y; + uint8 *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + uint8 t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + assert(s->img_out_n == 4); + if (stbi_unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + uint8 a = p[3]; + uint8 t = p[0]; + if (a) { + p[0] = p[2] * 255 / a; + p[1] = p[1] * 255 / a; + p[2] = t * 255 / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + uint8 t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +static int parse_png_file(png *z, int scan, int req_comp) +{ + uint8 palette[1024], pal_img_n=0; + uint8 has_trans=0, tc[3]; + uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, iphone=0; + stbi *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!check_png_header(s)) return 0; + + if (scan == SCAN_type) return 1; + + for (;;) { + chunk c = get_chunk_header(s); + switch (c.type) { + case PNG_TYPE('C','g','B','I'): + iphone = stbi_de_iphone_flag; + skip(s, c.length); + break; + case PNG_TYPE('I','H','D','R'): { + int depth,color,comp,filter; + if (!first) return e("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return e("bad IHDR len","Corrupt PNG"); + s->img_x = get32(s); if (s->img_x > (1 << 24)) return e("too large","Very large image (corrupt?)"); + s->img_y = get32(s); if (s->img_y > (1 << 24)) return e("too large","Very large image (corrupt?)"); + depth = get8(s); if (depth != 8) return e("8bit only","PNG not supported: 8-bit only"); + color = get8(s); if (color > 6) return e("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return e("bad ctype","Corrupt PNG"); + comp = get8(s); if (comp) return e("bad comp method","Corrupt PNG"); + filter= get8(s); if (filter) return e("bad filter method","Corrupt PNG"); + interlace = get8(s); if (interlace>1) return e("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return e("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return e("too large", "Image too large to decode"); + if (scan == SCAN_header) return 1; + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return e("too large","Corrupt PNG"); + // if SCAN_header, have to scan to see if we have a tRNS + } + break; + } + + case PNG_TYPE('P','L','T','E'): { + if (first) return e("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return e("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return e("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = get8u(s); + palette[i*4+1] = get8u(s); + palette[i*4+2] = get8u(s); + palette[i*4+3] = 255; + } + break; + } + + case PNG_TYPE('t','R','N','S'): { + if (first) return e("first not IHDR", "Corrupt PNG"); + if (z->idata) return e("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return e("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return e("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = get8u(s); + } else { + if (!(s->img_n & 1)) return e("tRNS with alpha","Corrupt PNG"); + if (c.length != (uint32) s->img_n*2) return e("bad tRNS len","Corrupt PNG"); + has_trans = 1; + for (k=0; k < s->img_n; ++k) + tc[k] = (uint8) get16(s); // non 8-bit images will be larger + } + break; + } + + case PNG_TYPE('I','D','A','T'): { + if (first) return e("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return e("no PLTE","Corrupt PNG"); + if (scan == SCAN_header) { s->img_n = pal_img_n; return 1; } + if (ioff + c.length > idata_limit) { + uint8 *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + p = (uint8 *) realloc(z->idata, idata_limit); if (p == NULL) return e("outofmem", "Out of memory"); + z->idata = p; + } + if (!getn(s, z->idata+ioff,c.length)) return e("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case PNG_TYPE('I','E','N','D'): { + uint32 raw_len; + if (first) return e("first not IHDR", "Corrupt PNG"); + if (scan != SCAN_load) return 1; + if (z->idata == NULL) return e("no IDAT","Corrupt PNG"); + z->expanded = (uint8 *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, 16384, (int *) &raw_len, !iphone); + if (z->expanded == NULL) return 0; // zlib should set error + free(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!create_png_image(z, z->expanded, raw_len, s->img_out_n, interlace)) return 0; + if (has_trans) + if (!compute_transparency(z, tc, s->img_out_n)) return 0; + if (iphone && s->img_out_n > 2) + stbi_de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!expand_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } + free(z->expanded); z->expanded = NULL; + return 1; + } + + default: + // if critical, fail + if (first) return e("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX chunk not known"; + invalid_chunk[0] = (uint8) (c.type >> 24); + invalid_chunk[1] = (uint8) (c.type >> 16); + invalid_chunk[2] = (uint8) (c.type >> 8); + invalid_chunk[3] = (uint8) (c.type >> 0); + #endif + return e(invalid_chunk, "PNG not supported: unknown chunk type"); + } + skip(s, c.length); + break; + } + // end of chunk, read and skip CRC + get32(s); + } +} + +static unsigned char *do_png(png *p, int *x, int *y, int *n, int req_comp) +{ + unsigned char *result=NULL; + if (req_comp < 0 || req_comp > 4) return epuc("bad req_comp", "Internal error"); + if (parse_png_file(p, SCAN_load, req_comp)) { + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + result = convert_format(result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + free(p->out); p->out = NULL; + free(p->expanded); p->expanded = NULL; + free(p->idata); p->idata = NULL; + + return result; +} + +static unsigned char *stbi_png_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + png p; + p.s = s; + return do_png(&p, x,y,comp,req_comp); +} + +static int stbi_png_test(stbi *s) +{ + int r; + r = check_png_header(s); + stbi_rewind(s); + return r; +} + +static int stbi_png_info_raw(png *p, int *x, int *y, int *comp) +{ + if (!parse_png_file(p, SCAN_header, 0)) { + stbi_rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi_png_info(stbi *s, int *x, int *y, int *comp) +{ + png p; + p.s = s; + return stbi_png_info_raw(&p, x, y, comp); +} + +// Microsoft/Windows BMP image + +static int bmp_test(stbi *s) +{ + int sz; + if (get8(s) != 'B') return 0; + if (get8(s) != 'M') return 0; + get32le(s); // discard filesize + get16le(s); // discard reserved + get16le(s); // discard reserved + get32le(s); // discard data offset + sz = get32le(s); + if (sz == 12 || sz == 40 || sz == 56 || sz == 108) return 1; + return 0; +} + +static int stbi_bmp_test(stbi *s) +{ + int r = bmp_test(s); + stbi_rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) n += 16, z >>= 16; + if (z >= 0x00100) n += 8, z >>= 8; + if (z >= 0x00010) n += 4, z >>= 4; + if (z >= 0x00004) n += 2, z >>= 2; + if (z >= 0x00002) n += 1, z >>= 1; + return n; +} + +static int bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +static int shiftsigned(int v, int shift, int bits) +{ + int result; + int z=0; + + if (shift < 0) v <<= -shift; + else v >>= shift; + result = v; + + z = bits; + while (z < 8) { + result += v >> z; + z += bits; + } + return result; +} + +static stbi_uc *bmp_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + uint8 *out; + unsigned int mr=0,mg=0,mb=0,ma=0, fake_a=0; + stbi_uc pal[256][4]; + int psize=0,i,j,compress=0,width; + int bpp, flip_vertically, pad, target, offset, hsz; + if (get8(s) != 'B' || get8(s) != 'M') return epuc("not BMP", "Corrupt BMP"); + get32le(s); // discard filesize + get16le(s); // discard reserved + get16le(s); // discard reserved + offset = get32le(s); + hsz = get32le(s); + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108) return epuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = get16le(s); + s->img_y = get16le(s); + } else { + s->img_x = get32le(s); + s->img_y = get32le(s); + } + if (get16le(s) != 1) return epuc("bad BMP", "bad BMP"); + bpp = get16le(s); + if (bpp == 1) return epuc("monochrome", "BMP type not supported: 1-bit"); + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + if (hsz == 12) { + if (bpp < 24) + psize = (offset - 14 - 24) / 3; + } else { + compress = get32le(s); + if (compress == 1 || compress == 2) return epuc("BMP RLE", "BMP type not supported: RLE"); + get32le(s); // discard sizeof + get32le(s); // discard hres + get32le(s); // discard vres + get32le(s); // discard colorsused + get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + get32le(s); + get32le(s); + get32le(s); + get32le(s); + } + if (bpp == 16 || bpp == 32) { + mr = mg = mb = 0; + if (compress == 0) { + if (bpp == 32) { + mr = 0xffu << 16; + mg = 0xffu << 8; + mb = 0xffu << 0; + ma = 0xffu << 24; + fake_a = 1; // @TODO: check for cases like alpha value is all 0 and switch it to 255 + } else { + mr = 31u << 10; + mg = 31u << 5; + mb = 31u << 0; + } + } else if (compress == 3) { + mr = get32le(s); + mg = get32le(s); + mb = get32le(s); + // not documented, but generated by photoshop and handled by mspaint + if (mr == mg && mg == mb) { + // ?!?!? + return epuc("bad BMP", "bad BMP"); + } + } else + return epuc("bad BMP", "bad BMP"); + } + } else { + assert(hsz == 108); + mr = get32le(s); + mg = get32le(s); + mb = get32le(s); + ma = get32le(s); + get32le(s); // discard color space + for (i=0; i < 12; ++i) + get32le(s); // discard color space parameters + } + if (bpp < 16) + psize = (offset - 14 - hsz) >> 2; + } + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + out = (stbi_uc *) malloc(target * s->img_x * s->img_y); + if (!out) return epuc("outofmem", "Out of memory"); + if (bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { free(out); return epuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = get8u(s); + pal[i][1] = get8u(s); + pal[i][0] = get8u(s); + if (hsz != 12) get8(s); + pal[i][3] = 255; + } + skip(s, offset - 14 - hsz - psize * (hsz == 12 ? 3 : 4)); + if (bpp == 4) width = (s->img_x + 1) >> 1; + else if (bpp == 8) width = s->img_x; + else { free(out); return epuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=get8(s),v2=0; + if (bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (bpp == 8) ? get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + skip(s, pad); + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + skip(s, offset - 14 - hsz); + if (bpp == 24) width = 3 * s->img_x; + else if (bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (bpp == 24) { + easy = 1; + } else if (bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { free(out); return epuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = high_bit(mr)-7; rcount = bitcount(mr); + gshift = high_bit(mg)-7; gcount = bitcount(mr); + bshift = high_bit(mb)-7; bcount = bitcount(mr); + ashift = high_bit(ma)-7; acount = bitcount(mr); + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + int a; + out[z+2] = get8u(s); + out[z+1] = get8u(s); + out[z+0] = get8u(s); + z += 3; + a = (easy == 2 ? get8(s) : 255); + if (target == 4) out[z++] = (uint8) a; + } + } else { + for (i=0; i < (int) s->img_x; ++i) { + uint32 v = (bpp == 16 ? get16le(s) : get32le(s)); + int a; + out[z++] = (uint8) shiftsigned(v & mr, rshift, rcount); + out[z++] = (uint8) shiftsigned(v & mg, gshift, gcount); + out[z++] = (uint8) shiftsigned(v & mb, bshift, bcount); + a = (ma ? shiftsigned(v & ma, ashift, acount) : 255); + if (target == 4) out[z++] = (uint8) a; + } + } + skip(s, pad); + } + } + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i], p1[i] = p2[i], p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} + +static stbi_uc *stbi_bmp_load(stbi *s,int *x, int *y, int *comp, int req_comp) +{ + return bmp_load(s, x,y,comp,req_comp); +} + + +// Targa Truevision - TGA +// by Jonathan Dummer + +static int tga_info(stbi *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp; + int sz; + get8u(s); // discard Offset + sz = get8u(s); // color type + if( sz > 1 ) { + stbi_rewind(s); + return 0; // only RGB or indexed allowed + } + sz = get8u(s); // image type + // only RGB or grey allowed, +/- RLE + if ((sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11)) return 0; + skip(s,9); + tga_w = get16le(s); + if( tga_w < 1 ) { + stbi_rewind(s); + return 0; // test width + } + tga_h = get16le(s); + if( tga_h < 1 ) { + stbi_rewind(s); + return 0; // test height + } + sz = get8(s); // bits per pixel + // only RGB or RGBA or grey allowed + if ((sz != 8) && (sz != 16) && (sz != 24) && (sz != 32)) { + stbi_rewind(s); + return 0; + } + tga_comp = sz; + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp / 8; + return 1; // seems to have passed everything +} + +int stbi_tga_info(stbi *s, int *x, int *y, int *comp) +{ + return tga_info(s, x, y, comp); +} + +static int tga_test(stbi *s) +{ + int sz; + get8u(s); // discard Offset + sz = get8u(s); // color type + if ( sz > 1 ) return 0; // only RGB or indexed allowed + sz = get8u(s); // image type + if ( (sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11) ) return 0; // only RGB or grey allowed, +/- RLE + get16(s); // discard palette start + get16(s); // discard palette length + get8(s); // discard bits per palette color entry + get16(s); // discard x origin + get16(s); // discard y origin + if ( get16(s) < 1 ) return 0; // test width + if ( get16(s) < 1 ) return 0; // test height + sz = get8(s); // bits per pixel + if ( (sz != 8) && (sz != 16) && (sz != 24) && (sz != 32) ) return 0; // only RGB or RGBA or grey allowed + return 1; // seems to have passed everything +} + +static int stbi_tga_test(stbi *s) +{ + int res = tga_test(s); + stbi_rewind(s); + return res; +} + +static stbi_uc *tga_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + // read in the TGA header stuff + int tga_offset = get8u(s); + int tga_indexed = get8u(s); + int tga_image_type = get8u(s); + int tga_is_RLE = 0; + int tga_palette_start = get16le(s); + int tga_palette_len = get16le(s); + int tga_palette_bits = get8u(s); + int tga_x_origin = get16le(s); + int tga_y_origin = get16le(s); + int tga_width = get16le(s); + int tga_height = get16le(s); + int tga_bits_per_pixel = get8u(s); + int tga_inverted = get8u(s); + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4]; + unsigned char trans_data[4]; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + /* int tga_alpha_bits = tga_inverted & 15; */ + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // error check + if ( //(tga_indexed) || + (tga_width < 1) || (tga_height < 1) || + (tga_image_type < 1) || (tga_image_type > 3) || + ((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16) && + (tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32)) + ) + { + return NULL; // we don't report this as a bad TGA because we don't even know if it's TGA + } + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) + { + tga_bits_per_pixel = tga_palette_bits; + } + + // tga info + *x = tga_width; + *y = tga_height; + if ( (req_comp < 1) || (req_comp > 4) ) + { + // just use whatever the file was + req_comp = tga_bits_per_pixel / 8; + *comp = req_comp; + } else + { + // force a new number of components + *comp = tga_bits_per_pixel/8; + } + tga_data = (unsigned char*)malloc( tga_width * tga_height * req_comp ); + if (!tga_data) return epuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + skip(s, tga_offset ); + // do I need to load a palette? + if ( tga_indexed ) + { + // any data to skip? (offset usually = 0) + skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)malloc( tga_palette_len * tga_palette_bits / 8 ); + if (!tga_palette) return epuc("outofmem", "Out of memory"); + if (!getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 )) { + free(tga_data); + free(tga_palette); + return epuc("bad palette", "Corrupt TGA"); + } + } + // load the data + trans_data[0] = trans_data[1] = trans_data[2] = trans_data[3] = 0; + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE chunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = get8u(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in 1 byte, then perform the lookup + int pal_idx = get8u(s); + if ( pal_idx >= tga_palette_len ) + { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_bits_per_pixel / 8; + for (j = 0; j*8 < tga_bits_per_pixel; ++j) + { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else + { + // read in the data raw + for (j = 0; j*8 < tga_bits_per_pixel; ++j) + { + raw_data[j] = get8u(s); + } + } + // convert raw to the intermediate format + switch (tga_bits_per_pixel) + { + case 8: + // Luminous => RGBA + trans_data[0] = raw_data[0]; + trans_data[1] = raw_data[0]; + trans_data[2] = raw_data[0]; + trans_data[3] = 255; + break; + case 16: + // Luminous,Alpha => RGBA + trans_data[0] = raw_data[0]; + trans_data[1] = raw_data[0]; + trans_data[2] = raw_data[0]; + trans_data[3] = raw_data[1]; + break; + case 24: + // BGR => RGBA + trans_data[0] = raw_data[2]; + trans_data[1] = raw_data[1]; + trans_data[2] = raw_data[0]; + trans_data[3] = 255; + break; + case 32: + // BGRA => RGBA + trans_data[0] = raw_data[2]; + trans_data[1] = raw_data[1]; + trans_data[2] = raw_data[0]; + trans_data[3] = raw_data[3]; + break; + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + // convert to final format + switch (req_comp) + { + case 1: + // RGBA => Luminance + tga_data[i*req_comp+0] = compute_y(trans_data[0],trans_data[1],trans_data[2]); + break; + case 2: + // RGBA => Luminance,Alpha + tga_data[i*req_comp+0] = compute_y(trans_data[0],trans_data[1],trans_data[2]); + tga_data[i*req_comp+1] = trans_data[3]; + break; + case 3: + // RGBA => RGB + tga_data[i*req_comp+0] = trans_data[0]; + tga_data[i*req_comp+1] = trans_data[1]; + tga_data[i*req_comp+2] = trans_data[2]; + break; + case 4: + // RGBA => RGBA + tga_data[i*req_comp+0] = trans_data[0]; + tga_data[i*req_comp+1] = trans_data[1]; + tga_data[i*req_comp+2] = trans_data[2]; + tga_data[i*req_comp+3] = trans_data[3]; + break; + } + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * req_comp; + int index2 = (tga_height - 1 - j) * tga_width * req_comp; + for (i = tga_width * req_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + free( tga_palette ); + } + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + // OK, done + return tga_data; +} + +static stbi_uc *stbi_tga_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + return tga_load(s,x,y,comp,req_comp); +} + + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +static int psd_test(stbi *s) +{ + if (get32(s) != 0x38425053) return 0; // "8BPS" + else return 1; +} + +static int stbi_psd_test(stbi *s) +{ + int r = psd_test(s); + stbi_rewind(s); + return r; +} + +static stbi_uc *psd_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + int pixelCount; + int channelCount, compression; + int channel, i, count, len; + int w,h; + uint8 *out; + + // Check identifier + if (get32(s) != 0x38425053) // "8BPS" + return epuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (get16(s) != 1) + return epuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = get16(s); + if (channelCount < 0 || channelCount > 16) + return epuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = get32(s); + w = get32(s); + + // Make sure the depth is 8 bits. + if (get16(s) != 8) + return epuc("unsupported bit depth", "PSD bit depth is not 8 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (get16(s) != 3) + return epuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + skip(s,get32(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + skip(s, get32(s) ); + + // Skip the reserved data. + skip(s, get32(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = get16(s); + if (compression > 1) + return epuc("bad compression", "PSD has an unknown compression format"); + + // Create the destination image. + out = (stbi_uc *) malloc(4 * w*h); + if (!out) return epuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data, + // which we're going to just skip. + skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + uint8 *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++) *p = (channel == 3 ? 255 : 0), p += 4; + } else { + // Read the RLE data. + count = 0; + while (count < pixelCount) { + len = get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + count += len; + while (len) { + *p = get8u(s); + p += 4; + len--; + } + } else if (len > 128) { + uint8 val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len ^= 0x0FF; + len += 2; + val = get8u(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + uint8 *p; + + p = out + channel; + if (channel > channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++) *p = channel == 3 ? 255 : 0, p += 4; + } else { + // Read the data. + for (i = 0; i < pixelCount; i++) + *p = get8u(s), p += 4; + } + } + } + + if (req_comp && req_comp != 4) { + out = convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // convert_format frees input on failure + } + + if (comp) *comp = channelCount; + *y = h; + *x = w; + + return out; +} + +static stbi_uc *stbi_psd_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + return psd_load(s,x,y,comp,req_comp); +} + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +static int pic_is4(stbi *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int pic_test(stbi *s) +{ + int i; + + if (!pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + get8(s); + + if (!pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} pic_packet_t; + +static stbi_uc *pic_readval(stbi *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (at_eof(s)) return epuc("bad file","PIC file too short"); + dest[i]=get8u(s); + } + } + + return dest; +} + +static void pic_copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *pic_load2(stbi *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + pic_packet_t packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + pic_packet_t *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return epuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = get8(s); + packet->size = get8u(s); + packet->type = get8u(s); + packet->channel = get8u(s); + + act_comp |= packet->channel; + + if (at_eof(s)) return epuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return epuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return epuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=get8u(s); + if (at_eof(s)) return epuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (uint8) left; + + if (!pic_readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = get8(s), i; + if (at_eof(s)) return epuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + int i; + + if (count==128) + count = get16(s); + else + count -= 127; + if (count > left) + return epuc("bad file","scanline overrun"); + + if (!pic_readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return epuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static stbi_uc *pic_load(stbi *s,int *px,int *py,int *comp,int req_comp) +{ + stbi_uc *result; + int i, x,y; + + for (i=0; i<92; ++i) + get8(s); + + x = get16(s); + y = get16(s); + if (at_eof(s)) return epuc("bad file","file too short (pic header)"); + if ((1 << 28) / x < y) return epuc("too large", "Image too large to decode"); + + get32(s); //skip `ratio' + get16(s); //skip `fields' + get16(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) malloc(x*y*4); + memset(result, 0xff, x*y*4); + + if (!pic_load2(s,x,y,comp, result)) { + free(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi_pic_test(stbi *s) +{ + int r = pic_test(s); + stbi_rewind(s); + return r; +} + +static stbi_uc *stbi_pic_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + return pic_load(s,x,y,comp,req_comp); +} + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb +typedef struct stbi_gif_lzw_struct { + int16 prefix; + uint8 first; + uint8 suffix; +} stbi_gif_lzw; + +typedef struct stbi_gif_struct +{ + int w,h; + stbi_uc *out; // output buffer (always 4 components) + int flags, bgindex, ratio, transparent, eflags; + uint8 pal[256][4]; + uint8 lpal[256][4]; + stbi_gif_lzw codes[4096]; + uint8 *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; +} stbi_gif; + +static int gif_test(stbi *s) +{ + int sz; + if (get8(s) != 'G' || get8(s) != 'I' || get8(s) != 'F' || get8(s) != '8') return 0; + sz = get8(s); + if (sz != '9' && sz != '7') return 0; + if (get8(s) != 'a') return 0; + return 1; +} + +static int stbi_gif_test(stbi *s) +{ + int r = gif_test(s); + stbi_rewind(s); + return r; +} + +static void stbi_gif_parse_colortable(stbi *s, uint8 pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = get8u(s); + pal[i][1] = get8u(s); + pal[i][0] = get8u(s); + pal[i][3] = transp ? 0 : 255; + } +} + +static int stbi_gif_header(stbi *s, stbi_gif *g, int *comp, int is_info) +{ + uint8 version; + if (get8(s) != 'G' || get8(s) != 'I' || get8(s) != 'F' || get8(s) != '8') + return e("not GIF", "Corrupt GIF"); + + version = get8u(s); + if (version != '7' && version != '9') return e("not GIF", "Corrupt GIF"); + if (get8(s) != 'a') return e("not GIF", "Corrupt GIF"); + + failure_reason = ""; + g->w = get16le(s); + g->h = get16le(s); + g->flags = get8(s); + g->bgindex = get8(s); + g->ratio = get8(s); + g->transparent = -1; + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi_gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi_gif_info_raw(stbi *s, int *x, int *y, int *comp) +{ + stbi_gif g; + if (!stbi_gif_header(s, &g, comp, 1)) { + stbi_rewind( s ); + return 0; + } + if (x) *x = g.w; + if (y) *y = g.h; + return 1; +} + +static void stbi_out_gif_code(stbi_gif *g, uint16 code) +{ + uint8 *p, *c; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi_out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + p = &g->out[g->cur_x + g->cur_y]; + c = &g->color_table[g->codes[code].suffix * 4]; + + if (c[3] >= 128) { + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static uint8 *stbi_process_gif_raster(stbi *s, stbi_gif *g) +{ + uint8 lzw_cs; + int32 len, code; + uint32 first; + int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi_gif_lzw *p; + + lzw_cs = get8u(s); + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (code = 0; code < clear; code++) { + g->codes[code].prefix = -1; + g->codes[code].first = (uint8) code; + g->codes[code].suffix = (uint8) code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (int32) get8(s) << valid_bits; + valid_bits += 8; + } else { + int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + skip(s, len); + while ((len = get8(s)) > 0) + skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) return epuc("no clear code", "Corrupt GIF"); + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 4096) return epuc("too many codes", "Corrupt GIF"); + p->prefix = (int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return epuc("illegal code in raster", "Corrupt GIF"); + + stbi_out_gif_code(g, (uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return epuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +static void stbi_fill_gif_background(stbi_gif *g) +{ + int i; + uint8 *c = g->pal[g->bgindex]; + // @OPTIMIZE: write a dword at a time + for (i = 0; i < g->w * g->h * 4; i += 4) { + uint8 *p = &g->out[i]; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +static uint8 *stbi_gif_load_next(stbi *s, stbi_gif *g, int *comp, int req_comp) +{ + int i; + uint8 *old_out = 0; + + if (g->out == 0) { + if (!stbi_gif_header(s, g, comp,0)) return 0; // failure_reason set by stbi_gif_header + g->out = (uint8 *) malloc(4 * g->w * g->h); + if (g->out == 0) return epuc("outofmem", "Out of memory"); + stbi_fill_gif_background(g); + } else { + // animated-gif-only path + if (((g->eflags & 0x1C) >> 2) == 3) { + old_out = g->out; + g->out = (uint8 *) malloc(4 * g->w * g->h); + if (g->out == 0) return epuc("outofmem", "Out of memory"); + memcpy(g->out, old_out, g->w*g->h*4); + } + } + + for (;;) { + switch (get8(s)) { + case 0x2C: /* Image Descriptor */ + { + int32 x, y, w, h; + uint8 *o; + + x = get16le(s); + y = get16le(s); + w = get16le(s); + h = get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return epuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + g->lflags = get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi_gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (uint8 *) g->lpal; + } else if (g->flags & 0x80) { + for (i=0; i < 256; ++i) // @OPTIMIZE: reset only the previous transparent + g->pal[i][3] = 255; + if (g->transparent >= 0 && (g->eflags & 0x01)) + g->pal[g->transparent][3] = 0; + g->color_table = (uint8 *) g->pal; + } else + return epuc("missing color table", "Corrupt GIF"); + + o = stbi_process_gif_raster(s, g); + if (o == NULL) return NULL; + + if (req_comp && req_comp != 4) + o = convert_format(o, 4, req_comp, g->w, g->h); + return o; + } + + case 0x21: // Comment Extension. + { + int len; + if (get8(s) == 0xF9) { // Graphic Control Extension. + len = get8(s); + if (len == 4) { + g->eflags = get8(s); + get16le(s); // delay + g->transparent = get8(s); + } else { + skip(s, len); + break; + } + } + while ((len = get8(s)) != 0) + skip(s, len); + break; + } + + case 0x3B: // gif stream termination code + return (uint8 *) 1; + + default: + return epuc("unknown code", "Corrupt GIF"); + } + } +} + +static stbi_uc *stbi_gif_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + uint8 *u = 0; + stbi_gif g={0}; + + u = stbi_gif_load_next(s, &g, comp, req_comp); + if (u == (void *) 1) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + } + + return u; +} + +static int stbi_gif_info(stbi *s, int *x, int *y, int *comp) +{ + return stbi_gif_info_raw(s,x,y,comp); +} + + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int hdr_test(stbi *s) +{ + const char *signature = "#?RADIANCE\n"; + int i; + for (i=0; signature[i]; ++i) + if (get8(s) != signature[i]) + return 0; + return 1; +} + +static int stbi_hdr_test(stbi* s) +{ + int r = hdr_test(s); + stbi_rewind(s); + return r; +} + +#define HDR_BUFLEN 1024 +static char *hdr_gettoken(stbi *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) get8(z); + + while (!at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == HDR_BUFLEN-1) { + // flush to end of line + while (!at_eof(z) && get8(z) != '\n') + ; + break; + } + c = (char) get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + char buffer[HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + + + // Check identifier + if (strcmp(hdr_gettoken(s,buffer), "#?RADIANCE") != 0) + return epf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return epf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return epf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return epf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = strtol(token, NULL, 10); + + *x = width; + *y = height; + + *comp = 3; + if (req_comp == 0) req_comp = 3; + + // Read data + hdr_data = (float *) malloc(height * width * req_comp * sizeof(float)); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + getn(s, rgbe, 4); + hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = get8(s); + c2 = get8(s); + len = get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + uint8 rgbe[4]; + rgbe[0] = (uint8) c1; + rgbe[1] = (uint8) c2; + rgbe[2] = (uint8) len; + rgbe[3] = (uint8) get8u(s); + hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + free(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= get8(s); + if (len != width) { free(hdr_data); free(scanline); return epf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) scanline = (stbi_uc *) malloc(width * 4); + + for (k = 0; k < 4; ++k) { + i = 0; + while (i < width) { + count = get8u(s); + if (count > 128) { + // Run + value = get8u(s); + count -= 128; + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = get8u(s); + } + } + } + for (i=0; i < width; ++i) + hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + free(scanline); + } + + return hdr_data; +} + +static float *stbi_hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + return hdr_load(s,x,y,comp,req_comp); +} + +static int stbi_hdr_info(stbi *s, int *x, int *y, int *comp) +{ + char buffer[HDR_BUFLEN]; + char *token; + int valid = 0; + + if (strcmp(hdr_gettoken(s,buffer), "#?RADIANCE") != 0) { + stbi_rewind( s ); + return 0; + } + + for(;;) { + token = hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi_rewind( s ); + return 0; + } + token = hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi_rewind( s ); + return 0; + } + token += 3; + *y = strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi_rewind( s ); + return 0; + } + token += 3; + *x = strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +static int stbi_bmp_info(stbi *s, int *x, int *y, int *comp) +{ + int hsz; + if (get8(s) != 'B' || get8(s) != 'M') { + stbi_rewind( s ); + return 0; + } + skip(s,12); + hsz = get32le(s); + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108) { + stbi_rewind( s ); + return 0; + } + if (hsz == 12) { + *x = get16le(s); + *y = get16le(s); + } else { + *x = get32le(s); + *y = get32le(s); + } + if (get16le(s) != 1) { + stbi_rewind( s ); + return 0; + } + *comp = get16le(s) / 8; + return 1; +} + +static int stbi_psd_info(stbi *s, int *x, int *y, int *comp) +{ + int channelCount; + if (get32(s) != 0x38425053) { + stbi_rewind( s ); + return 0; + } + if (get16(s) != 1) { + stbi_rewind( s ); + return 0; + } + skip(s, 6); + channelCount = get16(s); + if (channelCount < 0 || channelCount > 16) { + stbi_rewind( s ); + return 0; + } + *y = get32(s); + *x = get32(s); + if (get16(s) != 8) { + stbi_rewind( s ); + return 0; + } + if (get16(s) != 3) { + stbi_rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi_pic_info(stbi *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained; + pic_packet_t packets[10]; + + skip(s, 92); + + *x = get16(s); + *y = get16(s); + if (at_eof(s)) return 0; + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi_rewind( s ); + return 0; + } + + skip(s, 8); + + do { + pic_packet_t *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = get8(s); + packet->size = get8u(s); + packet->type = get8u(s); + packet->channel = get8u(s); + act_comp |= packet->channel; + + if (at_eof(s)) { + stbi_rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi_rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} + +static int stbi_info_main(stbi *s, int *x, int *y, int *comp) +{ + if (stbi_jpeg_info(s, x, y, comp)) + return 1; + if (stbi_png_info(s, x, y, comp)) + return 1; + if (stbi_gif_info(s, x, y, comp)) + return 1; + if (stbi_bmp_info(s, x, y, comp)) + return 1; + if (stbi_psd_info(s, x, y, comp)) + return 1; + if (stbi_pic_info(s, x, y, comp)) + return 1; + #ifndef STBI_NO_HDR + if (stbi_hdr_info(s, x, y, comp)) + return 1; + #endif + // test tga last because it's a crappy test! + if (stbi_tga_info(s, x, y, comp)) + return 1; + return e("unknown image type", "Image not of any known type, or corrupt"); +} + +#ifndef STBI_NO_STDIO +int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = fopen(filename, "rb"); + int result; + if (!f) return e("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi s; + long pos = ftell(f); + start_file(&s, f); + r = stbi_info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi s; + start_mem(&s,buffer,len); + return stbi_info_main(&s,x,y,comp); +} + +int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi s; + start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi_info_main(&s,x,y,comp); +} + +#endif // STBI_HEADER_FILE_ONLY + +/* + revision history: + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-uint8 to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.e. Janez (U+017D)emva) + 1.21 fix use of 'uint8' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 2008-08-02 + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi_bmp_load() and stbi_tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 first released version +*/ diff --git a/Demos/OpenGL/stb_image.h b/Demos/OpenGL/stb_image.h new file mode 100644 index 0000000..9df58d6 --- /dev/null +++ b/Demos/OpenGL/stb_image.h @@ -0,0 +1,332 @@ +/* stbi-1.33 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c + when you control the images you're loading + no warranty implied; use at your own risk + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline (no JPEG progressive) + PNG 8-bit only + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - overridable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD) + + Latest revisions: + 1.33 (2011-07-14) minor fixes suggested by Dave Moore + 1.32 (2011-07-13) info support for all filetypes (SpartanJ) + 1.31 (2011-06-19) a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) added ability to load files via io callbacks (Ben Wenger) + 1.29 (2010-08-16) various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) cast-to-uint8 to fix warnings (Laurent Gomila) + allow trailing 0s at end of image data (Laurent Gomila) + 1.26 (2010-07-24) fix bug in file buffering for PNG reported by SpartanJ + + See end of file for full revision history. + + TODO: + stbi_info support for BMP,PSD,HDR,PIC + + + ============================ Contributors ========================= + + Image formats Optimizations & bugfixes + Sean Barrett (jpeg, png, bmp) Fabian "ryg" Giesen + Nicolas Schulz (hdr, psd) + Jonathan Dummer (tga) Bug fixes & warning fixes + Jean-Marc Lienher (gif) Marc LeBlanc + Tom Seddon (pic) Christpher Lloyd + Thatcher Ulrich (psd) Dave Moore + Won Chun + the Horde3D community + Extensions, features Janez Zemva + Jetro Lauha (stbi_info) Jonathan Blow + James "moose2000" Brown (iPhone PNG) Laurent Gomila + Ben "Disch" Wenger (io callbacks) Aruelien Pocheville + Martin "SpartanJ" Golini Ryamond Barbiero + David Woo + + + If your name should be here but isn't, let Sean know. + +*/ + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +// To get a header file for this, either cut and paste the header, +// or create stb_image.h, #define STBI_HEADER_FILE_ONLY, and +// then include stb_image.c from it. + +//// begin header file //////////////////////////////////////////////////// +// +// Limitations: +// - no jpeg progressive support +// - non-HDR formats support 8-bit samples only (jpeg, png) +// - no delayed line count (jpeg) -- IJG doesn't support either +// - no 1-bit BMP +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data) +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *comp -- outputs # of image components in image file +// int req_comp -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise. +// If req_comp is non-zero, *comp has the number of components that _would_ +// have been output otherwise. E.g. if you set req_comp to 4, you will always +// get RGBA output, but you can check *comp to easily see if it's opaque. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *comp will be unchanged. The function stbi_failure_reason() +// can be queried for an extremely brief, end-user unfriendly explanation +// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid +// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// =========================================================================== +// +// iPhone PNG support: +// +// By default we convert iphone-formatted PNGs back to RGB; nominally they +// would silently load as BGR, except the existing code should have just +// failed on such iPhone PNGs. But you can disable this conversion by +// by calling stbi_convert_iphone_png_to_rgb(0), in which case +// you will always just get the native iphone "format" through. +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image now supports loading HDR images in general, and currently +// the Radiance .HDR file format, although the support is provided +// generically. You can still load any file through the existing interface; +// if you attempt to load an HDR file, it will be automatically remapped to +// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). + + +#ifndef STBI_NO_STDIO + +#if defined(_MSC_VER) && _MSC_VER >= 0x1400 +#define _CRT_SECURE_NO_WARNINGS // suppress bogus warnings about fopen() +#endif + +#include +#endif + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for req_comp + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +typedef unsigned char stbi_uc; + +#ifdef __cplusplus +extern "C" { +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +extern stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); + +#ifndef STBI_NO_STDIO +extern stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp); +extern stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,unsigned n); // skip the next 'n' bytes + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +extern stbi_uc *stbi_load_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp); + +#ifndef STBI_NO_HDR + extern float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); + + #ifndef STBI_NO_STDIO + extern float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp); + extern float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + #endif + + extern float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp); + + extern void stbi_hdr_to_ldr_gamma(float gamma); + extern void stbi_hdr_to_ldr_scale(float scale); + + extern void stbi_ldr_to_hdr_gamma(float gamma); + extern void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_HDR + +// stbi_is_hdr is always defined +extern int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +extern int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +extern int stbi_is_hdr (char const *filename); +extern int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// NOT THREADSAFE +extern const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +extern void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +extern int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +extern int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); + +#ifndef STBI_NO_STDIO +extern int stbi_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); + +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +extern void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +extern void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + + +// ZLIB client - used by PNG, available for other purposes + +extern char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +extern char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +extern int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +extern char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +extern int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +// define faster low-level operations (typically SIMD support) +#ifdef STBI_SIMD +typedef void (*stbi_idct_8x8)(stbi_uc *out, int out_stride, short data[64], unsigned short *dequantize); +// compute an integer IDCT on "input" +// input[x] = data[x] * dequantize[x] +// write results to 'out': 64 samples, each run of 8 spaced by 'out_stride' +// CLAMP results to 0..255 +typedef void (*stbi_YCbCr_to_RGB_run)(stbi_uc *output, stbi_uc const *y, stbi_uc const *cb, stbi_uc const *cr, int count, int step); +// compute a conversion from YCbCr to RGB +// 'count' pixels +// write pixels to 'output'; each pixel is 'step' bytes (either 3 or 4; if 4, write '255' as 4th), order R,G,B +// y: Y input channel +// cb: Cb input channel; scale/biased to be 0..255 +// cr: Cr input channel; scale/biased to be 0..255 + +extern void stbi_install_idct(stbi_idct_8x8 func); +extern void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func); +#endif // STBI_SIMD + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H diff --git a/Demos/OpenPL_Demo/CApi.cpp b/Demos/OpenPL_Demo/CApi.cpp new file mode 100644 index 0000000..171c770 --- /dev/null +++ b/Demos/OpenPL_Demo/CApi.cpp @@ -0,0 +1,159 @@ +/* +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. +*/ + +/* + Draft high-level generic physics C-API. For low-level access, use the physics SDK native API's. + Work in progress, functionality will be added on demand. + + If possible, use the richer Bullet C++ API, by including +*/ + +#include "Bullet-C-Api.h" +#include "btBulletDynamicsCommon.h" + +/* + Create and Delete a Physics SDK +*/ + +plPhysicsSdkHandle plNewBulletSdk() +{ + return 0; +} + +void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk) +{ + +} + +/* Dynamics World */ +plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdk) +{ + return (plDynamicsWorldHandle) new btDiscreteDynamicsWorld; +} +void plDeleteDynamicsWorld(plDynamicsWorldHandle world) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + delete dynamicsWorld; +} + +void plStepSimulation(plDynamicsWorldHandle world, plReal timeStep) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + assert(dynamicsWorld); + dynamicsWorld->stepSimulation(timeStep); +} + +void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + assert(dynamicsWorld); + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + assert(body); + + dynamicsWorld->addRigidBody(body); +} + +void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + assert(dynamicsWorld); + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + assert(body); + + dynamicsWorld->removeRigidBody(body); +} + +/* Rigid Body */ + +plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape ) +{ + btTransform trans; + trans.setIdentity(); + btVector3 localInertia; + btCollisionShape* shape = reinterpret_cast( cshape); + assert(shape); + shape->calculateLocalInertia(mass,localInertia); + btRigidBody* body = new btRigidBody(mass, trans,shape,localInertia); + body->m_userObjectPointer = user_data; + return (plRigidBodyHandle) body; +} + +void plDeleteRigidBody(plRigidBodyHandle cbody) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(cbody); + assert(body); + delete body; +} + + +/* Collision Shape definition */ + +plCollisionShapeHandle plNewSphereShape(plReal radius) +{ + return (plCollisionShapeHandle) new btSphereShape(radius); + +} + +plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z) +{ + return (plCollisionShapeHandle) new btBoxShape(btVector3(x,y,z)); +} + +plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height) +{ + //capsule is convex hull of 2 spheres, so use btMultiSphereShape + btVector3 inertiaHalfExtents(radius,height,radius); + const int numSpheres = 2; + btVector3 positions[numSpheres] = {btVector3(0,height,0),btVector3(0,-height,0)}; + btScalar radi[numSpheres] = {radius,radius}; + return (plCollisionShapeHandle) new btMultiSphereShape(inertiaHalfExtents,positions,radi,numSpheres); +} +plCollisionShapeHandle plNewConeShape(plReal radius, plReal height) +{ + return (plCollisionShapeHandle) new btConeShape(radius,height); +} + +plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height) +{ + return (plCollisionShapeHandle) new btCylinderShape(btVector3(radius,height,radius)); +} + +void plDeleteShape(plCollisionShapeHandle cshape) +{ + btCollisionShape* shape = reinterpret_cast( cshape); + assert(shape); + delete shape; +} +void plSetScaling(plCollisionShapeHandle cshape, plVector3 cscaling) +{ + btCollisionShape* shape = reinterpret_cast( cshape); + assert(shape); + btVector3 scaling(cscaling[0],cscaling[1],cscaling[2]); + shape->setLocalScaling(scaling); +} + + + +void plSetPosition(plRigidBodyHandle object, const plVector3 position) +{ +} +void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation) +{ +} + + +//plRigidBodyHandle plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); + +// extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); diff --git a/Demos/OpenPL_Demo/OpenPL_Demo.c b/Demos/OpenPL_Demo/OpenPL_Demo.c new file mode 100644 index 0000000..cef1f76 --- /dev/null +++ b/Demos/OpenPL_Demo/OpenPL_Demo.c @@ -0,0 +1,44 @@ + +#include "Bullet-C-Api.h" + + +int main() +{ + float timeStep = 1.f/60.f; + + /* initialize */ + plPhysicsSdkHandle sdk = plNewBulletSdk(); + + plDynamicsWorldHandle world = plCreateDynamicsWorld(sdk); + + + float radius = 1.f; + plCollisionShapeHandle collisionShape = plNewSphereShape(radius); + + void* user_data = 0;/* can point to a graphics object */ + + float mass = 1.f; + + plRigidBodyHandle body = plCreateRigidBody(user_data, mass, collisionShape ); + + plAddRigidBody(world, body); + + + + plStepSimulation(world,0.1f); + + /* cleanup */ + + plRemoveRigidBody(world, body); + + + plDeleteRigidBody(body); + + plDeleteShape( collisionShape); + + plDeleteDynamicsWorld( world); + + plDeletePhysicsSdk(sdk); + + return 0; +} \ No newline at end of file diff --git a/Demos/ParticlesOpenCL/AMD/CMakeLists.txt b/Demos/ParticlesOpenCL/AMD/CMakeLists.txt new file mode 100644 index 0000000..657d1ef --- /dev/null +++ b/Demos/ParticlesOpenCL/AMD/CMakeLists.txt @@ -0,0 +1,86 @@ + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL +${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +${AMD_OPENCL_INCLUDES} +) + +ADD_DEFINITIONS(-DUSE_AMD_OPENCL) +ADD_DEFINITIONS(-DCL_PLATFORM_AMD) + +IF(WIN32) +ADD_DEFINITIONS(-DGLEW_STATIC) +ENDIF(WIN32) + +IF (CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY + ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew64s.lib ) +ELSE(CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew32s.lib ) +ENDIF(CMAKE_CL_64) + + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport + BulletDynamics + BulletCollision + BulletMultiThreaded + LinearMath + ${GLUT_glut_LIBRARY} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${CMAK_GLEW_LIBRARY} + ${CMAKE_ATISTREAMSDK_LIBPATH}/OpenCL.lib + ) + + + ADD_EXECUTABLE(AppParticlesOCL_AMD + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesDynamicsWorld.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesSharedDefs.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesSharedTypes.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesDemo.h + + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/shaders.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLInclude.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesDemoDynamicsWorld.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/main.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesDemo.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/shaders.cpp + + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesOCL.cl + ) +ELSE (USE_GLUT) +ENDIF (USE_GLUT) + +IF(WIN32) +IF (CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_AMD POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} ) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_AMD POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesOCL.cl ${CMAKE_CURRENT_BINARY_DIR}) + ENDIF() +ELSE(CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_AMD POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR}) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_AMD POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesOCL.cl ${CMAKE_CURRENT_BINARY_DIR}) + ENDIF() +ENDIF(CMAKE_CL_64) +ENDIF(WIN32) + +IF (UNIX) + TARGET_LINK_LIBRARIES(AppParticlesOCL_AMD pthread) +ENDIF(UNIX) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppParticlesOCL_AMD PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppParticlesOCL_AMD PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppParticlesOCL_AMD PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/ParticlesOpenCL/Apple/CMakeLists.txt b/Demos/ParticlesOpenCL/Apple/CMakeLists.txt new file mode 100644 index 0000000..22ecedb --- /dev/null +++ b/Demos/ParticlesOpenCL/Apple/CMakeLists.txt @@ -0,0 +1,84 @@ + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL +${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +IF (APPLE) + FIND_LIBRARY(OPENCL_LIBRARY OpenCL DOC "OpenCL lib for OSX") + FIND_PATH(OPENCL_INCLUDE_DIR OpenCL/cl.h DOC "Include for OpenCL on OSX") +ENDIF (APPLE) + + +#ADD_DEFINITIONS(-DUSE_MINICL) + +IF(WIN32) +IF (CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew64.lib ) +ELSE(CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew32.lib ) +ENDIF(CMAKE_CL_64) +ENDIF(WIN32) + + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport + BulletDynamics + BulletCollision + LinearMath + ${OPENCL_LIBRARY} + ${GLUT_glut_LIBRARY} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${CMAK_GLEW_LIBRARY} + ) + + + ADD_EXECUTABLE(AppParticlesOCL_Apple + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesDynamicsWorld.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesSharedDefs.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesSharedTypes.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/shaders.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLInclude.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesDemoDynamicsWorld.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/main.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesDemo.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/shaders.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesOCL.cl + ) +ELSE (USE_GLUT) +ENDIF (USE_GLUT) + + +IF(WIN32) +IF (CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Apple POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} ) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Apple POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLEW64.DLL ${CMAKE_CURRENT_BINARY_DIR}) + ENDIF() +ELSE(CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Apple POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR}) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Apple POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLEW32.DLL ${CMAKE_CURRENT_BINARY_DIR}) + ENDIF() +ENDIF(CMAKE_CL_64) +ENDIF(WIN32) + +ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Apple POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesOCL.cl ${CMAKE_CURRENT_BINARY_DIR}) + + +IF (UNIX) + TARGET_LINK_LIBRARIES(AppParticlesOCL_Apple pthread) +ENDIF(UNIX) + diff --git a/Demos/ParticlesOpenCL/CMakeLists.txt b/Demos/ParticlesOpenCL/CMakeLists.txt new file mode 100644 index 0000000..369414d --- /dev/null +++ b/Demos/ParticlesOpenCL/CMakeLists.txt @@ -0,0 +1,19 @@ +IF(BUILD_MINICL_OPENCL_DEMOS) + SUBDIRS( MiniCL ) +ENDIF() + +IF(BUILD_INTEL_OPENCL_DEMOS) + SUBDIRS(Intel) +ENDIF() + +IF(BUILD_AMD_OPENCL_DEMOS) + SUBDIRS(AMD) +ENDIF() + +IF(BUILD_NVIDIA_OPENCL_DEMOS) + SUBDIRS(NVidia) +ENDIF() + +IF(APPLE) + SUBDIRS(Apple) +ENDIF() diff --git a/Demos/ParticlesOpenCL/Intel/CMakeLists.txt b/Demos/ParticlesOpenCL/Intel/CMakeLists.txt new file mode 100644 index 0000000..54828a5 --- /dev/null +++ b/Demos/ParticlesOpenCL/Intel/CMakeLists.txt @@ -0,0 +1,87 @@ + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL +${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +${INTEL_OPENCL_INCLUDES} +) + +ADD_DEFINITIONS(-DUSE_INTEL_OPENCL) +ADD_DEFINITIONS(-DCL_PLATFORM_INTEL) + + +IF (CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY + ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew64.lib ) +ELSE(CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew32.lib ) +ENDIF(CMAKE_CL_64) + + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport + BulletDynamics + BulletCollision + BulletMultiThreaded + LinearMath + ${GLUT_glut_LIBRARY} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${CMAK_GLEW_LIBRARY} + ${INTEL_OPENCL_LIBRARIES} + ) + + + ADD_EXECUTABLE(AppParticlesOCL_Intel + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesDynamicsWorld.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesSharedDefs.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesSharedTypes.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesDemo.h + + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/shaders.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLInclude.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesDemoDynamicsWorld.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/main.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesDemo.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/shaders.cpp + + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesOCL.cl + ) +ELSE (USE_GLUT) +ENDIF (USE_GLUT) + +IF(WIN32) +IF (CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Intel POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} ) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Intel POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLEW64.DLL ${CMAKE_CURRENT_BINARY_DIR}) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Intel POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesOCL.cl ${CMAKE_CURRENT_BINARY_DIR}) + ENDIF() +ELSE(CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Intel POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR}) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Intel POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLEW32.DLL ${CMAKE_CURRENT_BINARY_DIR}) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Intel POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesOCL.cl ${CMAKE_CURRENT_BINARY_DIR}) + ENDIF() +ENDIF(CMAKE_CL_64) +ENDIF(WIN32) + +IF (UNIX) + TARGET_LINK_LIBRARIES(AppParticlesOCL_Intel pthread) +ENDIF(UNIX) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppParticlesOCL_Intel PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppParticlesOCL_Intel PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppParticlesOCL_Intel PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) diff --git a/Demos/ParticlesOpenCL/MiniCL/CMakeLists.txt b/Demos/ParticlesOpenCL/MiniCL/CMakeLists.txt new file mode 100644 index 0000000..b97fe0b --- /dev/null +++ b/Demos/ParticlesOpenCL/MiniCL/CMakeLists.txt @@ -0,0 +1,94 @@ + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL +${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +ADD_DEFINITIONS(-DUSE_MINICL) + +#to get this to compile under linux, you could try setting CMAK_GLEW_LIBRARY +#to /usr/lib/libGLEW.so + +IF(WIN32) +ADD_DEFINITIONS(-DGLEW_STATIC) +ENDIF(WIN32) + +IF(WIN32) +IF (CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew64s.lib ) +ELSE(CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew32s.lib ) +ENDIF(CMAKE_CL_64) +ENDIF(WIN32) + +IF(UNIX AND NOT APPLE) + SET(CMAK_GLEW_LIBRARY /usr/lib/libGLEW.so ) +ENDIF(UNIX AND NOT APPLE) + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport + BulletDynamics + BulletCollision + MiniCL + BulletMultiThreaded + LinearMath + ${GLUT_glut_LIBRARY} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${CMAK_GLEW_LIBRARY} + ) + + + ADD_EXECUTABLE(AppParticlesOCL_Mini + + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesDynamicsWorld.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesSharedDefs.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesSharedTypes.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesDemoDynamicsWorld.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/main.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesDemo.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/shaders.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/shaders.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/MiniCL/MiniCLTaskWrap.cpp + + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLInclude.h + + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesOCL.cl + ) +ELSE (USE_GLUT) +ENDIF (USE_GLUT) + + +IF(WIN32) +IF (CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Mini POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} ) + ENDIF() +ELSE(CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Mini POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR}) + ENDIF() +ENDIF(CMAKE_CL_64) +ENDIF(WIN32) + +ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Mini POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesOCL.cl ${CMAKE_CURRENT_BINARY_DIR}) + + +IF (UNIX) + TARGET_LINK_LIBRARIES(AppParticlesOCL_Mini pthread) +ENDIF(UNIX) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppParticlesOCL_Mini PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppParticlesOCL_Mini PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppParticlesOCL_Mini PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/ParticlesOpenCL/MiniCL/MiniCLTaskWrap.cpp b/Demos/ParticlesOpenCL/MiniCL/MiniCLTaskWrap.cpp new file mode 100644 index 0000000..9f0c023 --- /dev/null +++ b/Demos/ParticlesOpenCL/MiniCL/MiniCLTaskWrap.cpp @@ -0,0 +1,33 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +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 + +#define MSTRINGIFY(A) A +#define LOCAL_SIZE_MAX 1024U + +#include "../ParticlesOCL.cl" + +MINICL_REGISTER(kComputeCellId) +MINICL_REGISTER(kClearCellStart) +MINICL_REGISTER(kFindCellStart) +MINICL_REGISTER(kIntegrateMotion) +MINICL_REGISTER(kCollideParticles) +MINICL_REGISTER(kBitonicSortCellIdLocal) +MINICL_REGISTER(kBitonicSortCellIdLocal1) +MINICL_REGISTER(kBitonicSortCellIdMergeGlobal) +MINICL_REGISTER(kBitonicSortCellIdMergeLocal) + diff --git a/Demos/ParticlesOpenCL/NVidia/CMakeLists.txt b/Demos/ParticlesOpenCL/NVidia/CMakeLists.txt new file mode 100644 index 0000000..1241f21 --- /dev/null +++ b/Demos/ParticlesOpenCL/NVidia/CMakeLists.txt @@ -0,0 +1,95 @@ + + +ADD_DEFINITIONS(-DUSE_NVIDIA_OPENCL) +ADD_DEFINITIONS(-DCL_PLATFORM_NVIDIA) + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL +${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +${NVIDIA_OPENCL_INCLUDES} +) + +IF(WIN32) +ADD_DEFINITIONS(-DGLEW_STATIC) +ENDIF(WIN32) + +IF(WIN32) + IF (CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew64s.lib ) + ELSE(CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew32s.lib ) + ENDIF(CMAKE_CL_64) +ELSE() + IF(UNIX AND NOT APPLE) + FIND_LIBRARY(CMAK_GLEW_LIBRARY GLEW PATH /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 ) + ENDIF() +ENDIF(WIN32) + +IF(CMAK_GLEW_LIBRARY) + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport + BulletDynamics + BulletCollision + LinearMath + ${GLUT_glut_LIBRARY} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${CMAK_GLEW_LIBRARY} + ${NVIDIA_OPENCL_LIBRARIES} + ) + + ADD_EXECUTABLE(AppParticlesOCL_Nv + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesDynamicsWorld.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesSharedDefs.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesSharedTypes.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/shaders.h + + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLInclude.h + + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/btParticlesDemoDynamicsWorld.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/main.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesDemo.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/shaders.cpp + + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesOCL.cl + ) +ELSE (USE_GLUT) +ENDIF (USE_GLUT) + +IF(WIN32) +IF (CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Nv POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} ) + ENDIF() +ELSE(CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Nv POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR}) + ENDIF() +ENDIF(CMAKE_CL_64) + + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppParticlesOCL_Nv POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Demos/ParticlesOpenCL/ParticlesOCL.cl ${CMAKE_CURRENT_BINARY_DIR}) + ENDIF() +ENDIF(WIN32) + +IF (UNIX) + TARGET_LINK_LIBRARIES(AppParticlesOCL_Nv pthread) +ENDIF(UNIX) + +ENDIF(CMAK_GLEW_LIBRARY) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppParticlesOCL_Nv PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppParticlesOCL_Nv PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppParticlesOCL_Nv PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/ParticlesOpenCL/ParticlesDemo.cpp b/Demos/ParticlesOpenCL/ParticlesDemo.cpp new file mode 100644 index 0000000..64f0b47 --- /dev/null +++ b/Demos/ParticlesOpenCL/ParticlesDemo.cpp @@ -0,0 +1,651 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006 - 2009 Sony Computer Entertainment Inc. + +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. +*/ + +#define START_POS_X btScalar(0.f) +#define START_POS_Y btScalar(0.f) +#define START_POS_Z btScalar(0.f) +//#define START_POS_Y btScalar(40.f) +//#define START_POS_Z btScalar(40.f) +//#define START_POS_Y btScalar(0.4f) +//#define START_POS_Z btScalar(0.4f) +#define ARRAY_SIZE_X 32 +#define ARRAY_SIZE_Y 32 +//#define ARRAY_SIZE_Y 16 +#define ARRAY_SIZE_Z 32 +//16 +//#define ARRAY_SIZE_Z 1 +//#define DIST btScalar(2.f) +#define DIST (DEF_PARTICLE_RADIUS * 2.f) + +#define STRESS_X 20 +//#define STRESS_Y 200 +#define STRESS_Y 640 + + + + + +///The 3 following lines include the CPU implementation of the kernels, keep them in this order. +#include "BulletMultiThreaded/btGpuDefines.h" +#include "BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#include "BulletMultiThreaded/btGpuUtilsSharedCode.h" +#ifndef __APPLE__ +#include +#endif + + +#include "GL_DialogDynamicsWorld.h" +#include "GL_DialogWindow.h" + + + +#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" +#include "GLDebugFont.h" +#include "GlutStuff.h" +///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files. +#include "btBulletDynamicsCommon.h" +#include //printf debugging +#include "shaders.h" + +#include "ParticlesDemo.h" + + + + + +btScalar gTimeStep = 0.5f;//btScalar(1./60.); + +#define SCALING btScalar(1.f) + +void ParticlesDemo::clientMoveAndDisplay() +{ + + + updateCamera(); + glDisable(GL_LIGHTING); + glColor3f(1.f, 1.f, 1.f); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glDisable(GL_TEXTURE_2D); // we always draw wireframe in this demo + + //simple dynamics world doesn't handle fixed-time-stepping + float ms = getDeltaTimeMicroseconds(); + + renderme(); + + if (m_dialogDynamicsWorld) + m_dialogDynamicsWorld->draw(gTimeStep); + + ///step the simulation + if (m_dynamicsWorld) + { + m_dynamicsWorld->stepSimulation(gTimeStep,0);//ms / 1000000.f); + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + } + + + + ms = getDeltaTimeMicroseconds(); + + glFlush(); + + glutSwapBuffers(); + +} + + + +void ParticlesDemo::displayCallback(void) { + + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + //optional but useful: debug drawing to detect problems + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + //if (m_dialogDynamicsWorld) + // m_dialogDynamicsWorld->draw(gTimeStep); + + glFlush(); + glutSwapBuffers(); +} + +class btNullBroadphase : public btBroadphaseInterface +{ +public: + btNullBroadphase() + { + } + virtual ~btNullBroadphase() + { + } + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) + { + return NULL; + } + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) + { + } + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher) + { + } + virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const + { + } + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)) + { + } + virtual void calculateOverlappingPairs(btDispatcher* dispatcher) + { + } + virtual btOverlappingPairCache* getOverlappingPairCache() + { + return NULL; + } + virtual const btOverlappingPairCache* getOverlappingPairCache() const + { + return NULL; + } + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + } + virtual void resetPool(btDispatcher* dispatcher) + { + } + virtual void printStats() + { + } + virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) + { + } +}; + + + +void ParticlesDemo::initPhysics() +{ + + setTexturing(false); + setShadows(false); + +// setCameraDistance(80.f); + setCameraDistance(3.0f); +// m_cameraTargetPosition.setValue(50, 10, 0); + m_cameraTargetPosition.setValue(0, 0, 0); +// m_azi = btScalar(0.f); +// m_ele = btScalar(0.f); + m_azi = btScalar(45.f); + m_ele = btScalar(30.f); + setFrustumZPlanes(0.1f, 10.f); + + ///collision configuration contains default setup for memory, collision setup + + btDefaultCollisionConstructionInfo dci; + dci.m_defaultMaxPersistentManifoldPoolSize=50000; + dci.m_defaultMaxCollisionAlgorithmPoolSize=50000; + + m_collisionConfiguration = new btDefaultCollisionConfiguration(dci); + + ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + + m_pairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16))btHashedOverlappingPairCache(); + + +// m_broadphase = new btDbvtBroadphase(m_pairCache); + m_broadphase = new btNullBroadphase(); + + ///the default constraint solver + m_solver = new btSequentialImpulseConstraintSolver(); + + m_pWorld = new btParticlesDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration, 65536); + + m_dialogDynamicsWorld = new GL_DialogDynamicsWorld(); + GL_DialogWindow* settings = m_dialogDynamicsWorld->createDialog(50,0,280,280,"CPU fallback"); + + m_pWorld->m_useCpuControls[0] = 0; + GL_ToggleControl* ctrl = 0; + m_pWorld->m_useCpuControls[SIMSTAGE_INTEGRATE_MOTION] = m_dialogDynamicsWorld->createToggle(settings,"Integrate Motion"); + m_pWorld->m_useCpuControls[SIMSTAGE_COMPUTE_CELL_ID] = m_dialogDynamicsWorld->createToggle(settings,"Compute Cell ID"); + m_pWorld->m_useCpuControls[SIMSTAGE_SORT_CELL_ID] = m_dialogDynamicsWorld->createToggle(settings,"Sort Cell ID"); + m_pWorld->m_useCpuControls[SIMSTAGE_FIND_CELL_START] = m_dialogDynamicsWorld->createToggle(settings,"Find Cell Start"); + m_pWorld->m_useCpuControls[SIMSTAGE_COLLIDE_PARTICLES] = m_dialogDynamicsWorld->createToggle(settings,"Collide Particles"); + + + for(int i = 1; i < SIMSTAGE_TOTAL; i++) + { + m_pWorld->m_useCpuControls[i]->m_active = false; + } +#if defined(CL_PLATFORM_MINI_CL) + // these kernels use barrier() + m_pWorld->m_useCpuControls[SIMSTAGE_SORT_CELL_ID]->m_active = true; + m_pWorld->m_useCpuControls[SIMSTAGE_FIND_CELL_START]->m_active = true; +#endif + +#if defined(CL_PLATFORM_AMD) + // these kernels use barrier() + m_pWorld->m_useCpuControls[SIMSTAGE_SORT_CELL_ID]->m_active = true; + m_pWorld->m_useCpuControls[SIMSTAGE_FIND_CELL_START]->m_active = true; +#endif + + + m_dynamicsWorld = m_pWorld; + + m_pWorld->getSimulationIslandManager()->setSplitIslands(true); + m_pWorld->setGravity(btVector3(0,-10.,0)); + m_pWorld->getSolverInfo().m_numIterations = 4; + + { +// btCollisionShape* colShape = new btSphereShape(btScalar(1.0f)); +/* + btCollisionShape* colShape = new btSphereShape(DEF_PARTICLE_RADIUS); + m_collisionShapes.push_back(colShape); + btTransform startTransform; + startTransform.setIdentity(); + btScalar mass(1.f); + btVector3 localInertia(0,0,0); + colShape->calculateLocalInertia(mass,localInertia); + float start_x = START_POS_X - ARRAY_SIZE_X * DIST * btScalar(0.5f); + float start_y = START_POS_Y - ARRAY_SIZE_Y * DIST * btScalar(0.5f); + float start_z = START_POS_Z - ARRAY_SIZE_Z * DIST * btScalar(0.5f); + startTransform.setOrigin(btVector3(start_x, start_y, start_z)); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape,localInertia); + rbInfo.m_startWorldTransform = startTransform; + btRigidBody* body = new btRigidBody(rbInfo); + m_pWorld->addRigidBody(body); + */ + + init_scene_directly(); + } + clientResetScene(); + m_pWorld->initDeviceData(); +} + +inline float frand(void){ + return (float)rand() / (float)RAND_MAX; +} + +void ParticlesDemo::init_scene_directly() +{ + + + srand(1969); + float start_x = -1+DEF_PARTICLE_RADIUS;//START_POS_X - ARRAY_SIZE_X * DIST * btScalar(0.5f); + float start_y = -1+DEF_PARTICLE_RADIUS;//START_POS_Y - ARRAY_SIZE_Y * DIST * btScalar(0.5f); + float start_z = -1+DEF_PARTICLE_RADIUS;//START_POS_Z - ARRAY_SIZE_Z * DIST * btScalar(0.5f); + int numParticles = ARRAY_SIZE_X * ARRAY_SIZE_Y * ARRAY_SIZE_Z; + m_pWorld->m_hPos.resize(numParticles); + m_pWorld->m_hVel.resize(numParticles); + + btScalar spacing = 2 * DEF_PARTICLE_RADIUS; + + for(int z=0; zm_hVel[i]= btVector3(0,0,0); + m_pWorld->m_hPos[i].setX((spacing * x) + 2*DEF_PARTICLE_RADIUS -WORLD_SIZE+jitter.getX()); + m_pWorld->m_hPos[i].setY((spacing * y) + 2*DEF_PARTICLE_RADIUS -WORLD_SIZE+jitter.getY()); + m_pWorld->m_hPos[i].setZ((spacing * z) + 2*DEF_PARTICLE_RADIUS -WORLD_SIZE+jitter.getZ()); + } + } + } + } + + m_pWorld->m_numParticles = numParticles; + +} + + +void ParticlesDemo::clientResetScene() +{ + static bool bFirstCall = true; + DemoApplication::clientResetScene(); + init_scene_directly(); + if(bFirstCall) + { + bFirstCall = false; + } + else + { + + m_pWorld->grabSimulationData(); + } +} + + +void ParticlesDemo::exitPhysics() +{ + delete m_dialogDynamicsWorld; + m_dialogDynamicsWorld = 0; + + //cleanup in the reverse order of creation/initialization + int i; + + //remove the rigidbodies from the dynamics world and delete them + for (i=m_pWorld->getNumCollisionObjects()-1; i>=0 ;i--) + { + btCollisionObject* obj = m_pWorld->getCollisionObjectArray()[i]; + btRigidBody* body = btRigidBody::upcast(obj); + if (body && body->getMotionState()) + { + delete body->getMotionState(); + } + m_pWorld->removeCollisionObject( obj ); + delete obj; + } + //delete collision shapes + for (int j=0;j m_glutScreenHeight) ? m_glutScreenHeight : m_glutScreenWidth; + glUniform1f( glGetUniformLocation(m_shaderProgram, "pointScale"), dist ); +// glUniform1f( glGetUniformLocation(m_shaderProgram, "pointRadius"), 0.5f ); + int numParticles = m_pWorld->getNumParticles(); + int col_vbo = m_pWorld->m_colVbo; + int curr_vbo = m_pWorld->m_vbo; + float sphere_rad = m_pWorld->m_particleRad; + + glUniform1f( glGetUniformLocation(m_shaderProgram, "pointRadius"), sphere_rad ); + glColor3f(1, 1, 1); + + // render from the vbo + glBindBuffer(GL_ARRAY_BUFFER, curr_vbo); + glVertexPointer(4, GL_FLOAT, 0, 0); + glEnableClientState(GL_VERTEX_ARRAY); + if(col_vbo) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, col_vbo); + glColorPointer(4, GL_FLOAT, 0, 0); + glEnableClientState(GL_COLOR_ARRAY); + } + glDrawArrays(GL_POINTS, 0, numParticles); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glUseProgram(0); + glDisable(GL_POINT_SPRITE_ARB); + glBindBufferARB(GL_ARRAY_BUFFER,0); + if(m_drawGridMode) + { + btVector3& wmin = m_pWorld->m_worldMin; + btVector3& wmax = m_pWorld->m_worldMax; + glBegin(GL_LINE_LOOP); + glVertex3f(wmin[0], wmin[1], wmin[2]); + glVertex3f(wmin[0], wmax[1], wmin[2]); + glVertex3f(wmax[0], wmax[1], wmin[2]); + glVertex3f(wmax[0], wmin[1], wmin[2]); + glVertex3f(wmax[0], wmin[1], wmax[2]); + glVertex3f(wmax[0], wmax[1], wmax[2]); + glVertex3f(wmin[0], wmax[1], wmax[2]); + glVertex3f(wmin[0], wmin[1], wmax[2]); + glEnd(); + glBegin(GL_LINES); + glVertex3f(wmin[0], wmin[1], wmin[2]); + glVertex3f(wmax[0], wmin[1], wmin[2]); + glVertex3f(wmin[0], wmin[1], wmax[2]); + glVertex3f(wmax[0], wmin[1], wmax[2]); + glVertex3f(wmin[0], wmax[1], wmin[2]); + glVertex3f(wmin[0], wmax[1], wmax[2]); + glVertex3f(wmax[0], wmax[1], wmin[2]); + glVertex3f(wmax[0], wmax[1], wmax[2]); + glEnd(); + if(m_drawGridMode == 2) + { + int szx = m_pWorld->m_simParams.m_gridSize[0]; + int szy = m_pWorld->m_simParams.m_gridSize[1]; + glBegin(GL_LINES); + for(int i = 1; i < (szx-1); i++) + { + float wgt = (float)i / (float)(szx-1); + btVector3 vtx = wmax * wgt + wmin * (1.0f - wgt); + glVertex3f(vtx[0], wmin[1], wmin[2]); + glVertex3f(vtx[0], wmax[1], wmin[2]); + } + for(int i = 1; i < (szy-1); i++) + { + float wgt = (float)i / (float)(szy-1); + btVector3 vtx = wmax * wgt + wmin * (1.0f - wgt); + glVertex3f(wmin[0], vtx[1], wmin[2]); + glVertex3f(wmax[0], vtx[1], wmin[2]); + } + glEnd(); + } + } + + if ((m_debugMode & btIDebugDraw::DBG_NoHelpText)==0) + { + setOrthographicProjection(); + int xOffset = 10.f; + int yStart = 20.f; + int yIncr = 20.f; + showProfileInfo(xOffset, yStart, yIncr); + outputDebugInfo(xOffset, yStart, yIncr); + resetPerspectiveProjection(); + } +} + + + +void ParticlesDemo::outputDebugInfo(int & xOffset,int & yStart, int yIncr) +{ + char buf[124]; + glDisable(GL_LIGHTING); + glColor3f(0, 0, 0); + + sprintf(buf,"mouse move+buttons to interact"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + sprintf(buf,"space to reset"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + sprintf(buf,"cursor keys and z,x to navigate"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + sprintf(buf,"i to toggle simulation, s single step"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + sprintf(buf,"q to quit"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + sprintf(buf,"h to toggle help text"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + + sprintf(buf,"p to toggle profiling (+results to file)"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + sprintf(buf,"j to toggle between demos (integration/OECake2D/OECake3D)"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + { + sprintf(buf,"G to draw broadphase grid"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + sprintf(buf,"D and U to toggle between GPU and CPU"); + GLDebugDrawString(xOffset,yStart,buf); + yStart += yIncr; + + } + +} + + +GLuint _compileProgram(const char *vsource, const char *fsource) +{ + GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); + GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + + glShaderSource(vertexShader, 1, &vsource, 0); + glShaderSource(fragmentShader, 1, &fsource, 0); + + glCompileShader(vertexShader); + glCompileShader(fragmentShader); + + GLuint program = glCreateProgram(); + + glAttachShader(program, vertexShader); + glAttachShader(program, fragmentShader); + + glLinkProgram(program); + + // check if program linked + GLint success = 0; + glGetProgramiv(program, GL_LINK_STATUS, &success); + + if (!success) { + char temp[256]; + glGetProgramInfoLog(program, 256, 0, temp); + printf("Failed to link program:\n%s\n", temp); + glDeleteProgram(program); + program = 0; + } + return program; +} + + +void ParticlesDemo::myinit() +{ + DemoApplication::myinit(); +#ifndef __APPLE__ + glewInit(); + if (!glewIsSupported("GL_VERSION_2_0 GL_VERSION_1_5 GL_ARB_multitexture GL_ARB_vertex_buffer_object")) { + fprintf(stderr, "Required OpenGL extensions missing."); + exit(-1); + } +#endif //__APPLE__ + + m_shaderProgram = _compileProgram(vertexShader, spherePixelShader); + m_pWorld->initCLKernels(m_argc, m_argv); +} + + + + + + +void ParticlesDemo::mouseFunc(int button, int state, int x, int y) +{ + + if (!m_dialogDynamicsWorld->mouseFunc(button,state,x,y)) + { + DemoApplication::mouseFunc(button,state,x,y); + } +} + +void ParticlesDemo::mouseMotionFunc(int x,int y) +{ + m_dialogDynamicsWorld->mouseMotionFunc(x,y); + DemoApplication::mouseMotionFunc(x,y); +} + + + +void ParticlesDemo::reshape(int w, int h) +{ + if (m_dialogDynamicsWorld) + m_dialogDynamicsWorld->setScreenSize(w,h); + GlutDemoApplication::reshape(w,h); +} + diff --git a/Demos/ParticlesOpenCL/ParticlesDemo.h b/Demos/ParticlesOpenCL/ParticlesDemo.h new file mode 100644 index 0000000..76c165b --- /dev/null +++ b/Demos/ParticlesOpenCL/ParticlesDemo.h @@ -0,0 +1,128 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006 - 2009 Sony Computer Entertainment Inc. + +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 SPHERES_GRID_DEMO_H +#define SPHERES_GRID_DEMO_H + +#define USE_BULLET_BODIES 0 + +///enable one or both options (NVidia profiler doesn't support multi-OpenCL context) +#define INTEGRATION_DEMO 1 +#define SPHERES_DEMO 1 + +#include "DemoApplication.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" + +#include "btParticlesDynamicsWorld.h" + +class btBroadphaseInterface; +class btCollisionShape; +class btOverlappingPairCache; +class btCollisionDispatcher; +class btConstraintSolver; +struct btCollisionAlgorithmCreateFunc; +class btDefaultCollisionConfiguration; +#include "../OpenGL/GlutDemoApplication.h" + + +///BasicDemo is good starting point for learning the code base and porting. +class ParticlesDemo : public GlutDemoApplication +{ + + class GL_DialogDynamicsWorld* m_dialogDynamicsWorld; + //keep the collision shapes, for deletion/cleanup + btAlignedObjectArray m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + btOverlappingPairCache* m_pairCache; + + int m_mouseButtons; + int m_mouseOldX; + int m_mouseOldY; + + int m_argc; + char** m_argv; + + public: + + int m_drawGridMode; + int m_GpuCpuTogglePtr; + + btParticlesDynamicsWorld* m_pWorld; + + + // shader + GLuint m_shaderProgram; + + ParticlesDemo(int argc, char** argv) + { + m_argc = argc; + m_argv = argv; + m_drawGridMode = 0; + m_GpuCpuTogglePtr = SIMSTAGE_NONE; + m_dialogDynamicsWorld = 0; + } + virtual ~ParticlesDemo() + { + exitPhysics(); + } + void initPhysics(); + + void exitPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + virtual void keyboardCallback(unsigned char key, int x, int y); + + virtual void clientResetScene(); + + virtual void mouseFunc(int button, int state, int x, int y); + virtual void mouseMotionFunc(int x,int y); + virtual void reshape(int w, int h); +/* + static DemoApplication* Create() + { + SpheresGridDemo* demo = new SpheresGridDemo; + demo->myinit(); + demo->initPhysics(); + demo->m_mouseButtons = 0; + demo->m_mouseOldX = 0; + demo->m_mouseOldY = 0; + return demo; + } +*/ + + void outputDebugInfo(int & xOffset,int & yStart, int yIncr); + + + virtual void renderme(); + virtual void myinit(); + void init_scene_directly(); + +}; + + +#endif // PARTICLES_DEMO_H + diff --git a/Demos/ParticlesOpenCL/ParticlesOCL.cl b/Demos/ParticlesOpenCL/ParticlesOCL.cl new file mode 100644 index 0000000..2e80e3a --- /dev/null +++ b/Demos/ParticlesOpenCL/ParticlesOCL.cl @@ -0,0 +1,467 @@ +MSTRINGIFY( + +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006 - 2009 Sony Computer Entertainment Inc. + +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. +*/ + + + +int4 getGridPos(float4 worldPos, __global float4* pParams) +{ + int4 gridPos; + gridPos.x = (int)floor((worldPos.x - pParams[1].x) / pParams[3].x); + gridPos.y = (int)floor((worldPos.y - pParams[1].y) / pParams[3].y); + gridPos.z = (int)floor((worldPos.z - pParams[1].z) / pParams[3].z); + return gridPos; +} + +unsigned int getPosHash(int4 gridPos, __global float4* pParams) +{ + int4 gridDim = *((__global int4*)(pParams + 4)); + if(gridPos.x < 0) gridPos.x = 0; + if(gridPos.x >= gridDim.x) gridPos.x = gridDim.x - 1; + if(gridPos.y < 0) gridPos.y = 0; + if(gridPos.y >= gridDim.y) gridPos.y = gridDim.y - 1; + if(gridPos.z < 0) gridPos.z = 0; + if(gridPos.z >= gridDim.z) gridPos.z = gridDim.z - 1; + unsigned int hash = gridPos.z * gridDim.y * gridDim.x + gridPos.y * gridDim.x + gridPos.x; + return hash; +} + + +__kernel void kComputeCellId( int numParticles, + __global float4* pPos, + __global int2* pPosHash, + __global float4* pParams GUID_ARG) +{ + int index = get_global_id(0); + if(index >= numParticles) + { + return; + } + float4 pos = pPos[index]; + int4 gridPos = getGridPos(pos, pParams); + unsigned int hash = getPosHash(gridPos, pParams); + pPosHash[index].x = hash; + pPosHash[index].y = index; +} + +__kernel void kClearCellStart( int numCells, + __global int* pCellStart GUID_ARG) +{ + int index = get_global_id(0); + if(index >= numCells) + { + return; + } + pCellStart[index] = -1; +} + +__kernel void kFindCellStart( int numParticles, + __global int2* pHash, + __global int* cellStart, + __global float4* pPos, + __global float4* pVel, + __global float4* pSortedPos, + __global float4* pSortedVel GUID_ARG) +{ + int index = get_global_id(0); + __local int sharedHash[1025];//maximum workgroup size 1024 + int2 sortedData; + + if(index < numParticles) + { + + sortedData = pHash[index]; + // Load hash data into shared memory so that we can look + // at neighboring body's hash value without loading + // two hash values per thread + sharedHash[get_local_id(0) + 1] = sortedData.x; + if((index > 0) && (get_local_id(0) == 0)) + { + // first thread in block must load neighbor body hash + sharedHash[0] = pHash[index-1].x; + } + + } + barrier(CLK_LOCAL_MEM_FENCE); + + if(index < numParticles) + { + if((index == 0) || (sortedData.x != sharedHash[get_local_id(0)])) + { + cellStart[sortedData.x] = index; + } + int unsortedIndex = sortedData.y; + float4 pos = pPos[unsortedIndex]; + float4 vel = pVel[unsortedIndex]; + pSortedPos[index] = pos; + pSortedVel[index] = vel; + } +} + +__kernel void kIntegrateMotion( int numParticles, + __global float4* pPos, + __global float4* pVel, + __global float4* pParams, + float timeStep GUID_ARG) +{ + int index = get_global_id(0); + if(index >= numParticles) + { + return; + } + float4 pos = pPos[index]; + float4 vel = pVel[index]; + pos.w = 1.0f; + vel.w = 0.0f; + // apply gravity + float4 gravity = *((__global float4*)(pParams + 0)); + float particleRad = pParams[5].x; + float globalDamping = pParams[5].y; + float boundaryDamping = pParams[5].z; + vel += gravity * timeStep; + vel *= globalDamping; + // integrate position + pos += vel * timeStep; + // collide with world boundaries + float4 worldMin = *((__global float4*)(pParams + 1)); + float4 worldMax = *((__global float4*)(pParams + 2)); + + + if(pos.x < (worldMin.x + 2*particleRad)) + { + pos.x = worldMin.x + 2*particleRad; + vel.x *= boundaryDamping; + } + if(pos.x > (worldMax.x - 2*particleRad)) + { + pos.x = worldMax.x - 2*particleRad; + vel.x *= boundaryDamping; + } + if(pos.y < (worldMin.y + 2*particleRad)) + { + pos.y = worldMin.y + 2*particleRad; + vel.y *= boundaryDamping; + } + if(pos.y > (worldMax.y - 2*particleRad)) + { + pos.y = worldMax.y - 2*particleRad; + vel.y *= boundaryDamping; + } + if(pos.z < (worldMin.z + 2*particleRad)) + { + pos.z = worldMin.z + 2*particleRad; + vel.z *= boundaryDamping; + } + if(pos.z > (worldMax.z - 2*particleRad)) + { + pos.z = worldMax.z - 2*particleRad; + vel.z *= boundaryDamping; + } + // write back position and velocity + pPos[index] = pos; + pVel[index] = vel; +} + + +float4 collideTwoParticles( + float4 posA, + float4 posB, + float4 velA, + float4 velB, + float radiusA, + float radiusB, + float spring, + float damping, + float shear, + float attraction +) +{ + //Calculate relative position + float4 relPos = posB - posA; relPos.w = 0.f; + float dist = sqrt(relPos.x * relPos.x + relPos.y * relPos.y + relPos.z * relPos.z); + float collideDist = radiusA + radiusB; + + float4 force = (float4)0.f; + if(dist < collideDist){ + float4 norm = relPos * (1.f / dist); norm.w = 0.f; + + //Relative velocity + float4 relVel = velB - velA; relVel.w = 0.f; + + //Relative tangential velocity + float relVelDotNorm = relVel.x * norm.x + relVel.y * norm.y + relVel.z * norm.z; + float4 tanVel = relVel - norm * relVelDotNorm; tanVel.w = 0.f; + + //Spring force (potential) + float springFactor = -spring * (collideDist - dist); + force = springFactor * norm + damping * relVel + shear * tanVel + attraction * relPos; + force.w = 0.f; + } + return force; +} + + +__kernel void kCollideParticles(int numParticles, + __global float4* pVel, //output: new velocity + __global const float4* pSortedPos, //input: reordered positions + __global const float4* pSortedVel, //input: reordered velocities + __global const int2 *pPosHash, //input: reordered particle indices + __global const int *pCellStart, //input: cell boundaries + __global float4* pParams GUID_ARG) +{ + int index = get_global_id(0); + if(index >= numParticles) + { + return; + } + + float4 posA = pSortedPos[index]; + float4 velA = pSortedVel[index]; + float4 force = (float4)0.f; + float particleRad = pParams[5].x; + float collisionDamping = pParams[5].w; + float spring = pParams[6].x; + float shear = pParams[6].y; + float attraction = pParams[6].z; + int unsortedIndex = pPosHash[index].y; + + //Get address in grid + int4 gridPosA = getGridPos(posA, pParams); + + //Accumulate surrounding cells + int4 gridPosB; + for(int z = -1; z <= 1; z++) + { + gridPosB.z = gridPosA.z + z; + for(int y = -1; y <= 1; y++) + { + gridPosB.y = gridPosA.y + y; + for(int x = -1; x <= 1; x++) + { + gridPosB.x = gridPosA.x + x; + //Get start particle index for this cell + uint hashB = getPosHash(gridPosB, pParams); + int startI = pCellStart[hashB]; + //Skip empty cell + if(startI < 0) + { + continue; + } + //Iterate over particles in this cell + int endI = startI + 32; + if(endI >= numParticles) + endI = numParticles ; + + for(int j = startI; j < endI; j++) + { + uint hashC = pPosHash[j].x; + if(hashC != hashB) + { + break; + } + if(j == index) + { + continue; + } + float4 posB = pSortedPos[j]; + float4 velB = pSortedVel[j]; + //Collide two spheres + force += collideTwoParticles( posA, posB, velA, velB, particleRad, particleRad, + spring, collisionDamping, shear, attraction); + } + } + } + } + //Write new velocity back to original unsorted location + pVel[unsortedIndex] = velA + force; +} + + + + + + +/* + * Copyright 1993-2009 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property and + * proprietary rights in and to this software and related documentation. + * Any use, reproduction, disclosure, or distribution of this software + * and related documentation without an express license agreement from + * NVIDIA Corporation is strictly prohibited. + * + * Please refer to the applicable NVIDIA end user license agreement (EULA) + * associated with this source code for terms and conditions that govern + * your use of this NVIDIA software. + * + */ + + + +inline void ComparatorPrivate(int2* keyA, int2* keyB, uint dir) +{ + if((keyA[0].x > keyB[0].x) == dir) + { + int2 tmp = *keyA; + *keyA = *keyB; + *keyB = tmp; + } +} + +inline void ComparatorLocal(__local int2* keyA, __local int2* keyB, uint dir) +{ + if((keyA[0].x > keyB[0].x) == dir) + { + int2 tmp = *keyA; + *keyA = *keyB; + *keyB = tmp; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Monolithic bitonic sort kernel for short arrays fitting into local memory +//////////////////////////////////////////////////////////////////////////////// +__kernel void kBitonicSortCellIdLocal(__global int2* pKey, uint arrayLength, uint dir GUID_ARG) +{ + __local int2 l_key[LOCAL_SIZE_MAX]; + int localSizeLimit = get_local_size(0) * 2; + + //Offset to the beginning of subbatch and load data + pKey += get_group_id(0) * localSizeLimit + get_local_id(0); + l_key[get_local_id(0) + 0] = pKey[ 0]; + l_key[get_local_id(0) + (localSizeLimit / 2)] = pKey[(localSizeLimit / 2)]; + + for(uint size = 2; size < arrayLength; size <<= 1) + { + //Bitonic merge + uint ddd = dir ^ ( (get_local_id(0) & (size / 2)) != 0 ); + for(uint stride = size / 2; stride > 0; stride >>= 1) + { + barrier(CLK_LOCAL_MEM_FENCE); + uint pos = 2 * get_local_id(0) - (get_local_id(0) & (stride - 1)); + ComparatorLocal(&l_key[pos + 0], &l_key[pos + stride], ddd); + } + } + + //ddd == dir for the last bitonic merge step + { + for(uint stride = arrayLength / 2; stride > 0; stride >>= 1) + { + barrier(CLK_LOCAL_MEM_FENCE); + uint pos = 2 * get_local_id(0) - (get_local_id(0) & (stride - 1)); + ComparatorLocal(&l_key[pos + 0], &l_key[pos + stride], dir); + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + pKey[ 0] = l_key[get_local_id(0) + 0]; + pKey[(localSizeLimit / 2)] = l_key[get_local_id(0) + (localSizeLimit / 2)]; +} + +//////////////////////////////////////////////////////////////////////////////// +// Bitonic sort kernel for large arrays (not fitting into local memory) +//////////////////////////////////////////////////////////////////////////////// +//Bottom-level bitonic sort +//Almost the same as bitonicSortLocal with the only exception +//of even / odd subarrays (of LOCAL_SIZE_LIMIT points) being +//sorted in opposite directions +__kernel void kBitonicSortCellIdLocal1(__global int2* pKey GUID_ARG) +{ + __local int2 l_key[LOCAL_SIZE_MAX]; + uint localSizeLimit = get_local_size(0) * 2; + + //Offset to the beginning of subarray and load data + pKey += get_group_id(0) * localSizeLimit + get_local_id(0); + l_key[get_local_id(0) + 0] = pKey[ 0]; + l_key[get_local_id(0) + (localSizeLimit / 2)] = pKey[(localSizeLimit / 2)]; + + uint comparatorI = get_global_id(0) & ((localSizeLimit / 2) - 1); + + for(uint size = 2; size < localSizeLimit; size <<= 1) + { + //Bitonic merge + uint ddd = (comparatorI & (size / 2)) != 0; + for(uint stride = size / 2; stride > 0; stride >>= 1) + { + barrier(CLK_LOCAL_MEM_FENCE); + uint pos = 2 * get_local_id(0) - (get_local_id(0) & (stride - 1)); + ComparatorLocal(&l_key[pos + 0], &l_key[pos + stride], ddd); + } + } + + //Odd / even arrays of localSizeLimit elements + //sorted in opposite directions + { + uint ddd = (get_group_id(0) & 1); + for(uint stride = localSizeLimit / 2; stride > 0; stride >>= 1) + { + barrier(CLK_LOCAL_MEM_FENCE); + uint pos = 2 * get_local_id(0) - (get_local_id(0) & (stride - 1)); + ComparatorLocal(&l_key[pos + 0], &l_key[pos + stride], ddd); + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + pKey[ 0] = l_key[get_local_id(0) + 0]; + pKey[(localSizeLimit / 2)] = l_key[get_local_id(0) + (localSizeLimit / 2)]; +} + +//Bitonic merge iteration for 'stride' >= LOCAL_SIZE_LIMIT +__kernel void kBitonicSortCellIdMergeGlobal(__global int2* pKey, uint arrayLength, uint size, uint stride, uint dir GUID_ARG) +{ + uint global_comparatorI = get_global_id(0); + uint comparatorI = global_comparatorI & (arrayLength / 2 - 1); + + //Bitonic merge + uint ddd = dir ^ ( (comparatorI & (size / 2)) != 0 ); + uint pos = 2 * global_comparatorI - (global_comparatorI & (stride - 1)); + + int2 keyA = pKey[pos + 0]; + int2 keyB = pKey[pos + stride]; + + ComparatorPrivate(&keyA, &keyB, ddd); + + pKey[pos + 0] = keyA; + pKey[pos + stride] = keyB; +} + +//Combined bitonic merge steps for +//'size' > LOCAL_SIZE_LIMIT and 'stride' = [1 .. LOCAL_SIZE_LIMIT / 2] +__kernel void kBitonicSortCellIdMergeLocal(__global int2* pKey, uint arrayLength, uint stride, uint size, uint dir GUID_ARG) +{ + __local int2 l_key[LOCAL_SIZE_MAX]; + int localSizeLimit = get_local_size(0) * 2; + + pKey += get_group_id(0) * localSizeLimit + get_local_id(0); + l_key[get_local_id(0) + 0] = pKey[ 0]; + l_key[get_local_id(0) + (localSizeLimit / 2)] = pKey[(localSizeLimit / 2)]; + + //Bitonic merge + uint comparatorI = get_global_id(0) & ((arrayLength / 2) - 1); + uint ddd = dir ^ ( (comparatorI & (size / 2)) != 0 ); + for(; stride > 0; stride >>= 1) + { + barrier(CLK_LOCAL_MEM_FENCE); + uint pos = 2 * get_local_id(0) - (get_local_id(0) & (stride - 1)); + ComparatorLocal(&l_key[pos + 0], &l_key[pos + stride], ddd); + } + + barrier(CLK_LOCAL_MEM_FENCE); + pKey[ 0] = l_key[get_local_id(0) + 0]; + pKey[(localSizeLimit / 2)] = l_key[get_local_id(0) + (localSizeLimit / 2)]; +} + +); diff --git a/Demos/ParticlesOpenCL/btParticlesDemoDynamicsWorld.cpp b/Demos/ParticlesOpenCL/btParticlesDemoDynamicsWorld.cpp new file mode 100644 index 0000000..24b4636 --- /dev/null +++ b/Demos/ParticlesOpenCL/btParticlesDemoDynamicsWorld.cpp @@ -0,0 +1,1177 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006 - 2009 Sony Computer Entertainment Inc. + +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 +#ifdef __APPLE__ +//CL_PLATFORM_MINI_CL could be defined in build system +#else +#include +#ifdef USE_MINICL + +#include //for CL_PLATFORM_MINI_CL definition +#else +#include //for CL_PLATFORM_MINI_CL definition +#endif +#endif //__APPLE__ + + +#include "btOpenCLUtils.h" + +#include "btBulletDynamicsCommon.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" +#include "LinearMath/btQuickprof.h" +#include "GlutStuff.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h" + +#include "btParticlesDynamicsWorld.h" +#include "GL_DialogWindow.h" + +//when loading from disk, you need to remove the 'MSTRINGIFY' line at the start, and ); at the end of the .cl file + +#define LOAD_FROM_MEMORY +#ifdef LOAD_FROM_MEMORY +#define MSTRINGIFY(A) #A +static const char* source= +#include "ParticlesOCL.cl" +#endif //LOAD_FROM_MEMORY + +btParticlesDynamicsWorld::~btParticlesDynamicsWorld() +{ +} + +static int gStepNum = 0; + +int btParticlesDynamicsWorld::stepSimulation( btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep) +{ + startProfiling(timeStep); + m_timeStep = timeStep; + BT_PROFILE("stepSimulation"); +// printf("Step : %d\n", gStepNum); + { + BT_PROFILE("IntegrateMotion"); + runIntegrateMotionKernel(); + } + { + runComputeCellIdKernel(); + } + { + BT_PROFILE("SortHash"); + runSortHashKernel(); + } + { + BT_PROFILE("FindCellStart"); + runFindCellStartKernel(); + } + { + BT_PROFILE("CollideParticles"); +// printf("\ncollide particles\n\n"); + runCollideParticlesKernel(); + } + gStepNum++; + +#ifndef BT_NO_PROFILE + CProfileManager::Increment_Frame_Counter(); +#endif //BT_NO_PROFILE + return 1; +} + +static unsigned int getMaxPowOf2(unsigned int num) +{ + unsigned int maxPowOf2 = 1; + for(int bit = 1; bit < 32; bit++) + { + if(maxPowOf2 >= num) + { + break; + } + maxPowOf2 <<= 1; + } + return maxPowOf2; +} + + +void btParticlesDynamicsWorld::initDeviceData() +{ + getShapeData(); +} + + + +void btParticlesDynamicsWorld::postInitDeviceData() +{ + m_hashSize = getMaxPowOf2(m_numParticles); + createVBO(); + allocateBuffers(); + adjustGrid(); + grabSimulationData(); +} + + +void btParticlesDynamicsWorld::getShapeData() +{ + int numObjects = getNumCollisionObjects(); + btCollisionObjectArray& collisionObjects = getCollisionObjectArray(); + for(int i = 0; i < numObjects; i++) + { + btCollisionObject* colObj = collisionObjects[i]; + btCollisionShape* pShape = colObj->getCollisionShape(); + int shapeType = pShape->getShapeType(); + if(shapeType == SPHERE_SHAPE_PROXYTYPE) + { + btSphereShape* pSph = (btSphereShape*)pShape; + btScalar sphRad = pSph->getRadius(); + if(!i) + { + m_particleRad = sphRad; + } + else + { + btAssert(m_particleRad == sphRad); + } + } + else + { + btAssert(0); + } + } + printf("Total number of particles : %d\n", m_numParticles); +} + +void btParticlesDynamicsWorld::allocateBuffers() +{ + cl_int ciErrNum; + // positions of spheres + m_hPos.resize(m_numParticles); + m_hVel.resize(m_numParticles); + m_hSortedPos.resize(m_numParticles); + m_hSortedVel.resize(m_numParticles); + m_hPosHash.resize(m_hashSize); + for(int i = 0; i < m_hashSize; i++) { m_hPosHash[i].x = 0x7FFFFFFF; m_hPosHash[i].y = 0; } + unsigned int memSize = sizeof(btVector3) * m_numParticles; + m_dPos = clCreateBuffer(m_cxMainContext, CL_MEM_READ_WRITE, memSize, NULL, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + m_dVel = clCreateBuffer(m_cxMainContext, CL_MEM_READ_WRITE, memSize, NULL, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + m_dSortedPos = clCreateBuffer(m_cxMainContext, CL_MEM_READ_WRITE, memSize, NULL, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + m_dSortedVel = clCreateBuffer(m_cxMainContext, CL_MEM_READ_WRITE, memSize, NULL, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + memSize = m_hashSize * sizeof(btInt2); + m_dPosHash = clCreateBuffer(m_cxMainContext, CL_MEM_READ_ONLY, memSize, NULL, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + // global simulation parameters + memSize = sizeof(btSimParams); + m_dSimParams = clCreateBuffer(m_cxMainContext, CL_MEM_READ_ONLY, memSize, NULL, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); +} + +void btParticlesDynamicsWorld::adjustGrid() +{ + //btVector3 wmin( BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT); + //btVector3 wmax(-BT_LARGE_FLOAT, -BT_LARGE_FLOAT, -BT_LARGE_FLOAT); + + btVector3 wmin( BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT); + btVector3 wmax(-BT_LARGE_FLOAT, -BT_LARGE_FLOAT, -BT_LARGE_FLOAT); + btVector3 boxDiag(m_particleRad, m_particleRad, m_particleRad); + for(int i = 0; i < m_numParticles; i++) + { + btVector3 pos = m_hPos[i]; + btVector3 boxMin = pos - boxDiag; + btVector3 boxMax = pos + boxDiag; + wmin.setMin(boxMin); + wmax.setMax(boxMax); + } + m_worldMin = wmin; + m_worldMax = wmax; + btVector3 wsize = m_worldMax - m_worldMin; + wsize[3] = 1.0f; + + glBindBufferARB(GL_ARRAY_BUFFER, m_colVbo); + btVector3* color = (btVector3*)glMapBufferARB(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + for(int i = 0; i < m_numParticles; i++, color++) + { + *color = (m_hPos[i] - m_worldMin) / wsize; + (*color)[3] = 1.f; + } + glUnmapBufferARB(GL_ARRAY_BUFFER); + +/* + wsize[0] *= 0.5f; + wsize[1] *= 0.1f; + wsize[2] *= 0.5f; + m_worldMin -= wsize; + m_worldMax += wsize; +*/ + m_worldMin.setValue(-WORLD_SIZE, -WORLD_SIZE, -WORLD_SIZE); + m_worldMax.setValue( WORLD_SIZE, WORLD_SIZE, WORLD_SIZE); + wsize = m_worldMax - m_worldMin; + + m_cellSize[0] = m_cellSize[1] = m_cellSize[2] = m_particleRad * btScalar(2.f); + + m_simParams.m_worldMin[0] = m_worldMin[0]; + m_simParams.m_worldMin[1] = m_worldMin[1]; + m_simParams.m_worldMin[2] = m_worldMin[2]; + + m_simParams.m_worldMax[0] = m_worldMax[0]; + m_simParams.m_worldMax[1] = m_worldMax[1]; + m_simParams.m_worldMax[2] = m_worldMax[2]; + + m_simParams.m_cellSize[0] = m_cellSize[0]; + m_simParams.m_cellSize[1] = m_cellSize[1]; + m_simParams.m_cellSize[2] = m_cellSize[2]; + + m_simParams.m_gridSize[0] = (int)(wsize[0] / m_cellSize[0] + 0.999999f); + m_simParams.m_gridSize[1] = (int)(wsize[1] / m_cellSize[1] + 0.999999f); + m_simParams.m_gridSize[2] = (int)(wsize[2] / m_cellSize[2] + 0.999999f); + + m_numGridCells = m_simParams.m_gridSize[0] * m_simParams.m_gridSize[1] * m_simParams.m_gridSize[2]; + m_hCellStart.resize(m_numGridCells); + unsigned int memSize = sizeof(int) * m_numGridCells; + cl_int ciErrNum; + m_dCellStart = clCreateBuffer(m_cxMainContext, CL_MEM_READ_WRITE, memSize, NULL, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + +} + + +void btParticlesDynamicsWorld::grabSimulationData() +{ +// const btVector3& gravity = getGravity(); + //btVector3 gravity(0., -0.06, 0.); + //btVector3 gravity(0., -0.0003f, 0.); + btVector3 gravity(0,-0.0003,0); + + + + m_simParams.m_gravity[0] = gravity[0]; + m_simParams.m_gravity[1] = gravity[1]; + m_simParams.m_gravity[2] = gravity[2]; + m_simParams.m_particleRad = m_particleRad; + m_simParams.m_globalDamping = 1.0f; + m_simParams.m_boundaryDamping = -0.5f; + +// m_simParams.m_collisionDamping = 0.02f; +// m_simParams.m_spring = 0.5f; +// m_simParams.m_shear = 0.1f; +// m_simParams.m_attraction = 0.0f; + m_simParams.m_collisionDamping = 0.025f;//0.02f; + m_simParams.m_spring = 0.5f; + m_simParams.m_shear = 0.1f; + m_simParams.m_attraction = 0.001f; + + + + // copy data to GPU + cl_int ciErrNum; + unsigned int memSize = sizeof(btVector3) * m_numParticles; + ciErrNum = clEnqueueWriteBuffer(m_cqCommandQue, m_dPos, CL_TRUE, 0, memSize, &(m_hPos[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + ciErrNum = clEnqueueWriteBuffer(m_cqCommandQue, m_dVel, CL_TRUE, 0, memSize, &(m_hVel[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + memSize = sizeof(btSimParams); + ciErrNum = clEnqueueWriteBuffer(m_cqCommandQue, m_dSimParams, CL_TRUE, 0, memSize, &m_simParams, 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + memSize = m_hashSize * sizeof(btInt2); + ciErrNum = clEnqueueWriteBuffer(m_cqCommandQue, m_dPosHash, CL_TRUE, 0, memSize, &(m_hPosHash[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); +} + + +void btParticlesDynamicsWorld::createVBO() +{ + // create buffer object + glGenBuffers(1, &m_vbo); + glBindBuffer(GL_ARRAY_BUFFER, m_vbo); + // positions of spheres + unsigned int memSize = sizeof(btVector3) * m_numParticles; + glBufferData(GL_ARRAY_BUFFER, memSize, 0, GL_DYNAMIC_DRAW); + // colors + GLuint vbo; + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, memSize, 0, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + m_colVbo = vbo; + // fill color buffer + glBindBufferARB(GL_ARRAY_BUFFER, m_colVbo); + float *data = (float*)glMapBufferARB(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + float *ptr = data; + for(int i = 0; i < m_numParticles; i++) + { + float t = i / (float)m_numParticles; + ptr[0] = 0.f; + ptr[1] = 1.f; + ptr[2] = 0.f; + ptr+=3; + *ptr++ = 1.0f; + } + glUnmapBufferARB(GL_ARRAY_BUFFER); + glBindBufferARB(GL_ARRAY_BUFFER, 0); +} + + + +void btParticlesDynamicsWorld::initCLKernels(int argc, char** argv) +{ + cl_int ciErrNum; + + if (!m_cxMainContext) + { + + cl_device_type deviceType = CL_DEVICE_TYPE_ALL; + m_cxMainContext = btOpenCLUtils::createContextFromType(deviceType, &ciErrNum, 0, 0); + + int numDev = btOpenCLUtils::getNumDevices(m_cxMainContext); + if (!numDev) + { + btAssert(0); + exit(0);//this is just a demo, exit now + } + + m_cdDevice = btOpenCLUtils::getDevice(m_cxMainContext,0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + btOpenCLDeviceInfo clInfo; + btOpenCLUtils::getDeviceInfo(m_cdDevice,clInfo); + btOpenCLUtils::printDeviceInfo(m_cdDevice); + + // create a command-queue + m_cqCommandQue = clCreateCommandQueue(m_cxMainContext, m_cdDevice, 0, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + // Program Setup + size_t program_length; + + +#ifdef LOAD_FROM_MEMORY + program_length = strlen(source); + printf("OpenCL compiles ParticlesOCL.cl ... "); +#else + + const char* fileName = "ParticlesOCL.cl"; + FILE * fp = fopen(fileName, "rb"); + char newFileName[512]; + + if (fp == NULL) + { + sprintf(newFileName,"..//%s",fileName); + fp = fopen(newFileName, "rb"); + if (fp) + fileName = newFileName; + } + + if (fp == NULL) + { + sprintf(newFileName,"Demos//ParticlesOpenCL//%s",fileName); + fp = fopen(newFileName, "rb"); + if (fp) + fileName = newFileName; + } + + if (fp == NULL) + { + sprintf(newFileName,"..//..//..//..//..//Demos//ParticlesOpenCL//%s",fileName); + fp = fopen(newFileName, "rb"); + if (fp) + fileName = newFileName; + else + { + printf("cannot find %s\n",newFileName); + exit(0); + } + } + +// char *source = oclLoadProgSource(".//Demos//SpheresGrid//SpheresGrid.cl", "", &program_length); + //char *source = btOclLoadProgSource(".//Demos//SpheresOpenCL//Shared//SpheresGrid.cl", "", &program_length); + + char *source = btOclLoadProgSource(fileName, "", &program_length); + if(source == NULL) + { + printf("ERROR : OpenCL can't load file %s\n", fileName); + } +// oclCHECKERROR (source == NULL, oclFALSE); + btAssert(source != NULL); + + // create the program + printf("OpenCL compiles %s ...", fileName); + +#endif //LOAD_FROM_MEMORY + + + //printf("%s\n", source); + + m_cpProgram = clCreateProgramWithSource(m_cxMainContext, 1, (const char**)&source, &program_length, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); +#ifndef LOAD_FROM_MEMORY + free(source); +#endif //LOAD_FROM_MEMORY + + //#define LOCAL_SIZE_LIMIT 1024U +#define LOCAL_SIZE_MAX 1024U + + // Build the program with 'mad' Optimization option +#ifdef MAC + const char* flags = "-I. -DLOCAL_SIZE_MAX=1024U -cl-mad-enable -DMAC -DGUID_ARG"; +#else + const char* flags = "-I. -DLOCAL_SIZE_MAX=1024U -DGUID_ARG= "; +#endif + // build the program + ciErrNum = clBuildProgram(m_cpProgram, 0, NULL, flags, NULL, NULL); + if(ciErrNum != CL_SUCCESS) + { + // write out standard error +// oclLog(LOGBOTH | ERRORMSG, (double)ciErrNum, STDERROR); + // write out the build log and ptx, then exit + char cBuildLog[10240]; +// char* cPtx; +// size_t szPtxLength; + clGetProgramBuildInfo(m_cpProgram, m_cdDevice, CL_PROGRAM_BUILD_LOG, + sizeof(cBuildLog), cBuildLog, NULL ); +// oclGetProgBinary(m_cpProgram, oclGetFirstDev(m_cxMainContext), &cPtx, &szPtxLength); +// oclLog(LOGBOTH | CLOSELOG, 0.0, "\n\nLog:\n%s\n\n\n\n\nPtx:\n%s\n\n\n", cBuildLog, cPtx); + printf("\n\n%s\n\n\n", cBuildLog); + printf("Press ENTER key to terminate the program\n"); + getchar(); + exit(-1); + } + printf("OK\n"); + + // create the kernels + + postInitDeviceData(); + + initKernel(PARTICLES_KERNEL_COMPUTE_CELL_ID, "kComputeCellId"); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_COMPUTE_CELL_ID].m_kernel, 1, sizeof(cl_mem), (void*) &m_dPos); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_COMPUTE_CELL_ID].m_kernel, 2, sizeof(cl_mem), (void*) &m_dPosHash); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_COMPUTE_CELL_ID].m_kernel, 3, sizeof(cl_mem), (void*) &m_dSimParams); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + initKernel(PARTICLES_KERNEL_INTEGRATE_MOTION, "kIntegrateMotion"); + ciErrNum = clSetKernelArg(m_kernels[PARTICLES_KERNEL_INTEGRATE_MOTION].m_kernel, 1, sizeof(cl_mem), (void *) &m_dPos); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_INTEGRATE_MOTION].m_kernel, 2, sizeof(cl_mem), (void *) &m_dVel); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_INTEGRATE_MOTION].m_kernel, 3, sizeof(cl_mem), (void *) &m_dSimParams); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + + initKernel(PARTICLES_KERNEL_CLEAR_CELL_START, "kClearCellStart"); + ciErrNum = clSetKernelArg(m_kernels[PARTICLES_KERNEL_CLEAR_CELL_START].m_kernel, 0, sizeof(int), (void *) &m_numGridCells); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_CLEAR_CELL_START].m_kernel, 1, sizeof(cl_mem), (void*) &m_dCellStart); + + initKernel(PARTICLES_KERNEL_FIND_CELL_START, "kFindCellStart"); +// ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_FIND_CELL_START].m_kernel, 0, sizeof(int), (void*) &m_numParticles); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_FIND_CELL_START].m_kernel, 1, sizeof(cl_mem), (void*) &m_dPosHash); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_FIND_CELL_START].m_kernel, 2, sizeof(cl_mem), (void*) &m_dCellStart); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_FIND_CELL_START].m_kernel, 3, sizeof(cl_mem), (void*) &m_dPos); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_FIND_CELL_START].m_kernel, 4, sizeof(cl_mem), (void*) &m_dVel); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_FIND_CELL_START].m_kernel, 5, sizeof(cl_mem), (void*) &m_dSortedPos); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_FIND_CELL_START].m_kernel, 6, sizeof(cl_mem), (void*) &m_dSortedVel); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + initKernel(PARTICLES_KERNEL_COLLIDE_PARTICLES, "kCollideParticles"); + ciErrNum = clSetKernelArg(m_kernels[PARTICLES_KERNEL_COLLIDE_PARTICLES].m_kernel, 1, sizeof(cl_mem), (void*) &m_dVel); + ciErrNum = clSetKernelArg(m_kernels[PARTICLES_KERNEL_COLLIDE_PARTICLES].m_kernel, 2, sizeof(cl_mem), (void*) &m_dSortedPos); + ciErrNum = clSetKernelArg(m_kernels[PARTICLES_KERNEL_COLLIDE_PARTICLES].m_kernel, 3, sizeof(cl_mem), (void*) &m_dSortedVel); + ciErrNum = clSetKernelArg(m_kernels[PARTICLES_KERNEL_COLLIDE_PARTICLES].m_kernel, 4, sizeof(cl_mem), (void*) &m_dPosHash); + ciErrNum = clSetKernelArg(m_kernels[PARTICLES_KERNEL_COLLIDE_PARTICLES].m_kernel, 5, sizeof(cl_mem), (void*) &m_dCellStart); + ciErrNum = clSetKernelArg(m_kernels[PARTICLES_KERNEL_COLLIDE_PARTICLES].m_kernel, 6, sizeof(cl_mem), (void*) &m_dSimParams); + + initKernel(PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_LOCAL, "kBitonicSortCellIdLocal"); + initKernel(PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_LOCAL_1, "kBitonicSortCellIdLocal1"); + initKernel(PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_MERGE_GLOBAL, "kBitonicSortCellIdMergeGlobal"); + initKernel(PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_MERGE_LOCAL, "kBitonicSortCellIdMergeLocal"); +} + +static btInt4 cpu_getGridPos(btVector3& worldPos, btSimParams* pParams) +{ + btInt4 gridPos; + gridPos.x = (int)floor((worldPos[0] - pParams->m_worldMin[0]) / pParams->m_cellSize[0]); + gridPos.y = (int)floor((worldPos[1] - pParams->m_worldMin[1]) / pParams->m_cellSize[1]); + gridPos.z = (int)floor((worldPos[2] - pParams->m_worldMin[2]) / pParams->m_cellSize[2]); + return gridPos; +} + +static unsigned int cpu_getPosHash(btInt4& gridPos, btSimParams* pParams) +{ + btInt4 gridDim = *((btInt4*)(pParams->m_gridSize)); + if(gridPos.x < 0) gridPos.x = 0; + if(gridPos.x >= gridDim.x) gridPos.x = gridDim.x - 1; + if(gridPos.y < 0) gridPos.y = 0; + if(gridPos.y >= gridDim.y) gridPos.y = gridDim.y - 1; + if(gridPos.z < 0) gridPos.z = 0; + if(gridPos.z >= gridDim.z) gridPos.z = gridDim.z - 1; + unsigned int hash = gridPos.z * gridDim.y * gridDim.x + gridPos.y * gridDim.x + gridPos.x; + return hash; +} + + + + +void btParticlesDynamicsWorld::runComputeCellIdKernel() +{ + cl_int ciErrNum; +#if 0 + if(m_useCpuControls[SIMSTAGE_COMPUTE_CELL_ID]->m_active) + { // CPU version + unsigned int memSize = sizeof(btVector3) * m_numParticles; + ciErrNum = clEnqueueReadBuffer(m_cqCommandQue, m_dPos, CL_TRUE, 0, memSize, &(m_hPos[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + for(int index = 0; index < m_numParticles; index++) + { + btVector3 pos = m_hPos[index]; + btInt4 gridPos = cpu_getGridPos(pos, &m_simParams); + unsigned int hash = cpu_getPosHash(gridPos, &m_simParams); + m_hPosHash[index].x = hash; + m_hPosHash[index].y = index; + } + memSize = sizeof(btInt2) * m_numParticles; + ciErrNum = clEnqueueWriteBuffer(m_cqCommandQue, m_dPosHash, CL_TRUE, 0, memSize, &(m_hPosHash[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + else +#endif + { + BT_PROFILE("ComputeCellId"); + runKernelWithWorkgroupSize(PARTICLES_KERNEL_COMPUTE_CELL_ID, m_numParticles); + ciErrNum = clFinish(m_cqCommandQue); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } +/* + // check + int memSize = sizeof(btInt2) * m_hashSize; + ciErrNum = clEnqueueReadBuffer(m_cqCommandQue, m_dPosHash, CL_TRUE, 0, memSize, &(m_hPosHash[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + memSize = sizeof(float) * 4 * m_numParticles; + ciErrNum = clEnqueueReadBuffer(m_cqCommandQue, m_dPos, CL_TRUE, 0, memSize, &(m_hPos[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); +*/ + + { + BT_PROFILE("Copy VBO"); + // Explicit Copy (until OpenGL interop will work) + // map the PBO to copy data from the CL buffer via host + glBindBufferARB(GL_ARRAY_BUFFER, m_vbo); + // map the buffer object into client's memory + void* ptr = glMapBufferARB(GL_ARRAY_BUFFER, GL_WRITE_ONLY_ARB); + ciErrNum = clEnqueueReadBuffer(m_cqCommandQue, m_dPos, CL_TRUE, 0, sizeof(float) * 4 * m_numParticles, ptr, 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + glUnmapBufferARB(GL_ARRAY_BUFFER); + glBindBufferARB(GL_ARRAY_BUFFER,0); + } +} + + + +static btVector3 cpu_collideTwoParticles( + btVector3& posA, + btVector3& posB, + btVector3& velA, + btVector3& velB, + float radiusA, + float radiusB, + float spring, + float damping, + float shear, + float attraction +) +{ + //Calculate relative position + btVector3 relPos = posB - posA; relPos[3] = 0.f; + float dist = sqrt(relPos[0] * relPos[0] + relPos[1] * relPos[1] + relPos[2] * relPos[2]); + float collideDist = radiusA + radiusB; + + btVector3 force = btVector3(0, 0, 0); + if(dist < collideDist) + { + btVector3 norm = relPos / dist; + + //Relative velocity + btVector3 relVel = velB - velA; relVel[3] = 0.f;; + + //Relative tangential velocity + float relVelDotNorm = relVel.dot(norm); + btVector3 tanVel = relVel - relVelDotNorm * norm; + //Spring force (potential) + //float springFactor = -spring * (collideDist - dist); + float springFactor = -0.4 * (collideDist - dist); + force = springFactor * norm + damping * relVel;// + shear * tanVel + attraction * relPos; + } + return force; +} + +struct btPair +{ + union + { + int value; + short v0[2]; + }; +}; + +void btParticlesDynamicsWorld::runCollideParticlesKernel() +{ + btAlignedObjectArray pairs; + + float particleRad = m_simParams.m_particleRad; + float collideDist2 = (particleRad + particleRad)*(particleRad + particleRad); + cl_int ciErrNum; + if(m_useCpuControls[SIMSTAGE_COLLIDE_PARTICLES]->m_active) + { // CPU version + int memSize = sizeof(btVector3) * m_numParticles; + { + BT_PROFILE("Copy from GPU"); + ciErrNum = clEnqueueReadBuffer(m_cqCommandQue, m_dSortedPos, CL_TRUE, 0, memSize, &(m_hSortedPos[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + ciErrNum = clEnqueueReadBuffer(m_cqCommandQue, m_dSortedVel, CL_TRUE, 0, memSize, &(m_hSortedVel[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + memSize = sizeof(btInt2) * m_numParticles; + ciErrNum = clEnqueueReadBuffer(m_cqCommandQue, m_dPosHash, CL_TRUE, 0, memSize, &(m_hPosHash[0]), 0, NULL, NULL); + memSize = m_numGridCells * sizeof(int); + ciErrNum = clEnqueueReadBuffer(m_cqCommandQue, m_dCellStart, CL_TRUE, 0, memSize, &(m_hCellStart[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + + for(int index = 0; index < m_numParticles; index++) + { + btVector3 posA = m_hSortedPos[index]; + btVector3 velA = m_hSortedVel[index]; + btVector3 force = btVector3(0, 0, 0); + float particleRad = m_simParams.m_particleRad; + float collisionDamping = m_simParams.m_collisionDamping; + float spring = m_simParams.m_spring; + float shear = m_simParams.m_shear; + float attraction = m_simParams.m_attraction; + int unsortedIndex = m_hPosHash[index].y; + //Get address in grid + btInt4 gridPosA = cpu_getGridPos(posA, &m_simParams); + //Accumulate surrounding cells + btInt4 gridPosB; + for(int z = -1; z <= 1; z++) + { + gridPosB.z = gridPosA.z + z; + for(int y = -1; y <= 1; y++) + { + gridPosB.y = gridPosA.y + y; + for(int x = -1; x <= 1; x++) + { + gridPosB.x = gridPosA.x + x; + //Get start particle index for this cell + unsigned int hashB = cpu_getPosHash(gridPosB, &m_simParams); + int startI = m_hCellStart[hashB]; + //Skip empty cell + if(startI < 0) + { + continue; + } + //Iterate over particles in this cell + int endI = startI + 32; + if(endI > m_numParticles) + endI = m_numParticles; + + for(int j = startI; j < endI; j++) + { + unsigned int hashC = m_hPosHash[j].x; + if(hashC != hashB) + { + break; + } + if(j == index) + { + continue; + } + + btPair pair; + pair.v0[0] = index; + pair.v0[1] = j; + pairs.push_back(pair.value); + +// printf("index=%d, j=%d\n",index,j); +// printf("(index=%d, j=%d) ",index,j); + btVector3 posB = m_hSortedPos[j]; + btVector3 velB = m_hSortedVel[j]; + //Collide two spheres + force += cpu_collideTwoParticles( posA, posB, velA, velB, particleRad, particleRad, + spring, collisionDamping, shear, attraction); + } + } + } + } + //Write new velocity back to original unsorted location + m_hVel[unsortedIndex] = velA + force; + } + +//#define BRUTE_FORCE_CHECK 1 +#ifdef BRUTE_FORCE_CHECK + for(int index = 0; index < m_numParticles; index++) + { + btVector3 posA = m_hSortedPos[index]; + btVector3 velA = m_hSortedVel[index]; + btVector3 force = btVector3(0, 0, 0); + int unsortedIndex = m_hPosHash[index].y; + + float collisionDamping = m_simParams.m_collisionDamping; + float spring = m_simParams.m_spring; + float shear = m_simParams.m_shear; + float attraction = m_simParams.m_attraction; + for(int j = 0 ; j < m_numParticles; j++) + { + if (index!=j) + { + btVector3 posB = m_hSortedPos[j]; + btVector3 velB = m_hSortedVel[j]; + + + btVector3 relPos = posB - posA; relPos[3] = 0.f; + float dist2 = (relPos[0] * relPos[0] + relPos[1] * relPos[1] + relPos[2] * relPos[2]); + + + + if(dist2 < collideDist2) + { + //Collide two spheres + // force += cpu_collideTwoParticles( posA, posB, velA, velB, particleRad, particleRad, + // spring, collisionDamping, shear, attraction); + + btPair pair; + pair.v0[0] = index; + pair.v0[1] = j; + if (pairs.findLinearSearch(pair.value)==pairs.size()) + { + printf("not found index=%d, j=%d\n",index,j); + } + + + } + } + } + //Write new velocity back to original unsorted location + //m_hVel[unsortedIndex] = velA + force; + } +#endif //BRUTE_FORCE_CHECK + + memSize = sizeof(btVector3) * m_numParticles; + ciErrNum = clEnqueueWriteBuffer(m_cqCommandQue, m_dVel, CL_TRUE, 0, memSize, &(m_hVel[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + else + { + runKernelWithWorkgroupSize(PARTICLES_KERNEL_COLLIDE_PARTICLES, m_numParticles); + cl_int ciErrNum = clFinish(m_cqCommandQue); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } +} + + +void btParticlesDynamicsWorld::runIntegrateMotionKernel() +{ + cl_int ciErrNum; + if(m_useCpuControls[SIMSTAGE_INTEGRATE_MOTION]->m_active) + { + // CPU version +#if 1 + // read from GPU + unsigned int memSize = sizeof(btVector3) * m_numParticles; + ciErrNum = clEnqueueReadBuffer(m_cqCommandQue, m_dPos, CL_TRUE, 0, memSize, &(m_hPos[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + ciErrNum = clEnqueueReadBuffer(m_cqCommandQue, m_dVel, CL_TRUE, 0, memSize, &(m_hVel[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + for(int index = 0; index < m_numParticles; index++) + { + btVector3 pos = m_hPos[index]; + btVector3 vel = m_hVel[index]; + pos[3] = 1.0f; + vel[3] = 0.0f; + // apply gravity + btVector3 gravity; + gravity[0] = m_simParams.m_gravity[0]; + gravity[1] = m_simParams.m_gravity[1]; + gravity[2] = m_simParams.m_gravity[2]; + + float particleRad = m_simParams.m_particleRad; + float globalDamping = m_simParams.m_globalDamping; + float boundaryDamping = m_simParams.m_boundaryDamping; + vel += gravity * m_timeStep; + vel *= globalDamping; + // integrate position + pos += vel * m_timeStep; + // collide with world boundaries + btVector3 worldMin; + worldMin[0] = m_simParams.m_worldMin[0]; + worldMin[1] = m_simParams.m_worldMin[1]; + worldMin[2] = m_simParams.m_worldMin[2]; + + btVector3 worldMax; + worldMax[0] = m_simParams.m_worldMax[0]; + worldMax[1] = m_simParams.m_worldMax[1]; + worldMax[2] = m_simParams.m_worldMax[2]; + + for(int j = 0; j < 3; j++) + { + if(pos[j] < (worldMin[j] + particleRad)) + { + pos[j] = worldMin[j] + particleRad; + vel[j] *= boundaryDamping; + } + if(pos[j] > (worldMax[j] - particleRad)) + { + pos[j] = worldMax[j] - particleRad; + vel[j] *= boundaryDamping; + } + } + // write back position and velocity + m_hPos[index] = pos; + m_hVel[index] = vel; + } +#endif + // write back to GPU + memSize = sizeof(btVector3) * m_numParticles; + ciErrNum = clEnqueueWriteBuffer(m_cqCommandQue, m_dPos, CL_TRUE, 0, memSize, &(m_hPos[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + ciErrNum = clEnqueueWriteBuffer(m_cqCommandQue, m_dVel, CL_TRUE, 0, memSize, &(m_hVel[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + else + { + // Set work size and execute the kernel + ciErrNum = clSetKernelArg(m_kernels[PARTICLES_KERNEL_INTEGRATE_MOTION].m_kernel, 4, sizeof(float), &m_timeStep); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + runKernelWithWorkgroupSize(PARTICLES_KERNEL_INTEGRATE_MOTION, m_numParticles); + ciErrNum = clFinish(m_cqCommandQue); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } +} + +void btParticlesDynamicsWorld::runSortHashKernel() +{ + cl_int ciErrNum; + int memSize = m_numParticles * sizeof(btInt2); + if(m_useCpuControls[SIMSTAGE_SORT_CELL_ID]->m_active) + { + // CPU version + // get hash from GPU + ciErrNum = clEnqueueReadBuffer(m_cqCommandQue, m_dPosHash, CL_TRUE, 0, memSize, &(m_hPosHash[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + // sort + class btHashPosKey + { + public: + unsigned int hash; + unsigned int index; + void quickSort(btHashPosKey* pData, int lo, int hi) + { + int i=lo, j=hi; + btHashPosKey x = pData[(lo+hi)/2]; + do + { + while(pData[i].hash < x.hash) i++; + while(x.hash < pData[j].hash) j--; + if(i <= j) + { + btHashPosKey t = pData[i]; + pData[i] = pData[j]; + pData[j] = t; + i++; j--; + } + } while(i <= j); + if(lo < j) pData->quickSort(pData, lo, j); + if(i < hi) pData->quickSort(pData, i, hi); + } + void bitonicSort(btHashPosKey* pData, int lo, int n, bool dir) + { + if(n > 1) + { + int m = n / 2; + bitonicSort(pData, lo, m, !dir); + bitonicSort(pData, lo + m, n - m, dir); + bitonicMerge(pData, lo, n, dir); + } + } + void bitonicMerge(btHashPosKey* pData, int lo, int n, bool dir) + { + if(n > 1) + { + int m = greatestPowerOfTwoLessThan(n); + for(int i = lo; i < (lo + n - m); i++) + { + compare(pData, i, i + m, dir); + } + bitonicMerge(pData, lo, m, dir); + bitonicMerge(pData, lo + m, n - m, dir); + } + } + void compare(btHashPosKey* pData, int i, int j, bool dir) + { + if(dir == (pData[i].hash > pData[j].hash)) + { + btHashPosKey t = pData[i]; + pData[i] = pData[j]; + pData[j] = t; + } + } + int greatestPowerOfTwoLessThan(int n) + { + int k = 1; + while(k < n) + { + k = k << 1; + } + return k>>1; + } + }; + btHashPosKey* pHash = (btHashPosKey*)(&m_hPosHash[0]); + pHash->quickSort(pHash, 0, m_numParticles-1 ); + // pHash->bitonicSort(pHash, 0, m_hashSize, true); + // write back to GPU + ciErrNum = clEnqueueWriteBuffer(m_cqCommandQue, m_dPosHash, CL_TRUE, 0, memSize, &(m_hPosHash[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + else + { + // bitonic sort on GPU (shared memory) + int dir = 1; + bitonicSortNv(m_dPosHash, 1, m_hashSize, dir); + ciErrNum = clFinish(m_cqCommandQue); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } +#if 0 + // check order + memSize = m_numParticles * sizeof(btInt2); + ciErrNum = clEnqueueReadBuffer(m_cqCommandQue, m_dPosHash, CL_TRUE, 0, memSize, &(m_hPosHash[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + for(int i = 1; i < m_hashSize; i++) + { + if(m_hPosHash[i-1].x > m_hPosHash[i].x) + { + printf("Hash sort error at %d\n", i); + } + } +#endif +} + + +void btParticlesDynamicsWorld::runFindCellStartKernel() +{ + cl_int ciErrNum; + if(m_useCpuControls[SIMSTAGE_FIND_CELL_START]->m_active) + { + // CPU version + // get hash from GPU + int memSize = m_numParticles * sizeof(btInt2); + ciErrNum = clEnqueueReadBuffer(m_cqCommandQue, m_dPosHash, CL_TRUE, 0, memSize, &(m_hPosHash[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + memSize = sizeof(btVector3) * m_numParticles; + ciErrNum = clEnqueueReadBuffer(m_cqCommandQue, m_dPos, CL_TRUE, 0, memSize, &(m_hPos[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + ciErrNum = clEnqueueReadBuffer(m_cqCommandQue, m_dVel, CL_TRUE, 0, memSize, &(m_hVel[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + // clear cells + for(int i = 0; i < m_numGridCells; i++) + { + m_hCellStart[i] = -1; + } + // find start of each cell in sorted hash + btInt2 hash = m_hPosHash[0]; + m_hCellStart[hash.x] = 0; + int unsortedIndex = hash.y; + btVector3 pos = m_hPos[unsortedIndex]; + btVector3 vel = m_hVel[unsortedIndex]; + m_hSortedPos[0] = pos; + m_hSortedVel[0] = vel; + for(int i = 1; i < m_numParticles; i++) + { + if(m_hPosHash[i-1].x != m_hPosHash[i].x) + { + m_hCellStart[m_hPosHash[i].x] = i; + } + unsortedIndex = m_hPosHash[i].y; + pos = m_hPos[unsortedIndex]; + vel = m_hVel[unsortedIndex]; + m_hSortedPos[i] = pos; + m_hSortedVel[i] = vel; + } + // write back to GPU + memSize = m_numGridCells * sizeof(int); + ciErrNum = clEnqueueWriteBuffer(m_cqCommandQue, m_dCellStart, CL_TRUE, 0, memSize, &(m_hCellStart[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + memSize = sizeof(btVector3) * m_numParticles; + ciErrNum = clEnqueueWriteBuffer(m_cqCommandQue, m_dSortedPos, CL_TRUE, 0, memSize, &(m_hSortedPos[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + ciErrNum = clEnqueueWriteBuffer(m_cqCommandQue, m_dSortedVel, CL_TRUE, 0, memSize, &(m_hSortedVel[0]), 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + else + { // GPU + runKernelWithWorkgroupSize(PARTICLES_KERNEL_CLEAR_CELL_START, m_numGridCells); + runKernelWithWorkgroupSize(PARTICLES_KERNEL_FIND_CELL_START, m_numParticles); + ciErrNum = clFinish(m_cqCommandQue); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } +} + + +void btParticlesDynamicsWorld::initKernel(int kernelId, const char* pName) +{ + + cl_int ciErrNum; + cl_kernel kernel = clCreateKernel(m_cpProgram, pName, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + size_t wgSize; + ciErrNum = clGetKernelWorkGroupInfo(kernel, m_cdDevice, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &wgSize, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + + + +// if (wgSize > 256) +// wgSize = 256; + + if (wgSize > 512) + wgSize = 512; + +// if (wgSize > 1024) +// wgSize = 1024; + + m_kernels[kernelId].m_Id = kernelId; + m_kernels[kernelId].m_kernel = kernel; + m_kernels[kernelId].m_name = pName; + m_kernels[kernelId].m_workgroupSize = wgSize; + + return; +} + +void btParticlesDynamicsWorld::runKernelWithWorkgroupSize(int kernelId, int globalSize) +{ + if(globalSize <= 0) + { + return; + } + cl_kernel kernelFunc = m_kernels[kernelId].m_kernel; + cl_int ciErrNum = clSetKernelArg(kernelFunc, 0, sizeof(int), (void*)&globalSize); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + int workgroupSize = m_kernels[kernelId].m_workgroupSize; + if(workgroupSize <= 0) + { // let OpenCL library calculate workgroup size + size_t globalWorkSize[2]; + globalWorkSize[0] = globalSize; + globalWorkSize[1] = 1; + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, kernelFunc, 1, NULL, globalWorkSize, NULL, 0,0,0 ); + } + else + { + size_t localWorkSize[2], globalWorkSize[2]; + workgroupSize = btMin(workgroupSize, globalSize); + int num_t = globalSize / workgroupSize; + int num_g = num_t * workgroupSize; + if(num_g < globalSize) + { + num_t++; + } + localWorkSize[0] = workgroupSize; + globalWorkSize[0] = num_t * workgroupSize; + localWorkSize[1] = 1; + globalWorkSize[1] = 1; + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, kernelFunc, 1, NULL, globalWorkSize, localWorkSize, 0,0,0 ); + } + oclCHECKERROR(ciErrNum, CL_SUCCESS); +} + + +//Note: logically shared with BitonicSort OpenCL code! +// TODO : get parameter from OpenCL and pass it to kernel (needed for platforms other than NVIDIA) +//static const unsigned int LOCAL_SIZE_LIMIT = 1024U; + +void btParticlesDynamicsWorld::bitonicSortNv(cl_mem pKey, unsigned int batch, unsigned int arrayLength, unsigned int dir) +{ + unsigned int localSizeLimit = m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_LOCAL].m_workgroupSize * 2; + if(arrayLength < 2) + return; + //Only power-of-two array lengths are supported so far + dir = (dir != 0); + cl_int ciErrNum; + size_t localWorkSize, globalWorkSize; + if(arrayLength <= localSizeLimit) + { + btAssert( (batch * arrayLength) % localSizeLimit == 0); + //Launch bitonicSortLocal + ciErrNum = clSetKernelArg(m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_LOCAL].m_kernel, 0, sizeof(cl_mem), (void *)&pKey); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_LOCAL].m_kernel, 1, sizeof(cl_uint), (void *)&arrayLength); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_LOCAL].m_kernel, 2, sizeof(cl_uint), (void *)&dir); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + localWorkSize = localSizeLimit / 2; + globalWorkSize = batch * arrayLength / 2; + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_LOCAL].m_kernel, 1, NULL, &globalWorkSize, &localWorkSize, 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + else + { + //Launch bitonicSortLocal1 + ciErrNum = clSetKernelArg(m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_LOCAL_1].m_kernel, 0, sizeof(cl_mem), (void *)&pKey); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + localWorkSize = localSizeLimit / 2; + globalWorkSize = batch * arrayLength / 2; + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_LOCAL_1].m_kernel, 1, NULL, &globalWorkSize, &localWorkSize, 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + for(unsigned int size = 2 * localSizeLimit; size <= arrayLength; size <<= 1) + { + for(unsigned stride = size / 2; stride > 0; stride >>= 1) + { + if(stride >= localSizeLimit) + { + //Launch bitonicMergeGlobal + ciErrNum = clSetKernelArg(m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_MERGE_GLOBAL].m_kernel, 0, sizeof(cl_mem), (void *)&pKey); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_MERGE_GLOBAL].m_kernel, 1, sizeof(cl_uint), (void *)&arrayLength); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_MERGE_GLOBAL].m_kernel, 2, sizeof(cl_uint), (void *)&size); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_MERGE_GLOBAL].m_kernel, 3, sizeof(cl_uint), (void *)&stride); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_MERGE_GLOBAL].m_kernel, 4, sizeof(cl_uint), (void *)&dir); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + localWorkSize = localSizeLimit / 4; + globalWorkSize = batch * arrayLength / 2; + + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_MERGE_GLOBAL].m_kernel, 1, NULL, &globalWorkSize, &localWorkSize, 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + else + { + //Launch bitonicMergeLocal + ciErrNum = clSetKernelArg(m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_MERGE_LOCAL].m_kernel, 0, sizeof(cl_mem), (void *)&pKey); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_MERGE_LOCAL].m_kernel, 1, sizeof(cl_uint), (void *)&arrayLength); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_MERGE_LOCAL].m_kernel, 2, sizeof(cl_uint), (void *)&stride); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_MERGE_LOCAL].m_kernel, 3, sizeof(cl_uint), (void *)&size); + ciErrNum |= clSetKernelArg(m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_MERGE_LOCAL].m_kernel, 4, sizeof(cl_uint), (void *)&dir); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + localWorkSize = localSizeLimit / 2; + globalWorkSize = batch * arrayLength / 2; + + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, m_kernels[PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_MERGE_LOCAL].m_kernel, 1, NULL, &globalWorkSize, &localWorkSize, 0, NULL, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + break; + } + } + } + } +} + diff --git a/Demos/ParticlesOpenCL/btParticlesDynamicsWorld.h b/Demos/ParticlesOpenCL/btParticlesDynamicsWorld.h new file mode 100644 index 0000000..66e99af --- /dev/null +++ b/Demos/ParticlesOpenCL/btParticlesDynamicsWorld.h @@ -0,0 +1,183 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006 - 2009 Sony Computer Entertainment Inc. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_PARTICLES_DYNAMICS_WORLD_H +#define BT_PARTICLES_DYNAMICS_WORLD_H + + +#ifdef USE_MINICL +#include +#include +#else +#ifdef __APPLE__ + #include +#else + #include + #include +#endif __APPLE__ +#endif + + + + + + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h" + +#include "btParticlesSharedDefs.h" +#include "btParticlesSharedTypes.h" + + +#define PARTICLES_MAX_NEIGHBORS (32) +#define DEF_PARTICLE_RADIUS (0.023f) +//#define WORLD_SIZE 1.9f +#define WORLD_SIZE 1.f + +enum +{ + PARTICLES_KERNEL_INTEGRATE_MOTION = 0, + PARTICLES_KERNEL_COMPUTE_CELL_ID, + PARTICLES_KERNEL_CLEAR_CELL_START, + PARTICLES_KERNEL_FIND_CELL_START, + PARTICLES_KERNEL_COLLIDE_PARTICLES, + PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_LOCAL, + PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_LOCAL_1, + PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_MERGE_GLOBAL, + PARTICLES_KERNEL_BITONIC_SORT_CELL_ID_MERGE_LOCAL, + PARTICLES_KERNEL_TOTAL +}; + + +enum +{ + SIMSTAGE_NONE = 0, + SIMSTAGE_INTEGRATE_MOTION, + SIMSTAGE_COMPUTE_CELL_ID, + SIMSTAGE_SORT_CELL_ID, + SIMSTAGE_FIND_CELL_START, + SIMSTAGE_COLLIDE_PARTICLES, + SIMSTAGE_TOTAL +}; + +struct btKernelInfo +{ + int m_Id; + cl_kernel m_kernel; + const char* m_name; + int m_workgroupSize; +}; + +class btParticlesDynamicsWorld : public btDiscreteDynamicsWorld +{ +public: + int m_numParticles; + int m_usedDevice; + btScalar m_particleRad; + struct GL_ToggleControl* m_useCpuControls[SIMSTAGE_TOTAL]; + +protected: + int m_hashSize; // power of 2 >= m_numSpheres; + int m_numGridCells; + int m_maxNeighbors; + int m_numSolverIterations; + // CPU side data +public: + btAlignedObjectArray m_hPos; + btAlignedObjectArray m_hVel; + btAlignedObjectArray m_hSortedPos; + btAlignedObjectArray m_hSortedVel; +protected: + btAlignedObjectArray m_hPosHash; + btAlignedObjectArray m_hCellStart; + // GPU side data + cl_mem m_dPos; + cl_mem m_dVel; + cl_mem m_dPosHash; + cl_mem m_dCellStart; + cl_mem m_dSimParams; // copy of m_simParams : global simulation paramerers such as gravity, etc. + cl_mem m_dSortedPos; + cl_mem m_dSortedVel; + // OpenCL +public: + cl_context m_cxMainContext; + cl_device_id m_cdDevice; + cl_command_queue m_cqCommandQue; + cl_program m_cpProgram; +protected: + btKernelInfo m_kernels[PARTICLES_KERNEL_TOTAL]; + + btVector3 m_cellSize; + +public: + btVector3 m_worldMin; + btVector3 m_worldMax; + // vbo variables + GLuint m_vbo; + unsigned int m_posVbo; + unsigned int m_colVbo; + btSimParams m_simParams; + float m_timeStep; + + int getNumParticles() { return m_numParticles; } + float* getPosBuffer() { return (float*)&(m_hPos[0]); } + + + btParticlesDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration, + int maxObjs , int maxNeighbors = PARTICLES_MAX_NEIGHBORS) + : btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration) + { + m_cxMainContext = 0; + m_usedDevice = 1; +// m_particleRad = btScalar(0.5f); + m_particleRad = DEF_PARTICLE_RADIUS; + m_simParams.m_gravity[0] = 0.f; + m_simParams.m_gravity[1] = -10.f; + m_simParams.m_gravity[2] = 0.f; + m_simParams.m_gravity[3] = 0.f; + m_numSolverIterations = 4; + } + virtual ~btParticlesDynamicsWorld(); + virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); + + void initDeviceData(); + void initCLKernels(int argc, char** argv); + void createVBO(); + void postInitDeviceData(); + void getShapeData(); + void allocateBuffers(); + void grabSimulationData(); + void adjustGrid(); + void runIntegrateMotionKernel(); + void runComputeCellIdKernel(); + void runSortHashKernel(); + void runFindCellStartKernel(); + void runCollideParticlesKernel(); + + void initKernel(int kernelId, const char* pName); + void runKernelWithWorkgroupSize(int kernelId, int globalSize); + void bitonicSortNv(cl_mem pKey, unsigned int batch, unsigned int arrayLength, unsigned int dir); + + void scanExclusiveLocal1(cl_mem d_Dst, cl_mem d_Src, unsigned int n, unsigned int size); + void scanExclusiveLocal2(cl_mem d_Buffer, cl_mem d_Dst, cl_mem d_Src, unsigned int n, unsigned int size); + void uniformUpdate(cl_mem d_Dst, cl_mem d_Buffer, unsigned int n); + void scanExclusive(cl_mem d_Dst, cl_mem d_Src, unsigned int arrayLength); + +}; + + +#endif //BT_PARTICLES_DYNAMICS_WORLD_H diff --git a/Demos/ParticlesOpenCL/btParticlesSharedDefs.h b/Demos/ParticlesOpenCL/btParticlesSharedDefs.h new file mode 100644 index 0000000..247075b --- /dev/null +++ b/Demos/ParticlesOpenCL/btParticlesSharedDefs.h @@ -0,0 +1,14 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006 - 2009 Sony Computer Entertainment Inc. + +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. +*/ diff --git a/Demos/ParticlesOpenCL/btParticlesSharedTypes.h b/Demos/ParticlesOpenCL/btParticlesSharedTypes.h new file mode 100644 index 0000000..8ee8690 --- /dev/null +++ b/Demos/ParticlesOpenCL/btParticlesSharedTypes.h @@ -0,0 +1,54 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006 - 2009 Sony Computer Entertainment Inc. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BT_SPHERES_GRID_DEMO_SHARED_TYPES +#define BT_SPHERES_GRID_DEMO_SHARED_TYPES + +struct btSimParams +{ + float m_gravity[4]; + float m_worldMin[4]; + float m_worldMax[4]; + float m_cellSize[4]; + int m_gridSize[4]; + + float m_particleRad; + float m_globalDamping; + float m_boundaryDamping; + float m_collisionDamping; + + float m_spring; + float m_shear; + float m_attraction; + float m_dummy; +}; + +struct btInt2 +{ + int x; + int y; +}; + +struct btInt4 +{ + int x; + int y; + int z; + int w; +}; + + + +#endif + diff --git a/Demos/ParticlesOpenCL/main.cpp b/Demos/ParticlesOpenCL/main.cpp new file mode 100644 index 0000000..037bba7 --- /dev/null +++ b/Demos/ParticlesOpenCL/main.cpp @@ -0,0 +1,51 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006 - 2009 Sony Computer Entertainment Inc. + +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 "ParticlesDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" + +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btHashMap.h" + + +// standard utility and system includes +//#include +// Extra CL/GL include +//#include + + +GLDebugDrawer gDebugDrawer; + +int main(int argc,char** argv) +{ + // start logs +// oclSetLogFileName ("appSpheresGrid.txt"); +// oclLog(LOGBOTH, 0.0, "appSpheresGrid.exe Starting...\n\n"); + + + ParticlesDemo ccdDemo(argc, argv); + ccdDemo.initPhysics(); + ccdDemo.getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + +#ifdef CHECK_MEMORY_LEAKS + ccdDemo.exitPhysics(); +#else + return glutmain(argc, argv,640,480,"Bullet Physics Demo. http://bulletphysics.com",&ccdDemo); +#endif + + //default glut doesn't return from mainloop + return 0; +} \ No newline at end of file diff --git a/Demos/ParticlesOpenCL/shaders.cpp b/Demos/ParticlesOpenCL/shaders.cpp new file mode 100644 index 0000000..79b01f5 --- /dev/null +++ b/Demos/ParticlesOpenCL/shaders.cpp @@ -0,0 +1,56 @@ +#define STRINGIFY(A) #A +//use most up-to-date AMD Radeon drivers to make point sprites work +//see also http://forums.amd.com/devforum/messageview.cfm?catid=392&threadid=129431 +// vertex shader +const char *vertexShader = STRINGIFY( +uniform float pointRadius; // point size in world space +uniform float pointScale; // scale to calculate size in pixels +uniform float densityScale; +uniform float densityOffset; +varying vec3 posEye; +void main() +{ + // calculate window-space point size + posEye = vec3(gl_ModelViewMatrix * vec4(gl_Vertex.xyz, 1.0)); + float dist = length(posEye); + gl_PointSize = pointRadius * (pointScale / dist); + + gl_TexCoord[0] = gl_MultiTexCoord0; + + gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz, 1.0); + + gl_FrontColor = gl_Color; +} +); + + + +// pixel shader for rendering points as shaded spheres +const char *spherePixelShader = STRINGIFY( +uniform float pointRadius; // point size in world space +varying vec3 posEye; // position of center in eye space +void main() +{ + const vec3 lightDir = vec3(0.577, 0.577, 0.577); + const float shininess = 40.0; + + // calculate normal from texture coordinates + vec3 N; + N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0); + float mag = dot(N.xy, N.xy); + if (mag > 1.0) discard; // kill pixels outside circle + N.z = sqrt(1.0-mag); + + // point on surface of sphere in eye space + vec3 spherePosEye = posEye + N*pointRadius; + + // calculate lighting + float diffuse = max(0.0, dot(lightDir, N)); +// gl_FragColor = gl_Color * diffuse; + + vec3 v = normalize(-spherePosEye); + vec3 h = normalize(lightDir + v); + float specular = pow(max(0.0, dot(N, h)), shininess); + gl_FragColor = gl_Color * diffuse + specular; +} +); diff --git a/Demos/ParticlesOpenCL/shaders.h b/Demos/ParticlesOpenCL/shaders.h new file mode 100644 index 0000000..d90b40c --- /dev/null +++ b/Demos/ParticlesOpenCL/shaders.h @@ -0,0 +1,2 @@ +extern const char *vertexShader; +extern const char *spherePixelShader; diff --git a/Demos/RagdollDemo/CMakeLists.txt b/Demos/RagdollDemo/CMakeLists.txt new file mode 100644 index 0000000..c6caa49 --- /dev/null +++ b/Demos/RagdollDemo/CMakeLists.txt @@ -0,0 +1,49 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# You shouldn't have to modify anything below this line +######################################################## + + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppRagdollDemo + RagdollDemo.cpp + main.cpp +) + +IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppRagdollDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppRagdollDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF(WIN32) + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppRagdollDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppRagdollDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppRagdollDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/RagdollDemo/RagdollDemo.cpp b/Demos/RagdollDemo/RagdollDemo.cpp new file mode 100644 index 0000000..0ec12df --- /dev/null +++ b/Demos/RagdollDemo/RagdollDemo.cpp @@ -0,0 +1,507 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Ragdoll Demo +Copyright (c) 2007 Starbreeze Studios + +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. + +Written by: Marten Svanfeldt +*/ + +#define CONSTRAINT_DEBUG_SIZE 0.2f + + +#include "btBulletDynamicsCommon.h" +#include "GlutStuff.h" +#include "GL_ShapeDrawer.h" + +#include "LinearMath/btIDebugDraw.h" + +#include "GLDebugDrawer.h" +#include "RagdollDemo.h" + + +// Enrico: Shouldn't these three variables be real constants and not defines? + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923 +#endif + +#ifndef M_PI_4 +#define M_PI_4 0.785398163397448309616 +#endif + +class RagDoll +{ + enum + { + BODYPART_PELVIS = 0, + BODYPART_SPINE, + BODYPART_HEAD, + + BODYPART_LEFT_UPPER_LEG, + BODYPART_LEFT_LOWER_LEG, + + BODYPART_RIGHT_UPPER_LEG, + BODYPART_RIGHT_LOWER_LEG, + + BODYPART_LEFT_UPPER_ARM, + BODYPART_LEFT_LOWER_ARM, + + BODYPART_RIGHT_UPPER_ARM, + BODYPART_RIGHT_LOWER_ARM, + + BODYPART_COUNT + }; + + enum + { + JOINT_PELVIS_SPINE = 0, + JOINT_SPINE_HEAD, + + JOINT_LEFT_HIP, + JOINT_LEFT_KNEE, + + JOINT_RIGHT_HIP, + JOINT_RIGHT_KNEE, + + JOINT_LEFT_SHOULDER, + JOINT_LEFT_ELBOW, + + JOINT_RIGHT_SHOULDER, + JOINT_RIGHT_ELBOW, + + JOINT_COUNT + }; + + btDynamicsWorld* m_ownerWorld; + btCollisionShape* m_shapes[BODYPART_COUNT]; + btRigidBody* m_bodies[BODYPART_COUNT]; + btTypedConstraint* m_joints[JOINT_COUNT]; + + btRigidBody* localCreateRigidBody (btScalar mass, const btTransform& startTransform, btCollisionShape* shape) + { + bool isDynamic = (mass != 0.f); + + btVector3 localInertia(0,0,0); + if (isDynamic) + shape->calculateLocalInertia(mass,localInertia); + + btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + m_ownerWorld->addRigidBody(body); + + return body; + } + +public: + RagDoll (btDynamicsWorld* ownerWorld, const btVector3& positionOffset) + : m_ownerWorld (ownerWorld) + { + // Setup the geometry + m_shapes[BODYPART_PELVIS] = new btCapsuleShape(btScalar(0.15), btScalar(0.20)); + m_shapes[BODYPART_SPINE] = new btCapsuleShape(btScalar(0.15), btScalar(0.28)); + m_shapes[BODYPART_HEAD] = new btCapsuleShape(btScalar(0.10), btScalar(0.05)); + m_shapes[BODYPART_LEFT_UPPER_LEG] = new btCapsuleShape(btScalar(0.07), btScalar(0.45)); + m_shapes[BODYPART_LEFT_LOWER_LEG] = new btCapsuleShape(btScalar(0.05), btScalar(0.37)); + m_shapes[BODYPART_RIGHT_UPPER_LEG] = new btCapsuleShape(btScalar(0.07), btScalar(0.45)); + m_shapes[BODYPART_RIGHT_LOWER_LEG] = new btCapsuleShape(btScalar(0.05), btScalar(0.37)); + m_shapes[BODYPART_LEFT_UPPER_ARM] = new btCapsuleShape(btScalar(0.05), btScalar(0.33)); + m_shapes[BODYPART_LEFT_LOWER_ARM] = new btCapsuleShape(btScalar(0.04), btScalar(0.25)); + m_shapes[BODYPART_RIGHT_UPPER_ARM] = new btCapsuleShape(btScalar(0.05), btScalar(0.33)); + m_shapes[BODYPART_RIGHT_LOWER_ARM] = new btCapsuleShape(btScalar(0.04), btScalar(0.25)); + + // Setup all the rigid bodies + btTransform offset; offset.setIdentity(); + offset.setOrigin(positionOffset); + + btTransform transform; + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(0.), btScalar(1.), btScalar(0.))); + m_bodies[BODYPART_PELVIS] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_PELVIS]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(0.), btScalar(1.2), btScalar(0.))); + m_bodies[BODYPART_SPINE] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_SPINE]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(0.), btScalar(1.6), btScalar(0.))); + m_bodies[BODYPART_HEAD] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_HEAD]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(-0.18), btScalar(0.65), btScalar(0.))); + m_bodies[BODYPART_LEFT_UPPER_LEG] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_LEFT_UPPER_LEG]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(-0.18), btScalar(0.2), btScalar(0.))); + m_bodies[BODYPART_LEFT_LOWER_LEG] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_LEFT_LOWER_LEG]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(0.18), btScalar(0.65), btScalar(0.))); + m_bodies[BODYPART_RIGHT_UPPER_LEG] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_RIGHT_UPPER_LEG]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(0.18), btScalar(0.2), btScalar(0.))); + m_bodies[BODYPART_RIGHT_LOWER_LEG] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_RIGHT_LOWER_LEG]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(-0.35), btScalar(1.45), btScalar(0.))); + transform.getBasis().setEulerZYX(0,0,M_PI_2); + m_bodies[BODYPART_LEFT_UPPER_ARM] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_LEFT_UPPER_ARM]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(-0.7), btScalar(1.45), btScalar(0.))); + transform.getBasis().setEulerZYX(0,0,M_PI_2); + m_bodies[BODYPART_LEFT_LOWER_ARM] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_LEFT_LOWER_ARM]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(0.35), btScalar(1.45), btScalar(0.))); + transform.getBasis().setEulerZYX(0,0,-M_PI_2); + m_bodies[BODYPART_RIGHT_UPPER_ARM] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_RIGHT_UPPER_ARM]); + + transform.setIdentity(); + transform.setOrigin(btVector3(btScalar(0.7), btScalar(1.45), btScalar(0.))); + transform.getBasis().setEulerZYX(0,0,-M_PI_2); + m_bodies[BODYPART_RIGHT_LOWER_ARM] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[BODYPART_RIGHT_LOWER_ARM]); + + // Setup some damping on the m_bodies + for (int i = 0; i < BODYPART_COUNT; ++i) + { + m_bodies[i]->setDamping(0.05, 0.85); + m_bodies[i]->setDeactivationTime(0.8); + m_bodies[i]->setSleepingThresholds(1.6, 2.5); + } + + // Now setup the constraints + btHingeConstraint* hingeC; + btConeTwistConstraint* coneC; + + btTransform localA, localB; + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,M_PI_2,0); localA.setOrigin(btVector3(btScalar(0.), btScalar(0.15), btScalar(0.))); + localB.getBasis().setEulerZYX(0,M_PI_2,0); localB.setOrigin(btVector3(btScalar(0.), btScalar(-0.15), btScalar(0.))); + hingeC = new btHingeConstraint(*m_bodies[BODYPART_PELVIS], *m_bodies[BODYPART_SPINE], localA, localB); + hingeC->setLimit(btScalar(-M_PI_4), btScalar(M_PI_2)); + m_joints[JOINT_PELVIS_SPINE] = hingeC; + hingeC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE); + + m_ownerWorld->addConstraint(m_joints[JOINT_PELVIS_SPINE], true); + + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,0,M_PI_2); localA.setOrigin(btVector3(btScalar(0.), btScalar(0.30), btScalar(0.))); + localB.getBasis().setEulerZYX(0,0,M_PI_2); localB.setOrigin(btVector3(btScalar(0.), btScalar(-0.14), btScalar(0.))); + coneC = new btConeTwistConstraint(*m_bodies[BODYPART_SPINE], *m_bodies[BODYPART_HEAD], localA, localB); + coneC->setLimit(M_PI_4, M_PI_4, M_PI_2); + m_joints[JOINT_SPINE_HEAD] = coneC; + coneC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE); + + m_ownerWorld->addConstraint(m_joints[JOINT_SPINE_HEAD], true); + + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,0,-M_PI_4*5); localA.setOrigin(btVector3(btScalar(-0.18), btScalar(-0.10), btScalar(0.))); + localB.getBasis().setEulerZYX(0,0,-M_PI_4*5); localB.setOrigin(btVector3(btScalar(0.), btScalar(0.225), btScalar(0.))); + coneC = new btConeTwistConstraint(*m_bodies[BODYPART_PELVIS], *m_bodies[BODYPART_LEFT_UPPER_LEG], localA, localB); + coneC->setLimit(M_PI_4, M_PI_4, 0); + m_joints[JOINT_LEFT_HIP] = coneC; + coneC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE); + + m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_HIP], true); + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,M_PI_2,0); localA.setOrigin(btVector3(btScalar(0.), btScalar(-0.225), btScalar(0.))); + localB.getBasis().setEulerZYX(0,M_PI_2,0); localB.setOrigin(btVector3(btScalar(0.), btScalar(0.185), btScalar(0.))); + hingeC = new btHingeConstraint(*m_bodies[BODYPART_LEFT_UPPER_LEG], *m_bodies[BODYPART_LEFT_LOWER_LEG], localA, localB); + hingeC->setLimit(btScalar(0), btScalar(M_PI_2)); + m_joints[JOINT_LEFT_KNEE] = hingeC; + hingeC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE); + + m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_KNEE], true); + + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,0,M_PI_4); localA.setOrigin(btVector3(btScalar(0.18), btScalar(-0.10), btScalar(0.))); + localB.getBasis().setEulerZYX(0,0,M_PI_4); localB.setOrigin(btVector3(btScalar(0.), btScalar(0.225), btScalar(0.))); + coneC = new btConeTwistConstraint(*m_bodies[BODYPART_PELVIS], *m_bodies[BODYPART_RIGHT_UPPER_LEG], localA, localB); + coneC->setLimit(M_PI_4, M_PI_4, 0); + m_joints[JOINT_RIGHT_HIP] = coneC; + coneC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE); + + m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_HIP], true); + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,M_PI_2,0); localA.setOrigin(btVector3(btScalar(0.), btScalar(-0.225), btScalar(0.))); + localB.getBasis().setEulerZYX(0,M_PI_2,0); localB.setOrigin(btVector3(btScalar(0.), btScalar(0.185), btScalar(0.))); + hingeC = new btHingeConstraint(*m_bodies[BODYPART_RIGHT_UPPER_LEG], *m_bodies[BODYPART_RIGHT_LOWER_LEG], localA, localB); + hingeC->setLimit(btScalar(0), btScalar(M_PI_2)); + m_joints[JOINT_RIGHT_KNEE] = hingeC; + hingeC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE); + + m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_KNEE], true); + + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,0,M_PI); localA.setOrigin(btVector3(btScalar(-0.2), btScalar(0.15), btScalar(0.))); + localB.getBasis().setEulerZYX(0,0,M_PI_2); localB.setOrigin(btVector3(btScalar(0.), btScalar(-0.18), btScalar(0.))); + coneC = new btConeTwistConstraint(*m_bodies[BODYPART_SPINE], *m_bodies[BODYPART_LEFT_UPPER_ARM], localA, localB); + coneC->setLimit(M_PI_2, M_PI_2, 0); + coneC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE); + + m_joints[JOINT_LEFT_SHOULDER] = coneC; + m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_SHOULDER], true); + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,M_PI_2,0); localA.setOrigin(btVector3(btScalar(0.), btScalar(0.18), btScalar(0.))); + localB.getBasis().setEulerZYX(0,M_PI_2,0); localB.setOrigin(btVector3(btScalar(0.), btScalar(-0.14), btScalar(0.))); + hingeC = new btHingeConstraint(*m_bodies[BODYPART_LEFT_UPPER_ARM], *m_bodies[BODYPART_LEFT_LOWER_ARM], localA, localB); +// hingeC->setLimit(btScalar(-M_PI_2), btScalar(0)); + hingeC->setLimit(btScalar(0), btScalar(M_PI_2)); + m_joints[JOINT_LEFT_ELBOW] = hingeC; + hingeC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE); + + m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_ELBOW], true); + + + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,0,0); localA.setOrigin(btVector3(btScalar(0.2), btScalar(0.15), btScalar(0.))); + localB.getBasis().setEulerZYX(0,0,M_PI_2); localB.setOrigin(btVector3(btScalar(0.), btScalar(-0.18), btScalar(0.))); + coneC = new btConeTwistConstraint(*m_bodies[BODYPART_SPINE], *m_bodies[BODYPART_RIGHT_UPPER_ARM], localA, localB); + coneC->setLimit(M_PI_2, M_PI_2, 0); + m_joints[JOINT_RIGHT_SHOULDER] = coneC; + coneC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE); + + m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_SHOULDER], true); + + localA.setIdentity(); localB.setIdentity(); + localA.getBasis().setEulerZYX(0,M_PI_2,0); localA.setOrigin(btVector3(btScalar(0.), btScalar(0.18), btScalar(0.))); + localB.getBasis().setEulerZYX(0,M_PI_2,0); localB.setOrigin(btVector3(btScalar(0.), btScalar(-0.14), btScalar(0.))); + hingeC = new btHingeConstraint(*m_bodies[BODYPART_RIGHT_UPPER_ARM], *m_bodies[BODYPART_RIGHT_LOWER_ARM], localA, localB); +// hingeC->setLimit(btScalar(-M_PI_2), btScalar(0)); + hingeC->setLimit(btScalar(0), btScalar(M_PI_2)); + m_joints[JOINT_RIGHT_ELBOW] = hingeC; + hingeC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE); + + m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_ELBOW], true); + } + + virtual ~RagDoll () + { + int i; + + // Remove all constraints + for ( i = 0; i < JOINT_COUNT; ++i) + { + m_ownerWorld->removeConstraint(m_joints[i]); + delete m_joints[i]; m_joints[i] = 0; + } + + // Remove all bodies and shapes + for ( i = 0; i < BODYPART_COUNT; ++i) + { + m_ownerWorld->removeRigidBody(m_bodies[i]); + + delete m_bodies[i]->getMotionState(); + + delete m_bodies[i]; m_bodies[i] = 0; + delete m_shapes[i]; m_shapes[i] = 0; + } + } +}; + + + + +void RagdollDemo::initPhysics() +{ + // Setup the basic world + + setTexturing(true); + setShadows(true); + + setCameraDistance(btScalar(5.)); + + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + + btVector3 worldAabbMin(-10000,-10000,-10000); + btVector3 worldAabbMax(10000,10000,10000); + m_broadphase = new btAxisSweep3 (worldAabbMin, worldAabbMax); + + m_solver = new btSequentialImpulseConstraintSolver; + + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + //m_dynamicsWorld->getDispatchInfo().m_useConvexConservativeDistanceUtil = true; + //m_dynamicsWorld->getDispatchInfo().m_convexConservativeDistanceThreshold = 0.01f; + + + + // Setup a big ground box + { + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(200.),btScalar(10.),btScalar(200.))); + m_collisionShapes.push_back(groundShape); + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-10,0)); + +#define CREATE_GROUND_COLLISION_OBJECT 1 +#ifdef CREATE_GROUND_COLLISION_OBJECT + btCollisionObject* fixedGround = new btCollisionObject(); + fixedGround->setCollisionShape(groundShape); + fixedGround->setWorldTransform(groundTransform); + m_dynamicsWorld->addCollisionObject(fixedGround); +#else + localCreateRigidBody(btScalar(0.),groundTransform,groundShape); +#endif //CREATE_GROUND_COLLISION_OBJECT + + } + + // Spawn one ragdoll + btVector3 startOffset(1,0.5,0); + spawnRagdoll(startOffset); + startOffset.setValue(-1,0.5,0); + spawnRagdoll(startOffset); + + clientResetScene(); +} + +void RagdollDemo::spawnRagdoll(const btVector3& startOffset) +{ + RagDoll* ragDoll = new RagDoll (m_dynamicsWorld, startOffset); + m_ragdolls.push_back(ragDoll); +} + +void RagdollDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //simple dynamics world doesn't handle fixed-time-stepping + float ms = getDeltaTimeMicroseconds(); + + float minFPS = 1000000.f/60.f; + if (ms > minFPS) + ms = minFPS; + + if (m_dynamicsWorld) + { + m_dynamicsWorld->stepSimulation(ms / 1000000.f); + + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + + + } + + renderme(); + + glFlush(); + + glutSwapBuffers(); +} + +void RagdollDemo::displayCallback() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + //optional but useful: debug drawing + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + glFlush(); + glutSwapBuffers(); +} + +void RagdollDemo::keyboardCallback(unsigned char key, int x, int y) +{ + switch (key) + { + case 'e': + { + btVector3 startOffset(0,2,0); + spawnRagdoll(startOffset); + break; + } + default: + DemoApplication::keyboardCallback(key, x, y); + } + + +} + + + +void RagdollDemo::exitPhysics() +{ + + int i; + + for (i=0;igetNumCollisionObjects()-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;j m_ragdolls; + + //keep the collision shapes, for deletion/cleanup + btAlignedObjectArray m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + +public: + void initPhysics(); + + void exitPhysics(); + + virtual ~RagdollDemo() + { + exitPhysics(); + } + + void spawnRagdoll(const btVector3& startOffset); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + virtual void keyboardCallback(unsigned char key, int x, int y); + + static DemoApplication* Create() + { + RagdollDemo* demo = new RagdollDemo(); + demo->myinit(); + demo->initPhysics(); + return demo; + } + +}; + + +#endif diff --git a/Demos/RagdollDemo/main.cpp b/Demos/RagdollDemo/main.cpp new file mode 100644 index 0000000..0cbf63b --- /dev/null +++ b/Demos/RagdollDemo/main.cpp @@ -0,0 +1,31 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com + +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 "RagdollDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" + +GLDebugDrawer gDebugDrawer; + +int main(int argc,char* argv[]) +{ + RagdollDemo demoApp; + + demoApp.initPhysics(); + demoApp.getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + return glutmain(argc, argv,640,480,"Bullet Physics Demo. http://bulletphysics.com",&demoApp); +} diff --git a/Demos/Raytracer/CMakeLists.txt b/Demos/Raytracer/CMakeLists.txt new file mode 100644 index 0000000..21eef24 --- /dev/null +++ b/Demos/Raytracer/CMakeLists.txt @@ -0,0 +1,49 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppRaytracer + Raytracer.cpp + main.cpp +) + + +IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppRaytracer + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppRaytracer + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF(WIN32) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppRaytracer PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppRaytracer PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppRaytracer PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/Raytracer/Raytracer.cpp b/Demos/Raytracer/Raytracer.cpp new file mode 100644 index 0000000..7d78901 --- /dev/null +++ b/Demos/Raytracer/Raytracer.cpp @@ -0,0 +1,625 @@ +/* +* Copyright (c) 2005 Erwin Coumans +* +* Permission to use, copy, modify, distribute and sell this software +* and its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies. +* Erwin Coumans makes no representations about the suitability +* of this software for any purpose. +* It is provided "as is" without express or implied warranty. +*/ + + + +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" + +/* +Raytracer uses the Convex rayCast to visualize the Collision Shapes/Minkowski Sum. +Very basic raytracer, rendering into a texture. +*/ + +///Low level demo, doesn't include btBulletCollisionCommon.h + +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btTransform.h" +#include "GL_ShapeDrawer.h" +#include "GLDebugDrawer.h" + +#include "Raytracer.h" +#include "GlutStuff.h" + + +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" + +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" + +#include "BulletCollision/CollisionShapes/btConvexHullShape.h" +#include "LinearMath/btAabbUtil2.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" + + +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" +#include "BulletCollision/CollisionShapes/btConeShape.h" +#include "BulletCollision/CollisionShapes/btCylinderShape.h" +#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" + +#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h" +#include "BulletCollision/BroadphaseCollision/btAxisSweep3.h" + +#include "RenderTexture.h" + + + +static btVoronoiSimplexSolver simplexSolver; + +static float yaw=0.f,pitch=0.f,roll=0.f; +static const int maxNumObjects = 4; +static const int numObjects = 3; + + +static btConvexShape* shapePtr[maxNumObjects]; +static btTransform transforms[maxNumObjects]; + +renderTexture* raytracePicture = 0; + +//this applies to the raytracer virtual screen/image buffer +static int screenWidth = 128;//256; +//float aspectRatio = (3.f/4.f); +static int screenHeight = 64;//256;//screenWidth * aspectRatio; +GLuint glTextureId; + +btConeShape myCone(1,1); +btSphereShape mysphere(1); +btBoxShape mybox(btVector3(1,1,1)); + +btCollisionWorld* m_collisionWorld = 0; + + + +/// +/// +/// + +void Raytracer::initPhysics() +{ + m_ele = 0; + + raytracePicture = new renderTexture(screenWidth,screenHeight); + myCone.setMargin(0.2f); + + //choose shape + shapePtr[0] = &myCone; + shapePtr[1] = &mysphere; + shapePtr[2] = &mybox; + + for (int i=0;isetCollisionShape(shapePtr[s]); + obj->setWorldTransform(transforms[s]); + m_collisionWorld->addCollisionObject(obj); + } + + +} + +Raytracer::~Raytracer() +{ + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int i; + for (i=m_collisionWorld->getNumCollisionObjects()-1; i>=0 ;i--) + { + btCollisionObject* obj = m_collisionWorld->getCollisionObjectArray()[i]; + m_collisionWorld->removeCollisionObject( obj ); + delete obj; + } + + //delete collision world + delete m_collisionWorld; + + //delete broadphase + delete m_overlappingPairCache; + + //delete dispatcher + delete m_dispatcher; + + delete m_collisionConfiguration; + + delete raytracePicture; + raytracePicture=0; +} + +//to be implemented by the demo + +void Raytracer::clientMoveAndDisplay() +{ + displayCallback(); +} + + + + + + +bool Raytracer::worldRaytest(const btVector3& rayFrom,const btVector3& rayTo,btVector3& worldNormal,btVector3& worldHitPoint) +{ + + struct AllRayResultCallback : public btCollisionWorld::RayResultCallback + { + AllRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld) + :m_rayFromWorld(rayFromWorld), + m_rayToWorld(rayToWorld) + { + } + + btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction + btVector3 m_rayToWorld; + + btVector3 m_hitNormalWorld; + btVector3 m_hitPointWorld; + + virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) + { + +//caller already does the filter on the m_closestHitFraction + btAssert(rayResult.m_hitFraction <= m_closestHitFraction); + + m_closestHitFraction = rayResult.m_hitFraction; + + m_collisionObject = rayResult.m_collisionObject; + if (normalInWorldSpace) + { + m_hitNormalWorld = rayResult.m_hitNormalLocal; + } else + { + ///need to transform normal into worldspace + m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; + } + m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction); + return 1.f; + } + }; + + + AllRayResultCallback resultCallback(rayFrom,rayTo); +// btCollisionWorld::ClosestRayResultCallback resultCallback(rayFrom,rayTo); + m_collisionWorld->rayTest(rayFrom,rayTo,resultCallback); + if (resultCallback.hasHit()) + { + worldNormal = resultCallback.m_hitNormalWorld; + return true; + } + return false; +} + + +bool Raytracer::singleObjectRaytest(const btVector3& rayFrom,const btVector3& rayTo,btVector3& worldNormal,btVector3& worldHitPoint) +{ + + btScalar closestHitResults = 1.f; + + btCollisionWorld::ClosestRayResultCallback resultCallback(rayFrom,rayTo); + + bool hasHit = false; + btConvexCast::CastResult rayResult; + btSphereShape pointShape(0.0f); + btTransform rayFromTrans; + btTransform rayToTrans; + + rayFromTrans.setIdentity(); + rayFromTrans.setOrigin(rayFrom); + rayToTrans.setIdentity(); + rayToTrans.setOrigin(rayTo); + + for (int s=0;sgetAabb(transforms[s],aabbMin,aabbMax); + btScalar hitLambda = 1.f; + btVector3 hitNormal; + btCollisionObject tmpObj; + tmpObj.setWorldTransform(transforms[s]); + + + if (btRayAabb(rayFrom,rayTo,aabbMin,aabbMax,hitLambda,hitNormal)) + { + //reset previous result + + btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans, &tmpObj, shapePtr[s], transforms[s], resultCallback); + if (resultCallback.hasHit()) + { + //float fog = 1.f - 0.1f * rayResult.m_fraction; + resultCallback.m_hitNormalWorld.normalize();//.m_normal.normalize(); + worldNormal = resultCallback.m_hitNormalWorld; + //worldNormal = transforms[s].getBasis() *rayResult.m_normal; + worldNormal.normalize(); + hasHit = true; + } + } + } + + return hasHit; +} + + +bool Raytracer::lowlevelRaytest(const btVector3& rayFrom,const btVector3& rayTo,btVector3& worldNormal,btVector3& worldHitPoint) +{ + + btScalar closestHitResults = 1.f; + + bool hasHit = false; + btConvexCast::CastResult rayResult; + btSphereShape pointShape(0.0f); + btTransform rayFromTrans; + btTransform rayToTrans; + + rayFromTrans.setIdentity(); + rayFromTrans.setOrigin(rayFrom); + rayToTrans.setIdentity(); + rayToTrans.setOrigin(rayTo); + + for (int s=0;sgetAabb(transforms[s],aabbMin,aabbMax); + btScalar hitLambda = 1.f; + btVector3 hitNormal; + btCollisionObject tmpObj; + tmpObj.setWorldTransform(transforms[s]); + + + if (btRayAabb(rayFrom,rayTo,aabbMin,aabbMax,hitLambda,hitNormal)) + { + //reset previous result + + //choose the continuous collision detection method + btSubsimplexConvexCast convexCaster(&pointShape,shapePtr[s],&simplexSolver); + //btGjkConvexCast convexCaster(&pointShape,shapePtr[s],&simplexSolver); + //btContinuousConvexCollision convexCaster(&pointShape,shapePtr[s],&simplexSolver,0); + + if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,transforms[s],transforms[s],rayResult)) + { + if (rayResult.m_fraction < closestHitResults) + { + closestHitResults = rayResult.m_fraction; + + worldNormal = transforms[s].getBasis() *rayResult.m_normal; + worldNormal.normalize(); + hasHit = true; + } + } + } + } + + return hasHit; + +} + + +void Raytracer::displayCallback() +{ + + updateCamera(); + + for (int i=0;isetPixel(x,y,rgba); + } + } + +#if 1 + btVector3 rayTo; + btTransform colObjWorldTransform; + colObjWorldTransform.setIdentity(); + + int mode = 0; + + for (x=0;xsetPixel(x,y,rgba); + } else + btVector4 rgba = raytracePicture->getPixel(x,y); + if (!rgba.length2()) + { + raytracePicture->setPixel(x,y,btVector4(1,1,1,1)); + } + } + } +#endif + +extern unsigned char sFontData[]; + if (0) + { + + const char* text="ABC abc 123 !@#"; + int x=0; + for (int cc = 0;ccsetPixel(x,y,rgba); + raytracePicture->addPixel(x,y,rgba); + } + y++; + } + x++; + } + } + } + + + //raytracePicture->grapicalPrintf("CCD RAYTRACER",sFontData); + char buffer[256]; + sprintf(buffer,"%d rays",screenWidth*screenHeight*numObjects); + //sprintf(buffer,"Toggle",screenWidth*screenHeight*numObjects); + //sprintf(buffer,"TEST",screenWidth*screenHeight*numObjects); + //raytracePicture->grapicalPrintf(buffer,sFontData,0,10);//&BMF_font_helv10,0,10); + raytracePicture->grapicalPrintf(buffer,sFontData,0,0);//&BMF_font_helv10,0,10); + + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glFrustum(-1.0,1.0,-1.0,1.0,3,2020.0); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); // reset The Modelview Matrix + glTranslatef(0.0f,0.0f,-3.1f); // Move Into The Screen 5 Units + + + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,glTextureId ); + + const unsigned char *ptr = raytracePicture->getBuffer(); + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + raytracePicture->getWidth(),raytracePicture->getHeight(), + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + ptr); + + + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4f (1,1,1,1); // alpha=0.5=half visible + + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); + glVertex2f(-1,1); + glTexCoord2f(1.0f, 0.0f); + glVertex2f(1,1); + glTexCoord2f(1.0f, 1.0f); + glVertex2f(1,-1); + glTexCoord2f(0.0f, 1.0f); + glVertex2f(-1,-1); + glEnd(); + + + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + + + glDisable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + + GL_ShapeDrawer::drawCoordSystem(); + + + + { + for (int i=0;igetAabb(transforms[i],aabbMin,aabbMax); + } + } + + glPushMatrix(); + + + + + glPopMatrix(); + + pitch += 0.005f; + yaw += 0.01f; + m_azi += 1.f; + + glFlush(); + glutSwapBuffers(); +} + diff --git a/Demos/Raytracer/Raytracer.h b/Demos/Raytracer/Raytracer.h new file mode 100644 index 0000000..a8ff33f --- /dev/null +++ b/Demos/Raytracer/Raytracer.h @@ -0,0 +1,65 @@ +/* +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 RAYTRACER_H +#define RAYTRACER_H + +#include "GlutDemoApplication.h" + +class btDefaultCollisionConfiguration; +class btCollisionDispatcher; +class btAxisSweep3; +class btCollisionWorld; + +///Raytracer shows the inner working of the ray casting, using ray tracing rendering into a texture. +class Raytracer : public GlutDemoApplication +{ + + btDefaultCollisionConfiguration* m_collisionConfiguration; + btCollisionDispatcher* m_dispatcher; + btAxisSweep3* m_overlappingPairCache; + btCollisionWorld* m_collisionWorld; + bool m_initialized; + + public: + + void initPhysics(); + + virtual ~Raytracer(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + ///worldRaytest performs a ray versus all objects in a collision world, returning true is a hit is found (filling in worldNormal and worldHitPoint) + bool worldRaytest(const btVector3& rayFrom,const btVector3& rayTo,btVector3& worldNormal,btVector3& worldHitPoint); + + ///singleObjectRaytest performs a ray versus one collision shape, returning true is a hit is found (filling in worldNormal and worldHitPoint) + bool singleObjectRaytest(const btVector3& rayFrom,const btVector3& rayTo,btVector3& worldNormal,btVector3& worldHitPoint); + + ///lowlevelRaytest performs a ray versus convex shape, returning true is a hit is found (filling in worldNormal and worldHitPoint) + bool lowlevelRaytest(const btVector3& rayFrom,const btVector3& rayTo,btVector3& worldNormal,btVector3& worldHitPoint); + + static DemoApplication* Create() + { + Raytracer* demo = new Raytracer(); + demo->myinit(); + demo->initPhysics(); + return demo; + } +}; + +#endif //RAYTRACER_H + + diff --git a/Demos/Raytracer/main.cpp b/Demos/Raytracer/main.cpp new file mode 100644 index 0000000..dd51529 --- /dev/null +++ b/Demos/Raytracer/main.cpp @@ -0,0 +1,16 @@ + +#include "Raytracer.h" +#include "GlutStuff.h" + + +int main(int argc,char** argv) +{ + Raytracer* raytraceDemo = new Raytracer(); + + raytraceDemo->initPhysics(); + + raytraceDemo->setCameraDistance(6.f); + + return glutmain(argc, argv,640,640,"Bullet GJK Implicit Shape Raytracer Demo",raytraceDemo); +} + diff --git a/Demos/SerializeDemo/AMD/CMakeLists.txt b/Demos/SerializeDemo/AMD/CMakeLists.txt new file mode 100644 index 0000000..ab13f6e --- /dev/null +++ b/Demos/SerializeDemo/AMD/CMakeLists.txt @@ -0,0 +1,164 @@ + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletFileLoader +${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletWorldImporter +${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL +${AMD_OPENCL_INCLUDES} +) + +ADD_DEFINITIONS(-DDESERIALIZE_SOFT_BODIES) +ADD_DEFINITIONS(-DUSE_AMD_OPENCL) +ADD_DEFINITIONS(-DCL_PLATFORM_AMD) + +IF(WIN32) +ADD_DEFINITIONS(-DGLEW_STATIC) +ENDIF(WIN32) + +IF (CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY + ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew64s.lib ) +ELSE(CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew32s.lib ) +ENDIF(CMAKE_CL_64) + + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport + BulletWorldImporter + BulletSoftBody + BulletDynamics + BulletCollision + BulletFileLoader + LinearMath + BulletSoftBodySolvers_OpenCL_AMD + BulletMultiThreaded + ${GLUT_glut_LIBRARY} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${CMAK_GLEW_LIBRARY} + ${CMAKE_ATISTREAMSDK_LIBPATH}/OpenCL.lib + ) + + IF (WIN32) + ADD_EXECUTABLE(AppSerializeDemo_AMD + ../main.cpp + ../SerializeDemo.cpp + ../SerializeDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLInclude.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/clew.c + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/clew.h + + ) + ELSE() + ADD_EXECUTABLE(AppSerializeDemo_AMD + ../main.cpp + ../SerializeDemo.cpp + ../SerializeDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLInclude.h + + ) + ENDIF() + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (WIN32) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppSerializeDemo_AMD + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppSerializeDemo_AMD + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF(WIN32) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + +ELSE (USE_GLUT) + + LINK_LIBRARIES( + OpenGLSupport + BulletWorldImporter + BulletSoftBody + BulletDynamics + BulletCollision + BulletFileLoader + LinearMath + BulletSoftBodySolvers_OpenCL_AMD + BulletMultiThreaded + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${CMAK_GLEW_LIBRARY} + ${CMAKE_ATISTREAMSDK_LIBPATH}/OpenCL.lib + ) + + ADD_EXECUTABLE(AppSerializeDemo_AMD + WIN32 + ../../OpenGL/Win32AppMain.cpp + ../Win32SerializeDemo.cpp + ../SerializeDemo.cpp + ../SerializeDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLUtils.h + ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOpenCLInclude.h + ) +ENDIF (USE_GLUT) + +IF(WIN32) +IF (CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppSerializeDemo_AMD POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} ) + ENDIF() +ELSE(CMAKE_CL_64) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( TARGET AppSerializeDemo_AMD POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR}) + ENDIF() +ENDIF(CMAKE_CL_64) +ENDIF(WIN32) + + +IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES AND NOT INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) + ADD_CUSTOM_COMMAND( + TARGET AppSerializeDemo_AMD + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SerializeDemo/testFileCloth.bullet ${CMAKE_CURRENT_BINARY_DIR}/testFile.bullet + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl ${CMAKE_CURRENT_BINARY_DIR}/OpenCLC10/ApplyForces.cl + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl ${CMAKE_CURRENT_BINARY_DIR}/OpenCLC10/ComputeBounds.cl + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl ${CMAKE_CURRENT_BINARY_DIR}/OpenCLC10/Integrate.cl + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl ${CMAKE_CURRENT_BINARY_DIR}/OpenCLC10/OutputToVertexArray.cl + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl ${CMAKE_CURRENT_BINARY_DIR}/OpenCLC10/PrepareLinks.cl + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl ${CMAKE_CURRENT_BINARY_DIR}/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl ${CMAKE_CURRENT_BINARY_DIR}/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl ${CMAKE_CURRENT_BINARY_DIR}/OpenCLC10/SolvePositions.cl + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl ${CMAKE_CURRENT_BINARY_DIR}/OpenCLC10/SolvePositionsSIMDBatched.cl + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl ${CMAKE_CURRENT_BINARY_DIR}/OpenCLC10/UpdateConstants.cl + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl ${CMAKE_CURRENT_BINARY_DIR}/OpenCLC10/UpdateFixedVertexPositions.cl + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl ${CMAKE_CURRENT_BINARY_DIR}/OpenCLC10/UpdateNodes.cl + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl ${CMAKE_CURRENT_BINARY_DIR}/OpenCLC10/UpdateNormals.cl + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl ${CMAKE_CURRENT_BINARY_DIR}/OpenCLC10/UpdatePositions.cl + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl ${CMAKE_CURRENT_BINARY_DIR}/OpenCLC10/UpdatePositionsFromVelocities.cl + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl ${CMAKE_CURRENT_BINARY_DIR}/OpenCLC10/VSolveLinks.cl + + ) +ENDIF () + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppSerializeDemo_AMD PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppSerializeDemo_AMD PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppSerializeDemo_AMD PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) diff --git a/Demos/SerializeDemo/AMD/premake4.lua b/Demos/SerializeDemo/AMD/premake4.lua new file mode 100644 index 0000000..360633b --- /dev/null +++ b/Demos/SerializeDemo/AMD/premake4.lua @@ -0,0 +1,65 @@ + + hasCL = findOpenCL_AMD() + + if (hasCL) then + + project "AppOpenCLClothDemo_AMD" + + defines { "USE_AMD_OPENCL","CL_PLATFORM_AMD"} + + initOpenCL_AMD() + + language "C++" + + kind "ConsoleApp" + targetdir "../../.." + + libdirs {"../../../Glut"} + + links { + "LinearMath", + "BulletCollision", + "BulletDynamics", + "BulletSoftBody", + "BulletSoftBodySolvers_OpenCL_AMD", + "opengl32" + } + + configuration "x64" + links { + "glut64", + "glew64s" + } + configuration "x32" + links { + "glut32", + "glew32s" + } + + configuration{} + + + includedirs { + "../../../src", + "../../../Glut", + "../../SharedOpenCL", + "../../OpenGL" + } + + files { + "../cl_cloth_demo.cpp", + "../../SharedOpenCL/btOclUtils.h", + "../../SharedOpenCL/btOclCommon.h", + "../../SharedOpenCL/btOclUtils.cpp", + "../../SharedOpenCL/btOclCommon.cpp", + "../../OpenGL/GLDebugDrawer.cpp", + "../../OpenGL/stb_image.cpp", + "../../OpenGL/stb_image.h", + "../gl_win.cpp", + "../clstuff.cpp", + "../clstuff.h", + "../gl_win.h", + "../cloth.h" + } + + end \ No newline at end of file diff --git a/Demos/SerializeDemo/CMakeLists.txt b/Demos/SerializeDemo/CMakeLists.txt new file mode 100644 index 0000000..b031750 --- /dev/null +++ b/Demos/SerializeDemo/CMakeLists.txt @@ -0,0 +1,95 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# This is the variable for Windows. I use this to define the root of my directory structure. +SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/Glut) + +# You shouldn't have to modify anything below this line +######################################################## + +IF(BUILD_AMD_OPENCL_DEMOS) + SUBDIRS(AMD) +ENDIF() + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletFileLoader +${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletWorldImporter +) + +ADD_DEFINITIONS(-DDESERIALIZE_SOFT_BODIES) + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport BulletWorldImporter BulletSoftBody BulletDynamics BulletCollision BulletFileLoader LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + IF (WIN32) + ADD_EXECUTABLE(AppSerializeDemo + main.cpp + SerializeDemo.cpp + SerializeDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) + ELSE() + ADD_EXECUTABLE(AppSerializeDemo + main.cpp + SerializeDemo.cpp + SerializeDemo.h + ) + ENDIF() + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (WIN32) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppSerializeDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppSerializeDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF(WIN32) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + +ELSE (USE_GLUT) + + LINK_LIBRARIES( + OpenGLSupport BulletWorldImporter BulletSoftBody BulletDynamics BulletCollision BulletFileLoader LinearMath ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + ADD_EXECUTABLE(AppSerializeDemo + WIN32 + ../OpenGL/Win32AppMain.cpp + Win32SerializeDemo.cpp + SerializeDemo.cpp + SerializeDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) +ENDIF (USE_GLUT) + +IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES AND NOT INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) + ADD_CUSTOM_COMMAND( + TARGET AppSerializeDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SerializeDemo/testFile.bullet ${CMAKE_CURRENT_BINARY_DIR}/testFile.bullet + ) +ENDIF () + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppSerializeDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppSerializeDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppSerializeDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + + diff --git a/Demos/SerializeDemo/SerializeDemo.cpp b/Demos/SerializeDemo/SerializeDemo.cpp new file mode 100644 index 0000000..9b6117c --- /dev/null +++ b/Demos/SerializeDemo/SerializeDemo.cpp @@ -0,0 +1,928 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2010 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. +*/ + +#define TEST_SERIALIZATION 1 +//#undef DESERIALIZE_SOFT_BODIES + +#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES +#define CREATE_NEW_BULLETFILE 1 +#endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + +///create 125 (5x5x5) dynamic object +#define ARRAY_SIZE_X 5 +#define ARRAY_SIZE_Y 5 +#define ARRAY_SIZE_Z 5 + +//maximum number of objects (and allow user to shoot additional boxes) +#define MAX_PROXIES (ARRAY_SIZE_X*ARRAY_SIZE_Y*ARRAY_SIZE_Z + 1024) + +///scaling of the objects (0.1 = 20 centimeter boxes ) +#define SCALING 1. +#define START_POS_X -5 +#define START_POS_Y -5 +#define START_POS_Z -3 + +#include "SerializeDemo.h" +#include "GlutStuff.h" +///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files. +#include "btBulletDynamicsCommon.h" +#ifdef TEST_SERIALIZATION +#include "LinearMath/btSerializer.h" +#include "btBulletFile.h" +#include "btBulletWorldImporter.h" +#endif //TEST_SERIALIZATION + +#include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h" +#include //printf debugging + + + +#ifdef DESERIALIZE_SOFT_BODIES +#include "BulletSoftBody/btSoftBodySolvers.h" + + +#ifdef USE_AMD_OPENCL + #include + #include + #include "../SharedOpenCL/btOpenCLUtils.h" + + extern cl_context g_cxMainContext; + extern cl_device_id g_cdDevice; + extern cl_command_queue g_cqCommandQue; +#endif + +btSoftBodySolver* fSoftBodySolver=0; + +#include "BulletSoftBody/btSoftBodyHelpers.h" +#include "BulletSoftBody/btSoftRigidDynamicsWorld.h" +#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h" +#endif + +void SerializeDemo::keyboardCallback(unsigned char key, int x, int y) +{ + btAlignedObjectArray bodies; + if (key == 'g') + { + int numManifolds = getDynamicsWorld()->getDispatcher()->getNumManifolds(); + + for (int i=0;igetDispatcher()->getManifoldByIndexInternal(i); + if (!manifold->getNumContacts()) + continue; + + btScalar minDist = 1e30f; + int minIndex = -1; + for (int v=0;vgetNumContacts();v++) + { + if (minDist >manifold->getContactPoint(v).getDistance()) + { + minDist = manifold->getContactPoint(v).getDistance(); + minIndex = v; + } + } + if (minDist>0.) + continue; + + btCollisionObject* colObj0 = (btCollisionObject*)manifold->getBody0(); + btCollisionObject* colObj1 = (btCollisionObject*)manifold->getBody1(); + int tag0 = (colObj0)->getIslandTag(); + int tag1 = (colObj1)->getIslandTag(); + btRigidBody* body0 = btRigidBody::upcast(colObj0); + btRigidBody* body1 = btRigidBody::upcast(colObj1); + if (bodies.findLinearSearch(body0)==bodies.size()) + bodies.push_back(body0); + if (bodies.findLinearSearch(body1)==bodies.size()) + bodies.push_back(body1); + + if (body0 && body1) + { + if (!colObj0->isStaticOrKinematicObject() && !colObj1->isStaticOrKinematicObject()) + { + if (body0->checkCollideWithOverride(body1)) + { + { + btTransform trA,trB; + trA.setIdentity(); + trB.setIdentity(); + btVector3 contactPosWorld = manifold->getContactPoint(minIndex).m_positionWorldOnA; + btTransform globalFrame; + globalFrame.setIdentity(); + globalFrame.setOrigin(contactPosWorld); + + trA = body0->getWorldTransform().inverse()*globalFrame; + trB = body1->getWorldTransform().inverse()*globalFrame; + + btGeneric6DofConstraint* dof6 = new btGeneric6DofConstraint(*body0,*body1,trA,trB,true); + dof6->setOverrideNumSolverIterations(100); + + dof6->setBreakingImpulseThreshold(35); + + for (int i=0;i<6;i++) + dof6->setLimit(i,0,0); + getDynamicsWorld()->addConstraint(dof6,true); + + } + } + } + } + + } + + for (int i=0;iremoveRigidBody(bodies[i]); + getDynamicsWorld()->addRigidBody(bodies[i]); + } + }else + { + PlatformDemoApplication::keyboardCallback(key,x,y); + } +} + + +void SerializeDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //simple dynamics world doesn't handle fixed-time-stepping + float ms = getDeltaTimeMicroseconds(); + + ///step the simulation + if (m_dynamicsWorld) + { + m_dynamicsWorld->stepSimulation(ms / 1000000.f); + +#ifdef DESERIALIZE_SOFT_BODIES + if (fSoftBodySolver) + fSoftBodySolver->copyBackToSoftBodies(); +#endif + + m_dynamicsWorld->debugDrawWorld(); + +#ifdef DESERIALIZE_SOFT_BODIES + if (m_dynamicsWorld->getWorldType()==BT_SOFT_RIGID_DYNAMICS_WORLD) + { + //optional but useful: debug drawing + btSoftRigidDynamicsWorld* softWorld = (btSoftRigidDynamicsWorld*)m_dynamicsWorld; + + for ( int i=0;igetSoftBodyArray().size();i++) + { + btSoftBody* psb=(btSoftBody*)softWorld->getSoftBodyArray()[i]; + if (softWorld->getDebugDrawer() && !(softWorld->getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe))) + { + btSoftBodyHelpers::DrawFrame(psb,softWorld->getDebugDrawer()); + btSoftBodyHelpers::Draw(psb,softWorld->getDebugDrawer(),softWorld->getDrawFlags()); + } + } + } +#endif //DESERIALIZE_SOFT_BODIES + + } + + renderme(); + + glFlush(); + + swapBuffers(); + +} +#ifdef USE_AMD_OPENCL + +///the CachingCLFuncs class will try to create/load precompiled binary programs, instead of the slow on-line compilation of programs +class CachingCLFuncs : public CLFunctions +{ + cl_device_id m_device; + + public: + + CachingCLFuncs (cl_command_queue cqCommandQue, cl_context cxMainContext, cl_device_id device) + :CLFunctions(cqCommandQue,cxMainContext), + m_device(device) + { + } + + virtual cl_kernel compileCLKernelFromString( const char* kernelSource, const char* kernelName, const char* additionalMacros, const char* srcFileNameForCaching) + { + + cl_int pErrNum; + cl_program prog; + + prog = btOpenCLUtils::compileCLProgramFromFile( m_cxMainContext,m_device, &pErrNum,additionalMacros ,srcFileNameForCaching); + if (!prog) + { + printf("Using embedded kernel source instead:\n"); + prog = btOpenCLUtils::compileCLProgramFromString( m_cxMainContext,m_device, kernelSource, &pErrNum,additionalMacros); + } + + return btOpenCLUtils::compileCLKernelFromString( m_cxMainContext,m_device, kernelSource, kernelName, &pErrNum, prog,additionalMacros); + } + +}; +#endif + + +void SerializeDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (m_dynamicsWorld->getWorldType()==BT_SOFT_RIGID_DYNAMICS_WORLD) + { +#ifdef DESERIALIZE_SOFT_BODIES + + //optional but useful: debug drawing + btSoftRigidDynamicsWorld* softWorld = (btSoftRigidDynamicsWorld*)m_dynamicsWorld; + + for ( int i=0;igetSoftBodyArray().size();i++) + { + btSoftBody* psb=(btSoftBody*)softWorld->getSoftBodyArray()[i]; + if (softWorld->getDebugDrawer() && !(softWorld->getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe))) + { + btSoftBodyHelpers::DrawFrame(psb,softWorld->getDebugDrawer()); + btSoftBodyHelpers::Draw(psb,softWorld->getDebugDrawer(),softWorld->getDrawFlags()); + } + } +#endif //DESERIALIZE_SOFT_BODIES + } + + renderme(); + + //optional but useful: debug drawing to detect problems + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + glFlush(); + swapBuffers(); +} + +enum SolverType +{ + kSolverAccelerationOpenCL_CPU = 1, + kSolverAccelerationOpenCL_GPU = 2, + kSolverAccelerationNone = 3 +}; + + +void SerializeDemo::setupEmptyDynamicsWorld() +{ + ///collision configuration contains default setup for memory, collision setup + //m_collisionConfiguration = new btDefaultCollisionConfiguration(); +#ifdef DESERIALIZE_SOFT_BODIES + m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration(); +#else + m_collisionConfiguration = new btDefaultCollisionConfiguration(); +#endif //DESERIALIZE_SOFT_BODIES + + //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; + +#ifdef DESERIALIZE_SOFT_BODIES + + + + #ifdef USE_AMD_OPENCL + + int solverAccel = kSolverAccelerationOpenCL_GPU; + + if ( 1 ) { + switch (solverAccel) + { + case kSolverAccelerationOpenCL_GPU: + { + btOpenCLSoftBodySolverSIMDAware* softSolv= new btOpenCLSoftBodySolverSIMDAware( g_cqCommandQue, g_cxMainContext ); + //btOpenCLSoftBodySolver* softSolv= new btOpenCLSoftBodySolver( g_cqCommandQue, g_cxMainContext); + fSoftBodySolver = softSolv; + + CLFunctions* funcs = new CachingCLFuncs(g_cqCommandQue, g_cxMainContext,g_cdDevice); + softSolv->setCLFunctions(funcs); + + + break; + } + case kSolverAccelerationOpenCL_CPU: + { + //fSoftBodySolver = new btCPUSoftBodySolver(); + break; + }; + case kSolverAccelerationNone: + default: + { + fSoftBodySolver = NULL; + } + }; + } + else + { + if ( solverAccel != kSolverAccelerationNone ) + { + } + else + { + } + fSoftBodySolver = NULL; + } +#else + + fSoftBodySolver = NULL; +#endif + + btSoftRigidDynamicsWorld* world = new btSoftRigidDynamicsWorld(m_dispatcher, m_broadphase, m_solver, + m_collisionConfiguration, fSoftBodySolver); + m_dynamicsWorld = world; + + //world->setDrawFlags(world->getDrawFlags()^fDrawFlags::Clusters); +#else + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + //m_dynamicsWorld ->getSolverInfo().m_solverMode|=SOLVER_RANDMIZE_ORDER; + //m_dynamicsWorld->getDispatchInfo().m_enableSatConvex = true; + //m_dynamicsWorld->getSolverInfo().m_splitImpulse=true; +#endif //DESERIALIZE_SOFT_BODIES + + //btGImpactCollisionAlgorithm::registerAlgorithm((btCollisionDispatcher*)m_dynamicsWorld->getDispatcher()); + + m_dynamicsWorld->setGravity(btVector3(0,-10,0)); + +} + + +#ifdef DESERIALIZE_SOFT_BODIES +#include "BulletSoftBody/btSoftBodyData.h" +class MySoftBulletWorldImporter : public btBulletWorldImporter +{ + + btSoftRigidDynamicsWorld* m_softRigidWorld; + + btHashMap m_materialMap; + + btHashMap m_clusterBodyMap; + btHashMap m_softBodyMap; + + + +public: + + MySoftBulletWorldImporter(btSoftRigidDynamicsWorld* world) + :btBulletWorldImporter(world), + m_softRigidWorld(world) + { + + } + + virtual ~MySoftBulletWorldImporter() + { + + } + + virtual bool convertAllObjects( bParse::btBulletFile* bulletFile2) + { + bool result = btBulletWorldImporter::convertAllObjects(bulletFile2); + int i; + //now the soft bodies + for (i=0;im_softBodies.size();i++) + { + if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) + { + btAssert(0); //not yet + //btSoftBodyFloatData* softBodyData = (btSoftBodyFloatData*)bulletFile2->m_softBodies[i]; + } else + { + btSoftBodyFloatData* softBodyData = (btSoftBodyFloatData*)bulletFile2->m_softBodies[i]; + int i; + int numNodes = softBodyData->m_numNodes; + + + btSoftBody* psb=new btSoftBody(&m_softRigidWorld->getWorldInfo()); + m_softBodyMap.insert(softBodyData,psb); + + //materials + for (i=0;im_numMaterials;i++) + { + SoftBodyMaterialData* matData = softBodyData->m_materials[i]; + btSoftBody::Material** matPtr = m_materialMap.find(matData); + btSoftBody::Material* mat = 0; + if (matPtr&& *matPtr) + { + mat = *matPtr; + } else + { + mat = psb->appendMaterial(); + mat->m_flags = matData->m_flags; + mat->m_kAST = matData->m_angularStiffness; + mat->m_kLST = matData->m_linearStiffness; + mat->m_kVST = matData->m_volumeStiffness; + m_materialMap.insert(matData,mat); + } + } + + + + + for (i=0;im_nodes[i]; + btVector3 position; + position.deSerializeFloat(nodeData.m_position); + btScalar mass = nodeData.m_inverseMass? 1./nodeData.m_inverseMass : 0.f; + psb->appendNode(position,mass); + btSoftBody::Node* node = &psb->m_nodes[psb->m_nodes.size()-1]; + node->m_area = nodeData.m_area; + node->m_battach = nodeData.m_attach; + node->m_f.deSerializeFloat(nodeData.m_accumulatedForce); + node->m_im = nodeData.m_inverseMass; + + btSoftBody::Material** matPtr = m_materialMap.find(nodeData.m_material); + if (matPtr && *matPtr) + { + node->m_material = *matPtr; + } else + { + printf("no mat?\n"); + } + + node->m_n.deSerializeFloat(nodeData.m_normal); + node->m_q = node->m_x; + node->m_v.deSerializeFloat(nodeData.m_velocity); + + } + + for (i=0;im_numLinks;i++) + { + SoftBodyLinkData& linkData = softBodyData->m_links[i]; + btSoftBody::Material** matPtr = m_materialMap.find(linkData.m_material); + if (matPtr && *matPtr) + { + psb->appendLink(linkData.m_nodeIndices[0],linkData.m_nodeIndices[1],*matPtr); + } else + { + psb->appendLink(linkData.m_nodeIndices[0],linkData.m_nodeIndices[1]); + } + btSoftBody::Link* link = &psb->m_links[psb->m_links.size()-1]; + link->m_bbending = linkData.m_bbending; + link->m_rl = linkData.m_restLength; + } + + for (i=0;im_numFaces;i++) + { + SoftBodyFaceData& faceData = softBodyData->m_faces[i]; + btSoftBody::Material** matPtr = m_materialMap.find(faceData.m_material); + if (matPtr && *matPtr) + { + psb->appendFace(faceData.m_nodeIndices[0],faceData.m_nodeIndices[1],faceData.m_nodeIndices[2],*matPtr); + } else + { + psb->appendFace(faceData.m_nodeIndices[0],faceData.m_nodeIndices[1],faceData.m_nodeIndices[2]); + } + btSoftBody::Face* face = &psb->m_faces[psb->m_faces.size()-1]; + face->m_normal.deSerializeFloat(faceData.m_normal); + face->m_ra = faceData.m_restArea; + } + + + + //anchors + for (i=0;im_numAnchors;i++) + { + btCollisionObject** colAptr = m_bodyMap.find(softBodyData->m_anchors[i].m_rigidBody); + if (colAptr && *colAptr) + { + btRigidBody* body = btRigidBody::upcast(*colAptr); + if (body) + { + bool disableCollision = false; + btVector3 localPivot; + localPivot.deSerializeFloat(softBodyData->m_anchors[i].m_localFrame); + psb->appendAnchor(softBodyData->m_anchors[i].m_nodeIndex,body,localPivot, disableCollision); + } + } + } + + if (softBodyData->m_pose) + { + psb->m_pose.m_aqq.deSerializeFloat( softBodyData->m_pose->m_aqq); + psb->m_pose.m_bframe = (softBodyData->m_pose->m_bframe!=0); + psb->m_pose.m_bvolume = (softBodyData->m_pose->m_bvolume!=0); + psb->m_pose.m_com.deSerializeFloat(softBodyData->m_pose->m_com); + + psb->m_pose.m_pos.resize(softBodyData->m_pose->m_numPositions); + for (i=0;im_pose->m_numPositions;i++) + { + psb->m_pose.m_pos[i].deSerializeFloat(softBodyData->m_pose->m_positions[i]); + } + psb->m_pose.m_rot.deSerializeFloat(softBodyData->m_pose->m_rot); + psb->m_pose.m_scl.deSerializeFloat(softBodyData->m_pose->m_scale); + psb->m_pose.m_wgh.resize(softBodyData->m_pose->m_numWeigts); + for (i=0;im_pose->m_numWeigts;i++) + { + psb->m_pose.m_wgh[i] = softBodyData->m_pose->m_weights[i]; + } + psb->m_pose.m_volume = softBodyData->m_pose->m_restVolume; + } + +#if 1 + psb->m_cfg.piterations=softBodyData->m_config.m_positionIterations; + psb->m_cfg.diterations=softBodyData->m_config.m_driftIterations; + psb->m_cfg.citerations=softBodyData->m_config.m_clusterIterations; + psb->m_cfg.viterations=softBodyData->m_config.m_velocityIterations; + + //psb->setTotalMass(0.1); + psb->m_cfg.aeromodel = (btSoftBody::eAeroModel::_)softBodyData->m_config.m_aeroModel; + psb->m_cfg.kLF = softBodyData->m_config.m_lift; + psb->m_cfg.kDG = softBodyData->m_config.m_drag; + psb->m_cfg.kMT = softBodyData->m_config.m_poseMatch; + psb->m_cfg.collisions = softBodyData->m_config.m_collisionFlags; + psb->m_cfg.kDF = 1.f;//softBodyData->m_config.m_dynamicFriction; + psb->m_cfg.kDP = softBodyData->m_config.m_damping; + psb->m_cfg.kPR = softBodyData->m_config.m_pressure; + psb->m_cfg.kVC = softBodyData->m_config.m_volume; + psb->m_cfg.kAHR = softBodyData->m_config.m_anchorHardness; + psb->m_cfg.kKHR = softBodyData->m_config.m_kineticContactHardness; + psb->m_cfg.kSHR = softBodyData->m_config.m_softContactHardness; + psb->m_cfg.kSRHR_CL = softBodyData->m_config.m_softRigidClusterHardness; + psb->m_cfg.kSKHR_CL = softBodyData->m_config.m_softKineticClusterHardness; + psb->m_cfg.kSSHR_CL = softBodyData->m_config.m_softSoftClusterHardness; +#endif + +// pm->m_kLST = 1; + +#if 1 + //clusters + if (softBodyData->m_numClusters) + { + m_clusterBodyMap.insert(softBodyData->m_clusters,psb); + int j; + psb->m_clusters.resize(softBodyData->m_numClusters); + for (i=0;im_numClusters;i++) + { + psb->m_clusters[i] = new(btAlignedAlloc(sizeof(btSoftBody::Cluster),16)) btSoftBody::Cluster(); + psb->m_clusters[i]->m_adamping = softBodyData->m_clusters[i].m_adamping; + psb->m_clusters[i]->m_av.deSerializeFloat(softBodyData->m_clusters[i].m_av); + psb->m_clusters[i]->m_clusterIndex = softBodyData->m_clusters[i].m_clusterIndex; + psb->m_clusters[i]->m_collide = (softBodyData->m_clusters[i].m_collide!=0); + psb->m_clusters[i]->m_com.deSerializeFloat(softBodyData->m_clusters[i].m_com); + psb->m_clusters[i]->m_containsAnchor = (softBodyData->m_clusters[i].m_containsAnchor!=0); + psb->m_clusters[i]->m_dimpulses[0].deSerializeFloat(softBodyData->m_clusters[i].m_dimpulses[0]); + psb->m_clusters[i]->m_dimpulses[1].deSerializeFloat(softBodyData->m_clusters[i].m_dimpulses[1]); + + psb->m_clusters[i]->m_framerefs.resize(softBodyData->m_clusters[i].m_numFrameRefs); + for (j=0;jm_clusters[i].m_numFrameRefs;j++) + { + psb->m_clusters[i]->m_framerefs[j].deSerializeFloat(softBodyData->m_clusters[i].m_framerefs[j]); + } + psb->m_clusters[i]->m_nodes.resize(softBodyData->m_clusters[i].m_numNodes); + for (j=0;jm_clusters[i].m_numNodes;j++) + { + int nodeIndex = softBodyData->m_clusters[i].m_nodeIndices[j]; + psb->m_clusters[i]->m_nodes[j] = &psb->m_nodes[nodeIndex]; + } + + psb->m_clusters[i]->m_masses.resize(softBodyData->m_clusters[i].m_numMasses); + for (j=0;jm_clusters[i].m_numMasses;j++) + { + psb->m_clusters[i]->m_masses[j] = softBodyData->m_clusters[i].m_masses[j]; + } + psb->m_clusters[i]->m_framexform.deSerializeFloat(softBodyData->m_clusters[i].m_framexform); + psb->m_clusters[i]->m_idmass = softBodyData->m_clusters[i].m_idmass; + psb->m_clusters[i]->m_imass = softBodyData->m_clusters[i].m_imass; + psb->m_clusters[i]->m_invwi.deSerializeFloat(softBodyData->m_clusters[i].m_invwi); + psb->m_clusters[i]->m_ldamping = softBodyData->m_clusters[i].m_ldamping; + psb->m_clusters[i]->m_locii.deSerializeFloat(softBodyData->m_clusters[i].m_locii); + psb->m_clusters[i]->m_lv.deSerializeFloat(softBodyData->m_clusters[i].m_lv); + psb->m_clusters[i]->m_matching = softBodyData->m_clusters[i].m_matching; + psb->m_clusters[i]->m_maxSelfCollisionImpulse = 0;//softBodyData->m_clusters[i].m_maxSelfCollisionImpulse; + psb->m_clusters[i]->m_ndamping = softBodyData->m_clusters[i].m_ndamping; + psb->m_clusters[i]->m_ndimpulses = softBodyData->m_clusters[i].m_ndimpulses; + psb->m_clusters[i]->m_nvimpulses = softBodyData->m_clusters[i].m_nvimpulses; + psb->m_clusters[i]->m_selfCollisionImpulseFactor = softBodyData->m_clusters[i].m_selfCollisionImpulseFactor; + psb->m_clusters[i]->m_vimpulses[0].deSerializeFloat(softBodyData->m_clusters[i].m_vimpulses[0]); + psb->m_clusters[i]->m_vimpulses[1].deSerializeFloat(softBodyData->m_clusters[i].m_vimpulses[1]); + + } + //psb->initializeClusters(); + //psb->updateClusters(); + + } +#else + + psb->m_cfg.piterations = 2; + psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS+ btSoftBody::fCollision::CL_RS; + //psb->setTotalMass(50,true); + //psb->generateClusters(64); + //psb->m_cfg.kDF=1; + psb->generateClusters(8); + + +#endif // + + + + psb->updateConstants(); + m_softRigidWorld->getWorldInfo().m_dispatcher = m_softRigidWorld->getDispatcher(); + + m_softRigidWorld->addSoftBody(psb); + + + } + } + + + //now the soft body joints + for (i=0;im_softBodies.size();i++) + { + if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) + { + btAssert(0); //not yet + //btSoftBodyFloatData* softBodyData = (btSoftBodyFloatData*)bulletFile2->m_softBodies[i]; + } else + { + btSoftBodyFloatData* softBodyData = (btSoftBodyFloatData*)bulletFile2->m_softBodies[i]; + btSoftBody** sbp = m_softBodyMap.find(softBodyData); + if (sbp && *sbp) + { + btSoftBody* sb = *sbp; + for (int i=0;im_numJoints;i++) + { + btSoftBodyJointData* sbjoint = &softBodyData->m_joints[i]; + + + btSoftBody::Body bdyB; + + btSoftBody* sbB = 0; + btTransform transA; + transA.setIdentity(); + transA = sb->m_clusters[0]->m_framexform; + + btCollisionObject** colBptr = m_bodyMap.find(sbjoint->m_bodyB); + if (colBptr && *colBptr) + { + btRigidBody* rbB = btRigidBody::upcast(*colBptr); + if (rbB) + { + bdyB = rbB; + } else + { + bdyB = *colBptr; + } + } + + + btSoftBody** bodyBptr = m_clusterBodyMap.find(sbjoint->m_bodyB); + if (bodyBptr && *bodyBptr ) + { + sbB = *bodyBptr; + bdyB = sbB->m_clusters[0]; + } + + + if (sbjoint->m_jointType==btSoftBody::Joint::eType::Linear) + { + btSoftBody::LJoint::Specs specs; + specs.cfm = sbjoint->m_cfm; + specs.erp = sbjoint->m_erp; + specs.split = sbjoint->m_split; + btVector3 relA; + relA.deSerializeFloat(sbjoint->m_refs[0]); + specs.position = transA*relA; + sb->appendLinearJoint(specs,sb->m_clusters[0],bdyB); + } + + if (sbjoint->m_jointType==btSoftBody::Joint::eType::Angular) + { + btSoftBody::AJoint::Specs specs; + specs.cfm = sbjoint->m_cfm; + specs.erp = sbjoint->m_erp; + specs.split = sbjoint->m_split; + btVector3 relA; + relA.deSerializeFloat(sbjoint->m_refs[0]); + specs.axis = transA.getBasis()*relA; + sb->appendAngularJoint(specs,sb->m_clusters[0],bdyB); + } + } + } + + } + } + + return result; + + } +}; +#endif //DESERIALIZE_SOFT_BODIES + + +SerializeDemo::~SerializeDemo() +{ + m_fileLoader->deleteAllData(); + delete m_fileLoader; + exitPhysics(); +} + +void SerializeDemo::initPhysics() +{ + setTexturing(true); + setShadows(true); + + setCameraDistance(btScalar(SCALING*30.)); + + setupEmptyDynamicsWorld(); + +#ifdef DESERIALIZE_SOFT_BODIES + m_fileLoader = new MySoftBulletWorldImporter((btSoftRigidDynamicsWorld*)m_dynamicsWorld); +#else + m_fileLoader = new btBulletWorldImporter(m_dynamicsWorld); +#endif //DESERIALIZE_SOFT_BODIES +// fileLoader->setVerboseMode(true); + + if (!m_fileLoader->loadFile("testFile.bullet")) +// if (!m_fileLoader->loadFile("../SoftDemo/testFile.bullet")) + { + ///create a few basic rigid bodies and save them to testFile.bullet + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); + // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); + btCollisionObject* groundObject = 0; + + + m_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + + //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here: + { + btScalar mass(0.); + + //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) + groundShape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + //add the body to the dynamics world + m_dynamicsWorld->addRigidBody(body); + groundObject = body; + } + + + { + //create a few dynamic rigidbodies + // Re-using the same collision is better for memory usage and performance + + int numSpheres = 2; + btVector3 positions[2] = {btVector3(0.1f,0.2f,0.3f),btVector3(0.4f,0.5f,0.6f)}; + btScalar radii[2] = {0.3f,0.4f}; + + btMultiSphereShape* colShape = new btMultiSphereShape(positions,radii,numSpheres); + + //btCollisionShape* colShape = new btCapsuleShapeZ(SCALING*1,SCALING*1); + //btCollisionShape* colShape = new btCylinderShapeZ(btVector3(SCALING*1,SCALING*1,SCALING*1)); + //btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,SCALING*1)); + //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); + m_collisionShapes.push_back(colShape); + + /// Create Dynamic Objects + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + + //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) + colShape->calculateLocalInertia(mass,localInertia); + + float start_x = START_POS_X - ARRAY_SIZE_X/2; + float start_y = START_POS_Y; + float start_z = START_POS_Z - ARRAY_SIZE_Z/2; + + for (int k=0;kaddRigidBody(body); + //body->setActivationState(ISLAND_SLEEPING); + } + } + } + } + + int maxSerializeBufferSize = 1024*1024*5; + + btDefaultSerializer* serializer = new btDefaultSerializer(maxSerializeBufferSize); + + static const char* groundName = "GroundName"; + serializer->registerNameForPointer(groundObject, groundName); + + for (int i=0;iregisterNameForPointer(m_collisionShapes[i],name); + } + + btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*(btRigidBody*)getDynamicsWorld()->getCollisionObjectArray()[2],btVector3(0,1,0)); + m_dynamicsWorld->addConstraint(p2p); + + const char* name = "constraintje"; + serializer->registerNameForPointer(p2p,name); + + m_dynamicsWorld->serialize(serializer); +#if 1 + FILE* f2 = fopen("testFile.bullet","wb"); + fwrite(serializer->getBufferPointer(),serializer->getCurrentBufferSize(),1,f2); + fclose(f2); +#endif + + } + + //clientResetScene(); + +} + + +void SerializeDemo::exitPhysics() +{ + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;j m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + class btBulletWorldImporter* m_fileLoader; + + public: + + SerializeDemo() + { + } + virtual ~SerializeDemo(); + + void initPhysics(); + + void setupEmptyDynamicsWorld(); + + void exitPhysics(); + + virtual void keyboardCallback(unsigned char key, int x, int y); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + static DemoApplication* Create() + { + SerializeDemo* demo = new SerializeDemo; + demo->myinit(); + demo->initPhysics(); + return demo; + } + + +}; + +#endif //SERIALIZE_DEMO_H + diff --git a/Demos/SerializeDemo/Win32SerializeDemo.cpp b/Demos/SerializeDemo/Win32SerializeDemo.cpp new file mode 100644 index 0000000..0cf13e8 --- /dev/null +++ b/Demos/SerializeDemo/Win32SerializeDemo.cpp @@ -0,0 +1,25 @@ +#ifdef _WINDOWS +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2010 Erwin Coumans http://bulletphysics.org + +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 "SerializeDemo.h" + +///The 'createDemo' function is called from Bullet/Demos/OpenGL/Win32AppMain.cpp to instantiate this particular demo +DemoApplication* createDemo() +{ + return new SerializeDemo(); +} + +#endif diff --git a/Demos/SerializeDemo/main.cpp b/Demos/SerializeDemo/main.cpp new file mode 100644 index 0000000..cd59147 --- /dev/null +++ b/Demos/SerializeDemo/main.cpp @@ -0,0 +1,109 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SerializeDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btHashMap.h" + + + +#ifdef USE_AMD_OPENCL + + + +#include "btOpenCLUtils.h" + +#include + +cl_context g_cxMainContext; +cl_device_id g_cdDevice; +cl_command_queue g_cqCommandQue; + + +// Returns true if OpenCL is initialized properly, false otherwise. +bool initCL( void* glCtx, void* glDC ) +{ + const char* vendorSDK = btOpenCLUtils::getSdkVendorName(); + printf("This program was compiled using the %s OpenCL SDK\n",vendorSDK); + + int ciErrNum = 0; + +#ifdef BT_USE_CLEW + ciErrNum = clewInit( "OpenCL.dll" ); + if ( ciErrNum != CLEW_SUCCESS ) { + return false; + } +#endif + +#if defined(CL_PLATFORM_MINI_CL) + cl_device_type deviceType = CL_DEVICE_TYPE_CPU; +#elif defined(CL_PLATFORM_AMD) + cl_device_type deviceType = CL_DEVICE_TYPE_GPU; +#elif defined(CL_PLATFORM_NVIDIA) + cl_device_type deviceType = CL_DEVICE_TYPE_GPU; +#else + cl_device_type deviceType = CL_DEVICE_TYPE_CPU; +#endif + + g_cxMainContext = btOpenCLUtils::createContextFromType(deviceType, &ciErrNum, glCtx, glDC); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + int numDev = btOpenCLUtils::getNumDevices(g_cxMainContext); + if (!numDev) + return false; + + g_cdDevice = btOpenCLUtils::getDevice(g_cxMainContext,0); + + btOpenCLDeviceInfo clInfo; + btOpenCLUtils::getDeviceInfo(g_cdDevice,clInfo); + btOpenCLUtils::printDeviceInfo(g_cdDevice); + + // create a command-queue + g_cqCommandQue = clCreateCommandQueue(g_cxMainContext, g_cdDevice, 0, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + return true; +} + +#endif //#ifdef USE_AMD_OPENCL + + +int main(int argc,char** argv) +{ + GLDebugDrawer gDebugDrawer; +#ifdef USE_AMD_OPENCL + + bool initialized = initCL(0,0); + btAssert(initialized); +#endif //USE_AMD_OPENCL + + + SerializeDemo serializeDemo; + serializeDemo.initPhysics(); + serializeDemo.getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + +#ifdef CHECK_MEMORY_LEAKS + serializeDemo.exitPhysics(); +#else + return glutmain(argc, argv,640,480,"Bullet Physics Demo. http://bulletphysics.org",&serializeDemo); +#endif + + //default glut doesn't return from mainloop + return 0; +} + diff --git a/Demos/SerializeDemo/testFile.bullet b/Demos/SerializeDemo/testFile.bullet new file mode 100644 index 0000000000000000000000000000000000000000..d535938f066791f0f6f12f50b6c83689721a9d9f GIT binary patch literal 171368 zcmd@7d0dR&|38k8JtSEoi9*O;M9s|AIWq}KC~NlYAw(;o5v7&VqGX9eD59iku4%3a z*|Ud`J$uOZM84;oYv%Tv_x$qwysp>OU%zv^F^}ss=W(5Lzn{nBJkD}mV>i*sY1o7X zvwR2ISd6o?pHg0r$7{gj@p_ z{2)#x8?=l^Z%-|q3h;c~9#!zITx$lXd8`0PAzHu$StrjN!Xo zOW@<{|M1OXtIql5OP6ffzq8*|{XYQ-n0MUAG3WTRT}D4>VX~H<&)*?Ompm-%#h63M zmToe9y#VE7`P-cr0AF*hmu5Y&4j#|6ko{Es|DS8a$ewV*{d-{gQ7dKNRek4gpQ^sa zBEoQ61)QBpjFDRLHL%_k$MJp5*#z z$)Lg}odd+W6M7SDv@KtJc!ps58Ary=vV#y;t8&gDY4MvhetP@uwaR%nI31S9gi@Xp zjA?wIQY8O*;sMjcz7WnOC?Csvnob}%aIF_t&J(&XgWo2PhXamGs}s(fqBg2?u7ew` zOciEPK!4pPFk-6*x%ZgWK9HBwjP|jPAsm+;3zM5Y@P!VYH;`+ygf2`)`C#z~>-7q( zLfi80o$d)%Qx@XK@h#N8bA2R)3)I$ z;@hQL_)=5(F~0TV+O_iqyU&AiJw_;*uS@J2%Qr^c1fp(L`4|eEZ-L}Vg0lc$bFCLw z&Rg`p1>9er0d4fpll$R&{(Iu)+gl)I>YVGUDUV*Y4jj3^8O-rnO8VQ6o_=UNFBT@d z1rv_T15@Px-0*=}W?|&oHMVi#)|Yd|dlo+-*V>kUIAW7vqSTRD+W0=~W(_o!EIx4bJt{IIrxq7W`Sb1$g_hoNu1#1N9qiv27F+ML5mf+p3_4kq@leAtBdK zk4D48(OKf>J2x>{jke{Zb9>3gZgXUY*oz7FV>ek!-#0$OU!0XxtDK)Ld=GfzZwQA+ z>Ji_LWyA0FpvAW7WPHc@Sk|4J2XMQ%){86WjVtQI$A^!D4oRQL{qQ~iJ#n-1R!Et; zo$IS9r#(Z##%pW9{vdW-xqH9|ii)LF>GmyzS}!AZp4D`q)MDXD{`cQewaWSJW0}C>?J>IK+bPnwtdQKe zeK;^1aYu;Tf%CC^b@3j;0oQtQ<$U_l5MYy+0yLk8#4VB)Ox1`!m)+NW%<`IUzqnJkX*kGNMO1r4HAc}k0;}~w&i)r_XVBP z9T|HA3E@0(?;xq$@uU2{HhXK8^YT1LkTgXAaWgb)x0n*evvr5U>m8cw&i(tNrKoyN9O19_Jj-3I!CFf z5KWqx9cGJy6_lG3qMbMJI+r>a*uD3?D)#DUR*iP8<`D< zb&r6)KX%s1c-~%v^LA>S2jxeAG7C=-eV6s^kE79C&Fs6dY)>@dct@WEdCpybSm`j2 zTwCaUg~CDG#FvjdGgytb<-d$Ll5Z64$n^Q%kJwv`&LF8(z)}8+gv464^SK%O0dwf7 zO!RRbiQ!6+?B6vBIP^DW`x?r}a(3Do(wDi`i!0}nCW*j4_8d4@x{usXjgr5J+{W_` zNQ=6i8>(qt;1db*bCbaSM~g^*i_!IkjK7=wY9u>XOPTkF4ms}ybCxF)&L=Ny3r2PV z;>76L3|6CU`Rbp>g5fBJv+FsA%$Y8A9xN4|J;9&oS-bP|+izOI&?m|+>YdS zKHVU1Y$EI1QNBKsC2~W81J`#_dn)BhD$By55zI+j-wl%eyQ`c_-Er&h6edFI*oxNt}0cG^wk$1@->V)%7h+lQija7uB&$rE2fj=hOKwuaf!>um$gS_%JwB#il zvw2Fr-QtsrJCeF;Ti&hB2I*S4BcnGpgmCWMbC}dEH=mzZ zwXIe;U()(EFuW_Id44j&u|ARygew3uzB{?D^py#*obux#;hbx|xN=_dOAfx@e*|93 zZZChx0VWD_n-dqJ%qiy+RL#7Dc7C16%=Kdm_=cQXqH@P0=ANSZ%tDL)k?EvTa zMcJ0xHz#vUEX%sNz?E(}B!;_*^09pMFuUi$wO(8~AGvK3EEQS9qwng*&bw%EZi>lL zrg_&QLDnaK@X(Zv;Sxn?U+vWhs`MbcuV(RZpPX^>hpsJ`5IeV-9;skXj}se&)n~8@ zZOiX4b`*?Ca%3!i80TYshKp>aHwC$Tk2SR$!}Y7sfsCatHT~rd!f`p0j}1q7_gWys z_a*sA{yp~{u{*By;>x+%&sOkr#cLp1(X>u{dpFc3bvy5h8>vk0bOeZ%g@K>mtZ%P& zMRva9i*QRvmUGwnhvmaJ`$GFFcCNeWMbzx z&kCgftW4$m9IxH+TsV3!5KY}D$Z8ZqILGp+*ZYBKzXhbPk$fbt%m^WzbFCLw&X;#P z0Fozc1eHtD$o*7&{QZ-gZ|{y2sdH|orufLM5HNf*T949YW4OSrw=IX+b3FFwBD2SPi@OP|0?4zM|&(T{VECPTW{DbDZytWKqkvgafYi;>!8(fv-Wx``2L6fuD84 zc~1?_G5@NRzBLrI__!YQYsmWcqE~3`^;jb+32Y{uCsyv3H{Rg~O&9x->!Y!jg-Q3; zi|?IVLpayAJl%VpU_atKWl$@Ey>XscdSp~Ke{oTCt&Zo#Uk#w4*Ke8`GK1WwEs_`Y z{07ROwWTl?IR6=vlMC6o8rOPp<$SH%CvcG00ru+1-cQBH-#@w8c`u|$-OkO`6nDKG z26Rd%gP>T}ZkKtWd0F~HdTkSSe(unfC%@EVHO#V`OgIk$x2T5qW{6u^@ffT|+wwPW z83+V%j!Z@W7~*5U?xLizzB&B$wzV6#{}XKl8SiRZ|G^_NeitJ-ej5+wjY=eaz!c>( zNdEGS-RI(3FRq+7I`|8`3}^#8+IFgw@w^Y>MxFECm@H+g8Wsc0FHHvmOZJ>h!w=q& z_bFB2SHaHBL^p!u6aHBRv!0G4oLfB`0;oYQ;!?vb1y-SL`KhCW1tVe{nRRy!x)wI7ov=JoE4*>%|v*Y=sC?Ciq46r?C#O|xv zm%WsGpF?B3moLGpFk_wVkquBhV*6Xdxwhpunk5KKVjY>Q2b~D#dLJ#N%kJm!2N=iK zs&79vegJg4bWJ8Y!|s=hkUVU8Zzwu^fy5CwUxH-s6TJxMT1;7h&* zxt|&(e-XKHK0t%>{%Tr3SxP|XYhmDdYj!;UI2x_VG&&<2KAb%dm-j75{yD-I>Q=BZ z+=b*Qh2QQm;w+y{gmZ1nuXWfd7?9&@*+yxupi@7HXWYF$)8m zUqu4ZOm?pJC>zbyR(%of&t~mhcSeSMKu2E~Y8^uC-0=Mt#V;TgU$}LhaIS6n^IaRs z9w$38Mh`lXakg~nAgRMY>HJXw+Sk(F)ZI9;c(fimlkqzqqW>&6UBmSt^LpayAyv6fmekeK{)zNk@ z@v(ROMoTZX%izcTQ@iJ6W(s;h$$)DDUTg`8(|JhtE9n8tnG1w-oL_^YeyDSCxD=cM9G9{mXC+Lkx3xRF0Wf#zym`NXazdu^ru=K1{4w76Qe^PAO! zf#?3+GA5KFeaj!ov$}Q%hPqG5HO|NKj;=Pu?zq;AE9YU`x`CvbHsJVZ>pHP>YYona zsBvDsGZ?f^3jhVbSkAx7e4*q#q~FYB&$&8GnkCQa;txd!eTdzE?rl)GD9cYgQ#XS2 zPi@Q3?3*koM0TE}`+{J9eSuIKd?bsXFr{|SK-O1GgQokdDY|SY8PCm;yj(v3>X%y* zJ16-_ZV=j|6W^;UpOwrx)+sEH66b3w7+-nC|)?<3g)ByTqrS#}GT$wtPwAqSK0OUJS4YnPz~(gA0wROd?zH|YbYgl$F*KuIp5xy z2PubKQ2qLDo!GfhgL49|l6SLKp&)(nYEY8L+W9!N&dU1|L|+)kuE{V_F7geQs2_N+ zcK+(HkTI3?79V_FPB_=Lyk5sUf`KWH%uVCp#Fx`Y`$)HR-p7xZ9H>>_K7ML@=yvL^ z(BZ-|62pm*y!lioC>gk0ilMN<`AC+{W%oR|){86WcZ8i`H!mHy|62Pxv2(oWpl;`E z5W|vgRu&GVoi~8$V0M0Pj^p;}UV|!eCT-bn4!HH ztU=rIrqlHWuhJYDNooagKWR(*NG&cG@=YUacQ3Wo2egOw<&TWHe~xfoUiC-Tv0Dr1 z$!ma3f>(_4qmkUR!FOVJTYS@PlfEz-tQ)loL~mm` zpZD1dI!pW5zN3=}$D#$#vez=j<%i7&tZ%;*hxSZ721~9Z%_00p!N2d#)*XUF7K?R)Z!C-JyGq( z?WI26uCf2l{8l$V zMdvLp;;&1FGgyVT<$uk*$&W>AGH3U9C7i>tHqt@Uj`3H<)-LB;j~9c`rIl35PjBMe zv8=b@Cuq3Pf?VT#EN3@4O57mVdU55vZ+9N-{X7HQXmOU@4`cc7iQAgYFr-YKb9*)A zp(iEa*TH4rz#4X6?Mo5bSG)RZ&>JmC|Rs;HH7p} zZOcn0hUB@>j?8qgND^9R?Gj6w7rFeBZ?$_)=6i4zu<-pMv-qh`IL7j6VFidjOq2VX zqx=*kKc}7$4!G8fE9WbEyaes~J_d#vU+aYP5gMEiSL6KQf-Ruaq$p54i#-oF#vi?3 zV1G0D zr2#z;^Zkz1?)-e*&{Pl|b3piAYCy(s36h)S9|V>h3<%Exlboa2N8uJz)|d1TZf z&?GM#%r|16l~SYRFCsTPAF08)gPPW7ZlNILd^Cu9#&Ul08H(EzD+KPI>^hu|f13PB zqz|;e$z!tLSB@1&_mwHI8g0v4Jc$%^MVucV8BaKW8(|`KypYU~7N*teT+M!@ z9(35(MK0;ZK6~thWTxXikUQOu?E@$u%RzEo;=j1oi!0}&|J(po+jU{n)pc_Qa+C(= zj%u9GYrY9AzYqah-)8q%LW zU^Uv7UvbGm_B9^G?WvHgja<5DEj9mjnBVYJ?b`X8H!{HUm*qwNNG86Ww?>vX%v=FV znoIL>J8(Xhhfmue}tpLKis zHina-_X|iq8&S*=<=Loq>2lr=U)WcdeHPg(jwfoLx<=f+?{WsK(6&5pjd4Ce&n_AE zVc!KXGMAF>7arwT{D`epJD)Vh1D$;f5abE+Nu16@^3XF&0k2_P9&SfE&PVbwT?xwp z$9i$)JY07f$h{*0jaMwL6VAt?HmP$y1~*cfyccc;tBR69v#spDTGe20$eg@D-D=6s z&)ar-A&=|e4I_K8Yc$O+6)CKn4H3^=*pI;~v@P$G9U)ka-Yw$av?*B+dyv4FHs;;p zgPhup;g0*YgCc`lwE2j=#LgX%EO^uan)@~-z8&YAA-Uu9Cd9XMtru6$y)x^;Ro5E9 z4pv6weo8w2<%8RJ?t(O_bMCCBd2w_sF#qfdF12LW+xzc9XQT8z^XorPD8OHH6RnX8 zEmp(O__5@AozK9+z9nAbe_mUWYi-Lj4QC0;&^v@y6?P={XP7@iDl*9AmuJ@Qc%J^u z8m3>}U|aF530{`u9YS*bpoK7_-8|9L4l? zgo~N_9T}`b+ww2&w#y$F;mGJX^dRH8af89q#$%50OIp?L*{JgyF9T=ZQ(4uNUxZ^U zR|K5}5{sT>JjeMdNM37+&M~0GwO(8~w@W$$`gMv1@}TSFe)yjMp19fhM5IiebNv1^ zRm$<*3NC#N2X=OB++H~m+4=g-!pt-5nTfWIj>sF%LuaG@VPm+1{HBHNjt7Y63~5d3 zs%`nD?M4eu<~cIs#uSja{b`1sbny4X{Or%Qdrro==MpG-Gli<$R7p6;a`P0_m)FLS zzE*+q86@w_7)R`!YrVK~Zl&;tbfhzEXwJsYDn9=H$&K^LNRc|{lhhO+5+{HQp5dSw z&AxMBXLmF|9}z}RVc7Bf()AFzXsIvsjAYM7RXv%_Y+N{6JSXzJ0;|!seC4JvK}agv zW8ohqFcyGLl_yFY7=lqFM|Q|G0dIaIS6niU)ZDV{`^`LD+2)!%aCoKpKLc zS98s--ML!xNOzdyJy#y;`;^!@mii^z@hX&RhQRnr>j5D7f}w}Q?sS>G=C=?z6A=2AVEu;<&$-<+1O8;<60 zHthIrV$;1a`uhg)*$P1S2WuHYhn%J~Z+{jf-wM{2> zu5I~PS|XT@*4wYHt0J76PPdXeRHHMHr)u{ZMK@FQj8J52zW!ZE`YLZ@YySORouPf| z5MuYbC|`u+G6nlwD%W~(<@}bO3G_bv9K`3d&+)5K@)wbtozK$Xe5RV#dAEW=vj7JW z{&fZEZ)F+iJe*#Pu%v=L50|oap{}` zNNmcrUR*i1KdTGZUONv~S2QEIt5Nb7ksIf;krwsw+)YiZ-hdFWGhYJw2DAI;J1h|A z;iD;6A^Tja?)Nmge<9jS<$Dv(*Y%;9o+ER_r<*4b&b2LX^!ir*+hdN*r}uUQ`^U7k zbj`<1zFp7Sjp2;CH-jbnd(g~^-!k0%awMC4s|TYK`;)#_g7UH4<$Ef9 zV9qOcUu{->dqrloR6MJZn89kaE&n6EyDVgL+zwn!zvaRJ$?U)zf=H z!`9a*|Lh1do@05v;bq`3uO6{`obQC>htCzn&bii$E9dpAO2F08r@%Z3yS}eR$zMcn zc0M0zQRjS~n%0VuQNZSD1h`Vc#&E+gdqLBs6Kv-_W#?)OnlvgXd4b;Xdx1Ra^rj<(xT4!0yVAuN9+Vo#%}@Dcif4O>DbH*in^Vlm(NNezTAunkyjt}fmZj~ zclLiV>c(9Benve1S_1~F(YAc%r@peD=nQ1*G=1W8y~_Af(a3##=byD3xA&cw0g9H# z(B*wv5zZMTx1Aja%I|L{z8&Xd`8{tp;eczsxN>fTo(JB)YbO~0B&$w1Uxc_(=iD8W zrAp!9VA9+WP;Jcm_7?WuP+!N*cIg3jz1{h1{esXGUuZFU1?dA%Y|IJ=zh5cd`#O;w zhqNr8b|XXZ8of7aa%ppdeT-nF^jFh7zC~s2o`Li$lt7DjS+@C(2T9y+h2&0q(qWwS z5^|06v3yb&l6G;e7gx@Wm<-s~%Lc|htef+2OAx>6oG(`KjXsTTYW_+Qdj_&%U$|V@+aEd~U^zFM*{@L7BuV^bzrYr&(Y8F};v!vuew(A*qlC=W zJU;`e)6SE8N&nhC5BF*GePBN58|`L#o%Ag;B)9#V4lJ&GCf7J0%kRTq61(GCFRq+F zADIS*%&Y*9dOWHVJ70>pQRmzPlch}W_eFsnUDkorgRGs;I*-<5>@HJR$Hf!7c71eO zzPiE>GB4QoM(t|ZRJ8a>ggADk4}(=`Tizo*CVw&7Ki?hERfhE~xHVAP{Q5Eex?1LZ z`;>Ixws5A9>G+Ps4OlKTIs$l4kC1DeuaD%o-t4v-=N~hU0LNEp;DkO>`Td|HFqQH+nKb>^0tNO{p}Cf=g*rY%Rs4c ziulQ;wG39FZF$4Tc6m?HyFYJ?+D@?d+9;4-H#ovS9J{$zW4O{HJ}mwslGn=*C%zoZ z4@E}MbEtsC@%2$YmR-iOb2YB@;>vllS38)!?;o&rvmHA|D*5>P2e%k*1yZEWxu=@q z`qrVq#VrUJ)@ObDi_<=6Z9S42smGp?h;unE&kgp2(aL8OXTH7-tVRckttn+O&=jb)l(jj5l{O!AI_Z>pNb!cGUMb9>4&NafZBa-!kK7oQ$?MY0B z^Raw+^BZD!T7=rIsoqQToI z^TE>hhiJb2lC8CB=Z~hw1JlK)gr#l=2CTtms9=wzrU$h)9fW4F#La*zx>kDYEm+ z$7Pqi*cdL-HeNn3*B6Rbv1caww!h6BmgS1|y*H9^QQPuV(&2pH%_OO(%{@*jq|of;oyo#1o*s?-9P{6fzCRQnNM}{VfWP>Ugybo zIr+kL8OwP+$CgZrSx@oDR$qv3*S5TF*>%BiwD#(Mm7SZ#IY6oXyA1xTd$qgvs<&_e zES_9Jr+f+~^8+le8f*yLPGFyL!1<;~9+23F_%E*Y;>x-BlL2fxu@7{AXQ}j;YNXUC z{--bfH@~A8puzcSHJyjhd5P9-*MLdUYz%iQ5j~^W=^FLxF&o2eoL?ZfYU&S59xg7x z#Zt1`6qa?{Aa+p3@!FPmp8b}81g**BHn=Rn`WYaWdZxzlO%%0j=dJv@L7lF*DdV>u zWL-fY$#Yj*L46_ndn`B~%ihPP5)Qc5i!0|3<_&={o-?8M<+^z%;97*Gx^G{D!BwUS zSGIsE-*C`Z&ieL*PUw6@@g%z8=2*gU-{&E6Lr-7m?aQ8x()kd=bh~ULHcvKYunKL< z`^O{-+8jjhf%G0uI1k-ESn56`lP~#MyYHDe^?LyHWERkR-^P$JNrGhm=RIN8y3<13 zj@Bq2%jeHFBAj!r7gx@&%6h;)CiP+Ct5$Vl=YgnA>YT5`jZ~(hwjrQJSOmzc&#uW_ zsz98F?x4<8vu7meMhf{oJM>J0ay+m8d>f8($QF0^WB1jxEg!$9oh$*p2hvsGLVT|C zhQZSC4w?L~4QuzE1H;C@11V#=P?d4($#|ZQWTQwPEcRf3n*--#S!ekTGQM)H7gx@A zOsNM$+g}5PE#H&-srdN&CpX`|9w}1iT%xAf>SqL)vtm6cNMJcH^hBKhE)fn4WXE%F zyWR4gnSQWxi7&DHgu*^>%#Fk10kd=%tVY}N(*qyo-$w6&3=11TIB&bLzx3D21N?V= zYWLi$sVEynCuGSSb;NUR*i9rhgbTGT9BLc%P^f z&Nm=#)Hx5rWGU0BK0#p6f+(}(5BJ|Dyv$eem=RvtWq$y(#^6g7%cQ190^&wyyxPs=T9u?wx zV>z*6GkA9JEV;({wO(8~w@QixHx06ZWBTDb;XD|%QJwRRxY5d_uNx00 z&5Q8KPm6yYsVKlIv@K5? z)t8CUIhmE;*)vMK)2*d$V~_CNUf1r~sCB__LD7nP^xF~Fh@I0&{<^amIQ0HSILG-| zw)Q?vIN(|@uAIl}6#-$I0=-MTs!llHgt$@XJVePi{+PNW8Vr|40ZA7&hU<`s=I770 z2n##1&!69nIV#^#?E`JjvN0SZ6hUFHrDC&pCQNOV7umnD8IRs4Q?`mM-xIg-JPavQ=R8zRdGuWg=r}G6?9yZBY7URlvr8F5s)Gx=)@t@^zkJzt zUs&;({cR49@>ZgaUMb>ZN8K2#M%(iKIWP04Zb9?&5km z40wf={PdH}iJkM9N`C36oghV`M>x+y`B<*l5lJ}bS}(4g$Iade?#+t;ri1F{Y*Yl| zMxFC;OqMd4xA6xTQcZc@ zyJQgEBMLNL$Uci)dIFt|>QyD*F^xSlA<6treeLHBZ+>O>T#`1=W8%|#iPzs9#$Ywt zmY+R-ufXttBV+k~umI~TpVeCm4(;cUh~HnUdo0`gTEfaIPtlj-{qZuAh682O$!6f>s3$@VhH`tvCkDK>G+oqZgw7nG^ukQt)}_=gfNg0Gas1TRX%@y7Ol6t z##8gZut$a57mpEsFsUUsQfp`HF_@r_MRWZcuXJQEnqzb$iQ=3Qmy$yu-M zrKYFy_<0L!_dJ~5K?TsYW2oq|Kw{Te-kb9b7zZCGoa20RBtK4iOxne@UR*h!FscHq zp8FIOIn>P_ORNUxTh%y!KR*JbltqG!=B%Bkqj$ASr1hz`#_apyvhE+1pEdS{R!`Y; zGInDc6#lTV727>v=kMB2i#CTmQA-XgmbR-;>!8tqV+(svJea%kKS|hUnOpK9*=aY z+j*SYJD`xWW567-`n7PR8?X2upR&6EL{S_? z16e(WeU7F68%yb)+Xwki=hW_cdq3ZY!0n&eGUtdq;>%Nz?D47;nBMMAVn-3qN3unu zo5b$8){86WFFi|v@$ehqOlIAjdrd;zsB@l($x zVSRaCs{r}J1-`I!G&^6HE;lO-9JX29_}U24Kea8N@}h#j1^rIL%Az|2`|S4uskbPH zpLeZx*V|hhr{LQ}6I<6-mBg20d0XWSXwhH*v2&bnh2)J_Cy;h=tru6$-^ktIhtHFs z3u9d;cAkv*Rp)%Wig5J#WMC3-(su{F9azp=xO<^@g;`Q|8`yUan2k-7zZEkz+g4nmUl}rm1XU7WE>VXB=+Z--%lEBxSxM4t9IAh!;eM+-G#{% zQ+AAu=Q>E%i#PyuzicP>%|iKD4quf>?3`=8xN?5$@*&XAFbSAk2_^T#SpIwBHlFW9 z%G5dEp{D#&<{q%_y&vdM#;&&))I)1CE`5ZBpZ61v^|$YrU!Uy{nb1Y#nrgF1$OezZ}W1 zi4NhMYrVK~Ua{{ZION$B9`E|1PV9US;#ZyX6cyp<^GQrBIO`q>>>sjrKG*^6v8?VO z8)M3@$yjYom5(0a3oFO7dn~?Fd4c!2Q8W;_G=RAIs@;a!9+l){86WKj|G{ zxK9o^m{d3W=cx!wbcx->z694@lyDyXZm=}(Q8vHIx^|yq`Enk-i1-5 z-Yb#3-y;@8Mg@{Sfb$cP+;Hw*!U5NMapindg9MOfn+85!tef|}9?;-?zZ&Nomjr_Z zLwB$YvYb~Zp}o}KLBi=P!U)GjjvM9W6IVftpqb=4_s#{-W@((**R2PG)o5G(>z}}U zXY}lnrKJwR{`FzLbh%3=zidtIK9^cFCJ&T<_7Iwh?i0?j>}D$iqT82=otvV3EDvv5 zNjT?PFRq;H6w1Id{%7!QJ3E$OEdM=mv-5*UnYx{)t0^xSpA4qXjR%*k*>?`CH$Zc> zJCo?m%h`7hm_FGnUv=9XIy_}#x*xYY7q8zL*lTd#T!%*SX)p#u}ZOShVqVKCV_p#bBu@IGaC57E`M+ zoUqeD5bAM@Dn8zbaE|4qnI+(D2OYvW&c|~4i~GdRxz>v-=f{`a1hZb11CJJUb515x zgYyhE&WC@D0DnBgKtq3ak7bP`nyVGHq}uwkdn^+kWy-&A^M%E}>{@K>)qczudc64P z-b50^X%xMg0ayv$o6leY0!#nFh;(^T7Gs7)n$wB>uz!$%Stp zfbujyGN#~sEHAiug>cTbUR*ifRQU*Ox48ErUqDZX&}Q}*1<_x2`*6~)ftepQSd|6SYiVGGU) zE+XGvJ=K_SVXtc?&HQ$d-zT+p*Ir$=HiOG@ddQh2Qwhf&NUruO1^!;c$oP))y^;Ja zo_&8i*Lrc~{ON{kz!kkK{?|~wTJ`Ni$Br5Q3-OYL{tZC?@H3ku&_BGlic@3s4?n|+ z6TaTi^Agyelmzhi*mp}=*Yw`$lD@V$ zng0Rh;d;1P&sLPktU*?6)PIQwF7@|>+kpS6@HmEK6&@}~o`wG5q=^T$r*lC~c#QfP z2rvC^DLB-_p5SrnflGea$3WPk`Y^d3@@6RgTQ7sY|CVi!>D)#@-*-zv)*W`er~a2f z_{b$yV3!$B$St3<-z zKlpSY%ENje?qlGZuG@{On7U#`Nr|#uCVSzEM~RD*BEMddLjOJcdlp>~cEczuLAv+=!NUNG@+bcegnvxikp5z- zdq6hGq7A)X>3{m_hQl?FHYrT2yAXWY+WznVYxa*5NRLx09hc)!>X-1u7nXGF$$i?Hu8NPl)soi zNVcI7yKhwXa*!|)}N%vd4HnO` zm&4)kAba@m$QgpKR$!pQns}T<`qD46X(iGN{h`@jFMi3bkgRe1D4axbN7O+1|SLTqZXmldzk_%e&8;(99I z59Dx?-jfgr7fhH)>TA4uH2uVSg6*}vEWaWfU1;u(&ZXTcBK#lQ7YNg*x!7+1$iAQ8 z!us*@V^ad*@6!&X{I3Nas3rAA*~VwE<=u<~1<${(hbd;k|78sR?^tQ#frBO$9{4>m zf3uf^mNmy?zG%E$QC^?=r=cHd->r3x>C-50z{lm}dO<56ddi0tbO?$`aLw$OH&?W# zE-OAu+5XPeUd+ZMDL%cst?+NVfY=+>sZG+v15fHzc&tD&jzMtJ>>ul{$ZGT-!_hdZ zd*+es);Ck)A6MRZB=kXfIepl(*GCVS3g<-g^Uo{&A+s?6Oy6=&!J9sW;KMb3sq8u* z9Py4<7^g(k2_Co+Dm>OBc>@LmB~3i`pEt9u$zFb;w$FUBNvNOiMaF}IHlebqsO^t- zTp|9nc$AlH=-!fiKP4XY%Dzvh8=+XzB56Fq2B*SAku9utHhXTp#!}8(M+&bwW*lDTon2%)a zLvYf>qg`rIjpNJ4`+?}C_b=%ihhhkyKP@V#1oIFLsExlZj!% zd;MAyegj8_$?hNw1hmHO}QJ$ z_tRbs%6o)jmEmu!iTxa-H^}bX6b8D^#!U+kx1jdnu z*z|Z$o0;cNL^12j1*-`j@3$M;!rQCpa^w^6-_17|DMa5SfU4h;w8sd|OWxh$AE@p{pWQ`xpX1Q^O+n$+V{(_F~8pA2${RmUQ9dnfi1i1 z!F!#G2|ir=SC;T%K~Tr-@O!>bo#1f_wOxe=-tYX|czeJ8kQ(EU{Lg_<(%y}_GTM#U z`@B)}>CBgbP#mBj*IR#1rJgn@q&}lOjPt>&NSG)&rEr@uk@!=tq}e}o{~27Py>P`N^iPbUxZMEA3_b$zeYnPRW`%2E zyN(j5Z+M>IiFIg`H1Q}x%2aslL~^oHxh5XNecIQEM_VQkD(1S$Y{pp;SA5KHy-*L? z`hpZd`o~u@E4jUcm}*S3{bQx!P(@`UGaz}FLHdh3^2cAt^629;$|-znqwadt)Q5qv zc_#b2gu8}4q&o#yQ~YAK{O%Lm6}*fk&@FGN%JnO2{J(u@;&BG4QQ={Nv+>x5O`gJayZ;l9iMnmHO_Q!x@Xqcg{8pl|xyj8F zGEwzD62CRcJt3q~-laY^#Q$XIq~{MgVJ*v2`X8qTDTp2u!&q+|O=VU3@b4r!#Ik{*(=d9X#PTJ0X3MYFz#oJcN zqXE!Sip{$`bfRLCZxVig`a033C>A{ywuIP= zUzfM}e+Dd}%uqkVs_oO7fw;~cp?mfzay3mSP{N-`u5q3=NfVD^q)dfJ5|X6(a3- z3cEk_C+$BzDOq+JwP&S~g!K2+KC7qz?*LgP`W{jJ+!p>h=LMYuj1>6#Gx~0Mlf$x8 z`&*Ls&+B$ri2I!3nbQPck8Ul69`MYK%W7qJ5PVMIq$}uaWkD%~H_I3j^UlM(s&|UY`0+c4TEc+ZHHp z!)q z5OI0tr=6{ip@E`2d^5ol=V_BP@wkALsqmPMWIv^HO+4Cp1k{MfC$v@?Z@w?j*)9c-Y@35kJRQ!wG!rth6SheJ3Pusn|>(Oua-X;BMAnG?Bg83Bnq&aE- zr!foZ4xa+y-s3*xI%TmA&7}I#0If0M@~-ESYmL+8jC;j8jlFvd*WCIy3yh*%jxp}y3>CIsNabEc}|()&p4BMI$CMLjt}=lGhF?_2lCq9&sGVDnb~q<`oeccY?q1<L0)PHRXx5*ulm2m84Ue5j#x{eKX8$;Qy`V-sqOt?wYm*Vwh9%Gzm-}81&zbyV5Q zdL&!oN~5HShrW|pjq%4oWCy3srV0l(T0!h(-;yaZSCp4<%AWWSkg-B$|7ECfsM22g z7KIiRn>B!EFB~O!;Qa<52$F@rdwUY!*NGn_T#I52-42ZIY%xEkVjucyvKB_Nh2&_K%K*S8I&NB#2*0i)cYepbzOE>oUUgo1-<2 zufjpZUOb2S%6|18MD0?>Q&}g6!%8NP7w#eh4S$Pp8e%nifL~p$2zr1n)Y%7DO2Hru~?*3u8GIm{f}$h zf8p95i_Amdc;^^=2$#oN5qq;dJDQ%{22dVK ze;U~#5^ikR8|wf1TA&RMsoxQYDyC0_v4Y@vzOgN}A7Pa3xSW*V&}6MJFm@Rgtt_8-IayJD zWI9}9^oW$#0t!-86OY>{SA_@eA0w1E(8MEQ*`^xpg=_yX{dhu==i65COgfqHeHX>% zE(N;uxq}9zf1KaZoGL&V9cuKQ^pARZ?dV*uFS5DH@k!F`AGzH zxN0gX@42{Cc&qtTT4itkA?P`Wr+Jj&=?sN7IH<~M;&B)KL4^k%Z)sEJ1hMc*3z z2iNgdw_iAn%NhtnCm4|S%thFJTD*$N+%}rTD-|PF(PNPRnX|=&##Nc&;hmr0YC=6i zF&@4a*&UI09e)NU{%Thzc-%wxP~m~s3YX%WqNIsO)A56Aj8AnCmu-!{$SgXHCiNFJ z_#o6nYZ?~MR+4Mer(>w?GgnZDl;gwG(n4q`&n$45g5L3q(soq-pB6^+j@i9Pe=w>x zrgYGEi*9Tt<(D1oL4Vr4g$nz`;&G@=DqJ=)0{UmqA?2|SZIWjHxQ~>n@W8%fqEfjg z9?}s~x~B1#tNq(_wuAa}`$JxFG3gJ7Q2%(~a#!ecW*WgGUUFYXqcQ9DvOPjvl~sai z^w()=vatv^d~JHVrNYy_6Da9`;`Uldns}5Uohm#gBRNxf4^2FJ07Fqtc_KuzrE*O?;_F+~xcu%;|)Rm87p@-6+ znqCQmd98av9&?TKKl~kSk|rLHkTMk>jgTCmRIZ7K)6Ky(_K&tGuIRNzLF>*IlKw68 zRZvgv212-ujn_vv8<7tuU!*T65pt#e1v4L#< z19m@Z`&=`jIl?2mEQRpj+z?O(?f1~HmGPY9iI3d=L!6@g*y}p+ACFNRRQ+QGk~iT- zp`_VAzVpA;XfL*?o$p@y$UfZ}M%q8Whqv%I>f5_d>Jxqs)pHOw3e~5&qcH>P?csP= z@%?3KftwZkZlCTb7LDtBi9uxT3J<&=h39lQY2tC~Tu_bnvimZM&7)0i%L?8Rds#HhRGt|S z2;aYTBK~ovMQ2&{F(=!%nQVK&md(&?-gbp#AG?0h9^u4gK4`Y$ImlfkQ>47{s+0cl z6t!K2M>iy6pNf+v9><3qt8xBfi2BEfD~E-S@4riNx$fr=%XCrR$J+-;e6f1vFaC|7 z1NoIodvT*;f%#b{Siqbm{BrfjjPPE;^ng_`onqgWhVQ9O((E74kTMk>*j{=mm22XW z{rysn{)4N%I66L6R0hv3pg<78W5m8dc&GhX+ltJk#J)O>agi7MqL^fUSJJ=ICOJ{N z26wlOIinnJJ6J;cl#jx-0eWVn7Lq0&&yh|Q9!W@^ro4wH9$VV2uW`P=`ZYRV{BSK5 zGvoki&x#0tx;?V>dar_r{re0$NbQ~=q5nbiSgbnzY=9y(APMMSXU}h}MB}Ywj4gd9 zsS)|U@ee-r8|~l5IG!ihovfPCqc;@OI_N&Qe2S$Vm{}YPMNJ3S$@uaD-9v@P3?#?m zo1&zNhvEI2pMT-H{!#JhxWf7B+k*1Ae@Hxa5!sQGse$lBaX1;D-Uqam8DO8%tsTMR zVo;Rek6}9+&l^d_x?6(06STtl(8D_MA1~2ORCrh-c@(+n|1Tcb`?smlpMFN|@f%T; zC%U_vv?r5!YNLb3P~(#$Nqg2D-HqPAJCgo|#u2PKC3YDQ?VSgAWnLlIlh9Z+EV(Cb zU)i6GPw-JsY62?HJSrCA?^l)d7LGY}UKWPp6nyP=TBo4zkQ7+?b4;D!QGxEE!ecFx z+u)m`q}e}=0&c*X<}U&0yu%m887j z!lvDEg}&*aIZOAv>0dDeGU)=eC-d$0bAs;-6Ia0lm*=us%Knj(a<*VXq!n}0cur_mS`PL8IUKFIP$ZkEW*6wkS_8`y095cm0BF>f4{PtIGL@ zc)hVAE87mZ&MqSTy#wkW^QXJgYgcrV;amS~NAkQTC4% z>0&u=Pc`KozKirX{2gtQCLV8)G8G~1VLwLY8A}YqAkl@$qFh%>L zIq!wb&B=J%a@ZBwnhniuGfP=}yX3z|kuuAsAUflBo!HA;H9Vq_Oe%#wHSyT`)3L_q z=bRp{gWWnZw$mE!ApEX4rI2?xyAEC+@Phb*eyJaYvo}7bXDio(v-WsF{q^rbWeIwQ z4yDJaFNH0a2uIe-B>f?9W}@uloj{oQx&^^w$@#-n|B-sOO)ju_L{EhqWjK><3p=V_s-%%58Y#{A*7jw6Psavv{NoJ^|)g#K4ke zA_e|?FEoz+m^CTi=FclZ`!DT{N%`1mhLl+=W7}A?u7JOPBp^m%pFRNc z+}YnO!Fk#wO*}p!Wh#4Fj^q_e<(hc33T|EFdeD&XfpF`up0v##iu8AnRo$rvXbc|z zbPBm%a2wFSt0vQUj~lBtjq3(e3Og568D|kZ_91&4;gl{dnm>t*Pm2oT`F&8V;?%>E z;B#TeBw^RCmeh5GJ1)QR^Lxec_uCb2`qxPOg7dUVns|Ih%2arGAvsv7ToaFH^CN5Q zANbiYgUcYIBkNS*~C@zD9O%bnS5N8liTeod6k@^lwcCqngDVmqWbxjaPUGO9J z^4dH>=8R+600*+(HbCYl?7D9%KU5jtX0;koa5mx)bm%^yPVo4O>ZrnFIg0DST>XcGbw7o}dqai$F-Ov#WYo@oc9rEPY+=uPj|(anD3JeXe#MmZmluA+WHC=o zsR)#Z@hrDo0J6e2DWVJNCSL!hfrl916eZ365o>2(WB=fahw~{N7%e{mJSHa-Jh;X$ z%vWz1y|l8x^E`XLh^_7a{=cTZd`GHO{bN3o|K?B4k44oOpN_kR&Jv!{k=L)!zR$(v zgN`jgG3#7C9_jy*d0Xfkt9u9)%JJn{bv0-x-4BaTULkmJ^`|9ah6Qee_uHn$y(8uS zcO=-7nt1$B!vn7+cTwIzvw!#noU3vEqLUN|pH7`&yE~gb-_Y^IEcxR3==|9D-Xwkq z8#|gRo!QT}GkWe2tF9bmq>#*c1a!LfC+%r~{6}%oBjNoS?0MdBs|T_iG{;-kC7syI zwsq@do!=awtsIn54wkX|Co($ijpQCUQI95IN$&OXnPZ| z8lU$M_@ELhNl3ONWKT#s=gbtzmJpIsvZX{qlCl(OLz1E_NtUAQ**fRUq=gWY>?He6 ze6w%w%>A6cZ}0i%x_-W1&voVa%sn&DJ)gPnd$#91=XdQR*VvneB56>CKlF|mlB$UNyu9x%CGO4vr7`1Nb34HUkKe<%x z<14GIijNKK|53`yRr&Zb;6aVgTL!W9$AR4sWuozSK!0b=>*5mvdmzq|i>AbtY&DiYB; z2HWVL@K9A&m5=XCP{l_>_Wz~IjH-N`s=r)Z)B4tD)lxkC=^RCfUIFmY=lL9I(rPxx za;pRT!S0Ll#bxKdo+wuCe~#>Zm>2~_p+dX``nw0?^Ks!1+0v+;P=4m+pW-Y&-p;)M z_A&eAcJbEii?TZ`A6IRraZehrA4YrEjs>h#_dkEA^6`V!RK*8>K8V{0zf}2n)uN=v z_%ZdyQfw0Ok7Ro2DhV%V;`d&@@iu$MT3_M$^}Z%i@~NTI@2PPaMrm@2N3x9Y2#LIUAj{Vvm8(nGpSNNz^jgLW$hhLpX zNyqQ6(O=BidW@2LveYaq;A5v|nb?Mnp~t=%15Pd$%R3%vD-U7oV9v8q?K>p@$$6~5 z3c>v0ch7IkqS{l9E<12!*5CPlRPAbf@b#PxSDIa__Hp-e=NkF=-Su4hq=s~dzCSez z9S(f_?tFdo&rlpvZw<-my!5ZwN1bYX@MkT->1*I)#>r+iK5w~@%@y*CTZ;XBN5gpV z_-rd#OP02A%?7|4S&lOQ;tjI*%JC&<^%XSJy)zZL3Hv2am@R#@Fqd>K6yCSBdX~A| zj-~B=E{r#7ojQmQmhKY2RhAE#a|2C%<%C72E`t5>zWbAlHJ^u!f8U3qR*esJmj0{w zap2AL8tr2e8#msQgL1zPZJ_;c+Z>dPWBb9Hxeq|!mkD+87& z<1-QZ_jlumS%D5NcDJH_FOU5d`%qWmgP%F@OVwYt4MsK2$9|U&qc59@NNPz+gN5hu zfA_q??CfY9t7A)bgERjM9~#y8aAiCM0~`OBk1?LNYTPfhWAh}>XS-#t58s1*%-p#{ z?8Izls{KB&k8^WB%L2acl{>OCYF@QRdkd5wvKFVD72db!&U{NJCtB7hE)mWv%=br$ z+dW;1$GY5<^Zd^o(yXFJ+>~UpG>%1{8j4e$+4s#9%;)}pxVW$IzpD2K)vd;dHcNL? z-b2+sX72vfucrCwb@tp&%9vf^&u`9w{&usHWLj+f(&c6-@R6{#Nb>z=h}>WK{m9sb zlc-VWNQLFopU}S-*}NnydYZ!gb6Xj|b&+hE^zc%)2YK*5l-FqPXZ0rVfjmp;Zz-wE zNo=e=Hd;OKukfK+jSp@cV}HTNqJv{=^q1f5->3UDv30Hj`DJ}W{8kohuXL6{JxS0x z;eDZXJ2a4cvv~TZc3t43bZ3A(!l0gf5X;B&SJ*7avG1hBC}Zkh@t1nl_~2Z$;WuTM zs(p;9(5i7h_Pgy7y}C^z3kTBJDXoAH{+w=!vxzLNSzWM?u6Z5BU75{Ad6WPj8JBB| zNBNYkdLZ*;i-fvCM>nvihvuT%OZv1!>uSAT>B6yub8!*Du8@ z?WjlY1GJ;|2FmOE(@T|)2G#g*WtHgIk2d;i_> zN%XL@B4k&tVuxPhU*SWm8Xp;q2OD7H|MH=yXsqTON zP_+;3YJ9X{wf6l5AFr-*FMA15(tI!)4E zIbNr?nMbXHMA##|<6q%Jry3tCS$p_emtU&>((GtfjqCk7tlukTBjxLlp9lTr)_o-B zXR+U8C=FNedJK$9C5!rmOIx@J@uM(cA=UKXhMesu03Xlqvc2cy@e-5VVkm$1P@LSJ z?WN7hYb)X9Z+9<|wCiIi4}T(*f9M>7M~-(QMjM3px$!)Ia;e%!!)ko+vxY6o%2oL& zxw){${jo;udl)%dZLIv)P|!c**y8L?Y%P23!6Lx#=2N+L&&BeAN`EP{?MX-8mg1=g zZbARnKFEFxr2igCj-`|I`>`zjh-Op!RTd|WlZc|S;T#dcgW zeiiVkRQErBsPds(jgMefD}UyJU#fhZH{My}{B$cDH+prH%9^RYg!$#-Tm8f~tS^T@ zxeNV0$o7NPfZKN^-pc;<%QC@*v3cnD+h;Id)?$A2s7ZIprDWlKGCe=`kk83y>%o6a z!M++D?m+@BTHwR7rzy4GrA-2-{GIo)HLAu3U*G=9U$zv_e{_A6&t1yix2@wU5-ZNj36e&c>Ip;CT7UpPRuy4(KOIzOePJ*@L%WA6vr` z=j9)!kCSov`HANx8<;J%Ni&1;x{bWW zwQvu~RTj6oTx1d_GrLnl%m)oM)b{*PiJ0wCuiUp8 z?B!FpA(Gv@x5);uG+uw}f;61cs0~f22>vVf(X1LDZQ1>PHNN0l;Wf@rf7jkquJ@yn z9yU1T$}zBy-yL6c$z@`e+=Dnz`aADaGN{G}f3}d%QTe6nFZq|I)wtg0zt3^TeV0{Z zCugvC^(h(IE0_<|aS^^xd(UN@_@WPzSSrVdQ;knjqiIxX-E21W@9)lUQzq?3Pa~}9 z(=gq?Vjs<`@xjk47XusrmybGM9@RJ>>w2A?UB`ctOpO-KD|;;ZBKN+<&g^$h0RI`< zDoWnJyAh+0o9V4pQP7^PY`lHAt60*;Q;wY+~%sSi#|w=c6FelY=7`KrMmz5 zLzRyf)%f7&x4(LxZf1afjqxL&o#nfqpC#Qux&a?420jX@IeX`e_e5Bas5hA;(TJR& z$k`~gr#RgO``Im{mN|~lzrQo%8g8pZ`pRvY;v-Evxat4fI$3(oy?G zjqyWP%6`uxTqGT&y&m{T`dLfSzl1%%?zs){_j|FD+B&-=gO&T^h2ui8q(Vf^rliAs z>UaI6y!0(PutgnPd-Cr{{Q0HIN2_XlaNAg;yoIX2(59s|^6|U<8=`%md`ewTMaf<; zf8ftD5AxNNOiW)b;kSO_p)UW)o|l^6TXMuss_-Mu|=VJ`NRPCc=lyQywV_xj+DJ3mTVzWh~ zA1}9TZJ4~6jklfUuYezPxn*|g{#WoDN?dNa%oytq%cp~%QE1Qaj!*t|8_;jFk5k*J zd4GkEw$=FH=P$pqkDuR`)VO~6&YrVUF2E^25B(?mh{Z{yygV4~Ta^U$@jCzHQne4`YJ7OJihsq&zJ7IT zj32kov%U0%1`5law!lZ{!Of+g*>7G&+H?y{e|~y^WVx1m7L6uCqH5S)#tR# zim#8a%on~tvg<)D@wM4|B|Vhu{i1vMC~@3Lnln%X#%raz|M^4JK1{0dF_6{TN?Efi zA9e1WuQ8r(W6y;hU$C&B=Q`ne+NRySvd6GF{6>Er;Ky@Dq9ksqj`T~Bz(@Q+Eov64 zhkIvcfd4N%#m+0=X+i!)bF<|!C)x975e8DOinq3|^tpKx#oG*_yn$y3wQk%F z7mH(|yi(o&{GrN6`)YiQV6~1{)~w3M^w%ym&Of%lV(+&-lqmOZFdO{E>qxxh;iaY6 z$5#W|GvINcyx|CS#W8lK!mGA!zZ%VL7LBdtsnEZUOPAuyS3DKE&+bC`PG7yGqoSAM z6L*F0XLi1NResT7m*gK7qd~O@6C`S&P*g0o{VRNQP~oHAFZk$xE3L+O`n!CDbUjP* zKU?Bhi&4-XIXkata9k!?usIX_WyJ}ZypW~!S+5CLEXuIz6QFBV_513gCFasBwN^B1 zZGC|srN005L)AVyR^wwKtCZUazf|obtnz)0@$@$H|8JcJomjtG1Ljj@ryTn6J%D}% z(;1=t!-L+kB3Cuw!_ls%xHns?EZlYr#+TZi>WTL!+>(q?u3!9e z#?r{|w%Frt4EW2j;-xs_eO;+~AL0FLD@64amdv+KADIZ{2TWThd9mADlFe*}x7*s> z92IMbXwKsXeTOjzx*nG1YL5i(LVARA3ks9SxwAq5BAXb^UQ1yHoojQ(FNL* zHnoH7;r=d?p342tif!!oJe#^=Ba6p~x9@l3M|pHZY@}X`hPXySeByQd$)#!^ovZP& zl~w$!@9$UYRMr?zOW1zS-~ksTdwO|-eOz5}K|Yq*!dzbi;KMfGN!g7Te~~%fbxpImn0u_woA6NeOlh`5NjML zmPMBCm6R&?$GVPA#s}_CClwajl()~8o$J1_vX%QqT!j3$0!<~y*m?Nuwh=J?nnYib z3|h&~!zT!Qq-5lgu0b8?%c;Ilp4agwm#Teqt;PrUmtV!xxCNtY9AEhFI(6_{YPCSE zE%0GFJTUtso3C&0+y~ls@Mv4vF{3_`B9_MWuH2PFt#8-IrrSLM2e9!v%_B)}=-?;e z^5Jd?5*Zt>D_0BSwTDHJyvRpgu}(Q&myg?r%HN$uMsq`0a~uax|wb#rM6JNE6&XL;E%6%vK!IT!M9M?t*`Z&u=ERY*74g{7D$4Ixj_8bbgDq^%VNqq zQypke)-rps|Llg6F6|_6mXMkf$XNf0Gc_F@6#pk(EBxFKcYQ3x+;xVt|PcBvaFssG~ zSD1gtfnTb81iQYgaXt5i&nx;S%0FG(2z+GU+AR6Ne0}M&k6<76?bgftp8X;jcvaxz zX?#OGb(RYb^sf#4ShKysR+6{kv};44{HC=ZWIoJ3)Yc2{|6JT}u)K8>7x{3dzZeu} z(5bb8apZg<{s`Ls_kUIS=vj>qzP@dstXh?idmkRvIKE`DwO7hHJxMFl9mWIW54!Sh ztS?;#3BNzN>1uarzFQkvW99nx_N~SAfYE&v_EKZuc8UbDA{8$IXTB-}YyDug}+( zm^#{lf27ZAD34@y8h7pi{OY{vCa!PWLrRt9pEiufx7$ynMt4U26@TefjgPI2vW~y7 z50l%|YJ47svhniE0xB6hPI#Y5BKv*9!)*U_-R=6&-}i^QoyUPU3mSk^$qc03QV>+sO%!vHHUKcBsQ8@x`{oBq_{hxN3gSuA{Kgrqs;a zg(_A3qYqX4=v|GEHmv4e%Gy=^W$LDtHO5mTHvb5XjFwgY><{hv{&AJqoQ*FXoQokI z_&yMe2hS~*FK21I>aJ7RydkoXm>p~jIB?ujeA78bI;qDR$gj6#jbcqd_Kru>`ViVv zn=O#fxul~w$ksW$yxFX7RCoL(Qa(Bl_~dDSa;fssry3tTcKpg;W+tT77(aHhe(Np| z5{G*T{_o}BEBndfVd(ei&^{uaAc^QQT^^%6uRKuv7)?g&u+jWY(4JGwZjzdO5!>G% z27ETK`5}AEzU#m7jv4riQ8Np%$9psB8nzF|+g;eLHcs(biVV7X(m&y$s;nv>7S;H0 zW0@u@GpgE03$+n8NO2f{^W`V7lDt!m!#j(xQp^irG13V z*{Voa??un*9)$L!++K?99zT$*HC`j+>}Zl3cnAcRQErBsPfUb8Xx@G^OR>S);hsmpv0k8-V{G_xG2(P103- zz9{r>;x=bm{2>Xg%6tvu!v_|7xA$-tN2M2neGFscj34v2o3DiT?JUqbBe}hOu3S&~ z{zI>^LvditMIxCd?9U6@{`Y@X?W12cKKT5DuVMJ5%EvgrnxE&l{ir}j-)3NQbzO)D zl?#iA=tG7?XZsB3ztm(W+UM?Bl)0Be`~4hTQF*v0%33rS>?5@x6Mfh^6X&e3fbvb3 zu)Ur-5t29$Hz;3HHjMVL$U{FSRY3V2z3ga3>tm$->eY~6(DuLotICH}H9lssYUe1c zR^=nzZ*PtMl6ieM@_RZPPnF*Re;=ViiKuOn|OEErpL?{2TIrbl~+Eu-t0wuNC{Ns;7;z z1~E&hO0#ja8E?h&5{1mY;to}Be>__PRFHBQq|~E*Nq?-JqlN(h1I2{ z(E>KVb&|yXEFdDhMZwkT^z{K*G*X*hy}b$Y`&Vkw=O%UODv^-i;D!lJ-g=+(JjZ^o zi(O}XPNl7129PgfdVpW`X*Q9*9%+PdHO7JVcuYnzsJ$E(BED9CCr`j z@;A1uqFV=Smf{w|yl-7v6kYgzn{-aZG?2G<#Wa1v1;vK^#ef4o)ur3cjwByFq5+3F z&m*;mMiBe`34k^Ai=@%-(umxCJK)emu_(Yfl~_8a1Jv7Ki=&K9J|N z#~{yqm4pvjB}fLY>kgR2g<`)u+0v5AaOgj)OjkVHU8XQ~72UFs_&tRMH6;F`ND#)WXJl}c$91wV5hSIwAjcQL`TJ>$ zXoJRkky(H>)MqxeLNdCu5qmFeE5JchmnzyV=#IZ0d^)(YqLodmf{JlWf9 z6LLA)4e-a@^~9soQM9YGfd5$=M;g5Lz}xBx&y#L%+zws!Gs5KowIP4gyjapaI}ppy z3-3?KTC<+mkoovTi8jb}z9f?mr~UDnI$D5RhVDjBhP&d+jfM6)%*sVantVe}wS@O! z9(ZsZi8WlY|FmtO?=s`lXlj!y=*~ugf5*g7g5~va*s#Hv_ebHeAhN%k4i4Ej9B}cv zK+<_=eXQ1a6yQC+o5|_GCG`6HzKG|qzhxGhCNig%8tNbq8}Ui1vp|IB%<}`>Y(*I9 zK2HPhZa4^VmECKyvNhSg4YL)c8G-%q@rb8Y+5Iuw0Ib)pl_JeA8t(t>@mc8!5{U2Q zyF&Y#4PQn!UH3(82MG6n6)_ZrbZy4wFKfUr`m?%J?VhLoFLtkL8&!5cK&ddVgJ0b4 z&6wTubZ+-NJ;py?dgXEgy0BS@pGK2q@(c22xU8}8ob~qgACPNS6Kq1aLAxgGe=i-~ zF9B5;@1eZT+9NLz|GlxuXxk>har<79Z4D#Qvjic&6i@$7-rX)kEe{Iw)Y{!A(%LC% z=;hpC$nRhhLd$3CODhY7@#4Pv3|d%6CQZ|R2)sSHJC~O0ZIJHk?+y85Qq1Vk`bp?T zobbIX&*jDBS-oc{tZN|V`osj7&?DdC(VN^AfF)QO>aWfCJmer9XPK!viL> z{VI0p-;^RZhtBxuXyJE$MK9{&sW(jUsX9$T?h()Cn8&)}!81nyo-|$``))PH57!I) z^j+tO@7PzMZx$VZpZy-qu*vZr=);#Z%Ik0cZ4}Nes6^#Q+4(-ZY$S&Gi-j5L)_OO{ z&pwtQxlo!k5Ci`V$io z{`_SDnQ=;3H-}BQik`-fqPE>fK>khc5lHvJWa2+l;3v|wlzd6(LY~ZzhW5N}pox9I zYtf49^#GrUYKt>(I+5PTgy&>arkp_`AD+lpJoE;6m7mmSZK=smY?*B-&F)`6;b~QV zk}?tF-f2(KL(NZw^U?EUHI%h$o+gUNF{|V} z|3Frks-N(*|HV&KZMn)%?34;u?V)i$@ne3%)48AUbdU0E`C>a~T9!GTay>lW#mgRh zIMKTIg?Ws~ycX&(z?CKyB9QNNQj>ZOTR?9XHv*jN@JXTFERc@zcymS%Uc1$=#feZ0!qine5P9e)2)C8KfBi)X~3aV(6R zx&1og~VKblW(jVSEKyDZ@0sHJ2MC!Rd0vyw6 zHMY+3RvaJo9pcd{`9NG29!Wah5c(zLk{+J?uqAykTZotK3+iHhwZ2q7yeH=OODuSY z+;+RtoF{_a1ddKdcE-!;AwA)Fy0AM(kYnazYPd)EzGdSyf7IwoG=1GdnD-VR>MsAD z6-R5Y658vxk}7VGOQ0iXZG`p?>K96mUrV5K9fa}WfYC%ni~gC|Tq-<2P*OG#+qRM5 z9J@d<*Qcy;0v>HA!a37&0gnoIz&{l&u|v{1sL#k+m&DIMf|ptdzo*c$OR}O*>>-?Z z;XSn9r)y^#QQrZT70iS7SxmH`wc9twa+x0V-}d+6)Yi(8Xvzisr+M1ZmNQ?VrdwNr z+#f|!7dv+{!@VK!JNRiC8F}EW%xjqt|Lwliqia6-)3s@>Kp)HdZKd(|C)4+NWstwh z&$L)uYVxx|%r=!~`>&tzv?@PKUuK0vw%jELn$`vV)8BT-0j6p=v7;L3=jUjxFin!+ z=LfoiJm|`7v}5RC`JAG;pwD1dm#UxfwExA=RDGe!&xR-!Hsl?|F79V3ERCmgKjY~W z4lO0IJ)2UO&%!yx#~$NJW#4Ah0txXv_{KD{=FAWB$t4{0?$~`cxv-%bMYRR_I)jwN5B+ZSPGCir$llV}$(mJoQl4^p7ZKz&a@ZBwK`L)cb(U8zlf9_V%Up?Da3G z=dd`ym5s(JL}l;Ll*6fjBSo5Wukza>rQE?`{KqoT&Ro>NO&Yat<5a0R{JGcb*ww!r&CNx&pWP)Z=EV3jtygVsoEt^`(Nx*wePCz(q5@BuY+Gz^CX_m z?UJXLE1c+(3mK$q=>pJe*?do$9(a}9uMp;^Eqiss!3VdK5g8w#U6pTA$@39gNwT{W z+br^ z6KPq}bBV)OVII|gcLEW`*CHiu!n|wJ{0;PBd=nDeNDTGo4=hwn4L2bDA36gz=)I1H zeM%#i;X?cz)DNLm@_wY?#Ym9v=x>Z8ohOm&Hr9aGo*s^K@}`sGNGrfzWD73!wIeHb z3w9~)aSEHX=tx>Sej&U)&%WQoI=DK5PfEgM7v zJ|A%h`@Q`s8TooF;^n70s#)h)osfo&Fvm$ao*Zje6ES*c=87+}*u~pB;`2dtzPTD*KSQuT-`%^Ux0i(=jWTV>@4)I(^%I`< zzxau2UsUnNNHj-1#Y-?+C5KYqIq*T(Le3@cY(- z@t##Nxa;IZ!rQYhB9%_tn~e7y3<3G_)q`=gOAOx8kG)@xUDG!%qhGGA!4J1t0-jPf z0=xRJ#6|Va0M4{>#dXm_TpTi(^88LarsJtCmtx6EVV&Q5nKSm#!SMc6MxXHJn74{h+=>;8~GGspn{?9&Uk*)PZkkM$y_UK-%3 zE!Kj()Z>9PtYQp$IzI=n!el?v+`Syx_c{&u!jT!s&uW??f6ryW*X?bk#y>WpZ6A&U zwo5vO8Xby5`d117KWiF_D@58f^1cn`?Xhqggbg<&l6v{a0SCX)q1nkPw0Tou9{R$_ z3C(C(NG-Yw`x4jg#?V*Kt!VvP3gGj*$ufF8D3V?qvm0>Jg5}gUIg;isx(fJOD^saq z6s39cNVtEMAM3Gu*W|||ne8jx;$J`JX;prF{eE3s`m`<1o1qK(_Ab?@Ije0jd65MD z)#Oeq>gd~*=$F}o{Nsjhiso7CQ01g%pwB2)m#QE0wExAARei0>j~$f?TXRC$#r>Gy zgr{>qwq}1G@@VP6QLV6}!xP}asFSZW%vK-UO%iZQehhL^d`~Mq%loL` zil=}ReAm)%3s$07<7E&J%?i|{Io8hDGCL3CA+=&<+Lh(V%0|eqqqTt^DvKn6!j{G z3~|uHN7S;HFi$#a(Hh%kJ*2M#n?wFj?vbe3{`+*_jtPLX_mrd0+2!4fouLJL)_}Z1)=B#IS{i*W8Uyllg*_cmwv{@mIe|RnS!YF5avb#^ z7ADBQ+f(NgTd97~7?3Zz_(Gv`Z5XX{B@N_{kGs<5qu0}o)0{zWY8*pP1PrBtYlJv* zsbef{pEiK{KNaFmK>MB4UKT@c`xHa|`a9EU)_gl+l2;BmN-K^2SnQ4}uo~v={b8|( zR(267<~FMXcwOmkYT~JmI=<5eT#~z;`Zh~LQ`Cg>I9;Pi`qKsDNtOjrpMB^Y`uY1n zJhgK@z~4SErz?U-;HS1ZfYUzoq0ht{u(#Pwz%R>M(`yel;O#S`0K1iTqmIuv;dx7i z^^yImBr;~X0#A(<_Py&3vL~xNCo6GJ>IDQ@fE2K1}Ey^5q2Q=D^Nz%QC? zm429h3eP;J1@eDd+(aYW7UM0V)lfdwe*-$OqY#J8afIg=;&;?V3+kT1XZEQ>{=mwi z==#V!Ty|~-;rwjgt&YxEAHh3gege+c+YE;8GRVA$xLfxy(mv!e(nI^kty40=b3M% z<`aZ@_h88YbmHfBns19iUKRKBSzR^7z0oXID8tCVagV1}#XYnv7@x?`kc`Zgf_@!# znoCNDEW)iObpw9(>_DW2S67sKUYJiOZIhCB!=H!~-vomHk70GG#yy_)zr;ON+pmgy zW0eZ?b4PyhxEI3Gcsh@JJbj6-Hc^XcKnI?wOL?9pHw%fc!FLj%c^vev^|(@T(*7NJ zu|)9eW!}T+u!-YIl6hZ{o2P~;5~i;uL36u6`C*?O>4TlONTX4i5LYxl^{0C2%N1j6 z>>>YwaT@6A{`1m(hlfJ`K3%)hL34JYB_{$w{&{;3bS40yEPr9Y&sfwKbvoG(IrbFd zhR)tTXsFpx^iE?ml<$AUi28qfkLos_0Obn~ZYDe{AVSE~&6Q!7+J_w61enq_f-r`2I$N8Q(pad_I-Wv_$iCg0n2F6_gi=> z>6PM*{ay*{q}=aTD0%xX)F*Tn+;8L9XvL>S@ro|3nnC_?tS(i%<7xkk-GPGD{;9G% zXQjeb->Knx`!R##>D=ykdbiT1)WG~2^%x<%5BG;{8=ScR6n$_+Sohm)-$f2~zD18r zy9fPpcU@Du%IX>|UsfdNw~TThM7Iw=Nh9@cLpwrywNlV=C=NUR`rhw1QFv61^&eAbE1iY$q8~i-%3~k*S=_6M<1k~%Y=O%vyEAbeSI&` z?q$Nh_Ph(16nRZ9(%Z??A^$4LEu!3?ZT|Dk2UJ^AQuz`m@UTAj}_nsomceGwyR@92Rioe(h){kquYc0-V|55V&w%K@JR6M^C`nfuhTd1{BshJA23`Y@SU zcb0`x_XSea-`EVWov{`B4%2SMvwsc%e)%zy8m;Ui*R5v-ct)2fnsvxa5kB7} z^yZf=a`l@qZ-1T=PL9quq+=o`gM7iL88oRtllH$?3-F1ijp@vsKx*bMyw|Um(+;9n zH)(uctvTUk{_7%q9YUKW-!09GgT-@=OSCpY?+$(g7_}X?l!4;7?8ZDu%Fk z>5L3Y1l%yd4O!ILNDCjjLHUw__fhJQ`Lv(+OW>opWn(;g{wR8Ws<1EB+M*wJIHFC% zi&lbu(e0h_(gz1fdNU!;`Q*&RSAQfZKGaVH`D2X`EHCPYL~Dfn2JDQyvablg+t?N4 zi*!S9IyazXzE+X~4Zx(q*U;s)cwvN=Db%iQiEt;sJ5&;QS?SoysGJ8W^f2(XQ0 z3?f})h*=gJ=h@Yr&C4D7Ov8_7HG%qOZ0t(!&zOp1d$b2!YrWF>_H`R1A4B*cbflXoiM7 zFuXOgFy9IHcVl&_`Wa9A6F+lTDs09TU>Db$I~Y&re#X;>)RCiarUvMi>;mXDca0V9 z`fVe++a?p*arTe_`8IMZI;VXRB0od&79ICry z6$&XTfp+WNw5R8@wxaloc2Iuv`e@=bf6v8=(*Y-w4RBt~jvOEWJ(bvlgvmF`e$&F&bBQIT0eAG`vNux^u zTbJ!dh2J_N(WE^tr zxYbbdQge@#bGYKe%dM@R4+dQ*+^`Yo*Kk`gk+Vt0(NpV#@ovek;%Jl0biZIjMQ6YO_zB51MM{yk0g6j zy3lNou^@kU*qiJQ>P+u#7uE?sPYx%UUR`O{QUR}(9Ys$fhLL@J!y$iqVK}j$berVO zT>*G;dSfIX(vrAcTnl(iVr?qvxE|HHDg&JVNe{`@Tav9q1p8=z>m4Zw=tIYz6`tp< z@_X*bHTnHS<||4!`geTgX;pqd*j$RGX6@!J zrayJYynpY8{ZQ1ts*rCT+Z}Q2!Rk`=d!F_uem_a6u&Uql^eVp})qE>*zSR>s<{br| z3fwoM{M|!P$gV8FB57Y~piE4>{B8i&r5DJ7LyOU()N;V<)wd$Ki8;C;6Uz5~vK47L zc1O?ckAeKM%Mko_SO_}ySeW;{d4%!(E}>|NiQv~7=j!6fR$Eb}!)nZVi2i3A)@^W7 zsy}@O;DWD_IK9~@)Nb%Zz#R_l#ny+#(yzNF0}c;Pz^1jtsB)SxZ?SKjgDuk*Nqf%_ z_H_(`4`7d69rR?Q5Qjblu=#o3Xvs`9wkhioMQj`o6_ODG>UzCQuHzm5w+1iL*6@ELV6+zuds}I7yqxIR9;-{L3JTtum^6hG0 zNM*g5NO$u?z|oIB5&!r}sNQS=i}t8Vw3uw>xdb~Pq8ovg$ZuJQAH)uSDJfBmJ zMjqXa`Tbt&4kw#u7NDa6+W_bM<3h@EFCmLf$$;76G&$x}ga)1z^7mx#zl&~BfWpSE z2YDB~;Ph zxZgkT_M@kf>GC(@{osDhGmc50o$aaE=kpTmX9}xJ)$e)QpZNV$rNYL%!`Q{gdn0!4 z#nZXp^YlK(D{*SwyNWe;>VjVDudKw6>z-Fku+RXk-fAO0H{rbE>4$V^N66t#*efAh zaedGRz{%GmaPDmOU5Nl;z1e8ZWURm7CCM}q;%S?#WjLa9E@`>S!5Zv*7df3uLrwH}CntQZ3K zzc_3@{pa;ye6y2q4)|cmLi+ap5F9`{fZXiOHk7e%99Fv|oST%6xF_F?S7MDy;e8M# zmo4y+B11f27@L!@t6;_iJmSa)Wbt4<+<&xjG<#q3V02;WTfi+xTt(0JT}QocHK#nk z+uRAIfXDjV0+Lx+_+xF9W&g`MQ2Vaon_ zC4s)TVtnY?QL9joyO#ln{A@@+Z+=76?h5k<&8>0LB`)X5h&qm#xA(%~auTi`Ml!8K z055ufk4zqAO*9>s0FF{`LVvtliEK}f1l%;T7Sc(1kGk4-102$^K3Zb-5!nst3b@K| zc#N&dZ@ieTDb4WT@r0*U`OT?^BeC1dv*`7_YruzVt5}l1%nP>*PlonvwyA|ZeCm;= zLtNl~ZJsTYuDoH64vpCe`Mp_Ps(!=M{={!)C>7@4tK%2<_gLmIJe~UuPaiOEC-(aA zQW4Uj1;pQ`9t*M9B#!L=o1?AOthU4?$YsmHK=}`Z}s5E@_$R|ZkgA3r7|5Pr*Mo+eo)R=sb z52_c6CvD$O)GUN~){)euxW3~WV%_d4$WL@wgp10Y$i^%Imo&1+$4B->KJPAo{Llr2 zx1Cyp0*9Ojyes|rsGed!NKkEfn&mYOBCQQDH<>W2ZwA2xsg_e;#z+f zeB$aBzzf=I(lyQ=*tkasU}|kZJ!?fwhvyG7T!i%ix0@YF=Qiw$n?}|Lym6vEed+i?Qks&Ad4JvTNTZwk>_s61gMlAC z?JacSPIY|ynBdpG*R!bW&57jacq_>7IXjcB_s0{WF3hW9$_~?2p`*wbubv>U(=drz z6%HUz(}d>=+i2{i>19Wyk4Fp70nR%eO0&D0l9J22Ab*z^i)e^XTk?8d8eko4Ne@_- zODe}50vwaym2N&dMCvk4*q;v3??Buig`yp~1mvQm#xlPb$;f?jE?^^*^C-LVNwjlj z9^mH|J#f?JSCMB%KHz3He)vcEIpmy}1Ni2I?byyzhW35U2E2S_Dqi!HqOZO(z{!ez zcwPNev|?%|;JmUTT>rZz+s}vqe9-MGzTa%E)W2{BV5dPx@W=Cs3ayn0?A^Zgb-c$R zR=W1GC&&YL{*=CU)S}h?`U zSsB9k-n-Tl5_oC~HNPO7-&VyTKBm(wE6~T~ zOd|3(_QBcL!XVBBy{=C?G(UydmITO43f;)&aWZMX%Np31oyqD_jYB-`PvX!lrNSLJ z0qo*&$b*gFJe|iOo}Qwggp=4Axv&0a;92v;d^D^@Evzx|I_O=V*bkX?pN1u|>^WI> zjSOP%DL>O6rw+-3{JMt6@Zj1Tk*?Mhz!qsIu(XaTGP`U7*skGBWL^J&B>z!o=!e!C z1PAZ*M*8N$a}J)D)A0+xS|pI2OY-_%9;0L z$JA*}+Z@^k@^Wh@9JgW+&Hr>1utR{M=+M`Pi@l?$EC} zV3(Awq`XgOoRri6@OPWnlgw&S48 z?$a2$zh4Kys~y(T@&GZ-yHFeOyWv}D^go`c>p@|@aAV^p+TN`NHE4DX^brM*r>9qJ z#F}Xj0KXr&8uzkMM{6^MbEPW3;Vj_i_(tM zdIG-&uWHjfldZAU#4CjB@ARn>T`BK?leRPkeb>51p_p^8CBfNN5Qk^8x>Ws&r~Qdv z`6(6Va~6Jaz4>~Pr*psJ=_L#6Adkse@s8$Wtq0Gw!6ALU1E!0Njn z03O)Rgv{w5i32l)^+`qeN^$F$8MyaxV`#VMdl#~r{U)Zz(G{#oZU=R^wf1mllE2%e@7=eKcki4ZqY4 zy?r6r-9D{a#MXTtk{zB1`TuclMhi*}aeS7r-uzMgQE|p22TkrH`2CU-OOW3FHCS|b z9pU=kPHB!)ANb;%8=axOF~Oa&SKLu_*TWw0x26_&^WpY%;&|a)$4S=)PY!QLa}NuC zx#XZW4%jsXFN{lo{G$x=klWh2_??q5K2-UIDZ5uqeldsHlG4on9dCGAm0$R+48+&h zj*x_Z^#^@(Q(B-?gQQsdc}L)j?2w|yW4ls6J7M3)yiGsJH%CL1S=dp*+c%fhrRoJk~{08jeeo@ZScslnBp5ArS0xa3)fOdTL1UY?bBFMyX_^)IqIWrhpb;4DmHf%_9Kt~$dh{YSRvKjQVQ~-?h(?I zwe`^?bP;g<9%U%xyNx8o{|sQidW+HVkaLPTYPSH-d_I%Tjkh5k?h509XOSBnea?wU zMpl3wc5w8er-DsMX2Kr8OE-6-89FiKKo2Lv^%0$JM~iP7;-i~t0j@mP8H?W6k(<@u z2KC3Bh(L3PtRb4}1_ty}yzX6?Cw=RYE6>~#ByPdpZ^h+l+UklK)AW()17Sa5KC4UB zu6f#@*mZzXVXh;;xLxP4G@j1wnx~gu?u^GgSTFI&9|gRIzTc=AKRyE;ei#Bg`uAvz zW31;&1`c}(a+0lyubK|0908}O=?Wr_=|fCb@w8x_NXSDR>eX(|l1@wzv+X#}?CktIL2nBgp^&~WU}_n?=PEoBCWe%JjhrM`N@iI^_6M`sbAl6|1mMiwPYCBg|MM$_-q;BI zX{Hfivr#8VSo87N&H6Q9>xLUhapM4-8}Sve!$|(x?h-Yj{TrUt+jR|ds+zc z#@1>y_x)wL?57Oy*2Q&b?NWELn!T%t-|u;D5efLDN8J;S1Kyi_fcW2#(r?B>{tFs& z71|~7)Wx(M#wBq51%OQ?`gNrhC3B$bGiTS*bMGa(@)ml9IRHJ99byZi2*Esx*N zvx7S;Q^})ZZTWox5--l65b?iX8MIk(=?upP70l z5~2O5b~8CA%X!S0e->Zh{N#3^zCNFr-`s+H`+z3&Ykz_Sd{jriYuy9F?_4HpY~_%< z-RlKOZd)Z;%Tla_{hiiwo;2kUKz*<_O0dX`aA9f z*}ueHaI3-ELIeEPHV+cyLfi>*{aw)zGP{zSZ6=TXHlh7Su&95=9VR-+x8ARXV@rN; zBuN{Y&W#3zhuvw`6tTQ~jwxH4SWI3QbwvHZokQ7M{&@rWF`~ZYf)xu(C?r?oJD~nD z|K5@}tF%a{x46Efxo!fLwbdqF`91Hsid%ncwaaD zs3LK58AD>aIb!*)S^i|U!D~#Uvh9s}wIU66 zc=8#Nrz@_5dk@!!XRD&g%f?+ePOq|*Sa;t3cPcVWuxIhjesFhx1i9`eu6JhDdt04N zT1(cgR6_m9riI|-r$ox=2OP)seu3nd^mt;?y(j8ZpG<`nFC58-szUU;B&8*gGqwY9 zms6!e{kQ9sp}Mn=r2SR#I(|xGE>Y{Yno5NYL3^D&+@b2LJZ)^(744Hrm!LDuHiac>ua zL&E{8Z0L*aXWmIBzJpgl>Gftjo?eeO(wi2lT-PC@Uyt0F$E9spKvX?7QNNzA>uI{%fQi>i=1=QQf?fj$YEt_E@o zMV8WeDOn`11`h8}p*~eVfQ<{!B?X_RQQjP>Y26-E_n>@IIzJcnc?F$VWYrEb=Z$Ee zd;d(PvPFj5BzFbNo8&BH$*0SUm8=e6`9+dVtVqg<20s$lm7^A4V4Gz-upi5RWBHQx z5$w9b7`phWsDG`*v10ePbo6I2Zsk(T*yluPre!CdPimY#v6BOInD%p7+<(@%7Pgs> z4Zq{!d*iN_zhTq&>oRABQK%1oE>+?h@Qaqr9gKeFYV?~;P`yvneRGgqls>R|3J%nD zs(9a6Kk+g9;jl(xtpIO;%jsPm(*WLvEK=#JZk(N}luY?-TTmjR%=rxdIFh zlLCPQjkhu_u zeJp8?8O+bgLH@O=J&n@W0Pj$7UHOZdJs34*lFZ=QsP~w^z$&(=BP5Nwjcl;;l;q=z zZzM_QCi3)d13=U<n^>_Q(LDvyGs@`wZ&G z&M=3c!$z=f1M<+G;NR`Zu*f)i*C-M7XRcFbTK<$?aDR%&>-ja4o$k<`^&CNw+wz(T zZ|nccYax6tXiXD;@|qxP%WJ1phJlf47jUrufbBbW9YRe{*n`q@ab3hYeJH4eo}|T{ z`hd_MjRASo{pM~?VMY*^59RCnJFf|{f5~fMtp@iI8ss-2uPO5LWI-lJ79m;%yDJrsDZ6(PEBDAN~@Bl)m7>7=R3 ztnZ1>{l3$+CiP!e6Ge9~-2YQTsl@(@4lPsjMV@&lge<8pA%iu&k!Rf4MB)r@kv{GV zk^eI|NSu{s!-9R{b5KT2$B1M41_+iPjrz?wQN;O00vrtLgY0M5EV=(>DO>?@-f5oY zCHZ}M0@wzM*FT9rOsH(yJ@Vwgco6zv>fkVm&-{VJSvnRuVtF5GF#Q=(>KB82+2prm zs`C*^^vF15y5XL5XGeBNIvCFz4QC=H4fqOxj!jPEg!3=j-}A4g}f1#KERkgD3t!b~o^i2y!6~1o`AciA>unoc|W*4YYF) z90q0EOnRViIC6*c36Pg*&s0-HKXkm9!*q;#vhP3BP=B=ZGMG6qn)M%i1N-&Y>x;~x z+<{fQ+M|B>4r568wV%D4I~>P-?}uu(u9q`2He7?{XT?7uQ@0;rDt4VgFf(J|Beok% zSX2-3dT?dOg~WiyF~?)#`jCur5Yy>rL3+5n#rmx-7s4wKdlIaYfP5sstMyamee|ci zI8WX(U*3ANVuyd#z;#*=KMZ z-=3|2`%|LX)g9vbIqBOm`1mP>{pb`=1bgR9Nr&393>KVn4Ou;qUk?pB$i`ArJf8D6 zJwW5~K_=5}BJyClp3vjLPIgUBjI+I5$N{~`NZ!S`r@`DnV9tod3R|Mb$8GpH$FZ?PWK+eE|czDWxF!uZ%x~o+6Wt} zr<{$vhh(#_8G+PmRwA=h^+>r_@OCIO;EG9AuyL7g4QW z;`*^psXvom*qc zE^bRvKl-DrwNsKE$xs%5CpOAc)>=2tiGO$6VAOLrWUU?E*pq{GVqVS(mA9T3d5pVt zLyWib#{S@L5eDr$r-0CZ{ci3f`9Ds;)(+{&xxR$(4+22H^g3kKYuap5$8&IW!%@r^ zIh!I#VckXe-Let&+_g_EJfebLelCyWxwqFnc2seSr0d{^$Q30Ypq@)4E{fuMN?Tqx z=iBbZ|Fxz>sosJy{1(9r+GK5cU68fq^*pO-{B`3g$H!=PF6!Tg2CX%Q1p+m z3^`Vur$#nhpN#tQJtHKSIsRVYX#V}_{1(aA^>%q zd0mj-F0q7hUgo57(+DP%F}6Df6G{S!oR)aq;+Px*8G#aFt!#{Xkln_-Y6vm&5YJa% zM#)MpXX}#vHDgep9v;PJ(8ZFXC*t~RfJQ8H+UZN8eu(RE&wJe`r`@&^EAJBQ7oEK8 zWXFVIWU-Mg?tf7;k-3EykzBWF*e{zlC$e4-iiytL`&NQ|66>dAb7L%tdSrm(XtFz* z$rhB52OZmipx-q+neCBbB#TKSPuh6R3;Jl#GR*}iTS(|3&}JGs%wv9hLA`oL)N z&}$U3_1I+gWaoJjw_e=;qSOa+Y~5W+%TWpHfB24rqxW7)=DrcjXPuf4%ii@Nv3rN3 zewzL?uqgj5i6jold-}veZde$xE*IC~e)Kp1BO5ZvufPDbU*T2(=yuN_QeFq~_`Xc! zAZXTp68tn2`$s0Gh=1-OlQh`6Vt*LLo&g<;EhJP&Tql&xErR&&iKOM=VJzRi(Txr2 ze2ZRwppEtWPFc>n&sa#!w(mi{t{lcXYwn?0tG-Hv{z@s^z=D@vq`75Rv3*7Jbmh^i%ts1RC1qEKNCE zhW%>&wLN)pGLci1cV$AI^_fi&y{nKv2aA3Y!{4uQ_$0^P`sw3w8Z{SzO@=Z{Uh@q5 z#X2&d_;+olTR&Q$J|XiPP0|aefpMzH_Fw046Yrg(A$d;7@5c0FrczOy>+i+Lsx#u5 zYsyW@l{aEOF6py_83g4@lqZLx-n-XER{43pq@ss7Ukk23%yPTW;wl$RL4A7VH0DuO zRGhgb5VYBd^_ap1DlTqP>>wK>I!2O4)&;0$Qor zAGvzSRn}$PBiiBNHtfFx->HlQRcKnm^t4XV%m?ns z4VEj}eD!`bPaziBfd58zO~7`lroR!{(_|AdZ5mAOREhdekw(O~(S$4-vJ>@IjvpbU z^Q|JQmMz#`^YAdJw0kQ#b4B-e^NqFobKq%xg_6?F8|Qe?#y z8%g!PsZ0_z2Fs7wmqxv(`_NY}43V!p*s;TEYaw-NDIWK#;}$I7UND^X5_!-zLzc8R z3KZX8M*RY7XO?i#8}vi-k<zLu(vDiN|$2=k{2Lv(Q`U%Lo%Kf3C zVKyAOa1QHNyVOiOxyQpYl~cICQ?nyXoV0`Fj(UWgTfPNcmwhEK*#s=VanWY@EYBn* zhbc1Y90sXnWmeC_>X0MPNJB*5^Wu5adE!2=bCkk2vkMgIRj|AnccB-A=UAY7^EtQ%+=s8q#cS$|_bYK+eD4m1Ykb z#G0dqA?G%1WbOIi%{=tmgRJpkHQRq;02?{=75dq0x$W$kqYd@F+7tVwUAGC4JVA#1%79zb0i5Gp-&^Vt0$@*ReUitiog)+4*cb z>IYBDCYe`f@DFu1Vfzh|ELykx7rFnPpuS;15V2Ak3S}A{koV8;1e+_(AZ0Iy<()Q` zlh@}6IG%ore7W{9>3!D*ei`3K&XDT>m5nAa^0w$lLoUj}l#qe^d)%&}{*bc<$Oq`b z!Bp}71~uFVJ?{)5?j9FWe;}a%CXTSBeb0&YmCrc}{t6EyOJ<7qlV?9Z4XfU_r=L&O zVEGs4a^Tt92zq&!ct5;4J05}p4A`g*CsDudXA}hQvSJs?QpNH!nyFt+9!XN23&I#z zyD6|`u_U8Ag8x@$2s}k{yn}fX9vL}lMJ6hu9ioAH$Px8Spoqq6?M;`N71(sZ_ z<6hhn@5B9AvyY_I-yo~`_a6)OH+)+maU^o!?d8;;v97chO#HO)av$_%QeEw>U3O z;OqK3ZUouC#LbRYg9RIfO^BNkUM9$exDn)@s;k(K`I*#y$S~}eC^I?MQYg=^8xBH# zqFh794Cuv*ngH2wniu;UF9DiBslicr;hM&+^vKpU&^0541vDFRwMSfn!POBvMJdUP^4XhWw>R$ypP7 ztS{;AL^?Is1kx;eA{Q4n)7)>V#5j5+^8GLXr;_ocL`|G$ehllz`~oKuV{=Q?-#R}W z=6v^}d!M=>f9>PO8f7QZr?ah)kGq>gO=2!hoi2`(_Jv`fs-efGdW+}J?;#wG@0Cd0 zdn{r?pSm66-^H-1xmb4F9ppYs4-=(ibGm(74f3EPuI#<~RqCN!fqCRsY9#Z$5=$4| z?}~o0Fv5-*UJEC$bHupZ_(Yu*l(mqRORF(1t{Zk_EhD->bVd3BruThsJb z5t{^Ob z;bIqXkBcSU&BKs;bhcyL8aGkP3n4g8UvtBmY_2+4wA2*))jDjdWc>>h@?DWK;TXLZ zEF#et_;=Yae2h%Mp*D@pLrdANVOCNrq5W?ZoB|9_sh<@fzx|e$`xz%8NfRk@S824O$zy-N5?t*;vPYyEg9ixix#p}3)=o3IU*V6G9 z`e46LHgksAwSAfFp#qFIcJCsboHmuFa$oT{-={@GX?joAeu8)%8}zlB#P0NDJ41$} zep&rQnB32rS$m4}Vo$6l1^n-o&n5jLq8n1h|mq} z`jHU+eQkwUzGKE<_Btzo6}z0q^8Ybgrl1$aJgSc1^E*GgYp@W-HB9w@c%I7W$p1Ev zY-XcedSLsbubNYx*v;%vIzj$)c@s&RxSHiFi@);;Q94e{y;rg?^Tpp+ht~{-Zt8@+ ze4T>!NQV&kWM|4!pXDQa!ZMf<_n3aEG+@H`Y^lbXi_3wuZhuh zQLmrY%xue^62H72sIT1@$ClNOheuB$u>GATJ6NAcD;O9j_ScozOm;D960~^z!t$nD z_1N8u}lX0inGqoi@OE=Yg=ztP1rnUQd)bvq&)OZ-bn5aUI+9 z&;Z6OsbTqylewU1?MXs^Y9K!g$c6m@Gf8Oc`_L~IwNTA89b!~tj{0KDa+n|94x-OH zV10f=mANfPwIzj9#dQq-fGqCqF#cIg62;J-*6;h-^U#a`YYp)~*XetBL7Pm7cj0CIiVf4gjKPpju$(&9f66lBDC>~UWdD+1i9v-p6s~NKycQyz<#j#CePY0wFEgu z@j5RzLk)6e{K$)xL6k2p)vH*6)g0&p{!7Jm@!3+{nB8p)m^w2G_22s3BNhd5Br@kX z9@na^(yX?AD3nLFNA9$u18a`y1*gY~`pGAz5jZ%A)W}W2ar3#^fsy*}#QL4M-tysj zXEtF_8ma%{jrxY{*Tt(ZF>ctcROI|7S@vYG5_xtc7I}taKj!q{F5N4|kjLe<&@BF0 zR`a4_WZzHPEMiCoy|w!+a+0Ks=BA&f<{gTV3#X_t_c{G()r_Oas%bl@Z*~Sf+e0k> z_`4@n1U^?fo<_Y?z9LaGoJeCG3X%PHIguJ0ciNGO`bCkKNXp{=wBnJ-N#jhRa^W+Vs7s_j(lvmp_b`Z0af=-;1PNxF)$I`R(e4 zdX=AfpmCd%nCK2czO?TQoNb>hnVY#A`@70F8(vHbw5s_MhIvAIiW%s!3x@cs~8tG{x!vGU;jtXE-Pok_=ki;u}z;}^w7F1$fhua zQ|nMg$ImW9=3kdDIWqA%b^3lDS!HfNYTTukt5?cLRy||}4Y&R1Rq3tBU#cRhM~xi+ zKG%cDj+4w_!JgGL<=z(LPcDVj%yl1`*>gKG9NI}UZLP_YcIn8r!9VHdm-5iO7#V%L?8H48#MS2>(rvie3-A{K*id@C#? zX}oC*Rm&0W({&ucRBP_hi&rV?+vc&O`Lh2jPo(j&)f#qx<}-qTTcEfB+grP$ic|VtK{F2T#5}&2uj}tTA;|tE zPo%dRj1I%wAmoV#K0yd_Ax{YMV=Il>ZO({&_*9GiJgKt`E6w+3(?{JvcI>9lYPT<9 z8&(@*HP=I|Sb0qkw)Vtb)GxFANPTibSw)5DN8N4*Q`4plc0aKlmM8brsn7Q;7G5R# ziB5!s%L>V1zkHA5{+q`Kk&$ak*m8s865brC3w;g|GvABM_2O>SPhHy!8h%}3D&Hee z?=tWP`IUQ#4c;fNQ#*{*1Bp`=)8M~DCG79;)B>^<@3LF=j>wB$FOygQ-D2h+e32*0 z6EflTB{pWzCS)6k;+B3q!_*%pBEPY6q1{ch*{G!%$c=CBQw{#z{Xb8OaePI#J^OSe zkPXm3kNW)|eOSw$C)7-L4jyl+o&kH@GLW&G)u^AbW-xo@D9uz->X5(cgt53i*^)yc z;aJ|j$b>a);J-67>k;Z*n(SFsP(Ny(ScCjxm^~ZtBUw_Zd>vVBls_AIL>p{>iuVnI zJ#AQrt<@xPB!~L7X#-en&Is6Jn~nT%>qzD`DF*KN?8WvTKJCHMz68QU*<{q$2Ncn4 zBmNx^Hfxdh1)t%cxi|-hx&2uF+JJ2||8fCr|K)}HkMc((1+w>G`!jL=n-^9u=@jr7 z#%85q`QJU1$??KE`1Mu=%YVMn8^TmSfb2{0_lNb_eL-vNdpHoAfaN2i`hca?2e3V| z3%Mc03Y4e4hj(@Bk!74s!G8XGsIcpgaWzA492^??9yT3aiuyS(^x%Z~d&u;Qp~Cok z3_L;T$md{O{TjJpt|lD5{1%E^zn7^~)t`*lZG`8w-%#(nT#9y%yawHZRhY1U>d0hT z)``KB2Yr$Cy`|WqGyCAoJsafgyZu?@jx8`c*A4lDmMt4w;{vy?tU*3WW-;^sl;OKg z401)&TsAx4EXmln2l<_f50lntvRbzI1oDe%bJ&o9-?_NVv&cOcj$w`O+p}Trw~;@t zj|F*$!4O&e1CMvn)e$iGkvVyxvk&z|nNOzUa@2YYoBcv=&$SLX5Aryyn0k zTQB~vH6{F+|Lo%hZL+rck05KyYc{C?p!p=0ruRLAdF<7ea5C?e4-D>>iS~55_=KyS zltM?VtpK6_#(3VfT6TS|Wc}q_jMx2qU4Q2_LG~|sEu+=o0YZcPCfFUvug3~NZIW}y|nawddY4Svk%Wjz4WL{ zbR7TgiU~WksnCX-M#_Im#rozBOO?EMHH!ZZXaVN?vKgOj&L-Fn>B}muueca}kU4sX z?p_j)`rx?lWN#8-T4TbIwQpY_ZqwaaSf6#s*Ozr5!|mhP1OB*$_N==^7aeiq-<@nV z6WPzFyH!;G-E2jbJF@JZYA66>82nI?;GoiiSx~eR+iwAJK6Oi4#MiBE=LqYmG#rjmuEZNjA zp&*w%3E6JF0y9u5qc^&X>o0@LYU$T~C#k3THq^Jp;W)nT{}qP^c;9Vx>p$}gLDm+B zuV*cU9|J;3=uk24;!JX^0(@+tbd`8r`rYIfm5Ee`o7F?GJuQV?E5FzaR{JJj#k_ft zuj}tP6lDJrhncMg{~d>dye$rw1-{`F^IRa#Ma-8LeS6Yh=jT9l{WvD{b0RF~%*IcF z-WoHI+v~*Bie916JGV3P!}XeA`mr}eJspMI+o=yro_G|#9Fs;ry_96Yyf+^Pi&3{Q z-?%mRX0rm0KuPQ?%9rAw8aR+lnHfS@#9%drZ9wevLK7cP3_FKQHWi znpm3khiwD&K&bz@-W1s4Z@}u7iGC2>7y+7NICidABqt~a;5?XWW>dfcsyk}73}Hh=aQ@uVw@OEK1OA? zZDM)K;_nJHk3MH%hAPxr^&I96rKj(i%;FVPrs5NhGa-}N(c`OG>AMj)jw3fUvDf~F zG`B!pCpCKfgTAui-}QfgBI-TfY$J=FK4HZs3z1g`%Y&|5`x0k`mB@$WG(q?CH>MMN z4C{}a!}q_>Yi9h!5Zh09Itpr*US*9Y2Z_+XRs1s!R}+u14g5Ez1$I{Oh47L5I_WVj zJl;2bL&4N-D0AO240*`aNGN*rlJUhuhjBXAw{YP)D(}Ax`g(}ZHLB7O@+L2xM0+m6!Ym(8wm%Bg%tgNpwi*I{5mrq4y_hfGhmWG?Zf#)) zE}p>h!5wtL{&E-gDbNq??YK?_mTG3x0GlnyZc5!DZe28`O52b(gM4p{!%))|C zk&z2bkgvTiB;6y1!H4^4$YE|u?2zpkP(RWSIkcfG3wt{eoObj_-uOeF#f)|Ui*E+V z(O)g-tR>N;?)w2I^l$nzW;JqD5AYqg75PVHHBqs(B&udf$nUsElDvcwWSjneWQ%5h zy6@~8s#7pw^#0?CCb)BS6OU-tgI=Uf8`h%9i@l* z3-vP0D8>W!$DP7FwrrddcV*;K2g;XN0x3tBr z6W-sxx1=+vEZBDDf!tn^35Vw`QOppt4E66iqqv>ON zA3DH58vE(ifJ0nXdW*z9RGe2O^&UkWZkKWkVsucyeCh*w>QW4Ce)^sYbu#^}tf?fO zbQ)fV{r;>+1as(-KuV^6L%x1Gf<1-^a&Au-EN^M2!{lp&$dXv`IkktA{8;}dN>nL3 z7WI2?cV}N|02x>J3R!lj3p;Y~81>%0OwH@ly%W6nrpehyb|vN`b}96l`#{@%*J>~t#J3^X-M~ArAQ${tkSn?Gg{zN$ll%L! z(av$MQf#Et8S?31I*wb!x53QvtQHg>n1meDAsKFlsDPaHB&=4$a31r`9|pF^_T&EQ z{QAJG+V3Q-&=QX`<>^*-%&9kMOPgW&#wnYj=*Sw9c2!)zEWe+@hALek9%se%$ZwJj zuwc9bRVpsW{k1huGpU)CBj-E_LY8{BkH6IrPO7drp*{2V7_--T#l*!`T&IaU(4Un? z?jw!Y3Q%wIb|I^iD8b37NaPKlS25$$z2K}*FtT0fZZ=zP2zb?q`Ox`E3RAu^6c)&c zemv7DoxOWC3}OPhVfh1JPqIZ5^dNn_3LdXp_!+h{y*K3c?u~Jqu(g~Sw0l58{B!Vl zpB$`U2F@2qu>1q$1w9@xpQ>QVs{Yo%cfXX5r`S^hwAry=qyBpMk_#bsX|S zHI8M@Izg3Eb|Gs#$YRXlKl=MY2C~zqTvq$|4LzW+A9--`ac1xKjXGZ!_0@WtnXTIk z`s`UY>gN=kWa^in@b9-vM=n`l$UVudC3->KU1BF5Vyhxab;OUD+9ySjJ(0$#=dEzA@b(HOT^bgk2fvO!z?_ zIEeQ(kHJOQDc3@r;!aYbKNU+U#67uADziE>fdh7@f%S=avR*|zU;e5|gUk8x#5aEe z>bLhvgAF!`q_I@w>%b9RopfsU@-phZ_B|(`q<2vTp9{zvzTPDAqmR=G%da3yYunJ0 z>~EIpAIp%dj3KEB_&y2cM*B6SpijfkSVDM6zjX<(1SI6bRmxH&l35$ssc>N7{%PjB_n67Qf4zM2>a$L{;pkGX$woA(~cHS9gg~g z{OE-+4`t{YzdeXf;?{XprA9 zukkWLF61>qt~OD^7RhfU+1}#3Fk5RlIKDp1sazE287c97K*#4gG3sf9$MvaM!elRQ zB;$V>;c@hwK7s|h%8_?x#B~;}!Z@2 zb+F35fgGPI=Gp2n{`@+}3KT;vv0o{8!|a3+@J@XUa-TXc2u~mo+$j{fM^^=K{$dOv zhXy0>e(TKk^fd&7)BCah@uTJFl4NtxUM8-)9Vf2r@zW8oUfv7!C1Fl1qFM)h%1(;* zdDt`V0wK{V3g}nHk;BiP^u|Nl(~(LEbUV zxp>fNz_R~5N3lW7OYjFJM}Unj>K zWc<6rrtt@n+x*&v-?tb4*Xj~~&ex}SL7S}Yd@ab@{5t+|Fa){E(p}o(b4MvL8l-e~ z0MwsbMFe}ge&{JV(j|oU&RK=_% z570R_8TBuE?IN8fxI@34R>)<_F~n>#KavUN$cCeK6HOaGh_DdXQ6^qkOb*|SfV;~y zQNMJh30HN#5U#yEjP>t#iRUb|^1)B%7tZIU+U1=+{P{41=tSf5WokP^xq;VD!)o6n zSl+Kg=~?$qM<8TSF6x6lQ>`A1ISi(kD^dS!UmvR!Y5rVyssg_sBI#O6YBU!^+`vGr zf90wt#K2<)$eb!co*6s@9HZY5@0~J4=<{*>a{%>e3rW-7X~?;^mw;5C(4xqeeaKfY zZGq_b1$6y`FUW`OA|Wu5qqc#MkbCp%y60*esZ7cq`-M9R(d zhO%&N)Ty1{i}SIzICtfB|0~YV@UhVvHh<1vf~+mh>l1z9N&k)H#H5Yb|LJ%0 zE$?kM0hPev*naQ$GbGEE|K6EQKjcPr8Hq97Ex9Hwh2_ukb^RUZg6v=7yr|V+9pQla zO^9zv}i}3N}nLg{H}3em?M_ zD+KvZg1uSda|PWiw^NJPu5j2@8_VZc-6eXLE|KbCkC87W^kfe3ldRt2h8#Y$gyfAL zLyB8|Bb&77Fn5J|;vnaYY+t{RB(~F`OamK%Z&2(TIKE* zpHoyjoj@iQo}ir~#dRl@h4yUmt5EKVo;sHA?YxPcuo}kZoaB%#1Nrw@M#-@s8h!A5 z5Pm9zywIM_a``nozB{D!U#c_r*ugBMaF?aP`6`>p`t)7wvg8bwck$@UCN}nG>F%dc zKOsh$MCblU_4;ADZD5IY@@{J))puB5a+)@C>b}WpV~gmgZGP{@*WHW% zYjv4F=eJ^B&?aj;zX`H7zn3*w3?Hn5=(uisvHoi*GGxzcUnm@Y47qwOC0fZqhWJ$RWQ7yMq3n;Ji(7fNSA zV&EIJV|cO+y=CSHFPg@p-NORD(EVgQjMotFck!RJV;|2+*iJ2Ro-nv_H~p>aORt%l zVn647J56#elimP%au?gXjOTH&XlQWIW0CTe|mgNw&b z)bCNRC9=l5L3^E89?~b@$Cg)_pe}hIJ=Gk___LnQn zqZyV_(9bT62=yn<9KdwS#}svK5ZB>1G>&1j?|3quZ4p@CXOo*mAt8pzmbjtcD6i(f zC33-xne_gE`yVpQrwbj-$u6_0IBs|I%xKC~{@tYf{8gymJ98|#nSX&698p4^9X<-4 zxyO@|8$F8!eVbpo^Z))|e#Q8)XdR|M`Bad#`4vqKhSZw7T&d;{9G?ttPO@OdI#_b> z9`ay&8LH#YxVYB$?bdtW<2)s&xTgVEP+!8=^|xOMvVZZbbFBsoztI;q!LLGihZ5w1 zUkUO`*Lc=AUY==8EWm!0)!i@2_5DmUuZX4u07_2++WA!;i8``T88DJ^ix%U^T>fuFrd=uWUV_CP3Sfw8hVnY4nW_h#p z3LmSY=i+()@#3w_`A!DslWKATJp4}^(>Q`D*{lM$Uqooe8#l51b ztF<*APt~?`T3k7S9xT0vdY`9{I9dIpbg;X49h?n4Nlp1TntqQ%{W}j+!oLfIeT@*g zLTN3D{?VDO3p|VZZWoon#ws;Tn6H{$Sj5K65M|UAxxvhbu8UyB_=#H!-wGkHo z?$3g@Oh)!vl?^9*NwM|npV2;rpyRO6<}>ZNr~!Fc;W-!_Yeti5M`C~LJi7?~o`F>A zi2>@ng`ETA^r6(^c`wu#Z76}GA;vT}H5=omr`uLI+#E&jcTWVNKi^eG!BU%zWXD53 zcko*dIS4(wt|xxWrXvSxWqTcFsXuSCQE_mbmwmXL;V@JS^SBhPJyq zjK$3t*L}La+(|pkC(LAK3f8ZFnE$?r&Tw|sQPex|efRK;H9OU~8ubs|)tO;uMPd zJ)it(jolD(X1lmf(w28-^ZWMV|5`)#&-v^;FKCmsozDbWTi!`J=l~N!-V?o=3L>=s zX~0wNn=Qb}qW;)kyr&k^zVenxE$)l<7R&VE_J(&Texf9cAbEP`kn|FI+5{rPk>jQcN@HXPn$B^+1fgk(@$ z7E2X(w?q9_$8Z>37)9&Hi1!iJ|4IkjiP2PPgSh_FbyO{cJ5Hf~tS|cQ(<8M|ChI~= zj$FX{s%O_iaP$;v{YrfP@3qYXIKF%utu%GO^7cQsfb(cSda0lW`ziBeAkF>!wOG63 zX6(n+Hmj*l@#kXM#3*D}_1;|NSr4v^|MrYv?~1(1EKFr4RWX=>Y?SH-PWRntL6|J^ zt>N~};Qd6}ccmwCCjWco{Q>i+(@JOLWY}QVyxUL8CIzG>-F3YAqv#Zgbt6x)C z$-OLkDfA}t#EwT z%pbYVXfZoG+LGHkY!vcz=NYVi(;7MHc9HkZR=53geivkIakgd)K+X74 z?xLar2=4!;&Z@LR<5O+Pj&-$-C*qZD%E&y z;(`^h`=R)~qj!P)y|HnFASfyv$0=~|S$e}p3(CvWkllvwr}@RnR#H>-v7dcQ@6g*G zonZ8=OQ?^|xlLcTY$2nYE+B^#T%sEtI>G9@=aFyqze8){BZ&P|QEz^sigtRwnLKS> z_f1fpOXr?x$I2E5Vf|+p?4`F{<08V*bCAvAh+L zqy7m4Sinm0d>c|}%{AN2Vb&I+Ul!-eSlhx6;XIa;P!65XZ)X`~H zKg$c4e5Dccjg%02`pr(()ZHA}O5q^Qez1wHw-oQ=9Ox;{B9EJ}f!D{QKB%S(bNf$~ zm3N$syrDsxdG|J^OZtk}{c+>9*t&a%xYa+Fp#Dq`dDhreKx+Dn^P?NF(oAMhJ%ODO zsFyNMjC2Fu4S=tp;1COz6`8o2G+f%-!?6S%ahwQ%u_7zaA0VICb`MP`Ahtez2xYb z5hQ+$cppj1&4N33zKYh(DQ7}=4VrhJxb2w2RxEYJ`tlUogXcN^zVuZO{b|; z{c_rLKik8^uT`Rb5D*kS3+}m~~TIcy( zxa$e(uX#$9oZL}Jo@R*aeIL(Dl??37ky&OaoJgCm&K zr4_i2l3ss@yi#*w*V0#_{#@t5FuigZs~IbJCTg&<>amPE#=WBryJ??A%? z6*&Av1M9bXataRqIzT)dv{1h&ssa{uJ4?Rv&v*&;>@LfK!f&#Y@GfSk*VRgb6d4=( zV)1BXIpdvRQZkd?dN>w2uA3e7k*G1r-9^aBrTwAs;Skov$shUkwVkA0RK#*ziIzg`B;SBAKI#Roi@=PfIN&OAiG?srCSLQ|Rzu&jz zq3fgz^NB(lC(*Z7AhghR=sADPzg~gDMHAe zEjzz^&(-JmefYlr_&y%)!|RdfIcMgcnLBgt%-ro1vNJgal250JjCSuqmVBKB8r7+! zCO!*U`FuW9N-PyWR1Za-@b&_XYDl2nn#_?`_!L3kMddW7M;~OhF=8nE*@dYLTZ6~v zz8r<12`Vhy)fMAtYrjG;ZdPZnQlqgwObWXIyJIz(a%dOe>;HI{d`S4#gZb3jBiBqi z3Fc3~(mgA7AU_mmLXtA2vrN*ErMyzWbn;XhwebqF-0dtDbz>5I7}OuRPF{{3oUj|B zX)*3^;+1J^*J)2^`jpD}{cS$XeMj1P224o~LHjK00ygtX5}B%zgnWes!x0-@Fd2UY zxg)OmaB2T5uHE2b!JjbkzwsR}>xgUTxND}iSH_7(sGdZBWFIcH%>TI&*y|BkU&{{X z(!1PuCzrbj<4bk@bWw)XEK&L9L8!mU<@I-5<7NL6*Z6xL`3(!m{pI6v8yC=cIUm<} zc_oP?yI=05PAw17?4yM%$kctH?mkw?DLvzfgw)2ur)n+8k~gf0T756(XHbvqIkyiy z-{jApMhW(oFW-u)x7jnYxC-@w{?A0xo>ST9-#3tR_kXc`x@`}eH%o|9+iDk*Zw_?$zIuZfL#EcKB)|OZYFPSvfb^-tN7Se|US-`@T0>eWbde z-xETU+itV2zS79|Zo9INi{7)`jUyRXT!|k;#xtiSuh}oNdaU=$2iLQUitpIs;t8m? zTe^i^THD6b#}MS4Wm0UF))#hmkUlaumSYj3mu!!_rPQuM7~dK8Nru)7Tf|2Dg!K?hb$2+MtpvAi6wtnXd;&ys*C6N9aLjLO#vZt{ zqKQ0`72-%@u_nCJ3Wc>w6@<@!O}sx`Z66D_B7}K&e^*ZkQ1pV2TIra+z$}~$kva{A zx|7h}!muwa91;cL!%w4Lt?51aHah`o_Hy?La+}VjF;rISCRn*z;rKm2rwh5Idjf)w zl%oD&j1KeKTLY^XXJY-|eb|jjxL*Smg|Vogdcm5DNjD+j{YTU*WoohFlQmEon1q~Q zeOpY9or78?_?K~Bj;$Jb2TEMWq272%ooIB>Nw_@wGUnHNa~8e0_6{_s3fD<3)+SJE z?woFWaVg>b&FtTa&RcaAWDn~D&x`W8@7UeA2zIw!k%QhST7K_(90LEWJ3F2=rv6rMMs{>73Y@`k(T{%W$& zU+;fTBHc8&=P<&bqW(+fF;@DvC*)>G;Ca{X_BiG(uKq|BrFnr6HO#4;1zr&*? zM1=>#iz@ro<9y;am)GBMj+gyQoU8uhFrNp%@o~}d_Yp&} z+`bCynBlOG!M6N{?3i$de2?hsQyG0QX+)!cNfTU>@4* zr2i&qTT~!-r11UH;)2N_yGse&pJrhCCds|<)L9vdb&jFGQTt=z-Lc+K|H~J-+fPRj z52_-k4%VT6*B#BF=ioDhOzMLE@1$vDe9ZvMfS1BNZxfW+vR3qbw`fhTD#I^Oi zSh;c$a&z)jB9U`l+{Z)U1=sJyMA=-ZKrt1viII1tDXe?Gah$@EwP#}zVc`ia#O!3?tZ#Xv@!fW)<@XF zNzkcwJN?Yv+soJg*M%R5sn%WE{#Fw?lQfgw6)J4z?gX@-I>sKhYh9zdBm{Xxcrh_; zJ4IubTcN#Oi7odn#gw92&r!(o{&N}o;3pp0R}T5v=ti=I%g9!iozs0W?y)$SQ zl-&4$e75Ww^&j+|2Km{bKieJUY4(|&bWi9$Jid3hy#DSdyzF24N$nqp`ESkf8}B#Y zL3laePk4D!{y1hdqkuL36vpL?)byFF>?x+VDFf@J^SJ|5|K4#HzHlS5WaC(NeQp73 z8E%Rkbw-u>#bvU^-^-CjlU+gU-VWv`y$|`2wi|pIx|5CKo-^is==+w@Bd0={!^@$J z=SaJ$kas_f{aBoe`cRES)Op?_c58wV-#y+~LhE89Ryv|D+E0lvp+jD(u+0(6kb7@7 zhY^l_S#E?rvhNsK+Q_ca?mGjJw^eDw{qh-9?~Je>(z0T|xT-x!JoI=d>ZjJJg6_k8 z;_$lZ$jwPf;%|r4$gEl0kPp^$f{K!O(kSVHY4Gz^4U$$ ztK8{A+v|*=<+QMVQv0)%xSX|zJE4H~m9efg@8M=pv=ZWu%ETlnz6^@3g&C zW!yfP=qQXw{DOCp_=$(1t7kjb&wBGCbWPbI7@jTI_fuO#`;?xBL%W3aq0J{&kz<3- zz}7?O(LV8@0v)4q1rp{*AV0ioK@`~yure3!J8hNL7W4)Flg@+a+wG?iJMa?nm(!{wMzIyvYYFQIy3!7!-RwE^?>L==^Bdmwq z)U;qf9gIkdV+_Vgss4rZR!=P`m-j;ZPRdGj;)QI8{3MJA3(nfGgzE(&*F&GMU+Fy< zL(h&;VFPM~dGN5*JZh@+o19Nyi0M1}y)U=#|LXU3TwnRqjsACjUM?vgDSD82n#H^p?sGA6x+Z$R?le2DvKsxm^+-*Wb@mL)+bx{` zOm|0%GLuiU%Hdm4AG0)!>|d9}#9~FPN5gvwu3OR4~b-^_lF?2 z{X9qpj*ej$mKzB5K3E1Gowa9AYlY+Nz}>rc(r*--G(HgZ%M0beF<~NG9lRddQ`QLz zXOz$tX_3g6kLyF2dk{5mjYi(*J{_!*Ptba;DCCNRkq{%hK@{9Yupc4m4RT?AWRSUF zug>;CF!!Af=fx3dpY|#rES5+?`<&ItqbxFDV_8@DC=r0HHS!cZ9QvJ1IV1SH>*#jS z4^)P!-okuS%`yw-xE7GJK|yF=CFb7IZaxW~RINq!F!=t z-0@=((!1%mR$(5{b-xE2kgdgn?g{hpRv9a{{iYWybxgtIckjLdvse($G=6tO9=oY4 zUB9T9xy=@yPs^=tr+T5snE4CgewYW}@6g*Cxom-f4CD9bY%_~?&nsf`Hm1nGwSS4> zF=KM)g!|!wbGtE@`V^LU%ZBpyt)H_<@LDa}?bj8wuPZsveY;T|TE0F--ga&hB>TyL zV|FfbKkj{D-lx1^*_92*9sP7Um)C#w(*~|>|7rIB>!-Y|qn|oGS_@6PN0ar_-O-=t zUnFVJK!1?!x*p3vLuV7Q44F#3JcQ$a=54HKnQ3uRa-1H>f_AmXk@sGoQ zzej+V^Zk^U56o;Q=eIu;Etfn697@zaSAa6^xrn~9amf2}$HJ>kH^kSu_RQ;3ddwxs z!!pTfdJ(yJ;04QG1`xtJVkv~t0`;SP;VJ?KMdL0d@$?v#gbON65?@Hv_5OAJVcG7ggEeN zvkoMtU7%wl&CtHaV=${oeN9atU&MNMxjdY$9^aYCcG44$gZ>Ea-13pa>oLgv=Zs}- z&sEr7SD_uL$J?>zi?dM zWc91ekOK~_BfF&wMRKk}JF~P?Cg%1>MJt~P^V2p(ThhE{0BKuv9_^0==8&rI!Iqu; z4kPFGj}gDpdL!PmECu=UMMLnRYw5Ql59FiH@zkJz`{sf~1oFohMj-QYJ++7w#uwvC zblKXIzv+RG_Nae+XEc-!45Nz_ZIK^#cL)E%bn3E419^a#H>8wYr#3ThVR<7?EQDbi zwN#0#Q@(t~*&AS4)e~wSOnF8leT3`(9|wiPg^{P|g9Ckl*ROjS22XQR z=`itdONTTOQ*6=A2U{NnV3NyKFz> z^XqN&oYa8=>|7zto6buOCfQ#Mz)MEZr=J@OGbB<;l=E3k|LjpDYm!MO3i@-<-;RF0 zlFRGA`gIf67yfjU|MhEL*3qw9uWg3;JNAoT4cdtP6jo)5$`v<3u1_bz`}b{wv*_2y zF4WO~6P8Erv6AJy$6IOFzOQiq_qn|O?$^BRU;6cfKMwQnJmEKf++ED=gqQREnwKxW zs6jp%?_fJ*gy&f@R}`~8FBh}y-M&~)ciRV(>F0FW$~a+tyyeUU;`p;09n8HufX`Dg zER{(tJus$g#AxIt6PJ_wDmTeyd7<53Ec$t$Q6PN?EXPZ!MAE*$yBj zb8}hr3ySsh`S)$+GBuHz6xk!^t0uC7gR)R5FGBm_4SR^$tECWd@+tba`xdjj_Asvw^_Q%Wv3*F$0W9?b8H$wxBbaUCqYIvaUORS**su8D-?$3q}TYb5dz<3w1% zeRp-pO;=>el_?;r>PnO*3jOY~%2{}2=1r3h%tHNvd*`8H@eXR!TbLhDbGZSR`}Ji< zuL}K8d1oE0OcSx8zsIA!$)$Q|o@~Wd?-scF)?HYlZOi;FjYYkNxB*^Q?q%cP4f;E! z$355qaZKv8a6jXtoCX;3JeIjmYC-*zuXkbOaWP97?P$p#&pyZNL4N5)W}cpe?egrD zi}14ID%+%%PI&#AInl85axwR9apC>}C$qayn#fo^TZ;CHfdfc4n#ZhL3ebMFwHb9# z%w;xHh5Pj{XJ2M11CFqm3uUOkx$*`}tUSo{f6PRlVt9*L)Er=jN`sI^%C{NOKfsDF z3UN6s`6cVNV>z3CciR8ZfXK6Z<*=%`&Tw4E$NgU|S&fPM?`dGN^3$wdx#V&B~ zf8y=i=YC-A9`|VL0|(^NzHivGx!vhNlcmUaOI|SRo<~LJZfrpwlK6}*PFYK0$X4X* zzv@}r^+M9VVjZ&6?MgPw^c`6yT7f+B@^M&4SGn1|fH~SV zTx3%wcVct8e8T)T?G&@CQT^B)+6(m#T;Glj)PWyEhGO}20-mzmiNnddbCZw@*4?xG zwle}ImxZGJtWljIQSSo@>OKqEq|;>>y46?YKX?c3Uw_Ua7-2FOBBg|RO-I~b&H19i z{r-eJ2`%0^ZfoWQ9kPz~5?)heKpq8lM{B}SCRy+ zuEKn`N8ncQ;hr7I{&WAPa@KUXH*_kv$T|qetv&(*uGzr5i(N6ln?sXeeOUtua_@wE z{Ocz8x;>dxr|w4k*kNgq(tj&i6Z#wdn7w`w02X5V2_)?Xq+i+NV!W zhxWJe^g?H8)b}2p0M%~V%zl{?^8FXn;eswOy`RGP?Q`$F+%vDvOs`zCQu zPtQ+frrh^id3|&21k3a3+_%-*h4G~4^OK_cKJKiCSr+P*DHD-T2F!la8D!(|8zS+l zlXT$mYsmTfF`~ow#?V@mTgVdQ`V{J~A4h)p-$%|IHA_7CbUJalAh7rRQIyCH1aF;Y z)YnLv(}X)ipw6cW*o2Z{DjU1=A(-9i0lfZEuVKvY z^8gZupn8UKrWk2yhytRwF6vW~dNl^FNSm+k-G{$FJh5-nU_f5$yu_Ahbo$sdPh z{y4<@9mM^gm-BItmv0#ye({QWK6`P-Wh{q0kNt~zJ^ZErKepQq3{|@fR zAGxF6{kg>dRqszb{onP@%R1`)*NurFS|-81{1C>w6FZlZ1s^=1vOEv_v5D+YTF@Xx zn|pfV@v*MStcYc%nY&H0uu@q$>Xb^4=9k*oz51qLk!?=(ov&5v(Ha zytv1@HCV3DG-IaY`$GKY+B)Q^hletC=QCo%0Yd*NJ2Qm27M6+?m4tYBL!yG--O`IL zK6@GMPlSx8I~z}lu5=GU4$|LG6SaELdsfZJw--jyi3{cEFH?b6PEi*XXZVTx9>0nD z{hv<}pY$F?l{;_o#m?`)i)dFoE7bpX3AyU&M0gt3U)1HwF66H3W`l82Pf^;1<;aOY z++e=^2$9S*VcfDf$`6Xq>xqUa%|m@a!8J%RN~M!$OlN%l&i60DuGg+K=bfawe8qC;bj;PGkO69zIbn#hbKVchSu>JXSNEE+Ro{tMKvah8KUw;OfFw(CEXU@RVN}>UYB7jTWnzA3}GHs981{4c2h8+XHcIuG?Z<3?+@2j)F6i!hcoXO zEimBT&Cl1D>XIUM>CF|A-KL1;Q*fbd(csIZ>YPwtO+y*$KPH#B>IwQY3B_z%VzTJu zwjY>2x~`O6Q7aIIi=;5U#@tgZwlGrEw$TsuXF@~3Z~SvwGJ68*7qL3(sy~d)TeV%p z?_bGiIcso}Vrhl_QSbcq2&=gnB3iiE0=ez{F;<&pKy5o2BX`7w050u+#f9fwU;5L{ z{%R1showp-sANxc$trg}~^)u4xfiCVac5oy5JI3HUoh9K<;#Rl;@1NJO^`i4X zhLC$Jh36+;aC!Y57kJsf#D$lC9OlczZ+txF@8RL)d|cq=rJn2Q=86}z=-zs)hwJ-N z=%BNf&lj-AOV+=?D567Ib=_GoXrJk2sKV%?@r5O>;lxX^$PZNzEjO4R%2*wUpBtsweIXXJjJ zSJP=92Ses4TlBAC>I5p@W)C%5kCAJ78c=q{3mR_={Wf*3IjtDLjWL#0V>@h~ydO2av1t1+F$uHN0q36qP+tsC>j#_r7W+Zu-4KWZv*Yw80x zmbByk(nj=!!9mTU6mMx9_egAcR+KVFnjD!>i1r=rcmubu|7yptxMTmPS^TdZ^RkY1 zeBR0vdecsf_+%q%W z_L|G_~{-qti`QvbZeh1vfw_^qFJ`G;Zw_{%JT{95Aq?d?Kd#Isbvz&Uu(}5?c z<5polvAR=#VDeX~f1U*DS6J#pio`zgpgIj?7j}nOJguXzD!*YlSBzH&*9$t#dPOR7 zW?F{jn;E+7`c~n3s)`5n>SH%%zLa6TXD`1*Zv2X2PINQn(`%el zV5YSbS^kh6XdkJs%C<(?vHh*PkT-AAWCbC1tgo@KPWE`v9m-v!U|-6G@uoylA{CeU zu;%xQn19maJ!DN`B0F1KiTTfUcc;JW_Q2GWF37(A8|dwOv9R*gC-gT-L5)o67Xv=) z1pVXwA#~!zIEcF1g8GRAhJw=AU@-Y6LVrA|9(XqFhJHofnBT6WzN9921=H)V%=q#s z_jP8+AFm=R@?zAV%;*DFI+sOOmDiAC_b+BeokV1N$aG|_p-wETPzr|m^&x!vtx-N~ z=GHb^aYb0yGF#=r%6iFCqn~A{@8}1CoUI1;`_qK}H@<$$2|8pQ<7-~l?~m=3mHyD} z!AbG(H6fT^SgEwAPuK>Cf8mIHF=_`Lwi0N`lU3M$w%k}xdOsLK7i?_A;tu zW&hF--u-d-@9VL=obLy`{FO#1WSnXeN6#NhIh0tKw-BOO8Z|Ez=9TAdr-1Ch1JvM| z7wX5$hr*(=E8^wdtdY|ec|efdO{y}j7naj*&p`N1)LFmjLVT`mKR}!pK@m&+^ZxqkYDsA3;`oV#zPL0L9S&8X0r7ssP zH=M@0PM(5#zu~5gTEdey(Wv1Z(7E+Z2{AS5wp)Ev&araEf8tfzs6Bwj=6So`_-N`YTiO zrDn*7W!#vKP6CxP@kS1QOPF%pZ+c~36#6r6u_4>CvzSUxSb_SW2^BqPB^l|Om5tIbtILWvkv+7(Q#0CaseGzE9mE)jsT}igDjmt3`4#4`AEpTw8v60 zz!2GNS|k*k-x!nSCFtw#_=xf?;>nYY6TsKkIV%NfKJH$TMDl55s~eBS`jZceZOihJ zC7yU$7WWP)+Q|e?TH7k3N8gh-Yg195(6+OvdD0A+KLC(lT5e-`eWFQYMSqMlkp|bu z#^c7Y>9P&u_t&`mCz(889JHMqg51$hH*>oG>Zk9yw*9Bs|L=Uo%R2gL>QNKuqBET& zO&W }_#1UKp_+{MFO3A3D7=VsvPMID6G-)bDkXpmTgIsqK;+^zQ?g*Wdk=m;FmW z{rJb>0epeEjgK$d-1&-^^Zk^UmvHYl*m+C|bVo-J-sb+B9P&d(9dP87Z&clwry z-Wv+zn28G`Sm=b!H0O*m*2Aqm;Y?4dkzU&;tn+p^=><0jJfPPuzr*yAU$(H7rnYRi zgDl!F@>|714{T+Pk;4Am_PnD?HH+DW(e-E_et8YEQd+}|orUz>o~S`|$S7v|gQ5QX zvnnWkbdN^)sbP68ACa(=C|bYEBbZhZ<_ml2IK2rQZ|Q1Zu6kZ3iFZIUf%~tHWpL= zd%}FXGn>HNX6dl+qf}A5{cZ1hleDW(g`&_3UN^$b(-uC6vl-q!;Zs5 z4}bBhH=j{2Gdu~(#?K*-Dh!ZAy6gt>>9*utQSIlkKV}l59=}8rAuJegakYuFE8n_RT<0SSB$C2<`poDZ-2tFf`^aisUS zBD6o=APqI?l;+>aMm7plVOA#7#yribL9Vsy3h|wa>EXr4kY5DXQI~${^!4*vWS^mm z%zD!*>Up6NdFNq8=GHTTy5v7V_UGQ|5SR6kR^L8{Ojj%*<41m`-<*yx-hauD@+|MA z1Dj(p*plavvYzbX3w!1ie+SFk5hsE<-G9Z2FI?aH)9wCu{^VsHabjPKHB@9xB=S|l zbrkpUzGT!fdpI5@hx?xrqsq#q6<|@eBKjAW7f*BM#*tQ$Chq?$m)GBMf|vbEocQ*~ z;R$?!xs8u+PTWp-IUgr@`H?mKVL&kj!#iuxuXekB(3VjQ?my=sE8KlAYICTAO`U~t z!O0{k7?@BD=|_b1NSTtJ(C2pwkU5ZBBrFgi2=%Q-(R zj5_RTgl4~VYDnRNsF#q=``5s@ z6O)lUdze9PNeOG{qk&xCnSf;E3GQCEamb(vm`-;JHgmQ>tg3r`8_MpEx<#NnSGv5ItSOn=_bhmBCa$@*Ig$c73+stLcF2Q9#dRh{C9!_03?;>;L(-X1 z;y~nbG7@IUr?G9uZpboc?}+;P?_hmD2yyB}gc;2AKg?9p+)*#3EKi>LdN6}N{>Vk4 zYS2tvSn%F$$g(%g$mdl`EWmIVa^qxW$f+}9&x3a&&l#ai=AJ5~9y22a{T)eIGWj^o z^NT{ZvQHKj4_j}U(7X>hPWl6B{PjWXbWC6c{W?n-HwB`+U@z*=u5Bg_S~?^;N4UPn z-R?^BxNE<8gSVr8(Yc$%Xi_U#aW4$H;D!x7p+5+0cL^LWT~4}>9|(b~{ZOwl&X>m3 zn?j$x!n_6Sp3x_+yC5RV2ld@|{ifdnW8jqM9OSUiR@}Yx=fU9BP~@Wla~LTp1H+3d z$P-kCu%53Qz`M)=kIxASiq=YxK>dJ~<4D0{)A1{2BX`8nZCu{}6-U2wvFA@%`d=L7WgT(Ue9#71zr>k3 zt^f0!jix)fWVQ~jXse_D4_YfMTjh0WSMEJ}y#M1y9I+hjqD1DE3F|pOxV-+3qrB{2 z;^@ym4*z{!h?nzml$ZZ9Ef;z2nGch;yu#xmU#<17-Tx(xaohZZ67zd00n?{l1l}JfMJ4v)$}iG>K;T>2RxItQIzm=& zxrgaH;zAgg_P^r7FRm|f|8VP=hw-wGxZr(p3Or7KLTrtzuzuPDWN9DgNif4+4f7w> zs}IWyxJw-VJa>EGcer?la~w$t5$3hOxxD_43%u-K;(`RX7Qt^rg+Cb2s(2aq*m2%*-MpdVk>bB>uu$(YL@Z-5OJ#ZM*D3m z4>36{0-2S~$mZPlTbCap&_;y!JjL9tqPcPhfl%Q&$Y#ZbZ1TH_koHoz?_c%aM^XRU zOW>d@j0X(kZ^qHR6Zwey)K3I?Cd3(sp;_LA0-g~U)MwKE2us7XTa^w-F0clUvVT^70fxC`dDdh8l_wYV?b8zhVu zQkTYqyow|ENSs9b)WK%3!qWgwbML$7t1(D_JG^Q<0PiMV5%V1E6bsu@>$ zmML_<)))1QqQrFLgAuT8sygz$x*v3C`bY@K73yQ0{Vy7lVg}2MRZ%}sYZE&bs|p6t z8QC~?C+mHt7c};gKvq^QWZ&23k&R`-yesO^CAPjXohXmJjs7owX9PI~a{+!22Hqcw z50X%MZlq{VygBmO<}qM3(*sVIYa+KS(V)6T``OSWVSFg(R8Q7(?<|sNzK!pz^L?UA z=4Bmcn)*}FJ|In+Ja}`J<<6Xk`)hdDNIGqO#EP#@#_^x7`FM7A-xN0Q(o?LDOto^6 z*<#8(mXxBsQn&%wf30Eu&tD+F8a)FZ`Gm9l%kqr(x1%42bN|=iejR;Qi&t`6C$8;x z$U6ElFYD;XKbQe`Z9IqE>t=xY9UbwQhWIQ1Cr@olKK-&$ePPz#eWc0*usqZBW{C2? z?x&`GucBU(%j@rc%*+0zA9v=`^BYzO_m}s(nd`v3obSiHyx4SIQ7=u(GWrSQxbU!H z;wQH#lim0Y>#1^|8STEml+ADu){_g4$C1ntsq9zpwOG!8@+;(5Vm!M(Pgu`T@Tw;z z)8d#-^>Wn5S?R%D=UMF1u!YF!bOgNHJC^k{6Ylr)b|i44hlmY+E3BtG)_Q_uUMa1Z zDcBbep9Puao9M0(3-ssW@+I(e&RqH`Y%%8d<=j$`x04|cDuw--?VSbhZ^aPT`M zB)wY-l_no73m>dRd!xNe!6Gz`6w59}E|zuz&vXOm=C%Y`jq5{G10BG8?M+NSG-@o^ z9-R(zB?Nmj(;g5XyB9|1uSWYhy()<6i$f6b?m610dOjjiQ!`*d{W{b)jW;AIbBiIw zS*YJvcJksMS>^CtQxD6dP_1HVcK#;R>k0K6B3(ucHa-B|1Wiou=q1a#E^LNbGyKuM zYHd@|gYMNJWw!(MS~tGY6H<@CWuXwazS*0w1*acD)X9x#-@I@%o3XtCWS+hhafe%? z?{5cob6+!@t$Bz3CcigilGAEoll?Bj>#wMwmtntfr`v}!@WM~Vg=bpeONO~~#;PK!Tm9Rc}opCdax&=&o$Zy|4D z-Xkk?UL(pISwa%O3!Fb~4ACt;E>3>kj{3mGBC>6ZEIlkOZ~(O+?mpV=QQxjR`CxlBa5Qh=_w7!=IcL;=l2k^xY|R=5_VBz^baPo zNwaH_BU_E=!qb=7_VeM$OZ9Up45?%C0bP+t9G78NeH)l@LLk;(B)1OIfB$W!>LHx3 zmp|>t9){mz4O4{sYQk(SnXg0*`!rRE3kjVjGrcV}EJtA~R?TEVn1@x=#?ac8xgSI9-$$I|Y74`}>dy`M*w*0EK+aZ_b0GVDKiC+BZ{hTEw1nozZ@V`&yQA__t_%>kTZA?2ENb z&b%A3W)!)gdmt;VwIP+my9?|U!fNy5iLFx?!XJhaj@y{(nK&XT(;N9fL>$CQ1HAqI2{T!>K{(NOH$YxlWyuzO9!5f!cp|49p2ULoOd;D&%s{RR z&7zj#RU(Bwn~*K72SU_KQ|eK^6nTz9leoodnAqgc`d!Os9a1q$naZ^97VI0MVOx*~ zoh)sMY#o{k3J1H2@)e5EUx$*tuyWEg$}NAPK4U{Bgg>nk)r4Jb7 zcxA<)sqAiLfmrT|5!$PL2okH@a;0zj3-gwaez%(|>won-X|ApQ-S2o=N5AX0(FA%t zd`5EbdhGc#xvlD+p{9R{@mI=)34kbW9S)I)c?}eA;pR{B9n|#Y|k=WUVryH zUiL5jt{a!0-!z3k!gzu!1TW|N9WRg8RHEkGyBwStHd#{s*qjBMiKu$eW`+HDe|eS>TsmSi(dXM zj2C8>>w-_c3FSVLjruwZ4QSsoi+m$0sBu&9OvXYQb%lbwL~f0;O&_&7w;qMq}RohppQ;t6T=W6XYJkD9)8 z|Ne9uXqk@ex=Dt9IgmrgMyDbtxPKA*tl-{#lP_?&>~T7GMI1GBPC)&gg}SW&01sL$ zw;lP~>oIKGJZbS6ZAr@Szw4U8><4k8gAWVm@2?d=%!Ry-i~nk*oer7OfbL zT-xokxS#qClKV}VUsom1B901D5M3k0#g29z$>sfD?OK*=3xBt3Ue?jBjWbt*+WZLd zJ??!zyno%@Zdyhk+5`u$$RH0^KS8?PeJc{*UylAviZr4JJd|l~(v0u<>CWZ#cf00g z|I)7Ixb*zSmxtf@^B{j8BroUNH81aH7!6N7(x|az5FU5g$M@*5QzxmF!&yr{jnWxO z+H(2`Em+ln<#_Qn9-4a|reDsELHqMzKH&B`i~6<=z;gBcY6nMt?5Cx_h56BbT?H z;r`W!2C*exjQSg9V0n(Z2D1S{4``=x(u^;!VNx*5c4?w5+XPltcVbVM)zQ65)~Fxr zJA{=!zeTm3Rv<^eAIy5T)KL8?!Z^HTtqLh#L8zavuuh|VHxq{L>p>lol5u}^2~&yh zSaW*m;$%#(By$vGM#hU0p6ejLc%K2obPegE)xK!o&2==(ZfhqOa}OX7i@!y7tyG73 z+&vAvzndi8Sns?BVgyde9ql-Z)BRUF?!g`VzuPe{>uASWnP%{$j~@5jq-8AkRaeo#tnbLng9DlB(GOyqTf+6n@%wYA_hwhNJVFum z-RA}~#rStLe^e;4?(>aoWw9>)@gPe6_y{f@?~9b(@W4Mq;?G<3`g z{|Ywer|`W*Z4yzKbfuhGk~}e=zpP#m@u{w0+AhL%yd#ov#7g=atDh*WQ!TTkWZAJx z?8-}5!rSMlUL!ZX&#>)hD-oPt@lHX@JCo0W9iV zXRQAXyUn1wGLL(YuMDzYtqbfJ@wsT9^>eg0fBKVns(vR1lF7(1cYPpgq$#;O>jv_~ zfNgMN;}24x=ZtK^tr2O?oCm5?HL?DFOYH`;LE50;_#XN6!+3}vI~f!VwqSWbj&cEG zvrSO7TzIZsA?>rMd}l5+m&f5aBl(CP8F!U?$L5Q%Xm6L+Q>>qn4$AohaDU-h0rbF; z7^oJ-BKNx?#V$?=f@^z)>w^2AXt4RKS3&uvAE+;m$|C_rms!bWD`eH!JBk!G0etTp7Qk_^}aKUT(}K(c0GtZ!1)LDS-l-5wq_!` ze~@NTgL6p{2=kRE?S^dSlsJ*9ehzaDlL?^#lU`KLc0L&M%ogPWmJxc^NO z$H;n5ImorK#^ddDY?FD|dY;{q@Hm$;zFrRO&@;SZkQoVb9%%lWv# z%VqTs(8u@k=z^~)=-0$W@~rNbO({xV8#AAN!Z>fi z*Xz`?R)KnSNyGFHjX%(S-wnv>p29r){yhB4cJRwKg}0*Dze>`4L?fE(f+m7OcJo+Hc0FZ!{gk3;|w`XO5vlXBI@TP zG>BBJGl4~o5!mjKD9MIflbHBL#P6>@)L(SA_hG2<7tWVQKRD7R?m02HFkybDV7HwH z>;QP^6N>3Ce7!~8PNtJ_s}3NiT>e7!4<8d9G08$+qc6b{CMSp#7H1-t7Ra+k$w4$* zN3d5O*`L`NU8m!QMWX)3B~7+#(Lm<7a1*lQbafWgbpg{GHyhc0lN8%f5XpXRwnEM> zuBERoXBvVYJfX5_|40tcRER=Ze2sHZlWx6YC?qs#=tqThE;8d*bmsQ0qmO zT+L>ol2d^%zeK*2Xd(Bkc+F&CKK45>{d@l zv@ajy3vRyxNW-r@)R*1c1kC|zBAuCq$Q^MchAXND_v?rmT722LO^NG!9kPx%!pl11 z$dWT#pvr8B_|7olJ&v0fZef#q=C?Zn;&tR;_}4`RLhUfcy^ z7oQ>R^L#M>MM*=L!kBXL)sez{&)e=KE|QFd!G|oZ1%ZBWVdxN<`>*BB$kgvC1*^;yX&Q$iBUEENy=$k~6oWkuCkasp4TtGH{7- z{qxHZebTO2OK7z)|0-`CNmj`>5MM)qZ(Wz?-t(^nn(o4U@a>L}+k6Lrz z8y>9=)fPRF#~j-YI(^h3*!~OpTlMNRROSC5Upfopi;YJw!$QeNB*V}h_0NyBz%{cq zWEfkEamD1pCx}k^DQfpQfamYa3tmC}o%!_M-D<2aqoOWWvOiU+U+7Qlm&{7mYNdD% zeOsu3dVPx$*zB>Az9=(e{IQn)o?p~0GJ_f%C_z3wq?Q&uIYn=syN~RtsKH#SABZ`k zcMRs=D{U|RrPYIJ{JDRyBQC^o`}(iApu+W~zvBWg>xc`dE^UO~N~1{1gtwNwzt0b7 z(G9nkz@+p-ET5FTSbWX&EYVdI=FeweB+_k(d&NHt_oICuF0a4i0x$cQxS-0V=eNJ_ z+vVkaT;Syg7NxQGee!5P=22{?=V#AjtrnN4-&f)MIYcd$jrF`sOV<=*y`8y~$aV}! z6t`u+!E%+UMzipfHAP)_D>HsyMlbiX^yJZEPnoXBK_rH$M$Z-5^fEwRYZ%Q|&Uqrz z-))N=m+sBNb0kRdR^fbkuzVtG4sx{|RgsVSc1vq!^~td)$od?zE%*F^r&};}e<9e* zsVK3=*o!o**CEvRJ5@y0Yx=VSqaDb%owv}vrKW6pv2gy@*)Ge98dTXM?jxkUzx8&n zEz2g%W;XjLp}qdefn%h z?#srUtjGEoKVmzv+$_s{PEG+nf7zPVa3bH6S?}C{`saG@;LQeGk=|b6`G84HPvOS; zA!6Gz!uL5JxIKr>(p$v)LxuZBoD*(>m&#Zw7rF}Tzs&bOY&x`rW(ErWH&kcAlAejw zvZxgGoenTC)%!-RX1C$}@IN-LfzJ~jQ0L=H=#TToT!@v_U{Oc3FwVRc*@EHYR=TfR z5A{9P?1VuhC$Y_^MxwuZ+&7>kmPoLQY12{P+3bnv5aIX}*F+UG2=ed=hl|cvbR#6^YlH7{;rx)&$&Z}7-~yU13sLVM!F_vEmAk%qbw2X%v8qfnX)C1GSs=fW z(qL<1w!(AArN~M~s%*E`R*?8~set!Se!vmpB8p_L7D9SG-wa6n@jJG8Ef%!$5+u6`pVk-P7ZX++J3;yZP?8eB#sgV9;IQknk#EhQuJw*F;S%K}W zDba|wtgxip2W~{Y2A9|0?TnZGOFPr#((~JJ;SaVm1+Ibda=xAMa<@gDiDk`OdUe1o z#+#M+mCyw{BUt0vKIrF`?`71cS2lIIycG34ti2f7?#sI8+(*CNyL&R(&lkiA{&P_8 z#yxlVkaqFD;+{L+Q{{vd7ocUI&LSvCtCKu2$ z>1euTUNW-N-9tq;jWg)|CgJ=P8#ju0pE^#J?S*le<&PFJ@@yQn-f$i58&>H;tJIHuUquoyZ9f3P5VeMDfP;O_Z-Mx!CLA`}-TQZ=4D|4{s=iJs%@U<1>5YmhCs7 zOz|K&x&AlSM@F{-u*w^5IV?}mCtbV=m8)lw9^5+``Siydjzajf>C}Cga6bDs=ptxG z9WQDNNXGpQp0o#sfds1^Hwp895LFE3lP(m+^vFhip4vvxP}5>t#5Sm(b$BpDM|iU} zdE=1dY?PofdO3^zXoc*S(V4`PDE2kO0@-}_S5b?16zeoZ;Bbv%%a?(B+4Y~o`JlD7 zndUhhU;_(=qy6Gw3HE+X68k#P1X)&lEjyAQ%`65RAcs!h$%>_;*e@~|`N86RcCBs+ z(;c9L{8RoioBwrtPVTdhbsa+&D6dejZYS^`rYWnEBGb!DF~7u%vDDFI z4fv=vBdh4G6GfksCUYhT>ou$I-w}r_UrxeTDx<&r^N)YW0bcemap3=+1Z)d-8Zcrv}X@5;R)-28+5|xtPU`Gn|Hpn)d_1F z{aSc`r%lOsetODU{^$VVytnj#gs%2&t-nw&7wrrztWRs$NVqe{lF^Uv-uThTkhfgi z7vXaRSFgP1?FJEY>*I9f7iKn~*R5mVy@B?WnNhSPil16@73p+yJo1wqCH(anIb`dn zNaP=mf$wkjt3|zi?qPqIEoRUbC5QAYr_@0HgOAblk3DVZ>G#FRFLH9D4{IjUK(qUZ zf7n-#`rMmKn?^+;ZhFXxPP>~7D|i?zs5| z9_jw^8SUXtu>HBIN4W-84`@br;e7?4Le7Y1Onpi36!t~_Vy95DcJ5tjd&84s{oS7? zC9Yd;(+TU{5FZ2Iow32@4h>Hmg7~jFV@S!uyVUF67{uRyvmucgSE<`$;XaJK|8-7m zevU5RC)Ay+$FsQyiX&8#B<#b+xt#3x?MgOP-xKQA!CsO2FE&eP(VB3=`hRtEIiF2@ zDff91;_)w+^RmOf)Z>DH7hYb@pDyvCZ*~dsQF^yJ{WR$af0)~c@?N*=!f)Os@$E=H z;=O%Z(sZky;*g=|5jPpyhF%-kUYw*5@S+**=;R$5?sKLd`Im0gqG8XvkQ<`ah;utk z=?twKc{6`0;;mXu;uF)e$XF-A-l9*F_(Psq zq}ra&h_4TIA^VU2MlxplQa0W$dONbb&IJ;9WhCO!@Vi0F_FW;Zm8OUn&7a3z+?XS4W(jX6Y=AA@*pMKb?&>^d^NmkRNA zFYKvr9XZ)<8Hf0@kprl^bSQjQD*^F1hiLi_`~+3EcixD18a#-eGlkyl5ovD+#k-^qwnd z^LzRwORkdz1+JC8=9iTmXRQ){bo&Y_}V)e*1RDUEd9JB*Gy(zAf^M-QGyH1p?C>uyds&S|i3 z^vqsHE!vGnyw}{b+!4`k+Gk8J#JAn5MtZ02p$9q$uM;kwHE`KVY zBA$|(sc+ZYopkGc0r6LJR@0&wD{<&E;l7rm{VKZJsT;TBc^vXbJ}@8wL~dhT{AfIjK78I2e)~}Pezq2lh5V1%dr9GtE*$d@-^`mffEsq>Gl%%v zE04L%b!UiFS`G2JqKn+$BYz{SoPR~!td14Acp{%1&3484Y@Fppny0NI>WQ8_)7STy zKWR29nLJ;#9P#=sV@Si{{mI;U!uTIeoI&11HYTapgmvxjRw=}D*fj2@_zudeo-8CK z&T{ejTwz_izb}LIIJSoW^^UOr8*Z0LX2-nbOZUx2`DHuXax2DV(g)-i$NCQ{%;D3M z^ZAofq0YF+_MvVvGyZ%ZbIcp_C%#nn*ppxR?Iy~nrN+~f0k8(S-$j2p)lku~CnIQU zbK!O7d5=Zp{x3P4N46EVZ}%{PdT!RxW<3sL|Hiz}hQ3Ar9ZJx zgZ6gp?Z+)!Exc~@AgqFdNe{`a>JxnkQSRJs7p`=N4^jNN6y;@mo06hDXYy*#Ow5aJ z2Nk4y{c2oa^V-;7R+uZXG_Aw6vy>t(S{p$Q$5$uWSA;xF%A8EPJP~m&2XCSN8xC<~ z_osVYXZxu*&s!cZBH8f`3%t^DvA?!qOUSz+1G&&YYY}FD;nP(lePynGN}h1upYF4a zBn)oCHBN4h{F=`0~vW3jHUCc1@6lNIDr zM6uYvpfk4bIb=OK>Se{R`fCv4(j_fv;hdxorNbjDW7+FzN`npgF|$JZGl%zy6~j;tHnoVQ*v0Qtte%mLY-Jlw*{=|tM2>Y0)yPwcWACkF^2gf15)cq#)cWuS_-xT)cZyG+J4dHX67Mft> zk5iqYUOwMk$JO;g{Ovyn>B>&2`kq^a^SP<3n(kjBO>mgzL0>8q((m{^5SeU;-t<-GOt}P z!neJR_!g5I{F$+nN!yv-Fz%BThCacm|j z(F>pNTl4Z5H@y8iGQ4IZp7~?gXczun@-|Xhy$JCXX`w#3*>>XEbRXg!h7I8dnC&2v z*TU<5Tizt2x zjX_y7B6B!@De5@R_wvp2c!_8|u^9cHXZqayEje+q4Y{(5qYQu6+MAzpD3gAO>xKC8 zQ%lLD$-(5PoA7;qZl|}Cv{#+Us|<70-zMffiGtU+M4`fbT(I7nML*t5 ze1?wWR)x*ev%b>Jc9Cf|Df*(OB5eO|=1uX(v4r$DX^HceqdY{c57eQ(KaWQKu15#R zRfitb;-(Dox4oo%c*G9Q{-Z0(YwqkNZEwz{y1%C)f8?ocg!f)VJA9jk__zFxWYJvlLqSLoMnkv*>~yUUdJ&m#FXbz76zXx-+#nE_|7pLCT!)JtaJ&~< zC(&`9%Q%lDd&K7_$Z14eM{?S>H{$!Fhtqd9gUQlTXT)oAc67Tajf^O5hxm4JBYL|y zhqMk7?qBI^Uf}ywKStuV3g@buik19_50{BJLO7>1T=GUgqR}Igo+*5;!aCwfLF>?0 zMD6$&#*6j+4n)40}b@_jQVA%63MH+L?tgsMx0b-}YatWGH|9*B#jZ!0kJ@Lo-8($WK_O>N<|)E&AW(I%NV4 z9#cB+;b!FdbG_#`Lit}nSJgabwEvRF_RyX^oP{SmSEwO@8J*=ZqpyD_Cq<>TxR2Fp zQYQ9#n+f$(aYWah@(j23Tt-}~SrLm*YZ1>#>O!s@+r<}+Yk=~y7WVX$PRo7ByN&z~ z%^!17n}cZMCC?H6?LjCtw@KtT+}wzG>B5zqZ}au^PETLNzrpvP$9?EY*F;BQoPY1T zmsfpTNp{JbBY)fa4C1Y7N^BmkM||(&RPsm@OGKSkV%~(WTuj~`wIZfx^N|19DU+;$ z-xfHSBdlMsd?pFLzEpfh+aB$Wn6iXqH?EmOb63{frENo#G48*XIB-4gKBTLM ze?fkn(+l4F^bva6?GMB)W;Eh<(Z6ZpVPSumF+7ESEm}Z#8eRu{-#3LOoll{qiX4=$ zGd6`bKbJ($hpt5Y(T-Hw>5GzHaqNru{#qGSI=v^2%gaLhUbI_G?`L(Pcfa32{6pX} zY8Nt(FL)@#@z~lcXoR{2-~9Rwp4oqA2>i}rUJ$n|O}KA4C_9U;vcJkXI@U-3jlH;% zN_RVwgkE(Kx81aoE=z~+`G8u^+MAwRKo`%-BtI;lpuXL0R?zqt3&^e!!u_E!PJuK! zU^^KcAl#3M&U5EQtqRFctq(mBe^d;wJJ(JmsfX>+pJz+E^8;

    0}(-=R7-^BHsMl5Rx=inuH;;rP}iUE$@J#;e0{I9S*SlPvNN?_(ucTc(-Ak; znJv&+D*$6nX~Q~)M^DI2Bh6T67|mE`il%vyRP_iGioYfCto=A= zJN>)-<6NUe1&-&@Ofh$Oo`-mM-&W`k2hdfu&M?}4sWXnyo;{ihPgrMWz#tf%)fq-F z+_H#E^@}1kgFB(!6JB2AoI84u`b}pd{<&}@DXHh$&-cLsjJxU&N0AN5p#{6wWgy==Tlrq4_^}(er_%<(vaJ?hI=? zu}^0u`5Ymv_nZEC$*+Ld%ZG=y@{?9_Mv zp`lOI=7^W%{wB`1^QFy8h4EX5x{CMgccF!xaBd8-HKq6Aez^LO5Z42zv?l(;cwSlf z2-`c1XiTy`o#%UY5!Ux`c;9=UXFaK-(=_DI%}b_s)!jMGqN8Y!G48g(SX%)YW6T(L zyPftaMi++twQ!un`(9fjo-#2G<1YNl zI`N?V`QnmDN0fI0T~*_b(f&)^^@jHBQT6vV8J)!)qxY&~PM$P>-0z07@Va2u0Xw>7 zq9fg9TOIAZ7PpoU{5_SP$P&)aMJ=p}f9DiFWtlLJ+atbmcOL%6WlWfZ@~!>ebF0@i zB1`(rLcI8fj&6us$a^>1faCmn{1N9qX)bxwREzw@MGrZ%=p>T1YXah4R`<9cDf3C` zoG8T2=A_ewcmENK4()bfV~Lm=!BuO&n}oL&&hNU(ef0y(ekZ51&!V5V^l2~tz4m>Q zwCFVA+t&6K+s^unbUJ?aLt3ia_Cd?x78^9P(w zW1&5_B9D4{Y}OyjJBadiau3ju%^CVZ>4y>Da%n&PZqtR|(PTd2PW~I{*^{66?7L@h z{T{PpExnT6kZ$SN9rI2-aR%KblhBO?p&YYk$*^P^;~hei)^|hv>HTOL?5?757c&sw z``aIU!k`R#c*1AIZ4@==UcZG@RQCbm$!VwfONooAUA1b0|7+Os9$=4l-M( z`fHNuhMmHFJI~TQ&iX_)wW%xA_ivxY#HGn*>Jd|d`aUUa$&i;(H1?%4wzq7skUKRp zo4%IASqL5$`OQeb>UF8tBjLPwP3}d0lxA_FMZ*3e@J%F{pn=bGEE+?ZyjAxxWZ2n6 z`qg|g;`6M(ad!RS`{@4(M|_d9if_^kzGHo`6XF+VbtXlvSCQx6TO)4F>m8u$XL;=m zxllE)8O@m2m%Iq!2e%>8dMcjT6Hxk!*ZFYdspc(?_rr)++_^!Md9M8k!uX|*j{Lcj zDPp&yTan)fbXCo3M*A;$?E>xDqw4)|MrV1==n2n?_2-&7a~ER9q93MzJ;h~M^ya$N ze2wEcu-cqUlk5}MA36;A&1atDN#SH}F&Tk)C$}7NuO`R1<}H?BeQbDlC_TAh7dOsD z*!QV#DQV4}yWu;re?|G|=aKx8S68{XDLjsQh+jUHpV`CNxO76kF7gQd?6{AMGqFYd zYzGltxn~il5d{)9mbf+NXzKfA+&^K~$bYXap!*VcbC>@T&R-dC&QZtr*<9`i;rz7j z$u+txSH|^;^}_L7D}sAcVX54?I3cc%x2j8BoD#Xma|L|b%WL#qqK;D>4MchF)pK4^ zZ9S)m5$@}ey!-r}piSI$e*ymxRU+QF%ZxY-7w#ka?^(;;hwoKNDiG?<=+tiH#np~v zbfF0C@4psaH)`Za+V?$!5k-eyqk0e7$&o%}X=0APf245V z#%|tuGGKOlPJMYh%6IJHL;}qA=(jy}L4R_=hsedef4FfW8?dhY_NoKf>{h7X7Q-R` zVUY#da%O}6KpS7gXY71YFmZ%Ez3eB9&tqjcZ{B)StwDYK-&oF#ZVlhktFF?dXB{I{(!!w;ntZD_@UB zd;5W|s(Hz1|0OS7p*?$4y)VS*EH4>-R=-%@Ij0>793nwKe+z!a-)Xgg%N#767iitF ze9L9-BsyN0hwI}de7lyXIWl(=$}e|<_lIV9aD7!%5KlO(=S#D?^102N5szvJzp1%C zUTnQpcwH-OSbg4iO#}L8h#L7N)n4njbZbnlK21Q}I@_AR*cftZu)t3Y{H8Z~+?sxe z-yvdSnc=?EbyIX0{r$#h#3Rl>&^H~ln(6}IYPbVYo~pK5-jDvS2< zzKM0C)!d`Jg?c6}8SIIEfAaV{zc+Cx{q0Y}G5uC2EoqCct?9JVBZwCaZcaN-{GD$% z!<;aFwS@Y#{p^way$B(WrarsKt4BMK<=c0lep9>J)J-?3;Lj2n%G=xB;xEp!<*bh+ zA+Frx!vE1^9yy^A&Kom_tmCyQySWSTYmvXjbRR$B{RVD_el_AJvqtkBKFuMUV&l=C z1#gG&OEx7D-!Fp^|9yEczE5&0IoGcR;>)}4((il=pZC*z;F-PIH$q%%-rh+HH|#}x z+^{^?y<>KhbJy1(UbMa`e`&~ka$-PZ%H*&2uTN6ORi}2X+hPBwH`$T?-DCI^rvTJn ze4-!8Z0gA!AJ84~w!9UIJ{HRli4^XWjGft@a5Dq>xh4D2AHTG5As>4_;4(*EL_BQe zK(08%hNfo=>ucn4_^vx~H`l!y;l5Sh>nFMIc~8YrtDB=eQQAJlxAWgzM!Yb8Pg+@! zs2#n?Am<@yf7GD5`pxQGvQ@tWaW8-Oo|$b$A~D4H4|uSg4FaOSyPvlmATgm@`6L-U zg-g_uaJg=xsB289RHBnGl1ibFYvn3sP?SV1(^jMm4vUtB>jaWgtJ6s2O2E2C$TeD> zsH;K(|6@WU6e@{MJF3?hxRxnKIkM+4iB`^Z|l*f7{=4GAPAnQX4l{-sazQ;IID7)cnPtiP=!kr zK>#4e8Ym=6nZHUCBT*PJFj1?6*#%r4qgKcv_%P1Ap*UVb91xA3z1gNxfHY@HLjbx%Q{D0F8VHYP+#2Usq%7KL~ z60|~`fd$Mh;5eN;T&8u5sDvR;u9PCnfw3G7SkK-Su|5nb=ir1JBh4`XA%-59WQ

    ukqgbr5ktHn!7zoDgoV+tBq(do1|O?-Prxz} zp^!u}f=n7I3$YLB>CV#Ci1!R}sDwL&*b6vx5hc+^1xsLTtOvlAvIL#s66dlk3V=6W zHn9xF%z`-bR%_)7Okozf5=}WS1CJ`$)W{Noqcq?Xl|pK;$V<*5I$TzfK1rrgxoc#S ziZo`7A=1k1G~nQh5Eguf5cpL#kzGYXhDgG7keldGusK%ALO>=BP_fF3b88r0WsWex zjD-<4v{Eym8PW-78PtYpR1&EgjFJtMD5cD1Vb!CClTdMVIFmIU93S-lw8+e!^DLe9xe@vm#K9@>L{5; z7Fbqq!liyHCQ`8%@SOYq!#2ZO+TRe-axKJ_G*}YZ6D$c=!Tc&gmk$f2azlf35}k|* zpf91UmF1Hxd_2y8R5nbmi$WEK4uqxIP=@8oI3Fb|Ba&b!swxdm14u*hsO)gbPkfAC z?+@0fSo8=@%FswyI)u40T!Go)GKEZIT>8qp_GN1UXwa#25=DQN1`3k_307$)V4($J zSZ!o}5-kgNp(`&*j9OSd48~O;!1BXfFHsn1WoEI3N#F=EW#E_1QP2c7mU1aWZ2jNF z%6bzF4N}Nt%+j(>SPz0ff66K|v3x+R0o1YRfnv^n`RNEi^g-OE4Gt1Pl*vh0nG3r=_md%7TEYeFOi8mA=sa(s-W?6b` zJ!HCgnM?`p950i4sHAeNO)8i#ja(}8kBtdZDFE?-WXGvz6Bq^sZ#;O!&`Cwd$hF=| z)&UE29qcB`hhPXt_gF8l*F{vgn1Y*!3Tk|2*^q(x=3TK46Yxn zRIo}S!`=+j3<-;|9K)W2VM`&?RVX?!k^~eeca1_7FVpzSW8`d?60261BML?gQbp*L zP-=h~CYNZ-!a^fcND|N)Wh8ApxFZOXoMm$v;sA&)9###;foo}5$P1A*v~rg$XMHQ0 zWEg5CF$1lV9Qa8{hkttuSc4-Xv@#teX8Bwg9o$>0iZINJR;_^{7$$F2Z`{;Rh?Ohk zVH$aC46Z{0RS*o)$s;0|b1D)I0WXjY$zzm*;TudZYYL<|l_EAqR!)J{CkARFY{_vW zY1q?&pjsn~lfxd`xXoj2%hwaAO|dbsi0EWeV*yecccT&rR@S)=77tcQmBML+ZQz8> zA6p!JWy(mbvteN}*xcc!wxS>&ZkQlj>p@Aly|8bpD1!$fCKG~#Vp3TASrmlZ!#~`Q z3a)3XES!*7!m%hesKFDG1a=f`zs?*GCW(!Sgl!?_u|~qS+6s9Di&pT5RvW8f48ezR zA)N?&`ASPB?4hCP>TulHAA|r~LkCJUQbS}z9?M{(`)`I8qW|Ai*#AVSG!@!2u|PHy zPerU2X08hBSA+VWGFgKCyjew!hI|czy2eJ%I;^bqCju2TSK&exD4QQ0Y!uib2EAyA zrb>kl{D;d;C8AUVQ&5Q#E{v`cO`}3%4ca9WCV=U%4`9{as1=W2@iKX26dtu;A;10J%%%H}vM!cZphIRW?Q7+G>Tw1IUto;}COh4OERaA{>!5eFiYIA#iJ(a0i% zlVEvfFkTF-*2ax0MlDnqgJJ$4X}Dx-I$q1AtN}B^@T@Ge0*H`Q29ppeFNEbaQBr;h zH2}^On1wK3K{7=|*@9)5PSB$L3AwBwhqFMJD`C6F;uWOB*@hNR!N%FbI}$L?Fvvk% zh1mrzMlepHG=xXQKvUS}vhED=2bn3ugoI_lIA4M^Dq@QsNTV*pbu`<=;|eZJK5VH<2DGBbl#0pO^SP`79 zB1N(IA8!+hq<9h)#i`^{5iTY&4IauwVY+~*iCTHMHfSQ0j~J0JESDZ|KmkSw+=EhS z9P#vnt5g|DIQAH5P~bH31jmF*f@Q=?qGjioiaN`Pl|t0KLUp0YG3KdFc5*fByL9>DIwR3t<3{^=bP@VN0_ ziBf7f?}X|6Vih{Ma0aTV#77C6HMn(WFgS=!^#4YKdmL)W4}-WTga|gTOg7%pFe-)l zV{0xWgKn9I#lC?D4Po1$kTG6GyNq-;IdC(>s0k0vMqbr6o^T9P#VVz!2k%H2&8)~U z(k4PG!acHzoq9^t+E_&;CmZ{!5F`VjM8O*S@7~#T42)G&xOo*;e$Fo84>CK%7) z0Utnd zYQ+;k#lcnKRa6Y!$%5Ioxx8P4O#@_b+Led*_EN!uP{sZVydd1m{!1c=EdUjE!Kjq& z6qqBSVBog15|QP2B?2p^l?be)Rw7_wEu)}Qh1yz1W4(cGP)aM2ASo+rGE`v{f+RQC ziPg9Yt=xIRzTW;O@XB2^_%k*9nM19%5Oolli>yU$;ZvI9L~f!PqK0r40F+=+B5-@b zUqhg?Hs%0r;gvpDQ6G^n{56FuSCDjrPsSITd=!FbN6{#224x!>e%YH9u3ZuNK%>2XIEK4V2oV8el~=pw|R2 z6Ip_c8CYTk&*tz~7oIJFV-3$%@LUgM>q09_&{7|+t>M}Vt{Z?ZQ_y4zoN7Q}QVl_; zB}iC8D^rj*MX82hNhA2H2~ySo|K>FY+l)F)MUCNmXe>ZS6M&`w%|K6cfEEBP0a`&n ztwE{{Xm1O6JAn2eX#u*M05k>ocbi6rHb!~Ywi)!xUI{e?Pr@e#p_dv!>jZt;0(1ty zbV1u&RHAnUdN*ie2i8;rx$c1X0IQgVzW~i1uGlx6bc7yF;MxH!Wl_SuozD?^W!G#@ z9l>&VF$u4oUJM#f;m;JjKLF$h!j%um41!UbVtZTBuW;py?Ye+p*jP+O ze%MFXDmWXxsmLE>2Ll8E41qqafEEZ41l|dT=b=Ck0T>1_9AE^%NT81b7!5E6U@Ypl zGx(Q{f!QheHxxWu1MRScOtKP5Kt2rQ!@=84Au^=^GO#@YXf_aSkpNL3CkKcI7!Mv* z0K@<&0aO5LfC&H^(4_^?0mK5t0mK6&08B)iegSV*?V}#_Q4jjCggz{x4@>C74EivG zKFpvGGw8z%`Y?k&%>F-p*h5DABANtQGa2+u0hkIf4PZLJ41k#cvjAoTB!a#<0CNH6 z0VDw=1Ec`V2S^220Jf(=OPynC@%pWqp zHdFx~`k??v0geG22RH#TEIv+x+$jJjtPo7rRCF5XXW+RIDh8|8Cs2o}=q%9BLB_E) z;JkrW1lR?DivYi&9uKJ7bw!sz<|4plnC~kthw*l?|+yy8BxCd|_;4gp&01p8k0Xzo%PXPV~Cp`X4uR=uu-P zoie@i5uHZ&A29y5Mp;?gWMyUbmLXr7kH+cG_ETkct%v48Tn6EdeV{2_I0XLXKzft|h%M{FfJIiM<9*^!nY|KvS zuN`h{*jn&L_a8nWah+Xf7kSKj$o;6aqUQGzRf!o{l{NBEJ}PT=eQ`;G&phIz=#T6g z^F`=Cl_?kc>#tcy4Lz@GU-uY|DRc9TM)|uHHQ=+FCI4}a^%oB|8m}#}8XNZ(Iwz&NUlS z9P>5@S&dZ-Hm2%(%V_b?w#6 zyW1Fz-Va%ggBG{_$2C4!GiD9P z`uccgRNHJcMqd={Rdz!)j#AghNqa9a8i&re8aJ(4&|nRHeH?RVwbAHwuho!q_aE0d zvF8S(vFa_WA=ltPt}*z+<_V6+vZnSr|GaC9M17BkzRvYtr51EB8YP_rPi(M;KIZSt z9&9uYJK1W8x7S;vuIr;`VV==ga*oxQ-7Hyejk@-#Ag97;EV|8V$ebFiq4#Rp4Yr?8 z-XUpxS2Suk=JZ@?z2>8#{k-G-wx6H%d0q_#T|fUPHGW@h`}q^At%mF84bjlOcAFP$ zKR@bntKs^2eKhnj*Pb}qD>O?zXE^ zc*$;CTMgIG8=^5pd3#wu+t084D%YG>uAkROLmv;lSA&jfYu0hb3ajDz`9G=gYSXc% zpFgt1YIIEZ^ZID$3KVNx?)##V*=k?Lhd!?_Bs#9z~f8*LAB5RHNAcr?Dr_VbR#R>Sr4hG^(@ynU(d z=bv0+HC#V$h{iCrj_c>!e%|*^t0CulgZD~bAN`)O{rq38h8Ry24b#u*hthh@M_v6~ zU+3D}7r$xy`M-Z2Tth+jh`rPfdMT;8x;L>ud;re+)H1zS^TF>~4cE`>qoMaoYy8w?qq%4J@jI*G`gwgc^j>L=b!%-u|LYKY4Z40_ zAC0=!@!^}cpI48v8m^x=L_;6*7uVQ+K5U-VklLmXHbg@|H+X1??dK2OWHnqrZ-|Dz z&JVfS_Vc5wt%mGvgV&+=D!JbF^NaTHXgpCgOs}O^N$WKq_3h{SyxRD??dN-KVQad6 zULTFR&Z{T49%B07Egy8KVbUB2?im`Qp?mG(ojV$hj~}uc)UL0Fz6Nz4e7vRY=Q}O1 z8m^z$XB}EYpSuT-xBdK%F;>I%^M+{XbzHyD_Vb_iu^O(Q*GEGibA3EcxX1SMlee%M zuAetVL!Z05JYxI#=(i6w=auW{4bjlY<3FF;em>)ItKnX6Z-|Co$J0;R=jVIeZ#CTW z^M+{XRV$JJQXy0|mf;PRSJLN(@pZl9k|ZXH~M_1dfD%X&O))^S8j`J8zj z7i`(WyuLfFlhttjJnlLUTe;{VG=96O?IU3tO+UB&{QlWiLu#8I6<4GEPn#Y@W9Vf^ z1nbZ}YWzF4pU=C@YPfzLSA)5uVL#iw($~i)FWP=ywc2X9e%=rbeVxC$#`g1*p0gS< zr+V#`oqz3h=)Jmpn@ZE8KIq({Ce1fJiauf=*Zuu--9Pke8Ee}ljmF?zZB5tD>!YEM zht~M?K-v@Y(GDylhttjJg!FG_G1obuRhr7t6;D6@wnkb+s`lC!D_gE9#><>x#!3pRi>`( zzFV*keO~SKz3u0JeZGr1uUtQmt1+U<)=SY?++|(p@u*sMb&bW0S zb6yp{azm&_@maQ?-@M#vxaa3_H4gmcVsl=t>)HGWcV6k^amN7L&o6#3*elbc;%cm0 zSJ{=l>U8%0frh?kIQuNy&)<8*YPfzLSL28wzZs45Pi-4$=wtqJ=T+H%$ZKR1zpxsv zpU2fGYI*T;*74B)^^(u_8q}}7Zq?I1KR>dWJ$K#n^SBznJTp$Ni^|k1D@Uww8hRZk zZ`UI6rL3d>XshA+d0dSzQ;*6XRi*~-c)w_6UdQa;Z9ji`memkXG(9S=#;x0Tk#n{( zwPn|>dN>XJ+@Qr5wx9QT+-kUf9#>^8}!}jx2*I5nW*K4m%yYfHF(75EXtGYT3y;p~}wEcXynH$sh zFZTI49#0M*QP0mO%($mJ-hS?5_Xb{~uk#mr+kXDvgstiNd0dSH4sXAdb*$g@U%~Ov z8qW-|{ruhSt%mF8aW%epV)q`bBd^Qo(DQ2JsE#$S%Jp&6stsmuTtAPi@zx$kb^lW| zp8Q|yp6n~VRv(Yl*cLS{Mph+`pJp{UpXldtHFoUuNDnlAKQ$GsL-*RA&)a@J>9-%u zI;dSAjkfutmj5mqIfoYq>(H;gHhOwh>KWOqZLY8yuAj$U$F|2l@W>|7`17=^Ktp@` zMPDvR{U{nAbhR3;pU2gB|C;efpwaluXM?@c=T)kEyVOB)JU;*Md$U)rpU2g>cj&OC zXdHgq=YfVk9^>baU-PG|W6u>#>*sMbHg1}+0>4_m z_}5UsI_c#N+1C!QN*q2VxCZOBSJ!vjzvusC9V5#&gs$V{#w`-x%Q~LTvR>l)dE9l( z?)-3%b)xZCkE~wKuk?BK;?ErtYvp+Sd2ir}rborqxOvYB#;?X7xB1-F$Gqa_!HM;< zj;ZHc4cE`(YV5PF(F(l1HlJLLXq@gAMs@z8tK|ixqKaZ<%;C&bL{7N(? z_q;XG&^_w+f)+LV$aVhNdDUkBT|bYj(d45`dfXuz|N3-Ha1HA7s?COtsi9-55*v1~ z8k|q`^SByC4-f2hsA$ZZcTS+8*RfxV)u~3Ks}kouywa?L+V#q0g&l&u*9cMAk9(uN7t; zuAj%%$bb0PBl`SNk=jt$G0@P*BX7eAYu*)&yyvWjdww2QW8&6bd+a9~_db1CprP0C z!l`5WPCBkCG5ijz;hvwz)tLX}={>d*jSiC!4>a`kF?d~@?CVA2+w+3GGCeA;M(YQ6 zSjjqCS8iU1_N$kMFUUShuE9MowHmIU$JIFExkFbr`?Dg|e!Et|I`r{4t<9?J7sX5N z-C#AOcD>ed(T+c@Y%ABtob#>^t`B`Y+BDjj-CnNqvktT8u3Url(#UP}OV8az}RiY*U#hb)sXgg_xMCKj{m=J1HaPixNDn^iPpoa5}mKI8t(ad zT#X&dUt0P2ri#?}QyvS}p})s6yU~zDmR#p!PYAr-+%v@0xaq0KSH2|c=rr zFX{GMUgB5j=kIp38m^zm)j0dVSDSl=-FGSp`nlG4_D5K*m=8t9#^C4kwLw75RJWV z|95a+>FZE{XDM5=&LU5_53dtsWEA|Sq<0E<7!-Y*Y>@a9#fHe z@YyQ^4ZV)v2dz$Bbw^d=lC|^9I=C+A=W#XO7}~V=;-M9(wI!Q1w3j?Ec42DI^JK4P zS`BK~M`QNVcGWY!oRgaL$*N!-`rN(o*LJC`uc=CO-NkCSejaxnzpeYW=ZOO=QfK{j zb*RRen@(EONY=6R^SNfP-1GCe8XtW+ulsH-D^kzxdta!=igu&>_PnktF=DaRaL>=< zYE*spZqMgWs7Q4md`Y08uaA{$+GOu|vHZT;ZB|3}%JitX8cptaedYSYDpG}sTLKMz z&(LPfg6yj=sY=GT|ZQBTv(CX?|)iG8xEd$Dy}suQFIJ@PZrvu((CgT5r;dqhW>qB~7#et@=}~btu3mFt zuT$k7u33k@15eb?4f_8&I5Au9ch}?u-d-<_EkAjpdam5Vef7{w)nT4E{inRdMCnm) z%J=Z#xPBgY9j~48#0u_xrVd&k-23S7vApt??dL=8vKp?R$JO}psNa|KI>WG^+Vd;t z8K2|KO84`&@3%4Q5RDo<5#J(*kEnir$EH`Lk5{IinpW`u+)TZ;?+MA8PvqXGyqT@( z`gvT9e}DGa%6DZQtrk5I?3F&RMxHjL<`TJYKclDBaQ!^4#vvap>Rl|ow)q|T!7rOyp7&q`go=kbAt z_V%BzU7gyebV;J-seQ~kTtAPivHOYhdtWzgR_fDllYxdl9?z~^n3^l+>MPe-4X%s& zoV!cM?$P^`AE&22eSJZoq0g%auH85FL++Bqtq1OH*1`PiqjB`|R;$ilG$S>l;+#;8 zM;1(2)A&D25{V{O!#zKbyH_KxJ*QXO@#U%a_q{Y!qx^NNv*x<7ynY)u`&NHkPGUymon@p}l?I zgBE1B*?mdktoByJ_4BwIe}0)-^~a{^sR28NAM^X?tja$2oyCdIXSQ(}q3l83xJ@W0viEr20WA6HS+;u#;@PJicEuWbxKD;E*(C2PX>E~PL zFHT%?w!O|>KaZ=CyY;NqEoaP5wJI1AXy|pkEYHu+KA2r$ha?^rjZ6O1&KwW-dV5@rJAZs<)mtxDq~2`$NpR1g?|mNpJuh*s z^r%O_w%+dgd0dSfTRqY1b$OlPnOzzM&(HPo81a+s=f50e*WvnkT#bR>-({YkPi~eU zJU`ca_0ECz`T3u7Mz5hCyMB(R*vHZR{Js~zG_SWG{rQ5>bu^lgtT|Qgea@{o&eU}M zoaZ5NG)_A4>gqw#&u^dEBKZD?-mB~rht%BOu_|%x$H$wRuAj$U$Kt)4^||WJiqxtJ z2M5Po_o#<*JJvk$r98*kbb`@v{XDM5`y1N!U48zUsqOO*4bENdiBGlOwPs++gNX&N zO)wg+pU2fWdquOpr4!CbO)YNHm%Yu@&(AsOr_{jhmnOO{&M_LUpT|8O-wwX3&-zEt zOwIXy+dxCFZB?Jhhc)oEGJKttdAY|L4dI&Z?V z#KCvv84cIZwVhxKJ=s6sjTac3Dx+|Iivd)Em@YR zxh!ckTtAPyjx$?bxN`jyGgH&OYf>4 zckJxc180s6G_+sMzGOl6d*?4pJam^`hwJBYH6H)$k(GD+JR>#lhB<+T_V#wUtFtE^ z@^GSP`_s)j-1GCe8ejdqZq@W1W~H|8J~hzL=T*}$e#~z4)^}Y$kE?M|Dz$pi z`*Tva5Byi)?Rp*SzRgQqCOv9a()zCJ=W#WvFTZx>4br1l6dxPBzN_zj-dkt;d7roK zI$S@Gt1)zaH}jhQtIsS8e&$YJAN%ZT`}r@`_PlWYobRv2>9uD+TP{7eGWGP6Tgvz9 zZU4~TUfw-f^Nj4(jpN3fny#PYDRDF|UNv+D-`hUC(e1(aKeU%j9XOPpt)Qa8|0% zHYcxkd!^6a!+&p4v)}a(Ca&J&Sfk87`Wj{Nl`+3}TJXW|{ z@0UBwOm*KdJJ8VgK4Tv{w(sk^Je+v{l|e>>+T1h5T}RL7ZteBNp|ev@?L0ov(AUTO z9olBsY?6D1&yO}5uAj%%IC)%6uW!cBOl^7c%s@kb|Ga16g6xl4Kb&}Bh}|pK&*N&m zc4epPbsJ}=CMAai8v2;8K52FK8DA|+RCl);uAj%%IQfos)uVTvmD*)gL8!*sOMcA0 zedE%^4-*HPy>k6LuExf8kFVZq_L-@zPTV$Bqsv<@67L@KP~yOY>^fXOkE`*{)w`{k z_x|kEpD%9{s`2#t4vCI0FHT&3sJ+fzKaZ=?ZbkPsvrjuC_2Y!8fnVukp8M_K#Kpz( zJgTYHaQ!^4#%C9tyZW{X6{(H+_pWk&rLT`RZ{;P5kF82{I%$+S9+5`5>E~NWAH4o;>+Pw!BZ%KhH>g+p1M?4eEP_ zZ(iJ(dU3*%#9lpG84cIZ<7%9=%bmSHs+yg;>*C>ohTf~j?N_IIS1d`q`C?0>;re-8 zjXgftvAXBt8L2^qXNPKB+ihX0-?mE*sOTG3l?ndwsdM zH1*Kh>jDjZ%ukcQCv(stOA^%`tp>I0vyM4cyY_zT`SR2^TVEV#^i{uqe%j*;vcH#e zcU%j5JX}AIyN>Gy9=>YzyQQi5k6s&S=;QI-qpPwdid45ndj#K0)z`-@ujC~TlwP~b zA=cYnKaZ=??+NQ;e#`Ur`S}Cut%mF8aW&rA@dWez^R4%OJb3P` zuaA9hvi*sMb zuDSFlbI~FY#ZgY)>>*sMbW_)#8@6XFCQb%8XcA%l} zcc(O8mD>K6s>BmtoNY8*KaZ>N>euJ5y0NwVeByn#2O9c#JW{bB)m47pr)*)R(Qy4d zuEyfG->$CtcSY)pt)>MU`n;Mpy=`j0tE&>v)KnM^x%NyykE=1a^~zq4msF&hd^|tU z(8uH8tH-T*TYi>vzw$XogV*2agK;%h-ZQs)_iHLrudT`rH1s--Icr?sF|%c_PO=(2 zC#a7`&!-RQJ$Z6P>XN^c?6)qgO02)sYT#4#(fB%dmzC}2RHTN!Um0j< zPyBK8g6yZK$#a}6dpy{q`e(FSVoq6R_^LyLBTpj$rnqJ4_C)(%d?_6nXx_%y4Bd7D( zN1(Ao^X{Pcq( zhU@2XHP&Qz>)A*&a=w2sxKGp?6_+%xd0Kww=Z+>T%{p8^kE`+0XIu8z+S*<(_iy^ZnVs2J6uGC0RAqspfJ#Zdmn* z(U97v560Cvchn`-pUKap9{%UrKtta%>{m2Db%z{}U)DTqG+aNAtFhhgU7OS$ay)+9w9II@ejZn&<^DhQTp-8e^dTn%>(Ixe^A*Rg883VF-yEyq z`gvT97mBx8xluI!cjcAA_oMVWPG~f)Z)5qLpOP}G;re-8joxjK>2N#v6B4|18IR)tN1VW3KOahg^}DxLU5kPOn=H*U#f>JpMw~O8y?e4aEnA z9`k97Y(M{YwCx|RpU2fW@b^CQ``VSM@{1SA-<7f6uKW4QcDA3d`gx-{9G3YH8~m0}bu%i<1koj}VPc_gf9u z&*N%Lx%Yw|o8)-R?eT1&q5W#!x7FFriZ|Uc8HSWr5z48yy*yr&FLN#8h z-jIDh$9(>`?i#F@#>5woUAa~?uKZ7<4^BKGue~0! zyY)oZ&*N&mH}%GqpNhuS$KDru4Sq2@FTrcbvsPFQ*U#f>EO>9B@x&8zR|fq^1hm5{ub++Q7sZ2GvS-(=NxrF^SBxdTg>l<@9uSa2l;!#neQ2n-$DMyytnKiV<=L(V7DYvXEkZ?}{2-Kig+FMF2x zzGUuz>ePQ_9XEfyvss7h=W#U}eS3@fy9U30x+qwOzGs+mz=8to8D}uFBMkH%lLJ8v1x#v&XUK@4ddi zekZe6uAj%%NDgQ!uUl27cA525uvgkkx_)o}-s{6}TMgIG<7!OGzuX-2<_4BwIlMlUL z&RO}}ZP#rIH1u9oKUjd;n4qk?nS^xC)@r(7|_+>5rj_xjL&zVq}A+5FwXZB|+h zJe_-nxEj|FpJe*S?MFQvT!VTY&)wKOv6X0?+tgm?)UJ=lxA#q5&b`mR2ma8*9doTw zTG=7N-^_e^fz@#RJnlMHoN$cPu1sCuDlgE`$Nbxq1}A&yw0GH`IS!$GWQIh-)c2nKaZ>N_{eFpN0q79zL+QeYyC?9 zyiemV4>cNN`&bRBU9Y`5b;4UR|H{+@`!12!8!~G=zhM`n(dffN6L4HVkGqc75B#DF z8rMJYNjLH{9gj^H*nWOtuGMh;Jg&y_mz$XTtLYuS30=qZ=_^gI?flUp3FhJYd0dT( zd)q$9c~$d&y9dWy|Lovag|?rcQ(-k+KaZ<%aY3i0?A7W64w27xuk?9!S;anP9dmnF z4cE`(YS_Bb*T?sdjWYc_x3Sf5{k%RJtOG4RIOcjCou*DO@2~dzm;Xw@as9j@8v6R! z@ps$Lhkau;TtAPiF<_@X%ys_K6L$yauKwAmmQ(HDZ!iDVYPfzLS7Y*#KbyZp-?;d) z;ND03)$Q}``=5^)5S+WF*T&WOV6VpJ-e>PlRe_i239)Elmc%t5`(wCC8^KCz$Cx3^Rny#P!lN$d!+xGJ_uCW@fpEpE9KOY=< zvF+!rdsq!Q)~25~L_Sr4hG^(@ zd^*JT^FQ7`+N{I%^M+{X?@f#wGtaE!f-9|t>*w{+(D$PH+#Pzm?dRVeVKrPoua8Du z$D{Xk!%RPawzbu8{k$O>dL8Ba9&h^jPHzr0$HVpW`e^9A($~kS>+SooeE5mgaQ(bK z8hWpEkGkc-`PuZSjqh6x*UuZGq4(;&yKO(;w@YyDntom%4ZT-d{3`rif_jXRcD4Qe-3 zL+{o1ALbg3Q#V-+*UuZW4z1Dl)j39E>;ATX$nk6NI`s81td;HOKXgu->s&NUk77Mp z>5saepVxI>?cK`u^Twa&nVPPjH$+3fW_jA-wx7R!zSWT9Q15ldxE0Gkx%y(N@Ft^M+{Xe%@x}3Zrq|>l4j7 zTtELOH8ve;`}x!=tKs^2eKhnj*XPx(JML}P@xc*R!}as}Xw-FmT=U2f)6W~Xu^O(Q zH$+3PqxapXn0`KRO^!JpuAetVLth`u53v3G_>ES>_49^kXm2lRW}ly5ves(2e%=rb zeZTu}`ME3Z8EzV8kB6MQrk^)NLtleSleV8voo+Q;Kd+C5K6mvxuC3X{^p6*|vDdll z=k?L3>)ie6E!)q(oMbgzKd+C5UWY#B=iP1l`M>Y88m^z$N29KFR9D%4e$)o5L2d3C z>Z768p^tf^n{7Wo>k!*NWKQ+g(Cg59b?#GV)o||S?_6oFbK#plh*nnmqrUxI-!nY( z>O`aQ?VA;*rt9bbq{f@;jy4*_XIc%{&+DV1kB5FevDIIP7>!ffS`F9F>!TsuTCa<0 zjV{e>Ki}f1IcBe1KW~VJJ|0aTvHkp`p;p87^M+{Xbu4>*x#@%dx8W?a4%g2cqM=`J z|N76lMq}ljR>Sr4hG^)$8q$3)qp_gEYPf#>Pijo)J=FB`=NelL*U$e+jeajoH2wUt zpU*VM!}arqXy{}9*%S8l_KQEX8m^x=L_@!xxN~3I&$sJg_saG2hG^(x{#45L^JTkQ z4cE`>qoKV-YaDcg?dSVlWHnqruaAasQ(5VcOy5_le8=|l4r{H3>*xQZMwe%8Kkqoo zdWq}j4bjlYeEc=GpYMB_)o}g1AsYI444-TJ`M~$AhU@1I(a^p2&9iJj|7IWCKd8+; zLqjzDz3Mlr-}uYNWo2z8=Y)JSCM%~&R+jv4J{rltM_m4PUmiHDg~H%~{aR%IW(Yj6 z#xnd|uw64?y9ws!lDCD7PM$6pJii_su%A3#F!VKV_Y7D|!F*lvwp2VYcz!)NIv0%n z^XCkzG+sp8C!CK4ExorgVbIEHaBjKG_U~Odhxp2UK_s%P@ z9c1{rU~OgS+;)Qby5#LB!`B6a=jXx!^L4>?lHu!u?JGm)?kAY9OWw{h{9G`2el8rH z3$}|4f6ie0%h0(82B9^RsT1MHv-yn_Yv&o%P2Z-Bw` z=K@FPg5ewfI>6e?(7FE-%wGq2+Bd-9`MGew{5gYZ-vB#AhR!`y<&uX-_;Ut>=jXx! z^XCkveFLn644vCiFn`YEY2N^Y=jX!FxnSBiz&d5fJxnlPmpttoVDNlhI64;$-|+Ve ztg{TAE8i5awO8b|k>Tfp!Si$B=v**-!@st`4ws>Gy9(xCTjb#pzAhL%KNk*|e|*94 z4PO_mn+%=XT`*slJUqhJ1%v13!U6Mj!SD?~7wiaz=fz+>Wcaz{;Sv6v!QlD1aKQXI zgW)BZGpk_>%jr@eHRSh(7eGJupxr^b0!au@O8o9`Ssv{`MSn$GVqScfDIMQ z*Trw}2wwvXo{z!NxnTH)KWDIEGIZ{6!TdRshnM&~FnB%&2h5){*a*eLTks9vo4`h9 zz>XEnp9^_-gr5rr&&S~CTrlk$V52hRjuy;6$H_}59vD1d7Y>*|XE1z2^TuSrjuXt! zB~SYX7(Blo958>*VEBgSjm?0K6U^5o50CJ3!QlBA9Gwe>Z)o1}8L;t!`MTuc5q>Th zJRgIjbHTK4fSr&b_e8<`y&_Nh1{geF7mm&a!#DhE3+yBrI(LF#evcJ}rusp?s1LmKnVA?mpk}`Y^ut_rfT=MV;-#fwJ`MGew z{B?k7-vFB|L+4Hr%-1DP`vw?1KNpV91;aP|IfLcP(7C4x=Fgct?Hge5{9HI-{+z+I zZ-7mep>qpVE_vEFz~K40aC9!1_6@LU8FC8+^XE(+9^vm57(8DW4w%1JVEBfg3sxjU z=N1d*=aPp<_}3N~JUn15}7;Tyg#*y%EKZi!&NE_rx_uL}mx&xHf#>w=vs!`B5X zm7#OX1oL%ImB)C5p9==h&xNCN!SD@#&S2#-bnbM){5g|{m-xD1@cdjjVE&xJW+)!s zqJ0BwrVL*LY?cha9(md~z~K40aC9yhzM*-uGhk;3=HJ(mr+otqo?j0Rm_KJQ?Hgcc z%FwxIsa*2#2%iTA&&S|^`Ev%-z5zBzhR&@J%%3xP+Bd-9`MGd(E|~TWuu2&^_iVv@ zUGlVVfWh-~;pkj2d_(ij$$-rj%-<{W@CZK_44#j{(YavwhJS5=&6A;X=L_b0CwX{; z&jW+!V{pLyIfLOFzAo4T89H~NV7@MSc!bXbgXd##z>|PZT=KMU zfWh0}P&z z!2$E<3|1*a^DfJPT`riPOCBEK=YqlWF*rIG4BybaD>7hL3g+vQr+otqo?j0Rn7>zG z+Bd-dBSYt2rEw;}BUza@X8({GKTsS%x4BznQ40gQ?oqK~|{+!9vUIGTs&xHf#&l&7S#lu^) zZ-CvDfp@cD{<%h;_6;z2{#@YbTrhmY_e8K;Wa!*m1@qTIp7sqecz!M%Fn`Wq+Bd*% zlc95OSGnZj5&oRP;Q6_5!2CIbY2N_5Lx#@1Q!szd=fcssVA?mpR%ggvBbYyD^6&_M zufX8>x^Te!y#m8G{9Le<44qpen4e1?9^qeGU^O!QTsUCX3mlybhHv=m0DDe`&V61m ze;wp$-vEQ>=fVN==M1KO1MCGEI`>7DOCBEK&lwD!p9=@fpEH>D4X~GF=-ihD^XE*S z_6;z2el8rH3#NSo?3E0;uL|btlBazG44$tGN9Tg!8~$E_y(UBFzAl)*SLD^m@N>c7 z`MGd(E*QSyUt3^r$k4fO3g%y1*|XE1!j*9Ch^hR%IkFkhEEJi^xn zgXibM0rPdi@C`o~>>U|8_g%sKT=MV;f6id={9HI-{+z+^5?>c=tqh&}o?yN%d0;*d zztO${_Pz{X0}hy94@~<8*atFn?uROuJUqhZfx+`JIAH$kTwvNaz}CsoxgQDU&zU^! z8({GKTsUBUE*QR{c^_xM{!cJ}&g5y|0E6e(g9GO4f@$9X`$UG${Z!?Whe!1Ae$EIC zo}UXx=Ynb90Q)RM?&pH}b0!au@HN2T`4}89f3Lvs4bA%^1NNoLB@d7AuPrcmemyu~ zzVCwJ8=Ci32JCCW{5g|{NBFv6@cepkz*|XE1!j*9H4UhR*#}FkhEEJi^ZfgXibM(YavwhMx=en+%=%yI{U9d3c1M3kJ{6 zg`;!9v~Pg@H$(3K1oQWbJnb7`@O)i3Iu{Jz@UJbfKV<0KKLzuzE%LN)fWh-~;eh#b z2E#XeU9e3ubnah*`MTt3-vEQ>=fVN=b-}c6fbmOLI=7KvelB@5>QLYv4EdhJUVsH4&aaKR96iy%`w3;pc*FnIU&8l}n!X4KR4VE*vm_ z4~(}6?(2dz&5*mb(#3D^2tOALp05i>=Ynb90NW-*?zV#Yb0!au@O8o9`MPkx{Cx() zH~d_%?K0$UuX4%5Bm7)2c)l(ioePF<__<)sGUV={bjj1c0S3?4g#+gA6`1x7upKkx z?xb?b!y|kRFnB%&2kZ~8&wy#)0NXi3?k-A~JUqhJ0E6daaKL>%!5wVEBgS?V17GO)!7Xxvd5Bb;-jc{9G`2el8rH3x;p_xnON%=-jq~`MTuc z5q>ThJUc7`4}9X3#NSoY`+Y-`wQk@ALQW?z6KaP zAA* zV0ekThJUV z`FjPXeFLn!44r#~$|Vnv@OfbHd<+hl-{ZlwZ-DiXp>ul*=FgctJi_OJ!SgXVV7@Mx z_6@LJGIVZl!F*lvv~PgH^K;?oTrhk?^ZI1K`U>XHnLOnFqSm*n9Qel8e1KNpV91;aNquYU&YNWpwRHF<*hx?u49dUz0+KW8v} z!_Ng9AVcRKC77Q}9v*VEBfw3pP-O&OKT%Uza>Q!p{YR=jX!FxnTH) zp9?lfhRz)X2j-z)O)2tOALo{z!NxnSBiz=meX z9VVE6eUOJo_!?mFd<+hlKW8xQ8(_m_=-d&4`MTuc5k3zLo{zx+^L4@S4b2;w0XtUZ zlBazG44z*P4wye@FuX+bMrFW83+B(6JTN~uA&>D0|6Btbqj+$@{PPqH-|%z6j+5bQ zfQ^;m=aQ#=0}P&@3kS?!2N=HL>w=Awp>vNH%-1CkkMMKB;Q6_5bS{|o4Y2VUa!(M< zpEG%Qgs%$*&)0f=!U2b59n` z*CkK;1{gd)7Y>-eS76#Vz)q2&b5B*deM=fVN=uPrd`8(=vybnZmK{5g|{ zNBFv6@cdjjV7@Mx_6@LH89FylFkhEE?Hge5{9HIX7YyI<=M0vVp>rn*=Fgct?ImFF z{9HI-{+z)kD<0m0Z}{gL*c2K5{J`>M`1juA;Sqi=7(720j?M+sz5#YxhTN%w`FlVf z9^vbP!Si+DfcbLt0c%-1CkkMMKB;Q6_5bS{|o4X~07xut^ndqtl14KR4V zE*zZ;hHq$ISq7|JF#ov*dD=I?;Q967fcbL(#-NBHL&*qJhXUxNeY z_dGCs!_NgfONP#!Bbc8{9vc7`MGd( zE*QR{d1q(9&JoO?GkJJ~uL}mxuLlRrpEDS~;pc+Qm7#Oz3FhaLhe!CiVDS80I64;$ z-|%z6=F8Bz3k36Z$-^Uj9vD0yg9GO86&Svuc?&aOi&QRo+Bd-9`Ssv{`PT;+zM*;N zX28x9%%3xP+Bd-9`Ssv{`MO~EhUT500lPpjUza>Q!p{YR=VNemE|~TWunRNfUL=@5 zXY%k8Ujq!DkHG=+=L~kS;^8g$hJUW{m}}q1c&x8;9&@ewJRWmh`WTP(^~PhaBcI1( zt_2_CG3ULH@tAYh$9SyIQy%N{kH?%>z8CXYpD#S-Jn(ru*2kB}`nd6!z4vo@?C(8) zr*~1({;k-q@;%zu8uQIt-Y0YO`*Jps$1MzMzO9?(-WwnjN6MSOs~N^2j>K*a~;+HXk^|sT0N_PMt05;1J)#5Zts*$Yx0bP29US6Ob%;}En}|Aai0>W2A-=7Q zed^#4_v@thxl&+roQP9rI~i^d^|63MymbVJ`1Uf|)WIR{*U`s|ICYxI7=2#XzVhjB z*I*mLh_{vDIC{>+caYIeM%cRG5T}mg==l(*&W?gx%W#SO0 zP8f$cb#|_ULwtXaqvuR~7a0f02wN8%;?!{*J!j(7X)Ysd&Txny=yCLX@Kt>7U>RZ8 zDIDSlMR15yC(2jh5N|KTY3X$l$LIbfBWzu8h*QUL^ty;sC(2jh5I;nQn~$zT9G^S1 z4i0g@j$RjW>O}b}9O4~hgsqD>KG#u3*qq@Ir%o7$ICY|Y6%O%EGQ#Q*$L9{KgF`&3 z4sq(>d0|>`h&S z;?%+OHos3s?fX?Y#Iqwf#PPX=jIjB@Ax@nz4sq(>c~KnV{USKT@wxso!qx?cICa7} z#HoYlh0O;J@gpNR#PPWSb#RDB)gewDJTGiMa7;XcLmZzQSO>?%|IVotD65GK;?%(x z!}bsk@uMR+#PPX7b#RFLb@cU4oH}@3SigWne6YvS{zDv}8zLiYU2up~$8q$0h*Jm8 z3!4ud;>UO#Js;xu+)x=#D-(w}b;3Brse|W5aflD|IC@>g@wwqL!qx?cICUIH&zU%N z@XfIKz#%@u4)Ku@9OBf$^TO)DAwJ6E=yegt=SIs2yH4Q{r;g+3 zITNQ&LPpqp;1C}Z!6A;%9ajg3xL-%Fi#T=gJU8b|9O7d=j$RjWd~TeKuyw&9PMt6g zaq8fCQ5@pOM{tNAC1ZRY9O6-Rh*Jm83!4ud;wN|295x>~_~xk*9OC#~P8}TLr+OScXX4bs^W2;>afna!IC@>g@ylEpVe5iJoH~x9 zwelo}Uq<;V9O6kCVdp$?d~Q-59O8Z*y)NR^iSkuA#3#!LTNiPBZiO}b}9OC&hTphhG;`rQYGTfXqafnmLarE&bPMs)Ug+qL*3^yNLhd4f0PzQ&2R2|~f ziSkuA#HYy!n-6h(uCNXcalcM_4=V-EY9fO;b)tL~4)G!xZlCqBAdb%!*TEs~*U|e- zoH|jy3WxaVGMp#q`4GqFN@Rr184hvkIF6nVaq2|*DjedaGQ#FV{8SlbGMtv4GaTa7 z3F8nyRYsJr!XaKR!`0F2B96~Zm*M7|i9?(^j-%&HoH|jy3WxX%8E!th4xWk6&8mY# zd}aiPICb#6FfBO5XGd^|<8x=o2)hr5L!3Hc9OBf$^TOr>hxnNh9OC%gS#@xTN7W%t z9Xu~=&Txp&iQo{&=PG1`tqTru>V$EKQwPtB;t;Ql;1I{>&aQ()yfT7AoH}@3*nHp+ zKPQ4i9G{yjBW$1H5T{NUhd6ccyeJOwc^*e!%f#`y`7*+K3LN6paU6Y}5~mKH7d9U_ z#20uRJs;xu+(H>nD-(w}bsR^}hd6ccys-JeA-*VrLmZzww+;?*zmA?Waq8fCZqAuF z#Lx3MdR@fv%kyP~tqTru>Nt+pxjNlN*=Ps&)L)@>U*F~H>9!IZ>I6n7p8DZ;!L!3Hc9OBf$^P)J!FY!2fUBvOZOJ#(u3l4GWIF4Qyaq8fU zVe^4Q{IUoR@k$w&*TEqkRfl+`3_LGvK5&R%5y2sj&s|vuhqzxSz0Z{bXEl*QoI3cT z+ruoRR@Q-Uq>G=;?%+O+&xkz4)Lo!j-E4deC`?+se^BZ%?A$g8$FJm51xt7-7F*Qx`0FcrU(vk>O}b}9OAdga9Vm@#PPXXWrVE@ z4sq%@j$RjW>O}b}9OAdhaP!f1h~sm&*TEs~*U{@DPMs)Ug+u%f8DZ-pj?djGBW%ua zh*KwwL!3HMz6yuO}b}9O4hk2wN9%{PH0gVRME< zoH~x9=d)B|H_3?dRXD_#$#Cbhu0tH3d$Mv*ACVEZF5>vyav5QB zhC`e>VI1Pr!SkXx#8-G6y)NST+)5d4&Y3vGspB|$pNUf^%2(kKua*%uXX5zWsyaBt zqv{Z+PL!|0A--Bh*nEiNb8G705clioJtR(@C|`v`JSD^Jv#vuNpR1{ZL)@>Uj~8+3 zMENQl;*ZJ*yWWZ8bC1agn=>5Z)Nvd=AL7)B@>Mv*AD0m}AL97j6Ed8Z-a|OVsT0N_ zPMs)Ug+u&F8Lp0A7jb;);Ug z>*zTXr%sfw!Xf^WjIebP$LC&_5jJNy#Hka;Ax@nrUxh>b6&Yc5h~smw*1;i8onf_q zHoj7ztR^yuQwPse96>g7h`%Po%}4JuaeVG|8Ey|VafnkVj6<9{HFa=^zu|H8`9mC^ zdsBwHmNRjPQ^#@ioQYE>%2(kKe@lj2m)0VV&%G_fX=UONr;g+3`4FcLp69eOafrVY z!6A;%y;}!|xL-%lnK*UuJU8b|9O7#|j-E4d{PH~+Ve5iJoH}8g_a%m3;(1XV;vYnC zh~sk~*1;hjRfjlr@I3dLuwFYH;_D(f#PPY0WQ45?4sq&)afnj~&x_&^|2Tp}9H09? z8DZ;!L!3Hc9OBf$^TOr>hxjKE9OC%gr*&|MN7W%t9eif8DVoKj?aBw z2Zwl69pco%7sK`t4)HG{IK=U}FYDkC_v`3unK*UuJl6{{afpBAar7P%$LGG55wiYSMj+GGQ!SzIK+R5;1H)yl&``ezEMV)7IA#;M;T%3 zfXaKDT`x9O6-R zh*Jm83)6x_yjg@6aeQuvIyl6m>JX<6o)@--+)7WXZak)A&$@OBAl=}!y!(cFb;9*;CW$MaELdT&tV+m_*@GaVOnsAQzwi= zoH}@36o>e(5gg+9+-@?$<_w28b;3Brse^BZ%?A$g-93)>UOW?@+e1d!JpdfyEh9L@ zse|W*)qz8N&j=22e6E!Y*9-KV;Si@z7>77@@WrtCz#+a@1cx|2w|5;J;!$;oQwPrr zn=>5Z`$TYv<8!TLgslq>aq5I|h*Jm8i{cP(6Tu;l&$X?CLp-Vuaq8fCVe^4Qyj=u` zI6k+pjIe!%L!3Hc9OBf$^P)J!_wzXV9)LJLx4(?A>l6-g>Nt)*=ZRAX&kLIm9O4If z96cZ6_}qaqoK_|daq2jZo)2;A;EQ4NfkXVD2o7<4?%+B&#Qi#Y&cvyM=eap&;t+4| zarC-~0^;)h0Xh~sk|>fjKMszaPQcwX54z#-l- zfm(y=U2up~CyYa!I(S|bhxlO;9OC#~XBlDZfKWLLmZzwq7Dx6s5-={ zgXe|aBf%lwBZ5O5pX(_jY+Z1OQzwi=oH}@3*nHp+?-juzj?eX$5vB!)ICa7}#HoWX zMsbMuiQo`7J|~~U)&-}p4C;h&h*JmO44V%e;@KWY`!k-2&-IfLcAo%;cp`#BoH}@3 zSRFXT`$uqy<8w#KaJ@j!84hvkgmH*d2VV@E4;3ed~R?Z9O6-Rh*Jm83!4ud;zJ@h#PPXf zWQ6TA9OBdo;}E9~o)^U-KGfsr`xfH(+%R|{uLHm_agU?VdE(T;^TOr>hxl-hqvt~$ zpBo_~Y(8*^Q^#@ie27yAUksZM9O5G*IK=U}W9#4$_v`3&5vLBG=jNP=LwuCS(d#0P zUyha$wk|ltsT0N-BQg9k%2(kKKTby2IZqs)8(Rm5cvKzY)QR#{IK;=v2wN9%eC~J| zVRMEIuQ;NXelBRItIxf5iB%^41H>V$EKQzyz-;SfJjM%cQD<8vp~!66=1 zhd6bjd=(Dy2{OXwLmZzwxegBTs5-={6XmOLh@T=OY@dnam#5ajA@0}F*D`VHMENQl z;yG|bex`yrJ~vTD*qq@Ir;g+3`4Fd0l&``eo+~44KE(04JQ+?)dlVev)CuDdr%sfw z!XciN;p*sh5y$5y$#8Sd#34={$I){pPMs)Ug+qL@jIjCOnfP43jIif%aEMQd;1H({ zo)=aJ4)N0>IK=U}sWRN!_5Q#iPMt6gaq8fUVe^4QydZ)@9G{z32Zwl69pco%^TOr~ zhj?KGhd4f0BqMBHaEMbUj6<9{cwQ8TcyR=WI6ilJ9US6Ob%;|3&kLIm9O5Mr9OC#~ zsf@6FhC`e>VI1PrF}@gbp9zO}nT)VH#PPXu8DY;o;Si@z7>77@@VqcBIK-z%aERk` zGh~Em!68naFb;9*;CW&5fkS*|1cx|2H>(Z~@u)h)se|W*%^42y*%2J#_~jWg!qx?c zICUIH`}3I+!!Pl?uzLwO#LtT05Xa}{)WIPhRfjlr@I2QG^qk=kuZZ9f$LA_#gslq> zaq5I|h*Jm8i{cPJJAy+TpF2lJ*t*~lr%o7$ICb#Fu=&6tJ~x6x9G{z42Zwl69pco% z^TOr>hxq&m4sm>LK^+|8QFVw@2hR)JLpa12MsSGZbBpTW5cliodjR6p!SmcTn2AID zT#uvAdE)roc{0M*1&26w97k&rrw*PMHXk^|&-XZbKE(043uHL0OdR6W3F8o_4xSgq zA%3C9(d#0P&s`)VY+Z1OQ^#@ioQYEh-wc}%9O4(JIsN3lS!(3R8n%|v!~S@K{9BnV z|EP~BEGp)gvAh@S`QcZH^Yy6y1IB+O>)TGq2gr~w&BwOs&-PRO=A6z+Y%cNtCVz8w z-Ct4P4e1%%ojk$jI9>PIqO9>R`Pd|*v3$+=|K`KZ$?5CI|KF%mb=$XZ?X~UO`}TI@ z#TSOA_eh?nrH^?t;rYjW`&!d+bN0cyu*9RA*>!OpGZW9nqCS)7hJVbn(${0{y8nMa z=A#Go8`)d7lk2**jK5#!ZZGY=opf>I#PWTf%w}*Da>xs`4}*~-(i=xvG0AuHA{T7fW!L@JL(X5 zFzuAm{MkwQl$%qWlbc^QE35sqQ}S}ka)62o3i3E$_vW%6ZSznqB^hvgUABDK++nHJ5llo2J9 zrHpxyGt)jumdfgUg^@WWOt7pZKc{eVK@cg<$xF|6bHa#{F^V;D`jqr+q=b8r!`$V; zv39~aWwLF8w|#yG*L}$i(ss z^Gv8Sp)To1hjsHG9l?Xm5p%%ZnU+5OW77&SrzK0LaMqUEnalZ^-dQAXj7m=~HTf1B%Kg79`W?=F4GH(XgCiwm2uRi#^B^qx9x&H78GD=_EO( zRLq@{Uyx^_lD7Fl`g}1!`ViJ4+tqLp1oL^Cl<9b{czFKQ34I z_^`2^Yd!8fwv&A<5>s+Yr;N#wwV@!73zIX;(qEcm8JqGRMc5O!`a<=9zvh zTQQcCFMSFelbpp@ljRD@$t{y>(`=~BxxA25AelF^2C#qMW>9nN)I6PGO#GwP3ZcZxB5D$Xd-oD$OV=DaadBl9N6sIJxCgEG{ZA zUN|l?IyAp9nNu=0DHkLyNae~wEib4Q&MC|BUxNFx_C;mBsnVZ zo7}u%MNoVd*|~lpb4&Nqf$1|kzf{hvyfHbG50jbX7Rm7~lv;y1l{QawbXiVW5`x)F zv9;iOO6E>AM<6dbF28JwDUlYitvPMO`GwO57h)qhW5iU8O3YypwwOol4bRE2$7a_D z%4~`_du&SZaI&-xd#uu5$+UBm1<4ZE`Zh}sr58wrvZAt_f`LUPVod1=V~R>nH%2RD z={Ct>Ii;NLR%$@bv|`&m(v$N5X+LazPC*(ArbT125qnOhIiBQ>gMMrl@I`9yQ6P3&hs^_QYW=B_J!4#>Sk z$>yAlpgEfglgYf&f%4D9oZP9*tXP_DGH>v-;_`x0jzr$X$pcDqW~2=$FTWJq3@-1| z{>ic#$z-8y=hS3g|DwEn<4r|!yh`%(lEcfVjV>yX2ZQBeH;0}BI8h95s_aNw#NU|w z(xVCy;6yKzyNS(9NT0IB`O}Na1{d~|c=}70UNW(tT$1LpEt%NgeJOh|Dmh86N-^_CqDf_iVl@(+n4eP`oE9a?f}ELVGXkh|hHS@ZxyZSig9n}ELD>xH8bsvlyx^3# zXV!7GCAnsY`cq0TwH7Un)#AxM*~{VYyCtC!lO~lW%jCk`d@S4scgri9ls+z{#U-+Y z^uar^o4Kh!y*$4le_}~~`83mqENY3P%kn2pVsm^jeZpHPeepP+EI&Q*=!c42cVlvp8MGJVVNnI|}aC*?@^T<yjdU6WTLkH!QPcI4{a1nIkKR7$1$vzX@d}R=uCf(ZIsG74@+$BA+;lfORNl!Ol=jV~YB+{P?gINeD z7gc&n=D}to-0X=to4*tfkmnTUDwN|jI$1C&XjtjPDOE}{z=0v>a-!!K%IzBGtFUvq zp*7Ef-O)0yNXR-T$~9=ZFkhHvB<2=2Y{=Bzb~oz9>t|ZNrpgUP%rI#a@3VkY0!R z+DHUP#1%Ftk#q*BXug!)affZp=Bg%S_bJUwUz6!aL(Fp!sUUkgDSvX-nDHZz8YHhX zp`WGEr8Zc_x}Qy(m8~%QTZ@iFs0%HL+~u zlv$JEkX{iy#Vi~+%B~h*czl@I6susM~lTJ+6^I^Z1kJqXbTn3w; zsZT89X+(bRNM3{SVKMKFub9Y=yVptz^U}|ECYB8=FDT2m&w>0RgA3(mOckPL^=)r(=>Rw+#hJV*b1w&cTrvGh8L} zq}j!E&XMvotf;&&&(txmNVsYG0f)_!OHp1U^F@!$DK0H9sI|#X%R5Pq7K@S|`*(E? z$Dr~8@5QT$o1bT=pVyho#7)6H2e&c*1Tp=wzxY)~P@OXFi3f8$Os*@eh!-8x&qvZ~ zLCN%EbCq^B|8C~`av2G=qzB1C^`8Owi&HVbu*fCHaNE3DH$A7Llk#jgKeyX}B54R} z{$6afxtIMLV>AuGy9+i&xl>>x#W2imXDyIxycU3&)&j89T7WUu05O|ty*0p4levkN z)`H}stX(PX!iFRld3v74jTN?e^TrH4YIr00E=MOsg9BN6FI5T`|_8m{*ccv2q#af>?i-8B=6)?BiNLz+Zv4?GwMjbIkIim z7E+nt{cn`Djm&R5c?`C#AlqhbDYIxS_*OESW;GK|QnU=N;tp z&cfYMvYJViUF7SX*i9ciBxJLk;a0+Y9Te738R^0H4%0b!)hTj*;W4AN?1F| z_t?=LD_3U+{K9w_4=*_VUO+*{Sc z+YA0L$vH%3(^ziPJ z`u?)|BLy8`<|scQBdcjFoPm;ap#0ZFcK>MM50bA23ulO|vWdw*P~L^HiJXJ1?O@p# z*3!hh6XO2z{?xS}v-&3T4v9_W9S)nyx!qLWeQA| zyr%L_cTMFT=$gtq%r%vFerqD{?AAoi+9vXjYE8^Lo$W6>Y4@EqFi*R`r^wE3Y39*P zuB08Za)duo)|@N5-BQlXJQ+!u`y|2km9uTKj48s)mvNemsj{O5GN#EWlu;z3SjOox zN~Bh)j4~PJGN#LzA!DYDS!Q25%5G|noke43(P$oFikdjCryb z^JOfMu~5b$8RyD4PsaH&E|6jCa;|ljbE%2ETSF6hH-;`UtHb4;5)L=-gupd)nT*S2 zTp{C1na_V@TqR#$E#n&b`dayXot)`gNbdELeS?e}<&3wFcaX-C?-*c^lMFG;DMqZAmAY1St^ZMXz+P7VzJGNgtvaMp zhm`2G?~f`Gdb<_bxNd%u-khW}C#lIvDsqvX;jC5LVD35h=e_3wqg=F-*Vl*oP#@}J zO?_QuNYV{Sxgo)}TyI_W-nt~)BtbUW^;33<%Um(1{QtOW-Zg5~4pGi6B$tNd(L!oy zdFqsNSH`a!zhT9dXTZ(Xv0Hu`<2HAy_w?AeTO>v%V@WDxr?kc*yIVc)t@h=6?#DUJ zeID?T2_~6hnnyh52~T;(b6zmREOWf{{#U%_4f7neqc!=C1r~YhTi)^B{3Xwq`M^g$ z85?u0+5Ou5T|b-ug|DkM-(0`*gP;5|_qUoqu37HPWJ4a=Mhf>0Y;qrLrjaddrOC5I zGc9?aZ*+3zPR%??bO=ccAxR-595~mE?Qq@6E_PG18*i)jfx|lZ>pJVZbk-l#(SAtB idbdvU9-ZPxba40S&~{Eye%~JU(#}5i(~ +#else +#include +#endif +#else +#ifdef USE_MINICL +#include +#else +#include +#ifdef _WIN32 +#include "CL/cl_gl.h" +#endif //_WIN32 +#endif +#endif //__APPLE__ + +#include +#include +#define oclCHECKERROR(a, b) if((a)!=(b)) { printf("OCL Error : %d\n", (a)); assert((a) == (b)); } + + +#endif //BT_OPENCL_INCLUDE_H + diff --git a/Demos/SharedOpenCL/btOpenCLUtils.cpp b/Demos/SharedOpenCL/btOpenCLUtils.cpp new file mode 100644 index 0000000..318e6d2 --- /dev/null +++ b/Demos/SharedOpenCL/btOpenCLUtils.cpp @@ -0,0 +1,789 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006 - 2011 Sony Computer Entertainment Inc. + +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. +*/ + +//original author: Roman Ponomarev +//cleanup by Erwin Coumans + +#include + +#include "btOpenCLUtils.h" +#include +#include + +#define BT_MAX_CL_DEVICES 16 //who needs 16 devices? +//#define BT_USE_CACHE_DIR +#ifdef _WIN32 +#include +#endif //_WIN32 + +#include +#define btAssert assert + +//Set the preferred platform vendor using the OpenCL SDK +static char* spPlatformVendor = +#if defined(CL_PLATFORM_MINI_CL) +"MiniCL, SCEA"; +#elif defined(CL_PLATFORM_AMD) +"Advanced Micro Devices, Inc."; +#elif defined(CL_PLATFORM_NVIDIA) +"NVIDIA Corporation"; +#elif defined(CL_PLATFORM_INTEL) +"Intel(R) Corporation"; +#else +"Unknown Vendor"; +#endif + +#ifndef CL_PLATFORM_MINI_CL +#ifdef _WIN32 +#include "CL/cl_gl.h" +#endif //_WIN32 +#endif + +int btOpenCLUtils::getNumPlatforms(cl_int* pErrNum) +{ + cl_uint numPlatforms=0; + cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms); + + if(ciErrNum != CL_SUCCESS) + { + if(pErrNum != NULL) + *pErrNum = ciErrNum; + } + return numPlatforms; +} + +const char* btOpenCLUtils::getSdkVendorName() +{ + return spPlatformVendor; +} + +cl_platform_id btOpenCLUtils::getPlatform(int platformIndex, cl_int* pErrNum) +{ + cl_platform_id platform = 0; + + cl_uint numPlatforms; + cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms); + + if (platformIndex>=0 && platformIndex=0 && preferredDeviceIndex 0) + { + cl_platform_id* platforms = new cl_platform_id[numPlatforms]; + ciErrNum = clGetPlatformIDs(numPlatforms, platforms, NULL); + if(ciErrNum != CL_SUCCESS) + { + if(pErrNum != NULL) *pErrNum = ciErrNum; + return NULL; + } + int i; + + + for ( i = 0; i < numPlatforms; ++i) + { + char pbuf[128]; + ciErrNum = clGetPlatformInfo( platforms[i], + CL_PLATFORM_VENDOR, + sizeof(pbuf), + pbuf, + NULL); + if(ciErrNum != CL_SUCCESS) + { + if(pErrNum != NULL) *pErrNum = ciErrNum; + return NULL; + } + + if (preferredPlatformIndex>=0 && i==preferredPlatformIndex) + { + cl_platform_id tmpPlatform = platforms[0]; + platforms[0] = platforms[i]; + platforms[i] = tmpPlatform; + break; + } else + { + if(!strcmp(pbuf, spPlatformVendor)) + { + cl_platform_id tmpPlatform = platforms[0]; + platforms[0] = platforms[i]; + platforms[i] = tmpPlatform; + break; + } + } + } + + for (i = 0; i < numPlatforms; ++i) + { + cl_platform_id platform = platforms[i]; + assert(platform); + + retContext = btOpenCLUtils::createContextFromPlatform(platform,deviceType,pErrNum,pGLContext,pGLDC,preferredDeviceIndex); + + if (retContext) + { +// printf("OpenCL platform details:\n"); + btOpenCLPlatformInfo platformInfo; + + btOpenCLUtils::getPlatformInfo(platform, platformInfo); + + printf(" CL_PLATFORM_VENDOR: \t\t\t%s\n",platformInfo.m_platformVendor); + printf(" CL_PLATFORM_NAME: \t\t\t%s\n",platformInfo.m_platformName); + printf(" CL_PLATFORM_VERSION: \t\t\t%s\n",platformInfo.m_platformVersion); + + break; + } + } + + delete[] platforms; + } + return retContext; +} + + +////////////////////////////////////////////////////////////////////////////// +//! Gets the id of the nth device from the context +//! +//! @return the id or -1 when out of range +//! @param cxMainContext OpenCL context +//! @param device_idx index of the device of interest +////////////////////////////////////////////////////////////////////////////// +cl_device_id btOpenCLUtils::getDevice(cl_context cxMainContext, int deviceIndex) +{ + size_t szParmDataBytes; + cl_device_id* cdDevices; + + // get the list of devices associated with context + clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, 0, NULL, &szParmDataBytes); + + if( szParmDataBytes / sizeof(cl_device_id) < deviceIndex ) { + return (cl_device_id)-1; + } + + cdDevices = (cl_device_id*) malloc(szParmDataBytes); + + clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, szParmDataBytes, cdDevices, NULL); + + cl_device_id device = cdDevices[deviceIndex]; + free(cdDevices); + + return device; +} + +int btOpenCLUtils::getNumDevices(cl_context cxMainContext) +{ + size_t szParamDataBytes; + clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, 0, NULL, &szParamDataBytes); + int device_count = (int) szParamDataBytes/ sizeof(cl_device_id); + return device_count; +} + +void btOpenCLUtils::printDeviceInfo(cl_device_id device) +{ + btOpenCLDeviceInfo info; + getDeviceInfo(device,info); + + printf(" CL_DEVICE_NAME: \t\t\t%s\n", info.m_deviceName); + printf(" CL_DEVICE_VENDOR: \t\t\t%s\n", info.m_deviceVendor); + printf(" CL_DRIVER_VERSION: \t\t\t%s\n", info.m_driverVersion); + + if( info.m_deviceType & CL_DEVICE_TYPE_CPU ) + printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_CPU"); + if( info.m_deviceType & CL_DEVICE_TYPE_GPU ) + printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_GPU"); + if( info.m_deviceType & CL_DEVICE_TYPE_ACCELERATOR ) + printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_ACCELERATOR"); + if( info.m_deviceType & CL_DEVICE_TYPE_DEFAULT ) + printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_DEFAULT"); + + printf(" CL_DEVICE_MAX_COMPUTE_UNITS:\t\t%u\n", info.m_computeUnits); + printf(" CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:\t%u\n", info.m_workitemDims); + printf(" CL_DEVICE_MAX_WORK_ITEM_SIZES:\t%u / %u / %u \n", info.m_workItemSize[0], info.m_workItemSize[1], info.m_workItemSize[2]); + printf(" CL_DEVICE_MAX_WORK_GROUP_SIZE:\t%u\n", info.m_workgroupSize); + printf(" CL_DEVICE_MAX_CLOCK_FREQUENCY:\t%u MHz\n", info.m_clockFrequency); + printf(" CL_DEVICE_ADDRESS_BITS:\t\t%u\n", info.m_addressBits); + printf(" CL_DEVICE_MAX_MEM_ALLOC_SIZE:\t\t%u MByte\n", (unsigned int)(info.m_maxMemAllocSize/ (1024 * 1024))); + printf(" CL_DEVICE_GLOBAL_MEM_SIZE:\t\t%u MByte\n", (unsigned int)(info.m_globalMemSize/ (1024 * 1024))); + printf(" CL_DEVICE_ERROR_CORRECTION_SUPPORT:\t%s\n", info.m_errorCorrectionSupport== CL_TRUE ? "yes" : "no"); + printf(" CL_DEVICE_LOCAL_MEM_TYPE:\t\t%s\n", info.m_localMemType == 1 ? "local" : "global"); + printf(" CL_DEVICE_LOCAL_MEM_SIZE:\t\t%u KByte\n", (unsigned int)(info.m_localMemSize / 1024)); + printf(" CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:\t%u KByte\n", (unsigned int)(info.m_constantBufferSize / 1024)); + if( info.m_queueProperties & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE ) + printf(" CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE"); + if( info.m_queueProperties & CL_QUEUE_PROFILING_ENABLE ) + printf(" CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_PROFILING_ENABLE"); + + printf(" CL_DEVICE_IMAGE_SUPPORT:\t\t%u\n", info.m_imageSupport); + + printf(" CL_DEVICE_MAX_READ_IMAGE_ARGS:\t%u\n", info.m_maxReadImageArgs); + printf(" CL_DEVICE_MAX_WRITE_IMAGE_ARGS:\t%u\n", info.m_maxWriteImageArgs); + printf("\n CL_DEVICE_IMAGE "); + printf("\t\t\t2D_MAX_WIDTH\t %u\n", info.m_image2dMaxWidth); + printf("\t\t\t\t\t2D_MAX_HEIGHT\t %u\n", info.m_image2dMaxHeight); + printf("\t\t\t\t\t3D_MAX_WIDTH\t %u\n", info.m_image3dMaxWidth); + printf("\t\t\t\t\t3D_MAX_HEIGHT\t %u\n", info.m_image3dMaxHeight); + printf("\t\t\t\t\t3D_MAX_DEPTH\t %u\n", info.m_image3dMaxDepth); + if (info.m_deviceExtensions != 0) + printf("\n CL_DEVICE_EXTENSIONS:%s\n",info.m_deviceExtensions); + else + printf(" CL_DEVICE_EXTENSIONS: None\n"); + printf(" CL_DEVICE_PREFERRED_VECTOR_WIDTH_\t"); + printf("CHAR %u, SHORT %u, INT %u,LONG %u, FLOAT %u, DOUBLE %u\n\n\n", + info.m_vecWidthChar, info.m_vecWidthShort, info.m_vecWidthInt, info.m_vecWidthLong,info.m_vecWidthFloat, info.m_vecWidthDouble); + + +} + +void btOpenCLUtils::getDeviceInfo(cl_device_id device, btOpenCLDeviceInfo& info) +{ + + // CL_DEVICE_NAME + clGetDeviceInfo(device, CL_DEVICE_NAME, BT_MAX_STRING_LENGTH, &info.m_deviceName, NULL); + + // CL_DEVICE_VENDOR + clGetDeviceInfo(device, CL_DEVICE_VENDOR, BT_MAX_STRING_LENGTH, &info.m_deviceVendor, NULL); + + // CL_DRIVER_VERSION + clGetDeviceInfo(device, CL_DRIVER_VERSION, BT_MAX_STRING_LENGTH, &info.m_driverVersion, NULL); + + // CL_DEVICE_INFO + clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(cl_device_type), &info.m_deviceType, NULL); + + // CL_DEVICE_MAX_COMPUTE_UNITS + clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(info.m_computeUnits), &info.m_computeUnits, NULL); + + // CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS + clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(info.m_workitemDims), &info.m_workitemDims, NULL); + + // CL_DEVICE_MAX_WORK_ITEM_SIZES + clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(info.m_workItemSize), &info.m_workItemSize, NULL); + + // CL_DEVICE_MAX_WORK_GROUP_SIZE + clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(info.m_workgroupSize), &info.m_workgroupSize, NULL); + + // CL_DEVICE_MAX_CLOCK_FREQUENCY + clGetDeviceInfo(device, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(info.m_clockFrequency), &info.m_clockFrequency, NULL); + + // CL_DEVICE_ADDRESS_BITS + clGetDeviceInfo(device, CL_DEVICE_ADDRESS_BITS, sizeof(info.m_addressBits), &info.m_addressBits, NULL); + + // CL_DEVICE_MAX_MEM_ALLOC_SIZE + clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(info.m_maxMemAllocSize), &info.m_maxMemAllocSize, NULL); + + // CL_DEVICE_GLOBAL_MEM_SIZE + clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(info.m_globalMemSize), &info.m_globalMemSize, NULL); + + // CL_DEVICE_ERROR_CORRECTION_SUPPORT + clGetDeviceInfo(device, CL_DEVICE_ERROR_CORRECTION_SUPPORT, sizeof(info.m_errorCorrectionSupport), &info.m_errorCorrectionSupport, NULL); + + // CL_DEVICE_LOCAL_MEM_TYPE + clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_TYPE, sizeof(info.m_localMemType), &info.m_localMemType, NULL); + + // CL_DEVICE_LOCAL_MEM_SIZE + clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(info.m_localMemSize), &info.m_localMemSize, NULL); + + // CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE + clGetDeviceInfo(device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(info.m_constantBufferSize), &info.m_constantBufferSize, NULL); + + // CL_DEVICE_QUEUE_PROPERTIES + clGetDeviceInfo(device, CL_DEVICE_QUEUE_PROPERTIES, sizeof(info.m_queueProperties), &info.m_queueProperties, NULL); + + // CL_DEVICE_IMAGE_SUPPORT + clGetDeviceInfo(device, CL_DEVICE_IMAGE_SUPPORT, sizeof(info.m_imageSupport), &info.m_imageSupport, NULL); + + // CL_DEVICE_MAX_READ_IMAGE_ARGS + clGetDeviceInfo(device, CL_DEVICE_MAX_READ_IMAGE_ARGS, sizeof(info.m_maxReadImageArgs), &info.m_maxReadImageArgs, NULL); + + // CL_DEVICE_MAX_WRITE_IMAGE_ARGS + clGetDeviceInfo(device, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, sizeof(info.m_maxWriteImageArgs), &info.m_maxWriteImageArgs, NULL); + + // CL_DEVICE_IMAGE2D_MAX_WIDTH, CL_DEVICE_IMAGE2D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_WIDTH, CL_DEVICE_IMAGE3D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_DEPTH + clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(size_t), &info.m_image2dMaxWidth, NULL); + clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(size_t), &info.m_image2dMaxHeight, NULL); + clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof(size_t), &info.m_image3dMaxWidth, NULL); + clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof(size_t), &info.m_image3dMaxHeight, NULL); + clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(size_t), &info.m_image3dMaxDepth, NULL); + + // CL_DEVICE_EXTENSIONS: get device extensions, and if any then parse & log the string onto separate lines + clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, BT_MAX_STRING_LENGTH, &info.m_deviceExtensions, NULL); + + // CL_DEVICE_PREFERRED_VECTOR_WIDTH_ + clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &info.m_vecWidthChar, NULL); + clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, sizeof(cl_uint), &info.m_vecWidthShort, NULL); + clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, sizeof(cl_uint), &info.m_vecWidthInt, NULL); + clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, sizeof(cl_uint), &info.m_vecWidthLong, NULL); + clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, sizeof(cl_uint), &info.m_vecWidthFloat, NULL); + clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, sizeof(cl_uint), &info.m_vecWidthDouble, NULL); +} + +static char* strip1(char* name, const char* pattern,int* numOccurences=0) +{ + size_t const patlen = strlen(pattern); + char * oriptr; + char * patloc; + // find how many times the pattern occurs in the original string + for (oriptr = name; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen) + { + if (numOccurences) + (*numOccurences)++; + } + return oriptr; +} +static const char* strip2(const char* name, const char* pattern,int* numOccurences=0) +{ + size_t const patlen = strlen(pattern); + const char * oriptr; + const char * patloc; + // find how many times the pattern occurs in the original string + for (oriptr = name; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen) + { + if (numOccurences) + (*numOccurences)++; + } + return oriptr; +} + +cl_program btOpenCLUtils::compileCLProgramFromString(cl_context clContext, cl_device_id device, const char* kernelSource, cl_int* pErrNum, const char* additionalMacros) +{ + + cl_int localErrNum; + size_t program_length = strlen(kernelSource); + + cl_program m_cpProgram = clCreateProgramWithSource(clContext, 1, (const char**)&kernelSource, &program_length, &localErrNum); + if (localErrNum!= CL_SUCCESS) + { + if (pErrNum) + *pErrNum = localErrNum; + return 0; + } + + // Build the program with 'mad' Optimization option + + +#ifdef MAC + char* flags = "-cl-mad-enable -DMAC -DGUID_ARG"; +#else + //const char* flags = "-DGUID_ARG= -fno-alias"; + const char* flags = "-DGUID_ARG= "; +#endif + + char* compileFlags = new char[strlen(additionalMacros) + strlen(flags) + 5]; + sprintf(compileFlags, "%s %s", flags, additionalMacros); + localErrNum = clBuildProgram(m_cpProgram, 1, &device, compileFlags, NULL, NULL); + if (localErrNum!= CL_SUCCESS) + { + char *build_log; + size_t ret_val_size; + clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size); + build_log = new char[ret_val_size+1]; + clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL); + + // to be carefully, terminate with \0 + // there's no information in the reference whether the string is 0 terminated or not + build_log[ret_val_size] = '\0'; + + + printf("Error in clBuildProgram, Line %u in file %s, Log: \n%s\n !!!\n\n", __LINE__, __FILE__, build_log); + delete[] build_log; + if (pErrNum) + *pErrNum = localErrNum; + return 0; + } + delete[] compileFlags; + return m_cpProgram; +} + +cl_program btOpenCLUtils::compileCLProgramFromFile(cl_context clContext, cl_device_id device, cl_int* pErrNum, const char* additionalMacros , const char* clFileNameForCaching) +{ + + cl_program m_cpProgram=0; + cl_int status; + char binaryFileName[522]; + + if (clFileNameForCaching) + { +#ifdef _WIN32 + char deviceName[256]; + char driverVersion[256]; + clGetDeviceInfo(device, CL_DEVICE_NAME, 256, &deviceName, NULL); + clGetDeviceInfo(device, CL_DRIVER_VERSION, 256, &driverVersion, NULL); + + + const char* strippedName = strip2(clFileNameForCaching,"\\"); + strippedName = strip2(strippedName,"/"); +#ifdef BT_USE_CACHE_DIR + sprintf_s(binaryFileName,"cache/%s.%s.%s.bin",strippedName, deviceName,driverVersion ); +#else + sprintf_s(binaryFileName,"%s.%s.%s.bin",strippedName, deviceName,driverVersion ); +#endif + + //printf("searching for %s\n", binaryFileName); + + bool fileUpToDate = false; + bool binaryFileValid=false; + + FILETIME modtimeBinary; + +#ifdef BT_USE_CACHE_DIR + CreateDirectory("cache",0); +#endif //BT_USE_CACHE_DIR + { + + HANDLE binaryFileHandle = CreateFile(binaryFileName,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); + if (binaryFileHandle ==INVALID_HANDLE_VALUE) + { + DWORD errorCode; + errorCode = GetLastError(); + switch (errorCode) + { + case ERROR_FILE_NOT_FOUND: + { + printf("\nCached file not found %s\n", binaryFileName); + break; + } + case ERROR_PATH_NOT_FOUND: + { + printf("\nCached file path not found %s\n", binaryFileName); + break; + } + default: + { + printf("\nFailed reading cached file with errorCode = %d\n", errorCode); + } + } + } else + { + if (GetFileTime(binaryFileHandle, NULL, NULL, &modtimeBinary)==0) + { + DWORD errorCode; + errorCode = GetLastError(); + printf("\nGetFileTime errorCode = %d\n", errorCode); + } else + { + binaryFileValid = true; + } + CloseHandle(binaryFileHandle); + } + + if (binaryFileValid) + { + HANDLE srcFileHandle = CreateFile(clFileNameForCaching,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); + if (srcFileHandle!=INVALID_HANDLE_VALUE) + { + FILETIME modtimeSrc; + if (GetFileTime(srcFileHandle, NULL, NULL, &modtimeSrc)==0) + { + DWORD errorCode; + errorCode = GetLastError(); + printf("\nGetFileTime errorCode = %d\n", errorCode); + } + if ( ( modtimeSrc.dwHighDateTime < modtimeBinary.dwHighDateTime) + ||(( modtimeSrc.dwHighDateTime == modtimeBinary.dwHighDateTime)&&(modtimeSrc.dwLowDateTime <= modtimeBinary.dwLowDateTime))) + { + fileUpToDate=true; + } else + { + printf("\nCached binary file out-of-date (%s)\n",binaryFileName); + } + CloseHandle(srcFileHandle); + } + else + { + DWORD errorCode; + errorCode = GetLastError(); + switch (errorCode) + { + case ERROR_FILE_NOT_FOUND: + { + printf("\nSrc file not found %s\n", clFileNameForCaching); + break; + } + case ERROR_PATH_NOT_FOUND: + { + printf("\nSrc path not found %s\n", clFileNameForCaching); + break; + } + default: + { + printf("\nnSrc file reading errorCode = %d\n", errorCode); + } + } + + //we should make sure the src file exists so we can verify the timestamp with binary + fileUpToDate = false; + } + } + + + } + + if( fileUpToDate) + { + FILE* file = fopen(binaryFileName, "rb"); + if (file) + { + fseek( file, 0L, SEEK_END ); + size_t binarySize = ftell( file ); + rewind( file ); + char* binary = new char[binarySize]; + fread( binary, sizeof(char), binarySize, file ); + fclose( file ); + + m_cpProgram = clCreateProgramWithBinary( clContext, 1,&device, &binarySize, (const unsigned char**)&binary, 0, &status ); + btAssert( status == CL_SUCCESS ); + status = clBuildProgram( m_cpProgram, 1, &device, additionalMacros, 0, 0 ); + btAssert( status == CL_SUCCESS ); + + if( status != CL_SUCCESS ) + { + char *build_log; + size_t ret_val_size; + clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size); + build_log = new char[ret_val_size+1]; + clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL); + build_log[ret_val_size] = '\0'; + printf("%s\n", build_log); + delete build_log; + btAssert(0); + m_cpProgram = 0; + } + delete[] binary; + } + } +#endif //_WIN32 + + } + + if (!m_cpProgram) + { + + FILE* file = fopen(clFileNameForCaching, "r"); + if (file) + { + fseek( file, 0L, SEEK_END ); + size_t fileSize= ftell( file ); + rewind( file ); + char* kernelSource2 = new char[fileSize+1]; + fread( kernelSource2, sizeof(char), fileSize, file ); + fclose( file ); + kernelSource2[fileSize]=0; + int numOccurences = 0; + ///patch/remove the MSTRINGIFY( and ); + char* kernelSource = strip1(kernelSource2,"MSTRINGIFY(",&numOccurences); + int newlen = strlen(kernelSource); + if (numOccurences) + { + int i=newlen-1; + + for (;i>=0;i--) + { + if (kernelSource[i] == ';') + { + kernelSource[i] = 0;//' '; + break; + } + } + for (;i>=0;i--) + { + if (kernelSource[i] == ')') + { + kernelSource[i] = 0;//' '; + break; + } + } + } + + m_cpProgram = compileCLProgramFromString(clContext,device,kernelSource,pErrNum,additionalMacros); + + if( clFileNameForCaching ) + { // write to binary + + cl_uint numAssociatedDevices; + status = clGetProgramInfo( m_cpProgram, CL_PROGRAM_NUM_DEVICES, sizeof(cl_uint), &numAssociatedDevices, 0 ); + btAssert( status == CL_SUCCESS ); + if (numAssociatedDevices==1) + { + + size_t binarySize; + status = clGetProgramInfo( m_cpProgram, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &binarySize, 0 ); + btAssert( status == CL_SUCCESS ); + + char* binary = new char[binarySize]; + + status = clGetProgramInfo( m_cpProgram, CL_PROGRAM_BINARIES, sizeof(char*), &binary, 0 ); + btAssert( status == CL_SUCCESS ); + + { + FILE* file = fopen(binaryFileName, "wb"); + if (file) + { + fwrite( binary, sizeof(char), binarySize, file ); + fclose( file ); + } else + { + printf("cannot write file %s\n", binaryFileName); + } + } + + delete [] binary; + } + } + } + } + + return m_cpProgram; +} + + +cl_kernel btOpenCLUtils::compileCLKernelFromString(cl_context clContext, cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum, cl_program prog, const char* additionalMacros ) +{ + printf("compiling kernel %s ",kernelName); + cl_kernel kernel; + cl_int localErrNum; + size_t program_length = strlen(kernelSource); + + + cl_program m_cpProgram = prog; + if (!m_cpProgram) + { + m_cpProgram = compileCLProgramFromString(clContext,device,kernelSource,pErrNum, additionalMacros); + } + + + // Create the kernel + kernel = clCreateKernel(m_cpProgram, kernelName, &localErrNum); + if (localErrNum != CL_SUCCESS) + { + printf("Error in clCreateKernel, Line %u in file %s, cannot find kernel function %s !!!\n\n", __LINE__, __FILE__, kernelName); + if (pErrNum) + *pErrNum = localErrNum; + return 0; + } + + if (!prog && m_cpProgram) + { + clReleaseProgram(m_cpProgram); + } + printf("ready. \n"); + + + if (pErrNum) + *pErrNum = CL_SUCCESS; + return kernel; + +} diff --git a/Demos/SharedOpenCL/btOpenCLUtils.h b/Demos/SharedOpenCL/btOpenCLUtils.h new file mode 100644 index 0000000..e9f4228 --- /dev/null +++ b/Demos/SharedOpenCL/btOpenCLUtils.h @@ -0,0 +1,107 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006 - 2011 Sony Computer Entertainment Inc. + +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. +*/ + +//original author: Roman Ponomarev +//cleanup by Erwin Coumans + +#ifndef BT_OPENCL_UTILS_H +#define BT_OPENCL_UTILS_H + +#include "btOpenCLInclude.h" + + +#define BT_MAX_STRING_LENGTH 1024 + +struct btOpenCLDeviceInfo +{ + char m_deviceName[BT_MAX_STRING_LENGTH]; + char m_deviceVendor[BT_MAX_STRING_LENGTH]; + char m_driverVersion[BT_MAX_STRING_LENGTH]; + char m_deviceExtensions[BT_MAX_STRING_LENGTH]; + + cl_device_type m_deviceType; + cl_uint m_computeUnits; + size_t m_workitemDims; + size_t m_workItemSize[3]; + size_t m_image2dMaxWidth; + size_t m_image2dMaxHeight; + size_t m_image3dMaxWidth; + size_t m_image3dMaxHeight; + size_t m_image3dMaxDepth; + size_t m_workgroupSize; + cl_uint m_clockFrequency; + cl_ulong m_constantBufferSize; + cl_ulong m_localMemSize; + cl_ulong m_globalMemSize; + cl_bool m_errorCorrectionSupport; + cl_device_local_mem_type m_localMemType; + cl_uint m_maxReadImageArgs; + cl_uint m_maxWriteImageArgs; + + + + cl_uint m_addressBits; + cl_ulong m_maxMemAllocSize; + cl_command_queue_properties m_queueProperties; + cl_bool m_imageSupport; + cl_uint m_vecWidthChar; + cl_uint m_vecWidthShort; + cl_uint m_vecWidthInt; + cl_uint m_vecWidthLong; + cl_uint m_vecWidthFloat; + cl_uint m_vecWidthDouble; + +}; + +struct btOpenCLPlatformInfo +{ + char m_platformVendor[BT_MAX_STRING_LENGTH]; + char m_platformName[BT_MAX_STRING_LENGTH]; + char m_platformVersion[BT_MAX_STRING_LENGTH]; +}; + +class btOpenCLUtils +{ +public: + + /// CL Context optionally takes a GL context. This is a generic type because we don't really want this code + /// to have to understand GL types. It is a HGLRC in _WIN32 or a GLXContext otherwise. + static cl_context createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx = 0, void* pGLDC = 0, int preferredDeviceIndex = -1, int preferredPlatformIndex= - 1); + + static int getNumDevices(cl_context cxMainContext); + static cl_device_id getDevice(cl_context cxMainContext, int nr); + static void getDeviceInfo(cl_device_id device, btOpenCLDeviceInfo& info); + static void printDeviceInfo(cl_device_id device); + + static cl_kernel compileCLKernelFromString( cl_context clContext,cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum=0, cl_program prog=0,const char* additionalMacros = "" ); + + //optional + static cl_program compileCLProgramFromString( cl_context clContext,cl_device_id device, const char* kernelSource, cl_int* pErrNum=0,const char* additionalMacros = ""); + ///compileCLProgramFromFile will attempt to save/load the binary precompiled program + static cl_program compileCLProgramFromFile( cl_context clContext,cl_device_id device, cl_int* pErrNum=0,const char* additionalMacros = "" , const char* srcFileNameForCaching=0); + + + //the following optional APIs provide access using specific platform information + static int getNumPlatforms(cl_int* pErrNum=0); + ///get the nr'th platform, where nr is in the range [0..getNumPlatforms) + static cl_platform_id getPlatform(int nr, cl_int* pErrNum=0); + static void getPlatformInfo(cl_platform_id platform, btOpenCLPlatformInfo& platformInfo); + static const char* getSdkVendorName(); + static cl_context createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx = 0, void* pGLDC = 0,int preferredDeviceIndex = -1, int preferredPlatformIndex= -1); +}; + + + +#endif // BT_OPENCL_UTILS_H diff --git a/Demos/SharedOpenCL/clew.c b/Demos/SharedOpenCL/clew.c new file mode 100644 index 0000000..cfc6ed0 --- /dev/null +++ b/Demos/SharedOpenCL/clew.c @@ -0,0 +1,313 @@ +////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2009 Organic Vectory B.V. +// Written by George van Venrooij +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file license.txt) +////////////////////////////////////////////////////////////////////////// +#ifndef USE_MINICL +#include "clew.h" + +//! \file clew.c +//! \brief OpenCL run-time loader source + +#ifndef CLCC_GENERATE_DOCUMENTATION +#ifdef _WIN32 + #define WIN32_LEAN_AND_MEAN + #define VC_EXTRALEAN + #define NOMINMAX + #include + + typedef HMODULE CLCC_DYNLIB_HANDLE; + + #define CLCC_DYNLIB_OPEN LoadLibrary + #define CLCC_DYNLIB_CLOSE FreeLibrary + #define CLCC_DYNLIB_IMPORT GetProcAddress +#else + #include + + typedef void* CLCC_DYNLIB_HANDLE; + + #define CLCC_DYNLIB_OPEN(path) dlopen(path, RTLD_NOW | RTLD_GLOBAL) + #define CLCC_DYNLIB_CLOSE dlclose + #define CLCC_DYNLIB_IMPORT dlsym +#endif +#else + //typedef implementation_defined CLCC_DYNLIB_HANDLE; + //#define CLCC_DYNLIB_OPEN(path) implementation_defined + //#define CLCC_DYNLIB_CLOSE implementation_defined + //#define CLCC_DYNLIB_IMPORT implementation_defined +#endif + +#include + +//! \brief module handle +static CLCC_DYNLIB_HANDLE module = NULL; + +// Variables holding function entry points +#ifndef CLCC_GENERATE_DOCUMENTATION +PFNCLGETPLATFORMIDS __clewGetPlatformIDs = NULL; +PFNCLGETPLATFORMINFO __clewGetPlatformInfo = NULL; +PFNCLGETDEVICEIDS __clewGetDeviceIDs = NULL; +PFNCLGETDEVICEINFO __clewGetDeviceInfo = NULL; +PFNCLCREATECONTEXT __clewCreateContext = NULL; +PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType = NULL; +PFNCLRETAINCONTEXT __clewRetainContext = NULL; +PFNCLRELEASECONTEXT __clewReleaseContext = NULL; +PFNCLGETCONTEXTINFO __clewGetContextInfo = NULL; +PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue = NULL; +PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue = NULL; +PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue = NULL; +PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo = NULL; +PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty = NULL; +PFNCLCREATEBUFFER __clewCreateBuffer = NULL; +PFNCLCREATEIMAGE2D __clewCreateImage2D = NULL; +PFNCLCREATEIMAGE3D __clewCreateImage3D = NULL; +PFNCLRETAINMEMOBJECT __clewRetainMemObject = NULL; +PFNCLRELEASEMEMOBJECT __clewReleaseMemObject = NULL; +PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats = NULL; +PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo = NULL; +PFNCLGETIMAGEINFO __clewGetImageInfo = NULL; +PFNCLCREATESAMPLER __clewCreateSampler = NULL; +PFNCLRETAINSAMPLER __clewRetainSampler = NULL; +PFNCLRELEASESAMPLER __clewReleaseSampler = NULL; +PFNCLGETSAMPLERINFO __clewGetSamplerInfo = NULL; +PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource = NULL; +PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary = NULL; +PFNCLRETAINPROGRAM __clewRetainProgram = NULL; +PFNCLRELEASEPROGRAM __clewReleaseProgram = NULL; +PFNCLBUILDPROGRAM __clewBuildProgram = NULL; +PFNCLUNLOADCOMPILER __clewUnloadCompiler = NULL; +PFNCLGETPROGRAMINFO __clewGetProgramInfo = NULL; +PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo = NULL; +PFNCLCREATEKERNEL __clewCreateKernel = NULL; +PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram = NULL; +PFNCLRETAINKERNEL __clewRetainKernel = NULL; +PFNCLRELEASEKERNEL __clewReleaseKernel = NULL; +PFNCLSETKERNELARG __clewSetKernelArg = NULL; +PFNCLGETKERNELINFO __clewGetKernelInfo = NULL; +PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo = NULL; +PFNCLWAITFOREVENTS __clewWaitForEvents = NULL; +PFNCLGETEVENTINFO __clewGetEventInfo = NULL; +PFNCLRETAINEVENT __clewRetainEvent = NULL; +PFNCLRELEASEEVENT __clewReleaseEvent = NULL; +PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo = NULL; +PFNCLFLUSH __clewFlush = NULL; +PFNCLFINISH __clewFinish = NULL; +PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer = NULL; +PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer = NULL; +PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer = NULL; +PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage = NULL; +PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage = NULL; +PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage = NULL; +PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer = NULL; +PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage = NULL; +PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer = NULL; +PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage = NULL; +PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject = NULL; +PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel = NULL; +PFNCLENQUEUETASK __clewEnqueueTask = NULL; +PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel = NULL; +PFNCLENQUEUEMARKER __clewEnqueueMarker = NULL; +PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents = NULL; +PFNCLENQUEUEBARRIER __clewEnqueueBarrier = NULL; +PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress = NULL; +#endif // CLCC_GENERATE_DOCUMENTATION + + +//! \brief Unloads OpenCL dynamic library, should not be called directly +static void clewExit(void) +{ + if (module != NULL) + { + // Ignore errors + CLCC_DYNLIB_CLOSE(module); + module = NULL; + } +} + +//! \param path path to dynamic library to load +//! \return CLEW_ERROR_OPEN_FAILED if the library could not be opened +//! CLEW_ERROR_ATEXIT_FAILED if atexit(clewExit) failed +//! CLEW_SUCCESS when the library was succesfully loaded +int clewInit(const char* path) +{ + int error = 0; + + // Check if already initialized + if (module != NULL) + { + return CLEW_SUCCESS; + } + + // Load library + module = CLCC_DYNLIB_OPEN(path); + + // Check for errors + if (module == NULL) + { + return CLEW_ERROR_OPEN_FAILED; + } + + // Set unloading + error = atexit(clewExit); + + if (error) + { + // Failure queing atexit, shutdown with error + CLCC_DYNLIB_CLOSE(module); + module = NULL; + + return CLEW_ERROR_ATEXIT_FAILED; + } + + // Determine function entry-points + __clewGetPlatformIDs = (PFNCLGETPLATFORMIDS )CLCC_DYNLIB_IMPORT(module, "clGetPlatformIDs"); + __clewGetPlatformInfo = (PFNCLGETPLATFORMINFO )CLCC_DYNLIB_IMPORT(module, "clGetPlatformInfo"); + __clewGetDeviceIDs = (PFNCLGETDEVICEIDS )CLCC_DYNLIB_IMPORT(module, "clGetDeviceIDs"); + __clewGetDeviceInfo = (PFNCLGETDEVICEINFO )CLCC_DYNLIB_IMPORT(module, "clGetDeviceInfo"); + __clewCreateContext = (PFNCLCREATECONTEXT )CLCC_DYNLIB_IMPORT(module, "clCreateContext"); + __clewCreateContextFromType = (PFNCLCREATECONTEXTFROMTYPE )CLCC_DYNLIB_IMPORT(module, "clCreateContextFromType"); + __clewRetainContext = (PFNCLRETAINCONTEXT )CLCC_DYNLIB_IMPORT(module, "clRetainContext"); + __clewReleaseContext = (PFNCLRELEASECONTEXT )CLCC_DYNLIB_IMPORT(module, "clReleaseContext"); + __clewGetContextInfo = (PFNCLGETCONTEXTINFO )CLCC_DYNLIB_IMPORT(module, "clGetContextInfo"); + __clewCreateCommandQueue = (PFNCLCREATECOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clCreateCommandQueue"); + __clewRetainCommandQueue = (PFNCLRETAINCOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clRetainCommandQueue"); + __clewReleaseCommandQueue = (PFNCLRELEASECOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clReleaseCommandQueue"); + __clewGetCommandQueueInfo = (PFNCLGETCOMMANDQUEUEINFO )CLCC_DYNLIB_IMPORT(module, "clGetCommandQueueInfo"); + __clewSetCommandQueueProperty = (PFNCLSETCOMMANDQUEUEPROPERTY )CLCC_DYNLIB_IMPORT(module, "clSetCommandQueueProperty"); + __clewCreateBuffer = (PFNCLCREATEBUFFER )CLCC_DYNLIB_IMPORT(module, "clCreateBuffer"); + __clewCreateImage2D = (PFNCLCREATEIMAGE2D )CLCC_DYNLIB_IMPORT(module, "clCreateImage2D"); + __clewCreateImage3D = (PFNCLCREATEIMAGE3D )CLCC_DYNLIB_IMPORT(module, "clCreateImage3D"); + __clewRetainMemObject = (PFNCLRETAINMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clRetainMemObject"); + __clewReleaseMemObject = (PFNCLRELEASEMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clReleaseMemObject"); + __clewGetSupportedImageFormats = (PFNCLGETSUPPORTEDIMAGEFORMATS )CLCC_DYNLIB_IMPORT(module, "clGetSupportedImageFormats"); + __clewGetMemObjectInfo = (PFNCLGETMEMOBJECTINFO )CLCC_DYNLIB_IMPORT(module, "clGetMemObjectInfo"); + __clewGetImageInfo = (PFNCLGETIMAGEINFO )CLCC_DYNLIB_IMPORT(module, "clGetImageInfo"); + __clewCreateSampler = (PFNCLCREATESAMPLER )CLCC_DYNLIB_IMPORT(module, "clCreateSampler"); + __clewRetainSampler = (PFNCLRETAINSAMPLER )CLCC_DYNLIB_IMPORT(module, "clRetainSampler"); + __clewReleaseSampler = (PFNCLRELEASESAMPLER )CLCC_DYNLIB_IMPORT(module, "clReleaseSampler"); + __clewGetSamplerInfo = (PFNCLGETSAMPLERINFO )CLCC_DYNLIB_IMPORT(module, "clGetSamplerInfo"); + __clewCreateProgramWithSource = (PFNCLCREATEPROGRAMWITHSOURCE )CLCC_DYNLIB_IMPORT(module, "clCreateProgramWithSource"); + __clewCreateProgramWithBinary = (PFNCLCREATEPROGRAMWITHBINARY )CLCC_DYNLIB_IMPORT(module, "clCreateProgramWithBinary"); + __clewRetainProgram = (PFNCLRETAINPROGRAM )CLCC_DYNLIB_IMPORT(module, "clRetainProgram"); + __clewReleaseProgram = (PFNCLRELEASEPROGRAM )CLCC_DYNLIB_IMPORT(module, "clReleaseProgram"); + __clewBuildProgram = (PFNCLBUILDPROGRAM )CLCC_DYNLIB_IMPORT(module, "clBuildProgram"); + __clewUnloadCompiler = (PFNCLUNLOADCOMPILER )CLCC_DYNLIB_IMPORT(module, "clUnloadCompiler"); + __clewGetProgramInfo = (PFNCLGETPROGRAMINFO )CLCC_DYNLIB_IMPORT(module, "clGetProgramInfo"); + __clewGetProgramBuildInfo = (PFNCLGETPROGRAMBUILDINFO )CLCC_DYNLIB_IMPORT(module, "clGetProgramBuildInfo"); + __clewCreateKernel = (PFNCLCREATEKERNEL )CLCC_DYNLIB_IMPORT(module, "clCreateKernel"); + __clewCreateKernelsInProgram = (PFNCLCREATEKERNELSINPROGRAM )CLCC_DYNLIB_IMPORT(module, "clCreateKernelsInProgram"); + __clewRetainKernel = (PFNCLRETAINKERNEL )CLCC_DYNLIB_IMPORT(module, "clRetainKernel"); + __clewReleaseKernel = (PFNCLRELEASEKERNEL )CLCC_DYNLIB_IMPORT(module, "clReleaseKernel"); + __clewSetKernelArg = (PFNCLSETKERNELARG )CLCC_DYNLIB_IMPORT(module, "clSetKernelArg"); + __clewGetKernelInfo = (PFNCLGETKERNELINFO )CLCC_DYNLIB_IMPORT(module, "clGetKernelInfo"); + __clewGetKernelWorkGroupInfo = (PFNCLGETKERNELWORKGROUPINFO )CLCC_DYNLIB_IMPORT(module, "clGetKernelWorkGroupInfo"); + __clewWaitForEvents = (PFNCLWAITFOREVENTS )CLCC_DYNLIB_IMPORT(module, "clWaitForEvents"); + __clewGetEventInfo = (PFNCLGETEVENTINFO )CLCC_DYNLIB_IMPORT(module, "clGetEventInfo"); + __clewRetainEvent = (PFNCLRETAINEVENT )CLCC_DYNLIB_IMPORT(module, "clRetainEvent"); + __clewReleaseEvent = (PFNCLRELEASEEVENT )CLCC_DYNLIB_IMPORT(module, "clReleaseEvent"); + __clewGetEventProfilingInfo = (PFNCLGETEVENTPROFILINGINFO )CLCC_DYNLIB_IMPORT(module, "clGetEventProfilingInfo"); + __clewFlush = (PFNCLFLUSH )CLCC_DYNLIB_IMPORT(module, "clFlush"); + __clewFinish = (PFNCLFINISH )CLCC_DYNLIB_IMPORT(module, "clFinish"); + __clewEnqueueReadBuffer = (PFNCLENQUEUEREADBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueReadBuffer"); + __clewEnqueueWriteBuffer = (PFNCLENQUEUEWRITEBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueWriteBuffer"); + __clewEnqueueCopyBuffer = (PFNCLENQUEUECOPYBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyBuffer"); + __clewEnqueueReadImage = (PFNCLENQUEUEREADIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueReadImage"); + __clewEnqueueWriteImage = (PFNCLENQUEUEWRITEIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueWriteImage"); + __clewEnqueueCopyImage = (PFNCLENQUEUECOPYIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyImage"); + __clewEnqueueCopyImageToBuffer = (PFNCLENQUEUECOPYIMAGETOBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyImageToBuffer"); + __clewEnqueueCopyBufferToImage = (PFNCLENQUEUECOPYBUFFERTOIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyBufferToImage"); + __clewEnqueueMapBuffer = (PFNCLENQUEUEMAPBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueMapBuffer"); + __clewEnqueueMapImage = (PFNCLENQUEUEMAPIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueMapImage"); + __clewEnqueueUnmapMemObject = (PFNCLENQUEUEUNMAPMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clEnqueueUnmapMemObject"); + __clewEnqueueNDRangeKernel = (PFNCLENQUEUENDRANGEKERNEL )CLCC_DYNLIB_IMPORT(module, "clEnqueueNDRangeKernel"); + __clewEnqueueTask = (PFNCLENQUEUETASK )CLCC_DYNLIB_IMPORT(module, "clEnqueueTask"); + __clewEnqueueNativeKernel = (PFNCLENQUEUENATIVEKERNEL )CLCC_DYNLIB_IMPORT(module, "clEnqueueNativeKernel"); + __clewEnqueueMarker = (PFNCLENQUEUEMARKER )CLCC_DYNLIB_IMPORT(module, "clEnqueueMarker"); + __clewEnqueueWaitForEvents = (PFNCLENQUEUEWAITFOREVENTS )CLCC_DYNLIB_IMPORT(module, "clEnqueueWaitForEvents"); + __clewEnqueueBarrier = (PFNCLENQUEUEBARRIER )CLCC_DYNLIB_IMPORT(module, "clEnqueueBarrier"); + __clewGetExtensionFunctionAddress = (PFNCLGETEXTENSIONFUNCTIONADDRESS )CLCC_DYNLIB_IMPORT(module, "clGetExtensionFunctionAddress"); + + return CLEW_SUCCESS; +} + +//! \param error CL error code +//! \return a string representation of the error code +const char* clewErrorString(cl_int error) +{ + static const char* strings[] = + { + // Error Codes + "CL_SUCCESS" // 0 + , "CL_DEVICE_NOT_FOUND" // -1 + , "CL_DEVICE_NOT_AVAILABLE" // -2 + , "CL_COMPILER_NOT_AVAILABLE" // -3 + , "CL_MEM_OBJECT_ALLOCATION_FAILURE" // -4 + , "CL_OUT_OF_RESOURCES" // -5 + , "CL_OUT_OF_HOST_MEMORY" // -6 + , "CL_PROFILING_INFO_NOT_AVAILABLE" // -7 + , "CL_MEM_COPY_OVERLAP" // -8 + , "CL_IMAGE_FORMAT_MISMATCH" // -9 + , "CL_IMAGE_FORMAT_NOT_SUPPORTED" // -10 + , "CL_BUILD_PROGRAM_FAILURE" // -11 + , "CL_MAP_FAILURE" // -12 + + , "" // -13 + , "" // -14 + , "" // -15 + , "" // -16 + , "" // -17 + , "" // -18 + , "" // -19 + + , "" // -20 + , "" // -21 + , "" // -22 + , "" // -23 + , "" // -24 + , "" // -25 + , "" // -26 + , "" // -27 + , "" // -28 + , "" // -29 + + , "CL_INVALID_VALUE" // -30 + , "CL_INVALID_DEVICE_TYPE" // -31 + , "CL_INVALID_PLATFORM" // -32 + , "CL_INVALID_DEVICE" // -33 + , "CL_INVALID_CONTEXT" // -34 + , "CL_INVALID_QUEUE_PROPERTIES" // -35 + , "CL_INVALID_COMMAND_QUEUE" // -36 + , "CL_INVALID_HOST_PTR" // -37 + , "CL_INVALID_MEM_OBJECT" // -38 + , "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR" // -39 + , "CL_INVALID_IMAGE_SIZE" // -40 + , "CL_INVALID_SAMPLER" // -41 + , "CL_INVALID_BINARY" // -42 + , "CL_INVALID_BUILD_OPTIONS" // -43 + , "CL_INVALID_PROGRAM" // -44 + , "CL_INVALID_PROGRAM_EXECUTABLE" // -45 + , "CL_INVALID_KERNEL_NAME" // -46 + , "CL_INVALID_KERNEL_DEFINITION" // -47 + , "CL_INVALID_KERNEL" // -48 + , "CL_INVALID_ARG_INDEX" // -49 + , "CL_INVALID_ARG_VALUE" // -50 + , "CL_INVALID_ARG_SIZE" // -51 + , "CL_INVALID_KERNEL_ARGS" // -52 + , "CL_INVALID_WORK_DIMENSION" // -53 + , "CL_INVALID_WORK_GROUP_SIZE" // -54 + , "CL_INVALID_WORK_ITEM_SIZE" // -55 + , "CL_INVALID_GLOBAL_OFFSET" // -56 + , "CL_INVALID_EVENT_WAIT_LIST" // -57 + , "CL_INVALID_EVENT" // -58 + , "CL_INVALID_OPERATION" // -59 + , "CL_INVALID_GL_OBJECT" // -60 + , "CL_INVALID_BUFFER_SIZE" // -61 + , "CL_INVALID_MIP_LEVEL" // -62 + , "CL_INVALID_GLOBAL_WORK_SIZE" // -63 + }; + + return strings[-error]; +} +#endif diff --git a/Demos/SharedOpenCL/clew.h b/Demos/SharedOpenCL/clew.h new file mode 100644 index 0000000..27198ae --- /dev/null +++ b/Demos/SharedOpenCL/clew.h @@ -0,0 +1,1316 @@ +#ifndef CLCC_CLEW_HPP_INCLUDED +#define CLCC_CLEW_HPP_INCLUDED +#ifndef USE_MINICL +////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2009 Organic Vectory B.V. +// Written by George van Venrooij +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file license.txt) +////////////////////////////////////////////////////////////////////////// + +//! \file clew.h +//! \brief OpenCL run-time loader header +//! +//! This file contains a copy of the contents of CL.H and CL_PLATFORM.H from the +//! official OpenCL spec. The purpose of this code is to load the OpenCL dynamic +//! library at run-time and thus allow the executable to function on many +//! platforms regardless of the vendor of the OpenCL driver actually installed. +//! Some of the techniques used here were inspired by work done in the GLEW +//! library (http://glew.sourceforge.net/) + +// Run-time dynamic linking functionality based on concepts used in GLEW +#ifdef __OPENCL_CL_H +#error cl.h included before clew.h +#endif + +#ifdef __OPENCL_CL_PLATFORM_H +#error cl_platform.h included before clew.h +#endif + +#ifndef CLCC_GENERATE_DOCUMENTATION +// Prevent cl.h inclusion +#define __OPENCL_CL_H +// Prevent cl_platform.h inclusion +#define __CL_PLATFORM_H +#endif // CLCC_GENERATE_DOCUMENTATION + +/******************************************************************************* +* Copyright (c) 2008-2009 The Khronos Group Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and/or associated documentation files (the +* "Materials"), to deal in the Materials without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Materials, and to +* permit persons to whom the Materials are 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 Materials. +* +* THE MATERIALS ARE 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 +* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +******************************************************************************/ +#ifdef __APPLE__ +/* Contains #defines for AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER below */ +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CLCC_GENERATE_DOCUMENTATION + +#if defined(_WIN32) +#define CL_API_ENTRY +#define CL_API_CALL __stdcall +#else +#define CL_API_ENTRY +#define CL_API_CALL +#endif + +#if defined(__APPLE__) +#define CL_API_SUFFIX__VERSION_1_0 AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER +#define CL_EXTENSION_WEAK_LINK __attribute__((weak_import)) +#else +#define CL_API_SUFFIX__VERSION_1_0 +#define CL_EXTENSION_WEAK_LINK +#endif + +#if defined(_WIN32) && defined(_MSC_VER) + +/* scalar types */ +typedef signed __int8 cl_char; +typedef unsigned __int8 cl_uchar; +typedef signed __int16 cl_short; +typedef unsigned __int16 cl_ushort; +typedef signed __int32 cl_int; +typedef unsigned __int32 cl_uint; +typedef signed __int64 cl_long; +typedef unsigned __int64 cl_ulong; + +typedef unsigned __int16 cl_half; +typedef float cl_float; +typedef double cl_double; + + +/* +* Vector types +* +* Note: OpenCL requires that all types be naturally aligned. +* This means that vector types must be naturally aligned. +* For example, a vector of four floats must be aligned to +* a 16 byte boundary (calculated as 4 * the natural 4-byte +* alignment of the float). The alignment qualifiers here +* will only function properly if your compiler supports them +* and if you don't actively work to defeat them. For example, +* in order for a cl_float4 to be 16 byte aligned in a struct, +* the start of the struct must itself be 16-byte aligned. +* +* Maintaining proper alignment is the user's responsibility. +*/ +typedef signed __int8 cl_char2[2]; +typedef signed __int8 cl_char4[4]; +typedef signed __int8 cl_char8[8]; +typedef signed __int8 cl_char16[16]; +typedef unsigned __int8 cl_uchar2[2]; +typedef unsigned __int8 cl_uchar4[4]; +typedef unsigned __int8 cl_uchar8[8]; +typedef unsigned __int8 cl_uchar16[16]; + +typedef signed __int16 cl_short2[2]; +typedef signed __int16 cl_short4[4]; +typedef signed __int16 cl_short8[8]; +typedef signed __int16 cl_short16[16]; +typedef unsigned __int16 cl_ushort2[2]; +typedef unsigned __int16 cl_ushort4[4]; +typedef unsigned __int16 cl_ushort8[8]; +typedef unsigned __int16 cl_ushort16[16]; + +typedef signed __int32 cl_int2[2]; +typedef signed __int32 cl_int4[4]; +typedef signed __int32 cl_int8[8]; +typedef signed __int32 cl_int16[16]; +typedef unsigned __int32 cl_uint2[2]; +typedef unsigned __int32 cl_uint4[4]; +typedef unsigned __int32 cl_uint8[8]; +typedef unsigned __int32 cl_uint16[16]; + +typedef signed __int64 cl_long2[2]; +typedef signed __int64 cl_long4[4]; +typedef signed __int64 cl_long8[8]; +typedef signed __int64 cl_long16[16]; +typedef unsigned __int64 cl_ulong2[2]; +typedef unsigned __int64 cl_ulong4[4]; +typedef unsigned __int64 cl_ulong8[8]; +typedef unsigned __int64 cl_ulong16[16]; + +typedef float cl_float2[2]; +typedef float cl_float4[4]; +typedef float cl_float8[8]; +typedef float cl_float16[16]; + +typedef double cl_double2[2]; +typedef double cl_double4[4]; +typedef double cl_double8[8]; +typedef double cl_double16[16]; +/* There are no vector types for half */ + +#else + +#include + +/* scalar types */ +typedef int8_t cl_char; +typedef uint8_t cl_uchar; +typedef int16_t cl_short __attribute__((aligned(2))); +typedef uint16_t cl_ushort __attribute__((aligned(2))); +typedef int32_t cl_int __attribute__((aligned(4))); +typedef uint32_t cl_uint __attribute__((aligned(4))); +typedef int64_t cl_long __attribute__((aligned(8))); +typedef uint64_t cl_ulong __attribute__((aligned(8))); + +typedef uint16_t cl_half __attribute__((aligned(2))); +typedef float cl_float __attribute__((aligned(4))); +typedef double cl_double __attribute__((aligned(8))); + +/* +* Vector types +* +* Note: OpenCL requires that all types be naturally aligned. +* This means that vector types must be naturally aligned. +* For example, a vector of four floats must be aligned to +* a 16 byte boundary (calculated as 4 * the natural 4-byte +* alignment of the float). The alignment qualifiers here +* will only function properly if your compiler supports them +* and if you don't actively work to defeat them. For example, +* in order for a cl_float4 to be 16 byte aligned in a struct, +* the start of the struct must itself be 16-byte aligned. +* +* Maintaining proper alignment is the user's responsibility. +*/ +typedef int8_t cl_char2[2] __attribute__((aligned(2))); +typedef int8_t cl_char4[4] __attribute__((aligned(4))); +typedef int8_t cl_char8[8] __attribute__((aligned(8))); +typedef int8_t cl_char16[16] __attribute__((aligned(16))); +typedef uint8_t cl_uchar2[2] __attribute__((aligned(2))); +typedef uint8_t cl_uchar4[4] __attribute__((aligned(4))); +typedef uint8_t cl_uchar8[8] __attribute__((aligned(8))); +typedef uint8_t cl_uchar16[16] __attribute__((aligned(16))); + +typedef int16_t cl_short2[2] __attribute__((aligned(4))); +typedef int16_t cl_short4[4] __attribute__((aligned(8))); +typedef int16_t cl_short8[8] __attribute__((aligned(16))); +typedef int16_t cl_short16[16] __attribute__((aligned(32))); +typedef uint16_t cl_ushort2[2] __attribute__((aligned(4))); +typedef uint16_t cl_ushort4[4] __attribute__((aligned(8))); +typedef uint16_t cl_ushort8[8] __attribute__((aligned(16))); +typedef uint16_t cl_ushort16[16] __attribute__((aligned(32))); + +typedef int32_t cl_int2[2] __attribute__((aligned(8))); +typedef int32_t cl_int4[4] __attribute__((aligned(16))); +typedef int32_t cl_int8[8] __attribute__((aligned(32))); +typedef int32_t cl_int16[16] __attribute__((aligned(64))); +typedef uint32_t cl_uint2[2] __attribute__((aligned(8))); +typedef uint32_t cl_uint4[4] __attribute__((aligned(16))); +typedef uint32_t cl_uint8[8] __attribute__((aligned(32))); +typedef uint32_t cl_uint16[16] __attribute__((aligned(64))); + +typedef int64_t cl_long2[2] __attribute__((aligned(16))); +typedef int64_t cl_long4[4] __attribute__((aligned(32))); +typedef int64_t cl_long8[8] __attribute__((aligned(64))); +typedef int64_t cl_long16[16] __attribute__((aligned(128))); +typedef uint64_t cl_ulong2[2] __attribute__((aligned(16))); +typedef uint64_t cl_ulong4[4] __attribute__((aligned(32))); +typedef uint64_t cl_ulong8[8] __attribute__((aligned(64))); +typedef uint64_t cl_ulong16[16] __attribute__((aligned(128))); + +typedef float cl_float2[2] __attribute__((aligned(8))); +typedef float cl_float4[4] __attribute__((aligned(16))); +typedef float cl_float8[8] __attribute__((aligned(32))); +typedef float cl_float16[16] __attribute__((aligned(64))); + +typedef double cl_double2[2] __attribute__((aligned(16))); +typedef double cl_double4[4] __attribute__((aligned(32))); +typedef double cl_double8[8] __attribute__((aligned(64))); +typedef double cl_double16[16] __attribute__((aligned(128))); + +/* There are no vector types for half */ + +#endif + +/******************************************************************************/ + +// Macro names and corresponding values defined by OpenCL + +#define CL_CHAR_BIT 8 +#define CL_SCHAR_MAX 127 +#define CL_SCHAR_MIN (-127-1) +#define CL_CHAR_MAX CL_SCHAR_MAX +#define CL_CHAR_MIN CL_SCHAR_MIN +#define CL_UCHAR_MAX 255 +#define CL_SHRT_MAX 32767 +#define CL_SHRT_MIN (-32767-1) +#define CL_USHRT_MAX 65535 +#define CL_INT_MAX 2147483647 +#define CL_INT_MIN (-2147483647-1) +#define CL_UINT_MAX 0xffffffffU +#define CL_LONG_MAX ((cl_long) 0x7FFFFFFFFFFFFFFFLL) +#define CL_LONG_MIN ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL) +#define CL_ULONG_MAX ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL) + +#define CL_FLT_DIG 6 +#define CL_FLT_MANT_DIG 24 +#define CL_FLT_MAX_10_EXP +38 +#define CL_FLT_MAX_EXP +128 +#define CL_FLT_MIN_10_EXP -37 +#define CL_FLT_MIN_EXP -125 +#define CL_FLT_RADIX 2 +#if defined(_MSC_VER) +// MSVC doesn't understand hex floats +#define CL_FLT_MAX 3.402823466e+38F +#define CL_FLT_MIN 1.175494351e-38F +#define CL_FLT_EPSILON 1.192092896e-07F +#else +#define CL_FLT_MAX 0x1.fffffep127f +#define CL_FLT_MIN 0x1.0p-126f +#define CL_FLT_EPSILON 0x1.0p-23f +#endif + +#define CL_DBL_DIG 15 +#define CL_DBL_MANT_DIG 53 +#define CL_DBL_MAX_10_EXP +308 +#define CL_DBL_MAX_EXP +1024 +#define CL_DBL_MIN_10_EXP -307 +#define CL_DBL_MIN_EXP -1021 +#define CL_DBL_RADIX 2 +#if defined(_MSC_VER) +// MSVC doesn't understand hex floats +#define CL_DBL_MAX 1.7976931348623158e+308 +#define CL_DBL_MIN 2.2250738585072014e-308 +#define CL_DBL_EPSILON 2.2204460492503131e-016 +#else +#define CL_DBL_MAX 0x1.fffffffffffffp1023 +#define CL_DBL_MIN 0x1.0p-1022 +#define CL_DBL_EPSILON 0x1.0p-52 +#endif + +#include + + +// CL.h contents +/******************************************************************************/ + +typedef struct _cl_platform_id * cl_platform_id; +typedef struct _cl_device_id * cl_device_id; +typedef struct _cl_context * cl_context; +typedef struct _cl_command_queue * cl_command_queue; +typedef struct _cl_mem * cl_mem; +typedef struct _cl_program * cl_program; +typedef struct _cl_kernel * cl_kernel; +typedef struct _cl_event * cl_event; +typedef struct _cl_sampler * cl_sampler; + +typedef cl_uint cl_bool; /* WARNING! Unlike cl_ types in cl_platform.h, cl_bool is not guaranteed to be the same size as the bool in kernels. */ +typedef cl_ulong cl_bitfield; +typedef cl_bitfield cl_device_type; +typedef cl_uint cl_platform_info; +typedef cl_uint cl_device_info; +typedef cl_bitfield cl_device_address_info; +typedef cl_bitfield cl_device_fp_config; +typedef cl_uint cl_device_mem_cache_type; +typedef cl_uint cl_device_local_mem_type; +typedef cl_bitfield cl_device_exec_capabilities; +typedef cl_bitfield cl_command_queue_properties; + +typedef intptr_t cl_context_properties; +typedef cl_uint cl_context_info; +typedef cl_uint cl_command_queue_info; +typedef cl_uint cl_channel_order; +typedef cl_uint cl_channel_type; +typedef cl_bitfield cl_mem_flags; +typedef cl_uint cl_mem_object_type; +typedef cl_uint cl_mem_info; +typedef cl_uint cl_image_info; +typedef cl_uint cl_addressing_mode; +typedef cl_uint cl_filter_mode; +typedef cl_uint cl_sampler_info; +typedef cl_bitfield cl_map_flags; +typedef cl_uint cl_program_info; +typedef cl_uint cl_program_build_info; +typedef cl_int cl_build_status; +typedef cl_uint cl_kernel_info; +typedef cl_uint cl_kernel_work_group_info; +typedef cl_uint cl_event_info; +typedef cl_uint cl_command_type; +typedef cl_uint cl_profiling_info; + +typedef struct _cl_image_format { + cl_channel_order image_channel_order; + cl_channel_type image_channel_data_type; +} cl_image_format; + + + +/******************************************************************************/ + +// Error Codes +#define CL_SUCCESS 0 +#define CL_DEVICE_NOT_FOUND -1 +#define CL_DEVICE_NOT_AVAILABLE -2 +#define CL_COMPILER_NOT_AVAILABLE -3 +#define CL_MEM_OBJECT_ALLOCATION_FAILURE -4 +#define CL_OUT_OF_RESOURCES -5 +#define CL_OUT_OF_HOST_MEMORY -6 +#define CL_PROFILING_INFO_NOT_AVAILABLE -7 +#define CL_MEM_COPY_OVERLAP -8 +#define CL_IMAGE_FORMAT_MISMATCH -9 +#define CL_IMAGE_FORMAT_NOT_SUPPORTED -10 +#define CL_BUILD_PROGRAM_FAILURE -11 +#define CL_MAP_FAILURE -12 + +#define CL_INVALID_VALUE -30 +#define CL_INVALID_DEVICE_TYPE -31 +#define CL_INVALID_PLATFORM -32 +#define CL_INVALID_DEVICE -33 +#define CL_INVALID_CONTEXT -34 +#define CL_INVALID_QUEUE_PROPERTIES -35 +#define CL_INVALID_COMMAND_QUEUE -36 +#define CL_INVALID_HOST_PTR -37 +#define CL_INVALID_MEM_OBJECT -38 +#define CL_INVALID_IMAGE_FORMAT_DESCRIPTOR -39 +#define CL_INVALID_IMAGE_SIZE -40 +#define CL_INVALID_SAMPLER -41 +#define CL_INVALID_BINARY -42 +#define CL_INVALID_BUILD_OPTIONS -43 +#define CL_INVALID_PROGRAM -44 +#define CL_INVALID_PROGRAM_EXECUTABLE -45 +#define CL_INVALID_KERNEL_NAME -46 +#define CL_INVALID_KERNEL_DEFINITION -47 +#define CL_INVALID_KERNEL -48 +#define CL_INVALID_ARG_INDEX -49 +#define CL_INVALID_ARG_VALUE -50 +#define CL_INVALID_ARG_SIZE -51 +#define CL_INVALID_KERNEL_ARGS -52 +#define CL_INVALID_WORK_DIMENSION -53 +#define CL_INVALID_WORK_GROUP_SIZE -54 +#define CL_INVALID_WORK_ITEM_SIZE -55 +#define CL_INVALID_GLOBAL_OFFSET -56 +#define CL_INVALID_EVENT_WAIT_LIST -57 +#define CL_INVALID_EVENT -58 +#define CL_INVALID_OPERATION -59 +#define CL_INVALID_GL_OBJECT -60 +#define CL_INVALID_BUFFER_SIZE -61 +#define CL_INVALID_MIP_LEVEL -62 +#define CL_INVALID_GLOBAL_WORK_SIZE -63 + +// OpenCL Version +#define CL_VERSION_1_0 1 + +// cl_bool +#define CL_FALSE 0 +#define CL_TRUE 1 + +// cl_platform_info +#define CL_PLATFORM_PROFILE 0x0900 +#define CL_PLATFORM_VERSION 0x0901 +#define CL_PLATFORM_NAME 0x0902 +#define CL_PLATFORM_VENDOR 0x0903 +#define CL_PLATFORM_EXTENSIONS 0x0904 + +// cl_device_type - bitfield +#define CL_DEVICE_TYPE_DEFAULT (1 << 0) +#define CL_DEVICE_TYPE_CPU (1 << 1) +#define CL_DEVICE_TYPE_GPU (1 << 2) +#define CL_DEVICE_TYPE_ACCELERATOR (1 << 3) +#define CL_DEVICE_TYPE_ALL 0xFFFFFFFF + +// cl_device_info +#define CL_DEVICE_TYPE 0x1000 +#define CL_DEVICE_VENDOR_ID 0x1001 +#define CL_DEVICE_MAX_COMPUTE_UNITS 0x1002 +#define CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS 0x1003 +#define CL_DEVICE_MAX_WORK_GROUP_SIZE 0x1004 +#define CL_DEVICE_MAX_WORK_ITEM_SIZES 0x1005 +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR 0x1006 +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT 0x1007 +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT 0x1008 +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG 0x1009 +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT 0x100A +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE 0x100B +#define CL_DEVICE_MAX_CLOCK_FREQUENCY 0x100C +#define CL_DEVICE_ADDRESS_BITS 0x100D +#define CL_DEVICE_MAX_READ_IMAGE_ARGS 0x100E +#define CL_DEVICE_MAX_WRITE_IMAGE_ARGS 0x100F +#define CL_DEVICE_MAX_MEM_ALLOC_SIZE 0x1010 +#define CL_DEVICE_IMAGE2D_MAX_WIDTH 0x1011 +#define CL_DEVICE_IMAGE2D_MAX_HEIGHT 0x1012 +#define CL_DEVICE_IMAGE3D_MAX_WIDTH 0x1013 +#define CL_DEVICE_IMAGE3D_MAX_HEIGHT 0x1014 +#define CL_DEVICE_IMAGE3D_MAX_DEPTH 0x1015 +#define CL_DEVICE_IMAGE_SUPPORT 0x1016 +#define CL_DEVICE_MAX_PARAMETER_SIZE 0x1017 +#define CL_DEVICE_MAX_SAMPLERS 0x1018 +#define CL_DEVICE_MEM_BASE_ADDR_ALIGN 0x1019 +#define CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE 0x101A +#define CL_DEVICE_SINGLE_FP_CONFIG 0x101B +#define CL_DEVICE_GLOBAL_MEM_CACHE_TYPE 0x101C +#define CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE 0x101D +#define CL_DEVICE_GLOBAL_MEM_CACHE_SIZE 0x101E +#define CL_DEVICE_GLOBAL_MEM_SIZE 0x101F +#define CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE 0x1020 +#define CL_DEVICE_MAX_CONSTANT_ARGS 0x1021 +#define CL_DEVICE_LOCAL_MEM_TYPE 0x1022 +#define CL_DEVICE_LOCAL_MEM_SIZE 0x1023 +#define CL_DEVICE_ERROR_CORRECTION_SUPPORT 0x1024 +#define CL_DEVICE_PROFILING_TIMER_RESOLUTION 0x1025 +#define CL_DEVICE_ENDIAN_LITTLE 0x1026 +#define CL_DEVICE_AVAILABLE 0x1027 +#define CL_DEVICE_COMPILER_AVAILABLE 0x1028 +#define CL_DEVICE_EXECUTION_CAPABILITIES 0x1029 +#define CL_DEVICE_QUEUE_PROPERTIES 0x102A +#define CL_DEVICE_NAME 0x102B +#define CL_DEVICE_VENDOR 0x102C +#define CL_DRIVER_VERSION 0x102D +#define CL_DEVICE_PROFILE 0x102E +#define CL_DEVICE_VERSION 0x102F +#define CL_DEVICE_EXTENSIONS 0x1030 +#define CL_DEVICE_PLATFORM 0x1031 + +// cl_device_fp_config - bitfield +#define CL_FP_DENORM (1 << 0) +#define CL_FP_INF_NAN (1 << 1) +#define CL_FP_ROUND_TO_NEAREST (1 << 2) +#define CL_FP_ROUND_TO_ZERO (1 << 3) +#define CL_FP_ROUND_TO_INF (1 << 4) +#define CL_FP_FMA (1 << 5) + +// cl_device_mem_cache_type +#define CL_NONE 0x0 +#define CL_READ_ONLY_CACHE 0x1 +#define CL_READ_WRITE_CACHE 0x2 + +// cl_device_local_mem_type +#define CL_LOCAL 0x1 +#define CL_GLOBAL 0x2 + +// cl_device_exec_capabilities - bitfield +#define CL_EXEC_KERNEL (1 << 0) +#define CL_EXEC_NATIVE_KERNEL (1 << 1) + +// cl_command_queue_properties - bitfield +#define CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE (1 << 0) +#define CL_QUEUE_PROFILING_ENABLE (1 << 1) + +// cl_context_info +#define CL_CONTEXT_REFERENCE_COUNT 0x1080 +#define CL_CONTEXT_DEVICES 0x1081 +#define CL_CONTEXT_PROPERTIES 0x1082 + +// cl_context_properties +#define CL_CONTEXT_PLATFORM 0x1084 + +// cl_command_queue_info +#define CL_QUEUE_CONTEXT 0x1090 +#define CL_QUEUE_DEVICE 0x1091 +#define CL_QUEUE_REFERENCE_COUNT 0x1092 +#define CL_QUEUE_PROPERTIES 0x1093 + +// cl_mem_flags - bitfield +#define CL_MEM_READ_WRITE (1 << 0) +#define CL_MEM_WRITE_ONLY (1 << 1) +#define CL_MEM_READ_ONLY (1 << 2) +#define CL_MEM_USE_HOST_PTR (1 << 3) +#define CL_MEM_ALLOC_HOST_PTR (1 << 4) +#define CL_MEM_COPY_HOST_PTR (1 << 5) + +// cl_channel_order +#define CL_R 0x10B0 +#define CL_A 0x10B1 +#define CL_RG 0x10B2 +#define CL_RA 0x10B3 +#define CL_RGB 0x10B4 +#define CL_RGBA 0x10B5 +#define CL_BGRA 0x10B6 +#define CL_ARGB 0x10B7 +#define CL_INTENSITY 0x10B8 +#define CL_LUMINANCE 0x10B9 + +// cl_channel_type +#define CL_SNORM_INT8 0x10D0 +#define CL_SNORM_INT16 0x10D1 +#define CL_UNORM_INT8 0x10D2 +#define CL_UNORM_INT16 0x10D3 +#define CL_UNORM_SHORT_565 0x10D4 +#define CL_UNORM_SHORT_555 0x10D5 +#define CL_UNORM_INT_101010 0x10D6 +#define CL_SIGNED_INT8 0x10D7 +#define CL_SIGNED_INT16 0x10D8 +#define CL_SIGNED_INT32 0x10D9 +#define CL_UNSIGNED_INT8 0x10DA +#define CL_UNSIGNED_INT16 0x10DB +#define CL_UNSIGNED_INT32 0x10DC +#define CL_HALF_FLOAT 0x10DD +#define CL_FLOAT 0x10DE + +// cl_mem_object_type +#define CL_MEM_OBJECT_BUFFER 0x10F0 +#define CL_MEM_OBJECT_IMAGE2D 0x10F1 +#define CL_MEM_OBJECT_IMAGE3D 0x10F2 + +// cl_mem_info +#define CL_MEM_TYPE 0x1100 +#define CL_MEM_FLAGS 0x1101 +#define CL_MEM_SIZE 0x1102 +#define CL_MEM_HOST_PTR 0x1103 +#define CL_MEM_MAP_COUNT 0x1104 +#define CL_MEM_REFERENCE_COUNT 0x1105 +#define CL_MEM_CONTEXT 0x1106 + +// cl_image_info +#define CL_IMAGE_FORMAT 0x1110 +#define CL_IMAGE_ELEMENT_SIZE 0x1111 +#define CL_IMAGE_ROW_PITCH 0x1112 +#define CL_IMAGE_SLICE_PITCH 0x1113 +#define CL_IMAGE_WIDTH 0x1114 +#define CL_IMAGE_HEIGHT 0x1115 +#define CL_IMAGE_DEPTH 0x1116 + +// cl_addressing_mode +#define CL_ADDRESS_NONE 0x1130 +#define CL_ADDRESS_CLAMP_TO_EDGE 0x1131 +#define CL_ADDRESS_CLAMP 0x1132 +#define CL_ADDRESS_REPEAT 0x1133 + +// cl_filter_mode +#define CL_FILTER_NEAREST 0x1140 +#define CL_FILTER_LINEAR 0x1141 + +// cl_sampler_info +#define CL_SAMPLER_REFERENCE_COUNT 0x1150 +#define CL_SAMPLER_CONTEXT 0x1151 +#define CL_SAMPLER_NORMALIZED_COORDS 0x1152 +#define CL_SAMPLER_ADDRESSING_MODE 0x1153 +#define CL_SAMPLER_FILTER_MODE 0x1154 + +// cl_map_flags - bitfield +#define CL_MAP_READ (1 << 0) +#define CL_MAP_WRITE (1 << 1) + +// cl_program_info +#define CL_PROGRAM_REFERENCE_COUNT 0x1160 +#define CL_PROGRAM_CONTEXT 0x1161 +#define CL_PROGRAM_NUM_DEVICES 0x1162 +#define CL_PROGRAM_DEVICES 0x1163 +#define CL_PROGRAM_SOURCE 0x1164 +#define CL_PROGRAM_BINARY_SIZES 0x1165 +#define CL_PROGRAM_BINARIES 0x1166 + +// cl_program_build_info +#define CL_PROGRAM_BUILD_STATUS 0x1181 +#define CL_PROGRAM_BUILD_OPTIONS 0x1182 +#define CL_PROGRAM_BUILD_LOG 0x1183 + +// cl_build_status +#define CL_BUILD_SUCCESS 0 +#define CL_BUILD_NONE -1 +#define CL_BUILD_ERROR -2 +#define CL_BUILD_IN_PROGRESS -3 + +// cl_kernel_info +#define CL_KERNEL_FUNCTION_NAME 0x1190 +#define CL_KERNEL_NUM_ARGS 0x1191 +#define CL_KERNEL_REFERENCE_COUNT 0x1192 +#define CL_KERNEL_CONTEXT 0x1193 +#define CL_KERNEL_PROGRAM 0x1194 + +// cl_kernel_work_group_info +#define CL_KERNEL_WORK_GROUP_SIZE 0x11B0 +#define CL_KERNEL_COMPILE_WORK_GROUP_SIZE 0x11B1 +#define CL_KERNEL_LOCAL_MEM_SIZE 0x11B2 + +// cl_event_info +#define CL_EVENT_COMMAND_QUEUE 0x11D0 +#define CL_EVENT_COMMAND_TYPE 0x11D1 +#define CL_EVENT_REFERENCE_COUNT 0x11D2 +#define CL_EVENT_COMMAND_EXECUTION_STATUS 0x11D3 + +// cl_command_type +#define CL_COMMAND_NDRANGE_KERNEL 0x11F0 +#define CL_COMMAND_TASK 0x11F1 +#define CL_COMMAND_NATIVE_KERNEL 0x11F2 +#define CL_COMMAND_READ_BUFFER 0x11F3 +#define CL_COMMAND_WRITE_BUFFER 0x11F4 +#define CL_COMMAND_COPY_BUFFER 0x11F5 +#define CL_COMMAND_READ_IMAGE 0x11F6 +#define CL_COMMAND_WRITE_IMAGE 0x11F7 +#define CL_COMMAND_COPY_IMAGE 0x11F8 +#define CL_COMMAND_COPY_IMAGE_TO_BUFFER 0x11F9 +#define CL_COMMAND_COPY_BUFFER_TO_IMAGE 0x11FA +#define CL_COMMAND_MAP_BUFFER 0x11FB +#define CL_COMMAND_MAP_IMAGE 0x11FC +#define CL_COMMAND_UNMAP_MEM_OBJECT 0x11FD +#define CL_COMMAND_MARKER 0x11FE +#define CL_COMMAND_ACQUIRE_GL_OBJECTS 0x11FF +#define CL_COMMAND_RELEASE_GL_OBJECTS 0x1200 + +// command execution status +#define CL_COMPLETE 0x0 +#define CL_RUNNING 0x1 +#define CL_SUBMITTED 0x2 +#define CL_QUEUED 0x3 + +// cl_profiling_info +#define CL_PROFILING_COMMAND_QUEUED 0x1280 +#define CL_PROFILING_COMMAND_SUBMIT 0x1281 +#define CL_PROFILING_COMMAND_START 0x1282 +#define CL_PROFILING_COMMAND_END 0x1283 + +/********************************************************************************************************/ + +/********************************************************************************************************/ + +// Function signature typedef's + +// Platform API +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLGETPLATFORMIDS)(cl_uint /* num_entries */, + cl_platform_id * /* platforms */, + cl_uint * /* num_platforms */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLGETPLATFORMINFO)(cl_platform_id /* platform */, + cl_platform_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Device APIs +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLGETDEVICEIDS)(cl_platform_id /* platform */, + cl_device_type /* device_type */, + cl_uint /* num_entries */, + cl_device_id * /* devices */, + cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLGETDEVICEINFO)(cl_device_id /* device */, + cl_device_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Context APIs +typedef CL_API_ENTRY cl_context (CL_API_CALL * +PFNCLCREATECONTEXT)(const cl_context_properties * /* properties */, + cl_uint /* num_devices */, + const cl_device_id * /* devices */, + void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */, + void * /* user_data */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_context (CL_API_CALL * +PFNCLCREATECONTEXTFROMTYPE)(const cl_context_properties * /* properties */, + cl_device_type /* device_type */, + void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */, + void * /* user_data */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLRETAINCONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLRELEASECONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLGETCONTEXTINFO)(cl_context /* context */, + cl_context_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Command Queue APIs +typedef CL_API_ENTRY cl_command_queue (CL_API_CALL * +PFNCLCREATECOMMANDQUEUE)(cl_context /* context */, + cl_device_id /* device */, + cl_command_queue_properties /* properties */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLRETAINCOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLRELEASECOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLGETCOMMANDQUEUEINFO)(cl_command_queue /* command_queue */, + cl_command_queue_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLSETCOMMANDQUEUEPROPERTY)(cl_command_queue /* command_queue */, + cl_command_queue_properties /* properties */, + cl_bool /* enable */, + cl_command_queue_properties * /* old_properties */) CL_API_SUFFIX__VERSION_1_0; + +// Memory Object APIs +typedef CL_API_ENTRY cl_mem (CL_API_CALL * +PFNCLCREATEBUFFER)(cl_context /* context */, + cl_mem_flags /* flags */, + size_t /* size */, + void * /* host_ptr */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_mem (CL_API_CALL * +PFNCLCREATEIMAGE2D)(cl_context /* context */, + cl_mem_flags /* flags */, + const cl_image_format * /* image_format */, + size_t /* image_width */, + size_t /* image_height */, + size_t /* image_row_pitch */, + void * /* host_ptr */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_mem (CL_API_CALL * +PFNCLCREATEIMAGE3D)(cl_context /* context */, + cl_mem_flags /* flags */, + const cl_image_format * /* image_format */, + size_t /* image_width */, + size_t /* image_height */, + size_t /* image_depth */, + size_t /* image_row_pitch */, + size_t /* image_slice_pitch */, + void * /* host_ptr */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLRETAINMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLRELEASEMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLGETSUPPORTEDIMAGEFORMATS)(cl_context /* context */, + cl_mem_flags /* flags */, + cl_mem_object_type /* image_type */, + cl_uint /* num_entries */, + cl_image_format * /* image_formats */, + cl_uint * /* num_image_formats */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLGETMEMOBJECTINFO)(cl_mem /* memobj */, + cl_mem_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLGETIMAGEINFO)(cl_mem /* image */, + cl_image_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Sampler APIs +typedef CL_API_ENTRY cl_sampler (CL_API_CALL * +PFNCLCREATESAMPLER)(cl_context /* context */, + cl_bool /* normalized_coords */, + cl_addressing_mode /* addressing_mode */, + cl_filter_mode /* filter_mode */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLRETAINSAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLRELEASESAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLGETSAMPLERINFO)(cl_sampler /* sampler */, + cl_sampler_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Program Object APIs +typedef CL_API_ENTRY cl_program (CL_API_CALL * +PFNCLCREATEPROGRAMWITHSOURCE)(cl_context /* context */, + cl_uint /* count */, + const char ** /* strings */, + const size_t * /* lengths */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_program (CL_API_CALL * +PFNCLCREATEPROGRAMWITHBINARY)(cl_context /* context */, + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const size_t * /* lengths */, + const unsigned char ** /* binaries */, + cl_int * /* binary_status */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLRETAINPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLRELEASEPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLBUILDPROGRAM)(cl_program /* program */, + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const char * /* options */, + void (*pfn_notify)(cl_program /* program */, void * /* user_data */), + void * /* user_data */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLUNLOADCOMPILER)(void) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLGETPROGRAMINFO)(cl_program /* program */, + cl_program_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLGETPROGRAMBUILDINFO)(cl_program /* program */, + cl_device_id /* device */, + cl_program_build_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Kernel Object APIs +typedef CL_API_ENTRY cl_kernel (CL_API_CALL * +PFNCLCREATEKERNEL)(cl_program /* program */, + const char * /* kernel_name */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLCREATEKERNELSINPROGRAM)(cl_program /* program */, + cl_uint /* num_kernels */, + cl_kernel * /* kernels */, + cl_uint * /* num_kernels_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLRETAINKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLRELEASEKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLSETKERNELARG)(cl_kernel /* kernel */, + cl_uint /* arg_index */, + size_t /* arg_size */, + const void * /* arg_value */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLGETKERNELINFO)(cl_kernel /* kernel */, + cl_kernel_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLGETKERNELWORKGROUPINFO)(cl_kernel /* kernel */, + cl_device_id /* device */, + cl_kernel_work_group_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Event Object APIs +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLWAITFOREVENTS)(cl_uint /* num_events */, + const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLGETEVENTINFO)(cl_event /* event */, + cl_event_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLRETAINEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLRELEASEEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0; + +// Profiling APIs +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLGETEVENTPROFILINGINFO)(cl_event /* event */, + cl_profiling_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Flush and Finish APIs +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLFLUSH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLFINISH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + +// Enqueued Commands APIs +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLENQUEUEREADBUFFER)(cl_command_queue /* command_queue */, + cl_mem /* buffer */, + cl_bool /* blocking_read */, + size_t /* offset */, + size_t /* cb */, + void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLENQUEUEWRITEBUFFER)(cl_command_queue /* command_queue */, + cl_mem /* buffer */, + cl_bool /* blocking_write */, + size_t /* offset */, + size_t /* cb */, + const void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLENQUEUECOPYBUFFER)(cl_command_queue /* command_queue */, + cl_mem /* src_buffer */, + cl_mem /* dst_buffer */, + size_t /* src_offset */, + size_t /* dst_offset */, + size_t /* cb */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLENQUEUEREADIMAGE)(cl_command_queue /* command_queue */, + cl_mem /* image */, + cl_bool /* blocking_read */, + const size_t * /* origin[3] */, + const size_t * /* region[3] */, + size_t /* row_pitch */, + size_t /* slice_pitch */, + void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLENQUEUEWRITEIMAGE)(cl_command_queue /* command_queue */, + cl_mem /* image */, + cl_bool /* blocking_write */, + const size_t * /* origin[3] */, + const size_t * /* region[3] */, + size_t /* input_row_pitch */, + size_t /* input_slice_pitch */, + const void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLENQUEUECOPYIMAGE)(cl_command_queue /* command_queue */, + cl_mem /* src_image */, + cl_mem /* dst_image */, + const size_t * /* src_origin[3] */, + const size_t * /* dst_origin[3] */, + const size_t * /* region[3] */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLENQUEUECOPYIMAGETOBUFFER)(cl_command_queue /* command_queue */, + cl_mem /* src_image */, + cl_mem /* dst_buffer */, + const size_t * /* src_origin[3] */, + const size_t * /* region[3] */, + size_t /* dst_offset */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLENQUEUECOPYBUFFERTOIMAGE)(cl_command_queue /* command_queue */, + cl_mem /* src_buffer */, + cl_mem /* dst_image */, + size_t /* src_offset */, + const size_t * /* dst_origin[3] */, + const size_t * /* region[3] */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY void * (CL_API_CALL * +PFNCLENQUEUEMAPBUFFER)(cl_command_queue /* command_queue */, + cl_mem /* buffer */, + cl_bool /* blocking_map */, + cl_map_flags /* map_flags */, + size_t /* offset */, + size_t /* cb */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY void * (CL_API_CALL * +PFNCLENQUEUEMAPIMAGE)(cl_command_queue /* command_queue */, + cl_mem /* image */, + cl_bool /* blocking_map */, + cl_map_flags /* map_flags */, + const size_t * /* origin[3] */, + const size_t * /* region[3] */, + size_t * /* image_row_pitch */, + size_t * /* image_slice_pitch */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLENQUEUEUNMAPMEMOBJECT)(cl_command_queue /* command_queue */, + cl_mem /* memobj */, + void * /* mapped_ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLENQUEUENDRANGEKERNEL)(cl_command_queue /* command_queue */, + cl_kernel /* kernel */, + cl_uint /* work_dim */, + const size_t * /* global_work_offset */, + const size_t * /* global_work_size */, + const size_t * /* local_work_size */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLENQUEUETASK)(cl_command_queue /* command_queue */, + cl_kernel /* kernel */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLENQUEUENATIVEKERNEL)(cl_command_queue /* command_queue */, + void (*user_func)(void *), + void * /* args */, + size_t /* cb_args */, + cl_uint /* num_mem_objects */, + const cl_mem * /* mem_list */, + const void ** /* args_mem_loc */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLENQUEUEMARKER)(cl_command_queue /* command_queue */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLENQUEUEWAITFOREVENTS)(cl_command_queue /* command_queue */, + cl_uint /* num_events */, + const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL * +PFNCLENQUEUEBARRIER)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + +// Extension function access +// +// Returns the extension function address for the given function name, +// or NULL if a valid function can not be found. The client must +// check to make sure the address is not NULL, before using or +// calling the returned function address. +// +typedef CL_API_ENTRY void * (CL_API_CALL * PFNCLGETEXTENSIONFUNCTIONADDRESS)(const char * /* func_name */) CL_API_SUFFIX__VERSION_1_0; + + +#define CLEW_STATIC + +#ifdef CLEW_STATIC +# define CLEWAPI extern +#else +# ifdef CLEW_BUILD +# define CLEWAPI extern __declspec(dllexport) +# else +# define CLEWAPI extern __declspec(dllimport) +# endif +#endif + +#if defined(_WIN32) +#define CLEW_FUN_EXPORT extern +#else +#define CLEW_FUN_EXPORT CLEWAPI +#endif + +#define CLEW_GET_FUN(x) x + + +// Variables holding function entry points +CLEW_FUN_EXPORT PFNCLGETPLATFORMIDS __clewGetPlatformIDs ; +CLEW_FUN_EXPORT PFNCLGETPLATFORMINFO __clewGetPlatformInfo ; +CLEW_FUN_EXPORT PFNCLGETDEVICEIDS __clewGetDeviceIDs ; +CLEW_FUN_EXPORT PFNCLGETDEVICEINFO __clewGetDeviceInfo ; +CLEW_FUN_EXPORT PFNCLCREATECONTEXT __clewCreateContext ; +CLEW_FUN_EXPORT PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType ; +CLEW_FUN_EXPORT PFNCLRETAINCONTEXT __clewRetainContext ; +CLEW_FUN_EXPORT PFNCLRELEASECONTEXT __clewReleaseContext ; +CLEW_FUN_EXPORT PFNCLGETCONTEXTINFO __clewGetContextInfo ; +CLEW_FUN_EXPORT PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue ; +CLEW_FUN_EXPORT PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue ; +CLEW_FUN_EXPORT PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue ; +CLEW_FUN_EXPORT PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo ; +CLEW_FUN_EXPORT PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty ; +CLEW_FUN_EXPORT PFNCLCREATEBUFFER __clewCreateBuffer ; +CLEW_FUN_EXPORT PFNCLCREATEIMAGE2D __clewCreateImage2D ; +CLEW_FUN_EXPORT PFNCLCREATEIMAGE3D __clewCreateImage3D ; +CLEW_FUN_EXPORT PFNCLRETAINMEMOBJECT __clewRetainMemObject ; +CLEW_FUN_EXPORT PFNCLRELEASEMEMOBJECT __clewReleaseMemObject ; +CLEW_FUN_EXPORT PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats ; +CLEW_FUN_EXPORT PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo ; +CLEW_FUN_EXPORT PFNCLGETIMAGEINFO __clewGetImageInfo ; +CLEW_FUN_EXPORT PFNCLCREATESAMPLER __clewCreateSampler ; +CLEW_FUN_EXPORT PFNCLRETAINSAMPLER __clewRetainSampler ; +CLEW_FUN_EXPORT PFNCLRELEASESAMPLER __clewReleaseSampler ; +CLEW_FUN_EXPORT PFNCLGETSAMPLERINFO __clewGetSamplerInfo ; +CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource ; +CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary ; +CLEW_FUN_EXPORT PFNCLRETAINPROGRAM __clewRetainProgram ; +CLEW_FUN_EXPORT PFNCLRELEASEPROGRAM __clewReleaseProgram ; +CLEW_FUN_EXPORT PFNCLBUILDPROGRAM __clewBuildProgram ; +CLEW_FUN_EXPORT PFNCLUNLOADCOMPILER __clewUnloadCompiler ; +CLEW_FUN_EXPORT PFNCLGETPROGRAMINFO __clewGetProgramInfo ; +CLEW_FUN_EXPORT PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo ; +CLEW_FUN_EXPORT PFNCLCREATEKERNEL __clewCreateKernel ; +CLEW_FUN_EXPORT PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram ; +CLEW_FUN_EXPORT PFNCLRETAINKERNEL __clewRetainKernel ; +CLEW_FUN_EXPORT PFNCLRELEASEKERNEL __clewReleaseKernel ; +CLEW_FUN_EXPORT PFNCLSETKERNELARG __clewSetKernelArg ; +CLEW_FUN_EXPORT PFNCLGETKERNELINFO __clewGetKernelInfo ; +CLEW_FUN_EXPORT PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo ; +CLEW_FUN_EXPORT PFNCLWAITFOREVENTS __clewWaitForEvents ; +CLEW_FUN_EXPORT PFNCLGETEVENTINFO __clewGetEventInfo ; +CLEW_FUN_EXPORT PFNCLRETAINEVENT __clewRetainEvent ; +CLEW_FUN_EXPORT PFNCLRELEASEEVENT __clewReleaseEvent ; +CLEW_FUN_EXPORT PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo ; +CLEW_FUN_EXPORT PFNCLFLUSH __clewFlush ; +CLEW_FUN_EXPORT PFNCLFINISH __clewFinish ; +CLEW_FUN_EXPORT PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer ; +CLEW_FUN_EXPORT PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer ; +CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer ; +CLEW_FUN_EXPORT PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage ; +CLEW_FUN_EXPORT PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage ; +CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage ; +CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer ; +CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage ; +CLEW_FUN_EXPORT PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer ; +CLEW_FUN_EXPORT PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage ; +CLEW_FUN_EXPORT PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject ; +CLEW_FUN_EXPORT PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel ; +CLEW_FUN_EXPORT PFNCLENQUEUETASK __clewEnqueueTask ; +CLEW_FUN_EXPORT PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel ; +CLEW_FUN_EXPORT PFNCLENQUEUEMARKER __clewEnqueueMarker ; +CLEW_FUN_EXPORT PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents ; +CLEW_FUN_EXPORT PFNCLENQUEUEBARRIER __clewEnqueueBarrier ; +CLEW_FUN_EXPORT PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress ; + + +#define clGetPlatformIDs CLEW_GET_FUN(__clewGetPlatformIDs ) +#define clGetPlatformInfo CLEW_GET_FUN(__clewGetPlatformInfo ) +#define clGetDeviceIDs CLEW_GET_FUN(__clewGetDeviceIDs ) +#define clGetDeviceInfo CLEW_GET_FUN(__clewGetDeviceInfo ) +#define clCreateContext CLEW_GET_FUN(__clewCreateContext ) +#define clCreateContextFromType CLEW_GET_FUN(__clewCreateContextFromType ) +#define clRetainContext CLEW_GET_FUN(__clewRetainContext ) +#define clReleaseContext CLEW_GET_FUN(__clewReleaseContext ) +#define clGetContextInfo CLEW_GET_FUN(__clewGetContextInfo ) +#define clCreateCommandQueue CLEW_GET_FUN(__clewCreateCommandQueue ) +#define clRetainCommandQueue CLEW_GET_FUN(__clewRetainCommandQueue ) +#define clReleaseCommandQueue CLEW_GET_FUN(__clewReleaseCommandQueue ) +#define clGetCommandQueueInfo CLEW_GET_FUN(__clewGetCommandQueueInfo ) +#define clSetCommandQueueProperty CLEW_GET_FUN(__clewSetCommandQueueProperty ) +#define clCreateBuffer CLEW_GET_FUN(__clewCreateBuffer ) +#define clCreateImage2D CLEW_GET_FUN(__clewCreateImage2D ) +#define clCreateImage3D CLEW_GET_FUN(__clewCreateImage3D ) +#define clRetainMemObject CLEW_GET_FUN(__clewRetainMemObject ) +#define clReleaseMemObject CLEW_GET_FUN(__clewReleaseMemObject ) +#define clGetSupportedImageFormats CLEW_GET_FUN(__clewGetSupportedImageFormats ) +#define clGetMemObjectInfo CLEW_GET_FUN(__clewGetMemObjectInfo ) +#define clGetImageInfo CLEW_GET_FUN(__clewGetImageInfo ) +#define clCreateSampler CLEW_GET_FUN(__clewCreateSampler ) +#define clRetainSampler CLEW_GET_FUN(__clewRetainSampler ) +#define clReleaseSampler CLEW_GET_FUN(__clewReleaseSampler ) +#define clGetSamplerInfo CLEW_GET_FUN(__clewGetSamplerInfo ) +#define clCreateProgramWithSource CLEW_GET_FUN(__clewCreateProgramWithSource ) +#define clCreateProgramWithBinary CLEW_GET_FUN(__clewCreateProgramWithBinary ) +#define clRetainProgram CLEW_GET_FUN(__clewRetainProgram ) +#define clReleaseProgram CLEW_GET_FUN(__clewReleaseProgram ) +#define clBuildProgram CLEW_GET_FUN(__clewBuildProgram ) +#define clUnloadCompiler CLEW_GET_FUN(__clewUnloadCompiler ) +#define clGetProgramInfo CLEW_GET_FUN(__clewGetProgramInfo ) +#define clGetProgramBuildInfo CLEW_GET_FUN(__clewGetProgramBuildInfo ) +#define clCreateKernel CLEW_GET_FUN(__clewCreateKernel ) +#define clCreateKernelsInProgram CLEW_GET_FUN(__clewCreateKernelsInProgram ) +#define clRetainKernel CLEW_GET_FUN(__clewRetainKernel ) +#define clReleaseKernel CLEW_GET_FUN(__clewReleaseKernel ) +#define clSetKernelArg CLEW_GET_FUN(__clewSetKernelArg ) +#define clGetKernelInfo CLEW_GET_FUN(__clewGetKernelInfo ) +#define clGetKernelWorkGroupInfo CLEW_GET_FUN(__clewGetKernelWorkGroupInfo ) +#define clWaitForEvents CLEW_GET_FUN(__clewWaitForEvents ) +#define clGetEventInfo CLEW_GET_FUN(__clewGetEventInfo ) +#define clRetainEvent CLEW_GET_FUN(__clewRetainEvent ) +#define clReleaseEvent CLEW_GET_FUN(__clewReleaseEvent ) +#define clGetEventProfilingInfo CLEW_GET_FUN(__clewGetEventProfilingInfo ) +#define clFlush CLEW_GET_FUN(__clewFlush ) +#define clFinish CLEW_GET_FUN(__clewFinish ) +#define clEnqueueReadBuffer CLEW_GET_FUN(__clewEnqueueReadBuffer ) +#define clEnqueueWriteBuffer CLEW_GET_FUN(__clewEnqueueWriteBuffer ) +#define clEnqueueCopyBuffer CLEW_GET_FUN(__clewEnqueueCopyBuffer ) +#define clEnqueueReadImage CLEW_GET_FUN(__clewEnqueueReadImage ) +#define clEnqueueWriteImage CLEW_GET_FUN(__clewEnqueueWriteImage ) +#define clEnqueueCopyImage CLEW_GET_FUN(__clewEnqueueCopyImage ) +#define clEnqueueCopyImageToBuffer CLEW_GET_FUN(__clewEnqueueCopyImageToBuffer ) +#define clEnqueueCopyBufferToImage CLEW_GET_FUN(__clewEnqueueCopyBufferToImage ) +#define clEnqueueMapBuffer CLEW_GET_FUN(__clewEnqueueMapBuffer ) +#define clEnqueueMapImage CLEW_GET_FUN(__clewEnqueueMapImage ) +#define clEnqueueUnmapMemObject CLEW_GET_FUN(__clewEnqueueUnmapMemObject ) +#define clEnqueueNDRangeKernel CLEW_GET_FUN(__clewEnqueueNDRangeKernel ) +#define clEnqueueTask CLEW_GET_FUN(__clewEnqueueTask ) +#define clEnqueueNativeKernel CLEW_GET_FUN(__clewEnqueueNativeKernel ) +#define clEnqueueMarker CLEW_GET_FUN(__clewEnqueueMarker ) +#define clEnqueueWaitForEvents CLEW_GET_FUN(__clewEnqueueWaitForEvents ) +#define clEnqueueBarrier CLEW_GET_FUN(__clewEnqueueBarrier ) +#define clGetExtensionFunctionAddress CLEW_GET_FUN(__clewGetExtensionFunctionAddress ) + +#endif // CLCC_GENERATE_DOCUMENTATION + +#define CLEW_SUCCESS 0 //!< Success error code +#define CLEW_ERROR_OPEN_FAILED -1 //!< Error code for failing to open the dynamic library +#define CLEW_ERROR_ATEXIT_FAILED -2 //!< Error code for failing to queue the closing of the dynamic library to atexit() + +//! \brief Load OpenCL dynamic library and set function entry points +int clewInit (const char*); +//! \brief Convert an OpenCL error code to its string equivalent +const char* clewErrorString (cl_int error); + +#ifdef __cplusplus +} +#endif +#endif //USE_MINICL +#endif // CLCC_CLEW_HPP_INCLUDED diff --git a/Demos/SimplexDemo/CMakeLists.txt b/Demos/SimplexDemo/CMakeLists.txt new file mode 100644 index 0000000..9556823 --- /dev/null +++ b/Demos/SimplexDemo/CMakeLists.txt @@ -0,0 +1,48 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppSimplexDemo + SimplexDemo.cpp +) + +IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppSimplexDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppSimplexDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF(WIN32) + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppSimplexDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppSimplexDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppSimplexDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/SimplexDemo/SimplexDemo.cpp b/Demos/SimplexDemo/SimplexDemo.cpp new file mode 100644 index 0000000..f804c73 --- /dev/null +++ b/Demos/SimplexDemo/SimplexDemo.cpp @@ -0,0 +1,123 @@ +/* +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. +*/ + +/* + SimplexDemo demonstrated the working of the subdistance algorithm as used in GJK. + It draws the simplex, and calculates the closest vector from simplex to the origin +*/ + +#include "GL_Simplex1to4.h" +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btTransform.h" +#include "GL_ShapeDrawer.h" + +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "SimplexDemo.h" +#include "GlutStuff.h" + +btVoronoiSimplexSolver simplexSolver; + + + +float yaw=0.f,pitch=0.f,roll=0.f; +const int maxNumObjects = 4; +const int numObjects = 1; +int screenWidth = 640; +int screenHeight = 480; +/// simplex contains the vertices, and some extra code to draw and debug +GL_Simplex1to4 simplex; + + +btPolyhedralConvexShape* shapePtr[maxNumObjects]; + + +/// +/// +/// +int main(int argc,char** argv) +{ + + SimplexDemo* demo = new SimplexDemo(); + + demo->initPhysics(); + + return glutmain(argc, argv,screenWidth,screenHeight,"SimplexDemo",demo); +} + +//to be implemented by the demo + +void SimplexDemo::clientMoveAndDisplay() +{ + + displayCallback(); +} + + + +void SimplexDemo::displayCallback() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glDisable(GL_LIGHTING); + + GL_ShapeDrawer::drawCoordSystem(); + + btScalar m[16]; + int i; + + btVector3 worldBoundsMin(-1000,-1000,-1000); + btVector3 worldBoundsMax(1000,1000,1000); + + for (i=0;idrawOpenGL(m,shapePtr[i],btVector3(1,1,1),getDebugMode(),worldBoundsMin,worldBoundsMax); + + /// calculate closest point from simplex to the origin, and draw this vector + simplex.calcClosest(m); + + } + pitch += 0.005f; + yaw += 0.01f; + + glFlush(); + glutSwapBuffers(); +} + +void SimplexDemo::initPhysics() +{ + + simplex.setSimplexSolver(&simplexSolver); + + simplex.addVertex(btVector3(-2,0,-2)); + simplex.addVertex(btVector3(2,0,-2)); + simplex.addVertex(btVector3(0,0,2)); + simplex.addVertex(btVector3(0,2,0)); + + shapePtr[0] = &simplex; + + btTransform tr; + tr.setIdentity(); +} + + diff --git a/Demos/SimplexDemo/SimplexDemo.h b/Demos/SimplexDemo/SimplexDemo.h new file mode 100644 index 0000000..72f6200 --- /dev/null +++ b/Demos/SimplexDemo/SimplexDemo.h @@ -0,0 +1,36 @@ +/* +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 SIMPLEX_DEMO_H +#define SIMPLEX_DEMO_H + +#include "GlutDemoApplication.h" + +///SimplexDemo shows the working of the sub-distance algorithm, used inside GJK +class SimplexDemo : public GlutDemoApplication +{ + public: + + void initPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + +}; + +#endif //SIMPLEX_DEMO_H + + diff --git a/Demos/SliderConstraintDemo/CMakeLists.txt b/Demos/SliderConstraintDemo/CMakeLists.txt new file mode 100644 index 0000000..d43bce4 --- /dev/null +++ b/Demos/SliderConstraintDemo/CMakeLists.txt @@ -0,0 +1,51 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( +OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppSliderConstraintDemo + SliderConstraintDemo.cpp + main.cpp +) + +IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppSliderConstraintDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppSliderConstraintDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF(WIN32) + + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppSliderConstraintDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppSliderConstraintDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppSliderConstraintDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/SliderConstraintDemo/SliderConstraintDemo.cpp b/Demos/SliderConstraintDemo/SliderConstraintDemo.cpp new file mode 100755 index 0000000..15e392f --- /dev/null +++ b/Demos/SliderConstraintDemo/SliderConstraintDemo.cpp @@ -0,0 +1,512 @@ +/* +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. +*/ + +/* +Added by Roman Ponomarev (rponom@gmail.com) +April 04, 2008 + +Added support for ODE sover +April 24, 2008 +*/ + + + + +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btIDebugDraw.h" + +#include "GLDebugDrawer.h" + + +#include //printf debugging + +#include "SliderConstraintDemo.h" +#include "GL_ShapeDrawer.h" +#include "GlutStuff.h" + + + +#define SLIDER_DEMO_USE_ODE_SOLVER 0 +#define SLIDER_DEMO_USE_6DOF 0 + +#define CUBE_HALF_EXTENTS 1.f + +#define SLIDER_ENABLE_ALL_DEMOS 1 + + + +// A couple of sliders +#if SLIDER_DEMO_USE_6DOF + static btGeneric6DofConstraint *spSlider1, *spSlider2; +#else + static btSliderConstraint *spSlider1, *spSlider2; +#endif + +static btPoint2PointConstraint* spP2PConst; +static btHingeConstraint* spHingeConst; + + + +static void draw_axes(const btRigidBody& rb, const btTransform& frame) +{ + glBegin(GL_LINES); + // draw world transform + btVector3 from = rb.getWorldTransform().getOrigin(); + btVector3 to = from + rb.getWorldTransform().getBasis() * btVector3(5,0,0); + // X in red + glColor3f(255.0F, 0.0F, 0.0F); + glVertex3d(from.getX(), from.getY(), from.getZ()); + glVertex3d(to.getX(), to.getY(), to.getZ()); + to = from + rb.getWorldTransform().getBasis() * btVector3(0,5,0); + // Y in green + glColor3f(0.0F, 255.0F, 0.0F); + glVertex3d(from.getX(), from.getY(), from.getZ()); + glVertex3d(to.getX(), to.getY(), to.getZ()); + to = from + rb.getWorldTransform().getBasis() * btVector3(0,0,5); + // Z in blue + glColor3f(0.0F, 0.0F, 255.0F); + glVertex3d(from.getX(), from.getY(), from.getZ()); + glVertex3d(to.getX(), to.getY(), to.getZ()); + // draw slider frame + btTransform calc_frame = rb.getWorldTransform() * frame; + from = calc_frame.getOrigin(); + to = from + calc_frame.getBasis() * btVector3(10,0,0); + // X in red + glColor3f(255.0F, 0.0F, 0.0F); + glVertex3d(from.getX(), from.getY(), from.getZ()); + glVertex3d(to.getX(), to.getY(), to.getZ()); + to = from + calc_frame.getBasis() * btVector3(0,10,0); + // Y in green + glColor3f(0.0F, 255.0F, 0.0F); + glVertex3d(from.getX(), from.getY(), from.getZ()); + glVertex3d(to.getX(), to.getY(), to.getZ()); + to = from + calc_frame.getBasis() * btVector3(0,0,10); + // Z in blue + glColor3f(0.0F, 0.0F, 255.0F); + glVertex3d(from.getX(), from.getY(), from.getZ()); + glVertex3d(to.getX(), to.getY(), to.getZ()); + glEnd(); +} // draw_axes() + + + +#if SLIDER_DEMO_USE_6DOF +static void drawSlider(btGeneric6DofConstraint* pSlider) +{ + draw_axes(pSlider->getRigidBodyA(), pSlider->getFrameOffsetA()); + draw_axes(pSlider->getRigidBodyB(), pSlider->getFrameOffsetB()); +} // drawSlider() +#else +static void drawSlider(btSliderConstraint* pSlider) +{ + draw_axes(pSlider->getRigidBodyA(), pSlider->getFrameOffsetA()); + draw_axes(pSlider->getRigidBodyB(), pSlider->getFrameOffsetB()); + // draw limits in white + btVector3 from(pSlider->getLowerLinLimit(), 0, 0); + btVector3 to(pSlider->getUpperLinLimit(), 0, 0); + btTransform trans; + if(pSlider->getUseLinearReferenceFrameA()) + { + trans = pSlider->getRigidBodyA().getWorldTransform() * pSlider->getFrameOffsetA(); + } + else + { + trans = pSlider->getRigidBodyB().getWorldTransform() * pSlider->getFrameOffsetB(); + } + from = trans * from; + to = trans * to; + glBegin(GL_LINES); + glColor3f(255.0F, 255.0F, 255.0F); + glVertex3d(from.getX(), from.getY(), from.getZ()); + glVertex3d(to.getX(), to.getY(), to.getZ()); + glEnd(); +} // drawSlider() +#endif + + + +void SliderConstraintDemo::initPhysics() +{ + setTexturing(true); + setShadows(true); + + setCameraDistance(26.f); + + // init world + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + btVector3 worldMin(-1000,-1000,-1000); + btVector3 worldMax(1000,1000,1000); + m_overlappingPairCache = new btAxisSweep3(worldMin,worldMax); + +#if SLIDER_DEMO_USE_ODE_SOLVER + m_constraintSolver = new btOdeQuickstepConstraintSolver(); +#else + m_constraintSolver = new btSequentialImpulseConstraintSolver(); +#endif + + btDiscreteDynamicsWorld* wp = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_constraintSolver,m_collisionConfiguration); + // wp->getSolverInfo().m_numIterations = 20; // default is 10 + m_dynamicsWorld = wp; +// wp->getSolverInfo().m_erp = 0.8; + + // add floor + //btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); + m_collisionShapes.push_back(groundShape); + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-76,0)); + btRigidBody* groundBody; + groundBody = localCreateRigidBody(0, groundTransform, groundShape); + + // add box shape (will be reused for all bodies) + btCollisionShape* shape = new btBoxShape(btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS)); + m_collisionShapes.push_back(shape); + // mass of dymamic bodies + btScalar mass = btScalar(1.); + + // add dynamic rigid body A1 + btTransform trans; + trans.setIdentity(); + btVector3 worldPos(-20,0,0); + trans.setOrigin(worldPos); + btTransform frameInA, frameInB; + frameInA = btTransform::getIdentity(); + frameInB = btTransform::getIdentity(); + +#if SLIDER_ENABLE_ALL_DEMOS + btRigidBody* pRbA1 = localCreateRigidBody(mass, trans, shape); +// btRigidBody* pRbA1 = localCreateRigidBody(0.f, trans, shape); + pRbA1->setActivationState(DISABLE_DEACTIVATION); + + // add dynamic rigid body B1 + worldPos.setValue(-30,0,0); + trans.setOrigin(worldPos); + btRigidBody* pRbB1 = localCreateRigidBody(mass, trans, shape); +// btRigidBody* pRbB1 = localCreateRigidBody(0.f, trans, shape); + pRbB1->setActivationState(DISABLE_DEACTIVATION); + + // create slider constraint between A1 and B1 and add it to world + +#if SLIDER_DEMO_USE_6DOF + spSlider1 = new btGeneric6DofConstraint(*pRbA1, *pRbB1, frameInA, frameInB, true); + btVector3 lowerSliderLimit = btVector3(-20,0,0); + btVector3 hiSliderLimit = btVector3(-10,0,0); +// btVector3 lowerSliderLimit = btVector3(-20,-5,-5); +// btVector3 hiSliderLimit = btVector3(-10,5,5); + spSlider1->setLinearLowerLimit(lowerSliderLimit); + spSlider1->setLinearUpperLimit(hiSliderLimit); + spSlider1->setAngularLowerLimit(btVector3(0,0,0)); + spSlider1->setAngularUpperLimit(btVector3(0,0,0)); +#else + spSlider1 = new btSliderConstraint(*pRbA1, *pRbB1, frameInA, frameInB, true); +// spSlider1 = new btSliderConstraint(*pRbA1, *pRbB1, frameInA, frameInB, false); + spSlider1->setLowerLinLimit(-15.0F); + spSlider1->setUpperLinLimit(-5.0F); +// spSlider1->setLowerLinLimit(5.0F); +// spSlider1->setUpperLinLimit(15.0F); +// spSlider1->setLowerLinLimit(-10.0F); +// spSlider1->setUpperLinLimit(-10.0F); + + spSlider1->setLowerAngLimit(-SIMD_PI / 3.0F); + spSlider1->setUpperAngLimit( SIMD_PI / 3.0F); +#endif + + m_dynamicsWorld->addConstraint(spSlider1, true); + spSlider1->setDbgDrawSize(btScalar(5.f)); +#endif + +#if SLIDER_ENABLE_ALL_DEMOS + // add kinematic rigid body A2 +// worldPos.setValue(20,4,0); + worldPos.setValue(5,-20,0); + trans.setOrigin(worldPos); + btRigidBody* pRbA2 = localCreateRigidBody(0., trans, shape); +// btRigidBody* pRbA2 = localCreateRigidBody(mass, trans, shape); +// btRigidBody* pRbA2 = localCreateRigidBody(mass * 10000, trans, shape); + pRbA2->setActivationState(DISABLE_DEACTIVATION); + + // add dynamic rigid body B2 +// worldPos.setValue(-20,4,0); + worldPos.setValue(-5,-20,0); + trans.setOrigin(worldPos); +// btRigidBody* pRbB2 = localCreateRigidBody(0., trans, shape); + btRigidBody* pRbB2 = localCreateRigidBody(mass, trans, shape); +// btRigidBody* pRbB2 = localCreateRigidBody(mass * 10000, trans, shape); + pRbB2->setActivationState(DISABLE_DEACTIVATION); + +// frameInA.getBasis().setEulerZYX(1.f, 1.f, 1.f); +// frameInB.getBasis().setEulerZYX(1.f, 1.f, 1.f); +// frameInA.getBasis().setEulerZYX(1.f, 1.f, 1.f); +// frameInB.getBasis().setEulerZYX(1.f, 1.f, 1.f); + + +// frameInA.setOrigin(btVector3(-20., 5., 0)); +// frameInB.setOrigin(btVector3( 20., 5., 0)); + frameInA.setOrigin(btVector3(-5., 20., 0)); + frameInB.setOrigin(btVector3( 5., 20., 0)); + + + // create slider constraint between A2 and B2 and add it to world +#if SLIDER_DEMO_USE_6DOF + spSlider2 = new btGeneric6DofConstraint(*pRbA2, *pRbB2, frameInA, frameInB, true); + spSlider2->setLinearLowerLimit(lowerSliderLimit); + spSlider2->setLinearUpperLimit(hiSliderLimit); + spSlider2->setAngularLowerLimit(btVector3(0,0,0)); + spSlider2->setAngularUpperLimit(btVector3(0,0,0)); +#else + spSlider2 = new btSliderConstraint(*pRbA2, *pRbB2, frameInA, frameInB, true); +// spSlider2 = new btSliderConstraint(*pRbA2, *pRbB2, frameInA, frameInB, false); +// spSlider2->setLowerLinLimit(0.0F); +// spSlider2->setUpperLinLimit(0.0F); + spSlider2->setLowerLinLimit(-2.0F); + spSlider2->setUpperLinLimit(2.0F); +// spSlider2->setLowerLinLimit(5.0F); +// spSlider2->setUpperLinLimit(25.0F); +// spSlider2->setUpperLinLimit(-5.0F); +// spSlider2->setUpperLinLimit(-9.99F); + + +// spSlider2->setLowerAngLimit(SIMD_PI / 2.0F); +// spSlider2->setUpperAngLimit(-SIMD_PI / 2.0F); + + // spSlider2->setLowerAngLimit(-SIMD_PI / 2.0F); +// spSlider2->setUpperAngLimit(SIMD_PI / 2.0F); + +// spSlider2->setLowerAngLimit(-SIMD_PI); +// spSlider2->setUpperAngLimit(SIMD_PI *0.8F); + + +// spSlider2->setLowerAngLimit(-0.01F); +// spSlider2->setUpperAngLimit(0.01F); + spSlider2->setLowerAngLimit(-1.570796326F * 0.5f); + spSlider2->setUpperAngLimit(1.570796326F * 0.5f); +// spSlider2->setLowerAngLimit(1.F); +// spSlider2->setUpperAngLimit(-1.F); + + +// spSlider2->setDampingLimLin(0.5f); + +#if 0 + // add motors + spSlider2->setPoweredLinMotor(true); + spSlider2->setMaxLinMotorForce(0.1); + spSlider2->setTargetLinMotorVelocity(-5.0); + + spSlider2->setPoweredAngMotor(true); +// spSlider2->setMaxAngMotorForce(0.01); + spSlider2->setMaxAngMotorForce(10.0); + spSlider2->setTargetAngMotorVelocity(1.0); + + // change default damping and restitution + + spSlider2->setDampingDirLin(0.005F); + spSlider2->setRestitutionLimLin(1.1F); +#endif + + // various ODE tests +// spSlider2->setDampingLimLin(0.1F); // linear bounce factor for ODE == 1.0 - DampingLimLin; +// spSlider2->setDampingLimAng(0.1F); // angular bounce factor for ODE == 1.0 - DampingLimAng; +// spSlider2->setSoftnessOrthoAng(0.1); +// spSlider2->setSoftnessOrthoLin(0.1); +// spSlider2->setSoftnessLimLin(0.1); +// spSlider2->setSoftnessLimAng(0.1); +#endif + m_dynamicsWorld->addConstraint(spSlider2, true); + spSlider2->setDbgDrawSize(btScalar(5.f)); +#endif + +#if SLIDER_ENABLE_ALL_DEMOS +{ + // add dynamic rigid body A1 + trans.setIdentity(); + worldPos.setValue(20,0,0); + trans.setOrigin(worldPos); + btRigidBody* pRbA3 = localCreateRigidBody(0.0F, trans, shape); + pRbA3->setActivationState(DISABLE_DEACTIVATION); + + // add dynamic rigid body B1 + worldPos.setValue(25,0,0); + trans.setOrigin(worldPos); + btRigidBody* pRbB3 = localCreateRigidBody(mass, trans, shape); + pRbB3->setActivationState(DISABLE_DEACTIVATION); + + btVector3 pivA( 2.5, 0., 0.); + btVector3 pivB(-2.5, 0., 0.); + spP2PConst = new btPoint2PointConstraint(*pRbA3, *pRbB3, pivA, pivB); + m_dynamicsWorld->addConstraint(spP2PConst, true); + spP2PConst->setDbgDrawSize(btScalar(5.f)); + +} +#endif + +#if 0 // SLIDER_ENABLE_ALL_DEMOS + // add dynamic rigid body A4 + trans.setIdentity(); + worldPos.setValue(20,10,0); + trans.setOrigin(worldPos); + btRigidBody* pRbA4 = localCreateRigidBody(0.0F, trans, shape); + pRbA4->setActivationState(DISABLE_DEACTIVATION); + + // add dynamic rigid body B1 + worldPos.setValue(27,10,0); + trans.setOrigin(worldPos); + btRigidBody* pRbB4 = localCreateRigidBody(mass, trans, shape); + pRbB1->setActivationState(DISABLE_DEACTIVATION); + + + btVector3 pivA( 2., 0., 0.); + btVector3 pivB(-5., 0., 0.); + btVector3 axisA(0., 0., 1.); + btVector3 axisB(0., 0., 1.); + + spHingeConst = new btHingeConstraint(*pRbA4, *pRbB4, pivA, pivB, axisA, axisB); +// spHingeConst->setLimit(-1.57, 1.57); + spHingeConst->setLimit(1.57, -1.57); + spHingeConst->enableAngularMotor(true, 10.0, 0.19); + + m_dynamicsWorld->addConstraint(spHingeConst, true); + spHingeConst->setDbgDrawSize(btScalar(5.f)); + +#endif + +} // SliderConstraintDemo::initPhysics() + + + +SliderConstraintDemo::~SliderConstraintDemo() +{ + //cleanup in the reverse order of creation/initialization + int i; + //removed/delete constraints + for (i=m_dynamicsWorld->getNumConstraints()-1; i>=0 ;i--) + { + btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i); + m_dynamicsWorld->removeConstraint(constraint); + delete constraint; + } + //remove the rigidbodies from the dynamics world and delete them + 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;jstepSimulation(dt,maxSimSubSteps); + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + bool verbose = false; + if (verbose) + { + if (!numSimSteps) + printf("Interpolated transforms\n"); + else + { + if (numSimSteps > maxSimSubSteps) + { + //detect dropping frames + printf("Dropped (%i) simulation steps out of %i\n",numSimSteps - maxSimSubSteps,numSimSteps); + } else + { + printf("Simulated (%i) steps\n",numSimSteps); + } + } + } + renderme(); +// drawSlider(spSlider1); +// drawSlider(spSlider2); + glFlush(); + glutSwapBuffers(); +} // SliderConstraintDemo::clientMoveAndDisplay() + + + +void SliderConstraintDemo::displayCallback(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + if(m_dynamicsWorld) + { + m_dynamicsWorld->debugDrawWorld(); + } +// drawSlider(spSlider1); +// drawSlider(spSlider2); + renderme(); + glFlush(); + glutSwapBuffers(); +} // SliderConstraintDemo::displayCallback() + + +void SliderConstraintDemo::keyboardCallback(unsigned char key, int x, int y) +{ + (void)x; + (void)y; + switch (key) + { + case 'O' : + { + bool offectOnOff; + offectOnOff = spSlider1->getUseFrameOffset(); + offectOnOff = !offectOnOff; + spSlider1->setUseFrameOffset(offectOnOff); + printf("Slider1 %s frame offset\n", offectOnOff ? "uses" : "does not use"); + offectOnOff = spSlider2->getUseFrameOffset(); + offectOnOff = !offectOnOff; + spSlider2->setUseFrameOffset(offectOnOff); + printf("Slider2 %s frame offset\n", offectOnOff ? "uses" : "does not use"); + } + break; + default : + { + DemoApplication::keyboardCallback(key, x, y); + } + break; + } +} + diff --git a/Demos/SliderConstraintDemo/SliderConstraintDemo.h b/Demos/SliderConstraintDemo/SliderConstraintDemo.h new file mode 100755 index 0000000..f0a652a --- /dev/null +++ b/Demos/SliderConstraintDemo/SliderConstraintDemo.h @@ -0,0 +1,73 @@ +/* +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 SLIDER_CONSTRAINT_DEMO_H +#define SLIDER_CONSTRAINT_DEMO_H + + + +#include "btBulletDynamicsCommon.h" +#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h" +#include "GlutDemoApplication.h" + + + + +/// SliderConstraintDemo shows how to create a slider constraint +class SliderConstraintDemo : public GlutDemoApplication +{ + //keep track of variables to delete memory at the end + btAlignedObjectArray m_collisionShapes; + + class btBroadphaseInterface* m_overlappingPairCache; + + class btCollisionDispatcher* m_dispatcher; + + class btConstraintSolver* m_constraintSolver; + + class btDefaultCollisionConfiguration* m_collisionConfiguration; + + public: + + virtual ~SliderConstraintDemo(); + + void initPhysics(); + + void initModel(); + + void drawSliders(); + void drawSliderConstraint(btSliderConstraint* constraint); + + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + static DemoApplication* Create() + { + SliderConstraintDemo* demo = new SliderConstraintDemo(); + demo->myinit(); + demo->initPhysics(); + return demo; + } + + virtual void keyboardCallback(unsigned char key, int x, int y); + +}; + +#endif //SLIDER_CONSTRAINT_DEMO_H + diff --git a/Demos/SliderConstraintDemo/main.cpp b/Demos/SliderConstraintDemo/main.cpp new file mode 100755 index 0000000..54f1afa --- /dev/null +++ b/Demos/SliderConstraintDemo/main.cpp @@ -0,0 +1,25 @@ +/* +Added by Roman Ponomarev (rponom@gmail.com) +April 04, 2008 +*/ +#include "SliderConstraintDemo.h" +#include "GlutStuff.h" + +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" + +GLDebugDrawer gDebugDrawer; + +int main(int argc,char** argv) +{ + + SliderConstraintDemo* sliderConstraintDemo = new SliderConstraintDemo(); + + sliderConstraintDemo->initPhysics(); + sliderConstraintDemo->getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + sliderConstraintDemo->setDebugMode(btIDebugDraw::DBG_DrawConstraints+btIDebugDraw::DBG_DrawConstraintLimits); + + + return glutmain(argc, argv,640,480,"Slider Constraint Demo. http://www.continuousphysics.com/Bullet/phpBB2/", sliderConstraintDemo); +} + diff --git a/Demos/SoftDemo/AMD/premake4.lua b/Demos/SoftDemo/AMD/premake4.lua new file mode 100644 index 0000000..2ff0887 --- /dev/null +++ b/Demos/SoftDemo/AMD/premake4.lua @@ -0,0 +1,59 @@ + + hasCL = findOpenCL_AMD() + + if (hasCL) then + + project "AppSoftBodyDemo_AMD" + + defines { "USE_AMD_OPENCL","CL_PLATFORM_AMD"} + + initOpenCL_AMD() + + language "C++" + + kind "ConsoleApp" + targetdir "../../.." + + libdirs {"../../../Glut"} + + links { + "LinearMath", + "BulletCollision", + "BulletDynamics", + "BulletSoftBody", + "BulletSoftBodySolvers_OpenCL_AMD", + "OpenGLSupport", + "opengl32" + } + + configuration "x64" + links { + "glut64", + "glew64s" + } + configuration "x32" + links { + "glut32", + "glew32s" + } + + configuration{} + + + includedirs { + "../../SharedOpenCL", + "../../../src", + "../../../Glut", + "../../OpenGL" + } + + files { + "../SoftDemo.cpp", + "../SoftDemo.h", + "../main.cpp", + "../../SharedOpenCL/btOpenCLUtils.cpp", + "../../SharedOpenCL/btOpenCLUtils.h", + "../../SharedOpenCL/btOpenCLInclude.h" + } + + end \ No newline at end of file diff --git a/Demos/SoftDemo/CMakeLists.txt b/Demos/SoftDemo/CMakeLists.txt new file mode 100644 index 0000000..c92199d --- /dev/null +++ b/Demos/SoftDemo/CMakeLists.txt @@ -0,0 +1,64 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + + +# You shouldn't have to modify anything below this line +######################################################## + +IF (USE_GLUT) + + INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL + ) + + LINK_LIBRARIES( + OpenGLSupport BulletSoftBody BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + IF (WIN32) + ADD_EXECUTABLE(AppSoftBodyDemo + main.cpp + SoftDemo.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) + ELSE() + ADD_EXECUTABLE(AppSoftBodyDemo + main.cpp + SoftDemo.cpp + + ) + ENDIF() + + IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppSoftBodyDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppSoftBodyDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ENDIF(WIN32) + + +ELSE(USE_GLUT) + +ENDIF (USE_GLUT) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppSoftBodyDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppSoftBodyDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppSoftBodyDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/SoftDemo/Makefile.am b/Demos/SoftDemo/Makefile.am new file mode 100644 index 0000000..ede95b8 --- /dev/null +++ b/Demos/SoftDemo/Makefile.am @@ -0,0 +1,5 @@ +noinst_PROGRAMS=SoftDemo + +SoftDemo_SOURCES=SoftDemo.cpp SoftDemo.h main.cpp +SoftDemo_CXXFLAGS=-I@top_builddir@/src -I@top_builddir@/Demos/OpenGL $(CXXFLAGS) +SoftDemo_LDADD=-L../OpenGL -lbulletopenglsupport -L../../src -lBulletSoftBody -lBulletDynamics -lBulletCollision -lLinearMath @opengl_LIBS@ diff --git a/Demos/SoftDemo/SoftDemo.cpp b/Demos/SoftDemo/SoftDemo.cpp new file mode 100644 index 0000000..0a370c1 --- /dev/null +++ b/Demos/SoftDemo/SoftDemo.cpp @@ -0,0 +1,2293 @@ +/* +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. +*/ + +///btSoftBody implementation by Nathanael Presson + + +#include "btBulletDynamicsCommon.h" +#include "BulletSoftBody/btSoftRigidDynamicsWorld.h" + +#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btIDebugDraw.h" + +#include "../GimpactTestDemo/BunnyMesh.h" +#include "../GimpactTestDemo/TorusMesh.h" +#include //printf debugging +#include "LinearMath/btConvexHull.h" +#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h" +#include "BulletSoftBody/btSoftBodyHelpers.h" + +#include "SoftDemo.h" +#include "GL_ShapeDrawer.h" +#include "GLDebugFont.h" +#include "GlutStuff.h" + +extern float eye[3]; +extern int glutScreenWidth; +extern int glutScreenHeight; + +static bool sDemoMode = false; + +const int maxProxies = 32766; +const int maxOverlap = 65535; + +static btVector3* gGroundVertices=0; +static int* gGroundIndices=0; +static btBvhTriangleMeshShape* trimeshShape =0; +static btRigidBody* staticBody = 0; +static float waveheight = 5.f; + +const float TRIANGLE_SIZE=8.f; +unsigned int current_demo=7; +#define DEMO_MODE_TIMEOUT 15.f //15 seconds for each demo + + +#ifdef _DEBUG +const int gNumObjects = 1; +#else +const int gNumObjects = 1;//try this in release mode: 3000. never go above 16384, unless you increate maxNumObjects value in DemoApplication.cp +#endif + +const int maxNumObjects = 32760; + +#define CUBE_HALF_EXTENTS 1.5 +#define EXTRA_HEIGHT -10.f + + +#ifdef USE_AMD_OPENCL +#include "btOpenCLUtils.h" +#include "BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h" +#include "BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h" +#include "BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h" + +btOpenCLSoftBodySolver* g_openCLSIMDSolver=0; +btSoftBodySolverOutputCLtoCPU* g_softBodyOutput = 0; + +cl_context g_cxMainContext; +cl_device_id g_cdDevice; +cl_command_queue g_cqCommandQue; + +void initCL( void* glCtx, void* glDC ) +{ + int ciErrNum = 0; + +#if defined(CL_PLATFORM_MINI_CL) + cl_device_type deviceType = CL_DEVICE_TYPE_CPU;//or use CL_DEVICE_TYPE_DEBUG to debug MiniCL +#elif defined(CL_PLATFORM_INTEL) + cl_device_type deviceType = CL_DEVICE_TYPE_CPU; +#elif defined(CL_PLATFORM_AMD) + cl_device_type deviceType = CL_DEVICE_TYPE_GPU; +#elif defined(CL_PLATFORM_NVIDIA) + cl_device_type deviceType = CL_DEVICE_TYPE_GPU; +#else +#ifdef __APPLE__ + cl_device_type deviceType = CL_DEVICE_TYPE_ALL;//GPU; +#else + cl_device_type deviceType = CL_DEVICE_TYPE_CPU;//CL_DEVICE_TYPE_ALL +#endif//__APPLE__ +#endif + + g_cxMainContext = btOpenCLUtils::createContextFromType(deviceType, &ciErrNum, glCtx, glDC); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + + int numDev = btOpenCLUtils::getNumDevices(g_cxMainContext); + if (!numDev) + { + btAssert(0); + exit(0);//this is just a demo, exit now + } + + g_cdDevice = btOpenCLUtils::getDevice(g_cxMainContext,0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + btOpenCLDeviceInfo clInfo; + btOpenCLUtils::getDeviceInfo(g_cdDevice,clInfo); + btOpenCLUtils::printDeviceInfo(g_cdDevice); + + // create a command-queue + g_cqCommandQue = clCreateCommandQueue(g_cxMainContext, g_cdDevice, 0, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); +} + +class CachingCLFunctions : public CLFunctions +{ +protected: + + cl_device_id m_device; + + const char* strip(const char* name, const char* pattern); + +public: + CachingCLFunctions(cl_command_queue cqCommandQue, cl_context cxMainContext) : + CLFunctions(cqCommandQue,cxMainContext) + { + size_t actualSize; + cl_int retval = clGetCommandQueueInfo ( cqCommandQue, CL_QUEUE_DEVICE, sizeof(cl_device_id), + &m_device, &actualSize); + } + + /** + * Compile a compute shader kernel from a string and return the appropriate cl_kernel object. + */ + virtual cl_kernel compileCLKernelFromString( const char* kernelSource, const char* kernelName, const char* additionalMacros , const char* orgSrcFileNameForCaching) + { + char srcFileNameForCaching[1024]; + sprintf(srcFileNameForCaching,"%s/%s","../../src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL",orgSrcFileNameForCaching); + + btAssert(additionalMacros); + btAssert(srcFileNameForCaching && strlen(srcFileNameForCaching)); + + printf("compiling kernelName: %s ",kernelName); + cl_kernel kernel=0; + cl_int ciErrNum; + + + size_t program_length = strlen(kernelSource); + + cl_program m_cpProgram = btOpenCLUtils::compileCLProgramFromString(m_cxMainContext, m_device, kernelSource, &ciErrNum, additionalMacros); + + + // Create the kernel + kernel = clCreateKernel(m_cpProgram, kernelName, &ciErrNum); + if (ciErrNum != CL_SUCCESS) + { + const char* msg = ""; + switch(ciErrNum) + { + case CL_INVALID_PROGRAM: + msg = "Program is not a valid program object."; + break; + case CL_INVALID_PROGRAM_EXECUTABLE: + msg = "There is no successfully built executable for program."; + break; + case CL_INVALID_KERNEL_NAME: + msg = "kernel_name is not found in program."; + break; + case CL_INVALID_KERNEL_DEFINITION: + msg = "the function definition for __kernel function given by kernel_name such as the number of arguments, the argument types are not the same for all devices for which the program executable has been built."; + break; + case CL_INVALID_VALUE: + msg = "kernel_name is NULL."; + break; + case CL_OUT_OF_HOST_MEMORY: + msg = "Failure to allocate resources required by the OpenCL implementation on the host."; + break; + default: + { + } + } + + printf("Error in clCreateKernel for kernel '%s', error is \"%s\", Line %u in file %s !!!\n\n", kernelName, msg, __LINE__, __FILE__); + + #ifndef BT_SUPPRESS_OPENCL_ASSERTS + btAssert(0); + #endif //BT_SUPPRESS_OPENCL_ASSERTS + m_kernelCompilationFailures++; + return 0; + } + + printf("ready. \n"); + if (!kernel) + m_kernelCompilationFailures++; + return kernel; + } + +}; + + +#endif //USE_AMD_OPENCL + +// +void SoftDemo::createStack( btCollisionShape* boxShape, float halfCubeSize, int size, float zPos ) +{ + btTransform trans; + trans.setIdentity(); + + for(int i=0; igetWorldUserInfo(); + + if(softDemo->m_drag) + { + const int x=softDemo->m_lastmousepos[0]; + const int y=softDemo->m_lastmousepos[1]; + const btVector3 rayFrom=softDemo->getCameraPosition(); + const btVector3 rayTo=softDemo->getRayTo(x,y); + const btVector3 rayDir=(rayTo-rayFrom).normalized(); + const btVector3 N=(softDemo->getCameraTargetPosition()-softDemo->getCameraPosition()).normalized(); + const btScalar O=btDot(softDemo->m_impact,N); + const btScalar den=btDot(N,rayDir); + if((den*den)>0) + { + const btScalar num=O-btDot(N,rayFrom); + const btScalar hit=num/den; + if((hit>0)&&(hit<1500)) + { + softDemo->m_goal=rayFrom+rayDir*hit; + } + } + btVector3 delta=softDemo->m_goal-softDemo->m_node->m_x; + static const btScalar maxdrag=10; + if(delta.length2()>(maxdrag*maxdrag)) + { + delta=delta.normalized()*maxdrag; + } + softDemo->m_node->m_v+=delta/timeStep; + } + +} + + + +void SoftDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + + renderme(); + + glFlush(); + swapBuffers(); +} + + +// +// ImplicitShape +// + +// +struct ImplicitSphere : btSoftBody::ImplicitFn +{ + btVector3 center; + btScalar sqradius; + ImplicitSphere() {} + ImplicitSphere(const btVector3& c,btScalar r) : center(c),sqradius(r*r) {} + btScalar Eval(const btVector3& x) + { + return((x-center).length2()-sqradius); + } +}; + +// +// Tetra meshes +// + +struct TetraBunny +{ +#include "bunny.inl" +}; + +struct TetraCube +{ +#include "cube.inl" +}; + + +// +// Random +// + +static inline btScalar UnitRand() +{ + return(rand()/(btScalar)RAND_MAX); +} + +static inline btScalar SignedUnitRand() +{ + return(UnitRand()*2-1); +} + +static inline btVector3 Vector3Rand() +{ + const btVector3 p=btVector3(SignedUnitRand(),SignedUnitRand(),SignedUnitRand()); + return(p.normalized()); +} + +// +// Rb rain +// +static void Ctor_RbUpStack(SoftDemo* pdemo,int count) +{ + float mass=10; + + btCompoundShape* cylinderCompound = new btCompoundShape; + btCollisionShape* cylinderShape = new btCylinderShapeX(btVector3(4,1,1)); + btCollisionShape* boxShape = new btBoxShape(btVector3(4,1,1)); + btTransform localTransform; + localTransform.setIdentity(); + cylinderCompound->addChildShape(localTransform,boxShape); + btQuaternion orn(SIMD_HALF_PI,0,0); + localTransform.setRotation(orn); + // localTransform.setOrigin(btVector3(1,1,1)); + cylinderCompound->addChildShape(localTransform,cylinderShape); + + + btCollisionShape* shape[]={cylinderCompound, + new btBoxShape(btVector3(1,1,1)), + new btSphereShape(1.5) + + }; + static const int nshapes=sizeof(shape)/sizeof(shape[0]); + for(int i=0;ilocalCreateRigidBody(mass,startTransform,shape[i%nshapes]); + //pdemo->localCreateRigidBody(mass,startTransform,shape[0]); + } +} + +// +// Big ball +// +static void Ctor_BigBall(SoftDemo* pdemo,btScalar mass=10) +{ + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(0,13,0)); + pdemo->localCreateRigidBody(mass,startTransform,new btSphereShape(3)); +} + +// +// Big plate +// +static btRigidBody* Ctor_BigPlate(SoftDemo* pdemo,btScalar mass=15,btScalar height=4) +{ + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(0,height,0.5)); + btRigidBody* body=pdemo->localCreateRigidBody(mass,startTransform,new btBoxShape(btVector3(5,1,5))); + body->setFriction(1); + return(body); +} + +// +// Linear stair +// +static void Ctor_LinearStair(SoftDemo* pdemo,const btVector3& org,const btVector3& sizes,btScalar angle,int count) +{ + btBoxShape* shape=new btBoxShape(sizes); + for(int i=0;ilocalCreateRigidBody(0,startTransform,shape); + body->setFriction(1); + } +} + +// +// Softbox +// +static btSoftBody* Ctor_SoftBox(SoftDemo* pdemo,const btVector3& p,const btVector3& s) +{ + const btVector3 h=s*0.5; + const btVector3 c[]={ p+h*btVector3(-1,-1,-1), + p+h*btVector3(+1,-1,-1), + p+h*btVector3(-1,+1,-1), + p+h*btVector3(+1,+1,-1), + p+h*btVector3(-1,-1,+1), + p+h*btVector3(+1,-1,+1), + p+h*btVector3(-1,+1,+1), + p+h*btVector3(+1,+1,+1)}; + btSoftBody* psb=btSoftBodyHelpers::CreateFromConvexHull(pdemo->m_softBodyWorldInfo,c,8); + psb->generateBendingConstraints(2); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + + return(psb); + +} + +// +// SoftBoulder +// +static btSoftBody* Ctor_SoftBoulder(SoftDemo* pdemo,const btVector3& p,const btVector3& s,int np,int id) +{ + btAlignedObjectArray pts; + if(id) srand(id); + for(int i=0;im_softBodyWorldInfo,&pts[0],pts.size()); + psb->generateBendingConstraints(2); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + + return(psb); +} + +//#define TRACEDEMO { pdemo->demoname=__FUNCTION__+5;printf("Launching demo: " __FUNCTION__ "\r\n"); } + +// +// Basic ropes +// +static void Init_Ropes(SoftDemo* pdemo) +{ + //TRACEDEMO + const int n=15; + for(int i=0;im_softBodyWorldInfo, btVector3(-10,0,i*0.25), + btVector3(10,0,i*0.25), + 16, + 1+2); + psb->m_cfg.piterations = 4; + psb->m_materials[0]->m_kLST = 0.1+(i/(btScalar)(n-1))*0.9; + psb->setTotalMass(20); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + + } +} + +// +// Rope attach +// +static void Init_RopeAttach(SoftDemo* pdemo) +{ + //TRACEDEMO + pdemo->m_softBodyWorldInfo.m_sparsesdf.RemoveReferences(0); + struct Functors + { + static btSoftBody* CtorRope(SoftDemo* pdemo,const btVector3& p) + { + btSoftBody* psb=btSoftBodyHelpers::CreateRope(pdemo->m_softBodyWorldInfo,p,p+btVector3(10,0,0),8,1); + psb->setTotalMass(50); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + return(psb); + } + }; + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(12,8,0)); + btRigidBody* body=pdemo->localCreateRigidBody(50,startTransform,new btBoxShape(btVector3(2,6,2))); + btSoftBody* psb0=Functors::CtorRope(pdemo,btVector3(0,8,-1)); + btSoftBody* psb1=Functors::CtorRope(pdemo,btVector3(0,8,+1)); + psb0->appendAnchor(psb0->m_nodes.size()-1,body); + psb1->appendAnchor(psb1->m_nodes.size()-1,body); +} + +// +// Cloth attach +// +static void Init_ClothAttach(SoftDemo* pdemo) +{ + //TRACEDEMO + const btScalar s=4; + const btScalar h=6; + const int r=9; + btSoftBody* psb=btSoftBodyHelpers::CreatePatch(pdemo->m_softBodyWorldInfo,btVector3(-s,h,-s), + btVector3(+s,h,-s), + btVector3(-s,h,+s), + btVector3(+s,h,+s),r,r,4+8,true); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(0,h,-(s+3.5))); + btRigidBody* body=pdemo->localCreateRigidBody(20,startTransform,new btBoxShape(btVector3(s,1,3))); + psb->appendAnchor(0,body); + psb->appendAnchor(r-1,body); + pdemo->m_cutting=true; +} + +// +// Impact +// +static void Init_Impact(SoftDemo* pdemo) +{ + //TRACEDEMO + btSoftBody* psb=btSoftBodyHelpers::CreateRope(pdemo->m_softBodyWorldInfo, btVector3(0,0,0), + btVector3(0,-1,0), + 0, + 1); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + psb->m_cfg.kCHR=0.5; + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(0,20,0)); + pdemo->localCreateRigidBody(10,startTransform,new btBoxShape(btVector3(2,2,2))); +} + +static void Init_CapsuleCollision(SoftDemo* pdemo) +{ +#ifdef USE_AMD_OPENCL + btAlignedObjectArray emptyArray; + if (g_openCLSIMDSolver) + g_openCLSIMDSolver->optimize(emptyArray); +#endif //USE_AMD_OPENCL + + //TRACEDEMO + const btScalar s=4; + const btScalar h=6; + const int r=20; + + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(0,h-2,0)); + + btCollisionShape* capsuleShape= new btCapsuleShapeX(1,5); + capsuleShape->setMargin( 0.5 ); + + // capsule->setLocalScaling(btVector3(5,1,1)); +// btRigidBody* body=pdemo->localCreateRigidBody(20,startTransform,capsuleShape); + btRigidBody* body=pdemo->localCreateRigidBody(0,startTransform,capsuleShape); + body->setFriction( 0.8f ); + + int fixed=0;//4+8; + btSoftBody* psb=btSoftBodyHelpers::CreatePatch(pdemo->m_softBodyWorldInfo,btVector3(-s,h,-s), + btVector3(+s,h,-s), + btVector3(-s,h,+s), + btVector3(+s,h,+s),r,r,fixed,true); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + psb->setTotalMass(0.1); + + psb->m_cfg.piterations = 10; + psb->m_cfg.citerations = 10; + psb->m_cfg.diterations = 10; +// psb->m_cfg.viterations = 10; + + + // psb->appendAnchor(0,body); +// psb->appendAnchor(r-1,body); +// pdemo->m_cutting=true; +} + +// +// Collide +// +static void Init_Collide(SoftDemo* pdemo) +{ + //TRACEDEMO + struct Functor + { + static btSoftBody* Create(SoftDemo* pdemo,const btVector3& x,const btVector3& a) + { + btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo,gVertices, + &gIndices[0][0], + NUM_TRIANGLES); + psb->generateBendingConstraints(2); + psb->m_cfg.piterations=2; + psb->m_cfg.collisions|=btSoftBody::fCollision::VF_SS; + psb->randomizeConstraints(); + btMatrix3x3 m; + m.setEulerZYX(a.x(),a.y(),a.z()); + psb->transform(btTransform(m,x)); + psb->scale(btVector3(2,2,2)); + psb->setTotalMass(50,true); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + return(psb); + } + }; + for(int i=0;i<3;++i) + { + Functor::Create(pdemo,btVector3(3*i,2,0),btVector3(SIMD_PI/2*(1-(i&1)),SIMD_PI/2*(i&1),0)); + } + pdemo->m_cutting=true; +} + +// +// Collide2 +// +static void Init_Collide2(SoftDemo* pdemo) +{ + //TRACEDEMO + struct Functor + { + static btSoftBody* Create(SoftDemo* pdemo,const btVector3& x,const btVector3& a) + { + btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo,gVerticesBunny, + &gIndicesBunny[0][0], + BUNNY_NUM_TRIANGLES); + btSoftBody::Material* pm=psb->appendMaterial(); + pm->m_kLST = 0.5; + pm->m_flags -= btSoftBody::fMaterial::DebugDraw; + psb->generateBendingConstraints(2,pm); + psb->m_cfg.piterations = 2; + psb->m_cfg.kDF = 0.5; + psb->m_cfg.collisions |= btSoftBody::fCollision::VF_SS; + psb->randomizeConstraints(); + btMatrix3x3 m; + m.setEulerZYX(a.x(),a.y(),a.z()); + psb->transform(btTransform(m,x)); + psb->scale(btVector3(6,6,6)); + psb->setTotalMass(100,true); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + return(psb); + } + }; + for(int i=0;i<3;++i) + { + Functor::Create(pdemo,btVector3(0,-1+5*i,0),btVector3(0,SIMD_PI/2*(i&1),0)); + } + pdemo->m_cutting=true; +} + +// +// Collide3 +// +static void Init_Collide3(SoftDemo* pdemo) +{ + //TRACEDEMO + { + const btScalar s=8; + btSoftBody* psb=btSoftBodyHelpers::CreatePatch( pdemo->m_softBodyWorldInfo,btVector3(-s,0,-s), + btVector3(+s,0,-s), + btVector3(-s,0,+s), + btVector3(+s,0,+s), + 15,15,1+2+4+8,true); + psb->m_materials[0]->m_kLST = 0.4; + psb->m_cfg.collisions |= btSoftBody::fCollision::VF_SS; + psb->setTotalMass(150); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + } + { + const btScalar s=4; + const btVector3 o=btVector3(5,10,0); + btSoftBody* psb=btSoftBodyHelpers::CreatePatch( pdemo->m_softBodyWorldInfo, + btVector3(-s,0,-s)+o, + btVector3(+s,0,-s)+o, + btVector3(-s,0,+s)+o, + btVector3(+s,0,+s)+o, + 7,7,0,true); + btSoftBody::Material* pm=psb->appendMaterial(); + pm->m_kLST = 0.1; + pm->m_flags -= btSoftBody::fMaterial::DebugDraw; + psb->generateBendingConstraints(2,pm); + psb->m_materials[0]->m_kLST = 0.5; + psb->m_cfg.collisions |= btSoftBody::fCollision::VF_SS; + psb->setTotalMass(150); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + pdemo->m_cutting=true; + } +} + +// +// Aerodynamic forces, 50x1g flyers +// +static void Init_Aero(SoftDemo* pdemo) +{ + //TRACEDEMO + const btScalar s=2; + const btScalar h=10; + const int segments=6; + const int count=50; + for(int i=0;im_softBodyWorldInfo,btVector3(-s,h,-s), + btVector3(+s,h,-s), + btVector3(-s,h,+s), + btVector3(+s,h,+s), + segments,segments, + 0,true); + btSoftBody::Material* pm=psb->appendMaterial(); + pm->m_flags -= btSoftBody::fMaterial::DebugDraw; + psb->generateBendingConstraints(2,pm); + psb->m_cfg.kLF = 0.004; + psb->m_cfg.kDG = 0.0003; + psb->m_cfg.aeromodel = btSoftBody::eAeroModel::V_TwoSided; + btTransform trs; + btQuaternion rot; + btVector3 ra=Vector3Rand()*0.1; + btVector3 rp=Vector3Rand()*15+btVector3(0,20,80); + rot.setEuler(SIMD_PI/8+ra.x(),-SIMD_PI/7+ra.y(),ra.z()); + trs.setIdentity(); + trs.setOrigin(rp); + trs.setRotation(rot); + psb->transform(trs); + psb->setTotalMass(0.1); + psb->addForce(btVector3(0,2,0),0); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + + } + pdemo->m_autocam=true; +} + +static void Init_Aero2(SoftDemo* pdemo) +{ + //TRACEDEMO + const btScalar s=5; + const int segments=10; + const int count=5; + btVector3 pos(-s*segments, 0, 0); + btScalar gap = 0.5; + + for(int i=0;im_softBodyWorldInfo,btVector3(-s,0,-s*3), + btVector3(+s,0,-s*3), + btVector3(-s,0,+s), + btVector3(+s,0,+s), + segments,segments*3, + 1+2,true); + + psb->getCollisionShape()->setMargin(0.5); + btSoftBody::Material* pm=psb->appendMaterial(); + pm->m_kLST = 0.0004; + pm->m_flags -= btSoftBody::fMaterial::DebugDraw; + psb->generateBendingConstraints(2,pm); + + psb->m_cfg.kLF = 0.05; + psb->m_cfg.kDG = 0.01; + + //psb->m_cfg.kLF = 0.004; + //psb->m_cfg.kDG = 0.0003; + + psb->m_cfg.piterations = 2; + psb->m_cfg.aeromodel = btSoftBody::eAeroModel::V_TwoSidedLiftDrag; + + + psb->setWindVelocity(btVector3(4, -12.0, -25.0)); + + btTransform trs; + btQuaternion rot; + pos += btVector3(s*2 + gap, 0, 0); + rot.setRotation(btVector3(1, 0, 0), btScalar(SIMD_PI/2)); + trs.setIdentity(); + trs.setOrigin(pos); + trs.setRotation(rot); + psb->transform(trs); + psb->setTotalMass(2.0); + + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + } + + pdemo->m_autocam=true; +} + +// +// Friction +// +static void Init_Friction(SoftDemo* pdemo) +{ + //TRACEDEMO + const btScalar bs=2; + const btScalar ts=bs+bs/4; + for(int i=0,ni=20;im_cfg.kDF = 0.1 * ((i+1)/(btScalar)ni); + psb->addVelocity(btVector3(0,0,-10)); + } +} + +// +// Pressure +// +static void Init_Pressure(SoftDemo* pdemo) +{ + //TRACEDEMO + btSoftBody* psb=btSoftBodyHelpers::CreateEllipsoid(pdemo->m_softBodyWorldInfo,btVector3(35,25,0), + btVector3(1,1,1)*3, + 512); + psb->m_materials[0]->m_kLST = 0.1; + psb->m_cfg.kDF = 1; + psb->m_cfg.kDP = 0.001; // fun factor... + psb->m_cfg.kPR = 2500; + psb->setTotalMass(30,true); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + + Ctor_BigPlate(pdemo); + Ctor_LinearStair(pdemo,btVector3(0,0,0),btVector3(2,1,5),0,10); + pdemo->m_autocam=true; + +} + +// +// Volume conservation +// +static void Init_Volume(SoftDemo* pdemo) +{ + //TRACEDEMO + btSoftBody* psb=btSoftBodyHelpers::CreateEllipsoid(pdemo->m_softBodyWorldInfo,btVector3(35,25,0), + btVector3(1,1,1)*3, + 512); + psb->m_materials[0]->m_kLST = 0.45; + psb->m_cfg.kVC = 20; + psb->setTotalMass(50,true); + psb->setPose(true,false); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + + Ctor_BigPlate(pdemo); + Ctor_LinearStair(pdemo,btVector3(0,0,0),btVector3(2,1,5),0,10); + pdemo->m_autocam=true; + +} + +// +// Stick+Bending+Rb's +// +static void Init_Sticks(SoftDemo* pdemo) +{ + //TRACEDEMO + const int n=16; + const int sg=4; + const btScalar sz=5; + const btScalar hg=4; + const btScalar in=1/(btScalar)(n-1); + for(int y=0;ym_softBodyWorldInfo, org, + org+btVector3(hg*0.001,hg,0), + sg, + 1); + psb->m_cfg.kDP = 0.005; + psb->m_cfg.kCHR = 0.1; + for(int i=0;i<3;++i) + { + psb->generateBendingConstraints(2+i); + } + psb->setMass(1,0); + psb->setTotalMass(0.01); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + + } + } + Ctor_BigBall(pdemo); +} + +// +// Bending +// +static void Init_Bending(SoftDemo* pdemo) +{ + //TRACEDEMO + const btScalar s=4; + const btVector3 x[]={ btVector3(-s,0,-s), + btVector3(+s,0,-s), + btVector3(+s,0,+s), + btVector3(-s,0,+s)}; + const btScalar m[]={ 0,0,0,1}; + btSoftBody* psb=new btSoftBody(&pdemo->m_softBodyWorldInfo,4,x,m); + psb->appendLink(0,1); + psb->appendLink(1,2); + psb->appendLink(2,3); + psb->appendLink(3,0); + psb->appendLink(0,2); + + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); +} + +// +// 100kg cloth locked at corners, 10 falling 10kg rb's. +// +static void Init_Cloth(SoftDemo* pdemo) +{ + //TRACEDEMO + const btScalar s=8; + btSoftBody* psb=btSoftBodyHelpers::CreatePatch( pdemo->m_softBodyWorldInfo,btVector3(-s,0,-s), + btVector3(+s,0,-s), + btVector3(-s,0,+s), + btVector3(+s,0,+s), + 31,31, + // 31,31, + 1+2+4+8,true); + + psb->getCollisionShape()->setMargin(0.5); + btSoftBody::Material* pm=psb->appendMaterial(); + pm->m_kLST = 0.4; + pm->m_flags -= btSoftBody::fMaterial::DebugDraw; + psb->generateBendingConstraints(2,pm); + psb->setTotalMass(150); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + + Ctor_RbUpStack(pdemo,10); + pdemo->m_cutting=true; +} + +// +// 100kg Stanford's bunny +// +static void Init_Bunny(SoftDemo* pdemo) +{ + //TRACEDEMO + btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo,gVerticesBunny, + &gIndicesBunny[0][0], + BUNNY_NUM_TRIANGLES); + btSoftBody::Material* pm=psb->appendMaterial(); + pm->m_kLST = 0.5; + pm->m_flags -= btSoftBody::fMaterial::DebugDraw; + psb->generateBendingConstraints(2,pm); + psb->m_cfg.piterations = 2; + psb->m_cfg.kDF = 0.5; + psb->randomizeConstraints(); + psb->scale(btVector3(6,6,6)); + psb->setTotalMass(100,true); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + pdemo->m_cutting=true; + +} + +// +// 100kg Stanford's bunny with pose matching +// +static void Init_BunnyMatch(SoftDemo* pdemo) +{ + //TRACEDEMO + btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVerticesBunny, + &gIndicesBunny[0][0], + BUNNY_NUM_TRIANGLES); + psb->m_cfg.kDF = 0.5; + psb->m_cfg.kMT = 0.05; + psb->m_cfg.piterations = 5; + psb->randomizeConstraints(); + psb->scale(btVector3(6,6,6)); + psb->setTotalMass(100,true); + psb->setPose(false,true); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + +} + +// +// 50Kg Torus +// +static void Init_Torus(SoftDemo* pdemo) +{ + //TRACEDEMO + btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh( pdemo->m_softBodyWorldInfo, gVertices, + &gIndices[0][0], + NUM_TRIANGLES); + psb->generateBendingConstraints(2); + psb->m_cfg.piterations=2; + psb->randomizeConstraints(); + btMatrix3x3 m; + m.setEulerZYX(SIMD_PI/2,0,0); + psb->transform(btTransform(m,btVector3(0,4,0))); + psb->scale(btVector3(2,2,2)); + psb->setTotalMass(50,true); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + pdemo->m_cutting=true; + + +} + +// +// 50Kg Torus with pose matching +// +static void Init_TorusMatch(SoftDemo* pdemo) +{ + //TRACEDEMO + btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVertices, + &gIndices[0][0], + NUM_TRIANGLES); + psb->m_materials[0]->m_kLST = 0.1; + psb->m_cfg.kMT = 0.05; + psb->randomizeConstraints(); + btMatrix3x3 m; + m.setEulerZYX(SIMD_PI/2,0,0); + psb->transform(btTransform(m,btVector3(0,4,0))); + psb->scale(btVector3(2,2,2)); + psb->setTotalMass(50,true); + psb->setPose(false,true); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); +} + +// +// Cutting1 +// +static void Init_Cutting1(SoftDemo* pdemo) +{ + const btScalar s=6; + const btScalar h=2; + const int r=16; + const btVector3 p[]={ btVector3(+s,h,-s), + btVector3(-s,h,-s), + btVector3(+s,h,+s), + btVector3(-s,h,+s)}; + btSoftBody* psb=btSoftBodyHelpers::CreatePatch(pdemo->m_softBodyWorldInfo,p[0],p[1],p[2],p[3],r,r,1+2+4+8,true); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + psb->m_cfg.piterations=1; + pdemo->m_cutting=true; +} + +// +// Clusters +// + +// +static void Ctor_Gear(SoftDemo* pdemo,const btVector3& pos,btScalar speed) +{ + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(pos); + btCompoundShape* shape=new btCompoundShape(); +#if 1 + shape->addChildShape(btTransform(btQuaternion(0,0,0)),new btBoxShape(btVector3(5,1,6))); + shape->addChildShape(btTransform(btQuaternion(0,0,SIMD_HALF_PI)),new btBoxShape(btVector3(5,1,6))); +#else + shape->addChildShape(btTransform(btQuaternion(0,0,0)),new btCylinderShapeZ(btVector3(5,1,7))); + shape->addChildShape(btTransform(btQuaternion(0,0,SIMD_HALF_PI)),new btBoxShape(btVector3(4,1,8))); +#endif + btRigidBody* body=pdemo->localCreateRigidBody(10,startTransform,shape); + body->setFriction(1); + btDynamicsWorld* world=pdemo->getDynamicsWorld(); + btHingeConstraint* hinge=new btHingeConstraint(*body,btTransform::getIdentity()); + if(speed!=0) hinge->enableAngularMotor(true,speed,3); + world->addConstraint(hinge); +} + +// +static btSoftBody* Ctor_ClusterBunny(SoftDemo* pdemo,const btVector3& x,const btVector3& a) +{ + btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo,gVerticesBunny,&gIndicesBunny[0][0],BUNNY_NUM_TRIANGLES); + btSoftBody::Material* pm=psb->appendMaterial(); + pm->m_kLST = 1; + pm->m_flags -= btSoftBody::fMaterial::DebugDraw; + psb->generateBendingConstraints(2,pm); + psb->m_cfg.piterations = 2; + psb->m_cfg.kDF = 1; + psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS+ + btSoftBody::fCollision::CL_RS; + psb->randomizeConstraints(); + btMatrix3x3 m; + m.setEulerZYX(a.x(),a.y(),a.z()); + psb->transform(btTransform(m,x)); + psb->scale(btVector3(8,8,8)); + psb->setTotalMass(150,true); + psb->generateClusters(1); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + return(psb); +} + +// +static btSoftBody* Ctor_ClusterTorus(SoftDemo* pdemo,const btVector3& x,const btVector3& a,const btVector3& s=btVector3(2,2,2)) +{ + btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo,gVertices,&gIndices[0][0],NUM_TRIANGLES); + btSoftBody::Material* pm=psb->appendMaterial(); + pm->m_kLST = 1; + pm->m_flags -= btSoftBody::fMaterial::DebugDraw; + psb->generateBendingConstraints(2,pm); + psb->m_cfg.piterations = 2; + psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS+ + btSoftBody::fCollision::CL_RS; + psb->randomizeConstraints(); + psb->scale(s); + psb->rotate(btQuaternion(a[0],a[1],a[2])); + psb->translate(x); + psb->setTotalMass(50,true); + psb->generateClusters(64); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + return(psb); +} + +// +static struct MotorControl : btSoftBody::AJoint::IControl +{ + MotorControl() + { + goal=0; + maxtorque=0; + } + btScalar Speed(btSoftBody::AJoint*,btScalar current) + { + return(current+btMin(maxtorque,btMax(-maxtorque,goal-current))); + } + btScalar goal; + btScalar maxtorque; +} motorcontrol; + +// +struct SteerControl : btSoftBody::AJoint::IControl +{ + SteerControl(btScalar s) + { + angle=0; + sign=s; + } + void Prepare(btSoftBody::AJoint* joint) + { + joint->m_refs[0][0]=btCos(angle*sign); + joint->m_refs[0][2]=btSin(angle*sign); + } + btScalar Speed(btSoftBody::AJoint* joint,btScalar current) + { + return(motorcontrol.Speed(joint,current)); + } + btScalar angle; + btScalar sign; +}; + +static SteerControl steercontrol_f(+1); +static SteerControl steercontrol_r(-1); + +// +static void Init_ClusterDeform(SoftDemo* pdemo) +{ + btSoftBody* psb=Ctor_ClusterTorus(pdemo,btVector3(0,0,0),btVector3(SIMD_PI/2,0,SIMD_HALF_PI)); + psb->generateClusters(8); + psb->m_cfg.kDF=1; +} + +// +static void Init_ClusterCollide1(SoftDemo* pdemo) +{ + const btScalar s=8; + btSoftBody* psb=btSoftBodyHelpers::CreatePatch( pdemo->m_softBodyWorldInfo,btVector3(-s,0,-s), + btVector3(+s,0,-s), + btVector3(-s,0,+s), + btVector3(+s,0,+s), + 17,17,//9,9,//31,31, + 1+2+4+8, + true); + btSoftBody::Material* pm=psb->appendMaterial(); + pm->m_kLST = 0.4; + pm->m_flags -= btSoftBody::fMaterial::DebugDraw; + psb->m_cfg.kDF = 1; + psb->m_cfg.kSRHR_CL = 1; + psb->m_cfg.kSR_SPLT_CL = 0; + psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS+ + + btSoftBody::fCollision::CL_RS; + psb->generateBendingConstraints(2,pm); + + psb->getCollisionShape()->setMargin(0.05); + psb->setTotalMass(50); + + ///pass zero in generateClusters to create cluster for each tetrahedron or triangle + psb->generateClusters(0); + //psb->generateClusters(64); + + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + + Ctor_RbUpStack(pdemo,10); +} + +// +static void Init_ClusterCollide2(SoftDemo* pdemo) +{ + struct Functor + { + static btSoftBody* Create(SoftDemo* pdemo,const btVector3& x,const btVector3& a) + { + btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo,gVertices, + &gIndices[0][0], + NUM_TRIANGLES); + btSoftBody::Material* pm=psb->appendMaterial(); + pm->m_flags -= btSoftBody::fMaterial::DebugDraw; + psb->generateBendingConstraints(2,pm); + psb->m_cfg.piterations=2; + psb->m_cfg.kDF =1; + psb->m_cfg.kSSHR_CL =1; + psb->m_cfg.kSS_SPLT_CL =0; + psb->m_cfg.kSKHR_CL =0.1f; + psb->m_cfg.kSK_SPLT_CL =1; + psb->m_cfg.collisions= btSoftBody::fCollision::CL_SS+ + btSoftBody::fCollision::CL_RS; + psb->randomizeConstraints(); + btMatrix3x3 m; + m.setEulerZYX(a.x(),a.y(),a.z()); + psb->transform(btTransform(m,x)); + psb->scale(btVector3(2,2,2)); + psb->setTotalMass(50,true); + psb->generateClusters(16); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + return(psb); + } + }; + for(int i=0;i<3;++i) + { + Functor::Create(pdemo,btVector3(3*i,2,0),btVector3(SIMD_PI/2*(1-(i&1)),SIMD_PI/2*(i&1),0)); + } +} + +// +static void Init_ClusterSocket(SoftDemo* pdemo) +{ + btSoftBody* psb=Ctor_ClusterTorus(pdemo,btVector3(0,0,0),btVector3(SIMD_PI/2,0,SIMD_HALF_PI)); + btRigidBody* prb=Ctor_BigPlate(pdemo,50,8); + psb->m_cfg.kDF=1; + btSoftBody::LJoint::Specs lj; + lj.position = btVector3(0,5,0); + psb->appendLinearJoint(lj,prb); +} + +// +static void Init_ClusterHinge(SoftDemo* pdemo) +{ + btSoftBody* psb=Ctor_ClusterTorus(pdemo,btVector3(0,0,0),btVector3(SIMD_PI/2,0,SIMD_HALF_PI)); + btRigidBody* prb=Ctor_BigPlate(pdemo,50,8); + psb->m_cfg.kDF=1; + btSoftBody::AJoint::Specs aj; + aj.axis = btVector3(0,0,1); + psb->appendAngularJoint(aj,prb); +} + +// +static void Init_ClusterCombine(SoftDemo* pdemo) +{ + const btVector3 sz(2,4,2); + btSoftBody* psb0=Ctor_ClusterTorus(pdemo,btVector3(0,8,0),btVector3(SIMD_PI/2,0,SIMD_HALF_PI),sz); + btSoftBody* psb1=Ctor_ClusterTorus(pdemo,btVector3(0,8,10),btVector3(SIMD_PI/2,0,SIMD_HALF_PI),sz); + btSoftBody* psbs[]={psb0,psb1}; + for(int j=0;j<2;++j) + { + psbs[j]->m_cfg.kDF=1; + psbs[j]->m_cfg.kDP=0; + psbs[j]->m_cfg.piterations=1; + psbs[j]->m_clusters[0]->m_matching = 0.05; + psbs[j]->m_clusters[0]->m_ndamping = 0.05; + } + btSoftBody::AJoint::Specs aj; + aj.axis = btVector3(0,0,1); + aj.icontrol = &motorcontrol; + psb0->appendAngularJoint(aj,psb1); + + btSoftBody::LJoint::Specs lj; + lj.position = btVector3(0,8,5); + psb0->appendLinearJoint(lj,psb1); +} + +// +static void Init_ClusterCar(SoftDemo* pdemo) +{ + pdemo->setAzi(180); + const btVector3 origin(100,80,0); + const btQuaternion orientation(-SIMD_PI/2,0,0); + const btScalar widthf=8; + const btScalar widthr=9; + const btScalar length=8; + const btScalar height=4; + const btVector3 wheels[]= { + btVector3(+widthf,-height,+length), // Front left + btVector3(-widthf,-height,+length), // Front right + btVector3(+widthr,-height,-length), // Rear left + btVector3(-widthr,-height,-length), // Rear right + }; + btSoftBody* pa=Ctor_ClusterBunny(pdemo,btVector3(0,0,0),btVector3(0,0,0)); + btSoftBody* pfl=Ctor_ClusterTorus(pdemo,wheels[0],btVector3(0,0,SIMD_HALF_PI),btVector3(2,4,2)); + btSoftBody* pfr=Ctor_ClusterTorus(pdemo,wheels[1],btVector3(0,0,SIMD_HALF_PI),btVector3(2,4,2)); + btSoftBody* prl=Ctor_ClusterTorus(pdemo,wheels[2],btVector3(0,0,SIMD_HALF_PI),btVector3(2,5,2)); + btSoftBody* prr=Ctor_ClusterTorus(pdemo,wheels[3],btVector3(0,0,SIMD_HALF_PI),btVector3(2,5,2)); + + pfl->m_cfg.kDF = + pfr->m_cfg.kDF = + prl->m_cfg.kDF = + prr->m_cfg.kDF = 1; + + btSoftBody::LJoint::Specs lspecs; + lspecs.cfm = 1; + lspecs.erp = 1; + lspecs.position = btVector3(0,0,0); + + lspecs.position=wheels[0];pa->appendLinearJoint(lspecs,pfl); + lspecs.position=wheels[1];pa->appendLinearJoint(lspecs,pfr); + lspecs.position=wheels[2];pa->appendLinearJoint(lspecs,prl); + lspecs.position=wheels[3];pa->appendLinearJoint(lspecs,prr); + + btSoftBody::AJoint::Specs aspecs; + aspecs.cfm = 1; + aspecs.erp = 1; + aspecs.axis = btVector3(1,0,0); + + aspecs.icontrol = &steercontrol_f; + pa->appendAngularJoint(aspecs,pfl); + pa->appendAngularJoint(aspecs,pfr); + + aspecs.icontrol = &motorcontrol; + pa->appendAngularJoint(aspecs,prl); + pa->appendAngularJoint(aspecs,prr); + + pa->rotate(orientation); + pfl->rotate(orientation); + pfr->rotate(orientation); + prl->rotate(orientation); + prr->rotate(orientation); + pa->translate(origin); + pfl->translate(origin); + pfr->translate(origin); + prl->translate(origin); + prr->translate(origin); + pfl->m_cfg.piterations = + pfr->m_cfg.piterations = + prl->m_cfg.piterations = + prr->m_cfg.piterations = 1; + pfl->m_clusters[0]->m_matching = + pfr->m_clusters[0]->m_matching = + prl->m_clusters[0]->m_matching = + prr->m_clusters[0]->m_matching = 0.05; + pfl->m_clusters[0]->m_ndamping = + pfr->m_clusters[0]->m_ndamping = + prl->m_clusters[0]->m_ndamping = + prr->m_clusters[0]->m_ndamping = 0.05; + + Ctor_LinearStair(pdemo,btVector3(0,-8,0),btVector3(3,2,40),0,20); + Ctor_RbUpStack(pdemo,50); + pdemo->m_autocam=true; + +} + +// +static void Init_ClusterRobot(SoftDemo* pdemo) +{ + struct Functor + { + static btSoftBody* CreateBall(SoftDemo* pdemo,const btVector3& pos) + { + btSoftBody* psb=btSoftBodyHelpers::CreateEllipsoid(pdemo->m_softBodyWorldInfo,pos,btVector3(1,1,1)*3,512); + psb->m_materials[0]->m_kLST = 0.45; + psb->m_cfg.kVC = 20; + psb->setTotalMass(50,true); + psb->setPose(true,false); + psb->generateClusters(1); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + return(psb); + } + }; + const btVector3 base=btVector3(0,25,8); + btSoftBody* psb0=Functor::CreateBall(pdemo,base+btVector3(-8,0,0)); + btSoftBody* psb1=Functor::CreateBall(pdemo,base+btVector3(+8,0,0)); + btSoftBody* psb2=Functor::CreateBall(pdemo,base+btVector3(0,0,+8*btSqrt(2))); + const btVector3 ctr=(psb0->clusterCom(0)+psb1->clusterCom(0)+psb2->clusterCom(0))/3; + btCylinderShape* pshp=new btCylinderShape(btVector3(8,1,8)); + btRigidBody* prb=pdemo->localCreateRigidBody(50,btTransform(btQuaternion(0,0,0),ctr+btVector3(0,5,0)),pshp); + btSoftBody::LJoint::Specs ls; + ls.erp=0.5f; + ls.position=psb0->clusterCom(0);psb0->appendLinearJoint(ls,prb); + ls.position=psb1->clusterCom(0);psb1->appendLinearJoint(ls,prb); + ls.position=psb2->clusterCom(0);psb2->appendLinearJoint(ls,prb); + + btBoxShape* pbox=new btBoxShape(btVector3(20,1,40)); + btRigidBody* pgrn=pdemo->localCreateRigidBody(0,btTransform(btQuaternion(0,-SIMD_HALF_PI/2,0),btVector3(0,0,0)),pbox); + + pdemo->m_autocam=true; + +} + +// +static void Init_ClusterStackSoft(SoftDemo* pdemo) +{ + for(int i=0;i<10;++i) + { + btSoftBody* psb=Ctor_ClusterTorus(pdemo,btVector3(0,-9+8.25*i,0),btVector3(0,0,0)); + psb->m_cfg.kDF=1; + } +} + +// +static void Init_ClusterStackMixed(SoftDemo* pdemo) +{ + for(int i=0;i<10;++i) + { + if((i+1)&1) + { + Ctor_BigPlate(pdemo,50,-9+4.25*i); + } + else + { + btSoftBody* psb=Ctor_ClusterTorus(pdemo,btVector3(0,-9+4.25*i,0),btVector3(0,0,0)); + psb->m_cfg.kDF=1; + } + } +} + + +// +// TetraBunny +// +static void Init_TetraBunny(SoftDemo* pdemo) +{ + btSoftBody* psb=btSoftBodyHelpers::CreateFromTetGenData(pdemo->m_softBodyWorldInfo, + TetraBunny::getElements(), + 0, + TetraBunny::getNodes(), + false,true,true); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + psb->rotate(btQuaternion(SIMD_PI/2,0,0)); + psb->setVolumeMass(150); + psb->m_cfg.piterations=2; + //psb->m_cfg.piterations=1; + pdemo->m_cutting=false; + //psb->getCollisionShape()->setMargin(0.01); + psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS+ btSoftBody::fCollision::CL_RS + //+ btSoftBody::fCollision::CL_SELF + ; + + ///pass zero in generateClusters to create cluster for each tetrahedron or triangle + psb->generateClusters(0); + //psb->m_materials[0]->m_kLST=.2; + psb->m_cfg.kDF = 10. ; + + +} + +// +// TetraCube +// +static void Init_TetraCube(SoftDemo* pdemo) +{ + btSoftBody* psb=btSoftBodyHelpers::CreateFromTetGenData(pdemo->m_softBodyWorldInfo, + TetraCube::getElements(), + 0, + TetraCube::getNodes(), + false,true,true); + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + psb->scale(btVector3(4,4,4)); + psb->translate(btVector3(0,5,0)); + psb->setVolumeMass(300); + + + ///fix one vertex + //psb->setMass(0,0); + //psb->setMass(10,0); + //psb->setMass(20,0); + psb->m_cfg.piterations=1; + //psb->generateClusters(128); + psb->generateClusters(16); + //psb->getCollisionShape()->setMargin(0.5); + + psb->getCollisionShape()->setMargin(0.01); + psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS+ btSoftBody::fCollision::CL_RS + //+ btSoftBody::fCollision::CL_SELF + ; + psb->m_materials[0]->m_kLST=0.8; + pdemo->m_cutting=false; +} + + + + + + /* Init */ + void (*demofncs[])(SoftDemo*)= + { + Init_Cloth, + Init_Pressure, + Init_Volume, + Init_Ropes, + Init_RopeAttach, + Init_ClothAttach, + Init_Sticks, + Init_CapsuleCollision, + Init_Collide, + Init_Collide2, + Init_Collide3, + Init_Impact, + Init_Aero, + Init_Aero2, + Init_Friction, + Init_Torus, + Init_TorusMatch, + Init_Bunny, + Init_BunnyMatch, + Init_Cutting1, + Init_ClusterDeform, + Init_ClusterCollide1, + Init_ClusterCollide2, + Init_ClusterSocket, + Init_ClusterHinge, + Init_ClusterCombine, + Init_ClusterCar, + Init_ClusterRobot, + Init_ClusterStackSoft, + Init_ClusterStackMixed, + Init_TetraCube, + Init_TetraBunny, + }; + +void SoftDemo::clientResetScene() +{ + m_azi = 0; + m_cameraDistance = 30.f; + m_cameraTargetPosition.setValue(0,0,0); + + DemoApplication::clientResetScene(); + /* Clean up */ + for(int 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(); + } + while(m_dynamicsWorld->getNumConstraints()) + { + btTypedConstraint* pc=m_dynamicsWorld->getConstraint(0); + m_dynamicsWorld->removeConstraint(pc); + delete pc; + } + btSoftBody* softBody = btSoftBody::upcast(obj); + if (softBody) + { + getSoftDynamicsWorld()->removeSoftBody(softBody); + } else + { + btRigidBody* body = btRigidBody::upcast(obj); + if (body) + m_dynamicsWorld->removeRigidBody(body); + else + m_dynamicsWorld->removeCollisionObject(obj); + } + delete obj; + } + + + //create ground object + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(0,-12,0)); + + btCollisionObject* newOb = new btCollisionObject(); + newOb->setWorldTransform(tr); + newOb->setInterpolationWorldTransform( tr); + int lastDemo = (sizeof(demofncs)/sizeof(demofncs[0]))-1; + + if (current_demo<0) + current_demo = lastDemo; + if (current_demo > lastDemo) + current_demo =0; + + + if (current_demo>19) + { + newOb->setCollisionShape(m_collisionShapes[0]); + } else + { + newOb->setCollisionShape(m_collisionShapes[1]); + } + + m_dynamicsWorld->addCollisionObject(newOb); + + m_softBodyWorldInfo.m_sparsesdf.Reset(); + + + + + + + + motorcontrol.goal = 0; + motorcontrol.maxtorque = 0; + + + + m_softBodyWorldInfo.air_density = (btScalar)1.2; + m_softBodyWorldInfo.water_density = 0; + m_softBodyWorldInfo.water_offset = 0; + m_softBodyWorldInfo.water_normal = btVector3(0,0,0); + m_softBodyWorldInfo.m_gravity.setValue(0,-10,0); + + + m_autocam = false; + m_raycast = false; + m_cutting = false; + m_results.fraction = 1.f; + demofncs[current_demo](this); +} + + +void SoftDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); + + + + + float ms = getDeltaTimeMicroseconds(); + float dt = ms / 1000000.f;//1.0/60.; + + + + if (m_dynamicsWorld) + { + + if (sDemoMode) + { + static float demoCounter = DEMO_MODE_TIMEOUT; + demoCounter-= dt; + if (demoCounter<0) + { + + demoCounter=DEMO_MODE_TIMEOUT; + current_demo++; + current_demo=current_demo%(sizeof(demofncs)/sizeof(demofncs[0])); + clientResetScene(); + } + } + + +//#define FIXED_STEP +#ifdef FIXED_STEP + m_dynamicsWorld->stepSimulation(dt=1.0f/60.f,0); + +#else + //during idle mode, just run 1 simulation step maximum, otherwise 4 at max + int maxSimSubSteps = m_idle ? 1 : 4; + //if (m_idle) + // dt = 1.0/420.f; + + int numSimSteps; + numSimSteps = m_dynamicsWorld->stepSimulation(dt); + //numSimSteps = m_dynamicsWorld->stepSimulation(dt,10,1./240.f); + +#ifdef VERBOSE_TIMESTEPPING_CONSOLEOUTPUT + if (!numSimSteps) + printf("Interpolated transforms\n"); + else + { + if (numSimSteps > maxSimSubSteps) + { + //detect dropping frames + printf("Dropped (%i) simulation steps out of %i\n",numSimSteps - maxSimSubSteps,numSimSteps); + } else + { + printf("Simulated (%i) steps\n",numSimSteps); + } + } +#endif //VERBOSE_TIMESTEPPING_CONSOLEOUTPUT + +#endif + +#ifdef USE_AMD_OPENCL + if (g_openCLSIMDSolver) + g_openCLSIMDSolver->copyBackToSoftBodies(); +#endif //USE_AMD_OPENCL + + if(m_drag) + { + m_node->m_v*=0; + } + + m_softBodyWorldInfo.m_sparsesdf.GarbageCollect(); + + //optional but useful: debug drawing + + } + +#ifdef USE_QUICKPROF + btProfiler::beginBlock("render"); +#endif //USE_QUICKPROF + + renderme(); + + //render the graphics objects, with center of mass shift + + updateCamera(); + + + +#ifdef USE_QUICKPROF + btProfiler::endBlock("render"); +#endif + glFlush(); + //some additional debugging info +#ifdef PRINT_CONTACT_STATISTICS + printf("num manifolds: %i\n",gNumManifold); + printf("num gOverlappingPairs: %i\n",gOverlappingPairs); + +#endif //PRINT_CONTACT_STATISTICS + + + swapBuffers(); + +} + + + +void SoftDemo::renderme() +{ + btIDebugDraw* idraw=m_dynamicsWorld->getDebugDrawer(); + + glDisable(GL_TEXTURE_2D); + glDisable(GL_LIGHTING); + m_dynamicsWorld->debugDrawWorld(); + + int debugMode = m_dynamicsWorld->getDebugDrawer()? m_dynamicsWorld->getDebugDrawer()->getDebugMode() : -1; + + btSoftRigidDynamicsWorld* softWorld = (btSoftRigidDynamicsWorld*)m_dynamicsWorld; + btIDebugDraw* sdraw = softWorld ->getDebugDrawer(); + + + for ( int i=0;igetSoftBodyArray().size();i++) + { + btSoftBody* psb=(btSoftBody*)softWorld->getSoftBodyArray()[i]; + if (softWorld->getDebugDrawer() && !(softWorld->getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe))) + { + btSoftBodyHelpers::DrawFrame(psb,softWorld->getDebugDrawer()); + btSoftBodyHelpers::Draw(psb,softWorld->getDebugDrawer(),softWorld->getDrawFlags()); + } + } + + /* Bodies */ + btVector3 ps(0,0,0); + int nps=0; + + btSoftBodyArray& sbs=getSoftDynamicsWorld()->getSoftBodyArray(); + for(int ib=0;ibm_nodes.size(); + for(int i=0;im_nodes.size();++i) + { + ps+=psb->m_nodes[i].m_x; + } + } + ps/=nps; + if(m_autocam) + m_cameraTargetPosition+=(ps-m_cameraTargetPosition)*0.05; + /* Anm */ + if(!isIdle()) + m_animtime=m_clock.getTimeMilliseconds()/1000.f; + /* Ray cast */ + if(m_raycast) + { + /* Prepare rays */ + const int res=64; + const btScalar fres=res-1; + const btScalar size=8; + const btScalar dist=10; + btTransform trs; + trs.setOrigin(ps); + btScalar rayLength = 1000.f; + + const btScalar angle=m_animtime*0.2; + trs.setRotation(btQuaternion(angle,SIMD_PI/4,0)); + btVector3 dir=trs.getBasis()*btVector3(0,-1,0); + trs.setOrigin(ps-dir*dist); + btAlignedObjectArray origins; + btAlignedObjectArray fractions; + origins.resize(res*res); + fractions.resize(res*res,1.f); + for(int y=0;yrayTest(rayFrom,rayTo,results)) + { + *fraction=results.fraction; + } + } + ++org;++fraction; + } + long ms=btMax(m_clock.getTimeMilliseconds(),1); + long rayperseconds=(1000*(origins.size()*sbs.size()))/ms; + printf("%d ms (%d rays/s)\r\n",int(ms),int(rayperseconds)); + } + } + /* Draw rays */ + const btVector3 c[]={ origins[0], + origins[res-1], + origins[res*(res-1)], + origins[res*(res-1)+res-1]}; + idraw->drawLine(c[0],c[1],btVector3(0,0,0)); + idraw->drawLine(c[1],c[3],btVector3(0,0,0)); + idraw->drawLine(c[3],c[2],btVector3(0,0,0)); + idraw->drawLine(c[2],c[0],btVector3(0,0,0)); + for(int i=0,ni=origins.size();idrawLine(org,org+dir*rayLength*fraction,btVector3(1,0,0)); + } + else + { + idraw->drawLine(org,org-dir*rayLength*0.1,btVector3(0,0,0)); + } + } +#undef RES + } + /* Water level */ + static const btVector3 axis[]={btVector3(1,0,0), + btVector3(0,1,0), + btVector3(0,0,1)}; + if(m_softBodyWorldInfo.water_density>0) + { + const btVector3 c= btVector3((btScalar)0.25,(btScalar)0.25,1); + const btScalar a= (btScalar)0.5; + const btVector3 n= m_softBodyWorldInfo.water_normal; + const btVector3 o= -n*m_softBodyWorldInfo.water_offset; + const btVector3 x= btCross(n,axis[n.minAxis()]).normalized(); + const btVector3 y= btCross(x,n).normalized(); + const btScalar s= 25; + idraw->drawTriangle(o-x*s-y*s,o+x*s-y*s,o+x*s+y*s,c,a); + idraw->drawTriangle(o-x*s-y*s,o+x*s+y*s,o-x*s+y*s,c,a); + } + // + + int lineWidth=280; + int xStart = m_glutScreenWidth - lineWidth; + int yStart = 20; + + if((getDebugMode() & btIDebugDraw::DBG_NoHelpText)==0) + { + setOrthographicProjection(); + glDisable(GL_LIGHTING); + glColor3f(0, 0, 0); + char buf[124]; + + glRasterPos3f(xStart, yStart, 0); + if (sDemoMode) + { + sprintf(buf,"d to toggle demo mode (on)"); + } else + { + sprintf(buf,"d to toggle demo mode (off)"); + } + GLDebugDrawString(xStart,20,buf); + glRasterPos3f(xStart, yStart, 0); + sprintf(buf,"] for next demo (%d)",current_demo); + yStart+=20; + GLDebugDrawString(xStart,yStart,buf); + glRasterPos3f(xStart, yStart, 0); + sprintf(buf,"c to visualize clusters"); + yStart+=20; + GLDebugDrawString(xStart,yStart,buf); + glRasterPos3f(xStart, yStart, 0); + sprintf(buf,"; to toggle camera mode"); + yStart+=20; + GLDebugDrawString(xStart,yStart,buf); + glRasterPos3f(xStart, yStart, 0); + sprintf(buf,"n,m,l,k for power and steering"); + yStart+=20; + GLDebugDrawString(xStart,yStart,buf); + + + resetPerspectiveProjection(); + glEnable(GL_LIGHTING); + } + + DemoApplication::renderme(); + +} + +void SoftDemo::setDrawClusters(bool drawClusters) +{ + if (drawClusters) + { + getSoftDynamicsWorld()->setDrawFlags(getSoftDynamicsWorld()->getDrawFlags()|fDrawFlags::Clusters); + } else + { + getSoftDynamicsWorld()->setDrawFlags(getSoftDynamicsWorld()->getDrawFlags()& (~fDrawFlags::Clusters)); + } +} + + + +void SoftDemo::keyboardCallback(unsigned char key, int x, int y) +{ + switch(key) + { + case 'd': sDemoMode = !sDemoMode; break; + case 'n': motorcontrol.maxtorque=10;motorcontrol.goal+=1;break; + case 'm': motorcontrol.maxtorque=10;motorcontrol.goal-=1;break; + case 'l': steercontrol_f.angle+=0.1;steercontrol_r.angle+=0.1;break; + case 'k': steercontrol_f.angle-=0.1;steercontrol_r.angle-=0.1;break; + case ']': ++current_demo;clientResetScene();break; + case '[': --current_demo;clientResetScene();break; + case ',': m_raycast=!m_raycast;break; + case ';': m_autocam=!m_autocam;break; + case 'c': getSoftDynamicsWorld()->setDrawFlags(getSoftDynamicsWorld()->getDrawFlags()^fDrawFlags::Clusters);break; + case '`': + { + btSoftBodyArray& sbs=getSoftDynamicsWorld()->getSoftBodyArray(); + for(int ib=0;ibstaticSolve(128); + } + } + break; + default: DemoApplication::keyboardCallback(key,x,y); + } +} + +// +void SoftDemo::mouseMotionFunc(int x,int y) +{ + if(m_node&&(m_results.fraction<1.f)) + { + if(!m_drag) + { +#define SQ(_x_) (_x_)*(_x_) + if((SQ(x-m_lastmousepos[0])+SQ(y-m_lastmousepos[1]))>6) + { + m_drag=true; + } +#undef SQ + } + if(m_drag) + { + m_lastmousepos[0] = x; + m_lastmousepos[1] = y; + } + } + else + { + DemoApplication::mouseMotionFunc(x,y); + } +} + +// +void SoftDemo::mouseFunc(int button, int state, int x, int y) +{ + if(button==0) + { + switch(state) + { + case 0: + { + m_results.fraction=1.f; + DemoApplication::mouseFunc(button,state,x,y); + if(!m_pickConstraint) + { + const btVector3 rayFrom=m_cameraPosition; + const btVector3 rayTo=getRayTo(x,y); + const btVector3 rayDir=(rayTo-rayFrom).normalized(); + btSoftBodyArray& sbs=getSoftDynamicsWorld()->getSoftBodyArray(); + for(int ib=0;ibrayTest(rayFrom,rayTo,res)) + { + m_results=res; + } + } + if(m_results.fraction<1.f) + { + m_impact = rayFrom+(rayTo-rayFrom)*m_results.fraction; + m_drag = m_cutting ? false : true; + m_lastmousepos[0] = x; + m_lastmousepos[1] = y; + m_node = 0; + switch(m_results.feature) + { + case btSoftBody::eFeature::Tetra: + { + btSoftBody::Tetra& tet=m_results.body->m_tetras[m_results.index]; + m_node=tet.m_n[0]; + for(int i=1;i<4;++i) + { + if( (m_node->m_x-m_impact).length2()> + (tet.m_n[i]->m_x-m_impact).length2()) + { + m_node=tet.m_n[i]; + } + } + break; + } + case btSoftBody::eFeature::Face: + { + btSoftBody::Face& f=m_results.body->m_faces[m_results.index]; + m_node=f.m_n[0]; + for(int i=1;i<3;++i) + { + if( (m_node->m_x-m_impact).length2()> + (f.m_n[i]->m_x-m_impact).length2()) + { + m_node=f.m_n[i]; + } + } + } + break; + } + if(m_node) m_goal=m_node->m_x; + return; + } + } + } + break; + case 1: + if((!m_drag)&&m_cutting&&(m_results.fraction<1.f)) + { + ImplicitSphere isphere(m_impact,1); + printf("Mass before: %f\r\n",m_results.body->getTotalMass()); + m_results.body->refine(&isphere,0.0001,true); + printf("Mass after: %f\r\n",m_results.body->getTotalMass()); + } + m_results.fraction=1.f; + m_drag=false; + DemoApplication::mouseFunc(button,state,x,y); + break; + } + } + else + { + DemoApplication::mouseFunc(button,state,x,y); + } +} + + +void SoftDemo::initPhysics() +{ + ///create concave ground mesh + + + m_azi = 0; + + //reset and disable motorcontrol at the start + motorcontrol.goal = 0; + motorcontrol.maxtorque = 0; + + btCollisionShape* groundShape = 0; + { + int i; + int j; + + const int NUM_VERTS_X = 30; + const int NUM_VERTS_Y = 30; + const int totalVerts = NUM_VERTS_X*NUM_VERTS_Y; + const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1); + + gGroundVertices = new btVector3[totalVerts]; + gGroundIndices = new int[totalTriangles*3]; + + btScalar offset(-50); + + for ( i=0;isetMargin(0.5); + } + + m_collisionShapes.push_back(groundShape); + + btCollisionShape* groundBox = new btBoxShape (btVector3(100,CUBE_HALF_EXTENTS,100)); + m_collisionShapes.push_back(groundBox); + + btCompoundShape* cylinderCompound = new btCompoundShape; + btCollisionShape* cylinderShape = new btCylinderShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS)); + btTransform localTransform; + localTransform.setIdentity(); + cylinderCompound->addChildShape(localTransform,cylinderShape); + btQuaternion orn(btVector3(0,1,0),SIMD_PI); + localTransform.setRotation(orn); + cylinderCompound->addChildShape(localTransform,cylinderShape); + + m_collisionShapes.push_back(cylinderCompound); + + + m_dispatcher=0; + + ///register some softbody collision algorithms on top of the default btDefaultCollisionConfiguration + m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration(); + + + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + m_softBodyWorldInfo.m_dispatcher = m_dispatcher; + + //////////////////////////// + ///Register softbody versus softbody collision algorithm + + + ///Register softbody versus rigidbody collision algorithm + + + //////////////////////////// + + btVector3 worldAabbMin(-1000,-1000,-1000); + btVector3 worldAabbMax(1000,1000,1000); + + m_broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies); + + m_softBodyWorldInfo.m_broadphase = m_broadphase; + + btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver(); + + m_solver = solver; + + btSoftBodySolver* softBodySolver = 0; +#ifdef USE_AMD_OPENCL + + static bool once = true; + if (once) + { + once=false; + initCL(0,0); + } + + if( g_openCLSIMDSolver ) + delete g_openCLSIMDSolver; + if( g_softBodyOutput ) + delete g_softBodyOutput; + + if (1) + { + g_openCLSIMDSolver = new btOpenCLSoftBodySolverSIMDAware( g_cqCommandQue, g_cxMainContext); + // g_openCLSIMDSolver = new btOpenCLSoftBodySolver( g_cqCommandQue, g_cxMainContext); + g_openCLSIMDSolver->setCLFunctions(new CachingCLFunctions(g_cqCommandQue, g_cxMainContext)); + } + + + + softBodySolver = g_openCLSIMDSolver; + g_softBodyOutput = new btSoftBodySolverOutputCLtoCPU; +#endif //USE_AMD_OPENCL + + btDiscreteDynamicsWorld* world = new btSoftRigidDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration,softBodySolver); + m_dynamicsWorld = world; + m_dynamicsWorld->setInternalTickCallback(pickingPreTickCallback,this,true); + + + m_dynamicsWorld->getDispatchInfo().m_enableSPU = true; + m_dynamicsWorld->setGravity(btVector3(0,-10,0)); + m_softBodyWorldInfo.m_gravity.setValue(0,-10,0); + + // clientResetScene(); + + m_softBodyWorldInfo.m_sparsesdf.Initialize(); + clientResetScene(); +} + + + + + + +void SoftDemo::exitPhysics() +{ + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;j m_SoftSoftCollisionAlgorithms; + + btAlignedObjectArray m_SoftRigidCollisionAlgorithms; + + btSoftBodyWorldInfo m_softBodyWorldInfo; + + + + bool m_autocam; + bool m_cutting; + bool m_raycast; + btScalar m_animtime; + btClock m_clock; + int m_lastmousepos[2]; + btVector3 m_impact; + btSoftBody::sRayCast m_results; + btSoftBody::Node* m_node; + btVector3 m_goal; + bool m_drag; + + + //keep the collision shapes, for deletion/cleanup + btAlignedObjectArray m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + + btConstraintSolver* m_solver; + + btCollisionAlgorithmCreateFunc* m_boxBoxCF; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + +public: + + void initPhysics(); + + void exitPhysics(); + + SoftDemo() : m_drag(false) + { + setTexturing(true); + setShadows(true); + } + virtual ~SoftDemo() + { + exitPhysics(); + } + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + void createStack( btCollisionShape* boxShape, float halfCubeSize, int size, float zPos ); + + static DemoApplication* Create() + { + SoftDemo* demo = new SoftDemo; + demo->myinit(); + demo->initPhysics(); + return demo; + } + + virtual void setDrawClusters(bool drawClusters); + + virtual const btSoftRigidDynamicsWorld* getSoftDynamicsWorld() const + { + ///just make it a btSoftRigidDynamicsWorld please + ///or we will add type checking + return (btSoftRigidDynamicsWorld*) m_dynamicsWorld; + } + + virtual btSoftRigidDynamicsWorld* getSoftDynamicsWorld() + { + ///just make it a btSoftRigidDynamicsWorld please + ///or we will add type checking + return (btSoftRigidDynamicsWorld*) m_dynamicsWorld; + } + + // + void clientResetScene(); + void renderme(); + void keyboardCallback(unsigned char key, int x, int y); + void mouseFunc(int button, int state, int x, int y); + void mouseMotionFunc(int x,int y); + +}; + +#define MACRO_SOFT_DEMO(a) class SoftDemo##a : public SoftDemo\ +{\ +public:\ + static DemoApplication* Create()\ + {\ + SoftDemo* demo = new SoftDemo##a;\ + extern unsigned int current_demo;\ + current_demo=a;\ + demo->myinit();\ + demo->initPhysics();\ + return demo;\ + }\ +}; + + +MACRO_SOFT_DEMO(0) //Init_Cloth +MACRO_SOFT_DEMO(1) //Init_Pressure +MACRO_SOFT_DEMO(2)//Init_Volume +MACRO_SOFT_DEMO(3)//Init_Ropes +MACRO_SOFT_DEMO(4)//Init_Ropes_Attach +MACRO_SOFT_DEMO(5)//Init_ClothAttach +MACRO_SOFT_DEMO(6)//Init_Sticks +MACRO_SOFT_DEMO(7)//Init_Collide +MACRO_SOFT_DEMO(8)//Init_Collide2 +MACRO_SOFT_DEMO(9)//Init_Collide3 +MACRO_SOFT_DEMO(10)//Init_Impact +MACRO_SOFT_DEMO(11)//Init_Aero +MACRO_SOFT_DEMO(12)//Init_Friction +MACRO_SOFT_DEMO(13)//Init_Torus +MACRO_SOFT_DEMO(14)//Init_TorusMatch +MACRO_SOFT_DEMO(15)//Init_Bunny +MACRO_SOFT_DEMO(16)//Init_BunnyMatch +MACRO_SOFT_DEMO(17)//Init_Cutting1 +MACRO_SOFT_DEMO(18)//Init_ClusterDeform +MACRO_SOFT_DEMO(19)//Init_ClusterCollide1 +MACRO_SOFT_DEMO(20)//Init_ClusterCollide2 +MACRO_SOFT_DEMO(21)//Init_ClusterSocket +MACRO_SOFT_DEMO(22)//Init_ClusterHinge +MACRO_SOFT_DEMO(23)//Init_ClusterCombine +MACRO_SOFT_DEMO(24)//Init_ClusterCar +MACRO_SOFT_DEMO(25)//Init_ClusterRobot +MACRO_SOFT_DEMO(26)//Init_ClusterStackSoft +MACRO_SOFT_DEMO(27)//Init_ClusterStackMixed +MACRO_SOFT_DEMO(28)//Init_TetraCube +MACRO_SOFT_DEMO(29)//Init_TetraBunny + + +#endif //CCD_PHYSICS_DEMO_H + + + + + diff --git a/Demos/SoftDemo/bunny.inl b/Demos/SoftDemo/bunny.inl new file mode 100755 index 0000000..fbdbfd3 --- /dev/null +++ b/Demos/SoftDemo/bunny.inl @@ -0,0 +1,4 @@ +static const char* getNodes() { return( +"454 3 0 0\n"" 0 -2.0063499999999999 0.79804200000000003 0.373554\n"" 1 -2.1011299999999999 0.90212400000000004 -0.88661400000000001\n"" 2 -1.4052100000000001 2.0628700000000002 -1.0458400000000001\n"" 3 -1.2015499999999999 1.7112400000000001 0.56249400000000005\n"" 4 0.02112 2.8512499999999998 -0.95618999999999998\n"" 5 0.011136 2.5152199999999998 0.59149200000000002\n"" 6 -1.51681 0.56199600000000005 1.42523\n"" 7 -0.977406 1.4278999999999999 1.24143\n"" 8 0.0051900000000000002 1.9088499999999999 1.41222\n"" 9 -2.4877400000000001 0.98449799999999998 -1.6695199999999999\n"" 10 -1.57328 2.1440000000000001 -1.7594799999999999\n"" 11 0.027768000000000001 2.8961600000000001 -2.0317599999999998\n"" 12 -2.4129700000000001 0.80116799999999999 -2.6594799999999998\n"" 13 -1.46269 1.9456500000000001 -2.6205799999999999\n"" 14 0.031758000000000002 2.6255500000000001 -2.7499899999999999\n"" 15 -2.0392999999999999 -0.24690000000000001 -4.0092699999999999\n"" 16 -1.4902899999999999 1.53495 -3.7649599999999999\n"" 17 0.037566000000000002 2.2566199999999998 -3.78904\n"" 18 -1.29721 -0.760656 -5.3216200000000002\n"" 19 -1.0264500000000001 0.069264000000000006 -5.2883199999999997\n"" 20 -1.0864400000000001 0.58933800000000003 -4.8886700000000003\n"" 21 -0.71934600000000004 1.3127200000000001 -4.5609200000000003\n"" 22 -0.47337000000000001 1.6606799999999999 -4.4356900000000001\n"" 23 0.040806000000000002 1.86575 -4.4139699999999999\n"" 24 -1.01305 0.61432200000000003 -5.5222899999999999\n"" 25 -0.62443199999999999 1.0636699999999999 -5.7151800000000001\n"" 26 -0.77822400000000003 1.2710900000000001 -5.0200699999999996\n"" 27 -0.59924999999999995 1.8655900000000001 -4.7962899999999999\n"" 28 0.043422000000000002 2.1701199999999998 -4.7666300000000001\n"" 29 -0.467478 1.5525199999999999 -5.5298400000000001\n"" 30 0.047742 1.6934499999999999 -5.5900800000000004\n"" 31 -1.5133300000000001 -3.3024100000000001 -3.3468599999999999\n"" 32 -1.6057999999999999 -3.6205099999999999 -3.9312499999999999\n"" 33 -2.6810299999999998 -0.71110200000000001 -2.7969499999999998\n"" 34 -2.7569300000000001 -0.55810199999999999 -1.86805\n"" 35 -2.2238699999999998 -0.60064799999999996 -0.95672400000000002\n"" 36 -2.2319 -0.55194600000000005 -0.066264000000000003\n"" 37 -1.97367 -0.58961399999999997 0.53195400000000004\n"" 38 -1.6947099999999999 -0.11317199999999999 1.8690100000000001\n"" 39 -2.11442 -0.78804600000000002 0.86941199999999996\n"" 40 -2.1847599999999998 -1.2017899999999999 1.2143299999999999\n"" 41 -1.7037899999999999 -1.3912100000000001 0.142008\n"" 42 -1.79366 -0.93130800000000002 2.2183000000000002\n"" 43 -1.7627200000000001 -0.73113600000000001 2.51458\n"" 44 -1.74098 -1.74478 0.64694399999999996\n"" 45 -1.5849899999999999 -1.6370899999999999 0.218082\n"" 46 -1.3714 -2.2354400000000001 1.7418499999999999\n"" 47 -1.14259 -1.7219800000000001 2.5314999999999999\n"" 48 -1.1462300000000001 -1.44584 3.04271\n"" 49 -1.72363 -1.65859 -0.39266400000000001\n"" 50 -1.7740499999999999 -1.6849099999999999 -1.0451999999999999\n"" 51 -2.3972199999999999 -1.87879 -2.2570000000000001\n"" 52 -2.3559999999999999 -2.9314900000000002 -2.5649600000000001\n"" 53 -1.9900100000000001 -3.4211100000000001 -2.7963200000000001\n"" 54 -1.69374 -3.7088399999999999 -3.53532\n"" 55 -2.2454299999999998 -3.5692900000000001 -1.9397899999999999\n"" 56 -2.2864300000000002 -3.77834 -2.10466\n"" 57 -2.2926700000000002 -3.7443599999999999 -1.3294600000000001\n"" 58 -1.6362099999999999 -3.39913 1.55494\n"" 59 -1.5402100000000001 -3.9804400000000002 1.7164699999999999\n"" 60 -1.6856899999999999 -2.5701499999999999 0.33473999999999998\n"" 61 -1.1098399999999999 -3.0533600000000001 1.9575899999999999\n"" 62 -1.6798299999999999 -3.1615099999999998 2.3719100000000002\n"" 63 -1.6955899999999999 -3.9803600000000001 2.4744700000000002\n"" 64 -1.1299699999999999 -2.8505600000000002 2.5077199999999999\n"" 65 -1.5803 -3.9803799999999998 2.79962\n"" 66 -1.2543800000000001 -3.9803600000000001 3.05606\n"" 67 -0.012264000000000001 -1.91774 3.31847\n"" 68 -0.0075960000000000003 -2.22756 2.4797799999999999\n"" 69 -1.3185199999999999 -2.03857 -0.24552599999999999\n"" 70 -1.54192 -1.6950700000000001 -0.038094000000000003\n"" 71 -1.6302399999999999 -1.5652900000000001 0.010584\n"" 72 -0.54714600000000002 -2.5150999999999999 -0.27547199999999999\n"" 73 -0.68966400000000005 -2.5785100000000001 -0.74843400000000004\n"" 74 -0.68381999999999998 -2.29792 -1.13124\n"" 75 -1.45807 -2.78965 -1.4571000000000001\n"" 76 -1.88889 -3.03241 -1.94861\n"" 77 0.016643999999999999 -2.6251600000000002 -1.5766\n"" 78 -0.43575000000000003 -2.5064899999999999 -1.32864\n"" 79 -0.96067199999999997 -2.8615900000000001 -1.7606999999999999\n"" 80 0.023154000000000001 -2.7205499999999998 -2.6635\n"" 81 -0.72217799999999999 -3.4893999999999998 -2.6321300000000001\n"" 82 -0.54899399999999998 -3.50515 -1.7670699999999999\n"" 83 -0.69881400000000005 -3.59917 -1.12985\n"" 84 -1.2481899999999999 -3.0818400000000001 -0.807894\n"" 85 -1.41449 -3.6600999999999999 -0.24563399999999999\n"" 86 -2.0695000000000001 -3.7349199999999998 -0.51227999999999996\n"" 87 -2.0184099999999998 -3.1911800000000001 -1.27379\n"" 88 0.011766 -2.7572999999999999 -0.81328199999999995\n"" 89 -0.34977599999999998 -2.5832199999999998 -0.26063999999999998\n"" 90 0.0082679999999999993 -2.6970700000000001 -0.226572\n"" 91 -0.78081 -3.0613299999999999 0.47486400000000001\n"" 92 0.000852 -2.8652899999999999 0.942384\n"" 93 -0.68570399999999998 -2.7192400000000001 1.8263799999999999\n"" 94 -0.003552 -2.6613500000000001 1.71241\n"" 95 -0.33728999999999998 -3.98041 1.95644\n"" 96 -0.15748799999999999 -3.4080599999999999 1.63991\n"" 97 -0.295566 -3.1863800000000002 2.3391199999999999\n"" 98 -0.76257600000000003 -3.9803899999999999 2.8759000000000001\n"" 99 -0.350304 -3.98041 2.2373500000000002\n"" 100 -1.8237699999999999 0.32519399999999998 3.7555299999999998\n"" 101 -1.6115600000000001 1.16042 3.0165999999999999\n"" 102 -1.6629499999999999 0.75673800000000002 2.6597300000000001\n"" 103 -1.72563 -0.034332000000000001 3.1910599999999998\n"" 104 -1.3883799999999999 -0.72773399999999999 3.5243199999999999\n"" 105 -1.52085 -0.490782 4.53925\n"" 106 -1.1709799999999999 -0.82781400000000005 4.3680700000000003\n"" 107 -1.00604 -0.939438 3.6563300000000001\n"" 108 -0.875502 -1.01417 4.1856\n"" 109 -0.46665600000000002 -1.28548 3.7355200000000002\n"" 110 -0.46123799999999998 -1.28983 4.17781\n"" 111 -0.014045999999999999 -1.3988100000000001 3.7371500000000002\n"" 112 -0.016379999999999999 -1.2811600000000001 4.1475999999999997\n"" 113 -0.018815999999999999 -1.15577 4.57639\n"" 114 -0.336816 -1.20733 4.58284\n"" 115 -0.68753399999999998 -0.99715200000000004 4.6243400000000001\n"" 116 -0.93086999999999998 -0.77779200000000004 4.7504299999999997\n"" 117 -1.1016699999999999 -0.35222999999999999 5.0820699999999999\n"" 118 -0.99337200000000003 0.01188 5.0003200000000003\n"" 119 -1.3205 0.11948400000000001 4.6136100000000004\n"" 120 -1.5343800000000001 0.54183599999999998 4.0246899999999997\n"" 121 -1.53356 0.68299799999999999 3.9803299999999999\n"" 122 -1.3582799999999999 1.27593 3.7064400000000002\n"" 123 -0.020202000000000001 -1.17205 4.7980799999999997\n"" 124 -0.17845800000000001 -1.26305 4.9630799999999997\n"" 125 -0.022908000000000001 -1.1687000000000001 5.2418199999999997\n"" 126 -0.024695999999999999 -0.94744200000000001 5.5876099999999997\n"" 127 -0.18768000000000001 -1.1073299999999999 5.3368599999999997\n"" 128 -0.35931000000000002 -1.10669 5.0479799999999999\n"" 129 -0.811998 -0.98599199999999998 5.2691999999999997\n"" 130 -0.51344400000000001 -1.02569 5.55328\n"" 131 -0.98299800000000004 -0.56501999999999997 5.3826799999999997\n"" 132 -0.83066399999999996 -0.62549999999999994 5.6758499999999996\n"" 133 -0.50098200000000004 -0.50960399999999995 5.8776400000000004\n"" 134 -0.026598 -0.87985199999999997 5.9152300000000002\n"" 135 -0.90429000000000004 0.19589999999999999 5.3046699999999998\n"" 136 -0.81535199999999997 -0.21312 5.6727299999999996\n"" 137 -0.42367199999999999 0.22109400000000001 5.8544\n"" 138 -0.026748000000000001 -0.25515599999999999 6.0940200000000004\n"" 139 -0.025493999999999999 0.276252 6.0194400000000003\n"" 140 -0.521814 0.79934400000000005 5.6858000000000004\n"" 141 -0.023238000000000002 0.96962999999999999 5.8229899999999999\n"" 142 -0.75326400000000004 0.84007200000000004 5.5060700000000002\n"" 143 -0.75390599999999997 1.5014799999999999 5.1456099999999996\n"" 144 -0.018762000000000001 1.70442 5.2732200000000002\n"" 145 -0.955044 0.75435600000000003 5.3332699999999997\n"" 146 -1.10284 1.1818200000000001 5.0668800000000003\n"" 147 -0.95933999999999997 1.7504200000000001 4.3948799999999997\n"" 148 -1.1969700000000001 1.2433799999999999 4.6791799999999997\n"" 149 -1.23709 0.98764799999999997 4.1595399999999998\n"" 150 -1.1178900000000001 0.96413400000000005 4.9031599999999997\n"" 151 -1.15696 1.00024 4.6936299999999997\n"" 152 -1.05067 0.66004799999999997 5.1637300000000002\n"" 153 -0.96613199999999999 0.34451999999999999 5.1306700000000003\n"" 154 -1.0339100000000001 0.21693000000000001 4.8971299999999998\n"" 155 -1.14191 0.38449800000000001 4.5636299999999999\n"" 156 -1.1704300000000001 0.77507400000000004 4.3866199999999997\n"" 157 -1.2187600000000001 2.4617200000000001 4.0832199999999998\n"" 158 -1.30006 1.85564 3.8536299999999999\n"" 159 -1.44909 1.8689100000000001 3.5269900000000001\n"" 160 -0.013254 2.19998 4.49648\n"" 161 -0.52937999999999996 2.3775900000000001 4.0718100000000002\n"" 162 -1.02088 0.65710199999999996 5.0446999999999997\n"" 163 -0.96312600000000004 0.40659600000000001 4.9839000000000002\n"" 164 -1.08928 0.83882999999999996 4.8728800000000003\n"" 165 -1.08297 0.89140799999999998 4.6565200000000004\n"" 166 -1.0815300000000001 0.77475000000000005 4.4651500000000004\n"" 167 -1.1177900000000001 0.46984799999999999 4.6161099999999999\n"" 168 -1.00573 0.363234 4.8400499999999997\n"" 169 -1.1392599999999999 0.61656 4.8154899999999996\n"" 170 -0.65003999999999995 2.7326800000000002 3.9430399999999999\n"" 171 -1.4495100000000001 3.1655500000000001 4.0157800000000003\n"" 172 -1.59406 3.0802 3.8075600000000001\n"" 173 -1.21844 2.8713000000000002 3.48916\n"" 174 -1.60063 3.85398 3.6123699999999999\n"" 175 -1.3017700000000001 3.3890799999999999 3.2126100000000002\n"" 176 -1.21326 3.1529699999999998 2.8556599999999999\n"" 177 -1.16333 2.80755 3.12364\n"" 178 -1.5950200000000001 4.5435999999999996 3.0055999999999998\n"" 179 -1.44184 3.9206400000000001 2.77929\n"" 180 -1.8554299999999999 4.6612099999999996 1.82836\n"" 181 -1.62605 4.09856 2.2921100000000001\n"" 182 -1.8726700000000001 4.0265899999999997 1.7201200000000001\n"" 183 -1.6127499999999999 3.7460499999999999 2.2633899999999998\n"" 184 -1.81474 3.2039800000000001 2.1617299999999999\n"" 185 -1.5819399999999999 3.1758600000000001 2.4753799999999999\n"" 186 -1.69387 2.4910000000000001 2.6859999999999999\n"" 187 -1.4352100000000001 2.6525799999999999 2.9736199999999999\n"" 188 -1.32026 3.4141599999999999 2.6752600000000002\n"" 189 -0.0075779999999999997 2.3737900000000001 3.6121699999999999\n"" 190 -0.34406999999999999 2.6552099999999998 3.4333399999999998\n"" 191 -0.53356199999999998 3.0379999999999998 3.1746400000000001\n"" 192 -0.75442799999999999 3.2104599999999999 3.6774800000000001\n"" 193 -0.75750600000000001 3.4630200000000002 2.8989500000000001\n"" 194 -0.89756400000000003 3.6691199999999999 3.34639\n"" 195 -0.979128 3.96475 2.9464800000000002\n"" 196 -1.0348900000000001 3.9803199999999999 2.4925000000000002\n"" 197 -0.96278399999999997 3.5502600000000002 2.2239499999999999\n"" 198 -0.93867 3.2183799999999998 2.2698100000000001\n"" 199 -0.81897600000000004 2.66615 2.5513599999999999\n"" 200 -0.573384 2.24261 2.8419500000000002\n"" 201 -0.62487599999999999 1.89547 2.9886200000000001\n"" 202 -0.0029759999999999999 2.3051599999999999 2.8429000000000002\n"" 203 -0.001098 1.7866200000000001 2.4089200000000002\n"" 204 -0.77425200000000005 1.62087 2.60697\n"" 205 0.00059999999999999995 1.63778 2.09483\n"" 206 -0.67835999999999996 1.4218999999999999 2.31332\n"" 207 0.043560000000000001 0.097865999999999995 -5.3003799999999996\n"" 208 0.047190000000000003 0.73262400000000005 -5.7368199999999998\n"" 209 -0.197052 0.69169199999999997 -5.7195099999999996\n"" 210 -0.53469 0.65069399999999999 -5.7019000000000002\n"" 211 -0.28464 0.088373999999999994 -5.2965400000000002\n"" 212 -0.62674799999999997 0.078822000000000003 -5.2924199999999999\n"" 213 -0.51863400000000004 -3.5091999999999999 -3.6500599999999999\n"" 214 -0.69015599999999999 -3.9756300000000002 -2.62039\n"" 215 -0.43009799999999998 -3.9922300000000002 -3.6383100000000002\n"" 216 -1.5472999999999999 -3.9922900000000001 -3.9483100000000002\n"" 217 -1.6352500000000001 -3.9922900000000001 -3.5523799999999999\n"" 218 -2.2279300000000002 -3.9922900000000001 -2.1217199999999998\n"" 219 -2.2341700000000002 -3.9922900000000001 -1.3465199999999999\n"" 220 -2.0110000000000001 -3.9922800000000001 -0.47173799999999999\n"" 221 -1.35599 -3.9922499999999999 -0.23388600000000001\n"" 222 -0.64031400000000005 -3.9922399999999998 -1.1181099999999999\n"" 223 -0.49049399999999999 -3.9922300000000002 -1.75532\n"" 224 0.041658000000000001 -0.54903000000000002 -5.1501200000000003\n"" 225 0.036701999999999999 -1.68591 -4.6197999999999997\n"" 226 0.026970000000000001 -3.01416 -3.3587899999999999\n"" 227 -1.1918299999999999 -1.81281 -5.0749000000000004\n"" 228 -1.4243699999999999 -3.2552599999999998 -3.5231300000000001\n"" 229 -1.62001 -1.67693 -4.0191699999999999\n"" 230 -0.80728200000000006 -0.71911199999999997 -5.7540199999999997\n"" 231 -0.31252799999999997 -0.73477800000000004 -5.6672900000000004\n"" 232 -0.74677800000000005 -1.76105 -5.3974000000000002\n"" 233 -0.28569600000000001 -1.73786 -5.2757500000000004\n"" 234 -1.0115700000000001 -3.1747899999999998 -3.9295900000000001\n"" 235 -0.59875800000000001 -3.0943100000000001 -3.8752399999999998\n"" 236 -1.1170100000000001 -3.6316899999999999 -4.3481399999999999\n"" 237 -0.67781999999999998 -3.49858 -4.2448100000000002\n"" 238 -0.64891200000000004 -3.9922499999999999 -4.2024499999999998\n"" 239 -1.0981099999999999 -3.99227 -4.3057800000000004\n"" 240 -2.0971700000000002 -2.0067499999999998 -3.0719099999999999\n"" 241 -0.84709199999999996 -2.6262300000000001 -4.7891599999999999\n"" 242 -1.2760199999999999 -2.6923499999999998 -4.4246800000000004\n"" 243 -1.56667 -2.4896699999999998 -3.6830099999999999\n"" 244 -0.46418399999999999 -2.5888800000000001 -4.6686800000000002\n"" 245 0.031043999999999999 -2.55166 -3.9095499999999999\n"" 246 0.535416 -2.5903900000000002 -4.66256\n"" 247 1.6260399999999999 -2.4944899999999999 -3.6634600000000002\n"" 248 1.34389 -2.6962999999999999 -4.4086400000000001\n"" 249 0.91964999999999997 -2.6288999999999998 -4.7783499999999997\n"" 250 2.1504799999999999 -2.0131700000000001 -3.04589\n"" 251 1.1606000000000001 -3.9956800000000001 -4.2919499999999999\n"" 252 0.71017799999999998 -3.9943 -4.1941300000000004\n"" 253 0.74109000000000003 -3.5007199999999998 -4.2361199999999997\n"" 254 1.1811100000000001 -3.6351599999999999 -4.3340699999999996\n"" 255 0.65872799999999998 -3.0962100000000001 -3.86754\n"" 256 1.0719399999999999 -3.17794 -3.91682\n"" 257 0.36694199999999999 -1.7388399999999999 -5.2717599999999996\n"" 258 0.82940400000000003 -1.7634300000000001 -5.3877499999999996\n"" 259 0.40159800000000001 -0.73585800000000001 -5.6629199999999997\n"" 260 0.89742599999999995 -0.72168600000000005 -5.7435799999999997\n"" 261 1.6859299999999999 -1.6819299999999999 -3.99892\n"" 262 1.47949 -3.2596500000000002 -3.5053399999999999\n"" 263 1.2703199999999999 -1.8165199999999999 -5.0598200000000002\n"" 264 0.52179600000000004 -3.99376 -1.74912\n"" 265 0.66380399999999995 -3.9942099999999998 -1.1101300000000001\n"" 266 1.36859 -3.9963700000000002 -0.21720600000000001\n"" 267 2.0264600000000002 -3.99838 -0.44701800000000003\n"" 268 2.2603300000000002 -3.9990800000000002 -1.319\n"" 269 2.2635900000000002 -3.9990800000000002 -2.09422\n"" 270 1.6884699999999999 -3.9973000000000001 -3.5320200000000002\n"" 271 1.60538 -3.9970400000000001 -3.9289999999999998\n"" 272 0.48447000000000001 -3.9936099999999999 -3.6327099999999999\n"" 273 0.73209599999999997 -3.9777800000000001 -2.6116799999999998\n"" 274 0.57460199999999995 -3.51085 -3.64337\n"" 275 0.71366399999999997 0.076794000000000001 -5.2842099999999999\n"" 276 0.37166399999999999 0.087384000000000003 -5.2925199999999997\n"" 277 0.62834999999999996 0.64893599999999996 -5.6947799999999997\n"" 278 0.291078 0.69095399999999996 -5.71652\n"" 279 0.676176 1.4198599999999999 2.3216199999999998\n"" 280 0.76906200000000002 1.6185400000000001 2.6164299999999998\n"" 281 0.61585800000000002 1.8935999999999999 2.9962200000000001\n"" 282 0.56720999999999999 2.2408899999999998 2.8489399999999998\n"" 283 0.81762000000000001 2.6636799999999998 2.5613700000000001\n"" 284 0.94242599999999999 3.2155399999999998 2.2813300000000001\n"" 285 0.96809999999999996 3.5473400000000002 2.2357800000000001\n"" 286 1.0382100000000001 3.9771899999999998 2.5051899999999998\n"" 287 0.97684800000000005 3.9617900000000001 2.9584600000000001\n"" 288 0.88949999999999996 3.66642 3.3573300000000001\n"" 289 0.75431400000000004 3.4607399999999999 2.90821\n"" 290 0.74093399999999998 3.2081900000000001 3.6866400000000001\n"" 291 0.52572600000000003 3.0364 3.18113\n"" 292 0.331926 2.6541899999999998 3.4374899999999999\n"" 293 1.31962 3.4101699999999999 2.69143\n"" 294 1.42859 2.64825 2.9911699999999999\n"" 295 1.6902699999999999 2.4858899999999999 2.7067299999999999\n"" 296 1.583 3.1710799999999999 2.4947599999999999\n"" 297 1.8197000000000001 3.1984900000000001 2.1839900000000001\n"" 298 1.61812 3.7411699999999999 2.2831700000000001\n"" 299 1.8855299999999999 4.0209200000000003 1.7431399999999999\n"" 300 1.6321399999999999 4.0936399999999997 2.3120599999999998\n"" 301 1.8688800000000001 4.6555900000000001 1.8511599999999999\n"" 302 1.44143 3.91628 2.7969499999999998\n"" 303 1.59371 4.53878 3.0251199999999998\n"" 304 1.15537 2.8040500000000002 3.1378300000000001\n"" 305 1.20963 3.1493099999999998 2.8704999999999998\n"" 306 1.2944599999999999 3.3851599999999999 3.2284999999999999\n"" 307 1.5898099999999999 3.8491599999999999 3.6318999999999999\n"" 308 1.2061900000000001 2.8676400000000002 3.5040100000000001\n"" 309 1.5785199999999999 3.0754000000000001 3.8269899999999999\n"" 310 1.4316899999999999 3.1612 4.0334199999999996\n"" 311 0.63185400000000003 2.7307399999999999 3.9508899999999998\n"" 312 1.1039600000000001 0.61316999999999999 4.8292299999999999\n"" 313 0.96937799999999996 0.36025200000000002 4.85215\n"" 314 1.08449 0.46652399999999999 4.6295999999999999\n"" 315 1.05101 0.77152799999999999 4.4782099999999998\n"" 316 1.0504500000000001 0.88817999999999997 4.6695799999999998\n"" 317 1.0539499999999999 0.83559000000000005 4.8860000000000001\n"" 318 0.92514600000000002 0.40374599999999999 4.9954700000000001\n"" 319 0.982908 0.65407800000000005 5.0569800000000003\n"" 320 0.50856000000000001 2.37602 4.0781700000000001\n"" 321 1.43333 1.86456 3.5446499999999999\n"" 322 1.2802800000000001 1.85175 3.8694299999999999\n"" 323 1.198 2.4580700000000002 4.09802\n"" 324 1.14086 0.77158199999999999 4.4007800000000001\n"" 325 1.109 0.38109599999999999 4.5774100000000004\n"" 326 0.99641999999999997 0.213864 4.9095700000000004\n"" 327 0.92616600000000004 0.34165800000000002 5.1422499999999998\n"" 328 1.01125 0.65693400000000002 5.1763500000000002\n"" 329 1.12432 0.99678599999999995 4.7075899999999997\n"" 330 1.08257 0.96081000000000005 4.9166299999999996\n"" 331 1.2109399999999999 0.98394599999999999 4.1745400000000004\n"" 332 1.1652400000000001 1.2398100000000001 4.6936499999999999\n"" 333 0.93262800000000001 1.74756 4.4064699999999997\n"" 334 1.0661799999999999 1.1785399999999999 5.0801600000000002\n"" 335 0.91383000000000003 0.75153599999999998 5.3447199999999997\n"" 336 0.71727600000000002 1.49926 5.1546200000000004\n"" 337 0.71021400000000001 0.83785799999999999 5.5150399999999999\n"" 338 0.47645999999999999 0.79783800000000005 5.69191\n"" 339 0.37451400000000001 0.219888 5.85928\n"" 340 0.76708200000000004 -0.21551400000000001 5.6824199999999996\n"" 341 0.86174399999999995 0.19323599999999999 5.31548\n"" 342 0.44932800000000001 -0.51103799999999999 5.8834600000000004\n"" 343 0.78110400000000002 -0.62793600000000005 5.6857199999999999\n"" 344 0.93720599999999998 -0.56791800000000003 5.3944400000000003\n"" 345 0.464196 -1.0271600000000001 5.5592699999999997\n"" 346 0.76633200000000001 -0.98837399999999997 5.2788599999999999\n"" 347 0.31602000000000002 -1.10771 5.0521099999999999\n"" 348 0.14086199999999999 -1.1078300000000001 5.33887\n"" 349 0.13575599999999999 -1.26352 4.9649999999999999\n"" 350 1.33853 1.27186 3.72296\n"" 351 1.5086599999999999 0.67840199999999995 3.9989599999999998\n"" 352 1.50851 0.53724000000000005 4.0433199999999996\n"" 353 1.28616 0.115548 4.6295700000000002\n"" 354 0.95399400000000001 0.00894 5.0122400000000003\n"" 355 1.0601799999999999 -0.35549399999999998 5.0953099999999996\n"" 356 0.89217599999999997 -0.78054599999999996 4.76159\n"" 357 0.64973999999999998 -0.99916799999999995 4.63253\n"" 358 0.29892000000000002 -1.2082900000000001 4.5867199999999997\n"" 359 0.42804599999999998 -1.2911699999999999 4.1832500000000001\n"" 360 0.438888 -1.28685 3.7410600000000001\n"" 361 0.84301199999999998 -1.01677 4.1961199999999996\n"" 362 0.980244 -0.942438 3.6684999999999999\n"" 363 1.1368 -0.83130000000000004 4.3822000000000001\n"" 364 1.48556 -0.49532399999999999 4.5576600000000003\n"" 365 1.3648100000000001 -0.73189199999999999 3.5411800000000002\n"" 366 1.70821 -0.039516000000000003 3.2120799999999998\n"" 367 1.65445 0.751722 2.6800600000000001\n"" 368 1.5999000000000001 1.1555599999999999 3.03626\n"" 369 1.8005199999999999 0.31972200000000001 3.77772\n"" 370 0.3327 -3.9836100000000001 2.2503899999999999\n"" 371 0.737124 -3.9848300000000001 2.8939400000000002\n"" 372 0.27911999999999998 -3.1894300000000002 2.3515100000000002\n"" 373 0.14894399999999999 -3.4106999999999998 1.6506400000000001\n"" 374 0.32312999999999997 -3.98359 1.9693400000000001\n"" 375 0.67697399999999996 -2.7212900000000002 1.83473\n"" 376 0.78759000000000001 -3.0636999999999999 0.48447600000000002\n"" 377 0.36704399999999998 -2.5842999999999998 -0.25625999999999999\n"" 378 2.0461100000000001 -3.1973199999999999 -1.2488999999999999\n"" 379 2.08623 -3.7412000000000001 -0.48683399999999999\n"" 380 1.42824 -3.66439 -0.22822200000000001\n"" 381 1.27058 -3.0856400000000002 -0.79246799999999995\n"" 382 0.72363 -3.6013099999999998 -1.12114\n"" 383 0.58191000000000004 -3.5068600000000001 -1.76014\n"" 384 0.76572600000000002 -3.4916499999999999 -2.6230199999999999\n"" 385 0.99541199999999996 -2.8645499999999999 -1.7487200000000001\n"" 386 0.46632000000000001 -2.5078499999999999 -1.32311\n"" 387 1.9253499999999999 -3.0381800000000001 -1.9252400000000001\n"" 388 1.4892799999999999 -2.7940999999999998 -1.4390499999999999\n"" 389 0.712584 -2.30003 -1.1226799999999999\n"" 390 0.71289599999999997 -2.5806399999999998 -0.739842\n"" 391 0.56478600000000001 -2.5167799999999998 -0.26866200000000001\n"" 392 1.64716 -1.5702400000000001 0.03066\n"" 393 1.55905 -1.6997500000000001 -0.019109999999999999\n"" 394 1.33717 -2.0425900000000001 -0.22925999999999999\n"" 395 1.2266699999999999 -3.9862799999999998 3.08012\n"" 396 1.55572 -3.9872800000000002 2.82769\n"" 397 1.1124099999999999 -2.8561200000000002 2.5303100000000001\n"" 398 1.6749799999999999 -3.9876200000000002 2.5039699999999998\n"" 399 1.6629400000000001 -3.16873 2.4012500000000001\n"" 400 1.0984100000000001 -3.0588700000000002 1.97997\n"" 401 1.6955899999999999 -2.5752600000000001 0.35545199999999999\n"" 402 1.5288999999999999 -3.98725 1.7441199999999999\n"" 403 1.62862 -3.4062399999999999 1.5838000000000001\n"" 404 2.3193700000000002 -3.7513299999999998 -1.30122\n"" 405 2.3225199999999999 -3.7852999999999999 -2.0764399999999998\n"" 406 2.2801300000000002 -3.57613 -1.9120699999999999\n"" 407 1.7476100000000001 -3.7140399999999998 -3.51424\n"" 408 2.0356800000000002 -3.42719 -2.7716799999999999\n"" 409 2.4002699999999999 -2.9386700000000001 -2.5358399999999999\n"" 410 2.4409000000000001 -1.88609 -2.2273800000000001\n"" 411 1.8035300000000001 -1.69031 -1.02329\n"" 412 1.7452000000000001 -1.6638200000000001 -0.37142999999999998\n"" 413 1.1264099999999999 -1.4492700000000001 3.0566200000000001\n"" 414 1.12819 -1.7254100000000001 2.5453999999999999\n"" 415 1.3651199999999999 -2.2395700000000001 1.75861\n"" 416 1.5991599999999999 -1.6418999999999999 0.23758199999999999\n"" 417 1.7495499999999999 -1.7500599999999999 0.66831600000000002\n"" 418 1.7514799999999999 -0.73644600000000005 2.5360999999999998\n"" 419 1.7854399999999999 -0.93671400000000005 2.2402099999999998\n"" 420 1.7196199999999999 -1.39639 0.16297200000000001\n"" 421 2.18798 -1.2083900000000001 1.2411000000000001\n"" 422 2.1231300000000002 -0.79444800000000004 0.89536800000000005\n"" 423 1.6932499999999999 -0.11829000000000001 1.8897600000000001\n"" 424 1.98712 -0.59559600000000001 0.55620599999999998\n"" 425 2.25278 -0.55871999999999999 -0.038802000000000003\n"" 426 2.2555000000000001 -0.60741599999999996 -0.92929200000000001\n"" 427 2.7998099999999999 -0.566496 -1.8340099999999999\n"" 428 2.7348300000000001 -0.71928599999999998 -2.7637900000000002\n"" 429 1.66479 -3.6254499999999998 -3.9112300000000002\n"" 430 1.56613 -3.3070599999999999 -3.3279999999999998\n"" 431 0.56176199999999998 1.5509599999999999 -5.5235300000000001\n"" 432 0.68548799999999999 1.86365 -4.7884200000000003\n"" 433 0.86539200000000005 1.2685999999999999 -5.0100100000000003\n"" 434 0.71949600000000002 1.0616399999999999 -5.70695\n"" 435 1.1043700000000001 0.611124 -5.5093199999999998\n"" 436 0.55458600000000002 1.65913 -4.4293899999999997\n"" 437 0.80102399999999996 1.3104199999999999 -4.5516100000000002\n"" 438 1.1699200000000001 0.58592999999999995 -4.87486\n"" 439 1.1132500000000001 0.066030000000000005 -5.2752100000000004\n"" 440 1.3818900000000001 -0.76470000000000005 -5.3052099999999998\n"" 441 1.5628299999999999 1.53034 -3.74627\n"" 442 2.1093999999999999 -0.253164 -3.98386\n"" 443 1.5224500000000001 1.9411400000000001 -2.6023000000000001\n"" 444 2.4696699999999998 0.793794 -2.6295799999999998\n"" 445 1.6230800000000001 2.1391800000000001 -1.7399\n"" 446 2.53288 0.97691399999999995 -1.6387799999999999\n"" 447 0.988344 1.4249400000000001 1.2534700000000001\n"" 448 1.52284 0.55740000000000001 1.44384\n"" 449 1.2216499999999999 1.7075800000000001 0.57733800000000002\n"" 450 1.44604 2.0585599999999999 -1.0283800000000001\n"" 451 2.13646 0.89572799999999997 -0.86065800000000003\n"" 452 2.0259399999999999 0.79195199999999999 0.39824399999999999\n"" 453 -0.42761063083709772 1.6952470543869633 2.5510779406671853\n""# Generated by tetgen -YY bunny.smesh \n"); } +static const char* getElements() { return( +"1374 4 0\n"" 0 395 372 399 371\n"" 1 96 46 93 44\n"" 2 135 140 137 163\n"" 3 318 326 354 313\n"" 4 133 127 128 126\n"" 5 76 83 55 218\n"" 6 193 188 198 176\n"" 7 450 443 451 1\n"" 8 437 442 438 441\n"" 9 160 336 320 144\n"" 10 79 50 51 75\n"" 11 408 378 387 273\n"" 12 94 38 47 68\n"" 13 323 308 322 311\n"" 14 339 135 163 341\n"" 15 152 135 153 145\n"" 16 333 166 160 147\n"" 17 348 346 347 342\n"" 18 446 426 451 444\n"" 19 46 92 94 93\n"" 20 208 21 26 207\n"" 21 38 360 48 413\n"" 22 229 80 243 245\n"" 23 241 229 227 242\n"" 24 34 50 35 51\n"" 25 9 33 35 34\n"" 26 103 122 121 206\n"" 27 257 260 259 440\n"" 28 142 318 163 144\n"" 29 446 443 444 451\n"" 30 272 251 252 274\n"" 31 193 199 176 198\n"" 32 165 149 147 166\n"" 33 447 3 8 449\n"" 34 29 208 209 30\n"" 35 300 285 286 299\n"" 36 100 104 119 105\n"" 37 39 44 40 41\n"" 38 315 318 313 316\n"" 39 422 417 421 419\n"" 40 382 273 264 383\n"" 41 145 143 150 146\n"" 42 406 268 405 404\n"" 43 427 411 426 428\n"" 44 323 290 308 311\n"" 45 232 18 230 227\n"" 46 243 79 80 240\n"" 47 391 412 390 389\n"" 48 360 423 107 362\n"" 49 389 71 393 392\n"" 50 142 162 163 145\n"" 51 245 247 261 80\n"" 52 376 373 375 92\n"" 53 324 352 325 362\n"" 54 119 104 106 105\n"" 55 165 149 166 151\n"" 56 428 389 411 442\n"" 57 366 351 331 352\n"" 58 166 318 316 163\n"" 59 368 281 280 350\n"" 60 315 168 313 166\n"" 61 417 422 423 419\n"" 62 279 203 205 453\n"" 63 80 243 245 226\n"" 64 416 41 420 45\n"" 65 319 330 317 335\n"" 66 15 442 225 224\n"" 67 116 131 117 129\n"" 68 335 318 337 319\n"" 69 188 197 193 198\n"" 70 326 314 325 313\n"" 71 313 315 314 325\n"" 72 451 3 449 450\n"" 73 451 449 452 450\n"" 74 299 286 300 301\n"" 75 450 1 3 2\n"" 76 107 103 120 149\n"" 77 76 82 81 79\n"" 78 81 83 218 214\n"" 79 14 10 2 11\n"" 80 22 436 437 23\n"" 81 318 144 316 163\n"" 82 420 426 425 412\n"" 83 450 14 11 445\n"" 84 262 254 429 274\n"" 85 443 442 441 444\n"" 86 356 353 364 363\n"" 87 102 122 206 101\n"" 88 315 168 325 313\n"" 89 281 331 280 350\n"" 90 107 155 120 104\n"" 91 443 426 444 451\n"" 92 123 118 354 113\n"" 93 84 220 86 83\n"" 94 268 406 405 269\n"" 95 287 293 289 286\n"" 96 17 16 443 13\n"" 97 315 168 166 325\n"" 98 283 296 297 284\n"" 99 333 144 336 160\n"" 100 450 13 1 2\n"" 101 414 423 418 419\n"" 102 331 352 324 362\n"" 103 144 315 333 316\n"" 104 21 442 16 15\n"" 105 45 72 91 69\n"" 106 437 208 21 433\n"" 107 288 310 290 306\n"" 108 213 217 214 31\n"" 109 335 327 328 341\n"" 110 109 67 48 111\n"" 111 316 314 315 312\n"" 112 45 60 91 44\n"" 113 128 118 115 116\n"" 114 423 45 38 448\n"" 115 155 362 166 325\n"" 116 130 136 132 133\n"" 117 92 72 89 91\n"" 118 145 143 142 150\n"" 119 153 140 163 142\n"" 120 317 313 312 319\n"" 121 347 118 126 354\n"" 122 148 165 147 143\n"" 123 170 157 171 173\n"" 124 78 50 74 240\n"" 125 381 273 385 378\n"" 126 337 330 335 317\n"" 127 267 273 379 268\n"" 128 80 247 261 250\n"" 129 80 225 261 245\n"" 130 80 442 261 225\n"" 131 211 24 212 20\n"" 132 398 395 399 371\n"" 133 390 389 377 391\n"" 134 308 292 290 291\n"" 135 176 191 177 199\n"" 136 318 166 313 163\n"" 137 23 16 436 17\n"" 138 354 353 325 326\n"" 139 423 362 366 279\n"" 140 415 400 375 403\n"" 141 217 239 216 213\n"" 142 377 89 88 90\n"" 143 10 12 13 9\n"" 144 155 325 113 112\n"" 145 151 164 165 150\n"" 146 113 118 128 123\n"" 147 95 97 99 96\n"" 148 449 3 8 5\n"" 149 61 99 97 64\n"" 150 223 83 222 82\n"" 151 37 38 6 39\n"" 152 0 7 6 37\n"" 153 385 430 247 250\n"" 154 108 109 110 107\n"" 155 415 401 417 403\n"" 156 102 121 122 101\n"" 157 120 107 149 156\n"" 158 104 100 119 120\n"" 159 3 4 2 5\n"" 160 207 21 224 437\n"" 161 270 273 408 430\n"" 162 80 247 226 245\n"" 163 80 228 81 243\n"" 164 43 107 48 38\n"" 165 354 340 344 341\n"" 166 312 316 313 317\n"" 167 435 275 277 439\n"" 168 27 30 29 28\n"" 169 52 76 31 240\n"" 170 338 339 163 318\n"" 171 47 43 42 48\n"" 172 61 96 59 58\n"" 173 428 389 442 261\n"" 174 194 171 192 174\n"" 175 318 339 341 338\n"" 176 417 422 416 423\n"" 177 123 124 125 128\n"" 178 113 108 115 155\n"" 179 300 285 299 298\n"" 180 320 160 189 333\n"" 181 443 35 1 13\n"" 182 96 46 44 61\n"" 183 316 314 313 315\n"" 184 119 107 155 106\n"" 185 357 325 356 361\n"" 186 224 15 21 20\n"" 187 319 336 337 317\n"" 188 306 287 307 302\n"" 189 143 141 140 144\n"" 190 366 423 279 367\n"" 191 74 73 88 89\n"" 192 447 7 8 3\n"" 193 449 8 447 5\n"" 194 436 21 22 437\n"" 195 92 72 91 45\n"" 196 153 140 142 135\n"" 197 206 121 103 149\n"" 198 35 69 389 71\n"" 199 165 168 167 166\n"" 200 12 1 13 9\n"" 201 361 112 113 325\n"" 202 195 175 193 194\n"" 203 292 304 322 321\n"" 204 337 336 144 338\n"" 205 399 372 400 371\n"" 206 332 336 334 333\n"" 207 111 68 67 48\n"" 208 389 391 393 72\n"" 209 196 179 188 195\n"" 210 104 119 155 120\n"" 211 168 166 325 155\n"" 212 112 108 113 155\n"" 213 449 425 451 452\n"" 214 220 214 83 221\n"" 215 261 246 245 225\n"" 216 93 44 46 92\n"" 217 80 255 226 247\n"" 218 384 262 247 430\n"" 219 336 144 319 337\n"" 220 144 315 316 166\n"" 221 332 336 333 316\n"" 222 175 191 194 192\n"" 223 362 353 325 363\n"" 224 110 113 115 114\n"" 225 400 370 374 402\n"" 226 319 337 335 317\n"" 227 430 262 247 248\n"" 228 324 362 315 331\n"" 229 80 228 235 81\n"" 230 347 342 126 348\n"" 231 295 283 296 297\n"" 232 306 304 305 308\n"" 233 356 353 325 354\n"" 234 21 23 437 433\n"" 235 195 174 194 178\n"" 236 192 175 177 173\n"" 237 302 287 303 286\n"" 238 208 211 26 209\n"" 239 118 128 115 113\n"" 240 351 366 369 352\n"" 241 342 344 340 343\n"" 242 118 347 123 354\n"" 243 354 168 163 313\n"" 244 356 325 363 361\n"" 245 282 321 294 304\n"" 246 268 379 267 404\n"" 247 296 305 284 283\n"" 248 290 304 308 291\n"" 249 316 318 313 319\n"" 250 143 160 147 161\n"" 251 149 201 122 147\n"" 252 38 448 45 6\n"" 253 92 415 417 94\n"" 254 225 224 261 440\n"" 255 198 185 184 186\n"" 256 7 205 447 8\n"" 257 368 351 350 367\n"" 258 74 13 12 35\n"" 259 190 147 161 158\n"" 260 270 429 262 407\n"" 261 3 4 450 2\n"" 262 15 443 442 16\n"" 263 193 188 195 196\n"" 264 342 347 340 344\n"" 265 391 393 45 416\n"" 266 92 415 94 375\n"" 267 61 60 91 58\n"" 268 60 72 69 91\n"" 269 289 283 305 291\n"" 270 96 44 93 92\n"" 271 324 362 325 315\n"" 272 13 2 14 10\n"" 273 62 63 61 64\n"" 274 144 166 160 315\n"" 275 417 423 416 94\n"" 276 449 4 450 3\n"" 277 450 13 443 1\n"" 278 352 364 365 369\n"" 279 7 448 205 6\n"" 280 225 440 261 263\n"" 281 116 155 119 118\n"" 282 2 4 450 11\n"" 283 416 377 92 89\n"" 284 376 403 415 375\n"" 285 417 376 415 92\n"" 286 416 377 89 391\n"" 287 249 262 246 256\n"" 288 336 317 316 330\n"" 289 47 43 48 38\n"" 290 354 168 313 113\n"" 291 115 168 118 113\n"" 292 34 50 51 33\n"" 293 166 169 167 165\n"" 294 319 316 317 313\n"" 295 318 144 337 319\n"" 296 354 325 313 326\n"" 297 30 436 433 431\n"" 298 289 283 291 284\n"" 299 58 91 96 59\n"" 300 185 182 183 197\n"" 301 224 438 276 437\n"" 302 15 442 80 225\n"" 303 111 110 112 109\n"" 304 52 76 240 51\n"" 305 208 26 30 29\n"" 306 7 449 3 447\n"" 307 296 294 283 295\n"" 308 306 291 289 305\n"" 309 338 140 141 144\n"" 310 331 352 351 324\n"" 311 322 281 333 320\n"" 312 83 81 76 82\n"" 313 384 262 274 255\n"" 314 60 45 91 69\n"" 315 15 20 19 16\n"" 316 197 188 193 196\n"" 317 80 229 225 245\n"" 318 18 233 227 232\n"" 319 344 345 343 342\n"" 320 417 414 94 415\n"" 321 443 16 441 442\n"" 322 177 199 187 176\n"" 323 149 206 121 453\n"" 324 350 279 331 280\n"" 325 181 188 196 179\n"" 326 102 121 101 103\n"" 327 347 357 354 356\n"" 328 338 327 318 337\n"" 329 337 330 334 335\n"" 330 319 336 317 316\n"" 331 193 175 188 176\n"" 332 164 143 162 165\n"" 333 120 104 100 103\n"" 334 376 416 92 417\n"" 335 113 325 155 168\n"" 336 416 376 92 391\n"" 337 420 45 41 393\n"" 338 249 262 248 246\n"" 339 147 189 161 160\n"" 340 18 231 224 233\n"" 341 71 45 70 41\n"" 342 126 341 135 339\n"" 343 21 23 22 437\n"" 344 148 165 143 151\n"" 345 337 327 318 335\n"" 346 354 318 313 163\n"" 347 115 118 155 116\n"" 348 341 340 338 339\n"" 349 166 168 313 163\n"" 350 166 318 313 315\n"" 351 48 68 67 47\n"" 352 150 162 145 152\n"" 353 140 339 137 163\n"" 354 199 185 187 176\n"" 355 333 144 316 336\n"" 356 338 327 337 341\n"" 357 389 70 72 393\n"" 358 331 366 350 351\n"" 359 94 45 92 44\n"" 360 9 33 12 35\n"" 361 126 139 137 138\n"" 362 321 295 282 294\n"" 363 135 140 136 137\n"" 364 153 162 163 152\n"" 365 325 362 363 361\n"" 366 80 235 226 81\n"" 367 74 377 89 88\n"" 368 13 14 450 443\n"" 369 157 172 158 171\n"" 370 450 443 14 445\n"" 371 155 107 120 156\n"" 372 135 339 163 137\n"" 373 365 325 352 362\n"" 374 153 140 135 163\n"" 375 448 206 205 6\n"" 376 137 141 139 339\n"" 377 103 107 120 104\n"" 378 448 425 447 452\n"" 379 165 162 168 163\n"" 380 76 83 79 87\n"" 381 420 45 393 416\n"" 382 334 329 330 336\n"" 383 89 45 92 416\n"" 384 181 195 179 196\n"" 385 420 448 41 416\n"" 386 438 277 435 275\n"" 387 400 399 402 403\n"" 388 304 296 283 305\n"" 389 170 158 190 161\n"" 390 387 386 388 250\n"" 391 54 218 217 53\n"" 392 311 304 308 322\n"" 393 149 281 201 189\n"" 394 211 24 209 212\n"" 395 166 333 149 147\n"" 396 426 424 420 425\n"" 397 394 376 401 416\n"" 398 147 159 122 158\n"" 399 202 203 201 453\n"" 400 280 203 279 453\n"" 401 135 126 339 137\n"" 402 449 4 3 5\n"" 403 14 2 450 11\n"" 404 126 125 127 347\n"" 405 423 413 38 414\n"" 406 185 198 188 176\n"" 407 144 163 142 162\n"" 408 201 122 204 453\n"" 409 447 425 451 449\n"" 410 290 289 306 291\n"" 411 35 69 71 49\n"" 412 207 224 211 231\n"" 413 135 154 163 118\n"" 414 126 118 341 354\n"" 415 191 175 194 193\n"" 416 436 16 437 17\n"" 417 420 422 416 421\n"" 418 135 142 153 145\n"" 419 15 443 16 13\n"" 420 440 275 259 224\n"" 421 416 421 422 417\n"" 422 442 275 440 224\n"" 423 347 340 354 126\n"" 424 254 256 253 274\n"" 425 34 50 33 35\n"" 426 176 191 175 177\n"" 427 433 278 434 277\n"" 428 175 191 192 177\n"" 429 101 206 102 204\n"" 430 132 135 136 130\n"" 431 49 35 50 36\n"" 432 353 356 325 363\n"" 433 435 277 433 434\n"" 434 224 275 276 438\n"" 435 212 230 18 19\n"" 436 143 150 148 151\n"" 437 235 228 243 234\n"" 438 29 22 26 30\n"" 439 125 347 349 123\n"" 440 237 234 235 236\n"" 441 144 336 319 316\n"" 442 165 316 166 144\n"" 443 142 318 338 163\n"" 444 137 141 140 139\n"" 445 447 279 205 448\n"" 446 106 116 108 155\n"" 447 217 238 239 215\n"" 448 16 17 443 441\n"" 449 407 262 270 430\n"" 450 88 74 389 77\n"" 451 78 79 80 81\n"" 452 126 138 134 342\n"" 453 165 150 143 151\n"" 454 409 430 387 250\n"" 455 128 118 116 131\n"" 456 339 126 340 342\n"" 457 173 192 171 170\n"" 458 400 376 403 373\n"" 459 15 18 212 224\n"" 460 37 49 36 35\n"" 461 81 82 83 214\n"" 462 173 157 171 172\n"" 463 220 214 219 83\n"" 464 114 113 128 123\n"" 465 366 423 367 418\n"" 466 379 273 378 406\n"" 467 30 436 23 433\n"" 468 23 432 28 436\n"" 469 147 144 160 143\n"" 470 79 243 31 240\n"" 471 33 74 50 240\n"" 472 342 348 345 126\n"" 473 94 416 417 92\n"" 474 416 377 391 92\n"" 475 147 158 149 157\n"" 476 273 274 384 430\n"" 477 203 281 201 453\n"" 478 243 235 245 226\n"" 479 18 229 227 225\n"" 480 45 72 69 70\n"" 481 189 149 147 201\n"" 482 175 195 193 188\n"" 483 362 107 155 166\n"" 484 185 199 198 176\n"" 485 331 166 333 149\n"" 486 31 76 81 79\n"" 487 323 290 310 308\n"" 488 43 107 104 48\n"" 489 436 16 21 437\n"" 490 368 279 350 280\n"" 491 424 416 423 448\n"" 492 150 142 164 143\n"" 493 258 248 246 249\n"" 494 381 383 385 273\n"" 495 73 49 72 74\n"" 496 117 106 119 116\n"" 497 74 377 88 389\n"" 498 408 273 387 384\n"" 499 191 170 173 190\n"" 500 199 177 200 191\n"" 501 13 80 74 12\n"" 502 130 135 128 131\n"" 503 92 90 89 377\n"" 504 84 219 83 86\n"" 505 408 378 273 406\n"" 506 386 384 80 385\n"" 507 392 426 389 420\n"" 508 80 79 243 81\n"" 509 158 177 173 190\n"" 510 377 72 89 391\n"" 511 394 376 416 391\n"" 512 442 224 440 261\n"" 513 130 131 129 132\n"" 514 95 63 61 59\n"" 515 252 274 253 272\n"" 516 273 274 272 384\n"" 517 225 263 246 257\n"" 518 76 52 31 53\n"" 519 243 79 31 81\n"" 520 448 420 424 416\n"" 521 347 358 349 123\n"" 522 138 137 126 133\n"" 523 368 279 367 350\n"" 524 38 360 413 423\n"" 525 165 168 166 163\n"" 526 207 211 26 208\n"" 527 54 217 32 228\n"" 528 125 347 348 349\n"" 529 118 347 128 123\n"" 530 423 94 45 416\n"" 531 250 389 428 261\n"" 532 119 116 118 117\n"" 533 358 113 347 357\n"" 534 168 164 165 169\n"" 535 242 235 243 234\n"" 536 354 318 341 327\n"" 537 226 247 255 245\n"" 538 377 72 389 74\n"" 539 168 354 163 118\n"" 540 163 316 166 165\n"" 541 145 163 142 153\n"" 542 262 80 247 255\n"" 543 281 304 292 321\n"" 544 12 1 9 35\n"" 545 392 426 420 412\n"" 546 51 79 76 240\n"" 547 274 270 273 272\n"" 548 270 274 273 430\n"" 549 329 331 332 324\n"" 550 325 313 168 113\n"" 551 306 304 308 290\n"" 552 71 35 49 41\n"" 553 348 346 342 345\n"" 554 270 262 274 430\n"" 555 353 363 365 364\n"" 556 29 22 30 27\n"" 557 447 425 424 451\n"" 558 53 31 217 54\n"" 559 194 171 175 192\n"" 560 29 25 209 210\n"" 561 123 358 349 113\n"" 562 80 385 384 247\n"" 563 204 202 201 453\n"" 564 259 225 440 224\n"" 565 128 347 125 123\n"" 566 111 68 48 413\n"" 567 48 68 47 414\n"" 568 415 68 414 94\n"" 569 437 208 207 21\n"" 570 424 1 3 451\n"" 571 447 452 449 448\n"" 572 389 390 377 88\n"" 573 158 170 190 173\n"" 574 169 165 168 167\n"" 575 155 154 119 118\n"" 576 115 168 155 118\n"" 577 354 168 113 118\n"" 578 147 201 161 189\n"" 579 115 168 113 155\n"" 580 168 166 155 167\n"" 581 259 225 257 440\n"" 582 263 247 261 246\n"" 583 281 279 201 453\n"" 584 128 135 136 126\n"" 585 275 260 439 440\n"" 586 66 63 65 64\n"" 587 277 438 276 275\n"" 588 163 339 341 318\n"" 589 325 314 324 315\n"" 590 338 327 341 318\n"" 591 319 327 328 335\n"" 592 391 45 89 416\n"" 593 203 281 280 202\n"" 594 362 423 206 279\n"" 595 239 237 213 238\n"" 596 362 353 365 325\n"" 597 80 235 243 226\n"" 598 80 228 243 235\n"" 599 15 21 20 16\n"" 600 31 214 81 53\n"" 601 227 244 233 225\n"" 602 442 21 224 15\n"" 603 284 293 298 285\n"" 604 233 18 227 225\n"" 605 18 233 224 225\n"" 606 205 203 204 453\n"" 607 163 154 168 118\n"" 608 208 21 433 26\n"" 609 443 389 442 444\n"" 610 27 23 30 28\n"" 611 54 218 56 217\n"" 612 391 412 389 393\n"" 613 9 13 10 1\n"" 614 61 44 96 91\n"" 615 316 314 312 313\n"" 616 416 376 401 417\n"" 617 116 108 155 115\n"" 618 106 107 155 108\n"" 619 442 389 411 426\n"" 620 164 142 162 143\n"" 621 321 294 322 295\n"" 622 144 165 143 147\n"" 623 357 325 313 354\n"" 624 389 35 41 426\n"" 625 448 7 205 447\n"" 626 227 244 229 241\n"" 627 206 38 103 102\n"" 628 206 448 205 279\n"" 629 10 4 2 11\n"" 630 246 256 245 255\n"" 631 37 49 35 41\n"" 632 128 127 124 125\n"" 633 126 138 133 134\n"" 634 312 318 319 313\n"" 635 81 235 226 213\n"" 636 213 228 235 234\n"" 637 228 81 243 31\n"" 638 81 228 235 213\n"" 639 317 336 337 330\n"" 640 330 336 337 334\n"" 641 316 330 317 329\n"" 642 319 330 335 328\n"" 643 231 18 232 233\n"" 644 18 231 232 230\n"" 645 17 437 436 441\n"" 646 287 307 302 303\n"" 647 287 306 307 288\n"" 648 303 288 287 307\n"" 649 323 320 333 311\n"" 650 393 420 416 392\n"" 651 79 51 76 75\n"" 652 336 329 316 332\n"" 653 213 236 234 237\n"" 654 76 31 81 53\n"" 655 45 72 391 89\n"" 656 31 76 79 240\n"" 657 395 372 397 399\n"" 658 393 45 41 70\n"" 659 45 416 94 92\n"" 660 211 21 224 207\n"" 661 376 417 415 401\n"" 662 262 254 274 256\n"" 663 320 304 292 311\n"" 664 1 10 9 2\n"" 665 162 165 168 164\n"" 666 385 247 80 250\n"" 667 371 400 370 372\n"" 668 384 247 385 430\n"" 669 128 130 131 129\n"" 670 443 13 442 80\n"" 671 284 293 289 305\n"" 672 448 206 6 423\n"" 673 360 107 109 362\n"" 674 112 360 359 111\n"" 675 287 305 306 289\n"" 676 362 325 112 361\n"" 677 362 166 325 315\n"" 678 437 17 16 441\n"" 679 438 277 276 433\n"" 680 200 189 190 201\n"" 681 416 422 424 423\n"" 682 320 292 281 189\n"" 683 110 108 113 112\n"" 684 108 110 113 115\n"" 685 144 318 316 319\n"" 686 250 386 389 80\n"" 687 166 318 315 316\n"" 688 63 62 59 58\n"" 689 319 327 335 318\n"" 690 337 327 335 341\n"" 691 1 450 3 451\n"" 692 239 237 236 213\n"" 693 21 442 437 16\n"" 694 450 443 445 451\n"" 695 14 13 450 2\n"" 696 39 44 42 40\n"" 697 363 357 356 361\n"" 698 350 366 367 351\n"" 699 331 366 362 279\n"" 700 368 366 369 351\n"" 701 47 43 38 42\n"" 702 140 339 163 338\n"" 703 289 285 293 284\n"" 704 339 141 338 140\n"" 705 137 141 339 140\n"" 706 234 216 213 32\n"" 707 273 408 430 384\n"" 708 273 270 408 269\n"" 709 84 220 83 85\n"" 710 158 170 157 161\n"" 711 255 262 274 256\n"" 712 304 282 283 294\n"" 713 83 218 219 87\n"" 714 377 72 74 89\n"" 715 206 205 204 453\n"" 716 446 443 451 445\n"" 717 304 292 322 320\n"" 718 155 362 112 107\n"" 719 292 283 304 282\n"" 720 443 1 426 451\n"" 721 149 362 166 107\n"" 722 272 271 274 270\n"" 723 306 287 289 288\n"" 724 366 331 350 279\n"" 725 331 366 352 362\n"" 726 61 95 96 97\n"" 727 224 442 275 438\n"" 728 273 387 384 385\n"" 729 262 271 429 270\n"" 730 185 182 197 184\n"" 731 153 162 145 163\n"" 732 74 443 35 426\n"" 733 41 389 426 420\n"" 734 40 47 46 44\n"" 735 262 246 247 248\n"" 736 1 37 3 0\n"" 737 433 432 431 436\n"" 738 23 432 436 30\n"" 739 67 360 413 111\n"" 740 109 360 112 111\n"" 741 361 360 112 362\n"" 742 246 258 249 257\n"" 743 87 218 219 55\n"" 744 151 149 166 156\n"" 745 165 149 151 148\n"" 746 149 165 147 148\n"" 747 155 154 118 168\n"" 748 217 214 218 215\n"" 749 31 214 53 217\n"" 750 291 304 283 305\n"" 751 23 16 22 436\n"" 752 143 162 165 144\n"" 753 103 102 100 101\n"" 754 195 175 179 188\n"" 755 182 196 197 180\n"" 756 400 376 375 403\n"" 757 149 281 189 331\n"" 758 146 143 150 148\n"" 759 150 146 152 145\n"" 760 168 162 164 169\n"" 761 262 384 274 430\n"" 762 54 218 53 56\n"" 763 125 127 347 128\n"" 764 304 306 291 290\n"" 765 262 80 384 247\n"" 766 153 162 152 145\n"" 767 150 162 152 164\n"" 768 168 162 169 163\n"" 769 262 80 255 384\n"" 770 38 68 414 47\n"" 771 423 206 38 107\n"" 772 46 68 94 47\n"" 773 385 430 250 387\n"" 774 413 68 48 414\n"" 775 46 68 93 94\n"" 776 41 416 448 45\n"" 777 111 68 413 67\n"" 778 77 88 74 73\n"" 779 393 41 420 392\n"" 780 274 256 253 255\n"" 781 26 23 433 30\n"" 782 218 217 53 214\n"" 783 231 212 18 224\n"" 784 446 426 444 427\n"" 785 113 114 128 115\n"" 786 128 114 123 124\n"" 787 285 289 293 286\n"" 788 301 285 299 286\n"" 789 300 285 298 286\n"" 790 297 285 298 299\n"" 791 26 23 30 22\n"" 792 44 38 94 45\n"" 793 187 158 159 177\n"" 794 218 76 81 53\n"" 795 162 143 142 144\n"" 796 397 373 400 372\n"" 797 164 142 145 162\n"" 798 128 135 126 118\n"" 799 289 283 284 305\n"" 800 282 189 281 292\n"" 801 200 186 187 199\n"" 802 21 24 211 20\n"" 803 11 13 14 10\n"" 804 2 13 1 10\n"" 805 72 377 389 391\n"" 806 74 72 73 89\n"" 807 92 72 45 89\n"" 808 413 366 418 362\n"" 809 281 304 282 292\n"" 810 429 251 274 254\n"" 811 438 439 275 435\n"" 812 37 424 1 3\n"" 813 202 189 201 281\n"" 814 333 189 320 281\n"" 815 94 38 68 423\n"" 816 389 261 250 80\n"" 817 242 241 235 234\n"" 818 364 366 365 369\n"" 819 302 305 306 287\n"" 820 362 366 352 365\n"" 821 350 366 279 367\n"" 822 368 366 351 367\n"" 823 191 176 175 193\n"" 824 173 191 177 192\n"" 825 103 121 101 100\n"" 826 176 191 199 193\n"" 827 191 177 200 190\n"" 828 275 442 439 438\n"" 829 275 442 440 439\n"" 830 224 442 225 261\n"" 831 442 224 437 438\n"" 832 258 246 263 257\n"" 833 386 384 385 383\n"" 834 149 333 331 189\n"" 835 318 326 327 354\n"" 836 207 437 224 276\n"" 837 56 76 218 53\n"" 838 350 333 322 281\n"" 839 37 38 45 6\n"" 840 232 244 227 241\n"" 841 423 206 6 38\n"" 842 411 386 250 410\n"" 843 224 229 18 225\n"" 844 6 423 38 448\n"" 845 218 57 219 55\n"" 846 68 423 38 414\n"" 847 377 376 391 92\n"" 848 415 376 375 92\n"" 849 103 121 100 120\n"" 850 101 121 122 100\n"" 851 102 121 103 122\n"" 852 7 206 6 205\n"" 853 38 206 6 102\n"" 854 107 38 103 206\n"" 855 448 206 423 279\n"" 856 298 305 284 296\n"" 857 30 432 436 431\n"" 858 23 432 30 28\n"" 859 119 107 104 155\n"" 860 142 337 318 144\n"" 861 107 103 43 104\n"" 862 426 424 425 451\n"" 863 107 156 155 166\n"" 864 119 107 106 104\n"" 865 156 107 149 166\n"" 866 103 107 43 38\n"" 867 103 122 206 102\n"" 868 448 41 45 37\n"" 869 423 416 45 448\n"" 870 81 228 213 31\n"" 871 217 239 213 215\n"" 872 403 376 415 401\n"" 873 443 74 80 389\n"" 874 135 163 341 118\n"" 875 133 126 136 137\n"" 876 228 216 213 217\n"" 877 447 451 7 449\n"" 878 71 41 393 392\n"" 879 282 321 304 281\n"" 880 95 63 99 61\n"" 881 185 197 183 188\n"" 882 433 23 437 436\n"" 883 212 24 210 19\n"" 884 257 260 440 258\n"" 885 184 197 185 198\n"" 886 175 178 195 179\n"" 887 61 60 58 44\n"" 888 362 363 361 365\n"" 889 447 451 424 7\n"" 890 132 135 130 131\n"" 891 61 91 96 58\n"" 892 385 430 387 384\n"" 893 127 133 130 126\n"" 894 80 274 226 255\n"" 895 80 274 255 384\n"" 896 219 87 86 84\n"" 897 275 259 224 276\n"" 898 18 229 15 227\n"" 899 320 304 311 322\n"" 900 23 21 26 433\n"" 901 109 38 48 107\n"" 902 342 139 126 138\n"" 903 21 23 26 22\n"" 904 426 428 444 427\n"" 905 331 166 362 315\n"" 906 122 206 204 453\n"" 907 12 1 35 13\n"" 908 189 331 281 333\n"" 909 35 9 34 1\n"" 910 426 412 389 411\n"" 911 287 305 289 293\n"" 912 320 160 333 336\n"" 913 0 35 37 36\n"" 914 262 255 247 256\n"" 915 353 352 325 324\n"" 916 336 329 330 316\n"" 917 275 260 440 259\n"" 918 16 442 437 441\n"" 919 380 378 273 381\n"" 920 7 424 447 448\n"" 921 400 376 373 375\n"" 922 222 223 214 83\n"" 923 30 22 23 27\n"" 924 262 271 274 429\n"" 925 45 44 37 41\n"" 926 380 265 382 273\n"" 927 149 333 189 147\n"" 928 242 245 229 243\n"" 929 131 135 128 118\n"" 930 245 256 247 255\n"" 931 391 412 393 394\n"" 932 99 61 97 95\n"" 933 281 203 280 453\n"" 934 350 333 331 322\n"" 935 41 71 393 70\n"" 936 398 400 399 402\n"" 937 323 309 308 310\n"" 938 37 3 0 7\n"" 939 72 393 45 391\n"" 940 408 270 430 407\n"" 941 40 47 44 42\n"" 942 298 305 293 284\n"" 943 250 385 386 80\n"" 944 266 379 273 380\n"" 945 191 170 192 173\n"" 946 364 354 356 355\n"" 947 200 186 159 187\n"" 948 159 147 190 158\n"" 949 229 244 225 245\n"" 950 427 250 411 428\n"" 951 342 347 126 340\n"" 952 13 80 12 15\n"" 953 342 346 347 344\n"" 954 268 273 379 406\n"" 955 352 365 366 369\n"" 956 78 50 240 51\n"" 957 322 321 304 294\n"" 958 183 180 196 182\n"" 959 266 379 267 273\n"" 960 58 59 60 91\n"" 961 405 273 269 406\n"" 962 84 220 85 86\n"" 963 81 82 214 223\n"" 964 21 24 26 211\n"" 965 87 219 86 57\n"" 966 442 411 428 426\n"" 967 35 443 1 426\n"" 968 47 44 94 46\n"" 969 357 325 113 313\n"" 970 313 357 354 113\n"" 971 31 217 228 213\n"" 972 99 61 66 64\n"" 973 144 166 147 160\n"" 974 298 284 285 297\n"" 975 398 400 371 399\n"" 976 51 78 50 79\n"" 977 298 284 297 296\n"" 978 7 451 3 449\n"" 979 281 279 280 331\n"" 980 158 177 190 159\n"" 981 117 106 105 119\n"" 982 278 276 277 433\n"" 983 200 122 201 177\n"" 984 72 35 389 74\n"" 985 54 228 31 217\n"" 986 379 406 378 404\n"" 987 347 127 126 128\n"" 988 109 362 112 360\n"" 989 126 339 340 341\n"" 990 142 338 140 163\n"" 991 38 44 47 42\n"" 992 150 142 145 164\n"" 993 426 424 451 420\n"" 994 431 208 433 30\n"" 995 437 207 433 276\n"" 996 135 154 153 163\n"" 997 163 341 354 318\n"" 998 443 13 74 35\n"" 999 143 142 144 140\n"" 1000 320 322 323 333\n"" 1001 122 147 158 149\n"" 1002 112 359 361 113\n"" 1003 359 112 361 360\n"" 1004 149 121 201 453\n"" 1005 361 358 113 359\n"" 1006 361 113 357 325\n"" 1007 113 359 358 112\n"" 1008 409 388 410 250\n"" 1009 71 69 389 70\n"" 1010 430 409 387 408\n"" 1011 32 217 216 228\n"" 1012 400 374 372 373\n"" 1013 419 422 423 421\n"" 1014 51 78 79 240\n"" 1015 387 386 250 385\n"" 1016 48 360 109 111\n"" 1017 438 277 433 435\n"" 1018 316 331 329 315\n"" 1019 74 50 49 35\n"" 1020 302 305 287 293\n"" 1021 287 293 286 302\n"" 1022 258 440 257 263\n"" 1023 188 183 181 196\n"" 1024 1 426 41 35\n"" 1025 236 216 213 234\n"" 1026 292 283 291 304\n"" 1027 381 383 273 382\n"" 1028 50 15 33 35\n"" 1029 79 240 78 80\n"" 1030 177 122 201 190\n"" 1031 307 308 309 310\n"" 1032 229 240 33 243\n"" 1033 200 187 177 199\n"" 1034 31 214 213 81\n"" 1035 128 133 126 136\n"" 1036 37 424 448 41\n"" 1037 263 247 246 248\n"" 1038 444 389 442 426\n"" 1039 423 417 414 94\n"" 1040 177 190 191 173\n"" 1041 417 419 415 421\n"" 1042 300 293 302 286\n"" 1043 442 13 15 80\n"" 1044 121 103 149 120\n"" 1045 136 126 135 137\n"" 1046 201 122 121 149\n"" 1047 331 316 333 315\n"" 1048 18 19 15 212\n"" 1049 38 45 423 94\n"" 1050 113 347 354 123\n"" 1051 273 405 269 408\n"" 1052 26 208 30 433\n"" 1053 431 208 278 433\n"" 1054 429 251 271 274\n"" 1055 109 38 360 48\n"" 1056 400 398 371 370\n"" 1057 174 173 175 171\n"" 1058 149 362 107 206\n"" 1059 245 242 229 244\n"" 1060 417 423 414 419\n"" 1061 185 199 186 198\n"" 1062 158 170 173 157\n"" 1063 177 122 190 159\n"" 1064 308 292 311 290\n"" 1065 380 378 379 273\n"" 1066 218 81 214 53\n"" 1067 232 244 233 227\n"" 1068 72 49 35 74\n"" 1069 235 245 226 244\n"" 1070 234 243 242 228\n"" 1071 316 331 332 329\n"" 1072 451 41 424 1\n"" 1073 362 353 363 365\n"" 1074 224 20 21 211\n"" 1075 258 248 263 246\n"" 1076 393 389 392 412\n"" 1077 212 15 224 20\n"" 1078 342 346 344 345\n"" 1079 229 74 240 80\n"" 1080 302 301 300 286\n"" 1081 203 202 204 453\n"" 1082 216 234 236 32\n"" 1083 386 388 410 411\n"" 1084 144 163 165 316\n"" 1085 347 344 346 356\n"" 1086 21 442 224 437\n"" 1087 190 122 201 147\n"" 1088 6 424 7 448\n"" 1089 269 270 408 407\n"" 1090 126 125 347 348\n"" 1091 37 44 45 38\n"" 1092 393 72 45 70\n"" 1093 413 423 418 414\n"" 1094 31 32 54 53\n"" 1095 29 22 27 26\n"" 1096 403 376 401 402\n"" 1097 83 220 221 85\n"" 1098 433 207 278 276\n"" 1099 218 57 55 56\n"" 1100 155 116 119 106\n"" 1101 173 175 171 192\n"" 1102 244 225 245 233\n"" 1103 158 173 172 157\n"" 1104 281 203 201 202\n"" 1105 344 354 356 347\n"" 1106 315 144 333 160\n"" 1107 392 426 412 389\n"" 1108 87 83 79 84\n"" 1109 347 358 357 349\n"" 1110 342 139 339 126\n"" 1111 126 341 340 354\n"" 1112 37 424 3 7\n"" 1113 210 29 25 26\n"" 1114 261 389 442 80\n"" 1115 107 112 155 108\n"" 1116 389 250 428 411\n"" 1117 80 12 15 74\n"" 1118 380 265 273 266\n"" 1119 190 122 147 159\n"" 1120 142 338 144 140\n"" 1121 109 362 107 112\n"" 1122 362 423 366 418\n"" 1123 97 66 98 64\n"" 1124 300 293 286 298\n"" 1125 130 136 133 128\n"" 1126 389 77 80 386\n"" 1127 142 337 338 318\n"" 1128 56 76 55 218\n"" 1129 214 82 83 223\n"" 1130 246 261 263 225\n"" 1131 35 12 15 33\n"" 1132 420 1 451 426\n"" 1133 63 99 61 66\n"" 1134 96 44 92 91\n"" 1135 219 214 218 83\n"" 1136 323 308 309 322\n"" 1137 224 229 225 15\n"" 1138 38 413 48 414\n"" 1139 281 149 279 331\n"" 1140 183 188 197 196\n"" 1141 180 195 181 196\n"" 1142 50 15 35 74\n"" 1143 113 347 357 354\n"" 1144 331 166 315 333\n"" 1145 19 15 212 20\n"" 1146 69 389 70 72\n"" 1147 216 236 213 239\n"" 1148 6 424 448 37\n"" 1149 74 229 33 15\n"" 1150 185 199 187 186\n"" 1151 71 389 41 392\n"" 1152 195 174 175 194\n"" 1153 398 400 402 370\n"" 1154 282 283 294 295\n"" 1155 244 227 229 225\n"" 1156 308 310 306 290\n"" 1157 288 310 306 307\n"" 1158 307 308 310 306\n"" 1159 251 274 254 252\n"" 1160 55 219 87 57\n"" 1161 64 63 65 62\n"" 1162 15 13 16 12\n"" 1163 190 201 189 161\n"" 1164 316 331 333 332\n"" 1165 329 331 324 315\n"" 1166 364 354 353 356\n"" 1167 166 144 147 165\n"" 1168 334 329 336 332\n"" 1169 420 422 424 416\n"" 1170 350 333 281 331\n"" 1171 322 292 321 281\n"" 1172 209 24 210 212\n"" 1173 424 37 1 41\n"" 1174 269 407 408 405\n"" 1175 429 430 407 408\n"" 1176 15 443 13 442\n"" 1177 214 221 222 83\n"" 1178 13 17 16 14\n"" 1179 333 166 315 160\n"" 1180 224 20 211 212\n"" 1181 122 201 121 453\n"" 1182 246 247 245 256\n"" 1183 391 393 416 394\n"" 1184 37 44 38 39\n"" 1185 344 354 355 356\n"" 1186 189 147 333 160\n"" 1187 437 208 433 207\n"" 1188 181 195 178 179\n"" 1189 403 376 402 373\n"" 1190 183 180 181 196\n"" 1191 433 276 438 437\n"" 1192 380 273 382 381\n"" 1193 209 24 26 210\n"" 1194 379 406 404 268\n"" 1195 7 451 424 3\n"" 1196 400 402 373 403\n"" 1197 21 207 211 26\n"" 1198 451 41 1 420\n"" 1199 201 149 279 281\n"" 1200 347 344 354 340\n"" 1201 419 417 415 414\n"" 1202 344 345 346 343\n"" 1203 79 83 76 82\n"" 1204 128 133 130 127\n"" 1205 6 424 37 7\n"" 1206 190 147 201 161\n"" 1207 87 218 55 83\n"" 1208 39 44 41 37\n"" 1209 245 242 235 243\n"" 1210 389 41 392 420\n"" 1211 24 212 20 19\n"" 1212 451 41 420 424\n"" 1213 78 75 50 79\n"" 1214 440 257 263 225\n"" 1215 81 83 76 218\n"" 1216 385 378 387 381\n"" 1217 430 387 384 408\n"" 1218 329 315 324 316\n"" 1219 281 280 279 453\n"" 1220 279 205 206 453\n"" 1221 253 254 274 252\n"" 1222 325 357 356 354\n"" 1223 443 17 13 14\n"" 1224 322 292 281 320\n"" 1225 399 372 397 400\n"" 1226 56 76 53 55\n"" 1227 212 231 18 230\n"" 1228 24 26 211 209\n"" 1229 420 1 426 41\n"" 1230 182 196 183 197\n"" 1231 229 74 80 15\n"" 1232 118 347 126 128\n"" 1233 180 195 178 181\n"" 1234 361 358 357 113\n"" 1235 239 213 215 238\n"" 1236 224 229 15 18\n"" 1237 423 68 94 414\n"" 1238 6 45 37 448\n"" 1239 48 360 111 413\n"" 1240 302 301 286 303\n"" 1241 35 41 1 37\n"" 1242 431 278 434 433\n"" 1243 145 164 162 150\n"" 1244 174 173 171 172\n"" 1245 423 279 367 448\n"" 1246 362 423 107 206\n"" 1247 272 271 251 274\n"" 1248 273 385 378 387\n"" 1249 200 122 177 159\n"" 1250 452 425 447 449\n"" 1251 210 29 26 209\n"" 1252 130 135 136 128\n"" 1253 234 213 237 235\n"" 1254 216 54 217 32\n"" 1255 402 373 376 374\n"" 1256 164 143 165 150\n"" 1257 427 250 410 411\n"" 1258 386 388 250 410\n"" 1259 96 61 59 95\n"" 1260 159 200 187 177\n"" 1261 389 443 442 80\n"" 1262 398 395 396 399\n"" 1263 87 83 55 76\n"" 1264 389 77 74 80\n"" 1265 229 15 80 225\n"" 1266 207 433 278 208\n"" 1267 96 59 91 95\n"" 1268 341 126 135 118\n"" 1269 62 61 59 58\n"" 1270 206 149 279 453\n"" 1271 400 370 372 374\n"" 1272 389 35 426 74\n"" 1273 360 423 362 413\n"" 1274 54 228 32 31\n"" 1275 109 38 107 360\n"" 1276 87 83 84 219\n"" 1277 72 35 69 389\n"" 1278 246 262 247 256\n"" 1279 352 364 353 365\n"" 1280 268 273 406 269\n"" 1281 443 74 13 80\n"" 1282 242 244 241 229\n"" 1283 149 279 362 206\n"" 1284 99 64 66 97\n"" 1285 376 373 92 374\n"" 1286 26 29 25 27\n"" 1287 32 213 228 216\n"" 1288 118 163 341 354\n"" 1289 161 158 147 157\n"" 1290 61 60 44 91\n"" 1291 292 308 304 291\n"" 1292 163 144 165 162\n"" 1293 407 262 430 429\n"" 1294 63 62 61 59\n"" 1295 153 163 154 168\n"" 1296 350 281 322 321\n"" 1297 262 271 270 274\n"" 1298 442 426 428 444\n"" 1299 38 44 42 39\n"" 1300 80 240 229 243\n"" 1301 194 171 174 175\n"" 1302 155 362 325 112\n"" 1303 306 304 291 305\n"" 1304 77 78 74 80\n"" 1305 80 74 240 78\n"" 1306 38 44 94 47\n"" 1307 273 405 408 406\n"" 1308 293 298 285 286\n"" 1309 88 389 390 77\n"" 1310 311 304 292 308\n"" 1311 99 66 98 97\n"" 1312 26 210 24 25\n"" 1313 259 224 276 207\n"" 1314 61 62 64 58\n"" 1315 244 242 235 245\n"" 1316 244 241 235 242\n"" 1317 63 61 64 66\n"" 1318 149 201 279 453\n"" 1319 206 122 121 453\n"" 1320 413 366 362 365\n"" 1321 409 388 250 387\n"" 1322 423 362 413 418\n"" 1323 38 414 48 47\n"" 1324 38 360 423 107\n"" 1325 290 289 288 306\n"" 1326 333 322 323 331\n"" 1327 389 443 74 426\n"" 1328 35 71 389 41\n"" 1329 279 149 362 331\n"" 1330 74 12 15 35\n"" 1331 424 423 422 448\n"" 1332 190 201 177 200\n"" 1333 365 325 353 352\n"" 1334 385 383 384 273\n"" 1335 331 322 321 350\n"" 1336 71 70 389 393\n"" 1337 126 139 339 137\n"" 1338 44 45 92 91\n"" 1339 72 49 69 35\n"" 1340 175 178 174 195\n"" 1341 247 246 245 261\n"" 1342 41 424 448 420\n"" 1343 46 92 44 94\n"" 1344 402 400 373 374\n"" 1345 198 197 185 188\n"" 1346 304 296 294 283\n"" 1347 116 131 129 128\n"" 1348 50 15 74 33\n"" 1349 110 108 112 109\n"" 1350 448 425 424 447\n"" 1351 166 331 362 149\n"" 1352 206 149 103 107\n"" 1353 209 26 208 29\n"" 1354 211 231 224 212\n"" 1355 33 50 51 240\n"" 1356 32 213 234 228\n"" 1357 444 389 426 443\n"" 1358 107 112 108 109\n"" 1359 217 213 214 215\n"" 1360 16 22 436 21\n"" 1361 142 337 144 338\n"" 1362 323 311 322 320\n"" 1363 411 386 389 250\n"" 1364 265 273 264 382\n"" 1365 211 230 231 212\n"" 1366 295 296 294 297\n"" 1367 0 35 1 37\n"" 1368 229 74 33 240\n"" 1369 131 118 116 117\n"" 1370 122 204 101 201\n"" 1371 206 122 204 101\n"" 1372 83 220 86 219\n"" 1373 113 358 347 123\n""# Generated by tetgen -YY bunny.smesh \n"); } diff --git a/Demos/SoftDemo/cube.inl b/Demos/SoftDemo/cube.inl new file mode 100755 index 0000000..7015a23 --- /dev/null +++ b/Demos/SoftDemo/cube.inl @@ -0,0 +1,4 @@ +static const char* getNodes() { return( +"400 3 0 0\n"" 0 1 1 -1\n"" 1 1 -1 -1\n"" 2 -1 -1 -1\n"" 3 1 1 1\n"" 4 -1 -1 1\n"" 5 -1 1 -1\n"" 6 1 -1 1\n"" 7 -1 1 1\n"" 8 -1 -1 -0.000116\n"" 9 0.00039500000000000006 -1 1\n"" 10 1 -1 -0.00065799999999999995\n"" 11 1 0.00061700000000000004 -1\n"" 12 0.00098999999999999999 1 -1\n"" 13 -1 1 0.00045400000000000008\n"" 14 0.00052800000000008396 1 1\n"" 15 1 1 -0.00038699999999991519\n"" 16 -1 -5.9999999999504894e-006 1\n"" 17 -1 0.00021000000000004349 -1\n"" 18 1 0.00067400000000006344 1\n"" 19 1.0863393114549872e-007 3.0682525964387253e-008 1\n"" 20 0.00097299999999989062 -1 -1\n"" 21 -1.4065544284846965e-008 1 5.0429866114086973e-008\n"" 22 1 -7.0792689266241382e-008 -4.4728299621228391e-008\n"" 23 8.4069120565846353e-008 3.8392827594879719e-007 -1\n"" 24 1 0.49980668112692161 -0.4996917965899465\n"" 25 1 0.50006700000000004 -1\n"" 26 1 1 -0.50034809999999996\n"" 27 1 1 0.50025040000000009\n"" 28 0.50020930000000008 1 1\n"" 29 -1 0.50010129999999997 1\n"" 30 -0.49958379999999991 1 1\n"" 31 -1 9.2038384777827427e-008 -1.100605984127867e-008\n"" 32 -0.5001201999999999 -1 1\n"" 33 1.0486788869007099e-007 -1 -3.3620911388254626e-008\n"" 34 -1 -1 0.50008699999999995\n"" 35 1 -0.50010220000000005 -1\n"" 36 1 -1 -0.49985400000000002\n"" 37 1 -0.4996526 1\n"" 38 1 -1 0.49990490000000004\n"" 39 -0.49930649999999999 1 -1\n"" 40 -1 1 -0.50002420000000003\n"" 41 1 -0.24974260000000004 -0.50015432157969908\n"" 42 0.50015422769290296 -0.24974260000000001 -1\n"" 43 0.50009680402228707 1 0.24993170000000009\n"" 44 1 0.50009675187018254 0.24993170000000009\n"" 45 0.24987467313200107 0.24987468273492527 -0.24987454967853764\n"" 46 0.50006970000000006 1 -1\n"" 47 -1 1 0.50062509999999982\n"" 48 -0.24952789999999991 1 0.50013191885453001\n"" 49 -0.24952789999999991 0.50013187836130635 1\n"" 50 -1 -0.50000239999999996 -1\n"" 51 -0.49917350000000005 -1 -1\n"" 52 -1 -0.37500110896930483 0.49999770999384097\n"" 53 -0.49999768418870116 -0.37500109958532857 1\n"" 54 0.50016842960649455 -0.24948929999999997 1\n"" 55 1 -0.24948929999999997 0.50016837821653382\n"" 56 -1 0.50011355427218929 -0.24978510000000004\n"" 57 -0.50011349993113807 1 -0.24978510000000009\n"" 58 0.49983560886453382 -1 -0.25025600000000003\n"" 59 1 -0.24959280000000006 -1\n"" 60 0.46861653427920624 0.31279234072878337 -1\n"" 61 0.46874721181012263 1 -0.31263609558485356\n"" 62 1 1 0.24986720000000007\n"" 63 1 0.50004500000000007 1\n"" 64 0.41666006216462159 0.41668749191836219 1\n"" 65 1 0.62492318088559184 0.62497446433589154\n"" 66 0.62493687874554793 1 0.62494713479954256\n"" 67 -0.32510780807963724 -0.32510780489834346 -0.32510793388507692\n"" 68 1 0.12495484505171366 -0.3748231366627352\n"" 69 -0.24915825000000003 0.50024732783000192 -1\n"" 70 1 0.74957571448653726 -0.74971600694021778\n"" 71 0.64874656072370729 1 -0.64882932411306993\n"" 72 0.6488668035834122 0.64886599996407779 -1\n"" 73 -1 0.41673079803079871 0.41664307505523179\n"" 74 -0.62468209179782908 1 0.62494186195929313\n"" 75 -0.62476903429567798 0.62489835940819183 1\n"" 76 -1 0.75020764999999989 1\n"" 77 0.12520010648567331 0.45856412436943739 0.37477910185628149\n"" 78 -0.24942439999999994 1 1\n"" 79 -0.37474797737976173 1 0.74996984889996166\n"" 80 -0.3748348177892612 0.74992638728967431 1\n"" 81 -1 -1 -0.49994339999999993\n"" 82 -0.50002894420427402 -1 0.24998549999999997\n"" 83 -1 -0.50045000000000006 1\n"" 84 -0.015617775048046156 -0.5000062299955631 1\n"" 85 -0.062520154989433377 -1 0.50002475010607028\n"" 86 0.50024029999999997 -1 1\n"" 87 1 -0.24929619999999997 1\n"" 88 0.37505270907528421 -0.3750526949043349 0.12522791934472338\n"" 89 -1 0.5001348000000001 -1\n"" 90 -1 1 -0.24999450000000001\n"" 91 1 -0.62477132796083668 -0.25025600000000003\n"" 92 0.50052129999999995 -1 -1\n"" 93 1 0.018238422269637886 -0.6785517711937521\n"" 94 0.750039598406532 -0.12448790000000004 -1\n"" 95 0.32367160517680327 0.022514689090561368 -0.65701963759824777\n"" 96 0.32369468988306127 0.65698780035674154 -0.022395524628340657\n"" 97 1 1 -0.25020424999999996\n"" 98 1 0.62501462613012171 -0.12492844204372336\n"" 99 0.16205966081319645 0.60689608104137205 -1\n"" 100 0.23307615322925276 1 -0.65509826790501591\n"" 101 0.6349049175761754 0.105723024682608 1\n"" 102 1 0.18290638148392097 0.59627500837254621\n"" 103 0.67708420758319754 0.67702605426027662 1\n"" 104 1 0.7498625000000001 1\n"" 105 0.75029925000000008 1 1\n"" 106 0.75006454389022692 1 0.37500606926950353\n"" 107 1 0.7500645207487896 0.37502882687227923\n"" 108 -0.39273716375981493 0.28664398202145958 -0.051638660454459806\n"" 109 -0.41671246738153483 -0.41657507574696978 -1\n"" 110 -0.24910025000000008 -1 -0.50024283860374685\n"" 111 -1 -0.50000177258228129 0.01562108247952367\n"" 112 -1 0.062713405747402015 -0.49998686350971472\n"" 113 -0.21672667787876426 1 -0.60296047487967241\n"" 114 1 0.7499052299192317 -0.37495181123207261\n"" 115 0.74540338978064358 1 -0.37527617499999999\n"" 116 0.52159008257288741 0.55923294709068649 -0.50062662770660094\n"" 117 0.75009235000000007 1 -1\n"" 118 -0.52928249862025711 0.10679011696853863 1\n"" 119 -1 0.034077217919757319 0.58381620432891879\n"" 120 -1 0.7383278941763165 0.25053954999999994\n"" 121 -0.70891631291249579 1 0.25053954999999989\n"" 122 -0.46050965421976553 0.49218708190674731 0.49218708126315491\n"" 123 -1 0.68039176952095026 0.65291562053589947\n"" 124 0.10567541850782136 0.6349221513724419 1\n"" 125 0.18288602711749127 1 0.59629803533945958\n"" 126 0.54298856425431818 0.54298737875163716 0.56762073808494473\n"" 127 -0.67702799351191578 -0.67732215502802495 -1\n"" 128 -0.74942264999999997 -1 -1\n"" 129 -1 -1 -0.74980449999999998\n"" 130 -1 -0.49218854513728494 -0.49218946358719012\n"" 131 -0.42414945787750447 -1 0.62500198796368489\n"" 132 -0.34611026252144428 -0.35284219355707647 0.34611025416343177\n"" 133 -1 -0.25018009999999996 1\n"" 134 1 -0.62478846817134759 0.62485153607962096\n"" 135 0.46873640237350567 -1 0.46875741869756882\n"" 136 0.62487945516234578 -0.62473271086601501 1\n"" 137 1 -1 0.75017445000000005\n"" 138 0.74996116568713633 -0.37481680473944939 1\n"" 139 1 -0.37487247538331225 0.74993327711783697\n"" 140 0.52037384429375466 0.13732055395658338 0.20134643019667742\n"" 141 0.15110486348630267 -0.58850137906978839 -0.32248691722782763\n"" 142 0.18460607304185575 -0.25601325165021294 0.59072519783751942\n"" 143 0.58280144730296801 -0.1236683742487249 -0.25429890766156527\n"" 144 -0.62459780071323356 0.62480472798869868 -1\n"" 145 -1 0.62491663124728913 -0.6248890159372763\n"" 146 -0.62484746422599169 1 -0.62502715932999464\n"" 147 -0.7093663193037405 1 -0.043380902757278066\n"" 148 -1 0.70881555044570888 -0.042280622034258974\n"" 149 1 -1 -0.25034290000000009\n"" 150 1 -0.40640338795560693 0.10958986646960317\n"" 151 0.62965348921187414 -1 0.11553823232370244\n"" 152 0.62491481284490769 -0.62481034920526324 -1\n"" 153 0.62518044398996542 -1 -0.62501367730297908\n"" 154 1 -0.63771354537448766 -0.63764519345816328\n"" 155 1 0.31875234539841601 -0.74994017167142224\n"" 156 1 0.25014510000000001 -1\n"" 157 0.74289722234692146 0.382058894292784 -1\n"" 158 0.32367160517680327 0.022514689090561313 -1\n"" 159 -0.16523027793533418 0.12134647368575949 -0.52708319267772263\n"" 160 0.66127538009577513 0.12758426427554953 -1\n"" 161 0.66190311587317174 -0.14472935797430672 -0.63288146125613987\n"" 162 0.32369468988306133 1 -0.022395524628340657\n"" 163 0.66678290425073372 1 -0.041514421404229618\n"" 164 0.25040265000000006 1 -1\n"" 165 0.0399620660587649 1 -0.35479393735090492\n"" 166 0.39507172571995386 0.7484116421252891 -1\n"" 167 1 -0.072369672334633761 0.72403943393322545\n"" 168 1 0.25022030000000006 1\n"" 169 -1 0.34715093732334323 0.069506853183406409\n"" 170 0.004224600474193374 -0.00030510666109673235 0.14430736392114327\n"" 171 -0.094962845556292308 0.5834952204256858 0.029410273259612763\n"" 172 -0.37516021595805987 -1 -0.12532788579913123\n"" 173 -0.24910025000000008 -0.73780528173239301 -1\n"" 174 -0.24899625000000003 -1 -1\n"" 175 -1 -0.68752594294730018 0.32233197415569781\n"" 176 -0.63898818329694262 -0.019780155017187176 -0.25640753531059018\n"" 177 -0.24918545000000003 1 -1\n"" 178 -0.090115044090208485 0.73312064098608642 -1\n"" 179 0.70087100707296945 0.7030864101348856 -0.70306291837965817\n"" 180 0.43929348327839085 1 -0.54468859277252801\n"" 181 0.24904127574612012 0.39074020564473289 -0.70186910867307939\n"" 182 1 0.37487410261969639 -0.24965440370335262\n"" 183 -1 0.25002235 1\n"" 184 -1 0.3834446703544917 0.71903607815447956\n"" 185 -0.1156880925075553 0.64434016438489528 0.64434017606689242\n"" 186 -0.49172745225271947 1 0.39835250767529351\n"" 187 -0.49767862299671706 0.38046779215689319 1\n"" 188 -0.71839703681869116 0.71780974657570373 0.44934935063382636\n"" 189 -0.51344827724776054 0.71469177745101886 0.71472798522876002\n"" 190 -0.23617534848477656 0.19448005635194549 1\n"" 191 0.10846459384596518 0.30820266021358389 1\n"" 192 0.25057285000000007 1 1\n"" 193 0.017230183845622971 1 0.32091029596366771\n"" 194 0.73101248242769623 0.7310147155780512 0.70877874225568527\n"" 195 0.31697048198150773 0.74665075980915008 0.4006579958540028\n"" 196 0.22826577744747956 0.47891948624469016 0.71004422740180217\n"" 197 1 0.41190390341165745 0.48757967789479273\n"" 198 0.39445308838583859 1 0.75656358081536812\n"" 199 0.37539107500000007 0.73916688955610543 1\n"" 200 1 0.37513265000000007 0.77169890914285255\n"" 201 0.73942011355234571 0.37513265000000007 1\n"" 202 0.63994038137069154 0.63994036678159205 0.2035446667438317\n"" 203 -0.46370016318896046 -0.62998103084618617 -0.61483850042635191\n"" 204 -1 -0.21786745446900305 -0.71882640763337879\n"" 205 -0.7381625142245487 -0.24989619999999996 -1\n"" 206 -1 -0.68409919087038817 -0.74320185410965045\n"" 207 -0.32233403971208485 -0.68753538843092254 1\n"" 208 -0.24999429999999997 -1 1\n"" 209 -1 -0.68747379665002328 0.68733786195201785\n"" 210 -1 -1 0.74993719999999997\n"" 211 -0.68734034505209507 -0.68746383783523624 1\n"" 212 0.012621642749083783 -0.62121055252239044 0.25549907282899653\n"" 213 -0.6302385799280833 -0.18856073836207951 0.63023858315073289\n"" 214 -1 -0.24375245663389172 0.20780956095073669\n"" 215 0.27457426263537876 -0.71671644193112283 1\n"" 216 0.25031765 -1 0.74826556642116959\n"" 217 0.67415846717387884 -1 0.72313083855082583\n"" 218 0.62503542334105555 -0.31221159888129457 0.62503541050290967\n"" 219 0.5971993096065894 0.14306806366195202 0.59872066564664705\n"" 220 1 0.017233350071975677 0.32090429254255515\n"" 221 0.26312362546126472 0.33468192363906535 0.084065768486193945\n"" 222 0.32197792152690552 -1 0.018797337932729474\n"" 223 0.18800195544968995 -1 -0.56289551925444881\n"" 224 0.57038729142869704 -0.57307887210152808 -0.20881754066389768\n"" 225 -0.0086896099297664228 -0.40801963637004723 -1\n"" 226 0.18460607304185569 -0.25601325165021294 1\n"" 227 -0.20780680948491165 -0.24375608761730455 1\n"" 228 0.16210795897650465 -0.16280891134401318 -0.30907215240469521\n"" 229 1 -0.26636148213032163 -0.17942676839456378\n"" 230 0.56446572384612781 0.1973176117738667 -0.43724659666019622\n"" 231 0.68853374013319157 -0.17744483013216472 0.09783510961497599\n"" 232 -1 0.25009230000000005 -1\n"" 233 -0.44245798368554617 0.091797696559903857 -1\n"" 234 -0.37472098690918887 0.74987909210814685 -1\n"" 235 -1 0.75000438735900432 -0.37495636858710685\n"" 236 -0.74996704638216471 1 -0.37508384505925174\n"" 237 -1 0.74990679999999998 -1\n"" 238 -0.54712707263607874 0.54712707774677038 -0.44245689687343565\n"" 239 -0.74990204999999999 1 -1\n"" 240 -0.72822316548562926 0.72874031845750664 0.1036085388532241\n"" 241 1 -0.71873547817891748 0.28112338497214717\n"" 242 1 -1 0.24972335000000001\n"" 243 0.75048264999999992 -1 -1\n"" 244 0.74989614566839657 -1 -0.37495931701899499\n"" 245 0.32778297288621805 -0.39528027615360428 -0.64821309452322518\n"" 246 1 -0.38051416654716286 -0.74727639147947866\n"" 247 0.75568696149005932 -0.39170758577960507 -1\n"" 248 0.67082477453227773 0.69774082076774491 -0.21670307025395311\n"" 249 0.25644629494787752 0.72897062001391455 -0.35498913750943906\n"" 250 -0.66044139980269567 0.12332997433814857 0.28570391360731856\n"" 251 -0.20800059812674501 0.28777064045558248 0.28593682199556314\n"" 252 0.29133599196527848 -0.095788071590640317 0.30648986161740821\n"" 253 -0.19340828105680374 -0.0068671095901119807 -0.17510149752792639\n"" 254 -0.21084753812463372 1 -0.20339622724796672\n"" 255 -0.098922382084248209 0.356624117376247 -0.256263439404529\n"" 256 -1 -0.74213790787259271 -0.24206983063972595\n"" 257 -0.72511478181115718 -1 -0.25002969999999997\n"" 258 -0.1250383368944159 -1 -0.24987830054645518\n"" 259 -0.5432409326212666 -0.58336779772250913 -0.0060938376146522089\n"" 260 -1 -1 0.25020549999999997\n"" 261 -0.69517902037783963 -1 0.48465629903462193\n"" 262 -1 0.19801494027267907 -0.22908951271298833\n"" 263 -1 -0.21170789004360985 -0.2804810168349573\n"" 264 0.12431896494966958 0.19380761445281547 -0.51506516411314296\n"" 265 0.016877018602808991 0.32057899216794972 -1\n"" 266 0.31815206866103007 0.69886802178230512 -0.69773364246572678\n"" 267 1 0.29452437620263039 0.03597223402760958\n"" 268 -0.23854616157962166 0.70039865549364788 0.32382827237146705\n"" 269 -0.072417036863037423 1 0.7240118059209224\n"" 270 -0.65715846697692126 0.26022065746019457 0.6943166148678479\n"" 271 0.032006652383344852 0.12877070459954792 0.60754383991332461\n"" 272 0.70679839053632465 0.35784100137989416 0.35408213575434944\n"" 273 1 0.75583880296190964 0.10796710954834202\n"" 274 -0.066417091587110066 -0.67493516441615642 -0.64835749920354258\n"" 275 -0.66000110931003353 -0.29732769674682547 -0.5356675566159671\n"" 276 -1 -0.7460956789293286 -0.49597432811515113\n"" 277 -0.63537062135554268 -1 -0.62487395000000001\n"" 278 -0.072189529852730625 -0.75207129129950046 1\n"" 279 -0.12479964999999998 -1 0.76180792382505302\n"" 280 -0.64633703603487636 -0.58450521092750218 0.50482020379778969\n"" 281 -0.19793040641595078 -1 0.22917284009874619\n"" 282 0.36430902573049584 -0.60319992435881997 0.46610302519244695\n"" 283 -0.014560432971481855 -0.28974170434477692 0.31899501601243035\n"" 284 -0.16677858939457951 -0.59736466720530357 0.62746423626615599\n"" 285 -0.70838149553417962 -0.14588171485233958 1\n"" 286 -1 -0.20773576611374234 0.72382280144202749\n"" 287 0.65401865792186442 -0.65865126715652123 0.6540215253821221\n"" 288 0.76868552550191671 -0.1162896631221611 1\n"" 289 0.39236022879703553 0.3070079448900544 0.42979647060190596\n"" 290 0.3368388593683827 0.015623435483033674 1\n"" 291 0.19283437348027005 -1 0.30983198636425424\n"" 292 0.23987671409711908 -0.66618838122351409 0.0008945936534150746\n"" 293 0.42213117252176491 -0.74712687995942406 -0.48458654817973601\n"" 294 1 -0.66026812967233972 0.017464640590841476\n"" 295 0.76163529643898698 -1 -0.11209435873849422\n"" 296 0.71607191560259942 -0.37037315933178871 -0.41086960011962592\n"" 297 -0.21716346053460103 -0.19947717862659675 -1\n"" 298 -0.066700914192858729 -0.25756978212559839 -0.62896708724727191\n"" 299 0.32965714090299714 -0.016623876027232615 -0.04345086208713933\n"" 300 0.3771146741942551 -0.33750921003054202 -0.17865283786030017\n"" 301 0.68867680851486557 0.35765454098697025 -0.68521532739244984\n"" 302 0.68683764447685003 -0.49596319168560488 0.30085803648362652\n"" 303 0.7090270874729655 -0.090415723473831255 0.40719961870896915\n"" 304 -0.71897798523587353 0.032300798531047246 -1\n"" 305 -0.78106895850102998 0.78106955040650416 -1\n"" 306 -1 1 -0.75022459999999991\n"" 307 -0.6917164744917017 0.69170418541265011 -0.69178840942223951\n"" 308 -0.44874465612278081 0.23033846865992608 -0.37975265656437374\n"" 309 -0.42791646676676653 1 -0.48213646482850109\n"" 310 -0.50093773209802361 0.36943796178744326 -1\n"" 311 -0.27376979380830829 0.64426231976101334 -0.66489790575084351\n"" 312 -1 0.35637030336560244 -0.50592472907968644\n"" 313 -0.67546025565396317 0.47435524682845248 -0.12755140965778172\n"" 314 1 -1 -0.74991180000000002\n"" 315 1 -0.75028080000000008 -1\n"" 316 0.75389683099717963 -0.68868788457723729 -0.44203141186583489\n"" 317 0.30599251534318156 -0.52261127269823027 -1\n"" 318 0.40047237565428867 -0.18178393484624253 -0.46933497457143036\n"" 319 0.59482353914036401 0.38624515090984007 -0.049897636224658731\n"" 320 -1 0.12332997433814856 0.2857039136073185\n"" 321 -1 -0.14689524813441618 0.42688908174824769\n"" 322 -0.66262979736993932 -0.22367581355790006 0.28652907305244368\n"" 323 -0.73506511384989526 0.43296210769478211 0.23284828493726362\n"" 324 -0.35917397776062404 -0.0011820981956873755 0.46134022362807492\n"" 325 -0.46329592253134338 -0.04321417701540118 0.047101266600350966\n"" 326 -0.27019578023748486 0.66094639539627242 -0.2626201492532621\n"" 327 -0.034393111593928383 0.28261880242562187 0.033764464745287937\n"" 328 0.18250360638285329 -1 -0.25535398043003921\n"" 329 -0.3030416241215706 -0.68638401151842854 -0.29392180366815041\n"" 330 -0.20024923856661142 -0.43390131265744347 0.010814269493628442\n"" 331 -0.70928533124789683 -1 0.043514240508664342\n"" 332 -0.66723744746271052 -0.6603325322519602 -0.32775579384930814\n"" 333 -0.75004930000000003 -1 1\n"" 334 -0.19527119007052851 0.17101403421852743 -1\n"" 335 0.035377884590221398 0.72616811699961958 0.38837547693302749\n"" 336 -0.3958963327893722 1 0.076655950240576198\n"" 337 -1 0.21457329427678187 0.47543850615348943\n"" 338 -0.7309823244201562 0.04824246580043276 0.53867561355267524\n"" 339 0.31731660817460328 0.019726050398274825 0.58867762989660533\n"" 340 -0.23374781763549932 0.32728908975345111 0.68606341552187544\n"" 341 -0.05707064185106852 -1 -0.71659883209883557\n"" 342 0.025895325626349025 -1 -0.41197380535174077\n"" 343 -0.63238580600180661 -0.3446250983839011 -0.21239475499198135\n"" 344 -1 -0.44899498782248648 -0.76904522126668295\n"" 345 -0.47299161220497166 -0.16458691872110107 -1\n"" 346 -0.71473237282422963 -0.73570249654826969 -0.71737349776128545\n"" 347 -0.74042724546706096 -1 0.74043153378626769\n"" 348 -0.75006482996996637 -0.43746254158362985 1\n"" 349 -1 -0.45163184813329721 0.75853196322407168\n"" 350 -0.50484417551448635 -0.72312317896459377 0.74770602252103513\n"" 351 -0.40758966352762416 -0.67845102844514626 0.2869272680702189\n"" 352 0.34674400209661604 -0.46348651949776365 1\n"" 353 -0.064367666161959269 -0.33637242545568102 0.74735946563471645\n"" 354 0.092602515587840606 -0.73476755239921543 0.53136369836931496\n"" 355 0.7405253302829875 -1 0.37931276242110001\n"" 356 0.72074474478028516 -0.071123657589263783 0.72858260191381197\n"" 357 -0.37493998320650845 -0.13123609584112483 -0.59370675998889832\n"" 358 -0.038352185780633007 -0.36921106178200458 -0.36036098843849301\n"" 359 -0.21058188105209746 -0.51336343843000509 -1\n"" 360 0.48755585676167218 -0.72413212665883209 0.19600157800093837\n"" 361 0.72678157399644117 -0.45646629587434373 0.011780680786240783\n"" 362 1 -0.2170765504241112 0.26033741814256661\n"" 363 -0.74541512030390267 -0.021189991595686748 -0.68170217165320612\n"" 364 -0.37387254482300358 0.32527982613660117 -0.69267828171913437\n"" 365 0.014913421017989981 0.548850834537849 -0.51262186425268497\n"" 366 -0.74537069514237131 0.2884463439624349 -1\n"" 367 -1 0.37511355000000007 -0.76842458715696027\n"" 368 -0.68532657097754035 0.18056419100293586 -0.02075972921423834\n"" 369 0.78133395148913365 -1 -0.78126287896225588\n"" 370 0.78115294817471781 -0.78112807555219699 -1\n"" 371 0.59082087507768066 -0.57000731366339108 -0.68829605397498683\n"" 372 0.062122976656860403 -0.70293283755163305 -1\n"" 373 0.71559274300689513 0.42281759201802555 -0.31813908171117911\n"" 374 0.7564597747876356 0.13217713297538497 -0.16417576007580004\n"" 375 0.40814884545639363 0.4915141193769953 -0.2436752542444009\n"" 376 -0.75696767061236314 -0.5164837362163468 0.21622587965261447\n"" 377 -0.452391830423859 0.55519361636450704 0.12429201972918034\n"" 378 -0.43481019055019038 -0.12925317405502307 1\n"" 379 -0.24742795067222612 -0.11366422696012682 0.2223275751188645\n"" 380 -0.006677616808027087 -0.21615237698969206 -0.065426614396930594\n"" 381 -0.062406752747729527 -0.70182414510247981 -0.087999792237402064\n"" 382 0.10306104864954116 0.76464771966531997 0.11700653142882178\n"" 383 0.27486783995540093 -0.12812237061584772 0.79536259891875982\n"" 384 -0.74059417471417499 -0.15757730258109431 0.00074049988054281091\n"" 385 -0.64002796579304344 -0.45394506207193958 -1\n"" 386 -0.42239397063762912 -0.42048979870740139 0.69490811148992537\n"" 387 -0.17195299402586212 -0.76346805360446235 0.40560748360163079\n"" 388 0.37676760090127209 -0.4417530820461561 0.70978247252690463\n"" 389 -0.20593363392839478 -0.044483242006169432 0.7439953909431003\n"" 390 -0.31521564832256066 -0.39420460209868968 -0.72065547292536469\n"" 391 -0.07315504595340451 0.34077703680706245 -0.71267230392230696\n"" 392 -0.0052948425242513517 1 -0.74523404665783877\n"" 393 -0.70127839101164502 0.30537699044254324 -0.64148488859352526\n"" 394 0.25061214999999992 -1 -1\n"" 395 0.40565131063307963 -0.76032995286218041 -1\n"" 396 0.38398614307047785 -1 -0.75304567260853106\n"" 397 0.23839244367761547 -0.68688896416028877 -0.73641430830181331\n"" 398 0.76674691103343318 0.57740125411814403 -0.50231823898754502\n"" 399 0.14110565781161721 -0.59279131304323562 0.77705687354697894\n""# Generated by tetgen -a0.01 cube.smesh \n"); } +static const char* getElements() { return( +"1580 4 0\n"" 0 120 148 13 240\n"" 1 77 251 185 268\n"" 2 126 194 66 198\n"" 3 297 298 159 357\n"" 4 13 148 147 240\n"" 5 219 272 102 303\n"" 6 134 137 37 136\n"" 7 302 360 88 361\n"" 8 23 264 95 391\n"" 9 307 311 238 364\n"" 10 57 309 254 326\n"" 11 345 357 233 363\n"" 12 176 343 325 384\n"" 13 275 332 67 343\n"" 14 141 245 228 318\n"" 15 108 368 323 377\n"" 16 7 47 74 123\n"" 17 73 188 184 270\n"" 18 56 235 148 313\n"" 19 46 72 117 179\n"" 20 66 105 28 194\n"" 21 205 275 204 344\n"" 22 66 194 28 198\n"" 23 96 221 45 375\n"" 24 93 160 94 161\n"" 25 225 317 245 397\n"" 26 121 186 74 188\n"" 27 213 280 52 322\n"" 28 52 322 280 376\n"" 29 96 195 77 221\n"" 30 8 257 256 331\n"" 31 358 380 330 381\n"" 32 99 181 166 266\n"" 33 120 123 73 188\n"" 34 122 189 187 340\n"" 35 141 292 224 300\n"" 36 313 326 240 377\n"" 37 203 274 173 390\n"" 38 140 299 221 319\n"" 39 44 197 107 272\n"" 40 171 326 108 377\n"" 41 71 166 46 179\n"" 42 69 364 334 391\n"" 43 26 114 97 115\n"" 44 228 253 159 358\n"" 45 221 272 202 289\n"" 46 123 184 73 188\n"" 47 22 220 140 231\n"" 48 250 324 322 325\n"" 49 270 324 213 338\n"" 50 147 240 57 336\n"" 51 69 265 178 391\n"" 52 100 249 165 365\n"" 53 296 316 224 371\n"" 54 74 188 186 189\n"" 55 21 171 165 249\n"" 56 23 297 225 298\n"" 57 191 196 64 290\n"" 58 87 139 138 288\n"" 59 126 198 196 199\n"" 60 223 328 141 342\n"" 61 293 371 153 396\n"" 62 238 308 108 313\n"" 63 49 187 80 189\n"" 64 143 300 224 361\n"" 65 111 256 130 343\n"" 66 62 107 106 273\n"" 67 64 196 126 219\n"" 68 314 154 315 369\n"" 69 50 205 204 344\n"" 70 0 70 26 71\n"" 71 95 158 23 265\n"" 72 37 138 87 139\n"" 73 125 193 43 195\n"" 74 56 312 238 313\n"" 75 257 259 172 332\n"" 76 25 70 0 72\n"" 77 141 300 228 358\n"" 78 32 207 208 350\n"" 79 101 201 200 219\n"" 80 13 147 121 240\n"" 81 67 275 176 357\n"" 82 116 249 180 266\n"" 83 197 219 200 272\n"" 84 152 247 42 371\n"" 85 95 158 60 160\n"" 86 45 230 116 375\n"" 87 88 282 142 283\n"" 88 96 162 61 249\n"" 89 209 280 211 350\n"" 90 84 353 226 399\n"" 91 33 258 172 381\n"" 92 118 285 213 378\n"" 93 196 271 77 289\n"" 94 282 287 218 388\n"" 95 196 198 125 199\n"" 96 74 7 76 30\n"" 97 95 230 181 264\n"" 98 297 359 225 390\n"" 99 280 347 261 350\n"" 100 253 299 170 380\n"" 101 125 269 193 335\n"" 102 245 293 224 300\n"" 103 41 143 68 161\n"" 104 58 295 244 316\n"" 105 83 348 211 349\n"" 106 75 29 76 123\n"" 107 171 249 96 255\n"" 108 124 196 125 199\n"" 109 61 248 96 249\n"" 110 221 255 45 327\n"" 111 254 326 171 336\n"" 112 194 198 126 199\n"" 113 208 278 9 279\n"" 114 94 93 11 160\n"" 115 275 357 345 363\n"" 116 127 173 109 203\n"" 117 134 139 55 218\n"" 118 45 255 253 327\n"" 119 154 35 315 370\n"" 120 283 284 142 353\n"" 121 186 336 268 377\n"" 122 59 93 11 94\n"" 123 110 203 51 277\n"" 124 59 246 94 247\n"" 125 116 248 61 249\n"" 126 41 229 143 296\n"" 127 91 154 36 316\n"" 128 71 179 116 180\n"" 129 45 299 221 327\n"" 130 319 373 182 374\n"" 131 64 219 101 290\n"" 132 116 301 179 398\n"" 133 122 323 188 377\n"" 134 182 373 68 374\n"" 135 97 115 114 248\n"" 136 60 158 95 181\n"" 137 185 268 48 335\n"" 138 66 125 43 195\n"" 139 86 215 136 287\n"" 140 106 202 163 273\n"" 141 43 106 66 195\n"" 142 271 324 283 389\n"" 143 95 158 42 245\n"" 144 186 188 122 189\n"" 145 25 179 157 301\n"" 146 173 274 110 341\n"" 147 136 138 37 287\n"" 148 244 293 58 316\n"" 149 107 197 65 272\n"" 150 42 160 158 161\n"" 151 28 105 103 194\n"" 152 200 201 126 219\n"" 153 147 235 90 236\n"" 154 224 292 141 293\n"" 155 220 272 140 303\n"" 156 4 209 83 211\n"" 157 207 278 208 279\n"" 158 296 300 143 318\n"" 159 226 352 84 399\n"" 160 104 65 63 194\n"" 161 212 282 88 283\n"" 162 255 308 238 364\n"" 163 150 229 91 361\n"" 164 43 163 106 202\n"" 165 126 219 196 289\n"" 166 48 185 79 189\n"" 167 257 329 110 332\n"" 168 170 299 252 380\n"" 169 30 74 75 76\n"" 170 30 79 78 80\n"" 171 39 234 146 307\n"" 172 218 252 142 339\n"" 173 185 251 77 340\n"" 174 102 200 197 219\n"" 175 49 189 185 340\n"" 176 213 348 286 349\n"" 177 133 286 285 348\n"" 178 65 197 126 272\n"" 179 187 189 49 340\n"" 180 213 285 53 378\n"" 181 63 194 65 200\n"" 182 131 279 85 387\n"" 183 120 169 148 323\n"" 184 197 200 126 272\n"" 185 46 166 72 179\n"" 186 15 248 98 273\n"" 187 98 114 24 373\n"" 188 46 180 100 266\n"" 189 22 231 140 374\n"" 190 171 335 77 382\n"" 191 27 106 62 107\n"" 192 255 264 159 391\n"" 193 132 325 322 379\n"" 194 240 323 313 377\n"" 195 155 160 93 301\n"" 196 221 299 170 327\n"" 197 158 160 95 161\n"" 198 79 80 30 189\n"" 199 178 365 311 391\n"" 200 16 285 133 286\n"" 201 249 255 171 365\n"" 202 188 270 73 323\n"" 203 162 165 61 249\n"" 204 107 126 65 194\n"" 205 155 156 93 160\n"" 206 219 303 102 356\n"" 207 259 330 132 351\n"" 208 224 293 141 300\n"" 209 77 271 170 289\n"" 210 231 252 140 299\n"" 211 147 240 148 313\n"" 212 152 370 153 395\n"" 213 154 246 35 247\n"" 214 291 354 212 387\n"" 215 211 348 280 349\n"" 216 144 234 39 307\n"" 217 212 292 33 381\n"" 218 133 348 83 349\n"" 219 119 337 270 338\n"" 220 120 188 73 323\n"" 221 211 280 209 349\n"" 222 209 211 333 347\n"" 223 251 325 108 379\n"" 224 236 238 146 309\n"" 225 274 329 110 342\n"" 226 39 305 144 307\n"" 227 144 305 89 307\n"" 228 96 249 248 375\n"" 229 113 178 177 392\n"" 230 91 294 224 295\n"" 231 94 160 42 161\n"" 232 165 171 21 326\n"" 233 170 324 251 379\n"" 234 211 347 209 350\n"" 235 116 179 115 398\n"" 236 214 263 31 384\n"" 237 70 117 71 0\n"" 238 43 195 96 202\n"" 239 90 235 40 236\n"" 240 134 136 37 287\n"" 241 67 253 159 357\n"" 242 33 328 258 381\n"" 243 71 116 115 180\n"" 244 55 241 134 302\n"" 245 155 301 24 398\n"" 246 275 345 205 363\n"" 247 52 209 175 280\n"" 248 287 302 241 355\n"" 249 79 185 48 269\n"" 250 45 181 116 230\n"" 251 68 182 24 373\n"" 252 106 126 66 195\n"" 253 170 299 253 327\n"" 254 228 298 245 358\n"" 255 275 357 67 390\n"" 256 126 195 77 196\n"" 257 176 275 67 343\n"" 258 17 363 232 367\n"" 259 248 249 116 375\n"" 260 251 324 250 325\n"" 261 122 251 185 340\n"" 262 238 311 309 326\n"" 263 157 160 155 301\n"" 264 60 181 99 265\n"" 265 98 248 114 373\n"" 266 34 261 209 347\n"" 267 132 330 212 351\n"" 268 245 274 141 358\n"" 269 190 191 19 271\n"" 270 236 238 57 313\n"" 271 105 104 103 194\n"" 272 94 246 161 247\n"" 273 35 246 59 247\n"" 274 140 319 267 374\n"" 275 212 281 33 291\n"" 276 117 71 46 179\n"" 277 70 117 72 179\n"" 278 159 253 228 264\n"" 279 80 185 49 189\n"" 280 209 333 4 210\n"" 281 2 128 127 206\n"" 282 100 164 46 166\n"" 283 74 76 7 123\n"" 284 80 187 75 189\n"" 285 103 194 63 201\n"" 286 171 326 249 365\n"" 287 136 6 137 37\n"" 288 216 291 85 354\n"" 289 47 120 13 121\n"" 290 101 288 54 356\n"" 291 130 263 111 343\n"" 292 168 200 101 201\n"" 293 68 143 41 229\n"" 294 282 291 135 354\n"" 295 49 191 190 340\n"" 296 184 189 75 270\n"" 297 202 272 126 289\n"" 298 218 356 339 383\n"" 299 352 388 215 399\n"" 300 124 192 125 269\n"" 301 70 117 0 72\n"" 302 136 218 138 287\n"" 303 108 255 171 327\n"" 304 223 293 153 396\n"" 305 25 156 155 157\n"" 306 115 116 61 180\n"" 307 320 321 250 338\n"" 308 60 166 99 181\n"" 309 228 245 141 358\n"" 310 127 346 203 385\n"" 311 96 249 171 382\n"" 312 219 272 140 289\n"" 313 112 275 204 363\n"" 314 126 197 65 200\n"" 315 270 337 250 338\n"" 316 42 158 95 161\n"" 317 183 187 118 270\n"" 318 212 283 132 284\n"" 319 204 275 205 363\n"" 320 165 180 61 249\n"" 321 67 275 203 332\n"" 322 14 185 80 269\n"" 323 224 296 91 316\n"" 324 209 261 175 280\n"" 325 290 339 219 383\n"" 326 193 269 48 335\n"" 327 106 195 43 202\n"" 328 176 357 275 363\n"" 329 77 251 170 271\n"" 330 44 267 220 272\n"" 331 75 189 187 270\n"" 332 65 194 126 200\n"" 333 68 267 182 374\n"" 334 125 195 66 198\n"" 335 17 204 50 205\n"" 336 250 325 322 384\n"" 337 66 195 126 198\n"" 338 79 185 80 189\n"" 339 159 298 67 357\n"" 340 218 302 88 303\n"" 341 78 80 79 269\n"" 342 77 221 170 327\n"" 343 90 147 13 148\n"" 344 319 373 230 375\n"" 345 126 200 194 201\n"" 346 143 161 41 296\n"" 347 297 357 345 390\n"" 348 126 195 106 202\n"" 349 64 196 124 199\n"" 350 209 333 211 4\n"" 351 44 202 107 273\n"" 352 195 196 125 335\n"" 353 284 353 84 399\n"" 354 125 196 195 198\n"" 355 64 126 103 201\n"" 356 63 200 168 201\n"" 357 278 279 207 284\n"" 358 175 209 34 261\n"" 359 224 294 91 361\n"" 360 274 298 225 390\n"" 361 258 329 172 381\n"" 362 293 316 153 371\n"" 363 37 139 134 287\n"" 364 200 219 126 272\n"" 365 110 277 257 332\n"" 366 158 225 42 245\n"" 367 191 271 190 340\n"" 368 6 86 136 217\n"" 369 96 163 43 202\n"" 370 41 246 154 296\n"" 371 2 127 50 206\n"" 372 120 240 188 323\n"" 373 171 268 77 335\n"" 374 257 277 276 332\n"" 375 308 313 238 393\n"" 376 98 248 202 273\n"" 377 167 303 55 356\n"" 378 136 137 6 217\n"" 379 88 283 252 380\n"" 380 188 323 240 377\n"" 381 140 272 267 319\n"" 382 121 188 120 240\n"" 383 323 368 313 377\n"" 384 172 258 110 329\n"" 385 192 198 28 199\n"" 386 284 354 85 387\n"" 387 155 157 156 160\n"" 388 143 230 45 299\n"" 389 173 341 20 372\n"" 390 248 319 96 375\n"" 391 242 241 151 355\n"" 392 30 80 75 189\n"" 393 51 173 127 203\n"" 394 81 256 8 257\n"" 395 187 270 122 340\n"" 396 38 241 242 355\n"" 397 141 293 245 300\n"" 398 93 156 11 160\n"" 399 88 252 218 303\n"" 400 29 123 75 184\n"" 401 159 334 297 357\n"" 402 206 344 130 346\n"" 403 185 269 125 335\n"" 404 151 294 10 295\n"" 405 105 66 27 194\n"" 406 150 302 55 362\n"" 407 261 280 209 347\n"" 408 312 367 145 393\n"" 409 194 200 63 201\n"" 410 176 275 112 363\n"" 411 334 357 159 364\n"" 412 231 302 88 361\n"" 413 57 238 236 309\n"" 414 88 300 292 380\n"" 415 192 124 125 199\n"" 416 148 240 120 323\n"" 417 126 194 103 201\n"" 418 259 331 82 351\n"" 419 119 184 183 270\n"" 420 150 241 55 302\n"" 421 126 272 219 289\n"" 422 230 301 116 373\n"" 423 123 188 74 189\n"" 424 74 186 79 189\n"" 425 92 369 243 370\n"" 426 131 280 261 350\n"" 427 143 299 228 300\n"" 428 220 303 231 362\n"" 429 277 332 203 346\n"" 430 256 257 81 276\n"" 431 154 314 36 369\n"" 432 100 180 165 249\n"" 433 149 294 91 295\n"" 434 274 329 141 358\n"" 435 126 201 64 219\n"" 436 64 201 101 219\n"" 437 207 211 53 350\n"" 438 283 330 132 379\n"" 439 243 369 1 370\n"" 440 24 373 114 398\n"" 441 143 230 161 318\n"" 442 161 296 245 371\n"" 443 110 257 172 329\n"" 444 96 162 43 163\n"" 445 248 373 319 375\n"" 446 171 221 77 327\n"" 447 21 254 171 336\n"" 448 306 5 239 305\n"" 449 197 220 102 272\n"" 450 82 281 172 351\n"" 451 113 146 39 234\n"" 452 143 229 68 374\n"" 453 68 93 41 161\n"" 454 172 351 281 381\n"" 455 112 204 17 363\n"" 456 124 191 185 196\n"" 457 215 216 9 278\n"" 458 19 383 353 389\n"" 459 185 189 122 340\n"" 460 137 38 287 134\n"" 461 122 270 250 324\n"" 462 126 202 107 272\n"" 463 70 71 117 179\n"" 464 84 227 226 353\n"" 465 109 173 390 203\n"" 466 13 121 120 240\n"" 467 53 285 213 348\n"" 468 228 358 300 380\n"" 469 14 80 78 269\n"" 470 55 302 218 303\n"" 471 285 286 213 348\n"" 472 107 202 106 273\n"" 473 307 367 366 393\n"" 474 147 148 90 235\n"" 475 94 161 42 247\n"" 476 276 332 277 346\n"" 477 141 293 223 397\n"" 478 51 203 127 346\n"" 479 22 229 150 231\n"" 480 163 202 96 248\n"" 481 48 269 185 335\n"" 482 162 163 96 248\n"" 483 141 274 245 397\n"" 484 115 163 61 248\n"" 485 147 236 57 313\n"" 486 158 181 60 265\n"" 487 311 365 364 391\n"" 488 193 195 125 335\n"" 489 125 185 124 269\n"" 490 224 296 245 300\n"" 491 49 185 124 191\n"" 492 132 280 213 322\n"" 493 96 202 195 221\n"" 494 233 357 334 364\n"" 495 99 166 164 266\n"" 496 245 293 141 397\n"" 497 36 244 149 316\n"" 498 74 79 30 189\n"" 499 30 75 74 189\n"" 500 12 178 99 392\n"" 501 322 325 259 384\n"" 502 195 196 126 198\n"" 503 57 313 238 326\n"" 504 48 268 186 336\n"" 505 91 296 154 316\n"" 506 14 192 124 269\n"" 507 259 332 111 343\n"" 508 238 311 255 364\n"" 509 45 230 95 264\n"" 510 140 252 221 299\n"" 511 176 262 112 263\n"" 512 32 211 207 350\n"" 513 261 376 351 82\n"" 514 19 227 190 389\n"" 515 2 129 128 206\n"" 516 102 220 167 303\n"" 517 181 249 116 266\n"" 518 170 271 251 324\n"" 519 186 188 121 240\n"" 520 213 321 286 338\n"" 521 124 185 14 269\n"" 522 91 295 224 316\n"" 523 143 299 231 374\n"" 524 159 364 255 391\n"" 525 310 334 69 364\n"" 526 170 283 271 379\n"" 527 229 231 143 361\n"" 528 241 287 134 302\n"" 529 70 72 25 179\n"" 530 72 157 25 179\n"" 531 26 71 70 179\n"" 532 70 114 26 179\n"" 533 287 388 282 399\n"" 534 68 229 22 374\n"" 535 61 180 116 249\n"" 536 115 116 71 179\n"" 537 143 296 229 361\n"" 538 142 354 282 399\n"" 539 25 155 70 179\n"" 540 139 288 167 356\n"" 541 114 115 26 179\n"" 542 26 115 71 179\n"" 543 116 180 179 266\n"" 544 164 166 100 266\n"" 545 100 166 46 266\n"" 546 171 255 221 327\n"" 547 132 330 325 379\n"" 548 140 289 252 339\n"" 549 24 182 98 373\n"" 550 180 249 100 266\n"" 551 320 321 214 322\n"" 552 213 285 270 338\n"" 553 214 321 52 322\n"" 554 122 188 186 268\n"" 555 271 289 196 339\n"" 556 108 251 250 325\n"" 557 153 293 244 316\n"" 558 43 193 162 382\n"" 559 80 124 49 185\n"" 560 159 67 358 253\n"" 561 142 282 212 283\n"" 562 14 124 80 185\n"" 563 110 174 173 341\n"" 564 187 189 122 270\n"" 565 252 299 88 380\n"" 566 55 218 139 356\n"" 567 227 378 190 389\n"" 568 33 292 222 328\n"" 569 47 121 74 188\n"" 570 74 123 47 188\n"" 571 120 121 47 188\n"" 572 47 123 120 188\n"" 573 55 303 218 356\n"" 574 167 288 18 356\n"" 575 58 224 151 295\n"" 576 18 167 87 288\n"" 577 116 230 181 301\n"" 578 161 246 41 296\n"" 579 91 244 149 295\n"" 580 33 281 212 381\n"" 581 23 225 158 245\n"" 582 79 186 48 189\n"" 583 75 184 123 189\n"" 584 74 75 76 189\n"" 585 75 123 76 189\n"" 586 76 123 74 189\n"" 587 67 357 298 390\n"" 588 124 185 125 196\n"" 589 186 240 121 336\n"" 590 64 191 124 196\n"" 591 209 210 34 347\n"" 592 80 185 79 269\n"" 593 63 103 104 194\n"" 594 27 107 65 194\n"" 595 9 278 216 279\n"" 596 66 126 106 194\n"" 597 104 27 65 194\n"" 598 66 106 27 194\n"" 599 106 107 27 194\n"" 600 27 3 105 194\n"" 601 105 3 104 194\n"" 602 104 3 27 194\n"" 603 77 335 195 382\n"" 604 136 217 86 287\n"" 605 226 290 54 383\n"" 606 290 356 54 383\n"" 607 218 339 142 383\n"" 608 21 268 193 336\n"" 609 193 268 48 336\n"" 610 171 268 21 336\n"" 611 103 194 126 199\n"" 612 28 198 194 199\n"" 613 125 198 192 199\n"" 614 28 194 103 199\n"" 615 106 163 62 273\n"" 616 98 202 44 273\n"" 617 221 252 170 299\n"" 618 141 300 245 318\n"" 619 185 196 77 335\n"" 620 244 295 91 316\n"" 621 62 163 15 273\n"" 622 231 299 143 300\n"" 623 317 371 245 397\n"" 624 126 196 64 199\n"" 625 103 126 64 199\n"" 626 93 94 59 246\n"" 627 127 344 206 346\n"" 628 224 292 222 360\n"" 629 225 359 274 390\n"" 630 221 319 45 375\n"" 631 25 157 155 301\n"" 632 19 271 191 290\n"" 633 110 341 274 342\n"" 634 163 248 15 273\n"" 635 132 283 212 330\n"" 636 119 321 320 338\n"" 637 186 189 122 268\n"" 638 106 194 126 202\n"" 639 126 194 107 202\n"" 640 107 194 106 202\n"" 641 141 358 329 381\n"" 642 88 302 282 360\n"" 643 263 275 176 343\n"" 644 173 203 110 274\n"" 645 260 175 34 261\n"" 646 250 270 122 323\n"" 647 21 165 162 249\n"" 648 193 335 268 382\n"" 649 130 332 275 343\n"" 650 204 275 130 344\n"" 651 51 110 174 203\n"" 652 110 173 174 203\n"" 653 174 173 51 203\n"" 654 70 155 24 398\n"" 655 177 113 39 234\n"" 656 218 252 88 282\n"" 657 352 383 54 388\n"" 658 112 263 204 275\n"" 659 54 352 226 383\n"" 660 134 287 241 355\n"" 661 238 307 146 309\n"" 662 224 295 58 316\n"" 663 325 343 259 384\n"" 664 259 329 67 330\n"" 665 88 292 224 360\n"" 666 9 215 86 216\n"" 667 221 299 45 319\n"" 668 245 296 161 318\n"" 669 136 134 137 287\n"" 670 83 211 209 349\n"" 671 132 324 283 379\n"" 672 84 284 207 353\n"" 673 138 139 37 287\n"" 674 140 252 231 303\n"" 675 219 289 140 339\n"" 676 181 230 45 264\n"" 677 228 300 299 380\n"" 678 85 279 216 354\n"" 679 169 320 250 323\n"" 680 68 230 143 374\n"" 681 207 227 84 353\n"" 682 240 313 57 326\n"" 683 49 190 187 340\n"" 684 286 348 133 349\n"" 685 52 280 213 349\n"" 686 263 343 176 384\n"" 687 51 277 203 346\n"" 688 220 267 140 272\n"" 689 137 217 136 287\n"" 690 203 329 274 390\n"" 691 31 320 250 368\n"" 692 224 316 293 371\n"" 693 231 252 88 303\n"" 694 252 271 170 283\n"" 695 253 358 228 380\n"" 696 256 276 130 332\n"" 697 19 353 227 389\n"" 698 219 339 303 356\n"" 699 170 252 221 289\n"" 700 142 271 252 283\n"" 701 209 347 280 350\n"" 702 142 252 88 283\n"" 703 251 324 271 340\n"" 704 95 264 181 391\n"" 705 171 251 77 268\n"" 706 98 319 248 373\n"" 707 331 351 259 376\n"" 708 41 154 91 296\n"" 709 10 241 151 242\n"" 710 330 380 292 381\n"" 711 132 284 283 353\n"" 712 140 272 221 289\n"" 713 126 196 77 289\n"" 714 152 371 317 395\n"" 715 36 149 91 316\n"" 716 108 253 176 308\n"" 717 255 365 264 391\n"" 718 202 248 163 273\n"" 719 224 300 88 361\n"" 720 65 126 107 272\n"" 721 67 159 358 298\n"" 722 88 300 231 361\n"" 723 153 223 58 293\n"" 724 146 238 236 307\n"" 725 202 248 98 319\n"" 726 141 328 292 381\n"" 727 42 161 95 245\n"" 728 176 253 108 325\n"" 729 10 294 149 295\n"" 730 155 179 25 301\n"" 731 68 161 143 230\n"" 732 264 365 181 391\n"" 733 225 274 245 298\n"" 734 225 245 23 298\n"" 735 41 161 93 246\n"" 736 97 163 115 248\n"" 737 93 161 94 246\n"" 738 45 255 96 375\n"" 739 212 291 282 354\n"" 740 148 313 323 169\n"" 741 224 292 88 300\n"" 742 142 283 212 354\n"" 743 61 162 96 248\n"" 744 97 114 98 248\n"" 745 185 189 48 268\n"" 746 205 345 275 385\n"" 747 48 268 193 335\n"" 748 24 155 68 301\n"" 749 60 160 157 301\n"" 750 159 357 308 364\n"" 751 297 345 109 390\n"" 752 61 163 162 248\n"" 753 61 116 115 248\n"" 754 230 299 143 374\n"" 755 140 267 22 374\n"" 756 102 303 167 356\n"" 757 134 287 218 302\n"" 758 218 282 88 302\n"" 759 93 161 68 230\n"" 760 357 363 308 364\n"" 761 224 295 294 361\n"" 762 153 244 36 316\n"" 763 303 339 218 356\n"" 764 294 302 150 361\n"" 765 153 371 152 395\n"" 766 57 326 254 336\n"" 767 48 189 186 268\n"" 768 238 308 255 326\n"" 769 214 322 52 376\n"" 770 132 322 259 376\n"" 771 111 331 259 376\n"" 772 121 240 147 336\n"" 773 253 379 330 380\n"" 774 223 274 141 397\n"" 775 176 308 262 313\n"" 776 31 262 176 263\n"" 777 334 364 159 391\n"" 778 255 311 238 326\n"" 779 110 274 203 329\n"" 780 315 369 154 370\n"" 781 146 234 113 311\n"" 782 363 366 232 367\n"" 783 159 298 228 358\n"" 784 292 328 33 381\n"" 785 68 301 230 373\n"" 786 271 340 324 389\n"" 787 176 263 112 275\n"" 788 1 369 315 370\n"" 789 159 308 255 364\n"" 790 253 255 159 308\n"" 791 262 312 56 313\n"" 792 19 290 226 383\n"" 793 84 352 215 399\n"" 794 23 158 95 245\n"" 795 145 235 56 238\n"" 796 132 322 213 324\n"" 797 77 268 185 335\n"" 798 175 214 52 376\n"" 799 108 255 253 308\n"" 800 56 238 235 313\n"" 801 111 175 8 331\n"" 802 52 286 213 321\n"" 803 149 244 91 316\n"" 804 237 5 306 305\n"" 805 165 326 113 365\n"" 806 58 293 224 316\n"" 807 204 263 130 275\n"" 808 222 292 58 328\n"" 809 175 261 260 331\n"" 810 45 253 228 299\n"" 811 250 321 320 322\n"" 812 102 272 220 303\n"" 813 182 267 98 319\n"" 814 170 379 253 380\n"" 815 151 241 10 294\n"" 816 52 321 213 322\n"" 817 215 278 84 399\n"" 818 282 354 216 399\n"" 819 22 267 68 374\n"" 820 230 373 319 374\n"" 821 97 98 15 248\n"" 822 274 341 223 342\n"" 823 15 163 97 248\n"" 824 153 316 36 369\n"" 825 132 351 212 387\n"" 826 185 251 122 268\n"" 827 122 189 185 268\n"" 828 250 324 270 338\n"" 829 233 345 297 357\n"" 830 129 277 128 346\n"" 831 165 249 171 326\n"" 832 122 268 251 377\n"" 833 259 329 172 332\n"" 834 255 364 311 365\n"" 835 140 220 22 267\n"" 836 142 282 218 388\n"" 837 108 326 313 377\n"" 838 221 252 140 289\n"" 839 77 196 195 335\n"" 840 251 271 77 340\n"" 841 250 251 122 324\n"" 842 238 309 57 326\n"" 843 227 386 378 389\n"" 844 171 255 108 326\n"" 845 256 259 111 331\n"" 846 178 365 266 392\n"" 847 178 311 69 391\n"" 848 102 219 197 272\n"" 849 172 259 257 331\n"" 850 258 342 329 381\n"" 851 143 296 224 300\n"" 852 88 299 231 300\n"" 853 182 319 98 373\n"" 854 44 220 197 272\n"" 855 107 202 44 272\n"" 856 333 210 209 347\n"" 857 299 300 88 380\n"" 858 67 253 176 325\n"" 859 212 354 284 387\n"" 860 203 110 332 277\n"" 861 171 251 108 327\n"" 862 96 221 171 255\n"" 863 45 221 96 255\n"" 864 58 293 223 328\n"" 865 148 235 147 313\n"" 866 36 316 154 369\n"" 867 92 395 394 396\n"" 868 132 351 280 376\n"" 869 253 299 45 327\n"" 870 233 334 310 364\n"" 871 195 335 193 382\n"" 872 193 268 21 382\n"" 873 223 293 141 328\n"" 874 292 293 58 328\n"" 875 38 137 287 217\n"" 876 315 1 314 369\n"" 877 141 274 223 342\n"" 878 188 268 122 377\n"" 879 141 293 292 328\n"" 880 235 236 147 313\n"" 881 235 238 236 313\n"" 882 57 240 147 313\n"" 883 88 282 212 292\n"" 884 23 297 159 334\n"" 885 259 325 132 330\n"" 886 23 334 159 391\n"" 887 283 324 132 389\n"" 888 205 345 304 363\n"" 889 253 325 67 330\n"" 890 43 162 96 382\n"" 891 257 331 259 332\n"" 892 256 331 257 332\n"" 893 172 329 257 332\n"" 894 54 356 218 383\n"" 895 259 331 256 332\n"" 896 208 131 32 350\n"" 897 280 348 213 349\n"" 898 118 270 213 285\n"" 899 16 270 118 285\n"" 900 253 308 159 357\n"" 901 81 276 257 277\n"" 902 228 253 45 264\n"" 903 31 262 169 368\n"" 904 262 313 169 368\n"" 905 108 313 308 368\n"" 906 159 255 253 264\n"" 907 253 255 45 264\n"" 908 95 181 158 265\n"" 909 45 264 255 365\n"" 910 113 311 178 392\n"" 911 177 178 12 392\n"" 912 100 365 165 392\n"" 913 369 370 92 395\n"" 914 72 179 166 266\n"" 915 150 294 241 302\n"" 916 134 218 55 302\n"" 917 166 179 71 266\n"" 918 179 180 71 266\n"" 919 46 166 71 266\n"" 920 71 180 46 266\n"" 921 308 364 363 393\n"" 922 238 313 312 393\n"" 923 238 364 308 393\n"" 924 366 367 363 393\n"" 925 218 287 282 302\n"" 926 72 166 60 266\n"" 927 166 181 60 266\n"" 928 116 373 301 398\n"" 929 225 372 317 397\n"" 930 226 388 352 399\n"" 931 145 238 56 312\n"" 932 176 325 108 368\n"" 933 152 35 154 370\n"" 934 108 327 251 379\n"" 935 135 291 216 354\n"" 936 283 324 271 379\n"" 937 213 324 322 338\n"" 938 284 351 132 387\n"" 939 321 322 250 338\n"" 940 73 323 270 337\n"" 941 270 323 250 337\n"" 942 286 321 119 338\n"" 943 250 323 320 337\n"" 944 320 323 73 337\n"" 945 213 322 321 338\n"" 946 122 189 188 270\n"" 947 183 184 29 270\n"" 948 29 187 183 270\n"" 949 16 183 118 270\n"" 950 119 183 16 270\n"" 951 252 271 142 339\n"" 952 196 289 219 339\n"" 953 69 311 310 364\n"" 954 185 191 49 340\n"" 955 29 184 75 270\n"" 956 75 187 29 270\n"" 957 184 188 123 270\n"" 958 188 189 123 270\n"" 959 123 189 184 270\n"" 960 255 308 108 326\n"" 961 108 308 238 326\n"" 962 245 298 274 358\n"" 963 111 332 256 343\n"" 964 53 227 207 386\n"" 965 58 244 153 293\n"" 966 91 296 224 361\n"" 967 268 336 171 377\n"" 968 162 249 96 382\n"" 969 141 329 274 342\n"" 970 259 322 132 325\n"" 971 213 348 280 386\n"" 972 130 275 263 343\n"" 973 161 230 95 318\n"" 974 95 230 45 318\n"" 975 228 298 95 318\n"" 976 302 303 55 362\n"" 977 45 230 143 318\n"" 978 95 245 161 318\n"" 979 77 251 171 327\n"" 980 233 363 357 364\n"" 981 213 280 132 386\n"" 982 173 109 390 359\n"" 983 159 297 23 298\n"" 984 213 286 52 349\n"" 985 108 251 171 377\n"" 986 209 280 52 349\n"" 987 252 289 271 339\n"" 988 84 278 207 284\n"" 989 142 252 218 282\n"" 990 88 252 142 282\n"" 991 190 271 19 389\n"" 992 257 276 256 332\n"" 993 251 268 171 377\n"" 994 122 270 188 323\n"" 995 138 218 139 287\n"" 996 226 383 352 388\n"" 997 73 169 120 323\n"" 998 73 320 169 323\n"" 999 324 325 251 379\n"" 1000 364 365 255 391\n"" 1001 228 300 141 318\n"" 1002 224 296 143 361\n"" 1003 87 167 139 288\n"" 1004 297 334 233 357\n"" 1005 85 284 279 354\n"" 1006 122 324 251 340\n"" 1007 170 221 77 289\n"" 1008 170 271 252 289\n"" 1009 77 195 126 289\n"" 1010 167 220 55 303\n"" 1011 139 218 134 287\n"" 1012 216 217 135 287\n"" 1013 135 282 216 287\n"" 1014 245 300 296 318\n"" 1015 58 292 224 293\n"" 1016 171 249 21 382\n"" 1017 172 259 82 351\n"" 1018 131 284 279 387\n"" 1019 134 241 38 355\n"" 1020 18 288 101 356\n"" 1021 38 287 134 355\n"" 1022 139 167 55 356\n"" 1023 139 218 138 356\n"" 1024 142 383 271 389\n"" 1025 216 282 135 354\n"" 1026 353 383 142 389\n"" 1027 271 283 142 389\n"" 1028 131 350 284 387\n"" 1029 274 358 298 390\n"" 1030 86 216 215 287\n"" 1031 86 217 216 287\n"" 1032 195 202 126 289\n"" 1033 195 221 202 289\n"" 1034 77 221 195 289\n"" 1035 140 272 219 303\n"" 1036 33 291 222 292\n"" 1037 212 291 33 292\n"" 1038 229 296 91 361\n"" 1039 140 231 220 303\n"" 1040 145 307 238 393\n"" 1041 222 224 58 292\n"" 1042 270 324 122 340\n"" 1043 96 319 221 375\n"" 1044 216 278 215 399\n"" 1045 274 341 173 372\n"" 1046 88 252 231 299\n"" 1047 216 279 278 399\n"" 1048 115 248 116 398\n"" 1049 274 359 225 372\n"" 1050 153 395 92 396\n"" 1051 245 298 228 318\n"" 1052 95 298 245 318\n"" 1053 143 300 228 318\n"" 1054 231 303 302 362\n"" 1055 91 229 41 296\n"" 1056 293 396 223 397\n"" 1057 249 255 45 375\n"" 1058 42 245 225 317\n"" 1059 304 345 233 363\n"" 1060 55 303 220 362\n"" 1061 231 302 150 362\n"" 1062 216 354 279 399\n"" 1063 361 224 151 360\n"" 1064 282 388 142 399\n"" 1065 96 255 249 375\n"" 1066 151 222 135 360\n"" 1067 222 292 291 360\n"" 1068 159 264 23 391\n"" 1069 127 206 128 346\n"" 1070 95 265 23 391\n"" 1071 69 334 265 391\n"" 1072 159 264 228 298\n"" 1073 228 264 95 298\n"" 1074 23 245 95 298\n"" 1075 282 292 88 360\n"" 1076 67 330 329 358\n"" 1077 23 264 159 298\n"" 1078 95 264 23 298\n"" 1079 229 231 22 374\n"" 1080 60 157 72 301\n"" 1081 157 179 72 301\n"" 1082 116 266 179 301\n"" 1083 95 160 60 301\n"" 1084 60 266 181 301\n"" 1085 181 266 116 301\n"" 1086 60 181 95 301\n"" 1087 181 230 95 301\n"" 1088 160 161 93 301\n"" 1089 161 230 93 301\n"" 1090 68 155 93 301\n"" 1091 93 230 68 301\n"" 1092 179 266 72 301\n"" 1093 72 266 60 301\n"" 1094 95 161 160 301\n"" 1095 95 230 161 301\n"" 1096 308 357 176 363\n"" 1097 255 326 171 365\n"" 1098 91 294 150 361\n"" 1099 294 360 302 361\n"" 1100 231 300 143 361\n"" 1101 88 302 231 303\n"" 1102 245 371 293 397\n"" 1103 146 236 40 307\n"" 1104 236 238 235 307\n"" 1105 235 238 145 307\n"" 1106 110 203 332 329\n"" 1107 177 234 178 311\n"" 1108 113 234 177 311\n"" 1109 169 262 56 313\n"" 1110 148 169 56 313\n"" 1111 89 237 145 307\n"" 1112 89 305 237 307\n"" 1113 306 40 145 307\n"" 1114 146 40 306 307\n"" 1115 237 306 145 307\n"" 1116 237 305 306 307\n"" 1117 306 239 146 307\n"" 1118 305 239 306 307\n"" 1119 146 239 39 307\n"" 1120 239 305 39 307\n"" 1121 40 235 145 307\n"" 1122 40 236 235 307\n"" 1123 177 178 113 311\n"" 1124 253 255 108 327\n"" 1125 307 309 238 311\n"" 1126 178 234 69 311\n"" 1127 170 251 77 327\n"" 1128 271 324 170 379\n"" 1129 146 307 234 311\n"" 1130 181 266 99 365\n"" 1131 69 234 144 311\n"" 1132 234 307 144 311\n"" 1133 228 299 253 380\n"" 1134 100 266 249 365\n"" 1135 178 266 99 392\n"" 1136 99 266 178 365\n"" 1137 113 365 311 392\n"" 1138 99 266 164 392\n"" 1139 108 308 176 368\n"" 1140 313 323 169 368\n"" 1141 45 255 249 365\n"" 1142 232 363 304 366\n"" 1143 308 313 176 368\n"" 1144 146 309 307 311\n"" 1145 113 309 146 311\n"" 1146 52 280 175 376\n"" 1147 144 310 69 311\n"" 1148 115 179 114 398\n"" 1149 114 248 115 398\n"" 1150 176 262 31 368\n"" 1151 212 284 132 387\n"" 1152 89 366 144 367\n"" 1153 153 370 369 395\n"" 1154 153 369 92 395\n"" 1155 301 373 24 398\n"" 1156 53 350 348 386\n"" 1157 108 325 250 368\n"" 1158 371 395 153 396\n"" 1159 24 301 68 373\n"" 1160 70 179 155 398\n"" 1161 161 296 143 318\n"" 1162 95 264 228 318\n"" 1163 228 264 45 318\n"" 1164 45 264 95 318\n"" 1165 45 299 228 318\n"" 1166 228 299 143 318\n"" 1167 143 299 45 318\n"" 1168 68 373 230 374\n"" 1169 267 319 182 374\n"" 1170 259 351 132 376\n"" 1171 202 272 221 319\n"" 1172 221 272 140 319\n"" 1173 202 221 96 319\n"" 1174 96 248 202 319\n"" 1175 116 373 248 375\n"" 1176 44 202 98 319\n"" 1177 98 267 44 319\n"" 1178 267 272 44 319\n"" 1179 44 272 202 319\n"" 1180 230 373 116 375\n"" 1181 143 231 229 374\n"" 1182 116 249 181 375\n"" 1183 45 319 230 375\n"" 1184 116 181 45 375\n"" 1185 175 331 111 376\n"" 1186 280 322 132 376\n"" 1187 171 336 326 377\n"" 1188 261 347 131 350\n"" 1189 131 347 32 350\n"" 1190 128 206 129 346\n"" 1191 238 313 108 326\n"" 1192 171 254 21 326\n"" 1193 329 358 330 381\n"" 1194 251 327 170 379\n"" 1195 325 330 253 379\n"" 1196 172 281 33 381\n"" 1197 212 282 142 354\n"" 1198 110 329 258 342\n"" 1199 205 344 50 385\n"" 1200 376 261 351 280\n"" 1201 173 174 20 341\n"" 1202 322 324 132 379\n"" 1203 322 325 324 379\n"" 1204 298 358 67 390\n"" 1205 67 329 203 390\n"" 1206 21 254 165 326\n"" 1207 184 270 119 337\n"" 1208 142 284 283 354\n"" 1209 73 270 184 337\n"" 1210 218 303 252 339\n"" 1211 250 323 108 368\n"" 1212 245 274 225 397\n"" 1213 165 254 113 326\n"" 1214 275 344 205 385\n"" 1215 254 309 113 326\n"" 1216 309 311 113 326\n"" 1217 96 221 77 382\n"" 1218 249 326 165 365\n"" 1219 125 196 185 335\n"" 1220 224 245 371 293\n"" 1221 203 329 67 332\n"" 1222 50 206 127 344\n"" 1223 162 193 21 382\n"" 1224 8 256 111 331\n"" 1225 82 259 172 331\n"" 1226 245 224 371 296\n"" 1227 260 8 175 331\n"" 1228 250 368 325 384\n"" 1229 219 356 290 383\n"" 1230 96 195 43 382\n"" 1231 271 339 290 383\n"" 1232 212 330 292 381\n"" 1233 265 334 23 391\n"" 1234 329 330 259 381\n"" 1235 329 342 141 381\n"" 1236 77 221 171 382\n"" 1237 43 195 193 382\n"" 1238 292 380 141 381\n"" 1239 141 380 358 381\n"" 1240 111 259 256 332\n"" 1241 135 355 151 360\n"" 1242 130 344 275 346\n"" 1243 206 276 129 346\n"" 1244 207 350 53 386\n"" 1245 128 277 51 346\n"" 1246 51 127 128 346\n"" 1247 353 386 227 389\n"" 1248 271 290 19 383\n"" 1249 339 356 219 383\n"" 1250 322 324 250 338\n"" 1251 250 337 320 338\n"" 1252 320 337 119 338\n"" 1253 119 270 16 338\n"" 1254 270 285 16 338\n"" 1255 213 286 285 338\n"" 1256 285 286 16 338\n"" 1257 16 286 119 338\n"" 1258 343 376 259 384\n"" 1259 250 320 31 384\n"" 1260 252 303 140 339\n"" 1261 140 303 219 339\n"" 1262 191 271 196 339\n"" 1263 191 290 271 339\n"" 1264 196 290 191 339\n"" 1265 196 219 64 339\n"" 1266 219 290 64 339\n"" 1267 64 290 196 339\n"" 1268 31 368 250 384\n"" 1269 31 263 176 384\n"" 1270 322 376 214 384\n"" 1271 185 196 191 340\n"" 1272 196 271 191 340\n"" 1273 203 275 67 390\n"" 1274 345 357 275 390\n"" 1275 77 196 185 340\n"" 1276 77 271 196 340\n"" 1277 187 190 118 340\n"" 1278 118 270 187 340\n"" 1279 256 332 130 343\n"" 1280 67 325 176 343\n"" 1281 67 329 259 343\n"" 1282 67 332 329 343\n"" 1283 329 332 259 343\n"" 1284 298 357 297 390\n"" 1285 227 353 207 386\n"" 1286 344 346 127 385\n"" 1287 203 346 275 385\n"" 1288 348 350 280 386\n"" 1289 67 330 325 343\n"" 1290 325 330 259 343\n"" 1291 259 330 67 343\n"" 1292 284 350 207 386\n"" 1293 280 350 284 386\n"" 1294 207 353 284 386\n"" 1295 130 276 206 346\n"" 1296 130 332 276 346\n"" 1297 129 276 81 346\n"" 1298 276 277 81 346\n"" 1299 81 277 129 346\n"" 1300 203 332 275 346\n"" 1301 275 332 130 346\n"" 1302 53 348 213 386\n"" 1303 284 353 132 386\n"" 1304 280 348 211 350\n"" 1305 211 348 53 350\n"" 1306 85 281 131 387\n"" 1307 207 284 279 350\n"" 1308 279 284 131 350\n"" 1309 207 279 208 350\n"" 1310 208 279 131 350\n"" 1311 333 211 32 350\n"" 1312 333 347 211 350\n"" 1313 32 347 333 350\n"" 1314 350 351 284 387\n"" 1315 85 291 281 387\n"" 1316 281 381 351 387\n"" 1317 240 336 186 377\n"" 1318 313 368 108 377\n"" 1319 21 268 171 382\n"" 1320 171 221 96 382\n"" 1321 268 335 171 382\n"" 1322 218 287 136 388\n"" 1323 54 383 218 388\n"" 1324 218 383 142 388\n"" 1325 142 383 226 388\n"" 1326 82 261 131 351\n"" 1327 261 280 131 351\n"" 1328 284 350 280 351\n"" 1329 280 350 131 351\n"" 1330 226 227 19 353\n"" 1331 85 354 291 387\n"" 1332 131 351 350 387\n"" 1333 150 231 229 361\n"" 1334 88 360 224 361\n"" 1335 279 284 85 387\n"" 1336 281 291 212 387\n"" 1337 135 287 217 355\n"" 1338 150 302 231 361\n"" 1339 217 287 38 355\n"" 1340 283 284 212 354\n"" 1341 132 353 283 389\n"" 1342 118 340 190 389\n"" 1343 190 340 271 389\n"" 1344 271 383 19 389\n"" 1345 138 288 139 356\n"" 1346 176 368 31 384\n"" 1347 102 167 168 356\n"" 1348 101 219 200 356\n"" 1349 200 219 102 356\n"" 1350 167 18 168 356\n"" 1351 168 18 101 356\n"" 1352 101 290 219 356\n"" 1353 54 290 101 356\n"" 1354 138 218 54 356\n"" 1355 54 288 138 356\n"" 1356 259 376 322 384\n"" 1357 325 368 176 384\n"" 1358 168 200 102 356\n"" 1359 101 200 168 356\n"" 1360 176 253 67 357\n"" 1361 176 308 253 357\n"" 1362 307 310 144 364\n"" 1363 266 365 100 392\n"" 1364 135 291 282 360\n"" 1365 222 291 135 360\n"" 1366 282 291 212 360\n"" 1367 291 292 212 360\n"" 1368 212 292 282 360\n"" 1369 58 222 151 360\n"" 1370 58 224 222 360\n"" 1371 151 224 58 360\n"" 1372 22 231 150 362\n"" 1373 220 231 22 362\n"" 1374 241 294 151 360\n"" 1375 241 302 294 360\n"" 1376 282 302 287 360\n"" 1377 302 355 287 360\n"" 1378 282 287 135 360\n"" 1379 287 355 135 360\n"" 1380 241 355 302 360\n"" 1381 151 355 241 360\n"" 1382 294 295 151 361\n"" 1383 151 360 294 361\n"" 1384 204 205 17 363\n"" 1385 205 304 17 363\n"" 1386 132 324 213 386\n"" 1387 17 304 232 363\n"" 1388 250 320 169 368\n"" 1389 113 326 311 365\n"" 1390 274 372 225 397\n"" 1391 238 312 145 393\n"" 1392 372 395 317 397\n"" 1393 144 307 89 367\n"" 1394 89 307 145 367\n"" 1395 181 264 45 365\n"" 1396 249 266 181 365\n"" 1397 311 326 255 365\n"" 1398 310 311 144 364\n"" 1399 144 311 307 364\n"" 1400 176 313 262 368\n"" 1401 169 320 31 368\n"" 1402 144 366 307 367\n"" 1403 169 323 250 368\n"" 1404 232 366 89 367\n"" 1405 112 363 17 367\n"" 1406 275 346 344 385\n"" 1407 317 395 371 397\n"" 1408 145 367 307 393\n"" 1409 363 364 233 393\n"" 1410 363 367 112 393\n"" 1411 164 266 100 392\n"" 1412 307 364 238 393\n"" 1413 112 367 312 393\n"" 1414 165 365 113 392\n"" 1415 311 365 178 392\n"" 1416 12 99 164 392\n"" 1417 173 359 274 372\n"" 1418 248 373 116 398\n"" 1419 245 317 42 371\n"" 1420 42 317 152 371\n"" 1421 161 245 42 371\n"" 1422 42 247 161 371\n"" 1423 161 247 246 371\n"" 1424 246 296 161 371\n"" 1425 154 296 246 371\n"" 1426 154 316 296 371\n"" 1427 246 247 154 371\n"" 1428 152 154 35 371\n"" 1429 154 247 35 371\n"" 1430 35 247 152 371\n"" 1431 152 370 154 371\n"" 1432 114 373 248 398\n"" 1433 179 301 155 398\n"" 1434 114 179 70 398\n"" 1435 24 114 70 398\n"" 1436 153 370 152 371\n"" 1437 154 369 316 371\n"" 1438 154 370 369 371\n"" 1439 316 369 153 371\n"" 1440 369 370 153 371\n"" 1441 215 388 287 399\n"" 1442 278 284 84 399\n"" 1443 231 299 140 374\n"" 1444 299 319 140 374\n"" 1445 45 299 230 374\n"" 1446 45 319 299 374\n"" 1447 230 319 45 374\n"" 1448 45 365 249 375\n"" 1449 249 365 181 375\n"" 1450 181 365 45 375\n"" 1451 311 364 69 391\n"" 1452 259 343 111 376\n"" 1453 111 214 175 376\n"" 1454 175 280 261 376\n"" 1455 224 361 151 295\n"" 1456 82 351 331 376\n"" 1457 127 203 109 385\n"" 1458 50 344 127 385\n"" 1459 82 331 261 376\n"" 1460 261 331 175 376\n"" 1461 250 251 108 377\n"" 1462 108 323 250 377\n"" 1463 122 251 250 377\n"" 1464 250 323 122 377\n"" 1465 188 240 186 377\n"" 1466 186 268 188 377\n"" 1467 240 326 57 377\n"" 1468 326 336 57 377\n"" 1469 57 336 240 377\n"" 1470 108 325 253 379\n"" 1471 170 327 253 379\n"" 1472 253 327 108 379\n"" 1473 252 283 170 380\n"" 1474 212 283 88 380\n"" 1475 212 330 283 380\n"" 1476 330 379 283 380\n"" 1477 283 379 170 380\n"" 1478 253 330 67 380\n"" 1479 330 358 67 380\n"" 1480 67 358 253 380\n"" 1481 21 249 162 382\n"" 1482 300 358 141 380\n"" 1483 292 300 141 380\n"" 1484 77 195 96 382\n"" 1485 88 292 212 380\n"" 1486 292 330 212 380\n"" 1487 330 351 259 381\n"" 1488 172 329 259 381\n"" 1489 259 351 172 381\n"" 1490 212 351 330 381\n"" 1491 141 342 328 381\n"" 1492 328 342 258 381\n"" 1493 142 353 226 383\n"" 1494 226 353 19 383\n"" 1495 142 339 271 383\n"" 1496 274 359 173 390\n"" 1497 225 298 297 390\n"" 1498 31 320 214 384\n"" 1499 250 322 320 384\n"" 1500 320 322 214 384\n"" 1501 111 376 343 384\n"" 1502 214 376 111 384\n"" 1503 111 263 214 384\n"" 1504 111 343 263 384\n"" 1505 53 378 227 386\n"" 1506 213 378 53 386\n"" 1507 203 385 275 390\n"" 1508 132 351 284 386\n"" 1509 284 351 280 386\n"" 1510 280 351 132 386\n"" 1511 109 385 203 390\n"" 1512 109 359 297 390\n"" 1513 351 381 212 387\n"" 1514 212 381 281 387\n"" 1515 131 281 82 387\n"" 1516 281 351 82 387\n"" 1517 82 351 131 387\n"" 1518 313 148 323 240\n"" 1519 136 287 215 388\n"" 1520 215 352 136 388\n"" 1521 136 352 54 388\n"" 1522 54 138 136 388\n"" 1523 54 218 138 388\n"" 1524 138 218 136 388\n"" 1525 283 353 142 389\n"" 1526 190 378 118 389\n"" 1527 324 340 270 389\n"" 1528 270 340 118 389\n"" 1529 378 386 213 389\n"" 1530 213 386 324 389\n"" 1531 132 386 353 389\n"" 1532 324 386 132 389\n"" 1533 118 378 213 389\n"" 1534 213 270 118 389\n"" 1535 213 324 270 389\n"" 1536 275 385 345 390\n"" 1537 345 385 109 390\n"" 1538 67 358 329 390\n"" 1539 329 358 274 390\n"" 1540 181 265 95 391\n"" 1541 99 265 181 391\n"" 1542 181 365 99 391\n"" 1543 178 265 99 391\n"" 1544 99 365 178 391\n"" 1545 233 364 310 393\n"" 1546 310 366 233 393\n"" 1547 304 363 233 393\n"" 1548 304 366 363 393\n"" 1549 233 366 304 393\n"" 1550 310 364 307 393\n"" 1551 308 363 176 393\n"" 1552 176 363 112 393\n"" 1553 312 313 262 393\n"" 1554 262 313 308 393\n"" 1555 144 310 307 393\n"" 1556 144 366 310 393\n"" 1557 307 366 144 393\n"" 1558 262 308 176 393\n"" 1559 112 262 176 393\n"" 1560 112 312 262 393\n"" 1561 223 341 274 397\n"" 1562 341 372 274 397\n"" 1563 223 396 341 397\n"" 1564 394 395 372 397\n"" 1565 394 396 395 397\n"" 1566 395 396 371 397\n"" 1567 371 396 293 397\n"" 1568 341 396 394 397\n"" 1569 341 394 20 397\n"" 1570 394 372 20 397\n"" 1571 20 372 341 397\n"" 1572 279 284 278 399\n"" 1573 279 354 284 399\n"" 1574 216 287 282 399\n"" 1575 215 287 216 399\n"" 1576 142 353 284 399\n"" 1577 284 354 142 399\n"" 1578 226 353 142 399\n"" 1579 142 388 226 399\n""# Generated by tetgen -a0.01 cube.smesh \n"); } diff --git a/Demos/SoftDemo/main.cpp b/Demos/SoftDemo/main.cpp new file mode 100644 index 0000000..3408ae3 --- /dev/null +++ b/Demos/SoftDemo/main.cpp @@ -0,0 +1,37 @@ +/* +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 "SoftDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" + +GLDebugDrawer gDebugDrawer; + +int main(int argc,char** argv) +{ + + SoftDemo* softDemo = new SoftDemo(); + + softDemo->initPhysics(); + softDemo->getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + + glutmain(argc, argv,1024,768,"Bullet Physics Demo. http://bulletphysics.com",softDemo); + + delete softDemo; + return 0; + +} diff --git a/Demos/TerrainDemo/Makefile.am b/Demos/TerrainDemo/Makefile.am new file mode 100644 index 0000000..3dbfb10 --- /dev/null +++ b/Demos/TerrainDemo/Makefile.am @@ -0,0 +1,6 @@ + +noinst_PROGRAMS=TerrainDemo + +TerrainDemo_SOURCES=TerrainDemo.cpp TerrainDemo.h main.cpp +TerrainDemo_CXXFLAGS=-I@top_builddir@/src -I@top_builddir@/Demos/OpenGL $(CXXFLAGS) +TerrainDemo_LDADD=-L../OpenGL -lbulletopenglsupport -L../../src -lBulletDynamics -lBulletCollision -lLinearMath @opengl_LIBS@ diff --git a/Demos/TerrainDemo/TerrainDemo.cpp b/Demos/TerrainDemo/TerrainDemo.cpp new file mode 100644 index 0000000..cc32b68 --- /dev/null +++ b/Demos/TerrainDemo/TerrainDemo.cpp @@ -0,0 +1,921 @@ + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006,2008 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 "TerrainDemo.h" // always include our own header first! + +#include "btBulletDynamicsCommon.h" +#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h" + +#include "GLDebugDrawer.h" + +#include "GL_ShapeDrawer.h" + +#include "GlutStuff.h" +#include "GLDebugFont.h" + + + +// constants ------------------------------------------------------------------- +static const float s_gravity = 9.8; // 9.8 m/s^2 + +static const int s_gridSize = 64 + 1; // must be (2^N) + 1 +static const float s_gridSpacing = 5.0; + +static const float s_gridHeightScale = 0.2; + +// the singularity at the center of the radial model means we need a lot of +// finely-spaced time steps to get the physics right. +// These numbers are probably too aggressive for a real game! +static const int s_requestedHz = 180; +static const float s_engineTimeStep = 1.0 / s_requestedHz; + +// delta phase: radians per second +static const float s_deltaPhase = 0.25 * 2.0 * SIMD_PI; + +// what type of terrain is generated? +enum eTerrainModel { + eRadial = 1, // deterministic + eFractal = 2 // random +}; + + +typedef unsigned char byte_t; + + + +//////////////////////////////////////////////////////////////////////////////// +// +// static helper methods +// +// Only used within this file (helpers and terrain generation, etc) +// +//////////////////////////////////////////////////////////////////////////////// + +static const char * +getTerrainTypeName +( +eTerrainModel model +) +{ + switch (model) { + case eRadial: + return "Radial"; + + case eFractal: + return "Fractal"; + + default: + btAssert(!"bad terrain model type"); + } + + return NULL; +} + + + +static const char * +getDataTypeName +( +PHY_ScalarType type +) +{ + switch (type) { + case PHY_UCHAR: + return "UnsignedChar"; + + case PHY_SHORT: + return "Short"; + + case PHY_FLOAT: + return "Float"; + + default: + btAssert(!"bad heightfield data type"); + } + + return NULL; +} + + + +static const char * +getUpAxisName +( +int axis +) +{ + switch (axis) { + case 0: + return "X"; + + case 1: + return "Y"; + + case 2: + return "Z"; + + default: + btAssert(!"bad up axis"); + } + + return NULL; +} + + + +static btVector3 +getUpVector +( +int upAxis, +btScalar regularValue, +btScalar upValue +) +{ + btAssert(upAxis >= 0 && upAxis <= 2 && "bad up axis"); + + btVector3 v(regularValue, regularValue, regularValue); + v[upAxis] = upValue; + + return v; +} + + + +// TODO: it would probably cleaner to have a struct per data type, so +// you could lookup byte sizes, conversion functions, etc. +static int getByteSize +( +PHY_ScalarType type +) +{ + int size = 0; + + switch (type) { + case PHY_FLOAT: + size = sizeof(float); + break; + + case PHY_UCHAR: + size = sizeof(unsigned char); + break; + + case PHY_SHORT: + size = sizeof(short); + break; + + default: + btAssert(!"Bad heightfield data type"); + } + + return size; +} + + + +static float +convertToFloat +( +const byte_t * p, +PHY_ScalarType type +) +{ + btAssert(p); + + switch (type) { + case PHY_FLOAT: + { + float * pf = (float *) p; + return *pf; + } + + case PHY_UCHAR: + { + unsigned char * pu = (unsigned char *) p; + return ((*pu) * s_gridHeightScale); + } + + case PHY_SHORT: + { + short * ps = (short *) p; + return ((*ps) * s_gridHeightScale); + } + + default: + btAssert(!"bad type"); + } + + return 0; +} + + + +static float +getGridHeight +( +byte_t * grid, +int i, +int j, +PHY_ScalarType type +) +{ + btAssert(grid); + btAssert(i >= 0 && i < s_gridSize); + btAssert(j >= 0 && j < s_gridSize); + + int bpe = getByteSize(type); + btAssert(bpe > 0 && "bad bytes per element"); + + int idx = (j * s_gridSize) + i; + long offset = ((long) bpe) * idx; + + byte_t * p = grid + offset; + + return convertToFloat(p, type); +} + + + +static void +convertFromFloat +( +byte_t * p, +float value, +PHY_ScalarType type +) +{ + btAssert(p && "null"); + + switch (type) { + case PHY_FLOAT: + { + float * pf = (float *) p; + *pf = value; + } + break; + + case PHY_UCHAR: + { + unsigned char * pu = (unsigned char *) p; + *pu = (unsigned char) (value / s_gridHeightScale); + } + break; + + case PHY_SHORT: + { + short * ps = (short *) p; + *ps = (short) (value / s_gridHeightScale); + } + break; + + default: + btAssert(!"bad type"); + } +} + + + +// creates a radially-varying heightfield +static void +setRadial +( +byte_t * grid, +int bytesPerElement, +PHY_ScalarType type, +float phase = 0.0 +) +{ + btAssert(grid); + btAssert(bytesPerElement > 0); + + // min/max + float period = 0.5 / s_gridSpacing; + float floor = 0.0; + float min_r = 3.0 * sqrt(s_gridSpacing); + float magnitude = 50.0 * sqrt(s_gridSpacing); + + // pick a base_phase such that phase = 0 results in max height + // (this way, if you create a heightfield with phase = 0, + // you can rely on the min/max heights that result) + float base_phase = (0.5 * SIMD_PI) - (period * min_r); + phase += base_phase; + + // center of grid + float cx = 0.5 * s_gridSize * s_gridSpacing; + float cy = cx; // assume square grid + byte_t * p = grid; + for (int i = 0; i < s_gridSize; ++i) { + float x = i * s_gridSpacing; + for (int j = 0; j < s_gridSize; ++j) { + float y = j * s_gridSpacing; + + float dx = x - cx; + float dy = y - cy; + + float r = sqrt((dx * dx) + (dy * dy)); + + float z = period; + if (r < min_r) { + r = min_r; + } + z = (1.0 / r) * sin(period * r + phase); + if (z > period) { + z = period; + } else if (z < -period) { + z = -period; + } + z = floor + magnitude * z; + + convertFromFloat(p, z, type); + p += bytesPerElement; + } + } +} + + + +static float +randomHeight +( +int step +) +{ + return (0.33 * s_gridSpacing * s_gridSize * step * (rand() - (0.5 * RAND_MAX))) / (1.0 * RAND_MAX * s_gridSize); +} + + + +static void +dumpGrid +( +const byte_t * grid, +int bytesPerElement, +PHY_ScalarType type, +int max +) +{ + //std::cerr << "Grid:\n"; + + char buffer[32]; + + for (int j = 0; j < max; ++j) { + for (int i = 0; i < max; ++i) { + long offset = j * s_gridSize + i; + float z = convertToFloat(grid + offset * bytesPerElement, type); + sprintf(buffer, "%6.2f", z); + //std::cerr << " " << buffer; + } + //std::cerr << "\n"; + } +} + + + +static void +updateHeight +( +byte_t * p, +float new_val, +PHY_ScalarType type +) +{ + float old_val = convertToFloat(p, type); + if (!old_val) { + convertFromFloat(p, new_val, type); + } +} + + + +// creates a random, fractal heightfield +static void +setFractal +( +byte_t * grid, +int bytesPerElement, +PHY_ScalarType type, +int step +) +{ + btAssert(grid); + btAssert(bytesPerElement > 0); + btAssert(step > 0); + btAssert(step < s_gridSize); + + int newStep = step / 2; +// std::cerr << "Computing grid with step = " << step << ": before\n"; +// dumpGrid(grid, bytesPerElement, type, step + 1); + + // special case: starting (must set four corners) + if (s_gridSize - 1 == step) { + // pick a non-zero (possibly negative) base elevation for testing + float base = randomHeight(step / 2); + + convertFromFloat(grid, base, type); + convertFromFloat(grid + step * bytesPerElement, base, type); + convertFromFloat(grid + step * s_gridSize * bytesPerElement, base, type); + convertFromFloat(grid + (step * s_gridSize + step) * bytesPerElement, base, type); + } + + // determine elevation of each corner + float c00 = convertToFloat(grid, type); + float c01 = convertToFloat(grid + step * bytesPerElement, type); + float c10 = convertToFloat(grid + (step * s_gridSize) * bytesPerElement, type); + float c11 = convertToFloat(grid + (step * s_gridSize + step) * bytesPerElement, type); + + // set top middle + updateHeight(grid + newStep * bytesPerElement, 0.5 * (c00 + c01) + randomHeight(step), type); + + // set left middle + updateHeight(grid + (newStep * s_gridSize) * bytesPerElement, 0.5 * (c00 + c10) + randomHeight(step), type); + + // set right middle + updateHeight(grid + (newStep * s_gridSize + step) * bytesPerElement, 0.5 * (c01 + c11) + randomHeight(step), type); + + // set bottom middle + updateHeight(grid + (step * s_gridSize + newStep) * bytesPerElement, 0.5 * (c10 + c11) + randomHeight(step), type); + + // set middle + updateHeight(grid + (newStep * s_gridSize + newStep) * bytesPerElement, 0.25 * (c00 + c01 + c10 + c11) + randomHeight(step), type); + +// std::cerr << "Computing grid with step = " << step << ": after\n"; +// dumpGrid(grid, bytesPerElement, type, step + 1); + + // terminate? + if (newStep < 2) { + return; + } + + // recurse + setFractal(grid, bytesPerElement, type, newStep); + setFractal(grid + newStep * bytesPerElement, bytesPerElement, type, newStep); + setFractal(grid + (newStep * s_gridSize) * bytesPerElement, bytesPerElement, type, newStep); + setFractal(grid + ((newStep * s_gridSize) + newStep) * bytesPerElement, bytesPerElement, type, newStep); +} + + + +static byte_t * +getRawHeightfieldData +( +eTerrainModel model, +PHY_ScalarType type, +btScalar& minHeight, +btScalar& maxHeight +) +{ +// std::cerr << "\nRegenerating terrain\n"; +// std::cerr << " model = " << model << "\n"; +// std::cerr << " type = " << type << "\n"; + + long nElements = ((long) s_gridSize) * s_gridSize; +// std::cerr << " nElements = " << nElements << "\n"; + + int bytesPerElement = getByteSize(type); +// std::cerr << " bytesPerElement = " << bytesPerElement << "\n"; + btAssert(bytesPerElement > 0 && "bad bytes per element"); + + long nBytes = nElements * bytesPerElement; +// std::cerr << " nBytes = " << nBytes << "\n"; + byte_t * raw = new byte_t[nBytes]; + btAssert(raw && "out of memory"); + + // reseed randomization every 30 seconds +// srand(time(NULL) / 30); + + // populate based on model + switch (model) { + case eRadial: + setRadial(raw, bytesPerElement, type); + break; + + case eFractal: + for (int i = 0; i < nBytes; i++) + { + raw[i] = 0; + } + setFractal(raw, bytesPerElement, type, s_gridSize - 1); + break; + + default: + btAssert(!"bad model type"); + } + + if (0) { + // inside if(0) so it keeps compiling but isn't + // exercised and doesn't cause warnings +// std::cerr << "final grid:\n"; + dumpGrid(raw, bytesPerElement, type, s_gridSize - 1); + } + + // find min/max + for (int i = 0; i < s_gridSize; ++i) { + for (int j = 0; j < s_gridSize; ++j) { + float z = getGridHeight(raw, i, j, type); +// std::cerr << "i=" << i << ", j=" << j << ": z=" << z << "\n"; + + // update min/max + if (!i && !j) { + minHeight = z; + maxHeight = z; + } else { + if (z < minHeight) { + minHeight = z; + } + if (z > maxHeight) { + maxHeight = z; + } + } + } + } + + if (maxHeight < -minHeight) { + maxHeight = -minHeight; + } + if (minHeight > -maxHeight) { + minHeight = -maxHeight; + } + +// std::cerr << " minHeight = " << minHeight << "\n"; +// std::cerr << " maxHeight = " << maxHeight << "\n"; + + return raw; +} + + + +//////////////////////////////////////////////////////////////////////////////// +// +// TerrainDemo class +// +//////////////////////////////////////////////////////////////////////////////// + +/// class that demonstrates the btHeightfieldTerrainShape object +class TerrainDemo : public GlutDemoApplication { +public: + // constructor, destructor --------------------------------------------- + TerrainDemo(void); + ~TerrainDemo(void); + + virtual void initPhysics() {} + + // public class methods ------------------------------------------------ + void initialize(void); + + // DemoApplication class interface methods ----------------------------- + void clientMoveAndDisplay(void); + void keyboardCallback(unsigned char key, int x, int y); + void renderme(void); + +private: + // private helper methods ---------------------------------------------- + void resetPhysics(void); + void clearWorld(void); + + // private data members ------------------------------------------------ + btDefaultCollisionConfiguration * m_collisionConfiguration; + btCollisionDispatcher * m_dispatcher; + btAxisSweep3 * m_overlappingPairCache; + btSequentialImpulseConstraintSolver * m_constraintSolver; + btAlignedObjectArray m_collisionShapes; + int m_upAxis; + PHY_ScalarType m_type; + eTerrainModel m_model; + byte_t * m_rawHeightfieldData; + btScalar m_minHeight; + btScalar m_maxHeight; + float m_phase; // for dynamics + bool m_isDynamic; +}; + + + +TerrainDemo::TerrainDemo(void) +: +m_collisionConfiguration(NULL), +m_dispatcher(NULL), +m_overlappingPairCache(NULL), +m_constraintSolver(NULL), +m_upAxis(1), +m_type(PHY_FLOAT), +m_model(eFractal), +m_rawHeightfieldData(NULL), +m_phase(0.0), +m_isDynamic(true) +{ +} + + + +TerrainDemo::~TerrainDemo(void) +{ + clearWorld(); + + //delete dynamics world + delete m_dynamicsWorld; + + //delete solver + delete m_constraintSolver; + + //delete broadphase + delete m_overlappingPairCache; + + //delete dispatcher + delete m_dispatcher; + + delete m_collisionConfiguration; + +} + + + +//////////////////////////////////////////////////////////////////////////////// +// +// TerrainDemo -- public class methods +// +//////////////////////////////////////////////////////////////////////////////// + +/// one-time class and physics initialization +void TerrainDemo::initialize(void) +{ +// std::cerr << "initializing...\n"; + + // set up basic state + m_upAxis = 1; // start with Y-axis as "up" + m_type = PHY_FLOAT; + m_model = eRadial;//eFractal; + m_isDynamic = true; + + // set up the physics world + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + btVector3 worldMin(-1000,-1000,-1000); + btVector3 worldMax(1000,1000,1000); + m_overlappingPairCache = new btAxisSweep3(worldMin,worldMax); + m_constraintSolver = new btSequentialImpulseConstraintSolver(); + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_constraintSolver,m_collisionConfiguration); + + // initialize axis- or type-dependent physics from here + this->resetPhysics(); +} + + + +//////////////////////////////////////////////////////////////////////////////// +// +// TerrainDemo -- DemoApplication class interface methods +// +//////////////////////////////////////////////////////////////////////////////// + +void TerrainDemo::clientMoveAndDisplay(void) +{ + // elapsed time + float us = getDeltaTimeMicroseconds(); + float seconds = 1.0e-6 * us; + + // we'll carefully iterate through each time step so we can update + // the dynamic model if necessary + long nStepsPerIteration = 1; + while (seconds > 1.0e-6) { + float dt = nStepsPerIteration * s_engineTimeStep; + if (dt > seconds) { + dt = seconds; + } + seconds -= dt; + // std::cerr << " Stepping through " << dt << " seconds\n"; + + // if dynamic and radial, go ahead and update the field + if (m_rawHeightfieldData && m_isDynamic && eRadial == m_model) { + m_phase += s_deltaPhase * dt; + if (m_phase > 2.0 * SIMD_PI) { + m_phase -= 2.0 * SIMD_PI; + } + int bpe = getByteSize(m_type); + btAssert(bpe > 0 && "Bad bytes per element"); + setRadial(m_rawHeightfieldData, bpe, m_type, m_phase); + } + + if (m_dynamicsWorld) { + m_dynamicsWorld->stepSimulation(dt, + nStepsPerIteration + 1, s_engineTimeStep); + } + } + + // okay, render + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + renderme(); + glFlush(); + glutSwapBuffers(); +} + + +static PHY_ScalarType nextType (PHY_ScalarType type) +{ + switch (type) + { + case PHY_FLOAT: + return PHY_SHORT; + break; + case PHY_SHORT: + return PHY_UCHAR; + break; + case PHY_UCHAR: + return PHY_FLOAT; + break; + } + btAssert (0); + return PHY_FLOAT; +} + +void TerrainDemo::keyboardCallback(unsigned char key, int x, int y) { + + if (',' == key) { + // increment model + m_model = (eFractal == m_model) ? eRadial : eFractal; + this->resetPhysics(); + } + if ('/' == key) { + // increment type + m_type = nextType(m_type); + this->resetPhysics(); + } + if ('\\' == key) { + // increment axis + m_upAxis++; + if (m_upAxis > 2) { + m_upAxis = 0; + } + this->resetPhysics(); + } + if ('[' == key) { + // toggle dynamics + m_isDynamic = !m_isDynamic; + } + + // let demo base class handle! + DemoApplication::keyboardCallback(key, x, y); +} + + + +static void doPrint(int x,int& y,int dy,const char * text) +{ + GLDebugDrawString(x,y, text); + y += dy; +} + + + +/// override the default display just so we can overlay a bit more text +void TerrainDemo::renderme(void) +{ + // give base class a shot + DemoApplication::renderme(); + + // overlay any debug information + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + // switch to orthographic + setOrthographicProjection(); + + // we'll draw on the right top of the screen + const int lineWidth = 200; + const int lineHeight = 16; + char buffer[256]; + + int xStart = m_glutScreenWidth - lineWidth; + int yStart = lineHeight; + + sprintf(buffer, "Terrain Type: %s", getTerrainTypeName(m_model)); + doPrint(xStart, yStart, lineHeight, buffer); + doPrint(xStart, yStart, lineHeight, "Press ',' to cycle terrain types"); + doPrint(xStart, yStart, lineHeight, ""); + + sprintf(buffer, "Data Type: %s", getDataTypeName(m_type)); + doPrint(xStart, yStart, lineHeight, buffer); + doPrint(xStart, yStart, lineHeight, "Press '/' to cycle data types"); + doPrint(xStart, yStart, lineHeight, ""); + + sprintf(buffer, "'up' axis: %s", getUpAxisName(m_upAxis)); + doPrint(xStart, yStart, lineHeight, buffer); + doPrint(xStart, yStart, lineHeight, "Press '\\' to cycle 'up' axes"); + doPrint(xStart, yStart, lineHeight, ""); + + if (eRadial == m_model) { + sprintf(buffer, "Dynamic: %s", m_isDynamic ? "yes" : "no"); + doPrint(xStart, yStart, lineHeight, buffer); + doPrint(xStart, yStart, lineHeight, "Press '[' to toggle dynamics"); + } +} + + + +//////////////////////////////////////////////////////////////////////////////// +// +// TerrainDemo -- private helper methods +// +//////////////////////////////////////////////////////////////////////////////// + +/// called whenever key terrain attribute is changed +void TerrainDemo::resetPhysics(void) +{ + // remove old heightfield + clearWorld(); + + // reset gravity to point in appropriate direction + m_dynamicsWorld->setGravity(getUpVector(m_upAxis, 0.0, -s_gravity)); + + // get new heightfield of appropriate type + m_rawHeightfieldData = + getRawHeightfieldData(m_model, m_type, m_minHeight, m_maxHeight); + btAssert(m_rawHeightfieldData && "failed to create raw heightfield"); + + bool flipQuadEdges = false; + btHeightfieldTerrainShape * heightfieldShape = + new btHeightfieldTerrainShape(s_gridSize, s_gridSize, + m_rawHeightfieldData, + s_gridHeightScale, + m_minHeight, m_maxHeight, + m_upAxis, m_type, flipQuadEdges); + btAssert(heightfieldShape && "null heightfield"); + + // scale the shape + btVector3 localScaling = getUpVector(m_upAxis, s_gridSpacing, 1.0); + heightfieldShape->setLocalScaling(localScaling); + + // stash this shape away + m_collisionShapes.push_back(heightfieldShape); + + // set origin to middle of heightfield + btTransform tr; + tr.setIdentity(); + tr.setOrigin(btVector3(0,-20,0)); + + // create ground object + float mass = 0.0; + localCreateRigidBody(mass, tr, heightfieldShape); +} + + +/// removes all objects and shapes from the world +void TerrainDemo::clearWorld(void) +{ + //remove the rigidbodies from the dynamics world and delete them + int 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;jinitialize(); + + return demo; +} + diff --git a/Demos/TerrainDemo/TerrainDemo.h b/Demos/TerrainDemo/TerrainDemo.h new file mode 100644 index 0000000..1b6a3e6 --- /dev/null +++ b/Demos/TerrainDemo/TerrainDemo.h @@ -0,0 +1,27 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006,2008 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 TERRAIN_DEMO_H +#define TERRAIN_DEMO_H + + +#include "GlutDemoApplication.h" + + +// all we need to expose publicly is the factory method! +GlutDemoApplication * btCreateTerrainDemo(void); + + +#endif //TERRAIN_DEMO_H + diff --git a/Demos/TerrainDemo/main.cpp b/Demos/TerrainDemo/main.cpp new file mode 100644 index 0000000..6510f24 --- /dev/null +++ b/Demos/TerrainDemo/main.cpp @@ -0,0 +1,14 @@ + +#include "TerrainDemo.h" +#include "GlutStuff.h" + +int main(int argc,char** argv) +{ + DemoApplication * demo = btCreateTerrainDemo(); + btAssert(demo && "failed to create terrain demo object"); + + return glutmain(argc, argv, 800, 600, + "Terrain Demo. http://www.continuousphysics.com/Bullet/phpBB2/", + demo); +} + diff --git a/Demos/ThreadingDemo/CMakeLists.txt b/Demos/ThreadingDemo/CMakeLists.txt new file mode 100644 index 0000000..b27cce4 --- /dev/null +++ b/Demos/ThreadingDemo/CMakeLists.txt @@ -0,0 +1,47 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# This is the variable for Windows. I use this to define the root of my directory structure. +SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/Glut) + +# You shouldn't have to modify anything below this line +######################################################## + +#currently this demo has only been tested under Windows 32bit +#IF (WIN32) + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL + ${VECTOR_MATH_INCLUDE} +) + +LINK_LIBRARIES( +BulletMultiThreaded BulletDynamics BulletCollision LinearMath +) + +IF (WIN32) +ADD_EXECUTABLE(AppThreadingDemo + main.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) +ELSE() + ADD_EXECUTABLE(AppThreadingDemo + main.cpp + ) +ENDIF() + +IF (UNIX) + TARGET_LINK_LIBRARIES(AppThreadingDemo pthread) +ENDIF(UNIX) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppThreadingDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppThreadingDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppThreadingDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + +#ENDIF(WIN32) diff --git a/Demos/ThreadingDemo/main.cpp b/Demos/ThreadingDemo/main.cpp new file mode 100644 index 0000000..0bd6d68 --- /dev/null +++ b/Demos/ThreadingDemo/main.cpp @@ -0,0 +1,177 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2010 Erwin Coumans http://bulletphysics.org + +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. +*/ + +/// ThreadingDemo shows how to use the cross platform thread support interface. +/// You can start threads and perform a blocking wait for completion +/// Under Windows it uses Win32 Threads. On Mac and Linux it uses pthreads. On PlayStation 3 Cell SPU it uses SPURS. + +/// June 2010 +/// New: critical section/barriers and non-blocking pollingn for completion, currently Windows only + +void SampleThreadFunc(void* userPtr,void* lsMemory); +void* SamplelsMemoryFunc(); + +#include +#include "BulletMultiThreaded/PlatformDefinitions.h" + +#ifdef USE_PTHREADS +//#ifdef __APPLE__ +#include "BulletMultiThreaded/PosixThreadSupport.h" + +btThreadSupportInterface* createThreadSupport(int numThreads) +{ + PosixThreadSupport::ThreadConstructionInfo constructionInfo("testThreads", + SampleThreadFunc, + SamplelsMemoryFunc, + numThreads); + btThreadSupportInterface* threadSupport = new PosixThreadSupport(constructionInfo); + + return threadSupport; + +} + + +#elif defined( _WIN32) +#include "BulletMultiThreaded/Win32ThreadSupport.h" + +btThreadSupportInterface* createThreadSupport(int numThreads) +{ + Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("testThreads",SampleThreadFunc,SamplelsMemoryFunc,numThreads); + Win32ThreadSupport* threadSupport = new Win32ThreadSupport(threadConstructionInfo); + return threadSupport; + +} + +#endif + + +struct SampleArgs +{ + btCriticalSection* m_cs; +}; + +struct SampleThreadLocalStorage +{ + int threadId; +}; + + +void SampleThreadFunc(void* userPtr,void* lsMemory) +{ + printf("thread started\n"); + + SampleThreadLocalStorage* localStorage = (SampleThreadLocalStorage*) lsMemory; + + SampleArgs* args = (SampleArgs*) userPtr; + int workLeft = true; + while (workLeft) + { + args->m_cs->lock(); + int count = args->m_cs->getSharedParam(0); + args->m_cs->setSharedParam(0,count-1); + args->m_cs->unlock(); + if (count>0) + { + printf("thread %d processed number %d\n",localStorage->threadId, count); + } + workLeft = count>0; + } + printf("finished\n"); + //do nothing +} + + +void* SamplelsMemoryFunc() +{ + //don't create local store memory, just return 0 + return new SampleThreadLocalStorage; +} + + + + + + + + + + +int main(int argc,char** argv) +{ + int numThreads = 4; + + btThreadSupportInterface* threadSupport = createThreadSupport(numThreads); + + + threadSupport->startSPU(); + + for (int i=0;igetNumTasks();i++) + { + SampleThreadLocalStorage* storage = (SampleThreadLocalStorage*)threadSupport->getThreadLocalMemory(i); + btAssert(storage); + storage->threadId = i; + } + + + SampleArgs args; + args.m_cs = threadSupport->createCriticalSection(); + args.m_cs->setSharedParam(0,100); + + + unsigned int arg0,arg1; + int i; + for (i=0;isendRequest(1, (ppu_address_t) &args, i); + } + + bool blockingWait =true; + if (blockingWait) + { + for (i=0;iwaitForResponse(&arg0,&arg1); + printf("finished waiting for response: %d %d\n", arg0,arg1); + } + } else + { +#if _WIN32 + int numActiveThreads = numThreads; + while (numActiveThreads) + { + if (((Win32ThreadSupport*)threadSupport)->isTaskCompleted(&arg0,&arg1,0)) + { + numActiveThreads--; + printf("numActiveThreads = %d\n",numActiveThreads); + + } else + { + printf("polling\n"); + } + }; +#else + btAssert(0); + printf("non-blocking wait is not supported on this platform\n"); + exit(0); +#endif + } + +printf("stopping threads\n"); + + delete threadSupport; + printf("Press ENTER to quit\n"); + getchar(); + return 0; +} diff --git a/Demos/UserCollisionAlgorithm/CMakeLists.txt b/Demos/UserCollisionAlgorithm/CMakeLists.txt new file mode 100644 index 0000000..47dc74f --- /dev/null +++ b/Demos/UserCollisionAlgorithm/CMakeLists.txt @@ -0,0 +1,38 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +IF (WIN32) + ADD_EXECUTABLE(AppUserCollisionAlgorithm + UserCollisionAlgorithm.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) +ELSE() + ADD_EXECUTABLE(AppUserCollisionAlgorithm + UserCollisionAlgorithm.cpp + ) +ENDIF() + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppUserCollisionAlgorithm PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppUserCollisionAlgorithm PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppUserCollisionAlgorithm PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/UserCollisionAlgorithm/UserCollisionAlgorithm.cpp b/Demos/UserCollisionAlgorithm/UserCollisionAlgorithm.cpp new file mode 100644 index 0000000..5d094f2 --- /dev/null +++ b/Demos/UserCollisionAlgorithm/UserCollisionAlgorithm.cpp @@ -0,0 +1,175 @@ +/* +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 "GLDebugDrawer.h" +#include "UserCollisionAlgorithm.h" +#include "GL_ShapeDrawer.h" +#include "GlutStuff.h" + +//The user defined collision algorithm +#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" + +GLDebugDrawer debugDrawer; + +static const int NUM_VERTICES = 5; +static const int NUM_TRIANGLES=4; + +btVector3 gVertices[NUM_VERTICES]; +int gIndices[NUM_TRIANGLES*3]; +const float TRIANGLE_SIZE=10.f; + + +///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; +inline btScalar calculateCombinedFriction(float friction0,float friction1) +{ + btScalar friction = friction0 * friction1; + + const btScalar MAX_FRICTION = 10.f; + if (friction < -MAX_FRICTION) + friction = -MAX_FRICTION; + if (friction > MAX_FRICTION) + friction = MAX_FRICTION; + return friction; + +} + +inline btScalar calculateCombinedRestitution(float restitution0,float restitution1) +{ + return restitution0 * restitution1; +} + + + + + + +int main(int argc,char** argv) +{ + + UserCollisionAlgorithm* userCollisionAlgorithm = new UserCollisionAlgorithm; + userCollisionAlgorithm->initPhysics(); + userCollisionAlgorithm->setCameraDistance(30.f); + + return glutmain(argc, argv,640,480,"Static Concave Mesh Demo",userCollisionAlgorithm); +} + +void UserCollisionAlgorithm::initPhysics() +{ + #define TRISIZE 5.f + + + const int NUM_VERTS_X = 50; + const int NUM_VERTS_Y = 50; + const int totalVerts = NUM_VERTS_X*NUM_VERTS_Y; + + btVector3* gVertices = new btVector3[totalVerts]; + + int i; + for ( i=0;iaddTriangle(gVertices[j*NUM_VERTS_X+i],gVertices[j*NUM_VERTS_X+i+1],gVertices[(j+1)*NUM_VERTS_X+i+1]); + trimesh->addTriangle(gVertices[j*NUM_VERTS_X+i],gVertices[(j+1)*NUM_VERTS_X+i+1],gVertices[(j+1)*NUM_VERTS_X+i]); + } + } + + delete[] gVertices; + + bool useQuantizedBvhTree = true; + btCollisionShape* trimeshShape = new btBvhTriangleMeshShape(trimesh,useQuantizedBvhTree); + + //ConstraintSolver* solver = new btSequentialImpulseConstraintSolver; + btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration(); + btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration); + + btVector3 maxAabb(10000,10000,10000); + btBroadphaseInterface* broadphase = new btAxisSweep3(-maxAabb,maxAabb);//SimpleBroadphase(); + dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE,GIMPACT_SHAPE_PROXYTYPE,new btSphereSphereCollisionAlgorithm::CreateFunc); + + btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver(); + m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,constraintSolver,collisionConfiguration); + + float mass = 0.f; + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(0,-2,0)); + + btRigidBody* staticBody= localCreateRigidBody(mass, startTransform,trimeshShape); + //enable custom material callback + staticBody->setCollisionFlags(staticBody->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + + { + for (int i=0;i<10;i++) + { + btCollisionShape* sphereShape = new btSphereShape(1); + startTransform.setOrigin(btVector3(1,2*i,1)); + //btRigidBody* body = localCreateRigidBody(1, startTransform,sphereShape); + localCreateRigidBody(1, startTransform,sphereShape); + } + } + + + + m_dynamicsWorld->setDebugDrawer(&debugDrawer); +} + +void UserCollisionAlgorithm::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + float dt = getDeltaTimeMicroseconds() * 0.000001f; + + + m_dynamicsWorld->stepSimulation(dt); + + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + + renderme(); + + glFlush(); + glutSwapBuffers(); + +} + + + + + + +void UserCollisionAlgorithm::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + glFlush(); + glutSwapBuffers(); +} + + diff --git a/Demos/UserCollisionAlgorithm/UserCollisionAlgorithm.h b/Demos/UserCollisionAlgorithm/UserCollisionAlgorithm.h new file mode 100644 index 0000000..acfa37c --- /dev/null +++ b/Demos/UserCollisionAlgorithm/UserCollisionAlgorithm.h @@ -0,0 +1,36 @@ +/* +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 USER_COLLISION_ALGORITHM_DEMO_H +#define USER_COLLISION_ALGORITHM_DEMO_H + +#include "GlutDemoApplication.h" + +///UserCollisionAlgorithmDemo shows how to register and use your own collision algorithm for a certain shape pair type +class UserCollisionAlgorithm : public GlutDemoApplication +{ + public: + + void initPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + + +}; + +#endif //USER_COLLISION_ALGORITHM_DEMO_H + diff --git a/Demos/VectorAdd_OpenCL/AMD/CMakeLists.txt b/Demos/VectorAdd_OpenCL/AMD/CMakeLists.txt new file mode 100644 index 0000000..68fcf19 --- /dev/null +++ b/Demos/VectorAdd_OpenCL/AMD/CMakeLists.txt @@ -0,0 +1,34 @@ + + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${AMD_OPENCL_INCLUDES} +) + +LINK_LIBRARIES( + BulletMultiThreaded LinearMath + ${CMAKE_ATISTREAMSDK_LIBPATH}/OpenCL.lib +) + +ADD_EXECUTABLE(AppVectorAdd_AMD +../MiniCL_VectorAdd.cpp +../VectorAddKernels.cl +) + +IF (UNIX) + TARGET_LINK_LIBRARIES(AppVectorAdd_AMD pthread) +ENDIF(UNIX) + +IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( + TARGET AppVectorAdd_AMD + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Demos/VectorAdd_OpenCL/VectorAddKernels.cl ${CMAKE_CURRENT_BINARY_DIR} + ) +ENDIF() + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppVectorAdd_AMD PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppVectorAdd_AMD PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppVectorAdd_AMD PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/VectorAdd_OpenCL/Apple/CMakeLists.txt b/Demos/VectorAdd_OpenCL/Apple/CMakeLists.txt new file mode 100644 index 0000000..521c3b4 --- /dev/null +++ b/Demos/VectorAdd_OpenCL/Apple/CMakeLists.txt @@ -0,0 +1,25 @@ +# AppVectorAdd is a very basic test OpenCL/MiniCL. + +IF (APPLE) + FIND_LIBRARY(OPENCL_LIBRARY OpenCL DOC "OpenCL lib for OSX") + FIND_PATH(OPENCL_INCLUDE_DIR OpenCL/cl.h DOC "Include for OpenCL on OSX") +ENDIF (APPLE) + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +) + +LINK_LIBRARIES( + LinearMath ${OPENCL_LIBRARY} +) + +ADD_EXECUTABLE(AppVectorAdd_Apple +../MiniCL_VectorAdd.cpp +../VectorAddKernels.cl +) + +IF (UNIX) + TARGET_LINK_LIBRARIES(AppVectorAdd_Apple pthread) +ENDIF(UNIX) + diff --git a/Demos/VectorAdd_OpenCL/CMakeLists.txt b/Demos/VectorAdd_OpenCL/CMakeLists.txt new file mode 100644 index 0000000..8f59145 --- /dev/null +++ b/Demos/VectorAdd_OpenCL/CMakeLists.txt @@ -0,0 +1,16 @@ + +IF(BUILD_MINICL_OPENCL_DEMOS) + SUBDIRS( MiniCL ) +ENDIF() + +IF(BUILD_AMD_OPENCL_DEMOS) + SUBDIRS(AMD) +ENDIF() + +IF(BUILD_NVIDIA_OPENCL_DEMOS) + SUBDIRS(NVidia) +ENDIF() + +IF(APPLE) + SUBDIRS(Apple) +ENDIF() diff --git a/Demos/VectorAdd_OpenCL/MiniCL/CMakeLists.txt b/Demos/VectorAdd_OpenCL/MiniCL/CMakeLists.txt new file mode 100644 index 0000000..d0c4863 --- /dev/null +++ b/Demos/VectorAdd_OpenCL/MiniCL/CMakeLists.txt @@ -0,0 +1,38 @@ +# AppMiniCLVectorAdd is a very basic test for MiniCL. + + +ADD_DEFINITIONS(-DUSE_MINICL) + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +) + +LINK_LIBRARIES( + MiniCL + BulletMultiThreaded + LinearMath +) + +ADD_EXECUTABLE(AppVectorAdd_Mini +../MiniCL_VectorAdd.cpp +../VectorAddKernels.cl +) + +IF (UNIX) + TARGET_LINK_LIBRARIES(AppVectorAdd_Mini pthread) +ENDIF(UNIX) + + +IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( + TARGET AppVectorAdd_Mini + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Demos/VectorAdd_OpenCL/VectorAddKernels.cl ${CMAKE_CURRENT_BINARY_DIR} + ) +ENDIF() + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppVectorAdd_Mini PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppVectorAdd_Mini PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppVectorAdd_Mini PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/VectorAdd_OpenCL/MiniCL_VectorAdd.cpp b/Demos/VectorAdd_OpenCL/MiniCL_VectorAdd.cpp new file mode 100644 index 0000000..ab9fd7f --- /dev/null +++ b/Demos/VectorAdd_OpenCL/MiniCL_VectorAdd.cpp @@ -0,0 +1,389 @@ + +///VectorAdd sample, from the NVidia JumpStart Guide +///http://developer.download.nvidia.com/OpenCL/NVIDIA_OpenCL_JumpStart_Guide.pdf + +///Instead of #include we include +///Apart from this include file, all other code should compile and work on OpenCL compliant implementation + + +//#define LOAD_FROM_FILE + +#ifdef USE_MINICL + #include "MiniCL/cl.h" +#else //USE_MINICL + #ifdef __APPLE__ + #include + #else + #include + #endif //__APPLE__ +#endif//USE_MINICL + +#include +#include +#include +#include +#include "LinearMath/btMinMax.h" +#define GRID3DOCL_CHECKERROR(a, b) if((a)!=(b)) { printf("3D GRID OCL Error : %d\n", (a)); btAssert((a) == (b)); } +size_t wgSize; + + +#ifndef USE_MINICL +#define MSTRINGIFY(A) #A +const char* stringifiedSourceCL = +#include "VectorAddKernels.cl" +#else +const char* stringifiedSourceCL = ""; +#endif + + + + +char* loadProgSource(const char* cFilename, const char* cPreamble, size_t* szFinalLength) +{ + // locals + FILE* pFileStream = NULL; + size_t szSourceLength; + + // open the OpenCL source code file + pFileStream = fopen(cFilename, "rb"); + if(pFileStream == 0) + { + return NULL; + } + + size_t szPreambleLength = strlen(cPreamble); + + // get the length of the source code + fseek(pFileStream, 0, SEEK_END); + szSourceLength = ftell(pFileStream); + fseek(pFileStream, 0, SEEK_SET); + + // allocate a buffer for the source code string and read it in + char* cSourceString = (char *)malloc(szSourceLength + szPreambleLength + 1); + memcpy(cSourceString, cPreamble, szPreambleLength); + fread((cSourceString) + szPreambleLength, szSourceLength, 1, pFileStream); + + // close the file and return the total length of the combined (preamble + source) string + fclose(pFileStream); + if(szFinalLength != 0) + { + *szFinalLength = szSourceLength + szPreambleLength; + } + cSourceString[szSourceLength + szPreambleLength] = '\0'; + + return cSourceString; +} + +size_t workitem_size[3]; + +void printDevInfo(cl_device_id device) +{ + char device_string[1024]; + + clGetDeviceInfo(device, CL_DEVICE_NAME, sizeof(device_string), &device_string, NULL); + printf( " Device %s:\n", device_string); + + // CL_DEVICE_INFO + cl_device_type type; + clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(type), &type, NULL); + if( type & CL_DEVICE_TYPE_CPU ) + printf(" CL_DEVICE_TYPE:\t\t%s\n", "CL_DEVICE_TYPE_CPU"); + if( type & CL_DEVICE_TYPE_GPU ) + printf( " CL_DEVICE_TYPE:\t\t%s\n", "CL_DEVICE_TYPE_GPU"); + if( type & CL_DEVICE_TYPE_ACCELERATOR ) + printf( " CL_DEVICE_TYPE:\t\t%s\n", "CL_DEVICE_TYPE_ACCELERATOR"); + if( type & CL_DEVICE_TYPE_DEFAULT ) + printf( " CL_DEVICE_TYPE:\t\t%s\n", "CL_DEVICE_TYPE_DEFAULT"); + + // CL_DEVICE_MAX_COMPUTE_UNITS + cl_uint compute_units; + clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(compute_units), &compute_units, NULL); + printf( " CL_DEVICE_MAX_COMPUTE_UNITS:\t%d\n", compute_units); + + // CL_DEVICE_MAX_WORK_GROUP_SIZE + + clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(workitem_size), &workitem_size, NULL); + printf( " CL_DEVICE_MAX_WORK_ITEM_SIZES:\t%zu / %zu / %zu \n", workitem_size[0], workitem_size[1], workitem_size[2]); + +} + + + + +// Main function +// ********************************************************************* +int main(int argc, char **argv) +{ + void *srcA, *srcB, *dst; // Host buffers for OpenCL test + cl_context cxGPUContext; // OpenCL context + cl_command_queue cqCommandQue; // OpenCL command que + cl_device_id* cdDevices; // OpenCL device list + cl_program cpProgram; // OpenCL program + cl_kernel ckKernel; // OpenCL kernel + cl_mem cmMemObjs[3]; // OpenCL memory buffer objects: 3 for device + size_t szGlobalWorkSize[1]; // 1D var for Total # of work items + size_t szLocalWorkSize[1]; // 1D var for # of work items in the work group + size_t szParmDataBytes; // Byte size of context information + cl_int ciErr1, ciErr2; // Error code var + int iTestN = 100000 * 8; // Size of Vectors to process + + int actualGlobalSize = iTestN>>3; + + // set Global and Local work size dimensions + szGlobalWorkSize[0] = iTestN >> 3; // do 8 computations per work item + szLocalWorkSize[0]= iTestN>>3; + + + // Allocate and initialize host arrays + srcA = (void *)malloc (sizeof(cl_float) * iTestN); + srcB = (void *)malloc (sizeof(cl_float) * iTestN); + dst = (void *)malloc (sizeof(cl_float) * iTestN); + + int i; + + // Initialize arrays with some values + for (i=0;i processing outside of the buffer + //make sure to check kernel + } + + size_t globalThreads[] = {num_t * workgroupSize}; + size_t localThreads[] = {workgroupSize}; + + + localWorkSize[0] = workgroupSize; + globalWorkSize[0] = num_t * workgroupSize; + localWorkSize[1] = 1; + globalWorkSize[1] = 1; + + // Copy input data from host to GPU and launch kernel + ciErr1 |= clEnqueueNDRangeKernel(cqCommandQue, ckKernel, 1, NULL, globalThreads, localThreads, 0, NULL, NULL); + + } + + if (ciErrNum != CL_SUCCESS) + { + printf("cannot clEnqueueNDRangeKernel\n"); + exit(0); + } + + clFinish(cqCommandQue); + // Read back results and check accumulated errors + ciErr1 |= clEnqueueReadBuffer(cqCommandQue, cmMemObjs[2], CL_TRUE, 0, sizeof(cl_float8) * szGlobalWorkSize[0], dst, 0, NULL, NULL); + + // Release kernel, program, and memory objects + // NOTE: Most properly this should be done at any of the exit points above, but it is omitted elsewhere for clarity. + free(cdDevices); + clReleaseKernel(ckKernel); + clReleaseProgram(cpProgram); + clReleaseCommandQueue(cqCommandQue); + clReleaseContext(cxGPUContext); + + + // print the results + int iErrorCount = 0; + for (i = 0; i < iTestN; i++) + { + if (((float*)dst)[i] != ((float*)srcA)[i]+((float*)srcB)[i]) + iErrorCount++; + } + + if (iErrorCount) + { + printf("MiniCL validation FAILED\n"); + } else + { + printf("MiniCL validation SUCCESSFULL\n"); + } + // Free host memory, close log and return success + for (i = 0; i < 3; i++) + { + clReleaseMemObject(cmMemObjs[i]); + } + + free(srcA); + free(srcB); + free (dst); + printf("Press ENTER to quit\n"); + getchar(); +} + + +#ifdef USE_MINICL + +#include "MiniCL/cl_MiniCL_Defs.h" + +extern "C" +{ + ///GUID_ARG is only used by MiniCL to pass in the guid used by its get_global_id implementation + + + #define MSTRINGIFY(A) A + #include "VectorAddKernels.cl" + #undef MSTRINGIFY +} +MINICL_REGISTER(VectorAdd) +#endif//USE_MINICL diff --git a/Demos/VectorAdd_OpenCL/NVidia/CMakeLists.txt b/Demos/VectorAdd_OpenCL/NVidia/CMakeLists.txt new file mode 100644 index 0000000..f23717b --- /dev/null +++ b/Demos/VectorAdd_OpenCL/NVidia/CMakeLists.txt @@ -0,0 +1,28 @@ + + + + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${NVIDIA_OPENCL_INCLUDES} +) + +LINK_LIBRARIES( + LinearMath + ${NVIDIA_OPENCL_LIBRARIES} +) + +ADD_EXECUTABLE(AppVectorAdd_NVidia +../MiniCL_VectorAdd.cpp +../VectorAddKernels.cl +) + +IF (UNIX) + TARGET_LINK_LIBRARIES(AppVectorAdd_NVidia pthread) +ENDIF(UNIX) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppVectorAdd_NVidia PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppVectorAdd_NVidia PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppVectorAdd_NVidia PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/VectorAdd_OpenCL/VectorAddKernels.cl b/Demos/VectorAdd_OpenCL/VectorAddKernels.cl new file mode 100644 index 0000000..03f13a9 --- /dev/null +++ b/Demos/VectorAdd_OpenCL/VectorAddKernels.cl @@ -0,0 +1,35 @@ + + +MSTRINGIFY( + +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006 - 2009 Sony Computer Entertainment Inc. + +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. +*/ + + + +/////////////////////////////////////////////////// +// OpenCL Kernel Function for element by element vector addition +__kernel void VectorAdd(__global const float8* a, __global const float8* b, __global float8* c GUID_ARG) +{ + // get oct-float index into global data array + int iGID = get_global_id(0); + if (iGID>=100000) + return; + + // write back out to GMEM + c[iGID] = a[iGID] + b[iGID]; +} + +); \ No newline at end of file diff --git a/Demos/VehicleDemo/CMakeLists.txt b/Demos/VehicleDemo/CMakeLists.txt new file mode 100644 index 0000000..744b73d --- /dev/null +++ b/Demos/VehicleDemo/CMakeLists.txt @@ -0,0 +1,31 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + + +# You shouldn't have to modify anything below this line +######################################################## + + + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + +LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} +) + +ADD_EXECUTABLE(AppVehicleDemo + VehicleDemo.cpp + main.cpp +) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppVehicleDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppVehicleDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppVehicleDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/VehicleDemo/Makefile.am b/Demos/VehicleDemo/Makefile.am new file mode 100644 index 0000000..89e5bca --- /dev/null +++ b/Demos/VehicleDemo/Makefile.am @@ -0,0 +1,5 @@ +noinst_PROGRAMS=VehicleDemo + +VehicleDemo_SOURCES=VehicleDemo.cpp VehicleDemo.h main.cpp +VehicleDemo_CXXFLAGS=-I@top_builddir@/src -I@top_builddir@/Demos/OpenGL $(CXXFLAGS) +VehicleDemo_LDADD=-L../OpenGL -lbulletopenglsupport -L../../src -lBulletDynamics -lBulletCollision -lLinearMath @opengl_LIBS@ diff --git a/Demos/VehicleDemo/VehicleDemo.cpp b/Demos/VehicleDemo/VehicleDemo.cpp new file mode 100644 index 0000000..2dfb990 --- /dev/null +++ b/Demos/VehicleDemo/VehicleDemo.cpp @@ -0,0 +1,671 @@ +/* +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. +*/ + +/// September 2006: VehicleDemo is work in progress, this file is mostly just a placeholder +/// This VehicleDemo file is very early in development, please check it later +/// One todo is a basic engine model: +/// A function that maps user input (throttle) into torque/force applied on the wheels +/// with gears etc. +#include "btBulletDynamicsCommon.h" +#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h" + +// +// By default, Bullet Vehicle uses Y as up axis. +// You can override the up axis, for example Z-axis up. Enable this define to see how to: +//#define FORCE_ZAXIS_UP 1 +// + +#ifdef FORCE_ZAXIS_UP + int rightIndex = 0; + int upIndex = 2; + int forwardIndex = 1; + btVector3 wheelDirectionCS0(0,0,-1); + btVector3 wheelAxleCS(1,0,0); +#else + int rightIndex = 0; + int upIndex = 1; + int forwardIndex = 2; + btVector3 wheelDirectionCS0(0,-1,0); + btVector3 wheelAxleCS(-1,0,0); +#endif + +#include "GLDebugDrawer.h" +#include //printf debugging + +#include "GL_ShapeDrawer.h" + +#include "GlutStuff.h" +#include "VehicleDemo.h" + +const int maxProxies = 32766; +const int maxOverlap = 65535; + +///btRaycastVehicle is the interface for the constraint that implements the raycast vehicle +///notice that for higher-quality slow-moving vehicles, another approach might be better +///implementing explicit hinged-wheel constraints with cylinder collision, rather then raycasts +float gEngineForce = 0.f; +float gBreakingForce = 0.f; + +float maxEngineForce = 1000.f;//this should be engine/velocity dependent +float maxBreakingForce = 100.f; + +float gVehicleSteering = 0.f; +float steeringIncrement = 0.04f; +float steeringClamp = 0.3f; +float wheelRadius = 0.5f; +float wheelWidth = 0.4f; +float wheelFriction = 1000;//BT_LARGE_FLOAT; +float suspensionStiffness = 20.f; +float suspensionDamping = 2.3f; +float suspensionCompression = 4.4f; +float rollInfluence = 0.1f;//1.0f; + + +btScalar suspensionRestLength(0.6); + +#define CUBE_HALF_EXTENTS 1 + + + +//////////////////////////////////// + + + + +VehicleDemo::VehicleDemo() +: +m_carChassis(0), +m_indexVertexArrays(0), +m_vertices(0), +m_cameraHeight(4.f), +m_minCameraDistance(3.f), +m_maxCameraDistance(10.f) +{ + m_vehicle = 0; + m_wheelShape = 0; + m_cameraPosition = btVector3(30,30,30); +} + +VehicleDemo::~VehicleDemo() +{ + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;jsetGravity(btVector3(0,0,-10)); +#endif + + //m_dynamicsWorld->setGravity(btVector3(0,0,0)); +btTransform tr; +tr.setIdentity(); + +//either use heightfield or triangle mesh +#define USE_TRIMESH_GROUND 1 +#ifdef USE_TRIMESH_GROUND + int i; + +const float TRIANGLE_SIZE=20.f; + + //create a triangle-mesh ground + int vertStride = sizeof(btVector3); + int indexStride = 3*sizeof(int); + + const int NUM_VERTS_X = 20; + const int NUM_VERTS_Y = 20; + const int totalVerts = NUM_VERTS_X*NUM_VERTS_Y; + + const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1); + + m_vertices = new btVector3[totalVerts]; + int* gIndices = new int[totalTriangles*3]; + + + + for ( i=0;isetUseDiamondSubdivision(true); + + btVector3 localScaling(20,20,20); + localScaling[upIndex]=1.f; + groundShape->setLocalScaling(localScaling); + + tr.setOrigin(btVector3(0,-64.5f,0)); + +#endif // + + m_collisionShapes.push_back(groundShape); + + //create ground object + localCreateRigidBody(0,tr,groundShape); + +#ifdef FORCE_ZAXIS_UP +// indexRightAxis = 0; +// indexUpAxis = 2; +// indexForwardAxis = 1; + btCollisionShape* chassisShape = new btBoxShape(btVector3(1.f,2.f, 0.5f)); + btCompoundShape* compound = new btCompoundShape(); + btTransform localTrans; + localTrans.setIdentity(); + //localTrans effectively shifts the center of mass with respect to the chassis + localTrans.setOrigin(btVector3(0,0,1)); +#else + btCollisionShape* chassisShape = new btBoxShape(btVector3(1.f,0.5f,2.f)); + m_collisionShapes.push_back(chassisShape); + + btCompoundShape* compound = new btCompoundShape(); + m_collisionShapes.push_back(compound); + btTransform localTrans; + localTrans.setIdentity(); + //localTrans effectively shifts the center of mass with respect to the chassis + localTrans.setOrigin(btVector3(0,1,0)); +#endif + + compound->addChildShape(localTrans,chassisShape); + + tr.setOrigin(btVector3(0,0.f,0)); + + m_carChassis = localCreateRigidBody(800,tr,compound);//chassisShape); + //m_carChassis->setDamping(0.2,0.2); + + m_wheelShape = new btCylinderShapeX(btVector3(wheelWidth,wheelRadius,wheelRadius)); + + clientResetScene(); + + /// create vehicle + { + + m_vehicleRayCaster = new btDefaultVehicleRaycaster(m_dynamicsWorld); + m_vehicle = new btRaycastVehicle(m_tuning,m_carChassis,m_vehicleRayCaster); + + ///never deactivate the vehicle + m_carChassis->setActivationState(DISABLE_DEACTIVATION); + + m_dynamicsWorld->addVehicle(m_vehicle); + + float connectionHeight = 1.2f; + + + bool isFrontWheel=true; + + //choose coordinate system + m_vehicle->setCoordinateSystem(rightIndex,upIndex,forwardIndex); + +#ifdef FORCE_ZAXIS_UP + btVector3 connectionPointCS0(CUBE_HALF_EXTENTS-(0.3*wheelWidth),2*CUBE_HALF_EXTENTS-wheelRadius, connectionHeight); +#else + btVector3 connectionPointCS0(CUBE_HALF_EXTENTS-(0.3*wheelWidth),connectionHeight,2*CUBE_HALF_EXTENTS-wheelRadius); +#endif + + m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel); +#ifdef FORCE_ZAXIS_UP + connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),2*CUBE_HALF_EXTENTS-wheelRadius, connectionHeight); +#else + connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),connectionHeight,2*CUBE_HALF_EXTENTS-wheelRadius); +#endif + + m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel); +#ifdef FORCE_ZAXIS_UP + connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),-2*CUBE_HALF_EXTENTS+wheelRadius, connectionHeight); +#else + connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),connectionHeight,-2*CUBE_HALF_EXTENTS+wheelRadius); +#endif //FORCE_ZAXIS_UP + isFrontWheel = false; + m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel); +#ifdef FORCE_ZAXIS_UP + connectionPointCS0 = btVector3(CUBE_HALF_EXTENTS-(0.3*wheelWidth),-2*CUBE_HALF_EXTENTS+wheelRadius, connectionHeight); +#else + connectionPointCS0 = btVector3(CUBE_HALF_EXTENTS-(0.3*wheelWidth),connectionHeight,-2*CUBE_HALF_EXTENTS+wheelRadius); +#endif + m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel); + + for (int i=0;igetNumWheels();i++) + { + btWheelInfo& wheel = m_vehicle->getWheelInfo(i); + wheel.m_suspensionStiffness = suspensionStiffness; + wheel.m_wheelsDampingRelaxation = suspensionDamping; + wheel.m_wheelsDampingCompression = suspensionCompression; + wheel.m_frictionSlip = wheelFriction; + wheel.m_rollInfluence = rollInfluence; + } + } + + + setCameraDistance(26.f); + +} + + +//to be implemented by the demo +void VehicleDemo::renderme() +{ + + updateCamera(); + + btScalar m[16]; + int i; + + + btVector3 wheelColor(1,0,0); + + btVector3 worldBoundsMin,worldBoundsMax; + getDynamicsWorld()->getBroadphase()->getBroadphaseAabb(worldBoundsMin,worldBoundsMax); + + + + for (i=0;igetNumWheels();i++) + { + //synchronize the wheels with the (interpolated) chassis worldtransform + m_vehicle->updateWheelTransform(i,true); + //draw wheels (cylinders) + m_vehicle->getWheelInfo(i).m_worldTransform.getOpenGLMatrix(m); + m_shapeDrawer->drawOpenGL(m,m_wheelShape,wheelColor,getDebugMode(),worldBoundsMin,worldBoundsMax); + } + + + DemoApplication::renderme(); + +} + +void VehicleDemo::clientMoveAndDisplay() +{ + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + + { + int wheelIndex = 2; + m_vehicle->applyEngineForce(gEngineForce,wheelIndex); + m_vehicle->setBrake(gBreakingForce,wheelIndex); + wheelIndex = 3; + m_vehicle->applyEngineForce(gEngineForce,wheelIndex); + m_vehicle->setBrake(gBreakingForce,wheelIndex); + + + wheelIndex = 0; + m_vehicle->setSteeringValue(gVehicleSteering,wheelIndex); + wheelIndex = 1; + m_vehicle->setSteeringValue(gVehicleSteering,wheelIndex); + + } + + + float dt = getDeltaTimeMicroseconds() * 0.000001f; + + if (m_dynamicsWorld) + { + //during idle mode, just run 1 simulation step maximum + int maxSimSubSteps = m_idle ? 1 : 2; + if (m_idle) + dt = 1.0/420.f; + + int numSimSteps = m_dynamicsWorld->stepSimulation(dt,maxSimSubSteps); + + +//#define VERBOSE_FEEDBACK +#ifdef VERBOSE_FEEDBACK + if (!numSimSteps) + printf("Interpolated transforms\n"); + else + { + if (numSimSteps > maxSimSubSteps) + { + //detect dropping frames + printf("Dropped (%i) simulation steps out of %i\n",numSimSteps - maxSimSubSteps,numSimSteps); + } else + { + printf("Simulated (%i) steps\n",numSimSteps); + } + } +#endif //VERBOSE_FEEDBACK + + } + + + + + + + +#ifdef USE_QUICKPROF + btProfiler::beginBlock("render"); +#endif //USE_QUICKPROF + + + renderme(); + + //optional but useful: debug drawing + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + +#ifdef USE_QUICKPROF + btProfiler::endBlock("render"); +#endif + + + glFlush(); + glutSwapBuffers(); + +} + + + +void VehicleDemo::displayCallback(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + +//optional but useful: debug drawing + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + glFlush(); + glutSwapBuffers(); +} + + + +void VehicleDemo::clientResetScene() +{ + gVehicleSteering = 0.f; + m_carChassis->setCenterOfMassTransform(btTransform::getIdentity()); + m_carChassis->setLinearVelocity(btVector3(0,0,0)); + m_carChassis->setAngularVelocity(btVector3(0,0,0)); + m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_carChassis->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher()); + if (m_vehicle) + { + m_vehicle->resetSuspension(); + for (int i=0;igetNumWheels();i++) + { + //synchronize the wheels with the (interpolated) chassis worldtransform + m_vehicle->updateWheelTransform(i,true); + } + } + +} + + + +void VehicleDemo::specialKeyboardUp(int key, int x, int y) +{ + switch (key) + { + case GLUT_KEY_UP : + { + gEngineForce = 0.f; + break; + } + case GLUT_KEY_DOWN : + { + gBreakingForce = 0.f; + break; + } + default: + DemoApplication::specialKeyboardUp(key,x,y); + break; + } + +} + + +void VehicleDemo::specialKeyboard(int key, int x, int y) +{ + +// printf("key = %i x=%i y=%i\n",key,x,y); + + switch (key) + { + case GLUT_KEY_LEFT : + { + gVehicleSteering += steeringIncrement; + if ( gVehicleSteering > steeringClamp) + gVehicleSteering = steeringClamp; + + break; + } + case GLUT_KEY_RIGHT : + { + gVehicleSteering -= steeringIncrement; + if ( gVehicleSteering < -steeringClamp) + gVehicleSteering = -steeringClamp; + + break; + } + case GLUT_KEY_UP : + { + gEngineForce = maxEngineForce; + gBreakingForce = 0.f; + break; + } + case GLUT_KEY_DOWN : + { + gBreakingForce = maxBreakingForce; + gEngineForce = 0.f; + break; + } + default: + DemoApplication::specialKeyboard(key,x,y); + break; + } + +// glutPostRedisplay(); + + +} + + + +void VehicleDemo::updateCamera() +{ + +//#define DISABLE_CAMERA 1 +#ifdef DISABLE_CAMERA + DemoApplication::updateCamera(); + return; +#endif //DISABLE_CAMERA + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + btTransform chassisWorldTrans; + + //look at the vehicle + m_carChassis->getMotionState()->getWorldTransform(chassisWorldTrans); + m_cameraTargetPosition = chassisWorldTrans.getOrigin(); + + //interpolate the camera height +#ifdef FORCE_ZAXIS_UP + m_cameraPosition[2] = (15.0*m_cameraPosition[2] + m_cameraTargetPosition[2] + m_cameraHeight)/16.0; +#else + m_cameraPosition[1] = (15.0*m_cameraPosition[1] + m_cameraTargetPosition[1] + m_cameraHeight)/16.0; +#endif + + btVector3 camToObject = m_cameraTargetPosition - m_cameraPosition; + + //keep distance between min and max distance + float cameraDistance = camToObject.length(); + float correctionFactor = 0.f; + if (cameraDistance < m_minCameraDistance) + { + correctionFactor = 0.15*(m_minCameraDistance-cameraDistance)/cameraDistance; + } + if (cameraDistance > m_maxCameraDistance) + { + correctionFactor = 0.15*(m_maxCameraDistance-cameraDistance)/cameraDistance; + } + m_cameraPosition -= correctionFactor*camToObject; + + btScalar aspect = m_glutScreenWidth / (btScalar)m_glutScreenHeight; + glFrustum (-aspect, aspect, -1.0, 1.0, 1.0, 10000.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + gluLookAt(m_cameraPosition[0],m_cameraPosition[1],m_cameraPosition[2], + m_cameraTargetPosition[0],m_cameraTargetPosition[1], m_cameraTargetPosition[2], + m_cameraUp.getX(),m_cameraUp.getY(),m_cameraUp.getZ()); + + + +} + diff --git a/Demos/VehicleDemo/VehicleDemo.h b/Demos/VehicleDemo/VehicleDemo.h new file mode 100644 index 0000000..4a05c8f --- /dev/null +++ b/Demos/VehicleDemo/VehicleDemo.h @@ -0,0 +1,91 @@ +/* +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 VEHICLE_DEMO_H +#define VEHICLE_DEMO_H + +class btVehicleTuning; +struct btVehicleRaycaster; +class btCollisionShape; + +#include "BulletDynamics/Vehicle/btRaycastVehicle.h" + +#include "GlutDemoApplication.h" + +///VehicleDemo shows how to setup and use the built-in raycast vehicle +class VehicleDemo : public GlutDemoApplication +{ + public: + + btRigidBody* m_carChassis; + + btAlignedObjectArray m_collisionShapes; + + class btBroadphaseInterface* m_overlappingPairCache; + + class btCollisionDispatcher* m_dispatcher; + + class btConstraintSolver* m_constraintSolver; + + class btDefaultCollisionConfiguration* m_collisionConfiguration; + + class btTriangleIndexVertexArray* m_indexVertexArrays; + + btVector3* m_vertices; + + + btRaycastVehicle::btVehicleTuning m_tuning; + btVehicleRaycaster* m_vehicleRayCaster; + btRaycastVehicle* m_vehicle; + btCollisionShape* m_wheelShape; + + float m_cameraHeight; + + float m_minCameraDistance; + float m_maxCameraDistance; + + + VehicleDemo(); + + virtual ~VehicleDemo(); + + virtual void clientMoveAndDisplay(); + + virtual void clientResetScene(); + + virtual void displayCallback(); + + ///a very basic camera following the vehicle + virtual void updateCamera(); + + virtual void specialKeyboard(int key, int x, int y); + + virtual void specialKeyboardUp(int key, int x, int y); + + void renderme(); + + void initPhysics(); + + static DemoApplication* Create() + { + VehicleDemo* demo = new VehicleDemo(); + demo->myinit(); + demo->initPhysics(); + return demo; + } +}; + +#endif //VEHICLE_DEMO_H + + diff --git a/Demos/VehicleDemo/main.cpp b/Demos/VehicleDemo/main.cpp new file mode 100644 index 0000000..0bc51c2 --- /dev/null +++ b/Demos/VehicleDemo/main.cpp @@ -0,0 +1,18 @@ + +#include "VehicleDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" +GLDebugDrawer gDebugDrawer; + +int main(int argc,char** argv) +{ + + VehicleDemo* vehicleDemo = new VehicleDemo; + + vehicleDemo->initPhysics(); + vehicleDemo->getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + return glutmain(argc, argv,640,480,"Bullet Vehicle Demo. http://www.continuousphysics.com/Bullet/phpBB2/", vehicleDemo); +} + diff --git a/Demos/VoronoiFractureDemo/CMakeLists.txt b/Demos/VoronoiFractureDemo/CMakeLists.txt new file mode 100644 index 0000000..7c06df2 --- /dev/null +++ b/Demos/VoronoiFractureDemo/CMakeLists.txt @@ -0,0 +1,87 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# This is the variable for Windows. I use this to define the root of my directory structure. +SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/Glut) + +# You shouldn't have to modify anything below this line +######################################################## + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + + + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + +IF (WIN32) +ADD_EXECUTABLE(AppVoronoiFractureDemo + main.cpp + VoronoiFractureDemo.cpp + VoronoiFractureDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) +ELSE() + ADD_EXECUTABLE(AppVoronoiFractureDemo + main.cpp + VoronoiFractureDemo.cpp + VoronoiFractureDemo.h + ) +ENDIF() + + + + + IF (WIN32) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppVoronoiFractureDemo + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR} + ) + ELSE(CMAKE_CL_64) + ADD_CUSTOM_COMMAND( + TARGET AppVoronoiFractureDemo + POST_BUILD +# COMMAND copy /Y ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR} + ) + ENDIF(CMAKE_CL_64) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + + ENDIF(WIN32) +ELSE (USE_GLUT) + + + + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + + ADD_EXECUTABLE(AppVoronoiFractureDemo + WIN32 + ../OpenGL/Win32AppMain.cpp + Win32VoronoiFractureDemo.cpp + VoronoiFractureDemo.cpp + VoronoiFractureDemo.h + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) + + +ENDIF (USE_GLUT) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppVoronoiFractureDemo PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppVoronoiFractureDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppVoronoiFractureDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Demos/VoronoiFractureDemo/Makefile.am b/Demos/VoronoiFractureDemo/Makefile.am new file mode 100644 index 0000000..a73e4fb --- /dev/null +++ b/Demos/VoronoiFractureDemo/Makefile.am @@ -0,0 +1,5 @@ +noinst_PROGRAMS=BasicDemo + +BasicDemo_SOURCES=BasicDemo.cpp BasicDemo.h main.cpp +BasicDemo_CXXFLAGS=-I@top_builddir@/src -I@top_builddir@/Demos/OpenGL $(CXXFLAGS) +BasicDemo_LDADD=-L../OpenGL -lbulletopenglsupport -L../../src -lBulletDynamics -lBulletCollision -lLinearMath @opengl_LIBS@ diff --git a/Demos/VoronoiFractureDemo/Makefile.original b/Demos/VoronoiFractureDemo/Makefile.original new file mode 100644 index 0000000..6db49cd --- /dev/null +++ b/Demos/VoronoiFractureDemo/Makefile.original @@ -0,0 +1,49 @@ +__ARCH_BITS__ := 32 + +# define macros +RM=rm -f +OUTDIR=. +CELLSDKDIR=/opt/ibm/cell-sdk +ARCHITECTUREFLAG=-m$(__ARCH_BITS__) +USE_CESOF=1 +ifeq "$(__ARCH_BITS__)" "64" + DEFFLAGS= -DUSE_LIBSPE2 -DUSE_ADDR64 -DUSE_PARALLEL_DISPATCHER + GCC=ppu-g++ +else + DEFFLAGS= -DUSE_LIBSPE2 -DUSE_PARALLEL_DISPATCHER + GCC=ppu32-g++ +endif +DEBUGFLAG= +ifeq "$(USE_CESOF)" "1" + CFLAGS= $(ARCHITECTUREFLAG) $(DEBUGFLAG) -DUSE_CESOF -W -Wall -Winline -O3 -mabi=altivec -maltivec -include altivec.h -include stdbool.h -c +else + CFLAGS= $(ARCHITECTUREFLAG) $(DEBUGFLAG) -W -Wall -Winline -O3 -mabi=altivec -maltivec -include altivec.h -include stdbool.h -c +endif +INCLUDEDIR= -I. -I$(CELLSDKDIR)/prototype/sysroot/usr/include -I../../src -I../OpenGL +LFLAGS= $(ARCHITECTUREFLAG) -Wl,-m,elf$(__ARCH_BITS__)ppc +ifeq "$(USE_CESOF)" "1" + LIBRARIES= -lstdc++ -lsupc++ -lgcc -lgcov -lspe2 -lpthread -L../../out/linuxppc/optimize/libs \ + -lbulletmultithreaded -lspu -lbulletdynamics -lbulletcollision -lbulletmath \ + -L$(CELLSDKDIR)/prototype/sysroot/usr/lib$(__ARCH_BITS__) -R$(CELLSDKDIR)/prototype/sysroot/usr/lib +else + LIBRARIES= -lstdc++ -lsupc++ -lgcc -lgcov -lspe2 -lpthread -L../../out/linuxppc/optimize/libs \ + -lbulletmultithreaded -lbulletdynamics -lbulletcollision -lbulletmath \ + -L$(CELLSDKDIR)/prototype/sysroot/usr/lib$(__ARCH_BITS__) -R$(CELLSDKDIR)/prototype/sysroot/usr/lib +endif + +DemoApplication : + $(GCC) $(DEFFLAGS) $(CFLAGS) $(INCLUDEDIR) -o $(OUTDIR)/$@.o ../OpenGL/$@.cpp + + +BasicDemo : DemoApplication + $(GCC) $(DEFFLAGS) $(CFLAGS) $(INCLUDEDIR) -o $(OUTDIR)/$@.o $@.cpp + + + +all : BasicDemo + $(GCC) -o$(OUTDIR)/BasicDemo $(OUTDIR)/BasicDemo.o $(OUTDIR)/DemoApplication.o $(LFLAGS) $(LIBRARIES) + + +clean : + $(RM) $(OUTDIR)/BasicDemo ; $(RM) $(OUTDIR)/BasicDemo.o ; $(RM) $(OUTDIR)/DemoApplication.o + diff --git a/Demos/VoronoiFractureDemo/VoronoiFractureDemo.cpp b/Demos/VoronoiFractureDemo/VoronoiFractureDemo.cpp new file mode 100644 index 0000000..d3dca4c --- /dev/null +++ b/Demos/VoronoiFractureDemo/VoronoiFractureDemo.cpp @@ -0,0 +1,660 @@ +/* +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. +*/ +/* +Voronoi fracture and shatter code and demo copyright (c) 2011 Alain Ducharme + - Reset scene (press spacebar) to generate new random voronoi shattered cuboids + - Check console for total time required to: compute and mesh all 3D shards, calculate volumes and centers of mass and create rigid bodies + - Modify VORONOIPOINTS define below to change number of potential voronoi shards + - Note that demo's visual cracks between voronoi shards are NOT present in the internally generated voronoi mesh! +*/ + +//Number of random voronoi points to generate for shattering +#define VORONOIPOINTS 100 + +//maximum number of objects (and allow user to shoot additional boxes) +#define MAX_PROXIES (2048) +#define BREAKING_THRESHOLD 2 +#define CONVEX_MARGIN 0.04 + +#include "VoronoiFractureDemo.h" +#include "GlutStuff.h" +///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files. +#include "btBulletDynamicsCommon.h" + +#include //printf debugging + +#include "GLDebugDrawer.h" +static GLDebugDrawer sDebugDraw; + +void VoronoiFractureDemo::attachFixedConstraints() +{ + btAlignedObjectArray bodies; + + int numManifolds = getDynamicsWorld()->getDispatcher()->getNumManifolds(); + + for (int i=0;igetDispatcher()->getManifoldByIndexInternal(i); + if (!manifold->getNumContacts()) + continue; + + btScalar minDist = 1e30f; + int minIndex = -1; + for (int v=0;vgetNumContacts();v++) + { + if (minDist >manifold->getContactPoint(v).getDistance()) + { + minDist = manifold->getContactPoint(v).getDistance(); + minIndex = v; + } + } + if (minDist>0.) + continue; + + btCollisionObject* colObj0 = (btCollisionObject*)manifold->getBody0(); + btCollisionObject* colObj1 = (btCollisionObject*)manifold->getBody1(); + int tag0 = (colObj0)->getIslandTag(); + int tag1 = (colObj1)->getIslandTag(); + btRigidBody* body0 = btRigidBody::upcast(colObj0); + btRigidBody* body1 = btRigidBody::upcast(colObj1); + if (bodies.findLinearSearch(body0)==bodies.size()) + bodies.push_back(body0); + if (bodies.findLinearSearch(body1)==bodies.size()) + bodies.push_back(body1); + + if (body0 && body1) + { + if (!colObj0->isStaticOrKinematicObject() && !colObj1->isStaticOrKinematicObject()) + { + if (body0->checkCollideWithOverride(body1)) + { + { + btTransform trA,trB; + trA.setIdentity(); + trB.setIdentity(); + btVector3 contactPosWorld = manifold->getContactPoint(minIndex).m_positionWorldOnA; + btTransform globalFrame; + globalFrame.setIdentity(); + globalFrame.setOrigin(contactPosWorld); + + trA = body0->getWorldTransform().inverse()*globalFrame; + trB = body1->getWorldTransform().inverse()*globalFrame; + + btGeneric6DofConstraint* dof6 = new btGeneric6DofConstraint(*body0,*body1,trA,trB,true); + dof6->setOverrideNumSolverIterations(100); + + float totalMass = 1.f/body0->getInvMass() + 1.f/body1->getInvMass(); + + dof6->setBreakingImpulseThreshold(BREAKING_THRESHOLD*totalMass); + + for (int i=0;i<6;i++) + dof6->setLimit(i,0,0); + getDynamicsWorld()->addConstraint(dof6,true); + + } + } + } + } + + } + + for (int i=0;iremoveRigidBody(bodies[i]); + getDynamicsWorld()->addRigidBody(bodies[i]); + } +} + +void VoronoiFractureDemo::keyboardCallback(unsigned char key, int x, int y) +{ + if (key == 'g') + { + attachFixedConstraints(); + }else + { + PlatformDemoApplication::keyboardCallback(key,x,y); + } +} + + +void VoronoiFractureDemo::getVerticesInsidePlanes(const btAlignedObjectArray& planes, btAlignedObjectArray& verticesOut, std::set& planeIndicesOut) +{ + // Based on btGeometryUtil.cpp (Gino van den Bergen / Erwin Coumans) + verticesOut.resize(0); + planeIndicesOut.clear(); + const int numPlanes = planes.size(); + int i, j, k, l; + for (i=0;i btScalar(0.0001)) + { + for (k=j+1;k btScalar(0.0001)) && (n3n1.length2() > btScalar(0.0001) )) + { + btScalar quotient = (N1.dot(n2n3)); + if (btFabs(quotient) > btScalar(0.0001)) + { + btVector3 potentialVertex = (n2n3 * N1[3] + n3n1 * N2[3] + n1n2 * N3[3]) * (btScalar(-1.) / quotient); + for (l=0; l btScalar(0.000001)) + break; + } + if (l == numPlanes) + { + // vertex (three plane intersection) inside all planes + verticesOut.push_back(potentialVertex); + planeIndicesOut.insert(i); + planeIndicesOut.insert(j); + planeIndicesOut.insert(k); + } + } + } + } + } + } + } +} + +static btVector3 curVoronoiPoint; // Here for btAlignedObjectArray.quickSort pointCmp scope + +struct pointCmp +{ + bool operator()(const btVector3& p1, const btVector3& p2) const + { + float v1 = (p1-curVoronoiPoint).length2(); + float v2 = (p2-curVoronoiPoint).length2(); + bool result0 = v1 < v2; + //bool result1 = ((btScalar)(p1-curVoronoiPoint).length2()) < ((btScalar)(p2-curVoronoiPoint).length2()); + //apparently result0 is not always result1, because extended precision used in registered is different from precision when values are stored in memory + return result0; + } +}; + +void VoronoiFractureDemo::voronoiBBShatter(const btAlignedObjectArray& points, const btVector3& bbmin, const btVector3& bbmax, const btQuaternion& bbq, const btVector3& bbt, btScalar matDensity) { + // points define voronoi cells in world space (avoid duplicates) + // bbmin & bbmax = bounding box min and max in local space + // bbq & bbt = bounding box quaternion rotation and translation + // matDensity = Material density for voronoi shard mass calculation + btVector3 bbvx = quatRotate(bbq, btVector3(1.0, 0.0, 0.0)); + btVector3 bbvy = quatRotate(bbq, btVector3(0.0, 1.0, 0.0)); + btVector3 bbvz = quatRotate(bbq, btVector3(0.0, 0.0, 1.0)); + btQuaternion bbiq = bbq.inverse(); + btConvexHullComputer* convexHC = new btConvexHullComputer(); + btAlignedObjectArray vertices; + btVector3 rbb, nrbb; + btScalar nlength, maxDistance, distance; + btAlignedObjectArray sortedVoronoiPoints; + sortedVoronoiPoints.copyFromArray(points); + btVector3 normal, plane; + btAlignedObjectArray planes; + std::set planeIndices; + std::set::iterator planeIndicesIter; + int numplaneIndices; + int cellnum = 0; + int i, j, k; + + int numpoints = points.size(); + for (i=0; i < numpoints ;i++) { + curVoronoiPoint = points[i]; + btVector3 icp = quatRotate(bbiq, curVoronoiPoint - bbt); + rbb = icp - bbmax; + nrbb = bbmin - icp; + planes.resize(6); + planes[0] = bbvx; planes[0][3] = rbb.x(); + planes[1] = bbvy; planes[1][3] = rbb.y(); + planes[2] = bbvz; planes[2][3] = rbb.z(); + planes[3] = -bbvx; planes[3][3] = nrbb.x(); + planes[4] = -bbvy; planes[4][3] = nrbb.y(); + planes[5] = -bbvz; planes[5][3] = nrbb.z(); + maxDistance = SIMD_INFINITY; + sortedVoronoiPoints.quickSort(pointCmp()); + for (j=1; j < numpoints; j++) { + normal = sortedVoronoiPoints[j] - curVoronoiPoint; + nlength = normal.length(); + if (nlength > maxDistance) + break; + plane = normal.normalized(); + plane[3] = -nlength / btScalar(2.); + planes.push_back(plane); + getVerticesInsidePlanes(planes, vertices, planeIndices); + if (vertices.size() == 0) + break; + numplaneIndices = planeIndices.size(); + if (numplaneIndices != planes.size()) { + planeIndicesIter = planeIndices.begin(); + for (k=0; k < numplaneIndices; k++) { + if (k != *planeIndicesIter) + planes[k] = planes[*planeIndicesIter]; + planeIndicesIter++; + } + planes.resize(numplaneIndices); + } + maxDistance = vertices[0].length(); + for (k=1; k < vertices.size(); k++) { + distance = vertices[k].length(); + if (maxDistance < distance) + maxDistance = distance; + } + maxDistance *= btScalar(2.); + } + if (vertices.size() == 0) + continue; + + // Clean-up voronoi convex shard vertices and generate edges & faces + convexHC->compute(&vertices[0].getX(), sizeof(btVector3), vertices.size(),CONVEX_MARGIN,0.0); + + // At this point we have a complete 3D voronoi shard mesh contained in convexHC + + // Calculate volume and center of mass (Stan Melax volume integration) + int numFaces = convexHC->faces.size(); + int v0, v1, v2; // Triangle vertices + btScalar volume = btScalar(0.); + btVector3 com(0., 0., 0.); + for (j=0; j < numFaces; j++) { + const btConvexHullComputer::Edge* edge = &convexHC->edges[convexHC->faces[j]]; + v0 = edge->getSourceVertex(); + v1 = edge->getTargetVertex(); + edge = edge->getNextEdgeOfFace(); + v2 = edge->getTargetVertex(); + while (v2 != v0) { + // Counter-clockwise triangulated voronoi shard mesh faces (v0-v1-v2) and edges here... + btScalar vol = convexHC->vertices[v0].triple(convexHC->vertices[v1], convexHC->vertices[v2]); + volume += vol; + com += vol * (convexHC->vertices[v0] + convexHC->vertices[v1] + convexHC->vertices[v2]); + edge = edge->getNextEdgeOfFace(); + v1 = v2; + v2 = edge->getTargetVertex(); + } + } + com /= volume * btScalar(4.); + volume /= btScalar(6.); + + // Shift all vertices relative to center of mass + int numVerts = convexHC->vertices.size(); + for (j=0; j < numVerts; j++) + { + convexHC->vertices[j] -= com; + } + + // Note: + // At this point convex hulls contained in convexHC should be accurate (line up flush with other pieces, no cracks), + // ...however Bullet Physics rigid bodies demo visualizations appear to produce some visible cracks. + // Use the mesh in convexHC for visual display or to perform boolean operations with. + + // Create Bullet Physics rigid body shards + btCollisionShape* shardShape = new btConvexHullShape(&(convexHC->vertices[0].getX()), convexHC->vertices.size()); + shardShape->setMargin(CONVEX_MARGIN); // for this demo; note convexHC has optional margin parameter for this + m_collisionShapes.push_back(shardShape); + btTransform shardTransform; + shardTransform.setIdentity(); + shardTransform.setOrigin(curVoronoiPoint + com); // Shard's adjusted location + btDefaultMotionState* shardMotionState = new btDefaultMotionState(shardTransform); + btScalar shardMass(volume * matDensity); + btVector3 shardInertia(0.,0.,0.); + shardShape->calculateLocalInertia(shardMass, shardInertia); + btRigidBody::btRigidBodyConstructionInfo shardRBInfo(shardMass, shardMotionState, shardShape, shardInertia); + btRigidBody* shardBody = new btRigidBody(shardRBInfo); + m_dynamicsWorld->addRigidBody(shardBody); + + cellnum ++; + + } + printf("Generated %d voronoi btRigidBody shards\n", cellnum); +} + +void VoronoiFractureDemo::voronoiConvexHullShatter(const btAlignedObjectArray& points, const btAlignedObjectArray& verts, const btQuaternion& bbq, const btVector3& bbt, btScalar matDensity) { + // points define voronoi cells in world space (avoid duplicates) + // verts = source (convex hull) mesh vertices in local space + // bbq & bbt = source (convex hull) mesh quaternion rotation and translation + // matDensity = Material density for voronoi shard mass calculation + btConvexHullComputer* convexHC = new btConvexHullComputer(); + btAlignedObjectArray vertices, chverts; + btVector3 rbb, nrbb; + btScalar nlength, maxDistance, distance; + btAlignedObjectArray sortedVoronoiPoints; + sortedVoronoiPoints.copyFromArray(points); + btVector3 normal, plane; + btAlignedObjectArray planes, convexPlanes; + std::set planeIndices; + std::set::iterator planeIndicesIter; + int numplaneIndices; + int cellnum = 0; + int i, j, k; + + // Convert verts to world space and get convexPlanes + int numverts = verts.size(); + chverts.resize(verts.size()); + for (i=0; i < numverts ;i++) { + chverts[i] = quatRotate(bbq, verts[i]) + bbt; + } + //btGeometryUtil::getPlaneEquationsFromVertices(chverts, convexPlanes); + // Using convexHullComputer faster than getPlaneEquationsFromVertices for large meshes... + convexHC->compute(&chverts[0].getX(), sizeof(btVector3), numverts, 0.0, 0.0); + int numFaces = convexHC->faces.size(); + int v0, v1, v2; // vertices + for (i=0; i < numFaces; i++) { + const btConvexHullComputer::Edge* edge = &convexHC->edges[convexHC->faces[i]]; + v0 = edge->getSourceVertex(); + v1 = edge->getTargetVertex(); + edge = edge->getNextEdgeOfFace(); + v2 = edge->getTargetVertex(); + plane = (convexHC->vertices[v1]-convexHC->vertices[v0]).cross(convexHC->vertices[v2]-convexHC->vertices[v0]).normalize(); + plane[3] = -plane.dot(convexHC->vertices[v0]); + convexPlanes.push_back(plane); + } + const int numconvexPlanes = convexPlanes.size(); + + int numpoints = points.size(); + for (i=0; i < numpoints ;i++) { + curVoronoiPoint = points[i]; + planes.copyFromArray(convexPlanes); + for (j=0; j < numconvexPlanes ;j++) { + planes[j][3] += planes[j].dot(curVoronoiPoint); + } + maxDistance = SIMD_INFINITY; + sortedVoronoiPoints.quickSort(pointCmp()); + for (j=1; j < numpoints; j++) { + normal = sortedVoronoiPoints[j] - curVoronoiPoint; + nlength = normal.length(); + if (nlength > maxDistance) + break; + plane = normal.normalized(); + plane[3] = -nlength / btScalar(2.); + planes.push_back(plane); + getVerticesInsidePlanes(planes, vertices, planeIndices); + if (vertices.size() == 0) + break; + numplaneIndices = planeIndices.size(); + if (numplaneIndices != planes.size()) { + planeIndicesIter = planeIndices.begin(); + for (k=0; k < numplaneIndices; k++) { + if (k != *planeIndicesIter) + planes[k] = planes[*planeIndicesIter]; + planeIndicesIter++; + } + planes.resize(numplaneIndices); + } + maxDistance = vertices[0].length(); + for (k=1; k < vertices.size(); k++) { + distance = vertices[k].length(); + if (maxDistance < distance) + maxDistance = distance; + } + maxDistance *= btScalar(2.); + } + if (vertices.size() == 0) + continue; + + // Clean-up voronoi convex shard vertices and generate edges & faces + convexHC->compute(&vertices[0].getX(), sizeof(btVector3), vertices.size(),0.0,0.0); + + // At this point we have a complete 3D voronoi shard mesh contained in convexHC + + // Calculate volume and center of mass (Stan Melax volume integration) + numFaces = convexHC->faces.size(); + btScalar volume = btScalar(0.); + btVector3 com(0., 0., 0.); + for (j=0; j < numFaces; j++) { + const btConvexHullComputer::Edge* edge = &convexHC->edges[convexHC->faces[j]]; + v0 = edge->getSourceVertex(); + v1 = edge->getTargetVertex(); + edge = edge->getNextEdgeOfFace(); + v2 = edge->getTargetVertex(); + while (v2 != v0) { + // Counter-clockwise triangulated voronoi shard mesh faces (v0-v1-v2) and edges here... + btScalar vol = convexHC->vertices[v0].triple(convexHC->vertices[v1], convexHC->vertices[v2]); + volume += vol; + com += vol * (convexHC->vertices[v0] + convexHC->vertices[v1] + convexHC->vertices[v2]); + edge = edge->getNextEdgeOfFace(); + v1 = v2; + v2 = edge->getTargetVertex(); + } + } + com /= volume * btScalar(4.); + volume /= btScalar(6.); + + // Shift all vertices relative to center of mass + int numVerts = convexHC->vertices.size(); + for (j=0; j < numVerts; j++) + { + convexHC->vertices[j] -= com; + } + + // Note: + // At this point convex hulls contained in convexHC should be accurate (line up flush with other pieces, no cracks), + // ...however Bullet Physics rigid bodies demo visualizations appear to produce some visible cracks. + // Use the mesh in convexHC for visual display or to perform boolean operations with. + + // Create Bullet Physics rigid body shards + btCollisionShape* shardShape = new btConvexHullShape(&(convexHC->vertices[0].getX()), convexHC->vertices.size()); + shardShape->setMargin(CONVEX_MARGIN); // for this demo; note convexHC has optional margin parameter for this + m_collisionShapes.push_back(shardShape); + btTransform shardTransform; + shardTransform.setIdentity(); + shardTransform.setOrigin(curVoronoiPoint + com); // Shard's adjusted location + btDefaultMotionState* shardMotionState = new btDefaultMotionState(shardTransform); + btScalar shardMass(volume * matDensity); + btVector3 shardInertia(0.,0.,0.); + shardShape->calculateLocalInertia(shardMass, shardInertia); + btRigidBody::btRigidBodyConstructionInfo shardRBInfo(shardMass, shardMotionState, shardShape, shardInertia); + btRigidBody* shardBody = new btRigidBody(shardRBInfo); + m_dynamicsWorld->addRigidBody(shardBody); + + cellnum ++; + + } + printf("Generated %d voronoi btRigidBody shards\n", cellnum); +} + +void VoronoiFractureDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //simple dynamics world doesn't handle fixed-time-stepping + float ms = getDeltaTimeMicroseconds(); + + ///step the simulation + if (m_dynamicsWorld) + { + m_dynamicsWorld->stepSimulation(ms / 1000000.f); + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + } + + renderme(); + + glFlush(); + + swapBuffers(); +} + + +void VoronoiFractureDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + //optional but useful: debug drawing to detect problems + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + glFlush(); + swapBuffers(); +} + + +void VoronoiFractureDemo::initPhysics() +{ + setTexturing(true); + setShadows(true); + + setCameraDistance(btScalar(20.)); + + ///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->getSolverInfo().m_splitImpulse = true; + m_dynamicsWorld->setDebugDrawer(&sDebugDraw); + + m_dynamicsWorld->setGravity(btVector3(0,-10,0)); + + ///create a few basic rigid bodies + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); +// btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); + + m_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + + //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here: + { + btScalar mass(0.); + + //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) + groundShape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + //add the body to the dynamics world + m_dynamicsWorld->addRigidBody(body); + } + + // ==> Voronoi Shatter Basic Demo: Random Cuboid + + // Random size cuboid (defined by bounding box max and min) + btVector3 bbmax(btScalar(rand() / btScalar(RAND_MAX)) * 6. +0.5, btScalar(rand() / btScalar(RAND_MAX)) * 6. +0.5, btScalar(rand() / btScalar(RAND_MAX)) * 6. +0.5); + btVector3 bbmin = -bbmax; + // Place it 10 units above ground + btVector3 bbt(0,10,0); + // Use an arbitrary material density for shards (should be consitent/relative with/to rest of RBs in world) + btScalar matDensity = 1; + // Using random rotation + btQuaternion bbq(btScalar(rand() / btScalar(RAND_MAX)) * 2. -1.,btScalar(rand() / btScalar(RAND_MAX)) * 2. -1.,btScalar(rand() / btScalar(RAND_MAX)) * 2. -1.,btScalar(rand() / btScalar(RAND_MAX)) * 2. -1.); + bbq.normalize(); + // Generate random points for voronoi cells + btAlignedObjectArray points; + btVector3 point; + btVector3 diff = bbmax - bbmin; + for (int i=0; i < VORONOIPOINTS; i++) { + // Place points within box area (points are in world coordinates) + point = quatRotate(bbq, btVector3(btScalar(rand() / btScalar(RAND_MAX)) * diff.x() -diff.x()/2., btScalar(rand() / btScalar(RAND_MAX)) * diff.y() -diff.y()/2., btScalar(rand() / btScalar(RAND_MAX)) * diff.z() -diff.z()/2.)) + bbt; + points.push_back(point); + } + m_perfmTimer.reset(); + voronoiBBShatter(points, bbmin, bbmax, bbq, bbt, matDensity); + printf("Total Time: %f seconds\n", m_perfmTimer.getTimeMilliseconds()/1000.); + + for (int i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--) + { + btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i]; + obj->getCollisionShape()->setMargin(CONVEX_MARGIN+0.01); + } + m_dynamicsWorld->performDiscreteCollisionDetection(); + + for (int i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--) + { + btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i]; + obj->getCollisionShape()->setMargin(CONVEX_MARGIN); + } + + attachFixedConstraints(); + +} +void VoronoiFractureDemo::clientResetScene() +{ + exitPhysics(); + initPhysics(); +} + + +void VoronoiFractureDemo::exitPhysics() +{ + + //cleanup in the reverse order of creation/initialization + + int i; + //remove all constraints + for (i=m_dynamicsWorld->getNumConstraints()-1;i>=0;i--) + { + btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i); + m_dynamicsWorld->removeConstraint(constraint); + delete constraint; + } + + //remove the rigidbodies from the dynamics world and delete them + + 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;j +#include + +class btBroadphaseInterface; +class btCollisionShape; +class btOverlappingPairCache; +class btCollisionDispatcher; +class btConstraintSolver; +struct btCollisionAlgorithmCreateFunc; +class btDefaultCollisionConfiguration; + +///VoronoiFractureDemo is good starting point for learning the code base and porting. + +class VoronoiFractureDemo : public PlatformDemoApplication +{ + //keep the collision shapes, for deletion/cleanup + btAlignedObjectArray m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + btClock m_perfmTimer; + + public: + + VoronoiFractureDemo() + { + srand((unsigned)time(NULL)); // Seed it... + } + virtual ~VoronoiFractureDemo() + { + exitPhysics(); + } + void initPhysics(); + + void exitPhysics(); + + void getVerticesInsidePlanes(const btAlignedObjectArray& planes, btAlignedObjectArray& verticesOut, std::set& planeIndicesOut); + void voronoiBBShatter(const btAlignedObjectArray& points, const btVector3& bbmin, const btVector3& bbmax, const btQuaternion& bbq, const btVector3& bbt, btScalar matDensity); + void voronoiConvexHullShatter(const btAlignedObjectArray& points, const btAlignedObjectArray& verts, const btQuaternion& bbq, const btVector3& bbt, btScalar matDensity); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + virtual void clientResetScene(); + + virtual void keyboardCallback(unsigned char key, int x, int y); + + void attachFixedConstraints(); + + + static DemoApplication* Create() + { + VoronoiFractureDemo* demo = new VoronoiFractureDemo; + demo->myinit(); + demo->initPhysics(); + return demo; + } + + +}; + +#endif //BASIC_DEMO_H + diff --git a/Demos/VoronoiFractureDemo/Win32VoronoiFractureDemo.cpp b/Demos/VoronoiFractureDemo/Win32VoronoiFractureDemo.cpp new file mode 100644 index 0000000..a55fb67 --- /dev/null +++ b/Demos/VoronoiFractureDemo/Win32VoronoiFractureDemo.cpp @@ -0,0 +1,25 @@ +#ifdef _WINDOWS +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "BasicDemo.h" + +///The 'createDemo' function is called from Bullet/Demos/OpenGL/Win32AppMain.cpp to instantiate this particular demo +DemoApplication* createDemo() +{ + return new BasicDemo(); +} + +#endif diff --git a/Demos/VoronoiFractureDemo/main.cpp b/Demos/VoronoiFractureDemo/main.cpp new file mode 100644 index 0000000..e391128 --- /dev/null +++ b/Demos/VoronoiFractureDemo/main.cpp @@ -0,0 +1,51 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "VoronoiFractureDemo.h" +#include "GlutStuff.h" +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btHashMap.h" + + + +static bool cmp(const int& p1, const int& p2) { + return p1 bla; + + bla.push_back(8); + bla.push_back(6); + bla.push_back(6); + bla.push_back(4); + bla.push_back(9); + bla.quickSort(cmp); + + VoronoiFractureDemo ccdDemo; + ccdDemo.initPhysics(); + +#ifdef CHECK_MEMORY_LEAKS + ccdDemo.exitPhysics(); +#else + return glutmain(argc, argv,1024,600,"Bullet Physics Demo. http://bulletphysics.org",&ccdDemo); +#endif + + //default glut doesn't return from mainloop + return 0; +} + diff --git a/Demos/premake4.lua b/Demos/premake4.lua new file mode 100644 index 0000000..4900db6 --- /dev/null +++ b/Demos/premake4.lua @@ -0,0 +1,96 @@ + + + +function createDemos( demos, incdirs, linknames) + for _, name in ipairs(demos) do + + project ( "App_" .. name ) + + kind "ConsoleApp" + targetdir ".." + + includedirs {incdirs} + + configuration { "Windows" } + defines { "GLEW_STATIC"} + links { "opengl32" } + includedirs{ "../Glut" } + libdirs {"../Glut"} + files { "../msvc/bullet.rc" } + + configuration {"Windows", "x32"} + links {"glew32s","glut32"} + configuration {"Windows", "x64"} + links {"glew64s", "glut64"} + + configuration {"MacOSX"} + --print "hello" + linkoptions { "-framework Carbon -framework OpenGL -framework AGL -framework Glut" } + + configuration {"not Windows", "not MacOSX"} + links {"GL","GLU","glut"} + + configuration{} + + links { + linknames + } + + files { + "./" .. name .. "/*.cpp" , + "./" .. name .. "/*.h" + } + end +end + +-- "CharacterDemo", fixme: it includes BspDemo files + + local localdemos = { + "BasicDemo", + "Box2dDemo", + "BspDemo", + "CcdPhysicsDemo", + "CollisionDemo", + "CollisionInterfaceDemo", + "ConcaveConvexcastDemo", + "ConcaveDemo", + "ConcaveRaycastDemo", + "ConstraintDemo", + "ContinuousConvexCollision", + "ConvexHullDistance", + "DynamicControlDemo", + "EPAPenDepthDemo", + "ForkLiftDemo", + "FractureDemo", + "GenericJointDemo", + "GimpactTestDemo", + "GjkConvexCastDemo", + "HelloWorld", + "InternalEdgeDemo", + "MovingConcaveDemo", + "MultiMaterialDemo", + "RagdollDemo", + "Raytracer", + "SimplexDemo", + "SliderConstraintDemo", + "TerrainDemo", + "UserCollisionAlgorithm", + "VehicleDemo", + "VoronoiFractureDemo" + } + +-- the following demos require custom include or link settings + + createDemos(localdemos,{"../src","OpenGL"},{"OpenGLSupport","LinearMath","BulletCollision","BulletDynamics"}) + + createDemos({"ConvexDecompositionDemo"},{"../Extras/HACD","../Extras/ConvexDecomposition","../src","OpenGL"},{"OpenGLSupport","LinearMath","BulletCollision","BulletDynamics", "HACD","ConvexDecomposition"}) + + createDemos({"SoftDemo"},{"../src","OpenGL"}, {"OpenGLSupport","LinearMath","BulletCollision","BulletDynamics", "BulletSoftBody"}) + + createDemos({"SerializeDemo"},{"../Extras/Serialize/BulletFileLoader","../Extras/Serialize/BulletWorldImporter","../src","OpenGL"},{"OpenGLSupport","LinearMath","BulletCollision","BulletDynamics", "BulletSoftBody", "BulletFileLoader","BulletWorldImporter"}) + + + +include "OpenGL" + + diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 0000000..d483fe4 --- /dev/null +++ b/Doxyfile @@ -0,0 +1,780 @@ +# Doxyfile 1.2.4 + +# This file describes the settings to be used by doxygen for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- + + + + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. +PROJECT_NAME = "Bullet Collision Detection & Physics Library" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese, +# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian, +# Polish, Portuguese and Slovene. + +OUTPUT_LANGUAGE = English + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these class will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a class diagram (in Html and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. + +CLASS_DIAGRAMS = YES + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower case letters. If set to YES upper case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are adviced to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explict @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# reimplements. + +INHERIT_DOCS = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# The ENABLE_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = src + + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +FILE_PATTERNS = *.h *.cpp *.c + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse. + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = YES + +# HHC_LOCATION = "C:\Program Files\HTML Help Workshop\hhc.exe" +HHC_LOCATION = "C:\Program Files (x86)\HTML Help Workshop\hhc.exe" + + +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +#HTML_STYLESHEET = "\\server\exchange\Software Development\Documentation\DoxyGen\doxygen.css" + +CHM_FILE = BulletDocs.chm +HHC_LOCATION = "c:\program files\HTML Help Workshop\hhc.exe" +GENERATE_CHI = YES +BINARY_TOC = YES + +TOC_EXPAND = YES + +SHOW_DIRECTORIES = YES + + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 1 + +# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript and frames is required (for instance Netscape 4.0+ +# or Internet explorer 4.0+). + +GENERATE_TREEVIEW = YES + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimised for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using a WORD or other. +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assigments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. Warning: This feature +# is still experimental and very incomplete. + +GENERATE_XML = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = src + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = "ATTRIBUTE_ALIGNED128(x)=x" \ + "ATTRIBUTE_ALIGNED16(x)=x" \ + "SIMD_FORCE_INLINE=inline" \ + "VECTORMATH_FORCE_INLINE=inline" \ + "USE_WIN32_THREADING=1"\ + "USE_PTHREADS=1"\ + "_WIN32=1" + + +# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tagfiles. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to +# YES then doxygen will generate a graph for each documented file showing +# the direct and indirect include dependencies of the file with other +# documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to +# YES then doxygen will generate a graph for each documented header file showing +# the documented files that directly or indirectly include this file + +INCLUDED_BY_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + + +# delete intermediate dot files? + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO + +# The CGI_NAME tag should be the name of the CGI script that +# starts the search engine (doxysearch) with the correct parameters. +# A script with this name will be generated by doxygen. + +CGI_NAME = search.cgi + +# The CGI_URL tag should be the absolute URL to the directory where the +# cgi binaries are located. See the documentation of your http daemon for +# details. + +CGI_URL = + +# The DOC_URL tag should be the absolute URL to the directory where the +# documentation is located. If left blank the absolute path to the +# documentation, with file:// prepended to it, will be used. + +DOC_URL = + +# The DOC_ABSPATH tag should be the absolute path to the directory where the +# documentation is located. If left blank the directory on the local machine +# will be used. + +DOC_ABSPATH = + +# The BIN_ABSPATH tag must point to the directory where the doxysearch binary +# is installed. + +BIN_ABSPATH = c:\program files\doxygen\bin + +# The EXT_DOC_PATHS tag can be used to specify one or more paths to +# documentation generated for other projects. This allows doxysearch to search +# the documentation for these projects as well. + +EXT_DOC_PATHS = diff --git a/Extras/AllBulletDemosOSX/AllBulletDemos.xcodeproj/TemplateIcon.icns b/Extras/AllBulletDemosOSX/AllBulletDemos.xcodeproj/TemplateIcon.icns new file mode 100644 index 0000000000000000000000000000000000000000..62cb7015e09d6ea3e65d7f7949c4c07f9246a908 GIT binary patch literal 52318 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 WhsmLR^b3` + + + + ActivePerspectiveName + Project + AllowedModules + + + BundleLoadPath + + MaxInstances + n + Module + PBXSmartGroupTreeModule + Name + Groups and Files Outline View + + + BundleLoadPath + + MaxInstances + n + Module + PBXNavigatorGroup + Name + Editor + + + BundleLoadPath + + MaxInstances + n + Module + XCTaskListModule + Name + Task List + + + BundleLoadPath + + MaxInstances + n + Module + XCDetailModule + Name + File and Smart Group Detail Viewer + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXBuildResultsModule + Name + Detailed Build Results Viewer + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXProjectFindModule + Name + Project Batch Find Tool + + + BundleLoadPath + + MaxInstances + n + Module + XCProjectFormatConflictsModule + Name + Project Format Conflicts List + + + BundleLoadPath + + MaxInstances + n + Module + PBXBookmarksModule + Name + Bookmarks Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXClassBrowserModule + Name + Class Browser + + + BundleLoadPath + + MaxInstances + n + Module + PBXCVSModule + Name + Source Code Control Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXDebugBreakpointsModule + Name + Debug Breakpoints Tool + + + BundleLoadPath + + MaxInstances + n + Module + XCDockableInspector + Name + Inspector + + + BundleLoadPath + + MaxInstances + n + Module + PBXOpenQuicklyModule + Name + Open Quickly Tool + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXDebugSessionModule + Name + Debugger + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXDebugCLIModule + Name + Debug Console + + + BundleLoadPath + + MaxInstances + n + Module + XCSnapshotModule + Name + Snapshots Tool + + + BundlePath + /Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources + Description + AIODescriptionKey + DockingSystemVisible + + Extension + perspectivev3 + FavBarConfig + + PBXProjectModuleGUID + 36C69D140DC9E7C30034504A + XCBarModuleItemNames + + XCBarModuleItems + + + FirstTimeWindowDisplayed + + Identifier + com.apple.perspectives.project.defaultV3 + MajorVersion + 34 + MinorVersion + 0 + Name + All-In-One + Notifications + + + XCObserverAutoDisconnectKey + + XCObserverDefintionKey + + PBXStatusErrorsKey + 0 + + XCObserverFactoryKey + XCPerspectivesSpecificationIdentifier + XCObserverGUIDKey + XCObserverProjectIdentifier + XCObserverNotificationKey + PBXStatusBuildStateMessageNotification + XCObserverTargetKey + XCMainBuildResultsModuleGUID + XCObserverTriggerKey + awakenModuleWithObserver: + XCObserverValidationKey + + PBXStatusErrorsKey + 2 + + + + XCObserverAutoDisconnectKey + + XCObserverDefintionKey + + PBXStatusWarningsKey + 0 + + XCObserverFactoryKey + XCPerspectivesSpecificationIdentifier + XCObserverGUIDKey + XCObserverProjectIdentifier + XCObserverNotificationKey + PBXStatusBuildStateMessageNotification + XCObserverTargetKey + XCMainBuildResultsModuleGUID + XCObserverTriggerKey + awakenModuleWithObserver: + XCObserverValidationKey + + PBXStatusWarningsKey + 2 + + + + OpenEditors + + PerspectiveWidths + + 1440 + 1440 + + Perspectives + + + ChosenToolbarItems + + XCToolbarPerspectiveControl + NSToolbarSeparatorItem + active-target-popup + active-executable-popup + active-buildstyle-popup + action + NSToolbarFlexibleSpaceItem + buildOrClean + build-and-goOrGo + com.apple.ide.PBXToolbarStopButton + get-info + toggle-editor + NSToolbarFlexibleSpaceItem + researchAssistant + com.apple.pbx.toolbar.searchfield + + ControllerClassBaseName + + IconName + WindowOfProject + Identifier + perspective.project + IsVertical + + Layout + + + BecomeActive + + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C37FBAC04509CD000000102 + 1C37FAAC04509CD000000102 + 1C08E77C0454961000C914BD + 1C37FABC05509CD000000102 + 1C37FABC05539CD112110102 + E2644B35053B69B200211256 + 1C37FABC04509CD000100104 + 1CC0EA4004350EF90044410B + 1CC0EA4004350EF90041110B + 1C77FABC04509CD000000102 + + PBXProjectModuleGUID + 1CA23ED40692098700951B8B + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + yes + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 352 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 29B97314FDCFA39411CA2CEA + 36A05D5A0DCBAD9000ADF289 + 36C69D250DC9E7FE0034504A + 36A05DC60DCBBAC000ADF289 + 29B97317FDCFA39411CA2CEA + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 20 + 18 + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {352, 780}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + + + GeometryConfiguration + + Frame + {{0, 0}, {369, 798}} + GroupTreeTableConfiguration + + MainColumn + 352 + + RubberWindowFrame + 0 39 1440 839 0 0 1440 878 + + Module + PBXSmartGroupTreeModule + Proportion + 369pt + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 36C69D0F0DC9E7C30034504A + PBXProjectModuleLabel + + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 36C69D100DC9E7C30034504A + PBXProjectModuleLabel + + + SplitCount + 1 + + StatusBarVisibility + + XCSharingToken + com.apple.Xcode.CommonNavigatorGroupSharingToken + + GeometryConfiguration + + Frame + {{0, 0}, {1066, 555}} + RubberWindowFrame + 0 39 1440 839 0 0 1440 878 + + Module + PBXNavigatorGroup + Proportion + 555pt + + + Proportion + 238pt + Tabs + + + ContentConfiguration + + PBXProjectModuleGUID + 1CA23EDF0692099D00951B8B + PBXProjectModuleLabel + Detail + + GeometryConfiguration + + Frame + {{10, 27}, {1066, 211}} + RubberWindowFrame + 0 39 1440 839 0 0 1440 878 + + Module + XCDetailModule + + + ContentConfiguration + + PBXProjectModuleGUID + 1CA23EE00692099D00951B8B + PBXProjectModuleLabel + Project Find + + GeometryConfiguration + + Frame + {{10, 27}, {1066, -27}} + + Module + PBXProjectFindModule + + + ContentConfiguration + + PBXCVSModuleFilterTypeKey + 1032 + PBXProjectModuleGUID + 1CA23EE10692099D00951B8B + PBXProjectModuleLabel + SCM Results + + GeometryConfiguration + + Frame + {{10, 31}, {603, 297}} + + Module + PBXCVSModule + + + ContentConfiguration + + PBXProjectModuleGUID + XCMainBuildResultsModuleGUID + PBXProjectModuleLabel + Build + XCBuildResultsTrigger_Collapse + 1021 + XCBuildResultsTrigger_Open + 1013 + + GeometryConfiguration + + Frame + {{10, 27}, {1066, 211}} + + Module + PBXBuildResultsModule + + + + + Proportion + 1066pt + + + Name + Project + ServiceClasses + + XCModuleDock + PBXSmartGroupTreeModule + XCModuleDock + PBXNavigatorGroup + XCDockableTabModule + XCDetailModule + PBXProjectFindModule + PBXCVSModule + PBXBuildResultsModule + + TableOfContents + + 3699D2370DCF89C9001D9494 + 1CA23ED40692098700951B8B + 3699D2380DCF89C9001D9494 + 36C69D0F0DC9E7C30034504A + 3699D2390DCF89C9001D9494 + 1CA23EDF0692099D00951B8B + 1CA23EE00692099D00951B8B + 1CA23EE10692099D00951B8B + XCMainBuildResultsModuleGUID + + ToolbarConfiguration + xcode.toolbar.config.defaultV3 + + + ChosenToolbarItems + + XCToolbarPerspectiveControl + NSToolbarSeparatorItem + build-and-go + go + NSToolbarFlexibleSpaceItem + debugger-fix-and-continue + debugger-restart-executable + debugger-pause + debugger-step-over + debugger-step-into + debugger-step-out + debugger-step-instruction + NSToolbarFlexibleSpaceItem + + ControllerClassBaseName + PBXDebugSessionModule + IconName + DebugTabIcon + Identifier + perspective.debug + IsVertical + + Layout + + + ContentConfiguration + + PBXProjectModuleGUID + 1CCC7628064C1048000F2A68 + PBXProjectModuleLabel + Debugger Console + + GeometryConfiguration + + Frame + {{0, 0}, {1440, 238}} + + Module + PBXDebugCLIModule + Proportion + 238pt + + + ContentConfiguration + + Debugger + + HorizontalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {703, 268}} + {{703, 0}, {737, 268}} + + + VerticalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {1440, 268}} + {{0, 268}, {1440, 287}} + + + + LauncherConfigVersion + 8 + PBXProjectModuleGUID + 1CCC7629064C1048000F2A68 + PBXProjectModuleLabel + Debug + + GeometryConfiguration + + DebugConsoleVisible + None + DebugConsoleWindowFrame + {{200, 200}, {500, 300}} + DebugSTDIOWindowFrame + {{200, 200}, {500, 300}} + Frame + {{0, 243}, {1440, 555}} + PBXDebugSessionStackFrameViewKey + + DebugVariablesTableConfiguration + + Name + 120 + Value + 85 + Summary + 507 + + Frame + {{703, 0}, {737, 268}} + + + Module + PBXDebugSessionModule + Proportion + 555pt + + + Name + Debug + ServiceClasses + + XCModuleDock + PBXDebugCLIModule + PBXDebugSessionModule + PBXDebugProcessAndThreadModule + PBXDebugProcessViewModule + PBXDebugThreadViewModule + PBXDebugStackFrameViewModule + PBXNavigatorGroup + + TableOfContents + + 3699D2080DCF68BE001D9494 + 1CCC7628064C1048000F2A68 + 1CCC7629064C1048000F2A68 + 3699D2090DCF68BE001D9494 + 3699D20A0DCF68BE001D9494 + 3699D20B0DCF68BE001D9494 + 3699D20C0DCF68BE001D9494 + 36C69D0F0DC9E7C30034504A + + ToolbarConfiguration + xcode.toolbar.config.debugV3 + + + PerspectivesBarVisible + + ShelfIsVisible + + SourceDescription + file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecification.xcperspec' + StatusbarIsVisible + + TimeStamp + 231705097.779064 + ToolbarDisplayMode + 2 + ToolbarIsVisible + + ToolbarSizeMode + 2 + Type + Perspectives + UpdateMessage + + WindowJustification + 5 + WindowOrderList + + /Users/zakariya/Code/vendor/bullet-2.68/Extras/AllBulletDemosOSX/AllBulletDemos.xcodeproj + + WindowString + 0 39 1440 839 0 0 1440 878 + WindowToolsV3 + + + Identifier + windowTool.debugger + Layout + + + Dock + + + ContentConfiguration + + Debugger + + HorizontalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {317, 164}} + {{317, 0}, {377, 164}} + + + VerticalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {694, 164}} + {{0, 164}, {694, 216}} + + + + LauncherConfigVersion + 8 + PBXProjectModuleGUID + 1C162984064C10D400B95A72 + PBXProjectModuleLabel + Debug - GLUTExamples (Underwater) + + GeometryConfiguration + + DebugConsoleDrawerSize + {100, 120} + DebugConsoleVisible + None + DebugConsoleWindowFrame + {{200, 200}, {500, 300}} + DebugSTDIOWindowFrame + {{200, 200}, {500, 300}} + Frame + {{0, 0}, {694, 380}} + RubberWindowFrame + 321 238 694 422 0 0 1440 878 + + Module + PBXDebugSessionModule + Proportion + 100% + + + Proportion + 100% + + + Name + Debugger + ServiceClasses + + PBXDebugSessionModule + + StatusbarIsVisible + 1 + TableOfContents + + 1CD10A99069EF8BA00B06720 + 1C0AD2AB069F1E9B00FABCE6 + 1C162984064C10D400B95A72 + 1C0AD2AC069F1E9B00FABCE6 + + ToolbarConfiguration + xcode.toolbar.config.debugV3 + WindowString + 321 238 694 422 0 0 1440 878 + WindowToolGUID + 1CD10A99069EF8BA00B06720 + WindowToolIsVisible + 0 + + + Identifier + windowTool.build + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1CD0528F0623707200166675 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1CD052900623707200166675 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {500, 215}} + RubberWindowFrame + 192 257 500 500 0 0 1280 1002 + + Module + PBXNavigatorGroup + Proportion + 218pt + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + XCMainBuildResultsModuleGUID + PBXProjectModuleLabel + Build + + GeometryConfiguration + + Frame + {{0, 222}, {500, 236}} + RubberWindowFrame + 192 257 500 500 0 0 1280 1002 + + Module + PBXBuildResultsModule + Proportion + 236pt + + + Proportion + 458pt + + + Name + Build Results + ServiceClasses + + PBXBuildResultsModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C78EAA5065D492600B07095 + 1C78EAA6065D492600B07095 + 1CD0528F0623707200166675 + XCMainBuildResultsModuleGUID + + ToolbarConfiguration + xcode.toolbar.config.buildV3 + WindowString + 192 257 500 500 0 0 1280 1002 + + + Identifier + windowTool.find + Layout + + + Dock + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1CDD528C0622207200134675 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1CD0528D0623707200166675 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {781, 167}} + RubberWindowFrame + 62 385 781 470 0 0 1440 878 + + Module + PBXNavigatorGroup + Proportion + 781pt + + + Proportion + 50% + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1CD0528E0623707200166675 + PBXProjectModuleLabel + Project Find + + GeometryConfiguration + + Frame + {{8, 0}, {773, 254}} + RubberWindowFrame + 62 385 781 470 0 0 1440 878 + + Module + PBXProjectFindModule + Proportion + 50% + + + Proportion + 428pt + + + Name + Project Find + ServiceClasses + + PBXProjectFindModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C530D57069F1CE1000CFCEE + 1C530D58069F1CE1000CFCEE + 1C530D59069F1CE1000CFCEE + 1CDD528C0622207200134675 + 1C530D5A069F1CE1000CFCEE + 1CE0B1FE06471DED0097A5F4 + 1CD0528E0623707200166675 + + WindowString + 62 385 781 470 0 0 1440 878 + WindowToolGUID + 1C530D57069F1CE1000CFCEE + WindowToolIsVisible + 0 + + + Identifier + windowTool.snapshots + Layout + + + Dock + + + Module + XCSnapshotModule + Proportion + 100% + + + Proportion + 100% + + + Name + Snapshots + ServiceClasses + + XCSnapshotModule + + StatusbarIsVisible + Yes + ToolbarConfiguration + xcode.toolbar.config.snapshots + WindowString + 315 824 300 550 0 0 1440 878 + WindowToolIsVisible + Yes + + + Identifier + windowTool.debuggerConsole + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1C78EAAC065D492600B07095 + PBXProjectModuleLabel + Debugger Console + + GeometryConfiguration + + Frame + {{0, 0}, {700, 358}} + RubberWindowFrame + 149 87 700 400 0 0 1440 878 + + Module + PBXDebugCLIModule + Proportion + 358pt + + + Proportion + 358pt + + + Name + Debugger Console + ServiceClasses + + PBXDebugCLIModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C530D5B069F1CE1000CFCEE + 1C530D5C069F1CE1000CFCEE + 1C78EAAC065D492600B07095 + + ToolbarConfiguration + xcode.toolbar.config.consoleV3 + WindowString + 149 87 440 400 0 0 1440 878 + WindowToolGUID + 1C530D5B069F1CE1000CFCEE + WindowToolIsVisible + 0 + + + Identifier + windowTool.scm + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1C78EAB2065D492600B07095 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1C78EAB3065D492600B07095 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {452, 0}} + RubberWindowFrame + 743 379 452 308 0 0 1280 1002 + + Module + PBXNavigatorGroup + Proportion + 0pt + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1CD052920623707200166675 + PBXProjectModuleLabel + SCM + + GeometryConfiguration + + ConsoleFrame + {{0, 259}, {452, 0}} + Frame + {{0, 7}, {452, 259}} + RubberWindowFrame + 743 379 452 308 0 0 1280 1002 + TableConfiguration + + Status + 30 + FileName + 199 + Path + 197.09500122070312 + + TableFrame + {{0, 0}, {452, 250}} + + Module + PBXCVSModule + Proportion + 262pt + + + Proportion + 266pt + + + Name + SCM + ServiceClasses + + PBXCVSModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C78EAB4065D492600B07095 + 1C78EAB5065D492600B07095 + 1C78EAB2065D492600B07095 + 1CD052920623707200166675 + + ToolbarConfiguration + xcode.toolbar.config.scmV3 + WindowString + 743 379 452 308 0 0 1280 1002 + + + Identifier + windowTool.breakpoints + IsVertical + 0 + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C77FABC04509CD000000102 + + PBXProjectModuleGUID + 1CE0B1FE06471DED0097A5F4 + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + no + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 168 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 1C77FABC04509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {168, 350}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + 0 + + GeometryConfiguration + + Frame + {{0, 0}, {185, 368}} + GroupTreeTableConfiguration + + MainColumn + 168 + + RubberWindowFrame + 315 424 744 409 0 0 1440 878 + + Module + PBXSmartGroupTreeModule + Proportion + 185pt + + + ContentConfiguration + + PBXProjectModuleGUID + 1CA1AED706398EBD00589147 + PBXProjectModuleLabel + Detail + + GeometryConfiguration + + Frame + {{190, 0}, {554, 368}} + RubberWindowFrame + 315 424 744 409 0 0 1440 878 + + Module + XCDetailModule + Proportion + 554pt + + + Proportion + 368pt + + + MajorVersion + 3 + MinorVersion + 0 + Name + Breakpoints + ServiceClasses + + PBXSmartGroupTreeModule + XCDetailModule + + StatusbarIsVisible + 1 + TableOfContents + + 1CDDB66807F98D9800BB5817 + 1CDDB66907F98D9800BB5817 + 1CE0B1FE06471DED0097A5F4 + 1CA1AED706398EBD00589147 + + ToolbarConfiguration + xcode.toolbar.config.breakpointsV3 + WindowString + 315 424 744 409 0 0 1440 878 + WindowToolGUID + 1CDDB66807F98D9800BB5817 + WindowToolIsVisible + 1 + + + Identifier + windowTool.debugAnimator + Layout + + + Dock + + + Module + PBXNavigatorGroup + Proportion + 100% + + + Proportion + 100% + + + Name + Debug Visualizer + ServiceClasses + + PBXNavigatorGroup + + StatusbarIsVisible + 1 + ToolbarConfiguration + xcode.toolbar.config.debugAnimatorV3 + WindowString + 100 100 700 500 0 0 1280 1002 + + + Identifier + windowTool.bookmarks + Layout + + + Dock + + + Module + PBXBookmarksModule + Proportion + 166pt + + + Proportion + 166pt + + + Name + Bookmarks + ServiceClasses + + PBXBookmarksModule + + StatusbarIsVisible + 0 + WindowString + 538 42 401 187 0 0 1280 1002 + + + Identifier + windowTool.projectFormatConflicts + Layout + + + Dock + + + Module + XCProjectFormatConflictsModule + Proportion + 100% + + + Proportion + 100% + + + Name + Project Format Conflicts + ServiceClasses + + XCProjectFormatConflictsModule + + StatusbarIsVisible + 0 + WindowContentMinSize + 450 300 + WindowString + 50 850 472 307 0 0 1440 877 + + + Identifier + windowTool.classBrowser + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + OptionsSetName + Hierarchy, all classes + PBXProjectModuleGUID + 1CA6456E063B45B4001379D8 + PBXProjectModuleLabel + Class Browser - NSObject + + GeometryConfiguration + + ClassesFrame + {{0, 0}, {369, 96}} + ClassesTreeTableConfiguration + + PBXClassNameColumnIdentifier + 208 + PBXClassBookColumnIdentifier + 22 + + Frame + {{0, 0}, {616, 353}} + MembersFrame + {{0, 105}, {369, 395}} + MembersTreeTableConfiguration + + PBXMemberTypeIconColumnIdentifier + 22 + PBXMemberNameColumnIdentifier + 216 + PBXMemberTypeColumnIdentifier + 94 + PBXMemberBookColumnIdentifier + 22 + + PBXModuleWindowStatusBarHidden2 + 1 + RubberWindowFrame + 597 125 616 374 0 0 1280 1002 + + Module + PBXClassBrowserModule + Proportion + 354pt + + + Proportion + 354pt + + + Name + Class Browser + ServiceClasses + + PBXClassBrowserModule + + StatusbarIsVisible + 0 + TableOfContents + + 1C78EABA065D492600B07095 + 1C78EABB065D492600B07095 + 1CA6456E063B45B4001379D8 + + ToolbarConfiguration + xcode.toolbar.config.classbrowser + WindowString + 597 125 616 374 0 0 1280 1002 + + + Identifier + windowTool.refactoring + IncludeInToolsMenu + 0 + Layout + + + Dock + + + BecomeActive + 1 + GeometryConfiguration + + Frame + {0, 0}, {500, 335} + RubberWindowFrame + {0, 0}, {500, 335} + + Module + XCRefactoringModule + Proportion + 100% + + + Proportion + 100% + + + Name + Refactoring + ServiceClasses + + XCRefactoringModule + + WindowString + 200 200 500 356 0 0 1920 1200 + + + + diff --git a/Extras/AllBulletDemosOSX/AllBulletDemos_Prefix.pch b/Extras/AllBulletDemosOSX/AllBulletDemos_Prefix.pch new file mode 100644 index 0000000..f1d2c11 --- /dev/null +++ b/Extras/AllBulletDemosOSX/AllBulletDemos_Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'AllBulletDemos' target in the 'AllBulletDemos' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/Extras/AllBulletDemosOSX/BulletIcon.icns b/Extras/AllBulletDemosOSX/BulletIcon.icns new file mode 100644 index 0000000000000000000000000000000000000000..1429602ce60360b8a4f8238c60b7fbc08505dd12 GIT binary patch literal 28472 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 A(*OVf literal 0 HcmV?d00001 diff --git a/Extras/AllBulletDemosOSX/BulletIcon.psd b/Extras/AllBulletDemosOSX/BulletIcon.psd new file mode 100644 index 0000000000000000000000000000000000000000..c0b4a99c98e71bf4d1248a33d32738024e8fa106 GIT binary patch literal 101941 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 a!Y*1dX%G66ZqL#C$|bw0ZoP5@jOGW1ArT7z literal 0 HcmV?d00001 diff --git a/Extras/AllBulletDemosOSX/English.lproj/MainMenu.xib b/Extras/AllBulletDemosOSX/English.lproj/MainMenu.xib new file mode 100644 index 0000000..6a63aae --- /dev/null +++ b/Extras/AllBulletDemosOSX/English.lproj/MainMenu.xib @@ -0,0 +1,2157 @@ + + + + 1040 + 9E17 + 670 + 949.33 + 352.00 + + YES + + + + + YES + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + YES + + + AllBulletDemos + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + AllBulletDemos + + YES + + + About AllBulletDemos + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + UHJlZmVyZW5jZXPigKY + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide AllBulletDemos + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit AllBulletDemos + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 2147483647 + + + submenuAction: + + File + + YES + + + Reset Current Demo + r + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + View + + YES + + + Previous Demo + [ + 1048576 + 2147483647 + + + + + + Next Demo + ] + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Fullscreen + F + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Show Paramaters + P + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + _NSMainMenu + + + 15 + 2 + {{500, 363}, {593, 360}} + 1954021376 + All Bullet Demos + NSWindow + + {3.40282e+38, 3.40282e+38} + {593, 360} + + + 256 + + YES + + + 274 + {593, 320} + + BTOpenGLView + + + + 268 + {{17, 328}, {210, 22}} + + YES + + -2076049856 + 133120 + + LucidaGrande + 1.100000e+01 + 3100 + + + 109199615 + 129 + + + 400 + 75 + + + Item 1 + + 1048576 + 2147483647 + 1 + + + _popUpItemAction: + + + YES + + OtherViews + + YES + + + + Item 2 + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + Item 3 + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + 1 + YES + YES + 2 + + + + + 265 + {{489, 331}, {86, 18}} + + YES + + 67239424 + 131072 + Fullscreen + + + 1211912703 + 130 + + NSImage + NSSwitch + + + NSSwitch + + + + 200 + 25 + + + + + 265 + {{393, 331}, {93, 18}} + + YES + + 67239424 + 131072 + Parameters + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{227, 325}, {96, 28}} + + YES + + 67239424 + 134348800 + Reset + + + -2038284033 + 129 + + + 200 + 25 + + + + {593, 360} + + {{0, 0}, {1440, 878}} + {593, 382} + {3.40282e+38, 3.40282e+38} + _main_window_ + + + NSFontManager + + + BTDemosAppController + + + 19 + 2 + {{196, 291}, {276, 219}} + -469762048 + Parameters + NSPanel + + {276, 219} + {276, 219} + + + 256 + + YES + + + 268 + {{17, 177}, {64, 17}} + + YES + + 68288064 + 272630784 + Iterations + + LucidaGrande + 1.300000e+01 + 1044 + + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2OQA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + + + + 268 + {{86, 174}, {121, 22}} + + YES + + -1804468671 + -1874852864 + + + + + YES + + YES + allowsFloats + formatterBehavior + minimum + + + YES + + + + + + # + # + + + + + + + + + + NaN + + YES + + YES + + + YES + + + + + + 0 + 0 + YES + NO + 1 + AAAAAAAAAAAAAAAAAAAAAA + + + 3 + YES + YES + YES + + . + , + NO + YES + YES + + + YES + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 6 + System + textColor + + + + + + + 268 + {{84, 140}, {149, 18}} + + YES + + -2080244224 + 0 + Disable deactivation + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 12 + {{12, 106}, {252, 5}} + + {0, 0} + + 67239424 + 0 + Box + + + + 3 + MCAwLjgwMDAwMDAxAA + + + 3 + 2 + 0 + NO + + + + 268 + {{212, 171}, {19, 27}} + + YES + + 917024 + 0 + + 1.000000e+02 + 1.000000e+00 + YES + + + + + 268 + {{9, 84}, {69, 17}} + + YES + + 68288064 + 272630784 + Rendering + + + + + + + + + 268 + {{84, 59}, {63, 18}} + + YES + + -2080244224 + 0 + AABBs + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{84, 39}, {113, 18}} + + YES + + -2080244224 + 0 + Wireframe + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{84, 19}, {113, 18}} + + YES + + -2080244224 + 0 + Contacts + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{84, 115}, {149, 18}} + + YES + + -2080244224 + 0 + Enable Split Impulse + + + 1211912703 + 130 + + + + + 200 + 25 + + + + {276, 219} + + + {{0, 0}, {1440, 878}} + {276, 235} + {276, 235} + _parameters_window_ + + + BTSimulationParameters + + + YES + + + + + YES + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + performZoom: + + + + 240 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + terminate: + + + + 369 + + + + unhideAllApplications: + + + + 370 + + + + _glView + + + + 451 + + + + delegate + + + + 453 + + + + content: demos + + + + + + content: demos + content + demos + 2 + + + 489 + + + + selectedValue: demo + + + + + + selectedValue: demo + selectedValue + demo + + 2 + + + 490 + + + + value: fullscreen + + + + + + value: fullscreen + value + fullscreen + 2 + + + 493 + + + + nextDemo: + + + + 498 + + + + previousDemo: + + + + 499 + + + + _parameters + + + + 526 + + + + value: iterations + + + + + + value: iterations + value + iterations + 2 + + + 527 + + + + maxValue: maxIterations + + + + + + maxValue: maxIterations + maxValue + maxIterations + 2 + + + 531 + + + + minValue: minIterations + + + + + + minValue: minIterations + minValue + minIterations + + 2 + + + 532 + + + + value: iterations + + + + + + value: iterations + value + iterations + + 2 + + + 533 + + + + value: disableDeactivation + + + + + + value: disableDeactivation + value + disableDeactivation + 2 + + + 534 + + + + value: drawAABBs + + + + + + value: drawAABBs + value + drawAABBs + 2 + + + 535 + + + + value: debugDraw + + + + + + value: debugDraw + value + debugDraw + 2 + + + 537 + + + + visible: showParameters + + + + + + visible: showParameters + visible + showParameters + 2 + + + 540 + + + + value: showParameters + + + + + + value: showParameters + value + showParameters + 2 + + + 543 + + + + performClose: + + + + 559 + + + + value: showParameters + + + + + + value: showParameters + value + showParameters + 2 + + + 564 + + + + value: fullscreen + + + + + + value: fullscreen + value + fullscreen + 2 + + + 567 + + + + resetDemo: + + + + 570 + + + + resetDemo: + + + + 573 + + + + value: drawContacts + + + + + + value: drawContacts + value + drawContacts + 2 + + + 576 + + + + nullMenuTarget: + + + + 579 + + + + nullMenuTarget: + + + + 580 + + + + value: splitImpulse + + + + + + value: splitImpulse + value + splitImpulse + 2 + + + 589 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + MainMenu + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + 1111 + + + 144 + + + + + 129 + + + 121 + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + + + 371 + + + YES + + + + + + 372 + + + YES + + + + + + + + + + 420 + + + + + 449 + + + + + 450 + + + + + 483 + + + YES + + + + + + 484 + + + YES + + + + + + 485 + + + YES + + + + + + + + 486 + + + + + 487 + + + + + 488 + + + + + 491 + + + YES + + + + + + 492 + + + + + 496 + + + + + 497 + + + + + 501 + + + + + 503 + + + YES + + + + + + 504 + + + YES + + + + + + + + + + + + + + + 507 + + + YES + + + + + + 508 + + + + + 509 + + + YES + + + + + + 510 + + + YES + + + + + + 511 + + + + + 512 + + + YES + + + + + + 513 + + + + + 514 + + + + + 515 + + + YES + + + + + + 516 + + + + + 517 + + + YES + + + + + + 518 + + + + + 519 + + + YES + + + + + + 520 + + + + + 521 + + + YES + + + + + + 522 + + + + + 523 + + + YES + + + + + + 524 + + + + + 525 + + + + + 538 + + + + + 541 + + + YES + + + + + + 542 + + + + + 544 + + + YES + + + + + + 545 + + + YES + + + + + + + + 550 + + + + + 560 + + + + + 561 + + + + + 562 + + + + + 568 + + + + + 569 + + + + + 571 + + + YES + + + + + + 572 + + + + + 581 + + + YES + + + + + + 582 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBEditorWindowLastContentRect + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBEditorWindowLastContentRect + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 371.IBEditorWindowLastContentRect + 371.IBPluginDependency + 371.IBWindowTemplateEditedContentRect + 371.NSWindowTemplate.visibleAtLaunch + 371.editorWindowContentRectSynchronizationRect + 371.windowTemplate.hasMinSize + 371.windowTemplate.maxSize + 371.windowTemplate.minSize + 372.IBPluginDependency + 449.IBPluginDependency + 450.IBPluginDependency + 483.IBPluginDependency + 484.IBPluginDependency + 485.IBPluginDependency + 486.IBPluginDependency + 487.IBPluginDependency + 488.IBPluginDependency + 491.IBPluginDependency + 492.IBPluginDependency + 496.IBPluginDependency + 497.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 501.IBPluginDependency + 503.IBEditorWindowLastContentRect + 503.IBPluginDependency + 503.IBWindowTemplateEditedContentRect + 503.NSWindowTemplate.visibleAtLaunch + 503.windowTemplate.hasMaxSize + 503.windowTemplate.hasMinSize + 503.windowTemplate.maxSize + 503.windowTemplate.minSize + 504.IBPluginDependency + 507.IBPluginDependency + 508.IBPluginDependency + 509.IBPluginDependency + 510.IBPluginDependency + 511.IBPluginDependency + 512.IBPluginDependency + 513.IBPluginDependency + 514.IBPluginDependency + 515.IBPluginDependency + 516.IBPluginDependency + 517.IBPluginDependency + 518.IBPluginDependency + 519.IBPluginDependency + 520.IBPluginDependency + 521.IBPluginDependency + 522.IBPluginDependency + 523.IBPluginDependency + 524.IBPluginDependency + 525.IBPluginDependency + 541.IBPluginDependency + 542.IBPluginDependency + 544.IBPluginDependency + 545.IBEditorWindowLastContentRect + 545.IBPluginDependency + 550.IBPluginDependency + 56.IBPluginDependency + 56.ImportedFromIB2 + 560.IBPluginDependency + 561.IBPluginDependency + 562.IBPluginDependency + 568.IBPluginDependency + 569.IBPluginDependency + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 571.IBPluginDependency + 572.IBPluginDependency + 58.IBPluginDependency + 58.ImportedFromIB2 + 581.IBPluginDependency + 582.IBPluginDependency + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{526, 428}, {211, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{525, 802}, {197, 73}} + {{293, 531}, {316, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{6, 978}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + {{390, 212}, {192, 73}} + com.apple.InterfaceBuilder.CocoaPlugin + {{475, 832}, {234, 43}} + {{1073, 539}, {593, 360}} + com.apple.InterfaceBuilder.CocoaPlugin + {{1073, 539}, {593, 360}} + + {{33, 99}, {480, 360}} + + {3.40282e+38, 3.40282e+38} + {593, 360} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + {{378, 681}, {276, 219}} + com.apple.InterfaceBuilder.CocoaPlugin + {{378, 681}, {276, 219}} + + + + {276, 219} + {276, 219} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{348, 232}, {218, 53}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{219, 102}, {242, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 589 + + + + YES + + BTDemosAppController + NSObject + + YES + + YES + nextDemo: + nullMenuTarget: + previousDemo: + resetDemo: + toggleFullscreen: + toggleParameters: + + + YES + id + id + id + id + id + id + + + + YES + + YES + _glView + _parameters + + + YES + BTOpenGLView + BTSimulationParameters + + + + IBProjectSource + src/BTDemosAppController.h + + + + BTOpenGLView + NSView + + _delegate + id + + + IBProjectSource + src/toolkit/BTOpenGLView.h + + + + BTSimulationParameters + NSObject + + IBProjectSource + src/BTSimulationParameters.h + + + + + 0 + ../AllBulletDemos.xcodeproj + 3 + + diff --git a/Extras/AllBulletDemosOSX/Info.plist b/Extras/AllBulletDemosOSX/Info.plist new file mode 100644 index 0000000..5081c73 --- /dev/null +++ b/Extras/AllBulletDemosOSX/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + BulletIcon + CFBundleIdentifier + org.bullet.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/Extras/AllBulletDemosOSX/README.txt b/Extras/AllBulletDemosOSX/README.txt new file mode 100644 index 0000000..173847c --- /dev/null +++ b/Extras/AllBulletDemosOSX/README.txt @@ -0,0 +1,6 @@ +To build: +Place AllBulletDemosOSX in bullet-/Extras and build with Xcode. + +Questions: +contact Shamyl Zakariya +shamyl@zakariya.net \ No newline at end of file diff --git a/Extras/AllBulletDemosOSX/main.m b/Extras/AllBulletDemosOSX/main.m new file mode 100644 index 0000000..699ddd4 --- /dev/null +++ b/Extras/AllBulletDemosOSX/main.m @@ -0,0 +1,14 @@ +// +// main.m +// AllBulletDemos +// +// Created by Shamyl Zakariya on 5/1/08. +// Copyright Shamyl Zakariya 2008. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/Extras/AllBulletDemosOSX/src/BTDemo.h b/Extras/AllBulletDemosOSX/src/BTDemo.h new file mode 100644 index 0000000..235353e --- /dev/null +++ b/Extras/AllBulletDemosOSX/src/BTDemo.h @@ -0,0 +1,106 @@ +/* +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. +*/ + +#import +#import "BTOpenGLDisplayDelegate.h" + +@class BTDemoEntry; + +@interface BTDemo : NSObject { + + NSString *_demoName; + BTDemoEntry *_demo; +} + +/** + @brief Array of all available bullet demos +*/ ++ (NSArray*) demoNames; + +/** + @brief Verify a given string is a demo name +*/ ++ (BOOL) isDemo: (NSString *) demoName; + +/** + @brief Create a demo with a given name + @note Returns nil if the name is not a valid demo name +*/ ++ (BTDemo*) demoWithName: (NSString *) demoName; + +/** + @brief Initialize a demo with a given name +*/ +- (id) initWithDemoName: (NSString *) demoName; + +/** + @brief Reset current demo +*/ +- (void) reset; + +/** + @brief Name of current demo +*/ +- (NSString*) demoName; + +/////////////////////////////////////////////////////////////////////// +// BTOpenGLDisplayDelegate + +- (void) contextCreated; +- (void) contextWillBeDestroyed; +- (void) contextWillResize; +- (void) contextResized: (NSSize) newSize; +- (void) contextDidResize; +- (void) contextStateInvalidated; + +- (void) display: (float) deltaT; + +- (void) keyPressed: (unsigned char) key; +- (void) keyReleased: (unsigned char) key; + +- (void) specialKeyPressed: (unsigned) GLUTKey; +- (void) specialKeyReleased: (unsigned) GLUTKey; + +- (void) mouseButtonPressed: (unsigned) mouseButton; +- (void) mouseButtonReleased: (unsigned) mouseButton; +- (void) mouseMoved: (NSPoint) delta; +- (void) newMousePosition: (NSPoint) newMousePosition; +- (void) scrollWheel: (NSPoint) delta; + +/////////////////////////////////////////////////////////////////////// +// Global simulation properties -- applies to all demos + ++ (void) setIterations: (unsigned) iterations; ++ (unsigned) iterations; + ++ (unsigned) minIterations; ++ (unsigned) maxIterations; + ++ (void) setDisableDeactivation: (BOOL) disableDeactivation; ++ (BOOL) disableDeactivation; + ++ (void) setDrawAABBs: (BOOL) drawAABBs; ++ (BOOL) drawAABBs; + ++ (void) setDebugDraw: (BOOL) debugDraw; ++ (BOOL) debugDraw; + ++ (void) setSplitImpulse: (BOOL) splitImpulse; ++ (BOOL) splitImpulse; + ++ (void) setDrawContacts: (BOOL) drawContacts; ++ (BOOL) drawContacts; + +@end diff --git a/Extras/AllBulletDemosOSX/src/BTDemo.mm b/Extras/AllBulletDemosOSX/src/BTDemo.mm new file mode 100644 index 0000000..c961d18 --- /dev/null +++ b/Extras/AllBulletDemosOSX/src/BTDemo.mm @@ -0,0 +1,411 @@ +/* +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. +*/ + +#import "BTDemo.h" + +/////////////////////////////////////////////////////////////////////// +// Bullet includes + +#include "LinearMath/btScalar.h" +#include "LinearMath/btMinMax.h" + +#include "DemoApplication.h" +#include "DemoEntries.h" +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" + +#include "GLDebugDrawer.h" + +#include "LinearMath/btQuickprof.h" + + +/////////////////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark Globals + +static NSPoint MousePosition; +static NSSize ViewSize; +static int NumIterations = 10; +static BOOL DisableDeactivation = NO; +static BOOL DrawAABBs = NO; +static BOOL DebugDraw = NO; +static BOOL SplitImpulse = NO; +static BOOL DrawContacts = NO; + +/////////////////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark BTDemoEntry + +@interface BTDemoEntry : NSObject { + btDemoEntry *ctor; + DemoApplication *demo; +} + +- (id) initWithDemoEntry: (btDemoEntry*) constructor; +- (DemoApplication*) demo; +- (void) reset; + +@end + +@implementation BTDemoEntry + +- (id) initWithDemoEntry: (btDemoEntry*) constructor +{ + if ( self = [super init] ) + { + ctor = constructor; + [self reset]; + } + + return self; +} + +- (void) dealloc +{ + if ( demo ) delete demo; + [super dealloc]; +} + +- (DemoApplication*) demo +{ + return demo; +} + +- (void) reset +{ + if ( demo ) + { + if (demo->getDynamicsWorld()->getDebugDrawer()) + delete demo->getDynamicsWorld()->getDebugDrawer(); + + delete demo; + demo = NULL; + } + + demo = ctor->createFcn(); + btAssert(demo); + + if (demo->getDynamicsWorld()) + { + demo->getDynamicsWorld()->setDebugDrawer(new GLDebugDrawer()); + } + + #ifndef BT_NO_PROFILE + CProfileManager::Reset(); + #endif //BT_NO_PROFILE +} + +@end + +/////////////////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark BTDemo + + +@implementation BTDemo + ++ (NSArray*) demoNames +{ + static NSMutableArray *DEMOS = nil; + if ( !DEMOS ) + { + DEMOS = [[NSMutableArray alloc] init]; + + btDemoEntry* e = g_demoEntries; + while (e->createFcn) + { + [DEMOS addObject: [NSString stringWithUTF8String: e->name]]; + ++e; + } + } + + return DEMOS; +} + ++ (BOOL) isDemo: (NSString *) demoName +{ + return [[self demoNames] containsObject: demoName]; +} + ++ (BTDemo*) demoWithName: (NSString *) demoName +{ + if ( [BTDemo isDemo: demoName] ) + { + return [[[BTDemo alloc] initWithDemoName: demoName] autorelease]; + } + + return nil; +} + +- (id) initWithDemoName: (NSString *) demoName +{ + if ( self = [super init] ) + { + _demoName = [demoName copy]; + + // now walk the constructor list and find this demo + + btDemoEntry* e = g_demoEntries; + while (e->createFcn) + { + NSString *name = [NSString stringWithCString: e->name]; + if ( [name isEqualToString: demoName] ) + { + _demo = [[BTDemoEntry alloc] initWithDemoEntry: e]; + break; + } + + e++; + } + } + + return self; +} + +- (void) dealloc +{ + [_demoName release]; + [_demo release]; + [super dealloc]; +} + +- (void) reset +{ + [_demo reset]; + + [self contextWillResize]; + [self contextResized: ViewSize]; + [self contextDidResize]; +} + +- (NSString*) demoName +{ + return _demoName; +} + +#pragma mark - +#pragma mark BTOpenGLDisplayDelegate + +- (void) contextCreated +{} + +- (void) contextWillBeDestroyed +{} + +- (void) contextWillResize +{} + +- (void) contextResized: (NSSize) newSize +{ + ViewSize = newSize; + glViewport( 0, 0, (int) newSize.width, (int) newSize.height ); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + [_demo demo]->reshape( (int) newSize.width, (int) newSize.height ); +} + +- (void) contextDidResize +{} + +- (void) contextStateInvalidated +{} + +- (void) display: (float) deltaT +{ + DemoApplication *demo = [_demo demo]; + + if ( !demo ) + { + glClearColor( 1, 0.5, 1, 1 ); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + return; + } + + if (demo->getDynamicsWorld()) + { + if (SplitImpulse) + { + demo->getDynamicsWorld()->getSolverInfo().m_splitImpulse=1; + } else + { + demo->getDynamicsWorld()->getSolverInfo().m_splitImpulse=0; + } + } + if (DrawAABBs) + { + demo->setDebugMode(demo->getDebugMode() |btIDebugDraw::DBG_DrawAabb); + } + else + { + demo->setDebugMode(demo->getDebugMode() & (~btIDebugDraw::DBG_DrawAabb)); + } + + if (DebugDraw) + { + demo->setDebugMode(demo->getDebugMode() |btIDebugDraw::DBG_DrawWireframe); + } + else + { + demo->setDebugMode(demo->getDebugMode() & (~btIDebugDraw::DBG_DrawWireframe)); + } + + if (DrawContacts) + { + demo->setDebugMode(demo->getDebugMode() |btIDebugDraw::DBG_DrawContactPoints); + } + else + { + demo->setDebugMode(demo->getDebugMode() & (~btIDebugDraw::DBG_DrawContactPoints)); + } + + if (DisableDeactivation) + { + demo->setDebugMode(demo->getDebugMode() |btIDebugDraw::DBG_NoDeactivation); + } + else + { + demo->setDebugMode(demo->getDebugMode() & (~btIDebugDraw::DBG_NoDeactivation)); + } + + if (demo->getDynamicsWorld() && demo->getDynamicsWorld()->getWorldType() == BT_DISCRETE_DYNAMICS_WORLD) + { + btDiscreteDynamicsWorld* discreteWorld = (btDiscreteDynamicsWorld*) demo->getDynamicsWorld(); + discreteWorld->getSolverInfo().m_numIterations = NumIterations; + } + + if (!demo->isIdle()) + { + demo->clientMoveAndDisplay(); + } + else + { + demo->displayCallback(); + } + +} + +- (void) keyPressed: (unsigned char) key +{ + [_demo demo]->keyboardCallback(key, (int)MousePosition.x, (int)MousePosition.y ); +} + +- (void) keyReleased: (unsigned char) key +{} + +- (void) specialKeyPressed: (unsigned) key +{ + [_demo demo]->specialKeyboard(key,(int)MousePosition.x, (int)MousePosition.y ); +} + +- (void) specialKeyReleased: (unsigned) key +{} + +- (void) mouseButtonPressed: (unsigned) mouseButton +{ + [_demo demo]->mouseFunc( mouseButton, GLUT_DOWN, (int)MousePosition.x, (int)MousePosition.y ); +} + +- (void) mouseButtonReleased: (unsigned) mouseButton +{ + [_demo demo]->mouseFunc( mouseButton, GLUT_UP, (int)MousePosition.x, (int)MousePosition.y ); +} + +- (void) mouseMoved: (NSPoint) delta +{ + [_demo demo]->mouseMotionFunc((int)MousePosition.x, (int)MousePosition.y ); +} + +- (void) newMousePosition: (NSPoint) newMousePosition +{ + // Need to invert Y, since DemoApplication assumes origin at top-left + MousePosition = NSMakePoint( newMousePosition.x, ViewSize.height - newMousePosition.y ); +} + +- (void) scrollWheel: (NSPoint) delta +{} + +#pragma mark - +#pragma mark Global Simulation Properties + ++ (void) setIterations: (unsigned) iterations +{ + NumIterations = iterations; +} + ++ (unsigned) iterations +{ + return NumIterations; +} + ++ (unsigned) minIterations { return 1; } ++ (unsigned) maxIterations { return 1000; } + + ++ (void) setDisableDeactivation: (BOOL) disableDeactivation +{ + DisableDeactivation = disableDeactivation; +} + ++ (BOOL) disableDeactivation +{ + return DisableDeactivation; +} + ++ (void) setDrawAABBs: (BOOL) drawAABBs +{ + DrawAABBs = drawAABBs; +} + ++ (BOOL) drawAABBs +{ + return DrawAABBs; +} + ++ (void) setDebugDraw: (BOOL) debugDraw +{ + DebugDraw = debugDraw; +} + ++ (BOOL) debugDraw +{ + return DebugDraw; +} + ++ (void) setSplitImpulse: (BOOL) splitImpulse +{ + SplitImpulse = splitImpulse; +} + ++ (BOOL) splitImpulse +{ + return SplitImpulse; +} + ++ (void) setDrawContacts: (BOOL) drawContacts +{ + DrawContacts = drawContacts; +} + ++ (BOOL) drawContacts +{ + return DrawContacts; +} + + +@end diff --git a/Extras/AllBulletDemosOSX/src/BTDemosAppController.h b/Extras/AllBulletDemosOSX/src/BTDemosAppController.h new file mode 100644 index 0000000..62349e3 --- /dev/null +++ b/Extras/AllBulletDemosOSX/src/BTDemosAppController.h @@ -0,0 +1,54 @@ +/* +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. +*/ + +#import +#import "BTOpenGLView.h" +#import "BTSimulationParameters.h" +#import "BTDemo.h" + +@interface BTDemosAppController : NSObject { + + IBOutlet BTOpenGLView* _glView; + IBOutlet BTSimulationParameters *_parameters; + + BTDemo *_currentDemo; + BOOL _showParameters; +} + +/////////////////////////////////////////////////////////////////////// +// Public API + +- (void) setFullscreen: (BOOL) fullscreen; +- (BOOL) fullscreen; + +- (void) setShowParameters: (BOOL) showParameters; +- (BOOL) showParameters; + +- (NSArray*) demos; + +- (void) setDemo: (NSString*) demoName; +- (NSString*) demo; + +/////////////////////////////////////////////////////////////////////// +// IBActions + +- (IBAction) nextDemo: (id) sender; +- (IBAction) previousDemo: (id) sender; +- (IBAction) toggleFullscreen: (id) sender; +- (IBAction) toggleParameters: (id) sender; +- (IBAction) resetDemo: (id) sender; +- (IBAction) nullMenuTarget: (id) sender; + +@end diff --git a/Extras/AllBulletDemosOSX/src/BTDemosAppController.m b/Extras/AllBulletDemosOSX/src/BTDemosAppController.m new file mode 100644 index 0000000..5444713 --- /dev/null +++ b/Extras/AllBulletDemosOSX/src/BTDemosAppController.m @@ -0,0 +1,151 @@ +/* +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. +*/ + +#import "BTDemosAppController.h" + + +@implementation BTDemosAppController + +- (id) init +{ + if ( self = [super init] ) + { + // change cwd to .app/Contents/Resources + NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; + [[NSFileManager defaultManager] changeCurrentDirectoryPath:resourcePath]; + } + + return self; +} + +- (void) awakeFromNib +{} + +#pragma mark - +#pragma mark Public API + +- (void) setFullscreen: (BOOL) fullscreen +{ + [_glView setFullscreen: fullscreen]; +} + +- (BOOL) fullscreen +{ + return [_glView fullscreen]; +} + +- (void) setShowParameters: (BOOL) showParameters +{ + _showParameters = showParameters; +} + +- (BOOL) showParameters +{ + return _showParameters; +} + +- (NSArray*) demos +{ + return [BTDemo demoNames]; +} + +- (void) setDemo: (NSString*) demoName +{ + [_currentDemo release]; + [_glView setDelegate: nil]; + + _currentDemo = [[BTDemo demoWithName: demoName] retain]; + + if ( _currentDemo ) + { + // the demo is the rendering & input delegate for the gl view + [_glView setDelegate: _currentDemo]; + + [_currentDemo contextWillResize]; + [_currentDemo contextResized: [_glView bounds].size]; + [_currentDemo contextDidResize]; + } +} + +- (NSString*) demo +{ + return _currentDemo ? [_currentDemo demoName] : nil; +} + +#pragma mark - +#pragma mark IBActions + +- (IBAction) nextDemo: (id) sender +{ + NSArray *demos = [self demos]; + unsigned index = [demos indexOfObject: [self demo]]; + if ( index != NSNotFound ) + { + index = ( index + 1 ) % [demos count]; + [self setDemo: [demos objectAtIndex: index]]; + } +} + +- (IBAction) previousDemo: (id) sender +{ + NSArray *demos = [self demos]; + unsigned index = [demos indexOfObject: [self demo]]; + if ( index != NSNotFound ) + { + if ( index == 0 ) index = [demos count] - 1; + else index--; + + [self setDemo: [demos objectAtIndex: index]]; + } +} + +- (IBAction) toggleFullscreen: (id) sender +{ + [self setFullscreen: ![self fullscreen]]; +} + +- (IBAction) toggleParameters: (id) sender +{ + [self setShowParameters: ![self showParameters]]; +} + +- (IBAction) resetDemo: (id) sender +{ + [_currentDemo reset]; +} + +- (IBAction) nullMenuTarget: (id) sender +{ + // this handles a 10.4 bug. A menu bound to some property for toggling + // will not invoke unless it has a target and selector set. +} + +#pragma mark - +#pragma mark NSApplicationDelegate + +- (void) applicationDidFinishLaunching: (NSNotification *)aNotification +{ + // note: We load the first demo here and not in -awakeFromNib as the + // OpenGL view is instantiated, but not running yet at that point + + [self setDemo: [[self demos] objectAtIndex:0]]; +} + +- (BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication *)theApplication +{ + return YES; +} + +@end diff --git a/Extras/AllBulletDemosOSX/src/BTSimulationParameters.h b/Extras/AllBulletDemosOSX/src/BTSimulationParameters.h new file mode 100644 index 0000000..298c9dd --- /dev/null +++ b/Extras/AllBulletDemosOSX/src/BTSimulationParameters.h @@ -0,0 +1,47 @@ +/* +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. +*/ + +#import + +/* + BTSimulationParameters is an instanceable proxy for BTDemo's global + simulation properties. We're doing this so we can bind UI to something + in the nib file. +*/ + +@interface BTSimulationParameters : NSObject {} + +- (void) setIterations: (unsigned) iterations; +- (unsigned) iterations; + +- (unsigned) minIterations; +- (unsigned) maxIterations; + +- (void) setDisableDeactivation: (BOOL) disableDeactivation; +- (BOOL) disableDeactivation; + +- (void) setDrawAABBs: (BOOL) drawAABBs; +- (BOOL) drawAABBs; + +- (void) setDebugDraw: (BOOL) debugDraw; +- (BOOL) debugDraw; + +- (void) setSplitImpulse: (BOOL) splitImpulse; +- (BOOL) splitImpulse; + +- (void) setDrawContacts: (BOOL) drawContacts; +- (BOOL) drawContacts; + +@end diff --git a/Extras/AllBulletDemosOSX/src/BTSimulationParameters.m b/Extras/AllBulletDemosOSX/src/BTSimulationParameters.m new file mode 100644 index 0000000..ab87cd9 --- /dev/null +++ b/Extras/AllBulletDemosOSX/src/BTSimulationParameters.m @@ -0,0 +1,96 @@ +/* +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. +*/ + +#import "BTSimulationParameters.h" +#import "BTDemo.h" + +@implementation BTSimulationParameters + +- (id) init +{ + if ( self = [super init] ) + {} + + return self; +} + +#pragma mark Public API + +- (void) setIterations: (unsigned) iterations +{ + [BTDemo setIterations: iterations]; +} + +- (unsigned) iterations +{ + return [BTDemo iterations]; +} + +- (unsigned) minIterations { return [BTDemo minIterations]; } +- (unsigned) maxIterations { return [BTDemo maxIterations]; } + + +- (void) setDisableDeactivation: (BOOL) disableDeactivation +{ + [BTDemo setDisableDeactivation: disableDeactivation]; +} + +- (BOOL) disableDeactivation +{ + return [BTDemo disableDeactivation]; +} + +- (void) setDrawAABBs: (BOOL) drawAABBs +{ + [BTDemo setDrawAABBs: drawAABBs]; +} + +- (BOOL) drawAABBs +{ + return [BTDemo drawAABBs];; +} + +- (void) setDebugDraw: (BOOL) debugDraw +{ + [BTDemo setDebugDraw: debugDraw]; +} + +- (BOOL) debugDraw +{ + return [BTDemo debugDraw]; +} + +- (void) setSplitImpulse: (BOOL) splitImpulse +{ + [BTDemo setSplitImpulse: splitImpulse]; +} + +- (BOOL) splitImpulse +{ + return [BTDemo splitImpulse]; +} + + +- (void) setDrawContacts: (BOOL) drawContacts +{ + [BTDemo setDrawContacts: drawContacts]; +} + +- (BOOL) drawContacts +{ + return [BTDemo drawContacts]; +} + +@end diff --git a/Extras/AllBulletDemosOSX/src/toolkit/BTFullscreenWindow.h b/Extras/AllBulletDemosOSX/src/toolkit/BTFullscreenWindow.h new file mode 100644 index 0000000..3172f95 --- /dev/null +++ b/Extras/AllBulletDemosOSX/src/toolkit/BTFullscreenWindow.h @@ -0,0 +1,25 @@ +/* +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. +*/ + +#import + + +@interface BTFullScreenWindow : NSWindow { + +} + +- (id) initForScreen: (NSScreen *) screen; + +@end diff --git a/Extras/AllBulletDemosOSX/src/toolkit/BTFullscreenWindow.m b/Extras/AllBulletDemosOSX/src/toolkit/BTFullscreenWindow.m new file mode 100644 index 0000000..2528f6e --- /dev/null +++ b/Extras/AllBulletDemosOSX/src/toolkit/BTFullscreenWindow.m @@ -0,0 +1,48 @@ +/* +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. +*/ + +#import "BTFullScreenWindow.h" + + +@implementation BTFullScreenWindow + +- (id) initForScreen: (NSScreen *) screen +{ + NSRect frame = [screen frame]; + frame.size.height -= [NSMenuView menuBarHeight]; + + self = [self initWithContentRect: frame + styleMask: NSBorderlessWindowMask + backing: NSBackingStoreBuffered + defer: YES + screen: screen ]; + if ( self ) + { + /* + For some reason, without this + we lose mouse moved events in fullscreen + */ + [self setAcceptsMouseMovedEvents: YES]; + } + + return self; +} + +- (BOOL)canBecomeKeyWindow +{ + return YES; +} + +@end diff --git a/Extras/AllBulletDemosOSX/src/toolkit/BTGLUTKeyAdapter.h b/Extras/AllBulletDemosOSX/src/toolkit/BTGLUTKeyAdapter.h new file mode 100644 index 0000000..3d19f47 --- /dev/null +++ b/Extras/AllBulletDemosOSX/src/toolkit/BTGLUTKeyAdapter.h @@ -0,0 +1,46 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef __BT_KEY_CODE_H__ +#define __BT_KEY_CODE_H__ + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + @brief Determine if a key is a letter. + @return true if @a keycode is a letter, and not a control + or modifier key. E.g., the letter 'b' is, where the Esc key ( BTKey_Escape ) is not. +*/ +extern BOOL BTKeyIsAlpha( int ); + +/** + @brief Determine if a key is a GLUT special key. ( arrow, F-Keys, etc ) +*/ +extern BOOL BTKeyIsSpecial( int keycode ); + +/** + @brief Convert an OS X keycode to GLUT Special key representation +*/ +extern int BTKeyTranslateKeyCodeToSpecial( int ); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/Extras/AllBulletDemosOSX/src/toolkit/BTGLUTKeyAdapter.m b/Extras/AllBulletDemosOSX/src/toolkit/BTGLUTKeyAdapter.m new file mode 100644 index 0000000..786498d --- /dev/null +++ b/Extras/AllBulletDemosOSX/src/toolkit/BTGLUTKeyAdapter.m @@ -0,0 +1,128 @@ +/* +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. +*/ + +#import "BTGLUTKeyAdapter.h" +#import + +BOOL BTKeyIsAlpha( int key ) +{ + return !BTKeyIsSpecial( key ); +} + +BOOL BTKeyIsSpecial( int keycode ) +{ + BOOL ret = NO; + switch( keycode ) + { + case NSUpArrowFunctionKey: + case NSDownArrowFunctionKey: + case NSLeftArrowFunctionKey: + case NSRightArrowFunctionKey: + case NSF1FunctionKey: + case NSF2FunctionKey: + case NSF3FunctionKey: + case NSF4FunctionKey: + case NSF5FunctionKey: + case NSF6FunctionKey: + case NSF7FunctionKey: + case NSF8FunctionKey: + case NSF9FunctionKey: + case NSF10FunctionKey: + case NSF11FunctionKey: + case NSF12FunctionKey: + ret = YES; + break; + + default: break; + } + + return ret; +} + + +int BTKeyTranslateKeyCodeToSpecial( int kc ) +{ + int ret = kc; + switch( kc ) + { + case NSUpArrowFunctionKey: + ret = GLUT_KEY_UP; + break; + + case NSDownArrowFunctionKey: + ret = GLUT_KEY_DOWN; + break; + + case NSLeftArrowFunctionKey: + ret = GLUT_KEY_LEFT; + break; + + case NSRightArrowFunctionKey: + ret = GLUT_KEY_RIGHT; + break; + + case NSF1FunctionKey: + ret = GLUT_KEY_F1; + break; + + case NSF2FunctionKey: + ret = GLUT_KEY_F2; + break; + + case NSF3FunctionKey: + ret = GLUT_KEY_F3; + break; + + case NSF4FunctionKey: + ret = GLUT_KEY_F4; + break; + + case NSF5FunctionKey: + ret = GLUT_KEY_F5; + break; + + case NSF6FunctionKey: + ret = GLUT_KEY_F6; + break; + + case NSF7FunctionKey: + ret = GLUT_KEY_F7; + break; + + case NSF8FunctionKey: + ret = GLUT_KEY_F8; + break; + + case NSF9FunctionKey: + ret = GLUT_KEY_F9; + break; + + case NSF10FunctionKey: + ret = GLUT_KEY_F10; + break; + + case NSF11FunctionKey: + ret = GLUT_KEY_F11; + break; + + case NSF12FunctionKey: + ret = GLUT_KEY_F12; + break; + + default: break; + } + + return ret; +} diff --git a/Extras/AllBulletDemosOSX/src/toolkit/BTOpenGLDisplayDelegate.h b/Extras/AllBulletDemosOSX/src/toolkit/BTOpenGLDisplayDelegate.h new file mode 100644 index 0000000..41d5069 --- /dev/null +++ b/Extras/AllBulletDemosOSX/src/toolkit/BTOpenGLDisplayDelegate.h @@ -0,0 +1,50 @@ +/* +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. +*/ + +#import + + +@protocol BTOpenGLDisplayDelegate + +- (void) contextCreated; +- (void) contextWillBeDestroyed; +- (void) contextWillResize; +- (void) contextResized: (NSSize) newSize; +- (void) contextDidResize; +- (void) contextStateInvalidated; + +- (void) display: (float) deltaT; + +/////////////////////////////////////////////////////////////////////// +// ASCII keypresses + +- (void) keyPressed: (unsigned char) key; +- (void) keyReleased: (unsigned char) key; + +/////////////////////////////////////////////////////////////////////// +// GLUT Special Keys, such as GLUT_KEY_LEFT ( "left arrow key" ) + +- (void) specialKeyPressed: (unsigned) GLUTKey; +- (void) specialKeyReleased: (unsigned) GLUTKey; + +/////////////////////////////////////////////////////////////////////// +// Mouse. button is GLUT_LEFT_MOUSE, GLUT_RIGHT_MOUSE, etc. + +- (void) mouseButtonPressed: (unsigned) mouseButton; +- (void) mouseButtonReleased: (unsigned) mouseButton; +- (void) mouseMoved: (NSPoint) delta; +- (void) newMousePosition: (NSPoint) newMousePosition; +- (void) scrollWheel: (NSPoint) delta; +@end diff --git a/Extras/AllBulletDemosOSX/src/toolkit/BTOpenGLView.h b/Extras/AllBulletDemosOSX/src/toolkit/BTOpenGLView.h new file mode 100644 index 0000000..a5f4c72 --- /dev/null +++ b/Extras/AllBulletDemosOSX/src/toolkit/BTOpenGLView.h @@ -0,0 +1,65 @@ +/* +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. +*/ + +#import +#import +#import "BTOpenGLDisplayDelegate.h" + +@interface BTOpenGLView : NSView +{ + IBOutlet id _delegate; + + BOOL _firstFrame, + _setupBoundsChangeNotification, + _isFullScreen, + _multisample, + _vblSync, + _suppressResize; + + NSOpenGLContext *_windowedContext; + + unsigned int _modifierFlags; + + float _interval, + _currentFPS; + + double _lastFrameTime; + + NSWindow *_fullscreenWindow, + *_windowedWindow; + + NSTimer *_timer; +} + +- (void) setDelegate: (id ) delegate; +- (id ) delegate; + +- (void) setTargetFPS: (float) fps; +- (float) targetFPS; +- (float) currentFPS; + +- (void) setFullscreen: (BOOL) yesno; +- (BOOL) fullscreen; + +- (void) setMultisampleRendering: (BOOL) multisample; +- (BOOL) multisampleRendering; + +- (void) setVBLSync: (BOOL) sync; +- (BOOL) vblSync; + +- (NSOpenGLContext*) openGLContext; + + +@end diff --git a/Extras/AllBulletDemosOSX/src/toolkit/BTOpenGLView.m b/Extras/AllBulletDemosOSX/src/toolkit/BTOpenGLView.m new file mode 100644 index 0000000..397764a --- /dev/null +++ b/Extras/AllBulletDemosOSX/src/toolkit/BTOpenGLView.m @@ -0,0 +1,603 @@ +/* +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. +*/ + +#import "BTOpenGLView.h" + +#include +#import +#import + +#import "BTFullScreenWindow.h" +#import "BTGLUTKeyAdapter.h" + +#pragma mark - +#pragma mark Private Methods + +@interface BTOpenGLView (Internal) + +- (void) update; +- (void) boundsDidChange: (NSNotification *) notification; +- (void) setVBL: (BOOL*) vbl forContext: (NSOpenGLContext*) context; +- (void) setMultithreaded: (BOOL) mt; +- (NSOpenGLPixelFormat*) windowedPixelFormat: (BOOL*) antialias; + +@end + +@implementation BTOpenGLView + +#pragma mark - +#pragma mark Bootstrap + +- (id)initWithFrame:(NSRect)frameRect +{ + self = [super initWithFrame:frameRect]; + if (self == nil) + { + NSLog( @"BTOpenGLView::initWithFrame - Unable to init" ); + return nil; + } + + _modifierFlags = 0; + _multisample = YES; + _vblSync = YES; + _firstFrame = YES; + _setupBoundsChangeNotification = NO; + + /* + Set up the windowed context -- it will be assigned to the + view later, not now. + */ + _windowedContext = [[NSOpenGLContext alloc] initWithFormat: [self windowedPixelFormat: &_multisample] + shareContext: nil]; + + [self setVBL: &_vblSync forContext: _windowedContext]; + + if (_windowedContext == nil) + { + NSLog(@"Got nil windowed context"); + [self dealloc]; + return nil; + } + + /* + Setup and start the update timer. + */ + _interval = 1.0 / 60.0; + _timer = [[NSTimer scheduledTimerWithTimeInterval: _interval + target: self + selector: @selector(update) + userInfo: nil + repeats: YES ] retain]; + + [[NSRunLoop currentRunLoop] addTimer: _timer forMode: NSEventTrackingRunLoopMode]; + + return self; +} + +- (void)dealloc +{ + [_timer invalidate]; + [_timer release]; + + [_delegate contextWillBeDestroyed]; + + [_windowedContext release]; + + [[NSNotificationCenter defaultCenter] removeObserver: self]; + + [super dealloc]; +} + +- (void) awakeFromNib +{ + NSWindow *window = [self window]; + [window setAcceptsMouseMovedEvents: YES]; + [window makeFirstResponder: self]; + [window setInitialFirstResponder: self]; +} + +- (void)drawRect:(NSRect)rect +{ + [self update]; +} + +#pragma mark - +#pragma mark Public API + +- (void) setDelegate: (id ) delegate +{ + // we don't retain delegates + _delegate = delegate; +} + +- (id ) delegate +{ + return _delegate; +} + +- (void) setTargetFPS: (float) fps +{ + float newInterval = 1.0 / fps; + if ( ABS( newInterval - _interval ) > 1.0e-3 ) + { + _interval = newInterval; + + [_timer invalidate]; + [_timer release]; + + _timer = [[NSTimer scheduledTimerWithTimeInterval: _interval + target: self + selector: @selector(update) + userInfo: nil + repeats: YES ] retain]; + + [[NSRunLoop currentRunLoop] addTimer: _timer forMode: NSEventTrackingRunLoopMode]; + } + +} + +- (float) targetFPS +{ + return 1.0 / _interval; +} + +- (float) currentFPS +{ + return _currentFPS; +} + +- (void) setFullscreen: (BOOL) fullscreen +{ + if ( fullscreen == _isFullScreen ) return; + + _isFullScreen = fullscreen; + _suppressResize = YES; + + if ( _isFullScreen ) + { + _windowedWindow = [self window]; + + /* + Detach & retain the content view from the non-fullscreen window. + */ + + NSView *contentView = [_windowedWindow contentView]; + [contentView retain]; + [contentView removeFromSuperviewWithoutNeedingDisplay]; + + /* + Create a fullscreen window, attach the content view, + and release the content view since the fullscreen window retained it. + */ + + _fullscreenWindow = [[BTFullScreenWindow alloc] initForScreen: [_windowedWindow screen]]; + [_fullscreenWindow setContentView: contentView ]; + [_fullscreenWindow makeKeyAndOrderFront:nil]; + [contentView release]; + + /* + Hide the old window + */ + [_windowedWindow orderOut: nil]; + + /* + Now, use the SetSystemUIMode API to auto-hide the dock + */ + + OSStatus error = SetSystemUIMode( kUIModeContentSuppressed, 0 ); + if ( error != noErr) + { + NSLog(@"Error couldn't set SystemUIMode: %ld", (long)error); + } + + } + else if ( _fullscreenWindow ) + { + /* + Detach and retain the content view from the fullscreen window + */ + NSView *contentView = [_fullscreenWindow contentView]; + [contentView retain]; + [contentView removeFromSuperviewWithoutNeedingDisplay]; + + /* + Reparent the content view to the non-fullscreen window, + and release it since it's now owned by the non-fullscreen window + */ + [_windowedWindow setContentView: contentView]; + [contentView release]; + + [_windowedWindow makeKeyAndOrderFront: nil]; + + /* + Release the fullscreen window + */ + [_fullscreenWindow orderOut: nil]; + [_fullscreenWindow release]; + _fullscreenWindow = nil; + + /* + Restore dock's normal behaior + */ + + OSStatus error = SetSystemUIMode( kUIModeNormal, 0 ); + if ( error != noErr) + { + NSLog(@"Error couldn't set SystemUIMode: %ld", (long)error); + } + } + + _suppressResize = NO; + + [self boundsDidChange: nil]; +} + +- (BOOL) fullscreen +{ + return _isFullScreen; +} + +- (void) setMultisampleRendering: (BOOL) multisample +{ + if ( multisample == _multisample ) return; + + _multisample = multisample; + _firstFrame = YES; + + + NSOpenGLContext *oldWindowedContext = _windowedContext; + _windowedContext = [[NSOpenGLContext alloc] initWithFormat: [self windowedPixelFormat: &_multisample] + shareContext: oldWindowedContext ]; + + [self setVBL: &_vblSync forContext: _windowedContext]; + + [oldWindowedContext release]; + [_windowedContext setView: self]; + [_windowedContext makeCurrentContext]; + [_windowedContext update]; + [self update]; +} + +- (BOOL) multisampleRendering +{ + return _multisample; +} + +- (void) setVBLSync: (BOOL) sync +{ + if ( sync == _vblSync ) return; + + _vblSync = sync; + [self setVBL: &_vblSync forContext: _windowedContext]; +} + +- (BOOL) vblSync +{ + return _vblSync; +} + +- (NSOpenGLContext *) openGLContext +{ + return _windowedContext; +} + +#pragma mark - +#pragma mark NSView Overrides + +- (BOOL) isOpaque +{ + return YES; +} + +- (BOOL) acceptsFirstResponder +{ + return YES; +} + +- (void) keyDown:(NSEvent *)theEvent +{ + int key = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]; + + if ( BTKeyIsAlpha( key )) + { + [ _delegate keyPressed: key ]; + } + else + { + [_delegate specialKeyPressed: BTKeyTranslateKeyCodeToSpecial( key )]; + } +} + +- (void) keyUp:(NSEvent *)theEvent +{ + int key = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]; + + if ( BTKeyIsAlpha( key )) + { + [ _delegate keyReleased: key ]; + } + else + { + [_delegate specialKeyReleased: BTKeyTranslateKeyCodeToSpecial( key )]; + } +} + +- (void) mouseDown: (NSEvent *) event +{ + int button = GLUT_LEFT_BUTTON; + switch( [event buttonNumber] ) + { + case 0: button = GLUT_LEFT_BUTTON; break; + case 1: button = GLUT_RIGHT_BUTTON; break; + case 2: button = GLUT_MIDDLE_BUTTON; break; + default: break; + } + + if ( _modifierFlags & NSControlKeyMask ) button = GLUT_RIGHT_BUTTON; + else if ( _modifierFlags & NSAlternateKeyMask ) button = GLUT_MIDDLE_BUTTON; + + [_delegate mouseButtonPressed: button]; +} + +- (void) mouseUp: (NSEvent *) event +{ + int button = GLUT_LEFT_BUTTON; + switch( [event buttonNumber] ) + { + case 0: button = GLUT_LEFT_BUTTON; break; + case 1: button = GLUT_RIGHT_BUTTON; break; + case 2: button = GLUT_MIDDLE_BUTTON; break; + default: break; + } + + if ( _modifierFlags & NSControlKeyMask ) button = GLUT_RIGHT_BUTTON; + else if ( _modifierFlags & NSAlternateKeyMask ) button = GLUT_MIDDLE_BUTTON; + + [_delegate mouseButtonReleased: button]; +} + +-(void) mouseMoved: (NSEvent *) event +{ + float dx = [event deltaX], + dy = [event deltaY]; + + NSPoint locationInView = [self convertPoint: [event locationInWindow] fromView: nil ]; + + [_delegate mouseMoved: NSMakePoint( dx, dy )]; + [_delegate newMousePosition: locationInView]; +} + +-(void) mouseDragged: (NSEvent *) event +{ + [self mouseMoved: event]; +} + +- (void) scrollWheel: (NSEvent *) event +{ + float dx = [event deltaX], + dy = [event deltaY]; + + [_delegate scrollWheel: NSMakePoint( dx, dy )]; +} + +- (void)flagsChanged:(NSEvent *) event +{ + _modifierFlags = [event modifierFlags]; +} + + +#pragma mark - +#pragma mark Private + +- (void) update +{ + if ( !_setupBoundsChangeNotification ) + { + _setupBoundsChangeNotification = YES; + + /* + This is hacky, but basically, we can't handle bounds-changing + ops correctly until everything's set up correctly. + */ + [self setPostsBoundsChangedNotifications:YES]; + [[NSNotificationCenter defaultCenter] addObserver: self + selector: @selector( boundsDidChange: ) + name: NSViewFrameDidChangeNotification + object: nil]; + } + + if (_firstFrame) + { + [_windowedContext setView:self]; + } + + [_windowedContext makeCurrentContext]; + + if (_firstFrame) + { + _firstFrame = NO; + + [_delegate contextCreated]; + + if ( _multisample ) + { + glEnable (GL_MULTISAMPLE_ARB); + // this fucks up text rendering, on nVIDIA, at least + //glHint (GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); + } + else + { + glDisable( GL_MULTISAMPLE_ARB ); + } + + [self setMultithreaded: NO]; + + NSSize contextSize; + if ( _isFullScreen ) + { + contextSize.width = CGDisplayPixelsWide(kCGDirectMainDisplay); + contextSize.height = CGDisplayPixelsHigh(kCGDirectMainDisplay); + } + else + { + contextSize = [self bounds].size; + } + + [_delegate contextWillResize]; + [_delegate contextResized: contextSize]; + [_delegate contextDidResize]; + [_delegate contextStateInvalidated]; + } + + double now = CFAbsoluteTimeGetCurrent(); + + if ( _delegate) [_delegate display: now - _lastFrameTime]; + else + { + glClearColor( 0.5, 0.5, 0.5, 1 ); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + } + + _lastFrameTime = now; + + + [[NSOpenGLContext currentContext] flushBuffer]; + + /* + Now, update our FPS + */ + + { + static unsigned int frameCounter = 1; + static double lastCheckTime = 0; + + double elapsed = now - lastCheckTime; + if ( elapsed > 1.0 ) + { + _currentFPS = (float) ( ((double) frameCounter ) / elapsed ); + + lastCheckTime = now; + frameCounter = 0; + } + + frameCounter++; + } +} + +- (void) boundsDidChange: (NSNotification *) notification +{ + if ( _suppressResize ) return; + + [_windowedContext setView:self]; + [_windowedContext makeCurrentContext]; + [_windowedContext update]; + + NSSize contextSize = [self bounds].size; + + if ( _delegate ) + { + [_delegate contextWillResize]; + [_delegate contextResized: contextSize ]; + [_delegate contextDidResize]; + } + else + { + glViewport( 0, 0, (int) contextSize.width, (int) contextSize.height ); + } +} + +- (void) setVBL: (BOOL*) vbl forContext: (NSOpenGLContext*) context +{ + GLint value = *vbl ? 1 : 0; + [context setValues: &value forParameter: NSOpenGLCPSwapInterval]; + + *vbl = value ? YES : NO; +} + +- (void) setMultithreaded: (BOOL) mt +{ + CGLError err = kCGLNoError; + CGLContextObj ctx = CGLGetCurrentContext(); + + // Enable Apple's multi-threaded GL engine -- it's generally useful for + // high vertex throughput. Not high fragment situations + + if ( mt ) + { + err = CGLEnable( ctx, kCGLCEMPEngine ); + } + else + { + err = CGLDisable( ctx, kCGLCEMPEngine ); + } + + if (err != kCGLNoError ) + { + NSLog( @"BTOpenGLView -setMultithreaded: forContext: -- Unable to %s multithreaded GL", + mt ? "enable" : "disable" ); + } +} + +- (NSOpenGLPixelFormat*) windowedPixelFormat: (BOOL*) antialias +{ + NSOpenGLPixelFormatAttribute aaAttrs[] = + { + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAAccelerated, + NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)32, + NSOpenGLPFAStencilSize, (NSOpenGLPixelFormatAttribute)0, + NSOpenGLPFASingleRenderer, + NSOpenGLPFASampleBuffers, (NSOpenGLPixelFormatAttribute)( 1 ), + NSOpenGLPFASamples, (NSOpenGLPixelFormatAttribute)( 4 ), + NSOpenGLPFAScreenMask, (NSOpenGLPixelFormatAttribute) CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), + NSOpenGLPFANoRecovery, + (NSOpenGLPixelFormatAttribute)0 + }; + + NSOpenGLPixelFormatAttribute vanillaAttrs[] = + { + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAAccelerated, + NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)32, + NSOpenGLPFAStencilSize, (NSOpenGLPixelFormatAttribute)0, + NSOpenGLPFASingleRenderer, + NSOpenGLPFASampleBuffers, (NSOpenGLPixelFormatAttribute)( 0 ), + NSOpenGLPFASamples, (NSOpenGLPixelFormatAttribute)( 0 ), + NSOpenGLPFAScreenMask, (NSOpenGLPixelFormatAttribute) CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), + NSOpenGLPFANoRecovery, + (NSOpenGLPixelFormatAttribute)0 + }; + + NSOpenGLPixelFormat* fmt = 0; + + if ( *antialias ) + { + fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: (NSOpenGLPixelFormatAttribute*) aaAttrs]; + if ( nil == fmt ) + { + *antialias = NO; + fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: (NSOpenGLPixelFormatAttribute*) vanillaAttrs]; + } + } + else + { + fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: (NSOpenGLPixelFormatAttribute*) vanillaAttrs]; + } + + return fmt; +} + + +@end diff --git a/Extras/CDTestFramework/AntTweakBar/ChangeLog.txt b/Extras/CDTestFramework/AntTweakBar/ChangeLog.txt new file mode 100644 index 0000000..3277df7 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/ChangeLog.txt @@ -0,0 +1,23 @@ +--- AntTweakBar library changes --- + +- Version 1.04 + OpenGL: Vertex buffer object state and Vertex/fragment program and object states are now reset and restored by TwDraw (thanks to Dylan and Siva for pointing this out). + +- Version 1.03 (2006/10/28) + Medium font is now antialiased. + Now also compiles on 64 bits x86 platform; use Makefile.x86_64 (thanks to Herling). + Slight changes to avoid visual 8 secure crt warnings. + Correct behaviour if min/max values are not defined. + Modif to avoid looping to max value when reaching zero with unsigned types. + Min/max/step commands for type TW_TYPE_CHAR now read ascii codes (not characters). + Add FPU precision control (because DirectX changes it). + Fix problem that occurs when the lib is initialized/unitialized more than once (thanks Lukasz for reporting it). + Distribution follows Savannah's recommendations. + +- Version 1.02 (2006/09/27) + Library sources released. + +- Version 1.01 (2006/09/14) + First official release. + + \ No newline at end of file diff --git a/Extras/CDTestFramework/AntTweakBar/Clean.bat b/Extras/CDTestFramework/AntTweakBar/Clean.bat new file mode 100644 index 0000000..34d2a4f --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/Clean.bat @@ -0,0 +1,19 @@ +RMDIR /S /Q src\debug +RMDIR /S /Q src\release +CD src +DEL *.ncb *.aps *.o *.bak +DEL /A:h *.suo +CD .. +RMDIR /S /Q lib\debug +RMDIR /S /Q examples\debug +CD examples +DEL *.ncb *.aps *.o *.bak +DEL /A:h *.suo +DEL /S BuildLog.htm +DEL bin\*.obj +DEL bin\*.idb +CD .. + +PAUSE + + diff --git a/Extras/CDTestFramework/AntTweakBar/License.txt b/Extras/CDTestFramework/AntTweakBar/License.txt new file mode 100644 index 0000000..0e3f293 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/License.txt @@ -0,0 +1,23 @@ +--- AntTweakBar license --- + +Copyright © 2005, 2006 Philippe Decaudin + +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. + +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. + + +http://www.antisphere.com diff --git a/Extras/CDTestFramework/AntTweakBar/Readme.txt b/Extras/CDTestFramework/AntTweakBar/Readme.txt new file mode 100644 index 0000000..87c46cb --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/Readme.txt @@ -0,0 +1,15 @@ +--- AntTweakBar development library --- + + +AntTweakBar is a small and easy-to-use C/C++ library that allows programmers +to quickly add a light and intuitive GUI into OpenGL and DirectX based +graphic programs to interactively tweak them. + +This package includes the development version of the AntTweakBar library +for GNU/Linux and Windows, + some program examples (sources + binaries). + +For installation and documentation please refer to: +http://www.antisphere.com/Wiki/tools:anttweakbar + + +Philippe Decaudin - http://www.antisphere.com - 2006/05/20 diff --git a/Extras/CDTestFramework/AntTweakBar/examples/Examples.ncb b/Extras/CDTestFramework/AntTweakBar/examples/Examples.ncb new file mode 100644 index 0000000000000000000000000000000000000000..57e218451ad7a728ba261536e0daf508abe46932 GIT binary patch literal 150528 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 a;m7o!(ZI_8%&?C~eXN1U8u(wJf&T)-|8L>| literal 0 HcmV?d00001 diff --git a/Extras/CDTestFramework/AntTweakBar/examples/Examples.sln b/Extras/CDTestFramework/AntTweakBar/examples/Examples.sln new file mode 100644 index 0000000..728596e --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/examples/Examples.sln @@ -0,0 +1,65 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwCopyDLL", "TwCopyDLL.vcproj", "{AB180E0E-0EFA-4AD4-8F08-4492D144D963}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleGLFW", "TwSimpleGLFW.vcproj", "{29C096AF-172E-4A36-A1FE-E15B259D6834}" + ProjectSection(ProjectDependencies) = postProject + {AB180E0E-0EFA-4AD4-8F08-4492D144D963} = {AB180E0E-0EFA-4AD4-8F08-4492D144D963} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleGLUT", "TwSimpleGLUT.vcproj", "{CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}" + ProjectSection(ProjectDependencies) = postProject + {AB180E0E-0EFA-4AD4-8F08-4492D144D963} = {AB180E0E-0EFA-4AD4-8F08-4492D144D963} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleSDL", "TwSimpleSDL.vcproj", "{3B516919-D0DA-43CE-820E-8306368F605B}" + ProjectSection(ProjectDependencies) = postProject + {AB180E0E-0EFA-4AD4-8F08-4492D144D963} = {AB180E0E-0EFA-4AD4-8F08-4492D144D963} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleDX9", "TwSimpleDX9.vcproj", "{6B414E54-701C-4ED3-9034-F5CD7BFC3451}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwAdvanced1", "TwAdvanced1.vcproj", "{008D1CEC-1586-4C89-B524-DF15D9605163}" + ProjectSection(ProjectDependencies) = postProject + {AB180E0E-0EFA-4AD4-8F08-4492D144D963} = {AB180E0E-0EFA-4AD4-8F08-4492D144D963} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Debug.ActiveCfg = Debug|Win32 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Debug.Build.0 = Debug|Win32 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Release.ActiveCfg = Release|Win32 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Release.Build.0 = Release|Win32 + {29C096AF-172E-4A36-A1FE-E15B259D6834}.Debug.ActiveCfg = Debug|Win32 + {29C096AF-172E-4A36-A1FE-E15B259D6834}.Debug.Build.0 = Debug|Win32 + {29C096AF-172E-4A36-A1FE-E15B259D6834}.Release.ActiveCfg = Release|Win32 + {29C096AF-172E-4A36-A1FE-E15B259D6834}.Release.Build.0 = Release|Win32 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Debug.ActiveCfg = Debug|Win32 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Debug.Build.0 = Debug|Win32 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Release.ActiveCfg = Release|Win32 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Release.Build.0 = Release|Win32 + {3B516919-D0DA-43CE-820E-8306368F605B}.Debug.ActiveCfg = Debug|Win32 + {3B516919-D0DA-43CE-820E-8306368F605B}.Debug.Build.0 = Debug|Win32 + {3B516919-D0DA-43CE-820E-8306368F605B}.Release.ActiveCfg = Release|Win32 + {3B516919-D0DA-43CE-820E-8306368F605B}.Release.Build.0 = Release|Win32 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Debug.ActiveCfg = Debug|Win32 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Debug.Build.0 = Debug|Win32 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Release.ActiveCfg = Release|Win32 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Release.Build.0 = Release|Win32 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Debug.ActiveCfg = Debug|Win32 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Debug.Build.0 = Debug|Win32 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Release.ActiveCfg = Release|Win32 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/Extras/CDTestFramework/AntTweakBar/examples/Examples.suo b/Extras/CDTestFramework/AntTweakBar/examples/Examples.suo new file mode 100644 index 0000000000000000000000000000000000000000..0a6131804ea3796859a442915f1841d30f552bf2 GIT binary patch literal 15360 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 /dev/null +EXP_PATH = "export LD_LIBRARY_PATH=\"../../lib:$(LD_LIBRARY_PATH)\"" + + +####### Files + + +SRC_FILES = TwSimpleGLFW.c TwSimpleGLUT.c TwSimpleSDL.c TwAdvanced1.cpp + + +####### Build rules + + +#first: depend all +first: all + +all: Makefile $(SRC_FILES) + + @echo "===== Build TwSimpleGLFW ====" + $(CXX) $(CXXFLAGS) $(INCPATH) TwSimpleGLFW.c $(LFLAGS) -lglfw $(LIBS) -o $(OUT_DIR)/TwSimpleGLFW.out + @echo "$(EXP_PATH) ; ./TwSimpleGLFW.out" > $(OUT_DIR)/TwSimpleGLFW + + @echo "===== Build TwSimpleGLUT ====" + $(CXX) $(CXXFLAGS) $(INCPATH) TwSimpleGLUT.c $(LFLAGS) -lglut $(LIBS) -o $(OUT_DIR)/TwSimpleGLUT.out + @echo "$(EXP_PATH) ; ./TwSimpleGLUT.out" > $(OUT_DIR)/TwSimpleGLUT + + @echo "===== Build TwSimpleSDL ====" + $(CXX) $(CXXFLAGS) $(INCPATH) TwSimpleSDL.c $(LFLAGS) -lSDL $(LIBS) -o $(OUT_DIR)/TwSimpleSDL.out + @echo "$(EXP_PATH) ; ./TwSimpleSDL.out" > $(OUT_DIR)/TwSimpleSDL + + @echo "===== Build TwAdvanced1 ====" + $(CXX) $(CXXFLAGS) $(INCPATH) TwAdvanced1.cpp $(LFLAGS) -lglfw $(LIBS) -o $(OUT_DIR)/TwAdvanced1.out + @echo "$(EXP_PATH) ; ./TwAdvanced1.out" > $(OUT_DIR)/TwAdvanced1 + +# append dependencies to this Makefile +#depend: +# @echo "===== Make dependencies =====" +# makedepend -Y +# makedepend -a -Y -- $(CXXFLAGS) $(INCPATH) -- $(SRC_FILES) $(NO_STDERR) + + +# clean temporary files +clean: + @echo "===== Clean =====" + -$(DEL_FILE) *.o + -$(DEL_FILE) *~ core *.core *.stackdump + -$(DEL_FILE) debug/* + -$(DEL_DIR) debug + + +####### DEPENDENCIES + +TwSimpleGLFW.o: ../include/AntTweakBar.h +TwSimpleGLUT.o: ../include/AntTweakBar.h +TwSimpleSDL.o: ../include/AntTweakBar.h +TwAdvanced1.o: ../include/AntTweakBar.h diff --git a/Extras/CDTestFramework/AntTweakBar/examples/Makefile.x86_64 b/Extras/CDTestFramework/AntTweakBar/examples/Makefile.x86_64 new file mode 100644 index 0000000..067e1bb --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/examples/Makefile.x86_64 @@ -0,0 +1,82 @@ +####### Compiler, tools and options + +#---- MinGW +#MINGWFLAGS = -mno-cygwin + + +#---- Release +CXXCFG = -O3 +LFLAGS = -L../lib +OUT_DIR = bin +#---- Debug +#CXXCFG = -g -D_DEBUG +#LFLAGS = -Wl -L./debug +#OUT_DIR = debug + + +CXX = gcc +#CXXFLAGS = $(CXXCFG) $(MINGWFLAGS) -pipe -Wall -ffast-math -fpic -fno-strength-reduce -mcpu=pentiumpro -march=i586 +#CXXFLAGS = $(CXXCFG) -Wall -mcpu=i386 -march=i386 +CXXFLAGS = $(CXXCFG) -Wall +INCPATH = -I../include -I/usr/local/include -I/usr/X11R6/include -I/usr/include +#LIBS = -L/usr/X11R6/lib -lAntTweakBar -lGL -lGLU -lX11 -lXxf86vm -lXext -lXmu -lpthread -lm +LIBS = -L/usr/lib64 -lAntTweakBar -lglfw -lGL -lGLU -lX11 -lXxf86vm -lXext -lXmu -lpthread -lm + +DEL_FILE = rm -f +DEL_DIR = rmdir +NO_STDERR = 2> /dev/null +EXP_PATH = "export LD_LIBRARY_PATH=\"../../lib:$(LD_LIBRARY_PATH)\"" + + +####### Files + + +SRC_FILES = TwSimpleGLFW.c TwSimpleGLUT.c TwSimpleSDL.c TwAdvanced1.cpp + + +####### Build rules + + +#first: depend all +first: all + +all: Makefile $(SRC_FILES) + + @echo "===== Build TwSimpleGLFW ====" + $(CXX) $(CXXFLAGS) $(INCPATH) TwSimpleGLFW.c $(LFLAGS) -lglfw $(LIBS) -o $(OUT_DIR)/TwSimpleGLFW.out + @echo "$(EXP_PATH) ; ./TwSimpleGLFW.out" > $(OUT_DIR)/TwSimpleGLFW + + @echo "===== Build TwSimpleGLUT ====" + $(CXX) $(CXXFLAGS) $(INCPATH) TwSimpleGLUT.c $(LFLAGS) -lglut $(LIBS) -o $(OUT_DIR)/TwSimpleGLUT.out + @echo "$(EXP_PATH) ; ./TwSimpleGLUT.out" > $(OUT_DIR)/TwSimpleGLUT + + @echo "===== Build TwSimpleSDL ====" + $(CXX) $(CXXFLAGS) $(INCPATH) TwSimpleSDL.c $(LFLAGS) -lSDL $(LIBS) -o $(OUT_DIR)/TwSimpleSDL.out + @echo "$(EXP_PATH) ; ./TwSimpleSDL.out" > $(OUT_DIR)/TwSimpleSDL + + @echo "===== Build TwAdvanced1 ====" + $(CXX) $(CXXFLAGS) $(INCPATH) TwAdvanced1.cpp $(LFLAGS) -lglfw $(LIBS) -o $(OUT_DIR)/TwAdvanced1.out + @echo "$(EXP_PATH) ; ./TwAdvanced1.out" > $(OUT_DIR)/TwAdvanced1 + +# append dependencies to this Makefile +#depend: +# @echo "===== Make dependencies =====" +# makedepend -Y +# makedepend -a -Y -- $(CXXFLAGS) $(INCPATH) -- $(SRC_FILES) $(NO_STDERR) + + +# clean temporary files +clean: + @echo "===== Clean =====" + -$(DEL_FILE) *.o + -$(DEL_FILE) *~ core *.core *.stackdump + -$(DEL_FILE) debug/* + -$(DEL_DIR) debug + + +####### DEPENDENCIES + +TwSimpleGLFW.o: ../include/AntTweakBar.h +TwSimpleGLUT.o: ../include/AntTweakBar.h +TwSimpleSDL.o: ../include/AntTweakBar.h +TwAdvanced1.o: ../include/AntTweakBar.h diff --git a/Extras/CDTestFramework/AntTweakBar/examples/TwAdvanced1.cpp b/Extras/CDTestFramework/AntTweakBar/examples/TwAdvanced1.cpp new file mode 100644 index 0000000..70e6ac5 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/examples/TwAdvanced1.cpp @@ -0,0 +1,693 @@ +// --------------------------------------------------------------------------- +// +// @file TwAdvanced1.cpp +// @brief An example showing many features of AntTweakBar. +// It also uses OpenGL and GLFW windowing system +// but could be easily adapted to other frameworks. +// +// AntTweakBar: http://www.antisphere.com/Wiki/tools:anttweakbar +// OpenGL: http://www.opengl.org +// GLFW: http://glfw.sourceforge.net +// +// +// This example draws a simple scene that can be re-tesselated +// interactively, and illuminated dynamically by an adjustable +// number of moving lights. +// +// +// @author Philippe Decaudin - http://www.antisphere.com +// @date 2006/05/20 +// +// note: TAB=4 +// +// Compilation: +// http://www.antisphere.com/Wiki/tools:anttweakbar:examples#twadvanced1 +// +// --------------------------------------------------------------------------- + +#include + +#define GLFW_DLL // use GLFW as a dynamically linked library +#include "glfw.h" + +#include +#include +#ifndef _WIN32 +# define _snprintf snprintf +#endif +const float FLOAT_2PI = 6.283185307f; // 2*PI + + +// Light structure: embed light parameters +struct Light +{ + bool Active; // light On or Off + float Pos[4]; // light position (in homogeneous coordinates, ie. Pos[4]=1) + float Color[4]; // light color (no alpha, ie. Color[4]=1) + float Radius; // radius of the light influence area + float Dist0, Angle0, Height0, Speed0; // light initial cylindrical coordinates and speed + char Name[4]; // light short name (will be named "1", "2", "3",...) + enum AnimMode { ANIM_FIXED, ANIM_BOUNCE, ANIM_ROTATE, ANIM_COMBINED }; + AnimMode Animation; // light animation mode +}; + + +// Class that describes the scene and its methods +class Scene +{ +public: + bool Wireframe; // draw scene in wireframe or filled + int Subdiv; // number of subdivisions used to tesselate the scene + int NumLights; // number of dynamic lights + float BgColor0[3], BgColor1[3]; // top and bottom background colors + float Ambient; // scene ambient factor + float Reflection; // ground plane reflection factor (0=no reflection, 1=full reflection) + float RotYAngle; // rotation angle of the scene around its Y axis (in degree) + enum RotMode { ROT_OFF, ROT_CW, ROT_CCW }; + RotMode Rotation; // scene rotation mode (off, clockwise, counter-clockwise) + + Scene(); // constructor + ~Scene(); // destructor + void Init(bool changeLightPos); // (re)intialize the scene + void Draw(); // draw scene + void Update(float time); // move lights + +private: + void CreateBar(); // create a tweak bar for lights + // Some drawing subroutines + void DrawSubdivPlaneY(float xMin, float xMax, float y, float zMin, float zMax, int xSubdiv, int zSubdiv); + void DrawSubdivCylinderY(float xCenter, float yBottom, float zCenter, float height, float radiusBottom, float radiusTop, int sideSubdiv, int ySubdiv); + void DrawSubdivHaloZ(float x, float y, float z, float radius, int subdiv); + void DrawHalos(bool reflected); + + GLuint objList, groundList, haloList; // OpenGL display list IDs + int maxLights; // maximum number of dynamic lights allowed by the graphic card + Light * lights; // array of lights + TwBar * lightsBar; // pointer to the tweak bar for lights created by CreateBar() +}; + + +// Constructor +Scene::Scene() +{ + // Set scene members. + // The scene will be created by Scene::Init( ) + Wireframe = false; + Subdiv = 20; + NumLights = 0; + BgColor0[0] = 0.9f; + BgColor0[1] = 0.0f; + BgColor0[2] = 0.0f; + BgColor1[0] = 0.6f; + BgColor1[1] = 0.6f; + BgColor1[2] = 0.6f; + Ambient = 0.3f; + Reflection = 0.5f; + RotYAngle = 0; + Rotation = ROT_CCW; + objList = 0; + groundList = 0; + haloList = 0; + maxLights = 0; + lights = NULL; + lightsBar = NULL; +} + + +// Destructor +Scene::~Scene() +{ + // delete all lights + if( lights ) + delete[] lights; +} + + +// Create the scene, and (re)initialize lights if changeLights is true +void Scene::Init(bool changeLights) +{ + // Get the max number of lights allowed by the graphic card + glGetIntegerv(GL_MAX_LIGHTS, &maxLights); + if( maxLights>16 ) + maxLights = 16; + + // Create the lights array + if( lights==NULL && maxLights>0 ) + { + lights = new Light[maxLights]; + NumLights = maxLights/2; // default number of lights + if( NumLights==0 ) + NumLights = 1; + changeLights = true; // force lights initialization + + // Create a tweak bar for lights + CreateBar(); + } + + // (Re)initialize lights if needed (uses random values) + if( changeLights ) + for(int i=0; ilights[i].Color[1]) ? 1.0f-lights[i].Color[1] : 1.0f-lights[i].Color[0]; + lights[i].Color[3] = 1; + lights[i].Active = true; + } + + // Initialize some OpenGL states + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glEnable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_LIGHTING); + glEnable(GL_CULL_FACE); + glEnable(GL_NORMALIZE); + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); + + // Create objects display list using the current Subdiv parameter to control the tesselation + if( objList>0 ) + glDeleteLists(objList, 1); // delete previously created display list + objList = glGenLists(1); + glNewList(objList, GL_COMPILE); + DrawSubdivCylinderY(-0.9f, 0, -0.9f, 1.4f, 0.15f, 0.12f, Subdiv/2+8, Subdiv); + DrawSubdivCylinderY(+0.9f, 0, -0.9f, 1.4f, 0.15f, 0.12f, Subdiv/2+8, Subdiv); + DrawSubdivCylinderY(+0.9f, 0, +0.9f, 1.4f, 0.15f, 0.12f, Subdiv/2+8, Subdiv); + DrawSubdivCylinderY(-0.9f, 0, +0.9f, 1.4f, 0.15f, 0.12f, Subdiv/2+8, Subdiv); + DrawSubdivCylinderY(0, 0, 0, 0.4f, 0.5f, 0.3f, Subdiv+16, Subdiv/8+1); + DrawSubdivCylinderY(0, 0.4f, 0, 0.05f, 0.3f, 0.0f, Subdiv+16, Subdiv/16+1); + glEndList(); + + // Create ground display list + if( groundList>0 ) + glDeleteLists(groundList, 1); // delete previously created display list + groundList = glGenLists(1); + glNewList(groundList, GL_COMPILE); + DrawSubdivPlaneY(-1.2f, 1.2f, 0, -1.2f, 1.2f, (3*Subdiv)/2, (3*Subdiv)/2); + glEndList(); + + // Create display list to draw light halos + if( haloList>0 ) + glDeleteLists(haloList, 1); // delete previously created display list + haloList = glGenLists(1); + glNewList(haloList, GL_COMPILE); + DrawSubdivHaloZ(0, 0, 0, 1, 32); + glEndList(); +} + + +// Callback function associated to the 'Change lights' button of the lights tweak bar. +void TW_CALL ReinitCB(void *clientData) +{ + Scene *scene = static_cast(clientData); // scene pointer is stored in clientData + scene->Init(true); // re-initialize the scene +} + + +// Create a tweak bar for lights. +// New enum type and struct type are defined and used by this bar. +void Scene::CreateBar() +{ + // Create a new tweak bar and change its label + lightsBar = TwNewBar("Lights"); + TwDefine(" Lights label='Lights TweakBar' "); + + // Add a variable of type int to control the number of lights + TwAddVarRW(lightsBar, "NumLights", TW_TYPE_INT32, &NumLights, " label='Number of lights' keyIncr=l keyDecr=L "); + // Set the NumLights min value (=0) and max value (depends on the user graphic card) + char def[256]; + _snprintf(def, 255, "Lights/NumLights min=0 max=%d", maxLights); + TwDefine(def); // min and max are defined using a defintion string + + // Add a button to re-initialize the lights; this button calls the ReinitCB callback function + TwAddButton(lightsBar, "Reinit", ReinitCB, this, " label='Change lights' key=RETURN "); + + // Define a new enum type for the tweak bar + TwEnumVal modeEV[] = // array used to describe the Scene::AnimMode enum values + { + { Light::ANIM_FIXED, "Fixed" }, + { Light::ANIM_BOUNCE, "Bounce" }, + { Light::ANIM_ROTATE, "Rotate" }, + { Light::ANIM_COMBINED, "Combined" } + }; + TwType modeType = TwDefineEnum("Mode", modeEV, 4); // create a new TwType associated to the enum defined by the modeEV array + + // Define a new struct type: light variables are embeded in this structure + TwStructMember lightMembers[] = // array used to describe tweakable variables of the Light structure + { + { "Active", TW_TYPE_BOOLCPP, offsetof(Light, Active), "" }, // Light::Active is a C++ boolean value + { "Color", TW_TYPE_COLOR4F, offsetof(Light, Color), "noalpha" }, // Light::Color is represented by 4 floats, but alpha channel should be ignored + { "Radius", TW_TYPE_FLOAT, offsetof(Light, Radius), "min=0 max=4 step=0.02" }, + { "Animation", modeType, offsetof(Light, Animation), "" }, // use the enum 'modeType' created before to tweak the Light::Animation variable + { "Speed", TW_TYPE_FLOAT, offsetof(Light, Speed0), "readonly" } // Light::Speed is made read-only + }; + TwType lightType = TwDefineStruct("Light", lightMembers, 5, sizeof(Light), NULL, NULL); // create a new TwType associated to the struct defined by the lightMembers array + + // Use the newly created 'lightType' to add variables associated with lights + for(int i=0; i
    c?|^GYh|pN$^R5z27KSORlgwvO-OL$*4bW)I&V>2ezVT@k!Kb zhq2_4QU9ja!0Zh?NAiUJibFy~jrv#OAhBxPbgfhfQ6kaVIHfaq$#90b*Q`)M^(zZ? zO?|1hR^)p{?t@oqNKFI$7{)+1NPO@;1Ifu)fWK0N< z%VmBvaJE(REmqCOSKzP^kOQYsxg;D_BHy0vnwASFSbmGNpWW(AS67{{Yo@QW#@9Jp zWXO$ORlY~Fu72LzaZJ!lwJUHNg75dZFJ0=h&IB<}3ml8yh~Aa&@UfeS4xrxL*;nav zsPDqq>KF7xG-6IDy}>7eHQc3*zR2If{mAn~GYiRiy{HRRubn@n0ci4(m7;j9uI0_Z zYO96`88v)czBsLGrc^M=E-~NCqJrp|S_6TSe5T7h5g0UAySyFfToMD9S%6HW^i<6U zkLq$#6=&J?UQYR)OT~Pzu|}O)LKhI?gF_X%7p-i=IbDnPqMx zyO+J7Mbyut$1JMufu!5_kxz!u^mB#Yj|~hZ=O0+~KHH}12q=htVRKtD^Tu{z5oT0* zI)grJVjM%Y$1l8qQfPtBA2Kh;E5W$Jyv1d3-pDO(<5na;9s>sUTFw~u*-AOo`yVxM z+%DD|vt1lN4dc91^$RXyW6LtYgexQ(o35%$;9Bsv=vsIQtjajd4Xj)Elx*gUXsBqV z-mcm$mix#jOVN`xE$THUl4+^2TJCMsuP-1?{1$xHGTdh#jh@G@SA53)i|J=x)u47? zjyAS(0uu=gaU${#;)0YimJ(p2k`w5MKrL<{c1q+EsmPi?kBp!n;`eP)kbTAyCF{B3 z5UN1*zO0Vxc%HhWYyOm)c!LLf9X4*9hcpR*keeOqnnj)nTf(HUBV>*ih`$ZQ#;6eX z0W~}k1xF4tOcEMOPwf?Ki3gOX{t#OlrRKb2Q=9s#q0~m?*?D#KDQ8YOvSo_wz(KHu zNRM*WV$Kc1A3L07uOA`_>rm{^n!7;6ZuPt$s2#kS?8#z^W-{M<><-Psu2*FLBBq$I~91I;h)L*Y3jeAAi~*sf7H{}ljYp6Vb~@meke9m*&O4Q6>Tyi9A$ykqmUR zLn48zN*>HPr3^!5sX2c-_OtV**TdJVOXNiZJUp&ybC%)my9{Ppogt~^SYD#nJRJQ` z&b0nN!}E0;9_qB<=`9cuekJ_AriMv=ACN4LpP<8< z#PXfLOwJ>0SZ;)t6G*|R3|j!U0N{@@03?;!MW+cn%~_+$)Sc!_c3O=vK|ZV3e34mo z4e=#;@pX9uC1gvTL*@AUo~5_x+N2{ls0t6!9lc2I-WCr;I3#QpWBrBHyj>jYhFIA0 zT8`9JfWKARlBS?z-NZbE`w;ZD|TUhBsFC8<&-N4lyJd2LN9@OeHDzL{9ze0l;Kd#QOZ zwp=yNw>7Bm!v4~YdFFMpn)2WrYVmaZSIoN*F*RiXrA1+wZ1kxgW6on%u!w(N#J7vZ z5z+^mc8Q(7*$=xlS5OUk@nm+7HM;--tx)t%a#3qjJxj2HxdWbU2z zb-yUW#Sp8~U-WFCcU88zx8n^dF>*=Zb@O@7=Xx%-j#$T>??6~VoAV(!2{ z@hE&=p-~DmSCtvi+2+?yB2P}z+hfcTwry$h+408eTtn*%a@13Z2(LGmX!B?MQ4b`^ z=P=sYYqlMt46S*+`X_XlrFqpmwh1#cX{ZH{?%i!pW+s$)k@117FAdI}WtreG-X8@%Mrj;rvh**4h(z~y&v_R57L19M zM78s5&JzqiztjwY!Q+)>yeKmormL`iXCd*>GGqSY+W7oss+Lq1cC24)Qywz=Et_wt z@2z3=#Xe|_eb_3so;$48(>|xxKSNke5&r;7y4E*IJ!yU4NVhNcK}+nz7OC&& z8cmp#i-ixdXJL**2Wnxe^qP}N-(NYXxsaw$I-3r}o-LH2Rnecr!dVX1Yr%q&&ntV*T-vt!G)e&^utXO|^+fr@P zmn6V~4P}iZ&SF(JYzD#P6JRDcI*Mxjkt!SuoYxO{VjsGGhkjNLM$5-o_xXr(-hlgQ zNr}DZO0NFV=1yz%k9v9knCyYa1P934$7t&zSC%^ZwuEuvOgM1TAr7m-J~_oPsuUP9L(Y!}=tf1tWS^CNKR;mC!=1GHI8qtf5d zS?N;q@&p&;HHab#VVgucN_M36IsO5a`E1e}-~sfEAX?Y71B`)KaNc;4IPM!uUB*(k zS(%%j5(KipmUko|(X^{vDi-n!ZT<7^&*>l3a{E9JX?zF2k(cbBesw*9MwYD+^{{fW zBpcYD?4c2|(xi-x8}ph=C_ zNuUuN?9n**@qd+mZ{chZ3+cs?ep?-G!Bcz^c#`-R>?n*QONsm!i9Q$EYUz>X9!fMmhbeUkC=+4KPO&(zLNNEMjv?xW09t#-Gi8^)V-t9VE^iHD5# zxC(}_`?BAIVO~8R5vhxDN=!b^fMnnp=&dTeMh-2FPQHH`0nRM9)}X5U8XIGR&Q0wO zZ!dNEz*a~HaK`Ab%umSQVafEJFBtyuI4R>1ncfv{3E8#oLIf>==hx*` zU0W06yDJA1gx|p>4&(gOZxs_Ft znA|GO%ulBlq;Jd9x3{EkgX!Bp>f2%|%n6ei&gNfY@)YJzywV@coVtf}g(sQM@p-v5 z;WAy0bX++5Y|3%7F-S}p)CYo0zQ27(F|%xAjoGvLG0~X+4`0vL^>M z93g>_&H`pMeY-Y&yC!|RI(>Uv>h}KQtOM+{%Hx%V@NHAV_jFRlXa|3p6*YvvN4hnW zSi9fR5ArDw-%UN-FN=u6t_bJfCAsIyK)QI{Sy^m9$&1d)%dMvAch>FwvflWVQ{rX0 z;V?5XTxL?pZsaPJC5g$Bnv&^d;BvW@ouqV+;5il&H47?AHtj5PUSW*|@@`n++LHiW z&{bK?Ms}PHw@ja|%FA_%fX~2_k_6FvzlN|IarC^BngnI$)`nfF`C+oT2#f2kHC@C9 zCUe>e#xz+0_B792w&gOrGMBeb$V3B@keFP?|0X<(xmX?1HPe-eUabCb6OS6^-*U>= zSTKcyy2=ak+Pn1f_elK=hLyEXTLcAchn3QkmjuoUk=7lb#E` z01@F|&^CG|SjjUmdR4MmGRH5?l8&&vc=NVN6Mis{@O);wQ(k?ZsrW^QYS5+BR zb0MxnCYxS=NK0YcPE#n?v3}YBM?%plmn5^YTt`8Qj0vh6t#`({a${YUv2LzeSrX`% z7ju&@N{n@-#=7aOXzRt)?_whmR<2!o(ujl`>4`vf5L-l*}fm?!{q2J z-sd|dXl)s~9_%%&5S18Eyfh%{-=f_;pE|+$SBdTY_MT%-tmnT39NLui2JzIdi{Df5 zBfwEOV4>_q%Ib;rx{ZZyb001?v)#Pj% zaBb&8^%74G!SHibNesWM%-Noztv!Rzz;>#~Gf6Cv7P<+FB-Otn)qh5_w4zm4-{>Y< zoUVSOF42yAN%d2yo)QYE+0P(UX)tL2+!2*d&8YN?!zx|CiNeOn8YfGGi8h(8ZX5KD zZ_A~jRJSZy-SYoqbuH?wQ&zVuU0r>;I=^vG!6WpHRikyD;fP8$g{yRKaT^&1^ zIQId~zV_dFAnQCm$P*RIEDpKFpWO++a=Gm&?hNc+WmVjioI?+jU;T!;VYjmhGmAWC zP^E--k)o4zzp8|dl#1MdVAs8#4C%VtdHTQ9y^;JXaEiL6=ycstsXL?5-Mp2G=?)q# z$nyVE@eAZvTbVK^YqS)duJ|}6PD2_^B;90-7Z)rTQR}4{U44NbW4o&{eo*s=S2RYbfrhA4o(XOvCU0SvXzOuTYF()hphJ|CYrqN}Pt0Sbs5r5G}NaUp;6~LYJOn&e3Qu8?-k; z9FAc}bl3@K9&>Y!gb~QC4K`RYeQ(3JRC3@JeUh@y%qVL-pQg(3OF2-Nnq)bbOF4f- z8JV!W|MA~eMkX9T{Ts{3gyY7)v5ZVO&X+PEr;y50W^!2>r=LPVpcy6JjrWK#QAGix zxoH!ahkTG|@1{HDzD+jOd1gaFtUtfwCCFSp6uK2gVlA8KXNHWn5V=e35fUP2Et#cB z>?9aPoyionXYo=u6H5=<+T_G~O)Z2SFzbb|<pJA1pq)ENP^8$lE7Ls zZDieOkjui#R3(-@DaO20?smqoDP4 zFWW7ZQqwIxjNzoNgF5q=6@Kb^f*deULNWh`Rtoo$8rW@8W!cCoH|he@t!$Gj=}5-4 z*y>;mU`{%ViZW)A1RP3rDS=|tt4xt}pk!IES_}VxV`3_@>qWvY$Kc}%@%4)*e7_#Y8_STGR7vdlF$eJJ5gIZLtU%OhZ2tNE@r%E)j7&IgmNF0- zn$@|2u(PgG}sOmT_wATY%^4#NmVx!r?SxI z@Vy-()-vZ6$TXA%C9hI|{09jcQUMVvA>fh&K$^1?ldBMo{%`AvUI$=@`|Iy!hCuv*B z-_o{9_Jm7m+z|$7wY%tW&k1KJqj3@41nC^RHTpI!#YC>*x8xd_PIh#M8tkHOwTi+m z6lxhg17}9!ReGi#X&{)X`ZgoHv*B8M zgbEb_*6Ru;%t2TUO0nc`plKbH%N;ltDZtpo9oT8U7CF7%yx91Xd6Ua%cEx(!v8^OW z4=urQtO=8j)W?=Qg7`l9C()Oc+xjwW>W`U!HZfa&L}HNCKc<&ba$@KJRZcmXO9GB} z>>xd3Z}L0z6z3Ja9(Wr=n_1m>_6>XQd@Zom8~cnlnY;JAm(0BvXY_8uOAtABXmOH# z)kK|Y&kUKB&VKD5_GVCRV=*H>!J7+x9fiui9Z!bsn7FDs!TWoSCHsvfub36PJ1ag6 zHq^!IA5s6r3us3??=xPqsjB6;FdSOd1*9j{ezF}(w%9@*IPL9-jHyu*H05!b)o|2P)i0ngQMX!f0urqhBu1E?m)ZXneQLCAH!8N_zK17ZXY~g)OcvU;m0Ywd*#x{h zLb%ugTG8%-FPfhg4dPT7tZh(dS>>XwGAs5HqvB;1mh!7r+<&Io8?SyumFnlAk)x7x z2vm&eg$|ddc3U+jU+D>oTf`(xm5pMtQ(ozcb-M#wqaUWk!7mWb?2M3k%V6xFJEq)$ z=aLzt16CeOpX)n`eRxv8TGGbbn6$tdHt+{djhqm#jat)kcMfg=kc}2U5D^lR_|6AP}169`J?K z{7I~-?uF4DwTHe9sY|Tq$h%FwPpE&zC*xfdMEHV)BRFWptM{sNUOSP9-FVy)uh>g) z;YZYxPfysc92JiQ`zs#NjvTxA=mqQhpV;4Tw7>tut3$s(N50pgmaOl!Gy1pW`-2Uv z?f$I$`0(Hn7(G#pVvvzI!i30*j1H-zsJ|AXeZ-nOl%PGlZzo^>DEY)n7h&ij-;ta{ zt6jdV(9`lFdP!`&evDTf4{q7d3kK{VUZ}Br9G>tZ!Jw{`WEExQEey+Ty!x=ZSl*V2 z&q~GNpbSOX1ET_c zZMda8Aa9zn?pymsJ%9@z$i0_SM9*z@g^VlZomx8NMNacsji`=a+VaSa5a*oxCAZ

    U&nRBw@^P}|!GEFdUKXxPR~P8H^^6(l%6w~l!j0s_y0Mvg z=}Xc;jtX)FnO-2+0ylN0#`oew{8+X9>T;;8_uO zSM;=*dw1Fz4d*Prl6E%MjdrI z98WuzF&ur*Ea0O+|H4(?%!-cQiWL*)NzLx?ewl*1&WDq8tJ?%D!kD)mpL(Qn+LfgY zNz}&?yNSu=w1CEyaWSqeA-$`@_hT8dX>Fe9m#59}-Rts2&b!~kC8k^t$Tg57iMNh5 z9Vj2(P3#_cC%hI|o><90mBnIQ7;cy6R(bvivzdi@I_EN-r?vT_=Nr0yYFFRk<Rv&O^pi*7s)>5SBMDhL;k;x*mPVgG`|+SeN}k$%q&F+#Z1y!C z>2*b%vF+|7y>7X>j`aHEnth}aA(6a4sgg* zvallOZ#d?l%OifSEOie5-5DJ}u76<6xMv6WmijJyEix|f`>2P4vK*4ecSri=6d7H( z%YpVtYR)Q4!;yq5Tj20%cw^i1kM;^I8btH?-wF&DJ{NjggK;6%Q&;5lz)os=E;?zv zfI2{>040?Iqxt-XcL+A=h$*&Wc=ZY6IUwAVh6&!R29@AfX5Eyqq`zhsf9TuCPaS)W_F1?@N}F-Vc5TcY}MPA zBR>|4gORfm)d$wXW9;vvr^d@CcwHPU5g5d_bBEO->e6X6qj7oQoGH!B_tENSa3AL0 z*zJBt)C-c9$@&CNkqZ|NT&Y38V9xvaDEOn_Tq(%=xcBkV!MaNIQ=Vem2o!5p9G^pj zMcMe;(xRRw`cact`sv(|8qesJ1=a8A0O;(($T<4N2uSf_$woBhpv@|NvO^J z`hzs(&@nNVP1iM2eBw%3mTK+wlw*#Ug=!wYUy{r{M2X$%3jBH1ye%?e*e7Ijpwdpf zkN$#T@nto8tRBg6 zT%;f2zawK4Uk<9@F`pJLTuNLV)-5i`njaCLI5uY1#|Rve^i;Yd7bVuX)MsOKIlWwx z^30E5)dL|61TY2H}L2sqPKRs$a$hzLrSxLpV_Rp z=tR3&S|3d83T!rsqJuc9$K2!W3!GT(<`j}UTY>m!Kj_C1_4gdij{VUYJLbOi;*Wol zDEMB>U=|zq-^$C_LD#LG*nX#Td!nFY{n0F6q9ESN>&;vpa@|bYll=DcyKqm}sLs({ zm06v0vbrj>DYkPCXBRnR{krfMQibDdkjkrbWySikWBu6z!oQ_*ZMO2n`mzMT{w#Uh znR-hZUj=|5zbbxZ{7U&1^DE?+&(AF1bigS8)&Z`HtKxcy>mja(xgO^F3D-}!4ss>H z{HEhvkH=kcn(lBOb`BPgHpEmfb8hqEG^Eww_0zf0OODzp*xa!1y=(vhtgqsv4^bOIm_IsmM#}LR}MB|HLkhe531@to9?3 zdh@6Vyt_s-lS_9;&cOa^eAg)JVJse_A9GGJDAP(h96cCcm+1Pt?DhkZLP^Rl-5-6r zYo?R0a=TU}Vm%~8-X8c5D9ECvU0V;%sKO9qPJ)MC5H$Y}zJA08iCR4kA`tuyvl*D& zA#1kPMJ51De-=efv*+K3=IGxhPMlch+#Nfdn7TFA@A|1DD{DhUnRAYl?R=og{VAe1 z7!NLvM08i|!>obv%$5N+lK_K^4_$05{YU#WN*QDBV~#`@4_wf7It`^SW^|q*OZZ?` z(dvrgD<3j+{a=XZG9 z@8j#(x&lXJOzg8eymyJHZNq26sja$zh|pQ^X#yHC0dsn;S)yJEi z9N7R@5Eia5vD&XDGUsC3@+t13*kD$4l=tz9;{$o#$E*K3wY%%a8{mr)$_)jHG}?vAFy6;fo#+p(WkJ#i2J)T{IO z?2}OcD0#wW7v4qEp#lihN&+Oy%m6L$dTv25eY<79zD z-RW2lQ=^}H_Pd>1o3kEpkXJ2%(}Vtb+xJU->o1q5=vZ|x$p>GQq<5g*SPfJ21CD$7 z;LK`=28My^^-KBZ0hEDIY%n`o9^ObP%~@(J<(P*% zj=;!GfrnatvoNlE*Xm7r#IL&fY$3*=z#NIS#mf*n$msABAS6;ttY06;wpwGX-%o9*a30se^D$ zI2cg4GkUR=@m-SWDyPvV1xF?&s~oFe>k5T^L*6)W7C{Y7w>c(Qqsl0rIc46c7JY}91n-SzOiypspwly2o&u1cCNeJ+hgGdUjT}PvI%OGZVvI^}T z$EATQ_p)7B^98mLn~=cRJC9Man~;WyG-WE~02ozWh+An^rS)xA1VrkM{rBOFJx8PL zIrdNk?jLSSy!%Xw>BY(1wSUb8nhlLY)MPrHJ`Efc@#!?Gm8lzj3xu7x@{`+`1hQRv zmaG7N{{kAvGWAN{#BMT1kT#bkO$))tuA@DIAR`4`S+O2L!1Jtx=!Xy(5cz|!wW*7l zH3TR3q;T>~!O2&ElM5`IJW1o^NcO;s@tNWu>niH$jn6!hy8CPD?znxYNfzt>Z{iO( zW+P-f34eHB7Tj_{{71YN{xDyzkC68N(e^g*QB>z1@NRaJY?4i8fq(&nED{tA*l0i# zH^2t6At=GcKthy&y@fQUwNjYjqb9I%cH3-*RoZKNwbd4i-fOG9wO7To0w!!sh;osy zN+JP+qMmgqhJyK!n0f!tncWc7+uQf|-WScz%=tdg`FhUt*@Zt7K8A6=e}o@W;lLk; z(?)QOui%H2>VL)$BV{N^v=)C=_+3pKgf4+0^e0st*n7-S@YHZLz%kCqjnaP1(r))M^z(1Z>Fi zV4J)D6dDC;2vH#VX;WUdnRYQ7Bwdy6FQM21dqJz!*}UM2!GLphfL8{tG!={zm2(1$ z97H>^n>-%Sn+J6{6=y+&rg6x_@drc`BilVl&N&7Nv4Xi1XY$kEr^6bbf>I>F|CI|Q zIFG(IRbLAuiP*>-`dZrL9PB4XF$UdYW(iy{OaV?Hk8T_t2biLjW@HZk7R^-Fbb!6p zH3#7lL!jM|2*w_bPLU}vcRE>2aXSL;9%aoXB=5)HpeeBCQsAL}!#7F5-2py>0nIk| zK~w~YfXi|iVqgLH@u2j6-YyAL!d-6Mh6wB{h_OoJxrn&H7vD>?#}2(+{Wu%M!& za}f9uAHYElW~(!nL*W_}NkBhf1=|Hcr~dein)z5%N+Qy?xyUyi9oSlRwHX2WT9^sI zZz}&KsKJOl1rYI-dG6uRM}V>^!vy36hqi2E7jeoGVbl1JI1*I^PWEdY-AW7OpFz9B z3`$qO=g_-RSER*Ctqro>Wptm105>cqwPIMI99xqEcda;9|BTvj-(MUQ;N(NeEfQ*D zVf1ec&UaKw5W_g}3{+6<+f+?)YGL43h&%+$&IPuOg0lyv-PWO)RVZU63PH^@SvX}Y z5XZt(QG>T05CExyoy1q*CHexb+J5&$}!#~1i9Sjv7+DR5>wc_!J; zo}vJ_O01_sP(qT$F%I}z zSJ&DwDAFxp8)Qh+f-^U$wwFnj1NsU|&CBTS=qfWNgj(>jmAO!;zVv0Q7FzvyEZ*s+ zfyMx_SgnE>jSIGa}r0XNvZG@F9%OW1RIz}W)-N+0_G zFe}hpu{H52qi?V?8-PsM(7L*z!)t(W6AwPAZm5UeS7LJOu|2plRQ46xY-YI_8rFIK z<%BlQHN8&sY}rx59>c8`MFisIF;ID{jv)=mxaEPuG|WO6o|sGK3Fib>!epgTS-030 zGYWU=`&|a5m9RRKbUii4)?1itm&TQ{?SPxNGWonxnPyUMFe#N*6X>$N`8F4jMNr

    c4`kj?D)9v?U=fq{k6>h!ZphtFD2sFZLR+L1m7P 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 literal 0 HcmV?d00001 diff --git a/Extras/CDTestFramework/AntTweakBar/lib/AntTweakBar.lib b/Extras/CDTestFramework/AntTweakBar/lib/AntTweakBar.lib new file mode 100644 index 0000000000000000000000000000000000000000..02d0f588d99134f70094889d3327a381cded2f5f GIT binary patch literal 8904 zcmcIo&2JM&6o2_55YiCHC;7BPplJ_)O>6>cD<>p@2q&O;A*fPimUwAQ9Xnb(EalQe zF9`L>KTrvAs5o-qggA4oP=$KrP;utSg}&LD*?lu!uQ4VYy{zXqZ|65}=Dm3{6aCJ# zH@AN1Iu%i$SS*>0CuS3KNfkdWim|hE;^)mS09XO&u>pFY0vvt^F!Y$q@GtEe>Y01PFm%-}*uDrrGN@Rx1*b~%88GpcK>IMLl zq4Qj#I2KICKQPH=S5~iHSvRtaOPLGnD_4yx>)H8Y#c(Y1mj%;?Y()4rHq-bl@1L;3BUY*2;Jy=?s&s7i35xmwySTMN6D zN~sw5ML@myGP7fC=FP&z^fg24kW%CK=vK+Ja{=nuDNE7uZQOTUsM5d0ObmDVq&X}8=N%5Y3*Y~+h);;C5D@4Kty!-j*F zU$w1r*~-yLRZ+unJHD}HSp~|dqC$(CM;jwnGg#(+MZt~FmMTsQ49RjR6xx~NEP;CccyocUZ% z7!*J4cS=QFE&SrbLMl$;3YC0N>a1T$X$_%{06m?JARP{(XIm9q2iDAOi<+mRu9i{S zLB$m5HY)j`;bgobnHdFSqg}8nY&@~4GHt7>Lh3S3(jM0npy8}pj;7!vZm-j3xw2&2 zCB5ScZaA0BVyw*UV@S=%`G(&Wx!&ig{QXCR7a(Z z7(IVg<(8_XBmgg$(KSV`>16$vkhh|13!E0o>bg+9&HA*xn76l59a8SNl+2)l!TCW= z2)?7rZ#8#SVdAuYMd+%ot;N2BY*WV86dKZ!xym4BO^oej|$9aJxTlN#MM5^{m zYJ~_T2`T|4K_#pts03H&d4-&1PUZ@QQ}s@oiI_Zd-t0=Zw84ize_!fv!EA?_3ZIsf zIqTN$&(j%R#O#Pa{*VRnPC@U&$$ZYNnA34tg~<{AM)^+wZTL>X>6bzePlEixBn|Dz zC-oSbg2>BOd=Fw4WX~bZs2S+%?L?fl$(~NknjPIoR`Z*7sa(2UiOj5j6G^YEUFOx= z|86X^FIfx7?fzoD=x~2&RFK*%ZSP>GJGy^@j~^u``-(lRm#rXePXW07-jaxGCF5$7 z$Sl)A06d+9k1!mM%-+LV2l(DAGp--8v^OVR&GNdQ6Hg?>Z3Xk3R@Zaz!oeLAdI}q0;b`yO~l2}M%djMi`jGwTh$`S)Q*4p zZdaQ-(8_h=AQ21Z!(#-lDU#1S&}z*?AXlmYh3>mv9qrdswQ_h2uQ{C4#&l%#S z-ISAWnVaUD^={JDsK>)So~F6i@S6#pN-Nj*nUERm;Y|8IU!(X8ubB<@(5aINX z5IUt+u5YDGP@10}M@ANh^0=%VPBfCn?M&8KyT3)wUScQNy^DKuomwl`wKplZ!J54@ z$lOBgRhaQarSa(Hrg&R*UUF7zmN!wuUcC6i+a@<&TrcLQz^2)1MCUZJwGk`nwMx^R zA#3{)Vxf0()d?HV%;$om^lP-Tk23}xiks)H5j7Fy?H9cCysZ;z<+?tb2w9B=JU)7o z*BBa(lCVA2pvUOl5$JS{&t!;&L!3{$e$Xkka@{cv%U{EsQCw_jEjK=vA>MM7GbvXl zP4k7s;Rxp=iz;5m=!A{WUI^nTVf5~Knr93d(=oy*uaI;?tz6$*LiWhxoX@+Q(%ROC zw=S1=%-1p_+p$h?F8$g|r)+!%Lw1jol#}16?I~Y`^U=$?J>`pXK6($>JYR@^PH{fv Iicu&0A6oz=;Q#;t literal 0 HcmV?d00001 diff --git a/Extras/CDTestFramework/AntTweakBar/lib/Readme.txt b/Extras/CDTestFramework/AntTweakBar/lib/Readme.txt new file mode 100644 index 0000000..ae00121 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/lib/Readme.txt @@ -0,0 +1,6 @@ +These files are part of the AntTweakBar library. +http://www.antisphere.com/Wiki/tools:anttweakbar + +Copyright © 2005, 2006 Philippe Decaudin. +AntTweakBar is a free software released under the zlib license. +For conditions of distribution and use, see ../License.txt diff --git a/Extras/CDTestFramework/AntTweakBar/lib/libAntTweakBar.so b/Extras/CDTestFramework/AntTweakBar/lib/libAntTweakBar.so new file mode 100644 index 0000000000000000000000000000000000000000..dedd7d94f24d1d842198bdf748850cba843578ae GIT binary patch literal 380940 zcmd3P51f@#{{Ol64x%U|A)1s5Vg6MUVVXZRqp5Dq^apY0&djZuX_`A`?$ksWgwU?g z5*ua-SuMk6H!Hidt6kZR4IwKGn-$tMO9^^E}U;%L|If1_A+Lu8;@`Qi~4=h%Dglzw9TIvP7!bPYe}Di=$+^;V1Sh+E3n+ zvzL(RGVWZ&;~ssv5W8*?Vt+CtJqXA~o@}J?-UOOA(^GJV-%V7CBOp!RI}zl~G~Sb$ zp5!w54*=6N+$V<=(@2DeA^Z_4_6OYG>UgFeh%|FOXaX7on(uE^7*_;&Kf%rGx40MT z_?5ufxWB|b4D#y1vjBOEH17thyc*=&qUo!E-+=y5)6)?i0vQ#c2LbKtNf0+_z8_m@ z&uXSd;5|qm2D}6J3LT%&xJ&EuEO&AZ^Ughbp*Zxy3I;wo;P&)S7^K* zxJmOoW${+&^h1EDxDQ8Jry~FLn&)KDO^7eid^0E<*CfQ>3hWKO?YN&pIHGyFA2Co4fcrGW{~EHt zLU1Syk zrmaNYa$rKsxI^QYz>{)=U~K7)df^oGS?w|wB~sr zWGn-HI_OV<8Mx2G{W|3R7WfSA3SAD1_*%>P6u2AoDbx*jK6p}qy+~WvqgGxMT@RV| z^(J^q5!VCvYJ{K0{Wj#E09gUt8$eG*+VMKml?XTC=9R6>y9E5NA#M(^AL6zFc^!iA znF#+v)9Hx&H^N`xZo_>iWRKP|-bVg<#I4n`uK`|$`wb~ch$nSC$zD4Aj7}pY5VsZb zu0r^)2%ibLt08YJ?xPVt5mbBV=I0> z;vND$SEs4mLewGd8y&YBdCheg;>KuV9CXXFWHI^$(C28oECTNhpr6rloz61xlA|L&yjv3(%whJXF7k2&hrl9 zKSKO@psRpcC?^$hmmz#B;x;4vd)%LaK1}O?pm-8#&5-pX?z0g8CV0%%ssmeeS!0oY z8u;gHn#n`8tf!IhNQCDDZ^69^X`8^y>jhvh9sU*aPC)wkxDVHHj{{?fKN$HZXn6xP zGXG#5o(jIJ!S`$AeHS=S=ijZd74f5Ro9iTmCnE3h;N2fLub07lJK{G23vqvha60e- z;JvsH$30W?4nf|lkoFMr{TTNOguh1mFM;_;3nT6f&_@Az{T*RmnOfgU@bMa@k>Qn^ zhvBUVk3-s72&W@_C+^j_FU36t_jbgW0sYrW$n&U2!D%oUQ0F47^Io&w@Bwz1K#}*9u4eir8DhxUC!STJ`gf?fNwc47koEp zndFm;P#IAF{2clE==AZ(Ge^r=2s{IM^MGF={XO7kj6*iABOgcjuZZtq^w2sQ(dQs- zqK-Qscn0Xjz%|JC32t6NoqnAn<-fa;b|_>%r{f;gJh$mQX917XVX~Z|(;0phWneii z>VV_H^DEqc1N{roaWddKROc;58OspQYYJri67kpK9-^Y;zlHdBBJTab`#bQY0hfU1 zb%Y<$d0#{NQqV=XpGDlspeNuCfZhe(GT@(Z-;JBs1&AA_!@mbUuH`IK$@1R|5q~83 zcm+}BV9h@naeY7^qmsl#o%dtlK*SHnZC|G%{s81%k9#QYo3$MBq+7iIhTQI;cL2+A z7a}}N%ian4F5JBC0A2dI{#qMM}wynbU%b|(fPm7eAfa0jJO)e z_!M`RmQ}6OmudcX#BYZD65KgRI|}mB5chA;ALu*}BmNhlPtke%Y90Or`h3lED&pP; z{iWvl5#+B%o>`#32L259L*Tsuc%062vDV>u;9$fpMw+>zI*s&OR(PfrJ_NFhQ102d zZ%2G5Wc*o|Z{!e2@^tuh$a@g?KY1hWZx#>v{;ysq z{9jdUAN88Hk9-66fp6qK@YpP~Z9<37OcM8fqL%D|xnd9T|EuUr|5t*2a>r`A+86&_ z&Z?WQu}u3u9Fb?E1l36JZC3i8n}nN zWQ`=@H&H!&`Q9@LN$`9t?iwrnxegx*+-Su!c%DTcW|dW>;|mZMw&E>zC-@aYe{`t5 z2folO%YCdDSmhKWe5IAXALxFX&PDh~xPOYm}E2fnDo26}0pdPMZsku8Y32jQ1BT@E@+ zhYgI=fd_T|H$le{o~G%$G?MK|t^c`*o2B#p!%BZ#$K9^+9L=AvQAdk~$aB9Y4l$7$ zFF{&5?k_C4O!~b=-=@ReEV=W1a{T0Qo#$3d&J_sfSTfplT8)lN1-(DQ&+GVp2sh~P zN~?fs9k)Zr{YldofX>lzlYrOict+if`%+!bp^Wfdb1dE=Iy?#dBf$3uA1}!Z!SkVx zAEogY#7)y>FzQUulRx5&r59qDo0 zy?pV1w&*;hud(F3qxI`!#f?F@)uLYk&mTa)g!^7Aejvglb^fTvD|LEbi;u-02Ra5k z34Fh^^fAF0(t}9bY31u4QmGFh{vj*=deA#?^LiKeJv#gf!mnCJFwnbluyo0QK%?PhT9Iu}$kpDicR^Ejl7!>{u=ieNE-w>2l-^}MA}7&+p6W<0L(Cj0H4tD z2kU%W5I4<|@wzT+AmSGwoN1+9gS?L+z69~VK>V*k$AOOkpVIk|EU%k%IV5rso&vl} z$8~`B5zr&F>}No)!`)k_ry*^umiI^StU~+>&5I;?y@h}O4xY;qe=+VGb^HXKZv*no z(DHPW=ni_imU9jw!=RrBrs8fzzM)84uk(ixeoONr*}3WvIuP;WlBD(5<-G+N7wGVF z2p^%tuK{P_z8!HlBmb*f>d$nU9h%Q641uE%H$cY^*LW%TPelG=+%F(JUgtjw^j|F* z_aXl`h-=1uA9ya)d;+w&Qd96u6Y&S*F2wyCE5G6So90hL+T~XIKXiB?(jPX=z}dQ- zD>a&=4-mLd%X&%U8{i2ee4(bv`wt!dG4OckXRaUV_=`-0#?88%pII_IEP7EN65V7p z-!0)45(i0K@@thbB)Utw-JyF(TD}J&`PHgr=h6Gg_>fRDd+lgLt5qo9IpG!3Gr};3 zR?=_{_hgNwcL zt{DJd0Y}BNmg6CB1|5&Sn19=3Ln-~k2cSGl-ebBik&FDh(4=i;Zh0r5KAl#3d{E$( z7wPS#uYi!=3xm)^>9hVMJj=%c<58el-w)8#OI~*6chC0b&xii`R{CO}J>Ei>T7m=R z`?UNll-F+Qd-l0rd7LwL9T$+#=ve;7iQe>{KKtaIhWa;!eV>CpwqF*K?-jB9J~#~OVfD|K$0FTok6X~5 z>n-|IpMH-|^Okr2sn7@Yn}le}e*pb!nbjXY1--(e_s1bXjzxch@mXb+msjqU|Cn`P z!Txk2_`??eSoD{zaNzX6Y>y16SF$tV-9iRphveseMXJ}hpR;bD={|14kr z1E5cqW$*pr4+<^&-Glx;s3;)!Q>_1h*+#nR|Ig%Lezf#G9v!#y&47IOh59T*f7lRp z`@`}Pun!(;P7f-3Mq&SiHJ(4f!>2)5m>r8^n14TCfBz;^mA^`+W9@Q^qB*C~TeiY~ zrCRcqLEo)b{eFu@=Sm#bbH76QAE2O3+k$c}N}B7ibW zKECm@YpS>WV+UeQzC4IGLzR7dWB%H1$y;$C`fGkbJfZFL9vIiH2nz0-Sf8uT!Fv~0 zdtfMtVc1|aLLSpc!M=TA->{bdd@9Bh<`r*ke3M)Cr!o7(9+v!&Fa1swG8zYBTabDbAB^`>OWz%1O=+tBrP{tHAe!UtIG;X4U|(}lzsch;el2-#p#J7!dK~?) z*-B6MrQef*bC`bz#fAfvzK8qPlg+UA3hWmc&GuM_{-5gDua8K;KIUS15Bd7r$)hko zJsgtH#o1p|PBz@Cz7s$fR%3mDXr}jo9;KGOPxtAw6#l|oEbpfr$oeAvw6A`*A%C;g zUiTfTmaPY&k71r-n%-6yy|1pqj@Ni&?PCv9e>|wQMlW)EJTPU&Q@_>9V zjq?RB|teD#OY+b;fIR zW@#tIYpN8U(CN5^G}M^pVp0rPq{NB z-;-r|>kF|ywDftcMhgc}es}n5Vby;Z#Dc{Dzc$-t(8-|3`|r&)$<^ziyVkw?bcYvHfd%VtoBO1!D*2e%O!P z!iLlr(_i(?5BI_!n2YHboJ0R+%I_my_x0D`Vf?1949Rn4>N^pBZl^U~FF}85w(R$$ zPrq!;hg&WEv&UjRVU5QxF+Z%Z+Gkd-(N6WZU&CLSi~4q)j`qCUUEd5&ga5&Lh}$ss zj}KsvpTHgmfu=o{N_3%x3`tvfym7*0r@=_^^5xE!=p~d_`rdCEAle^RA2vouLAb7^k26h_PB6(Zw}g}x7GfO z%ZxPL|I(oE+d=t#4ePViH$JXB0O?kF59E9EKZ=eLUKA3|Xg8L>atdgx{(0!H=A!<$ zApZ(W-orz125Ft2T@8A@wLi;4`K_%7!{ zhdxpaMy7SvdE_Z&Mw-$`^u_s>bsp5|+b@+4g^z$d0l9~YBgM0my!mIKzFRDNd{%(@ z)uQjicprrEem1gE-z8WdEt(UQ@2Qi%9Q~*4>7W>bb|;+z|F+rc|0iL6J_8Tz@V`v& zPsgM$+T-tNuU2b4n+JV+S>=!StrtH*d-k*B{|)|fxz&Cz_|`L9&O&?PVH>N>{&wXU zw2vkKGU#hA>Qm{XpC1f;@FH$A(wP5)D#NYp|F0A9ZZgilx*?kW^$yI3s~Q91;e%9t zi+JZa{vsMEf0p{?^y(KXXu@RaSjZhy7Dwf4C`W&tG7Cw^;Q#jm3Sg z$~+8OeT|8*4C90TbpY0r-}Zoi!-FbzbJk}D+SgpH{|#ubmOG&j!qn%rGojyuA;IUr zhp+P4`xNw_HcOuqU~h9#{x5OVLyv@3kH7 z`R?>eoDW#_I}Ht2YSBMM{qimPakNJz##;%BVST#gU_NNW`88!4&O*6RaM7VEza>x13+ z_~m>UkmY^GiCACMXBY>nzDUpY_5ZP9ld9@>k+1*Xb0YM?ev{3>@{UJ;7-o&HQnatR zDF0&g-&FXEK?u`dEc2B&_++$Co7=umqNCPZ{lBHaNK^XE^!bN(F#gtA{0&(Dn2Y6q zf$>&l*{dh|ODkU1cv|--eiyiSXh42nPJ2y3rlpwQ`XVpqw=2<~i!J$E;jacc^JyP3 z+c#cvefk!ly_Q+!e~pPF#gexL^LI1OLzkgE+VitxFZo&n~QgAwL@G63t>TC0B*_||_v!+7BJrRw{c!*%LVdBkQ@X)Emi)IczIR%50SA`8$bT;S=`!q3(Hye=gJzmk zRllG4#@{0NlV->MM~a`!^73!sz}6S#Pw@5s4`yS%XX$^f&z`M5{((OK_C=YIuJrpQ zCboQRUQa_b+iyMEZ~I?xo(nzM9!Ei5s#X6*DBoPvuQ+BXCGV3{F~3^RchfM?(yadT zTVMZr#J3;09u3`Q&By0V!}+b%-wN`*<^2`*UT*1^K*#U3EFiyYrv4jzumH+uc81GK|^$|yeO>R~HuZO^YS?lrVurTg- zZBVR(J!#+b(NUUl9tttC{C3#0!)nhoq?aOnkWRm{2L8$_?=kpOb5Y+Ng_xr(`#y6v z`~&94Gmyse9)-W|u+s0qcs3XFUk!iPY^8qz|GL8(FB^URXD#Zt-KyV+6R_XF`A{ol zvAp|oP+u$mCd?;o3HAPj9N#E^iB;Z%`PSk;oc;^@hl3AL?bDcpLSILtpm6%r-9G#O z4gSPj)bH5ASfAqgA(}WW!d9?pa1wV%3EsjuN;FtoF%_3g#F~efc&PG`t^su+hUdX_cV;ZcY^Yr zf2RKy<7XH4C+7L{yKo$xIRAwkl=Zs^?cI)-4lmX8uh5^&#rkDqJf>Ru?DqNZ&Ct(W zg_NpGCxVHhg-Z>HN7skiiS0AeMc^DWj4~R3+gw+4;S(tCF{5@fx zg_b@A$lvX3oHzDR{L4ov`TUpq%=hV+J^<~5=eL-aWqaR({%0=of8cB1(|z^57yUWk zs$aKs)X#c;bt34ccrotyfYRqU(5sL>6tY>LD^Q=cR(&S>nuRXKiZ_P!0 zbI@;6tn=3b-}qev`JNqH`e0thJ7{56IF%$lZ_P!SD^;MXEjs4F= ze5ZAO`T+b#E#@msOR~KOVm;m${uI@a^wHR#nv3P%4*LwV?DHqs!(2?iH-`DrYR}7k z_4x+vJJf35GT0-_qSMj8>#h7RqP#4tybr^sG}V3qtUt}g^8euTzt3Pjz0qoqn^3=S zSx~;q%KkkV^Z$BF{wdwj{+4~qFkb8N;xE5hBL4~)a+7ubm6Cz=+y^+%LqBEuedzB! z@H}xKbfNth`1Hv^ebcP^X8YRrG}v>g)xS>0_%Iji7xwknV^D6XC2un9WiIl6jfpx9 zAIX~^cwT{iNBVZ3{?`xo%IlWrrN_b_n~U`sh4~@7HY92=f3m!LV9(K3{j<v5i+1vO}&t1u9^-x`p=7eV^`TKH>}&#M>S zm$?xAcgF=m@s;K;#D2Ey>Y)5>0NUfalVKk$2F>~4+aWxU!t)>ub7`-+2=v|*l;0&% z{?z_BFTs2|Ud!u=@w?d4|1ZTz&=>7Lq7467=|8_fCjyv0rvUSXRlijy!G5dp{u1Mq5?i{%KzN0Cf1ZmOl5Qe>CGI@*7cqwolzyFaHf#Pi?`+ z{`{=~+NTfFH(C03fPHCi^*$T(KZ5qEx7NE2zV+uuG-Qiq-&c=;ysOmuiuvy!g!3)@ z=tC>yl71BP$!?2(t8ae)X&Cji>VLj({X7i*++1wGcgxYKX zncT{r=lj}cysv&yy&l7`g1s=;`TEQKzWL@f^sf}Fylc?^6X^eOng1Yh4h89p`p@&# z{|lc#Trw2>#Tx(5q5MTwdp$HA`+3V=Yb%X(Rlh;`UV8D-Sl|64AhyBpu>I%F@}^HN zgZ`F1dmNAFeYXYW@A9$zzD0j97xljl`VO`DAH;ZQxAc1f{=Cv^j|%uVb20x}=>MCo z{3)0p+pYTi0rp#j^#Ya^Qs2u`5x{~{e6o0}~C_lG}8%L_Q~lit$D%YQujpSh^d8_2)S z%6}L7^BSwX@fZ*0BL7pEXL2n5cQL*eS@dx5nC~$T!}l0{eE#7NzV*r0G$kF=knF!7 z`}#XxjS*@1;ID^FKS;a}`){@MdmZ|ii~0@3eAs(4*3$^no^PZ4LaV)Rf&Z$t^7q61 zvJ}r7BH$zcud!Y>7v(KOJFLO;$oKbC=|`h{b20tz=r292_39miO{!|2XE1&?SoV1d z9c2^Np98_h{&BT$zj7}6o4F|eckmyDR{wj$H-7#I{nsoHh>d!@JasiZ7p85SKr5#9B!p!^1l^^c>_HjHQ5o9C~w!_c0y1M>SSrhg6pu*;JFQOszo>O1l% ztiSM*#^FI_uM06>4YT;4Lx0|7mH)hN{nOp&Khx14S6ck@kA*+M^QU`sdql#pzm@)p z&wo9*Klm;CU*&7Rui;-dSoST1J+p6e&$C`WT-EP%08AmyM1QZh<&8sqtp0`NrM#Bo zU$`dmPpm()E&WQ-Kgz80iUAmZ=3;xF;u|m5VBNI>?a>WsY>#I%5y1OhoF>?RT73O= z!dN8ei}G4wZ*!4;cZQ)vS>^?4oRr}>bO z{QjNeqr1=km-zhI3;F2JR{4|Q56ne-^Sj5zR(Ut0JaaMqabN%V#%KT6VT2vnoSE-Y zE{1-+@4@<4kC#{AAIwF0@8=pywO;`u*Q5S$CpdrWBaT6TueI#`8tSvkqJM?)F#{ha z@;4G#|2nj%xhVfA{Ik}QcOxA0LaY8gFducZ9Z^S=5V;_DBX?(w`3jf;!l z51iLq2Ic#B91q!Ok6uoH!t*DT-y8E4FYce#*I>L@=?5WcA@)b7A)Wr!!V!q1I z^v)^FsV?d}0rpF^{AUD?WSwQNqDsT9?EB3Tkcan=%=#t;?PD&=yW2;%`uyX$SpP1u z+HW!Rong_PXqb-Nfb%}>9N+ji-?O6|N`LV({86Xnk50jOnTh#O`FpG%P`@;*e)A!J zlSQ9UWVBcHTa9sGF4pJ35Y8L%u=bY-b9}sj_AnRIFR3z=%D?<%%vV(*!D9>Bf5LG1 zgzNEq;b27{kB*hV2h$r-4%2TK0e_19@(c`E%0CGDr&{_4&>pL;_GrL(N;vI(q{vHy z{0{d#`ApyZSTY*xJAAzT6Rl5Ate3-vtx`pSftSgs=ZUMviT zKhL!Io60dBtoD7l%;Z+>^Lh+2tn{bRzbY;I^aHTpv*iD6wl{yFPu|WF)ZZ%qBlsV4 zQQtYf`ML@9onhH~E$qF>viEOzz@#tc@8`46$G-kI6Z2o#()VMG&)qoh#u7;Or;Vr& zuMN2APu?zr|FG)&(UI`qSG(^g7h!&>x8&V~^M=(H-5pA;DRbwS!{L9-MSUNFqZx|# znJ-0{?H|N?avS!i*J*v$VLUCteqf5GkD6t2tM=i!eU)X8JJFvvTlW1J^X)D??;NJ( zpD_mG+p=c__FruA<0wmvMtO8Y?4RZ6FNIcm+hA|`neb1Gt@>UJd-rwp=_8&(dHGg( zzkvNlKM<6^RYUnVACLVFo^PC`^-D*=o2~Jd0sr0&->dU;Shsnf4PCmU8B5DN}c_P!AFp}8pk71-Zgq;JOhct$j!exDlh`(r&@ z{9!;Gr}L-RLf>D7F zUaKW<8pgA^SpM(ekJ_#Fzt^{)dD^NV`Del3_Qv}Ul+W^7#~W!%pX0HO0am z-p@n3w_4xZ-jN2q-*(p%|MdB%A*g64_P_WfS=#fdD8{>Guis!i4aIrv8k9wSPD6X= zTkp@FkNoS=UyxnCACL?GnF4>sVM_iRF@C#Q=P?U0p4zPb`+?8?W8gnp-U*1!5J>x% zkHMPRYTrE6f2C!=dX%>Y`&$kZmeNT8fd>+(dt^TW@Nb1b#5t&_^TU}R~ z+caxdtYOTQT%jYv4e{9x(YZQiTr5!-t*fk!X?kj7OfyU>uZdM8Wb}EZ)6fM`--c*? z)uj4Z9kh&`S6Y-La-u&js|cN4HC&gZlB%XXB#p|&AgIf4h|VvNZPrEX$bz~`nJk;$ zFL_i^BNMCZW+yLs7o|?_P#np8&lwDn2Q&Y~K;V;6+v}c|vu%Z@J!;Y6+ zlFOBhB|U9oY(APbfksKLb9$!gaE3_@3BS^#a+|7aE6Gz3o);cp(ipBO$&6Ho$2+4g zxwU0wbv9ZgnT~qYb*Wx{n$);-T6U4{LCBq+CVRW=O0oqr#ucZJL=Q!OME|Q8Q(4&% zYiukaYla>NU76h~H-VeX6DcPXa>7lGRbvu~hU#)BdX$dNtF4aJC47m@Ga(B8<_Yo2 zn3KndQb|tqaB#B%MU{|*aqJ{yApun=s!POX#~S82@#%=4RvnvPA8$yQ$ZW(-YDiSY zO+$wmc>8kIJcPAm(iQ({*_lR5F^4#(?# zR;Gavo3y=j4sRpD~~m2%rcxKzzCNDa%vs?MkQw9#-_P3 zcBzs?Mph(Jsiw3DX0&)kBoUiiUyJ${6_=+M6j!Ge6r`tB#$+0;5XKj=x-%+U*XbI& zos{w6>gHH&2^~?j(L)Xb8DH8Et!sqqc2t!88gh!}MrX$|@|_%19ns+^ygH^FouMQ# zVjetCyrHPeh|HQ6tH>xQi58WlM+yptV}fjq6-*q3RZ3kGmLtv3AyOyj=}0x?MJXf< zUbu>af|8M3b-*Y_d<_KE?6a5}S!T&_C8RM6cCJr{XjrsiE>}UaT3w{0?h~+Vk`r*W zsd=y3s$!;$m(Acx+lwi_Zz;wmQ^q5d)G8Qi6R^6gt<}o!qvAE+Tl4Q*j!_*YY2A(I zl>Lr<+v#{2^gwDTCmZVQf79e}3dgJA_!^v^$?=GunHP^YRQl8CSvk*+X=sQpaEApw zs~oTvzZ!r|bzC-A%XM;Pq#|CwAcCGy6y8&tW<&}~(;}sjk}P&y_*SgkY8zvb#De-5 z+Nvax#day$Tfg6vc&GnEIENC)21W;99?BdQnKB-w%W^VCL?T}0WrwKyPW5F6hM>#{ z#6VVhvKr7Yc_lk$`7c*1%NTPE>z2fr|Nm6U-m5C#W$*v4UATI}HV-D*V=L|B^pWk% z9dKE4Pgu?saHJxdsHoC04Y5R3Lwvrbus74G*v8C_&-*@|y2f>h+I<%kU}1@xjI=uL z2-Q!E!ZkHDtYx}WOWChY^4?6Ev@j`fq%E*?+QjrUR=qh|UOg`zPAAe>9jV|ZSdLkE z&{=Y+R9fO+)WN>zfP@0RMfBlcw;RTyp53oCM| zt&LsYDC~|k1NIITVeXotFT_b{9!=8I!8|2~t!-WHf`YEHOlx>D={>_lPh@%q6)&m6 z61oEWMx1j{TIn>F4%;wX^^($ka0GKH zq5z8@IDsi<-Rg)(jT%K`J=!e6bH9>AeQi+%B&JtXMH^6Bv^vp<8p~=Il$00Yj1!A2 z>?1G}BJT*juFp%SZDf;E^?K~xD+_9HiiWdHo|`4c#}=rbfsUch99%wGMHskZZoMF2 zd%_^hz;Oph^WCFFGo`1)nNDS&;Eqi8EqB(FE(=bB=J*dbL85g2lo;n+<#(*zkYDf* z-%>=2jLZT(`qJgmBTblxvkIQ}!eXMau_9VGiw3L2%p>~@S^+6mCoM_*piYyXskdNQ zbY9dHV-siSHLfEU{k%L{8?CE|MP|htB64#XMh9{k>Y#L_9F01KgA{u|vv52sqa%@kG3&wi;!^{8CrbAv31d zSE4V9ENcY6_d>R`f%TvW_T_ZwvDmEYV?M>+kex^V(&%jGEaQidwtXn%haQ-Ghx$K!7jF!jR*Yvz#nJLuZ6mzAQ>&6j zdc4L0#HB?rZ^)w?tEK#=cKE-yWgDemHIslxEjg+0T`f!|wr1>OZbd584787JQ6ZJl zr%u#`9W@UVP!s0JEIsLKSKx63T?+i(2Rf=~9JBBd5}))PbsTXijwM?`WaH;tIZa~lpl_2kIo$z+-*CYuhCIow!SKRr{`x-eE- z54Yl`fk;oE5N~RXO^7F|<8}J^k8U)&ro1LRKWix9LfZ_b^x-UI5>BXPzIl9dV<#(t zxlM@#1g4LG+mf6rqA0)I<%VipQ2Ly0>3lqYfo7QZ@nk|}Ls&h3V7#TuNTo`#;>yR? z(5H;nRWnSj_a&!E)uva)Vzo$dHKSqDFz1K)U?f)Q&6S01(R?*I=p~76tZY86V_Ox3 zJqv%crm!`K&!~$P?JKuurqk}+OfKnZGy*11%v-8yyQWmv`BKt#9`76_KPGR#(h`miedbtVAKG9##qqR#R*D#O zv2Ul-h%5=h|Fl!=oQ{#1qlkYGbqZl8Z-0n3}j(l; z1ZOyvasq@(IA52K6C&}ZL?k{dg2&CXV|q9H11B%J(!_S173FTxE|n$kJ$eajb53q6%TYX*9jAQoa-6lFmzMkU$P4gRdT`5Kf8Q zXmgk!E>ej&uFsFntFCZQ@8x55l~~Y>J(eS6Y`h77S3;fQC#rZ9>4<<*JV8+Oq*=2X zw65qWsli^0ZYU>w;FHx}JgoLhtPC<@ABJ}4dCs`nI1cLM zu;QrqY>C)4jEqcW5Le3V+8J2cgKoe%ItB8LBYXpA$5uDu^_T?^IvvN%@%gg%yE1WX z=C2L{s^yRaqGi+pKxZOrWpobxrWa)f;I>0w*8$sG7%47X1 zxovhAP~})+m*Yh$->W__duAlJI^i4#%hNlze zQ~cWOO)N6WZ34Dt@>m;^aqI)PRMe#&zSS0{9BTq)&aITj!x(-R0>RX6h-^-QXlAn3s#7dTfT73vBA~ptFH8 zM^a|!ea|l0r5E|-egE@MJ(it!eLf$>u270$oWj zRj@R`gYU2zXexlTuBRF7)NIWv4LtCX4i2Kd3;ghTu){H@(2UgK zc`U|R4E%6^y{`|vq0@*6)oM&M)ZsNPr`l>wD7EFw0cNPV-rK02o~hR}YG68b_|H1N z8J=FDPU(&6Ra^P?0#;{nyz+}0=(iVs&>_h9J=Vt=+Me^XFega9H4rJuiM9Jg{D4h9r&6p+2{A)?VNKDW@i_vv zN)OE~d1cd?jJh7G!-DWs`pwV1t#F@NC;|I-0BQXJTMK2%BB$@x<()`u@4_?rUmN>KC5Ax1t zIGA~I51nQ2PZRcha=f=*VpQnjVEoB+`@OC!tcpoU46&*v&?_H+wA4B-1nIA)!56_hwwkVaw(pip;P|F0qdzuxI zCwI=5V-UyJOevNg&AjZ_MXXwXcn{J3M`GoQ&i8y`k9sAm?so}r=a&Cqfs;(In#f8T zu@9{NgTJ?f83+A_7ng%I9%_QOsR7=;n z`Q@rwb+Hr`Vt_wDKs`+%@^emnDZ?H{&O9A9=~Ugs;hQpx&>XZ&o;=cJA_FEXzekf1 zj@ewQ3y)kbO8FF_7LUsC*q3NI`LTL_nrl;CiRI=xy6g+WYUD;;MaTV*#|y>b%G|<`9e0c93KKZ$@095p9H$O@o}t4 zmao|`)y-XL<*rPU8($Ne+`X}v7B5?M|i91XLqDj;lX;O2JQKC5fnXIX8JaM#>!+h=uc`z)*N5$>AX zHC~ouJ6ChdbXl(DT+Lm>WjS_pb6aN1g4J|0<7087hGSyHx&4HM;c$gn&775_nGt78 zaFw+rSlT9O<}9?V(-%n?9ULtuL>uwr__`V-38QS zQ-I0gl%YIW6Mm+KdvI!^!$x0zr?1}gIvPg=A`b`KoWPO~?NIaQUA6J_ar98x{pM;U}9Ln%;+L15os##ps z7hHN4cZQIW<#r3^Qk0R!eqB(BpZ2N6EBesLgiSgpV-x3m?%gHIaMPlOTaE&UplJEC z7f!%y3H+{u5yBn?(ySkJ(4?}h3+6@9m+`@Ry7YM#X}D-2D_ZH|=5hw5SDN&JZZ^jc zdZj5}Xt5=imf_Vc!>OM~T88q=jx^Aw4j$e3D;QRlGLq|-;nNMYktUl47MKugtV%bs zB$13G!{*2^9PCikRCWYMh@z76IASD^BZt0dY%Eq;jyGxCj_!@o^0?~6^Z4pUxlB_b zoy4vwkM*dlI^R?Cz7!vyEiE<{X!C=Voq_SjHkx0~VTd;qn3NCF@Vk=%ZHc4Dx`c5^ z4q>doK0LOesWG8e_c~}&Iq2}KSB|qXVblXbznfw|;8Ux3981kQsf|S%ne0`3&SzGZ zG>T0dKDHs^)kl~{n5GPm(oY@4YB};yR*6(UeWSwWM|4b1Exnj;&M8BqEKMcjQN}eq zu7$M*6QcEMe1JoSjSM&4DFx|Hi^>^8<#9?tx+|YktxQ+*swKokn38;)mN>=PMW*zx zQWizU^@BkriR$`#{%Vm@ z$rEXGV1Gvr?Ed+gu;NsN;m{?c>*Cjn9BUd<v&R@TNy^^x+A4XaI@+0bf%K$BT9KwS zdKt8fox?83$>Eg2j#r4!hFNo>F&`UP?rhCE#~};{jUpp;Z=wX7)_io=GFnc4Dr7`Z zTNNV>se}HE(re2!im(ouTfODBZVYGY;I%sH~zAjn{WF%Jq{>b5>4{s%o^U zM3d1Kt9G3-)!mKIHR&iW96USrdkXV^X?n{*G9!YzvDtT1w5+C08$Pcz*+4Fv z(@I`xs;MkCV|KQejCQs1^bnQi>f-4kGSOAQDVq(g(%g*BXu&}rQ~6S<<0CB+#&>?+ z&D5BUPuu54@$6nQs4#=pZ_yccSpeeIkE+QrLpDt&=Tg;oxEveEq7lu0C5zT!BSlsf z%bAKv^(t8gbt>07n6uP+S_XUxvQ#FR@^lWh%0+^+zBLIZhr3i|_XFp+hHAZVcL<}S z&0+FOc2lZ68r9jHqRHVD@8Pgz`1Q~eJ#At3+fFH5#yF9(XSkGCSG@?Zr8u3-mZG|~ zk%BHJ3(!AhXhgC*Ou%olf(%S*lT!sYH$I3ojz9;E40aav>!g|T(8+{N zIvc{o$@)8l;jkn~MKy!7%dsS=x!o|B@hsP9I#O1`giQ&S1U2s)hGY`t*wzeA16UH2 z{S8Ah3DOs924^C$B&eytFgOypK2(v`%; zV-|?2`YvU7q$K`6Ax4B=L>eaRgwn&MYTaib8!S5x<8p82LoU!edrUr(^mRwq<_)Ei<{@GJSRfom`sNZkfsLmg%z_=%muJ zymoV+Pvz}CVdPtVnZtfEcuQZ?CtS1*UGOxvLH)=vYhfs37rJ2l zpa7nqsA{WV*Hl$OnQB+Dq#|0Ya;lJJF&QDVsgNzRq@uc!KX(C7t%D|&ZLWUi%WX}Y zHhgUJlB#GWeozDZE-A>N3=eymez0sFSXg8dF0+}}T=ruNPQE%?Z3i5}$e~8q99qZh zE@gPAksB+!lSLXXk0fb9hsoGp?zG%kuOz3Z$>;VCm+WsYWlHntq`IEVWcr_1lI(>J zlj(|Hom7W(nUYFUld55IwZI|J(Q$|udWq9obGMOYbi5kV-In=J5oM$5R3|lII!sB&9i~S*9+xS( zBu{^G=Sq)G-u`6Gl%Cpo?Bvdq9!Xw1sptPjL%rcLJ&e8|Nj!ko^6$6XYeZ4@M1)p^`@)y-rn>rLNVF>=vc)Ro6KVN*0` zR}&{KO2%sDJp2ZV zO?xs=Ej78U53I%&BYHOeve(p7r~t{;v+#Rr@{@K%IkbFFRTqLX%j5X16`57XmDI;7 z@ZOatD!*9NR+rDNsE9P4+894Iom2%wBSa*I-wKW5Hv`KX8`WP9LlmY0aEz%-l+MSG zqTqv3@QQJHd6CRh)5N&qqTIYl#;NJ2W;$W~;kZ3s{A+IlfAfu~{w12*4Jj_0$K)|_ zwj`UId~TYTGUX^4sx-x+@&rXt<~DJZYk0lfN|O0kp_1Y98!1YgWbycuiMsYGuPVdl zRORzu!>PiGM}_TNCf>-ibzo_(6jL8J&ge-V*A88C_+_gyRY`{1F4rw7nWlDbI~O%@ zrI`@5HDOy173=EYN(zXOY*ST^n^)0>Pl}b2T^U_@O(_OV&6vkI)AyiE1; zyE$Ag!>3|orY`x6B$evc%Y@jbiYHl#Dwj%e%T30w;*?ao{|en_Y#BCtYEZPQcbL(yt0gylqAJth8|w|(W!t&kunD=+ydjfLjd+>K{IV{icnEZw|9>^`jF#(@ zxxIakT+E>^mB)-Km1a_nJcDkzCS+u|w2^1aFkAtVf^yA&{yhG8mu7xNxl&b(H$~Nn zoPL{n^SRPgJac#@DauVXr5i3ILB*^5CTyoE2_|MV{0{+2iKCj5PG;tKrjVB+2Qo9@JWgvcS@ zi@(`Rd;))JowyEv^OyL0^c&)zgeWDxj=yD2d>4O%o%lZfwli@T{w6T-8~iP9V*ddC zt~W34v5xp{K(rGF1jTydz@XSb zOb?2U#GIhmL@Wx5&BSm}Y$47Fimk+kpy(jZ4~lKXmY~>9yf!Fy5N{8PPU264VkdEB zQ0yW;9u&KYzlO&=ANXWYq!6D9if+We21O6z=Ah_B+!7SMiC+apUt+hA=tn#{BvOed zhr}S_$dDLHEC`8V#Nv=hBVHI1S;X>?$R^GTiP6OBkjNp{heSTHDI^Msmxe?!@rsZL z6R!%1QsTWKF@v}&BxVwS9uj3l{2lsA;<}KiBK|fcYKa>|qMrCtNF<1FhD0-QTSzP< zeiRZd#N$%LB4TQaSWHY$5le`fDPk!xH$^NX=BJ3|#BhpOL7bc-cEGO$+Tr2hCjwO= z(T#||!`*|3zj57*SdMW+#2=gQOB?|E5#NXXi0{CD#6JbaP-0Kmk9cB=NF#m_5Lv|2 zgCd*wL{N+-{vs%Hh$jR@J`sOkzK~dj{uou*rm>ju!vZ2qydL(_SVhbZidv2J8WS3u zH7?ZHqH&SN#Tu7rT&i)I#^oAUXdFs?P~I?&*&17!j=!0{l6Xi^tRk)riWN);t|onE zKx`vshs1W`i9+lk-X%mQ@jW4S5{m<37x8C8>?W?kJV!a>QbY=|9)5~AIV4tVT&ppS z7)lXY#F?-&5q~Q_hj>gtR1znoh$`Ygg{UPS2|q&|g?>iF{MJl-1%8H@KtCgng`Xj| zgv4SZ{+|63;z0NrBK~IjGU77$8R8`&(Mr4peucOTeuP*dL|^#nKqLGw@#jLM63;-r zh{s|a67LI$VZ<=TA#oJ^FY)9Q`M28xQPhw0W#~u528=`E^q?ptz8;i+b3O1f#v$p$ zFb;{M0%8X7diY=B(-?g67z>g5m4TxUE ze+5Ku;*@~sOS}<&gm_9oq!OPDh(W}|F#i%0n16{6q5X+}gdZUujrJ#&zz-9*qkj{# zQ$#*-DEtUFwGeH@SWv7Xeu;UQI43C95x)qEcH%4{))UVQhz-Q|F%J``VIC$< z3W?3c>jGj6@gG8LCH^cVI*6G1AM9NTd*t$2?4YJs^4z&q4bWe}ncX-hz3An1%6AY{U2`-WL>ui0=i&P~yN8F^u>s z)?dVaL6Jo~9_ugSGK_y2pCWRIpJV++9Dwx~asL!iO#B_@4dQVa|HNR5m_fV)^Dyyf zA+DKx`%6it$hU722P8Aljc8!1{o=1M?Gc zYDnxPcEk85UKtX*iF48ZuK+*5&WIR5`x9Tl_$O|{I*j-x))B-$82`j+82`jYSVs`g zMEeudG5(3&FwYY23W_vhceFq8Cs;=iZ^HN|ZV8AS;v-l`5R1|N#4y(1#CtLRiASV} zQsN^)F@x9~6f=nrqWy_yV_iX97!Xy&moPsPw_^MgCt&;&PsR8r_Cfm-=V5*%9*gl$ z3SU;gt!guPrMEDBXKm^pEwBXaN;W%|HM%#VkPliv_J7)tiy>LgQAVN1pc4+ zE!v-W4g5dx=U9gm{}vGIiEm^46E}y%Mq;H9n}``HVl(klv_CNc|4-b7bvSV;)+fXp z17bU|C)%G_g!U(1jPXy*4~bpG-(Y_Qd!n-ii62_$b<+Sb_E@ zeuME(%)tCloCE()T#fY+@i4SMaVz#=#FMc;A`VCU6ORz0m3T%-tR!A1#46(7;s1%P zXn$gNv_CNr5^IV3!~YYng#Ra=jrJ$@!Te7gfbmZ(Mf(#cVf+)*F#i(|Mf($fB18xA zxscdK?8H8dcn|hr#Dh{qC-Do6f8rx(e;JSYpZE>t|1H2zv2rBdjP@tyVEhwzVEhyB zL;DjKhD2ZDzv2Ih_n`fW4`UxedB^D6Nq z*p)a8>nh@K*p--#pn1Pswd6hT;b|p@NUnR~EVmtACtgDDKF|LRgVBJqF6Ji%J zig87(7FeJH`GjQaYeixb|qq;Qb=rtU5USdU5SriT}6Bx=NiOkpf>R@ z7+1s>v92a=!MO(UHTYHH-{4n?ZwrwizJqZ^+$O|A;zw9l5j){mi90c_h@WC!C4MHv zQsNiztHiIct|o>su81jER}=Tcev)_~{3@{r+Mjp`&Nqm?Fs_J)VqHZ%9DbG98-A78 z7vqX}H2f;@c#JFJkbu}k%)q!Jo{n`D@eItX#L<{ni8=7A#60*_;yA3Uh!e4{CQik= znm7&fDsg5&>?U3azj^^Mf^kKhg>gl!g#E-G> zBz}T*74b9pRpRH^cM`vXUnK@HuM!WyzMI$+^D6OhtgDDeVqHx<2J0$ffB046Agrs2 zCj`Y>;t=>%;>qx<#0>1Kh$C>mMLZkpYGNMN)x><9ZxP4ie2X|4ew8={^D40f`zqpj z@T+pLY@?m{*BqSXUFv;a7>XgF;*gtit&gu^Q_t;#{0>5$oVriE*575f@=z zC0-pA{fO5DMJjPI=2hZ#IG-V2k9n1N8~iHq4$P~>6XvMF|QH@_Ep4CNGvC&U|mh@j&(J$2j*4cA=pXtztgDHmv9BWLVqPT{ zg~V23G4@r&iI`W3Q?RclP7jG4#PhMQBF@CTO02-VO02}Xnm7mZD$eH)h+|zvY{b5r z*o1kNxCHAe;ogRbmJB)x@`Pu0s3=)>Xt0alT3H#JY<3aY&RAKgYV7xC{F# z;@4PL5x>RxCK2aV31SM)orvABuO=RxB3g)t<9w6Y2j`o_V{pDnJRawp#34A}Bo4*- zCh;_!ZxTnQh*shmSXUEAr-)U=vr@!rVh+w#h+|U38e$&KRfy-Lh;_u`6wyvBO%YSC zd-tjx-L_xa3sZQ?q4*~co&4FS#kapq!6g0dz1{FHuW#?|fq$zQe81ycT=yb}sABT_ znUTu{aS` zIi$-ZP1dSH(qTzwkq(p2kuCvRiNT*6VhjbO`UXsoyT~As_nxdfWQOnQ@~OGz&!-7aYsUA3Hao20QQ5>>6FTP0madKKxVlCC7(M!H4P zRIO?)>3T`ml5QtmCTXf#wSjb4(h1U=NaskJs#k3xohE54oE)!c!a)5cy@GTq=~hX% zk{(KWsiaquP9xnS=~bk&N!LqyHR&AEWs+_qT}V1C={2Ooq;n*_mh=qLX_8(?x{P$H zq}xeXk?tkw^`z@b3rW+oRn4S3ceDN*Nw<*hkTgwQwV3oKNpB{-lytkKY5J<=q}wFD zm2@lVR!Mh|UPXGTq_>f7Bi$ltHci!9()E(wLAsrEnWWiNRU1f$CB2jMCek^QX46$| zA)O}a-K0B6r%GBNShbyWFG*ujiS{QgB;AelF4CP}vHnE)#Rl5Ugq3eu^hTP58}8YkMQzob`^P9xnS=~bk& zN!LqyHR&AEWs+_qT}V1C={2Ooq;n*_mh=qLX_8(?x{P$Hq}xeXk?tkw^`z@b3rTMv z-AuZ3mmL43TS#|EdK2lzq&G==GwG$I+a0P9^kWQ2IZqgm3Qzb3Xv{lq!eq7m{u!-T9du|D;<;cSt%+dNJuuk}f5^lytkKXOLb_x=qqE zNw<=2m2?^D|Ht0fz(-YG`%Ykh0V8LyDa1CdX>Zzw!o4?GYKc%As1qV(V3INu{6Oiw zmYdS{73d6KWnge-Fo(^-Xh=&HmD|#m+uDkTAPUhW#!P~!fr~l^2u4Ia(annM?wH-22-1?(e+^zsxyn?X~w_d+oK?-h1tjvyshT-%?{S#cm@JfQ?1Q#*9hTv|3^BE2iY!K{ZI6`nQ!8V4g3GO4f z_fOpZ3APOb+|6(e!485u8Qwy$li((Xw-TI7@Gge85u8u(c80eTTu5*Y!#fBrA~?kG zPJ*Wpyo6y)(op{dFJyQZ!DR${7~V~=hu{*1_Yypx;39_i6TFb%e1@9{t|HjUa4W$} z2(~fYPVh>Cd(UwDCpbiKH^ZF-R}jQLHZ<)j zgJ37am|UX%3AQopAh?g<-gmkE6Kop}xSL@o!485u8OEd&^-pjU!?^_K61$?!aaYY1*)cs{{f z3EsspCc~(Ig10lgkl>vJ*D!oL!Mg|!FEGV1r;M!x4ge3AQm@O>iHD~-Cm22nl%L@mf*k~RGQ5Rg zC&5h&ZzVXF;9U%FBRHSn?F?@xxRBr)hIbHLL~w}Vodi!IcnQOp!55Xl2?x;Z}l|5Nu<(o#2%O_x5u8CpbiKH^ZF- zR}jQLHkkG*gJ37aa8jWD3AQopAh?g<-am5t zCz$qTCb}7R66_$jli?hKodh>AoJ(*n!MhmFBRHSn?F{D=Tu5*YVE7@vZD59CyLtW7 z3j7it5vEy4w8=jt)hQNS=ypzgs%JCv2_qkm5L+-MjCT016t$-) zqr-j$F|{zEJ*mTpXR=5<`o4`Yt1RC{d_A0h%lj$a<%l18rTc8FOLt}KE~g0O2zRdV z=IKxCt@<-cGz$j0E3O;*bMY6MPKlnzm<_0B(+I2-*}A$0(7;(uG#zH*O7!Q1I0~8r z@xx|1w2^_+VZ<=K#cv1LWKj$QcvNpj8viaCd^#{7+y#)rTlD9(Z~>KN!5MJ*v~C0M z9q|KtN3YG^sIdOY`8W1 z=36_SR?q5BBN3!*#NP!)yo26b}P)wZ&O8j3ZK6F=aJUo%<;-ZL3^I3hk9-cyPmJ|ac zPQ04<4yu|WByPfsw%n$7oG{ZFL#dpJb8hkP_9h>ziH9d6e*C**d_m*4Abk<|HY2Ka+JvEC4x1x0X)2*M9BlAcc?GRT5$!2s_)h4BRF$+O9L`@Ln689{JnY5y`>+P ze=p~Mkn%sMd)q1hcHP^md0YM8$}Im2fyp10Zy=BI{Vd9@efP}Gx86qj&5H4od_sYS z$FJblroJ3_L(fuQNInc5V}1LY)Hiw`NcS4iC9*BOybBs*#>u4f?hl*s@8+?=J-Lh{%1gY42I-r{8cnyeZeXJcoGVX#}Iui zbb5$BPPp=*Sfk03e##Oy+FkP9uA|YjO5`3&j+#k4>|t%wa|-kW+&Vf^(DeoF`hva2 zDGYRVm?Ed{+N-8=I9Hy(4*F*KrndN4$lM=!pbZEZ1k^sA(G>GHpVw`SjCsfNg+1u&VTB`1LDb z6{LBnAnu#U9uPa>c~tfewh+#K3*jIOQDRsY;wK;0IzG%oP@j|8LdZg_A{?7c(?Se| zh4>Kr5X^*KAPj8czhfKFM6d2nsJ6TNL^DPY1j44r z-KVI@pJ-tOEDH~gWS{gb`XK~_xm$2KrJc}UK=&1Q_W*Jq*Pq8g-~jCOi8dN<9K?u3 z+UjT1wpxi`-P{I3Ihaw=Q=DXk`f~gwn35A@c&xtS0d!Oka7VRG|KYY*f;IXNAJ7ko zV2yf?23`8I&9COhDL)-O*|S=(N%!v8pVQFGdG~7Gy-MU?C~3P6uapNgWS80 zsoqVpZwzjtzHt-!#&j+RDVO(~PdjOtrXL)Ml5sw}^@Cb)x9;7Ae#pH`_dcX~A5tRN zD@s;Tj_6c3^1<#O!tgL_U_S0mdRBiv9l~3q9%_EoK`iMVBY9-RIqgIb7u>0PcTkVF zL-%giyxaXZpo)-7*HJKz@&qPPFETLw0p&m`$m)(fcdOctZqDqFl1J11+z6|m^KJ^9 z)`ufaN-_B`jg87-5^G=wGieO!yO<_Xh+s-5(aiSm*dRJ9t;AN=VbG0dx)YgwYl8Yr z?g{M(gzaRFzHxo?P8>Uc4(jU%jQlW6$M`%j9NP98x`_kvyGcK(YZ~Ui^~BSJpfRIF zjDf69p6H0H^MN|ij7duT?pw^zEWJ7Kcj(^MF9ZT~JoX=^Kkd&3k`nJYaWeUImoEP& zX?$=jxt(ph2xO-xLqou2^sI0@M9}FUr?yWzT+wXgdS01W5EnEG47WP;&%$tiMt#2d zE$5^r&-&BYMrrd6Ah=3+b1?YHMX<8xFO}&q%t1K5@aA%Gs#4kWc7Ie@M+&}@$1elt zU*E@Ga^ZDMY7&CvQ=`tlBU{~cN4CReqX%YG^vJf^Vv#$tonQ$6O1@5qU&7qC z_&_WghaqMTqn+uu;La zX=H3l**uD|YpyXqwZeM2aAO;mR&6 zZqs~ON(84!Y*W42>Pu^mrZ@?~tQGV7ni|nSd57Q1U;q9q$Wd+B4RGDmQo%e)WGoUj zu;_tc=xfvf0llt02A~SgU=v>jj|9I)n?OPAPeRG4e3#RE$E36BSuN)}5vij{r4#T( zjPU!4HrtW4_VuY6MO!;uHj^EjR2&fxGv-Nl`2 z&LdNGrbBsnrrl%Qb^>Bv;lM;(d3c3g9pPJS^B6~yK-O-91r|e)eY8o5xZy$yPl3pP zfi|nNC!oK+W6_<+m701ix&v=`fesKSLL+#NV1ih5zZs}%R55D9F8s=QgBsn7cTq=p zvAd4yVFDhgnW;?W|7MCSO=v_{%<#U4gmJQLeD8L-7u6dX{WV`nJb5K@uv5=q-{$ zmgPi;Br!`wl(3R|lLut>0;IOWAqkGdpEHy#715vxL*JR^M8}M9^H3Cm@aRC)Est%2 zR;kQW;?Ho73@DjdXjznSi&nsd8;!4<41qpV203q%V>- zXn}xSqi3+iYw^4)9N@5NwcQlgcoZFj5a5{Hm(eB_&9ffC>-Umz=*F88{Uv@qix=~5 z9j!M1mlW+M94+1-&3}7;l)!w?;+0i7Xc6GhnF9H2Ca3ABnTvl+2Kg{{e`>Xlb7?$E ze`&&dF*-o|@fcr5fnXm^nmL&?XF!wescS3!JW2yY!w^stp5+ zSg9OUltT4ssKJ}nDn$MDl*Cve43tKzT@PwCONCnks8)n%wfAJAIvMq^nW*hRsaf0$ zBqJnGaxXeD7_f9}E4C4aR@!ZW8^sbw^sE{<6DT$cxES1L`!6Go)n4}1ansWJCCJvHxzCg@&Jwj-DD(0 zNuzeoI#I}I1E@j?^scPM3#33u{-w0R6R}2MQssBLfP^ekCy`L<$CL7 zsrBOF7a?}Yq)rkzX8ui8*p+On8bWnYyS1N*>~M2Vd6n(+gsuj<%Jz4lNA+h{**=E| z6v8+mZl_pdZWP`l^TRE<6;&ma@;IbCtzg@3d-s| zB4*@6$QY?q{}85Y(%Is+;8kKDiGbR=w%Jx>vz4dDm4Xy>Q;Zn7cSdTOlV zx@anJov5W&Du%%8lr8G1d5Y1|j)23mPhh#KL?G8r5j>*KoD3l#1u%j1l1C{te*-bP zn?y8D1dddf7JKLAX(_&lIJ@h*Ew)uFiL+SU>NyZwZU^fWy6n1 ziZk+Q{zPlqw#2PKXtfJr4l1h1MXT*2b5N<(7vSMDF1*Zhb+!fBBAB)X?_%$BXq`Pv ziGCYZj6B;gKTfSEsCpIIih2iFA+=}04=2GlDNzR~rIi$8FwM;gtt&#Oh(kI^X%gOO zr>GEI8I#~xc8XfA3{;G)G~|+6kt^y+7pv@0%hcHUH>FnORSn~JsCH^aj;Zpb)27PL zPpxnY!A)&U+VDtYBI*w^qg17)b-}ANO2mE@Rq0r<&qh?^Pz*~aNRLx1CZ{?{?vxj) z0oAyurRK?ImiIfS)uW#Aq%(=pOpme@%6jaiQcTRK$d{>3#CA5(B($`NevwUd)k|C_ zu*}My8TO8+(|ri0%D!|Bm0yFo@?q6`CNOSbUzX9|U7~OJ_kJHF%y>Grp-3&X3MM^} zCxZDKy#=y5BZrm9f1uj9n6LvP%*BMfO@l}3pt^h6bdZQeEm?jTN z5n>JAn%~S-dn;6TkFuv-?S(_7T-kF_?Zt0E~SeqZw+W&A$G?-TBx%G4OrwWm~k+)m1xTNumt!=y^Xun&@I?A8u}(wu1txs~=nFFGy}i_|kOe5gjo8PPlvyzt-zuARs(*KG;t-xH z94Jo^?8;6&ilDsKYT3or^of7B#yuF06&a8ojq|g=f^q&dV-W^LT3L3Cb|}D1 zmpJ%=V;uxdXGkl{jSWH+3`P_|)nXI}NuaN!N3MJn$OrmGN-#5B9?|#fPd3Il7IQzs zd23o(>q8{rD-xws#&riM$d>O*ElK%d2o? zu-{C+&SrA@At*p>fE;kZ^dsf){g04C@rTM`B;-(O>^W+dfeOD0Qz2A*k`DNgI4X>P zF)ywi3bVew&!(h<2#%Q%dwkgo7FEKA_1%{VpUGb9F<0 zJnldv6k+P*)o31m*(Rl&H{QA!eLo|5q2JU!V}SBDzutHoUf=1*zT1yIV_~zZ{=~1h z-X`P#dEXC^xKC}&r9AR@KqH+AHAxdhw6U&V~sRlw-7;io&<9V|& zd7yZ!5ib|<>ar1TW>rrTT%K2+Y9OQ*?5Q*!&4^cE#VeqAtXE)hNX*qr3a3Qoar8n& zr!XyOR2uad1QENGZIKndh@#ugY!SUlMrW;BJ{i#|jHCNy^jMTes6>U`0mT{tvFI%z z0=w`7~K#%nxQAZI~jV8BR_RnBcSD#TEdnqtX zOJW;s)pm@;b0(b?#Tb$`o&wH4Ni2sP5{DaeMksq)s_Xtp7;nD7f)tDkO`fyfM*WEf;#jYv z5g@jJ=uu`!Lj|PtTkT?&T`Yr3++O^)5*dx57`FdiCcJw^aKF0Bu8z@GIfOeKug9Vs z7PnMs`huEEa9d)<4%Udk7ImpzEl!seU4XJj*36okY_YqBmJ9{A zc9;t_SUt7OAsR^))D?Cm@}k2mK(HFC=;@?1G6g7(l@$7wO*OOzDfY_**;c6T5L~;I z)GC+=`_wrOC31T@!H@_HoLNQw zn0#ua>q29l?q_vXI%N)S@PF)-GkB)NaRtb z_t>X;P?INlNfMMAQ;yQma2tt0ojZtfn??DNY5FY6k4)2PQGR5a2cY0wA}*nNb!LfD zY+*&T7lJI7?+s*CluZ+9T_R9OE3zZV)us^%c|3798rEg0S3_HsHh1b=M=a_A29AxV z^t$7q)bF21$wY8trL2-V3KtE8r7B@Frg4V}xdsboRtoMuVIyI)Xc6ZAGLTN4<p4+eGawV? z5K%|iw5^hfmfJ68a0hc7g3nS zB&=v8Y}yK@#b(t4%fApLvQQH_iBah!C`2?6_F~Dqb7^e+1!@e~6D~XGbno0Nc(kDG znYLc`(?X;1#K?D=-*AfQ_L1kOPIstv1wd&H^s7WxBO$mIhp0~MftS?kbhHMFCd_s- zm1wwyQ5>^{5dpWbOiElwBPlhelr4-YsfA@yK4MWeGNo*_Oi8V_pVI$h&iNzK^M6&g z7f$PHZr7aFTziTIf}NMeQZkzkVUx2p`z!aMFG?+&EJt0&)z8Xl(6f~T@t-pBnr9$> zh{PvIr3VGQae$LbjJP=Hpc&Kxi@ARegAf``m3dY+Oz zlo3G#83~jkli*pC;AI#jTF;Y0E0iN+>1NoA=O|vPfro`u6sMdz7&fygt3ZHo>J+)CR(SW5 zvM@trICaMZ!kf(S>ONFds)2^71H!kP;iD0bu|JJG284&q@SowFsV~()gPZ~33(fE^ zBD^xyKm)9D+Fw~_;+vrC;G2eRKEf9Pj|4E~!opqRc7&>D5x&a`cMb^8w!&$c$?EOLFaGulbc=zaS^jYSwyg$G>8{t$V?ds1Uy zGNC54uz@?HY}(pf;hQXG(!_a!uLvHs^F!cND{fID`6v$OOSLQ=4{#g^_(GRCOwWY_ zY4e&AErf}Eloh+HQ`f+`F&r)rYz+iz@ep46OfAng(Tj(OTGDCwxl0Q%9-mNJFkv+O zht21Pg16#!{|aPWMQdqdAL%eHX62gB*<3hhbER_@TNMwK!(+}VVTUlKG#Y7ClrOd| zw!@KwnB=XcBuo*cx#bsLts^%sU%&!6^9hx}9aiqLFv|{&LlFxy&W{<*XKSauc5c zuiCy4w+q~C+21Zm@jb>(`w=WCxV$Qxf(I!7D>c{`!AgJA`j+c(_D_9X++iR^tnI*u zt7e&dJFysUHH};gswc}%Ohb?*jLUEr6tRwdyB#Xl zsObpQHkc5#O{}$x636&HYN+kX9mjwaLqvrgn-A3U6TI0_$l?R43tP4iE)RrzhAdia z({i2zm90{JfBZ|8KBMz#R71e2zSDdXM>5(8i)HXEk6nFxf;(F_!)V9aPln%e+z|dF zw!y+Mfr}AprF~seMNz!%@DgZ&ZjVpPe!0BTccW9E=dz(V zl{VCJv#G9DCHk)@Ubts85){EEiU~)duL9>zjPO3>XSci0%1ix6)&v2>D$(FVy6Z#3;j59^|sq}oM^Z=zWs%wxRKOk!vPw)nj2jr&JK zr)D^c`_z`ed#Wog0}=^@LuUmK z$E32ie*q@V* ze;dVzuDY?uTy>pN-Q7wggbKlE1kT*??>E0cr1&M}j>myg&q2ckl+%5@`P>jugk>Ex z3U_?@&CMr=sPB6!#=qpNG}fU6Xba7+4pGlz_oM4n7FL!cy0O#YV6Zk!UMp@&#>8dBVe1zasadKfT<4v)DyQ8F7^sS;gJ#SX%I?W;uX zbQ%q^WnkH2Xppo|^Y&I&7~eoW&quMu68lXkm5)|216aPf6V$|=TpWYsk(oC6IxKyA zI|&avu+*+iy93OqW7M^d#HUzupl7sZr9PRdXG1*3{6~>o@D$QfU7bQn{4=Qg>ko_e zbL^J6*@i3VAQZU9RByNccFdeF6Xktk)dl3U%1&N8)S1r?hQ$;$a9ms3rv~Hd3zorv zwHSxBxl7p#jB?0ixQ`1&xK5p8w`xU<9gj6VH0u~_55(plcBmUNL`#fzm?Bl8TM%Hi z>rQUh?w*Qr)qT+T-D6a^9yC!Lez;t?yG0fmaJ1DCG6KwWWoo%>(+7<;L_V4tbg&2J zOl?P7>2K54Y9j6Vq9(i+QtpJYhlpt%jG7y-Cw@^XRx%DEYRxByRv7Q>qSj0sGQ?QE zijJFd9x4O7y?`x#UqyAjsFovx8UuNXc4fJ%$GF&Eu8WL8R#aP>r+VlK`xuo6`|{&|lN3T_xj zz@zZeUWTl9{C1(JqlBv$Y67)J@35N0Uuir{L}2d{dJWC!Me3Gb_e#CS);%e7((6aq zf;*Fkg%^wb)GjNG;KL-|USc2p>gdGx5JAd^3{fDvm}T)9t;}Kd-Rkr{Sn*!9{DO9a z12)IyphLN499pHM^%S?mKUO^p?H|ScJv)rT&5k*N9(lNl>i{`aqKy~#`CxhcSE_5jHtIXr|#o@j10Ua9VXcuwT;52Yor>IeaR{v)NPKPAq7DNqwI9Q#eOXAq#n; zxgiC0+*I_@y@6NNK=!Ss^)+>X#w*?&vU@?a*E8T9#~;S|KWn9Rx$vHmV*<1YT3?u> zjtjgFVGT$J?Y%O37{-T|AK;GlUrzCdt6AY@`z(xM6pK1Nj$3}k#~H_YKs9(Ax1gRi zJ3WrWR6mG39mVg%&ig-Q%A5uoQs!+Ah`spzfRQP8>Ny<6?JV{j4dNQE&bXj<7Po5^ z_P{$-qde||FsN8)BdDH1WooDMIcP`U_E@dw7h~+U^}%d%+WCh|{=z{=R^W^fPN{`j zxwE3&_?@)m$>VbUoA%CHN!*4cL@km?gBKJp>-Y``n;KCG&kN0@r2fu+t9DfoK1+kfWTNR5Ep{0x!ECR zW~+fCu*wg($)RQk!)~eGiD$7ow@P1LyXRRNzRt zF_FhI&g3byLG%cW%QbONW#DLhf?7-7%e~B5Sn=4*+2GCwWa4I0K^jP&V0@W{F9P1I z;{o#c_2~b$^2jrrTc$i5CN5JRXZB{w<1{*&OUdJT#($(deu|5EKaPI1La+n$<31oh zu6}%HuzpN~17?82jN?xK%YWdKS)Fr+4%o~x$1`v}sBzMZ`V3s$#BFAsIM6UaHghdq zd6e;K*%V~z%KDz!Sl@#C3d`;1dB9*brSD_C7Mq$Q-@qELh;m?A9wv!6X7f3q)}MP9 z233iClHcFq_mTX5mf!#4AeuA${u;l(&F^$S(fV_L;`dH00h&p##Puag^ml~t6k?K5 z*92~q$X$fscd$|yjR6^c|8nKd$50(&Oa1Y!I3{&8bu!dQA-1;Yd-Mpb+BmMdj$SwN zZ{#qxV#^XNnT@Wz@B-8ft@^#{PRR0|KfHJ7hDw?)!T>#g<>(rfARN#VjF?S%MI-O^I&AulSnUKp3r& zenkT(GaLtnPuqv?qIAkDwNkrQ=lC-mIu*v0-+>6;1%@#L!X&h@4-x&?WarRk<*+;T z??99|3ohYd=Cs3pl+B|x&79crWodb#*8?%Q&^9NODstODz_q@-NYe;gp04#|JY7yYMP>_>QaR~$V;%iQ4*SPT^$M+V$ zU-1P}r*hy$A+so0B)+ytZ6HXhYiKpHcq~c?CE`LB<;m>>HJpMn(rh==j73jz zlHmJlYMcbgb`e_XwfV0=nNW4mAubsc&6RE!;}gLDa-hzj6|FhH}=SzYz6>u*`|SP{y)T@f6DLDp7GRjayQ- z{w=gCr&9eeA@{MJSH#^BGTM)a@H?KiN^04MHTwZAy9K{$bMvc8Ry%m)(WbTEl?~F9S~feitc*J8uTVKyXT&NGlEA=W^DJ+`NW36c2a`n^HR$_l$5ap9ACz9k09=(CUayUdv;Gb^ZOOVO>Wj|kAcDpS9=qw z_rM0HCrZl_6-ZXAe}g3O8l{IdmU7Prja{fMZPu6iwxnd{?S)yd9sp*Uf%uwZwUAPXor}ar_{Ng4xhVx#VoN! z`<>7_@gi7-A{UQ7~>x( zNb0J!$E~r?B}YBY!Tlj*V{X&MJ&M<0 z78t#8Y_<2TQ1C4q-^FE82H&bQDPJebMeu;ZOpjS4M&ly6o<-qck1cUEn6tRJGp~WmNgBtGxsLNU zC9IT>TPdHGl8d7)gA4fA-ErZHC%&4IZrn=uwAl-xYH$u%QXkP>M-so59Xb^+cqE;& z**Ac?Ye9S96Jjg|wrcR8>TU0GwI`PK$H7hmlk?M1aHx0Uvj|N4T4xVz4}N^wC3?0C zC#9nJ2rQaJ0W}F+&qOW*;eNu4Lfy>fvM$ z%;kPlMy@1qo|N|?Y8J2I-E0^0KB8Sr9(?uUE5W^dx7l9G4ohVLyE;61kCjVn@;;=E zyYfOG#NV4r;^n zc6r+aBf37Dmc#y!O5@poEXcZkxwaNp(d z26u%^9z=5CGW=pi0mmg*d{IQg5o$p3RJXhg6Sft`xC`ee<+X9RvlhPNlz(E^Rq*y= z_I?%I_;}~*t`w|DcH!nlTrUeJC*32KdC2k?@7&?4T$#Czs2akeDhQ#vboND{nKTJ}omtXE2BLk9YR1ZlJkP#&98R<1ne zn+2&U@ zhXLZxk+^`$mvQvcGQD)RUg}A#NoU?wTGmzS=_;MicfeR{NI6yy|BLfOaY~EU0&$EV z2@SpB%*G)QVs(~WJTqD_IDr+KbQq&AT5B6_-m8Jt-VXmrNIEtId8Ob3B@?E0_WP5` z*O<=dTI8eEj{F%aH|T5|fy1ZS6+Yt`jB#j?*2KPYB|;lWp-)<^0z!oUDjkji2!?`p zo8cm#hDbgmnhu9Gw)wH&!O=DXTeNZz9XlNsrGxDhjEx>h`bwGftaKQ;QvBCanD{Kh zknBIC!{A}E`9Dix`@SU8yaHj94l~nAUCXTS$r1epx5iQHdp02+l-iQ=G<;$-oEiZ^ zuee-n*|*>973l5{hY0@wa!(bduLrSVIzZQh$PHjvrr~X{ZfB_27PyQf>;!%CIU%UR zM5*08aHP6-4=p*faZI%nTRyx^6h^7N+C-NU*2Ixba@|@~Om9P-;F$vQ4;}u&wxUQ8pQM|EMUNvOa-wI#u_sl?SZ5 zqR{k34NYVw)P(T+Vbd7*u3#-GUilf}-X&bSu%}^sv+CX^T)XkAdUwWLJCFpnu5DFa zHL)luHNnF5kZ_7SLiFn1D&}Q5Cd|vSWAhp&OsZ@9rRPlU9ZLA~NIr<-h!l4wZoC50tj0>)POOO@!g(7ksd={y#3icK@# zO%zZ=qQ7G396KrqkzAX~Q$@xG?2ckh@hd6UjxcAHm-sp&&h>wRQXD0MTZi(5Ppq(K z@u3l!FwV3k=27jUs8hsaRMf1%7UH+up2b;Pbaw7nP@!m>SQ#cQQKCS`adONr~HCw<4W~8SaRAt70ktQ>(EMU zgUPL|2)E^Fu2!GNcnTZ9U|Yk@v&l>7&Q&5EM30*E=1!QEhn*dmqD31Bhg~H5*sLr+ z125BP(q30?Y6;ebbBw+RF$3BNDjXuie&s-QYI%NzF#}l0j0YOn$%kz_P9mQ0ucj!~ znEw-);0Rk~$_ctilMWat}8xf3PK~Yu0F^mF3qL!BD zdc!juS=ubzE)k*CIf7_;PCm2M^Fr_dz9o-ie#A1JwMaMMYC|p9jybon5EfK;BW*JZ zanr^W$R3Z0^1;h?u^E#IQoYr%`9Y_gMN-RzbZ?-xnF@rAXKRp%fMrODVli_b)hXFc zB${=})cmu=-fl{DHSUP78jy%nH3av2uoEgLwe$xS z#=iSyH9SSN=&Htvab%rJ*0cRNg4e_>Og(EtYp;O1y@=Pg(krqcd8(_cV4SH6p9Go- zBD*DlE!jo!hr{=f@;Gly)B!CKw&Z`L#|r5_WB3{BGbX|AX7(9(LkL`U-0)BKyja@v z)fPISJb{%4Iilw7h^WNZrDdOIQ9Xg9bT&U74A*L1GKDGWu*)dyNsf1ejF*=V%cihj za6Gq+NA{W-dIHBqZT<}$uR_K45yf5rYOD&HACOEEFFFYho3>K=J?-}IaZ{@Kf&R&U)56yACSZN z66#!SNwfg-gcE`2N)rtP;6g52@@+YGSl`nF2z{G2^F6D3TYxWOVwEV|H%jG`HW-U3 zcRq(&5L?2>&AtxXLHHz?Pafkek3|=Pb0mfP0&h3p3>UNhE_eeHx#?f=_Qg$b7LVJ!IOqm~TenuKu)J1ry41LFUP^WhLsY z>yy8r-Po%!nh0Ho>RO7IaO!gFSQYU)FP-ufywR}4KN{nKRJO7O=Vb{eH0F4EUf38G z?sF)2<{=eG!hsGo3+quL%He#DLz`DtriFiqszHnV1Uh=9yu#x%E(a;(Q0D&}s!oJ^ zPzmZ;3=!A>q$U|%xb)LBkNlI_{_P zUI_?y96{x2h?^J%5RH|pyFfWnK)5fY zY^L*0;l6dsT@8enwuxFww*NDjbt=(E{!A-vL@wo9?OT|*pKu!Cs%Onh+yw}>CY(}C zLo_o_+0u-bjW&;VcIOI&i{0Ug)V5EgPRl&1XU$IdD1fC|T{b&WMi95K>bY|h*Am3d zs(Ow$!Dl=rZ>#g>hEqe8JLwahWQcO{46Vl2lo4VExxYWnuHA<>B05JPl_##F)W@lHx%8{$;g`l493=0bNbwyNDZb94vMu^Girt@xK{vHv zp(#vP)chWW5_|v-Bi_vq0@|n%7ol_0sx<{K)$K~;H5k#*xu5t)htA#X9~nAVs6+#x zoHk8~&{yH6{X~iUo}M@3Ium*pDv=d>BbS04o`_vg36N(^zdJaF71;uRL*;2 z_O;5B&BeWbd!!?f+{hVU3tV(Gve5#2D|~X1q(Xyx(x^elkK09X>%QQ#eLna}jmuO} zx^N9ZyBaM*`sghNtpg~V@jZIf4+#^C1=$to<&DS&CQWxy^76*Nhph9(*ye8gP~Kml z@-bD-8~0UUe5kprJ>_k#Z8nupFRFZO)A%x^y3xA{V^ra;jvU4ut=hXyiS9#EB03Ry znik6m4-coGPF-7KR~zz)Vu?N6hV9SvaL9+gG_5uO~}(RYdR9YS6( z7K?Lz#-_U|Lr#>nK84B1vOJ*?BfQp@FS63x9>8;|p%5YAHaiaB6;MVuqelf^J?9y! zk;J5aX|)k3q_!%nqO!kkjUS;xzz^EaC(_~_nH7_omnCpWq3q0)lm-@RmRyLQT{|w+ z$Vw@_98u~464$+lMBr<0pxP@pCa{t^lP_lA#z|a)6rXHRKlNXjTW8|4Fq&q@)nJlTUlc?*sUt-%^yOVgoI`y^07Vs$Ba`H6$DpG+w zd5#9hGuT)duWdr3Y~gQIk}mQ}RdDBCO2JyDlIu~QBBAjDREcChX`oDMTk=($X$Ie zuZadu%ZK$a|Kr3bHg>pwQ!YOQHYY#%D_X~r8=bn*1TD)*cduIhdo}t4V&_tOdYTn& zGbqC;Typ5ADDuLI>G{}#opymJk+Bry)EJ|(M?j4(p)_U6PSW;Ax1fdK2rA)er;j)8 zsZi_ufQ)b52~zCnchgx19K(Q1w^Cqo=-R6`!=+4^ol4|S&@ZdB`C>XeQ7UKXAE6FO z#QOtF3$RTx5(7etLuQ%kOtcd!mF1s0Gw_gDP1~Y_I|JCXycg$N;8Za&e&`*VBs2CX zS~41!s>T5{rA4Xa$v-7~h$gLB*tgkE>@!p{A_?26rO!#TpnBoBS;+ zD#xXol8Q&vl;5&ERiirL5m}gac7#EmxWa*{B)2`S*0CKkFd=e4g)#U!5G4#WEmJ_H z6G;Z-dnbmM7bX6J_-5D~s9l@uL7V>?QoRR5!3QnXdr*n~8>J!DlhjX%tm8Bsv{%aY zVB(JcELh`OERB1xU*rCekq=fb;WhJ@EE2_w)ZmUuO<23!A+y7(#E!sK1M>PrMqWD- zV*xEvvl4&7xWlS<(()&)Ja_cx`D-&BYEm)Rc4(T-KUIuTz1!iV4sMq@!W}m#!(Sk2 zN{tG)J@G3*$WI%TU!$2{aC>FCRsCC=>wy8ycqz&90m-Ja$2UuP_&o0WdqA^a3#bfN z-4B7Aj;~`;_Eg?b+_@HTv}xrv@-q~}_Rq$Zp| z$Y}U?S|WKMEs_Mavo_cL1Grp3T;6YT`K09XN$>r{B^DnBaQS4KOK^3+60JeD1Grk0 z!PWhV?@@3DN3_$7P0{^nj*@p$znxK0eiquc!9v^ipB5Ur`nNGy8NeQIz%;9NTjBtM zKTv4f(k!yjGB||#-V04yxJXP|qz3LaIep4Eo2vII@4dw7Q-cKeROKwQdOM)v_bSmT z)Mhg4b0V0r>hs>jKN9B|lEZFlDY<*oY$Z1gsY>}Dg=-63l1H-(aNRyGn5A)CZw(Fu6u10%7*-yz`A8yX&Mt0QJ`@;P?wZ8( z!7a4a9MzF^t4YKF4O}eeax=rppUOfg53lrO1#6Ob4k-H+aAK9croZf;BL-!C&dHZ4 zNAaD^P5w3b;?sgnvfOYaRHCSH*Cu^NnRLx??cy6&oBVU}^`Ryr<<_B>%mx8I$3!wH z0vZLwn#3lxIC1_gvXVoOa_*H9KoCpVyX@MO=mCU<)EDrT%iRMwC+S(7V-bW_%EX*} z-f3f2%d9l#T?;}=`uK^m| zW4*?@(Q8cNn!#oGLPi-vi9%V14wT^!rbf~BawW3NECXuM9YPso0nL(l5vbKKycd4P zsy|_UP}@h_wkkED{)`6lGlJ;R=#ET$^9N^;mgZSb(kWe71APB-TnfFVz6r6(71%cY zt64Sc->0#nzfkV|URz*|5yhoOhiySSMWPQ4wN1ZaUEB1sP}}rbS#8t5m1>(l+m?J3 zSiF_llE$Lg^jWEO_${-A@H;!p);4_(!sgnNn>Z}RVYcK+1fo#uh!Qj3*mMuZmLQ%7 zVy`W63&JD?9zZ?v_`}J;}Dc+uM`TC*D2y>N<70M=hV1 zhS3<9XnGl9cHKC?ZTdoF@f};@9EM7l@c$nt|Nny!EBpVkPEBjZcSoRLyk<;pez+s> z3x(5acYqM#OVi=x;#VRE%y98rsvnmXfj>yUHzlFj?lZ^LTI*gp?{t}MYD&xh{VdQQ1<92_Q5`~bxoFH6YTzQ+58nD3+@0R`iX+t8kjU5 zMM&`q#2e8ckM?MQ+Lr9ZS@K$@s07996hWqZlqvGEV2b*4W}m$br~9PaO7d*U%^C53 zMe)~7#*%G>eD>I+0skDGX<$`4BvonQdQ&|EBim+vHY<^9hS$C*#Ze-|X@`dr9g09u z*%I$y2sLQVj|22)paPigcOmfN_UeoCGLV>sMe$xy&+ER}PBOe2K9OEt^vyPYyxd}D z0v4-but!20<#*L^Q3lqqN1{GrHb@Q?(`!w`p*rZ*XXR0v@^Wc*MapAm8-blIU}aWbvP{5YftcHX}UiH)17ypG~Mc1tF5S=H}MW5%j=2x(tNh%%36=u7=l`f zJ7_}$-&l=f+FEv#mV=$#o%p2>Gb&lwJSS??btzO4(I3h1GrL(2$MTE0K zMOVA5b-;sc5_!z$Jo7nUE~?A!8|&(tuj(Tf)@coW&g?;-3@oi87AuY6tDq%3kkK}W z&}X%kV2QnC3I)bWCdx;VeDD(cz$?yU8z>I_(|)=gZ>mP#25itWo`jN`i|usNf4>Kz zjhx#a2aOT-;nms_j@8igP8w{zz6u*=L>)V0M%^Y> zpHuba#7cA9k$IrcExZp^ zRM9MU@j4-WKU2iamEg8TsU8FNiVlzO^cYKj3~uDrqGQCYmD(yCo5y)Nb@fW6x{Epi z>_c(y7QtQN^Vn$;Sfz_<<0J;|m#$225hDS9=32s`e@VvXYQwvrj3a*A7*L>13@&NWGgwKI4 z#N_N`k}K*ng-8ex1=6e)5UKIO9w08Y60@?#t5V-@sIltZEu2@w1hN!3??8;;++ zDy#EQpOzCkbW-&d%6-J@Pf6gSmcAFS`XKadalR1Qe~ zhkX1>KH*jw7p`9!{LtvCp7>m5vCr zBa`MwS}<;0OU<&>p*GSw$5Z%YwsCO$JpAT-lDrc8(6ExwkGNWlrGw<}gJ2mgD_}bn zyr$%|H1@AXd`!+7D7A8<3!@Q8A$cML*J0w=muJ#7n7BGEheoD!w??H=0u~XOuRgK% zd{DzT@JIc^k2?Rm_X}@f0{6G*7k&+!{&D&R^as`fSo3TX&J+2J5#OidR#wlD*)jZ| z=ofDMAqw;V`-T7CFKqa~xnBsw%u>G~pzZ&Q{X!L*@87;(_&hbszgoYr1ASCRAMi}z z;(p-~6PMX9+;8Fr^b3WssssB4+^qt4g4Hin9vF(-ym_#oL}_oCc#QgcOi80OA`y>K zS5MGa8KPdEpy3QrFHg|R=wr0ILWILtgYKjk`CTB{=T5>fV*EQF(cAhz(chiHAB654 zY@@H#R?PMpEmVt@bp0Y7stm;UQrBxORlDU~Edy|079$27d0m_FjXnpCz5a-VjNUc@ zNdsJHf-wn}o8S)9-!TfGK0=7Vj)$vL%N?omi6m49xcE>4`o7eM67VLzS{@Z&It#iZ z02x=xRPce?71)hRdDBL7jBBLWu^OKt_{{MRE?9GnZ-MM_P1}bLc4*8`@}4`p+^AU0 znP|AbuoA1Zor89%tgX0&$p8Lgk;_d4FH&7%m=oy4`BWts zt~NnauUDDie?Pr`@SkM`|4sFJ^}lc?e;vL43)Q8m*Pp{66ZP7!*G?0W*6Wm1;N&2^ zuEtE@L-hLFIMhz=F>KVvXf)h1+p^mawhpyb7_0vY`m+F6=aOH~qNQW-=BR%asA!Y; zqiD}*I{vm`dcVF8Bp09YdR4NOKI1hBCLLu>pYdu=hm(^^iHtGBMO?Zs|1}*Bmj=S$ zX5)hRKf{p_`1{wV!|7TxC1UOh)5HlG|2ye$2Zz(bDChr%bbn4yhs*VZyUlR%M;ZTf z>2N+WKxfRf+CCX~SUQZ44BUvY%=2fb(bu3xP;~OTnP<%C{27)Z4y42Q{28AytF>?C zBK-kj1J0NY?|1uKHfntjIjnK-yH!E)7V__3MrX{H!m+>PKIx~#Ew0#Fj!zdkL)YRC z7Mj0W`)jeGyq@|Ce7kuQJmLLk&NQF>0}hE@e=C;=M#pDNfrD``D$ACP@xC!W$Cmu9 zbhO@!C7aMUZ2o)b;Mk+`5Zeaxcv1wDRZ@4{hFU@26;tgt(Wm}1CGMW z?J*o&KvZ&rrTts(8j7-&Tw-uSZyI@y$*W}!5hjNVEKMGakY{U?df>8g@M$H;ozErg z5kZ5?wjbZYqgXipt_Iu9Blh^nG~vt(Q)8}!l8w#`&JPkBM@-J!*S`Sr6tmJQS!t3{ zTKidXH&K*!lk@#1=X)jjZYB@zRW_GHY-wlSZe{ayz&JycD3-NL7mPe}8&*Z=Y!PaE z@zCU3^ca$SgH=R{{1^dJFO|r@kb5Q=s+4=Sa7T-iRH4EcimN@Tm!r+Q7l@v>y1@av z`7MH6AvjkyzlK-Um#dcMCH{%h!5%O=H3?fnG^~g?8bKkvpk1!<9=HlkP$syc`T_Kv zRwh5AC>)Lis#Sv6!;E~Ye*%acx1~9W^W;N9K6LI*iToQNt0ebR2!FQBgGFK5|4wJP zjB8~cSakX-QqkF88|RyKU9J3*KnGEso= z3JQ-SIC+A;#Tf3RSA3_}ti6UmBQsOBbXkwaJ9g6xfR#pBny+snHNoF-Bfh>0NG&Z) zJcdZwb71-4Fp@(?`R{s zr{($h7#>o^7xM6H+zA7PFSly$<1jDr3e9^2SGM4*g9bkNYTS!Kf*wBe0DfJ^X$u6r z;@AbDL=TnNZ2E%ZP}LOYlWL$OQw@|PT@zj3hd4BjbljNU-4VVXeq^n-48OXoTR#v# z^a}ls;xvcpu2cBlukPy6pVhsc`g2;KQ}-U!4{Gj%y0=~PV#|36W%^wF2=ByDUr?f7 zVubo~{KZ$gySiw5hFyJ6J*$t<8?QjI7YU6X4cUuS&50NN_w@Tpql4cmNPiZe!NOBL zr_~c*ls0xtjBb84_iQV+g0$)#TCi33Hi3^olkVNGdH3UJ=r_Pehs8%jFUqV$eK87whRzPuukEB?+jZ|Y(ywhgHm7;FDv_eE57Mu3jQH#57wf&L zU!yGj+CuuZMfcW_e$`;>k>=f`MAl#t;UfLIO(Opm`c+MJTdjK|q+b!;8^V_*vF~H* zCG_j}68TrxFYd6w2CrV}yfY1=;Z0mR_cO9L!ue~-z+jDg_1cRy?qjsQOXwU;%RfNp zY!6DCHhJEELFag>6Kco%%=J3zo>1w$n_90!hl0~R^s7Y97Z1|HR~eD1g+tW${!2FQ zQaZ?IMj`7)S_#+d7D~Pv_*r)g^F_Z(#0iUL6)(fuMd>hCG@oBgY}g9YwCNkv(VaEDf`}!V;lL58R=;WmuVXP zLQnb02P-xHRU*H*21Uv2ja5ec&Gd9KaRNQ%Cw~AAeDT2`y>24HH2zg0C%#G|9@ING zOXOc)PYa1F=mS6b`+}sW1%$23XRhd1iR2LjgL~@~He3Mtx6so(lP`YqsX)@xT;?l> z`J!KZy;-s_SWhPr`hP)BWe+~`oXXp7V!TO{6gGATO~`E?8-`^xKD}t%Xnzn$=x*m6 zNKoEi#JYZj3qzK2x#w17(1PyvD<%gENP9P%n@!g+6I!suhrYv*@?I3v_^i`K?KYxKkF{M zPZ~_WO5_JugEx+yF{YX;kv!7vA60#9+oASbT1b!!u0L;$F!@{AkXmCO^4Iyx)g-ku z4D~W+^s7XEJtjSwqwKXpAV;joYEh=C`q7 zFzLh8<`-pQFpo1t$G@~X`c)!VN`CsMFE&PG8q8rh@QZt~MqFZq-ak|6@5P_(*R3Oz z-LqOFKkGUPf_3C)-9cu8esK-VKZ50F2U*8&NhGEcUB~)s@MGu}WL3xWr zcoIdevm-u|2HpGxaF(tS?zwl zK2W#x4wEnJ9K@|u%oS3>oa*hk!hG$QoHX*YZZAQwkNm9L&3w_X5;=}zxiHa#?c?Kw z{x8@^mKNqXg6HWY52<(Uh7QH<+=1T^*~dF~;?3jn;EmjKy^PyszI}krbUX-C0-L!F zI~Fr-rfD!U=GvFCn7gR#P+xx5Jwy=Hm!EYzSrYWCM1DIFMb7N+?`A}%`u=CfrBZhe znH41G-ikRls@p-FKy&z6w_Wnpz|XpE%oqJCk<$}cbIfMN%^Kf|k;p-s^KsgKzdoC6 zS#xozH(QAh^!NO%+d>ffdw$l{{7>fI2R_Q;S|87{5hJEhkXz*re{R_f}eaueFrwEnrrVX2Ztp0x!c0v9N$GD!sKWy|o3DKu`k-rAa`FiI-}k ziA786uAv%`@~@Wn_dI9b-E2YvwAcPVU-;ymednDybLPyMGiT1soDr<}bcOSXK;QBH zQXTnsjrTUK2IA-CHeM1&m+}q#EMYV(c<~8Gm7fv3`toxjqyG>5d|9jJXk#TUpiN8a z@dQ(Xi^YJ-m;T55Oq+KPO#;R#(s-th{OEai7V!Y@N*KM5Z{S@CqxT9{ ze8NxbKMRlawk-WXNB$#t_Z}NB38Q!O4ZJI1^e(}RPgl76p9HVIy!#tQe)v@ajk#FA1X~_y%5;Fq$WL@#zY$zESY%%d2x4{gLo$v&h-~ zc;X-AYzxET!v~VHS+<;AfCZ>j{%x;o+<;SXjbnF5key5=L{R z?tHq!b3TPirn0bKB2roSZ=72t^~?cug>2#i9+ohgr7^3KFq$ct@d+K~lO%s1d28y( zkDiA!hzEFB!e~0*z{3(o(*!F%UE$bp;g#Mz{F09RNANJ02#J@3QTn_h4@($5jyF@D zxZhf%(3gk*dc#M>!w12#1IXJPn_ru619mBT!QaBK-K-h-Rl?{IzJXsQjM68CDNk28 zixo=c*OS*X;vdMb^uk7dl`wipV^$+!v_mlC(-odZMEdgUXLaO9&#zpACSOPxJ;*ok ztAx=O!HQ2;cMOshs+e&cU`4 z6Y!~o(ajpK8VRG%2wr@;!pE*9iTlXa-|EPZo=-Ot5Admk(Wm(aK9w-KL9pTz>v=?= zFQ0x~NB$%DbiIw2gwb_;1D{G5T`hR=2^-8cf>&QYbu;=S;nNQAY15KJjIl} z0bEz#Ek_T1^5 z9S{k7p*H%oH`r=$(i(M_F0@X4;W9@`*=7Hs5RQ9qAI@eOJYG{$>K9Zveo75>v z!v3Y;a9axAi)BTwF|EoajZ+oQ-EBiaOj$ZT&)jGfYX^BKVRR(lAP*&sj*zCN8XHIZx1;6}7sx{iqr)|3H4;X11v5UemxqY-m4}z<$N_j`!2X?B zLrGb6>b<8annOGw4<(Fd^9}M)!f2LY#iuKLUzYGjZ+VE@pvf=;_NM`Pw*5l;oT8aF zUJ^z#_y(SpFq$rS@#zY0a0v>%`+1d)91yR8>1E?(vzf}f2Yck~sd%3?r^DdorblCV zc6WD!Q#ny;-`gHdBdRZ%H4;WYL>Hh4kT7}*Z>Buqdk^kc^a?5kIb`JjNCX%VH12!@ zkps)f#9ldBfxv6dcw<1i7flFuI>lbXf_b&3H5A=?d?-9J%%EjZWg@wbcH7pg(P|GG5FIuQV8_7 z@K`_cj5u+fQ}&KVpCKNQvl2!(YOHD`j6N+`@#zYOaIWK=9{Ha-azJ?&J^vVd+0p0I z(u!`^LQRjwJ-auImEGX3wkvSiFgB%fO*X_hbiGS z*$UAfEhiq}GYO*$G*&edM#}^%K4BY%Gq`j3?8`cGKt8(wy+r8iMScp{m#`Qq+umiV z-&paXNHH!nlDXy(H8iAz(FZi5ri9U1f+(M^@Q*G@B_Eh;nM9;A*9GSidcR$R<_0;|7jNZ#Ppd?}R9zlXn*j3W|;jQ25$N_lk|0Kii)|k{u7`=;c;4KNG9>I%G zSNL;8p)YR@)scS(Z`pc9awm|jD<)*vox}sYC1G@m#;Qib=pBL;pV&8rvv23{)(jmv zAa4ywuY|6cs`~fQ#pqWhF)M427TJhN7#+_yC>at)#|oN!y23xi5k4>jFtRnUr4o^< zft_c3yr2#?Mi*QsVRRJVpo2*m9Vuw==?cF`xBAn;Mrcgx zB#h?q4djt9I$ZGL6F%dJLXtf8`1mm$IRMZ9A9S!>;sG5@!f1}hsz$JkfH$vWTYoAwXw4!wVhY2&}e3KP;!Kv3QJ`nhRS;KqmQv=PiC z2zPJ-ht~pezvniBBXUl+KzL}PQ|koV?WY<5kbFoO2zYII&I|{ zrtRn-&wKC@@ET5E1fDCA2x@ljp(HkB@-2 z<-|qcxd@4n_D_Gl2t4bM2x;>r?FH~WeO%H$h+sf^PSR<9`~lOnpG%|EdOw6jDEqBr zOxsV{sqMZ6iIDa>NqYhQ{L@iM`*j2Z^5=M+=CN+3xd6PcArZ>{&HDqSO~vyENQAVP zN!kn4zx_Q)TZo{#v$KEx{J5k6#Lxc;Gbi?E{_jiI-=+5Z_+O3)+;1W1w+&M9E!1g$ z*fl`iQrqi0NCZs&@UDj2Z@;g{N2JM@G#8-j$+)Eb27-RuAQjKg>$E?N4N#|4Jm(@2 zaAB);Bt;Gff(zpN@*gDa7ZLQ^2C4XdOs9SD@Oki^ijRWt zL%+Xhe8(Xv@cr4_7lH45BtqIhymb-y)*unmUL|P=zFs5(zBQdpI{>~b@lojeRL4c*`%NST+~2-&5%~THiI8@vq`iP#cSksMdN!pk|M_=Z5M&>WF$h`n%9{20{BLd2xUr>Oz(=9)Yrnl{ ze4j#6!2KA43-ZGo2PN%P1Q*2j8lCo$|2+@BUVIdM{jXd!zBeE#@HJZpz#&zheFce- zc5e&Q_A~aS%7?W`L^?>?0r>ZiFH4$Y1mu}>bdywg*Xgvz0j7QP+_b59{u>gZ>|g)p zBH*q7wcSQzQl4s}Nj}4}QN-(v~2&ARl~Er>)$p>((#6 zGx1UIUDABf_|8C5;9J*p5%?-3LfX@f7lH3yBtqJJNjm@^Tq0?Z>R*0+(fFR+BXGZg z;DYr1f=*lWtBb(53Wpb}G!bhYjU>fbu6Moyc%0g$J|6LAeo~zO=`f|vq+MQtxQ!|Due{SJEqXiz_ z=cVI(KV4}=wjsUIjT_Snn*)DB0yQ}=zomh0Il}k?M{4?}WjJ+KlQWIL{+$4687|xl zKjnDBqv@S$at1w`9!o@gMmzs9P9kCEu_z@x+4h`~@#unWuF>-}8+6T^R#0hN@Z`3GaeKMhc}bEi9OWDh4IK5s`PojZNXj@Xc_ z&gM_)>fA?yx(~+hL3mC(zK%O<|6gv$e=6wayZ#Rv%$mgk8_P+o-pYM5zrOq>webtMk3;VJ3=nSV`uf+5o?po{QDa; z5x#QXHbu7ofBI&aEM~XqM%~Z4l5M)yj!3rYVmqRzO|$Ll^xLNJY-4y^aQ%8h*nVNY zGmUPE4!}N!YYsvSvT%9&C;3vGsfLd8=9JGE=gnO-O$D+I2-HAJWuth)#ATMjtZ~yb zj9^Ej`%oHu&gr{LaDBqnfMYmRu)}yHU3m`~CAi=tQw^i1{tC!$bD;ybrWm(T2I9hl z(IwW^=!M~WeeI6mfO|i_h-(wg1-a;Bu%9=_FEdWV^zC?=L6+lXGkqbPkqt5L zD*9{V9cwZi)d`mJdz8Dy+Ds_E*zc~wXjGgDMAgvvtzZTELb7Rrkp(wFcr%S|IMM!a z2Q1)eO|UWJ>CQq*>w}-G;C^BRr`St#w?x7{mg(JCDBkq-y^k()I;e$970jx~{~KuIBF4H0P@W;)nGAhtfuuJxi_GyR zDXTJXQDCci$0H|CJkn0;D;TKJ}&2k2@ z#!s+eH_*Xoa05s;4jw^UaFrzhQpGq5)NtRd3T!YYAw{h@BYBPLeE2(et=NGC@YtpV zK^0uDo@EOIQ?_>c3V<`GW;%;*!ht>>Vh0sG5*2T8nw-qaP~q z$fB>C#pMi%+GgLv&T>;}vZq|bQr%Ch&C(Z1jFH6l5frV0xkfOo0rh~e?_g8KtH<4W zOM1}lnLT{A!xE1#u^;7-X);q{9zzT|B5qAko0ntvkC{0Sbp&;c;%W=muSp%do=pG^ zt}6_#4$jszfMZj0e3Z0R#kjj`Ck_>-1%@c^Qk3o5HfE^D=yvUFfg>-w^iQKKL~Uz^ zgi)(kWTH3~z#YC>4sSIa%74RhFRuzNAGGLl7F@ipuy}R(Pb^LCK&Y^$9Gnt_|GTF( zQt?+{F-PAFw)JVL-fCP;8M2kcrd}uArRy;K=T*HssL;DQ_&8*vTDFH+xU0=EOUDJm zW)Y+W?RU%A8Q^?Hp{C*zP&r*AOCX-xh;qqVAGP~}@^t+ce(x6sV_ zFB_42QFNTAZIax8%X)%OtL?-#{w;jZp+n@gFEUZ zdJgiI#%^%|w3i)2O-zp;`;fj6#itH{ZipG#I@9kFU#;e*t5xfO%CbSuhmS8EY@7v7 zPR*gWv473L9Xv}_$#KKGF8-g$!Ao{)`}#4ysam<)`bKI`yWhUH7skucbAeaa?^9~A zz>a$X;|A{W-Kurc$|KxblaO&=ngbb!OL#E8fpIWY)!f7OGwhI`v&T&Ec`b1RW%OJ-(C1BJPYErF|r7W(_B^ak-Egu?J>Pu;cf5|G#q-T zGKu9tgBoslXli&T!*Pm1mgAH;eqvK(48akt;-!V+$Hk}{izvecM9XES5h+QOB3JwH zEcUQs3xkTV?9hU-aAo=xY#vZ`f{XCjKoA-uUqT*7V`L%%)NKNTqyUTDj^%yhj1tm2 z*N7Cm3GE2SbLzHIpM|-c)EDg=dW6Lu2Yo9ma*v`yuJ9qegety(UyJa|e2&A0f^$f) zmUs+OF9;hBQ{p#hX|@ag+)Dkpt$dwwH~WkT)ZmmG-J2qJ5I6jb?cgXci~ymGvd2xx zfRjd)0Uv>pw=pDeC=h2!#zc$;>-xwT*NUGaO{k7FPYYZds*_6NWS7JWA#md_MRyI^ zOp_It2Vb%gg^%;0tY7M3;tIR9EBV0~gekAmj5$BuruXKiI4?@gnYn-%8@S92~AE{4_ z5#q=PV}#4-E=`OP%pG%F2@raW$VrS5HEcE1(jji4Fj9QS5^z;@{4i+IWs`L=<&Rs! zVRW;FL{&pu-YyG=>#s$p8}99F_>95!AHu2RK0s!~P` zLB|~P=(rlG^6~(3X%<7>)8hBzHT1k($OFH@6x{Rj)EbfdW3JpKa=-iJ`vzzVxzE{B z{+V8K--u)|(j@Ts7UcJNN-b%}*c+e{2ok@SQ0t^={pnCZnj-fhF$%ZJK2BAi$9hFU zwc`2sY077R*LKKEJDVnsKmC#o$OQ;x-)FuLF*N8Ns}}P^JdTJG7Ef-D-D4O3?@T7_ zY7-f7p0VMy63%B+;P6BIT115Eq<@s%)Hmy9JL?)|I3fj1OIK~RmeIz^R3KA%TUfKNG*)HjE<|oz zyx3oL%C1fAuuz|*Cay>Y_7b2`*o@{290vRl^1j$nYAxc-4q7-`&{paXgCyXGNE1Rz za%oKJ_3m}hILtupF2Lc%3kzWPbFEl`WHxX4(!o$=--JxeQ0nlL5Enxz4aHNQkr0c} zamL|7EYZo36}L|!{a`&66cH}6bAEdK+h|JDBzJnCoaxScJy2%noxyLAe+EQN$rkqQ)st|kIX7>fyJz<>iSkLVT%glyfba~hQi9wSV=*@OjpI!MK3flqJ&+~U)va9; zGlvSmF6|YU98eN_#E#nv-ET8=dZUpSY6NR*?SdwL7^z=G!;in~mFlk7d;FH)38sT- zBu3m}fgXN8u2*tmfp=2l5g|JhvVn)op49uFuF+g@%k^C5;gp zi_$EA7Fv{}@E4f&YBe!SiRU^sFH;FvH6uIpyxdM=h(I^Y7EsoRur{uU0#ck}RxyN= z;_nj4g*k;M8zUHlth9IHL+)sZ3VFn2=1}lt`UB zPMW_WOG#*Wa&3UhWFxCe8JW^Ug}Zy8B$D6`YE6(SS!TMcu)6}|cK#_G8%Au zo@@C(;gp7w+BsUsiRxJ~Oi7Q;e^uu<=0FE$#jEQ0M4nf1U_psnt%7JSFxN00Yes?s zjy0o5hZOW$4=LXWAeadc&Ixh=HNk%~@o)I!p!}1CXN*&*rZj*tIgv0_C!{Rj$ybph64%(b>vl;6a+kH7ulBzHB6tRgRQ~ro!3u;Q9S};=6%trZ? zu{e|HPRc0|Qs$qkiVZRrXCtm)(g;J>LbuN1EGDd!H=CA{Q(o|zsuB71q znOQwQ1_Lj7-$=%aFshtH*_^?pEfzlExN#QtI_%bdRJy1}?^tzay zVr@!B(txh9j5jqZLEX{dG@0I5CJcSlcr=e#FC$}P6zVNu7dl^Mi)SW|i)={7sfnwvMd5A_kH#`LB)UC zt-R%4lmIho%@M>dD7Ja6T8!s1Jv#5*R+$qEO=b*cs|Z6HKC@R)$@(k}1zHGKlk1k5 zEM1Gmr7L(9sX4|rbalhfbu<vnky&lGhWhS9(^vuZJ;LfEhI7>4khZ*172n6G8lu1-zov}}f z8f_K6=BlcNuqpAGGWmgbeq{8=z5rnbeHlGe30SbI5j})Yy2I`S80tV|Ti1$v0YI7M z1TDN_yqtg1;A%lrWF#WVQ?BrJx|Ar@Nvq~KK$XTe38Q7&`o&su4H&y%Eg7fOnh%a1 zi^L^5xs6(r%!moIN$gbmSCL&#>_up7N_><;uT=GLal^~{NX3%+RE#8OsP23S)8uO48tKdiD>l0&}?5Sm~fH9t?uU}m4!N~wS`y4c|;(RJy4ZC8m()^9#C0{PiGY&sqGC5l$R>H z01;Rqk+{G^Tq7{sfCAWTTn&Ge4c~Na2<5bNf{b)_+cpa zU>2L~f_f9mirh=M-6Solu9&Pq`}#9Gi-fO@?Aw7QnURwEh}2KL7|7B;+{9Ot|m3*gxcA;rguFYk)! zxN$47h+QaAAN-ta`&Hj#bBL~Q!uFiGQ`cRuJj0H25cj^Iw9?r94su$iUVy4rb;Q#i z3nENmh}y0^=^CXmSpI(29J34tPb^=YWsv1KtATUX5%gRsD!r!XcA1o{6msR~*GRX}P8%7z+^7+zq@uuq}x4tTL?mS?V@xex}DN$>%({+WSMh79S(VSP2k=$flX1yRk9H#Z@-Cp6 zu+8A!CScTicydLaW*jyL1lAQo4ebCa%5Icgv?KQ(p=QYl#U$sBP=P|GKWAm#zDXPt z0V_7|EF=+oidN)Tf#Xqixk+3PYoEkyiZQh*sUEabg%PJy{YA^~_+-Fjzry;jP80tm zVr*-mnAgqe$E7CF%PP19@Sn~dvBQ5tZIYlj0CZQ4lup&IB=$a021bp>2~FXy7j+n~ z!FT)TPX4sN$04_S_GHj34ttcEmX|O|nP0{}oxO&)+ZFyeoC76H6l!6H3UnK|ZmuHB z^baz;G3D+y&N!>dl;*_081BOb?wFoX53YK5uz?%uf-z_CFnoo)cZ1_(E0l|FT>xc4`?sq8@1e~#MW8ktdSqxeoL=jphc{!t@xC&=G$2sg35sN}cP z4PxoYEW?fIFMm6+R-8Vu(7nfSZ*`e(pu>@GylqaAsOFu+uv>JGnTDjuHXo5;;PZrt8=hr@y858U77&#l^%tGq|lt+@6N6T2-;u8I%)uwq|=D*=5I zVCco7W}qITHdHYJL^%yNJScdgE|a)pKH}|GdjE*M%>{ckFwb96$F#-u*jsfMHYFWV zSyBq{v$iy&AZMV(X9W&fcn=(c`YFg1AHmiVH<1zCeJXHh5>mC{?+B8hD4?QC3zgrJ zkru#xjP+bC`2dc9R53_7)h4BUhOaEf2kOlU4$Ky1?ZGyJy7!>X!TYNC$hgJS0@P4f z_&;d!1ZyomNJ<3TJkH>LKQRs**68BKGvJY@@d!OX5BWfqAJJOq1@*CGq@&^88=T$_ z&YQbi&sdx5kpg>?%*>n63MJD@Nm$YsfUwiR@}N#aUbuP2xmE&V`5nlG4PHTfR13#M ztiVH+3&;K$W2Y;83T8&5NqP5}>7}43q=d6l)Qh=!7@$}q_Yv2oHQWKCM)`q-T9BuT z+ni!WLFwH}^aAH2S$@=TvS00BufwZ(=dHY9?}+8g1Chz6vJ9hwTa~O1z!r(!U*0{z zVFaqJhI%QoKj0^=Q77)C{kOfy*TG)sYkML9j1~Y3QPXpm~)4WQNe=> z{r{0Xr`|`h@I#cM+%d-~>Hp~8We@>Q!+VI}AIk$U-ct#Afqp(r)h-34D&Ij@|wn4yXf`K#iCP|Ff$u)}WzSDO`saVzE#qj((~(M@Iw)k-4{^bo3wwOfP`BC*MN(SZ*f1&(bAoh78{#)O z4z!*%CtnuhykdR=zE@GXvof#}FNun$!yv;_2sQ^af0BscK|5xbqTT}TsGbD(wd2*t7a)%wQk)h6}Wm1yEbt7o_ z{kMQd>0-#QG3X0L(_Yi0AHrkAzNJr3(IuATBsxe>hp}m&_~N&GQXdz(Yp`37c4~e$ zyQ1>vII&*+E~p7xsBB1b`jMUQInMduB;ERunKN?K=XXTb4s(T1Q>R&+l(n+;*;$cY)#QZQ5pv4A zIm1e}NpWa`9!o{$qA`c`;RCY&y?_kw^wH_LJAajOKiY4+toh zm+ld9qD#j^+u~#w!}=qVQr~r8%SBQ&awc_W9);1fbqyFh$?9^=bUUP z3yp)E-VheP%8;s-Thb<$p8N${)M&|X1{PRAn~?43u96nYFg@wGo7>}r;W`;ty2w!k zP2q^Xr@Cjb9)e4oIi?Fbx)u{r*+I~oSeTl4E?DDKexjt(3Jp~c+^Qr`^B?70BUU1E z$X+|iLADBnoKjt~8gwv z7@E}QQi?byeQ(TqWfNV5s+e$$<~YqYJ$(0S{sBXFj~m^_KJ*#%MDQRwq2@tP>lrjn z?a%+`e?H@YNr{F!4IzIYCVfV8k;gFaBb&%gYSj?EL}U`F z;c-QqZm?S|q2?a{4kmf1y`CG(X1<M<&d(@JslO2qeL)Ilefn!Zc*P?#5wp$xTiE5Tc^GA8Cg?3$32(m5%2 zG3hcZ2B9~=vY-|2;qjl@={a3U)x1&H!}yCO6mKw5!ur5!=y?fK940I+)gZxBL7<=* z{thQV^!ZHaOrk#zkG~4TC#H`aKH}@~8};pgB2Jlh1*`^QykU0_w9s}yBpk28Zs4oh zJ&4?X$Ot?`RFZ?lXuI~p^WJABD)-@14iA{AmKJ$R4EIKR@D!=4)fYmw2nQ5OwY?xo z2FD!2lJ6Vk`$pJqbCsCDI8K(|lJ0PYzk$|K?ma~?4iui!c9mcj4$-JP*UQ-1v!Q(ZP`Qkl#Dq}3r8dj!Z7vD&e zHsrD@LWSM{V1P|U>_`To8aU!qd;}mzL$-F~g!Xx%Zs^*0?o3o}M^?oovo`k}O6X-; zRM~Xa$=Dhj_51`x*K^e2aqfwLiEXkWCl}(spsiH}_Ds@eKjKgDv-^lojY`q1ECHC( zwpw=rTMj`@(7a+SfMr1^)W)?^ws25PYx)Szvqz-=qJeeW#z(VkvEq$I%RqI&$v#nL zsoa2%Hsc97cP~11FYVJ-TZ`@Dn0m7q6~RjJx-N9%=T5@T@0&F^6O5r~=Pxl=aTTC6 zHlg!uk8Sw@G91qMl_YJ;qrb>ApoVz|igbmC499o19=|bbpPzv}!1#&QH2qnn*riiq z$X&&;&;H@;`S$3v&%_3K0&Jf+rrmuQ4&5FtLc!X@I4tAb?i^lm1B#MV>QNdF$31!< zo@H0Ucx%W{tS7xGhID;YfJacUooJOHhc&=^z~Y63A%_7%JI5n8>@im{N{#`9cIo{{ zk;$}~%lQEAxrBYn*k?ZCa7E4_1G&DAYw@AlZxeuW1wIz4oupy?1wQRHc(wRNeDr9* zP?DXZB$sN%c^WoZWMhfO65?1;P2?&*v<;7r%mEOVA|KUlXmml?+Ex#U*2CFqdQQO# z?z1wQX<2V*J&ox|iM4GxqHKu%F{&a@ZD)_9Vxoy=5^GG@so^SVK5GkY?q-Dp9XQ81 zA!~}qZ_Q0$1-qG$08$-@VNBEr(NunQ0;8qGXxs9XXElC1r{|gzED!JmVpB`}*277d z!>jg;P*EbHhFIGUBeC-3LhZ!>q@@ApWS5ktWGR7am7@fAHPp^BDHpoH6c6@EIwuin zz46Iekwp~^3VNQ}Nd^JhdX*El`WkMBS}?(GRoFu>YPZtML08YlpIVr-u{KLKRda@u z4mMT|?_I+!ZVi9T@y(`*xG2{-StbFP`N*I!nGqf|IB)|6@)8t~jd7Sv<#O`Gsi{n> zKnsaMpl7o-mq<>#Nan<*Iwg>G89B~grD1&$5wt@}K4Dok40)JQH@{3BFlI^H6Noi8 zTfcx0bT-WWkilp3bfT$zITYDM*q)6`1X`^GWsOwGL~ZPAx@k+<{10d2iSLOCrFzt|Ivwg8eZ=AL6{&&Iws%yB)1QzMxke)qoW6;DjQo(mW&F<33cHPj#vVxnsnBC98 zH=SCabyGWJK})&@=PXUS;}~)rjvFGEutT*TG9ujjA$#h$myRzoPkIJFdhMk%WC6Zs zzm$@FRfV!U%7|=4@}@{Vp6CX!+M9S{4V)2rJ*sCh$`xJ*`#4sjg!>YUQL19(xEDG= zX+ySfxWbcZkJRX6!-CDJBb_1#EZMcCmnI!@>Z(f0&Mb_M2MBD~)>1-Nl;QzIRqIx_ zt%0uaZ?P~Z#E!g#U&~~}TX^qM(}}c@fjhZN4=u5kyGM1|o7oGwTM#R*mTT!^e$j1& z))AprAesrbtPOOuom&Paw>g%%r)L}8Y8#u$%)UYujdV(r7;+h|Ym?q`rLxJSuGKiF*w1X-!u zfN9UI6$M1XGW|CccK%}epv392EhJ>W8&oXeO4RLHsav8G8Vy`zXl^~Fq>Hu2bsf!e zhvl~$ECD)y9|URtB*|~4H6ckCq_hd^gPaGN zjpiL!eCVX-gAZB6=Dnu1HkKbvyqGNeBy3JflRdkOH9`sKpWu6IKlJJ{b)pq@tqzs3p={ z>lb8>Te2RAy22is+_Yx2h{tNX5S!deFzsIMDUY&OO`N3`9FJJ$v{|lj7!jd`_aQag z3uG#RuLghYx>jth(Ly1yt;r_Vgq+s5u>~l<1*1=%KX%uh0C)x6H4I5^oK%CA=Pqmo z)jP@k+}Lujy4sqT!A;Qm^u=xJIZ-_Kj4-EXHBP=S&GcoIl*YEbo}zY6=hpD)+!{U@ zf0MX1+}+&%wFjVIVu$282fBXB+9uW68Q3sEi1(#JJa@A>71;WBc2s}M?oNDFlghC? zKA}($FDsNfh&DHB7GU3CS7<>l>}E6kYD$iC3gnkHC)=8nPyu~;)qtIFn}UJP6Kla9 zIBtLWzV_*1M4pDY`j8tg`C|tJt0h|;eOM-COx5mLrLpf~I~6j?4jG_<{W(8_*1(v_ zNK&nC3oR-G7ajsyXj<&EUNsK08?(5%6myc}NCHR9c*Z_>O>)gnpY1STn2IERQ#Mok zVwVA4Vppbdk{HNIMhIWYcm|&ndQqN|lP+kb)_2Ivr%SMH-%j`FRPvGV#4T!ih8o?& z*TdAbyOJj)baKd(d2^J@nww$yM%fdqp*U=eQ$=aqA>7xa$SO9e^ij5jJrr2mg_D-B zr6K#Ed^#Vc>VlPY>^fsaR)IvwK(kgD!cRWJK%^JXXxyjeLu=nxb8P8mNh>AojBIcu z((1L48IUjb4A7cC#~0rTgB6g`n@LMzSE9$TS$t?l<3wmt5k%-uu$PSZMum57vhfw* zfa{!*o#cBiA0Q%??^E!dkyy&n_$H*c@V%ympe}qr0P5EEb)Zt*4eW@K){}L=v_-p9 zdSr>wph6-~IZtxV%{C{U@?4xq7n(^wO-OFY@N*;o7I7}QCuJAKKZnh*_JF6&g&T3~ z(pKdjJ%}cY7xY9-%Qjw%kKkTZTNG!j%^Vow*UJ7>&TQg?@sl<_-xzN18467=A!4g; zceqwJxVGUs`7uaoX5Kpbgkf@*9nu@eXiL-7bD86Bs(J@UPe!oGkLI5SVP{)Lvp(?H zqoB&h6YyD)Yt!x&WrYwudb=&w2OYbO=x`S2a~S$~pJ)VX8P%iw2Bm!kY-+&FdFfX$ z_%xhyDxKkuEPxUH5Nr;p}aq zSZ9>IzK3FR4Hc z<9Yzp@B;uyjg98Z2M1jC`~;Sccoyv3?7h931NMQxrzz0HT|eJJ9O8>KZ&%e{8b3^- zhVThm<245^%!{wXCSBOyP0rbLtaDk24L2I@N9eJ~74ZY_&_W8m|6t-4^*zz+Jz2Kq z`j+t;T=SgPd!Jk1hXaRbCbFPg7_wVggT=8-?U!OfO^S-$q=EK5@v)BpiJXA}XWUXMm#)?IaNRVu z@-2Zc!lE)R@P}b&mm&mpY=m^`Qc5O?rkprXLE4w*W^r6QRgx=n*oek*Y z-zl@D;qfLmpezJ*9U#l-VM1%bQ4&#I0oq&JIX}Z{59zCStIM_nIrpp=1voV3a@vJ! zBanvr&!*{08c&uD^ciXV#HIo%#MagIn1|J9$pLDzxhLt8koppgx;@E<8)xFHh_M#f zwWMOa7~DqGwS6R^+I#dl23W*A*0$A1hsgoON&F932cSVAdCbNY`4Gt3x{FxKVC2HN zKj#YJ-Jzj{JbZEGpTIX2(EB49_+=v?!v)rTl_wA5A?Dv&jezxj(<#j`D$Clk8sM=n zA2ta42aIwi*F@fbK;A3u3|qH9x>3HA7i!<>@V*s=hXR65@#Z4Id`L)5a$ zay;QrAaV_zGD-2Fg>24~80OToOru?hVWT%!#Lr+O#t|YCjp51d7!0``gT#@}8m{L$ z`A?W%Tbb;=Zh4^dC{-7A zZY=Rm7%F-)Uoaa9(kt73mRTdnZkIB-w?+;U!mwn6e@e-eG_;(6st!JGAl3Os12oEgS8dD`aC%vKvas1hgq*!~8``#RzDqnlRmqxu2Pkx2+)?`2BjZ0USa zL8edaKf>Hmu1LltRAvRKREdd7OkWnToJ$ymi&``&DO>N z?W4q5&AQ+q3={*WoYO6Bh2tgS=r|_3S@dZ@4NLY=$!WIy-S#l1=bq*0t!08vt&4{|rXJv2OWDEGdiHV49;`Z;28mS%2UmKg*^3Dlnj#gMgr-On&GUH2%m+pT=#0MD z!8&cddHs+?cw#?l&=K2oL}~084yMt*^L0evAT|tL{#oy3VhU<|5w>>~biD|3nYXz= zCrcIDW9N=W0D`xrlGyK>1Y}nX=iM5+-lhkrzTTb|?MG5=V(L0jo$$?6b!2=D=+i6H zvRpXs)XEpk#~G1Va6JGno&{oR3XXrfR{VvBBRrX~a;)ga&(N;%thp=vioD29fJXQG z(3hq%;pD7BcV?seJseewm0$0ioP*ck)oOBfp*ySm3g_fpgu%f`0N+2hHO#^DWK(ig zQBHot=o9dOPYk3zz*%ghC$`1R+M`a7aBy8a9dV5*%d!b!-5Qn8J`4wj-G5%nI zt@!;WG0mfKti~m>jMTV9R<0VC$h59;iGXQb@&I!;E|G&KjZ5SZNaGUOLEE@wj{c_C zFv4kA!@%($%w!6^nXVPrQ>DY{4OwR@3}j-}n=$@uC8uZ2F+&RjS+3NxuAjSmHAp4XFo~`i$ZhGZV-8mSG(S z-nE+a&j)5IyhZf^+JiHfa!x0U{K9CoM1@{O1&xBj&Wf zqJHHC<~%2>b|c|}_2d|-nR#_#aaM)Pxi$y52rPdR)~#gHwPW~U?N~g6Hz%1G+8wd^ zG*10FXXIeL1SQ}AU2)d9l_Qa|JagR2Q3zej-xqvXxg&VjYk|mQmJJaApD_-gHdXKO zC3v0g4zN!Hr*ao~e%um5b1i=&3FRk*(vv^m*yr@;z@mVD7R1?~tZ~~}Zu!upDZTK3 zYk5gB`#14X$n#kMAyqz|++lAVaJ)(^K5k2$%N;EcI`pA zkcsvQ!v4?gCe%&Ph08A!lKxUMk_hjBjRgcYx5a=tOBY`!Izwi84lB}wLbIUoZ^`^W zP2~T=0Qs+D{(g~2w}F)1F9>`lS#eOp!5&bK1CTLujE6)>a@KY!@V&IMQ9Ze&&22xa z=~o&D@*BwuF6l|BVMQzXu0g5u(-|IP8rhm zYEQmwAkx){J%9XOXl*BA*629z*z6I3G$Y4PaT!3D2RKwzx>o2Bz!5({e;ImIaKsyQ zLOoU_$|dFFU!hF!9&B8~Aws^~YHd&Bmme^XMq;QQYaG_IG$F;mgFKXNZX`=9D^7~* zFR3LVMA^cBH-*2us=%Rg(h78D;s3phk_I7Dt(+r)$xY_o2O zZP{_wf~MezFT~PG(`2l(!ENy?UCm9Cu_p-)@!z3ccLEIz=!4l)cTJX;a2Qc)JI4pO zAakp=L=|JHS~&(kaG`>0Q>)Qpc(WcqdDdujZodby3#KWNbMSgs*jzCdQ|uX|AocyR z|AL-LBBCsrUlyK7}B(Yl?n( z1yP}0|Egai@-j_c!fOEma;#vx(AEnl=b4WAxq2+rje^E9mXQ9$WU#}ZV@SJMo3jz; ziB;B~wT$t3u^n3lX&FmDr3N<^!GB`WO#H!zVo{lcBu!v_Bg-5N&-;NaHoX+B%SsmQ z@Mq;iT)|JfS9T^3HdYD?2wknsStz=zst0d(W`UsSn4g`Wz}|tbK2Uyky?7D32v9&~ zjY2;lvhvRZg&i|~hVu~N-U4qX2kk(n!#_fEtUvan=X$7;ryEqk*}=ia3HM;jeM0YH zzqD?OUq?`)SyxpKycn z-0}@D(8Y>2pSAC&syxyG)=x|+ZplhaDVCw14qh5vM1DxlEsoNOfSz0Ykw5j^;tl+? z=N65T3S_{T^PI%ln~lH9wEnC@Z?+*Wy~^{TV$aVh3}gqdm61ND{7RW$ZnBdsid+1fi$@$f5wk8_bd@G+g_1gyVEZ>I{}z~8oHjWpp~BKwWW z>{*h1h|YdvPm(}xQjnd&%p{TVbIFXKP}?cH3b%_cW|uz=NmI(dIwAie*QdakstenM zSxExy%{nSCC29Z^m!>Ck5k*^?eXS?9Y=DeS9Az~1n9-JePxizPl<_R(cuz)KO8&Md zcA$)3=t%;P|GTtAjc~4IgTsb;P;l9dqA(6~knehwAaNW?l`q@1`~bg5gqiMPjQJvC zI2+Azt=Np;Oqk;`e~h0bWZ8G{be4Ulx}Oex^jYZ@u5H4eiTRVNg3PtXjVc?VR<-fh zO=ZJMU@^W)cYEvRSpIe`2%hmFdQ{gt@YkoRo`KNlI?6e)WFKAjiDdTQsTcTl+%19a ze&iV4RU&zC;ctUH zSPUwChLJOJ91_n-g?6edbkm8MO!lv0^oLdt2Z~LFK~RtzdIVA4Z%{19@b;v*3JmYBk#@J)>L=8RiA3b|d&H}EyFHL7r*%UsC_k>dp-$CZCn z;W3x_CXh2HVp@=COdjQr{q=v&TJa_#Yy54W0PL-Jtn(AH)Wy8ZYuLL(mP2jnKZ?(B2I};X=dK6 z`I3wVzUbzTFkw{KG4mzP>|mVTIa=`B?i{~nG`gufM~jOjtyqkWg*_$gMJ$;eO2gO| zJlE2@2J1Y)BR}@&KuMq^tOFhWQ)9f3$?~*Qzb9L1g^*)wpj{f(8@L$ z2C|dn;sn`|AR*Q3G+g@xZQGuw%DydEguZ&0dB(smd-xc%5M@5V5d?k)yQfs0avHMQ zW*nWL!2~}>g38mf$0&?j8SxuwZ*Z-c$&7kRpzqeXSuI|N@(LDnJZ(6Y4uvX>Zg^KZ zkdiLo|4Q{^r#+A!!HaD2ZCoOgdYiA{Yl|QBYMej<;mlRubvXL+R=T61)R3)Vv6>%Y zZa1l1>7oa#Ipw^KSFC)-^x>SU%WgAmM+3h(8qi@4UzVCYQlDZ}Ywrbhz`7F+ae(ZU zG26AN#VOv_3?H;)(Ewz*r1fo>XYyN&Nw`mk8(bSF72zW7dq_3y0a&myvj?lW8TOF@ z*QR5wr_8cZ@FY(-=ADD_>puL_cMm~<#|)uR-$N7#8^Eqyx~d%gSQphmwLgCxuBspqu9vY%>vV>BJUtvhtRu`rk5Ky3@ZEdjFLNy zN2Vyf+3t~a)7xgqW;x~0fG;q-1)KHdNak~8IJk+cH_WQEPy7{&TVq%cSs^v#sFA)> z%#a(DO00QV_TrQ{W{&0m@~ma=MW(AY9?~0+{FZjxEN=9$95%N+*8LO}z2Q8KWq%Za z+^Sq2`!b+_V%QaaJ5K(>*_gi8&AI5fIVWS;prw~0%BY(HxY*IXgYb|2(s=pgYcp_o zK{oaIVw;~75a1~LdXq(fskbPqX}A=$jV-dzC~kH|ZbANDgwwm?#x_pACoO)fp67XD z-}y1}%hot0Jxh&Np4_HM<=}iQ$ie3{SK#8GgWgabeg!u;=;Kh(Gp?|Jt1f;M$LA3EZ<0be%(9i-SMA7 zj^LGDL5W3YM@kP|~vIUy2{-NLJ-Hx~-Qj z>x4VYS(aW^oaMx?`m#$ai?iyH`lLIHI*+{b2j8)#tKYe}>xSIP#j@*Y+`@1K8Q|R| zM*SFe`#I_P2O7>|CFh8%>gV{PvRznByv%YRfist`&T7;vW%=yu3V2S-Rb#NulUX=v zY}w}|EDF4gWB*wCxzTsWjqdKk-GN$UBSJ^{dAk@~=P6*#V@=gM{IqwBjip36%=!O-2C zmx6Hcnu(hMSvzft`VoI>UZNV1Fh#kKrIpP$eOBd}e+CsF&P4kkOSHdP`~mz0Wckeb zclyX2u^YZ`%Xp))>{VW^T-G86!)qx_GDg>jf*+*0qV?uoxCRXS+eQL^=_{|H;v--R0m_M-&}{z-d+{piDU`De@e1pj=QEfh$0rJsH{2)1)s z*S`jp2vuB(Ztdc)#9IEfc=7m5|DC0NIKz#d)Qrzdme?JW$$p0ydUNUa$I5=1s4Bd9 zF5OMy$$66kS${OAIjF_YAE`H)8qF}y<5rtS`}!|TmApsFGi1&3NO_5ziGVK}Y~}DC z$=`?Vo&He^z9zM=L+xn;51?*p2|E~QQP>^4HosBL7=?Rk_QJHk;4_l;F-<8<#PZ=z zB5VtMM%5}@58tuwOyry_{*I5LLE$g}-e$6_(P)BLsTQzEM_xt;z>1jI$r~q* za4U90rA|!GZ^j0&!X{T$B@;^pZwf6$e;A2sf(&K<)~lvvUR_g_enn`(2$;&$$Mf2&aQ{z|v`g}(cJ z=z9+&7~*rMK{#0%z=nf`84)asWRzXQs$c52Ji3+3E(`74Llz7q9Y{i2=yfyvXs;T3 z&snRzYB-;J+waQ5;mr2zy!O4bhvOtG@?lpYp6xRawa@H`Jq+C*`~G!qaeUH|NT*gX z-Gq`@X@6KYY2a0 z@~CYxv0B5#OvdEB3+g$S+Y7Qznp!{Zd+S_$1OVFW+uv%B!ShMGedVL0?6S_b&bIhY zbjLObHvvG_2aZ@$$&^9Wq!lyu4~UxG*c37XioErKIxp&Ik)QgrV2*qd=?@g6Dd z$q!(O{AwrbJlP*R3zrvvBLuaRRKreOP4O26!tnShDBEBVU+h;=9Lb&8VvNa)t%C~D zIkTBR&2{+cZt3_z(Nh*~xkO($vF8%pJBwE8bT@bWV2VW34UF8!NMd#TpuQ*aS@y>j z$5Ar3c2Q~ST>K*5O5RA%16=zo?%uZF+kE$%wwKy>xBsT&!RGegym=H<|4sXT`P++w zy8GK->YQ0`^X5x!|4V$*PwasMm=l;Xw;lZ5Awe#Vmri#*-#a_RL(OZ5X|KuyT7Z^} zj?^Q%Z|@G#gMBKZ7w6O_`*hdn2~ol7z|T=(qhYw)NO{9cew3_a1gi>*0DBZ!KmM zc|~xUZFpCAx~t!8NI^mxQP_u#IOKjsR_M(L-ouVoX~ZO^nr)a`I1Y@H!g27Fri=c+ zw&VJXXvcLQSv#&jPdl!&+mQ#TUWaK-I_nh7PxN^CWe=TVJ+=Ytl^7JSIRk45I_o;f!K9z9dC*HrW9^S=y~OurUNFBV71nQ#5>}@>vus?) znrBc5MNU!Kkj^$tF23?rjM^xrQ@*Gnow<3|Hs;1@ZOYQGuM%aV>mX9Av?r-m-^kMK z+dNk3(!aveMK|Eko<$T^q@pm5DC{l!?DHS&f6L;O4X0~xrA%>mN$rN_u81ztz}&5L zM5mi`9-@Usbt&(2=a$!1eg5)Z@9rsYkzF23gNw-Xl^2roZa%lX?Rl|M+C9JmmmuKsfDTu< z6oy~e(o_)s?Qsomrm>cKi?N+rj6b#>75N%DDX==W0Su&ySF0VO*uWqDV^jyQ=Y1*D z7A)lekMn2VFixf&!{KSyrdJ)ii8Rn?Kl4WD6uu|?U1VdhYjRgx_@@U{SL7S8a&ue; zui}ZJwf%$6nM*@~m7z}e(hk+l(M4LLqoFkW(2DLx9 z{*9UI+8=xp_X9t^6LWvmd-ch)p&g>!8QyAF*vlchy|Z0`L~A;LmRfuW&&mc?s9-{R z0qWpBhA%U=$VHYkD_3PPgHk z_MF=}b94LNPA@b7BQx*y%)GYNgx1kHbA##K5OCr?EhT<$I|p}MOL^chS_6ZX90%`o zwAZ)oeG@~!l=gvHT&rL>cGqJVbZrXOyEfqprPm@>=M$W6S6mvZS%feIvQUo5Qqb$7 zJ^4E2p7GdUSAg%t0R2_nBH#=A)7$veDb7vb6jhbZ`O0nt9J0=@@v;3-pU+U_K1RG8xrDDhP~ol*?>1z`G(h4>rlFWy$O!l9&UNf@Aa?9q zIz`7%sQ5whVJ}a|Wp6A#j+3VR!5}+8N=eH}@r((0qX) zz=Cf!bY6 zqr(;d*;x*Ulp`WR)JoO_fQ+?Ljg_p1UsJsEiLodowg~95eb*9d=UO7txP-mb(J6~O zpfTy&rZ^|umT5jGDyrdK-!ZsfDx+U@%5{{O7lFP{k=*D#PqE=UpCSRZ56{4Ad!`q- z3KVEuEP_F|OB`ko)I#dN0gUr+kbS<`Prw)CtpkvTiMeU#8o_#v02l7-T*CrE|E`}^ z_geM5mnDA{fP2oPlw%f;!3WBeY+KFZl}g^N31R(*_#j*zz6aUT0&evz^W(6?ICu%D z4dJ)?UKr1OUg>$hCDPy!?&IS%m8o;>R9j}8m&u65$i5g)?+P4}Jd9xMcKSyeD>txE zS&qhT7_5{zjv9?TjnoZ?8G%Dk>;rHF+rd#J&|z%fkJQFmic*kK6(3T8!6w07?X3Rg@txs3|0!Hr-TQ_xO#2(v^8<<54Q{5{6u#=BKLPrP^1 z?YVKvIDPWHhSN7-Zoc=;W9@Gl;!GM&#opX21A!JBhDcitNv4&Tl-qMi49-g zJAa~1KSkbBwJIx!rl`unGruK}fB`yrN@F*pKNIbDllDJ&Y0pqYjpF~0y|)36s=5}x z6EebpQzmE%sYZ=0Rw7t|QXvK{q)tF;AQMTVtzZ4HrPSL3oe`u=2uvb5IUbB67JIoZ zZPC(RZc7_b5DyN%KVj=(Qch67WMwZ`$HS;zd*OBs$i=`=3qP|K_R z8`D%2wi|o{v4e;pDDBKzv>mav$+gMJ$d&$QnuY(`w7^GNNoJ(8D12bvdUCngn%@!O zYpu#&46)08Q|K1njwJ>v&3&)hZ7Ot6i)SFW4qYXt`Y<~6AyzX#~0)&IG)`r|wJrg>FzxKn-fApEK0B8}tHJ!Y|Z6uaG=II(Vr zIpbzlCUjlh@z7AYOblOz_*W}7R9|8)RB8+hA7}cz)flQjZ5*d|6TfBi?AePLoj*3- zz34?&>Q4HI9c8$YtH6cZ8xUx4eX>lViN%yBVFs5pat7O11E_b)5HEKi_9+K$7IZGB zRd)#2$q-!eXEAbdZqkeZEcW-%k&w~&N!OUHV`oQ2yC935@Fm+i0=ey_?Vz3a;Op*cZ#RdNxg$DC{wiFg@CTUct5o$` zdq<$XqnQtXCik1jxg^_8-gdNa)7drZdOWbNCbEy460sWsW4ziCIkf-p9WR1`4n5;* z-+?3mDbm3|A$k3eLtuTE4oVLy+7)gL_om_l9XtON@X{hI(xLVj+nbSmLB8S84YTVuaj{YuRUw?uArRrqmiJO&ypeBp~)&cH$+6Z+U-roV1 zeX#?{8;1zyx1K+WJ?>B}unI$w-w{~fp%6A>WcyC3rrDXUZ9S(e(4KgLMSqPBzu2)eewTE%gPyY}NA%K( z__OEIg%8Ag35Ds1KZ&$b@is^dxLL|zQtj{TQAh%rguB;=xf`YTn{1Sb*9y0rOT^1f zbeq?l;KNkmd442~LAYHsjuJMr>~!7B)fMIhZ;yoGW|ha9bj&zGj=2(8^Fnu^>}!#S zhxZ2UwGLrAn3g8|9B3=CB`xh?C+&xgjpz3B?gRfqKfiKzKgXIAJUu!-2pmvlU$a2< z;yiuMaQY&5!0tFY8+4zW($d?LcrdDIZCVr?I|x z6gkxR)(b6{A8JiRz9T&7u?AsAkJVSa2lWf)Sr6tlno~RlFKOH4t4!Z-sqTW3#5;mh zy`mCe4iFF0ls+bOAefhU3kE^%8{M@Y<*xN5Z}iG&fbP+qNOpbcK68m!%XCGHy_wN% zK4YNiH-pED%PZ|!YF>Q)=PUM=PtUBh%WLJ5xC(!ZAYGX)ql*T%c`_Q!fkq4f0DRU9 zyZ{Epr%_}OYw;@Egg2p+_9ALmQ#NP{0? z?9HIZoq^ofdu0>_ndUBLAan!7?E(n4(a%DMiKwfSJ?3a@?&+ZsU-a;4oT7()1*gjG zsWp%+t~b$28tHW)V&-Fs20O>kUIDZcHN00}hK7AXkREe(c)p_kOv`uzzLS>*tWh_C7P;M|+ksAFrpFq) zP`W$7sP@LEGwn>Wj))s)p(vAhnR_Re0NtOUy>1Q%CR8gVq+_<})qH{r8**3AR9ICW zvm`Z3NB6^OZ3_>=SD8`bVV;dK&bV1}<9I<^u&lhwzLB0vjU}GME2;f@tMFAs8A#Rj zG*TX8Rx8TD#Ra5t?H@;H^6z{!8sv(V~mAhe{ZFVay1$ zhKDl-D}XqE4K7W>Ys>5>F?bT67%XbVdSgJ#cuywX>+T%+%k90e7}BxQHF65dEG*8R z#dWsV$Zi?u$w=(cbp{iw%?Esmhg?`u`_BicpaTNHxd%FKch74DpHqytf^c^A<-n`y zH~OpVg4criZ^MHc;bR2H33r7)W|jGh0OhvuaW3g;W@se4ImzN~ zv3$>3qaHyO;Vmy=a(HBCzGC@i6R;I6*aC?FY;$#JOaMmN0bXM`qjUD3yNB= z&r17E5DZXZjV*6J+>5v!nbnMKQ^6UdVwG`JH}heq>6~IlFRmgsReuT`_*Y-_T_4@_ zo0C1p6wf4jhZ4sW@BFvX{~^YUiAXN&Ga_xYMU?X@f}vLhEA7VF3Pw_N+36|KbcaUP zv++0CKdM$;ByjG~3IY`q2hS7T-k+UkJm_Iil7|gz&kmD~i#Xr7=yus}NF6h$NaR5I zn)m^+XmJl&u}RJPhYg7+$R}|$U{z$#LWH<03ydNMTl`q8MR!@vV}F`7BiyoueZ*$3 zEH^4v+xLS{=n`L&;jJ9Rz@L0yZGS!Lrb`L~NY3<7PCgY13M$<$s(?f_*~^%WuExT) z&;`-0zQhTMMB@O+hj$g6e1%8@D%MbuHEJBwVU7JQYpBuDf5U~~ltD1kTX?6nt5hem z6T8SN80k>2O8ZkG!ANUpPPXar_+_9lMN>J5P7uflui-->(Wnt#hkRDCkNMdaJ^@NV zNP>n|E*+2=rx7q5=)vyN$jF{3Rmbd?9%KrH1bG*_c7o0Z4->$q%e=)?a6}MpYR@G1 zDfYsiHup?&C{tO{RWJ+8mu>W+Cknq9CpE?E=1oA!sq$N-d_X{t3))Cd=)1Vyo9Tgs zVN}!RU-%Oiv7wJ~qCW60#D(Sy_pz}a2v!*<$_w^ESi9)3*yJ89*vZ{u=0p#kxwiYr zD=S`brqbRcBiar*WBuRFD$N%5*k>CImkxI87!{lfmiwP+0$y(Rq)e%=Zbv1ICzK*|8GVJr!3@^u1(i06q45;+!t32anKrqjRAsPp zi}(uPr(AaEDr2`QlSvtA%A=aXtEi7+Y{?@MXv=%I(FTL5=br9WQB>GU!~@Lyz|a-& zg{qc5)G|TUGC^8qC*NZ94!@ORA5(n8or?KgFZ4HzASSi1zPT5MtrFwvwMLu2_P4-c z-OJXb)1iym`?z}l)+~XD^{gBNB#A{3#-P~4O2IHx65!nqNS?@gD6}>6q)S~WK}8Rq z29H*Y!7_1Gqwji9gZw!=Dp|Uk=v0zr$NWF@QK=n3L$<2@Mxb~;ahkBgtu7SIk+YAx znlDg6yPC7DSP)M z(??;=j(!PjO8*jj%+ghY{DmF;^mo*9kZc52n*Mk{_L2CIQZgdw#XL?JqRZFrxS{IN zyZL|89s7#YF+5Cx7cPb?G%Hq8rPy9odns3ZFFmcc+L3d9{9C8qF|YO7UrsjkQMU8tv-WoZ~eodJ6Wy96}~q{87=I zh42}z=IDYh(QX7kZ?Z}SKbLOG%8Uh806B0AE76ta#f7023Wh4S3%9V`{*fAk<`&i{ zZecs$m)lRM0c)t+US)>YCLhoMwA}tSMNBxeQh_{^n6S%;6OX(#{P;fsJI^atJv#yH ztWATRPnyJ!gMElB1Bi?{9xLZJGBmGImA-v6_*}}#MW$U=SyJqGzD`#skiYK~Vpz8sTaRSoG{DDaXDq{YJex@cy*wIR=g3fM(TD=3}XF)8_Qkg*d zkqNRoQ4ll2tBf;{F9-<5@%?c*t$-h*|FKF4=qh``j5Eo}>Jzkrqbz&X_XI?DHFEP+ zmE2L=pZ_jZe+Z`VKQcgf9MJlK-Xig&@J%9XkS6}#wYvfr+Sm={d5&` zsZ12yJu*zTlh_^mj6p8_zGpXd01<9i=+ovPNQHO>aVia!p*Twq386aD7-fX$34Xt={WGX1B9J+=eHDZ8D?dvvC3Y}GZD^m zu$b!I>(r{GYn4v_-m!1h{re+ZK=sd;)<1R5@4gbsri(BZk?e3k=kWZ3k|$M_*-wM` zU_Dq?S^q9ri}0but7+p*T@$>x%jKyM<3!LdX0Vzx?X9x+u--Dm^_Xn*3BQ@@Dxw$#HUsIb1K0SUYg2ID_D{g| z8}V`5YGAN&Sgd>2Sdftk>YiJg^wD?cK|nLv8Sla7xEPr z`$F#;nTZ5_Aj>$9IY82nB@U@G6U;2ud*%SS0*4hToa6}=!CX@P&TV~LQJ&-%Ed0={BA(6iY*xoi3yQpLEP61P@ zN9w|LhrbT6$S`O6jH8A8s=Z2nMGjH`VmrrUOz?)TF;21^^HD205bA3{0LO6@I6&N3 zV}_T*jR7k@o_jrBVC1_B@mcu?q0r+!g%f#~D{%EuWr2alvDSWgcZkt`1Ba6b)j11k z@FkowaoN!qq?s4JDKj*Pm)^17!XJ{QdtV~VE^P7FHcL7zwz17$tFE@y(p(T7lNpXM zD^z#^p4h{ep#&D_DjKeB2^d9a74>eE2A)a$m#7PpD>MW!+hO#I^^w+SHB+7n=rFK( zPh(Yulu3(a$VXitH*e+kr{o+~h4eL>b`$I5&(B$}?yNYZ5jA0|T18blYy4K|QKMOf z<|Un&4H&WDs`vMqlQ^~bYrh~wu@ILzH}FE9Yow!BeN;z(D5RrYik+vI*Q%yPY)k!# z_44PJ+>c^pp@!4l$EnmpzsMN>26d^m^Tt09L6%n`z44Ly2T(EB6Uq{h;H+HHRoE*u zk343vr?AW$y5E=~x4nh^LSqot7WTtGzZ4S?5BHP9RIhlZB$Nm&9tE;A)Q3-)rM593 z{x%mk05#h~GEF}R(sh&#y(?bN}>miKA%rfk)~E( z`cbkx6eJ^UoKlhVq1Hl66$jEdM$!Bmp+#(CAG3VVSz{ZF_eH8n)DDqq?y)>`>$b)M zTNSh`IsH}@fjJfs1x?OgJNfJK%_xV%&z0`23?j(1dkZ~`>{Vy4(8VG=8(<7Vwj-Tj zde{c)$cD@pQCq7kYFlsb7Vtx0HQX$Nl8UqqG4SzjSsPsrYGLd@khPH!L2O`?60|*F zWLiE>Uag2Y;~xM`>9V$j-nWTeW?*ZYxNYsdGJ;m%n`47HTKNi9q~lLAw2Do95I%2L zs6TR~Zdn^rl&z3WWNlm1Wo?`6THTDjpL&tC-S-WLZY+oKaPhGSs*nY^IC#Z&NO7S^ z-YRm@K`G^A9SX4*m2yQ66@YfxPk0d)hPyBp`eM->Z|EjATCBt?D-fENEyib~@v(mJf zJ{HaKg^k3^N-k27gIvU0$!Z6DMTi2ML)UU9HEw`>NC;w{`s;p|WjoqVKwL zA7n*ApF*m_H;?y$r6wY~5!p*o|4=?}MH9WDY-pD;$;%N!kyh|SnK$uQnWKS;!)`wb z>?fo})#E*1JwB<&YfSQ`*W*jCN8uC=127RT6#Q@-TqlChE^%tcfwiJDGy(CDB5Ex- zo2A1+FXGbL2EH;wH$`vA2p1ZATmq!85RcRj;usA^~N6Exyg_J{m>5RWtylECy z`$C^Y(AZtC>Jufo4NuPU*i95qJndHYH(|@&%39OpmAUS`ENt$TF+CUTX7{~Iv3t>z zz+)(v8suWmUv8D<7!$M0?YZ};&oV|OLQ^&d$Uhjz9rsMnt+eB?#&p{rPdy^5*zr}h zH!JN7P9LnV=)ezgo4t@`O;fDVugymPSU)&3oM_=jZcVt<07h-;q`=WA;l^(=J4Oi}tm|30Yefr}Umek# zX`my})sAwn=%k3YMS4jnSV{JrTW>^xA)~ratR!1r(2*%U_Bt9Dju{m+P4eZ;$xY?U zk$kSH!vo+A%n8x7{R{9wCF*?x@3=5B=CGC*NPptr<}GDsk(!^xmJgjDtD;j+QQG|E z$o#xIIa_AuPmGZ1ne=5fJ?>yTWuDvtD@{WC>|rxujHvgV`FcRGgKFH&(@wN^&KkET zZGJo-F+bk4`SG4TKi;(YLF=EnlKF|@`H$C!TzozpIB?cCOsXgI@w$4X3oT+P_8K3iny1b~R$LE-s-f4m#1(0ta;F{W|l3YX5qb zxy>rwFPRTYv@`B}+WWpQq0Rz(b@n!uJ+ikud!&u*us4IasqMRyO9JA(#R9E5`*xkZ z)y>{&MYc=!T^9~ADhJEyu5t(p3(6F{v8Ckl%y=GP*O-DkWcFa6)am*^He-@vw|+@& zXgGKu6P)QxmJ8q?R(6Cc`|vqsDSt(#vpG~*g{N%43c6Ct;bBIcq7E0Az5SH}cH!`30iI5${fR)^C#2>(~PluO?YFbnb}aWvA*mga>>0yS7v>&e)p!m``pBAUKphr%xRdC zS3l_@JQ>+{f%S#NPUbY7XO`tQOt@@J@kJq=`$;j$QPiD-eir8`pE9-0oM6b)GHz6c zWEw~&WLF&CR>=X1o{#f1jJs$|TYca;9MCWiu(&Wr4HeIgDZ2=J6*tAl094A=Zc4VB z@^LpM$4$v1B|eou%rT8u*}uL68gGccZI%5sx)7hs$Ce3~WyC+g0@2!dV70h9*utDy zP3=EHfz&cjuM~ydhbY*+_wHxu+`aex4Px)6b{!a&MSuyz5v{zI`Wk|2!#t(--xz2A zX&qg^xk2r}8(1SSZ=>L5A1~2JHv8>*?5kkq8cHs!4?M-jZkUiSu>qd;*WxM{Kk`q( z)!<}-rS*0cLzk7czoyR7i43e`rzpaAya*Jv??kV@BeP??r(?Xg<3%gn*#RBg-GP1b zF7R$g1-HpaR2r$RW4E@!4j6mloi4s3BZIjwNMK^+OiFFozp+4o5Mi>jTy*mXztc2u-6sBl|H1$r5~{I%bf zT6emG3e!$dr@YLVUhUaVWI01iweuqC491D(!(KIyJNxc=9j#8)QY#}0w{}!)r^V9k z9Tg}*vEY9MW*CvG*B#R{q>0g0s-5sT<3ZiY*xmOGD=auD^y!+&(;4A>&YVXC{k*Bs zPn&~&UJ~@PTj2{IARKKb61m`fpIn1C=L+%xE*{@j1@`eN?DJ#5mhZ&HdvNeofO^J) z!}1q|RCqEZbp-7@$s!v%;4@~VaFp0PC=rcuTwYOu?%jToUaX4c;XijE5L+%Iiw~wc z$rIlUUTQ?;xldX?yQ4Q3m@41nd{+6cRrxy3%9pCovs7&8jn5eq^$PamsBx(lTBMmpiSR&ulDd~E%^e?l-uh$u^0~tIgyH#{Jy^UsOF+4k+#KQjrseZNVy4-SBvffogtNuc<;XEs5=WbrTyps9u8?HugDfL`7;V2q#Z)_DD~Gc{ z7xx!|E~R+un3xpOC8XTuNDk5E$;u(dgnJRwnq$xhC9;KYuu7U?ExC;eLQ;VW29_+> zmeJXgsVH5KpGw_A>z`nvtc_nLml3h886Mm*nh|@0^g?3W--4od*hYV@l)(i$?>4>n zm=8`RhDAQ*h-#r9xx%u?Cgin}n2Ifvidd#&DjBnf#3tlZ?Y@=?V^E>(tV#~I$Lc{M zP7@b>pWv%)&{EtlZ%I}G?{CzZk$6q%YPi8_<2K961WX@eU&4vQG~s-RcP!TfTMr%nUTfcmo_>{Ib%GR&4nkGIaTmP#vHR2PgC!Bm~O*))} zFYJbjM*F&Qn#PyxG3lYdu9?3|8b+U~KO;2CoOG`&xhWqe%|MC%>#}Hb3DJv-2@n3= zCP|Ok=d5pGtk_Gw3_E^nHyEL#e4!RxvHA%_h?wPm!Wqw-bePhKH>A!1sN;|2mpKsm zJ?d6K(il8@dXrVd%z?4u8B#N!`^V-68d5VS9j`pptmjY$OKHOZ` z#PCGDmS|9 zE7M=IK_&TX|BG@p8yx?-HT>BBr1U{sQhnFtJ`q)PXMimaNxn=y%<`c9H+IH9F~~15 z#0vY4*M1~}G)Lk-hbOi<-?&Bg%yL!=n80HTeWq)Dv_HW5S0%IZ5?H^7S6K{E^^hf6 zr#|HwvF_+~&S4q8jyQG$RUEs1HFJF#ArBtR8dVItL&`p(`uk-HUnL24EEAEO2@4}2 zTItmbIzmoVAR!q#@sRTfbFUSW&V27W%Og!^WEBqv!+AE;%<*M}vq}WCM%T<#c^f$62BjIOQ7F;81#@FLGUYZ{kH(sco|>zKY4&AU<<#` zSH=Th_%?4R+EqLi9%Ai8&6W12_124jk5YDl?8k=$Y`N!{Bq=|bBq;*Aq+COawdB_d z?YzV)r_fGFp`FARUH>ON@y=WSo!Vnd4$`h1vipd5ydTH4C8%sBjgg`I^bPsl#40Mm zK)jgF88fntiOR;iGDn$?nzM3+=k^!P%nQkRm=RYoU!oHN@;Iy}rdyXcZFV3*lfeVV zas22V&^Ta0r$X@f>Qs!0X(^(wNPl!&uDMQrD(EKA;*|^_Ha?e0fG`Y}N3?lxG&WrG z8?j=K`l4}OtYoeOJtYoato-L0wiz4nrbSI3-Wy-|J zm^{r?U5);=rl*L|Sf|*US7Hlmq!RuuXnB~w(+Arp1B|-2kztJU;0HO6MEh-$G>dbG zaY_&S?giT(mr~7wfQ&_r{EaP=6#3V4c&e%eF~L2-D!WjqhGv&g*r~{lEt&yX$UkGW z*(7UiVBlsxDRg_FQROopxu5T*DQk|$;w5reHfB>y#K`h5HbKpe6Jjd1=!_)!DvImiuE9X6Rp`%-DoE|H*r7!aPZdEm|QD z{>2up)GyenN@rgC@pgVc|KyV!KCk8K8-DoYlTXGLt#We37VY8jdMK*tVDBRex=$QP9E$Wm9|6+@}^otNQmqpWju&H=e4FYnX z{d^5MG3!xmtM)eSuU$n?aGGK)9m^b;%GWg8BHEHyY2Ph)QTh8o^~JPgmdrU^I4iZJ zGlq)LYN&9kp{ZN=sBE9D$+ca4v^RT6KfQf_xro=c^aI4O^iqP>|1?Z-gdtWmszCeo6> z?<9XphC5c|A{hnyq@u%Fm`r>in3F<67t#uqIE63*OIki%=p`wH@-gysrx1KydZ7VM zq0Wa?B`Q=Wb^W*%z6Ld>w;rz>-LTBUr3!LEw77=V0vucR@_3ptw)}^o=-d zxrdnw?{!Gy&60&MneWt44C8mRzDDXp@9T(Ih=*4jrK|k4!kr>N7Itu3Ub#I53Lus` zEtsRM5}g1{kX&9cvLaNrMMx@{t;*bT`;%n0CTAmgvj<7J^I(HN3e$EL2lzh@2N+%v zUWYvq7t5M2>-FJ$nK*e8Dfih_-M{!VQdwZt7&EfEFv4ZQaQY`kvu>py!R(0<4-;e- zPdkfO@GllK7WJv@tWVXLW(tT91R}Z>Hjhi;aSm&DE9)VGzzM@NM|X|nM75$sU;K6p zvr~Ker*Jd^f}Gu*UEb)VY)_?BJ1IXU1v{dk{d))cLuw&(+6E`>7Shh;;EHq=-M;R1 zp<1WV^TNUPVEcN(_VsoOJ>+n3(sa2~g0)uMlce3`qzy_-yT(b&hRag+4ze$>Dz<+E z%@E-3bJnc-7pq`PsGbgT_+Aed*>ZS5Bec`EASN(hWsd~L!3G!v?@j(zZG(HA3QO6u zvJ=Q0v@gBEVH72s;t~s;Y=ON|yN3A9a>9AEhWsdGVs;uqjdv5;-^H2_%9opDe%AIF7ymp@5u+H5LYuOFhPyQ1p zAvx`urJKxik3rX~-LPp4%A|z>v<%d4h-^m^e(E0|e#FJNOipl`8E)lpvju2!ZEyXH zf8lS_UewnWuATcRA(a#iDCbG)-F2$gVi& zT+;<2X8GgQY0y5_DKR=NZHSZR*J;fM1hqFgg|BuFAF_Rt8ZzS5V!8Q5&w`*Ub5`N>Ew5ra)(Z?6q508)5&j8T2M(3Iys)5$ZRQ=~MFPUcCLf0a&NJ%&R6ES)?BXgGB8U0%Ey+_inHnDolc?i)5+IC^@0)7>Ety|2>>gFi3U1p z>2$J}lXecBG<2o^E}iUmy~8f1=;Rou!X9+;JG2&%WVNTh|^t`LPo_fT5nSkot=pqa{SGYr`JlY|VNVe9&K4&2JP6@iU)P*HFgN84Sx%&gf05FMSxhMOkK#Q8!P% zsBqB2%LQspOHxc-0;~GKR_(-Iha@({Jh8^Kq&^sWg1h1jB0ULz ze?aZAO?-O>b{P_46utYpexcqa@!O<*MpBGSpjLa(Far-`Z)cVwT3CZ`mx5LtKqF3| zYeP#{)2Z9sPOX$qt&~o!Fk0t)TRIe3VdX4xIwXk`jnb7kGeCFLEM2a8f>Q+P%rb+3 z3#H3&mT#0c_8q{ab5<~BjBTlrsn0C47hb2ffqNkq-I|Zj8vJt@r7IHuV~xKe(dZ^I z)OO_pg?Z;g{Lg@?Wp3hzIymj;fQWlT9bL%{b(ww3wUDSL`CK{eY5DA^%tc%IoOr{9 z!D#2LVr*TR0>FGr1E2&)b^!2hd7V7QtR5?#`677p!YRiZQ9wXJY4RwOn3OoHD?M0n z3VjhnJmPesGGgVt#HG;Cii7wdi5wu>k~)0(YBp$~tCb5_^9eZzPQoBny*MHIB%a(@ zF2`rfimCNr<>q;wV|V-GLU9?3hcUs?OQCbnA(iG2^@vi+aI(dWka1>^GQ6(RU?M>4Rg4 zP1#a%XQr%y6T;11AHqqrCVnJKwjlP9dzq^oR9Q{0s%6+H%dkY$m&z@*N{waqPeBme z<2yN?J7=Mk-8%7UP&S>ETBCU;YeZZqjLSr)QPe6zgi#%n(J~GNi{64|&<#-mYb2)W zNd+VLaY(hkM1Y{&zKX_EcJUZtrX!+UX#>ZFzR+jDc-Pca(?*)#6>Lm=xchuzm;&FL z>MfC5cuH!Zn%!aYO_`rEzl#@zrza<(csEFXD$MoFZXl-V-w>zT5kDR2`_FCP;LJes`|9oCX@On3RT!)enUJ^q-WfRX}10rI(W z+M%@7kIq0zA@PRRuS}8EtBqbn&oftnR?JMaRd7i=tgM`fxMU8ROLD-VP{YTrrsqq# zc$fWv(Pg#^XN;~q*_L?AepjGM;g@cjy|W%#>(njyMmbq{LR2Bb-!vZ*O$h+`+8Vak z5c45XtiUtuld7eO$urMR+cdVG4 z{{7jWlIov8-~y>6rv3sXc-e*5klnUW(#2nOH>=ZF!8_CY!b~qhKA67G}R-g*0GzE-esBnGxleqGquNuxjfVjQjgZ7 z?af-FAdMOs8m(bGoOP=MzRgT`s{?}bF!H{j=JOf&dllXXcQP$%1x~ckcz$Dc$~%i>n>MWeA7hN#O^hm>)Si3%E0*c^|F*& zY0z&WZ-aP;v98Z9!mkKXe`}SR8=fIZ#nI_jFcrIozC-T{y`bDmN<$xID(1JjTFx2YwoYp5o}Ke5{u7k5YQjWiIf} zQF?$-L3lbX-GAbxEBl*+WN)Gs8-In#aI~JHC1X5^9r$LN1;`o2k zzZxkJzfb-088ICH*xz9u)%^;*MmOD`=fc8g>e6A#sHhdIv{%IzC_*q$v#gcs#LDV7tW=)0%F$m`=puBXI+;6`u{bV8cE2 zR;hTaQHleMo87wowU_hCfJ8|%*PN4Auy4e1e2p0|8G(lj&wTF^ad8vsZx)X&3Oruj zd!kW1);M0mOyaW!rx>LV6P_yC40pB3D6N-h#o=}#XzPVH7T+<7H(uY(8>b*T;m|QqpPWH}b{20Xwq3aL;{JluonB!aTClY6-eR{n*E0oIAQSwxDquIs z{mq#}Oak5QF^&}O#DPSwqQJ7y$Evd?8oi?1Jla3dD~V%;yRE9hA>4{%fr}pP|6GBL z^bW3))a(=_^#)fg=-oLY02s#;6# zS5$Nd0Gnc@ZN*4u0Es9DULo+uD5iTo@nYGNX`Fie2;0pn&X50|C;lJ{OV|4AR`RY+ zqVXTfW^}T%lI!F5I@vjgqhzXE-jv?5?`a5hEk05TXLF0R22r-I>1p2N#Df2z34AC@ zeHg);-~w|nUBiy!di$2ag1h6FN>};Nq>%OXOjvSw;w?e)rcjRL2wTRN_+vL-xYNZ8 z0~df7oWK~umT}YiDl6|eLWu>|t8I2%Wb*^8S-IRTrBr_->%Vs+7eV5&c@&&~xKA>$ zKJkj8NtMaKCVLp26XpKBSF&PqCu*F@nvu&Ec8tl}lC$!Hl@>v8?KfFAF*0I<`;rd~ zu_g~rJ}@{44z02u$a6|tV1*gO%{imEATkK!Q_fy**NEJZdz}Mjq@9yPn4{rAOm#Uo z;O)~I)jX8Yc>v3C|Kf#=g$PBU63)TkF(a^oIHdTw67oskC#z)`Jr$A^H7!#j36Qap{ z9JPd|OjZ{ek@m!+CWqHByLGQI853}xs52d&TciaMDfs-(ia-*1)Iq zl$rFJ-xDUf{K^&|mQGAbg&>c>_M=lEOBi-cCGyZ@E;u60`JTwNmPdIX6n$_=F)q0L z^^$;5fo9v`v+#=Kdm@xIA+d#HB!|F@bUiLrFO1F0S42+%`f%(kV65%}j2gQc730iA zTnQl@!T+Qk$u=hpwkBtqIrT;kc8`e!K9tb#GbhZ;n!*)IC;b=^8X)9J&gR57(s)A6 zbz-$@OZHCUF~#3>&rmDaCegszZAq;{9eq5)s%pEmjlL)90OT{%u=?`O|!t zxV^m%ZbdeY1R{qz&YhPL&b2&srGP^TJPi8)FkvVIg*veDjBn1+` zS32K&WN*9n9D}8g#D6$v9dGFFM}Kj}EBtL}ChT3mC_O2gKXM|D#sr@zv?2K9eE_0+ ziuopt-ZAD%Pt>8t=*g_`E+>8UC31-+If}`V*zY9&jvsg2F3Eov@cNzDM5p>XhsjF( zm+EVZr(S~HNLjaG9n!kcSeS`?b>h9)m0vC0=6`0}IK^zQ2a9GTj-_{fq&sW;Qh`+d&jTSL8Ts=XQEp~^cL9x6|qRy9ktE;*wQ zW%glq1t>M~x^ouT=lqVP!9&mb2med;FFLFK**)rKT!bh+?|A=TNmuj3Eon+V{mr>D zIsV#-&?o>!UT>7w6a{nQR-(Osld!e<@^OL$6bXREE|OoP7YH)-`xkrUS3`~Tf1w;3 zWP@g5u_xL+IcRpb@z;1sG`n~5<3z`TW-?_L?)F>a9n5-&KV8d}0-(~Y7J^Qe_3wKB6SiZlhx{e?}usn;E^=jy=3+8x_<02w- z2jY&J>imq*4BWP5&GrQmhkGmS6Zt|pZFAx&Aje69q#I`u}^##>>b-rv)$YDCa#UZg~ z4vR!^G{GrDiJin=zM5oNkZ3NDSCk$4-1!&8msNsv<$;_s;bbodpRo*S>m%#Y3O>l1 z;7Je#v&UjB((6G`gJd{YqCV^YlHnX&J8Rj5J?^%YJmai1ZlW`Yb1dims}1`w-K{Y&nxNW*|*zWM7zK zmR$sf1Cq)Uua;xSH9!^0PVA5|OJsMvsfjsntmL%RZce#B?xtT~nMul)g=pypIxf9+!R@-csHoqFl# zubsz>FyIGdD2~vimbH<6qsoc}wJIyp^_o+Zm7vTurzks|moXJ@`=8(GuN}<0|M|ed z!e%XeH{K^yX5ASotvPkI)-tR)^+~?9%orw3YP^XtX-FVORhpvB@MmD($z;O zI<_AHoRAM>N^K1T{k30Jd!_be#0{k2Dhlyh#R1tR5t|S(eZXo3UG56f$4~)X4}F|& zhx#J8xq!`-%s@g9^6M}+HUhGU|4Qx50f~3Os!6t}tv&rEUIm|vi+5Z52UH$-OjDI0 zLKr3D(`4s>ieZGg%EA>X@l8tiHX(Z=WcFdY+E$cSaqKOiGroaVqu znk8m*8$q<%%}6fSw6VYnpa3XZsUOSbq3xIu0qZ5@WX#rIyoxUfM2D8PbIyytpEdh| z>32@QZh9sGok~{*iFaO(fM$KAeP4fpiF{$XmRCO~ks^Y}KyPbU_@cmp(6x}sOHAb& zBRbB5uy?uTxk>H>GRGOQL<2~xvdsR8sv|qGue`D>xlU%?K69}GwZv}1Ob}c{!BJ_u zqTHO5{I$QPdmL;0wNFbwBkM8GLXl7#!#*$5f_;@zC!8e^7;Z0YG3vyGEtJ1SzV_7p zt}X;g6|Ix+;kQlI0ZwKmjtN}99!Dgt_c`yycTtW>8>k#aY09=fICm3^*zqXQ9gCZze03p!C z912nDMf7tYEpo+1M_3XZKrNN|Ax<&#Gx->r23zQfOpe$mR>QzJlM|>9U8X*rH8a=C z%!KR1wz*l>C8Y@6E8K5A{mh8J379irJuTC~si|oRKOD55g*HpV2ALB{c-l#LsIhy| zDr$SI*taAu5G#gAzUHGkRYRxFS*!JQCnJCdvuC~0dA+dCrU+z zRukgRRT?18p^c9MB>4^?ojYT)-QvI2ay>m`*Qa-G-8>2g?S&f6I)J3pzN6DLAf-VA z0eD9!jsR$|HvS9}RNuP_Fxai@70%|Y9U_#l$9yBZa^_p9bbQpnX6S*PJL{w;`Kkqt- zL?M24dUt>2;2XW6rCs9RIMA%StJ4nYG}T??M7VzOJsR(7i4WkGwY)5~Yo79-&cP8YvV zZ#2Kh(Yae(b@8|5Of6&uACDEpDg#@88(#ODqWksL=*c9`ztKTB9=eEl%;khhD?>%# z8-G(98w){P@}I4R}+$D7^H89}_hm1}~QTqngV9eP~dTedS~ z-oIG+&=LRT(0OC&R5JPNvKUFt*x?!BnVBsOy=%9I7dPt3#%?6AY72RiO2tOPX01rjONTza-B)dyc*9rdN%17L|Y?CV@dZSJc zBVIP@1jQPg%lKR0)>1d0XGYo?0vAxqTSju7}HP^opE<+~kJ}#`XeX;BHw}(Mc6H2?rA!&3>7sk0;`C(ri-L@_Ku>Pe#Cs zxSn7(>jXA4uFx@0N*(w8_5CTR)>4D_0Riu%0&lxdwt{Z`E1oO;=>ZP)nG85pR^G3- zZ&NM#%B<+{pM%NP0=K~UpBaU;YpVImgq^7G-Lu^?a>rLfG?ndKQnAZH`;Q!D8Au$5 z2k@Ovd1kvIvmQZ3TEClCQNGgMmXlSnv~BqxePmlMdtO#X@6GOQN&H^fukqV7#b)E( zqgzcJk~^=~EP;F(YI<|otJ0c#L!B^aPN|+i0nV@^xTOR#K}cJqQTRL+&GAaE&(1O> z^FMOp?~1jlbo?g@KHBdbTH2UDYvUK86IIjxDs;ke_!|8KbfU~&3aDC38A%_RXkj7mDY34s^wV|w9j}Qh_Ci*02EM+KYEI8olJ%% zL{FYU2pn#eGr>6kBls}BQ^Q6>A13RpsfymoRKnJy^*hv$P2w3^7^Ybyz_ASJd)(62vl(85siJ!S=Z_!G-=} zfsUsx8Jwma_lvvzwHJWQ9W}-_LFK5h%;U^l_h0g3%`z%7>qTLufYYnD`HY9Kjp~dT zV!&QG{8o)PK0@Zw@%=HtY*2+BQ-uijE(+A2wS0qm+)*(at!VGH8%Y~RjaSi&qCEpe{`aZPZelB z?6F3nwkXk`U>Lpdi2l0i)L|`A;;wzh(wkWaO`%3?Rc;Eaf&~7p#;)GNG8Gf>i(&g> z%9kX4;w+jCx+qlME&b7EQczL10`-P+p`-l+Ii4rcwj8w$f;W*C%$v7ytrPBTMWtO( z_^l+`?I4ZYzhs1$>EBj(d8Iw|3@s~;3e^syPWTfcian#K`4=mODX=V9W-0HTh#oh> z@*#Sx*(}sSWcq>Sz@#*1WFQ{Nqq>1uuK=6YRSID1h_)NvWmz- zdB530VoK^TKx1Le<;1@OT2UKXmN{tGu?pQDg$2;dLXji8%K_S<*f8%}lgJ{4kY-0czF-1EyzQE#z6`YkqxdeiM(TUW4`}PP=vk%wqW+HeM$cpMaZRA*W$kd+)sCgBHV){ihnC>ulj zg44>mDR)WZ#$&5w8RxQ$vPXqFSc+3t%2o<5$6ul>ld1OL7O9v$sGMCr@~oP8D1dBj z?JwHZg}9#^7Z-;Qy_0j}aU3Ct_H8H&%OU4PLi`?oZ3zspsJGn26Kf&D6pZ3cg(iY` zlth-619E0CDfmh_%8Mm~-+Z)|{a|jW;cvmI=2JLwc-iuBWxS2QMzh=>bD6yDL`Pw1 zj(?Fby~u8x-^?0Xnq%ecvF4(!v$m!8_ghLbGg<;o9OdNvn1KjEVxpqwL{OW#o`RF2 z?D`=W(}kt0{n4+|8JvC?C|XqjR%mRlM!BvWl%U#LU1p7a1d|iH-|Lrc9qId@pM~~4rgY9L>D#0BbECS2@ zwH70hc^gxf9OO(|f2km_+$*$AT6m;(nxXA_4}C_{t{m{s8$kWNc))%YJw zhAwRJj2>p}VHPqbq>JuZSLRMacC%opr`{l=PW@8PTh@&Q^g-ZFne4cEe~jN z_xBfXKQE6qiiWtz@Cw+;WqdXa2WX%#;m9CjpHXKQSIyn5liVnqbwL>&%H1vO7yeA{ zrJZ<-6<$mu^!b?UIOW1Zc5b7&PAWm`RU?Mq)Q~8_=sp}VSi>psz0X^|(c(l>EhTJw zFGh|ue}r5LuVEFLKe~TmQneI~jY&K~1~b}7+4y*Aaj9x|r1^v(q@hnpyVB~|m#tB! zEZF#^kbzwx}tn%Bg2-J ziFsI^Tr1muQm7=m1tn2p>FMm-^`lik6q_Njdqv3{)C9|@XRWSHPCkldw8G2SuIog< zUGD>9pTpL0&{>{T9}G)mH}(xj;pD>0Z?_cFWvt7m7sfjIWYp!!V3z2?6f+p4Wt(p& zO$*EvU36Zjxv9x@G7Mw0lAQEsFlKlK8`C%{XdG;NE*kf2J0Zc|3j^8y=wB}oh{|q0 zkTo=rU5Oc5xn)hIzNG3<&@NRhxw^PsC!MobAESkcD8P#RXPFc)%{9YfOoygwtS*;K zGHu)`7jBjx{^;BCbE&*Hzm;XG#G(4FiOtc8oWo*u- zFQLA2H&|E1N9U4z^Fh|YRDaKE97i+Bb@H{`p4SD}rbg+q{A!R3FQrQ7Y?W!PuaN=G z_7oBG$Lf@oUFVajsKqC|(C4}Z?0B)@nBp<(JIad|otrFOskD!?suo7cbzT`mV8zhD@(*EEa@t}#5}3J8@;X19 zuwce3bYsMh6R(FZNoiU!*UfMBDz~%#s#-RhEzjSWxr~A?tP;$nQi(Nc0RcyieyCg% z1U+aflpqo7ueVD<7I&DIgL{gToDsi-Mz!N_4xH(-30-b`1rX@k+oQ z(YZ`ha*d$mD!btCdJe@)j>}Fs$WCn(*6mxV52bQ@em0a!mlc#s-TwlVjxv`jC_UTxkN=Th zp6mfp|Lx4i5|Yn#VRY?DHCLjKlY+qqof7vkA!*59b&_u&**K1XKoEl8E`~BUOOi}KjP5OzlArNCBBWBhrdc02iackp`?$ZHf8Dp7XWd2mqt;#OmUWjN{}b5hW@pa~IP0`o zJxJ*$C)de<928~Gm(}fF*cF6`FF6cPjrQOBrceGySMfxzI8<3mU;YnJ)ehTtJ6@eC{aj(F|Oo zHrm-6Or7L+{nI3{Vt2W~RE_S{LI67BO`sqUcyf zzHk`|S(FZz48k4CgoTGC!$XvcsH<&y#+GHvzmbvnjac>ce}Nx%bb0qgK4%G~?6N$f z(~Ew#{@t9uj^S&_MM z4zqw2&Gq(0U_mtfUR7|JvQ60EiM$4T682h|3#RQXn=4B|?J6Zpc;k!u&OF;+`wd~_ zbZoXS%PT_42tmcA$0N3C9j%tYyO|C~;GBEnC8*6iy+Q+O=8a4a4fUH8>Z9Jm#~VB& z$L9NMv#3V&>HhAK$@N*jkwN>qIQ&__cKwf_IVKfZ+Axw&WIRZ zYPWd28RJyAg-ZJfi-8Cy)*x;*Yqu&rS^x8G<+c|ZQQv2Rx+dh3)@Gipjqf2)g*Uj9 zSt2`Uj^2zf>dlgm=KFlaarWm^ANw-m1^u=%TvhmtE__AW_keGKH^ZmDn^`|o<&zq( ziCE2sk7SsY_J6{Ix>QjOkk+H`e}EmQ%7HVOz7*yb)3!6ns{8f{)#}B3K!#!4hZ&Ii z5Y9*R6YI^fPb!yBV=3c*Ch)Ec6lypFr91NVSE+(rE+O{pOTonNB+rsd+*TXhJR#j` zzT4_d_e1zX)hdI{NQjWlG6%a22tSh6FpvQ

    ZUJIY#C)5qLqo=(eF>WyXQOSb1U zUc?Q7Tibj$n==&?_@EZx8}0|1k#5eH@^hW?P4~Oad_FB(1>0o+Y<>JTC!0BwY-&|< z)3V9jhy_P{m|NQy-P(?5D$IR=ZuDZwCh`ikenGM+sM(p8O=`=LY_Ee@)k;;mjsDEd zrpMNFm)lH(`+;Vp(_*p^|B+LE<5$S0rr>L7*<=a^O19Z5r#nlTPPKwgR`d@4B`9)!lH;6nsLm^&;DIfQW1>EE)xAMBhJ6xNi6T@BX^i zVK=cY;fnejA@A4{f8Fm%AYyJ=5Qi_;#*3CQs^W4d){}i$H#0HR7o?UE|A`b1bm7Q> zAUpo~i3_Azwt&$){t%zAt+f5mpu^=g`p3g0sP%Y2hE{2xe#e1Sf9(exSP;}L@MlP` z-{luLtyrPM&`GY%kHwD(f7Mj8M#x_to7y$PTQXIVzj24U@ibmJQh0haVqI}?0-pW@ zDEUMSm;^EFdzt>arRw)qe*5e0Q18;XzfQC*7aS6NrDI15?z6o&=JRp(9Fxl$`jGiX z^03u3mvPWfncEX72_8YY*sflCv4&g_&U-Gxv6^Zrk=SE3)yp$xH7%Cs7OQEgJfF3i z{!^a6wwkKt`E#r3$MXEK;P(pOqy?u$H+y!D|M^m1l~Ta=+O5oCVww1sd77-)$*T}y z`@4IC22^;z^yiEQBgUQ)|0WP&HN8lQ_~+GYo4k%vufLMl0`a|N=A5^c$2C@{e@#-$;J+>(r)LlD;YOsi52*`sWWE zeZOd@SnedJ!_Pwsz4nGeG2GF*fP{e07Nee&4Oi9|dhrv(*RnP`cC0x^ zd8ojFg%kQ}F-CwHW*N6Q{>9(r6{MoJ+~FdmU-){nuY>^JC_y@BXGIU4)|)<*72Tb6 zqGcwkp{`nW3BH2_uG;c7c z+-z8@_=F=iys)7gZ&pn-_DnIBu9Okf4*=tsbut>GP7d_Q%q@9hPTy@OEzwA_CgqAt z9z(SgDpuC7V;$?)@Mke39G6{KCk@T}bXIY$evMpe7UvWyF9h?lvx@WdtN&q%u-iCg zPT!i%s_&tP&84bMdh2wO9?mIuK8J5<{HOXf(D6a#c$BN{WE#LtY3;24ztK+JJ?Cjh z&taxHXDT*g7vi4-V5n@z*oCWJ%Lx(l@1VP^s(|&J&vWy7#N9UuE_kjJRIGdrF?Ap*B9Bk_bJ* z-ZFdChh~C9?z!El6QM5}D(ROMlYouo`g)>tg?gGBJ(SaGE72HcN-GV| z;FiEDn3rGh|1UGYp)QK~i#A3qu!g1}8Qk7TcS%^UA2J+-9wNcBZ$0ngl5c9TG_s>dvmP^C5N$Ff6V zmvWg>JqhNNGNlgeuiM6P#z~t!l{l-~8t4W`4O7l$=(tUL56o&#m}=GwOFp#T$KN1C z=>eS8O^t55wcP#!R0MH?IeRK4rX7>)i&fsmPF{VPRGw-o+Hz~9{V}0Es;5>77ccpQ zIfyBVkPORE*c5!Mp5_cs0V+?u3Y8GWAKlhZii-3|oXmL!f+#K#?|b1K-9*uZdEA3Y ztV6M(PO4fHYw6tdvGykcenScROjAjkHj4<27^t@!elt3bStPD@S9BcLRAoL>-EHB7 zN+lRUuk%DWC?J4G9b-Vt`0R|9@dNn(A{KspPDTcQ2eQuNa~TLXf4cs>SaF_=%u&~g z>A-x+b+Y{WHpQO6amUnMQ|s9>Zb(LK+!$4A+%WwZt{*SZYlJ>^ z|H;{y9Z_Co8-jT>Bvei{)hNw|15#{Ct~F^Iu16?>Yp#|FLo$ucgBcD^Pbtl0_A2tZo{;ml+}MAoHJL z|HmI0yCvVcm8S-nO8RS*6O*i$Tr1H5g;>lHS#xroWzlzC#sh@dG)FK$*4$h181R4C zdl&eqs%w8dArT^`O!P*fHm#|bS|YR+8!Hi1Kob-VWFnb}S|9a=_(Gf!v`!vQqB%Jp zh=o{gYb(8_mbNIUL_;MIkS4)Wj7SB&wnC-#jKj6TDz7T@|9;or=ggT&0!VxBzrWw- zH;{AoS$plZ_g;JLwcl&E?EocT-JBD+x5`&{H{PbepySbMch<8TO@fBBQmXZ$&~6r? zrLQl-aj)4zH-$EL2)0-Zta;$1G@RU*@Ubp1(7C9WTUfS|;2yJ{k>kL!S!7lgBGBzH zMXSstR9)|M&(yUnW>X!4@Zed7VQojKzLrV3+r>GMA3n|EHO4r&|9iaB3SKko8O+3a zd=_vhpBh~)5!xSoll)>@z!vk8Jhe-!a*V&+l0AP4Enu(TO0nY&S*|L+1P& ztUP?imNhBXfp5_a0Mza}b7EFecW3=pkY`HNij}YKYRs~kWjVF)1BN!L8{WQ#d;(RI zdV%?UX4!nP22Xb#e;hXW$O@yr`Y-z+HuzW)*m{>;zBamXGu=pWnAwMvKCI&i)NElQ zxZCJm#6z8Nll=j-v(X79Z*QP_b(-_Z(@acv&U-W`E$y|Pw-{4%O^JkidK?FGpV7#~ z;R6^EPUKW{v1vh93TJN(~<5Mj#`|9oof~zFVX7PgIKPStIJ&FUE z?`~OvpjP4UnEQ<9YVb6ti89_JWn75TJqO2Mi;*77pNX2X;596Jm7}axdD0 zQ=KVQRBoog;CVG5qqi(%AV*V%NfCvxqlIh`gK2$r3zPyan`SnOvTmfZ_N}eV#oBPe zYyO!T@%x6wr9#!zWSeWT1(EBV8hY* zjBqweg-wQi9cZc$Xe>-QnB_DNZER^k!Klvel+!t28{6BNxu%500>+7Kccr%pJhO6G z^g%2grtnVMNa?hqN31$lQE+A()!f(;_JPt2Y&MXE=-^PPPg&>!sj%2c9sSz@@}8^E0l(_f#b-lu zN!ot$Eyep+iG%Yc(wU-#(L4NhMEgCrSNY-QCyeo;-^M3Z)HwTlKrmzuLJdbS5;5CW zg6x&XxyB)!H%(#xRL%aWiv7maY+TD^N^f)>_8#ULzK%&?`6RG>5?MY;SU!m?pQKnm zN%cdMZj#mo@SE3B0On;V0K-~{G>|WylT;6Mk}8c!ss}nrO2a7tvyIs9&^O+~Pu%yt z$t{Fg)2zS@(_+S;zfb}l6Go(&Yj&VG6qG9Mev|-n;;WWv;rZ}sgV#y?+~-5nQJ7(8rAW{PPhku z38k$=RC+^5EypOxd`?0<=fq*IKnM)rB#y602&lnNnD?nNwzJRr7V<5@VJRi;TIFef z>opN1%8<5gUTMkBr^@(!ca+=bZl_+NOjCkqPmBHq6fs7U(`P(a&f%KsvMU~x^y+`# zS7rv(pl#krrBpuIBa&EV7rm;ac$)ySYS*u3*+?48YdcrsqY{R9W#-I&`VD7zUE8q? zK5w?Gx+X(y46-r8t`Yb~47dNd^UZJXdNVTOnnUq7i+8=bar^iy-`x1eH{aQTT?DCBTyx_vJX^Q zFy&AP=AJG>T~qp-26&Wme~2=v4%=Rennr!Dt;#Buk3``pMXGYIXTyNKr-jn<%8`Q$ zx{sx{*fzAnpPeWSw=Yvt3Jo!6EVj+v12#f5Nqej z1l>DZ3nXVZu5W(63ZfJ_juLf5hbRbIAQ=o99r3fH(-aK8M ztw!YHYM?$u!e%Rb*HLGi%!m@0mCkBxmnLQ4>yrSK+#ygF9t17QxeuwnYeJ)Gy@IY9jR(c{a<_S^`K$3vn`N_yLxul()B;00de`D$54Swlu-0)Pnb?^y%^bu?XiE_^=Z85VG<8*L@@K* zxTM^d?&Z{Q6IHnABp`b2E{5H8 z$mKXeQnU6WM1pCu-%@fOVT|1V&?a9}7x1;5U#epbg8@cGkFS0kK-L1*1tg-}t_P=a z$LhtJT~a0N@nDeg$bOK-0j#T(mpxK|p8yE_5)C{>fL!pn@~Rn)@YC=^8%Tj|;`D20 zG$i1E5ja~N;6I#zZx(o#;LjYQiL4SJ8!99tTLYH}Fh^ltqk;1U$hB->o~MBi2#|aF zkzglbHw%!$DZk6xr@!jzVODjED>R^Y?k-9^_6MEi9KEJ z;$6vC-32uooCw2IGDL`L7oe-8sN9~2v|lwn{vzc?F;r<*y8sEBer^0k%8cgpDFESU z-HVhM4a(416c!EYL86F7Inkg$07P085e<4pV^Kgf=tYf1@z9_p8jHfAL62!HiiQSN zX)Fqc2Hmc)C>9!YrN*LAXizagj(o&dic~0{68lVeX#s)t?5y~U6bv0~h$c?i(4fDs z|1_?|#BIJ18p;W~gB&s0wo!?R?rYgY!8 zJ;KLTo1A19)V>i3(DlGKwpR4$yY^;ej5lh*hC5=b?;4qK(lcQ+*kKS zy4BXp{n+27&eX|@{gWtV3RkuRz80 zTC&uUOe3jq&JbVSdCKL3$z0{aju~z-s||B5z*kkI9H;r_y?K(`LJcq*7NLMf%Gq`t zQkOa3{Gw7!qe_mgb(qEjZ!x{;16N^d1gYZ`=T3aNw9T zL9a9b>vh1e7odz?ZnY8QG7Pp*@ENf4*(ta#V1cvJ#6G%8>(03waK$pv!AyhS^F7?~wm z8S~BKbgi=Eu?8ZRm>m8w;o!lPkJf6qn5MfICxZnM6V1jxjDo~C$ECf^o1ngQ+4CVg zMyEP!n6Mi%$k-qK(3z%Uiv0E&svW0EZ_EcO*hw1pQxELWD^k&-_aRLl@Ov73Su(g= zgYy8kS|}`K0W`+(IT&JZRjM$Gfg}zoTVV&ZG2yJ>>1Ju(=yux7t!bkkN(&BHk*;LAp`cC9NWWGAuo1-NU8&jF_Hwj~B6=ODG{!tlj8 zUqkukSmS!&g8`1$HLW>XAu(FtxT0}xmHa7nD0XiyNH z^oT0Bn*Cg=VQ`;Sj2vT(4L1(hjTDEK z{kUNj0-{c!`zv9M2~`Jmw9KeK3vl~hbfK@j3M=~Y7JdUfis0QZQ9{(o>K1{h{siV4 zNDk*8@C?|;K_6Q(bcb~t;A0lvXdVGCqZtEqw~nZVl6hDk!u8E5b-_39I>43X3tike zk_i$)bn$LOtu~tZ1*->=5A$AtELkAK&h6t?Yc11dz4Tqt0B!j|w!entJ6a}DpIhh` zu-hTCqF-R(Gt+~JHY|Zl{qlVvQop=J<)ZjwwB?ch?|z-2Zwe?8vV|B5+pYkG>oDC; z)+(Oa-%AS0ta*a+Q{$bApfK^IRL&ZJsZ?n6(>HG@SDc`elJ6Gx&9m81gj4Sv_sv^H zxE!_YwXTI*wcJJ;lFDQHVk1f0I5I;GG`f?{K1Fy@!$6pcKngL&Wm&**dmxSlYTB8~ zvagb!1*`bgkcE`xn5u7@;f9p-R$;A#!W#V?Bt^6k1;=mS0GUFrV>>;tQVm;0lRL?4 zb5-BKbv}qrwg!VmWjNpNo4-wtA3+H!nx9kQqwUGyy%2sz)n>L$L)@GZxe|?;GiF7u zt+xH}upVv#b1<(m3?D{YE}r&V5Iux7#mj2m4p=2l&Dwb5%od)0Ll%eabRgn97Q?)O z_#EQq8qze{7!c>|RK>NbvT%hH77hutm?kw@iNyn~U*Xee5&Y6c+SC#9-Z(U4Jl4}- z&|y(S4kl3^XwNE-cJS;DR`#Eem+|Ea(tgxii_%flZ(? zOv(d}^KA6}&lkL^f*zjw&d+#@;GKzdX+_L$DB@3$F#ASt@MHyrX~~eG@5bFGH!p#OQek+o;2_iCp(Gv6i6Wra;{l{kc=Msyxo$>g=fzmcbL%o zP6TA}%Q0lIk?la+ZuqPL?L=?rezpL;l!I^HWPvYDQ5wE^Um(1qRfu?dO1^pTQw5fe zLLUK&X_Oq{ZXrk-232RMxCSXRZvwS1K^~Ac&Qsk(T-CnLM)PYUrKpSmy$u)o$0_YC z?#|doV*}VE(Y^1TqBi3Dtb^2@;+Cxu1X{Uk%m;GJsod?;ybAzsR-s313940=)iM`F z%kJ^GRjT1?X#gN#hgT-pYqs?vBmsLc27=PrMUQog7d=@h0`^XfD$%^fTSPej9jH(a zVj@LBZct4-ruUI9g{4LCTxbTYu2cN9Z2kFpZ@T&v9Ff60Ig%BEh%3^OgV+hzV)afN ze8bW|NNuv7q`D2$y0sLt+r-Thc<&}|g1~z>adI0<8=2XQ)D9_FGG3xcmZN3##AS2J zAfd<7UW5I4@3xYAM_CRAPSdoH7&j+79;L|nu_+;=28oVtz zy&p+qkP}^+4E}=#^DKggc83N}2G|rWky>Tv|J9ofzr9e0*bcC&oJrlk=m4Y=M+1yK zR7f~(!o!zJrJSl0T;L3GRIV@51mlkSR^U+@yg3BMKH7(Akz=)a{KC#wF_S(iX(coPDI5=!escKUg>adAEezmw0Zy`R`!^l8; z`D*e^0#19@EtF)=;jTY$4u&`?VV_QTR+?u7V8SJrJez{~n0&Kz1Z@7w;*n-zNiL>N zf|r=Zx!BSGeqtI%WW--+zBCLmj~&`sj9D(6wBTJTxb7xf%SnJG5&Z&~1$Y4PxPL@! zH+#{-yZG$k_L<8RlceXV=o*tU(l+)sz==(%dvwY{7k1PQ+W@{{5 zG`yJK+x5uWSN9~5!?JF;kWMvAWx&}{&tZCc6c;~W&4}qymV7RBL)3p7bI0hux*mKe zyyxd4VEkLrd|;A2&K-|=E3n*qk^;h_Es(IpRtX?D0zB7XW+oVg-l)gQS}PfWc0|^d z^OfrL!m8VmJ}82N2r2d$;Qjz^vida`P3@0VmKu7*o>akK(m|p$k)E*e=8dTeL6)N3 zh-p)u4T&Jy(3F^kOAXTM2~yz%K@@@?6PXCr`O+uEXCq#w5mrC_hE```{h;MO)A6u;~5{)%rwO$Uf^<{+% zdya+y87cNstU5!DQ5=}!3o4>Y>j)$>`X}#~-+ui?m0;EK62ot=)vzDZ09Y%Uz+`%N zB4SCo!hTF)%N7U*U^mwrp!y{b@=cob&xy%VbQ0!z59WCq^BJ$wW$YLtnJa+mT0 zYgI9K#6AN5fcPoW&*DlgP$w3dhJ@I*M$c45<_wQEsYWcet1od#4J|^y%q={>JueYj zj}bh=lp2}?e7VNbiMz}Rtp!F(wjY^conv1u_6tw+K9@kU1Z`DQSF{Hy5*107u;|%f zYch(QG3Q>B2CyfkbgHJA&D3V8GFRaCl$@L@u{+1xRf*p2{qoz_s0L73jME)HJ$}Iv zS;$6LO6Mzr|F?`1a$F8 zHg`<)%=WTA{B4NeKTQnhAuHHwwmYFtmO{j zG|VxtmAFHLBjGG;KJH?NM%@nkGdf@5rX#GWjKy^`3jx6XvC(GWK^(*`$@4WAZy8y_ zyW5S9(eWuA#jmH$y%u*NS>swrJL7@jrca-SEW-AxF*ViMX~DD22oIrRQe|wGvg9ri zKg>(2&4|RNyttpNCj2@Md(6Z==EFu#zC5xnBXVG%?-5oe z>L_)g&+N-#V5QRj_!l^%SNuArqoOClU)m#J;Kl}I6B96UVM7S)&I2iFf-| z+HJoQt&E`2w;)(1?o2+n<6$Ysj)$dOqXEDnkJfy$(Qkc!C0^zB@a4`%JnO|}faue1 zY73qma>G_UZo&J*lN;bIglQ?YINO-lEdcfxHJ2aW1cm__P}6Z z`RY!`v-ZFV;wGf_0QWZd>i&k5*B^6*spu`09QLH!Q9U zu8ooxM%TudYY%Yf6#Q=O0g7+%w%P*&_`a(4058o5URHa68!Lk2Y7Y$L`)joa2J!u+ z+5_B55%kp_I3DlN%2nJT5qo+SO=rZOT16`pu_ssY2vBU1oNJ0bwudGsA7US*E!z8fmG#x|gW@r)ElG0s+AYXP^g zma8qS&NbC)3+tDDirF)LM|ACO4j`eR9j@nO@SrR-y{`_J{Wz2PIFS$AJNzC$jm}@u zN#n`Bx`*hTHM|~%mYSF?BlM`R4mOc+#)Z2pT@a6Yiuaz!S`S{Bq!27zy#Ih5A*DkRnb+{X*4rX^*5EZ z*fnrF)1+0f+2h*Xl@^tle*01xRbyQQcY73cR>H76R`UEtXFPP_B z-as}eVY~(N6XsykKkXKC@~C}p;`0=w&1~d$uFjHtJaH7_oOB$CzzK?B<|%=Ax!T5% zr?xS014C$G@MPJ!a28KtPRzu0CX=GaA&FM$LRfym9PEAh<#qwmj+E+kCB@T^RXZY= ziWYrnYzv-h4noJuyOvb-4V-T++86qZSz3oiaDuuw&sTR5>%MbwRq0Zp9sRlj#`Tq8 zk1O)AwkGVXeE|~|Gv4HWY-j3a-}jKj`!L*}vY0!ziQ%8|1~Hs#G-&$*>n70g&(k+B z)EEB2hJ*e@` zpNwR9h~5D7=r;iadi3l1Jp*s2uXwqqvj02IuCY2l#tD68xa?LqbtUkaETAFrb=j!B z741gp_AqSGZ}+ptR@(k0iOP!WZlQ;=^>MoxbpUon-=8;nuj$V-!YfgiSDJG(3%0F` z4=6h1i!35W=5r9ffi-h+G&QpXcW0@(^*%UZ6t8CGS_|ob5yS9mR451&&KiG_IuMFK zTlEuhSoK7l=!6~x?`Vo{4Cq=Dv%rL(+?ovU?X>UoR_Wg z5bWRBx*!u}d1mHNb8aCg=2+p)($$?4@^}=;EE{9^FX@Y!9Fp725S5*~R|Kmvo~#qH&8Dryi!rvmqUOejR~DQ5O_=KWCkt+G6V zDONTU>H?#jhTI|$QHL;Km@mTLBya&G6{WdA6@RS33U4T@MAs^Q50t?0r&L8919{Rs1fQ4z+?=F%7z&sb zt8w_8XA;pum=p8T_royngfU==G2s&Rjb>z=G2wFeW4tk;%>B67m@v)Q4-+Qln8wON zY}bl@kLgjT0xDKxPWS$4h(HduPCPLkqG?VYJ`pA1TmBd|<1I#It~%{%uFA&zV&tzG zQ>#zB#r;4+ZZYmZ#VlUkF}^T8S|seqHY@X#t)q#VQ7p$H|J$L;u)}FB^6Jb2v2kg4 zT3Cn|tY_>|EQ$R^ErK}bV&q)9>Tjbl=M*LwZR}^Y1ef!p?_ypadu?8%Ry#zkh8ZB-3qDxb~@*sjLjH(b%0RSw+;`+P_r@`dhMU+Og^!3N{;aW967g`Rk^pAXp}ngZZRIny~UV(3a;AaJbd=Z z$$61Z8t8(>Yu;=yI}gi-2L@m?2q`RDr_ERRBHU77WzJLW5V}FTa2?Cr-)FY7)!inL zR0BIbI`Ld$UV^@$zBd7S-z;9?_6I|_8G*fNGuMa9r$3Keo3rxL52;IYVfY`a1@^dj zhf%h9c6t01(Fm}8gj`O^i**Bx<8xP_>trs-hD6X9Lx+LOcbAGy7qfT?Cb`9lm3{>h zqYXHuNK_ciJ|+36BCgUny3>l#PxcQ{&bV}jy}YZ^52)jcW1uDaKD8Jh9k98w#ypng zr5`lTW(lHhPtKEpqT4^RU_iKFonKY&O8d{vs(LR$Sa+|m*M{2P_Cr3<=X)z5AFt90 zyWsa{CU1Qqd*vEhR8UF}Zmz%vmA6V4N!MX5d4~4tqT>F38h%j4aqF(^hI6=*R5&1Y*RBfPYDgN z7HoMO8o45S4dlT|$__ZWO>8?sa@&t=PwgyT1c2POzK{+*+UY2spWabC4|aGgbjj6# z2gjA;uo=G|$Enl>;ReQTxbt;Ef0wyp}1LRJ8BG=X!4h zsKSgL?=2C2=*bD`z*$k z*b@60X-#rswM{TIMEiG(?Gt_=DaE{kn;GP#sFOwQv&JGivtnWTK}c_7=3vBfvTsdS zxfo(xY+v{v5_XcluLQfn7TYnCsc@fntA1 z4ey%p>03S^y?7BKO^@zJpTsGh@Q)>i=t#htKz`p_<>2oU`!`CoqJKl@qRCotJ-QF& zGa{Z5(esN@VbL}$z`U7>;i)=I+E=gPeO4*yHRPzs)O{`N6Rkz=oeoj;7L}&hHcpcF zTASJIr1-Z#k`!Yo$95%f1@xgA$aECK6CY9`gpPOb5;k$IC3>9bXv{`Bpetb*VTfZC zfh{x7%&Hp%Vy`p_P0=;%keCC^F%IF2Kp2w+6+OYPHsN$THY5hJ%nQryJHRL${}_(* zDJU$SqTyO`QD^8aBh46}=~NH54NRpQ+tWAQLSz#MM)Cso14l_0M#}sy9~Oe_SnN$e zdcrxu^KdxkICJtR#$anQdR{#Sx=rU=4}3Bb*BHI`i614NU2w46?nYrk=*g6`orKFF zv4U3&wppFUyHP#Ug2%nK!zkV@XKp%+g+ZaY=-d=+E~8;k+inm#Ht3{(7(`5<_5k{6 zJ!qjuhO)~rH-(Ah8;OMEsgXQz5rI{BK?t1$oABb@#yy$VxQCeB6OF2@=uF58%2Ew) zZ(gLN05>*sH6L^PetYzz9O&6R?S^`p6}=4sJbX{$Pq610__Knw{-3~~8A9g>{JDro z$IPE%t%$t*InnHwKefAgD2*M|FnS2+N8`5f)mY2$Cl+7^=zUWEShaK zn%RBz)!`I&8caz}&NjzG;wTu(8iF-Bou{)oDUNb6x_k|^ak*~)akK%P`_Q@_#}%xD z1yg!-!vjGLXkBHS0O0Tr6t231#Hi>tD|TSk&nVtylx{U%8(F&D4DYfEUmY2G+bZ6H z{rt)To*4D<&3l>6TWPyl(JhmM%cu{uXyUNVTXgVgU zdHP>d*3GGzM)&JGaA8=zgevYbRlrMNH|P_RosfA6?2V20)omuaq{6&J0;w34{YRs; zodfoY_WA+7I+-U`c04M&K;ZZRQ|k9t*Qx{7rkrX<=8aG{#+TBcc>OO}HmqqQ&#_x% zg%MgAJRi5X9iL-1votU&FehhDh#bhrjU|bb%ALwkhPs!4LoT_R0{d=ae=tM1ENsQT zH@AXN7m$qoBjF4! zGcV1wGCPX8Xr%B%U)@UVKt+Gd*l&utr~=sUUtiD#MHF6SgqqOGN7_$QCJEQs$0f}1 z`RcDgKulqnauEj@YA7>p1C_ZpWxx&%h^g)ck{dmZaE;pJp-lC47PG)0o^^)0lBl>w z-MDRp8VdGfIvEp^Ml+{k4ViAV3fGO4nOQ8dLNJ>-6YZP#Tad8Sz1#KN0HW-`S#ran z(Y%Q{ukR)tV@-|5rCPI@$gLualQWI=um1^Vwwvi=h#@&s1%+A{BMOiMoZlCFW01G{ zLFzhOU)?$EAX|(@TNI+yxk0q(`0DneCYu&x#3*c1B%W{FpXsaH04O9BQx@v_#A}ct zvyF3#hFpPVwh&TcN=_q(@{Q&z=_glR8g0|)77SnAjY6LgN3P}SO-Horxr@w@OIJ|` ziQ9HLAjgj}Me9HzX(M}>8IZ)0Zk5%zE0 zcv*cUURKTMm&H#hONnKTSsyDIc(!5l7juP1#Xspgh>Yq zXlS=pVM8=4Hu>h&f}&Nr!@{&;MK>mfIk{cYP97DbU)E(-Y)DZTFoRpM9doH@9ZW2K zipXL1UF0p?9SlM%q6;q#k@9z%lF3|FbQMAHs}!n%NMEeEiQVq-E;h=i7`)hbywP** zbsN`brXd{;pG&*Q8D92gyXmpw>R7I7j%-> zhlWP%OiYcjgEB_DM8p0ecxb$xMe+To@5`a>6&Xy%plk!IvEO2_gSx|4R|EE&v$D8Gb%?f9 z-|#&o`vMM(g#4hMmcC7+?q?OfW`xi`+J4{FFg$1+Dl0E|BT#8iLPDS(Fsd;QVr{>8 zS2}u>Z(!_%nQDj>2T%q3D(!q>6~qyuhRe8jTjQRSv7G&VCAqqeyljPbmjy;vY)2jW z8tRA%#e$WN37G(apq1MMJHc|H1CGaUst1C=ksx5E`!fTvUve#S7Yb^BK^NyPyV0Gu zLOHWDtdN~CP+NI6inrn-MP{4#=az9nsM`*M9LfP#9%O{OA%Ipz4<_A*RwI()UDskJ z^*ZDVhnRb0OgNR1BXxa@3A+g|-s+4Acd0SqsgNyqOz3Y^WsZpirJM7sKrXzC3c0x3 z^hIw3wj;lzpoE?ByY){fKU_W!^}01Uk&EpWn54&IHI_!U+UKFhm;u>sRF##oyj}&{ zEx5TlVE_iSm{W@I7e2@6CqB-nh2bDz^BUX+- zqCPpWpoab01G`?snmw?~6-25rY*LY<$ z%-eSFd(+8w&koGhY@{A3?W&rg;(+is)^bM03S?SSGt2$|r5JqgRslx!g48VA47q-YCi&!iI7wR`wFEOzb@19H}v|(&`1N4@` zb`LEm*3g9AO)32L&D%yvPUg99-ZKJB;=6BNJ%K|Z8SWvXs+-KxZWy5*i^jRM+juqf z6EnPtcQ}SNfJIO-&of*r7JPCoSTI$7~!taH=z~cp%u`bOZ_-C zT4`^2khK8QO<4D6HO}ssn8`ht(Brzkplg93<@Wo!TOo%yc&8oqOes5$CYBp7Fz?B! z{VQ{)^B7({x9GFv5naK>^;_m1S5&L zI~xJ}-*obUi%msCft#-G-EponwF+UWVzJyLyckkoWp|>%{o+HP#@E@Wp=$VEXvZ~x zFy^$>tjtD{MqAJ+cJD%!z)K|X5;yP;R4q4fGzfg`%X_IEo5Lz+-0E3cHg`Y9eNyRR zwWm_gr-og9yAO-P)VEkK=?R{}y{52XfgJYOKmIN{D%ZkJ`^?-*yS7f$6x8xQO!8=3 zN6xeYXM8%E~j&|brLZAu?&1W?tTd5%Pfm;!V;hS{IY!KBzA z?7Nvv+n)6sF^z%3ObdOrbG$grp`0-us?4rqt{61~Q$$W`(61$Sn!gNdk(IWO-5DRv z&kr)ope3@fmxNT?gU9o#l`O1K>@!Z(o>&d!&EY4&b|n1Zq@Uc&B(@|2_Oom|*}TNh z#rpic=)-|lY*%8A`VO*Sj@wIK{9j~i4lg-IU%$s!$DN(^d#ykZEhuH-a;zusSE}_R z>?wn)Y)1isBpMPagGhT04nAR195w`CeW}%+1$2}~XthZTwBQW`#yc{xqz|^}N$h22=`xf#Zot3~_B`Pe**yeTX-Y-IGT?@CXqN!z zps@6k!|qA(1}F`Tnz2gX5gd+Kz^yX7crFr)A=Z`9SeR;qB(i;yDw?Ax%3)mC&&C#x z5azd**z1uk6Ac1JIxyygJ*Q6?6$`O8rdGv*mzkj^FdZr=V4sV!CkJ4p`3^RRp(aoE zlltugBgIWQG3+E_<`=696pP_b0NgH$Dg4aP7uVgq48txeP25JEfqQ6u1{$Wytmw9$snf?o&%CDg!kBgEnQ@CpAs10C0q4%t1@S7#S&wiQL%{Ih?k*`pG>}j?@EK) zOA#C)?KChHKG;U;w?87g!0>er;9Uifz0=^8(J32v*@vSXAd}xwR3sg#i5P4bqV7g{ z7|@}&Ku7Rrl)`WE_lE?fVVY8LQ}jDhtg(;W@$-WiT{v3vLKuzI36E*Y~ z)_2Bdu{oD}#{25^747jwE@ZP^yu{4GK!OWOZ2D6T>16Il)8AuM)ELFftO|}XDwbtn z>8XKL)WF`=dT#SqbqWW@G0H$SU5QPwsHJuG@9rZTRSjNDaSG*>2aJk3yNP>7 z5{bYj2m}on;W~Sf1UiK`=qflCyI0x+05!4O;A|*y*9<{w&T_j^X#3s@jWA0eg|T`w zv}9!Iqd41!sbBQktZ@yT9?3%aIcmwhu>$Pps#U=LfzraUHfe1iWo_fc(v9~}CYPA! zA_8o{G(t7eK@eXl&c)cDRcXI=FLh4o;%lL8uz_Jyz+MXoFYvwxcfy3ajm=j<>6m`B z?pryuD7T+v2q^T$#)s%NN7fI+FciCrclhmkhD2s3W*Ws$j4aO9g;R*`dk?$sZ}7_d z53R!PeSbs~gCt=<`|uN@F0pF&dzKB@SMUb*0B|cz=@SKeWIMp`9w6NuEFbR3K#}7n zme7)POyPu{D8ON_2azG;!;ux)xEsMNegZq+v50MDVwkWVPh%a&3`hYk{y>aaN-AAg zbuSnY`5-TH=b}6`MvLrgLaddj1Q;+VtveZz=@>Bpb|sEyn}KY@kJVc2I^~#Ql!K2U zoq@aBU$LeP10($9_DS%Gmo9|*mB^|ehvXY-9$%igLcy8V$9~c00+oKOy_cg`Y;R|S zSiD2j0K#Hah7M+8Aa<+T0GI$w!V#UMq1#v0F)|m!H~)7?3v!CBcK?MzEQm&5av>WP zB=(9z__hB0rTYAp{%mBMJ^+PMS@0pQ{CvXx&)F1?oPs@`Lj&ABfm)%a0DwzG)C&7P zXb&s*V-{<{hnOSaTmT9#kcp*YBFI&ZSf{Vdv5H#_Su}wPN@|I&W)~p^_Dvb0uGLzY z+i9w@RXY%{UuI(oWhk4W{q`Ifpu%xDi3V6hCN0d+2N)pR*Ow>JWt5ETy8z( zN4N>4B(anG2c4nyO}czsz(id>E+Ai*j|1?{=Ug>Y5o&U5VZ-USzphjBs`B&OU(|r7 z9YD4Qm@408_DfPj8nF2rrHrlbIQYCRc!!%25h~#J8lNsl+4LHpJ|w`T@oCk!Q^ux6 zX!>PrT4$6l#n|*`Si!_h0*AX#?cPBi_}PuIm$thzR_ z=b0}J8?9mUJ+Ln-m<&Z_{z2m&r{U*;kJv+M*F!j?A3?;`oI>sHx0#bt7+0WTm!h87@BR5*5a+-qs{|KA+(CL1Ge?$e z>bn6_%W78cer1eZj|Vy@Wg$Un#x`(c^u~Sf=q)3`Q?2Yz=}~ZidYiites#OB%vfh- ziVw`=Ax2E+561L6YNR5|Rg}ss)HuJg?*V(R;%be}#PvLtVm;yj z7G6+txSGQV46~~8V1@X1C>Vv-I5pp_9NsV`-v|shu?@0vlrd$55g27oJOHT z2IOv=>@8LyG&dTFR}4&F_|iAy!`MuQZQ1uny@;y!x^))I&bQ#dCzK33nFFw&W+o(U zy(tSgOz2#!0*f9pt?S80ZU*s_k5=|WW(z?u$wkctTWCxUxcCc{_EpoBr)g0EnEo8| zewvOjTbMDh(WuHbac#z{U?e7pj1McZRkYl$z5^LnA=-%8=+8Ir8QxHtZ_F8P`bU`e zj56z`&8i$>%o$~3qy9aGSn4z86k7K*8I@=0wk*TCAFbAw{u(k^C1jdpWeTIEyHQ;t zAB>6obqq#J7ScZbO0;F=nEmqGccIsU)(uuM&{|E+!FF_9aAO7XcoW*xJTzzD27cod zTtPRyVQRinIo!n7*T5)a>IkE9lsV-rGf)U78dJ|QDhuNhZR`=Loy;BdI99stQ$Yf8 zU|b^XM0Yn}??rduI-D@aaO_I7)kY5<^ZlThcJimRd zLYJeAm@5$-ge|z|xf55agH+h%N_>yewQqZ;tZGC3qy@9EMM1tydEz8>Jr^vgGko>j zd#Zb~0xd(4SQT}Z<%U`bZ@w6)_Akij3N#NeMym|17_#8)tNW7DaH`gp+wHdj(W$S{ zajKe*EXhpj&AEv+n#X~>mD{6MPt7*2zH7y1yn$gj7zJJT$7B^qm8UuedmNS5dW);_ zlur-qCp4VT!1fuf=2{q8{Ju<#VY8qjuTlw}ZqCM)Hsj%A+=H7za*ca(&Dq0@dxjwa z9eL1!0cem8?1I}hgVH9IxsB+D7dQ$%s^io`a95FsR7KW}@hfG=WKiD8UPEmE*cVgQ zq;f;$=*A|54IiU`!db%e4B0x+G*%$Kx>r$v+$CI@XS8r#KV<}_&fO_#=ABQ75EC`a zSwPV1SaGi(jzA-u`Q*i5eJjsbkPi$lz9HSFWU-EPj)`*hT7;De@Y~O70mind-&4K{ z-hd~1pL{mto3Y4Ha;t z05OM+GXi2lNjEGQQcTH`>z%A|DqXN+j~+%wWx)RNES02ZaQ}oRsmM^YfMI|8CKfw& zE{jwuiFrY^>l2ilY?8tF9&?afzjRO6$TSdkeWHBHAbTdd7Kjk@Ax+R~WWc*HeG4D6 z$aqCj;Rvt4v1@MkzPEz^k*Y3W{~v8Nh(*84w29Wzw4{f@(dB)a_L^G-$;1S{bOU0| z3Mu++gi=nl!=^Mgm{j3mJNdqz$vamQ#MBKYuKFA-vp9n7sfi2NB`R^TpCM&RM?O3--IVpX@3Dp)XEbLdmyXe;F07JXL1oVRmdu1hEdO*J-ne9n!axx-w3%( z((z9~cO0dT|CTA;5?FOenQ~Eu&A6jO4oQ`OrvIsy_IG=8X9QY2%E5A}2ujlj6?*hK zP|>a0DY}4?WAn}bi5`hXe+h@~Q7ERK65HaimpaNEgUM8Enm1(2kW+t^>DbAlx*ZvP z0V&cuSwtNnbw#fj&D^GAZ1dIq2bB#@IoC6-Xon`{r8INCdGET6O{kmkH-qX_DO6mo zIY4c*IlQWQu(zryHzggB^dFTh}HIO%m#E$%!c5kac9s}IoEYArdiJJoG7E6&}^j>6=bG2o*i87gfZ9KGF){7t-_Nr^K&V&ik2}l%BD($&| zI=sN{2y9exm!2M6kDWw^g5LmMz}^8;vKWIH>bK~gPw0!ha9yqa3^8!i7LE*LGug6Z z=H>GEx1cox_HZU|2$y;WrY!XgZt|}6DBnKUdN4r(>wvfy$VuxctY=|&v+NDS{mig= z;*{NQ)^UeGPViDrzn+C5Zm3(ywoSw1TvxNm~^F#ylQnD9lE!gcYsocu86y_vO#L$e~-bk#W zVIPRQ597Laa9OsW1+Rv{U(WEA_DqPEEMS#mQ(C!wH9k4Ln6w`OqqQ8rJzg-~{RjXK z^V=f?WG~ibb;BF0g7=0=%qIW=OqH~Zc>SioR zcR)C$zk_d_`+Wp;?swOdKI&X1y0(rSv(7n^d%{|mr*}eoU{s4mUkfuBsM-~_%qc;L zA6G&gK(~B%x!r&-j7X>Ao_1WBkp=6J5MWeyjE4o!tjsk6xtO@cVH3Z76<}CR#sD6f z8(V?d?kwYt(9c~><1OoiBDfbDkWn4D2E7%@4c>|d>}tga*q4ShVkK|uRWh@V!MJ@h zAgE5$&B>Tr$9?mYk+5vzHOwjdF|}N77c<0Fv}ZLLrYdvkGYme%%I%SqY$^Y#p&x>; zt|q}sSOC+fDE#i!!oMADJodk&h{VOR+SaS=q3>k;#j?kgc$R(XwUPV%6J_6FzedTX9?e1*(kXjyee&TJ zGF_jpPt>PVA(DEEgZ1eIe1dbBulMZlQT3_kDq^P8r~d*F{Imkx*~8*~BlJ_sCx`h* zs#N6bXQ)&8XelEb+&Z;~bqRIq(kq#7RfW!19sER{8l?elonrqQp<+j0r|xI@u}-Z( z{0YAH*Eam(CDk^}^|TFsqz~0)MnUDC(q(8Jv(H#23997g9-_RXCk zjY%Q|8mPS35-H#=*#8q5$cer004~!2bruvD=V`#t9gG4EsJBlGh@@aNa>q20?!E%Dhy54yb>2j86LaD?#2noWr*gd`uIPt+b=m<@>kttOO!4*~(DiedYnxW3 zEDoVFr=_nE167J@FwmLAHA|bRT){lg|->-zMaU^6Gh8774$%cd&d;d3N zWDE*{Ros=4uWEoRBd2J9DeJ=<7c@FAyH#%;kFKCAGcUM|_kI}NZA^uvAcV1o?} zIG$x-=jYt4f_<=WgmZE@kZBcSf9O7(cr-rbW>M@M-G>{8U>4|+S{{@NZQ{-}>=AF} z-qK9$E$z^IOZTta;Y&yJz0ArzwC}C46&rjHT_M$M1Fw_AIlxvNPW0@*9Sk;lHf;SJ z<%!n0ul=_>lFMK1zx^$MaU8uA6F_?ZZ9DegB2%-l0e0Eg@G`ys_9oe4vtkXqy}kF} z@?3tZ?!Grwcl%S;HqV0ckhRTaYTxZIa83oAXg6`~9*#j)_6kf%b9pzhDuA7pemf+h zloMMkf&;)!8t`KWaD@UyY3a~`U8rF)?S(!_rkda6J_kKvm%3ks`=7bzc_sIpmaeYC z6@_f5AD<>XN8dy?<~@Q>vywc=&^o|TH+q}s17pGG4#7+`)Kj?Uxe~xQ4%8H{hODFc z0^94!bDS>4oL;Dln`CkD2YZl*;7mKVdto0h*6ne~vSQiDidITw;TDLWm5qxvUNH`F zv&TNp;TIl6r&7=NWAhTyU9cHjpi0vP@TfqMpw_F zK4L7r!5vG7HaH`a`=6uM!%c(*tOe*$j6vHN#-`!}(vEP*H>V8i#W*96BNA%y1S9p* zR@u_Ny4POi+-_&OAiO$xsl;6^?qiv_u2i_^E)y5*=h|?^YHM7r@j#X=7K8PEF}}s6 z;jMnC;p=F93}bmLA%xr2k|5Rtu`0;*K&%QLD2MR-?bfN_bZI-5NE)z!iRIv`5xCQh z>w@>gG0KE753B`;aBaQxr7kf1g|OkU0W*Bo92nQa_R$T-XwDUcHej2NT%MFXUx0Bd z;^&t46hl$Ic{EEY-L-ewdGvPIRyK_duk_W)(QLJF5?TQYQvES4ruO7LCc!z=mYBx8 zAElvJO^P9|%Z@ZZ-S2vdEF-XCK>e;$oq4hU(`()_w9L*F5zdLN#Mr{A?qw>BY{|1P zx}2>5dvZk@Ohbn}W!Hg=?2fRY09$T-$Z@4Tk4+2e)Q{k+rpZy_SUEyz!iELLTz9f) zm31{NQ&p_Sf}p&Vb6gp)1QyjN$))_6s$ovVJ3stzjcP zd)C20*sf&{Gtx06{u~Z&M009)a>3FVf{&ZUg7ygA5Q+g>^&`EbO(v2M17XTZxewY;Gc^B9KkaxOF1R@2- zAa@vwSv6M|^``gn(~90RD4)+n4`qc)Rn!$g`hvMu8KxhNiJutVMO{{TX6QqsIP2Pt zFSAT(Q8mCm3Gh<($9Dn6Ow$8t1Xl&my})d&p}!m};qkN# zm>cN#Oi6K1_;Z+5#-WmdMa8=x{AQD!C#fH*8g*p!!6`bUnA2vQ%0%P@>ne zikJ3ar{_qTD1j9Vtaa^{jhnm8QX4t8GS^}I^b1f~?n#N*kCF~aX!Cpvct`^F=Ppb1 zAz2nqLA?GeoVkJhxgO*#E%X&M4$z6115<_o?cX4nGIZip2k^|wReO;RqRPu=n$sq6 zs=o(Wh^-Ns$Nc$a=qmt#s{94d-X+W6#ol`%CIf?u_ z5;=1?PtvuN0DV2^!WKnv@F%MVA=SpVzp1%SYKLB7Kl~-aqM6UO?@tMf+f{mny&|&P z9oM!pWUf6C!5HEG9%DW4z=h>VV={J{Dyw0LPf|I(c3lJTYs1;xbP*h|@nu>x5A8Q= zN1-f#4XdSTO_S9j4t?Sy(w-GL7!SQ4Q?u_NFbM=I%-V}t_>axS)5tOYEN85xu4$Lp zI72dLFru01_5(mf`c&SpD06sr@E7SY9|mPRdSfJ2R zR1K*;c&-HE%~MscSr5e}@cF(+sEW;n5u2%eEB>d}FCd24%2u&R{&cHY9e=8ox4p-n zY^6oj*rL|siSk%$7GI66oM(zfTC4FT-SyUC07Pk+yp@K&Wj9YNEt^YA-pWY_*<9aB z8{|An#*&WyH`3F3CMoW2rM8LvxpgF8e{B6aU)yMGZXAdR{E5&+5upSv75`{(Jnq#>I!5*(~;?IB(J)~BIFLm!~%lnBH}m)q|_oxz?i z>Qq9G&qjEWV-TT%YSDXvpy*=Iuo^{UIO;mM9lZ4Eh_gUgAx;JO5lesL?o_lUWGXy$;?ao8VyA(R#R z+P+RQ2(liC*Bt!(oZ})L*GpL$J(Vyy@3%iiJLhQBrg-<#^x$!8u}Ld!>44zC+E*EN zX=d=(wXc$^vFDICN3Xf@o|+Ob`q^5G`|3@EN6e9fC(QYVwT7~2&54iRQhVsDaNZ}Y zjMp07To{tQwxOO%`wk??SdXe-@3u9Z5_wpJ>}3u~n+EMF`2 zW9eFoeC#J{8At2~Yborp1#2nku}9ZR{iw&7jrkjd)ae`!sx9qNS@hLafN}T~>EUK) z(U&xy=zC#(1lJynGwULGFb0smJ-*`>G}pJF12OIwB2ee} zUg(Y-Jgxe4SS1U75mFGpC)=8MJ=Sy4;Nrj=I!`^?Xq)on`NW;d8NVkhw$1mVA18mZ z%JIgm)X7kav96kf#|2MqymSEIz8Ch4-dJ;RU;v8BZ{If_-oJp4HQ|$S>2uzxIglAV z1=j@5m%&N=c{=Q$Oa@Y2Ji?Edjk1*3Xe`ct<6OsM%NHy`_chXh!L~K) z6Lb70k^S-D5R}yinelEci|&tyum~Y-f*a%n1Sz)%a|rY8Pd0M!bJ*X7@ExC)){ehf z6JZJw@0AzT*3^u>;e>C&ulgdu_y>2-#FmvSFEkn&#-*hd0ygWSi*C5%Zkv5?Fn`ulP8Sk21(sJf(+8XYRB<^&s%3H&iZ?}AHCI%)_yRL5dLtq|H*!mC1yy{jAS$E zj6>3&qbSBD%bthkQe6XwQVpVGm>K>nB0_@;C}uHF1)&BoQ+aOrA<((np_# zCHM>?Vcd}XcBqgTG2Dj$`h6%u{d)KBQB5x$nt8!bKAnigQ~dRV-idFQu;9}}{9KGw zYzNJGJLoEuq{VSMZ#RmgbyN!(jjeMd#3XCN^F$_9g0(j@pZLM;{?};Ew;*b42GK+v z?*zcXA(GB(B7&oLRVRXjq9Ur(DjC!dCk}~CQP)lv*^?#53#r!>lRd@XCFMHYR0Gl* z==vVXQSCu+D5=5%RRQpUKNSfb`X^5Hjc3Y#!AW2^j3Go}I&Xofht9r=&57k0-qj34 zlIjJQOPLTAnG?T@Dd;+g1QZIyW~m4TIuwR-iKl`%MBUt}c*N6js=x~L8K2dC;P*og z;8Y*?+jaCo?r@-E4R<)2)qQyO7mwz9A0hs=K-JaNY52#d{M1W-xL`p^U?p%B%=Jlf zD3XHP&jVob>GO50eCn%|j+NHGNVxx_vP9Jbz8#?gAWN=pQs{hYpr|f!lUU*lAi+^V zorn_AX@~}BvMPuqCqc;}>(J9=B?3vm&VPtI#io!M(xIlv=%+?^ zDC;*~>c1v}p!9KIF3lt$Klsx?Is_yyxRTz2=U_UX61>-=n%;@PB&z-s6E02J`A{I& zCxJm!^+#grpS%(zBo>#T^W_9{J>1|-heJ|P_eP@AK=LU+WXX*mE)XFZhQ&`_@K!L# zhi`&hM1DHxiWr~xFE61(f6teMC6PohK~TYTNRn_7=#%uvkbVEERm6D8PlpmpiiFT- zSOwE@=$8U25^jv}Q>jOSoIoU=AmPB>APybAb#TEs)+{M*N#r^yPE>@cNZc$*F=;#g;lY^&Di+RBy{A7FHcm0s(gf+4k#}np~xhNsz@}+Uax8=(q2CQLx964=kSqA zSUe6-qx$ef{s(+j{WvDVI;cwlC94ZJiJa=$C3m&@>USwvZy!Pue%e2ooEL%7CD4=I zeTMQN!^toGa>FKN2Ot0YrIeb2fBJW|E0?YVaX4Y$L;_r_5avO^a@#> zNWRBUC)!E7yd`SK<-z?&oFwP`X*#NYNIb_#x!MiqrJ~&q$a(AHOMJS4dpnLAiHII# z<@5l0lRg5ZTKp+sN_V&}$3d`o@uj3h0UQK|OoS#18SO!4iix4#;#NokBV7J;Liw2l z(D0*wRcllotEQj$0>Jy>b*Ff^pMt|wI{%%w1}H?wn?UvFqG`asWu)45;J8TN70d1y@j=9`~jE zk^(0D+&sEiB8Qr|Lr_Ib6!~L9@Z+cR6z6AtR7(gY{6ZWLe#t`t5=nJk^yh#5=8IvR zK#G71WEA4dmv-n#5R-kS`IDIbZOX)6@?mju4DeaZ`6hN^D6*td=6&`_=_rAq16k%% zYEeok<)wgqBEYLZxI?O1s~)eO@l+q8c`_r^#9INGJdLdgNP@+weR_i#hBW(38G!sL zPbUtY)&wb)rW9`{M`_i{qxaLn&{0T40t0FyH7;2?dJz#+21;_shsu@^?DZf5{8N7l zqTz`oq@p29655NNO3dqr@c2y7)3^%YMWoyL(_t95#;3FYACO3p2@?`@0$YVua6#yY zLbZcPe{o9|z1TudqwNbS+*9#LDD6xkBA+hIbx2I=!7NGqeDLS-6T*xfK;`995Jw8GCuFsYsA%Am z5TT^eyci0Unk9|yMRW+bFxR1}^3^L79zXGy{HPQqo_$gB2CP`DG~hsLnH_I7yL@e(!XE| zKYNnUv2wd$aInwid1xk@<2mIOSA04*J5+jsI-4rPZo{~r^Kc#Z`?1Qp5FCKpe)&z7Q z`Em&eedmiG;^tHS7?ptJ;ou$VUF{+;nCDM&p|YY;gf1R^-Q2n_P zBso-ni2uLC$$Ml;7r{}zL=kCqBr1Uquq^p02pTSa$g1#!55oC7(p!)enl8A*yj(BD z^I5W_!%6DAZk=AIBqiNUv-)#h&O71bVD$NRa+DwfG}7qxQUKu){FxwG$aH7$p#e&bcmu=sy;FR;Q%l@=(0B)J`G z&RerD5v7|}H<3VP61?BqtrF*^Ua(TXB<&<19w;TI$*B#19p=lCeigf$2$ht?Q#^>H z{{&qn!{vugl}bcXRupj^MyJw2)1gvdo|q7hSyG8Px|d+-v?kn&rt{R^o`}S$BS`h_ z_ZuDzqW^U0K3^IM{37;e&Jqh0!6Y~fR26ILQxLST`02E%1PTdF#39!EE%6|L#3k4| z=H4$w79@z?YaWmAqxq5Uzv{30m=gA{oFf#I{Eq%rorJ1BQlI?x{v|qW3Nz7>JHmI0 zxBl$wB{2Osrc(Ns4pc353rVCb;g2=mNwDkC0R7FE8lh~?DCX!I4)o_2gwheG$GU{Ifhmq%+s;`s*g6 zpY}f-S|3zhP_^qiyyIBuAD(J2Ux`M=b?h;+i|6ei_5Re5evmLO76Scv_ag4}@A}2} zq^7!8mX8*2>>-afhW|70{vRJyIk|ioyXS_@PbHPz($kYZJs;EmK0PgMdOVE(gbwQL z7n9zN$z%!o*ZV0xH10fk><4FVc5*dcQZ9U09*^T=&@0GzTH4r;efTfXyT#fL_uF)eL5IX0c?dA$#-5V|e<`laV>H0zbwo*$1v8A=^&&$U~oe zK($~%$`ClHGwV3`oo&|YtXltOQ$?CM`1Tywnodb@mZ zJ(o>qK_S_!7fK$S8s7N#C!Ls8wv+_8`k^mA5a#5<&8%DMU@I~%EMUEWT(Ht;wIlj! z`QN7li5L_|47p{f)Z0Cw2mkmu*fg9k*;O8IyySCV)CABqni|Hd#RLcW)tuCk00 zg=9iUu*zk}sMAz2oJ*wah^|yVX!U@!LRcla(n4tc zKmkT6kg9-HyO|P+Eq*(Hvfg>|8lfw+n42gwehGuA{ zWoh|Ync2&LURL(luTg}B#h{#gt7l^w?(4)d03F|@>9h9tklrBD<6gVDV6Hj{5YqyK@4Yx#V zEi>FA(znN@26obGc1ysb=t5`IQ`h@!abBfCIx}+6GHH$EvEgw`qB6vOVr9oJ%Q5H> zkY|w#Xbc?^CqQHhJ_zEegL9K)L*N&Pr$GOD;A##G#TMVi)dY|prpOhGI4RL>;NHZo ztjJ5>t$!!!`j;=waxRw9A>ufQ@}MG}GHDhBojamzKvJ5p3`w&h(3s6Ag@mNF05xs_ z&#P`{DR@Fv)-$7$**wCzgjfU$!1vfO2FfJ^gNx4%kJphsv`l zx9fBe>byz@%tpAHmhr)Waoks3=$v-DFT~ss?SZ9O>1N4 zN?ahj3xb#cdg88<#DG7_VSH5GdnYxw+mdaF%E7;bP{x&zgUlo?p2-XB}e^#J3hw%#@=f^vPAiBVAw zmNx}2;~U? zC%Hpm*Hrkk^^6FdW1!{mh4Wb@sr2l@ob9_rmE{nhVac@Mq!Yc+>5U00Yn|?iRbiIF z+))hRPp7uFj5`(Bspw=l zv=?q*0KrKCF7+Rng}f@ufy0W66XUEn`O^epmx~d&}$sH z?ouAE=yXIePX{gFQ@X=&YvH}>ArF~B=jdia?lN$;h-lV%mfp**hbf%(@NEc7 zi9RuFaA!iodZJO0GD$bo=VT!gfbeG9$ZxFD7EvLs^h7;CMFEKLx1V>ku*njDJ&=S4jVKrvMd)1K@^ zz9Gj5TW@YG=s9l(IndOqijz-ii+5(|du>s+T~XW}MS%Vas+K2`AcB!)rx{t2A_8my z?CA@k467dHo)VqAbM}hc#RkfQJS`U0a?krCA9>aKk$f(_O4hRe%fWIYksW*C3#uZ1`;VFo-Z8%U$b z_ScVIdlWfa;LE|S7q8tegh5gcYiVoH7R^6b9xe*(rc48>36eC|(0~-m8cTdUkkQl4GX)mFh- zPxl*nu1DMeB-R@kBY7PxNhK)trK9DL!ysTwF=!Lc}~qNA4KSr5oD6Bu)|(Sl*E<^V>+7;?GSs~tK>88 z9H2XwKlI3#99N|{5p@Mo#`Zx43zjj@D~aY|2-Mz^`k;k;N*uk4u0^r^v-`<1a^UkP zuiYpKxlUR`*Lj7!(_Fr95pN=g*{g2H`HSr4>pw-1s0m#{Qi!O_{(Tuo+FOs8x#QbJWC*+xFR9hzyL)yUmn2gv2k4!wL6_i-1?V#; z6r^AuD*4peGEM@#3AfD2#77fBT0Kd$mn8?W4}5A)v10@{p*Vx=V>T-X8Ur@&%|4x? zUWu1Xv?}zr%;$HIc;cV~C+TI}ccm_8P2i!6@MVJ2jCs^`cb1T?>O)dLK{<8a<=Rp? zI6L7=5!+YM@!;9bD3}FNi?aHlXFWc99;Y5@CedQeo+HMCLjgI62xJz}kjK=;4x_+R z2iOPOK#azQogOpoU77j-IMe|(@BkhLQ%+1^%DE@NywKJhJ+Bq3h+c`8^xBkUV(iku zbRLQ(LXP!;7%_F%azYMzsO6!Fx=Lq|TD5+E*mO)Mm0=kOW9gb^@&*`7$Ky$)OBCD)`tw z&_u_2teyfVv|Dm18G0==89K>W;;ryy+Nq_O^sJTE^@0V?W(g0{GWwmCLy9_7!8$>B zk4MhuQV9Q$*|dM@4!qD=S-<}wJDt@jyG?bQSnguIy={~MnnOv(E*EWglZZ)hoO3A` z$F(GdVu2{Q^scRGxnI>X>D5j5&&Ob=>=h+k!9QvISC)f1L0kUHt=2HMHFCtA)L-+G z7oGl^4XPZh)5pcj`oxw80bm6YIdBESYCKzf3L?mg$V%AB%4xK%RT4#r5d?0YtZr_* zF8cs3rgDCx>$XD{mr!_fC1S*-eL;7{vdM9-u$SRFj@F#3YkeD6OX3nakOg%)2xnC| ziy{YM&i`mjUsu#STqU<^C+JHiiO3=>$jX(K0~|D6qn%tlA{63<@*-$lxI#87a0tEg z0SpFMusg&=h7F<<@)9L!sE-#@Ln@vZ98)+y>RpIu#2cjRUb#ySl5`v_Zsu#Kq8TEG zJ4Oz?F3|uoD{d!ke5XfuMlX7tBDlEUlmqbMaTmcr7wPv<4*G1v5}<-g!|TnvyUb;J zu1|{5aQGSbQod`xG*&r)B0TaH7h?Nvy(~6Por62cmsMq6KtE$I(cryw;(`Ty5sp5v zT@Xo23w7nIc$V{b1oT1$=mYhY7yEAOMY=0G1Glrf9N_uu)|D)fQB^<59E<^w@j*EX ztRjen9V;5!c_GhR`4Wk^xrkXwhA*~QWKj;6v?hks?iyzEv_u|MzjmQ)8>0S+8@&d+~Db02p} zd%}BUA0Q)nnZ`0?ud3zc}gA_5npuP29y!>TZx-$AIAL1}g`Sj?8TK0^gSme5{ebT;g_k2|i*u;L8B8 z>Qu+g3u||%ZhSXGNecykUO1A;d12+C^MVqL=Y^|~Jl>5;B@xMi61B9F7@EV>wey0A z;M6fGb==7ssI8K3D}2)$lZ)hF?Sma3wUeA#N{4blD^{7cI#tHm$%vqDCmrt`2@Kxm zrSVuRel&lg>VATq)9rp`Ibe0Oc9N@tXs~FBh(m-)st^Ko4q8NeTcVkf97K2VX%Fp| znil2Bmjg80Kf5Sh4*hO;>6#I}I<%7yhg%*HD_2n;;!1Ybss|w%ku*tYSu~t}52e1! zK}pHHh^hK165vUEa^;0OsIm7^v(hyq`jw-hOwJ3Z^*(C<(_144=#{r__P^~a6f)(Y zzo}ED=C**j_q3rTvU}77hAVS>UQ|jKMWB-HuY+jpa%lodsKb)jW=hgA6XYi%SSgbf z7W5%nPVL7X?)fX8n0X!`T?-!dWnU2ubub(WBHIUM#K?O3%g?rS9dS?AP$weiYQ$LC z?c36*o@+Iu$r#5c#d+Z-J=bd4QiwI24cCwz=dwiW=q*S-0h_i;tfXL~ScNrtut&Pg z1GwT*lvwvmYvRN|dKBt53vR9BHbl385mvf-iWS!t=i)^KqIwbSWKG{bBq8ZsWjUm= z|4#B;Pv|w#pVV)!$vv~bYj#unw-|o@5`wF~+YYG<(?YvrH~+I~cllScw7ndl~RfDm9t?AP8Z0-6wgNKA&KRB3|R z%Ll03v~UzxtgcBPWM4*$BmNbiJYkDio)cgOZ2@kmz_+s*FY= zkgUo9cNBvNfm#{&D3MVV!zhRq6od2wzLk4l#HSFUM+wMYo^p#4tXhvFS`{h4S4o1HA z&Ttkoic0;5fsf%EDRoIy{tY^St*P5O*BtwsTYobg?|J>wc%K}ndVJUo z>}MBhnitUi^bu=6n|;Go=l((*Y%amw$AA@2RTp(1eIw%(zG= ztcRn@WssMxuk{>IAQ`u)F+E7}8zZ(Xt#k*r?V>)o^B3|A&w$S5V>q}*7H$oJ<>a8N zwW9!JIw7os2+37zpC0-0=EF8Xw(C16YI^q)Q)A7OakcyshnjggCO)|IkcdQS$Wvg|>q4G1<8?=b!_ zeA31*fh}<<)l1CiaG4^}2T>}~XkumN>=s*QB@P+ItF$}t%qS9q9V7BZXBouFC&<}I z=2o0_r4hUI{ABJY1dx=2`!JjhfB-vSI}wqomJm6RDz1u=njrBZMJ9*aUD!=V9C`CXUf^JV?2vMEqn~w+|`@&UyA)RG;56KLX)1}X5TG~T-mY;58=H!I$vd8pw!M@4_-C7jdH-?UC5Vi z-YAzY>rM`u+dAI3{f)M^$^B?%F2>FT$Aw5m|I4@Gw##unA2(vGGFq~-&28fdZ=Ll1 z;j!P8V(AdSDU(Vv!QMjO`-+h&*>o6B@>x4z`X{Q&c2tf&>`A=3uyiI!Nn-Ks(I5|X z#O0?5v5@Ht2GJIorH+BJO(g)tCef|AR3`LBv1qHijYAyiKUo6P=sbNq`w}U=NO|Lc z=l!}Vq@Ox_%l!|4M%jxV0q}&7m2v&I**`q=#?MFDExP`CFX{2}UI0RiMBx}n75Ck> zB38P~3-Mbi6i+7dW6+=vCP@kW=*l;{fumMUP5qRN7E71f0TZXz*HY)aYkU^i1XCoMZj4RI_Ji%d_P7e7RoxuY_% z@9%$zF0>qm0OCTJgY=sA}tzNkORXW@X|@nV;gw zi}5s1q{{h^nF1>bdqeR=fBC}7M9h$^J7O=vn3@)WtHJ3^kae>SFm- zq4_e2h-c{u`zt+5=!rh0kcuE{Pncw>qW}e!LQ*vmkvjcI8jna%A|9AD--$Y0hU6w zRd}FfYY0_mU%AG)NkkD)X9*MM2a0b6Kos{#g403liYL~j>d16fp0;)F=uila$ehS5 zQjy5iLY||<>C7KRmF^1Isf)7U?pB&26U!lfs)^ncPmN$_NQjn4+Oc+pGKumuPUyUw zFV4I{8Q83@J2iM7+bR>+kyKpCwbQSD818UQPo>=1RLQ}XoO;Ej_UOzO zxLPjOV#)CqCH$i^hg)Nug{EZ=l4LH$?^caRKlNm*+WLDzep4o;BlXWG6E5*^y~GOA zA5h2HmyF1S{-51J@J|538#6pR5kG)FGE%mLeuOv>_|rQY3p%mw?}pJYQy+$hLwqM4 zbwG8#(L)dW$rfK6(4_ita9SeT>U3B?L|Ty&No~dppL(q@;xbNp&HkM{@OddaD*Gh< z^*rg(s$V`sw-#Ow{vHf3e8x&CIH$^ak^Tk>GEpbex{{y_-XHfC3e2;h^+sfw|Xv%9*XH=56Y0Mc7R+6 zCm?3Klqk}Hk5Fuatyt+hnb4JtWr9biaNxfu;^H~m%lJJ6QDAti(j0E3CDuU%D;|O!jb&j<7gVs7TS+t%&ulr6CY-{Umuj1IDohriZ@BMam>B zdcxBU=k>cT*^y^eN5-L)m5FTT9RdBDkofM0GT{*8ZYh9cCzFyAeh?{wW6Po#AZTSG zJqFtY4Ub@+?r?jgRqG*m;nR{6L@N_}Xik|(qas)mr%d=)1yIh<=^;q{qjPAFa}P=` z%>&PM3Dnh&M6vl28|I||S}juKC0$liqp`^Mx=op{@X^to3IBNrc2m_m?uY8 zII=R4Es@lKufKwCj%fStYg3pv%MRz3m5KF%foYXU?2wROHW0_KXc020e@R8aj)ypTXW<%sJF}a~Q%GndOa*lvV;d#7>C^CW6@aB&%0SpB=PnBqcP!*N0Kta&S z1PZ3RXK=^g0t7VTvbjc_;m-GQY9%W#38XVk*{(r1vhsk<|w$6P-M&QNBblcc4S02PUv>6Uq>|lL>y%#vTva63Qbj6PqtD6Iqyi zneZ`&m5Et_uR|%92~{;dmI-E^ zwV&*rqpcQ|W>rdL7PFr^>6J|}BPuQsQJv+VszMbqqz!|nv}J|o$wVhlrc9!9VL=zl zlU{>AL>nt(Rl#RdKDfjI*-a|6LZ9u&%RqvYQdaC$;W8n)8PXQ2k)Ak-s)rcK1Re29 z;Np!WOFGn6CUQEZeuX=m7gx#tc@B=RicIE?9A#nMaC)MyY_?2vNFb3n+_hs)j3Swc zD_ce;YFTC0ys^Y0reeFZ6v;#q37JscalN7UfOZqKeZ``CK%uFB|GkvFJ$&(xd$LYv zN>6TFiHqH9RkpS*PD7)7RwEIK7%NJ-go`8Gj08L5@Umkq_3v>N{w~9tS4sl-Cf_}v zOhNv6v(OXkGpY;{Hphy^Eq%;l?RS62LjFpXMNyEhvRNcNv>lO@Cr7lI_U})7ZO|{U zm$K)<$|NC^$Pg1Ht3$p_y!A1X$)wljQ?Rb8i_5fFxpu(eIB;Fe!LA07vpQ@fMkf*C^hjxTEk& z_cwe84aZQ#rQeFbLk^t!m*=lS%AWHchex#NNP>k$%;$8z~LQTtG+JSL{fE zBge$E*RL4K7gO-!mI9y)az>zAT&pM8(BhJf5l<@nqbDRZaNT^-UGRj4Q6NVv!UVIk z?QTU_kj_9*U@wx%3fbGJOziI?dT2rts_mLckYOWeP=)SfLQJGt=cR}FyP}h@4d##N z2teL`VKo_v$S#V-TOp@Y-1_!QCbE%JnV?B)OSJ*_!i<%PE0oUpGU1+2%(Qe(hR~CV zR0Eq*%{AfR+(%;YlQN-};oKCsvmfQJL}N~3Ysj6a0x%*_MSBK-5mj4<-LxnOzAC~@ z?T<{jqjY-W7?!q0zokEJ7$xI6xJ2+aMD(qmN9`F{dX`!h_jSoZenozhS<7 zA10>(R9RYk)etlYF*%v=@LA4AO)K@hG;Ki4T{*|h7GLdS6 zj%uz6Ct7xjJx$mX_L(ze#gF;osk|^Yd&@0qp6`cN@xX!ggtC>19u=`vum0!>>8=Q6 z?nFmHmn}Cq{HMI-g`mg;$`c3{rez|gt(;6as7ji)#=ZS($;f*h_-30&?||}If^=G* zyUB>lPxX<8Jq-b#+c-ne5Wx0di@9C=8f@$ayn#vS+qIa-!aUa_7}iw%6I+-e6MS>W zr6Y6h2uWFsWhFQ@Ds5JxYW zVNQQ4#A%=*g_>rVY+Ng%STSoPXO3>1l3Fp@&L*<=}B#*Id1x} zts;JHSQSZZXJEf&qMlJES6HiRF!i-zWj0W~5Mz>B3`*)K3Jg>?!rSHHC~~XZc~(|?^k~vAw&Rl^*%oEt+poyIS;*G7%pVAhngGv0u@7IZx6a?@&~es3Cu**CGD(^CSS$&d*kZU)!ngOO zq&QmoUJ;P27iv{1)fRd2isB?Be&S7g-LJo^gdeD`Hs;C=7@YLbBZsZKTTTsP#=TVB zgcgc#s172Zq09arkTjaz_IZSuQ~@uOqbA)33jzd4mm%IGErV)F4LU&ZOcrztS8I8oX7+()Z8h*L{h(Q ze|DDrfjNh1ATM5P3c{c%kDz1!o-QgS(A3Ce8{jON=-hE1$YC(hHpWGalbmr#N|g-B zL|ZzGy&^B^^;DBWf+r{yE|Ce~_(d^k7P7D(G0LWqBa>)Cu)wpO*e3ehx=A#Qho0eO zG)oCm{IDO$!7))S6Gat5%3P+N*jemx=_MWcD3%4`30)3C7gPPci5wwwWYyuu z2@JJMYKujezs0P^Q+LP~*b{`8 zbflxW7CniOk&yL}{Z*N`f%ckk2GyR$pw6;r+Iwgu8qF?d5?9vTAwu+loF@}$5KWY~ zv3C9Qha|;GqHzv&HG7h*V9)>M^f#-sP8KePOze-~`u0TMPm-yKB$j!OCG}qCQ#qML zAIRz45%)>oE5cvuDYq7@;!>iqHhalr_qIC6kFxLy-3fw+l?0beGvUL~9+ z4xL?gpe<0kq)f_i=6xV1HdeG;XEST41>(d{_-wKi>VqZ1#41=+wU1?5tF0J}#9pJU z#cVIKhjt~9b18R@3Bp-R3w8kNl|rQUSFvkj;U5GmLng2bu5&m!^1XFe{0|;y$mAcq z$2D|M4qN=g7oN)`&t_~+k7c}jgy--DW^b;N#4e*SFBc`FL`+nuqFh0xcLzx}=n?X3 z`o(@lpDYN8z~0o8QoZ@x$i%*2xW1I1REhh0KdIs!o81bT@GSAKeU2MrWGKwWoHCopg=@v zcXH^c_63|mCgg*^0#kD7+!5(OGzpU_a$-9mlwnV(%tVncBBAIIKLzo;w1p)93l65j zz;%~GUb8pg`zQIXCB;msOzcp>0IHsFZba5zjJ3*_gc360277ghp165SK>&fmt{{^X zcbbi40tzKEu{Ep^BRzq3@n`aGcV>z?Tr}vAEZzje->Ku@n$FN@H+NKPMNgtrM`uqU zOA)ry5l?MUf!e8a$8v{;eS6|$LfZVndXVzwPE<$#o?o2xQ?Vo_}~z;QO#8ds@@o4@WjnGh8` z;!!F-q;-fk_UuUtB3XF}N57LSt0!77UUyVYsNpivRZXZRa&aON2Fpjs3+B+jR3@rH zx)uwvXGba3NKaVRf3)UIyAz~OTGLJ@(JD|LwY0L9)W3W`Y=)ToDl+jX*k#M=iR7eb z9B@04_zOKvM= zBCjaH#>baiDdLi{sjWaw&?qMpT@@3k+a;5bNo9)E6X{lLPbyc~UQkaa9!aeA&OCUf z+a<|^6rResLzi-~Af$jU%leK$RF+IcIS;j@iYu_Ot>daD;{-5~iC7V~YRe@=Nj-7? zh8>SR?hNnSg-G~wQ3>^glK8VGK?gR)k%4vL07hg4&pu`YC|T}^@Ph@c2E1Z(6+N4a z>)_RLZ*Smgm&Wmys9smBn1qL{Ag@4@l!-H*cB#7jzC$0n2E{PT_T_f{^GlFVLPTj& z=0{dyDjY{#Hs`}df}S}mgrnYg`fIxYdYAyR*bJ`YKV@6TV{m4b3HeFOZ) zdE&-557ej9U**tohr?jiqt;X`f7EysdZ2`GFj665=Ouo+L-vfI0UcIP3^GBdgo$)q z9)Q2=qi!52Q84(82TR#*MBRooiggzyJjOR#4jBnZ5=jEY(~&2twWeZ;NDY2pQb80E z2rYqek(&;IK*W|oCi)XfrEysRHiD5%%E=&IUREZs8vG35cKNQs4lH+O%6#>dT_MmJ zsWI@eTU_1BdV>Dyt4X5S@bFn(8 zXfE!S9J*6$N@OZqIjKP-TxrT^uSG||BC80e&`kc&ld~so)YCEd$D$7Dm}JFw~gT3YmpOq@|4Qpxr--w9!tvI7=qh69F^iC-uupY)R==P7z5r{J^8HP`gaj%nHX= zCVEbyf4>lC-#YSfY*isHh!G%HQ6REoRlKY$oQx{S1bRrBq<&ec_PG=334dTpEH%l& ze%kj_vlC=qWGNiNd6Pql#jVYk=8u(ZvtTt5z;vr8} z5|N%bnPA-^Gnwxxk=9mS?$C3qDs6Y-RL>CG z?2-iRi8x^Zi03$P-3mH^l#KVJ0B2Rv^P&_9T}Dx;iBg zyXcy%hASSGow|1l=~wg8k#l5y-P!A}(-qj^xJ|OlZ)HpytKHQTNTlfqzJ#BxVLR}7 z= zX6ka!(R97TDWmWX?^X7@^84G-P=OD-VM-AxpRH}(DL;40Q!a(LAF3>c)Lg>nOEq1Q zOlrbTBH`ONxO_aC%80T{;a;jI?jjB|>myD_-0|vvfMnd$zpf-zsFJLj6$7Nl>y|~C za#kNX-&1+}BTO4!lOJu;&Hq*^$}+xz#uKTmNd9(T5(vh4%mDp|4Y(7(w*>LH>5Jc6 z(yWarhUmWxgftXUf+WFq#`GD(#e0x*x& zVwf_yw!8@I&v&7!$%IOXA1|lI@+P@Rur(#{ofmcY_RI)l>jTA&kUq$KA$^;3aT1uA zI|AAUnMA$7!-Ca&)*=)6t))mN_Lr9;GBqTYkypqhGm@?*fpQ`Vx_0jHe1eyalToQm zpdZ4ln>#hcq%QUZj~8&fQesm}<`P=H-!?;)k{pTDe#w~<-m+mIOCmjzjeuZ?RsqJf zex2CZWw5ajsl0_NF@I7HSsU>nKKjoiBHAP;lWMlr!PymSWA%eG65(^yaxn%7EV3E9 z=#b&9y5u|-z9*+`Nd&5XDFuQ)!*)P8Tp7_AF{mpxPDYVH$RUjpCB}(P>6Tl2)8(!^ zBrS_IET8j5;r(mm)jMV{p|} zKV(w*C4;Ih?=S>Ts#qqH+q$;4Std}%tj!V0|1T|hu&v6w7Hf@dJ5h66DU~*3sBhJatiX`-wA)ZLQ~aHg;Z6Y`UPmabfGc#mMP<1c1CmSf|l+n;~m|_?HQEKg0^E@ z+nbJEJb!+3=d{z0wfWOJI~H^{F4Te(o4aQ;wl}pkYxc~pW(z*`-1j%n>t^Y!^Oa%g zSDHVc;qK1G&1UYb<|W;z9QAxIg%agbB1>dH*xK2>xUsF++TL9}Zr1rHb~Y|*(WWO( zJfmfC_n5H>^pcFL|G|#drV;|jHZN#xr)U~h}tyIL2tH#d>3am8fr+>VYmZL})=(=lROO+VS1pG$YOa{J9~&E3s*@W*fn z4&JKz$1ZMdYhrb+JFYmdqrI!U*wx)Mabj0@CuYRKENkoNJo1P{N<^l}$Duy84e+c% zuFOBi$8X*dNDoJefG)lt8h|kB1Y?GuaQIP4%{3EFvYKqpY(KBPh~U?&9ud z^Pa}G#m&Xmt|CoCV{t)e$Kpk{u(SCCi(5OJo6NB=7#}2FRKNRzMa|~q#SqT9&Bc!S zMdpjgw=Z637PogcH_mHmJh!dcoO;3u=G0Tn=*1}2cBS6vdBri~myB*W;;gZT>CsJN z4NAruEtKe}vm}~umKi;|VRX}cGkSrh+K_BpU_OlTSUj)$LQ^c7G3_1g&120NG~86| zXm7hvXY;()uGWrr5L?n{fY7?IvCTkU zW^_vv!eTR;JR>YFj-EHV-4w^+243~@_^V&MPnhizO+C(~w zx;ssK2jZ4S)6&*uIv1R4Iy#%0JI&}trei^yX7Y-PAC8{1F(ui)84Fr*$k^yr_7QnR|LiM{I2uBHP{3uyF2s8e{37 z+t}4QZ?4X%i4z;UBLkM6AE-2~yJO+RiSJB@aNaI zgcJX?CA=A7J;Irrw}kg141Ik|*oE*2!oh#u5-vv=@s};(rrs^#HxS;{wTP@Sh0JA?$2=!U+h2ay{W%#4U(FgYW}{EePZDJz+D#=MkPn2ns#n zI}sKlT!S#Gt|#0n6)r{oECj~4BixVh3xrn@#sod#(FiXL=n3-!HH_J*C%ko+p76gB zeuVHM!efJb!nY0S2|K-z-@PZi+=dN^kKUsvyc%KdZav{C2#lWs{vyOzAl!to3gIz? z)xf{chQ|>z{LF@Ez*32_<98A!QS-v)c3B+8n!AVhglqQg36DoSX1|{BMuhqiJ>h>M zOxwRF{58Ud4?ut3(i84o>!b>B2!sk=rh`08HBM=xLjc^vie1yvpu1EM5 zLhIiEC{uALTgjW%U9n=%vIR<>#aN^jW@ZAV5&zNPdoG^xeM}W1( zjF>o4<1xApzyx+;^|@nmPk1cCHxV8|xceCB48ju#KSh`@72}A|gK+J%p3wOXLh#tm zj`O>kXS6oMN1NAj0hd*`thmMId`u8m2Jl#uAaLfQCQM-XEQwOO0VJwUR~EFqmqSm0 zevR;Va>wGX=94>UaiS$Zz2K(wqqP39i@Uo~|9JSSB&XSvrjIKUwPX=3t^eMZ=H|Aj z`H~8i+K0hA4Q8^dxhbk&g?*D~pN=5~IR*m3IGo6}6N90-64ygG!5Bs2qbqjORuX9H zSd5i5B0O%Mpt z=O=#kjmBjN;SV35dCahtCmwU;kw+eL`rQW{Gk^a4V}AJf<5N&R<@2BW9Kt@#Pc~*M zV85DT%v}#6J?$NTx$0=pnfCKtPdeu3yFNOVa=dlz%a{J&Ts(U{F$EQCu zW#X0NU%cvq;3ZN-F|!MM?QDm2f))B z9JoC{&6pPu|9;xwho_Dk{+Gke@I$B1+H&ANQ{Q>h>0dnI`D^I^;hH{GBJ;vA8jqU# z(Y22*96$G=V_yI7dHX*5<(Ue<_=8hbM|Ek9OmlG}{C;)RIy#YTUAU-CY&LcUbVqhJ z={+U)f_9sE=#+(XWxEvZvyNSG9DU`k26`Z4#!j9rYU;8Pt*By(7dr@=v z;ojUchmVi@W!|A_Gp&to-34&R;Ttu!ftRMJtP5MZCOE|A6nMWr!kO(|ix(~G=+>_)*x{X-QM_2V3VgM}>FC~xoz3tgkEO>x1A)G65l-vm@kO|;laGA+JIze)-P>XN z(!e9${&sUlWB20DMsXykiPw2@2b|;MPMvw`=|>)6;}bMK>I5_Ey>n+AKl3zrfivJu z7vEMqqXlxCw-^$*2ySFjCyqb;^ixkC<2jOJi&Lf)M|bUPMt5-|00(qITgSO@p6M@6 zc1IU;vEDenlJkdYvVl2iI*uPakU67U9M;pOoqopgbEnOkb^1xinlomcbiyoi+^o}Q znv;*8HO)+$IqSsJ&AE;9&g)v#i19nO%XBxM3$MEwZtc9bPB_o#K7HtJv#1eEl4w# zcAT_!y0&zhv~oPiPgnAGn`TazCT6mUleCE$B#(0dbJ~J47vVOY%6r1$=7b~62}ha} zjxr~_-JI|abHcxv6DF7w-U-ln1i%jm!r{O;94LpsT_kY`MRABo<`9+AA>5YG!FICd zo}h>w4%f(u7$yjqTDKS_Mph5Z258^8ZRngizl9s7a}GPloKut?6t_}EBRj3hER@Y9 zQe8OTS#m+thVFDGkCsg)Han9?FDl9&sA#&dZ=m*LnCH&wn6?NDZc|hbs_6A9VVO#~xIq712E*a8hS$DFY=sA1SYAAfc;qTVDC8+|F4$i8+%%TR0cX>#6hR zEnd{x+!W&^=9SC|eg&Czhes_F_}>e40Cyjl+p$ zdvg)0f(`HDh3!oJ`{+Xte@9nCL&N(j*PU2Azq12mqq7e^)2K{wbXR3~1zsmo7Z2(d zz1g}(tM%ic$p^`CjVvlfOgngl)J_U*t9n;a))R{*r$zmc1*Tjp4~0C&s|;l&J(yU8 z`qfIR8Rt?bwKp{{vAP`PkM`7=hgWWDLjE2^O`d~Io(xTd2^4~d91c`7_c$z%zEaP{ zdf7VPm6%yA&BfSQ!YydSwyp@L0-i*36PywZ8_v+cKyxS0;8icX8c2IqM{yyEU4Ruo zg@B{Tw$^#);l!)hiWA%JmgaWgez2J-B(QK5JFp0I?dJ&{3Kw+3n$K(P#8PLq=Dg*EiCJpXL`m_geL;Em`5npz z2fqt-7PZ2Ok>)Yc*%&+&Z2i!b2;k(74<`AWk8z*h(YerP#7b08;&7Om!PGe0VF-xy z+OgJWP?+C{6V0sZ!oSrCH?CsQ{3U2Ec4EhY7p^(Z_zM#DSefOz*G+?rPbX@O$Aq)s zgHN6ee{0t4(~h5e?3uG>;dB-H=e3)__u6&k)Tww;C3nmn*Vc-~P!-)Sw?a2wUx}H~ ze{Y)5`SVvGV@_Jo-a(^XJPVJR)S6GUMtvS;3~e`$n42MUo8Q?ap46!Dk`4(wP~qx= z1K2vRsM}oGejLA~8%Hx8i!Oi#I-#>;A@au^n>^qrHumlQvHCb6QM!k(On+8~QrFWN zOSU3)o(If2|2Ryd?q*rhc@QEA>^H_51>1){+9~n$Cr-p--MWzbDmjY*qe*Dvk_yln zunF1q&TQviA%c|(I?)RBi;p_&iI?}}gQp}B^WxG%Ga{B)$!}PCT5*a2pp)CT2?!r!9FlSU#E0-3ko|~_K&G%vgSf@%)w*FSdk`Y zN~yMwEjNAi{0ti2+>MTz&Ka<|Xkkz(4;x=)Zcy*$CI#(1^Iz z%e!*MA1G7qa4yJzeB!pQAa}nN;uo&TDgewp}i|_@6I}yHv@BqRO5uQQ#1wzXF>ng2hIcMTb zMQw1`7>%(cz0Daxe+lxezSuv-KCWZoA{=5&oQQ|UIIZjG90U6-FD&RH5RtOkS{@IG z!!fO?3G1s}t{p$t^20mf0%PsFdq^W*fvgYGKC`gq64|9dR*#D1Zp}zE==EGB$@N>0 zf#`4A1;Ce8qI$d9Lr!Qm}dX|P!h#4lnw=et>%6D{_ zhIVEkoQm+C3T?g*u$K^;5Y9vBL|BS&8N$^FpGT;b*V};mZG?Lf9zys5!jBP1|8(@7 z;T#)2fSBQof9nhX4WSXC1)&4sg9sNQEJwHkVdTGS_=8PPL;g$~9IR4&8*p>`6((&8 zjJX$Tbr;?R7&-vYjPT5U0^;dA^@R5zejV{kh_Bum&%6g3b0eO=pN9D8p*`W1h_6I^ z7vdN241NRR%kjLvILMgdu%2)_;-mKJ3EL2#jc3+3BEIwBo^T21J%jj0#LExCvwD<| zZ|Di@cEWoRhxLTx5Z`%tPk0XE;S=#}AMv2+J>j#=p9nlW+d1uI;2|D2t0$a=_>MVv zR{-%-=i#|E;-lNa58^?K&@cQNT=9e82l0fZXdm&=Wqc>Wm<=DnGj7DgF6jwhL44Oo zfsa1{e)Z+RN4)7#@Q?WJAK;lc;){O>xgehP1muFa(A~DhwTRW&Fu}3M!X1d6XMl~FGsuyarZE^cMjS^d}|}xLwwG;z2OGL#Rb5F{FflU z6ZqXNz2Q@cUuwmAg!t_9unz5R%#-cC;W>!USp+iy;TZW0nAK4`ZH1 zd=}!R7XT0OLx@)+Zu$`TMO^pc-f$?|y>VG@I2G|L9|8aPcx&jT;2-hjh}#g~aT)rH z`1+6chW8*I_KDu`6~sq>sy7_Imoc{?o{D(rwY^~r;t8Ma4R1v}^E${M@#@cG-P;@T zz5#q8p8kd2@HE5|zS0{mL43|i;3Gc!+r8mh#2XNALfrOU$bUHGfOT^Q;+GIFLcHi+ z$Pe-3h}R$3kQd^M5kHCe4#b-fKZ$tge$YR};}Ku|Bh*8D*N@=`ARhIT z-tZ2@7ylgNhj`qx7(c|%ARaRU#2RA zc^mWz@#BbJJp(op{LYxw7j}d0t%z?#{5s-?5D&*X^9te#u)o8KFno=D;Z(#eh+7z+ z+ZSGscuW)egSfl7FWi85>H@4;2SU$U`@-pnhrPcqY(xAC;%gC~)&YJHuU!m0ygy&} z(Z293#6y?&g_k3~2k~me<1d4J5HJ5&AKnAP{J0$S5MTUptTBk6SL)*KsX0$#=xA1H~pi9e**^LywJu>X=LCHA7LZfinhVF#*KmvM_fl_ z*VeSl3h!$uMr|Ag9I&0lIlEyz>$f0WjCa<)nT8+x(YnhD=LxUGyBeXsfcM_gc*hej z|1Kg<1?+BwrNFBPLkXTv(EjJAHw>NMU}iN8J+{G|BKI>IhAwU}`B@F)-`g;B0_yi5 zOvf5}E##6#qrG8h{;LhwOmK1Wy=i zh(P$>1e~XUvwI#mdt-9Bv2=2~v0*63c{t!}@ZR4TtQQGdR=@HXvi#2)#-9zk#Ge8D zyYXIKFX;QhPr5^q@s{rf?CF=#JnFsE7C^#$ky-p6}OIoiiI3>^j9 zM*;8Z_rX>po#^ZFoOvH+7tI)ivw?Tc_?~bh*5bOics#f{I#A~*X?-{^H9M=<0f^A69vu&RbE;$DXeDb88@B;W>bvI!#aO2>{ z`8^Fo3ug|1u+|`PQ@)|tD*YobN2Bgg_;f2-m$cG#Kd8FY1mLj7o^S!j+Q)N!gZdW= zAPv|kglmB`b6!vQ4ANQnv=$uWdjQs})DY)-;Lr~)v8TY9?fMU#8_$PN4k8IUZtPBkeqW95KN9O1_Yl+JSI?bRrq0xc zBKu64F1;82Hs=DJ4kstq=dWm=rvh)p{TA;x55d2u3_k7Abu##~;%xxlAnXqgpss!*1Mk}nLuY~B(1E!9 zPfz$s`oZ7KzeqD*JN zFun`X6KJ@vp}3%7XbW<`0Q6pJ|IP)Fes9D0a}WWXzXO21bHH7W%yB5}1k%0(k+=zo z&+NqZX}?Acf}PtBK4g80XR8B+S5>b#uVw)Eu7i5R6Hzy_f6rkG77pCGp-2tadA<~N z*8U65$EXu1i~8quY=w^9ZNR%@LT`9n8c*zP{);3y3e~wcedwLN;TEJb>2)Z*SAlo^ z#NMzuP0zMV3r>0?V7H%{)Ehosjvf{z;!OwM}X7LB- z0^Uin@B@go@D8)`6SK1s8*pSKs=6mW_aaHtb!0p}s?^RFeH-(eH#=C0MTMV9}Ifp z6$X*De>k@rhI6q4(tXl>=)clgW&2ZsSN{Q=7iHs}L_CgF3-F%m>J2}X?vw3%;mef$ zlWbnrUY;Ws&+iQnO4~w*{}rqckQaG)2)HAb_J;G3PRPsRcG+=y1$buzuQko9v#)nH zj6VuAhJlG&FYFE9Mm@PHT(jlv%I?oVPYxNiTChiCic{Dqms!H{2Hwt;(Id#XF|>U_`?BxbKzeudhI>KaSu)RK(JH*eIXEYxJpw~m zcPI2YEq_ZJi-P)pz}xio4FA;O-K2PJz^h+{@yzT~9=m1j`?bJp0p5S4@hm-hX+^;9 z0p2UXYfs}r?s=@E#GzVGSlt_*n}q}4pW{-8DZcg_7?(2RT-Yzxv+=+^`kUo_gu*n% z#qQUf4cuGrf*nb>jWa>QmjZrA1^A7CuLfLr1b#HObF}_FfZq-H*fjmQdgk~n;12b#ff=#(f9R0?O$F&PvGZEZ}wHnZs=CIqSF~aysek z&q}Bn&L>IpV&L9}=M7&=_d(VfoDQO#H17c3m^B%ARwv*J!5;IhAL|To?*Q&v+N+H) z`sw!9qy0-7hMwP0$U{#qNgsJkAOggt++uL9la*>1!oPEeGhQY`d>U_DYM4rVc3Z`3NGX`FZPCe zmRYB;j~+^Wo(a6Qzw8b1NGNGzPHiX_QPu|dLx8_M4aZ&yY#HKQ&9;DZR0hsG;Ei#8(}LXOpi3Z#D6* zF2$qmI-{Y8t+>i)I`G#{!!x*YvbAS*ZNNJR&j?G-C~W(*9_;(Iz*{~Y&j`!WL(AiV zcMtH!oPe<@qYL>B4Mot*U)NBK)>b}uojC)~DcLuKv<#r}!ozSJx7`Z7pAzrs`Vu@o zJDUpFRN$RP(;47tUgxx0cr79{64r;4FDGhdR`mwWxOvo&$dd>8x?( zc?;=p0^XCrYa;#Mdor`Ub59PQI6x77)*G`w<~N=%pT&B=D6L1n{yU@IIjA=R&!fd& zW#|!PP`DTx0U=;R#b=FbAFoHfL3n;G^?p#=UN`D3%c%Dx>b;8R+`?yuK4$Sr`SJPx zu(rPNlWBWy<&s~kP{Wr7Z%v&>QbF3thCMx+$HwqDd0bgcNf|@R>-I4 zI1Ybw{RiHt1Ny>Eq}$@rbv%7S`#cJdNnbe-?+SoeU6+UFWCLHj@CC4p{Xn4=F*dH` z<80J>Xf$ki8T*8>7u{VByn7Dn3-e|0@~5jWe<$#+AKMqc6SNck^3GzO1kUhIyf>G| zvAkj#mNs7p-qafKibePvz`L@HEP3Y0F`5Cq;oW`V9c=fCQoX=g5uR@7Sr=uq1o(r{ z7uk<}xD+4ABEwsO*8;keNEabJmOQW_y|qQ?WfeT2m`%7{4ZI_fPSCT@$Wd&PLUT6N43wjIYihS^$y!mnA>Y@?x+dSaY`R_rwp4l~cX%F+u zU4xJ9VK&MA^`Yya8Nk^8+@C>Gn}-BX4Kr8n8r(X}Jh zlnWj&n9K5o8}lZ#m%4_?^Ge6w(W9irO?1s~bTJRtYgJ1MPy{cipvx!3nFE9(N> zUk_fdL-d{c;In&}pUV9=^*_s_=uf)_*b{zrw*!&>)owx09wwCg_jhN#AMByj&V1kh zVnY9Dr`vMNN1NyC$GVLKoud&o!)sslew50BswzU+qoxzyQMJU@gR3=01f!qfWg-eFt-cfBqeuQOlH2W#q}GPoChF6sX*z?NPe3|<|u-i48Vjn3`=k=%qk zg4|tsAbh6qaBg#*xi$c$*Mq^=53r4dH|&$!^@w10;g(!*Th6Q^gN}^A#s()8uE+&f z=gbWyu<^l+vaqogVE+=FSpceUxZmX-EZnuLSur5^@({CSz*Tu{++jryxJbC|)-2all;Mswo zTKL>RbLl{BeD2%;JNwrP!OMG^F9yN?+s&*Tup)=dBRdD5*~@%<7Xn_{CAfQ-`C@(W z`(ftU`ryCzG~XV4EXrTpHTdE%^PQo@xqLTPequM0TSG(e+dW7CjO?=TJGndZ=9|_U z?Y%lU;;BK9&KY>c`HKTjMS2a{2j*qD_4(I>)kX8CLBYzR`R2~o6PG-{P%y#FQa*P+dDO)@ zbECB{{jeKhZr8U4cjwHa;K7`^&(gaf*ES)zJ1{2(mj`A6TD&N@Cop&BrmPLj##{iq z)sth%=6vw#z}%+_xEH=s2<{wE_&(FQO@-j$K`?f~^MlNbbtl5z4p`~AAoz~~=CuJq z&p>nWz~H_?=Kg_$9~cxFAhDJ2%pLaa+{Bl5&iy7o1%5{%`0t&}Q-$EJoy^8U@TEcK z;ktVY>vl4mIAE974}PVd)#VCrxIC9zIxBc#H?t-ee03<9{N+%yG9P?vH**E2NeCs| z%{)*SEZ^Pq)CEuMZu)}NIh>*Xc~G!=PxGmrgNOFX!B#x9PvM)p1Z(yz{9>2jhrU`l0pch(#OLK)^<${Ou<_RBLaK{Hv<_pKN!nv%lH27?;0N>`R zym`I^cPvPN?p>sN8|kjd6@Cj3BE^N!Jvz9u4m@8{SC}8XUMPGRvMt+tSZ@K{iI1g=G3 zHq=2+&1dbp8?B#V?wS0O@8{MWY97u9Umj~-$-l8vT!P>FrOF^*a5VIx- zK7FuxCJ4TLh}jYZ4z~ErhVdiIpgGUZCn{hwXd~^u!w+;y&XfXdJci5NzYcQ|L{ia=mn+`KS z92)%QF!QV3gLQ|QKkacS(yR9x0s6n(EBNve<`a7dn-4R$?HzpT2=nmX!MDbn-|QV+ za)h~Nc<_JY&DVwpe>~hgHaz&o;pX@IT$9^!lv%M~@Y|!z*Y^wVKEixg?myix`0kPB zCAt3z&?B)C=lzQ#f?pkF9vcx{dz9HA_nQw0{&1AJ>A(PVZX3x?Ui;Qy`8e~;D5lqr z4n8-|{OoNH=aG4EETfAN#^U^Micwu>t0fa1jTZ zj}(G$3^ac#Oh$S|K%75vs8D6^_ndtt)*^V91I=T(djn)Pa|x;LBfy8)33&f%(1JTS0Q6p2ui)?3>}UNo zeJT8cTla_ZX8AYZ0#PQoB!L^v%F%5a|107l$m1uwO+67d8-oppx$-*&*$X{|G-bMa zfidtU%xNQy!D}<-M&RSv-Ecq77H<9bz+gjS#t*`o0pi^daMWy`+^Fdp|7#2$w_#N@ z29KW%&~RcKcD(+q@Ycb)n~;Ua{q5N<|TiEtmnI)vvCHX`&P4EYP{BQzjPK{y3r z4njM^MF>|R+>Edi;XZ_Q2+tvGMCd~pvIX@K8W5%+oPsb1p&j8OgsTv4Mp%h(AHq6> z=MXj`^dSuCL4AYS0UVtuoB@ugmnndA#6nGLl{zr`UnjOQxHx;n1j%ca1p{)2sb0FM7R%O z9l~=68xi^th6JdO(10)n;S_{92<-?LAzX!UGr~%Q`w-S4JcqCmp$}om0MtilK$wDX z3c?(Oc7%%%u0psOVI{(S2o{!nMWf$%WGPY|9*cm*N%$L-&z9oe5+XuCeUn05R# z^XxVK5?=5H!d^+mehPgHJfRjJwISH_P5I5{M^37E5;Q%c(#-^l{1~;}`mAi;^r#=7^#tPX9{a791m5vMv&M zj8tOBwhLUSdX2co8QWqfLmwn*g}dTpt^^?i>{=jhCK$z9UT*wYk(adg=4~4!;ET>r zTT%((X2CIVk@!pDC~<`{P7$gjkJusjDZeBAg?kP7WaD()KwRdh`U$V1o}^x(1qGEy z=r3H_E>E7!r3cNI4bv5C?|68BnrGcg^#OC>O#KDa(|-yhb+J~eD4DGcP2%pbTs0=P z4Q{)hEx3eQWzqNLnhp2HCPOk(C#zxtcgG`C(*SZ%feQtdN9ZqH+AdF?%-L~F$Ss+v zSf8lX5Nd*#Q6yodCIU&O6FJV~N>@cVrg*hkUYUBOmUkqq8dv>-R~jzcseaK1jcWBP z$gbLeRjA5_LP16moyzDRTYEX7t1- zM@~z*jY>3;%Gw$t5TO;NEFvP?tXE%3Y(ADQ3$&04EsvpbnY2R;CK3o1B2fg05}8oH z@Xho;fdoWBGj-yP)cNWRx|!l)pL^}2mUwWTQ+8&#sTRYTazLb5T?r|Qe58b5R13f)cJgG{7o>0jvnF#Fe&Exw>?#8j8p6o5}u4AXANe zO|Lejn4FacjIauD0hNcBhe*Hs17;s92#>G|a0Qh|=r3H_E>FJPJc(<>DZi6ZX_WAx zUXQcjzE)(xJ&Bb8M-r_JudGqzvRr-J8|q|5l*-VgO#X(sihbb3tbjlnl*q{+LK*D} z1f+5`cqQRfs*8G6z&jdVQFzK-1r8Nd9-+VRs=}{kmj7n*jb#$2d@YGf<5YQg3a1AB zbu}{eKcRLc=C`bAzsOIQV*U+FvKaT+Vc#q8UTPP-x=2=o_g}X%C$~Si6}T5(tHCoH z@Ozm(_%Q|>sL+Ul$|Lj_E^U`5Pv$bUH|{`X{uQrc14O9}Aq&fuF?MNfRPRw4b=3#h zbX=CvPxc)bQEgO0A+BEnl7jxiv#I|5mpZwY>q!;4l^YI6E_<*YR8*x(3)$)vQ$VUF z3Kcn3U-Q2?AAo0#L8iKqVNODGOGv%7a|cD)YWrws(w@)B|HRwrewfblu_&mD5yL_ zf8o-0dGg>5mt!U?t_ZByHBu{ITOj4Z)%mWXlU2G!-n8Qs0IsaQzgbp`1geOxifpS0 zU%-_{r%L^3n9KI03V%*bO6%KxNA**3u;med5uQ?#^7JikBn`3oDhM$+>bF#6ITAh? z1)7b@Q(%W2!CgTr?k618(~S8I2)HVOUn8BaNS?@L`kkipW`2iAKnA!hWjp-k6d(d; zBM>a4qeP-12W6q3wn)jMWX`K%0VVLbT$xBCXdZW785~5V{erV&+3mY7mjgR^rZl9` z)+|Ze8Y0w6@>c}%hbyX-NGPl<7`TFwsPj*i@#K~zB}&K1!%KQaF-CbfNDxgfSCz3> z=8{os7Vfkt6He0$fF&8HY=J~^X`J%mF@b9EM6Eberdov1PdKVaJ&b6^2?19?=r3Hy zC~mJbRgpcQ|Bc}ln@{LZcGqluM0)vHUYSceWmGg*8moFH+^3mLlR&a0m8%R*A(zQk zZKE0w*>EMx9>|qy+!b1AnuG(Z{xO%VAHh*v0@SjoQW0xyQAz*uw)mAmQa8RMXbkdh!xd2Dz+Gr&`&DEEua;t6y;2>#|Ms7cNrScK*p%h5nJd3bIk=%OWVaJdGHRR*)$n zq-8N$8X>CVP)ZP7fki;pp(a~%rRCsJwJ4FSuTmrx*J5^D8$u-_%4s%rDHVimhgYdy zQ}Y#C|AzuW7!~`|FSts&ghW&vC6X*e#ZjUR9K}FM0#mvE!c*ibW;5H0*^}Nx1Z=t1 z5m0;sl9qdOIfl9vNx5`p9K(sKxN(YtlWJ0A5&U#1LIjN~CMh@szch1zG7DYpH{&<1 z1R_N%!(xBoWyo%AaTWa{mr629_$_EBq@)zCK;DVq!fRCGnv z7!U#u`OUbx1R&57Bo(qiGUe^Tb-+?2s=>VmEvi?NNCI3*Uj+<=M4dQe!Er${RT&Iu zhG-%RwSX(sm+Jk1XHS%v<81a4@Te8*NB!Un$F$NQaToPn< zGCRqP%#UTJqZ`OY50XPJ5(E(s@uD6C7YW3RAgHkDWd#utmHY)>4Cq0@@2gj@y1J)- zEIUSnOf9eLz4v|ZM^*Je@2Sw9-KNRLt;fP8glTauuOvNssDQ5*?#p^5y+esR(LzSz zwOaZY0GA9#K+7&dVMeK*Nv`pEux7O(ju3{YaH)`m(;cO|pWtraQGWEY_TuaXOVfY~ zxGHyRsI_BTS2@D&`dk3AR}1$m$gY*K9V*+tcD(JA|BF_8kT!8+SH{BAj2-PjAd7uC8#rbE7Kbl;`$2fQo|U#{Yn-> zwv_8pNMdLvKQl(NaP~k-Nf;@2Xb2_rWc1?fj#yNjaA9XYwxIK^;C^+EoSmk{k?*?p zpY3;M=e|nbY0q;iT|xiexjm&S)z)y^F(2tByxS|=#M5D+HBmDJp-+ov(*3_o9!trJ2v-wI63CCD zgiuky!o?lh<|^Ra;tXVNfbvYU2yxKsrjTGU_3I3#avUzfVuXnt?22b_1$}YF6F_6HKv;JkPXYkUx< z>a@6Sz2?i#VS8DOHt;;R`ify2Rsu6`F)VGD)JAAYw4SysAeXC7ne%dquNc=o__ycR z|C+OR9kcEg=x;ci_ZHH=;B4M&Nc&A^^B(25pnvFW-edR)^sk)F`;lpHI(vt+zlY7! zoQHggTbD2XIcGkAdNEJ$EOB zT=I@SB(nUBF}!*F4hT8?j=K*+A9?GiMc(bfaKnC$Lq`eTZ9OFKFbY#X!iOSl4$hPa zg1fIR?~k91p&W%zYp^cIQ;^#rj5+wT$ayra`N-pU=(7;zZT@NuWzp58UwKEMv)5Z7 z=68{Msk@z2xr_8Nucfw)FiGX+E%FTxI00B3&ZWA{1 zF~jHJP@aB?9vO8vcQGr^+=G*bTnj#dHQ%cN@7n#~K-PA;B$$-Xg=RN0dE1k1@L%IIyB#VaA>|I@Rq<+j9k^Ym@JR^KZa<&TaTmWp_+M{4mX&Oav7q$ODAgP((^U*uoiP1nx6%{s}200aRmFf z2B#Z!H-CYd_1WL@4>hyAQ8SnCav-L (0x00d1e000) + libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00dcf000) + libc.so.6 => /lib/tls/libc.so.6 (0x00113000) + /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x00773000) diff --git a/Extras/CDTestFramework/AntTweakBar/src/AntPerfTimer.h b/Extras/CDTestFramework/AntTweakBar/src/AntPerfTimer.h new file mode 100644 index 0000000..6d462cc --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/AntPerfTimer.h @@ -0,0 +1,58 @@ +// --------------------------------------------------------------------------- +// +// @file AntPerfTimer.h +// @brief A performance (precision) timer for benchs +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// notes: TAB=4 +// No cpp file is needed, everything is defined in this header +// +// --------------------------------------------------------------------------- + +#if !defined ANT_PERF_TIMER_INCLUDED +#define ANT_PERF_TIMER_INCLUDED + +#ifndef __cplusplus +# error This is a C++ header +#endif // __cplusplus + + +#if defined(WIN32) || defined(WIN64) || defined(_WIN32) || defined(_WIN64) + + #include + #include + + struct PerfTimer + { + __forceinline PerfTimer() { if( !QueryPerformanceFrequency(&Freq) ) MessageBox(NULL, _T("Precision timer not supported"), _T("Problem"), MB_ICONEXCLAMATION); Reset(); } + __forceinline void Reset() { QueryPerformanceCounter(&Start); } + __forceinline double GetTime() { if( QueryPerformanceCounter(&End) ) return ((double)End.QuadPart - (double)Start.QuadPart)/((double)Freq.QuadPart); else return 0; } + protected: + LARGE_INTEGER Start, End, Freq; + }; + +#else // !_WIN (-> LINUX) + + #include + #include + + struct PerfTimer + { + inline PerfTimer() { Reset(); } + inline void Reset() { gettimeofday(&Start, &TZ); } + inline double GetTime() { gettimeofday(&End,&TZ); + double t1 = (double)Start.tv_sec + (double)Start.tv_usec/(1000*1000); + double t2 = (double)End.tv_sec + (double)End.tv_usec/(1000*1000); + return t2-t1; } + protected: + struct timeval Start, End; + struct timezone TZ; + }; + +#endif // _WIN + + +#endif // ANT_PERF_TIMER_INCLUDED diff --git a/Extras/CDTestFramework/AntTweakBar/src/AntTweakBar.rc b/Extras/CDTestFramework/AntTweakBar/src/AntTweakBar.rc new file mode 100644 index 0000000..8ff7072 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/AntTweakBar.rc @@ -0,0 +1,83 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +//#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Français (France) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA) +#ifdef _WIN32 +//LANGUAGE LANG_FRENCH, SUBLANG_FRENCH +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Cursor +// + +IDC_CURSOR1 CURSOR "res\\cur00013.cur" +IDC_CURSOR2 CURSOR "res\\cur00000.cur" +IDC_CURSOR3 CURSOR "res\\cur00001.cur" +IDC_CURSOR4 CURSOR "res\\cur00002.cur" +IDC_CURSOR5 CURSOR "res\\cur00003.cur" +IDC_CURSOR6 CURSOR "res\\cur00004.cur" +IDC_CURSOR7 CURSOR "res\\cur00005.cur" +IDC_CURSOR8 CURSOR "res\\cur00006.cur" +IDC_CURSOR9 CURSOR "res\\cur00007.cur" +IDC_CURSOR10 CURSOR "res\\cur00008.cur" +IDC_CURSOR11 CURSOR "res\\cur00009.cur" +IDC_CURSOR12 CURSOR "res\\cur00010.cur" +IDC_CURSOR13 CURSOR "res\\cur00011.cur" +IDC_CURSOR14 CURSOR "res\\cur00012.cur" +#endif // Français (France) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Extras/CDTestFramework/AntTweakBar/src/AntTweakBar.sln b/Extras/CDTestFramework/AntTweakBar/src/AntTweakBar.sln new file mode 100644 index 0000000..6b93b89 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/AntTweakBar.sln @@ -0,0 +1,29 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AntTweakBar", "AntTweakBar.vcproj", "{B99E1FA1-C30A-45F2-9D57-9E9C21B2DF42}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwAdvanced1", "..\examples\TwAdvanced1.vcproj", "{008D1CEC-1586-4C89-B524-DF15D9605163}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {B99E1FA1-C30A-45F2-9D57-9E9C21B2DF42}.Debug.ActiveCfg = Debug|Win32 + {B99E1FA1-C30A-45F2-9D57-9E9C21B2DF42}.Debug.Build.0 = Debug|Win32 + {B99E1FA1-C30A-45F2-9D57-9E9C21B2DF42}.Release.ActiveCfg = Release|Win32 + {B99E1FA1-C30A-45F2-9D57-9E9C21B2DF42}.Release.Build.0 = Release|Win32 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Debug.ActiveCfg = Debug|Win32 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Debug.Build.0 = Debug|Win32 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Release.ActiveCfg = Release|Win32 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/Extras/CDTestFramework/AntTweakBar/src/AntTweakBar.vcproj b/Extras/CDTestFramework/AntTweakBar/src/AntTweakBar.vcproj new file mode 100644 index 0000000..e713ebf --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/AntTweakBar.vcproj @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/CDTestFramework/AntTweakBar/src/LoadOGL.cpp b/Extras/CDTestFramework/AntTweakBar/src/LoadOGL.cpp new file mode 100644 index 0000000..3529da2 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/LoadOGL.cpp @@ -0,0 +1,498 @@ +// --------------------------------------------------------------------------- +// +// @file LoadOGL.cpp +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// note: TAB=4 +// +// --------------------------------------------------------------------------- + + +#include "TwPrecomp.h" + +#include "LoadOGL.h" + + +// --------------------------------------------------------------------------- + +#define ANT_NB_OGL_FUNC_MAX 512 + +struct COGLFuncRec +{ + const char * m_Name; + GL::PFNOpenGL * m_FuncPtr; + COGLFuncRec() : m_Name(NULL), m_FuncPtr(NULL) {} +}; +COGLFuncRec g_OGLFuncRec[ANT_NB_OGL_FUNC_MAX]; +int g_NbOGLFunc = 0; +#if defined(ANT_WINDOWS) +HMODULE g_OGLModule = NULL; +#endif + +// --------------------------------------------------------------------------- + +ANT_GL_IMPL(glAccum) +ANT_GL_IMPL(glAlphaFunc) +ANT_GL_IMPL(glAreTexturesResident) +ANT_GL_IMPL(glArrayElement) +ANT_GL_IMPL(glBegin) +ANT_GL_IMPL(glBindTexture) +ANT_GL_IMPL(glBitmap) +ANT_GL_IMPL(glBlendFunc) +ANT_GL_IMPL(glCallList) +ANT_GL_IMPL(glCallLists) +ANT_GL_IMPL(glClear) +ANT_GL_IMPL(glClearAccum) +ANT_GL_IMPL(glClearColor) +ANT_GL_IMPL(glClearDepth) +ANT_GL_IMPL(glClearIndex) +ANT_GL_IMPL(glClearStencil) +ANT_GL_IMPL(glClipPlane) +ANT_GL_IMPL(glColor3b) +ANT_GL_IMPL(glColor3bv) +ANT_GL_IMPL(glColor3d) +ANT_GL_IMPL(glColor3dv) +ANT_GL_IMPL(glColor3f) +ANT_GL_IMPL(glColor3fv) +ANT_GL_IMPL(glColor3i) +ANT_GL_IMPL(glColor3iv) +ANT_GL_IMPL(glColor3s) +ANT_GL_IMPL(glColor3sv) +ANT_GL_IMPL(glColor3ub) +ANT_GL_IMPL(glColor3ubv) +ANT_GL_IMPL(glColor3ui) +ANT_GL_IMPL(glColor3uiv) +ANT_GL_IMPL(glColor3us) +ANT_GL_IMPL(glColor3usv) +ANT_GL_IMPL(glColor4b) +ANT_GL_IMPL(glColor4bv) +ANT_GL_IMPL(glColor4d) +ANT_GL_IMPL(glColor4dv) +ANT_GL_IMPL(glColor4f) +ANT_GL_IMPL(glColor4fv) +ANT_GL_IMPL(glColor4i) +ANT_GL_IMPL(glColor4iv) +ANT_GL_IMPL(glColor4s) +ANT_GL_IMPL(glColor4sv) +ANT_GL_IMPL(glColor4ub) +ANT_GL_IMPL(glColor4ubv) +ANT_GL_IMPL(glColor4ui) +ANT_GL_IMPL(glColor4uiv) +ANT_GL_IMPL(glColor4us) +ANT_GL_IMPL(glColor4usv) +ANT_GL_IMPL(glColorMask) +ANT_GL_IMPL(glColorMaterial) +ANT_GL_IMPL(glColorPointer) +ANT_GL_IMPL(glCopyPixels) +ANT_GL_IMPL(glCopyTexImage1D) +ANT_GL_IMPL(glCopyTexImage2D) +ANT_GL_IMPL(glCopyTexSubImage1D) +ANT_GL_IMPL(glCopyTexSubImage2D) +ANT_GL_IMPL(glCullFace) +ANT_GL_IMPL(glDeleteLists) +ANT_GL_IMPL(glDeleteTextures) +ANT_GL_IMPL(glDepthFunc) +ANT_GL_IMPL(glDepthMask) +ANT_GL_IMPL(glDepthRange) +ANT_GL_IMPL(glDisable) +ANT_GL_IMPL(glDisableClientState) +ANT_GL_IMPL(glDrawArrays) +ANT_GL_IMPL(glDrawBuffer) +ANT_GL_IMPL(glDrawElements) +ANT_GL_IMPL(glDrawPixels) +ANT_GL_IMPL(glEdgeFlag) +ANT_GL_IMPL(glEdgeFlagPointer) +ANT_GL_IMPL(glEdgeFlagv) +ANT_GL_IMPL(glEnable) +ANT_GL_IMPL(glEnableClientState) +ANT_GL_IMPL(glEnd) +ANT_GL_IMPL(glEndList) +ANT_GL_IMPL(glEvalCoord1d) +ANT_GL_IMPL(glEvalCoord1dv) +ANT_GL_IMPL(glEvalCoord1f) +ANT_GL_IMPL(glEvalCoord1fv) +ANT_GL_IMPL(glEvalCoord2d) +ANT_GL_IMPL(glEvalCoord2dv) +ANT_GL_IMPL(glEvalCoord2f) +ANT_GL_IMPL(glEvalCoord2fv) +ANT_GL_IMPL(glEvalMesh1) +ANT_GL_IMPL(glEvalMesh2) +ANT_GL_IMPL(glEvalPoint1) +ANT_GL_IMPL(glEvalPoint2) +ANT_GL_IMPL(glFeedbackBuffer) +ANT_GL_IMPL(glFinish) +ANT_GL_IMPL(glFlush) +ANT_GL_IMPL(glFogf) +ANT_GL_IMPL(glFogfv) +ANT_GL_IMPL(glFogi) +ANT_GL_IMPL(glFogiv) +ANT_GL_IMPL(glFrontFace) +ANT_GL_IMPL(glFrustum) +ANT_GL_IMPL(glGenLists) +ANT_GL_IMPL(glGenTextures) +ANT_GL_IMPL(glGetBooleanv) +ANT_GL_IMPL(glGetClipPlane) +ANT_GL_IMPL(glGetDoublev) +ANT_GL_IMPL(glGetError) +ANT_GL_IMPL(glGetFloatv) +ANT_GL_IMPL(glGetIntegerv) +ANT_GL_IMPL(glGetLightfv) +ANT_GL_IMPL(glGetLightiv) +ANT_GL_IMPL(glGetMapdv) +ANT_GL_IMPL(glGetMapfv) +ANT_GL_IMPL(glGetMapiv) +ANT_GL_IMPL(glGetMaterialfv) +ANT_GL_IMPL(glGetMaterialiv) +ANT_GL_IMPL(glGetPixelMapfv) +ANT_GL_IMPL(glGetPixelMapuiv) +ANT_GL_IMPL(glGetPixelMapusv) +ANT_GL_IMPL(glGetPointerv) +ANT_GL_IMPL(glGetPolygonStipple) +ANT_GL_IMPL(glGetString) +ANT_GL_IMPL(glGetTexEnvfv) +ANT_GL_IMPL(glGetTexEnviv) +ANT_GL_IMPL(glGetTexGendv) +ANT_GL_IMPL(glGetTexGenfv) +ANT_GL_IMPL(glGetTexGeniv) +ANT_GL_IMPL(glGetTexImage) +ANT_GL_IMPL(glGetTexLevelParameterfv) +ANT_GL_IMPL(glGetTexLevelParameteriv) +ANT_GL_IMPL(glGetTexParameterfv) +ANT_GL_IMPL(glGetTexParameteriv) +ANT_GL_IMPL(glHint) +ANT_GL_IMPL(glIndexMask) +ANT_GL_IMPL(glIndexPointer) +ANT_GL_IMPL(glIndexd) +ANT_GL_IMPL(glIndexdv) +ANT_GL_IMPL(glIndexf) +ANT_GL_IMPL(glIndexfv) +ANT_GL_IMPL(glIndexi) +ANT_GL_IMPL(glIndexiv) +ANT_GL_IMPL(glIndexs) +ANT_GL_IMPL(glIndexsv) +ANT_GL_IMPL(glIndexub) +ANT_GL_IMPL(glIndexubv) +ANT_GL_IMPL(glInitNames) +ANT_GL_IMPL(glInterleavedArrays) +ANT_GL_IMPL(glIsEnabled) +ANT_GL_IMPL(glIsList) +ANT_GL_IMPL(glIsTexture) +ANT_GL_IMPL(glLightModelf) +ANT_GL_IMPL(glLightModelfv) +ANT_GL_IMPL(glLightModeli) +ANT_GL_IMPL(glLightModeliv) +ANT_GL_IMPL(glLightf) +ANT_GL_IMPL(glLightfv) +ANT_GL_IMPL(glLighti) +ANT_GL_IMPL(glLightiv) +ANT_GL_IMPL(glLineStipple) +ANT_GL_IMPL(glLineWidth) +ANT_GL_IMPL(glListBase) +ANT_GL_IMPL(glLoadIdentity) +ANT_GL_IMPL(glLoadMatrixd) +ANT_GL_IMPL(glLoadMatrixf) +ANT_GL_IMPL(glLoadName) +ANT_GL_IMPL(glLogicOp) +ANT_GL_IMPL(glMap1d) +ANT_GL_IMPL(glMap1f) +ANT_GL_IMPL(glMap2d) +ANT_GL_IMPL(glMap2f) +ANT_GL_IMPL(glMapGrid1d) +ANT_GL_IMPL(glMapGrid1f) +ANT_GL_IMPL(glMapGrid2d) +ANT_GL_IMPL(glMapGrid2f) +ANT_GL_IMPL(glMaterialf) +ANT_GL_IMPL(glMaterialfv) +ANT_GL_IMPL(glMateriali) +ANT_GL_IMPL(glMaterialiv) +ANT_GL_IMPL(glMatrixMode) +ANT_GL_IMPL(glMultMatrixd) +ANT_GL_IMPL(glMultMatrixf) +ANT_GL_IMPL(glNewList) +ANT_GL_IMPL(glNormal3b) +ANT_GL_IMPL(glNormal3bv) +ANT_GL_IMPL(glNormal3d) +ANT_GL_IMPL(glNormal3dv) +ANT_GL_IMPL(glNormal3f) +ANT_GL_IMPL(glNormal3fv) +ANT_GL_IMPL(glNormal3i) +ANT_GL_IMPL(glNormal3iv) +ANT_GL_IMPL(glNormal3s) +ANT_GL_IMPL(glNormal3sv) +ANT_GL_IMPL(glNormalPointer) +ANT_GL_IMPL(glOrtho) +ANT_GL_IMPL(glPassThrough) +ANT_GL_IMPL(glPixelMapfv) +ANT_GL_IMPL(glPixelMapuiv) +ANT_GL_IMPL(glPixelMapusv) +ANT_GL_IMPL(glPixelStoref) +ANT_GL_IMPL(glPixelStorei) +ANT_GL_IMPL(glPixelTransferf) +ANT_GL_IMPL(glPixelTransferi) +ANT_GL_IMPL(glPixelZoom) +ANT_GL_IMPL(glPointSize) +ANT_GL_IMPL(glPolygonMode) +ANT_GL_IMPL(glPolygonOffset) +ANT_GL_IMPL(glPolygonStipple) +ANT_GL_IMPL(glPopAttrib) +ANT_GL_IMPL(glPopClientAttrib) +ANT_GL_IMPL(glPopMatrix) +ANT_GL_IMPL(glPopName) +ANT_GL_IMPL(glPrioritizeTextures) +ANT_GL_IMPL(glPushAttrib) +ANT_GL_IMPL(glPushClientAttrib) +ANT_GL_IMPL(glPushMatrix) +ANT_GL_IMPL(glPushName) +ANT_GL_IMPL(glRasterPos2d) +ANT_GL_IMPL(glRasterPos2dv) +ANT_GL_IMPL(glRasterPos2f) +ANT_GL_IMPL(glRasterPos2fv) +ANT_GL_IMPL(glRasterPos2i) +ANT_GL_IMPL(glRasterPos2iv) +ANT_GL_IMPL(glRasterPos2s) +ANT_GL_IMPL(glRasterPos2sv) +ANT_GL_IMPL(glRasterPos3d) +ANT_GL_IMPL(glRasterPos3dv) +ANT_GL_IMPL(glRasterPos3f) +ANT_GL_IMPL(glRasterPos3fv) +ANT_GL_IMPL(glRasterPos3i) +ANT_GL_IMPL(glRasterPos3iv) +ANT_GL_IMPL(glRasterPos3s) +ANT_GL_IMPL(glRasterPos3sv) +ANT_GL_IMPL(glRasterPos4d) +ANT_GL_IMPL(glRasterPos4dv) +ANT_GL_IMPL(glRasterPos4f) +ANT_GL_IMPL(glRasterPos4fv) +ANT_GL_IMPL(glRasterPos4i) +ANT_GL_IMPL(glRasterPos4iv) +ANT_GL_IMPL(glRasterPos4s) +ANT_GL_IMPL(glRasterPos4sv) +ANT_GL_IMPL(glReadBuffer) +ANT_GL_IMPL(glReadPixels) +ANT_GL_IMPL(glRectd) +ANT_GL_IMPL(glRectdv) +ANT_GL_IMPL(glRectf) +ANT_GL_IMPL(glRectfv) +ANT_GL_IMPL(glRecti) +ANT_GL_IMPL(glRectiv) +ANT_GL_IMPL(glRects) +ANT_GL_IMPL(glRectsv) +ANT_GL_IMPL(glRenderMode) +ANT_GL_IMPL(glRotated) +ANT_GL_IMPL(glRotatef) +ANT_GL_IMPL(glScaled) +ANT_GL_IMPL(glScalef) +ANT_GL_IMPL(glScissor) +ANT_GL_IMPL(glSelectBuffer) +ANT_GL_IMPL(glShadeModel) +ANT_GL_IMPL(glStencilFunc) +ANT_GL_IMPL(glStencilMask) +ANT_GL_IMPL(glStencilOp) +ANT_GL_IMPL(glTexCoord1d) +ANT_GL_IMPL(glTexCoord1dv) +ANT_GL_IMPL(glTexCoord1f) +ANT_GL_IMPL(glTexCoord1fv) +ANT_GL_IMPL(glTexCoord1i) +ANT_GL_IMPL(glTexCoord1iv) +ANT_GL_IMPL(glTexCoord1s) +ANT_GL_IMPL(glTexCoord1sv) +ANT_GL_IMPL(glTexCoord2d) +ANT_GL_IMPL(glTexCoord2dv) +ANT_GL_IMPL(glTexCoord2f) +ANT_GL_IMPL(glTexCoord2fv) +ANT_GL_IMPL(glTexCoord2i) +ANT_GL_IMPL(glTexCoord2iv) +ANT_GL_IMPL(glTexCoord2s) +ANT_GL_IMPL(glTexCoord2sv) +ANT_GL_IMPL(glTexCoord3d) +ANT_GL_IMPL(glTexCoord3dv) +ANT_GL_IMPL(glTexCoord3f) +ANT_GL_IMPL(glTexCoord3fv) +ANT_GL_IMPL(glTexCoord3i) +ANT_GL_IMPL(glTexCoord3iv) +ANT_GL_IMPL(glTexCoord3s) +ANT_GL_IMPL(glTexCoord3sv) +ANT_GL_IMPL(glTexCoord4d) +ANT_GL_IMPL(glTexCoord4dv) +ANT_GL_IMPL(glTexCoord4f) +ANT_GL_IMPL(glTexCoord4fv) +ANT_GL_IMPL(glTexCoord4i) +ANT_GL_IMPL(glTexCoord4iv) +ANT_GL_IMPL(glTexCoord4s) +ANT_GL_IMPL(glTexCoord4sv) +ANT_GL_IMPL(glTexCoordPointer) +ANT_GL_IMPL(glTexEnvf) +ANT_GL_IMPL(glTexEnvfv) +ANT_GL_IMPL(glTexEnvi) +ANT_GL_IMPL(glTexEnviv) +ANT_GL_IMPL(glTexGend) +ANT_GL_IMPL(glTexGendv) +ANT_GL_IMPL(glTexGenf) +ANT_GL_IMPL(glTexGenfv) +ANT_GL_IMPL(glTexGeni) +ANT_GL_IMPL(glTexGeniv) +ANT_GL_IMPL(glTexImage1D) +ANT_GL_IMPL(glTexImage2D) +ANT_GL_IMPL(glTexParameterf) +ANT_GL_IMPL(glTexParameterfv) +ANT_GL_IMPL(glTexParameteri) +ANT_GL_IMPL(glTexParameteriv) +ANT_GL_IMPL(glTexSubImage1D) +ANT_GL_IMPL(glTexSubImage2D) +ANT_GL_IMPL(glTranslated) +ANT_GL_IMPL(glTranslatef) +ANT_GL_IMPL(glVertex2d) +ANT_GL_IMPL(glVertex2dv) +ANT_GL_IMPL(glVertex2f) +ANT_GL_IMPL(glVertex2fv) +ANT_GL_IMPL(glVertex2i) +ANT_GL_IMPL(glVertex2iv) +ANT_GL_IMPL(glVertex2s) +ANT_GL_IMPL(glVertex2sv) +ANT_GL_IMPL(glVertex3d) +ANT_GL_IMPL(glVertex3dv) +ANT_GL_IMPL(glVertex3f) +ANT_GL_IMPL(glVertex3fv) +ANT_GL_IMPL(glVertex3i) +ANT_GL_IMPL(glVertex3iv) +ANT_GL_IMPL(glVertex3s) +ANT_GL_IMPL(glVertex3sv) +ANT_GL_IMPL(glVertex4d) +ANT_GL_IMPL(glVertex4dv) +ANT_GL_IMPL(glVertex4f) +ANT_GL_IMPL(glVertex4fv) +ANT_GL_IMPL(glVertex4i) +ANT_GL_IMPL(glVertex4iv) +ANT_GL_IMPL(glVertex4s) +ANT_GL_IMPL(glVertex4sv) +ANT_GL_IMPL(glVertexPointer) +ANT_GL_IMPL(glViewport) +#if defined(ANT_WINDOWS) +ANT_GL_IMPL(wglGetProcAddress) +#endif + +namespace GL { PFNGLGetProcAddress _glGetProcAddress = NULL; } + +// --------------------------------------------------------------------------- + +#if defined(ANT_WINDOWS) + + // --------------------------------------------------------------------------- + + int LoadOpenGL() + { + if( g_OGLModule!=NULL ) + { + return 1; // "OpenGL library already loaded" + } + + g_OGLModule = LoadLibrary("OPENGL32.DLL"); + if( g_OGLModule ) + { + // Info(VERB_LOW, "Load %d OpenGL functions", g_NbOGLFunc); + + int Res = 1; + for(int i=0; i0); + *(g_OGLFuncRec[i].m_FuncPtr) = reinterpret_cast(GetProcAddress(g_OGLModule, g_OGLFuncRec[i].m_Name)); + if( *(g_OGLFuncRec[i].m_FuncPtr)==NULL ) + Res = 0; // Error("cannot find OpenGL function"); + + } + + _glGetProcAddress = reinterpret_cast(_wglGetProcAddress); + if( _glGetProcAddress==NULL ) + Res = 0; + + return Res; + } + else + { + // InternDisplayLastErrorWIN("Cannot load opengl32 DLL", false); + return 0; // cannot load DLL + } + } + + // --------------------------------------------------------------------------- + + int UnloadOpenGL() + { + if( g_OGLModule==NULL ) + { + return 1; // "OpenGL library not loaded" + } + + // Info(VERB_LOW, "Unload %d OpenGL functions", g_NbOGLFunc); + for(int i=0; i0); + *(g_OGLFuncRec[i].m_FuncPtr) = NULL; + } + if( FreeLibrary(g_OGLModule) ) + { + // Info(VERB_LOW, "OpenGL library unloaded"); + g_OGLModule = NULL; + return 1; + } + else + { + // InternDisplayLastErrorWIN("Cannot unload opengl32 DLL", false); + return 0; // cannot unload opengl32.dll + } + } + + // --------------------------------------------------------------------------- + + namespace GL + { + + PFNOpenGL Record(const char *_FuncName, PFNOpenGL *_FuncPtr) + { + if( g_NbOGLFunc>=ANT_NB_OGL_FUNC_MAX ) + { + fprintf(stderr, "Too many OpenGL functions declared. Change ANT_NB_OGL_FUNC_MAX."); + exit(-1); + } + + g_OGLFuncRec[g_NbOGLFunc].m_Name = _FuncName; + g_OGLFuncRec[g_NbOGLFunc].m_FuncPtr = _FuncPtr; + ++g_NbOGLFunc; + + return NULL; + } + + } // namespace GL + + // --------------------------------------------------------------------------- + +#endif // defined(ANT_WINDOWS) + +// --------------------------------------------------------------------------- + +#if defined(ANT_UNIX) + + int LoadOpenGL() + { + _glGetProcAddress = reinterpret_cast(glXGetProcAddressARB); + + return 1; // "OpenGL library is statically linked" + } + + int UnloadOpenGL() + { + return 1; // "OpenGL library is statically linked" + } + +#endif // defined(ANT_UNIX) + +// --------------------------------------------------------------------------- diff --git a/Extras/CDTestFramework/AntTweakBar/src/LoadOGL.h b/Extras/CDTestFramework/AntTweakBar/src/LoadOGL.h new file mode 100644 index 0000000..a963b99 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/LoadOGL.h @@ -0,0 +1,393 @@ +// --------------------------------------------------------------------------- +// +// @file LoadOGL.h +// @brief OpenGL declarations for dynamic loading +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// notes: Private header +// TAB=4 +// +// --------------------------------------------------------------------------- + + +#if !defined ANT_LOAD_OGL_INCLUDED +#define ANT_LOAD_OGL_INCLUDED + + +#define ANT_GL_DECL(_Ret, _Fct, _Params) \ + extern "C" { typedef _Ret (APIENTRY* PFN##_Fct)_Params; } \ + namespace GL { extern PFN##_Fct _##_Fct; } \ + using GL::_##_Fct; + +#if defined(ANT_WINDOWS) +# define ANT_GL_IMPL(_Fct) \ + namespace GL { PFN##_Fct _##_Fct = (PFN##_Fct)Record(#_Fct, (PFNOpenGL*)(&_##_Fct)); } +#elif defined(ANT_UNIX) +# define ANT_GL_IMPL(_Fct) \ + namespace GL { PFN##_Fct _##_Fct = _Fct; } +# if !defined(APIENTRY) +# define APIENTRY +# endif +#endif + + +int LoadOpenGL(); +int UnloadOpenGL(); + +namespace GL +{ + extern "C" { typedef void (APIENTRY* PFNOpenGL)(); } + PFNOpenGL Record(const char *_FuncName, PFNOpenGL *_FuncPtr); + + extern "C" { typedef PFNOpenGL (APIENTRY *PFNGLGetProcAddress)(const char *); } + extern PFNGLGetProcAddress _glGetProcAddress; +} +using GL::_glGetProcAddress; + + +ANT_GL_DECL(void, glAccum, (GLenum op, GLfloat value)) +ANT_GL_DECL(void, glAlphaFunc, (GLenum func, GLclampf ref)) +ANT_GL_DECL(GLboolean, glAreTexturesResident, (GLsizei n, const GLuint *textures, GLboolean *residences)) +ANT_GL_DECL(void, glArrayElement, (GLint i)) +ANT_GL_DECL(void, glBegin, (GLenum mode)) +ANT_GL_DECL(void, glBindTexture, (GLenum target, GLuint texture)) +ANT_GL_DECL(void, glBitmap, (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap)) +ANT_GL_DECL(void, glBlendFunc, (GLenum sfactor, GLenum dfactor)) +ANT_GL_DECL(void, glCallList, (GLuint list)) +ANT_GL_DECL(void, glCallLists, (GLsizei n, GLenum type, const GLvoid *lists)) +ANT_GL_DECL(void, glClear, (GLbitfield mask)) +ANT_GL_DECL(void, glClearAccum, (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)) +ANT_GL_DECL(void, glClearColor, (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)) +ANT_GL_DECL(void, glClearDepth, (GLclampd depth)) +ANT_GL_DECL(void, glClearIndex, (GLfloat c)) +ANT_GL_DECL(void, glClearStencil, (GLint s)) +ANT_GL_DECL(void, glClipPlane, (GLenum plane, const GLdouble *equation)) +ANT_GL_DECL(void, glColor3b, (GLbyte red, GLbyte green, GLbyte blue)) +ANT_GL_DECL(void, glColor3bv, (const GLbyte *v)) +ANT_GL_DECL(void, glColor3d, (GLdouble red, GLdouble green, GLdouble blue)) +ANT_GL_DECL(void, glColor3dv, (const GLdouble *v)) +ANT_GL_DECL(void, glColor3f, (GLfloat red, GLfloat green, GLfloat blue)) +ANT_GL_DECL(void, glColor3fv, (const GLfloat *v)) +ANT_GL_DECL(void, glColor3i, (GLint red, GLint green, GLint blue)) +ANT_GL_DECL(void, glColor3iv, (const GLint *v)) +ANT_GL_DECL(void, glColor3s, (GLshort red, GLshort green, GLshort blue)) +ANT_GL_DECL(void, glColor3sv, (const GLshort *v)) +ANT_GL_DECL(void, glColor3ub, (GLubyte red, GLubyte green, GLubyte blue)) +ANT_GL_DECL(void, glColor3ubv, (const GLubyte *v)) +ANT_GL_DECL(void, glColor3ui, (GLuint red, GLuint green, GLuint blue)) +ANT_GL_DECL(void, glColor3uiv, (const GLuint *v)) +ANT_GL_DECL(void, glColor3us, (GLushort red, GLushort green, GLushort blue)) +ANT_GL_DECL(void, glColor3usv, (const GLushort *v)) +ANT_GL_DECL(void, glColor4b, (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha)) +ANT_GL_DECL(void, glColor4bv, (const GLbyte *v)) +ANT_GL_DECL(void, glColor4d, (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha)) +ANT_GL_DECL(void, glColor4dv, (const GLdouble *v)) +ANT_GL_DECL(void, glColor4f, (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)) +ANT_GL_DECL(void, glColor4fv, (const GLfloat *v)) +ANT_GL_DECL(void, glColor4i, (GLint red, GLint green, GLint blue, GLint alpha)) +ANT_GL_DECL(void, glColor4iv, (const GLint *v)) +ANT_GL_DECL(void, glColor4s, (GLshort red, GLshort green, GLshort blue, GLshort alpha)) +ANT_GL_DECL(void, glColor4sv, (const GLshort *v)) +ANT_GL_DECL(void, glColor4ub, (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)) +ANT_GL_DECL(void, glColor4ubv, (const GLubyte *v)) +ANT_GL_DECL(void, glColor4ui, (GLuint red, GLuint green, GLuint blue, GLuint alpha)) +ANT_GL_DECL(void, glColor4uiv, (const GLuint *v)) +ANT_GL_DECL(void, glColor4us, (GLushort red, GLushort green, GLushort blue, GLushort alpha)) +ANT_GL_DECL(void, glColor4usv, (const GLushort *v)) +ANT_GL_DECL(void, glColorMask, (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)) +ANT_GL_DECL(void, glColorMaterial, (GLenum face, GLenum mode)) +ANT_GL_DECL(void, glColorPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)) +ANT_GL_DECL(void, glCopyPixels, (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)) +ANT_GL_DECL(void, glCopyTexImage1D, (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border)) +ANT_GL_DECL(void, glCopyTexImage2D, (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)) +ANT_GL_DECL(void, glCopyTexSubImage1D, (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width)) +ANT_GL_DECL(void, glCopyTexSubImage2D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)) +ANT_GL_DECL(void, glCullFace, (GLenum mode)) +ANT_GL_DECL(void, glDeleteLists, (GLuint list, GLsizei range)) +ANT_GL_DECL(void, glDeleteTextures, (GLsizei n, const GLuint *textures)) +ANT_GL_DECL(void, glDepthFunc, (GLenum func)) +ANT_GL_DECL(void, glDepthMask, (GLboolean flag)) +ANT_GL_DECL(void, glDepthRange, (GLclampd zNear, GLclampd zFar)) +ANT_GL_DECL(void, glDisable, (GLenum cap)) +ANT_GL_DECL(void, glDisableClientState, (GLenum array)) +ANT_GL_DECL(void, glDrawArrays, (GLenum mode, GLint first, GLsizei count)) +ANT_GL_DECL(void, glDrawBuffer, (GLenum mode)) +ANT_GL_DECL(void, glDrawElements, (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)) +ANT_GL_DECL(void, glDrawPixels, (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)) +ANT_GL_DECL(void, glEdgeFlag, (GLboolean flag)) +ANT_GL_DECL(void, glEdgeFlagPointer, (GLsizei stride, const void *pointer)) +ANT_GL_DECL(void, glEdgeFlagv, (const GLboolean *flag)) +ANT_GL_DECL(void, glEnable, (GLenum cap)) +ANT_GL_DECL(void, glEnableClientState, (GLenum array)) +ANT_GL_DECL(void, glEnd, (void)) +ANT_GL_DECL(void, glEndList, (void)) +ANT_GL_DECL(void, glEvalCoord1d, (GLdouble u)) +ANT_GL_DECL(void, glEvalCoord1dv, (const GLdouble *u)) +ANT_GL_DECL(void, glEvalCoord1f, (GLfloat u)) +ANT_GL_DECL(void, glEvalCoord1fv, (const GLfloat *u)) +ANT_GL_DECL(void, glEvalCoord2d, (GLdouble u, GLdouble v)) +ANT_GL_DECL(void, glEvalCoord2dv, (const GLdouble *u)) +ANT_GL_DECL(void, glEvalCoord2f, (GLfloat u, GLfloat v)) +ANT_GL_DECL(void, glEvalCoord2fv, (const GLfloat *u)) +ANT_GL_DECL(void, glEvalMesh1, (GLenum mode, GLint i1, GLint i2)) +ANT_GL_DECL(void, glEvalMesh2, (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)) +ANT_GL_DECL(void, glEvalPoint1, (GLint i)) +ANT_GL_DECL(void, glEvalPoint2, (GLint i, GLint j)) +ANT_GL_DECL(void, glFeedbackBuffer, (GLsizei size, GLenum type, GLfloat *buffer)) +ANT_GL_DECL(void, glFinish, (void)) +ANT_GL_DECL(void, glFlush, (void)) +ANT_GL_DECL(void, glFogf, (GLenum pname, GLfloat param)) +ANT_GL_DECL(void, glFogfv, (GLenum pname, const GLfloat *params)) +ANT_GL_DECL(void, glFogi, (GLenum pname, GLint param)) +ANT_GL_DECL(void, glFogiv, (GLenum pname, const GLint *params)) +ANT_GL_DECL(void, glFrontFace, (GLenum mode)) +ANT_GL_DECL(void, glFrustum, (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)) +ANT_GL_DECL(GLuint, glGenLists, (GLsizei range)) +ANT_GL_DECL(void, glGenTextures, (GLsizei n, GLuint *textures)) +ANT_GL_DECL(void, glGetBooleanv, (GLenum pname, GLboolean *params)) +ANT_GL_DECL(void, glGetClipPlane, (GLenum plane, GLdouble *equation)) +ANT_GL_DECL(void, glGetDoublev, (GLenum pname, GLdouble *params)) +ANT_GL_DECL(GLenum, glGetError, (void)) +ANT_GL_DECL(void, glGetFloatv, (GLenum pname, GLfloat *params)) +ANT_GL_DECL(void, glGetIntegerv, (GLenum pname, GLint *params)) +ANT_GL_DECL(void, glGetLightfv, (GLenum light, GLenum pname, GLfloat *params)) +ANT_GL_DECL(void, glGetLightiv, (GLenum light, GLenum pname, GLint *params)) +ANT_GL_DECL(void, glGetMapdv, (GLenum target, GLenum query, GLdouble *v)) +ANT_GL_DECL(void, glGetMapfv, (GLenum target, GLenum query, GLfloat *v)) +ANT_GL_DECL(void, glGetMapiv, (GLenum target, GLenum query, GLint *v)) +ANT_GL_DECL(void, glGetMaterialfv, (GLenum face, GLenum pname, GLfloat *params)) +ANT_GL_DECL(void, glGetMaterialiv, (GLenum face, GLenum pname, GLint *params)) +ANT_GL_DECL(void, glGetPixelMapfv, (GLenum map, GLfloat *values)) +ANT_GL_DECL(void, glGetPixelMapuiv, (GLenum map, GLuint *values)) +ANT_GL_DECL(void, glGetPixelMapusv, (GLenum map, GLushort *values)) +ANT_GL_DECL(void, glGetPointerv, (GLenum pname, GLvoid* *params)) +ANT_GL_DECL(void, glGetPolygonStipple, (GLubyte *mask)) +ANT_GL_DECL(const GLubyte *, glGetString, (GLenum name)) +ANT_GL_DECL(void, glGetTexEnvfv, (GLenum target, GLenum pname, GLfloat *params)) +ANT_GL_DECL(void, glGetTexEnviv, (GLenum target, GLenum pname, GLint *params)) +ANT_GL_DECL(void, glGetTexGendv, (GLenum coord, GLenum pname, GLdouble *params)) +ANT_GL_DECL(void, glGetTexGenfv, (GLenum coord, GLenum pname, GLfloat *params)) +ANT_GL_DECL(void, glGetTexGeniv, (GLenum coord, GLenum pname, GLint *params)) +ANT_GL_DECL(void, glGetTexImage, (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels)) +ANT_GL_DECL(void, glGetTexLevelParameterfv, (GLenum target, GLint level, GLenum pname, GLfloat *params)) +ANT_GL_DECL(void, glGetTexLevelParameteriv, (GLenum target, GLint level, GLenum pname, GLint *params)) +ANT_GL_DECL(void, glGetTexParameterfv, (GLenum target, GLenum pname, GLfloat *params)) +ANT_GL_DECL(void, glGetTexParameteriv, (GLenum target, GLenum pname, GLint *params)) +ANT_GL_DECL(void, glHint, (GLenum target, GLenum mode)) +ANT_GL_DECL(void, glIndexMask, (GLuint mask)) +ANT_GL_DECL(void, glIndexPointer, (GLenum type, GLsizei stride, const GLvoid *pointer)) +ANT_GL_DECL(void, glIndexd, (GLdouble c)) +ANT_GL_DECL(void, glIndexdv, (const GLdouble *c)) +ANT_GL_DECL(void, glIndexf, (GLfloat c)) +ANT_GL_DECL(void, glIndexfv, (const GLfloat *c)) +ANT_GL_DECL(void, glIndexi, (GLint c)) +ANT_GL_DECL(void, glIndexiv, (const GLint *c)) +ANT_GL_DECL(void, glIndexs, (GLshort c)) +ANT_GL_DECL(void, glIndexsv, (const GLshort *c)) +ANT_GL_DECL(void, glIndexub, (GLubyte c)) +ANT_GL_DECL(void, glIndexubv, (const GLubyte *c)) +ANT_GL_DECL(void, glInitNames, (void)) +ANT_GL_DECL(void, glInterleavedArrays, (GLenum format, GLsizei stride, const GLvoid *pointer)) +ANT_GL_DECL(GLboolean, glIsEnabled, (GLenum cap)) +ANT_GL_DECL(GLboolean, glIsList, (GLuint list)) +ANT_GL_DECL(GLboolean, glIsTexture, (GLuint texture)) +ANT_GL_DECL(void, glLightModelf, (GLenum pname, GLfloat param)) +ANT_GL_DECL(void, glLightModelfv, (GLenum pname, const GLfloat *params)) +ANT_GL_DECL(void, glLightModeli, (GLenum pname, GLint param)) +ANT_GL_DECL(void, glLightModeliv, (GLenum pname, const GLint *params)) +ANT_GL_DECL(void, glLightf, (GLenum light, GLenum pname, GLfloat param)) +ANT_GL_DECL(void, glLightfv, (GLenum light, GLenum pname, const GLfloat *params)) +ANT_GL_DECL(void, glLighti, (GLenum light, GLenum pname, GLint param)) +ANT_GL_DECL(void, glLightiv, (GLenum light, GLenum pname, const GLint *params)) +ANT_GL_DECL(void, glLineStipple, (GLint factor, GLushort pattern)) +ANT_GL_DECL(void, glLineWidth, (GLfloat width)) +ANT_GL_DECL(void, glListBase, (GLuint base)) +ANT_GL_DECL(void, glLoadIdentity, (void)) +ANT_GL_DECL(void, glLoadMatrixd, (const GLdouble *m)) +ANT_GL_DECL(void, glLoadMatrixf, (const GLfloat *m)) +ANT_GL_DECL(void, glLoadName, (GLuint name)) +ANT_GL_DECL(void, glLogicOp, (GLenum opcode)) +ANT_GL_DECL(void, glMap1d, (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points)) +ANT_GL_DECL(void, glMap1f, (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points)) +ANT_GL_DECL(void, glMap2d, (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points)) +ANT_GL_DECL(void, glMap2f, (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points)) +ANT_GL_DECL(void, glMapGrid1d, (GLint un, GLdouble u1, GLdouble u2)) +ANT_GL_DECL(void, glMapGrid1f, (GLint un, GLfloat u1, GLfloat u2)) +ANT_GL_DECL(void, glMapGrid2d, (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2)) +ANT_GL_DECL(void, glMapGrid2f, (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2)) +ANT_GL_DECL(void, glMaterialf, (GLenum face, GLenum pname, GLfloat param)) +ANT_GL_DECL(void, glMaterialfv, (GLenum face, GLenum pname, const GLfloat *params)) +ANT_GL_DECL(void, glMateriali, (GLenum face, GLenum pname, GLint param)) +ANT_GL_DECL(void, glMaterialiv, (GLenum face, GLenum pname, const GLint *params)) +ANT_GL_DECL(void, glMatrixMode, (GLenum mode)) +ANT_GL_DECL(void, glMultMatrixd, (const GLdouble *m)) +ANT_GL_DECL(void, glMultMatrixf, (const GLfloat *m)) +ANT_GL_DECL(void, glNewList, (GLuint list, GLenum mode)) +ANT_GL_DECL(void, glNormal3b, (GLbyte nx, GLbyte ny, GLbyte nz)) +ANT_GL_DECL(void, glNormal3bv, (const GLbyte *v)) +ANT_GL_DECL(void, glNormal3d, (GLdouble nx, GLdouble ny, GLdouble nz)) +ANT_GL_DECL(void, glNormal3dv, (const GLdouble *v)) +ANT_GL_DECL(void, glNormal3f, (GLfloat nx, GLfloat ny, GLfloat nz)) +ANT_GL_DECL(void, glNormal3fv, (const GLfloat *v)) +ANT_GL_DECL(void, glNormal3i, (GLint nx, GLint ny, GLint nz)) +ANT_GL_DECL(void, glNormal3iv, (const GLint *v)) +ANT_GL_DECL(void, glNormal3s, (GLshort nx, GLshort ny, GLshort nz)) +ANT_GL_DECL(void, glNormal3sv, (const GLshort *v)) +ANT_GL_DECL(void, glNormalPointer, (GLenum type, GLsizei stride, const GLvoid *pointer)) +ANT_GL_DECL(void, glOrtho, (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)) +ANT_GL_DECL(void, glPassThrough, (GLfloat token)) +ANT_GL_DECL(void, glPixelMapfv, (GLenum map, GLsizei mapsize, const GLfloat *values)) +ANT_GL_DECL(void, glPixelMapuiv, (GLenum map, GLsizei mapsize, const GLuint *values)) +ANT_GL_DECL(void, glPixelMapusv, (GLenum map, GLsizei mapsize, const GLushort *values)) +ANT_GL_DECL(void, glPixelStoref, (GLenum pname, GLfloat param)) +ANT_GL_DECL(void, glPixelStorei, (GLenum pname, GLint param)) +ANT_GL_DECL(void, glPixelTransferf, (GLenum pname, GLfloat param)) +ANT_GL_DECL(void, glPixelTransferi, (GLenum pname, GLint param)) +ANT_GL_DECL(void, glPixelZoom, (GLfloat xfactor, GLfloat yfactor)) +ANT_GL_DECL(void, glPointSize, (GLfloat size)) +ANT_GL_DECL(void, glPolygonMode, (GLenum face, GLenum mode)) +ANT_GL_DECL(void, glPolygonOffset, (GLfloat factor, GLfloat units)) +ANT_GL_DECL(void, glPolygonStipple, (const GLubyte *mask)) +ANT_GL_DECL(void, glPopAttrib, (void)) +ANT_GL_DECL(void, glPopClientAttrib, (void)) +ANT_GL_DECL(void, glPopMatrix, (void)) +ANT_GL_DECL(void, glPopName, (void)) +ANT_GL_DECL(void, glPrioritizeTextures, (GLsizei n, const GLuint *textures, const GLclampf *priorities)) +ANT_GL_DECL(void, glPushAttrib, (GLbitfield mask)) +ANT_GL_DECL(void, glPushClientAttrib, (GLbitfield mask)) +ANT_GL_DECL(void, glPushMatrix, (void)) +ANT_GL_DECL(void, glPushName, (GLuint name)) +ANT_GL_DECL(void, glRasterPos2d, (GLdouble x, GLdouble y)) +ANT_GL_DECL(void, glRasterPos2dv, (const GLdouble *v)) +ANT_GL_DECL(void, glRasterPos2f, (GLfloat x, GLfloat y)) +ANT_GL_DECL(void, glRasterPos2fv, (const GLfloat *v)) +ANT_GL_DECL(void, glRasterPos2i, (GLint x, GLint y)) +ANT_GL_DECL(void, glRasterPos2iv, (const GLint *v)) +ANT_GL_DECL(void, glRasterPos2s, (GLshort x, GLshort y)) +ANT_GL_DECL(void, glRasterPos2sv, (const GLshort *v)) +ANT_GL_DECL(void, glRasterPos3d, (GLdouble x, GLdouble y, GLdouble z)) +ANT_GL_DECL(void, glRasterPos3dv, (const GLdouble *v)) +ANT_GL_DECL(void, glRasterPos3f, (GLfloat x, GLfloat y, GLfloat z)) +ANT_GL_DECL(void, glRasterPos3fv, (const GLfloat *v)) +ANT_GL_DECL(void, glRasterPos3i, (GLint x, GLint y, GLint z)) +ANT_GL_DECL(void, glRasterPos3iv, (const GLint *v)) +ANT_GL_DECL(void, glRasterPos3s, (GLshort x, GLshort y, GLshort z)) +ANT_GL_DECL(void, glRasterPos3sv, (const GLshort *v)) +ANT_GL_DECL(void, glRasterPos4d, (GLdouble x, GLdouble y, GLdouble z, GLdouble w)) +ANT_GL_DECL(void, glRasterPos4dv, (const GLdouble *v)) +ANT_GL_DECL(void, glRasterPos4f, (GLfloat x, GLfloat y, GLfloat z, GLfloat w)) +ANT_GL_DECL(void, glRasterPos4fv, (const GLfloat *v)) +ANT_GL_DECL(void, glRasterPos4i, (GLint x, GLint y, GLint z, GLint w)) +ANT_GL_DECL(void, glRasterPos4iv, (const GLint *v)) +ANT_GL_DECL(void, glRasterPos4s, (GLshort x, GLshort y, GLshort z, GLshort w)) +ANT_GL_DECL(void, glRasterPos4sv, (const GLshort *v)) +ANT_GL_DECL(void, glReadBuffer, (GLenum mode)) +ANT_GL_DECL(void, glReadPixels, (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)) +ANT_GL_DECL(void, glRectd, (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)) +ANT_GL_DECL(void, glRectdv, (const GLdouble *v1, const GLdouble *v2)) +ANT_GL_DECL(void, glRectf, (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)) +ANT_GL_DECL(void, glRectfv, (const GLfloat *v1, const GLfloat *v2)) +ANT_GL_DECL(void, glRecti, (GLint x1, GLint y1, GLint x2, GLint y2)) +ANT_GL_DECL(void, glRectiv, (const GLint *v1, const GLint *v2)) +ANT_GL_DECL(void, glRects, (GLshort x1, GLshort y1, GLshort x2, GLshort y2)) +ANT_GL_DECL(void, glRectsv, (const GLshort *v1, const GLshort *v2)) +ANT_GL_DECL(GLint, glRenderMode, (GLenum mode)) +ANT_GL_DECL(void, glRotated, (GLdouble angle, GLdouble x, GLdouble y, GLdouble z)) +ANT_GL_DECL(void, glRotatef, (GLfloat angle, GLfloat x, GLfloat y, GLfloat z)) +ANT_GL_DECL(void, glScaled, (GLdouble x, GLdouble y, GLdouble z)) +ANT_GL_DECL(void, glScalef, (GLfloat x, GLfloat y, GLfloat z)) +ANT_GL_DECL(void, glScissor, (GLint x, GLint y, GLsizei width, GLsizei height)) +ANT_GL_DECL(void, glSelectBuffer, (GLsizei size, GLuint *buffer)) +ANT_GL_DECL(void, glShadeModel, (GLenum mode)) +ANT_GL_DECL(void, glStencilFunc, (GLenum func, GLint ref, GLuint mask)) +ANT_GL_DECL(void, glStencilMask, (GLuint mask)) +ANT_GL_DECL(void, glStencilOp, (GLenum fail, GLenum zfail, GLenum zpass)) +ANT_GL_DECL(void, glTexCoord1d, (GLdouble s)) +ANT_GL_DECL(void, glTexCoord1dv, (const GLdouble *v)) +ANT_GL_DECL(void, glTexCoord1f, (GLfloat s)) +ANT_GL_DECL(void, glTexCoord1fv, (const GLfloat *v)) +ANT_GL_DECL(void, glTexCoord1i, (GLint s)) +ANT_GL_DECL(void, glTexCoord1iv, (const GLint *v)) +ANT_GL_DECL(void, glTexCoord1s, (GLshort s)) +ANT_GL_DECL(void, glTexCoord1sv, (const GLshort *v)) +ANT_GL_DECL(void, glTexCoord2d, (GLdouble s, GLdouble t)) +ANT_GL_DECL(void, glTexCoord2dv, (const GLdouble *v)) +ANT_GL_DECL(void, glTexCoord2f, (GLfloat s, GLfloat t)) +ANT_GL_DECL(void, glTexCoord2fv, (const GLfloat *v)) +ANT_GL_DECL(void, glTexCoord2i, (GLint s, GLint t)) +ANT_GL_DECL(void, glTexCoord2iv, (const GLint *v)) +ANT_GL_DECL(void, glTexCoord2s, (GLshort s, GLshort t)) +ANT_GL_DECL(void, glTexCoord2sv, (const GLshort *v)) +ANT_GL_DECL(void, glTexCoord3d, (GLdouble s, GLdouble t, GLdouble r)) +ANT_GL_DECL(void, glTexCoord3dv, (const GLdouble *v)) +ANT_GL_DECL(void, glTexCoord3f, (GLfloat s, GLfloat t, GLfloat r)) +ANT_GL_DECL(void, glTexCoord3fv, (const GLfloat *v)) +ANT_GL_DECL(void, glTexCoord3i, (GLint s, GLint t, GLint r)) +ANT_GL_DECL(void, glTexCoord3iv, (const GLint *v)) +ANT_GL_DECL(void, glTexCoord3s, (GLshort s, GLshort t, GLshort r)) +ANT_GL_DECL(void, glTexCoord3sv, (const GLshort *v)) +ANT_GL_DECL(void, glTexCoord4d, (GLdouble s, GLdouble t, GLdouble r, GLdouble q)) +ANT_GL_DECL(void, glTexCoord4dv, (const GLdouble *v)) +ANT_GL_DECL(void, glTexCoord4f, (GLfloat s, GLfloat t, GLfloat r, GLfloat q)) +ANT_GL_DECL(void, glTexCoord4fv, (const GLfloat *v)) +ANT_GL_DECL(void, glTexCoord4i, (GLint s, GLint t, GLint r, GLint q)) +ANT_GL_DECL(void, glTexCoord4iv, (const GLint *v)) +ANT_GL_DECL(void, glTexCoord4s, (GLshort s, GLshort t, GLshort r, GLshort q)) +ANT_GL_DECL(void, glTexCoord4sv, (const GLshort *v)) +ANT_GL_DECL(void, glTexCoordPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)) +ANT_GL_DECL(void, glTexEnvf, (GLenum target, GLenum pname, GLfloat param)) +ANT_GL_DECL(void, glTexEnvfv, (GLenum target, GLenum pname, const GLfloat *params)) +ANT_GL_DECL(void, glTexEnvi, (GLenum target, GLenum pname, GLint param)) +ANT_GL_DECL(void, glTexEnviv, (GLenum target, GLenum pname, const GLint *params)) +ANT_GL_DECL(void, glTexGend, (GLenum coord, GLenum pname, GLdouble param)) +ANT_GL_DECL(void, glTexGendv, (GLenum coord, GLenum pname, const GLdouble *params)) +ANT_GL_DECL(void, glTexGenf, (GLenum coord, GLenum pname, GLfloat param)) +ANT_GL_DECL(void, glTexGenfv, (GLenum coord, GLenum pname, const GLfloat *params)) +ANT_GL_DECL(void, glTexGeni, (GLenum coord, GLenum pname, GLint param)) +ANT_GL_DECL(void, glTexGeniv, (GLenum coord, GLenum pname, const GLint *params)) +ANT_GL_DECL(void, glTexImage1D, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels)) +ANT_GL_DECL(void, glTexImage2D, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)) +ANT_GL_DECL(void, glTexParameterf, (GLenum target, GLenum pname, GLfloat param)) +ANT_GL_DECL(void, glTexParameterfv, (GLenum target, GLenum pname, const GLfloat *params)) +ANT_GL_DECL(void, glTexParameteri, (GLenum target, GLenum pname, GLint param)) +ANT_GL_DECL(void, glTexParameteriv, (GLenum target, GLenum pname, const GLint *params)) +ANT_GL_DECL(void, glTexSubImage1D, (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels)) +ANT_GL_DECL(void, glTexSubImage2D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)) +ANT_GL_DECL(void, glTranslated, (GLdouble x, GLdouble y, GLdouble z)) +ANT_GL_DECL(void, glTranslatef, (GLfloat x, GLfloat y, GLfloat z)) +ANT_GL_DECL(void, glVertex2d, (GLdouble x, GLdouble y)) +ANT_GL_DECL(void, glVertex2dv, (const GLdouble *v)) +ANT_GL_DECL(void, glVertex2f, (GLfloat x, GLfloat y)) +ANT_GL_DECL(void, glVertex2fv, (const GLfloat *v)) +ANT_GL_DECL(void, glVertex2i, (GLint x, GLint y)) +ANT_GL_DECL(void, glVertex2iv, (const GLint *v)) +ANT_GL_DECL(void, glVertex2s, (GLshort x, GLshort y)) +ANT_GL_DECL(void, glVertex2sv, (const GLshort *v)) +ANT_GL_DECL(void, glVertex3d, (GLdouble x, GLdouble y, GLdouble z)) +ANT_GL_DECL(void, glVertex3dv, (const GLdouble *v)) +ANT_GL_DECL(void, glVertex3f, (GLfloat x, GLfloat y, GLfloat z)) +ANT_GL_DECL(void, glVertex3fv, (const GLfloat *v)) +ANT_GL_DECL(void, glVertex3i, (GLint x, GLint y, GLint z)) +ANT_GL_DECL(void, glVertex3iv, (const GLint *v)) +ANT_GL_DECL(void, glVertex3s, (GLshort x, GLshort y, GLshort z)) +ANT_GL_DECL(void, glVertex3sv, (const GLshort *v)) +ANT_GL_DECL(void, glVertex4d, (GLdouble x, GLdouble y, GLdouble z, GLdouble w)) +ANT_GL_DECL(void, glVertex4dv, (const GLdouble *v)) +ANT_GL_DECL(void, glVertex4f, (GLfloat x, GLfloat y, GLfloat z, GLfloat w)) +ANT_GL_DECL(void, glVertex4fv, (const GLfloat *v)) +ANT_GL_DECL(void, glVertex4i, (GLint x, GLint y, GLint z, GLint w)) +ANT_GL_DECL(void, glVertex4iv, (const GLint *v)) +ANT_GL_DECL(void, glVertex4s, (GLshort x, GLshort y, GLshort z, GLshort w)) +ANT_GL_DECL(void, glVertex4sv, (const GLshort *v)) +ANT_GL_DECL(void, glVertexPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)) +ANT_GL_DECL(void, glViewport, (GLint x, GLint y, GLsizei width, GLsizei height)) + +#ifdef ANT_WINDOWS +ANT_GL_DECL(PROC, wglGetProcAddress, (LPCSTR)) +#endif + + +#endif // !defined ANT_LOAD_OGL_INCLUDED diff --git a/Extras/CDTestFramework/AntTweakBar/src/Makefile b/Extras/CDTestFramework/AntTweakBar/src/Makefile new file mode 100644 index 0000000..bddb7a2 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/Makefile @@ -0,0 +1,98 @@ +####### Compiler, tools and options + +#---- MinGW +#MINGWFLAGS = -mno-cygwin +#SO_EXT = .dll +#---- LINUX +SO_EXT = .so + +#---- Release +CXXCFG = -O3 +LFLAGS = -Wl,-s +OUT_DIR = ../lib +#---- Debug +#CXXCFG = -g -D_DEBUG +#LFLAGS = +#OUT_DIR = ../lib/debug + + +CXX = gcc +#CXXFLAGS = $(CXXCFG) $(MINGWFLAGS) -pipe -Wall -fomit-frame-pointer -mcpu=pentiumpro -march=i586 -ffast-math -fno-strength-reduce -fpic -D_UNIX -D__PLACEMENT_NEW_INLINE +CXXFLAGS = $(CXXCFG) $(MINGWFLAGS) -Wall -ffast-math -mcpu=i386 -march=i386 -fPIC -D_UNIX -D__PLACEMENT_NEW_INLINE +INCPATH = -I/usr/X11R6/include -I/usr/include -I../include +LINK = gcc +#LIBS = -L/usr/X11R6/lib -L. -lglfw -lGL -lGLU -lX11 -lXxf86vm -lXext -lpthread -lm +#LIBS = -L/usr/X11R6/lib -lGL -lX11 -lXxf86vm -lXext -lpthread -lm +LIBS = +AR = ar cqs +RANLIB = +TAR = tar -cf +GZIP = gzip -9f +COPY = cp -f +COPY_FILE = $(COPY) -p +COPY_DIR = $(COPY) -pR +DEL_FILE = rm -f +SYMLINK = ln -sf +DEL_DIR = rmdir +MOVE = mv +NO_STDERR = 2> /dev/null + + +####### Files + + +# name of the application: +TARGET = AntTweakBar + +# source files without extension: +SRC_FILES = TwColors.cpp TwFonts.cpp TwOpenGL.cpp TwBar.cpp TwMgr.cpp TwPrecomp.cpp LoadOGL.cpp TwEventGLFW.c TwEventGLUT.c TwEventSDL.c + +# build object list from source files +OBJS_1 = $(SRC_FILES:.c=.o) +OBJS = $(OBJS_1:.cpp=.o) + + +####### Build rules + + +#first: depend all +first: all + +all: Makefile $(TARGET) + +# append dependencies to this Makefile +#depend: +# @echo "==== Make dependencies =====" +# makedepend -Y +# makedepend -a -Y -- $(CXXFLAGS) $(INCPATH) -- $(SRC_FILES) $(NO_STDERR) + +$(TARGET): $(OBJS) + @echo "===== Link $@ =====" + $(LINK) $(LFLAGS) -shared -Wl,-soname,lib$(TARGET)$(SO_EXT) -o $(OUT_DIR)/lib$(TARGET)$(SO_EXT) $(OBJS) $(LIBS) + +.cpp.o: + @echo "===== Compile $< =====" + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + @echo "===== Compile $< =====" + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +clean: + @echo "===== Clean =====" + -$(DEL_FILE) *.o + -$(DEL_FILE) *~ core *.core *.stackdump + + +####### DEPENDENCIES + +TwColors.o: TwPrecomp.h TwColors.h +TwFonts.o: TwPrecomp.h ../include/AntTweakBar.h TwFonts.h TwMgr.h TwColors.h TwGraph.h AntPerfTimer.h +TwOpenGL.o: TwPrecomp.h ../include/AntTweakBar.h TwOpenGL.h LoadOGL.h TwGraph.h TwColors.h TwFonts.h TwMgr.h AntPerfTimer.h +TwBar.o: TwPrecomp.h ../include/AntTweakBar.h TwBar.h TwMgr.h TwColors.h TwFonts.h TwGraph.h AntPerfTimer.h +TwMgr.o: TwPrecomp.h ../include/AntTweakBar.h TwMgr.h TwColors.h TwFonts.h TwGraph.h AntPerfTimer.h TwBar.h TwOpenGL.h res/TwXCursors.h +TwPrecomp.o: TwPrecomp.h +LoadOGL.o: TwPrecomp.h LoadOGL.h +TwEventGLFW.o: ../include/AntTweakBar.h +TwEventGLUT.o: ../include/AntTweakBar.h +TwEventSDL.o: ../include/AntTweakBar.h diff --git a/Extras/CDTestFramework/AntTweakBar/src/Makefile.x86_64 b/Extras/CDTestFramework/AntTweakBar/src/Makefile.x86_64 new file mode 100644 index 0000000..e237e0a --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/Makefile.x86_64 @@ -0,0 +1,97 @@ +####### Compiler, tools and options + +#---- MinGW +#MINGWFLAGS = -mno-cygwin +#SO_EXT = .dll +#---- LINUX +SO_EXT = .so + +#---- Release +CXXCFG = -O3 +LFLAGS = -Wl,-s +OUT_DIR = ../lib +#---- Debug +#CXXCFG = -g -D_DEBUG +#LFLAGS = +#OUT_DIR = ../lib/debug + + +CXX = gcc -fPIC +#CXXFLAGS = $(CXXCFG) $(MINGWFLAGS) -pipe -Wall -fomit-frame-pointer -mcpu=pentiumpro -march=i586 -ffast-math -fno-strength-reduce -fpic -D_UNIX -D__PLACEMENT_NEW_INLINE +CXXFLAGS = $(CXXCFG) $(MINGWFLAGS) -Wall -ffast-math -D_UNIX -D__PLACEMENT_NEW_INLINE +INCPATH = -I/usr/include -I/usr/include -I../include +LINK = gcc -fPIC +#LIBS = -L/usr/lib64 -L. -lGL -lGLU -lX11 -lXxf86vm -lXext -lpthread -lm +#LIBS = -L/usr/lib -lGL -lX11 -lXxf86vm -lXext -lpthread -lm +LIBS = +AR = ar cqs +RANLIB = +TAR = tar -cf +GZIP = gzip -9f +COPY = cp -f +COPY_FILE = $(COPY) -p +COPY_DIR = $(COPY) -pR +DEL_FILE = rm -f +SYMLINK = ln -sf +DEL_DIR = rmdir +MOVE = mv +NO_STDERR = 2> /dev/null + + +####### Files + + +# name of the application: +TARGET = AntTweakBar + +# source files without extension: +SRC_FILES = TwColors.cpp TwFonts.cpp TwOpenGL.cpp TwBar.cpp TwMgr.cpp TwPrecomp.cpp LoadOGL.cpp TwEventGLFW.c TwEventGLUT.c TwEventSDL.c + +# build object list from source files +OBJS_1 = $(SRC_FILES:.c=.o) +OBJS = $(OBJS_1:.cpp=.o) + + +####### Build rules + +#first: depend all +first: all + +all: Makefile $(TARGET) + +# append dependencies to this Makefile +#depend: +# @echo "==== Make dependencies =====" +# makedepend -Y +# makedepend -a -Y -- $(CXXFLAGS) $(INCPATH) -- $(SRC_FILES) $(NO_STDERR) + +$(TARGET): $(OBJS) + @echo "===== Link $@ =====" + $(LINK) $(LFLAGS) -shared -Wl,-soname,lib$(TARGET)$(SO_EXT) -o $(OUT_DIR)/lib$(TARGET)$(SO_EXT) $(OBJS) $(LIBS) + +.cpp.o: + @echo "===== Compile $< =====" + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + @echo "===== Compile $< =====" + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +clean: + @echo "===== Clean =====" + -$(DEL_FILE) *.o + -$(DEL_FILE) *~ core *.core *.stackdump + + +####### DEPENDENCIES + +TwColors.o: TwPrecomp.h TwColors.h +TwFonts.o: TwPrecomp.h ../include/AntTweakBar.h TwFonts.h TwMgr.h TwColors.h TwGraph.h AntPerfTimer.h +TwOpenGL.o: TwPrecomp.h ../include/AntTweakBar.h TwOpenGL.h LoadOGL.h TwGraph.h TwColors.h TwFonts.h TwMgr.h AntPerfTimer.h +TwBar.o: TwPrecomp.h ../include/AntTweakBar.h TwBar.h TwMgr.h TwColors.h TwFonts.h TwGraph.h AntPerfTimer.h +TwMgr.o: TwPrecomp.h ../include/AntTweakBar.h TwMgr.h TwColors.h TwFonts.h TwGraph.h AntPerfTimer.h TwBar.h TwOpenGL.h res/TwXCursors.h +TwPrecomp.o: TwPrecomp.h +LoadOGL.o: TwPrecomp.h LoadOGL.h +TwEventGLFW.o: ../include/AntTweakBar.h +TwEventGLUT.o: ../include/AntTweakBar.h +TwEventSDL.o: ../include/AntTweakBar.h diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwBar.cpp b/Extras/CDTestFramework/AntTweakBar/src/TwBar.cpp new file mode 100644 index 0000000..fdfc3c7 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwBar.cpp @@ -0,0 +1,4841 @@ +// --------------------------------------------------------------------------- +// +// @file TwBar.cpp +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// note: TAB=4 +// +// --------------------------------------------------------------------------- + + +#include "TwPrecomp.h" + +#include +#include "TwMgr.h" +#include "TwBar.h" +#include "TwColors.h" + +using namespace std; + +extern const char *g_ErrNotFound; +const char *g_ErrUnknownAttrib = "Unknown attribute"; +const char *g_ErrNotGroup = "Value is not a group"; +const char *g_ErrNoValue = "Value required"; +const char *g_ErrBadValue = "Bad value"; +const char *g_ErrUnknownType = "Unknown type"; +const char *g_ErrNotEnum = "Must be of type Enum"; + +#undef PERF // comment to print benchs +#define PERF(cmd) + + +PerfTimer g_BarTimer; + +#define ANT_SET_CURSOR(_Name) g_TwMgr->SetCursor(g_TwMgr->m_Cursor##_Name) +#define ANT_SET_ROTO_CURSOR(_Num) g_TwMgr->SetCursor(g_TwMgr->m_RotoCursors[_Num]) + +#if !defined(ANT_WINDOWS) +# define _stricmp strcasecmp +# define _strdup strdup +#endif // defined(ANT_WINDOWS) + +#if !defined(M_PI) +# define M_PI 3.1415926535897932384626433832795 +#endif // !defined(M_PI) + +const float FLOAT_MAX = 3.0e+38f; +const double DOUBLE_MAX = 1.0e+308; +const double DOUBLE_EPS = 1.0e-307; + + +// --------------------------------------------------------------------------- + +CTwVarAtom::CTwVarAtom() +{ + m_Type = TW_TYPE_UNDEF; + m_Ptr = NULL; + m_SetCallback = NULL; + m_GetCallback = NULL; + m_ButtonCallback = NULL; + m_ClientData = NULL; + m_ReadOnly = false; + m_NoSlider = false; + m_KeyIncr[0] = 0; + m_KeyIncr[1] = 0; + m_KeyDecr[0] = 0; + m_KeyDecr[1] = 0; + memset(&m_Val, 0, sizeof(UVal)); +} + +CTwVarAtom::~CTwVarAtom() +{ + if( m_Type==TW_TYPE_BOOL8 || m_Type==TW_TYPE_BOOL16 || m_Type==TW_TYPE_BOOL32 || m_Type==TW_TYPE_BOOLCPP ) + { + if( m_Val.m_Bool.m_FreeTrueString && m_Val.m_Bool.m_TrueString!=NULL ) + { + free(m_Val.m_Bool.m_TrueString); + m_Val.m_Bool.m_TrueString = NULL; + } + if( m_Val.m_Bool.m_FreeFalseString && m_Val.m_Bool.m_FalseString!=NULL ) + { + free(m_Val.m_Bool.m_FalseString); + m_Val.m_Bool.m_FalseString = NULL; + } + } + /* + else if( m_Type==TW_TYPE_ENUM8 || m_Type==TW_TYPE_ENUM16 || m_Type==TW_TYPE_ENUM32 ) + { + if( m_Val.m_Enum.m_Entries!=NULL ) + { + delete m_Val.m_Enum.m_Entries; + m_Val.m_Enum.m_Entries = NULL; + } + } + */ +} + +// --------------------------------------------------------------------------- + +void CTwVarAtom::ValueToString(std::string *_Str) const +{ + assert(_Str!=NULL); + static const char *ErrStr = "unreachable"; + char Tmp[1024]; + if( m_Type==TW_TYPE_UNDEF || m_Type==TW_TYPE_HELP_ATOM || m_Type==TW_TYPE_HELP_GRP || m_Type==TW_TYPE_BUTTON ) // has no value + { + *_Str = ""; + return; + } + else if( m_Type==TW_TYPE_HELP_HEADER ) + { + *_Str = "KEY+ KEY-"; + return; + } + else if( m_Type==TW_TYPE_SHORTCUT ) // special case for help bar: display shortcut + { + *_Str = ""; + if( m_ReadOnly && m_Val.m_Shortcut.m_Incr[0]==0 && m_Val.m_Shortcut.m_Decr[0]==0 ) + (*_Str) = "(read only)"; + else + { + if( m_Val.m_Shortcut.m_Incr[0]>0 ) + TwGetKeyString(_Str, m_Val.m_Shortcut.m_Incr[0], m_Val.m_Shortcut.m_Incr[1]); + else + (*_Str) += "(none)"; + if( m_Val.m_Shortcut.m_Decr[0]>0 ) + { + (*_Str) += " "; + TwGetKeyString(_Str, m_Val.m_Shortcut.m_Decr[0], m_Val.m_Shortcut.m_Decr[1]); + } + } + return; + } + else if( m_Type==TW_TYPE_HELP_STRUCT ) + { + int idx = m_Val.m_HelpStruct.m_StructType - TW_TYPE_STRUCT_BASE; + if( idx>=0 && idx<(int)g_TwMgr->m_Structs.size() ) + { + if( g_TwMgr->m_Structs[idx].m_Name.length()>0 ) + (*_Str) = '{' + g_TwMgr->m_Structs[idx].m_Name + '}'; + else + (*_Str) = "{struct}"; + } + return; + } + if( m_Ptr==NULL && m_GetCallback==NULL ) + { + *_Str = ErrStr; + return; + } + bool UseGet = (m_GetCallback!=NULL); + switch( m_Type ) + { + case TW_TYPE_BOOLCPP: + { + bool Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(bool *)m_Ptr; + if( Val ) + *_Str = (m_Val.m_Bool.m_TrueString!=NULL) ? m_Val.m_Bool.m_TrueString : "ON"; + else + *_Str = (m_Val.m_Bool.m_FalseString!=NULL) ? m_Val.m_Bool.m_FalseString : "OFF"; + } + break; + case TW_TYPE_BOOL8: + { + char Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(char *)m_Ptr; + if( Val ) + *_Str = (m_Val.m_Bool.m_TrueString!=NULL) ? m_Val.m_Bool.m_TrueString : "ON"; + else + *_Str = (m_Val.m_Bool.m_FalseString!=NULL) ? m_Val.m_Bool.m_FalseString : "OFF"; + } + break; + case TW_TYPE_BOOL16: + { + short Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(short *)m_Ptr; + if( Val ) + *_Str = (m_Val.m_Bool.m_TrueString!=NULL) ? m_Val.m_Bool.m_TrueString : "ON"; + else + *_Str = (m_Val.m_Bool.m_FalseString!=NULL) ? m_Val.m_Bool.m_FalseString : "OFF"; + } + break; + case TW_TYPE_BOOL32: + { + int Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(int *)m_Ptr; + if( Val ) + *_Str = (m_Val.m_Bool.m_TrueString!=NULL) ? m_Val.m_Bool.m_TrueString : "ON"; + else + *_Str = (m_Val.m_Bool.m_FalseString!=NULL) ? m_Val.m_Bool.m_FalseString : "OFF"; + } + break; + case TW_TYPE_CHAR: + { + unsigned char Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(unsigned char *)m_Ptr; + if( Val!=0 ) + { + int d = Val; + if( m_Val.m_Char.m_Hexa ) + sprintf(Tmp, "%c (0x%.2X)", Val, d); + else + sprintf(Tmp, "%c (%d)", Val, d); + *_Str = Tmp; + } + else + *_Str = " (0)"; + } + break; + case TW_TYPE_INT8: + { + signed char Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(signed char *)m_Ptr; + int d = Val; + if( m_Val.m_Int8.m_Hexa ) + sprintf(Tmp, "0x%.2X", d&0xff); + else + sprintf(Tmp, "%d", d); + *_Str = Tmp; + } + break; + case TW_TYPE_UINT8: + { + unsigned char Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(unsigned char *)m_Ptr; + unsigned int d = Val; + if( m_Val.m_UInt8.m_Hexa ) + sprintf(Tmp, "0x%.2X", d); + else + sprintf(Tmp, "%u", d); + *_Str = Tmp; + } + break; + case TW_TYPE_INT16: + { + short Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(short *)m_Ptr; + int d = Val; + if( m_Val.m_Int16.m_Hexa ) + sprintf(Tmp, "0x%.4X", d&0xffff); + else + sprintf(Tmp, "%d", d); + *_Str = Tmp; + } + break; + case TW_TYPE_UINT16: + { + unsigned short Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(unsigned short *)m_Ptr; + unsigned int d = Val; + if( m_Val.m_UInt16.m_Hexa ) + sprintf(Tmp, "0x%.4X", d); + else + sprintf(Tmp, "%u", d); + *_Str = Tmp; + } + break; + case TW_TYPE_INT32: + { + int Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(int *)m_Ptr; + if( m_Val.m_Int32.m_Hexa ) + sprintf(Tmp, "0x%.8X", Val); + else + sprintf(Tmp, "%d", Val); + *_Str = Tmp; + } + break; + case TW_TYPE_UINT32: + { + unsigned int Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(unsigned int *)m_Ptr; + if( m_Val.m_UInt32.m_Hexa ) + sprintf(Tmp, "0x%.8X", Val); + else + sprintf(Tmp, "%u", Val); + *_Str = Tmp; + } + break; + case TW_TYPE_FLOAT: + { + float Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(float *)m_Ptr; + if( m_Val.m_Float32.m_Precision<0 ) + sprintf(Tmp, "%g", Val); + else + { + char Fmt[32]; + sprintf(Fmt, "%%.%df", (int)m_Val.m_Float32.m_Precision); + sprintf(Tmp, Fmt, Val); + } + *_Str = Tmp; + } + break; + case TW_TYPE_DOUBLE: + { + double Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(double *)m_Ptr; + if( m_Val.m_Float64.m_Precision<0 ) + sprintf(Tmp, "%lg", Val); + else + { + char Fmt[128]; + sprintf(Fmt, "%%.%dlf", (int)m_Val.m_Float64.m_Precision); + sprintf(Tmp, Fmt, Val); + } + *_Str = Tmp; + } + break; + /* + case TW_TYPE_ENUM8: + case TW_TYPE_ENUM16: + case TW_TYPE_ENUM32: + { + unsigned int d = 0; + if( m_Type==TW_TYPE_ENUM8 ) + { + unsigned char Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(unsigned char *)m_Ptr; + d = Val; + } + else if( m_Type==TW_TYPE_ENUM16 ) + { + unsigned short Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(unsigned short *)m_Ptr; + d = Val; + } + else + { + assert(m_Type==TW_TYPE_ENUM32); + unsigned int Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(unsigned int *)m_Ptr; + d = Val; + } + bool Found = false; + if( m_Val.m_Enum.m_Entries!=NULL ) + { + UVal::CEnumVal::CEntries::iterator It = m_Val.m_Enum.m_Entries->find(d); + if( It!=m_Val.m_Enum.m_Entries->end() ) + { + *_Str = It->second; + Found = true; + } + } + if( !Found ) + { + sprintf(Tmp, "%u", d); + *_Str = Tmp; + } + } + break; + */ + default: + if( m_Type>=TW_TYPE_ENUM_BASE && m_Typem_Enums.size() ) + { + unsigned int Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(unsigned int *)m_Ptr; + + CTwMgr::CEnum& e = g_TwMgr->m_Enums[m_Type-TW_TYPE_ENUM_BASE]; + CTwMgr::CEnum::CEntries::iterator It = e.m_Entries.find(Val); + if( It!=e.m_Entries.end() ) + *_Str = It->second; + else + { + sprintf(Tmp, "%u", Val); + *_Str = Tmp; + } + } + else + *_Str = "unknown type"; + } +} + +// --------------------------------------------------------------------------- + +double CTwVarAtom::ValueToDouble() const +{ + if( m_Ptr==NULL && m_GetCallback==NULL ) + return 0; // unreachable + bool UseGet = (m_GetCallback!=NULL); + switch( m_Type ) + { + case TW_TYPE_BOOLCPP: + { + bool Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(bool *)m_Ptr; + if( Val ) + return 1; + else + return 0; + } + break; + case TW_TYPE_BOOL8: + { + char Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(char *)m_Ptr; + if( Val ) + return 1; + else + return 0; + } + break; + case TW_TYPE_BOOL16: + { + short Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(short *)m_Ptr; + if( Val ) + return 1; + else + return 0; + } + break; + case TW_TYPE_BOOL32: + { + int Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(int *)m_Ptr; + if( Val ) + return 1; + else + return 0; + } + break; + case TW_TYPE_CHAR: + { + unsigned char Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(unsigned char *)m_Ptr; + return Val; + } + break; + case TW_TYPE_INT8: + { + signed char Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(signed char *)m_Ptr; + int d = Val; + return d; + } + break; + case TW_TYPE_UINT8: + { + unsigned char Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(unsigned char *)m_Ptr; + unsigned int d = Val; + return d; + } + break; + case TW_TYPE_INT16: + { + short Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(short *)m_Ptr; + int d = Val; + return d; + } + break; + case TW_TYPE_UINT16: + { + unsigned short Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(unsigned short *)m_Ptr; + unsigned int d = Val; + return d; + } + break; + case TW_TYPE_INT32: + { + int Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(int *)m_Ptr; + return Val; + } + break; + case TW_TYPE_UINT32: + { + unsigned int Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(unsigned int *)m_Ptr; + return Val; + } + break; + case TW_TYPE_FLOAT: + { + float Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(float *)m_Ptr; + return Val; + } + break; + case TW_TYPE_DOUBLE: + { + double Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(double *)m_Ptr; + return Val; + } + break; + /* + case TW_TYPE_ENUM8: + case TW_TYPE_ENUM16: + case TW_TYPE_ENUM32: + { + unsigned int d = 0; + if( m_Type==TW_TYPE_ENUM8 ) + { + unsigned char Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(unsigned char *)m_Ptr; + d = Val; + } + else if( m_Type==TW_TYPE_ENUM16 ) + { + unsigned short Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(unsigned short *)m_Ptr; + d = Val; + } + else + { + assert(m_Type==TW_TYPE_ENUM32); + unsigned int Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(unsigned int *)m_Ptr; + d = Val; + } + return d; + } + break; + */ + default: + if( m_Type>=TW_TYPE_ENUM_BASE && m_Typem_Enums.size() ) + { + unsigned int Val = 0; + if( UseGet ) + m_GetCallback(&Val, m_ClientData); + else + Val = *(unsigned int *)m_Ptr; + return Val; + } + else + return 0; // unknown type + } +} + +// --------------------------------------------------------------------------- + +void CTwVarAtom::ValueFromDouble(double _Val) +{ + if( m_Ptr==NULL && m_SetCallback==NULL ) + return; // unreachable + bool UseSet = (m_SetCallback!=NULL); + switch( m_Type ) + { + case TW_TYPE_BOOLCPP: + { + bool Val = (_Val!=0); + if( UseSet ) + m_SetCallback(&Val, m_ClientData); + else + *(bool*)m_Ptr = Val; + } + break; + case TW_TYPE_BOOL8: + { + char Val = (_Val!=0) ? 1 : 0; + if( UseSet ) + m_SetCallback(&Val, m_ClientData); + else + *(char*)m_Ptr = Val; + } + break; + case TW_TYPE_BOOL16: + { + short Val = (_Val!=0) ? 1 : 0; + if( UseSet ) + m_SetCallback(&Val, m_ClientData); + else + *(short*)m_Ptr = Val; + } + break; + case TW_TYPE_BOOL32: + { + int Val = (_Val!=0) ? 1 : 0; + if( UseSet ) + m_SetCallback(&Val, m_ClientData); + else + *(int*)m_Ptr = Val; + } + break; + case TW_TYPE_CHAR: + { + unsigned char Val = (unsigned char)_Val; + if( UseSet ) + m_SetCallback(&Val, m_ClientData); + else + *(unsigned char*)m_Ptr = Val; + } + break; + case TW_TYPE_INT8: + { + signed char Val = (signed char)_Val; + if( UseSet ) + m_SetCallback(&Val, m_ClientData); + else + *(signed char*)m_Ptr = Val; + } + break; + case TW_TYPE_UINT8: + //case TW_TYPE_ENUM8: + { + unsigned char Val = (unsigned char)_Val; + if( UseSet ) + m_SetCallback(&Val, m_ClientData); + else + *(unsigned char*)m_Ptr = Val; + } + break; + case TW_TYPE_INT16: + { + short Val = (short)_Val; + if( UseSet ) + m_SetCallback(&Val, m_ClientData); + else + *(short*)m_Ptr = Val; + } + break; + case TW_TYPE_UINT16: + //case TW_TYPE_ENUM16: + { + unsigned short Val = (unsigned short)_Val; + if( UseSet ) + m_SetCallback(&Val, m_ClientData); + else + *(unsigned short*)m_Ptr = Val; + } + break; + case TW_TYPE_INT32: + { + int Val = (int)_Val; + if( UseSet ) + m_SetCallback(&Val, m_ClientData); + else + *(int*)m_Ptr = Val; + } + break; + case TW_TYPE_UINT32: + //case TW_TYPE_ENUM32: + { + unsigned int Val = (unsigned int)_Val; + if( UseSet ) + m_SetCallback(&Val, m_ClientData); + else + *(unsigned int*)m_Ptr = Val; + } + break; + case TW_TYPE_FLOAT: + { + float Val = (float)_Val; + if( UseSet ) + m_SetCallback(&Val, m_ClientData); + else + *(float*)m_Ptr = Val; + } + break; + case TW_TYPE_DOUBLE: + { + double Val = (double)_Val; + if( UseSet ) + m_SetCallback(&Val, m_ClientData); + else + *(double*)m_Ptr = Val; + } + break; + default: + if( m_Type>=TW_TYPE_ENUM_BASE && m_Typem_Enums.size() ) + { + unsigned int Val = (unsigned int)_Val; + if( UseSet ) + m_SetCallback(&Val, m_ClientData); + else + *(unsigned int*)m_Ptr = Val; + } + } +} + +// --------------------------------------------------------------------------- + +void CTwVarAtom::MinMaxStepToDouble(double *_Min, double *_Max, double *_Step) const +{ + double max = DOUBLE_MAX; + double min = -DOUBLE_MAX; + double step = 1; + + switch( m_Type ) + { + case TW_TYPE_BOOLCPP: + case TW_TYPE_BOOL8: + case TW_TYPE_BOOL16: + case TW_TYPE_BOOL32: + min = 0; + max = 1; + step = 1; + break; + case TW_TYPE_CHAR: + min = (double)m_Val.m_Char.m_Min; + max = (double)m_Val.m_Char.m_Max; + step = (double)m_Val.m_Char.m_Step; + break; + case TW_TYPE_INT8: + min = (double)m_Val.m_Int8.m_Min; + max = (double)m_Val.m_Int8.m_Max; + step = (double)m_Val.m_Int8.m_Step; + break; + case TW_TYPE_UINT8: + min = (double)m_Val.m_UInt8.m_Min; + max = (double)m_Val.m_UInt8.m_Max; + step = (double)m_Val.m_UInt8.m_Step; + break; + case TW_TYPE_INT16: + min = (double)m_Val.m_Int16.m_Min; + max = (double)m_Val.m_Int16.m_Max; + step = (double)m_Val.m_Int16.m_Step; + break; + case TW_TYPE_UINT16: + min = (double)m_Val.m_UInt16.m_Min; + max = (double)m_Val.m_UInt16.m_Max; + step = (double)m_Val.m_UInt16.m_Step; + break; + case TW_TYPE_INT32: + min = (double)m_Val.m_Int32.m_Min; + max = (double)m_Val.m_Int32.m_Max; + step = (double)m_Val.m_Int32.m_Step; + break; + case TW_TYPE_UINT32: + min = (double)m_Val.m_UInt32.m_Min; + max = (double)m_Val.m_UInt32.m_Max; + step = (double)m_Val.m_UInt32.m_Step; + break; + case TW_TYPE_FLOAT: + min = (double)m_Val.m_Float32.m_Min; + max = (double)m_Val.m_Float32.m_Max; + step = (double)m_Val.m_Float32.m_Step; + break; + case TW_TYPE_DOUBLE: + min = m_Val.m_Float64.m_Min; + max = m_Val.m_Float64.m_Max; + step = m_Val.m_Float64.m_Step; + break; + default: + {} // nothing + } + + if( _Min!=NULL ) + *_Min = min; + if( _Max!=NULL ) + *_Max = max; + if( _Step!=NULL ) + *_Step = step; +} + +// --------------------------------------------------------------------------- + +const CTwVar *CTwVarAtom::Find(const char *_Name, CTwVarGroup **_Parent, int *_Index) const +{ + if( strcmp(_Name, m_Name.c_str())==0 ) + { + if( _Parent!=NULL ) + *_Parent = NULL; + if( _Index!=NULL ) + *_Index = -1; + return this; + } + else + return NULL; +} + +// --------------------------------------------------------------------------- + +enum EVarAttribs +{ + V_LABEL = 1, + V_HELP, + V_GROUP, + V_SHOW, + V_HIDE, + V_READONLY, + V_READWRITE, + V_ENDTAG +}; + +int CTwVar::HasAttrib(const char *_Attrib, bool *_HasValue) const +{ + *_HasValue = true; + if( _stricmp(_Attrib, "label")==0 ) + return V_LABEL; + else if( _stricmp(_Attrib, "help")==0 ) + return V_HELP; + else if( _stricmp(_Attrib, "group")==0 ) + return V_GROUP; + + *_HasValue = false; + if( _stricmp(_Attrib, "show")==0 ) + return V_SHOW; + else if( _stricmp(_Attrib, "hide")==0 ) + return V_HIDE; + if( _stricmp(_Attrib, "readonly")==0 ) + return V_READONLY; + else if( _stricmp(_Attrib, "readwrite")==0 ) + return V_READWRITE; + + return 0; // not found +} + +int CTwVar::SetAttrib(int _AttribID, const char *_Value, TwBar *_Bar, struct CTwVarGroup *_VarParent, int _VarIndex) +{ + switch( _AttribID ) + { + /* + case V_LABEL: + if( _Value && strlen(_Value)>0 ) + { + m_Label = _Value; + _Bar->NotUpToDate(); + return 1; + } + else + { + g_TwMgr->SetLastError(g_ErrNoValue); + return 0; + } + */ + case V_LABEL: + case V_HELP: + if( _Value && strlen(_Value)>0 ) + { + /* + if( IsGroup() && static_cast(this)->m_StructValuePtr!=NULL ) + { + int Idx = static_cast(this)->m_StructType-TW_TYPE_STRUCT_BASE; + if( Idx>=0 && Idx<(int)g_TwMgr->m_Structs.size() ) + if( _AttribID==V_LABEL ) + g_TwMgr->m_Structs[Idx].m_Label = _Value; + else // V_HELP + g_TwMgr->m_Structs[Idx].m_Help = _Value; + } + else + */ + { + CTwVarGroup *Parent = NULL; + CTwVar *ThisVar = _Bar->Find(m_Name.c_str(), &Parent); + if( this==ThisVar && Parent!=NULL && Parent->m_StructValuePtr!=NULL ) + { + int Idx = Parent->m_StructType-TW_TYPE_STRUCT_BASE; + if( Idx>=0 && Idx<(int)g_TwMgr->m_Structs.size() ) + { + size_t nl = m_Name.length(); + for( size_t im=0; imm_Structs[Idx].m_Members.size(); ++im ) + { + size_t ml = g_TwMgr->m_Structs[Idx].m_Members[im].m_Name.length(); + if( nl>=ml && strcmp(g_TwMgr->m_Structs[Idx].m_Members[im].m_Name.c_str(), m_Name.c_str()+(nl-ml))==0 ) + { + if( _AttribID==V_LABEL ) + g_TwMgr->m_Structs[Idx].m_Members[im].m_Label = _Value; + else // V_HELP + g_TwMgr->m_Structs[Idx].m_Members[im].m_Help = _Value; + break; + } + } + } + } + else + { + if( _AttribID==V_LABEL ) + m_Label = _Value; + else // V_HELP + m_Help = _Value; + } + } + _Bar->NotUpToDate(); + return 1; + } + else + { + g_TwMgr->SetLastError(g_ErrNoValue); + return 0; + } + case V_GROUP: + { + CTwVarGroup *Grp = NULL; + if( _Value==NULL || strlen(_Value)<=0 ) + Grp = &(_Bar->m_VarRoot); + else + { + CTwVar *v = _Bar->Find(_Value, NULL, NULL); + if( v && !v->IsGroup() ) + { + g_TwMgr->SetLastError(g_ErrNotGroup); + return 0; + } + Grp = static_cast(v); + if( Grp==NULL ) + { + Grp = new CTwVarGroup; + Grp->m_Name = _Value; + Grp->m_Open = true; + Grp->m_SummaryCallback = NULL; + Grp->m_SummaryClientData = NULL; + Grp->m_StructValuePtr = NULL; + if( g_TwMgr->m_HelpBar ) + Grp->m_Color = g_TwMgr->m_HelpBar->m_ColGrpText; + else + Grp->m_Color = COLOR32_WHITE; + _Bar->m_VarRoot.m_Vars.push_back(Grp); + } + } + Grp->m_Vars.push_back(this); + if( _VarParent!=NULL && _VarIndex>=0 ) + { + _VarParent->m_Vars.erase(_VarParent->m_Vars.begin()+_VarIndex); + if( _VarParent!=&(_Bar->m_VarRoot) && _VarParent->m_Vars.size()<=0 ) + TwRemoveVar(_Bar, _VarParent->m_Name.c_str()); + } + _Bar->NotUpToDate(); + return 1; + } + case V_SHOW: + if( !m_Visible ) + { + m_Visible = true; + _Bar->NotUpToDate(); + } + return 1; + case V_HIDE: + if( m_Visible ) + { + m_Visible = false; + _Bar->NotUpToDate(); + } + return 1; + case V_READONLY: + SetReadOnly(true); + _Bar->NotUpToDate(); + return 1; + case V_READWRITE: + SetReadOnly(false); + _Bar->NotUpToDate(); + return 1; + default: + g_TwMgr->SetLastError(g_ErrUnknownAttrib); + return 0; + } +} + +// --------------------------------------------------------------------------- + +enum EVarAtomAttribs +{ + VA_KEY_INCR = V_ENDTAG+1, + VA_KEY_DECR, + VA_MIN, + VA_MAX, + VA_STEP, + VA_PRECISION, + VA_HEXA, + VA_DECIMAL, + VA_TRUE, + VA_FALSE, + VA_VAL, +}; + +int CTwVarAtom::HasAttrib(const char *_Attrib, bool *_HasValue) const +{ + *_HasValue = true; + if( _stricmp(_Attrib, "keyincr")==0 || _stricmp(_Attrib, "key")==0 ) + return VA_KEY_INCR; + else if( _stricmp(_Attrib, "keydecr")==0 ) + return VA_KEY_DECR; + else if( _stricmp(_Attrib, "min")==0 ) + return VA_MIN; + else if( _stricmp(_Attrib, "max")==0 ) + return VA_MAX; + else if( _stricmp(_Attrib, "step")==0 ) + return VA_STEP; + else if( _stricmp(_Attrib, "precision")==0 ) + return VA_PRECISION; + else if( _stricmp(_Attrib, "hexa")==0 ) + { + *_HasValue = false; + return VA_HEXA; + } + else if( _stricmp(_Attrib, "decimal")==0 ) + { + *_HasValue = false; + return VA_DECIMAL; + } + else if( _stricmp(_Attrib, "true")==0 ) + return VA_TRUE; + else if( _stricmp(_Attrib, "false")==0 ) + return VA_FALSE; + else if( _stricmp(_Attrib, "val")==0 ) + return VA_VAL; + + return CTwVar::HasAttrib(_Attrib, _HasValue); +} + +int CTwVarAtom::SetAttrib(int _AttribID, const char *_Value, TwBar *_Bar, struct CTwVarGroup *_VarParent, int _VarIndex) +{ + switch( _AttribID ) + { + case VA_KEY_INCR: + { + int Key = 0; + int Mod = 0; + if( TwGetKeyCode(&Key, &Mod, _Value) ) + { + m_KeyIncr[0] = Key; + m_KeyIncr[1] = Mod; + return 1; + } + else + return 0; + } + case VA_KEY_DECR: + { + int Key = 0; + int Mod = 0; + if( TwGetKeyCode(&Key, &Mod, _Value) ) + { + m_KeyDecr[0] = Key; + m_KeyDecr[1] = Mod; + return 1; + } + else + return 0; + } + case VA_TRUE: + if( (m_Type==TW_TYPE_BOOL8 || m_Type==TW_TYPE_BOOL16 || m_Type==TW_TYPE_BOOL32 || m_Type==TW_TYPE_BOOLCPP) && _Value!=NULL ) + { + if( m_Val.m_Bool.m_FreeTrueString && m_Val.m_Bool.m_TrueString!=NULL ) + free(m_Val.m_Bool.m_TrueString); + m_Val.m_Bool.m_TrueString = _strdup(_Value); + m_Val.m_Bool.m_FreeTrueString = true; + return 1; + } + else + return 0; + case VA_FALSE: + if( (m_Type==TW_TYPE_BOOL8 || m_Type==TW_TYPE_BOOL16 || m_Type==TW_TYPE_BOOL32 || m_Type==TW_TYPE_BOOLCPP) && _Value!=NULL ) + { + if( m_Val.m_Bool.m_FreeFalseString && m_Val.m_Bool.m_FalseString!=NULL ) + free(m_Val.m_Bool.m_FalseString); + m_Val.m_Bool.m_FalseString = _strdup(_Value); + m_Val.m_Bool.m_FreeFalseString = true; + return 1; + } + else + return 0; + case VA_MIN: + case VA_MAX: + case VA_STEP: + if( _Value && strlen(_Value)>0 ) + { + void *Ptr = NULL; + const char *Fmt = NULL; + int d = 0; + unsigned int u = 0; + int Num = (_AttribID==VA_STEP) ? 2 : ((_AttribID==VA_MAX) ? 1 : 0); + switch( m_Type ) + { + case TW_TYPE_CHAR: + //Ptr = (&m_Val.m_Char.m_Min) + Num; + //Fmt = "%c"; + Ptr = &u; + Fmt = "%u"; + break; + case TW_TYPE_INT16: + Ptr = (&m_Val.m_Int16.m_Min) + Num; + Fmt = "%hd"; + break; + case TW_TYPE_INT32: + Ptr = (&m_Val.m_Int32.m_Min) + Num; + Fmt = "%d"; + break; + case TW_TYPE_UINT16: + Ptr = (&m_Val.m_UInt16.m_Min) + Num; + Fmt = "%hu"; + break; + case TW_TYPE_UINT32: + Ptr = (&m_Val.m_UInt32.m_Min) + Num; + Fmt = "%u"; + break; + case TW_TYPE_FLOAT: + Ptr = (&m_Val.m_Float32.m_Min) + Num; + Fmt = "%f"; + break; + case TW_TYPE_DOUBLE: + Ptr = (&m_Val.m_Float64.m_Min) + Num; + Fmt = "%lf"; + break; + case TW_TYPE_INT8: + Ptr = &d; + Fmt = "%d"; + break; + case TW_TYPE_UINT8: + Ptr = &u; + Fmt = "%u"; + break; + default: + g_TwMgr->SetLastError(g_ErrUnknownType); + return 0; + } + + if( Fmt!=NULL && Ptr!=NULL && sscanf(_Value, Fmt, Ptr)==1 ) + { + if( m_Type==TW_TYPE_CHAR ) + *((&m_Val.m_Char.m_Min)+Num) = (unsigned char)(u); + else if( m_Type==TW_TYPE_INT8 ) + *((&m_Val.m_Int8.m_Min)+Num) = (signed char)(d); + else if( m_Type==TW_TYPE_UINT8 ) + *((&m_Val.m_UInt8.m_Min)+Num) = (unsigned char)(u); + + // set precision + if( _AttribID==VA_STEP && ((m_Type==TW_TYPE_FLOAT && m_Val.m_Float32.m_Precision<0) || (m_Type==TW_TYPE_DOUBLE && m_Val.m_Float64.m_Precision<0)) ) + { + double Step = fabs( (m_Type==TW_TYPE_FLOAT) ? m_Val.m_Float32.m_Step : m_Val.m_Float64.m_Step ); + signed char *Precision = (m_Type==TW_TYPE_FLOAT) ? &m_Val.m_Float32.m_Precision : &m_Val.m_Float64.m_Precision; + if( Step>=1 ) + *Precision = 0; + else if( Step>=0.1 ) + *Precision = 1; + else if( Step>=0.01 ) + *Precision = 2; + else if( Step>=0.001 ) + *Precision = 3; + else if( Step>=0.0001 ) + *Precision = 4; + else if( Step>=0.00001 ) + *Precision = 5; + else if( Step>=0.000001 ) + *Precision = 6; + else if( Step>=0.0000001 ) + *Precision = 7; + else if( Step>=0.00000001 ) + *Precision = 8; + else if( Step>=0.000000001 ) + *Precision = 9; + else if( Step>=0.0000000001 ) + *Precision = 10; + else if( Step>=0.00000000001 ) + *Precision = 11; + else if( Step>=0.000000000001 ) + *Precision = 12; + else + *Precision = -1; + } + + return 1; + } + else + { + g_TwMgr->SetLastError(g_ErrBadValue); + return 0; + } + } + else + { + g_TwMgr->SetLastError(g_ErrNoValue); + return 0; + } + case VA_PRECISION: + if( _Value && strlen(_Value)>0 ) + { + int Precision = 0; + if( sscanf(_Value, "%d", &Precision)==1 && Precision>-128 && Precision<128 ) + { + if( m_Type==TW_TYPE_FLOAT ) + m_Val.m_Float32.m_Precision = (signed char)Precision; + else if ( m_Type==TW_TYPE_DOUBLE ) + m_Val.m_Float64.m_Precision = (signed char)Precision; + return 1; + } + else + { + g_TwMgr->SetLastError(g_ErrBadValue); + return 0; + } + } + else + { + g_TwMgr->SetLastError(g_ErrNoValue); + return 0; + } + case VA_HEXA: + case VA_DECIMAL: + { + bool hexa = (_AttribID==VA_HEXA); + switch( m_Type ) + { + case TW_TYPE_CHAR: + m_Val.m_Char.m_Hexa = hexa; + return 1; + case TW_TYPE_INT8: + m_Val.m_Int8.m_Hexa = hexa; + return 1; + case TW_TYPE_INT16: + m_Val.m_Int16.m_Hexa = hexa; + return 1; + case TW_TYPE_INT32: + m_Val.m_Int32.m_Hexa = hexa; + return 1; + case TW_TYPE_UINT8: + m_Val.m_UInt8.m_Hexa = hexa; + return 1; + case TW_TYPE_UINT16: + m_Val.m_UInt16.m_Hexa = hexa; + return 1; + case TW_TYPE_UINT32: + m_Val.m_UInt32.m_Hexa = hexa; + return 1; + default: + return 0; + } + } + case VA_VAL: + if( _Value && strlen(_Value)>0 && m_Type>=TW_TYPE_ENUM_BASE && m_Typem_Enums.size() ) + { + const char *s = _Value; + int n = 0, i = 0; + unsigned int u; + bool Cont; + do + { + Cont = false; + i = 0; + char Sep; + n = sscanf(s, "%u %c%n", &u, &Sep, &i); + if( n==2 && i>0 && ( Sep=='<' || Sep=='{' || Sep=='[' || Sep=='(' ) ) + { + if( Sep=='<' ) // Change to closing separator + Sep = '>'; + else if( Sep=='{' ) + Sep = '}'; + else if( Sep=='[' ) + Sep = ']'; + else if( Sep=='(' ) + Sep = ')'; + s += i; + i = 0; + while( s[i]!=Sep && s[i]!=0 ) + ++i; + if( s[i]==Sep ) + { + //if( m_Val.m_Enum.m_Entries==NULL ) + // m_Val.m_Enum.m_Entries = new UVal::CEnumVal::CEntries; + //UVal::CEnumVal::CEntries::value_type v(u, ""); + CTwMgr::CEnum::CEntries::value_type v(u, ""); + if( i>0 ) + v.second.assign(s, i); + //m_Val.m_Enum.m_Entries->insert(v); + pair ret; + ret = g_TwMgr->m_Enums[m_Type-TW_TYPE_ENUM_BASE].m_Entries.insert(v); + if( !ret.second ) // force overwrite if element already exists + { + g_TwMgr->m_Enums[m_Type-TW_TYPE_ENUM_BASE].m_Entries.erase(ret.first); + g_TwMgr->m_Enums[m_Type-TW_TYPE_ENUM_BASE].m_Entries.insert(v); + } + + s += i+1; + i = 0; + n = sscanf(s, " ,%n", &i); + if( n==0 && i>=1 ) + { + s += i; + Cont = true; + } + } + else + { + g_TwMgr->SetLastError(g_ErrBadValue); + return 0; + } + } + else + { + g_TwMgr->SetLastError(g_ErrBadValue); + return 0; + } + } while( Cont ); + return 1; + } + else + { + g_TwMgr->SetLastError(g_ErrNoValue); + return 0; + } + break; + default: + return CTwVar::SetAttrib(_AttribID, _Value, _Bar, _VarParent, _VarIndex); + } +} + +// --------------------------------------------------------------------------- + +void CTwVarAtom::Increment(int _Step) +{ + if( _Step==0 ) + return; + switch( m_Type ) + { + case TW_TYPE_BOOL8: + { + char v = false; + if( m_Ptr!=NULL ) + v = *((char *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + if( v ) + v = false; + else + v = true; + if( m_Ptr!=NULL ) + *((char *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + break; + case TW_TYPE_BOOL16: + { + short v = false; + if( m_Ptr!=NULL ) + v = *((short *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + if( v ) + v = false; + else + v = true; + if( m_Ptr!=NULL ) + *((short *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + break; + case TW_TYPE_BOOL32: + { + int v = false; + if( m_Ptr!=NULL ) + v = *((int *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + if( v ) + v = false; + else + v = true; + if( m_Ptr!=NULL ) + *((int *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + break; + case TW_TYPE_BOOLCPP: + { + bool v = false; + if( m_Ptr!=NULL ) + v = *((bool *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + if( v ) + v = false; + else + v = true; + if( m_Ptr!=NULL ) + *((bool *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + break; + case TW_TYPE_CHAR: + { + unsigned char v = 0; + if( m_Ptr!=NULL ) + v = *((unsigned char *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + int iv = _Step*(int)m_Val.m_Char.m_Step + (int)v; + if( ivm_Val.m_Char.m_Max ) + iv = m_Val.m_Char.m_Max; + if( iv<0 ) + iv = 0; + else if( iv>0xff ) + iv = 0xff; + v = (unsigned char)iv; + if( m_Ptr!=NULL ) + *((unsigned char *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + break; + case TW_TYPE_INT8: + { + signed char v = 0; + if( m_Ptr!=NULL ) + v = *((signed char *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + int iv = _Step*(int)m_Val.m_Int8.m_Step + (int)v; + if( ivm_Val.m_Int8.m_Max ) + iv = m_Val.m_Int8.m_Max; + v = (signed char)iv; + if( m_Ptr!=NULL ) + *((signed char *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + break; + case TW_TYPE_UINT8: + { + unsigned char v = 0; + if( m_Ptr!=NULL ) + v = *((unsigned char *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + int iv = _Step*(int)m_Val.m_UInt8.m_Step + (int)v; + if( ivm_Val.m_UInt8.m_Max ) + iv = m_Val.m_UInt8.m_Max; + if( iv<0 ) + iv = 0; + else if( iv>0xff ) + iv = 0xff; + v = (unsigned char)iv; + if( m_Ptr!=NULL ) + *((unsigned char *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + break; + case TW_TYPE_INT16: + { + short v = 0; + if( m_Ptr!=NULL ) + v = *((short *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + int iv = _Step*(int)m_Val.m_Int16.m_Step + (int)v; + if( ivm_Val.m_Int16.m_Max ) + iv = m_Val.m_Int16.m_Max; + v = (short)iv; + if( m_Ptr!=NULL ) + *((short *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + break; + case TW_TYPE_UINT16: + { + unsigned short v = 0; + if( m_Ptr!=NULL ) + v = *((unsigned short *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + int iv = _Step*(int)m_Val.m_UInt16.m_Step + (int)v; + if( ivm_Val.m_UInt16.m_Max ) + iv = m_Val.m_UInt16.m_Max; + if( iv<0 ) + iv = 0; + else if( iv>0xffff ) + iv = 0xffff; + v = (unsigned short)iv; + if( m_Ptr!=NULL ) + *((unsigned short *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + break; + case TW_TYPE_INT32: + { + int v = 0; + if( m_Ptr!=NULL ) + v = *((int *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + double dv = (double)_Step*(double)m_Val.m_Int32.m_Step + (double)v; + if( dv>(double)0x7fffffff ) + v = 0x7fffffff; + else if( dv<(double)(-0x7fffffff-1) ) + v = -0x7fffffff-1; + else + v = _Step*m_Val.m_Int32.m_Step + v; + if( vm_Val.m_Int32.m_Max ) + v = m_Val.m_Int32.m_Max; + if( m_Ptr!=NULL ) + *((int *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + break; + case TW_TYPE_UINT32: + { + unsigned int v = 0; + if( m_Ptr!=NULL ) + v = *((unsigned int *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + double dv = (double)_Step*(double)m_Val.m_UInt32.m_Step + (double)v; + if( dv>(double)0xffffffff ) + v = 0xffffffff; + else if( dv<0 ) + v = 0; + else + v = _Step*m_Val.m_UInt32.m_Step + v; + if( vm_Val.m_UInt32.m_Max ) + v = m_Val.m_UInt32.m_Max; + if( m_Ptr!=NULL ) + *((unsigned int *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + break; + case TW_TYPE_FLOAT: + { + float v = 0; + if( m_Ptr!=NULL ) + v = *((float *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + v += _Step*m_Val.m_Float32.m_Step; + if( vm_Val.m_Float32.m_Max ) + v = m_Val.m_Float32.m_Max; + if( m_Ptr!=NULL ) + *((float *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + break; + case TW_TYPE_DOUBLE: + { + double v = 0; + if( m_Ptr!=NULL ) + v = *((double *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + v += _Step*m_Val.m_Float64.m_Step; + if( vm_Val.m_Float64.m_Max ) + v = m_Val.m_Float64.m_Max; + if( m_Ptr!=NULL ) + *((double *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + break; + /* + case TW_TYPE_ENUM8: + { + assert(_Step==1 || _Step==-1); + unsigned char v = 0; + if( m_Ptr!=NULL ) + v = *((unsigned char *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + if( m_Val.m_Enum.m_Entries!=NULL ) + { + UVal::CEnumVal::CEntries::iterator It = m_Val.m_Enum.m_Entries->find(v); + if( It==m_Val.m_Enum.m_Entries->end() ) + It = m_Val.m_Enum.m_Entries->begin(); + else if( _Step==1 ) + { + ++It; + if( It==m_Val.m_Enum.m_Entries->end() ) + It = m_Val.m_Enum.m_Entries->begin(); + } + else if( _Step==-1 ) + { + if( It==m_Val.m_Enum.m_Entries->begin() ) + It = m_Val.m_Enum.m_Entries->end(); + if( It!=m_Val.m_Enum.m_Entries->begin() ) + --It; + } + if( It != m_Val.m_Enum.m_Entries->end() ) + { + v = (unsigned char)(It->first); + if( m_Ptr!=NULL ) + *((unsigned char *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + } + } + break; + case TW_TYPE_ENUM16: + { + assert(_Step==1 || _Step==-1); + unsigned short v = 0; + if( m_Ptr!=NULL ) + v = *((unsigned short *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + if( m_Val.m_Enum.m_Entries!=NULL ) + { + UVal::CEnumVal::CEntries::iterator It = m_Val.m_Enum.m_Entries->find(v); + if( It==m_Val.m_Enum.m_Entries->end() ) + It = m_Val.m_Enum.m_Entries->begin(); + else if( _Step==1 ) + { + ++It; + if( It==m_Val.m_Enum.m_Entries->end() ) + It = m_Val.m_Enum.m_Entries->begin(); + } + else if( _Step==-1 ) + { + if( It==m_Val.m_Enum.m_Entries->begin() ) + It = m_Val.m_Enum.m_Entries->end(); + if( It!=m_Val.m_Enum.m_Entries->begin() ) + --It; + } + if( It != m_Val.m_Enum.m_Entries->end() ) + { + v = (unsigned short)(It->first); + if( m_Ptr!=NULL ) + *((unsigned short *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + } + } + break; + case TW_TYPE_ENUM32: + { + assert(_Step==1 || _Step==-1); + unsigned int v = 0; + if( m_Ptr!=NULL ) + v = *((unsigned int *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + if( m_Val.m_Enum.m_Entries!=NULL ) + { + UVal::CEnumVal::CEntries::iterator It = m_Val.m_Enum.m_Entries->find(v); + if( It==m_Val.m_Enum.m_Entries->end() ) + It = m_Val.m_Enum.m_Entries->begin(); + else if( _Step==1 ) + { + ++It; + if( It==m_Val.m_Enum.m_Entries->end() ) + It = m_Val.m_Enum.m_Entries->begin(); + } + else if( _Step==-1 ) + { + if( It==m_Val.m_Enum.m_Entries->begin() ) + It = m_Val.m_Enum.m_Entries->end(); + if( It!=m_Val.m_Enum.m_Entries->begin() ) + --It; + } + if( It!=m_Val.m_Enum.m_Entries->end() ) + { + v = (unsigned int)(It->first); + if( m_Ptr!=NULL ) + *((unsigned int *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + } + } + break; + */ + default: + if( m_Type==TW_TYPE_BUTTON ) + { + if( m_ButtonCallback!=NULL ) + m_ButtonCallback(m_ClientData); + } + else if( m_Type>=TW_TYPE_ENUM_BASE && m_Typem_Enums.size() ) + { + assert(_Step==1 || _Step==-1); + unsigned int v = 0; + if( m_Ptr!=NULL ) + v = *((unsigned int *)m_Ptr); + else if( m_GetCallback!=NULL ) + m_GetCallback(&v, m_ClientData); + CTwMgr::CEnum& e = g_TwMgr->m_Enums[m_Type-TW_TYPE_ENUM_BASE]; + CTwMgr::CEnum::CEntries::iterator It = e.m_Entries.find(v); + if( It==e.m_Entries.end() ) + It = e.m_Entries.begin(); + else if( _Step==1 ) + { + ++It; + if( It==e.m_Entries.end() ) + It = e.m_Entries.begin(); + } + else if( _Step==-1 ) + { + if( It==e.m_Entries.begin() ) + It = e.m_Entries.end(); + if( It!=e.m_Entries.begin() ) + --It; + } + if( It!=e.m_Entries.end() ) + { + v = (unsigned int)(It->first); + if( m_Ptr!=NULL ) + *((unsigned int *)m_Ptr) = v; + else if( m_SetCallback!=NULL ) + m_SetCallback(&v, m_ClientData); + } + } + else + fprintf(stderr, "CTwVarAtom::Increment : unknown or unimplemented type\n"); + } +} + +// --------------------------------------------------------------------------- + +void CTwVarAtom::SetDefaults() +{ + switch( m_Type ) + { + case TW_TYPE_BOOL8: + case TW_TYPE_BOOL16: + case TW_TYPE_BOOL32: + case TW_TYPE_BOOLCPP: + m_NoSlider = true; + break; + case TW_TYPE_CHAR: + m_Val.m_Char.m_Max = 0xff; + m_Val.m_Char.m_Min = 0; + m_Val.m_Char.m_Step = 1; + m_Val.m_Char.m_Precision = -1; + m_Val.m_Char.m_Hexa = false; + break; + case TW_TYPE_INT8: + m_Val.m_Int8.m_Max = 0x7f; + m_Val.m_Int8.m_Min = -m_Val.m_Int8.m_Max-1; + m_Val.m_Int8.m_Step = 1; + m_Val.m_Int8.m_Precision = -1; + m_Val.m_Int8.m_Hexa = false; + break; + case TW_TYPE_UINT8: + m_Val.m_UInt8.m_Max = 0xff; + m_Val.m_UInt8.m_Min = 0; + m_Val.m_UInt8.m_Step = 1; + m_Val.m_UInt8.m_Precision = -1; + m_Val.m_UInt8.m_Hexa = false; + break; + case TW_TYPE_INT16: + m_Val.m_Int16.m_Max = 0x7fff; + m_Val.m_Int16.m_Min = -m_Val.m_Int16.m_Max-1; + m_Val.m_Int16.m_Step = 1; + m_Val.m_Int16.m_Precision = -1; + m_Val.m_Int16.m_Hexa = false; + break; + case TW_TYPE_UINT16: + m_Val.m_UInt16.m_Max = 0xffff; + m_Val.m_UInt16.m_Min = 0; + m_Val.m_UInt16.m_Step = 1; + m_Val.m_UInt16.m_Precision = -1; + m_Val.m_UInt16.m_Hexa = false; + break; + case TW_TYPE_INT32: + m_Val.m_Int32.m_Max = 0x7fffffff; + m_Val.m_Int32.m_Min = -m_Val.m_Int32.m_Max-1; + m_Val.m_Int32.m_Step = 1; + m_Val.m_Int32.m_Precision = -1; + m_Val.m_Int32.m_Hexa = false; + break; + case TW_TYPE_UINT32: + m_Val.m_UInt32.m_Max = 0xffffffff; + m_Val.m_UInt32.m_Min = 0; + m_Val.m_UInt32.m_Step = 1; + m_Val.m_UInt32.m_Precision = -1; + m_Val.m_UInt32.m_Hexa = false; + break; + case TW_TYPE_FLOAT: + m_Val.m_Float32.m_Max = FLOAT_MAX; + m_Val.m_Float32.m_Min = -FLOAT_MAX; + m_Val.m_Float32.m_Step = 1; + m_Val.m_Float32.m_Precision = -1; + m_Val.m_Float32.m_Hexa = false; + break; + case TW_TYPE_DOUBLE: + m_Val.m_Float64.m_Max = DOUBLE_MAX; + m_Val.m_Float64.m_Min = -DOUBLE_MAX; + m_Val.m_Float64.m_Step = 1; + m_Val.m_Float64.m_Precision = -1; + m_Val.m_Float64.m_Hexa = false; + break; + /* + case TW_TYPE_ENUM8: + case TW_TYPE_ENUM16: + case TW_TYPE_ENUM32: + m_NoSlider = true; + break; + */ + default: + {} // nothing + } + + // special types + if( m_Type==TW_TYPE_BUTTON || (m_Type>=TW_TYPE_ENUM_BASE && m_Typem_Enums.size()) ) + m_NoSlider = true; +} + +// --------------------------------------------------------------------------- + +/* +int CTwVarAtom::DefineEnum(const TwEnumVal *_EnumValues, unsigned int _NbValues) +{ + assert(_EnumValues!=NULL); + if( m_Type!=TW_TYPE_ENUM8 && m_Type!=TW_TYPE_ENUM16 && m_Type!=TW_TYPE_ENUM32 ) + { + g_TwMgr->SetLastError(g_ErrNotEnum); + return 0; + } + if( m_Val.m_Enum.m_Entries==NULL ) + m_Val.m_Enum.m_Entries = new UVal::CEnumVal::CEntries; + for(unsigned int i=0; i<_NbValues; ++i) + { + UVal::CEnumVal::CEntries::value_type Entry(_EnumValues[i].Value, (_EnumValues[i].Label!=NULL)?_EnumValues[i].Label:""); + pair Result = m_Val.m_Enum.m_Entries->insert(Entry); + if( !Result.second ) + (Result.first)->second = Entry.second; + } + return 1; +} +*/ + +// --------------------------------------------------------------------------- + +enum EVarGroupAttribs +{ + VG_OPEN = V_ENDTAG+1, + VG_CLOSE, + VG_TYPEID, // used internally for structs + VG_VALPTR, // used internally for structs + VG_ALPHA, // tw_type_color* only + VG_NOALPHA, // tw_type_color* only + VG_HLS, // tw_type_color* only + VG_RGB, // tw_type_color* only + VG_ORDER, // tw_type_color* only +}; + +int CTwVarGroup::HasAttrib(const char *_Attrib, bool *_HasValue) const +{ + *_HasValue = false; + if( _stricmp(_Attrib, "open")==0 ) + return VG_OPEN; + else if( _stricmp(_Attrib, "close")==0 ) + return VG_CLOSE; + else if( _stricmp(_Attrib, "typeid")==0 ) + { + *_HasValue = true; + return VG_TYPEID; + } + else if( _stricmp(_Attrib, "valptr")==0 ) + { + *_HasValue = true; + return VG_VALPTR; + } + else if( _stricmp(_Attrib, "alpha")==0 ) + return VG_ALPHA; + else if( _stricmp(_Attrib, "noalpha")==0 ) + return VG_NOALPHA; + else if( _stricmp(_Attrib, "hls")==0 ) + return VG_HLS; + else if( _stricmp(_Attrib, "rgb")==0 ) + return VG_RGB; + else if( _stricmp(_Attrib, "order")==0 ) + { + *_HasValue = true; + return VG_ORDER; + } + + return CTwVar::HasAttrib(_Attrib, _HasValue); +} + +int CTwVarGroup::SetAttrib(int _AttribID, const char *_Value, TwBar *_Bar, struct CTwVarGroup *_VarParent, int _VarIndex) +{ + switch( _AttribID ) + { + case VG_OPEN: + if( !m_Open ) + { + m_Open = true; + _Bar->NotUpToDate(); + } + return 1; + case VG_CLOSE: + if( m_Open ) + { + m_Open = false; + _Bar->NotUpToDate(); + } + return 1; + case VG_TYPEID: + { + int type = TW_TYPE_UNDEF; + if( _Value!=NULL && sscanf(_Value, "%d", &type)==1 ) + { + int idx = type - TW_TYPE_STRUCT_BASE; + if( idx>=0 && idx<(int)g_TwMgr->m_Structs.size() ) + { + m_SummaryCallback = g_TwMgr->m_Structs[idx].m_SummaryCallback; + m_SummaryClientData = g_TwMgr->m_Structs[idx].m_SummaryClientData; + m_StructType = (TwType)type; + return 1; + } + } + return 0; + } + case VG_VALPTR: + { + void *structValuePtr = NULL; + if( _Value!=NULL && sscanf(_Value, "%p", &structValuePtr)==1 ) + { + m_StructValuePtr = structValuePtr; + m_Color = _Bar->m_ColStructText; + return 1; + } + return 0; + } + case VG_ALPHA: + if( m_SummaryCallback==CColorExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_color? + if( static_cast(m_StructValuePtr)->m_CanHaveAlpha ) + { + static_cast(m_StructValuePtr)->m_HasAlpha = true; + _Bar->NotUpToDate(); + return 1; + } + return 0; + case VG_NOALPHA: + if( m_SummaryCallback==CColorExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_color? + { + static_cast(m_StructValuePtr)->m_HasAlpha = false; + _Bar->NotUpToDate(); + return 1; + } + else + return 0; + case VG_HLS: + if( m_SummaryCallback==CColorExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_color? + { + static_cast(m_StructValuePtr)->m_HLS = true; + _Bar->NotUpToDate(); + return 1; + } + else + return 0; + case VG_RGB: + if( m_SummaryCallback==CColorExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_color? + { + static_cast(m_StructValuePtr)->m_HLS = false; + _Bar->NotUpToDate(); + return 1; + } + else + return 0; + case VG_ORDER: + if( m_SummaryCallback==CColorExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_color? + { + if( _Value!=NULL ) + { + if( _stricmp(_Value, "ogl")==0 ) + static_cast(m_StructValuePtr)->m_OGL = true; + else if( _stricmp(_Value, "dx")==0 ) + static_cast(m_StructValuePtr)->m_OGL = false; + else + return 0; + return 1; + } + return 0; + } + else + return 0; + default: + return CTwVar::SetAttrib(_AttribID, _Value, _Bar, _VarParent, _VarIndex); + } +} + +// --------------------------------------------------------------------------- + +const CTwVar *CTwVarGroup::Find(const char *_Name, CTwVarGroup **_Parent, int *_Index) const +{ + if( strcmp(_Name, m_Name.c_str())==0 ) + { + if( _Parent!=NULL ) + *_Parent = NULL; + if( _Index!=NULL ) + *_Index = -1; + return this; + } + else + { + const CTwVar *v; + for( size_t i=0; iFind(_Name, _Parent, _Index); + if( v!=NULL ) + { + if( _Parent!=NULL && *_Parent==NULL ) + { + *_Parent = const_cast(this); + if( _Index!=NULL ) + *_Index = (int)i; + } + return v; + } + } + return NULL; + } +} + +// --------------------------------------------------------------------------- + +size_t CTwVar::GetDataSize(TwType _Type) +{ + switch( _Type ) + { + case TW_TYPE_BOOLCPP: + return sizeof(bool); + case TW_TYPE_BOOL8: + case TW_TYPE_CHAR: + case TW_TYPE_INT8: + case TW_TYPE_UINT8: + //case TW_TYPE_ENUM8: + return 1; + case TW_TYPE_BOOL16: + case TW_TYPE_INT16: + case TW_TYPE_UINT16: + //case TW_TYPE_ENUM16: + return 2; + case TW_TYPE_BOOL32: + case TW_TYPE_INT32: + case TW_TYPE_UINT32: + case TW_TYPE_FLOAT: + //case TW_TYPE_ENUM32: + return 4; + case TW_TYPE_DOUBLE: + return 8; + default: + if( g_TwMgr && _Type>=TW_TYPE_STRUCT_BASE && _Typem_Structs.size() ) + { + const CTwMgr::CStruct& s = g_TwMgr->m_Structs[_Type-TW_TYPE_STRUCT_BASE]; + return s.m_Size; + /* + size_t size = 0; + for( size_t i=0; i=TW_TYPE_ENUM_BASE && _Typem_Enums.size() ) + return 4; + else // includes TW_TYPE_BUTTON + return 0; + } +} + +// --------------------------------------------------------------------------- + +CTwBar::CTwBar(const char *_Name) +{ + assert(g_TwMgr!=NULL && g_TwMgr->m_Graph!=NULL); + + m_Name = _Name; + m_Visible = true; + m_VarRoot.m_IsRoot = true; + m_VarRoot.m_Open = true; + m_VarRoot.m_SummaryCallback = NULL; + m_VarRoot.m_SummaryClientData = NULL; + m_VarRoot.m_StructValuePtr = NULL; + + m_UpToDate = false; + int n = (int)g_TwMgr->m_Bars.size(); + m_PosX = 24*n-8; + m_PosY = 24*n-8; + m_Width = 200; + m_Height = 320; + int cr, cg, cb; + ColorHLSToRGBi(g_TwMgr->m_BarInitColorHue%256, 127, 255, &cr, &cg, &cb); + g_TwMgr->m_BarInitColorHue -= 16; + if( g_TwMgr->m_BarInitColorHue<0 ) + g_TwMgr->m_BarInitColorHue += 256; + m_Color = Color32FromARGBi(0xf0, cr, cg, cb); + //m_Color = 0xd7008f8f; + m_Font = g_TwMgr->m_CurrentFont; + //m_Font = g_DefaultNormalFont; + //m_Font = g_DefaultSmallFont; + //m_Font = g_DefaultLargeFont; + m_TitleWidth = 0; + m_Sep = 1; + m_ValuesWidth = 10*(m_Font->m_CharHeight/2); // about 10 characters + m_NbHierLines = 0; + m_NbDisplayedLines = 0; + m_FirstLine = 0; + m_LastUpdateTime = 0; + m_UpdatePeriod = 2; + m_ScrollYW = 0; + m_ScrollYH = 0; + m_ScrollY0 = 0; + m_ScrollY1 = 0; + + m_DrawHandles = false; + m_DrawIncrDecrBtn = false; + m_DrawClickBtn = false; + m_MouseDrag = false; + m_MouseDragVar = false; + m_MouseDragTitle = false; + m_MouseDragScroll = false; + m_MouseDragResizeUR = false; + m_MouseDragResizeUL = false; + m_MouseDragResizeLR = false; + m_MouseDragResizeLL = false; + m_MouseDragValWidth = false; + m_MouseOriginX = 0; + m_MouseOriginY = 0; + m_VarHasBeenIncr = true; + m_FirstLine0 = 0; + m_HighlightedLine = -1; + m_HighlightedLinePrev = -1; + m_HighlightIncrBtn = false; + m_HighlightDecrBtn = false; + m_HighlightClickBtn = false; + m_HighlightTitle = false; + m_HighlightScroll = false; + m_HighlightUpScroll = false; + m_HighlightDnScroll = false; + m_HighlightMinimize = false; + m_HighlightFont = false; + m_HighlightValWidth = false; + + m_IsMinimized = false; + m_MinNumber = 0; + m_MinPosX = 0; + m_MinPosY = 0; + m_HighlightMaximize = false; + m_IsHelpBar = false; + m_IsPopupList = false; + m_VarEnumLinkedToPopupList = NULL; + m_BarLinkedToPopupList = NULL; + + m_TitleTextObj = g_TwMgr->m_Graph->NewTextObj(); + m_LabelsTextObj = g_TwMgr->m_Graph->NewTextObj(); + m_ValuesTextObj = g_TwMgr->m_Graph->NewTextObj(); + m_ShortcutTextObj = g_TwMgr->m_Graph->NewTextObj(); + m_ShortcutLine = -1; + + m_RotoMinRadius = 24; + m_RotoNbSubdiv = 256; // number of steps for one turn + + UpdateColors(); + NotUpToDate(); +} + +// --------------------------------------------------------------------------- + +CTwBar::~CTwBar() +{ + if( m_IsMinimized ) + g_TwMgr->Maximize(this); + if( m_TitleTextObj ) + g_TwMgr->m_Graph->DeleteTextObj(m_TitleTextObj); + if( m_LabelsTextObj ) + g_TwMgr->m_Graph->DeleteTextObj(m_LabelsTextObj); + if( m_ValuesTextObj ) + g_TwMgr->m_Graph->DeleteTextObj(m_ValuesTextObj); + if( m_ShortcutTextObj ) + g_TwMgr->m_Graph->DeleteTextObj(m_ShortcutTextObj); +} + +// --------------------------------------------------------------------------- + +const CTwVar *CTwBar::Find(const char *_Name, CTwVarGroup **_Parent, int *_Index) const +{ + return m_VarRoot.Find(_Name, _Parent, _Index); +} + +CTwVar *CTwBar::Find(const char *_Name, CTwVarGroup **_Parent, int *_Index) +{ + return const_cast(const_cast(this)->Find(_Name, _Parent, _Index)); +} + +// --------------------------------------------------------------------------- + +enum EBarAttribs +{ + BAR_LABEL = 1, + BAR_HELP, + BAR_COLOR, + BAR_SHOW, + BAR_HIDE, + BAR_ICONIFY, + BAR_SIZE, + BAR_POSITION, + BAR_REFRESH, + BAR_FONT_SIZE, + BAR_VALUES_WIDTH, +}; + +int CTwBar::HasAttrib(const char *_Attrib, bool *_HasValue) const +{ + *_HasValue = true; + if( _stricmp(_Attrib, "label")==0 ) + return BAR_LABEL; + else if( _stricmp(_Attrib, "help")==0 ) + return BAR_HELP; + else if( _stricmp(_Attrib, "color")==0 ) + return BAR_COLOR; + else if( _stricmp(_Attrib, "size")==0 ) + return BAR_SIZE; + else if( _stricmp(_Attrib, "position")==0 ) + return BAR_POSITION; + else if( _stricmp(_Attrib, "refresh")==0 ) + return BAR_REFRESH; + else if( _stricmp(_Attrib, "fontsize")==0 ) + return BAR_FONT_SIZE; + else if( _stricmp(_Attrib, "valueswidth")==0 ) + return BAR_VALUES_WIDTH; + + *_HasValue = false; + if( _stricmp(_Attrib, "show")==0 ) + return BAR_SHOW; + else if( _stricmp(_Attrib, "hide")==0 ) + return BAR_HIDE; + else if( _stricmp(_Attrib, "iconify")==0 ) + return BAR_ICONIFY; + + return 0; // not found +} + +int CTwBar::SetAttrib(int _AttribID, const char *_Value) +{ + switch( _AttribID ) + { + case BAR_LABEL: + if( _Value && strlen(_Value)>0 ) + { + m_Label = _Value; + NotUpToDate(); + return 1; + } + else + { + g_TwMgr->SetLastError(g_ErrNoValue); + return 0; + } + case BAR_HELP: + if( _Value && strlen(_Value)>0 ) + { + m_Help = _Value; + NotUpToDate(); + return 1; + } + else + { + g_TwMgr->SetLastError(g_ErrNoValue); + return 0; + } + case BAR_COLOR: + if( _Value && strlen(_Value)>0 ) + { + int v0, v1, v2, v3; + int n = sscanf(_Value, "%d%d%d%d", &v0, &v1, &v2, &v3); + color32 c; + if( n==3 ) + c = Color32FromARGBi(255, v0, v1, v2); + else if( n==4 ) + c = Color32FromARGBi(v0, v1, v2, v3); + else + { + g_TwMgr->SetLastError(g_ErrBadValue); + return 0; + } + m_Color = c; + NotUpToDate(); + return 1; + } + else + { + g_TwMgr->SetLastError(g_ErrNoValue); + return 0; + } + case BAR_SIZE: + if( _Value && strlen(_Value)>0 ) + { + int sx, sy; + int n = sscanf(_Value, "%d%d", &sx, &sy); + if( n==2 && sx>0 && sy>0 ) + { + m_Width = sx; + m_Height = sy; + NotUpToDate(); + return 1; + } + else + { + g_TwMgr->SetLastError(g_ErrBadValue); + return 0; + } + } + else + { + g_TwMgr->SetLastError(g_ErrNoValue); + return 0; + } + case BAR_POSITION: + if( _Value && strlen(_Value)>0 ) + { + int x, y; + int n = sscanf(_Value, "%d%d", &x, &y); + if( n==2 && x>=0 && y>=0 ) + { + m_PosX = x; + m_PosY = y; + NotUpToDate(); + return 1; + } + else + { + g_TwMgr->SetLastError(g_ErrBadValue); + return 0; + } + } + else + { + g_TwMgr->SetLastError(g_ErrNoValue); + return 0; + } + case BAR_REFRESH: + if( _Value && strlen(_Value)>0 ) + { + float r; + int n = sscanf(_Value, "%f", &r); + if( n==1 && r>=0 ) + { + m_UpdatePeriod = r; + return 1; + } + else + { + g_TwMgr->SetLastError(g_ErrBadValue); + return 0; + } + } + else + { + g_TwMgr->SetLastError(g_ErrNoValue); + return 0; + } + case BAR_FONT_SIZE: + if( _Value && strlen(_Value)>0 ) + { + int s; + int n = sscanf(_Value, "%d", &s); + if( n==1 && s>=1 && s<=3 ) + { + if( s==1 ) + g_TwMgr->SetFont(g_DefaultSmallFont, true); + else if( s==2 ) + g_TwMgr->SetFont(g_DefaultNormalFont, true); + else if( s==3 ) + g_TwMgr->SetFont(g_DefaultLargeFont, true); + return 1; + } + else + { + g_TwMgr->SetLastError(g_ErrBadValue); + return 0; + } + } + else + { + g_TwMgr->SetLastError(g_ErrNoValue); + return 0; + } + case BAR_VALUES_WIDTH: + if( _Value && strlen(_Value)>0 ) + { + int w; + int n = sscanf(_Value, "%d", &w); + if( n==1 && w>0 ) + { + m_ValuesWidth = w; + NotUpToDate(); + return 1; + } + else + { + g_TwMgr->SetLastError(g_ErrBadValue); + return 0; + } + } + else + { + g_TwMgr->SetLastError(g_ErrNoValue); + return 0; + } + case BAR_SHOW: + TwSetBarState(this, TW_STATE_SHOWN); + return 1; + case BAR_HIDE: + TwSetBarState(this, TW_STATE_HIDDEN); + return 1; + case BAR_ICONIFY: + TwSetBarState(this, TW_STATE_ICONIFIED); + return 1; + default: + g_TwMgr->SetLastError(g_ErrUnknownAttrib); + return 0; + } +} + +// --------------------------------------------------------------------------- + +void CTwBar::NotUpToDate() +{ + m_UpToDate = false; +} + +// --------------------------------------------------------------------------- + +void CTwBar::UpdateColors() +{ + float a, r, g, b, h, l, s; + Color32ToARGBf(m_Color, &a, &r, &g, &b); + ColorRGBToHLSf(r, g, b, &h, &l, &s); + if( s>0.8f ) + s = 0.8f; + + ColorHLSToRGBf(h, 0.78f, s, &r, &g, &b); + m_ColBg = Color32FromARGBf(a, r, g, b); + ColorHLSToRGBf(h, 0.70f, s, &r, &g, &b); + m_ColBg1 = Color32FromARGBf(a, r, g, b); + ColorHLSToRGBf(h, 0.62f, s, &r, &g, &b); + m_ColBg2 = Color32FromARGBf(a, r, g, b); + + ColorHLSToRGBf(h, 0.8f, s, &r, &g, &b); + m_ColHighBg = Color32FromARGBf(a, r, g, b); + //m_ColHighBg = Color32FromARGBf(a, 0.95f, 0.95f, 0.2f); + + m_ColLabelText = COLOR32_BLACK; + m_ColStructText = 0xff005000; + + ColorHLSToRGBf(h, 0.9f, s, &r, &g, &b); + m_ColValBg = Color32FromARGBf(a, r, g, b); + m_ColStructBg = Color32FromARGBf(0.7f*a, r, g, b); + + //m_ColValText = COLOR32_BLACK; + m_ColValText = 0xff000080; + m_ColValTextRO = 0xff505050; + //m_ColValMin = 0xff800000; + //m_ColValMax = 0xff800000; + m_ColValMin = 0xff0000f0; + m_ColValMax = 0xff0000f0; + + ColorHLSToRGBf(h, 0.4f, s, &r, &g, &b); + m_ColTitleBg = Color32FromARGBf(a, r, g, b); + m_ColTitleText = COLOR32_WHITE; + m_ColTitleShadow = COLOR32_BLACK; + ColorHLSToRGBf(h, 0.2f, s, &r, &g, &b); + m_ColTitleHighBg = Color32FromARGBf(a, r, g, b); + + ColorHLSToRGBf(h, 0.8f, s, &r, &g, &b); + m_ColLine = Color32FromARGBf(1, r, g, b); // 0xfff0f0f0; + m_ColLineShadow = COLOR32_BLACK; + m_ColUnderline = 0xff202000; + ColorHLSToRGBf(h, 0.3f, s, &r, &g, &b); + m_ColBtn = Color32FromARGBf(0.6f*a, r, g, b); + ColorHLSToRGBf(h, 0.1f, s, &r, &g, &b); + m_ColHighBtn = Color32FromARGBf(0.6f*a, r, g, b); + + ColorHLSToRGBf(h, 0.4f, s, &r, &g, &b); + m_ColGrpBg = Color32FromARGBf(a, r, g, b); + m_ColGrpText = COLOR32_WHITE; + + ColorHLSToRGBf(h, 0.75f, s, &r, &g, &b); + m_ColHelpBg = Color32FromARGBf(a, r, g, b); + m_ColHelpText = Color32FromARGBf(1, 0, 0.4f, 0); + + ColorHLSToRGBf(h, 0.45f, s, &r, &g, &b); + m_ColHierBg = Color32FromARGBf(0.75f*a, r, g, b); + + m_ColShortcutText = 0xfff0f0f0; + m_ColShortcutBg = Color32FromARGBf(0.5f*a, 0.1f, 0.1f, 0.1f); + m_ColInfoText = Color32FromARGBf(1.0f, 0.7f, 0.7f, 0.7f); + + m_ColRoto = Color32FromARGBf(1, 0.75f, 0.75f, 0.75f); + m_ColRotoVal = Color32FromARGBf(1, 1.0f, 0.2f, 0.2f); + m_ColRotoBound = Color32FromARGBf(1, 0.4f, 0.4f, 0.4f); +} + +// --------------------------------------------------------------------------- + +CTwVarGroup::~CTwVarGroup() +{ + for( vector::iterator it= m_Vars.begin(); it!=m_Vars.end(); ++it ) + if( *it != NULL ) + { + CTwVar *Var = *it; + delete Var; + *it = NULL; + } +} + +// --------------------------------------------------------------------------- + +static inline int IncrBtnWidth(int _CharHeight) +{ + return ((2*_CharHeight)/3+2)&0xfffe; // force even value +} + +// --------------------------------------------------------------------------- + +void CTwBar::BrowseHierarchy(int *_CurrLine, int _CurrLevel, const CTwVar *_Var, int _First, int _Last) +{ + assert(_Var!=NULL); + if( !_Var->m_IsRoot ) + { + if( (*_CurrLine)>=_First && (*_CurrLine)<=_Last ) + { + CHierTag Tag; + Tag.m_Level = _CurrLevel; + Tag.m_Var = const_cast(_Var); + Tag.m_Closing = false; + m_HierTags.push_back(Tag); + } + *_CurrLine += 1; + } + else + { + *_CurrLine = 0; + _CurrLevel = -1; + m_HierTags.resize(0); + } + + if( _Var->IsGroup() ) + { + const CTwVarGroup *Grp = static_cast(_Var); + if( Grp->m_Open ) + for( vector::const_iterator it=Grp->m_Vars.begin(); it!=Grp->m_Vars.end(); ++it ) + if( (*it)->m_Visible ) + BrowseHierarchy(_CurrLine, _CurrLevel+1, *it, _First, _Last); + if( m_HierTags.size()>0 ) + m_HierTags[m_HierTags.size()-1].m_Closing = true; + } +} + +// --------------------------------------------------------------------------- + +void CTwBar::ListLabels(vector& _Labels, vector& _Colors, const CTexFont *_Font, int _AtomWidthMax, int _GroupWidthMax) +{ + const int NbEtc = 2; + string ValStr; + int Len, i, x, Etc; + const unsigned char *Text; + unsigned char ch; + int WidthMax; + + int nh = (int)m_HierTags.size(); + for( int h=0; hm_Label.length(); + if( Len>0 ) + Text = (const unsigned char *)(m_HierTags[h].m_Var->m_Label.c_str()); + else + { + Text = (const unsigned char *)(m_HierTags[h].m_Var->m_Name.c_str()); + Len = (int)m_HierTags[h].m_Var->m_Name.length(); + } + x = 0; + Etc = 0; + _Labels.push_back(""); // add a new text line + _Colors.push_back(m_HierTags[h].m_Var->m_Color); + string& CurrentLabel = _Labels[_Labels.size()-1]; + if( m_HierTags[h].m_Var->IsGroup() && static_cast(m_HierTags[h].m_Var)->m_SummaryCallback==NULL ) + WidthMax = _GroupWidthMax; + else if( !m_HierTags[h].m_Var->IsGroup() && static_cast(m_HierTags[h].m_Var)->m_Type==TW_TYPE_BUTTON ) + WidthMax = _GroupWidthMax - 2*IncrBtnWidth(m_Font->m_CharHeight); + else + WidthMax = _AtomWidthMax; + for( i=0; im_CharWidth[(int)' ']; + } + for( i=0; im_CharWidth[(int)ch]; + if( Etc>0 ) + { + ++Etc; + if( Etc>NbEtc ) + break; + } + else if( im_CharWidth[(int)'.']>=WidthMax && !(m_HierTags[h].m_Var->m_DontClip)) + Etc = 1; + } + } +} + +// --------------------------------------------------------------------------- + +void CTwBar::ListValues(vector& _Values, vector& _Colors, vector& _BgColors, const CTexFont *_Font, int _WidthMax) +{ + CTwFPU fpu; // force fpu precision + + const int NbEtc = 2; + const CTwVarAtom *Atom = NULL; + string ValStr; + int Len, i, x, Etc; + const unsigned char *Text; + unsigned char ch; + bool ReadOnly; + bool IsMax; + bool IsMin; + size_t SummaryMaxLength = max(_WidthMax/_Font->m_CharWidth[(int)'I'], 4); + static vector Summary; + Summary.resize(SummaryMaxLength+32); + + int nh = (int)m_HierTags.size(); + for( int h=0; hIsGroup() || m_IsHelpBar + || (m_HierTags[h].m_Var->IsGroup() && static_cast(m_HierTags[h].m_Var)->m_SummaryCallback!=NULL) ) + { + ReadOnly = true; + IsMax = false; + IsMin = false; + if( !m_HierTags[h].m_Var->IsGroup() ) + { + Atom = static_cast(m_HierTags[h].m_Var); + Atom->ValueToString(&ValStr); + if( !m_IsHelpBar || (Atom->m_Type==TW_TYPE_SHORTCUT && (Atom->m_Val.m_Shortcut.m_Incr[0]>0 || Atom->m_Val.m_Shortcut.m_Decr[0]>0)) ) + ReadOnly = Atom->m_ReadOnly; + if( !Atom->m_NoSlider ) + { + double v, vmin, vmax; + v = Atom->ValueToDouble(); + Atom->MinMaxStepToDouble(&vmin, &vmax, NULL); + IsMax = (v>=vmax); + IsMin = (v<=vmin); + } + } + else if(m_HierTags[h].m_Var->IsGroup() && static_cast(m_HierTags[h].m_Var)->m_SummaryCallback!=NULL) + { + const CTwVarGroup *Grp = static_cast(m_HierTags[h].m_Var); + Summary[0] = '\0'; + if( Grp->m_SummaryCallback==CTwMgr::CStruct::DefaultSummary ) + Grp->m_SummaryCallback(&Summary[0], SummaryMaxLength, Grp, Grp->m_SummaryClientData); + else + Grp->m_SummaryCallback(&Summary[0], SummaryMaxLength, Grp->m_StructValuePtr, Grp->m_SummaryClientData); + ValStr = (const char *)(&Summary[0]); + } + else + ValStr = ""; // is a group in the help bar + Len = (int)ValStr.length(); + Text = (const unsigned char *)(ValStr.c_str()); + x = 0; + Etc = 0; + _Values.push_back(""); // add a new text line + if( ReadOnly || (IsMin && IsMax) ) + _Colors.push_back(m_ColValTextRO); + else if( IsMin ) + _Colors.push_back(m_ColValMin); + else if( IsMax ) + _Colors.push_back(m_ColValMax); + else + _Colors.push_back(m_ColValText); + if( m_HierTags[h].m_Var->IsGroup() ) + { + const CTwVarGroup *Grp = static_cast(m_HierTags[h].m_Var); + // if typecolor set bgcolor + if( Grp->m_SummaryCallback==CColorExt::SummaryCB ) + _BgColors.push_back(0xff000000); + else + _BgColors.push_back(m_ColStructBg); + } + else + _BgColors.push_back(m_ColValBg); + + string& CurrentValue = _Values[_Values.size()-1]; + int wmax = _WidthMax; + if( m_HighlightedLine==h && m_DrawIncrDecrBtn ) + wmax -= 2*IncrBtnWidth(m_Font->m_CharHeight); + for( i=0; im_CharWidth[(int)ch]; + if( Etc>0 ) + { + ++Etc; + if( Etc>NbEtc ) + break; + } + else if( im_CharWidth[(int)'.']>=wmax ) + Etc = 1; + } + } + else + { + _Values.push_back(""); // add a new empty line + _Colors.push_back(COLOR32_BLACK); + _BgColors.push_back(0x00000000); + } +} + +// --------------------------------------------------------------------------- + +static int ClampText(string& _Text, const CTexFont *_Font, int _WidthMax) +{ + int Len = (int)_Text.length(); + unsigned char ch; + int Width = 0; + int i; + for( i=0; im_CharWidth[(int)'.']>=_WidthMax ) + break; + Width += _Font->m_CharWidth[ch]; + } + if( im_CharWidth[(int)'.']; + } + return Width; +} + +// --------------------------------------------------------------------------- + +void CTwBar::Update() +{ + assert(m_UpToDate==false); + assert(m_Font); + ITwGraph *Gr = g_TwMgr->m_Graph; + + bool DoEndDraw = false; + if( !Gr->IsDrawing() ) + { + Gr->BeginDraw(g_TwMgr->m_WndWidth, g_TwMgr->m_WndHeight); + DoEndDraw = true; + } + + int PrevPosY = m_PosY; + int vpx, vpy, vpw, vph; + vpx = 0; + vpy = 0; + vpw = g_TwMgr->m_WndWidth; + vph = g_TwMgr->m_WndHeight; + if( !m_IsMinimized && vpw>0 && vph>0 ) + { + bool Modif = false; + if( m_Width>vpw ) + { + m_Width = vpw; + Modif = true; + } + if( m_Width<8*m_Font->m_CharHeight ) + { + m_Width = 8*m_Font->m_CharHeight; + Modif = true; + } + if( m_Height>vph ) + { + m_Height = vph; + Modif = true; + } + if( m_Height<5*m_Font->m_CharHeight ) + { + m_Height = 5*m_Font->m_CharHeight; + Modif = true; + } + if( m_PosX+m_Width>vpx+vpw ) + m_PosX = vpx+vpw-m_Width; + if( m_PosXvpy+vph ) + m_PosY = vpy+vph-m_Height; + if( m_PosYm_CharHeight ) + { + m_ValuesWidth = 2*m_Font->m_CharHeight; + Modif = true; + } + if( m_ValuesWidth>m_Width-4*m_Font->m_CharHeight ) + { + m_ValuesWidth = m_Width-4*m_Font->m_CharHeight; + Modif = true; + } + if( Modif && m_IsHelpBar ) + { + g_TwMgr->m_HelpBarNotUpToDate = true; + g_TwMgr->m_KeyPressedBuildText = true; + g_TwMgr->m_InfoBuildText = true; + } + } + + UpdateColors(); + + // update geometry relatively to (m_PosX, m_PosY) + if( !m_IsPopupList ) + { + //m_VarX0 = 2*m_Font->m_CharHeight+m_Sep; + m_VarX0 = m_Font->m_CharHeight+m_Sep; + //m_VarX2 = m_Width - 4; + m_VarX2 = m_Width - m_Font->m_CharHeight - m_Sep-2; + m_VarX1 = m_VarX2 - m_ValuesWidth; + } + else + { + //m_VarX0 = m_Font->m_CharHeight+6+m_Sep; + m_VarX0 = 2; + //m_VarX2 = m_Width - 4; + m_VarX2 = m_Width - m_Font->m_CharHeight - m_Sep-2; + m_VarX1 = m_VarX2; + } + if( m_VarX1m_VarX2 ) + m_VarX1 = m_VarX2; + if( !m_IsPopupList ) + { + m_VarY0 = m_Font->m_CharHeight+2+m_Sep+6; + m_VarY1 = m_Height-m_Font->m_CharHeight-2-m_Sep; + m_VarY2 = m_Height-1; + } + else + { + m_VarY0 = 4; + m_VarY1 = m_Height-2-m_Sep; + m_VarY2 = m_Height-1; + } + + int NbLines = (m_VarY1-m_VarY0+1)/(m_Font->m_CharHeight+m_Sep); + if( NbLines<= 0 ) + NbLines = 1; + if( !m_IsMinimized ) + { + int LineNum = 0; + BrowseHierarchy(&LineNum, 0, &m_VarRoot, m_FirstLine, m_FirstLine+NbLines); // add a dummy tag at the end to avoid wrong 'tag-closing' problems + if( (int)m_HierTags.size()>NbLines ) + m_HierTags.resize(NbLines); // remove the last dummy tag + m_NbHierLines = LineNum; + m_NbDisplayedLines = (int)m_HierTags.size(); + } + + // scroll bar + int y0 = m_PosY+m_VarY0; + int y1 = m_PosY+m_VarY1; + int x0 = m_PosX+2; + int x1 = m_PosX+m_Font->m_CharHeight-2; + if( ((x0+x1)&1)==1 ) + x1 += 1; + int w = x1-x0+1; + int h = y1-y0-2*w; + int hscr = (m_NbHierLines>0) ? ((h*m_NbDisplayedLines)/m_NbHierLines) : h; + if( hscr<=4 ) + hscr = 4; + if( hscr>h ) + hscr = h; + int yscr = (m_NbHierLines>0) ? ((h*m_FirstLine)/m_NbHierLines) : 0; + if( yscr<=0 ) + yscr = 0; + if( yscr>h-4 ) + yscr = h-4; + if( yscr+hscr>h ) + hscr = h-yscr; + if( hscr>h ) + hscr = h; + if( hscr<=4 ) + hscr = 4; + m_ScrollYW = w; + m_ScrollYH = h; + m_ScrollY0 = y0+w+yscr; + m_ScrollY1 = y0+w+yscr+hscr; + + // Build title + string Title; + if( m_Label.size()>0 ) + Title = m_Label; + else + Title = m_Name; + m_TitleWidth = ClampText(Title, m_Font, (!m_IsMinimized)?(m_Width-5*m_Font->m_CharHeight):(16*m_Font->m_CharHeight)); + Gr->BuildText(m_TitleTextObj, &Title, NULL, NULL, 1, m_Font, 0, 0); + + if( !m_IsMinimized ) + { + // Build labels + vector Labels; + vector Colors; + ListLabels(Labels, Colors, m_Font, m_VarX1-m_VarX0, m_VarX2-m_VarX0); + Gr->BuildText(m_LabelsTextObj, &(Labels[0]), &(Colors[0]), NULL, (int)Labels.size(), m_Font, 1, 0); + + // Should draw click button? + m_DrawClickBtn = ( m_VarX2-m_VarX1>4*IncrBtnWidth(m_Font->m_CharHeight) + && m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size() + && m_HierTags[m_HighlightedLine].m_Var!=NULL + && !m_HierTags[m_HighlightedLine].m_Var->IsGroup() + && !static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly + && ( static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_Type==TW_TYPE_BUTTON )); + // || static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_Type==TW_TYPE_BOOLCPP + // || static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_Type==TW_TYPE_BOOL8 + // || static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_Type==TW_TYPE_BOOL16 + // || static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_Type==TW_TYPE_BOOL32 )); + + // Should draw [-/+] button? + m_DrawIncrDecrBtn = ( m_VarX2-m_VarX1>4*IncrBtnWidth(m_Font->m_CharHeight) + && m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size() + && m_HierTags[m_HighlightedLine].m_Var!=NULL + && !m_HierTags[m_HighlightedLine].m_Var->IsGroup() + && static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_Type!=TW_TYPE_BUTTON + && !static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly + && !static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_NoSlider ); + + // Build values + vector& Values = Labels; // reuse + Values.resize(0); + Colors.resize(0); + vector BgColors; + ListValues(Values, Colors, BgColors, m_Font, m_VarX2-m_VarX1); + assert(BgColors.size()==Values.size()); + Gr->BuildText(m_ValuesTextObj, &(Values[0]), &(Colors[0]), &(BgColors[0]), (int)Values.size(), m_Font, 1, m_VarX2-m_VarX1); + + // Build key shortcut text + string Shortcut; + m_ShortcutLine = -1; + if( m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size() && m_HierTags[m_HighlightedLine].m_Var!=NULL && !m_HierTags[m_HighlightedLine].m_Var->IsGroup() ) + { + const CTwVarAtom *Atom = static_cast(m_HierTags[m_HighlightedLine].m_Var); + if( Atom->m_KeyIncr[0]>0 || Atom->m_KeyDecr[0]>0 ) + { + if( Atom->m_KeyIncr[0]>0 && Atom->m_KeyDecr[0]>0 ) + Shortcut = "Keys: "; + else + Shortcut = "Key: "; + if( Atom->m_KeyIncr[0]>0 ) + TwGetKeyString(&Shortcut, Atom->m_KeyIncr[0], Atom->m_KeyIncr[1]); + else + Shortcut += "(none)"; + if( Atom->m_KeyDecr[0]>0 ) + { + Shortcut += " "; + TwGetKeyString(&Shortcut, Atom->m_KeyDecr[0], Atom->m_KeyDecr[1]); + } + m_ShortcutLine = m_HighlightedLine; + } + } + ClampText(Shortcut, m_Font, m_Width-3*m_Font->m_CharHeight); + Gr->BuildText(m_ShortcutTextObj, &Shortcut, NULL, NULL, 1, m_Font, 0, 0); + } + + if( DoEndDraw ) + Gr->EndDraw(); + + m_UpToDate = true; + m_LastUpdateTime = float(g_BarTimer.GetTime()); +} + +// --------------------------------------------------------------------------- + +void CTwBar::DrawHierHandle() +{ + assert(m_Font); + ITwGraph *Gr = g_TwMgr->m_Graph; + + //int x0 = m_PosX+m_Font->m_CharHeight+1; + int x0 = m_PosX+2; + int x2 = m_PosX+m_VarX0-5; + if( (x2-x0)&1 ) + --x2; + int x1 = (x0+x2)/2; + int w = x2-x0+1; + int y0 = m_PosY+m_VarY0; + int y1; + int dh0 = (m_Font->m_CharHeight+m_Sep-1-w)/2; + if( dh0<0 ) + dh0 = 0; + int dh1 = dh0+w-1; + int i, h=0; + + if( !m_IsPopupList ) + { + CTwVarGroup *Grp; + int nh = (int)m_HierTags.size(); + for( h=0; hm_CharHeight+m_Sep-1; + if( m_HierTags[h].m_Var->IsGroup() ) + Grp = static_cast(m_HierTags[h].m_Var); + else + Grp = NULL; + + if( Grp ) + { + Gr->DrawLine(x2+1,y0+dh0+1,x2+1,y0+dh1+1, m_ColLineShadow); + Gr->DrawLine(x0+1,y0+dh1+1,x2+2,y0+dh1+1, m_ColLineShadow); + if( Grp->m_Open ) + { + Gr->DrawLine(x1,y0+dh1, x1,y1+1, m_ColLine); + Gr->DrawLine(x1+1,y0+dh1, x1+1,y1+1, m_ColLineShadow); + } + } + + if( m_HierTags[h].m_Level>0 ) + { + if( Grp!=NULL ) + { + Gr->DrawLine(x1,y0, x1,y0+dh0, m_ColLine); + Gr->DrawLine(x1+1,y0, x1+1,y0+dh0, m_ColLineShadow); + } + + if( !m_HierTags[h].m_Closing && Grp==NULL ) + { + Gr->DrawLine(x1,y0, x1,y1+1, m_ColLine); + Gr->DrawLine(x1+1,y0, x1+1,y1+1, m_ColLineShadow); + } + + if( m_HierTags[h].m_Closing && Grp==NULL ) + { + Gr->DrawLine(x1,y0+dh0+w/2, x2+2,y0+dh0+w/2, m_ColLine); + Gr->DrawLine(x1+1,y0+dh0+w/2+1, x2+3,y0+dh0+w/2+1, m_ColLineShadow); + Gr->DrawLine(x1,y0, x1,y0+dh0+w/2, m_ColLine); + Gr->DrawLine(x1+1,y0, x1+1,y0+dh0+w/2, m_ColLineShadow); + if( m_HierTags[h].m_Level!=1 && h+1DrawLine(x1,y0+dh0+w/2+2, x1,y1+1, m_ColLine); + Gr->DrawLine(x1+1,y0+dh0+w/2+3, x1+1,y1+1, m_ColLineShadow); + } + } + } + + if( Grp ) + { + //Gr->DrawRect(x0+1,y0+dh0+1,x2-1,y0+dh1-1, (h==m_HighlightedLine) ? m_ColHighBtn : m_ColBtn); + Gr->DrawRect(x0,y0+dh0,x2,y0+dh1, (h==m_HighlightedLine) ? m_ColHighBtn : m_ColBtn); + if( m_DrawHandles ) + { + Gr->DrawLine(x0,y0+dh0,x2,y0+dh0, m_ColLine); + Gr->DrawLine(x2,y0+dh0,x2,y0+dh1+1, m_ColLine); + Gr->DrawLine(x2,y0+dh1,x0,y0+dh1, m_ColLine); + Gr->DrawLine(x0,y0+dh1,x0,y0+dh0, m_ColLine); + } + + Gr->DrawLine(x0+2,y0+dh0+w/2, x2-1,y0+dh0+w/2, m_ColTitleText); + if( !Grp->m_Open ) + Gr->DrawLine(x1,y0+dh0+2, x1,y0+dh1-1, m_ColTitleText); + + if( m_ColGrpBg!=0 && Grp->m_StructValuePtr==NULL ) + { + color32 cb = (Grp->m_StructType==TW_TYPE_HELP_STRUCT) ? m_ColStructBg : m_ColGrpBg; + //int decal = m_Font->m_CharHeight/2-2+2*m_HierTags[h].m_Level; + //if( decal>m_Font->m_CharHeight-3 ) + // decal = m_Font->m_CharHeight-3; + int margin = m_Font->m_CharWidth[(int)' ']*m_HierTags[h].m_Level; + //Gr->DrawRect(m_PosX+m_VarX0+margin, y0+decal, m_PosX+m_VarX2, y0+m_Font->m_CharHeight-1, cb); + Gr->DrawRect(m_PosX+m_VarX0+margin-1, y0+1, m_PosX+m_VarX2, y0+m_Font->m_CharHeight, cb);// m_ColHierBg); + //Gr->DrawRect(m_PosX+m_VarX0-4, y0+m_Font->m_CharHeight/2-1, m_PosX+m_VarX0+margin-2, y0+m_Font->m_CharHeight/2, m_ColHierBg); + } + } + else if( static_cast(m_HierTags[h].m_Var)->m_Type==TW_TYPE_HELP_GRP && m_ColHelpBg!=0 ) + Gr->DrawRect(m_PosX+m_VarX0+m_HierTags[h].m_Var->m_LeftMargin, y0+m_HierTags[h].m_Var->m_TopMargin, m_PosX+m_VarX2, y0+m_Font->m_CharHeight-1, m_ColHelpBg); + else if( static_cast(m_HierTags[h].m_Var)->m_Type==TW_TYPE_HELP_HEADER && m_ColHelpBg!=0 ) + Gr->DrawRect(m_PosX+m_VarX0+m_HierTags[h].m_Var->m_LeftMargin, y0+m_HierTags[h].m_Var->m_TopMargin, m_PosX+m_VarX2, y0+m_Font->m_CharHeight-1, m_ColHelpBg); + /* + else if( static_cast(m_HierTags[h].m_Var)->m_Type==TW_TYPE_BUTTON && m_ColBtn!=0 ) + { + // draw button + int cbx0 = m_PosX+m_VarX2-2*bw+bw/2, cby0 = y0+2, cbx1 = m_PosX+m_VarX2-2-bw/2, cby1 = y0+m_Font->m_CharHeight-4; + if( m_HighlightClickBtn ) + { + Gr->DrawRect(cbx0+2, cby0+2, cbx1+2, cby1+2, m_ColBtn); + Gr->DrawLine(cbx0+3, cby1+3, cbx1+4, cby1+3, 0x7F000000); + Gr->DrawLine(cbx1+3, cby0+3, cbx1+3, cby1+3, 0x7F000000); + } + else + { + Gr->DrawRect(cbx0+3, cby1+1, cbx1+3, cby1+3, 0x7F000000); + Gr->DrawRect(cbx1+1, cby0+3, cbx1+3, cby1, 0x7F000000); + Gr->DrawRect(cbx0, cby0, cbx1, cby1, m_ColBtn); + } + } + */ + + y0 = y1+1; + } + } + + if( m_NbDisplayedLinesm_CharHeight-2; + x0 = m_PosX + m_VarX2+4; + x1 = x0 + m_Font->m_CharHeight-4; + if( ((x0+x1)&1)==1 ) + x1 += 1; + w = m_ScrollYW; + h = m_ScrollYH; + + Gr->DrawRect(x0+2,y0+w, x1-2,y1-1-w, (m_ColBg&0xffffff)|0x3f000000); + if( m_DrawHandles || m_IsPopupList ) + { + // scroll handle shadow lines + Gr->DrawLine(x1-1,m_ScrollY0+1, x1-1,m_ScrollY1+1, m_ColLineShadow); + Gr->DrawLine(x0+2,m_ScrollY1+1, x1,m_ScrollY1+1, m_ColLineShadow); + + // up & down arrow + for( i=0; i<(x1-x0-2)/2; ++i ) + { + Gr->DrawLine(x0+2+i,y0+w-2*i, x1-i,y0+w-2*i, m_ColLineShadow); + Gr->DrawLine(x0+1+i,y0+w-1-2*i, x1-1-i,y0+w-1-2*i, m_HighlightUpScroll?m_ColBtn:m_ColLine); + + Gr->DrawLine(x0+2+i,y1-w+2+2*i, x1-i,y1-w+2+2*i, m_ColLineShadow); + Gr->DrawLine(x0+1+i,y1-w+1+2*i, x1-1-i,y1-w+1+2*i, m_HighlightDnScroll?m_ColBtn:m_ColLine); + } + + // middle lines + Gr->DrawLine((x0+x1)/2-1,y0+w, (x0+x1)/2-1,m_ScrollY0, m_ColLine); + Gr->DrawLine((x0+x1)/2,y0+w, (x0+x1)/2,m_ScrollY0, m_ColLine); + Gr->DrawLine((x0+x1)/2+1,y0+w, (x0+x1)/2+1,m_ScrollY0, m_ColLineShadow); + Gr->DrawLine((x0+x1)/2-1,m_ScrollY1, (x0+x1)/2-1,y1-w+1, m_ColLine); + Gr->DrawLine((x0+x1)/2,m_ScrollY1, (x0+x1)/2,y1-w+1, m_ColLine); + Gr->DrawLine((x0+x1)/2+1,m_ScrollY1, (x0+x1)/2+1,y1-w+1, m_ColLineShadow); + // scroll handle lines + Gr->DrawRect(x0+2,m_ScrollY0+1, x1-3,m_ScrollY1-1, m_HighlightScroll?m_ColHighBtn:m_ColBtn); + Gr->DrawLine(x1-2,m_ScrollY0, x1-2,m_ScrollY1, m_ColLine); + Gr->DrawLine(x0+1,m_ScrollY0, x0+1,m_ScrollY1, m_ColLine); + Gr->DrawLine(x0+1,m_ScrollY1, x1-1,m_ScrollY1, m_ColLine); + Gr->DrawLine(x0+1,m_ScrollY0, x1-2,m_ScrollY0, m_ColLine); + } + else + Gr->DrawRect(x0+3,m_ScrollY0+1, x1-3,m_ScrollY1-1, (m_ColBtn&0xffffff)|0x3f000000); + } + + if( m_DrawHandles && !m_IsPopupList ) + { + // Draw resize handles + // lower-left + Gr->DrawLine(m_PosX+3, m_PosY+m_Height-m_Font->m_CharHeight+3, m_PosX+3, m_PosY+m_Height-4, m_ColLine); + Gr->DrawLine(m_PosX+4, m_PosY+m_Height-m_Font->m_CharHeight+4, m_PosX+4, m_PosY+m_Height-3, m_ColLineShadow); + Gr->DrawLine(m_PosX+3, m_PosY+m_Height-4, m_PosX+m_Font->m_CharHeight-4, m_PosY+m_Height-4, m_ColLine); + Gr->DrawLine(m_PosX+4, m_PosY+m_Height-3, m_PosX+m_Font->m_CharHeight-3, m_PosY+m_Height-3, m_ColLineShadow); + // lower-right + Gr->DrawLine(m_PosX+m_Width-4, m_PosY+m_Height-m_Font->m_CharHeight+3, m_PosX+m_Width-4, m_PosY+m_Height-4, m_ColLine); + Gr->DrawLine(m_PosX+m_Width-3, m_PosY+m_Height-m_Font->m_CharHeight+4, m_PosX+m_Width-3, m_PosY+m_Height-3, m_ColLineShadow); + Gr->DrawLine(m_PosX+m_Width-4, m_PosY+m_Height-4, m_PosX+m_Width-m_Font->m_CharHeight+3, m_PosY+m_Height-4, m_ColLine); + Gr->DrawLine(m_PosX+m_Width-3, m_PosY+m_Height-3, m_PosX+m_Width-m_Font->m_CharHeight+4, m_PosY+m_Height-3, m_ColLineShadow); + // upper-left + Gr->DrawLine(m_PosX+3, m_PosY+m_Font->m_CharHeight-4, m_PosX+3, m_PosY+3, m_ColLine); + Gr->DrawLine(m_PosX+4, m_PosY+m_Font->m_CharHeight-3, m_PosX+4, m_PosY+4, m_ColLineShadow); + Gr->DrawLine(m_PosX+3, m_PosY+3, m_PosX+m_Font->m_CharHeight-4, m_PosY+3, m_ColLine); + Gr->DrawLine(m_PosX+4, m_PosY+4, m_PosX+m_Font->m_CharHeight-3, m_PosY+4, m_ColLineShadow); + // upper-right + Gr->DrawLine(m_PosX+m_Width-4, m_PosY+3, m_PosX+m_Width-m_Font->m_CharHeight+3, m_PosY+3, m_ColLine); + Gr->DrawLine(m_PosX+m_Width-3, m_PosY+4, m_PosX+m_Width-m_Font->m_CharHeight+4, m_PosY+4, m_ColLineShadow); + Gr->DrawLine(m_PosX+m_Width-4, m_PosY+m_Font->m_CharHeight-4, m_PosX+m_Width-4, m_PosY+3, m_ColLine); + Gr->DrawLine(m_PosX+m_Width-3, m_PosY+m_Font->m_CharHeight-3, m_PosX+m_Width-3, m_PosY+4, m_ColLineShadow); + + // Draw minimize button + int xm = m_PosX+m_Width-2*m_Font->m_CharHeight, wm=m_Font->m_CharHeight-6; + wm = (wm<6) ? 6 : wm; + Gr->DrawRect(xm+1, m_PosY+4, xm+wm-1, m_PosY+3+wm, m_HighlightMinimize?m_ColHighBtn:m_ColBtn); + Gr->DrawLine(xm, m_PosY+3, xm+wm, m_PosY+3, m_ColLine); + Gr->DrawLine(xm+wm, m_PosY+3, xm+wm, m_PosY+3+wm, m_ColLine); + Gr->DrawLine(xm+wm, m_PosY+3+wm, xm, m_PosY+3+wm, m_ColLine); + Gr->DrawLine(xm, m_PosY+3+wm, xm, m_PosY+3, m_ColLine); + Gr->DrawLine(xm+wm+1, m_PosY+4, xm+wm+1, m_PosY+4+wm, m_ColLineShadow); + Gr->DrawLine(xm+wm+1, m_PosY+4+wm, xm, m_PosY+4+wm, m_ColLineShadow); + Gr->DrawLine(xm+wm/3+((wm<9)?1:0), m_PosY+4+wm/3-((wm<9)?0:1), xm+wm/2+1, m_PosY+2+wm, m_ColTitleText, true); + Gr->DrawLine(xm+wm-wm/3+((wm<9)?0:1), m_PosY+4+wm/3-((wm<9)?0:1), xm+wm/2, m_PosY+2+wm, m_ColTitleText, true); + + // Draw font button + xm = m_PosX+m_Font->m_CharHeight+2; + Gr->DrawRect(xm+1, m_PosY+4, xm+wm-1, m_PosY+3+wm, m_HighlightFont?m_ColHighBtn:m_ColBtn); + Gr->DrawLine(xm, m_PosY+3, xm+wm, m_PosY+3, m_ColLine); + Gr->DrawLine(xm+wm, m_PosY+3, xm+wm, m_PosY+3+wm, m_ColLine); + Gr->DrawLine(xm+wm, m_PosY+3+wm, xm, m_PosY+3+wm, m_ColLine); + Gr->DrawLine(xm, m_PosY+3+wm, xm, m_PosY+3, m_ColLine); + Gr->DrawLine(xm+wm+1, m_PosY+4, xm+wm+1, m_PosY+4+wm, m_ColLineShadow); + Gr->DrawLine(xm+wm+1, m_PosY+4+wm, xm, m_PosY+4+wm, m_ColLineShadow); + Gr->DrawLine(xm+wm/2-wm/6, m_PosY+3+wm/3, xm+wm/2+wm/6+1, m_PosY+3+wm/3, m_ColTitleText); + Gr->DrawLine(xm+wm/2-wm/6, m_PosY+3+wm/3, xm+wm/2-wm/6, m_PosY+4+wm-wm/3+(wm>11?1:0), m_ColTitleText); + Gr->DrawLine(xm+wm/2-wm/6, m_PosY+3+wm/2+(wm>11?1:0), xm+wm/2+wm/6, m_PosY+3+wm/2+(wm>11?1:0), m_ColTitleText); + } +} + +// --------------------------------------------------------------------------- + +void CTwBar::Draw() +{ + PERF( PerfTimer Timer; double DT; ) + + assert(m_Font); + ITwGraph *Gr = g_TwMgr->m_Graph; + + if( float(g_BarTimer.GetTime())>m_LastUpdateTime+m_UpdatePeriod ) + NotUpToDate(); + + if( m_HighlightedLine!=m_HighlightedLinePrev ) + { + m_HighlightedLinePrev = m_HighlightedLine; + NotUpToDate(); + } + + if( m_IsHelpBar && g_TwMgr->m_HelpBarNotUpToDate ) + g_TwMgr->UpdateHelpBar(); + + if( !m_UpToDate ) + Update(); + + if( !m_IsMinimized ) + { + int y = m_PosY+1; + + // Draw title + if( !m_IsPopupList ) + { + PERF( Timer.Reset(); ) + Gr->DrawRect(m_PosX, m_PosY, m_PosX+m_Width-1, m_PosY+m_Font->m_CharHeight, (m_HighlightTitle||m_MouseDragTitle) ? m_ColTitleHighBg : m_ColTitleBg); + if( m_ColTitleShadow!=0 ) + Gr->DrawText(m_TitleTextObj, m_PosX+(m_Width-m_TitleWidth)/2+1, m_PosY+1, m_ColTitleShadow, 0); + Gr->DrawText(m_TitleTextObj, m_PosX+(m_Width-m_TitleWidth)/2, m_PosY, m_ColTitleText, 0); + y = m_PosY+m_Font->m_CharHeight+1; + Gr->DrawLine(m_PosX, y, m_PosX+m_Width-1, y, m_ColTitleShadow); + y++; + PERF( DT = Timer.GetTime(); printf("Title=%.4fms ", 1000.0*DT); ) + } + + // Draw background + PERF( Timer.Reset(); ) + //Gr->DrawRect(m_PosX, y, m_PosX+m_Width-1, m_PosY+m_Height-1, m_ColBg); + Gr->DrawRect(m_PosX, y, m_PosX+m_Width-1, m_PosY+m_Height-1, m_ColBg2, m_ColBg1, m_ColBg1, m_ColBg); + Gr->DrawRect(m_PosX, y, m_PosX+m_VarX0-5, m_PosY+m_Height-1, m_ColHierBg); + Gr->DrawRect(m_PosX+m_VarX2+3, y, m_PosX+m_Width-1, m_PosY+m_Height-1, m_ColHierBg); + // Draw highlighted line + if( m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size() && m_HierTags[m_HighlightedLine].m_Var!=NULL + && (m_HierTags[m_HighlightedLine].m_Var->IsGroup() || (!static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly && !m_IsHelpBar)) ) + { + int y0 = m_PosY + m_VarY0 + m_HighlightedLine*(m_Font->m_CharHeight+m_Sep); + Gr->DrawRect(m_PosX+m_VarX0, y0, m_PosX+m_VarX2, y0+m_Font->m_CharHeight-1, m_ColHighBg); + int eps = (g_TwMgr->m_GraphAPI==TW_OPENGL) ? 1 : 0; + Gr->DrawLine(m_PosX+m_VarX0, y0+m_Font->m_CharHeight+eps, m_PosX+m_VarX2, y0+m_Font->m_CharHeight+eps, m_ColUnderline); + } + int dshad = 3; // bar shadows + color32 cshad = (((m_Color>>24)/2)<<24) & 0xFF000000; + Gr->DrawRect(m_PosX, m_PosY+m_Height, m_PosX+dshad, m_PosY+m_Height+dshad, 0, cshad, 0, 0); + Gr->DrawRect(m_PosX+dshad+1, m_PosY+m_Height, m_PosX+m_Width-1, m_PosY+m_Height+dshad, cshad, cshad, 0, 0); + Gr->DrawRect(m_PosX+m_Width, m_PosY+m_Height, m_PosX+m_Width+dshad, m_PosY+m_Height+dshad, cshad, 0, 0, 0); + Gr->DrawRect(m_PosX+m_Width, m_PosY, m_PosX+m_Width+dshad, m_PosY+dshad, 0, 0, cshad, 0); + Gr->DrawRect(m_PosX+m_Width, m_PosY+dshad+1, m_PosX+m_Width+dshad, m_PosY+m_Height-1, cshad, 0, cshad, 0); + color32 clight = 0x5FFFFFFF; + Gr->DrawLine(m_PosX, m_PosY, m_PosX, m_PosY+m_Height, clight); + Gr->DrawLine(m_PosX, m_PosY, m_PosX+m_Width, m_PosY, clight); + PERF( DT = Timer.GetTime(); printf("Bg=%.4fms ", 1000.0*DT); ) + + // Draw hierarchy handle + PERF( Timer.Reset(); ) + DrawHierHandle(); + PERF( DT = Timer.GetTime(); printf("Handles=%.4fms ", 1000.0*DT); ) + + // Draw labels + PERF( Timer.Reset(); ) + Gr->DrawText(m_LabelsTextObj, m_PosX+m_VarX0, m_PosY+m_VarY0, 0 /*m_ColLabelText*/, 0); + PERF( DT = Timer.GetTime(); printf("Labels=%.4fms ", 1000.0*DT); ) + + // Draw values + if( !m_IsPopupList ) + { + PERF( Timer.Reset(); ) + Gr->DrawText(m_ValuesTextObj, m_PosX+m_VarX1, m_PosY+m_VarY0, 0 /*m_ColValText*/, 0 /*m_ColValBg*/); + PERF( DT = Timer.GetTime(); printf("Values=%.4fms ", 1000.0*DT); ) + } + + // Draw preview for color values and draw buttons + int h, nh = (int)m_HierTags.size(); + int yh = m_PosY+m_VarY0; + int bw = IncrBtnWidth(m_Font->m_CharHeight); + for( h=0; hIsGroup() ) + { + const CTwVarGroup * Grp = static_cast(m_HierTags[h].m_Var); + if( Grp->m_SummaryCallback==CColorExt::SummaryCB && Grp->m_StructValuePtr!=NULL ) + { + // draw color value + int ydecal = (g_TwMgr->m_GraphAPI==TW_OPENGL) ? 1 : 0; + const int checker = 8; + for( int c=0; cDrawRect(m_PosX+m_VarX1+(c*(m_VarX2-m_VarX1))/checker, yh+1+ydecal+((c%2)*(m_Font->m_CharHeight-2))/2, m_PosX+m_VarX1-1+((c+1)*(m_VarX2-m_VarX1))/checker, yh+ydecal+(((c%2)+1)*(m_Font->m_CharHeight-2))/2, 0xffffffff); + Gr->DrawRect(m_PosX+m_VarX1, yh+1+ydecal, m_PosX+m_VarX2-1, yh+ydecal+m_Font->m_CharHeight-2, 0xbfffffff); + const CColorExt *colExt = static_cast(Grp->m_StructValuePtr); + color32 col = Color32FromARGBi((colExt->m_HasAlpha ? colExt->A : 255), colExt->R, colExt->G, colExt->B); + if( col!=0 ) + Gr->DrawRect(m_PosX+m_VarX1, yh+1+ydecal, m_PosX+m_VarX2-1, yh+ydecal+m_Font->m_CharHeight-2, col); + /* + Gr->DrawLine(m_PosX+m_VarX1-1, yh, m_PosX+m_VarX2+1, yh, 0xff000000); + Gr->DrawLine(m_PosX+m_VarX1-1, yh+m_Font->m_CharHeight, m_PosX+m_VarX2+1, yh+m_Font->m_CharHeight, 0xff000000); + Gr->DrawLine(m_PosX+m_VarX1-1, yh, m_PosX+m_VarX1-1, yh+m_Font->m_CharHeight, 0xff000000); + Gr->DrawLine(m_PosX+m_VarX2, yh, m_PosX+m_VarX2, yh+m_Font->m_CharHeight, 0xff000000); + */ + } + } + else if( static_cast(m_HierTags[h].m_Var)->m_Type==TW_TYPE_BUTTON && !m_IsPopupList ) + { + // draw button + int cbx0 = m_PosX+m_VarX2-2*bw+bw/2, cby0 = yh+2, cbx1 = m_PosX+m_VarX2-2-bw/2, cby1 = yh+m_Font->m_CharHeight-4; + if( !static_cast(m_HierTags[h].m_Var)->m_ReadOnly ) + { + if( m_HighlightClickBtn && h==m_HighlightedLine ) + { + Gr->DrawRect(cbx0+2, cby0+2, cbx1+2, cby1+2, m_ColHighBtn); + Gr->DrawLine(cbx0+3, cby1+3, cbx1+4, cby1+3, 0xAF000000); + Gr->DrawLine(cbx1+3, cby0+3, cbx1+3, cby1+3, 0xAF000000); + } + else + { + Gr->DrawRect(cbx0+3, cby1+1, cbx1+3, cby1+3, (h==m_HighlightedLine)?0xAF000000:0x7F000000); + Gr->DrawRect(cbx1+1, cby0+3, cbx1+3, cby1, (h==m_HighlightedLine)?0xAF000000:0x7F000000); + Gr->DrawRect(cbx0, cby0, cbx1, cby1, (h==m_HighlightedLine)?m_ColHighBtn:m_ColBtn); + } + } + } + yh += m_Font->m_CharHeight+m_Sep; + } + + if( m_DrawHandles && !m_IsPopupList ) + { + // Draw -/+/click buttons + if( (m_DrawIncrDecrBtn || m_DrawClickBtn) && m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size() ) + { + int y0 = m_PosY + m_VarY0 + m_HighlightedLine*(m_Font->m_CharHeight+m_Sep); + if( m_DrawIncrDecrBtn ) + { + Gr->DrawRect(m_PosX+m_VarX2-2*bw+1, y0+1, m_PosX+m_VarX2-bw-1, y0+m_Font->m_CharHeight-2, m_HighlightDecrBtn?m_ColHighBtn:m_ColBtn); + Gr->DrawRect(m_PosX+m_VarX2-bw+1, y0+1, m_PosX+m_VarX2-1, y0+m_Font->m_CharHeight-2, m_HighlightIncrBtn?m_ColHighBtn:m_ColBtn); + // [-] + Gr->DrawLine(m_PosX+m_VarX2-2*bw+3, y0+m_Font->m_CharHeight/2, m_PosX+m_VarX2-bw-2, y0+m_Font->m_CharHeight/2, m_ColTitleText); + // [+] + Gr->DrawLine(m_PosX+m_VarX2-bw+3, y0+m_Font->m_CharHeight/2, m_PosX+m_VarX2-2, y0+m_Font->m_CharHeight/2, m_ColTitleText); + Gr->DrawLine(m_PosX+m_VarX2-bw/2, y0+m_Font->m_CharHeight/2-bw/2+2, m_PosX+m_VarX2-bw/2, y0+m_Font->m_CharHeight/2+bw/2-1, m_ColTitleText); + + // [o] rotoslider + //Gr->DrawRect(m_PosX+m_VarX2-3*bw+1, y0+1, m_PosX+m_VarX2-2*bw-1, y0+m_Font->m_CharHeight-2, (!m_HighlightDecrBtn && !m_HighlightIncrBtn)?m_ColHighBtn:m_ColBtn); + //Gr->DrawLine(m_PosX+m_VarX2-3*bw+bw/2-0, y0+m_Font->m_CharHeight/2-1, m_PosX+m_VarX2-3*bw+bw/2+1, y0+m_Font->m_CharHeight/2-1, m_ColTitleText); + //Gr->DrawLine(m_PosX+m_VarX2-3*bw+bw/2-1, y0+m_Font->m_CharHeight/2+0, m_PosX+m_VarX2-3*bw+bw/2+2, y0+m_Font->m_CharHeight/2+0, m_ColTitleText); + //Gr->DrawLine(m_PosX+m_VarX2-3*bw+bw/2-1, y0+m_Font->m_CharHeight/2+1, m_PosX+m_VarX2-3*bw+bw/2+2, y0+m_Font->m_CharHeight/2+1, m_ColTitleText); + //Gr->DrawLine(m_PosX+m_VarX2-3*bw+bw/2-0, y0+m_Font->m_CharHeight/2+2, m_PosX+m_VarX2-3*bw+bw/2+1, y0+m_Font->m_CharHeight/2+2, m_ColTitleText); + } + } + + // Draw value width slider + if( !m_HighlightValWidth ) + { + Gr->DrawRect(m_PosX+m_VarX1-2, m_PosY+m_VarY0-8, m_PosX+m_VarX1-1, m_PosY+m_VarY0-4, m_ColTitleText); + Gr->DrawLine(m_PosX+m_VarX1-1, m_PosY+m_VarY0-3, m_PosX+m_VarX1, m_PosY+m_VarY0-3, m_ColLineShadow); + Gr->DrawLine(m_PosX+m_VarX1, m_PosY+m_VarY0-3, m_PosX+m_VarX1, m_PosY+m_VarY0-8, m_ColLineShadow); + } + else + { + Gr->DrawRect(m_PosX+m_VarX1-2, m_PosY+m_VarY0-8, m_PosX+m_VarX1-1, m_PosY+m_VarY1, m_ColTitleText); + Gr->DrawLine(m_PosX+m_VarX1-1, m_PosY+m_VarY1+1, m_PosX+m_VarX1, m_PosY+m_VarY1+1, m_ColLineShadow); + Gr->DrawLine(m_PosX+m_VarX1, m_PosY+m_VarY1+1, m_PosX+m_VarX1, m_PosY+m_VarY0-8, m_ColLineShadow); + } + } + + // Draw key shortcut text + if( m_HighlightedLine>=0 && m_HighlightedLine==m_ShortcutLine && !m_IsPopupList ) + { + PERF( Timer.Reset(); ) + Gr->DrawRect(m_PosX+m_Font->m_CharHeight-2, m_PosY+m_VarY1+1, m_PosX+m_Width-m_Font->m_CharHeight-2, m_PosY+m_VarY1+1+m_Font->m_CharHeight, m_ColShortcutBg); + Gr->DrawText(m_ShortcutTextObj, m_PosX+m_Font->m_CharHeight, m_PosY+m_VarY1+1, m_ColShortcutText, 0); + PERF( DT = Timer.GetTime(); printf("Shortcut=%.4fms ", 1000.0*DT); ) + } + else if( m_IsHelpBar ) + { + if( g_TwMgr->m_KeyPressedTextObj && g_TwMgr->m_KeyPressedStr.size()>0 ) // Draw key pressed + { + if( g_TwMgr->m_KeyPressedBuildText ) + { + string Str = g_TwMgr->m_KeyPressedStr; + ClampText(Str, m_Font, m_Width-2*m_Font->m_CharHeight); + g_TwMgr->m_Graph->BuildText(g_TwMgr->m_KeyPressedTextObj, &Str, NULL, NULL, 1, g_TwMgr->m_HelpBar->m_Font, 0, 0); + g_TwMgr->m_KeyPressedBuildText = false; + g_TwMgr->m_KeyPressedTime = (float)g_BarTimer.GetTime(); + } + if( (float)g_BarTimer.GetTime()>g_TwMgr->m_KeyPressedTime+1.0f ) // draw key pressed at least 1 second + g_TwMgr->m_KeyPressedStr = ""; + PERF( Timer.Reset(); ) + Gr->DrawRect(m_PosX+m_Font->m_CharHeight-2, m_PosY+m_VarY1+1, m_PosX+m_Width-m_Font->m_CharHeight-2, m_PosY+m_VarY1+1+m_Font->m_CharHeight, m_ColShortcutBg); + Gr->DrawText(g_TwMgr->m_KeyPressedTextObj, m_PosX+m_Font->m_CharHeight, m_PosY+m_VarY1+1, m_ColShortcutText, 0); + PERF( DT = Timer.GetTime(); printf("KeyPressed=%.4fms ", 1000.0*DT); ) + } + else + { + if( g_TwMgr->m_InfoBuildText ) + { + string Info = "> AntTweakBar"; + //string Info = "> AntTweakBar - www.antisphere.com"; + char Ver[64]; + sprintf(Ver, " (v%d.%02d)", TW_VERSION/100, TW_VERSION%100); + Info += Ver; + ClampText(Info, m_Font, m_Width-2*m_Font->m_CharHeight); + g_TwMgr->m_Graph->BuildText(g_TwMgr->m_InfoTextObj, &Info, NULL, NULL, 1, g_TwMgr->m_HelpBar->m_Font, 0, 0); + g_TwMgr->m_InfoBuildText = false; + } + PERF( Timer.Reset(); ) + Gr->DrawRect(m_PosX+m_Font->m_CharHeight-2, m_PosY+m_VarY1+1, m_PosX+m_Width-m_Font->m_CharHeight-2, m_PosY+m_VarY1+1+m_Font->m_CharHeight, m_ColShortcutBg); + Gr->DrawText(g_TwMgr->m_InfoTextObj, m_PosX+m_Font->m_CharHeight, m_PosY+m_VarY1+1, m_ColInfoText, 0); + PERF( DT = Timer.GetTime(); printf("Info=%.4fms ", 1000.0*DT); ) + } + } + + if( !m_IsPopupList ) + { + // Draw RotoSlider + RotoDraw(); + } + + if( g_TwMgr->m_PopupBar!=NULL && this!=g_TwMgr->m_PopupBar ) + { + // darken bar if a popup bar is displayed + Gr->DrawRect(m_PosX, m_PosY, m_PosX+m_Width-1, m_PosY+m_Height-1, 0x1F000000); + } + + } + else // minimized + { + int vpx, vpy, vpw, vph; + vpx = 0; + vpy = 0; + vpw = g_TwMgr->m_WndWidth; + vph = g_TwMgr->m_WndHeight; + int n = vph/m_Font->m_CharHeight-1; + if( n<1 ) + n = 1; + m_MinPosY = vph-((m_MinNumber%n)+1)*m_Font->m_CharHeight; + m_MinPosX = (m_MinNumber/n)*m_Font->m_CharHeight; + + if( m_HighlightMaximize ) + { + // Draw title + Gr->DrawRect(m_MinPosX, m_MinPosY, m_MinPosX+m_TitleWidth+2*m_Font->m_CharHeight, m_MinPosY+m_Font->m_CharHeight, m_ColTitleBg); + if( m_ColTitleShadow!=0 ) + Gr->DrawText(m_TitleTextObj, m_MinPosX+(3*m_Font->m_CharHeight)/2, m_MinPosY+1, m_ColTitleShadow, 0); + Gr->DrawText(m_TitleTextObj, m_MinPosX+(3*m_Font->m_CharHeight)/2, m_MinPosY, m_ColTitleText, 0); + } + + if( !m_IsHelpBar ) + { + // Draw maximize button + int xm = m_MinPosX+2, wm=m_Font->m_CharHeight-6; + wm = (wm<6) ? 6 : wm; + Gr->DrawRect(xm+1, m_MinPosY+4, xm+wm-1, m_MinPosY+3+wm, m_HighlightMaximize?m_ColHighBtn:m_ColBtn); + Gr->DrawLine(xm, m_MinPosY+3, xm+wm, m_MinPosY+3, m_ColLine); + Gr->DrawLine(xm+wm, m_MinPosY+3, xm+wm, m_MinPosY+3+wm, m_ColLine); + Gr->DrawLine(xm+wm, m_MinPosY+3+wm, xm, m_MinPosY+3+wm, m_ColLine); + Gr->DrawLine(xm, m_MinPosY+3+wm, xm, m_MinPosY+3, m_ColLine); + Gr->DrawLine(xm+wm+1, m_MinPosY+4, xm+wm+1, m_MinPosY+4+wm, m_ColLineShadow); + Gr->DrawLine(xm+wm+1, m_MinPosY+4+wm, xm, m_MinPosY+4+wm, m_ColLineShadow); + Gr->DrawLine(xm+wm/3, m_MinPosY+3+wm-wm/3, xm+wm/2+1, m_MinPosY+5, m_ColTitleText, true); + Gr->DrawLine(xm+wm-wm/3+1, m_MinPosY+3+wm-wm/3, xm+wm/2, m_MinPosY+5, m_ColTitleText, true); + } + else + { + // Draw help button + int xm = m_MinPosX+2, wm=m_Font->m_CharHeight-6; + wm = (wm<6) ? 6 : wm; + Gr->DrawRect(xm+1, m_MinPosY+4, xm+wm-1, m_MinPosY+3+wm, m_HighlightMaximize?m_ColHighBtn:m_ColBtn); + Gr->DrawLine(xm, m_MinPosY+3, xm+wm, m_MinPosY+3, m_ColLine); + Gr->DrawLine(xm+wm, m_MinPosY+3, xm+wm, m_MinPosY+3+wm, m_ColLine); + Gr->DrawLine(xm+wm, m_MinPosY+3+wm, xm, m_MinPosY+3+wm, m_ColLine); + Gr->DrawLine(xm, m_MinPosY+3+wm, xm, m_MinPosY+3, m_ColLine); + Gr->DrawLine(xm+wm+1, m_MinPosY+4, xm+wm+1, m_MinPosY+4+wm, m_ColLineShadow); + Gr->DrawLine(xm+wm+1, m_MinPosY+4+wm, xm, m_MinPosY+4+wm, m_ColLineShadow); + Gr->DrawLine(xm+wm/2-wm/6, m_MinPosY+3+wm/4, xm+wm-wm/3, m_MinPosY+3+wm/4, m_ColTitleText); + Gr->DrawLine(xm+wm-wm/3, m_MinPosY+3+wm/4, xm+wm-wm/3, m_MinPosY+3+wm/2, m_ColTitleText); + Gr->DrawLine(xm+wm-wm/3, m_MinPosY+3+wm/2, xm+wm/2, m_MinPosY+3+wm/2, m_ColTitleText); + Gr->DrawLine(xm+wm/2, m_MinPosY+3+wm/2, xm+wm/2, m_MinPosY+3+wm-wm/4, m_ColTitleText); + Gr->DrawLine(xm+wm/2, m_MinPosY+3+wm-wm/4+1, xm+wm/2, m_MinPosY+3+wm-wm/4+2, m_ColTitleText); + } + } +} + +// --------------------------------------------------------------------------- + +bool CTwBar::MouseMotion(int _X, int _Y) +{ + assert(g_TwMgr->m_Graph && g_TwMgr->m_WndHeight>0 && g_TwMgr->m_WndWidth>0); + if( !m_UpToDate ) + Update(); + + bool Handled = false; + if( !m_IsMinimized ) + { + bool InBar = (_X>=m_PosX && _X=m_PosY && _Ym_Bars.size(); ++ib ) + if( g_TwMgr->m_Bars[ib]!=NULL ) + { + g_TwMgr->m_Bars[ib]->m_DrawHandles = false; + g_TwMgr->m_Bars[ib]->m_HighlightTitle = false; + } + m_DrawHandles = InBar; + + if( !m_MouseDrag ) + { + Handled = InBar; + m_HighlightedLine = -1; + m_HighlightIncrBtn = false; + m_HighlightDecrBtn = false; + m_HighlightClickBtn = false; + m_HighlightTitle = false; + m_HighlightScroll = false; + m_HighlightUpScroll = false; + m_HighlightDnScroll = false; + m_HighlightMinimize = false; + m_HighlightFont = false; + m_HighlightValWidth = false; + //if( InBar && _X>m_PosX+m_Font->m_CharHeight+1 && _X=m_PosY+m_VarY0 && _Ym_PosX+2 && _X=m_PosY+m_VarY0 && _Ym_CharHeight+m_Sep); + if( m_HighlightedLine>=(int)m_HierTags.size() ) + m_HighlightedLine = -1; + if( m_HighlightedLine<0 || m_HierTags[m_HighlightedLine].m_Var==NULL || m_HierTags[m_HighlightedLine].m_Var->IsGroup() ) + ANT_SET_CURSOR(Arrow); + else + { + if( !m_HierTags[m_HighlightedLine].m_Var->IsGroup() && static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_NoSlider ) + { + if( static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly && !m_IsHelpBar ) + ANT_SET_CURSOR(No); //(Arrow); + else + ANT_SET_CURSOR(Arrow); + } + else if( m_DrawIncrDecrBtn && _X>=m_PosX+m_VarX2-IncrBtnWidth(m_Font->m_CharHeight) ) // [+] button + { + m_HighlightIncrBtn = true; + ANT_SET_CURSOR(Arrow); + } + else if( m_DrawIncrDecrBtn && _X>=m_PosX+m_VarX2-2*IncrBtnWidth(m_Font->m_CharHeight) ) // [-] button + { + m_HighlightDecrBtn = true; + ANT_SET_CURSOR(Arrow); + } + else if( !m_HierTags[m_HighlightedLine].m_Var->IsGroup() && static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly ) + { + if( !m_IsHelpBar ) + ANT_SET_CURSOR(No); + else + ANT_SET_CURSOR(Arrow); + } + else + ANT_SET_CURSOR(Point); + //ANT_SET_CURSOR(WE); + } + } + else if( InBar && !m_IsPopupList && _X>=m_PosX+2*m_Font->m_CharHeight && _Xm_CharHeight && _Ym_CharHeight ) + { + m_HighlightTitle = true; + ANT_SET_CURSOR(Move); + } + else if ( InBar && !m_IsPopupList && _X>=m_PosX+m_VarX1-3 && _Xm_PosY+m_Font->m_CharHeight && _Y=m_PosX && _Xm_CharHeight && _Y>=m_ScrollY0 && _Y=m_PosX+m_VarX2+2 && _X=m_ScrollY0 && _Y=m_PosX+m_VarX2+2 && _X=m_PosY+m_VarY0 && _Y=m_PosX+m_VarX2+2 && _X=m_ScrollY1 && _Y=m_PosX && _Xm_CharHeight && _Y>=m_PosY && _Ym_CharHeight ) + ANT_SET_CURSOR(TopLeft); + else if( InBar && !m_IsPopupList && _X>=m_PosX && _Xm_CharHeight && _Y>=m_PosY+m_Height-m_Font->m_CharHeight && _Y=m_PosX+m_Width-m_Font->m_CharHeight && _X=m_PosY && _Ym_CharHeight ) + ANT_SET_CURSOR(TopRight); + else if( InBar && !m_IsPopupList && _X>=m_PosX+m_Width-m_Font->m_CharHeight && _X=m_PosY+m_Height-m_Font->m_CharHeight && _Y=m_PosX+m_Font->m_CharHeight && _Xm_CharHeight && _Ym_CharHeight ) + { + m_HighlightFont = true; + ANT_SET_CURSOR(Arrow); + } + else if( InBar && !m_IsPopupList && _X>=m_PosX+m_Width-2*m_Font->m_CharHeight && _Xm_CharHeight && _Ym_CharHeight ) + { + m_HighlightMinimize = true; + ANT_SET_CURSOR(Arrow); + } + else if( m_IsHelpBar && InBar && _X>=m_PosX+m_VarX0 && _Xm_CharHeight && _Y>m_PosY+m_Height-m_Font->m_CharHeight && _Y=0 && m_HighlightedLine<(int)m_HierTags.size() && m_HierTags[m_HighlightedLine].m_Var && !m_HierTags[m_HighlightedLine].m_Var->IsGroup() ) + { + /* + CTwVarAtom *Var = static_cast(m_HierTags[m_HighlightedLine].m_Var); + int Delta = _X-m_MouseOriginX; + if( Delta!=0 ) + { + if( !Var->m_NoSlider && !Var->m_ReadOnly ) + { + Var->Increment(Delta); + NotUpToDate(); + } + m_VarHasBeenIncr = true; + } + m_MouseOriginX = _X; + m_MouseOriginY = _Y; + if( !Var->m_NoSlider && !Var->m_ReadOnly ) + ANT_SET_CURSOR(Center); + //ANT_SET_CURSOR(WE); + else + ANT_SET_CURSOR(Arrow); + Handled = true; + */ + + // move rotoslider + if( !static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_NoSlider ) + RotoOnMouseMove(_X, _Y); + + if( static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly ) + ANT_SET_CURSOR(No); + else if( static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_NoSlider ) + ANT_SET_CURSOR(Arrow); + m_VarHasBeenIncr = true; + Handled = true; + m_DrawHandles = true; + } + else if( m_MouseDragTitle ) + { + int y = m_PosY; + m_PosX += _X-m_MouseOriginX; + m_PosY += _Y-m_MouseOriginY; + m_MouseOriginX = _X; + m_MouseOriginY = _Y; + int vpx, vpy, vpw, vph; + vpx = 0; + vpy = 0; + vpw = g_TwMgr->m_WndWidth; + vph = g_TwMgr->m_WndHeight; + if( m_PosX+m_Width>vpx+vpw ) + m_PosX = vpx+vpw-m_Width; + if( m_PosXvpy+vph ) + m_PosY = vpy+vph-m_Height; + if( m_PosYm_HelpBarNotUpToDate = true; + ANT_SET_CURSOR(WE); + Handled = true; + m_DrawHandles = true; + } + else if( m_MouseDragScroll ) + { + if( m_ScrollYH>0 ) + { + int dl = ((_Y-m_MouseOriginY)*m_NbHierLines)/m_ScrollYH; + if( m_FirstLine0+dl<0 ) + m_FirstLine = 0; + else if( m_FirstLine0+dl+m_NbDisplayedLines>m_NbHierLines ) + m_FirstLine = m_NbHierLines-m_NbDisplayedLines; + else + m_FirstLine = m_FirstLine0+dl; + NotUpToDate(); + } + ANT_SET_CURSOR(NS); + Handled = true; + m_DrawHandles = true; + } + else if( m_MouseDragResizeUL ) + { + m_PosX += _X-m_MouseOriginX; + m_PosY += _Y-m_MouseOriginY; + m_Width -= _X-m_MouseOriginX; + m_Height -= _Y-m_MouseOriginY; + m_MouseOriginX = _X; + m_MouseOriginY = _Y; + ANT_SET_CURSOR(TopLeft); + NotUpToDate(); + if( m_IsHelpBar ) + { + g_TwMgr->m_HelpBarNotUpToDate = true; + g_TwMgr->m_HelpBarUpdateNow = true; + } + g_TwMgr->m_KeyPressedBuildText = true; + g_TwMgr->m_InfoBuildText = true; + Handled = true; + m_DrawHandles = true; + } + else if( m_MouseDragResizeUR ) + { + m_PosY += _Y-m_MouseOriginY; + m_Width += _X-m_MouseOriginX; + m_Height -= _Y-m_MouseOriginY; + m_MouseOriginX = _X; + m_MouseOriginY = _Y; + ANT_SET_CURSOR(TopRight); + NotUpToDate(); + if( m_IsHelpBar ) + { + g_TwMgr->m_HelpBarNotUpToDate = true; + g_TwMgr->m_HelpBarUpdateNow = true; + } + g_TwMgr->m_KeyPressedBuildText = true; + g_TwMgr->m_InfoBuildText = true; + Handled = true; + m_DrawHandles = true; + } + else if( m_MouseDragResizeLL ) + { + m_PosX += _X-m_MouseOriginX; + m_Width -= _X-m_MouseOriginX; + m_Height += _Y-m_MouseOriginY; + m_MouseOriginX = _X; + m_MouseOriginY = _Y; + ANT_SET_CURSOR(BottomLeft); + NotUpToDate(); + if( m_IsHelpBar ) + { + g_TwMgr->m_HelpBarNotUpToDate = true; + g_TwMgr->m_HelpBarUpdateNow = true; + } + g_TwMgr->m_KeyPressedBuildText = true; + g_TwMgr->m_InfoBuildText = true; + Handled = true; + m_DrawHandles = true; + } + else if( m_MouseDragResizeLR ) + { + m_Width += _X-m_MouseOriginX; + m_Height += _Y-m_MouseOriginY; + m_MouseOriginX = _X; + m_MouseOriginY = _Y; + ANT_SET_CURSOR(BottomRight); + NotUpToDate(); + if( m_IsHelpBar ) + { + g_TwMgr->m_HelpBarNotUpToDate = true; + g_TwMgr->m_HelpBarUpdateNow = true; + } + g_TwMgr->m_KeyPressedBuildText = true; + g_TwMgr->m_InfoBuildText = true; + Handled = true; + m_DrawHandles = true; + } + //else if( InBar ) + // ANT_SET_CURSOR(Arrow); + } + } + else // minimized + { + if( _X>=m_MinPosX+2 && _Xm_CharHeight && _Y>m_MinPosY && _Ym_CharHeight-2 ) + { + m_HighlightMaximize = true; + if( !m_IsHelpBar ) + ANT_SET_CURSOR(Arrow); + else + ANT_SET_CURSOR(Help); + Handled = true; + } + else + m_HighlightMaximize = false; + } + + return Handled; +} + +// --------------------------------------------------------------------------- + +#ifdef ANT_WINDOWS +# pragma optimize("", off) +// disable optimizations because the conversion of Enum from unsigned int to double is not always exact if optimized and GraphAPI=DirectX ! +#endif +static void ANT_CALL PopupCallback(void *_ClientData) +{ + if( g_TwMgr!=NULL && g_TwMgr->m_PopupBar!=NULL ) + { + unsigned int Enum = *(unsigned int *)&_ClientData; + CTwVarAtom *Var = g_TwMgr->m_PopupBar->m_VarEnumLinkedToPopupList; + CTwBar *Bar = g_TwMgr->m_PopupBar->m_BarLinkedToPopupList; + if( Bar!=NULL && Var!=NULL && !Var->m_ReadOnly && (Var->m_Type>=TW_TYPE_ENUM_BASE && Var->m_Type<=TW_TYPE_ENUM_BASE+(int)g_TwMgr->m_Enums.size()) ) + { + Var->ValueFromDouble(Enum); + Bar->UnHighlightLine(); + Bar->NotUpToDate(); + } + TwDeleteBar(g_TwMgr->m_PopupBar); + g_TwMgr->m_PopupBar = NULL; + } +} +#ifdef ANT_WINDOWS +# pragma optimize("", on) +#endif + +// --------------------------------------------------------------------------- + +bool CTwBar::MouseButton(ETwMouseButtonID _Button, bool _Pressed, int _X, int _Y) +{ + assert(g_TwMgr->m_Graph && g_TwMgr->m_WndHeight>0 && g_TwMgr->m_WndWidth>0); + bool Handled = false; + if( !m_UpToDate ) + Update(); + + if( !m_IsMinimized ) + { + Handled = (_X>=m_PosX && _X=m_PosY && _Y=0 && m_HighlightedLine<(int)m_HierTags.size() && m_HierTags[m_HighlightedLine].m_Var ) + { + if( m_HierTags[m_HighlightedLine].m_Var->IsGroup() ) + { + if( _Pressed && !g_TwMgr->m_IsRepeatingMousePressed ) + { + CTwVarGroup *Grp = static_cast(m_HierTags[m_HighlightedLine].m_Var); + Grp->m_Open = !Grp->m_Open; + NotUpToDate(); + ANT_SET_CURSOR(Arrow); + } + } + else if( _Pressed && m_HighlightIncrBtn ) + { + static_cast(m_HierTags[m_HighlightedLine].m_Var)->Increment(1); + NotUpToDate(); + } + else if( _Pressed && m_HighlightDecrBtn ) + { + static_cast(m_HierTags[m_HighlightedLine].m_Var)->Increment(-1); + NotUpToDate(); + } + else if( _Pressed && !m_MouseDrag ) + { + m_MouseDrag = true; + m_MouseDragVar = true; + m_MouseOriginX = _X; + m_MouseOriginY = _Y; + m_VarHasBeenIncr = false; + CTwVarAtom * Var = static_cast(m_HierTags[m_HighlightedLine].m_Var); + if( !Var->m_NoSlider && !Var->m_ReadOnly ) + { + // begin rotoslider + RotoOnLButtonDown(_X, _Y); + m_MouseDrag = true; + m_MouseDragVar = true; + } + else if( (Var->m_Type==TW_TYPE_BOOL8 || Var->m_Type==TW_TYPE_BOOL16 || Var->m_Type==TW_TYPE_BOOL32 || Var->m_Type==TW_TYPE_BOOLCPP) && !Var->m_ReadOnly ) + { + Var->Increment(1); + //m_HighlightClickBtn = true; + m_VarHasBeenIncr = true; + m_MouseDragVar = false; + m_MouseDrag = false; + NotUpToDate(); + } + else if( Var->m_Type==TW_TYPE_BUTTON && !Var->m_ReadOnly ) + { + m_HighlightClickBtn = true; + m_MouseDragVar = false; + m_MouseDrag = false; + } + //else if( (Var->m_Type==TW_TYPE_ENUM8 || Var->m_Type==TW_TYPE_ENUM16 || Var->m_Type==TW_TYPE_ENUM32) && !Var->m_ReadOnly ) + else if( (Var->m_Type>=TW_TYPE_ENUM_BASE && Var->m_Type<=TW_TYPE_ENUM_BASE+(int)g_TwMgr->m_Enums.size()) && !Var->m_ReadOnly && !g_TwMgr->m_IsRepeatingMousePressed ) + { + m_MouseDragVar = false; + m_MouseDrag = false; + if( g_TwMgr->m_PopupBar!=NULL ) + { + TwDeleteBar(g_TwMgr->m_PopupBar); + g_TwMgr->m_PopupBar = NULL; + } + // popup list + CTwMgr::CEnum& e = g_TwMgr->m_Enums[Var->m_Type-TW_TYPE_ENUM_BASE]; + g_TwMgr->m_PopupBar = TwNewBar("~ Enum Popup ~"); + g_TwMgr->m_PopupBar->m_IsPopupList = true; + g_TwMgr->m_PopupBar->m_Color = m_Color; + g_TwMgr->m_PopupBar->m_PosX = m_PosX + m_VarX1 - 2; + g_TwMgr->m_PopupBar->m_PosY = m_PosY + m_VarY0 + (m_HighlightedLine+1)*(m_Font->m_CharHeight+m_Sep); + g_TwMgr->m_PopupBar->m_Width = m_Width - 2*m_Font->m_CharHeight; + int popHeight0 = (int)e.m_Entries.size()*(m_Font->m_CharHeight+m_Sep) + m_Font->m_CharHeight/2+2; + int popHeight = popHeight0; + if( g_TwMgr->m_PopupBar->m_PosY+popHeight+2 > g_TwMgr->m_WndHeight ) + popHeight = g_TwMgr->m_WndHeight-g_TwMgr->m_PopupBar->m_PosY-2; + if( popHeightm_WndHeight/2 ) + popHeight = min(popHeight0, g_TwMgr->m_WndHeight/2); + if( popHeight<3*(m_Font->m_CharHeight+m_Sep) ) + popHeight = 3*(m_Font->m_CharHeight+m_Sep); + g_TwMgr->m_PopupBar->m_Height = popHeight; + g_TwMgr->m_PopupBar->m_VarEnumLinkedToPopupList = Var; + g_TwMgr->m_PopupBar->m_BarLinkedToPopupList = this; + for( CTwMgr::CEnum::CEntries::iterator It=e.m_Entries.begin(); It!=e.m_Entries.end(); ++It ) + { + char ID[64]; + sprintf(ID, "%u", It->first); + //ultoa(It->first, ID, 10); + TwAddButton(g_TwMgr->m_PopupBar, ID, PopupCallback, *(void**)&(It->first), NULL); + CTwVar *Btn = g_TwMgr->m_PopupBar->Find(ID); + if( Btn!=NULL ) + Btn->m_Label = It->second.c_str(); + } + g_TwMgr->m_HelpBarNotUpToDate = false; + } + else if( Var->m_ReadOnly ) + ANT_SET_CURSOR(No); + else + ANT_SET_CURSOR(Arrow); + } + else if ( !_Pressed && m_MouseDragVar ) + { + m_MouseDrag = false; + m_MouseDragVar = false; + if( !Handled ) + m_DrawHandles = false; + Handled = true; + // end rotoslider + RotoOnLButtonUp(_X, _Y); + + /* Incr/decr on right or left click + if( !m_VarHasBeenIncr && !static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly ) + { + if( _Button==TW_MOUSE_LEFT ) + static_cast(m_HierTags[m_HighlightedLine].m_Var)->Increment(-1); + else if( _Button==TW_MOUSE_RIGHT ) + static_cast(m_HierTags[m_HighlightedLine].m_Var)->Increment(1); + NotUpToDate(); + } + */ + + if( static_cast(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly ) + ANT_SET_CURSOR(No); + else + ANT_SET_CURSOR(Arrow); + } + else if( !_Pressed && m_HighlightClickBtn ) // a button variable is activated + { + m_HighlightClickBtn = false; + m_MouseDragVar = false; + m_MouseDrag = false; + Handled = true; + NotUpToDate(); + CTwVarAtom * Var = static_cast(m_HierTags[m_HighlightedLine].m_Var); + if( !Var->m_ReadOnly && Var->m_Type==TW_TYPE_BUTTON && Var->m_ButtonCallback!=NULL ) + Var->m_ButtonCallback(Var->m_ClientData); + } + else if( !_Pressed ) + { + m_MouseDragVar = false; + m_MouseDrag = false; + } + } + else if( _Pressed && !m_MouseDrag && !m_IsPopupList && _Button==TW_MOUSE_LEFT && _X>=m_PosX+2*m_Font->m_CharHeight && _Xm_CharHeight && _Y>=m_PosY && _Ym_CharHeight ) + { + m_MouseDrag = true; + m_MouseDragTitle = true; + m_MouseOriginX = _X; + m_MouseOriginY = _Y; + m_HighlightTitle = true; + ANT_SET_CURSOR(Move); + } + else if( !_Pressed && m_MouseDragTitle ) + { + m_MouseDrag = false; + m_MouseDragTitle = false; + ANT_SET_CURSOR(Arrow); + } + else if ( _Pressed && !m_MouseDrag && !m_IsPopupList && _Button==TW_MOUSE_LEFT && _X>=m_PosX+m_VarX1-3 && _Xm_PosY+m_Font->m_CharHeight && _Y=m_PosX+m_VarX2+2 && _X=m_ScrollY0 && _Y=m_PosX+m_VarX2+2 && _X=m_PosY+m_VarY0 && _Y0 ) + { + --m_FirstLine; + NotUpToDate(); + } + } + else if( _Pressed && _Button==TW_MOUSE_LEFT && _X>=m_PosX+m_VarX2+2 && _X=m_ScrollY1 && _Y=m_PosX && _Xm_CharHeight && _Y>=m_PosY && _Ym_CharHeight ) + { + m_MouseDrag = true; + m_MouseDragResizeUL = true; + m_MouseOriginX = _X; + m_MouseOriginY = _Y; + ANT_SET_CURSOR(TopLeft); + } + else if( !_Pressed && m_MouseDragResizeUL ) + { + m_MouseDrag = false; + m_MouseDragResizeUL = false; + ANT_SET_CURSOR(Arrow); + } + else if( _Pressed && !m_MouseDrag && !m_IsPopupList && _Button==TW_MOUSE_LEFT && _X>=m_PosX+m_Width-m_Font->m_CharHeight && _X=m_PosY && _Ym_CharHeight ) + { + m_MouseDrag = true; + m_MouseDragResizeUR = true; + m_MouseOriginX = _X; + m_MouseOriginY = _Y; + ANT_SET_CURSOR(TopRight); + } + else if( !_Pressed && m_MouseDragResizeUR ) + { + m_MouseDrag = false; + m_MouseDragResizeUR = false; + ANT_SET_CURSOR(Arrow); + } + else if( _Pressed && !m_MouseDrag && !m_IsPopupList && _Button==TW_MOUSE_LEFT && _X>=m_PosX && _Xm_CharHeight && _Y>=m_PosY+m_Height-m_Font->m_CharHeight && _Y=m_PosX+m_Width-m_Font->m_CharHeight && _X=m_PosY+m_Height-m_Font->m_CharHeight && _Y=m_PosX+m_Font->m_CharHeight && _Xm_CharHeight && _Y>m_PosY && _Ym_CharHeight ) + { + // change font + if( _Button==TW_MOUSE_LEFT ) + { + if( m_Font==g_DefaultSmallFont ) + g_TwMgr->SetFont(g_DefaultNormalFont, true); + else if( m_Font==g_DefaultNormalFont ) + g_TwMgr->SetFont(g_DefaultLargeFont, true); + else if( m_Font==g_DefaultLargeFont ) + g_TwMgr->SetFont(g_DefaultSmallFont, true); + else + g_TwMgr->SetFont(g_DefaultNormalFont, true); + } + else if( _Button==TW_MOUSE_RIGHT ) + { + if( m_Font==g_DefaultSmallFont ) + g_TwMgr->SetFont(g_DefaultLargeFont, true); + else if( m_Font==g_DefaultNormalFont ) + g_TwMgr->SetFont(g_DefaultSmallFont, true); + else if( m_Font==g_DefaultLargeFont ) + g_TwMgr->SetFont(g_DefaultNormalFont, true); + else + g_TwMgr->SetFont(g_DefaultNormalFont, true); + } + + ANT_SET_CURSOR(Arrow); + } + else if( _Pressed && !m_IsPopupList && _Button==TW_MOUSE_LEFT && _X>=m_PosX+m_Width-2*m_Font->m_CharHeight && _Xm_CharHeight && _Y>m_PosY && _Ym_CharHeight ) + { + // minimize + g_TwMgr->Minimize(this); + ANT_SET_CURSOR(Arrow); + } + else if( m_IsHelpBar && _Pressed && !g_TwMgr->m_IsRepeatingMousePressed && _X>=m_PosX+m_VarX0 && _Xm_CharHeight && _Y>m_PosY+m_Height-m_Font->m_CharHeight && _YMaximize(this); + ANT_SET_CURSOR(Arrow); + Handled = true; + } + } + + return Handled; +} + + +// --------------------------------------------------------------------------- + +bool CTwBar::MouseWheel(int _Pos, int _PrevPos, int _MouseX, int _MouseY) +{ + assert(g_TwMgr->m_Graph && g_TwMgr->m_WndHeight>0 && g_TwMgr->m_WndWidth>0); + if( !m_UpToDate ) + Update(); + + bool Handled = false; + if( !m_IsMinimized && _MouseX>=m_PosX && _MouseX=m_PosY && _MouseY_PrevPos && m_FirstLine>0 ) + { + --m_FirstLine; + NotUpToDate(); + } + else if( _Pos<_PrevPos && m_FirstLine' ' && _Key<256 ) // don't test SHIFT if _Key is a common key + Mask &= ~TW_KMOD_SHIFT; + + // don't test KMOD_NUM and KMOD_CAPS modifiers coming from SDL + Mask &= ~(0x1000); // 0x1000 is the KMOD_NUM value defined in SDL_keysym.h + Mask &= ~(0x2000); // 0x2000 is the KMOD_CAPS value defined in SDL_keysym.h + + // complete partial modifiers comming from SDL + if( _Modifiers & TW_KMOD_SHIFT ) + _Modifiers |= TW_KMOD_SHIFT; + if( _Modifiers & TW_KMOD_CTRL ) + _Modifiers |= TW_KMOD_CTRL; + if( _Modifiers & TW_KMOD_ALT ) + _Modifiers |= TW_KMOD_ALT; + if( _Modifiers & TW_KMOD_META ) + _Modifiers |= TW_KMOD_META; + + for(size_t i=0; iIsGroup() ) + { + Atom = static_cast(m_Vars[i])->FindShortcut(_Key, _Modifiers, _DoIncr); + if( Atom!=NULL ) + return Atom; + } + else + { + Atom = static_cast(m_Vars[i]); + if( Atom->m_KeyIncr[0]==_Key && (Atom->m_KeyIncr[1]&Mask)==(_Modifiers&Mask) ) + { + if( _DoIncr!=NULL ) + *_DoIncr = true; + return Atom; + } + else if( Atom->m_KeyDecr[0]==_Key && (Atom->m_KeyDecr[1]&Mask)==(_Modifiers&Mask) ) + { + if( _DoIncr!=NULL ) + *_DoIncr = false; + return Atom; + } + } + } + return NULL; +} + +bool CTwBar::KeyPressed(int _Key, int _Modifiers) +{ + assert(g_TwMgr->m_Graph && g_TwMgr->m_WndHeight>0 && g_TwMgr->m_WndWidth>0); + bool Handled = false; + if( !m_UpToDate ) + Update(); + + if( _Key>0 && _Key0 && _Key<32 ) + _Key += 'a'-1; + + // PAD translation (for SDL keysym) + if( _Key>=256 && _Key<=272 ) // 256=SDLK_KP0 ... 272=SDLK_KP_EQUALS + { + bool Num = ((_Modifiers&TW_KMOD_SHIFT) && !(_Modifiers&0x1000)) || (!(_Modifiers&TW_KMOD_SHIFT) && (_Modifiers&0x1000)); // 0x1000 is SDL's KMOD_NUM + _Modifiers &= ~TW_KMOD_SHIFT; // remove shift modifier + if( _Key==266 ) // SDLK_KP_PERIOD + _Key = Num ? '.' : TW_KEY_DELETE; + else if( _Key==267 ) // SDLK_KP_DIVIDE + _Key = '/'; + else if( _Key==268 ) // SDLK_KP_MULTIPLY + _Key = '*'; + else if( _Key==269 ) // SDLK_KP_MINUS + _Key = '-'; + else if( _Key==270 ) // SDLK_KP_PLUS + _Key = '+'; + else if( _Key==271 ) // SDLK_KP_ENTER + _Key = TW_KEY_RETURN; + else if( _Key==272 ) // SDLK_KP_EQUALS + _Key = '='; + else if( Num ) // num SDLK_KP0..9 + _Key += '0' - 256; + else if( _Key==256 ) // non-num SDLK_KP01 + _Key = TW_KEY_INSERT; + else if( _Key==257 ) // non-num SDLK_KP1 + _Key = TW_KEY_END; + else if( _Key==258 ) // non-num SDLK_KP2 + _Key = TW_KEY_DOWN; + else if( _Key==259 ) // non-num SDLK_KP3 + _Key = TW_KEY_PAGE_DOWN; + else if( _Key==260 ) // non-num SDLK_KP4 + _Key = TW_KEY_LEFT; + else if( _Key==262 ) // non-num SDLK_KP6 + _Key = TW_KEY_RIGHT; + else if( _Key==263 ) // non-num SDLK_KP7 + _Key = TW_KEY_HOME; + else if( _Key==264 ) // non-num SDLK_KP8 + _Key = TW_KEY_UP; + else if( _Key==265 ) // non-num SDLK_KP9 + _Key = TW_KEY_PAGE_UP; + } + */ + + /* + string Str; + TwGetKeyString(&Str, _Key, _Modifiers); + printf("key: %d 0x%04xd %s\n", _Key, _Modifiers, Str.c_str()); + */ + bool DoIncr = true; + CTwVarAtom *Atom = m_VarRoot.FindShortcut(_Key, _Modifiers, &DoIncr); + if( Atom!=NULL && Atom->m_Visible ) + { + if( !Atom->m_ReadOnly ) + Atom->Increment( DoIncr ? +1 : -1 ); + NotUpToDate(); + Show(Atom); + Handled = true; + } + } + return Handled; +} + +// --------------------------------------------------------------------------- + +bool CTwBar::Show(CTwVar *_Var) +{ + if( _Var==NULL || !_Var->m_Visible ) + return false; + if( !m_UpToDate ) + Update(); + + if( OpenHier(&m_VarRoot, _Var) ) + { + if( !m_UpToDate ) + Update(); + int l = LineInHier(&m_VarRoot, _Var); + if( l>=0 ) + { + int NbLines = (m_VarY1-m_VarY0+1)/(m_Font->m_CharHeight+m_Sep); + if( NbLines<= 0 ) + NbLines = 1; + if( l=m_FirstLine+NbLines ) + { + m_FirstLine = l-NbLines/2; + if( m_FirstLine<0 ) + m_FirstLine = 0; + NotUpToDate(); + Update(); + if( m_NbDisplayedLinesm_Vars.size(); ++i) + if( _Root->m_Vars[i]!=NULL ) + { + if( _Var==_Root->m_Vars[i] + || (_Root->m_Vars[i]->IsGroup() && OpenHier(static_cast(_Root->m_Vars[i]), _Var)) ) + { + _Root->m_Open = true; + NotUpToDate(); + return true; + } + } + return false; +} + +// --------------------------------------------------------------------------- + +int CTwBar::LineInHier(CTwVarGroup *_Root, CTwVar *_Var) +{ + assert( _Root!=NULL ); + int l = 0; + for(size_t i=0; i<_Root->m_Vars.size(); ++i) + if( _Root->m_Vars[i]!=NULL && _Root->m_Vars[i]->m_Visible ) + { + if( _Var==_Root->m_Vars[i] ) + return l; + else if( _Root->m_Vars[i]->IsGroup() && static_cast(_Root->m_Vars[i])->m_Open ) + { + ++l; + int ll = LineInHier(static_cast(_Root->m_Vars[i]), _Var); + if( ll>=0 ) + return l+ll; + else + l += -ll-2; + } + ++l; + } + return -l-1; +} + +// --------------------------------------------------------------------------- + +static void DrawArc(int _X, int _Y, int _Radius, float _StartAngleDeg, float _EndAngleDeg, color32 _Color) // angles in degree +{ + ITwGraph *Gr = g_TwMgr->m_Graph; + if( Gr==NULL || !Gr->IsDrawing() || _Radius==0 || _StartAngleDeg==_EndAngleDeg ) + return; + + float startAngle = (float)M_PI*_StartAngleDeg/180; + float endAngle = (float)M_PI*_EndAngleDeg/180; + float stepAngle = 8/(float)_Radius; // segment length = 8 pixels + if( stepAngle>(float)M_PI/4 ) + stepAngle = (float)M_PI/4; + bool fullCircle = fabsf(endAngle-startAngle)>=2.0f*(float)M_PI+fabsf(stepAngle); + int numSteps; + if( fullCircle ) + { + numSteps = int((2.0f*(float)M_PI)/stepAngle); + startAngle = 0; + endAngle = 2.0f*(float)M_PI; + } + else + numSteps = int(fabsf(endAngle-startAngle)/stepAngle); + if( startAngle>endAngle ) + stepAngle = -stepAngle; + + int x0 = int(_X + _Radius * cosf(startAngle) + 0.5f); + int y0 = int(_Y - _Radius * sinf(startAngle) + 0.5f); + int x1, y1; + float angle = startAngle+stepAngle; + + for( int i=0; iDrawLine(x0, y0, x1, y1, _Color, true); + x0 = x1; + y0 = y1; + } + + if( fullCircle ) + { + x1 = int(_X + _Radius * cosf(startAngle) + 0.5f); + y1 = int(_Y - _Radius * sinf(startAngle) + 0.5f); + } + else + { + x1 = int(_X + _Radius * cosf(endAngle) + 0.5f); + y1 = int(_Y - _Radius * sinf(endAngle) + 0.5f); + } + Gr->DrawLine(x0, y0, x1, y1, _Color, true); +} + +// --------------------------------------------------------------------------- + +CTwBar::CRotoSlider::CRotoSlider() +{ + m_Var = NULL; + m_Active = false; + m_ActiveMiddle = false; + m_Subdiv = 256; // will be recalculate in RotoOnLButtonDown +} + +void CTwBar::RotoDraw() +{ + ITwGraph *Gr = g_TwMgr->m_Graph; + if( Gr==NULL || !Gr->IsDrawing() ) + return; + + if( m_Roto.m_Active ) + { + DrawArc(m_Roto.m_Origin.x, m_Roto.m_Origin.y, 32, 0, 360, m_ColRoto); + DrawArc(m_Roto.m_Origin.x+1, m_Roto.m_Origin.y, 32, 0, 360, m_ColRoto); + DrawArc(m_Roto.m_Origin.x, m_Roto.m_Origin.y+1, 32, 0, 360, m_ColRoto); + + if( m_Roto.m_HasPrevious ) + { + double varMax = RotoGetMax(); + double varMin = RotoGetMin(); + double varStep = RotoGetStep(); + if( varMax-DOUBLE_MAX && fabs(varStep)>DOUBLE_EPS && m_Roto.m_Subdiv>0 ) + { + double dtMax = 360.0*(varMax-m_Roto.m_ValueAngle0)/((double)m_Roto.m_Subdiv*varStep);//+2; + double dtMin = 360.0*(varMin-m_Roto.m_ValueAngle0)/((double)m_Roto.m_Subdiv*varStep);//-2; + + if( dtMax>=0 && dtMax<360 && dtMin<=0 && dtMin>-360 && fabs(dtMax-dtMin)<=360 ) + { + int x1, y1, x2, y2; + double da = 2.0*M_PI/m_Roto.m_Subdiv; + + x1 = m_Roto.m_Origin.x + (int)(40*cos(-M_PI*(m_Roto.m_Angle0+dtMax)/180-da)); + y1 = m_Roto.m_Origin.y + (int)(40*sin(-M_PI*(m_Roto.m_Angle0+dtMax)/180-da)+0.5); + x2 = m_Roto.m_Origin.x + (int)(40*cos(-M_PI*(m_Roto.m_Angle0+dtMax-10)/180-da)); + y2 = m_Roto.m_Origin.y + (int)(40*sin(-M_PI*(m_Roto.m_Angle0+dtMax-10)/180-da)+0.5); + Gr->DrawLine(m_Roto.m_Origin.x, m_Roto.m_Origin.y, x1, y1, m_ColRotoBound, true); + Gr->DrawLine(m_Roto.m_Origin.x+1, m_Roto.m_Origin.y, x1+1, y1, m_ColRotoBound, true); + Gr->DrawLine(m_Roto.m_Origin.x, m_Roto.m_Origin.y+1, x1, y1+1, m_ColRotoBound, true); + Gr->DrawLine(x1, y1, x2, y2, m_ColRotoBound, true); + Gr->DrawLine(x1+1, y1, x2+1, y2, m_ColRotoBound, true); + Gr->DrawLine(x1, y1+1, x2, y2+1, m_ColRotoBound, true); + + x1 = m_Roto.m_Origin.x + (int)(40*cos(-M_PI*(m_Roto.m_Angle0+dtMin)/180+da)); + y1 = m_Roto.m_Origin.y + (int)(40*sin(-M_PI*(m_Roto.m_Angle0+dtMin)/180+da)+0.5); + x2 = m_Roto.m_Origin.x + (int)(40*cos(-M_PI*(m_Roto.m_Angle0+dtMin+10)/180+da)); + y2 = m_Roto.m_Origin.y + (int)(40*sin(-M_PI*(m_Roto.m_Angle0+dtMin+10)/180+da)+0.5); + Gr->DrawLine(m_Roto.m_Origin.x, m_Roto.m_Origin.y, x1, y1, m_ColRotoBound, true); + Gr->DrawLine(m_Roto.m_Origin.x+1, m_Roto.m_Origin.y, x1+1, y1, m_ColRotoBound, true); + Gr->DrawLine(m_Roto.m_Origin.x, m_Roto.m_Origin.y+1, x1, y1+1, m_ColRotoBound, true); + Gr->DrawLine(x1, y1, x2, y2, m_ColRotoBound, true); + Gr->DrawLine(x1+1, y1, x2+1, y2, m_ColRotoBound, true); + Gr->DrawLine(x1, y1+1, x2, y2+1, m_ColRotoBound, true); + } + } + } + + Gr->DrawLine(m_Roto.m_Origin.x+1, m_Roto.m_Origin.y, m_Roto.m_Current.x+1, m_Roto.m_Current.y, m_ColRotoVal, true); + Gr->DrawLine(m_Roto.m_Origin.x, m_Roto.m_Origin.y+1, m_Roto.m_Current.x, m_Roto.m_Current.y+1, m_ColRotoVal, true); + Gr->DrawLine(m_Roto.m_Origin.x, m_Roto.m_Origin.y, m_Roto.m_Current.x, m_Roto.m_Current.y, m_ColRotoVal, true); + + if( fabs(m_Roto.m_AngleDT)>=1 ) + { + DrawArc(m_Roto.m_Origin.x, m_Roto.m_Origin.y, 32, float(m_Roto.m_Angle0), float(m_Roto.m_Angle0+m_Roto.m_AngleDT-1), m_ColRotoVal); + DrawArc(m_Roto.m_Origin.x+1, m_Roto.m_Origin.y, 32, float(m_Roto.m_Angle0), float(m_Roto.m_Angle0+m_Roto.m_AngleDT-1), m_ColRotoVal); + DrawArc(m_Roto.m_Origin.x, m_Roto.m_Origin.y+1, 32, float(m_Roto.m_Angle0), float(m_Roto.m_Angle0+m_Roto.m_AngleDT-1), m_ColRotoVal); + } + } +} + +double CTwBar::RotoGetValue() const +{ + assert(m_Roto.m_Var!=NULL); + return m_Roto.m_Var->ValueToDouble(); +} + +void CTwBar::RotoSetValue(double _Val) +{ + assert(m_Roto.m_Var!=NULL); + if( _Val!=m_Roto.m_CurrentValue ) + { + m_Roto.m_CurrentValue = _Val; + m_Roto.m_Var->ValueFromDouble(_Val); + NotUpToDate(); + } +} + +double CTwBar::RotoGetMin() const +{ + assert(m_Roto.m_Var!=NULL); + double min = -DOUBLE_MAX; + m_Roto.m_Var->MinMaxStepToDouble(&min, NULL, NULL); + return min; +} + +double CTwBar::RotoGetMax() const +{ + assert(m_Roto.m_Var!=NULL); + double max = DOUBLE_MAX; + m_Roto.m_Var->MinMaxStepToDouble(NULL, &max, NULL); + return max; +} + +double CTwBar::RotoGetStep() const +{ + assert(m_Roto.m_Var!=NULL); + double step = 1; + m_Roto.m_Var->MinMaxStepToDouble(NULL, NULL, &step); + return step; +} + +double CTwBar::RotoGetSteppedValue() const +{ + double d = m_Roto.m_PreciseValue-m_Roto.m_Value0; + double n = int(d/RotoGetStep()); + return m_Roto.m_Value0 + RotoGetStep()*n; +} + +void CTwBar::RotoOnMouseMove(int _X, int _Y) +{ + CPoint p(_X, _Y); + if( m_Roto.m_Active ) + { + m_Roto.m_Current = p; + RotoSetValue(RotoGetSteppedValue()); + //DrawManip(); + + int ti = -1; + double t = 0; + float r = sqrtf(float( (m_Roto.m_Current.x-m_Roto.m_Origin.x)*(m_Roto.m_Current.x-m_Roto.m_Origin.x) + + (m_Roto.m_Current.y-m_Roto.m_Origin.y)*(m_Roto.m_Current.y-m_Roto.m_Origin.y))); + if( r>m_RotoMinRadius ) + { + t = - atan2(double(m_Roto.m_Current.y-m_Roto.m_Origin.y), double(m_Roto.m_Current.x-m_Roto.m_Origin.x)); + ti = (int((t/(2.0*M_PI)+1.0)*NB_ROTO_CURSORS+0.5)) % NB_ROTO_CURSORS; + if( m_Roto.m_HasPrevious ) + { + CPoint v0 = m_Roto.m_Previous-m_Roto.m_Origin; + CPoint v1 = m_Roto.m_Current-m_Roto.m_Origin; + double l0 = sqrt(double(v0.x*v0.x+v0.y*v0.y)); + double l1 = sqrt(double(v1.x*v1.x+v1.y*v1.y)); + double dt = acos(max(-1+1.0e-30,min(1-1.0e-30,double(v0.x*v1.x+v0.y*v1.y)/(l0*l1)))); + if( v0.x*v1.y-v0.y*v1.x>0 ) + dt = - dt; + double preciseInc = double(m_Roto.m_Subdiv) * dt/(2.0*M_PI) * RotoGetStep(); + if( preciseInc>RotoGetStep() || preciseInc<-RotoGetStep() ) + { + m_Roto.m_PreciseValue += preciseInc; + if( m_Roto.m_PreciseValue>RotoGetMax() ) + { + m_Roto.m_PreciseValue = RotoGetMax(); + m_Roto.m_Value0 = RotoGetMax(); + + double da = 360*(RotoGetMax()-m_Roto.m_ValueAngle0)/(double(m_Roto.m_Subdiv)*RotoGetStep()); + m_Roto.m_Angle0 = ((int((t/(2.0*M_PI)+1.0)*360.0+0.5)) % 360) - da; + m_Roto.m_AngleDT = da; + } + else if( m_Roto.m_PreciseValue=0 && ti=0 && m_HighlightedLine<(int)m_HierTags.size() && m_HierTags[m_HighlightedLine].m_Var && !m_HierTags[m_HighlightedLine].m_Var->IsGroup() ) + { + m_Roto.m_Var = static_cast(m_HierTags[m_HighlightedLine].m_Var); + int y = m_PosY + m_VarY0 + m_HighlightedLine*(m_Font->m_CharHeight+m_Sep) + m_Font->m_CharHeight/2; + m_Roto.m_Origin = CPoint(p.x, y); //r.CenterPoint().y); + m_Roto.m_Current = p; + m_Roto.m_Active = true; + m_Roto.m_HasPrevious = false; + m_Roto.m_Angle0 = 0; + m_Roto.m_AngleDT = 0; + //SetCapture(); + + m_Roto.m_Value0 = RotoGetValue(); + m_Roto.m_CurrentValue = m_Roto.m_Value0; + m_Roto.m_ValueAngle0 = m_Roto.m_Value0; + m_Roto.m_PreciseValue = m_Roto.m_Value0; + //RotoSetValue(RotoGetSteppedValue()); Not here + //DrawManip(); + + m_Roto.m_Subdiv = m_RotoNbSubdiv; + // re-adjust m_Subdiv if needed: + double min=-DOUBLE_MAX, max=DOUBLE_MAX, step=1; + m_Roto.m_Var->MinMaxStepToDouble(&min, &max, &step); + if( fabs(step)>0 && min>-DOUBLE_MAX && maxRedrawWindow(); + } +} + +void CTwBar::RotoOnMButtonDown(int _X, int _Y) +{ + if( !m_Roto.m_Active ) + { + m_Roto.m_ActiveMiddle = true; + RotoOnLButtonDown(_X, _Y); + } +} + +void CTwBar::RotoOnMButtonUp(int _X, int _Y) +{ + if( m_Roto.m_ActiveMiddle ) + { + m_Roto.m_ActiveMiddle = false; + RotoOnLButtonUp(_X, _Y); + } +} + + diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwBar.h b/Extras/CDTestFramework/AntTweakBar/src/TwBar.h new file mode 100644 index 0000000..bef32ce --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwBar.h @@ -0,0 +1,337 @@ +// --------------------------------------------------------------------------- +// +// @file TwBar.h +// @brief Tweak bar manager. +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// notes: Private header +// TAB=4 +// +// --------------------------------------------------------------------------- + + +#if !defined ANT_TW_BAR_INCLUDED +#define ANT_TW_BAR_INCLUDED + +#include +#include "TwColors.h" + +#define ANT_TWEAK_BAR_DLL "AntTweakBar" + + +// --------------------------------------------------------------------------- + +struct CTwVar +{ + std::string m_Name; + std::string m_Label; + std::string m_Help; + bool m_IsRoot; + bool m_DontClip; + bool m_Visible; + signed short m_LeftMargin; + signed short m_TopMargin; + color32 m_Color; + + virtual bool IsGroup() const = 0; + virtual const CTwVar * Find(const char *_Name, struct CTwVarGroup **_Parent, int *_Index) const = 0; + virtual int HasAttrib(const char *_Attrib, bool *_HasValue) const; + virtual int SetAttrib(int _AttribID, const char *_Value, TwBar *_Bar, struct CTwVarGroup *_VarParent, int _VarIndex); + virtual void SetReadOnly(bool _ReadOnly) = 0; + CTwVar() { m_IsRoot = false; m_DontClip = false; m_Visible = true; m_LeftMargin = 0; m_TopMargin = 0; m_Color = COLOR32_BLACK; } + virtual ~CTwVar() {} + + static size_t GetDataSize(TwType _Type); +}; + + +struct CTwVarAtom : CTwVar +{ + ETwType m_Type; + void * m_Ptr; + TwSetVarCallback m_SetCallback; + TwGetVarCallback m_GetCallback; + TwButtonCallback m_ButtonCallback; + void * m_ClientData; + bool m_ReadOnly; + bool m_NoSlider; + int m_KeyIncr[2]; // [0]=key_code [1]=modifiers + int m_KeyDecr[2]; // [0]=key_code [1]=modifiers + + template struct TVal + { + _T m_Min; + _T m_Max; + _T m_Step; + signed char m_Precision; + bool m_Hexa; + }; + union UVal + { + TVal m_Char; + TVal m_Int8; + TVal m_UInt8; + TVal m_Int16; + TValm_UInt16; + TVal m_Int32; + TVal m_UInt32; + TVal m_Float32; + TVal m_Float64; + struct CBoolVal + { + char * m_TrueString; + char * m_FalseString; + bool m_FreeTrueString; + bool m_FreeFalseString; + } m_Bool; + struct CEnumVal // empty -> enum entries are deduced from m_Type + { + //typedef std::map CEntries; + //CEntries * m_Entries; + } m_Enum; + struct CShortcutVal + { + int m_Incr[2]; + int m_Decr[2]; + } m_Shortcut; + struct CHelpStruct + { + int m_StructType; + } m_HelpStruct; + }; + UVal m_Val; + + virtual bool IsGroup() const { return false; } + virtual void ValueToString(std::string *_Str) const; + virtual double ValueToDouble() const; + virtual void ValueFromDouble(double _Val); + virtual void MinMaxStepToDouble(double *_Min, double *_Max, double *_Step) const; + virtual const CTwVar * Find(const char *_Name, struct CTwVarGroup **_Parent, int *_Index) const; + virtual int HasAttrib(const char *_Attrib, bool *_HasValue) const; + virtual int SetAttrib(int _AttribID, const char *_Value, TwBar *_Bar, struct CTwVarGroup *_VarParent, int _VarIndex); + virtual void Increment(int _Step); + virtual void SetDefaults(); + virtual void SetReadOnly(bool _ReadOnly) { if(_ReadOnly || m_SetCallback || m_Ptr) m_ReadOnly=_ReadOnly; } + //virtual int DefineEnum(const TwEnumVal *_EnumValues, unsigned int _NbValues); + CTwVarAtom(); + virtual ~CTwVarAtom(); +}; + + +struct CTwVarGroup : CTwVar +{ + std::vector m_Vars; + bool m_Open; + TwSummaryCallback m_SummaryCallback; + void * m_SummaryClientData; + void * m_StructValuePtr; + TwType m_StructType; + + virtual bool IsGroup() const { return true; } + virtual const CTwVar * Find(const char *_Name, CTwVarGroup **_Parent, int *_Index) const; + virtual int HasAttrib(const char *_Attrib, bool *_HasValue) const; + virtual int SetAttrib(int _AttribID, const char *_Value, TwBar *_Bar, struct CTwVarGroup *_VarParent, int _VarIndex); + virtual CTwVarAtom * FindShortcut(int _Key, int _Modifiers, bool *_DoIncr); + virtual void SetReadOnly(bool _ReadOnly) { for(size_t i=0; iSetReadOnly(_ReadOnly); } + CTwVarGroup() { m_Open=false; m_StructType=TW_TYPE_UNDEF; m_SummaryCallback=NULL; m_SummaryClientData=NULL; m_StructValuePtr=NULL; } + virtual ~CTwVarGroup(); +}; + +// --------------------------------------------------------------------------- + +struct CTwBar +{ + std::string m_Name; + std::string m_Label; + std::string m_Help; + bool m_Visible; + int m_PosX; + int m_PosY; + int m_Width; + int m_Height; + color32 m_Color; + const CTexFont * m_Font; + int m_ValuesWidth; + int m_Sep; + int m_FirstLine; + float m_UpdatePeriod; + bool m_IsHelpBar; + int m_MinNumber; // accessed by TwDeleteBar + bool m_IsPopupList; + CTwVarAtom * m_VarEnumLinkedToPopupList; + CTwBar * m_BarLinkedToPopupList; + + CTwVarGroup m_VarRoot; + + void NotUpToDate(); + void Draw(); + const CTwVar * Find(const char *_Name, CTwVarGroup **_Parent=NULL, int *_Index=NULL) const; + CTwVar * Find(const char *_Name, CTwVarGroup **_Parent=NULL, int *_Index=NULL); + int HasAttrib(const char *_Attrib, bool *_HasValue) const; + int SetAttrib(int _AttribID, const char *_Value); + bool MouseMotion(int _X, int _Y); + bool MouseButton(ETwMouseButtonID _Button, bool _Pressed, int _X, int _Y); + bool MouseWheel(int _Pos, int _PrevPos, int _MouseX, int _MouseY); + bool KeyPressed(int _Key, int _Modifiers); + bool IsMinimized() const { return m_IsMinimized; } + bool Show(CTwVar *_Var); // display the line associated to _Var + bool OpenHier(CTwVarGroup *_Root, CTwVar *_Var); // open a hierarchy if it contains _Var + int LineInHier(CTwVarGroup *_Root, CTwVar *_Var); // returns the number of the line associated to _Var + void UnHighlightLine() { m_HighlightedLine = -1; NotUpToDate(); } // used by PopupCallback + CTwBar(const char *_Name); + ~CTwBar(); + + color32 m_ColBg, m_ColBg1, m_ColBg2; + color32 m_ColHighBg; + color32 m_ColLabelText; + color32 m_ColStructText; + color32 m_ColValBg; + color32 m_ColValText; + color32 m_ColValTextRO; + color32 m_ColValMin; + color32 m_ColValMax; + color32 m_ColStructBg; + color32 m_ColTitleBg; + color32 m_ColTitleHighBg; + color32 m_ColTitleText; + color32 m_ColTitleShadow; + color32 m_ColLine; + color32 m_ColLineShadow; + color32 m_ColUnderline; + color32 m_ColBtn; + color32 m_ColHighBtn; + color32 m_ColGrpBg; + color32 m_ColGrpText; + color32 m_ColHierBg; + color32 m_ColShortcutText; + color32 m_ColShortcutBg; + color32 m_ColInfoText; + color32 m_ColHelpBg; + color32 m_ColHelpText; + color32 m_ColRoto; + color32 m_ColRotoVal; + color32 m_ColRotoBound; + void UpdateColors(); + +protected: + int m_TitleWidth; + int m_VarX0; + int m_VarX1; + int m_VarX2; + int m_VarY0; + int m_VarY1; + int m_VarY2; + int m_ScrollYW; + int m_ScrollYH; + int m_ScrollY0; + int m_ScrollY1; + int m_NbHierLines; + int m_NbDisplayedLines; + bool m_UpToDate; + float m_LastUpdateTime; + void Update(); + + bool m_MouseDrag; + bool m_MouseDragVar; + bool m_MouseDragTitle; + bool m_MouseDragScroll; + bool m_MouseDragResizeUR; + bool m_MouseDragResizeUL; + bool m_MouseDragResizeLR; + bool m_MouseDragResizeLL; + bool m_MouseDragValWidth; + int m_MouseOriginX; + int m_MouseOriginY; + bool m_VarHasBeenIncr; + int m_FirstLine0; + int m_HighlightedLine; + int m_HighlightedLinePrev; + bool m_HighlightIncrBtn; + bool m_HighlightDecrBtn; + bool m_HighlightClickBtn; + bool m_HighlightTitle; + bool m_HighlightScroll; + bool m_HighlightUpScroll; + bool m_HighlightDnScroll; + bool m_HighlightMinimize; + bool m_HighlightFont; + bool m_HighlightValWidth; + bool m_DrawHandles; + + bool m_IsMinimized; + int m_MinPosX; + int m_MinPosY; + bool m_HighlightMaximize; + bool m_DrawIncrDecrBtn; + bool m_DrawClickBtn; + + struct CHierTag + { + CTwVar * m_Var; + int m_Level; + bool m_Closing; + }; + std::vector m_HierTags; + void BrowseHierarchy(int *_LineNum, int _CurrLevel, const CTwVar *_Var, int _First, int _Last); + void * m_TitleTextObj; + void * m_LabelsTextObj; + void * m_ValuesTextObj; + void * m_ShortcutTextObj; + int m_ShortcutLine; + void ListLabels(std::vector& _Labels, std::vector& _Colors, const CTexFont *_Font, int _AtomWidthMax, int _GroupWidthMax); + void ListValues(std::vector& _Values, std::vector& _Colors, std::vector& _BgColors, const CTexFont *_Font, int _WidthMax); + void DrawHierHandle(); + + // RotoSlider + struct CPoint + { + int x, y; + CPoint() {} + CPoint(int _X, int _Y):x(_X), y(_Y) {} + const CPoint operator+ (const CPoint& p) const { return CPoint(x+p.x, y+p.y); } + const CPoint operator- (const CPoint& p) const { return CPoint(x-p.x, y-p.y); } + }; + struct CRotoSlider + { + CRotoSlider(); + CTwVarAtom * m_Var; + double m_PreciseValue; + double m_CurrentValue; + double m_Value0; + double m_ValueAngle0; + bool m_Active; + bool m_ActiveMiddle; + CPoint m_Origin; + CPoint m_Current; + bool m_HasPrevious; + CPoint m_Previous; + double m_Angle0; + double m_AngleDT; + int m_Subdiv; + }; + CRotoSlider m_Roto; + int m_RotoMinRadius; + int m_RotoNbSubdiv; // number of steps for one turn + void RotoDraw(); + void RotoOnMouseMove(int _X, int _Y); + void RotoOnLButtonDown(int _X, int _Y); + void RotoOnLButtonUp(int _X, int _Y); + void RotoOnMButtonDown(int _X, int _Y); + void RotoOnMButtonUp(int _X, int _Y); + double RotoGetValue() const; + void RotoSetValue(double _Val); + double RotoGetMin() const; + double RotoGetMax() const; + double RotoGetStep() const; + double RotoGetSteppedValue() const; + + friend struct CTwMgr; +}; + +// --------------------------------------------------------------------------- + + +#endif // !defined ANT_TW_BAR_INCLUDED diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwColors.cpp b/Extras/CDTestFramework/AntTweakBar/src/TwColors.cpp new file mode 100644 index 0000000..1fd9dd1 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwColors.cpp @@ -0,0 +1,161 @@ +// --------------------------------------------------------------------------- +// +// @file TwColors.cpp +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// note: TAB=4 +// +// --------------------------------------------------------------------------- + + +#include "TwPrecomp.h" + +#include "TwColors.h" + + +typedef float float32; +typedef int int32; + + +void ColorRGBToHLSf(float32 _R, float32 _G, float32 _B, float32 *_Hue, float32 *_Light, float32 *_Saturation) +{ + // Compute HLS from RGB. The r,g,b triplet is between [0,1], + // hue is between [0,360], light and saturation are [0,1]. + + float32 rnorm, gnorm, bnorm, minval, maxval, msum, mdiff, r, g, b; + r = g = b = 0; + if(_R>0) r = _R; if(r>1) r = 1; + if(_G>0) g = _G; if(g>1) g = 1; + if(_B>0) b = _B; if(b>1) b = 1; + + minval = r; + if(gmaxval) maxval = g; + if(b>maxval) maxval = b; + + rnorm = gnorm = bnorm = 0; + mdiff = maxval - minval; + msum = maxval + minval; + float32 l = 0.5f * msum; + if(_Light) + *_Light = l; + if(maxval!=minval) + { + rnorm = (maxval - r)/mdiff; + gnorm = (maxval - g)/mdiff; + bnorm = (maxval - b)/mdiff; + } + else + { + if(_Saturation) + *_Saturation = 0; + if(_Hue) + *_Hue = 0; + return; + } + + if(_Saturation) + { + if(l<0.5f) + *_Saturation = mdiff/msum; + else + *_Saturation = mdiff/(2.0f - msum); + } + + if(_Hue) + { + if(r==maxval) + *_Hue = 60.0f * (6.0f + bnorm - gnorm); + else if(g==maxval) + *_Hue = 60.0f * (2.0f + rnorm - bnorm); + else + *_Hue = 60.0f * (4.0f + gnorm - rnorm); + + if(*_Hue>360.0f) + *_Hue -= 360.0f; + } +} + + +void ColorRGBToHLSi(int32 _R, int32 _G, int32 _B, int32 *_Hue, int32 *_Light, int32 *_Saturation) +{ + float32 h, l, s; + ColorRGBToHLSf((1.0f/255.0f)*float32(_R), (1.0f/255.0f)*float32(_G), (1.0f/255.0f)*float32(_B), &h, &l, &s); + if(_Hue) *_Hue = (int32)TClamp(h*(256.0f/360.0f), 0.0f, 255.0f); + if(_Light) *_Light = (int32)TClamp(l*256.0f, 0.0f, 255.0f); + if(_Saturation) *_Saturation= (int32)TClamp(s*256.0f, 0.0f, 255.0f); +} + + +void ColorHLSToRGBf(float32 _Hue, float32 _Light, float32 _Saturation, float32 *_R, float32 *_G, float32 *_B) +{ + // Compute RGB from HLS. The light and saturation are between [0,1] + // and hue is between [0,360]. The returned r,g,b triplet is between [0,1]. + + // a local auxiliary function + struct CLocal + { + static float32 HLSToRGB(float32 _Rn1, float32 _Rn2, float32 _Huei) + { + float32 hue = _Huei; + if(hue>360) hue = hue - 360; + if(hue<0) hue = hue + 360; + if(hue<60 ) return _Rn1 + (_Rn2-_Rn1)*hue/60; + if(hue<180) return _Rn2; + if(hue<240) return _Rn1 + (_Rn2-_Rn1)*(240-hue)/60; + return _Rn1; + } + }; + + float32 rh, rl, rs, rm1, rm2; + rh = rl = rs = 0; + if(_Hue>0) rh = _Hue; if(rh>360) rh = 360; + if(_Light>0) rl = _Light; if(rl>1) rl = 1; + if(_Saturation>0) rs = _Saturation; if(rs>1) rs = 1; + + if(rl<=0.5f) + rm2 = rl*(1.0f + rs); + else + rm2 = rl + rs - rl*rs; + rm1 = 2.0f*rl - rm2; + + if(!rs) + { + if(_R) *_R = rl; + if(_G) *_G = rl; + if(_B) *_B = rl; + } + else + { + if(_R) *_R = CLocal::HLSToRGB(rm1, rm2, rh+120); + if(_G) *_G = CLocal::HLSToRGB(rm1, rm2, rh); + if(_B) *_B = CLocal::HLSToRGB(rm1, rm2, rh-120); + } +} + + +void ColorHLSToRGBi(int32 _Hue, int32 _Light, int32 _Saturation, int32 *_R, int32 *_G, int32 *_B) +{ + float32 r, g, b; + ColorHLSToRGBf((360.0f/255.0f)*float32(_Hue), (1.0f/255.0f)*float32(_Light), (1.0f/255.0f)*float32(_Saturation), &r, &g, &b); + if(_R) *_R = (int32)TClamp(r*256.0f, 0.0f, 255.0f); + if(_G) *_G = (int32)TClamp(g*256.0f, 0.0f, 255.0f); + if(_B) *_B = (int32)TClamp(b*256.0f, 0.0f, 255.0f); +} + + +color32 ColorBlend(color32 _Color1, color32 _Color2, float32 _S) +{ + float32 a1, r1, g1, b1, a2, r2, g2, b2; + Color32ToARGBf(_Color1, &a1, &r1, &g1, &b1); + Color32ToARGBf(_Color2, &a2, &r2, &g2, &b2); + float32 t = 1.0f-_S; + return Color32FromARGBf(t*a1+_S*a2, t*r1+_S*r2, t*g1+_S*g2, t*b1+_S*b2); +} + + diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwColors.h b/Extras/CDTestFramework/AntTweakBar/src/TwColors.h new file mode 100644 index 0000000..48aca54 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwColors.h @@ -0,0 +1,81 @@ +// --------------------------------------------------------------------------- +// +// @file TwColors.h +// @brief Color conversions +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// notes: Private header +// TAB=4 +// +// --------------------------------------------------------------------------- + + +#if !defined ANT_TW_COLORS_INCLUDED +#define ANT_TW_COLORS_INCLUDED + + +// --------------------------------------------------------------------------- + + +typedef unsigned int color32; + + +const color32 COLOR32_BLACK = 0xff000000; ///< Black color +const color32 COLOR32_WHITE = 0xffffffff; ///< White color +const color32 COLOR32_RED = 0xffff0000; ///< Red color +const color32 COLOR32_GREEN = 0xff00ff00; ///< Green color +const color32 COLOR32_BLUE = 0xff0000ff; ///< Blue color + + +template inline const _T& TClamp(const _T& _X, const _T& _Limit1, const _T& _Limit2) +{ + if( _Limit1<_Limit2 ) + return (_X<=_Limit1) ? _Limit1 : ( (_X>=_Limit2) ? _Limit2 : _X ); + else + return (_X<=_Limit2) ? _Limit2 : ( (_X>=_Limit1) ? _Limit1 : _X ); +} + +inline color32 Color32FromARGBi(int _A, int _R, int _G, int _B) +{ + return (((color32)TClamp(_A, 0, 255))<<24) | (((color32)TClamp(_R, 0, 255))<<16) | (((color32)TClamp(_G, 0, 255))<<8) | ((color32)TClamp(_B, 0, 255)); +} + +inline color32 Color32FromARGBf(float _A, float _R, float _G, float _B) +{ + return (((color32)TClamp(_A*256.0f, 0.0f, 255.0f))<<24) | (((color32)TClamp(_R*256.0f, 0.0f, 255.0f))<<16) | (((color32)TClamp(_G*256.0f, 0.0f, 255.0f))<<8) | ((color32)TClamp(_B*256.0f, 0.0f, 255.0f)); +} + +inline void Color32ToARGBi(color32 _Color, int *_A, int *_R, int *_G, int *_B) +{ + if(_A) *_A = (_Color>>24)&0xff; + if(_R) *_R = (_Color>>16)&0xff; + if(_G) *_G = (_Color>>8)&0xff; + if(_B) *_B = _Color&0xff; +} + +inline void Color32ToARGBf(color32 _Color, float *_A, float *_R, float *_G, float *_B) +{ + if(_A) *_A = (1.0f/255.0f)*float((_Color>>24)&0xff); + if(_R) *_R = (1.0f/255.0f)*float((_Color>>16)&0xff); + if(_G) *_G = (1.0f/255.0f)*float((_Color>>8)&0xff); + if(_B) *_B = (1.0f/255.0f)*float(_Color&0xff); +} + +void ColorRGBToHLSf(float _R, float _G, float _B, float *_Hue, float *_Light, float *_Saturation); + +void ColorRGBToHLSi(int _R, int _G, int _B, int *_Hue, int *_Light, int *_Saturation); + +void ColorHLSToRGBf(float _Hue, float _Light, float _Saturation, float *_R, float *_G, float *_B); + +void ColorHLSToRGBi(int _Hue, int _Light, int _Saturation, int *_R, int *_G, int *_B); + +color32 ColorBlend(color32 _Color1, color32 _Color2, float _S); + + +// --------------------------------------------------------------------------- + + +#endif // !defined ANT_TW_COLORS_INCLUDED diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwDirect3D9.cpp b/Extras/CDTestFramework/AntTweakBar/src/TwDirect3D9.cpp new file mode 100644 index 0000000..6188bcc --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwDirect3D9.cpp @@ -0,0 +1,674 @@ +// --------------------------------------------------------------------------- +// +// @file TwDirect3D9.cpp +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// note: TAB=4 +// +// --------------------------------------------------------------------------- + + +#include "TwPrecomp.h" +#include "TwDirect3D9.h" +#include "TwMgr.h" + +#include +#ifdef _DEBUG + #include + #pragma comment(lib, "dxerr9") +#endif // _DEBUG + + +using namespace std; + +const char *g_ErrCantLoadD3D9 = "Cannot load Direct3D9 library dynamically"; +const char *g_ErrCantUnloadD3D9 = "Cannot unload Direct3D9 library"; + + +// --------------------------------------------------------------------------- + +static IDirect3DTexture9 *BindFont(IDirect3DDevice9 *_Dev, const CTexFont *_Font) +{ + assert(_Font!=NULL); + + IDirect3DTexture9 *Tex = NULL; + HRESULT hr = _Dev->CreateTexture(_Font->m_TexWidth, _Font->m_TexHeight, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &Tex, NULL); + if( FAILED(hr) ) + return NULL; + + D3DLOCKED_RECT r; + hr = Tex->LockRect(0, &r, NULL, 0); + if( SUCCEEDED(hr) ) + { + color32 *p = static_cast(r.pBits); + for( int i=0; i<_Font->m_TexWidth*_Font->m_TexHeight; ++i, ++p ) + *p = 0x00ffffff | (((color32)(_Font->m_TexBytes[i]))<<24); + Tex->UnlockRect(0); + } + return Tex; +} + +// --------------------------------------------------------------------------- + +static void UnbindFont(IDirect3DDevice9 *_Dev, IDirect3DTexture9 *_Tex) +{ + (void)_Dev; + + if( _Tex ) + _Tex->Release(); +} + +// --------------------------------------------------------------------------- + +struct CState +{ + // viewport + D3DVIEWPORT9 m_Vp; + + // render states + DWORD m_Z; + DWORD m_CullMode; + DWORD m_AlphaTest; + DWORD m_AlphaBlend; + DWORD m_BlendOp; + DWORD m_SrcBlend; + DWORD m_DstBlend; + DWORD m_ClipPlane; + DWORD m_FillMode; + DWORD m_LastPixel; + DWORD m_Fog; + DWORD m_Stencil; + DWORD m_ColorWrite; + DWORD m_Scissor; + DWORD m_SeparateAlphaBlend; + DWORD m_AntiAliasedLine; + + // primitive + DWORD m_FVF; + IDirect3DVertexBuffer9 *m_StreamData; + IDirect3DVertexShader9 *m_VertexShader; + UINT m_StreamOffset; + UINT m_StreamStride; + + // texture + IDirect3DBaseTexture9 *m_Tex; + IDirect3DPixelShader9 *m_PixelShader; + + // texture stage states + DWORD m_ColorOp; + DWORD m_ColorArg1; + DWORD m_ColorArg2; + DWORD m_AlphaOp; + DWORD m_AlphaArg1; + DWORD m_TexCoordIndex; + DWORD m_TexTransfFlags; + DWORD m_AddressU; + DWORD m_AddressV; + DWORD m_MinFilter; + DWORD m_MagFilter; + DWORD m_MipFilter; + + // DeviceCaps (filled by constructor) + D3DCAPS9 m_Caps; + + void Save(); + void Restore(); + CState(IDirect3DDevice9 *_Dev); +private: + IDirect3DDevice9 *m_D3DDev; +}; + +CState::CState(IDirect3DDevice9 *_Dev) +{ + ZeroMemory(this, sizeof(CState)); + m_D3DDev = _Dev; + + m_D3DDev->GetDeviceCaps(&m_Caps); +} + +void CState::Save() +{ + // viewport + m_D3DDev->GetViewport(&m_Vp); + + // render states + m_D3DDev->GetRenderState(D3DRS_ZENABLE, &m_Z); + m_D3DDev->GetRenderState(D3DRS_CULLMODE, &m_CullMode); + m_D3DDev->GetRenderState(D3DRS_ALPHATESTENABLE, &m_AlphaTest); + m_D3DDev->GetRenderState(D3DRS_ALPHABLENDENABLE, &m_AlphaBlend); + m_D3DDev->GetRenderState(D3DRS_BLENDOP, &m_BlendOp); + m_D3DDev->GetRenderState(D3DRS_SRCBLEND, &m_SrcBlend); + m_D3DDev->GetRenderState(D3DRS_DESTBLEND, &m_DstBlend); + m_D3DDev->GetRenderState(D3DRS_CLIPPLANEENABLE, &m_ClipPlane); + m_D3DDev->GetRenderState(D3DRS_FILLMODE, &m_FillMode); + m_D3DDev->GetRenderState(D3DRS_LASTPIXEL, &m_LastPixel); + m_D3DDev->GetRenderState(D3DRS_FOGENABLE, &m_Fog); + m_D3DDev->GetRenderState(D3DRS_STENCILENABLE, &m_Stencil); + m_D3DDev->GetRenderState(D3DRS_COLORWRITEENABLE, &m_ColorWrite); + m_D3DDev->GetRenderState(D3DRS_SCISSORTESTENABLE, &m_Scissor); + if( m_Caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND ) + m_D3DDev->GetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, &m_SeparateAlphaBlend); + //if( m_Caps.LineCaps & D3DLINECAPS_ANTIALIAS ) + m_D3DDev->GetRenderState(D3DRS_ANTIALIASEDLINEENABLE, &m_AntiAliasedLine); + + // primitive + m_D3DDev->GetFVF(&m_FVF); + m_D3DDev->GetStreamSource(0, &m_StreamData, &m_StreamOffset, &m_StreamStride); + m_D3DDev->GetVertexShader(&m_VertexShader); + + // texture + m_D3DDev->GetTexture(0, &m_Tex); + m_D3DDev->GetPixelShader(&m_PixelShader); + + // texture stage states + m_D3DDev->GetTextureStageState(0, D3DTSS_COLOROP, &m_ColorOp); + m_D3DDev->GetTextureStageState(0, D3DTSS_COLORARG1, &m_ColorArg1); + m_D3DDev->GetTextureStageState(0, D3DTSS_COLORARG2, &m_ColorArg2); + m_D3DDev->GetTextureStageState(0, D3DTSS_ALPHAOP, &m_AlphaOp); + m_D3DDev->GetTextureStageState(0, D3DTSS_ALPHAARG1, &m_AlphaArg1); + m_D3DDev->GetTextureStageState(0, D3DTSS_TEXCOORDINDEX, &m_TexCoordIndex); + m_D3DDev->GetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, &m_TexTransfFlags); + m_D3DDev->GetSamplerState(0, D3DSAMP_ADDRESSU, &m_AddressU); + m_D3DDev->GetSamplerState(0, D3DSAMP_ADDRESSV, &m_AddressV); + m_D3DDev->GetSamplerState(0, D3DSAMP_MAGFILTER, &m_MagFilter); + m_D3DDev->GetSamplerState(0, D3DSAMP_MINFILTER, &m_MinFilter); + m_D3DDev->GetSamplerState(0, D3DSAMP_MIPFILTER, &m_MipFilter); +} + +void CState::Restore() +{ + // viewport + m_D3DDev->SetViewport(&m_Vp); + + // render states + m_D3DDev->SetRenderState(D3DRS_ZENABLE, m_Z); + m_D3DDev->SetRenderState(D3DRS_CULLMODE, m_CullMode); + m_D3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, m_AlphaTest); + m_D3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, m_AlphaBlend); + m_D3DDev->SetRenderState(D3DRS_BLENDOP, m_BlendOp); + m_D3DDev->SetRenderState(D3DRS_SRCBLEND, m_SrcBlend); + m_D3DDev->SetRenderState(D3DRS_DESTBLEND, m_DstBlend); + m_D3DDev->SetRenderState(D3DRS_CLIPPLANEENABLE, m_ClipPlane); + m_D3DDev->SetRenderState(D3DRS_FILLMODE, m_FillMode); + m_D3DDev->SetRenderState(D3DRS_LASTPIXEL, m_LastPixel); + m_D3DDev->SetRenderState(D3DRS_FOGENABLE, m_Fog); + m_D3DDev->SetRenderState(D3DRS_STENCILENABLE, m_Stencil); + m_D3DDev->SetRenderState(D3DRS_COLORWRITEENABLE, m_ColorWrite); + m_D3DDev->SetRenderState(D3DRS_SCISSORTESTENABLE, m_Scissor); + if( m_Caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND ) + m_D3DDev->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, m_SeparateAlphaBlend); + //if( m_Caps.LineCaps & D3DLINECAPS_ANTIALIAS ) + m_D3DDev->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, m_AntiAliasedLine); + + // primitive + m_D3DDev->SetFVF(m_FVF); + m_D3DDev->SetStreamSource(0, m_StreamData, m_StreamOffset, m_StreamStride); + if( m_StreamData ) + m_StreamData->Release(); + m_D3DDev->SetVertexShader(m_VertexShader); + if( m_VertexShader ) + m_VertexShader->Release(); + + // texture + m_D3DDev->SetTexture(0, m_Tex); + if( m_Tex ) + m_Tex->Release(); + m_D3DDev->SetPixelShader(m_PixelShader); + if( m_PixelShader ) + m_PixelShader->Release(); + + // texture stage states + m_D3DDev->SetTextureStageState(0, D3DTSS_COLOROP, m_ColorOp); + m_D3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, m_ColorArg1); + m_D3DDev->SetTextureStageState(0, D3DTSS_COLORARG2, m_ColorArg2); + m_D3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP, m_AlphaOp); + m_D3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, m_AlphaArg1); + m_D3DDev->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, m_TexCoordIndex); + m_D3DDev->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, m_TexTransfFlags); + m_D3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, m_AddressU); + m_D3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, m_AddressV); + m_D3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, m_MagFilter); + m_D3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, m_MinFilter); + m_D3DDev->SetSamplerState(0, D3DSAMP_MIPFILTER, m_MipFilter); +} + +// --------------------------------------------------------------------------- + +int CTwGraphDirect3D9::Init() +{ + assert(g_TwMgr->m_Device!=NULL); + + m_D3DDev = static_cast(g_TwMgr->m_Device); + m_Drawing = false; + m_FontTex = NULL; + m_FontD3DTex = NULL; + D3DDEVICE_CREATION_PARAMETERS cp; + m_D3DDev->GetCreationParameters(&cp); + m_PureDevice = ( cp.BehaviorFlags & D3DCREATE_PUREDEVICE ) ? true : false; + m_WndWidth = 0; + m_WndHeight = 0; + m_State = new CState(m_D3DDev); + + return 1; +} + +// --------------------------------------------------------------------------- + +int CTwGraphDirect3D9::Shut() +{ + assert(m_Drawing==false); + + UnbindFont(m_D3DDev, m_FontD3DTex); + m_FontD3DTex = NULL; + delete m_State; + m_State = NULL; + m_D3DDev = NULL; + + return 1; +} + +// --------------------------------------------------------------------------- + +void CTwGraphDirect3D9::BeginDraw(int _WndWidth, int _WndHeight) +{ + assert(m_Drawing==false && _WndWidth>0 && _WndHeight>0); + m_Drawing = true; + + m_WndWidth = _WndWidth; + m_WndHeight = _WndHeight; + + // save context + if( !m_PureDevice ) + m_State->Save(); + + if( m_WndWidth>0 && m_WndHeight>0 ) + { + D3DVIEWPORT9 Vp; + Vp.X = 0; + Vp.Y = 0; + Vp.Width = m_WndWidth; + Vp.Height = m_WndHeight; + Vp.MinZ = 0; + Vp.MaxZ = 1; + m_D3DDev->SetViewport(&Vp); + + //D3DMATRIX Transfo = { 2.0f/_WndWidth,0,0,0, 0,2.0f/_WndHeight,0,0, 0,0,-1,0, 0,0,0,1 }; + //m_D3DDev->SetTransform(D3DTS_PROJECTION, &Transfo); + } + // const D3DMATRIX id = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 }; + // m_D3DDev->SetTransform(D3DTS_VIEW, &id); + // m_D3DDev->SetTransform(D3DTS_WORLD, &id); + // m_D3DDev->SetTransform(D3DTS_TEXTURE0, &id); + + m_D3DDev->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + m_D3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + m_D3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + m_D3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + m_D3DDev->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + m_D3DDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + m_D3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + m_D3DDev->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + m_D3DDev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + m_D3DDev->SetRenderState(D3DRS_LASTPIXEL, FALSE); + m_D3DDev->SetRenderState(D3DRS_FOGENABLE, FALSE); + m_D3DDev->SetRenderState(D3DRS_STENCILENABLE, FALSE); + m_D3DDev->SetRenderState(D3DRS_COLORWRITEENABLE, 0x0000000F); + m_D3DDev->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); + if( m_State->m_Caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND ) + m_D3DDev->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); + //if( m_State->m_Caps.LineCaps & D3DLINECAPS_ANTIALIAS ) + m_D3DDev->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, FALSE); + + m_D3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + m_D3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + m_D3DDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + m_D3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + m_D3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + m_D3DDev->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU); + m_D3DDev->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); + m_D3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + m_D3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + m_D3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + m_D3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + m_D3DDev->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); + + m_D3DDev->SetVertexShader(NULL); + m_D3DDev->SetPixelShader(NULL); +} + +// --------------------------------------------------------------------------- + +void CTwGraphDirect3D9::EndDraw() +{ + assert(m_Drawing==true); + m_Drawing = false; + + // restore context + if( !m_PureDevice ) + m_State->Restore(); + + /* + _glPolygonMode(GL_FRONT, m_PrevPolygonMode[0]); + _glPolygonMode(GL_BACK, m_PrevPolygonMode[1]); + _glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, m_PrevTexEnv); + _glLineWidth(m_PrevLineWidth); + _glMatrixMode(GL_PROJECTION); + _glPopMatrix(); + _glMatrixMode(GL_MODELVIEW); + _glPopMatrix(); + _glMatrixMode(GL_TEXTURE); + _glPopMatrix(); + _glPopClientAttrib(); + _glPopAttrib(); + */ +} + +// --------------------------------------------------------------------------- + +bool CTwGraphDirect3D9::IsDrawing() +{ + return m_Drawing; +} + +// --------------------------------------------------------------------------- + +void CTwGraphDirect3D9::Restore() +{ + + UnbindFont(m_D3DDev, m_FontD3DTex); + m_FontD3DTex = NULL; + + m_FontTex = NULL; +} + + +// --------------------------------------------------------------------------- + +void CTwGraphDirect3D9::DrawLine(int _X0, int _Y0, int _X1, int _Y1, color32 _Color0, color32 _Color1, bool _AntiAliased) +{ + assert(m_Drawing==true); + + struct CVtx + { + float m_Pos[4]; + DWORD m_Color; + }; + CVtx p[2]; + + p[0].m_Pos[0] = (float)_X0; + p[0].m_Pos[1] = (float)_Y0; + p[0].m_Pos[2] = 0; + p[0].m_Pos[3] = 0; + p[0].m_Color = _Color0; + + p[1].m_Pos[0] = (float)_X1; + p[1].m_Pos[1] = (float)_Y1; + p[1].m_Pos[2] = 0; + p[1].m_Pos[3] = 0; + p[1].m_Color = _Color1; + + //if( m_State->m_Caps.LineCaps & D3DLINECAPS_ANTIALIAS ) + m_D3DDev->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, (_AntiAliased ? TRUE : FALSE)); + m_D3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); + m_D3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + m_D3DDev->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE); + m_D3DDev->DrawPrimitiveUP(D3DPT_LINELIST, 1, p, sizeof(CVtx)); + //if( m_State->m_Caps.LineCaps & D3DLINECAPS_ANTIALIAS ) + m_D3DDev->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, FALSE); +} + +// --------------------------------------------------------------------------- + +void CTwGraphDirect3D9::DrawRect(int _X0, int _Y0, int _X1, int _Y1, color32 _Color00, color32 _Color10, color32 _Color01, color32 _Color11) +{ + assert(m_Drawing==true); + + // border adjustment + if(_X0<_X1) + ++_X1; + else if(_X0>_X1) + ++_X0; + if(_Y0<_Y1) + ++_Y1; + else if(_Y0>_Y1) + ++_Y0; + + struct CVtx + { + float m_Pos[4]; + DWORD m_Color; + }; + CVtx p[4]; + + p[0].m_Pos[0] = (float)_X1; + p[0].m_Pos[1] = (float)_Y0; + p[0].m_Pos[2] = 0; + p[0].m_Pos[3] = 1; + p[0].m_Color = _Color10; + + p[1].m_Pos[0] = (float)_X0; + p[1].m_Pos[1] = (float)_Y0; + p[1].m_Pos[2] = 0; + p[1].m_Pos[3] = 1; + p[1].m_Color = _Color00; + + p[2].m_Pos[0] = (float)_X1; + p[2].m_Pos[1] = (float)_Y1; + p[2].m_Pos[2] = 0; + p[2].m_Pos[3] = 1; + p[2].m_Color = _Color11; + + p[3].m_Pos[0] = (float)_X0; + p[3].m_Pos[1] = (float)_Y1; + p[3].m_Pos[2] = 0; + p[3].m_Pos[3] = 1; + p[3].m_Color = _Color01; + + m_D3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); + m_D3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + m_D3DDev->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE); + m_D3DDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, p, sizeof(CVtx)); +} + +// --------------------------------------------------------------------------- + +void *CTwGraphDirect3D9::NewTextObj() +{ + return new CTextObj; +} + +// --------------------------------------------------------------------------- + +void CTwGraphDirect3D9::DeleteTextObj(void *_TextObj) +{ + assert(_TextObj!=NULL); + delete static_cast(_TextObj); +} + +// --------------------------------------------------------------------------- + +void CTwGraphDirect3D9::BuildText(void *_TextObj, const std::string *_TextLines, color32 *_LineColors, color32 *_LineBgColors, int _NbLines, const CTexFont *_Font, int _Sep, int _BgWidth) +{ + assert(m_Drawing==true); + assert(_TextObj!=NULL); + assert(_Font!=NULL); + + if( _Font != m_FontTex ) + { + UnbindFont(m_D3DDev, m_FontD3DTex); + m_FontD3DTex = BindFont(m_D3DDev, _Font); + m_FontTex = _Font; + } + + CTextObj *TextObj = static_cast(_TextObj); + TextObj->m_TextVerts.resize(0); + TextObj->m_BgVerts.resize(0); + TextObj->m_LineColors = (_LineColors!=NULL); + TextObj->m_LineBgColors = (_LineBgColors!=NULL); + + int x, x1, y, y1, i, Len; + unsigned char ch; + const unsigned char *Text; + color32 LineColor = COLOR32_RED; + CTextVtx Vtx; + Vtx.m_Pos[2] = 0; + Vtx.m_Pos[3] = 1; + CBgVtx BgVtx; + BgVtx.m_Pos[2] = 0; + BgVtx.m_Pos[3] = 1; + for( int Line=0; Line<_NbLines; ++Line ) + { + x = 0; + y = Line * (_Font->m_CharHeight+_Sep); + y1 = y+_Font->m_CharHeight; + Len = (int)_TextLines[Line].length(); + Text = (const unsigned char *)(_TextLines[Line].c_str()); + if( _LineColors!=NULL ) + LineColor = _LineColors[Line]; + + for( i=0; im_CharWidth[ch]; + + Vtx.m_Color = LineColor; + + Vtx.m_Pos[0] = (float)x; + Vtx.m_Pos[1] = (float)y; + Vtx.m_UV [0] = _Font->m_CharU0[ch]; + Vtx.m_UV [1] = _Font->m_CharV0[ch]; + TextObj->m_TextVerts.push_back(Vtx); + + Vtx.m_Pos[0] = (float)x1; + Vtx.m_Pos[1] = (float)y; + Vtx.m_UV [0] = _Font->m_CharU1[ch]; + Vtx.m_UV [1] = _Font->m_CharV0[ch]; + TextObj->m_TextVerts.push_back(Vtx); + + Vtx.m_Pos[0] = (float)x; + Vtx.m_Pos[1] = (float)y1; + Vtx.m_UV [0] = _Font->m_CharU0[ch]; + Vtx.m_UV [1] = _Font->m_CharV1[ch]; + TextObj->m_TextVerts.push_back(Vtx); + + Vtx.m_Pos[0] = (float)x1; + Vtx.m_Pos[1] = (float)y; + Vtx.m_UV [0] = _Font->m_CharU1[ch]; + Vtx.m_UV [1] = _Font->m_CharV0[ch]; + TextObj->m_TextVerts.push_back(Vtx); + + Vtx.m_Pos[0] = (float)x1; + Vtx.m_Pos[1] = (float)y1; + Vtx.m_UV [0] = _Font->m_CharU1[ch]; + Vtx.m_UV [1] = _Font->m_CharV1[ch]; + TextObj->m_TextVerts.push_back(Vtx); + + Vtx.m_Pos[0] = (float)x; + Vtx.m_Pos[1] = (float)y1; + Vtx.m_UV [0] = _Font->m_CharU0[ch]; + Vtx.m_UV [1] = _Font->m_CharV1[ch]; + TextObj->m_TextVerts.push_back(Vtx); + + x = x1; + } + if( _BgWidth>0 && Len>0 ) + { + if( _LineBgColors!=NULL ) + BgVtx.m_Color = _LineBgColors[Line]; + else + BgVtx.m_Color = COLOR32_BLACK; + + BgVtx.m_Pos[0] = -1; + BgVtx.m_Pos[1] = (float)y; + TextObj->m_BgVerts.push_back(BgVtx); + + BgVtx.m_Pos[0] = (float)(_BgWidth+1); + BgVtx.m_Pos[1] = (float)y; + TextObj->m_BgVerts.push_back(BgVtx); + + BgVtx.m_Pos[0] = -1; + BgVtx.m_Pos[1] = (float)y1; + TextObj->m_BgVerts.push_back(BgVtx); + + BgVtx.m_Pos[0] = (float)(_BgWidth+1); + BgVtx.m_Pos[1] = (float)y; + TextObj->m_BgVerts.push_back(BgVtx); + + BgVtx.m_Pos[0] = (float)(_BgWidth+1); + BgVtx.m_Pos[1] = (float)y1; + TextObj->m_BgVerts.push_back(BgVtx); + + BgVtx.m_Pos[0] = -1; + BgVtx.m_Pos[1] = (float)y1; + TextObj->m_BgVerts.push_back(BgVtx); + } + } + +} + +// --------------------------------------------------------------------------- + +void CTwGraphDirect3D9::DrawText(void *_TextObj, int _X, int _Y, color32 _Color, color32 _BgColor) +{ + assert(m_Drawing==true); + assert(_TextObj!=NULL); + CTextObj *TextObj = static_cast(_TextObj); + float x = (float)_X; + float y = (float)_Y; + + int nv = (int)TextObj->m_TextVerts.size(); + if( nv<4 ) + return; // no character to draw + + int i; + int nb = (int)TextObj->m_BgVerts.size(); + + if( nb>=4 ) + { + for( i=0; im_BgVerts[i].m_Pos[0] += x; + TextObj->m_BgVerts[i].m_Pos[1] += y; + if( _BgColor!=0 || !TextObj->m_LineBgColors ) + TextObj->m_BgVerts[i].m_Color = _BgColor; + } + + m_D3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); + m_D3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + m_D3DDev->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE); + m_D3DDev->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nb/3, &(TextObj->m_BgVerts[0]), sizeof(CBgVtx)); + + for( i=0; im_BgVerts[i].m_Pos[0] -= x; + TextObj->m_BgVerts[i].m_Pos[1] -= y; + } + } + + for( i=0; im_TextVerts[i].m_Pos[0] += x; + TextObj->m_TextVerts[i].m_Pos[1] += y; + } + if( _Color!=0 || !TextObj->m_LineColors ) + for( i=0; im_TextVerts[i].m_Color = _Color; + + m_D3DDev->SetTexture(0, m_FontD3DTex); + m_D3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + m_D3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + m_D3DDev->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1|D3DFVF_TEXCOORDSIZE2(0)); + m_D3DDev->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nv/3, &(TextObj->m_TextVerts[0]), sizeof(CTextVtx)); + + for( i=0; im_TextVerts[i].m_Pos[0] -= x; + TextObj->m_TextVerts[i].m_Pos[1] -= y; + } + +} + +// --------------------------------------------------------------------------- diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwDirect3D9.h b/Extras/CDTestFramework/AntTweakBar/src/TwDirect3D9.h new file mode 100644 index 0000000..785c42b --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwDirect3D9.h @@ -0,0 +1,77 @@ +// --------------------------------------------------------------------------- +// +// @file TwDirect3D9.h +// @brief Direct3D9 graph functions +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// notes: Private header +// TAB=4 +// +// --------------------------------------------------------------------------- + + +#if !defined ANT_TW_DIRECT3D9_INCLUDED +#define ANT_TW_DIRECT3D9_INCLUDED + +#include "TwGraph.h" + +// --------------------------------------------------------------------------- + +class CTwGraphDirect3D9 : public ITwGraph +{ +public: + virtual int Init(); + virtual int Shut(); + virtual void BeginDraw(int _WndWidth, int _WndHeight); + virtual void EndDraw(); + virtual bool IsDrawing(); + virtual void Restore(); + virtual void DrawLine(int _X0, int _Y0, int _X1, int _Y1, color32 _Color0, color32 _Color1, bool _AntiAliased=false); + virtual void DrawLine(int _X0, int _Y0, int _X1, int _Y1, color32 _Color, bool _AntiAliased=false) { DrawLine(_X0, _Y0, _X1, _Y1, _Color, _Color, _AntiAliased); } + virtual void DrawRect(int _X0, int _Y0, int _X1, int _Y1, color32 _Color00, color32 _Color10, color32 _Color01, color32 _Color11); + virtual void DrawRect(int _X0, int _Y0, int _X1, int _Y1, color32 _Color) { DrawRect(_X0, _Y0, _X1, _Y1, _Color, _Color, _Color, _Color); } + + virtual void * NewTextObj(); + virtual void DeleteTextObj(void *_TextObj); + virtual void BuildText(void *_TextObj, const std::string *_TextLines, color32 *_LineColors, color32 *_LineBgColors, int _NbLines, const CTexFont *_Font, int _Sep, int _BgWidth); + virtual void DrawText(void *_TextObj, int _X, int _Y, color32 _Color, color32 _BgColor); + +protected: + struct IDirect3DDevice9 * m_D3DDev; + bool m_Drawing; + const CTexFont * m_FontTex; + struct IDirect3DTexture9 * m_FontD3DTex; + bool m_PureDevice; + int m_WndWidth; + int m_WndHeight; + + struct CTextVtx + { + float m_Pos[4]; + color32 m_Color; + float m_UV[2]; + }; + struct CBgVtx + { + float m_Pos[4]; + color32 m_Color; + }; + + struct CTextObj + { + std::vector m_TextVerts; + std::vector m_BgVerts; + bool m_LineColors; + bool m_LineBgColors; + }; + + struct CState * m_State; +}; + +// --------------------------------------------------------------------------- + + +#endif // !defined ANT_TW_DIRECT3D9_INCLUDED diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwEventGLFW.c b/Extras/CDTestFramework/AntTweakBar/src/TwEventGLFW.c new file mode 100644 index 0000000..d1158bf --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwEventGLFW.c @@ -0,0 +1,191 @@ +// --------------------------------------------------------------------------- +// +// @file TwEventGLFW.c +// @brief Helper: +// translate and re-send mouse and keyboard events +// from GLFW event callbacks to AntTweakBar +// +// @author Philippe Decaudin - http://www.antisphere.com +// @date 2006/05/10 +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// note: TAB=4 +// +// --------------------------------------------------------------------------- + +#include +#include + + +int TW_CALL TwEventMouseButtonGLFW(int glfwButton, int glfwAction) +{ + int handled = 0; + TwMouseAction action = (glfwAction==GLFW_PRESS) ? TW_MOUSE_PRESSED : TW_MOUSE_RELEASED; + + if( glfwButton==GLFW_MOUSE_BUTTON_LEFT ) + handled = TwMouseButton(action, TW_MOUSE_LEFT); + else if( glfwButton==GLFW_MOUSE_BUTTON_RIGHT ) + handled = TwMouseButton(action, TW_MOUSE_RIGHT); + else if( glfwButton==GLFW_MOUSE_BUTTON_MIDDLE ) + handled = TwMouseButton(action, TW_MOUSE_MIDDLE); + + return handled; +} + + +int g_KMod = 0; + + +int TW_CALL TwEventKeyGLFW(int glfwKey, int glfwAction) +{ + int handled = 0; + + // Register of modifiers state + if( glfwAction==GLFW_PRESS ) + { + switch( glfwKey ) + { + case GLFW_KEY_LSHIFT: + case GLFW_KEY_RSHIFT: + g_KMod |= TW_KMOD_SHIFT; + break; + case GLFW_KEY_LCTRL: + case GLFW_KEY_RCTRL: + g_KMod |= TW_KMOD_CTRL; + break; + case GLFW_KEY_LALT: + case GLFW_KEY_RALT: + g_KMod |= TW_KMOD_ALT; + break; + } + } + else + { + switch( glfwKey ) + { + case GLFW_KEY_LSHIFT: + case GLFW_KEY_RSHIFT: + g_KMod &= ~TW_KMOD_SHIFT; + break; + case GLFW_KEY_LCTRL: + case GLFW_KEY_RCTRL: + g_KMod &= ~TW_KMOD_CTRL; + break; + case GLFW_KEY_LALT: + case GLFW_KEY_RALT: + g_KMod &= ~TW_KMOD_ALT; + break; + } + } + + // Process key pressed + if( glfwAction==GLFW_PRESS ) + { + int mod = g_KMod; + int testkp = ((mod&TW_KMOD_CTRL) || (mod&TW_KMOD_ALT)) ? 1 : 0; + + if( (mod&TW_KMOD_CTRL) && glfwKey>0 && glfwKey=GLFW_KEY_SPECIAL ) + { + int k = 0; + + if( glfwKey>=GLFW_KEY_F1 && glfwKey<=GLFW_KEY_F15 ) + k = TW_KEY_F1 + (glfwKey-GLFW_KEY_F1); + else if( testkp && glfwKey>=GLFW_KEY_KP_0 && glfwKey<=GLFW_KEY_KP_9 ) + k = '0' + (glfwKey-GLFW_KEY_KP_0); + else + { + switch( glfwKey ) + { + case GLFW_KEY_ESC: + k = TW_KEY_ESCAPE; + break; + case GLFW_KEY_UP: + k = TW_KEY_UP; + break; + case GLFW_KEY_DOWN: + k = TW_KEY_DOWN; + break; + case GLFW_KEY_LEFT: + k = TW_KEY_LEFT; + break; + case GLFW_KEY_RIGHT: + k = TW_KEY_RIGHT; + break; + case GLFW_KEY_TAB: + k = TW_KEY_TAB; + break; + case GLFW_KEY_ENTER: + k = TW_KEY_RETURN; + break; + case GLFW_KEY_BACKSPACE: + k = TW_KEY_BACKSPACE; + break; + case GLFW_KEY_INSERT: + k = TW_KEY_INSERT; + break; + case GLFW_KEY_DEL: + k = TW_KEY_DELETE; + break; + case GLFW_KEY_PAGEUP: + k = TW_KEY_PAGE_UP; + break; + case GLFW_KEY_PAGEDOWN: + k = TW_KEY_PAGE_DOWN; + break; + case GLFW_KEY_HOME: + k = TW_KEY_HOME; + break; + case GLFW_KEY_END: + k = TW_KEY_END; + break; + case GLFW_KEY_KP_ENTER: + k = TW_KEY_RETURN; + break; + case GLFW_KEY_KP_DIVIDE: + if( testkp ) + k = '/'; + break; + case GLFW_KEY_KP_MULTIPLY: + if( testkp ) + k = '*'; + break; + case GLFW_KEY_KP_SUBTRACT: + if( testkp ) + k = '-'; + break; + case GLFW_KEY_KP_ADD: + if( testkp ) + k = '+'; + break; + case GLFW_KEY_KP_DECIMAL: + if( testkp ) + k = '.'; + break; + case GLFW_KEY_KP_EQUAL: + if( testkp ) + k = '='; + break; + } + } + + if( k>0 ) + handled = TwKeyPressed(k, mod); + } + } + + return handled; +} + + +int TW_CALL TwEventCharGLFW(int glfwChar, int glfwAction) +{ + if( glfwAction==GLFW_PRESS && (glfwChar & 0xff00)==0 ) + return TwKeyPressed(glfwChar, g_KMod); + else + return 0; +} + diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwEventGLUT.c b/Extras/CDTestFramework/AntTweakBar/src/TwEventGLUT.c new file mode 100644 index 0000000..4e28b82 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwEventGLUT.c @@ -0,0 +1,148 @@ +// --------------------------------------------------------------------------- +// +// @file TwEventGLUT.c +// @brief Helper: +// translate and re-send mouse and keyboard events +// from GLUT event callbacks to AntTweakBar +// +// @author Philippe Decaudin - http://www.antisphere.com +// @date 2006/05/10 +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// note: TAB=4 +// +// --------------------------------------------------------------------------- + + +#define GLUT_NO_LIB_PRAGMA // we do not want to force linkage with glut +#ifdef _MSC_VER +# pragma warning(disable: 4505) // glut generates 'unreferenced function' warnings +# pragma warning(disable: 4100) // unreferenced parameter +#endif // _MSC_VER +#include + +#include + + +int TW_GLUT_CALL TwEventMouseButtonGLUT(int glutButton, int glutState, int mouseX, int mouseY) +{ + TwMouseAction action = (glutState==GLUT_DOWN) ? TW_MOUSE_PRESSED : TW_MOUSE_RELEASED; + + switch( glutButton ) + { + case GLUT_LEFT_BUTTON: + return TwMouseButton(action, TW_MOUSE_LEFT); + case GLUT_RIGHT_BUTTON: + return TwMouseButton(action, TW_MOUSE_RIGHT); + case GLUT_MIDDLE_BUTTON: + return TwMouseButton(action, TW_MOUSE_MIDDLE); + default: + return 0; + } +} + +int TW_GLUT_CALL TwEventMouseMotionGLUT(int mouseX, int mouseY) +{ + return TwMouseMotion(mouseX, mouseY); +} + + +// GLUT does not send modifiers state to 'Key' and 'Special' callbacks, +// and we cannot call glutGetModifiers here because we do not want to link +// AntTweakBar with glut, so the following function is used to store +// a pointer to the glutGetModifiers function of the calling application. +// It must be called at initialisation of the application. + +int (TW_CALL *g_GLUTGetModifiers)(void) = NULL; + +int TW_CALL TwGLUTModifiersFunc(int (TW_CALL *glutGetModifiersFunc)(void)) +{ + g_GLUTGetModifiers = glutGetModifiersFunc; + return (g_GLUTGetModifiers==NULL) ? 0 : 1; +} + + +int TW_GLUT_CALL TwEventKeyboardGLUT(unsigned char glutKey, int mouseX, int mouseY) +{ + int kmod = 0; + + if( g_GLUTGetModifiers!=NULL ) + { + int glutMod = g_GLUTGetModifiers(); + + if( glutMod&GLUT_ACTIVE_SHIFT ) + kmod |= TW_KMOD_SHIFT; + if( glutMod&GLUT_ACTIVE_CTRL ) + kmod |= TW_KMOD_CTRL; + if( glutMod&GLUT_ACTIVE_ALT ) + kmod |= TW_KMOD_ALT; + } + + if( (kmod&TW_KMOD_CTRL) && (glutKey>0 && glutKey<27) ) // CTRL special case + glutKey += 'a'-1; + + return TwKeyPressed((int)glutKey, kmod); +} + + +int TW_GLUT_CALL TwEventSpecialGLUT(int glutKey, int mouseX, int mouseY) +{ + int k = 0, kmod = 0; + + if( g_GLUTGetModifiers!=NULL ) + { + int glutMod = g_GLUTGetModifiers(); + + if( glutMod&GLUT_ACTIVE_SHIFT ) + kmod |= TW_KMOD_SHIFT; + if( glutMod&GLUT_ACTIVE_CTRL ) + kmod |= TW_KMOD_CTRL; + if( glutMod&GLUT_ACTIVE_ALT ) + kmod |= TW_KMOD_ALT; + } + + if( glutKey>=GLUT_KEY_F1 && glutKey<=GLUT_KEY_F12 ) + k = TW_KEY_F1 + (glutKey-GLUT_KEY_F1); + else + { + switch( glutKey ) + { + case GLUT_KEY_LEFT: + k = TW_KEY_LEFT; + break; + case GLUT_KEY_UP: + k = TW_KEY_UP; + break; + case GLUT_KEY_RIGHT: + k = TW_KEY_RIGHT; + break; + case GLUT_KEY_DOWN: + k = TW_KEY_DOWN; + break; + case GLUT_KEY_PAGE_UP: + k = TW_KEY_PAGE_UP; + break; + case GLUT_KEY_PAGE_DOWN: + k = TW_KEY_PAGE_DOWN; + break; + case GLUT_KEY_HOME: + k = TW_KEY_HOME; + break; + case GLUT_KEY_END: + k = TW_KEY_END; + break; + case GLUT_KEY_INSERT: + k = TW_KEY_INSERT; + break; + } + } + + if( k>0 && k +#include + + +// TwEventSDL returns zero if msg has not been handled, +// and a non-zero value if it has been handled by the AntTweakBar library. +int TW_CALL TwEventSDL(const void *sdlEvent) +{ + int handled = 0; + const SDL_Event *event = (const SDL_Event *)sdlEvent; + + if( event==NULL ) + return 0; + + switch( event->type ) + { + case SDL_KEYDOWN: + if ( event->key.keysym.unicode!=0 && (event->key.keysym.unicode & 0xFF00)==0 ) + { + if( (event->key.keysym.unicode & 0xFF)<32 && (event->key.keysym.unicode & 0xFF)!=event->key.keysym.sym ) + handled = TwKeyPressed((event->key.keysym.unicode & 0xFF)+'a'-1, event->key.keysym.mod); + else + handled = TwKeyPressed(event->key.keysym.unicode & 0xFF, event->key.keysym.mod); + } + else + handled = TwKeyPressed(event->key.keysym.sym, event->key.keysym.mod); + break; + case SDL_MOUSEMOTION: + handled = TwMouseMotion(event->motion.x, event->motion.y); + break; + case SDL_MOUSEBUTTONUP: + case SDL_MOUSEBUTTONDOWN: + if( event->type==SDL_MOUSEBUTTONDOWN && (event->button.button==4 || event->button.button==5) ) // mouse wheel + { + static int s_WheelPos = 0; + if( event->button.button==4 ) + ++s_WheelPos; + else + --s_WheelPos; + handled = TwMouseWheel(s_WheelPos); + } + else + handled = TwMouseButton((event->type==SDL_MOUSEBUTTONUP)?TW_MOUSE_RELEASED:TW_MOUSE_PRESSED, (TwMouseButtonID)event->button.button); + break; + case SDL_VIDEORESIZE: + // tell the new size to TweakBar + TwWindowSize(event->resize.w, event->resize.h); + // do not set 'handled', SDL_VIDEORESIZE may be also processed by the calling application + break; + } + + return handled; +} diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwEventWin32.c b/Extras/CDTestFramework/AntTweakBar/src/TwEventWin32.c new file mode 100644 index 0000000..3c39f77 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwEventWin32.c @@ -0,0 +1,188 @@ +// --------------------------------------------------------------------------- +// +// @file TwEventWin32.c +// @brief Helper: +// translate and re-send mouse and keyboard events +// from Win32 message proc to AntTweakBar +// +// @author Philippe Decaudin - http://www.antisphere.com +// @date 2006/05/10 +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// note: TAB=4 +// +// --------------------------------------------------------------------------- + +#include + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include + +// Mouse wheel support +#if !defined WM_MOUSEWHEEL +# define WM_MOUSEWHEEL 0x020A +#endif // WM_MOUSEWHEEL +#if !defined WHEEL_DELTA +#define WHEEL_DELTA 120 +#endif // WHEEL_DELTA + + +// TwEventWin32 returns zero if msg has not been handled, +// and a non-zero value if it has been handled by the AntTweakBar library. +int TW_CALL TwEventWin32(void *wnd, unsigned int msg, unsigned int _W64 wParam, int _W64 lParam) +{ + int handled = 0; + switch( msg ) + { + case WM_MOUSEMOVE: + // send signed! mouse coordinates + handled = TwMouseMotion((short)LOWORD(lParam), (short)HIWORD(lParam)); + break; + case WM_LBUTTONDOWN: + SetCapture(wnd); + handled = TwMouseButton(TW_MOUSE_PRESSED, TW_MOUSE_LEFT); + break; + case WM_LBUTTONUP: + ReleaseCapture(); + handled = TwMouseButton(TW_MOUSE_RELEASED, TW_MOUSE_LEFT); + break; + case WM_MBUTTONDOWN: + SetCapture(wnd); + handled = TwMouseButton(TW_MOUSE_PRESSED, TW_MOUSE_MIDDLE); + break; + case WM_MBUTTONUP: + ReleaseCapture(); + handled = TwMouseButton(TW_MOUSE_RELEASED, TW_MOUSE_MIDDLE); + break; + case WM_RBUTTONDOWN: + SetCapture(wnd); + handled = TwMouseButton(TW_MOUSE_PRESSED, TW_MOUSE_RIGHT); + break; + case WM_RBUTTONUP: + ReleaseCapture(); + handled = TwMouseButton(TW_MOUSE_RELEASED, TW_MOUSE_RIGHT); + break; + case WM_CHAR: + case WM_SYSCHAR: + { + int key = (int)(wParam&0xff); + int kmod = 0; + + if( GetAsyncKeyState(VK_SHIFT)<0 ) + kmod |= TW_KMOD_SHIFT; + if( GetAsyncKeyState(VK_CONTROL)<0 ) + { + kmod |= TW_KMOD_CTRL; + if( key>0 && key<27 ) + key += 'a'-1; + } + if( GetAsyncKeyState(VK_MENU)<0 ) + kmod |= TW_KMOD_ALT; + if( key>0 && key<256 ) + handled = TwKeyPressed(key, kmod); + } + break; + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + { + int kmod = 0; + int testkp = 0; + int k = 0; + + if( GetAsyncKeyState(VK_SHIFT)<0 ) + kmod |= TW_KMOD_SHIFT; + if( GetAsyncKeyState(VK_CONTROL)<0 ) + { + kmod |= TW_KMOD_CTRL; + testkp = 1; + } + if( GetAsyncKeyState(VK_MENU)<0 ) + { + kmod |= TW_KMOD_ALT; + testkp = 1; + } + if( wParam>=VK_F1 && wParam<=VK_F15 ) + k = TW_KEY_F1 + ((int)wParam-VK_F1); + else if( testkp && wParam>=VK_NUMPAD0 && wParam<=VK_NUMPAD9 ) + k = '0' + ((int)wParam-VK_NUMPAD0); + else + { + switch( wParam ) + { + case VK_UP: + k = TW_KEY_UP; + break; + case VK_DOWN: + k = TW_KEY_DOWN; + break; + case VK_LEFT: + k = TW_KEY_LEFT; + break; + case VK_RIGHT: + k = TW_KEY_RIGHT; + break; + case VK_INSERT: + k = TW_KEY_INSERT; + break; + case VK_DELETE: + k = TW_KEY_DELETE; + break; + case VK_PRIOR: + k = TW_KEY_PAGE_UP; + break; + case VK_NEXT: + k = TW_KEY_PAGE_DOWN; + break; + case VK_HOME: + k = TW_KEY_HOME; + break; + case VK_END: + k = TW_KEY_END; + break; + case VK_DIVIDE: + if( testkp ) + k = '/'; + break; + case VK_MULTIPLY: + if( testkp ) + k = '*'; + break; + case VK_SUBTRACT: + if( testkp ) + k = '-'; + break; + case VK_ADD: + if( testkp ) + k = '+'; + break; + case VK_DECIMAL: + if( testkp ) + k = '.'; + break; + default: + if( (kmod&TW_KMOD_CTRL) && (kmod&TW_KMOD_ALT) ) + k = MapVirtualKey( (UINT)wParam, 2 ) & 0x0000FFFF; + } + } + if( k!=0 ) + handled = TwKeyPressed(k, kmod); + } + break; + case WM_MOUSEWHEEL: + { + static int s_WheelPos = 0; + s_WheelPos += ((short)HIWORD(wParam))/WHEEL_DELTA; + handled = TwMouseWheel(s_WheelPos); + } + break; + case WM_SIZE: + // tell the new size to TweakBar + TwWindowSize(LOWORD(lParam), HIWORD(lParam)); + // do not set 'handled', WM_SIZE may be also processed by the calling application + break; + } + + return handled; +} diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwFonts.cpp b/Extras/CDTestFramework/AntTweakBar/src/TwFonts.cpp new file mode 100644 index 0000000..036c469 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwFonts.cpp @@ -0,0 +1,3935 @@ +// --------------------------------------------------------------------------- +// +// @file TwFonts.cpp +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// note: TAB=4 +// +// --------------------------------------------------------------------------- + + +#include "TwPrecomp.h" +#include "TwMgr.h" +#include "TwFonts.h" + + +// --------------------------------------------------------------------------- + +CTexFont::CTexFont() +{ + for( int i=0; i<256; ++i ) + { + m_CharU0[i] = 0; + m_CharU1[i] = 0; + m_CharV0[i] = 0; + m_CharV1[i] = 0; + m_CharWidth[i] = 0; + } + m_TexWidth = 0; + m_TexHeight = 0; + m_TexBytes = NULL; + m_NbCharRead = 0; + m_CharHeight = 0; +} + +// --------------------------------------------------------------------------- + +CTexFont::~CTexFont() +{ + if( m_TexBytes ) + delete m_TexBytes; + m_TexBytes = NULL; + m_TexWidth = 0; + m_TexHeight = 0; + m_NbCharRead = 0; +} + +// --------------------------------------------------------------------------- + +static int NextPow2(int _n) +{ + int r = 1; + while( r<_n ) + r *= 2; + return r; +} + +// --------------------------------------------------------------------------- + +const char *g_ErrBadFontHeight = "Cannot determine font height while reading font bitmap (check first pixel column)"; + +CTexFont *TwGenerateFont(const unsigned char *_Bitmap, int _BmWidth, int _BmHeight) +{ + // find height of the font + int x, y; + int h = 0, hh = 0; + int r, NbRow = 0; + for( y=0; y<_BmHeight; ++y ) + if( _Bitmap[y*_BmWidth]==0 ) + { + if( (hh<=0 && h<=0) || (h!=hh && h>0 && hh>0) ) + { + g_TwMgr->SetLastError(g_ErrBadFontHeight); + return NULL; + } + else if( h<=0 ) + h = hh; + else if( hh<=0 ) + break; + hh = 0; + ++NbRow; + } + else + ++hh; + + // find width and position of each character + int w = 0; + int x0[224], y0[224], x1[224], y1[224]; + int ch = 32; + int start; + for( r=0; rlmax ) + lmax = l; + } + // A little empty margin is added between chars to avoid artefact when antialiasing is on + const int MARGIN_X = 2; + const int MARGIN_Y = 2; + lmax += 16*MARGIN_X; + // - Second, build the texture + CTexFont *TexFont = new CTexFont; + TexFont->m_NbCharRead = ch-32; + TexFont->m_CharHeight = h; + TexFont->m_TexWidth = NextPow2(lmax); + TexFont->m_TexHeight = NextPow2(14*(h+MARGIN_Y)); + TexFont->m_TexBytes = new unsigned char[TexFont->m_TexWidth*TexFont->m_TexHeight]; + memset(TexFont->m_TexBytes, 0, TexFont->m_TexWidth*TexFont->m_TexHeight); + int xx; + float du = 0.4f; + float dv = 0.4f; + assert( g_TwMgr!=NULL ); + if( g_TwMgr ) + { + if( g_TwMgr->m_GraphAPI==TW_OPENGL ) + { + du = 0; + dv = 0; + } + else // texel alignement for D3D + { + du = 0.5f; + dv = 0.5f; + } + } + float alpha; + for( r=0; r<14; ++r ) + for( xx=0, ch=r*16; ch<(r+1)*16; ++ch ) + if( y1[ch]-y0[ch]==h-1 ) + { + for( y=0; ym_TexBytes[(xx+x-x0[ch])+(r*(h+MARGIN_Y)+y)*TexFont->m_TexWidth] = (unsigned char)(alpha*256.0f); + } + TexFont->m_CharU0[ch+32] = (float(xx)+du)/float(TexFont->m_TexWidth); + xx += x1[ch]-x0[ch]+1; + TexFont->m_CharU1[ch+32] = (float(xx)+du)/float(TexFont->m_TexWidth); + TexFont->m_CharV0[ch+32] = (float(r*(h+MARGIN_Y))+dv)/float(TexFont->m_TexHeight); + TexFont->m_CharV1[ch+32] = (float(r*(h+MARGIN_Y)+h)+dv)/float(TexFont->m_TexHeight); + TexFont->m_CharWidth[ch+32] = x1[ch]-x0[ch]+1; + xx += MARGIN_X; + } + + return TexFont; +} + +// --------------------------------------------------------------------------- + +CTexFont *g_DefaultSmallFont = NULL; +CTexFont *g_DefaultNormalFont = NULL; +CTexFont *g_DefaultLargeFont = NULL; + +// Small font +const int FONT0_BM_W = 211; +const int FONT0_BM_H = 84; +static const unsigned char s_Font0[] = +{ + 127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0, + 0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,255,0,0,0,255,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 0,0,0,0,255,0,255,0,255,0,0,0,255,0,0,255,0,0,0,255,0,0,0,0,255,255,0,0, + 0,255,0,0,0,0,255,255,0,0,0,255,0,0,255,0,0,255,0,0,255,0,255,0,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,255,0,0,0,255,0,0,255,255, + 255,0,0,255,255,255,0,0,0,0,0,255,0,255,255,255,255,0,0,255,255,0,0,255, + 255,255,255,0,0,255,255,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,127,0,0,0,0,255,0,255,0,255,0,0,0,255,0,0,255,0,0,255,255,255,255, + 0,255,0,0,255,0,255,0,0,0,0,255,0,0,255,0,0,255,0,255,0,0,0,0,255,0,0,255, + 255,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,255,0,255, + 255,0,0,0,0,0,255,0,0,0,0,255,0,0,0,255,255,0,255,0,0,0,0,255,0,0,0,0,0, + 0,0,255,0,255,0,0,255,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 0,0,0,0,255,0,0,0,0,0,0,255,255,255,255,255,255,255,0,255,0,0,0,255,0,0, + 255,0,255,0,0,0,0,255,0,0,255,0,0,0,0,255,0,0,0,0,255,0,255,0,255,0,255, + 0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,255,0,0,255,0,0,0, + 0,0,255,0,0,0,0,255,0,0,255,0,255,0,255,0,0,0,0,255,0,0,0,0,0,0,255,0,0, + 255,0,0,255,0,255,0,0,255,0,0,255,0,0,255,0,0,0,0,0,255,255,0,0,0,0,0,0, + 0,0,0,255,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 127,0,0,0,0,255,0,0,0,0,0,0,0,255,0,255,0,0,0,255,255,0,0,0,0,255,255,0, + 255,0,255,255,0,0,0,255,255,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0, + 0,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,255,0,0,255, + 0,0,0,0,255,0,0,0,255,255,0,0,255,0,0,255,0,255,255,255,0,0,255,255,255, + 0,0,0,0,255,0,0,0,255,255,0,0,0,255,255,255,0,0,255,0,0,255,0,0,0,255,255, + 0,0,0,255,255,255,255,255,255,0,0,0,0,255,255,0,0,0,0,255,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,255,0,0,0,0,0,255,255,255,255,255, + 255,0,0,0,255,255,0,0,0,0,0,255,0,255,0,0,255,0,255,0,0,255,0,0,0,0,255, + 0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,255,0,0,0,0,0,255,0, + 0,255,0,0,255,0,0,255,0,0,0,255,0,0,0,0,0,0,255,0,255,255,255,255,255,0, + 0,0,255,0,255,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0,0,0,255,0,0,0,0,0,0, + 0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0, + 255,0,255,0,0,0,0,255,0,255,0,0,255,0,255,0,0,255,255,0,0,0,255,0,0,0,0, + 255,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,255,0,0,255,0,0,255,0, + 0,255,0,0,255,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,255,0,255,0, + 0,255,0,0,255,0,0,0,255,0,0,255,0,0,0,0,255,0,0,255,0,0,255,0,0,0,255,255, + 0,0,0,255,255,255,255,255,255,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,255,0,0,0,0,0,0,255,0,0,255,0,0,255, + 255,255,255,0,0,0,0,255,0,0,0,255,255,0,0,0,255,255,0,0,255,0,0,255,0,0, + 0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,255,0,0,0,0,255, + 255,0,0,255,255,255,0,255,255,255,255,0,255,255,255,0,0,0,0,0,255,0,255, + 255,255,0,0,0,255,255,0,0,255,0,0,0,0,0,255,255,0,0,0,255,255,0,0,0,255, + 0,0,255,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,255,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127,0,127,0,127,127,127, + 0,127,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,127, + 127,127,127,0,127,127,127,127,127,0,127,0,127,127,0,127,127,127,0,127,127, + 127,127,127,0,127,127,127,127,127,127,0,127,127,0,127,127,127,0,127,0,127, + 127,127,0,127,127,127,127,0,127,127,127,0,127,127,127,127,0,127,127,127, + 127,0,127,127,127,127,0,127,127,127,127,0,127,127,127,127,0,127,127,127, + 127,0,127,127,127,127,0,127,127,127,127,0,127,127,0,127,127,0,127,127,127, + 127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127, + 127,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,255,0,0,0,255,255,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,255,255,255,0,0,0,0,0, + 255,255,0,0,0,255,255,255,0,0,0,0,0,255,255,255,0,0,255,255,255,255,0,0, + 0,255,255,255,255,255,0,255,255,255,255,255,0,0,0,255,255,255,0,0,255,0, + 0,0,0,255,0,255,255,255,0,0,255,255,0,255,0,0,0,255,0,255,0,0,0,255,255, + 0,0,0,255,255,0,255,0,0,0,0,255,0,0,0,255,255,255,0,0,0,255,255,255,255, + 0,0,0,0,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,255,255, + 255,255,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,255,0,0,255,0, + 255,0,0,255,0,255,0,0,0,255,0,255,255,255,255,0,255,0,0,255,0,0,0,0,255, + 0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,255,0, + 0,0,255,0,0,0,0,255,255,0,0,0,255,0,0,255,0,0,0,255,0,0,0,255,0,255,0,0, + 0,255,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,255,0,255,0,0,0,0,255, + 0,0,255,0,0,0,0,255,0,255,0,0,255,0,0,255,0,0,0,255,255,0,0,0,255,255,0, + 255,255,0,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0,0,255, + 0,0,255,0,0,0,255,0,255,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,255,0, + 0,0,0,255,0,255,0,0,255,0,0,255,0,255,0,0,255,0,0,255,0,255,0,0,0,0,0,255, + 0,255,0,0,0,255,0,0,0,255,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,127,255,0,0,255,255,0,255,0,0,255,0,0,255,0,0,255,0,0,255, + 0,0,255,0,0,0,0,0,0,255,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0, + 0,0,0,0,0,255,0,0,0,0,255,0,0,255,0,0,0,0,255,0,255,0,255,0,0,0,255,0,0, + 0,255,0,255,0,255,0,255,0,255,0,255,0,0,255,0,255,0,0,0,0,0,255,0,255,0, + 0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,0,0,0,0,255,0,0, + 0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,255,0,255,0,255,0,0,255,255, + 0,0,0,255,0,255,0,0,0,0,255,0,0,255,0,0,0,255,0,0,0,255,0,255,0,0,0,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,255,0,255,0,255,0,255, + 0,0,255,0,0,255,0,0,255,255,255,255,0,0,255,0,0,0,0,0,0,255,0,0,0,0,255, + 0,255,255,255,255,0,0,255,255,255,255,0,0,255,0,0,255,255,255,0,255,255, + 255,255,255,255,0,0,255,0,0,0,0,255,0,255,255,0,0,0,0,255,0,0,0,255,0,255, + 0,255,0,255,0,255,0,0,255,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,255,0,255, + 0,0,0,0,0,255,0,255,255,255,255,0,0,0,255,255,255,0,0,0,0,255,0,0,0,255, + 0,0,0,0,255,0,0,255,0,0,255,0,0,255,0,255,0,255,0,255,0,0,255,255,0,0,0, + 0,255,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,255,0,255,0,255,0,255,0,255,255,255, + 255,255,255,0,255,0,0,0,255,0,255,0,0,0,0,0,0,255,0,0,0,0,255,0,255,0,0, + 0,0,0,255,0,0,0,0,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,0,255,0,0,0,0,255, + 0,255,0,255,0,0,0,255,0,0,0,255,0,0,255,0,0,255,0,255,0,0,0,255,255,0,255, + 0,0,0,0,0,255,0,255,255,255,255,0,0,255,0,0,0,0,0,255,0,255,0,255,0,0,0, + 0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,255,0,0,255,0,0,255,0,255, + 0,255,0,255,0,0,255,255,0,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0, + 0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,255, + 0,0,255,255,255,0,0,255,0,0,0,0,255,0,255,0,0,0,255,0,0,255,0,0,0,255,0, + 255,0,0,0,255,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,255,0,255,0,0, + 0,0,255,0,0,255,0,0,0,0,255,0,255,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0, + 255,0,255,0,0,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0,0,0,0,0,255,0,0,0,255, + 0,0,255,0,0,255,0,0,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255, + 255,0,0,0,0,255,0,0,0,255,0,0,255,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,255, + 0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,127,0,255,0,0,0,0,0,0,255,0,0,0,0,255,0,255,255,255,255,0,0,0,0,255, + 255,255,0,0,255,255,255,255,0,0,0,255,255,255,255,255,0,255,0,0,0,0,0,0, + 0,255,255,255,255,0,255,0,0,0,0,255,0,255,255,255,0,255,255,0,0,255,0,0, + 0,255,0,255,255,255,255,255,0,0,0,0,0,255,0,255,0,0,0,0,255,0,0,0,255,255, + 255,0,0,0,255,0,0,0,0,0,0,0,255,255,255,0,0,0,255,0,0,0,255,0,255,255,255, + 255,0,0,0,0,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,0,0,0,0,255,0,0, + 0,255,0,0,255,0,0,255,0,0,0,255,0,0,0,255,255,255,255,0,255,0,0,0,0,255, + 0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0, + 0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0, + 0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255, + 0,0,0,0,0,255,255,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127, + 0,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127, + 0,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,127,0, + 127,127,127,127,127,127,0,127,127,127,0,127,127,127,0,127,127,127,127,127, + 0,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,0, + 127,127,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127, + 127,127,0,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127, + 0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,0,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,0,127, + 127,0,127,127,127,0,127,127,0,127,127,127,127,127,0,127,127,127,127,127, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,127,255,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0, + 0,0,255,0,0,0,0,0,0,0,255,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0, + 0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,255,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,255,0,0,0,0,0,0,0,255,0,0, + 0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0, + 255,0,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,255, + 255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0, + 0,0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,255, + 0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,127,0,0,0,0,0,255,255,0,0,255,255,255,0,0,0,255,255,0,0,255, + 255,255,0,0,255,255,0,0,255,255,255,0,255,255,255,0,255,255,255,0,0,255, + 0,255,255,0,255,0,0,255,0,255,0,255,255,255,0,255,255,0,0,255,255,255,0, + 0,0,255,255,0,0,255,255,255,0,0,0,255,255,255,0,255,0,255,255,255,255,0, + 255,255,0,255,0,0,255,0,255,0,0,0,255,0,255,0,0,255,0,0,255,0,255,0,255, + 0,255,0,0,0,255,0,255,255,255,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0, + 0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 0,0,0,0,0,0,0,255,0,255,0,0,255,0,255,0,0,0,255,0,0,255,0,255,0,0,255,0, + 255,0,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,255,0,0,255,0,255, + 0,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255, + 0,255,255,0,255,0,0,0,255,0,0,255,0,0,255,0,0,255,0,255,0,0,255,0,0,255, + 0,0,255,0,0,255,0,0,0,255,0,255,0,0,0,0,255,0,0,255,0,0,0,255,0,0,0,255, + 0,0,0,255,255,0,0,255,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,255,255,255,0,255,0,0,255,0,255,0,0,0,255, + 0,0,255,0,255,255,255,255,0,255,0,0,255,0,0,255,0,255,0,0,255,0,255,0,0, + 255,0,255,255,0,0,0,255,0,255,0,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255, + 0,255,0,0,255,0,255,0,0,255,0,255,0,0,0,255,0,0,255,0,0,255,0,0,255,0,0, + 255,0,255,0,0,255,0,255,0,255,0,255,0,0,255,0,0,0,255,0,255,0,0,0,255,0, + 0,255,0,0,0,0,255,0,0,0,0,255,0,255,0,0,255,255,0,0,0,255,0,0,0,0,0,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,255,0,0,255,0, + 255,0,0,255,0,255,0,0,0,255,0,0,255,0,255,0,0,0,0,255,0,0,255,0,0,255,0, + 255,0,0,255,0,255,0,0,255,0,255,0,255,0,0,255,0,255,0,0,255,0,0,255,0,255, + 0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,0,0,255,0,255, + 0,0,255,0,0,255,0,0,255,0,255,0,0,0,255,255,0,255,255,0,0,0,255,0,0,0,255, + 0,255,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,255,0, + 0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0, + 255,255,255,0,255,255,255,0,0,0,255,255,0,0,255,255,255,0,0,255,255,255, + 0,255,0,0,0,255,255,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,255, + 0,255,0,0,255,0,0,255,0,255,0,0,255,0,0,255,255,0,0,255,255,255,0,0,0,255, + 255,255,0,255,0,0,255,255,255,0,0,255,0,0,255,255,255,0,0,0,255,0,0,0,0, + 255,0,0,0,255,0,0,255,0,255,0,0,0,255,0,0,0,255,255,255,0,0,255,0,0,0,255, + 0,0,0,255,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0, + 0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,255,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127,0,127,127, + 127,127,0,127,127,127,127,0,127,127,127,0,127,127,127,127,0,127,127,127, + 127,0,127,127,0,127,127,127,127,0,127,127,127,127,0,127,0,127,127,0,127, + 127,127,127,0,127,0,127,127,127,127,127,127,127,0,127,127,127,127,0,127, + 127,127,127,0,127,127,127,127,0,127,127,127,127,0,127,127,0,127,127,127, + 0,127,127,0,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127, + 127,127,0,127,127,127,0,127,127,127,127,127,0,127,127,127,0,127,127,127, + 0,127,127,127,0,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0, + 0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,0,0,255,255,0,255,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,255,0,255,0,0,0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,127,0,255,255,255,0,0,255,255,255,255,255,255,255,0,0,0,0, + 0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,255,0,255, + 0,0,255,255,0,0,0,255,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,255,255,255, + 255,255,255,255,0,0,255,255,255,255,255,255,255,0,255,255,255,255,0,0,255, + 255,255,255,255,255,255,0,0,255,255,255,255,255,255,255,0,255,0,0,255,255, + 0,255,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,255,255,255, + 255,255,0,255,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255, + 255,255,255,0,0,255,0,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,127,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,255,255,255,255,0,255,255,255,255,255,0,0,0,0,0,0,255, + 0,0,255,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,0, + 255,0,0,0,0,0,255,0,0,0,0,255,0,0,255,0,0,0,0,0,255,0,0,255,0,0,0,0,0,255, + 0,0,255,255,0,0,255,0,255,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,255,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0, + 0,0,0,0,255,0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,127,255,255,255,255,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,255,0,0,255,0, + 255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,255,0,0,0,255,0,0,0,0,0,255,0,0, + 0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,0,255,0,0,255,0,0,0,0,0,255,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0, + 0,255,0,255,0,255,255,255,0,255,0,0,0,255,255,0,255,255,0,0,0,255,0,0,0, + 0,0,255,0,255,255,255,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,127,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255,255,255,255,255,0,0,0,0,0,0,0,255, + 255,0,255,0,255,255,0,255,255,0,0,0,255,255,255,0,0,255,0,0,255,0,0,0,255, + 255,255,255,0,0,255,0,0,0,0,0,255,0,0,255,0,0,0,0,255,0,0,0,0,0,255,0,0, + 255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,255,0,0,255,0,0, + 255,0,0,255,0,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,127,255,255,255,255,0,0,255,0,0,0,0,0,255,0,0,0, + 0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0, + 0,0,0,255,0,255,0,0,255,0,0,255,0,0,0,0,0,255,0,255,0,0,255,0,0,0,255,0, + 0,0,0,0,255,0,0,0,0,0,255,0,0,255,0,0,0,0,255,0,0,0,0,0,255,0,0,255,0,0, + 0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,255,255,255,255,0,255, + 255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255,0, + 255,0,0,255,255,255,255,0,0,255,0,0,0,0,0,255,0,0,255,0,0,0,0,255,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,255,0,0,0,0,0,255,0,0,0, + 0,0,255,0,0,255,0,0,255,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0, + 255,0,0,0,0,0,0,0,0,0,0,0,255,0,255,0,0,255,0,0,255,0,0,0,0,0,255,0,0,255, + 0,255,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,0,0, + 0,255,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,255,0,0,255,0, + 0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,255,255,255,0,0,255,255,255,255,255, + 255,255,0,0,255,0,255,0,0,0,0,255,0,255,0,255,0,255,0,255,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255,255,0,255,255,0,0,255,255,255,255, + 0,0,0,0,0,0,255,255,255,255,255,255,255,0,0,255,255,255,255,255,255,255, + 0,255,255,255,255,0,0,255,255,255,255,255,255,255,0,0,255,255,255,255,255, + 255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,255,255,0,255,255,255,0,0,255, + 255,255,255,255,255,255,0,255,255,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,255,255, + 0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,127,127,127,127,0,127,127,127,127,127,127,127,127, + 0,127,0,127,127,127,127,0,127,127,127,127,0,127,127,127,127,127,0,127,127, + 127,127,127,0,127,127,127,127,127,0,127,127,127,127,0,127,127,127,127,127, + 127,127,127,127,127,127,127,0,127,127,127,127,127,0,127,127,0,127,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127,127,127, + 0,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127, + 0,127,0,127,127,127,0,127,127,127,0,127,127,127,0,127,127,127,127,0,127, + 127,127,127,127,127,127,0,127,127,127,127,0,127,127,127,127,127,127,127, + 0,127,127,127,0,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,127,0,127,127,127,0,127,127,127,127,127,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,255,0,0,0,255,0,0,0,0,255,255,0,0, + 0,0,0,0,0,255,0,0,0,255,0,255,0,0,255,255,255,0,0,255,0,255,0,0,0,255,255, + 255,255,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255, + 0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,255,255,255,0,255,255,255,0,0,255, + 0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,255,0,0,0, + 0,0,0,0,0,255,0,0,255,0,0,0,0,0,255,0,0,0,255,0,0,0,255,255,255,0,0,255, + 0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,255, + 0,0,0,255,0,0,255,0,255,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255, + 0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0, + 0,255,0,255,0,0,0,0,255,0,0,0,0,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255, + 255,0,255,0,0,0,0,0,0,0,0,0,0,255,255,0,255,0,0,255,0,0,0,0,0,0,255,255, + 0,255,0,0,0,0,0,255,255,0,0,255,0,0,0,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,127,0,0,0,0,0,255,0,0,255,255,255,0,0,255,0,0,0,0,255,255,255, + 0,0,0,255,0,255,0,0,255,0,255,0,0,0,0,0,0,0,0,0,255,0,0,255,255,0,0,255, + 255,0,255,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,255,0,255,255,255,0,0,255, + 0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,255,0, + 0,255,0,255,255,0,255,0,0,0,0,0,0,0,0,0,0,0,255,0,255,0,0,255,0,255,0,255, + 0,0,0,255,0,255,0,0,0,0,0,0,255,0,0,255,0,0,0,0,0,0,255,0,255,0,0,0,0,0, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,255,0,255,0,255,0,0,255,255,255,0,0,0, + 255,0,255,0,0,0,0,255,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,255,0,255,0,0, + 0,0,255,0,255,255,0,255,0,255,0,0,0,255,255,255,255,255,0,0,0,0,255,0,255, + 0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,0,0,255,255,255,0, + 255,255,0,0,0,0,0,0,255,0,0,255,0,255,255,0,255,0,0,255,0,0,0,0,0,0,0,255, + 255,255,0,255,255,0,0,0,255,0,255,0,0,255,255,0,0,255,255,0,0,0,255,0,255, + 0,255,255,0,0,255,255,0,255,0,255,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0, + 0,0,0,255,0,255,0,255,0,0,0,255,0,0,0,0,255,255,255,0,0,0,255,255,255,0, + 0,0,0,255,0,0,255,0,0,0,0,0,0,255,0,255,0,0,0,0,255,0,0,0,0,255,0,255,0, + 0,0,0,0,0,0,255,0,255,255,0,255,0,255,255,255,0,0,255,0,0,0,0,0,0,0,0,0, + 0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,255,0,255,0,0, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,255,0,0,0,255,0,255,0,255,0,0, + 0,0,255,0,0,0,0,255,0,0,0,255,0,255,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 0,0,0,0,0,255,0,255,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, + 255,0,0,255,255,255,0,0,0,0,0,0,255,0,0,255,255,0,0,255,0,0,0,0,0,255,0, + 255,0,0,0,0,0,0,255,0,0,0,0,255,0,255,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0, + 0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,255,0,255,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,255,0,0,0,0,255,0,255,255,255,255,0, + 0,0,255,0,0,0,255,0,0,0,0,255,0,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 127,0,0,0,0,0,255,0,0,255,255,255,0,255,255,255,255,0,0,0,0,0,0,0,0,0,255, + 0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255,255,255, + 255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,255,0,255,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0, + 0,255,255,255,0,0,255,0,0,0,0,255,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0, + 0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255, + 0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,255,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,255,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127,127,0,127,0,127,127,127,127,0,127, + 127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,0,127,0,127,127, + 127,127,0,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,0, + 127,127,127,127,0,127,127,127,127,127,127,0,127,127,0,127,127,127,127,127, + 127,127,0,127,127,127,127,0,127,127,127,127,0,127,127,127,127,127,0,127, + 127,127,127,0,127,127,127,0,127,127,127,0,127,127,127,127,0,127,127,127, + 127,0,127,127,127,0,127,127,127,0,127,127,127,0,127,127,127,127,0,127,127, + 127,127,0,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 127,0,127,127,127,127,127,127,127,0,127,127,127,127,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0, + 0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,255,0,255,0,0,0,255,0,255,255,0,0,0,255, + 0,0,255,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0, + 0,0,0,255,0,0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,255,0,0,0,255,0,0,255, + 0,255,0,255,0,255,0,0,0,0,0,0,0,0,0,255,0,255,255,0,0,0,0,0,255,0,0,0,0, + 0,0,0,255,0,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,255,0,0,0,0,255,0,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0, + 255,0,255,0,0,0,255,0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,127,0,0, + 255,255,0,0,0,0,0,255,255,0,0,0,0,0,255,255,0,0,0,0,0,255,255,0,0,0,0,0, + 255,255,0,0,0,0,0,255,255,0,0,0,0,0,255,255,255,255,255,0,0,0,255,255,255, + 0,0,255,255,255,255,255,0,255,255,255,255,255,0,255,255,255,255,255,0,255, + 255,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255, + 0,255,255,255,255,0,0,0,255,0,0,0,0,255,0,0,0,255,255,255,0,0,0,0,0,255, + 255,255,0,0,0,0,0,255,255,255,0,0,0,0,0,255,255,255,0,0,0,0,0,255,255,255, + 0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,255,0,255,0,0,0,0,255,0,255,0,0,0, + 0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,0, + 255,0,0,255,0,127,0,0,255,255,0,0,0,0,0,255,255,0,0,0,0,0,255,255,0,0,0, + 0,0,255,255,0,0,0,0,0,255,255,0,0,0,0,0,255,255,0,0,0,0,255,0,255,0,0,0, + 0,0,255,0,0,0,255,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0, + 0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,255,0,0,0,255,0,0,255,255,0, + 0,0,255,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, + 255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255,0,0, + 255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0, + 0,255,0,255,0,0,255,255,255,0,0,255,0,0,255,0,127,0,255,0,0,255,0,0,0,255, + 0,0,255,0,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0,0,255, + 0,0,255,0,0,0,255,0,255,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0, + 0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0, + 255,0,0,0,0,255,0,255,0,255,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0, + 255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,255, + 0,0,0,255,0,255,0,0,0,255,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255, + 0,0,0,0,255,0,255,0,0,0,0,255,0,0,255,0,255,0,0,255,0,0,255,0,255,0,255, + 0,0,127,0,255,0,0,255,0,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0,0,255,0,0, + 255,0,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0,0,255,0,255,255,255,255,0,255, + 0,0,0,0,0,0,255,255,255,255,0,0,255,255,255,255,0,0,255,255,255,255,0,0, + 255,255,255,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,255,255,255, + 0,0,255,0,255,0,0,255,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255, + 0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,0,255,0,255,0, + 0,255,0,0,255,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0, + 255,0,255,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,255,0,255,0,0,255,0,127,255, + 255,255,255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255, + 0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255, + 255,0,0,255,255,255,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0, + 255,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,255, + 0,0,0,0,255,0,255,0,0,0,255,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255, + 0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,0,0,255, + 0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0, + 0,0,255,0,255,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,255,0,255,0,0,255,0,127, + 255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0, + 255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,255,0,0,0,0,0,255,0,0,0,255, + 0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,255, + 0,0,0,255,0,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0,0,0,255,0,0,255,0,0,0, + 255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255, + 0,0,0,255,0,0,0,0,255,0,255,0,0,0,255,0,0,0,255,0,0,255,0,0,0,0,255,0,255, + 0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,0,0,255,0,0,0,255,255, + 255,0,0,255,0,0,255,0,127,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0, + 0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,255, + 255,255,255,0,0,0,255,255,255,0,0,255,255,255,255,255,0,255,255,255,255, + 255,0,255,255,255,255,255,0,255,255,255,255,255,0,255,255,255,0,255,255, + 255,0,255,255,255,0,255,255,255,0,255,255,255,255,0,0,0,255,0,0,0,0,255, + 0,0,0,255,255,255,0,0,0,0,0,255,255,255,0,0,0,0,0,255,255,255,0,0,0,0,0, + 255,255,255,0,0,0,0,0,255,255,255,0,0,0,0,255,0,0,0,255,0,255,0,255,255, + 255,0,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255, + 0,0,0,255,255,255,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,255,0,0,127,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127,127, + 127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127, + 127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,0,127, + 127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127, + 0,127,127,127,0,127,127,127,0,127,127,127,0,127,127,127,127,127,127,0,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127, + 127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127, + 127,0,127,127,127,127,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,127,0,255,0,0,0,0,0,0,255,0,0,0,255,0,0,255,255,0,255,0, + 0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0, + 0,255,0,0,0,0,0,0,0,255,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,255,255,0,255, + 0,0,255,0,0,0,0,0,0,255,0,0,0,255,0,0,255,255,0,255,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,255, + 0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,255, + 0,0,0,0,255,0,0,0,255,0,255,0,255,0,255,255,0,0,255,0,255,0,0,255,0,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,255,0,255,0,0,255,0, + 255,0,0,255,0,255,0,255,0,255,255,0,255,0,0,255,255,0,255,0,255,255,0,0, + 0,255,0,0,0,0,255,0,0,0,255,0,255,0,255,0,255,255,0,255,0,0,255,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,255,0,255,0,0,255,0,255,0, + 0,0,255,0,0,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,127,0,255,255,0,0,0,255,255,0,0,0,255,255,0,0,0,255,255,0,0,0,255, + 255,0,0,0,255,255,0,0,255,255,255,0,255,255,0,0,0,255,255,0,0,255,255,0, + 0,0,255,255,0,0,0,255,255,0,0,0,255,255,0,0,0,255,0,255,0,0,255,0,0,255, + 0,0,0,0,255,0,255,255,255,0,0,0,255,255,0,0,0,255,255,0,0,0,255,255,0,0, + 0,255,255,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,255,0,0,255, + 0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,0,255,0,255,255,255, + 0,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,255,0,0,0, + 0,255,0,0,0,0,255,0,0,0,0,255,0,0,0,0,255,0,0,0,0,255,0,0,0,0,255,0,0,255, + 0,255,0,0,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,0,255, + 0,255,0,0,255,0,0,255,0,0,255,255,255,0,255,0,0,255,0,255,0,0,255,0,255, + 0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,0,255,255,255,255,255, + 0,255,0,0,255,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255, + 0,0,255,0,255,0,0,255,0,0,255,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,127,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255, + 0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,255,255,255,0,255,0,0,0, + 255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0, + 0,255,0,255,0,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0, + 255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,0,0,0,0,0,0,0,255, + 0,255,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,0, + 255,0,255,0,0,255,0,0,255,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,127,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0, + 255,0,255,0,0,255,0,255,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0, + 0,255,0,0,0,0,255,0,0,0,0,0,255,0,255,0,0,255,0,0,255,0,255,0,0,255,0,255, + 0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,255,0, + 0,255,0,0,0,0,255,0,0,0,255,255,0,0,255,0,255,0,0,255,0,255,0,0,255,0,255, + 0,0,255,0,255,0,0,255,0,0,255,0,255,0,0,255,0,0,255,0,0,255,0,255,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,255,255,255,0,0,255,255,255,0,0,255, + 255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,0,255, + 255,255,0,0,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0, + 255,255,255,0,0,255,0,255,0,0,255,0,0,255,0,0,255,255,0,0,255,0,0,255,0, + 0,255,255,0,0,0,255,255,0,0,0,255,255,0,0,0,255,255,0,0,0,255,255,0,0,0, + 0,0,0,0,0,0,0,255,255,255,0,0,0,255,255,255,0,0,255,255,255,0,0,255,255, + 255,0,0,255,255,255,0,0,0,255,0,0,0,255,255,255,0,0,0,0,255,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127,127,0,127,127,127,127,0,127,127, + 127,127,0,127,127,127,127,0,127,127,127,127,0,127,127,127,127,0,127,127, + 127,127,127,127,127,0,127,127,127,0,127,127,127,127,0,127,127,127,127,0, + 127,127,127,127,0,127,127,127,127,0,127,127,0,127,0,127,127,0,127,127,0, + 127,127,127,127,0,127,127,127,127,0,127,127,127,127,0,127,127,127,127,0, + 127,127,127,127,0,127,127,127,127,0,127,127,127,127,0,127,127,127,127,127, + 127,0,127,127,127,127,127,0,127,127,127,127,0,127,127,127,127,0,127,127, + 127,127,0,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,0,127, + 127,127,127,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; + + +// Normal font +const int FONT1_BM_W = 253; +const int FONT1_BM_H = 106; +static const unsigned char s_Font1[] = +{ + 127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,255, + 0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,255,0,0,0,255,0,255,0,0,0,0, + 0,255,0,255,0,0,0,0,0,255,0,0,0,0,255,255,0,0,0,0,255,0,0,0,0,0,255,255, + 255,0,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,255,0,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,255,255,255,0,0,0,0,0, + 255,0,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,0,0,0,255,0,0,255, + 255,255,255,255,255,0,0,0,255,255,255,0,0,255,255,255,255,255,255,0,0,255, + 255,255,255,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,127,0,0,0,0,0,0,255,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,255,255, + 255,0,0,255,0,0,255,0,0,255,0,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255, + 0,0,0,0,255,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,0,0,255,0,0,0,0,255,0,0,255,255,255,0,0,0,255,0,0,0,0,255,0, + 255,0,0,0,0,255,0,0,0,0,255,255,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0, + 0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,127,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255, + 0,0,255,0,255,0,255,0,255,0,0,255,0,0,255,0,0,0,0,0,255,0,0,0,255,0,0,0, + 0,0,0,0,255,0,0,0,0,0,0,255,0,0,255,0,255,0,255,0,0,0,0,255,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0, + 0,0,255,0,0,0,0,0,0,255,0,0,0,255,0,255,0,0,255,0,0,0,0,0,0,255,0,0,0,0, + 0,0,0,0,0,0,255,0,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,0,255,0,0,0,255, + 0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,255,0,255, + 0,0,0,0,255,0,255,0,0,0,255,0,0,255,0,255,0,0,0,0,0,0,0,255,0,255,0,0,0, + 0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,0, + 0,255,0,0,0,0,0,0,255,0,0,255,0,0,255,0,0,255,255,255,255,255,0,0,255,255, + 255,255,255,0,0,0,0,0,0,255,0,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,0,255, + 0,0,0,255,0,0,0,0,0,0,255,255,0,0,0,0,255,255,255,255,255,255,0,0,0,0,255, + 255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,255,0,0, + 0,0,0,0,0,0,0,0,255,0,255,0,0,0,0,0,255,255,0,0,0,0,255,255,0,0,255,0,0, + 255,255,0,0,0,255,255,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0, + 0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0, + 255,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,255,255,255,0,0,255,0,0,0,255, + 0,0,0,0,0,0,0,255,0,255,0,0,0,0,255,0,0,0,0,255,0,0,0,0,255,255,255,255, + 0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,255,255,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0, + 0,0,0,0,255,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,255,255,0, + 0,0,0,0,0,0,255,0,255,0,0,255,0,255,0,0,255,0,0,255,0,0,0,0,0,255,0,0,0, + 0,0,0,255,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,0,0,0,0,0,255,255, + 255,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,255,255, + 0,0,0,0,0,0,0,0,255,0,255,255,255,255,255,255,0,0,0,0,0,0,255,0,255,0,0, + 0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,255,255,255,255,255,0,0,0, + 0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0, + 0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,255,0,0,0,0, + 0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,255,0,0,255, + 0,255,0,0,0,255,255,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0, + 0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0, + 0,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,255, + 0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,255,0,0, + 0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0, + 0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,255,0,255,0,0,0,0,0,255,0,255,0,255,0,0,0,0,0,255,0,0,255,0,0,255,0,255, + 0,0,0,255,255,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255, + 0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,0, + 255,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,255,0,0,255,0,0,0,0, + 255,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,255,0, + 0,0,255,0,0,0,255,0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,255,0,0,0,0,0, + 0,0,0,0,255,0,255,0,0,0,0,0,0,255,255,255,0,0,0,0,0,255,0,0,0,0,255,255, + 0,0,0,255,255,255,0,0,255,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0, + 0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,255,255,255, + 255,0,0,0,255,255,255,255,255,0,255,255,255,255,255,255,0,0,255,255,255, + 255,0,0,0,0,0,0,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255, + 0,0,0,0,0,0,255,255,255,255,0,0,0,255,255,255,0,0,0,0,255,0,0,0,255,0,0, + 0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,255,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0, + 0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0, + 0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127,127,0, + 127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,0,127,127,127,127,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,0,127,127,127,0,127,127,127,0,127,127,127,127,0,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,0,127,127,127, + 127,0,127,127,127,0,127,127,127,127,0,127,127,127,127,127,127,0,127,127, + 127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127, + 127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127, + 0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127, + 127,0,127,127,0,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127, + 127,127,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,255,0,0,0,0,0,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,255, + 255,255,255,0,0,0,0,0,0,0,255,0,0,0,0,255,255,255,255,255,0,0,0,0,255,255, + 255,255,0,255,255,255,255,255,0,0,0,255,255,255,255,255,255,0,255,255,255, + 255,255,0,0,0,255,255,255,255,0,0,255,0,0,0,0,0,255,0,255,255,255,0,0,255, + 255,255,0,255,0,0,0,0,255,0,255,0,0,0,0,0,255,255,0,0,0,0,255,255,0,255, + 255,0,0,0,0,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,255,0,0,0,0, + 255,255,255,255,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,255,255, + 255,255,255,255,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0, + 0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,255,255,255, + 255,255,0,0,255,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,255,255,0,0,0,0,255,255,0,0, + 0,0,255,0,255,0,0,0,255,0,0,0,0,255,0,0,255,0,0,0,0,0,255,0,0,0,0,255,0, + 0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,255,0,255,0,0,0,0,0,255,0, + 0,255,0,0,0,0,0,255,0,255,0,0,0,255,0,0,255,0,0,0,0,0,255,255,0,0,0,0,255, + 255,0,255,255,0,0,0,0,255,0,0,255,0,0,0,0,255,0,0,255,0,0,0,0,255,0,0,255, + 0,0,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0,0,0,255,0,0,0,0,255,0,0,0,0,255, + 0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,255,0,0,0,0,255,0,0,255, + 0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0,255,0,0,0, + 0,0,0,255,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,127,0,255,0,255,255,255,255,0,255,0,0,0,0,255,0,255,0,0,0,255,0,0, + 0,0,255,0,255,0,0,0,0,0,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,0,0, + 0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,255,0,0,0,0,0,255,0,255,0,0, + 255,0,0,0,255,0,0,0,0,0,255,0,255,0,0,255,0,255,0,255,0,255,0,0,0,255,0, + 255,0,0,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,255,0,0,0, + 255,0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,255,0,0,255,0,0, + 0,255,0,0,0,255,0,0,255,0,255,0,0,255,0,0,0,255,0,0,255,0,0,0,255,0,0,0, + 255,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,255,0,0, + 0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,255,0,255,0,0, + 0,255,0,0,255,0,0,0,255,0,255,0,0,0,255,0,0,0,0,255,0,255,0,0,0,0,0,0,255, + 0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0, + 0,0,0,255,0,0,255,0,0,0,0,0,255,0,255,0,255,0,0,0,0,255,0,0,0,0,0,255,0, + 255,0,0,255,0,255,0,255,0,255,0,0,0,255,0,255,0,0,0,0,0,0,255,0,255,0,0, + 0,0,255,0,255,0,0,0,0,0,0,255,0,255,0,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0, + 255,0,0,0,0,255,0,0,0,0,0,255,0,0,255,0,0,0,255,0,0,0,255,0,0,255,0,255, + 0,0,255,0,0,0,0,255,255,0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,0,0,0,255, + 0,0,0,0,255,0,0,0,0,0,0,255,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,127,255,0,255,0,0,0,255,0,0,255,0,0,255,0,0,0,255, + 0,0,255,255,255,255,255,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,255,0,255,255, + 255,255,255,255,0,255,255,255,255,255,0,255,0,0,0,255,255,255,0,255,255, + 255,255,255,255,255,0,0,255,0,0,0,0,0,255,0,255,255,0,0,0,0,0,255,0,0,0, + 0,0,255,0,255,0,0,255,0,255,0,255,0,0,255,0,0,255,0,255,0,0,0,0,0,0,255, + 0,255,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,255,255,255,255,0,0,0,0,255,255, + 255,255,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,255,0,0,255,0,0,0,255,0,0,0, + 255,0,0,255,0,255,0,0,255,0,0,0,0,255,255,0,0,0,0,0,0,255,0,0,0,0,0,0,255, + 0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,255,0,255,0,0,0,255,0,0,255,0,0,255, + 0,0,0,255,0,0,255,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,0,0,0,0,255,0,255, + 0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,255, + 0,0,0,0,0,255,0,255,0,255,0,0,0,0,255,0,0,0,0,0,255,0,0,255,255,0,0,255, + 0,255,0,0,0,255,0,255,0,255,0,0,0,0,0,0,255,0,255,255,255,255,255,0,0,255, + 0,0,0,0,0,0,255,0,255,0,0,255,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,255, + 0,0,0,0,0,255,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,0, + 255,255,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0, + 0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,127,255,0,255,0,0,0,255,0,0,255,0,0,255,255,255,255,255,0,0,255,0,0,0, + 0,255,0,255,0,0,0,0,0,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,0,0,0, + 0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,255,0,0,0,0,0,255,0,255,0,0, + 255,0,0,0,255,0,0,0,0,0,255,0,0,255,255,0,0,255,0,255,0,0,0,255,0,255,0, + 255,0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,255,0,0,0,255, + 0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,255,0,0,0,255,0,255, + 0,0,0,0,0,255,255,0,0,0,255,255,0,0,0,0,255,0,0,255,0,0,0,0,0,255,0,0,0, + 0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,255,0,255,255,255,255, + 255,255,0,0,255,0,0,0,0,0,255,0,255,0,0,0,0,255,0,0,255,0,0,0,0,0,255,0, + 0,0,0,255,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,255,0,255,0,0, + 0,0,0,255,0,0,255,0,0,0,0,0,255,0,255,0,0,0,255,0,0,255,0,0,0,0,0,255,0, + 0,0,0,0,0,255,0,255,0,0,0,0,255,255,0,0,255,0,0,0,0,255,0,0,255,0,0,0,0, + 0,0,0,255,0,0,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0,0,0,255,0,0,0,0,255, + 0,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0, + 0,0,0,255,0,0,255,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0, + 255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,127,0,255,255,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,255,255,255, + 255,255,0,0,0,0,255,255,255,255,0,255,255,255,255,255,0,0,0,255,255,255, + 255,255,255,0,255,0,0,0,0,0,0,0,255,255,255,255,255,0,255,0,0,0,0,0,255, + 0,255,255,255,0,255,255,255,0,0,255,0,0,0,0,255,0,255,255,255,255,255,0, + 255,0,0,0,0,0,0,255,0,255,0,0,0,0,255,255,0,0,0,255,255,255,255,0,0,0,255, + 0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,255,0,0,0,0,255,0,0,255,255,255,255, + 0,0,0,0,0,255,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0, + 0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,0,255,0,0,0,0,255,255,255,255,255, + 255,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,255,255,255,255,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,255,0,0, + 255,255,255,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,127,127,127,127,127,127,127,127,127,127,0,127,127,127, + 127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127, + 0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127, + 0,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,0,127, + 127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127, + 127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127, + 127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127, + 127,0,127,127,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127, + 127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127, + 127,0,127,127,127,127,0,127,127,127,127,0,127,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,255, + 0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0, + 0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0, + 0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,255, + 0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,127,0,255,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0, + 0,0,0,255,0,0,255,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0, + 0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0, + 0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255, + 0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,255,255,255,0,0,255,0,255,255, + 255,0,0,0,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,0, + 0,255,255,255,255,0,255,255,255,255,255,0,255,0,255,255,255,0,0,255,0,255, + 255,0,255,0,0,0,255,0,255,0,255,255,255,255,0,255,255,255,0,0,255,0,255, + 255,255,0,0,0,255,255,255,255,0,0,255,0,255,255,255,0,0,0,255,255,255,255, + 255,0,255,0,255,0,0,255,255,255,0,255,255,255,255,0,255,0,0,0,0,255,0,255, + 0,0,0,255,0,255,0,0,0,255,0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,255,0,255, + 255,255,255,0,0,0,255,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0, + 0,0,0,0,0,0,255,0,255,255,0,0,0,255,0,255,0,0,0,0,0,255,0,0,0,0,255,0,255, + 0,0,0,0,255,0,0,255,0,0,255,0,0,0,0,255,0,255,255,0,0,0,255,0,255,0,0,255, + 0,255,0,0,255,0,0,255,0,255,0,0,0,255,0,0,0,255,0,255,255,0,0,0,255,0,255, + 0,0,0,0,255,0,255,255,0,0,0,255,0,255,0,0,0,0,255,0,255,255,0,0,255,0,0, + 0,0,0,255,0,0,0,255,0,0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,255,0,0,0,255, + 0,0,255,0,255,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,0,255,0,0, + 0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,255,0,255,0,0,0,0,255,0,255, + 0,0,0,0,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,0,255,0,0,255,0,0,0,0,255, + 0,255,0,0,0,0,255,0,255,0,0,255,0,255,0,255,0,0,0,255,0,255,0,0,0,255,0, + 0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0, + 0,0,255,0,255,0,0,0,255,0,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,255,0,255, + 0,0,0,255,0,255,0,255,0,255,0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,0,255, + 0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,255,255,0,0,0,255,0,0,0, + 255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0, + 0,255,255,255,255,0,255,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,0,0,255,0,255, + 255,255,255,255,255,0,0,255,0,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255, + 0,0,255,0,255,255,0,0,0,0,255,0,255,0,0,0,255,0,0,0,255,0,255,0,0,0,0,255, + 0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255, + 255,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,255,0,255,0,0,0,255,0,255,0,255, + 0,255,0,0,0,0,255,0,0,0,0,255,0,255,0,0,0,255,0,0,0,255,255,0,0,0,0,0,0, + 255,0,0,0,0,0,255,255,0,0,255,0,0,255,0,0,255,0,0,0,255,0,0,0,0,0,0,0,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,255,0,0,0,255,0,255,0, + 0,0,0,255,0,255,0,0,0,0,0,255,0,0,0,0,255,0,255,0,0,0,0,0,0,0,255,0,0,255, + 0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,255,0,255,0,255,0,0,0,255,0,255, + 0,0,0,255,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255, + 0,255,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,0,255,0,0,0,255,0,0,0,0,255,0, + 0,255,0,255,0,0,0,255,0,255,0,255,0,255,0,0,0,255,0,255,0,0,0,255,0,255, + 0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,255,0,0,0,255, + 255,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 0,0,0,0,0,0,255,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,0,255, + 255,0,255,0,0,0,0,255,0,0,255,0,0,255,0,0,0,255,255,0,255,0,0,0,0,255,0, + 255,0,0,255,0,255,0,0,255,0,0,255,0,255,0,0,0,255,0,0,0,255,0,255,0,0,0, + 0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,255,255,0,255,0,0, + 0,0,0,0,255,0,0,255,0,0,0,255,0,0,0,255,255,0,0,0,255,0,0,0,0,0,255,0,0, + 0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0, + 255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,255,255,255,255,0,255,255, + 255,255,255,0,0,0,255,255,255,255,0,0,255,255,255,0,255,0,0,255,255,255, + 255,0,0,0,255,0,0,0,255,255,255,0,255,0,255,0,0,0,0,255,0,255,0,0,255,0, + 255,0,0,0,255,0,255,0,255,0,0,0,255,0,0,0,255,0,255,0,0,0,0,255,0,0,255, + 255,255,255,0,0,255,255,255,255,255,0,0,0,255,255,255,0,255,0,255,0,0,0, + 255,255,255,0,0,0,0,255,255,0,0,255,255,255,0,255,0,0,0,255,0,0,0,0,0,255, + 0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,255,255,255,0,0,0,255, + 0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255, + 255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0, + 0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0, + 255,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127,127,127,0,127,127,127,127,127,0, + 127,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,127, + 0,127,127,127,127,127,127,0,127,127,127,0,127,127,127,127,127,127,0,127, + 127,127,127,127,127,0,127,0,127,127,0,127,127,127,127,127,0,127,0,127,127, + 127,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127, + 127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127, + 0,127,127,127,127,0,127,127,127,127,0,127,127,127,127,127,127,0,127,127, + 127,127,127,0,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127, + 0,127,127,127,127,127,0,127,127,127,127,0,127,127,127,127,127,0,127,127, + 127,127,0,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,127,127,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,0,0,255,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0, + 0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255,0,255,0,255, + 0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0,127,0,0,255, + 255,255,255,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,255, + 255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0, + 255,0,0,255,0,0,0,255,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,255,255,255,255, + 0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,255,255,255, + 255,255,255,255,255,255,0,255,255,255,255,255,255,0,0,0,255,255,255,255, + 255,255,255,255,255,0,0,0,255,255,255,255,255,255,255,255,255,0,255,0,0, + 0,255,0,255,0,255,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,255,0,255,255,0,0,0,255,255,255,0,255,0,0,0,255,0,0,255,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255, + 255,0,0,255,255,0,0,255,0,0,0,0,0,255,0,127,0,255,0,0,0,0,0,0,0,255,0,0, + 0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,255,255,0,0,255,255,255,255,255,0,0,0,0,0,0,0,0,255,0,0,255,0,0, + 255,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,255,0, + 0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,0,0, + 0,255,0,0,0,255,0,0,0,0,0,0,0,255,0,0,255,0,255,0,0,0,255,0,255,0,255,0, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 255,0,0,255,255,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,255,0,0,127,255,0,0,0,0, + 0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0, + 0,255,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,255,0,255,0,0,0,0,0,255, + 0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0, + 0,0,255,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255, + 0,255,0,255,0,0,255,255,255,0,0,255,0,0,0,0,255,255,255,255,0,255,255,255, + 0,0,0,0,255,0,0,0,0,0,0,0,255,0,255,255,255,255,0,0,255,0,0,0,255,0,0,127, + 255,255,255,255,255,255,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0, + 0,0,0,0,255,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,255, + 0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,255,0, + 0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,255,0,255,0,0,0,0,0,0,255,0,0,255,0,0, + 0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,255,0,255, + 0,0,0,127,255,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,255, + 255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0, + 0,0,0,0,0,0,0,0,255,255,0,0,255,0,0,255,255,0,0,0,255,255,0,0,0,255,255, + 255,255,0,0,0,255,0,0,0,255,0,0,0,0,0,255,255,255,255,255,0,0,0,255,0,0, + 0,0,0,0,0,255,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,255,0,0, + 0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0, + 0,0,0,0,0,0,255,0,255,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,255, + 0,0,0,255,0,0,0,0,0,255,0,0,0,0,127,255,255,255,255,255,255,0,0,0,255,0, + 0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,0,0,0,0,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,255, + 0,0,255,0,255,0,0,255,0,0,0,0,0,0,255,0,0,255,0,0,0,255,0,0,0,0,0,255,0, + 0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0, + 0,255,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,255,0,255,255,255,255,255,0,255,255,255,255,255,255,255,255,255, + 255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,255, + 0,255,0,0,0,0,255,255,255,255,255,0,0,0,255,0,0,0,0,0,0,0,255,0,0,255,0, + 0,0,0,0,0,255,0,0,0,0,127,255,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0, + 0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,255,0,255,0,0,255,0,0,0, + 0,0,0,255,0,0,0,255,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0, + 0,255,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,0,0, + 0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255, + 0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0, + 0,0,255,0,0,0,0,127,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,255,0, + 0,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,255,0,255,0,0,255,0,255, + 0,0,0,0,255,0,0,0,0,255,0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0, + 0,0,255,0,255,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,0, + 0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0, + 0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,255,0,0,0,0,0, + 0,0,255,0,0,0,0,127,0,0,255,255,255,255,0,0,0,255,255,255,255,255,255,255, + 255,255,0,0,255,0,0,0,255,0,0,0,0,0,255,0,255,0,0,255,0,0,255,0,0,255,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,255,0, + 0,0,255,255,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255, + 255,255,255,255,0,0,0,255,255,255,255,255,255,255,255,255,0,255,255,255, + 255,255,255,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,255,255,255, + 255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,0,0,0,0,0,0,0,0,255,255,255,255,0,255,255,255,255,0,0,0,255,255, + 255,255,255,255,255,255,255,0,255,255,255,255,0,0,0,0,255,0,0,0,0,127,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,255,0,0,0,0,0,255,0,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 127,127,127,0,127,127,0,127,127,127,127,127,127,0,127,127,127,127,0,127, + 127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127, + 127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127, + 127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127, + 127,0,127,127,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,127,127,0, + 127,127,0,127,127,0,127,127,127,127,0,127,127,127,127,0,127,127,127,127, + 0,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,127,0,127,127, + 127,127,0,127,127,127,127,0,127,127,127,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,127,127,127,127,0,127,127,127,127,0,127,127,127, + 127,127,127,127,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,255,0,0,0, + 0,0,255,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0, + 255,0,0,0,0,255,255,255,255,0,0,255,0,0,255,0,0,0,0,0,255,255,255,255,0, + 0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,0,0,0,255,255,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255,255,255, + 255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255,255,255,0,0,0,0,0,0, + 0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,255,255, + 255,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0, + 0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255, + 0,0,0,0,255,255,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0,255, + 0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255, + 255,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,255,0,0,0,255,0,0, + 0,0,0,0,0,0,0,255,255,0,0,0,255,0,0,0,0,0,0,255,255,0,0,0,0,255,0,0,0,0, + 0,0,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,127,0,0,0,0,0,255,0,0,0,0,255,255,255,255,0,0,255,0,0,0,0, + 0,255,0,0,0,0,255,0,0,0,255,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,0, + 0,0,0,0,0,255,0,0,255,255,0,0,255,0,0,0,0,255,255,255,0,0,0,255,0,0,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,255,255,255,0,0,255,0,0,0,0,0,0,0,0, + 0,0,255,0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,255,255,0,0,0,0,0, + 0,0,0,0,255,0,0,0,0,255,0,255,255,255,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,255,0,0,255,0,0,0,255,0,255,0,0,255,0,0,0,0,0,255,0,0,0,255,0,0,0, + 0,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,255,255,0,0,0,255,0,0,0,0,0,0,0,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,255,0,0, + 0,255,0,255,0,0,0,0,255,0,0,0,0,0,0,255,255,255,255,0,0,0,0,255,0,255,0, + 0,0,0,255,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,255,0,0,255, + 0,0,255,0,0,255,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255, + 0,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,255,0,0,0,0,0,0,255, + 0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,255,255,255,255,0,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0,255,0,0, + 0,0,255,0,0,255,0,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,255,0,255, + 0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 0,0,0,0,0,255,0,0,0,255,0,255,0,0,0,0,255,0,0,0,0,0,0,255,0,0,255,0,0,0, + 0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0, + 0,0,0,255,0,0,255,0,0,255,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 255,0,0,255,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255, + 255,255,255,0,0,255,255,255,255,0,0,255,255,255,0,0,0,0,0,0,0,0,0,255,0, + 0,0,0,255,0,0,255,255,255,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255,255,255, + 0,255,0,0,0,255,0,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0,255,255,0,0,0,0, + 255,0,0,255,0,255,255,255,0,0,0,0,0,0,255,0,255,0,0,255,255,0,0,0,255,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,255,0,0, + 0,255,0,255,0,0,0,255,255,255,255,255,0,0,0,255,0,0,255,0,0,0,255,255,255, + 255,255,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0, + 0,255,0,0,0,255,255,255,0,255,0,0,255,0,0,0,0,255,255,255,255,255,255,255, + 0,255,255,255,0,255,0,0,255,255,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255, + 0,0,0,0,255,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0, + 0,0,0,255,0,0,255,0,0,0,0,0,255,0,0,255,0,255,0,0,0,0,0,0,0,255,0,0,0,0, + 255,0,0,255,255,255,0,255,0,0,255,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,255,0,0,0,255,0,255,0,0,0,0, + 255,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,255, + 0,0,255,0,0,0,0,0,0,0,0,255,0,0,255,0,0,255,0,0,255,0,0,0,0,0,0,0,0,255, + 0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,255,0,0,255,0,0,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,0,0,0,0,255,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0,0,255,0,0,255,0,0,255,0,0,0,0,0, + 0,255,0,0,0,0,255,0,0,0,0,0,0,255,0,0,255,0,0,255,0,255,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,255,0,0,0,255,0,255, + 0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0, + 0,255,255,0,0,0,0,0,0,0,0,0,0,255,0,0,255,255,0,0,255,0,0,0,0,0,0,0,0,0, + 0,255,0,0,255,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,255,0,0,0,255,255,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255,255,0,0,0,0,255,0,255,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0,0,0,255,0,0,255, + 255,255,255,255,0,0,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,255,0,0,255,255,255, + 255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 0,0,0,0,0,255,0,0,0,0,255,255,255,255,0,255,255,255,255,255,255,0,0,0,0, + 0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,255, + 255,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0, + 0,0,0,0,255,255,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,255,0,0,0, + 0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,255,255,255,255,0,0,0,0,255, + 0,0,0,0,0,0,255,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,255,255, + 255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,255,0,255,0,0,0, + 0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0, + 0,0,255,0,255,0,0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 127,127,0,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127, + 0,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,0, + 127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,0,127,127,127,0,127,127,127,127,127,127,127, + 127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127, + 127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127, + 127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127, + 127,0,127,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127, + 0,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127, + 127,127,127,127,127,0,127,127,127,127,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,127,0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,255, + 0,0,0,0,0,255,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,255,0,0,0,0,255,255,0, + 0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,255,255,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255, + 255,0,0,0,0,0,0,0,255,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,127,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,255,0,0,0, + 255,0,255,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,255,0,0,255,0, + 0,0,255,0,0,255,0,0,0,255,0,0,0,255,0,0,255,0,0,255,255,0,255,0,0,0,0,0, + 0,0,0,0,0,255,0,255,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0, + 0,255,0,0,255,0,0,0,0,0,255,0,255,255,0,0,0,0,0,255,0,0,255,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,255, + 0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,255,0,0,0,0,0,0,0,255,0, + 0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0, + 0,0,0,0,0,0,255,255,255,255,255,255,255,0,0,0,255,255,255,255,0,255,255, + 255,255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255, + 255,255,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255, + 255,0,0,255,255,255,255,0,0,0,255,255,0,0,0,0,255,0,0,0,255,255,255,255, + 0,0,0,0,0,255,255,255,255,0,0,0,0,0,255,255,255,255,0,0,0,0,0,255,255,255, + 255,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255, + 0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255, + 0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,0,0,255,0,0,0, + 0,0,0,0,0,0,0,0,127,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255, + 0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,0, + 255,0,255,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,255, + 0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255, + 0,0,0,255,0,0,255,255,0,0,0,0,255,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0, + 255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0, + 0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,255,0,0,0,0,0,255,0,255,0,0,0, + 0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,255,0,0,0,255,0,0,255, + 0,0,0,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,127,0,0,255,0,255,0,0,0, + 0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255, + 0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,255, + 0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0, + 255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,255,0,255,0,255,0,0,0,255,0,255, + 0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,255,0,0,0, + 0,0,0,255,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,255, + 0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0, + 0,0,255,0,0,255,0,0,0,255,0,0,255,255,255,255,255,0,0,255,0,0,0,255,0,0, + 0,0,0,0,0,0,0,0,0,127,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0, + 255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0, + 0,255,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0, + 255,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0, + 0,255,0,0,0,0,255,0,255,0,255,0,0,0,255,0,255,0,0,0,0,0,0,255,0,255,0,0, + 0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,255,0,0,0,0,0, + 0,255,0,0,0,255,0,0,0,255,0,0,255,0,0,0,255,0,0,255,0,255,0,0,0,0,0,255, + 0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,0,255,0, + 255,0,0,0,255,0,0,0,0,255,0,255,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,127,0, + 255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255, + 0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,255,255,255,255, + 255,0,255,0,0,0,0,0,0,255,255,255,255,255,255,0,255,255,255,255,255,255, + 0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,0,255,0,0,0,255,0, + 0,0,255,0,0,0,255,0,0,255,255,255,255,0,0,255,0,255,0,0,255,0,0,255,0,255, + 0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,255,0,0,0, + 0,0,0,255,0,255,0,0,0,0,0,0,255,0,0,0,0,255,0,255,0,0,0,255,0,0,255,0,0, + 0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255, + 0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,255,0,0,0,0,255,0,255,0,0,0,255,0,0,0, + 0,0,0,0,0,0,0,0,127,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, + 255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255, + 255,255,255,255,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0, + 0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0, + 0,0,255,0,0,0,0,255,0,255,0,0,0,255,0,255,0,255,0,0,0,0,0,0,255,0,255,0, + 0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,255,0,0,0,0, + 0,0,255,0,0,0,0,0,255,0,0,0,0,255,0,0,255,0,0,0,255,0,255,0,0,0,0,0,255, + 0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,0,0,255, + 0,0,0,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,127,0,255, + 255,255,255,255,0,0,0,255,255,255,255,255,0,0,0,255,255,255,255,255,0,0, + 0,255,255,255,255,255,0,0,0,255,255,255,255,255,0,0,0,255,255,255,255,255, + 0,0,0,255,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0, + 0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255, + 0,0,0,255,0,0,0,0,255,0,255,0,0,0,255,0,255,0,255,0,0,0,0,0,0,255,0,255, + 0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,255,0,0,0,0,0,0,255,0,255,0,0,0, + 0,0,0,255,0,0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,0, + 255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,0,0, + 255,0,0,0,0,255,255,255,255,255,0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0, + 127,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0, + 0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,255,0,0,0,255,0,0, + 0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,255, + 0,0,0,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0, + 255,0,0,0,0,255,255,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255, + 0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,0,255,0,0, + 0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0, + 0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0, + 0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,127,255,0,0,0,0,0,255,0,255,0,0,0, + 0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255,0,0,0,0,0,255,0,255, + 0,0,0,0,0,255,0,255,0,0,0,0,255,255,255,255,255,0,0,0,255,255,255,255,0, + 255,255,255,255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255, + 255,0,255,255,255,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255, + 0,255,255,255,0,0,255,255,255,255,0,0,0,255,0,0,0,0,255,255,0,0,0,255,255, + 255,255,0,0,0,0,0,255,255,255,255,0,0,0,0,0,255,255,255,255,0,0,0,0,0,255, + 255,255,255,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255, + 255,255,255,0,0,0,0,0,255,255,255,0,0,0,0,0,255,255,255,0,0,0,0,0,255,255, + 255,0,0,0,0,0,255,255,255,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,0,0,255,0, + 255,255,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127,127,127,127, + 127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,0,127,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127, + 127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127, + 127,127,0,127,127,127,127,127,127,0,127,127,127,0,127,127,127,0,127,127, + 127,0,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127, + 127,0,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127, + 127,127,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,255,0,0,0,0,0,0,255,0,0, + 0,0,255,255,0,0,0,255,255,0,255,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,255,255,0,0, + 0,0,0,0,0,0,0,0,255,0,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0, + 255,0,0,255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,255,0,0,0,0,0,255,255,0,255, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0, + 0,255,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,255,0,0,0,0,255,0,0,0,0,255, + 0,0,255,0,255,0,255,255,0,0,0,255,0,0,255,0,0,255,0,0,255,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,255,0,0, + 0,255,0,0,255,0,0,0,255,0,255,0,255,0,255,255,0,255,0,0,255,0,255,0,0,0, + 255,0,255,255,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,255,0,0,0,255, + 0,255,255,0,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 255,0,0,0,0,0,0,255,0,0,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0,0,0,255,0, + 0,0,255,0,0,0,0,0,0,0,255,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 127,0,255,255,255,0,0,0,255,255,255,0,0,0,255,255,255,0,0,0,255,255,255, + 0,0,0,255,255,255,0,0,0,255,255,255,0,0,0,255,255,255,0,0,255,255,0,0,0, + 0,255,255,255,255,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255, + 255,255,0,0,0,255,255,255,255,0,0,0,255,0,255,0,0,255,0,0,255,0,0,255,255, + 0,255,0,0,255,0,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255, + 0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0, + 0,0,0,255,0,0,0,0,0,0,255,255,255,255,0,0,255,0,0,0,0,255,0,255,0,0,0,0, + 255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,255,0,255,0,255,255, + 255,0,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,255,0,0,0,0,0, + 255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255, + 255,0,0,255,0,0,255,0,0,0,0,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0, + 0,0,0,255,0,255,0,0,0,0,255,0,0,255,0,255,0,0,255,0,0,255,0,0,0,0,0,0,255, + 0,255,255,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255, + 0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,255, + 0,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255, + 0,255,0,0,0,255,0,255,255,0,0,0,255,0,255,0,0,0,255,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,127,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0, + 255,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,255,0,255,0,0,0,0,0,255,0,0,0,0, + 255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,0,255,0,255, + 0,0,255,0,0,255,0,0,255,255,255,255,255,0,255,0,0,0,0,255,0,255,0,0,0,0, + 255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0, + 255,0,0,0,0,0,0,0,0,0,0,255,0,0,0,255,0,255,0,255,0,0,0,0,255,0,255,0,0, + 0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,0,255,0,255,0,0,255,0,0,0, + 0,255,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,255,255,255,255,0,0, + 255,255,255,255,0,0,255,255,255,255,0,0,255,255,255,255,0,0,255,255,255, + 255,0,0,255,255,255,255,0,0,255,255,255,255,255,255,255,255,255,0,255,0, + 0,0,0,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255,255,255, + 255,255,255,0,255,255,255,255,255,255,0,0,255,0,255,0,0,255,0,0,255,0,255, + 0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255, + 0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,0,255,255,255,255,255, + 255,255,0,255,0,0,255,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255, + 0,0,0,0,255,0,255,0,0,0,0,255,0,0,255,0,255,0,0,255,0,0,0,0,255,0,0,255, + 0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,255,0,0,0,255,0,255,0,0,0,255,0,255, + 0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,255, + 0,0,0,0,0,0,255,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,0, + 0,255,0,0,0,0,0,0,0,255,0,255,0,0,255,0,0,255,0,255,0,0,0,0,255,0,255,0, + 0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0, + 0,0,0,255,0,255,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,255,0,255,0,0,0,255,0,255, + 0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,0,255, + 0,255,0,0,255,0,0,0,0,255,0,0,255,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,255, + 0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,255,0,255,0,0,0,255, + 0,255,0,0,0,255,0,255,0,0,0,255,255,0,0,0,255,0,255,0,0,0,0,0,255,0,0,0, + 0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,0,255,0,255, + 0,0,255,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0, + 255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0,255,0,0,0,0,255,0, + 0,0,0,0,255,0,0,0,0,0,255,0,0,0,255,0,0,255,0,0,0,255,255,0,255,0,0,0,255, + 255,0,255,0,0,0,255,255,0,255,0,0,0,255,255,0,0,0,255,0,0,0,255,0,0,0,0, + 255,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,255,255,255,255,0,0,255, + 255,255,255,0,0,255,255,255,255,0,0,255,255,255,255,0,0,255,255,255,255, + 0,0,255,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,0,255,255,255,255, + 0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255, + 255,255,255,0,0,0,255,0,255,0,0,255,0,0,255,0,0,255,255,255,255,0,0,255, + 0,0,0,0,255,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255, + 255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,0,0,0,255,0,0,0,0, + 0,255,255,255,255,0,0,0,0,255,255,255,0,255,0,0,255,255,255,0,255,0,0,255, + 255,255,0,255,0,0,255,255,255,0,255,0,0,0,255,0,0,0,255,255,255,255,255, + 0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0, + 0,255,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,0,0,0,0,255,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127, + 127,127,0,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127, + 127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,127,0,127, + 127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127, + 0,127,127,0,127,0,127,127,0,127,127,0,127,127,127,127,127,127,0,127,127, + 127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127, + 127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127, + 127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,127,0,127, + 127,127,127,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; + +// Normal font anti-aliased +const int FONT1AA_BM_W = 264; +const int FONT1AA_BM_H = 106; +static const unsigned char s_Font1AA[] = +{ + 127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0, + 59,241,97,206,166,0,0,0,0,0,0,0,0,0,0,0,0,0,168,34,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,251,89,0,0,89,255,125,89,255,125,0,0,0,0, + 7,199,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,166, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,138,225,21,59,238,42, + 206,125,0,0,0,0,7,199,34,89,166,0,0,0,0,168,34,0,0,0,175,255,255,166,0, + 0,7,202,89,0,0,0,0,59,245,255,251,89,0,0,0,59,238,34,0,12,232,89,0,0,89, + 247,34,0,59,245,206,199,124,255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,7,202,89,0,12,235,255,247,34,0,0,0,0,12,232,89,0,0,12,235, + 255,255,251,89,0,7,206,255,255,255,125,0,0,0,0,138,251,89,0,0,59,245,255, + 255,255,251,89,0,0,89,255,255,166,0,89,255,255,255,255,255,201,0,0,59,245, + 255,255,125,0,0,12,235,255,247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,255,255,255,247,34,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,127,0,0,0,0,0,138,225,21,59,238,34,175,125,0,0,0,0,59,192,0,172, + 89,0,0,59,245,255,255,251,89,89,247,34,12,228,34,0,138,166,0,0,0,0,12,235, + 125,0,175,225,21,0,0,59,238,34,0,138,201,0,0,0,0,175,166,0,0,0,89,255,201, + 0,0,0,0,0,0,7,202,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,215,21,0,175, + 166,0,138,201,0,0,7,206,255,251,89,0,0,59,192,0,0,138,247,34,59,192,0,0, + 89,251,89,0,0,59,245,251,89,0,0,59,241,89,0,0,0,0,0,89,247,34,0,0,0,0,0, + 0,0,7,206,166,0,7,206,125,0,89,247,34,7,206,166,0,138,225,21,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,12,232,89,0,0,0,0,0,0,0,0,0,0,0,175,166,0,0,0,0,0, + 0,0,89,125,0,0,175,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,138,225,21,12,206, + 21,175,125,0,0,89,255,255,255,255,255,255,166,59,241,89,168,34,138,125, + 89,225,21,7,202,89,12,228,34,0,0,0,0,12,232,89,0,138,201,0,0,0,12,206,21, + 7,202,89,0,0,0,0,59,215,21,59,245,206,199,124,255,125,0,0,0,0,7,202,89, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,166,0,12,232,89,0,59,238,34,0,0, + 0,59,241,89,0,0,0,0,0,0,59,241,89,0,0,0,0,59,241,89,0,12,232,132,241,89, + 0,0,59,241,89,0,0,0,0,7,206,125,0,0,0,0,0,0,0,0,89,247,34,0,12,232,89,0, + 12,232,89,59,241,89,0,59,241,89,0,138,247,34,0,0,138,247,34,0,0,0,0,0,12, + 235,247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,138,255,166,0,0,0,0,0,0,0,0,0,138, + 225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,138,225,21,0,0,0,0,0,0,0,0,0,172, + 89,59,192,0,0,59,238,34,168,34,0,0,89,247,34,12,228,34,138,166,0,0,0,0, + 0,0,138,251,159,247,34,0,0,0,0,0,0,59,238,34,0,0,0,0,7,202,89,0,0,7,199, + 34,0,0,0,0,0,0,7,202,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,202,89,0,59, + 241,89,0,59,241,89,0,0,0,59,241,89,0,0,0,0,0,0,89,247,34,0,0,0,0,138,201, + 0,7,206,125,59,241,89,0,0,59,245,255,255,251,89,0,12,235,255,255,255,125, + 0,0,0,0,7,206,166,0,0,0,175,251,89,138,201,0,59,241,89,0,12,235,125,0,138, + 247,34,0,0,138,247,34,0,0,0,59,245,247,34,0,0,0,0,7,206,255,255,255,255, + 255,255,125,0,0,0,0,138,255,201,0,0,0,0,0,0,89,251,89,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 127,0,0,0,0,0,138,201,0,0,0,0,0,0,0,0,0,12,206,21,138,125,0,0,7,206,255, + 247,34,0,0,0,175,255,255,166,59,215,21,175,255,255,125,0,0,138,171,206, + 166,0,175,201,0,0,0,0,89,201,0,0,0,0,0,0,175,125,0,0,0,0,0,0,0,0,12,235, + 255,255,255,255,255,255,125,0,0,0,0,138,255,255,251,89,0,0,0,0,0,59,215, + 21,0,59,241,89,0,59,241,89,0,0,0,59,241,89,0,0,0,0,0,12,235,166,0,0,0,138, + 255,255,125,0,175,201,0,59,241,89,0,0,0,0,0,0,175,247,34,59,241,89,0,89, + 247,34,0,0,0,89,247,34,0,0,0,89,255,255,255,125,0,12,235,166,0,59,245,125, + 0,0,0,0,0,0,0,0,0,0,0,175,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,89,251,89,0,0,7,206,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,89,201, + 0,0,0,0,0,0,0,12,235,255,255,255,255,255,225,21,0,0,0,175,255,251,89,0, + 0,0,0,0,175,125,89,225,21,59,238,34,89,225,21,12,235,166,175,166,0,0,0, + 0,89,201,0,0,0,0,0,0,175,125,0,0,0,0,0,0,0,0,0,0,0,7,202,89,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,138,166,0,0,59,241,89,0,59,241,89,0,0,0,59,241,89, + 0,0,0,0,12,235,166,0,0,0,0,0,0,59,241,97,206,255,255,255,255,255,125,0, + 0,0,0,0,59,241,89,59,238,34,0,12,235,125,0,0,12,235,125,0,0,0,12,232,89, + 0,59,245,125,0,89,255,255,232,241,89,0,0,0,0,0,0,0,0,0,0,0,0,59,245,247, + 34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,255,201,0,0,0,0,7,206,125,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,125,12,206,21, + 0,0,0,0,0,168,34,175,166,0,0,0,0,59,215,21,138,201,0,12,228,34,138,225, + 21,0,12,235,251,89,0,0,0,0,59,215,21,0,0,0,0,12,232,89,0,0,0,0,0,0,0,0, + 0,0,0,7,202,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,202,89,0,0,12,232,89,0, + 59,238,34,0,0,0,59,241,89,0,0,0,12,235,166,0,0,0,0,0,0,0,12,235,125,0,0, + 0,59,241,89,0,0,0,0,0,0,59,241,89,12,232,89,0,12,232,89,0,0,138,225,21, + 0,0,0,59,238,34,0,7,206,166,0,0,0,0,89,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,12,235,247,34,0,0,7,206,255,255,255,255,255,255,125,0,0,138,255,166,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,138,225,21,0,0,0,0, + 0,0,0,0,172,89,89,166,0,0,0,89,166,0,168,42,206,125,0,0,0,7,202,89,0,89, + 225,21,59,238,34,89,251,89,0,0,175,255,201,0,0,0,0,7,202,89,0,0,0,0,59, + 215,21,0,0,0,0,0,0,0,0,0,0,0,7,202,89,0,0,0,0,138,247,34,0,0,0,0,0,7,206, + 201,0,12,228,34,0,0,0,175,166,0,138,201,0,0,0,0,59,241,89,0,0,12,235,166, + 0,0,0,0,89,166,0,0,89,251,89,0,0,0,59,241,89,0,0,59,192,0,0,175,225,21, + 0,175,201,0,138,225,21,0,12,235,125,0,0,0,0,12,235,166,0,59,241,89,0,0, + 0,7,206,166,0,0,138,247,34,0,0,59,245,125,0,0,0,0,0,0,0,12,232,89,0,0,0, + 0,0,0,0,0,0,0,0,175,166,0,0,0,0,0,0,0,0,7,206,166,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 127,0,0,0,0,0,138,225,21,0,0,0,0,0,0,0,12,206,21,138,125,0,0,0,12,235,255, + 255,255,166,0,0,0,0,138,201,0,0,0,175,255,255,125,0,0,138,255,255,255,125, + 12,235,247,0,0,0,0,138,201,0,0,0,0,175,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,7,206,166,0,0,0,0,0,0,7,206,201,0,89,201,0,0,0,0,12,235,255,247, + 34,0,0,7,206,255,255,255,225,21,89,255,255,255,255,255,166,59,245,255,255, + 251,89,0,0,0,0,59,241,89,0,0,12,235,255,255,225,21,0,0,12,235,255,251,89, + 0,0,175,225,21,0,0,0,0,0,59,245,255,255,125,0,0,89,255,255,166,0,0,0,138, + 247,34,0,0,138,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,7,206,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,168,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,12,232,89,0,0,59,238,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,59,241,89,0,0,0,0,0,0,0,0,0,0,175,125,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,125, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,168,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89, + 255,125,89,255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,201,0,0,0,0, + 0,0,0,0,0,0,12,228,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,228,34,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 127,127,127,127,0,127,127,0,127,127,127,127,127,0,127,127,127,127,127,127, + 127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127, + 127,127,127,0,127,127,127,127,127,127,127,127,0,127,127,0,127,127,127,127, + 0,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127, + 127,127,0,127,127,127,0,127,127,127,127,0,127,127,127,0,127,127,127,127, + 0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127, + 127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,0, + 127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,255,255,125,138,166,0,0,0,89,255,255,247, + 34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,89,255,255, + 255,255,166,0,0,0,0,0,12,235,225,21,0,0,59,245,255,255,255,251,89,0,0,0, + 59,245,255,255,251,89,59,245,255,255,255,247,34,0,0,59,245,255,255,255, + 255,127,81,245,255,255,255,255,127,0,0,59,245,255,255,255,166,0,59,241, + 89,0,0,0,59,241,89,89,255,255,255,125,7,206,255,251,89,59,241,89,0,0,89, + 255,166,59,241,89,0,0,0,0,59,245,225,21,0,0,7,206,251,89,59,245,247,34, + 0,0,59,241,89,0,0,138,255,255,255,166,0,0,59,245,255,255,255,225,21,0,0, + 0,138,255,255,255,166,0,0,59,245,255,255,255,251,89,0,0,0,59,245,255,255, + 201,89,255,255,255,255,255,255,255,125,59,241,89,0,0,0,59,241,97,206,166, + 0,0,0,0,175,201,175,201,0,0,7,206,201,0,0,0,175,171,206,225,21,0,0,59,245, + 166,245,125,0,0,0,89,251,89,89,255,255,255,255,255,127,0,228,34,0,0,59, + 215,21,0,0,0,0,12,228,34,0,0,0,59,245,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,127,0,0,175,225,21,0,0,0,175,225,21,0,0,0,89,232,241,89,0,0,59, + 241,89,0,0,138,225,21,0,89,255,125,0,0,59,192,59,241,89,0,0,175,251,89, + 0,59,241,89,0,0,0,0,59,241,89,0,0,0,0,0,89,255,125,0,0,7,199,34,59,241, + 89,0,0,0,59,241,89,0,59,241,89,0,0,0,59,241,89,59,241,89,0,59,241,89,0, + 59,241,89,0,0,0,0,59,245,255,125,0,0,89,255,251,89,59,245,255,201,0,0,59, + 241,89,0,138,251,89,0,12,235,166,0,59,241,89,0,7,206,225,21,0,138,251,89, + 0,12,235,166,0,59,241,89,0,0,138,247,34,0,12,235,125,0,7,176,21,0,0,59, + 241,89,0,0,0,59,241,89,0,0,0,59,241,89,138,225,21,0,0,12,235,125,89,225, + 21,0,59,245,247,34,0,12,232,89,12,235,166,0,7,206,166,0,89,247,34,0,7,206, + 125,0,0,0,0,0,7,206,166,12,228,34,0,0,7,202,89,0,0,0,0,12,228,34,0,0,12, + 235,133,206,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,138,201,0,138, + 255,255,255,125,138,166,0,0,7,206,166,175,166,0,0,59,241,89,0,0,89,247, + 34,7,206,166,0,0,0,0,0,59,241,89,0,0,0,175,225,21,59,241,89,0,0,0,0,59, + 241,89,0,0,0,0,7,206,166,0,0,0,0,0,0,59,241,89,0,0,0,59,241,89,0,59,241, + 89,0,0,0,59,241,89,59,241,89,59,241,89,0,0,59,241,89,0,0,0,0,59,241,159, + 225,21,0,175,166,241,89,59,241,132,241,89,0,59,241,89,12,235,166,0,0,0, + 89,247,34,59,241,89,0,0,89,247,34,12,235,166,0,0,0,89,247,34,59,241,89, + 0,0,59,241,89,0,59,238,34,0,0,0,0,0,0,59,241,89,0,0,0,59,241,89,0,0,0,59, + 241,89,59,241,89,0,0,89,225,21,59,241,89,0,89,206,202,89,0,59,238,34,0, + 89,251,89,138,225,21,0,0,175,201,0,138,225,21,0,0,0,0,0,175,225,21,12,228, + 34,0,0,0,138,166,0,0,0,0,12,228,34,0,7,206,166,0,12,235,125,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,127,7,202,89,89,225,21,7,206,125,12,206,21,0,59,238, + 34,89,247,34,0,59,241,89,0,0,175,201,0,59,241,89,0,0,0,0,0,59,241,89,0, + 0,0,59,241,89,59,241,89,0,0,0,0,59,241,89,0,0,0,0,59,241,89,0,0,0,0,0,0, + 59,241,89,0,0,0,59,241,89,0,59,241,89,0,0,0,59,241,89,59,241,102,232,89, + 0,0,0,59,241,89,0,0,0,0,59,241,102,232,89,59,215,81,241,89,59,241,89,138, + 225,21,59,241,89,59,241,89,0,0,0,59,241,89,59,241,89,0,7,206,201,0,59,241, + 89,0,0,0,59,241,89,59,241,89,0,0,175,201,0,0,12,235,166,0,0,0,0,0,0,59, + 241,89,0,0,0,59,241,89,0,0,0,59,241,89,7,206,166,0,0,175,166,0,7,206,125, + 0,175,125,175,166,0,138,201,0,0,0,175,255,251,89,0,0,0,59,245,166,241,89, + 0,0,0,0,0,89,247,34,0,12,228,34,0,0,0,89,201,0,0,0,0,12,228,34,12,235,201, + 0,0,0,59,245,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,59,215,21,175,125, + 0,7,206,125,7,199,34,0,138,201,0,12,235,125,0,59,245,255,255,255,247,34, + 0,59,241,89,0,0,0,0,0,59,241,89,0,0,0,59,241,89,59,245,255,255,255,255, + 127,59,245,255,255,255,255,127,59,241,89,0,0,0,0,0,0,59,245,255,255,255, + 255,255,251,89,0,59,241,89,0,0,0,59,241,89,59,245,255,247,34,0,0,0,59,241, + 89,0,0,0,0,59,241,89,138,201,175,166,59,241,89,59,241,89,12,235,125,59, + 241,89,59,241,89,0,0,0,12,235,125,59,245,255,255,255,201,0,0,59,241,89, + 0,0,0,12,235,125,59,245,255,255,255,125,0,0,0,0,59,245,255,255,125,0,0, + 0,59,241,89,0,0,0,59,241,89,0,0,0,59,241,89,0,138,225,21,59,241,89,0,0, + 175,201,7,202,89,89,201,0,175,166,0,0,0,12,235,166,0,0,0,0,0,138,255,166, + 0,0,0,0,0,59,245,125,0,0,12,228,34,0,0,0,12,228,34,0,0,0,12,228,34,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,59,215,21,175,125,0,7, + 206,125,7,199,34,7,206,125,0,0,175,201,0,59,241,89,0,0,89,247,34,59,241, + 89,0,0,0,0,0,59,241,89,0,0,0,59,241,89,59,241,89,0,0,0,0,59,241,89,0,0, + 0,0,59,241,89,0,59,245,255,251,89,59,241,89,0,0,0,59,241,89,0,59,241,89, + 0,0,0,59,241,89,59,241,89,175,225,21,0,0,59,241,89,0,0,0,0,59,241,89,12, + 235,247,34,59,241,89,59,241,89,0,89,247,94,241,89,59,241,89,0,0,0,59,241, + 89,59,241,89,0,0,0,0,0,59,241,89,0,0,0,59,241,89,59,241,89,12,235,166,0, + 0,0,0,0,0,0,138,251,89,0,0,59,241,89,0,0,0,59,241,89,0,0,0,59,241,89,0, + 12,232,89,138,225,21,0,0,89,225,81,215,21,12,228,47,232,89,0,0,0,175,255, + 251,89,0,0,0,0,59,241,89,0,0,0,0,7,206,201,0,0,0,12,228,34,0,0,0,0,175, + 125,0,0,0,12,228,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 12,228,34,89,201,0,7,206,125,59,215,21,59,245,255,255,255,255,247,34,59, + 241,89,0,0,59,241,89,7,206,166,0,0,0,0,0,59,241,89,0,0,0,138,225,21,59, + 241,89,0,0,0,0,59,241,89,0,0,0,0,7,206,166,0,0,0,59,241,89,59,241,89,0, + 0,0,59,241,89,0,59,241,89,0,0,0,59,241,89,59,241,89,7,206,201,0,0,59,241, + 89,0,0,0,0,59,241,89,0,175,166,0,59,241,89,59,241,89,0,7,206,200,241,89, + 12,235,166,0,0,0,89,247,34,59,241,89,0,0,0,0,0,12,235,166,0,0,0,89,247, + 34,59,241,89,0,59,245,125,0,0,0,0,0,0,12,232,89,0,0,59,241,89,0,0,0,12, + 232,89,0,0,0,59,238,34,0,0,175,171,206,166,0,0,0,12,232,159,201,0,7,202, + 132,215,21,0,0,89,247,34,175,225,21,0,0,0,59,241,89,0,0,0,0,138,225,21, + 0,0,0,12,228,34,0,0,0,0,89,201,0,0,0,12,228,34,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,138,201,7,206,255,251,226,255,255,166,0, + 138,201,0,0,0,12,235,125,59,241,89,0,0,138,247,34,0,89,255,125,0,0,59,192, + 59,241,89,0,0,138,251,89,0,59,241,89,0,0,0,0,59,241,89,0,0,0,0,0,89,255, + 125,0,0,59,241,89,59,241,89,0,0,0,59,241,89,0,59,241,89,0,0,0,89,247,34, + 59,241,89,0,12,235,166,0,59,241,89,0,0,0,0,59,241,89,0,0,0,0,59,241,89, + 59,241,89,0,0,59,245,251,89,0,138,251,89,0,59,245,166,0,59,241,89,0,0,0, + 0,0,0,138,251,89,0,59,245,166,0,59,241,89,0,0,138,251,89,0,89,166,0,0,89, + 247,34,0,0,59,241,89,0,0,0,0,138,225,21,0,7,206,166,0,0,0,89,255,251,89, + 0,0,0,7,206,255,125,0,0,138,255,201,0,0,12,235,125,0,12,235,166,0,0,0,59, + 241,89,0,0,0,89,251,89,0,0,0,0,12,228,34,0,0,0,0,12,228,34,0,0,12,228,34, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,7,206,225,21,0, + 0,0,0,0,0,7,206,125,0,0,0,0,175,201,59,245,255,255,255,247,34,0,0,0,59, + 245,255,255,251,89,59,245,255,255,255,225,21,0,0,59,245,255,255,255,255, + 127,81,241,89,0,0,0,0,0,0,59,245,255,255,255,201,0,59,241,89,0,0,0,59,241, + 89,89,255,255,255,138,235,255,255,125,0,59,241,89,0,0,89,255,201,59,245, + 255,255,255,255,166,59,241,89,0,0,0,0,59,241,89,59,241,89,0,0,0,175,251, + 89,0,0,138,255,255,255,166,0,0,59,241,89,0,0,0,0,0,0,0,138,255,255,255, + 166,0,0,59,241,89,0,0,0,175,251,89,12,235,255,255,251,89,0,0,0,59,241,89, + 0,0,0,0,0,59,245,255,251,89,0,0,0,0,12,235,201,0,0,0,0,0,138,251,89,0,0, + 89,255,125,0,7,206,225,21,0,0,89,255,125,0,0,59,241,89,0,0,0,175,255,255, + 255,255,255,127,0,228,34,0,0,0,0,0,175,125,0,0,12,228,34,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,89,255,255,255,255,125,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,241,89,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12, + 228,34,0,0,0,0,0,89,201,0,0,12,228,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,138,255,255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,255,255,125,0,0,0,12,228, + 124,255,255,247,34,0,0,0,0,0,0,0,0,0,245,255,255,255,255,255,255,0,0,0, + 0,0,0,0,0,0,0,127,127,127,127,127,127,127,127,127,127,127,0,127,127,127, + 127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127, + 127,0,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127, + 127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,127,0,127,127,127,127,0,127,127,127,127,0,127,127,127,127,127,127, + 127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,0,127, + 127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,127,0,89,255,125,0,0,0,0,0,0,0,0,0,0,59,241,89,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,59,241,89,0,0,0,0,0,0,0,0,89,255,255,166,0,0,0,0,0, + 0,0,59,241,89,0,0,0,0,0,0,0,0,0,0,0,59,241,89,0,0,0,0,59,241,89,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,255,201,0,12,228, + 34,0,0,89,255,247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,89,255,255,255,255,255,255, + 255,255,255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,59,241,89,0,0,0,0,0,0,0,0, + 0,59,241,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,241,89,0,0,0,0,0,0,0,12,235, + 125,0,0,0,0,0,0,0,0,0,59,241,89,0,0,0,0,59,241,89,0,89,251,89,59,241,89, + 0,0,0,0,59,241,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,241,89,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,89,225,21,0,0,12,228,34,0,0,0,0,138,201,0,0,0,0,0,0,0,0,0,0,0,0, + 0,89,166,0,0,0,0,0,0,0,138,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,59,241,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,241,89,0,0,0,0,0, + 0,0,59,241,89,0,0,0,0,0,0,0,0,0,59,241,89,0,0,0,0,0,0,0,0,0,0,0,59,241, + 89,0,0,0,0,59,241,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,241,89,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,138,166,0,0,0,12,228,34,0,0,0,0,89,225,21,0,0,0,0,0,0,0,0,0, + 0,0,0,89,166,0,0,0,0,0,0,0,138,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0, + 0,0,7,206,255,255,255,125,0,59,241,194,255,251,89,0,0,7,206,255,255,201, + 0,12,235,255,255,251,89,0,12,235,255,251,89,7,206,255,255,247,34,0,12,235, + 255,255,251,89,59,241,194,255,255,125,0,59,241,89,89,255,251,89,59,241, + 89,0,138,251,89,59,241,89,59,241,159,255,255,125,89,255,255,166,0,59,241, + 194,255,255,125,0,0,0,12,235,255,247,34,0,59,241,194,255,255,125,0,0,12, + 235,255,255,251,89,59,241,159,255,201,0,138,255,255,247,34,206,255,255, + 255,166,59,241,89,0,59,241,97,206,166,0,0,12,235,125,175,201,0,7,206,166, + 0,7,206,133,206,225,21,0,89,255,255,166,0,0,12,235,125,138,255,255,255, + 255,166,0,0,138,166,0,0,0,12,228,34,0,0,0,0,89,225,21,0,0,0,0,0,0,0,0,0, + 0,0,0,89,166,0,0,0,0,0,0,0,138,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0, + 0,0,0,0,0,0,89,247,34,59,245,166,0,138,225,21,7,206,201,0,0,0,7,206,166, + 0,59,241,89,7,206,125,0,89,225,21,59,241,89,0,0,7,206,166,0,59,241,89,59, + 245,166,0,89,247,34,59,241,89,0,59,241,89,59,241,89,138,225,21,0,59,241, + 89,59,245,201,0,89,255,201,0,89,247,34,59,245,166,0,89,247,34,0,7,206,166, + 0,138,225,21,59,245,166,0,138,247,34,7,206,166,0,59,241,89,59,245,201,0, + 0,59,238,34,0,130,34,59,241,89,0,0,59,241,89,0,59,241,89,89,247,34,0,89, + 247,34,138,225,21,12,235,225,21,12,232,89,7,206,166,12,235,125,89,247,34, + 0,89,247,34,0,0,0,89,247,34,0,0,138,166,0,0,0,12,228,34,0,0,0,0,89,225, + 21,0,0,7,206,247,34,0,0,89,201,0,0,89,166,0,0,0,0,0,0,0,138,125,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,59,241,89,59,241,89,0,59,241,89, + 59,241,89,0,0,0,59,241,89,0,59,241,89,59,238,34,0,59,238,34,59,241,89,0, + 0,59,241,89,0,59,241,89,59,241,89,0,59,241,89,59,241,89,0,59,241,89,59, + 241,159,201,0,0,0,59,241,89,59,241,89,0,59,241,89,0,59,241,89,59,241,89, + 0,59,241,89,0,59,241,89,0,59,241,89,59,241,89,0,59,241,89,59,241,89,0,59, + 241,89,59,241,89,0,0,59,241,89,0,0,0,59,241,89,0,0,59,241,89,0,59,241,89, + 12,235,125,0,175,166,0,59,238,34,89,171,202,89,89,225,21,0,59,241,226,201, + 0,12,235,125,0,175,166,0,0,0,12,235,125,0,0,59,238,34,0,0,0,12,228,34,0, + 0,0,0,7,206,125,0,7,202,89,12,235,166,0,175,125,0,0,89,166,0,0,0,0,0,0, + 0,138,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,89,255,255,255,251, + 89,59,241,89,0,59,241,89,59,238,34,0,0,0,59,238,34,0,59,241,89,59,245,255, + 255,255,251,0,59,241,89,0,0,59,238,34,0,59,241,89,59,241,89,0,59,241,89, + 59,241,89,0,59,241,89,59,245,255,225,21,0,0,59,241,89,59,241,89,0,59,241, + 89,0,59,241,89,59,241,89,0,59,241,89,0,59,238,34,0,12,232,89,59,241,89, + 0,12,232,89,59,238,34,0,59,241,89,59,241,89,0,0,0,175,255,255,201,0,59, + 241,89,0,0,59,241,89,0,59,241,89,0,175,201,12,232,89,0,7,206,125,172,89, + 138,166,138,201,0,0,0,138,247,34,0,0,175,201,12,232,89,0,0,7,206,166,0, + 0,175,225,21,0,0,0,0,12,228,34,0,0,0,0,0,0,175,225,34,206,21,0,0,175,255, + 166,0,0,0,89,166,0,0,0,0,0,0,0,138,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0, + 0,0,0,0,59,241,89,0,59,241,89,59,241,89,0,59,238,34,59,241,89,0,0,0,59, + 241,89,0,59,241,89,59,238,34,0,0,0,0,59,241,89,0,0,59,241,89,0,59,241,89, + 59,241,89,0,59,241,89,59,241,89,0,59,241,89,59,241,97,206,201,0,0,59,241, + 89,59,241,89,0,59,241,89,0,59,241,89,59,241,89,0,59,241,89,0,59,241,89, + 0,59,241,89,59,241,89,0,59,241,89,59,241,89,0,59,241,89,59,241,89,0,0,0, + 0,0,59,245,125,59,241,89,0,0,59,241,89,0,59,241,89,0,59,238,124,225,21, + 0,0,175,176,206,21,59,215,187,125,0,0,59,245,255,201,0,0,89,247,124,225, + 21,0,0,138,225,21,0,0,0,59,241,89,0,0,0,12,228,34,0,0,0,0,12,235,125,0, + 0,0,0,0,0,0,0,0,0,0,0,89,166,0,0,0,0,0,0,0,138,125,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,127,0,0,0,0,0,0,0,89,247,34,0,89,251,89,59,241,89,0,175,201,0,7,206,201, + 0,0,0,7,206,166,0,138,251,89,7,206,166,0,7,199,34,59,241,89,0,0,7,206,166, + 0,138,251,89,59,241,89,0,59,241,89,59,241,89,0,59,241,89,59,241,89,12,235, + 166,0,59,241,89,59,241,89,0,59,241,89,0,59,241,89,59,241,89,0,59,241,89, + 0,7,206,166,0,138,225,21,59,241,89,0,138,225,21,7,206,166,0,89,251,89,59, + 241,89,0,0,89,125,0,12,232,89,12,232,89,0,12,12,235,125,0,175,251,89,0, + 7,206,255,125,0,0,0,89,255,201,0,7,206,247,34,0,7,206,166,59,245,125,0, + 7,206,255,125,0,0,59,241,89,0,0,0,0,0,138,166,0,0,0,12,228,34,0,0,0,0,89, + 225,21,0,0,0,0,0,0,0,0,0,0,0,0,89,166,0,0,0,0,0,0,0,138,125,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,127,0,0,0,0,0,0,0,0,175,255,255,232,241,89,59,245,255,255,247, + 34,0,0,12,235,255,255,201,0,59,245,255,200,241,89,0,12,235,255,251,89,0, + 59,241,89,0,0,0,12,235,255,200,241,89,59,241,89,0,59,241,89,59,241,89,0, + 59,241,89,59,241,89,0,59,245,201,59,241,89,59,241,89,0,59,241,89,0,59,241, + 89,59,241,89,0,59,241,89,0,0,12,235,255,247,34,0,59,245,166,255,247,34, + 0,0,59,245,255,166,241,89,59,241,89,0,0,59,245,255,255,166,0,0,138,255, + 255,125,0,89,255,255,166,241,89,0,0,138,247,34,0,0,0,59,245,125,0,0,138, + 225,21,7,206,225,21,0,138,251,0,0,138,247,34,0,0,175,255,255,255,255,166, + 0,0,138,166,0,0,0,12,228,34,0,0,0,0,89,225,21,0,0,0,0,0,0,0,0,0,0,0,0,89, + 255,255,255,255,255,255,255,255,255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,138,225,21,0,0,0,0,0,0,0,0,0,0,0,89,247,34,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,241, + 89,0,0,0,0,0,0,0,0,59,241,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,232,89,0,0,0,0,0, + 0,0,0,0,0,0,138,201,0,0,0,12,228,34,0,0,0,0,138,201,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,166,255,255,247,34,0,0,0,0,0,0,0,0,0,0,0,255,255,125,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,241,89,0, + 0,0,0,0,0,0,0,59,241,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,225,21,0,0,0,0,0,0,0, + 0,0,0,0,7,206,255,201,0,12,228,34,0,0,89,255,251,89,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127,127,127, + 127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127, + 127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127, + 0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,0,127,127, + 127,0,127,127,127,127,127,127,0,127,127,0,127,127,127,127,127,127,127,127, + 127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127, + 127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,0,127,127,127, + 127,127,0,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127, + 127,0,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127,0,127,127, + 127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127, + 127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,127,127,127,127,127,127,127,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,89,247,34,138,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,125,59,238,34,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 89,255,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,12,235,251,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,238,34,138,201,0,0, + 0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,199,34,0,0,0,0,0,7,199,34,0,0,0,0, + 138,255,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,251,89,0,0,138,255,251,97,206,201, + 0,0,138,251,102,235,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,89,255,201,12,228,34,0,0,0,0,0,0,0,0,0,0,0,0,7,206,166,12,232,89,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,166,12,235,127, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,175,255,255,255,225,21,59,245,255, + 255,255,255,255,125,0,0,0,0,0,0,0,7,206,255,247,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,7,199,34,0,0,0,0,0,7,199,34,0,0,0,138,225,21,175,166,0,0,175, + 255,255,166,0,0,7,202,89,0,0,0,0,0,0,0,0,0,0,59,245,255,255,201,0,0,0,0, + 0,0,0,0,59,245,255,255,255,255,255,255,255,255,125,0,59,245,255,255,255, + 255,255,125,0,0,89,255,255,255,255,255,225,21,59,245,255,255,255,255,255, + 125,0,0,0,59,245,255,255,255,255,255,125,7,206,166,0,0,175,171,206,166, + 89,247,34,0,175,201,59,241,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,12,228,34,175,255,125,0,0,89,255,255,255,125,175,251,89,89,255,125, + 0,7,206,255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,245,255,255, + 255,255,255,125,0,0,7,206,255,125,59,245,125,0,0,0,89,251,89,0,0,0,0,0, + 0,0,127,7,206,225,21,0,0,0,0,59,115,0,0,0,0,59,115,0,0,0,0,0,0,0,175,201, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,245,255,255,255,255,125,0,59,245, + 255,255,255,255,125,0,0,0,0,0,0,0,89,247,34,12,228,34,0,138,166,0,0,0,0, + 0,0,0,0,0,0,12,235,125,0,7,176,21,0,0,0,0,0,0,138,251,89,0,0,138,201,0, + 0,0,0,0,0,59,115,0,0,0,0,59,115,0,0,0,0,0,0,7,206,166,0,59,115,0,0,0,0, + 59,115,0,0,0,59,115,0,0,0,0,59,115,0,89,201,0,12,232,89,89,201,7,202,89, + 12,232,89,138,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,7,199,34,0,172,132,196,199,163,125,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,115,0,0,0,0,59,115,0,0,0,0,0,0,0,89,247, + 34,0,7,206,125,0,0,0,0,0,0,0,0,127,89,247,34,0,0,0,0,0,59,115,0,0,0,0,59, + 115,0,0,0,0,0,0,7,206,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,199, + 34,0,0,0,0,0,7,199,34,0,0,0,0,0,0,0,0,0,89,225,21,7,202,89,12,228,34,0, + 0,0,0,0,0,0,0,0,0,59,238,34,0,0,0,0,0,0,0,130,34,59,241,89,0,0,0,138,201, + 0,0,0,0,0,0,59,115,0,0,0,0,59,115,0,0,0,0,0,0,175,225,21,0,59,115,0,0,0, + 0,59,115,0,0,0,59,115,0,0,0,0,59,115,0,12,228,34,59,192,0,12,228,34,138, + 166,59,215,21,175,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,7,199,34,0,172,89,175,166,138,125,0,138,255,255,247,34, + 12,146,0,0,0,0,89,255,255,255,125,12,235,255,255,125,0,0,0,59,115,0,0,0, + 0,59,115,0,138,255,255,255,255,127,0,175,201,0,138,225,21,0,0,0,0,0,0,0, + 0,127,245,255,255,255,255,255,125,0,59,115,0,0,0,0,59,115,0,0,0,0,0,0,12, + 232,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,199,34,0,0,0,0,0,7,199, + 34,0,0,0,0,0,0,0,0,0,89,247,34,12,228,34,138,166,0,0,0,0,0,0,0,0,0,0,0, + 12,235,166,0,0,0,0,0,0,175,225,21,138,225,21,0,0,0,138,201,0,0,0,0,0,0, + 59,115,0,0,0,0,59,115,0,0,0,0,0,89,247,34,0,0,59,115,0,0,0,0,59,115,0,0, + 0,59,115,0,0,0,0,59,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,255,166, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,199,34,0,172, + 89,0,0,138,125,59,238,34,0,130,34,7,206,201,0,0,59,241,89,0,12,235,255, + 125,0,59,241,89,0,0,59,115,0,0,0,0,59,115,0,0,0,0,89,247,34,0,59,245,166, + 241,89,0,0,0,0,0,0,0,0,0,127,138,225,21,0,0,0,0,0,59,115,0,0,0,0,59,115, + 0,0,0,0,0,89,255,255,255,247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,199, + 34,0,0,0,0,0,7,199,34,0,0,0,0,0,0,0,0,0,0,175,255,255,166,59,215,21,175, + 255,255,125,0,89,255,255,201,0,0,0,59,245,255,255,125,0,12,235,166,0,0, + 138,225,21,0,0,0,138,255,255,255,255,247,34,0,59,115,0,0,0,0,59,115,0,0, + 0,0,59,245,125,0,0,0,59,115,0,0,0,0,59,115,0,0,0,59,115,0,0,0,0,59,115, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,245,255,251,102,0,255,255,255,255, + 255,0,245,255,255,255,255,255,255,255,255,255,255,127,21,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,59,241,89,0,0,0,0,0,138,247,34,138,201,0,0,0,175, + 201,0,0,0,175,166,0,0,59,115,0,0,0,0,59,115,0,0,0,12,235,125,0,0,0,138, + 255,166,0,0,0,0,0,0,0,0,0,0,127,245,255,255,255,255,225,21,0,59,115,0,0, + 0,0,59,115,0,0,0,0,0,0,89,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,7,199,34,0,0,0,59,245,255,255,255,255,125,0,0,0,0,0,0,0,0,0,0,0,0,175, + 125,89,225,21,59,238,47,232,89,7,206,125,0,0,0,0,0,138,251,89,12,235,166, + 0,0,138,225,21,0,0,0,138,201,0,0,0,0,0,0,59,115,0,0,0,0,59,115,0,0,0,7, + 206,201,0,0,0,0,59,115,0,0,0,0,59,115,0,0,0,59,115,0,0,0,0,59,115,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,245,255,251,89,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,255,255,201,0, + 0,0,138,247,34,175,201,0,0,0,138,255,255,255,255,255,166,0,0,59,115,0,0, + 0,0,59,115,0,0,7,206,166,0,0,0,0,59,241,89,0,0,0,0,0,0,0,0,0,0,127,89,251, + 89,0,0,0,0,0,59,115,0,0,0,0,59,115,0,0,0,0,0,0,138,201,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,7,199,34,0,0,0,0,0,7,199,34,0,0,0,0,0,0,0,0,0, + 0,0,0,0,59,215,21,138,201,0,12,228,47,228,34,0,175,166,0,0,0,0,0,12,232, + 89,0,0,175,225,21,59,241,89,0,0,0,138,201,0,0,0,0,0,0,59,115,0,0,0,0,59, + 115,0,0,0,138,225,21,0,0,0,0,59,115,0,0,0,0,59,115,0,0,0,59,115,0,0,0,0, + 59,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,255,166,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59, + 245,125,7,206,201,0,0,138,201,0,0,0,175,201,0,0,0,0,0,0,0,59,115,0,0,0, + 0,59,115,0,0,138,225,21,0,0,0,0,59,241,89,0,0,0,0,0,0,0,0,0,0,127,7,206, + 247,34,0,0,0,0,59,115,0,0,0,0,59,115,0,59,245,125,0,0,175,166,0,0,0,59, + 245,125,175,225,29,206,166,0,89,247,34,7,206,166,0,0,0,7,199,34,0,0,0,0, + 0,7,199,34,0,0,0,0,0,0,0,0,0,0,0,0,7,202,89,0,89,225,21,59,238,47,232,89, + 7,206,125,0,89,166,0,0,89,247,34,0,0,0,130,34,0,138,255,125,0,0,138,201, + 0,0,0,0,0,0,59,115,0,0,0,0,59,115,0,0,89,251,89,0,0,0,0,0,59,115,0,0,0, + 0,59,115,0,0,0,59,115,0,0,0,0,59,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,89,125,0,12,232,89,12,146,0,0,0,59,241,89,0,12,235,247, + 34,0,0,89,125,0,0,59,115,0,0,0,0,59,115,0,59,241,89,0,0,0,0,0,59,241,89, + 0,0,0,0,0,0,0,0,0,0,127,0,0,175,255,255,255,225,21,59,245,255,255,255,255, + 255,125,0,138,225,21,0,12,235,125,0,0,0,138,225,34,235,125,7,206,166,0, + 89,247,34,7,206,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 138,201,0,0,0,175,255,255,125,0,89,255,255,201,0,0,12,235,255,255,251,89, + 0,0,0,0,0,0,0,0,89,255,255,255,255,255,255,255,255,255,125,0,59,245,255, + 255,255,255,255,125,0,0,175,255,255,255,255,255,247,34,59,245,255,255,255, + 255,255,125,0,0,0,59,245,255,255,255,255,255,125,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,245,255,255,166,0,0,0,0,0,0,0,89,255,255, + 255,125,59,245,255,255,201,0,0,0,59,245,255,255,255,255,255,125,0,175,255, + 255,255,255,127,0,0,59,241,89,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,175,166,0,255,255,201,0,0,0,0,175,166,59,238,34,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,228,34,0,0, + 0,0,0,0,0,12,228,34,138,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127, + 127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127,0,127,127,127, + 127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127, + 127,127,0,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, + 127,127,0,127,127,127,127,127,127,127,0,127,127,127,0,127,127,127,127,127, + 127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,0, + 127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,127,127,0,127,127,0,127,127,0,127,127,127,127,0, + 127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,0,127,127, + 127,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127, + 127,0,127,127,127,127,127,127,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,127,127, + 0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,245,255,255,255,255,255, + 251,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,12,228,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,138,225,21, + 0,0,0,138,125,0,0,0,0,59,245,255,255,125,0,0,0,0,0,0,0,0,138,225,21,0,0, + 175,166,0,12,228,34,0,0,59,245,255,255,247,34,0,89,225,29,206,166,0,0,0, + 0,0,89,255,255,255,255,125,0,0,0,7,206,255,255,247,34,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,255,255,255,255,125,0,0,0,0,0,0,0, + 0,0,0,0,0,138,255,255,166,0,0,0,0,7,202,89,0,0,0,0,0,12,235,255,125,0,0, + 175,255,255,225,21,0,0,0,12,235,125,0,0,0,0,0,0,0,0,0,0,0,138,255,255,255, + 255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,228,34,0,0,89,255,255,225,21,0,0, + 0,0,0,0,0,0,0,0,0,138,166,0,0,0,89,225,21,0,0,0,0,0,138,166,0,0,0,89,225, + 21,0,0,0,12,235,255,255,166,0,0,7,206,125,0,0,0,0,0,0,89,247,34,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,138,225,21,0,0,0,138,125,0,0,0,12, + 235,125,0,59,115,0,0,0,0,0,0,0,0,7,206,125,0,59,215,21,0,12,228,34,0,12, + 235,125,0,0,168,34,0,0,0,0,0,0,0,0,0,0,175,225,21,0,0,0,175,225,21,0,0, + 0,0,0,138,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,225, + 21,0,0,0,175,225,21,0,0,0,0,0,0,0,0,0,59,238,34,7,206,125,0,0,0,7,202,89, + 0,0,0,0,7,199,34,59,238,34,0,0,0,7,202,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,89,255,255,255,125,175,125,0,0,0,0,0,0,0,0,0,0,0,0,0,138,255,247,34,0, + 59,241,89,0,175,201,0,0,0,0,0,0,0,0,0,7,206,255,166,0,0,12,232,89,0,0,0, + 0,7,206,255,166,0,0,12,232,89,0,0,0,0,0,0,0,59,215,21,0,89,201,0,0,0,0, + 0,0,0,89,247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,7, + 206,255,255,251,89,0,59,241,89,0,0,0,138,201,0,0,0,138,201,0,0,89,225,21, + 175,125,0,0,12,228,34,0,12,235,125,0,0,0,0,0,0,0,0,0,0,0,0,0,138,166,0, + 89,255,255,247,34,89,201,0,0,89,255,255,255,166,0,0,0,0,168,34,7,151,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,166,7,206,255,255,225,21,89,201,0,0,0, + 0,0,0,0,0,0,89,166,0,0,138,166,0,0,0,7,202,89,0,0,0,0,0,0,0,59,238,34,0, + 7,206,255,125,0,0,0,0,0,0,0,0,0,59,238,34,0,0,175,166,0,175,255,255,255, + 125,175,125,0,138,247,34,0,0,0,0,0,0,0,0,0,0,12,228,34,0,89,201,0,0,89, + 225,0,81,115,0,134,89,0,0,0,0,0,138,166,0,0,138,166,0,0,0,0,0,0,0,138,166, + 0,0,138,166,0,0,0,0,0,0,59,245,247,34,0,12,232,89,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,89,201,0,7,206,201,138,125, + 138,125,0,59,241,89,0,0,0,0,175,255,255,255,225,21,0,0,7,206,166,215,21, + 0,0,12,228,34,0,0,138,255,255,251,89,0,0,0,0,0,0,0,0,0,12,206,21,59,241, + 89,0,134,89,0,172,89,59,238,34,0,138,166,0,0,7,206,201,12,235,125,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,12,206,21,7,202,89,12,235,125,0,172,89,0,0,0,0, + 0,0,0,0,59,238,34,7,206,125,12,235,255,255,255,255,255,255,125,0,0,0,12, + 235,125,0,0,0,0,7,206,125,0,0,0,0,0,0,0,0,59,238,34,0,0,175,166,0,175,255, + 255,255,125,175,125,0,138,247,34,0,0,0,0,0,0,0,0,0,0,12,228,34,0,89,201, + 0,0,89,225,0,29,206,166,59,245,125,0,0,0,0,138,166,0,12,228,34,0,175,225, + 21,0,0,0,138,166,0,12,228,42,206,255,255,166,0,0,0,0,12,228,34,138,166, + 0,89,247,34,0,0,0,0,59,238,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0, + 0,0,138,201,0,59,241,89,138,125,0,0,59,245,255,255,255,125,0,0,138,166, + 0,89,201,0,0,0,0,89,255,125,0,0,0,0,0,0,0,7,206,125,0,138,251,89,0,0,0, + 0,0,0,0,0,89,166,0,138,201,0,0,0,0,0,89,166,59,215,21,0,175,166,0,59,245, + 125,89,251,89,0,0,12,235,255,255,255,255,255,255,125,138,255,255,251,89, + 127,166,0,7,202,89,12,232,89,0,89,166,0,0,0,0,0,0,0,0,0,138,255,255,166, + 0,0,0,0,7,202,89,0,0,0,0,0,59,241,89,0,0,0,0,0,7,206,125,0,0,0,0,0,0,0, + 0,59,238,34,0,0,175,166,0,89,255,255,255,125,175,125,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,12,228,34,0,59,241,89,0,175,201,0,0,0,175,201,7,206,201,0,0,0, + 138,166,0,175,166,0,138,200,215,21,0,0,0,138,166,0,175,166,7,151,0,89,247, + 34,0,0,0,59,238,47,228,34,59,219,209,34,0,0,0,89,255,125,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,138,225,21,59,238,34,138,125,0,0,0,59, + 241,89,0,0,0,0,138,166,0,89,201,0,0,59,245,255,255,255,255,125,0,0,0,0, + 0,59,238,34,0,7,206,125,0,0,0,0,0,0,0,0,89,166,0,138,201,0,0,0,0,0,89,166, + 0,175,255,255,223,166,0,12,235,125,59,241,89,0,0,0,0,0,0,0,0,0,175,125, + 0,0,0,0,0,138,125,0,7,206,255,255,125,0,0,59,157,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,7,202,89,0,0,0,0,7,206,255,255,255,166,7,206,255,255,201,0, + 0,0,0,0,0,0,0,0,59,238,34,0,0,175,166,0,0,89,255,255,125,175,125,0,0,0, + 0,0,0,0,0,0,0,0,0,0,89,255,255,251,89,0,89,255,255,225,21,0,0,0,175,225, + 29,206,166,0,0,0,138,166,59,215,21,59,215,81,215,21,0,0,0,138,166,59,215, + 21,0,0,0,89,225,21,59,245,255,255,125,138,166,7,202,97,199,34,0,0,89,251, + 89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,138,225,21,59,241, + 89,138,125,0,0,0,89,247,34,0,0,0,0,175,255,255,255,225,21,0,0,0,12,232, + 89,0,0,0,12,228,34,0,12,235,225,21,59,215,21,0,0,0,0,0,0,0,0,12,206,21, + 59,241,89,0,134,89,0,172,89,0,0,0,0,0,0,0,0,7,206,201,12,235,125,0,0,0, + 0,0,0,0,0,175,125,0,0,0,0,0,12,206,21,7,202,89,7,206,125,0,172,89,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,202,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,59,238,34,0,0,175,166,0,0,0,0,175,125,175,125,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,166,59,245,125,0,0,0,0,0,0, + 175,125,12,228,34,59,215,21,0,0,0,0,0,175,125,0,0,0,12,232,89,0,0,0,0,0, + 59,238,34,175,125,7,199,34,0,0,175,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,127,0,0,0,0,0,138,225,21,7,206,201,138,125,138,125,7,202,89,0,0,0, + 0,138,201,0,0,0,138,166,0,0,0,12,232,89,0,0,0,12,228,34,0,0,0,175,255,255, + 166,0,0,0,0,0,0,0,0,0,0,138,166,0,89,255,255,247,34,89,201,0,0,0,0,0,0, + 0,0,0,0,0,168,34,7,151,0,0,0,0,0,0,0,0,175,125,0,0,0,0,0,0,138,166,7,202, + 89,0,89,247,124,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,255,255,255,255, + 255,255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,245,125,0,7,206, + 166,0,0,0,0,175,125,175,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,59,115,0,134,89,0,0,0,0,0,0,59,215,21,59,245,255,255,255,225,21,0, + 0,0,59,215,21,0,0,59,238,34,0,0,0,0,0,0,175,125,7,206,255,255,255,251,89, + 0,138,247,34,0,59,157,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,138,225, + 21,0,7,206,255,255,251,89,138,255,255,255,255,255,166,0,0,0,0,0,0,0,0,0, + 0,12,232,89,0,0,0,12,228,34,0,0,0,0,0,59,241,89,0,0,0,0,0,0,0,0,0,0,175, + 225,21,0,0,0,175,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,175,225,21,0,0,0,175,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,238,198, + 255,251,194,166,0,0,0,0,175,125,175,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,125,0,0,0,0,89,225,21,0,0,0, + 7,206,125,0,0,12,235,255,255,255,166,0,0,0,89,225,21,0,0,0,12,228,34,0, + 0,0,175,255,255,255,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0, + 0,0,0,0,138,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,228, + 34,0,7,176,21,0,89,247,34,0,0,0,0,0,0,0,0,0,0,0,89,255,255,255,255,125, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89, + 255,255,255,255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,238,34,0,0,0,0,0,0,0,0,175, + 125,175,125,0,0,0,0,0,0,0,0,59,215,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0, + 0,0,0,0,0,0,0,138,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 12,228,34,0,7,206,255,255,251,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,238,34,0,0,0,0,0,0,0,0,175,125,175,125, + 0,0,0,0,0,0,59,245,251,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127,0,127,127, + 127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,0,127,127,127,127, + 127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127, + 127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,127,0,127,127,127,127,0,127,127,127,127,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127, + 0,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127, + 127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,0,127,127,127,127,0,127,127,127,127,127,127,0,127, + 127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,127,127,127,0, + 127,127,127,127,127,127,127,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,89, + 255,125,0,0,0,0,0,0,12,235,201,0,0,0,0,12,235,251,89,0,0,0,0,175,255,125, + 89,201,0,0,0,0,0,0,0,0,0,0,0,59,245,247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,89,255,125,0,0,0,0,0,0,138,251,89,0,0,0,12,235,251, + 89,0,0,0,0,0,0,0,0,7,206,225,21,0,0,0,89,255,125,0,89,255,225,21,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,247,34,172,89,0,0,0,0,7,206,225,21,0,0, + 0,0,0,0,0,89,255,125,0,0,0,0,0,0,89,255,225,21,0,0,0,0,12,235,247,34,172, + 89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89, + 255,125,0,0,0,0,0,0,0,7,206,225,21,0,0,0,0,89,255,225,21,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,89,255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0, + 0,89,247,34,0,0,0,0,0,175,166,0,0,0,0,7,206,125,59,241,89,0,0,89,201,12, + 235,247,34,0,0,7,206,166,59,241,89,0,0,12,228,34,59,215,21,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,238,34,0,0,0,0,89,247,34,0,0,0,7, + 206,125,59,241,89,0,7,206,166,59,238,34,0,0,175,166,0,0,59,241,89,0,89, + 247,34,138,201,59,238,34,138,201,0,0,0,0,0,0,0,0,0,0,0,175,125,89,255,201, + 0,0,0,0,0,0,0,175,201,0,0,0,0,0,0,12,232,89,0,0,0,0,0,0,59,238,34,138,225, + 21,0,0,0,175,125,89,255,201,0,0,0,0,59,238,34,138,201,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,247,34,0,0,0,0,0,0,138,201,0,0,0,0, + 0,59,238,34,138,225,21,0,0,0,59,238,34,138,201,0,0,0,0,12,232,89,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,228,34,59,215,21,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,255,255,125,0, + 0,0,0,127,0,0,12,235,225,21,0,0,0,0,12,235,225,21,0,0,0,0,12,235,225,21, + 0,0,0,0,12,235,225,21,0,0,0,0,12,235,225,21,0,0,0,0,12,235,225,21,0,0,0, + 0,0,175,255,255,255,255,255,255,255,166,0,0,138,255,255,255,251,89,59,245, + 255,255,255,255,127,81,245,255,255,255,255,225,21,59,245,255,255,255,255, + 127,81,245,255,255,255,255,127,111,255,255,255,125,89,255,255,255,125,89, + 255,255,255,125,89,255,255,255,125,7,206,255,255,255,255,125,0,0,59,245, + 247,34,0,0,59,241,89,0,0,0,138,255,255,255,166,0,0,0,0,138,255,255,255, + 166,0,0,0,0,0,138,255,255,255,166,0,0,0,0,138,255,255,255,166,0,0,0,0,138, + 255,255,255,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,255,255,255,210,235,166, + 59,241,89,0,0,0,59,241,89,59,241,89,0,0,0,59,241,89,59,241,89,0,0,0,59, + 241,89,59,241,89,0,0,0,59,241,132,245,125,0,0,0,89,251,89,12,232,89,0,0, + 0,0,7,206,166,0,89,251,89,0,0,0,127,0,0,89,232,241,89,0,0,0,0,89,232,241, + 89,0,0,0,0,89,232,241,89,0,0,0,0,89,232,241,89,0,0,0,0,89,232,241,89,0, + 0,0,0,89,232,241,89,0,0,0,0,12,232,89,89,225,21,0,0,0,0,0,175,247,34,0, + 0,59,192,59,241,89,0,0,0,0,59,241,89,0,0,0,0,0,59,241,89,0,0,0,0,59,241, + 89,0,0,0,0,0,59,241,89,0,0,59,241,89,0,0,59,241,89,0,0,59,241,89,0,7,206, + 166,0,0,59,245,201,0,59,245,255,201,0,0,59,241,89,0,0,138,251,89,0,12,235, + 166,0,0,138,251,89,0,12,235,166,0,0,0,138,251,89,0,12,235,166,0,0,138,251, + 89,0,12,235,166,0,0,138,251,89,0,12,235,166,0,0,0,138,166,0,0,0,12,228, + 34,0,0,175,247,34,0,0,175,225,21,59,241,89,0,0,0,59,241,89,59,241,89,0, + 0,0,59,241,89,59,241,89,0,0,0,59,241,89,59,241,89,0,0,0,59,241,89,89,247, + 34,0,7,206,125,0,12,232,89,0,0,0,0,59,241,89,0,12,232,89,0,0,0,127,0,7, + 206,166,175,166,0,0,0,7,206,166,175,166,0,0,0,7,206,166,175,166,0,0,0,7, + 206,166,175,166,0,0,0,7,206,166,175,166,0,0,0,0,175,166,175,166,0,0,0,0, + 138,225,21,89,225,21,0,0,0,0,59,241,89,0,0,0,0,0,59,241,89,0,0,0,0,59,241, + 89,0,0,0,0,0,59,241,89,0,0,0,0,59,241,89,0,0,0,0,0,59,241,89,0,0,59,241, + 89,0,0,59,241,89,0,0,59,241,89,0,7,206,166,0,0,0,59,245,125,59,241,132, + 241,89,0,59,241,89,0,12,235,166,0,0,0,89,247,34,12,235,166,0,0,0,89,247, + 34,0,12,235,166,0,0,0,89,247,34,12,235,166,0,0,0,89,247,34,12,235,166,0, + 0,0,89,247,34,0,0,12,235,125,0,12,235,125,0,0,59,241,89,0,0,138,176,235, + 166,59,241,89,0,0,0,59,241,89,59,241,89,0,0,0,59,241,89,59,241,89,0,0,0, + 59,241,89,59,241,89,0,0,0,59,241,89,0,175,201,0,138,225,21,0,12,235,255, + 255,255,225,21,59,238,34,0,138,225,21,0,0,0,127,0,59,238,34,89,247,34,0, + 0,59,238,34,89,247,34,0,0,59,238,34,89,247,34,0,0,59,238,34,89,247,34,0, + 0,59,238,34,89,247,34,0,0,59,241,89,89,225,21,0,0,7,206,125,0,89,225,21, + 0,0,0,0,138,225,21,0,0,0,0,0,59,241,89,0,0,0,0,59,241,89,0,0,0,0,0,59,241, + 89,0,0,0,0,59,241,89,0,0,0,0,0,59,241,89,0,0,59,241,89,0,0,59,241,89,0, + 0,59,241,89,0,7,206,166,0,0,0,7,206,166,59,241,89,138,225,21,59,241,89, + 0,59,241,89,0,0,0,59,241,89,59,241,89,0,0,0,59,241,89,0,59,241,89,0,0,0, + 59,241,89,59,241,89,0,0,0,59,241,89,59,241,89,0,0,0,59,241,89,0,0,0,12, + 235,138,235,125,0,0,0,138,225,21,0,59,215,21,175,201,59,241,89,0,0,0,59, + 241,89,59,241,89,0,0,0,59,241,89,59,241,89,0,0,0,59,241,89,59,241,89,0, + 0,0,59,241,89,0,59,245,166,241,89,0,0,12,232,89,0,0,175,225,59,238,47,235, + 225,21,0,0,0,0,127,0,138,201,0,12,235,125,0,0,138,201,0,12,235,125,0,0, + 138,201,0,12,235,125,0,0,138,201,0,12,235,125,0,0,138,201,0,12,235,125, + 0,0,138,225,21,12,235,125,0,0,89,247,34,0,89,255,255,255,255,251,89,138, + 225,21,0,0,0,0,0,59,245,255,255,255,255,127,59,245,255,255,255,255,166, + 0,59,245,255,255,255,255,127,59,245,255,255,255,255,127,0,59,241,89,0,0, + 59,241,89,0,0,59,241,89,0,0,59,241,89,7,206,255,255,255,166,0,0,175,201, + 59,241,89,12,235,125,59,241,89,0,59,241,89,0,0,0,12,235,125,59,241,89,0, + 0,0,12,235,125,0,59,241,89,0,0,0,12,235,125,59,241,89,0,0,0,12,235,125, + 59,241,89,0,0,0,12,235,125,0,0,0,0,12,235,125,0,0,0,0,138,225,21,7,199, + 34,0,138,225,81,241,89,0,0,0,59,241,89,59,241,89,0,0,0,59,241,89,59,241, + 89,0,0,0,59,241,89,59,241,89,0,0,0,59,241,89,0,0,138,255,166,0,0,0,12,232, + 89,0,0,89,247,59,238,34,0,59,245,125,0,0,0,127,7,206,125,0,0,175,201,0, + 7,206,125,0,0,175,201,0,7,206,125,0,0,175,201,0,7,206,125,0,0,175,201,0, + 7,206,125,0,0,175,201,0,7,206,125,0,0,175,201,0,7,206,255,255,255,255,225, + 21,0,0,0,0,138,225,21,0,0,0,0,0,59,241,89,0,0,0,0,59,241,89,0,0,0,0,0,59, + 241,89,0,0,0,0,59,241,89,0,0,0,0,0,59,241,89,0,0,59,241,89,0,0,59,241,89, + 0,0,59,241,89,0,7,206,166,0,0,0,7,206,166,59,241,89,0,89,247,94,241,89, + 0,59,241,89,0,0,0,59,241,89,59,241,89,0,0,0,59,241,89,0,59,241,89,0,0,0, + 59,241,89,59,241,89,0,0,0,59,241,89,59,241,89,0,0,0,59,241,89,0,0,0,12, + 235,138,235,125,0,0,0,138,225,21,175,125,0,0,175,201,59,241,89,0,0,0,59, + 241,89,59,241,89,0,0,0,59,241,89,59,241,89,0,0,0,59,241,89,59,241,89,0, + 0,0,59,241,89,0,0,59,241,89,0,0,0,12,232,89,0,7,206,201,59,238,34,0,0,138, + 201,0,0,0,127,59,245,255,255,255,255,247,34,59,245,255,255,255,255,247, + 34,59,245,255,255,255,255,247,34,59,245,255,255,255,255,247,34,59,245,255, + 255,255,255,247,34,59,245,255,255,255,255,247,34,59,241,89,0,0,89,225,21, + 0,0,0,0,59,241,89,0,0,0,0,0,59,241,89,0,0,0,0,59,241,89,0,0,0,0,0,59,241, + 89,0,0,0,0,59,241,89,0,0,0,0,0,59,241,89,0,0,59,241,89,0,0,59,241,89,0, + 0,59,241,89,0,7,206,166,0,0,0,59,241,89,59,241,89,0,7,206,200,241,89,0, + 12,235,166,0,0,0,89,247,34,12,235,166,0,0,0,89,247,34,0,12,235,166,0,0, + 0,89,247,34,12,235,166,0,0,0,89,247,34,12,235,166,0,0,0,89,247,34,0,0,12, + 235,125,0,12,235,125,0,0,59,241,159,166,0,0,12,235,166,12,232,89,0,0,0, + 59,238,34,12,232,89,0,0,0,59,238,34,12,232,89,0,0,0,59,238,34,12,232,89, + 0,0,0,59,238,34,0,0,59,241,89,0,0,0,12,235,255,255,255,201,0,59,238,34, + 0,0,138,201,0,0,0,127,138,201,0,0,0,12,235,125,138,201,0,0,0,12,235,125, + 138,201,0,0,0,12,235,125,138,201,0,0,0,12,235,125,138,201,0,0,0,12,235, + 125,138,201,0,0,0,12,235,125,175,201,0,0,0,89,225,21,0,0,0,0,0,175,247, + 34,0,0,59,192,59,241,89,0,0,0,0,59,241,89,0,0,0,0,0,59,241,89,0,0,0,0,59, + 241,89,0,0,0,0,0,59,241,89,0,0,59,241,89,0,0,59,241,89,0,0,59,241,89,0, + 7,206,166,0,0,59,245,201,0,59,241,89,0,0,59,245,251,89,0,0,138,251,89,0, + 59,245,166,0,0,138,251,89,0,59,245,166,0,0,0,138,251,89,0,59,245,166,0, + 0,138,251,89,0,59,245,166,0,0,138,251,89,0,59,245,166,0,0,0,138,166,0,0, + 0,12,228,34,0,0,175,247,34,0,7,206,225,21,0,138,225,21,0,7,206,166,0,0, + 138,225,21,0,7,206,166,0,0,138,225,21,0,7,206,166,0,0,138,225,21,0,7,206, + 166,0,0,0,59,241,89,0,0,0,12,232,89,0,0,0,0,59,238,34,0,12,235,125,0,0, + 0,127,206,125,0,0,0,0,175,206,206,125,0,0,0,0,175,206,206,125,0,0,0,0,175, + 206,206,125,0,0,0,0,175,206,206,125,0,0,0,0,175,206,206,125,0,0,0,0,175, + 232,245,125,0,0,0,89,255,255,255,255,255,166,0,0,138,255,255,255,251,89, + 59,245,255,255,255,255,127,81,245,255,255,255,255,225,21,59,245,255,255, + 255,255,127,81,245,255,255,255,255,127,111,255,255,255,125,89,255,255,255, + 125,89,255,255,255,125,89,255,255,255,125,7,206,255,255,255,255,125,0,0, + 59,241,89,0,0,0,175,251,89,0,0,0,138,255,255,255,166,0,0,0,0,138,255,255, + 255,166,0,0,0,0,0,138,255,255,255,166,0,0,0,0,138,255,255,255,166,0,0,0, + 0,138,255,255,255,166,0,0,0,0,0,0,0,0,0,0,0,0,0,7,202,194,255,255,255,201, + 0,0,0,0,59,245,255,251,89,0,0,0,0,59,245,255,251,89,0,0,0,0,59,245,255, + 251,89,0,0,0,0,59,245,255,251,89,0,0,0,0,59,241,89,0,0,0,12,232,89,0,0, + 0,0,59,238,47,235,255,166,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,12,228,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138, + 166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,255,166,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127,127,127,127,127,0,127,127,127, + 127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127, + 127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127, + 127,0,127,127,127,127,127,127,0,127,127,127,127,0,127,127,127,127,0,127, + 127,127,127,0,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,0, + 0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,255,201,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,7,206, + 225,21,0,0,0,0,0,12,235,201,0,0,0,138,255,201,0,0,0,59,245,225,29,202,89, + 0,0,0,0,0,0,0,0,138,166,7,202,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 7,206,225,21,0,0,0,0,0,12,235,201,0,0,0,89,255,225,21,0,0,0,0,0,0,0,0,175, + 247,34,0,12,235,255,255,166,0,0,0,0,0,0,0,0,0,0,0,0,59,245,225,29,202,89, + 0,0,138,251,89,0,0,0,0,0,7,206,225,21,0,0,0,89,255,225,21,0,0,59,245,225, + 29,202,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,225, + 21,0,0,0,0,0,89,255,125,0,0,0,89,255,225,21,0,0,0,0,0,0,0,0,0,0,0,0,138, + 251,89,0,59,238,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,175, + 166,0,0,0,0,7,206,166,0,0,0,89,225,21,175,201,0,7,202,89,138,255,166,0, + 0,89,247,34,175,166,0,0,138,166,7,202,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,7,206,166,0,0,0,0,0,175,166,0,0,0,89,247,34,138,201,0,0,89,247, + 34,175,201,0,0,138,201,0,175,200,215,34,235,247,47,232,0,138,255,225,111, + 225,21,0,0,172,89,138,255,166,0,0,0,0,89,225,21,0,0,0,0,175,201,0,0,0,0, + 89,247,34,138,201,0,0,172,89,138,255,166,0,0,59,238,34,138,201,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,166,0,0,0,0,59,241,89,0,0,0,89, + 247,34,138,201,0,0,0,59,238,34,138,201,0,0,0,89,247,34,0,0,59,238,34,0, + 0,0,0,0,138,225,29,206,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,255,201,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,225,21,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,12,235,166,0,0,0,0,0,0,0,0,89,166,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,238,34,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,7,206,255,255,255,125,0,7,206,255,255,255, + 125,0,7,206,255,255,255,125,0,7,206,255,255,255,125,0,7,206,255,255,255, + 125,0,12,235,255,255,251,89,0,12,235,255,255,251,89,59,245,255,166,0,0, + 59,245,255,255,201,0,12,235,255,251,89,0,0,12,235,255,251,89,0,0,12,235, + 255,251,89,0,0,12,235,255,251,89,0,59,238,34,59,238,34,59,238,34,59,238, + 34,0,59,241,89,175,225,21,0,59,241,194,255,255,125,0,0,12,235,255,247,34, + 0,0,12,235,255,247,34,0,0,0,12,235,255,247,34,0,0,12,235,255,247,34,0,0, + 12,235,255,247,34,0,0,0,0,0,12,235,166,0,0,0,0,7,206,255,255,225,21,0,59, + 241,89,0,59,241,89,59,241,89,0,59,241,89,59,241,89,0,59,241,89,0,59,241, + 89,0,59,241,97,206,166,0,0,12,235,125,59,238,163,255,255,201,7,206,166, + 0,0,12,235,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,89,247,34,0,0,0,0,89,247, + 34,0,0,0,0,89,247,34,0,0,0,0,89,247,34,0,0,0,0,89,247,34,0,0,0,0,138,225, + 21,0,0,0,0,89,255,225,21,0,138,201,59,245,125,0,0,0,7,206,125,0,89,225, + 21,7,206,125,0,89,225,21,7,206,125,0,89,225,21,7,206,125,0,89,225,21,59, + 238,34,59,238,34,59,238,34,59,238,34,0,0,0,0,12,235,125,0,59,245,166,0, + 89,247,34,7,206,166,0,138,225,21,7,206,166,0,138,225,21,0,7,206,166,0,138, + 225,21,7,206,166,0,138,225,21,7,206,166,0,138,225,21,0,0,0,0,0,0,0,0,0, + 0,12,232,89,0,138,251,89,0,59,241,89,0,59,241,89,59,241,89,0,59,241,89, + 59,241,89,0,59,241,89,0,59,241,89,0,59,241,89,89,247,34,0,89,247,34,59, + 245,166,0,7,206,166,89,247,34,0,89,247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0, + 59,241,89,0,0,0,0,59,241,89,0,0,0,0,59,241,89,0,0,0,0,59,241,89,0,0,0,0, + 59,241,89,0,0,0,0,59,238,34,0,0,0,0,12,232,89,0,0,59,238,127,225,21,0,0, + 0,59,238,34,0,59,238,34,59,238,34,0,59,238,34,59,238,34,0,59,238,34,59, + 238,34,0,59,238,34,59,238,34,59,238,34,59,238,34,59,238,34,0,138,255,255, + 255,255,201,0,59,241,89,0,59,241,89,59,241,89,0,59,241,89,59,241,89,0,59, + 241,89,0,59,241,89,0,59,241,89,59,241,89,0,59,241,89,59,241,89,0,59,241, + 89,0,12,235,255,255,255,255,255,255,166,138,201,0,59,157,175,201,0,59,241, + 89,0,59,241,89,59,241,89,0,59,241,89,59,241,89,0,59,241,89,0,59,241,89, + 0,59,241,89,12,235,125,0,175,166,0,59,238,34,0,0,138,225,34,235,125,0,175, + 166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,127,0,89,255,255,255,251,89,0,89,255,255,255,251, + 89,0,89,255,255,255,251,89,0,89,255,255,255,251,89,0,89,255,255,255,251, + 89,0,138,255,255,255,247,34,0,175,255,255,255,255,255,255,255,255,251,127, + 201,0,0,0,0,59,245,255,255,255,251,89,59,245,255,255,255,251,89,59,245, + 255,255,255,251,89,59,245,255,255,255,251,89,59,238,34,59,238,34,59,238, + 34,59,238,34,138,247,34,0,0,138,201,0,59,241,89,0,59,241,89,59,238,34,0, + 12,232,89,59,238,34,0,12,232,89,0,59,238,34,0,12,232,89,59,238,34,0,12, + 232,89,59,238,34,0,12,232,89,0,0,0,0,0,0,0,0,0,0,175,201,7,176,21,138,201, + 0,59,241,89,0,59,241,89,59,241,89,0,59,241,89,59,241,89,0,59,241,89,0,59, + 241,89,0,59,241,89,0,175,201,12,232,89,0,59,238,34,0,0,138,225,21,175,201, + 12,232,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,59,241,89,0,59,241,89,59,241,89,0,59, + 241,89,59,241,89,0,59,241,89,59,241,89,0,59,241,89,59,241,89,0,59,241,89, + 138,247,34,0,59,238,34,138,225,21,0,12,232,89,0,0,0,0,138,201,0,0,0,0,59, + 238,34,0,0,0,0,59,238,34,0,0,0,0,59,238,34,0,0,0,0,59,238,34,0,0,0,0,59, + 238,34,59,238,34,59,238,34,59,238,34,175,201,0,0,0,138,166,0,59,241,89, + 0,59,241,89,59,241,89,0,59,241,89,59,241,89,0,59,241,89,0,59,241,89,0,59, + 241,89,59,241,89,0,59,241,89,59,241,89,0,59,241,89,0,0,0,0,12,235,166,0, + 0,0,138,201,134,89,0,175,166,0,59,241,89,0,59,241,89,59,241,89,0,59,241, + 89,59,241,89,0,59,241,89,0,59,241,89,0,59,241,89,0,89,247,124,225,21,0, + 59,238,34,0,0,138,201,0,89,247,124,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,89,247, + 34,0,89,251,89,89,247,34,0,89,251,89,89,247,34,0,89,251,89,89,247,34,0, + 89,251,89,89,247,34,0,89,251,89,175,201,0,0,175,247,34,175,201,0,0,59,245, + 225,21,0,7,199,94,245,125,0,0,0,7,206,166,0,7,199,34,7,206,166,0,7,199, + 34,7,206,166,0,7,199,34,7,206,166,0,7,199,34,59,238,34,59,238,34,59,238, + 34,59,238,34,138,247,34,0,12,232,89,0,59,241,89,0,59,241,89,7,206,166,0, + 138,225,21,7,206,166,0,138,225,21,0,7,206,166,0,138,225,21,7,206,166,0, + 138,225,21,7,206,166,0,138,225,21,0,0,0,0,12,235,166,0,0,0,59,245,166,0, + 59,241,89,0,12,235,125,0,175,251,89,12,235,125,0,175,251,89,12,235,125, + 0,175,251,89,0,12,235,125,0,175,251,89,0,7,206,255,125,0,0,59,238,34,0, + 12,235,125,0,7,206,255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,175,255,255,232, + 241,89,0,175,255,255,232,241,89,0,175,255,255,232,241,89,0,175,255,255, + 232,241,89,0,175,255,255,232,241,89,12,235,255,255,166,238,34,12,235,255, + 255,225,21,89,255,255,251,89,0,89,255,255,255,201,0,12,235,255,251,89,0, + 0,12,235,255,251,89,0,0,12,235,255,251,89,0,0,12,235,255,251,89,0,59,238, + 34,59,238,34,59,238,34,59,238,34,0,138,255,255,255,125,0,0,59,241,89,0, + 59,241,89,0,12,235,255,247,34,0,0,12,235,255,247,34,0,0,0,12,235,255,247, + 34,0,0,12,235,255,247,34,0,0,12,235,255,247,34,0,0,0,0,0,0,0,0,0,0,0,7, + 206,255,255,225,21,0,0,0,89,255,255,166,241,89,0,89,255,255,166,241,89, + 0,89,255,255,166,241,89,0,0,89,255,255,166,241,89,0,0,138,247,34,0,0,59, + 245,166,255,255,166,0,0,0,138,247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,215,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,232,89,0,0,0,59,238,34,0,0,0,0,0, + 12,232,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,12,235,255,125,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,138,225,21,0,0,0,59,238,34,0,0,0,0,0,138,225,21,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127, + 127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,127,0,127,127, + 127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127, + 127,127,127,127,0,127,127,127,127,127,127,0,127,127,0,127,127,0,127,127, + 0,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127, + 127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127, + 127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127, + 127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; + + +// Large font anti-aliased +const int FONT2AA_BM_W = 276; +const int FONT2AA_BM_H = 120; +static const unsigned char s_Font2AA[] = +{ + 127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,59,245,125,175,225,21, + 0,0,0,0,0,0,0,0,0,0,0,0,0,138,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,59,241,89,0,0,12,235,201,89,255,166,0,0,0,0,0,172,89,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,225,21,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,138,247,34,0,12, + 232,89,138,225,21,0,0,0,0,138,125,7,199,34,0,0,0,0,138,125,0,0,0,0,138, + 255,255,201,0,0,0,59,215,21,0,0,0,0,59,245,255,255,166,0,0,0,59,241,89, + 0,7,206,201,0,0,89,251,89,0,59,215,21,172,89,59,192,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,166,0,0,138,255,251,89,0,0,0,0,0, + 138,201,0,0,0,7,206,255,255,255,166,0,0,7,206,255,255,255,201,0,0,0,0,0, + 0,138,251,89,0,0,175,255,255,255,255,225,21,0,0,12,235,255,255,125,89,255, + 255,255,255,255,251,89,0,12,235,255,255,225,21,0,0,59,245,255,255,166,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,59,245,255,255,251,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,89,247, + 34,0,12,232,89,138,201,0,0,0,0,7,202,89,59,215,21,0,0,12,235,255,255,255, + 166,0,59,241,89,12,235,125,0,0,172,89,0,0,0,0,7,206,166,0,89,251,89,0,0, + 12,228,34,0,89,247,34,0,0,0,175,201,0,0,89,251,191,194,247,34,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,232,89,0,175,201,0,12,235, + 125,0,0,138,255,255,201,0,0,0,12,182,0,0,59,245,125,0,12,206,21,0,12,235, + 166,0,0,0,0,89,255,251,89,0,0,175,201,0,0,0,0,0,0,89,255,125,0,0,0,0,0, + 0,0,0,89,251,89,12,235,166,0,7,206,201,0,59,245,125,0,12,235,166,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,89,166,0,0,138,251,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,89,247,34,0,12, + 228,34,89,201,0,0,0,0,12,206,21,89,166,0,0,12,235,125,138,125,59,192,0, + 89,247,34,7,206,166,0,89,201,0,0,0,0,0,12,235,125,0,12,232,89,0,0,12,228, + 34,0,175,201,0,0,0,0,59,241,89,0,0,7,206,166,0,0,0,0,0,0,0,138,166,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,225,21,59,241,89,0,0,138,225,21,0, + 0,0,175,201,0,0,0,0,0,0,0,7,206,201,0,0,0,0,0,0,175,201,0,0,0,59,241,132, + 241,89,0,0,175,201,0,0,0,0,0,7,206,166,0,0,0,0,0,0,0,0,7,206,201,0,59,241, + 89,0,0,138,225,21,138,225,21,0,0,138,225,21,89,255,125,0,0,89,255,125,0, + 0,0,0,0,0,0,0,138,225,21,0,0,0,0,0,0,0,0,0,0,0,138,201,0,0,0,0,0,0,0,0, + 0,0,0,59,241,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,89,247,34,0,0,0,0,0,0,0, + 0,89,255,255,255,255,255,255,255,125,59,238,34,138,125,0,0,0,89,247,34, + 7,206,166,7,202,89,0,0,0,0,0,0,175,225,21,138,225,21,0,0,0,0,0,12,235,125, + 0,0,0,0,7,206,125,0,89,251,191,194,247,34,0,0,0,0,0,138,166,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,138,166,0,89,247,34,0,0,89,247,34,0,0,0,175,201, + 0,0,0,0,0,0,0,12,235,166,0,0,0,0,0,59,245,125,0,0,12,235,125,59,241,89, + 0,0,175,201,0,0,0,0,0,59,241,89,0,0,0,0,0,0,0,0,89,247,34,0,12,235,201, + 0,0,175,201,0,138,225,21,0,0,89,247,34,89,255,125,0,0,89,255,125,0,0,0, + 0,0,12,235,255,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,175,255,251,89,0,0,0,0, + 0,0,0,0,138,247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,89,247,34,0,0,0,0,0, + 0,0,0,0,0,175,125,7,199,34,0,0,12,235,166,138,125,0,0,0,59,241,89,12,235, + 125,89,201,12,235,255,251,89,0,0,7,206,255,166,0,59,241,89,0,0,0,59,238, + 34,0,0,0,0,0,175,166,59,215,21,172,89,59,192,0,0,0,0,0,138,166,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,125,0,138,247,34,0,0,89,247,34,0,0,0, + 175,201,0,0,0,0,0,0,0,89,251,89,0,0,0,89,255,247,34,0,0,7,206,166,0,59, + 241,89,0,0,175,255,255,255,225,21,0,89,251,226,255,255,247,34,0,0,0,7,206, + 166,0,0,0,12,235,255,255,201,0,0,89,255,125,0,0,138,247,34,0,0,0,0,0,0, + 0,0,0,0,0,89,255,255,166,0,0,0,0,0,175,255,255,255,255,255,255,225,21,0, + 0,0,0,59,245,255,201,0,0,0,0,0,175,251,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0, + 0,0,89,225,21,0,0,0,0,0,0,0,0,0,7,199,34,59,215,21,0,0,0,59,245,255,255, + 201,0,0,0,138,255,255,201,12,228,34,175,166,0,138,201,0,12,235,125,89,255, + 125,59,241,89,0,0,0,59,238,34,0,0,0,0,0,138,201,0,0,0,172,89,0,0,0,7,206, + 255,255,255,255,255,255,247,34,0,0,0,0,89,255,255,255,166,0,0,0,0,0,59, + 238,34,0,138,247,34,0,0,89,247,34,0,0,0,175,201,0,0,0,0,0,0,59,245,166, + 0,0,0,0,0,0,12,235,166,0,138,201,0,0,59,241,89,0,0,0,0,0,12,235,201,0,138, + 251,89,0,0,175,225,21,0,0,89,247,34,0,0,7,206,166,0,175,255,166,0,0,89, + 255,255,255,223,247,34,0,0,0,0,0,0,0,0,0,0,175,247,34,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,225,21,0,0,175,225,21,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,127,0,0,0,0,0,59,215,21,0,0,0,0,0,0,0,12,235,255,255,255,255,255,255, + 166,0,0,0,0,138,125,175,225,21,0,0,0,0,0,138,166,7,206,125,0,89,247,34, + 138,225,21,0,89,255,166,215,21,0,0,0,59,238,34,0,0,0,0,0,138,201,0,0,0, + 0,0,0,0,0,0,0,0,0,138,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,201,0, + 0,89,247,34,0,0,89,247,34,0,0,0,175,201,0,0,0,0,0,12,235,201,0,0,0,0,0, + 0,0,0,138,225,21,175,255,255,255,255,255,255,125,0,0,0,0,0,138,247,34,89, + 247,34,0,0,59,241,89,0,7,206,166,0,0,0,138,247,34,0,0,138,247,34,0,0,0, + 0,0,138,225,21,0,0,0,0,0,0,0,0,0,0,0,89,255,255,166,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,59,245,255,201,0,0,0,0,175,201,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,166,0,175,125,0,0,0,0,0,0,138, + 125,89,247,34,0,0,0,0,12,228,34,7,206,125,0,89,247,34,138,247,34,0,0,89, + 255,166,0,0,0,0,59,238,34,0,0,0,0,0,175,166,0,0,0,0,0,0,0,0,0,0,0,0,138, + 166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,125,0,0,59,241,89,0,0,138,225, + 21,0,0,0,175,201,0,0,0,0,12,235,201,0,0,0,0,0,0,0,0,0,138,225,21,0,0,0, + 0,59,241,89,0,0,0,0,0,0,138,225,21,59,241,89,0,0,59,241,89,0,89,247,34, + 0,0,0,138,247,34,0,0,89,251,89,0,0,0,0,7,206,166,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,12,235,255,225,21,0,0,175,255,255,255,255,255,255,225,21,0,0,175, + 255,251,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,89,247, + 34,0,0,0,0,0,0,0,0,0,175,125,7,199,34,0,0,0,89,201,0,138,125,175,201,0, + 0,0,0,0,138,166,0,0,175,166,0,138,201,0,89,255,166,0,0,89,255,255,125,0, + 0,0,12,235,125,0,0,0,0,7,206,125,0,0,0,0,0,0,0,0,0,0,0,0,138,166,0,0,0, + 0,0,138,255,125,0,0,0,0,0,0,175,247,34,59,238,34,0,0,0,175,201,0,12,235, + 125,0,0,0,0,175,201,0,0,0,12,235,166,0,0,0,0,0,89,166,0,0,59,245,166,0, + 0,0,0,0,59,241,89,0,59,215,21,0,12,235,166,0,7,206,201,0,0,175,225,21,7, + 206,166,0,0,0,0,59,245,166,0,7,206,225,21,0,0,0,0,175,225,21,0,89,255,125, + 0,0,12,235,201,0,0,0,0,0,0,0,0,138,225,21,0,0,0,0,0,0,0,0,0,0,0,138,201, + 0,0,0,0,0,0,0,0,0,175,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,89,247, + 34,0,0,0,0,0,0,0,0,7,199,34,59,215,21,0,0,0,12,235,255,255,255,201,0,0, + 0,0,0,59,215,21,0,0,12,235,255,251,89,0,0,89,255,255,255,201,0,89,255,0, + 0,0,0,175,201,0,0,0,0,59,238,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175, + 201,0,0,0,0,0,0,0,175,247,34,138,201,0,0,0,0,0,138,255,251,89,0,0,0,138, + 255,255,255,255,166,0,89,255,255,255,255,255,247,34,12,235,255,255,255, + 166,0,0,0,0,0,0,59,241,89,0,12,235,255,255,255,166,0,0,0,7,206,255,255, + 225,21,0,138,247,34,0,0,0,0,0,59,245,255,255,201,0,0,0,175,255,255,201, + 0,0,0,89,255,125,0,0,89,251,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,175,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,125,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,247,34,0,0,0,175,201,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,232,89,0,0,0,0,0,0,0,0,0,0,175,125, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,125,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,201,0,0,89,251,89,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,201,0,0,0,0,0,0,0,0,0,0,12,232,89, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,232,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,201,0,0,201,201,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127,0,127,127,127, + 127,0,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,127,0,127,127,0,127,127,127,127,0,127,127, + 127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127, + 127,0,127,127,127,0,127,127,127,127,0,127,127,127,0,127,127,127,127,0,127, + 127,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127, + 127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 0,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,255,255, + 201,0,138,201,0,0,0,0,89,255,255,255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,127,0,0,0,0,175,255,255,255,247,34,0,0,0,0,0,7,206,251,89,0,0,12,0, + 235,255,255,255,255,201,0,0,0,0,59,245,255,255,255,201,12,0,235,255,255, + 255,255,166,0,0,0,12,235,255,255,255,255,255,127,12,235,255,255,255,255, + 251,89,0,0,12,235,255,255,255,251,89,12,235,166,0,0,0,12,235,125,89,255, + 255,255,201,0,0,175,255,255,225,21,12,235,166,0,0,7,206,251,102,0,235,166, + 0,0,0,0,12,235,251,89,0,0,0,89,255,225,21,12,235,251,89,0,0,12,235,125, + 0,0,0,138,255,255,166,0,0,0,12,235,255,255,255,251,89,0,0,0,0,175,255,255, + 201,0,0,0,12,235,255,255,255,251,89,0,0,0,12,235,255,255,255,247,47,235, + 255,255,255,255,255,255,255,138,0,235,125,0,0,0,59,245,133,206,166,0,0, + 0,0,59,245,255,133,201,0,0,0,138,251,89,0,0,12,235,133,206,247,34,0,0,0, + 175,229,216,225,21,0,0,0,138,247,124,255,255,255,255,255,255,125,7,206, + 125,0,0,0,59,238,34,0,0,0,0,0,12,235,125,0,0,0,0,175,247,34,0,0,0,0,0,0, + 0,0,0,0,127,0,0,59,245,166,0,0,0,59,245,166,0,0,0,0,59,245,255,166,0,0, + 12,0,235,166,0,0,59,245,125,0,0,138,255,125,0,0,7,202,102,0,235,166,0,0, + 59,245,225,21,0,12,235,166,0,0,0,0,0,12,235,166,0,0,0,0,0,0,89,255,166, + 0,0,0,89,127,12,235,166,0,0,0,12,235,125,0,12,235,125,0,0,0,0,0,138,225, + 21,12,235,166,0,7,206,225,21,12,0,235,166,0,0,0,0,12,235,255,166,0,0,7, + 206,255,225,21,12,235,255,201,0,0,12,235,125,0,59,245,166,0,0,138,251,89, + 0,12,235,166,0,0,138,251,89,0,89,255,125,0,0,89,255,125,0,12,235,166,0, + 0,138,251,89,0,12,235,166,0,0,7,202,89,0,0,0,138,225,21,0,0,12,0,235,125, + 0,0,0,59,245,125,138,225,21,0,0,0,138,225,151,34,247,34,0,0,175,255,125, + 0,0,89,247,34,12,235,166,0,0,89,247,34,59,245,125,0,0,59,245,125,0,0,0, + 0,0,138,247,34,7,206,125,0,0,0,7,206,125,0,0,0,0,0,12,235,125,0,0,0,138, + 225,187,201,0,0,0,0,0,0,0,0,0,0,127,0,12,232,89,0,0,0,0,0,12,232,89,0,0, + 0,138,225,151,225,21,0,12,0,235,166,0,0,12,235,166,0,12,235,166,0,0,0,0, + 0,12,0,235,166,0,0,0,12,235,166,0,12,235,166,0,0,0,0,0,12,235,166,0,0,0, + 0,0,12,235,166,0,0,0,0,0,0,12,235,166,0,0,0,12,235,125,0,12,235,125,0,0, + 0,0,0,138,225,21,12,235,166,0,175,225,21,0,12,0,235,166,0,0,0,0,12,235, + 166,238,34,0,59,215,187,225,21,12,235,166,245,125,0,12,235,125,12,235,125, + 0,0,0,0,138,247,34,12,235,166,0,0,12,235,166,12,235,125,0,0,0,0,138,247, + 34,12,235,166,0,0,12,235,166,0,89,247,34,0,0,0,0,0,0,0,0,138,225,21,0,0, + 12,0,235,125,0,0,0,59,245,125,59,241,89,0,0,7,206,166,59,0,241,89,0,12, + 232,194,201,0,0,138,225,21,0,89,251,89,12,235,166,0,0,138,247,34,7,206, + 201,0,0,0,0,0,59,245,125,0,7,206,125,0,0,0,0,138,201,0,0,0,0,0,12,235,125, + 0,0,59,241,89,12,235,166,0,0,0,0,0,0,0,0,0,127,0,175,166,0,59,245,255,255, + 247,34,138,201,0,0,7,206,166,59,241,89,0,12,0,235,166,0,0,89,251,89,0,89, + 247,34,0,0,0,0,0,12,0,235,166,0,0,0,0,138,225,21,12,235,166,0,0,0,0,0,12, + 235,166,0,0,0,0,0,89,247,34,0,0,0,0,0,0,12,235,166,0,0,0,12,235,125,0,12, + 235,125,0,0,0,0,0,138,225,21,12,235,166,175,247,34,0,0,12,0,235,166,0,0, + 0,0,12,235,133,206,166,0,175,166,175,225,21,12,235,125,138,225,21,12,235, + 125,89,247,34,0,0,0,0,59,245,125,12,235,166,0,0,12,235,166,89,247,34,0, + 0,0,0,59,245,125,12,235,166,0,0,12,235,125,0,89,255,125,0,0,0,0,0,0,0,0, + 138,225,21,0,0,12,0,235,125,0,0,0,59,245,125,7,206,201,0,0,59,241,89,7, + 0,206,166,0,59,215,111,225,21,7,206,166,0,0,0,175,225,187,225,21,0,0,12, + 235,166,89,247,34,0,0,0,0,7,206,201,0,0,7,206,125,0,0,0,0,89,225,21,0,0, + 0,0,12,235,125,0,12,235,166,0,0,59,241,89,0,0,0,0,0,0,0,0,127,0,202,89, + 12,235,125,0,12,228,34,59,215,0,0,59,241,89,7,206,166,0,12,0,235,255,255, + 255,255,166,0,0,138,225,21,0,0,0,0,0,12,0,235,166,0,0,0,0,89,247,34,12, + 235,255,255,255,255,247,34,12,235,255,255,255,255,247,0,163,225,21,0,0, + 0,0,0,0,12,235,255,255,255,255,255,255,125,0,12,235,125,0,0,0,0,0,138,225, + 21,12,235,255,247,34,0,0,0,12,0,235,166,0,0,0,0,12,235,125,89,225,34,228, + 34,175,225,21,12,235,125,12,235,125,12,235,125,138,225,21,0,0,0,0,12,235, + 166,12,235,166,0,0,175,247,34,138,225,21,0,0,0,0,12,235,166,12,235,166, + 0,0,175,225,21,0,0,175,255,255,225,21,0,0,0,0,0,138,225,21,0,0,12,0,235, + 125,0,0,0,59,245,125,0,138,247,34,0,138,225,21,0,0,175,201,0,138,201,12, + 232,89,12,235,125,0,0,0,12,235,251,89,0,0,0,0,89,255,255,125,0,0,0,0,0, + 138,247,34,0,0,7,206,125,0,0,0,0,12,232,89,0,0,0,0,12,235,125,7,206,201, + 0,0,0,0,138,251,89,0,0,0,0,0,0,0,127,7,228,34,89,225,21,0,12,228,34,12, + 228,0,0,138,225,21,0,138,225,21,12,0,235,166,0,0,12,235,201,0,138,225,21, + 0,0,0,0,0,12,0,235,166,0,0,0,0,89,247,34,12,235,166,0,0,0,0,0,12,235,166, + 0,0,0,0,0,138,225,21,0,12,235,255,255,127,12,235,166,0,0,0,12,235,125,0, + 12,235,125,0,0,0,0,0,138,225,21,12,235,229,216,225,21,0,0,12,0,235,166, + 0,0,0,0,12,235,125,12,235,223,201,0,175,225,21,12,235,125,0,138,225,34, + 235,125,138,225,21,0,0,0,0,12,235,166,12,235,255,255,255,247,34,0,138,225, + 21,0,0,0,0,12,235,166,12,235,255,255,255,166,0,0,0,0,0,0,89,255,255,247, + 34,0,0,0,138,225,21,0,0,12,0,235,125,0,0,0,59,245,125,0,59,245,125,7,206, + 166,0,0,0,89,247,34,175,125,7,206,125,89,247,34,0,0,0,12,235,251,89,0,0, + 0,0,7,206,225,21,0,0,0,0,59,245,125,0,0,0,7,206,125,0,0,0,0,0,175,166,0, + 0,0,0,12,235,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,12,228,34,89,225, + 21,0,12,228,34,59,215,0,7,206,255,255,255,255,251,89,12,0,235,166,0,0,0, + 138,247,0,124,247,34,0,0,0,0,0,12,0,235,166,0,0,0,0,138,225,21,12,235,166, + 0,0,0,0,0,12,235,166,0,0,0,0,0,89,247,34,0,0,0,0,175,127,12,235,166,0,0, + 0,12,235,125,0,12,235,125,0,0,0,0,0,138,225,21,12,235,166,59,245,201,0, + 0,12,0,235,166,0,0,0,0,12,235,125,0,138,251,89,0,175,225,21,12,235,125, + 0,12,235,138,235,125,89,247,34,0,0,0,0,59,245,125,12,235,166,0,0,0,0,0, + 89,247,34,0,0,0,0,59,245,125,12,235,166,0,175,247,34,0,0,0,0,0,0,0,59,245, + 166,0,0,0,138,225,21,0,0,12,0,235,125,0,0,0,59,241,89,0,7,206,201,59,241, + 89,0,0,0,59,241,102,232,89,0,138,201,138,225,21,0,0,0,175,201,175,225,21, + 0,0,0,0,175,225,21,0,0,0,7,206,201,0,0,0,0,7,206,125,0,0,0,0,0,89,225,21, + 0,0,0,12,235,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,12,232,89,59,241, + 89,0,89,247,34,89,201,0,59,241,89,0,0,7,206,166,12,0,235,166,0,0,0,138, + 225,0,81,245,166,0,0,0,0,0,12,0,235,166,0,0,0,12,235,166,0,12,235,166,0, + 0,0,0,0,12,235,166,0,0,0,0,0,12,235,166,0,0,0,0,175,127,12,235,166,0,0, + 0,12,235,125,0,12,235,125,0,0,0,0,0,138,225,21,12,235,166,0,89,255,166, + 0,12,0,235,166,0,0,0,0,12,235,125,0,12,182,0,0,175,225,21,12,235,125,0, + 0,138,232,245,125,12,235,125,0,0,0,0,138,247,34,12,235,166,0,0,0,0,0,12, + 235,125,0,0,0,0,138,247,34,12,235,166,0,7,206,225,21,0,0,0,0,0,0,12,235, + 166,0,0,0,138,225,21,0,0,12,0,235,166,0,0,0,89,251,89,0,0,138,247,163,225, + 21,0,0,0,7,206,200,215,21,0,89,225,187,166,0,0,0,89,251,89,12,235,166,0, + 0,0,0,175,225,21,0,0,0,138,247,34,0,0,0,0,7,206,125,0,0,0,0,0,12,232,89, + 0,0,0,12,235,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,12,175,166,0,89, + 255,255,210,235,255,255,125,0,138,225,21,0,0,0,138,247,47,0,235,166,0,0, + 59,245,166,0,0,138,255,125,0,0,7,202,102,0,235,166,0,0,12,235,225,21,0, + 12,235,166,0,0,0,0,0,12,235,166,0,0,0,0,0,0,138,255,125,0,0,0,175,127,12, + 235,166,0,0,0,12,235,125,0,12,235,125,0,0,0,0,7,206,201,0,12,235,166,0, + 0,138,255,125,12,0,235,166,0,0,0,12,0,235,125,0,0,0,0,0,175,225,21,12,235, + 125,0,0,12,235,255,125,0,89,255,125,0,0,89,251,89,0,12,235,166,0,0,0,0, + 0,0,89,255,125,0,0,89,255,125,0,12,235,166,0,0,12,235,201,0,138,166,0,0, + 0,138,251,89,0,0,0,138,225,21,0,0,0,0,138,247,34,0,7,206,225,21,0,0,12, + 235,255,166,0,0,0,0,0,175,255,201,0,0,12,235,255,125,0,0,12,235,166,0,0, + 138,251,89,0,0,0,175,225,21,0,0,89,251,89,0,0,0,0,0,7,206,125,0,0,0,0,0, + 0,175,166,0,0,0,12,235,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,59,241, + 89,0,0,0,0,0,0,0,0,7,206,166,0,0,0,0,59,245,138,0,235,255,255,255,255,125, + 0,0,0,0,59,245,255,255,255,201,12,0,235,255,255,255,255,166,0,0,0,12,235, + 255,255,255,255,255,127,12,235,166,0,0,0,0,0,0,0,59,245,255,255,255,225, + 21,12,235,166,0,0,0,12,235,125,89,255,255,255,210,127,235,255,255,225,21, + 0,12,235,166,0,0,0,175,255,127,0,235,255,255,255,247,47,0,235,125,0,0,0, + 0,0,175,225,21,12,235,125,0,0,0,138,255,125,0,0,0,175,255,255,201,0,0,0, + 12,235,166,0,0,0,0,0,0,0,0,175,255,255,201,0,0,0,12,235,166,0,0,0,89,255, + 225,34,235,255,255,255,247,34,0,0,0,0,138,225,21,0,0,0,0,0,138,255,255, + 255,201,0,0,0,0,0,175,251,89,0,0,0,0,0,89,255,166,0,0,7,206,247,34,0,7, + 206,225,21,0,0,7,206,225,21,0,0,175,225,21,0,0,138,255,255,255,255,255, + 255,166,7,206,125,0,0,0,0,0,0,138,201,0,0,0,12,235,125,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,127,0,0,89,255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,201,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,7,206,125,0,0,0,0,0,0,59,238,34,0,0,12,235,125,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,127,0,0,0,7,206,255,255,255,225,21,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,251,89,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,7,206,125,0,0,0,0,0,0,7,206,125,0,0,12,235,125,0,0,0, + 0,0,0,0,0,0,0,245,255,255,255,255,255,255,127,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138, + 255,255,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,255,255,201,0,0,0,0,0,0,89,89,255,255, + 255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127,127,127,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127, + 127,0,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127, + 0,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,127,0,127,127,127,127,127,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127, + 127,0,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,59,245,166,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,89,247,34,0,0,0,0,0,0,0,0,0,0,12,235, + 125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,225,21,0,0,0,0,0,0,0,0,0,12,235, + 255,247,0,0,0,0,0,0,0,12,12,235,125,0,0,0,0,0,0,0,0,0,0,0,0,12,235,125, + 0,0,0,0,0,12,235,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,255,251,89,0,7,206,125,0,89,255,251,89, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,255,255,255,255,255,255,255,255,255,255, + 125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,127,0,0,7,206,125,0,0,0,0,0,0,0,0,0,0,12,235,125,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,138,225,21,0,0,0,0,0,0,0,0,0,175,201,0,0,0,0,0,0, + 0,0,0,12,12,235,125,0,0,0,0,0,59,245,102,0,89,247,34,12,235,125,0,0,0,0, + 0,12,235,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,125,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,59,241,89,0,0,0,7,206,125,0,0,0,138,225,21,0, + 0,0,0,0,0,0,0,0,0,0,0,0,89,201,0,0,0,0,0,0,0,0,175,125,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,12,235,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138, + 225,21,0,0,0,0,0,0,0,12,0,235,125,0,0,0,0,0,0,0,0,0,0,12,235,125,0,0,0, + 0,0,0,0,0,0,0,0,0,12,235,125,0,0,0,0,0,12,235,125,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,12,235,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,247,34, + 0,0,0,7,206,125,0,0,0,59,238,34,0,0,0,0,0,0,0,0,0,0,0,0,0,89,201,0,0,0, + 0,0,0,0,0,175,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,12,235,255,255,255,166,0,12, + 235,166,245,255,247,34,0,0,12,235,255,255,247,34,0,34,235,255,255,255,225, + 21,0,12,235,255,255,225,29,0,206,255,255,255,127,0,12,235,255,255,255,225, + 21,12,235,138,235,255,247,34,0,12,235,102,175,255,247,34,12,235,125,0,59, + 245,201,0,12,235,125,12,0,235,166,245,255,225,29,206,255,251,89,0,12,235, + 138,235,255,247,34,0,0,12,235,255,255,201,0,0,12,235,166,245,255,251,89, + 0,0,12,235,255,255,255,225,21,12,235,138,235,247,127,34,138,255,255,255, + 206,0,206,255,255,255,201,59,241,89,0,0,89,247,42,206,201,0,0,0,138,225, + 187,201,0,0,138,225,21,0,59,241,187,226,247,34,0,7,206,206,206,201,0,0, + 0,138,225,151,255,255,255,255,247,0,0,89,247,34,0,0,0,7,206,125,0,0,0,59, + 238,34,0,0,0,0,0,0,0,0,0,0,0,0,0,89,201,0,0,0,0,0,0,0,0,175,125,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 0,0,0,0,0,0,0,0,12,206,21,0,59,245,125,12,235,247,34,0,138,225,21,12,235, + 166,0,0,134,102,0,235,166,0,0,138,225,21,12,235,125,0,0,175,201,12,0,235, + 125,0,0,12,235,166,0,0,138,225,21,12,235,247,34,0,175,201,0,12,235,102, + 0,89,247,34,12,235,125,12,235,166,0,0,12,235,125,12,0,235,225,21,12,235, + 251,89,0,175,201,0,12,235,247,34,0,175,201,0,12,235,166,0,7,206,201,0,12, + 235,225,21,0,175,225,21,12,235,166,0,0,138,225,21,12,235,247,34,0,0,89, + 247,34,0,12,206,34,0,235,125,0,0,59,241,89,0,0,89,247,34,89,247,34,0,7, + 206,166,138,225,21,7,206,251,89,0,89,225,138,34,235,201,0,138,225,21,89, + 247,34,0,7,206,166,0,0,0,7,206,166,0,0,89,225,21,0,0,0,7,206,125,0,0,0, + 59,241,89,0,0,0,0,138,251,89,0,0,7,202,89,0,89,201,0,0,0,0,0,0,0,0,175, + 125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,7,206,102,12,235,125,0,0,59,241,89, + 138,225,21,0,0,0,34,89,225,21,0,0,138,225,21,89,225,21,0,0,89,247,47,0, + 235,125,0,0,89,225,21,0,0,138,225,21,12,235,125,0,0,89,247,34,12,235,102, + 0,89,247,34,12,235,138,235,166,0,0,0,12,235,125,12,0,235,125,0,7,206,166, + 0,0,138,225,21,12,235,125,0,0,89,247,34,138,225,21,0,0,59,238,34,12,235, + 125,0,0,59,241,89,89,225,21,0,0,138,225,21,12,235,125,0,0,0,138,225,21, + 0,0,0,12,0,235,125,0,0,59,241,89,0,0,89,247,34,12,235,125,0,59,241,89,59, + 238,34,12,228,198,166,0,175,166,59,0,89,251,132,241,89,0,12,235,125,0,59, + 238,34,0,0,0,138,225,21,0,12,235,166,0,0,0,0,7,206,125,0,0,0,0,175,201, + 0,0,0,138,166,12,235,166,0,12,232,89,0,89,201,0,0,0,0,0,0,0,0,175,125,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,127,0,0,0,0,0,0,0,0,0,59,245,255,255,255,102,12,235,125,0,0,12,235, + 125,175,201,0,0,0,0,0,175,201,0,0,0,138,225,21,175,255,255,255,255,255, + 247,47,0,235,125,0,0,175,201,0,0,0,138,225,21,12,235,125,0,0,89,247,34, + 12,235,102,0,89,247,34,12,235,255,225,21,0,0,0,12,235,125,12,0,235,125, + 0,7,206,166,0,0,138,225,21,12,235,125,0,0,89,247,34,175,201,0,0,0,12,232, + 89,12,235,125,0,0,12,235,125,175,201,0,0,0,138,225,21,12,235,125,0,0,0, + 59,245,255,247,34,0,12,0,235,125,0,0,59,241,89,0,0,89,247,34,0,175,201, + 0,138,201,0,12,235,125,89,201,89,225,29,206,125,12,0,0,175,255,166,0,0, + 0,175,201,0,138,201,0,0,0,89,251,89,0,138,247,34,0,0,0,0,0,7,206,125,0, + 0,0,0,0,89,255,125,7,202,89,0,89,251,89,89,201,0,0,89,201,0,0,0,0,0,0,0, + 0,175,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,89,255,166,0,7,206,102,12,235,125,0, + 0,12,235,125,175,201,0,0,0,0,0,175,201,0,0,0,138,225,21,175,201,0,0,0,0, + 0,12,0,235,125,0,0,175,201,0,0,0,138,225,21,12,235,125,0,0,89,247,34,12, + 235,102,0,89,247,34,12,235,138,235,201,0,0,0,12,235,125,12,0,235,125,0, + 7,206,166,0,0,138,225,21,12,235,125,0,0,89,247,34,175,201,0,0,0,12,232, + 89,12,235,125,0,0,12,235,125,175,201,0,0,0,138,225,21,12,235,125,0,0,0, + 0,0,138,255,255,201,12,0,235,125,0,0,59,241,89,0,0,89,247,34,0,89,247,42, + 206,125,0,0,175,166,175,125,12,232,102,232,89,0,0,0,175,255,201,0,0,0,89, + 247,47,235,125,0,0,12,235,166,0,0,0,12,235,125,0,0,0,0,7,206,125,0,0,0, + 0,138,201,0,0,12,232,89,0,0,59,245,225,21,0,0,89,201,0,0,0,0,0,0,0,0,175, + 125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,127,0,0,0,0,0,0,0,0,175,201,0,0,7,206,102,12,235,125,0,0,59,241, + 89,138,225,21,0,0,0,34,89,225,21,0,0,138,225,21,138,247,34,0,0,0,0,12,0, + 235,125,0,0,138,225,21,0,0,138,225,21,12,235,125,0,0,89,247,34,12,235,102, + 0,89,247,34,12,235,125,59,245,125,0,0,12,235,125,12,0,235,125,0,7,206,166, + 0,0,138,225,21,12,235,125,0,0,89,247,34,138,225,21,0,0,89,247,34,12,235, + 125,0,0,59,241,89,138,225,21,0,0,138,225,21,12,235,125,0,0,0,0,0,0,0,89, + 247,47,0,235,125,0,0,59,241,89,0,0,89,247,34,0,12,235,166,238,34,0,0,138, + 210,228,34,0,175,166,215,21,0,0,89,251,159,251,89,0,0,12,235,191,247,34, + 0,0,175,225,21,0,0,0,0,138,225,21,0,0,0,7,206,125,0,0,0,12,232,89,0,0,0, + 0,0,0,0,0,0,0,0,0,0,89,201,0,0,0,0,0,0,0,0,175,125,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0, + 0,0,0,138,225,21,0,138,255,102,12,235,125,0,7,206,201,0,12,235,166,0,0, + 134,132,0,245,125,0,59,245,225,21,12,235,201,0,0,12,206,34,0,235,125,0, + 0,59,245,125,0,12,235,225,21,12,235,125,0,0,89,247,34,12,235,102,0,89,247, + 34,12,235,125,0,138,251,89,0,12,235,125,12,0,235,125,0,7,206,166,0,0,138, + 225,21,12,235,125,0,0,89,247,34,12,235,166,0,7,206,201,0,12,235,125,0,7, + 206,201,0,59,245,125,0,12,235,225,21,12,235,125,0,0,0,138,125,0,0,138,225, + 29,0,206,166,0,0,7,206,166,0,59,245,247,34,0,0,175,255,201,0,0,0,59,245, + 225,21,0,89,255,201,0,0,12,235,166,0,175,225,21,0,0,138,255,166,0,0,89, + 251,89,0,0,0,0,0,89,247,34,0,0,0,7,206,125,0,0,0,59,238,34,0,0,0,0,0,0, + 0,0,0,0,0,0,0,89,201,0,0,0,0,0,0,0,0,175,125,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0, + 7,206,255,255,171,206,102,12,232,226,255,255,225,21,0,0,12,235,255,255, + 247,34,0,89,255,255,247,163,225,21,0,7,206,255,255,247,34,12,0,235,125, + 0,0,0,89,255,255,247,163,225,21,12,235,125,0,0,89,247,34,12,235,102,0,89, + 247,34,12,235,125,0,0,175,251,34,0,235,125,12,0,235,125,0,7,206,166,0,0, + 138,225,21,12,235,125,0,0,89,247,34,0,12,235,255,255,201,0,0,12,235,255, + 255,255,225,21,0,0,89,255,255,247,163,225,21,12,235,125,0,0,0,89,255,255, + 255,247,34,0,0,89,255,255,127,0,59,245,255,225,111,247,34,0,0,59,245,125, + 0,0,0,12,235,166,0,0,59,245,125,7,0,206,225,21,0,12,235,201,0,0,59,241, + 89,0,0,175,255,255,255,255,247,0,0,89,247,34,0,0,0,7,206,125,0,0,0,59,238, + 34,0,0,0,0,0,0,0,0,0,0,0,0,0,89,255,255,255,255,255,255,255,255,255,255, + 125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,201,0,0,0,0,0, + 0,0,0,0,0,0,0,0,89,247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,125,0,0,0,0,0,0,0,0,0,0,138,225, + 21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,225,21,0,0,0,0,0,0,0,0,0,0,89, + 247,34,0,0,0,7,206,125,0,0,0,59,238,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,199,34,0,12, + 232,89,0,0,0,0,0,0,0,0,0,0,0,0,0,138,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,125,0,0,0,0, + 0,0,0,0,0,0,138,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,166,0,0,0, + 0,0,0,0,0,0,0,0,12,235,125,0,0,0,7,206,125,0,0,0,138,225,21,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,12,235,255,247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,255,251,89,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,12,235,125,0,0,0,0,0,0,0,0,0,0,138,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,89,247,34,0,0,0,0,0,0,0,0,0,0,0,0,89,255,251,89,0,7,206,125,0,89,255, + 247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,0,127,127,127,127,0,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,0,127,127,0,127,127,127,0,127,127,127,127,127,127, + 127,0,127,127,127,0,127,127,127,127,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127, + 127,127,127,0,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127, + 127,127,127,0,127,127,127,127,127,127,127,127,127,127,0,127,127,127,127, + 127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127, + 127,127,127,0,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,127,127,127,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,125,0,175,166,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,206,125,0,175, + 166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,245,225,21,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,255,125,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,255,125,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,166,0,138,201,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,166,0,138,201,0,7,206,166,12,235, + 125,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,125,0,0,0,0,0,175,125, + 0,0,0,0,0,175,171,206,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,255,125,0, + 31,206,130,255,166,175,247,34,0,0,89,255,125,175,247,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,245,247,34,138,166,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,59,241,132,238,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,59,241,132,238,34,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0, + 59,245,255,255,255,125,0,12,235,255,255,255,255,255,225,21,0,0,0,0,0,0, + 0,0,175,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,125,0,0,0, + 0,0,175,125,0,0,0,0,89,225,21,59,238,34,0,0,138,255,255,201,0,0,0,59,215, + 21,0,0,0,0,0,0,0,0,0,12,235,255,255,255,247,34,0,0,0,0,0,0,0,12,235,255, + 255,255,255,255,255,255,255,251,89,0,12,235,255,255,255,255,255,225,21, + 0,89,255,255,255,255,255,255,125,0,12,235,255,255,255,255,255,225,21,0, + 0,12,235,255,255,255,255,255,225,21,7,206,201,0,50,206,56,255,201,12,235, + 125,0,0,138,225,29,206,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,7,202,89,89,255,225,21,0,89,255,255,255,225,81,245,201,0,138,251, + 89,0,0,138,255,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,255,255, + 255,255,255,225,21,0,0,0,138,255,166,7,206,225,21,0,0,0,138,247,34,0,0, + 0,0,127,0,89,255,125,0,0,0,0,0,12,146,0,0,0,0,0,144,21,0,0,0,0,0,0,0,89, + 247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,125,0,0,0,0,0,175, + 125,0,0,0,0,0,0,0,0,0,0,0,59,241,89,12,235,125,0,0,172,89,0,0,0,0,0,0,0, + 0,0,12,235,166,0,0,7,202,89,0,0,0,0,0,0,89,255,201,0,0,12,235,125,0,0,0, + 0,0,0,12,146,0,0,0,0,0,144,21,0,0,0,0,0,0,138,247,34,0,12,146,0,0,0,0,0, + 144,21,0,0,12,146,0,0,0,0,0,144,21,0,89,225,21,71,157,22,191,225,21,175, + 201,0,7,206,125,59,238,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,175,125,0,59,196,199,47,206,184,89,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,146,0,0,0,0,0,144,21,0,0,0,0, + 0,0,0,59,245,125,0,0,59,245,125,0,0,0,0,0,127,12,235,166,0,0,0,0,0,0,12, + 146,0,0,0,0,0,144,21,0,0,0,0,0,0,0,175,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,12,235,255,255,255,255,127,34,235,255,255,255,255,225,21,0, + 0,0,0,0,0,0,0,89,247,34,7,206,166,0,89,201,0,0,0,0,0,0,0,0,0,0,89,247,34, + 0,0,0,0,0,0,0,0,59,115,12,235,166,0,0,0,12,235,125,0,0,0,0,0,0,12,146,0, + 0,0,0,0,144,21,0,0,0,0,0,59,245,125,0,0,12,146,0,0,0,0,0,144,21,0,0,12, + 146,0,0,0,0,0,144,21,0,7,202,89,117,104,0,29,202,89,59,215,21,59,215,21, + 138,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,175,125,0,59,192,89,223,125,172,89,0,138,255,255,255,201,12,182, + 0,0,0,0,0,175,255,255,125,0,89,255,255,247,34,0,0,12,146,0,0,0,0,0,144, + 21,0,138,255,255,255,255,247,34,138,247,34,7,206,201,0,0,0,0,0,0,127,89, + 251,89,0,0,0,0,0,0,12,146,0,0,0,0,0,144,21,0,0,0,0,0,0,7,206,166,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,125,0,0,0,0,0,175,125,0,0,0, + 0,0,0,0,0,0,0,0,89,247,34,7,206,166,7,202,89,0,0,0,0,0,0,0,0,0,0,89,255, + 125,0,0,0,0,0,0,0,89,255,125,89,247,34,0,0,0,12,235,125,0,0,0,0,0,0,12, + 146,0,0,0,0,0,144,21,0,0,0,0,7,206,201,0,0,0,12,146,0,0,0,0,0,144,21,0, + 0,12,146,0,0,0,0,0,144,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,245, + 255,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175, + 125,0,59,192,12,228,34,172,89,89,247,34,0,12,206,29,206,201,0,0,7,206,166, + 0,7,206,255,225,21,0,89,247,34,0,12,146,0,0,0,0,0,144,21,0,0,0,0,7,206, + 166,0,12,235,166,89,247,34,0,0,0,0,0,0,127,245,255,255,255,255,255,201, + 0,0,12,146,0,0,0,0,0,144,21,0,0,0,0,0,59,245,255,255,255,127,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,125,0,0,0,0,0,175,125,0,0,0,0,0,0,0, + 0,0,0,0,59,241,89,12,235,125,89,201,12,235,255,251,89,0,89,255,255,225, + 21,0,175,255,255,225,21,0,0,0,89,251,89,0,138,225,21,0,0,0,12,235,255,255, + 255,255,225,21,0,12,146,0,0,0,0,0,144,21,0,0,0,0,138,247,34,0,0,0,12,146, + 0,0,0,0,0,144,21,0,0,12,146,0,0,0,0,0,144,21,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,12,235,255,255,255,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,175,125,0,59,192,0,0,0,172,89,138,225,21,0,0,0, + 0,7,206,225,21,138,225,21,0,0,89,251,89,0,0,12,235,125,0,12,146,0,0,0,0, + 0,144,21,0,0,0,0,138,225,21,0,0,89,255,255,125,0,0,0,0,0,0,0,127,138,225, + 21,0,0,0,0,0,0,12,146,0,0,0,0,0,144,21,0,0,0,0,0,0,59,241,89,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,125,0,0,12,235,255,255,255,255, + 225,21,0,0,0,0,0,0,0,0,0,138,255,255,201,12,228,34,175,166,0,138,201,7, + 206,125,7,206,166,0,0,0,89,255,255,247,34,59,241,89,0,0,138,225,21,0,0, + 0,12,235,125,0,0,0,0,0,0,12,146,0,0,0,0,0,144,21,0,0,0,59,245,125,0,0,0, + 0,12,146,0,0,0,0,0,144,21,0,0,12,146,0,0,0,0,0,144,21,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,59,245,255,255,255,207,235,255,255,255,255,255,255, + 207,235,255,255,255,255,255,255,255,255,255,255,255,225,21,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,59,245,255,247,34,0,0,0,0,175,166,175,201,0,0,0, + 59,245,255,255,255,255,255,125,0,12,146,0,0,0,0,0,144,21,0,0,0,89,251,89, + 0,0,0,7,206,225,21,0,0,0,0,0,0,0,127,245,255,255,255,255,255,125,0,0,12, + 146,0,0,0,0,0,144,21,0,0,0,0,0,0,59,241,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,175,125,0,0,0,0,0,175,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,138,166,7,206,125,0,89,247,94,241,89,0,138,201,0,0,0,0,0,59,245,166, + 0,89,251,89,0,89,247,34,0,0,0,12,235,125,0,0,0,0,0,0,12,146,0,0,0,0,0,144, + 21,0,0,7,206,201,0,0,0,0,0,12,146,0,0,0,0,0,144,21,0,0,12,146,0,0,0,0,0, + 144,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,255,255,255,166,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,138,255,255,201,0,7,206,225,21,175,201,0,0,0,59,241,89,0,0,0,0, + 0,0,12,146,0,0,0,0,0,144,21,0,0,12,235,166,0,0,0,0,0,175,225,21,0,0,0,0, + 0,0,0,127,89,255,125,0,0,0,0,0,0,12,146,0,0,0,0,0,144,21,0,0,0,0,0,0,89, + 247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,125,0,0,0,0,0, + 175,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,228,34,7,206,125,0,89,247,94,241, + 89,0,138,201,0,0,0,0,0,12,235,166,0,0,89,255,125,12,235,166,0,0,0,12,235, + 125,0,0,0,0,0,0,12,146,0,0,0,0,0,144,21,0,0,138,247,34,0,0,0,0,0,12,146, + 0,0,0,0,0,144,21,0,0,12,146,0,0,0,0,0,144,21,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,59,245,255,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,247,42,206,201,0,0,89, + 225,21,0,0,89,255,125,0,0,0,0,0,0,12,146,0,0,0,0,0,144,21,0,0,175,225,21, + 0,0,0,0,0,175,225,21,0,0,0,0,0,0,0,127,0,175,251,89,0,0,0,0,0,12,146,0, + 0,0,0,0,144,21,0,59,245,166,0,0,138,225,21,0,0,0,59,245,166,138,251,89, + 7,206,201,0,12,235,125,0,59,241,89,0,0,0,175,125,0,0,0,0,0,175,125,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,138,166,0,0,175,166,0,138,201,7,206,125,7,206, + 166,138,166,0,0,0,138,251,89,0,0,0,59,115,0,89,255,201,0,0,12,235,125,0, + 0,0,0,0,0,12,146,0,0,0,0,0,144,21,0,89,251,89,0,0,0,0,0,0,12,146,0,0,0, + 0,0,144,21,0,0,12,146,0,0,0,0,0,144,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,138,125,0,0,138,225,34,182,0,0,0,7,206,166,0, + 7,206,255,247,34,0,0,175,125,0,12,146,0,0,0,0,0,144,21,0,89,251,89,0,0, + 0,0,0,0,175,225,21,0,0,0,0,0,0,0,127,0,0,138,255,255,255,255,125,0,12,235, + 255,255,255,255,255,225,21,0,138,247,34,0,7,206,166,0,0,0,0,89,247,34,175, + 201,0,7,206,201,0,12,235,125,0,59,241,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,59,215,21,0,0,12,235,255,251,89,0,89,255,255,225, + 21,12,235,255,255,255,247,34,0,0,0,0,0,0,0,0,12,235,255,255,255,255,255, + 255,255,255,251,89,0,12,235,255,255,255,255,255,225,21,0,138,255,255,255, + 255,255,255,166,0,12,235,255,255,255,255,255,225,21,0,0,12,235,255,255, + 255,255,255,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,89,255,255,255,247,34,0,0,0,0,0,0,0,175,255,255,125,0,138,255,255, + 255,125,0,0,12,235,255,255,255,255,255,225,21,0,175,255,255,255,255,247, + 0,0,0,175,225,21,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,175,166,0,255,255,201,0,0,0,0,0,175,166,12,232,89,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12, + 228,34,0,0,0,0,0,0,0,0,12,232,89,59,215,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127,0,127, + 127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127, + 127,127,127,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127, + 127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 127,127,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 0,127,127,127,127,0,127,127,127,127,127,127,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 127,0,127,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127, + 127,127,0,127,127,127,0,127,127,0,127,127,127,127,127,0,127,127,127,127, + 127,0,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127, + 127,127,127,127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127, + 0,127,127,127,127,127,127,127,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,127,127,0,127,127,127,127,127,0,127,127,127,127,127,127,127, + 127,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,245,255,255,255,255,255,255,225,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,225,21,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,7,206,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,89,247, + 34,0,0,0,0,59,192,0,0,0,0,0,7,206,255,255,225,21,0,0,0,0,0,0,0,0,138,247, + 34,0,0,89,251,89,0,7,206,125,0,0,7,206,255,255,255,166,0,89,251,89,138, + 247,34,0,0,0,0,7,206,255,255,255,247,34,0,0,0,0,175,255,255,251,89,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,255,255,255,247, + 34,0,0,0,0,0,0,0,0,0,0,0,0,89,255,255,247,34,0,0,0,0,0,0,0,0,0,0,0,0,12, + 235,255,247,34,0,0,7,206,255,251,89,0,0,7,206,125,0,0,0,0,0,0,0,0,0,0,0, + 0,89,255,255,255,255,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,202,89,0,0,0, + 59,245,255,247,34,0,0,0,0,0,0,0,0,0,0,0,89,201,0,0,0,0,175,166,0,0,0,0, + 0,0,89,201,0,0,0,0,175,166,0,0,0,0,0,59,245,255,201,0,0,0,59,241,89,0,0, + 0,0,0,59,245,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,89,247,34, + 0,0,0,0,59,192,0,0,0,0,0,175,201,0,0,144,21,0,0,0,0,0,0,0,0,7,206,166,0, + 7,206,166,0,0,7,206,125,0,7,206,201,0,0,89,166,0,0,0,0,0,0,0,0,0,0,89,255, + 125,0,0,0,59,245,166,0,0,0,0,0,0,12,206,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,89,255,125,0,0,0,59,245,166,0,0,0,0,0,0,0,0,0,0,59, + 241,89,0,138,201,0,0,0,0,0,138,166,0,0,0,0,0,168,34,7,206,166,0,0,172,89, + 0,175,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,255,255,255,166,89,225,21, + 0,0,0,0,0,0,0,0,0,0,0,0,0,89,255,251,89,0,0,12,235,125,0,138,225,21,0,0, + 0,0,0,0,0,0,7,206,255,201,0,0,0,89,225,21,0,0,0,0,7,206,255,201,0,0,0,89, + 225,21,0,0,0,0,12,206,21,12,235,125,0,0,175,166,0,0,0,0,0,0,59,245,125, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,175,255,255,255, + 166,0,0,12,235,125,0,0,0,0,89,225,21,0,0,12,232,89,0,89,247,34,89,247,34, + 0,0,7,206,125,0,12,235,125,0,0,0,0,0,0,0,0,0,0,0,0,0,89,225,21,0,0,0,0, + 0,7,206,125,0,0,7,206,255,255,247,34,0,0,0,85,89,0,85,89,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,89,225,21,0,0,0,0,0,7,206,125,0,0,0,0,0,0,0,0,0,89,201, + 0,0,12,228,34,0,0,0,0,138,166,0,0,0,0,0,0,0,7,206,125,0,0,7,206,255,166, + 0,0,0,0,0,0,0,0,0,12,235,125,0,0,89,247,34,175,255,255,255,166,89,225,21, + 0,89,255,125,0,0,0,0,0,0,0,0,0,0,7,202,89,0,0,89,225,21,0,12,232,89,59, + 115,0,59,115,0,0,0,0,0,89,201,0,0,7,206,125,0,0,0,0,0,0,0,89,201,0,0,7, + 206,125,0,0,0,0,0,0,0,0,12,232,89,0,59,238,34,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,89,225,21,0,0,138,247,94,192,12,182, + 0,0,12,235,125,0,0,0,0,0,175,255,255,255,255,166,0,0,7,206,171,206,166, + 0,0,0,7,206,125,0,7,206,251,89,0,0,0,0,0,0,0,0,0,0,0,7,202,89,0,59,245, + 255,255,201,0,12,228,34,12,235,166,0,12,228,34,0,0,138,251,89,138,247,34, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,202,89,0,138,255,255,255,125,0,12,228,34, + 0,0,0,0,0,0,0,0,59,241,89,0,138,201,0,0,0,0,0,138,166,0,0,0,0,0,0,0,175, + 201,0,0,0,0,0,0,175,201,0,0,0,0,0,0,0,0,12,235,125,0,0,89,247,34,175,255, + 255,255,166,89,225,21,0,89,255,125,0,0,0,0,0,0,0,0,0,0,7,202,89,0,0,138, + 225,21,0,12,235,125,12,235,166,59,245,166,0,0,0,0,89,201,0,0,89,225,21, + 0,0,0,0,0,0,0,89,201,0,0,89,225,21,0,0,0,0,0,0,12,235,255,125,0,0,175,125, + 0,0,0,0,0,0,0,12,235,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,89, + 225,21,0,12,235,125,59,192,0,0,0,0,12,235,125,0,0,0,0,0,59,215,21,59,238, + 34,0,0,0,89,255,247,34,0,0,0,7,206,125,0,0,7,206,255,255,247,34,0,0,0,0, + 0,0,0,0,59,192,0,12,235,166,0,7,176,21,0,175,125,59,238,34,0,12,228,34, + 0,138,247,34,138,247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,192,0,0,138, + 201,0,89,247,34,0,175,125,0,0,0,0,0,0,0,0,0,89,255,255,225,21,0,7,206,255, + 255,255,255,255,255,247,34,0,12,235,125,0,0,0,7,176,21,0,175,201,0,0,0, + 0,0,0,0,0,12,235,125,0,0,89,247,34,89,255,255,255,166,89,225,21,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,7,202,89,0,0,89,225,21,0,12,232,89,0,12,235,166,12, + 235,166,0,0,0,89,201,0,7,206,125,0,12,235,166,0,0,0,0,89,201,0,7,206,125, + 89,255,255,255,125,0,0,0,0,7,206,125,89,225,21,0,138,225,21,0,0,0,138,255, + 125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,89,247,34,0,59,241,89,59, + 192,0,0,0,12,235,255,255,255,225,21,0,0,138,166,0,7,202,89,0,0,0,7,206, + 166,0,0,0,0,0,0,0,0,7,206,125,0,12,235,201,0,0,0,0,0,0,0,0,89,166,0,89, + 247,34,0,0,0,0,0,89,166,12,232,89,0,138,247,34,89,247,34,59,238,34,0,0, + 12,235,255,255,255,255,255,255,247,34,89,255,255,255,166,89,166,0,0,138, + 201,0,138,225,21,0,89,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,166, + 0,0,0,0,7,206,255,255,255,247,34,0,59,245,255,247,34,0,0,0,0,0,0,0,0,12, + 235,125,0,0,89,247,34,0,89,255,255,166,89,225,21,0,0,0,0,0,0,0,0,0,0,0, + 0,0,89,255,255,255,166,0,12,235,125,0,138,225,21,0,0,12,235,125,12,235, + 125,0,0,89,201,0,89,201,0,7,206,223,166,0,0,0,0,89,201,0,89,201,0,89,125, + 0,138,225,21,12,182,0,7,206,133,206,125,0,89,232,215,21,0,7,206,247,34, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,89,247,34,0,59,241,89,59, + 192,0,0,0,0,12,235,125,0,0,0,0,0,59,215,21,59,238,34,0,59,245,255,255,255, + 255,225,21,0,0,0,0,0,59,241,89,0,0,138,225,21,0,0,0,0,0,0,0,89,166,0,89, + 247,34,0,0,0,0,0,89,166,0,138,255,255,176,228,34,0,138,247,34,138,247,34, + 0,0,0,0,0,0,0,0,59,238,34,0,0,0,0,0,89,166,0,0,138,255,255,225,21,0,0,89, + 166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,166,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,125,0,0,89,247,34,0,0,0,138,166,89,225, + 21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,245,255,247,34,0,0,12,235, + 166,12,235,166,0,0,0,0,0,12,232,89,0,175,166,138,166,0,0,0,0,0,0,12,232, + 89,0,0,0,0,138,201,0,0,89,255,255,201,89,225,21,89,225,81,215,21,0,138, + 247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,89,247,34,0,12,235, + 125,59,192,0,0,0,0,59,241,89,0,0,0,0,0,175,255,255,255,255,166,0,0,0,7, + 206,166,0,0,0,0,7,206,125,0,12,235,201,0,7,206,166,0,0,0,0,0,0,0,0,59,192, + 0,12,235,166,0,7,176,21,0,175,125,0,0,0,0,0,0,0,0,0,138,251,89,138,247, + 34,0,0,0,0,0,0,0,59,238,34,0,0,0,0,0,59,192,0,0,138,201,59,245,166,0,0, + 175,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,166,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,125,0,0,89,247,34,0,0,0,138,166, + 89,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,166, + 59,245,166,0,0,0,0,0,0,138,201,0,138,201,0,138,166,0,0,0,0,0,0,138,201, + 0,0,0,0,89,247,34,0,0,0,0,0,7,206,125,59,238,34,59,215,21,0,175,225,21, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,89,247,34,0,0,175,225,81, + 192,12,182,0,7,206,125,0,0,0,0,0,89,225,21,0,0,12,232,89,0,0,7,206,166, + 0,0,0,0,7,206,125,0,0,59,245,255,255,166,0,0,0,0,0,0,0,0,0,7,202,89,0,59, + 245,255,255,166,0,12,228,34,0,0,0,0,0,0,0,0,0,0,85,89,0,85,89,0,0,0,0,0, + 0,0,59,238,34,0,0,0,0,0,7,202,89,0,138,201,0,59,245,225,34,228,34,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,7,206,255,255,255,255,255,255,247,34,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,201,0,0,175,247,34,0,0,0,138,166, + 89,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,115,0, + 59,115,0,0,0,0,0,0,12,232,89,0,175,255,255,255,255,201,0,0,0,0,12,232,89, + 0,0,0,138,201,0,0,0,0,0,0,0,89,201,0,89,255,255,255,255,247,34,138,251, + 89,0,7,176,21,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,138,247,34,0,0,0, + 175,255,255,255,166,0,89,255,255,255,255,255,247,34,0,0,0,0,0,0,0,0,0,0, + 7,206,166,0,0,0,0,7,206,125,0,0,0,0,0,138,255,166,0,0,0,0,0,0,0,0,0,89, + 225,21,0,0,0,0,0,7,206,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,59,238,34,0,0,0,0,0,0,89,225,21,0,0,0,0,0,7,206,125,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,12,235,191,255,255,166,238,34,0,0,0,138,166,89,225,21,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,201,0,0, + 0,0,0,138,166,0,0,0,0,0,175,201,0,0,0,89,255,255,255,255,125,0,0,0,12,232, + 89,0,0,0,0,59,215,21,0,0,138,255,255,255,225,21,0,0,0,0,0,0,0,0,0,0,0,0, + 0,127,0,0,0,0,0,0,0,0,0,0,0,0,59,192,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,7,206,125,0,0,0,0,0,0,175,201,0,0,0,0,0,0,0,0,0,0, + 89,255,125,0,0,0,59,245,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,89,255,125,0,0,0,59,245,166,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,12,235,125,0,0,0,0,0,0,0,0,138,166,89,225,21,0,0,0,0,0,0,0,0,0,175, + 125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,59,192,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,125,0,7,199,34, + 0,12,235,125,0,0,0,0,0,0,0,0,0,0,0,7,206,255,255,255,247,34,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,255,255, + 255,247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,125,0,0,0,0,0,0,0,0,138,166, + 89,225,21,0,0,0,0,0,0,0,0,7,202,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,7,206,125,0,7,206,255,255,255,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,125,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,12,235,255,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127, + 127,127,0,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 127,0,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127, + 127,0,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127, + 0,127,127,127,127,0,127,127,127,127,127,127,127,127,127,127,127,127,0,127, + 127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,0,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,0,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127, + 127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127, + 127,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,138,225, + 21,0,0,0,0,0,12,235,125,0,0,0,0,19,172,255,190,11,0,0,0,0,138,255,201,7, + 202,89,0,0,0,0,0,0,0,0,0,0,7,206,255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,59,138,225,21,0,0,0,0,0,0,59,245,201,0,0,0,19,172, + 255,190,11,0,0,0,0,0,0,0,0,0,7,206,225,21,0,0,0,59,245,201,19,172,255,190, + 11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,251,89,89,201,0,0,0,0,0,175, + 201,0,0,0,0,0,0,0,0,7,206,225,21,0,0,0,0,0,19,172,255,190,11,0,0,0,0,0, + 175,255,166,12,228,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,89,255,125,0,0,0,0,0,0,0,12,175,247,34,0,0,0,19,172,255, + 190,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,247,34,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,127,0,0,0,7,206,125,0,0,0,0,0,138,201,0,0,0,0,0,136,190, + 45,196,145,0,0,0,59,215,21,175,255,166,0,0,0,175,225,29,206,166,0,0,7,202, + 89,7,202,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,209,125, + 0,0,0,0,0,0,138,225,21,0,0,0,136,190,45,196,145,0,0,0,175,225,29,206,166, + 0,0,12,235,125,0,0,12,138,225,21,136,190,45,196,145,159,251,89,138,247, + 34,0,0,0,0,0,0,0,0,0,0,0,175,125,59,245,247,34,0,0,0,0,0,12,232,89,0,0, + 0,0,0,0,0,175,166,0,0,0,0,0,0,12,136,190,45,196,145,0,0,0,0,138,166,12, + 235,255,125,0,0,0,0,7,206,166,12,235,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,12,232,89,0,0,0,0,0,0,138,201,0,0,0,0,0,136,190,45, + 196,145,34,0,0,0,89,251,89,138,247,34,0,0,0,0,0,138,201,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,202,89,7,202,89,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,255, + 255,125,0,0,0,0,127,0,0,7,206,251,89,0,0,0,0,7,206,251,89,0,0,0,0,7,206, + 251,89,0,0,0,0,0,7,206,251,89,0,0,0,0,7,206,251,89,0,0,0,0,12,235,255,125, + 0,0,0,0,0,89,255,255,255,255,255,255,255,255,125,0,0,0,59,245,255,255,255, + 201,12,235,255,255,255,255,255,125,12,235,255,255,255,255,255,125,12,235, + 255,255,255,255,255,125,12,235,255,255,255,255,255,125,89,255,255,255,201, + 89,255,255,255,201,89,255,255,255,201,89,255,255,255,201,0,175,255,255, + 255,255,201,0,0,0,12,235,251,89,0,0,12,235,125,0,0,0,138,255,255,166,0, + 0,0,0,0,0,138,255,255,166,0,0,0,0,0,0,138,255,255,166,0,0,0,0,0,0,138,255, + 255,166,0,0,0,0,0,0,138,255,255,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138, + 255,255,201,89,251,89,12,235,125,0,0,0,59,245,125,12,235,125,0,0,0,59,245, + 125,12,235,125,0,0,0,59,245,125,12,235,125,0,0,0,59,245,125,7,206,225,21, + 0,0,0,138,247,0,235,166,0,0,0,0,0,0,138,225,21,7,206,166,0,0,0,127,0,0, + 59,245,255,166,0,0,0,0,59,245,255,166,0,0,0,0,59,245,255,166,0,0,0,0,0, + 59,245,255,166,0,0,0,0,59,245,255,166,0,0,0,0,59,245,255,166,0,0,0,0,0, + 175,201,7,206,166,0,0,0,0,0,0,0,138,255,125,0,0,7,202,102,235,166,0,0,0, + 0,0,12,235,166,0,0,0,0,0,12,235,166,0,0,0,0,0,12,235,166,0,0,0,0,0,0,12, + 235,125,0,0,12,235,125,0,0,12,235,125,0,0,12,235,125,0,0,175,201,0,0,7, + 206,251,89,0,12,235,255,201,0,0,12,235,125,0,59,245,166,0,0,138,251,89, + 0,0,59,245,166,0,0,138,251,89,0,0,59,245,166,0,0,138,251,89,0,0,59,245, + 166,0,0,138,251,89,0,0,59,245,166,0,0,138,251,89,0,0,0,0,0,0,0,0,0,0,0, + 0,59,245,166,0,0,89,255,166,0,12,235,125,0,0,0,59,245,125,12,235,125,0, + 0,0,59,245,125,12,235,125,0,0,0,59,245,125,12,235,125,0,0,0,59,245,125, + 0,59,245,125,0,0,59,245,125,12,235,166,0,0,0,0,0,12,235,125,0,0,175,201, + 0,0,0,127,0,0,138,225,151,225,21,0,0,0,138,225,151,225,21,0,0,0,138,225, + 151,225,21,0,0,0,0,138,225,151,225,21,0,0,0,138,225,151,225,21,0,0,0,138, + 225,151,225,21,0,0,0,59,241,89,7,206,166,0,0,0,0,0,0,12,235,166,0,0,0,0, + 0,12,235,166,0,0,0,0,0,12,235,166,0,0,0,0,0,12,235,166,0,0,0,0,0,12,235, + 166,0,0,0,0,0,0,12,235,125,0,0,12,235,125,0,0,12,235,125,0,0,12,235,125, + 0,0,175,201,0,0,0,0,175,225,21,12,235,166,245,125,0,12,235,125,12,235,125, + 0,0,0,0,138,247,34,12,235,125,0,0,0,0,138,247,34,12,235,125,0,0,0,0,138, + 247,34,12,235,125,0,0,0,0,138,247,34,12,235,125,0,0,0,0,138,247,34,0,138, + 225,21,0,0,0,175,201,0,12,235,125,0,0,7,202,159,247,34,12,235,125,0,0,0, + 59,245,125,12,235,125,0,0,0,59,245,125,12,235,125,0,0,0,59,245,125,12,235, + 125,0,0,0,59,245,125,0,0,138,247,34,7,206,201,0,12,235,255,255,255,251, + 89,0,12,235,125,0,12,235,125,0,0,0,127,0,7,206,166,59,241,89,0,0,7,206, + 166,59,241,89,0,0,7,206,166,59,241,89,0,0,0,7,206,166,59,241,89,0,0,7,206, + 166,59,241,89,0,0,7,206,166,59,241,89,0,0,0,138,225,21,7,206,166,0,0,0, + 0,0,0,89,247,34,0,0,0,0,0,12,235,166,0,0,0,0,0,12,235,166,0,0,0,0,0,12, + 235,166,0,0,0,0,0,12,235,166,0,0,0,0,0,0,12,235,125,0,0,12,235,125,0,0, + 12,235,125,0,0,12,235,125,0,0,175,201,0,0,0,0,59,241,89,12,235,125,138, + 225,21,12,235,125,89,247,34,0,0,0,0,59,245,125,89,247,34,0,0,0,0,59,245, + 125,89,247,34,0,0,0,0,59,245,125,89,247,34,0,0,0,0,59,245,125,89,247,34, + 0,0,0,0,59,245,125,0,0,175,225,21,0,175,225,21,0,89,247,34,0,0,138,166, + 12,235,125,12,235,125,0,0,0,59,245,125,12,235,125,0,0,0,59,245,125,12,235, + 125,0,0,0,59,245,125,12,235,125,0,0,0,59,245,125,0,0,12,235,166,89,247, + 34,0,12,235,166,0,0,138,251,89,12,235,133,206,255,125,0,0,0,0,127,0,59, + 241,89,7,206,166,0,0,59,241,89,7,206,166,0,0,59,241,89,7,206,166,0,0,0, + 59,241,89,7,206,166,0,0,59,241,89,7,206,166,0,0,59,241,89,7,206,166,0,0, + 12,235,125,0,7,206,255,255,255,255,247,34,0,138,225,21,0,0,0,0,0,12,235, + 255,255,255,255,247,34,12,235,255,255,255,255,247,34,12,235,255,255,255, + 255,247,34,12,235,255,255,255,255,247,34,0,12,235,125,0,0,12,235,125,0, + 0,12,235,125,0,0,12,235,125,0,206,255,255,255,247,34,0,12,235,125,12,235, + 125,12,235,125,12,235,125,138,225,21,0,0,0,0,12,235,166,138,225,21,0,0, + 0,0,12,235,166,138,225,21,0,0,0,0,12,235,166,138,225,21,0,0,0,0,12,235, + 166,138,225,21,0,0,0,0,12,235,166,0,0,0,175,225,187,225,21,0,0,138,225, + 21,0,59,215,21,7,206,166,12,235,125,0,0,0,59,245,125,12,235,125,0,0,0,59, + 245,125,12,235,125,0,0,0,59,245,125,12,235,125,0,0,0,59,245,125,0,0,0,89, + 255,255,125,0,0,12,235,166,0,0,12,235,166,12,235,125,0,7,206,201,0,0,0, + 127,0,138,225,21,0,138,225,21,0,138,225,21,0,138,225,21,0,138,225,21,0, + 138,225,21,0,0,138,225,21,0,138,225,21,0,138,225,21,0,138,225,21,0,138, + 225,21,0,138,225,21,0,89,255,255,255,255,255,166,0,0,0,0,0,0,138,225,21, + 0,0,0,0,0,12,235,166,0,0,0,0,0,12,235,166,0,0,0,0,0,12,235,166,0,0,0,0, + 0,12,235,166,0,0,0,0,0,0,12,235,125,0,0,12,235,125,0,0,12,235,125,0,0,12, + 235,125,0,0,175,201,0,0,0,0,12,235,125,12,235,125,0,138,225,34,235,125, + 138,225,21,0,0,0,0,12,235,166,138,225,21,0,0,0,0,12,235,166,138,225,21, + 0,0,0,0,12,235,166,138,225,21,0,0,0,0,12,235,166,138,225,21,0,0,0,0,12, + 235,166,0,0,0,0,175,225,21,0,0,0,138,225,21,7,202,89,0,7,206,166,12,235, + 125,0,0,0,59,245,125,12,235,125,0,0,0,59,245,125,12,235,125,0,0,0,59,245, + 125,12,235,125,0,0,0,59,245,125,0,0,0,7,206,225,21,0,0,12,235,166,0,0,12, + 235,166,12,235,125,0,0,59,241,89,0,0,127,7,206,255,255,255,255,251,89,7, + 206,255,255,255,255,251,89,7,206,255,255,255,255,251,89,0,7,206,255,255, + 255,255,251,89,7,206,255,255,255,255,251,89,7,206,255,255,255,255,251,89, + 7,206,166,0,0,7,206,166,0,0,0,0,0,0,89,247,34,0,0,0,0,0,12,235,166,0,0, + 0,0,0,12,235,166,0,0,0,0,0,12,235,166,0,0,0,0,0,12,235,166,0,0,0,0,0,0, + 12,235,125,0,0,12,235,125,0,0,12,235,125,0,0,12,235,125,0,0,175,201,0,0, + 0,0,59,241,89,12,235,125,0,12,235,138,235,125,89,247,34,0,0,0,0,59,245, + 125,89,247,34,0,0,0,0,59,245,125,89,247,34,0,0,0,0,59,245,125,89,247,34, + 0,0,0,0,59,245,125,89,247,34,0,0,0,0,59,245,125,0,0,0,175,225,187,225,21, + 0,0,138,247,34,175,125,0,0,12,235,125,12,235,125,0,0,0,59,241,89,12,235, + 125,0,0,0,59,241,89,12,235,125,0,0,0,59,241,89,12,235,125,0,0,0,59,241, + 89,0,0,0,0,175,225,21,0,0,12,235,166,0,0,175,247,34,12,235,125,0,0,12,235, + 125,0,0,127,59,241,89,0,0,7,206,166,59,241,89,0,0,7,206,166,59,241,89,0, + 0,7,206,166,0,59,241,89,0,0,7,206,166,59,241,89,0,0,7,206,166,59,241,89, + 0,0,7,206,166,59,241,89,0,0,7,206,166,0,0,0,0,0,0,59,245,166,0,0,0,0,0, + 12,235,166,0,0,0,0,0,12,235,166,0,0,0,0,0,12,235,166,0,0,0,0,0,12,235,166, + 0,0,0,0,0,0,12,235,125,0,0,12,235,125,0,0,12,235,125,0,0,12,235,125,0,0, + 175,201,0,0,0,0,175,225,21,12,235,125,0,0,138,232,245,125,12,235,125,0, + 0,0,0,138,247,34,12,235,125,0,0,0,0,138,247,34,12,235,125,0,0,0,0,138,247, + 34,12,235,125,0,0,0,0,138,247,34,12,235,125,0,0,0,0,138,247,34,0,0,175, + 225,21,0,175,225,21,0,59,245,191,201,0,0,0,89,225,21,12,235,166,0,0,0,89, + 251,89,12,235,166,0,0,0,89,251,89,12,235,166,0,0,0,89,251,89,12,235,166, + 0,0,0,89,251,89,0,0,0,0,175,225,21,0,0,12,235,255,255,255,247,34,0,12,235, + 125,0,0,59,241,89,0,0,127,138,225,21,0,0,0,138,247,163,225,21,0,0,0,138, + 247,163,225,21,0,0,0,138,247,34,138,225,21,0,0,0,138,247,163,225,21,0,0, + 0,138,247,163,225,21,0,0,0,138,247,198,225,21,0,0,7,206,166,0,0,0,0,0,0, + 0,138,255,125,0,0,7,202,102,235,166,0,0,0,0,0,12,235,166,0,0,0,0,0,12,235, + 166,0,0,0,0,0,12,235,166,0,0,0,0,0,0,12,235,125,0,0,12,235,125,0,0,12,235, + 125,0,0,12,235,125,0,0,175,201,0,0,7,206,251,89,0,12,235,125,0,0,12,235, + 255,125,0,89,255,125,0,0,89,251,89,0,0,89,255,125,0,0,89,251,89,0,0,89, + 255,125,0,0,89,251,89,0,0,89,255,125,0,0,89,251,89,0,0,89,255,125,0,0,89, + 251,89,0,0,138,225,21,0,0,0,175,201,0,0,138,251,89,0,0,89,251,89,0,0,138, + 247,34,0,7,206,225,21,0,138,247,34,0,7,206,225,21,0,138,247,34,0,7,206, + 225,21,0,138,247,34,0,7,206,225,21,0,0,0,0,175,225,21,0,0,12,235,166,0, + 0,0,0,0,12,235,125,0,0,175,225,21,0,0,127,206,166,0,0,0,0,59,245,255,166, + 0,0,0,0,59,245,255,166,0,0,0,0,59,245,133,206,166,0,0,0,0,59,245,255,166, + 0,0,0,0,59,245,255,166,0,0,0,0,59,245,255,125,0,0,0,7,206,255,255,255,255, + 255,125,0,0,0,59,245,255,255,255,201,12,235,255,255,255,255,255,125,12, + 235,255,255,255,255,255,125,12,235,255,255,255,255,255,125,12,235,255,255, + 255,255,255,125,89,255,255,255,201,89,255,255,255,201,89,255,255,255,201, + 89,255,255,255,201,0,175,255,255,255,255,225,21,0,0,12,235,125,0,0,0,138, + 255,125,0,0,0,175,255,255,201,0,0,0,0,0,0,175,255,255,201,0,0,0,0,0,0,175, + 255,255,201,0,0,0,0,0,0,175,255,255,201,0,0,0,0,0,0,175,255,255,201,0,0, + 0,0,0,0,0,0,0,0,0,0,0,7,202,97,206,255,255,201,0,0,0,0,0,138,255,255,255, + 201,0,0,0,0,138,255,255,255,201,0,0,0,0,138,255,255,255,201,0,0,0,0,138, + 255,255,255,201,0,0,0,0,0,0,175,225,21,0,0,12,235,166,0,0,0,0,0,12,235, + 133,206,255,225,21,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,138,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,138,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,175,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,255,225,21, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127,127,127, + 127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127, + 127,127,127,127,0,127,127,127,127,127,127,127,127,127,127,127,127,127,0, + 127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127, + 127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127, + 127,0,127,127,127,127,0,127,127,127,127,0,127,127,127,127,0,127,127,127, + 127,0,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 127,0,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 127,127,0,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127, + 127,127,127,0,127,127,127,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,127,127,0,127,127,127,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,127,0,127,127,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,127,0,127,127,127,127,127,127,127,127,0,127,127,127,127,127,127, + 127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127, + 0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,7,206,225,21, + 0,0,0,0,0,12,235,225,21,0,0,89,255,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,7,206,255,247,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,247, + 34,0,0,0,0,0,0,0,138,251,89,0,0,59,245,247,34,0,0,0,0,0,0,0,0,0,175,247, + 34,0,0,175,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,225,21, + 0,0,0,0,0,0,0,138,255,125,0,0,0,12,235,251,89,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,251,89,0,0,0,0,0,0, + 7,206,225,21,0,0,0,7,206,251,89,0,0,0,0,0,0,0,0,0,0,0,0,0,59,245,166,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,59,241,89,0,0,0,0, + 0,89,247,34,0,0,7,206,138,235,125,0,0,89,255,225,21,175,125,0,0,0,0,0,0, + 0,0,0,138,201,0,138,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12, + 235,125,0,0,0,0,0,0,12,235,125,0,0,0,175,171,206,166,0,0,0,0,0,0,0,0,0, + 7,206,166,0,59,245,255,166,238,0,0,0,0,0,0,0,0,0,0,0,0,7,206,255,125,59, + 215,21,0,0,59,241,89,0,0,0,0,0,0,7,206,166,0,0,0,0,138,201,175,201,0,0, + 0,12,235,251,89,89,201,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,7,206,166,0,0,0,0,0,0,89,247,34,0,0,0,0,89,225,151,201,0,0,0,0, + 0,0,0,0,0,0,0,0,0,175,201,0,12,235,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,127,0,0,0,138,201,0,0,0,0,7,206,125,0,0,0,138,201,0,89,225,21, + 12,228,34,138,255,201,0,0,0,138,247,34,175,225,21,0,138,201,0,138,201,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,225,21,0,0,0,0,0,89,225, + 21,0,0,89,247,34,59,241,89,0,59,241,89,89,247,34,0,0,89,225,21,175,127, + 215,21,206,247,42,206,0,138,255,247,42,206,125,0,0,138,166,12,235,251,89, + 0,0,0,0,138,201,0,0,0,0,0,0,89,225,21,0,0,0,59,241,89,12,235,125,0,0,175, + 125,59,245,247,34,0,0,12,235,125,89,251,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,59,238,34,0,0,0,0,0,175,166,0,0,0,0,12,232,89,7,206,125,0, + 0,12,235,166,59,245,125,0,0,0,59,238,34,0,12,235,125,0,0,0,0,0,0,89,247, + 34,138,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,255,247,34,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,175,251,89,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,199,34,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,235,125,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,12,235,255,255,255,166,0,12,235,255, + 255,255,166,0,12,235,255,255,255,166,0,12,235,255,255,255,166,0,0,12,235, + 255,255,255,166,0,12,235,255,255,255,166,0,12,235,255,255,255,166,0,175, + 255,255,125,0,0,12,235,255,255,125,0,0,12,235,255,255,225,21,0,0,12,235, + 255,255,225,21,0,12,235,255,255,225,21,0,12,235,255,255,225,21,0,12,235, + 125,12,235,125,12,235,125,12,235,125,0,12,235,125,89,251,89,0,12,235,138, + 235,255,247,34,0,0,12,235,255,255,201,0,0,0,12,235,255,255,201,0,0,0,12, + 235,255,255,201,0,0,0,12,235,255,255,201,0,0,0,12,235,255,255,201,0,0,0, + 0,0,0,175,247,34,0,0,0,12,235,255,255,255,166,0,59,241,89,0,0,89,247,34, + 59,241,89,0,0,89,247,34,59,241,89,0,0,89,247,34,59,241,89,0,0,89,247,42, + 206,201,0,0,0,138,232,245,166,245,255,251,89,7,206,201,0,0,0,138,225,21, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,127,12,206,21,0,59,245,125,12,206,21,0,59,245,125,12,206, + 21,0,59,245,125,12,206,21,0,59,245,125,0,12,206,21,0,59,245,125,12,206, + 21,0,59,245,125,12,206,21,0,12,235,255,125,0,7,206,166,12,235,166,0,0,172, + 102,0,235,125,0,0,175,201,0,12,235,125,0,0,175,201,12,235,125,0,0,175,201, + 12,235,125,0,0,175,201,0,12,235,125,12,235,125,12,235,125,12,235,125,0, + 0,0,0,0,175,201,0,12,235,247,34,0,175,201,0,12,235,166,0,7,206,201,0,12, + 235,166,0,7,206,201,0,12,235,166,0,7,206,201,0,12,235,166,0,7,206,201,0, + 12,235,166,0,7,206,201,0,0,0,0,0,175,247,34,0,0,12,235,166,0,12,235,201, + 0,59,241,89,0,0,89,247,34,59,241,89,0,0,89,247,34,59,241,89,0,0,89,247, + 34,59,241,89,0,0,89,247,34,89,247,34,0,7,206,176,235,225,21,0,175,225,21, + 89,247,34,0,7,206,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,7,206,166,0,0,0,0,7, + 206,166,0,0,0,0,7,206,166,0,0,0,0,7,206,166,0,0,0,0,0,7,206,166,0,0,0,0, + 7,206,166,0,0,0,0,0,175,201,0,0,0,89,225,138,225,21,0,0,0,0,89,225,21,0, + 0,89,247,34,89,225,21,0,0,89,247,124,225,21,0,0,89,247,124,225,21,0,0,89, + 247,34,12,235,125,12,235,125,12,235,125,12,235,125,0,89,255,255,255,255, + 247,34,12,235,125,0,0,89,247,34,138,225,21,0,0,59,238,34,138,225,21,0,0, + 59,238,34,138,225,21,0,0,59,238,34,138,225,21,0,0,59,238,34,138,225,21, + 0,0,59,238,34,0,0,0,0,0,0,0,0,0,138,225,21,0,172,132,238,34,59,241,89,0, + 0,89,247,34,59,241,89,0,0,89,247,34,59,241,89,0,0,89,247,34,59,241,89,0, + 0,89,247,34,12,235,125,0,59,238,47,235,125,0,0,59,241,89,12,235,125,0,59, + 238,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,59,245,255,255,255,166,0,59,245,255,255, + 255,166,0,59,245,255,255,255,166,0,59,245,255,255,255,166,0,0,59,245,255, + 255,255,166,0,59,245,255,255,255,166,0,89,255,255,255,255,255,255,255,255, + 255,247,175,201,0,0,0,0,0,175,255,255,255,255,255,247,34,175,255,255,255, + 255,255,247,198,255,255,255,255,255,247,198,255,255,255,255,255,247,34, + 12,235,125,12,235,125,12,235,125,12,235,125,89,251,89,0,0,59,241,89,12, + 235,125,0,0,89,247,34,175,201,0,0,0,12,232,89,175,201,0,0,0,12,232,89,175, + 201,0,0,0,12,232,89,175,201,0,0,0,12,232,89,175,201,0,0,0,12,232,89,7,206, + 255,255,255,255,255,255,251,226,201,0,89,166,12,232,89,59,241,89,0,0,89, + 247,34,59,241,89,0,0,89,247,34,59,241,89,0,0,89,247,34,59,241,89,0,0,89, + 247,34,0,175,201,0,138,201,12,235,125,0,0,12,235,125,0,175,201,0,138,201, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,127,89,255,166,0,7,206,166,89,255,166,0,7,206,166,89, + 255,166,0,7,206,166,89,255,166,0,7,206,166,0,89,255,166,0,7,206,166,89, + 255,166,0,7,206,166,138,255,125,0,0,175,201,0,0,0,0,0,175,201,0,0,0,0,0, + 175,201,0,0,0,0,0,0,175,201,0,0,0,0,0,175,201,0,0,0,0,0,175,201,0,0,0,0, + 0,0,12,235,125,12,235,125,12,235,125,12,235,125,175,201,0,0,0,59,241,89, + 12,235,125,0,0,89,247,34,175,201,0,0,0,12,232,89,175,201,0,0,0,12,232,89, + 175,201,0,0,0,12,232,89,175,201,0,0,0,12,232,89,175,201,0,0,0,12,232,89, + 0,0,0,0,0,0,0,0,0,175,201,7,176,21,12,232,89,59,241,89,0,0,89,247,34,59, + 241,89,0,0,89,247,34,59,241,89,0,0,89,247,34,59,241,89,0,0,89,247,34,0, + 89,247,47,235,125,12,235,125,0,0,12,235,125,0,89,247,47,235,125,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,127,175,201,0,0,7,206,166,175,201,0,0,7,206,166,175,201,0,0, + 7,206,166,175,201,0,0,7,206,166,0,175,201,0,0,7,206,166,175,201,0,0,7,206, + 166,175,201,0,0,0,138,225,21,0,0,0,0,138,225,21,0,0,0,0,138,247,34,0,0, + 0,0,0,138,247,34,0,0,0,0,138,247,34,0,0,0,0,138,247,34,0,0,0,0,0,12,235, + 125,12,235,125,12,235,125,12,235,125,175,201,0,0,0,89,247,34,12,235,125, + 0,0,89,247,34,138,225,21,0,0,89,247,34,138,225,21,0,0,89,247,34,138,225, + 21,0,0,89,247,34,138,225,21,0,0,89,247,34,138,225,21,0,0,89,247,34,0,0, + 0,0,175,247,34,0,0,138,225,151,125,0,89,247,34,59,241,89,0,0,89,247,34, + 59,241,89,0,0,89,247,34,59,241,89,0,0,89,247,34,59,241,89,0,0,89,247,34, + 0,12,235,191,247,34,12,235,125,0,0,59,241,89,0,12,235,191,247,34,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,127,138,225,21,0,138,255,166,138,225,21,0,138,255,166,138, + 225,21,0,138,255,166,138,225,21,0,138,255,166,0,138,225,21,0,138,255,166, + 138,225,21,0,138,255,166,89,247,34,0,89,255,255,166,0,0,12,206,12,235,166, + 0,0,127,102,0,235,201,0,0,12,206,21,12,235,201,0,0,12,206,34,235,201,0, + 0,12,206,34,235,201,0,0,12,206,21,12,235,125,12,235,125,12,235,125,12,235, + 125,89,255,125,0,7,206,166,0,12,235,125,0,0,89,247,34,12,235,166,0,7,206, + 201,0,12,235,166,0,7,206,201,0,12,235,166,0,7,206,201,0,12,235,166,0,7, + 206,201,0,12,235,166,0,7,206,201,0,0,0,0,0,175,247,34,0,0,12,235,201,0, + 7,206,201,0,7,206,166,0,59,245,247,34,7,206,166,0,59,245,247,34,7,206,166, + 0,59,245,247,34,7,206,166,0,59,245,247,34,0,0,138,255,166,0,12,235,125, + 0,7,206,201,0,0,0,138,255,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,7,206,255,255,171, + 206,166,7,206,255,255,171,206,166,7,206,255,255,171,206,166,7,206,255,255, + 171,206,166,0,7,206,255,255,171,206,166,7,206,255,255,171,206,166,0,89, + 255,255,201,0,0,175,255,255,247,34,0,12,235,255,255,166,0,0,7,206,255,255, + 247,34,0,0,7,206,255,255,247,34,0,7,206,255,255,247,34,0,7,206,255,255, + 247,34,0,12,235,125,12,235,125,12,235,125,12,235,125,0,89,255,255,255,201, + 0,0,12,235,125,0,0,89,247,34,0,12,235,255,255,201,0,0,0,12,235,255,255, + 201,0,0,0,12,235,255,255,201,0,0,0,12,235,255,255,201,0,0,0,12,235,255, + 255,201,0,0,0,0,0,0,0,0,0,0,0,7,206,255,255,255,201,0,0,0,59,245,255,225, + 111,247,34,0,59,245,255,225,111,247,34,0,59,245,255,225,111,247,34,0,59, + 245,255,225,111,247,34,0,0,59,241,89,0,12,235,255,255,255,225,21,0,0,0, + 59,241,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,175,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,138,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,225,21,0,12,235,125,0,0,0,0,0,0,0, + 138,225,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,7,202,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,206,166,0,0,12,235,125,0,0,0,0,0,0,7,206, + 166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 12,235,255,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,247,34,0,0,12,235,125,0,0,0,0,0,0,89,247, + 34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127,127,127,127,0,127,127,127,127, + 127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,0,127,127,0,127,127,0,127,127,0,127,127,0,127,127,127,127,127,127, + 127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127, + 127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127, + 127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,127, + 0,127,127,127,127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127, + 127,127,127,127,0,127,127,127,127,127,127,127,0,127,127,127,127,127,127, + 127,0,127,127,127,127,127,127,0,127,127,127,127,127,127,0,127,127,127,127, + 127,127,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0 +}; + + +void TwGenerateDefaultFonts() +{ + g_DefaultSmallFont = TwGenerateFont(s_Font0, FONT0_BM_W, FONT0_BM_H); + assert(g_DefaultSmallFont && g_DefaultSmallFont->m_NbCharRead==224); + g_DefaultNormalFont = TwGenerateFont(s_Font1AA, FONT1AA_BM_W, FONT1AA_BM_H); + assert(g_DefaultNormalFont && g_DefaultNormalFont->m_NbCharRead==224); + g_DefaultLargeFont = TwGenerateFont(s_Font2AA, FONT2AA_BM_W, FONT2AA_BM_H); + assert(g_DefaultLargeFont && g_DefaultLargeFont->m_NbCharRead==224); +} + +// --------------------------------------------------------------------------- + +void TwDeleteDefaultFonts() +{ + delete g_DefaultSmallFont; + g_DefaultSmallFont = NULL; + delete g_DefaultNormalFont; + g_DefaultNormalFont = NULL; + delete g_DefaultLargeFont; + g_DefaultLargeFont = NULL; +} + +// --------------------------------------------------------------------------- diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwFonts.h b/Extras/CDTestFramework/AntTweakBar/src/TwFonts.h new file mode 100644 index 0000000..79500c6 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwFonts.h @@ -0,0 +1,67 @@ +// --------------------------------------------------------------------------- +// +// @file TwFonts.h +// @brief Bitmaps fonts +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// notes: Private header +// TAB=4 +// +// --------------------------------------------------------------------------- + + +#if !defined ANT_TW_FONTS_INCLUDED +#define ANT_TW_FONTS_INCLUDED + +//#include + +/* +A source bitmap includes 224 characters starting from ascii char 32 (i.e. space) to ascii char 255: + + !"#$%&'()*+,-./0123456789:;<=>? +@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ +`abcdefghijklmnopqrstuvwxyz{|}~ +€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ + ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ +ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß +àáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + +First column of a source bitmap is a delimiter with color=zero at the end of each line of characters. +Last row of a line of characters is a delimiter with color=zero at the last pixel of each character. + +*/ + + +struct CTexFont +{ + unsigned char * m_TexBytes; + int m_TexWidth; // power of 2 + int m_TexHeight; // power of 2 + float m_CharU0[256]; + float m_CharV0[256]; + float m_CharU1[256]; + float m_CharV1[256]; + int m_CharWidth[256]; + int m_CharHeight; + int m_NbCharRead; + + CTexFont(); + ~CTexFont(); +}; + + +CTexFont *TwGenerateFont(const unsigned char *_Bitmap, int _BmWidth, int _BmHeight); + + +extern CTexFont *g_DefaultSmallFont; +extern CTexFont *g_DefaultNormalFont; +extern CTexFont *g_DefaultLargeFont; + +void TwGenerateDefaultFonts(); +void TwDeleteDefaultFonts(); + + +#endif // !defined ANT_TW_FONTS_INCLUDED diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwGraph.h b/Extras/CDTestFramework/AntTweakBar/src/TwGraph.h new file mode 100644 index 0000000..e16f205 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwGraph.h @@ -0,0 +1,54 @@ +// --------------------------------------------------------------------------- +// +// @file TwGraph.h +// @brief ITwGraph pure interface +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// notes: Private header +// TAB=4 +// +// --------------------------------------------------------------------------- + + +#if !defined ANT_TW_GRAPH_INCLUDED +#define ANT_TW_GRAPH_INCLUDED + +#include "TwColors.h" +#include "TwFonts.h" + + +// --------------------------------------------------------------------------- + +#ifdef DrawText // DirectX redefines 'DrawText' !! +# undef DrawText +#endif // DrawText + +class ITwGraph +{ +public: + virtual int Init() = 0; + virtual int Shut() = 0; + virtual void BeginDraw(int _WndWidth, int _WndHeight) = 0; + virtual void EndDraw() = 0; + virtual bool IsDrawing() = 0; + virtual void Restore() = 0; + virtual void DrawLine(int _X0, int _Y0, int _X1, int _Y1, color32 _Color0, color32 _Color1, bool _AntiAliased=false) = 0; + virtual void DrawLine(int _X0, int _Y0, int _X1, int _Y1, color32 _Color, bool _AntiAliased=false) = 0; + + virtual void DrawRect(int _X0, int _Y0, int _X1, int _Y1, color32 _Color00, color32 _Color10, color32 _Color01, color32 _Color11) = 0; + virtual void DrawRect(int _X0, int _Y0, int _X1, int _Y1, color32 _Color) = 0; + + virtual void * NewTextObj() = 0; + virtual void DeleteTextObj(void *_TextObj) = 0; + virtual void BuildText(void *_TextObj, const std::string *_TextLines, color32 *_LineColors, color32 *_LineBgColors, int _NbLines, const CTexFont *_Font, int _Sep, int _BgWidth) = 0; + virtual void DrawText(void *_TextObj, int _X, int _Y, color32 _Color, color32 _BgColor) = 0; + + virtual ~ITwGraph() {} // required by gcc +}; + +// --------------------------------------------------------------------------- + +#endif // ANT_TW_GRAPH_INCLUDED diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwMgr.cpp b/Extras/CDTestFramework/AntTweakBar/src/TwMgr.cpp new file mode 100644 index 0000000..9f7980f --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwMgr.cpp @@ -0,0 +1,3265 @@ +// --------------------------------------------------------------------------- +// +// @file TwMgr.cpp +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// note: TAB=4 +// +// --------------------------------------------------------------------------- + + +#include "TwPrecomp.h" + +#include +#include "TwMgr.h" +#include "TwBar.h" +#include "TwFonts.h" +#include "TwOpenGL.h" +#ifdef ANT_WINDOWS +# include "TwDirect3D9.h" +# include "resource.h" +# ifdef _DEBUG +# include +# endif // _DEBUG +#endif // ANT_WINDOWS + +using namespace std; + + +CTwMgr *g_TwMgr = NULL; +bool g_BreakOnError = false; +TwErrorHandler g_ErrorHandler = NULL; +int g_TabLength = 4; +CTwBar * const TW_GLOBAL_BAR = (CTwBar *)(-1); +int g_InitWndWidth = -1; +int g_InitWndHeight = -1; + +extern const char *g_ErrUnknownAttrib; +extern const char *g_ErrNoValue; +extern const char *g_ErrBadValue; +const char *g_ErrInit = "Already initialized"; +const char *g_ErrShut = "Already shutdown"; +const char *g_ErrNotInit = "Not initialized"; +const char *g_ErrUnknownAPI = "Unsupported graph API"; +const char *g_ErrBadDevice = "Invalid graph device"; +const char *g_ErrBadParam = "Invalid parameter"; +const char *g_ErrExist = "Exists already"; +const char *g_ErrNotFound = "Not found"; +const char *g_ErrNthToDo = "Nothing to do"; +const char *g_ErrBadWndSize = "Bad window size"; +const char *g_ErrOffset = "Offset larger than StructSize"; +const char *g_ErrDelStruct = "Cannot delete a struct member"; +const char *g_ErrNoBackQuote= "Name cannot include back-quote"; +char g_ErrParse[512]; + +void ANT_CALL TwGlobalError(const char *_ErrorMessage); + +#if defined(_UNIX) +#define _stricmp strcasecmp +#define _strdup strdup +#endif + + +// --------------------------------------------------------------------------- + +// a static global object to verify that Tweakbar module has been properly terminated (in debug mode only) +#ifdef _DEBUG +static struct CTwVerif +{ + ~CTwVerif() + { + if( g_TwMgr!=NULL ) + g_TwMgr->SetLastError("Tweak bar module has not been terminated properly: call TwTerminate()\n"); + } +} s_Verif; +#endif // _DEBUG + +// --------------------------------------------------------------------------- + +void CColorExt::RGB2HLS() +{ + float fH = 0, fL = 0, fS = 0; + ColorRGBToHLSf((float)R/255.0f, (float)G/255.0f, (float)B/255.0f, &fH, &fL, &fS); + H = (int)fH; + if( H>=360 ) + H -= 360; + else if( H<0 ) + H += 360; + L = (int)(255.0f*fL + 0.5f); + if( L<0 ) + L = 0; + else if( L>255 ) + L = 255; + S = (int)(255.0f*fS + 0.5f); + if( S<0 ) + S = 0; + else if( S>255 ) + S = 255; +} + +void CColorExt::HLS2RGB() +{ + float fR = 0, fG = 0, fB = 0; + ColorHLSToRGBf((float)H, (float)L/255.0f, (float)S/255.0f, &fR, &fG, &fB); + R = (int)(255.0f*fR + 0.5f); + if( R<0 ) + R = 0; + else if( R>255 ) + R = 255; + G = (int)(255.0f*fG + 0.5f); + if( G<0 ) + G = 0; + else if( G>255 ) + G = 255; + B = (int)(255.0f*fB + 0.5f); + if( B<0 ) + B = 0; + else if( B>255 ) + B = 255; +} + +void ANT_CALL CColorExt::InitColor32CB(void *_ExtValue, void *_ClientData) +{ + CColorExt *ext = static_cast(_ExtValue); + if( ext ) + { + ext->m_IsColorF = false; + ext->R = 0; + ext->G = 0; + ext->B = 0; + ext->H = 0; + ext->L = 0; + ext->S = 0; + ext->A = 255; + ext->m_HLS = false; + ext->m_HasAlpha = false; + ext->m_CanHaveAlpha = true; + if( g_TwMgr && g_TwMgr->m_GraphAPI!=TW_OPENGL ) + ext->m_OGL = false; + else + ext->m_OGL = true; + ext->m_PrevConvertedColor = Color32FromARGBi(ext->A, ext->R, ext->G, ext->B); + ext->m_StructProxy = (CTwMgr::CStructProxy *)_ClientData; + } +} + +void ANT_CALL CColorExt::InitColor3FCB(void *_ExtValue, void *_ClientData) +{ + InitColor32CB(_ExtValue, _ClientData); + CColorExt *ext = static_cast(_ExtValue); + if( ext ) + { + ext->m_IsColorF = true; + ext->m_HasAlpha = false; + ext->m_CanHaveAlpha = false; + } +} + +void ANT_CALL CColorExt::InitColor4FCB(void *_ExtValue, void *_ClientData) +{ + InitColor32CB(_ExtValue, _ClientData); + CColorExt *ext = static_cast(_ExtValue); + if( ext ) + { + ext->m_IsColorF = true; + ext->m_HasAlpha = true; + ext->m_CanHaveAlpha = true; + } +} + +void ANT_CALL CColorExt::CopyVarFromExtCB(void *_VarValue, const void *_ExtValue, unsigned int _ExtMemberIndex, void *_ClientData) +{ + unsigned int *var32 = static_cast(_VarValue); + float *varF = static_cast(_VarValue); + CColorExt *ext = (CColorExt *)(_ExtValue); + CTwMgr::CMemberProxy *mProxy = static_cast(_ClientData); + if( _VarValue && ext ) + { + if( ext->m_HasAlpha && mProxy && mProxy->m_StructProxy && mProxy->m_StructProxy->m_Type==g_TwMgr->m_TypeColor3F ) + ext->m_HasAlpha = false; + + // Synchronize HLS and RGB + if( _ExtMemberIndex>=0 && _ExtMemberIndex<=2 ) + ext->RGB2HLS(); + else if( _ExtMemberIndex>=3 && _ExtMemberIndex<=5 ) + ext->HLS2RGB(); + else if( mProxy && _ExtMemberIndex==7 && mProxy->m_VarParent ) + { + assert( mProxy->m_VarParent->m_Vars.size()==8 ); + if( mProxy->m_VarParent->m_Vars[0]->m_Visible != !ext->m_HLS + || mProxy->m_VarParent->m_Vars[1]->m_Visible != !ext->m_HLS + || mProxy->m_VarParent->m_Vars[2]->m_Visible != !ext->m_HLS + || mProxy->m_VarParent->m_Vars[3]->m_Visible != ext->m_HLS + || mProxy->m_VarParent->m_Vars[4]->m_Visible != ext->m_HLS + || mProxy->m_VarParent->m_Vars[5]->m_Visible != ext->m_HLS ) + { + mProxy->m_VarParent->m_Vars[0]->m_Visible = !ext->m_HLS; + mProxy->m_VarParent->m_Vars[1]->m_Visible = !ext->m_HLS; + mProxy->m_VarParent->m_Vars[2]->m_Visible = !ext->m_HLS; + mProxy->m_VarParent->m_Vars[3]->m_Visible = ext->m_HLS; + mProxy->m_VarParent->m_Vars[4]->m_Visible = ext->m_HLS; + mProxy->m_VarParent->m_Vars[5]->m_Visible = ext->m_HLS; + mProxy->m_Bar->NotUpToDate(); + } + if( mProxy->m_VarParent->m_Vars[6]->m_Visible != ext->m_HasAlpha ) + { + mProxy->m_VarParent->m_Vars[6]->m_Visible = ext->m_HasAlpha; + mProxy->m_Bar->NotUpToDate(); + } + if( static_cast(mProxy->m_VarParent->m_Vars[7])->m_ReadOnly ) + { + static_cast(mProxy->m_VarParent->m_Vars[7])->m_ReadOnly = false; + mProxy->m_Bar->NotUpToDate(); + } + } + // Convert to color32 + color32 col = Color32FromARGBi((ext->m_HasAlpha ? ext->A : 255), ext->R, ext->G, ext->B); + if( ext->m_OGL && !ext->m_IsColorF ) + col = (col&0xff00ff00) | (unsigned char)(col>>16) | (((unsigned char)(col))<<16); + if( ext->m_IsColorF ) + Color32ToARGBf(col, (ext->m_HasAlpha ? varF+3 : NULL), varF+0, varF+1, varF+2); + else + { + if( ext->m_HasAlpha ) + *var32 = col; + else + *var32 = ((*var32)&0xff000000) | (col&0x00ffffff); + } + ext->m_PrevConvertedColor = col; + } +} + +void ANT_CALL CColorExt::CopyVarToExtCB(const void *_VarValue, void *_ExtValue, unsigned int _ExtMemberIndex, void *_ClientData) +{ + const unsigned int *var32 = static_cast(_VarValue); + const float *varF = static_cast(_VarValue); + CColorExt *ext = static_cast(_ExtValue); + CTwMgr::CMemberProxy *mProxy = static_cast(_ClientData); + if( _VarValue && ext ) + { + if( ext->m_HasAlpha && mProxy && mProxy->m_StructProxy && mProxy->m_StructProxy->m_Type==g_TwMgr->m_TypeColor3F ) + ext->m_HasAlpha = false; + + if( mProxy && _ExtMemberIndex==7 && mProxy->m_VarParent ) + { + assert( mProxy->m_VarParent->m_Vars.size()==8 ); + if( mProxy->m_VarParent->m_Vars[0]->m_Visible != !ext->m_HLS + || mProxy->m_VarParent->m_Vars[1]->m_Visible != !ext->m_HLS + || mProxy->m_VarParent->m_Vars[2]->m_Visible != !ext->m_HLS + || mProxy->m_VarParent->m_Vars[3]->m_Visible != ext->m_HLS + || mProxy->m_VarParent->m_Vars[4]->m_Visible != ext->m_HLS + || mProxy->m_VarParent->m_Vars[5]->m_Visible != ext->m_HLS ) + { + mProxy->m_VarParent->m_Vars[0]->m_Visible = !ext->m_HLS; + mProxy->m_VarParent->m_Vars[1]->m_Visible = !ext->m_HLS; + mProxy->m_VarParent->m_Vars[2]->m_Visible = !ext->m_HLS; + mProxy->m_VarParent->m_Vars[3]->m_Visible = ext->m_HLS; + mProxy->m_VarParent->m_Vars[4]->m_Visible = ext->m_HLS; + mProxy->m_VarParent->m_Vars[5]->m_Visible = ext->m_HLS; + mProxy->m_Bar->NotUpToDate(); + } + if( mProxy->m_VarParent->m_Vars[6]->m_Visible != ext->m_HasAlpha ) + { + mProxy->m_VarParent->m_Vars[6]->m_Visible = ext->m_HasAlpha; + mProxy->m_Bar->NotUpToDate(); + } + if( static_cast(mProxy->m_VarParent->m_Vars[7])->m_ReadOnly ) + { + static_cast(mProxy->m_VarParent->m_Vars[7])->m_ReadOnly = false; + mProxy->m_Bar->NotUpToDate(); + } + } + color32 col; + if( ext->m_IsColorF ) + col = Color32FromARGBf((ext->m_HasAlpha ? varF[3] : 1), varF[0], varF[1], varF[2]); + else + col = *var32; + if( ext->m_OGL && !ext->m_IsColorF ) + col = (col&0xff00ff00) | (unsigned char)(col>>16) | (((unsigned char)(col))<<16); + Color32ToARGBi(col, (ext->m_HasAlpha ? &ext->A : NULL), &ext->R, &ext->G, &ext->B); + if( (col & 0x00ffffff)!=(ext->m_PrevConvertedColor & 0x00ffffff) ) + ext->RGB2HLS(); + ext->m_PrevConvertedColor = col; + } +} + +void ANT_CALL CColorExt::SummaryCB(char *_SummaryString, size_t /*_SummaryMaxLength*/, const void *_ExtValue, void * /*_ClientData*/) +{ + // copy var + CColorExt *ext = (CColorExt *)(_ExtValue); + if( ext && ext->m_StructProxy && ext->m_StructProxy->m_StructData ) + { + if( ext->m_StructProxy->m_StructGetCallback ) + ext->m_StructProxy->m_StructGetCallback(ext->m_StructProxy->m_StructData, ext->m_StructProxy->m_StructClientData); + //if( *(unsigned int *)(ext->m_StructProxy->m_StructData)!=ext->m_PrevConvertedColor ) + CopyVarToExtCB(ext->m_StructProxy->m_StructData, ext, 99, NULL); + } + + //unsigned int col = 0; + //CopyVar32FromExtCB(&col, _ExtValue, 99, _ClientData); + //_snprintf(_SummaryString, _SummaryMaxLength, "0x%.8X", col); + //(void) _SummaryMaxLength, _ExtValue, _ClientData; + _SummaryString[0] = ' '; // required to force background color for this value + _SummaryString[1] = '\0'; +} + +void CColorExt::CreateTypes() +{ + if( g_TwMgr==NULL ) + return; + TwStructMember ColorExtMembers[] = { { "Red", TW_TYPE_INT32, offsetof(CColorExt, R), "min=0 max=255" }, + { "Green", TW_TYPE_INT32, offsetof(CColorExt, G), "min=0 max=255" }, + { "Blue", TW_TYPE_INT32, offsetof(CColorExt, B), "min=0 max=255" }, + { "Hue", TW_TYPE_INT32, offsetof(CColorExt, H), "hide min=0 max=359" }, + { "Lightness", TW_TYPE_INT32, offsetof(CColorExt, L), "hide min=0 max=255" }, + { "Saturation", TW_TYPE_INT32, offsetof(CColorExt, S), "hide min=0 max=255" }, + { "Alpha", TW_TYPE_INT32, offsetof(CColorExt, A), "hide min=0 max=255" }, + { "Mode", TW_TYPE_BOOLCPP, offsetof(CColorExt, m_HLS), "true='HLS' false='RGB' readwrite" } }; + g_TwMgr->m_TypeColor32 = TwDefineStructExt("COLOR32", ColorExtMembers, 8, sizeof(unsigned int), sizeof(CColorExt), CColorExt::InitColor32CB, CColorExt::CopyVarFromExtCB, CColorExt::CopyVarToExtCB, CColorExt::SummaryCB, CTwMgr::CStruct::s_PassProxyAsClientData); + g_TwMgr->m_TypeColor3F = TwDefineStructExt("COLOR3F", ColorExtMembers, 8, 3*sizeof(float), sizeof(CColorExt), CColorExt::InitColor3FCB, CColorExt::CopyVarFromExtCB, CColorExt::CopyVarToExtCB, CColorExt::SummaryCB, CTwMgr::CStruct::s_PassProxyAsClientData); + g_TwMgr->m_TypeColor4F = TwDefineStructExt("COLOR4F", ColorExtMembers, 8, 4*sizeof(float), sizeof(CColorExt), CColorExt::InitColor4FCB, CColorExt::CopyVarFromExtCB, CColorExt::CopyVarToExtCB, CColorExt::SummaryCB, CTwMgr::CStruct::s_PassProxyAsClientData); +} + + +// --------------------------------------------------------------------------- + +static int TwCreateGraph(ETwGraphAPI _GraphAPI) +{ + assert( g_TwMgr!=NULL && g_TwMgr->m_Graph==NULL ); + + switch( _GraphAPI ) + { + case TW_OPENGL: + g_TwMgr->m_Graph = new CTwGraphOpenGL; + break; + case TW_DIRECT3D9: + #ifdef ANT_WINDOWS + if( g_TwMgr->m_Device!=NULL ) + g_TwMgr->m_Graph = new CTwGraphDirect3D9; + else + { + g_TwMgr->SetLastError(g_ErrBadDevice); + return 0; + } + #endif // ANT_WINDOWS + break; + } + + if( g_TwMgr->m_Graph==NULL ) + { + g_TwMgr->SetLastError(g_ErrUnknownAPI); + return 0; + } + else + return g_TwMgr->m_Graph->Init(); +} + +// --------------------------------------------------------------------------- + +int ANT_CALL TwInit(ETwGraphAPI _GraphAPI, void *_Device) +{ +#if defined(_DEBUG) && defined(ANT_WINDOWS) + _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF)); +#endif + + if( g_TwMgr!=NULL ) + { + g_TwMgr->SetLastError(g_ErrInit); + return 0; + } + + g_TwMgr = new CTwMgr(_GraphAPI, _Device); + + TwGenerateDefaultFonts(); + g_TwMgr->m_CurrentFont = g_DefaultNormalFont; + + int Res = TwCreateGraph(_GraphAPI); + + if( Res ) + { + g_TwMgr->m_KeyPressedTextObj = g_TwMgr->m_Graph->NewTextObj(); + g_TwMgr->m_InfoTextObj = g_TwMgr->m_Graph->NewTextObj(); + + g_TwMgr->m_HelpBar = TwNewBar("TW_HELP"); + if( g_TwMgr->m_HelpBar ) + { + g_TwMgr->m_HelpBar->m_Label = "~ Help & Shortcuts ~"; + g_TwMgr->m_HelpBar->m_PosX = 32; + g_TwMgr->m_HelpBar->m_PosY = 32; + g_TwMgr->m_HelpBar->m_Width = 400; + g_TwMgr->m_HelpBar->m_Height = 200; + g_TwMgr->m_HelpBar->m_ValuesWidth = 12*(g_TwMgr->m_HelpBar->m_Font->m_CharHeight/2); + g_TwMgr->m_HelpBar->m_Color = 0xd7ffffff; + g_TwMgr->m_HelpBar->m_IsHelpBar = true; + g_TwMgr->Minimize(g_TwMgr->m_HelpBar); + } + else + { + TwTerminate(); + Res = 0; + } + } + + if( Res ) + CColorExt::CreateTypes(); + + return Res; +} + +// --------------------------------------------------------------------------- + +int ANT_CALL TwTerminate() +{ + if( g_TwMgr==NULL ) + { + //TwGlobalError(g_ErrShut); -> not an error + return 0; // already shutdown + } + + TwDeleteAllBars(); + if( g_TwMgr->m_CursorsCreated ) + g_TwMgr->FreeCursors(); + + int Res = 1; + if( g_TwMgr->m_Graph ) + { + if( g_TwMgr->m_KeyPressedTextObj ) + { + g_TwMgr->m_Graph->DeleteTextObj(g_TwMgr->m_KeyPressedTextObj); + g_TwMgr->m_KeyPressedTextObj = NULL; + } + if( g_TwMgr->m_InfoTextObj ) + { + g_TwMgr->m_Graph->DeleteTextObj(g_TwMgr->m_InfoTextObj); + g_TwMgr->m_InfoTextObj = NULL; + } + Res = g_TwMgr->m_Graph->Shut(); + delete g_TwMgr->m_Graph; + g_TwMgr->m_Graph = NULL; + } + + TwDeleteDefaultFonts(); + + delete g_TwMgr; + g_TwMgr = NULL; + + return Res; +} + +// --------------------------------------------------------------------------- + +int ANT_CALL TwDraw() +{ + PERF( PerfTimer Timer; double DT; ) + //CTwFPU fpu; // fpu precision only forced in update (do not modif dx draw calls) + + if( g_TwMgr==NULL || g_TwMgr->m_Graph==NULL ) + { + TwGlobalError(g_ErrNotInit); + return 0; // not initialized + } + + assert(g_TwMgr->m_Bars.size()==g_TwMgr->m_Order.size()); + + // Create cursors + #if defined(ANT_WINDOWS) + if( !g_TwMgr->m_CursorsCreated ) + g_TwMgr->CreateCursors(); + #elif defined(ANT_UNIX) + if( !g_TwMgr->m_CurrentXDisplay ) + g_TwMgr->m_CurrentXDisplay = glXGetCurrentDisplay(); + if( !g_TwMgr->m_CurrentXWindow ) + g_TwMgr->m_CurrentXWindow = glXGetCurrentDrawable(); + if( g_TwMgr->m_CurrentXDisplay && !g_TwMgr->m_CursorsCreated ) + g_TwMgr->CreateCursors(); + #endif // defined(ANT_UNIX) + + // Autorepeat TW_MOUSE_PRESSED + double RepeatDT = g_TwMgr->m_Timer.GetTime() - g_TwMgr->m_LastMousePressedTime; + if( fabs(RepeatDT)>2.0*g_TwMgr->m_RepeatMousePressedDelay + || abs(g_TwMgr->m_LastMousePressedPosition[0]-g_TwMgr->m_LastMouseX)>4 + || abs(g_TwMgr->m_LastMousePressedPosition[1]-g_TwMgr->m_LastMouseY)>4 ) + { + g_TwMgr->m_CanRepeatMousePressed = false; + g_TwMgr->m_IsRepeatingMousePressed = false; + } + if( g_TwMgr->m_CanRepeatMousePressed ) + { + if( (!g_TwMgr->m_IsRepeatingMousePressed && RepeatDT>g_TwMgr->m_RepeatMousePressedDelay) + || (g_TwMgr->m_IsRepeatingMousePressed && RepeatDT>g_TwMgr->m_RepeatMousePressedPeriod) ) + { + g_TwMgr->m_IsRepeatingMousePressed = true; + g_TwMgr->m_LastMousePressedTime = g_TwMgr->m_Timer.GetTime(); + TwMouseButton(TW_MOUSE_PRESSED, g_TwMgr->m_LastMousePressedButtonID); + } + } + + + if( g_TwMgr->m_WndWidth<0 || g_TwMgr->m_WndHeight<0 ) + { + g_TwMgr->SetLastError(g_ErrBadWndSize); + return 0; + } + else if( g_TwMgr->m_WndWidth==0 || g_TwMgr->m_WndHeight==0 ) // probably iconified + return 1; // nothing to do + + // count number of bars to draw + size_t i, idx; + int Nb = 0; + for( i=0; im_Bars.size(); ++i ) + if( g_TwMgr->m_Bars[i]!=NULL && g_TwMgr->m_Bars[i]->m_Visible ) + ++Nb; + + if( Nb>0 ) + { + PERF( Timer.Reset(); ) + g_TwMgr->m_Graph->BeginDraw(g_TwMgr->m_WndWidth, g_TwMgr->m_WndHeight); + PERF( DT = Timer.GetTime(); printf("\nBegin=%.4fms ", 1000.0*DT); ) + + PERF( Timer.Reset(); ) + for( i=0; im_Bars.size(); ++i ) + { + idx = g_TwMgr->m_Order[i]; + if( g_TwMgr->m_Bars[idx]->m_Visible ) + { + g_TwMgr->m_Bars[idx]->Draw(); + } + } + PERF( DT = Timer.GetTime(); printf("Draw=%.4fms ", 1000.0*DT); ) + + PERF( Timer.Reset(); ) + g_TwMgr->m_Graph->EndDraw(); + PERF( DT = Timer.GetTime(); printf("End=%.4fms\n", 1000.0*DT); ) + } + + return 1; +} + +// --------------------------------------------------------------------------- + +int ANT_CALL TwWindowSize(int _Width, int _Height) +{ + g_InitWndWidth = _Width; + g_InitWndHeight = _Height; + + if( g_TwMgr==NULL || g_TwMgr->m_Graph==NULL ) + { + //TwGlobalError(g_ErrNotInit); -> not an error here + return 0; // not initialized + } + + if( _Width<0 || _Height<0 ) + { + g_TwMgr->SetLastError(g_ErrBadWndSize); + return 0; + } + + g_TwMgr->m_WndWidth = _Width; + g_TwMgr->m_WndHeight = _Height; + g_TwMgr->m_Graph->Restore(); + for( std::vector::iterator it=g_TwMgr->m_Bars.begin(); it!=g_TwMgr->m_Bars.end(); ++it ) + (*it)->NotUpToDate(); + return 1; +} + +// --------------------------------------------------------------------------- + +CTwMgr::CTwMgr(ETwGraphAPI _GraphAPI, void *_Device) +{ + m_GraphAPI = _GraphAPI; + m_Device = _Device; + m_LastError = NULL; + m_CurrentDbgFile = ""; + m_CurrentDbgLine = 0; + m_Graph = NULL; + m_WndWidth = g_InitWndWidth; + m_WndHeight = g_InitWndHeight; + m_CurrentFont = NULL; // set after by TwIntialize + m_NbMinimizedBars = 0; + m_HelpBar = NULL; + m_HelpBarNotUpToDate = true; + m_HelpBarUpdateNow = false; + m_LastHelpUpdateTime = 0; + m_LastMouseX = -1; + m_LastMouseY = -1; + m_LastMouseWheelPos = 0; + m_KeyPressedTextObj = NULL; + m_KeyPressedBuildText = false; + m_KeyPressedTime = 0; + m_InfoTextObj = NULL; + m_InfoBuildText = true; + m_BarInitColorHue = 155; + m_PopupBar = NULL; + m_TypeColor32 = TW_TYPE_UNDEF; + m_TypeColor3F = TW_TYPE_UNDEF; + m_TypeColor4F = TW_TYPE_UNDEF; + m_LastMousePressedTime = 0; + m_LastMousePressedButtonID = TW_MOUSE_MIDDLE; + m_LastMousePressedPosition[0] = -1000; + m_LastMousePressedPosition[1] = -1000; + m_RepeatMousePressedDelay = 0.5; + m_RepeatMousePressedPeriod = 0.1; + m_CanRepeatMousePressed = false; + m_IsRepeatingMousePressed = false; + + m_CursorsCreated = false; + #if defined(ANT_UNIX) + m_CurrentXDisplay = NULL; + m_CurrentXWindow = 0; + #endif // defined(ANT_UNIX) +} + +// --------------------------------------------------------------------------- + +CTwMgr::~CTwMgr() +{ +} + +// --------------------------------------------------------------------------- + +int CTwMgr::FindBar(const char *_Name) const +{ + if( _Name==NULL || strlen(_Name)<=0 ) + return -1; + int i; + for( i=0; i<(int)m_Bars.size(); ++i ) + if( m_Bars[i]!=NULL && strcmp(_Name, m_Bars[i]->m_Name.c_str())==0 ) + return i; + return -1; +} + + +// --------------------------------------------------------------------------- + +enum EMgrAttribs +{ + MGR_HELP = 1, +}; + +int CTwMgr::HasAttrib(const char *_Attrib, bool *_HasValue) const +{ + *_HasValue = true; + if( _stricmp(_Attrib, "help")==0 ) + return MGR_HELP; + + *_HasValue = false; + return 0; // not found +} + +int CTwMgr::SetAttrib(int _AttribID, const char *_Value) +{ + switch( _AttribID ) + { + case MGR_HELP: + if( _Value && strlen(_Value)>0 ) + { + m_Help = _Value; + m_HelpBarNotUpToDate = true; + return 1; + } + else + { + g_TwMgr->SetLastError(g_ErrNoValue); + return 0; + } + default: + g_TwMgr->SetLastError(g_ErrUnknownAttrib); + return 0; + } +} + +// --------------------------------------------------------------------------- + +void CTwMgr::Minimize(TwBar *_Bar) +{ + assert(m_Graph!=NULL && _Bar!=NULL); + assert(m_Bars.size()==m_MinOccupied.size()); + if( _Bar->m_IsMinimized ) + return; + size_t i = m_NbMinimizedBars; + m_NbMinimizedBars++; + for( i=0; im_MinNumber = (int)i; + _Bar->m_IsMinimized = true; + _Bar->NotUpToDate(); +} + +// --------------------------------------------------------------------------- + +void CTwMgr::Maximize(TwBar *_Bar) +{ + assert(m_Graph!=NULL && _Bar!=NULL); + assert(m_Bars.size()==m_MinOccupied.size()); + if( !_Bar->m_IsMinimized ) + return; + --m_NbMinimizedBars; + if( m_NbMinimizedBars<0 ) + m_NbMinimizedBars = 0; + if( _Bar->m_MinNumber>=0 && _Bar->m_MinNumber<(int)m_MinOccupied.size() ) + m_MinOccupied[_Bar->m_MinNumber] = false; + _Bar->m_IsMinimized = false; + _Bar->NotUpToDate(); + if( _Bar->m_IsHelpBar ) + m_HelpBarNotUpToDate = true; +} + +// --------------------------------------------------------------------------- + +void CTwMgr::Hide(TwBar *_Bar) +{ + assert(m_Graph!=NULL && _Bar!=NULL); + if( !_Bar->m_Visible ) + return; + _Bar->m_Visible = false; + if( !_Bar->m_IsHelpBar ) + m_HelpBarNotUpToDate = true; +} + +// --------------------------------------------------------------------------- + +void CTwMgr::Unhide(TwBar *_Bar) +{ + assert(m_Graph!=NULL && _Bar!=NULL); + if( _Bar->m_Visible ) + return; + _Bar->m_Visible = true; + _Bar->NotUpToDate(); + if( !_Bar->m_IsHelpBar ) + m_HelpBarNotUpToDate = true; +} + +// --------------------------------------------------------------------------- + +void CTwMgr::SetFont(const CTexFont *_Font, bool _ResizeBars) +{ + assert(m_Graph!=NULL); + assert(_Font!=NULL); + + m_CurrentFont = _Font; + + for( int i=0; i<(int)m_Bars.size(); ++i ) + if( m_Bars[i]!=NULL ) + { + int fh = m_Bars[i]->m_Font->m_CharHeight; + m_Bars[i]->m_Font = _Font; + if( _ResizeBars ) + { + m_Bars[i]->m_PosX += (3*(fh-_Font->m_CharHeight))/2; + m_Bars[i]->m_PosY += (fh-_Font->m_CharHeight)/2; + m_Bars[i]->m_Width = (m_Bars[i]->m_Width*_Font->m_CharHeight)/fh; + m_Bars[i]->m_Height = (m_Bars[i]->m_Height*_Font->m_CharHeight)/fh; + m_Bars[i]->m_ValuesWidth = (m_Bars[i]->m_ValuesWidth*_Font->m_CharHeight)/fh; + } + m_Bars[i]->NotUpToDate(); + } + + if( g_TwMgr->m_HelpBar!=NULL ) + g_TwMgr->m_HelpBar->Update(); + g_TwMgr->m_InfoBuildText = true; + g_TwMgr->m_KeyPressedBuildText = true; + m_HelpBarNotUpToDate = true; +} + +// --------------------------------------------------------------------------- + +void ANT_CALL TwGlobalError(const char *_ErrorMessage) // to be called when g_TwMgr is not created +{ + if( g_ErrorHandler==NULL ) + { + fprintf(stderr, "ERROR(AntTweakBar) >> %s\n", _ErrorMessage); + #ifdef ANT_WINDOWS + OutputDebugString("ERROR(AntTweakBar) >> "); + OutputDebugString(_ErrorMessage); + OutputDebugString("\n"); + #endif // ANT_WINDOWS + } + else + g_ErrorHandler(_ErrorMessage); + + if( g_BreakOnError ) + abort(); +} + +// --------------------------------------------------------------------------- + +void CTwMgr::SetLastError(const char *_ErrorMessage) // _ErrorMessage must be a static string +{ + m_LastError = _ErrorMessage; + + if( g_ErrorHandler==NULL ) + { + if( m_CurrentDbgFile!=NULL && strlen(m_CurrentDbgFile)>0 && m_CurrentDbgLine>0 ) + fprintf(stderr, "%s(%d): ", m_CurrentDbgFile, m_CurrentDbgLine); + fprintf(stderr, "ERROR(AntTweakBar) >> %s\n", m_LastError); + #ifdef ANT_WINDOWS + if( m_CurrentDbgFile!=NULL && strlen(m_CurrentDbgFile)>0 && m_CurrentDbgLine>0 ) + { + OutputDebugString(m_CurrentDbgFile); + char sl[32]; + sprintf(sl, "(%d): ", m_CurrentDbgLine); + OutputDebugString(sl); + } + OutputDebugString("ERROR(AntTweakBar) >> "); + OutputDebugString(m_LastError); + OutputDebugString("\n"); + #endif // ANT_WINDOWS + } + else + g_ErrorHandler(_ErrorMessage); + + if( g_BreakOnError ) + abort(); +} + +// --------------------------------------------------------------------------- + +const char *CTwMgr::GetLastError() +{ + const char *Err = m_LastError; + m_LastError = NULL; + return Err; +} + +// --------------------------------------------------------------------------- + +const char *CTwMgr::CheckLastError() const +{ + return m_LastError; +} + +// --------------------------------------------------------------------------- + +void CTwMgr::SetCurrentDbgParams(const char *dbgFile, int dbgLine) +{ + m_CurrentDbgFile = dbgFile; + m_CurrentDbgLine = dbgLine; +} + +// --------------------------------------------------------------------------- + +int ANT_CALL __TwDbg(const char *dbgFile, int dbgLine) +{ + if( g_TwMgr!=NULL ) + g_TwMgr->SetCurrentDbgParams(dbgFile, dbgLine); + return 0; // always returns zero +} + +// --------------------------------------------------------------------------- + +void ANT_CALL TwHandleErrors(TwErrorHandler _ErrorHandler, int _BreakOnError) +{ + g_ErrorHandler = _ErrorHandler; + g_BreakOnError = (_BreakOnError) ? true : false; +} + +// --------------------------------------------------------------------------- + +const char *ANT_CALL TwGetLastError() +{ + if( g_TwMgr==NULL ) + { + TwGlobalError(g_ErrNotInit); + return g_ErrNotInit; + } + else + return g_TwMgr->GetLastError(); +} + +// --------------------------------------------------------------------------- + +TwBar *ANT_CALL TwNewBar(const char *_Name) +{ + if( g_TwMgr==NULL || g_TwMgr->m_Graph==NULL ) + { + TwGlobalError(g_ErrNotInit); + return NULL; // not initialized + } + + if( _Name==NULL || strlen(_Name)<=0 ) + { + g_TwMgr->SetLastError(g_ErrBadParam); + return NULL; + } + if( g_TwMgr->FindBar(_Name)>=0 ) + { + g_TwMgr->SetLastError(g_ErrExist); + return NULL; + } + + if( strstr(_Name, "`")!=NULL ) + { + g_TwMgr->SetLastError(g_ErrNoBackQuote); + return NULL; + } + + if( g_TwMgr->m_PopupBar!=NULL ) // delete popup bar if it exists + { + TwDeleteBar(g_TwMgr->m_PopupBar); + g_TwMgr->m_PopupBar = NULL; + } + + TwBar *Bar = new CTwBar(_Name); + g_TwMgr->m_Bars.push_back(Bar); + g_TwMgr->m_Order.push_back((int)g_TwMgr->m_Bars.size()-1); + g_TwMgr->m_MinOccupied.push_back(false); + g_TwMgr->m_HelpBarNotUpToDate = true; + + return Bar; +} + +// --------------------------------------------------------------------------- + +int ANT_CALL TwDeleteBar(TwBar *_Bar) +{ + if( g_TwMgr==NULL ) + { + TwGlobalError(g_ErrNotInit); + return 0; // not initialized + } + if( _Bar==NULL ) + { + g_TwMgr->SetLastError(g_ErrBadParam); + return 0; + } + vector::iterator BarIt; + int i = 0; + for( BarIt=g_TwMgr->m_Bars.begin(); BarIt!=g_TwMgr->m_Bars.end(); ++BarIt, ++i ) + if( (*BarIt)==_Bar ) + break; + if( BarIt==g_TwMgr->m_Bars.end() ) + { + g_TwMgr->SetLastError(g_ErrNotFound); + return 0; + } + + if( g_TwMgr->m_PopupBar!=NULL && _Bar!=g_TwMgr->m_PopupBar ) // delete popup bar first if it exists + { + TwDeleteBar(g_TwMgr->m_PopupBar); + g_TwMgr->m_PopupBar = NULL; + } + + // force bar to un-minimize + g_TwMgr->Maximize(_Bar); + // find an empty MinOccupied + vector::iterator itm; + int j = 0; + for( itm=g_TwMgr->m_MinOccupied.begin(); itm!=g_TwMgr->m_MinOccupied.end(); ++itm, ++j) + if( (*itm)==false ) + break; + assert( itm!=g_TwMgr->m_MinOccupied.end() ); + // shift MinNumbers and erase the empty MinOccupied + for( size_t k=0; km_Bars.size(); ++k ) + if( g_TwMgr->m_Bars[k]!=NULL && g_TwMgr->m_Bars[k]->m_MinNumber>j ) + g_TwMgr->m_Bars[k]->m_MinNumber -= 1; + g_TwMgr->m_MinOccupied.erase(itm); + // erase _Bar order + vector::iterator BarOrderIt = g_TwMgr->m_Order.end(); + for(vector::iterator it=g_TwMgr->m_Order.begin(); it!=g_TwMgr->m_Order.end(); ++it ) + if( (*it)==i ) + BarOrderIt = it; + else if( (*it)>i ) + (*it) -= 1; + assert( BarOrderIt!=g_TwMgr->m_Order.end() ); + g_TwMgr->m_Order.erase(BarOrderIt); + + // erase & delete _Bar + g_TwMgr->m_Bars.erase(BarIt); + delete _Bar; + + g_TwMgr->m_HelpBarNotUpToDate = true; + return 1; +} + +// --------------------------------------------------------------------------- + +int ANT_CALL TwDeleteAllBars() +{ + if( g_TwMgr==NULL ) + { + TwGlobalError(g_ErrNotInit); + return 0; // not initialized + } + + int n = 0; + for( size_t i=0; im_Bars.size(); ++i ) + if( g_TwMgr->m_Bars[i]!=NULL ) + { + ++n; + delete g_TwMgr->m_Bars[i]; + g_TwMgr->m_Bars[i] = NULL; + } + g_TwMgr->m_Bars.clear(); + g_TwMgr->m_Order.clear(); + g_TwMgr->m_MinOccupied.clear(); + g_TwMgr->m_HelpBarNotUpToDate = true; + + if( n==0 ) + { + g_TwMgr->SetLastError(g_ErrNthToDo); + return 0; + } + else + return 1; +} + +// --------------------------------------------------------------------------- + +int ANT_CALL TwSetTopBar(const TwBar *_Bar) +{ + if( g_TwMgr==NULL ) + { + TwGlobalError(g_ErrNotInit); + return 0; // not initialized + } + if( _Bar==NULL ) + { + g_TwMgr->SetLastError(g_ErrBadParam); + return 0; + } + + int i = -1, iOrder; + for( iOrder=0; iOrder<(int)g_TwMgr->m_Bars.size(); ++iOrder ) + { + i = g_TwMgr->m_Order[iOrder]; + assert( i>=0 && i<(int)g_TwMgr->m_Bars.size() ); + if( g_TwMgr->m_Bars[i]==_Bar ) + break; + } + if( i<0 || iOrder>=(int)g_TwMgr->m_Bars.size() ) // bar not found + { + g_TwMgr->SetLastError(g_ErrNotFound); + return 0; + } + + for( int j=iOrder; j<(int)g_TwMgr->m_Bars.size()-1; ++j ) + g_TwMgr->m_Order[j] = g_TwMgr->m_Order[j+1]; + g_TwMgr->m_Order[(int)g_TwMgr->m_Bars.size()-1] = i; + + if( g_TwMgr->m_PopupBar!=NULL && _Bar!=g_TwMgr->m_PopupBar ) + TwSetTopBar(g_TwMgr->m_PopupBar); + + return 1; +} + +// --------------------------------------------------------------------------- + +TwBar * ANT_CALL TwGetTopBar() +{ + if( g_TwMgr==NULL ) + { + TwGlobalError(g_ErrNotInit); + return NULL; // not initialized + } + + if( g_TwMgr->m_Bars.size()>0 && g_TwMgr->m_PopupBar==NULL ) + return g_TwMgr->m_Bars[g_TwMgr->m_Order[ g_TwMgr->m_Bars.size()-1 ]]; + else if( g_TwMgr->m_Bars.size()>1 && g_TwMgr->m_PopupBar!=NULL ) + return g_TwMgr->m_Bars[g_TwMgr->m_Order[ g_TwMgr->m_Bars.size()-2 ]]; + else + return NULL; +} + +// --------------------------------------------------------------------------- + +int ANT_CALL TwSetBarState(TwBar *_Bar, TwState _State) +{ + if( g_TwMgr==NULL ) + { + TwGlobalError(g_ErrNotInit); + return 0; // not initialized + } + if( _Bar==NULL ) + { + g_TwMgr->SetLastError(g_ErrBadParam); + return 0; + } + + switch( _State ) + { + case TW_STATE_SHOWN: + g_TwMgr->Unhide(_Bar); + return 1; + case TW_STATE_ICONIFIED: + g_TwMgr->Unhide(_Bar); + g_TwMgr->Minimize(_Bar); + return 1; + case TW_STATE_HIDDEN: + g_TwMgr->Maximize(_Bar); + g_TwMgr->Hide(_Bar); + return 1; + default: + g_TwMgr->SetLastError(g_ErrBadParam); + return 0; + } +} + +// --------------------------------------------------------------------------- + +TwState ANT_CALL TwGetBarState(const TwBar *_Bar) +{ + if( g_TwMgr==NULL ) + { + TwGlobalError(g_ErrNotInit); + return TW_STATE_ERROR; // not initialized + } + if( _Bar==NULL ) + { + g_TwMgr->SetLastError(g_ErrBadParam); + return TW_STATE_ERROR; + } + + if( !_Bar->m_Visible ) + return TW_STATE_HIDDEN; + else if( _Bar->IsMinimized() ) + return TW_STATE_ICONIFIED; + else + return TW_STATE_SHOWN; +} + +// --------------------------------------------------------------------------- + +const char * ANT_CALL TwGetBarName(TwBar *_Bar) +{ + if( g_TwMgr==NULL ) + { + TwGlobalError(g_ErrNotInit); + return NULL; // not initialized + } + if( _Bar==NULL ) + { + g_TwMgr->SetLastError(g_ErrBadParam); + return NULL; + } + + return _Bar->m_Name.c_str(); +} + +// --------------------------------------------------------------------------- + +static int s_PassProxy = 0; +void *CTwMgr::CStruct::s_PassProxyAsClientData = &s_PassProxy; // special tag + +CTwMgr::CStructProxy::CStructProxy() +{ + memset(this, 0, sizeof(*this)); +} + +CTwMgr::CStructProxy::~CStructProxy() +{ + if( m_StructData!=NULL && m_DeleteStructData ) + delete[] (char*)m_StructData; + if( m_StructExtData!=NULL ) + delete[] (char*)m_StructExtData; + memset(this, 0, sizeof(*this)); +} + +CTwMgr::CMemberProxy::CMemberProxy() +{ + memset(this, 0, sizeof(*this)); +} + +CTwMgr::CMemberProxy::~CMemberProxy() +{ + memset(this, 0, sizeof(*this)); +} + +void ANT_CALL CTwMgr::CMemberProxy::SetCB(const void *_Value, void *_ClientData) +{ + if( _ClientData && _Value ) + { + const CMemberProxy *mProxy = static_cast(_ClientData); + if( g_TwMgr && mProxy ) + { + const CStructProxy *sProxy = mProxy->m_StructProxy; + if( sProxy && sProxy->m_StructData && sProxy->m_Type>=TW_TYPE_STRUCT_BASE && sProxy->m_Typem_Structs.size() ) + { + CTwMgr::CStruct& s = g_TwMgr->m_Structs[sProxy->m_Type-TW_TYPE_STRUCT_BASE]; + if( mProxy->m_MemberIndex>=0 && mProxy->m_MemberIndex<(int)s.m_Members.size() ) + { + CTwMgr::CStructMember& m = s.m_Members[mProxy->m_MemberIndex]; + if( m.m_Size>0 && m.m_Type!=TW_TYPE_BUTTON ) + { + if( s.m_IsExt ) + { + memcpy((char *)sProxy->m_StructExtData + m.m_Offset, _Value, m.m_Size); + if( s.m_CopyVarFromExtCallback && sProxy->m_StructExtData ) + s.m_CopyVarFromExtCallback(sProxy->m_StructData, sProxy->m_StructExtData, mProxy->m_MemberIndex, (s.m_ExtClientData==s.s_PassProxyAsClientData) ? _ClientData : s.m_ExtClientData); + } + else + memcpy((char *)sProxy->m_StructData + m.m_Offset, _Value, m.m_Size); + if( sProxy->m_StructSetCallback ) + sProxy->m_StructSetCallback(sProxy->m_StructData, sProxy->m_StructClientData); + } + } + } + } + } +} + +void ANT_CALL CTwMgr::CMemberProxy::GetCB(void *_Value, void *_ClientData) +{ + if( _ClientData && _Value ) + { + const CMemberProxy *mProxy = static_cast(_ClientData); + if( g_TwMgr && mProxy ) + { + const CStructProxy *sProxy = mProxy->m_StructProxy; + if( sProxy && sProxy->m_StructData && sProxy->m_Type>=TW_TYPE_STRUCT_BASE && sProxy->m_Typem_Structs.size() ) + { + CTwMgr::CStruct& s = g_TwMgr->m_Structs[sProxy->m_Type-TW_TYPE_STRUCT_BASE]; + if( mProxy->m_MemberIndex>=0 && mProxy->m_MemberIndex<(int)s.m_Members.size() ) + { + CTwMgr::CStructMember& m = s.m_Members[mProxy->m_MemberIndex]; + if( m.m_Size>0 && m.m_Type!=TW_TYPE_BUTTON ) + { + if( sProxy->m_StructGetCallback ) + sProxy->m_StructGetCallback(sProxy->m_StructData, sProxy->m_StructClientData); + if( s.m_IsExt ) + { + if( s.m_CopyVarToExtCallback && sProxy->m_StructExtData ) + s.m_CopyVarToExtCallback(sProxy->m_StructData, sProxy->m_StructExtData, mProxy->m_MemberIndex, (s.m_ExtClientData==s.s_PassProxyAsClientData) ? _ClientData : s.m_ExtClientData); + memcpy(_Value, (char *)sProxy->m_StructExtData + m.m_Offset, m.m_Size); + } + else + memcpy(_Value, (char *)sProxy->m_StructData + m.m_Offset, m.m_Size); + } + } + } + } + } +} + +// --------------------------------------------------------------------------- + +static int AddVar(TwBar *_Bar, const char *_Name, ETwType _Type, void *_VarPtr, bool _ReadOnly, TwSetVarCallback _SetCallback, TwGetVarCallback _GetCallback, TwButtonCallback _ButtonCallback, void *_ClientData, const char *_Def) +{ + CTwFPU fpu; // force fpu precision + + if( g_TwMgr==NULL ) + { + TwGlobalError(g_ErrNotInit); + return 0; // not initialized + } + if( _Bar==NULL || _Name==NULL || strlen(_Name)==0 || (_VarPtr==NULL && _GetCallback==NULL && _Type!=TW_TYPE_BUTTON) ) + { + g_TwMgr->SetLastError(g_ErrBadParam); + return 0; + } + if( _Bar->Find(_Name)!=NULL ) + { + g_TwMgr->SetLastError(g_ErrExist); + return 0; + } + + if( strstr(_Name, "`")!=NULL ) + { + g_TwMgr->SetLastError(g_ErrNoBackQuote); + return 0; + } + + if( _VarPtr==NULL && _Type!=TW_TYPE_BUTTON && _GetCallback!=NULL && _SetCallback==NULL ) + _ReadOnly = true; // force readonly in this case + + // Convert color types + if( _Type==TW_TYPE_COLOR32 ) + _Type = g_TwMgr->m_TypeColor32; + else if( _Type==TW_TYPE_COLOR3F ) + _Type = g_TwMgr->m_TypeColor3F; + else if( _Type==TW_TYPE_COLOR4F ) + _Type = g_TwMgr->m_TypeColor4F; + + if( _Type=TW_TYPE_ENUM_BASE && _Typem_Enums.size()) ) + { + CTwVarAtom *Var = new CTwVarAtom; + Var->m_Name = _Name; + Var->m_Ptr = _VarPtr; + Var->m_Type = _Type; + if( _VarPtr!=NULL ) + { + assert( _GetCallback==NULL && _SetCallback==NULL && _ButtonCallback==NULL ); + + Var->m_ReadOnly = _ReadOnly; + Var->m_GetCallback = NULL; + Var->m_SetCallback = NULL; + Var->m_ButtonCallback = NULL; + Var->m_ClientData = NULL; + } + else + { + assert( _GetCallback!=NULL || _Type==TW_TYPE_BUTTON ); + + Var->m_GetCallback = _GetCallback; + Var->m_SetCallback = _SetCallback; + Var->m_ButtonCallback = _ButtonCallback; + Var->m_ClientData = _ClientData; + if( _Type!=TW_TYPE_BUTTON ) + Var->m_ReadOnly = (_SetCallback==NULL || _ReadOnly); + else + Var->m_ReadOnly = (_ButtonCallback==NULL); + } + Var->m_Color = _Bar->m_ColLabelText; + Var->SetDefaults(); + + _Bar->m_VarRoot.m_Vars.push_back(Var); + _Bar->NotUpToDate(); + g_TwMgr->m_HelpBarNotUpToDate = true; + + if( _Def!=NULL && strlen(_Def)>0 ) + { + string d = '`' + _Bar->m_Name + "`/`" + _Name + "` " + _Def; + return TwDefine(d.c_str()); + } + else + return 1; + } + else if(_Type>=TW_TYPE_STRUCT_BASE && _Typem_Structs.size()) + { + CTwMgr::CStruct& s = g_TwMgr->m_Structs[_Type-TW_TYPE_STRUCT_BASE]; + CTwMgr::CStructProxy *sProxy = NULL; + void *vPtr; + if( !s.m_IsExt ) + { + if( _VarPtr!=NULL ) + vPtr = _VarPtr; + else + { + assert( _GetCallback!=NULL || _SetCallback!=NULL ); + assert( s.m_Size>0 ); + vPtr = new char[s.m_Size]; + memset(vPtr, 0, s.m_Size); + // create a new StructProxy + g_TwMgr->m_StructProxies.push_back(CTwMgr::CStructProxy()); + sProxy = &(g_TwMgr->m_StructProxies.back()); + sProxy->m_Type = _Type; + sProxy->m_StructData = vPtr; + sProxy->m_DeleteStructData = true; + sProxy->m_StructSetCallback = _SetCallback; + sProxy->m_StructGetCallback = _GetCallback; + sProxy->m_StructClientData = _ClientData; + } + } + else // s.m_IsExt + { + assert( s.m_Size>0 && s.m_ClientStructSize>0 ); + vPtr = new char[s.m_Size]; // will be m_StructExtData + memset(vPtr, 0, s.m_Size); + // create a new StructProxy + g_TwMgr->m_StructProxies.push_back(CTwMgr::CStructProxy()); + sProxy = &(g_TwMgr->m_StructProxies.back()); + sProxy->m_Type = _Type; + sProxy->m_StructExtData = vPtr; + sProxy->m_StructSetCallback = _SetCallback; + sProxy->m_StructGetCallback = _GetCallback; + sProxy->m_StructClientData = _ClientData; + if( _VarPtr!=NULL ) + { + sProxy->m_StructData = _VarPtr; + sProxy->m_DeleteStructData = false; + } + else + { + sProxy->m_StructData = new char[s.m_ClientStructSize]; + memset(sProxy->m_StructData, 0, s.m_ClientStructSize); + sProxy->m_DeleteStructData = true; + } + _VarPtr = NULL; // force use of TwAddVarCB for members + + // init m_StructExtdata + if( s.m_ExtClientData==CTwMgr::CStruct::s_PassProxyAsClientData ) + s.m_StructExtInitCallback(sProxy->m_StructExtData, sProxy); + else + s.m_StructExtInitCallback(sProxy->m_StructExtData, s.m_ExtClientData); + } + for( int i=0; i<(int)s.m_Members.size(); ++i ) + { + CTwMgr::CStructMember& m = s.m_Members[i]; + string name = string(_Name) + '.' + m.m_Name; + const char *access = ""; + if( _ReadOnly ) + access = "readonly "; + string def = "label=`" + m.m_Name + "` group=`" + _Name + "` " + access; // + m.m_DefString; // member def must be done after group def + if( _VarPtr!=NULL ) + { + if( TwAddVarRW(_Bar, name.c_str(), m.m_Type, (char*)vPtr+m.m_Offset, def.c_str())==0 ) + return 0; + } + else + { + assert( sProxy!=NULL ); + // create a new MemberProxy + g_TwMgr->m_MemberProxies.push_back(CTwMgr::CMemberProxy()); + CTwMgr::CMemberProxy& mProxy = g_TwMgr->m_MemberProxies.back(); + mProxy.m_StructProxy = sProxy; + mProxy.m_MemberIndex = i; + if( TwAddVarCB(_Bar, name.c_str(), m.m_Type, CTwMgr::CMemberProxy::SetCB, CTwMgr::CMemberProxy::GetCB, &mProxy, def.c_str())==0 ) + return 0; + mProxy.m_Var = _Bar->Find(name.c_str(), &mProxy.m_VarParent, NULL); + mProxy.m_Bar = _Bar; + } + } + char structInfo[64]; + sprintf(structInfo, "typeid=%d valptr=%p close ", _Type, vPtr); + string grpDef = '`' + _Bar->m_Name + "`/`" + _Name + "` " + structInfo; + if( _Def!=NULL && strlen(_Def)>0 ) + grpDef += _Def; + if( TwDefine(grpDef.c_str()) ) + { + for( int i=0; i<(int)s.m_Members.size(); ++i ) + { + CTwMgr::CStructMember& m = s.m_Members[i]; + if( m.m_DefString.length()>0 ) + { + string memberDef = '`' + _Bar->m_Name + "`/`" + _Name + '.' + m.m_Name + "` " + m.m_DefString; + if( !TwDefine(memberDef.c_str()) ) + return 0; + } + } + return 1; + } + else + return 0; + } + else + { + g_TwMgr->SetLastError(g_ErrNotFound); + return 0; + } +} + +// --------------------------------------------------------------------------- + +int ANT_CALL TwAddVarRW(TwBar *_Bar, const char *_Name, ETwType _Type, void *_Var, const char *_Def) +{ + return AddVar(_Bar, _Name, _Type, _Var, false, NULL, NULL, NULL, NULL, _Def); +} + +// --------------------------------------------------------------------------- + +int ANT_CALL TwAddVarRO(TwBar *_Bar, const char *_Name, ETwType _Type, const void *_Var, const char *_Def) +{ + return AddVar(_Bar, _Name, _Type, const_cast(_Var), true, NULL, NULL, NULL, NULL, _Def); +} + +// --------------------------------------------------------------------------- + +int ANT_CALL TwAddVarCB(TwBar *_Bar, const char *_Name, ETwType _Type, TwSetVarCallback _SetCallback, TwGetVarCallback _GetCallback, void *_ClientData, const char *_Def) +{ + return AddVar(_Bar, _Name, _Type, NULL, false, _SetCallback, _GetCallback, NULL, _ClientData, _Def); +} + +// --------------------------------------------------------------------------- + +int ANT_CALL TwAddButton(TwBar *_Bar, const char *_Name, TwButtonCallback _Callback, void *_ClientData, const char *_Def) +{ + return AddVar(_Bar, _Name, TW_TYPE_BUTTON, NULL, false, NULL, NULL, _Callback, _ClientData, _Def); +} + +// --------------------------------------------------------------------------- + +int ANT_CALL TwRemoveVar(TwBar *_Bar, const char *_Name) +{ + if( g_TwMgr==NULL ) + { + TwGlobalError(g_ErrNotInit); + return 0; // not initialized + } + if( _Bar==NULL || _Name==NULL || strlen(_Name)==0 ) + { + g_TwMgr->SetLastError(g_ErrBadParam); + return 0; + } + + if( g_TwMgr->m_PopupBar!=NULL && _Bar!=g_TwMgr->m_PopupBar ) // delete popup bar first if it exists + { + TwDeleteBar(g_TwMgr->m_PopupBar); + g_TwMgr->m_PopupBar = NULL; + } + + CTwVarGroup *Parent = NULL; + int Index = -1; + CTwVar *Var = _Bar->Find(_Name, &Parent, &Index); + if( Var!=NULL && Parent!=NULL && Index>=0 ) + { + if( Parent->m_StructValuePtr!=NULL ) + { + g_TwMgr->SetLastError(g_ErrDelStruct); + return 0; + } + + delete Var; + Parent->m_Vars.erase(Parent->m_Vars.begin()+Index); + if( Parent!=&(_Bar->m_VarRoot) && Parent->m_Vars.size()<=0 ) + TwRemoveVar(_Bar, Parent->m_Name.c_str()); + _Bar->NotUpToDate(); + if( _Bar!=g_TwMgr->m_HelpBar ) + g_TwMgr->m_HelpBarNotUpToDate = true; + return 1; + } + + g_TwMgr->SetLastError(g_ErrNotFound); + return 0; +} + +// --------------------------------------------------------------------------- + +int ANT_CALL TwRemoveAllVars(TwBar *_Bar) +{ + if( g_TwMgr==NULL ) + { + TwGlobalError(g_ErrNotInit); + return 0; // not initialized + } + if( _Bar==NULL ) + { + g_TwMgr->SetLastError(g_ErrBadParam); + return 0; + } + + if( g_TwMgr->m_PopupBar!=NULL && _Bar!=g_TwMgr->m_PopupBar ) // delete popup bar first if it exists + { + TwDeleteBar(g_TwMgr->m_PopupBar); + g_TwMgr->m_PopupBar = NULL; + } + + for( vector::iterator it=_Bar->m_VarRoot.m_Vars.begin(); it!=_Bar->m_VarRoot.m_Vars.end(); ++it ) + if( *it != NULL ) + { + delete *it; + *it = NULL; + } + _Bar->m_VarRoot.m_Vars.resize(0); + _Bar->NotUpToDate(); + g_TwMgr->m_HelpBarNotUpToDate = true; + return 1; +} + +// --------------------------------------------------------------------------- + +int ParseToken(string& _Token, const char *_Def, int& Line, int& Column, bool _KeepQuotes, bool _EndCR, char _Sep1='\0', char _Sep2='\0') +{ + const char *Cur = _Def; + _Token = ""; + // skip spaces + while( *Cur==' ' || *Cur=='\t' || *Cur=='\r' || *Cur=='\n' ) + { + if( *Cur=='\n' && _EndCR ) + return (int)(Cur-_Def); // a CR has been found + ++Cur; + if( *Cur=='\n' ) + { + ++Line; + Column = 1; + } + else if( *Cur=='\t' ) + Column += g_TabLength; + else if( *Cur!='\r' ) + ++Column; + } + // read token + int QuoteLine=0, QuoteColumn=0; + const char *QuoteCur; + char Quote = 0; + bool AddChar; + while( (Quote==0 && (*Cur!='\0' && *Cur!=' ' && *Cur!='\t' && *Cur!='\r' && *Cur!='\n' && *Cur!=_Sep1 && *Cur!=_Sep2)) + || (Quote!=0 && (*Cur!='\0' /* && *Cur!='\r' && *Cur!='\n' */)) ) // allow multi-line strings + { + AddChar = true; + if( Quote==0 && (*Cur=='\'' || *Cur=='\"' || *Cur=='`') ) + { + Quote = *Cur; + QuoteLine = Line; + QuoteColumn = Column; + QuoteCur = Cur; + AddChar = _KeepQuotes; + } + else if ( Quote!=0 && *Cur==Quote ) + { + Quote = 0; + AddChar = _KeepQuotes; + } + + if( AddChar ) + _Token += *Cur; + ++Cur; + if( *Cur=='\t' ) + Column += g_TabLength; + else if( *Cur=='\n' ) + { + ++Line; + Column = 1; + } + else + ++Column; + } + + if( Quote!=0 ) + { + Line = QuoteLine; + Column = QuoteColumn; + return -(int)(Cur-_Def); // unclosed quote + } + else + { + if( *Cur=='\n' ) + { + ++Line; + Column = 1; + } + else if( *Cur=='\t' ) + Column += g_TabLength; + else if( *Cur!='\r' && *Cur!='\0' ) + ++Column; + return (int)(Cur-_Def); + } +} + +// --------------------------------------------------------------------------- + +int GetBarVarFromString(CTwBar **_Bar, CTwVar **_Var, CTwVarGroup **_VarParent, int *_VarIndex, const char *_Str) +{ + *_Bar = NULL; + *_Var = NULL; + *_VarParent = NULL; + *_VarIndex = -1; + vector Names; + string Token; + const char *Cur =_Str; + int l=1, c=1, p=1; + while( *Cur!='\0' && p>0 && Names.size()<=3 ) + { + p = ParseToken(Token, Cur, l, c, false, true, '/', '\\'); + if( p>0 && Token.size()>0 ) + { + Names.push_back(Token); + Cur += p + ((Cur[p]!='\0')?1:0); + } + } + if( p<=0 || (Names.size()!=1 && Names.size()!=2) ) + return 0; // parse error + int BarIdx = g_TwMgr->FindBar(Names[0].c_str()); + if( BarIdx<0 ) + { + if( Names.size()==1 && _stricmp(Names[0].c_str(), "global")==0 ) + { + *_Bar = TW_GLOBAL_BAR; + return +3; // 'GLOBAL' found + } + else + return -1; // bar not found + } + *_Bar = g_TwMgr->m_Bars[BarIdx]; + if( Names.size()==1 ) + return 1; // bar found, no var name parsed + *_Var = (*_Bar)->Find(Names[1].c_str(), _VarParent, _VarIndex); + if( *_Var==NULL ) + return -2; // var not found + return 2; // bar and var found +} + +// --------------------------------------------------------------------------- + +int BarVarHasAttrib(CTwBar *_Bar, CTwVar *_Var, const char *_Attrib, bool *_HasValue) +{ + assert(_Bar!=NULL && _HasValue!=NULL && _Attrib!=NULL && strlen(_Attrib)>0); + *_HasValue = false; + if( _Bar==TW_GLOBAL_BAR ) + { + assert( _Var==NULL ); + return g_TwMgr->HasAttrib(_Attrib, _HasValue); + } + else if( _Var==NULL ) + return _Bar->HasAttrib(_Attrib, _HasValue); + else + return _Var->HasAttrib(_Attrib, _HasValue); +} + +// --------------------------------------------------------------------------- + +int BarVarSetAttrib(CTwBar *_Bar, CTwVar *_Var, CTwVarGroup *_VarParent, int _VarIndex, int _AttribID, const char *_Value) +{ + assert(_Bar!=NULL && _AttribID>0); + + /* don't delete popupbar here: if any attrib is changed every frame by the app, popup will not work anymore. + if( g_TwMgr->m_PopupBar!=NULL && _Bar!=g_TwMgr->m_PopupBar && g_TwMgr->m_PopupBar->m_BarLinkedToPopupList==_Bar ) // delete popup bar first if it exists + { + TwDeleteBar(g_TwMgr->m_PopupBar); + g_TwMgr->m_PopupBar = NULL; + } + */ + + if( _Bar==TW_GLOBAL_BAR ) + { + assert( _Var==NULL ); + return g_TwMgr->SetAttrib(_AttribID, _Value); + } + else if( _Var==NULL ) + return _Bar->SetAttrib(_AttribID, _Value); + else + return _Var->SetAttrib(_AttribID, _Value, _Bar, _VarParent, _VarIndex); +} + +// --------------------------------------------------------------------------- + +int ANT_CALL TwDefine(const char *_Def) +{ + CTwFPU fpu; // force fpu precision + + if( g_TwMgr==NULL ) + { + TwGlobalError(g_ErrNotInit); + return 0; // not initialized + } + if( _Def==NULL ) + { + g_TwMgr->SetLastError(g_ErrBadParam); + return 0; + } + + int Line = 1; + int Column = 1; + const char *Cur = _Def; + enum EState { PARSE_NAME, PARSE_ATTRIB }; + EState State = PARSE_NAME; + string Token; + string Value; + CTwBar *Bar = NULL; + CTwVar *Var = NULL; + CTwVarGroup *VarParent = NULL; + int VarIndex = -1; + int p; + while( *Cur!='\0' ) + { + const char *PrevCur = Cur; + p = ParseToken(Token, Cur, Line, Column, (State==PARSE_NAME), (State==PARSE_ATTRIB), (State==PARSE_ATTRIB)?'=':'\0'); + if( p<=0 || Token.size()<=0 ) + { + if( p>0 && Cur[p]=='\0' ) + { + Cur += p; + continue; + } + sprintf(g_ErrParse, "Parsing error in def string, line %d column %d [%-16s...]", Line, Column, (p<0)?(Cur-p):PrevCur); + g_TwMgr->SetLastError(g_ErrParse); + return 0; + } + char CurSep = Cur[p]; + Cur += p + ((CurSep!='\0')?1:0); + + if( State==PARSE_NAME ) + { + int Err = GetBarVarFromString(&Bar, &Var, &VarParent, &VarIndex, Token.c_str()); + if( Err<=0 ) + { + if( Err==-1 ) + sprintf(g_ErrParse, "Parsing error in def string: Bar not found line %d column %d [%-16s...]", Line, Column, Token.c_str()); + else if( Err==-2 ) + sprintf(g_ErrParse, "Parsing error in def string: Variable not found line %d column %d [%-16s...]", Line, Column, Token.c_str()); + else + sprintf(g_ErrParse, "Parsing error in def string, line %d column %d [%-16s...]", Line, Column, Token.c_str()); + g_TwMgr->SetLastError(g_ErrParse); + return 0; + } + State = PARSE_ATTRIB; + } + else // State==PARSE_ATTRIB + { + assert(State==PARSE_ATTRIB); + assert(Bar!=NULL); + + bool HasValue = false; + Value = ""; + int AttribID = BarVarHasAttrib(Bar, Var, Token.c_str(), &HasValue); + if( AttribID<=0 ) + { + sprintf(g_ErrParse, "Parsing error in def string: Unknown attribute line %d column %d [%-16s...]", Line, Column, Token.c_str()); + g_TwMgr->SetLastError(g_ErrParse); + return 0; + } + if( HasValue ) + { + if( CurSep!='=' ) + { + string EqualStr; + p = ParseToken(EqualStr, Cur, Line, Column, true, true, '='); + CurSep = Cur[p]; + if( p<0 || EqualStr.size()>0 || CurSep!='=' ) + { + sprintf(g_ErrParse, "Parsing error in def string: '=' not found while reading attribute value line %d column %d [%-16s...]", Line, Column, Token.c_str()); + g_TwMgr->SetLastError(g_ErrParse); + return 0; + } + Cur += p + 1; + } + p = ParseToken(Value, Cur, Line, Column, false, true); + if( p<=0 ) + { + sprintf(g_ErrParse, "Parsing error in def string: can't read attribute value line %d column %d [%-16s...]", Line, Column, Token.c_str()); + g_TwMgr->SetLastError(g_ErrParse); + return 0; + } + CurSep = Cur[p]; + Cur += p + ((CurSep!='\0')?1:0); + } + if( BarVarSetAttrib(Bar, Var, VarParent, VarIndex, AttribID, HasValue?Value.c_str():NULL)==0 ) + { + if( g_TwMgr->CheckLastError()==NULL || strlen(g_TwMgr->CheckLastError())<=0 ) + sprintf(g_ErrParse, "Parsing error in def string: wrong attribute value line %d column %d [%-16s...]", Line, Column, Token.c_str()); + else + sprintf(g_ErrParse, "%s line %d column %d [%-16s...]", g_TwMgr->CheckLastError(), Line, Column, Token.c_str()); + g_TwMgr->SetLastError(g_ErrParse); + return 0; + } + // sweep spaces to detect next attrib + while( *Cur==' ' || *Cur=='\t' || *Cur=='\r' ) + { + ++Cur; + if( *Cur=='\t' ) + Column += g_TabLength; + else if( *Cur!='\r' ) + ++Column; + } + if( *Cur=='\n' ) // new line detected + { + ++Line; + Column = 1; + State = PARSE_NAME; + } + } + } + + g_TwMgr->m_HelpBarNotUpToDate = true; + return 1; +} + +// --------------------------------------------------------------------------- + +TwType ANT_CALL TwDefineEnum(const char *_Name, const TwEnumVal *_EnumValues, unsigned int _NbValues) +{ + CTwFPU fpu; // force fpu precision + + if( g_TwMgr==NULL ) + { + TwGlobalError(g_ErrNotInit); + return TW_TYPE_UNDEF; // not initialized + } + if( _EnumValues==NULL && _NbValues!=0 ) + { + g_TwMgr->SetLastError(g_ErrBadParam); + return TW_TYPE_UNDEF; + } + + if( g_TwMgr->m_PopupBar!=NULL ) // delete popup bar first if it exists + { + TwDeleteBar(g_TwMgr->m_PopupBar); + g_TwMgr->m_PopupBar = NULL; + } + + size_t enumIndex = g_TwMgr->m_Enums.size(); + if( _Name!=NULL && strlen(_Name)>0 ) + for( size_t j=0; jm_Enums.size(); ++j ) + if( strcmp(_Name, g_TwMgr->m_Enums[j].m_Name.c_str())==0 ) + { + enumIndex = j; + break; + } + if( enumIndex==g_TwMgr->m_Enums.size() ) + g_TwMgr->m_Enums.push_back(CTwMgr::CEnum()); + assert( enumIndex>=0 && enumIndexm_Enums.size() ); + CTwMgr::CEnum& e = g_TwMgr->m_Enums[enumIndex]; + if( _Name!=NULL && strlen(_Name)>0 ) + e.m_Name = _Name; + else + e.m_Name = ""; + e.m_Entries.clear(); + for(unsigned int i=0; i<_NbValues; ++i) + { + CTwMgr::CEnum::CEntries::value_type Entry(_EnumValues[i].Value, (_EnumValues[i].Label!=NULL)?_EnumValues[i].Label:""); + pair Result = e.m_Entries.insert(Entry); + if( !Result.second ) + (Result.first)->second = Entry.second; + } + + return TwType( TW_TYPE_ENUM_BASE + enumIndex ); +} + +// --------------------------------------------------------------------------- + +void ANT_CALL CTwMgr::CStruct::DefaultSummary(char *_SummaryString, size_t _SummaryMaxLength, const void *_Value, void *_ClientData) +{ + const CTwVarGroup *varGroup = static_cast(_Value); // special case + if( _SummaryString && _SummaryMaxLength>0 ) + _SummaryString[0] = '\0'; + size_t structIndex = (size_t)(_ClientData); + if( g_TwMgr && _SummaryString && _SummaryMaxLength>2 + && varGroup && static_cast(varGroup)->IsGroup() + && structIndex>=0 && structIndex<=g_TwMgr->m_Structs.size() ) + { + // return g_TwMgr->m_Structs[structIndex].m_Name.c_str(); + CTwMgr::CStruct& s = g_TwMgr->m_Structs[structIndex]; + _SummaryString[0] = '{'; + _SummaryString[1] = '\0'; + bool separator = false; + for( size_t i=0; im_Name + '.' + s.m_Members[i].m_Name; + const CTwVar *var = varGroup->Find(varName.c_str(), NULL, NULL); + if( var ) + { + if( var->IsGroup() ) + { + const CTwVarGroup *grp = static_cast(var); + if( grp->m_SummaryCallback!=NULL ) + { + size_t l = strlen(_SummaryString); + if( separator ) + { + _SummaryString[l++] = ','; + _SummaryString[l++] = '\0'; + } + if( grp->m_SummaryCallback==CTwMgr::CStruct::DefaultSummary ) + grp->m_SummaryCallback(_SummaryString+l, _SummaryMaxLength-l, grp, grp->m_SummaryClientData); + else + grp->m_SummaryCallback(_SummaryString+l, _SummaryMaxLength-l, grp->m_StructValuePtr, grp->m_SummaryClientData); + separator = true; + } + } + else + { + size_t l = strlen(_SummaryString); + if( separator ) + { + _SummaryString[l++] = ','; + _SummaryString[l++] = '\0'; + } + string valString; + const CTwVarAtom *atom = static_cast(var); + atom->ValueToString(&valString); + strncat(_SummaryString, valString.c_str(), _SummaryMaxLength-l); + separator = true; + } + if( strlen(_SummaryString)>_SummaryMaxLength-2 ) + break; + } + } + size_t l = strlen(_SummaryString); + if( l>_SummaryMaxLength-2 ) + { + _SummaryString[_SummaryMaxLength-2] = '.'; + _SummaryString[_SummaryMaxLength-1] = '.'; + _SummaryString[_SummaryMaxLength+0] = '\0'; + } + else + { + _SummaryString[l+0] = '}'; + _SummaryString[l+1] = '\0'; + } + } +} + +// --------------------------------------------------------------------------- + +TwType ANT_CALL TwDefineStruct(const char *_StructName, const TwStructMember *_StructMembers, unsigned int _NbMembers, size_t _StructSize, TwSummaryCallback _SummaryCallback, void *_SummaryClientData) +{ + CTwFPU fpu; // force fpu precision + + if( g_TwMgr==NULL ) + { + TwGlobalError(g_ErrNotInit); + return TW_TYPE_UNDEF; // not initialized + } + if( _StructMembers==NULL || _NbMembers==0 || _StructSize==0 ) + { + g_TwMgr->SetLastError(g_ErrBadParam); + return TW_TYPE_UNDEF; + } + + if( _StructName!=NULL && strlen(_StructName)>0 ) + for( size_t j=0; jm_Structs.size(); ++j ) + if( strcmp(_StructName, g_TwMgr->m_Structs[j].m_Name.c_str())==0 ) + { + g_TwMgr->SetLastError(g_ErrExist); + return TW_TYPE_UNDEF; + } + + size_t structIndex = g_TwMgr->m_Structs.size(); + CTwMgr::CStruct s; + s.m_Size = _StructSize; + if( _StructName!=NULL && strlen(_StructName)>0 ) + s.m_Name = _StructName; + else + s.m_Name = ""; + s.m_Members.resize(_NbMembers); + if( _SummaryCallback!=NULL ) + { + s.m_SummaryCallback = _SummaryCallback; + s.m_SummaryClientData = _SummaryClientData; + } + else + { + s.m_SummaryCallback = CTwMgr::CStruct::DefaultSummary; + s.m_SummaryClientData = (void *)(structIndex); + } + for( unsigned int i=0; i<_NbMembers; ++i ) + { + CTwMgr::CStructMember& m = s.m_Members[i]; + if( _StructMembers[i].Name!=NULL ) + m.m_Name = _StructMembers[i].Name; + else + { + char name[16]; + sprintf(name, "%u", i); + m.m_Name = name; + } + m.m_Type = _StructMembers[i].Type; + m.m_Size = 0; // to avoid endless recursivity in GetDataSize + m.m_Size = CTwVar::GetDataSize(m.m_Type); + if( _StructMembers[i].Offset<_StructSize ) + m.m_Offset = _StructMembers[i].Offset; + else + { + g_TwMgr->SetLastError(g_ErrOffset); + return TW_TYPE_UNDEF; + } + if( _StructMembers[i].DefString!=NULL && strlen(_StructMembers[i].DefString)>0 ) + m.m_DefString = _StructMembers[i].DefString; + else + m.m_DefString = ""; + } + + g_TwMgr->m_Structs.push_back(s); + assert( g_TwMgr->m_Structs.size()==structIndex+1 ); + return TwType( TW_TYPE_STRUCT_BASE + structIndex ); +} + +// --------------------------------------------------------------------------- + +TwType ANT_CALL TwDefineStructExt(const char *_StructName, const TwStructMember *_StructExtMembers, unsigned int _NbExtMembers, size_t _StructSize, size_t _StructExtSize, TwStructExtInitCallback _StructExtInitCallback, TwCopyVarFromExtCallback _CopyVarFromExtCallback, TwCopyVarToExtCallback _CopyVarToExtCallback, TwSummaryCallback _SummaryCallback, void *_ClientData) +{ + CTwFPU fpu; // force fpu precision + + if( g_TwMgr==NULL ) + { + TwGlobalError(g_ErrNotInit); + return TW_TYPE_UNDEF; // not initialized + } + if( _StructSize==0 || _StructExtInitCallback==NULL || _CopyVarFromExtCallback==NULL || _CopyVarToExtCallback==NULL ) + { + g_TwMgr->SetLastError(g_ErrBadParam); + return TW_TYPE_UNDEF; + } + TwType type = TwDefineStruct(_StructName, _StructExtMembers, _NbExtMembers, _StructExtSize, _SummaryCallback, _ClientData); + if( type>=TW_TYPE_STRUCT_BASE && typem_Structs.size() ) + { + CTwMgr::CStruct& s = g_TwMgr->m_Structs[type-TW_TYPE_STRUCT_BASE]; + s.m_IsExt = true; + s.m_ClientStructSize = _StructSize; + s.m_StructExtInitCallback = _StructExtInitCallback; + s.m_CopyVarFromExtCallback = _CopyVarFromExtCallback; + s.m_CopyVarToExtCallback = _CopyVarToExtCallback; + s.m_ExtClientData = _ClientData; + } + return type; +} + + +// --------------------------------------------------------------------------- + +bool TwGetKeyCode(int *_Code, int *_Modif, const char *_String) +{ + assert(_Code!=NULL && _Modif!=NULL); + bool Ok = true; + *_Modif = TW_KMOD_NONE; + *_Code = 0; + size_t Start = strlen(_String)-1; + if( Start<0 ) + return false; + while( Start>0 && _String[Start-1]!='+' ) + --Start; + while( _String[Start]==' ' || _String[Start]=='\t' ) + ++Start; + char *CodeStr = _strdup(_String+Start); + for( size_t i=strlen(CodeStr)-1; i>=0; ++i ) + if( CodeStr[i]==' ' || CodeStr[i]=='\t' ) + CodeStr[i] = '\0'; + else + break; + + /* + if( strstr(_String, "SHIFT")!=NULL || strstr(_String, "shift")!=NULL ) + *_Modif |= TW_KMOD_SHIFT; + if( strstr(_String, "CTRL")!=NULL || strstr(_String, "ctrl")!=NULL ) + *_Modif |= TW_KMOD_CTRL; + if( strstr(_String, "META")!=NULL || strstr(_String, "meta")!=NULL ) + *_Modif |= TW_KMOD_META; + + if( strstr(_String, "ALTGR")!=NULL || strstr(_String, "altgr")!=NULL ) + ((void)(0)); // *_Modif |= TW_KMOD_ALTGR; + else // ALT and ALTGR are exclusive + if( strstr(_String, "ALT")!=NULL || strstr(_String, "alt")!=NULL ) + *_Modif |= TW_KMOD_ALT; + */ + char *up = _strdup(_String); + // _strupr(up); + for( char *upch=up; *upch!='\0'; ++upch ) + *upch = (char)toupper(*upch); + if( strstr(up, "SHIFT")!=NULL ) + *_Modif |= TW_KMOD_SHIFT; + if( strstr(up, "CTRL")!=NULL ) + *_Modif |= TW_KMOD_CTRL; + if( strstr(up, "META")!=NULL ) + *_Modif |= TW_KMOD_META; + + if( strstr(up, "ALTGR")!=NULL ) + ((void)(0)); // *_Modif |= TW_KMOD_ALTGR; + else // ALT and ALTGR are exclusive + if( strstr(up, "ALT")!=NULL ) + *_Modif |= TW_KMOD_ALT; + free(up); + + if( strlen(CodeStr)==1 ) + *_Code = (unsigned char)(CodeStr[0]); + else if( _stricmp(CodeStr, "backspace")==0 || _stricmp(CodeStr, "bs")==0 ) + *_Code = TW_KEY_BACKSPACE; + else if( _stricmp(CodeStr, "tab")==0 ) + *_Code = TW_KEY_TAB; + else if( _stricmp(CodeStr, "clear")==0 || _stricmp(CodeStr, "clr")==0 ) + *_Code = TW_KEY_CLEAR; + else if( _stricmp(CodeStr, "return")==0 || _stricmp(CodeStr, "ret")==0 ) + *_Code = TW_KEY_RETURN; + else if( _stricmp(CodeStr, "pause")==0 ) + *_Code = TW_KEY_PAUSE; + else if( _stricmp(CodeStr, "escape")==0 || _stricmp(CodeStr, "esc")==0 ) + *_Code = TW_KEY_ESCAPE; + else if( _stricmp(CodeStr, "space")==0 ) + *_Code = TW_KEY_SPACE; + else if( _stricmp(CodeStr, "delete")==0 || _stricmp(CodeStr, "del")==0 ) + *_Code = TW_KEY_DELETE; + /* + else if( strlen(CodeStr)==4 && CodeStr[3]>='0' && CodeStr[3]<='9' && (strstr(CodeStr, "pad")==CodeStr || strstr(CodeStr, "PAD")==CodeStr) ) + *_Code = TW_KEY_PAD_0 + CodeStr[3]-'0'; + else if( _stricmp(CodeStr, "pad.")==0 ) + *_Code = TW_KEY_PAD_PERIOD; + else if( _stricmp(CodeStr, "pad/")==0 ) + *_Code = TW_KEY_PAD_DIVIDE; + else if( _stricmp(CodeStr, "pad*")==0 ) + *_Code = TW_KEY_PAD_MULTIPLY; + else if( _stricmp(CodeStr, "pad+")==0 ) + *_Code = TW_KEY_PAD_PLUS; + else if( _stricmp(CodeStr, "pad-")==0 ) + *_Code = TW_KEY_PAD_MINUS; + else if( _stricmp(CodeStr, "padenter")==0 ) + *_Code = TW_KEY_PAD_ENTER; + else if( _stricmp(CodeStr, "pad=")==0 ) + *_Code = TW_KEY_PAD_EQUALS; + */ + else if( _stricmp(CodeStr, "up")==0 ) + *_Code = TW_KEY_UP; + else if( _stricmp(CodeStr, "down")==0 ) + *_Code = TW_KEY_DOWN; + else if( _stricmp(CodeStr, "right")==0 ) + *_Code = TW_KEY_RIGHT; + else if( _stricmp(CodeStr, "left")==0 ) + *_Code = TW_KEY_LEFT; + else if( _stricmp(CodeStr, "insert")==0 || _stricmp(CodeStr, "ins")==0 ) + *_Code = TW_KEY_INSERT; + else if( _stricmp(CodeStr, "home")==0 ) + *_Code = TW_KEY_HOME; + else if( _stricmp(CodeStr, "end")==0 ) + *_Code = TW_KEY_END; + else if( _stricmp(CodeStr, "pgup")==0 ) + *_Code = TW_KEY_PAGE_UP; + else if( _stricmp(CodeStr, "pgdown")==0 ) + *_Code = TW_KEY_PAGE_DOWN; + else if( (strlen(CodeStr)==2 || strlen(CodeStr)==3) && (CodeStr[0]=='f' || CodeStr[0]=='F') ) + { + int n = 0; + if( sscanf(CodeStr+1, "%d", &n)==1 && n>0 && n<16 ) + *_Code = TW_KEY_F1 + n-1; + else + Ok = false; + } + + free(CodeStr); + return Ok; +} + +bool TwGetKeyString(std::string *_String, int _Code, int _Modif) +{ + assert(_String!=NULL); + bool Ok = true; + if( _Modif & TW_KMOD_SHIFT ) + *_String += "SHIFT+"; + if( _Modif & TW_KMOD_CTRL ) + *_String += "CTRL+"; + if ( _Modif & TW_KMOD_ALT ) + *_String += "ALT+"; + if ( _Modif & TW_KMOD_META ) + *_String += "META+"; + // if ( _Modif & TW_KMOD_ALTGR ) + // *_String += "ALTGR+"; + switch( _Code ) + { + case TW_KEY_BACKSPACE: + *_String += "BackSpace"; + break; + case TW_KEY_TAB: + *_String += "Tab"; + break; + case TW_KEY_CLEAR: + *_String += "Clear"; + break; + case TW_KEY_RETURN: + *_String += "Return"; + break; + case TW_KEY_PAUSE: + *_String += "Pause"; + break; + case TW_KEY_ESCAPE: + *_String += "Esc"; + break; + case TW_KEY_SPACE: + *_String += "Space"; + break; + case TW_KEY_DELETE: + *_String += "Delete"; + break; + /* + case TW_KEY_PAD_0: + *_String += "PAD0"; + break; + case TW_KEY_PAD_1: + *_String += "PAD1"; + break; + case TW_KEY_PAD_2: + *_String += "PAD2"; + break; + case TW_KEY_PAD_3: + *_String += "PAD3"; + break; + case TW_KEY_PAD_4: + *_String += "PAD4"; + break; + case TW_KEY_PAD_5: + *_String += "PAD5"; + break; + case TW_KEY_PAD_6: + *_String += "PAD6"; + break; + case TW_KEY_PAD_7: + *_String += "PAD7"; + break; + case TW_KEY_PAD_8: + *_String += "PAD8"; + break; + case TW_KEY_PAD_9: + *_String += "PAD9"; + break; + case TW_KEY_PAD_PERIOD: + *_String += "PAD."; + break; + case TW_KEY_PAD_DIVIDE: + *_String += "PAD/"; + break; + case TW_KEY_PAD_MULTIPLY: + *_String += "PAD*"; + break; + case TW_KEY_PAD_MINUS: + *_String += "PAD-"; + break; + case TW_KEY_PAD_PLUS: + *_String += "PAD+"; + break; + case TW_KEY_PAD_ENTER: + *_String += "PADEnter"; + break; + case TW_KEY_PAD_EQUALS: + *_String += "PAD="; + break; + */ + case TW_KEY_UP: + *_String += "Up"; + break; + case TW_KEY_DOWN: + *_String += "Down"; + break; + case TW_KEY_RIGHT: + *_String += "Right"; + break; + case TW_KEY_LEFT: + *_String += "Left"; + break; + case TW_KEY_INSERT: + *_String += "Insert"; + break; + case TW_KEY_HOME: + *_String += "Home"; + break; + case TW_KEY_END: + *_String += "End"; + break; + case TW_KEY_PAGE_UP: + *_String += "PgUp"; + break; + case TW_KEY_PAGE_DOWN: + *_String += "PgDown"; + break; + case TW_KEY_F1: + *_String += "F1"; + break; + case TW_KEY_F2: + *_String += "F2"; + break; + case TW_KEY_F3: + *_String += "F3"; + break; + case TW_KEY_F4: + *_String += "F4"; + break; + case TW_KEY_F5: + *_String += "F5"; + break; + case TW_KEY_F6: + *_String += "F6"; + break; + case TW_KEY_F7: + *_String += "F7"; + break; + case TW_KEY_F8: + *_String += "F8"; + break; + case TW_KEY_F9: + *_String += "F9"; + break; + case TW_KEY_F10: + *_String += "F10"; + break; + case TW_KEY_F11: + *_String += "F11"; + break; + case TW_KEY_F12: + *_String += "F12"; + break; + case TW_KEY_F13: + *_String += "F13"; + break; + case TW_KEY_F14: + *_String += "F14"; + break; + case TW_KEY_F15: + *_String += "F15"; + break; + default: + if( _Code>0 && _Code<256 ) + *_String += char(_Code); + else + { + *_String += "Unknown"; + Ok = false; + } + } + return Ok; +} + +// --------------------------------------------------------------------------- + +const int TW_MOUSE_NOMOTION = -1; +ETwMouseAction TW_MOUSE_MOTION = (ETwMouseAction)(-2); +ETwMouseAction TW_MOUSE_WHEEL = (ETwMouseAction)(-3); +ETwMouseButtonID TW_MOUSE_NA = (ETwMouseButtonID)(-1); + +static int TwMouseEvent(ETwMouseAction _EventType, TwMouseButtonID _Button, int _MouseX, int _MouseY, int _WheelPos) +{ + CTwFPU fpu; // force fpu precision + + if( g_TwMgr==NULL || g_TwMgr->m_Graph==NULL ) + { + // TwGlobalError(g_ErrNotInit); -> not an error here + return 0; // not initialized + } + if( g_TwMgr->m_WndHeight<=0 || g_TwMgr->m_WndWidth<=0 ) + { + //g_TwMgr->SetLastError(g_ErrBadWndSize); // not an error, windows not yet ready. + return 0; + } + + if( _MouseX==TW_MOUSE_NOMOTION ) + _MouseX = g_TwMgr->m_LastMouseX; + else + g_TwMgr->m_LastMouseX = _MouseX; + if( _MouseY==TW_MOUSE_NOMOTION ) + _MouseY = g_TwMgr->m_LastMouseY; + else + g_TwMgr->m_LastMouseY = _MouseY; + + // for autorepeat + if( (!g_TwMgr->m_IsRepeatingMousePressed || !g_TwMgr->m_CanRepeatMousePressed) && _EventType==TW_MOUSE_PRESSED ) + { + g_TwMgr->m_LastMousePressedTime = g_TwMgr->m_Timer.GetTime(); + g_TwMgr->m_LastMousePressedButtonID = _Button; + g_TwMgr->m_LastMousePressedPosition[0] = _MouseX; + g_TwMgr->m_LastMousePressedPosition[1] = _MouseY; + g_TwMgr->m_CanRepeatMousePressed = true; + g_TwMgr->m_IsRepeatingMousePressed = false; + } + else if( _EventType==TW_MOUSE_RELEASED || _EventType==TW_MOUSE_WHEEL ) + { + g_TwMgr->m_CanRepeatMousePressed = false; + g_TwMgr->m_IsRepeatingMousePressed = false; + } + + bool Handled = false; + bool wasPopup = (g_TwMgr->m_PopupBar!=NULL); + CTwBar *Bar = NULL; + int i; + for( i=((int)g_TwMgr->m_Bars.size())-1; i>=0; --i ) + { + Bar = g_TwMgr->m_Bars[g_TwMgr->m_Order[i]]; + if( Bar!=NULL && Bar->m_Visible ) + { + if( _EventType==TW_MOUSE_MOTION ) + Handled = Bar->MouseMotion(_MouseX, _MouseY); + else if( _EventType==TW_MOUSE_PRESSED || _EventType==TW_MOUSE_RELEASED ) + Handled = Bar->MouseButton(_Button, (_EventType==TW_MOUSE_PRESSED), _MouseX, _MouseY); + else if( _EventType==TW_MOUSE_WHEEL ) + { + if( abs(_WheelPos-g_TwMgr->m_LastMouseWheelPos)<4 ) // avoid crazy wheel positions + Handled = Bar->MouseWheel(_WheelPos, g_TwMgr->m_LastMouseWheelPos, _MouseX, _MouseY); + } + if( Handled ) + break; + } + } + + /* + if( i>=0 && Bar!=NULL && Handled && (_EventType==TW_MOUSE_PRESSED || Bar->IsMinimized()) && i!=((int)g_TwMgr->m_Bars.size())-1 ) + { + int iOrder = g_TwMgr->m_Order[i]; + for( int j=i; j<(int)g_TwMgr->m_Bars.size()-1; ++j ) + g_TwMgr->m_Order[j] = g_TwMgr->m_Order[j+1]; + g_TwMgr->m_Order[(int)g_TwMgr->m_Bars.size()-1] = iOrder; + } + */ + if( _EventType==TW_MOUSE_PRESSED || (Bar!=NULL && Bar->IsMinimized() && Handled) ) + { + if( wasPopup && Bar!=g_TwMgr->m_PopupBar && g_TwMgr->m_PopupBar!=NULL ) // delete popup + { + TwDeleteBar(g_TwMgr->m_PopupBar); + g_TwMgr->m_PopupBar = NULL; + } + + if( i>=0 && Bar!=NULL && Handled && !wasPopup ) + TwSetTopBar(Bar); + } + + if( _EventType==TW_MOUSE_WHEEL ) + g_TwMgr->m_LastMouseWheelPos = _WheelPos; + + return Handled ? 1 : 0; +} + +int ANT_CALL TwMouseButton(ETwMouseAction _EventType, TwMouseButtonID _Button) +{ + return TwMouseEvent(_EventType, _Button, TW_MOUSE_NOMOTION, TW_MOUSE_NOMOTION, 0); +} + +int ANT_CALL TwMouseMotion(int _MouseX, int _MouseY) +{ + return TwMouseEvent(TW_MOUSE_MOTION, TW_MOUSE_NA, _MouseX, _MouseY, 0); +} + +int ANT_CALL TwMouseWheel(int _Pos) +{ + return TwMouseEvent(TW_MOUSE_WHEEL, TW_MOUSE_NA, TW_MOUSE_NOMOTION, TW_MOUSE_NOMOTION, _Pos); +} + +// --------------------------------------------------------------------------- + +static int TranslateKey(int _Key, int _Modifiers) +{ + // CTRL special cases +// if( (_Modifiers&TW_KMOD_CTRL) && !(_Modifiers&TW_KMOD_ALT || _Modifiers&TW_KMOD_META) && _Key>0 && _Key<32 ) +// _Key += 'a'-1; + if( (_Modifiers&TW_KMOD_CTRL) ) + { + if( _Key>='a' && _Key<='z' && ( ((_Modifiers&0x2000) && !(_Modifiers&TW_KMOD_SHIFT)) || (!(_Modifiers&0x2000) && (_Modifiers&TW_KMOD_SHIFT)) )) // 0x2000 is SDL's KMOD_CAPS + _Key += 'A'-'a'; + else if ( _Key>='A' && _Key<='Z' && ( ((_Modifiers&0x2000) && (_Modifiers&TW_KMOD_SHIFT)) || (!(_Modifiers&0x2000) && !(_Modifiers&TW_KMOD_SHIFT)) )) // 0x2000 is SDL's KMOD_CAPS + _Key += 'a'-'A'; + } + + // PAD translation (for SDL keysym) + if( _Key>=256 && _Key<=272 ) // 256=SDLK_KP0 ... 272=SDLK_KP_EQUALS + { + //bool Num = ((_Modifiers&TW_KMOD_SHIFT) && !(_Modifiers&0x1000)) || (!(_Modifiers&TW_KMOD_SHIFT) && (_Modifiers&0x1000)); // 0x1000 is SDL's KMOD_NUM + //_Modifiers &= ~TW_KMOD_SHIFT; // remove shift modifier + bool Num = (!(_Modifiers&TW_KMOD_SHIFT) && (_Modifiers&0x1000)); // 0x1000 is SDL's KMOD_NUM + if( _Key==266 ) // SDLK_KP_PERIOD + _Key = Num ? '.' : TW_KEY_DELETE; + else if( _Key==267 ) // SDLK_KP_DIVIDE + _Key = '/'; + else if( _Key==268 ) // SDLK_KP_MULTIPLY + _Key = '*'; + else if( _Key==269 ) // SDLK_KP_MINUS + _Key = '-'; + else if( _Key==270 ) // SDLK_KP_PLUS + _Key = '+'; + else if( _Key==271 ) // SDLK_KP_ENTER + _Key = TW_KEY_RETURN; + else if( _Key==272 ) // SDLK_KP_EQUALS + _Key = '='; + else if( Num ) // num SDLK_KP0..9 + _Key += '0' - 256; + else if( _Key==256 ) // non-num SDLK_KP01 + _Key = TW_KEY_INSERT; + else if( _Key==257 ) // non-num SDLK_KP1 + _Key = TW_KEY_END; + else if( _Key==258 ) // non-num SDLK_KP2 + _Key = TW_KEY_DOWN; + else if( _Key==259 ) // non-num SDLK_KP3 + _Key = TW_KEY_PAGE_DOWN; + else if( _Key==260 ) // non-num SDLK_KP4 + _Key = TW_KEY_LEFT; + else if( _Key==262 ) // non-num SDLK_KP6 + _Key = TW_KEY_RIGHT; + else if( _Key==263 ) // non-num SDLK_KP7 + _Key = TW_KEY_HOME; + else if( _Key==264 ) // non-num SDLK_KP8 + _Key = TW_KEY_UP; + else if( _Key==265 ) // non-num SDLK_KP9 + _Key = TW_KEY_PAGE_UP; + } + return _Key; +} + +// --------------------------------------------------------------------------- + +int ANT_CALL TwKeyPressed(int _Key, int _Modifiers) +{ + CTwFPU fpu; // force fpu precision + + if( g_TwMgr==NULL || g_TwMgr->m_Graph==NULL ) + { + // TwGlobalError(g_ErrNotInit); -> not an error here + return 0; // not initialized + } + if( g_TwMgr->m_WndHeight<=0 || g_TwMgr->m_WndWidth<=0 ) + { + //g_TwMgr->SetLastError(g_ErrBadWndSize); // not an error, windows not yet ready. + return 0; + } + + /* + // Test for TwDeleteBar + if( _Key>='0' && _Key<='9' ) + { + int n = _Key-'0'; + if( (int)g_TwMgr->m_Bars.size()>n && g_TwMgr->m_Bars[n]!=NULL ) + { + printf("Delete %s\n", g_TwMgr->m_Bars[n]->m_Name.c_str()); + TwDeleteBar(g_TwMgr->m_Bars[n]); + } + else + printf("can't delete %d\n", n); + return 1; + } + */ + + //char s[256]; + //sprintf(s, "twkeypressed k=%d m=%x\n", _Key, _Modifiers); + //OutputDebugString(s); + + _Key = TranslateKey(_Key, _Modifiers); + if( _Key>' ' && _Key<256 ) // don't test SHIFT if _Key is a common key + _Modifiers &= ~TW_KMOD_SHIFT; + // complete partial modifiers comming from SDL + if( _Modifiers & TW_KMOD_SHIFT ) + _Modifiers |= TW_KMOD_SHIFT; + if( _Modifiers & TW_KMOD_CTRL ) + _Modifiers |= TW_KMOD_CTRL; + if( _Modifiers & TW_KMOD_ALT ) + _Modifiers |= TW_KMOD_ALT; + if( _Modifiers & TW_KMOD_META ) + _Modifiers |= TW_KMOD_META; + + bool Handled = false; + CTwBar *Bar = NULL; + //int Order = 0; + int i; + if( _Key>0 && _Keym_LastMouseX; + int MouseY = g_TwMgr->m_LastMouseY; + for( i=((int)g_TwMgr->m_Bars.size())-1; i>=0 && !Handled; --i ) + { + Bar = g_TwMgr->m_Bars[g_TwMgr->m_Order[i]]; + if( Bar!=NULL && Bar->m_Visible && !Bar->IsMinimized() && MouseX>=Bar->m_PosX && MouseXm_PosX+Bar->m_Width && MouseY>=Bar->m_PosY && MouseYm_PosY+Bar->m_Height ) + Handled = Bar->KeyPressed(_Key, _Modifiers); + } + + // If not handled, send it to non-iconified bars in the right order + for( i=((int)g_TwMgr->m_Bars.size())-1; i>=0 && !Handled; --i ) + { + Bar = g_TwMgr->m_Bars[g_TwMgr->m_Order[i]]; + /* + for( size_t j=0; jm_Bars.size(); ++j ) + if( g_TwMgr->m_Order[j]==i ) + { + Bar = g_TwMgr->m_Bars[j]; + break; + } + Order = i; + */ + + if( Bar!=NULL && Bar->m_Visible && !Bar->IsMinimized() ) + Handled = Bar->KeyPressed(_Key, _Modifiers); + } + + // If not handled, send it to iconified bars in the right order + for( i=((int)g_TwMgr->m_Bars.size())-1; i>=0 && !Handled; --i ) + { + Bar = g_TwMgr->m_Bars[g_TwMgr->m_Order[i]]; + if( Bar!=NULL && Bar->m_Visible && Bar->IsMinimized() ) + Handled = Bar->KeyPressed(_Key, _Modifiers); + } + + if( g_TwMgr->m_HelpBar!=NULL && g_TwMgr->m_Graph ) + { + string Str; + TwGetKeyString(&Str, _Key, _Modifiers); + char Msg[256]; + sprintf(Msg, "Key pressed: %s", Str.c_str()); + g_TwMgr->m_KeyPressedStr = Msg; + g_TwMgr->m_KeyPressedBuildText = true; + // OutputDebugString(Msg); + } + } + + if( Handled && Bar!=g_TwMgr->m_PopupBar && g_TwMgr->m_PopupBar!=NULL ) // delete popup + { + TwDeleteBar(g_TwMgr->m_PopupBar); + g_TwMgr->m_PopupBar = NULL; + } + + if( Handled && Bar!=NULL && Bar!=g_TwMgr->m_PopupBar ) + TwSetTopBar(Bar); + + return Handled ? 1 : 0; +} + +// --------------------------------------------------------------------------- + +struct StructCompare : public binary_function +{ + bool operator()(const TwType& _Left, const TwType& _Right) const + { + assert( g_TwMgr!=NULL ); + int i0 = _Left-TW_TYPE_STRUCT_BASE; + int i1 = _Right-TW_TYPE_STRUCT_BASE; + if( i0>=0 && i0<(int)g_TwMgr->m_Structs.size() && i1>=0 && i1<(int)g_TwMgr->m_Structs.size() ) + return g_TwMgr->m_Structs[i0].m_Name < g_TwMgr->m_Structs[i1].m_Name; + else + return false; + } +}; + +typedef set StructSet; + +static void InsertUsedStructs(StructSet& _Set, const CTwVarGroup *_Grp) +{ + assert( g_TwMgr!=NULL && _Grp!=NULL ); + + for( size_t i=0; i<_Grp->m_Vars.size(); ++i ) + if( _Grp->m_Vars[i]!=NULL && _Grp->m_Vars[i]->m_Visible && _Grp->m_Vars[i]->IsGroup() ) + { + const CTwVarGroup *SubGrp = static_cast(_Grp->m_Vars[i]); + if( SubGrp->m_StructValuePtr!=NULL && SubGrp->m_StructType>=TW_TYPE_STRUCT_BASE && SubGrp->m_StructTypem_Structs.size() && g_TwMgr->m_Structs[SubGrp->m_StructType-TW_TYPE_STRUCT_BASE].m_Name.length()>0 ) + _Set.insert(SubGrp->m_StructType); + InsertUsedStructs(_Set, SubGrp); + } +} + +static void SplitString(vector& _OutSplits, const char *_String, int _Width, const CTexFont *_Font) +{ + assert( _Font!=NULL && _String!=NULL ); + _OutSplits.resize(0); + int l = (int)strlen(_String); + if( l==0 ) + { + _String = " "; + l = 1; + } + + if( _String!=NULL && l>0 && _Width>0 ) + { + int w = 0; + int i = 0; + int First = 0; + int Last = 0; + bool PrevNotBlank = true; + unsigned char c; + bool Tab = false, CR = false; + string Split; + const string TabString(g_TabLength, ' '); + + while( im_CharWidth[(int)' ']; + Tab = true; + } + else if( c=='\n' ) + { + w += _Width+1; // force split + Last = i; + CR = true; + } + else + w += _Font->m_CharWidth[(int)c]; + if( w>_Width || i==l-1 ) + { + if( Last<=First || i==l-1 ) + Last = i; + if( Tab ) + { + Split.resize(0); + for(int k=0; km_HelpBar!=NULL); + assert( _String!=NULL ); + int n = 0; + const CTexFont *Font = g_TwMgr->m_HelpBar->m_Font; + assert(Font!=NULL); + string Decal; + for( int s=0; s<_Level; ++s ) + Decal += ' '; + int DecalWidth = (_Level+2)*Font->m_CharWidth[(int)' ']; + + if( _Width>DecalWidth ) + { + vector Split; + SplitString(Split, _String, _Width-DecalWidth, Font); + for( int i=0; i<(int)Split.size(); ++i ) + { + CTwVarAtom *Var = new CTwVarAtom; + Var->m_Name = Decal + Split[i]; + Var->m_Ptr = NULL; + if( _Type==TW_TYPE_HELP_HEADER ) + Var->m_ReadOnly = false; + else + Var->m_ReadOnly = true; + Var->m_NoSlider = true; + Var->m_DontClip = true; + Var->m_Type = _Type; + Var->m_LeftMargin = (signed short)(_Level*Font->m_CharWidth[(int)' ']); + Var->m_TopMargin = (signed short)(-g_TwMgr->m_HelpBar->m_Sep); + //Var->m_TopMargin = 1; + Var->m_Color = g_TwMgr->m_HelpBar->m_ColHelpText; + Var->SetDefaults(); + _Grp->m_Vars.push_back(Var); + ++n; + } + } + return n; +} + +static int AppendHelp(CTwVarGroup *_Grp, const CTwVarGroup *_ToAppend, int _Level, int _Width) +{ + assert( _Grp!=NULL ); + assert( _ToAppend!=NULL ); + int n = 0; + string Decal; + for( int s=0; s<_Level; ++s ) + Decal += ' '; + + if( _ToAppend->m_Help.size()>0 ) + n += AppendHelpString(_Grp, _ToAppend->m_Help.c_str(), _Level, _Width, TW_TYPE_HELP_GRP); + + for( size_t i=0; i<_ToAppend->m_Vars.size(); ++i ) + if( _ToAppend->m_Vars[i]!=NULL && _ToAppend->m_Vars[i]->m_Visible ) + { + CTwVarAtom *Var = new CTwVarAtom; + Var->m_Name = Decal; + if( _ToAppend->m_Vars[i]->m_Label.size()>0 ) + Var->m_Name += _ToAppend->m_Vars[i]->m_Label; + else + Var->m_Name += _ToAppend->m_Vars[i]->m_Name; + Var->m_Ptr = NULL; + if( _ToAppend->m_Vars[i]->IsGroup() && static_cast(_ToAppend->m_Vars[i])->m_StructValuePtr!=NULL ) + { // That's a struct var + Var->m_Type = TW_TYPE_HELP_STRUCT; + Var->m_Val.m_HelpStruct.m_StructType = static_cast(_ToAppend->m_Vars[i])->m_StructType; + Var->m_ReadOnly = true; + Var->m_NoSlider = true; + } + else if( !_ToAppend->m_Vars[i]->IsGroup() ) + { + Var->m_Type = TW_TYPE_SHORTCUT; + Var->m_Val.m_Shortcut.m_Incr[0] = static_cast(_ToAppend->m_Vars[i])->m_KeyIncr[0]; + Var->m_Val.m_Shortcut.m_Incr[1] = static_cast(_ToAppend->m_Vars[i])->m_KeyIncr[1]; + Var->m_Val.m_Shortcut.m_Decr[0] = static_cast(_ToAppend->m_Vars[i])->m_KeyDecr[0]; + Var->m_Val.m_Shortcut.m_Decr[1] = static_cast(_ToAppend->m_Vars[i])->m_KeyDecr[1]; + Var->m_ReadOnly = static_cast(_ToAppend->m_Vars[i])->m_ReadOnly; + Var->m_NoSlider = true; + } + else + { + Var->m_Type = TW_TYPE_HELP_GRP; + Var->m_DontClip = true; + Var->m_LeftMargin = (signed short)((_Level+1)*g_TwMgr->m_HelpBar->m_Font->m_CharWidth[(int)' ']); + //Var->m_TopMargin = (signed short)(g_TwMgr->m_HelpBar->m_Font->m_CharHeight/2-2+2*(_Level-1)); + Var->m_TopMargin = 2; + if( Var->m_TopMargin>g_TwMgr->m_HelpBar->m_Font->m_CharHeight-3 ) + Var->m_TopMargin = (signed short)(g_TwMgr->m_HelpBar->m_Font->m_CharHeight-3); + Var->m_ReadOnly = true; + } + Var->SetDefaults(); + _Grp->m_Vars.push_back(Var); + ++n; + if( _ToAppend->m_Vars[i]->IsGroup() && static_cast(_ToAppend->m_Vars[i])->m_StructValuePtr==NULL ) + n += AppendHelp(_Grp, static_cast(_ToAppend->m_Vars[i]), _Level+1, _Width); + else if( _ToAppend->m_Vars[i]->m_Help.length()>0 ) + n += AppendHelpString(_Grp, _ToAppend->m_Vars[i]->m_Help.c_str(), _Level+1, _Width, TW_TYPE_HELP_ATOM); + } + return n; +} + + +static void CopyHierarchy(CTwVarGroup *dst, const CTwVarGroup *src) +{ + if( dst==NULL || src==NULL ) + return; + + dst->m_Name = src->m_Name; + dst->m_Open = src->m_Open; + dst->m_Visible = src->m_Visible; + dst->m_Color = src->m_Color; + dst->m_DontClip = src->m_DontClip; + dst->m_IsRoot = src->m_IsRoot; + dst->m_LeftMargin = src->m_LeftMargin; + dst->m_TopMargin = src->m_TopMargin; + + dst->m_Vars.resize(src->m_Vars.size()); + for(size_t i=0; im_Vars.size(); ++i) + if( src->m_Vars[i]!=NULL && src->m_Vars[i]->IsGroup() ) + { + CTwVarGroup *grp = new CTwVarGroup; + CopyHierarchy(grp, static_cast(src->m_Vars[i])); + dst->m_Vars[i] = grp; + } + else + dst->m_Vars[i] = NULL; +} + +// copy the 'open' flag from original hierarchy to current hierarchy +static void SynchroHierarchy(CTwVarGroup *cur, const CTwVarGroup *orig) +{ + if( cur==NULL || orig==NULL ) + return; + + if( strcmp(cur->m_Name.c_str(), orig->m_Name.c_str())==0 ) + cur->m_Open = orig->m_Open; + + size_t j = 0; + while( jm_Vars.size() && (orig->m_Vars[j]==NULL || !orig->m_Vars[j]->IsGroup()) ) + ++j; + + for(size_t i=0; im_Vars.size(); ++i) + if( cur->m_Vars[i]!=NULL && cur->m_Vars[i]->IsGroup() && jm_Vars.size() && orig->m_Vars[j]!=NULL && orig->m_Vars[j]->IsGroup() ) + { + CTwVarGroup *curGrp = static_cast(cur->m_Vars[i]); + const CTwVarGroup *origGrp = static_cast(orig->m_Vars[j]); + if( strcmp(curGrp->m_Name.c_str(), origGrp->m_Name.c_str())==0 ) + { + curGrp->m_Open = origGrp->m_Open; + + SynchroHierarchy(curGrp, origGrp); + + ++j; + while( jm_Vars.size() && (orig->m_Vars[j]==NULL || !orig->m_Vars[j]->IsGroup()) ) + ++j; + } + } +} + + +void CTwMgr::UpdateHelpBar() +{ + if( m_HelpBar==NULL || m_HelpBar->IsMinimized() ) + return; + if( !m_HelpBarUpdateNow && (float)m_Timer.GetTime()m_VarRoot); + + TwRemoveAllVars(m_HelpBar); + + if( m_HelpBar->m_UpToDate ) + m_HelpBar->Update(); + + if( m_Help.size()>0 ) + AppendHelpString(&(m_HelpBar->m_VarRoot), m_Help.c_str(), 0, m_HelpBar->m_VarX2-m_HelpBar->m_VarX0, TW_TYPE_HELP_ATOM); + if( m_HelpBar->m_Help.size()>0 ) + AppendHelpString(&(m_HelpBar->m_VarRoot), m_HelpBar->m_Help.c_str(), 0, m_HelpBar->m_VarX2-m_HelpBar->m_VarX0, TW_TYPE_HELP_ATOM); + AppendHelpString(&(m_HelpBar->m_VarRoot), "", 0, m_HelpBar->m_VarX2-m_HelpBar->m_VarX0, TW_TYPE_HELP_HEADER); + + for( size_t ib=0; ibm_IsHelpBar) && m_Bars[ib]!=m_PopupBar && m_Bars[ib]->m_Visible ) + { + // Create a group + CTwVarGroup *Grp = new CTwVarGroup; + Grp->m_SummaryCallback = NULL; + Grp->m_SummaryClientData = NULL; + Grp->m_StructValuePtr = NULL; + if( m_Bars[ib]->m_Label.size()<=0 ) + Grp->m_Name = m_Bars[ib]->m_Name; + else + Grp->m_Name = m_Bars[ib]->m_Label; + Grp->m_Open = true; + Grp->m_Color = m_HelpBar->m_ColGrpText; + m_HelpBar->m_VarRoot.m_Vars.push_back(Grp); + if( m_Bars[ib]->m_Help.size()>0 ) + AppendHelpString(Grp, m_Bars[ib]->m_Help.c_str(), 0, m_HelpBar->m_VarX2-m_HelpBar->m_VarX0, TW_TYPE_HELP_GRP); + + // Append variables (recursive) + AppendHelp(Grp, &(m_Bars[ib]->m_VarRoot), 1, m_HelpBar->m_VarX2-m_HelpBar->m_VarX0); + + // Append structures + StructSet UsedStructs; + InsertUsedStructs(UsedStructs, &(m_Bars[ib]->m_VarRoot)); + CTwVarGroup *StructGrp = NULL; + for( StructSet::iterator it=UsedStructs.begin(); it!=UsedStructs.end(); ++it ) + { + int idx = (*it) - TW_TYPE_STRUCT_BASE; + if( idx>=0 && idx<(int)g_TwMgr->m_Structs.size() && g_TwMgr->m_Structs[idx].m_Name.length()>0 ) + { + if( StructGrp==NULL ) + { + StructGrp = new CTwVarGroup; + StructGrp->m_StructType = TW_TYPE_HELP_STRUCT; // a special line background color will be used + StructGrp->m_Name = "Structures"; + StructGrp->m_Open = false; + StructGrp->m_Color = m_HelpBar->m_ColStructText; + Grp->m_Vars.push_back(StructGrp); + } + CTwVarAtom *Var = new CTwVarAtom; + Var->m_Ptr = NULL; + Var->m_Type = TW_TYPE_HELP_GRP; + Var->m_DontClip = true; + Var->m_LeftMargin = (signed short)(2*g_TwMgr->m_HelpBar->m_Font->m_CharWidth[(int)' ']); + Var->m_TopMargin = 2; + Var->m_ReadOnly = true; + Var->m_NoSlider = true; + Var->m_Name = '{'+g_TwMgr->m_Structs[idx].m_Name+'}'; + StructGrp->m_Vars.push_back(Var); + if( g_TwMgr->m_Structs[idx].m_Help.size()>0 ) + AppendHelpString(StructGrp, g_TwMgr->m_Structs[idx].m_Help.c_str(), 2, m_HelpBar->m_VarX2-m_HelpBar->m_VarX0-2*Var->m_LeftMargin, TW_TYPE_HELP_GRP); + + // Append struct members + for( size_t im=0; imm_Structs[idx].m_Members.size(); ++im ) + { + CTwVarAtom *Var = new CTwVarAtom; + Var->m_Ptr = NULL; + Var->m_Type = TW_TYPE_SHORTCUT; + Var->m_Val.m_Shortcut.m_Incr[0] = 0; + Var->m_Val.m_Shortcut.m_Incr[1] = 0; + Var->m_Val.m_Shortcut.m_Decr[0] = 0; + Var->m_Val.m_Shortcut.m_Decr[1] = 0; + Var->m_ReadOnly = false; + Var->m_NoSlider = true; + if( g_TwMgr->m_Structs[idx].m_Members[im].m_Label.length()>0 ) + Var->m_Name = " "+g_TwMgr->m_Structs[idx].m_Members[im].m_Label; + else + Var->m_Name = " "+g_TwMgr->m_Structs[idx].m_Members[im].m_Name; + StructGrp->m_Vars.push_back(Var); + if( g_TwMgr->m_Structs[idx].m_Members[im].m_Help.size()>0 ) + AppendHelpString(StructGrp, g_TwMgr->m_Structs[idx].m_Members[im].m_Help.c_str(), 3, m_HelpBar->m_VarX2-m_HelpBar->m_VarX0-4*Var->m_LeftMargin, TW_TYPE_HELP_ATOM); + } + } + } + } + + // Append RotoSlider + CTwVarGroup *RotoGrp = new CTwVarGroup; + RotoGrp->m_SummaryCallback = NULL; + RotoGrp->m_SummaryClientData = NULL; + RotoGrp->m_StructValuePtr = NULL; + RotoGrp->m_Name = "RotoSlider"; + RotoGrp->m_Open = false; + RotoGrp->m_Color = m_HelpBar->m_ColGrpText; + m_HelpBar->m_VarRoot.m_Vars.push_back(RotoGrp); + AppendHelpString(RotoGrp, "The RotoSlider allows rapid editing of numerical values.", 0, m_HelpBar->m_VarX2-m_HelpBar->m_VarX0, TW_TYPE_HELP_ATOM); + AppendHelpString(RotoGrp, "To modify a numerical value, click on it, then move the mouse outside of the grey circle while keeping the mouse button pressed, and turn around the circle to increase or decrease the numerical value.", 0, m_HelpBar->m_VarX2-m_HelpBar->m_VarX0, TW_TYPE_HELP_ATOM); + AppendHelpString(RotoGrp, "The two grey lines depict the min and max bounds.", 0, m_HelpBar->m_VarX2-m_HelpBar->m_VarX0, TW_TYPE_HELP_ATOM); + AppendHelpString(RotoGrp, "Moving the mouse far form the circle allows precise increase or decrease, while moving near the circle allows fast increase or decrease.", 0, m_HelpBar->m_VarX2-m_HelpBar->m_VarX0, TW_TYPE_HELP_ATOM); + + SynchroHierarchy(&m_HelpBar->m_VarRoot, &prevHierarchy); + + m_HelpBarNotUpToDate = false; +} + +// --------------------------------------------------------------------------- + +#if defined(ANT_WINDOWS) + +void CTwMgr::CreateCursors() +{ + if( m_CursorsCreated ) + return; + m_CursorArrow = ::LoadCursor(NULL ,MAKEINTRESOURCE(IDC_ARROW)); + m_CursorMove = ::LoadCursor(NULL ,MAKEINTRESOURCE(IDC_SIZEALL)); + m_CursorWE = ::LoadCursor(NULL ,MAKEINTRESOURCE(IDC_SIZEWE)); + m_CursorNS = ::LoadCursor(NULL ,MAKEINTRESOURCE(IDC_SIZENS)); + m_CursorTopRight = ::LoadCursor(NULL ,MAKEINTRESOURCE(IDC_SIZENESW)); + m_CursorTopLeft = ::LoadCursor(NULL ,MAKEINTRESOURCE(IDC_SIZENWSE)); + m_CursorBottomLeft = ::LoadCursor(NULL ,MAKEINTRESOURCE(IDC_SIZENESW)); + m_CursorBottomRight = ::LoadCursor(NULL ,MAKEINTRESOURCE(IDC_SIZENWSE)); + m_CursorHelp = ::LoadCursor(NULL ,MAKEINTRESOURCE(IDC_HELP)); + m_CursorCross = ::LoadCursor(NULL ,MAKEINTRESOURCE(IDC_CROSS)); + m_CursorUpArrow = ::LoadCursor(NULL ,MAKEINTRESOURCE(IDC_UPARROW)); + m_CursorNo = ::LoadCursor(NULL ,MAKEINTRESOURCE(IDC_NO)); + #ifdef IDC_HAND + m_CursorHand = ::LoadCursor(NULL ,MAKEINTRESOURCE(IDC_HAND)); + #else + m_CursorHand = ::LoadCursor(NULL ,MAKEINTRESOURCE(IDC_UPARROW)); + #endif + int cur; + HMODULE hdll = GetModuleHandle(ANT_TWEAK_BAR_DLL); + m_CursorCenter = ::LoadCursor(hdll, MAKEINTRESOURCE(IDC_CURSOR1+0)); + if( m_CursorCenter==NULL ) + m_CursorCenter = ::LoadCursor(NULL ,MAKEINTRESOURCE(IDC_CROSS)); + m_CursorPoint = ::LoadCursor(hdll, MAKEINTRESOURCE(IDC_CURSOR1+1)); + if( m_CursorPoint==NULL ) + m_CursorPoint = ::LoadCursor(NULL ,MAKEINTRESOURCE(IDC_CROSS)); + + for( cur=0; curerror_code, err->request_code); + // No exit! + return 0 ; +} + +static void IgnoreXErrors() +{ + if( g_TwMgr!=NULL && g_TwMgr->m_CurrentXDisplay==glXGetCurrentDisplay() ) + { + XFlush(g_TwMgr->m_CurrentXDisplay); + XSync(g_TwMgr->m_CurrentXDisplay, False); + } + s_PrevErrorHandler = XSetErrorHandler(InactiveErrorHandler); +} + +static void RestoreXErrors() +{ + if( g_TwMgr!=NULL && g_TwMgr->m_CurrentXDisplay==glXGetCurrentDisplay() ) + { + XFlush(g_TwMgr->m_CurrentXDisplay); + XSync(g_TwMgr->m_CurrentXDisplay, False); + } + XSetErrorHandler(s_PrevErrorHandler); +} + +CTwMgr::CCursor CTwMgr::PixmapCursor(int _CurIdx) +{ + if( !m_CurrentXDisplay || !m_CurrentXWindow ) + return XC_left_ptr; + + IgnoreXErrors(); + + XColor black, white, exact; + Colormap colmap = DefaultColormap(m_CurrentXDisplay, DefaultScreen(m_CurrentXDisplay)); + Status s1 = XAllocNamedColor(m_CurrentXDisplay, colmap, "black", &black, &exact); + Status s2 = XAllocNamedColor(m_CurrentXDisplay, colmap, "white", &white, &exact); + if( s1==0 || s2==0 ) + return XC_left_ptr; // cannot allocate colors! + int x, y; + unsigned int mask[32]; + unsigned int pict[32]; + for( y=0; y<32; ++y ) + { + mask[y] = pict[y] = 0; + for( x=0; x<32; ++x ) + { + mask[y] |= (((unsigned int)(g_CurMask[_CurIdx][x+y*32]))<m_CurrentXDisplay ) + { + Window wnd = glXGetCurrentDrawable(); + if( wnd!=g_TwMgr->m_CurrentXWindow ) + { + FreeCursors(); + g_TwMgr->m_CurrentXWindow = wnd; + CreateCursors(); + // now _Cursor is not a valid cursor ID. + } + else + { + IgnoreXErrors(); + XDefineCursor(m_CurrentXDisplay, m_CurrentXWindow, _Cursor); + RestoreXErrors(); + } + } + } +} + +#endif //defined(ANT_UNIX) + +// --------------------------------------------------------------------------- diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwMgr.h b/Extras/CDTestFramework/AntTweakBar/src/TwMgr.h new file mode 100644 index 0000000..efc3023 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwMgr.h @@ -0,0 +1,309 @@ +// --------------------------------------------------------------------------- +// +// @file TwMgr.h +// @brief Tweak bar manager. +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// notes: Private header +// TAB=4 +// +// --------------------------------------------------------------------------- + + +#if !defined ANT_TW_MGR_INCLUDED +#define ANT_TW_MGR_INCLUDED + +#include +#define ANT_CALL TW_CALL + +#include "TwColors.h" +#include "TwFonts.h" +#include "TwGraph.h" +#include "AntPerfTimer.h" + + +//#define BENCH // uncomment to activate bench + +#ifdef BENCH +# define PERF(cmd) cmd +#else // BENCH +# define PERF(cmd) +#endif // BENCH + +const int NB_ROTO_CURSORS = 12; + + +// --------------------------------------------------------------------------- +// API unexposed by AntTweakBar.h +// --------------------------------------------------------------------------- + +// bar states -> use TwDefine instead +typedef enum ETwState +{ + TW_STATE_SHOWN = 1, + TW_STATE_ICONIFIED = 2, + TW_STATE_HIDDEN = 3, + TW_STATE_ERROR = 0 +} TwState; +/*ANT_TWEAK_BAR_API*/ int ANT_CALL TwSetBarState(TwBar *bar, TwState state); +/*ANT_TWEAK_BAR_API*/ TwState ANT_CALL TwGetBarState(const TwBar *bar); +// var states -> use TwDefine instead: show/hide/iconify implemented only as string commands +//ANT_TWEAK_BAR_API int ANT_CALL TwSetVarState(TwBar *bar, const char *name, TwState state); +//ANT_TWEAK_BAR_API TwState ANT_CALL TwGetVarState(const TwBar *bar, const char *name); + +typedef void (ANT_CALL *TwStructExtInitCallback)(void *structExtValue, void *clientData); +typedef void (ANT_CALL *TwCopyVarFromExtCallback)(void *structValue, const void *structExtValue, unsigned int structExtMemberIndex, void *clientData); +typedef void (ANT_CALL *TwCopyVarToExtCallback)(const void *structValue, void *structExtValue, unsigned int structExtMemberIndex, void *clientData); +/*ANT_TWEAK_BAR_API*/ TwType ANT_CALL TwDefineStructExt(const char *name, const TwStructMember *structExtMembers, unsigned int nbExtMembers, size_t structSize, size_t structExtSize, TwStructExtInitCallback structExtInitCallback, TwCopyVarFromExtCallback copyVarFromExtCallback, TwCopyVarToExtCallback copyVarToExtCallback, TwSummaryCallback summaryCallback, void *clientData); + + +// --------------------------------------------------------------------------- +// AntTweakBar Manager +// --------------------------------------------------------------------------- + +struct CTwMgr +{ + ETwGraphAPI m_GraphAPI; + void * m_Device; + class ITwGraph * m_Graph; + int m_WndWidth; + int m_WndHeight; + const CTexFont * m_CurrentFont; + + std::vector m_Bars; + std::vector m_Order; + + std::vector m_MinOccupied; + void Minimize(TwBar *_Bar); + void Maximize(TwBar *_Bar); + void Hide(TwBar *_Bar); + void Unhide(TwBar *_Bar); + void SetFont(const CTexFont *_Font, bool _ResizeBars); + int m_LastMouseX; + int m_LastMouseY; + int m_LastMouseWheelPos; + + std::string m_Help; + TwBar * m_HelpBar; + float m_LastHelpUpdateTime; + void UpdateHelpBar(); + bool m_HelpBarNotUpToDate; + bool m_HelpBarUpdateNow; + void * m_KeyPressedTextObj; + bool m_KeyPressedBuildText; + std::string m_KeyPressedStr; + float m_KeyPressedTime; + void * m_InfoTextObj; + bool m_InfoBuildText; + int m_BarInitColorHue; + int FindBar(const char *_Name) const; + int HasAttrib(const char *_Attrib, bool *_HasValue) const; + int SetAttrib(int _AttribID, const char *_Value); + void SetLastError(const char *_StaticErrorMesssage); // _StaticErrorMesssage must be a static string + const char * GetLastError(); // returns a static string describing the error, and set LastError to NULL + const char * CheckLastError() const; // returns the LastError, but does not set it to NULL + void SetCurrentDbgParams(const char *file, int line); + TwBar * m_PopupBar; + CTwMgr(ETwGraphAPI _GraphAPI, void *_Device); + ~CTwMgr(); + + struct CStructMember + { + std::string m_Name; + std::string m_Label; + TwType m_Type; + size_t m_Offset; + std::string m_DefString; + size_t m_Size; + std::string m_Help; + }; + struct CStruct + { + std::string m_Name; + std::vector m_Members; + size_t m_Size; + TwSummaryCallback m_SummaryCallback; + void * m_SummaryClientData; + std::string m_Help; + bool m_IsExt; + size_t m_ClientStructSize; + TwStructExtInitCallback m_StructExtInitCallback; + TwCopyVarFromExtCallback m_CopyVarFromExtCallback; + TwCopyVarToExtCallback m_CopyVarToExtCallback; + void * m_ExtClientData; + CStruct() : m_IsExt(false), m_StructExtInitCallback(NULL), m_CopyVarFromExtCallback(NULL), m_CopyVarToExtCallback(NULL), m_ExtClientData(NULL) {} + static void ANT_CALL DefaultSummary(char *_SummaryString, size_t _SummaryMaxLength, const void *_Value, void *_ClientData); + static void * s_PassProxyAsClientData; + }; + std::vector m_Structs; + + // followings are used for TwAddVarCB( ... StructType ... ) + struct CStructProxy + { + TwType m_Type; + void * m_StructData; + bool m_DeleteStructData; + void * m_StructExtData; + TwSetVarCallback m_StructSetCallback; + TwGetVarCallback m_StructGetCallback; + void * m_StructClientData; + CStructProxy(); + ~CStructProxy(); + }; + struct CMemberProxy + { + CStructProxy * m_StructProxy; + int m_MemberIndex; + struct CTwVar * m_Var; + struct CTwVarGroup * m_VarParent; + CTwBar * m_Bar; + CMemberProxy(); + ~CMemberProxy(); + static void ANT_CALL SetCB(const void *_Value, void *_ClientData); + static void ANT_CALL GetCB(void *_Value, void *_ClientData); + }; + std::list m_StructProxies; // elements should not move + std::list m_MemberProxies; // elements should not move + + struct CEnum + { + std::string m_Name; + typedef std::map CEntries; + CEntries m_Entries; + }; + std::vector m_Enums; + + TwType m_TypeColor32; + TwType m_TypeColor3F; + TwType m_TypeColor4F; + + PerfTimer m_Timer; + double m_LastMousePressedTime; + TwMouseButtonID m_LastMousePressedButtonID; + int m_LastMousePressedPosition[2]; + double m_RepeatMousePressedDelay; + double m_RepeatMousePressedPeriod; + bool m_CanRepeatMousePressed; + bool m_IsRepeatingMousePressed; + + #if defined(ANT_WINDOWS) + typedef HCURSOR CCursor; + #elif defined(ANT_UNIX) + typedef Cursor CCursor; + CCursor PixmapCursor(int _CurIdx); + Display * m_CurrentXDisplay; + Window m_CurrentXWindow; + #endif // defined(ANT_UNIX) + bool m_CursorsCreated; + void CreateCursors(); + void FreeCursors(); + void SetCursor(CCursor _Cursor); + CCursor m_CursorArrow; + CCursor m_CursorMove; + CCursor m_CursorWE; + CCursor m_CursorNS; + CCursor m_CursorTopLeft; + CCursor m_CursorTopRight; + CCursor m_CursorBottomLeft; + CCursor m_CursorBottomRight; + CCursor m_CursorHelp; + CCursor m_CursorHand; + CCursor m_CursorCross; + CCursor m_CursorUpArrow; + CCursor m_CursorNo; + CCursor m_RotoCursors[NB_ROTO_CURSORS]; + CCursor m_CursorCenter; + CCursor m_CursorPoint; + +protected: + int m_NbMinimizedBars; + const char * m_LastError; + const char * m_CurrentDbgFile; + int m_CurrentDbgLine; +}; + +extern CTwMgr *g_TwMgr; + + +// --------------------------------------------------------------------------- +// Extra functions and twtypes +// --------------------------------------------------------------------------- + + +bool TwGetKeyCode(int *_Code, int *_Modif, const char *_String); +bool TwGetKeyString(std::string *_String, int _Code, int _Modif); + +const ETwType TW_TYPE_SHORTCUT = ETwType(0xfff1); +const ETwType TW_TYPE_HELP_GRP = ETwType(0xfff2); +const ETwType TW_TYPE_HELP_ATOM = ETwType(0xfff3); +const ETwType TW_TYPE_HELP_HEADER = ETwType(0xfff4); +const ETwType TW_TYPE_HELP_STRUCT = ETwType(0xfff5); +const ETwType TW_TYPE_BUTTON = ETwType(0xfff6); +const ETwType TW_TYPE_STRUCT_BASE = ETwType(0x10000000); +const ETwType TW_TYPE_ENUM_BASE = ETwType(0x20000000); + + +// --------------------------------------------------------------------------- +// Color struct ext +// --------------------------------------------------------------------------- + + +struct CColorExt +{ + int R, G, B; + int H, L, S; + int A; + bool m_HLS, m_HasAlpha, m_OGL; + bool m_CanHaveAlpha; + bool m_IsColorF; + unsigned int m_PrevConvertedColor; + CTwMgr::CStructProxy*m_StructProxy; + void RGB2HLS(); + void HLS2RGB(); + static void ANT_CALL InitColor32CB(void *_ExtValue, void *_ClientData); + static void ANT_CALL InitColor3FCB(void *_ExtValue, void *_ClientData); + static void ANT_CALL InitColor4FCB(void *_ExtValue, void *_ClientData); + static void ANT_CALL CopyVarFromExtCB(void *_VarValue, const void *_ExtValue, unsigned int _ExtMemberIndex, void *_ClientData); + static void ANT_CALL CopyVarToExtCB(const void *_VarValue, void *_ExtValue, unsigned int _ExtMemberIndex, void *_ClientData); + static void ANT_CALL SummaryCB(char *_SummaryString, size_t _SummaryMaxLength, const void *_ExtValue, void *_ClientData); + static void CreateTypes(); +}; + + +// --------------------------------------------------------------------------- +// CTwFPU objects set and restore the fpu precision if needed. +// (could be usefull because DirectX changes it and AntTweakBar requires default double precision) +// --------------------------------------------------------------------------- + +struct CTwFPU +{ + CTwFPU() + { + #ifdef ANT_WINDOWS + state0 = _controlfp(0, 0); + if( (state0&MCW_PC)==_PC_24 ) // we need at least _PC_53 + _controlfp(_PC_53, MCW_PC); + #else + state0 = 0; + #endif + } + ~CTwFPU() + { + #ifdef ANT_WINDOWS + if( (state0&MCW_PC)==_PC_24 ) + _controlfp(_PC_24, MCW_PC); + #else + state0 = 0; + #endif + } +private: + unsigned int state0; +}; + +// --------------------------------------------------------------------------- + + +#endif // !defined ANT_TW_MGR_INCLUDED diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwOpenGL.cpp b/Extras/CDTestFramework/AntTweakBar/src/TwOpenGL.cpp new file mode 100644 index 0000000..c002c84 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwOpenGL.cpp @@ -0,0 +1,574 @@ +// --------------------------------------------------------------------------- +// +// @file TwOpenGL.cpp +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// note: TAB=4 +// +// --------------------------------------------------------------------------- + + +#include "TwPrecomp.h" +#include "LoadOGL.h" +#include "TwOpenGL.h" +#include "TwMgr.h" + +using namespace std; + +const char *g_ErrCantLoadOGL = "Cannot load OpenGL library dynamically"; +const char *g_ErrCantUnloadOGL = "Cannot unload OpenGL library"; + +GLuint g_SmallFontTexID = 0; +GLuint g_NormalFontTexID = 0; +GLuint g_LargeFontTexID = 0; + +// --------------------------------------------------------------------------- +// Extensions + +typedef void (APIENTRY * PFNGLBindBufferARB)(GLenum target, GLuint buffer); +typedef void (APIENTRY * PFNGLBindProgramARB)(GLenum target, GLuint program); +typedef GLuint (APIENTRY * PFNGLGetHandleARB)(GLenum pname); +typedef void (APIENTRY * PFNGLUseProgramObjectARB)(GLuint programObj); +PFNGLBindBufferARB _glBindBufferARB = NULL; +PFNGLBindProgramARB _glBindProgramARB = NULL; +PFNGLGetHandleARB _glGetHandleARB = NULL; +PFNGLUseProgramObjectARB _glUseProgramObjectARB = NULL; +#ifndef GL_ARRAY_BUFFER_ARB +# define GL_ARRAY_BUFFER_ARB 0x8892 +#endif +#ifndef GL_ELEMENT_ARRAY_BUFFER_ARB +# define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 +#endif +#ifndef GL_ARRAY_BUFFER_BINDING_ARB +# define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 +#endif +#ifndef GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB +# define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 +#endif +#ifndef GL_VERTEX_PROGRAM_ARB +# define GL_VERTEX_PROGRAM_ARB 0x8620 +#endif +#ifndef GL_FRAGMENT_PROGRAM_ARB +# define GL_FRAGMENT_PROGRAM_ARB 0x8804 +#endif +#ifndef GL_PROGRAM_OBJECT_ARB +# define GL_PROGRAM_OBJECT_ARB 0x8B40 +#endif + +// --------------------------------------------------------------------------- + +static GLuint BindFont(const CTexFont *_Font) +{ + GLuint TexID = 0; + _glGenTextures(1, &TexID); + _glBindTexture(GL_TEXTURE_2D, TexID); + _glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + _glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); + _glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + _glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + _glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + _glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + _glPixelTransferf(GL_ALPHA_SCALE, 1); + _glPixelTransferf(GL_ALPHA_BIAS, 0); + _glPixelTransferf(GL_RED_BIAS, 1); + _glPixelTransferf(GL_GREEN_BIAS, 1); + _glPixelTransferf(GL_BLUE_BIAS, 1); + _glTexImage2D(GL_TEXTURE_2D, 0, 4, _Font->m_TexWidth, _Font->m_TexHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, _Font->m_TexBytes); + _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST); + _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST); + _glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + _glBindTexture(GL_TEXTURE_2D, 0); + _glPixelTransferf(GL_ALPHA_BIAS, 0); + _glPixelTransferf(GL_RED_BIAS, 0); + _glPixelTransferf(GL_GREEN_BIAS, 0); + _glPixelTransferf(GL_BLUE_BIAS, 0); + + return TexID; +} + +static void UnbindFont(GLuint _FontTexID) +{ + if( _FontTexID>0 ) + _glDeleteTextures(1, &_FontTexID); +} + +// --------------------------------------------------------------------------- + +int CTwGraphOpenGL::Init() +{ + if( LoadOpenGL()==0 ) + { + g_TwMgr->SetLastError(g_ErrCantLoadOGL); + return 0; + } + + m_Drawing = false; + m_FontTexID = 0; + m_FontTex = NULL; + m_MaxClipPlanes = -1; + + // Get extensions + _glBindBufferARB = reinterpret_cast(_glGetProcAddress("glBindBufferARB")); + _glBindProgramARB = reinterpret_cast(_glGetProcAddress("glBindProgramARB")); + _glGetHandleARB = reinterpret_cast(_glGetProcAddress("glGetHandleARB")); + _glUseProgramObjectARB = reinterpret_cast(_glGetProcAddress("glUseProgramObjectARB")); + + return 1; +} + +// --------------------------------------------------------------------------- + +int CTwGraphOpenGL::Shut() +{ + assert(m_Drawing==false); + + UnbindFont(m_FontTexID); + + int Res = 1; + if( UnloadOpenGL()==0 ) + { + g_TwMgr->SetLastError(g_ErrCantUnloadOGL); + Res = 0; + } + + return Res; +} + +// --------------------------------------------------------------------------- + +void CTwGraphOpenGL::BeginDraw(int _WndWidth, int _WndHeight) +{ + assert(m_Drawing==false && _WndWidth>0 && _WndHeight>0); + m_Drawing = true; + +#ifdef _DEBUG + { + int err=0; + char msg[128]; + while( (err=_glGetError())!=0 ) + { + sprintf(msg, "Before BeginDraw GL_ERROR=0x%x\n", err); + #ifdef ANT_WINDOWS + OutputDebugString(msg); + #endif + fprintf(stderr, msg); + } + } +#endif + + _glPushAttrib(GL_ALL_ATTRIB_BITS); + _glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); + _glMatrixMode(GL_TEXTURE); + _glPushMatrix(); + _glLoadIdentity(); + _glMatrixMode(GL_MODELVIEW); + _glPushMatrix(); + _glLoadIdentity(); + _glMatrixMode(GL_PROJECTION); + _glPushMatrix(); + GLint Vp[4]; + _glGetIntegerv(GL_VIEWPORT, Vp); + /* + if( _WndWidth>0 && _WndHeight>0 ) + { + Vp[0] = 0; + Vp[1] = 0; + Vp[2] = _WndWidth; + Vp[3] = _WndHeight; + _glViewport(Vp[0], Vp[1], Vp[2], Vp[3]); + } + _glLoadIdentity(); + //_glOrtho(Vp[0], Vp[0]+Vp[2]-1, Vp[1]+Vp[3]-1, Vp[1], -1, 1); // Doesn't work + _glOrtho(Vp[0], Vp[0]+Vp[2], Vp[1]+Vp[3], Vp[1], -1, 1); + */ + if( _WndWidth>0 && _WndHeight>0 ) + { + Vp[0] = 0; + Vp[1] = 0; + Vp[2] = _WndWidth-1; + Vp[3] = _WndHeight-1; + _glViewport(Vp[0], Vp[1], Vp[2], Vp[3]); + } + _glLoadIdentity(); + _glOrtho(Vp[0], Vp[0]+Vp[2], Vp[1]+Vp[3], Vp[1], -1, 1); + + _glGetFloatv(GL_LINE_WIDTH, &m_PrevLineWidth); + _glDisable(GL_POLYGON_STIPPLE); + _glLineWidth(1); + _glDisable(GL_LINE_SMOOTH); + _glDisable(GL_LINE_STIPPLE); + _glDisable(GL_CULL_FACE); + _glDisable(GL_DEPTH_TEST); + _glDisable(GL_LIGHTING); + _glEnable(GL_BLEND); + _glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + _glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &m_PrevTexEnv); + _glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + _glGetIntegerv(GL_POLYGON_MODE, m_PrevPolygonMode); + _glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + _glDisable(GL_ALPHA_TEST); + //_glEnable(GL_ALPHA_TEST); + //_glAlphaFunc(GL_GREATER, 0); + _glDisable(GL_FOG); + _glDisable(GL_LOGIC_OP); + _glDisable(GL_SCISSOR_TEST); + if( m_MaxClipPlanes<0 ) + { + _glGetIntegerv(GL_MAX_CLIP_PLANES, &m_MaxClipPlanes); + if( m_MaxClipPlanes<0 || m_MaxClipPlanes>255 ) + m_MaxClipPlanes = 6; + } + for( int i=0; i_X1) + ++_X0; + if(_Y0<_Y1) + ++_Y1; + else if(_Y0>_Y1) + ++_Y0; + */ + const GLfloat dx = +0.0f; + //GLfloat dy = -0.2f; + const GLfloat dy = -0.5f; + if( _AntiAliased ) + _glEnable(GL_LINE_SMOOTH); + else + _glDisable(GL_LINE_SMOOTH); + _glDisable(GL_TEXTURE_2D); + _glMatrixMode(GL_MODELVIEW); + _glLoadIdentity(); + _glBegin(GL_LINES); + _glColor4ub(GLubyte(_Color0>>16), GLubyte(_Color0>>8), GLubyte(_Color0), GLubyte(_Color0>>24)); + _glVertex2f((GLfloat)_X0+dx, (GLfloat)_Y0+dy); + _glColor4ub(GLubyte(_Color1>>16), GLubyte(_Color1>>8), GLubyte(_Color1), GLubyte(_Color1>>24)); + _glVertex2f((GLfloat)_X1+dx, (GLfloat)_Y1+dy); + //_glVertex2i(_X0, _Y0); + //_glVertex2i(_X1, _Y1); + _glEnd(); + _glDisable(GL_LINE_SMOOTH); +} + +// --------------------------------------------------------------------------- + +void CTwGraphOpenGL::DrawRect(int _X0, int _Y0, int _X1, int _Y1, color32 _Color00, color32 _Color10, color32 _Color01, color32 _Color11) +{ + assert(m_Drawing==true); + + /* + // border adjustment + if(_X0<_X1) + ++_X1; + else if(_X0>_X1) + ++_X0; + if(_Y0<_Y1) + ++_Y1; + else if(_Y0>_Y1) + ++_Y0; + */ + // border adjustment + if(_X0<_X1) + ++_X1; + else if(_X0>_X1) + ++_X0; + if(_Y0<_Y1) + --_Y0; + else if(_Y0>_Y1) + --_Y1; + const GLfloat dx = +0.0f; + const GLfloat dy = +0.0f; + + _glDisable(GL_TEXTURE_2D); + _glMatrixMode(GL_MODELVIEW); + _glLoadIdentity(); + //GLubyte r = GLubyte(_Color>>16); + //GLubyte g = GLubyte(_Color>>8); + //GLubyte b = GLubyte(_Color); + //GLubyte a = GLubyte(_Color>>24); + //_glColor4ub(GLubyte(_Color>>16), GLubyte(_Color>>8), GLubyte(_Color), GLubyte(_Color>>24)); + //_glColor4ub(r, g, b, a); + _glBegin(GL_QUADS); + _glColor4ub(GLubyte(_Color00>>16), GLubyte(_Color00>>8), GLubyte(_Color00), GLubyte(_Color00>>24)); + _glVertex2f((GLfloat)_X0+dx, (GLfloat)_Y0+dy); + _glColor4ub(GLubyte(_Color10>>16), GLubyte(_Color10>>8), GLubyte(_Color10), GLubyte(_Color10>>24)); + _glVertex2f((GLfloat)_X1+dx, (GLfloat)_Y0+dy); + _glColor4ub(GLubyte(_Color11>>16), GLubyte(_Color11>>8), GLubyte(_Color11), GLubyte(_Color11>>24)); + _glVertex2f((GLfloat)_X1+dx, (GLfloat)_Y1+dy); + _glColor4ub(GLubyte(_Color01>>16), GLubyte(_Color01>>8), GLubyte(_Color01), GLubyte(_Color01>>24)); + _glVertex2f((GLfloat)_X0+dx, (GLfloat)_Y1+dy); + _glEnd(); +} + +// --------------------------------------------------------------------------- + +void *CTwGraphOpenGL::NewTextObj() +{ + return new CTextObj; +} + +// --------------------------------------------------------------------------- + +void CTwGraphOpenGL::DeleteTextObj(void *_TextObj) +{ + assert(_TextObj!=NULL); + delete static_cast(_TextObj); +} + +// --------------------------------------------------------------------------- + +void CTwGraphOpenGL::BuildText(void *_TextObj, const std::string *_TextLines, color32 *_LineColors, color32 *_LineBgColors, int _NbLines, const CTexFont *_Font, int _Sep, int _BgWidth) +{ + assert(m_Drawing==true); + assert(_TextObj!=NULL); + assert(_Font!=NULL); + + if( _Font != m_FontTex ) + { + UnbindFont(m_FontTexID); + m_FontTexID = BindFont(_Font); + m_FontTex = _Font; + } + CTextObj *TextObj = static_cast(_TextObj); + TextObj->m_TextVerts.resize(0); + TextObj->m_TextUVs.resize(0); + TextObj->m_BgVerts.resize(0); + TextObj->m_Colors.resize(0); + TextObj->m_BgColors.resize(0); + + int x, x1, y, y1, i, Len; + unsigned char ch; + const unsigned char *Text; + color32 LineColor = COLOR32_RED; + for( int Line=0; Line<_NbLines; ++Line ) + { + x = 0; + y = Line * (_Font->m_CharHeight+_Sep); + y1 = y+_Font->m_CharHeight; + Len = (int)_TextLines[Line].length(); + Text = (const unsigned char *)(_TextLines[Line].c_str()); + if( _LineColors!=NULL ) + LineColor = (_LineColors[Line]&0xff00ff00) | GLubyte(_LineColors[Line]>>16) | (GLubyte(_LineColors[Line])<<16); + + for( i=0; im_CharWidth[ch]; + + TextObj->m_TextVerts.push_back(Vec2(x , y )); + TextObj->m_TextVerts.push_back(Vec2(x1, y )); + TextObj->m_TextVerts.push_back(Vec2(x , y1)); + TextObj->m_TextVerts.push_back(Vec2(x1, y )); + TextObj->m_TextVerts.push_back(Vec2(x1, y1)); + TextObj->m_TextVerts.push_back(Vec2(x , y1)); + + TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV0[ch])); + TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV0[ch])); + TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV1[ch])); + TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV0[ch])); + TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV1[ch])); + TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV1[ch])); + + if( _LineColors!=NULL ) + { + TextObj->m_Colors.push_back(LineColor); + TextObj->m_Colors.push_back(LineColor); + TextObj->m_Colors.push_back(LineColor); + TextObj->m_Colors.push_back(LineColor); + TextObj->m_Colors.push_back(LineColor); + TextObj->m_Colors.push_back(LineColor); + } + + x = x1; + } + if( _BgWidth>0 && Len>0 ) + { + TextObj->m_BgVerts.push_back(Vec2(-1 , y )); + TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y )); + TextObj->m_BgVerts.push_back(Vec2(-1 , y1)); + TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y )); + TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y1)); + TextObj->m_BgVerts.push_back(Vec2(-1 , y1)); + + if( _LineBgColors!=NULL ) + { + color32 LineBgColor = (_LineBgColors[Line]&0xff00ff00) | GLubyte(_LineBgColors[Line]>>16) | (GLubyte(_LineBgColors[Line])<<16); + TextObj->m_BgColors.push_back(LineBgColor); + TextObj->m_BgColors.push_back(LineBgColor); + TextObj->m_BgColors.push_back(LineBgColor); + TextObj->m_BgColors.push_back(LineBgColor); + TextObj->m_BgColors.push_back(LineBgColor); + TextObj->m_BgColors.push_back(LineBgColor); + } + } + } +} + +// --------------------------------------------------------------------------- + +void CTwGraphOpenGL::DrawText(void *_TextObj, int _X, int _Y, color32 _Color, color32 _BgColor) +{ + assert(m_Drawing==true); + assert(_TextObj!=NULL); + CTextObj *TextObj = static_cast(_TextObj); + + if( TextObj->m_TextVerts.size()<4 ) + return; // no character to draw + + _glMatrixMode(GL_MODELVIEW); + _glLoadIdentity(); + _glTranslatef((GLfloat)_X, (GLfloat)_Y, 0); + _glEnableClientState(GL_VERTEX_ARRAY); + if( (_BgColor!=0 || TextObj->m_BgColors.size()==TextObj->m_BgVerts.size()) && TextObj->m_BgVerts.size()>=4 ) + { + _glDisable(GL_TEXTURE_2D); + _glVertexPointer(2, GL_FLOAT, 0, &(TextObj->m_BgVerts[0])); + if( TextObj->m_BgColors.size()==TextObj->m_BgVerts.size() && _BgColor==0 ) + { + _glEnableClientState(GL_COLOR_ARRAY); + _glColorPointer(4, GL_UNSIGNED_BYTE, 0, &(TextObj->m_BgColors[0])); + } + else + { + _glDisableClientState(GL_COLOR_ARRAY); + _glColor4ub(GLubyte(_BgColor>>16), GLubyte(_BgColor>>8), GLubyte(_BgColor), GLubyte(_BgColor>>24)); + } + _glDrawArrays(GL_TRIANGLES, 0, (int)TextObj->m_BgVerts.size()); + } + _glEnable(GL_TEXTURE_2D); + _glBindTexture(GL_TEXTURE_2D, m_FontTexID); + _glEnableClientState(GL_TEXTURE_COORD_ARRAY); + _glVertexPointer(2, GL_FLOAT, 0, &(TextObj->m_TextVerts[0])); + _glTexCoordPointer(2, GL_FLOAT, 0, &(TextObj->m_TextUVs[0])); + if( TextObj->m_Colors.size()==TextObj->m_TextVerts.size() && _Color==0 ) + { + _glEnableClientState(GL_COLOR_ARRAY); + _glColorPointer(4, GL_UNSIGNED_BYTE, 0, &(TextObj->m_Colors[0])); + } + else + { + _glDisableClientState(GL_COLOR_ARRAY); + _glColor4ub(GLubyte(_Color>>16), GLubyte(_Color>>8), GLubyte(_Color), GLubyte(_Color>>24)); + } + + _glDrawArrays(GL_TRIANGLES, 0, (int)TextObj->m_TextVerts.size()); + + _glDisableClientState(GL_VERTEX_ARRAY); + _glDisableClientState(GL_TEXTURE_COORD_ARRAY); + _glDisableClientState(GL_COLOR_ARRAY); +} + +// --------------------------------------------------------------------------- diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwOpenGL.h b/Extras/CDTestFramework/AntTweakBar/src/TwOpenGL.h new file mode 100644 index 0000000..af02ed0 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwOpenGL.h @@ -0,0 +1,72 @@ +// --------------------------------------------------------------------------- +// +// @file TwOpenGL.h +// @brief OpenGL graph functions +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// notes: Private header +// TAB=4 +// +// --------------------------------------------------------------------------- + + +#if !defined ANT_TW_OPENGL_INCLUDED +#define ANT_TW_OPENGL_INCLUDED + +#include "TwGraph.h" + +// --------------------------------------------------------------------------- + +class CTwGraphOpenGL : public ITwGraph +{ +public: + virtual int Init(); + virtual int Shut(); + virtual void BeginDraw(int _WndWidth, int _WndHeight); + virtual void EndDraw(); + virtual bool IsDrawing(); + virtual void Restore(); + virtual void DrawLine(int _X0, int _Y0, int _X1, int _Y1, color32 _Color0, color32 _Color1, bool _AntiAliased=false); + virtual void DrawLine(int _X0, int _Y0, int _X1, int _Y1, color32 _Color, bool _AntiAliased=false) { DrawLine(_X0, _Y0, _X1, _Y1, _Color, _Color, _AntiAliased); } + virtual void DrawRect(int _X0, int _Y0, int _X1, int _Y1, color32 _Color00, color32 _Color10, color32 _Color01, color32 _Color11); + virtual void DrawRect(int _X0, int _Y0, int _X1, int _Y1, color32 _Color) { DrawRect(_X0, _Y0, _X1, _Y1, _Color, _Color, _Color, _Color); } + + + virtual void * NewTextObj(); + virtual void DeleteTextObj(void *_TextObj); + virtual void BuildText(void *_TextObj, const std::string *_TextLines, color32 *_LineColors, color32 *_LineBgColors, int _NbLines, const CTexFont *_Font, int _Sep, int _BgWidth); + virtual void DrawText(void *_TextObj, int _X, int _Y, color32 _Color, color32 _BgColor); + +protected: + bool m_Drawing; + GLuint m_FontTexID; + const CTexFont * m_FontTex; + GLfloat m_PrevLineWidth; + GLint m_PrevTexEnv; + GLint m_PrevPolygonMode[2]; + GLint m_MaxClipPlanes; + GLint m_PrevTexture; + GLint m_PrevArrayBufferARB; + GLint m_PrevElementArrayBufferARB; + GLboolean m_PrevVertexProgramARB; + GLboolean m_PrevFragmentProgramARB; + GLuint m_PrevProgramObjectARB; + + struct Vec2 { GLfloat x, y; Vec2(){} Vec2(GLfloat _X, GLfloat _Y):x(_X),y(_Y){} Vec2(int _X, int _Y):x(GLfloat(_X)),y(GLfloat(_Y)){} }; + struct CTextObj + { + std::vector m_TextVerts; + std::vector m_TextUVs; + std::vector m_BgVerts; + std::vectorm_Colors; + std::vectorm_BgColors; + }; +}; + +// --------------------------------------------------------------------------- + + +#endif // !defined ANT_TW_OPENGL_INCLUDED diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwPrecomp.cpp b/Extras/CDTestFramework/AntTweakBar/src/TwPrecomp.cpp new file mode 100644 index 0000000..6c9502e --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwPrecomp.cpp @@ -0,0 +1 @@ +#include "TwPrecomp.h" diff --git a/Extras/CDTestFramework/AntTweakBar/src/TwPrecomp.h b/Extras/CDTestFramework/AntTweakBar/src/TwPrecomp.h new file mode 100644 index 0000000..c1e517a --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/TwPrecomp.h @@ -0,0 +1,65 @@ +// --------------------------------------------------------------------------- +// +// @file TwPrecomp.h +// @brief Precompiled header +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// notes: Private header +// TAB=4 +// +// --------------------------------------------------------------------------- + + +#if !defined ANT_TW_PRECOMP_INCLUDED +#define ANT_TW_PRECOMP_INCLUDED + + +#if defined _MSC_VER +# pragma warning(disable: 4514) // unreferenced inline function has been removed +# pragma warning(disable: 4710) // function not inlined +# pragma warning(disable: 4786) // template name truncated +# pragma warning(disable: 4530) // exceptions not handled +# define _CRT_SECURE_NO_DEPRECATE // visual 8 secure crt warning +#endif + +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER<=1200 +# pragma warning(push, 3) +#endif +#include +#include +#include +#include +#include +#if defined(_MSC_VER) && _MSC_VER<=1200 +# pragma warning(pop) +#endif +#if defined(_UNIX) +# define ANT_UNIX +# include +# include +# undef _WIN32 +# undef WIN32 +# undef _WIN64 +# undef WIN64 +# undef _WINDOWS +# undef ANT_WINDOWS +#elif defined(_WINDOWS) || defined(WIN32) || defined(WIN64) || defined(_WIN32) || defined(_WIN64) +# define ANT_WINDOWS +# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +# include +# include +#endif // defined _WINDOWS + +#include // must be included after windows.h +#define ANT_OGL_HEADER_INCLUDED + + +#endif // !defined ANT_TW_PRECOMP_INCLUDED diff --git a/Extras/CDTestFramework/AntTweakBar/src/res/FontChars.txt b/Extras/CDTestFramework/AntTweakBar/src/res/FontChars.txt new file mode 100644 index 0000000..70e5393 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/res/FontChars.txt @@ -0,0 +1,232 @@ + !"#$%&'()*+,-./0123456789:;<=>? +@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ +`abcdefghijklmnopqrstuvwxyz{|}~ +€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ + ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ +ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß +àáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + +032 +033 ! +034 " +035 # +036 $ +037 % +038 & +039 ' +040 ( +041 ) +042 * +043 + +044 , +045 - +046 . +047 / +048 0 +049 1 +050 2 +051 3 +052 4 +053 5 +054 6 +055 7 +056 8 +057 9 +058 : +059 ; +060 < +061 = +062 > +063 ? +064 @ +065 A +066 B +067 C +068 D +069 E +070 F +071 G +072 H +073 I +074 J +075 K +076 L +077 M +078 N +079 O +080 P +081 Q +082 R +083 S +084 T +085 U +086 V +087 W +088 X +089 Y +090 Z +091 [ +092 \ +093 ] +094 ^ +095 _ +096 ` +097 a +098 b +099 c +100 d +101 e +102 f +103 g +104 h +105 i +106 j +107 k +108 l +109 m +110 n +111 o +112 p +113 q +114 r +115 s +116 t +117 u +118 v +119 w +120 x +121 y +122 z +123 { +124 | +125 } +126 ~ +127  +128 € +129  +130 ‚ +131 ƒ +132 „ +133 … +134 † +135 ‡ +136 ˆ +137 ‰ +138 Š +139 ‹ +140 Œ +141  +142 Ž +143  +144  +145 ‘ +146 ’ +147 “ +148 ” +149 • +150 – +151 — +152 ˜ +153 ™ +154 š +155 › +156 œ +157  +158 ž +159 Ÿ +160   +161 ¡ +162 ¢ +163 £ +164 ¤ +165 ¥ +166 ¦ +167 § +168 ¨ +169 © +170 ª +171 « +172 ¬ +173 ­ +174 ® +175 ¯ +176 ° +177 ± +178 ² +179 ³ +180 ´ +181 µ +182 ¶ +183 · +184 ¸ +185 ¹ +186 º +187 » +188 ¼ +189 ½ +190 ¾ +191 ¿ +192 À +193 Á +194  +195 à +196 Ä +197 Å +198 Æ +199 Ç +200 È +201 É +202 Ê +203 Ë +204 Ì +205 Í +206 Î +207 Ï +208 Ð +209 Ñ +210 Ò +211 Ó +212 Ô +213 Õ +214 Ö +215 × +216 Ø +217 Ù +218 Ú +219 Û +220 Ü +221 Ý +222 Þ +223 ß +224 à +225 á +226 â +227 ã +228 ä +229 å +230 æ +231 ç +232 è +233 é +234 ê +235 ë +236 ì +237 í +238 î +239 ï +240 ð +241 ñ +242 ò +243 ó +244 ô +245 õ +246 ö +247 ÷ +248 ø +249 ù +250 ú +251 û +252 ü +253 ý +254 þ +255 ÿ \ No newline at end of file diff --git a/Extras/CDTestFramework/AntTweakBar/src/res/FontLargeAA.pgm b/Extras/CDTestFramework/AntTweakBar/src/res/FontLargeAA.pgm new file mode 100644 index 0000000..ee35d38 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/res/FontLargeAA.pgm @@ -0,0 +1,1197 @@ +P2 +# Created by Paint Shop Pro +276 120 +255 +127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 59 245 125 175 225 21 +0 0 0 0 0 0 0 0 0 0 0 0 0 138 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 59 241 89 0 0 12 235 201 89 255 166 0 0 0 0 0 172 89 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 225 21 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 138 247 34 0 12 +232 89 138 225 21 0 0 0 0 138 125 7 199 34 0 0 0 0 138 125 0 0 0 0 138 +255 255 201 0 0 0 59 215 21 0 0 0 0 59 245 255 255 166 0 0 0 59 241 89 +0 7 206 201 0 0 89 251 89 0 59 215 21 172 89 59 192 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 166 0 0 138 255 251 89 0 0 0 0 0 +138 201 0 0 0 7 206 255 255 255 166 0 0 7 206 255 255 255 201 0 0 0 0 0 +0 138 251 89 0 0 175 255 255 255 255 225 21 0 0 12 235 255 255 125 89 255 +255 255 255 255 251 89 0 12 235 255 255 225 21 0 0 59 245 255 255 166 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 59 245 255 255 251 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 89 247 +34 0 12 232 89 138 201 0 0 0 0 7 202 89 59 215 21 0 0 12 235 255 255 255 +166 0 59 241 89 12 235 125 0 0 172 89 0 0 0 0 7 206 166 0 89 251 89 0 0 +12 228 34 0 89 247 34 0 0 0 175 201 0 0 89 251 191 194 247 34 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 232 89 0 175 201 0 12 235 +125 0 0 138 255 255 201 0 0 0 12 182 0 0 59 245 125 0 12 206 21 0 12 235 +166 0 0 0 0 89 255 251 89 0 0 175 201 0 0 0 0 0 0 89 255 125 0 0 0 0 0 +0 0 0 89 251 89 12 235 166 0 7 206 201 0 59 245 125 0 12 235 166 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 89 166 0 0 138 251 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 89 247 34 0 12 +228 34 89 201 0 0 0 0 12 206 21 89 166 0 0 12 235 125 138 125 59 192 0 +89 247 34 7 206 166 0 89 201 0 0 0 0 0 12 235 125 0 12 232 89 0 0 12 228 +34 0 175 201 0 0 0 0 59 241 89 0 0 7 206 166 0 0 0 0 0 0 0 138 166 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 225 21 59 241 89 0 0 138 225 21 0 +0 0 175 201 0 0 0 0 0 0 0 7 206 201 0 0 0 0 0 0 175 201 0 0 0 59 241 132 +241 89 0 0 175 201 0 0 0 0 0 7 206 166 0 0 0 0 0 0 0 0 7 206 201 0 59 241 +89 0 0 138 225 21 138 225 21 0 0 138 225 21 89 255 125 0 0 89 255 125 0 +0 0 0 0 0 0 0 138 225 21 0 0 0 0 0 0 0 0 0 0 0 138 201 0 0 0 0 0 0 0 0 +0 0 0 59 241 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 89 247 34 0 0 0 0 0 0 0 +0 89 255 255 255 255 255 255 255 125 59 238 34 138 125 0 0 0 89 247 34 +7 206 166 7 202 89 0 0 0 0 0 0 175 225 21 138 225 21 0 0 0 0 0 12 235 125 +0 0 0 0 7 206 125 0 89 251 191 194 247 34 0 0 0 0 0 138 166 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 138 166 0 89 247 34 0 0 89 247 34 0 0 0 175 201 +0 0 0 0 0 0 0 12 235 166 0 0 0 0 0 59 245 125 0 0 12 235 125 59 241 89 +0 0 175 201 0 0 0 0 0 59 241 89 0 0 0 0 0 0 0 0 89 247 34 0 12 235 201 +0 0 175 201 0 138 225 21 0 0 89 247 34 89 255 125 0 0 89 255 125 0 0 0 +0 0 12 235 255 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 175 255 251 89 0 0 0 0 +0 0 0 0 138 247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 89 247 34 0 0 0 0 0 +0 0 0 0 0 175 125 7 199 34 0 0 12 235 166 138 125 0 0 0 59 241 89 12 235 +125 89 201 12 235 255 251 89 0 0 7 206 255 166 0 59 241 89 0 0 0 59 238 +34 0 0 0 0 0 175 166 59 215 21 172 89 59 192 0 0 0 0 0 138 166 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 125 0 138 247 34 0 0 89 247 34 0 0 0 +175 201 0 0 0 0 0 0 0 89 251 89 0 0 0 89 255 247 34 0 0 7 206 166 0 59 +241 89 0 0 175 255 255 255 225 21 0 89 251 226 255 255 247 34 0 0 0 7 206 +166 0 0 0 12 235 255 255 201 0 0 89 255 125 0 0 138 247 34 0 0 0 0 0 0 +0 0 0 0 0 89 255 255 166 0 0 0 0 0 175 255 255 255 255 255 255 225 21 0 +0 0 0 59 245 255 201 0 0 0 0 0 175 251 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 +0 0 89 225 21 0 0 0 0 0 0 0 0 0 7 199 34 59 215 21 0 0 0 59 245 255 255 +201 0 0 0 138 255 255 201 12 228 34 175 166 0 138 201 0 12 235 125 89 255 +125 59 241 89 0 0 0 59 238 34 0 0 0 0 0 138 201 0 0 0 172 89 0 0 0 7 206 +255 255 255 255 255 255 247 34 0 0 0 0 89 255 255 255 166 0 0 0 0 0 59 +238 34 0 138 247 34 0 0 89 247 34 0 0 0 175 201 0 0 0 0 0 0 59 245 166 +0 0 0 0 0 0 12 235 166 0 138 201 0 0 59 241 89 0 0 0 0 0 12 235 201 0 138 +251 89 0 0 175 225 21 0 0 89 247 34 0 0 7 206 166 0 175 255 166 0 0 89 +255 255 255 223 247 34 0 0 0 0 0 0 0 0 0 0 175 247 34 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 225 21 0 0 175 225 21 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 127 0 0 0 0 0 59 215 21 0 0 0 0 0 0 0 12 235 255 255 255 255 255 255 +166 0 0 0 0 138 125 175 225 21 0 0 0 0 0 138 166 7 206 125 0 89 247 34 +138 225 21 0 89 255 166 215 21 0 0 0 59 238 34 0 0 0 0 0 138 201 0 0 0 +0 0 0 0 0 0 0 0 0 138 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 201 0 +0 89 247 34 0 0 89 247 34 0 0 0 175 201 0 0 0 0 0 12 235 201 0 0 0 0 0 +0 0 0 138 225 21 175 255 255 255 255 255 255 125 0 0 0 0 0 138 247 34 89 +247 34 0 0 59 241 89 0 7 206 166 0 0 0 138 247 34 0 0 138 247 34 0 0 0 +0 0 138 225 21 0 0 0 0 0 0 0 0 0 0 0 89 255 255 166 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 59 245 255 201 0 0 0 0 175 201 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 166 0 175 125 0 0 0 0 0 0 138 +125 89 247 34 0 0 0 0 12 228 34 7 206 125 0 89 247 34 138 247 34 0 0 89 +255 166 0 0 0 0 59 238 34 0 0 0 0 0 175 166 0 0 0 0 0 0 0 0 0 0 0 0 138 +166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 125 0 0 59 241 89 0 0 138 225 +21 0 0 0 175 201 0 0 0 0 12 235 201 0 0 0 0 0 0 0 0 0 138 225 21 0 0 0 +0 59 241 89 0 0 0 0 0 0 138 225 21 59 241 89 0 0 59 241 89 0 89 247 34 +0 0 0 138 247 34 0 0 89 251 89 0 0 0 0 7 206 166 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 12 235 255 225 21 0 0 175 255 255 255 255 255 255 225 21 0 0 175 +255 251 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 89 247 +34 0 0 0 0 0 0 0 0 0 175 125 7 199 34 0 0 0 89 201 0 138 125 175 201 0 +0 0 0 0 138 166 0 0 175 166 0 138 201 0 89 255 166 0 0 89 255 255 125 0 +0 0 12 235 125 0 0 0 0 7 206 125 0 0 0 0 0 0 0 0 0 0 0 0 138 166 0 0 0 +0 0 138 255 125 0 0 0 0 0 0 175 247 34 59 238 34 0 0 0 175 201 0 12 235 +125 0 0 0 0 175 201 0 0 0 12 235 166 0 0 0 0 0 89 166 0 0 59 245 166 0 +0 0 0 0 59 241 89 0 59 215 21 0 12 235 166 0 7 206 201 0 0 175 225 21 7 +206 166 0 0 0 0 59 245 166 0 7 206 225 21 0 0 0 0 175 225 21 0 89 255 125 +0 0 12 235 201 0 0 0 0 0 0 0 0 138 225 21 0 0 0 0 0 0 0 0 0 0 0 138 201 +0 0 0 0 0 0 0 0 0 175 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 89 247 +34 0 0 0 0 0 0 0 0 7 199 34 59 215 21 0 0 0 12 235 255 255 255 201 0 0 +0 0 0 59 215 21 0 0 12 235 255 251 89 0 0 89 255 255 255 201 0 89 255 0 +0 0 0 175 201 0 0 0 0 59 238 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 +201 0 0 0 0 0 0 0 175 247 34 138 201 0 0 0 0 0 138 255 251 89 0 0 0 138 +255 255 255 255 166 0 89 255 255 255 255 255 247 34 12 235 255 255 255 +166 0 0 0 0 0 0 59 241 89 0 12 235 255 255 255 166 0 0 0 7 206 255 255 +225 21 0 138 247 34 0 0 0 0 0 59 245 255 255 201 0 0 0 175 255 255 201 +0 0 0 89 255 125 0 0 89 251 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 175 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 125 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 247 34 0 0 0 175 201 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 232 89 0 0 0 0 0 0 0 0 0 0 175 125 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 201 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 125 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 201 0 0 89 251 89 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 201 0 0 0 0 0 0 0 0 0 0 12 232 89 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 232 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 201 0 0 201 201 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 127 127 0 127 127 127 +127 0 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 127 0 127 127 0 127 127 127 127 0 127 127 +127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 +127 0 127 127 127 0 127 127 127 127 0 127 127 127 0 127 127 127 127 0 127 +127 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 +127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +0 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 255 255 +201 0 138 201 0 0 0 0 89 255 255 255 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 127 0 0 0 0 175 255 255 255 247 34 0 0 0 0 0 7 206 251 89 0 0 12 0 +235 255 255 255 255 201 0 0 0 0 59 245 255 255 255 201 12 0 235 255 255 +255 255 166 0 0 0 12 235 255 255 255 255 255 127 12 235 255 255 255 255 +251 89 0 0 12 235 255 255 255 251 89 12 235 166 0 0 0 12 235 125 89 255 +255 255 201 0 0 175 255 255 225 21 12 235 166 0 0 7 206 251 102 0 235 166 +0 0 0 0 12 235 251 89 0 0 0 89 255 225 21 12 235 251 89 0 0 12 235 125 +0 0 0 138 255 255 166 0 0 0 12 235 255 255 255 251 89 0 0 0 0 175 255 255 +201 0 0 0 12 235 255 255 255 251 89 0 0 0 12 235 255 255 255 247 47 235 +255 255 255 255 255 255 255 138 0 235 125 0 0 0 59 245 133 206 166 0 0 +0 0 59 245 255 133 201 0 0 0 138 251 89 0 0 12 235 133 206 247 34 0 0 0 +175 229 216 225 21 0 0 0 138 247 124 255 255 255 255 255 255 125 7 206 +125 0 0 0 59 238 34 0 0 0 0 0 12 235 125 0 0 0 0 175 247 34 0 0 0 0 0 0 +0 0 0 0 127 0 0 59 245 166 0 0 0 59 245 166 0 0 0 0 59 245 255 166 0 0 +12 0 235 166 0 0 59 245 125 0 0 138 255 125 0 0 7 202 102 0 235 166 0 0 +59 245 225 21 0 12 235 166 0 0 0 0 0 12 235 166 0 0 0 0 0 0 89 255 166 +0 0 0 89 127 12 235 166 0 0 0 12 235 125 0 12 235 125 0 0 0 0 0 138 225 +21 12 235 166 0 7 206 225 21 12 0 235 166 0 0 0 0 12 235 255 166 0 0 7 +206 255 225 21 12 235 255 201 0 0 12 235 125 0 59 245 166 0 0 138 251 89 +0 12 235 166 0 0 138 251 89 0 89 255 125 0 0 89 255 125 0 12 235 166 0 +0 138 251 89 0 12 235 166 0 0 7 202 89 0 0 0 138 225 21 0 0 12 0 235 125 +0 0 0 59 245 125 138 225 21 0 0 0 138 225 151 34 247 34 0 0 175 255 125 +0 0 89 247 34 12 235 166 0 0 89 247 34 59 245 125 0 0 59 245 125 0 0 0 +0 0 138 247 34 7 206 125 0 0 0 7 206 125 0 0 0 0 0 12 235 125 0 0 0 138 +225 187 201 0 0 0 0 0 0 0 0 0 0 127 0 12 232 89 0 0 0 0 0 12 232 89 0 0 +0 138 225 151 225 21 0 12 0 235 166 0 0 12 235 166 0 12 235 166 0 0 0 0 +0 12 0 235 166 0 0 0 12 235 166 0 12 235 166 0 0 0 0 0 12 235 166 0 0 0 +0 0 12 235 166 0 0 0 0 0 0 12 235 166 0 0 0 12 235 125 0 12 235 125 0 0 +0 0 0 138 225 21 12 235 166 0 175 225 21 0 12 0 235 166 0 0 0 0 12 235 +166 238 34 0 59 215 187 225 21 12 235 166 245 125 0 12 235 125 12 235 125 +0 0 0 0 138 247 34 12 235 166 0 0 12 235 166 12 235 125 0 0 0 0 138 247 +34 12 235 166 0 0 12 235 166 0 89 247 34 0 0 0 0 0 0 0 0 138 225 21 0 0 +12 0 235 125 0 0 0 59 245 125 59 241 89 0 0 7 206 166 59 0 241 89 0 12 +232 194 201 0 0 138 225 21 0 89 251 89 12 235 166 0 0 138 247 34 7 206 +201 0 0 0 0 0 59 245 125 0 7 206 125 0 0 0 0 138 201 0 0 0 0 0 12 235 125 +0 0 59 241 89 12 235 166 0 0 0 0 0 0 0 0 0 127 0 175 166 0 59 245 255 255 +247 34 138 201 0 0 7 206 166 59 241 89 0 12 0 235 166 0 0 89 251 89 0 89 +247 34 0 0 0 0 0 12 0 235 166 0 0 0 0 138 225 21 12 235 166 0 0 0 0 0 12 +235 166 0 0 0 0 0 89 247 34 0 0 0 0 0 0 12 235 166 0 0 0 12 235 125 0 12 +235 125 0 0 0 0 0 138 225 21 12 235 166 175 247 34 0 0 12 0 235 166 0 0 +0 0 12 235 133 206 166 0 175 166 175 225 21 12 235 125 138 225 21 12 235 +125 89 247 34 0 0 0 0 59 245 125 12 235 166 0 0 12 235 166 89 247 34 0 +0 0 0 59 245 125 12 235 166 0 0 12 235 125 0 89 255 125 0 0 0 0 0 0 0 0 +138 225 21 0 0 12 0 235 125 0 0 0 59 245 125 7 206 201 0 0 59 241 89 7 +0 206 166 0 59 215 111 225 21 7 206 166 0 0 0 175 225 187 225 21 0 0 12 +235 166 89 247 34 0 0 0 0 7 206 201 0 0 7 206 125 0 0 0 0 89 225 21 0 0 +0 0 12 235 125 0 12 235 166 0 0 59 241 89 0 0 0 0 0 0 0 0 127 0 202 89 +12 235 125 0 12 228 34 59 215 0 0 59 241 89 7 206 166 0 12 0 235 255 255 +255 255 166 0 0 138 225 21 0 0 0 0 0 12 0 235 166 0 0 0 0 89 247 34 12 +235 255 255 255 255 247 34 12 235 255 255 255 255 247 0 163 225 21 0 0 +0 0 0 0 12 235 255 255 255 255 255 255 125 0 12 235 125 0 0 0 0 0 138 225 +21 12 235 255 247 34 0 0 0 12 0 235 166 0 0 0 0 12 235 125 89 225 34 228 +34 175 225 21 12 235 125 12 235 125 12 235 125 138 225 21 0 0 0 0 12 235 +166 12 235 166 0 0 175 247 34 138 225 21 0 0 0 0 12 235 166 12 235 166 +0 0 175 225 21 0 0 175 255 255 225 21 0 0 0 0 0 138 225 21 0 0 12 0 235 +125 0 0 0 59 245 125 0 138 247 34 0 138 225 21 0 0 175 201 0 138 201 12 +232 89 12 235 125 0 0 0 12 235 251 89 0 0 0 0 89 255 255 125 0 0 0 0 0 +138 247 34 0 0 7 206 125 0 0 0 0 12 232 89 0 0 0 0 12 235 125 7 206 201 +0 0 0 0 138 251 89 0 0 0 0 0 0 0 127 7 228 34 89 225 21 0 12 228 34 12 +228 0 0 138 225 21 0 138 225 21 12 0 235 166 0 0 12 235 201 0 138 225 21 +0 0 0 0 0 12 0 235 166 0 0 0 0 89 247 34 12 235 166 0 0 0 0 0 12 235 166 +0 0 0 0 0 138 225 21 0 12 235 255 255 127 12 235 166 0 0 0 12 235 125 0 +12 235 125 0 0 0 0 0 138 225 21 12 235 229 216 225 21 0 0 12 0 235 166 +0 0 0 0 12 235 125 12 235 223 201 0 175 225 21 12 235 125 0 138 225 34 +235 125 138 225 21 0 0 0 0 12 235 166 12 235 255 255 255 247 34 0 138 225 +21 0 0 0 0 12 235 166 12 235 255 255 255 166 0 0 0 0 0 0 89 255 255 247 +34 0 0 0 138 225 21 0 0 12 0 235 125 0 0 0 59 245 125 0 59 245 125 7 206 +166 0 0 0 89 247 34 175 125 7 206 125 89 247 34 0 0 0 12 235 251 89 0 0 +0 0 7 206 225 21 0 0 0 0 59 245 125 0 0 0 7 206 125 0 0 0 0 0 175 166 0 +0 0 0 12 235 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 12 228 34 89 225 +21 0 12 228 34 59 215 0 7 206 255 255 255 255 251 89 12 0 235 166 0 0 0 +138 247 0 124 247 34 0 0 0 0 0 12 0 235 166 0 0 0 0 138 225 21 12 235 166 +0 0 0 0 0 12 235 166 0 0 0 0 0 89 247 34 0 0 0 0 175 127 12 235 166 0 0 +0 12 235 125 0 12 235 125 0 0 0 0 0 138 225 21 12 235 166 59 245 201 0 +0 12 0 235 166 0 0 0 0 12 235 125 0 138 251 89 0 175 225 21 12 235 125 +0 12 235 138 235 125 89 247 34 0 0 0 0 59 245 125 12 235 166 0 0 0 0 0 +89 247 34 0 0 0 0 59 245 125 12 235 166 0 175 247 34 0 0 0 0 0 0 0 59 245 +166 0 0 0 138 225 21 0 0 12 0 235 125 0 0 0 59 241 89 0 7 206 201 59 241 +89 0 0 0 59 241 102 232 89 0 138 201 138 225 21 0 0 0 175 201 175 225 21 +0 0 0 0 175 225 21 0 0 0 7 206 201 0 0 0 0 7 206 125 0 0 0 0 0 89 225 21 +0 0 0 12 235 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 12 232 89 59 241 +89 0 89 247 34 89 201 0 59 241 89 0 0 7 206 166 12 0 235 166 0 0 0 138 +225 0 81 245 166 0 0 0 0 0 12 0 235 166 0 0 0 12 235 166 0 12 235 166 0 +0 0 0 0 12 235 166 0 0 0 0 0 12 235 166 0 0 0 0 175 127 12 235 166 0 0 +0 12 235 125 0 12 235 125 0 0 0 0 0 138 225 21 12 235 166 0 89 255 166 +0 12 0 235 166 0 0 0 0 12 235 125 0 12 182 0 0 175 225 21 12 235 125 0 +0 138 232 245 125 12 235 125 0 0 0 0 138 247 34 12 235 166 0 0 0 0 0 12 +235 125 0 0 0 0 138 247 34 12 235 166 0 7 206 225 21 0 0 0 0 0 0 12 235 +166 0 0 0 138 225 21 0 0 12 0 235 166 0 0 0 89 251 89 0 0 138 247 163 225 +21 0 0 0 7 206 200 215 21 0 89 225 187 166 0 0 0 89 251 89 12 235 166 0 +0 0 0 175 225 21 0 0 0 138 247 34 0 0 0 0 7 206 125 0 0 0 0 0 12 232 89 +0 0 0 12 235 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 12 175 166 0 89 +255 255 210 235 255 255 125 0 138 225 21 0 0 0 138 247 47 0 235 166 0 0 +59 245 166 0 0 138 255 125 0 0 7 202 102 0 235 166 0 0 12 235 225 21 0 +12 235 166 0 0 0 0 0 12 235 166 0 0 0 0 0 0 138 255 125 0 0 0 175 127 12 +235 166 0 0 0 12 235 125 0 12 235 125 0 0 0 0 7 206 201 0 12 235 166 0 +0 138 255 125 12 0 235 166 0 0 0 12 0 235 125 0 0 0 0 0 175 225 21 12 235 +125 0 0 12 235 255 125 0 89 255 125 0 0 89 251 89 0 12 235 166 0 0 0 0 +0 0 89 255 125 0 0 89 255 125 0 12 235 166 0 0 12 235 201 0 138 166 0 0 +0 138 251 89 0 0 0 138 225 21 0 0 0 0 138 247 34 0 7 206 225 21 0 0 12 +235 255 166 0 0 0 0 0 175 255 201 0 0 12 235 255 125 0 0 12 235 166 0 0 +138 251 89 0 0 0 175 225 21 0 0 89 251 89 0 0 0 0 0 7 206 125 0 0 0 0 0 +0 175 166 0 0 0 12 235 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 59 241 +89 0 0 0 0 0 0 0 0 7 206 166 0 0 0 0 59 245 138 0 235 255 255 255 255 125 +0 0 0 0 59 245 255 255 255 201 12 0 235 255 255 255 255 166 0 0 0 12 235 +255 255 255 255 255 127 12 235 166 0 0 0 0 0 0 0 59 245 255 255 255 225 +21 12 235 166 0 0 0 12 235 125 89 255 255 255 210 127 235 255 255 225 21 +0 12 235 166 0 0 0 175 255 127 0 235 255 255 255 247 47 0 235 125 0 0 0 +0 0 175 225 21 12 235 125 0 0 0 138 255 125 0 0 0 175 255 255 201 0 0 0 +12 235 166 0 0 0 0 0 0 0 0 175 255 255 201 0 0 0 12 235 166 0 0 0 89 255 +225 34 235 255 255 255 247 34 0 0 0 0 138 225 21 0 0 0 0 0 138 255 255 +255 201 0 0 0 0 0 175 251 89 0 0 0 0 0 89 255 166 0 0 7 206 247 34 0 7 +206 225 21 0 0 7 206 225 21 0 0 175 225 21 0 0 138 255 255 255 255 255 +255 166 7 206 125 0 0 0 0 0 0 138 201 0 0 0 12 235 125 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 127 0 0 89 255 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 201 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 7 206 125 0 0 0 0 0 0 59 238 34 0 0 12 235 125 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 127 0 0 0 7 206 255 255 255 225 21 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 251 89 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 7 206 125 0 0 0 0 0 0 7 206 125 0 0 12 235 125 0 0 0 +0 0 0 0 0 0 0 245 255 255 255 255 255 255 127 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 +255 255 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 255 255 201 0 0 0 0 0 0 89 89 255 255 +255 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 127 127 127 127 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 +127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 +0 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 127 0 127 127 127 127 127 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 +127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 59 245 166 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 89 247 34 0 0 0 0 0 0 0 0 0 0 12 235 +125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 225 21 0 0 0 0 0 0 0 0 0 12 235 +255 247 0 0 0 0 0 0 0 12 12 235 125 0 0 0 0 0 0 0 0 0 0 0 0 12 235 125 +0 0 0 0 0 12 235 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 255 251 89 0 7 206 125 0 89 255 251 89 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 255 255 255 255 255 255 255 255 255 255 +125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 127 0 0 7 206 125 0 0 0 0 0 0 0 0 0 0 12 235 125 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 138 225 21 0 0 0 0 0 0 0 0 0 175 201 0 0 0 0 0 0 +0 0 0 12 12 235 125 0 0 0 0 0 59 245 102 0 89 247 34 12 235 125 0 0 0 0 +0 12 235 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 125 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 59 241 89 0 0 0 7 206 125 0 0 0 138 225 21 0 +0 0 0 0 0 0 0 0 0 0 0 0 89 201 0 0 0 0 0 0 0 0 175 125 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 12 235 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 +225 21 0 0 0 0 0 0 0 12 0 235 125 0 0 0 0 0 0 0 0 0 0 12 235 125 0 0 0 +0 0 0 0 0 0 0 0 0 12 235 125 0 0 0 0 0 12 235 125 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 12 235 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 247 34 +0 0 0 7 206 125 0 0 0 59 238 34 0 0 0 0 0 0 0 0 0 0 0 0 0 89 201 0 0 0 +0 0 0 0 0 175 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 12 235 255 255 255 166 0 12 +235 166 245 255 247 34 0 0 12 235 255 255 247 34 0 34 235 255 255 255 225 +21 0 12 235 255 255 225 29 0 206 255 255 255 127 0 12 235 255 255 255 225 +21 12 235 138 235 255 247 34 0 12 235 102 175 255 247 34 12 235 125 0 59 +245 201 0 12 235 125 12 0 235 166 245 255 225 29 206 255 251 89 0 12 235 +138 235 255 247 34 0 0 12 235 255 255 201 0 0 12 235 166 245 255 251 89 +0 0 12 235 255 255 255 225 21 12 235 138 235 247 127 34 138 255 255 255 +206 0 206 255 255 255 201 59 241 89 0 0 89 247 42 206 201 0 0 0 138 225 +187 201 0 0 138 225 21 0 59 241 187 226 247 34 0 7 206 206 206 201 0 0 +0 138 225 151 255 255 255 255 247 0 0 89 247 34 0 0 0 7 206 125 0 0 0 59 +238 34 0 0 0 0 0 0 0 0 0 0 0 0 0 89 201 0 0 0 0 0 0 0 0 175 125 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +0 0 0 0 0 0 0 0 12 206 21 0 59 245 125 12 235 247 34 0 138 225 21 12 235 +166 0 0 134 102 0 235 166 0 0 138 225 21 12 235 125 0 0 175 201 12 0 235 +125 0 0 12 235 166 0 0 138 225 21 12 235 247 34 0 175 201 0 12 235 102 +0 89 247 34 12 235 125 12 235 166 0 0 12 235 125 12 0 235 225 21 12 235 +251 89 0 175 201 0 12 235 247 34 0 175 201 0 12 235 166 0 7 206 201 0 12 +235 225 21 0 175 225 21 12 235 166 0 0 138 225 21 12 235 247 34 0 0 89 +247 34 0 12 206 34 0 235 125 0 0 59 241 89 0 0 89 247 34 89 247 34 0 7 +206 166 138 225 21 7 206 251 89 0 89 225 138 34 235 201 0 138 225 21 89 +247 34 0 7 206 166 0 0 0 7 206 166 0 0 89 225 21 0 0 0 7 206 125 0 0 0 +59 241 89 0 0 0 0 138 251 89 0 0 7 202 89 0 89 201 0 0 0 0 0 0 0 0 175 +125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 7 206 102 12 235 125 0 0 59 241 89 +138 225 21 0 0 0 34 89 225 21 0 0 138 225 21 89 225 21 0 0 89 247 47 0 +235 125 0 0 89 225 21 0 0 138 225 21 12 235 125 0 0 89 247 34 12 235 102 +0 89 247 34 12 235 138 235 166 0 0 0 12 235 125 12 0 235 125 0 7 206 166 +0 0 138 225 21 12 235 125 0 0 89 247 34 138 225 21 0 0 59 238 34 12 235 +125 0 0 59 241 89 89 225 21 0 0 138 225 21 12 235 125 0 0 0 138 225 21 +0 0 0 12 0 235 125 0 0 59 241 89 0 0 89 247 34 12 235 125 0 59 241 89 59 +238 34 12 228 198 166 0 175 166 59 0 89 251 132 241 89 0 12 235 125 0 59 +238 34 0 0 0 138 225 21 0 12 235 166 0 0 0 0 7 206 125 0 0 0 0 175 201 +0 0 0 138 166 12 235 166 0 12 232 89 0 89 201 0 0 0 0 0 0 0 0 175 125 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 127 0 0 0 0 0 0 0 0 0 59 245 255 255 255 102 12 235 125 0 0 12 235 +125 175 201 0 0 0 0 0 175 201 0 0 0 138 225 21 175 255 255 255 255 255 +247 47 0 235 125 0 0 175 201 0 0 0 138 225 21 12 235 125 0 0 89 247 34 +12 235 102 0 89 247 34 12 235 255 225 21 0 0 0 12 235 125 12 0 235 125 +0 7 206 166 0 0 138 225 21 12 235 125 0 0 89 247 34 175 201 0 0 0 12 232 +89 12 235 125 0 0 12 235 125 175 201 0 0 0 138 225 21 12 235 125 0 0 0 +59 245 255 247 34 0 12 0 235 125 0 0 59 241 89 0 0 89 247 34 0 175 201 +0 138 201 0 12 235 125 89 201 89 225 29 206 125 12 0 0 175 255 166 0 0 +0 175 201 0 138 201 0 0 0 89 251 89 0 138 247 34 0 0 0 0 0 7 206 125 0 +0 0 0 0 89 255 125 7 202 89 0 89 251 89 89 201 0 0 89 201 0 0 0 0 0 0 0 +0 175 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 89 255 166 0 7 206 102 12 235 125 0 +0 12 235 125 175 201 0 0 0 0 0 175 201 0 0 0 138 225 21 175 201 0 0 0 0 +0 12 0 235 125 0 0 175 201 0 0 0 138 225 21 12 235 125 0 0 89 247 34 12 +235 102 0 89 247 34 12 235 138 235 201 0 0 0 12 235 125 12 0 235 125 0 +7 206 166 0 0 138 225 21 12 235 125 0 0 89 247 34 175 201 0 0 0 12 232 +89 12 235 125 0 0 12 235 125 175 201 0 0 0 138 225 21 12 235 125 0 0 0 +0 0 138 255 255 201 12 0 235 125 0 0 59 241 89 0 0 89 247 34 0 89 247 42 +206 125 0 0 175 166 175 125 12 232 102 232 89 0 0 0 175 255 201 0 0 0 89 +247 47 235 125 0 0 12 235 166 0 0 0 12 235 125 0 0 0 0 7 206 125 0 0 0 +0 138 201 0 0 12 232 89 0 0 59 245 225 21 0 0 89 201 0 0 0 0 0 0 0 0 175 +125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 127 0 0 0 0 0 0 0 0 175 201 0 0 7 206 102 12 235 125 0 0 59 241 +89 138 225 21 0 0 0 34 89 225 21 0 0 138 225 21 138 247 34 0 0 0 0 12 0 +235 125 0 0 138 225 21 0 0 138 225 21 12 235 125 0 0 89 247 34 12 235 102 +0 89 247 34 12 235 125 59 245 125 0 0 12 235 125 12 0 235 125 0 7 206 166 +0 0 138 225 21 12 235 125 0 0 89 247 34 138 225 21 0 0 89 247 34 12 235 +125 0 0 59 241 89 138 225 21 0 0 138 225 21 12 235 125 0 0 0 0 0 0 0 89 +247 47 0 235 125 0 0 59 241 89 0 0 89 247 34 0 12 235 166 238 34 0 0 138 +210 228 34 0 175 166 215 21 0 0 89 251 159 251 89 0 0 12 235 191 247 34 +0 0 175 225 21 0 0 0 0 138 225 21 0 0 0 7 206 125 0 0 0 12 232 89 0 0 0 +0 0 0 0 0 0 0 0 0 0 89 201 0 0 0 0 0 0 0 0 175 125 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 +0 0 0 138 225 21 0 138 255 102 12 235 125 0 7 206 201 0 12 235 166 0 0 +134 132 0 245 125 0 59 245 225 21 12 235 201 0 0 12 206 34 0 235 125 0 +0 59 245 125 0 12 235 225 21 12 235 125 0 0 89 247 34 12 235 102 0 89 247 +34 12 235 125 0 138 251 89 0 12 235 125 12 0 235 125 0 7 206 166 0 0 138 +225 21 12 235 125 0 0 89 247 34 12 235 166 0 7 206 201 0 12 235 125 0 7 +206 201 0 59 245 125 0 12 235 225 21 12 235 125 0 0 0 138 125 0 0 138 225 +29 0 206 166 0 0 7 206 166 0 59 245 247 34 0 0 175 255 201 0 0 0 59 245 +225 21 0 89 255 201 0 0 12 235 166 0 175 225 21 0 0 138 255 166 0 0 89 +251 89 0 0 0 0 0 89 247 34 0 0 0 7 206 125 0 0 0 59 238 34 0 0 0 0 0 0 +0 0 0 0 0 0 0 89 201 0 0 0 0 0 0 0 0 175 125 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 +7 206 255 255 171 206 102 12 232 226 255 255 225 21 0 0 12 235 255 255 +247 34 0 89 255 255 247 163 225 21 0 7 206 255 255 247 34 12 0 235 125 +0 0 0 89 255 255 247 163 225 21 12 235 125 0 0 89 247 34 12 235 102 0 89 +247 34 12 235 125 0 0 175 251 34 0 235 125 12 0 235 125 0 7 206 166 0 0 +138 225 21 12 235 125 0 0 89 247 34 0 12 235 255 255 201 0 0 12 235 255 +255 255 225 21 0 0 89 255 255 247 163 225 21 12 235 125 0 0 0 89 255 255 +255 247 34 0 0 89 255 255 127 0 59 245 255 225 111 247 34 0 0 59 245 125 +0 0 0 12 235 166 0 0 59 245 125 7 0 206 225 21 0 12 235 201 0 0 59 241 +89 0 0 175 255 255 255 255 247 0 0 89 247 34 0 0 0 7 206 125 0 0 0 59 238 +34 0 0 0 0 0 0 0 0 0 0 0 0 0 89 255 255 255 255 255 255 255 255 255 255 +125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 201 0 0 0 0 0 +0 0 0 0 0 0 0 0 89 247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 125 0 0 0 0 0 0 0 0 0 0 138 225 +21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 225 21 0 0 0 0 0 0 0 0 0 0 89 +247 34 0 0 0 7 206 125 0 0 0 59 238 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 199 34 0 12 +232 89 0 0 0 0 0 0 0 0 0 0 0 0 0 138 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 125 0 0 0 0 +0 0 0 0 0 0 138 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 166 0 0 0 +0 0 0 0 0 0 0 0 12 235 125 0 0 0 7 206 125 0 0 0 138 225 21 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 12 235 255 247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 255 251 89 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 12 235 125 0 0 0 0 0 0 0 0 0 0 138 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 89 247 34 0 0 0 0 0 0 0 0 0 0 0 0 89 255 251 89 0 7 206 125 0 89 255 +247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 0 127 127 127 127 0 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 0 127 127 0 127 127 127 0 127 127 127 127 127 127 +127 0 127 127 127 0 127 127 127 127 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 +127 127 127 0 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 +127 127 127 0 127 127 127 127 127 127 127 127 127 127 0 127 127 127 127 +127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 +127 127 127 0 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 127 127 127 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 125 0 175 166 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 206 125 0 175 +166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 245 225 21 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 255 125 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 255 125 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 166 0 138 201 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 166 0 138 201 0 7 206 166 12 235 +125 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 125 0 0 0 0 0 175 125 +0 0 0 0 0 175 171 206 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 255 125 0 +31 206 130 255 166 175 247 34 0 0 89 255 125 175 247 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 245 247 34 138 166 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 59 241 132 238 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 59 241 132 238 34 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 +59 245 255 255 255 125 0 12 235 255 255 255 255 255 225 21 0 0 0 0 0 0 +0 0 175 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 125 0 0 0 +0 0 175 125 0 0 0 0 89 225 21 59 238 34 0 0 138 255 255 201 0 0 0 59 215 +21 0 0 0 0 0 0 0 0 0 12 235 255 255 255 247 34 0 0 0 0 0 0 0 12 235 255 +255 255 255 255 255 255 255 251 89 0 12 235 255 255 255 255 255 225 21 +0 89 255 255 255 255 255 255 125 0 12 235 255 255 255 255 255 225 21 0 +0 12 235 255 255 255 255 255 225 21 7 206 201 0 50 206 56 255 201 12 235 +125 0 0 138 225 29 206 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 7 202 89 89 255 225 21 0 89 255 255 255 225 81 245 201 0 138 251 +89 0 0 138 255 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 255 255 +255 255 255 225 21 0 0 0 138 255 166 7 206 225 21 0 0 0 138 247 34 0 0 +0 0 127 0 89 255 125 0 0 0 0 0 12 146 0 0 0 0 0 144 21 0 0 0 0 0 0 0 89 +247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 125 0 0 0 0 0 175 +125 0 0 0 0 0 0 0 0 0 0 0 59 241 89 12 235 125 0 0 172 89 0 0 0 0 0 0 0 +0 0 12 235 166 0 0 7 202 89 0 0 0 0 0 0 89 255 201 0 0 12 235 125 0 0 0 +0 0 0 12 146 0 0 0 0 0 144 21 0 0 0 0 0 0 138 247 34 0 12 146 0 0 0 0 0 +144 21 0 0 12 146 0 0 0 0 0 144 21 0 89 225 21 71 157 22 191 225 21 175 +201 0 7 206 125 59 238 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 175 125 0 59 196 199 47 206 184 89 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 146 0 0 0 0 0 144 21 0 0 0 0 +0 0 0 59 245 125 0 0 59 245 125 0 0 0 0 0 127 12 235 166 0 0 0 0 0 0 12 +146 0 0 0 0 0 144 21 0 0 0 0 0 0 0 175 201 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 12 235 255 255 255 255 127 34 235 255 255 255 255 225 21 0 +0 0 0 0 0 0 0 89 247 34 7 206 166 0 89 201 0 0 0 0 0 0 0 0 0 0 89 247 34 +0 0 0 0 0 0 0 0 59 115 12 235 166 0 0 0 12 235 125 0 0 0 0 0 0 12 146 0 +0 0 0 0 144 21 0 0 0 0 0 59 245 125 0 0 12 146 0 0 0 0 0 144 21 0 0 12 +146 0 0 0 0 0 144 21 0 7 202 89 117 104 0 29 202 89 59 215 21 59 215 21 +138 201 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 175 125 0 59 192 89 223 125 172 89 0 138 255 255 255 201 12 182 +0 0 0 0 0 175 255 255 125 0 89 255 255 247 34 0 0 12 146 0 0 0 0 0 144 +21 0 138 255 255 255 255 247 34 138 247 34 7 206 201 0 0 0 0 0 0 127 89 +251 89 0 0 0 0 0 0 12 146 0 0 0 0 0 144 21 0 0 0 0 0 0 7 206 166 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 125 0 0 0 0 0 175 125 0 0 0 +0 0 0 0 0 0 0 0 89 247 34 7 206 166 7 202 89 0 0 0 0 0 0 0 0 0 0 89 255 +125 0 0 0 0 0 0 0 89 255 125 89 247 34 0 0 0 12 235 125 0 0 0 0 0 0 12 +146 0 0 0 0 0 144 21 0 0 0 0 7 206 201 0 0 0 12 146 0 0 0 0 0 144 21 0 +0 12 146 0 0 0 0 0 144 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 245 +255 201 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 +125 0 59 192 12 228 34 172 89 89 247 34 0 12 206 29 206 201 0 0 7 206 166 +0 7 206 255 225 21 0 89 247 34 0 12 146 0 0 0 0 0 144 21 0 0 0 0 7 206 +166 0 12 235 166 89 247 34 0 0 0 0 0 0 127 245 255 255 255 255 255 201 +0 0 12 146 0 0 0 0 0 144 21 0 0 0 0 0 59 245 255 255 255 127 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 125 0 0 0 0 0 175 125 0 0 0 0 0 0 0 +0 0 0 0 59 241 89 12 235 125 89 201 12 235 255 251 89 0 89 255 255 225 +21 0 175 255 255 225 21 0 0 0 89 251 89 0 138 225 21 0 0 0 12 235 255 255 +255 255 225 21 0 12 146 0 0 0 0 0 144 21 0 0 0 0 138 247 34 0 0 0 12 146 +0 0 0 0 0 144 21 0 0 12 146 0 0 0 0 0 144 21 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 12 235 255 255 255 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 175 125 0 59 192 0 0 0 172 89 138 225 21 0 0 0 +0 7 206 225 21 138 225 21 0 0 89 251 89 0 0 12 235 125 0 12 146 0 0 0 0 +0 144 21 0 0 0 0 138 225 21 0 0 89 255 255 125 0 0 0 0 0 0 0 127 138 225 +21 0 0 0 0 0 0 12 146 0 0 0 0 0 144 21 0 0 0 0 0 0 59 241 89 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 125 0 0 12 235 255 255 255 255 +225 21 0 0 0 0 0 0 0 0 0 138 255 255 201 12 228 34 175 166 0 138 201 7 +206 125 7 206 166 0 0 0 89 255 255 247 34 59 241 89 0 0 138 225 21 0 0 +0 12 235 125 0 0 0 0 0 0 12 146 0 0 0 0 0 144 21 0 0 0 59 245 125 0 0 0 +0 12 146 0 0 0 0 0 144 21 0 0 12 146 0 0 0 0 0 144 21 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 59 245 255 255 255 207 235 255 255 255 255 255 255 +207 235 255 255 255 255 255 255 255 255 255 255 255 225 21 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 59 245 255 247 34 0 0 0 0 175 166 175 201 0 0 0 +59 245 255 255 255 255 255 125 0 12 146 0 0 0 0 0 144 21 0 0 0 89 251 89 +0 0 0 7 206 225 21 0 0 0 0 0 0 0 127 245 255 255 255 255 255 125 0 0 12 +146 0 0 0 0 0 144 21 0 0 0 0 0 0 59 241 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 175 125 0 0 0 0 0 175 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 138 166 7 206 125 0 89 247 94 241 89 0 138 201 0 0 0 0 0 59 245 166 +0 89 251 89 0 89 247 34 0 0 0 12 235 125 0 0 0 0 0 0 12 146 0 0 0 0 0 144 +21 0 0 7 206 201 0 0 0 0 0 12 146 0 0 0 0 0 144 21 0 0 12 146 0 0 0 0 0 +144 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 255 255 255 166 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 138 255 255 201 0 7 206 225 21 175 201 0 0 0 59 241 89 0 0 0 0 +0 0 12 146 0 0 0 0 0 144 21 0 0 12 235 166 0 0 0 0 0 175 225 21 0 0 0 0 +0 0 0 127 89 255 125 0 0 0 0 0 0 12 146 0 0 0 0 0 144 21 0 0 0 0 0 0 89 +247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 125 0 0 0 0 0 +175 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 228 34 7 206 125 0 89 247 94 241 +89 0 138 201 0 0 0 0 0 12 235 166 0 0 89 255 125 12 235 166 0 0 0 12 235 +125 0 0 0 0 0 0 12 146 0 0 0 0 0 144 21 0 0 138 247 34 0 0 0 0 0 12 146 +0 0 0 0 0 144 21 0 0 12 146 0 0 0 0 0 144 21 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 59 245 255 201 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 247 42 206 201 0 0 89 +225 21 0 0 89 255 125 0 0 0 0 0 0 12 146 0 0 0 0 0 144 21 0 0 175 225 21 +0 0 0 0 0 175 225 21 0 0 0 0 0 0 0 127 0 175 251 89 0 0 0 0 0 12 146 0 +0 0 0 0 144 21 0 59 245 166 0 0 138 225 21 0 0 0 59 245 166 138 251 89 +7 206 201 0 12 235 125 0 59 241 89 0 0 0 175 125 0 0 0 0 0 175 125 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 138 166 0 0 175 166 0 138 201 7 206 125 7 206 +166 138 166 0 0 0 138 251 89 0 0 0 59 115 0 89 255 201 0 0 12 235 125 0 +0 0 0 0 0 12 146 0 0 0 0 0 144 21 0 89 251 89 0 0 0 0 0 0 12 146 0 0 0 +0 0 144 21 0 0 12 146 0 0 0 0 0 144 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 138 125 0 0 138 225 34 182 0 0 0 7 206 166 0 +7 206 255 247 34 0 0 175 125 0 12 146 0 0 0 0 0 144 21 0 89 251 89 0 0 +0 0 0 0 175 225 21 0 0 0 0 0 0 0 127 0 0 138 255 255 255 255 125 0 12 235 +255 255 255 255 255 225 21 0 138 247 34 0 7 206 166 0 0 0 0 89 247 34 175 +201 0 7 206 201 0 12 235 125 0 59 241 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 59 215 21 0 0 12 235 255 251 89 0 89 255 255 225 +21 12 235 255 255 255 247 34 0 0 0 0 0 0 0 0 12 235 255 255 255 255 255 +255 255 255 251 89 0 12 235 255 255 255 255 255 225 21 0 138 255 255 255 +255 255 255 166 0 12 235 255 255 255 255 255 225 21 0 0 12 235 255 255 +255 255 255 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 89 255 255 255 247 34 0 0 0 0 0 0 0 175 255 255 125 0 138 255 255 +255 125 0 0 12 235 255 255 255 255 255 225 21 0 175 255 255 255 255 247 +0 0 0 175 225 21 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 175 166 0 255 255 201 0 0 0 0 0 175 166 12 232 89 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 +228 34 0 0 0 0 0 0 0 0 12 232 89 59 215 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 +127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 +127 127 127 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 +127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +127 127 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +0 127 127 127 127 0 127 127 127 127 127 127 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +127 0 127 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 +127 127 0 127 127 127 0 127 127 0 127 127 127 127 127 0 127 127 127 127 +127 0 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 +127 127 127 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 +0 127 127 127 127 127 127 127 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 127 +127 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 245 255 255 255 255 255 255 225 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 225 21 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 7 206 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 89 247 +34 0 0 0 0 59 192 0 0 0 0 0 7 206 255 255 225 21 0 0 0 0 0 0 0 0 138 247 +34 0 0 89 251 89 0 7 206 125 0 0 7 206 255 255 255 166 0 89 251 89 138 +247 34 0 0 0 0 7 206 255 255 255 247 34 0 0 0 0 175 255 255 251 89 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 255 255 255 247 +34 0 0 0 0 0 0 0 0 0 0 0 0 89 255 255 247 34 0 0 0 0 0 0 0 0 0 0 0 0 12 +235 255 247 34 0 0 7 206 255 251 89 0 0 7 206 125 0 0 0 0 0 0 0 0 0 0 0 +0 89 255 255 255 255 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 202 89 0 0 0 +59 245 255 247 34 0 0 0 0 0 0 0 0 0 0 0 89 201 0 0 0 0 175 166 0 0 0 0 +0 0 89 201 0 0 0 0 175 166 0 0 0 0 0 59 245 255 201 0 0 0 59 241 89 0 0 +0 0 0 59 245 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 89 247 34 +0 0 0 0 59 192 0 0 0 0 0 175 201 0 0 144 21 0 0 0 0 0 0 0 0 7 206 166 0 +7 206 166 0 0 7 206 125 0 7 206 201 0 0 89 166 0 0 0 0 0 0 0 0 0 0 89 255 +125 0 0 0 59 245 166 0 0 0 0 0 0 12 206 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 89 255 125 0 0 0 59 245 166 0 0 0 0 0 0 0 0 0 0 59 +241 89 0 138 201 0 0 0 0 0 138 166 0 0 0 0 0 168 34 7 206 166 0 0 172 89 +0 175 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 255 255 255 166 89 225 21 +0 0 0 0 0 0 0 0 0 0 0 0 0 89 255 251 89 0 0 12 235 125 0 138 225 21 0 0 +0 0 0 0 0 0 7 206 255 201 0 0 0 89 225 21 0 0 0 0 7 206 255 201 0 0 0 89 +225 21 0 0 0 0 12 206 21 12 235 125 0 0 175 166 0 0 0 0 0 0 59 245 125 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 175 255 255 255 +166 0 0 12 235 125 0 0 0 0 89 225 21 0 0 12 232 89 0 89 247 34 89 247 34 +0 0 7 206 125 0 12 235 125 0 0 0 0 0 0 0 0 0 0 0 0 0 89 225 21 0 0 0 0 +0 7 206 125 0 0 7 206 255 255 247 34 0 0 0 85 89 0 85 89 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 89 225 21 0 0 0 0 0 7 206 125 0 0 0 0 0 0 0 0 0 89 201 +0 0 12 228 34 0 0 0 0 138 166 0 0 0 0 0 0 0 7 206 125 0 0 7 206 255 166 +0 0 0 0 0 0 0 0 0 12 235 125 0 0 89 247 34 175 255 255 255 166 89 225 21 +0 89 255 125 0 0 0 0 0 0 0 0 0 0 7 202 89 0 0 89 225 21 0 12 232 89 59 +115 0 59 115 0 0 0 0 0 89 201 0 0 7 206 125 0 0 0 0 0 0 0 89 201 0 0 7 +206 125 0 0 0 0 0 0 0 0 12 232 89 0 59 238 34 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 89 225 21 0 0 138 247 94 192 12 182 +0 0 12 235 125 0 0 0 0 0 175 255 255 255 255 166 0 0 7 206 171 206 166 +0 0 0 7 206 125 0 7 206 251 89 0 0 0 0 0 0 0 0 0 0 0 7 202 89 0 59 245 +255 255 201 0 12 228 34 12 235 166 0 12 228 34 0 0 138 251 89 138 247 34 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 202 89 0 138 255 255 255 125 0 12 228 34 +0 0 0 0 0 0 0 0 59 241 89 0 138 201 0 0 0 0 0 138 166 0 0 0 0 0 0 0 175 +201 0 0 0 0 0 0 175 201 0 0 0 0 0 0 0 0 12 235 125 0 0 89 247 34 175 255 +255 255 166 89 225 21 0 89 255 125 0 0 0 0 0 0 0 0 0 0 7 202 89 0 0 138 +225 21 0 12 235 125 12 235 166 59 245 166 0 0 0 0 89 201 0 0 89 225 21 +0 0 0 0 0 0 0 89 201 0 0 89 225 21 0 0 0 0 0 0 12 235 255 125 0 0 175 125 +0 0 0 0 0 0 0 12 235 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 89 +225 21 0 12 235 125 59 192 0 0 0 0 12 235 125 0 0 0 0 0 59 215 21 59 238 +34 0 0 0 89 255 247 34 0 0 0 7 206 125 0 0 7 206 255 255 247 34 0 0 0 0 +0 0 0 0 59 192 0 12 235 166 0 7 176 21 0 175 125 59 238 34 0 12 228 34 +0 138 247 34 138 247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 192 0 0 138 +201 0 89 247 34 0 175 125 0 0 0 0 0 0 0 0 0 89 255 255 225 21 0 7 206 255 +255 255 255 255 255 247 34 0 12 235 125 0 0 0 7 176 21 0 175 201 0 0 0 +0 0 0 0 0 12 235 125 0 0 89 247 34 89 255 255 255 166 89 225 21 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 7 202 89 0 0 89 225 21 0 12 232 89 0 12 235 166 12 +235 166 0 0 0 89 201 0 7 206 125 0 12 235 166 0 0 0 0 89 201 0 7 206 125 +89 255 255 255 125 0 0 0 0 7 206 125 89 225 21 0 138 225 21 0 0 0 138 255 +125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 89 247 34 0 59 241 89 59 +192 0 0 0 12 235 255 255 255 225 21 0 0 138 166 0 7 202 89 0 0 0 7 206 +166 0 0 0 0 0 0 0 0 7 206 125 0 12 235 201 0 0 0 0 0 0 0 0 89 166 0 89 +247 34 0 0 0 0 0 89 166 12 232 89 0 138 247 34 89 247 34 59 238 34 0 0 +12 235 255 255 255 255 255 255 247 34 89 255 255 255 166 89 166 0 0 138 +201 0 138 225 21 0 89 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 166 +0 0 0 0 7 206 255 255 255 247 34 0 59 245 255 247 34 0 0 0 0 0 0 0 0 12 +235 125 0 0 89 247 34 0 89 255 255 166 89 225 21 0 0 0 0 0 0 0 0 0 0 0 +0 0 89 255 255 255 166 0 12 235 125 0 138 225 21 0 0 12 235 125 12 235 +125 0 0 89 201 0 89 201 0 7 206 223 166 0 0 0 0 89 201 0 89 201 0 89 125 +0 138 225 21 12 182 0 7 206 133 206 125 0 89 232 215 21 0 7 206 247 34 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 89 247 34 0 59 241 89 59 +192 0 0 0 0 12 235 125 0 0 0 0 0 59 215 21 59 238 34 0 59 245 255 255 255 +255 225 21 0 0 0 0 0 59 241 89 0 0 138 225 21 0 0 0 0 0 0 0 89 166 0 89 +247 34 0 0 0 0 0 89 166 0 138 255 255 176 228 34 0 138 247 34 138 247 34 +0 0 0 0 0 0 0 0 59 238 34 0 0 0 0 0 89 166 0 0 138 255 255 225 21 0 0 89 +166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 166 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 125 0 0 89 247 34 0 0 0 138 166 89 225 +21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 245 255 247 34 0 0 12 235 +166 12 235 166 0 0 0 0 0 12 232 89 0 175 166 138 166 0 0 0 0 0 0 12 232 +89 0 0 0 0 138 201 0 0 89 255 255 201 89 225 21 89 225 81 215 21 0 138 +247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 89 247 34 0 12 235 +125 59 192 0 0 0 0 59 241 89 0 0 0 0 0 175 255 255 255 255 166 0 0 0 7 +206 166 0 0 0 0 7 206 125 0 12 235 201 0 7 206 166 0 0 0 0 0 0 0 0 59 192 +0 12 235 166 0 7 176 21 0 175 125 0 0 0 0 0 0 0 0 0 138 251 89 138 247 +34 0 0 0 0 0 0 0 59 238 34 0 0 0 0 0 59 192 0 0 138 201 59 245 166 0 0 +175 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 166 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 125 0 0 89 247 34 0 0 0 138 166 +89 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 166 +59 245 166 0 0 0 0 0 0 138 201 0 138 201 0 138 166 0 0 0 0 0 0 138 201 +0 0 0 0 89 247 34 0 0 0 0 0 7 206 125 59 238 34 59 215 21 0 175 225 21 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 89 247 34 0 0 175 225 81 +192 12 182 0 7 206 125 0 0 0 0 0 89 225 21 0 0 12 232 89 0 0 7 206 166 +0 0 0 0 7 206 125 0 0 59 245 255 255 166 0 0 0 0 0 0 0 0 0 7 202 89 0 59 +245 255 255 166 0 12 228 34 0 0 0 0 0 0 0 0 0 0 85 89 0 85 89 0 0 0 0 0 +0 0 59 238 34 0 0 0 0 0 7 202 89 0 138 201 0 59 245 225 34 228 34 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 7 206 255 255 255 255 255 255 247 34 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 201 0 0 175 247 34 0 0 0 138 166 +89 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 115 0 +59 115 0 0 0 0 0 0 12 232 89 0 175 255 255 255 255 201 0 0 0 0 12 232 89 +0 0 0 138 201 0 0 0 0 0 0 0 89 201 0 89 255 255 255 255 247 34 138 251 +89 0 7 176 21 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 138 247 34 0 0 0 +175 255 255 255 166 0 89 255 255 255 255 255 247 34 0 0 0 0 0 0 0 0 0 0 +7 206 166 0 0 0 0 7 206 125 0 0 0 0 0 138 255 166 0 0 0 0 0 0 0 0 0 89 +225 21 0 0 0 0 0 7 206 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 59 238 34 0 0 0 0 0 0 89 225 21 0 0 0 0 0 7 206 125 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 12 235 191 255 255 166 238 34 0 0 0 138 166 89 225 21 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 201 0 0 +0 0 0 138 166 0 0 0 0 0 175 201 0 0 0 89 255 255 255 255 125 0 0 0 12 232 +89 0 0 0 0 59 215 21 0 0 138 255 255 255 225 21 0 0 0 0 0 0 0 0 0 0 0 0 +0 127 0 0 0 0 0 0 0 0 0 0 0 0 59 192 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 7 206 125 0 0 0 0 0 0 175 201 0 0 0 0 0 0 0 0 0 0 +89 255 125 0 0 0 59 245 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 89 255 125 0 0 0 59 245 166 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 12 235 125 0 0 0 0 0 0 0 0 138 166 89 225 21 0 0 0 0 0 0 0 0 0 175 +125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 59 192 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 125 0 7 199 34 +0 12 235 125 0 0 0 0 0 0 0 0 0 0 0 7 206 255 255 255 247 34 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 255 255 +255 247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 125 0 0 0 0 0 0 0 0 138 166 +89 225 21 0 0 0 0 0 0 0 0 7 202 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 7 206 125 0 7 206 255 255 255 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 125 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 12 235 255 201 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +127 127 0 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +127 0 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 +127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 +0 127 127 127 127 0 127 127 127 127 127 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 0 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 +127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 +127 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 138 225 +21 0 0 0 0 0 12 235 125 0 0 0 0 19 172 255 190 11 0 0 0 0 138 255 201 7 +202 89 0 0 0 0 0 0 0 0 0 0 7 206 255 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 59 138 225 21 0 0 0 0 0 0 59 245 201 0 0 0 19 172 +255 190 11 0 0 0 0 0 0 0 0 0 7 206 225 21 0 0 0 59 245 201 19 172 255 190 +11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 251 89 89 201 0 0 0 0 0 175 +201 0 0 0 0 0 0 0 0 7 206 225 21 0 0 0 0 0 19 172 255 190 11 0 0 0 0 0 +175 255 166 12 228 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 89 255 125 0 0 0 0 0 0 0 12 175 247 34 0 0 0 19 172 255 +190 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 247 34 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 127 0 0 0 7 206 125 0 0 0 0 0 138 201 0 0 0 0 0 136 190 +45 196 145 0 0 0 59 215 21 175 255 166 0 0 0 175 225 29 206 166 0 0 7 202 +89 7 202 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 209 125 +0 0 0 0 0 0 138 225 21 0 0 0 136 190 45 196 145 0 0 0 175 225 29 206 166 +0 0 12 235 125 0 0 12 138 225 21 136 190 45 196 145 159 251 89 138 247 +34 0 0 0 0 0 0 0 0 0 0 0 175 125 59 245 247 34 0 0 0 0 0 12 232 89 0 0 +0 0 0 0 0 175 166 0 0 0 0 0 0 12 136 190 45 196 145 0 0 0 0 138 166 12 +235 255 125 0 0 0 0 7 206 166 12 235 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 12 232 89 0 0 0 0 0 0 138 201 0 0 0 0 0 136 190 45 +196 145 34 0 0 0 89 251 89 138 247 34 0 0 0 0 0 138 201 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 202 89 7 202 89 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 255 +255 125 0 0 0 0 127 0 0 7 206 251 89 0 0 0 0 7 206 251 89 0 0 0 0 7 206 +251 89 0 0 0 0 0 7 206 251 89 0 0 0 0 7 206 251 89 0 0 0 0 12 235 255 125 +0 0 0 0 0 89 255 255 255 255 255 255 255 255 125 0 0 0 59 245 255 255 255 +201 12 235 255 255 255 255 255 125 12 235 255 255 255 255 255 125 12 235 +255 255 255 255 255 125 12 235 255 255 255 255 255 125 89 255 255 255 201 +89 255 255 255 201 89 255 255 255 201 89 255 255 255 201 0 175 255 255 +255 255 201 0 0 0 12 235 251 89 0 0 12 235 125 0 0 0 138 255 255 166 0 +0 0 0 0 0 138 255 255 166 0 0 0 0 0 0 138 255 255 166 0 0 0 0 0 0 138 255 +255 166 0 0 0 0 0 0 138 255 255 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 +255 255 201 89 251 89 12 235 125 0 0 0 59 245 125 12 235 125 0 0 0 59 245 +125 12 235 125 0 0 0 59 245 125 12 235 125 0 0 0 59 245 125 7 206 225 21 +0 0 0 138 247 0 235 166 0 0 0 0 0 0 138 225 21 7 206 166 0 0 0 127 0 0 +59 245 255 166 0 0 0 0 59 245 255 166 0 0 0 0 59 245 255 166 0 0 0 0 0 +59 245 255 166 0 0 0 0 59 245 255 166 0 0 0 0 59 245 255 166 0 0 0 0 0 +175 201 7 206 166 0 0 0 0 0 0 0 138 255 125 0 0 7 202 102 235 166 0 0 0 +0 0 12 235 166 0 0 0 0 0 12 235 166 0 0 0 0 0 12 235 166 0 0 0 0 0 0 12 +235 125 0 0 12 235 125 0 0 12 235 125 0 0 12 235 125 0 0 175 201 0 0 7 +206 251 89 0 12 235 255 201 0 0 12 235 125 0 59 245 166 0 0 138 251 89 +0 0 59 245 166 0 0 138 251 89 0 0 59 245 166 0 0 138 251 89 0 0 59 245 +166 0 0 138 251 89 0 0 59 245 166 0 0 138 251 89 0 0 0 0 0 0 0 0 0 0 0 +0 59 245 166 0 0 89 255 166 0 12 235 125 0 0 0 59 245 125 12 235 125 0 +0 0 59 245 125 12 235 125 0 0 0 59 245 125 12 235 125 0 0 0 59 245 125 +0 59 245 125 0 0 59 245 125 12 235 166 0 0 0 0 0 12 235 125 0 0 175 201 +0 0 0 127 0 0 138 225 151 225 21 0 0 0 138 225 151 225 21 0 0 0 138 225 +151 225 21 0 0 0 0 138 225 151 225 21 0 0 0 138 225 151 225 21 0 0 0 138 +225 151 225 21 0 0 0 59 241 89 7 206 166 0 0 0 0 0 0 12 235 166 0 0 0 0 +0 12 235 166 0 0 0 0 0 12 235 166 0 0 0 0 0 12 235 166 0 0 0 0 0 12 235 +166 0 0 0 0 0 0 12 235 125 0 0 12 235 125 0 0 12 235 125 0 0 12 235 125 +0 0 175 201 0 0 0 0 175 225 21 12 235 166 245 125 0 12 235 125 12 235 125 +0 0 0 0 138 247 34 12 235 125 0 0 0 0 138 247 34 12 235 125 0 0 0 0 138 +247 34 12 235 125 0 0 0 0 138 247 34 12 235 125 0 0 0 0 138 247 34 0 138 +225 21 0 0 0 175 201 0 12 235 125 0 0 7 202 159 247 34 12 235 125 0 0 0 +59 245 125 12 235 125 0 0 0 59 245 125 12 235 125 0 0 0 59 245 125 12 235 +125 0 0 0 59 245 125 0 0 138 247 34 7 206 201 0 12 235 255 255 255 251 +89 0 12 235 125 0 12 235 125 0 0 0 127 0 7 206 166 59 241 89 0 0 7 206 +166 59 241 89 0 0 7 206 166 59 241 89 0 0 0 7 206 166 59 241 89 0 0 7 206 +166 59 241 89 0 0 7 206 166 59 241 89 0 0 0 138 225 21 7 206 166 0 0 0 +0 0 0 89 247 34 0 0 0 0 0 12 235 166 0 0 0 0 0 12 235 166 0 0 0 0 0 12 +235 166 0 0 0 0 0 12 235 166 0 0 0 0 0 0 12 235 125 0 0 12 235 125 0 0 +12 235 125 0 0 12 235 125 0 0 175 201 0 0 0 0 59 241 89 12 235 125 138 +225 21 12 235 125 89 247 34 0 0 0 0 59 245 125 89 247 34 0 0 0 0 59 245 +125 89 247 34 0 0 0 0 59 245 125 89 247 34 0 0 0 0 59 245 125 89 247 34 +0 0 0 0 59 245 125 0 0 175 225 21 0 175 225 21 0 89 247 34 0 0 138 166 +12 235 125 12 235 125 0 0 0 59 245 125 12 235 125 0 0 0 59 245 125 12 235 +125 0 0 0 59 245 125 12 235 125 0 0 0 59 245 125 0 0 12 235 166 89 247 +34 0 12 235 166 0 0 138 251 89 12 235 133 206 255 125 0 0 0 0 127 0 59 +241 89 7 206 166 0 0 59 241 89 7 206 166 0 0 59 241 89 7 206 166 0 0 0 +59 241 89 7 206 166 0 0 59 241 89 7 206 166 0 0 59 241 89 7 206 166 0 0 +12 235 125 0 7 206 255 255 255 255 247 34 0 138 225 21 0 0 0 0 0 12 235 +255 255 255 255 247 34 12 235 255 255 255 255 247 34 12 235 255 255 255 +255 247 34 12 235 255 255 255 255 247 34 0 12 235 125 0 0 12 235 125 0 +0 12 235 125 0 0 12 235 125 0 206 255 255 255 247 34 0 12 235 125 12 235 +125 12 235 125 12 235 125 138 225 21 0 0 0 0 12 235 166 138 225 21 0 0 +0 0 12 235 166 138 225 21 0 0 0 0 12 235 166 138 225 21 0 0 0 0 12 235 +166 138 225 21 0 0 0 0 12 235 166 0 0 0 175 225 187 225 21 0 0 138 225 +21 0 59 215 21 7 206 166 12 235 125 0 0 0 59 245 125 12 235 125 0 0 0 59 +245 125 12 235 125 0 0 0 59 245 125 12 235 125 0 0 0 59 245 125 0 0 0 89 +255 255 125 0 0 12 235 166 0 0 12 235 166 12 235 125 0 7 206 201 0 0 0 +127 0 138 225 21 0 138 225 21 0 138 225 21 0 138 225 21 0 138 225 21 0 +138 225 21 0 0 138 225 21 0 138 225 21 0 138 225 21 0 138 225 21 0 138 +225 21 0 138 225 21 0 89 255 255 255 255 255 166 0 0 0 0 0 0 138 225 21 +0 0 0 0 0 12 235 166 0 0 0 0 0 12 235 166 0 0 0 0 0 12 235 166 0 0 0 0 +0 12 235 166 0 0 0 0 0 0 12 235 125 0 0 12 235 125 0 0 12 235 125 0 0 12 +235 125 0 0 175 201 0 0 0 0 12 235 125 12 235 125 0 138 225 34 235 125 +138 225 21 0 0 0 0 12 235 166 138 225 21 0 0 0 0 12 235 166 138 225 21 +0 0 0 0 12 235 166 138 225 21 0 0 0 0 12 235 166 138 225 21 0 0 0 0 12 +235 166 0 0 0 0 175 225 21 0 0 0 138 225 21 7 202 89 0 7 206 166 12 235 +125 0 0 0 59 245 125 12 235 125 0 0 0 59 245 125 12 235 125 0 0 0 59 245 +125 12 235 125 0 0 0 59 245 125 0 0 0 7 206 225 21 0 0 12 235 166 0 0 12 +235 166 12 235 125 0 0 59 241 89 0 0 127 7 206 255 255 255 255 251 89 7 +206 255 255 255 255 251 89 7 206 255 255 255 255 251 89 0 7 206 255 255 +255 255 251 89 7 206 255 255 255 255 251 89 7 206 255 255 255 255 251 89 +7 206 166 0 0 7 206 166 0 0 0 0 0 0 89 247 34 0 0 0 0 0 12 235 166 0 0 +0 0 0 12 235 166 0 0 0 0 0 12 235 166 0 0 0 0 0 12 235 166 0 0 0 0 0 0 +12 235 125 0 0 12 235 125 0 0 12 235 125 0 0 12 235 125 0 0 175 201 0 0 +0 0 59 241 89 12 235 125 0 12 235 138 235 125 89 247 34 0 0 0 0 59 245 +125 89 247 34 0 0 0 0 59 245 125 89 247 34 0 0 0 0 59 245 125 89 247 34 +0 0 0 0 59 245 125 89 247 34 0 0 0 0 59 245 125 0 0 0 175 225 187 225 21 +0 0 138 247 34 175 125 0 0 12 235 125 12 235 125 0 0 0 59 241 89 12 235 +125 0 0 0 59 241 89 12 235 125 0 0 0 59 241 89 12 235 125 0 0 0 59 241 +89 0 0 0 0 175 225 21 0 0 12 235 166 0 0 175 247 34 12 235 125 0 0 12 235 +125 0 0 127 59 241 89 0 0 7 206 166 59 241 89 0 0 7 206 166 59 241 89 0 +0 7 206 166 0 59 241 89 0 0 7 206 166 59 241 89 0 0 7 206 166 59 241 89 +0 0 7 206 166 59 241 89 0 0 7 206 166 0 0 0 0 0 0 59 245 166 0 0 0 0 0 +12 235 166 0 0 0 0 0 12 235 166 0 0 0 0 0 12 235 166 0 0 0 0 0 12 235 166 +0 0 0 0 0 0 12 235 125 0 0 12 235 125 0 0 12 235 125 0 0 12 235 125 0 0 +175 201 0 0 0 0 175 225 21 12 235 125 0 0 138 232 245 125 12 235 125 0 +0 0 0 138 247 34 12 235 125 0 0 0 0 138 247 34 12 235 125 0 0 0 0 138 247 +34 12 235 125 0 0 0 0 138 247 34 12 235 125 0 0 0 0 138 247 34 0 0 175 +225 21 0 175 225 21 0 59 245 191 201 0 0 0 89 225 21 12 235 166 0 0 0 89 +251 89 12 235 166 0 0 0 89 251 89 12 235 166 0 0 0 89 251 89 12 235 166 +0 0 0 89 251 89 0 0 0 0 175 225 21 0 0 12 235 255 255 255 247 34 0 12 235 +125 0 0 59 241 89 0 0 127 138 225 21 0 0 0 138 247 163 225 21 0 0 0 138 +247 163 225 21 0 0 0 138 247 34 138 225 21 0 0 0 138 247 163 225 21 0 0 +0 138 247 163 225 21 0 0 0 138 247 198 225 21 0 0 7 206 166 0 0 0 0 0 0 +0 138 255 125 0 0 7 202 102 235 166 0 0 0 0 0 12 235 166 0 0 0 0 0 12 235 +166 0 0 0 0 0 12 235 166 0 0 0 0 0 0 12 235 125 0 0 12 235 125 0 0 12 235 +125 0 0 12 235 125 0 0 175 201 0 0 7 206 251 89 0 12 235 125 0 0 12 235 +255 125 0 89 255 125 0 0 89 251 89 0 0 89 255 125 0 0 89 251 89 0 0 89 +255 125 0 0 89 251 89 0 0 89 255 125 0 0 89 251 89 0 0 89 255 125 0 0 89 +251 89 0 0 138 225 21 0 0 0 175 201 0 0 138 251 89 0 0 89 251 89 0 0 138 +247 34 0 7 206 225 21 0 138 247 34 0 7 206 225 21 0 138 247 34 0 7 206 +225 21 0 138 247 34 0 7 206 225 21 0 0 0 0 175 225 21 0 0 12 235 166 0 +0 0 0 0 12 235 125 0 0 175 225 21 0 0 127 206 166 0 0 0 0 59 245 255 166 +0 0 0 0 59 245 255 166 0 0 0 0 59 245 133 206 166 0 0 0 0 59 245 255 166 +0 0 0 0 59 245 255 166 0 0 0 0 59 245 255 125 0 0 0 7 206 255 255 255 255 +255 125 0 0 0 59 245 255 255 255 201 12 235 255 255 255 255 255 125 12 +235 255 255 255 255 255 125 12 235 255 255 255 255 255 125 12 235 255 255 +255 255 255 125 89 255 255 255 201 89 255 255 255 201 89 255 255 255 201 +89 255 255 255 201 0 175 255 255 255 255 225 21 0 0 12 235 125 0 0 0 138 +255 125 0 0 0 175 255 255 201 0 0 0 0 0 0 175 255 255 201 0 0 0 0 0 0 175 +255 255 201 0 0 0 0 0 0 175 255 255 201 0 0 0 0 0 0 175 255 255 201 0 0 +0 0 0 0 0 0 0 0 0 0 0 7 202 97 206 255 255 201 0 0 0 0 0 138 255 255 255 +201 0 0 0 0 138 255 255 255 201 0 0 0 0 138 255 255 255 201 0 0 0 0 138 +255 255 255 201 0 0 0 0 0 0 175 225 21 0 0 12 235 166 0 0 0 0 0 12 235 +133 206 255 225 21 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 138 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 138 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 175 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 255 225 21 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 127 127 127 127 +127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 +127 127 127 127 0 127 127 127 127 127 127 127 127 127 127 127 127 127 0 +127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 +127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 +127 0 127 127 127 127 0 127 127 127 127 0 127 127 127 127 0 127 127 127 +127 0 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +127 0 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +127 127 0 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 +127 127 127 0 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 127 127 0 127 127 127 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 +127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 +0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 7 206 225 21 +0 0 0 0 0 12 235 225 21 0 0 89 255 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 7 206 255 247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 247 +34 0 0 0 0 0 0 0 138 251 89 0 0 59 245 247 34 0 0 0 0 0 0 0 0 0 175 247 +34 0 0 175 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 225 21 +0 0 0 0 0 0 0 138 255 125 0 0 0 12 235 251 89 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 251 89 0 0 0 0 0 0 +7 206 225 21 0 0 0 7 206 251 89 0 0 0 0 0 0 0 0 0 0 0 0 0 59 245 166 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 59 241 89 0 0 0 0 +0 89 247 34 0 0 7 206 138 235 125 0 0 89 255 225 21 175 125 0 0 0 0 0 0 +0 0 0 138 201 0 138 201 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 +235 125 0 0 0 0 0 0 12 235 125 0 0 0 175 171 206 166 0 0 0 0 0 0 0 0 0 +7 206 166 0 59 245 255 166 238 0 0 0 0 0 0 0 0 0 0 0 0 7 206 255 125 59 +215 21 0 0 59 241 89 0 0 0 0 0 0 7 206 166 0 0 0 0 138 201 175 201 0 0 +0 12 235 251 89 89 201 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 7 206 166 0 0 0 0 0 0 89 247 34 0 0 0 0 89 225 151 201 0 0 0 0 +0 0 0 0 0 0 0 0 0 175 201 0 12 235 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 127 0 0 0 138 201 0 0 0 0 7 206 125 0 0 0 138 201 0 89 225 21 +12 228 34 138 255 201 0 0 0 138 247 34 175 225 21 0 138 201 0 138 201 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 225 21 0 0 0 0 0 89 225 +21 0 0 89 247 34 59 241 89 0 59 241 89 89 247 34 0 0 89 225 21 175 127 +215 21 206 247 42 206 0 138 255 247 42 206 125 0 0 138 166 12 235 251 89 +0 0 0 0 138 201 0 0 0 0 0 0 89 225 21 0 0 0 59 241 89 12 235 125 0 0 175 +125 59 245 247 34 0 0 12 235 125 89 251 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 59 238 34 0 0 0 0 0 175 166 0 0 0 0 12 232 89 7 206 125 0 +0 12 235 166 59 245 125 0 0 0 59 238 34 0 12 235 125 0 0 0 0 0 0 89 247 +34 138 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 255 247 34 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 251 89 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 199 34 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 125 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 12 235 255 255 255 166 0 12 235 255 +255 255 166 0 12 235 255 255 255 166 0 12 235 255 255 255 166 0 0 12 235 +255 255 255 166 0 12 235 255 255 255 166 0 12 235 255 255 255 166 0 175 +255 255 125 0 0 12 235 255 255 125 0 0 12 235 255 255 225 21 0 0 12 235 +255 255 225 21 0 12 235 255 255 225 21 0 12 235 255 255 225 21 0 12 235 +125 12 235 125 12 235 125 12 235 125 0 12 235 125 89 251 89 0 12 235 138 +235 255 247 34 0 0 12 235 255 255 201 0 0 0 12 235 255 255 201 0 0 0 12 +235 255 255 201 0 0 0 12 235 255 255 201 0 0 0 12 235 255 255 201 0 0 0 +0 0 0 175 247 34 0 0 0 12 235 255 255 255 166 0 59 241 89 0 0 89 247 34 +59 241 89 0 0 89 247 34 59 241 89 0 0 89 247 34 59 241 89 0 0 89 247 42 +206 201 0 0 0 138 232 245 166 245 255 251 89 7 206 201 0 0 0 138 225 21 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 127 12 206 21 0 59 245 125 12 206 21 0 59 245 125 12 206 +21 0 59 245 125 12 206 21 0 59 245 125 0 12 206 21 0 59 245 125 12 206 +21 0 59 245 125 12 206 21 0 12 235 255 125 0 7 206 166 12 235 166 0 0 172 +102 0 235 125 0 0 175 201 0 12 235 125 0 0 175 201 12 235 125 0 0 175 201 +12 235 125 0 0 175 201 0 12 235 125 12 235 125 12 235 125 12 235 125 0 +0 0 0 0 175 201 0 12 235 247 34 0 175 201 0 12 235 166 0 7 206 201 0 12 +235 166 0 7 206 201 0 12 235 166 0 7 206 201 0 12 235 166 0 7 206 201 0 +12 235 166 0 7 206 201 0 0 0 0 0 175 247 34 0 0 12 235 166 0 12 235 201 +0 59 241 89 0 0 89 247 34 59 241 89 0 0 89 247 34 59 241 89 0 0 89 247 +34 59 241 89 0 0 89 247 34 89 247 34 0 7 206 176 235 225 21 0 175 225 21 +89 247 34 0 7 206 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 7 206 166 0 0 0 0 7 +206 166 0 0 0 0 7 206 166 0 0 0 0 7 206 166 0 0 0 0 0 7 206 166 0 0 0 0 +7 206 166 0 0 0 0 0 175 201 0 0 0 89 225 138 225 21 0 0 0 0 89 225 21 0 +0 89 247 34 89 225 21 0 0 89 247 124 225 21 0 0 89 247 124 225 21 0 0 89 +247 34 12 235 125 12 235 125 12 235 125 12 235 125 0 89 255 255 255 255 +247 34 12 235 125 0 0 89 247 34 138 225 21 0 0 59 238 34 138 225 21 0 0 +59 238 34 138 225 21 0 0 59 238 34 138 225 21 0 0 59 238 34 138 225 21 +0 0 59 238 34 0 0 0 0 0 0 0 0 0 138 225 21 0 172 132 238 34 59 241 89 0 +0 89 247 34 59 241 89 0 0 89 247 34 59 241 89 0 0 89 247 34 59 241 89 0 +0 89 247 34 12 235 125 0 59 238 47 235 125 0 0 59 241 89 12 235 125 0 59 +238 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 59 245 255 255 255 166 0 59 245 255 255 +255 166 0 59 245 255 255 255 166 0 59 245 255 255 255 166 0 0 59 245 255 +255 255 166 0 59 245 255 255 255 166 0 89 255 255 255 255 255 255 255 255 +255 247 175 201 0 0 0 0 0 175 255 255 255 255 255 247 34 175 255 255 255 +255 255 247 198 255 255 255 255 255 247 198 255 255 255 255 255 247 34 +12 235 125 12 235 125 12 235 125 12 235 125 89 251 89 0 0 59 241 89 12 +235 125 0 0 89 247 34 175 201 0 0 0 12 232 89 175 201 0 0 0 12 232 89 175 +201 0 0 0 12 232 89 175 201 0 0 0 12 232 89 175 201 0 0 0 12 232 89 7 206 +255 255 255 255 255 255 251 226 201 0 89 166 12 232 89 59 241 89 0 0 89 +247 34 59 241 89 0 0 89 247 34 59 241 89 0 0 89 247 34 59 241 89 0 0 89 +247 34 0 175 201 0 138 201 12 235 125 0 0 12 235 125 0 175 201 0 138 201 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 127 89 255 166 0 7 206 166 89 255 166 0 7 206 166 89 +255 166 0 7 206 166 89 255 166 0 7 206 166 0 89 255 166 0 7 206 166 89 +255 166 0 7 206 166 138 255 125 0 0 175 201 0 0 0 0 0 175 201 0 0 0 0 0 +175 201 0 0 0 0 0 0 175 201 0 0 0 0 0 175 201 0 0 0 0 0 175 201 0 0 0 0 +0 0 12 235 125 12 235 125 12 235 125 12 235 125 175 201 0 0 0 59 241 89 +12 235 125 0 0 89 247 34 175 201 0 0 0 12 232 89 175 201 0 0 0 12 232 89 +175 201 0 0 0 12 232 89 175 201 0 0 0 12 232 89 175 201 0 0 0 12 232 89 +0 0 0 0 0 0 0 0 0 175 201 7 176 21 12 232 89 59 241 89 0 0 89 247 34 59 +241 89 0 0 89 247 34 59 241 89 0 0 89 247 34 59 241 89 0 0 89 247 34 0 +89 247 47 235 125 12 235 125 0 0 12 235 125 0 89 247 47 235 125 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 127 175 201 0 0 7 206 166 175 201 0 0 7 206 166 175 201 0 0 +7 206 166 175 201 0 0 7 206 166 0 175 201 0 0 7 206 166 175 201 0 0 7 206 +166 175 201 0 0 0 138 225 21 0 0 0 0 138 225 21 0 0 0 0 138 247 34 0 0 +0 0 0 138 247 34 0 0 0 0 138 247 34 0 0 0 0 138 247 34 0 0 0 0 0 12 235 +125 12 235 125 12 235 125 12 235 125 175 201 0 0 0 89 247 34 12 235 125 +0 0 89 247 34 138 225 21 0 0 89 247 34 138 225 21 0 0 89 247 34 138 225 +21 0 0 89 247 34 138 225 21 0 0 89 247 34 138 225 21 0 0 89 247 34 0 0 +0 0 175 247 34 0 0 138 225 151 125 0 89 247 34 59 241 89 0 0 89 247 34 +59 241 89 0 0 89 247 34 59 241 89 0 0 89 247 34 59 241 89 0 0 89 247 34 +0 12 235 191 247 34 12 235 125 0 0 59 241 89 0 12 235 191 247 34 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 127 138 225 21 0 138 255 166 138 225 21 0 138 255 166 138 +225 21 0 138 255 166 138 225 21 0 138 255 166 0 138 225 21 0 138 255 166 +138 225 21 0 138 255 166 89 247 34 0 89 255 255 166 0 0 12 206 12 235 166 +0 0 127 102 0 235 201 0 0 12 206 21 12 235 201 0 0 12 206 34 235 201 0 +0 12 206 34 235 201 0 0 12 206 21 12 235 125 12 235 125 12 235 125 12 235 +125 89 255 125 0 7 206 166 0 12 235 125 0 0 89 247 34 12 235 166 0 7 206 +201 0 12 235 166 0 7 206 201 0 12 235 166 0 7 206 201 0 12 235 166 0 7 +206 201 0 12 235 166 0 7 206 201 0 0 0 0 0 175 247 34 0 0 12 235 201 0 +7 206 201 0 7 206 166 0 59 245 247 34 7 206 166 0 59 245 247 34 7 206 166 +0 59 245 247 34 7 206 166 0 59 245 247 34 0 0 138 255 166 0 12 235 125 +0 7 206 201 0 0 0 138 255 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 7 206 255 255 171 +206 166 7 206 255 255 171 206 166 7 206 255 255 171 206 166 7 206 255 255 +171 206 166 0 7 206 255 255 171 206 166 7 206 255 255 171 206 166 0 89 +255 255 201 0 0 175 255 255 247 34 0 12 235 255 255 166 0 0 7 206 255 255 +247 34 0 0 7 206 255 255 247 34 0 7 206 255 255 247 34 0 7 206 255 255 +247 34 0 12 235 125 12 235 125 12 235 125 12 235 125 0 89 255 255 255 201 +0 0 12 235 125 0 0 89 247 34 0 12 235 255 255 201 0 0 0 12 235 255 255 +201 0 0 0 12 235 255 255 201 0 0 0 12 235 255 255 201 0 0 0 12 235 255 +255 201 0 0 0 0 0 0 0 0 0 0 0 7 206 255 255 255 201 0 0 0 59 245 255 225 +111 247 34 0 59 245 255 225 111 247 34 0 59 245 255 225 111 247 34 0 59 +245 255 225 111 247 34 0 0 59 241 89 0 12 235 255 255 255 225 21 0 0 0 +59 241 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 175 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 138 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 225 21 0 12 235 125 0 0 0 0 0 0 0 +138 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 7 202 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 166 0 0 12 235 125 0 0 0 0 0 0 7 206 +166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +12 235 255 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 247 34 0 0 12 235 125 0 0 0 0 0 0 89 247 +34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 127 127 127 127 127 0 127 127 127 127 +127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 0 127 127 0 127 127 0 127 127 0 127 127 0 127 127 127 127 127 127 +127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 +127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 +127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 diff --git a/Extras/CDTestFramework/AntTweakBar/src/res/FontNormal.pgm b/Extras/CDTestFramework/AntTweakBar/src/res/FontNormal.pgm new file mode 100644 index 0000000..f05e831 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/res/FontNormal.pgm @@ -0,0 +1,895 @@ +P2 +# Created by Paint Shop Pro +253 106 +255 +127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 255 +0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 255 0 0 0 255 0 255 0 0 0 0 +0 255 0 255 0 0 0 0 0 255 0 0 0 0 255 255 0 0 0 0 255 0 0 0 0 0 255 255 +255 0 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 0 255 0 255 0 255 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 255 255 255 0 0 0 0 0 +255 0 0 0 0 255 255 255 255 0 0 0 255 255 255 255 0 0 0 0 0 0 255 0 0 255 +255 255 255 255 255 0 0 0 255 255 255 0 0 255 255 255 255 255 255 0 0 255 +255 255 255 0 0 0 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 127 0 0 0 0 0 0 255 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 255 255 +255 0 0 255 0 0 255 0 0 255 0 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 0 255 +0 0 0 0 255 0 0 0 0 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 255 0 0 255 0 0 0 0 255 0 0 255 255 255 0 0 0 255 0 0 0 0 255 0 +255 0 0 0 0 255 0 0 0 0 255 255 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 +0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 127 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 +0 0 255 0 255 0 255 0 255 0 0 255 0 0 255 0 0 0 0 0 255 0 0 0 255 0 0 0 +0 0 0 0 255 0 0 0 0 0 0 255 0 0 255 0 255 0 255 0 0 0 0 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 +0 0 255 0 0 0 0 0 0 255 0 0 0 255 0 255 0 0 255 0 0 0 0 0 0 255 0 0 0 0 +0 0 0 0 0 0 255 0 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 0 255 0 0 0 255 +0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 255 0 255 +0 0 0 0 255 0 255 0 0 0 255 0 0 255 0 255 0 0 0 0 0 0 0 255 0 255 0 0 0 +0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 +0 255 0 0 0 0 0 0 255 0 0 255 0 0 255 0 0 255 255 255 255 255 0 0 255 255 +255 255 255 0 0 0 0 0 0 255 0 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 0 255 +0 0 0 255 0 0 0 0 0 0 255 255 0 0 0 0 255 255 255 255 255 255 0 0 0 0 255 +255 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 255 0 0 +0 0 0 0 0 0 0 0 255 0 255 0 0 0 0 0 255 255 0 0 0 0 255 255 0 0 255 0 0 +255 255 0 0 0 255 255 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 +0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 +255 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 255 255 255 0 0 255 0 0 0 255 +0 0 0 0 0 0 0 255 0 255 0 0 0 0 255 0 0 0 0 255 0 0 0 0 255 255 255 255 +0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 255 255 0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 +0 0 0 0 255 0 0 0 0 0 0 0 0 255 255 255 255 255 255 0 0 0 0 0 255 255 0 +0 0 0 0 0 0 255 0 255 0 0 255 0 255 0 0 255 0 0 255 0 0 0 0 0 255 0 0 0 +0 0 0 255 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 0 0 0 0 0 255 255 +255 0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 255 255 +0 0 0 0 0 0 0 0 255 0 255 255 255 255 255 255 0 0 0 0 0 0 255 0 255 0 0 +0 0 255 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 255 255 255 255 255 0 0 0 +0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 255 255 255 255 255 255 0 0 0 0 0 0 0 +0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 255 0 0 0 0 +0 0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 255 0 0 255 +0 255 0 0 0 255 255 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 +0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 0 +0 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 255 +0 255 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 255 0 0 +0 0 0 0 0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 +0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 255 0 255 0 0 0 0 0 255 0 255 0 255 0 0 0 0 0 255 0 0 255 0 0 255 0 255 +0 0 0 255 255 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 255 +0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 0 0 +255 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 255 0 0 255 0 0 0 0 +255 0 255 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 255 0 +0 0 255 0 0 0 255 0 0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 255 0 0 0 0 0 +0 0 0 0 255 0 255 0 0 0 0 0 0 255 255 255 0 0 0 0 0 255 0 0 0 0 255 255 +0 0 0 255 255 255 0 0 255 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 +0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 255 255 255 +255 0 0 0 255 255 255 255 255 0 255 255 255 255 255 255 0 0 255 255 255 +255 0 0 0 0 0 0 255 0 0 0 255 255 255 255 0 0 0 255 255 255 255 0 0 0 255 +0 0 0 0 0 0 255 255 255 255 0 0 0 255 255 255 0 0 0 0 255 0 0 0 255 0 0 +0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 255 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 +0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 +0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 127 127 127 0 +127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 0 127 127 127 127 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 0 127 127 127 0 127 127 127 0 127 127 127 127 0 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 0 127 127 127 +127 0 127 127 127 0 127 127 127 127 0 127 127 127 127 127 127 0 127 127 +127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 +127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 +0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 +127 0 127 127 0 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 +127 127 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 0 255 0 0 0 0 0 255 255 255 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 255 +255 255 255 0 0 0 0 0 0 0 255 0 0 0 0 255 255 255 255 255 0 0 0 0 255 255 +255 255 0 255 255 255 255 255 0 0 0 255 255 255 255 255 255 0 255 255 255 +255 255 0 0 0 255 255 255 255 0 0 255 0 0 0 0 0 255 0 255 255 255 0 0 255 +255 255 0 255 0 0 0 0 255 0 255 0 0 0 0 0 255 255 0 0 0 0 255 255 0 255 +255 0 0 0 0 255 0 0 0 255 255 255 255 0 0 0 255 255 255 255 255 0 0 0 0 +255 255 255 255 0 0 0 255 255 255 255 0 0 0 0 255 255 255 255 0 0 255 255 +255 255 255 255 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 +0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 255 255 255 +255 255 0 0 255 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 255 255 0 0 0 0 255 255 0 0 +0 0 255 0 255 0 0 0 255 0 0 0 0 255 0 0 255 0 0 0 0 0 255 0 0 0 0 255 0 +0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 255 0 255 0 0 0 0 0 255 0 +0 255 0 0 0 0 0 255 0 255 0 0 0 255 0 0 255 0 0 0 0 0 255 255 0 0 0 0 255 +255 0 255 255 0 0 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 0 0 255 0 0 255 +0 0 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 0 0 255 0 0 0 0 255 0 0 0 0 255 +0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 255 0 0 0 0 255 0 0 255 +0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 255 0 0 0 +0 0 0 255 0 0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 127 0 255 0 255 255 255 255 0 255 0 0 0 0 255 0 255 0 0 0 255 0 0 +0 0 255 0 255 0 0 0 0 0 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 0 0 +0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 255 0 0 0 0 0 255 0 255 0 0 +255 0 0 0 255 0 0 0 0 0 255 0 255 0 0 255 0 255 0 255 0 255 0 0 0 255 0 +255 0 0 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 255 0 0 0 +255 0 0 255 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 255 0 0 255 0 0 +0 255 0 0 0 255 0 0 255 0 255 0 0 255 0 0 0 255 0 0 255 0 0 0 255 0 0 0 +255 0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 255 0 0 +0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 255 0 255 0 0 +0 255 0 0 255 0 0 0 255 0 255 0 0 0 255 0 0 0 0 255 0 255 0 0 0 0 0 0 255 +0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 +0 0 0 255 0 0 255 0 0 0 0 0 255 0 255 0 255 0 0 0 0 255 0 0 0 0 0 255 0 +255 0 0 255 0 255 0 255 0 255 0 0 0 255 0 255 0 0 0 0 0 0 255 0 255 0 0 +0 0 255 0 255 0 0 0 0 0 0 255 0 255 0 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 +255 0 0 0 0 255 0 0 0 0 0 255 0 0 255 0 0 0 255 0 0 0 255 0 0 255 0 255 +0 0 255 0 0 0 0 255 255 0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 0 0 0 255 +0 0 0 0 255 0 0 0 0 0 0 255 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 127 255 0 255 0 0 0 255 0 0 255 0 0 255 0 0 0 255 +0 0 255 255 255 255 255 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 255 0 255 255 +255 255 255 255 0 255 255 255 255 255 0 255 0 0 0 255 255 255 0 255 255 +255 255 255 255 255 0 0 255 0 0 0 0 0 255 0 255 255 0 0 0 0 0 255 0 0 0 +0 0 255 0 255 0 0 255 0 255 0 255 0 0 255 0 0 255 0 255 0 0 0 0 0 0 255 +0 255 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 255 255 255 255 0 0 0 0 255 255 +255 255 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 255 0 0 255 0 0 0 255 0 0 0 +255 0 0 255 0 255 0 0 255 0 0 0 0 255 255 0 0 0 0 0 0 255 0 0 0 0 0 0 255 +0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 255 0 255 0 0 0 255 0 0 255 0 0 255 +0 0 0 255 0 0 255 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 0 0 0 0 255 0 255 +0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 255 +0 0 0 0 0 255 0 255 0 255 0 0 0 0 255 0 0 0 0 0 255 0 0 255 255 0 0 255 +0 255 0 0 0 255 0 255 0 255 0 0 0 0 0 0 255 0 255 255 255 255 255 0 0 255 +0 0 0 0 0 0 255 0 255 0 0 255 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 255 +0 0 0 0 0 255 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 255 0 255 0 0 0 0 +255 255 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 +0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 127 255 0 255 0 0 0 255 0 0 255 0 0 255 255 255 255 255 0 0 255 0 0 0 +0 255 0 255 0 0 0 0 0 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 0 0 0 +0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 255 0 0 0 0 0 255 0 255 0 0 +255 0 0 0 255 0 0 0 0 0 255 0 0 255 255 0 0 255 0 255 0 0 0 255 0 255 0 +255 0 0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 255 0 0 0 255 +0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 255 0 0 0 255 0 255 +0 0 0 0 0 255 255 0 0 0 255 255 0 0 0 0 255 0 0 255 0 0 0 0 0 255 0 0 0 +0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 255 0 255 255 255 255 +255 255 0 0 255 0 0 0 0 0 255 0 255 0 0 0 0 255 0 0 255 0 0 0 0 0 255 0 +0 0 0 255 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 255 0 255 0 0 +0 0 0 255 0 0 255 0 0 0 0 0 255 0 255 0 0 0 255 0 0 255 0 0 0 0 0 255 0 +0 0 0 0 0 255 0 255 0 0 0 0 255 255 0 0 255 0 0 0 0 255 0 0 255 0 0 0 0 +0 0 0 255 0 0 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 0 0 255 0 0 0 0 255 +0 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 +0 0 0 255 0 0 255 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 +255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 127 0 255 255 0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 255 255 255 +255 255 0 0 0 0 255 255 255 255 0 255 255 255 255 255 0 0 0 255 255 255 +255 255 255 0 255 0 0 0 0 0 0 0 255 255 255 255 255 0 255 0 0 0 0 0 255 +0 255 255 255 0 255 255 255 0 0 255 0 0 0 0 255 0 255 255 255 255 255 0 +255 0 0 0 0 0 0 255 0 255 0 0 0 0 255 255 0 0 0 255 255 255 255 0 0 0 255 +0 0 0 0 0 0 0 0 255 255 255 255 0 0 0 255 0 0 0 0 255 0 0 255 255 255 255 +0 0 0 0 0 255 0 0 0 0 0 0 255 255 255 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 +0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 0 0 255 0 0 0 0 255 255 255 255 255 +255 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 255 255 255 255 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 0 0 0 0 255 0 0 +255 255 255 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 127 127 127 127 127 127 127 127 127 127 0 127 127 127 +127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 +0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 +0 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 0 127 +127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 +127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 +127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 +127 0 127 127 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 +127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 +127 0 127 127 127 127 0 127 127 127 127 0 127 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 255 +0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 +0 0 0 0 0 0 255 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 +0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 0 0 255 +0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 127 0 255 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 255 0 0 0 +0 0 0 255 0 0 255 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 +0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 +0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 +0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 255 255 255 0 0 255 0 255 255 +255 0 0 0 255 255 255 255 0 0 255 255 255 255 255 0 0 255 255 255 255 0 +0 255 255 255 255 0 255 255 255 255 255 0 255 0 255 255 255 0 0 255 0 255 +255 0 255 0 0 0 255 0 255 0 255 255 255 255 0 255 255 255 0 0 255 0 255 +255 255 0 0 0 255 255 255 255 0 0 255 0 255 255 255 0 0 0 255 255 255 255 +255 0 255 0 255 0 0 255 255 255 0 255 255 255 255 0 255 0 0 0 0 255 0 255 +0 0 0 255 0 255 0 0 0 255 0 0 0 255 0 255 0 0 0 255 0 255 0 0 0 255 0 255 +255 255 255 0 0 0 255 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 +0 0 0 0 0 0 255 0 255 255 0 0 0 255 0 255 0 0 0 0 0 255 0 0 0 0 255 0 255 +0 0 0 0 255 0 0 255 0 0 255 0 0 0 0 255 0 255 255 0 0 0 255 0 255 0 0 255 +0 255 0 0 255 0 0 255 0 255 0 0 0 255 0 0 0 255 0 255 255 0 0 0 255 0 255 +0 0 0 0 255 0 255 255 0 0 0 255 0 255 0 0 0 0 255 0 255 255 0 0 255 0 0 +0 0 0 255 0 0 0 255 0 0 0 0 255 0 255 0 0 0 255 0 255 0 0 0 255 0 0 0 255 +0 0 255 0 255 0 0 255 0 0 0 255 0 0 0 0 255 0 0 0 255 0 0 0 0 0 255 0 0 +0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 255 0 255 0 0 0 0 255 0 255 +0 0 0 0 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 0 255 0 0 255 0 0 0 0 255 +0 255 0 0 0 0 255 0 255 0 0 255 0 255 0 255 0 0 0 255 0 255 0 0 0 255 0 +0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 +0 0 255 0 255 0 0 0 255 0 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 255 0 255 +0 0 0 255 0 255 0 255 0 255 0 0 0 255 0 255 0 0 0 255 0 255 0 0 0 0 255 +0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 255 255 0 0 0 255 0 0 0 +255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 +0 255 255 255 255 0 255 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 0 0 255 0 255 +255 255 255 255 255 0 0 255 0 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 +0 0 255 0 255 255 0 0 0 0 255 0 255 0 0 0 255 0 0 0 255 0 255 0 0 0 0 255 +0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 +255 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 255 0 255 0 0 0 255 0 255 0 255 +0 255 0 0 0 0 255 0 0 0 0 255 0 255 0 0 0 255 0 0 0 255 255 0 0 0 0 0 0 +255 0 0 0 0 0 255 255 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 0 0 0 0 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 255 0 0 0 255 0 255 0 +0 0 0 255 0 255 0 0 0 0 0 255 0 0 0 0 255 0 255 0 0 0 0 0 0 0 255 0 0 255 +0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 255 0 255 0 255 0 0 0 255 0 255 +0 0 0 255 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 +0 255 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 0 255 0 0 0 255 0 0 0 0 255 0 +0 255 0 255 0 0 0 255 0 255 0 255 0 255 0 0 0 255 0 255 0 0 0 255 0 255 +0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 255 0 0 0 255 +255 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +0 0 0 0 0 0 255 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 0 255 +255 0 255 0 0 0 0 255 0 0 255 0 0 255 0 0 0 255 255 0 255 0 0 0 0 255 0 +255 0 0 255 0 255 0 0 255 0 0 255 0 255 0 0 0 255 0 0 0 255 0 255 0 0 0 +0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 255 255 0 255 0 0 +0 0 0 0 255 0 0 255 0 0 0 255 0 0 0 255 255 0 0 0 255 0 0 0 0 0 255 0 0 +0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 +255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 255 255 255 255 0 255 255 +255 255 255 0 0 0 255 255 255 255 0 0 255 255 255 0 255 0 0 255 255 255 +255 0 0 0 255 0 0 0 255 255 255 0 255 0 255 0 0 0 0 255 0 255 0 0 255 0 +255 0 0 0 255 0 255 0 255 0 0 0 255 0 0 0 255 0 255 0 0 0 0 255 0 0 255 +255 255 255 0 0 255 255 255 255 255 0 0 0 255 255 255 0 255 0 255 0 0 0 +255 255 255 0 0 0 0 255 255 0 0 255 255 255 0 255 0 0 0 255 0 0 0 0 0 255 +0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 255 255 255 0 0 0 255 +0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 +255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 +0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 0 0 +255 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 127 127 127 127 0 127 127 127 127 127 0 +127 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 +0 127 127 127 127 127 127 0 127 127 127 0 127 127 127 127 127 127 0 127 +127 127 127 127 127 0 127 0 127 127 0 127 127 127 127 127 0 127 0 127 127 +127 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 +127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 +0 127 127 127 127 0 127 127 127 127 0 127 127 127 127 127 127 0 127 127 +127 127 127 0 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 +0 127 127 127 127 127 0 127 127 127 127 0 127 127 127 127 127 0 127 127 +127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 127 127 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 255 0 0 255 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 +0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 255 0 255 0 255 +0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 +255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 127 0 0 255 +255 255 255 0 0 0 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 255 +255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 +255 0 0 255 0 0 0 255 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 255 255 255 255 +0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 255 255 0 0 0 255 255 255 +255 255 255 255 255 255 0 255 255 255 255 255 255 0 0 0 255 255 255 255 +255 255 255 255 255 0 0 0 255 255 255 255 255 255 255 255 255 0 255 0 0 +0 255 0 255 0 255 0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 255 0 255 255 0 0 0 255 255 255 0 255 0 0 0 255 0 0 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 255 +255 0 0 255 255 0 0 255 0 0 0 0 0 255 0 127 0 255 0 0 0 0 0 0 0 255 0 0 +0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 +255 255 255 255 0 0 255 255 255 255 255 0 0 0 0 0 0 0 0 255 0 0 255 0 0 +255 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 255 0 +0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 0 0 +0 255 0 0 0 255 0 0 0 0 0 0 0 255 0 0 255 0 255 0 0 0 255 0 255 0 255 0 +255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 0 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 255 0 0 127 255 0 0 0 0 +0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 +0 255 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 255 0 255 0 0 0 0 0 255 +0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 +0 0 255 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 +0 255 0 255 0 0 255 255 255 0 0 255 0 0 0 0 255 255 255 255 0 255 255 255 +0 0 0 0 255 0 0 0 0 0 0 0 255 0 255 255 255 255 0 0 255 0 0 0 255 0 0 127 +255 255 255 255 255 255 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 +0 0 0 0 255 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 255 +0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 255 0 +0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 255 0 255 0 0 0 0 0 0 255 0 0 255 0 0 +0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 255 0 255 +0 0 0 127 255 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 255 +255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 +0 0 0 0 0 0 0 0 255 255 0 0 255 0 0 255 255 0 0 0 255 255 0 0 0 255 255 +255 255 0 0 0 255 0 0 0 255 0 0 0 0 0 255 255 255 255 255 0 0 0 255 0 0 +0 0 0 0 0 255 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 255 0 0 +0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 +0 0 0 0 0 0 255 0 255 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 255 +0 0 0 255 0 0 0 0 0 255 0 0 0 0 127 255 255 255 255 255 255 0 0 0 255 0 +0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 255 0 0 0 0 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 255 +0 0 255 0 255 0 0 255 0 0 0 0 0 0 255 0 0 255 0 0 0 255 0 0 0 0 0 255 0 +0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 +0 255 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 +255 255 255 0 255 255 255 255 255 0 255 255 255 255 255 255 255 255 255 +255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 0 0 0 0 255 +0 255 0 0 0 0 255 255 255 255 255 0 0 0 255 0 0 0 0 0 0 0 255 0 0 255 0 +0 0 0 0 0 255 0 0 0 0 127 255 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 +0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 +255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 255 0 0 255 0 0 0 +0 0 0 255 0 0 0 255 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 +0 255 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 0 0 +0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 255 +0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 +0 0 255 0 0 0 0 127 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 255 0 +0 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 +255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 255 0 0 255 0 255 +0 0 0 0 255 0 0 0 0 255 0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 +0 0 255 0 255 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 0 +0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 +0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 255 0 0 0 0 0 +0 0 255 0 0 0 0 127 0 0 255 255 255 255 0 0 0 255 255 255 255 255 255 255 +255 255 0 0 255 0 0 0 255 0 0 0 0 0 255 0 255 0 0 255 0 0 255 0 0 255 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 255 0 +0 0 255 255 0 0 0 255 255 255 255 0 0 0 0 0 0 0 0 0 255 255 255 255 255 +255 255 255 255 0 0 0 255 255 255 255 255 255 255 255 255 0 255 255 255 +255 255 255 0 0 0 255 255 255 255 255 255 255 255 255 0 0 0 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 +255 255 0 0 0 0 0 0 0 0 255 255 255 255 0 255 255 255 255 0 0 0 255 255 +255 255 255 255 255 255 255 0 255 255 255 255 0 0 0 0 255 0 0 0 0 127 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 255 0 0 0 0 0 255 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +127 127 127 0 127 127 0 127 127 127 127 127 127 0 127 127 127 127 0 127 +127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 +127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 +127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 +127 0 127 127 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 127 127 0 +127 127 0 127 127 0 127 127 127 127 0 127 127 127 127 0 127 127 127 127 +0 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 127 0 127 127 +127 127 0 127 127 127 127 0 127 127 127 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 127 127 127 127 0 127 127 127 127 0 127 127 127 +127 127 127 127 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 255 0 0 0 +0 0 255 0 0 0 0 0 255 255 255 255 0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 +255 0 0 0 0 255 255 255 255 0 0 255 0 0 255 0 0 0 0 0 255 255 255 255 0 +0 0 0 0 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 +255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 255 +255 255 0 0 0 255 255 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 255 255 255 +255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 255 255 +255 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 +0 0 0 0 255 255 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 255 255 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 255 +0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 +255 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 0 255 0 0 0 255 0 0 +0 0 0 0 0 0 0 255 255 0 0 0 255 0 0 0 0 0 0 255 255 0 0 0 0 255 0 0 0 0 +0 0 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 127 0 0 0 0 0 255 0 0 0 0 255 255 255 255 0 0 255 0 0 0 0 +0 255 0 0 0 0 255 0 0 0 255 0 255 0 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 0 +0 0 0 0 0 255 0 0 255 255 0 0 255 0 0 0 0 255 255 255 0 0 0 255 0 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 255 255 255 0 0 255 0 0 0 0 0 0 0 0 +0 0 255 0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 255 255 0 0 0 0 0 +0 0 0 0 255 0 0 0 0 255 0 255 255 255 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 0 0 255 0 0 0 255 0 255 0 0 255 0 0 0 0 0 255 0 0 0 255 0 0 0 +0 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 255 255 0 0 0 255 0 0 0 0 0 0 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 255 0 0 +0 255 0 255 0 0 0 0 255 0 0 0 0 0 0 255 255 255 255 0 0 0 0 255 0 255 0 +0 0 0 255 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 0 255 +0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 +0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 255 255 0 0 0 0 0 255 0 0 0 0 0 0 255 +0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 255 255 255 255 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 255 0 0 +0 0 255 0 0 255 0 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 255 0 255 +0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +0 0 0 0 0 255 0 0 0 255 0 255 0 0 0 0 255 0 0 0 0 0 0 255 0 0 255 0 0 0 +0 0 255 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 +0 0 0 255 0 0 255 0 0 255 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 +255 255 255 0 0 255 255 255 255 0 0 255 255 255 0 0 0 0 0 0 0 0 0 255 0 +0 0 0 255 0 0 255 255 255 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 255 255 255 +0 255 0 0 0 255 0 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 255 255 0 0 0 0 +255 0 0 255 0 255 255 255 0 0 0 0 0 0 255 0 255 0 0 255 255 0 0 0 255 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 255 0 0 +0 255 0 255 0 0 0 255 255 255 255 255 0 0 0 255 0 0 255 0 0 0 255 255 255 +255 255 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 +0 255 0 0 0 255 255 255 0 255 0 0 255 0 0 0 0 255 255 255 255 255 255 255 +0 255 255 255 0 255 0 0 255 255 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 +0 0 0 0 255 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 0 +0 0 0 255 0 0 255 0 0 0 0 0 255 0 0 255 0 255 0 0 0 0 0 0 0 255 0 0 0 0 +255 0 0 255 255 255 0 255 0 0 255 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 255 0 0 0 255 0 255 0 0 0 0 +255 0 0 0 0 0 0 255 255 255 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 255 +0 0 255 0 0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 255 +0 0 255 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 255 0 0 255 0 0 255 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 255 0 0 0 0 255 0 0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 0 255 0 0 255 0 0 255 0 0 0 0 0 +0 255 0 0 0 0 255 0 0 0 0 0 0 255 0 0 255 0 0 255 0 255 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 255 0 0 0 255 0 255 +0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 +0 255 255 0 0 0 0 0 0 0 0 0 0 255 0 0 255 255 0 0 255 0 0 0 0 0 0 0 0 0 +0 255 0 0 255 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 255 0 0 0 255 255 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 255 255 0 0 0 0 255 0 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 0 0 255 0 0 255 +255 255 255 255 0 0 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 255 0 0 255 255 255 +255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +0 0 0 0 0 255 0 0 0 0 255 255 255 255 0 255 255 255 255 255 255 0 0 0 0 +0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 255 +255 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 +0 0 0 0 255 255 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 0 255 0 0 0 +0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 255 255 255 255 0 0 0 0 255 +0 0 0 0 0 0 255 0 0 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 255 255 +255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 255 0 255 0 0 0 +0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 255 255 255 +255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 +0 0 255 0 255 0 0 0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +127 127 0 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 +0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 0 +127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 0 127 127 127 0 127 127 127 127 127 127 127 +127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 +127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 +127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 +127 0 127 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 +0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 +127 127 127 127 127 0 127 127 127 127 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 127 0 0 255 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 255 +0 0 0 0 0 255 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 255 0 0 0 0 255 255 0 +0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 255 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 +255 0 0 0 0 0 0 0 255 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 255 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 127 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 255 0 0 0 +255 0 255 255 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 255 0 0 255 0 +0 0 255 0 0 255 0 0 0 255 0 0 0 255 0 0 255 0 0 255 255 0 255 0 0 0 0 0 +0 0 0 0 0 255 0 255 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 +0 255 0 0 255 0 0 0 0 0 255 0 255 255 0 0 0 0 0 255 0 0 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 +0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 255 0 0 0 0 0 0 0 255 0 +0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 +0 0 0 0 0 0 255 255 255 255 255 255 255 0 0 0 255 255 255 255 0 255 255 +255 255 255 255 0 255 255 255 255 255 255 0 255 255 255 255 255 255 0 255 +255 255 255 255 255 0 255 255 255 0 255 255 255 0 255 255 255 0 255 255 +255 0 0 255 255 255 255 0 0 0 255 255 0 0 0 0 255 0 0 0 255 255 255 255 +0 0 0 0 0 255 255 255 255 0 0 0 0 0 255 255 255 255 0 0 0 0 0 255 255 255 +255 0 0 0 0 0 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 +0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 +0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 0 0 255 0 0 0 +0 0 0 0 0 0 0 0 127 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 +0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 0 +255 0 255 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 255 +0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 +0 0 0 255 0 0 255 255 0 0 0 0 255 0 0 255 0 0 0 0 255 0 0 0 255 0 0 0 0 +255 0 0 0 255 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 +0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 255 0 0 0 0 0 255 0 255 0 0 0 +0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 255 0 0 0 255 0 0 255 +0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 127 0 0 255 0 255 0 0 0 +0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 +0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 255 +0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 +255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 255 0 255 0 255 0 0 0 255 0 255 +0 0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 255 0 0 0 +0 0 0 255 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 255 +0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 +0 0 255 0 0 255 0 0 0 255 0 0 255 255 255 255 255 0 0 255 0 0 0 255 0 0 +0 0 0 0 0 0 0 0 0 127 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 +255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 +0 255 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 +255 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 +0 255 0 0 0 0 255 0 255 0 255 0 0 0 255 0 255 0 0 0 0 0 0 255 0 255 0 0 +0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 255 0 0 0 0 0 +0 255 0 0 0 255 0 0 0 255 0 0 255 0 0 0 255 0 0 255 0 255 0 0 0 0 0 255 +0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 0 255 0 +255 0 0 0 255 0 0 0 0 255 0 255 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 127 0 +255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 +0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 255 255 255 255 +255 0 255 0 0 0 0 0 0 255 255 255 255 255 255 0 255 255 255 255 255 255 +0 255 255 255 255 255 255 0 255 255 255 255 255 255 0 0 255 0 0 0 255 0 +0 0 255 0 0 0 255 0 0 255 255 255 255 0 0 255 0 255 0 0 255 0 0 255 0 255 +0 0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 255 0 0 0 +0 0 0 255 0 255 0 0 0 0 0 0 255 0 0 0 0 255 0 255 0 0 0 255 0 0 255 0 0 +0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 +0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 255 0 0 0 0 255 0 255 0 0 0 255 0 0 0 +0 0 0 0 0 0 0 0 127 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 +255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 +255 255 255 255 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 +0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 +0 0 255 0 0 0 0 255 0 255 0 0 0 255 0 255 0 255 0 0 0 0 0 0 255 0 255 0 +0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 255 0 0 0 0 +0 0 255 0 0 0 0 0 255 0 0 0 0 255 0 0 255 0 0 0 255 0 255 0 0 0 0 0 255 +0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 0 0 255 +0 0 0 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 127 0 255 +255 255 255 255 0 0 0 255 255 255 255 255 0 0 0 255 255 255 255 255 0 0 +0 255 255 255 255 255 0 0 0 255 255 255 255 255 0 0 0 255 255 255 255 255 +0 0 0 255 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 +0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 +0 0 0 255 0 0 0 0 255 0 255 0 0 0 255 0 255 0 255 0 0 0 0 0 0 255 0 255 +0 0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 255 0 0 0 +0 0 0 255 0 0 0 0 255 0 255 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 0 +255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 0 0 +255 0 0 0 0 255 255 255 255 255 0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 +127 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 +0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 255 0 0 0 255 0 0 +0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 255 +0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 +255 0 0 0 0 255 255 0 0 255 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 0 255 +0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 0 0 255 0 0 +0 255 0 0 0 255 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 +0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 +0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 127 255 0 0 0 0 0 255 0 255 0 0 0 +0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 +0 0 0 0 0 255 0 255 0 0 0 0 255 255 255 255 255 0 0 0 255 255 255 255 0 +255 255 255 255 255 255 0 255 255 255 255 255 255 0 255 255 255 255 255 +255 0 255 255 255 255 255 255 0 255 255 255 0 255 255 255 0 255 255 255 +0 255 255 255 0 0 255 255 255 255 0 0 0 255 0 0 0 0 255 255 0 0 0 255 255 +255 255 0 0 0 0 0 255 255 255 255 0 0 0 0 0 255 255 255 255 0 0 0 0 0 255 +255 255 255 0 0 0 0 0 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 +255 255 255 0 0 0 0 0 255 255 255 0 0 0 0 0 255 255 255 0 0 0 0 0 255 255 +255 0 0 0 0 0 255 255 255 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 255 0 +255 255 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 127 127 127 127 127 +127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 0 127 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 +127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 +127 127 0 127 127 127 127 127 127 0 127 127 127 0 127 127 127 0 127 127 +127 0 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 +127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 +127 127 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 255 0 0 0 0 0 0 255 0 0 +0 0 255 255 0 0 0 255 255 0 255 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 255 255 0 0 +0 0 0 0 0 0 0 0 255 0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 +255 0 0 255 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 255 0 0 0 0 0 255 255 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 +0 255 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 255 0 0 0 0 255 0 0 0 0 255 +0 0 255 0 255 0 255 255 0 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 255 0 0 +0 255 0 0 255 0 0 0 255 0 255 0 255 0 255 255 0 255 0 0 255 0 255 0 0 0 +255 0 255 255 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 255 0 0 0 255 +0 255 255 0 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 0 0 0 0 0 0 255 0 0 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 0 0 255 0 +0 0 255 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +127 0 255 255 255 0 0 0 255 255 255 0 0 0 255 255 255 0 0 0 255 255 255 +0 0 0 255 255 255 0 0 0 255 255 255 0 0 0 255 255 255 0 0 255 255 0 0 0 +0 255 255 255 255 0 0 255 255 255 255 0 0 0 255 255 255 255 0 0 0 255 255 +255 255 0 0 0 255 255 255 255 0 0 0 255 0 255 0 0 255 0 0 255 0 0 255 255 +0 255 0 0 255 0 255 255 255 0 0 0 255 255 255 255 0 0 0 255 255 255 255 +0 0 0 255 255 255 255 0 0 0 255 255 255 255 0 0 0 255 255 255 255 0 0 0 +0 0 0 255 0 0 0 0 0 0 255 255 255 255 0 0 255 0 0 0 0 255 0 255 0 0 0 0 +255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 255 0 255 0 255 255 +255 0 0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 255 0 0 0 0 0 +255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 +255 0 0 255 0 0 255 0 0 0 0 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 +0 0 0 255 0 255 0 0 0 0 255 0 0 255 0 255 0 0 255 0 0 255 0 0 0 0 0 0 255 +0 255 255 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 +0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 255 +0 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 +0 255 0 0 0 255 0 255 255 0 0 0 255 0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 127 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 +255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 0 0 +255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 0 255 0 255 +0 0 255 0 0 255 0 0 255 255 255 255 255 0 255 0 0 0 0 255 0 255 0 0 0 0 +255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 +255 0 0 0 0 0 0 0 0 0 0 255 0 0 0 255 0 255 0 255 0 0 0 0 255 0 255 0 0 +0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 0 255 0 255 0 0 255 0 0 0 +0 255 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 255 255 255 255 0 0 +255 255 255 255 0 0 255 255 255 255 0 0 255 255 255 255 0 0 255 255 255 +255 0 0 255 255 255 255 0 0 255 255 255 255 255 255 255 255 255 0 255 0 +0 0 0 0 255 255 255 255 255 255 0 255 255 255 255 255 255 0 255 255 255 +255 255 255 0 255 255 255 255 255 255 0 0 255 0 255 0 0 255 0 0 255 0 255 +0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 +0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 0 255 255 255 255 255 +255 255 0 255 0 0 255 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 +0 0 0 0 255 0 255 0 0 0 0 255 0 0 255 0 255 0 0 255 0 0 0 0 255 0 0 255 +0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 255 0 0 0 255 0 255 0 0 0 255 0 255 +0 0 0 255 0 255 0 0 0 255 0 255 0 0 0 255 0 255 0 0 0 255 0 255 0 0 0 255 +0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 +0 255 0 0 0 0 0 0 0 255 0 255 0 0 255 0 0 255 0 255 0 0 0 0 255 0 255 0 +0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 +0 0 0 255 0 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 255 0 255 0 0 0 255 0 255 +0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 0 255 +0 255 0 0 255 0 0 0 0 255 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 255 +0 0 0 255 0 255 0 0 0 255 0 255 0 0 0 255 0 255 0 0 0 255 0 255 0 0 0 255 +0 255 0 0 0 255 0 255 0 0 0 255 255 0 0 0 255 0 255 0 0 0 0 0 255 0 0 0 +0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 0 255 0 255 +0 0 255 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 +255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 +0 0 0 0 255 0 0 0 0 0 255 0 0 0 255 0 0 255 0 0 0 255 255 0 255 0 0 0 255 +255 0 255 0 0 0 255 255 0 255 0 0 0 255 255 0 0 0 255 0 0 0 255 0 0 0 0 +255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 255 255 255 255 0 0 255 +255 255 255 0 0 255 255 255 255 0 0 255 255 255 255 0 0 255 255 255 255 +0 0 255 255 255 255 0 0 255 255 255 0 0 255 255 255 0 0 0 255 255 255 255 +0 0 255 255 255 255 0 0 0 255 255 255 255 0 0 0 255 255 255 255 0 0 0 255 +255 255 255 0 0 0 255 0 255 0 0 255 0 0 255 0 0 255 255 255 255 0 0 255 +0 0 0 0 255 0 0 255 255 255 255 0 0 0 255 255 255 255 0 0 0 255 255 255 +255 0 0 0 255 255 255 255 0 0 0 255 255 255 255 0 0 0 0 0 0 255 0 0 0 0 +0 255 255 255 255 0 0 0 0 255 255 255 0 255 0 0 255 255 255 0 255 0 0 255 +255 255 0 255 0 0 255 255 255 0 255 0 0 0 255 0 0 0 255 255 255 255 255 +0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 +0 255 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 +127 127 0 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 +127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 0 127 +127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 +0 127 127 0 127 0 127 127 0 127 127 0 127 127 127 127 127 127 0 127 127 +127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 +127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 +127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 0 127 +127 127 127 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/Extras/CDTestFramework/AntTweakBar/src/res/FontNormalAA.pgm b/Extras/CDTestFramework/AntTweakBar/src/res/FontNormalAA.pgm new file mode 100644 index 0000000..34cff30 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/res/FontNormalAA.pgm @@ -0,0 +1,1012 @@ +P2 +# Created by Paint Shop Pro +264 106 +255 +127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 +59 241 97 206 166 0 0 0 0 0 0 0 0 0 0 0 0 0 168 34 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 251 89 0 0 89 255 125 89 255 125 0 0 0 0 +7 199 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 166 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 138 225 21 59 238 42 +206 125 0 0 0 0 7 199 34 89 166 0 0 0 0 168 34 0 0 0 175 255 255 166 0 +0 7 202 89 0 0 0 0 59 245 255 251 89 0 0 0 59 238 34 0 12 232 89 0 0 89 +247 34 0 59 245 206 199 124 255 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 7 202 89 0 12 235 255 247 34 0 0 0 0 12 232 89 0 0 12 235 +255 255 251 89 0 7 206 255 255 255 125 0 0 0 0 138 251 89 0 0 59 245 255 +255 255 251 89 0 0 89 255 255 166 0 89 255 255 255 255 255 201 0 0 59 245 +255 255 125 0 0 12 235 255 247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 255 255 255 247 34 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 127 0 0 0 0 0 138 225 21 59 238 34 175 125 0 0 0 0 59 192 0 172 +89 0 0 59 245 255 255 251 89 89 247 34 12 228 34 0 138 166 0 0 0 0 12 235 +125 0 175 225 21 0 0 59 238 34 0 138 201 0 0 0 0 175 166 0 0 0 89 255 201 +0 0 0 0 0 0 7 202 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 215 21 0 175 +166 0 138 201 0 0 7 206 255 251 89 0 0 59 192 0 0 138 247 34 59 192 0 0 +89 251 89 0 0 59 245 251 89 0 0 59 241 89 0 0 0 0 0 89 247 34 0 0 0 0 0 +0 0 7 206 166 0 7 206 125 0 89 247 34 7 206 166 0 138 225 21 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 12 232 89 0 0 0 0 0 0 0 0 0 0 0 175 166 0 0 0 0 0 +0 0 89 125 0 0 175 201 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 138 225 21 12 206 +21 175 125 0 0 89 255 255 255 255 255 255 166 59 241 89 168 34 138 125 +89 225 21 7 202 89 12 228 34 0 0 0 0 12 232 89 0 138 201 0 0 0 12 206 21 +7 202 89 0 0 0 0 59 215 21 59 245 206 199 124 255 125 0 0 0 0 7 202 89 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 166 0 12 232 89 0 59 238 34 0 0 +0 59 241 89 0 0 0 0 0 0 59 241 89 0 0 0 0 59 241 89 0 12 232 132 241 89 +0 0 59 241 89 0 0 0 0 7 206 125 0 0 0 0 0 0 0 0 89 247 34 0 12 232 89 0 +12 232 89 59 241 89 0 59 241 89 0 138 247 34 0 0 138 247 34 0 0 0 0 0 12 +235 247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 138 255 166 0 0 0 0 0 0 0 0 0 138 +225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 138 225 21 0 0 0 0 0 0 0 0 0 172 +89 59 192 0 0 59 238 34 168 34 0 0 89 247 34 12 228 34 138 166 0 0 0 0 +0 0 138 251 159 247 34 0 0 0 0 0 0 59 238 34 0 0 0 0 7 202 89 0 0 7 199 +34 0 0 0 0 0 0 7 202 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 202 89 0 59 +241 89 0 59 241 89 0 0 0 59 241 89 0 0 0 0 0 0 89 247 34 0 0 0 0 138 201 +0 7 206 125 59 241 89 0 0 59 245 255 255 251 89 0 12 235 255 255 255 125 +0 0 0 0 7 206 166 0 0 0 175 251 89 138 201 0 59 241 89 0 12 235 125 0 138 +247 34 0 0 138 247 34 0 0 0 59 245 247 34 0 0 0 0 7 206 255 255 255 255 +255 255 125 0 0 0 0 138 255 201 0 0 0 0 0 0 89 251 89 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +127 0 0 0 0 0 138 201 0 0 0 0 0 0 0 0 0 12 206 21 138 125 0 0 7 206 255 +247 34 0 0 0 175 255 255 166 59 215 21 175 255 255 125 0 0 138 171 206 +166 0 175 201 0 0 0 0 89 201 0 0 0 0 0 0 175 125 0 0 0 0 0 0 0 0 12 235 +255 255 255 255 255 255 125 0 0 0 0 138 255 255 251 89 0 0 0 0 0 59 215 +21 0 59 241 89 0 59 241 89 0 0 0 59 241 89 0 0 0 0 0 12 235 166 0 0 0 138 +255 255 125 0 175 201 0 59 241 89 0 0 0 0 0 0 175 247 34 59 241 89 0 89 +247 34 0 0 0 89 247 34 0 0 0 89 255 255 255 125 0 12 235 166 0 59 245 125 +0 0 0 0 0 0 0 0 0 0 0 175 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 89 251 89 0 0 7 206 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 89 201 +0 0 0 0 0 0 0 12 235 255 255 255 255 255 225 21 0 0 0 175 255 251 89 0 +0 0 0 0 175 125 89 225 21 59 238 34 89 225 21 12 235 166 175 166 0 0 0 +0 89 201 0 0 0 0 0 0 175 125 0 0 0 0 0 0 0 0 0 0 0 7 202 89 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 138 166 0 0 59 241 89 0 59 241 89 0 0 0 59 241 89 +0 0 0 0 12 235 166 0 0 0 0 0 0 59 241 97 206 255 255 255 255 255 125 0 +0 0 0 0 59 241 89 59 238 34 0 12 235 125 0 0 12 235 125 0 0 0 12 232 89 +0 59 245 125 0 89 255 255 232 241 89 0 0 0 0 0 0 0 0 0 0 0 0 59 245 247 +34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 255 201 0 0 0 0 7 206 125 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 125 12 206 21 +0 0 0 0 0 168 34 175 166 0 0 0 0 59 215 21 138 201 0 12 228 34 138 225 +21 0 12 235 251 89 0 0 0 0 59 215 21 0 0 0 0 12 232 89 0 0 0 0 0 0 0 0 +0 0 0 7 202 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 202 89 0 0 12 232 89 0 +59 238 34 0 0 0 59 241 89 0 0 0 12 235 166 0 0 0 0 0 0 0 12 235 125 0 0 +0 59 241 89 0 0 0 0 0 0 59 241 89 12 232 89 0 12 232 89 0 0 138 225 21 +0 0 0 59 238 34 0 7 206 166 0 0 0 0 89 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 12 235 247 34 0 0 7 206 255 255 255 255 255 255 125 0 0 138 255 166 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 138 225 21 0 0 0 0 +0 0 0 0 172 89 89 166 0 0 0 89 166 0 168 42 206 125 0 0 0 7 202 89 0 89 +225 21 59 238 34 89 251 89 0 0 175 255 201 0 0 0 0 7 202 89 0 0 0 0 59 +215 21 0 0 0 0 0 0 0 0 0 0 0 7 202 89 0 0 0 0 138 247 34 0 0 0 0 0 7 206 +201 0 12 228 34 0 0 0 175 166 0 138 201 0 0 0 0 59 241 89 0 0 12 235 166 +0 0 0 0 89 166 0 0 89 251 89 0 0 0 59 241 89 0 0 59 192 0 0 175 225 21 +0 175 201 0 138 225 21 0 12 235 125 0 0 0 0 12 235 166 0 59 241 89 0 0 +0 7 206 166 0 0 138 247 34 0 0 59 245 125 0 0 0 0 0 0 0 12 232 89 0 0 0 +0 0 0 0 0 0 0 0 175 166 0 0 0 0 0 0 0 0 7 206 166 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +127 0 0 0 0 0 138 225 21 0 0 0 0 0 0 0 12 206 21 138 125 0 0 0 12 235 255 +255 255 166 0 0 0 0 138 201 0 0 0 175 255 255 125 0 0 138 255 255 255 125 +12 235 247 0 0 0 0 138 201 0 0 0 0 175 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 7 206 166 0 0 0 0 0 0 7 206 201 0 89 201 0 0 0 0 12 235 255 247 +34 0 0 7 206 255 255 255 225 21 89 255 255 255 255 255 166 59 245 255 255 +251 89 0 0 0 0 59 241 89 0 0 12 235 255 255 225 21 0 0 12 235 255 251 89 +0 0 175 225 21 0 0 0 0 0 59 245 255 255 125 0 0 89 255 255 166 0 0 0 138 +247 34 0 0 138 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 7 206 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 168 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 12 232 89 0 0 59 238 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 59 241 89 0 0 0 0 0 0 0 0 0 0 175 125 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 125 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 168 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 +255 125 89 255 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 201 0 0 0 0 +0 0 0 0 0 0 12 228 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 228 34 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +127 127 127 127 0 127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 +127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 +127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 0 127 127 127 127 +0 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 +127 127 0 127 127 127 0 127 127 127 127 0 127 127 127 0 127 127 127 127 +0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 +127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 0 +127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 255 255 125 138 166 0 0 0 89 255 255 247 +34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 89 255 255 +255 255 166 0 0 0 0 0 12 235 225 21 0 0 59 245 255 255 255 251 89 0 0 0 +59 245 255 255 251 89 59 245 255 255 255 247 34 0 0 59 245 255 255 255 +255 127 81 245 255 255 255 255 127 0 0 59 245 255 255 255 166 0 59 241 +89 0 0 0 59 241 89 89 255 255 255 125 7 206 255 251 89 59 241 89 0 0 89 +255 166 59 241 89 0 0 0 0 59 245 225 21 0 0 7 206 251 89 59 245 247 34 +0 0 59 241 89 0 0 138 255 255 255 166 0 0 59 245 255 255 255 225 21 0 0 +0 138 255 255 255 166 0 0 59 245 255 255 255 251 89 0 0 0 59 245 255 255 +201 89 255 255 255 255 255 255 255 125 59 241 89 0 0 0 59 241 97 206 166 +0 0 0 0 175 201 175 201 0 0 7 206 201 0 0 0 175 171 206 225 21 0 0 59 245 +166 245 125 0 0 0 89 251 89 89 255 255 255 255 255 127 0 228 34 0 0 59 +215 21 0 0 0 0 12 228 34 0 0 0 59 245 201 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 127 0 0 175 225 21 0 0 0 175 225 21 0 0 0 89 232 241 89 0 0 59 +241 89 0 0 138 225 21 0 89 255 125 0 0 59 192 59 241 89 0 0 175 251 89 +0 59 241 89 0 0 0 0 59 241 89 0 0 0 0 0 89 255 125 0 0 7 199 34 59 241 +89 0 0 0 59 241 89 0 59 241 89 0 0 0 59 241 89 59 241 89 0 59 241 89 0 +59 241 89 0 0 0 0 59 245 255 125 0 0 89 255 251 89 59 245 255 201 0 0 59 +241 89 0 138 251 89 0 12 235 166 0 59 241 89 0 7 206 225 21 0 138 251 89 +0 12 235 166 0 59 241 89 0 0 138 247 34 0 12 235 125 0 7 176 21 0 0 59 +241 89 0 0 0 59 241 89 0 0 0 59 241 89 138 225 21 0 0 12 235 125 89 225 +21 0 59 245 247 34 0 12 232 89 12 235 166 0 7 206 166 0 89 247 34 0 7 206 +125 0 0 0 0 0 7 206 166 12 228 34 0 0 7 202 89 0 0 0 0 12 228 34 0 0 12 +235 133 206 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 138 201 0 138 +255 255 255 125 138 166 0 0 7 206 166 175 166 0 0 59 241 89 0 0 89 247 +34 7 206 166 0 0 0 0 0 59 241 89 0 0 0 175 225 21 59 241 89 0 0 0 0 59 +241 89 0 0 0 0 7 206 166 0 0 0 0 0 0 59 241 89 0 0 0 59 241 89 0 59 241 +89 0 0 0 59 241 89 59 241 89 59 241 89 0 0 59 241 89 0 0 0 0 59 241 159 +225 21 0 175 166 241 89 59 241 132 241 89 0 59 241 89 12 235 166 0 0 0 +89 247 34 59 241 89 0 0 89 247 34 12 235 166 0 0 0 89 247 34 59 241 89 +0 0 59 241 89 0 59 238 34 0 0 0 0 0 0 59 241 89 0 0 0 59 241 89 0 0 0 59 +241 89 59 241 89 0 0 89 225 21 59 241 89 0 89 206 202 89 0 59 238 34 0 +89 251 89 138 225 21 0 0 175 201 0 138 225 21 0 0 0 0 0 175 225 21 12 228 +34 0 0 0 138 166 0 0 0 0 12 228 34 0 7 206 166 0 12 235 125 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 127 7 202 89 89 225 21 7 206 125 12 206 21 0 59 238 +34 89 247 34 0 59 241 89 0 0 175 201 0 59 241 89 0 0 0 0 0 59 241 89 0 +0 0 59 241 89 59 241 89 0 0 0 0 59 241 89 0 0 0 0 59 241 89 0 0 0 0 0 0 +59 241 89 0 0 0 59 241 89 0 59 241 89 0 0 0 59 241 89 59 241 102 232 89 +0 0 0 59 241 89 0 0 0 0 59 241 102 232 89 59 215 81 241 89 59 241 89 138 +225 21 59 241 89 59 241 89 0 0 0 59 241 89 59 241 89 0 7 206 201 0 59 241 +89 0 0 0 59 241 89 59 241 89 0 0 175 201 0 0 12 235 166 0 0 0 0 0 0 59 +241 89 0 0 0 59 241 89 0 0 0 59 241 89 7 206 166 0 0 175 166 0 7 206 125 +0 175 125 175 166 0 138 201 0 0 0 175 255 251 89 0 0 0 59 245 166 241 89 +0 0 0 0 0 89 247 34 0 12 228 34 0 0 0 89 201 0 0 0 0 12 228 34 12 235 201 +0 0 0 59 245 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 59 215 21 175 125 +0 7 206 125 7 199 34 0 138 201 0 12 235 125 0 59 245 255 255 255 247 34 +0 59 241 89 0 0 0 0 0 59 241 89 0 0 0 59 241 89 59 245 255 255 255 255 +127 59 245 255 255 255 255 127 59 241 89 0 0 0 0 0 0 59 245 255 255 255 +255 255 251 89 0 59 241 89 0 0 0 59 241 89 59 245 255 247 34 0 0 0 59 241 +89 0 0 0 0 59 241 89 138 201 175 166 59 241 89 59 241 89 12 235 125 59 +241 89 59 241 89 0 0 0 12 235 125 59 245 255 255 255 201 0 0 59 241 89 +0 0 0 12 235 125 59 245 255 255 255 125 0 0 0 0 59 245 255 255 125 0 0 +0 59 241 89 0 0 0 59 241 89 0 0 0 59 241 89 0 138 225 21 59 241 89 0 0 +175 201 7 202 89 89 201 0 175 166 0 0 0 12 235 166 0 0 0 0 0 138 255 166 +0 0 0 0 0 59 245 125 0 0 12 228 34 0 0 0 12 228 34 0 0 0 12 228 34 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 59 215 21 175 125 0 7 +206 125 7 199 34 7 206 125 0 0 175 201 0 59 241 89 0 0 89 247 34 59 241 +89 0 0 0 0 0 59 241 89 0 0 0 59 241 89 59 241 89 0 0 0 0 59 241 89 0 0 +0 0 59 241 89 0 59 245 255 251 89 59 241 89 0 0 0 59 241 89 0 59 241 89 +0 0 0 59 241 89 59 241 89 175 225 21 0 0 59 241 89 0 0 0 0 59 241 89 12 +235 247 34 59 241 89 59 241 89 0 89 247 94 241 89 59 241 89 0 0 0 59 241 +89 59 241 89 0 0 0 0 0 59 241 89 0 0 0 59 241 89 59 241 89 12 235 166 0 +0 0 0 0 0 0 138 251 89 0 0 59 241 89 0 0 0 59 241 89 0 0 0 59 241 89 0 +12 232 89 138 225 21 0 0 89 225 81 215 21 12 228 47 232 89 0 0 0 175 255 +251 89 0 0 0 0 59 241 89 0 0 0 0 7 206 201 0 0 0 12 228 34 0 0 0 0 175 +125 0 0 0 12 228 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +12 228 34 89 201 0 7 206 125 59 215 21 59 245 255 255 255 255 247 34 59 +241 89 0 0 59 241 89 7 206 166 0 0 0 0 0 59 241 89 0 0 0 138 225 21 59 +241 89 0 0 0 0 59 241 89 0 0 0 0 7 206 166 0 0 0 59 241 89 59 241 89 0 +0 0 59 241 89 0 59 241 89 0 0 0 59 241 89 59 241 89 7 206 201 0 0 59 241 +89 0 0 0 0 59 241 89 0 175 166 0 59 241 89 59 241 89 0 7 206 200 241 89 +12 235 166 0 0 0 89 247 34 59 241 89 0 0 0 0 0 12 235 166 0 0 0 89 247 +34 59 241 89 0 59 245 125 0 0 0 0 0 0 12 232 89 0 0 59 241 89 0 0 0 12 +232 89 0 0 0 59 238 34 0 0 175 171 206 166 0 0 0 12 232 159 201 0 7 202 +132 215 21 0 0 89 247 34 175 225 21 0 0 0 59 241 89 0 0 0 0 138 225 21 +0 0 0 12 228 34 0 0 0 0 89 201 0 0 0 12 228 34 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 138 201 7 206 255 251 226 255 255 166 0 +138 201 0 0 0 12 235 125 59 241 89 0 0 138 247 34 0 89 255 125 0 0 59 192 +59 241 89 0 0 138 251 89 0 59 241 89 0 0 0 0 59 241 89 0 0 0 0 0 89 255 +125 0 0 59 241 89 59 241 89 0 0 0 59 241 89 0 59 241 89 0 0 0 89 247 34 +59 241 89 0 12 235 166 0 59 241 89 0 0 0 0 59 241 89 0 0 0 0 59 241 89 +59 241 89 0 0 59 245 251 89 0 138 251 89 0 59 245 166 0 59 241 89 0 0 0 +0 0 0 138 251 89 0 59 245 166 0 59 241 89 0 0 138 251 89 0 89 166 0 0 89 +247 34 0 0 59 241 89 0 0 0 0 138 225 21 0 7 206 166 0 0 0 89 255 251 89 +0 0 0 7 206 255 125 0 0 138 255 201 0 0 12 235 125 0 12 235 166 0 0 0 59 +241 89 0 0 0 89 251 89 0 0 0 0 12 228 34 0 0 0 0 12 228 34 0 0 12 228 34 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 7 206 225 21 0 +0 0 0 0 0 7 206 125 0 0 0 0 175 201 59 245 255 255 255 247 34 0 0 0 59 +245 255 255 251 89 59 245 255 255 255 225 21 0 0 59 245 255 255 255 255 +127 81 241 89 0 0 0 0 0 0 59 245 255 255 255 201 0 59 241 89 0 0 0 59 241 +89 89 255 255 255 138 235 255 255 125 0 59 241 89 0 0 89 255 201 59 245 +255 255 255 255 166 59 241 89 0 0 0 0 59 241 89 59 241 89 0 0 0 175 251 +89 0 0 138 255 255 255 166 0 0 59 241 89 0 0 0 0 0 0 0 138 255 255 255 +166 0 0 59 241 89 0 0 0 175 251 89 12 235 255 255 251 89 0 0 0 59 241 89 +0 0 0 0 0 59 245 255 251 89 0 0 0 0 12 235 201 0 0 0 0 0 138 251 89 0 0 +89 255 125 0 7 206 225 21 0 0 89 255 125 0 0 59 241 89 0 0 0 175 255 255 +255 255 255 127 0 228 34 0 0 0 0 0 175 125 0 0 12 228 34 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 89 255 255 255 255 125 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 241 89 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 +228 34 0 0 0 0 0 89 201 0 0 12 228 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 138 255 255 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 255 255 125 0 0 0 12 228 +124 255 255 247 34 0 0 0 0 0 0 0 0 0 245 255 255 255 255 255 255 0 0 0 +0 0 0 0 0 0 0 127 127 127 127 127 127 127 127 127 127 127 0 127 127 127 +127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 +127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 +127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 127 0 127 127 127 127 0 127 127 127 127 0 127 127 127 127 127 127 +127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 0 127 +127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 127 0 89 255 125 0 0 0 0 0 0 0 0 0 0 59 241 89 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 59 241 89 0 0 0 0 0 0 0 0 89 255 255 166 0 0 0 0 0 +0 0 59 241 89 0 0 0 0 0 0 0 0 0 0 0 59 241 89 0 0 0 0 59 241 89 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 255 201 0 12 228 +34 0 0 89 255 247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 89 255 255 255 255 255 255 +255 255 255 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 59 241 89 0 0 0 0 0 0 0 0 +0 59 241 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 241 89 0 0 0 0 0 0 0 12 235 +125 0 0 0 0 0 0 0 0 0 59 241 89 0 0 0 0 59 241 89 0 89 251 89 59 241 89 +0 0 0 0 59 241 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 241 89 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 89 225 21 0 0 12 228 34 0 0 0 0 138 201 0 0 0 0 0 0 0 0 0 0 0 0 +0 89 166 0 0 0 0 0 0 0 138 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 59 241 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 241 89 0 0 0 0 0 +0 0 59 241 89 0 0 0 0 0 0 0 0 0 59 241 89 0 0 0 0 0 0 0 0 0 0 0 59 241 +89 0 0 0 0 59 241 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 241 89 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 138 166 0 0 0 12 228 34 0 0 0 0 89 225 21 0 0 0 0 0 0 0 0 0 +0 0 0 89 166 0 0 0 0 0 0 0 138 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 +0 0 7 206 255 255 255 125 0 59 241 194 255 251 89 0 0 7 206 255 255 201 +0 12 235 255 255 251 89 0 12 235 255 251 89 7 206 255 255 247 34 0 12 235 +255 255 251 89 59 241 194 255 255 125 0 59 241 89 89 255 251 89 59 241 +89 0 138 251 89 59 241 89 59 241 159 255 255 125 89 255 255 166 0 59 241 +194 255 255 125 0 0 0 12 235 255 247 34 0 59 241 194 255 255 125 0 0 12 +235 255 255 251 89 59 241 159 255 201 0 138 255 255 247 34 206 255 255 +255 166 59 241 89 0 59 241 97 206 166 0 0 12 235 125 175 201 0 7 206 166 +0 7 206 133 206 225 21 0 89 255 255 166 0 0 12 235 125 138 255 255 255 +255 166 0 0 138 166 0 0 0 12 228 34 0 0 0 0 89 225 21 0 0 0 0 0 0 0 0 0 +0 0 0 89 166 0 0 0 0 0 0 0 138 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 +0 0 0 0 0 0 89 247 34 59 245 166 0 138 225 21 7 206 201 0 0 0 7 206 166 +0 59 241 89 7 206 125 0 89 225 21 59 241 89 0 0 7 206 166 0 59 241 89 59 +245 166 0 89 247 34 59 241 89 0 59 241 89 59 241 89 138 225 21 0 59 241 +89 59 245 201 0 89 255 201 0 89 247 34 59 245 166 0 89 247 34 0 7 206 166 +0 138 225 21 59 245 166 0 138 247 34 7 206 166 0 59 241 89 59 245 201 0 +0 59 238 34 0 130 34 59 241 89 0 0 59 241 89 0 59 241 89 89 247 34 0 89 +247 34 138 225 21 12 235 225 21 12 232 89 7 206 166 12 235 125 89 247 34 +0 89 247 34 0 0 0 89 247 34 0 0 138 166 0 0 0 12 228 34 0 0 0 0 89 225 +21 0 0 7 206 247 34 0 0 89 201 0 0 89 166 0 0 0 0 0 0 0 138 125 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 59 241 89 59 241 89 0 59 241 89 +59 241 89 0 0 0 59 241 89 0 59 241 89 59 238 34 0 59 238 34 59 241 89 0 +0 59 241 89 0 59 241 89 59 241 89 0 59 241 89 59 241 89 0 59 241 89 59 +241 159 201 0 0 0 59 241 89 59 241 89 0 59 241 89 0 59 241 89 59 241 89 +0 59 241 89 0 59 241 89 0 59 241 89 59 241 89 0 59 241 89 59 241 89 0 59 +241 89 59 241 89 0 0 59 241 89 0 0 0 59 241 89 0 0 59 241 89 0 59 241 89 +12 235 125 0 175 166 0 59 238 34 89 171 202 89 89 225 21 0 59 241 226 201 +0 12 235 125 0 175 166 0 0 0 12 235 125 0 0 59 238 34 0 0 0 12 228 34 0 +0 0 0 7 206 125 0 7 202 89 12 235 166 0 175 125 0 0 89 166 0 0 0 0 0 0 +0 138 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 89 255 255 255 251 +89 59 241 89 0 59 241 89 59 238 34 0 0 0 59 238 34 0 59 241 89 59 245 255 +255 255 251 0 59 241 89 0 0 59 238 34 0 59 241 89 59 241 89 0 59 241 89 +59 241 89 0 59 241 89 59 245 255 225 21 0 0 59 241 89 59 241 89 0 59 241 +89 0 59 241 89 59 241 89 0 59 241 89 0 59 238 34 0 12 232 89 59 241 89 +0 12 232 89 59 238 34 0 59 241 89 59 241 89 0 0 0 175 255 255 201 0 59 +241 89 0 0 59 241 89 0 59 241 89 0 175 201 12 232 89 0 7 206 125 172 89 +138 166 138 201 0 0 0 138 247 34 0 0 175 201 12 232 89 0 0 7 206 166 0 +0 175 225 21 0 0 0 0 12 228 34 0 0 0 0 0 0 175 225 34 206 21 0 0 175 255 +166 0 0 0 89 166 0 0 0 0 0 0 0 138 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 +0 0 0 0 59 241 89 0 59 241 89 59 241 89 0 59 238 34 59 241 89 0 0 0 59 +241 89 0 59 241 89 59 238 34 0 0 0 0 59 241 89 0 0 59 241 89 0 59 241 89 +59 241 89 0 59 241 89 59 241 89 0 59 241 89 59 241 97 206 201 0 0 59 241 +89 59 241 89 0 59 241 89 0 59 241 89 59 241 89 0 59 241 89 0 59 241 89 +0 59 241 89 59 241 89 0 59 241 89 59 241 89 0 59 241 89 59 241 89 0 0 0 +0 0 59 245 125 59 241 89 0 0 59 241 89 0 59 241 89 0 59 238 124 225 21 +0 0 175 176 206 21 59 215 187 125 0 0 59 245 255 201 0 0 89 247 124 225 +21 0 0 138 225 21 0 0 0 59 241 89 0 0 0 12 228 34 0 0 0 0 12 235 125 0 +0 0 0 0 0 0 0 0 0 0 0 89 166 0 0 0 0 0 0 0 138 125 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 127 0 0 0 0 0 0 0 89 247 34 0 89 251 89 59 241 89 0 175 201 0 7 206 201 +0 0 0 7 206 166 0 138 251 89 7 206 166 0 7 199 34 59 241 89 0 0 7 206 166 +0 138 251 89 59 241 89 0 59 241 89 59 241 89 0 59 241 89 59 241 89 12 235 +166 0 59 241 89 59 241 89 0 59 241 89 0 59 241 89 59 241 89 0 59 241 89 +0 7 206 166 0 138 225 21 59 241 89 0 138 225 21 7 206 166 0 89 251 89 59 +241 89 0 0 89 125 0 12 232 89 12 232 89 0 12 12 235 125 0 175 251 89 0 +7 206 255 125 0 0 0 89 255 201 0 7 206 247 34 0 7 206 166 59 245 125 0 +7 206 255 125 0 0 59 241 89 0 0 0 0 0 138 166 0 0 0 12 228 34 0 0 0 0 89 +225 21 0 0 0 0 0 0 0 0 0 0 0 0 89 166 0 0 0 0 0 0 0 138 125 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 127 0 0 0 0 0 0 0 0 175 255 255 232 241 89 59 245 255 255 247 +34 0 0 12 235 255 255 201 0 59 245 255 200 241 89 0 12 235 255 251 89 0 +59 241 89 0 0 0 12 235 255 200 241 89 59 241 89 0 59 241 89 59 241 89 0 +59 241 89 59 241 89 0 59 245 201 59 241 89 59 241 89 0 59 241 89 0 59 241 +89 59 241 89 0 59 241 89 0 0 12 235 255 247 34 0 59 245 166 255 247 34 +0 0 59 245 255 166 241 89 59 241 89 0 0 59 245 255 255 166 0 0 138 255 +255 125 0 89 255 255 166 241 89 0 0 138 247 34 0 0 0 59 245 125 0 0 138 +225 21 7 206 225 21 0 138 251 0 0 138 247 34 0 0 175 255 255 255 255 166 +0 0 138 166 0 0 0 12 228 34 0 0 0 0 89 225 21 0 0 0 0 0 0 0 0 0 0 0 0 89 +255 255 255 255 255 255 255 255 255 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 138 225 21 0 0 0 0 0 0 0 0 0 0 0 89 247 34 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 241 +89 0 0 0 0 0 0 0 0 59 241 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 232 89 0 0 0 0 0 +0 0 0 0 0 0 138 201 0 0 0 12 228 34 0 0 0 0 138 201 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 166 255 255 247 34 0 0 0 0 0 0 0 0 0 0 0 255 255 125 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 241 89 0 +0 0 0 0 0 0 0 59 241 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 225 21 0 0 0 0 0 0 0 +0 0 0 0 7 206 255 201 0 12 228 34 0 0 89 255 251 89 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 127 127 127 127 +127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 +127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 +0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 0 127 127 +127 0 127 127 127 127 127 127 0 127 127 0 127 127 127 127 127 127 127 127 +127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 +127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 0 127 127 127 +127 127 0 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 +127 0 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 0 127 127 +127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 +127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 127 127 127 127 127 127 127 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 89 247 34 138 201 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 125 59 238 34 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +89 255 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 12 235 251 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 238 34 138 201 0 0 +0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 199 34 0 0 0 0 0 7 199 34 0 0 0 0 +138 255 201 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 251 89 0 0 138 255 251 97 206 201 +0 0 138 251 102 235 201 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 89 255 201 12 228 34 0 0 0 0 0 0 0 0 0 0 0 0 7 206 166 12 232 89 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 166 12 235 127 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 175 255 255 255 225 21 59 245 255 +255 255 255 255 125 0 0 0 0 0 0 0 7 206 255 247 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 7 199 34 0 0 0 0 0 7 199 34 0 0 0 138 225 21 175 166 0 0 175 +255 255 166 0 0 7 202 89 0 0 0 0 0 0 0 0 0 0 59 245 255 255 201 0 0 0 0 +0 0 0 0 59 245 255 255 255 255 255 255 255 255 125 0 59 245 255 255 255 +255 255 125 0 0 89 255 255 255 255 255 225 21 59 245 255 255 255 255 255 +125 0 0 0 59 245 255 255 255 255 255 125 7 206 166 0 0 175 171 206 166 +89 247 34 0 175 201 59 241 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 12 228 34 175 255 125 0 0 89 255 255 255 125 175 251 89 89 255 125 +0 7 206 255 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 245 255 255 +255 255 255 125 0 0 7 206 255 125 59 245 125 0 0 0 89 251 89 0 0 0 0 0 +0 0 127 7 206 225 21 0 0 0 0 59 115 0 0 0 0 59 115 0 0 0 0 0 0 0 175 201 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 245 255 255 255 255 125 0 59 245 +255 255 255 255 125 0 0 0 0 0 0 0 89 247 34 12 228 34 0 138 166 0 0 0 0 +0 0 0 0 0 0 12 235 125 0 7 176 21 0 0 0 0 0 0 138 251 89 0 0 138 201 0 +0 0 0 0 0 59 115 0 0 0 0 59 115 0 0 0 0 0 0 7 206 166 0 59 115 0 0 0 0 +59 115 0 0 0 59 115 0 0 0 0 59 115 0 89 201 0 12 232 89 89 201 7 202 89 +12 232 89 138 201 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 7 199 34 0 172 132 196 199 163 125 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 115 0 0 0 0 59 115 0 0 0 0 0 0 0 89 247 +34 0 7 206 125 0 0 0 0 0 0 0 0 127 89 247 34 0 0 0 0 0 59 115 0 0 0 0 59 +115 0 0 0 0 0 0 7 206 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 199 +34 0 0 0 0 0 7 199 34 0 0 0 0 0 0 0 0 0 89 225 21 7 202 89 12 228 34 0 +0 0 0 0 0 0 0 0 0 59 238 34 0 0 0 0 0 0 0 130 34 59 241 89 0 0 0 138 201 +0 0 0 0 0 0 59 115 0 0 0 0 59 115 0 0 0 0 0 0 175 225 21 0 59 115 0 0 0 +0 59 115 0 0 0 59 115 0 0 0 0 59 115 0 12 228 34 59 192 0 12 228 34 138 +166 59 215 21 175 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 7 199 34 0 172 89 175 166 138 125 0 138 255 255 247 34 +12 146 0 0 0 0 89 255 255 255 125 12 235 255 255 125 0 0 0 59 115 0 0 0 +0 59 115 0 138 255 255 255 255 127 0 175 201 0 138 225 21 0 0 0 0 0 0 0 +0 127 245 255 255 255 255 255 125 0 59 115 0 0 0 0 59 115 0 0 0 0 0 0 12 +232 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 199 34 0 0 0 0 0 7 199 +34 0 0 0 0 0 0 0 0 0 89 247 34 12 228 34 138 166 0 0 0 0 0 0 0 0 0 0 0 +12 235 166 0 0 0 0 0 0 175 225 21 138 225 21 0 0 0 138 201 0 0 0 0 0 0 +59 115 0 0 0 0 59 115 0 0 0 0 0 89 247 34 0 0 59 115 0 0 0 0 59 115 0 0 +0 59 115 0 0 0 0 59 115 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 255 166 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 199 34 0 172 +89 0 0 138 125 59 238 34 0 130 34 7 206 201 0 0 59 241 89 0 12 235 255 +125 0 59 241 89 0 0 59 115 0 0 0 0 59 115 0 0 0 0 89 247 34 0 59 245 166 +241 89 0 0 0 0 0 0 0 0 0 127 138 225 21 0 0 0 0 0 59 115 0 0 0 0 59 115 +0 0 0 0 0 89 255 255 255 247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 199 +34 0 0 0 0 0 7 199 34 0 0 0 0 0 0 0 0 0 0 175 255 255 166 59 215 21 175 +255 255 125 0 89 255 255 201 0 0 0 59 245 255 255 125 0 12 235 166 0 0 +138 225 21 0 0 0 138 255 255 255 255 247 34 0 59 115 0 0 0 0 59 115 0 0 +0 0 59 245 125 0 0 0 59 115 0 0 0 0 59 115 0 0 0 59 115 0 0 0 0 59 115 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 245 255 251 102 0 255 255 255 255 +255 0 245 255 255 255 255 255 255 255 255 255 255 127 21 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 59 241 89 0 0 0 0 0 138 247 34 138 201 0 0 0 175 +201 0 0 0 175 166 0 0 59 115 0 0 0 0 59 115 0 0 0 12 235 125 0 0 0 138 +255 166 0 0 0 0 0 0 0 0 0 0 127 245 255 255 255 255 225 21 0 59 115 0 0 +0 0 59 115 0 0 0 0 0 0 89 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 7 199 34 0 0 0 59 245 255 255 255 255 125 0 0 0 0 0 0 0 0 0 0 0 0 175 +125 89 225 21 59 238 47 232 89 7 206 125 0 0 0 0 0 138 251 89 12 235 166 +0 0 138 225 21 0 0 0 138 201 0 0 0 0 0 0 59 115 0 0 0 0 59 115 0 0 0 7 +206 201 0 0 0 0 59 115 0 0 0 0 59 115 0 0 0 59 115 0 0 0 0 59 115 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 245 255 251 89 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 255 255 201 0 +0 0 138 247 34 175 201 0 0 0 138 255 255 255 255 255 166 0 0 59 115 0 0 +0 0 59 115 0 0 7 206 166 0 0 0 0 59 241 89 0 0 0 0 0 0 0 0 0 0 127 89 251 +89 0 0 0 0 0 59 115 0 0 0 0 59 115 0 0 0 0 0 0 138 201 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 7 199 34 0 0 0 0 0 7 199 34 0 0 0 0 0 0 0 0 0 +0 0 0 0 59 215 21 138 201 0 12 228 47 228 34 0 175 166 0 0 0 0 0 12 232 +89 0 0 175 225 21 59 241 89 0 0 0 138 201 0 0 0 0 0 0 59 115 0 0 0 0 59 +115 0 0 0 138 225 21 0 0 0 0 59 115 0 0 0 0 59 115 0 0 0 59 115 0 0 0 0 +59 115 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 255 166 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 +245 125 7 206 201 0 0 138 201 0 0 0 175 201 0 0 0 0 0 0 0 59 115 0 0 0 +0 59 115 0 0 138 225 21 0 0 0 0 59 241 89 0 0 0 0 0 0 0 0 0 0 127 7 206 +247 34 0 0 0 0 59 115 0 0 0 0 59 115 0 59 245 125 0 0 175 166 0 0 0 59 +245 125 175 225 29 206 166 0 89 247 34 7 206 166 0 0 0 7 199 34 0 0 0 0 +0 7 199 34 0 0 0 0 0 0 0 0 0 0 0 0 7 202 89 0 89 225 21 59 238 47 232 89 +7 206 125 0 89 166 0 0 89 247 34 0 0 0 130 34 0 138 255 125 0 0 138 201 +0 0 0 0 0 0 59 115 0 0 0 0 59 115 0 0 89 251 89 0 0 0 0 0 59 115 0 0 0 +0 59 115 0 0 0 59 115 0 0 0 0 59 115 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 89 125 0 12 232 89 12 146 0 0 0 59 241 89 0 12 235 247 +34 0 0 89 125 0 0 59 115 0 0 0 0 59 115 0 59 241 89 0 0 0 0 0 59 241 89 +0 0 0 0 0 0 0 0 0 0 127 0 0 175 255 255 255 225 21 59 245 255 255 255 255 +255 125 0 138 225 21 0 12 235 125 0 0 0 138 225 34 235 125 7 206 166 0 +89 247 34 7 206 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +138 201 0 0 0 175 255 255 125 0 89 255 255 201 0 0 12 235 255 255 251 89 +0 0 0 0 0 0 0 0 89 255 255 255 255 255 255 255 255 255 125 0 59 245 255 +255 255 255 255 125 0 0 175 255 255 255 255 255 247 34 59 245 255 255 255 +255 255 125 0 0 0 59 245 255 255 255 255 255 125 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 245 255 255 166 0 0 0 0 0 0 0 89 255 255 +255 125 59 245 255 255 201 0 0 0 59 245 255 255 255 255 255 125 0 175 255 +255 255 255 127 0 0 59 241 89 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 175 166 0 255 255 201 0 0 0 0 175 166 59 238 34 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 228 34 0 0 +0 0 0 0 0 12 228 34 138 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 127 127 +127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 0 127 127 127 +127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 +0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 +127 127 0 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 +127 127 0 127 127 127 127 127 127 127 0 127 127 127 0 127 127 127 127 127 +127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 0 +127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 127 127 0 127 127 0 127 127 0 127 127 127 127 0 +127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 0 127 127 +127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 +127 0 127 127 127 127 127 127 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 127 +0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 245 255 255 255 255 255 +251 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 12 228 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 255 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 138 225 21 +0 0 0 138 125 0 0 0 0 59 245 255 255 125 0 0 0 0 0 0 0 0 138 225 21 0 0 +175 166 0 12 228 34 0 0 59 245 255 255 247 34 0 89 225 29 206 166 0 0 0 +0 0 89 255 255 255 255 125 0 0 0 7 206 255 255 247 34 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 255 255 255 255 125 0 0 0 0 0 0 0 +0 0 0 0 0 138 255 255 166 0 0 0 0 7 202 89 0 0 0 0 0 12 235 255 125 0 0 +175 255 255 225 21 0 0 0 12 235 125 0 0 0 0 0 0 0 0 0 0 0 138 255 255 255 +255 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 228 34 0 0 89 255 255 225 21 0 0 +0 0 0 0 0 0 0 0 0 138 166 0 0 0 89 225 21 0 0 0 0 0 138 166 0 0 0 89 225 +21 0 0 0 12 235 255 255 166 0 0 7 206 125 0 0 0 0 0 0 89 247 34 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 138 225 21 0 0 0 138 125 0 0 0 12 +235 125 0 59 115 0 0 0 0 0 0 0 0 7 206 125 0 59 215 21 0 12 228 34 0 12 +235 125 0 0 168 34 0 0 0 0 0 0 0 0 0 0 175 225 21 0 0 0 175 225 21 0 0 +0 0 0 138 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 225 +21 0 0 0 175 225 21 0 0 0 0 0 0 0 0 0 59 238 34 7 206 125 0 0 0 7 202 89 +0 0 0 0 7 199 34 59 238 34 0 0 0 7 202 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 89 255 255 255 125 175 125 0 0 0 0 0 0 0 0 0 0 0 0 0 138 255 247 34 0 +59 241 89 0 175 201 0 0 0 0 0 0 0 0 0 7 206 255 166 0 0 12 232 89 0 0 0 +0 7 206 255 166 0 0 12 232 89 0 0 0 0 0 0 0 59 215 21 0 89 201 0 0 0 0 +0 0 0 89 247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 7 +206 255 255 251 89 0 59 241 89 0 0 0 138 201 0 0 0 138 201 0 0 89 225 21 +175 125 0 0 12 228 34 0 12 235 125 0 0 0 0 0 0 0 0 0 0 0 0 0 138 166 0 +89 255 255 247 34 89 201 0 0 89 255 255 255 166 0 0 0 0 168 34 7 151 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 166 7 206 255 255 225 21 89 201 0 0 0 +0 0 0 0 0 0 89 166 0 0 138 166 0 0 0 7 202 89 0 0 0 0 0 0 0 59 238 34 0 +7 206 255 125 0 0 0 0 0 0 0 0 0 59 238 34 0 0 175 166 0 175 255 255 255 +125 175 125 0 138 247 34 0 0 0 0 0 0 0 0 0 0 12 228 34 0 89 201 0 0 89 +225 0 81 115 0 134 89 0 0 0 0 0 138 166 0 0 138 166 0 0 0 0 0 0 0 138 166 +0 0 138 166 0 0 0 0 0 0 59 245 247 34 0 12 232 89 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 89 201 0 7 206 201 138 125 +138 125 0 59 241 89 0 0 0 0 175 255 255 255 225 21 0 0 7 206 166 215 21 +0 0 12 228 34 0 0 138 255 255 251 89 0 0 0 0 0 0 0 0 0 12 206 21 59 241 +89 0 134 89 0 172 89 59 238 34 0 138 166 0 0 7 206 201 12 235 125 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 12 206 21 7 202 89 12 235 125 0 172 89 0 0 0 0 +0 0 0 0 59 238 34 7 206 125 12 235 255 255 255 255 255 255 125 0 0 0 12 +235 125 0 0 0 0 7 206 125 0 0 0 0 0 0 0 0 59 238 34 0 0 175 166 0 175 255 +255 255 125 175 125 0 138 247 34 0 0 0 0 0 0 0 0 0 0 12 228 34 0 89 201 +0 0 89 225 0 29 206 166 59 245 125 0 0 0 0 138 166 0 12 228 34 0 175 225 +21 0 0 0 138 166 0 12 228 42 206 255 255 166 0 0 0 0 12 228 34 138 166 +0 89 247 34 0 0 0 0 59 238 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 +0 0 138 201 0 59 241 89 138 125 0 0 59 245 255 255 255 125 0 0 138 166 +0 89 201 0 0 0 0 89 255 125 0 0 0 0 0 0 0 7 206 125 0 138 251 89 0 0 0 +0 0 0 0 0 89 166 0 138 201 0 0 0 0 0 89 166 59 215 21 0 175 166 0 59 245 +125 89 251 89 0 0 12 235 255 255 255 255 255 255 125 138 255 255 251 89 +127 166 0 7 202 89 12 232 89 0 89 166 0 0 0 0 0 0 0 0 0 138 255 255 166 +0 0 0 0 7 202 89 0 0 0 0 0 59 241 89 0 0 0 0 0 7 206 125 0 0 0 0 0 0 0 +0 59 238 34 0 0 175 166 0 89 255 255 255 125 175 125 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 12 228 34 0 59 241 89 0 175 201 0 0 0 175 201 7 206 201 0 0 0 +138 166 0 175 166 0 138 200 215 21 0 0 0 138 166 0 175 166 7 151 0 89 247 +34 0 0 0 59 238 47 228 34 59 219 209 34 0 0 0 89 255 125 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 138 225 21 59 238 34 138 125 0 0 0 59 +241 89 0 0 0 0 138 166 0 89 201 0 0 59 245 255 255 255 255 125 0 0 0 0 +0 59 238 34 0 7 206 125 0 0 0 0 0 0 0 0 89 166 0 138 201 0 0 0 0 0 89 166 +0 175 255 255 223 166 0 12 235 125 59 241 89 0 0 0 0 0 0 0 0 0 175 125 +0 0 0 0 0 138 125 0 7 206 255 255 125 0 0 59 157 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 7 202 89 0 0 0 0 7 206 255 255 255 166 7 206 255 255 201 0 +0 0 0 0 0 0 0 0 59 238 34 0 0 175 166 0 0 89 255 255 125 175 125 0 0 0 +0 0 0 0 0 0 0 0 0 0 89 255 255 251 89 0 89 255 255 225 21 0 0 0 175 225 +29 206 166 0 0 0 138 166 59 215 21 59 215 81 215 21 0 0 0 138 166 59 215 +21 0 0 0 89 225 21 59 245 255 255 125 138 166 7 202 97 199 34 0 0 89 251 +89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 138 225 21 59 241 +89 138 125 0 0 0 89 247 34 0 0 0 0 175 255 255 255 225 21 0 0 0 12 232 +89 0 0 0 12 228 34 0 12 235 225 21 59 215 21 0 0 0 0 0 0 0 0 12 206 21 +59 241 89 0 134 89 0 172 89 0 0 0 0 0 0 0 0 7 206 201 12 235 125 0 0 0 +0 0 0 0 0 175 125 0 0 0 0 0 12 206 21 7 202 89 7 206 125 0 172 89 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 202 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 59 238 34 0 0 175 166 0 0 0 0 175 125 175 125 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 166 59 245 125 0 0 0 0 0 0 +175 125 12 228 34 59 215 21 0 0 0 0 0 175 125 0 0 0 12 232 89 0 0 0 0 0 +59 238 34 175 125 7 199 34 0 0 175 201 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 127 0 0 0 0 0 138 225 21 7 206 201 138 125 138 125 7 202 89 0 0 0 +0 138 201 0 0 0 138 166 0 0 0 12 232 89 0 0 0 12 228 34 0 0 0 175 255 255 +166 0 0 0 0 0 0 0 0 0 0 138 166 0 89 255 255 247 34 89 201 0 0 0 0 0 0 +0 0 0 0 0 168 34 7 151 0 0 0 0 0 0 0 0 175 125 0 0 0 0 0 0 138 166 7 202 +89 0 89 247 124 201 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 255 255 255 255 +255 255 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 245 125 0 7 206 +166 0 0 0 0 175 125 175 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 59 115 0 134 89 0 0 0 0 0 0 59 215 21 59 245 255 255 255 225 21 0 +0 0 59 215 21 0 0 59 238 34 0 0 0 0 0 0 175 125 7 206 255 255 255 251 89 +0 138 247 34 0 59 157 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 138 225 +21 0 7 206 255 255 251 89 138 255 255 255 255 255 166 0 0 0 0 0 0 0 0 0 +0 12 232 89 0 0 0 12 228 34 0 0 0 0 0 59 241 89 0 0 0 0 0 0 0 0 0 0 175 +225 21 0 0 0 175 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 175 225 21 0 0 0 175 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 238 198 +255 251 194 166 0 0 0 0 175 125 175 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 125 0 0 0 0 89 225 21 0 0 0 +7 206 125 0 0 12 235 255 255 255 166 0 0 0 89 225 21 0 0 0 12 228 34 0 +0 0 175 255 255 255 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 +0 0 0 0 138 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 228 +34 0 7 176 21 0 89 247 34 0 0 0 0 0 0 0 0 0 0 0 89 255 255 255 255 125 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 +255 255 255 255 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 238 34 0 0 0 0 0 0 0 0 175 +125 175 125 0 0 0 0 0 0 0 0 59 215 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 +0 0 0 0 0 0 0 138 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +12 228 34 0 7 206 255 255 251 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 238 34 0 0 0 0 0 0 0 0 175 125 175 125 +0 0 0 0 0 0 59 245 251 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 127 127 0 127 127 +127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 0 127 127 127 127 +127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 +127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 127 0 127 127 127 127 0 127 127 127 127 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 +0 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 +127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 0 127 127 127 127 0 127 127 127 127 127 127 0 127 +127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 127 127 127 0 +127 127 127 127 127 127 127 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 89 +255 125 0 0 0 0 0 0 12 235 201 0 0 0 0 12 235 251 89 0 0 0 0 175 255 125 +89 201 0 0 0 0 0 0 0 0 0 0 0 59 245 247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 89 255 125 0 0 0 0 0 0 138 251 89 0 0 0 12 235 251 +89 0 0 0 0 0 0 0 0 7 206 225 21 0 0 0 89 255 125 0 89 255 225 21 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 247 34 172 89 0 0 0 0 7 206 225 21 0 0 +0 0 0 0 0 89 255 125 0 0 0 0 0 0 89 255 225 21 0 0 0 0 12 235 247 34 172 +89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 +255 125 0 0 0 0 0 0 0 7 206 225 21 0 0 0 0 89 255 225 21 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 89 255 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 +0 89 247 34 0 0 0 0 0 175 166 0 0 0 0 7 206 125 59 241 89 0 0 89 201 12 +235 247 34 0 0 7 206 166 59 241 89 0 0 12 228 34 59 215 21 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 238 34 0 0 0 0 89 247 34 0 0 0 7 +206 125 59 241 89 0 7 206 166 59 238 34 0 0 175 166 0 0 59 241 89 0 89 +247 34 138 201 59 238 34 138 201 0 0 0 0 0 0 0 0 0 0 0 175 125 89 255 201 +0 0 0 0 0 0 0 175 201 0 0 0 0 0 0 12 232 89 0 0 0 0 0 0 59 238 34 138 225 +21 0 0 0 175 125 89 255 201 0 0 0 0 59 238 34 138 201 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 247 34 0 0 0 0 0 0 138 201 0 0 0 0 +0 59 238 34 138 225 21 0 0 0 59 238 34 138 201 0 0 0 0 12 232 89 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 228 34 59 215 21 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 255 255 125 0 +0 0 0 127 0 0 12 235 225 21 0 0 0 0 12 235 225 21 0 0 0 0 12 235 225 21 +0 0 0 0 12 235 225 21 0 0 0 0 12 235 225 21 0 0 0 0 12 235 225 21 0 0 0 +0 0 175 255 255 255 255 255 255 255 166 0 0 138 255 255 255 251 89 59 245 +255 255 255 255 127 81 245 255 255 255 255 225 21 59 245 255 255 255 255 +127 81 245 255 255 255 255 127 111 255 255 255 125 89 255 255 255 125 89 +255 255 255 125 89 255 255 255 125 7 206 255 255 255 255 125 0 0 59 245 +247 34 0 0 59 241 89 0 0 0 138 255 255 255 166 0 0 0 0 138 255 255 255 +166 0 0 0 0 0 138 255 255 255 166 0 0 0 0 138 255 255 255 166 0 0 0 0 138 +255 255 255 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 255 255 255 210 235 166 +59 241 89 0 0 0 59 241 89 59 241 89 0 0 0 59 241 89 59 241 89 0 0 0 59 +241 89 59 241 89 0 0 0 59 241 132 245 125 0 0 0 89 251 89 12 232 89 0 0 +0 0 7 206 166 0 89 251 89 0 0 0 127 0 0 89 232 241 89 0 0 0 0 89 232 241 +89 0 0 0 0 89 232 241 89 0 0 0 0 89 232 241 89 0 0 0 0 89 232 241 89 0 +0 0 0 89 232 241 89 0 0 0 0 12 232 89 89 225 21 0 0 0 0 0 175 247 34 0 +0 59 192 59 241 89 0 0 0 0 59 241 89 0 0 0 0 0 59 241 89 0 0 0 0 59 241 +89 0 0 0 0 0 59 241 89 0 0 59 241 89 0 0 59 241 89 0 0 59 241 89 0 7 206 +166 0 0 59 245 201 0 59 245 255 201 0 0 59 241 89 0 0 138 251 89 0 12 235 +166 0 0 138 251 89 0 12 235 166 0 0 0 138 251 89 0 12 235 166 0 0 138 251 +89 0 12 235 166 0 0 138 251 89 0 12 235 166 0 0 0 138 166 0 0 0 12 228 +34 0 0 175 247 34 0 0 175 225 21 59 241 89 0 0 0 59 241 89 59 241 89 0 +0 0 59 241 89 59 241 89 0 0 0 59 241 89 59 241 89 0 0 0 59 241 89 89 247 +34 0 7 206 125 0 12 232 89 0 0 0 0 59 241 89 0 12 232 89 0 0 0 127 0 7 +206 166 175 166 0 0 0 7 206 166 175 166 0 0 0 7 206 166 175 166 0 0 0 7 +206 166 175 166 0 0 0 7 206 166 175 166 0 0 0 0 175 166 175 166 0 0 0 0 +138 225 21 89 225 21 0 0 0 0 59 241 89 0 0 0 0 0 59 241 89 0 0 0 0 59 241 +89 0 0 0 0 0 59 241 89 0 0 0 0 59 241 89 0 0 0 0 0 59 241 89 0 0 59 241 +89 0 0 59 241 89 0 0 59 241 89 0 7 206 166 0 0 0 59 245 125 59 241 132 +241 89 0 59 241 89 0 12 235 166 0 0 0 89 247 34 12 235 166 0 0 0 89 247 +34 0 12 235 166 0 0 0 89 247 34 12 235 166 0 0 0 89 247 34 12 235 166 0 +0 0 89 247 34 0 0 12 235 125 0 12 235 125 0 0 59 241 89 0 0 138 176 235 +166 59 241 89 0 0 0 59 241 89 59 241 89 0 0 0 59 241 89 59 241 89 0 0 0 +59 241 89 59 241 89 0 0 0 59 241 89 0 175 201 0 138 225 21 0 12 235 255 +255 255 225 21 59 238 34 0 138 225 21 0 0 0 127 0 59 238 34 89 247 34 0 +0 59 238 34 89 247 34 0 0 59 238 34 89 247 34 0 0 59 238 34 89 247 34 0 +0 59 238 34 89 247 34 0 0 59 241 89 89 225 21 0 0 7 206 125 0 89 225 21 +0 0 0 0 138 225 21 0 0 0 0 0 59 241 89 0 0 0 0 59 241 89 0 0 0 0 0 59 241 +89 0 0 0 0 59 241 89 0 0 0 0 0 59 241 89 0 0 59 241 89 0 0 59 241 89 0 +0 59 241 89 0 7 206 166 0 0 0 7 206 166 59 241 89 138 225 21 59 241 89 +0 59 241 89 0 0 0 59 241 89 59 241 89 0 0 0 59 241 89 0 59 241 89 0 0 0 +59 241 89 59 241 89 0 0 0 59 241 89 59 241 89 0 0 0 59 241 89 0 0 0 12 +235 138 235 125 0 0 0 138 225 21 0 59 215 21 175 201 59 241 89 0 0 0 59 +241 89 59 241 89 0 0 0 59 241 89 59 241 89 0 0 0 59 241 89 59 241 89 0 +0 0 59 241 89 0 59 245 166 241 89 0 0 12 232 89 0 0 175 225 59 238 47 235 +225 21 0 0 0 0 127 0 138 201 0 12 235 125 0 0 138 201 0 12 235 125 0 0 +138 201 0 12 235 125 0 0 138 201 0 12 235 125 0 0 138 201 0 12 235 125 +0 0 138 225 21 12 235 125 0 0 89 247 34 0 89 255 255 255 255 251 89 138 +225 21 0 0 0 0 0 59 245 255 255 255 255 127 59 245 255 255 255 255 166 +0 59 245 255 255 255 255 127 59 245 255 255 255 255 127 0 59 241 89 0 0 +59 241 89 0 0 59 241 89 0 0 59 241 89 7 206 255 255 255 166 0 0 175 201 +59 241 89 12 235 125 59 241 89 0 59 241 89 0 0 0 12 235 125 59 241 89 0 +0 0 12 235 125 0 59 241 89 0 0 0 12 235 125 59 241 89 0 0 0 12 235 125 +59 241 89 0 0 0 12 235 125 0 0 0 0 12 235 125 0 0 0 0 138 225 21 7 199 +34 0 138 225 81 241 89 0 0 0 59 241 89 59 241 89 0 0 0 59 241 89 59 241 +89 0 0 0 59 241 89 59 241 89 0 0 0 59 241 89 0 0 138 255 166 0 0 0 12 232 +89 0 0 89 247 59 238 34 0 59 245 125 0 0 0 127 7 206 125 0 0 175 201 0 +7 206 125 0 0 175 201 0 7 206 125 0 0 175 201 0 7 206 125 0 0 175 201 0 +7 206 125 0 0 175 201 0 7 206 125 0 0 175 201 0 7 206 255 255 255 255 225 +21 0 0 0 0 138 225 21 0 0 0 0 0 59 241 89 0 0 0 0 59 241 89 0 0 0 0 0 59 +241 89 0 0 0 0 59 241 89 0 0 0 0 0 59 241 89 0 0 59 241 89 0 0 59 241 89 +0 0 59 241 89 0 7 206 166 0 0 0 7 206 166 59 241 89 0 89 247 94 241 89 +0 59 241 89 0 0 0 59 241 89 59 241 89 0 0 0 59 241 89 0 59 241 89 0 0 0 +59 241 89 59 241 89 0 0 0 59 241 89 59 241 89 0 0 0 59 241 89 0 0 0 12 +235 138 235 125 0 0 0 138 225 21 175 125 0 0 175 201 59 241 89 0 0 0 59 +241 89 59 241 89 0 0 0 59 241 89 59 241 89 0 0 0 59 241 89 59 241 89 0 +0 0 59 241 89 0 0 59 241 89 0 0 0 12 232 89 0 7 206 201 59 238 34 0 0 138 +201 0 0 0 127 59 245 255 255 255 255 247 34 59 245 255 255 255 255 247 +34 59 245 255 255 255 255 247 34 59 245 255 255 255 255 247 34 59 245 255 +255 255 255 247 34 59 245 255 255 255 255 247 34 59 241 89 0 0 89 225 21 +0 0 0 0 59 241 89 0 0 0 0 0 59 241 89 0 0 0 0 59 241 89 0 0 0 0 0 59 241 +89 0 0 0 0 59 241 89 0 0 0 0 0 59 241 89 0 0 59 241 89 0 0 59 241 89 0 +0 59 241 89 0 7 206 166 0 0 0 59 241 89 59 241 89 0 7 206 200 241 89 0 +12 235 166 0 0 0 89 247 34 12 235 166 0 0 0 89 247 34 0 12 235 166 0 0 +0 89 247 34 12 235 166 0 0 0 89 247 34 12 235 166 0 0 0 89 247 34 0 0 12 +235 125 0 12 235 125 0 0 59 241 159 166 0 0 12 235 166 12 232 89 0 0 0 +59 238 34 12 232 89 0 0 0 59 238 34 12 232 89 0 0 0 59 238 34 12 232 89 +0 0 0 59 238 34 0 0 59 241 89 0 0 0 12 235 255 255 255 201 0 59 238 34 +0 0 138 201 0 0 0 127 138 201 0 0 0 12 235 125 138 201 0 0 0 12 235 125 +138 201 0 0 0 12 235 125 138 201 0 0 0 12 235 125 138 201 0 0 0 12 235 +125 138 201 0 0 0 12 235 125 175 201 0 0 0 89 225 21 0 0 0 0 0 175 247 +34 0 0 59 192 59 241 89 0 0 0 0 59 241 89 0 0 0 0 0 59 241 89 0 0 0 0 59 +241 89 0 0 0 0 0 59 241 89 0 0 59 241 89 0 0 59 241 89 0 0 59 241 89 0 +7 206 166 0 0 59 245 201 0 59 241 89 0 0 59 245 251 89 0 0 138 251 89 0 +59 245 166 0 0 138 251 89 0 59 245 166 0 0 0 138 251 89 0 59 245 166 0 +0 138 251 89 0 59 245 166 0 0 138 251 89 0 59 245 166 0 0 0 138 166 0 0 +0 12 228 34 0 0 175 247 34 0 7 206 225 21 0 138 225 21 0 7 206 166 0 0 +138 225 21 0 7 206 166 0 0 138 225 21 0 7 206 166 0 0 138 225 21 0 7 206 +166 0 0 0 59 241 89 0 0 0 12 232 89 0 0 0 0 59 238 34 0 12 235 125 0 0 +0 127 206 125 0 0 0 0 175 206 206 125 0 0 0 0 175 206 206 125 0 0 0 0 175 +206 206 125 0 0 0 0 175 206 206 125 0 0 0 0 175 206 206 125 0 0 0 0 175 +232 245 125 0 0 0 89 255 255 255 255 255 166 0 0 138 255 255 255 251 89 +59 245 255 255 255 255 127 81 245 255 255 255 255 225 21 59 245 255 255 +255 255 127 81 245 255 255 255 255 127 111 255 255 255 125 89 255 255 255 +125 89 255 255 255 125 89 255 255 255 125 7 206 255 255 255 255 125 0 0 +59 241 89 0 0 0 175 251 89 0 0 0 138 255 255 255 166 0 0 0 0 138 255 255 +255 166 0 0 0 0 0 138 255 255 255 166 0 0 0 0 138 255 255 255 166 0 0 0 +0 138 255 255 255 166 0 0 0 0 0 0 0 0 0 0 0 0 0 7 202 194 255 255 255 201 +0 0 0 0 59 245 255 251 89 0 0 0 0 59 245 255 251 89 0 0 0 0 59 245 255 +251 89 0 0 0 0 59 245 255 251 89 0 0 0 0 59 241 89 0 0 0 12 232 89 0 0 +0 0 59 238 47 235 255 166 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 12 228 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 +166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 255 166 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 127 127 127 127 127 127 0 127 127 127 +127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 +127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 +127 0 127 127 127 127 127 127 0 127 127 127 127 0 127 127 127 127 0 127 +127 127 127 0 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 0 +0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 255 201 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 7 206 +225 21 0 0 0 0 0 12 235 201 0 0 0 138 255 201 0 0 0 59 245 225 29 202 89 +0 0 0 0 0 0 0 0 138 166 7 202 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +7 206 225 21 0 0 0 0 0 12 235 201 0 0 0 89 255 225 21 0 0 0 0 0 0 0 0 175 +247 34 0 12 235 255 255 166 0 0 0 0 0 0 0 0 0 0 0 0 59 245 225 29 202 89 +0 0 138 251 89 0 0 0 0 0 7 206 225 21 0 0 0 89 255 225 21 0 0 59 245 225 +29 202 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 225 +21 0 0 0 0 0 89 255 125 0 0 0 89 255 225 21 0 0 0 0 0 0 0 0 0 0 0 0 138 +251 89 0 59 238 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 175 +166 0 0 0 0 7 206 166 0 0 0 89 225 21 175 201 0 7 202 89 138 255 166 0 +0 89 247 34 175 166 0 0 138 166 7 202 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 7 206 166 0 0 0 0 0 175 166 0 0 0 89 247 34 138 201 0 0 89 247 +34 175 201 0 0 138 201 0 175 200 215 34 235 247 47 232 0 138 255 225 111 +225 21 0 0 172 89 138 255 166 0 0 0 0 89 225 21 0 0 0 0 175 201 0 0 0 0 +89 247 34 138 201 0 0 172 89 138 255 166 0 0 59 238 34 138 201 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 175 166 0 0 0 0 59 241 89 0 0 0 89 +247 34 138 201 0 0 0 59 238 34 138 201 0 0 0 89 247 34 0 0 59 238 34 0 +0 0 0 0 138 225 29 206 166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 235 255 201 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 206 225 21 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 12 235 166 0 0 0 0 0 0 0 0 89 166 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 238 34 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 7 206 255 255 255 125 0 7 206 255 255 255 +125 0 7 206 255 255 255 125 0 7 206 255 255 255 125 0 7 206 255 255 255 +125 0 12 235 255 255 251 89 0 12 235 255 255 251 89 59 245 255 166 0 0 +59 245 255 255 201 0 12 235 255 251 89 0 0 12 235 255 251 89 0 0 12 235 +255 251 89 0 0 12 235 255 251 89 0 59 238 34 59 238 34 59 238 34 59 238 +34 0 59 241 89 175 225 21 0 59 241 194 255 255 125 0 0 12 235 255 247 34 +0 0 12 235 255 247 34 0 0 0 12 235 255 247 34 0 0 12 235 255 247 34 0 0 +12 235 255 247 34 0 0 0 0 0 12 235 166 0 0 0 0 7 206 255 255 225 21 0 59 +241 89 0 59 241 89 59 241 89 0 59 241 89 59 241 89 0 59 241 89 0 59 241 +89 0 59 241 97 206 166 0 0 12 235 125 59 238 163 255 255 201 7 206 166 +0 0 12 235 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 89 247 34 0 0 0 0 89 247 +34 0 0 0 0 89 247 34 0 0 0 0 89 247 34 0 0 0 0 89 247 34 0 0 0 0 138 225 +21 0 0 0 0 89 255 225 21 0 138 201 59 245 125 0 0 0 7 206 125 0 89 225 +21 7 206 125 0 89 225 21 7 206 125 0 89 225 21 7 206 125 0 89 225 21 59 +238 34 59 238 34 59 238 34 59 238 34 0 0 0 0 12 235 125 0 59 245 166 0 +89 247 34 7 206 166 0 138 225 21 7 206 166 0 138 225 21 0 7 206 166 0 138 +225 21 7 206 166 0 138 225 21 7 206 166 0 138 225 21 0 0 0 0 0 0 0 0 0 +0 12 232 89 0 138 251 89 0 59 241 89 0 59 241 89 59 241 89 0 59 241 89 +59 241 89 0 59 241 89 0 59 241 89 0 59 241 89 89 247 34 0 89 247 34 59 +245 166 0 7 206 166 89 247 34 0 89 247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 +59 241 89 0 0 0 0 59 241 89 0 0 0 0 59 241 89 0 0 0 0 59 241 89 0 0 0 0 +59 241 89 0 0 0 0 59 238 34 0 0 0 0 12 232 89 0 0 59 238 127 225 21 0 0 +0 59 238 34 0 59 238 34 59 238 34 0 59 238 34 59 238 34 0 59 238 34 59 +238 34 0 59 238 34 59 238 34 59 238 34 59 238 34 59 238 34 0 138 255 255 +255 255 201 0 59 241 89 0 59 241 89 59 241 89 0 59 241 89 59 241 89 0 59 +241 89 0 59 241 89 0 59 241 89 59 241 89 0 59 241 89 59 241 89 0 59 241 +89 0 12 235 255 255 255 255 255 255 166 138 201 0 59 157 175 201 0 59 241 +89 0 59 241 89 59 241 89 0 59 241 89 59 241 89 0 59 241 89 0 59 241 89 +0 59 241 89 12 235 125 0 175 166 0 59 238 34 0 0 138 225 34 235 125 0 175 +166 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 127 0 89 255 255 255 251 89 0 89 255 255 255 251 +89 0 89 255 255 255 251 89 0 89 255 255 255 251 89 0 89 255 255 255 251 +89 0 138 255 255 255 247 34 0 175 255 255 255 255 255 255 255 255 251 127 +201 0 0 0 0 59 245 255 255 255 251 89 59 245 255 255 255 251 89 59 245 +255 255 255 251 89 59 245 255 255 255 251 89 59 238 34 59 238 34 59 238 +34 59 238 34 138 247 34 0 0 138 201 0 59 241 89 0 59 241 89 59 238 34 0 +12 232 89 59 238 34 0 12 232 89 0 59 238 34 0 12 232 89 59 238 34 0 12 +232 89 59 238 34 0 12 232 89 0 0 0 0 0 0 0 0 0 0 175 201 7 176 21 138 201 +0 59 241 89 0 59 241 89 59 241 89 0 59 241 89 59 241 89 0 59 241 89 0 59 +241 89 0 59 241 89 0 175 201 12 232 89 0 59 238 34 0 0 138 225 21 175 201 +12 232 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 59 241 89 0 59 241 89 59 241 89 0 59 +241 89 59 241 89 0 59 241 89 59 241 89 0 59 241 89 59 241 89 0 59 241 89 +138 247 34 0 59 238 34 138 225 21 0 12 232 89 0 0 0 0 138 201 0 0 0 0 59 +238 34 0 0 0 0 59 238 34 0 0 0 0 59 238 34 0 0 0 0 59 238 34 0 0 0 0 59 +238 34 59 238 34 59 238 34 59 238 34 175 201 0 0 0 138 166 0 59 241 89 +0 59 241 89 59 241 89 0 59 241 89 59 241 89 0 59 241 89 0 59 241 89 0 59 +241 89 59 241 89 0 59 241 89 59 241 89 0 59 241 89 0 0 0 0 12 235 166 0 +0 0 138 201 134 89 0 175 166 0 59 241 89 0 59 241 89 59 241 89 0 59 241 +89 59 241 89 0 59 241 89 0 59 241 89 0 59 241 89 0 89 247 124 225 21 0 +59 238 34 0 0 138 201 0 89 247 124 225 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 89 247 +34 0 89 251 89 89 247 34 0 89 251 89 89 247 34 0 89 251 89 89 247 34 0 +89 251 89 89 247 34 0 89 251 89 175 201 0 0 175 247 34 175 201 0 0 59 245 +225 21 0 7 199 94 245 125 0 0 0 7 206 166 0 7 199 34 7 206 166 0 7 199 +34 7 206 166 0 7 199 34 7 206 166 0 7 199 34 59 238 34 59 238 34 59 238 +34 59 238 34 138 247 34 0 12 232 89 0 59 241 89 0 59 241 89 7 206 166 0 +138 225 21 7 206 166 0 138 225 21 0 7 206 166 0 138 225 21 7 206 166 0 +138 225 21 7 206 166 0 138 225 21 0 0 0 0 12 235 166 0 0 0 59 245 166 0 +59 241 89 0 12 235 125 0 175 251 89 12 235 125 0 175 251 89 12 235 125 +0 175 251 89 0 12 235 125 0 175 251 89 0 7 206 255 125 0 0 59 238 34 0 +12 235 125 0 7 206 255 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 175 255 255 232 +241 89 0 175 255 255 232 241 89 0 175 255 255 232 241 89 0 175 255 255 +232 241 89 0 175 255 255 232 241 89 12 235 255 255 166 238 34 12 235 255 +255 225 21 89 255 255 251 89 0 89 255 255 255 201 0 12 235 255 251 89 0 +0 12 235 255 251 89 0 0 12 235 255 251 89 0 0 12 235 255 251 89 0 59 238 +34 59 238 34 59 238 34 59 238 34 0 138 255 255 255 125 0 0 59 241 89 0 +59 241 89 0 12 235 255 247 34 0 0 12 235 255 247 34 0 0 0 12 235 255 247 +34 0 0 12 235 255 247 34 0 0 12 235 255 247 34 0 0 0 0 0 0 0 0 0 0 0 7 +206 255 255 225 21 0 0 0 89 255 255 166 241 89 0 89 255 255 166 241 89 +0 89 255 255 166 241 89 0 0 89 255 255 166 241 89 0 0 138 247 34 0 0 59 +245 166 255 255 166 0 0 0 138 247 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 215 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 138 125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 232 89 0 0 0 59 238 34 0 0 0 0 0 +12 232 89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 12 235 255 125 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 138 225 21 0 0 0 59 238 34 0 0 0 0 0 138 225 21 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 +127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 127 127 127 0 127 127 +127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 +127 127 127 127 0 127 127 127 127 127 127 0 127 127 0 127 127 0 127 127 +0 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 +127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 +127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 +127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/Extras/CDTestFramework/AntTweakBar/src/res/FontSmall.pgm b/Extras/CDTestFramework/AntTweakBar/src/res/FontSmall.pgm new file mode 100644 index 0000000..482ac79 --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/res/FontSmall.pgm @@ -0,0 +1,603 @@ +P2 +# Created by Paint Shop Pro +211 84 +255 +127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 +0 0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 0 0 0 255 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +0 0 0 0 255 0 255 0 255 0 0 0 255 0 0 255 0 0 0 255 0 0 0 0 255 255 0 0 +0 255 0 0 0 0 255 255 0 0 0 255 0 0 255 0 0 255 0 0 255 0 255 0 255 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 255 0 0 0 255 0 0 255 255 +255 0 0 255 255 255 0 0 0 0 0 255 0 255 255 255 255 0 0 255 255 0 0 255 +255 255 255 0 0 255 255 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 127 0 0 0 0 255 0 255 0 255 0 0 0 255 0 0 255 0 0 255 255 255 255 +0 255 0 0 255 0 255 0 0 0 0 255 0 0 255 0 0 255 0 255 0 0 0 0 255 0 0 255 +255 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 255 +255 0 0 0 0 0 255 0 0 0 0 255 0 0 0 255 255 0 255 0 0 0 0 255 0 0 0 0 0 +0 0 255 0 255 0 0 255 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +0 0 0 0 255 0 0 0 0 0 0 255 255 255 255 255 255 255 0 255 0 0 0 255 0 0 +255 0 255 0 0 0 0 255 0 0 255 0 0 0 0 255 0 0 0 0 255 0 255 0 255 0 255 +0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 +0 0 255 0 0 0 0 255 0 0 255 0 255 0 255 0 0 0 0 255 0 0 0 0 0 0 255 0 0 +255 0 0 255 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 0 255 255 0 0 0 0 0 0 +0 0 0 255 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +127 0 0 0 0 255 0 0 0 0 0 0 0 255 0 255 0 0 0 255 255 0 0 0 0 255 255 0 +255 0 255 255 0 0 0 255 255 0 255 0 0 0 255 0 0 0 0 255 0 0 0 255 0 0 0 +0 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 0 255 +0 0 0 0 255 0 0 0 255 255 0 0 255 0 0 255 0 255 255 255 0 0 255 255 255 +0 0 0 0 255 0 0 0 255 255 0 0 0 255 255 255 0 0 255 0 0 255 0 0 0 255 255 +0 0 0 255 255 255 255 255 255 0 0 0 0 255 255 0 0 0 0 255 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 255 0 0 0 0 0 255 255 255 255 255 +255 0 0 0 255 255 0 0 0 0 0 255 0 255 0 0 255 0 255 0 0 255 0 0 0 0 255 +0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 255 0 0 0 0 0 255 0 +0 255 0 0 255 0 0 255 0 0 0 255 0 0 0 0 0 0 255 0 255 255 255 255 255 0 +0 0 255 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 0 0 255 0 0 0 0 0 0 +0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 0 0 +255 0 255 0 0 0 0 255 0 255 0 0 255 0 255 0 0 255 255 0 0 0 255 0 0 0 0 +255 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 255 0 0 255 0 0 255 0 +0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 255 0 255 0 +0 255 0 0 255 0 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 255 0 0 0 255 255 +0 0 0 255 255 255 255 255 255 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 255 0 0 0 0 0 0 255 0 0 255 0 0 255 +255 255 255 0 0 0 0 255 0 0 0 255 255 0 0 0 255 255 0 0 255 0 0 255 0 0 +0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 255 0 0 0 0 255 +255 0 0 255 255 255 0 255 255 255 255 0 255 255 255 0 0 0 0 0 255 0 255 +255 255 0 0 0 255 255 0 0 255 0 0 0 0 0 255 255 0 0 0 255 255 0 0 0 255 +0 0 255 0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 255 255 0 0 0 0 0 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 127 127 0 127 0 127 127 127 +0 127 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 +127 127 127 0 127 127 127 127 127 0 127 0 127 127 0 127 127 127 0 127 127 +127 127 127 0 127 127 127 127 127 127 0 127 127 0 127 127 127 0 127 0 127 +127 127 0 127 127 127 127 0 127 127 127 0 127 127 127 127 0 127 127 127 +127 0 127 127 127 127 0 127 127 127 127 0 127 127 127 127 0 127 127 127 +127 0 127 127 127 127 0 127 127 127 127 0 127 127 0 127 127 0 127 127 127 +127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 +127 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 255 0 0 0 255 255 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 255 255 255 0 0 0 0 0 +255 255 0 0 0 255 255 255 0 0 0 0 0 255 255 255 0 0 255 255 255 255 0 0 +0 255 255 255 255 255 0 255 255 255 255 255 0 0 0 255 255 255 0 0 255 0 +0 0 0 255 0 255 255 255 0 0 255 255 0 255 0 0 0 255 0 255 0 0 0 255 255 +0 0 0 255 255 0 255 0 0 0 0 255 0 0 0 255 255 255 0 0 0 255 255 255 255 +0 0 0 0 255 255 255 0 0 0 255 255 255 255 0 0 0 255 255 255 255 0 255 255 +255 255 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 255 0 0 255 0 +255 0 0 255 0 255 0 0 0 255 0 255 255 255 255 0 255 0 0 255 0 0 0 0 255 +0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 255 0 +0 0 255 0 0 0 0 255 255 0 0 0 255 0 0 255 0 0 0 255 0 0 0 255 0 255 0 0 +0 255 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 255 0 255 0 0 0 0 255 +0 0 255 0 0 0 0 255 0 255 0 0 255 0 0 255 0 0 0 255 255 0 0 0 255 255 0 +255 255 0 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 0 255 +0 0 255 0 0 0 255 0 255 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 255 0 +0 0 0 255 0 255 0 0 255 0 0 255 0 255 0 0 255 0 0 255 0 255 0 0 0 0 0 255 +0 255 0 0 0 255 0 0 0 255 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 127 255 0 0 255 255 0 255 0 0 255 0 0 255 0 0 255 0 0 255 +0 0 255 0 0 0 0 0 0 255 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 +0 0 0 0 0 255 0 0 0 0 255 0 0 255 0 0 0 0 255 0 255 0 255 0 0 0 255 0 0 +0 255 0 255 0 255 0 255 0 255 0 255 0 0 255 0 255 0 0 0 0 0 255 0 255 0 +0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 255 0 255 0 0 0 0 0 0 0 255 0 0 +0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 255 0 255 0 255 0 0 255 255 +0 0 0 255 0 255 0 0 0 0 255 0 0 255 0 0 0 255 0 0 0 255 0 255 0 0 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 255 0 255 0 255 0 255 +0 0 255 0 0 255 0 0 255 255 255 255 0 0 255 0 0 0 0 0 0 255 0 0 0 0 255 +0 255 255 255 255 0 0 255 255 255 255 0 0 255 0 0 255 255 255 0 255 255 +255 255 255 255 0 0 255 0 0 0 0 255 0 255 255 0 0 0 0 255 0 0 0 255 0 255 +0 255 0 255 0 255 0 0 255 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 255 0 255 +0 0 0 0 0 255 0 255 255 255 255 0 0 0 255 255 255 0 0 0 0 255 0 0 0 255 +0 0 0 0 255 0 0 255 0 0 255 0 0 255 0 255 0 255 0 255 0 0 255 255 0 0 0 +0 255 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 255 0 255 0 255 0 255 0 255 255 255 +255 255 255 0 255 0 0 0 255 0 255 0 0 0 0 0 0 255 0 0 0 0 255 0 255 0 0 +0 0 0 255 0 0 0 0 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 0 255 0 0 0 0 255 +0 255 0 255 0 0 0 255 0 0 0 255 0 0 255 0 0 255 0 255 0 0 0 255 255 0 255 +0 0 0 0 0 255 0 255 255 255 255 0 0 255 0 0 0 0 0 255 0 255 0 255 0 0 0 +0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 255 0 0 255 0 0 255 0 255 +0 255 0 255 0 0 255 255 0 0 0 0 255 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 +0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 255 +0 0 255 255 255 0 0 255 0 0 0 0 255 0 255 0 0 0 255 0 0 255 0 0 0 255 0 +255 0 0 0 255 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 255 0 255 0 0 +0 0 255 0 0 255 0 0 0 0 255 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 +255 0 255 0 0 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 0 0 0 0 255 0 0 0 255 +0 0 255 0 0 255 0 0 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 0 255 +255 0 0 0 0 255 0 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 255 +0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 127 0 255 0 0 0 0 0 0 255 0 0 0 0 255 0 255 255 255 255 0 0 0 0 255 +255 255 0 0 255 255 255 255 0 0 0 255 255 255 255 255 0 255 0 0 0 0 0 0 +0 255 255 255 255 0 255 0 0 0 0 255 0 255 255 255 0 255 255 0 0 255 0 0 +0 255 0 255 255 255 255 255 0 0 0 0 0 255 0 255 0 0 0 0 255 0 0 0 255 255 +255 0 0 0 255 0 0 0 0 0 0 0 255 255 255 0 0 0 255 0 0 0 255 0 255 255 255 +255 0 0 0 0 255 0 0 0 0 255 255 255 255 0 0 0 0 255 255 0 0 0 0 255 0 0 +0 255 0 0 255 0 0 255 0 0 0 255 0 0 0 255 255 255 255 0 255 0 0 0 0 255 +0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 +0 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 +0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 +0 0 0 0 0 255 255 0 0 0 0 0 0 0 255 255 255 255 255 255 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 +0 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 +0 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 127 0 +127 127 127 127 127 127 0 127 127 127 0 127 127 127 0 127 127 127 127 127 +0 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 0 +127 127 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 +127 127 0 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 +0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 0 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 0 127 +127 0 127 127 127 0 127 127 0 127 127 127 127 127 0 127 127 127 127 127 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 127 255 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 +0 0 255 0 0 0 0 0 0 0 255 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 255 0 0 0 +0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 255 0 0 0 0 0 0 0 255 0 0 +0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 +255 0 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 +0 0 0 255 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 255 +0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 127 0 0 0 0 0 255 255 0 0 255 255 255 0 0 0 255 255 0 0 255 +255 255 0 0 255 255 0 0 255 255 255 0 255 255 255 0 255 255 255 0 0 255 +0 255 255 0 255 0 0 255 0 255 0 255 255 255 0 255 255 0 0 255 255 255 0 +0 0 255 255 0 0 255 255 255 0 0 0 255 255 255 0 255 0 255 255 255 255 0 +255 255 0 255 0 0 255 0 255 0 0 0 255 0 255 0 0 255 0 0 255 0 255 0 255 +0 255 0 0 0 255 0 255 255 255 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 +0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +0 0 0 0 0 0 0 255 0 255 0 0 255 0 255 0 0 0 255 0 0 255 0 255 0 0 255 0 +255 0 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 255 0 0 255 0 255 +0 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 +0 255 255 0 255 0 0 0 255 0 0 255 0 0 255 0 0 255 0 255 0 0 255 0 0 255 +0 0 255 0 0 255 0 0 0 255 0 255 0 0 0 0 255 0 0 255 0 0 0 255 0 0 0 255 +0 0 0 255 255 0 0 255 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 255 255 255 0 255 0 0 255 0 255 0 0 0 255 +0 0 255 0 255 255 255 255 0 255 0 0 255 0 0 255 0 255 0 0 255 0 255 0 0 +255 0 255 255 0 0 0 255 0 255 0 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 +0 255 0 0 255 0 255 0 0 255 0 255 0 0 0 255 0 0 255 0 0 255 0 0 255 0 0 +255 0 255 0 0 255 0 255 0 255 0 255 0 0 255 0 0 0 255 0 255 0 0 0 255 0 +0 255 0 0 0 0 255 0 0 0 0 255 0 255 0 0 255 255 0 0 0 255 0 0 0 0 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 255 0 0 255 0 +255 0 0 255 0 255 0 0 0 255 0 0 255 0 255 0 0 0 0 255 0 0 255 0 0 255 0 +255 0 0 255 0 255 0 0 255 0 255 0 255 0 0 255 0 255 0 0 255 0 0 255 0 255 +0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 0 0 255 0 255 +0 0 255 0 0 255 0 0 255 0 255 0 0 0 255 255 0 255 255 0 0 0 255 0 0 0 255 +0 255 0 0 255 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 255 0 +0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 +255 255 255 0 255 255 255 0 0 0 255 255 0 0 255 255 255 0 0 255 255 255 +0 255 0 0 0 255 255 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 +0 255 0 0 255 0 0 255 0 255 0 0 255 0 0 255 255 0 0 255 255 255 0 0 0 255 +255 255 0 255 0 0 255 255 255 0 0 255 0 0 255 255 255 0 0 0 255 0 0 0 0 +255 0 0 0 255 0 0 255 0 255 0 0 0 255 0 0 0 255 255 255 0 0 255 0 0 0 255 +0 0 0 255 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 +0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 +0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 127 127 0 127 127 +127 127 0 127 127 127 127 0 127 127 127 0 127 127 127 127 0 127 127 127 +127 0 127 127 0 127 127 127 127 0 127 127 127 127 0 127 0 127 127 0 127 +127 127 127 0 127 0 127 127 127 127 127 127 127 0 127 127 127 127 0 127 +127 127 127 0 127 127 127 127 0 127 127 127 127 0 127 127 0 127 127 127 +0 127 127 0 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 +127 127 0 127 127 127 0 127 127 127 127 127 0 127 127 127 0 127 127 127 +0 127 127 127 0 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 +0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 255 0 0 255 255 0 255 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 255 255 0 255 0 0 0 0 0 0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 127 0 255 255 255 0 0 255 255 255 255 255 255 255 0 0 0 0 +0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 255 0 255 +0 0 255 255 0 0 0 255 0 0 0 0 0 0 0 255 255 255 255 0 0 0 0 0 255 255 255 +255 255 255 255 0 0 255 255 255 255 255 255 255 0 255 255 255 255 0 0 255 +255 255 255 255 255 255 0 0 255 255 255 255 255 255 255 0 255 0 0 255 255 +0 255 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 255 255 255 +255 255 0 255 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 +255 255 255 0 0 255 0 0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 127 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 +0 0 0 0 0 0 0 0 255 255 255 255 255 0 255 255 255 255 255 0 0 0 0 0 0 255 +0 0 255 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 0 +255 0 0 0 0 0 255 0 0 0 0 255 0 0 255 0 0 0 0 0 255 0 0 255 0 0 0 0 0 255 +0 0 255 255 0 0 255 0 255 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 255 0 0 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 +0 0 0 0 255 0 0 0 0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 127 255 255 255 255 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 255 0 0 255 0 +255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 255 0 0 0 255 0 0 0 0 0 255 0 0 +0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 0 255 0 0 255 0 0 0 0 0 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 +0 255 0 255 0 255 255 255 0 255 0 0 0 255 255 0 255 255 0 0 0 255 0 0 0 +0 0 255 0 255 255 255 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 127 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 255 255 255 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 255 255 255 255 255 0 0 0 0 0 0 0 255 +255 0 255 0 255 255 0 255 255 0 0 0 255 255 255 0 0 255 0 0 255 0 0 0 255 +255 255 255 0 0 255 0 0 0 0 0 255 0 0 255 0 0 0 0 255 0 0 0 0 0 255 0 0 +255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 255 0 0 255 0 0 +255 0 0 255 0 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 127 255 255 255 255 0 0 255 0 0 0 0 0 255 0 0 0 +0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 +0 0 0 255 0 255 0 0 255 0 0 255 0 0 0 0 0 255 0 255 0 0 255 0 0 0 255 0 +0 0 0 0 255 0 0 0 0 0 255 0 0 255 0 0 0 0 255 0 0 0 0 0 255 0 0 255 0 0 +0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 0 255 255 255 255 0 255 +255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 255 0 +255 0 0 255 255 255 255 0 0 255 0 0 0 0 0 255 0 0 255 0 0 0 0 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 255 0 0 0 0 0 255 0 0 0 +0 0 255 0 0 255 0 0 255 0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 +255 0 0 0 0 0 0 0 0 0 0 0 255 0 255 0 0 255 0 0 255 0 0 0 0 0 255 0 0 255 +0 255 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 0 0 +0 255 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 255 0 0 255 0 +0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 255 255 255 0 0 255 255 255 255 255 +255 255 0 0 255 0 255 0 0 0 0 255 0 255 0 255 0 255 0 255 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 255 255 0 255 255 0 0 255 255 255 255 +0 0 0 0 0 0 255 255 255 255 255 255 255 0 0 255 255 255 255 255 255 255 +0 255 255 255 255 0 0 255 255 255 255 255 255 255 0 0 255 255 255 255 255 +255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 255 255 255 0 0 0 0 0 255 255 0 255 255 255 0 0 255 +255 255 255 255 255 255 0 255 255 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 255 255 +0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 127 127 127 127 0 127 127 127 127 127 127 127 127 +0 127 0 127 127 127 127 0 127 127 127 127 0 127 127 127 127 127 0 127 127 +127 127 127 0 127 127 127 127 127 0 127 127 127 127 0 127 127 127 127 127 +127 127 127 127 127 127 127 0 127 127 127 127 127 0 127 127 0 127 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 +0 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 127 0 127 +0 127 0 127 127 127 0 127 127 127 0 127 127 127 0 127 127 127 127 0 127 +127 127 127 127 127 127 0 127 127 127 127 0 127 127 127 127 127 127 127 +0 127 127 127 0 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 +127 127 127 127 0 127 127 127 0 127 127 127 127 127 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 255 0 0 0 255 0 0 0 0 255 255 0 0 +0 0 0 0 0 255 0 0 0 255 0 255 0 0 255 255 255 0 0 255 0 255 0 0 0 255 255 +255 255 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 +0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 255 255 255 0 255 255 255 0 0 255 +0 0 0 0 0 0 0 0 255 255 255 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 255 0 0 0 +0 0 0 0 0 255 0 0 255 0 0 0 0 0 255 0 0 0 255 0 0 0 255 255 255 0 0 255 +0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 255 +0 0 0 255 0 0 255 0 255 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 +0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 +0 255 0 255 0 0 0 0 255 0 0 0 0 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 255 +255 0 255 0 0 0 0 0 0 0 0 0 0 255 255 0 255 0 0 255 0 0 0 0 0 0 255 255 +0 255 0 0 0 0 0 255 255 0 0 255 0 0 0 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 127 0 0 0 0 0 255 0 0 255 255 255 0 0 255 0 0 0 0 255 255 255 +0 0 0 255 0 255 0 0 255 0 255 0 0 0 0 0 0 0 0 0 255 0 0 255 255 0 0 255 +255 0 255 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 255 0 255 255 255 0 0 255 +0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 255 0 +0 255 0 255 255 0 255 0 0 0 0 0 0 0 0 0 0 0 255 0 255 0 0 255 0 255 0 255 +0 0 0 255 0 255 0 0 0 0 0 0 255 0 0 255 0 0 0 0 0 0 255 0 255 0 0 0 0 0 +255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 255 0 255 0 255 0 0 255 255 255 0 0 0 +255 0 255 0 0 0 0 255 0 0 0 0 0 255 255 255 0 0 0 0 0 0 0 255 0 255 0 0 +0 0 255 0 255 255 0 255 0 255 0 0 0 255 255 255 255 255 0 0 0 0 255 0 255 +0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 0 0 255 255 255 0 +255 255 0 0 0 0 0 0 255 0 0 255 0 255 255 0 255 0 0 255 0 0 0 0 0 0 0 255 +255 255 0 255 255 0 0 0 255 0 255 0 0 255 255 0 0 255 255 0 0 0 255 0 255 +0 255 255 0 0 255 255 0 255 0 255 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 +0 0 0 255 0 255 0 255 0 0 0 255 0 0 0 0 255 255 255 0 0 0 255 255 255 0 +0 0 0 255 0 0 255 0 0 0 0 0 0 255 0 255 0 0 0 0 255 0 0 0 0 255 0 255 0 +0 0 0 0 0 0 255 0 255 255 0 255 0 255 255 255 0 0 255 0 0 0 0 0 0 0 0 0 +0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 255 0 0 +255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 255 0 0 0 255 0 255 0 255 0 0 +0 0 255 0 0 0 0 255 0 0 0 255 0 255 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 +0 0 0 0 0 255 0 255 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 +255 0 0 255 255 255 0 0 0 0 0 0 255 0 0 255 255 0 0 255 0 0 0 0 0 255 0 +255 0 0 0 0 0 0 255 0 0 0 0 255 0 255 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 +0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 255 0 0 0 0 255 0 255 255 255 255 0 +0 0 255 0 0 0 255 0 0 0 0 255 0 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +127 0 0 0 0 0 255 0 0 255 255 255 0 255 255 255 255 0 0 0 0 0 0 0 0 0 255 +0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 255 255 255 +255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 0 0 255 0 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 255 0 0 +0 255 255 255 0 0 255 0 0 0 0 255 0 0 255 255 255 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 +0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 +0 0 0 0 0 0 0 0 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 0 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 255 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 127 127 127 0 127 0 127 127 127 127 0 127 +127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 0 127 0 127 127 +127 127 0 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 0 +127 127 127 127 0 127 127 127 127 127 127 0 127 127 0 127 127 127 127 127 +127 127 0 127 127 127 127 0 127 127 127 127 0 127 127 127 127 127 0 127 +127 127 127 0 127 127 127 0 127 127 127 0 127 127 127 127 0 127 127 127 +127 0 127 127 127 0 127 127 127 0 127 127 127 0 127 127 127 127 0 127 127 +127 127 0 127 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 +127 0 127 127 127 127 127 127 127 0 127 127 127 127 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 +0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 255 0 255 0 0 0 255 0 255 255 0 0 0 255 +0 0 255 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 +0 0 0 255 0 0 0 0 255 0 255 0 0 0 255 0 255 0 0 0 255 0 0 0 255 0 0 255 +0 255 0 255 0 255 0 0 0 0 0 0 0 0 0 255 0 255 255 0 0 0 0 0 255 0 0 0 0 +0 0 0 255 0 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 255 0 0 0 0 255 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 +255 0 255 0 0 0 255 0 0 255 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 +0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 0 127 0 0 +255 255 0 0 0 0 0 255 255 0 0 0 0 0 255 255 0 0 0 0 0 255 255 0 0 0 0 0 +255 255 0 0 0 0 0 255 255 0 0 0 0 0 255 255 255 255 255 0 0 0 255 255 255 +0 0 255 255 255 255 255 0 255 255 255 255 255 0 255 255 255 255 255 0 255 +255 255 255 255 0 255 255 255 0 255 255 255 0 255 255 255 0 255 255 255 +0 255 255 255 255 0 0 0 255 0 0 0 0 255 0 0 0 255 255 255 0 0 0 0 0 255 +255 255 0 0 0 0 0 255 255 255 0 0 0 0 0 255 255 255 0 0 0 0 0 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 0 255 0 255 0 0 0 0 255 0 255 0 0 0 +0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 255 0 255 0 0 0 0 +255 0 0 255 0 127 0 0 255 255 0 0 0 0 0 255 255 0 0 0 0 0 255 255 0 0 0 +0 0 255 255 0 0 0 0 0 255 255 0 0 0 0 0 255 255 0 0 0 0 255 0 255 0 0 0 +0 0 255 0 0 0 255 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 +0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 255 0 0 0 255 0 0 255 255 0 +0 0 255 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 +255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 255 0 0 0 255 0 0 +255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 +0 255 0 255 0 0 255 255 255 0 0 255 0 0 255 0 127 0 255 0 0 255 0 0 0 255 +0 0 255 0 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 0 255 +0 0 255 0 0 0 255 0 255 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 +0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 +255 0 0 0 0 255 0 255 0 255 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 +255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 255 +0 0 0 255 0 255 0 0 0 255 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 +0 0 0 0 255 0 255 0 0 0 0 255 0 0 255 0 255 0 0 255 0 0 255 0 255 0 255 +0 0 127 0 255 0 0 255 0 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 0 255 0 0 +255 0 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 0 255 0 255 255 255 255 0 255 +0 0 0 0 0 0 255 255 255 255 0 0 255 255 255 255 0 0 255 255 255 255 0 0 +255 255 255 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 255 255 255 +0 0 255 0 255 0 0 255 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 +0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 0 255 0 255 0 +0 255 0 0 255 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 +255 0 255 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 255 0 255 0 0 255 0 127 255 +255 255 255 255 255 0 255 255 255 255 255 255 0 255 255 255 255 255 255 +0 255 255 255 255 255 255 0 255 255 255 255 255 255 0 255 255 255 255 255 +255 0 0 255 255 255 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 +255 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 255 +0 0 0 0 255 0 255 0 0 0 255 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 +0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 255 0 0 0 0 255 +0 0 0 255 0 255 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 +0 0 255 0 255 0 0 0 0 255 0 0 0 255 0 0 0 255 0 0 255 0 255 0 0 255 0 127 +255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 +255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 255 0 0 0 0 0 255 0 0 0 255 +0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 255 +0 0 0 255 0 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 0 0 255 0 0 255 0 0 0 +255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 0 0 0 255 +0 0 0 255 0 0 0 0 255 0 255 0 0 0 255 0 0 0 255 0 0 255 0 0 0 0 255 0 255 +0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 0 0 255 0 0 0 255 255 +255 0 0 255 0 0 255 0 127 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 +0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 0 0 255 0 255 0 0 255 +255 255 255 0 0 0 255 255 255 0 0 255 255 255 255 255 0 255 255 255 255 +255 0 255 255 255 255 255 0 255 255 255 255 255 0 255 255 255 0 255 255 +255 0 255 255 255 0 255 255 255 0 255 255 255 255 0 0 0 255 0 0 0 0 255 +0 0 0 255 255 255 0 0 0 0 0 255 255 255 0 0 0 0 0 255 255 255 0 0 0 0 0 +255 255 255 0 0 0 0 0 255 255 255 0 0 0 0 255 0 0 0 255 0 255 0 255 255 +255 0 0 0 0 255 255 255 255 0 0 0 255 255 255 255 0 0 0 255 255 255 255 +0 0 0 255 255 255 255 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 255 0 0 127 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 127 127 127 +127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 +127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 +127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 0 127 +127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 +0 127 127 127 0 127 127 127 0 127 127 127 0 127 127 127 127 127 127 0 127 +127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 0 127 127 127 127 127 127 127 0 127 127 127 127 127 127 127 0 127 +127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 +127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 127 0 127 127 127 +127 127 127 0 127 127 127 127 127 127 0 127 127 127 127 127 0 127 127 127 +127 0 127 127 127 127 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 127 0 255 0 0 0 0 0 0 255 0 0 0 255 0 0 255 255 0 255 0 +0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 +0 255 0 0 0 0 0 0 0 255 0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 255 255 0 255 +0 0 255 0 0 0 0 0 0 255 0 0 0 255 0 0 255 255 0 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 255 +0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 255 +0 0 0 0 255 0 0 0 255 0 255 0 255 0 255 255 0 0 255 0 255 0 0 255 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 255 0 255 0 0 255 0 +255 0 0 255 0 255 0 255 0 255 255 0 255 0 0 255 255 0 255 0 255 255 0 0 +0 255 0 0 0 0 255 0 0 0 255 0 255 0 255 0 255 255 0 255 0 0 255 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 255 0 255 0 0 255 0 255 0 +0 0 255 0 0 0 255 0 0 0 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 127 0 255 255 0 0 0 255 255 0 0 0 255 255 0 0 0 255 255 0 0 0 255 +255 0 0 0 255 255 0 0 255 255 255 0 255 255 0 0 0 255 255 0 0 255 255 0 +0 0 255 255 0 0 0 255 255 0 0 0 255 255 0 0 0 255 0 255 0 0 255 0 0 255 +0 0 0 0 255 0 255 255 255 0 0 0 255 255 0 0 0 255 255 0 0 0 255 255 0 0 +0 255 255 0 0 0 255 255 0 0 0 0 0 0 0 0 0 0 255 255 255 0 0 255 0 0 255 +0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 0 255 0 255 255 255 +0 0 255 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 255 0 0 0 +0 255 0 0 0 0 255 0 0 0 0 255 0 0 0 0 255 0 0 0 0 255 0 0 0 0 255 0 0 255 +0 255 0 0 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 0 255 +0 255 0 0 255 0 0 255 0 0 255 255 255 0 255 0 0 255 0 255 0 0 255 0 255 +0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 0 255 255 255 255 255 +0 255 0 0 255 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 +0 0 255 0 255 0 0 255 0 0 255 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 127 0 255 255 255 0 0 255 255 255 0 0 255 255 255 0 0 255 255 255 +0 0 255 255 255 0 0 255 255 255 0 0 255 255 255 255 255 255 0 255 0 0 0 +255 255 255 255 0 255 255 255 255 0 255 255 255 255 0 255 255 255 255 0 +0 255 0 255 0 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 +255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 0 0 0 0 0 0 0 255 +0 255 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 0 +255 0 255 0 0 255 0 0 255 0 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 127 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 +255 0 255 0 0 255 0 255 0 0 255 0 0 0 0 255 0 0 0 255 0 0 0 0 255 0 0 0 +0 255 0 0 0 0 255 0 0 0 0 0 255 0 255 0 0 255 0 0 255 0 255 0 0 255 0 255 +0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 0 +0 255 0 0 0 0 255 0 0 0 255 255 0 0 255 0 255 0 0 255 0 255 0 0 255 0 255 +0 0 255 0 255 0 0 255 0 0 255 0 255 0 0 255 0 0 255 0 0 255 0 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 255 255 255 0 0 255 255 255 0 0 255 +255 255 0 0 255 255 255 0 0 255 255 255 0 0 255 255 255 0 0 255 255 0 255 +255 255 0 0 255 255 0 0 255 255 255 0 0 255 255 255 0 0 255 255 255 0 0 +255 255 255 0 0 255 0 255 0 0 255 0 0 255 0 0 255 255 0 0 255 0 0 255 0 +0 255 255 0 0 0 255 255 0 0 0 255 255 0 0 0 255 255 0 0 0 255 255 0 0 0 +0 0 0 0 0 0 0 255 255 255 0 0 0 255 255 255 0 0 255 255 255 0 0 255 255 +255 0 0 255 255 255 0 0 0 255 0 0 0 255 255 255 0 0 0 0 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 255 0 0 0 0 0 0 255 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 255 0 0 0 0 0 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 127 127 127 0 127 127 127 127 0 127 127 +127 127 0 127 127 127 127 0 127 127 127 127 0 127 127 127 127 0 127 127 +127 127 127 127 127 0 127 127 127 0 127 127 127 127 0 127 127 127 127 0 +127 127 127 127 0 127 127 127 127 0 127 127 0 127 0 127 127 0 127 127 0 +127 127 127 127 0 127 127 127 127 0 127 127 127 127 0 127 127 127 127 0 +127 127 127 127 0 127 127 127 127 0 127 127 127 127 0 127 127 127 127 127 +127 0 127 127 127 127 127 0 127 127 127 127 0 127 127 127 127 0 127 127 +127 127 0 127 127 127 127 0 127 127 127 127 127 0 127 127 127 127 0 127 +127 127 127 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/Extras/CDTestFramework/AntTweakBar/src/res/TwXCursors.h b/Extras/CDTestFramework/AntTweakBar/src/res/TwXCursors.h new file mode 100644 index 0000000..7f82c4f --- /dev/null +++ b/Extras/CDTestFramework/AntTweakBar/src/res/TwXCursors.h @@ -0,0 +1,909 @@ +// --------------------------------------------------------------------------- +// +// @file TwXCursors.h +// @brief Bitmaps data for X cursors +// @author Philippe Decaudin - http://www.antisphere.com +// @license This file is part of the AntTweakBar library. +// Copyright © 2005, 2006 Philippe Decaudin. +// For conditions of distribution and use, see License.txt +// +// note: TAB=4 +// +// --------------------------------------------------------------------------- + + +static int g_CurHot[][2] = +{ + {16, 15}, // curs00 + {16, 15}, // curs01 + {16, 15}, // curs02 + {16, 15}, // curs03 + {16, 15}, // curs04 + {16, 15}, // curs05 + {16, 15}, // curs06 + {16, 15}, // curs07 + {16, 15}, // curs08 + {16, 15}, // curs09 + {16, 15}, // curs10 + {16, 15}, // curs11 + {16, 15}, // curs12 + {16, 15} // curs13 +}; + + +static bool g_CurPict[][32*32] = +{ + { // curs00 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // curs01 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // curs02 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // curs03 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // curs04 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // curs05 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // curs06 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // curs07 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // curs08 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // curs09 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // curs10 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // curs11 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // curs12 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // curs13 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + } +}; + + +static bool g_CurMask[][32*32] = +{ + { // mask00 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // mask01 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // mask02 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // mask03 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // mask04 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // mask05 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // mask06 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // mask07 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // mask08 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // mask09 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { // mask10 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 + }, + { // mask11 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // mask12 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // mask13 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + } +}; diff --git a/Extras/CDTestFramework/AntTweakBar/src/res/cur00000.cur b/Extras/CDTestFramework/AntTweakBar/src/res/cur00000.cur new file mode 100644 index 0000000000000000000000000000000000000000..46c0fbcfe06a5e9a43bf303352a79c5fa5069632 GIT binary patch literal 326 zcmaJ*F%E)25S#-O8>3Xl3a+%Yv>*{*1~K-&$@mfc0i^|DoPmN0<}$mtyEA(SBnXHR z$Z)_V07n34Q7u$r&@q}ZP9ae;4U*GkEv7B7JL!>)7Ry;_=lu;lVuNQk)3y7aTW7s} usr)O@AC}PTl>B_j*N-gvnt53dWqup3`Q;`Hp$Fjr9T<^{F#m@Egrn!!mi=v@fJ55? zH7YzEa0BolEFludC+oA{T)|Js%xnwfFQg)60%E?|y1dMx3(44yk>$5hQ z=MsPOj6DnbHb_=8A4Ue~O5A}pEZ%Sj2Q~CCz>_^6GaY@SIu)v8rTRq|Vt=9MlaK1} TMcFlsp@O5+afde=J`bg18WxrOV!+9<0zpJy?4JuTZFWD1v01v_xF?hxh+y7Bc~h z!F$L#QW`h|H$_L>6{9bzU3@jG5s4C!wQTeZ$_pGy(`Q%fuct@;a&_U{K6hBJ2m9Y9 zr!CPyNImAi^bec#7I}^$-5@e_p&I+Th}X;ryQyWGKgBGeT6Rt937SA6&0;2f0WoNE Ao&W#< literal 0 HcmV?d00001 diff --git a/Extras/CDTestFramework/AntTweakBar/src/res/cur00005.cur b/Extras/CDTestFramework/AntTweakBar/src/res/cur00005.cur new file mode 100644 index 0000000000000000000000000000000000000000..8e2142ebc032dab4efdb8fee230c16ed760634b5 GIT binary patch literal 326 zcmZvWJr06E6oh91!&WXfwrpu>X$QxmFpQ8&r=zS)?&Ah~%{V@wl0KsctKg)Ur}|v1wq}9yZBFPDy5M zbg`pV&bB4|lm3yE{1C9vc?M>iQ RFjn&{?qXK!$S>cF`~Y7~a!&vN literal 0 HcmV?d00001 diff --git a/Extras/CDTestFramework/AntTweakBar/src/res/cur00006.cur b/Extras/CDTestFramework/AntTweakBar/src/res/cur00006.cur new file mode 100644 index 0000000000000000000000000000000000000000..02f5aad32e222c0986d3ee0fece0715a47be991d GIT binary patch literal 326 zcmY+8%?ZLl5QX2y9C8qnlL!jgqenZ?UaY_h60iVUu#^Q4mSJEk2wrj!pKn}4^ex}~ zF*7?r1_$qf3MIAE~rDN!B)jT>4v0-Tqi=q*pl%it~&4_j)~Z-HW)kdS(8IKVfjlr V&*CQHo$QsUDXhONYYjI1(Ho$ebOHbX literal 0 HcmV?d00001 diff --git a/Extras/CDTestFramework/AntTweakBar/src/res/cur00007.cur b/Extras/CDTestFramework/AntTweakBar/src/res/cur00007.cur new file mode 100644 index 0000000000000000000000000000000000000000..59d9b7d6d2ba6411ee1c0ea3859799c4cfb249dd GIT binary patch literal 326 zcmZ9GI}(CG5JY>>&~h;`Az%XoLvJ7fhcZ$!uHrE~%HDv~fTHbLRH~S*H=nMl-T?|2 zVgyPATnsn@I15Q=gz0&7InSw3aXd)Qjk3wbaD&+sA)VB>qRGq-owmN%OC}N6mJ2?+ z{@eN2Mw-)RU&tT&$FKI#4ICeX=sDguOgphRrf`r}iCX%VoK}oA`3?&{uXlW=bXM6f M`^uk_U@r!K09kNuLI3~& literal 0 HcmV?d00001 diff --git a/Extras/CDTestFramework/AntTweakBar/src/res/cur00008.cur b/Extras/CDTestFramework/AntTweakBar/src/res/cur00008.cur new file mode 100644 index 0000000000000000000000000000000000000000..0785b19f11f97f0211bd1e4e2158d3e6199bfdc6 GIT binary patch literal 326 zcmYk1O^U)m5QSg2E?fw4CBg{Fa+cmeujC05m;-o)IZA^Ik72+Q$ZWC@pI=1-Q_WYe zew%J7E2(Lul`8F$w3hS@lyrc^3F}7xb{Pr6Y`=r>QzNuKcjUct`c=-2G=~L^6%eML zd2~)b5&5i87d5Gc&~YtR<6*%UEa79k!5;omwyn#icG*@Q9x%ZDWZ$m#g+an+Wj|{6 b(1|hMk9XmL~W_ZJxC&i7gT(sSD4!I2*~&oxks|5tun;rX?Ixl6gj2WK~*V zhhYh$J=o&%bOU{0VB)^s-sO*^w)$|+r8nPwo&49W=}Aq{y$ou(upXHF$|^paNQZ^A TlWvZ+V_kJL&dtPI?7w;d-B)kB literal 0 HcmV?d00001 diff --git a/Extras/CDTestFramework/AntTweakBar/src/res/cur00010.cur b/Extras/CDTestFramework/AntTweakBar/src/res/cur00010.cur new file mode 100644 index 0000000000000000000000000000000000000000..bb8b5f0a6d2026a8353572b98ce08569aba3d0fa GIT binary patch literal 326 zcmah@OA5j;5PcJ+WFZ(3#6_W5y37sg!3r(ZgQY8%UZK$5p$O7(lC)44;tTIH!!Q{@ zfnY6QaD*e^4B#r17H&e47tlmaqQn9Nm^p=SHBv^_z`W+g(#ESFyBTw3 zb4NbA0EY~4Y4E?w4O={Qc3;L84B}A^3q?wg8k$^;G z!0ZLlgA@Js;oUpUiCl^CB&&Z|bU?n1gG|HJUcV(`Qh>blSyE X!^Uv~C%dz1Skin5IWrOpWO2AIOIw@d11#CV34AgR|QWC-tu?l?}R) z3y<0?sg|70hDCG19x3>S-#9ppTc?2<8r4u?P<_peJrT@FH8$U-4InmyE)|nE-1)cF P%=?599m@_^JfQjpiz0Q= literal 0 HcmV?d00001 diff --git a/Extras/CDTestFramework/AntTweakBar/src/res/cur00013.cur b/Extras/CDTestFramework/AntTweakBar/src/res/cur00013.cur new file mode 100644 index 0000000000000000000000000000000000000000..16356062761e23c7b2b3c6c6dd4e5f11ede2cb48 GIT binary patch literal 326 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]SJT>Wkr;OLp=_&Frf*cJIf7^8Ml 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

    c4`kj?D)9v?U=fq{k6>h!ZphtFD2sFZLR+L1m7P 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

    U>d?rn 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 J|8pAnzW^c=Jb(ZI literal 0 HcmV?d00001 diff --git a/Extras/CDTestFramework/BipartiteBoxPruning.cpp b/Extras/CDTestFramework/BipartiteBoxPruning.cpp new file mode 100644 index 0000000..87d9886 --- /dev/null +++ b/Extras/CDTestFramework/BipartiteBoxPruning.cpp @@ -0,0 +1,165 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 "stdafx.h" +#include "BipartiteBoxPruning.h" +#include "RenderingHelpers.h" +#include "GLFontRenderer.h" + +BipartiteBoxPruningTest::BipartiteBoxPruningTest() : + mBar (null), + mNbBoxes (0), + mBoxes (null), + mBoxPtrs (null), + mBoxTime (null), + mSpeed (0.0f), + mAmplitude (100.0f) +{ +} + +BipartiteBoxPruningTest::~BipartiteBoxPruningTest() +{ + DELETEARRAY(mBoxTime); + DELETEARRAY(mBoxPtrs); + DELETEARRAY(mBoxes); +} + +void BipartiteBoxPruningTest::Init() +{ + mNbBoxes = 1024; + mBoxes = new AABB[mNbBoxes]; + mBoxPtrs = new const AABB*[mNbBoxes]; + mBoxTime = new float[mNbBoxes]; + for(udword i=0;i buffer; +int sizes[2]; +btScalar scales[2]; +btScalar offsets[2]; +btScalar wtrs[16]; +btVector3 eye; +btVector3 neardist; +btScalar ocarea; +btScalar qrarea; +GLuint texture; + OcclusionBuffer() + { + initialized=false; + neardist=btVector3(2,2,2); + ocarea=(btScalar)0; + qrarea=(btScalar)0; + } +void setup(int w,int h) + { + initialized=true; + sizes[0]=w; + sizes[1]=h; + scales[0]=w/2; + scales[1]=h/2; + offsets[0]=scales[0]+0.5; + offsets[1]=scales[1]+0.5; + glGenTextures(1,&texture); + clear(); + } +void clear() + { + buffer.resize(0); + buffer.resize(sizes[0]*sizes[1],0); + } +void initialize() + { + if(!initialized) + { + setup(128,128); + } + GLint v[4]; + GLdouble m[16],p[16]; + glGetIntegerv(GL_VIEWPORT,v); + glGetDoublev(GL_MODELVIEW_MATRIX,m); + glGetDoublev(GL_PROJECTION_MATRIX,p); + for(int i=0;i<16;++i) wtrs[i]=p[i]; + clear(); + } +void drawBuffer( btScalar l,btScalar t, + btScalar r,btScalar b) + { + btAlignedObjectArray data; + data.resize(buffer.size()); + for(int i=0;i +static int clip(const btVector4* pi,btVector4* po) + { + btScalar s[NP]; + int m=0; + for(int i=0;i0)&&(t<1)) + { + po[n][0] = a[0]+(b[0]-a[0])*t; + po[n][1] = a[1]+(b[1]-a[1])*t; + po[n][2] = a[2]+(b[2]-a[2])*t; + po[n][3] = a[3]+(b[3]-a[3])*t; + ++n; + } + if(s[j]>0) po[n++]=b; + } + return(n); + } + for(int i=0;i +inline bool draw( const btVector4& a, + const btVector4& b, + const btVector4& c, + const btScalar minarea) + { + const btScalar a2=(b-a).cross(c-a)[2]; + if(a2>0) + { + if(a20) + { + const int dx[]={ y[0]-y[1], + y[1]-y[2], + y[2]-y[0]}; + const int dy[]={ x[1]-x[0]-dx[0]*width, + x[2]-x[1]-dx[1]*width, + x[0]-x[2]-dx[2]*width}; + const int a=x[2]*y[0]+x[0]*y[1]-x[2]*y[1]-x[0]*y[2]+x[1]*y[2]-x[1]*y[0]; + const btScalar ia=1/(btScalar)a; + const btScalar dzx=ia*(y[2]*(z[1]-z[0])+y[1]*(z[0]-z[2])+y[0]*(z[2]-z[1])); + const btScalar dzy=ia*(x[2]*(z[0]-z[1])+x[0]*(z[1]-z[2])+x[1]*(z[2]-z[0]))-(dzx*width); + int c[]={ miy*x[1]+mix*y[0]-x[1]*y[0]-mix*y[1]+x[0]*y[1]-miy*x[0], + miy*x[2]+mix*y[1]-x[2]*y[1]-mix*y[2]+x[1]*y[2]-miy*x[1], + miy*x[0]+mix*y[2]-x[0]*y[2]-mix*y[0]+x[2]*y[0]-miy*x[2]}; + btScalar v=ia*((z[2]*c[0])+(z[0]*c[1])+(z[1]*c[2])); + btScalar* scan=&buffer[miy*sizes[1]]; + for(int iy=miy;iy=0)&&(c[1]>=0)&&(c[2]>=0)) + { + if(POLICY::Process(scan[ix],v)) return(true); + } + c[0]+=dx[0];c[1]+=dx[1];c[2]+=dx[2];v+=dzx; + } + c[0]+=dy[0];c[1]+=dy[1];c[2]+=dy[2];v+=dzy; + scan+=sizes[0]; + } + } + } + return(false); + } +template +inline bool clipDraw( const btVector4* p, + btScalar minarea) + { + btVector4 o[NP*2]; + const int n=clip(p,o); + bool earlyexit=false; + project(o,n); + for(int i=2;i(o[0],o[i-1],o[i],minarea); + } + return(earlyexit); + } +void appendOccluder( const btVector3& a, + const btVector3& b, + const btVector3& c) + { + const btVector4 p[]={transform(a),transform(b),transform(c)}; + clipDraw<3,WriteOCL>(p,ocarea); + } +void appendOccluder( const btVector3& a, + const btVector3& b, + const btVector3& c, + const btVector3& d) + { + const btVector4 p[]={transform(a),transform(b),transform(c),transform(d)}; + clipDraw<4,WriteOCL>(p,ocarea); + } +void appendOccluder( const btVector3& c, + const btVector3& e) + { + const btVector4 x[]={ transform(btVector3(c[0]-e[0],c[1]-e[1],c[2]-e[2])), + transform(btVector3(c[0]+e[0],c[1]-e[1],c[2]-e[2])), + transform(btVector3(c[0]+e[0],c[1]+e[1],c[2]-e[2])), + transform(btVector3(c[0]-e[0],c[1]+e[1],c[2]-e[2])), + transform(btVector3(c[0]-e[0],c[1]-e[1],c[2]+e[2])), + transform(btVector3(c[0]+e[0],c[1]-e[1],c[2]+e[2])), + transform(btVector3(c[0]+e[0],c[1]+e[1],c[2]+e[2])), + transform(btVector3(c[0]-e[0],c[1]+e[1],c[2]+e[2]))}; + static const int d[]={ 1,0,3,2, + 4,5,6,7, + 4,7,3,0, + 6,5,1,2, + 7,6,2,3, + 5,4,0,1}; + for(int i=0;i<(sizeof(d)/sizeof(d[0]));) + { + const btVector4 p[]={ x[d[i++]], + x[d[i++]], + x[d[i++]], + x[d[i++]]}; + clipDraw<4,WriteOCL>(p,ocarea); + } + } +inline bool queryOccluder( const btVector3& a, + const btVector3& b, + const btVector3& c) + { + const btVector4 p[]={transform(a),transform(b),transform(c)}; + return(clipDraw<3,QueryOCL>(p,qrarea)); + } +inline bool queryOccluder( const btVector3& a, + const btVector3& b, + const btVector3& c, + const btVector3& d) + { + const btVector4 p[]={transform(a),transform(b),transform(c),transform(d)}; + return(clipDraw<4,QueryOCL>(p,qrarea)); + } +inline bool queryOccluder( const btVector3& c, + const btVector3& e) + { + const btVector4 x[]={ transform(btVector3(c[0]-e[0],c[1]-e[1],c[2]-e[2])), + transform(btVector3(c[0]+e[0],c[1]-e[1],c[2]-e[2])), + transform(btVector3(c[0]+e[0],c[1]+e[1],c[2]-e[2])), + transform(btVector3(c[0]-e[0],c[1]+e[1],c[2]-e[2])), + transform(btVector3(c[0]-e[0],c[1]-e[1],c[2]+e[2])), + transform(btVector3(c[0]+e[0],c[1]-e[1],c[2]+e[2])), + transform(btVector3(c[0]+e[0],c[1]+e[1],c[2]+e[2])), + transform(btVector3(c[0]-e[0],c[1]+e[1],c[2]+e[2]))}; + for(int i=0;i<8;++i) + { + if((x[i][2]+x[i][3])<=0) return(true); + } + static const int d[]={ 1,0,3,2, + 4,5,6,7, + 4,7,3,0, + 6,5,1,2, + 7,6,2,3, + 5,4,0,1}; + for(int i=0;i<(sizeof(d)/sizeof(d[0]));) + { + const btVector4 p[]={ x[d[i++]], + x[d[i++]], + x[d[i++]], + x[d[i++]]}; + if(clipDraw<4,QueryOCL>(p,qrarea)) return(true); + } + return(false); + } +}; + +OcclusionBuffer ocb; + +BulletSAPCompleteBoxPruningTest::BulletSAPCompleteBoxPruningTest(int numBoxes,int method) : + mBar (null), + mNbBoxes (numBoxes), + mBoxes (null), + mBoxPtrs (null), + mBoxTime (null), + mAmplitude (100.0f), + m_method(method) +{ + btVector3 aabbMin(-200,-200,-200); + btVector3 aabbMax(200,200,200); + + int maxNumBoxes = numBoxes; + m_isdbvt=false; + bool disableRaycastAccelerator = true; + switch (method) + { + case 1: + m_broadphase = new btAxisSweep3(aabbMin,aabbMax,maxNumBoxes,0,disableRaycastAccelerator); + methodname = "btAxisSweep3"; + break; + case 2: + m_broadphase = new btAxisSweep3(aabbMin,aabbMax,maxNumBoxes,new btNullPairCache(),disableRaycastAccelerator); + methodname = "btAxisSweep3+btNullPairCache"; + break; + case 3: + m_broadphase = new btAxisSweep3(aabbMin,aabbMax,maxNumBoxes,new btSortedOverlappingPairCache(),disableRaycastAccelerator); + methodname = "btAxisSweep3+btSortedOverlappingPairCache"; + break; + case 4: + m_broadphase = new btSimpleBroadphase(maxNumBoxes,new btSortedOverlappingPairCache()); + methodname = "btSimpleBroadphase+btSortedOverlappingPairCache"; + break; + case 5: + m_broadphase = new btSimpleBroadphase(maxNumBoxes,new btNullPairCache()); + methodname = "btSimpleBroadphase+btNullPairCache"; + break; + +/* case 6: + { + methodname = "btMultiSapBroadphase"; + btMultiSapBroadphase* multiSap = new btMultiSapBroadphase(maxNumBoxes); + m_broadphase = multiSap; + + btVector3 tmpAabbMin,tmpAabbMax; + + float numP = (float) numParts; + + for (int i=0;igetOverlappingPairCache(),disableRaycastAccelerator); + multiSap->getBroadphaseArray().push_back(childBp); + } + } + } + + // btAxisSweep3* childBp = new btAxisSweep3(aabbMin,aabbMax,maxNumBoxes,multiSap->getOverlappingPairCache()); + // multiSap->getBroadphaseArray().push_back(childBp); + multiSap->buildTree(aabbMin,aabbMax); + + } + break; + */ + case 7: + { + btDbvtBroadphase* pbp=new btDbvtBroadphase(); + m_broadphase = pbp; + pbp->m_deferedcollide = true; /* Faster initialization, set to false after. */ + m_isdbvt = true; + methodname = "dynamic AABB tree, btDbvtBroadphase"; + } + break; + case 8: +// m_broadphase = new btAxisSweep3(aabbMin,aabbMax,maxNumBoxes); +// m_broadphase = new btSimpleBroadphase(maxNumBoxes,new btSortedOverlappingPairCache()); +// m_broadphase = new btCudaBroadphase(aabbMin, aabbMax, 8, 8, 8, 8192, 8192, 64, 16); +// m_broadphase = new btCudaBroadphase(aabbMin, aabbMax, 12, 12, 12, 8192, 8192, 64, 16); +// m_broadphase = new btCudaBroadphase(aabbMin, aabbMax, 16, 16, 16, 8192, 8192, 64, 16); +#ifdef USE_CUDA_BROADPHASE + m_broadphase = new btCudaBroadphase(aabbMin, aabbMax, 24, 24, 24,maxNumBoxes , maxNumBoxes, 64, 16); +// m_broadphase = new btCudaBroadphase(aabbMin, aabbMax, 32, 32, 32, 8192, 8192, 64, 16); + methodname = "btCudaBroadphase"; + break; + + case 9: + m_broadphase = new bt3DGridBroadphase(aabbMin, aabbMax, 24, 24, 24,maxNumBoxes , maxNumBoxes, 64, 16); + methodname = "bt3DGridBroadphase"; + break; +#endif //USE_CUDA_BROADPHASE + + default: + { + + btDbvtBroadphase* pbp=new btDbvtBroadphase(); + m_broadphase = pbp; + pbp->m_deferedcollide = true; /* Faster initialization, set to false after. */ + m_isdbvt = true; + methodname = "dynamic AABB tree, btDbvtBroadphase"; + + //m_broadphase = new btAxisSweep3(aabbMin,aabbMax,numBoxes,new btNullPairCache()); + //methodname = "btAxisSweep3+btNullPairCache"; + } + } +} + +BulletSAPCompleteBoxPruningTest::~BulletSAPCompleteBoxPruningTest() +{ + DELETEARRAY(mBoxTime); + DELETEARRAY(mBoxPtrs); + DELETEARRAY(mBoxes); + delete m_broadphase; +} + +void BulletSAPCompleteBoxPruningTest::Init() +{ + btClock clock; + m_firstTime = true; + SRand(0); + + + mBoxes = new AABB[mNbBoxes]; + mFlags = new bool[mNbBoxes]; + mBoxPtrs = new const AABB*[mNbBoxes]; + mBoxTime = new float[mNbBoxes]; + for(udword i=0;icreateProxy(aabbMin,aabbMax,shapeType,&mBoxes[i],1,1,0,0);//m_dispatcher); + m_proxies.push_back( proxy ); + + mBoxTime[i] = 2000.0f*UnitRandomFloat(); + } + printf("Initialization of %s with %u boxes: %ums\r\n",methodname,mNbBoxes,clock.getTimeMilliseconds()); +} + +void BulletSAPCompleteBoxPruningTest::Release() +{ + DELETEARRAY(mBoxTime); + DELETEARRAY(mBoxes); +} + +extern int doTree; +extern int percentUpdate; +extern float objectSpeed; +extern bool enableDraw; + +static void TW_CALL NormalMode(void* pdata) +{ +btDbvtBroadphase* pb=(btDbvtBroadphase*)pdata; +pb->m_deferedcollide = true; +} + +static void TW_CALL SlowSpeedMode(void* pdata) +{ +btDbvtBroadphase* pb=(btDbvtBroadphase*)pdata; +pb->m_deferedcollide = false; +} + +void BulletSAPCompleteBoxPruningTest::Select() +{ + // Create a tweak bar + { + mBar = TwNewBar("OPC_CompleteBoxPruning"); + TwAddVarRW(mBar, "Speed", TW_TYPE_FLOAT, &objectSpeed, " min=0.0 max=0.01 step=0.0001"); + TwAddVarRW(mBar, "Amplitude", TW_TYPE_FLOAT, &mAmplitude, " min=10.0 max=200.0 step=0.1"); + if(m_isdbvt) + { + btDbvtBroadphase* pbp=(btDbvtBroadphase*)m_broadphase; + TwAddVarRW(mBar, "Enable culling",TW_TYPE_BOOLCPP,&enableCulling,""); + TwAddVarRW(mBar, "Enable occlusion",TW_TYPE_BOOLCPP,&enableOcclusion,""); + TwAddVarRW(mBar, "Show culling",TW_TYPE_BOOLCPP,&showCulling,""); + TwAddVarRW(mBar, "Show occlusion",TW_TYPE_BOOLCPP,&showOcclusion,""); + TwAddVarRW(mBar, "Cull far plane",TW_TYPE_BOOLCPP,&cullFarPlane,""); + TwAddVarRW(mBar, "OC Min area",TW_TYPE_FLOAT,&ocb.ocarea,"min=0.0 max=1.0 step=0.001"); + TwAddVarRW(mBar, "QR Min area",TW_TYPE_FLOAT,&ocb.qrarea,"min=0.0 max=1.0 step=0.001"); + TwAddVarRW(mBar, "Dyn lkhd",TW_TYPE_INT32,&pbp->m_sets[0].m_lkhd,"min=-1 max=32"); + TwAddVarRW(mBar, "Fix lkhd",TW_TYPE_INT32,&pbp->m_sets[1].m_lkhd,"min=-1 max=32"); + TwAddVarRW(mBar, "Dyn opt/f(%)",TW_TYPE_INT32,&pbp->m_dupdates,"min=0 max=100"); + TwAddVarRW(mBar, "Fix opt/f(%)",TW_TYPE_INT32,&pbp->m_fupdates,"min=0 max=100"); + TwAddVarRW(mBar, "Cln opt/f(%)",TW_TYPE_INT32,&pbp->m_cupdates,"min=0 max=100"); + TwAddVarRW(mBar, "Prediction",TW_TYPE_FLOAT,&pbp->m_prediction,"min=0.0 max=2.0 step=0.1"); + TwAddVarRW(mBar, "Defered collide",TW_TYPE_BOOLCPP,&pbp->m_deferedcollide,""); + TwAddVarRO(mBar, "Dyn leafs",TW_TYPE_INT32,&pbp->m_sets[0].m_leaves,""); + TwAddVarRO(mBar, "Fix leafs",TW_TYPE_INT32,&pbp->m_sets[1].m_leaves,""); + TwAddVarRO(mBar, "Updates ratio",TW_TYPE_FLOAT,&pbp->m_updates_ratio,""); + TwAddVarRO(mBar, "Visible",TW_TYPE_INT32,&visiblecount,""); + TwAddButton(mBar,"Normal mode",&NormalMode,m_broadphase,""); + TwAddButton(mBar,"Slow speed mode",&SlowSpeedMode,m_broadphase,""); + } + } + printf("SubMethod: %s\r\n",methodname); +} + +void BulletSAPCompleteBoxPruningTest::Deselect() +{ + if(mBar) + { + TwDeleteBar(mBar); + mBar = null; + } +} + +bool BulletSAPCompleteBoxPruningTest::UpdateBoxes(int numBoxes) +{ + static bool once=true; + + for(udword i=0;i<(udword)numBoxes;i++) + { + mBoxTime[i] += objectSpeed; + + Point Center,Extents; + mBoxes[i].GetExtents(Extents); + + Center.x = cosf(mBoxTime[i]*2.17f)*mAmplitude + sinf(mBoxTime[i])*mAmplitude*0.5f; + Center.y = cosf(mBoxTime[i]*1.38f)*mAmplitude + sinf(mBoxTime[i]*mAmplitude); + Center.z = sinf(mBoxTime[i]*0.777f)*mAmplitude; + + mBoxes[i].SetCenterExtents(Center, Extents); + } + return true; +} + +void BulletSAPCompleteBoxPruningTest::PerformTest() +{ + int numUpdatedBoxes = (mNbBoxes*percentUpdate)/100; + if (m_firstTime) + { + numUpdatedBoxes = mNbBoxes; + } + mProfiler.Start(); + UpdateBoxes(numUpdatedBoxes); + + + mPairs.ResetPairs(); + + //CompleteBoxPruning(mNbBoxes, mBoxPtrs, mPairs, Axes(AXES_XZY)); + ///add batch query? + + + for (int i=0;iGetCenter(Center); + mBoxPtrs[i]->GetExtents(Extents); + btVector3 aabbMin(Center.x-Extents.x,Center.y-Extents.y,Center.z-Extents.z); + btVector3 aabbMax(Center.x+Extents.x,Center.y+Extents.y,Center.z+Extents.z); + m_broadphase->setAabb(m_proxies[i],aabbMin,aabbMax,0);//m_dispatcher); + } + +#ifndef BT_NO_PROFILE + if(sBulletProfilerToggle) + { + CProfileManager::Reset(); + } +#endif //BT_NO_PROFILE + + m_broadphase->calculateOverlappingPairs(0); + +#ifndef BT_NO_PROFILE + if(sBulletProfilerToggle) + { + CProfileManager::Increment_Frame_Counter(); + CProfileManager::dumpAll(); + } +#endif //BT_NO_PROFILE + + + mProfiler.End(); + mProfiler.Accum(); + + if (m_firstTime) + { + //initialization messes up timings + m_firstTime = false; + if(m_isdbvt) + { + ((btDbvtBroadphase*)m_broadphase)->m_deferedcollide=false; + } + mProfiler.Reset(); + } + + #if 0 + { + int missedpairs=0; + for(int i=0;iaabb,pb->aabb)) + { + btDbvtProxy* spa=pa; + btDbvtProxy* spb=pb; + if(spa>spb) btSwap(spa,spb); + if(!m_broadphase->getOverlappingPairCache()->findPair(spa,spb)) + { + ++missedpairs; + printf("Cannot find %i,%i\r\n",i,j); + } + } + } + } + if(missedpairs>0) printf("Missed pairs: %u\r\n",missedpairs); + } + #endif + +// printf("%d pairs colliding\r ", mPairs.GetNbPairs()); + + ZeroMemory(mFlags,sizeof(bool)*mNbBoxes); + + btOverlappingPairCache* pairCache = m_broadphase->getOverlappingPairCache(); + const btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr(); + + for(udword i=0;i<(udword)pairCache->getNumOverlappingPairs();i++) + { +// Flags[pairPtr[i].m_pProxy0->getUid()-1] = true; +// Flags[pairPtr[i].m_pProxy1->getUid()-1] = true; + int j; + j=((AABB*)pairPtr[i].m_pProxy0->m_clientObject)-mBoxes; + mFlags[j] = true; + j=((AABB*)pairPtr[i].m_pProxy1->m_clientObject)-mBoxes; + mFlags[j] = true; + } + + if(enableDraw) + { + btVector3 aabbMin(-200,-200,-200); + btVector3 aabbMax(200,200,200); + + btVector3 tmpAabbMin,tmpAabbMax; + glDisable(GL_DEPTH_TEST); + + + float numP = (float) numParts; + + for (int i=0;igetOverlappingPairCache()->getNumOverlappingPairs()); + +// m_broadphase)->printStats(); + + GLFontRenderer::print(10.0f, 10.0f, 0.02f, Buffer); +} + +// +static void DrawVolume(const btDbvtVolume& volume,const btVector3& color) +{ +const btVector3 mins=volume.Mins(); +const btVector3 maxs=volume.Maxs(); +glColor3f(color.x(),color.y(),color.z()); +glVertex3f(mins.x(),mins.y(),mins.z()); +glVertex3f(maxs.x(),mins.y(),mins.z()); + +glVertex3f(maxs.x(),mins.y(),mins.z()); +glVertex3f(maxs.x(),maxs.y(),mins.z()); + +glVertex3f(maxs.x(),maxs.y(),mins.z()); +glVertex3f(mins.x(),maxs.y(),mins.z()); + +glVertex3f(mins.x(),maxs.y(),mins.z()); +glVertex3f(mins.x(),mins.y(),mins.z()); + +glVertex3f(mins.x(),mins.y(),maxs.z()); +glVertex3f(maxs.x(),mins.y(),maxs.z()); + +glVertex3f(maxs.x(),mins.y(),maxs.z()); +glVertex3f(maxs.x(),maxs.y(),maxs.z()); + +glVertex3f(maxs.x(),maxs.y(),maxs.z()); +glVertex3f(mins.x(),maxs.y(),maxs.z()); + +glVertex3f(mins.x(),maxs.y(),maxs.z()); +glVertex3f(mins.x(),mins.y(),maxs.z()); + +glVertex3f(mins.x(),mins.y(),mins.z()); +glVertex3f(mins.x(),mins.y(),maxs.z()); + +glVertex3f(maxs.x(),mins.y(),mins.z()); +glVertex3f(maxs.x(),mins.y(),maxs.z()); + +glVertex3f(maxs.x(),maxs.y(),mins.z()); +glVertex3f(maxs.x(),maxs.y(),maxs.z()); + +glVertex3f(mins.x(),maxs.y(),mins.z()); +glVertex3f(mins.x(),maxs.y(),maxs.z()); +} + +// +void BulletSAPCompleteBoxPruningTest::RenderAll() +{ +OBB CurrentBox; +CurrentBox.mRot.Identity(); +for(udword i=0;iqueryOccluder(node->volume.Center(),node->volume.Extents())); + } + void Process(const btDbvtNode* node,btScalar depth) + { + Process(node); + } + void Process(const btDbvtNode* leaf) + { + btBroadphaseProxy* proxy=(btBroadphaseProxy*)leaf->data; + int i=((AABB*)proxy->m_clientObject)-self->mBoxes; + if(self->mFlags[i]) glColor3f(1.0f, 0.0f, 0.0f); + else glColor3f(0.0f, 1.0f, 0.0f); + self->mBoxes[i].GetCenter(box.mCenter); + self->mBoxes[i].GetExtents(box.mExtents); + DrawOBB(box);drawn++; + if(ocb) + { + ocb->appendOccluder(btVector3(box.mCenter.x,box.mCenter.y,box.mCenter.z), + btVector3(box.mExtents.x,box.mExtents.y,box.mExtents.z)); + } + } + } srenderer; + srenderer.self=this; + srenderer.ocb=0; + if(enableOcclusion) + { + srenderer.ocb=&ocb; + btDbvt::collideOCL(pbp->m_sets[1].m_root,planes_n,planes_o,dir,acplanes,srenderer); + btDbvt::collideOCL(pbp->m_sets[0].m_root,planes_n,planes_o,dir,acplanes,srenderer); + } + else + { + btDbvt::collideKDOP(pbp->m_sets[1].m_root,planes_n,planes_o,acplanes,srenderer); + btDbvt::collideKDOP(pbp->m_sets[0].m_root,planes_n,planes_o,acplanes,srenderer); + } + visiblecount=srenderer.drawn; + if(showOcclusion&&enableOcclusion) + { + const btScalar ratio=((float)glutGet(GLUT_WINDOW_HEIGHT))/((float)glutGet(GLUT_WINDOW_WIDTH)); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-1,1,-1,1,-1,1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + const float mm[]={ 1,0,0,0, + 0,1,0,0, + 0,0,0,1, + 0,0,0,1}; + glMultMatrixf(mm); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + const float size=0.6f; + const float orgx=0.3f; + const float orgy=0.25f; + const float left=orgx; + const float right=orgx+size; + const float top=orgy+size; + const float bottom=orgy; + ocb.drawBuffer(left,bottom,right,top); + } + if(showCulling) + { + const btScalar ratio=((float)glutGet(GLUT_WINDOW_HEIGHT))/((float)glutGet(GLUT_WINDOW_WIDTH)); + static const float scale=0.004; + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-1,1,-1*ratio,1*ratio,-1,1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + const float mm[]={ 1,0,0,0, + 0,0,1,0, + 0,1,0,0, + 0,0,0,1}; + glMultMatrixf(mm); + glScalef(scale,scale,scale); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + + glBegin(GL_LINES); + glColor4f(1,1,1,1); + + struct DebugRenderer : btDbvt::ICollide + { + OcclusionBuffer* ocb; + int sid; + bool AllLeafs(const btDbvtNode* node) + { + Process(node); + return(false); + } + bool Descent(const btDbvtNode* node) + { + return(ocb->queryOccluder(node->volume.Center(),node->volume.Extents())); + } + void Process(const btDbvtNode* node,btScalar depth) + { + Process(node); + } + void Process(const btDbvtNode* node) + { + if(ocb) + { + ocb->appendOccluder(node->volume.Center(),node->volume.Extents()); + } + if(sid>=0) + { + const float f=sid/1023.; + DrawVolume(node->volume,btVector3(1,f,f)); + sid=(sid+1)%1024; + } + else + { + if(node->isinternal()) + DrawVolume(node->volume,btVector3(0,1,0)); + else + DrawVolume(node->volume,btVector3(1,0,1)); + } + } + } drenderer; + if(enableOcclusion) + { + drenderer.ocb=&ocb; + drenderer.sid=0; + ocb.clear(); + btDbvt::collideOCL(pbp->m_sets[1].m_root,planes_n,planes_o,dir,acplanes,drenderer); + btDbvt::collideOCL(pbp->m_sets[0].m_root,planes_n,planes_o,dir,acplanes,drenderer); + } + else + { + drenderer.ocb=0; + drenderer.sid=-1; + btDbvt::collideKDOP(pbp->m_sets[1].m_root,planes_n,planes_o,acplanes,drenderer); + btDbvt::collideKDOP(pbp->m_sets[0].m_root,planes_n,planes_o,acplanes,drenderer); + } + glEnd(); + + glBegin(GL_LINES); + glColor4f(1,1,1,1); + glVertex3f(eye.x(),eye.y(),eye.z()); + glVertex3f(x00.x(),x00.y(),x00.z()); + glVertex3f(eye.x(),eye.y(),eye.z()); + glVertex3f(x10.x(),x10.y(),x10.z()); + glVertex3f(eye.x(),eye.y(),eye.z()); + glVertex3f(x01.x(),x01.y(),x01.z()); + glVertex3f(eye.x(),eye.y(),eye.z()); + glVertex3f(x11.x(),x11.y(),x11.z()); + + glVertex3f(x00.x(),x00.y(),x00.z()); + glVertex3f(x10.x(),x10.y(),x10.z()); + + glVertex3f(x10.x(),x10.y(),x10.z()); + glVertex3f(x11.x(),x11.y(),x11.z()); + + glVertex3f(x11.x(),x11.y(),x11.z()); + glVertex3f(x01.x(),x01.y(),x01.z()); + + glVertex3f(x01.x(),x01.y(),x01.z()); + glVertex3f(x00.x(),x00.y(),x00.z()); + glEnd(); + } + } +} + +void BulletSAPCompleteBoxPruningTest::KeyboardCallback(unsigned char key, int x, int y) +{ + switch (key) + { + case 'p': + case 'P': + sBulletProfilerToggle = !sBulletProfilerToggle; + break; + default : break; + } +} + +void BulletSAPCompleteBoxPruningTest::MouseCallback(int button, int state, int x, int y) +{ +} + +void BulletSAPCompleteBoxPruningTest::MotionCallback(int x, int y) +{ +} diff --git a/Extras/CDTestFramework/BulletSAPCompleteBoxPruningTest.h b/Extras/CDTestFramework/BulletSAPCompleteBoxPruningTest.h new file mode 100644 index 0000000..e944d19 --- /dev/null +++ b/Extras/CDTestFramework/BulletSAPCompleteBoxPruningTest.h @@ -0,0 +1,65 @@ +/* +BulletSAPCompleteBoxPruningTest, Copyright (c) 2008 Erwin Coumans +Part of: +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 BULLET_SAP_COMPLETEBOXPRUNING_H +#define BULLET_SAP_COMPLETEBOXPRUNING_H + +#include "LinearMath/btAlignedObjectArray.h" + +#include "CollisionTest.h" +#include "Profiling.h" + + class BulletSAPCompleteBoxPruningTest : public CollisionTest + { + public: + BulletSAPCompleteBoxPruningTest(int numBoxes,int method); + virtual ~BulletSAPCompleteBoxPruningTest(); + + virtual void Init(); + virtual void Release(); + virtual void PerformTest(); + void RenderAll(); + void Render(); + virtual void Select(); + virtual void Deselect(); + virtual void KeyboardCallback(unsigned char key, int x, int y); + virtual void MouseCallback(int button, int state, int x, int y); + virtual void MotionCallback(int x, int y); + + TwBar* mBar; //!< AntTweakBar + Profiler mProfiler; + + class btBroadphaseInterface* m_broadphase; + bool m_isdbvt; + btAlignedObjectArray m_proxies; + + udword mNbBoxes; + AABB* mBoxes; + bool* mFlags; + const char* methodname; + const AABB** mBoxPtrs; + Pairs mPairs; + float* mBoxTime; + float mAmplitude; + bool m_firstTime; + int m_method; + + private: + bool UpdateBoxes(int numBoxes); + }; + +#endif // BULLET_SAP_COMPLETEBOXPRUNING_H diff --git a/Extras/CDTestFramework/CDTestFramework.cpp b/Extras/CDTestFramework/CDTestFramework.cpp new file mode 100644 index 0000000..6ac4309 --- /dev/null +++ b/Extras/CDTestFramework/CDTestFramework.cpp @@ -0,0 +1,444 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 "stdafx.h" + +#include "CollisionTest.h" +#include "SphereMeshQuery.h" +#include "OBBMeshQuery.h" +#include "CapsuleMeshQuery.h" +#include "CompleteBoxPruning.h" +#include "BulletSAPCompleteBoxPruningTest.h" +#include "BulletSAPCompleteBoxPruningTest.h" +#include "BipartiteBoxPruning.h" +#include "OpcodeArraySAPTest.h" +#include "RenderingHelpers.h" +#include "Terrain.h" +#include "Camera.h" +#include "GLFontRenderer.h" +#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h" +#include "LinearMath/btQuickprof.h" + +#define NUM_SAP_BOXES 8192 +//#define NUM_SAP_BOXES 16384 +//#define NUM_SAP_BOXES 1024 + +int percentUpdate = 100; +//float objectSpeed = 0.005f; +float objectSpeed = 0.01f; +bool enableDraw = true; + +//Broadphase comparison +//Static case (updating 10% of objects to same position ( -> no swaps) +//number of objects //OPCODE BoxPruning / Bullet SAP / Bullet MultiSAP +//1024 0.35ms, 0.03ms, 0.15ms +//8192 21ms, 0.2ms, 5ms +//16384 92ms , 0.5ms, 28ms + +//Dynamic case, 10% objects are moving as fast as this testbed allows (0.01?) +//number of objects //OPCODE BoxPruning / Bullet SAP / Bullet MultiSAP +//1024 0.35ms, 0.2ms, 0.25ms +//8192 21ms , 15ms , 13ms +//16384 92ms, 80ms, 49ms + + +#define WINDOW_WIDTH 1024 +#define WINDOW_HEIGHT 768 + +static int gMouseX = 0; +static int gMouseY = 0; +static int gButton = 0; + +static TwBar* gMainBar = null; +enum TestIndex +{ +// TEST_SPHERE_MESH_QUERY, +// TEST_OBB_MESH_QUERY, +// TEST_CAPSULE_MESH_QUERY, +// TEST_COMPLETE_BOX_PRUNING=0, + TEST_COMPLETE_BOX_PRUNING_8192, +// TEST_BULLET_SAP_1024, +// TEST_BULLET_SAP_8192, +// TEST_BULLET_SAP_SORTEDPAIRS_8192, +// TEST_BULLET_MULTISAP_8192, +// TEST_BIPARTITE_BOX_PRUNING, + TEST_DBVT_8192, + TEST_BULLET_CUDA_8192, + TEST_BULLET_3DGRID_8192, + TEST_OPCODE_ARRAY_SAP, + MAX_NB_TESTS +}; + +//static int gTest = TEST_DBVT_8192;//TEST_BULLET_MULTISAP_8192; +//static int gSelectedTest = TEST_DBVT_8192;//TEST_BULLET_MULTISAP_8192; +static int gTest = TEST_BULLET_CUDA_8192; +static int gSelectedTest = TEST_BULLET_CUDA_8192; +static CollisionTest* gCollisionTests[MAX_NB_TESTS]; + +static GLFontRenderer gFnt; + +///////////////// + +static void KeyboardCallback(unsigned char key, int x, int y) +{ + switch (key) + { + case 27: exit(0); break; + + case '+': + { + if(gTest!=MAX_NB_TESTS-1) + { + gCollisionTests[gTest]->Deselect(); + gTest++; + gSelectedTest++; + gCollisionTests[gTest]->Select(); + } + } + break; + + case '-': + { + if(gTest) + { + gCollisionTests[gTest]->Deselect(); + gTest--; + gSelectedTest--; + gCollisionTests[gTest]->Select(); + } + } + break; + + case 101: MoveCameraForward(); break; + case 103: MoveCameraBackward(); break; + case 100: MoveCameraRight(); break; + case 102: MoveCameraLeft(); break; + default: gCollisionTests[gTest]->KeyboardCallback(key, x, y); break; + } + + TwEventKeyboardGLUT(key, x, y); +} + +static void ArrowKeyCallback(int key, int x, int y) +{ + KeyboardCallback(key, x, y); + + TwEventSpecialGLUT(key, x, y); +} + +static void MouseCallback(int button, int state, int x, int y) +{ + gButton = button; + gMouseX = x; + gMouseY = y; + + if(!TwEventMouseButtonGLUT(button, state, x, y)) + { + gCollisionTests[gTest]->MouseCallback(button, state, x, y); + } +} + +static void MotionCallback(int x, int y) +{ + if(!TwEventMouseMotionGLUT(x, y)) + { + if(gButton==2) + { + int dx = gMouseX - x; + int dy = gMouseY - y; + + RotateCamera(dx, dy); + + gMouseX = x; + gMouseY = y; + } + else + gCollisionTests[gTest]->MotionCallback(x, y); + } +} + +static void RenderCallback() +{ + // Clear buffers + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Setup camera + glMatrixMode(GL_PROJECTION); + SetupCameraMatrix(); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glEnable(GL_LIGHTING); + + if(0 /*gRenderWireframe*/) + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + else + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + gCollisionTests[gTest]->PerformTest(); + + // Draw tweak bars + TwDraw(); + + glutSwapBuffers(); + glutPostRedisplay(); + + if(gSelectedTest!=gTest) + { + gCollisionTests[gTest]->Deselect(); + gTest = gSelectedTest; + gCollisionTests[gTest]->Select(); + } +} + +static void ReshapeCallback(int width, int height) +{ + glViewport(0, 0, width, height); + + // Send the new window size to AntTweakBar + TwWindowSize(width, height); +} + +static void IdleCallback() +{ + glutPostRedisplay(); +} + +static void Terminate() +{ + ReleaseTerrain(); + + for(int i=0;iRelease(); + DELETESINGLE(gCollisionTests[i]); + } + + if(gMainBar) + { + TwDeleteBar(gMainBar); + gMainBar = null; + } + + TwTerminate(); +} + +int main(int argc, char** argv) +{ + { + ::SetPriorityClass(::GetCurrentProcess(),REALTIME_PRIORITY_CLASS); + /*btDbvt::benchmark(); + exit(0);*/ + } + // Initialize AntTweakBar + // (note that AntTweakBar could also be intialize after GLUT, no matter) + if(!TwInit(TW_OPENGL, NULL)) + { + // A fatal error occured + fprintf(stderr, "AntTweakBar initialization failed: %s\n", TwGetLastError()); + } + + // Initialize Glut + glutInit(&argc, argv); + glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); + int mainHandle = glutCreateWindow("CD Test Framework"); + +/* HWND hWnd; + hWnd = FindWindow("GLUT", "CD Test Framework"); + RECT Rect; + GetWindowRect(hWnd, &Rect); +*/ + glutCreateMenu(NULL); + glutSetWindow(mainHandle); + glutDisplayFunc(RenderCallback); + glutReshapeFunc(ReshapeCallback); + glutIdleFunc(IdleCallback); + glutKeyboardFunc(KeyboardCallback); + glutSpecialFunc(ArrowKeyCallback); + glutMouseFunc(MouseCallback); + glutMotionFunc(MotionCallback); + atexit(Terminate); // Called after glutMainLoop ends + + glutPassiveMotionFunc((GLUTmousemotionfun)TwEventMouseMotionGLUT); + TwGLUTModifiersFunc(glutGetModifiers); + + // Setup default render states + glClearColor(0.3f, 0.4f, 0.5f, 1.0); + glEnable(GL_DEPTH_TEST); + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_CULL_FACE); + glDepthFunc(GL_LEQUAL); + + // Setup lighting + glEnable(GL_LIGHTING); + float AmbientColor[] = { 0.0f, 0.1f, 0.2f, 0.0f }; glLightfv(GL_LIGHT0, GL_AMBIENT, AmbientColor); + float DiffuseColor[] = { 1.0f, 1.0f, 1.0f, 0.0f }; glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseColor); + float SpecularColor[] = { 0.0f, 0.0f, 0.0f, 0.0f }; glLightfv(GL_LIGHT0, GL_SPECULAR, SpecularColor); + float Position[] = { -10.0f, 1000.0f, -4.0f, 1.0f }; glLightfv(GL_LIGHT0, GL_POSITION, Position); + glEnable(GL_LIGHT0); + + gFnt.init(); + gFnt.setScreenResolution(WINDOW_WIDTH, WINDOW_HEIGHT); + gFnt.setColor(1.0f, 1.0f, 1.0f, 1.0f); + + CreateTerrain(); + + // Create main tweak bar + { + gMainBar = TwNewBar("CollisionTests"); + TwEnumVal testEV[MAX_NB_TESTS] = { +// {TEST_SPHERE_MESH_QUERY, "Sphere-mesh query"}, +// {TEST_OBB_MESH_QUERY, "OBB-mesh query"}, +// {TEST_CAPSULE_MESH_QUERY, "Capsule-mesh query"}, +// {TEST_COMPLETE_BOX_PRUNING, "OPCODE SAP 1024"}, + {TEST_COMPLETE_BOX_PRUNING_8192, "OPCODE BOX PRUNING 8192"}, +// {TEST_BULLET_SAP_1024, "Bullet SAP HASHPAIR 1024"}, +// {TEST_BULLET_SAP_8192, "Bullet SAP HASHPAIR 8192"}, +// {TEST_BULLET_SAP_SORTEDPAIRS_8192, "Bullet SAP SORTEDPAIR 8192"}, +// {TEST_BULLET_MULTISAP_8192, "Bullet MultiSAP 8192"}, +// {TEST_BIPARTITE_BOX_PRUNING, "Bipartite box pruning"}, + {TEST_DBVT_8192, "Bullet DBVT 8192"}, + {TEST_BULLET_CUDA_8192, "Bullet CUDA 8192"}, + {TEST_BULLET_3DGRID_8192, "Bullet 3D Grid 8192"}, + {TEST_OPCODE_ARRAY_SAP, "OPCODE ARRAY SAP"}, + }; + TwType testType = TwDefineEnum("CollisionTest", testEV, MAX_NB_TESTS); + TwAddVarRW(gMainBar, "CollisionTests", testType, &gSelectedTest, ""); + TwAddVarRW(gMainBar, "% of updates",TW_TYPE_INT32,&percentUpdate,"min=0 max=100"); + TwAddVarRW(gMainBar, "Draw",TW_TYPE_BOOLCPP,&enableDraw,""); + } + + // Create tests + gTest = 0; +// gCollisionTests[TEST_SPHERE_MESH_QUERY] = new SphereMeshQuery; +// gCollisionTests[TEST_OBB_MESH_QUERY] = new OBBMeshQuery; +// gCollisionTests[TEST_CAPSULE_MESH_QUERY] = new CapsuleMeshQuery; +// gCollisionTests[TEST_COMPLETE_BOX_PRUNING] = new CompleteBoxPruningTest(NUM_SAP_BOXES); + // gCollisionTests[TEST_COMPLETE_BOX_PRUNING_8192] = new CompleteBoxPruningTest(NUM_SAP_BOXES); + gCollisionTests[TEST_COMPLETE_BOX_PRUNING_8192] = new CompleteBoxPruningTest(NUM_SAP_BOXES); +// gCollisionTests[TEST_BULLET_SAP_1024] = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,1); +// gCollisionTests[TEST_BULLET_SAP_8192] = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,1); +// gCollisionTests[TEST_BULLET_SAP_SORTEDPAIRS_8192] = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,3); +// gCollisionTests[TEST_BULLET_MULTISAP_8192] = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,6); +// gCollisionTests[TEST_BIPARTITE_BOX_PRUNING] = new BipartiteBoxPruningTest; + gCollisionTests[TEST_DBVT_8192] = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,7); + gCollisionTests[TEST_BULLET_CUDA_8192] = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,8); + gCollisionTests[TEST_BULLET_3DGRID_8192] = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,9); + gCollisionTests[TEST_OPCODE_ARRAY_SAP] = new OpcodeArraySAPTest(NUM_SAP_BOXES); + + for(int i=0;iInit(); + gCollisionTests[gTest]->Select(); + + // + MotionCallback(0,0); + + // Run + glutMainLoop(); + + return 0; +} + + +#ifdef OLDIES + +#include "btBulletCollisionCommon.h" + +class BulletMeshInterface : public btStridingMeshInterface +{ + public: + /// get read and write access to a subpart of a triangle mesh + /// this subpart has a continuous array of vertices and indices + /// in this way the mesh can be handled as chunks of memory with striding + /// very similar to OpenGL vertexarray support + /// make a call to unLockVertexBase when the read and write access is finished + virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) + { + numverts = gTerrainData->nbVerts; + (*vertexbase) = (unsigned char *)gTerrainData->verts; + type = PHY_FLOAT; + stride = sizeof(Point); + + numfaces = gTerrainData->nbFaces; + (*indexbase) = (unsigned char *)gTerrainData->faces; + indicestype = PHY_INTEGER; + indexstride = 3*sizeof(udword); // ?? + } + + virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const + { + numverts = gTerrainData->nbVerts; + (*vertexbase) = (unsigned char *)gTerrainData->verts; + type = PHY_FLOAT; + stride = sizeof(Point); + + numfaces = gTerrainData->nbFaces; + (*indexbase) = (unsigned char *)gTerrainData->faces; + indicestype = PHY_INTEGER; + indexstride = 3*sizeof(udword); // ?? + } + + /// unLockVertexBase finishes the access to a subpart of the triangle mesh + /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished + virtual void unLockVertexBase(int subpart) + { + } + + virtual void unLockReadOnlyVertexBase(int subpart) const + { + } + + + /// getNumSubParts returns the number of seperate subparts + /// each subpart has a continuous array of vertices and indices + virtual int getNumSubParts() const + { + return 1; + } + + virtual void preallocateVertices(int numverts) + { + } + virtual void preallocateIndices(int numindices) + { + } +}; + +void BuildBulletTree() +{ +/* BulletMeshInterface btMeshInterface; + + btOptimizedBvh* btTree = new btOptimizedBvh; + btTree->build(&btMeshInterface, true); + + + struct MyNodeOverlapCallback : public btNodeOverlapCallback + { + virtual void processNode(int nodeSubPart, int nodeTriangleIndex) + { + } + }; + + MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); + + m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); +*/ + + +} + +#endif \ No newline at end of file diff --git a/Extras/CDTestFramework/CDTestFramework.h b/Extras/CDTestFramework/CDTestFramework.h new file mode 100644 index 0000000..b803cb3 --- /dev/null +++ b/Extras/CDTestFramework/CDTestFramework.h @@ -0,0 +1,20 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 CDTESTFRAMEWORK_H +#define CDTESTFRAMEWORK_H + +#endif // CDTESTFRAMEWORK_H diff --git a/Extras/CDTestFramework/CDTestFramework.sln b/Extras/CDTestFramework/CDTestFramework.sln new file mode 100644 index 0000000..19f2e5b --- /dev/null +++ b/Extras/CDTestFramework/CDTestFramework.sln @@ -0,0 +1,96 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDTestFramework", "CDTestFramework.vcproj", "{0565DB39-45CC-416E-B549-BFC24F2666D1}" + ProjectSection(ProjectDependencies) = postProject + {519F115F-F196-49FE-9B24-49618A6202BB} = {519F115F-F196-49FE-9B24-49618A6202BB} + {C0E1329C-3D6F-492D-8EFF-08069F096C6E} = {C0E1329C-3D6F-492D-8EFF-08069F096C6E} + {DBE44CA3-2912-4441-8D99-AA2242688AD2} = {DBE44CA3-2912-4441-8D99-AA2242688AD2} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Opcode", "Opcode\Opcode.vcproj", "{DBE44CA3-2912-4441-8D99-AA2242688AD2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LinearMath", "..\..\msvc\2008\src\LinearMath\LinearMath.vcproj", "{519F115F-F196-49FE-9B24-49618A6202BB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletCollision", "..\..\msvc\2008\src\BulletCollision\BulletCollision.vcproj", "{C0E1329C-3D6F-492D-8EFF-08069F096C6E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + DebugDll|Win32 = DebugDll|Win32 + DebugDoublePrecision|Win32 = DebugDoublePrecision|Win32 + MinSizeRel|Win32 = MinSizeRel|Win32 + Release|Win32 = Release|Win32 + ReleaseDll|Win32 = ReleaseDll|Win32 + ReleaseDoublePrecision|Win32 = ReleaseDoublePrecision|Win32 + RelWithDebInfo|Win32 = RelWithDebInfo|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0565DB39-45CC-416E-B549-BFC24F2666D1}.Debug|Win32.ActiveCfg = Debug|Win32 + {0565DB39-45CC-416E-B549-BFC24F2666D1}.Debug|Win32.Build.0 = Debug|Win32 + {0565DB39-45CC-416E-B549-BFC24F2666D1}.DebugDll|Win32.ActiveCfg = Debug|Win32 + {0565DB39-45CC-416E-B549-BFC24F2666D1}.DebugDll|Win32.Build.0 = Debug|Win32 + {0565DB39-45CC-416E-B549-BFC24F2666D1}.DebugDoublePrecision|Win32.ActiveCfg = Debug|Win32 + {0565DB39-45CC-416E-B549-BFC24F2666D1}.DebugDoublePrecision|Win32.Build.0 = Debug|Win32 + {0565DB39-45CC-416E-B549-BFC24F2666D1}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {0565DB39-45CC-416E-B549-BFC24F2666D1}.MinSizeRel|Win32.Build.0 = Release|Win32 + {0565DB39-45CC-416E-B549-BFC24F2666D1}.Release|Win32.ActiveCfg = Release|Win32 + {0565DB39-45CC-416E-B549-BFC24F2666D1}.Release|Win32.Build.0 = Release|Win32 + {0565DB39-45CC-416E-B549-BFC24F2666D1}.ReleaseDll|Win32.ActiveCfg = Release|Win32 + {0565DB39-45CC-416E-B549-BFC24F2666D1}.ReleaseDll|Win32.Build.0 = Release|Win32 + {0565DB39-45CC-416E-B549-BFC24F2666D1}.ReleaseDoublePrecision|Win32.ActiveCfg = Release|Win32 + {0565DB39-45CC-416E-B549-BFC24F2666D1}.ReleaseDoublePrecision|Win32.Build.0 = Release|Win32 + {0565DB39-45CC-416E-B549-BFC24F2666D1}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {0565DB39-45CC-416E-B549-BFC24F2666D1}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {DBE44CA3-2912-4441-8D99-AA2242688AD2}.Debug|Win32.ActiveCfg = Debug|Win32 + {DBE44CA3-2912-4441-8D99-AA2242688AD2}.Debug|Win32.Build.0 = Debug|Win32 + {DBE44CA3-2912-4441-8D99-AA2242688AD2}.DebugDll|Win32.ActiveCfg = Debug|Win32 + {DBE44CA3-2912-4441-8D99-AA2242688AD2}.DebugDll|Win32.Build.0 = Debug|Win32 + {DBE44CA3-2912-4441-8D99-AA2242688AD2}.DebugDoublePrecision|Win32.ActiveCfg = Debug|Win32 + {DBE44CA3-2912-4441-8D99-AA2242688AD2}.DebugDoublePrecision|Win32.Build.0 = Debug|Win32 + {DBE44CA3-2912-4441-8D99-AA2242688AD2}.MinSizeRel|Win32.ActiveCfg = Debug|Win32 + {DBE44CA3-2912-4441-8D99-AA2242688AD2}.MinSizeRel|Win32.Build.0 = Debug|Win32 + {DBE44CA3-2912-4441-8D99-AA2242688AD2}.Release|Win32.ActiveCfg = Release|Win32 + {DBE44CA3-2912-4441-8D99-AA2242688AD2}.Release|Win32.Build.0 = Release|Win32 + {DBE44CA3-2912-4441-8D99-AA2242688AD2}.ReleaseDll|Win32.ActiveCfg = Release|Win32 + {DBE44CA3-2912-4441-8D99-AA2242688AD2}.ReleaseDll|Win32.Build.0 = Release|Win32 + {DBE44CA3-2912-4441-8D99-AA2242688AD2}.ReleaseDoublePrecision|Win32.ActiveCfg = Release|Win32 + {DBE44CA3-2912-4441-8D99-AA2242688AD2}.ReleaseDoublePrecision|Win32.Build.0 = Release|Win32 + {DBE44CA3-2912-4441-8D99-AA2242688AD2}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {DBE44CA3-2912-4441-8D99-AA2242688AD2}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {519F115F-F196-49FE-9B24-49618A6202BB}.Debug|Win32.ActiveCfg = Debug|Win32 + {519F115F-F196-49FE-9B24-49618A6202BB}.Debug|Win32.Build.0 = Debug|Win32 + {519F115F-F196-49FE-9B24-49618A6202BB}.DebugDll|Win32.ActiveCfg = Debug|Win32 + {519F115F-F196-49FE-9B24-49618A6202BB}.DebugDll|Win32.Build.0 = Debug|Win32 + {519F115F-F196-49FE-9B24-49618A6202BB}.DebugDoublePrecision|Win32.ActiveCfg = Debug|Win32 + {519F115F-F196-49FE-9B24-49618A6202BB}.DebugDoublePrecision|Win32.Build.0 = Debug|Win32 + {519F115F-F196-49FE-9B24-49618A6202BB}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {519F115F-F196-49FE-9B24-49618A6202BB}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {519F115F-F196-49FE-9B24-49618A6202BB}.Release|Win32.ActiveCfg = Release|Win32 + {519F115F-F196-49FE-9B24-49618A6202BB}.Release|Win32.Build.0 = Release|Win32 + {519F115F-F196-49FE-9B24-49618A6202BB}.ReleaseDll|Win32.ActiveCfg = Release|Win32 + {519F115F-F196-49FE-9B24-49618A6202BB}.ReleaseDll|Win32.Build.0 = Release|Win32 + {519F115F-F196-49FE-9B24-49618A6202BB}.ReleaseDoublePrecision|Win32.ActiveCfg = Release|Win32 + {519F115F-F196-49FE-9B24-49618A6202BB}.ReleaseDoublePrecision|Win32.Build.0 = Release|Win32 + {519F115F-F196-49FE-9B24-49618A6202BB}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {519F115F-F196-49FE-9B24-49618A6202BB}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {C0E1329C-3D6F-492D-8EFF-08069F096C6E}.Debug|Win32.ActiveCfg = Debug|Win32 + {C0E1329C-3D6F-492D-8EFF-08069F096C6E}.Debug|Win32.Build.0 = Debug|Win32 + {C0E1329C-3D6F-492D-8EFF-08069F096C6E}.DebugDll|Win32.ActiveCfg = Debug|Win32 + {C0E1329C-3D6F-492D-8EFF-08069F096C6E}.DebugDll|Win32.Build.0 = Debug|Win32 + {C0E1329C-3D6F-492D-8EFF-08069F096C6E}.DebugDoublePrecision|Win32.ActiveCfg = Debug|Win32 + {C0E1329C-3D6F-492D-8EFF-08069F096C6E}.DebugDoublePrecision|Win32.Build.0 = Debug|Win32 + {C0E1329C-3D6F-492D-8EFF-08069F096C6E}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {C0E1329C-3D6F-492D-8EFF-08069F096C6E}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {C0E1329C-3D6F-492D-8EFF-08069F096C6E}.Release|Win32.ActiveCfg = Release|Win32 + {C0E1329C-3D6F-492D-8EFF-08069F096C6E}.Release|Win32.Build.0 = Release|Win32 + {C0E1329C-3D6F-492D-8EFF-08069F096C6E}.ReleaseDll|Win32.ActiveCfg = Release|Win32 + {C0E1329C-3D6F-492D-8EFF-08069F096C6E}.ReleaseDll|Win32.Build.0 = Release|Win32 + {C0E1329C-3D6F-492D-8EFF-08069F096C6E}.ReleaseDoublePrecision|Win32.ActiveCfg = Release|Win32 + {C0E1329C-3D6F-492D-8EFF-08069F096C6E}.ReleaseDoublePrecision|Win32.Build.0 = Release|Win32 + {C0E1329C-3D6F-492D-8EFF-08069F096C6E}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {C0E1329C-3D6F-492D-8EFF-08069F096C6E}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Extras/CDTestFramework/CDTestFramework.txt b/Extras/CDTestFramework/CDTestFramework.txt new file mode 100644 index 0000000..6ff06a0 --- /dev/null +++ b/Extras/CDTestFramework/CDTestFramework.txt @@ -0,0 +1,31 @@ + +CD Test Framework +================= + +This is a very small app used to test various collision detection (CD) algorithms. +It will be first used as a demo/sample for Opcode 1.3 (a lot of people requested this), +and then I will also include benchmarks against competing libraries (Bullet, GIMPACT, etc). + +Update April 2, 2008 +Erwin Coumans added Bullet support for broadphase test (SAP, MultiSAP, other tests follow) +This CDTestFramework is now included in Bullet/Extras under the ZLib license. + +Current version includes tests for: +- sphere vs mesh queries +- OBB vs mesh queries +- capsule vs mesh queries +- complete box pruning +- bipartite box pruning + + +Pierre Terdiman +March 16, 2007 + +External libs used: + +Opcode 1.3 (http://www.codercorner.com/Opcode.htm) +AntTweakBar (http://www.antisphere.com/Wiki/tools:anttweakbar) +Bullet Physics Library (http://bulletphysics.com) + +Contact email: +pierre@codercorner.com \ No newline at end of file diff --git a/Extras/CDTestFramework/CDTestFramework.vcproj b/Extras/CDTestFramework/CDTestFramework.vcproj new file mode 100644 index 0000000..4907d1a --- /dev/null +++ b/Extras/CDTestFramework/CDTestFramework.vcproj @@ -0,0 +1,363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/CDTestFramework/Camera.cpp b/Extras/CDTestFramework/Camera.cpp new file mode 100644 index 0000000..21ee727 --- /dev/null +++ b/Extras/CDTestFramework/Camera.cpp @@ -0,0 +1,156 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 "stdafx.h" +#include "Camera.h" + +static const float gCamSpeed = 1.0f; +//static Point gEye(3.0616338f, 1.1985892f, 2.5769043f); +//static Point gDir(-0.66853905,-0.14004262,-0.73037237); +static Point gEye(240, 205, 205); +static Point gDir(-1,-1,-1); +static Point gN; +static float gFOV = 60.0f; + +const Point& GetCameraPos() +{ + return gEye; +} + +const Point& GetCameraDir() +{ + return gDir; +} + +void MoveCameraForward() +{ + gEye += gDir * gCamSpeed; +} + +void MoveCameraBackward() +{ + gEye -= gDir * gCamSpeed; +} + +void MoveCameraRight() +{ + gEye -= gN * gCamSpeed; +} + +void MoveCameraLeft() +{ + gEye += gN * gCamSpeed; +} + + static const float NxPiF32 = 3.141592653589793f; + + float degToRad(float a) + { + return (float)0.01745329251994329547 * a; + } + + class NxQuat + { + public: + NxQuat(){} + + NxQuat(const float angle, const Point & axis) + { + x = axis.x; + y = axis.y; + z = axis.z; + + const float i_length = 1.0f / sqrtf( x*x + y*y + z*z ); + x = x * i_length; + y = y * i_length; + z = z * i_length; + + float Half = degToRad(angle * 0.5f); + + w = cosf(Half); + const float sin_theta_over_two = sinf(Half ); + x = x * sin_theta_over_two; + y = y * sin_theta_over_two; + z = z * sin_theta_over_two; + } + + void NxQuat::multiply(const NxQuat& left, const Point& right) + { + float a,b,c,d; + + a = - left.x*right.x - left.y*right.y - left.z *right.z; + b = left.w*right.x + left.y*right.z - right.y*left.z; + c = left.w*right.y + left.z*right.x - right.z*left.x; + d = left.w*right.z + left.x*right.y - right.x*left.y; + + w = a; + x = b; + y = c; + z = d; + } + + void NxQuat::rotate(Point & v) const + { + NxQuat myInverse; + myInverse.x = -x; + myInverse.y = -y; + myInverse.z = -z; + myInverse.w = w; + + NxQuat left; + left.multiply(*this,v); + v.x = left.w*myInverse.x + myInverse.w*left.x + left.y*myInverse.z - myInverse.y*left.z; + v.y = left.w*myInverse.y + myInverse.w*left.y + left.z*myInverse.x - myInverse.z*left.x; + v.z = left.w*myInverse.z + myInverse.w*left.z + left.x*myInverse.y - myInverse.x*left.y; + } + + float x,y,z,w; + }; + +void RotateCamera(int dx, int dy) +{ + gDir = gDir.Normalize(); + gN = gDir ^ Point(0,1,0); + + NxQuat qx(NxPiF32 * dx * 20/ 180.0f, Point(0,1,0)); + qx.rotate(gDir); + NxQuat qy(NxPiF32 * dy * 20/ 180.0f, gN); + qy.rotate(gDir); +} + +void SetupCameraMatrix() +{ + glLoadIdentity(); + gluPerspective(gFOV, ((float)glutGet(GLUT_WINDOW_WIDTH))/((float)glutGet(GLUT_WINDOW_HEIGHT)), 1.0f, 10000.0f); + gluLookAt(gEye.x, gEye.y, gEye.z, gEye.x + gDir.x, gEye.y + gDir.y, gEye.z + gDir.z, 0.0f, 1.0f, 0.0f); +} + +Point ComputeWorldRay(int xs, int ys) +{ + GLint viewPort[4]; + GLdouble modelMatrix[16]; + GLdouble projMatrix[16]; + glGetIntegerv(GL_VIEWPORT, viewPort); + glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); + glGetDoublev(GL_PROJECTION_MATRIX, projMatrix); + ys = viewPort[3] - ys - 1; + GLdouble wx0, wy0, wz0; + gluUnProject((GLdouble) xs, (GLdouble) ys, 0.0, modelMatrix, projMatrix, viewPort, &wx0, &wy0, &wz0); + GLdouble wx1, wy1, wz1; + gluUnProject((GLdouble) xs, (GLdouble) ys, 1.0, modelMatrix, projMatrix, viewPort, &wx1, &wy1, &wz1); + Point tmp(float(wx1-wx0), float(wy1-wy0), float(wz1-wz0)); + tmp.Normalize(); + return tmp; +} diff --git a/Extras/CDTestFramework/Camera.h b/Extras/CDTestFramework/Camera.h new file mode 100644 index 0000000..0696e68 --- /dev/null +++ b/Extras/CDTestFramework/Camera.h @@ -0,0 +1,32 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 CAMERA_H +#define CAMERA_H + + const Point& GetCameraPos(); + const Point& GetCameraDir(); + void RotateCamera(int dx, int dy); + + void MoveCameraForward(); + void MoveCameraBackward(); + void MoveCameraRight(); + void MoveCameraLeft(); + + void SetupCameraMatrix(); + Point ComputeWorldRay(int xs, int ys); + +#endif // CAMERA_H diff --git a/Extras/CDTestFramework/CapsuleMeshQuery.cpp b/Extras/CDTestFramework/CapsuleMeshQuery.cpp new file mode 100644 index 0000000..b1a6209 --- /dev/null +++ b/Extras/CDTestFramework/CapsuleMeshQuery.cpp @@ -0,0 +1,127 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 "stdafx.h" +#include "IceHelpers.h" +#include "RenderingHelpers.h" +#include "Terrain.h" +#include "CapsuleMeshQuery.h" +#include "Camera.h" +#include "GLFontRenderer.h" + +CapsuleMeshQuery::CapsuleMeshQuery() : + mBar (null), + mDist (0.0f), + mValidHit (false) +{ +} + +CapsuleMeshQuery::~CapsuleMeshQuery() +{ +} + +void CapsuleMeshQuery::Init() +{ + mP0 = Point(0.0f, -4.0f, 0.0f); + mP1 = Point(0.0f, 4.0f, 0.0f); + + Matrix3x3 MX,MY; + RotX(MX, 45.0f); + RotY(MY, 45.0f); + + mWorld = MX * MY; + mWorld.SetTrans(0.0f, 4.0f, 0.0f); +} + +void CapsuleMeshQuery::Release() +{ +} + +void CapsuleMeshQuery::PerformTest() +{ + RenderTerrain(); + + mCapsule.mP0 = mP0 * mWorld; + mCapsule.mP1 = mP1 * mWorld; + mCapsule.mRadius = 1.0f; + DrawCapsule(mWorld, mP0, mP1, 1.0f); + + const Model* TM = GetTerrainModel(); + if(TM) + { + LSSCollider Collider; + + mProfiler.Start(); + bool Status = Collider.Collide(mCache, mCapsule, *TM, null, null); + mProfiler.End(); + mProfiler.Accum(); + + if(Status) + { + if(Collider.GetContactStatus()) + { + udword NbTris = Collider.GetNbTouchedPrimitives(); + const udword* Indices = Collider.GetTouchedPrimitives(); + + RenderTerrainTriangles(NbTris, Indices); + } + } + } + + // Raycast hit + if(mValidHit) + { + Point wp = mLocalHit + (Point)mWorld.GetTrans(); + DrawLine(wp, wp + Point(1.0f, 0.0f, 0.0f), Point(1,0,0), 1.0f); + DrawLine(wp, wp + Point(0.0f, 1.0f, 0.0f), Point(0,1,0), 1.0f); + DrawLine(wp, wp + Point(0.0f, 0.0f, 1.0f), Point(0,0,1), 1.0f); + } + + char Buffer[4096]; + sprintf(Buffer, "Capsule-mesh query = %5.1f us (%d cycles)\n", mProfiler.mMsTime, mProfiler.mCycles); + GLFontRenderer::print(10.0f, 10.0f, 0.02f, Buffer); +} + +void CapsuleMeshQuery::KeyboardCallback(unsigned char key, int x, int y) +{ +} + +void CapsuleMeshQuery::MouseCallback(int button, int state, int x, int y) +{ + mValidHit = false; + if(!button && !state) + { + Point Dir = ComputeWorldRay(x, y); + + float s[2]; + if(RayCapsuleOverlap(GetCameraPos(), Dir, mCapsule, s)) + { + mValidHit = true; + mDist = s[0]; + Point hit = GetCameraPos() + Dir * mDist; + mLocalHit = hit - (Point)mWorld.GetTrans(); + } + } +} + +void CapsuleMeshQuery::MotionCallback(int x, int y) +{ + if(mValidHit) + { + Point Dir = ComputeWorldRay(x, y); + mWorld.SetTrans(GetCameraPos() + Dir*mDist - mLocalHit); + } +} diff --git a/Extras/CDTestFramework/CapsuleMeshQuery.h b/Extras/CDTestFramework/CapsuleMeshQuery.h new file mode 100644 index 0000000..590e369 --- /dev/null +++ b/Extras/CDTestFramework/CapsuleMeshQuery.h @@ -0,0 +1,49 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 CAPSULEMESHQUERY_H +#define CAPSULEMESHQUERY_H + +#include "CollisionTest.h" +#include "Profiling.h" + + class CapsuleMeshQuery : public CollisionTest + { + public: + CapsuleMeshQuery(); + virtual ~CapsuleMeshQuery(); + + virtual void Init(); + virtual void Release(); + virtual void PerformTest(); + virtual void KeyboardCallback(unsigned char key, int x, int y); + virtual void MouseCallback(int button, int state, int x, int y); + virtual void MotionCallback(int x, int y); + + TwBar* mBar; //!< AntTweakBar + Profiler mProfiler; + + Point mP0; + Point mP1; + Matrix4x4 mWorld; + LSS mCapsule; + LSSCache mCache; + + float mDist; + Point mLocalHit; + bool mValidHit; + }; + +#endif // CAPSULEMESHQUERY_H diff --git a/Extras/CDTestFramework/CollisionTest.cpp b/Extras/CDTestFramework/CollisionTest.cpp new file mode 100644 index 0000000..e487154 --- /dev/null +++ b/Extras/CDTestFramework/CollisionTest.cpp @@ -0,0 +1,38 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 "stdafx.h" +#include "CollisionTest.h" + +OpcodeSettings::OpcodeSettings() : + mPrimitiveTests (true), + mFirstContact (false), + mUseCache (false) +{ +} + +void OpcodeSettings::AddToTweakBar(TwBar* tbar) +{ + TwAddVarRW(tbar, "Primitive tests", TW_TYPE_BOOLCPP, &mPrimitiveTests, " group='Opcode' "); + TwAddVarRW(tbar, "First contact", TW_TYPE_BOOLCPP, &mFirstContact, " group='Opcode' "); + TwAddVarRW(tbar, "Temporal coherence", TW_TYPE_BOOLCPP, &mUseCache, " group='Opcode' "); +} + +void OpcodeSettings::SetupCollider(Collider& collider) const +{ + collider.SetFirstContact(mFirstContact); + collider.SetPrimitiveTests(mPrimitiveTests); + collider.SetTemporalCoherence(mUseCache); +} \ No newline at end of file diff --git a/Extras/CDTestFramework/CollisionTest.h b/Extras/CDTestFramework/CollisionTest.h new file mode 100644 index 0000000..addef25 --- /dev/null +++ b/Extras/CDTestFramework/CollisionTest.h @@ -0,0 +1,50 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 COLLISIONTEST_H +#define COLLISIONTEST_H + + class CollisionTest + { + public: + + CollisionTest() {} + virtual ~CollisionTest() {} + + virtual void Init() = 0; + virtual void Release() = 0; + virtual void PerformTest() = 0; + virtual void Select() {} + virtual void Deselect() {} + virtual void KeyboardCallback(unsigned char key, int x, int y) {} + virtual void MouseCallback(int button, int state, int x, int y) {} + virtual void MotionCallback(int x, int y) {} + }; + + class OpcodeSettings + { + public: + OpcodeSettings(); + + void AddToTweakBar(TwBar* tbar); + void SetupCollider(Collider& collider) const; + + bool mPrimitiveTests; + bool mFirstContact; + bool mUseCache; + }; + +#endif // COLLISIONTEST_H diff --git a/Extras/CDTestFramework/CompleteBoxPruning.cpp b/Extras/CDTestFramework/CompleteBoxPruning.cpp new file mode 100644 index 0000000..9f0c1b2 --- /dev/null +++ b/Extras/CDTestFramework/CompleteBoxPruning.cpp @@ -0,0 +1,168 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 "stdafx.h" +#include "CompleteBoxPruning.h" +#include "RenderingHelpers.h" +#include "GLFontRenderer.h" + +CompleteBoxPruningTest::CompleteBoxPruningTest(int numBoxes) : + mBar (null), + mNbBoxes (numBoxes), + mBoxes (null), + mBoxPtrs (null), + mBoxTime (null), + mSpeed (0.005f), + mAmplitude (100.0f) +{ +} + +CompleteBoxPruningTest::~CompleteBoxPruningTest() +{ + DELETEARRAY(mBoxTime); + DELETEARRAY(mBoxPtrs); + DELETEARRAY(mBoxes); +} + +void CompleteBoxPruningTest::Init() +{ + m_firstTime = true; + + SRand(0); + mBoxes = new AABB[mNbBoxes]; + mBoxPtrs = new const AABB*[mNbBoxes]; + mBoxTime = new float[mNbBoxes]; + for(udword i=0;i +#include +#include +#include + +#include "GLFontData.h" +#include "GLFontRenderer.h" + +bool GLFontRenderer::m_isInit=false; +unsigned int GLFontRenderer::m_textureObject=0; +int GLFontRenderer::m_screenWidth=640; +int GLFontRenderer::m_screenHeight=480; +float GLFontRenderer::m_color[4]={1.0f, 1.0f, 1.0f, 1.0f}; + +bool GLFontRenderer::init() +{ + glGenTextures(1, &m_textureObject); + if(m_textureObject == 0) return false; + + glBindTexture(GL_TEXTURE_2D, m_textureObject); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + // expand to rgba + unsigned char* pNewSource = new unsigned char[OGL_FONT_TEXTURE_WIDTH*OGL_FONT_TEXTURE_HEIGHT*4]; + for(int i=0;i 0) + { + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, m_textureObject); + + + if(doOrthoProj) + { + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, m_screenWidth, 0, m_screenHeight, -1, 1); + } + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glEnable(GL_BLEND); + + glColor4f(m_color[0], m_color[1], m_color[2], m_color[3]); + + const float glyphHeightUV = ((float)OGL_FONT_CHARS_PER_COL)/OGL_FONT_TEXTURE_HEIGHT*2-0.01f; + + float translate = 0.0f; + + float* pVertList = new float[num*3*6]; + float* pTextureCoordList = new float[num*2*6]; + int vertIndex = 0; + int textureCoordIndex = 0; + + float translateDown = 0.0f; + unsigned int count = 0; + + for(unsigned int i=0;iRB6|uMTbzJ;*3;m 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 literal 0 HcmV?d00001 diff --git a/Extras/CDTestFramework/History.txt b/Extras/CDTestFramework/History.txt new file mode 100644 index 0000000..b0f93f2 --- /dev/null +++ b/Extras/CDTestFramework/History.txt @@ -0,0 +1,11 @@ + +========================= + +V 1.0 - March 16, 2007 + + - sphere vs mesh queries + - OBB vs mesh queries + - capsule vs mesh queries + - complete box pruning + - bipartite box pruning + diff --git a/Extras/CDTestFramework/IceHelpers.cpp b/Extras/CDTestFramework/IceHelpers.cpp new file mode 100644 index 0000000..1e2c422 --- /dev/null +++ b/Extras/CDTestFramework/IceHelpers.cpp @@ -0,0 +1,358 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 "stdafx.h" +#include "IceHelpers.h" + +// Misc functions borrowed & adapted from ICE + +void RotX(Matrix3x3& m, float angle) +{ + float Cos = cosf(angle); + float Sin = sinf(angle); + m.Identity(); + m.m[1][1] = m.m[2][2] = Cos; + m.m[2][1] = -Sin; + m.m[1][2] = Sin; +} + +void RotY(Matrix3x3& m, float angle) +{ + float Cos = cosf(angle); + float Sin = sinf(angle); + m.Identity(); + m.m[0][0] = m.m[2][2] = Cos; + m.m[2][0] = Sin; + m.m[0][2] = -Sin; +} + +void RotZ(Matrix3x3& m, float angle) +{ + float Cos = cosf(angle); + float Sin = sinf(angle); + m.Identity(); + m.m[0][0] = m.m[1][1] = Cos; + m.m[1][0] = -Sin; + m.m[0][1] = Sin; +} + +bool SegmentSphere(const Point& origin, const Point& dir, float length, const Point& center, float radius, float& dist, Point& hit_pos) +{ + // get the offset vector + Point offset = center - origin; + + // get the distance along the ray to the center point of the sphere + float ray_dist = dir | offset; + + // get the squared distances + float off2 = offset | offset; + float rd2 = radius * radius; + if(off2 <= rd2) + { + // we're in the sphere + hit_pos = origin; + dist = 0.0f; + return true; + } + + if(ray_dist <= 0 || (ray_dist - length) > radius) + { + // moving away from object or too far away + return false; + } + + // find hit distance squared + float d = rd2 - (off2 - ray_dist * ray_dist); + if(d<0.0f) + { + // ray passes by sphere without hitting + return false; + } + + // get the distance along the ray + dist = ray_dist - sqrtf(d); + if(dist > length) + { + // hit point beyond length + return false; + } + + // sort out the details + hit_pos = origin + dir * dist; + return true; +} + +bool /*Ctc::*/RayAABB2(const Point& min, const Point& max, const Point& origin, const Point& dir, Point& coord) +{ + BOOL Inside = TRUE; + Point MaxT; + MaxT.x=MaxT.y=MaxT.z=-1.0f; + + // Find candidate planes. + for(udword i=0;i<3;i++) + { + if(origin[i] < min[i]) + { + coord[i] = min[i]; + Inside = FALSE; + + // Calculate T distances to candidate planes + if(IR(dir[i])) MaxT[i] = (min[i] - origin[i]) / dir[i]; + } + else if(origin[i] > max[i]) + { + coord[i] = max[i]; + Inside = FALSE; + + // Calculate T distances to candidate planes + if(IR(dir[i])) MaxT[i] = (max[i] - origin[i]) / dir[i]; + } + } + + // Ray origin inside bounding box + if(Inside) + { + coord = origin; + return true; + } + + // Get largest of the maxT's for final choice of intersection + udword WhichPlane = 0; + if(MaxT[1] > MaxT[WhichPlane]) WhichPlane = 1; + if(MaxT[2] > MaxT[WhichPlane]) WhichPlane = 2; + + // Check final candidate actually inside box + if(IR(MaxT[WhichPlane])&0x80000000) return false; + + for(udword i=0;i<3;i++) + { + if(i!=WhichPlane) + { + coord[i] = origin[i] + MaxT[WhichPlane] * dir[i]; +#ifdef RAYAABB_EPSILON + if(coord[i] < min[i] - RAYAABB_EPSILON || coord[i] > max[i] + RAYAABB_EPSILON) return false; +#else + if(coord[i] < min[i] || coord[i] > max[i]) return false; +#endif + } + } + return true; // ray hits box +} + +static const bool gNormalize = true; + +udword /*Ctc::*/RayCapsuleOverlap(const Point& origin, const Point& dir, const LSS& capsule, float s[2]) +{ + // set up quadratic Q(t) = a*t^2 + 2*b*t + c + Point kU, kV, kW, capsDir; + capsule.ComputeDirection(capsDir); + kW = capsDir; + + float fWLength = kW.Magnitude(); + kW.Normalize(); + + // generate orthonormal basis + + float fInvLength; + if ( fabsf(kW.x) >= fabsf(kW.y) ) + { + // W.x or W.z is the largest magnitude component, swap them + fInvLength = 1.0f/sqrtf(kW.x*kW.x + kW.z*kW.z); + kU.x = -kW.z*fInvLength; + kU.y = 0.0f; + kU.z = +kW.x*fInvLength; + } + else + { + // W.y or W.z is the largest magnitude component, swap them + fInvLength = 1.0f/sqrtf(kW.y*kW.y + kW.z*kW.z); + kU.x = 0.0f; + kU.y = +kW.z*fInvLength; + kU.z = -kW.y*fInvLength; + } + kV = kW^kU; +kU.Normalize(); + if(gNormalize) + kV.Normalize(); + + // compute intersection + + Point kD(kU|dir, kV|dir, kW|dir); + float fDLength = kD.Magnitude(); + kD.Normalize(); + + float fInvDLength = 1.0f/fDLength; + Point kDiff = origin - capsule.mP0; + Point kP(kU|kDiff, kV|kDiff, kW|kDiff); + float fRadiusSqr = capsule.mRadius*capsule.mRadius; + + float fInv, fA, fB, fC, fDiscr, fRoot, fT, fTmp; + + // Is the velocity parallel to the capsule direction? (or zero) + if ( fabsf(kD.z) >= 1.0f - FLT_EPSILON || fDLength < FLT_EPSILON ) + { + + float fAxisDir = dir|capsDir; + + fDiscr = fRadiusSqr - kP.x*kP.x - kP.y*kP.y; + if ( fAxisDir < 0 && fDiscr >= 0.0f ) + { + // Velocity anti-parallel to the capsule direction + fRoot = sqrtf(fDiscr); + s[0] = (kP.z + fRoot)*fInvDLength; + s[1] = -(fWLength - kP.z + fRoot)*fInvDLength; + return 2; + } + else if ( fAxisDir > 0 && fDiscr >= 0.0f ) + { + // Velocity parallel to the capsule direction + fRoot = sqrtf(fDiscr); + s[0] = -(kP.z + fRoot)*fInvDLength; + s[1] = (fWLength - kP.z + fRoot)*fInvDLength; + return 2; + } + else + { + // sphere heading wrong direction, or no velocity at all + return 0; + } + } + + // test intersection with infinite cylinder + fA = kD.x*kD.x + kD.y*kD.y; + fB = kP.x*kD.x + kP.y*kD.y; + fC = kP.x*kP.x + kP.y*kP.y - fRadiusSqr; + fDiscr = fB*fB - fA*fC; + if ( fDiscr < 0.0f ) + { + // line does not intersect infinite cylinder + return 0; + } + + int iQuantity = 0; + + if ( fDiscr > 0.0f ) + { + // line intersects infinite cylinder in two places + fRoot = sqrtf(fDiscr); + fInv = 1.0f/fA; + fT = (-fB - fRoot)*fInv; + fTmp = kP.z + fT*kD.z; + if ( 0.0f <= fTmp && fTmp <= fWLength ) + s[iQuantity++] = fT*fInvDLength; + + fT = (-fB + fRoot)*fInv; + fTmp = kP.z + fT*kD.z; + if ( 0.0f <= fTmp && fTmp <= fWLength ) + s[iQuantity++] = fT*fInvDLength; + + if ( iQuantity == 2 ) + { + // line intersects capsule wall in two places + return 2; + } + } + else + { + // line is tangent to infinite cylinder + fT = -fB/fA; + fTmp = kP.z + fT*kD.z; + if ( 0.0f <= fTmp && fTmp <= fWLength ) + { + s[0] = fT*fInvDLength; + return 1; + } + } + + // test intersection with bottom hemisphere + // fA = 1 + fB += kP.z*kD.z; + fC += kP.z*kP.z; + fDiscr = fB*fB - fC; + if ( fDiscr > 0.0f ) + { + fRoot = sqrtf(fDiscr); + fT = -fB - fRoot; + fTmp = kP.z + fT*kD.z; + if ( fTmp <= 0.0f ) + { + s[iQuantity++] = fT*fInvDLength; + if ( iQuantity == 2 ) + return 2; + } + + fT = -fB + fRoot; + fTmp = kP.z + fT*kD.z; + if ( fTmp <= 0.0f ) + { + s[iQuantity++] = fT*fInvDLength; + if ( iQuantity == 2 ) + return 2; + } + } + else if ( fDiscr == 0.0f ) + { + fT = -fB; + fTmp = kP.z + fT*kD.z; + if ( fTmp <= 0.0f ) + { + s[iQuantity++] = fT*fInvDLength; + if ( iQuantity == 2 ) + return 2; + } + } + + // test intersection with top hemisphere + // fA = 1 + fB -= kD.z*fWLength; + fC += fWLength*(fWLength - 2.0f*kP.z); + + fDiscr = fB*fB - fC; + if ( fDiscr > 0.0f ) + { + fRoot = sqrtf(fDiscr); + fT = -fB - fRoot; + fTmp = kP.z + fT*kD.z; + if ( fTmp >= fWLength ) + { + s[iQuantity++] = fT*fInvDLength; + if ( iQuantity == 2 ) + return 2; + } + + fT = -fB + fRoot; + fTmp = kP.z + fT*kD.z; + if ( fTmp >= fWLength ) + { + s[iQuantity++] = fT*fInvDLength; + if ( iQuantity == 2 ) + return 2; + } + } + else if ( fDiscr == 0.0f ) + { + fT = -fB; + fTmp = kP.z + fT*kD.z; + if ( fTmp >= fWLength ) + { + s[iQuantity++] = fT*fInvDLength; + if ( iQuantity == 2 ) + return 2; + } + } + + return iQuantity; +} + diff --git a/Extras/CDTestFramework/IceHelpers.h b/Extras/CDTestFramework/IceHelpers.h new file mode 100644 index 0000000..0d260d5 --- /dev/null +++ b/Extras/CDTestFramework/IceHelpers.h @@ -0,0 +1,41 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 ICEHELPERS_H +#define ICEHELPERS_H + + void RotX(Matrix3x3& m, float angle); + void RotY(Matrix3x3& m, float angle); + void RotZ(Matrix3x3& m, float angle); + + udword RayCapsuleOverlap(const Point& origin, const Point& dir, const LSS& capsule, float s[2]); + bool SegmentSphere(const Point& origin, const Point& dir, float length, const Point& center, float radius, float& dist, Point& hit_pos); + bool RayAABB2(const Point& min, const Point& max, const Point& origin, const Point& dir, Point& coord); + + inline_ bool RayOBB(const Point& origin, const Point& dir, const OBB& box, float& dist, Point& hit_pos) + { + Point LocalOrigin = box.mRot * (origin - box.mCenter); + Point LocalDir = box.mRot * dir; + + Point LocalImpact; + if(RayAABB2(-box.mExtents, box.mExtents, LocalOrigin, LocalDir, LocalImpact)) + { + dist = LocalImpact.Distance(LocalOrigin); + hit_pos = LocalImpact * box.mRot + box.mCenter; + return true; + } + return false; + } + +#endif // ICEHELPERS_H diff --git a/Extras/CDTestFramework/License.txt b/Extras/CDTestFramework/License.txt new file mode 100644 index 0000000..290add7 --- /dev/null +++ b/Extras/CDTestFramework/License.txt @@ -0,0 +1,49 @@ + +//////////////////////////////////////////////////////////////////////////////////////////////// +//CDTestFramework re-distributed under the ZLib license with permission of Pierre Terdiman +//////////////////////////////////////////////////////////////////////////////////////////////// + +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +//////////////////////////////////////////////////////////////////////////////////////////////// +DbvtTest.* and btDbvt.* are distributed under the ZLIb license, Copyright Nathanael Presson +//////////////////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////////////////// +BulletSAPCompleteBoxPruningTest.* distributed under the ZLib license, Copyright Erwin Coumans +//////////////////////////////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////////////////////////////// +//ICE and OPCODE 1.3 re-distributed under the ZLib license with permission of Pierre Terdiman +//////////////////////////////////////////////////////////////////////////////////////////////// + +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ \ No newline at end of file diff --git a/Extras/CDTestFramework/License.txt.bak b/Extras/CDTestFramework/License.txt.bak new file mode 100644 index 0000000..e69de29 diff --git a/Extras/CDTestFramework/OBBMeshQuery.cpp b/Extras/CDTestFramework/OBBMeshQuery.cpp new file mode 100644 index 0000000..2bf7371 --- /dev/null +++ b/Extras/CDTestFramework/OBBMeshQuery.cpp @@ -0,0 +1,157 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 "stdafx.h" +#include "OBBMeshQuery.h" +#include "Terrain.h" +#include "IceHelpers.h" +#include "RenderingHelpers.h" +#include "Camera.h" +#include "GLFontRenderer.h" + +OBBMeshQuery::OBBMeshQuery() : + mBar (null), + mAngleX (0.0f), + mAngleY (0.0f), + mAngleZ (0.0f), + mDist (0.0f), + mValidHit (false) +{ +} + +OBBMeshQuery::~OBBMeshQuery() +{ +} + +void OBBMeshQuery::Init() +{ + mBox.mCenter = Point(0.0f, 0.0f, 0.0f); + mBox.mExtents = Point(1.0f, 1.0f, 1.0f); + mBox.mRot.Identity(); +} + +void OBBMeshQuery::Release() +{ + Deselect(); +} + +void OBBMeshQuery::Select() +{ + // Create a tweak bar + { + mBar = TwNewBar("OBBMeshQuery"); + TwAddVarRW(mBar, "Extents.x", TW_TYPE_FLOAT, &mBox.mExtents.x, " min=0.01 max=200.0 step=0.05 group='Extents' "); + TwAddVarRW(mBar, "Extents.y", TW_TYPE_FLOAT, &mBox.mExtents.y, " min=0.01 max=200.0 step=0.05 group='Extents' "); + TwAddVarRW(mBar, "Extents.z", TW_TYPE_FLOAT, &mBox.mExtents.z, " min=0.01 max=200.0 step=0.05 group='Extents' "); + TwAddVarRW(mBar, "Rot.x", TW_TYPE_FLOAT, &mAngleX, " min=0.0 max=6.28 step=0.01 group='Rotation' "); + TwAddVarRW(mBar, "Rot.y", TW_TYPE_FLOAT, &mAngleY, " min=0.0 max=6.28 step=0.01 group='Rotation' "); + TwAddVarRW(mBar, "Rot.z", TW_TYPE_FLOAT, &mAngleZ, " min=0.0 max=6.28 step=0.01 group='Rotation' "); + + mSettings.AddToTweakBar(mBar); + +// mProfiler.AddToTweakBar(mBar); + } +} + +void OBBMeshQuery::Deselect() +{ + if(mBar) + { + TwDeleteBar(mBar); + mBar = null; + } +} + +void OBBMeshQuery::PerformTest() +{ + RenderTerrain(); + + Matrix3x3 MX,MY,MZ; + RotX(MX, mAngleX); + RotY(MY, mAngleY); + RotY(MZ, mAngleZ); + mBox.mRot = MX * MY * MZ; + + DrawOBB(mBox); + + const Model* TM = GetTerrainModel(); + if(TM) + { + OBBCollider Collider; + mSettings.SetupCollider(Collider); + + mProfiler.Start(); + bool Status = Collider.Collide(mCache, mBox, *TM, null, null); + mProfiler.End(); + mProfiler.Accum(); + + if(Status) + { + if(Collider.GetContactStatus()) + { + udword NbTris = Collider.GetNbTouchedPrimitives(); + const udword* Indices = Collider.GetTouchedPrimitives(); + + RenderTerrainTriangles(NbTris, Indices); + } + } + } + + // Raycast hit + if(mValidHit) + { + Point wp = mLocalHit + mBox.mCenter; + DrawLine(wp, wp + Point(1.0f, 0.0f, 0.0f), Point(1,0,0), 1.0f); + DrawLine(wp, wp + Point(0.0f, 1.0f, 0.0f), Point(0,1,0), 1.0f); + DrawLine(wp, wp + Point(0.0f, 0.0f, 1.0f), Point(0,0,1), 1.0f); + } + + char Buffer[4096]; + sprintf(Buffer, "OBB-mesh query = %5.1f us (%d cycles)\n", mProfiler.mMsTime, mProfiler.mCycles); + GLFontRenderer::print(10.0f, 10.0f, 0.02f, Buffer); +} + +void OBBMeshQuery::KeyboardCallback(unsigned char key, int x, int y) +{ +} + +void OBBMeshQuery::MouseCallback(int button, int state, int x, int y) +{ + mValidHit = false; + if(!button && !state) + { + Point Dir = ComputeWorldRay(x, y); + + float d; + Point hit; + if(RayOBB(GetCameraPos(), Dir, mBox, d, hit)) + { + mValidHit = true; + mDist = d; + mLocalHit = hit - mBox.mCenter; + } + } +} + +void OBBMeshQuery::MotionCallback(int x, int y) +{ + if(mValidHit) + { + Point Dir = ComputeWorldRay(x, y); + mBox.mCenter = GetCameraPos() + Dir*mDist - mLocalHit; + } +} + + diff --git a/Extras/CDTestFramework/OBBMeshQuery.h b/Extras/CDTestFramework/OBBMeshQuery.h new file mode 100644 index 0000000..e274691 --- /dev/null +++ b/Extras/CDTestFramework/OBBMeshQuery.h @@ -0,0 +1,53 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 OBBMESHQUERY_H +#define OBBMESHQUERY_H + +#include "CollisionTest.h" +#include "Profiling.h" + + class OBBMeshQuery : public CollisionTest + { + public: + OBBMeshQuery(); + virtual ~OBBMeshQuery(); + + virtual void Init(); + virtual void Release(); + virtual void PerformTest(); + virtual void Select(); + virtual void Deselect(); + virtual void KeyboardCallback(unsigned char key, int x, int y); + virtual void MouseCallback(int button, int state, int x, int y); + virtual void MotionCallback(int x, int y); + + TwBar* mBar; //!< AntTweakBar + OBB mBox; + + float mAngleX; + float mAngleY; + float mAngleZ; + + OBBCache mCache; + OpcodeSettings mSettings; + Profiler mProfiler; + + float mDist; + Point mLocalHit; + bool mValidHit; + }; + +#endif // OBBMESHQUERY_H diff --git a/Extras/CDTestFramework/Opcode/Ice/IceAABB.cpp b/Extras/CDTestFramework/Opcode/Ice/IceAABB.cpp new file mode 100644 index 0000000..7ea20f2 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceAABB.cpp @@ -0,0 +1,422 @@ +/* + * ICE OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains AABB-related code. + * \file IceAABB.cpp + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * AABB class. + * \class AABB + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the sum of two AABBs. + * \param aabb [in] the other AABB + * \return Self-Reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABB& AABB::Add(const AABB& aabb) +{ + // Compute new min & max values + Point Min; GetMin(Min); + Point Tmp; aabb.GetMin(Tmp); + Min.Min(Tmp); + + Point Max; GetMax(Max); + aabb.GetMax(Tmp); + Max.Max(Tmp); + + // Update this + SetMinMax(Min, Max); + return *this; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Makes a cube from the AABB. + * \param cube [out] the cube AABB + * \return cube edge length + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float AABB::MakeCube(AABB& cube) const +{ + Point Ext; GetExtents(Ext); + float Max = Ext.Max(); + + Point Cnt; GetCenter(Cnt); + cube.SetCenterExtents(Cnt, Point(Max, Max, Max)); + return Max; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Makes a sphere from the AABB. + * \param sphere [out] sphere containing the AABB + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABB::MakeSphere(Sphere& sphere) const +{ + GetExtents(sphere.mCenter); + sphere.mRadius = sphere.mCenter.Magnitude() * 1.00001f; // To make sure sphere::Contains(*this) succeeds + GetCenter(sphere.mCenter); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks a box is inside another box. + * \param box [in] the other AABB + * \return true if current box is inside input box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABB::IsInside(const AABB& box) const +{ + if(box.GetMin(0)>GetMin(0)) return false; + if(box.GetMin(1)>GetMin(1)) return false; + if(box.GetMin(2)>GetMin(2)) return false; + if(box.GetMax(0) max.x) ? 2 : 0) // 2 = right + + ((local_eye.y < min.y) ? 4 : 0) // 4 = bottom + + ((local_eye.y > max.y) ? 8 : 0) // 8 = top + + ((local_eye.z < min.z) ? 16 : 0) // 16 = front + + ((local_eye.z > max.z) ? 32 : 0); // 32 = back + + // Look up number of vertices in outline + num = (sdword)gIndexList[pos][7]; + // Zero indicates invalid case + if(!num) return null; + + return &gIndexList[pos][0]; +} + +// calculateBoxArea: computes the screen-projected 2D area of an oriented 3D bounding box + +//const Point& eye, //eye point (in bbox object coordinates) +//const AABB& box, //3d bbox +//const Matrix4x4& mat, //free transformation for bbox +//float width, float height, int& num) +float AABB::ComputeBoxArea(const Point& eye, const Matrix4x4& mat, float width, float height, sdword& num) const +{ + const sbyte* Outline = ComputeOutline(eye, num); + if(!Outline) return -1.0f; + + // Compute box vertices + Point vertexBox[8], dst[8]; + ComputePoints(vertexBox); + + // Transform all outline corners into 2D screen space + for(sdword i=0;i max.x) max.x = p.x; + if(p.x < min.x) min.x = p.x; + + if(p.y > max.y) max.y = p.y; + if(p.y < min.y) min.y = p.y; + + if(p.z > max.z) max.z = p.z; + if(p.z < min.z) min.z = p.z; + } + + // Forward declarations + class Sphere; + +//! Declarations of type-independent methods (most of them implemented in the .cpp) +#define AABB_COMMON_METHODS \ + AABB& Add(const AABB& aabb); \ + AABB& Sub(const AABB& aabb); \ + float MakeCube(AABB& cube) const; \ + void MakeSphere(Sphere& sphere) const; \ + const sbyte* ComputeOutline(const Point& local_eye, sdword& num) const; \ + float ComputeBoxArea(const Point& eye, const Matrix4x4& mat, float width, float height, sdword& num) const; \ + bool IsInside(const AABB& box) const; \ + bool ComputePlanes(Plane* planes) const; \ + bool ComputePoints(Point* pts) const; \ + const Point* GetVertexNormals() const; \ + const udword* GetEdges() const; \ + const Point* GetEdgeNormals() const; \ + inline_ BOOL ContainsPoint(const Point& p) const \ + { \ + if(p.x > GetMax(0) || p.x < GetMin(0)) return FALSE; \ + if(p.y > GetMax(1) || p.y < GetMin(1)) return FALSE; \ + if(p.z > GetMax(2) || p.z < GetMin(2)) return FALSE; \ + return TRUE; \ + } + + enum AABBType + { + AABB_RENDER = 0, //!< AABB used for rendering. Not visible == not rendered. + AABB_UPDATE = 1, //!< AABB used for dynamic updates. Not visible == not updated. + + AABB_FORCE_DWORD = 0x7fffffff, + }; + +#ifdef USE_MINMAX + + struct ICEMATHS_API ShadowAABB + { + Point mMin; + Point mMax; + }; + + class ICEMATHS_API AABB : public Allocateable + { + public: + //! Constructor + inline_ AABB() {} + //! Destructor + inline_ ~AABB() {} + + //! Type-independent methods + AABB_COMMON_METHODS; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from min & max vectors. + * \param min [in] the min point + * \param max [in] the max point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetMinMax(const Point& min, const Point& max) { mMin = min; mMax = max; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from center & extents vectors. + * \param c [in] the center point + * \param e [in] the extents vector + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetCenterExtents(const Point& c, const Point& e) { mMin = c - e; mMax = c + e; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an empty AABB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetEmpty() { Point p(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); mMin = -p; mMax = p;} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups a point AABB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetPoint(const Point& pt) { mMin = mMax = pt; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the size of the AABB. The size is defined as the longest extent. + * \return the size of the AABB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + float GetSize() const { Point e; GetExtents(e); return e.Max(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Extends the AABB. + * \param p [in] the next point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void Extend(const Point& p) { ComputeMinMax(p, mMin, mMax); } + + // Data access + + //! Get min point of the box + inline_ void GetMin(Point& min) const { min = mMin; } + //! Get max point of the box + inline_ void GetMax(Point& max) const { max = mMax; } + + //! Get component of the box's min point along a given axis + inline_ float GetMin(udword axis) const { return mMin[axis]; } + //! Get component of the box's max point along a given axis + inline_ float GetMax(udword axis) const { return mMax[axis]; } + + //! Get box center + inline_ void GetCenter(Point& center) const { center = (mMax + mMin)*0.5f; } + //! Get box extents + inline_ void GetExtents(Point& extents) const { extents = (mMax - mMin)*0.5f; } + + //! Get component of the box's center along a given axis + inline_ float GetCenter(udword axis) const { return (mMax[axis] + mMin[axis])*0.5f; } + //! Get component of the box's extents along a given axis + inline_ float GetExtents(udword axis) const { return (mMax[axis] - mMin[axis])*0.5f; } + + //! Get box diagonal + inline_ void GetDiagonal(Point& diagonal) const { diagonal = mMax - mMin; } + inline_ float GetWidth() const { return mMax.x - mMin.x; } + inline_ float GetHeight() const { return mMax.y - mMin.y; } + inline_ float GetDepth() const { return mMax.z - mMin.z; } + + //! Volume + inline_ float GetVolume() const { return GetWidth() * GetHeight() * GetDepth(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the intersection between two AABBs. + * \param a [in] the other AABB + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Intersect(const AABB& a) const + { + if(mMax.x < a.mMin.x + || a.mMax.x < mMin.x + || mMax.y < a.mMin.y + || a.mMax.y < mMin.y + || mMax.z < a.mMin.z + || a.mMax.z < mMin.z) return FALSE; + + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the 1D-intersection between two AABBs, on a given axis. + * \param a [in] the other AABB + * \param axis [in] the axis (0, 1, 2) + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Intersect(const AABB& a, udword axis) const + { + if(mMax[axis] < a.mMin[axis] || a.mMax[axis] < mMin[axis]) return FALSE; + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Recomputes the AABB after an arbitrary transform by a 4x4 matrix. + * Original code by Charles Bloom on the GD-Algorithm list. (I slightly modified it) + * \param mtx [in] the transform matrix + * \param aabb [out] the transformed AABB [can be *this] + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const + { + // The three edges transformed: you can efficiently transform an X-only vector + // by just getting the "X" column of the matrix + Point vx,vy,vz; + mtx.GetRow(0, vx); vx *= (mMax.x - mMin.x); + mtx.GetRow(1, vy); vy *= (mMax.y - mMin.y); + mtx.GetRow(2, vz); vz *= (mMax.z - mMin.z); + + // Transform the min point + aabb.mMin = aabb.mMax = mMin * mtx; + + // Take the transformed min & axes and find new extents + // Using CPU code in the right place is faster... + if(IS_NEGATIVE_FLOAT(vx.x)) aabb.mMin.x += vx.x; else aabb.mMax.x += vx.x; + if(IS_NEGATIVE_FLOAT(vx.y)) aabb.mMin.y += vx.y; else aabb.mMax.y += vx.y; + if(IS_NEGATIVE_FLOAT(vx.z)) aabb.mMin.z += vx.z; else aabb.mMax.z += vx.z; + if(IS_NEGATIVE_FLOAT(vy.x)) aabb.mMin.x += vy.x; else aabb.mMax.x += vy.x; + if(IS_NEGATIVE_FLOAT(vy.y)) aabb.mMin.y += vy.y; else aabb.mMax.y += vy.y; + if(IS_NEGATIVE_FLOAT(vy.z)) aabb.mMin.z += vy.z; else aabb.mMax.z += vy.z; + if(IS_NEGATIVE_FLOAT(vz.x)) aabb.mMin.x += vz.x; else aabb.mMax.x += vz.x; + if(IS_NEGATIVE_FLOAT(vz.y)) aabb.mMin.y += vz.y; else aabb.mMax.y += vz.y; + if(IS_NEGATIVE_FLOAT(vz.z)) aabb.mMin.z += vz.z; else aabb.mMax.z += vz.z; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the AABB is valid. + * \return true if the box is valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsValid() const + { + // Consistency condition for (Min, Max) boxes: min < max + if(mMin.x > mMax.x) return FALSE; + if(mMin.y > mMax.y) return FALSE; + if(mMin.z > mMax.z) return FALSE; + return TRUE; + } + + //! Operator for AABB *= float. Scales the extents, keeps same center. + inline_ AABB& operator*=(float s) + { + Point Center; GetCenter(Center); + Point Extents; GetExtents(Extents); + SetCenterExtents(Center, Extents * s); + return *this; + } + + //! Operator for AABB /= float. Scales the extents, keeps same center. + inline_ AABB& operator/=(float s) + { + Point Center; GetCenter(Center); + Point Extents; GetExtents(Extents); + SetCenterExtents(Center, Extents / s); + return *this; + } + + //! Operator for AABB += Point. Translates the box. + inline_ AABB& operator+=(const Point& trans) + { + mMin+=trans; + mMax+=trans; + return *this; + } + private: + Point mMin; //!< Min point + Point mMax; //!< Max point + }; + +#else + + class ICEMATHS_API AABB + { + public: + //! Constructor + inline_ AABB() {} + //! Destructor + inline_ ~AABB() {} + + //! Type-independent methods + AABB_COMMON_METHODS; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from min & max vectors. + * \param min [in] the min point + * \param max [in] the max point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetMinMax(const Point& min, const Point& max) { mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from center & extents vectors. + * \param c [in] the center point + * \param e [in] the extents vector + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetCenterExtents(const Point& c, const Point& e) { mCenter = c; mExtents = e; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an empty AABB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetEmpty() { mCenter.Zero(); mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups a point AABB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetPoint(const Point& pt) { mCenter = pt; mExtents.Zero(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the size of the AABB. The size is defined as the longest extent. + * \return the size of the AABB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + float GetSize() const { return mExtents.Max(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Extends the AABB. + * \param p [in] the next point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Extend(const Point& p) + { + Point Max = mCenter + mExtents; + Point Min = mCenter - mExtents; + + if(p.x > Max.x) Max.x = p.x; + if(p.x < Min.x) Min.x = p.x; + + if(p.y > Max.y) Max.y = p.y; + if(p.y < Min.y) Min.y = p.y; + + if(p.z > Max.z) Max.z = p.z; + if(p.z < Min.z) Min.z = p.z; + + SetMinMax(Min, Max); + } + // Data access + + //! Get min point of the box + inline_ void GetMin(Point& min) const { min = mCenter - mExtents; } + //! Get max point of the box + inline_ void GetMax(Point& max) const { max = mCenter + mExtents; } + + //! Get component of the box's min point along a given axis + inline_ float GetMin(udword axis) const { return mCenter[axis] - mExtents[axis]; } + //! Get component of the box's max point along a given axis + inline_ float GetMax(udword axis) const { return mCenter[axis] + mExtents[axis]; } + + //! Get box center + inline_ void GetCenter(Point& center) const { center = mCenter; } + //! Get box extents + inline_ void GetExtents(Point& extents) const { extents = mExtents; } + + //! Get component of the box's center along a given axis + inline_ float GetCenter(udword axis) const { return mCenter[axis]; } + //! Get component of the box's extents along a given axis + inline_ float GetExtents(udword axis) const { return mExtents[axis]; } + + //! Get box diagonal + inline_ void GetDiagonal(Point& diagonal) const { diagonal = mExtents * 2.0f; } + inline_ float GetWidth() const { return mExtents.x * 2.0f; } + inline_ float GetHeight() const { return mExtents.y * 2.0f; } + inline_ float GetDepth() const { return mExtents.z * 2.0f; } + + //! Volume + inline_ float GetVolume() const { return mExtents.x * mExtents.y * mExtents.z * 8.0f; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the intersection between two AABBs. + * \param a [in] the other AABB + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Intersect(const AABB& a) const + { + float tx = mCenter.x - a.mCenter.x; float ex = a.mExtents.x + mExtents.x; if(AIR(tx) > IR(ex)) return FALSE; + float ty = mCenter.y - a.mCenter.y; float ey = a.mExtents.y + mExtents.y; if(AIR(ty) > IR(ey)) return FALSE; + float tz = mCenter.z - a.mCenter.z; float ez = a.mExtents.z + mExtents.z; if(AIR(tz) > IR(ez)) return FALSE; + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * The standard intersection method from Gamasutra. Just here to check its speed against the one above. + * \param a [in] the other AABB + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool GomezIntersect(const AABB& a) + { + Point T = mCenter - a.mCenter; // Vector from A to B + return ((fabsf(T.x) <= (a.mExtents.x + mExtents.x)) + && (fabsf(T.y) <= (a.mExtents.y + mExtents.y)) + && (fabsf(T.z) <= (a.mExtents.z + mExtents.z))); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the 1D-intersection between two AABBs, on a given axis. + * \param a [in] the other AABB + * \param axis [in] the axis (0, 1, 2) + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Intersect(const AABB& a, udword axis) const + { + float t = mCenter[axis] - a.mCenter[axis]; + float e = a.mExtents[axis] + mExtents[axis]; + if(AIR(t) > IR(e)) return FALSE; + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Recomputes the AABB after an arbitrary transform by a 4x4 matrix. + * \param mtx [in] the transform matrix + * \param aabb [out] the transformed AABB [can be *this] + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const + { + // Compute new center + aabb.mCenter = mCenter * mtx; + + // Compute new extents. FPU code & CPU code have been interleaved for improved performance. + Point Ex(mtx.m[0][0] * mExtents.x, mtx.m[0][1] * mExtents.x, mtx.m[0][2] * mExtents.x); + IR(Ex.x)&=0x7fffffff; IR(Ex.y)&=0x7fffffff; IR(Ex.z)&=0x7fffffff; + + Point Ey(mtx.m[1][0] * mExtents.y, mtx.m[1][1] * mExtents.y, mtx.m[1][2] * mExtents.y); + IR(Ey.x)&=0x7fffffff; IR(Ey.y)&=0x7fffffff; IR(Ey.z)&=0x7fffffff; + + Point Ez(mtx.m[2][0] * mExtents.z, mtx.m[2][1] * mExtents.z, mtx.m[2][2] * mExtents.z); + IR(Ez.x)&=0x7fffffff; IR(Ez.y)&=0x7fffffff; IR(Ez.z)&=0x7fffffff; + + aabb.mExtents.x = Ex.x + Ey.x + Ez.x; + aabb.mExtents.y = Ex.y + Ey.y + Ez.y; + aabb.mExtents.z = Ex.z + Ey.z + Ez.z; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the AABB is valid. + * \return true if the box is valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsValid() const + { + // Consistency condition for (Center, Extents) boxes: Extents >= 0 + if(IS_NEGATIVE_FLOAT(mExtents.x)) return FALSE; + if(IS_NEGATIVE_FLOAT(mExtents.y)) return FALSE; + if(IS_NEGATIVE_FLOAT(mExtents.z)) return FALSE; + return TRUE; + } + + //! Operator for AABB *= float. Scales the extents, keeps same center. + inline_ AABB& operator*=(float s) { mExtents*=s; return *this; } + + //! Operator for AABB /= float. Scales the extents, keeps same center. + inline_ AABB& operator/=(float s) { mExtents/=s; return *this; } + + //! Operator for AABB += Point. Translates the box. + inline_ AABB& operator+=(const Point& trans) + { + mCenter+=trans; + return *this; + } + private: + Point mCenter; //!< AABB Center + Point mExtents; //!< x, y and z extents + }; + +#endif + + //! Computes the AABB around a set of vertices + inline_ void ComputeAABB(AABB& aabb, const Point* list, udword nb_pts) + { + if(list) + { + Point Maxi(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); + Point Mini(MAX_FLOAT, MAX_FLOAT, MAX_FLOAT); + while(nb_pts--) + { +// _prefetch(list+1); // off by one ? + ComputeMinMax(*list++, Mini, Maxi); + } + aabb.SetMinMax(Mini, Maxi); + } + } + + //! Computes the AABB around a set of vertices after transform by a matrix + inline_ void ComputeAABB(AABB& aabb, const Point* list, udword nb_pts, const Matrix4x4& world) + { + if(list) + { + Point Maxi(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); + Point Mini(MAX_FLOAT, MAX_FLOAT, MAX_FLOAT); + while(nb_pts--) + { +// _prefetch(list+1); // off by one ? + ComputeMinMax((*list++)*world, Mini, Maxi); + } + aabb.SetMinMax(Mini, Maxi); + } + } + +#endif // ICEAABB_H diff --git a/Extras/CDTestFramework/Opcode/Ice/IceAllocator.cpp b/Extras/CDTestFramework/Opcode/Ice/IceAllocator.cpp new file mode 100644 index 0000000..2b8abe8 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceAllocator.cpp @@ -0,0 +1,805 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an allocator base class. + * \file IceAllocator.cpp + * \author Pierre Terdiman + * \date December, 19, 2003 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" +#include + +using namespace Opcode; + +//#define ZERO_OVERHEAD_RELEASE +#define NEW_CODE +// For some reason dmalloc seems a lot slower than the system malloc? +//#define USE_DMALLOC + +#ifdef USE_DMALLOC + #include "dmalloc.h" + #define LOCAL_MALLOC dlmalloc + #define LOCAL_FREE dlfree +#else + #define LOCAL_MALLOC ::malloc + #define LOCAL_FREE ::free +#endif + + +// WARNING: this makes allocations a lot slower. Only use when tracking memory leaks. +//#define ALLOC_STRINGS + +// ### doesn't seem that useful +//#define FAST_BUFFER_SIZE 256*1024 + +#define DEBUG_IDENTIFIER 0xBeefBabe +#define DEBUG_DEALLOCATED 0xDeadDead + +#ifdef ALLOC_STRINGS +static const char* AllocString(const char* str) +{ + if(!str) return null; + char* mem = (char*)LOCAL_MALLOC(strlen(str)+1); + strcpy(mem, str); + return mem; +} + +static void FreeString(const char* str) +{ + if(str) LOCAL_FREE((void*)str); +} + +#endif + + class DefaultAllocator : public Allocator + { + public: + DefaultAllocator(); + virtual ~DefaultAllocator(); + + void reset(); + + override(Allocator) void* malloc(size_t size, MemoryType type); + override(Allocator) void* mallocDebug(size_t size, const char* filename, udword line, const char* class_name, MemoryType type); + override(Allocator) void* realloc(void* memory, size_t size); + override(Allocator) void* shrink(void* memory, size_t size); + override(Allocator) void free(void* memory); + + void DumpCurrentMemoryState() const; + + void** mMemBlockList; + udword mMemBlockListSize; +#ifdef NEW_CODE + udword mFirstFree; +#else + udword mMemBlockFirstFree; +#endif + udword mMemBlockUsed; + + sdword mNbAllocatedBytes; + sdword mHighWaterMark; + sdword mTotalNbAllocs; + sdword mNbAllocs; + sdword mNbReallocs; +#ifdef FAST_BUFFER_SIZE + udword mNbFastBytes; + udword mFastBufferOffset; + ubyte* mFastBuffer; +#endif + }; + +#define MEMBLOCKSTART 64 + + struct DebugBlock + { + udword mCheckValue; +#ifdef FAST_BUFFER_SIZE + MemoryType mType; +#endif + udword mSize; + const char* mFilename; + udword mLine; + udword mSlotIndex; + const char* mClassName; + }; + +#ifndef FAST_BUFFER_SIZE + ICE_COMPILE_TIME_ASSERT(sizeof(DebugBlock)==24); // Prevents surprises..... +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +DefaultAllocator::DefaultAllocator() : mNbAllocatedBytes(0), mHighWaterMark(0), mTotalNbAllocs(0), mNbAllocs(0), mNbReallocs(0) +{ + mMemBlockList = null; + +#ifdef _DEBUG + // Initialize the Memory blocks list (DEBUG mode only) + mMemBlockList = (void**)LOCAL_MALLOC(MEMBLOCKSTART*sizeof(void*)); + ZeroMemory(mMemBlockList, MEMBLOCKSTART*sizeof(void*)); + mMemBlockListSize = MEMBLOCKSTART; +#ifdef NEW_CODE + mFirstFree = INVALID_ID; +#else + mMemBlockFirstFree = 0; +#endif + mMemBlockUsed = 0; +#endif + + +#ifdef FAST_BUFFER_SIZE + mNbFastBytes = 0; + mFastBufferOffset = 0; + mFastBuffer = (ubyte*)LOCAL_MALLOC(FAST_BUFFER_SIZE); +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +DefaultAllocator::~DefaultAllocator() +{ +#ifdef FAST_BUFFER_SIZE + mNbFastBytes = 0; + mFastBufferOffset = 0; + if(mFastBuffer) LOCAL_FREE(mFastBuffer); + mFastBuffer = null; +#endif + +#ifdef _DEBUG + + // Ok, it is a bad idea to use _F() here, because it internally uses the allocator (for the log string). So let's use good old C style here. + char Buffer[4096]; + + if(mNbAllocatedBytes) + { + sprintf(Buffer, "Memory leak detected: %d bytes non released\n", mNbAllocatedBytes); +// IceTrace(Buffer); +// IceTrace(_F("Memory leak detected: %d bytes non released\n", mNbAllocatedBytes)); + } + if(mNbAllocs) + { + sprintf(Buffer, "Remaining allocs: %d\n", mNbAllocs); +// IceTrace(Buffer); +// IceTrace(_F("Remaining allocs: %d\n", mNbAllocs)); + } +// IceTrace(_F("Nb alloc: %d\n", mTotalNbAllocs)); + sprintf(Buffer, "Total nb alloc: %d\n", mTotalNbAllocs); +// IceTrace(Buffer); + +// IceTrace(_F("Nb realloc: %d\n", mNbReallocs)); + sprintf(Buffer, "Nb realloc: %d\n", mNbReallocs); +// IceTrace(Buffer); + +// IceTrace(_F("High water mark: %d Kb\n", mHighWaterMark/1024)); + sprintf(Buffer, "High water mark: %d Kb\n", mHighWaterMark/1024); +// IceTrace(Buffer); + + // Scanning for memory leaks + if(mMemBlockList && mNbAllocs) + { + udword NbLeaks = 0; +// IceTrace("\n\n ICE Message Memory leaks detected :\n\n"); + +#ifdef NEW_CODE + for(udword i=0; imSize, DB->mClassName, DB->mFilename, DB->mLine)); + sprintf(Buffer, " Address 0x%.8X, %d bytes (%s), allocated in: %s(%d):\n\n", DB+1, DB->mSize, DB->mClassName, DB->mFilename, DB->mLine); +// IceTrace(Buffer); + + NbLeaks++; +// Free(cur+4); + } +#else + for(udword i=0, j=0; imSize, DB->mClassName, DB->mFilename, DB->mLine)); + sprintf(Buffer, " Address 0x%.8X, %d bytes (%s), allocated in: %s(%d):\n\n", DB+1, DB->mSize, DB->mClassName, DB->mFilename, DB->mLine); + IceTrace(Buffer); + + NbLeaks++; +// Free(cur+4); + } +#endif +// IceTrace(_F("\n Dump complete (%d leaks)\n\n", NbLeaks)); + sprintf(Buffer, "\n Dump complete (%d leaks)\n\n", NbLeaks); +// IceTrace(Buffer); + } + // Free the Memory Block list + if(mMemBlockList) LOCAL_FREE(mMemBlockList); + mMemBlockList = null; +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void DefaultAllocator::reset() +{ + mNbAllocatedBytes = 0; + mHighWaterMark = 0; + mNbAllocs = 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void* DefaultAllocator::malloc(udword size, MemoryType type) +{ +// return ::malloc(size); + +#ifdef _DEBUG + return mallocDebug(size, null, 0, "Undefined", type); +#endif + + if(!size) + { +#ifdef _DEBUG +// IceTrace("Warning: trying to allocate 0 bytes\n"); +#endif + return null; + } + + mTotalNbAllocs++; + mNbAllocs++; + + mNbAllocatedBytes+=size; + if(mNbAllocatedBytes>mHighWaterMark) mHighWaterMark = mNbAllocatedBytes; + +#ifdef ZERO_OVERHEAD_RELEASE + return LOCAL_MALLOC(size); +#else + void* ptr = (void*)LOCAL_MALLOC(size+8); + udword* blockStart = (udword*)ptr; + blockStart[0] = DEBUG_IDENTIFIER; + blockStart[1] = size; + return ((udword*)ptr)+2; +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void* DefaultAllocator::mallocDebug(size_t size, const char* filename, udword line, const char* class_name, MemoryType type) +{ +#ifdef _DEBUG + if(!size) + { +// IceTrace("Warning: trying to allocate 0 bytes\n"); + return null; + } + + // Catch improper use of alloc macro... + if(0 && class_name) + { + const char* c = class_name; + while(*c) + { + if(*c==']' || *c=='[') + { + int stop=0; + } + c++; + } + } + + // Make sure size is even + if(size&1) size++; + +#ifdef FAST_BUFFER_SIZE + // Allocate one debug block in front of each real allocation + void* ptr = null; + if(type==MEMORY_TEMP) + { + udword NeededSize = size + sizeof(DebugBlock); + if(mFastBufferOffset + NeededSize <= FAST_BUFFER_SIZE) + { + ptr = mFastBuffer + mFastBufferOffset; + mFastBufferOffset += NeededSize; + mNbFastBytes += NeededSize; + } + } + + if(!ptr) + { + ptr = (void*)LOCAL_MALLOC(size + sizeof(DebugBlock)); + type = MEMORY_PERSISTENT; + } +#else + // Allocate one debug block in front of each real allocation + void* ptr = (void*)LOCAL_MALLOC(size + sizeof(DebugBlock)); +#endif + ASSERT(IS_ALIGNED_2(udword(ptr))); + + // Fill debug block + DebugBlock* DB = (DebugBlock*)ptr; + DB->mCheckValue = DEBUG_IDENTIFIER; +#ifdef FAST_BUFFER_SIZE + DB->mType = type; +#endif + DB->mSize = size; + DB->mLine = line; + DB->mSlotIndex = INVALID_ID; +#ifdef ALLOC_STRINGS + DB->mFilename = AllocString(filename); + DB->mClassName = AllocString(class_name); +#else + DB->mFilename = filename; + DB->mClassName = class_name; +#endif + + // Update global stats + mTotalNbAllocs++; + mNbAllocs++; + mNbAllocatedBytes += size; + if(mNbAllocatedBytes>mHighWaterMark) + mHighWaterMark = mNbAllocatedBytes; + + // Insert the allocated block in the debug memory block list + if(mMemBlockList) + { +#ifdef NEW_CODE + if(mFirstFree!=INVALID_ID) + { + // Recycle old location + + udword NextFree = udword(mMemBlockList[mFirstFree]); + if(NextFree!=INVALID_ID) NextFree>>=1; + + mMemBlockList[mFirstFree] = ptr; + DB->mSlotIndex = mFirstFree; + + mFirstFree = NextFree; + } + else + { + if(mMemBlockUsed==mMemBlockListSize) + { + // Allocate a bigger block + void** tps = (void**)LOCAL_MALLOC((mMemBlockListSize+MEMBLOCKSTART)*sizeof(void*)); + // Copy already used part + CopyMemory(tps, mMemBlockList, mMemBlockListSize*sizeof(void*)); + // Initialize remaining part + void* Next = tps + mMemBlockListSize; + ZeroMemory(Next, MEMBLOCKSTART*sizeof(void*)); + + // Free previous memory, setup new pointer + LOCAL_FREE(mMemBlockList); + mMemBlockList = tps; + // Setup new size + mMemBlockListSize += MEMBLOCKSTART; + } + + mMemBlockList[mMemBlockUsed] = ptr; + DB->mSlotIndex = mMemBlockUsed++; + } +#else + // Store allocated pointer in first free slot + mMemBlockList[mMemBlockFirstFree] = ptr; + DB->mSlotIndex = mMemBlockFirstFree; + + // Count number of used slots + mMemBlockUsed++; + + // Resize if needed + if(mMemBlockUsed==mMemBlockListSize) + { + // Allocate a bigger block + void** tps = (void**)LOCAL_MALLOC((mMemBlockListSize+MEMBLOCKSTART)*sizeof(void*)); + // Copy already used part + CopyMemory(tps, mMemBlockList, mMemBlockListSize*sizeof(void*)); + // Initialize remaining part + void* Next = tps + mMemBlockListSize; + ZeroMemory(Next, MEMBLOCKSTART*sizeof(void*)); + + // Free previous memory, setup new pointer + LOCAL_FREE(mMemBlockList); + mMemBlockList = tps; + // -1 because we'll do a ++ just afterwards + mMemBlockFirstFree = mMemBlockListSize-1; + // Setup new size + mMemBlockListSize += MEMBLOCKSTART; + } + + // Look for first free ### recode this ugly thing + while(mMemBlockList[++mMemBlockFirstFree] && (mMemBlockFirstFreemCheckValue!=DEBUG_IDENTIFIER) + { + // Not a valid memory block + return null; + } + if(size>DB->mSize) + { + // New size should be smaller! + return null; + } + + // Try to shrink the block + void* Reduced = _expand(SystemPointer, size + sizeof(DebugBlock)); + if(!Reduced) return null; + + if(Reduced!=SystemPointer) + { + // Should not be possible?! + } + + // Update stats + mNbAllocatedBytes -= DB->mSize; + mNbAllocatedBytes += size; + // Setup new size + DB->mSize = size; + + return memory; // The pointer should not have changed! +#else + // Release codepath + udword* SystemPointer = ((udword*)memory)-2; + if(SystemPointer[0]!=DEBUG_IDENTIFIER) + { + // Not a valid memory block + return null; + } + if(size>SystemPointer[1]) + { + // New size should be smaller! + return null; + } + + // Try to shrink the block + void* Reduced = _expand(SystemPointer, size+8); + if(!Reduced) return null; + + if(Reduced!=SystemPointer) + { + // Should not be possible?! + } + + // Update stats + mNbAllocatedBytes -= SystemPointer[1]; + mNbAllocatedBytes += size; + // Setup new size + SystemPointer[1] = size; + + return memory; // The pointer should not have changed! +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void* DefaultAllocator::realloc(void* memory, udword size) +{ +// return ::realloc(memory, size); + + ASSERT(0); + return null; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void DefaultAllocator::free(void* memory) +{ + if(!memory) + { +#ifdef _DEBUG +// IceTrace("Warning: trying to free null pointer\n"); +#endif + return; + } + +#ifdef _DEBUG + DebugBlock* DB = ((DebugBlock*)memory)-1; + +// DebugBlock TmpDB = *DB; // Keep a local copy to have readable data when ::free() fails! + + // Check we allocated it + if(DB->mCheckValue!=DEBUG_IDENTIFIER) + { +// IceTrace("Error: free unknown memory!!\n"); + // ### should we really continue?? + return; + } + + // Update global stats + mNbAllocatedBytes -= DB->mSize; + mNbAllocs--; + +#ifdef NEW_CODE + // Remove the block from the Memory block list + if(mMemBlockList) + { + udword FreeSlot = DB->mSlotIndex; + ASSERT(mMemBlockList[FreeSlot]==DB); + + udword NextFree = mFirstFree; + if(NextFree!=INVALID_ID) + { + NextFree<<=1; + NextFree|=1; + } + + mMemBlockList[FreeSlot] = (void*)NextFree; + mFirstFree = FreeSlot; + } +#else + udword MemBlockFirstFree = DB->mSlotIndex; // The slot we are in + udword Line = DB->mLine; + const char* File = DB->mFilename; + + // Remove the block from the Memory block list + if(mMemBlockList) + { + ASSERT(mMemBlockList[MemBlockFirstFree]==DB); + mMemBlockList[MemBlockFirstFree] = null; + mMemBlockUsed--; + } +#endif + +#ifdef ALLOC_STRINGS + FreeString(DB->mClassName); + FreeString(DB->mFilename); +#endif + +#ifdef FAST_BUFFER_SIZE + if(DB->mType==MEMORY_TEMP) + { + mNbFastBytes -= DB->mSize + sizeof(DebugBlock); + if(mNbFastBytes==0) + { + mFastBufferOffset = 0; + } + return; + } +#endif + + // ### should be useless since we'll release the memory just afterwards + DB->mCheckValue = DEBUG_DEALLOCATED; + DB->mSize = 0; + DB->mClassName = null; + DB->mFilename = null; + DB->mSlotIndex = INVALID_ID; + DB->mLine = INVALID_ID; + + LOCAL_FREE(DB); +#else + // Release codepath + #ifdef ZERO_OVERHEAD_RELEASE + +// mNbAllocatedBytes -= ptr[1]; // ### use _msize() ? + mNbAllocs--; + LOCAL_FREE(memory); + + #else + + udword* ptr = ((udword*)memory)-2; + if(ptr[0]!=DEBUG_IDENTIFIER) + { + #ifdef _DEBUG + IceTrace("Error: free unknown memory!!\n"); + #endif + } + mNbAllocatedBytes -= ptr[1]; + if(mNbAllocatedBytes<0) + { + #ifdef _DEBUG + IceTrace(_F("Oops (%d)\n", ptr[1])); + #endif + } + mNbAllocs--; + ptr[0]=DEBUG_DEALLOCATED; + ptr[1]=0; + LOCAL_FREE(ptr); + + #endif +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +inline_ bool ValidAddress(const void* addy) +{ +#ifdef NEW_CODE + return (addy && !(udword(addy)&1)); +#else + return addy!=null; +#endif +} + +void DefaultAllocator::DumpCurrentMemoryState() const +{ +#ifdef _DEBUG + // Scanning for memory leaks + if(mMemBlockList && mMemBlockUsed) + { +// IceTrace("\n\n----ALLOCATOR MEMORY DUMP:\n\n"); + + // We can't just use the "const char*" stored in the debug blocks because they're not guaranteed to + // be unique for similar strings. For example if a Container is allocated from two different DLLs, + // the "Container" character string will be duplicated (one per DLL). So we need to group similar + // strings together using the actual characters, not just the string address. We also have to do this + // without allocating any new memory, since it would add new entries to the memory debug structure. + // + // The good news is that we don't care about speed too much in this function, since it's not supposed + // to be called all the time. + + struct Local + { + struct TmpStruct + { + const char* mName; + udword mSize; + }; + static int SortCB(const void* elem1, const void* elem2) + { + const TmpStruct* s1 = (const TmpStruct*)elem1; + const TmpStruct* s2 = (const TmpStruct*)elem2; + return strcmp(s1->mName, s2->mName); + } + }; + + Local::TmpStruct* SortedStrings = (Local::TmpStruct*)LOCAL_MALLOC(sizeof(Local::TmpStruct)*mMemBlockListSize); + udword NbStrings = 0; + udword TotalSize = 0; + for(udword i=0;imClassName) + { + SortedStrings[NbStrings].mName = DB->mClassName; // Memory by class +// SortedStrings[NbStrings].mName = DB->mFilename; // Memory by file + SortedStrings[NbStrings].mSize = DB->mSize; + TotalSize += DB->mSize; + NbStrings++; + } + } + } + qsort(SortedStrings, NbStrings, sizeof(Local::TmpStruct), Local::SortCB); + + // Strings are now sorted. They might still be duplicated, i.e. we may have two strings for the same + // class. So now we parse the list and collect used memory for all classes. Then we sort this again, + // to report results in order of increasing memory. + + udword NbClasses=0; + udword* Classes = (udword*)LOCAL_MALLOC(sizeof(udword)*NbStrings); + udword* Sizes = (udword*)LOCAL_MALLOC(sizeof(udword)*NbStrings); + + udword CurrentSize = SortedStrings[0].mSize; + const char* CurrentClass = SortedStrings[0].mName; + for(udword i=1;i<=NbStrings;i++) // One more time on purpose + { + const char* Current = null; + if(i!=NbStrings) + { + Current = SortedStrings[i].mName; + } + + if(Current && strcmp(Current, CurrentClass)==0) + { + // Same class + CurrentSize += SortedStrings[i].mSize; + } + else + { + // New class + + // Store previous class + if(CurrentClass) + { + Classes[NbClasses] = (udword)CurrentClass; // We can store this pointer now because it's unique in our new array + Sizes[NbClasses++] = CurrentSize; + } + + // Next one + if(Current) + { + CurrentClass = Current; + CurrentSize = SortedStrings[i].mSize; + } + } + } + + udword* Ranks0 = (udword*)LOCAL_MALLOC(sizeof(udword)*NbClasses); + udword* Ranks1 = (udword*)LOCAL_MALLOC(sizeof(udword)*NbClasses); + + StackRadixSort(RS, Ranks0, Ranks1); + const udword* Sorted = RS.Sort(Sizes, NbClasses).GetRanks(); + for(udword i=0;iDumpCurrentMemoryState(); +} + +void InitDefaultAllocator() +{ +// gDefault = ::new DefaultAllocator; +} + +void ReleaseDefaultAllocator() +{ +// if(gDefault) ::delete gDefault; +// gDefault = null; +} diff --git a/Extras/CDTestFramework/Opcode/Ice/IceAllocator.h b/Extras/CDTestFramework/Opcode/Ice/IceAllocator.h new file mode 100644 index 0000000..694d542 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceAllocator.h @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an allocator base class. + * \file IceAllocator.h + * \author Pierre Terdiman + * \date December, 19, 2003 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef ICEALLOCATOR_H +#define ICEALLOCATOR_H + + enum MemoryType + { + MEMORY_PERSISTENT, + MEMORY_TEMP, + }; + + class ICECORE_API Allocator + { + public: + virtual void* malloc(size_t size, MemoryType type) = 0; + virtual void* mallocDebug(size_t size, const char* filename, udword line, const char* class_name, MemoryType type) = 0; + virtual void* realloc(void* memory, size_t size) = 0; + virtual void* shrink(void* memory, size_t size) = 0; + virtual void free(void* memory) = 0; + }; + + FUNCTION ICECORE_API Allocator* GetAllocator(); + FUNCTION ICECORE_API bool SetAllocator(Allocator& allocator); + FUNCTION ICECORE_API void DumpMemory(); + + class ICECORE_API Allocateable + { + public: +#ifdef DONT_TRACK_MEMORY_LEAKS + inline_ void* operator new (size_t size, MemoryType type) { return GetAllocator()->malloc(size, type); } + inline_ void* operator new (size_t size, const char * filename, int line, const char* class_name, MemoryType type) { return GetAllocator()->mallocDebug(size, filename, line, class_name, type); } + inline_ void* operator new[] (size_t size, MemoryType type) { return GetAllocator()->malloc(size, type); } + inline_ void* operator new[] (size_t size, const char * filename, int line, const char* class_name, MemoryType type) { return GetAllocator()->mallocDebug(size, filename, line, class_name, type); } + inline_ void operator delete (void* p) { GetAllocator()->free(p); } + inline_ void operator delete (void* p, MemoryType) { GetAllocator()->free(p); } + inline_ void operator delete (void* p, const char*, int, const char*, MemoryType) { GetAllocator()->free(p); } + inline_ void operator delete[] (void* p) { GetAllocator()->free(p); } + inline_ void operator delete[] (void* p, MemoryType) { GetAllocator()->free(p); } + inline_ void operator delete[] (void* p, const char*, int, const char*, MemoryType) { GetAllocator()->free(p); } +#endif + }; + +#endif // ICEALLOCATOR_H diff --git a/Extras/CDTestFramework/Opcode/Ice/IceAssert.h b/Extras/CDTestFramework/Opcode/Ice/IceAssert.h new file mode 100644 index 0000000..386ec13 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceAssert.h @@ -0,0 +1,48 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains custom assertion code. + * \file IceAssert.h + * \author Pierre Terdiman + * \date January, 14, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef ICEASSERT_H +#define ICEASSERT_H + +// Leave the {} so that you can write this kind of things safely in release mode: +// if(condition) ASSERT() + +#ifndef ASSERT + #if defined( _DEBUG ) + FUNCTION ICECORE_API bool CustomAssertFunction(int, char*, int, char*, bool&); + + //! Custom ASSERT function. Various usages: + //! ASSERT(condition) + //! ASSERT(!"Not implemented") + //! ASSERT(condition && "error text") + #define ASSERT(exp) \ + { \ + static bool IgnoreAlways = false; \ + if(!IgnoreAlways) \ + { \ + if(CustomAssertFunction((int)(exp), #exp, __LINE__, __FILE__, IgnoreAlways)) \ + { \ + _asm { int 3 } \ + } \ + } \ + } + #else + #define ASSERT(exp) {} + #endif +#endif + +#ifndef assert + #define assert ASSERT +#endif + + #define ICE_COMPILE_TIME_ASSERT(exp) extern char ICE_Dummy[ (exp) ? 1 : -1 ] + +#endif // ICEASSERT_H diff --git a/Extras/CDTestFramework/Opcode/Ice/IceAxes.h b/Extras/CDTestFramework/Opcode/Ice/IceAxes.h new file mode 100644 index 0000000..37032dc --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceAxes.h @@ -0,0 +1,70 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains axes definition. + * \file IceAxes.h + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEAXES_H__ +#define __ICEAXES_H__ + + enum PointComponent + { + _X = 0, + _Y = 1, + _Z = 2, + _W = 3, + + _FORCE_DWORD = 0x7fffffff + }; + + enum AxisOrder + { + AXES_XYZ = (_X)|(_Y<<2)|(_Z<<4), + AXES_XZY = (_X)|(_Z<<2)|(_Y<<4), + AXES_YXZ = (_Y)|(_X<<2)|(_Z<<4), + AXES_YZX = (_Y)|(_Z<<2)|(_X<<4), + AXES_ZXY = (_Z)|(_X<<2)|(_Y<<4), + AXES_ZYX = (_Z)|(_Y<<2)|(_X<<4), + + AXES_FORCE_DWORD = 0x7fffffff + }; + + class ICEMATHS_API Axes + { + public: + + inline_ Axes(AxisOrder order) + { + mAxis0 = (order ) & 3; + mAxis1 = (order>>2) & 3; + mAxis2 = (order>>4) & 3; + } + inline_ ~Axes() {} + + udword mAxis0; + udword mAxis1; + udword mAxis2; + }; + +#endif // __ICEAXES_H__ diff --git a/Extras/CDTestFramework/Opcode/Ice/IceBitArray.cpp b/Extras/CDTestFramework/Opcode/Ice/IceBitArray.cpp new file mode 100644 index 0000000..1ec64c3 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceBitArray.cpp @@ -0,0 +1,73 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for bit arrays. + * \file IceBitArray.cpp + * \author Pierre Terdiman + * \date February, 5, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A simple array of bits stored as bytes. + * + * \class Container + * \author Pierre Terdiman + * \version 1.0 + * \date February, 5, 2000 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BitArray::BitArray() : mSize(0), mBits(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BitArray::BitArray(udword nb_bits) : mSize(0), mBits(null) +{ + Init(nb_bits); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BitArray::~BitArray() +{ + ICE_FREE(mBits); + mSize = 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes the bit array for a given number of entries + * \param nb_bits [in] max number of entries in the array + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool BitArray::Init(udword nb_bits) +{ + mSize = BitsToDwords(nb_bits); + // Get ram for n bits + ICE_FREE(mBits); + mBits = (udword*)ICE_ALLOC(sizeof(udword)*mSize); + // Set all bits to 0 + ClearAll(); + return true; +} diff --git a/Extras/CDTestFramework/Opcode/Ice/IceBitArray.h b/Extras/CDTestFramework/Opcode/Ice/IceBitArray.h new file mode 100644 index 0000000..60c60be --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceBitArray.h @@ -0,0 +1,82 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for bit arrays. + * \file IceBitArray.h + * \author Pierre Terdiman + * \date February, 5, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef ICEBITARRAY_H +#define ICEBITARRAY_H + + inline_ udword BitsToBytes(udword nb_bits) + { + return (nb_bits>>3) + ((nb_bits&7) ? 1 : 0); + } + + inline_ udword BitsToDwords(udword nb_bits) + { + return (nb_bits>>5) + ((nb_bits&31) ? 1 : 0); + } + + // Use that one instead of an array of bools. Takes less ram, nearly as fast [no bounds checkings and so on]. + class ICECORE_API BitArray + { + public: + //! Constructor + BitArray(); + BitArray(udword nb_bits); + //! Destructor + ~BitArray(); + + bool Init(udword nb_bits); + + // Data management + inline_ void SetBit(udword bit_number) { mBits[bit_number>>5] |= 1<<(bit_number&31); } + inline_ void ClearBit(udword bit_number) { mBits[bit_number>>5] &= ~(1<<(bit_number&31)); } + inline_ void ToggleBit(udword bit_number) { mBits[bit_number>>5] ^= 1<<(bit_number&31); } + + inline_ void ClearAll() { ZeroMemory(mBits, mSize*4); } + inline_ void SetAll() { FillMemory(mBits, mSize*4, 0xff); } + + // Data access + inline_ BOOL IsSet(udword bit_number) const { return mBits[bit_number>>5] & (1<<(bit_number&31)); } + + inline_ const udword* GetBits() const { return mBits; } + inline_ udword GetSize() const { return mSize; } + + protected: + udword* mBits; //!< Array of bits + udword mSize; //!< Size of the array in dwords + }; + + // - We consider square symmetric N*N matrices + // - A N*N symmetric matrix has N(N+1)/2 elements + // - A boolean version needs N(N+1)/16 bytes + // N NbBits NbBytes + // 4 10 - + // 8 36 4.5 + // 16 136 17 <= the one we select + // 32 528 66 + static ubyte BitMasks[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; + static ubyte NegBitMasks[] = { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F }; + class ICECORE_API BoolSquareSymmetricMatrix16 + { + public: + inline_ udword Index(udword x, udword y) const { if(x>y) Swap(x,y); return x + (y ? ((y-1)*y)>>1 : 0); } + + inline_ void Set(udword x, udword y) { udword i = Index(x, y); mBits[i>>3] |= BitMasks[i&7]; } + inline_ void Clear(udword x, udword y) { udword i = Index(x, y); mBits[i>>3] &= NegBitMasks[i&7]; } + inline_ void Toggle(udword x, udword y) { udword i = Index(x, y); mBits[i>>3] ^= BitMasks[i&7]; } + inline_ bool IsSet(udword x, udword y) const { udword i = Index(x, y); return (mBits[i>>3] & BitMasks[i&7])!=0; } + + inline_ void ClearAll() { ZeroMemory(mBits, 17); } + inline_ void SetAll() { FillMemory(mBits, 17, 0xff); } + + ubyte mBits[17]; + }; + +#endif // ICEBITARRAY_H diff --git a/Extras/CDTestFramework/Opcode/Ice/IceBoundingSphere.h b/Extras/CDTestFramework/Opcode/Ice/IceBoundingSphere.h new file mode 100644 index 0000000..053f007 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceBoundingSphere.h @@ -0,0 +1,158 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code to compute the minimal bounding sphere. + * \file IceBoundingSphere.h + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEBOUNDINGSPHERE_H__ +#define __ICEBOUNDINGSPHERE_H__ + + enum BSphereMethod + { + BS_NONE, + BS_GEMS, + BS_MINIBALL, + + BS_FORCE_DWORD = 0x7fffffff + }; + + class ICEMATHS_API Sphere + { + public: + //! Constructor + inline_ Sphere() {} + //! Constructor + inline_ Sphere(const Point& center, float radius) : mCenter(center), mRadius(radius) {} + //! Constructor + Sphere(udword nb_verts, const Point* verts); + //! Copy constructor + inline_ Sphere(const Sphere& sphere) : mCenter(sphere.mCenter), mRadius(sphere.mRadius) {} + //! Destructor + inline_ ~Sphere() {} + + BSphereMethod Compute(udword nb_verts, const Point* verts); + bool FastCompute(udword nb_verts, const Point* verts); + + // Access methods + inline_ const Point& GetCenter() const { return mCenter; } + inline_ float GetRadius() const { return mRadius; } + + inline_ const Point& Center() const { return mCenter; } + inline_ float Radius() const { return mRadius; } + + inline_ Sphere& Set(const Point& center, float radius) { mCenter = center; mRadius = radius; return *this; } + inline_ Sphere& SetCenter(const Point& center) { mCenter = center; return *this; } + inline_ Sphere& SetRadius(float radius) { mRadius = radius; return *this; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a point is contained within the sphere. + * \param p [in] the point to test + * \return true if inside the sphere + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Contains(const Point& p) const + { + return mCenter.SquareDistance(p) <= mRadius*mRadius; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a sphere is contained within the sphere. + * \param sphere [in] the sphere to test + * \return true if inside the sphere + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Contains(const Sphere& sphere) const + { + // If our radius is the smallest, we can't possibly contain the other sphere + if(mRadius < sphere.mRadius) return false; + // So r is always positive or null now + float r = mRadius - sphere.mRadius; + return mCenter.SquareDistance(sphere.mCenter) <= r*r; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a box is contained within the sphere. + * \param aabb [in] the box to test + * \return true if inside the sphere + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Contains(const AABB& aabb) const + { + // I assume if all 8 box vertices are inside the sphere, so does the whole box. + // Sounds ok but maybe there's a better way? + float R2 = mRadius * mRadius; +#ifdef USE_MIN_MAX + const Point& Max = ((ShadowAABB&)&aabb).mMax; + const Point& Min = ((ShadowAABB&)&aabb).mMin; +#else + Point Max; aabb.GetMax(Max); + Point Min; aabb.GetMin(Min); +#endif + Point p; + p.x=Max.x; p.y=Max.y; p.z=Max.z; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Max.x; p.y=Min.y; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Max.x; p.y=Max.y; p.z=Min.z; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Max.x; p.y=Min.y; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; + + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if the sphere intersects another sphere + * \param sphere [in] the other sphere + * \return true if spheres overlap + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Intersect(const Sphere& sphere) const + { + float r = mRadius + sphere.mRadius; + return mCenter.SquareDistance(sphere.mCenter) <= r*r; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the sphere is valid. + * \return true if the box is valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsValid() const + { + // Consistency condition for spheres: Radius >= 0.0f + if(mRadius < 0.0f) return FALSE; + return TRUE; + } + public: + Point mCenter; //!< Sphere center + float mRadius; //!< Sphere radius + }; + +#endif // __ICEBOUNDINGSPHERE_H__ diff --git a/Extras/CDTestFramework/Opcode/Ice/IceContainer.cpp b/Extras/CDTestFramework/Opcode/Ice/IceContainer.cpp new file mode 100644 index 0000000..2c3e9ac --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceContainer.cpp @@ -0,0 +1,423 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a simple container class. + * \file IceContainer.cpp + * \author Pierre Terdiman + * \date February, 5, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a list of 32-bits values. + * Use this class when you need to store an unknown number of values. The list is automatically + * resized and can contains 32-bits entities (dwords or floats) + * + * \class Container + * \author Pierre Terdiman + * \version 1.0 + * \date 08.15.98 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +// Static members +#ifdef CONTAINER_STATS +udword Container::mNbContainers = 0; +udword Container::mUsedRam = 0; +LinkedList Container::mContainers; +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. No entries allocated there. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container::Container() : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f) +{ +#ifdef CONTAINER_STATS + mNbContainers++; + mUsedRam+=sizeof(Container); + mContainers.AddElem(this); +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. Also allocates a given number of entries. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container::Container(udword size, float growth_factor) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null) +{ + SetGrowthFactor(growth_factor); +#ifdef CONTAINER_STATS + mNbContainers++; + mUsedRam+=sizeof(Container); + mContainers.AddElem(this); +#endif + SetSize(size); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Copy constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container::Container(const Container& object) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f) +{ +#ifdef CONTAINER_STATS + mNbContainers++; + mUsedRam+=sizeof(Container); + mContainers.AddElem(this); +#endif + *this = object; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. Frees everything and leaves. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container::~Container() +{ + Empty(); +#ifdef CONTAINER_STATS + mNbContainers--; + mUsedRam-=GetUsedRam(); + mContainers.RemElem(this); +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes the container so that it uses an external memory buffer. The container doesn't own the memory, resizing is disabled. + * \param max_entries [in] max number of entries in the container + * \param entries [in] external memory buffer + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Container::InitSharedBuffers(udword max_entries, udword* entries) +{ + Empty(); // Make sure everything has been released + mMaxNbEntries = max_entries; + mEntries = entries; + mGrowthFactor = -1.0f; // Negative growth ==> resize is disabled +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Clears the container. All stored values are deleted, and it frees used ram. + * \see Reset() + * \return Self-Reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container& Container::Empty() +{ +#ifdef CONTAINER_STATS + mUsedRam-=mMaxNbEntries*sizeof(udword); +#endif + if(mGrowthFactor>=0.0f) ICE_FREE(mEntries); // Release memory if we own it + mCurNbEntries = mMaxNbEntries = 0; + return *this; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Resizes the container. + * \param needed [in] assume the container can be added at least "needed" values + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Container::Resize(udword needed) +{ + // Check growth is allowed + if(mGrowthFactor<=0.0f) + { + ASSERT(!"Invalid operation - trying to resize a static buffer!"); + return false; + } + +#ifdef CONTAINER_STATS + // Subtract previous amount of bytes + mUsedRam-=mMaxNbEntries*sizeof(udword); +#endif + + // Get more entries + mMaxNbEntries = mMaxNbEntries ? udword(float(mMaxNbEntries)*mGrowthFactor) : 2; // Default nb Entries = 2 + if(mMaxNbEntriesshrink(mEntries, sizeof(udword)*mCurNbEntries)) + return false; + +#ifdef CONTAINER_STATS + // Subtract previous amount of bytes + mUsedRam-=mMaxNbEntries*sizeof(udword); +#endif + + // Get just enough entries + mMaxNbEntries = mCurNbEntries; + +#ifdef CONTAINER_STATS + // Add current amount of bytes + mUsedRam+=mMaxNbEntries*sizeof(udword); +#endif + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks whether the container already contains a given value. + * \param entry [in] the value to look for in the container + * \param location [out] a possible pointer to store the entry location + * \see Add(udword entry) + * \see Add(float entry) + * \see Empty() + * \return true if the value has been found in the container, else false. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Container::Contains(udword entry, udword* location) const +{ + // Look for the entry + for(udword i=0;imMaxNbEntries) Resize(nb); + + // Add new entry + CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(udword)); + mCurNbEntries += nb; + } + return *this; + } + + inline_ Container& Add(const Container& container) + { + return Add(container.GetEntries(), container.GetNbEntries()); + } + + inline_ udword* Reserve(udword nb) + { + // Resize if needed + if(mCurNbEntries+nb>mMaxNbEntries) Resize(nb); + + // We expect the user to fill reserved memory with 'nb' udwords + udword* Reserved = &mEntries[mCurNbEntries]; + + // Meanwhile, we do as if it had been filled + mCurNbEntries += nb; + + // This is mainly used to avoid the copy when possible + return Reserved; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * A O(1) method to add a value in the container. The container is automatically resized if needed. + * The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation + * costs a lot more than the call overhead... + * + * \param entry [in] a float to store in the container + * \see Add(udword entry) + * \see Empty() + * \see Contains(udword entry) + * \return Self-Reference + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ Container& Add(float entry) + { + // Resize if needed + if(mCurNbEntries==mMaxNbEntries) Resize(); + + // Add new entry + mEntries[mCurNbEntries++] = IR(entry); + return *this; + } + + inline_ Container& Add(const float* entries, udword nb) + { + // Resize if needed + if(mCurNbEntries+nb>mMaxNbEntries) Resize(nb); + + // Add new entry + CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(float)); + mCurNbEntries+=nb; + return *this; + } + + //! Add unique [slow] + inline_ Container& AddUnique(udword entry) + { + if(!Contains(entry)) Add(entry); + return *this; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Clears the container. All stored values are deleted, and it frees used ram. + * \see Reset() + * \return Self-Reference + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Container& Empty(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Resets the container. Stored values are discarded but the buffer is kept so that further calls don't need resizing again. + * That's a kind of temporal coherence. + * \see Empty() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void Reset() + { + // Avoid the write if possible + // ### CMOV + if(mCurNbEntries) mCurNbEntries = 0; + } + + // HANDLE WITH CARE - I hope you know what you're doing + inline_ void ForceSize(udword size) + { + mCurNbEntries = size; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Sets the initial size of the container. If it already contains something, it's discarded. + * \param nb [in] Number of entries + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool SetSize(udword nb); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Refits the container and get rid of unused bytes. + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Refit(); + + bool Shrink(); + + // Checks whether the container already contains a given value. + bool Contains(udword entry, udword* location=null) const; + // Deletes an entry - doesn't preserve insertion order. + bool Delete(udword entry); + // Deletes an entry - does preserve insertion order. + bool DeleteKeepingOrder(udword entry); + //! Deletes the very last entry. + inline_ void DeleteLastEntry() { if(mCurNbEntries) mCurNbEntries--; } + //! Deletes the entry whose index is given + inline_ void DeleteIndex(udword index) { mEntries[index] = mEntries[--mCurNbEntries]; } + + // Helpers + Container& FindNext(udword& entry, FindMode find_mode=FIND_CLAMP); + Container& FindPrev(udword& entry, FindMode find_mode=FIND_CLAMP); + // Data access. + inline_ udword GetNbEntries() const { return mCurNbEntries; } //!< Returns the current number of entries. + inline_ udword GetMaxNbEntries() const { return mMaxNbEntries; } //!< Returns max number of entries before resizing. + inline_ udword GetEntry(udword i) const { return mEntries[i]; } //!< Returns ith entry. + inline_ udword* GetEntries() const { return mEntries; } //!< Returns the list of entries. + + inline_ udword GetFirst() const { return mEntries[0]; } + inline_ udword GetLast() const { return mEntries[mCurNbEntries-1]; } + + // Growth control + float GetGrowthFactor() const; //!< Returns the growth factor + void SetGrowthFactor(float growth); //!< Sets the growth factor + inline_ bool IsFull() const { return mCurNbEntries==mMaxNbEntries; } //!< Checks the container is full + inline_ BOOL IsNotEmpty() const { return mCurNbEntries; } //!< Checks the container is empty + + //! Read-access as an array + inline_ udword operator[](udword i) const { ASSERT(i>=0 && i=0 && i>31); + return (float&)y; + } + + //! Computes 1.0f / sqrtf(x). + inline_ float frsqrt(float f) + { + float x = f * 0.5f; + udword y = 0x5f3759df - ((udword&)f >> 1); + // Iteration... + (float&)y = (float&)y * ( 1.5f - ( x * (float&)y * (float&)y ) ); + // Result + return (float&)y; + } + + //! Computes 1.0f / sqrtf(x). Comes from NVIDIA. + inline_ float InvSqrt(const float& x) + { + udword tmp = (udword(IEEE_1_0 << 1) + IEEE_1_0 - *(udword*)&x) >> 1; + float y = *(float*)&tmp; + return y * (1.47f - 0.47f * x * y * y); + } + + //! Computes 1.0f / sqrtf(x). Comes from Quake3. Looks like the first one I had above. + //! See http://www.magic-software.com/3DGEDInvSqrt.html + inline_ float RSqrt(float number) + { + long i; + float x2, y; + const float threehalfs = 1.5f; + + x2 = number * 0.5f; + y = number; + i = * (long *) &y; + i = 0x5f3759df - (i >> 1); + y = * (float *) &i; + y = y * (threehalfs - (x2 * y * y)); + + return y; + } + + //! TO BE DOCUMENTED + inline_ float fsqrt(float f) + { + udword y = ( ( (sdword&)f - 0x3f800000 ) >> 1 ) + 0x3f800000; + // Iteration...? + // (float&)y = (3.0f - ((float&)y * (float&)y) / f) * (float&)y * 0.5f; + // Result + return (float&)y; + } + + //! Returns the float ranged espilon value. + inline_ float fepsilon(float f) + { + udword b = (udword&)f & 0xff800000; + udword a = b | 0x00000001; + (float&)a -= (float&)b; + // Result + return (float&)a; + } + + //! Is the float valid ? + inline_ bool IsNAN(float value) { return (IR(value)&0x7f800000) == 0x7f800000; } + inline_ bool IsIndeterminate(float value) { return IR(value) == 0xffc00000; } + inline_ bool IsPlusInf(float value) { return IR(value) == 0x7f800000; } + inline_ bool IsMinusInf(float value) { return IR(value) == 0xff800000; } + + inline_ bool IsValidFloat(float value) + { + if(IsNAN(value)) return false; + if(IsIndeterminate(value)) return false; + if(IsPlusInf(value)) return false; + if(IsMinusInf(value)) return false; + return true; + } + + #define CHECK_VALID_FLOAT(x) ASSERT(IsValidFloat(x)); + +/* + //! FPU precision setting function. + inline_ void SetFPU() + { + // This function evaluates whether the floating-point + // control word is set to single precision/round to nearest/ + // exceptions disabled. If these conditions don't hold, the + // function changes the control word to set them and returns + // TRUE, putting the old control word value in the passback + // location pointed to by pwOldCW. + { + uword wTemp, wSave; + + __asm fstcw wSave + if (wSave & 0x300 || // Not single mode + 0x3f != (wSave & 0x3f) || // Exceptions enabled + wSave & 0xC00) // Not round to nearest mode + { + __asm + { + mov ax, wSave + and ax, not 300h ;; single mode + or ax, 3fh ;; disable all exceptions + and ax, not 0xC00 ;; round to nearest mode + mov wTemp, ax + fldcw wTemp + } + } + } + } +*/ + //! This function computes the slowest possible floating-point value (you can also directly use FLT_EPSILON) + inline_ float ComputeFloatEpsilon() + { + float f = 1.0f; + ((udword&)f)^=1; + return f - 1.0f; // You can check it's the same as FLT_EPSILON + } + + inline_ bool IsFloatZero(float x, float epsilon=1e-6f) + { + return x*x < epsilon; + } + + #define FCOMI_ST0 _asm _emit 0xdb _asm _emit 0xf0 + #define FCOMIP_ST0 _asm _emit 0xdf _asm _emit 0xf0 + #define FCMOVB_ST0 _asm _emit 0xda _asm _emit 0xc0 + #define FCMOVNB_ST0 _asm _emit 0xdb _asm _emit 0xc0 + + #define FCOMI_ST1 _asm _emit 0xdb _asm _emit 0xf1 + #define FCOMIP_ST1 _asm _emit 0xdf _asm _emit 0xf1 + #define FCMOVB_ST1 _asm _emit 0xda _asm _emit 0xc1 + #define FCMOVNB_ST1 _asm _emit 0xdb _asm _emit 0xc1 + + #define FCOMI_ST2 _asm _emit 0xdb _asm _emit 0xf2 + #define FCOMIP_ST2 _asm _emit 0xdf _asm _emit 0xf2 + #define FCMOVB_ST2 _asm _emit 0xda _asm _emit 0xc2 + #define FCMOVNB_ST2 _asm _emit 0xdb _asm _emit 0xc2 + + #define FCOMI_ST3 _asm _emit 0xdb _asm _emit 0xf3 + #define FCOMIP_ST3 _asm _emit 0xdf _asm _emit 0xf3 + #define FCMOVB_ST3 _asm _emit 0xda _asm _emit 0xc3 + #define FCMOVNB_ST3 _asm _emit 0xdb _asm _emit 0xc3 + + #define FCOMI_ST4 _asm _emit 0xdb _asm _emit 0xf4 + #define FCOMIP_ST4 _asm _emit 0xdf _asm _emit 0xf4 + #define FCMOVB_ST4 _asm _emit 0xda _asm _emit 0xc4 + #define FCMOVNB_ST4 _asm _emit 0xdb _asm _emit 0xc4 + + #define FCOMI_ST5 _asm _emit 0xdb _asm _emit 0xf5 + #define FCOMIP_ST5 _asm _emit 0xdf _asm _emit 0xf5 + #define FCMOVB_ST5 _asm _emit 0xda _asm _emit 0xc5 + #define FCMOVNB_ST5 _asm _emit 0xdb _asm _emit 0xc5 + + #define FCOMI_ST6 _asm _emit 0xdb _asm _emit 0xf6 + #define FCOMIP_ST6 _asm _emit 0xdf _asm _emit 0xf6 + #define FCMOVB_ST6 _asm _emit 0xda _asm _emit 0xc6 + #define FCMOVNB_ST6 _asm _emit 0xdb _asm _emit 0xc6 + + #define FCOMI_ST7 _asm _emit 0xdb _asm _emit 0xf7 + #define FCOMIP_ST7 _asm _emit 0xdf _asm _emit 0xf7 + #define FCMOVB_ST7 _asm _emit 0xda _asm _emit 0xc7 + #define FCMOVNB_ST7 _asm _emit 0xdb _asm _emit 0xc7 + + //! A global function to find MAX(a,b) using FCOMI/FCMOV + inline_ float FCMax2(float a, float b) + { + float Res; + _asm fld [a] + _asm fld [b] + FCOMI_ST1 + FCMOVB_ST1 + _asm fstp [Res] + _asm fcomp + return Res; + } + + //! A global function to find MIN(a,b) using FCOMI/FCMOV + inline_ float FCMin2(float a, float b) + { + float Res; + _asm fld [a] + _asm fld [b] + FCOMI_ST1 + FCMOVNB_ST1 + _asm fstp [Res] + _asm fcomp + return Res; + } + + //! A global function to find MAX(a,b,c) using FCOMI/FCMOV + inline_ float FCMax3(float a, float b, float c) + { + float Res; + _asm fld [a] + _asm fld [b] + _asm fld [c] + FCOMI_ST1 + FCMOVB_ST1 + FCOMI_ST2 + FCMOVB_ST2 + _asm fstp [Res] + _asm fcompp + return Res; + } + + //! A global function to find MIN(a,b,c) using FCOMI/FCMOV + inline_ float FCMin3(float a, float b, float c) + { + float Res; + _asm fld [a] + _asm fld [b] + _asm fld [c] + FCOMI_ST1 + FCMOVNB_ST1 + FCOMI_ST2 + FCMOVNB_ST2 + _asm fstp [Res] + _asm fcompp + return Res; + } + + //! A global function to find MAX(a,b,c,d) using FCOMI/FCMOV + inline_ float FCMax4(float a, float b, float c, float d) + { + float Res; + _asm fld [a] + _asm fld [b] + _asm fld [c] + _asm fld [d] + FCOMI_ST1 + FCMOVB_ST1 + FCOMI_ST2 + FCMOVB_ST2 + FCOMI_ST3 + FCMOVB_ST3 + _asm fstp [Res] + _asm fcompp + _asm fcomp + return Res; + } + + //! A global function to find MIN(a,b,c,d) using FCOMI/FCMOV + inline_ float FCMin4(float a, float b, float c, float d) + { + float Res; + _asm fld [a] + _asm fld [b] + _asm fld [c] + _asm fld [d] + FCOMI_ST1 + FCMOVNB_ST1 + FCOMI_ST2 + FCMOVNB_ST2 + FCOMI_ST3 + FCMOVNB_ST3 + _asm fstp [Res] + _asm fcompp + _asm fcomp + return Res; + } + + inline_ int ConvertToSortable(float f) + { + int& Fi = (int&)f; + int Fmask = (Fi>>31); + Fi ^= Fmask; + Fmask &= ~(1<<31); + Fi -= Fmask; + return Fi; + } + + inline_ udword EncodeFloat(const float val) + { + // We may need to check on -0 and 0 + // But it should make no practical difference. + udword ir = IR(val); + + if(ir & 0x80000000) //negative? + ir = ~ir;//reverse sequence of negative numbers + else + ir |= 0x80000000; // flip sign + + return ir; + } + + inline_ float DecodeFloat(udword ir) + { + udword rv; + + if(ir & 0x80000000) //positive? + rv = ir & ~0x80000000; //flip sign + else + rv = ~ir; //undo reversal + + return FR(rv); + } + + enum FPUMode + { + FPU_FLOOR = 0, + FPU_CEIL = 1, + FPU_BEST = 2, + + FPU_FORCE_DWORD = 0x7fffffff + }; + + FUNCTION ICECORE_API FPUMode GetFPUMode(); + FUNCTION ICECORE_API void SaveFPU(); + FUNCTION ICECORE_API void RestoreFPU(); + FUNCTION ICECORE_API void SetFPUFloorMode(); + FUNCTION ICECORE_API void SetFPUCeilMode(); + FUNCTION ICECORE_API void SetFPUBestMode(); + + FUNCTION ICECORE_API void SetFPUPrecision24(); + FUNCTION ICECORE_API void SetFPUPrecision53(); + FUNCTION ICECORE_API void SetFPUPrecision64(); + FUNCTION ICECORE_API void SetFPURoundingChop(); + FUNCTION ICECORE_API void SetFPURoundingUp(); + FUNCTION ICECORE_API void SetFPURoundingDown(); + FUNCTION ICECORE_API void SetFPURoundingNear(); + + FUNCTION ICECORE_API int intChop(const float& f); + FUNCTION ICECORE_API int intFloor(const float& f); + FUNCTION ICECORE_API int intCeil(const float& f); + + inline_ sdword MyFloor(float f) + { + return (sdword)f - (IR(f)>>31); + } + + class ICECORE_API FPUGuard + { + public: + FPUGuard(); + ~FPUGuard(); + private: + uword mControlWord; + }; + +#endif // ICEFPU_H diff --git a/Extras/CDTestFramework/Opcode/Ice/IceHPoint.cpp b/Extras/CDTestFramework/Opcode/Ice/IceHPoint.cpp new file mode 100644 index 0000000..32d8e59 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceHPoint.cpp @@ -0,0 +1,87 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for homogeneous points. + * \file IceHPoint.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Homogeneous point. + * + * Use it: + * - for clipping in homogeneous space (standard way) + * - to differentiate between points (w=1) and vectors (w=0). + * - in some cases you can also use it instead of Point for padding reasons. + * + * \class HPoint + * \author Pierre Terdiman + * \version 1.0 + * \warning No cross-product in 4D. + * \warning HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Point Mul = HPoint * Matrix3x3; +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Point HPoint::operator*(const Matrix3x3& mat) const +{ + return Point( + x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0], + x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1], + x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] ); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// HPoint Mul = HPoint * Matrix4x4; +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HPoint HPoint::operator*(const Matrix4x4& mat) const +{ + return HPoint( + x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0], + x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1], + x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2], + x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// HPoint *= Matrix4x4 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HPoint& HPoint::operator*=(const Matrix4x4& mat) +{ + float xp = x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0]; + float yp = x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1]; + float zp = x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2]; + float wp = x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]; + + x = xp; y = yp; z = zp; w = wp; + + return *this; +} + + diff --git a/Extras/CDTestFramework/Opcode/Ice/IceHPoint.h b/Extras/CDTestFramework/Opcode/Ice/IceHPoint.h new file mode 100644 index 0000000..b35ac9e --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceHPoint.h @@ -0,0 +1,173 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for homogeneous points. + * \file IceHPoint.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEHPOINT_H__ +#define __ICEHPOINT_H__ + + class ICEMATHS_API HPoint : public Point + { + public: + + //! Empty constructor + inline_ HPoint() {} + //! Constructor from floats + inline_ HPoint(float _x, float _y, float _z, float _w=0.0f) : Point(_x, _y, _z), w(_w) {} + //! Constructor from array + inline_ HPoint(const float f[4]) : Point(f), w(f[3]) {} + //! Constructor from a Point + inline_ HPoint(const Point& p, float _w=0.0f) : Point(p), w(_w) {} + //! Destructor + inline_ ~HPoint() {} + + //! Clear the point + inline_ HPoint& Zero() { x = y = z = w = 0.0f; return *this; } + + //! Assignment from values + inline_ HPoint& Set(float _x, float _y, float _z, float _w ) { x = _x; y = _y; z = _z; w = _w; return *this; } + //! Assignment from array + inline_ HPoint& Set(const float f[4]) { x = f[_X]; y = f[_Y]; z = f[_Z]; w = f[_W]; return *this; } + //! Assignment from another h-point + inline_ HPoint& Set(const HPoint& src) { x = src.x; y = src.y; z = src.z; w = src.w; return *this; } + + //! Add a vector + inline_ HPoint& Add(float _x, float _y, float _z, float _w ) { x += _x; y += _y; z += _z; w += _w; return *this; } + //! Add a vector + inline_ HPoint& Add(const float f[4]) { x += f[_X]; y += f[_Y]; z += f[_Z]; w += f[_W]; return *this; } + + //! Subtract a vector + inline_ HPoint& Sub(float _x, float _y, float _z, float _w ) { x -= _x; y -= _y; z -= _z; w -= _w; return *this; } + //! Subtract a vector + inline_ HPoint& Sub(const float f[4]) { x -= f[_X]; y -= f[_Y]; z -= f[_Z]; w -= f[_W]; return *this; } + + //! Multiplies by a scalar + inline_ HPoint& Mul(float s) { x *= s; y *= s; z *= s; w *= s; return *this; } + + //! Returns MIN(x, y, z, w); + float Min() const { return MIN(x, MIN(y, MIN(z, w))); } + //! Returns MAX(x, y, z, w); + float Max() const { return MAX(x, MAX(y, MAX(z, w))); } + //! Sets each element to be componentwise minimum + HPoint& Min(const HPoint& p) { x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z); w = MIN(w, p.w); return *this; } + //! Sets each element to be componentwise maximum + HPoint& Max(const HPoint& p) { x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z); w = MAX(w, p.w); return *this; } + + //! Computes square magnitude + inline_ float SquareMagnitude() const { return x*x + y*y + z*z + w*w; } + //! Computes magnitude + inline_ float Magnitude() const { return sqrtf(x*x + y*y + z*z + w*w); } + + //! Normalize the vector + inline_ HPoint& Normalize() + { + float M = Magnitude(); + if(M) + { + M = 1.0f / M; + x *= M; + y *= M; + z *= M; + w *= M; + } + return *this; + } + + // Arithmetic operators + //! Operator for HPoint Negate = - HPoint; + inline_ HPoint operator-() const { return HPoint(-x, -y, -z, -w); } + + //! Operator for HPoint Plus = HPoint + HPoint; + inline_ HPoint operator+(const HPoint& p) const { return HPoint(x + p.x, y + p.y, z + p.z, w + p.w); } + //! Operator for HPoint Minus = HPoint - HPoint; + inline_ HPoint operator-(const HPoint& p) const { return HPoint(x - p.x, y - p.y, z - p.z, w - p.w); } + + //! Operator for HPoint Mul = HPoint * HPoint; + inline_ HPoint operator*(const HPoint& p) const { return HPoint(x * p.x, y * p.y, z * p.z, w * p.w); } + //! Operator for HPoint Scale = HPoint * float; + inline_ HPoint operator*(float s) const { return HPoint(x * s, y * s, z * s, w * s); } + //! Operator for HPoint Scale = float * HPoint; + inline_ friend HPoint operator*(float s, const HPoint& p) { return HPoint(s * p.x, s * p.y, s * p.z, s * p.w); } + + //! Operator for HPoint Div = HPoint / HPoint; + inline_ HPoint operator/(const HPoint& p) const { return HPoint(x / p.x, y / p.y, z / p.z, w / p.w); } + //! Operator for HPoint Scale = HPoint / float; + inline_ HPoint operator/(float s) const { s = 1.0f / s; return HPoint(x * s, y * s, z * s, w * s); } + //! Operator for HPoint Scale = float / HPoint; + inline_ friend HPoint operator/(float s, const HPoint& p) { return HPoint(s / p.x, s / p.y, s / p.z, s / p.w); } + + //! Operator for float DotProd = HPoint | HPoint; + inline_ float operator|(const HPoint& p) const { return x*p.x + y*p.y + z*p.z + w*p.w; } + // No cross-product in 4D + + //! Operator for HPoint += HPoint; + inline_ HPoint& operator+=(const HPoint& p) { x += p.x; y += p.y; z += p.z; w += p.w; return *this; } + //! Operator for HPoint += float; + inline_ HPoint& operator+=(float s) { x += s; y += s; z += s; w += s; return *this; } + + //! Operator for HPoint -= HPoint; + inline_ HPoint& operator-=(const HPoint& p) { x -= p.x; y -= p.y; z -= p.z; w -= p.w; return *this; } + //! Operator for HPoint -= float; + inline_ HPoint& operator-=(float s) { x -= s; y -= s; z -= s; w -= s; return *this; } + + //! Operator for HPoint *= HPoint; + inline_ HPoint& operator*=(const HPoint& p) { x *= p.x; y *= p.y; z *= p.z; w *= p.w; return *this; } + //! Operator for HPoint *= float; + inline_ HPoint& operator*=(float s) { x*=s; y*=s; z*=s; w*=s; return *this; } + + //! Operator for HPoint /= HPoint; + inline_ HPoint& operator/=(const HPoint& p) { x /= p.x; y /= p.y; z /= p.z; w /= p.w; return *this; } + //! Operator for HPoint /= float; + inline_ HPoint& operator/=(float s) { s = 1.0f / s; x*=s; y*=s; z*=s; w*=s; return *this; } + + // Arithmetic operators + + //! Operator for Point Mul = HPoint * Matrix3x3; + Point operator*(const Matrix3x3& mat) const; + //! Operator for HPoint Mul = HPoint * Matrix4x4; + HPoint operator*(const Matrix4x4& mat) const; + + // HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4 + //! Operator for HPoint *= Matrix4x4 + HPoint& operator*=(const Matrix4x4& mat); + + // Logical operators + + //! Operator for "if(HPoint==HPoint)" + inline_ bool operator==(const HPoint& p) const { return ( (x==p.x)&&(y==p.y)&&(z==p.z)&&(w==p.w)); } + //! Operator for "if(HPoint!=HPoint)" + inline_ bool operator!=(const HPoint& p) const { return ( (x!=p.x)||(y!=p.y)||(z!=p.z)||(w!=p.w)); } + + // Cast operators + + //! Cast a HPoint to a Point. w is discarded. + inline_ operator Point() const { return Point(x, y, z); } + + public: + float w; + }; + +#endif // __ICEHPOINT_H__ + diff --git a/Extras/CDTestFramework/Opcode/Ice/IceHashing.h b/Extras/CDTestFramework/Opcode/Ice/IceHashing.h new file mode 100644 index 0000000..45160f8 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceHashing.h @@ -0,0 +1,78 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains hashing code. + * \file IceHashing.h + * \author Pierre Terdiman + * \date May, 08, 1999 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef ICEHASHING_H +#define ICEHASHING_H + + #define HashSize(n) ((udword)1<<(n)) + #define HashMask(n) (HashSize(n)-1) + + ICECORE_API udword Hash(const char* str); + ICECORE_API udword Hash(ubyte* k, udword length, udword initval); + + // Bob Jenkin's hash + inline_ unsigned int Hash32Bits_0(unsigned int key) + { + key += (key << 12); + key ^= (key >> 22); + key += (key << 4); + key ^= (key >> 9); + key += (key << 10); + key ^= (key >> 2); + key += (key << 7); + key ^= (key >> 12); + return key; + } + + // Thomas Wang's hash + inline_ int Hash32Bits_1(int key) + { + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; + } + + // Thomas Wang's hash + inline_ __int64 Hash64Bits_0(__int64 key) + { + key += ~(key << 32); + key ^= (key >> 22); + key += ~(key << 13); + key ^= (key >> 8); + key += (key << 3); + key ^= (key >> 15); + key += ~(key << 27); + key ^= (key >> 31); + return key; + } + + inline_ __int64 Hash64Bits_1(__int64 key) + { + __int64 c1 = 0x6e5ea73858134343L; + __int64 c2 = 0xb34e8f99a2ec9ef5L; + key ^= ((c1 ^ key) >> 32); + key *= c1; + key ^= ((c2 ^ key) >> 31); + key *= c2; + key ^= ((c1 ^ key) >> 32); + return key; + } + + inline_ udword Hash(udword id0, udword id1) + { + return Hash32Bits_1( (id0&0xffff)|(id1<<16) ); + } + +#endif // ICEHASHING_H diff --git a/Extras/CDTestFramework/Opcode/Ice/IceIndexedTriangle.cpp b/Extras/CDTestFramework/Opcode/Ice/IceIndexedTriangle.cpp new file mode 100644 index 0000000..4657f08 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceIndexedTriangle.cpp @@ -0,0 +1,564 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a handy indexed triangle class. + * \file IceIndexedTriangle.cpp + * \author Pierre Terdiman + * \date January, 17, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an indexed triangle class. + * + * \class Triangle + * \author Pierre Terdiman + * \version 1.0 + * \date 08.15.98 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Flips the winding order. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::Flip() +{ + Swap(mVRef[1], mVRef[2]); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle area. + * \param verts [in] the list of indexed vertices + * \return the area + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::Area(const Point* verts) const +{ + if(!verts) return 0.0f; + const Point& p0 = verts[0]; + const Point& p1 = verts[1]; + const Point& p2 = verts[2]; + return ((p0-p1)^(p0-p2)).Magnitude() * 0.5f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle perimeter. + * \param verts [in] the list of indexed vertices + * \return the perimeter + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::Perimeter(const Point* verts) const +{ + if(!verts) return 0.0f; + const Point& p0 = verts[0]; + const Point& p1 = verts[1]; + const Point& p2 = verts[2]; + return p0.Distance(p1) + + p0.Distance(p2) + + p1.Distance(p2); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle compacity. + * \param verts [in] the list of indexed vertices + * \return the compacity + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::Compacity(const Point* verts) const +{ + if(!verts) return 0.0f; + float P = Perimeter(verts); + if(P==0.0f) return 0.0f; + return (4.0f*PI*Area(verts)/(P*P)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle normal. + * \param verts [in] the list of indexed vertices + * \param normal [out] the computed normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::Normal(const Point* verts, Point& normal) const +{ + if(!verts) return; + + const Point& p0 = verts[mVRef[0]]; + const Point& p1 = verts[mVRef[1]]; + const Point& p2 = verts[mVRef[2]]; + normal = ((p2-p1)^(p0-p1)).Normalize(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle denormalized normal. + * \param verts [in] the list of indexed vertices + * \param normal [out] the computed normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::DenormalizedNormal(const Point* verts, Point& normal) const +{ + if(!verts) return; + + const Point& p0 = verts[mVRef[0]]; + const Point& p1 = verts[mVRef[1]]; + const Point& p2 = verts[mVRef[2]]; + normal = ((p2-p1)^(p0-p1)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle center. + * \param verts [in] the list of indexed vertices + * \param center [out] the computed center + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::Center(const Point* verts, Point& center) const +{ + if(!verts) return; + + const Point& p0 = verts[mVRef[0]]; + const Point& p1 = verts[mVRef[1]]; + const Point& p2 = verts[mVRef[2]]; + center = (p0+p1+p2)*INV3; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the centered normal + * \param verts [in] the list of indexed vertices + * \param normal [out] the computed centered normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::CenteredNormal(const Point* verts, Point& normal) const +{ + if(!verts) return; + + const Point& p0 = verts[mVRef[0]]; + const Point& p1 = verts[mVRef[1]]; + const Point& p2 = verts[mVRef[2]]; + Point Center = (p0+p1+p2)*INV3; + normal = Center + ((p2-p1)^(p0-p1)).Normalize(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a random point within the triangle. + * \param verts [in] the list of indexed vertices + * \param normal [out] the computed centered normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::RandomPoint(const Point* verts, Point& random) const +{ + if(!verts) return; + + // Random barycentric coords + float Alpha = UnitRandomFloat(); + float Beta = UnitRandomFloat(); + float Gamma = UnitRandomFloat(); + float OneOverTotal = 1.0f / (Alpha + Beta + Gamma); + Alpha *= OneOverTotal; + Beta *= OneOverTotal; + Gamma *= OneOverTotal; + + const Point& p0 = verts[mVRef[0]]; + const Point& p1 = verts[mVRef[1]]; + const Point& p2 = verts[mVRef[2]]; + random = Alpha*p0 + Beta*p1 + Gamma*p2; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes backface culling. + * \param verts [in] the list of indexed vertices + * \param source [in] source point (in local space) from which culling must be computed + * \return true if the triangle is visible from the source point + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::IsVisible(const Point* verts, const Point& source) const +{ + // Checkings + if(!verts) return false; + + const Point& p0 = verts[mVRef[0]]; + const Point& p1 = verts[mVRef[1]]; + const Point& p2 = verts[mVRef[2]]; + + // Compute denormalized normal + Point Normal = (p2 - p1)^(p0 - p1); + + // Backface culling + return (Normal | source) >= 0.0f; + +// Same as: +// Plane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); +// return PL.Distance(source) > PL.d; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes backface culling. + * \param verts [in] the list of indexed vertices + * \param source [in] source point (in local space) from which culling must be computed + * \return true if the triangle is visible from the source point + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::BackfaceCulling(const Point* verts, const Point& source) const +{ + // Checkings + if(!verts) return false; + + const Point& p0 = verts[mVRef[0]]; + const Point& p1 = verts[mVRef[1]]; + const Point& p2 = verts[mVRef[2]]; + + // Compute base +// Point Base = (p0 + p1 + p2)*INV3; + + // Compute denormalized normal + Point Normal = (p2 - p1)^(p0 - p1); + + // Backface culling +// return (Normal | (source - Base)) >= 0.0f; + return (Normal | (source - p0)) >= 0.0f; + +// Same as: (but a bit faster) +// Plane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); +// return PL.Distance(source)>0.0f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the occlusion potential of the triangle. + * \param verts [in] the list of indexed vertices + * \param source [in] source point (in local space) from which occlusion potential must be computed + * \return the occlusion potential + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::ComputeOcclusionPotential(const Point* verts, const Point& view) const +{ + if(!verts) return 0.0f; + // Occlusion potential: -(A * (N|V) / d^2) + // A = polygon area + // N = polygon normal + // V = view vector + // d = distance viewpoint-center of polygon + + float A = Area(verts); + Point N; Normal(verts, N); + Point C; Center(verts, C); + float d = view.Distance(C); + return -(A*(N|view))/(d*d); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Replaces a vertex reference with another one. + * \param oldref [in] the vertex reference to replace + * \param newref [in] the new vertex reference + * \return true if success, else false if the input vertex reference doesn't belong to the triangle + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::ReplaceVertex(udword oldref, udword newref) +{ + if(mVRef[0]==oldref) { mVRef[0] = newref; return true; } + else if(mVRef[1]==oldref) { mVRef[1] = newref; return true; } + else if(mVRef[2]==oldref) { mVRef[2] = newref; return true; } + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks whether the triangle is degenerate or not. A degenerate triangle has two common vertex references. This is a zero-area triangle. + * \return true if the triangle is degenerate + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::IsDegenerate() const +{ + if(mVRef[0]==mVRef[1]) return true; + if(mVRef[1]==mVRef[2]) return true; + if(mVRef[2]==mVRef[0]) return true; + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks whether the input vertex reference belongs to the triangle or not. + * \param ref [in] the vertex reference to look for + * \return true if the triangle contains the vertex reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::HasVertex(udword ref) const +{ + if(mVRef[0]==ref) return true; + if(mVRef[1]==ref) return true; + if(mVRef[2]==ref) return true; + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks whether the input vertex reference belongs to the triangle or not. + * \param ref [in] the vertex reference to look for + * \param index [out] the corresponding index in the triangle + * \return true if the triangle contains the vertex reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::HasVertex(udword ref, udword* index) const +{ + if(mVRef[0]==ref) { *index = 0; return true; } + if(mVRef[1]==ref) { *index = 1; return true; } + if(mVRef[2]==ref) { *index = 2; return true; } + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Finds an edge in a tri, given two vertex references. + * \param vref0 [in] the edge's first vertex reference + * \param vref1 [in] the edge's second vertex reference + * \return the edge number between 0 and 2, or 0xff if input refs are wrong. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +ubyte IndexedTriangle::FindEdge(udword vref0, udword vref1) const +{ + if(mVRef[0]==vref0 && mVRef[1]==vref1) return 0; + else if(mVRef[0]==vref1 && mVRef[1]==vref0) return 0; + else if(mVRef[0]==vref0 && mVRef[2]==vref1) return 1; + else if(mVRef[0]==vref1 && mVRef[2]==vref0) return 1; + else if(mVRef[1]==vref0 && mVRef[2]==vref1) return 2; + else if(mVRef[1]==vref1 && mVRef[2]==vref0) return 2; + return 0xff; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Gets the last reference given the first two. + * \param vref0 [in] the first vertex reference + * \param vref1 [in] the second vertex reference + * \return the last reference, or INVALID_ID if input refs are wrong. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword IndexedTriangle::OppositeVertex(udword vref0, udword vref1) const +{ + if(mVRef[0]==vref0 && mVRef[1]==vref1) return mVRef[2]; + else if(mVRef[0]==vref1 && mVRef[1]==vref0) return mVRef[2]; + else if(mVRef[0]==vref0 && mVRef[2]==vref1) return mVRef[1]; + else if(mVRef[0]==vref1 && mVRef[2]==vref0) return mVRef[1]; + else if(mVRef[1]==vref0 && mVRef[2]==vref1) return mVRef[0]; + else if(mVRef[1]==vref1 && mVRef[2]==vref0) return mVRef[0]; + return INVALID_ID; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Gets the three sorted vertex references according to an edge number. + * edgenb = 0 => edge 0-1, returns references 0, 1, 2 + * edgenb = 1 => edge 0-2, returns references 0, 2, 1 + * edgenb = 2 => edge 1-2, returns references 1, 2, 0 + * + * \param edgenb [in] the edge number, 0, 1 or 2 + * \param vref0 [out] the returned first vertex reference + * \param vref1 [out] the returned second vertex reference + * \param vref2 [out] the returned third vertex reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2) const +{ + if(edgenb==0) + { + vref0 = mVRef[0]; + vref1 = mVRef[1]; + vref2 = mVRef[2]; + } + else if(edgenb==1) + { + vref0 = mVRef[0]; + vref1 = mVRef[2]; + vref2 = mVRef[1]; + } + else if(edgenb==2) + { + vref0 = mVRef[1]; + vref1 = mVRef[2]; + vref2 = mVRef[0]; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle's smallest edge length. + * \param verts [in] the list of indexed vertices + * \return the smallest edge length + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::MinEdgeLength(const Point* verts) const +{ + if(!verts) return 0.0f; + + float Min = MAX_FLOAT; + float Length01 = verts[0].Distance(verts[1]); + float Length02 = verts[0].Distance(verts[2]); + float Length12 = verts[1].Distance(verts[2]); + if(Length01 < Min) Min = Length01; + if(Length02 < Min) Min = Length02; + if(Length12 < Min) Min = Length12; + return Min; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle's largest edge length. + * \param verts [in] the list of indexed vertices + * \return the largest edge length + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::MaxEdgeLength(const Point* verts) const +{ + if(!verts) return 0.0f; + + float Max = MIN_FLOAT; + float Length01 = verts[0].Distance(verts[1]); + float Length02 = verts[0].Distance(verts[2]); + float Length12 = verts[1].Distance(verts[2]); + if(Length01 > Max) Max = Length01; + if(Length02 > Max) Max = Length02; + if(Length12 > Max) Max = Length12; + return Max; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a point on the triangle according to the stabbing information. + * \param verts [in] the list of indexed vertices + * \param u,v [in] point's barycentric coordinates + * \param pt [out] point on triangle + * \param nearvtx [out] index of nearest vertex + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::ComputePoint(const Point* verts, float u, float v, Point& pt, udword* nearvtx) const +{ + // Checkings + if(!verts) return; + + // Get face in local or global space + const Point& p0 = verts[mVRef[0]]; + const Point& p1 = verts[mVRef[1]]; + const Point& p2 = verts[mVRef[2]]; + + // Compute point coordinates + pt = (1.0f - u - v)*p0 + u*p1 + v*p2; + + // Compute nearest vertex if needed + if(nearvtx) + { + // Compute distance vector + Point d(p0.SquareDistance(pt), // Distance^2 from vertex 0 to point on the face + p1.SquareDistance(pt), // Distance^2 from vertex 1 to point on the face + p2.SquareDistance(pt)); // Distance^2 from vertex 2 to point on the face + + // Get smallest distance + *nearvtx = mVRef[d.SmallestAxis()]; + } +} + + //************************************** + // Angle between two vectors (in radians) + // we use this formula + // uv = |u||v| cos(u,v) + // u ^ v = w + // |w| = |u||v| |sin(u,v)| + //************************************** + float Angle(const Point& u, const Point& v) + { + float NormU = u.Magnitude(); // |u| + float NormV = v.Magnitude(); // |v| + float Product = NormU*NormV; // |u||v| + if(Product==0.0f) return 0.0f; + float OneOverProduct = 1.0f / Product; + + // Cosinus + float Cosinus = (u|v) * OneOverProduct; + + // Sinus + Point w = u^v; + float NormW = w.Magnitude(); + + float AbsSinus = NormW * OneOverProduct; + + // Remove degeneracy + if(AbsSinus > 1.0f) AbsSinus = 1.0f; + if(AbsSinus < -1.0f) AbsSinus = -1.0f; + + if(Cosinus>=0.0f) return asinf(AbsSinus); + else return (PI-asinf(AbsSinus)); + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the angle between two triangles. + * \param tri [in] the other triangle + * \param verts [in] the list of indexed vertices + * \return the angle in radians + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::Angle(const IndexedTriangle& tri, const Point* verts) const +{ + // Checkings + if(!verts) return 0.0f; + + // Compute face normals + Point n0, n1; + Normal(verts, n0); + tri.Normal(verts, n1); + + // Compute angle + float dp = n0|n1; + if(dp>1.0f) return 0.0f; + if(dp<-1.0f) return PI; + return acosf(dp); + +// return ::Angle(n0,n1); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks a triangle is the same as another one. + * \param tri [in] the other triangle + * \return true if same triangle + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::Equal(const IndexedTriangle& tri) const +{ + // Test all vertex references + return (HasVertex(tri.mVRef[0]) && + HasVertex(tri.mVRef[1]) && + HasVertex(tri.mVRef[2])); +} diff --git a/Extras/CDTestFramework/Opcode/Ice/IceIndexedTriangle.h b/Extras/CDTestFramework/Opcode/Ice/IceIndexedTriangle.h new file mode 100644 index 0000000..3317a9b --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceIndexedTriangle.h @@ -0,0 +1,84 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a handy indexed triangle class. + * \file IceIndexedTriangle.h + * \author Pierre Terdiman + * \date January, 17, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEINDEXEDTRIANGLE_H__ +#define __ICEINDEXEDTRIANGLE_H__ + + // Forward declarations + enum CubeIndex; + + // An indexed triangle class. + class ICEMATHS_API IndexedTriangle + { + public: + //! Constructor + inline_ IndexedTriangle() {} + //! Constructor + inline_ IndexedTriangle(udword r0, udword r1, udword r2) { mVRef[0]=r0; mVRef[1]=r1; mVRef[2]=r2; } + //! Copy constructor + inline_ IndexedTriangle(const IndexedTriangle& triangle) + { + mVRef[0] = triangle.mVRef[0]; + mVRef[1] = triangle.mVRef[1]; + mVRef[2] = triangle.mVRef[2]; + } + //! Destructor + inline_ ~IndexedTriangle() {} + //! Vertex-references + udword mVRef[3]; + + // Methods + void Flip(); + float Area(const Point* verts) const; + float Perimeter(const Point* verts) const; + float Compacity(const Point* verts) const; + void Normal(const Point* verts, Point& normal) const; + void DenormalizedNormal(const Point* verts, Point& normal) const; + void Center(const Point* verts, Point& center) const; + void CenteredNormal(const Point* verts, Point& normal) const; + void RandomPoint(const Point* verts, Point& random) const; + bool IsVisible(const Point* verts, const Point& source) const; + bool BackfaceCulling(const Point* verts, const Point& source) const; + float ComputeOcclusionPotential(const Point* verts, const Point& view) const; + bool ReplaceVertex(udword oldref, udword newref); + bool IsDegenerate() const; + bool HasVertex(udword ref) const; + bool HasVertex(udword ref, udword* index) const; + ubyte FindEdge(udword vref0, udword vref1) const; + udword OppositeVertex(udword vref0, udword vref1) const; + inline_ udword OppositeVertex(ubyte edgenb) const { return mVRef[2-edgenb]; } + void GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2) const; + float MinEdgeLength(const Point* verts) const; + float MaxEdgeLength(const Point* verts) const; + void ComputePoint(const Point* verts, float u, float v, Point& pt, udword* nearvtx=null) const; + float Angle(const IndexedTriangle& tri, const Point* verts) const; + inline_ Plane PlaneEquation(const Point* verts) const { return Plane(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); } + bool Equal(const IndexedTriangle& tri) const; + CubeIndex ComputeCubeIndex(const Point* verts) const; + }; + +#endif // __ICEINDEXEDTRIANGLE_H__ diff --git a/Extras/CDTestFramework/Opcode/Ice/IceLSS.h b/Extras/CDTestFramework/Opcode/Ice/IceLSS.h new file mode 100644 index 0000000..d9816d5 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceLSS.h @@ -0,0 +1,91 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for line-swept spheres. + * \file IceLSS.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICELSS_H__ +#define __ICELSS_H__ + + class ICEMATHS_API LSS : public Segment + { + public: + //! Constructor + inline_ LSS() {} + //! Constructor + inline_ LSS(const Segment& seg, float radius) : Segment(seg), mRadius(radius) {} + //! Destructor + inline_ ~LSS() {} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes an OBB surrounding the LSS. + * \param box [out] the OBB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void ComputeOBB(OBB& box); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a point is contained within the LSS. + * \param pt [in] the point to test + * \return true if inside the LSS + * \warning point and LSS must be in same space + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Contains(const Point& pt) const { return SquareDistance(pt) <= mRadius*mRadius; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a sphere is contained within the LSS. + * \param sphere [in] the sphere to test + * \return true if inside the LSS + * \warning sphere and LSS must be in same space + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Contains(const Sphere& sphere) + { + float d = mRadius - sphere.mRadius; + if(d>=0.0f) return SquareDistance(sphere.mCenter) <= d*d; + else return false; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if an LSS is contained within the LSS. + * \param lss [in] the LSS to test + * \return true if inside the LSS + * \warning both LSS must be in same space + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Contains(const LSS& lss) + { + // We check the LSS contains the two spheres at the start and end of the sweep + return Contains(Sphere(lss.mP0, lss.mRadius)) && Contains(Sphere(lss.mP0, lss.mRadius)); + } + + float mRadius; //!< Sphere radius + }; + +#endif // __ICELSS_H__ diff --git a/Extras/CDTestFramework/Opcode/Ice/IceMatrix3x3.cpp b/Extras/CDTestFramework/Opcode/Ice/IceMatrix3x3.cpp new file mode 100644 index 0000000..8a981b5 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceMatrix3x3.cpp @@ -0,0 +1,64 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 3x3 matrices. + * \file IceMatrix3x3.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * 3x3 matrix. + * DirectX-compliant, ie row-column order, ie m[Row][Col]. + * Same as: + * m11 m12 m13 first row. + * m21 m22 m23 second row. + * m31 m32 m33 third row. + * Stored in memory as m11 m12 m13 m21... + * + * Multiplication rules: + * + * [x'y'z'] = [xyz][M] + * + * x' = x*m11 + y*m21 + z*m31 + * y' = x*m12 + y*m22 + z*m32 + * z' = x*m13 + y*m23 + z*m33 + * + * \class Matrix3x3 + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +// Cast operator +Matrix3x3::operator Matrix4x4() const +{ + return Matrix4x4( + m[0][0], m[0][1], m[0][2], 0.0f, + m[1][0], m[1][1], m[1][2], 0.0f, + m[2][0], m[2][1], m[2][2], 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); +} diff --git a/Extras/CDTestFramework/Opcode/Ice/IceMatrix3x3.h b/Extras/CDTestFramework/Opcode/Ice/IceMatrix3x3.h new file mode 100644 index 0000000..a2da08a --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceMatrix3x3.h @@ -0,0 +1,512 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 3x3 matrices. + * \file IceMatrix3x3.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEMATRIX3X3_H__ +#define __ICEMATRIX3X3_H__ + + // Forward declarations + class Quat; + + #define MATRIX3X3_EPSILON (1.0e-7f) + + class ICEMATHS_API Matrix3x3 + { + public: + //! Empty constructor + inline_ Matrix3x3() {} + //! Constructor from 9 values + inline_ Matrix3x3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) + { + m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; + m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; + m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; + } + //! Copy constructor + inline_ Matrix3x3(const Matrix3x3& mat) { CopyMemory(m, &mat.m, 9*sizeof(float)); } + //! Destructor + inline_ ~Matrix3x3() {} + + //! Assign values + inline_ void Set(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) + { + m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; + m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; + m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; + } + + //! Sets the scale from a Point. The point is put on the diagonal. + inline_ void SetScale(const Point& p) { m[0][0] = p.x; m[1][1] = p.y; m[2][2] = p.z; } + + //! Sets the scale from floats. Values are put on the diagonal. + inline_ void SetScale(float sx, float sy, float sz) { m[0][0] = sx; m[1][1] = sy; m[2][2] = sz; } + + //! Scales from a Point. Each row is multiplied by a component. + inline_ void Scale(const Point& p) + { + m[0][0] *= p.x; m[0][1] *= p.x; m[0][2] *= p.x; + m[1][0] *= p.y; m[1][1] *= p.y; m[1][2] *= p.y; + m[2][0] *= p.z; m[2][1] *= p.z; m[2][2] *= p.z; + } + + //! Scales from floats. Each row is multiplied by a value. + inline_ void Scale(float sx, float sy, float sz) + { + m[0][0] *= sx; m[0][1] *= sx; m[0][2] *= sx; + m[1][0] *= sy; m[1][1] *= sy; m[1][2] *= sy; + m[2][0] *= sz; m[2][1] *= sz; m[2][2] *= sz; + } + + //! Copy from a Matrix3x3 + inline_ void Copy(const Matrix3x3& source) { CopyMemory(m, source.m, 9*sizeof(float)); } + + // Row-column access + //! Returns a row. + inline_ void GetRow(const udword r, Point& p) const { p.x = m[r][0]; p.y = m[r][1]; p.z = m[r][2]; } + //! Returns a row. + inline_ const Point& GetRow(const udword r) const { return *(const Point*)&m[r][0]; } + //! Returns a row. + inline_ Point& GetRow(const udword r) { return *(Point*)&m[r][0]; } + //! Sets a row. + inline_ void SetRow(const udword r, const Point& p) { m[r][0] = p.x; m[r][1] = p.y; m[r][2] = p.z; } + //! Returns a column. + inline_ void GetCol(const udword c, Point& p) const { p.x = m[0][c]; p.y = m[1][c]; p.z = m[2][c]; } + //! Sets a column. + inline_ void SetCol(const udword c, const Point& p) { m[0][c] = p.x; m[1][c] = p.y; m[2][c] = p.z; } + + //! Computes the trace. The trace is the sum of the 3 diagonal components. + inline_ float Trace() const { return m[0][0] + m[1][1] + m[2][2]; } + //! Clears the matrix. + inline_ void Zero() { ZeroMemory(&m, sizeof(m)); } + //! Sets the identity matrix. + inline_ void Identity() { Zero(); m[0][0] = m[1][1] = m[2][2] = 1.0f; } + //! Checks for identity + inline_ bool IsIdentity() const + { + if(IR(m[0][0])!=IEEE_1_0) return false; + if(IR(m[0][1])!=0) return false; + if(IR(m[0][2])!=0) return false; + + if(IR(m[1][0])!=0) return false; + if(IR(m[1][1])!=IEEE_1_0) return false; + if(IR(m[1][2])!=0) return false; + + if(IR(m[2][0])!=0) return false; + if(IR(m[2][1])!=0) return false; + if(IR(m[2][2])!=IEEE_1_0) return false; + + return true; + } + + //! Checks matrix validity + inline_ BOOL IsValid() const + { + for(udword j=0;j<3;j++) + { + for(udword i=0;i<3;i++) + { + if(!IsValidFloat(m[j][i])) return FALSE; + } + } + return TRUE; + } + + //! Makes a skew-symmetric matrix (a.k.a. Star(*) Matrix) + //! [ 0.0 -a.z a.y ] + //! [ a.z 0.0 -a.x ] + //! [ -a.y a.x 0.0 ] + //! This is also called a "cross matrix" since for any vectors A and B, + //! A^B = Skew(A) * B = - B * Skew(A); + inline_ void SkewSymmetric(const Point& a) + { + m[0][0] = 0.0f; + m[0][1] = -a.z; + m[0][2] = a.y; + + m[1][0] = a.z; + m[1][1] = 0.0f; + m[1][2] = -a.x; + + m[2][0] = -a.y; + m[2][1] = a.x; + m[2][2] = 0.0f; + } + + //! Negates the matrix + inline_ void Neg() + { + m[0][0] = -m[0][0]; m[0][1] = -m[0][1]; m[0][2] = -m[0][2]; + m[1][0] = -m[1][0]; m[1][1] = -m[1][1]; m[1][2] = -m[1][2]; + m[2][0] = -m[2][0]; m[2][1] = -m[2][1]; m[2][2] = -m[2][2]; + } + + //! Neg from another matrix + inline_ void Neg(const Matrix3x3& mat) + { + m[0][0] = -mat.m[0][0]; m[0][1] = -mat.m[0][1]; m[0][2] = -mat.m[0][2]; + m[1][0] = -mat.m[1][0]; m[1][1] = -mat.m[1][1]; m[1][2] = -mat.m[1][2]; + m[2][0] = -mat.m[2][0]; m[2][1] = -mat.m[2][1]; m[2][2] = -mat.m[2][2]; + } + + //! Add another matrix + inline_ void Add(const Matrix3x3& mat) + { + m[0][0] += mat.m[0][0]; m[0][1] += mat.m[0][1]; m[0][2] += mat.m[0][2]; + m[1][0] += mat.m[1][0]; m[1][1] += mat.m[1][1]; m[1][2] += mat.m[1][2]; + m[2][0] += mat.m[2][0]; m[2][1] += mat.m[2][1]; m[2][2] += mat.m[2][2]; + } + + //! Sub another matrix + inline_ void Sub(const Matrix3x3& mat) + { + m[0][0] -= mat.m[0][0]; m[0][1] -= mat.m[0][1]; m[0][2] -= mat.m[0][2]; + m[1][0] -= mat.m[1][0]; m[1][1] -= mat.m[1][1]; m[1][2] -= mat.m[1][2]; + m[2][0] -= mat.m[2][0]; m[2][1] -= mat.m[2][1]; m[2][2] -= mat.m[2][2]; + } + //! Mac + inline_ void Mac(const Matrix3x3& a, const Matrix3x3& b, float s) + { + m[0][0] = a.m[0][0] + b.m[0][0] * s; + m[0][1] = a.m[0][1] + b.m[0][1] * s; + m[0][2] = a.m[0][2] + b.m[0][2] * s; + + m[1][0] = a.m[1][0] + b.m[1][0] * s; + m[1][1] = a.m[1][1] + b.m[1][1] * s; + m[1][2] = a.m[1][2] + b.m[1][2] * s; + + m[2][0] = a.m[2][0] + b.m[2][0] * s; + m[2][1] = a.m[2][1] + b.m[2][1] * s; + m[2][2] = a.m[2][2] + b.m[2][2] * s; + } + //! Mac + inline_ void Mac(const Matrix3x3& a, float s) + { + m[0][0] += a.m[0][0] * s; m[0][1] += a.m[0][1] * s; m[0][2] += a.m[0][2] * s; + m[1][0] += a.m[1][0] * s; m[1][1] += a.m[1][1] * s; m[1][2] += a.m[1][2] * s; + m[2][0] += a.m[2][0] * s; m[2][1] += a.m[2][1] * s; m[2][2] += a.m[2][2] * s; + } + + //! this = A * s + inline_ void Mult(const Matrix3x3& a, float s) + { + m[0][0] = a.m[0][0] * s; m[0][1] = a.m[0][1] * s; m[0][2] = a.m[0][2] * s; + m[1][0] = a.m[1][0] * s; m[1][1] = a.m[1][1] * s; m[1][2] = a.m[1][2] * s; + m[2][0] = a.m[2][0] * s; m[2][1] = a.m[2][1] * s; m[2][2] = a.m[2][2] * s; + } + + inline_ void Add(const Matrix3x3& a, const Matrix3x3& b) + { + m[0][0] = a.m[0][0] + b.m[0][0]; m[0][1] = a.m[0][1] + b.m[0][1]; m[0][2] = a.m[0][2] + b.m[0][2]; + m[1][0] = a.m[1][0] + b.m[1][0]; m[1][1] = a.m[1][1] + b.m[1][1]; m[1][2] = a.m[1][2] + b.m[1][2]; + m[2][0] = a.m[2][0] + b.m[2][0]; m[2][1] = a.m[2][1] + b.m[2][1]; m[2][2] = a.m[2][2] + b.m[2][2]; + } + + inline_ void Sub(const Matrix3x3& a, const Matrix3x3& b) + { + m[0][0] = a.m[0][0] - b.m[0][0]; m[0][1] = a.m[0][1] - b.m[0][1]; m[0][2] = a.m[0][2] - b.m[0][2]; + m[1][0] = a.m[1][0] - b.m[1][0]; m[1][1] = a.m[1][1] - b.m[1][1]; m[1][2] = a.m[1][2] - b.m[1][2]; + m[2][0] = a.m[2][0] - b.m[2][0]; m[2][1] = a.m[2][1] - b.m[2][1]; m[2][2] = a.m[2][2] - b.m[2][2]; + } + + //! this = a * b + inline_ void Mult(const Matrix3x3& a, const Matrix3x3& b) + { + m[0][0] = a.m[0][0] * b.m[0][0] + a.m[0][1] * b.m[1][0] + a.m[0][2] * b.m[2][0]; + m[0][1] = a.m[0][0] * b.m[0][1] + a.m[0][1] * b.m[1][1] + a.m[0][2] * b.m[2][1]; + m[0][2] = a.m[0][0] * b.m[0][2] + a.m[0][1] * b.m[1][2] + a.m[0][2] * b.m[2][2]; + m[1][0] = a.m[1][0] * b.m[0][0] + a.m[1][1] * b.m[1][0] + a.m[1][2] * b.m[2][0]; + m[1][1] = a.m[1][0] * b.m[0][1] + a.m[1][1] * b.m[1][1] + a.m[1][2] * b.m[2][1]; + m[1][2] = a.m[1][0] * b.m[0][2] + a.m[1][1] * b.m[1][2] + a.m[1][2] * b.m[2][2]; + m[2][0] = a.m[2][0] * b.m[0][0] + a.m[2][1] * b.m[1][0] + a.m[2][2] * b.m[2][0]; + m[2][1] = a.m[2][0] * b.m[0][1] + a.m[2][1] * b.m[1][1] + a.m[2][2] * b.m[2][1]; + m[2][2] = a.m[2][0] * b.m[0][2] + a.m[2][1] * b.m[1][2] + a.m[2][2] * b.m[2][2]; + } + + //! this = transpose(a) * b + inline_ void MultAtB(const Matrix3x3& a, const Matrix3x3& b) + { + m[0][0] = a.m[0][0] * b.m[0][0] + a.m[1][0] * b.m[1][0] + a.m[2][0] * b.m[2][0]; + m[0][1] = a.m[0][0] * b.m[0][1] + a.m[1][0] * b.m[1][1] + a.m[2][0] * b.m[2][1]; + m[0][2] = a.m[0][0] * b.m[0][2] + a.m[1][0] * b.m[1][2] + a.m[2][0] * b.m[2][2]; + m[1][0] = a.m[0][1] * b.m[0][0] + a.m[1][1] * b.m[1][0] + a.m[2][1] * b.m[2][0]; + m[1][1] = a.m[0][1] * b.m[0][1] + a.m[1][1] * b.m[1][1] + a.m[2][1] * b.m[2][1]; + m[1][2] = a.m[0][1] * b.m[0][2] + a.m[1][1] * b.m[1][2] + a.m[2][1] * b.m[2][2]; + m[2][0] = a.m[0][2] * b.m[0][0] + a.m[1][2] * b.m[1][0] + a.m[2][2] * b.m[2][0]; + m[2][1] = a.m[0][2] * b.m[0][1] + a.m[1][2] * b.m[1][1] + a.m[2][2] * b.m[2][1]; + m[2][2] = a.m[0][2] * b.m[0][2] + a.m[1][2] * b.m[1][2] + a.m[2][2] * b.m[2][2]; + } + + //! this = a * transpose(b) + inline_ void MultABt(const Matrix3x3& a, const Matrix3x3& b) + { + m[0][0] = a.m[0][0] * b.m[0][0] + a.m[0][1] * b.m[0][1] + a.m[0][2] * b.m[0][2]; + m[0][1] = a.m[0][0] * b.m[1][0] + a.m[0][1] * b.m[1][1] + a.m[0][2] * b.m[1][2]; + m[0][2] = a.m[0][0] * b.m[2][0] + a.m[0][1] * b.m[2][1] + a.m[0][2] * b.m[2][2]; + m[1][0] = a.m[1][0] * b.m[0][0] + a.m[1][1] * b.m[0][1] + a.m[1][2] * b.m[0][2]; + m[1][1] = a.m[1][0] * b.m[1][0] + a.m[1][1] * b.m[1][1] + a.m[1][2] * b.m[1][2]; + m[1][2] = a.m[1][0] * b.m[2][0] + a.m[1][1] * b.m[2][1] + a.m[1][2] * b.m[2][2]; + m[2][0] = a.m[2][0] * b.m[0][0] + a.m[2][1] * b.m[0][1] + a.m[2][2] * b.m[0][2]; + m[2][1] = a.m[2][0] * b.m[1][0] + a.m[2][1] * b.m[1][1] + a.m[2][2] * b.m[1][2]; + m[2][2] = a.m[2][0] * b.m[2][0] + a.m[2][1] * b.m[2][1] + a.m[2][2] * b.m[2][2]; + } + + //! Makes a rotation matrix mapping vector "from" to vector "to". + Matrix3x3& FromTo(const Point& from, const Point& to); + + //! Set a rotation matrix around the X axis. + //! 1 0 0 + //! RX = 0 cx sx + //! 0 -sx cx + void RotX(float angle); + //! Set a rotation matrix around the Y axis. + //! cy 0 -sy + //! RY = 0 1 0 + //! sy 0 cy + void RotY(float angle); + //! Set a rotation matrix around the Z axis. + //! cz sz 0 + //! RZ = -sz cz 0 + //! 0 0 1 + void RotZ(float angle); + //! cy sx.sy -sy.cx + //! RY.RX 0 cx sx + //! sy -sx.cy cx.cy + void RotYX(float y, float x); + + //! Make a rotation matrix about an arbitrary axis + Matrix3x3& Rot(float angle, const Point& axis); + + //! Transpose the matrix. + void Transpose() + { + IR(m[1][0]) ^= IR(m[0][1]); IR(m[0][1]) ^= IR(m[1][0]); IR(m[1][0]) ^= IR(m[0][1]); + IR(m[2][0]) ^= IR(m[0][2]); IR(m[0][2]) ^= IR(m[2][0]); IR(m[2][0]) ^= IR(m[0][2]); + IR(m[2][1]) ^= IR(m[1][2]); IR(m[1][2]) ^= IR(m[2][1]); IR(m[2][1]) ^= IR(m[1][2]); + } + + //! this = Transpose(a) + void Transpose(const Matrix3x3& a) + { + m[0][0] = a.m[0][0]; m[0][1] = a.m[1][0]; m[0][2] = a.m[2][0]; + m[1][0] = a.m[0][1]; m[1][1] = a.m[1][1]; m[1][2] = a.m[2][1]; + m[2][0] = a.m[0][2]; m[2][1] = a.m[1][2]; m[2][2] = a.m[2][2]; + } + + //! Compute the determinant of the matrix. We use the rule of Sarrus. + float Determinant() const + { + return (m[0][0]*m[1][1]*m[2][2] + m[0][1]*m[1][2]*m[2][0] + m[0][2]*m[1][0]*m[2][1]) + - (m[2][0]*m[1][1]*m[0][2] + m[2][1]*m[1][2]*m[0][0] + m[2][2]*m[1][0]*m[0][1]); + } +/* + //! Compute a cofactor. Used for matrix inversion. + float CoFactor(ubyte row, ubyte column) const + { + static sdword gIndex[3+2] = { 0, 1, 2, 0, 1 }; + return (m[gIndex[row+1]][gIndex[column+1]]*m[gIndex[row+2]][gIndex[column+2]] - m[gIndex[row+2]][gIndex[column+1]]*m[gIndex[row+1]][gIndex[column+2]]); + } +*/ + //! Invert the matrix. Determinant must be different from zero, else matrix can't be inverted. + Matrix3x3& Invert() + { + float Det = Determinant(); // Must be !=0 + float OneOverDet = 1.0f / Det; + + Matrix3x3 Temp; + Temp.m[0][0] = +(m[1][1] * m[2][2] - m[2][1] * m[1][2]) * OneOverDet; + Temp.m[1][0] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]) * OneOverDet; + Temp.m[2][0] = +(m[1][0] * m[2][1] - m[2][0] * m[1][1]) * OneOverDet; + Temp.m[0][1] = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]) * OneOverDet; + Temp.m[1][1] = +(m[0][0] * m[2][2] - m[2][0] * m[0][2]) * OneOverDet; + Temp.m[2][1] = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]) * OneOverDet; + Temp.m[0][2] = +(m[0][1] * m[1][2] - m[1][1] * m[0][2]) * OneOverDet; + Temp.m[1][2] = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]) * OneOverDet; + Temp.m[2][2] = +(m[0][0] * m[1][1] - m[1][0] * m[0][1]) * OneOverDet; + + *this = Temp; + + return *this; + } + + Matrix3x3& Normalize(); + + //! this = exp(a) + Matrix3x3& Exp(const Matrix3x3& a); + +void FromQuat(const Quat &q); +void FromQuatL2(const Quat &q, float l2); + + // Arithmetic operators + //! Operator for Matrix3x3 Plus = Matrix3x3 + Matrix3x3; + inline_ Matrix3x3 operator+(const Matrix3x3& mat) const + { + return Matrix3x3( + m[0][0] + mat.m[0][0], m[0][1] + mat.m[0][1], m[0][2] + mat.m[0][2], + m[1][0] + mat.m[1][0], m[1][1] + mat.m[1][1], m[1][2] + mat.m[1][2], + m[2][0] + mat.m[2][0], m[2][1] + mat.m[2][1], m[2][2] + mat.m[2][2]); + } + + //! Operator for Matrix3x3 Minus = Matrix3x3 - Matrix3x3; + inline_ Matrix3x3 operator-(const Matrix3x3& mat) const + { + return Matrix3x3( + m[0][0] - mat.m[0][0], m[0][1] - mat.m[0][1], m[0][2] - mat.m[0][2], + m[1][0] - mat.m[1][0], m[1][1] - mat.m[1][1], m[1][2] - mat.m[1][2], + m[2][0] - mat.m[2][0], m[2][1] - mat.m[2][1], m[2][2] - mat.m[2][2]); + } + + //! Operator for Matrix3x3 Mul = Matrix3x3 * Matrix3x3; + inline_ Matrix3x3 operator*(const Matrix3x3& mat) const + { + return Matrix3x3( + m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0], + m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1], + m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2], + + m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0], + m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1], + m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2], + + m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0], + m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1], + m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2]); + } + + //! Operator for Point Mul = Matrix3x3 * Point; + inline_ Point operator*(const Point& v) const { return Point(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v); } + + //! Operator for Matrix3x3 Mul = Matrix3x3 * float; + inline_ Matrix3x3 operator*(float s) const + { + return Matrix3x3( + m[0][0]*s, m[0][1]*s, m[0][2]*s, + m[1][0]*s, m[1][1]*s, m[1][2]*s, + m[2][0]*s, m[2][1]*s, m[2][2]*s); + } + + //! Operator for Matrix3x3 Mul = float * Matrix3x3; + inline_ friend Matrix3x3 operator*(float s, const Matrix3x3& mat) + { + return Matrix3x3( + s*mat.m[0][0], s*mat.m[0][1], s*mat.m[0][2], + s*mat.m[1][0], s*mat.m[1][1], s*mat.m[1][2], + s*mat.m[2][0], s*mat.m[2][1], s*mat.m[2][2]); + } + + //! Operator for Matrix3x3 Div = Matrix3x3 / float; + inline_ Matrix3x3 operator/(float s) const + { + if (s) s = 1.0f / s; + return Matrix3x3( + m[0][0]*s, m[0][1]*s, m[0][2]*s, + m[1][0]*s, m[1][1]*s, m[1][2]*s, + m[2][0]*s, m[2][1]*s, m[2][2]*s); + } + + //! Operator for Matrix3x3 Div = float / Matrix3x3; + inline_ friend Matrix3x3 operator/(float s, const Matrix3x3& mat) + { + return Matrix3x3( + s/mat.m[0][0], s/mat.m[0][1], s/mat.m[0][2], + s/mat.m[1][0], s/mat.m[1][1], s/mat.m[1][2], + s/mat.m[2][0], s/mat.m[2][1], s/mat.m[2][2]); + } + + //! Operator for Matrix3x3 += Matrix3x3 + inline_ Matrix3x3& operator+=(const Matrix3x3& mat) + { + m[0][0] += mat.m[0][0]; m[0][1] += mat.m[0][1]; m[0][2] += mat.m[0][2]; + m[1][0] += mat.m[1][0]; m[1][1] += mat.m[1][1]; m[1][2] += mat.m[1][2]; + m[2][0] += mat.m[2][0]; m[2][1] += mat.m[2][1]; m[2][2] += mat.m[2][2]; + return *this; + } + + //! Operator for Matrix3x3 -= Matrix3x3 + inline_ Matrix3x3& operator-=(const Matrix3x3& mat) + { + m[0][0] -= mat.m[0][0]; m[0][1] -= mat.m[0][1]; m[0][2] -= mat.m[0][2]; + m[1][0] -= mat.m[1][0]; m[1][1] -= mat.m[1][1]; m[1][2] -= mat.m[1][2]; + m[2][0] -= mat.m[2][0]; m[2][1] -= mat.m[2][1]; m[2][2] -= mat.m[2][2]; + return *this; + } + + //! Operator for Matrix3x3 *= Matrix3x3 + inline_ Matrix3x3& operator*=(const Matrix3x3& mat) + { + Point TempRow; + + GetRow(0, TempRow); + m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0]; + m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1]; + m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2]; + + GetRow(1, TempRow); + m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0]; + m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1]; + m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2]; + + GetRow(2, TempRow); + m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0]; + m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1]; + m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2]; + return *this; + } + + //! Operator for Matrix3x3 *= float + inline_ Matrix3x3& operator*=(float s) + { + m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; + m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; + m[2][0] *= s; m[2][1] *= s; m[2][2] *= s; + return *this; + } + + //! Operator for Matrix3x3 /= float + inline_ Matrix3x3& operator/=(float s) + { + if (s) s = 1.0f / s; + m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; + m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; + m[2][0] *= s; m[2][1] *= s; m[2][2] *= s; + return *this; + } + + // Cast operators + //! Cast a Matrix3x3 to a Matrix4x4. + operator Matrix4x4() const; + //! Cast a Matrix3x3 to a Quat. + operator Quat() const; + + inline_ const Point& operator[](int row) const { return *(const Point*)&m[row][0]; } + inline_ Point& operator[](int row) { return *(Point*)&m[row][0]; } + + public: + + float m[3][3]; + }; + +#endif // __ICEMATRIX3X3_H__ + diff --git a/Extras/CDTestFramework/Opcode/Ice/IceMatrix4x4.cpp b/Extras/CDTestFramework/Opcode/Ice/IceMatrix4x4.cpp new file mode 100644 index 0000000..7e10f45 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceMatrix4x4.cpp @@ -0,0 +1,152 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 4x4 matrices. + * \file IceMatrix4x4.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * 4x4 matrix. + * DirectX-compliant, ie row-column order, ie m[Row][Col]. + * Same as: + * m11 m12 m13 m14 first row. + * m21 m22 m23 m24 second row. + * m31 m32 m33 m34 third row. + * m41 m42 m43 m44 fourth row. + * Translation is (m41, m42, m43), (m14, m24, m34, m44) = (0, 0, 0, 1). + * Stored in memory as m11 m12 m13 m14 m21... + * + * Multiplication rules: + * + * [x'y'z'1] = [xyz1][M] + * + * x' = x*m11 + y*m21 + z*m31 + m41 + * y' = x*m12 + y*m22 + z*m32 + m42 + * z' = x*m13 + y*m23 + z*m33 + m43 + * 1' = 0 + 0 + 0 + m44 + * + * \class Matrix4x4 + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Inverts a PR matrix. (which only contains a rotation and a translation) + * This is faster and less subject to FPU errors than the generic inversion code. + * + * \relates Matrix4x4 + * \fn InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src) + * \param dest [out] destination matrix + * \param src [in] source matrix + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +ICEMATHS_API void IceMaths::InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src) +{ + dest.m[0][0] = src.m[0][0]; + dest.m[1][0] = src.m[0][1]; + dest.m[2][0] = src.m[0][2]; + dest.m[3][0] = -(src.m[3][0]*src.m[0][0] + src.m[3][1]*src.m[0][1] + src.m[3][2]*src.m[0][2]); + + dest.m[0][1] = src.m[1][0]; + dest.m[1][1] = src.m[1][1]; + dest.m[2][1] = src.m[1][2]; + dest.m[3][1] = -(src.m[3][0]*src.m[1][0] + src.m[3][1]*src.m[1][1] + src.m[3][2]*src.m[1][2]); + + dest.m[0][2] = src.m[2][0]; + dest.m[1][2] = src.m[2][1]; + dest.m[2][2] = src.m[2][2]; + dest.m[3][2] = -(src.m[3][0]*src.m[2][0] + src.m[3][1]*src.m[2][1] + src.m[3][2]*src.m[2][2]); + + dest.m[0][3] = 0.0f; + dest.m[1][3] = 0.0f; + dest.m[2][3] = 0.0f; + dest.m[3][3] = 1.0f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Compute the cofactor of the Matrix at a specified location +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Matrix4x4::CoFactor(udword row, udword col) const +{ + return (( m[(row+1)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+3)&3][(col+3)&3] + + m[(row+1)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+3)&3][(col+1)&3] + + m[(row+1)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+3)&3][(col+2)&3]) + - (m[(row+3)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+1)&3][(col+3)&3] + + m[(row+3)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+1)&3][(col+1)&3] + + m[(row+3)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+1)&3][(col+2)&3])) * ((row + col) & 1 ? -1.0f : +1.0f); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Compute the determinant of the Matrix +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Matrix4x4::Determinant() const +{ + return m[0][0] * CoFactor(0, 0) + + m[0][1] * CoFactor(0, 1) + + m[0][2] * CoFactor(0, 2) + + m[0][3] * CoFactor(0, 3); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Compute the inverse of the matrix +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Matrix4x4& Matrix4x4::Invert() +{ + float Det = Determinant(); + Matrix4x4 Temp; + + if(fabsf(Det) < MATRIX4X4_EPSILON) + return *this; // The matrix is not invertible! Singular case! + + float IDet = 1.0f / Det; + + Temp.m[0][0] = CoFactor(0,0) * IDet; + Temp.m[1][0] = CoFactor(0,1) * IDet; + Temp.m[2][0] = CoFactor(0,2) * IDet; + Temp.m[3][0] = CoFactor(0,3) * IDet; + Temp.m[0][1] = CoFactor(1,0) * IDet; + Temp.m[1][1] = CoFactor(1,1) * IDet; + Temp.m[2][1] = CoFactor(1,2) * IDet; + Temp.m[3][1] = CoFactor(1,3) * IDet; + Temp.m[0][2] = CoFactor(2,0) * IDet; + Temp.m[1][2] = CoFactor(2,1) * IDet; + Temp.m[2][2] = CoFactor(2,2) * IDet; + Temp.m[3][2] = CoFactor(2,3) * IDet; + Temp.m[0][3] = CoFactor(3,0) * IDet; + Temp.m[1][3] = CoFactor(3,1) * IDet; + Temp.m[2][3] = CoFactor(3,2) * IDet; + Temp.m[3][3] = CoFactor(3,3) * IDet; + + *this = Temp; + + return *this; +} + + diff --git a/Extras/CDTestFramework/Opcode/Ice/IceMatrix4x4.h b/Extras/CDTestFramework/Opcode/Ice/IceMatrix4x4.h new file mode 100644 index 0000000..8abc2a7 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceMatrix4x4.h @@ -0,0 +1,471 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 4x4 matrices. + * \file IceMatrix4x4.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEMATRIX4X4_H__ +#define __ICEMATRIX4X4_H__ + + // Forward declarations + class PRS; + class PR; + + #define MATRIX4X4_EPSILON (1.0e-7f) + + class ICEMATHS_API Matrix4x4 + { +// void LUBackwardSubstitution( sdword *indx, float* b ); +// void LUDecomposition( sdword* indx, float* d ); + + public: + //! Empty constructor. + inline_ Matrix4x4() {} + //! Constructor from 16 values + inline_ Matrix4x4( float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33) + { + m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03; + m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13; + m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23; + m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33; + } + //! Copy constructor + inline_ Matrix4x4(const Matrix4x4& mat) { CopyMemory(m, &mat.m, 16*sizeof(float)); } + //! Destructor. + inline_ ~Matrix4x4() {} + + //! Assign values (rotation only) + inline_ Matrix4x4& Set( float m00, float m01, float m02, + float m10, float m11, float m12, + float m20, float m21, float m22) + { + m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; + m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; + m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; + return *this; + } + //! Assign values + inline_ Matrix4x4& Set( float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33) + { + m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03; + m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13; + m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23; + m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33; + return *this; + } + + //! Copy from a Matrix4x4 + inline_ void Copy(const Matrix4x4& source) { CopyMemory(m, source.m, 16*sizeof(float)); } + + // Row-column access + //! Returns a row. + inline_ void GetRow(const udword r, HPoint& p) const { p.x=m[r][0]; p.y=m[r][1]; p.z=m[r][2]; p.w=m[r][3]; } + //! Returns a row. + inline_ void GetRow(const udword r, Point& p) const { p.x=m[r][0]; p.y=m[r][1]; p.z=m[r][2]; } + //! Returns a row. + inline_ const HPoint& GetRow(const udword r) const { return *(const HPoint*)&m[r][0]; } + //! Returns a row. + inline_ HPoint& GetRow(const udword r) { return *(HPoint*)&m[r][0]; } + //! Sets a row. + inline_ void SetRow(const udword r, const HPoint& p) { m[r][0]=p.x; m[r][1]=p.y; m[r][2]=p.z; m[r][3]=p.w; } + //! Sets a row. + inline_ void SetRow(const udword r, const Point& p) { m[r][0]=p.x; m[r][1]=p.y; m[r][2]=p.z; m[r][3]= (r!=3) ? 0.0f : 1.0f; } + //! Returns a column. + inline_ void GetCol(const udword c, HPoint& p) const { p.x=m[0][c]; p.y=m[1][c]; p.z=m[2][c]; p.w=m[3][c]; } + //! Returns a column. + inline_ void GetCol(const udword c, Point& p) const { p.x=m[0][c]; p.y=m[1][c]; p.z=m[2][c]; } + //! Sets a column. + inline_ void SetCol(const udword c, const HPoint& p) { m[0][c]=p.x; m[1][c]=p.y; m[2][c]=p.z; m[3][c]=p.w; } + //! Sets a column. + inline_ void SetCol(const udword c, const Point& p) { m[0][c]=p.x; m[1][c]=p.y; m[2][c]=p.z; m[3][c]= (c!=3) ? 0.0f : 1.0f; } + + // Translation + //! Returns the translation part of the matrix. + inline_ const HPoint& GetTrans() const { return GetRow(3); } + //! Gets the translation part of the matrix + inline_ void GetTrans(Point& p) const { p.x=m[3][0]; p.y=m[3][1]; p.z=m[3][2]; } + //! Sets the translation part of the matrix, from a Point. + inline_ void SetTrans(const Point& p) { m[3][0]=p.x; m[3][1]=p.y; m[3][2]=p.z; } + //! Sets the translation part of the matrix, from a HPoint. + inline_ void SetTrans(const HPoint& p) { m[3][0]=p.x; m[3][1]=p.y; m[3][2]=p.z; m[3][3]=p.w; } + //! Sets the translation part of the matrix, from floats. + inline_ void SetTrans(float tx, float ty, float tz) { m[3][0]=tx; m[3][1]=ty; m[3][2]=tz; } + + // Scale + //! Sets the scale from a Point. The point is put on the diagonal. + inline_ void SetScale(const Point& p) { m[0][0]=p.x; m[1][1]=p.y; m[2][2]=p.z; } + //! Sets the scale from floats. Values are put on the diagonal. + inline_ void SetScale(float sx, float sy, float sz) { m[0][0]=sx; m[1][1]=sy; m[2][2]=sz; } + //! Scales from a Point. Each row is multiplied by a component. + void Scale(const Point& p) + { + m[0][0] *= p.x; m[1][0] *= p.y; m[2][0] *= p.z; + m[0][1] *= p.x; m[1][1] *= p.y; m[2][1] *= p.z; + m[0][2] *= p.x; m[1][2] *= p.y; m[2][2] *= p.z; + } + //! Scales from floats. Each row is multiplied by a value. + void Scale(float sx, float sy, float sz) + { + m[0][0] *= sx; m[1][0] *= sy; m[2][0] *= sz; + m[0][1] *= sx; m[1][1] *= sy; m[2][1] *= sz; + m[0][2] *= sx; m[1][2] *= sy; m[2][2] *= sz; + } +/* + //! Returns a row. + inline_ HPoint GetRow(const udword row) const { return mRow[row]; } + //! Sets a row. + inline_ Matrix4x4& SetRow(const udword row, const HPoint& p) { mRow[row] = p; return *this; } + //! Sets a row. + Matrix4x4& SetRow(const udword row, const Point& p) + { + m[row][0] = p.x; + m[row][1] = p.y; + m[row][2] = p.z; + m[row][3] = (row != 3) ? 0.0f : 1.0f; + return *this; + } + //! Returns a column. + HPoint GetCol(const udword col) const + { + HPoint Res; + Res.x = m[0][col]; + Res.y = m[1][col]; + Res.z = m[2][col]; + Res.w = m[3][col]; + return Res; + } + //! Sets a column. + Matrix4x4& SetCol(const udword col, const HPoint& p) + { + m[0][col] = p.x; + m[1][col] = p.y; + m[2][col] = p.z; + m[3][col] = p.w; + return *this; + } + //! Sets a column. + Matrix4x4& SetCol(const udword col, const Point& p) + { + m[0][col] = p.x; + m[1][col] = p.y; + m[2][col] = p.z; + m[3][col] = (col != 3) ? 0.0f : 1.0f; + return *this; + } +*/ + //! Computes the trace. The trace is the sum of the 4 diagonal components. + inline_ float Trace() const { return m[0][0] + m[1][1] + m[2][2] + m[3][3]; } + //! Computes the trace of the upper 3x3 matrix. + inline_ float Trace3x3() const { return m[0][0] + m[1][1] + m[2][2]; } + //! Clears the matrix. + inline_ void Zero() { ZeroMemory(&m, sizeof(m)); } + //! Sets the identity matrix. + inline_ void Identity() { Zero(); m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; } + //! Checks for identity + inline_ bool IsIdentity() const + { + if(IR(m[0][0])!=IEEE_1_0) return false; + if(IR(m[0][1])!=0) return false; + if(IR(m[0][2])!=0) return false; + if(IR(m[0][3])!=0) return false; + + if(IR(m[1][0])!=0) return false; + if(IR(m[1][1])!=IEEE_1_0) return false; + if(IR(m[1][2])!=0) return false; + if(IR(m[1][3])!=0) return false; + + if(IR(m[2][0])!=0) return false; + if(IR(m[2][1])!=0) return false; + if(IR(m[2][2])!=IEEE_1_0) return false; + if(IR(m[2][3])!=0) return false; + + if(IR(m[3][0])!=0) return false; + if(IR(m[3][1])!=0) return false; + if(IR(m[3][2])!=0) return false; + if(IR(m[3][3])!=IEEE_1_0) return false; + return true; + } + + //! Checks matrix validity + inline_ BOOL IsValid() const + { + for(udword j=0;j<4;j++) + { + for(udword i=0;i<4;i++) + { + if(!IsValidFloat(m[j][i])) return FALSE; + } + } + return TRUE; + } + + //! Sets a rotation matrix around the X axis. + void RotX(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[1][1] = m[2][2] = Cos; m[2][1] = -Sin; m[1][2] = Sin; } + //! Sets a rotation matrix around the Y axis. + void RotY(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[2][2] = Cos; m[2][0] = Sin; m[0][2] = -Sin; } + //! Sets a rotation matrix around the Z axis. + void RotZ(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[1][1] = Cos; m[1][0] = -Sin; m[0][1] = Sin; } + + //! Makes a rotation matrix about an arbitrary axis + Matrix4x4& Rot(float angle, Point& p1, Point& p2); + + //! Transposes the matrix. + void Transpose() + { + IR(m[1][0]) ^= IR(m[0][1]); IR(m[0][1]) ^= IR(m[1][0]); IR(m[1][0]) ^= IR(m[0][1]); + IR(m[2][0]) ^= IR(m[0][2]); IR(m[0][2]) ^= IR(m[2][0]); IR(m[2][0]) ^= IR(m[0][2]); + IR(m[3][0]) ^= IR(m[0][3]); IR(m[0][3]) ^= IR(m[3][0]); IR(m[3][0]) ^= IR(m[0][3]); + IR(m[1][2]) ^= IR(m[2][1]); IR(m[2][1]) ^= IR(m[1][2]); IR(m[1][2]) ^= IR(m[2][1]); + IR(m[1][3]) ^= IR(m[3][1]); IR(m[3][1]) ^= IR(m[1][3]); IR(m[1][3]) ^= IR(m[3][1]); + IR(m[2][3]) ^= IR(m[3][2]); IR(m[3][2]) ^= IR(m[2][3]); IR(m[2][3]) ^= IR(m[3][2]); + } + + //! Computes a cofactor. Used for matrix inversion. + float CoFactor(udword row, udword col) const; + //! Computes the determinant of the matrix. + float Determinant() const; + //! Inverts the matrix. Determinant must be different from zero, else matrix can't be inverted. + Matrix4x4& Invert(); +// Matrix& ComputeAxisMatrix(Point& axis, float angle); + + // Cast operators + //! Casts a Matrix4x4 to a Matrix3x3. + inline_ operator Matrix3x3() const + { + return Matrix3x3( + m[0][0], m[0][1], m[0][2], + m[1][0], m[1][1], m[1][2], + m[2][0], m[2][1], m[2][2]); + } + //! Casts a Matrix4x4 to a Quat. + operator Quat() const; + //! Casts a Matrix4x4 to a PR. + operator PR() const; + + // Arithmetic operators + //! Operator for Matrix4x4 Plus = Matrix4x4 + Matrix4x4; + inline_ Matrix4x4 operator+(const Matrix4x4& mat) const + { + return Matrix4x4( + m[0][0]+mat.m[0][0], m[0][1]+mat.m[0][1], m[0][2]+mat.m[0][2], m[0][3]+mat.m[0][3], + m[1][0]+mat.m[1][0], m[1][1]+mat.m[1][1], m[1][2]+mat.m[1][2], m[1][3]+mat.m[1][3], + m[2][0]+mat.m[2][0], m[2][1]+mat.m[2][1], m[2][2]+mat.m[2][2], m[2][3]+mat.m[2][3], + m[3][0]+mat.m[3][0], m[3][1]+mat.m[3][1], m[3][2]+mat.m[3][2], m[3][3]+mat.m[3][3]); + } + + //! Operator for Matrix4x4 Minus = Matrix4x4 - Matrix4x4; + inline_ Matrix4x4 operator-(const Matrix4x4& mat) const + { + return Matrix4x4( + m[0][0]-mat.m[0][0], m[0][1]-mat.m[0][1], m[0][2]-mat.m[0][2], m[0][3]-mat.m[0][3], + m[1][0]-mat.m[1][0], m[1][1]-mat.m[1][1], m[1][2]-mat.m[1][2], m[1][3]-mat.m[1][3], + m[2][0]-mat.m[2][0], m[2][1]-mat.m[2][1], m[2][2]-mat.m[2][2], m[2][3]-mat.m[2][3], + m[3][0]-mat.m[3][0], m[3][1]-mat.m[3][1], m[3][2]-mat.m[3][2], m[3][3]-mat.m[3][3]); + } + + //! Operator for Matrix4x4 Mul = Matrix4x4 * Matrix4x4; + inline_ Matrix4x4 operator*(const Matrix4x4& mat) const + { + return Matrix4x4( + m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0] + m[0][3]*mat.m[3][0], + m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1] + m[0][3]*mat.m[3][1], + m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2] + m[0][3]*mat.m[3][2], + m[0][0]*mat.m[0][3] + m[0][1]*mat.m[1][3] + m[0][2]*mat.m[2][3] + m[0][3]*mat.m[3][3], + + m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0] + m[1][3]*mat.m[3][0], + m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1] + m[1][3]*mat.m[3][1], + m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2] + m[1][3]*mat.m[3][2], + m[1][0]*mat.m[0][3] + m[1][1]*mat.m[1][3] + m[1][2]*mat.m[2][3] + m[1][3]*mat.m[3][3], + + m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0] + m[2][3]*mat.m[3][0], + m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1] + m[2][3]*mat.m[3][1], + m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2] + m[2][3]*mat.m[3][2], + m[2][0]*mat.m[0][3] + m[2][1]*mat.m[1][3] + m[2][2]*mat.m[2][3] + m[2][3]*mat.m[3][3], + + m[3][0]*mat.m[0][0] + m[3][1]*mat.m[1][0] + m[3][2]*mat.m[2][0] + m[3][3]*mat.m[3][0], + m[3][0]*mat.m[0][1] + m[3][1]*mat.m[1][1] + m[3][2]*mat.m[2][1] + m[3][3]*mat.m[3][1], + m[3][0]*mat.m[0][2] + m[3][1]*mat.m[1][2] + m[3][2]*mat.m[2][2] + m[3][3]*mat.m[3][2], + m[3][0]*mat.m[0][3] + m[3][1]*mat.m[1][3] + m[3][2]*mat.m[2][3] + m[3][3]*mat.m[3][3]); + } + + //! Operator for HPoint Mul = Matrix4x4 * HPoint; + inline_ HPoint operator*(const HPoint& v) const { return HPoint(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v, GetRow(3)|v); } + + //! Operator for Point Mul = Matrix4x4 * Point; + inline_ Point operator*(const Point& v) const + { + return Point( m[0][0]*v.x + m[0][1]*v.y + m[0][2]*v.z + m[0][3], + m[1][0]*v.x + m[1][1]*v.y + m[1][2]*v.z + m[1][3], + m[2][0]*v.x + m[2][1]*v.y + m[2][2]*v.z + m[2][3] ); + } + + //! Operator for Matrix4x4 Scale = Matrix4x4 * float; + inline_ Matrix4x4 operator*(float s) const + { + return Matrix4x4( + m[0][0]*s, m[0][1]*s, m[0][2]*s, m[0][3]*s, + m[1][0]*s, m[1][1]*s, m[1][2]*s, m[1][3]*s, + m[2][0]*s, m[2][1]*s, m[2][2]*s, m[2][3]*s, + m[3][0]*s, m[3][1]*s, m[3][2]*s, m[3][3]*s); + } + + //! Operator for Matrix4x4 Scale = float * Matrix4x4; + inline_ friend Matrix4x4 operator*(float s, const Matrix4x4& mat) + { + return Matrix4x4( + s*mat.m[0][0], s*mat.m[0][1], s*mat.m[0][2], s*mat.m[0][3], + s*mat.m[1][0], s*mat.m[1][1], s*mat.m[1][2], s*mat.m[1][3], + s*mat.m[2][0], s*mat.m[2][1], s*mat.m[2][2], s*mat.m[2][3], + s*mat.m[3][0], s*mat.m[3][1], s*mat.m[3][2], s*mat.m[3][3]); + } + + //! Operator for Matrix4x4 Div = Matrix4x4 / float; + inline_ Matrix4x4 operator/(float s) const + { + if(s) s = 1.0f / s; + + return Matrix4x4( + m[0][0]*s, m[0][1]*s, m[0][2]*s, m[0][3]*s, + m[1][0]*s, m[1][1]*s, m[1][2]*s, m[1][3]*s, + m[2][0]*s, m[2][1]*s, m[2][2]*s, m[2][3]*s, + m[3][0]*s, m[3][1]*s, m[3][2]*s, m[3][3]*s); + } + + //! Operator for Matrix4x4 Div = float / Matrix4x4; + inline_ friend Matrix4x4 operator/(float s, const Matrix4x4& mat) + { + return Matrix4x4( + s/mat.m[0][0], s/mat.m[0][1], s/mat.m[0][2], s/mat.m[0][3], + s/mat.m[1][0], s/mat.m[1][1], s/mat.m[1][2], s/mat.m[1][3], + s/mat.m[2][0], s/mat.m[2][1], s/mat.m[2][2], s/mat.m[2][3], + s/mat.m[3][0], s/mat.m[3][1], s/mat.m[3][2], s/mat.m[3][3]); + } + + //! Operator for Matrix4x4 += Matrix4x4; + inline_ Matrix4x4& operator+=(const Matrix4x4& mat) + { + m[0][0]+=mat.m[0][0]; m[0][1]+=mat.m[0][1]; m[0][2]+=mat.m[0][2]; m[0][3]+=mat.m[0][3]; + m[1][0]+=mat.m[1][0]; m[1][1]+=mat.m[1][1]; m[1][2]+=mat.m[1][2]; m[1][3]+=mat.m[1][3]; + m[2][0]+=mat.m[2][0]; m[2][1]+=mat.m[2][1]; m[2][2]+=mat.m[2][2]; m[2][3]+=mat.m[2][3]; + m[3][0]+=mat.m[3][0]; m[3][1]+=mat.m[3][1]; m[3][2]+=mat.m[3][2]; m[3][3]+=mat.m[3][3]; + return *this; + } + + //! Operator for Matrix4x4 -= Matrix4x4; + inline_ Matrix4x4& operator-=(const Matrix4x4& mat) + { + m[0][0]-=mat.m[0][0]; m[0][1]-=mat.m[0][1]; m[0][2]-=mat.m[0][2]; m[0][3]-=mat.m[0][3]; + m[1][0]-=mat.m[1][0]; m[1][1]-=mat.m[1][1]; m[1][2]-=mat.m[1][2]; m[1][3]-=mat.m[1][3]; + m[2][0]-=mat.m[2][0]; m[2][1]-=mat.m[2][1]; m[2][2]-=mat.m[2][2]; m[2][3]-=mat.m[2][3]; + m[3][0]-=mat.m[3][0]; m[3][1]-=mat.m[3][1]; m[3][2]-=mat.m[3][2]; m[3][3]-=mat.m[3][3]; + return *this; + } + + //! Operator for Matrix4x4 *= Matrix4x4; + Matrix4x4& operator*=(const Matrix4x4& mat) + { + HPoint TempRow; + + GetRow(0, TempRow); + m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; + m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; + m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; + m[0][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; + + GetRow(1, TempRow); + m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; + m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; + m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; + m[1][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; + + GetRow(2, TempRow); + m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; + m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; + m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; + m[2][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; + + GetRow(3, TempRow); + m[3][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; + m[3][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; + m[3][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; + m[3][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; + + return *this; + } + + //! Operator for Matrix4x4 *= float; + inline_ Matrix4x4& operator*=(float s) + { + m[0][0]*=s; m[0][1]*=s; m[0][2]*=s; m[0][3]*=s; + m[1][0]*=s; m[1][1]*=s; m[1][2]*=s; m[1][3]*=s; + m[2][0]*=s; m[2][1]*=s; m[2][2]*=s; m[2][3]*=s; + m[3][0]*=s; m[3][1]*=s; m[3][2]*=s; m[3][3]*=s; + return *this; + } + + //! Operator for Matrix4x4 /= float; + inline_ Matrix4x4& operator/=(float s) + { + if(s) s = 1.0f / s; + m[0][0]*=s; m[0][1]*=s; m[0][2]*=s; m[0][3]*=s; + m[1][0]*=s; m[1][1]*=s; m[1][2]*=s; m[1][3]*=s; + m[2][0]*=s; m[2][1]*=s; m[2][2]*=s; m[2][3]*=s; + m[3][0]*=s; m[3][1]*=s; m[3][2]*=s; m[3][3]*=s; + return *this; + } + + inline_ const HPoint& operator[](int row) const { return *(const HPoint*)&m[row][0]; } + inline_ HPoint& operator[](int row) { return *(HPoint*)&m[row][0]; } + + public: + + float m[4][4]; + }; + + //! Quickly rotates & translates a vector, using the 4x3 part of a 4x4 matrix + inline_ void TransformPoint4x3(Point& dest, const Point& source, const Matrix4x4& rot) + { + dest.x = rot.m[3][0] + source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0]; + dest.y = rot.m[3][1] + source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1]; + dest.z = rot.m[3][2] + source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2]; + } + + //! Quickly rotates a vector, using the 3x3 part of a 4x4 matrix + inline_ void TransformPoint3x3(Point& dest, const Point& source, const Matrix4x4& rot) + { + dest.x = source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0]; + dest.y = source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1]; + dest.z = source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2]; + } + + ICEMATHS_API void InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src); + +#endif // __ICEMATRIX4X4_H__ + diff --git a/Extras/CDTestFramework/Opcode/Ice/IceMemoryMacros.h b/Extras/CDTestFramework/Opcode/Ice/IceMemoryMacros.h new file mode 100644 index 0000000..3f24975 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceMemoryMacros.h @@ -0,0 +1,180 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains all memory macros. + * \file IceMemoryMacros.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef ICEMEMORYMACROS_H +#define ICEMEMORYMACROS_H + +#undef ZeroMemory +#undef CopyMemory +#undef MoveMemory +#undef FillMemory + + //! Clears a buffer. + //! \param addr [in] buffer address + //! \param size [in] buffer length + //! \see FillMemory + //! \see StoreDwords + //! \see CopyMemory + //! \see MoveMemory + inline_ void ZeroMemory(void* addr, regsize size) { memset(addr, 0, size); } + + //! Fills a buffer with a given byte. + //! \param addr [in] buffer address + //! \param size [in] buffer length + //! \param val [in] the byte value + //! \see StoreDwords + //! \see ZeroMemory + //! \see CopyMemory + //! \see MoveMemory + inline_ void FillMemory(void* dest, regsize size, ubyte val) { memset(dest, val, size); } + + //! Fills a buffer with a given dword. + //! \param addr [in] buffer address + //! \param nb [in] number of dwords to write + //! \param value [in] the dword value + //! \see FillMemory + //! \see ZeroMemory + //! \see CopyMemory + //! \see MoveMemory + //! \warning writes nb*4 bytes ! + inline_ void StoreDwords(udword* dest, udword nb, udword value) + { + // The asm code below **SHOULD** be equivalent to one of those C versions + // or the other if your compiled is good: (checked on VC++ 6.0) + // + // 1) while(nb--) *dest++ = value; + // + // 2) for(udword i=0;iRelease(); (x) = null; } + + //! Safe ICE-style release + #define SAFE_DESTRUCT(x) if (x) { (x)->SelfDestruct(); (x) = null; } + +#ifdef ICEERROR_H + //! Standard alloc checking. HANDLE WITH CARE. Relies on strict coding rules. Probably shouldn't be used outside of ICE. + #define CHECKALLOC(x) if(!x) return SetIceError("Out of memory.", EC_OUT_OF_MEMORY); +#else + #define CHECKALLOC(x) if(!x) return false; +#endif + + //! Standard allocation cycle + #define SAFE_ALLOC(ptr, type, count) DELETEARRAY(ptr); ptr = new type[count]; CHECKALLOC(ptr); + #define SAFE_ICE_ALLOC(ptr, type, count) DELETEARRAY(ptr); ptr = ICE_NEW(type)[count]; CHECKALLOC(ptr); + + //! Don't use inline for alloca !!! +#ifdef WIN32 + #define StackAlloc(x) _alloca(x) +#elif LINUX + #define StackAlloc(x) alloca(x) +#elif defined(__APPLE__) + #define StackAlloc(x) alloca(x) +#elif defined(_XBOX) + #define StackAlloc(x) _alloca(x) +#endif + +#ifdef _DEBUG +// #define ICE_ALLOC_TMP(x) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, #x, MEMORY_TEMP) +// #define ICE_ALLOC(x) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, #x, MEMORY_PERSISTENT) + #define ICE_ALLOC_TMP(x) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, "(undefined)", MEMORY_TEMP) + #define ICE_ALLOC(x) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, "(undefined)", MEMORY_PERSISTENT) + #define ICE_ALLOC_TMP2(x, y) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, #y, MEMORY_TEMP) + #define ICE_ALLOC2(x, y) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, #y, MEMORY_PERSISTENT) +#else + #define ICE_ALLOC_TMP(x) GetAllocator()->malloc(x, MEMORY_TEMP) + #define ICE_ALLOC(x) GetAllocator()->malloc(x, MEMORY_PERSISTENT) +#endif + #define ICE_FREE(x) if(x) { GetAllocator()->free(x); x = null; } + +#ifdef DONT_TRACK_MEMORY_LEAKS + #ifdef _DEBUG + #define ICE_NEW_TMP(x) new(__FILE__, __LINE__, #x, MEMORY_TEMP) x + #define ICE_NEW(x) new(__FILE__, __LINE__, #x, MEMORY_PERSISTENT) x + #else + #define ICE_NEW_TMP(x) new(MEMORY_TEMP) x + #define ICE_NEW(x) new(MEMORY_PERSISTENT) x + #endif +#else + #define ICE_NEW_TMP(x) new x + #define ICE_NEW(x) new x +#endif + +#endif // ICEMEMORYMACROS_H diff --git a/Extras/CDTestFramework/Opcode/Ice/IceOBB.cpp b/Extras/CDTestFramework/Opcode/Ice/IceOBB.cpp new file mode 100644 index 0000000..7956321 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceOBB.cpp @@ -0,0 +1,339 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains OBB-related code. + * \file IceOBB.cpp + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * An Oriented Bounding Box (OBB). + * \class OBB + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Tests if a point is contained within the OBB. + * \param p [in] the world point to test + * \return true if inside the OBB + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool OBB::ContainsPoint(const Point& p) const +{ + // Point in OBB test using lazy evaluation and early exits + + // Translate to box space + Point RelPoint = p - mCenter; + + // Point * mRot maps from box space to world space + // mRot * Point maps from world space to box space (what we need here) + + float f = mRot.m[0][0] * RelPoint.x + mRot.m[0][1] * RelPoint.y + mRot.m[0][2] * RelPoint.z; + if(f >= mExtents.x || f <= -mExtents.x) return false; + + f = mRot.m[1][0] * RelPoint.x + mRot.m[1][1] * RelPoint.y + mRot.m[1][2] * RelPoint.z; + if(f >= mExtents.y || f <= -mExtents.y) return false; + + f = mRot.m[2][0] * RelPoint.x + mRot.m[2][1] * RelPoint.y + mRot.m[2][2] * RelPoint.z; + if(f >= mExtents.z || f <= -mExtents.z) return false; + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds an OBB from an AABB and a world transform. + * \param aabb [in] the aabb + * \param mat [in] the world transform + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBB::Create(const AABB& aabb, const Matrix4x4& mat) +{ + // Note: must be coherent with Rotate() + + aabb.GetCenter(mCenter); + aabb.GetExtents(mExtents); + // Here we have the same as OBB::Rotate(mat) where the obb is (mCenter, mExtents, Identity). + + // So following what's done in Rotate: + // - x-form the center + mCenter *= mat; + // - combine rotation with identity, i.e. just use given matrix + mRot = mat; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the obb planes. + * \param planes [out] 6 box planes + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool OBB::ComputePlanes(Plane* planes) const +{ + // Checkings + if(!planes) return false; + + Point Axis0 = mRot[0]; + Point Axis1 = mRot[1]; + Point Axis2 = mRot[2]; + + // Writes normals + planes[0].n = Axis0; + planes[1].n = -Axis0; + planes[2].n = Axis1; + planes[3].n = -Axis1; + planes[4].n = Axis2; + planes[5].n = -Axis2; + + // Compute a point on each plane + Point p0 = mCenter + Axis0 * mExtents.x; + Point p1 = mCenter - Axis0 * mExtents.x; + Point p2 = mCenter + Axis1 * mExtents.y; + Point p3 = mCenter - Axis1 * mExtents.y; + Point p4 = mCenter + Axis2 * mExtents.z; + Point p5 = mCenter - Axis2 * mExtents.z; + + // Compute d + planes[0].d = -(planes[0].n|p0); + planes[1].d = -(planes[1].n|p1); + planes[2].d = -(planes[2].n|p2); + planes[3].d = -(planes[3].n|p3); + planes[4].d = -(planes[4].n|p4); + planes[5].d = -(planes[5].n|p5); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the obb points. + * \param pts [out] 8 box points + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool OBB::ComputePoints(Point* pts) const +{ + // Checkings + if(!pts) return false; + + Point Axis0 = mRot[0]; + Point Axis1 = mRot[1]; + Point Axis2 = mRot[2]; + + Axis0 *= mExtents.x; + Axis1 *= mExtents.y; + Axis2 *= mExtents.z; + + // 7+------+6 0 = --- + // /| /| 1 = +-- + // / | / | 2 = ++- + // / 4+---/--+5 3 = -+- + // 3+------+2 / y z 4 = --+ + // | / | / | / 5 = +-+ + // |/ |/ |/ 6 = +++ + // 0+------+1 *---x 7 = -++ + + pts[0] = mCenter - Axis0 - Axis1 - Axis2; + pts[1] = mCenter + Axis0 - Axis1 - Axis2; + pts[2] = mCenter + Axis0 + Axis1 - Axis2; + pts[3] = mCenter - Axis0 + Axis1 - Axis2; + pts[4] = mCenter - Axis0 - Axis1 + Axis2; + pts[5] = mCenter + Axis0 - Axis1 + Axis2; + pts[6] = mCenter + Axis0 + Axis1 + Axis2; + pts[7] = mCenter - Axis0 + Axis1 + Axis2; + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes vertex normals. + * \param pts [out] 8 box points + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool OBB::ComputeVertexNormals(Point* pts) const +{ + static float VertexNormals[] = + { + -INVSQRT3, -INVSQRT3, -INVSQRT3, + INVSQRT3, -INVSQRT3, -INVSQRT3, + INVSQRT3, INVSQRT3, -INVSQRT3, + -INVSQRT3, INVSQRT3, -INVSQRT3, + -INVSQRT3, -INVSQRT3, INVSQRT3, + INVSQRT3, -INVSQRT3, INVSQRT3, + INVSQRT3, INVSQRT3, INVSQRT3, + -INVSQRT3, INVSQRT3, INVSQRT3 + }; + + if(!pts) return false; + + const Point* VN = (const Point*)VertexNormals; + for(udword i=0;i<8;i++) + { + pts[i] = VN[i] * mRot; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Returns edges. + * \return 24 indices (12 edges) indexing the list returned by ComputePoints() + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const udword* OBB::GetEdges() const +{ + static udword Indices[] = { + 0, 1, 1, 2, 2, 3, 3, 0, + 7, 6, 6, 5, 5, 4, 4, 7, + 1, 5, 6, 2, + 3, 7, 4, 0 + }; + return Indices; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Returns local edge normals. + * \return edge normals in local space + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const Point* OBB::GetLocalEdgeNormals() const +{ + static float EdgeNormals[] = + { + 0, -INVSQRT2, -INVSQRT2, // 0-1 + INVSQRT2, 0, -INVSQRT2, // 1-2 + 0, INVSQRT2, -INVSQRT2, // 2-3 + -INVSQRT2, 0, -INVSQRT2, // 3-0 + + 0, INVSQRT2, INVSQRT2, // 7-6 + INVSQRT2, 0, INVSQRT2, // 6-5 + 0, -INVSQRT2, INVSQRT2, // 5-4 + -INVSQRT2, 0, INVSQRT2, // 4-7 + + INVSQRT2, -INVSQRT2, 0, // 1-5 + INVSQRT2, INVSQRT2, 0, // 6-2 + -INVSQRT2, INVSQRT2, 0, // 3-7 + -INVSQRT2, -INVSQRT2, 0 // 4-0 + }; + return (const Point*)EdgeNormals; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Returns world edge normal + * \param edge_index [in] 0 <= edge index < 12 + * \param world_normal [out] edge normal in world space + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBB::ComputeWorldEdgeNormal(udword edge_index, Point& world_normal) const +{ + ASSERT(edge_index<12); + world_normal = GetLocalEdgeNormals()[edge_index] * mRot; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes an LSS surrounding the OBB. + * \param lss [out] the LSS + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBB::ComputeLSS(LSS& lss) const +{ + Point Axis0 = mRot[0]; + Point Axis1 = mRot[1]; + Point Axis2 = mRot[2]; + + switch(mExtents.LargestAxis()) + { + case 0: + lss.mRadius = (mExtents.y + mExtents.z)*0.5f; + lss.mP0 = mCenter + Axis0 * (mExtents.x - lss.mRadius); + lss.mP1 = mCenter - Axis0 * (mExtents.x - lss.mRadius); + break; + case 1: + lss.mRadius = (mExtents.x + mExtents.z)*0.5f; + lss.mP0 = mCenter + Axis1 * (mExtents.y - lss.mRadius); + lss.mP1 = mCenter - Axis1 * (mExtents.y - lss.mRadius); + break; + case 2: + lss.mRadius = (mExtents.x + mExtents.y)*0.5f; + lss.mP0 = mCenter + Axis2 * (mExtents.z - lss.mRadius); + lss.mP1 = mCenter - Axis2 * (mExtents.z - lss.mRadius); + break; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the OBB is inside another OBB. + * \param box [in] the other OBB + * \return TRUE if we're inside the other box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL OBB::IsInside(const OBB& box) const +{ + // Make a 4x4 from the box & inverse it + Matrix4x4 M0Inv; + { + Matrix4x4 M0 = box.mRot; + M0.SetTrans(box.mCenter); + InvertPRMatrix(M0Inv, M0); + } + + // With our inversed 4x4, create box1 in space of box0 + OBB _1in0; + Rotate(M0Inv, _1in0); + + // This should cancel out box0's rotation, i.e. it's now an AABB. + // => Center(0,0,0), Rot(identity) + + // The two boxes are in the same space so now we can compare them. + + // Create the AABB of (box1 in space of box0) + const Matrix3x3& mtx = _1in0.mRot; + + float f = fabsf(mtx.m[0][0] * mExtents.x) + fabsf(mtx.m[1][0] * mExtents.y) + fabsf(mtx.m[2][0] * mExtents.z) - box.mExtents.x; + if(f > _1in0.mCenter.x) return FALSE; + if(-f < _1in0.mCenter.x) return FALSE; + + f = fabsf(mtx.m[0][1] * mExtents.x) + fabsf(mtx.m[1][1] * mExtents.y) + fabsf(mtx.m[2][1] * mExtents.z) - box.mExtents.y; + if(f > _1in0.mCenter.y) return FALSE; + if(-f < _1in0.mCenter.y) return FALSE; + + f = fabsf(mtx.m[0][2] * mExtents.x) + fabsf(mtx.m[1][2] * mExtents.y) + fabsf(mtx.m[2][2] * mExtents.z) - box.mExtents.z; + if(f > _1in0.mCenter.z) return FALSE; + if(-f < _1in0.mCenter.z) return FALSE; + + return TRUE; +} diff --git a/Extras/CDTestFramework/Opcode/Ice/IceOBB.h b/Extras/CDTestFramework/Opcode/Ice/IceOBB.h new file mode 100644 index 0000000..28ad400 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceOBB.h @@ -0,0 +1,193 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains OBB-related code. (oriented bounding box) + * \file IceOBB.h + * \author Pierre Terdiman + * \date January, 13, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEOBB_H__ +#define __ICEOBB_H__ + + // Forward declarations + class LSS; + + class ICEMATHS_API OBB + { + public: + //! Constructor + inline_ OBB() {} + //! Constructor + inline_ OBB(const Point& center, const Point& extents, const Matrix3x3& rot) : mCenter(center), mExtents(extents), mRot(rot) {} + //! Destructor + inline_ ~OBB() {} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an empty OBB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetEmpty() + { + mCenter.Zero(); + mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); + mRot.Identity(); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a point is contained within the OBB. + * \param p [in] the world point to test + * \return true if inside the OBB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool ContainsPoint(const Point& p) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Builds an OBB from an AABB and a world transform. + * \param aabb [in] the aabb + * \param mat [in] the world transform + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Create(const AABB& aabb, const Matrix4x4& mat); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Recomputes the OBB after an arbitrary transform by a 4x4 matrix. + * \param mtx [in] the transform matrix + * \param obb [out] the transformed OBB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void Rotate(const Matrix4x4& mtx, OBB& obb) const + { + // The extents remain constant + obb.mExtents = mExtents; + // The center gets x-formed + obb.mCenter = mCenter * mtx; + // Combine rotations + obb.mRot = mRot * Matrix3x3(mtx); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the OBB is valid. + * \return true if the box is valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsValid() const + { + // Consistency condition for (Center, Extents) boxes: Extents >= 0.0f + if(mExtents.x < 0.0f) return FALSE; + if(mExtents.y < 0.0f) return FALSE; + if(mExtents.z < 0.0f) return FALSE; + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the obb planes. + * \param planes [out] 6 box planes + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool ComputePlanes(Plane* planes) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the obb points. + * \param pts [out] 8 box points + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool ComputePoints(Point* pts) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes vertex normals. + * \param pts [out] 8 box points + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool ComputeVertexNormals(Point* pts) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Returns edges. + * \return 24 indices (12 edges) indexing the list returned by ComputePoints() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + const udword* GetEdges() const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Returns local edge normals. + * \return edge normals in local space + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + const Point* GetLocalEdgeNormals() const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Returns world edge normal + * \param edge_index [in] 0 <= edge index < 12 + * \param world_normal [out] edge normal in world space + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void ComputeWorldEdgeNormal(udword edge_index, Point& world_normal) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes an LSS surrounding the OBB. + * \param lss [out] the LSS + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void ComputeLSS(LSS& lss) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the OBB is inside another OBB. + * \param box [in] the other OBB + * \return TRUE if we're inside the other box + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + BOOL IsInside(const OBB& box) const; + + inline_ const Point& GetCenter() const { return mCenter; } + inline_ const Point& GetExtents() const { return mExtents; } + inline_ const Matrix3x3& GetRot() const { return mRot; } + + inline_ void GetRotatedExtents(Matrix3x3& extents) const + { + extents = mRot; + extents.Scale(mExtents); + } + + Point mCenter; //!< B for Box + Point mExtents; //!< B for Bounding + Matrix3x3 mRot; //!< O for Oriented + + // Orientation is stored in row-major format, + // i.e. rows = eigen vectors of the covariance matrix + }; + +#endif // __ICEOBB_H__ diff --git a/Extras/CDTestFramework/Opcode/Ice/IcePairs.h b/Extras/CDTestFramework/Opcode/Ice/IcePairs.h new file mode 100644 index 0000000..6817c33 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IcePairs.h @@ -0,0 +1,61 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a simple pair class. + * \file IcePairs.h + * \author Pierre Terdiman + * \date January, 13, 2003 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEPAIRS_H__ +#define __ICEPAIRS_H__ + + //! A generic couple structure + struct ICECORE_API Pair + { + inline_ Pair() {} + inline_ Pair(udword i0, udword i1) : id0(i0), id1(i1) {} + + udword id0; //!< First index of the pair + udword id1; //!< Second index of the pair + }; + + class ICECORE_API Pairs : private Container + { + public: + // Constructor / Destructor + Pairs() {} + ~Pairs() {} + + inline_ udword GetNbPairs() const { return GetNbEntries()>>1; } + inline_ const Pair* GetPairs() const { return (const Pair*)GetEntries(); } + inline_ const Pair* GetPair(udword i) const { return (const Pair*)&GetEntries()[i+i]; } + + inline_ BOOL HasPairs() const { return IsNotEmpty(); } + + inline_ void ResetPairs() { Reset(); } + inline_ void DeleteLastPair() { DeleteLastEntry(); DeleteLastEntry(); } + + inline_ void AddPair(const Pair& p) { Add(p.id0).Add(p.id1); } + inline_ void AddPair(udword id0, udword id1) { Add(id0).Add(id1); } + }; + +#endif // __ICEPAIRS_H__ diff --git a/Extras/CDTestFramework/Opcode/Ice/IcePlane.cpp b/Extras/CDTestFramework/Opcode/Ice/IcePlane.cpp new file mode 100644 index 0000000..b7fe652 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IcePlane.cpp @@ -0,0 +1,61 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for planes. + * \file IcePlane.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Plane class. + * \class Plane + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the plane equation from 3 points. + * \param p0 [in] first point + * \param p1 [in] second point + * \param p2 [in] third point + * \return Self-reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Plane& Plane::Set(const Point& p0, const Point& p1, const Point& p2) +{ + Point Edge0 = p1 - p0; + Point Edge1 = p2 - p0; + + n = Edge0 ^ Edge1; + n.Normalize(); + + d = -(p0 | n); + + return *this; +} diff --git a/Extras/CDTestFramework/Opcode/Ice/IcePlane.h b/Extras/CDTestFramework/Opcode/Ice/IcePlane.h new file mode 100644 index 0000000..1f3669b --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IcePlane.h @@ -0,0 +1,129 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for planes. + * \file IcePlane.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEPLANE_H__ +#define __ICEPLANE_H__ + + #define PLANE_EPSILON (1.0e-7f) + + class ICEMATHS_API Plane + { + public: + //! Constructor + inline_ Plane() { } + //! Constructor from a normal and a distance + inline_ Plane(float nx, float ny, float nz, float d) { Set(nx, ny, nz, d); } + //! Constructor from a point on the plane and a normal + inline_ Plane(const Point& p, const Point& n) { Set(p, n); } + //! Constructor from three points + inline_ Plane(const Point& p0, const Point& p1, const Point& p2) { Set(p0, p1, p2); } + //! Constructor from a normal and a distance + inline_ Plane(const Point& _n, float _d) { n = _n; d = _d; } + //! Copy constructor + inline_ Plane(const Plane& plane) : n(plane.n), d(plane.d) { } + //! Destructor + inline_ ~Plane() { } + + inline_ Plane& Zero() { n.Zero(); d = 0.0f; return *this; } + inline_ Plane& Set(float nx, float ny, float nz, float _d) { n.Set(nx, ny, nz); d = _d; return *this; } + inline_ Plane& Set(const Point& p, const Point& _n) { n = _n; d = - p | _n; return *this; } + Plane& Set(const Point& p0, const Point& p1, const Point& p2); + + inline_ float Distance(const Point& p) const { return (p | n) + d; } + inline_ bool Belongs(const Point& p) const { return fabsf(Distance(p)) < PLANE_EPSILON; } + + inline_ void Normalize() + { + float Denom = 1.0f / n.Magnitude(); + n.x *= Denom; + n.y *= Denom; + n.z *= Denom; + d *= Denom; + } + public: + // Members + Point n; //!< The normal to the plane + float d; //!< The distance from the origin + + // Cast operators + inline_ operator Point() const { return n; } + inline_ operator HPoint() const { return HPoint(n, d); } + + // Arithmetic operators + inline_ Plane operator*(const Matrix4x4& m) const + { + // Old code from Irion. Kept for reference. + Plane Ret(*this); + return Ret *= m; + } + + inline_ Plane& operator*=(const Matrix4x4& m) + { + // Old code from Irion. Kept for reference. + Point n2 = HPoint(n, 0.0f) * m; + d = -((Point) (HPoint( -d*n, 1.0f ) * m) | n2); + n = n2; + return *this; + } + }; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Transforms a plane by a 4x4 matrix. Same as Plane * Matrix4x4 operator, but faster. + * \param transformed [out] transformed plane + * \param plane [in] source plane + * \param transform [in] transform matrix + * \warning the plane normal must be unit-length + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void TransformPlane(Plane& transformed, const Plane& plane, const Matrix4x4& transform) + { + // Rotate the normal using the rotation part of the 4x4 matrix + transformed.n = plane.n * Matrix3x3(transform); + + // Compute new d + transformed.d = plane.d - (Point(transform.GetTrans())|transformed.n); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Transforms a plane by a 4x4 matrix. Same as Plane * Matrix4x4 operator, but faster. + * \param plane [in/out] source plane (transformed on return) + * \param transform [in] transform matrix + * \warning the plane normal must be unit-length + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void TransformPlane(Plane& plane, const Matrix4x4& transform) + { + // Rotate the normal using the rotation part of the 4x4 matrix + plane.n *= Matrix3x3(transform); + + // Compute new d + plane.d -= Point(transform.GetTrans())|plane.n; + } + +#endif // __ICEPLANE_H__ diff --git a/Extras/CDTestFramework/Opcode/Ice/IcePoint.cpp b/Extras/CDTestFramework/Opcode/Ice/IcePoint.cpp new file mode 100644 index 0000000..5fcbd52 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IcePoint.cpp @@ -0,0 +1,209 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 3D vectors. + * \file IcePoint.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * 3D point. + * + * The name is "Point" instead of "Vector" since a vector is N-dimensional, whereas a point is an implicit "vector of dimension 3". + * So the choice was between "Point" and "Vector3", the first one looked better (IMHO). + * + * Some people, then, use a typedef to handle both points & vectors using the same class: typedef Point Vector3; + * This is bad since it opens the door to a lot of confusion while reading the code. I know it may sounds weird but check this out: + * + * \code + * Point P0,P1 = some 3D points; + * Point Delta = P1 - P0; + * \endcode + * + * This compiles fine, although you should have written: + * + * \code + * Point P0,P1 = some 3D points; + * Vector3 Delta = P1 - P0; + * \endcode + * + * Subtle things like this are not caught at compile-time, and when you find one in the code, you never know whether it's a mistake + * from the author or something you don't get. + * + * One way to handle it at compile-time would be to use different classes for Point & Vector3, only overloading operator "-" for vectors. + * But then, you get a lot of redundant code in thoses classes, and basically it's really a lot of useless work. + * + * Another way would be to use homogeneous points: w=1 for points, w=0 for vectors. That's why the HPoint class exists. Now, to store + * your model's vertices and in most cases, you really want to use Points to save ram. + * + * \class Point + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Creates a positive unit random vector. + * \return Self-reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Point& Point::PositiveUnitRandomVector() +{ + x = UnitRandomFloat(); + y = UnitRandomFloat(); + z = UnitRandomFloat(); + Normalize(); + return *this; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Creates a unit random vector. + * \return Self-reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Point& Point::UnitRandomVector() +{ + x = UnitRandomFloat() - 0.5f; + y = UnitRandomFloat() - 0.5f; + z = UnitRandomFloat() - 0.5f; + Normalize(); + return *this; +} + +// Cast operator +// WARNING: not inlined +Point::operator HPoint() const { return HPoint(x, y, z, 0.0f); } + +Point& Point::Refract(const Point& eye, const Point& n, float refractindex, Point& refracted) +{ + // Point EyePt = eye position + // Point p = current vertex + // Point n = vertex normal + // Point rv = refracted vector + // Eye vector - doesn't need to be normalized + Point Env; + Env.x = eye.x - x; + Env.y = eye.y - y; + Env.z = eye.z - z; + + float NDotE = n|Env; + float NDotN = n|n; + NDotE /= refractindex; + + // Refracted vector + refracted = n*NDotE - Env*NDotN; + + return *this; +} + +Point& Point::ProjectToPlane(const Plane& p) +{ + *this-= (p.d + (*this|p.n))*p.n; + return *this; +} + +void Point::ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const +{ + projected = HPoint(x, y, z, 1.0f) * mat; + projected.w = 1.0f / projected.w; + + projected.x*=projected.w; + projected.y*=projected.w; + projected.z*=projected.w; + + projected.x *= halfrenderwidth; projected.x += halfrenderwidth; + projected.y *= -halfrenderheight; projected.y += halfrenderheight; +} + +void Point::SetNotUsed() +{ + // We use a particular integer pattern : 0xffffffff everywhere. This is a NAN. + IR(x) = 0xffffffff; + IR(y) = 0xffffffff; + IR(z) = 0xffffffff; +} + +BOOL Point::IsNotUsed() const +{ + if(IR(x)!=0xffffffff) return FALSE; + if(IR(y)!=0xffffffff) return FALSE; + if(IR(z)!=0xffffffff) return FALSE; + return TRUE; +} + +Point& Point::Mult(const Matrix3x3& mat, const Point& a) +{ + x = a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2]; + y = a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2]; + z = a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2]; + return *this; +} + +Point& Point::Mult2(const Matrix3x3& mat1, const Point& a1, const Matrix3x3& mat2, const Point& a2) +{ + x = a1.x * mat1.m[0][0] + a1.y * mat1.m[0][1] + a1.z * mat1.m[0][2] + a2.x * mat2.m[0][0] + a2.y * mat2.m[0][1] + a2.z * mat2.m[0][2]; + y = a1.x * mat1.m[1][0] + a1.y * mat1.m[1][1] + a1.z * mat1.m[1][2] + a2.x * mat2.m[1][0] + a2.y * mat2.m[1][1] + a2.z * mat2.m[1][2]; + z = a1.x * mat1.m[2][0] + a1.y * mat1.m[2][1] + a1.z * mat1.m[2][2] + a2.x * mat2.m[2][0] + a2.y * mat2.m[2][1] + a2.z * mat2.m[2][2]; + return *this; +} + +Point& Point::Mac(const Matrix3x3& mat, const Point& a) +{ + x += a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2]; + y += a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2]; + z += a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2]; + return *this; +} + +Point& Point::TransMult(const Matrix3x3& mat, const Point& a) +{ + x = a.x * mat.m[0][0] + a.y * mat.m[1][0] + a.z * mat.m[2][0]; + y = a.x * mat.m[0][1] + a.y * mat.m[1][1] + a.z * mat.m[2][1]; + z = a.x * mat.m[0][2] + a.y * mat.m[1][2] + a.z * mat.m[2][2]; + return *this; +} + +Point& Point::Transform(const Point& r, const Matrix3x3& rotpos, const Point& linpos) +{ + x = r.x * rotpos.m[0][0] + r.y * rotpos.m[0][1] + r.z * rotpos.m[0][2] + linpos.x; + y = r.x * rotpos.m[1][0] + r.y * rotpos.m[1][1] + r.z * rotpos.m[1][2] + linpos.y; + z = r.x * rotpos.m[2][0] + r.y * rotpos.m[2][1] + r.z * rotpos.m[2][2] + linpos.z; + return *this; +} + +Point& Point::InvTransform(const Point& r, const Matrix3x3& rotpos, const Point& linpos) +{ + float sx = r.x - linpos.x; + float sy = r.y - linpos.y; + float sz = r.z - linpos.z; + x = sx * rotpos.m[0][0] + sy * rotpos.m[1][0] + sz * rotpos.m[2][0]; + y = sx * rotpos.m[0][1] + sy * rotpos.m[1][1] + sz * rotpos.m[2][1]; + z = sx * rotpos.m[0][2] + sy * rotpos.m[1][2] + sz * rotpos.m[2][2]; + return *this; +} diff --git a/Extras/CDTestFramework/Opcode/Ice/IcePoint.h b/Extras/CDTestFramework/Opcode/Ice/IcePoint.h new file mode 100644 index 0000000..a5b372b --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IcePoint.h @@ -0,0 +1,544 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 3D vectors. + * \file IcePoint.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEPOINT_H__ +#define __ICEPOINT_H__ + + // Forward declarations + class HPoint; + class Plane; + class Matrix3x3; + class Matrix4x4; + + #define CROSS2D(a, b) (a.x*b.y - b.x*a.y) + + const float EPSILON2 = 1.0e-20f; + + class ICEMATHS_API Point + { + public: + + //! Empty constructor + inline_ Point() {} + //! Constructor from a single float +// inline_ Point(float val) : x(val), y(val), z(val) {} +// Removed since it introduced the nasty "Point T = *Matrix4x4.GetTrans();" bug....... + //! Constructor from floats + inline_ Point(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {} + //! Constructor from array + inline_ Point(const float f[3]) : x(f[_X]), y(f[_Y]), z(f[_Z]) {} + //! Copy constructor + inline_ Point(const Point& p) : x(p.x), y(p.y), z(p.z) {} + //! Destructor + inline_ ~Point() {} + + //! Clears the vector + inline_ Point& Zero() { x = y = z = 0.0f; return *this; } + + //! + infinity + inline_ Point& SetPlusInfinity() { x = y = z = MAX_FLOAT; return *this; } + //! - infinity + inline_ Point& SetMinusInfinity() { x = y = z = MIN_FLOAT; return *this; } + + //! Sets positive unit random vector + Point& PositiveUnitRandomVector(); + //! Sets unit random vector + Point& UnitRandomVector(); + + //! Assignment from values + inline_ Point& Set(float _x, float _y, float _z) { x = _x; y = _y; z = _z; return *this; } + //! Assignment from array + inline_ Point& Set(const float f[3]) { x = f[_X]; y = f[_Y]; z = f[_Z]; return *this; } + //! Assignment from another point + inline_ Point& Set(const Point& src) { x = src.x; y = src.y; z = src.z; return *this; } + + //! Adds a vector + inline_ Point& Add(const Point& p) { x += p.x; y += p.y; z += p.z; return *this; } + //! Adds a vector + inline_ Point& Add(float _x, float _y, float _z) { x += _x; y += _y; z += _z; return *this; } + //! Adds a vector + inline_ Point& Add(const float f[3]) { x += f[_X]; y += f[_Y]; z += f[_Z]; return *this; } + //! Adds vectors + inline_ Point& Add(const Point& p, const Point& q) { x = p.x+q.x; y = p.y+q.y; z = p.z+q.z; return *this; } + + //! Subtracts a vector + inline_ Point& Sub(const Point& p) { x -= p.x; y -= p.y; z -= p.z; return *this; } + //! Subtracts a vector + inline_ Point& Sub(float _x, float _y, float _z) { x -= _x; y -= _y; z -= _z; return *this; } + //! Subtracts a vector + inline_ Point& Sub(const float f[3]) { x -= f[_X]; y -= f[_Y]; z -= f[_Z]; return *this; } + //! Subtracts vectors + inline_ Point& Sub(const Point& p, const Point& q) { x = p.x-q.x; y = p.y-q.y; z = p.z-q.z; return *this; } + + //! this = -this + inline_ Point& Neg() { x = -x; y = -y; z = -z; return *this; } + //! this = -a + inline_ Point& Neg(const Point& a) { x = -a.x; y = -a.y; z = -a.z; return *this; } + + //! Multiplies by a scalar + inline_ Point& Mult(float s) { x *= s; y *= s; z *= s; return *this; } + + //! this = a * scalar + inline_ Point& Mult(const Point& a, float scalar) + { + x = a.x * scalar; + y = a.y * scalar; + z = a.z * scalar; + return *this; + } + + //! this = a + b * scalar + inline_ Point& Mac(const Point& a, const Point& b, float scalar) + { + x = a.x + b.x * scalar; + y = a.y + b.y * scalar; + z = a.z + b.z * scalar; + return *this; + } + + //! this = this + a * scalar + inline_ Point& Mac(const Point& a, float scalar) + { + x += a.x * scalar; + y += a.y * scalar; + z += a.z * scalar; + return *this; + } + + //! this = a - b * scalar + inline_ Point& Msc(const Point& a, const Point& b, float scalar) + { + x = a.x - b.x * scalar; + y = a.y - b.y * scalar; + z = a.z - b.z * scalar; + return *this; + } + + //! this = this - a * scalar + inline_ Point& Msc(const Point& a, float scalar) + { + x -= a.x * scalar; + y -= a.y * scalar; + z -= a.z * scalar; + return *this; + } + + //! this = a + b * scalarb + c * scalarc + inline_ Point& Mac2(const Point& a, const Point& b, float scalarb, const Point& c, float scalarc) + { + x = a.x + b.x * scalarb + c.x * scalarc; + y = a.y + b.y * scalarb + c.y * scalarc; + z = a.z + b.z * scalarb + c.z * scalarc; + return *this; + } + + //! this = a - b * scalarb - c * scalarc + inline_ Point& Msc2(const Point& a, const Point& b, float scalarb, const Point& c, float scalarc) + { + x = a.x - b.x * scalarb - c.x * scalarc; + y = a.y - b.y * scalarb - c.y * scalarc; + z = a.z - b.z * scalarb - c.z * scalarc; + return *this; + } + + //! this = mat * a + inline_ Point& Mult(const Matrix3x3& mat, const Point& a); + + //! this = mat1 * a1 + mat2 * a2 + inline_ Point& Mult2(const Matrix3x3& mat1, const Point& a1, const Matrix3x3& mat2, const Point& a2); + + //! this = this + mat * a + inline_ Point& Mac(const Matrix3x3& mat, const Point& a); + + //! this = transpose(mat) * a + inline_ Point& TransMult(const Matrix3x3& mat, const Point& a); + + //! Linear interpolate between two vectors: this = a + t * (b - a) + inline_ Point& Lerp(const Point& a, const Point& b, float t) + { + x = a.x + t * (b.x - a.x); + y = a.y + t * (b.y - a.y); + z = a.z + t * (b.z - a.z); + return *this; + } + + //! Hermite interpolate between p1 and p2. p0 and p3 are used for finding gradient at p1 and p2. + //! this = p0 * (2t^2 - t^3 - t)/2 + //! + p1 * (3t^3 - 5t^2 + 2)/2 + //! + p2 * (4t^2 - 3t^3 + t)/2 + //! + p3 * (t^3 - t^2)/2 + inline_ Point& Herp(const Point& p0, const Point& p1, const Point& p2, const Point& p3, float t) + { + float t2 = t * t; + float t3 = t2 * t; + float kp0 = (2.0f * t2 - t3 - t) * 0.5f; + float kp1 = (3.0f * t3 - 5.0f * t2 + 2.0f) * 0.5f; + float kp2 = (4.0f * t2 - 3.0f * t3 + t) * 0.5f; + float kp3 = (t3 - t2) * 0.5f; + x = p0.x * kp0 + p1.x * kp1 + p2.x * kp2 + p3.x * kp3; + y = p0.y * kp0 + p1.y * kp1 + p2.y * kp2 + p3.y * kp3; + z = p0.z * kp0 + p1.z * kp1 + p2.z * kp2 + p3.z * kp3; + return *this; + } + + //! this = rotpos * r + linpos + inline_ Point& Transform(const Point& r, const Matrix3x3& rotpos, const Point& linpos); + + //! this = trans(rotpos) * (r - linpos) + inline_ Point& InvTransform(const Point& r, const Matrix3x3& rotpos, const Point& linpos); + + //! Returns MIN(x, y, z); + inline_ float Min() const { return MIN(x, MIN(y, z)); } + //! Returns MAX(x, y, z); + inline_ float Max() const { return MAX(x, MAX(y, z)); } + //! Sets each element to be componentwise minimum + inline_ Point& Min(const Point& p) { x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z); return *this; } + //! Sets each element to be componentwise maximum + inline_ Point& Max(const Point& p) { x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z); return *this; } + + //! Clamps each element + inline_ Point& Clamp(float min, float max) + { + if(xmax) x=max; + if(ymax) y=max; + if(zmax) z=max; + return *this; + } + + //! Computes square magnitude + inline_ float SquareMagnitude() const { return x*x + y*y + z*z; } + //! Computes magnitude + inline_ float Magnitude() const { return sqrtf(x*x + y*y + z*z); } + //! Computes volume + inline_ float Volume() const { return x * y * z; } + + //! Checks the point is near zero + inline_ bool ApproxZero() const { return SquareMagnitude() < EPSILON2; } + + //! Tests for exact zero vector + inline_ BOOL IsZero() const + { + if(IR(x) || IR(y) || IR(z)) return FALSE; + return TRUE; + } + + //! Checks point validity + inline_ BOOL IsValid() const + { + if(!IsValidFloat(x)) return FALSE; + if(!IsValidFloat(y)) return FALSE; + if(!IsValidFloat(z)) return FALSE; + return TRUE; + } + + //! Slighty moves the point + void Tweak(udword coord_mask, udword tweak_mask) + { + if(coord_mask&1) { udword Dummy = IR(x); Dummy^=tweak_mask; x = FR(Dummy); } + if(coord_mask&2) { udword Dummy = IR(y); Dummy^=tweak_mask; y = FR(Dummy); } + if(coord_mask&4) { udword Dummy = IR(z); Dummy^=tweak_mask; z = FR(Dummy); } + } + + #define TWEAKMASK 0x3fffff + #define TWEAKNOTMASK ~TWEAKMASK + //! Slighty moves the point out + inline_ void TweakBigger() + { + udword Dummy = (IR(x)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(x)) Dummy+=TWEAKMASK+1; x = FR(Dummy); + Dummy = (IR(y)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(y)) Dummy+=TWEAKMASK+1; y = FR(Dummy); + Dummy = (IR(z)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(z)) Dummy+=TWEAKMASK+1; z = FR(Dummy); + } + + //! Slighty moves the point in + inline_ void TweakSmaller() + { + udword Dummy = (IR(x)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(x)) Dummy+=TWEAKMASK+1; x = FR(Dummy); + Dummy = (IR(y)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(y)) Dummy+=TWEAKMASK+1; y = FR(Dummy); + Dummy = (IR(z)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(z)) Dummy+=TWEAKMASK+1; z = FR(Dummy); + } + + //! Normalizes the vector + inline_ Point& Normalize() + { + float M = x*x + y*y + z*z; + if(M) + { + M = 1.0f / sqrtf(M); + x *= M; + y *= M; + z *= M; + } + return *this; + } + + //! Sets vector length + inline_ Point& SetLength(float length) + { + float NewLength = length / Magnitude(); + x *= NewLength; + y *= NewLength; + z *= NewLength; + return *this; + } + + //! Clamps vector length + inline_ Point& ClampLength(float limit_length) + { + if(limit_length>=0.0f) // Magnitude must be positive + { + float CurrentSquareLength = SquareMagnitude(); + + if(CurrentSquareLength > limit_length * limit_length) + { + float Coeff = limit_length / sqrtf(CurrentSquareLength); + x *= Coeff; + y *= Coeff; + z *= Coeff; + } + } + return *this; + } + + //! Computes distance to another point + inline_ float Distance(const Point& b) const + { + return sqrtf((x - b.x)*(x - b.x) + (y - b.y)*(y - b.y) + (z - b.z)*(z - b.z)); + } + + //! Computes square distance to another point + inline_ float SquareDistance(const Point& b) const + { + return ((x - b.x)*(x - b.x) + (y - b.y)*(y - b.y) + (z - b.z)*(z - b.z)); + } + + //! Dot product dp = this|a + inline_ float Dot(const Point& p) const { return p.x * x + p.y * y + p.z * z; } + + //! Cross product this = a x b + inline_ Point& Cross(const Point& a, const Point& b) + { + x = a.y * b.z - a.z * b.y; + y = a.z * b.x - a.x * b.z; + z = a.x * b.y - a.y * b.x; + return *this; + } + + //! Vector code ( bitmask = sign(z) | sign(y) | sign(x) ) + inline_ udword VectorCode() const + { + return (IR(x)>>31) | ((IR(y)&SIGN_BITMASK)>>30) | ((IR(z)&SIGN_BITMASK)>>29); + } + + //! Returns largest axis + inline_ PointComponent LargestAxis() const + { + const float* Vals = &x; + PointComponent m = _X; + if(Vals[_Y] > Vals[m]) m = _Y; + if(Vals[_Z] > Vals[m]) m = _Z; + return m; + } + + //! Returns closest axis + inline_ PointComponent ClosestAxis() const + { + const float* Vals = &x; + PointComponent m = _X; + if(AIR(Vals[_Y]) > AIR(Vals[m])) m = _Y; + if(AIR(Vals[_Z]) > AIR(Vals[m])) m = _Z; + return m; + } + + //! Returns smallest axis + inline_ PointComponent SmallestAxis() const + { + const float* Vals = &x; + PointComponent m = _X; + if(Vals[_Y] < Vals[m]) m = _Y; + if(Vals[_Z] < Vals[m]) m = _Z; + return m; + } + + //! Refracts the point + Point& Refract(const Point& eye, const Point& n, float refractindex, Point& refracted); + + //! Projects the point onto a plane + Point& ProjectToPlane(const Plane& p); + + //! Projects the point onto the screen + void ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const; + + //! Unfolds the point onto a plane according to edge(a,b) + Point& Unfold(Plane& p, Point& a, Point& b); + + //! Hash function from Ville Miettinen + inline_ udword GetHashValue() const + { + const udword* h = (const udword*)(this); + udword f = (h[0]+h[1]*11-(h[2]*17)) & 0x7fffffff; // avoid problems with +-0 + return (f>>22)^(f>>12)^(f); + } + + //! Stuff magic values in the point, marking it as explicitely not used. + void SetNotUsed(); + //! Checks the point is marked as not used + BOOL IsNotUsed() const; + + // Arithmetic operators + + //! Unary operator for Point Negate = - Point + inline_ Point operator-() const { return Point(-x, -y, -z); } + + //! Operator for Point Plus = Point + Point. + inline_ Point operator+(const Point& p) const { return Point(x + p.x, y + p.y, z + p.z); } + //! Operator for Point Minus = Point - Point. + inline_ Point operator-(const Point& p) const { return Point(x - p.x, y - p.y, z - p.z); } + + //! Operator for Point Mul = Point * Point. + inline_ Point operator*(const Point& p) const { return Point(x * p.x, y * p.y, z * p.z); } + //! Operator for Point Scale = Point * float. + inline_ Point operator*(float s) const { return Point(x * s, y * s, z * s ); } + //! Operator for Point Scale = float * Point. + inline_ friend Point operator*(float s, const Point& p) { return Point(s * p.x, s * p.y, s * p.z); } + + //! Operator for Point Div = Point / Point. + inline_ Point operator/(const Point& p) const { return Point(x / p.x, y / p.y, z / p.z); } + //! Operator for Point Scale = Point / float. + inline_ Point operator/(float s) const { s = 1.0f / s; return Point(x * s, y * s, z * s); } + //! Operator for Point Scale = float / Point. + inline_ friend Point operator/(float s, const Point& p) { return Point(s / p.x, s / p.y, s / p.z); } + + //! Operator for float DotProd = Point | Point. + inline_ float operator|(const Point& p) const { return x*p.x + y*p.y + z*p.z; } + //! Operator for Point VecProd = Point ^ Point. + inline_ Point operator^(const Point& p) const + { + return Point( + y * p.z - z * p.y, + z * p.x - x * p.z, + x * p.y - y * p.x ); + } + + //! Operator for Point += Point. + inline_ Point& operator+=(const Point& p) { x += p.x; y += p.y; z += p.z; return *this; } + //! Operator for Point += float. + inline_ Point& operator+=(float s) { x += s; y += s; z += s; return *this; } + + //! Operator for Point -= Point. + inline_ Point& operator-=(const Point& p) { x -= p.x; y -= p.y; z -= p.z; return *this; } + //! Operator for Point -= float. + inline_ Point& operator-=(float s) { x -= s; y -= s; z -= s; return *this; } + + //! Operator for Point *= Point. + inline_ Point& operator*=(const Point& p) { x *= p.x; y *= p.y; z *= p.z; return *this; } + //! Operator for Point *= float. + inline_ Point& operator*=(float s) { x *= s; y *= s; z *= s; return *this; } + + //! Operator for Point /= Point. + inline_ Point& operator/=(const Point& p) { x /= p.x; y /= p.y; z /= p.z; return *this; } + //! Operator for Point /= float. + inline_ Point& operator/=(float s) { s = 1.0f/s; x *= s; y *= s; z *= s; return *this; } + + // Logical operators + + //! Operator for "if(Point==Point)" + inline_ bool operator==(const Point& p) const { return ( (IR(x)==IR(p.x))&&(IR(y)==IR(p.y))&&(IR(z)==IR(p.z))); } + //! Operator for "if(Point!=Point)" + inline_ bool operator!=(const Point& p) const { return ( (IR(x)!=IR(p.x))||(IR(y)!=IR(p.y))||(IR(z)!=IR(p.z))); } + + // Arithmetic operators + + //! Operator for Point Mul = Point * Matrix3x3. + inline_ Point operator*(const Matrix3x3& mat) const + { + class ShadowMatrix3x3{ public: float m[3][3]; }; // To allow inlining + const ShadowMatrix3x3* Mat = (const ShadowMatrix3x3*)&mat; + + return Point( + x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0], + x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1], + x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] ); + } + + //! Operator for Point Mul = Point * Matrix4x4. + inline_ Point operator*(const Matrix4x4& mat) const + { + class ShadowMatrix4x4{ public: float m[4][4]; }; // To allow inlining + const ShadowMatrix4x4* Mat = (const ShadowMatrix4x4*)&mat; + + return Point( + x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0] + Mat->m[3][0], + x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1] + Mat->m[3][1], + x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] + Mat->m[3][2]); + } + + //! Operator for Point *= Matrix3x3. + inline_ Point& operator*=(const Matrix3x3& mat) + { + class ShadowMatrix3x3{ public: float m[3][3]; }; // To allow inlining + const ShadowMatrix3x3* Mat = (const ShadowMatrix3x3*)&mat; + + float xp = x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0]; + float yp = x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1]; + float zp = x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2]; + + x = xp; y = yp; z = zp; + + return *this; + } + + //! Operator for Point *= Matrix4x4. + inline_ Point& operator*=(const Matrix4x4& mat) + { + class ShadowMatrix4x4{ public: float m[4][4]; }; // To allow inlining + const ShadowMatrix4x4* Mat = (const ShadowMatrix4x4*)&mat; + + float xp = x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0] + Mat->m[3][0]; + float yp = x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1] + Mat->m[3][1]; + float zp = x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] + Mat->m[3][2]; + + x = xp; y = yp; z = zp; + + return *this; + } + + // Cast operators + + //! Cast a Point to a HPoint. w is set to zero. + operator HPoint() const; + + inline_ operator const float*() const { return &x; } + inline_ operator float*() { return &x; } + + public: + float x, y, z; + }; + + FUNCTION ICEMATHS_API void Normalize1(Point& a); + FUNCTION ICEMATHS_API void Normalize2(Point& a); + +#endif //__ICEPOINT_H__ diff --git a/Extras/CDTestFramework/Opcode/Ice/IcePreprocessor.h b/Extras/CDTestFramework/Opcode/Ice/IcePreprocessor.h new file mode 100644 index 0000000..f02501a --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IcePreprocessor.h @@ -0,0 +1,158 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains preprocessor stuff. This should be the first included header. + * \file IcePreprocessor.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef ICEPREPROCESSOR_H +#define ICEPREPROCESSOR_H + + // Check platform + #if defined( _WIN32 ) || defined( WIN32 ) + #pragma message("Compiling on Windows...") + #define PLATFORM_WINDOWS + #else + #pragma message("Compiling on unknown platform...") + #endif + + // Check compiler + #if defined(_MSC_VER) + #pragma message("Compiling with VC++...") + #define COMPILER_VISUAL_CPP + + #if _MSC_VER > 1300 + #pragma message("Compiling with VC7") + #define COMPILER_VC7 + #else + #pragma message("Compiling with VC6") + #define COMPILER_VC6 + #endif + #else + #pragma message("Compiling with unknown compiler...") + #endif + + // Check compiler options. If this file is included in user-apps, this + // shouldn't be needed, so that they can use what they like best. + #ifndef ICE_DONT_CHECK_COMPILER_OPTIONS + #ifdef COMPILER_VISUAL_CPP + #if defined(_CHAR_UNSIGNED) + #endif + + #if defined(_CPPRTTI) + #error Please disable RTTI... + #endif + + #if defined(_CPPUNWIND) + #error Please disable exceptions... + #endif + + #if defined(_MT) + // Multithreading + #endif + #endif + #endif + + // Check debug mode + #ifdef DEBUG // May be defined instead of _DEBUG. Let's fix it. + #ifndef _DEBUG + #define _DEBUG + #endif + #endif + + #ifdef _DEBUG + // Here you may define items for debug builds + #endif + + #ifndef THIS_FILE + #define THIS_FILE __FILE__ + #endif + + #ifndef ICE_NO_DLL + #ifdef ICECORE_EXPORTS + #define ICECORE_API __declspec(dllexport) + #else + #define ICECORE_API __declspec(dllimport) + #endif + #else + #define ICECORE_API + #endif + + #define FUNCTION extern "C" + + // Cosmetic stuff [mainly useful with multiple inheritance] + #define override(base_class) virtual + + // Our own inline keyword, so that: + // - we can switch to __forceinline to check it's really better or not + // - we can remove __forceinline if the compiler doesn't support it +// #define inline_ __forceinline +// #define inline_ inline + + // Contributed by Bruce Mitchener + #if defined(COMPILER_VISUAL_CPP) + #define inline_ __forceinline +// #define inline_ inline + #elif defined(__GNUC__) && __GNUC__ < 3 + #define inline_ inline + #elif defined(__GNUC__) + #define inline_ inline __attribute__ ((always_inline)) + #else + #define inline_ inline + #endif + + // Down the hatch + #pragma inline_depth( 255 ) + + #ifdef COMPILER_VISUAL_CPP + #pragma intrinsic(memcmp) + #pragma intrinsic(memcpy) + #pragma intrinsic(memset) + #pragma intrinsic(strcat) + #pragma intrinsic(strcmp) + #pragma intrinsic(strcpy) + #pragma intrinsic(strlen) + #pragma intrinsic(abs) + #pragma intrinsic(labs) + #endif + + // ANSI compliance + #ifdef _DEBUG + // Remove painful warning in debug + inline_ bool ReturnsFalse(){ return false; } + #define for if(ReturnsFalse()){} else for + #else + #define for if(0){} else for + #endif + + // Don't override new/delete + #define DEFAULT_NEWDELETE + #define DONT_TRACK_MEMORY_LEAKS + + //! Macro used to give me a clue when it crashes in release and only the assembly is available + #define INCLUDE_GUARDIANS + #ifdef INCLUDE_GUARDIANS + #define GUARD(x) \ + { \ + static const char guard_text[] = x; \ + _asm push eax \ + _asm nop \ + _asm nop \ + _asm nop \ + _asm nop \ + _asm lea eax, guard_text \ + _asm nop \ + _asm nop \ + _asm nop \ + _asm nop \ + _asm pop eax \ + } + #else + #define GUARD(x) + #endif + +#endif // ICEPREPROCESSOR_H diff --git a/Extras/CDTestFramework/Opcode/Ice/IceRandom.cpp b/Extras/CDTestFramework/Opcode/Ice/IceRandom.cpp new file mode 100644 index 0000000..93bdd13 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceRandom.cpp @@ -0,0 +1,52 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for random generators. + * \file IceRandom.cpp + * \author Pierre Terdiman + * \date August, 9, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +void IceCore:: SRand(udword seed) +{ + srand(seed); +} + +udword IceCore::Rand() +{ + return rand(); +} + + +static BasicRandom gRandomGenerator(42); + +udword IceCore::GetRandomIndex(udword max_index) +{ + // We don't use rand() since it's limited to RAND_MAX + udword Index = gRandomGenerator.Randomize(); + return Index % max_index; +} + + diff --git a/Extras/CDTestFramework/Opcode/Ice/IceRandom.h b/Extras/CDTestFramework/Opcode/Ice/IceRandom.h new file mode 100644 index 0000000..67c3a9b --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceRandom.h @@ -0,0 +1,58 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for random generators. + * \file IceRandom.h + * \author Pierre Terdiman + * \date August, 9, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICERANDOM_H__ +#define __ICERANDOM_H__ + + FUNCTION ICECORE_API void SRand(udword seed); + FUNCTION ICECORE_API udword Rand(); + + //! Returns a unit random floating-point value + inline_ float UnitRandomFloat() { return float(Rand()) * ONE_OVER_RAND_MAX; } + + //! Returns a random index so that 0<= index < max_index + ICECORE_API udword GetRandomIndex(udword max_index); + + class ICECORE_API BasicRandom + { + public: + + //! Constructor + inline_ BasicRandom(udword seed=0) : mRnd(seed) {} + //! Destructor + inline_ ~BasicRandom() {} + + inline_ void SetSeed(udword seed) { mRnd = seed; } + inline_ udword GetCurrentValue() const { return mRnd; } + inline_ udword Randomize() { mRnd = mRnd * 2147001325 + 715136305; return mRnd; } + + private: + udword mRnd; + }; + +#endif // __ICERANDOM_H__ + diff --git a/Extras/CDTestFramework/Opcode/Ice/IceRay.cpp b/Extras/CDTestFramework/Opcode/Ice/IceRay.cpp new file mode 100644 index 0000000..ce93b91 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceRay.cpp @@ -0,0 +1,100 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for rays. + * \file IceRay.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Ray class. + * A ray is a half-line P(t) = mOrig + mDir * t, with 0 <= t <= +infinity + * \class Ray + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* + O = Origin = impact point + i = normalized vector along the x axis + j = normalized vector along the y axis = actually the normal vector in O + D = Direction vector, norm |D| = 1 + N = Projection of D on y axis, norm |N| = normal reaction + T = Projection of D on x axis, norm |T| = tangential reaction + R = Reflexion vector + + ^y + | + | + | + _ _ _| _ _ _ + * * *| + \ | / + \ |N / | + R\ | /D + \ | / | + \ | / + _________\|/______*_______>x + O T + + Let define theta = angle between D and N. Then cos(theta) = |N| / |D| = |N| since D is normalized. + + j|D = |j|*|D|*cos(theta) => |N| = j|D + + Then we simply have: + + D = N + T + + To compute tangential reaction : + + T = D - N + + To compute reflexion vector : + + R = N - T = N - (D-N) = 2*N - D +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +float Ray::SquareDistance(const Point& point, float* t) const +{ + Point Diff = point - mOrig; + float fT = Diff | mDir; + + if(fT<=0.0f) + { + fT = 0.0f; + } + else + { + fT /= mDir.SquareMagnitude(); + Diff -= fT*mDir; + } + + if(t) *t = fT; + + return Diff.SquareMagnitude(); +} diff --git a/Extras/CDTestFramework/Opcode/Ice/IceRay.h b/Extras/CDTestFramework/Opcode/Ice/IceRay.h new file mode 100644 index 0000000..7ea5773 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceRay.h @@ -0,0 +1,114 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for rays. + * \file IceRay.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICERAY_H__ +#define __ICERAY_H__ + + class ICEMATHS_API Ray + { + public: + //! Constructor + inline_ Ray() {} + //! Constructor + inline_ Ray(const Point& orig, const Point& dir) : mOrig(orig), mDir(dir) {} + //! Copy constructor + inline_ Ray(const Ray& ray) : mOrig(ray.mOrig), mDir(ray.mDir) {} + //! Destructor + inline_ ~Ray() {} + + float SquareDistance(const Point& point, float* t=null) const; + inline_ float Distance(const Point& point, float* t=null) const { return sqrtf(SquareDistance(point, t)); } + + Point mOrig; //!< Ray origin + Point mDir; //!< Normalized direction + }; + + inline_ void ComputeReflexionVector(Point& reflected, const Point& incoming_dir, const Point& outward_normal) + { + reflected = incoming_dir - outward_normal * 2.0f * (incoming_dir|outward_normal); + } + + inline_ void ComputeReflexionVector(Point& reflected, const Point& source, const Point& impact, const Point& normal) + { + Point V = impact - source; + reflected = V - normal * 2.0f * (V|normal); + } + + inline_ void DecomposeVector(Point& normal_compo, Point& tangent_compo, const Point& outward_dir, const Point& outward_normal) + { + normal_compo = outward_normal * (outward_dir|outward_normal); + tangent_compo = outward_dir - normal_compo; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Transforms a direction vector from world space to local space + * \param local_dir [out] direction vector in local space + * \param world_dir [in] direction vector in world space + * \param world [in] world transform + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void ComputeLocalDirection(Point& local_dir, const Point& world_dir, const Matrix4x4& world) + { + // Get world direction back in local space +// Matrix3x3 InvWorld = world; +// local_dir = InvWorld * world_dir; + local_dir = Matrix3x3(world) * world_dir; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Transforms a position vector from world space to local space + * \param local_pt [out] position vector in local space + * \param world_pt [in] position vector in world space + * \param world [in] world transform + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void ComputeLocalPoint(Point& local_pt, const Point& world_pt, const Matrix4x4& world) + { + // Get world vertex back in local space + Matrix4x4 InvWorld = world; + InvWorld.Invert(); + local_pt = world_pt * InvWorld; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Transforms a ray from world space to local space + * \param local_ray [out] ray in local space + * \param world_ray [in] ray in world space + * \param world [in] world transform + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void ComputeLocalRay(Ray& local_ray, const Ray& world_ray, const Matrix4x4& world) + { + // Get world ray back in local space + ComputeLocalDirection(local_ray.mDir, world_ray.mDir, world); + ComputeLocalPoint(local_ray.mOrig, world_ray.mOrig, world); + } + +#endif // __ICERAY_H__ diff --git a/Extras/CDTestFramework/Opcode/Ice/IceRevisitedRadix.cpp b/Extras/CDTestFramework/Opcode/Ice/IceRevisitedRadix.cpp new file mode 100644 index 0000000..3cb3aac --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceRevisitedRadix.cpp @@ -0,0 +1,592 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains source code from the article "Radix Sort Revisited". + * \file IceRevisitedRadix.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Revisited Radix Sort. + * This is my new radix routine: + * - it uses indices and doesn't recopy the values anymore, hence wasting less ram + * - it creates all the histograms in one run instead of four + * - it sorts words faster than dwords and bytes faster than words + * - it correctly sorts negative floating-point values by patching the offsets + * - it automatically takes advantage of temporal coherence + * - multiple keys support is a side effect of temporal coherence + * - it may be worth recoding in asm... (mainly to use FCOMI, FCMOV, etc) [it's probably memory-bound anyway] + * + * History: + * - 08.15.98: very first version + * - 04.04.00: recoded for the radix article + * - 12.xx.00: code lifting + * - 09.18.01: faster CHECK_PASS_VALIDITY thanks to Mark D. Shattuck (who provided other tips, not included here) + * - 10.11.01: added local ram support + * - 01.20.02: bugfix! In very particular cases the last pass was skipped in the float code-path, leading to incorrect sorting...... + * - 01.02.02: - "mIndices" renamed => "mRanks". That's a rank sorter after all. + * - ranks are not "reset" anymore, but implicit on first calls + * - 07.05.02: offsets rewritten with one less indirection. + * - 11.03.02: "bool" replaced with RadixHint enum + * - 07.15.04: stack-based radix added + * - we want to use the radix sort but without making it static, and without allocating anything. + * - we internally allocate two arrays of ranks. Each of them has N udwords to sort N values. + * - 1Mb/2/sizeof(udword) = 131072 values max, at the same time. + * - 09.22.04: - adapted to MacOS by Chris Lamb + * - 01.12.06: - added optimizations suggested by Kyle Hubert + * + * \class RadixSort + * \author Pierre Terdiman + * \version 1.5 + * \date August, 15, 1998 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* +To do: + - add an offset parameter between two input values (avoid some data recopy sometimes) + - unroll ? asm ? + - prefetch stuff the day I have a P3 + - make a version with 16-bits indices ? +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +#define INVALIDATE_RANKS mCurrentSize|=0x80000000 +#define VALIDATE_RANKS mCurrentSize&=0x7fffffff +#define CURRENT_SIZE (mCurrentSize&0x7fffffff) +#define INVALID_RANKS (mCurrentSize&0x80000000) + +#define CHECK_RESIZE(n) \ + if(n!=mPreviousSize) \ + { \ + if(n>mCurrentSize) Resize(n); \ + else ResetRanks(); \ + mPreviousSize = n; \ + } + +#if defined(__APPLE__) || defined(_XBOX) + #define H0_OFFSET 768 + #define H1_OFFSET 512 + #define H2_OFFSET 256 + #define H3_OFFSET 0 + #define BYTES_INC (3-j) +#else + #define H0_OFFSET 0 + #define H1_OFFSET 256 + #define H2_OFFSET 512 + #define H3_OFFSET 768 + #define BYTES_INC j +#endif + +#define CREATE_HISTOGRAMS(type, buffer) \ + /* Clear counters/histograms */ \ + ZeroMemory(mHistogram, 256*4*sizeof(udword)); \ + \ + /* Prepare to count */ \ + const ubyte* p = (const ubyte*)input; \ + const ubyte* pe = &p[nb*4]; \ + udword* h0= &mHistogram[H0_OFFSET]; /* Histogram for first pass (LSB) */ \ + udword* h1= &mHistogram[H1_OFFSET]; /* Histogram for second pass */ \ + udword* h2= &mHistogram[H2_OFFSET]; /* Histogram for third pass */ \ + udword* h3= &mHistogram[H3_OFFSET]; /* Histogram for last pass (MSB) */ \ + \ + bool AlreadySorted = true; /* Optimism... */ \ + \ + if(INVALID_RANKS) \ + { \ + /* Prepare for temporal coherence */ \ + type* Running = (type*)buffer; \ + type PrevVal = *Running; \ + \ + while(p!=pe) \ + { \ + /* Read input buffer in previous sorted order */ \ + type Val = *Running++; \ + /* Check whether already sorted or not */ \ + if(ValCurSize) Resize(nb); + mCurrentSize = nb; + INVALIDATE_RANKS; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Main sort routine. + * This one is for integer values. After the call, mRanks contains a list of indices in sorted order, i.e. in the order you may process your data. + * \param input [in] a list of integer values to sort + * \param nb [in] number of values to sort, must be < 2^31 + * \param hint [in] RADIX_SIGNED to handle negative values, RADIX_UNSIGNED if you know your input buffer only contains positive values + * \return Self-Reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +RadixSort& RadixSort::Sort(const udword* input, udword nb, RadixHint hint) +{ + // Checkings + if(!input || !nb || nb&0x80000000) return *this; + + // Stats + mTotalCalls++; + + // Resize lists if needed + CheckResize(nb); + +#ifdef RADIX_LOCAL_RAM + // Allocate histograms & offsets on the stack + udword mHistogram[256*4]; +// udword mOffset[256]; + udword* mLink[256]; +#endif + + // Create histograms (counters). Counters for all passes are created in one run. + // Pros: read input buffer once instead of four times + // Cons: mHistogram is 4Kb instead of 1Kb + // We must take care of signed/unsigned values for temporal coherence.... I just + // have 2 code paths even if just a single opcode changes. Self-modifying code, someone? + if(hint==RADIX_UNSIGNED) { CREATE_HISTOGRAMS(udword, input); } + else { CREATE_HISTOGRAMS(sdword, input); } +/* + // Compute #negative values involved if needed + udword NbNegativeValues = 0; + if(hint==RADIX_SIGNED) + { + // An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128 + // last values of the last histogram. Last histogram because that's the one for the Most Significant Byte, + // responsible for the sign. 128 last values because the 128 first ones are related to positive numbers. + udword* h3= &mHistogram[768]; + for(udword i=128;i<256;i++) NbNegativeValues += h3[i]; // 768 for last histogram, 128 for negative part + } +*/ + // Radix sort, j is the pass number (0=LSB, 3=MSB) + for(udword j=0;j<4;j++) + { + CHECK_PASS_VALIDITY(j); + + // Sometimes the fourth (negative) pass is skipped because all numbers are negative and the MSB is 0xFF (for example). This is + // not a problem, numbers are correctly sorted anyway. + if(PerformPass) + { + // Should we care about negative values? + if(j!=3 || hint==RADIX_UNSIGNED) + { + // Here we deal with positive values only + + // Create offsets +// mOffset[0] = 0; +// for(udword i=1;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; + mLink[0] = mRanks2; + for(udword i=1;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; + } + else + { + // This is a special case to correctly handle negative integers. They're sorted in the right order but at the wrong place. +/* + // Create biased offsets, in order for negative numbers to be sorted as well +// mOffset[0] = NbNegativeValues; // First positive number takes place after the negative ones +// for(udword i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers + mLink[0] = &mRanks2[NbNegativeValues]; // First positive number takes place after the negative ones + for(udword i=1;i<128;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers + + // Fixing the wrong place for negative values +// mOffset[128] = 0; +// for(i=129;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; + mLink[128] = mRanks2; + for(udword i=129;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; +*/ + +// From Kyle Hubert: + +//mOffset[128] = 0; +mLink[128] = mRanks2; +//for(i=129;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; +for(udword i=129;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; + +//mOffset[0] = mOffset[255] + CurCount[255]; +mLink[0] = mLink[255] + CurCount[255]; +//for(i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; +for(udword i=1;i<128;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; + + + } + + // Perform Radix Sort + const ubyte* InputBytes = (const ubyte*)input; + InputBytes += BYTES_INC; + if(INVALID_RANKS) + { +// for(udword i=0;i127;i--) mOffset[i] = mOffset[i+1] + CurCount[i]; +for(udword i=254;i>127;i--) mLink[i] = mLink[i+1] + CurCount[i]; +//mOffset[0] = mOffset[128] + CurCount[128]; +mLink[0] = mLink[128] + CurCount[128]; +//for(udword i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; +for(udword i=1;i<128;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; + + // Perform Radix Sort + if(INVALID_RANKS) + { + for(udword i=0;i>24; // Radix byte, same as above. AND is useless here (udword). + // ### cmp to be killed. Not good. Later. +// if(Radix<128) mRanks2[mOffset[Radix]++] = i; // Number is positive, same as above +// else mRanks2[--mOffset[Radix]] = i; // Number is negative, flip the sorting order + if(Radix<128) *mLink[Radix]++ = i; // Number is positive, same as above + else *(--mLink[Radix]) = i; // Number is negative, flip the sorting order + } + VALIDATE_RANKS; + } + else + { + for(udword i=0;i>24; // Radix byte, same as above. AND is useless here (udword). + // ### cmp to be killed. Not good. Later. +// if(Radix<128) mRanks2[mOffset[Radix]++] = mRanks[i]; // Number is positive, same as above +// else mRanks2[--mOffset[Radix]] = mRanks[i]; // Number is negative, flip the sorting order + if(Radix<128) *mLink[Radix]++ = mRanks[i]; // Number is positive, same as above + else *(--mLink[Radix]) = mRanks[i]; // Number is negative, flip the sorting order + } + } + // Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap. + udword* Tmp = mRanks; + mRanks = mRanks2; + mRanks2 = Tmp; + } + else + { + // The pass is useless, yet we still have to reverse the order of current list if all values are negative. + if(UniqueVal>=128) + { + if(INVALID_RANKS) + { + // ###Possible? + for(udword i=0;i=SqrLen) + { + fT = 1.0f; + Diff -= Dir; + } + else + { + fT /= SqrLen; + Diff -= fT*Dir; + } + } + + if(t) *t = fT; + + return Diff.SquareMagnitude(); +} diff --git a/Extras/CDTestFramework/Opcode/Ice/IceSegment.h b/Extras/CDTestFramework/Opcode/Ice/IceSegment.h new file mode 100644 index 0000000..6764c0c --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceSegment.h @@ -0,0 +1,71 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for segments. + * \file IceSegment.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICESEGMENT_H__ +#define __ICESEGMENT_H__ + + class ICEMATHS_API Segment + { + public: + //! Constructor + inline_ Segment() {} + //! Constructor + inline_ Segment(const Point& p0, const Point& p1) : mP0(p0), mP1(p1) {} + //! Copy constructor + inline_ Segment(const Segment& seg) : mP0(seg.mP0), mP1(seg.mP1) {} + //! Destructor + inline_ ~Segment() {} + + inline_ const Point& GetOrigin() const { return mP0; } + inline_ Point ComputeDirection() const { return mP1 - mP0; } + inline_ void ComputeDirection(Point& dir) const { dir = mP1 - mP0; } + inline_ float ComputeLength() const { return mP1.Distance(mP0); } + inline_ float ComputeSquareLength() const { return mP1.SquareDistance(mP0); } + + inline_ void SetOriginDirection(const Point& origin, const Point& direction) + { + mP0 = mP1 = origin; + mP1 += direction; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes a point on the segment + * \param pt [out] point on segment + * \param t [in] point's parameter [t=0 => pt = mP0, t=1 => pt = mP1] + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void ComputePoint(Point& pt, float t) const { pt = mP0 + t * (mP1 - mP0); } + + float SquareDistance(const Point& point, float* t=null) const; + inline_ float Distance(const Point& point, float* t=null) const { return sqrtf(SquareDistance(point, t)); } + + Point mP0; //!< Start of segment + Point mP1; //!< End of segment + }; + +#endif // __ICESEGMENT_H__ diff --git a/Extras/CDTestFramework/Opcode/Ice/IceTriangle.cpp b/Extras/CDTestFramework/Opcode/Ice/IceTriangle.cpp new file mode 100644 index 0000000..d95174d --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceTriangle.cpp @@ -0,0 +1,302 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a handy triangle class. + * \file IceTriangle.cpp + * \author Pierre Terdiman + * \date January, 17, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a triangle class. + * + * \class Tri + * \author Pierre Terdiman + * \version 1.0 + * \date 08.15.98 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static sdword VPlaneSideEps(const Point& v, const Plane& plane, float epsilon) +{ + // Compute distance from current vertex to the plane + float Dist = plane.Distance(v); + // Compute side: + // 1 = the vertex is on the positive side of the plane + // -1 = the vertex is on the negative side of the plane + // 0 = the vertex is on the plane (within epsilon) + return Dist > epsilon ? 1 : Dist < -epsilon ? -1 : 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Flips the winding order. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Triangle::Flip() +{ + Point Tmp = mVerts[1]; + mVerts[1] = mVerts[2]; + mVerts[2] = Tmp; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle area. + * \return the area + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Triangle::Area() const +{ + const Point& p0 = mVerts[0]; + const Point& p1 = mVerts[1]; + const Point& p2 = mVerts[2]; + return ((p0 - p1)^(p0 - p2)).Magnitude() * 0.5f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle perimeter. + * \return the perimeter + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Triangle::Perimeter() const +{ + const Point& p0 = mVerts[0]; + const Point& p1 = mVerts[1]; + const Point& p2 = mVerts[2]; + return p0.Distance(p1) + + p0.Distance(p2) + + p1.Distance(p2); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle compacity. + * \return the compacity + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Triangle::Compacity() const +{ + float P = Perimeter(); + if(P==0.0f) return 0.0f; + return (4.0f*PI*Area()/(P*P)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle normal. + * \param normal [out] the computed normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Triangle::Normal(Point& normal) const +{ + const Point& p0 = mVerts[0]; + const Point& p1 = mVerts[1]; + const Point& p2 = mVerts[2]; + normal = ((p0 - p1)^(p0 - p2)).Normalize(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle denormalized normal. + * \param normal [out] the computed normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Triangle::DenormalizedNormal(Point& normal) const +{ + const Point& p0 = mVerts[0]; + const Point& p1 = mVerts[1]; + const Point& p2 = mVerts[2]; + normal = ((p0 - p1)^(p0 - p2)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle center. + * \param center [out] the computed center + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Triangle::Center(Point& center) const +{ + const Point& p0 = mVerts[0]; + const Point& p1 = mVerts[1]; + const Point& p2 = mVerts[2]; + center = (p0 + p1 + p2)*INV3; +} + +PartVal Triangle::TestAgainstPlane(const Plane& plane, float epsilon) const +{ + bool Pos = false, Neg = false; + + // Loop through all vertices + for(udword i=0;i<3;i++) + { + // Compute side: + sdword Side = VPlaneSideEps(mVerts[i], plane, epsilon); + + if (Side < 0) Neg = true; + else if (Side > 0) Pos = true; + } + + if (!Pos && !Neg) return TRI_ON_PLANE; + else if (Pos && Neg) return TRI_INTERSECT; + else if (Pos && !Neg) return TRI_PLUS_SPACE; + else if (!Pos && Neg) return TRI_MINUS_SPACE; + + // What?! + return TRI_FORCEDWORD; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle moment. + * \param m [out] the moment + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* +void Triangle::ComputeMoment(Moment& m) +{ + // Compute the area of the triangle + m.mArea = Area(); + + // Compute the centroid + Center(m.mCentroid); + + // Second-order components. Handle zero-area faces. + Point& p = mVerts[0]; + Point& q = mVerts[1]; + Point& r = mVerts[2]; + if(m.mArea==0.0f) + { + // This triangle has zero area. The second order components would be eliminated with the usual formula, so, for the + // sake of robustness we use an alternative form. These are the centroid and second-order components of the triangle's vertices. + m.mCovariance.m[0][0] = (p.x*p.x + q.x*q.x + r.x*r.x); + m.mCovariance.m[0][1] = (p.x*p.y + q.x*q.y + r.x*r.y); + m.mCovariance.m[0][2] = (p.x*p.z + q.x*q.z + r.x*r.z); + m.mCovariance.m[1][1] = (p.y*p.y + q.y*q.y + r.y*r.y); + m.mCovariance.m[1][2] = (p.y*p.z + q.y*q.z + r.y*r.z); + m.mCovariance.m[2][2] = (p.z*p.z + q.z*q.z + r.z*r.z); + m.mCovariance.m[2][1] = m.mCovariance.m[1][2]; + m.mCovariance.m[1][0] = m.mCovariance.m[0][1]; + m.mCovariance.m[2][0] = m.mCovariance.m[0][2]; + } + else + { + const float OneOverTwelve = 1.0f / 12.0f; + m.mCovariance.m[0][0] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.x + p.x*p.x + q.x*q.x + r.x*r.x) * OneOverTwelve; + m.mCovariance.m[0][1] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.y + p.x*p.y + q.x*q.y + r.x*r.y) * OneOverTwelve; + m.mCovariance.m[1][1] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.y + p.y*p.y + q.y*q.y + r.y*r.y) * OneOverTwelve; + m.mCovariance.m[0][2] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.z + p.x*p.z + q.x*q.z + r.x*r.z) * OneOverTwelve; + m.mCovariance.m[1][2] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.z + p.y*p.z + q.y*q.z + r.y*r.z) * OneOverTwelve; + m.mCovariance.m[2][2] = m.mArea * (9.0f * m.mCentroid.z*m.mCentroid.z + p.z*p.z + q.z*q.z + r.z*r.z) * OneOverTwelve; + m.mCovariance.m[2][1] = m.mCovariance.m[1][2]; + m.mCovariance.m[1][0] = m.mCovariance.m[0][1]; + m.mCovariance.m[2][0] = m.mCovariance.m[0][2]; + } +} +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle's smallest edge length. + * \return the smallest edge length + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Triangle::MinEdgeLength() const +{ + float Min = MAX_FLOAT; + float Length01 = mVerts[0].Distance(mVerts[1]); + float Length02 = mVerts[0].Distance(mVerts[2]); + float Length12 = mVerts[1].Distance(mVerts[2]); + if(Length01 < Min) Min = Length01; + if(Length02 < Min) Min = Length02; + if(Length12 < Min) Min = Length12; + return Min; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle's largest edge length. + * \return the largest edge length + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Triangle::MaxEdgeLength() const +{ + float Max = MIN_FLOAT; + float Length01 = mVerts[0].Distance(mVerts[1]); + float Length02 = mVerts[0].Distance(mVerts[2]); + float Length12 = mVerts[1].Distance(mVerts[2]); + if(Length01 > Max) Max = Length01; + if(Length02 > Max) Max = Length02; + if(Length12 > Max) Max = Length12; + return Max; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a point on the triangle according to the stabbing information. + * \param u,v [in] point's barycentric coordinates + * \param pt [out] point on triangle + * \param nearvtx [out] index of nearest vertex + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Triangle::ComputePoint(float u, float v, Point& pt, udword* nearvtx) const +{ + // Compute point coordinates + pt = (1.0f - u - v)*mVerts[0] + u*mVerts[1] + v*mVerts[2]; + + // Compute nearest vertex if needed + if(nearvtx) + { + // Compute distance vector + Point d(mVerts[0].SquareDistance(pt), // Distance^2 from vertex 0 to point on the face + mVerts[1].SquareDistance(pt), // Distance^2 from vertex 1 to point on the face + mVerts[2].SquareDistance(pt)); // Distance^2 from vertex 2 to point on the face + + // Get smallest distance + *nearvtx = d.SmallestAxis(); + } +} + +void Triangle::Inflate(float fat_coeff, bool constant_border) +{ + // Compute triangle center + Point TriangleCenter; + Center(TriangleCenter); + + // Don't normalize? + // Normalize => add a constant border, regardless of triangle size + // Don't => add more to big triangles + for(udword i=0;i<3;i++) + { + Point v = mVerts[i] - TriangleCenter; + + if(constant_border) v.Normalize(); + + mVerts[i] += v * fat_coeff; + } +} diff --git a/Extras/CDTestFramework/Opcode/Ice/IceTriangle.h b/Extras/CDTestFramework/Opcode/Ice/IceTriangle.h new file mode 100644 index 0000000..99a6467 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceTriangle.h @@ -0,0 +1,84 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a handy triangle class. + * \file IceTriangle.h + * \author Pierre Terdiman + * \date January, 17, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICETRIANGLE_H__ +#define __ICETRIANGLE_H__ + + // Forward declarations + class Moment; + + // Partitioning values + enum PartVal + { + TRI_MINUS_SPACE = 0, //!< Triangle is in the negative space + TRI_PLUS_SPACE = 1, //!< Triangle is in the positive space + TRI_INTERSECT = 2, //!< Triangle intersects plane + TRI_ON_PLANE = 3, //!< Triangle and plane are coplanar + + TRI_FORCEDWORD = 0x7fffffff + }; + + // A triangle class. + class ICEMATHS_API Triangle + { + public: + //! Constructor + inline_ Triangle() {} + //! Constructor + inline_ Triangle(const Point& p0, const Point& p1, const Point& p2) { mVerts[0]=p0; mVerts[1]=p1; mVerts[2]=p2; } + //! Copy constructor + inline_ Triangle(const Triangle& triangle) + { + mVerts[0] = triangle.mVerts[0]; + mVerts[1] = triangle.mVerts[1]; + mVerts[2] = triangle.mVerts[2]; + } + //! Destructor + inline_ ~Triangle() {} + //! Vertices + Point mVerts[3]; + + // Methods + void Flip(); + float Area() const; + float Perimeter() const; + float Compacity() const; + void Normal(Point& normal) const; + void DenormalizedNormal(Point& normal) const; + void Center(Point& center) const; + inline_ Plane PlaneEquation() const { return Plane(mVerts[0], mVerts[1], mVerts[2]); } + + PartVal TestAgainstPlane(const Plane& plane, float epsilon) const; +// float Distance(Point& cp, Point& cq, Tri& tri); + void ComputeMoment(Moment& m); + float MinEdgeLength() const; + float MaxEdgeLength() const; + void ComputePoint(float u, float v, Point& pt, udword* nearvtx=null) const; + void Inflate(float fat_coeff, bool constant_border); + }; + +#endif // __ICETRIANGLE_H__ diff --git a/Extras/CDTestFramework/Opcode/Ice/IceTrilist.h b/Extras/CDTestFramework/Opcode/Ice/IceTrilist.h new file mode 100644 index 0000000..73d23b5 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceTrilist.h @@ -0,0 +1,77 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a triangle container. + * \file IceTrilist.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICETRILIST_H__ +#define __ICETRILIST_H__ + + class ICEMATHS_API TriList : public Container + { + public: + // Constructor / Destructor + TriList() {} + ~TriList() {} + + inline_ udword GetNbTriangles() const { return GetNbEntries()/9; } + inline_ Triangle* GetTriangles() const { return (Triangle*)GetEntries(); } + + void AddTri(const Triangle& tri) + { + Add(tri.mVerts[0].x).Add(tri.mVerts[0].y).Add(tri.mVerts[0].z); + Add(tri.mVerts[1].x).Add(tri.mVerts[1].y).Add(tri.mVerts[1].z); + Add(tri.mVerts[2].x).Add(tri.mVerts[2].y).Add(tri.mVerts[2].z); + } + + void AddTri(const Point& p0, const Point& p1, const Point& p2) + { + Add(p0.x).Add(p0.y).Add(p0.z); + Add(p1.x).Add(p1.y).Add(p1.z); + Add(p2.x).Add(p2.y).Add(p2.z); + } + }; + + class ICEMATHS_API TriangleList : public Container + { + public: + // Constructor / Destructor + TriangleList() {} + ~TriangleList() {} + + inline_ udword GetNbTriangles() const { return GetNbEntries()/3; } + inline_ IndexedTriangle* GetTriangles() const { return (IndexedTriangle*)GetEntries();} + + void AddTriangle(const IndexedTriangle& tri) + { + Add(tri.mVRef[0]).Add(tri.mVRef[1]).Add(tri.mVRef[2]); + } + + void AddTriangle(udword vref0, udword vref1, udword vref2) + { + Add(vref0).Add(vref1).Add(vref2); + } + }; + +#endif //__ICETRILIST_H__ diff --git a/Extras/CDTestFramework/Opcode/Ice/IceTypes.h b/Extras/CDTestFramework/Opcode/Ice/IceTypes.h new file mode 100644 index 0000000..9316d8d --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/IceTypes.h @@ -0,0 +1,181 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains custom types. + * \file IceTypes.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef ICETYPES_H +#define ICETYPES_H + + #define USE_HANDLE_MANAGER + + // Constants +#ifndef PI + #define PI 3.1415926535897932384626433832795028841971693993751f //!< PI +#endif + #define HALFPI 1.57079632679489661923f //!< 0.5 * PI + #define TWOPI 6.28318530717958647692f //!< 2.0 * PI + #define INVPI 0.31830988618379067154f //!< 1.0 / PI + + #define RADTODEG 57.2957795130823208768f //!< 180.0 / PI, convert radians to degrees + #define DEGTORAD 0.01745329251994329577f //!< PI / 180.0, convert degrees to radians + + #define EXP 2.71828182845904523536f //!< e + #define INVLOG2 3.32192809488736234787f //!< 1.0 / log10(2) + #define LN2 0.693147180559945f //!< ln(2) + #define INVLN2 1.44269504089f //!< 1.0f / ln(2) + + #define INV3 0.33333333333333333333f //!< 1/3 + #define INV6 0.16666666666666666666f //!< 1/6 + #define INV7 0.14285714285714285714f //!< 1/7 + #define INV9 0.11111111111111111111f //!< 1/9 + #define INV255 0.00392156862745098039f //!< 1/255 + + #define SQRT2 1.41421356237f //!< sqrt(2) + #define INVSQRT2 0.707106781188f //!< 1 / sqrt(2) + + #define SQRT3 1.73205080757f //!< sqrt(3) + #define INVSQRT3 0.577350269189f //!< 1 / sqrt(3) + + #define null 0 //!< our own NULL pointer + + // Custom types used in ICE + typedef signed char sbyte; //!< sizeof(sbyte) must be 1 + typedef unsigned char ubyte; //!< sizeof(ubyte) must be 1 + typedef signed short sword; //!< sizeof(sword) must be 2 + typedef unsigned short uword; //!< sizeof(uword) must be 2 + typedef signed int sdword; //!< sizeof(sdword) must be 4 + typedef unsigned int udword; //!< sizeof(udword) must be 4 +#ifdef WIN32 + typedef signed __int64 sqword; //!< sizeof(sqword) must be 8 + typedef unsigned __int64 uqword; //!< sizeof(uqword) must be 8 +#elif LINUX + typedef signed long long sqword; //!< sizeof(sqword) must be 8 + typedef unsigned long long uqword; //!< sizeof(uqword) must be 8 +#elif defined(__APPLE__) + typedef signed long long sqword; //!< sizeof(sqword) must be 8 + typedef unsigned long long uqword; //!< sizeof(uqword) must be 8 +#elif defined(_XBOX) + typedef signed __int64 sqword; //!< sizeof(sqword) must be 8 + typedef unsigned __int64 uqword; //!< sizeof(uqword) must be 8 +#endif + typedef float float32; //!< sizeof(float32) must be 4 + typedef double float64; //!< sizeof(float64) must be 8 + typedef size_t regsize; //!< sizeof(regsize) must be sizeof(void*) + + // For test purpose you can force one of those: +// typedef udword regsize; +// typedef uqword regsize; + + ICE_COMPILE_TIME_ASSERT(sizeof(bool)==1); // ...otherwise things might fail with VC++ 4.2 ! + ICE_COMPILE_TIME_ASSERT(sizeof(ubyte)==1); + ICE_COMPILE_TIME_ASSERT(sizeof(sbyte)==1); + ICE_COMPILE_TIME_ASSERT(sizeof(sword)==2); + ICE_COMPILE_TIME_ASSERT(sizeof(uword)==2); + ICE_COMPILE_TIME_ASSERT(sizeof(udword)==4); + ICE_COMPILE_TIME_ASSERT(sizeof(sdword)==4); + ICE_COMPILE_TIME_ASSERT(sizeof(uqword)==8); + ICE_COMPILE_TIME_ASSERT(sizeof(sqword)==8); + ICE_COMPILE_TIME_ASSERT(sizeof(float32)==4); + ICE_COMPILE_TIME_ASSERT(sizeof(float64)==8); + ICE_COMPILE_TIME_ASSERT(sizeof(regsize)==sizeof(void*)); + + //! TO BE DOCUMENTED + #define DECLARE_ICE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name + + typedef udword DynID; //!< Dynamic identifier +#ifdef USE_HANDLE_MANAGER + typedef udword KID; //!< Kernel ID +// DECLARE_ICE_HANDLE(KID); +#else + typedef uword KID; //!< Kernel ID +#endif + #define INVALID_ID 0xffffffff //!< Invalid dword ID (counterpart of null pointers) +#ifdef USE_HANDLE_MANAGER + #define INVALID_KID 0xffffffff //!< Invalid Kernel ID +#else + #define INVALID_KID 0xffff //!< Invalid Kernel ID +#endif + #define INVALID_NUMBER 0xDEADBEEF //!< Standard junk value + + // Define BOOL if needed + #ifndef BOOL + typedef int BOOL; //!< Another boolean type. + #endif + + //! Union of a float and a sdword + typedef union { + float f; //!< The float + sdword d; //!< The integer + }scell; + + //! Union of a float and a udword + typedef union { + float f; //!< The float + udword d; //!< The integer + }ucell; + + // Type ranges + #define MAX_SBYTE 0x7f //!< max possible sbyte value + #define MIN_SBYTE 0x80 //!< min possible sbyte value + #define MAX_UBYTE 0xff //!< max possible ubyte value + #define MIN_UBYTE 0x00 //!< min possible ubyte value + #define MAX_SWORD 0x7fff //!< max possible sword value + #define MIN_SWORD 0x8000 //!< min possible sword value + #define MAX_UWORD 0xffff //!< max possible uword value + #define MIN_UWORD 0x0000 //!< min possible uword value + #define MAX_SDWORD 0x7fffffff //!< max possible sdword value + #define MIN_SDWORD 0x80000000 //!< min possible sdword value + #define MAX_UDWORD 0xffffffff //!< max possible udword value + #define MIN_UDWORD 0x00000000 //!< min possible udword value + #define MAX_FLOAT FLT_MAX //!< max possible float value + #define MIN_FLOAT (-FLT_MAX) //!< min possible loat value + #define IEEE_1_0 0x3f800000 //!< integer representation of 1.0 + #define IEEE_255_0 0x437f0000 //!< integer representation of 255.0 + #define IEEE_MAX_FLOAT 0x7f7fffff //!< integer representation of MAX_FLOAT + #define IEEE_MIN_FLOAT 0xff7fffff //!< integer representation of MIN_FLOAT + #define IEEE_UNDERFLOW_LIMIT 0x1a000000 + + #define ONE_OVER_RAND_MAX (1.0f / float(RAND_MAX)) //!< Inverse of the max possible value returned by rand() + + typedef void** VTABLE; //!< A V-Table. + + #undef MIN + #undef MAX + #define MIN(a, b) ((a) < (b) ? (a) : (b)) //!< Returns the min value between a and b + #define MAX(a, b) ((a) > (b) ? (a) : (b)) //!< Returns the max value between a and b + #define MAXMAX(a,b,c) ((a) > (b) ? MAX (a,c) : MAX (b,c)) //!< Returns the max value between a, b and c + + template inline_ const T& TMin (const T& a, const T& b) { return b < a ? b : a; } + template inline_ const T& TMax (const T& a, const T& b) { return a < b ? b : a; } + template inline_ void TSetMin (T& a, const T& b) { if(a>b) a = b; } + template inline_ void TSetMax (T& a, const T& b) { if(a> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa); + n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc); + n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0); + n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00); + n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000); + // Etc for larger integers (64 bits in Java) + // NOTE: the >> operation must be unsigned! (>>> in java) + } + + //! Count the number of '1' bits in a 32 bit word (from Steve Baker's Cute Code Collection) + inline_ udword CountBits(udword n) + { + // This relies of the fact that the count of n bits can NOT overflow + // an n bit integer. EG: 1 bit count takes a 1 bit integer, 2 bit counts + // 2 bit integer, 3 bit count requires only a 2 bit integer. + // So we add all bit pairs, then each nible, then each byte etc... + n = (n & 0x55555555) + ((n & 0xaaaaaaaa) >> 1); + n = (n & 0x33333333) + ((n & 0xcccccccc) >> 2); + n = (n & 0x0f0f0f0f) + ((n & 0xf0f0f0f0) >> 4); + n = (n & 0x00ff00ff) + ((n & 0xff00ff00) >> 8); + n = (n & 0x0000ffff) + ((n & 0xffff0000) >> 16); + // Etc for larger integers (64 bits in Java) + // NOTE: the >> operation must be unsigned! (>>> in java) + return n; + } + + //! Even faster? + inline_ udword CountBits2(udword bits) + { + bits = bits - ((bits >> 1) & 0x55555555); + bits = ((bits >> 2) & 0x33333333) + (bits & 0x33333333); + bits = ((bits >> 4) + bits) & 0x0F0F0F0F; + return (bits * 0x01010101) >> 24; + } + + // "Population Count (Ones Count) + // The population count of a binary integer value x is the number of one bits in the value. Although many machines have + // single instructions for this, the single instructions are usually microcoded loops that test a bit per cycle; a log-time + // algorithm coded in C is often faster. The following code uses a variable-precision SWAR algorithm to perform a tree + // reduction adding the bits in a 32-bit value:" + inline_ udword ones32(udword x) + { + /* 32-bit recursive reduction using SWAR... + but first step is mapping 2-bit values + into sum of 2 1-bit values in sneaky way + */ + x -= ((x >> 1) & 0x55555555); + x = (((x >> 2) & 0x33333333) + (x & 0x33333333)); + x = (((x >> 4) + x) & 0x0f0f0f0f); + x += (x >> 8); + x += (x >> 16); + return (x & 0x0000003f); + // "It is worthwhile noting that the SWAR population count algorithm given above can be improved upon for the case of + // counting the population of multi-word bit sets. How? The last few steps in the reduction are using only a portion + // of the SWAR width to produce their results; thus, it would be possible to combine these steps across multiple words + // being reduced. One additional note: the AMD Athlon optimization guidelines suggest a very similar algorithm that + // replaces the last three lines with return((x * 0x01010101) >> 24);. For the Athlon (which has a very fast integer + // multiply), I would have expected AMD's code to be faster... but it is actually 6% slower according to my benchmarks + // using a 1.2GHz Athlon (a Thunderbird). Why? Well, it so happens that GCC doesn't use a multiply instruction - it + // writes out the equivalent shift and add sequence!" + } + + // "Trailing Zero Count + // Given the Least Significant 1 Bit and Population Count (Ones Count) algorithms, it is trivial to combine them to + // construct a trailing zero count (as pointed-out by Joe Bowbeer):" + inline_ udword tzc(sdword x) + { + return(ones32((x & -x) - 1)); + } + + //! Spread out bits. EG 00001111 -> 0101010101 + //! 00001010 -> 0100010000 + //! This is used to interleave two integers to produce a `Morton Key' + //! used in Space Filling Curves (See DrDobbs Journal, July 1999) + //! Order is important. + inline_ void SpreadBits(udword& n) + { + n = ( n & 0x0000ffff) | (( n & 0xffff0000) << 16); + n = ( n & 0x000000ff) | (( n & 0x0000ff00) << 8); + n = ( n & 0x000f000f) | (( n & 0x00f000f0) << 4); + n = ( n & 0x03030303) | (( n & 0x0c0c0c0c) << 2); + n = ( n & 0x11111111) | (( n & 0x22222222) << 1); + } + + // "Next Largest Power of 2 + // Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm + // that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with + // the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next + // largest power of 2. For a 32-bit value:" + inline_ udword NextPowerOfTwo(udword x) + { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return x+1; + } + + //! Test to see if a number is an exact power of two (from Steve Baker's Cute Code Collection) + inline_ bool IsPowerOfTwo(udword n) { return ((n&(n-1))==0); } + + //! Zero the least significant '1' bit in a word. (from Steve Baker's Cute Code Collection) + inline_ void ZeroLeastSetBit(udword& n) { n&=(n-1); } + + //! Set the least significant N bits in a word. (from Steve Baker's Cute Code Collection) + inline_ void SetLeastNBits(udword& x, udword n) { x|=~(~0<> 31; return (x^y)-y; } + + // "Integer Minimum or Maximum + // Given 2's complement integer values x and y, the minimum can be computed without any branches as + // x+(((y-x)>>(WORDBITS-1))&(y-x)). + // Logically, this works because the shift by (WORDBITS-1) replicates the sign bit to create a mask + // -- be aware, however, that the C language does not require that shifts are signed even if their + // operands are signed, so there is a potential portability problem. Additionally, one might think + // that a shift by any number greater than or equal to WORDBITS would have the same effect, but many + // instruction sets have shifts that behave strangely when such shift distances are specified. + // Of course, maximum can be computed using the same trick: + // x-(((x-y)>>(WORDBITS-1))&(x-y))." + + //!< Alternative min function + inline_ sdword min_(sdword a, sdword b) { sdword delta = b-a; return a + (delta&(delta>>31)); } + //!< Alternative max function + inline_ sdword max_(sdword a, sdword b) { sdword delta = a-b; return a - (delta&(delta>>31)); } + + // "Integer Selection + // A branchless, lookup-free, alternative to code like if (a> (WORDBITS-1)) & (c^d)) ^ d). + // This code assumes that the shift is signed, which, of course, C does not promise." + inline_ sdword IntegerSelection(sdword a, sdword b, sdword c, sdword d) + { + return ((((a-b)>>31) & (c^d)) ^ d); + } + + // Determine if one of the bytes in a 4 byte word is zero + inline_ BOOL HasNullByte(udword x) { return ((x + 0xfefefeff) & (~x) & 0x80808080); } + + // To find the smallest 1 bit in a word EG: ~~~~~~10---0 => 0----010---0 + inline_ udword LowestOneBit(udword w) { return ((w) & (~(w)+1)); } +// inline_ udword LowestOneBit_(udword w) { return ((w) & (-(w))); } + + // "Most Significant 1 Bit + // Given a binary integer value x, the most significant 1 bit (highest numbered element of a bit set) + // can be computed using a SWAR algorithm that recursively "folds" the upper bits into the lower bits. + // This process yields a bit vector with the same most significant 1 as x, but all 1's below it. + // Bitwise AND of the original value with the complement of the "folded" value shifted down by one + // yields the most significant bit. For a 32-bit value:" + inline_ udword msb32(udword x) + { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return (x & ~(x >> 1)); + } + + // "Gray Code Conversion + // A Gray code is any binary coding sequence in which only a single bit position changes as we move from one value to the next. + // There are many such codes, but the traditional one is computed such that the Kth Gray code is K^(K>>1). + // + // The well-known algorithm for conversion from Gray to binary is a linear sequence of XORs that makes it seem each bit must be + // dealt with separately. Fortunately, that is equivalent to a parallel prefix XOR that can be computed using SWAR techniques + // in log time. For 32-bit Gray code values produced as described above, the conversion from Gray code back to unsigned binary is:" + inline_ udword g2b(udword gray) + { + gray ^= (gray >> 16); + gray ^= (gray >> 8); + gray ^= (gray >> 4); + gray ^= (gray >> 2); + gray ^= (gray >> 1); + return gray; + } + + /* + "Just call it repeatedly with various input values and always with the same variable as "memory". + The sharpness determines the degree of filtering, where 0 completely filters out the input, and 1 + does no filtering at all. + + I seem to recall from college that this is called an IIR (Infinite Impulse Response) filter. As opposed + to the more typical FIR (Finite Impulse Response). + + Also, I'd say that you can make more intelligent and interesting filters than this, for example filters + that remove wrong responses from the mouse because it's being moved too fast. You'd want such a filter + to be applied before this one, of course." + + (JCAB on Flipcode) + */ + inline_ float FeedbackFilter(float val, float& memory, float sharpness) + { + ASSERT(sharpness>=0.0f && sharpness<=1.0f && "Invalid sharpness value in feedback filter"); + if(sharpness<0.0f) sharpness = 0.0f; + else if(sharpness>1.0f) sharpness = 1.0f; + return memory = val * sharpness + memory * (1.0f - sharpness); + } + + //! "If you can guarantee that your input domain (i.e. value of x) is slightly + //! limited (abs(x) must be < ((1<<31u)-32767)), then you can use the + //! following code to clamp the resulting value into [-32768,+32767] range:" + inline_ int ClampToInt16(int x) + { +// ASSERT(abs(x) < (int)((1<<31u)-32767)); + + int delta = 32767 - x; + x += (delta>>31) & delta; + delta = x + 32768; + x -= (delta>>31) & delta; + return x; + } + + // Generic functions + template inline_ void TSwap(Type& a, Type& b) { const Type c = a; a = b; b = c; } + template inline_ Type TClamp(const Type& x, const Type& lo, const Type& hi) { return ((xhi) ? hi : x); } + + template inline_ void TSort(Type& a, Type& b) + { + if(a>b) TSwap(a, b); + } + + template inline_ void TSort(Type& a, Type& b, Type& c) + { + if(a>b) TSwap(a, b); + if(b>c) TSwap(b, c); + if(a>b) TSwap(a, b); + if(b>c) TSwap(b, c); + } + + // Prevent nasty user-manipulations (strategy borrowed from Charles Bloom) +// #define PREVENT_COPY(curclass) void operator = (const curclass& object) { ASSERT(!"Bad use of operator ="); } + // ... actually this is better ! + #define PREVENT_COPY(cur_class) private: cur_class(const cur_class& object); cur_class& operator=(const cur_class& object); + + //! TO BE DOCUMENTED + #define OFFSET_OF(Class, Member) (size_t)&(((Class*)0)->Member) + + //! TO BE DOCUMENTED + #if !defined(_XBOX) + // Already defined on Xbox. + #define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0])) + #endif + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Returns the alignment of the input address. + * \fn Alignment() + * \param address [in] address to check + * \return the best alignment (e.g. 1 for odd addresses, etc) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + FUNCTION ICECORE_API udword Alignment(udword address); + + #define IS_ALIGNED_2(x) ((x&1)==0) + #define IS_ALIGNED_4(x) ((x&3)==0) + #define IS_ALIGNED_8(x) ((x&7)==0) + + // Updates a pointer with "stride" bytes + inline_ void UpdatePtr(void*& ptr, udword stride) { ptr = ((ubyte*)ptr) + stride; } + + // From Jon Watte IIRC + inline_ void _prefetch(void const* ptr) { (void)*(char const volatile *)ptr; } + + // Compute implicit coords from an index: + // The idea is to get back 2D coords from a 1D index. + // For example: + // + // 0 1 2 ... nbu-1 + // nbu nbu+1 i ... + // + // We have i, we're looking for the equivalent (u=2, v=1) location. + // i = u + v*nbu + // <=> i/nbu = u/nbu + v + // Since 0 <= u < nbu, u/nbu = 0 (integer) + // Hence: v = i/nbu + // Then we simply put it back in the original equation to compute u = i - v*nbu + inline_ void Compute2DCoords(udword& u, udword& v, udword i, udword nbu) + { + v = i / nbu; + u = i - (v * nbu); + } + + // In 3D: i = u + v*nbu + w*nbu*nbv + // <=> i/(nbu*nbv) = u/(nbu*nbv) + v/nbv + w + // u/(nbu*nbv) is null since u/nbu was null already. + // v/nbv is null as well for the same reason. + // Hence w = i/(nbu*nbv) + // Then we're left with a 2D problem: i' = i - w*nbu*nbv = u + v*nbu + inline_ void Compute3DCoords(udword& u, udword& v, udword& w, udword i, udword nbu, udword nbu_nbv) + { + w = i / (nbu_nbv); + Compute2DCoords(u, v, i - (w * nbu_nbv), nbu); + } + + // Calling fsincos instead of fsin+fcos. Twice faster. + inline_ void FSinCos(float& c, float& s, float f) + { + float LocalCos, LocalSin; + float Local = f; +#ifdef WIN32 + _asm fld Local + _asm fsincos + _asm fstp LocalCos + _asm fstp LocalSin +#elif LINUX + asm("fld Local\n\t" + "fsincos\n\t" + "fstp LocalCos\n\t" + "fstp LocalSin\n\t" + ); +#endif + c = LocalCos; + s = LocalSin; + } + + // Modulo3 macros. See http://www.codercorner.com/Modulo3.htm + #define GET_NEXT_INDICES(i, j, k) \ + k = 0x01000201; \ + k>>=(i<<3); \ + j = k & 0xff; \ + k>>=8; \ + k&=0xff; + + #define GET_NEXT_INDICES2(i, j, k) \ + j = ( 9 >> (i<<1)) & 3; \ + k = (18 >> (i<<1)) & 3; + + // 0=>1, 1=>2, 2=>0 + inline_ udword Modulo3(udword i) + { + ASSERT(i==0 || i==1 || i==2); + return (9 >> (i << 1)) & 3; + } + +#endif // ICEUTILS_H diff --git a/Extras/CDTestFramework/Opcode/Ice/_IceAABB.h b/Extras/CDTestFramework/Opcode/Ice/_IceAABB.h new file mode 100644 index 0000000..23375fa --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/_IceAABB.h @@ -0,0 +1,522 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains AABB-related code. (axis-aligned bounding box) + * \file IceAABB.h + * \author Pierre Terdiman + * \date January, 13, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEAABB_H__ +#define __ICEAABB_H__ + + // Forward declarations + class Sphere; + +//! Declarations of type-independent methods (most of them implemented in the .cpp) +#define AABB_COMMON_METHODS \ + AABB& Add(const AABB& aabb); \ + float MakeCube(AABB& cube) const; \ + void MakeSphere(Sphere& sphere) const; \ + const sbyte* ComputeOutline(const Point& local_eye, sdword& num) const; \ + float ComputeBoxArea(const Point& eye, const Matrix4x4& mat, float width, float height, sdword& num) const; \ + bool IsInside(const AABB& box) const; \ + bool ComputePlanes(Plane* planes) const; \ + bool ComputePoints(Point* pts) const; \ + const Point* GetVertexNormals() const; \ + const udword* GetEdges() const; \ + const Point* GetEdgeNormals() const; \ + inline_ BOOL ContainsPoint(const Point& p) const \ + { \ + if(p.x > GetMax(0) || p.x < GetMin(0)) return FALSE; \ + if(p.y > GetMax(1) || p.y < GetMin(1)) return FALSE; \ + if(p.z > GetMax(2) || p.z < GetMin(2)) return FALSE; \ + return TRUE; \ + } + + enum AABBType + { + AABB_RENDER = 0, //!< AABB used for rendering. Not visible == not rendered. + AABB_UPDATE = 1, //!< AABB used for dynamic updates. Not visible == not updated. + + AABB_FORCE_DWORD = 0x7fffffff, + }; + +#ifdef USE_MINMAX + + struct ICEMATHS_API ShadowAABB + { + Point mMin; + Point mMax; + }; + + class ICEMATHS_API AABB + { + public: + //! Constructor + inline_ AABB() {} + //! Destructor + inline_ ~AABB() {} + + //! Type-independent methods + AABB_COMMON_METHODS; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from min & max vectors. + * \param min [in] the min point + * \param max [in] the max point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetMinMax(const Point& min, const Point& max) { mMin = min; mMax = max; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from center & extents vectors. + * \param c [in] the center point + * \param e [in] the extents vector + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetCenterExtents(const Point& c, const Point& e) { mMin = c - e; mMax = c + e; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an empty AABB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetEmpty() { Point p(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); mMin = -p; mMax = p;} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups a point AABB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetPoint(const Point& pt) { mMin = mMax = pt; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the size of the AABB. The size is defined as the longest extent. + * \return the size of the AABB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + float GetSize() const { Point e; GetExtents(e); return e.Max(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Extends the AABB. + * \param p [in] the next point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Extend(const Point& p) + { + if(p.x > mMax.x) mMax.x = p.x; + if(p.x < mMin.x) mMin.x = p.x; + + if(p.y > mMax.y) mMax.y = p.y; + if(p.y < mMin.y) mMin.y = p.y; + + if(p.z > mMax.z) mMax.z = p.z; + if(p.z < mMin.z) mMin.z = p.z; + } + // Data access + + //! Get min point of the box + inline_ void GetMin(Point& min) const { min = mMin; } + //! Get max point of the box + inline_ void GetMax(Point& max) const { max = mMax; } + + //! Get component of the box's min point along a given axis + inline_ float GetMin(udword axis) const { return mMin[axis]; } + //! Get component of the box's max point along a given axis + inline_ float GetMax(udword axis) const { return mMax[axis]; } + + //! Get box center + inline_ void GetCenter(Point& center) const { center = (mMax + mMin)*0.5f; } + //! Get box extents + inline_ void GetExtents(Point& extents) const { extents = (mMax - mMin)*0.5f; } + + //! Get component of the box's center along a given axis + inline_ float GetCenter(udword axis) const { return (mMax[axis] + mMin[axis])*0.5f; } + //! Get component of the box's extents along a given axis + inline_ float GetExtents(udword axis) const { return (mMax[axis] - mMin[axis])*0.5f; } + + //! Get box diagonal + inline_ void GetDiagonal(Point& diagonal) const { diagonal = mMax - mMin; } + inline_ float GetWidth() const { return mMax.x - mMin.x; } + inline_ float GetHeight() const { return mMax.y - mMin.y; } + inline_ float GetDepth() const { return mMax.z - mMin.z; } + + //! Volume + inline_ float GetVolume() const { return GetWidth() * GetHeight() * GetDepth(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the intersection between two AABBs. + * \param a [in] the other AABB + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Intersect(const AABB& a) const + { + if(mMax.x < a.mMin.x + || a.mMax.x < mMin.x + || mMax.y < a.mMin.y + || a.mMax.y < mMin.y + || mMax.z < a.mMin.z + || a.mMax.z < mMin.z) return FALSE; + + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the 1D-intersection between two AABBs, on a given axis. + * \param a [in] the other AABB + * \param axis [in] the axis (0, 1, 2) + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Intersect(const AABB& a, udword axis) const + { + if(mMax[axis] < a.mMin[axis] || a.mMax[axis] < mMin[axis]) return FALSE; + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Recomputes the AABB after an arbitrary transform by a 4x4 matrix. + * Original code by Charles Bloom on the GD-Algorithm list. (I slightly modified it) + * \param mtx [in] the transform matrix + * \param aabb [out] the transformed AABB [can be *this] + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const + { + // The three edges transformed: you can efficiently transform an X-only vector + // by just getting the "X" column of the matrix + Point vx,vy,vz; + mtx.GetRow(0, vx); vx *= (mMax.x - mMin.x); + mtx.GetRow(1, vy); vy *= (mMax.y - mMin.y); + mtx.GetRow(2, vz); vz *= (mMax.z - mMin.z); + + // Transform the min point + aabb.mMin = aabb.mMax = mMin * mtx; + + // Take the transformed min & axes and find new extents + // Using CPU code in the right place is faster... + if(IS_NEGATIVE_FLOAT(vx.x)) aabb.mMin.x += vx.x; else aabb.mMax.x += vx.x; + if(IS_NEGATIVE_FLOAT(vx.y)) aabb.mMin.y += vx.y; else aabb.mMax.y += vx.y; + if(IS_NEGATIVE_FLOAT(vx.z)) aabb.mMin.z += vx.z; else aabb.mMax.z += vx.z; + if(IS_NEGATIVE_FLOAT(vy.x)) aabb.mMin.x += vy.x; else aabb.mMax.x += vy.x; + if(IS_NEGATIVE_FLOAT(vy.y)) aabb.mMin.y += vy.y; else aabb.mMax.y += vy.y; + if(IS_NEGATIVE_FLOAT(vy.z)) aabb.mMin.z += vy.z; else aabb.mMax.z += vy.z; + if(IS_NEGATIVE_FLOAT(vz.x)) aabb.mMin.x += vz.x; else aabb.mMax.x += vz.x; + if(IS_NEGATIVE_FLOAT(vz.y)) aabb.mMin.y += vz.y; else aabb.mMax.y += vz.y; + if(IS_NEGATIVE_FLOAT(vz.z)) aabb.mMin.z += vz.z; else aabb.mMax.z += vz.z; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the AABB is valid. + * \return true if the box is valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsValid() const + { + // Consistency condition for (Min, Max) boxes: min < max + if(mMin.x > mMax.x) return FALSE; + if(mMin.y > mMax.y) return FALSE; + if(mMin.z > mMax.z) return FALSE; + return TRUE; + } + + //! Operator for AABB *= float. Scales the extents, keeps same center. + inline_ AABB& operator*=(float s) + { + Point Center; GetCenter(Center); + Point Extents; GetExtents(Extents); + SetCenterExtents(Center, Extents * s); + return *this; + } + + //! Operator for AABB /= float. Scales the extents, keeps same center. + inline_ AABB& operator/=(float s) + { + Point Center; GetCenter(Center); + Point Extents; GetExtents(Extents); + SetCenterExtents(Center, Extents / s); + return *this; + } + + //! Operator for AABB += Point. Translates the box. + inline_ AABB& operator+=(const Point& trans) + { + mMin+=trans; + mMax+=trans; + return *this; + } + private: + Point mMin; //!< Min point + Point mMax; //!< Max point + }; + +#else + + class ICEMATHS_API AABB + { + public: + //! Constructor + inline_ AABB() {} + //! Destructor + inline_ ~AABB() {} + + //! Type-independent methods + AABB_COMMON_METHODS; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from min & max vectors. + * \param min [in] the min point + * \param max [in] the max point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetMinMax(const Point& min, const Point& max) { mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from center & extents vectors. + * \param c [in] the center point + * \param e [in] the extents vector + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetCenterExtents(const Point& c, const Point& e) { mCenter = c; mExtents = e; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an empty AABB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetEmpty() { mCenter.Zero(); mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups a point AABB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetPoint(const Point& pt) { mCenter = pt; mExtents.Zero(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the size of the AABB. The size is defined as the longest extent. + * \return the size of the AABB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + float GetSize() const { return mExtents.Max(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Extends the AABB. + * \param p [in] the next point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Extend(const Point& p) + { + Point Max = mCenter + mExtents; + Point Min = mCenter - mExtents; + + if(p.x > Max.x) Max.x = p.x; + if(p.x < Min.x) Min.x = p.x; + + if(p.y > Max.y) Max.y = p.y; + if(p.y < Min.y) Min.y = p.y; + + if(p.z > Max.z) Max.z = p.z; + if(p.z < Min.z) Min.z = p.z; + + SetMinMax(Min, Max); + } + // Data access + + //! Get min point of the box + inline_ void GetMin(Point& min) const { min = mCenter - mExtents; } + //! Get max point of the box + inline_ void GetMax(Point& max) const { max = mCenter + mExtents; } + + //! Get component of the box's min point along a given axis + inline_ float GetMin(udword axis) const { return mCenter[axis] - mExtents[axis]; } + //! Get component of the box's max point along a given axis + inline_ float GetMax(udword axis) const { return mCenter[axis] + mExtents[axis]; } + + //! Get box center + inline_ void GetCenter(Point& center) const { center = mCenter; } + //! Get box extents + inline_ void GetExtents(Point& extents) const { extents = mExtents; } + + //! Get component of the box's center along a given axis + inline_ float GetCenter(udword axis) const { return mCenter[axis]; } + //! Get component of the box's extents along a given axis + inline_ float GetExtents(udword axis) const { return mExtents[axis]; } + + //! Get box diagonal + inline_ void GetDiagonal(Point& diagonal) const { diagonal = mExtents * 2.0f; } + inline_ float GetWidth() const { return mExtents.x * 2.0f; } + inline_ float GetHeight() const { return mExtents.y * 2.0f; } + inline_ float GetDepth() const { return mExtents.z * 2.0f; } + + //! Volume + inline_ float GetVolume() const { return mExtents.x * mExtents.y * mExtents.z * 8.0f; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the intersection between two AABBs. + * \param a [in] the other AABB + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Intersect(const AABB& a) const + { + float tx = mCenter.x - a.mCenter.x; float ex = a.mExtents.x + mExtents.x; if(AIR(tx) > IR(ex)) return FALSE; + float ty = mCenter.y - a.mCenter.y; float ey = a.mExtents.y + mExtents.y; if(AIR(ty) > IR(ey)) return FALSE; + float tz = mCenter.z - a.mCenter.z; float ez = a.mExtents.z + mExtents.z; if(AIR(tz) > IR(ez)) return FALSE; + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * The standard intersection method from Gamasutra. Just here to check its speed against the one above. + * \param a [in] the other AABB + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool GomezIntersect(const AABB& a) + { + Point T = mCenter - a.mCenter; // Vector from A to B + return ((fabsf(T.x) <= (a.mExtents.x + mExtents.x)) + && (fabsf(T.y) <= (a.mExtents.y + mExtents.y)) + && (fabsf(T.z) <= (a.mExtents.z + mExtents.z))); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the 1D-intersection between two AABBs, on a given axis. + * \param a [in] the other AABB + * \param axis [in] the axis (0, 1, 2) + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Intersect(const AABB& a, udword axis) const + { + float t = mCenter[axis] - a.mCenter[axis]; + float e = a.mExtents[axis] + mExtents[axis]; + if(AIR(t) > IR(e)) return FALSE; + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Recomputes the AABB after an arbitrary transform by a 4x4 matrix. + * \param mtx [in] the transform matrix + * \param aabb [out] the transformed AABB [can be *this] + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const + { + // Compute new center + aabb.mCenter = mCenter * mtx; + + // Compute new extents. FPU code & CPU code have been interleaved for improved performance. + Point Ex(mtx.m[0][0] * mExtents.x, mtx.m[0][1] * mExtents.x, mtx.m[0][2] * mExtents.x); + IR(Ex.x)&=0x7fffffff; IR(Ex.y)&=0x7fffffff; IR(Ex.z)&=0x7fffffff; + + Point Ey(mtx.m[1][0] * mExtents.y, mtx.m[1][1] * mExtents.y, mtx.m[1][2] * mExtents.y); + IR(Ey.x)&=0x7fffffff; IR(Ey.y)&=0x7fffffff; IR(Ey.z)&=0x7fffffff; + + Point Ez(mtx.m[2][0] * mExtents.z, mtx.m[2][1] * mExtents.z, mtx.m[2][2] * mExtents.z); + IR(Ez.x)&=0x7fffffff; IR(Ez.y)&=0x7fffffff; IR(Ez.z)&=0x7fffffff; + + aabb.mExtents.x = Ex.x + Ey.x + Ez.x; + aabb.mExtents.y = Ex.y + Ey.y + Ez.y; + aabb.mExtents.z = Ex.z + Ey.z + Ez.z; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the AABB is valid. + * \return true if the box is valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsValid() const + { + // Consistency condition for (Center, Extents) boxes: Extents >= 0 + if(IS_NEGATIVE_FLOAT(mExtents.x)) return FALSE; + if(IS_NEGATIVE_FLOAT(mExtents.y)) return FALSE; + if(IS_NEGATIVE_FLOAT(mExtents.z)) return FALSE; + return TRUE; + } + + //! Operator for AABB *= float. Scales the extents, keeps same center. + inline_ AABB& operator*=(float s) { mExtents*=s; return *this; } + + //! Operator for AABB /= float. Scales the extents, keeps same center. + inline_ AABB& operator/=(float s) { mExtents/=s; return *this; } + + //! Operator for AABB += Point. Translates the box. + inline_ AABB& operator+=(const Point& trans) + { + mCenter+=trans; + return *this; + } + private: + Point mCenter; //!< AABB Center + Point mExtents; //!< x, y and z extents + }; + +#endif + + inline_ void ComputeMinMax(const Point& p, Point& min, Point& max) + { + if(p.x > max.x) max.x = p.x; + if(p.x < min.x) min.x = p.x; + + if(p.y > max.y) max.y = p.y; + if(p.y < min.y) min.y = p.y; + + if(p.z > max.z) max.z = p.z; + if(p.z < min.z) min.z = p.z; + } + + inline_ void ComputeAABB(AABB& aabb, const Point* list, udword nb_pts) + { + if(list) + { + Point Maxi(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); + Point Mini(MAX_FLOAT, MAX_FLOAT, MAX_FLOAT); + while(nb_pts--) + { +// _prefetch(list+1); // off by one ? + ComputeMinMax(*list++, Mini, Maxi); + } + aabb.SetMinMax(Mini, Maxi); + } + } + +#endif // __ICEAABB_H__ diff --git a/Extras/CDTestFramework/Opcode/Ice/_IceContainer.cpp b/Extras/CDTestFramework/Opcode/Ice/_IceContainer.cpp new file mode 100644 index 0000000..b5b6734 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/_IceContainer.cpp @@ -0,0 +1,361 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a simple container class. + * \file IceContainer.cpp + * \author Pierre Terdiman + * \date February, 5, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a list of 32-bits values. + * Use this class when you need to store an unknown number of values. The list is automatically + * resized and can contains 32-bits entities (dwords or floats) + * + * \class Container + * \author Pierre Terdiman + * \version 1.0 + * \date 08.15.98 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace IceCore; + +// Static members +#ifdef CONTAINER_STATS +udword Container::mNbContainers = 0; +udword Container::mUsedRam = 0; +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. No entries allocated there. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container::Container() : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f) +{ +#ifdef CONTAINER_STATS + mNbContainers++; + mUsedRam+=sizeof(Container); +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. Also allocates a given number of entries. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container::Container(udword size, float growth_factor) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(growth_factor) +{ +#ifdef CONTAINER_STATS + mNbContainers++; + mUsedRam+=sizeof(Container); +#endif + SetSize(size); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Copy constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container::Container(const Container& object) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f) +{ +#ifdef CONTAINER_STATS + mNbContainers++; + mUsedRam+=sizeof(Container); +#endif + *this = object; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. Frees everything and leaves. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container::~Container() +{ + Empty(); +#ifdef CONTAINER_STATS + mNbContainers--; + mUsedRam-=GetUsedRam(); +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Clears the container. All stored values are deleted, and it frees used ram. + * \see Reset() + * \return Self-Reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container& Container::Empty() +{ +#ifdef CONTAINER_STATS + mUsedRam-=mMaxNbEntries*sizeof(udword); +#endif + DELETEARRAY(mEntries); + mCurNbEntries = mMaxNbEntries = 0; + return *this; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Resizes the container. + * \param needed [in] assume the container can be added at least "needed" values + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Container::Resize(udword needed) +{ +#ifdef CONTAINER_STATS + // Subtract previous amount of bytes + mUsedRam-=mMaxNbEntries*sizeof(udword); +#endif + + // Get more entries + mMaxNbEntries = mMaxNbEntries ? udword(float(mMaxNbEntries)*mGrowthFactor) : 2; // Default nb Entries = 2 + if(mMaxNbEntriesmMaxNbEntries) Resize(nb); + + // Add new entry + CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(udword)); + mCurNbEntries+=nb; + return *this; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * A O(1) method to add a value in the container. The container is automatically resized if needed. + * The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation + * costs a lot more than the call overhead... + * + * \param entry [in] a float to store in the container + * \see Add(udword entry) + * \see Empty() + * \see Contains(udword entry) + * \return Self-Reference + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ Container& Add(float entry) + { + // Resize if needed + if(mCurNbEntries==mMaxNbEntries) Resize(); + + // Add new entry + mEntries[mCurNbEntries++] = IR(entry); + return *this; + } + + inline_ Container& Add(const float* entries, udword nb) + { + // Resize if needed + if(mCurNbEntries+nb>mMaxNbEntries) Resize(nb); + + // Add new entry + CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(float)); + mCurNbEntries+=nb; + return *this; + } + + //! Add unique [slow] + inline_ Container& AddUnique(udword entry) + { + if(!Contains(entry)) Add(entry); + return *this; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Clears the container. All stored values are deleted, and it frees used ram. + * \see Reset() + * \return Self-Reference + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Container& Empty(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Resets the container. Stored values are discarded but the buffer is kept so that further calls don't need resizing again. + * That's a kind of temporal coherence. + * \see Empty() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void Reset() + { + // Avoid the write if possible + // ### CMOV + if(mCurNbEntries) mCurNbEntries = 0; + } + + // HANDLE WITH CARE + inline_ void ForceSize(udword size) + { + mCurNbEntries = size; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Sets the initial size of the container. If it already contains something, it's discarded. + * \param nb [in] Number of entries + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool SetSize(udword nb); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Refits the container and get rid of unused bytes. + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Refit(); + + // Checks whether the container already contains a given value. + bool Contains(udword entry, udword* location=null) const; + // Deletes an entry - doesn't preserve insertion order. + bool Delete(udword entry); + // Deletes an entry - does preserve insertion order. + bool DeleteKeepingOrder(udword entry); + //! Deletes the very last entry. + inline_ void DeleteLastEntry() { if(mCurNbEntries) mCurNbEntries--; } + //! Deletes the entry whose index is given + inline_ void DeleteIndex(udword index) { mEntries[index] = mEntries[--mCurNbEntries]; } + + // Helpers + Container& FindNext(udword& entry, FindMode find_mode=FIND_CLAMP); + Container& FindPrev(udword& entry, FindMode find_mode=FIND_CLAMP); + // Data access. + inline_ udword GetNbEntries() const { return mCurNbEntries; } //!< Returns the current number of entries. + inline_ udword GetEntry(udword i) const { return mEntries[i]; } //!< Returns ith entry + inline_ udword* GetEntries() const { return mEntries; } //!< Returns the list of entries. + + inline_ udword GetFirst() const { return mEntries[0]; } + inline_ udword GetLast() const { return mEntries[mCurNbEntries-1]; } + + // Growth control + inline_ float GetGrowthFactor() const { return mGrowthFactor; } //!< Returns the growth factor + inline_ void SetGrowthFactor(float growth) { mGrowthFactor = growth; } //!< Sets the growth factor + inline_ bool IsFull() const { return mCurNbEntries==mMaxNbEntries; } //!< Checks the container is full + inline_ BOOL IsNotEmpty() const { return mCurNbEntries; } //!< Checks the container is empty + + //! Read-access as an array + inline_ udword operator[](udword i) const { ASSERT(i>=0 && i=0 && i>31); + return (float&)y; + } + + //! Computes 1.0f / sqrtf(x). + inline_ float frsqrt(float f) + { + float x = f * 0.5f; + udword y = 0x5f3759df - ((udword&)f >> 1); + // Iteration... + (float&)y = (float&)y * ( 1.5f - ( x * (float&)y * (float&)y ) ); + // Result + return (float&)y; + } + + //! Computes 1.0f / sqrtf(x). Comes from NVIDIA. + inline_ float InvSqrt(const float& x) + { + udword tmp = (udword(IEEE_1_0 << 1) + IEEE_1_0 - *(udword*)&x) >> 1; + float y = *(float*)&tmp; + return y * (1.47f - 0.47f * x * y * y); + } + + //! Computes 1.0f / sqrtf(x). Comes from Quake3. Looks like the first one I had above. + //! See http://www.magic-software.com/3DGEDInvSqrt.html + inline_ float RSqrt(float number) + { + long i; + float x2, y; + const float threehalfs = 1.5f; + + x2 = number * 0.5f; + y = number; + i = * (long *) &y; + i = 0x5f3759df - (i >> 1); + y = * (float *) &i; + y = y * (threehalfs - (x2 * y * y)); + + return y; + } + + //! TO BE DOCUMENTED + inline_ float fsqrt(float f) + { + udword y = ( ( (sdword&)f - 0x3f800000 ) >> 1 ) + 0x3f800000; + // Iteration...? + // (float&)y = (3.0f - ((float&)y * (float&)y) / f) * (float&)y * 0.5f; + // Result + return (float&)y; + } + + //! Returns the float ranged espilon value. + inline_ float fepsilon(float f) + { + udword b = (udword&)f & 0xff800000; + udword a = b | 0x00000001; + (float&)a -= (float&)b; + // Result + return (float&)a; + } + + //! Is the float valid ? + inline_ bool IsNAN(float value) { return (IR(value)&0x7f800000) == 0x7f800000; } + inline_ bool IsIndeterminate(float value) { return IR(value) == 0xffc00000; } + inline_ bool IsPlusInf(float value) { return IR(value) == 0x7f800000; } + inline_ bool IsMinusInf(float value) { return IR(value) == 0xff800000; } + + inline_ bool IsValidFloat(float value) + { + if(IsNAN(value)) return false; + if(IsIndeterminate(value)) return false; + if(IsPlusInf(value)) return false; + if(IsMinusInf(value)) return false; + return true; + } + + #define CHECK_VALID_FLOAT(x) ASSERT(IsValidFloat(x)); + +/* + //! FPU precision setting function. + inline_ void SetFPU() + { + // This function evaluates whether the floating-point + // control word is set to single precision/round to nearest/ + // exceptions disabled. If these conditions don't hold, the + // function changes the control word to set them and returns + // TRUE, putting the old control word value in the passback + // location pointed to by pwOldCW. + { + uword wTemp, wSave; + + __asm fstcw wSave + if (wSave & 0x300 || // Not single mode + 0x3f != (wSave & 0x3f) || // Exceptions enabled + wSave & 0xC00) // Not round to nearest mode + { + __asm + { + mov ax, wSave + and ax, not 300h ;; single mode + or ax, 3fh ;; disable all exceptions + and ax, not 0xC00 ;; round to nearest mode + mov wTemp, ax + fldcw wTemp + } + } + } + } +*/ + //! This function computes the slowest possible floating-point value (you can also directly use FLT_EPSILON) + inline_ float ComputeFloatEpsilon() + { + float f = 1.0f; + ((udword&)f)^=1; + return f - 1.0f; // You can check it's the same as FLT_EPSILON + } + + inline_ bool IsFloatZero(float x, float epsilon=1e-6f) + { + return x*x < epsilon; + } + + #define FCOMI_ST0 _asm _emit 0xdb _asm _emit 0xf0 + #define FCOMIP_ST0 _asm _emit 0xdf _asm _emit 0xf0 + #define FCMOVB_ST0 _asm _emit 0xda _asm _emit 0xc0 + #define FCMOVNB_ST0 _asm _emit 0xdb _asm _emit 0xc0 + + #define FCOMI_ST1 _asm _emit 0xdb _asm _emit 0xf1 + #define FCOMIP_ST1 _asm _emit 0xdf _asm _emit 0xf1 + #define FCMOVB_ST1 _asm _emit 0xda _asm _emit 0xc1 + #define FCMOVNB_ST1 _asm _emit 0xdb _asm _emit 0xc1 + + #define FCOMI_ST2 _asm _emit 0xdb _asm _emit 0xf2 + #define FCOMIP_ST2 _asm _emit 0xdf _asm _emit 0xf2 + #define FCMOVB_ST2 _asm _emit 0xda _asm _emit 0xc2 + #define FCMOVNB_ST2 _asm _emit 0xdb _asm _emit 0xc2 + + #define FCOMI_ST3 _asm _emit 0xdb _asm _emit 0xf3 + #define FCOMIP_ST3 _asm _emit 0xdf _asm _emit 0xf3 + #define FCMOVB_ST3 _asm _emit 0xda _asm _emit 0xc3 + #define FCMOVNB_ST3 _asm _emit 0xdb _asm _emit 0xc3 + + #define FCOMI_ST4 _asm _emit 0xdb _asm _emit 0xf4 + #define FCOMIP_ST4 _asm _emit 0xdf _asm _emit 0xf4 + #define FCMOVB_ST4 _asm _emit 0xda _asm _emit 0xc4 + #define FCMOVNB_ST4 _asm _emit 0xdb _asm _emit 0xc4 + + #define FCOMI_ST5 _asm _emit 0xdb _asm _emit 0xf5 + #define FCOMIP_ST5 _asm _emit 0xdf _asm _emit 0xf5 + #define FCMOVB_ST5 _asm _emit 0xda _asm _emit 0xc5 + #define FCMOVNB_ST5 _asm _emit 0xdb _asm _emit 0xc5 + + #define FCOMI_ST6 _asm _emit 0xdb _asm _emit 0xf6 + #define FCOMIP_ST6 _asm _emit 0xdf _asm _emit 0xf6 + #define FCMOVB_ST6 _asm _emit 0xda _asm _emit 0xc6 + #define FCMOVNB_ST6 _asm _emit 0xdb _asm _emit 0xc6 + + #define FCOMI_ST7 _asm _emit 0xdb _asm _emit 0xf7 + #define FCOMIP_ST7 _asm _emit 0xdf _asm _emit 0xf7 + #define FCMOVB_ST7 _asm _emit 0xda _asm _emit 0xc7 + #define FCMOVNB_ST7 _asm _emit 0xdb _asm _emit 0xc7 + + //! A global function to find MAX(a,b) using FCOMI/FCMOV + inline_ float FCMax2(float a, float b) + { + float Res; + _asm fld [a] + _asm fld [b] + FCOMI_ST1 + FCMOVB_ST1 + _asm fstp [Res] + _asm fcomp + return Res; + } + + //! A global function to find MIN(a,b) using FCOMI/FCMOV + inline_ float FCMin2(float a, float b) + { + float Res; + _asm fld [a] + _asm fld [b] + FCOMI_ST1 + FCMOVNB_ST1 + _asm fstp [Res] + _asm fcomp + return Res; + } + + //! A global function to find MAX(a,b,c) using FCOMI/FCMOV + inline_ float FCMax3(float a, float b, float c) + { + float Res; + _asm fld [a] + _asm fld [b] + _asm fld [c] + FCOMI_ST1 + FCMOVB_ST1 + FCOMI_ST2 + FCMOVB_ST2 + _asm fstp [Res] + _asm fcompp + return Res; + } + + //! A global function to find MIN(a,b,c) using FCOMI/FCMOV + inline_ float FCMin3(float a, float b, float c) + { + float Res; + _asm fld [a] + _asm fld [b] + _asm fld [c] + FCOMI_ST1 + FCMOVNB_ST1 + FCOMI_ST2 + FCMOVNB_ST2 + _asm fstp [Res] + _asm fcompp + return Res; + } + + inline_ int ConvertToSortable(float f) + { + int& Fi = (int&)f; + int Fmask = (Fi>>31); + Fi ^= Fmask; + Fmask &= ~(1<<31); + Fi -= Fmask; + return Fi; + } + + enum FPUMode + { + FPU_FLOOR = 0, + FPU_CEIL = 1, + FPU_BEST = 2, + + FPU_FORCE_DWORD = 0x7fffffff + }; + + FUNCTION ICECORE_API FPUMode GetFPUMode(); + FUNCTION ICECORE_API void SaveFPU(); + FUNCTION ICECORE_API void RestoreFPU(); + FUNCTION ICECORE_API void SetFPUFloorMode(); + FUNCTION ICECORE_API void SetFPUCeilMode(); + FUNCTION ICECORE_API void SetFPUBestMode(); + + FUNCTION ICECORE_API void SetFPUPrecision24(); + FUNCTION ICECORE_API void SetFPUPrecision53(); + FUNCTION ICECORE_API void SetFPUPrecision64(); + FUNCTION ICECORE_API void SetFPURoundingChop(); + FUNCTION ICECORE_API void SetFPURoundingUp(); + FUNCTION ICECORE_API void SetFPURoundingDown(); + FUNCTION ICECORE_API void SetFPURoundingNear(); + + FUNCTION ICECORE_API int intChop(const float& f); + FUNCTION ICECORE_API int intFloor(const float& f); + FUNCTION ICECORE_API int intCeil(const float& f); + +#endif // __ICEFPU_H__ diff --git a/Extras/CDTestFramework/Opcode/Ice/_IceMemoryMacros.h b/Extras/CDTestFramework/Opcode/Ice/_IceMemoryMacros.h new file mode 100644 index 0000000..c1867dc --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/_IceMemoryMacros.h @@ -0,0 +1,121 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains all memory macros. + * \file IceMemoryMacros.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEMEMORYMACROS_H__ +#define __ICEMEMORYMACROS_H__ + +#undef ZeroMemory +#undef CopyMemory +#undef MoveMemory +#undef FillMemory + + //! Clears a buffer. + //! \param addr [in] buffer address + //! \param size [in] buffer length + //! \see FillMemory + //! \see StoreDwords + //! \see CopyMemory + //! \see MoveMemory + inline_ void ZeroMemory(void* addr, udword size) { memset(addr, 0, size); } + + //! Fills a buffer with a given byte. + //! \param addr [in] buffer address + //! \param size [in] buffer length + //! \param val [in] the byte value + //! \see StoreDwords + //! \see ZeroMemory + //! \see CopyMemory + //! \see MoveMemory + inline_ void FillMemory(void* dest, udword size, ubyte val) { memset(dest, val, size); } + + //! Fills a buffer with a given dword. + //! \param addr [in] buffer address + //! \param nb [in] number of dwords to write + //! \param value [in] the dword value + //! \see FillMemory + //! \see ZeroMemory + //! \see CopyMemory + //! \see MoveMemory + //! \warning writes nb*4 bytes ! + inline_ void StoreDwords(udword* dest, udword nb, udword value) + { + // The asm code below **SHOULD** be equivalent to one of those C versions + // or the other if your compiled is good: (checked on VC++ 6.0) + // + // 1) while(nb--) *dest++ = value; + // + // 2) for(udword i=0;iRelease(); (x) = null; } //!< Safe D3D-style release + #define SAFE_DESTRUCT(x) if (x) { (x)->SelfDestruct(); (x) = null; } //!< Safe ICE-style release + +#ifdef __ICEERROR_H__ + #define CHECKALLOC(x) if(!x) return SetIceError("Out of memory.", EC_OUT_OF_MEMORY); //!< Standard alloc checking. HANDLE WITH CARE. +#else + #define CHECKALLOC(x) if(!x) return false; +#endif + + //! Standard allocation cycle + #define SAFE_ALLOC(ptr, type, count) DELETEARRAY(ptr); ptr = new type[count]; CHECKALLOC(ptr); + +#endif // __ICEMEMORYMACROS_H__ diff --git a/Extras/CDTestFramework/Opcode/Ice/_IcePreprocessor.h b/Extras/CDTestFramework/Opcode/Ice/_IcePreprocessor.h new file mode 100644 index 0000000..8019343 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/_IcePreprocessor.h @@ -0,0 +1,144 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains preprocessor stuff. This should be the first included header. + * \file IcePreprocessor.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEPREPROCESSOR_H__ +#define __ICEPREPROCESSOR_H__ + + // Check platform + #if defined( _WIN32 ) || defined( WIN32 ) + #pragma message("Compiling on Windows...") + #define PLATFORM_WINDOWS + #else + #pragma message("Compiling on unknown platform...") + #endif + + // Check compiler + #if defined(_MSC_VER) + #pragma message("Compiling with VC++...") + #define COMPILER_VISUAL_CPP + #else + #pragma message("Compiling with unknown compiler...") + #endif + + // Check compiler options. If this file is included in user-apps, this + // shouldn't be needed, so that they can use what they like best. + #ifndef ICE_DONT_CHECK_COMPILER_OPTIONS + #ifdef COMPILER_VISUAL_CPP + #if defined(_CHAR_UNSIGNED) + #endif + + #if defined(_CPPRTTI) + #error Please disable RTTI... + #endif + + #if defined(_CPPUNWIND) + #error Please disable exceptions... + #endif + + #if defined(_MT) + // Multithreading + #endif + #endif + #endif + + // Check debug mode + #ifdef DEBUG // May be defined instead of _DEBUG. Let's fix it. + #ifndef _DEBUG + #define _DEBUG + #endif + #endif + + #ifdef _DEBUG + // Here you may define items for debug builds + #endif + + #ifndef THIS_FILE + #define THIS_FILE __FILE__ + #endif + + #ifndef ICE_NO_DLL + #ifdef ICECORE_EXPORTS + #define ICECORE_API __declspec(dllexport) + #else + #define ICECORE_API __declspec(dllimport) + #endif + #else + #define ICECORE_API + #endif + + // Don't override new/delete +// #define DEFAULT_NEWDELETE + #define DONT_TRACK_MEMORY_LEAKS + + #define FUNCTION extern "C" + + // Cosmetic stuff [mainly useful with multiple inheritance] + #define override(base_class) virtual + + // Our own inline keyword, so that: + // - we can switch to __forceinline to check it's really better or not + // - we can remove __forceinline if the compiler doesn't support it +// #define inline_ __forceinline +// #define inline_ inline + + // Contributed by Bruce Mitchener + #if defined(COMPILER_VISUAL_CPP) + #define inline_ __forceinline +// #define inline_ inline + #elif defined(__GNUC__) && __GNUC__ < 3 + #define inline_ inline + #elif defined(__GNUC__) + #define inline_ inline __attribute__ ((always_inline)) + #else + #define inline_ inline + #endif + + // Down the hatch + #pragma inline_depth( 255 ) + + #ifdef COMPILER_VISUAL_CPP + #pragma intrinsic(memcmp) + #pragma intrinsic(memcpy) + #pragma intrinsic(memset) + #pragma intrinsic(strcat) + #pragma intrinsic(strcmp) + #pragma intrinsic(strcpy) + #pragma intrinsic(strlen) + #pragma intrinsic(abs) + #pragma intrinsic(labs) + #endif + + // ANSI compliance + #ifdef _DEBUG + // Remove painful warning in debug + inline_ bool __False__(){ return false; } + #define for if(__False__()){} else for + #else + #define for if(0){} else for + #endif + +#endif // __ICEPREPROCESSOR_H__ diff --git a/Extras/CDTestFramework/Opcode/Ice/_IceRevisitedRadix.cpp b/Extras/CDTestFramework/Opcode/Ice/_IceRevisitedRadix.cpp new file mode 100644 index 0000000..15e2468 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Ice/_IceRevisitedRadix.cpp @@ -0,0 +1,536 @@ +/* + * ICE / OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains source code from the article "Radix Sort Revisited". + * \file IceRevisitedRadix.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Revisited Radix Sort. + * This is my new radix routine: + * - it uses indices and doesn't recopy the values anymore, hence wasting less ram + * - it creates all the histograms in one run instead of four + * - it sorts words faster than dwords and bytes faster than words + * - it correctly sorts negative floating-point values by patching the offsets + * - it automatically takes advantage of temporal coherence + * - multiple keys support is a side effect of temporal coherence + * - it may be worth recoding in asm... (mainly to use FCOMI, FCMOV, etc) [it's probably memory-bound anyway] + * + * History: + * - 08.15.98: very first version + * - 04.04.00: recoded for the radix article + * - 12.xx.00: code lifting + * - 09.18.01: faster CHECK_PASS_VALIDITY thanks to Mark D. Shattuck (who provided other tips, not included here) + * - 10.11.01: added local ram support + * - 01.20.02: bugfix! In very particular cases the last pass was skipped in the float code-path, leading to incorrect sorting...... + * - 01.02.02: - "mIndices" renamed => "mRanks". That's a rank sorter after all. + * - ranks are not "reset" anymore, but implicit on first calls + * - 07.05.02: - offsets rewritten with one less indirection. + * - 11.03.02: - "bool" replaced with RadixHint enum + * + * \class RadixSort + * \author Pierre Terdiman + * \version 1.4 + * \date August, 15, 1998 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* +To do: + - add an offset parameter between two input values (avoid some data recopy sometimes) + - unroll ? asm ? + - 11 bits trick & 3 passes as Michael did + - prefetch stuff the day I have a P3 + - make a version with 16-bits indices ? +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace IceCore; + +#define INVALIDATE_RANKS mCurrentSize|=0x80000000 +#define VALIDATE_RANKS mCurrentSize&=0x7fffffff +#define CURRENT_SIZE (mCurrentSize&0x7fffffff) +#define INVALID_RANKS (mCurrentSize&0x80000000) + +#define CHECK_RESIZE(n) \ + if(n!=mPreviousSize) \ + { \ + if(n>mCurrentSize) Resize(n); \ + else ResetRanks(); \ + mPreviousSize = n; \ + } + +#define CREATE_HISTOGRAMS(type, buffer) \ + /* Clear counters/histograms */ \ + ZeroMemory(mHistogram, 256*4*sizeof(udword)); \ + \ + /* Prepare to count */ \ + ubyte* p = (ubyte*)input; \ + ubyte* pe = &p[nb*4]; \ + udword* h0= &mHistogram[0]; /* Histogram for first pass (LSB) */ \ + udword* h1= &mHistogram[256]; /* Histogram for second pass */ \ + udword* h2= &mHistogram[512]; /* Histogram for third pass */ \ + udword* h3= &mHistogram[768]; /* Histogram for last pass (MSB) */ \ + \ + bool AlreadySorted = true; /* Optimism... */ \ + \ + if(INVALID_RANKS) \ + { \ + /* Prepare for temporal coherence */ \ + type* Running = (type*)buffer; \ + type PrevVal = *Running; \ + \ + while(p!=pe) \ + { \ + /* Read input buffer in previous sorted order */ \ + type Val = *Running++; \ + /* Check whether already sorted or not */ \ + if(ValCurSize) Resize(nb); + mCurrentSize = nb; + INVALIDATE_RANKS; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Main sort routine. + * This one is for integer values. After the call, mRanks contains a list of indices in sorted order, i.e. in the order you may process your data. + * \param input [in] a list of integer values to sort + * \param nb [in] number of values to sort, must be < 2^31 + * \param hint [in] RADIX_SIGNED to handle negative values, RADIX_UNSIGNED if you know your input buffer only contains positive values + * \return Self-Reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +RadixSort& RadixSort::Sort(const udword* input, udword nb, RadixHint hint) +{ + // Checkings + if(!input || !nb || nb&0x80000000) return *this; + + // Stats + mTotalCalls++; + + // Resize lists if needed + CheckResize(nb); + +#ifdef RADIX_LOCAL_RAM + // Allocate histograms & offsets on the stack + udword mHistogram[256*4]; +// udword mOffset[256]; + udword* mLink[256]; +#endif + + // Create histograms (counters). Counters for all passes are created in one run. + // Pros: read input buffer once instead of four times + // Cons: mHistogram is 4Kb instead of 1Kb + // We must take care of signed/unsigned values for temporal coherence.... I just + // have 2 code paths even if just a single opcode changes. Self-modifying code, someone? + if(hint==RADIX_UNSIGNED) { CREATE_HISTOGRAMS(udword, input); } + else { CREATE_HISTOGRAMS(sdword, input); } + + // Compute #negative values involved if needed + udword NbNegativeValues = 0; + if(hint==RADIX_SIGNED) + { + // An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128 + // last values of the last histogram. Last histogram because that's the one for the Most Significant Byte, + // responsible for the sign. 128 last values because the 128 first ones are related to positive numbers. + udword* h3= &mHistogram[768]; + for(udword i=128;i<256;i++) NbNegativeValues += h3[i]; // 768 for last histogram, 128 for negative part + } + + // Radix sort, j is the pass number (0=LSB, 3=MSB) + for(udword j=0;j<4;j++) + { + CHECK_PASS_VALIDITY(j); + + // Sometimes the fourth (negative) pass is skipped because all numbers are negative and the MSB is 0xFF (for example). This is + // not a problem, numbers are correctly sorted anyway. + if(PerformPass) + { + // Should we care about negative values? + if(j!=3 || hint==RADIX_UNSIGNED) + { + // Here we deal with positive values only + + // Create offsets +// mOffset[0] = 0; +// for(udword i=1;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; + mLink[0] = mRanks2; + for(udword i=1;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; + } + else + { + // This is a special case to correctly handle negative integers. They're sorted in the right order but at the wrong place. + + // Create biased offsets, in order for negative numbers to be sorted as well +// mOffset[0] = NbNegativeValues; // First positive number takes place after the negative ones + mLink[0] = &mRanks2[NbNegativeValues]; // First positive number takes place after the negative ones +// for(udword i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers + for(udword i=1;i<128;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers + + // Fixing the wrong place for negative values +// mOffset[128] = 0; + mLink[128] = mRanks2; +// for(i=129;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; + for(udword i=129;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; + } + + // Perform Radix Sort + ubyte* InputBytes = (ubyte*)input; + InputBytes += j; + if(INVALID_RANKS) + { +// for(udword i=0;i>24; // Radix byte, same as above. AND is useless here (udword). + // ### cmp to be killed. Not good. Later. +// if(Radix<128) mRanks2[mOffset[Radix]++] = i; // Number is positive, same as above +// else mRanks2[--mOffset[Radix]] = i; // Number is negative, flip the sorting order + if(Radix<128) *mLink[Radix]++ = i; // Number is positive, same as above + else *(--mLink[Radix]) = i; // Number is negative, flip the sorting order + } + VALIDATE_RANKS; + } + else + { + for(udword i=0;i>24; // Radix byte, same as above. AND is useless here (udword). + // ### cmp to be killed. Not good. Later. +// if(Radix<128) mRanks2[mOffset[Radix]++] = mRanks[i]; // Number is positive, same as above +// else mRanks2[--mOffset[Radix]] = mRanks[i]; // Number is negative, flip the sorting order + if(Radix<128) *mLink[Radix]++ = mRanks[i]; // Number is positive, same as above + else *(--mLink[Radix]) = mRanks[i]; // Number is negative, flip the sorting order + } + } + // Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap. + udword* Tmp = mRanks; mRanks = mRanks2; mRanks2 = Tmp; + } + else + { + // The pass is useless, yet we still have to reverse the order of current list if all values are negative. + if(UniqueVal>=128) + { + if(INVALID_RANKS) + { + // ###Possible? + for(udword i=0;i (b) ? (a) : (b)) //!< Returns the max value between a and b + #define MAXMAX(a,b,c) ((a) > (b) ? MAX (a,c) : MAX (b,c)) //!< Returns the max value between a, b and c + + template inline_ const T& TMin (const T& a, const T& b) { return b < a ? b : a; } + template inline_ const T& TMax (const T& a, const T& b) { return a < b ? b : a; } + template inline_ void TSetMin (T& a, const T& b) { if(a>b) a = b; } + template inline_ void TSetMax (T& a, const T& b) { if(a> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa); + n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc); + n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0); + n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00); + n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000); + // Etc for larger intergers (64 bits in Java) + // NOTE: the >> operation must be unsigned! (>>> in java) + } + + //! Count the number of '1' bits in a 32 bit word (from Steve Baker's Cute Code Collection) + inline_ udword CountBits(udword n) + { + // This relies of the fact that the count of n bits can NOT overflow + // an n bit interger. EG: 1 bit count takes a 1 bit interger, 2 bit counts + // 2 bit interger, 3 bit count requires only a 2 bit interger. + // So we add all bit pairs, then each nible, then each byte etc... + n = (n & 0x55555555) + ((n & 0xaaaaaaaa) >> 1); + n = (n & 0x33333333) + ((n & 0xcccccccc) >> 2); + n = (n & 0x0f0f0f0f) + ((n & 0xf0f0f0f0) >> 4); + n = (n & 0x00ff00ff) + ((n & 0xff00ff00) >> 8); + n = (n & 0x0000ffff) + ((n & 0xffff0000) >> 16); + // Etc for larger intergers (64 bits in Java) + // NOTE: the >> operation must be unsigned! (>>> in java) + return n; + } + + //! Even faster? + inline_ udword CountBits2(udword bits) + { + bits = bits - ((bits >> 1) & 0x55555555); + bits = ((bits >> 2) & 0x33333333) + (bits & 0x33333333); + bits = ((bits >> 4) + bits) & 0x0F0F0F0F; + return (bits * 0x01010101) >> 24; + } + + //! Spread out bits. EG 00001111 -> 0101010101 + //! 00001010 -> 0100010000 + //! This is used to interleve to intergers to produce a `Morten Key' + //! used in Space Filling Curves (See DrDobbs Journal, July 1999) + //! Order is important. + inline_ void SpreadBits(udword& n) + { + n = ( n & 0x0000ffff) | (( n & 0xffff0000) << 16); + n = ( n & 0x000000ff) | (( n & 0x0000ff00) << 8); + n = ( n & 0x000f000f) | (( n & 0x00f000f0) << 4); + n = ( n & 0x03030303) | (( n & 0x0c0c0c0c) << 2); + n = ( n & 0x11111111) | (( n & 0x22222222) << 1); + } + + // Next Largest Power of 2 + // Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm + // that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with + // the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next + // largest power of 2. For a 32-bit value: + inline_ udword nlpo2(udword x) + { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return x+1; + } + + //! Test to see if a number is an exact power of two (from Steve Baker's Cute Code Collection) + inline_ bool IsPowerOfTwo(udword n) { return ((n&(n-1))==0); } + + //! Zero the least significant '1' bit in a word. (from Steve Baker's Cute Code Collection) + inline_ void ZeroLeastSetBit(udword& n) { n&=(n-1); } + + //! Set the least significant N bits in a word. (from Steve Baker's Cute Code Collection) + inline_ void SetLeastNBits(udword& x, udword n) { x|=~(~0<> 31; return (x^y)-y; } + + //!< Alternative min function + inline_ sdword min_(sdword a, sdword b) { sdword delta = b-a; return a + (delta&(delta>>31)); } + + // Determine if one of the bytes in a 4 byte word is zero + inline_ BOOL HasNullByte(udword x) { return ((x + 0xfefefeff) & (~x) & 0x80808080); } + + // To find the smallest 1 bit in a word EG: ~~~~~~10---0 => 0----010---0 + inline_ udword LowestOneBit(udword w) { return ((w) & (~(w)+1)); } +// inline_ udword LowestOneBit_(udword w) { return ((w) & (-(w))); } + + // Most Significant 1 Bit + // Given a binary integer value x, the most significant 1 bit (highest numbered element of a bit set) + // can be computed using a SWAR algorithm that recursively "folds" the upper bits into the lower bits. + // This process yields a bit vector with the same most significant 1 as x, but all 1's below it. + // Bitwise AND of the original value with the complement of the "folded" value shifted down by one + // yields the most significant bit. For a 32-bit value: + inline_ udword msb32(udword x) + { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return (x & ~(x >> 1)); + } + + /* + "Just call it repeatedly with various input values and always with the same variable as "memory". + The sharpness determines the degree of filtering, where 0 completely filters out the input, and 1 + does no filtering at all. + + I seem to recall from college that this is called an IIR (Infinite Impulse Response) filter. As opposed + to the more typical FIR (Finite Impulse Response). + + Also, I'd say that you can make more intelligent and interesting filters than this, for example filters + that remove wrong responses from the mouse because it's being moved too fast. You'd want such a filter + to be applied before this one, of course." + + (JCAB on Flipcode) + */ + inline_ float FeedbackFilter(float val, float& memory, float sharpness) + { + ASSERT(sharpness>=0.0f && sharpness<=1.0f && "Invalid sharpness value in feedback filter"); + if(sharpness<0.0f) sharpness = 0.0f; + else if(sharpness>1.0f) sharpness = 1.0f; + return memory = val * sharpness + memory * (1.0f - sharpness); + } + + //! If you can guarantee that your input domain (i.e. value of x) is slightly + //! limited (abs(x) must be < ((1<<31u)-32767)), then you can use the + //! following code to clamp the resulting value into [-32768,+32767] range: + inline_ int ClampToInt16(int x) + { +// ASSERT(abs(x) < (int)((1<<31u)-32767)); + + int delta = 32767 - x; + x += (delta>>31) & delta; + delta = x + 32768; + x -= (delta>>31) & delta; + return x; + } + + // Generic functions + template inline_ void TSwap(Type& a, Type& b) { const Type c = a; a = b; b = c; } + template inline_ Type TClamp(const Type& x, const Type& lo, const Type& hi) { return ((xhi) ? hi : x); } + + template inline_ void TSort(Type& a, Type& b) + { + if(a>b) TSwap(a, b); + } + + template inline_ void TSort(Type& a, Type& b, Type& c) + { + if(a>b) TSwap(a, b); + if(b>c) TSwap(b, c); + if(a>b) TSwap(a, b); + if(b>c) TSwap(b, c); + } + + // Prevent nasty user-manipulations (strategy borrowed from Charles Bloom) +// #define PREVENT_COPY(curclass) void operator = (const curclass& object) { ASSERT(!"Bad use of operator ="); } + // ... actually this is better ! + #define PREVENT_COPY(cur_class) private: cur_class(const cur_class& object); cur_class& operator=(const cur_class& object); + + //! TO BE DOCUMENTED + #define OFFSET_OF(Class, Member) (size_t)&(((Class*)0)->Member) + //! TO BE DOCUMENTED + #define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0])) + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Returns the alignment of the input address. + * \fn Alignment() + * \param address [in] address to check + * \return the best alignment (e.g. 1 for odd addresses, etc) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + FUNCTION ICECORE_API udword Alignment(udword address); + + #define IS_ALIGNED_2(x) ((x&1)==0) + #define IS_ALIGNED_4(x) ((x&3)==0) + #define IS_ALIGNED_8(x) ((x&7)==0) + + inline_ void _prefetch(void const* ptr) { (void)*(char const volatile *)ptr; } + + // Compute implicit coords from an index: + // The idea is to get back 2D coords from a 1D index. + // For example: + // + // 0 1 2 ... nbu-1 + // nbu nbu+1 i ... + // + // We have i, we're looking for the equivalent (u=2, v=1) location. + // i = u + v*nbu + // <=> i/nbu = u/nbu + v + // Since 0 <= u < nbu, u/nbu = 0 (integer) + // Hence: v = i/nbu + // Then we simply put it back in the original equation to compute u = i - v*nbu + inline_ void Compute2DCoords(udword& u, udword& v, udword i, udword nbu) + { + v = i / nbu; + u = i - (v * nbu); + } + + // In 3D: i = u + v*nbu + w*nbu*nbv + // <=> i/(nbu*nbv) = u/(nbu*nbv) + v/nbv + w + // u/(nbu*nbv) is null since u/nbu was null already. + // v/nbv is null as well for the same reason. + // Hence w = i/(nbu*nbv) + // Then we're left with a 2D problem: i' = i - w*nbu*nbv = u + v*nbu + inline_ void Compute3DCoords(udword& u, udword& v, udword& w, udword i, udword nbu, udword nbu_nbv) + { + w = i / (nbu_nbv); + Compute2DCoords(u, v, i - (w * nbu_nbv), nbu); + } + +#endif // __ICEUTILS_H__ diff --git a/Extras/CDTestFramework/Opcode/OPC_AABBCollider.cpp b/Extras/CDTestFramework/Opcode/OPC_AABBCollider.cpp new file mode 100644 index 0000000..568fd6b --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_AABBCollider.cpp @@ -0,0 +1,705 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for an AABB collider. + * \file OPC_AABBCollider.cpp + * \author Pierre Terdiman + * \date January, 1st, 2002 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an AABB-vs-tree collider. + * + * \class AABBCollider + * \author Pierre Terdiman + * \version 1.3 + * \date January, 1st, 2002 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +#include "OPC_BoxBoxOverlap.h" +#include "OPC_TriBoxOverlap.h" + +#define SET_CONTACT(prim_index, flag) \ + /* Set contact status */ \ + mFlags |= flag; \ + mTouchedPrimitives->Add(prim_index); + +//! AABB-triangle test +#define AABB_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + VertexPointers VP; mIMesh->GetTriangle(VP, prim_index);\ + mLeafVerts[0] = *VP.Vertex[0]; \ + mLeafVerts[1] = *VP.Vertex[1]; \ + mLeafVerts[2] = *VP.Vertex[2]; \ + /* Perform triangle-box overlap test */ \ + if(TriBoxOverlap()) \ + { \ + SET_CONTACT(prim_index, flag) \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBCollider::AABBCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBCollider::~AABBCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a box cache + * \param box [in] collision AABB in world space + * \param model [in] Opcode model to collide with + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const Model& model) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, box)) return true; + + if(!model.HasLeafNodes()) + { + if(model.IsQuantized()) + { + const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - check temporal coherence + * + * \param cache [in/out] a box cache + * \param box [in] AABB in world space + * \return TRUE if we can return immediately + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL AABBCollider::InitQuery(AABBCache& cache, const CollisionAABB& box) +{ + // 1) Call the base method + VolumeCollider::InitQuery(); + + // 2) Keep track of the query box + mBox = box; + + // 3) Setup destination pointer + mTouchedPrimitives = &cache.TouchedPrimitives; + + // 4) Special case: 1-triangle meshes [Opcode 1.3] + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + if(!SkipPrimitiveTests()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + mTouchedPrimitives->Reset(); + + // Perform overlap test between the unique triangle and the box (and set contact status if needed) + AABB_PRIM(udword(0), OPC_CONTACT) + + // Return immediately regardless of status + return TRUE; + } + } + + // 5) Check temporal coherence : + if(TemporalCoherenceEnabled()) + { + // Here we use temporal coherence + // => check results from previous frame before performing the collision query + if(FirstContactEnabled()) + { + // We're only interested in the first contact found => test the unique previously touched face + if(mTouchedPrimitives->GetNbEntries()) + { + // Get index of previously touched face = the first entry in the array + udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); + + // Then reset the array: + // - if the overlap test below is successful, the index we'll get added back anyway + // - if it isn't, then the array should be reset anyway for the normal query + mTouchedPrimitives->Reset(); + + // Perform overlap test between the cached triangle and the box (and set contact status if needed) + AABB_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) + + // Return immediately if possible + if(GetContactStatus()) return TRUE; + } + // else no face has been touched during previous query + // => we'll have to perform a normal query + } + else + { + // We're interested in all contacts =>test the new real box N(ew) against the previous fat box P(revious): + if(IsCacheValid(cache) && mBox.IsInside(cache.FatBox)) + { + // - if N is included in P, return previous list + // => we simply leave the list (mTouchedFaces) unchanged + + // Set contact status if needed + if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; + + // In any case we don't need to do a query + return TRUE; + } + else + { + // - else do the query using a fat N + + // Reset cache since we'll about to perform a real query + mTouchedPrimitives->Reset(); + + // Make a fat box so that coherence will work for subsequent frames + mBox.mExtents *= cache.FatCoeff; + + // Update cache with query data (signature for cached faces) + cache.FatBox = mBox; + } + } + } + else + { + // Here we don't use temporal coherence => do a normal query + mTouchedPrimitives->Reset(); + } + + // 5) Precompute min & max bounds if needed + mMin = box.mCenter - box.mExtents; + mMax = box.mCenter + box.mExtents; + + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for vanilla AABB trees. + * \param cache [in/out] a box cache + * \param box [in] collision AABB in world space + * \param tree [in] AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const AABBTree* tree) +{ + // This is typically called for a scene tree, full of -AABBs-, not full of triangles. + // So we don't really have "primitives" to deal with. Hence it doesn't work with + // "FirstContact" + "TemporalCoherence". + ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); + + // Checkings + if(!tree) return false; + + // Init collision query + if(InitQuery(cache, box)) return true; + + // Perform collision query + _Collide(tree); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the AABB completely contains the box. In which case we can end the query sooner. + * \param bc [in] box center + * \param be [in] box extents + * \return true if the AABB contains the whole box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL AABBCollider::AABBContainsBox(const Point& bc, const Point& be) +{ + if(mMin.x > bc.x - be.x) return FALSE; + if(mMin.y > bc.y - be.y) return FALSE; + if(mMin.z > bc.z - be.z) return FALSE; + + if(mMax.x < bc.x + be.x) return FALSE; + if(mMax.y < bc.y + be.y) return FALSE; + if(mMax.z < bc.z + be.z) return FALSE; + + return TRUE; +} + +#define TEST_BOX_IN_AABB(center, extents) \ + if(AABBContainsBox(center, extents)) \ + { \ + /* Set contact status */ \ + mFlags |= OPC_CONTACT; \ + _Dump(node); \ + return; \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_Collide(const AABBCollisionNode* node) +{ + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + AABB_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) +{ + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_Collide(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(Extents, Center)) return; + + TEST_BOX_IN_AABB(Center, Extents) + + if(node->IsLeaf()) + { + AABB_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(Extents, Center)) return; + + TEST_BOX_IN_AABB(Center, Extents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_Collide(const AABBNoLeafNode* node) +{ + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) +{ + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_Collide(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(Extents, Center)) return; + + TEST_BOX_IN_AABB(Center, Extents) + + if(node->HasPosLeaf()) { AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(Extents, Center)) return; + + TEST_BOX_IN_AABB(Center, Extents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for vanilla AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_Collide(const AABBTreeNode* node) +{ + // Perform AABB-AABB overlap test + Point Center, Extents; + node->GetAABB()->GetCenter(Center); + node->GetAABB()->GetExtents(Extents); + if(!AABBAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf() || AABBContainsBox(Center, Extents)) + { + mFlags |= OPC_CONTACT; + mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives()); + } + else + { + _Collide(node->GetPos()); + _Collide(node->GetNeg()); + } +} + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridAABBCollider::HybridAABBCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridAABBCollider::~HybridAABBCollider() +{ +} + +bool HybridAABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const HybridModel& model) +{ + // We don't want primitive tests here! + mFlags |= OPC_NO_PRIMITIVE_TESTS; + + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, box)) return true; + + // Special case for 1-leaf trees + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles + udword Nb = mIMesh->GetNbTriangles(); + + // Loop through all triangles + for(udword i=0;imCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + + // We only have a list of boxes so far + if(GetContactStatus()) + { + // Reset contact status, since it currently only reflects collisions with leaf boxes + Collider::InitQuery(); + + // Change dest container so that we can use built-in overlap tests and get collided primitives + cache.TouchedPrimitives.Reset(); + mTouchedPrimitives = &cache.TouchedPrimitives; + + // Read touched leaf boxes + udword Nb = mTouchedBoxes.GetNbEntries(); + const udword* Touched = mTouchedBoxes.GetEntries(); + + const LeafTriangles* LT = model.GetLeafTriangles(); + const udword* Indices = model.GetIndices(); + + // Loop through touched leaves + while(Nb--) + { + const LeafTriangles& CurrentLeaf = LT[*Touched++]; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = *T++; + AABB_PRIM(TriangleIndex, OPC_CONTACT) + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = BaseIndex++; + AABB_PRIM(TriangleIndex, OPC_CONTACT) + } + } + } + } + + return true; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_AABBCollider.h b/Extras/CDTestFramework/Opcode/OPC_AABBCollider.h new file mode 100644 index 0000000..ca8aee9 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_AABBCollider.h @@ -0,0 +1,106 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for an AABB collider. + * \file OPC_AABBCollider.h + * \author Pierre Terdiman + * \date January, 1st, 2002 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_AABBCOLLIDER_H__ +#define __OPC_AABBCOLLIDER_H__ + + struct OPCODE_API AABBCache : VolumeCache + { + AABBCache() : FatCoeff(1.1f) + { + FatBox.mCenter.Zero(); + FatBox.mExtents.Zero(); + } + + // Cached faces signature + CollisionAABB FatBox; //!< Box used when performing the query resulting in cached faces + // User settings + float FatCoeff; //!< mRadius2 multiplier used to create a fat sphere + }; + + class OPCODE_API AABBCollider : public VolumeCollider + { + public: + // Constructor / Destructor + AABBCollider(); + virtual ~AABBCollider(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a box cache + * \param box [in] collision AABB in world space + * \param model [in] Opcode model to collide with + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(AABBCache& cache, const CollisionAABB& box, const Model& model); + // + bool Collide(AABBCache& cache, const CollisionAABB& box, const AABBTree* tree); + protected: + CollisionAABB mBox; //!< Query box in (center, extents) form + Point mMin; //!< Query box min point + Point mMax; //!< Query box max point + // Leaf description + Point mLeafVerts[3]; //!< Triangle vertices + // Internal methods + void _Collide(const AABBCollisionNode* node); + void _Collide(const AABBNoLeafNode* node); + void _Collide(const AABBQuantizedNode* node); + void _Collide(const AABBQuantizedNoLeafNode* node); + void _Collide(const AABBTreeNode* node); + void _CollideNoPrimitiveTest(const AABBCollisionNode* node); + void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); + // Overlap tests + inline_ BOOL AABBContainsBox(const Point& bc, const Point& be); + inline_ BOOL AABBAABBOverlap(const Point& b, const Point& Pb); + inline_ BOOL TriBoxOverlap(); + // Init methods + BOOL InitQuery(AABBCache& cache, const CollisionAABB& box); + }; + + class OPCODE_API HybridAABBCollider : public AABBCollider + { + public: + // Constructor / Destructor + HybridAABBCollider(); + virtual ~HybridAABBCollider(); + + bool Collide(AABBCache& cache, const CollisionAABB& box, const HybridModel& model); + protected: + Container mTouchedBoxes; + }; + +#endif // __OPC_AABBCOLLIDER_H__ diff --git a/Extras/CDTestFramework/Opcode/OPC_AABBTree.cpp b/Extras/CDTestFramework/Opcode/OPC_AABBTree.cpp new file mode 100644 index 0000000..bb692bb --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_AABBTree.cpp @@ -0,0 +1,582 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a versatile AABB tree. + * \file OPC_AABBTree.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a generic AABB tree node. + * + * \class AABBTreeNode + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a generic AABB tree. + * This is a vanilla AABB tree, without any particular optimization. It contains anonymous references to + * user-provided primitives, which can theoretically be anything - triangles, boxes, etc. Each primitive + * is surrounded by an AABB, regardless of the primitive's nature. When the primitive is a triangle, the + * resulting tree can be converted into an optimized tree. If the primitive is a box, the resulting tree + * can be used for culling - VFC or occlusion -, assuming you cull on a mesh-by-mesh basis (modern way). + * + * \class AABBTree + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBTreeNode::AABBTreeNode() : + mPos (null), +#ifndef OPC_NO_NEG_VANILLA_TREE + mNeg (null), +#endif + mNbPrimitives (0), + mNodePrimitives (null) +{ +#ifdef OPC_USE_TREE_COHERENCE + mBitmask = 0; +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBTreeNode::~AABBTreeNode() +{ + // Opcode 1.3: + const AABBTreeNode* Pos = GetPos(); + const AABBTreeNode* Neg = GetNeg(); +#ifndef OPC_NO_NEG_VANILLA_TREE + if(!(mPos&1)) DELETESINGLE(Pos); + if(!(mNeg&1)) DELETESINGLE(Neg); +#else + if(!(mPos&1)) DELETEARRAY(Pos); +#endif + mNodePrimitives = null; // This was just a shortcut to the global list => no release + mNbPrimitives = 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Splits the node along a given axis. + * The list of indices is reorganized according to the split values. + * \param axis [in] splitting axis index + * \param builder [in] the tree builder + * \return the number of primitives assigned to the first child + * \warning this method reorganizes the internal list of primitives + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword AABBTreeNode::Split(udword axis, AABBTreeBuilder* builder) +{ + // Get node split value + float SplitValue = builder->GetSplittingValue(mNodePrimitives, mNbPrimitives, mBV, axis); + + udword NbPos = 0; + // Loop through all node-related primitives. Their indices range from mNodePrimitives[0] to mNodePrimitives[mNbPrimitives-1]. + // Those indices map the global list in the tree builder. + for(udword i=0;iGetSplittingValue(Index, axis); + + // Reorganize the list of indices in this order: positive - negative. + if(PrimitiveValue > SplitValue) + { + // Swap entries + udword Tmp = mNodePrimitives[i]; + mNodePrimitives[i] = mNodePrimitives[NbPos]; + mNodePrimitives[NbPos] = Tmp; + // Count primitives assigned to positive space + NbPos++; + } + } + return NbPos; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Subdivides the node. + * + * N + * / \ + * / \ + * N/2 N/2 + * / \ / \ + * N/4 N/4 N/4 N/4 + * (etc) + * + * A well-balanced tree should have a O(log n) depth. + * A degenerate tree would have a O(n) depth. + * Note a perfectly-balanced tree is not well-suited to collision detection anyway. + * + * \param builder [in] the tree builder + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeNode::Subdivide(AABBTreeBuilder* builder) +{ + // Checkings + if(!builder) return false; + + // Stop subdividing if we reach a leaf node. This is always performed here, + // else we could end in trouble if user overrides this. + if(mNbPrimitives==1) return true; + + // Let the user validate the subdivision + if(!builder->ValidateSubdivision(mNodePrimitives, mNbPrimitives, mBV)) return true; + + bool ValidSplit = true; // Optimism... + udword NbPos; + if(builder->mSettings.mRules & SPLIT_LARGEST_AXIS) + { + // Find the largest axis to split along + Point Extents; mBV.GetExtents(Extents); // Box extents + udword Axis = Extents.LargestAxis(); // Index of largest axis + + // Split along the axis + NbPos = Split(Axis, builder); + + // Check split validity + if(!NbPos || NbPos==mNbPrimitives) ValidSplit = false; + } + else if(builder->mSettings.mRules & SPLIT_SPLATTER_POINTS) + { + // Compute the means + Point Means(0.0f, 0.0f, 0.0f); + for(udword i=0;iGetSplittingValue(Index, 0); + Means.y+=builder->GetSplittingValue(Index, 1); + Means.z+=builder->GetSplittingValue(Index, 2); + } + Means/=float(mNbPrimitives); + + // Compute variances + Point Vars(0.0f, 0.0f, 0.0f); + for(udword i=0;iGetSplittingValue(Index, 0); + float Cy = builder->GetSplittingValue(Index, 1); + float Cz = builder->GetSplittingValue(Index, 2); + Vars.x += (Cx - Means.x)*(Cx - Means.x); + Vars.y += (Cy - Means.y)*(Cy - Means.y); + Vars.z += (Cz - Means.z)*(Cz - Means.z); + } + Vars/=float(mNbPrimitives-1); + + // Choose axis with greatest variance + udword Axis = Vars.LargestAxis(); + + // Split along the axis + NbPos = Split(Axis, builder); + + // Check split validity + if(!NbPos || NbPos==mNbPrimitives) ValidSplit = false; + } + else if(builder->mSettings.mRules & SPLIT_BALANCED) + { + // Test 3 axis, take the best + float Results[3]; + NbPos = Split(0, builder); Results[0] = float(NbPos)/float(mNbPrimitives); + NbPos = Split(1, builder); Results[1] = float(NbPos)/float(mNbPrimitives); + NbPos = Split(2, builder); Results[2] = float(NbPos)/float(mNbPrimitives); + Results[0]-=0.5f; Results[0]*=Results[0]; + Results[1]-=0.5f; Results[1]*=Results[1]; + Results[2]-=0.5f; Results[2]*=Results[2]; + udword Min=0; + if(Results[1]mSettings.mRules & SPLIT_BEST_AXIS) + { + // Test largest, then middle, then smallest axis... + + // Sort axis + Point Extents; mBV.GetExtents(Extents); // Box extents + udword SortedAxis[] = { 0, 1, 2 }; + float* Keys = (float*)&Extents.x; + for(udword j=0;j<3;j++) + { + for(udword i=0;i<2;i++) + { + if(Keys[SortedAxis[i]]mSettings.mRules & SPLIT_FIFTY) + { + // Don't even bother splitting (mainly a performance test) + NbPos = mNbPrimitives>>1; + } + else return false; // Unknown splitting rules + + // Check the subdivision has been successful + if(!ValidSplit) + { + // Here, all boxes lie in the same sub-space. Two strategies: + // - if the tree *must* be complete, make an arbitrary 50-50 split + // - else stop subdividing +// if(builder->mSettings.mRules&SPLIT_COMPLETE) + if(builder->mSettings.mLimit==1) + { + builder->IncreaseNbInvalidSplits(); + NbPos = mNbPrimitives>>1; + } + else return true; + } + + // Now create children and assign their pointers. + if(builder->mNodeBase) + { + // We use a pre-allocated linear pool for complete trees [Opcode 1.3] + AABBTreeNode* Pool = (AABBTreeNode*)builder->mNodeBase; + udword Count = builder->GetCount() - 1; // Count begins to 1... + // Set last bit to tell it shouldn't be freed ### pretty ugly, find a better way. Maybe one bit in mNbPrimitives + ASSERT(!(udword(&Pool[Count+0])&1)); + ASSERT(!(udword(&Pool[Count+1])&1)); + mPos = udword(&Pool[Count+0])|1; +#ifndef OPC_NO_NEG_VANILLA_TREE + mNeg = udword(&Pool[Count+1])|1; +#endif + } + else + { + // Non-complete trees and/or Opcode 1.2 allocate nodes on-the-fly +#ifndef OPC_NO_NEG_VANILLA_TREE + mPos = (udword)new AABBTreeNode; CHECKALLOC(mPos); + mNeg = (udword)new AABBTreeNode; CHECKALLOC(mNeg); +#else + AABBTreeNode* PosNeg = new AABBTreeNode[2]; + CHECKALLOC(PosNeg); + mPos = (udword)PosNeg; +#endif + } + + // Update stats + builder->IncreaseCount(2); + + // Assign children + AABBTreeNode* Pos = (AABBTreeNode*)GetPos(); + AABBTreeNode* Neg = (AABBTreeNode*)GetNeg(); + Pos->mNodePrimitives = &mNodePrimitives[0]; + Pos->mNbPrimitives = NbPos; + Neg->mNodePrimitives = &mNodePrimitives[NbPos]; + Neg->mNbPrimitives = mNbPrimitives - NbPos; + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive hierarchy building in a top-down fashion. + * \param builder [in] the tree builder + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeNode::_BuildHierarchy(AABBTreeBuilder* builder) +{ + // 1) Compute the global box for current node. The box is stored in mBV. + builder->ComputeGlobalBox(mNodePrimitives, mNbPrimitives, mBV); + + // 2) Subdivide current node + Subdivide(builder); + + // 3) Recurse + AABBTreeNode* Pos = (AABBTreeNode*)GetPos(); + AABBTreeNode* Neg = (AABBTreeNode*)GetNeg(); + if(Pos) Pos->_BuildHierarchy(builder); + if(Neg) Neg->_BuildHierarchy(builder); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the tree (top-down). + * \param builder [in] the tree builder + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeNode::_Refit(AABBTreeBuilder* builder) +{ + // 1) Recompute the new global box for current node + builder->ComputeGlobalBox(mNodePrimitives, mNbPrimitives, mBV); + + // 2) Recurse + AABBTreeNode* Pos = (AABBTreeNode*)GetPos(); + AABBTreeNode* Neg = (AABBTreeNode*)GetNeg(); + if(Pos) Pos->_Refit(builder); + if(Neg) Neg->_Refit(builder); +} + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBTree::AABBTree() : mIndices(null), mTotalNbNodes(0), mPool(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBTree::~AABBTree() +{ + Release(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Releases the tree. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTree::Release() +{ + DELETEARRAY(mPool); + DELETEARRAY(mIndices); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds a generic AABB tree from a tree builder. + * \param builder [in] the tree builder + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTree::Build(AABBTreeBuilder* builder) +{ + // Checkings + if(!builder || !builder->mNbPrimitives) return false; + + // Release previous tree + Release(); + + // Init stats + builder->SetCount(1); + builder->SetNbInvalidSplits(0); + + // Initialize indices. This list will be modified during build. + mIndices = new udword[builder->mNbPrimitives]; + CHECKALLOC(mIndices); + // Identity permutation + for(udword i=0;imNbPrimitives;i++) mIndices[i] = i; + + // Setup initial node. Here we have a complete permutation of the app's primitives. + mNodePrimitives = mIndices; + mNbPrimitives = builder->mNbPrimitives; + + // Use a linear array for complete trees (since we can predict the final number of nodes) [Opcode 1.3] +// if(builder->mRules&SPLIT_COMPLETE) + if(builder->mSettings.mLimit==1) + { + // Allocate a pool of nodes + mPool = new AABBTreeNode[builder->mNbPrimitives*2 - 1]; + + builder->mNodeBase = mPool; // ### ugly ! + } + + // Build the hierarchy + _BuildHierarchy(builder); + + // Get back total number of nodes + mTotalNbNodes = builder->GetCount(); + + // For complete trees, check the correct number of nodes has been created [Opcode 1.3] + if(mPool) ASSERT(mTotalNbNodes==builder->mNbPrimitives*2 - 1); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the depth of the tree. + * A well-balanced tree should have a log(n) depth. A degenerate tree O(n) depth. + * \return depth of the tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword AABBTree::ComputeDepth() const +{ + return Walk(null, null); // Use the walking code without callback +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Walks the tree, calling the user back for each node. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword AABBTree::Walk(WalkingCallback callback, void* user_data) const +{ + // Call it without callback to compute max depth + udword MaxDepth = 0; + udword CurrentDepth = 0; + + struct Local + { + static void _Walk(const AABBTreeNode* current_node, udword& max_depth, udword& current_depth, WalkingCallback callback, void* user_data) + { + // Checkings + if(!current_node) return; + // Entering a new node => increase depth + current_depth++; + // Keep track of max depth + if(current_depth>max_depth) max_depth = current_depth; + + // Callback + if(callback && !(callback)(current_node, current_depth, user_data)) return; + + // Recurse + if(current_node->GetPos()) { _Walk(current_node->GetPos(), max_depth, current_depth, callback, user_data); current_depth--; } + if(current_node->GetNeg()) { _Walk(current_node->GetNeg(), max_depth, current_depth, callback, user_data); current_depth--; } + } + }; + Local::_Walk(this, MaxDepth, CurrentDepth, callback, user_data); + return MaxDepth; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the tree in a top-down way. + * \param builder [in] the tree builder + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTree::Refit(AABBTreeBuilder* builder) +{ + if(!builder) return false; + _Refit(builder); + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the tree in a bottom-up way. + * \param builder [in] the tree builder + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTree::Refit2(AABBTreeBuilder* builder) +{ + // Checkings + if(!builder) return false; + + ASSERT(mPool); + + // Bottom-up update + Point Min,Max; + Point Min_,Max_; + udword Index = mTotalNbNodes; + while(Index--) + { + AABBTreeNode& Current = mPool[Index]; + + if(Current.IsLeaf()) + { + builder->ComputeGlobalBox(Current.GetPrimitives(), Current.GetNbPrimitives(), *(AABB*)Current.GetAABB()); + } + else + { + Current.GetPos()->GetAABB()->GetMin(Min); + Current.GetPos()->GetAABB()->GetMax(Max); + + Current.GetNeg()->GetAABB()->GetMin(Min_); + Current.GetNeg()->GetAABB()->GetMax(Max_); + + Min.Min(Min_); + Max.Max(Max_); + + ((AABB*)Current.GetAABB())->SetMinMax(Min, Max); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the number of bytes used by the tree. + * \return number of bytes used + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword AABBTree::GetUsedBytes() const +{ + udword TotalSize = mTotalNbNodes*GetNodeSize(); + if(mIndices) TotalSize+=mNbPrimitives*sizeof(udword); + return TotalSize; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the tree is a complete tree or not. + * A complete tree is made of 2*N-1 nodes, where N is the number of primitives in the tree. + * \return true for complete trees + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTree::IsComplete() const +{ + return (GetNbNodes()==GetNbPrimitives()*2-1); +} diff --git a/Extras/CDTestFramework/Opcode/OPC_AABBTree.h b/Extras/CDTestFramework/Opcode/OPC_AABBTree.h new file mode 100644 index 0000000..c63bfa3 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_AABBTree.h @@ -0,0 +1,146 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a versatile AABB tree. + * \file OPC_AABBTree.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_AABBTREE_H__ +#define __OPC_AABBTREE_H__ + +#ifdef OPC_NO_NEG_VANILLA_TREE + //! TO BE DOCUMENTED + #define IMPLEMENT_TREE(base_class, volume) \ + public: \ + /* Constructor / Destructor */ \ + base_class(); \ + ~base_class(); \ + /* Data access */ \ + inline_ const volume* Get##volume() const { return &mBV; } \ + /* Clear the last bit */ \ + inline_ const base_class* GetPos() const { return (const base_class*)(mPos&~1); } \ + inline_ const base_class* GetNeg() const { const base_class* P = GetPos(); return P ? P+1 : null;} \ + \ + /* We don't need to test both nodes since we can't have one without the other */ \ + inline_ bool IsLeaf() const { return !GetPos(); } \ + \ + /* Stats */ \ + inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ + protected: \ + /* Tree-independent data */ \ + /* Following data always belong to the BV-tree, regardless of what the tree actually contains.*/ \ + /* Whatever happens we need the two children and the enclosing volume.*/ \ + volume mBV; /* Global bounding-volume enclosing all the node-related primitives */ \ + udword mPos; /* "Positive" & "Negative" children */ +#else + //! TO BE DOCUMENTED + #define IMPLEMENT_TREE(base_class, volume) \ + public: \ + /* Constructor / Destructor */ \ + base_class(); \ + ~base_class(); \ + /* Data access */ \ + inline_ const volume* Get##volume() const { return &mBV; } \ + /* Clear the last bit */ \ + inline_ const base_class* GetPos() const { return (const base_class*)(mPos&~1); } \ + inline_ const base_class* GetNeg() const { return (const base_class*)(mNeg&~1); } \ + \ +/* inline_ bool IsLeaf() const { return (!GetPos() && !GetNeg()); } */ \ + /* We don't need to test both nodes since we can't have one without the other */ \ + inline_ bool IsLeaf() const { return !GetPos(); } \ + \ + /* Stats */ \ + inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ + protected: \ + /* Tree-independent data */ \ + /* Following data always belong to the BV-tree, regardless of what the tree actually contains.*/ \ + /* Whatever happens we need the two children and the enclosing volume.*/ \ + volume mBV; /* Global bounding-volume enclosing all the node-related primitives */ \ + udword mPos; /* "Positive" child */ \ + udword mNeg; /* "Negative" child */ +#endif + + typedef void (*CullingCallback) (udword nb_primitives, udword* node_primitives, BOOL need_clipping, void* user_data); + + class OPCODE_API AABBTreeNode + { + IMPLEMENT_TREE(AABBTreeNode, AABB) + public: + // Data access + inline_ const udword* GetPrimitives() const { return mNodePrimitives; } + inline_ udword GetNbPrimitives() const { return mNbPrimitives; } + + protected: + // Tree-dependent data + udword* mNodePrimitives; //!< Node-related primitives (shortcut to a position in mIndices below) + udword mNbPrimitives; //!< Number of primitives for this node + // Internal methods + udword Split(udword axis, AABBTreeBuilder* builder); + bool Subdivide(AABBTreeBuilder* builder); + void _BuildHierarchy(AABBTreeBuilder* builder); + void _Refit(AABBTreeBuilder* builder); + }; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * User-callback, called for each node by the walking code. + * \param current [in] current node + * \param depth [in] current node's depth + * \param user_data [in] user-defined data + * \return true to recurse through children, else false to bypass them + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + typedef bool (*WalkingCallback) (const AABBTreeNode* current, udword depth, void* user_data); + + class OPCODE_API AABBTree : public AABBTreeNode + { + public: + // Constructor / Destructor + AABBTree(); + ~AABBTree(); + // Build + bool Build(AABBTreeBuilder* builder); + void Release(); + + // Data access + inline_ const udword* GetIndices() const { return mIndices; } //!< Catch the indices + inline_ udword GetNbNodes() const { return mTotalNbNodes; } //!< Catch the number of nodes + + // Infos + bool IsComplete() const; + // Stats + udword ComputeDepth() const; + udword GetUsedBytes() const; + udword Walk(WalkingCallback callback, void* user_data) const; + + bool Refit(AABBTreeBuilder* builder); + bool Refit2(AABBTreeBuilder* builder); + private: + udword* mIndices; //!< Indices in the app list. Indices are reorganized during build (permutation). + AABBTreeNode* mPool; //!< Linear pool of nodes for complete trees. Null otherwise. [Opcode 1.3] + // Stats + udword mTotalNbNodes; //!< Number of nodes in the tree. + }; + +#endif // __OPC_AABBTREE_H__ diff --git a/Extras/CDTestFramework/Opcode/OPC_ArraySAP.cpp b/Extras/CDTestFramework/Opcode/OPC_ArraySAP.cpp new file mode 100644 index 0000000..3c1e767 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_ArraySAP.cpp @@ -0,0 +1,1228 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an array-based version of the sweep-and-prune algorithm + * \file OPC_ArraySAP.cpp + * \author Pierre Terdiman + * \date December, 2, 2007 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +//#include "SAP_Utils.h" + +#define INVALID_USER_ID 0xffff + +inline_ void Sort(uword& id0, uword& id1) { if(id0>id1) TSwap(id0, id1); } +inline_ void Sort(uword& id0, uword& id1, const void*& obj0, const void*& obj1) { if(id0>id1) { TSwap(id0, id1); TSwap(obj0, obj1); } } + + + struct Opcode::IAABB : public Allocateable + { + udword mMinX; + udword mMinY; + udword mMinZ; + udword mMaxX; + udword mMaxY; + udword mMaxZ; + + inline_ udword GetMin(udword i) const { return (&mMinX)[i]; } + inline_ udword GetMax(udword i) const { return (&mMaxX)[i]; } + }; + + + +/* + - already sorted for batch create? + - better axis selection batch create +*/ + +//#define USE_WORDS // Use words or dwords for box indices. Words save memory but seriously limit the max number of objects in the SAP. +#define USE_PREFETCH +#define USE_INTEGERS +#define PAIR_USER_DATA +#define USE_OVERLAP_TEST_ON_REMOVES // "Useless" but faster overall because seriously reduces number of calls (from ~10000 to ~3 sometimes!) +#define RELEASE_ON_RESET // Release memory instead of just doing a reset + +#include "OPC_ArraySAP.h" + +//#include "SAP_PairManager.h" +//#include "SAP_PairManager.cpp" + + +inline_ udword Hash(uword id0, uword id1) { return Hash32Bits_1( udword(id0)|(udword(id1)<<16) ); } +inline_ bool DifferentPair(const ASAP_Pair& p, uword id0, uword id1) { return (id0!=p.id0) || (id1!=p.id1); } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +ASAP_PairManager::ASAP_PairManager() : + mHashSize (0), + mMask (0), + mHashTable (null), + mNext (null), + mNbActivePairs (0), + mActivePairs (null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +ASAP_PairManager::~ASAP_PairManager() +{ + Purge(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void ASAP_PairManager::Purge() +{ + ICE_FREE(mNext); + ICE_FREE(mActivePairs); + ICE_FREE(mHashTable); + mHashSize = 0; + mMask = 0; + mNbActivePairs = 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +const ASAP_Pair* ASAP_PairManager::FindPair(uword id0, uword id1) const +{ + if(!mHashTable) return null; // Nothing has been allocated yet + + // Order the ids + Sort(id0, id1); + + // Compute hash value for this pair + udword HashValue = Hash(id0, id1) & mMask; + + // Look for it in the table + udword Offset = mHashTable[HashValue]; + while(Offset!=INVALID_ID && DifferentPair(mActivePairs[Offset], id0, id1)) + { + ASSERT(mActivePairs[Offset].id0!=INVALID_USER_ID); + Offset = mNext[Offset]; // Better to have a separate array for this + } + if(Offset==INVALID_ID) return null; + ASSERT(Offset the pair is persistent + return &mActivePairs[Offset]; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Internal version saving hash computation +inline_ ASAP_Pair* ASAP_PairManager::FindPair(uword id0, uword id1, udword hash_value) const +{ + if(!mHashTable) return null; // Nothing has been allocated yet + + // Look for it in the table + udword Offset = mHashTable[hash_value]; + while(Offset!=INVALID_ID && DifferentPair(mActivePairs[Offset], id0, id1)) + { + ASSERT(mActivePairs[Offset].id0!=INVALID_USER_ID); + Offset = mNext[Offset]; // Better to have a separate array for this + } + if(Offset==INVALID_ID) return null; + ASSERT(Offset the pair is persistent + return &mActivePairs[Offset]; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +const ASAP_Pair* ASAP_PairManager::AddPair(uword id0, uword id1, const void* object0, const void* object1) +{ + // Order the ids + Sort(id0, id1, object0, object1); + + udword HashValue = Hash(id0, id1) & mMask; + + ASAP_Pair* P = FindPair(id0, id1, HashValue); + if(P) + { + return P; // Persistent pair + } + + // This is a new pair + if(mNbActivePairs >= mHashSize) + { + // Get more entries + mHashSize = NextPowerOfTwo(mNbActivePairs+1); + mMask = mHashSize-1; + + ReallocPairs(); + + // Recompute hash value with new hash size + HashValue = Hash(id0, id1) & mMask; + } + + ASAP_Pair* p = &mActivePairs[mNbActivePairs]; + p->id0 = id0; // ### CMOVs would be nice here + p->id1 = id1; + p->object0 = object0; + p->object1 = object1; + + mNext[mNbActivePairs] = mHashTable[HashValue]; + mHashTable[HashValue] = mNbActivePairs++; + return p; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void ASAP_PairManager::RemovePair(uword id0, uword id1, udword hash_value, udword pair_index) +{ + // Walk the hash table to fix mNext + udword Offset = mHashTable[hash_value]; + ASSERT(Offset!=INVALID_ID); + + udword Previous=INVALID_ID; + while(Offset!=pair_index) + { + Previous = Offset; + Offset = mNext[Offset]; + } + + // Let us go/jump us + if(Previous!=INVALID_ID) + { + ASSERT(mNext[Previous]==pair_index); + mNext[Previous] = mNext[pair_index]; + } + // else we were the first + else mHashTable[hash_value] = mNext[pair_index]; + // we're now free to reuse mNext[PairIndex] without breaking the list + +#ifdef _DEBUG + mNext[pair_index]=INVALID_ID; +#endif + // Invalidate entry + + // Fill holes + if(1) + { + // 1) Remove last pair + const udword LastPairIndex = mNbActivePairs-1; + if(LastPairIndex==pair_index) + { + mNbActivePairs--; + } + else + { + const ASAP_Pair* Last = &mActivePairs[LastPairIndex]; + const udword LastHashValue = Hash(Last->id0, Last->id1) & mMask; + + // Walk the hash table to fix mNext + udword Offset = mHashTable[LastHashValue]; + ASSERT(Offset!=INVALID_ID); + + udword Previous=INVALID_ID; + while(Offset!=LastPairIndex) + { + Previous = Offset; + Offset = mNext[Offset]; + } + + // Let us go/jump us + if(Previous!=INVALID_ID) + { + ASSERT(mNext[Previous]==LastPairIndex); + mNext[Previous] = mNext[LastPairIndex]; + } + // else we were the first + else mHashTable[LastHashValue] = mNext[LastPairIndex]; + // we're now free to reuse mNext[LastPairIndex] without breaking the list + +#ifdef _DEBUG + mNext[LastPairIndex]=INVALID_ID; +#endif + + // Don't invalidate entry since we're going to shrink the array + + // 2) Re-insert in free slot + mActivePairs[pair_index] = mActivePairs[LastPairIndex]; +#ifdef _DEBUG + ASSERT(mNext[pair_index]==INVALID_ID); +#endif + mNext[pair_index] = mHashTable[LastHashValue]; + mHashTable[LastHashValue] = pair_index; + + mNbActivePairs--; + } + } +} + +bool ASAP_PairManager::RemovePair(uword id0, uword id1) +{ + // Order the ids + Sort(id0, id1); + + const udword HashValue = Hash(id0, id1) & mMask; + const ASAP_Pair* P = FindPair(id0, id1, HashValue); + if(!P) return false; + ASSERT(P->id0==id0); + ASSERT(P->id1==id1); + + RemovePair(id0, id1, HashValue, GetPairIndex(P)); + + ShrinkMemory(); + return true; +} + +bool ASAP_PairManager::RemovePairs(const BitArray& array) +{ + udword i=0; + while(i only less efficient but still ok + for(udword i=0;i>2; } + }; + + class Opcode::ASAP_Box : public Allocateable + { + public: + inline_ ASAP_Box() {} + inline_ ~ASAP_Box() {} + + IndexType mMin[3]; + IndexType mMax[3]; + void* mObject; + udword mGUID; + + inline_ void SetInvalid() { mMin[0]=INVALID_INDEX; } + inline_ bool IsValid() const { return mMin[0]!=INVALID_INDEX; } + + inline_ ValType GetMaxValue(udword i, const ASAP_EndPoint* base) const + { + return base[mMax[i]].mValue; + } + + inline_ ValType GetMinValue(udword i, const ASAP_EndPoint* base) const + { + return base[mMin[i]].mValue; + } +#ifdef _DEBUG + bool HasBeenInserted() const + { + assert(mMin[0]!=INVALID_INDEX); + assert(mMax[0]!=INVALID_INDEX); + assert(mMin[1]!=INVALID_INDEX); + assert(mMax[1]!=INVALID_INDEX); + assert(mMin[2]!=INVALID_INDEX); + assert(mMax[2]!=INVALID_INDEX); + return true; + } +#endif + }; + +inline_ BOOL Intersect1D_Min(const SAP_AABB& a, const ASAP_Box& b, const ASAP_EndPoint* const base, udword axis) +{ + if(b.GetMaxValue(axis, base) < a.GetMin(axis)) + return FALSE; + return TRUE; +} + +inline_ BOOL Intersect2D(const ASAP_Box& c, const ASAP_Box& b, udword axis1, udword axis2) +{ + if( b.mMax[axis1] < c.mMin[axis1] || c.mMax[axis1] < b.mMin[axis1] + || b.mMax[axis2] < c.mMin[axis2] || c.mMax[axis2] < b.mMin[axis2]) return FALSE; + return TRUE; +} + + +ArraySAP::ArraySAP() +{ + mNbBoxes = 0; + mMaxNbBoxes = 0; + mBoxes = null; + mEndPoints[0] = mEndPoints[1] = mEndPoints[2] = null; + mFirstFree = INVALID_ID; +} + +ArraySAP::~ArraySAP() +{ + mNbBoxes = 0; + mMaxNbBoxes = 0; + DELETEARRAY(mBoxes); + for(udword i=0;i<3;i++) + { + DELETEARRAY(mEndPoints[i]); + } +} + +void ArraySAP::ResizeBoxArray() +{ + const udword NewMaxBoxes = mMaxNbBoxes ? mMaxNbBoxes*2 : 64; + + ASAP_Box* NewBoxes = ICE_NEW_TMP(ASAP_Box)[NewMaxBoxes]; + const udword NbSentinels=2; + ASAP_EndPoint* NewEndPointsX = ICE_NEW_TMP(ASAP_EndPoint)[NewMaxBoxes*2+NbSentinels]; + ASAP_EndPoint* NewEndPointsY = ICE_NEW_TMP(ASAP_EndPoint)[NewMaxBoxes*2+NbSentinels]; + ASAP_EndPoint* NewEndPointsZ = ICE_NEW_TMP(ASAP_EndPoint)[NewMaxBoxes*2+NbSentinels]; + + if(mNbBoxes) + { + CopyMemory(NewBoxes, mBoxes, sizeof(ASAP_Box)*mNbBoxes); + CopyMemory(NewEndPointsX, mEndPoints[0], sizeof(ASAP_EndPoint)*(mNbBoxes*2+NbSentinels)); + CopyMemory(NewEndPointsY, mEndPoints[1], sizeof(ASAP_EndPoint)*(mNbBoxes*2+NbSentinels)); + CopyMemory(NewEndPointsZ, mEndPoints[2], sizeof(ASAP_EndPoint)*(mNbBoxes*2+NbSentinels)); + } + else + { + // Initialize sentinels +#ifdef USE_INTEGERS + const udword Min = EncodeFloat(MIN_FLOAT); + const udword Max = EncodeFloat(MAX_FLOAT); +#else + const float Min = MIN_FLOAT; + const float Max = MAX_FLOAT; +#endif + NewEndPointsX[0].SetData(Min, INVALID_INDEX, FALSE); + NewEndPointsX[1].SetData(Max, INVALID_INDEX, TRUE); + NewEndPointsY[0].SetData(Min, INVALID_INDEX, FALSE); + NewEndPointsY[1].SetData(Max, INVALID_INDEX, TRUE); + NewEndPointsZ[0].SetData(Min, INVALID_INDEX, FALSE); + NewEndPointsZ[1].SetData(Max, INVALID_INDEX, TRUE); + } + DELETEARRAY(mBoxes); + DELETEARRAY(mEndPoints[2]); + DELETEARRAY(mEndPoints[1]); + DELETEARRAY(mEndPoints[0]); + mBoxes = NewBoxes; + mEndPoints[0] = NewEndPointsX; + mEndPoints[1] = NewEndPointsY; + mEndPoints[2] = NewEndPointsZ; + + mMaxNbBoxes = NewMaxBoxes; +} + +inline_ BOOL Intersect(const IAABB& a, const IAABB& b, udword axis) +{ + if(b.GetMax(axis) < a.GetMin(axis) || a.GetMax(axis) < b.GetMin(axis)) return FALSE; + return TRUE; +} + +// ### TODO: the sorts here might be useless, as the values have been sorted already +bool ArraySAP::CompleteBoxPruning2(udword nb, const IAABB* array, const Axes& axes, const CreateData* batched) +{ + // Checkings + if(!nb || !array) return false; + + // Catch axes + const udword Axis0 = axes.mAxis0; + const udword Axis1 = axes.mAxis1; + const udword Axis2 = axes.mAxis2; + + // Allocate some temporary data + udword* PosList = (udword*)ICE_ALLOC_TMP(sizeof(udword)*(nb+1)); + + // 1) Build main list using the primary axis + for(udword i=0;iSort(PosList, nb, RADIX_SIGNED).GetRanks(); + const udword* Sorted = RS->Sort(PosList, nb, RADIX_UNSIGNED).GetRanks(); + + // 3) Prune the list + const udword* const LastSorted = &Sorted[nb]; + const udword* RunningAddress = Sorted; + udword Index0, Index1; + while(RunningAddressmObject, Box1->mObject, Box0->mGUID, Box1->mGUID); + } + } + } + } + } + + ICE_FREE(PosList); + return true; +} + +bool ArraySAP::BipartiteBoxPruning2(udword nb0, const IAABB* array0, udword nb1, const IAABB* array1, const Axes& axes, const CreateData* batched, const udword* box_indices) +{ + // Checkings + if(!nb0 || !array0 || !nb1 || !array1) return false; + + // Catch axes + const udword Axis0 = axes.mAxis0; + const udword Axis1 = axes.mAxis1; + const udword Axis2 = axes.mAxis2; + + // Allocate some temporary data + udword* MinPosList0 = (udword*)ICE_ALLOC_TMP(sizeof(udword)*nb0); + udword* MinPosList1 = (udword*)ICE_ALLOC_TMP(sizeof(udword)*nb1); + + // 1) Build main lists using the primary axis + for(udword i=0;iSort(MinPosList0, nb0, RADIX_UNSIGNED).GetRanks(); + const udword* Sorted1 = RS1->Sort(MinPosList1, nb1, RADIX_UNSIGNED).GetRanks(); + + // 3) Prune the lists + udword Index0, Index1; + + const udword* const LastSorted0 = &Sorted0[nb0]; + const udword* const LastSorted1 = &Sorted1[nb1]; + const udword* RunningAddress0 = Sorted0; + const udword* RunningAddress1 = Sorted1; + + while(RunningAddress1mObject, Box1->mObject, Box0->mGUID, Box1->mGUID); + } + } + } + } + + //// + + while(RunningAddress0mObject, Box1->mObject, Box0->mGUID, Box1->mGUID); + } + } + + } + } + + ICE_FREE(MinPosList0); + ICE_FREE(MinPosList1); + return true; +} + +udword ArraySAP::AddObject(void* object, uword guid, const AABB& box) +{ + assert(!(size_t(object)&3)); // We will use the 2 LSBs + +#ifdef _DEBUG + int a = sizeof(ASAP_Box); // 32 + int b = sizeof(ASAP_EndPoint); // 8 +#endif + + udword BoxIndex; + if(mFirstFree!=INVALID_ID) + { + BoxIndex = mFirstFree; + mFirstFree = mBoxes[BoxIndex].mGUID; + } + else + { + if(mNbBoxes==mMaxNbBoxes) + ResizeBoxArray(); + BoxIndex = mNbBoxes; + } + + ASAP_Box* Box = &mBoxes[BoxIndex]; + // Initialize box + Box->mObject = object; + Box->mGUID = guid; + for(udword i=0;i<3;i++) + { + Box->mMin[i] = INVALID_INDEX; + Box->mMax[i] = INVALID_INDEX; + } + + mNbBoxes++; + + CreateData* CD = (CreateData*)mCreated.Reserve(sizeof(CreateData)/sizeof(udword)); + CD->mHandle = BoxIndex; + CD->mBox = box; + + return BoxIndex; +} + +void ArraySAP::InsertEndPoints(udword axis, const ASAP_EndPoint* end_points, udword nb_endpoints) +{ + ASAP_EndPoint* const BaseEP = mEndPoints[axis]; + + const udword OldSize = mNbBoxes*2 - nb_endpoints; + const udword NewSize = mNbBoxes*2; + + BaseEP[NewSize + 1] = BaseEP[OldSize + 1]; + + sdword WriteIdx = NewSize; + udword CurrInsIdx = 0; + + const ASAP_EndPoint* First = &BaseEP[0]; + const ASAP_EndPoint* Current = &BaseEP[OldSize]; + while(Current>=First) + { + const ASAP_EndPoint& Src = *Current; + const ASAP_EndPoint& Ins = end_points[CurrInsIdx]; + + // We need to make sure we insert maxs before mins to handle exactly equal endpoints correctly + const bool ShouldInsert = Ins.IsMax() ? (Src.mValue <= Ins.mValue) : (Src.mValue < Ins.mValue); + + const ASAP_EndPoint& Moved = ShouldInsert ? Ins : Src; + BaseEP[WriteIdx] = Moved; + mBoxes[Moved.GetOwner()].mMin[axis + Moved.IsMax()] = WriteIdx--; + + if(ShouldInsert) + { + CurrInsIdx++; + if(CurrInsIdx >= nb_endpoints) + break;//we just inserted the last endpoint + } + else + { + Current--; + } + } +} + +void ArraySAP::BatchCreate() +{ + udword NbBatched = mCreated.GetNbEntries(); + if(!NbBatched) return; // Early-exit if no object has been created + NbBatched /= sizeof(CreateData)/sizeof(udword); + const CreateData* Batched = (const CreateData*)mCreated.GetEntries(); + mCreated.Reset(); + + { + const udword NbEndPoints = NbBatched*2; + ASAP_EndPoint* NewEPSorted = ICE_NEW_TMP(ASAP_EndPoint)[NbEndPoints]; + ASAP_EndPoint* Buffer = (ASAP_EndPoint*)ICE_ALLOC_TMP(sizeof(ASAP_EndPoint)*NbEndPoints); + RadixSort RS; + + for(udword Axis=0;Axis<3;Axis++) + { + for(udword i=0;iHasBeenInserted()); + } + for(udword i=0;imMin[0]; + NewBoxes[i].mMaxX = Box->mMax[0]; + NewBoxes[i].mMinY = Box->mMin[1]; + NewBoxes[i].mMaxY = Box->mMax[1]; + NewBoxes[i].mMinZ = Box->mMin[2]; + NewBoxes[i].mMaxZ = Box->mMax[2]; + } + + CompleteBoxPruning2(NbBatched, NewBoxes, Axes(AXES_XZY), Batched); + + // the old boxes are not the first ones in the array + + const udword NbOldBoxes = mNbBoxes - NbBatched; + if(NbOldBoxes) + { + IAABB* OldBoxes = ICE_NEW_TMP(IAABB)[NbOldBoxes]; + udword* OldBoxesIndices = (udword*)ICE_ALLOC_TMP(sizeof(udword)*NbOldBoxes); + udword Offset=0; + udword i=0; + while(imObject) + if(Box->IsValid()) + { + OldBoxesIndices[Offset] = i; + + OldBoxes[Offset].mMinX = Box->mMin[0]; + OldBoxes[Offset].mMaxX = Box->mMax[0]; + OldBoxes[Offset].mMinY = Box->mMin[1]; + OldBoxes[Offset].mMaxY = Box->mMax[1]; + OldBoxes[Offset].mMinZ = Box->mMin[2]; + OldBoxes[Offset].mMaxZ = Box->mMax[2]; + Offset++; + } + } + i++; + } +// assert(i==NbOldBoxes); + BipartiteBoxPruning2(NbBatched, NewBoxes, Offset, OldBoxes, Axes(AXES_XZY), Batched, OldBoxesIndices); + + ICE_FREE(OldBoxesIndices); + DELETEARRAY(OldBoxes); + } + DELETEARRAY(NewBoxes); + } +#ifdef RELEASE_ON_RESET + mCreated.Empty(); +#endif +} + +void ArraySAP::BatchRemove() +{ + udword NbRemoved = mRemoved.GetNbEntries(); + if(!NbRemoved) return; // Early-exit if no object has been removed + const udword* Removed = mRemoved.GetEntries(); + mRemoved.Reset(); + + for(udword Axis=0;Axis<3;Axis++) + { + ASAP_EndPoint* const BaseEP = mEndPoints[Axis]; + udword MinMinIndex = MAX_UDWORD; + for(udword i=0;imMin[Axis]; + assert(MinIndexmMax[Axis]; + assert(MaxIndexmMin[Axis + BaseEP[DestIndex].IsMax()] = DestIndex; + } + } + DestIndex++; + ReadIndex++; + } + } + } + + BitArray BA(65536); + const udword Saved = NbRemoved; + while(NbRemoved--) + { + udword Index = *Removed++; + assert(IndexmGUID < 65536); + BA.SetBit(Object->mGUID); + + Object->mGUID = mFirstFree; +// Object->mObject = null; // ########### + Object->SetInvalid(); + mFirstFree = Index; + } + mNbBoxes -= Saved; + mPairs.RemovePairs(BA); + +#ifdef RELEASE_ON_RESET + mRemoved.Empty(); +#endif +} + +bool ArraySAP::RemoveObject(udword handle) +{ + mRemoved.Add(handle); + return true; +} + +#ifdef USE_INTEGERS +bool ArraySAP::UpdateObject(udword handle, const AABB& box_) +#else +bool ArraySAP::UpdateObject(udword handle, const AABB& box) +#endif +{ + const ASAP_Box* Object = mBoxes + handle; + assert(Object->HasBeenInserted()); + const void* UserObject = Object->mObject; + const udword UserGUID = Object->mGUID; + +#ifdef USE_INTEGERS + IAABB box; + box.mMinX = EncodeFloat(box_.GetMin(0)); + box.mMinY = EncodeFloat(box_.GetMin(1)); + box.mMinZ = EncodeFloat(box_.GetMin(2)); + box.mMaxX = EncodeFloat(box_.GetMax(0)); + box.mMaxY = EncodeFloat(box_.GetMax(1)); + box.mMaxZ = EncodeFloat(box_.GetMax(2)); +#endif + + for(udword Axis=0;Axis<3;Axis++) + { + const udword Axis1 = (1 << Axis) & 3; + const udword Axis2 = (1 << Axis1) & 3; + + ASAP_EndPoint* const BaseEP = mEndPoints[Axis]; + + // Update min + { + ASAP_EndPoint* CurrentMin = BaseEP + Object->mMin[Axis]; + ASSERT(!CurrentMin->IsMax()); + + const ValType Limit = box.GetMin(Axis); + if(Limit < CurrentMin->mValue) + { + CurrentMin->mValue = Limit; + + // Min is moving left: + ASAP_EndPoint Saved = *CurrentMin; + udword EPIndex = (size_t(CurrentMin) - size_t(BaseEP))/sizeof(ASAP_EndPoint); + const udword SavedIndex = EPIndex; + + while((--CurrentMin)->mValue > Limit) + { +#ifdef USE_PREFETCH + _prefetch(CurrentMin-1); +#endif + ASAP_Box* id1 = mBoxes + CurrentMin->GetOwner(); + const BOOL IsMax = CurrentMin->IsMax(); + if(IsMax) + { + // Our min passed a max => start overlap + if(Object!=id1 + && Intersect2D(*Object, *id1, Axis1, Axis2) + && Intersect1D_Min(box, *id1, BaseEP, Axis) + ) + AddPair(UserObject, id1->mObject, UserGUID, id1->mGUID); + } + + id1->mMin[Axis + IsMax] = EPIndex--; + *(CurrentMin+1) = *CurrentMin; + } + + if(SavedIndex!=EPIndex) + { + mBoxes[Saved.GetOwner()].mMin[Axis + Saved.IsMax()] = EPIndex; + BaseEP[EPIndex] = Saved; + } + } + else if(Limit > CurrentMin->mValue) + { + CurrentMin->mValue = Limit; + + // Min is moving right: + ASAP_EndPoint Saved = *CurrentMin; + udword EPIndex = (size_t(CurrentMin) - size_t(BaseEP))/sizeof(ASAP_EndPoint); + const udword SavedIndex = EPIndex; + + while((++CurrentMin)->mValue < Limit) + { +#ifdef USE_PREFETCH + _prefetch(CurrentMin+1); +#endif + ASAP_Box* id1 = mBoxes + CurrentMin->GetOwner(); + const BOOL IsMax = CurrentMin->IsMax(); + if(IsMax) + { + // Our min passed a max => stop overlap + if(Object!=id1 +#ifdef USE_OVERLAP_TEST_ON_REMOVES + && Intersect2D(*Object, *id1, Axis1, Axis2) +#endif + ) + RemovePair(UserObject, id1->mObject, UserGUID, id1->mGUID); + } + + id1->mMin[Axis + IsMax] = EPIndex++; + *(CurrentMin-1) = *CurrentMin; + } + + if(SavedIndex!=EPIndex) + { + mBoxes[Saved.GetOwner()].mMin[Axis + Saved.IsMax()] = EPIndex; + BaseEP[EPIndex] = Saved; + } + } + } + + // Update max + { + ASAP_EndPoint* CurrentMax = BaseEP + Object->mMax[Axis]; + ASSERT(CurrentMax->IsMax()); + + const ValType Limit = box.GetMax(Axis); + if(Limit > CurrentMax->mValue) + { + CurrentMax->mValue = Limit; + + // Max is moving right: + ASAP_EndPoint Saved = *CurrentMax; + udword EPIndex = (size_t(CurrentMax) - size_t(BaseEP))/sizeof(ASAP_EndPoint); + const udword SavedIndex = EPIndex; + + while((++CurrentMax)->mValue < Limit) + { +#ifdef USE_PREFETCH + _prefetch(CurrentMax+1); +#endif + ASAP_Box* id1 = mBoxes + CurrentMax->GetOwner(); + const BOOL IsMax = CurrentMax->IsMax(); + if(!IsMax) + { + // Our max passed a min => start overlap + if(Object!=id1 + && Intersect2D(*Object, *id1, Axis1, Axis2) + && Intersect1D_Min(box, *id1, BaseEP, Axis) + ) + AddPair(UserObject, id1->mObject, UserGUID, id1->mGUID); + } + + id1->mMin[Axis + IsMax] = EPIndex++; + *(CurrentMax-1) = *CurrentMax; + } + + if(SavedIndex!=EPIndex) + { + mBoxes[Saved.GetOwner()].mMin[Axis + Saved.IsMax()] = EPIndex; + BaseEP[EPIndex] = Saved; + } + } + else if(Limit < CurrentMax->mValue) + { + CurrentMax->mValue = Limit; + + // Max is moving left: + ASAP_EndPoint Saved = *CurrentMax; + udword EPIndex = (size_t(CurrentMax) - size_t(BaseEP))/sizeof(ASAP_EndPoint); + const udword SavedIndex = EPIndex; + + while((--CurrentMax)->mValue > Limit) + { +#ifdef USE_PREFETCH + _prefetch(CurrentMax-1); +#endif + ASAP_Box* id1 = mBoxes + CurrentMax->GetOwner(); + const BOOL IsMax = CurrentMax->IsMax(); + if(!IsMax) + { + // Our max passed a min => stop overlap + if(Object!=id1 +#ifdef USE_OVERLAP_TEST_ON_REMOVES + && Intersect2D(*Object, *id1, Axis1, Axis2) +#endif + ) + RemovePair(UserObject, id1->mObject, UserGUID, id1->mGUID); + } + + id1->mMin[Axis + IsMax] = EPIndex--; + *(CurrentMax+1) = *CurrentMax; + } + + if(SavedIndex!=EPIndex) + { + mBoxes[Saved.GetOwner()].mMin[Axis + Saved.IsMax()] = EPIndex; + BaseEP[EPIndex] = Saved; + } + } + } + } + return true; +} + +udword ArraySAP::DumpPairs(SAP_CreatePair create_cb, SAP_DeletePair delete_cb, void* cb_user_data, ASAP_Pair** pairs) +{ + BatchCreate(); + + const udword* Entries = mData.GetEntries(); + const udword* Last = Entries + mData.GetNbEntries(); + mData.Reset(); + + udword* ToRemove = (udword*)Entries; + while(Entries!=Last) + { + const udword ID = *Entries++; + ASAP_Pair* UP = mPairs.mActivePairs + ID; + + { + ASSERT(UP->IsInArray()); + if(UP->IsRemoved()) + { + // No need to call "ClearInArray" in this case, since the pair will get removed anyway + + // Remove + if(delete_cb && !UP->IsNew()) + { +#ifdef PAIR_USER_DATA + (delete_cb)(UP->GetObject0(), UP->GetObject1(), cb_user_data, UP->userData); +#else + (delete_cb)(UP->GetObject0(), UP->GetObject1(), cb_user_data, null); +#endif + } + + *ToRemove++ = udword(UP->id0)<<16|UP->id1; + } + else + { + UP->ClearInArray(); + // Add => already there... Might want to create user data, though + if(UP->IsNew()) + { + if(create_cb) + { +#ifdef PAIR_USER_DATA + UP->userData = (create_cb)(UP->GetObject0(), UP->GetObject1(), cb_user_data); +#else + (create_cb)(UP->GetObject0(), UP->GetObject1(), cb_user_data); +#endif + } + UP->ClearNew(); + } + } + } + } + + // #### try batch removal here + Entries = mData.GetEntries(); + while(Entries!=ToRemove) + { + const udword ID = *Entries++; + const udword id0 = ID>>16; + const udword id1 = ID&0xffff; + bool Status = mPairs.RemovePair(id0, id1); + ASSERT(Status); + } + +#ifdef RELEASE_ON_RESET + mData.Empty(); +#endif + + BatchRemove(); + + if(pairs) *pairs = mPairs.mActivePairs; + + return mPairs.mNbActivePairs; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_ArraySAP.h b/Extras/CDTestFramework/Opcode/OPC_ArraySAP.h new file mode 100644 index 0000000..db35571 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_ArraySAP.h @@ -0,0 +1,159 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an array-based version of the sweep-and-prune algorithm + * \file OPC_ArraySAP.h + * \author Pierre Terdiman + * \date December, 2, 2007 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef OPC_ARRAYSAP_H +#define OPC_ARRAYSAP_H + +#pragma pack(1) + struct OPCODE_API ASAP_Pair + { + uword id0; + uword id1; + const void* object0; + const void* object1; +//#ifdef PAIR_USER_DATA + void* userData; +//#endif + inline_ const void* GetObject0() const { return (const void*)(size_t(object0) & ~3); } + inline_ const void* GetObject1() const { return (const void*)(size_t(object1) & ~3); } + inline_ size_t IsInArray() const { return size_t(object0) & 1; } + inline_ size_t IsRemoved() const { return size_t(object1) & 1; } + inline_ size_t IsNew() const { return size_t(object0) & 2; } + private: + inline_ void SetInArray() { object0 = (const void*)(size_t(object0) | 1); } + inline_ void SetRemoved() { object1 = (const void*)(size_t(object1) | 1); } + inline_ void SetNew() { object0 = (const void*)(size_t(object0) | 2); } + inline_ void ClearInArray() { object0 = (const void*)(size_t(object0) & ~1); } + inline_ void ClearRemoved() { object1 = (const void*)(size_t(object1) & ~1); } + inline_ void ClearNew() { object0 = (const void*)(size_t(object0) & ~2); } + + friend class ArraySAP; + }; +#pragma pack() + + class OPCODE_API ASAP_PairManager + { + public: + ASAP_PairManager(); + ~ASAP_PairManager(); + + void Purge(); + void ShrinkMemory(); + + const ASAP_Pair* AddPair (uword id0, uword id1, const void* object0, const void* object1); + bool RemovePair (uword id0, uword id1); + bool RemovePairs (const BitArray& array); + const ASAP_Pair* FindPair (uword id0, uword id1) const; + inline_ udword GetPairIndex(const ASAP_Pair* pair) const + { + return ((udword)((size_t(pair) - size_t(mActivePairs)))/sizeof(ASAP_Pair)); + } + + udword mHashSize; + udword mMask; + udword mNbActivePairs; + udword* mHashTable; + udword* mNext; + ASAP_Pair* mActivePairs; + inline_ ASAP_Pair* FindPair(uword id0, uword id1, udword hash_value) const; + void RemovePair(uword id0, uword id1, udword hash_value, udword pair_index); + void ReallocPairs(); + }; + + typedef void* (*SAP_CreatePair)(const void* object0, const void* object1, void* user_data); + typedef void (*SAP_DeletePair)(const void* object0, const void* object1, void* user_data, void* pair_user_data); + + // Forward declarations + class ASAP_EndPoint; + class ASAP_Box; + struct IAABB; + struct CreateData; + + class OPCODE_API ArraySAP : public Allocateable + { + public: + ArraySAP(); + ~ArraySAP(); + + udword AddObject(void* object, uword guid, const AABB& box); + bool RemoveObject(udword handle); + bool UpdateObject(udword handle, const AABB& box); + + udword DumpPairs(SAP_CreatePair create_cb, SAP_DeletePair delete_cb, void* cb_user_data, ASAP_Pair** pairs=null); + private: + Container mData; + ASAP_PairManager mPairs; + + inline_ void AddPair(const void* object0, const void* object1, uword id0, uword id1) + { + ASSERT(object0); + ASAP_Pair* UP = (ASAP_Pair*)mPairs.AddPair(id0, id1, null, null); + ASSERT(UP); + + if(UP->object0) + { + // Persistent pair + } + else + { + // New pair + ASSERT(!(int(object0)&1)); + ASSERT(!(int(object1)&1)); + UP->object0 = object0; + UP->object1 = object1; + UP->SetInArray(); + mData.Add(mPairs.GetPairIndex(UP)); + UP->SetNew(); + } + UP->ClearRemoved(); + } + + inline_ void RemovePair(const void* object0, const void* object1, uword id0, uword id1) + { + ASAP_Pair* UP = (ASAP_Pair*)mPairs.FindPair(id0, id1); + if(UP) + { + if(!UP->IsInArray()) + { + UP->SetInArray(); + mData.Add(mPairs.GetPairIndex(UP)); + } + UP->SetRemoved(); + } + } + + udword mNbBoxes; + udword mMaxNbBoxes; + ASAP_Box* mBoxes; + ASAP_EndPoint* mEndPoints[3]; + udword mFirstFree; + + void ResizeBoxArray(); + // For batch creation + Container mCreated; + void BatchCreate(); + void InsertEndPoints(udword axis, const ASAP_EndPoint* end_points, udword nb_endpoints); + bool CompleteBoxPruning2(udword nb, const IAABB* array, const Axes& axes, const CreateData* batched); + bool BipartiteBoxPruning2(udword nb0, const IAABB* array0, udword nb1, const IAABB* array1, const Axes& axes, const CreateData* batched, const udword* box_indices); + // For batch removal + Container mRemoved; + void BatchRemove(); + }; + +#endif // OPC_ARRAYSAP_H diff --git a/Extras/CDTestFramework/Opcode/OPC_BaseModel.cpp b/Extras/CDTestFramework/Opcode/OPC_BaseModel.cpp new file mode 100644 index 0000000..bdb2ae8 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_BaseModel.cpp @@ -0,0 +1,147 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains base model interface. + * \file OPC_BaseModel.cpp + * \author Pierre Terdiman + * \date May, 18, 2003 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * The base class for collision models. + * + * \class BaseModel + * \author Pierre Terdiman + * \version 1.3 + * \date May, 18, 2003 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +OPCODECREATE::OPCODECREATE() +{ + mIMesh = null; + mSettings.mRules = SPLIT_SPLATTER_POINTS | SPLIT_GEOM_CENTER; + mSettings.mLimit = 1; // Mandatory for complete trees + mNoLeaf = true; + mQuantized = true; +#ifdef __MESHMERIZER_H__ + mCollisionHull = false; +#endif // __MESHMERIZER_H__ + mKeepOriginal = false; + mCanRemap = false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BaseModel::BaseModel() : mIMesh(null), mModelCode(0), mSource(null), mTree(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BaseModel::~BaseModel() +{ + ReleaseBase(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Releases everything. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void BaseModel::ReleaseBase() +{ + DELETESINGLE(mSource); + DELETESINGLE(mTree); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Creates an optimized tree according to user-settings, and setups mModelCode. + * \param no_leaf [in] true for "no leaf" tree + * \param quantized [in] true for quantized tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool BaseModel::CreateTree(bool no_leaf, bool quantized) +{ + DELETESINGLE(mTree); + + // Setup model code + if(no_leaf) mModelCode |= OPC_NO_LEAF; + else mModelCode &= ~OPC_NO_LEAF; + + if(quantized) mModelCode |= OPC_QUANTIZED; + else mModelCode &= ~OPC_QUANTIZED; + + // Create the correct class + if(mModelCode & OPC_NO_LEAF) + { + if(mModelCode & OPC_QUANTIZED) mTree = new AABBQuantizedNoLeafTree; + else mTree = new AABBNoLeafTree; + } + else + { + if(mModelCode & OPC_QUANTIZED) mTree = new AABBQuantizedTree; + else mTree = new AABBCollisionTree; + } + CHECKALLOC(mTree); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the collision model. This can be used to handle dynamic meshes. Usage is: + * 1. modify your mesh vertices (keep the topology constant!) + * 2. refit the tree (call this method) + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool BaseModel::Refit() +{ + // Refit the optimized tree + return mTree->Refit(mIMesh); + +// Old code kept for reference : refit the source tree then rebuild ! +// if(!mSource) return false; +// // Ouch... +// mSource->Refit(&mTB); +// // Ouch... +// return mTree->Build(mSource); +} diff --git a/Extras/CDTestFramework/Opcode/OPC_BaseModel.h b/Extras/CDTestFramework/Opcode/OPC_BaseModel.h new file mode 100644 index 0000000..905fc92 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_BaseModel.h @@ -0,0 +1,184 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains base model interface. + * \file OPC_BaseModel.h + * \author Pierre Terdiman + * \date May, 18, 2003 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_BASEMODEL_H__ +#define __OPC_BASEMODEL_H__ + + //! Model creation structure + struct OPCODE_API OPCODECREATE + { + //! Constructor + OPCODECREATE(); + + MeshInterface* mIMesh; //!< Mesh interface (access to triangles & vertices) (*) + BuildSettings mSettings; //!< Builder's settings + bool mNoLeaf; //!< true => discard leaf nodes (else use a normal tree) + bool mQuantized; //!< true => quantize the tree (else use a normal tree) +#ifdef __MESHMERIZER_H__ + bool mCollisionHull; //!< true => use convex hull + GJK +#endif // __MESHMERIZER_H__ + bool mKeepOriginal; //!< true => keep a copy of the original tree (debug purpose) + bool mCanRemap; //!< true => allows OPCODE to reorganize client arrays + + // (*) This pointer is saved internally and used by OPCODE until collision structures are released, + // so beware of the object's lifetime. + }; + + enum ModelFlag + { + OPC_QUANTIZED = (1<<0), //!< Compressed/uncompressed tree + OPC_NO_LEAF = (1<<1), //!< Leaf/NoLeaf tree + OPC_SINGLE_NODE = (1<<2) //!< Special case for 1-node models + }; + + class OPCODE_API BaseModel + { + public: + // Constructor/Destructor + BaseModel(); + virtual ~BaseModel(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Builds a collision model. + * \param create [in] model creation structure + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual bool Build(const OPCODECREATE& create) = 0; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of bytes used by the tree. + * \return amount of bytes used + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual udword GetUsedBytes() const = 0; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Refits the collision model. This can be used to handle dynamic meshes. Usage is: + * 1. modify your mesh vertices (keep the topology constant!) + * 2. refit the tree (call this method) + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual bool Refit(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the source tree. + * \return generic tree + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const AABBTree* GetSourceTree() const { return mSource; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the tree. + * \return the collision tree + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const AABBOptimizedTree* GetTree() const { return mTree; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the tree. + * \return the collision tree + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ AABBOptimizedTree* GetTree() { return mTree; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of nodes in the tree. + * Should be 2*N-1 for normal trees and N-1 for optimized ones. + * \return number of nodes + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbNodes() const { return mTree->GetNbNodes(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks whether the tree has leaf nodes or not. + * \return true if the tree has leaf nodes (normal tree), else false (optimized tree) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL HasLeafNodes() const { return !(mModelCode & OPC_NO_LEAF); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks whether the tree is quantized or not. + * \return true if the tree is quantized + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsQuantized() const { return mModelCode & OPC_QUANTIZED; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks whether the model has a single node or not. This special case must be handled separately. + * \return true if the model has only 1 node + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL HasSingleNode() const { return mModelCode & OPC_SINGLE_NODE; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the model's code. + * \return model's code + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetModelCode() const { return mModelCode; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the mesh interface. + * \return mesh interface + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const MeshInterface* GetMeshInterface() const { return mIMesh; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Sets the mesh interface. + * \param imesh [in] mesh interface + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetMeshInterface(const MeshInterface* imesh) { mIMesh = imesh; } + + protected: + const MeshInterface* mIMesh; //!< User-defined mesh interface + udword mModelCode; //!< Model code = combination of ModelFlag(s) + AABBTree* mSource; //!< Original source tree + AABBOptimizedTree* mTree; //!< Optimized tree owned by the model + // Internal methods + void ReleaseBase(); + bool CreateTree(bool no_leaf, bool quantized); + }; + +#endif //__OPC_BASEMODEL_H__ \ No newline at end of file diff --git a/Extras/CDTestFramework/Opcode/OPC_BoxBoxOverlap.h b/Extras/CDTestFramework/Opcode/OPC_BoxBoxOverlap.h new file mode 100644 index 0000000..63aa87e --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_BoxBoxOverlap.h @@ -0,0 +1,139 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * OBB-OBB overlap test using the separating axis theorem. + * - original code by Gomez / Gamasutra (similar to Gottschalk's one in RAPID) + * - optimized for AABB trees by computing the rotation matrix once (SOLID-fashion) + * - the fabs matrix is precomputed as well and epsilon-tweaked (RAPID-style, we found this almost mandatory) + * - Class III axes can be disabled... (SOLID & Intel fashion) + * - ...or enabled to perform some profiling + * - CPU comparisons used when appropriate + * - lazy evaluation sometimes saves some work in case of early exits (unlike SOLID) + * + * \param ea [in] extents from box A + * \param ca [in] center from box A + * \param eb [in] extents from box B + * \param cb [in] center from box B + * \return true if boxes overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL AABBTreeCollider::BoxBoxOverlap(const Point& ea, const Point& ca, const Point& eb, const Point& cb) +{ + // Stats + mNbBVBVTests++; + + float t,t2; + + // Class I : A's basis vectors + float Tx = (mR1to0.m[0][0]*cb.x + mR1to0.m[1][0]*cb.y + mR1to0.m[2][0]*cb.z) + mT1to0.x - ca.x; + t = ea.x + eb.x*mAR.m[0][0] + eb.y*mAR.m[1][0] + eb.z*mAR.m[2][0]; + if(GREATER(Tx, t)) return FALSE; + + float Ty = (mR1to0.m[0][1]*cb.x + mR1to0.m[1][1]*cb.y + mR1to0.m[2][1]*cb.z) + mT1to0.y - ca.y; + t = ea.y + eb.x*mAR.m[0][1] + eb.y*mAR.m[1][1] + eb.z*mAR.m[2][1]; + if(GREATER(Ty, t)) return FALSE; + + float Tz = (mR1to0.m[0][2]*cb.x + mR1to0.m[1][2]*cb.y + mR1to0.m[2][2]*cb.z) + mT1to0.z - ca.z; + t = ea.z + eb.x*mAR.m[0][2] + eb.y*mAR.m[1][2] + eb.z*mAR.m[2][2]; + if(GREATER(Tz, t)) return FALSE; + + // Class II : B's basis vectors + t = Tx*mR1to0.m[0][0] + Ty*mR1to0.m[0][1] + Tz*mR1to0.m[0][2]; t2 = ea.x*mAR.m[0][0] + ea.y*mAR.m[0][1] + ea.z*mAR.m[0][2] + eb.x; + if(GREATER(t, t2)) return FALSE; + + t = Tx*mR1to0.m[1][0] + Ty*mR1to0.m[1][1] + Tz*mR1to0.m[1][2]; t2 = ea.x*mAR.m[1][0] + ea.y*mAR.m[1][1] + ea.z*mAR.m[1][2] + eb.y; + if(GREATER(t, t2)) return FALSE; + + t = Tx*mR1to0.m[2][0] + Ty*mR1to0.m[2][1] + Tz*mR1to0.m[2][2]; t2 = ea.x*mAR.m[2][0] + ea.y*mAR.m[2][1] + ea.z*mAR.m[2][2] + eb.z; + if(GREATER(t, t2)) return FALSE; + + // Class III : 9 cross products + // Cool trick: always perform the full test for first level, regardless of settings. + // That way pathological cases (such as the pencils scene) are quickly rejected anyway ! + if(mFullBoxBoxTest || mNbBVBVTests==1) + { + t = Tz*mR1to0.m[0][1] - Ty*mR1to0.m[0][2]; t2 = ea.y*mAR.m[0][2] + ea.z*mAR.m[0][1] + eb.y*mAR.m[2][0] + eb.z*mAR.m[1][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B0 + t = Tz*mR1to0.m[1][1] - Ty*mR1to0.m[1][2]; t2 = ea.y*mAR.m[1][2] + ea.z*mAR.m[1][1] + eb.x*mAR.m[2][0] + eb.z*mAR.m[0][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B1 + t = Tz*mR1to0.m[2][1] - Ty*mR1to0.m[2][2]; t2 = ea.y*mAR.m[2][2] + ea.z*mAR.m[2][1] + eb.x*mAR.m[1][0] + eb.y*mAR.m[0][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B2 + t = Tx*mR1to0.m[0][2] - Tz*mR1to0.m[0][0]; t2 = ea.x*mAR.m[0][2] + ea.z*mAR.m[0][0] + eb.y*mAR.m[2][1] + eb.z*mAR.m[1][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B0 + t = Tx*mR1to0.m[1][2] - Tz*mR1to0.m[1][0]; t2 = ea.x*mAR.m[1][2] + ea.z*mAR.m[1][0] + eb.x*mAR.m[2][1] + eb.z*mAR.m[0][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B1 + t = Tx*mR1to0.m[2][2] - Tz*mR1to0.m[2][0]; t2 = ea.x*mAR.m[2][2] + ea.z*mAR.m[2][0] + eb.x*mAR.m[1][1] + eb.y*mAR.m[0][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B2 + t = Ty*mR1to0.m[0][0] - Tx*mR1to0.m[0][1]; t2 = ea.x*mAR.m[0][1] + ea.y*mAR.m[0][0] + eb.y*mAR.m[2][2] + eb.z*mAR.m[1][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B0 + t = Ty*mR1to0.m[1][0] - Tx*mR1to0.m[1][1]; t2 = ea.x*mAR.m[1][1] + ea.y*mAR.m[1][0] + eb.x*mAR.m[2][2] + eb.z*mAR.m[0][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B1 + t = Ty*mR1to0.m[2][0] - Tx*mR1to0.m[2][1]; t2 = ea.x*mAR.m[2][1] + ea.y*mAR.m[2][0] + eb.x*mAR.m[1][2] + eb.y*mAR.m[0][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B2 + } + return TRUE; +} + +//! A dedicated version when one box is constant +inline_ BOOL OBBCollider::BoxBoxOverlap(const Point& extents, const Point& center) +{ + // Stats + mNbVolumeBVTests++; + + float t,t2; + + // Class I : A's basis vectors + float Tx = mTBoxToModel.x - center.x; t = extents.x + mBBx1; if(GREATER(Tx, t)) return FALSE; + float Ty = mTBoxToModel.y - center.y; t = extents.y + mBBy1; if(GREATER(Ty, t)) return FALSE; + float Tz = mTBoxToModel.z - center.z; t = extents.z + mBBz1; if(GREATER(Tz, t)) return FALSE; + + // Class II : B's basis vectors + t = Tx*mRBoxToModel.m[0][0] + Ty*mRBoxToModel.m[0][1] + Tz*mRBoxToModel.m[0][2]; + t2 = extents.x*mAR.m[0][0] + extents.y*mAR.m[0][1] + extents.z*mAR.m[0][2] + mBoxExtents.x; + if(GREATER(t, t2)) return FALSE; + + t = Tx*mRBoxToModel.m[1][0] + Ty*mRBoxToModel.m[1][1] + Tz*mRBoxToModel.m[1][2]; + t2 = extents.x*mAR.m[1][0] + extents.y*mAR.m[1][1] + extents.z*mAR.m[1][2] + mBoxExtents.y; + if(GREATER(t, t2)) return FALSE; + + t = Tx*mRBoxToModel.m[2][0] + Ty*mRBoxToModel.m[2][1] + Tz*mRBoxToModel.m[2][2]; + t2 = extents.x*mAR.m[2][0] + extents.y*mAR.m[2][1] + extents.z*mAR.m[2][2] + mBoxExtents.z; + if(GREATER(t, t2)) return FALSE; + + // Class III : 9 cross products + // Cool trick: always perform the full test for first level, regardless of settings. + // That way pathological cases (such as the pencils scene) are quickly rejected anyway ! + if(mFullBoxBoxTest || mNbVolumeBVTests==1) + { + t = Tz*mRBoxToModel.m[0][1] - Ty*mRBoxToModel.m[0][2]; t2 = extents.y*mAR.m[0][2] + extents.z*mAR.m[0][1] + mBB_1; if(GREATER(t, t2)) return FALSE; // L = A0 x B0 + t = Tz*mRBoxToModel.m[1][1] - Ty*mRBoxToModel.m[1][2]; t2 = extents.y*mAR.m[1][2] + extents.z*mAR.m[1][1] + mBB_2; if(GREATER(t, t2)) return FALSE; // L = A0 x B1 + t = Tz*mRBoxToModel.m[2][1] - Ty*mRBoxToModel.m[2][2]; t2 = extents.y*mAR.m[2][2] + extents.z*mAR.m[2][1] + mBB_3; if(GREATER(t, t2)) return FALSE; // L = A0 x B2 + t = Tx*mRBoxToModel.m[0][2] - Tz*mRBoxToModel.m[0][0]; t2 = extents.x*mAR.m[0][2] + extents.z*mAR.m[0][0] + mBB_4; if(GREATER(t, t2)) return FALSE; // L = A1 x B0 + t = Tx*mRBoxToModel.m[1][2] - Tz*mRBoxToModel.m[1][0]; t2 = extents.x*mAR.m[1][2] + extents.z*mAR.m[1][0] + mBB_5; if(GREATER(t, t2)) return FALSE; // L = A1 x B1 + t = Tx*mRBoxToModel.m[2][2] - Tz*mRBoxToModel.m[2][0]; t2 = extents.x*mAR.m[2][2] + extents.z*mAR.m[2][0] + mBB_6; if(GREATER(t, t2)) return FALSE; // L = A1 x B2 + t = Ty*mRBoxToModel.m[0][0] - Tx*mRBoxToModel.m[0][1]; t2 = extents.x*mAR.m[0][1] + extents.y*mAR.m[0][0] + mBB_7; if(GREATER(t, t2)) return FALSE; // L = A2 x B0 + t = Ty*mRBoxToModel.m[1][0] - Tx*mRBoxToModel.m[1][1]; t2 = extents.x*mAR.m[1][1] + extents.y*mAR.m[1][0] + mBB_8; if(GREATER(t, t2)) return FALSE; // L = A2 x B1 + t = Ty*mRBoxToModel.m[2][0] - Tx*mRBoxToModel.m[2][1]; t2 = extents.x*mAR.m[2][1] + extents.y*mAR.m[2][0] + mBB_9; if(GREATER(t, t2)) return FALSE; // L = A2 x B2 + } + return TRUE; +} + +//! A special version for 2 axis-aligned boxes +inline_ BOOL AABBCollider::AABBAABBOverlap(const Point& extents, const Point& center) +{ + // Stats + mNbVolumeBVTests++; + + float tx = mBox.mCenter.x - center.x; float ex = extents.x + mBox.mExtents.x; if(GREATER(tx, ex)) return FALSE; + float ty = mBox.mCenter.y - center.y; float ey = extents.y + mBox.mExtents.y; if(GREATER(ty, ey)) return FALSE; + float tz = mBox.mCenter.z - center.z; float ez = extents.z + mBox.mExtents.z; if(GREATER(tz, ez)) return FALSE; + + return TRUE; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_BoxPruning.cpp b/Extras/CDTestFramework/Opcode/OPC_BoxPruning.cpp new file mode 100644 index 0000000..7d4f50d --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_BoxPruning.cpp @@ -0,0 +1,376 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for box pruning. + * \file IceBoxPruning.cpp + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + You could use a complex sweep-and-prune as implemented in I-Collide. + You could use a complex hashing scheme as implemented in V-Clip or recently in ODE it seems. + You could use a "Recursive Dimensional Clustering" algorithm as implemented in GPG2. + + Or you could use this. + Faster ? I don't know. Probably not. It would be a shame. But who knows ? + Easier ? Definitely. Enjoy the sheer simplicity. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +*/ + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + + inline_ void FindRunningIndex(udword& index, float* array, udword* sorted, int last, float max) + { + int First=index; + while(First<=last) + { + index = (First+last)>>1; + + if(max>array[sorted[index]]) First = index+1; + else last = index-1; + } + } +// ### could be log(n) ! +// and maybe use cmp integers + +// InsertionSort has better coherence, RadixSort is better for one-shot queries. +#define PRUNING_SORTER RadixSort +//#define PRUNING_SORTER InsertionSort + +// Static for coherence +static PRUNING_SORTER* gCompletePruningSorter = null; +static PRUNING_SORTER* gBipartitePruningSorter0 = null; +static PRUNING_SORTER* gBipartitePruningSorter1 = null; +inline_ PRUNING_SORTER* GetCompletePruningSorter() +{ + if(!gCompletePruningSorter) gCompletePruningSorter = ICE_NEW(PRUNING_SORTER); + return gCompletePruningSorter; +} +inline_ PRUNING_SORTER* GetBipartitePruningSorter0() +{ + if(!gBipartitePruningSorter0) gBipartitePruningSorter0 = ICE_NEW(PRUNING_SORTER); + return gBipartitePruningSorter0; +} +inline_ PRUNING_SORTER* GetBipartitePruningSorter1() +{ + if(!gBipartitePruningSorter1) gBipartitePruningSorter1 = ICE_NEW(PRUNING_SORTER); + return gBipartitePruningSorter1; +} +void ReleasePruningSorters() +{ + DELETESINGLE(gBipartitePruningSorter1); + DELETESINGLE(gBipartitePruningSorter0); + DELETESINGLE(gCompletePruningSorter); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set. + * \param nb0 [in] number of boxes in the first set + * \param array0 [in] array of boxes for the first set + * \param nb1 [in] number of boxes in the second set + * \param array1 [in] array of boxes for the second set + * \param pairs [out] array of overlapping pairs + * \param axes [in] projection order (0,2,1 is often best) + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Opcode::BipartiteBoxPruning(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs, const Axes& axes) +{ + // Checkings + if(!nb0 || !array0 || !nb1 || !array1) return false; + + // Catch axes + udword Axis0 = axes.mAxis0; + udword Axis1 = axes.mAxis1; + udword Axis2 = axes.mAxis2; + + // Allocate some temporary data + float* MinPosList0 = new float[nb0]; + float* MinPosList1 = new float[nb1]; + + // 1) Build main lists using the primary axis + for(udword i=0;iGetMin(Axis0); + for(udword i=0;iGetMin(Axis0); + + // 2) Sort the lists + PRUNING_SORTER* RS0 = GetBipartitePruningSorter0(); + PRUNING_SORTER* RS1 = GetBipartitePruningSorter1(); + const udword* Sorted0 = RS0->Sort(MinPosList0, nb0).GetRanks(); + const udword* Sorted1 = RS1->Sort(MinPosList1, nb1).GetRanks(); + + // 3) Prune the lists + udword Index0, Index1; + + const udword* const LastSorted0 = &Sorted0[nb0]; + const udword* const LastSorted1 = &Sorted1[nb1]; + const udword* RunningAddress0 = Sorted0; + const udword* RunningAddress1 = Sorted1; + + while(RunningAddress1GetMax(Axis0)) + { + if(array0[Index0]->Intersect(*array1[Index1], Axis1)) + { + if(array0[Index0]->Intersect(*array1[Index1], Axis2)) + { + pairs.AddPair(Index0, Index1); + } + } + } + } + + //// + + while(RunningAddress0GetMax(Axis0)) + { + if(array0[Index1]->Intersect(*array1[Index0], Axis1)) + { + if(array0[Index1]->Intersect(*array1[Index0], Axis2)) + { + pairs.AddPair(Index1, Index0); + } + } + + } + } + + DELETEARRAY(MinPosList1); + DELETEARRAY(MinPosList0); + + return true; +} + +#define ORIGINAL_VERSION +//#define JOAKIM + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set. + * \param nb [in] number of boxes + * \param array [in] array of boxes + * \param pairs [out] array of overlapping pairs + * \param axes [in] projection order (0,2,1 is often best) + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Opcode::CompleteBoxPruning(udword nb, const AABB** array, Pairs& pairs, const Axes& axes) +{ + // Checkings + if(!nb || !array) return false; + + // Catch axes + udword Axis0 = axes.mAxis0; + udword Axis1 = axes.mAxis1; + udword Axis2 = axes.mAxis2; + +#ifdef ORIGINAL_VERSION + // Allocate some temporary data +// float* PosList = new float[nb]; + float* PosList = new float[nb+1]; + + // 1) Build main list using the primary axis + for(udword i=0;iGetMin(Axis0); +PosList[nb++] = MAX_FLOAT; + + // 2) Sort the list + PRUNING_SORTER* RS = GetCompletePruningSorter(); + const udword* Sorted = RS->Sort(PosList, nb).GetRanks(); + + // 3) Prune the list + const udword* const LastSorted = &Sorted[nb]; + const udword* RunningAddress = Sorted; + udword Index0, Index1; + while(RunningAddressGetMax(Axis0)) + while(PosList[Index1 = *RunningAddress2++]<=array[Index0]->GetMax(Axis0)) + { +// if(Index0!=Index1) +// { + if(array[Index0]->Intersect(*array[Index1], Axis1)) + { + if(array[Index0]->Intersect(*array[Index1], Axis2)) + { + pairs.AddPair(Index0, Index1); + } + } +// } + } + } + } + + DELETEARRAY(PosList); +#endif + +#ifdef JOAKIM + // Allocate some temporary data +// float* PosList = new float[nb]; + float* MinList = new float[nb+1]; + + // 1) Build main list using the primary axis + for(udword i=0;iGetMin(Axis0); + MinList[nb] = MAX_FLOAT; + + // 2) Sort the list + PRUNING_SORTER* RS = GetCompletePruningSorter(); + udword* Sorted = RS->Sort(MinList, nb+1).GetRanks(); + + // 3) Prune the list +// const udword* const LastSorted = &Sorted[nb]; +// const udword* const LastSorted = &Sorted[nb-1]; + const udword* RunningAddress = Sorted; + udword Index0, Index1; + +// while(RunningAddressGetMax(Axis0)) + +// float CurrentMin = array[Index0]->GetMin(Axis0); + float CurrentMax = array[Index0]->GetMax(Axis0); + + while(MinList[Index1 = *RunningAddress2] <= CurrentMax) +// while(PosList[Index1 = *RunningAddress] <= CurrentMax) + { +// if(Index0!=Index1) +// { + if(array[Index0]->Intersect(*array[Index1], Axis1)) + { + if(array[Index0]->Intersect(*array[Index1], Axis2)) + { + pairs.AddPair(Index0, Index1); + } + } +// } + + RunningAddress2++; +// RunningAddress++; + } + } + } + + DELETEARRAY(MinList); +#endif + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Brute-force versions are kept: +// - to check the optimized versions return the correct list of intersections +// - to check the speed of the optimized code against the brute-force one +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Brute-force bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set. + * \param nb0 [in] number of boxes in the first set + * \param array0 [in] array of boxes for the first set + * \param nb1 [in] number of boxes in the second set + * \param array1 [in] array of boxes for the second set + * \param pairs [out] array of overlapping pairs + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Opcode::BruteForceBipartiteBoxTest(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs) +{ + // Checkings + if(!nb0 || !array0 || !nb1 || !array1) return false; + + // Brute-force nb0*nb1 overlap tests + for(udword i=0;iIntersect(*array1[j])) pairs.AddPair(i, j); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set. + * \param nb [in] number of boxes + * \param array [in] array of boxes + * \param pairs [out] array of overlapping pairs + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Opcode::BruteForceCompleteBoxTest(udword nb, const AABB** array, Pairs& pairs) +{ + // Checkings + if(!nb || !array) return false; + + // Brute-force n(n-1)/2 overlap tests + for(udword i=0;iIntersect(*array[j])) pairs.AddPair(i, j); + } + } + return true; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_BoxPruning.h b/Extras/CDTestFramework/Opcode/OPC_BoxPruning.h new file mode 100644 index 0000000..163fe4e --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_BoxPruning.h @@ -0,0 +1,40 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for box pruning. + * \file IceBoxPruning.h + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_BOXPRUNING_H__ +#define __OPC_BOXPRUNING_H__ + + // Optimized versions + FUNCTION OPCODE_API bool CompleteBoxPruning(udword nb, const AABB** array, Pairs& pairs, const Axes& axes); + FUNCTION OPCODE_API bool BipartiteBoxPruning(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs, const Axes& axes); + + // Brute-force versions + FUNCTION OPCODE_API bool BruteForceCompleteBoxTest(udword nb, const AABB** array, Pairs& pairs); + FUNCTION OPCODE_API bool BruteForceBipartiteBoxTest(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs); + +#endif //__OPC_BOXPRUNING_H__ \ No newline at end of file diff --git a/Extras/CDTestFramework/Opcode/OPC_Collider.cpp b/Extras/CDTestFramework/Opcode/OPC_Collider.cpp new file mode 100644 index 0000000..bd62aec --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_Collider.cpp @@ -0,0 +1,63 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains base collider class. + * \file OPC_Collider.cpp + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains the abstract class for colliders. + * + * \class Collider + * \author Pierre Terdiman + * \version 1.3 + * \date June, 2, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Collider::Collider() : + mFlags (0), + mCurrentModel (null), + mIMesh (null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Collider::~Collider() +{ +} diff --git a/Extras/CDTestFramework/Opcode/OPC_Collider.h b/Extras/CDTestFramework/Opcode/OPC_Collider.h new file mode 100644 index 0000000..594109b --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_Collider.h @@ -0,0 +1,185 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains base collider class. + * \file OPC_Collider.h + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_COLLIDER_H__ +#define __OPC_COLLIDER_H__ + + enum CollisionFlag + { + OPC_FIRST_CONTACT = (1<<0), //!< Report all contacts (false) or only first one (true) + OPC_TEMPORAL_COHERENCE = (1<<1), //!< Use temporal coherence or not + OPC_CONTACT = (1<<2), //!< Final contact status after a collision query + OPC_TEMPORAL_HIT = (1<<3), //!< There has been an early exit due to temporal coherence + OPC_NO_PRIMITIVE_TESTS = (1<<4), //!< Keep or discard primitive-bv tests in leaf nodes (volume-mesh queries) + + OPC_CONTACT_FOUND = OPC_FIRST_CONTACT | OPC_CONTACT, + OPC_TEMPORAL_CONTACT = OPC_TEMPORAL_HIT | OPC_CONTACT, + + OPC_FORCE_DWORD = 0x7fffffff + }; + + class OPCODE_API Collider + { + public: + // Constructor / Destructor + Collider(); + virtual ~Collider(); + + // Collision report + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the last collision status after a collision query. + * \return true if a collision occured + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL GetContactStatus() const { return mFlags & OPC_CONTACT; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the "first contact" mode. + * \return true if "first contact" mode is on + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL FirstContactEnabled() const { return mFlags & OPC_FIRST_CONTACT; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the temporal coherence mode. + * \return true if temporal coherence is on + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL TemporalCoherenceEnabled() const { return mFlags & OPC_TEMPORAL_COHERENCE; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks a first contact has already been found. + * \return true if a first contact has been found and we can stop a query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL ContactFound() const { return (mFlags&OPC_CONTACT_FOUND)==OPC_CONTACT_FOUND; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks there's been an early exit due to temporal coherence; + * \return true if a temporal hit has occured + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL TemporalHit() const { return mFlags & OPC_TEMPORAL_HIT; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks primitive tests are enabled; + * \return true if primitive tests must be skipped + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL SkipPrimitiveTests() const { return mFlags & OPC_NO_PRIMITIVE_TESTS; } + + // Settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Reports all contacts (false) or first contact only (true) + * \param flag [in] true for first contact, false for all contacts + * \see SetTemporalCoherence(bool flag) + * \see ValidateSettings() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetFirstContact(bool flag) + { + if(flag) mFlags |= OPC_FIRST_CONTACT; + else mFlags &= ~OPC_FIRST_CONTACT; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Enable/disable temporal coherence. + * \param flag [in] true to enable temporal coherence, false to discard it + * \see SetFirstContact(bool flag) + * \see ValidateSettings() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetTemporalCoherence(bool flag) + { + if(flag) mFlags |= OPC_TEMPORAL_COHERENCE; + else mFlags &= ~OPC_TEMPORAL_COHERENCE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Enable/disable primitive tests. + * \param flag [in] true to enable primitive tests, false to discard them + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetPrimitiveTests(bool flag) + { + if(!flag) mFlags |= OPC_NO_PRIMITIVE_TESTS; + else mFlags &= ~OPC_NO_PRIMITIVE_TESTS; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider. + * \return null if everything is ok, else a string describing the problem + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual const char* ValidateSettings() = 0; + + protected: + udword mFlags; //!< Bit flags + const BaseModel* mCurrentModel; //!< Current model for collision query (owner of touched faces) + // User mesh interface + const MeshInterface* mIMesh; //!< User-defined mesh interface + + // Internal methods + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups current collision model + * \param model [in] current collision model + * \return TRUE if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Setup(const BaseModel* model) + { + // Keep track of current model + mCurrentModel = model; + if(!mCurrentModel) return FALSE; + + mIMesh = model->GetMeshInterface(); + return mIMesh!=null; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Initializes a query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual inline_ void InitQuery() { mFlags &= ~OPC_TEMPORAL_CONTACT; } + }; + +#endif // __OPC_COLLIDER_H__ diff --git a/Extras/CDTestFramework/Opcode/OPC_Common.cpp b/Extras/CDTestFramework/Opcode/OPC_Common.cpp new file mode 100644 index 0000000..4f1a250 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_Common.cpp @@ -0,0 +1,57 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains common classes & defs used in OPCODE. + * \file OPC_Common.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * An AABB dedicated to collision detection. + * We don't use the generic AABB class included in ICE, since it can be a Min/Max or a Center/Extents one (depends + * on compilation flags). Since the Center/Extents model is more efficient in collision detection, it was worth + * using an extra special class. + * + * \class CollisionAABB + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A quantized AABB. + * Center/Extent model, using 16-bits integers. + * + * \class QuantizedAABB + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; diff --git a/Extras/CDTestFramework/Opcode/OPC_Common.h b/Extras/CDTestFramework/Opcode/OPC_Common.h new file mode 100644 index 0000000..9510668 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_Common.h @@ -0,0 +1,110 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains common classes & defs used in OPCODE. + * \file OPC_Common.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_COMMON_H__ +#define __OPC_COMMON_H__ + +// [GOTTFRIED]: Just a small change for readability. +#ifdef OPC_CPU_COMPARE + #define GREATER(x, y) AIR(x) > IR(y) +#else + #define GREATER(x, y) fabsf(x) > (y) +#endif + + class OPCODE_API CollisionAABB + { + public: + //! Constructor + inline_ CollisionAABB() {} + //! Constructor + inline_ CollisionAABB(const AABB& b) { b.GetCenter(mCenter); b.GetExtents(mExtents); } + //! Destructor + inline_ ~CollisionAABB() {} + + //! Get min point of the box + inline_ void GetMin(Point& min) const { min = mCenter - mExtents; } + //! Get max point of the box + inline_ void GetMax(Point& max) const { max = mCenter + mExtents; } + + //! Get component of the box's min point along a given axis + inline_ float GetMin(udword axis) const { return mCenter[axis] - mExtents[axis]; } + //! Get component of the box's max point along a given axis + inline_ float GetMax(udword axis) const { return mCenter[axis] + mExtents[axis]; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from min & max vectors. + * \param min [in] the min point + * \param max [in] the max point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetMinMax(const Point& min, const Point& max) { mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks a box is inside another box. + * \param box [in] the other box + * \return true if current box is inside input box + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsInside(const CollisionAABB& box) const + { + if(box.GetMin(0)>GetMin(0)) return FALSE; + if(box.GetMin(1)>GetMin(1)) return FALSE; + if(box.GetMin(2)>GetMin(2)) return FALSE; + if(box.GetMax(0)IsValid()) return false; + + // Look for degenerate faces. + udword NbDegenerate = create.mIMesh->CheckTopology(); + if(NbDegenerate) Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate); + // We continue nonetheless.... + + Release(); // Make sure previous tree has been discarded + + // 1-1) Setup mesh interface automatically + SetMeshInterface(create.mIMesh); + + bool Status = false; + AABBTree* LeafTree = null; + Internal Data; + + // 2) Build a generic AABB Tree. + mSource = new AABBTree; + CHECKALLOC(mSource); + + // 2-1) Setup a builder. Our primitives here are triangles from input mesh, + // so we use an AABBTreeOfTrianglesBuilder..... + { + AABBTreeOfTrianglesBuilder TB; + TB.mIMesh = create.mIMesh; + TB.mNbPrimitives = create.mIMesh->GetNbTriangles(); + TB.mSettings = create.mSettings; + TB.mSettings.mLimit = 16; // ### Hardcoded, but maybe we could let the user choose 8 / 16 / 32 ... + if(!mSource->Build(&TB)) goto FreeAndExit; + } + + // 2-2) Here's the trick : create *another* AABB tree using the leaves of the first one (which are boxes, this time) + struct Local + { + // A callback to count leaf nodes + static bool CountLeaves(const AABBTreeNode* current, udword depth, void* user_data) + { + if(current->IsLeaf()) + { + Internal* Data = (Internal*)user_data; + Data->mNbLeaves++; + } + return true; + } + + // A callback to setup leaf nodes in our internal structures + static bool SetupLeafData(const AABBTreeNode* current, udword depth, void* user_data) + { + if(current->IsLeaf()) + { + Internal* Data = (Internal*)user_data; + + // Get current leaf's box + Data->mLeaves[Data->mNbLeaves] = *current->GetAABB(); + + // Setup leaf data + udword Index = (udword(current->GetPrimitives()) - udword(Data->mBase))/sizeof(udword); + Data->mTriangles[Data->mNbLeaves].SetData(current->GetNbPrimitives(), Index); + + Data->mNbLeaves++; + } + return true; + } + }; + + // Walk the tree & count number of leaves + Data.mNbLeaves = 0; + mSource->Walk(Local::CountLeaves, &Data); + mNbLeaves = Data.mNbLeaves; // Keep track of it + + // Special case for 1-leaf meshes + if(mNbLeaves==1) + { + mModelCode |= OPC_SINGLE_NODE; + Status = true; + goto FreeAndExit; + } + + // Allocate our structures + Data.mLeaves = new AABB[Data.mNbLeaves]; CHECKALLOC(Data.mLeaves); + mTriangles = new LeafTriangles[Data.mNbLeaves]; CHECKALLOC(mTriangles); + + // Walk the tree again & setup leaf data + Data.mTriangles = mTriangles; + Data.mBase = mSource->GetIndices(); + Data.mNbLeaves = 0; // Reset for incoming walk + mSource->Walk(Local::SetupLeafData, &Data); + + // Handle source indices + { + bool MustKeepIndices = true; + if(create.mCanRemap) + { + // We try to get rid of source indices (saving more ram!) by reorganizing triangle arrays... + // Remap can fail when we use callbacks => keep track of indices in that case (it still + // works, only using more memory) + if(create.mIMesh->RemapClient(mSource->GetNbPrimitives(), mSource->GetIndices())) + { + MustKeepIndices = false; + } + } + + if(MustKeepIndices) + { + // Keep track of source indices (from vanilla tree) + mNbPrimitives = mSource->GetNbPrimitives(); + mIndices = new udword[mNbPrimitives]; + CopyMemory(mIndices, mSource->GetIndices(), mNbPrimitives*sizeof(udword)); + } + } + + // Now, create our optimized tree using previous leaf nodes + LeafTree = new AABBTree; + CHECKALLOC(LeafTree); + { + AABBTreeOfAABBsBuilder TB; // Now using boxes ! + TB.mSettings = create.mSettings; + TB.mSettings.mLimit = 1; // We now want a complete tree so that we can "optimize" it + TB.mNbPrimitives = Data.mNbLeaves; + TB.mAABBArray = Data.mLeaves; + if(!LeafTree->Build(&TB)) goto FreeAndExit; + } + + // 3) Create an optimized tree according to user-settings + if(!CreateTree(create.mNoLeaf, create.mQuantized)) goto FreeAndExit; + + // 3-2) Create optimized tree + if(!mTree->Build(LeafTree)) goto FreeAndExit; + + // Finally ok... + Status = true; + +FreeAndExit: // Allow me this one... + DELETESINGLE(LeafTree); + + // 3-3) Delete generic tree if needed + if(!create.mKeepOriginal) DELETESINGLE(mSource); + + return Status; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Gets the number of bytes used by the tree. + * \return amount of bytes used + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword HybridModel::GetUsedBytes() const +{ + udword UsedBytes = 0; + if(mTree) UsedBytes += mTree->GetUsedBytes(); + if(mIndices) UsedBytes += mNbPrimitives * sizeof(udword); // mIndices + if(mTriangles) UsedBytes += mNbLeaves * sizeof(LeafTriangles); // mTriangles + return UsedBytes; +} + +inline_ void ComputeMinMax_HM(Point& min, Point& max, const VertexPointers& vp) +{ + // Compute triangle's AABB = a leaf box +#ifdef OPC_USE_FCOMI // a 15% speedup on my machine, not much + min.x = FCMin3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); + max.x = FCMax3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); + + min.y = FCMin3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); + max.y = FCMax3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); + + min.z = FCMin3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); + max.z = FCMax3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); +#else + min = *vp.Vertex[0]; + max = *vp.Vertex[0]; + min.Min(*vp.Vertex[1]); + max.Max(*vp.Vertex[1]); + min.Min(*vp.Vertex[2]); + max.Max(*vp.Vertex[2]); +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the collision model. This can be used to handle dynamic meshes. Usage is: + * 1. modify your mesh vertices (keep the topology constant!) + * 2. refit the tree (call this method) + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool HybridModel::Refit() +{ + if(!mIMesh) return false; + if(!mTree) return false; + + if(IsQuantized()) return false; + if(HasLeafNodes()) return false; + + const LeafTriangles* LT = GetLeafTriangles(); + const udword* Indices = GetIndices(); + + // Bottom-up update + VertexPointers VP; + Point Min,Max; + Point Min_,Max_; + udword Index = mTree->GetNbNodes(); + AABBNoLeafNode* Nodes = (AABBNoLeafNode*)((AABBNoLeafTree*)mTree)->GetNodes(); + while(Index--) + { + AABBNoLeafNode& Current = Nodes[Index]; + + if(Current.HasPosLeaf()) + { + const LeafTriangles& CurrentLeaf = LT[Current.GetPosPrimitive()]; + + Min.SetPlusInfinity(); + Max.SetMinusInfinity(); + + Point TmpMin, TmpMax; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + mIMesh->GetTriangle(VP, *T++); + ComputeMinMax_HM(TmpMin, TmpMax, VP); + Min.Min(TmpMin); + Max.Max(TmpMax); + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + mIMesh->GetTriangle(VP, BaseIndex++); + ComputeMinMax_HM(TmpMin, TmpMax, VP); + Min.Min(TmpMin); + Max.Max(TmpMax); + } + } + } + else + { + const CollisionAABB& CurrentBox = Current.GetPos()->mAABB; + CurrentBox.GetMin(Min); + CurrentBox.GetMax(Max); + } + + if(Current.HasNegLeaf()) + { + const LeafTriangles& CurrentLeaf = LT[Current.GetNegPrimitive()]; + + Min_.SetPlusInfinity(); + Max_.SetMinusInfinity(); + + Point TmpMin, TmpMax; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + mIMesh->GetTriangle(VP, *T++); + ComputeMinMax_HM(TmpMin, TmpMax, VP); + Min_.Min(TmpMin); + Max_.Max(TmpMax); + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + mIMesh->GetTriangle(VP, BaseIndex++); + ComputeMinMax_HM(TmpMin, TmpMax, VP); + Min_.Min(TmpMin); + Max_.Max(TmpMax); + } + } + } + else + { + const CollisionAABB& CurrentBox = Current.GetNeg()->mAABB; + CurrentBox.GetMin(Min_); + CurrentBox.GetMax(Max_); + } +#ifdef OPC_USE_FCOMI + Min.x = FCMin2(Min.x, Min_.x); + Max.x = FCMax2(Max.x, Max_.x); + Min.y = FCMin2(Min.y, Min_.y); + Max.y = FCMax2(Max.y, Max_.y); + Min.z = FCMin2(Min.z, Min_.z); + Max.z = FCMax2(Max.z, Max_.z); +#else + Min.Min(Min_); + Max.Max(Max_); +#endif + Current.mAABB.SetMinMax(Min, Max); + } + return true; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_HybridModel.h b/Extras/CDTestFramework/Opcode/OPC_HybridModel.h new file mode 100644 index 0000000..117b9c3 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_HybridModel.h @@ -0,0 +1,115 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for hybrid models. + * \file OPC_HybridModel.h + * \author Pierre Terdiman + * \date May, 18, 2003 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_HYBRIDMODEL_H__ +#define __OPC_HYBRIDMODEL_H__ + + //! Leaf descriptor + struct LeafTriangles + { + udword Data; //!< Packed data + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets number of triangles in the leaf. + * \return number of triangles N, with 0 < N <= 16 + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbTriangles() const { return (Data & 15)+1; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets triangle index for this leaf. Indexed model's array of indices retrieved with HybridModel::GetIndices() + * \return triangle index + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetTriangleIndex() const { return Data>>4; } + inline_ void SetData(udword nb, udword index) { ASSERT(nb>0 && nb<=16); nb--; Data = (index<<4)|(nb&15); } + }; + + class OPCODE_API HybridModel : public BaseModel + { + public: + // Constructor/Destructor + HybridModel(); + virtual ~HybridModel(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Builds a collision model. + * \param create [in] model creation structure + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(BaseModel) bool Build(const OPCODECREATE& create); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of bytes used by the tree. + * \return amount of bytes used + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(BaseModel) udword GetUsedBytes() const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Refits the collision model. This can be used to handle dynamic meshes. Usage is: + * 1. modify your mesh vertices (keep the topology constant!) + * 2. refit the tree (call this method) + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(BaseModel) bool Refit(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets array of triangles. + * \return array of triangles + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const LeafTriangles* GetLeafTriangles() const { return mTriangles; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets array of indices. + * \return array of indices + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const udword* GetIndices() const { return mIndices; } + + private: + udword mNbLeaves; //!< Number of leaf nodes in the model + LeafTriangles* mTriangles; //!< Array of mNbLeaves leaf descriptors + udword mNbPrimitives; //!< Number of primitives in the model + udword* mIndices; //!< Array of primitive indices + + // Internal methods + void Release(); + }; + +#endif // __OPC_HYBRIDMODEL_H__ diff --git a/Extras/CDTestFramework/Opcode/OPC_IceHook.h b/Extras/CDTestFramework/Opcode/OPC_IceHook.h new file mode 100644 index 0000000..4666d44 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_IceHook.h @@ -0,0 +1,92 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +// Should be included by Opcode.h if needed + + #define ICE_DONT_CHECK_COMPILER_OPTIONS + + // From Windows... + typedef int BOOL; + #ifndef FALSE + #define FALSE 0 + #endif + + #ifndef TRUE + #define TRUE 1 + #endif + + #include + #include + #include + #include + #include + #include + + #ifndef ASSERT + #define ASSERT(exp) {} + #endif + #define ICE_COMPILE_TIME_ASSERT(exp) extern char ICE_Dummy[ (exp) ? 1 : -1 ] + + #define Log {} + #define SetIceError false + #define EC_OUTOFMEMORY "Out of memory" + + #include ".\Ice\IcePreprocessor.h" + + #undef ICECORE_API + #define ICECORE_API OPCODE_API + + #include ".\Ice\IceTypes.h" + #include ".\Ice\IceFPU.h" + #include ".\Ice\IceMemoryMacros.h" + + namespace Opcode + { + namespace IceCore + { + #include ".\Ice\IceAllocator.h" + #include ".\Ice\IceUtils.h" + #include ".\Ice\IceBitArray.h" + #include ".\Ice\IceContainer.h" + #include ".\Ice\IcePairs.h" + #include ".\Ice\IceRevisitedRadix.h" + #include ".\Ice\IceRandom.h" + #include ".\Ice\IceHashing.h" + } + using namespace IceCore; + + #define ICEMATHS_API OPCODE_API + namespace IceMaths + { + #include ".\Ice\IceAxes.h" + #include ".\Ice\IcePoint.h" + #include ".\Ice\IceHPoint.h" + #include ".\Ice\IceMatrix3x3.h" + #include ".\Ice\IceMatrix4x4.h" + #include ".\Ice\IcePlane.h" + #include ".\Ice\IceRay.h" + #include ".\Ice\IceIndexedTriangle.h" + #include ".\Ice\IceTriangle.h" + #include ".\Ice\IceTriList.h" + #include ".\Ice\IceAABB.h" + #include ".\Ice\IceOBB.h" + #include ".\Ice\IceBoundingSphere.h" + #include ".\Ice\IceSegment.h" + #include ".\Ice\IceLSS.h" + } + using namespace IceMaths; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_LSSAABBOverlap.h b/Extras/CDTestFramework/Opcode/OPC_LSSAABBOverlap.h new file mode 100644 index 0000000..6e8e477 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_LSSAABBOverlap.h @@ -0,0 +1,539 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +// Following code from Magic-Software (http://www.magic-software.com/) +// A bit modified for Opcode + +inline_ float OPC_PointAABBSqrDist(const Point& point, const Point& center, const Point& extents) +{ + // Compute coordinates of point in box coordinate system + Point Closest = point - center; + + float SqrDistance = 0.0f; + + if(Closest.x < -extents.x) + { + float Delta = Closest.x + extents.x; + SqrDistance += Delta*Delta; + } + else if(Closest.x > extents.x) + { + float Delta = Closest.x - extents.x; + SqrDistance += Delta*Delta; + } + + if(Closest.y < -extents.y) + { + float Delta = Closest.y + extents.y; + SqrDistance += Delta*Delta; + } + else if(Closest.y > extents.y) + { + float Delta = Closest.y - extents.y; + SqrDistance += Delta*Delta; + } + + if(Closest.z < -extents.z) + { + float Delta = Closest.z + extents.z; + SqrDistance += Delta*Delta; + } + else if(Closest.z > extents.z) + { + float Delta = Closest.z - extents.z; + SqrDistance += Delta*Delta; + } + return SqrDistance; +} + +static void Face(int i0, int i1, int i2, Point& rkPnt, const Point& rkDir, const Point& extents, const Point& rkPmE, float* pfLParam, float& rfSqrDistance) +{ + Point kPpE; + float fLSqr, fInv, fTmp, fParam, fT, fDelta; + + kPpE[i1] = rkPnt[i1] + extents[i1]; + kPpE[i2] = rkPnt[i2] + extents[i2]; + if(rkDir[i0]*kPpE[i1] >= rkDir[i1]*rkPmE[i0]) + { + if(rkDir[i0]*kPpE[i2] >= rkDir[i2]*rkPmE[i0]) + { + // v[i1] >= -e[i1], v[i2] >= -e[i2] (distance = 0) + if(pfLParam) + { + rkPnt[i0] = extents[i0]; + fInv = 1.0f/rkDir[i0]; + rkPnt[i1] -= rkDir[i1]*rkPmE[i0]*fInv; + rkPnt[i2] -= rkDir[i2]*rkPmE[i0]*fInv; + *pfLParam = -rkPmE[i0]*fInv; + } + } + else + { + // v[i1] >= -e[i1], v[i2] < -e[i2] + fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i2]*rkDir[i2]; + fTmp = fLSqr*kPpE[i1] - rkDir[i1]*(rkDir[i0]*rkPmE[i0] + rkDir[i2]*kPpE[i2]); + if(fTmp <= 2.0f*fLSqr*extents[i1]) + { + fT = fTmp/fLSqr; + fLSqr += rkDir[i1]*rkDir[i1]; + fTmp = kPpE[i1] - fT; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*fTmp + rkDir[i2]*kPpE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + fTmp*fTmp + kPpE[i2]*kPpE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = fT - extents[i1]; + rkPnt[i2] = -extents[i2]; + } + } + else + { + fLSqr += rkDir[i1]*rkDir[i1]; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*rkPmE[i1] + rkDir[i2]*kPpE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + rkPmE[i1]*rkPmE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = extents[i1]; + rkPnt[i2] = -extents[i2]; + } + } + } + } + else + { + if ( rkDir[i0]*kPpE[i2] >= rkDir[i2]*rkPmE[i0] ) + { + // v[i1] < -e[i1], v[i2] >= -e[i2] + fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]; + fTmp = fLSqr*kPpE[i2] - rkDir[i2]*(rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1]); + if(fTmp <= 2.0f*fLSqr*extents[i2]) + { + fT = fTmp/fLSqr; + fLSqr += rkDir[i2]*rkDir[i2]; + fTmp = kPpE[i2] - fT; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*fTmp; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + fTmp*fTmp + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = -extents[i1]; + rkPnt[i2] = fT - extents[i2]; + } + } + else + { + fLSqr += rkDir[i2]*rkDir[i2]; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*rkPmE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + rkPmE[i2]*rkPmE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = -extents[i1]; + rkPnt[i2] = extents[i2]; + } + } + } + else + { + // v[i1] < -e[i1], v[i2] < -e[i2] + fLSqr = rkDir[i0]*rkDir[i0]+rkDir[i2]*rkDir[i2]; + fTmp = fLSqr*kPpE[i1] - rkDir[i1]*(rkDir[i0]*rkPmE[i0] + rkDir[i2]*kPpE[i2]); + if(fTmp >= 0.0f) + { + // v[i1]-edge is closest + if ( fTmp <= 2.0f*fLSqr*extents[i1] ) + { + fT = fTmp/fLSqr; + fLSqr += rkDir[i1]*rkDir[i1]; + fTmp = kPpE[i1] - fT; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*fTmp + rkDir[i2]*kPpE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + fTmp*fTmp + kPpE[i2]*kPpE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = fT - extents[i1]; + rkPnt[i2] = -extents[i2]; + } + } + else + { + fLSqr += rkDir[i1]*rkDir[i1]; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*rkPmE[i1] + rkDir[i2]*kPpE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + rkPmE[i1]*rkPmE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = extents[i1]; + rkPnt[i2] = -extents[i2]; + } + } + return; + } + + fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]; + fTmp = fLSqr*kPpE[i2] - rkDir[i2]*(rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1]); + if(fTmp >= 0.0f) + { + // v[i2]-edge is closest + if(fTmp <= 2.0f*fLSqr*extents[i2]) + { + fT = fTmp/fLSqr; + fLSqr += rkDir[i2]*rkDir[i2]; + fTmp = kPpE[i2] - fT; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*fTmp; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + fTmp*fTmp + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = -extents[i1]; + rkPnt[i2] = fT - extents[i2]; + } + } + else + { + fLSqr += rkDir[i2]*rkDir[i2]; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*rkPmE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + rkPmE[i2]*rkPmE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = -extents[i1]; + rkPnt[i2] = extents[i2]; + } + } + return; + } + + // (v[i1],v[i2])-corner is closest + fLSqr += rkDir[i2]*rkDir[i2]; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*kPpE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = -extents[i1]; + rkPnt[i2] = -extents[i2]; + } + } + } +} + +static void CaseNoZeros(Point& rkPnt, const Point& rkDir, const Point& extents, float* pfLParam, float& rfSqrDistance) +{ + Point kPmE(rkPnt.x - extents.x, rkPnt.y - extents.y, rkPnt.z - extents.z); + + float fProdDxPy, fProdDyPx, fProdDzPx, fProdDxPz, fProdDzPy, fProdDyPz; + + fProdDxPy = rkDir.x*kPmE.y; + fProdDyPx = rkDir.y*kPmE.x; + if(fProdDyPx >= fProdDxPy) + { + fProdDzPx = rkDir.z*kPmE.x; + fProdDxPz = rkDir.x*kPmE.z; + if(fProdDzPx >= fProdDxPz) + { + // line intersects x = e0 + Face(0, 1, 2, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); + } + else + { + // line intersects z = e2 + Face(2, 0, 1, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); + } + } + else + { + fProdDzPy = rkDir.z*kPmE.y; + fProdDyPz = rkDir.y*kPmE.z; + if(fProdDzPy >= fProdDyPz) + { + // line intersects y = e1 + Face(1, 2, 0, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); + } + else + { + // line intersects z = e2 + Face(2, 0, 1, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); + } + } +} + +static void Case0(int i0, int i1, int i2, Point& rkPnt, const Point& rkDir, const Point& extents, float* pfLParam, float& rfSqrDistance) +{ + float fPmE0 = rkPnt[i0] - extents[i0]; + float fPmE1 = rkPnt[i1] - extents[i1]; + float fProd0 = rkDir[i1]*fPmE0; + float fProd1 = rkDir[i0]*fPmE1; + float fDelta, fInvLSqr, fInv; + + if(fProd0 >= fProd1) + { + // line intersects P[i0] = e[i0] + rkPnt[i0] = extents[i0]; + + float fPpE1 = rkPnt[i1] + extents[i1]; + fDelta = fProd0 - rkDir[i0]*fPpE1; + if(fDelta >= 0.0f) + { + fInvLSqr = 1.0f/(rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]); + rfSqrDistance += fDelta*fDelta*fInvLSqr; + if(pfLParam) + { + rkPnt[i1] = -extents[i1]; + *pfLParam = -(rkDir[i0]*fPmE0+rkDir[i1]*fPpE1)*fInvLSqr; + } + } + else + { + if(pfLParam) + { + fInv = 1.0f/rkDir[i0]; + rkPnt[i1] -= fProd0*fInv; + *pfLParam = -fPmE0*fInv; + } + } + } + else + { + // line intersects P[i1] = e[i1] + rkPnt[i1] = extents[i1]; + + float fPpE0 = rkPnt[i0] + extents[i0]; + fDelta = fProd1 - rkDir[i1]*fPpE0; + if(fDelta >= 0.0f) + { + fInvLSqr = 1.0f/(rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]); + rfSqrDistance += fDelta*fDelta*fInvLSqr; + if(pfLParam) + { + rkPnt[i0] = -extents[i0]; + *pfLParam = -(rkDir[i0]*fPpE0+rkDir[i1]*fPmE1)*fInvLSqr; + } + } + else + { + if(pfLParam) + { + fInv = 1.0f/rkDir[i1]; + rkPnt[i0] -= fProd1*fInv; + *pfLParam = -fPmE1*fInv; + } + } + } + + if(rkPnt[i2] < -extents[i2]) + { + fDelta = rkPnt[i2] + extents[i2]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i2] = -extents[i2]; + } + else if ( rkPnt[i2] > extents[i2] ) + { + fDelta = rkPnt[i2] - extents[i2]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i2] = extents[i2]; + } +} + +static void Case00(int i0, int i1, int i2, Point& rkPnt, const Point& rkDir, const Point& extents, float* pfLParam, float& rfSqrDistance) +{ + float fDelta; + + if(pfLParam) + *pfLParam = (extents[i0] - rkPnt[i0])/rkDir[i0]; + + rkPnt[i0] = extents[i0]; + + if(rkPnt[i1] < -extents[i1]) + { + fDelta = rkPnt[i1] + extents[i1]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i1] = -extents[i1]; + } + else if(rkPnt[i1] > extents[i1]) + { + fDelta = rkPnt[i1] - extents[i1]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i1] = extents[i1]; + } + + if(rkPnt[i2] < -extents[i2]) + { + fDelta = rkPnt[i2] + extents[i2]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i1] = -extents[i2]; + } + else if(rkPnt[i2] > extents[i2]) + { + fDelta = rkPnt[i2] - extents[i2]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i2] = extents[i2]; + } +} + +static void Case000(Point& rkPnt, const Point& extents, float& rfSqrDistance) +{ + float fDelta; + + if(rkPnt.x < -extents.x) + { + fDelta = rkPnt.x + extents.x; + rfSqrDistance += fDelta*fDelta; + rkPnt.x = -extents.x; + } + else if(rkPnt.x > extents.x) + { + fDelta = rkPnt.x - extents.x; + rfSqrDistance += fDelta*fDelta; + rkPnt.x = extents.x; + } + + if(rkPnt.y < -extents.y) + { + fDelta = rkPnt.y + extents.y; + rfSqrDistance += fDelta*fDelta; + rkPnt.y = -extents.y; + } + else if(rkPnt.y > extents.y) + { + fDelta = rkPnt.y - extents.y; + rfSqrDistance += fDelta*fDelta; + rkPnt.y = extents.y; + } + + if(rkPnt.z < -extents.z) + { + fDelta = rkPnt.z + extents.z; + rfSqrDistance += fDelta*fDelta; + rkPnt.z = -extents.z; + } + else if(rkPnt.z > extents.z) + { + fDelta = rkPnt.z - extents.z; + rfSqrDistance += fDelta*fDelta; + rkPnt.z = extents.z; + } +} + +static float SqrDistance(const Ray& rkLine, const Point& center, const Point& extents, float* pfLParam) +{ + // compute coordinates of line in box coordinate system + Point kDiff = rkLine.mOrig - center; + Point kPnt = kDiff; + Point kDir = rkLine.mDir; + + // Apply reflections so that direction vector has nonnegative components. + bool bReflect[3]; + for(int i=0;i<3;i++) + { + if(kDir[i]<0.0f) + { + kPnt[i] = -kPnt[i]; + kDir[i] = -kDir[i]; + bReflect[i] = true; + } + else + { + bReflect[i] = false; + } + } + + float fSqrDistance = 0.0f; + + if(kDir.x>0.0f) + { + if(kDir.y>0.0f) + { + if(kDir.z>0.0f) CaseNoZeros(kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,+,+) + else Case0(0, 1, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,+,0) + } + else + { + if(kDir.z>0.0f) Case0(0, 2, 1, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,0,+) + else Case00(0, 1, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,0,0) + } + } + else + { + if(kDir.y>0.0f) + { + if(kDir.z>0.0f) Case0(1, 2, 0, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,+,+) + else Case00(1, 0, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,+,0) + } + else + { + if(kDir.z>0.0f) Case00(2, 0, 1, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,0,+) + else + { + Case000(kPnt, extents, fSqrDistance); // (0,0,0) + if(pfLParam) *pfLParam = 0.0f; + } + } + } + return fSqrDistance; +} + +inline_ float OPC_SegmentOBBSqrDist(const Segment& segment, const Point& c0, const Point& e0) +{ + float fLP; + float fSqrDistance = SqrDistance(Ray(segment.GetOrigin(), segment.ComputeDirection()), c0, e0, &fLP); + if(fLP>=0.0f) + { + if(fLP<=1.0f) return fSqrDistance; + else return OPC_PointAABBSqrDist(segment.mP1, c0, e0); + } + else return OPC_PointAABBSqrDist(segment.mP0, c0, e0); +} + +inline_ BOOL LSSCollider::LSSAABBOverlap(const Point& center, const Point& extents) +{ + // Stats + mNbVolumeBVTests++; + + float s2 = OPC_SegmentOBBSqrDist(mSeg, center, extents); + if(s2Add(prim_index); + +//! LSS-triangle overlap test +#define LSS_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \ + \ + /* Perform LSS-tri overlap test */ \ + if(LSSTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ + { \ + SET_CONTACT(prim_index, flag) \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +LSSCollider::LSSCollider() +{ +// mCenter.Zero(); +// mRadius2 = 0.0f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +LSSCollider::~LSSCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] an lss cache + * \param lss [in] collision lss in local space + * \param model [in] Opcode model to collide with + * \param worldl [in] lss world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool LSSCollider::Collide(LSSCache& cache, const LSS& lss, const Model& model, const Matrix4x4* worldl, const Matrix4x4* worldm) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, lss, worldl, worldm)) return true; + + if(!model.HasLeafNodes()) + { + if(model.IsQuantized()) + { + const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - setup matrices + * - check temporal coherence + * + * \param cache [in/out] an lss cache + * \param lss [in] lss in local space + * \param worldl [in] lss world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return TRUE if we can return immediately + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL LSSCollider::InitQuery(LSSCache& cache, const LSS& lss, const Matrix4x4* worldl, const Matrix4x4* worldm) +{ + // 1) Call the base method + VolumeCollider::InitQuery(); + + // 2) Compute LSS in model space: + // - Precompute R^2 + mRadius2 = lss.mRadius * lss.mRadius; + // - Compute segment + mSeg.mP0 = lss.mP0; + mSeg.mP1 = lss.mP1; + // -> to world space + if(worldl) + { + mSeg.mP0 *= *worldl; + mSeg.mP1 *= *worldl; + } + // -> to model space + if(worldm) + { + // Invert model matrix + Matrix4x4 InvWorldM; + InvertPRMatrix(InvWorldM, *worldm); + + mSeg.mP0 *= InvWorldM; + mSeg.mP1 *= InvWorldM; + } + + // 3) Setup destination pointer + mTouchedPrimitives = &cache.TouchedPrimitives; + + // 4) Special case: 1-triangle meshes [Opcode 1.3] + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + if(!SkipPrimitiveTests()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + mTouchedPrimitives->Reset(); + + // Perform overlap test between the unique triangle and the LSS (and set contact status if needed) + LSS_PRIM(udword(0), OPC_CONTACT) + + // Return immediately regardless of status + return TRUE; + } + } + + // 5) Check temporal coherence : + if(TemporalCoherenceEnabled()) + { + // Here we use temporal coherence + // => check results from previous frame before performing the collision query + if(FirstContactEnabled()) + { + // We're only interested in the first contact found => test the unique previously touched face + if(mTouchedPrimitives->GetNbEntries()) + { + // Get index of previously touched face = the first entry in the array + udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); + + // Then reset the array: + // - if the overlap test below is successful, the index we'll get added back anyway + // - if it isn't, then the array should be reset anyway for the normal query + mTouchedPrimitives->Reset(); + + // Perform overlap test between the cached triangle and the LSS (and set contact status if needed) + LSS_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) + + // Return immediately if possible + if(GetContactStatus()) return TRUE; + } + // else no face has been touched during previous query + // => we'll have to perform a normal query + } + else + { + // We're interested in all contacts =>test the new real LSS N(ew) against the previous fat LSS P(revious): + + // ### rewrite this + + LSS Test(mSeg, lss.mRadius); // in model space + LSS Previous(cache.Previous, sqrtf(cache.Previous.mRadius)); + +// if(cache.Previous.Contains(Test)) + if(IsCacheValid(cache) && Previous.Contains(Test)) + { + // - if N is included in P, return previous list + // => we simply leave the list (mTouchedFaces) unchanged + + // Set contact status if needed + if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; + + // In any case we don't need to do a query + return TRUE; + } + else + { + // - else do the query using a fat N + + // Reset cache since we'll about to perform a real query + mTouchedPrimitives->Reset(); + + // Make a fat sphere so that coherence will work for subsequent frames + mRadius2 *= cache.FatCoeff; +// mRadius2 = (lss.mRadius * cache.FatCoeff)*(lss.mRadius * cache.FatCoeff); + + + // Update cache with query data (signature for cached faces) + cache.Previous.mP0 = mSeg.mP0; + cache.Previous.mP1 = mSeg.mP1; + cache.Previous.mRadius = mRadius2; + } + } + } + else + { + // Here we don't use temporal coherence => do a normal query + mTouchedPrimitives->Reset(); + } + + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for vanilla AABB trees. + * \param cache [in/out] an lss cache + * \param lss [in] collision lss in world space + * \param tree [in] AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool LSSCollider::Collide(LSSCache& cache, const LSS& lss, const AABBTree* tree) +{ + // This is typically called for a scene tree, full of -AABBs-, not full of triangles. + // So we don't really have "primitives" to deal with. Hence it doesn't work with + // "FirstContact" + "TemporalCoherence". + ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); + + // Checkings + if(!tree) return false; + + // Init collision query + if(InitQuery(cache, lss)) return true; + + // Perform collision query + _Collide(tree); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the LSS completely contains the box. In which case we can end the query sooner. + * \param bc [in] box center + * \param be [in] box extents + * \return true if the LSS contains the whole box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL LSSCollider::LSSContainsBox(const Point& bc, const Point& be) +{ + // Not implemented + return FALSE; +} + +#define TEST_BOX_IN_LSS(center, extents) \ + if(LSSContainsBox(center, extents)) \ + { \ + /* Set contact status */ \ + mFlags |= OPC_CONTACT; \ + _Dump(node); \ + return; \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_Collide(const AABBCollisionNode* node) +{ + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + LSS_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) +{ + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_Collide(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_LSS(Center, Extents) + + if(node->IsLeaf()) + { + LSS_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_LSS(Center, Extents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_Collide(const AABBNoLeafNode* node) +{ + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) +{ + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_Collide(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_LSS(Center, Extents) + + if(node->HasPosLeaf()) { LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_LSS(Center, Extents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for vanilla AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_Collide(const AABBTreeNode* node) +{ + // Perform LSS-AABB overlap test + Point Center, Extents; + node->GetAABB()->GetCenter(Center); + node->GetAABB()->GetExtents(Extents); + if(!LSSAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf() || LSSContainsBox(Center, Extents)) + { + mFlags |= OPC_CONTACT; + mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives()); + } + else + { + _Collide(node->GetPos()); + _Collide(node->GetNeg()); + } +} + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridLSSCollider::HybridLSSCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridLSSCollider::~HybridLSSCollider() +{ +} + +bool HybridLSSCollider::Collide(LSSCache& cache, const LSS& lss, const HybridModel& model, const Matrix4x4* worldl, const Matrix4x4* worldm) +{ + // We don't want primitive tests here! + mFlags |= OPC_NO_PRIMITIVE_TESTS; + + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, lss, worldl, worldm)) return true; + + // Special case for 1-leaf trees + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles + udword Nb = mIMesh->GetNbTriangles(); + + // Loop through all triangles + for(udword i=0;imCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + + // We only have a list of boxes so far + if(GetContactStatus()) + { + // Reset contact status, since it currently only reflects collisions with leaf boxes + Collider::InitQuery(); + + // Change dest container so that we can use built-in overlap tests and get collided primitives + cache.TouchedPrimitives.Reset(); + mTouchedPrimitives = &cache.TouchedPrimitives; + + // Read touched leaf boxes + udword Nb = mTouchedBoxes.GetNbEntries(); + const udword* Touched = mTouchedBoxes.GetEntries(); + + const LeafTriangles* LT = model.GetLeafTriangles(); + const udword* Indices = model.GetIndices(); + + // Loop through touched leaves + while(Nb--) + { + const LeafTriangles& CurrentLeaf = LT[*Touched++]; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = *T++; + LSS_PRIM(TriangleIndex, OPC_CONTACT) + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = BaseIndex++; + LSS_PRIM(TriangleIndex, OPC_CONTACT) + } + } + } + } + + return true; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_LSSCollider.h b/Extras/CDTestFramework/Opcode/OPC_LSSCollider.h new file mode 100644 index 0000000..43921b3 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_LSSCollider.h @@ -0,0 +1,108 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for an LSS collider. + * \file OPC_LSSCollider.h + * \author Pierre Terdiman + * \date December, 28, 2002 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_LSSCOLLIDER_H__ +#define __OPC_LSSCOLLIDER_H__ + + struct OPCODE_API LSSCache : VolumeCache + { + LSSCache() + { + Previous.mP0 = Point(0.0f, 0.0f, 0.0f); + Previous.mP1 = Point(0.0f, 0.0f, 0.0f); + Previous.mRadius = 0.0f; + FatCoeff = 1.1f; + } + + // Cached faces signature + LSS Previous; //!< LSS used when performing the query resulting in cached faces + // User settings + float FatCoeff; //!< mRadius2 multiplier used to create a fat LSS + }; + + class OPCODE_API LSSCollider : public VolumeCollider + { + public: + // Constructor / Destructor + LSSCollider(); + virtual ~LSSCollider(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] an lss cache + * \param lss [in] collision lss in local space + * \param model [in] Opcode model to collide with + * \param worldl [in] lss world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(LSSCache& cache, const LSS& lss, const Model& model, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null); + // + bool Collide(LSSCache& cache, const LSS& lss, const AABBTree* tree); + protected: + // LSS in model space + Segment mSeg; //!< Segment + float mRadius2; //!< LSS radius squared + // Internal methods + void _Collide(const AABBCollisionNode* node); + void _Collide(const AABBNoLeafNode* node); + void _Collide(const AABBQuantizedNode* node); + void _Collide(const AABBQuantizedNoLeafNode* node); + void _Collide(const AABBTreeNode* node); + void _CollideNoPrimitiveTest(const AABBCollisionNode* node); + void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); + // Overlap tests + inline_ BOOL LSSContainsBox(const Point& bc, const Point& be); + inline_ BOOL LSSAABBOverlap(const Point& center, const Point& extents); + inline_ BOOL LSSTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2); + // Init methods + BOOL InitQuery(LSSCache& cache, const LSS& lss, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null); + }; + + class OPCODE_API HybridLSSCollider : public LSSCollider + { + public: + // Constructor / Destructor + HybridLSSCollider(); + virtual ~HybridLSSCollider(); + + bool Collide(LSSCache& cache, const LSS& lss, const HybridModel& model, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null); + protected: + Container mTouchedBoxes; + }; + +#endif // __OPC_LSSCOLLIDER_H__ diff --git a/Extras/CDTestFramework/Opcode/OPC_LSSTriOverlap.h b/Extras/CDTestFramework/Opcode/OPC_LSSTriOverlap.h new file mode 100644 index 0000000..b6171a8 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_LSSTriOverlap.h @@ -0,0 +1,696 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +// Following code from Magic-Software (http://www.magic-software.com/) +// A bit modified for Opcode + +static const float gs_fTolerance = 1e-05f; + +static float OPC_PointTriangleSqrDist(const Point& point, const Point& p0, const Point& p1, const Point& p2) +{ + // Hook + Point TriEdge0 = p1 - p0; + Point TriEdge1 = p2 - p0; + + Point kDiff = p0 - point; + float fA00 = TriEdge0.SquareMagnitude(); + float fA01 = TriEdge0 | TriEdge1; + float fA11 = TriEdge1.SquareMagnitude(); + float fB0 = kDiff | TriEdge0; + float fB1 = kDiff | TriEdge1; + float fC = kDiff.SquareMagnitude(); + float fDet = fabsf(fA00*fA11 - fA01*fA01); + float fS = fA01*fB1-fA11*fB0; + float fT = fA01*fB0-fA00*fB1; + float fSqrDist; + + if(fS + fT <= fDet) + { + if(fS < 0.0f) + { + if(fT < 0.0f) // region 4 + { + if(fB0 < 0.0f) + { + if(-fB0 >= fA00) fSqrDist = fA00+2.0f*fB0+fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + else + { + if(fB1 >= 0.0f) fSqrDist = fC; + else if(-fB1 >= fA11) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + } + else // region 3 + { + if(fB1 >= 0.0f) fSqrDist = fC; + else if(-fB1 >= fA11) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + } + else if(fT < 0.0f) // region 5 + { + if(fB0 >= 0.0f) fSqrDist = fC; + else if(-fB0 >= fA00) fSqrDist = fA00+2.0f*fB0+fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + else // region 0 + { + // minimum at interior point + if(fDet==0.0f) + { + fSqrDist = MAX_FLOAT; + } + else + { + float fInvDet = 1.0f/fDet; + fS *= fInvDet; + fT *= fInvDet; + fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; + } + } + } + else + { + float fTmp0, fTmp1, fNumer, fDenom; + + if(fS < 0.0f) // region 2 + { + fTmp0 = fA01 + fB0; + fTmp1 = fA11 + fB1; + if(fTmp1 > fTmp0) + { + fNumer = fTmp1 - fTmp0; + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { + fSqrDist = fA00+2.0f*fB0+fC; + } + else + { + fS = fNumer/fDenom; + fT = 1.0f - fS; + fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; + } + } + else + { + if(fTmp1 <= 0.0f) fSqrDist = fA11+2.0f*fB1+fC; + else if(fB1 >= 0.0f) fSqrDist = fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + } + else if(fT < 0.0f) // region 6 + { + fTmp0 = fA01 + fB1; + fTmp1 = fA00 + fB0; + if(fTmp1 > fTmp0) + { + fNumer = fTmp1 - fTmp0; + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { + fSqrDist = fA11+2.0f*fB1+fC; + } + else + { + fT = fNumer/fDenom; + fS = 1.0f - fT; + fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; + } + } + else + { + if(fTmp1 <= 0.0f) fSqrDist = fA00+2.0f*fB0+fC; + else if(fB0 >= 0.0f) fSqrDist = fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + } + else // region 1 + { + fNumer = fA11 + fB1 - fA01 - fB0; + if(fNumer <= 0.0f) + { + fSqrDist = fA11+2.0f*fB1+fC; + } + else + { + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { + fSqrDist = fA00+2.0f*fB0+fC; + } + else + { + fS = fNumer/fDenom; + fT = 1.0f - fS; + fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; + } + } + } + } + return fabsf(fSqrDist); +} + +static float OPC_SegmentSegmentSqrDist(const Segment& rkSeg0, const Segment& rkSeg1) +{ + // Hook + Point rkSeg0Direction = rkSeg0.ComputeDirection(); + Point rkSeg1Direction = rkSeg1.ComputeDirection(); + + Point kDiff = rkSeg0.mP0 - rkSeg1.mP0; + float fA00 = rkSeg0Direction.SquareMagnitude(); + float fA01 = -rkSeg0Direction.Dot(rkSeg1Direction); + float fA11 = rkSeg1Direction.SquareMagnitude(); + float fB0 = kDiff.Dot(rkSeg0Direction); + float fC = kDiff.SquareMagnitude(); + float fDet = fabsf(fA00*fA11-fA01*fA01); + + float fB1, fS, fT, fSqrDist, fTmp; + + if(fDet>=gs_fTolerance) + { + // line segments are not parallel + fB1 = -kDiff.Dot(rkSeg1Direction); + fS = fA01*fB1-fA11*fB0; + fT = fA01*fB0-fA00*fB1; + + if(fS >= 0.0f) + { + if(fS <= fDet) + { + if(fT >= 0.0f) + { + if(fT <= fDet) // region 0 (interior) + { + // minimum at two interior points of 3D lines + float fInvDet = 1.0f/fDet; + fS *= fInvDet; + fT *= fInvDet; + fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; + } + else // region 3 (side) + { + fTmp = fA01+fB0; + if(fTmp>=0.0f) fSqrDist = fA11+2.0f*fB1+fC; + else if(-fTmp>=fA00) fSqrDist = fA00+fA11+fC+2.0f*(fB1+fTmp); + else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC; + } + } + else // region 7 (side) + { + if(fB0>=0.0f) fSqrDist = fC; + else if(-fB0>=fA00) fSqrDist = fA00+2.0f*fB0+fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + } + else + { + if ( fT >= 0.0 ) + { + if ( fT <= fDet ) // region 1 (side) + { + fTmp = fA01+fB1; + if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC; + else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp); + else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC; + } + else // region 2 (corner) + { + fTmp = fA01+fB0; + if ( -fTmp <= fA00 ) + { + if(fTmp>=0.0f) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC; + } + else + { + fTmp = fA01+fB1; + if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC; + else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp); + else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC; + } + } + } + else // region 8 (corner) + { + if ( -fB0 < fA00 ) + { + if(fB0>=0.0f) fSqrDist = fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + else + { + fTmp = fA01+fB1; + if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC; + else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp); + else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC; + } + } + } + } + else + { + if ( fT >= 0.0f ) + { + if ( fT <= fDet ) // region 5 (side) + { + if(fB1>=0.0f) fSqrDist = fC; + else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + else // region 4 (corner) + { + fTmp = fA01+fB0; + if ( fTmp < 0.0f ) + { + if(-fTmp>=fA00) fSqrDist = fA00+fA11+fC+2.0f*(fB1+fTmp); + else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC; + } + else + { + if(fB1>=0.0f) fSqrDist = fC; + else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + } + } + else // region 6 (corner) + { + if ( fB0 < 0.0f ) + { + if(-fB0>=fA00) fSqrDist = fA00+2.0f*fB0+fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + else + { + if(fB1>=0.0f) fSqrDist = fC; + else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + } + } + } + else + { + // line segments are parallel + if ( fA01 > 0.0f ) + { + // direction vectors form an obtuse angle + if ( fB0 >= 0.0f ) + { + fSqrDist = fC; + } + else if ( -fB0 <= fA00 ) + { + fSqrDist = fB0*(-fB0/fA00)+fC; + } + else + { + fB1 = -kDiff.Dot(rkSeg1Direction); + fTmp = fA00+fB0; + if ( -fTmp >= fA01 ) + { + fSqrDist = fA00+fA11+fC+2.0f*(fA01+fB0+fB1); + } + else + { + fT = -fTmp/fA01; + fSqrDist = fA00+2.0f*fB0+fC+fT*(fA11*fT+2.0f*(fA01+fB1)); + } + } + } + else + { + // direction vectors form an acute angle + if ( -fB0 >= fA00 ) + { + fSqrDist = fA00+2.0f*fB0+fC; + } + else if ( fB0 <= 0.0f ) + { + fSqrDist = fB0*(-fB0/fA00)+fC; + } + else + { + fB1 = -kDiff.Dot(rkSeg1Direction); + if ( fB0 >= -fA01 ) + { + fSqrDist = fA11+2.0f*fB1+fC; + } + else + { + fT = -fB0/fA01; + fSqrDist = fC+fT*(2.0f*fB1+fA11*fT); + } + } + } + } + return fabsf(fSqrDist); +} + +inline_ float OPC_SegmentRaySqrDist(const Segment& rkSeg0, const Ray& rkSeg1) +{ + return OPC_SegmentSegmentSqrDist(rkSeg0, Segment(rkSeg1.mOrig, rkSeg1.mOrig + rkSeg1.mDir)); +} + +static float OPC_SegmentTriangleSqrDist(const Segment& segment, const Point& p0, const Point& p1, const Point& p2) +{ + // Hook + const Point TriEdge0 = p1 - p0; + const Point TriEdge1 = p2 - p0; + + const Point& rkSegOrigin = segment.GetOrigin(); + Point rkSegDirection = segment.ComputeDirection(); + + Point kDiff = p0 - rkSegOrigin; + float fA00 = rkSegDirection.SquareMagnitude(); + float fA01 = -rkSegDirection.Dot(TriEdge0); + float fA02 = -rkSegDirection.Dot(TriEdge1); + float fA11 = TriEdge0.SquareMagnitude(); + float fA12 = TriEdge0.Dot(TriEdge1); + float fA22 = TriEdge1.Dot(TriEdge1); + float fB0 = -kDiff.Dot(rkSegDirection); + float fB1 = kDiff.Dot(TriEdge0); + float fB2 = kDiff.Dot(TriEdge1); + float fCof00 = fA11*fA22-fA12*fA12; + float fCof01 = fA02*fA12-fA01*fA22; + float fCof02 = fA01*fA12-fA02*fA11; + float fDet = fA00*fCof00+fA01*fCof01+fA02*fCof02; + + Ray kTriSeg; + Point kPt; + float fSqrDist, fSqrDist0; + + if(fabsf(fDet)>=gs_fTolerance) + { + float fCof11 = fA00*fA22-fA02*fA02; + float fCof12 = fA02*fA01-fA00*fA12; + float fCof22 = fA00*fA11-fA01*fA01; + float fInvDet = 1.0f/fDet; + float fRhs0 = -fB0*fInvDet; + float fRhs1 = -fB1*fInvDet; + float fRhs2 = -fB2*fInvDet; + + float fR = fCof00*fRhs0+fCof01*fRhs1+fCof02*fRhs2; + float fS = fCof01*fRhs0+fCof11*fRhs1+fCof12*fRhs2; + float fT = fCof02*fRhs0+fCof12*fRhs1+fCof22*fRhs2; + + if ( fR < 0.0f ) + { + if ( fS+fT <= 1.0f ) + { + if ( fS < 0.0f ) + { + if ( fT < 0.0f ) // region 4m + { + // min on face s=0 or t=0 or r=0 + kTriSeg.mOrig = p0; + kTriSeg.mDir = TriEdge1; + fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg); + kTriSeg.mOrig = p0; + kTriSeg.mDir = TriEdge0; + fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg); + if(fSqrDist0 1 + { + if ( fS+fT <= 1.0f ) + { + if ( fS < 0.0f ) + { + if ( fT < 0.0f ) // region 4p + { + // min on face s=0 or t=0 or r=1 + kTriSeg.mOrig = p0; + kTriSeg.mDir = TriEdge1; + fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg); + kTriSeg.mOrig = p0; + kTriSeg.mDir = TriEdge0; + fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg); + if(fSqrDist0GetTriangle(triangle_index); + * // Setup pointers to vertices for the collision system + * triangle.Vertex[0] = MyMesh->GetVertex(Tri->mVRef[0]); + * triangle.Vertex[1] = MyMesh->GetVertex(Tri->mVRef[1]); + * triangle.Vertex[2] = MyMesh->GetVertex(Tri->mVRef[2]); + * } + * + * // Setup callbacks + * MeshInterface0->SetCallback(ColCallback, udword(Mesh0)); + * MeshInterface1->SetCallback(ColCallback, udword(Mesh1)); + * \endcode + * + * Of course, you should make this callback as fast as possible. And you're also not supposed + * to modify the geometry *after* the collision trees have been built. The alternative was to + * store the geometry & topology in the collision system as well (as in RAPID) but we have found + * this approach to waste a lot of ram in many cases. + * + * + * POINTERS: + * + * If you're internally using the following canonical structures: + * - a vertex made of three 32-bits floating point values + * - a triangle made of three 32-bits integer vertex references + * ...then you may want to use pointers instead of callbacks. This is the same, except OPCODE will directly + * use provided pointers to access the topology and geometry, without using a callback. It might be faster, + * but probably not as safe. Pointers have been introduced in OPCODE 1.2. + * + * Ex: + * + * \code + * // Setup pointers + * MeshInterface0->SetPointers(Mesh0->GetFaces(), Mesh0->GetVerts()); + * MeshInterface1->SetPointers(Mesh1->GetFaces(), Mesh1->GetVerts()); + * \endcode + * + * + * STRIDES: + * + * If your vertices are D3D-like entities interleaving a position, a normal and/or texture coordinates + * (i.e. if your vertices are FVFs), you might want to use a vertex stride to skip extra data OPCODE + * doesn't need. Using a stride shouldn't be notably slower than not using it, but it might increase + * cache misses. Please also note that you *shouldn't* read from AGP or video-memory buffers ! + * + * + * In any case, compilation flags are here to select callbacks/pointers/strides at compile time, so + * choose what's best for your application. All of this has been wrapped into this MeshInterface. + * + * \class MeshInterface + * \author Pierre Terdiman + * \version 1.3 + * \date November, 27, 2002 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +MeshInterface::MeshInterface() : +#ifdef OPC_USE_CALLBACKS + mUserData (null), + mObjCallback (null), +#else + mTris (null), + mVerts (null), + #ifdef OPC_USE_STRIDE + mTriStride (sizeof(IndexedTriangle)), + mVertexStride (sizeof(Point)), + #endif +#endif + mNbTris (0), + mNbVerts (0) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +MeshInterface::~MeshInterface() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the mesh interface is valid, i.e. things have been setup correctly. + * \return true if valid + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool MeshInterface::IsValid() const +{ + if(!mNbTris || !mNbVerts) return false; +#ifdef OPC_USE_CALLBACKS + if(!mObjCallback) return false; +#else + if(!mTris || !mVerts) return false; +#endif + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the mesh itself is valid. + * Currently we only look for degenerate faces. + * \return number of degenerate faces + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword MeshInterface::CheckTopology() const +{ + // Check topology. If the model contains degenerate faces, collision report can be wrong in some cases. + // e.g. it happens with the standard MAX teapot. So clean your meshes first... If you don't have a mesh cleaner + // you can try this: www.codercorner.com/Consolidation.zip + + udword NbDegenerate = 0; + + VertexPointers VP; + + // Using callbacks, we don't have access to vertex indices. Nevertheless we still can check for + // redundant vertex pointers, which cover all possibilities (callbacks/pointers/strides). + for(udword i=0;i= 0.0f; + } + }; + +#ifdef OPC_USE_CALLBACKS + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * User-callback, called by OPCODE to request vertices from the app. + * \param triangle_index [in] face index for which the system is requesting the vertices + * \param triangle [out] triangle's vertices (must be provided by the user) + * \param user_data [in] user-defined data from SetCallback() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + typedef void (*RequestCallback) (udword triangle_index, VertexPointers& triangle, void* user_data); +#endif + + class OPCODE_API MeshInterface + { + public: + // Constructor / Destructor + MeshInterface(); + ~MeshInterface(); + // Common settings + inline_ udword GetNbTriangles() const { return mNbTris; } + inline_ udword GetNbVertices() const { return mNbVerts; } + inline_ void SetNbTriangles(udword nb) { mNbTris = nb; } + inline_ void SetNbVertices(udword nb) { mNbVerts = nb; } + +#ifdef OPC_USE_CALLBACKS + // Callback settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Callback control: setups object callback. Must provide triangle-vertices for a given triangle index. + * \param callback [in] user-defined callback + * \param user_data [in] user-defined data + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool SetCallback(RequestCallback callback, void* user_data); + inline_ void* GetUserData() const { return mUserData; } + inline_ RequestCallback GetCallback() const { return mObjCallback; } +#else + // Pointers settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Pointers control: setups object pointers. Must provide access to faces and vertices for a given object. + * \param tris [in] pointer to triangles + * \param verts [in] pointer to vertices + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool SetPointers(const IndexedTriangle* tris, const Point* verts); + inline_ const IndexedTriangle* GetTris() const { return mTris; } + inline_ const Point* GetVerts() const { return mVerts; } + + #ifdef OPC_USE_STRIDE + // Strides settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Strides control + * \param tri_stride [in] size of a triangle in bytes. The first sizeof(IndexedTriangle) bytes are used to get vertex indices. + * \param vertex_stride [in] size of a vertex in bytes. The first sizeof(Point) bytes are used to get vertex position. + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool SetStrides(udword tri_stride=sizeof(IndexedTriangle), udword vertex_stride=sizeof(Point)); + inline_ udword GetTriStride() const { return mTriStride; } + inline_ udword GetVertexStride() const { return mVertexStride; } + #endif +#endif + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Fetches a triangle given a triangle index. + * \param vp [out] required triangle's vertex pointers + * \param index [in] triangle index + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void GetTriangle(VertexPointers& vp, udword index) const + { +#ifdef OPC_USE_CALLBACKS + (mObjCallback)(index, vp, mUserData); +#else + #ifdef OPC_USE_STRIDE + const IndexedTriangle* T = (const IndexedTriangle*)(((ubyte*)mTris) + index * mTriStride); + vp.Vertex[0] = (const Point*)(((ubyte*)mVerts) + T->mVRef[0] * mVertexStride); + vp.Vertex[1] = (const Point*)(((ubyte*)mVerts) + T->mVRef[1] * mVertexStride); + vp.Vertex[2] = (const Point*)(((ubyte*)mVerts) + T->mVRef[2] * mVertexStride); + #else + const IndexedTriangle* T = &mTris[index]; + vp.Vertex[0] = &mVerts[T->mVRef[0]]; + vp.Vertex[1] = &mVerts[T->mVRef[1]]; + vp.Vertex[2] = &mVerts[T->mVRef[2]]; + #endif +#endif + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Remaps client's mesh according to a permutation. + * \param nb_indices [in] number of indices in the permutation (will be checked against number of triangles) + * \param permutation [in] list of triangle indices + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool RemapClient(udword nb_indices, const udword* permutation) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the mesh interface is valid, i.e. things have been setup correctly. + * \return true if valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool IsValid() const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the mesh itself is valid. + * Currently we only look for degenerate faces. + * \return number of degenerate faces + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + udword CheckTopology() const; + private: + + udword mNbTris; //!< Number of triangles in the input model + udword mNbVerts; //!< Number of vertices in the input model +#ifdef OPC_USE_CALLBACKS + // User callback + void* mUserData; //!< User-defined data sent to callback + RequestCallback mObjCallback; //!< Object callback +#else + // User pointers + const IndexedTriangle* mTris; //!< Array of indexed triangles + const Point* mVerts; //!< Array of vertices + #ifdef OPC_USE_STRIDE + udword mTriStride; //!< Possible triangle stride in bytes [Opcode 1.3] + udword mVertexStride; //!< Possible vertex stride in bytes [Opcode 1.3] + #endif +#endif + }; + +#endif //__OPC_MESHINTERFACE_H__ \ No newline at end of file diff --git a/Extras/CDTestFramework/Opcode/OPC_Model.cpp b/Extras/CDTestFramework/Opcode/OPC_Model.cpp new file mode 100644 index 0000000..f8c4c87 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_Model.cpp @@ -0,0 +1,231 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for OPCODE models. + * \file OPC_Model.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * The main collision wrapper, for all trees. Supported trees are: + * - Normal trees (2*N-1 nodes, full size) + * - No-leaf trees (N-1 nodes, full size) + * - Quantized trees (2*N-1 nodes, half size) + * - Quantized no-leaf trees (N-1 nodes, half size) + * + * Usage: + * + * 1) Create a static mesh interface using callbacks or pointers. (see OPC_MeshInterface.cpp). + * Keep it around in your app, since a pointer to this interface is saved internally and + * used until you release the collision structures. + * + * 2) Build a Model using a creation structure: + * + * \code + * Model Sample; + * + * OPCODECREATE OPCC; + * OPCC.IMesh = ...; + * OPCC.Rules = ...; + * OPCC.NoLeaf = ...; + * OPCC.Quantized = ...; + * OPCC.KeepOriginal = ...; + * bool Status = Sample.Build(OPCC); + * \endcode + * + * 3) Create a tree collider and set it up: + * + * \code + * AABBTreeCollider TC; + * TC.SetFirstContact(...); + * TC.SetFullBoxBoxTest(...); + * TC.SetFullPrimBoxTest(...); + * TC.SetTemporalCoherence(...); + * \endcode + * + * 4) Perform a collision query + * + * \code + * // Setup cache + * static BVTCache ColCache; + * ColCache.Model0 = &Model0; + * ColCache.Model1 = &Model1; + * + * // Collision query + * bool IsOk = TC.Collide(ColCache, World0, World1); + * + * // Get collision status => if true, objects overlap + * BOOL Status = TC.GetContactStatus(); + * + * // Number of colliding pairs and list of pairs + * udword NbPairs = TC.GetNbPairs(); + * const Pair* p = TC.GetPairs() + * \endcode + * + * 5) Stats + * + * \code + * Model0.GetUsedBytes() = number of bytes used for this collision tree + * TC.GetNbBVBVTests() = number of BV-BV overlap tests performed during last query + * TC.GetNbPrimPrimTests() = number of Triangle-Triangle overlap tests performed during last query + * TC.GetNbBVPrimTests() = number of Triangle-BV overlap tests performed during last query + * \endcode + * + * \class Model + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Model::Model() +{ +#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! + mHull = null; +#endif // __MESHMERIZER_H__ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Model::~Model() +{ + Release(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Releases the model. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Model::Release() +{ + ReleaseBase(); +#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! + DELETESINGLE(mHull); +#endif // __MESHMERIZER_H__ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds a collision model. + * \param create [in] model creation structure + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Model::Build(const OPCODECREATE& create) +{ + // 1) Checkings + if(!create.mIMesh || !create.mIMesh->IsValid()) return false; + + // For this model, we only support complete trees + if(create.mSettings.mLimit!=1) return SetIceError("OPCODE WARNING: supports complete trees only! Use mLimit = 1.\n", null); + + // Look for degenerate faces. + udword NbDegenerate = create.mIMesh->CheckTopology(); + if(NbDegenerate) Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate); + // We continue nonetheless.... + + Release(); // Make sure previous tree has been discarded [Opcode 1.3, thanks Adam] + + // 1-1) Setup mesh interface automatically [Opcode 1.3] + SetMeshInterface(create.mIMesh); + + // Special case for 1-triangle meshes [Opcode 1.3] + udword NbTris = create.mIMesh->GetNbTriangles(); + if(NbTris==1) + { + // We don't need to actually create a tree here, since we'll only have a single triangle to deal with anyway. + // It's a waste to use a "model" for this but at least it will work. + mModelCode |= OPC_SINGLE_NODE; + return true; + } + + // 2) Build a generic AABB Tree. + mSource = new AABBTree; + CHECKALLOC(mSource); + + // 2-1) Setup a builder. Our primitives here are triangles from input mesh, + // so we use an AABBTreeOfTrianglesBuilder..... + { + AABBTreeOfTrianglesBuilder TB; + TB.mIMesh = create.mIMesh; + TB.mSettings = create.mSettings; + TB.mNbPrimitives = NbTris; + if(!mSource->Build(&TB)) return false; + } + + // 3) Create an optimized tree according to user-settings + if(!CreateTree(create.mNoLeaf, create.mQuantized)) return false; + + // 3-2) Create optimized tree + if(!mTree->Build(mSource)) return false; + + // 3-3) Delete generic tree if needed + if(!create.mKeepOriginal) DELETESINGLE(mSource); + +#ifdef __MESHMERIZER_H__ + // 4) Convex hull + if(create.mCollisionHull) + { + // Create hull + mHull = new CollisionHull; + CHECKALLOC(mHull); + + CONVEXHULLCREATE CHC; + // ### doesn't work with strides + CHC.NbVerts = create.mIMesh->GetNbVertices(); + CHC.Vertices = create.mIMesh->GetVerts(); + CHC.UnifyNormals = true; + CHC.ReduceVertices = true; + CHC.WordFaces = false; + mHull->Compute(CHC); + } +#endif // __MESHMERIZER_H__ + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Gets the number of bytes used by the tree. + * \return amount of bytes used + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword Model::GetUsedBytes() const +{ + if(!mTree) return 0; + return mTree->GetUsedBytes(); +} diff --git a/Extras/CDTestFramework/Opcode/OPC_Model.h b/Extras/CDTestFramework/Opcode/OPC_Model.h new file mode 100644 index 0000000..0124135 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_Model.h @@ -0,0 +1,74 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for OPCODE models. + * \file OPC_Model.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_MODEL_H__ +#define __OPC_MODEL_H__ + + class OPCODE_API Model : public BaseModel + { + public: + // Constructor/Destructor + Model(); + virtual ~Model(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Builds a collision model. + * \param create [in] model creation structure + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(BaseModel) bool Build(const OPCODECREATE& create); + +#ifdef __MESHMERIZER_H__ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the collision hull. + * \return the collision hull if it exists + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const CollisionHull* GetHull() const { return mHull; } +#endif // __MESHMERIZER_H__ + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of bytes used by the tree. + * \return amount of bytes used + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(BaseModel) udword GetUsedBytes() const; + + private: +#ifdef __MESHMERIZER_H__ + CollisionHull* mHull; //!< Possible convex hull +#endif // __MESHMERIZER_H__ + // Internal methods + void Release(); + }; + +#endif //__OPC_MODEL_H__ \ No newline at end of file diff --git a/Extras/CDTestFramework/Opcode/OPC_OBBCollider.cpp b/Extras/CDTestFramework/Opcode/OPC_OBBCollider.cpp new file mode 100644 index 0000000..9930240 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_OBBCollider.cpp @@ -0,0 +1,776 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for an OBB collider. + * \file OPC_OBBCollider.cpp + * \author Pierre Terdiman + * \date January, 1st, 2002 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an OBB-vs-tree collider. + * + * \class OBBCollider + * \author Pierre Terdiman + * \version 1.3 + * \date January, 1st, 2002 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +#include "OPC_BoxBoxOverlap.h" +#include "OPC_TriBoxOverlap.h" + +#define SET_CONTACT(prim_index, flag) \ + /* Set contact status */ \ + mFlags |= flag; \ + mTouchedPrimitives->Add(prim_index); + +//! OBB-triangle test +#define OBB_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \ + /* Transform them in a common space */ \ + TransformPoint(mLeafVerts[0], *VP.Vertex[0], mRModelToBox, mTModelToBox); \ + TransformPoint(mLeafVerts[1], *VP.Vertex[1], mRModelToBox, mTModelToBox); \ + TransformPoint(mLeafVerts[2], *VP.Vertex[2], mRModelToBox, mTModelToBox); \ + /* Perform triangle-box overlap test */ \ + if(TriBoxOverlap()) \ + { \ + SET_CONTACT(prim_index, flag) \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +OBBCollider::OBBCollider() : mFullBoxBoxTest(true) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +OBBCollider::~OBBCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Validates current settings. You should call this method after all the settings and callbacks have been defined. + * \return null if everything is ok, else a string describing the problem + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const char* OBBCollider::ValidateSettings() +{ + if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!"; + + return VolumeCollider::ValidateSettings(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a box cache + * \param box [in] collision OBB in local space + * \param model [in] Opcode model to collide with + * \param worldb [in] OBB's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool OBBCollider::Collide(OBBCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb, const Matrix4x4* worldm) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, box, worldb, worldm)) return true; + + if(!model.HasLeafNodes()) + { + if(model.IsQuantized()) + { + const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - setup matrices + * - check temporal coherence + * + * \param cache [in/out] a box cache + * \param box [in] obb in local space + * \param worldb [in] obb's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return TRUE if we can return immediately + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL OBBCollider::InitQuery(OBBCache& cache, const OBB& box, const Matrix4x4* worldb, const Matrix4x4* worldm) +{ + // 1) Call the base method + VolumeCollider::InitQuery(); + + // 2) Compute obb in world space + mBoxExtents = box.mExtents; + + Matrix4x4 WorldB; + + if(worldb) + { + WorldB = Matrix4x4( box.mRot * Matrix3x3(*worldb) ); + WorldB.SetTrans(box.mCenter * *worldb); + } + else + { + WorldB = box.mRot; + WorldB.SetTrans(box.mCenter); + } + + // Setup matrices + Matrix4x4 InvWorldB; + InvertPRMatrix(InvWorldB, WorldB); + + if(worldm) + { + Matrix4x4 InvWorldM; + InvertPRMatrix(InvWorldM, *worldm); + + Matrix4x4 WorldBtoM = WorldB * InvWorldM; + Matrix4x4 WorldMtoB = *worldm * InvWorldB; + + mRModelToBox = WorldMtoB; WorldMtoB.GetTrans(mTModelToBox); + mRBoxToModel = WorldBtoM; WorldBtoM.GetTrans(mTBoxToModel); + } + else + { + mRModelToBox = InvWorldB; InvWorldB.GetTrans(mTModelToBox); + mRBoxToModel = WorldB; WorldB.GetTrans(mTBoxToModel); + } + + // 3) Setup destination pointer + mTouchedPrimitives = &cache.TouchedPrimitives; + + // 4) Special case: 1-triangle meshes [Opcode 1.3] + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + if(!SkipPrimitiveTests()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + mTouchedPrimitives->Reset(); + + // Perform overlap test between the unique triangle and the box (and set contact status if needed) + OBB_PRIM(udword(0), OPC_CONTACT) + + // Return immediately regardless of status + return TRUE; + } + } + + // 5) Check temporal coherence: + if(TemporalCoherenceEnabled()) + { + // Here we use temporal coherence + // => check results from previous frame before performing the collision query + if(FirstContactEnabled()) + { + // We're only interested in the first contact found => test the unique previously touched face + if(mTouchedPrimitives->GetNbEntries()) + { + // Get index of previously touched face = the first entry in the array + udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); + + // Then reset the array: + // - if the overlap test below is successful, the index we'll get added back anyway + // - if it isn't, then the array should be reset anyway for the normal query + mTouchedPrimitives->Reset(); + + // Perform overlap test between the cached triangle and the box (and set contact status if needed) + OBB_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) + + // Return immediately if possible + if(GetContactStatus()) return TRUE; + } + // else no face has been touched during previous query + // => we'll have to perform a normal query + } + else + { + // ### rewrite this + OBB TestBox(mTBoxToModel, mBoxExtents, mRBoxToModel); + + // We're interested in all contacts =>test the new real box N(ew) against the previous fat box P(revious): + if(IsCacheValid(cache) && TestBox.IsInside(cache.FatBox)) + { + // - if N is included in P, return previous list + // => we simply leave the list (mTouchedFaces) unchanged + + // Set contact status if needed + if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; + + // In any case we don't need to do a query + return TRUE; + } + else + { + // - else do the query using a fat N + + // Reset cache since we'll about to perform a real query + mTouchedPrimitives->Reset(); + + // Make a fat box so that coherence will work for subsequent frames + TestBox.mExtents *= cache.FatCoeff; + mBoxExtents *= cache.FatCoeff; + + // Update cache with query data (signature for cached faces) + cache.FatBox = TestBox; + } + } + } + else + { + // Here we don't use temporal coherence => do a normal query + mTouchedPrimitives->Reset(); + } + + // Now we can precompute box-box data + + // Precompute absolute box-to-model rotation matrix + for(udword i=0;i<3;i++) + { + for(udword j=0;j<3;j++) + { + // Epsilon value prevents floating-point inaccuracies (strategy borrowed from RAPID) + mAR.m[i][j] = 1e-6f + fabsf(mRBoxToModel.m[i][j]); + } + } + + // Precompute bounds for box-in-box test + mB0 = mBoxExtents - mTModelToBox; + mB1 = - mBoxExtents - mTModelToBox; + + // Precompute box-box data - Courtesy of Erwin de Vries + mBBx1 = mBoxExtents.x*mAR.m[0][0] + mBoxExtents.y*mAR.m[1][0] + mBoxExtents.z*mAR.m[2][0]; + mBBy1 = mBoxExtents.x*mAR.m[0][1] + mBoxExtents.y*mAR.m[1][1] + mBoxExtents.z*mAR.m[2][1]; + mBBz1 = mBoxExtents.x*mAR.m[0][2] + mBoxExtents.y*mAR.m[1][2] + mBoxExtents.z*mAR.m[2][2]; + + mBB_1 = mBoxExtents.y*mAR.m[2][0] + mBoxExtents.z*mAR.m[1][0]; + mBB_2 = mBoxExtents.x*mAR.m[2][0] + mBoxExtents.z*mAR.m[0][0]; + mBB_3 = mBoxExtents.x*mAR.m[1][0] + mBoxExtents.y*mAR.m[0][0]; + mBB_4 = mBoxExtents.y*mAR.m[2][1] + mBoxExtents.z*mAR.m[1][1]; + mBB_5 = mBoxExtents.x*mAR.m[2][1] + mBoxExtents.z*mAR.m[0][1]; + mBB_6 = mBoxExtents.x*mAR.m[1][1] + mBoxExtents.y*mAR.m[0][1]; + mBB_7 = mBoxExtents.y*mAR.m[2][2] + mBoxExtents.z*mAR.m[1][2]; + mBB_8 = mBoxExtents.x*mAR.m[2][2] + mBoxExtents.z*mAR.m[0][2]; + mBB_9 = mBoxExtents.x*mAR.m[1][2] + mBoxExtents.y*mAR.m[0][2]; + + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the OBB completely contains the box. In which case we can end the query sooner. + * \param bc [in] box center + * \param be [in] box extents + * \return true if the OBB contains the whole box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL OBBCollider::OBBContainsBox(const Point& bc, const Point& be) +{ + // I assume if all 8 box vertices are inside the OBB, so does the whole box. + // Sounds ok but maybe there's a better way? +/* +#define TEST_PT(a,b,c) \ + p.x=a; p.y=b; p.z=c; p+=bc; \ + f = p.x * mRModelToBox.m[0][0] + p.y * mRModelToBox.m[1][0] + p.z * mRModelToBox.m[2][0]; if(f>mB0.x || fmB0.y || fmB0.z || f NCx-NEx) return FALSE; + + float NCy = bc.x * mRModelToBox.m[0][1] + bc.y * mRModelToBox.m[1][1] + bc.z * mRModelToBox.m[2][1]; + float NEy = fabsf(mRModelToBox.m[0][1] * be.x) + fabsf(mRModelToBox.m[1][1] * be.y) + fabsf(mRModelToBox.m[2][1] * be.z); + + if(mB0.y < NCy+NEy) return FALSE; + if(mB1.y > NCy-NEy) return FALSE; + + float NCz = bc.x * mRModelToBox.m[0][2] + bc.y * mRModelToBox.m[1][2] + bc.z * mRModelToBox.m[2][2]; + float NEz = fabsf(mRModelToBox.m[0][2] * be.x) + fabsf(mRModelToBox.m[1][2] * be.y) + fabsf(mRModelToBox.m[2][2] * be.z); + + if(mB0.z < NCz+NEz) return FALSE; + if(mB1.z > NCz-NEz) return FALSE; + + return TRUE; +} + +#define TEST_BOX_IN_OBB(center, extents) \ + if(OBBContainsBox(center, extents)) \ + { \ + /* Set contact status */ \ + mFlags |= OPC_CONTACT; \ + _Dump(node); \ + return; \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_Collide(const AABBCollisionNode* node) +{ + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + OBB_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) +{ + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_Collide(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(Extents, Center)) return; + + TEST_BOX_IN_OBB(Center, Extents) + + if(node->IsLeaf()) + { + OBB_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(Extents, Center)) return; + + TEST_BOX_IN_OBB(Center, Extents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_Collide(const AABBNoLeafNode* node) +{ + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { OBB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { OBB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) +{ + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_Collide(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(Extents, Center)) return; + + TEST_BOX_IN_OBB(Center, Extents) + + if(node->HasPosLeaf()) { OBB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { OBB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(Extents, Center)) return; + + TEST_BOX_IN_OBB(Center, Extents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridOBBCollider::HybridOBBCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridOBBCollider::~HybridOBBCollider() +{ +} + +bool HybridOBBCollider::Collide(OBBCache& cache, const OBB& box, const HybridModel& model, const Matrix4x4* worldb, const Matrix4x4* worldm) +{ + // We don't want primitive tests here! + mFlags |= OPC_NO_PRIMITIVE_TESTS; + + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, box, worldb, worldm)) return true; + + // Special case for 1-leaf trees + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles + udword Nb = mIMesh->GetNbTriangles(); + + // Loop through all triangles + for(udword i=0;imCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + + // We only have a list of boxes so far + if(GetContactStatus()) + { + // Reset contact status, since it currently only reflects collisions with leaf boxes + Collider::InitQuery(); + + // Change dest container so that we can use built-in overlap tests and get collided primitives + cache.TouchedPrimitives.Reset(); + mTouchedPrimitives = &cache.TouchedPrimitives; + + // Read touched leaf boxes + udword Nb = mTouchedBoxes.GetNbEntries(); + const udword* Touched = mTouchedBoxes.GetEntries(); + + const LeafTriangles* LT = model.GetLeafTriangles(); + const udword* Indices = model.GetIndices(); + + // Loop through touched leaves + while(Nb--) + { + const LeafTriangles& CurrentLeaf = LT[*Touched++]; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = *T++; + OBB_PRIM(TriangleIndex, OPC_CONTACT) + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = BaseIndex++; + OBB_PRIM(TriangleIndex, OPC_CONTACT) + } + } + } + } + + return true; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_OBBCollider.h b/Extras/CDTestFramework/Opcode/OPC_OBBCollider.h new file mode 100644 index 0000000..58272cd --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_OBBCollider.h @@ -0,0 +1,151 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for an OBB collider. + * \file OPC_OBBCollider.h + * \author Pierre Terdiman + * \date January, 1st, 2002 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_OBBCOLLIDER_H__ +#define __OPC_OBBCOLLIDER_H__ + + struct OPCODE_API OBBCache : VolumeCache + { + OBBCache() : FatCoeff(1.1f) + { + FatBox.mCenter.Zero(); + FatBox.mExtents.Zero(); + FatBox.mRot.Identity(); + } + + // Cached faces signature + OBB FatBox; //!< Box used when performing the query resulting in cached faces + // User settings + float FatCoeff; //!< extents multiplier used to create a fat box + }; + + class OPCODE_API OBBCollider : public VolumeCollider + { + public: + // Constructor / Destructor + OBBCollider(); + virtual ~OBBCollider(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a box cache + * \param box [in] collision OBB in local space + * \param model [in] Opcode model to collide with + * \param worldb [in] OBB's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(OBBCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null); + + // Settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: select between full box-box tests or "SAT-lite" tests (where Class III axes are discarded) + * \param flag [in] true for full tests, false for coarse tests + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetFullBoxBoxTest(bool flag) { mFullBoxBoxTest = flag; } + + // Settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. + * \return null if everything is ok, else a string describing the problem + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(Collider) const char* ValidateSettings(); + + protected: + // Precomputed data + Matrix3x3 mAR; //!< Absolute rotation matrix + Matrix3x3 mRModelToBox; //!< Rotation from model space to obb space + Matrix3x3 mRBoxToModel; //!< Rotation from obb space to model space + Point mTModelToBox; //!< Translation from model space to obb space + Point mTBoxToModel; //!< Translation from obb space to model space + + Point mBoxExtents; + Point mB0; //!< - mTModelToBox + mBoxExtents + Point mB1; //!< - mTModelToBox - mBoxExtents + + float mBBx1; + float mBBy1; + float mBBz1; + + float mBB_1; + float mBB_2; + float mBB_3; + float mBB_4; + float mBB_5; + float mBB_6; + float mBB_7; + float mBB_8; + float mBB_9; + + // Leaf description + Point mLeafVerts[3]; //!< Triangle vertices + // Settings + bool mFullBoxBoxTest; //!< Perform full BV-BV tests (true) or SAT-lite tests (false) + // Internal methods + void _Collide(const AABBCollisionNode* node); + void _Collide(const AABBNoLeafNode* node); + void _Collide(const AABBQuantizedNode* node); + void _Collide(const AABBQuantizedNoLeafNode* node); + void _CollideNoPrimitiveTest(const AABBCollisionNode* node); + void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); + // Overlap tests + inline_ BOOL OBBContainsBox(const Point& bc, const Point& be); + inline_ BOOL BoxBoxOverlap(const Point& extents, const Point& center); + inline_ BOOL TriBoxOverlap(); + // Init methods + BOOL InitQuery(OBBCache& cache, const OBB& box, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null); + }; + + class OPCODE_API HybridOBBCollider : public OBBCollider + { + public: + // Constructor / Destructor + HybridOBBCollider(); + virtual ~HybridOBBCollider(); + + bool Collide(OBBCache& cache, const OBB& box, const HybridModel& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null); + protected: + Container mTouchedBoxes; + }; + +#endif // __OPC_OBBCOLLIDER_H__ diff --git a/Extras/CDTestFramework/Opcode/OPC_OptimizedTree.cpp b/Extras/CDTestFramework/Opcode/OPC_OptimizedTree.cpp new file mode 100644 index 0000000..59eb562 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_OptimizedTree.cpp @@ -0,0 +1,791 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for optimized trees. Implements 4 trees: + * - normal + * - no leaf + * - quantized + * - no leaf / quantized + * + * \file OPC_OptimizedTree.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A standard AABB tree. + * + * \class AABBCollisionTree + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A no-leaf AABB tree. + * + * \class AABBNoLeafTree + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A quantized AABB tree. + * + * \class AABBQuantizedTree + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A quantized no-leaf AABB tree. + * + * \class AABBQuantizedNoLeafTree + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +//! Compilation flag: +//! - true to fix quantized boxes (i.e. make sure they enclose the original ones) +//! - false to see the effects of quantization errors (faster, but wrong results in some cases) +static bool gFixQuantized = true; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds an implicit tree from a standard one. An implicit tree is a complete tree (2*N-1 nodes) whose negative + * box pointers and primitive pointers have been made implicit, hence packing 3 pointers in one. + * + * Layout for implicit trees: + * Node: + * - box + * - data (32-bits value) + * + * if data's LSB = 1 => remaining bits are a primitive pointer + * else remaining bits are a P-node pointer, and N = P + 1 + * + * \relates AABBCollisionNode + * \fn _BuildCollisionTree(AABBCollisionNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) + * \param linear [in] base address of destination nodes + * \param box_id [in] index of destination node + * \param current_id [in] current running index + * \param current_node [in] current node from input tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static void _BuildCollisionTree(AABBCollisionNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) +{ + // Current node from input tree is "current_node". Must be flattened into "linear[boxid]". + + // Store the AABB + current_node->GetAABB()->GetCenter(linear[box_id].mAABB.mCenter); + current_node->GetAABB()->GetExtents(linear[box_id].mAABB.mExtents); + // Store remaining info + if(current_node->IsLeaf()) + { + // The input tree must be complete => i.e. one primitive/leaf + ASSERT(current_node->GetNbPrimitives()==1); + // Get the primitive index from the input tree + udword PrimitiveIndex = current_node->GetPrimitives()[0]; + // Setup box data as the primitive index, marked as leaf + linear[box_id].mData = (PrimitiveIndex<<1)|1; + } + else + { + // To make the negative one implicit, we must store P and N in successive order + udword PosID = current_id++; // Get a new id for positive child + udword NegID = current_id++; // Get a new id for negative child + // Setup box data as the forthcoming new P pointer + linear[box_id].mData = (udword)&linear[PosID]; + // Make sure it's not marked as leaf + ASSERT(!(linear[box_id].mData&1)); + // Recurse with new IDs + _BuildCollisionTree(linear, PosID, current_id, current_node->GetPos()); + _BuildCollisionTree(linear, NegID, current_id, current_node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds a "no-leaf" tree from a standard one. This is a tree whose leaf nodes have been removed. + * + * Layout for no-leaf trees: + * + * Node: + * - box + * - P pointer => a node (LSB=0) or a primitive (LSB=1) + * - N pointer => a node (LSB=0) or a primitive (LSB=1) + * + * \relates AABBNoLeafNode + * \fn _BuildNoLeafTree(AABBNoLeafNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) + * \param linear [in] base address of destination nodes + * \param box_id [in] index of destination node + * \param current_id [in] current running index + * \param current_node [in] current node from input tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static void _BuildNoLeafTree(AABBNoLeafNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) +{ + const AABBTreeNode* P = current_node->GetPos(); + const AABBTreeNode* N = current_node->GetNeg(); + // Leaf nodes here?! + ASSERT(P); + ASSERT(N); + // Internal node => keep the box + current_node->GetAABB()->GetCenter(linear[box_id].mAABB.mCenter); + current_node->GetAABB()->GetExtents(linear[box_id].mAABB.mExtents); + + if(P->IsLeaf()) + { + // The input tree must be complete => i.e. one primitive/leaf + ASSERT(P->GetNbPrimitives()==1); + // Get the primitive index from the input tree + udword PrimitiveIndex = P->GetPrimitives()[0]; + // Setup prev box data as the primitive index, marked as leaf + linear[box_id].mPosData = (PrimitiveIndex<<1)|1; + } + else + { + // Get a new id for positive child + udword PosID = current_id++; + // Setup box data + linear[box_id].mPosData = (udword)&linear[PosID]; + // Make sure it's not marked as leaf + ASSERT(!(linear[box_id].mPosData&1)); + // Recurse + _BuildNoLeafTree(linear, PosID, current_id, P); + } + + if(N->IsLeaf()) + { + // The input tree must be complete => i.e. one primitive/leaf + ASSERT(N->GetNbPrimitives()==1); + // Get the primitive index from the input tree + udword PrimitiveIndex = N->GetPrimitives()[0]; + // Setup prev box data as the primitive index, marked as leaf + linear[box_id].mNegData = (PrimitiveIndex<<1)|1; + } + else + { + // Get a new id for negative child + udword NegID = current_id++; + // Setup box data + linear[box_id].mNegData = (udword)&linear[NegID]; + // Make sure it's not marked as leaf + ASSERT(!(linear[box_id].mNegData&1)); + // Recurse + _BuildNoLeafTree(linear, NegID, current_id, N); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBCollisionTree::AABBCollisionTree() : mNodes(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBCollisionTree::~AABBCollisionTree() +{ + DELETEARRAY(mNodes); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds the collision tree from a generic AABB tree. + * \param tree [in] generic AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBCollisionTree::Build(AABBTree* tree) +{ + // Checkings + if(!tree) return false; + // Check the input tree is complete + udword NbTriangles = tree->GetNbPrimitives(); + udword NbNodes = tree->GetNbNodes(); + if(NbNodes!=NbTriangles*2-1) return false; + + // Get nodes + if(mNbNodes!=NbNodes) // Same number of nodes => keep moving + { + mNbNodes = NbNodes; + DELETEARRAY(mNodes); + mNodes = new AABBCollisionNode[mNbNodes]; + CHECKALLOC(mNodes); + } + + // Build the tree + udword CurID = 1; + _BuildCollisionTree(mNodes, 0, CurID, tree); + ASSERT(CurID==mNbNodes); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the collision tree after vertices have been modified. + * \param mesh_interface [in] mesh interface for current model + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBCollisionTree::Refit(const MeshInterface* mesh_interface) +{ + ASSERT(!"Not implemented since AABBCollisionTrees have twice as more nodes to refit as AABBNoLeafTrees!"); + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Walks the tree and call the user back for each node. + * \param callback [in] walking callback + * \param user_data [in] callback's user data + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBCollisionTree::Walk(GenericWalkingCallback callback, void* user_data) const +{ + if(!callback) return false; + + struct Local + { + static void _Walk(const AABBCollisionNode* current_node, GenericWalkingCallback callback, void* user_data) + { + if(!current_node || !(callback)(current_node, user_data)) return; + + if(!current_node->IsLeaf()) + { + _Walk(current_node->GetPos(), callback, user_data); + _Walk(current_node->GetNeg(), callback, user_data); + } + } + }; + Local::_Walk(mNodes, callback, user_data); + return true; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBNoLeafTree::AABBNoLeafTree() : mNodes(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBNoLeafTree::~AABBNoLeafTree() +{ + DELETEARRAY(mNodes); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds the collision tree from a generic AABB tree. + * \param tree [in] generic AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBNoLeafTree::Build(AABBTree* tree) +{ + // Checkings + if(!tree) return false; + // Check the input tree is complete + udword NbTriangles = tree->GetNbPrimitives(); + udword NbNodes = tree->GetNbNodes(); + if(NbNodes!=NbTriangles*2-1) return false; + + // Get nodes + if(mNbNodes!=NbTriangles-1) // Same number of nodes => keep moving + { + mNbNodes = NbTriangles-1; + DELETEARRAY(mNodes); + mNodes = new AABBNoLeafNode[mNbNodes]; + CHECKALLOC(mNodes); + } + + // Build the tree + udword CurID = 1; + _BuildNoLeafTree(mNodes, 0, CurID, tree); + ASSERT(CurID==mNbNodes); + + return true; +} + +inline_ void ComputeMinMax_OT(Point& min, Point& max, const VertexPointers& vp) +{ + // Compute triangle's AABB = a leaf box +#ifdef OPC_USE_FCOMI // a 15% speedup on my machine, not much + min.x = FCMin3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); + max.x = FCMax3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); + + min.y = FCMin3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); + max.y = FCMax3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); + + min.z = FCMin3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); + max.z = FCMax3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); +#else + min = *vp.Vertex[0]; + max = *vp.Vertex[0]; + min.Min(*vp.Vertex[1]); + max.Max(*vp.Vertex[1]); + min.Min(*vp.Vertex[2]); + max.Max(*vp.Vertex[2]); +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the collision tree after vertices have been modified. + * \param mesh_interface [in] mesh interface for current model + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBNoLeafTree::Refit(const MeshInterface* mesh_interface) +{ + // Checkings + if(!mesh_interface) return false; + + // Bottom-up update + VertexPointers VP; + Point Min,Max; + Point Min_,Max_; + udword Index = mNbNodes; + while(Index--) + { + AABBNoLeafNode& Current = mNodes[Index]; + + if(Current.HasPosLeaf()) + { + mesh_interface->GetTriangle(VP, Current.GetPosPrimitive()); + ComputeMinMax_OT(Min, Max, VP); + } + else + { + const CollisionAABB& CurrentBox = Current.GetPos()->mAABB; + CurrentBox.GetMin(Min); + CurrentBox.GetMax(Max); + } + + if(Current.HasNegLeaf()) + { + mesh_interface->GetTriangle(VP, Current.GetNegPrimitive()); + ComputeMinMax_OT(Min_, Max_, VP); + } + else + { + const CollisionAABB& CurrentBox = Current.GetNeg()->mAABB; + CurrentBox.GetMin(Min_); + CurrentBox.GetMax(Max_); + } +#ifdef OPC_USE_FCOMI + Min.x = FCMin2(Min.x, Min_.x); + Max.x = FCMax2(Max.x, Max_.x); + Min.y = FCMin2(Min.y, Min_.y); + Max.y = FCMax2(Max.y, Max_.y); + Min.z = FCMin2(Min.z, Min_.z); + Max.z = FCMax2(Max.z, Max_.z); +#else + Min.Min(Min_); + Max.Max(Max_); +#endif + Current.mAABB.SetMinMax(Min, Max); + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Walks the tree and call the user back for each node. + * \param callback [in] walking callback + * \param user_data [in] callback's user data + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBNoLeafTree::Walk(GenericWalkingCallback callback, void* user_data) const +{ + if(!callback) return false; + + struct Local + { + static void _Walk(const AABBNoLeafNode* current_node, GenericWalkingCallback callback, void* user_data) + { + if(!current_node || !(callback)(current_node, user_data)) return; + + if(!current_node->HasPosLeaf()) _Walk(current_node->GetPos(), callback, user_data); + if(!current_node->HasNegLeaf()) _Walk(current_node->GetNeg(), callback, user_data); + } + }; + Local::_Walk(mNodes, callback, user_data); + return true; +} + +// Quantization notes: +// - We could use the highest bits of mData to store some more quantized bits. Dequantization code +// would be slightly more complex, but number of overlap tests would be reduced (and anyhow those +// bits are currently wasted). Of course it's not possible if we move to 16 bits mData. +// - Something like "16 bits floats" could be tested, to bypass the int-to-float conversion. +// - A dedicated BV-BV test could be used, dequantizing while testing for overlap. (i.e. it's some +// lazy-dequantization which may save some work in case of early exits). At the very least some +// muls could be saved by precomputing several more matrices. But maybe not worth the pain. +// - Do we need to dequantize anyway? Not doing the extents-related muls only implies the box has +// been scaled, for example. +// - The deeper we move into the hierarchy, the smaller the extents should be. May not need a fixed +// number of quantization bits. Even better, could probably be best delta-encoded. + + +// Find max values. Some people asked why I wasn't simply using the first node. Well, I can't. +// I'm not looking for (min, max) values like in a standard AABB, I'm looking for the extremal +// centers/extents in order to quantize them. The first node would only give a single center and +// a single extents. While extents would be the biggest, the center wouldn't. +#define FIND_MAX_VALUES \ + /* Get max values */ \ + Point CMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); \ + Point EMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); \ + for(udword i=0;iCMax.x) CMax.x = fabsf(Nodes[i].mAABB.mCenter.x); \ + if(fabsf(Nodes[i].mAABB.mCenter.y)>CMax.y) CMax.y = fabsf(Nodes[i].mAABB.mCenter.y); \ + if(fabsf(Nodes[i].mAABB.mCenter.z)>CMax.z) CMax.z = fabsf(Nodes[i].mAABB.mCenter.z); \ + if(fabsf(Nodes[i].mAABB.mExtents.x)>EMax.x) EMax.x = fabsf(Nodes[i].mAABB.mExtents.x); \ + if(fabsf(Nodes[i].mAABB.mExtents.y)>EMax.y) EMax.y = fabsf(Nodes[i].mAABB.mExtents.y); \ + if(fabsf(Nodes[i].mAABB.mExtents.z)>EMax.z) EMax.z = fabsf(Nodes[i].mAABB.mExtents.z); \ + } + +#define INIT_QUANTIZATION \ + udword nbc=15; /* Keep one bit for sign */ \ + udword nbe=15; /* Keep one bit for fix */ \ + if(!gFixQuantized) nbe++; \ + \ + /* Compute quantization coeffs */ \ + Point CQuantCoeff, EQuantCoeff; \ + CQuantCoeff.x = CMax.x!=0.0f ? float((1<Min[j]) mNodes[i].mAABB.mExtents[j]++; \ + else FixMe=false; \ + /* Prevent wrapping */ \ + if(!mNodes[i].mAABB.mExtents[j]) \ + { \ + mNodes[i].mAABB.mExtents[j]=0xffff; \ + FixMe=false; \ + } \ + }while(FixMe); \ + } \ + } + +#define REMAP_DATA(member) \ + /* Fix data */ \ + Data = Nodes[i].member; \ + if(!(Data&1)) \ + { \ + /* Compute box number */ \ + udword Nb = (Data - udword(Nodes))/Nodes[i].GetNodeSize(); \ + Data = udword(&mNodes[Nb]); \ + } \ + /* ...remapped */ \ + mNodes[i].member = Data; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBQuantizedTree::AABBQuantizedTree() : mNodes(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBQuantizedTree::~AABBQuantizedTree() +{ + DELETEARRAY(mNodes); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds the collision tree from a generic AABB tree. + * \param tree [in] generic AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBQuantizedTree::Build(AABBTree* tree) +{ + // Checkings + if(!tree) return false; + // Check the input tree is complete + udword NbTriangles = tree->GetNbPrimitives(); + udword NbNodes = tree->GetNbNodes(); + if(NbNodes!=NbTriangles*2-1) return false; + + // Get nodes + mNbNodes = NbNodes; + DELETEARRAY(mNodes); + AABBCollisionNode* Nodes = new AABBCollisionNode[mNbNodes]; + CHECKALLOC(Nodes); + + // Build the tree + udword CurID = 1; + _BuildCollisionTree(Nodes, 0, CurID, tree); + + // Quantize + { + mNodes = new AABBQuantizedNode[mNbNodes]; + CHECKALLOC(mNodes); + + // Get max values + FIND_MAX_VALUES + + // Quantization + INIT_QUANTIZATION + + // Quantize + udword Data; + for(udword i=0;iIsLeaf()) + { + _Walk(current_node->GetPos(), callback, user_data); + _Walk(current_node->GetNeg(), callback, user_data); + } + } + }; + Local::_Walk(mNodes, callback, user_data); + return true; +} + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBQuantizedNoLeafTree::AABBQuantizedNoLeafTree() : mNodes(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBQuantizedNoLeafTree::~AABBQuantizedNoLeafTree() +{ + DELETEARRAY(mNodes); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds the collision tree from a generic AABB tree. + * \param tree [in] generic AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBQuantizedNoLeafTree::Build(AABBTree* tree) +{ + // Checkings + if(!tree) return false; + // Check the input tree is complete + udword NbTriangles = tree->GetNbPrimitives(); + udword NbNodes = tree->GetNbNodes(); + if(NbNodes!=NbTriangles*2-1) return false; + + // Get nodes + mNbNodes = NbTriangles-1; + DELETEARRAY(mNodes); + AABBNoLeafNode* Nodes = new AABBNoLeafNode[mNbNodes]; + CHECKALLOC(Nodes); + + // Build the tree + udword CurID = 1; + _BuildNoLeafTree(Nodes, 0, CurID, tree); + ASSERT(CurID==mNbNodes); + + // Quantize + { + mNodes = new AABBQuantizedNoLeafNode[mNbNodes]; + CHECKALLOC(mNodes); + + // Get max values + FIND_MAX_VALUES + + // Quantization + INIT_QUANTIZATION + + // Quantize + udword Data; + for(udword i=0;iHasPosLeaf()) _Walk(current_node->GetPos(), callback, user_data); + if(!current_node->HasNegLeaf()) _Walk(current_node->GetNeg(), callback, user_data); + } + }; + Local::_Walk(mNodes, callback, user_data); + return true; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_OptimizedTree.h b/Extras/CDTestFramework/Opcode/OPC_OptimizedTree.h new file mode 100644 index 0000000..e25db74 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_OptimizedTree.h @@ -0,0 +1,215 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for optimized trees. + * \file OPC_OptimizedTree.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_OPTIMIZEDTREE_H__ +#define __OPC_OPTIMIZEDTREE_H__ + + //! Common interface for a node of an implicit tree + #define IMPLEMENT_IMPLICIT_NODE(base_class, volume) \ + public: \ + /* Constructor / Destructor */ \ + inline_ base_class() : mData(0) {} \ + inline_ ~base_class() {} \ + /* Leaf test */ \ + inline_ BOOL IsLeaf() const { return mData&1; } \ + /* Data access */ \ + inline_ const base_class* GetPos() const { return (base_class*)mData; } \ + inline_ const base_class* GetNeg() const { return ((base_class*)mData)+1; } \ + inline_ udword GetPrimitive() const { return (mData>>1); } \ + /* Stats */ \ + inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ + \ + volume mAABB; \ + udword mData; + + //! Common interface for a node of a no-leaf tree + #define IMPLEMENT_NOLEAF_NODE(base_class, volume) \ + public: \ + /* Constructor / Destructor */ \ + inline_ base_class() : mPosData(0), mNegData(0) {} \ + inline_ ~base_class() {} \ + /* Leaf tests */ \ + inline_ BOOL HasPosLeaf() const { return mPosData&1; } \ + inline_ BOOL HasNegLeaf() const { return mNegData&1; } \ + /* Data access */ \ + inline_ const base_class* GetPos() const { return (base_class*)mPosData; } \ + inline_ const base_class* GetNeg() const { return (base_class*)mNegData; } \ + inline_ udword GetPosPrimitive() const { return (mPosData>>1); } \ + inline_ udword GetNegPrimitive() const { return (mNegData>>1); } \ + /* Stats */ \ + inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ + \ + volume mAABB; \ + udword mPosData; \ + udword mNegData; + + class OPCODE_API AABBCollisionNode + { + IMPLEMENT_IMPLICIT_NODE(AABBCollisionNode, CollisionAABB) + + inline_ float GetVolume() const { return mAABB.mExtents.x * mAABB.mExtents.y * mAABB.mExtents.z; } + inline_ float GetSize() const { return mAABB.mExtents.SquareMagnitude(); } + inline_ udword GetRadius() const + { + udword* Bits = (udword*)&mAABB.mExtents.x; + udword Max = Bits[0]; + if(Bits[1]>Max) Max = Bits[1]; + if(Bits[2]>Max) Max = Bits[2]; + return Max; + } + + // NB: using the square-magnitude or the true volume of the box, seems to yield better results + // (assuming UNC-like informed traversal methods). I borrowed this idea from PQP. The usual "size" + // otherwise, is the largest box extent. In SOLID that extent is computed on-the-fly each time it's + // needed (the best approach IMHO). In RAPID the rotation matrix is permuted so that Extent[0] is + // always the greatest, which saves looking for it at runtime. On the other hand, it yields matrices + // whose determinant is not 1, i.e. you can't encode them anymore as unit quaternions. Not a very + // good strategy. + }; + + class OPCODE_API AABBQuantizedNode + { + IMPLEMENT_IMPLICIT_NODE(AABBQuantizedNode, QuantizedAABB) + + inline_ uword GetSize() const + { + const uword* Bits = mAABB.mExtents; + uword Max = Bits[0]; + if(Bits[1]>Max) Max = Bits[1]; + if(Bits[2]>Max) Max = Bits[2]; + return Max; + } + // NB: for quantized nodes I don't feel like computing a square-magnitude with integers all + // over the place.......! + }; + + class OPCODE_API AABBNoLeafNode + { + IMPLEMENT_NOLEAF_NODE(AABBNoLeafNode, CollisionAABB) + }; + + class OPCODE_API AABBQuantizedNoLeafNode + { + IMPLEMENT_NOLEAF_NODE(AABBQuantizedNoLeafNode, QuantizedAABB) + }; + + //! Common interface for a collision tree + #define IMPLEMENT_COLLISION_TREE(base_class, node) \ + public: \ + /* Constructor / Destructor */ \ + base_class(); \ + virtual ~base_class(); \ + /* Builds from a standard tree */ \ + override(AABBOptimizedTree) bool Build(AABBTree* tree); \ + /* Refits the tree */ \ + override(AABBOptimizedTree) bool Refit(const MeshInterface* mesh_interface); \ + /* Walks the tree */ \ + override(AABBOptimizedTree) bool Walk(GenericWalkingCallback callback, void* user_data) const; \ + /* Data access */ \ + inline_ const node* GetNodes() const { return mNodes; } \ + /* Stats */ \ + override(AABBOptimizedTree) udword GetUsedBytes() const { return mNbNodes*sizeof(node); } \ + private: \ + node* mNodes; + + typedef bool (*GenericWalkingCallback) (const void* current, void* user_data); + + class OPCODE_API AABBOptimizedTree + { + public: + // Constructor / Destructor + AABBOptimizedTree() : + mNbNodes (0) + {} + virtual ~AABBOptimizedTree() {} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Builds the collision tree from a generic AABB tree. + * \param tree [in] generic AABB tree + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual bool Build(AABBTree* tree) = 0; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Refits the collision tree after vertices have been modified. + * \param mesh_interface [in] mesh interface for current model + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual bool Refit(const MeshInterface* mesh_interface) = 0; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Walks the tree and call the user back for each node. + * \param callback [in] walking callback + * \param user_data [in] callback's user data + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual bool Walk(GenericWalkingCallback callback, void* user_data) const = 0; + + // Data access + virtual udword GetUsedBytes() const = 0; + inline_ udword GetNbNodes() const { return mNbNodes; } + + protected: + udword mNbNodes; + }; + + class OPCODE_API AABBCollisionTree : public AABBOptimizedTree + { + IMPLEMENT_COLLISION_TREE(AABBCollisionTree, AABBCollisionNode) + }; + + class OPCODE_API AABBNoLeafTree : public AABBOptimizedTree + { + IMPLEMENT_COLLISION_TREE(AABBNoLeafTree, AABBNoLeafNode) + }; + + class OPCODE_API AABBQuantizedTree : public AABBOptimizedTree + { + IMPLEMENT_COLLISION_TREE(AABBQuantizedTree, AABBQuantizedNode) + + public: + Point mCenterCoeff; + Point mExtentsCoeff; + }; + + class OPCODE_API AABBQuantizedNoLeafTree : public AABBOptimizedTree + { + IMPLEMENT_COLLISION_TREE(AABBQuantizedNoLeafTree, AABBQuantizedNoLeafNode) + + public: + Point mCenterCoeff; + Point mExtentsCoeff; + }; + +#endif // __OPC_OPTIMIZEDTREE_H__ diff --git a/Extras/CDTestFramework/Opcode/OPC_Picking.cpp b/Extras/CDTestFramework/Opcode/OPC_Picking.cpp new file mode 100644 index 0000000..02a9ed7 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_Picking.cpp @@ -0,0 +1,191 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code to perform "picking". + * \file OPC_Picking.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +#ifdef OPC_RAYHIT_CALLBACK + +/* + Possible RayCollider usages: + - boolean query (shadow feeler) + - closest hit + - all hits + - number of intersection (boolean) + +*/ + +bool Opcode::SetupAllHits(RayCollider& collider, CollisionFaces& contacts) +{ + struct Local + { + static void AllContacts(const CollisionFace& hit, void* user_data) + { + CollisionFaces* CF = (CollisionFaces*)user_data; + CF->AddFace(hit); + } + }; + + collider.SetFirstContact(false); + collider.SetHitCallback(Local::AllContacts); + collider.SetUserData(&contacts); + return true; +} + +bool Opcode::SetupClosestHit(RayCollider& collider, CollisionFace& closest_contact) +{ + struct Local + { + static void ClosestContact(const CollisionFace& hit, void* user_data) + { + CollisionFace* CF = (CollisionFace*)user_data; + if(hit.mDistancemDistance) *CF = hit; + } + }; + + collider.SetFirstContact(false); + collider.SetHitCallback(Local::ClosestContact); + collider.SetUserData(&closest_contact); + closest_contact.mDistance = MAX_FLOAT; + return true; +} + +bool Opcode::SetupShadowFeeler(RayCollider& collider) +{ + collider.SetFirstContact(true); + collider.SetHitCallback(null); + return true; +} + +bool Opcode::SetupInOutTest(RayCollider& collider) +{ + collider.SetFirstContact(false); + collider.SetHitCallback(null); + // Results with collider.GetNbIntersections() + return true; +} + +bool Opcode::Picking( +CollisionFace& picked_face, +const Ray& world_ray, const Model& model, const Matrix4x4* world, +float min_dist, float max_dist, const Point& view_point, CullModeCallback callback, void* user_data) +{ + struct Local + { + struct CullData + { + CollisionFace* Closest; + float MinLimit; + CullModeCallback Callback; + void* UserData; + Point ViewPoint; + const MeshInterface* IMesh; + }; + + // Called for each stabbed face + static void RenderCullingCallback(const CollisionFace& hit, void* user_data) + { + CullData* Data = (CullData*)user_data; + + // Discard face if we already have a closer hit + if(hit.mDistance>=Data->Closest->mDistance) return; + + // Discard face if hit point is smaller than min limit. This mainly happens when the face is in front + // of the near clip plane (or straddles it). If we keep the face nonetheless, the user can select an + // object that he may not even be able to see, which is very annoying. + if(hit.mDistance<=Data->MinLimit) return; + + // This is the index of currently stabbed triangle. + udword StabbedFaceIndex = hit.mFaceID; + + // We may keep it or not, depending on backface culling + bool KeepIt = true; + + // Catch *render* cull mode for this face + CullMode CM = (Data->Callback)(StabbedFaceIndex, Data->UserData); + + if(CM!=CULLMODE_NONE) // Don't even compute culling for double-sided triangles + { + // Compute backface culling for current face + + VertexPointers VP; + Data->IMesh->GetTriangle(VP, StabbedFaceIndex); + if(VP.BackfaceCulling(Data->ViewPoint)) + { + if(CM==CULLMODE_CW) KeepIt = false; + } + else + { + if(CM==CULLMODE_CCW) KeepIt = false; + } + } + + if(KeepIt) *Data->Closest = hit; + } + }; + + RayCollider RC; + RC.SetMaxDist(max_dist); + RC.SetTemporalCoherence(false); + RC.SetCulling(false); // We need all faces since some of them can be double-sided + RC.SetFirstContact(false); + RC.SetHitCallback(Local::RenderCullingCallback); + + picked_face.mFaceID = INVALID_ID; + picked_face.mDistance = MAX_FLOAT; + picked_face.mU = 0.0f; + picked_face.mV = 0.0f; + + Local::CullData Data; + Data.Closest = &picked_face; + Data.MinLimit = min_dist; + Data.Callback = callback; + Data.UserData = user_data; + Data.ViewPoint = view_point; + Data.IMesh = model.GetMeshInterface(); + + if(world) + { + // Get matrices + Matrix4x4 InvWorld; + InvertPRMatrix(InvWorld, *world); + + // Compute camera position in mesh space + Data.ViewPoint *= InvWorld; + } + + RC.SetUserData(&Data); + if(RC.Collide(world_ray, model, world)) + { + return picked_face.mFaceID!=INVALID_ID; + } + return false; +} + +#endif diff --git a/Extras/CDTestFramework/Opcode/OPC_Picking.h b/Extras/CDTestFramework/Opcode/OPC_Picking.h new file mode 100644 index 0000000..5c69f5d --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_Picking.h @@ -0,0 +1,54 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code to perform "picking". + * \file OPC_Picking.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_PICKING_H__ +#define __OPC_PICKING_H__ + +#ifdef OPC_RAYHIT_CALLBACK + + enum CullMode + { + CULLMODE_NONE = 0, + CULLMODE_CW = 1, + CULLMODE_CCW = 2 + }; + + typedef CullMode (*CullModeCallback)(udword triangle_index, void* user_data); + + OPCODE_API bool SetupAllHits (RayCollider& collider, CollisionFaces& contacts); + OPCODE_API bool SetupClosestHit (RayCollider& collider, CollisionFace& closest_contact); + OPCODE_API bool SetupShadowFeeler (RayCollider& collider); + OPCODE_API bool SetupInOutTest (RayCollider& collider); + + OPCODE_API bool Picking( + CollisionFace& picked_face, + const Ray& world_ray, const Model& model, const Matrix4x4* world, + float min_dist, float max_dist, const Point& view_point, CullModeCallback callback, void* user_data); +#endif + +#endif //__OPC_PICKING_H__ \ No newline at end of file diff --git a/Extras/CDTestFramework/Opcode/OPC_PlanesAABBOverlap.h b/Extras/CDTestFramework/Opcode/OPC_PlanesAABBOverlap.h new file mode 100644 index 0000000..21ab91c --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_PlanesAABBOverlap.h @@ -0,0 +1,67 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Planes-AABB overlap test. + * - original code by Ville Miettinen, from Umbra/dPVS (released on the GD-Algorithms mailing list) + * - almost used "as-is", I even left the comments (hence the frustum-related notes) + * + * \param center [in] box center + * \param extents [in] box extents + * \param out_clip_mask [out] bitmask for active planes + * \param in_clip_mask [in] bitmask for active planes + * \return TRUE if boxes overlap planes + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL PlanesCollider::PlanesAABBOverlap(const Point& center, const Point& extents, udword& out_clip_mask, udword in_clip_mask) +{ + // Stats + mNbVolumeBVTests++; + + const Plane* p = mPlanes; + + // Evaluate through all active frustum planes. We determine the relation + // between the AABB and a plane by using the concept of "near" and "far" + // vertices originally described by Zhang (and later by Möller). Our + // variant here uses 3 fabs ops, 6 muls, 7 adds and two floating point + // comparisons per plane. The routine early-exits if the AABB is found + // to be outside any of the planes. The loop also constructs a new output + // clip mask. Most FPUs have a native single-cycle fabsf() operation. + + udword Mask = 1; // current mask index (1,2,4,8,..) + udword TmpOutClipMask = 0; // initialize output clip mask into empty. + + while(Mask<=in_clip_mask) // keep looping while we have active planes left... + { + if(in_clip_mask & Mask) // if clip plane is active, process it.. + { + float NP = extents.x*fabsf(p->n.x) + extents.y*fabsf(p->n.y) + extents.z*fabsf(p->n.z); // ### fabsf could be precomputed + float MP = center.x*p->n.x + center.y*p->n.y + center.z*p->n.z + p->d; + + if(NP < MP) // near vertex behind the clip plane... + return FALSE; // .. so there is no intersection.. + if((-NP) < MP) // near and far vertices on different sides of plane.. + TmpOutClipMask |= Mask; // .. so update the clip mask... + } + Mask+=Mask; // mk = (1<Add(prim_index); + +//! Planes-triangle test +#define PLANES_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + mIMesh->GetTriangle(mVP, prim_index); \ + /* Perform triangle-box overlap test */ \ + if(PlanesTriOverlap(clip_mask)) \ + { \ + SET_CONTACT(prim_index, flag) \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +PlanesCollider::PlanesCollider() : + mPlanes (null), + mNbPlanes (0) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +PlanesCollider::~PlanesCollider() +{ + DELETEARRAY(mPlanes); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Validates current settings. You should call this method after all the settings and callbacks have been defined. + * \return null if everything is ok, else a string describing the problem + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const char* PlanesCollider::ValidateSettings() +{ + if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!"; + + return VolumeCollider::ValidateSettings(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a planes cache + * \param planes [in] list of planes in world space + * \param nb_planes [in] number of planes + * \param model [in] Opcode model to collide with + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool PlanesCollider::Collide(PlanesCache& cache, const Plane* planes, udword nb_planes, const Model& model, const Matrix4x4* worldm) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, planes, nb_planes, worldm)) return true; + + udword PlaneMask = (1<mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + else _Collide(Tree->GetNodes(), PlaneMask); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + else _Collide(Tree->GetNodes(), PlaneMask); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + else _Collide(Tree->GetNodes(), PlaneMask); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + else _Collide(Tree->GetNodes(), PlaneMask); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - compute planes in model space + * - check temporal coherence + * + * \param cache [in/out] a planes cache + * \param planes [in] list of planes + * \param nb_planes [in] number of planes + * \param worldm [in] model's world matrix, or null + * \return TRUE if we can return immediately + * \warning SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL PlanesCollider::InitQuery(PlanesCache& cache, const Plane* planes, udword nb_planes, const Matrix4x4* worldm) +{ + // 1) Call the base method + VolumeCollider::InitQuery(); + + // 2) Compute planes in model space + if(nb_planes>mNbPlanes) + { + DELETEARRAY(mPlanes); + mPlanes = new Plane[nb_planes]; + } + mNbPlanes = nb_planes; + + if(worldm) + { + Matrix4x4 InvWorldM; + InvertPRMatrix(InvWorldM, *worldm); + +// for(udword i=0;iHasSingleNode()) + { + if(!SkipPrimitiveTests()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + mTouchedPrimitives->Reset(); + + // Perform overlap test between the unique triangle and the planes (and set contact status if needed) + udword clip_mask = (1< check results from previous frame before performing the collision query + if(FirstContactEnabled()) + { + // We're only interested in the first contact found => test the unique previously touched face + if(mTouchedPrimitives->GetNbEntries()) + { + // Get index of previously touched face = the first entry in the array + udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); + + // Then reset the array: + // - if the overlap test below is successful, the index we'll get added back anyway + // - if it isn't, then the array should be reset anyway for the normal query + mTouchedPrimitives->Reset(); + + // Perform overlap test between the cached triangle and the planes (and set contact status if needed) + udword clip_mask = (1< we'll have to perform a normal query + } + else mTouchedPrimitives->Reset(); + } + else + { + // Here we don't use temporal coherence => do a normal query + mTouchedPrimitives->Reset(); + } + + return FALSE; +} + +#define TEST_CLIP_MASK \ + /* If the box is completely included, so are its children. We don't need to do extra tests, we */ \ + /* can immediately output a list of visible children. Those ones won't need to be clipped. */ \ + if(!OutClipMask) \ + { \ + /* Set contact status */ \ + mFlags |= OPC_CONTACT; \ + _Dump(node); \ + return; \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_Collide(const AABBCollisionNode* node, udword clip_mask) +{ + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->IsLeaf()) + { + PLANES_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + _Collide(node->GetNeg(), OutClipMask); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node, udword clip_mask) +{ + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_Collide(const AABBQuantizedNode* node, udword clip_mask) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->IsLeaf()) + { + PLANES_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + _Collide(node->GetNeg(), OutClipMask); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node, udword clip_mask) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_Collide(const AABBNoLeafNode* node, udword clip_mask) +{ + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->HasPosLeaf()) { PLANES_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { PLANES_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg(), OutClipMask); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node, udword clip_mask) +{ + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_Collide(const AABBQuantizedNoLeafNode* node, udword clip_mask) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->HasPosLeaf()) { PLANES_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { PLANES_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg(), OutClipMask); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node, udword clip_mask) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); +} + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridPlanesCollider::HybridPlanesCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridPlanesCollider::~HybridPlanesCollider() +{ +} + +bool HybridPlanesCollider::Collide(PlanesCache& cache, const Plane* planes, udword nb_planes, const HybridModel& model, const Matrix4x4* worldm) +{ + // We don't want primitive tests here! + mFlags |= OPC_NO_PRIMITIVE_TESTS; + + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, planes, nb_planes, worldm)) return true; + + // Special case for 1-leaf trees + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles + udword Nb = mIMesh->GetNbTriangles(); + + // Loop through all triangles + udword clip_mask = (1<mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + } + } + + // We only have a list of boxes so far + if(GetContactStatus()) + { + // Reset contact status, since it currently only reflects collisions with leaf boxes + Collider::InitQuery(); + + // Change dest container so that we can use built-in overlap tests and get collided primitives + cache.TouchedPrimitives.Reset(); + mTouchedPrimitives = &cache.TouchedPrimitives; + + // Read touched leaf boxes + udword Nb = mTouchedBoxes.GetNbEntries(); + const udword* Touched = mTouchedBoxes.GetEntries(); + + const LeafTriangles* LT = model.GetLeafTriangles(); + const udword* Indices = model.GetIndices(); + + // Loop through touched leaves + udword clip_mask = (1<Distance(*mVP.Vertex[0]); + float d1 = p->Distance(*mVP.Vertex[1]); + float d2 = p->Distance(*mVP.Vertex[2]); + if(d0>0.0f && d1>0.0f && d2>0.0f) return FALSE; +// if(!(IR(d0)&SIGN_BITMASK) && !(IR(d1)&SIGN_BITMASK) && !(IR(d2)&SIGN_BITMASK)) return FALSE; + } + Mask+=Mask; + p++; + } +/* + for(udword i=0;i<6;i++) + { + float d0 = p[i].Distance(mLeafVerts[0]); + float d1 = p[i].Distance(mLeafVerts[1]); + float d2 = p[i].Distance(mLeafVerts[2]); + if(d0>0.0f && d1>0.0f && d2>0.0f) return false; + } +*/ + return TRUE; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_RayAABBOverlap.h b/Extras/CDTestFramework/Opcode/OPC_RayAABBOverlap.h new file mode 100644 index 0000000..0d2639c --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_RayAABBOverlap.h @@ -0,0 +1,81 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + + +// Opcode 1.1: ray-AABB overlap tests based on Woo's code +// Opcode 1.2: ray-AABB overlap tests based on the separating axis theorem +// +// The point of intersection is not computed anymore. The distance to impact is not needed anymore +// since we now have two different queries for segments or rays. + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a segment-AABB overlap test using the separating axis theorem. Segment is cached within the class. + * \param center [in] AABB center + * \param extents [in] AABB extents + * \return true on overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL RayCollider::SegmentAABBOverlap(const Point& center, const Point& extents) +{ + // Stats + mNbRayBVTests++; + + float Dx = mData2.x - center.x; if(fabsf(Dx) > extents.x + mFDir.x) return FALSE; + float Dy = mData2.y - center.y; if(fabsf(Dy) > extents.y + mFDir.y) return FALSE; + float Dz = mData2.z - center.z; if(fabsf(Dz) > extents.z + mFDir.z) return FALSE; + + float f; + f = mData.y * Dz - mData.z * Dy; if(fabsf(f) > extents.y*mFDir.z + extents.z*mFDir.y) return FALSE; + f = mData.z * Dx - mData.x * Dz; if(fabsf(f) > extents.x*mFDir.z + extents.z*mFDir.x) return FALSE; + f = mData.x * Dy - mData.y * Dx; if(fabsf(f) > extents.x*mFDir.y + extents.y*mFDir.x) return FALSE; + + return TRUE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a ray-AABB overlap test using the separating axis theorem. Ray is cached within the class. + * \param center [in] AABB center + * \param extents [in] AABB extents + * \return true on overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL RayCollider::RayAABBOverlap(const Point& center, const Point& extents) +{ + // Stats + mNbRayBVTests++; + +// float Dx = mOrigin.x - center.x; if(fabsf(Dx) > extents.x && Dx*mDir.x>=0.0f) return FALSE; +// float Dy = mOrigin.y - center.y; if(fabsf(Dy) > extents.y && Dy*mDir.y>=0.0f) return FALSE; +// float Dz = mOrigin.z - center.z; if(fabsf(Dz) > extents.z && Dz*mDir.z>=0.0f) return FALSE; + + float Dx = mOrigin.x - center.x; if(GREATER(Dx, extents.x) && Dx*mDir.x>=0.0f) return FALSE; + float Dy = mOrigin.y - center.y; if(GREATER(Dy, extents.y) && Dy*mDir.y>=0.0f) return FALSE; + float Dz = mOrigin.z - center.z; if(GREATER(Dz, extents.z) && Dz*mDir.z>=0.0f) return FALSE; + +// float Dx = mOrigin.x - center.x; if(GREATER(Dx, extents.x) && ((SIR(Dx)-1)^SIR(mDir.x))>=0.0f) return FALSE; +// float Dy = mOrigin.y - center.y; if(GREATER(Dy, extents.y) && ((SIR(Dy)-1)^SIR(mDir.y))>=0.0f) return FALSE; +// float Dz = mOrigin.z - center.z; if(GREATER(Dz, extents.z) && ((SIR(Dz)-1)^SIR(mDir.z))>=0.0f) return FALSE; + + float f; + f = mDir.y * Dz - mDir.z * Dy; if(fabsf(f) > extents.y*mFDir.z + extents.z*mFDir.y) return FALSE; + f = mDir.z * Dx - mDir.x * Dz; if(fabsf(f) > extents.x*mFDir.z + extents.z*mFDir.x) return FALSE; + f = mDir.x * Dy - mDir.y * Dx; if(fabsf(f) > extents.x*mFDir.y + extents.y*mFDir.x) return FALSE; + + return TRUE; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_RayCollider.cpp b/Extras/CDTestFramework/Opcode/OPC_RayCollider.cpp new file mode 100644 index 0000000..07ceb32 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_RayCollider.cpp @@ -0,0 +1,771 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a ray collider. + * \file OPC_RayCollider.cpp + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a ray-vs-tree collider. + * This class performs a stabbing query on an AABB tree, i.e. does a ray-mesh collision. + * + * HIGHER DISTANCE BOUND: + * + * If P0 and P1 are two 3D points, let's define: + * - d = distance between P0 and P1 + * - Origin = P0 + * - Direction = (P1 - P0) / d = normalized direction vector + * - A parameter t such as a point P on the line (P0,P1) is P = Origin + t * Direction + * - t = 0 --> P = P0 + * - t = d --> P = P1 + * + * Then we can define a general "ray" as: + * + * struct Ray + * { + * Point Origin; + * Point Direction; + * }; + * + * But it actually maps three different things: + * - a segment, when 0 <= t <= d + * - a half-line, when 0 <= t < +infinity, or -infinity < t <= d + * - a line, when -infinity < t < +infinity + * + * In Opcode, we support segment queries, which yield half-line queries by setting d = +infinity. + * We don't support line-queries. If you need them, shift the origin along the ray by an appropriate margin. + * + * In short, the lower bound is always 0, and you can setup the higher bound "d" with RayCollider::SetMaxDist(). + * + * Query |segment |half-line |line + * --------|-------------------|---------------|---------------- + * Usages |-shadow feelers |-raytracing |- + * |-sweep tests |-in/out tests | + * + * FIRST CONTACT: + * + * - You can setup "first contact" mode or "all contacts" mode with RayCollider::SetFirstContact(). + * - In "first contact" mode we return as soon as the ray hits one face. If can be useful e.g. for shadow feelers, where + * you want to know whether the path to the light is free or not (a boolean answer is enough). + * - In "all contacts" mode we return all faces hit by the ray. + * + * TEMPORAL COHERENCE: + * + * - You can enable or disable temporal coherence with RayCollider::SetTemporalCoherence(). + * - It currently only works in "first contact" mode. + * - If temporal coherence is enabled, the previously hit triangle is cached during the first query. Then, next queries + * start by colliding the ray against the cached triangle. If they still collide, we return immediately. + * + * CLOSEST HIT: + * + * - You can enable or disable "closest hit" with RayCollider::SetClosestHit(). + * - It currently only works in "all contacts" mode. + * - If closest hit is enabled, faces are sorted by distance on-the-fly and the closest one only is reported. + * + * BACKFACE CULLING: + * + * - You can enable or disable backface culling with RayCollider::SetCulling(). + * - If culling is enabled, ray will not hit back faces (only front faces). + * + * + * + * \class RayCollider + * \author Pierre Terdiman + * \version 1.3 + * \date June, 2, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * This class describes a face hit by a ray or segment. + * This is a particular class dedicated to stabbing queries. + * + * \class CollisionFace + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * This class is a dedicated collection of CollisionFace. + * + * \class CollisionFaces + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +#include "OPC_RayAABBOverlap.h" +#include "OPC_RayTriOverlap.h" + +#define SET_CONTACT(prim_index, flag) \ + mNbIntersections++; \ + /* Set contact status */ \ + mFlags |= flag; \ + /* In any case the contact has been found and recorded in mStabbedFace */ \ + mStabbedFace.mFaceID = prim_index; + +#ifdef OPC_RAYHIT_CALLBACK + + #define HANDLE_CONTACT(prim_index, flag) \ + SET_CONTACT(prim_index, flag) \ + \ + if(mHitCallback) (mHitCallback)(mStabbedFace, mUserData); + + #define UPDATE_CACHE \ + if(cache && GetContactStatus()) \ + { \ + *cache = mStabbedFace.mFaceID; \ + } +#else + + #define HANDLE_CONTACT(prim_index, flag) \ + SET_CONTACT(prim_index, flag) \ + \ + /* Now we can also record it in mStabbedFaces if available */ \ + if(mStabbedFaces) \ + { \ + /* If we want all faces or if that's the first one we hit */ \ + if(!mClosestHit || !mStabbedFaces->GetNbFaces()) \ + { \ + mStabbedFaces->AddFace(mStabbedFace); \ + } \ + else \ + { \ + /* We only keep closest hit */ \ + CollisionFace* Current = const_cast(mStabbedFaces->GetFaces()); \ + if(Current && mStabbedFace.mDistancemDistance) \ + { \ + *Current = mStabbedFace; \ + } \ + } \ + } + + #define UPDATE_CACHE \ + if(cache && GetContactStatus() && mStabbedFaces) \ + { \ + const CollisionFace* Current = mStabbedFaces->GetFaces(); \ + if(Current) *cache = Current->mFaceID; \ + else *cache = INVALID_ID; \ + } +#endif + +#define SEGMENT_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \ + \ + /* Perform ray-tri overlap test and return */ \ + if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ + { \ + /* Intersection point is valid if dist < segment's length */ \ + /* We know dist>0 so we can use integers */ \ + if(IR(mStabbedFace.mDistance)GetTriangle(VP, prim_index); \ + \ + /* Perform ray-tri overlap test and return */ \ + if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ + { \ + HANDLE_CONTACT(prim_index, flag) \ + } + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +RayCollider::RayCollider() : + mNbRayBVTests (0), + mNbRayPrimTests (0), + mNbIntersections (0), + mCulling (true), +#ifdef OPC_RAYHIT_CALLBACK + mHitCallback (null), + mUserData (0), +#else + mClosestHit (false), + mStabbedFaces (null), +#endif + mMaxDist (MAX_FLOAT) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +RayCollider::~RayCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Validates current settings. You should call this method after all the settings and callbacks have been defined. + * \return null if everything is ok, else a string describing the problem + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const char* RayCollider::ValidateSettings() +{ + if(mMaxDist<0.0f) return "Higher distance bound must be positive!"; + if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!"; +#ifndef OPC_RAYHIT_CALLBACK + if(mClosestHit && FirstContactEnabled()) return "Closest hit doesn't work with ""First contact"" mode!"; + if(TemporalCoherenceEnabled() && mClosestHit) return "Temporal coherence can't guarantee to report closest hit!"; +#endif + if(SkipPrimitiveTests()) return "SkipPrimitiveTests not possible for RayCollider ! (not implemented)"; + return null; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic stabbing query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - in the user-provided destination array + * + * \param world_ray [in] stabbing ray in world space + * \param model [in] Opcode model to collide with + * \param world [in] model's world matrix, or null + * \param cache [in] a possibly cached face index, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool RayCollider::Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world, udword* cache) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(world_ray, world, cache)) return true; + + if(!model.HasLeafNodes()) + { + if(model.IsQuantized()) + { + const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform stabbing query + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); + else _RayStab(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform stabbing query + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); + else _RayStab(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform stabbing query + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); + else _RayStab(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform stabbing query + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); + else _RayStab(Tree->GetNodes()); + } + } + + // Update cache if needed + UPDATE_CACHE + return true; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a stabbing query : + * - reset stats & contact status + * - compute ray in local space + * - check temporal coherence + * + * \param world_ray [in] stabbing ray in world space + * \param world [in] object's world matrix, or null + * \param face_id [in] index of previously stabbed triangle + * \return TRUE if we can return immediately + * \warning SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL RayCollider::InitQuery(const Ray& world_ray, const Matrix4x4* world, udword* face_id) +{ + // Reset stats & contact status + Collider::InitQuery(); + mNbRayBVTests = 0; + mNbRayPrimTests = 0; + mNbIntersections = 0; +#ifndef OPC_RAYHIT_CALLBACK + if(mStabbedFaces) mStabbedFaces->Reset(); +#endif + + // Compute ray in local space + // The (Origin/Dir) form is needed for the ray-triangle test anyway (even for segment tests) + if(world) + { + Matrix3x3 InvWorld = *world; + mDir = InvWorld * world_ray.mDir; + + Matrix4x4 World; + InvertPRMatrix(World, *world); + mOrigin = world_ray.mOrig * World; + } + else + { + mDir = world_ray.mDir; + mOrigin = world_ray.mOrig; + } + + // 4) Special case: 1-triangle meshes [Opcode 1.3] + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + if(!SkipPrimitiveTests()) + { + // Perform overlap test between the unique triangle and the ray (and set contact status if needed) + SEGMENT_PRIM(udword(0), OPC_CONTACT) + + // Return immediately regardless of status + return TRUE; + } + } + + // Check temporal coherence : + + // Test previously colliding primitives first + if(TemporalCoherenceEnabled() && FirstContactEnabled() && face_id && *face_id!=INVALID_ID) + { +#ifdef OLD_CODE +#ifndef OPC_RAYHIT_CALLBACK + if(!mClosestHit) +#endif + { + // Request vertices from the app + VertexPointers VP; + mIMesh->GetTriangle(VP, *face_id); + // Perform ray-cached tri overlap test + if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) + { + // Intersection point is valid if: + // - distance is positive (else it can just be a face behind the orig point) + // - distance is smaller than a given max distance (useful for shadow feelers) +// if(mStabbedFace.mDistance>0.0f && mStabbedFace.mDistanceAddFace(mStabbedFace); +#endif + return TRUE; + } + } + } +#else + // New code + // We handle both Segment/ray queries with the same segment code, and a possible infinite limit + SEGMENT_PRIM(*face_id, OPC_TEMPORAL_CONTACT) + + // Return immediately if possible + if(GetContactStatus()) return TRUE; +#endif + } + + // Precompute data (moved after temporal coherence since only needed for ray-AABB) + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) + { + // For Segment-AABB overlap + mData = 0.5f * mDir * mMaxDist; + mData2 = mOrigin + mData; + + // Precompute mFDir; + mFDir.x = fabsf(mData.x); + mFDir.y = fabsf(mData.y); + mFDir.z = fabsf(mData.z); + } + else + { + // For Ray-AABB overlap +// udword x = SIR(mDir.x)-1; +// udword y = SIR(mDir.y)-1; +// udword z = SIR(mDir.z)-1; +// mData.x = FR(x); +// mData.y = FR(y); +// mData.z = FR(z); + + // Precompute mFDir; + mFDir.x = fabsf(mDir.x); + mFDir.y = fabsf(mDir.y); + mFDir.z = fabsf(mDir.z); + } + + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Stabbing query for vanilla AABB trees. + * \param world_ray [in] stabbing ray in world space + * \param tree [in] AABB tree + * \param box_indices [out] indices of stabbed boxes + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool RayCollider::Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices) +{ + // ### bad design here + + // This is typically called for a scene tree, full of -AABBs-, not full of triangles. + // So we don't really have "primitives" to deal with. Hence it doesn't work with + // "FirstContact" + "TemporalCoherence". + ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); + + // Checkings + if(!tree) return false; + + // Init collision query + // Basically this is only called to initialize precomputed data + if(InitQuery(world_ray)) return true; + + // Perform stabbing query + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(tree, box_indices); + else _RayStab(tree, box_indices); + + return true; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_SegmentStab(const AABBCollisionNode* node) +{ + // Perform Segment-AABB overlap test + if(!SegmentAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + if(node->IsLeaf()) + { + SEGMENT_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _SegmentStab(node->GetPos()); + + if(ContactFound()) return; + + _SegmentStab(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_SegmentStab(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Segment-AABB overlap test + if(!SegmentAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf()) + { + SEGMENT_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _SegmentStab(node->GetPos()); + + if(ContactFound()) return; + + _SegmentStab(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_SegmentStab(const AABBNoLeafNode* node) +{ + // Perform Segment-AABB overlap test + if(!SegmentAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + if(node->HasPosLeaf()) + { + SEGMENT_PRIM(node->GetPosPrimitive(), OPC_CONTACT) + } + else _SegmentStab(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) + { + SEGMENT_PRIM(node->GetNegPrimitive(), OPC_CONTACT) + } + else _SegmentStab(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_SegmentStab(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Segment-AABB overlap test + if(!SegmentAABBOverlap(Center, Extents)) return; + + if(node->HasPosLeaf()) + { + SEGMENT_PRIM(node->GetPosPrimitive(), OPC_CONTACT) + } + else _SegmentStab(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) + { + SEGMENT_PRIM(node->GetNegPrimitive(), OPC_CONTACT) + } + else _SegmentStab(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for vanilla AABB trees. + * \param node [in] current collision node + * \param box_indices [out] indices of stabbed boxes + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_SegmentStab(const AABBTreeNode* node, Container& box_indices) +{ + // Test the box against the segment + Point Center, Extents; + node->GetAABB()->GetCenter(Center); + node->GetAABB()->GetExtents(Extents); + if(!SegmentAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf()) + { + box_indices.Add(node->GetPrimitives(), node->GetNbPrimitives()); + } + else + { + _SegmentStab(node->GetPos(), box_indices); + _SegmentStab(node->GetNeg(), box_indices); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_RayStab(const AABBCollisionNode* node) +{ + // Perform Ray-AABB overlap test + if(!RayAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + if(node->IsLeaf()) + { + RAY_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _RayStab(node->GetPos()); + + if(ContactFound()) return; + + _RayStab(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_RayStab(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Ray-AABB overlap test + if(!RayAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf()) + { + RAY_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _RayStab(node->GetPos()); + + if(ContactFound()) return; + + _RayStab(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_RayStab(const AABBNoLeafNode* node) +{ + // Perform Ray-AABB overlap test + if(!RayAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + if(node->HasPosLeaf()) + { + RAY_PRIM(node->GetPosPrimitive(), OPC_CONTACT) + } + else _RayStab(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) + { + RAY_PRIM(node->GetNegPrimitive(), OPC_CONTACT) + } + else _RayStab(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_RayStab(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Ray-AABB overlap test + if(!RayAABBOverlap(Center, Extents)) return; + + if(node->HasPosLeaf()) + { + RAY_PRIM(node->GetPosPrimitive(), OPC_CONTACT) + } + else _RayStab(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) + { + RAY_PRIM(node->GetNegPrimitive(), OPC_CONTACT) + } + else _RayStab(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for vanilla AABB trees. + * \param node [in] current collision node + * \param box_indices [out] indices of stabbed boxes + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_RayStab(const AABBTreeNode* node, Container& box_indices) +{ + // Test the box against the ray + Point Center, Extents; + node->GetAABB()->GetCenter(Center); + node->GetAABB()->GetExtents(Extents); + if(!RayAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf()) + { + mFlags |= OPC_CONTACT; + box_indices.Add(node->GetPrimitives(), node->GetNbPrimitives()); + } + else + { + _RayStab(node->GetPos(), box_indices); + _RayStab(node->GetNeg(), box_indices); + } +} diff --git a/Extras/CDTestFramework/Opcode/OPC_RayCollider.h b/Extras/CDTestFramework/Opcode/OPC_RayCollider.h new file mode 100644 index 0000000..d347b18 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_RayCollider.h @@ -0,0 +1,234 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a ray collider. + * \file OPC_RayCollider.h + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_RAYCOLLIDER_H__ +#define __OPC_RAYCOLLIDER_H__ + + class OPCODE_API CollisionFace + { + public: + //! Constructor + inline_ CollisionFace() {} + //! Destructor + inline_ ~CollisionFace() {} + + udword mFaceID; //!< Index of touched face + float mDistance; //!< Distance from collider to hitpoint + float mU, mV; //!< Impact barycentric coordinates + }; + + class OPCODE_API CollisionFaces : private Container + { + public: + //! Constructor + CollisionFaces() {} + //! Destructor + ~CollisionFaces() {} + + inline_ udword GetNbFaces() const { return GetNbEntries()>>2; } + inline_ const CollisionFace* GetFaces() const { return (const CollisionFace*)GetEntries(); } + + inline_ void Reset() { Container::Reset(); } + + inline_ void AddFace(const CollisionFace& face) { Add(face.mFaceID).Add(face.mDistance).Add(face.mU).Add(face.mV); } + }; + +#ifdef OPC_RAYHIT_CALLBACK + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * User-callback, called by OPCODE to record a hit. + * \param hit [in] current hit + * \param user_data [in] user-defined data from SetCallback() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + typedef void (*HitCallback) (const CollisionFace& hit, void* user_data); +#endif + + class OPCODE_API RayCollider : public Collider + { + public: + // Constructor / Destructor + RayCollider(); + virtual ~RayCollider(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic stabbing query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - in the user-provided destination array + * + * \param world_ray [in] stabbing ray in world space + * \param model [in] Opcode model to collide with + * \param world [in] model's world matrix, or null + * \param cache [in] a possibly cached face index, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world=null, udword* cache=null); + // + bool Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices); + // Settings + +#ifndef OPC_RAYHIT_CALLBACK + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: enable or disable "closest hit" mode. + * \param flag [in] true to report closest hit only + * \see SetCulling(bool flag) + * \see SetMaxDist(float max_dist) + * \see SetDestination(StabbedFaces* sf) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetClosestHit(bool flag) { mClosestHit = flag; } +#endif + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: enable or disable backface culling. + * \param flag [in] true to enable backface culling + * \see SetClosestHit(bool flag) + * \see SetMaxDist(float max_dist) + * \see SetDestination(StabbedFaces* sf) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetCulling(bool flag) { mCulling = flag; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: sets the higher distance bound. + * \param max_dist [in] higher distance bound. Default = maximal value, for ray queries (else segment) + * \see SetClosestHit(bool flag) + * \see SetCulling(bool flag) + * \see SetDestination(StabbedFaces* sf) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetMaxDist(float max_dist=MAX_FLOAT) { mMaxDist = max_dist; } + +#ifdef OPC_RAYHIT_CALLBACK + inline_ void SetHitCallback(HitCallback cb) { mHitCallback = cb; } + inline_ void SetUserData(void* user_data) { mUserData = user_data; } +#else + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: sets the destination array for stabbed faces. + * \param cf [in] destination array, filled during queries + * \see SetClosestHit(bool flag) + * \see SetCulling(bool flag) + * \see SetMaxDist(float max_dist) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetDestination(CollisionFaces* cf) { mStabbedFaces = cf; } +#endif + // Stats + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of Ray-BV overlap tests after a collision query. + * \see GetNbRayPrimTests() + * \see GetNbIntersections() + * \return the number of Ray-BV tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbRayBVTests() const { return mNbRayBVTests; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of Ray-Triangle overlap tests after a collision query. + * \see GetNbRayBVTests() + * \see GetNbIntersections() + * \return the number of Ray-Triangle tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbRayPrimTests() const { return mNbRayPrimTests; } + + // In-out test + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of intersection found after a collision query. Can be used for in/out tests. + * \see GetNbRayBVTests() + * \see GetNbRayPrimTests() + * \return the number of valid intersections during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbIntersections() const { return mNbIntersections; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. + * \return null if everything is ok, else a string describing the problem + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(Collider) const char* ValidateSettings(); + + protected: + // Ray in local space + Point mOrigin; //!< Ray origin + Point mDir; //!< Ray direction (normalized) + Point mFDir; //!< fabsf(mDir) + Point mData, mData2; + // Stabbed faces + CollisionFace mStabbedFace; //!< Current stabbed face +#ifdef OPC_RAYHIT_CALLBACK + HitCallback mHitCallback; //!< Callback used to record a hit + void* mUserData; //!< User-defined data +#else + CollisionFaces* mStabbedFaces; //!< List of stabbed faces +#endif + // Stats + udword mNbRayBVTests; //!< Number of Ray-BV tests + udword mNbRayPrimTests; //!< Number of Ray-Primitive tests + // In-out test + udword mNbIntersections; //!< Number of valid intersections + // Dequantization coeffs + Point mCenterCoeff; + Point mExtentsCoeff; + // Settings + float mMaxDist; //!< Valid segment on the ray +#ifndef OPC_RAYHIT_CALLBACK + bool mClosestHit; //!< Report closest hit only +#endif + bool mCulling; //!< Stab culled faces or not + // Internal methods + void _SegmentStab(const AABBCollisionNode* node); + void _SegmentStab(const AABBNoLeafNode* node); + void _SegmentStab(const AABBQuantizedNode* node); + void _SegmentStab(const AABBQuantizedNoLeafNode* node); + void _SegmentStab(const AABBTreeNode* node, Container& box_indices); + void _RayStab(const AABBCollisionNode* node); + void _RayStab(const AABBNoLeafNode* node); + void _RayStab(const AABBQuantizedNode* node); + void _RayStab(const AABBQuantizedNoLeafNode* node); + void _RayStab(const AABBTreeNode* node, Container& box_indices); + // Overlap tests + inline_ BOOL RayAABBOverlap(const Point& center, const Point& extents); + inline_ BOOL SegmentAABBOverlap(const Point& center, const Point& extents); + inline_ BOOL RayTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2); + // Init methods + BOOL InitQuery(const Ray& world_ray, const Matrix4x4* world=null, udword* face_id=null); + }; + +#endif // __OPC_RAYCOLLIDER_H__ diff --git a/Extras/CDTestFramework/Opcode/OPC_RayTriOverlap.h b/Extras/CDTestFramework/Opcode/OPC_RayTriOverlap.h new file mode 100644 index 0000000..11f2121 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_RayTriOverlap.h @@ -0,0 +1,106 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +#define LOCAL_EPSILON 0.000001f + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a ray-triangle intersection test. + * Original code from Tomas Möller's "Fast Minimum Storage Ray-Triangle Intersection". + * It's been optimized a bit with integer code, and modified to return a non-intersection if distance from + * ray origin to triangle is negative. + * + * \param vert0 [in] triangle vertex + * \param vert1 [in] triangle vertex + * \param vert2 [in] triangle vertex + * \return true on overlap. mStabbedFace is filled with relevant info. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL RayCollider::RayTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2) +{ + // Stats + mNbRayPrimTests++; + + // Find vectors for two edges sharing vert0 + Point edge1 = vert1 - vert0; + Point edge2 = vert2 - vert0; + + // Begin calculating determinant - also used to calculate U parameter + Point pvec = mDir^edge2; + + // If determinant is near zero, ray lies in plane of triangle + float det = edge1|pvec; + + if(mCulling) + { + if(det 0. So we can use integer cmp. + + // Calculate distance from vert0 to ray origin + Point tvec = mOrigin - vert0; + + // Calculate U parameter and test bounds + mStabbedFace.mU = tvec|pvec; +// if(IR(u)&0x80000000 || u>det) return FALSE; + if(IS_NEGATIVE_FLOAT(mStabbedFace.mU) || IR(mStabbedFace.mU)>IR(det)) return FALSE; + + // Prepare to test V parameter + Point qvec = tvec^edge1; + + // Calculate V parameter and test bounds + mStabbedFace.mV = mDir|qvec; + if(IS_NEGATIVE_FLOAT(mStabbedFace.mV) || mStabbedFace.mU+mStabbedFace.mV>det) return FALSE; + + // Calculate t, scale parameters, ray intersects triangle + mStabbedFace.mDistance = edge2|qvec; + // Det > 0 so we can early exit here + // Intersection point is valid if distance is positive (else it can just be a face behind the orig point) + if(IS_NEGATIVE_FLOAT(mStabbedFace.mDistance)) return FALSE; + // Else go on + float OneOverDet = 1.0f / det; + mStabbedFace.mDistance *= OneOverDet; + mStabbedFace.mU *= OneOverDet; + mStabbedFace.mV *= OneOverDet; + } + else + { + // the non-culling branch + if(det>-LOCAL_EPSILON && det1.0f) return FALSE; + if(IS_NEGATIVE_FLOAT(mStabbedFace.mU) || IR(mStabbedFace.mU)>IEEE_1_0) return FALSE; + + // prepare to test V parameter + Point qvec = tvec^edge1; + + // Calculate V parameter and test bounds + mStabbedFace.mV = (mDir|qvec) * OneOverDet; + if(IS_NEGATIVE_FLOAT(mStabbedFace.mV) || mStabbedFace.mU+mStabbedFace.mV>1.0f) return FALSE; + + // Calculate t, ray intersects triangle + mStabbedFace.mDistance = (edge2|qvec) * OneOverDet; + // Intersection point is valid if distance is positive (else it can just be a face behind the orig point) + if(IS_NEGATIVE_FLOAT(mStabbedFace.mDistance)) return FALSE; + } + return TRUE; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_Settings.h b/Extras/CDTestFramework/Opcode/OPC_Settings.h new file mode 100644 index 0000000..1074a0d --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_Settings.h @@ -0,0 +1,58 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains compilation flags. + * \file OPC_Settings.h + * \author Pierre Terdiman + * \date May, 12, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_SETTINGS_H__ +#define __OPC_SETTINGS_H__ + + //! Use CPU comparisons (comment that line to use standard FPU compares) + #define OPC_CPU_COMPARE + + //! Use FCOMI / FCMOV on Pentium-Pro based processors (comment that line to use plain C++) + #define OPC_USE_FCOMI + + //! Use epsilon value in tri-tri overlap test + #define OPC_TRITRI_EPSILON_TEST + + //! Use tree-coherence or not [not implemented yet] +// #define OPC_USE_TREE_COHERENCE + + //! Use callbacks or direct pointers. Using callbacks might be a bit slower (but probably not much) +// #define OPC_USE_CALLBACKS + + //! Support triangle and vertex strides or not. Using strides might be a bit slower (but probably not much) +// #define OPC_USE_STRIDE + + //! Discard negative pointer in vanilla trees + #define OPC_NO_NEG_VANILLA_TREE + + //! Use a callback in the ray collider + #define OPC_RAYHIT_CALLBACK + + // NB: no compilation flag to enable/disable stats since they're actually needed in the box/box overlap test + +#endif //__OPC_SETTINGS_H__ \ No newline at end of file diff --git a/Extras/CDTestFramework/Opcode/OPC_SphereAABBOverlap.h b/Extras/CDTestFramework/Opcode/OPC_SphereAABBOverlap.h new file mode 100644 index 0000000..acc97ab --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_SphereAABBOverlap.h @@ -0,0 +1,145 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Sphere-AABB overlap test, based on Jim Arvo's code. + * \param center [in] box center + * \param extents [in] box extents + * \return TRUE on overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL SphereCollider::SphereAABBOverlap(const Point& center, const Point& extents) +{ + // Stats + mNbVolumeBVTests++; + + float d = 0.0f; + + //find the square of the distance + //from the sphere to the box +#ifdef OLDIES + for(udword i=0;i<3;i++) + { + float tmp = mCenter[i] - center[i]; + float s = tmp + extents[i]; + + if(s<0.0f) d += s*s; + else + { + s = tmp - extents[i]; + if(s>0.0f) d += s*s; + } + } +#endif + +//#ifdef NEW_TEST + +// float tmp = mCenter.x - center.x; +// float s = tmp + extents.x; + + float tmp,s; + + tmp = mCenter.x - center.x; + s = tmp + extents.x; + + if(s<0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + else + { + s = tmp - extents.x; + if(s>0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + } + + tmp = mCenter.y - center.y; + s = tmp + extents.y; + + if(s<0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + else + { + s = tmp - extents.y; + if(s>0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + } + + tmp = mCenter.z - center.z; + s = tmp + extents.z; + + if(s<0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + else + { + s = tmp - extents.z; + if(s>0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + } +//#endif + +#ifdef OLDIES +// Point Min = center - extents; +// Point Max = center + extents; + + float d = 0.0f; + + //find the square of the distance + //from the sphere to the box + for(udword i=0;i<3;i++) + { +float Min = center[i] - extents[i]; + +// if(mCenter[i]Max[i]) + if(mCenter[i]>Max) + { + float s = mCenter[i] - Max; + d += s*s; + } + } + } +#endif + return d <= mRadius2; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_SphereCollider.cpp b/Extras/CDTestFramework/Opcode/OPC_SphereCollider.cpp new file mode 100644 index 0000000..485bd00 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_SphereCollider.cpp @@ -0,0 +1,735 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a sphere collider. + * \file OPC_SphereCollider.cpp + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a sphere-vs-tree collider. + * This class performs a collision test between a sphere and an AABB tree. You can use this to do a standard player vs world collision, + * in a Nettle/Telemachos way. It doesn't suffer from all reported bugs in those two classic codes - the "new" one by Paul Nettle is a + * debuggued version I think. Collision response can be driven by reported collision data - it works extremely well for me. In sake of + * efficiency, all meshes (that is, all AABB trees) should of course also be kept in an extra hierarchical structure (octree, whatever). + * + * \class SphereCollider + * \author Pierre Terdiman + * \version 1.3 + * \date June, 2, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +#include "OPC_SphereAABBOverlap.h" +#include "OPC_SphereTriOverlap.h" + +#define SET_CONTACT(prim_index, flag) \ + /* Set contact status */ \ + mFlags |= flag; \ + mTouchedPrimitives->Add(prim_index); + +//! Sphere-triangle overlap test +#define SPHERE_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \ + \ + /* Perform sphere-tri overlap test */ \ + if(SphereTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ + { \ + SET_CONTACT(prim_index, flag) \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SphereCollider::SphereCollider() +{ + mCenter.Zero(); + mRadius2 = 0.0f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SphereCollider::~SphereCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a sphere cache + * \param sphere [in] collision sphere in local space + * \param model [in] Opcode model to collide with + * \param worlds [in] sphere's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool SphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const Model& model, const Matrix4x4* worlds, const Matrix4x4* worldm) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, sphere, worlds, worldm)) return true; + + if(!model.HasLeafNodes()) + { + if(model.IsQuantized()) + { + const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - setup matrices + * - check temporal coherence + * + * \param cache [in/out] a sphere cache + * \param sphere [in] sphere in local space + * \param worlds [in] sphere's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return TRUE if we can return immediately + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL SphereCollider::InitQuery(SphereCache& cache, const Sphere& sphere, const Matrix4x4* worlds, const Matrix4x4* worldm) +{ + // 1) Call the base method + VolumeCollider::InitQuery(); + + // 2) Compute sphere in model space: + // - Precompute R^2 + mRadius2 = sphere.mRadius * sphere.mRadius; + // - Compute center position + mCenter = sphere.mCenter; + // -> to world space + if(worlds) mCenter *= *worlds; + // -> to model space + if(worldm) + { + // Invert model matrix + Matrix4x4 InvWorldM; + InvertPRMatrix(InvWorldM, *worldm); + + mCenter *= InvWorldM; + } + + // 3) Setup destination pointer + mTouchedPrimitives = &cache.TouchedPrimitives; + + // 4) Special case: 1-triangle meshes [Opcode 1.3] + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + if(!SkipPrimitiveTests()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + mTouchedPrimitives->Reset(); + + // Perform overlap test between the unique triangle and the sphere (and set contact status if needed) + SPHERE_PRIM(udword(0), OPC_CONTACT) + + // Return immediately regardless of status + return TRUE; + } + } + + // 5) Check temporal coherence : + if(TemporalCoherenceEnabled()) + { + // Here we use temporal coherence + // => check results from previous frame before performing the collision query + if(FirstContactEnabled()) + { + // We're only interested in the first contact found => test the unique previously touched face + if(mTouchedPrimitives->GetNbEntries()) + { + // Get index of previously touched face = the first entry in the array + udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); + + // Then reset the array: + // - if the overlap test below is successful, the index we'll get added back anyway + // - if it isn't, then the array should be reset anyway for the normal query + mTouchedPrimitives->Reset(); + + // Perform overlap test between the cached triangle and the sphere (and set contact status if needed) + SPHERE_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) + + // Return immediately if possible + if(GetContactStatus()) return TRUE; + } + // else no face has been touched during previous query + // => we'll have to perform a normal query + } + else + { + // We're interested in all contacts =>test the new real sphere N(ew) against the previous fat sphere P(revious): + float r = sqrtf(cache.FatRadius2) - sphere.mRadius; + if(IsCacheValid(cache) && cache.Center.SquareDistance(mCenter) < r*r) + { + // - if N is included in P, return previous list + // => we simply leave the list (mTouchedFaces) unchanged + + // Set contact status if needed + if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; + + // In any case we don't need to do a query + return TRUE; + } + else + { + // - else do the query using a fat N + + // Reset cache since we'll about to perform a real query + mTouchedPrimitives->Reset(); + + // Make a fat sphere so that coherence will work for subsequent frames + mRadius2 *= cache.FatCoeff; +// mRadius2 = (sphere.mRadius * cache.FatCoeff)*(sphere.mRadius * cache.FatCoeff); + + // Update cache with query data (signature for cached faces) + cache.Center = mCenter; + cache.FatRadius2 = mRadius2; + } + } + } + else + { + // Here we don't use temporal coherence => do a normal query + mTouchedPrimitives->Reset(); + } + + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for vanilla AABB trees. + * \param cache [in/out] a sphere cache + * \param sphere [in] collision sphere in world space + * \param tree [in] AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool SphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const AABBTree* tree) +{ + // This is typically called for a scene tree, full of -AABBs-, not full of triangles. + // So we don't really have "primitives" to deal with. Hence it doesn't work with + // "FirstContact" + "TemporalCoherence". + ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); + + // Checkings + if(!tree) return false; + + // Init collision query + if(InitQuery(cache, sphere)) return true; + + // Perform collision query + _Collide(tree); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the sphere completely contains the box. In which case we can end the query sooner. + * \param bc [in] box center + * \param be [in] box extents + * \return true if the sphere contains the whole box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL SphereCollider::SphereContainsBox(const Point& bc, const Point& be) +{ + // I assume if all 8 box vertices are inside the sphere, so does the whole box. + // Sounds ok but maybe there's a better way? + Point p; + p.x=bc.x+be.x; p.y=bc.y+be.y; p.z=bc.z+be.z; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x+be.x; p.y=bc.y-be.y; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x+be.x; p.y=bc.y+be.y; p.z=bc.z-be.z; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x+be.x; p.y=bc.y-be.y; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + + return TRUE; +} + +#define TEST_BOX_IN_SPHERE(center, extents) \ + if(SphereContainsBox(center, extents)) \ + { \ + /* Set contact status */ \ + mFlags |= OPC_CONTACT; \ + _Dump(node); \ + return; \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_Collide(const AABBCollisionNode* node) +{ + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + SPHERE_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) +{ + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_Collide(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_SPHERE(Center, Extents) + + if(node->IsLeaf()) + { + SPHERE_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_SPHERE(Center, Extents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_Collide(const AABBNoLeafNode* node) +{ + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) +{ + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_Collide(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_SPHERE(Center, Extents) + + if(node->HasPosLeaf()) { SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_SPHERE(Center, Extents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for vanilla AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_Collide(const AABBTreeNode* node) +{ + // Perform Sphere-AABB overlap test + Point Center, Extents; + node->GetAABB()->GetCenter(Center); + node->GetAABB()->GetExtents(Extents); + if(!SphereAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf() || SphereContainsBox(Center, Extents)) + { + mFlags |= OPC_CONTACT; + mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives()); + } + else + { + _Collide(node->GetPos()); + _Collide(node->GetNeg()); + } +} + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridSphereCollider::HybridSphereCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridSphereCollider::~HybridSphereCollider() +{ +} + +bool HybridSphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const HybridModel& model, const Matrix4x4* worlds, const Matrix4x4* worldm) +{ + // We don't want primitive tests here! + mFlags |= OPC_NO_PRIMITIVE_TESTS; + + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, sphere, worlds, worldm)) return true; + + // Special case for 1-leaf trees + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles + udword Nb = mIMesh->GetNbTriangles(); + + // Loop through all triangles + for(udword i=0;imCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + + // We only have a list of boxes so far + if(GetContactStatus()) + { + // Reset contact status, since it currently only reflects collisions with leaf boxes + Collider::InitQuery(); + + // Change dest container so that we can use built-in overlap tests and get collided primitives + cache.TouchedPrimitives.Reset(); + mTouchedPrimitives = &cache.TouchedPrimitives; + + // Read touched leaf boxes + udword Nb = mTouchedBoxes.GetNbEntries(); + const udword* Touched = mTouchedBoxes.GetEntries(); + + const LeafTriangles* LT = model.GetLeafTriangles(); + const udword* Indices = model.GetIndices(); + + // Loop through touched leaves + while(Nb--) + { + const LeafTriangles& CurrentLeaf = LT[*Touched++]; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = *T++; + SPHERE_PRIM(TriangleIndex, OPC_CONTACT) + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = BaseIndex++; + SPHERE_PRIM(TriangleIndex, OPC_CONTACT) + } + } + } + } + + return true; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_SphereCollider.h b/Extras/CDTestFramework/Opcode/OPC_SphereCollider.h new file mode 100644 index 0000000..d4aa861 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_SphereCollider.h @@ -0,0 +1,105 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a sphere collider. + * \file OPC_SphereCollider.h + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_SPHERECOLLIDER_H__ +#define __OPC_SPHERECOLLIDER_H__ + + struct OPCODE_API SphereCache : VolumeCache + { + SphereCache() : Center(0.0f,0.0f,0.0f), FatRadius2(0.0f), FatCoeff(1.1f) {} + ~SphereCache() {} + + // Cached faces signature + Point Center; //!< Sphere used when performing the query resulting in cached faces + float FatRadius2; //!< Sphere used when performing the query resulting in cached faces + // User settings + float FatCoeff; //!< mRadius2 multiplier used to create a fat sphere + }; + + class OPCODE_API SphereCollider : public VolumeCollider + { + public: + // Constructor / Destructor + SphereCollider(); + virtual ~SphereCollider(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a sphere cache + * \param sphere [in] collision sphere in local space + * \param model [in] Opcode model to collide with + * \param worlds [in] sphere's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(SphereCache& cache, const Sphere& sphere, const Model& model, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null); + + // + bool Collide(SphereCache& cache, const Sphere& sphere, const AABBTree* tree); + protected: + // Sphere in model space + Point mCenter; //!< Sphere center + float mRadius2; //!< Sphere radius squared + // Internal methods + void _Collide(const AABBCollisionNode* node); + void _Collide(const AABBNoLeafNode* node); + void _Collide(const AABBQuantizedNode* node); + void _Collide(const AABBQuantizedNoLeafNode* node); + void _Collide(const AABBTreeNode* node); + void _CollideNoPrimitiveTest(const AABBCollisionNode* node); + void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); + // Overlap tests + inline_ BOOL SphereContainsBox(const Point& bc, const Point& be); + inline_ BOOL SphereAABBOverlap(const Point& center, const Point& extents); + BOOL SphereTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2); + // Init methods + BOOL InitQuery(SphereCache& cache, const Sphere& sphere, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null); + }; + + class OPCODE_API HybridSphereCollider : public SphereCollider + { + public: + // Constructor / Destructor + HybridSphereCollider(); + virtual ~HybridSphereCollider(); + + bool Collide(SphereCache& cache, const Sphere& sphere, const HybridModel& model, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null); + protected: + Container mTouchedBoxes; + }; + +#endif // __OPC_SPHERECOLLIDER_H__ diff --git a/Extras/CDTestFramework/Opcode/OPC_SphereTriOverlap.h b/Extras/CDTestFramework/Opcode/OPC_SphereTriOverlap.h new file mode 100644 index 0000000..4542e51 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_SphereTriOverlap.h @@ -0,0 +1,203 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +// This is collision detection. If you do another distance test for collision *response*, +// if might be useful to simply *skip* the test below completely, and report a collision. +// - if sphere-triangle overlap, result is ok +// - if they don't, we'll discard them during collision response with a similar test anyway +// Overall this approach should run faster. + +// Original code by David Eberly in Magic. +BOOL SphereCollider::SphereTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2) +{ + // Stats + mNbVolumePrimTests++; + + // Early exit if one of the vertices is inside the sphere + Point kDiff = vert2 - mCenter; + float fC = kDiff.SquareMagnitude(); + if(fC <= mRadius2) return TRUE; + + kDiff = vert1 - mCenter; + fC = kDiff.SquareMagnitude(); + if(fC <= mRadius2) return TRUE; + + kDiff = vert0 - mCenter; + fC = kDiff.SquareMagnitude(); + if(fC <= mRadius2) return TRUE; + + // Else do the full distance test + Point TriEdge0 = vert1 - vert0; + Point TriEdge1 = vert2 - vert0; + +//Point kDiff = vert0 - mCenter; + float fA00 = TriEdge0.SquareMagnitude(); + float fA01 = TriEdge0 | TriEdge1; + float fA11 = TriEdge1.SquareMagnitude(); + float fB0 = kDiff | TriEdge0; + float fB1 = kDiff | TriEdge1; +//float fC = kDiff.SquareMagnitude(); + float fDet = fabsf(fA00*fA11 - fA01*fA01); + float u = fA01*fB1-fA11*fB0; + float v = fA01*fB0-fA00*fB1; + float SqrDist; + + if(u + v <= fDet) + { + if(u < 0.0f) + { + if(v < 0.0f) // region 4 + { + if(fB0 < 0.0f) + { +// v = 0.0f; + if(-fB0>=fA00) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } + else { u = -fB0/fA00; SqrDist = fB0*u+fC; } + } + else + { +// u = 0.0f; + if(fB1>=0.0f) { /*v = 0.0f;*/ SqrDist = fC; } + else if(-fB1>=fA11) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } + else { v = -fB1/fA11; SqrDist = fB1*v+fC; } + } + } + else // region 3 + { +// u = 0.0f; + if(fB1>=0.0f) { /*v = 0.0f;*/ SqrDist = fC; } + else if(-fB1>=fA11) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } + else { v = -fB1/fA11; SqrDist = fB1*v+fC; } + } + } + else if(v < 0.0f) // region 5 + { +// v = 0.0f; + if(fB0>=0.0f) { /*u = 0.0f;*/ SqrDist = fC; } + else if(-fB0>=fA00) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } + else { u = -fB0/fA00; SqrDist = fB0*u+fC; } + } + else // region 0 + { + // minimum at interior point + if(fDet==0.0f) + { +// u = 0.0f; +// v = 0.0f; + SqrDist = MAX_FLOAT; + } + else + { + float fInvDet = 1.0f/fDet; + u *= fInvDet; + v *= fInvDet; + SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; + } + } + } + else + { + float fTmp0, fTmp1, fNumer, fDenom; + + if(u < 0.0f) // region 2 + { + fTmp0 = fA01 + fB0; + fTmp1 = fA11 + fB1; + if(fTmp1 > fTmp0) + { + fNumer = fTmp1 - fTmp0; + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { +// u = 1.0f; +// v = 0.0f; + SqrDist = fA00+2.0f*fB0+fC; + } + else + { + u = fNumer/fDenom; + v = 1.0f - u; + SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; + } + } + else + { +// u = 0.0f; + if(fTmp1 <= 0.0f) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } + else if(fB1 >= 0.0f) { /*v = 0.0f;*/ SqrDist = fC; } + else { v = -fB1/fA11; SqrDist = fB1*v+fC; } + } + } + else if(v < 0.0f) // region 6 + { + fTmp0 = fA01 + fB1; + fTmp1 = fA00 + fB0; + if(fTmp1 > fTmp0) + { + fNumer = fTmp1 - fTmp0; + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { +// v = 1.0f; +// u = 0.0f; + SqrDist = fA11+2.0f*fB1+fC; + } + else + { + v = fNumer/fDenom; + u = 1.0f - v; + SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; + } + } + else + { +// v = 0.0f; + if(fTmp1 <= 0.0f) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } + else if(fB0 >= 0.0f) { /*u = 0.0f;*/ SqrDist = fC; } + else { u = -fB0/fA00; SqrDist = fB0*u+fC; } + } + } + else // region 1 + { + fNumer = fA11 + fB1 - fA01 - fB0; + if(fNumer <= 0.0f) + { +// u = 0.0f; +// v = 1.0f; + SqrDist = fA11+2.0f*fB1+fC; + } + else + { + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { +// u = 1.0f; +// v = 0.0f; + SqrDist = fA00+2.0f*fB0+fC; + } + else + { + u = fNumer/fDenom; + v = 1.0f - u; + SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; + } + } + } + } + + return fabsf(SqrDist) < mRadius2; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_SweepAndPrune.cpp b/Extras/CDTestFramework/Opcode/OPC_SweepAndPrune.cpp new file mode 100644 index 0000000..8928076 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_SweepAndPrune.cpp @@ -0,0 +1,673 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an implementation of the sweep-and-prune algorithm (moved from Z-Collide) + * \file OPC_SweepAndPrune.cpp + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +inline_ void Sort(udword& id0, udword& id1) +{ + if(id0>id1) Swap(id0, id1); +} + + class Opcode::SAP_Element + { + public: + inline_ SAP_Element() {} + inline_ SAP_Element(udword id, SAP_Element* next) : mID(id), mNext(next) {} + inline_ ~SAP_Element() {} + + udword mID; + SAP_Element* mNext; + }; + + class Opcode::SAP_Box + { + public: + SAP_EndPoint* Min[3]; + SAP_EndPoint* Max[3]; + }; + + class Opcode::SAP_EndPoint + { + public: + float Value; // Min or Max value + SAP_EndPoint* Previous; // Previous EndPoint whose Value is smaller than ours (or null) + SAP_EndPoint* Next; // Next EndPoint whose Value is greater than ours (or null) + udword Data; // Parent box ID *2 | MinMax flag + + inline_ void SetData(udword box_id, BOOL is_max) { Data = (box_id<<1)|is_max; } + inline_ BOOL IsMax() const { return Data & 1; } + inline_ udword GetBoxID() const { return Data>>1; } + + inline_ void InsertAfter(SAP_EndPoint* element) + { + if(this!=element && this!=element->Next) + { + // Remove + if(Previous) Previous->Next = Next; + if(Next) Next->Previous = Previous; + + // Insert + Next = element->Next; + if(Next) Next->Previous = this; + + element->Next = this; + Previous = element; + } + } + + inline_ void InsertBefore(SAP_EndPoint* element) + { + if(this!=element && this!=element->Previous) + { + // Remove + if(Previous) Previous->Next = Next; + if(Next) Next->Previous = Previous; + + // Insert + Previous = element->Previous; + element->Previous = this; + + Next = element; + if(Previous) Previous->Next = this; + } + } + }; + + + + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SAP_PairData::SAP_PairData() : + mNbElements (0), + mNbUsedElements (0), + mElementPool (null), + mFirstFree (null), + mNbObjects (0), + mArray (null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SAP_PairData::~SAP_PairData() +{ + Release(); +} + +void SAP_PairData::Release() +{ + mNbElements = 0; + mNbUsedElements = 0; + mNbObjects = 0; + DELETEARRAY(mElementPool); + DELETEARRAY(mArray); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes. + * \param nb_objects [in] + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool SAP_PairData::Init(udword nb_objects) +{ + // Make sure everything has been released + Release(); + if(!nb_objects) return false; + + mArray = new SAP_Element*[nb_objects]; + CHECKALLOC(mArray); + ZeroMemory(mArray, nb_objects*sizeof(SAP_Element*)); + mNbObjects = nb_objects; + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Remaps a pointer when pool gets resized. + * \param element [in/out] remapped element + * \param delta [in] offset in bytes + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ void Remap(SAP_Element*& element, udword delta) +{ + if(element) element = (SAP_Element*)(udword(element) + delta); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Gets a free element in the pool. + * \param id [in] element id + * \param next [in] next element + * \param remap [out] possible remapping offset + * \return the new element + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SAP_Element* SAP_PairData::GetFreeElem(udword id, SAP_Element* next, udword* remap) +{ + if(remap) *remap = 0; + + SAP_Element* FreeElem; + if(mFirstFree) + { + // Recycle + FreeElem = mFirstFree; + mFirstFree = mFirstFree->mNext; // First free = next free (or null) + } + else + { + if(mNbUsedElements==mNbElements) + { + // Resize + mNbElements = mNbElements ? (mNbElements<<1) : 2; + + SAP_Element* NewElems = new SAP_Element[mNbElements]; + + if(mNbUsedElements) CopyMemory(NewElems, mElementPool, mNbUsedElements*sizeof(SAP_Element)); + + // Remap everything + { + udword Delta = udword(NewElems) - udword(mElementPool); + + for(udword i=0;imID = id; + FreeElem->mNext = next; + + return FreeElem; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Frees an element of the pool. + * \param elem [in] element to free/recycle + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ void SAP_PairData::FreeElem(SAP_Element* elem) +{ + elem->mNext = mFirstFree; // Next free + mFirstFree = elem; +} + +// Add a pair to the set. +void SAP_PairData::AddPair(udword id1, udword id2) +{ + // Order the ids + Sort(id1, id2); + + ASSERT(id1=mNbObjects) return; + + // Select the right list from "mArray". + SAP_Element* Current = mArray[id1]; + + if(!Current) + { + // Empty slot => create new element + mArray[id1] = GetFreeElem(id2, null); + } + else if(Current->mID>id2) + { + // The list is not empty but all elements are greater than id2 => insert id2 in the front. + mArray[id1] = GetFreeElem(id2, mArray[id1]); + } + else + { + // Else find the correct location in the sorted list (ascending order) and insert id2 there. + while(Current->mNext) + { + if(Current->mNext->mID > id2) break; + + Current = Current->mNext; + } + + if(Current->mID==id2) return; // The pair already exists + +// Current->mNext = GetFreeElem(id2, Current->mNext); + udword Delta; + SAP_Element* E = GetFreeElem(id2, Current->mNext, &Delta); + if(Delta) Remap(Current, Delta); + Current->mNext = E; + } +} + +// Delete a pair from the set. +void SAP_PairData::RemovePair(udword id1, udword id2) +{ + // Order the ids. + Sort(id1, id2); + + // Exit if the pair doesn't exist in the set + if(id1>=mNbObjects) return; + + // Otherwise, select the correct list. + SAP_Element* Current = mArray[id1]; + + // If this list is empty, the pair doesn't exist. + if(!Current) return; + + // Otherwise, if id2 is the first element, delete it. + if(Current->mID==id2) + { + mArray[id1] = Current->mNext; + FreeElem(Current); + } + else + { + // If id2 is not the first element, start traversing the sorted list. + while(Current->mNext) + { + // If we have moved too far away without hitting id2, then the pair doesn't exist + if(Current->mNext->mID > id2) return; + + // Otherwise, delete id2. + if(Current->mNext->mID == id2) + { + SAP_Element* Temp = Current->mNext; + Current->mNext = Temp->mNext; + FreeElem(Temp); + return; + } + Current = Current->mNext; + } + } +} + +void SAP_PairData::DumpPairs(Pairs& pairs) const +{ + // ### Ugly and slow + for(udword i=0;imIDmID); + Current = Current->mNext; + } + } +} + +void SAP_PairData::DumpPairs(PairCallback callback, void* user_data) const +{ + if(!callback) return; + + // ### Ugly and slow + for(udword i=0;imIDmID, user_data)) return; + Current = Current->mNext; + } + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SweepAndPrune::SweepAndPrune() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SweepAndPrune::~SweepAndPrune() +{ +} + +void SweepAndPrune::GetPairs(Pairs& pairs) const +{ + mPairs.DumpPairs(pairs); +} + +void SweepAndPrune::GetPairs(PairCallback callback, void* user_data) const +{ + mPairs.DumpPairs(callback, user_data); +} + +bool SweepAndPrune::Init(udword nb_objects, const AABB** boxes) +{ + // 1) Create sorted lists + mNbObjects = nb_objects; + + mBoxes = new SAP_Box[nb_objects]; +// for(udword i=0;iGetMin(Axis); + Data[i*2+1] = boxes[i]->GetMax(Axis); + } + RadixSort RS; + const udword* Sorted = RS.Sort(Data, nb_objects*2).GetRanks(); + + SAP_EndPoint* PreviousEndPoint = null; + + for(udword i=0;i>1; + + ASSERT(BoxIndexValue = SortedCoord; +// CurrentEndPoint->IsMax = SortedIndex&1; // ### could be implicit ? +// CurrentEndPoint->ID = BoxIndex; // ### could be implicit ? + CurrentEndPoint->SetData(BoxIndex, SortedIndex&1); // ### could be implicit ? + CurrentEndPoint->Previous = PreviousEndPoint; + CurrentEndPoint->Next = null; + if(PreviousEndPoint) PreviousEndPoint->Next = CurrentEndPoint; + + if(CurrentEndPoint->IsMax()) mBoxes[BoxIndex].Max[Axis] = CurrentEndPoint; + else mBoxes[BoxIndex].Min[Axis] = CurrentEndPoint; + + PreviousEndPoint = CurrentEndPoint; + } + } + + DELETEARRAY(Data); + + CheckListsIntegrity(); + + // 2) Quickly find starting pairs + + mPairs.Init(nb_objects); + + { + Pairs P; + CompleteBoxPruning(nb_objects, boxes, P, Axes(AXES_XZY)); + for(udword i=0;iid0; + udword id1 = PP->id1; + + if(id0!=id1 && boxes[id0]->Intersect(*boxes[id1])) + { + mPairs.AddPair(id0, id1); + } + else ASSERT(0); + } + } + + return true; +} + +bool SweepAndPrune::CheckListsIntegrity() +{ + for(udword Axis=0;Axis<3;Axis++) + { + // Find list head + SAP_EndPoint* Current = mList[Axis]; + while(Current->Previous) Current = Current->Previous; + + udword Nb = 0; + + SAP_EndPoint* Previous = null; + while(Current) + { + Nb++; + + if(Previous) + { + ASSERT(Previous->Value <= Current->Value); + if(Previous->Value > Current->Value) return false; + } + + ASSERT(Current->Previous==Previous); + if(Current->Previous!=Previous) return false; + + Previous = Current; + Current = Current->Next; + } + + ASSERT(Nb==mNbObjects*2); + } + return true; +} + +inline_ BOOL Intersect(const AABB& a, const SAP_Box& b) +{ + if(b.Max[0]->Value < a.GetMin(0) || a.GetMax(0) < b.Min[0]->Value + || b.Max[1]->Value < a.GetMin(1) || a.GetMax(1) < b.Min[1]->Value + || b.Max[2]->Value < a.GetMin(2) || a.GetMax(2) < b.Min[2]->Value) return FALSE; + + return TRUE; +} + + + +bool SweepAndPrune::UpdateObject(udword i, const AABB& box) +{ + for(udword Axis=0;Axis<3;Axis++) + { +// udword Base = (udword)&mList[Axis][0]; + + // Update min + { + SAP_EndPoint* const CurrentMin = mBoxes[i].Min[Axis]; + ASSERT(!CurrentMin->IsMax()); + + const float Limit = box.GetMin(Axis); + if(Limit == CurrentMin->Value) + { + } + else if(Limit < CurrentMin->Value) + { + CurrentMin->Value = Limit; + + // Min is moving left: + SAP_EndPoint* NewPos = CurrentMin; + ASSERT(NewPos); + + SAP_EndPoint* tmp; + while((tmp = NewPos->Previous) && tmp->Value > Limit) + { + NewPos = tmp; + + if(NewPos->IsMax()) + { + // Our min passed a max => start overlap + //udword SortedIndex = (udword(CurrentMin) - Base)/sizeof(NS_EndPoint); + const udword id0 = CurrentMin->GetBoxID(); + const udword id1 = NewPos->GetBoxID(); + + if(id0!=id1 && Intersect(box, mBoxes[id1])) mPairs.AddPair(id0, id1); + } + } + + CurrentMin->InsertBefore(NewPos); + } + else// if(Limit > CurrentMin->Value) + { + CurrentMin->Value = Limit; + + // Min is moving right: + SAP_EndPoint* NewPos = CurrentMin; + ASSERT(NewPos); + + SAP_EndPoint* tmp; + while((tmp = NewPos->Next) && tmp->Value < Limit) + { + NewPos = tmp; + + if(NewPos->IsMax()) + { + // Our min passed a max => stop overlap + const udword id0 = CurrentMin->GetBoxID(); + const udword id1 = NewPos->GetBoxID(); + + if(id0!=id1) mPairs.RemovePair(id0, id1); + } + } + + CurrentMin->InsertAfter(NewPos); + } + } + + // Update max + { + SAP_EndPoint* const CurrentMax = mBoxes[i].Max[Axis]; + ASSERT(CurrentMax->IsMax()); + + const float Limit = box.GetMax(Axis); + if(Limit == CurrentMax->Value) + { + } + else if(Limit > CurrentMax->Value) + { + CurrentMax->Value = Limit; + + // Max is moving right: + SAP_EndPoint* NewPos = CurrentMax; + ASSERT(NewPos); + + SAP_EndPoint* tmp; + while((tmp = NewPos->Next) && tmp->Value < Limit) + { + NewPos = tmp; + + if(!NewPos->IsMax()) + { + // Our max passed a min => start overlap + const udword id0 = CurrentMax->GetBoxID(); + const udword id1 = NewPos->GetBoxID(); + + if(id0!=id1 && Intersect(box, mBoxes[id1])) mPairs.AddPair(id0, id1); + } + } + + CurrentMax->InsertAfter(NewPos); + } + else// if(Limit < CurrentMax->Value) + { + CurrentMax->Value = Limit; + + // Max is moving left: + SAP_EndPoint* NewPos = CurrentMax; + ASSERT(NewPos); + + SAP_EndPoint* tmp; + while((tmp = NewPos->Previous) && tmp->Value > Limit) + { + NewPos = tmp; + + if(!NewPos->IsMax()) + { + // Our max passed a min => stop overlap + const udword id0 = CurrentMax->GetBoxID(); + const udword id1 = NewPos->GetBoxID(); + + if(id0!=id1) mPairs.RemovePair(id0, id1); + } + } + + CurrentMax->InsertBefore(NewPos); + } + } + } + + return true; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_SweepAndPrune.h b/Extras/CDTestFramework/Opcode/OPC_SweepAndPrune.h new file mode 100644 index 0000000..0221d28 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_SweepAndPrune.h @@ -0,0 +1,95 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an implementation of the sweep-and-prune algorithm (moved from Z-Collide) + * \file OPC_SweepAndPrune.h + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_SWEEPANDPRUNE_H__ +#define __OPC_SWEEPANDPRUNE_H__ + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * User-callback, called by OPCODE for each colliding pairs. + * \param id0 [in] id of colliding object + * \param id1 [in] id of colliding object + * \param user_data [in] user-defined data + * \return TRUE to continue enumeration + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + typedef BOOL (*PairCallback) (udword id0, udword id1, void* user_data); + + class SAP_Element; + class SAP_EndPoint; + class SAP_Box; + + class OPCODE_API SAP_PairData + { + public: + SAP_PairData(); + ~SAP_PairData(); + + bool Init(udword nb_objects); + + void AddPair(udword id1, udword id2); + void RemovePair(udword id1, udword id2); + + void DumpPairs(Pairs& pairs) const; + void DumpPairs(PairCallback callback, void* user_data) const; + private: + udword mNbElements; //!< Total number of elements in the pool + udword mNbUsedElements; //!< Number of used elements + SAP_Element* mElementPool; //!< Array of mNbElements elements + SAP_Element* mFirstFree; //!< First free element in the pool + + udword mNbObjects; //!< Max number of objects we can handle + SAP_Element** mArray; //!< Pointers to pool + // Internal methods + SAP_Element* GetFreeElem(udword id, SAP_Element* next, udword* remap=null); + inline_ void FreeElem(SAP_Element* elem); + void Release(); + }; + + class OPCODE_API SweepAndPrune + { + public: + SweepAndPrune(); + ~SweepAndPrune(); + + bool Init(udword nb_objects, const AABB** boxes); + bool UpdateObject(udword i, const AABB& box); + + void GetPairs(Pairs& pairs) const; + void GetPairs(PairCallback callback, void* user_data) const; + private: + SAP_PairData mPairs; + + udword mNbObjects; + SAP_Box* mBoxes; + SAP_EndPoint* mList[3]; + // Internal methods + bool CheckListsIntegrity(); + }; + +#endif //__OPC_SWEEPANDPRUNE_H__ \ No newline at end of file diff --git a/Extras/CDTestFramework/Opcode/OPC_TreeBuilders.cpp b/Extras/CDTestFramework/Opcode/OPC_TreeBuilders.cpp new file mode 100644 index 0000000..7fbb4e3 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_TreeBuilders.cpp @@ -0,0 +1,264 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for tree builders. + * \file OPC_TreeBuilders.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A builder for AABB-trees of vertices. + * + * \class AABBTreeOfVerticesBuilder + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A builder for AABB-trees of AABBs. + * + * \class AABBTreeOfAABBsBuilder + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A builder for AABB-trees of triangles. + * + * \class AABBTreeOfTrianglesBuilder + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the AABB of a set of primitives. + * \param primitives [in] list of indices of primitives + * \param nb_prims [in] number of indices + * \param global_box [out] global AABB enclosing the set of input primitives + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeOfAABBsBuilder::ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const +{ + // Checkings + if(!primitives || !nb_prims) return false; + + // Initialize global box + global_box = mAABBArray[primitives[0]]; + + // Loop through boxes + for(udword i=1;iGetTriangle(VP, *primitives++); + // Update global box + Min.Min(*VP.Vertex[0]).Min(*VP.Vertex[1]).Min(*VP.Vertex[2]); + Max.Max(*VP.Vertex[0]).Max(*VP.Vertex[1]).Max(*VP.Vertex[2]); + } + global_box.SetMinMax(Min, Max); + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the splitting value along a given axis for a given primitive. + * \param index [in] index of the primitive to split + * \param axis [in] axis index (0,1,2) + * \return splitting value + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float AABBTreeOfTrianglesBuilder::GetSplittingValue(udword index, udword axis) const +{ +/* // Compute center of triangle + Point Center; + mTriList[index].Center(mVerts, Center); + // Return value + return Center[axis];*/ + + // Compute correct component from center of triangle +// return (mVerts[mTriList[index].mVRef[0]][axis] +// +mVerts[mTriList[index].mVRef[1]][axis] +// +mVerts[mTriList[index].mVRef[2]][axis])*INV3; + + VertexPointers VP; + mIMesh->GetTriangle(VP, index); + + // Compute correct component from center of triangle + return ((*VP.Vertex[0])[axis] + +(*VP.Vertex[1])[axis] + +(*VP.Vertex[2])[axis])*INV3; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the splitting value along a given axis for a given node. + * \param primitives [in] list of indices of primitives + * \param nb_prims [in] number of indices + * \param global_box [in] global AABB enclosing the set of input primitives + * \param axis [in] axis index (0,1,2) + * \return splitting value + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float AABBTreeOfTrianglesBuilder::GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis) const +{ + if(mSettings.mRules&SPLIT_GEOM_CENTER) + { + // Loop through triangles + float SplitValue = 0.0f; + VertexPointers VP; + for(udword i=0;iGetTriangle(VP, primitives[i]); + // Update split value + SplitValue += (*VP.Vertex[0])[axis]; + SplitValue += (*VP.Vertex[1])[axis]; + SplitValue += (*VP.Vertex[2])[axis]; + } + return SplitValue / float(nb_prims*3); + } + else return AABBTreeBuilder::GetSplittingValue(primitives, nb_prims, global_box, axis); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the AABB of a set of primitives. + * \param primitives [in] list of indices of primitives + * \param nb_prims [in] number of indices + * \param global_box [out] global AABB enclosing the set of input primitives + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeOfVerticesBuilder::ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const +{ + // Checkings + if(!primitives || !nb_prims) return false; + + // Initialize global box + global_box.SetEmpty(); + + // Loop through vertices + for(udword i=0;iHasLeafNodes()!=cache.Model1->HasLeafNodes()) return false; + if(cache.Model0->IsQuantized()!=cache.Model1->IsQuantized()) return false; + + /* + + Rules: + - perform hull test + - when hulls collide, disable hull test + - if meshes overlap, reset countdown + - if countdown reaches 0, enable hull test + + */ + +#ifdef __MESHMERIZER_H__ + // Handle hulls + if(cache.HullTest) + { + if(cache.Model0->GetHull() && cache.Model1->GetHull()) + { + struct Local + { + static Point* SVCallback(const Point& sv, udword& previndex, udword user_data) + { + CollisionHull* Hull = (CollisionHull*)user_data; + previndex = Hull->ComputeSupportingVertex(sv, previndex); + return (Point*)&Hull->GetVerts()[previndex]; + } + }; + + bool Collide; + + if(0) + { + static GJKEngine GJK; + static bool GJKInitDone=false; + if(!GJKInitDone) + { + GJK.Enable(GJK_BACKUP_PROCEDURE); + GJK.Enable(GJK_DEGENERATE); + GJK.Enable(GJK_HILLCLIMBING); + GJKInitDone = true; + } + GJK.SetCallbackObj0(Local::SVCallback); + GJK.SetCallbackObj1(Local::SVCallback); + GJK.SetUserData0(udword(cache.Model0->GetHull())); + GJK.SetUserData1(udword(cache.Model1->GetHull())); + Collide = GJK.Collide(*world0, *world1, &cache.SepVector); + } + else + { + static SVEngine SVE; + SVE.SetCallbackObj0(Local::SVCallback); + SVE.SetCallbackObj1(Local::SVCallback); + SVE.SetUserData0(udword(cache.Model0->GetHull())); + SVE.SetUserData1(udword(cache.Model1->GetHull())); + Collide = SVE.Collide(*world0, *world1, &cache.SepVector); + } + + if(!Collide) + { + // Reset stats & contact status + mFlags &= ~OPC_CONTACT; + mNbBVBVTests = 0; + mNbPrimPrimTests = 0; + mNbBVPrimTests = 0; + mPairs.Reset(); + return true; + } + } + } + + // Here, hulls collide + cache.HullTest = false; +#endif // __MESHMERIZER_H__ + + // Checkings + if(!Setup(cache.Model0->GetMeshInterface(), cache.Model1->GetMeshInterface())) return false; + + // Simple double-dispatch + bool Status; + if(!cache.Model0->HasLeafNodes()) + { + if(cache.Model0->IsQuantized()) + { + const AABBQuantizedNoLeafTree* T0 = (const AABBQuantizedNoLeafTree*)cache.Model0->GetTree(); + const AABBQuantizedNoLeafTree* T1 = (const AABBQuantizedNoLeafTree*)cache.Model1->GetTree(); + Status = Collide(T0, T1, world0, world1, &cache); + } + else + { + const AABBNoLeafTree* T0 = (const AABBNoLeafTree*)cache.Model0->GetTree(); + const AABBNoLeafTree* T1 = (const AABBNoLeafTree*)cache.Model1->GetTree(); + Status = Collide(T0, T1, world0, world1, &cache); + } + } + else + { + if(cache.Model0->IsQuantized()) + { + const AABBQuantizedTree* T0 = (const AABBQuantizedTree*)cache.Model0->GetTree(); + const AABBQuantizedTree* T1 = (const AABBQuantizedTree*)cache.Model1->GetTree(); + Status = Collide(T0, T1, world0, world1, &cache); + } + else + { + const AABBCollisionTree* T0 = (const AABBCollisionTree*)cache.Model0->GetTree(); + const AABBCollisionTree* T1 = (const AABBCollisionTree*)cache.Model1->GetTree(); + Status = Collide(T0, T1, world0, world1, &cache); + } + } + +#ifdef __MESHMERIZER_H__ + if(Status) + { + // Reset counter as long as overlap occurs + if(GetContactStatus()) cache.ResetCountDown(); + + // Enable hull test again when counter reaches zero + cache.CountDown--; + if(!cache.CountDown) + { + cache.ResetCountDown(); + cache.HullTest = true; + } + } +#endif + return Status; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - setup matrices + * + * \param world0 [in] world matrix for first object + * \param world1 [in] world matrix for second object + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::InitQuery(const Matrix4x4* world0, const Matrix4x4* world1) +{ + // Reset stats & contact status + Collider::InitQuery(); + mNbBVBVTests = 0; + mNbPrimPrimTests = 0; + mNbBVPrimTests = 0; + mPairs.Reset(); + + // Setup matrices + Matrix4x4 InvWorld0, InvWorld1; + if(world0) InvertPRMatrix(InvWorld0, *world0); + else InvWorld0.Identity(); + + if(world1) InvertPRMatrix(InvWorld1, *world1); + else InvWorld1.Identity(); + + Matrix4x4 World0to1 = world0 ? (*world0 * InvWorld1) : InvWorld1; + Matrix4x4 World1to0 = world1 ? (*world1 * InvWorld0) : InvWorld0; + + mR0to1 = World0to1; World0to1.GetTrans(mT0to1); + mR1to0 = World1to0; World1to0.GetTrans(mT1to0); + + // Precompute absolute 1-to-0 rotation matrix + for(udword i=0;i<3;i++) + { + for(udword j=0;j<3;j++) + { + // Epsilon value prevents floating-point inaccuracies (strategy borrowed from RAPID) + mAR.m[i][j] = 1e-6f + fabsf(mR1to0.m[i][j]); + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Takes advantage of temporal coherence. + * \param cache [in] cache for a pair of previously colliding primitives + * \return true if we can return immediately + * \warning only works for "First Contact" mode + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeCollider::CheckTemporalCoherence(Pair* cache) +{ + // Checkings + if(!cache) return false; + + // Test previously colliding primitives first + if(TemporalCoherenceEnabled() && FirstContactEnabled()) + { + PrimTest(cache->id0, cache->id1); + if(GetContactStatus()) return true; + } + return false; +} + +#define UPDATE_CACHE \ + if(cache && GetContactStatus()) \ + { \ + cache->id0 = mPairs.GetEntry(0); \ + cache->id1 = mPairs.GetEntry(1); \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for normal AABB trees. + * \param tree0 [in] AABB tree from first object + * \param tree1 [in] AABB tree from second object + * \param world0 [in] world matrix for first object + * \param world1 [in] world matrix for second object + * \param cache [in/out] cache for a pair of previously colliding primitives + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeCollider::Collide(const AABBCollisionTree* tree0, const AABBCollisionTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) +{ + // Init collision query + InitQuery(world0, world1); + + // Check previous state + if(CheckTemporalCoherence(cache)) return true; + + // Perform collision query + _Collide(tree0->GetNodes(), tree1->GetNodes()); + + UPDATE_CACHE + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for no-leaf AABB trees. + * \param tree0 [in] AABB tree from first object + * \param tree1 [in] AABB tree from second object + * \param world0 [in] world matrix for first object + * \param world1 [in] world matrix for second object + * \param cache [in/out] cache for a pair of previously colliding primitives + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeCollider::Collide(const AABBNoLeafTree* tree0, const AABBNoLeafTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) +{ + // Init collision query + InitQuery(world0, world1); + + // Check previous state + if(CheckTemporalCoherence(cache)) return true; + + // Perform collision query + _Collide(tree0->GetNodes(), tree1->GetNodes()); + + UPDATE_CACHE + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for quantized AABB trees. + * \param tree0 [in] AABB tree from first object + * \param tree1 [in] AABB tree from second object + * \param world0 [in] world matrix for first object + * \param world1 [in] world matrix for second object + * \param cache [in/out] cache for a pair of previously colliding primitives + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeCollider::Collide(const AABBQuantizedTree* tree0, const AABBQuantizedTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) +{ + // Init collision query + InitQuery(world0, world1); + + // Check previous state + if(CheckTemporalCoherence(cache)) return true; + + // Setup dequantization coeffs + mCenterCoeff0 = tree0->mCenterCoeff; + mExtentsCoeff0 = tree0->mExtentsCoeff; + mCenterCoeff1 = tree1->mCenterCoeff; + mExtentsCoeff1 = tree1->mExtentsCoeff; + + // Dequantize box A + const AABBQuantizedNode* N0 = tree0->GetNodes(); + const Point a(float(N0->mAABB.mExtents[0]) * mExtentsCoeff0.x, float(N0->mAABB.mExtents[1]) * mExtentsCoeff0.y, float(N0->mAABB.mExtents[2]) * mExtentsCoeff0.z); + const Point Pa(float(N0->mAABB.mCenter[0]) * mCenterCoeff0.x, float(N0->mAABB.mCenter[1]) * mCenterCoeff0.y, float(N0->mAABB.mCenter[2]) * mCenterCoeff0.z); + // Dequantize box B + const AABBQuantizedNode* N1 = tree1->GetNodes(); + const Point b(float(N1->mAABB.mExtents[0]) * mExtentsCoeff1.x, float(N1->mAABB.mExtents[1]) * mExtentsCoeff1.y, float(N1->mAABB.mExtents[2]) * mExtentsCoeff1.z); + const Point Pb(float(N1->mAABB.mCenter[0]) * mCenterCoeff1.x, float(N1->mAABB.mCenter[1]) * mCenterCoeff1.y, float(N1->mAABB.mCenter[2]) * mCenterCoeff1.z); + + // Perform collision query + _Collide(N0, N1, a, Pa, b, Pb); + + UPDATE_CACHE + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for quantized no-leaf AABB trees. + * \param tree0 [in] AABB tree from first object + * \param tree1 [in] AABB tree from second object + * \param world0 [in] world matrix for first object + * \param world1 [in] world matrix for second object + * \param cache [in/out] cache for a pair of previously colliding primitives + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeCollider::Collide(const AABBQuantizedNoLeafTree* tree0, const AABBQuantizedNoLeafTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) +{ + // Init collision query + InitQuery(world0, world1); + + // Check previous state + if(CheckTemporalCoherence(cache)) return true; + + // Setup dequantization coeffs + mCenterCoeff0 = tree0->mCenterCoeff; + mExtentsCoeff0 = tree0->mExtentsCoeff; + mCenterCoeff1 = tree1->mCenterCoeff; + mExtentsCoeff1 = tree1->mExtentsCoeff; + + // Perform collision query + _Collide(tree0->GetNodes(), tree1->GetNodes()); + + UPDATE_CACHE + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Standard trees +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// The normal AABB tree can use 2 different descent rules (with different performances) +//#define ORIGINAL_CODE //!< UNC-like descent rules +#define ALTERNATIVE_CODE //!< Alternative descent rules + +#ifdef ORIGINAL_CODE +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param b0 [in] collision node from first tree + * \param b1 [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1) +{ + // Perform BV-BV overlap test + if(!BoxBoxOverlap(b0->mAABB.mExtents, b0->mAABB.mCenter, b1->mAABB.mExtents, b1->mAABB.mCenter)) return; + + if(b0->IsLeaf() && b1->IsLeaf()) { PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); return; } + + if(b1->IsLeaf() || (!b0->IsLeaf() && (b0->GetSize() > b1->GetSize()))) + { + _Collide(b0->GetNeg(), b1); + if(ContactFound()) return; + _Collide(b0->GetPos(), b1); + } + else + { + _Collide(b0, b1->GetNeg()); + if(ContactFound()) return; + _Collide(b0, b1->GetPos()); + } +} +#endif + +#ifdef ALTERNATIVE_CODE +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param b0 [in] collision node from first tree + * \param b1 [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1) +{ + // Perform BV-BV overlap test + if(!BoxBoxOverlap(b0->mAABB.mExtents, b0->mAABB.mCenter, b1->mAABB.mExtents, b1->mAABB.mCenter)) + { + return; + } + + if(b0->IsLeaf()) + { + if(b1->IsLeaf()) + { + PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); + } + else + { + _Collide(b0, b1->GetNeg()); + if(ContactFound()) return; + _Collide(b0, b1->GetPos()); + } + } + else if(b1->IsLeaf()) + { + _Collide(b0->GetNeg(), b1); + if(ContactFound()) return; + _Collide(b0->GetPos(), b1); + } + else + { + _Collide(b0->GetNeg(), b1->GetNeg()); + if(ContactFound()) return; + _Collide(b0->GetNeg(), b1->GetPos()); + if(ContactFound()) return; + _Collide(b0->GetPos(), b1->GetNeg()); + if(ContactFound()) return; + _Collide(b0->GetPos(), b1->GetPos()); + } +} +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// No-leaf trees +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Leaf-leaf test for two primitive indices. + * \param id0 [in] index from first leaf-triangle + * \param id1 [in] index from second leaf-triangle + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::PrimTest(udword id0, udword id1) +{ + // Request vertices from the app + VertexPointers VP0; + VertexPointers VP1; + mIMesh0->GetTriangle(VP0, id0); + mIMesh1->GetTriangle(VP1, id1); + + // Transform from space 1 to space 0 + Point u0,u1,u2; + TransformPoint(u0, *VP1.Vertex[0], mR1to0, mT1to0); + TransformPoint(u1, *VP1.Vertex[1], mR1to0, mT1to0); + TransformPoint(u2, *VP1.Vertex[2], mR1to0, mT1to0); + + // Perform triangle-triangle overlap test + if(TriTriOverlap(*VP0.Vertex[0], *VP0.Vertex[1], *VP0.Vertex[2], u0, u1, u2)) + { + // Keep track of colliding pairs + mPairs.Add(id0).Add(id1); + // Set contact status + mFlags |= OPC_CONTACT; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Leaf-leaf test for a previously fetched triangle from tree A (in B's space) and a new leaf from B. + * \param id1 [in] leaf-triangle index from tree B + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ void AABBTreeCollider::PrimTestTriIndex(udword id1) +{ + // Request vertices from the app + VertexPointers VP; + mIMesh1->GetTriangle(VP, id1); + + // Perform triangle-triangle overlap test + if(TriTriOverlap(mLeafVerts[0], mLeafVerts[1], mLeafVerts[2], *VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) + { + // Keep track of colliding pairs + mPairs.Add(mLeafIndex).Add(id1); + // Set contact status + mFlags |= OPC_CONTACT; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Leaf-leaf test for a previously fetched triangle from tree B (in A's space) and a new leaf from A. + * \param id0 [in] leaf-triangle index from tree A + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ void AABBTreeCollider::PrimTestIndexTri(udword id0) +{ + // Request vertices from the app + VertexPointers VP; + mIMesh0->GetTriangle(VP, id0); + + // Perform triangle-triangle overlap test + if(TriTriOverlap(mLeafVerts[0], mLeafVerts[1], mLeafVerts[2], *VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) + { + // Keep track of colliding pairs + mPairs.Add(id0).Add(mLeafIndex); + // Set contact status + mFlags |= OPC_CONTACT; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision of a leaf node from A and a branch from B. + * \param b [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_CollideTriBox(const AABBNoLeafNode* b) +{ + // Perform triangle-box overlap test + if(!TriBoxOverlap(b->mAABB.mCenter, b->mAABB.mExtents)) return; + + // Keep same triangle, deal with first child + if(b->HasPosLeaf()) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + // Keep same triangle, deal with second child + if(b->HasNegLeaf()) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision of a leaf node from B and a branch from A. + * \param b [in] collision node from first tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_CollideBoxTri(const AABBNoLeafNode* b) +{ + // Perform triangle-box overlap test + if(!TriBoxOverlap(b->mAABB.mCenter, b->mAABB.mExtents)) return; + + // Keep same triangle, deal with first child + if(b->HasPosLeaf()) PrimTestIndexTri(b->GetPosPrimitive()); + else _CollideBoxTri(b->GetPos()); + + if(ContactFound()) return; + + // Keep same triangle, deal with second child + if(b->HasNegLeaf()) PrimTestIndexTri(b->GetNegPrimitive()); + else _CollideBoxTri(b->GetNeg()); +} + +//! Request triangle vertices from the app and transform them +#define FETCH_LEAF(prim_index, imesh, rot, trans) \ + mLeafIndex = prim_index; \ + /* Request vertices from the app */ \ + VertexPointers VP; imesh->GetTriangle(VP, prim_index); \ + /* Transform them in a common space */ \ + TransformPoint(mLeafVerts[0], *VP.Vertex[0], rot, trans); \ + TransformPoint(mLeafVerts[1], *VP.Vertex[1], rot, trans); \ + TransformPoint(mLeafVerts[2], *VP.Vertex[2], rot, trans); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param a [in] collision node from first tree + * \param b [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_Collide(const AABBNoLeafNode* a, const AABBNoLeafNode* b) +{ + // Perform BV-BV overlap test + if(!BoxBoxOverlap(a->mAABB.mExtents, a->mAABB.mCenter, b->mAABB.mExtents, b->mAABB.mCenter)) return; + + // Catch leaf status + BOOL BHasPosLeaf = b->HasPosLeaf(); + BOOL BHasNegLeaf = b->HasNegLeaf(); + + if(a->HasPosLeaf()) + { + FETCH_LEAF(a->GetPosPrimitive(), mIMesh0, mR0to1, mT0to1) + + if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); + } + else + { + if(BHasPosLeaf) + { + FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetPos()); + } + else _Collide(a->GetPos(), b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) + { + FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetPos()); + } + else _Collide(a->GetPos(), b->GetNeg()); + } + + if(ContactFound()) return; + + if(a->HasNegLeaf()) + { + FETCH_LEAF(a->GetNegPrimitive(), mIMesh0, mR0to1, mT0to1) + + if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); + } + else + { + if(BHasPosLeaf) + { + // ### That leaf has possibly already been fetched + FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetNeg()); + } + else _Collide(a->GetNeg(), b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) + { + // ### That leaf has possibly already been fetched + FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetNeg()); + } + else _Collide(a->GetNeg(), b->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Quantized trees +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param b0 [in] collision node from first tree + * \param b1 [in] collision node from second tree + * \param a [in] extent from box A + * \param Pa [in] center from box A + * \param b [in] extent from box B + * \param Pb [in] center from box B + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_Collide(const AABBQuantizedNode* b0, const AABBQuantizedNode* b1, const Point& a, const Point& Pa, const Point& b, const Point& Pb) +{ + // Perform BV-BV overlap test + if(!BoxBoxOverlap(a, Pa, b, Pb)) return; + + if(b0->IsLeaf() && b1->IsLeaf()) { PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); return; } + + if(b1->IsLeaf() || (!b0->IsLeaf() && (b0->GetSize() > b1->GetSize()))) + { + // Dequantize box + const QuantizedAABB* Box = &b0->GetNeg()->mAABB; + const Point negPa(float(Box->mCenter[0]) * mCenterCoeff0.x, float(Box->mCenter[1]) * mCenterCoeff0.y, float(Box->mCenter[2]) * mCenterCoeff0.z); + const Point nega(float(Box->mExtents[0]) * mExtentsCoeff0.x, float(Box->mExtents[1]) * mExtentsCoeff0.y, float(Box->mExtents[2]) * mExtentsCoeff0.z); + _Collide(b0->GetNeg(), b1, nega, negPa, b, Pb); + + if(ContactFound()) return; + + // Dequantize box + Box = &b0->GetPos()->mAABB; + const Point posPa(float(Box->mCenter[0]) * mCenterCoeff0.x, float(Box->mCenter[1]) * mCenterCoeff0.y, float(Box->mCenter[2]) * mCenterCoeff0.z); + const Point posa(float(Box->mExtents[0]) * mExtentsCoeff0.x, float(Box->mExtents[1]) * mExtentsCoeff0.y, float(Box->mExtents[2]) * mExtentsCoeff0.z); + _Collide(b0->GetPos(), b1, posa, posPa, b, Pb); + } + else + { + // Dequantize box + const QuantizedAABB* Box = &b1->GetNeg()->mAABB; + const Point negPb(float(Box->mCenter[0]) * mCenterCoeff1.x, float(Box->mCenter[1]) * mCenterCoeff1.y, float(Box->mCenter[2]) * mCenterCoeff1.z); + const Point negb(float(Box->mExtents[0]) * mExtentsCoeff1.x, float(Box->mExtents[1]) * mExtentsCoeff1.y, float(Box->mExtents[2]) * mExtentsCoeff1.z); + _Collide(b0, b1->GetNeg(), a, Pa, negb, negPb); + + if(ContactFound()) return; + + // Dequantize box + Box = &b1->GetPos()->mAABB; + const Point posPb(float(Box->mCenter[0]) * mCenterCoeff1.x, float(Box->mCenter[1]) * mCenterCoeff1.y, float(Box->mCenter[2]) * mCenterCoeff1.z); + const Point posb(float(Box->mExtents[0]) * mExtentsCoeff1.x, float(Box->mExtents[1]) * mExtentsCoeff1.y, float(Box->mExtents[2]) * mExtentsCoeff1.z); + _Collide(b0, b1->GetPos(), a, Pa, posb, posPb); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Quantized no-leaf trees +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision of a leaf node from A and a quantized branch from B. + * \param leaf [in] leaf triangle from first tree + * \param b [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_CollideTriBox(const AABBQuantizedNoLeafNode* b) +{ + // Dequantize box + const QuantizedAABB* bb = &b->mAABB; + const Point Pb(float(bb->mCenter[0]) * mCenterCoeff1.x, float(bb->mCenter[1]) * mCenterCoeff1.y, float(bb->mCenter[2]) * mCenterCoeff1.z); + const Point eb(float(bb->mExtents[0]) * mExtentsCoeff1.x, float(bb->mExtents[1]) * mExtentsCoeff1.y, float(bb->mExtents[2]) * mExtentsCoeff1.z); + + // Perform triangle-box overlap test + if(!TriBoxOverlap(Pb, eb)) return; + + if(b->HasPosLeaf()) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + if(b->HasNegLeaf()) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision of a leaf node from B and a quantized branch from A. + * \param b [in] collision node from first tree + * \param leaf [in] leaf triangle from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_CollideBoxTri(const AABBQuantizedNoLeafNode* b) +{ + // Dequantize box + const QuantizedAABB* bb = &b->mAABB; + const Point Pa(float(bb->mCenter[0]) * mCenterCoeff0.x, float(bb->mCenter[1]) * mCenterCoeff0.y, float(bb->mCenter[2]) * mCenterCoeff0.z); + const Point ea(float(bb->mExtents[0]) * mExtentsCoeff0.x, float(bb->mExtents[1]) * mExtentsCoeff0.y, float(bb->mExtents[2]) * mExtentsCoeff0.z); + + // Perform triangle-box overlap test + if(!TriBoxOverlap(Pa, ea)) return; + + if(b->HasPosLeaf()) PrimTestIndexTri(b->GetPosPrimitive()); + else _CollideBoxTri(b->GetPos()); + + if(ContactFound()) return; + + if(b->HasNegLeaf()) PrimTestIndexTri(b->GetNegPrimitive()); + else _CollideBoxTri(b->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param a [in] collision node from first tree + * \param b [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_Collide(const AABBQuantizedNoLeafNode* a, const AABBQuantizedNoLeafNode* b) +{ + // Dequantize box A + const QuantizedAABB* ab = &a->mAABB; + const Point Pa(float(ab->mCenter[0]) * mCenterCoeff0.x, float(ab->mCenter[1]) * mCenterCoeff0.y, float(ab->mCenter[2]) * mCenterCoeff0.z); + const Point ea(float(ab->mExtents[0]) * mExtentsCoeff0.x, float(ab->mExtents[1]) * mExtentsCoeff0.y, float(ab->mExtents[2]) * mExtentsCoeff0.z); + // Dequantize box B + const QuantizedAABB* bb = &b->mAABB; + const Point Pb(float(bb->mCenter[0]) * mCenterCoeff1.x, float(bb->mCenter[1]) * mCenterCoeff1.y, float(bb->mCenter[2]) * mCenterCoeff1.z); + const Point eb(float(bb->mExtents[0]) * mExtentsCoeff1.x, float(bb->mExtents[1]) * mExtentsCoeff1.y, float(bb->mExtents[2]) * mExtentsCoeff1.z); + + // Perform BV-BV overlap test + if(!BoxBoxOverlap(ea, Pa, eb, Pb)) return; + + // Catch leaf status + BOOL BHasPosLeaf = b->HasPosLeaf(); + BOOL BHasNegLeaf = b->HasNegLeaf(); + + if(a->HasPosLeaf()) + { + FETCH_LEAF(a->GetPosPrimitive(), mIMesh0, mR0to1, mT0to1) + + if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); + } + else + { + if(BHasPosLeaf) + { + FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetPos()); + } + else _Collide(a->GetPos(), b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) + { + FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetPos()); + } + else _Collide(a->GetPos(), b->GetNeg()); + } + + if(ContactFound()) return; + + if(a->HasNegLeaf()) + { + FETCH_LEAF(a->GetNegPrimitive(), mIMesh0, mR0to1, mT0to1) + + if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); + } + else + { + if(BHasPosLeaf) + { + // ### That leaf has possibly already been fetched + FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetNeg()); + } + else _Collide(a->GetNeg(), b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) + { + // ### That leaf has possibly already been fetched + FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetNeg()); + } + else _Collide(a->GetNeg(), b->GetNeg()); + } +} diff --git a/Extras/CDTestFramework/Opcode/OPC_TreeCollider.h b/Extras/CDTestFramework/Opcode/OPC_TreeCollider.h new file mode 100644 index 0000000..f0d731d --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_TreeCollider.h @@ -0,0 +1,253 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a tree collider. + * \file OPC_TreeCollider.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_TREECOLLIDER_H__ +#define __OPC_TREECOLLIDER_H__ + + //! This structure holds cached information used by the algorithm. + //! Two model pointers and two colliding primitives are cached. Model pointers are assigned + //! to their respective meshes, and the pair of colliding primitives is used for temporal + //! coherence. That is, in case temporal coherence is enabled, those two primitives are + //! tested for overlap before everything else. If they still collide, we're done before + //! even entering the recursive collision code. + struct OPCODE_API BVTCache : Pair + { + //! Constructor + inline_ BVTCache() + { + ResetCache(); + ResetCountDown(); + } + + void ResetCache() + { + Model0 = null; + Model1 = null; + id0 = 0; + id1 = 1; +#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! + HullTest = true; + SepVector.pid = 0; + SepVector.qid = 0; + SepVector.SV = Point(1.0f, 0.0f, 0.0f); +#endif // __MESHMERIZER_H__ + } + + inline_ void ResetCountDown() + { +#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! + CountDown = 50; +#endif // __MESHMERIZER_H__ + } + + const Model* Model0; //!< Model for first object + const Model* Model1; //!< Model for second object + +#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! + SVCache SepVector; + udword CountDown; + bool HullTest; +#endif // __MESHMERIZER_H__ + }; + + class OPCODE_API AABBTreeCollider : public Collider + { + public: + // Constructor / Destructor + AABBTreeCollider(); + virtual ~AABBTreeCollider(); + // Generic collision query + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic collision query for generic OPCODE models. After the call, access the results with: + * - GetContactStatus() + * - GetNbPairs() + * - GetPairs() + * + * \param cache [in] collision cache for model pointers and a colliding pair of primitives + * \param world0 [in] world matrix for first object, or null + * \param world1 [in] world matrix for second object, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(BVTCache& cache, const Matrix4x4* world0=null, const Matrix4x4* world1=null); + + // Collision queries + bool Collide(const AABBCollisionTree* tree0, const AABBCollisionTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); + bool Collide(const AABBNoLeafTree* tree0, const AABBNoLeafTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); + bool Collide(const AABBQuantizedTree* tree0, const AABBQuantizedTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); + bool Collide(const AABBQuantizedNoLeafTree* tree0, const AABBQuantizedNoLeafTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); + // Settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: selects between full box-box tests or "SAT-lite" tests (where Class III axes are discarded) + * \param flag [in] true for full tests, false for coarse tests + * \see SetFullPrimBoxTest(bool flag) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetFullBoxBoxTest(bool flag) { mFullBoxBoxTest = flag; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: selects between full triangle-box tests or "SAT-lite" tests (where Class III axes are discarded) + * \param flag [in] true for full tests, false for coarse tests + * \see SetFullBoxBoxTest(bool flag) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetFullPrimBoxTest(bool flag) { mFullPrimBoxTest = flag; } + + // Stats + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of BV-BV overlap tests after a collision query. + * \see GetNbPrimPrimTests() + * \see GetNbBVPrimTests() + * \return the number of BV-BV tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbBVBVTests() const { return mNbBVBVTests; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of Triangle-Triangle overlap tests after a collision query. + * \see GetNbBVBVTests() + * \see GetNbBVPrimTests() + * \return the number of Triangle-Triangle tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbPrimPrimTests() const { return mNbPrimPrimTests; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of BV-Triangle overlap tests after a collision query. + * \see GetNbBVBVTests() + * \see GetNbPrimPrimTests() + * \return the number of BV-Triangle tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbBVPrimTests() const { return mNbBVPrimTests; } + + // Data access + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of contacts after a collision query. + * \see GetContactStatus() + * \see GetPairs() + * \return the number of contacts / colliding pairs. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbPairs() const { return mPairs.GetNbEntries()>>1; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the pairs of colliding triangles after a collision query. + * \see GetContactStatus() + * \see GetNbPairs() + * \return the list of colliding pairs (triangle indices) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const Pair* GetPairs() const { return (const Pair*)mPairs.GetEntries(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. + * \return null if everything is ok, else a string describing the problem + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(Collider) const char* ValidateSettings(); + + protected: + // Colliding pairs + Container mPairs; //!< Pairs of colliding primitives + // User mesh interfaces + const MeshInterface* mIMesh0; //!< User-defined mesh interface for object0 + const MeshInterface* mIMesh1; //!< User-defined mesh interface for object1 + // Stats + udword mNbBVBVTests; //!< Number of BV-BV tests + udword mNbPrimPrimTests; //!< Number of Primitive-Primitive tests + udword mNbBVPrimTests; //!< Number of BV-Primitive tests + // Precomputed data + Matrix3x3 mAR; //!< Absolute rotation matrix + Matrix3x3 mR0to1; //!< Rotation from object0 to object1 + Matrix3x3 mR1to0; //!< Rotation from object1 to object0 + Point mT0to1; //!< Translation from object0 to object1 + Point mT1to0; //!< Translation from object1 to object0 + // Dequantization coeffs + Point mCenterCoeff0; + Point mExtentsCoeff0; + Point mCenterCoeff1; + Point mExtentsCoeff1; + // Leaf description + Point mLeafVerts[3]; //!< Triangle vertices + udword mLeafIndex; //!< Triangle index + // Settings + bool mFullBoxBoxTest; //!< Perform full BV-BV tests (true) or SAT-lite tests (false) + bool mFullPrimBoxTest; //!< Perform full Primitive-BV tests (true) or SAT-lite tests (false) + // Internal methods + + // Standard AABB trees + void _Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1); + // Quantized AABB trees + void _Collide(const AABBQuantizedNode* b0, const AABBQuantizedNode* b1, const Point& a, const Point& Pa, const Point& b, const Point& Pb); + // No-leaf AABB trees + void _CollideTriBox(const AABBNoLeafNode* b); + void _CollideBoxTri(const AABBNoLeafNode* b); + void _Collide(const AABBNoLeafNode* a, const AABBNoLeafNode* b); + // Quantized no-leaf AABB trees + void _CollideTriBox(const AABBQuantizedNoLeafNode* b); + void _CollideBoxTri(const AABBQuantizedNoLeafNode* b); + void _Collide(const AABBQuantizedNoLeafNode* a, const AABBQuantizedNoLeafNode* b); + // Overlap tests + void PrimTest(udword id0, udword id1); + inline_ void PrimTestTriIndex(udword id1); + inline_ void PrimTestIndexTri(udword id0); + + inline_ BOOL BoxBoxOverlap(const Point& ea, const Point& ca, const Point& eb, const Point& cb); + inline_ BOOL TriBoxOverlap(const Point& center, const Point& extents); + inline_ BOOL TriTriOverlap(const Point& V0, const Point& V1, const Point& V2, const Point& U0, const Point& U1, const Point& U2); + // Init methods + void InitQuery(const Matrix4x4* world0=null, const Matrix4x4* world1=null); + bool CheckTemporalCoherence(Pair* cache); + + inline_ BOOL Setup(const MeshInterface* mi0, const MeshInterface* mi1) + { + mIMesh0 = mi0; + mIMesh1 = mi1; + + if(!mIMesh0 || !mIMesh1) return FALSE; + + return TRUE; + } + }; + +#endif // __OPC_TREECOLLIDER_H__ diff --git a/Extras/CDTestFramework/Opcode/OPC_TriBoxOverlap.h b/Extras/CDTestFramework/Opcode/OPC_TriBoxOverlap.h new file mode 100644 index 0000000..a9ac2be --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_TriBoxOverlap.h @@ -0,0 +1,356 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + + +//! This macro quickly finds the min & max values among 3 variables +#define FINDMINMAX(x0, x1, x2, min, max) \ + min = max = x0; \ + if(x1max) max=x1; \ + if(x2max) max=x2; + +//! TO BE DOCUMENTED +inline_ BOOL planeBoxOverlap(const Point& normal, const float d, const Point& maxbox) +{ + Point vmin, vmax; + for(udword q=0;q<=2;q++) + { + if(normal[q]>0.0f) { vmin[q]=-maxbox[q]; vmax[q]=maxbox[q]; } + else { vmin[q]=maxbox[q]; vmax[q]=-maxbox[q]; } + } + if((normal|vmin)+d>0.0f) return FALSE; + if((normal|vmax)+d>=0.0f) return TRUE; + + return FALSE; +} + +//! TO BE DOCUMENTED +#define AXISTEST_X01(a, b, fa, fb) \ + min = a*v0.y - b*v0.z; \ + max = a*v2.y - b*v2.z; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.y + fb * extents.z; \ + if(min>rad || max<-rad) return FALSE; + +//! TO BE DOCUMENTED +#define AXISTEST_X2(a, b, fa, fb) \ + min = a*v0.y - b*v0.z; \ + max = a*v1.y - b*v1.z; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.y + fb * extents.z; \ + if(min>rad || max<-rad) return FALSE; + +//! TO BE DOCUMENTED +#define AXISTEST_Y02(a, b, fa, fb) \ + min = b*v0.z - a*v0.x; \ + max = b*v2.z - a*v2.x; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.x + fb * extents.z; \ + if(min>rad || max<-rad) return FALSE; + +//! TO BE DOCUMENTED +#define AXISTEST_Y1(a, b, fa, fb) \ + min = b*v0.z - a*v0.x; \ + max = b*v1.z - a*v1.x; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.x + fb * extents.z; \ + if(min>rad || max<-rad) return FALSE; + +//! TO BE DOCUMENTED +#define AXISTEST_Z12(a, b, fa, fb) \ + min = a*v1.x - b*v1.y; \ + max = a*v2.x - b*v2.y; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.x + fb * extents.y; \ + if(min>rad || max<-rad) return FALSE; + +//! TO BE DOCUMENTED +#define AXISTEST_Z0(a, b, fa, fb) \ + min = a*v0.x - b*v0.y; \ + max = a*v1.x - b*v1.y; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.x + fb * extents.y; \ + if(min>rad || max<-rad) return FALSE; + +// compute triangle edges +// - edges lazy evaluated to take advantage of early exits +// - fabs precomputed (half less work, possible since extents are always >0) +// - customized macros to take advantage of the null component +// - axis vector discarded, possibly saves useless movs +#define IMPLEMENT_CLASS3_TESTS \ + float rad; \ + float min, max; \ + \ + const float fey0 = fabsf(e0.y); \ + const float fez0 = fabsf(e0.z); \ + AXISTEST_X01(e0.z, e0.y, fez0, fey0); \ + const float fex0 = fabsf(e0.x); \ + AXISTEST_Y02(e0.z, e0.x, fez0, fex0); \ + AXISTEST_Z12(e0.y, e0.x, fey0, fex0); \ + \ + const float fey1 = fabsf(e1.y); \ + const float fez1 = fabsf(e1.z); \ + AXISTEST_X01(e1.z, e1.y, fez1, fey1); \ + const float fex1 = fabsf(e1.x); \ + AXISTEST_Y02(e1.z, e1.x, fez1, fex1); \ + AXISTEST_Z0(e1.y, e1.x, fey1, fex1); \ + \ + const Point e2 = mLeafVerts[0] - mLeafVerts[2]; \ + const float fey2 = fabsf(e2.y); \ + const float fez2 = fabsf(e2.z); \ + AXISTEST_X2(e2.z, e2.y, fez2, fey2); \ + const float fex2 = fabsf(e2.x); \ + AXISTEST_Y1(e2.z, e2.x, fez2, fex2); \ + AXISTEST_Z12(e2.y, e2.x, fey2, fex2); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Triangle-Box overlap test using the separating axis theorem. + * This is the code from Tomas Möller, a bit optimized: + * - with some more lazy evaluation (faster path on PC) + * - with a tiny bit of assembly + * - with "SAT-lite" applied if needed + * - and perhaps with some more minor modifs... + * + * \param center [in] box center + * \param extents [in] box extents + * \return true if triangle & box overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL AABBTreeCollider::TriBoxOverlap(const Point& center, const Point& extents) +{ + // Stats + mNbBVPrimTests++; + + // use separating axis theorem to test overlap between triangle and box + // need to test for overlap in these directions: + // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle + // we do not even need to test these) + // 2) normal of the triangle + // 3) crossproduct(edge from tri, {x,y,z}-directin) + // this gives 3x3=9 more tests + + // move everything so that the boxcenter is in (0,0,0) + Point v0, v1, v2; + v0.x = mLeafVerts[0].x - center.x; + v1.x = mLeafVerts[1].x - center.x; + v2.x = mLeafVerts[2].x - center.x; + + // First, test overlap in the {x,y,z}-directions +#ifdef OPC_USE_FCOMI + // find min, max of the triangle in x-direction, and test for overlap in X + if(FCMin3(v0.x, v1.x, v2.x)>extents.x) return FALSE; + if(FCMax3(v0.x, v1.x, v2.x)<-extents.x) return FALSE; + + // same for Y + v0.y = mLeafVerts[0].y - center.y; + v1.y = mLeafVerts[1].y - center.y; + v2.y = mLeafVerts[2].y - center.y; + + if(FCMin3(v0.y, v1.y, v2.y)>extents.y) return FALSE; + if(FCMax3(v0.y, v1.y, v2.y)<-extents.y) return FALSE; + + // same for Z + v0.z = mLeafVerts[0].z - center.z; + v1.z = mLeafVerts[1].z - center.z; + v2.z = mLeafVerts[2].z - center.z; + + if(FCMin3(v0.z, v1.z, v2.z)>extents.z) return FALSE; + if(FCMax3(v0.z, v1.z, v2.z)<-extents.z) return FALSE; +#else + float min,max; + // Find min, max of the triangle in x-direction, and test for overlap in X + FINDMINMAX(v0.x, v1.x, v2.x, min, max); + if(min>extents.x || max<-extents.x) return FALSE; + + // Same for Y + v0.y = mLeafVerts[0].y - center.y; + v1.y = mLeafVerts[1].y - center.y; + v2.y = mLeafVerts[2].y - center.y; + + FINDMINMAX(v0.y, v1.y, v2.y, min, max); + if(min>extents.y || max<-extents.y) return FALSE; + + // Same for Z + v0.z = mLeafVerts[0].z - center.z; + v1.z = mLeafVerts[1].z - center.z; + v2.z = mLeafVerts[2].z - center.z; + + FINDMINMAX(v0.z, v1.z, v2.z, min, max); + if(min>extents.z || max<-extents.z) return FALSE; +#endif + // 2) Test if the box intersects the plane of the triangle + // compute plane equation of triangle: normal*x+d=0 + // ### could be precomputed since we use the same leaf triangle several times + const Point e0 = v1 - v0; + const Point e1 = v2 - v1; + const Point normal = e0 ^ e1; + const float d = -normal|v0; + if(!planeBoxOverlap(normal, d, extents)) return FALSE; + + // 3) "Class III" tests + if(mFullPrimBoxTest) + { + IMPLEMENT_CLASS3_TESTS + } + return TRUE; +} + +//! A dedicated version where the box is constant +inline_ BOOL OBBCollider::TriBoxOverlap() +{ + // Stats + mNbVolumePrimTests++; + + // Hook + const Point& extents = mBoxExtents; + const Point& v0 = mLeafVerts[0]; + const Point& v1 = mLeafVerts[1]; + const Point& v2 = mLeafVerts[2]; + + // use separating axis theorem to test overlap between triangle and box + // need to test for overlap in these directions: + // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle + // we do not even need to test these) + // 2) normal of the triangle + // 3) crossproduct(edge from tri, {x,y,z}-directin) + // this gives 3x3=9 more tests + + // Box center is already in (0,0,0) + + // First, test overlap in the {x,y,z}-directions +#ifdef OPC_USE_FCOMI + // find min, max of the triangle in x-direction, and test for overlap in X + if(FCMin3(v0.x, v1.x, v2.x)>mBoxExtents.x) return FALSE; + if(FCMax3(v0.x, v1.x, v2.x)<-mBoxExtents.x) return FALSE; + + if(FCMin3(v0.y, v1.y, v2.y)>mBoxExtents.y) return FALSE; + if(FCMax3(v0.y, v1.y, v2.y)<-mBoxExtents.y) return FALSE; + + if(FCMin3(v0.z, v1.z, v2.z)>mBoxExtents.z) return FALSE; + if(FCMax3(v0.z, v1.z, v2.z)<-mBoxExtents.z) return FALSE; +#else + float min,max; + // Find min, max of the triangle in x-direction, and test for overlap in X + FINDMINMAX(v0.x, v1.x, v2.x, min, max); + if(min>mBoxExtents.x || max<-mBoxExtents.x) return FALSE; + + FINDMINMAX(v0.y, v1.y, v2.y, min, max); + if(min>mBoxExtents.y || max<-mBoxExtents.y) return FALSE; + + FINDMINMAX(v0.z, v1.z, v2.z, min, max); + if(min>mBoxExtents.z || max<-mBoxExtents.z) return FALSE; +#endif + // 2) Test if the box intersects the plane of the triangle + // compute plane equation of triangle: normal*x+d=0 + // ### could be precomputed since we use the same leaf triangle several times + const Point e0 = v1 - v0; + const Point e1 = v2 - v1; + const Point normal = e0 ^ e1; + const float d = -normal|v0; + if(!planeBoxOverlap(normal, d, mBoxExtents)) return FALSE; + + // 3) "Class III" tests - here we always do full tests since the box is a primitive (not a BV) + { + IMPLEMENT_CLASS3_TESTS + } + return TRUE; +} + +//! ...and another one, jeez +inline_ BOOL AABBCollider::TriBoxOverlap() +{ + // Stats + mNbVolumePrimTests++; + + // Hook + const Point& center = mBox.mCenter; + const Point& extents = mBox.mExtents; + + // use separating axis theorem to test overlap between triangle and box + // need to test for overlap in these directions: + // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle + // we do not even need to test these) + // 2) normal of the triangle + // 3) crossproduct(edge from tri, {x,y,z}-directin) + // this gives 3x3=9 more tests + + // move everything so that the boxcenter is in (0,0,0) + Point v0, v1, v2; + v0.x = mLeafVerts[0].x - center.x; + v1.x = mLeafVerts[1].x - center.x; + v2.x = mLeafVerts[2].x - center.x; + + // First, test overlap in the {x,y,z}-directions +#ifdef OPC_USE_FCOMI + // find min, max of the triangle in x-direction, and test for overlap in X + if(FCMin3(v0.x, v1.x, v2.x)>extents.x) return FALSE; + if(FCMax3(v0.x, v1.x, v2.x)<-extents.x) return FALSE; + + // same for Y + v0.y = mLeafVerts[0].y - center.y; + v1.y = mLeafVerts[1].y - center.y; + v2.y = mLeafVerts[2].y - center.y; + + if(FCMin3(v0.y, v1.y, v2.y)>extents.y) return FALSE; + if(FCMax3(v0.y, v1.y, v2.y)<-extents.y) return FALSE; + + // same for Z + v0.z = mLeafVerts[0].z - center.z; + v1.z = mLeafVerts[1].z - center.z; + v2.z = mLeafVerts[2].z - center.z; + + if(FCMin3(v0.z, v1.z, v2.z)>extents.z) return FALSE; + if(FCMax3(v0.z, v1.z, v2.z)<-extents.z) return FALSE; +#else + float min,max; + // Find min, max of the triangle in x-direction, and test for overlap in X + FINDMINMAX(v0.x, v1.x, v2.x, min, max); + if(min>extents.x || max<-extents.x) return FALSE; + + // Same for Y + v0.y = mLeafVerts[0].y - center.y; + v1.y = mLeafVerts[1].y - center.y; + v2.y = mLeafVerts[2].y - center.y; + + FINDMINMAX(v0.y, v1.y, v2.y, min, max); + if(min>extents.y || max<-extents.y) return FALSE; + + // Same for Z + v0.z = mLeafVerts[0].z - center.z; + v1.z = mLeafVerts[1].z - center.z; + v2.z = mLeafVerts[2].z - center.z; + + FINDMINMAX(v0.z, v1.z, v2.z, min, max); + if(min>extents.z || max<-extents.z) return FALSE; +#endif + // 2) Test if the box intersects the plane of the triangle + // compute plane equation of triangle: normal*x+d=0 + // ### could be precomputed since we use the same leaf triangle several times + const Point e0 = v1 - v0; + const Point e1 = v2 - v1; + const Point normal = e0 ^ e1; + const float d = -normal|v0; + if(!planeBoxOverlap(normal, d, extents)) return FALSE; + + // 3) "Class III" tests - here we always do full tests since the box is a primitive (not a BV) + { + IMPLEMENT_CLASS3_TESTS + } + return TRUE; +} diff --git a/Extras/CDTestFramework/Opcode/OPC_TriTriOverlap.h b/Extras/CDTestFramework/Opcode/OPC_TriTriOverlap.h new file mode 100644 index 0000000..d1968e5 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_TriTriOverlap.h @@ -0,0 +1,295 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +//! if OPC_TRITRI_EPSILON_TEST is true then we do a check (if |dv|b) \ + { \ + const float c=a; \ + a=b; \ + b=c; \ + } + +//! Edge to edge test based on Franlin Antonio's gem: "Faster Line Segment Intersection", in Graphics Gems III, pp. 199-202 +#define EDGE_EDGE_TEST(V0, U0, U1) \ + Bx = U0[i0] - U1[i0]; \ + By = U0[i1] - U1[i1]; \ + Cx = V0[i0] - U0[i0]; \ + Cy = V0[i1] - U0[i1]; \ + f = Ay*Bx - Ax*By; \ + d = By*Cx - Bx*Cy; \ + if((f>0.0f && d>=0.0f && d<=f) || (f<0.0f && d<=0.0f && d>=f)) \ + { \ + const float e=Ax*Cy - Ay*Cx; \ + if(f>0.0f) \ + { \ + if(e>=0.0f && e<=f) return TRUE; \ + } \ + else \ + { \ + if(e<=0.0f && e>=f) return TRUE; \ + } \ + } + +//! TO BE DOCUMENTED +#define EDGE_AGAINST_TRI_EDGES(V0, V1, U0, U1, U2) \ +{ \ + float Bx,By,Cx,Cy,d,f; \ + const float Ax = V1[i0] - V0[i0]; \ + const float Ay = V1[i1] - V0[i1]; \ + /* test edge U0,U1 against V0,V1 */ \ + EDGE_EDGE_TEST(V0, U0, U1); \ + /* test edge U1,U2 against V0,V1 */ \ + EDGE_EDGE_TEST(V0, U1, U2); \ + /* test edge U2,U1 against V0,V1 */ \ + EDGE_EDGE_TEST(V0, U2, U0); \ +} + +//! TO BE DOCUMENTED +#define POINT_IN_TRI(V0, U0, U1, U2) \ +{ \ + /* is T1 completly inside T2? */ \ + /* check if V0 is inside tri(U0,U1,U2) */ \ + float a = U1[i1] - U0[i1]; \ + float b = -(U1[i0] - U0[i0]); \ + float c = -a*U0[i0] - b*U0[i1]; \ + float d0 = a*V0[i0] + b*V0[i1] + c; \ + \ + a = U2[i1] - U1[i1]; \ + b = -(U2[i0] - U1[i0]); \ + c = -a*U1[i0] - b*U1[i1]; \ + const float d1 = a*V0[i0] + b*V0[i1] + c; \ + \ + a = U0[i1] - U2[i1]; \ + b = -(U0[i0] - U2[i0]); \ + c = -a*U2[i0] - b*U2[i1]; \ + const float d2 = a*V0[i0] + b*V0[i1] + c; \ + if(d0*d1>0.0f) \ + { \ + if(d0*d2>0.0f) return TRUE; \ + } \ +} + +//! TO BE DOCUMENTED +BOOL CoplanarTriTri(const Point& n, const Point& v0, const Point& v1, const Point& v2, const Point& u0, const Point& u1, const Point& u2) +{ + float A[3]; + short i0,i1; + /* first project onto an axis-aligned plane, that maximizes the area */ + /* of the triangles, compute indices: i0,i1. */ + A[0] = fabsf(n[0]); + A[1] = fabsf(n[1]); + A[2] = fabsf(n[2]); + if(A[0]>A[1]) + { + if(A[0]>A[2]) + { + i0=1; /* A[0] is greatest */ + i1=2; + } + else + { + i0=0; /* A[2] is greatest */ + i1=1; + } + } + else /* A[0]<=A[1] */ + { + if(A[2]>A[1]) + { + i0=0; /* A[2] is greatest */ + i1=1; + } + else + { + i0=0; /* A[1] is greatest */ + i1=2; + } + } + + /* test all edges of triangle 1 against the edges of triangle 2 */ + EDGE_AGAINST_TRI_EDGES(v0, v1, u0, u1, u2); + EDGE_AGAINST_TRI_EDGES(v1, v2, u0, u1, u2); + EDGE_AGAINST_TRI_EDGES(v2, v0, u0, u1, u2); + + /* finally, test if tri1 is totally contained in tri2 or vice versa */ + POINT_IN_TRI(v0, u0, u1, u2); + POINT_IN_TRI(u0, v0, v1, v2); + + return FALSE; +} + +//! TO BE DOCUMENTED +#define NEWCOMPUTE_INTERVALS(VV0, VV1, VV2, D0, D1, D2, D0D1, D0D2, A, B, C, X0, X1) \ +{ \ + if(D0D1>0.0f) \ + { \ + /* here we know that D0D2<=0.0 */ \ + /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \ + A=VV2; B=(VV0 - VV2)*D2; C=(VV1 - VV2)*D2; X0=D2 - D0; X1=D2 - D1; \ + } \ + else if(D0D2>0.0f) \ + { \ + /* here we know that d0d1<=0.0 */ \ + A=VV1; B=(VV0 - VV1)*D1; C=(VV2 - VV1)*D1; X0=D1 - D0; X1=D1 - D2; \ + } \ + else if(D1*D2>0.0f || D0!=0.0f) \ + { \ + /* here we know that d0d1<=0.0 or that D0!=0.0 */ \ + A=VV0; B=(VV1 - VV0)*D0; C=(VV2 - VV0)*D0; X0=D0 - D1; X1=D0 - D2; \ + } \ + else if(D1!=0.0f) \ + { \ + A=VV1; B=(VV0 - VV1)*D1; C=(VV2 - VV1)*D1; X0=D1 - D0; X1=D1 - D2; \ + } \ + else if(D2!=0.0f) \ + { \ + A=VV2; B=(VV0 - VV2)*D2; C=(VV1 - VV2)*D2; X0=D2 - D0; X1=D2 - D1; \ + } \ + else \ + { \ + /* triangles are coplanar */ \ + return CoplanarTriTri(N1, V0, V1, V2, U0, U1, U2); \ + } \ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Triangle/triangle intersection test routine, + * by Tomas Moller, 1997. + * See article "A Fast Triangle-Triangle Intersection Test", + * Journal of Graphics Tools, 2(2), 1997 + * + * Updated June 1999: removed the divisions -- a little faster now! + * Updated October 1999: added {} to CROSS and SUB macros + * + * int NoDivTriTriIsect(float V0[3],float V1[3],float V2[3], + * float U0[3],float U1[3],float U2[3]) + * + * \param V0 [in] triangle 0, vertex 0 + * \param V1 [in] triangle 0, vertex 1 + * \param V2 [in] triangle 0, vertex 2 + * \param U0 [in] triangle 1, vertex 0 + * \param U1 [in] triangle 1, vertex 1 + * \param U2 [in] triangle 1, vertex 2 + * \return true if triangles overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL AABBTreeCollider::TriTriOverlap(const Point& V0, const Point& V1, const Point& V2, const Point& U0, const Point& U1, const Point& U2) +{ + // Stats + mNbPrimPrimTests++; + + // Compute plane equation of triangle(V0,V1,V2) + Point E1 = V1 - V0; + Point E2 = V2 - V0; + const Point N1 = E1 ^ E2; + const float d1 =-N1 | V0; + // Plane equation 1: N1.X+d1=0 + + // Put U0,U1,U2 into plane equation 1 to compute signed distances to the plane + float du0 = (N1|U0) + d1; + float du1 = (N1|U1) + d1; + float du2 = (N1|U2) + d1; + + // Coplanarity robustness check +#ifdef OPC_TRITRI_EPSILON_TEST + if(fabsf(du0)0.0f && du0du2>0.0f) // same sign on all of them + not equal 0 ? + return FALSE; // no intersection occurs + + // Compute plane of triangle (U0,U1,U2) + E1 = U1 - U0; + E2 = U2 - U0; + const Point N2 = E1 ^ E2; + const float d2=-N2 | U0; + // plane equation 2: N2.X+d2=0 + + // put V0,V1,V2 into plane equation 2 + float dv0 = (N2|V0) + d2; + float dv1 = (N2|V1) + d2; + float dv2 = (N2|V2) + d2; + +#ifdef OPC_TRITRI_EPSILON_TEST + if(fabsf(dv0)0.0f && dv0dv2>0.0f) // same sign on all of them + not equal 0 ? + return FALSE; // no intersection occurs + + // Compute direction of intersection line + const Point D = N1^N2; + + // Compute and index to the largest component of D + float max=fabsf(D[0]); + short index=0; + float bb=fabsf(D[1]); + float cc=fabsf(D[2]); + if(bb>max) max=bb,index=1; + if(cc>max) max=cc,index=2; + + // This is the simplified projection onto L + const float vp0 = V0[index]; + const float vp1 = V1[index]; + const float vp2 = V2[index]; + + const float up0 = U0[index]; + const float up1 = U1[index]; + const float up2 = U2[index]; + + // Compute interval for triangle 1 + float a,b,c,x0,x1; + NEWCOMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,a,b,c,x0,x1); + + // Compute interval for triangle 2 + float d,e,f,y0,y1; + NEWCOMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,d,e,f,y0,y1); + + const float xx=x0*x1; + const float yy=y0*y1; + const float xxyy=xx*yy; + + float isect1[2], isect2[2]; + + float tmp=a*xxyy; + isect1[0]=tmp+b*x1*yy; + isect1[1]=tmp+c*x0*yy; + + tmp=d*xxyy; + isect2[0]=tmp+e*xx*y1; + isect2[1]=tmp+f*xx*y0; + + SORT(isect1[0],isect1[1]); + SORT(isect2[0],isect2[1]); + + if(isect1[1]HasPosLeaf()) mTouchedPrimitives->Add(node->GetPosPrimitive()); \ + else _Dump(node->GetPos()); \ + \ + if(ContactFound()) return; \ + \ + if(node->HasNegLeaf()) mTouchedPrimitives->Add(node->GetNegPrimitive()); \ + else _Dump(node->GetNeg()); \ +} + +#define IMPLEMENT_LEAFDUMP(type) \ +void VolumeCollider::_Dump(const type* node) \ +{ \ + if(node->IsLeaf()) \ + { \ + mTouchedPrimitives->Add(node->GetPrimitive()); \ + } \ + else \ + { \ + _Dump(node->GetPos()); \ + \ + if(ContactFound()) return; \ + \ + _Dump(node->GetNeg()); \ + } \ +} + +IMPLEMENT_NOLEAFDUMP(AABBNoLeafNode) +IMPLEMENT_NOLEAFDUMP(AABBQuantizedNoLeafNode) + +IMPLEMENT_LEAFDUMP(AABBCollisionNode) +IMPLEMENT_LEAFDUMP(AABBQuantizedNode) diff --git a/Extras/CDTestFramework/Opcode/OPC_VolumeCollider.h b/Extras/CDTestFramework/Opcode/OPC_VolumeCollider.h new file mode 100644 index 0000000..e0eb626 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/OPC_VolumeCollider.h @@ -0,0 +1,147 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains base volume collider class. + * \file OPC_VolumeCollider.h + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_VOLUMECOLLIDER_H__ +#define __OPC_VOLUMECOLLIDER_H__ + + struct OPCODE_API VolumeCache + { + VolumeCache() : Model(null) {} + ~VolumeCache() {} + + Container TouchedPrimitives; //!< Indices of touched primitives + const BaseModel* Model; //!< Owner + }; + + class OPCODE_API VolumeCollider : public Collider + { + public: + // Constructor / Destructor + VolumeCollider(); + virtual ~VolumeCollider() = 0; + + // Collision report + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of touched primitives after a collision query. + * \see GetContactStatus() + * \see GetTouchedPrimitives() + * \return the number of touched primitives + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbTouchedPrimitives() const { return mTouchedPrimitives ? mTouchedPrimitives->GetNbEntries() : 0; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the list of touched primitives after a collision query. + * \see GetContactStatus() + * \see GetNbTouchedPrimitives() + * \return the list of touched primitives (primitive indices) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const udword* GetTouchedPrimitives() const { return mTouchedPrimitives ? mTouchedPrimitives->GetEntries() : null; } + + // Stats + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of Volume-BV overlap tests after a collision query. + * \see GetNbVolumePrimTests() + * \return the number of Volume-BV tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbVolumeBVTests() const { return mNbVolumeBVTests; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of Volume-Triangle overlap tests after a collision query. + * \see GetNbVolumeBVTests() + * \return the number of Volume-Triangle tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbVolumePrimTests() const { return mNbVolumePrimTests; } + + // Settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider. + * \return null if everything is ok, else a string describing the problem + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(Collider) const char* ValidateSettings(); + + protected: + // Touched primitives + Container* mTouchedPrimitives; //!< List of touched primitives + + // Dequantization coeffs + Point mCenterCoeff; + Point mExtentsCoeff; + // Stats + udword mNbVolumeBVTests; //!< Number of Volume-BV tests + udword mNbVolumePrimTests; //!< Number of Volume-Primitive tests + // Internal methods + void _Dump(const AABBCollisionNode* node); + void _Dump(const AABBNoLeafNode* node); + void _Dump(const AABBQuantizedNode* node); + void _Dump(const AABBQuantizedNoLeafNode* node); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Initializes a query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(Collider) inline_ void InitQuery() + { + // Reset stats & contact status + mNbVolumeBVTests = 0; + mNbVolumePrimTests = 0; + Collider::InitQuery(); + } + + inline_ BOOL IsCacheValid(VolumeCache& cache) + { + // We're going to do a volume-vs-model query. + if(cache.Model!=mCurrentModel) + { + // Cached list was for another model so we can't keep it + // Keep track of new owner and reset cache + cache.Model = mCurrentModel; + return FALSE; + } + else + { + // Same models, no problem + return TRUE; + } + } + }; + +#endif // __OPC_VOLUMECOLLIDER_H__ diff --git a/Extras/CDTestFramework/Opcode/Opcode.cpp b/Extras/CDTestFramework/Opcode/Opcode.cpp new file mode 100644 index 0000000..68511a6 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Opcode.cpp @@ -0,0 +1,74 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Main file for Opcode.dll. + * \file Opcode.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* + Finding a good name is difficult! + Here's the draft for this lib.... Spooky, uh? + + VOID? Very Optimized Interference Detection + ZOID? Zappy's Optimized Interference Detection + CID? Custom/Clever Interference Detection + AID / ACID! Accurate Interference Detection + QUID? Quick Interference Detection + RIDE? Realtime Interference DEtection + WIDE? Wicked Interference DEtection (....) + GUID! + KID ! k-dop interference detection :) + OPCODE! OPtimized COllision DEtection +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "Stdafx.h" + +bool Opcode::InitOpcode() +{ + Log("// Initializing OPCODE\n\n"); +// LogAPIInfo(); + return true; +} + +void ReleasePruningSorters(); +bool Opcode::CloseOpcode() +{ + Log("// Closing OPCODE\n\n"); + + ReleasePruningSorters(); + + return true; +} + +#ifdef ICE_MAIN + +void ModuleAttach(HINSTANCE hinstance) +{ +} + +void ModuleDetach() +{ +} + +#endif \ No newline at end of file diff --git a/Extras/CDTestFramework/Opcode/Opcode.dsp b/Extras/CDTestFramework/Opcode/Opcode.dsp new file mode 100644 index 0000000..ddadef6 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Opcode.dsp @@ -0,0 +1,517 @@ +# Microsoft Developer Studio Project File - Name="Opcode" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=Opcode - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Opcode.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Opcode.mak" CFG="Opcode - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Opcode - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Opcode - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Opcode - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPCODE_EXPORTS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPCODE_EXPORTS" /Yu"stdafx.h" /FD /QIfist /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 /nologo /dll /machine:I386 +# SUBTRACT LINK32 /debug + +!ELSEIF "$(CFG)" == "Opcode - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPCODE_EXPORTS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPCODE_EXPORTS" /FR /Yu"stdafx.h" /FD /GZ /QIfist /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /dll /incremental:no /debug /machine:I386 /out:"Debug\Opcode_D.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "Opcode - Win32 Release" +# Name "Opcode - Win32 Debug" +# Begin Group "API" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\OPC_BaseModel.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_BaseModel.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_HybridModel.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_HybridModel.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_IceHook.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_Model.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_Model.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_Settings.h +# End Source File +# Begin Source File + +SOURCE=.\Opcode.cpp +# End Source File +# Begin Source File + +SOURCE=.\Opcode.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"stdafx.h" +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Trees" + +# PROP Default_Filter "" +# Begin Group "Collision queries" + +# PROP Default_Filter "" +# Begin Group "Base colliders" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\OPC_Collider.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_Collider.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_VolumeCollider.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_VolumeCollider.h +# End Source File +# End Group +# Begin Group "Standard colliders" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\OPC_AABBCollider.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_AABBCollider.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_LSSCollider.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_LSSCollider.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_OBBCollider.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_OBBCollider.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_PlanesCollider.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_PlanesCollider.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_RayCollider.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_RayCollider.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_SphereCollider.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_SphereCollider.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_TreeCollider.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_TreeCollider.h +# End Source File +# End Group +# End Group +# Begin Source File + +SOURCE=.\OPC_AABBTree.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_AABBTree.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_Common.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_Common.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_MeshInterface.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_MeshInterface.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_OptimizedTree.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_OptimizedTree.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_TreeBuilders.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_TreeBuilders.h +# End Source File +# End Group +# Begin Group "Overlap tests" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\OPC_BoxBoxOverlap.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_LSSAABBOverlap.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_LSSTriOverlap.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_PlanesAABBOverlap.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_PlanesTriOverlap.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_RayAABBOverlap.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_RayTriOverlap.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_SphereAABBOverlap.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_SphereTriOverlap.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_TriBoxOverlap.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_TriTriOverlap.h +# End Source File +# End Group +# Begin Group "SweepAndPrune" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\OPC_BoxPruning.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_BoxPruning.h +# End Source File +# Begin Source File + +SOURCE=.\OPC_SweepAndPrune.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_SweepAndPrune.h +# End Source File +# End Group +# Begin Group "Usages" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\OPC_Picking.cpp +# End Source File +# Begin Source File + +SOURCE=.\OPC_Picking.h +# End Source File +# End Group +# Begin Group "Ice" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\Ice\IceAABB.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceAABB.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceAxes.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceBoundingSphere.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceContainer.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceContainer.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceFPU.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceHPoint.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceHPoint.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceIndexedTriangle.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceIndexedTriangle.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceLSS.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceMatrix3x3.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceMatrix3x3.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceMatrix4x4.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceMatrix4x4.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceMemoryMacros.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceOBB.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceOBB.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IcePairs.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IcePlane.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ice\IcePlane.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IcePoint.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ice\IcePoint.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IcePreprocessor.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceRandom.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceRandom.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceRay.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceRay.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceRevisitedRadix.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceRevisitedRadix.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceSegment.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceSegment.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceTriangle.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceTriangle.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceTrilist.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceTypes.h +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceUtils.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ice\IceUtils.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\ReadMe.txt +# End Source File +# End Target +# End Project diff --git a/Extras/CDTestFramework/Opcode/Opcode.dsw b/Extras/CDTestFramework/Opcode/Opcode.dsw new file mode 100644 index 0000000..bc37a2c --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Opcode.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Opcode"=.\Opcode.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/Extras/CDTestFramework/Opcode/Opcode.h b/Extras/CDTestFramework/Opcode/Opcode.h new file mode 100644 index 0000000..094b579 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Opcode.h @@ -0,0 +1,99 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Main file for Opcode.dll. + * \file Opcode.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPCODE_H__ +#define __OPCODE_H__ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Compilation messages +#if defined(OPCODE_EXPORTS) + #pragma message("Compiling OPCODE") +#elif !defined(OPCODE_EXPORTS) + #pragma message("Using OPCODE") + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Automatic linking + #ifndef BAN_OPCODE_AUTOLINK + #ifdef _DEBUG + #pragma comment(lib, "Opcode_D.lib") + #else + #pragma comment(lib, "Opcode.lib") + #endif + #endif +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Preprocessor +#ifndef ICE_NO_DLL + #ifdef OPCODE_EXPORTS + #define OPCODE_API __declspec(dllexport) + #else + #define OPCODE_API __declspec(dllimport) + #endif +#else + #define OPCODE_API +#endif + + #include "OPC_IceHook.h" + + namespace Opcode + { + // Bulk-of-the-work + #include "OPC_Settings.h" + #include "OPC_Common.h" + #include "OPC_MeshInterface.h" + // Builders + #include "OPC_TreeBuilders.h" + // Trees + #include "OPC_AABBTree.h" + #include "OPC_OptimizedTree.h" + // Models + #include "OPC_BaseModel.h" + #include "OPC_Model.h" + #include "OPC_HybridModel.h" + // Colliders + #include "OPC_Collider.h" + #include "OPC_VolumeCollider.h" + #include "OPC_TreeCollider.h" + #include "OPC_RayCollider.h" + #include "OPC_SphereCollider.h" + #include "OPC_OBBCollider.h" + #include "OPC_AABBCollider.h" + #include "OPC_LSSCollider.h" + #include "OPC_PlanesCollider.h" + // Usages + #include "OPC_Picking.h" + // Sweep-and-prune + #include "OPC_BoxPruning.h" + #include "OPC_SweepAndPrune.h" + #include "OPC_ArraySAP.h" + + FUNCTION OPCODE_API bool InitOpcode(); + FUNCTION OPCODE_API bool CloseOpcode(); + } + +#endif // __OPCODE_H__ diff --git a/Extras/CDTestFramework/Opcode/Opcode.sln b/Extras/CDTestFramework/Opcode/Opcode.sln new file mode 100644 index 0000000..269cc7d --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Opcode.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Opcode", "Opcode.vcproj", "{4B23B91D-D4D6-4ED6-9583-FE6CC3730F51}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {4B23B91D-D4D6-4ED6-9583-FE6CC3730F51}.Debug.ActiveCfg = Debug|Win32 + {4B23B91D-D4D6-4ED6-9583-FE6CC3730F51}.Debug.Build.0 = Debug|Win32 + {4B23B91D-D4D6-4ED6-9583-FE6CC3730F51}.Release.ActiveCfg = Release|Win32 + {4B23B91D-D4D6-4ED6-9583-FE6CC3730F51}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/Extras/CDTestFramework/Opcode/Opcode.vcproj b/Extras/CDTestFramework/Opcode/Opcode.vcproj new file mode 100644 index 0000000..1683de8 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/Opcode.vcproj @@ -0,0 +1,1416 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/CDTestFramework/Opcode/ReadMe.txt b/Extras/CDTestFramework/Opcode/ReadMe.txt new file mode 100644 index 0000000..01ad45b --- /dev/null +++ b/Extras/CDTestFramework/Opcode/ReadMe.txt @@ -0,0 +1,188 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + + + OPCODE distribution 1.3 (june 2003) + ----------------------- + + New in Opcode 1.3: + - fixed the divide by 0 bug that was happening when all centers where located on a coordinate axis (thanks to Jorrit T) + - linearized "complete" vanilla AABB trees + - ANSI-compliant "for" loops (for the ones porting it to Linux...) + - callbacks & pointers moved to mesh interface + - support for triangle & vertex strides + - optimized the sphere-triangle overlap code a bit + - dynamic trees (refit) + - more builders + - ValidateSubdivision in builders + - LSS collider + - primitive-bv tests can now be skipped in most volume queries + - temporal coherence now also works for airborne objects + - temporal coherence completed for boxes / all contacts, LSS, etc + - ray-collider now uses a callback + - some common "usages" have been introduced (only picking for now) + - SPLIT_COMPLETE removed (now implicitely using mLimit = 1) + - hybrid collision models + - sweep-and-prune code added, moved from my old Z-Collide lib + - it now works with meshes made of only 1 triangle (except in mesh-mesh case!) + + Disclaimer: + + - I forced myself to actually *do* the release today no matter what. Else it would never have been done. That's + why the code may not be very polished. I also removed a *lot* of things (more usages, distance queries, etc...) + that weren't ready for prime-time (or that were linked to too many of my supporting libs) + + - Some comments may also be obsolete here and there. The old User Manual for Opcode 1.2 may not fit version 1.3 + either, since there's a new "mesh interface" to support strides, etc. + + - Everything in the "Ice" directory has been hacked out of my engine and edited until everything compiled. Don't + expect anything out there to be cute or something. In particular, some CPP files are not even included when not + needed, so you can expect some linker errors if you try messing around with them... + + Otherwise, it should be just like previous version, only better. In particular, hybrid models can be very + memory-friendly (sometimes using like 10 times less ram than the best trees from version 1.2). The possible + speed hit is often invisible (if it even exists), especially using temporal coherence in "all contacts" mode. + (Admittedly, this depends on your particular usage pattern / what you do on collided triangles). + + The sweep-and-prune code is similar to the "vanilla" version found in V-Collide (but that one's better IMHO...) + The simple "radix" version is often just as good, see for yourself. + + OPCODE distribution 1.2 (august 2002) + ----------------------- + + New in Opcode 1.2: + - new VolumeCollider base class + - simplified callback setup + - you can now use callbacks or pointers (setup at compile time) + - destination array not needed anymore in the RayCollider (faster in-out tests) + - renamed classes: AABBRayCollider => RayCollider, AABBSphereCollider => SphereCollider + - the sphere query now only returns a list of faces (extra info discarded). On the other hand it's a lot faster. + - OBB, AABB and planes queries. Original OBB and AABB queries contributed by Erwin de Vries. + - cosmetic changes in OPC_BoxBoxOverlap.h contributed by Gottfried Chen + - some inlining problems fixed + - faster ray-mesh tests using the separating axis theorem + - new split value in AABB tree construction (contributed by Igor Kravtchenko). Provides faster queries most of the time. + - improved temporal coherence for sphere & AABB queries (works in "All contacts" mode) + + Notes: + + - Everything in the "Ice code" directory (in VC++) is basically copy-pasted from my engine, with a lot + of code removed until there was no link error anymore. Don't expect those files to be cute or anything, + they've never been meant to be released and they're often updated/modified/messy. + - Some experimental features have been removed as well. Else I would never have released the 1.2... + - Not as polished/optimal as I would like it to be, but that's life. I promised myself to release it + before october 2002 (one YEAR later ?!).... That's the only reason why it's there. + - Some people reported ColDet was faster. Uh, come on. They were using Opcode in + "All contacts" mode whereas ColDet was doing "first contact"... + + OPCODE distribution 1.1 (october 2001) + ----------------------- + + New in Opcode 1.1: + - stabbing queries + - sphere queries + - abtract base class for colliders + - settings validation methods + - compilation flags now grouped in OPC_Settings.h + - smaller files, new VC++ virtual dirs (cleaner) + + Notes: + + - "override(baseclass)" is a personal cosmetic thing. It's the same as "virtual", but provides more info. + - I code in 1600*1200, so some lines may look a bit long.. + - This version is not as polished as the previous one due to lack of time. The stabbing & sphere queries + can still be optimized: for example by trying other atomic overlap tests. I'm using my first ray-AABB + code, but the newer one seems better. Tim Schröder's one is good as well. See: www.codercorner.com/RayAABB.cpp + - The trees can easily be compressed even more, I save this for later (lack of time, lack of time!) + - I removed various tests before releasing this one: + - a separation line, a.k.a. "front" in QuickCD, because gains were unclear + - distance queries in a PQP style, because it was way too slow + - support for deformable models, too slow as well + - You can easily use Opcode to do your player-vs-world collision detection, in a Nettle/Telemachos way. + If someone out there wants to donate some art / level for the cause, I'd be glad to release a demo. (current + demo uses copyrighted art I'm not allowed to spread) + - Sorry for the lack of real docs and/or solid examples. I just don't have enough time. + + OPCODE distribution 1.0 (march 2001) + ----------------------- + + - First release + + =============================================================================== + + WHAT ? + + OPCODE means OPtimized COllision DEtection. + So this is a collision detection package similar to RAPID. Here's a + quick list of features: + + - C++ interface, developed for Windows systems using VC++ 6.0 + - Works on arbitrary meshes (convex or non-convex), even polygon soups + - Current implementation uses AABB-trees + - Introduces Primitive-BV overlap tests during recursive collision queries (whereas + standard libraries only rely on Primitive-Primitive and BV-BV tests) + - Introduces no-leaf trees, i.e. collision trees whose leaf nodes have been removed + - Supports collision queries on quantized trees (decompressed on-the-fly) + - Supports "first contact" or "all contacts" modes (à la RAPID) + - Uses temporal coherence for "first contact" mode (~10 to 20 times faster, useful + in rigid body simulation during bisection) + - Memory footprint is 7.2 times smaller than RAPID's one, which is ideal for console + games with limited ram (actually, if you use the unmodified RAPID code using double + precision, it's more like 13 times smaller...) + - And yet it often runs faster than RAPID (according to RDTSC, sometimes more than 5 + times faster when objects are deeply overlapping) + - Performance is usually close to RAPID's one in close-proximity situations + - Stabbing, planes & volume queries (sphere, AABB, OBB, LSS) + - Sweep-and-prune + - Now works with deformable meshes + - Hybrid trees + + + What it can be used for: + - standard mesh-mesh collision detection (similar to RAPID, SOLID, QuickCD, PQP, ColDet...) + - N-body collisions (similar to V-Collide) + - camera-vs-world collisions (similar to Telemachos/Paul Nettle/Stan Melax articles) + - shadow feelers to speed up lightmap computations + - in-out tests to speed up voxelization processes + - picking + - rigid body simulation + - view frustum culling + - etc + + WHY ? + + - Because RAPID uses too many bytes. + - Because the idea was nice... + + WHEN ? + + It's been coded in march 2001 following a thread on the GD-Algorithms list. + + GDAlgorithms-list mailing list + GDAlgorithms-list@lists.sourceforge.net + http://lists.sourceforge.net/lists/listinfo/gdalgorithms-list + + WHO ? + + Pierre Terdiman + June, 1, 2003 + + p.terdiman@wanadoo.fr + p.terdiman@codercorner.com + + http://www.codercorner.com + http://www.codercorner.com/Opcode.htm diff --git a/Extras/CDTestFramework/Opcode/StdAfx.cpp b/Extras/CDTestFramework/Opcode/StdAfx.cpp new file mode 100644 index 0000000..632a740 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/StdAfx.cpp @@ -0,0 +1,19 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +//#define ICE_MAIN +#include "Stdafx.h" diff --git a/Extras/CDTestFramework/Opcode/StdAfx.h b/Extras/CDTestFramework/Opcode/StdAfx.h new file mode 100644 index 0000000..4b30a04 --- /dev/null +++ b/Extras/CDTestFramework/Opcode/StdAfx.h @@ -0,0 +1,33 @@ +/* + * OPCODE - Optimized Collision Detection + * http://www.codercorner.com/Opcode.htm + * + * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +#if !defined(AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_) +#define AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// Insert your headers here +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include "Opcode.h" + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_) diff --git a/Extras/CDTestFramework/OpcodeArraySAPTest.cpp b/Extras/CDTestFramework/OpcodeArraySAPTest.cpp new file mode 100644 index 0000000..bfea328 --- /dev/null +++ b/Extras/CDTestFramework/OpcodeArraySAPTest.cpp @@ -0,0 +1,215 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 "stdafx.h" +#include "OpcodeArraySAPTest.h" +#include "RenderingHelpers.h" +#include "GLFontRenderer.h" + +static udword gNbCreatedPairs; +static udword gNbDeletedPairs; +static udword gTotalNbPairs; + +static void* CBData = (void*)0x12345678; +static void* PairUserData = (void*)0xDeadDead; + +static void* CreatePairCB(const void* object0, const void* object1, void* user_data) +{ + assert(user_data==CBData); + + gNbCreatedPairs++; + return PairUserData; +} + +static void DeletePairCB(const void* object0, const void* object1, void* user_data, void* pair_user_data) +{ + assert(user_data==CBData); + assert(pair_user_data==PairUserData); + + gNbDeletedPairs++; +} + +OpcodeArraySAPTest::OpcodeArraySAPTest(int numBoxes) : + mBar (null), + mNbBoxes (numBoxes), + mBoxes (null), + mHandles (null), + mBoxTime (null), + mAmplitude (100.0f) +{ +} + +OpcodeArraySAPTest::~OpcodeArraySAPTest() +{ + Release(); +} + +void OpcodeArraySAPTest::Init() +{ + m_firstTime = true; + + SRand(0); + mBoxes = new AABB[mNbBoxes]; + mBoxTime = new float[mNbBoxes]; + mHandles = new void*[mNbBoxes]; + for(udword i=0;i +#include "GL/glut.h" + +#include "RenderingHelpers.h" + +//////////////////////// + +void DrawLine(const Point& p0, const Point& p1, const Point& color, float line_width) +{ + glDisable(GL_LIGHTING); + glLineWidth(line_width); + glColor4f(color.x, color.y, color.z, 1.0f); + Point tmp[] = {p0, p1}; + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(Point), &tmp[0].x); + glDrawArrays(GL_LINES, 0, 2); + glDisableClientState(GL_VERTEX_ARRAY); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glEnable(GL_LIGHTING); +} + +void DrawTriangle(const Point& p0, const Point& p1, const Point& p2, const Point& color) +{ +// glDisable(GL_LIGHTING); + glColor4f(color.x, color.y, color.z, 1.0f); + Point tmp[] = {p0, p1, p2}; + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(Point), &tmp[0].x); + glDrawArrays(GL_TRIANGLES, 0, 3); + glDisableClientState(GL_VERTEX_ARRAY); +// glColor4f(1.0f, 1.0f, 1.0f, 1.0f); +// glEnable(GL_LIGHTING); +} + + +//////////////////////// + +static void SetupGLMatrix(const Point& pos) +{ + float glmat[16]; //4x4 column major matrix for OpenGL. + glmat[0] = 1.0f; + glmat[1] = 0.0f; + glmat[2] = 0.0f; + glmat[3] = 0.0f; + + glmat[4] = 0.0f; + glmat[5] = 1.0f; + glmat[6] = 0.0f; + glmat[7] = 0.0f; + + glmat[8] = 0.0f; + glmat[9] = 0.0f; + glmat[10] = 1.0f; + glmat[11] = 0.0f; + + glmat[12] = pos.x; + glmat[13] = pos.y; + glmat[14] = pos.z; + glmat[15] = 1.0f; + + glMultMatrixf(glmat); +} + +void SetupGLMatrix(const Point& pos, const Matrix3x3& rot) +{ + float glmat[16]; //4x4 column major matrix for OpenGL. + glmat[0] = rot.m[0][0]; + glmat[1] = rot.m[0][1]; + glmat[2] = rot.m[0][2]; + glmat[3] = 0.0f; + + glmat[4] = rot.m[1][0]; + glmat[5] = rot.m[1][1]; + glmat[6] = rot.m[1][2]; + glmat[7] = 0.0f; + + glmat[8] = rot.m[2][0]; + glmat[9] = rot.m[2][1]; + glmat[10] = rot.m[2][2]; + glmat[11] = 0.0f; + + glmat[12] = pos.x; + glmat[13] = pos.y; + glmat[14] = pos.z; + glmat[15] = 1.0f; + + glMultMatrixf(glmat); +} + +void SetupGLMatrix(const Matrix4x4& world) +{ + SetupGLMatrix(world.GetTrans(), world); +} + +//////////////////////// + +static void RenderSphere(float radius) +{ + glutSolidSphere(radius, 12, 12); // Radius / slices / stacks +} + +void DrawSphere(const Sphere& sphere) +{ + glPushMatrix(); + SetupGLMatrix(sphere.mCenter); + RenderSphere(sphere.mRadius); + glPopMatrix(); +} + +//////////////////////// + +static void RenderBox(int size) +{ + glutSolidCube(size); +} + +void DrawOBB(const OBB& obb) +{ + glPushMatrix(); + SetupGLMatrix(obb.mCenter, obb.mRot); + glScalef(obb.mExtents.x, obb.mExtents.y, obb.mExtents.z); + RenderBox(2); + glPopMatrix(); +} + +//////////////////////// + +static float gCylinderData[]={ + 1.0f,0.0f,1.0f,1.0f,0.0f,1.0f,1.0f,0.0f,0.0f,1.0f,0.0f,0.0f, + 0.866025f,0.500000f,1.0f,0.866025f,0.500000f,1.0f,0.866025f,0.500000f,0.0f,0.866025f,0.500000f,0.0f, + 0.500000f,0.866025f,1.0f,0.500000f,0.866025f,1.0f,0.500000f,0.866025f,0.0f,0.500000f,0.866025f,0.0f, + -0.0f,1.0f,1.0f,-0.0f,1.0f,1.0f,-0.0f,1.0f,0.0f,-0.0f,1.0f,0.0f, + -0.500000f,0.866025f,1.0f,-0.500000f,0.866025f,1.0f,-0.500000f,0.866025f,0.0f,-0.500000f,0.866025f,0.0f, + -0.866025f,0.500000f,1.0f,-0.866025f,0.500000f,1.0f,-0.866025f,0.500000f,0.0f,-0.866025f,0.500000f,0.0f, + -1.0f,-0.0f,1.0f,-1.0f,-0.0f,1.0f,-1.0f,-0.0f,0.0f,-1.0f,-0.0f,0.0f, + -0.866025f,-0.500000f,1.0f,-0.866025f,-0.500000f,1.0f,-0.866025f,-0.500000f,0.0f,-0.866025f,-0.500000f,0.0f, + -0.500000f,-0.866025f,1.0f,-0.500000f,-0.866025f,1.0f,-0.500000f,-0.866025f,0.0f,-0.500000f,-0.866025f,0.0f, + 0.0f,-1.0f,1.0f,0.0f,-1.0f,1.0f,0.0f,-1.0f,0.0f,0.0f,-1.0f,0.0f, + 0.500000f,-0.866025f,1.0f,0.500000f,-0.866025f,1.0f,0.500000f,-0.866025f,0.0f,0.500000f,-0.866025f,0.0f, + 0.866026f,-0.500000f,1.0f,0.866026f,-0.500000f,1.0f,0.866026f,-0.500000f,0.0f,0.866026f,-0.500000f,0.0f, + 1.0f,0.0f,1.0f,1.0f,0.0f,1.0f,1.0f,0.0f,0.0f,1.0f,0.0f,0.0f +}; + +static float gCylinderDataCapsTop[]={ + 0.866026f,-0.500000f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.000000f,1.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.500000f,-0.866025f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.500000f,-0.866025f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.000000f,1.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.000000f,-1.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.000000f,-1.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.000000f,1.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + -0.500000f,-0.866025f,1.000000f,0.000000f,1.000000f,1.000000f, + -0.500000f,-0.866025f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.000000f,1.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + -0.866025f,-0.500000f,1.000000f,0.000000f,1.000000f,1.000000f, + -0.866025f,-0.500000f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.000000f,1.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + -1.000000f,-0.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + -1.000000f,-0.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.000000f,1.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + -0.866025f,0.500000f,1.000000f,0.000000f,1.000000f,1.000000f, + -0.866025f,0.500000f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.000000f,1.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + -0.500000f,0.866025f,1.000000f,0.000000f,1.000000f,1.000000f, + -0.500000f,0.866025f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.000000f,1.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + -0.000000f,1.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + -0.000000f,1.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.000000f,1.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.500000f,0.866025f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.500000f,0.866025f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.000000f,1.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.866025f,0.500000f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.866025f,0.500000f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.000000f,1.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + 1.000000f,0.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + 1.000000f,0.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.000000f,1.000000f,1.000000f,0.000000f,1.000000f,1.000000f, + 0.866026f,-0.500000f,1.000000f,0.000000f,1.000000f,1.000000f, +}; + +static float gCylinderDataCapsBottom[]={ + 1.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.866025f,0.500000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.866025f,0.500000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.500000f,0.866025f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.500000f,0.866025f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + -0.000000f,1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + -0.000000f,1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + -0.500000f,0.866025f,0.000000f,0.000000f,-1.000000f,0.000000f, + -0.500000f,0.866025f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + -0.866025f,0.500000f,0.000000f,0.000000f,-1.000000f,0.000000f, + -0.866025f,0.500000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + -1.000000f,-0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + -1.000000f,-0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + -0.866025f,-0.500000f,0.000000f,0.000000f,-1.000000f,0.000000f, + -0.866025f,-0.500000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + -0.500000f,-0.866025f,0.000000f,0.000000f,-1.000000f,0.000000f, + -0.500000f,-0.866025f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.500000f,-0.866025f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.500000f,-0.866025f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.866026f,-0.500000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.866026f,-0.500000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 0.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, + 1.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f, +}; + +static void RenderCylinder() +{ + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glVertexPointer(3, GL_FLOAT, 2*3*sizeof(float), gCylinderData); + glNormalPointer(GL_FLOAT, 2*3*sizeof(float), gCylinderData+3); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 13*2); + + glVertexPointer(3, GL_FLOAT, 2*3*sizeof(float), gCylinderDataCapsTop); + glNormalPointer(GL_FLOAT, 2*3*sizeof(float), gCylinderDataCapsTop+3); + glDrawArrays(GL_TRIANGLES, 0, 36); + + glVertexPointer(3, GL_FLOAT, 2*3*sizeof(float), gCylinderDataCapsBottom); + glNormalPointer(GL_FLOAT, 2*3*sizeof(float), gCylinderDataCapsBottom+3); + glDrawArrays(GL_TRIANGLES, 0, 36); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); +} + +void DrawCapsule(const Matrix4x4& world, const Point& p0, const Point& p1, float r) +{ + const float h = p0.Distance(p1); + + glPushMatrix(); + SetupGLMatrix(world); + + glPushMatrix(); + glTranslatef(0.0f, h*0.5f, 0.0f); + RenderSphere(r); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(0.0f,-h*0.5f, 0.0f); + RenderSphere(r); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(0.0f,h*0.5f, 0.0f); + glScalef(r,h,r); + glRotatef(90.0f,1.0f,0.0f,0.0f); + RenderCylinder(); + glPopMatrix(); + + glPopMatrix(); +} + + + +#ifdef TOSEE +#include "NxPhysics.h" +#include "DrawObjects.h" + +#include + +static float gPlaneData[]={ + -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f +}; + + +static void RenderPlane() +{ + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glVertexPointer(3, GL_FLOAT, 2*3*sizeof(float), gPlaneData); + glNormalPointer(GL_FLOAT, 2*3*sizeof(float), gPlaneData+3); + glDrawArrays(GL_TRIANGLES, 0, 6); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); +} + +void SetupGLMatrix(const NxVec3& pos, const NxMat33& orient) +{ + float glmat[16]; //4x4 column major matrix for OpenGL. + orient.getColumnMajorStride4(&(glmat[0])); + pos.get(&(glmat[12])); + + //clear the elements we don't need: + glmat[3] = glmat[7] = glmat[11] = 0.0f; + glmat[15] = 1.0f; + + glMultMatrixf(&(glmat[0])); +} + +void DrawLine(const NxVec3& p0, const NxVec3& p1, const NxVec3& color, float lineWidth) +{ + glDisable(GL_LIGHTING); + glLineWidth(lineWidth); + glColor4f(color.x, color.y, color.z, 1.0f); + NxVec3 av3LineEndpoints[] = {p0, p1}; + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(NxVec3), &av3LineEndpoints[0].x); + glDrawArrays(GL_LINES, 0, 2); + glDisableClientState(GL_VERTEX_ARRAY); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glEnable(GL_LIGHTING); +} + +void DrawTriangle(const NxVec3& p0, const NxVec3& p1, const NxVec3& p2, const NxVec3& color) +{ + glDisable(GL_LIGHTING); + glColor4f(color.x, color.y, color.z, 1.0f); + NxVec3 av3LineEndpoints[] = {p0, p1, p2}; + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(NxVec3), &av3LineEndpoints[0].x); + glDrawArrays(GL_TRIANGLES, 0, 3); + glDisableClientState(GL_VERTEX_ARRAY); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glEnable(GL_LIGHTING); +} + +void DrawCircle(NxU32 nbSegments, const NxMat34& matrix, const NxVec3& color, const NxF32 radius, const bool semicircle) +{ + NxF32 step = NxTwoPiF32/NxF32(nbSegments); + NxU32 segs = nbSegments; + if(semicircle) + { + segs /= 2; + } + + for(NxU32 i=0;igetGlobalPose(); + NxPlaneShape* planeShape = plane->isPlane(); + NxPlane p = planeShape->getPlane(); + pose.t.x += p.d; + pose.t.y += p.d; + pose.t.z += p.d; + + glPushMatrix(); + glDisable(GL_LIGHTING); + glColor4f(0.1f, 0.2f, 0.3f, 1.0f); + pose.t.y -= 0.1f; + SetupGLMatrix(pose.t, pose.M); + glScalef(1024,0,1024); + RenderPlane(); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glEnable(GL_LIGHTING); + glPopMatrix(); +} + +void DrawWireBox(const NxBox& obb, const NxVec3& color, float lineWidth) +{ + // Compute obb vertices + NxVec3 pp[8]; + NxComputeBoxPoints(obb, pp); + + // Draw all lines + const NxU32* Indices = NxGetBoxEdges(); + for(NxU32 i=0;i<12;i++) + { + NxU32 VRef0 = *Indices++; + NxU32 VRef1 = *Indices++; + DrawLine(pp[VRef0], pp[VRef1], color, lineWidth); + } +} + +void DrawWireBox(NxShape* box, const NxVec3& color, float lineWidth) +{ + NxBox obb; + box->isBox()->getWorldOBB(obb); + + DrawWireBox(obb, color, lineWidth); +} + + +void DrawWireSphere(NxShape* sphere, const NxVec3& color) +{ + NxMat34 pose = sphere->getGlobalPose(); + + glPushMatrix(); + NxReal r = sphere->isSphere()->getRadius(); + + NxVec3 c0; pose.M.getColumn(0, c0); + NxVec3 c1; pose.M.getColumn(1, c1); + NxVec3 c2; pose.M.getColumn(2, c2); + DrawCircle(20, pose, color, r); + + pose.M.setColumn(0, c1); + pose.M.setColumn(1, c2); + pose.M.setColumn(2, c0); + DrawCircle(20, pose, color, r); + + pose.M.setColumn(0, c2); + pose.M.setColumn(1, c0); + pose.M.setColumn(2, c1); + DrawCircle(20, pose, color, r); + + glPopMatrix(); +} + +void DrawSphere(NxShape* sphere) +{ + NxMat34 pose = sphere->getGlobalPose(); + + glPushMatrix(); + SetupGLMatrix(pose.t, pose.M); + NxReal r = sphere->isSphere()->getRadius(); + glScalef(r,r,r); + RenderSphere(); + glPopMatrix(); +} + +void DrawWireCapsule(NxShape* capsule, const NxVec3& color) +{ + NxMat34 pose = capsule->getGlobalPose(); + + NxReal r = capsule->isCapsule()->getRadius(); + NxReal h = capsule->isCapsule()->getHeight(); + + NxSegment SG; + pose.M.getColumn(1, SG.p1); + SG.p1 *= 0.5f*h; + SG.p0 = -SG.p1; + SG.p0 += pose.t; + SG.p1 += pose.t; + + NxVec3 c0; pose.M.getColumn(0, c0); + NxVec3 c1; pose.M.getColumn(1, c1); + NxVec3 c2; pose.M.getColumn(2, c2); + DrawLine(SG.p0 + c0*r, SG.p1 + c0*r, color); + DrawLine(SG.p0 - c0*r, SG.p1 - c0*r, color); + DrawLine(SG.p0 + c2*r, SG.p1 + c2*r, color); + DrawLine(SG.p0 - c2*r, SG.p1 - c2*r, color); + + pose.M.setColumn(0, -c1); + pose.M.setColumn(1, -c0); + pose.M.setColumn(2, c2); + pose.t = SG.p0; + DrawCircle(20, pose, color, r, true); //halfcircle -- flipped + + pose.M.setColumn(0, c1); + pose.M.setColumn(1, -c0); + pose.M.setColumn(2, c2); + pose.t = SG.p1; + DrawCircle(20, pose, color, r, true); + + pose.M.setColumn(0, -c1); + pose.M.setColumn(1, c2); + pose.M.setColumn(2, c0); + pose.t = SG.p0; + DrawCircle(20, pose, color, r, true);//halfcircle -- good + + pose.M.setColumn(0, c1); + pose.M.setColumn(1, c2); + pose.M.setColumn(2, c0); + pose.t = SG.p1; + DrawCircle(20, pose, color, r, true); + + pose.M.setColumn(0, c2); + pose.M.setColumn(1, c0); + pose.M.setColumn(2, c1); + pose.t = SG.p0; + DrawCircle(20, pose, color, r); //full circle + pose.t = SG.p1; + DrawCircle(20, pose, color, r); +} + +static void computeBasis(const NxVec3& dir, NxVec3& right, NxVec3& up) +{ + // Derive two remaining vectors + if(fabsf(dir.y)>0.9999f) right = NxVec3(1.0f, 0.0f, 0.0f); + else right = (NxVec3(0.0f, 1.0f, 0.0f) ^ dir); + right.normalize(); + up = dir ^ right; +} + +void DrawWireCapsule(const NxCapsule& capsule, const NxVec3& color) +{ + NxReal r = capsule.radius; + NxVec3 dir = capsule.p0 - capsule.p1; + NxReal h = dir.magnitude(); + NxMat34 pose; + pose.t = (capsule.p0 + capsule.p1)*0.5f; + + if(h!=0.0f) + { + dir/=h; + NxVec3 right, up; + computeBasis(dir, right, up); + pose.M.setColumn(0, right); + pose.M.setColumn(1, dir); + pose.M.setColumn(2, up); + } + else + { + pose.M.id(); + } + +// NxMat34 pose = capsule->getGlobalPose(); +// const NxReal & r = capsule->isCapsule()->getRadius(); +// const NxReal & h = capsule->isCapsule()->getHeight(); + + + + NxSegment SG; + pose.M.getColumn(1, SG.p1); + SG.p1 *= 0.5f*h; + SG.p0 = -SG.p1; + SG.p0 += pose.t; + SG.p1 += pose.t; + + NxVec3 c0; pose.M.getColumn(0, c0); + NxVec3 c1; pose.M.getColumn(1, c1); + NxVec3 c2; pose.M.getColumn(2, c2); + DrawLine(SG.p0 + c0*r, SG.p1 + c0*r, color); + DrawLine(SG.p0 - c0*r, SG.p1 - c0*r, color); + DrawLine(SG.p0 + c2*r, SG.p1 + c2*r, color); + DrawLine(SG.p0 - c2*r, SG.p1 - c2*r, color); + + pose.M.setColumn(0, -c1); + pose.M.setColumn(1, -c0); + pose.M.setColumn(2, c2); + pose.t = SG.p0; + DrawCircle(20, pose, color, r, true); //halfcircle -- flipped + + pose.M.setColumn(0, c1); + pose.M.setColumn(1, -c0); + pose.M.setColumn(2, c2); + pose.t = SG.p1; + DrawCircle(20, pose, color, r, true); + + pose.M.setColumn(0, -c1); + pose.M.setColumn(1, c2); + pose.M.setColumn(2, c0); + pose.t = SG.p0; + DrawCircle(20, pose, color, r, true);//halfcircle -- good + + pose.M.setColumn(0, c1); + pose.M.setColumn(1, c2); + pose.M.setColumn(2, c0); + pose.t = SG.p1; + DrawCircle(20, pose, color, r, true); + + pose.M.setColumn(0, c2); + pose.M.setColumn(1, c0); + pose.M.setColumn(2, c1); + pose.t = SG.p0; + DrawCircle(20, pose, color, r); //full circle + pose.t = SG.p1; + DrawCircle(20, pose, color, r); +} + +void DrawCapsule(const NxVec3& color, NxF32 r, NxF32 h) +{ + glColor4f(color.x, color.y, color.z, 1.0f); + + glPushMatrix(); + glTranslatef(0.0f, h*0.5f, 0.0f); + glScalef(r,r,r); + RenderSphere(); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(0.0f,-h*0.5f, 0.0f); + glScalef(r,r,r); + RenderSphere(); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(0.0f,h*0.5f, 0.0f); + glScalef(r,h,r); + glRotatef(90.0f,1.0f,0.0f,0.0f); + RenderCylinder(); + glPopMatrix(); +} + +typedef NxVec3 Point; +typedef struct _Triangle { NxU32 p0; NxU32 p1; NxU32 p2; } Triangle; + +void DrawWireConvex(NxShape* mesh, const NxVec3& color) +{ + if(mesh->userData == NULL) return; + + NxMat34 pose = mesh->getGlobalPose(); + + NxConvexMeshDesc meshDesc = *((NxConvexMeshDesc*)(mesh->userData)); +// mesh->isConvexMesh()->getConvexMesh().saveToDesc(meshDesc); + + NxU32 nbVerts = meshDesc.numVertices; + NxU32 nbTriangles = meshDesc.numTriangles; + + Point* points = (Point *)meshDesc.points; + Triangle* triangles = (Triangle *)meshDesc.triangles; + + glPushMatrix(); + + float glmat[16]; //4x4 column major matrix for OpenGL. + pose.M.getColumnMajorStride4(&(glmat[0])); + pose.t.get(&(glmat[12])); + + //clear the elements we don't need: + glmat[3] = glmat[7] = glmat[11] = 0.0f; + glmat[15] = 1.0f; + + glMultMatrixf(&(glmat[0])); + + while(nbTriangles--) + { + DrawLine(points[triangles->p0], points[triangles->p1], color); + DrawLine(points[triangles->p1], points[triangles->p2], color); + DrawLine(points[triangles->p2], points[triangles->p0], color); + triangles++; + } + + glPopMatrix(); +} + +void DrawTriangleList(int iTriangleCount, Triangle *pTriangles, Point *pPoints) +{ + static int iBufferSize=0; + static float *pfVertexBuffer=NULL; + static float *pfNormalBuffer=NULL; + + if(iBufferSize < iTriangleCount*3) + { + iBufferSize=3*iTriangleCount; + + delete[] pfVertexBuffer; + pfVertexBuffer = new float[iBufferSize*3]; + + delete[] pfNormalBuffer; + pfNormalBuffer = new float[iBufferSize*3]; + } + + float *pfDestinationVertex=pfVertexBuffer; + float *pfDestinationNormal=pfNormalBuffer; + + for(int iTriangle=0; iTrianglep0].x; + *pfDestinationVertex++=pPoints[pTriangles->p0].y; + *pfDestinationVertex++=pPoints[pTriangles->p0].z; + *pfDestinationVertex++=pPoints[pTriangles->p1].x; + *pfDestinationVertex++=pPoints[pTriangles->p1].y; + *pfDestinationVertex++=pPoints[pTriangles->p1].z; + *pfDestinationVertex++=pPoints[pTriangles->p2].x; + *pfDestinationVertex++=pPoints[pTriangles->p2].y; + *pfDestinationVertex++=pPoints[pTriangles->p2].z; + + NxVec3 edge1 = pPoints[pTriangles->p1] - pPoints[pTriangles->p0]; + NxVec3 edge2 = pPoints[pTriangles->p2] - pPoints[pTriangles->p0]; + NxVec3 normal = edge1.cross(edge2); + normal.normalize(); + + *pfDestinationNormal++=normal.x; + *pfDestinationNormal++=normal.y; + *pfDestinationNormal++=normal.z; + *pfDestinationNormal++=normal.x; + *pfDestinationNormal++=normal.y; + *pfDestinationNormal++=normal.z; + *pfDestinationNormal++=normal.x; + *pfDestinationNormal++=normal.y; + *pfDestinationNormal++=normal.z; + + pTriangles++; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, pfVertexBuffer); + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, pfNormalBuffer); + + glDrawArrays(GL_TRIANGLES, 0, 3*iTriangleCount); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + +} + +void DrawConvex(NxShape* mesh) +{ + NxConvexMeshDesc meshDesc; + + // SRM : Please note that I looked into a crash issue posed by + // one of our customers, and this code (i.e. reinterpreting the + // NxShape's userData as an NxConvexMeshDesc * was crashing because + // in the SampleRaycastCar demo, it sets that pointer equal to the + // NxWheel because that is used in NxVehicle::handleContactPair(). Thus + // in order to allow this code not to crash on the PS3, we should + // simply force the shape to save its description here. + mesh->isConvexMesh()->getConvexMesh().saveToDesc(meshDesc); + /** + if(mesh->userData != NULL) + { + meshDesc = *((NxConvexMeshDesc*)(mesh->userData)); + } else { + mesh->isConvexMesh()->getConvexMesh().saveToDesc(meshDesc); + } + **/ + + NxMat34 pose = mesh->getGlobalPose(); + + NxU32 nbVerts = meshDesc.numVertices; + NxU32 nbTriangles = meshDesc.numTriangles; + + Point* points = (Point *)meshDesc.points; + Triangle* triangles = (Triangle *)meshDesc.triangles; + + glPushMatrix(); + + float glmat[16]; //4x4 column major matrix for OpenGL. + pose.M.getColumnMajorStride4(&(glmat[0])); + pose.t.get(&(glmat[12])); + + //clear the elements we don't need: + glmat[3] = glmat[7] = glmat[11] = 0.0f; + glmat[15] = 1.0f; + + glMultMatrixf(&(glmat[0])); + + DrawTriangleList(nbTriangles, triangles, points); + + glPopMatrix(); +} + +void DrawWireMesh(NxShape* mesh, const NxVec3& color) +{ + if(mesh->userData == NULL) return; + + NxMat34 pose = mesh->getGlobalPose(); + + NxTriangleMeshDesc meshDesc = *((NxTriangleMeshDesc*)(mesh->userData)); +// mesh->isTriangleMesh()->getTriangleMesh().saveToDesc(meshDesc); + + NxU32 nbVerts = meshDesc.numVertices; + NxU32 nbTriangles = meshDesc.numTriangles; + + Point* points = (Point *)meshDesc.points; + Triangle* triangles = (Triangle *)meshDesc.triangles; + + glPushMatrix(); + + float glmat[16]; //4x4 column major matrix for OpenGL. + pose.M.getColumnMajorStride4(&(glmat[0])); + pose.t.get(&(glmat[12])); + + //clear the elements we don't need: + glmat[3] = glmat[7] = glmat[11] = 0.0f; + glmat[15] = 1.0f; + + glMultMatrixf(&(glmat[0])); + + while(nbTriangles--) + { + DrawLine(points[triangles->p0], points[triangles->p1], color); + DrawLine(points[triangles->p1], points[triangles->p2], color); + DrawLine(points[triangles->p2], points[triangles->p0], color); + triangles++; + } + + glPopMatrix(); +} + +void DrawMesh(NxShape* mesh) +{ + if(mesh->userData == NULL) return; + + NxMat34 pose = mesh->getGlobalPose(); + + NxTriangleMeshDesc meshDesc = *((NxTriangleMeshDesc*)(mesh->userData)); +// mesh->isTriangleMesh()->getTriangleMesh().saveToDesc(meshDesc); + + NxU32 nbVerts = meshDesc.numVertices; + NxU32 nbTriangles = meshDesc.numTriangles; + + Point* points = (Point *)meshDesc.points; + Triangle* triangles = (Triangle *)meshDesc.triangles; + + glPushMatrix(); + + float glmat[16]; //4x4 column major matrix for OpenGL. + pose.M.getColumnMajorStride4(&(glmat[0])); + pose.t.get(&(glmat[12])); + + //clear the elements we don't need: + glmat[3] = glmat[7] = glmat[11] = 0.0f; + glmat[15] = 1.0f; + + glMultMatrixf(&(glmat[0])); + + if(meshDesc.heightFieldVerticalAxis != NX_NOT_HEIGHTFIELD) + { + glDisable(GL_LIGHT0); + glEnable(GL_LIGHT1); + } + + DrawTriangleList(nbTriangles, triangles, points); + + if(meshDesc.heightFieldVerticalAxis != NX_NOT_HEIGHTFIELD) + { + glDisable(GL_LIGHT1); + glEnable(GL_LIGHT0); + } + + glPopMatrix(); +} + +void DrawWheelShape(NxShape* wheel) +{ + if(wheel->is(NX_SHAPE_WHEEL) != NULL) + { + NxWheelShape* wheelShape = (NxWheelShape*)wheel; + glPushMatrix(); + + float glmat[16]; + wheel->getGlobalPose().getColumnMajor44(glmat); + + NxWheelShapeDesc wheelShapeDesc; + + float r = wheelShape->getRadius(); + float a = wheelShape->getSteerAngle(); + + glMultMatrixf(&(glmat[0])); + glTranslatef(-r/2,0,0); + glRotatef(90,0,1,0); + glRotatef(NxMath::radToDeg(a),0,1,0); + + glScalef(r, r, r); + RenderCylinder(); + glPopMatrix(); + } +} + +void DrawArrow(const NxVec3& posA, const NxVec3& posB, const NxVec3& color) +{ + NxVec3 vec = posB - posA; + NxVec3 t0, t1, t2; + NxNormalToTangents(vec, t1, t2); + + t0 = posB - posA; + t0.normalize(); + + NxVec3 lobe1 = posB - t0*0.15 + t1 * 0.15; + NxVec3 lobe2 = posB - t0*0.15 - t1 * 0.15; + NxVec3 lobe3 = posB - t0*0.15 + t2 * 0.15; + NxVec3 lobe4 = posB - t0*0.15 - t2 * 0.15; + + NxVec3 v3ArrowShape[] = { + NxVec3(posA), NxVec3(posB), + NxVec3(posB), NxVec3(lobe1), + NxVec3(posB), NxVec3(lobe2), + NxVec3(posB), NxVec3(lobe3), + NxVec3(posB), NxVec3(lobe4), + }; + + glDisable(GL_LIGHTING); + glLineWidth(3.0f); + glColor4f(color.x,color.y,color.z,1.0f); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(NxVec3), &v3ArrowShape[0].x); + glDrawArrays(GL_LINES, 0, sizeof(v3ArrowShape)/sizeof(NxVec3)); + glDisableClientState(GL_VERTEX_ARRAY); + glColor4f(1.0f,1.0f,1.0f,1.0f); +} + +void DrawContactPoint(const NxVec3& pos, const NxReal radius, const NxVec3& color) +{ + NxMat34 pose; + pose.t = pos; + + NxVec3 c0; pose.M.getColumn(0, c0); + NxVec3 c1; pose.M.getColumn(1, c1); + NxVec3 c2; pose.M.getColumn(2, c2); + DrawCircle(20, pose, color, radius); + + pose.M.setColumn(0, c1); + pose.M.setColumn(1, c2); + pose.M.setColumn(2, c0); + DrawCircle(20, pose, color, radius); + + pose.M.setColumn(0, c2); + pose.M.setColumn(1, c0); + pose.M.setColumn(2, c1); + DrawCircle(20, pose, color, radius); +} + +void DrawWireShape(NxShape *shape, const NxVec3& color) +{ + switch(shape->getType()) + { + case NX_SHAPE_PLANE: + DrawWirePlane(shape, color); + break; + case NX_SHAPE_BOX: + DrawWireBox(shape, color); + break; + case NX_SHAPE_SPHERE: + DrawWireSphere(shape, color); + break; + case NX_SHAPE_CAPSULE: + DrawWireCapsule(shape, color); + break; + case NX_SHAPE_CONVEX: + DrawWireConvex(shape, color); + break; + case NX_SHAPE_MESH: + DrawWireMesh(shape, color); + break; + } +} + +void DrawShape(NxShape* shape) +{ + switch(shape->getType()) + { + case NX_SHAPE_PLANE: + DrawPlane(shape); + break; + case NX_SHAPE_BOX: + DrawBox(shape); + break; + case NX_SHAPE_SPHERE: + DrawSphere(shape); + break; + case NX_SHAPE_CAPSULE: + DrawCapsule(shape); + break; + case NX_SHAPE_CONVEX: + DrawConvex(shape); + break; + case NX_SHAPE_MESH: + DrawMesh(shape); + break; + case NX_SHAPE_WHEEL: + DrawWheelShape(shape); + break; + } +} + +void DrawActor(NxActor* actor, NxActor* gSelectedActor) +{ + NxShape*const* shapes = actor->getShapes(); + NxU32 nShapes = actor->getNbShapes(); + if (actor == gSelectedActor) + { + while (nShapes--) + { + DrawWireShape(shapes[nShapes], NxVec3(1,1,1)); + } + } + nShapes = actor->getNbShapes(); + while (nShapes--) + { + DrawShape(shapes[nShapes]); + } +} + +void DrawWireActor(NxActor* actor) +{ + NxShape*const* shapes = actor->getShapes(); + NxU32 nShapes = actor->getNbShapes(); + nShapes = actor->getNbShapes(); + while (nShapes--) + { + DrawWireShape(shapes[nShapes], NxVec3(1,1,1)); + } +} + +static void DrawActorShadow(NxActor* actor, const float* ShadowMat) +{ + glPushMatrix(); + glMultMatrixf(ShadowMat); + + glDisable(GL_LIGHTING); + glColor4f(0.05f, 0.1f, 0.15f, 1.0f); + + NxShape*const* shapes = actor->getShapes(); + NxU32 nShapes = actor->getNbShapes(); + while (nShapes--) + { + switch(shapes[nShapes]->getType()) + { + case NX_SHAPE_BOX: + DrawBox(shapes[nShapes]); + break; + case NX_SHAPE_SPHERE: + DrawSphere(shapes[nShapes]); + break; + case NX_SHAPE_CAPSULE: + DrawCapsule(shapes[nShapes]); + break; + case NX_SHAPE_CONVEX: + DrawConvex(shapes[nShapes]); + break; + } + } + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glEnable(GL_LIGHTING); + + glPopMatrix(); +} + + +void DrawActorShadow(NxActor* actor) +{ + const static float ShadowMat[]={ 1,0,0,0, 0,0,0,0, 0,0,1,0, 0,0,0,1 }; + DrawActorShadow(actor, ShadowMat); +} + +void DrawActorShadow2(NxActor* actor) +{ + const static float ShadowMat[]={ 1,0,0,0, 1,0,-0.2,0, 0,0,1,0, 0,0,0,1 }; + DrawActorShadow(actor, ShadowMat); +} + +void DrawActorShadowZUp(NxActor* actor) +{ + const static float ShadowMat[]={ 1,0,0,0, 0,1,0,0, 0,0,0,0, 0,0,0,1 }; + DrawActorShadow(actor, ShadowMat); +} + +void DrawCloth(NxCloth *cloth, bool shadows) +{ + NxMeshData meshData = cloth->getMeshData(); + + NxU32 numVertices = *meshData.numVerticesPtr; + NxU32 numTriangles = *meshData.numIndicesPtr / 3; + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, meshData.verticesPosBegin); + glNormalPointer(GL_FLOAT, 0, meshData.verticesNormalBegin); + +#ifdef __CELLOS_LV2__ + glDrawRangeElements(GL_TRIANGLES, 0, numVertices-1, 3*numTriangles, GL_UNSIGNED_INT, meshData.indicesBegin); +#else + glDrawElements(GL_TRIANGLES, 3*numTriangles, GL_UNSIGNED_INT, meshData.indicesBegin); +#endif + + if (shadows) { + const static float ShadowMat[]={ 1,0,0,0, 0,0,0,0, 0,0,1,0, 0,0,0,1 }; + glPushMatrix(); + glMultMatrixf(ShadowMat); + glDisable(GL_LIGHTING); + glColor4f(0.05f, 0.1f, 0.15f,1.0f); + +#ifdef __CELLOS_LV2__ + glDrawRangeElements(GL_TRIANGLES, 0, numVertices-1, 3*numTriangles, GL_UNSIGNED_INT, meshData.indicesBegin); +#else + glDrawElements(GL_TRIANGLES, 3*numTriangles, GL_UNSIGNED_INT, meshData.indicesBegin); +#endif + + glColor4f(1.0f, 1.0f, 1.0f,1.0f); + glEnable(GL_LIGHTING); + glPopMatrix(); + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); +} + +#ifdef WIN32 +#include +typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALFARPROC)( int ); +PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = 0; +int vsyncState = 1; +#endif + +void toggleVSync() +{ +#ifdef WIN32 + if (wglSwapIntervalEXT == NULL) + { + const char* extensions = (const char*)glGetString(GL_EXTENSIONS); + if (strstr(extensions, "WGL_EXT_swap_control") != 0) + { + wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress( "wglSwapIntervalEXT" ); + } + } + if (wglSwapIntervalEXT != NULL) + { + vsyncState = 1 - vsyncState; + wglSwapIntervalEXT(vsyncState); + } +#endif +} +#endif diff --git a/Extras/CDTestFramework/RenderingHelpers.h b/Extras/CDTestFramework/RenderingHelpers.h new file mode 100644 index 0000000..24dcfb7 --- /dev/null +++ b/Extras/CDTestFramework/RenderingHelpers.h @@ -0,0 +1,26 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 RENDERINGHELPERS_H +#define RENDERINGHELPERS_H + +#include "Opcode.h" + + void DrawLine(const Point& p0, const Point& p1, const Point& color, float line_width); + void DrawTriangle(const Point& p0, const Point& p1, const Point& p2, const Point& color); + void DrawSphere(const Sphere& sphere); + void DrawOBB(const OBB& obb); + void DrawCapsule(const Matrix4x4& world, const Point& p0, const Point& p1, float r); + +#endif // RENDERINGHELPERS_H diff --git a/Extras/CDTestFramework/SphereMeshQuery.cpp b/Extras/CDTestFramework/SphereMeshQuery.cpp new file mode 100644 index 0000000..e78eadb --- /dev/null +++ b/Extras/CDTestFramework/SphereMeshQuery.cpp @@ -0,0 +1,141 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 "stdafx.h" +#include "RenderingHelpers.h" +#include "IceHelpers.h" +#include "SphereMeshQuery.h" +#include "Terrain.h" +#include "Profiling.h" +#include "Camera.h" +#include "GLFontRenderer.h" + +SphereMeshQuery::SphereMeshQuery() : + mBar (null), + mDist (0.0f), + mValidHit (false) +{ +} + +SphereMeshQuery::~SphereMeshQuery() +{ +} + +void SphereMeshQuery::Init() +{ + mSphere.mCenter = Point(0.0f, 0.0f, 0.0f); + mSphere.mRadius = 1.0f; +} + +void SphereMeshQuery::Release() +{ + Deselect(); +} + +void SphereMeshQuery::Select() +{ + // Create a tweak bar + { + mBar = TwNewBar("SphereMeshQuery"); + TwAddVarRW(mBar, "Radius", TW_TYPE_FLOAT, &mSphere.mRadius, " min=0.01 max=200.0 step=0.05"); + + mSettings.AddToTweakBar(mBar); +// mProfiler.AddToTweakBar(mBar); + } +} + +void SphereMeshQuery::Deselect() +{ + if(mBar) + { + TwDeleteBar(mBar); + mBar = null; + } +} + +void SphereMeshQuery::PerformTest() +{ + RenderTerrain(); + + DrawSphere(mSphere); + + // OPCODE query + const Model* TM = GetTerrainModel(); + if(TM) + { + SphereCollider Collider; + mSettings.SetupCollider(Collider); + + mProfiler.Start(); + bool Status = Collider.Collide(mCache, mSphere, *TM, null, null); + mProfiler.End(); + mProfiler.Accum(); + + if(Status) + { + if(Collider.GetContactStatus()) + { + udword NbTris = Collider.GetNbTouchedPrimitives(); + const udword* Indices = Collider.GetTouchedPrimitives(); + + RenderTerrainTriangles(NbTris, Indices); + } + } + } + + // Raycast hit + if(mValidHit) + { + Point wp = mLocalHit + mSphere.mCenter; + DrawLine(wp, wp + Point(1.0f, 0.0f, 0.0f), Point(1,0,0), 1.0f); + DrawLine(wp, wp + Point(0.0f, 1.0f, 0.0f), Point(0,1,0), 1.0f); + DrawLine(wp, wp + Point(0.0f, 0.0f, 1.0f), Point(0,0,1), 1.0f); + } + + char Buffer[4096]; + sprintf(Buffer, "Sphere-mesh query = %5.1f us (%d cycles)\n", mProfiler.mMsTime, mProfiler.mCycles); + GLFontRenderer::print(10.0f, 10.0f, 0.02f, Buffer); +} + +void SphereMeshQuery::KeyboardCallback(unsigned char key, int x, int y) +{ +} + +void SphereMeshQuery::MouseCallback(int button, int state, int x, int y) +{ + mValidHit = false; + if(!button && !state) + { + Point Dir = ComputeWorldRay(x, y); + + float d; + Point hit; + if(SegmentSphere(GetCameraPos(), Dir, 10000.0f, mSphere.mCenter, mSphere.mRadius, d, hit)) + { + mValidHit = true; + mDist = d; + mLocalHit = hit - mSphere.mCenter; + } + } +} + +void SphereMeshQuery::MotionCallback(int x, int y) +{ + if(mValidHit) + { + Point Dir = ComputeWorldRay(x, y); + mSphere.mCenter = GetCameraPos() + Dir*mDist - mLocalHit; + } +} diff --git a/Extras/CDTestFramework/SphereMeshQuery.h b/Extras/CDTestFramework/SphereMeshQuery.h new file mode 100644 index 0000000..e03eee7 --- /dev/null +++ b/Extras/CDTestFramework/SphereMeshQuery.h @@ -0,0 +1,48 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 SPHEREMESHQUERY_H +#define SPHEREMESHQUERY_H + +#include "CollisionTest.h" +#include "Profiling.h" + + class SphereMeshQuery : public CollisionTest + { + public: + SphereMeshQuery(); + virtual ~SphereMeshQuery(); + + virtual void Init(); + virtual void Release(); + virtual void PerformTest(); + virtual void Select(); + virtual void Deselect(); + virtual void KeyboardCallback(unsigned char key, int x, int y); + virtual void MouseCallback(int button, int state, int x, int y); + virtual void MotionCallback(int x, int y); + + TwBar* mBar; //!< AntTweakBar + Sphere mSphere; + + SphereCache mCache; + OpcodeSettings mSettings; + Profiler mProfiler; + + float mDist; + Point mLocalHit; + bool mValidHit; + }; + +#endif // SPHEREMESHQUERY_H diff --git a/Extras/CDTestFramework/Terrain.cpp b/Extras/CDTestFramework/Terrain.cpp new file mode 100644 index 0000000..c849ce3 --- /dev/null +++ b/Extras/CDTestFramework/Terrain.cpp @@ -0,0 +1,470 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 "stdafx.h" +#include "Terrain.h" + +inline float NxAngle(const Point& v0, const Point& v1) + { + float cos = v0|v1; // |v0|*|v1|*Cos(Angle) + float sin = (v0^v1).Magnitude(); // |v0|*|v1|*Sin(Angle) + return ::atan2(sin, cos); + } + +static float computeAngle(const Point* verts, const udword* refs, udword vref) +{ + udword e0=0,e2=0; + if(vref==refs[0]) + { + e0 = 2; + e2 = 1; + } + else if(vref==refs[1]) + { + e0 = 2; + e2 = 0; + } + else if(vref==refs[2]) + { + e0 = 0; + e2 = 1; + } + else + { + assert(0); + } + Point edge0 = verts[refs[e0]] - verts[vref]; + Point edge1 = verts[refs[e2]] - verts[vref]; + + return NxAngle(edge0, edge1); +} +static bool buildSmoothNormals( + udword nbTris, udword nbVerts, + const Point* verts, + const udword* dFaces, const uword* wFaces, + Point* normals, + bool flip) + { + // Checkings + if(!verts || !normals || !nbTris || !nbVerts) return false; + + // Get correct destination buffers + // - if available, write directly to user-provided buffers + // - else get some ram and keep track of it + Point* FNormals = new Point[nbTris]; + if(!FNormals) return false; + + // Compute face normals + udword c = (flip!=0); + for(udword i=0;i>=1; + if(!currentSize) return; + + // Compute new heights + float v0 = (value * float(rand()-RAND_MAX_OVER_TWO) * ONE_OVER_RAND_MAX); + float v1 = (value * float(rand()-RAND_MAX_OVER_TWO) * ONE_OVER_RAND_MAX); + float v2 = (value * float(rand()-RAND_MAX_OVER_TWO) * ONE_OVER_RAND_MAX); + float v3 = (value * float(rand()-RAND_MAX_OVER_TWO) * ONE_OVER_RAND_MAX); + float v4 = (value * float(rand()-RAND_MAX_OVER_TWO) * ONE_OVER_RAND_MAX); + + udword x1 = (x0+currentSize) % initSize; + udword x2 = (x0+currentSize+currentSize) % initSize; + udword y1 = (y0+currentSize) % initSize; + udword y2 = (y0+currentSize+currentSize) % initSize; + + if(!done[x1 + y0*initSize]) field[x1 + y0*initSize].y = v0 + 0.5f * (field[x0 + y0*initSize].y + field[x2 + y0*initSize].y); + if(!done[x0 + y1*initSize]) field[x0 + y1*initSize].y = v1 + 0.5f * (field[x0 + y0*initSize].y + field[x0 + y2*initSize].y); + if(!done[x2 + y1*initSize]) field[x2 + y1*initSize].y = v2 + 0.5f * (field[x2 + y0*initSize].y + field[x2 + y2*initSize].y); + if(!done[x1 + y2*initSize]) field[x1 + y2*initSize].y = v3 + 0.5f * (field[x0 + y2*initSize].y + field[x2 + y2*initSize].y); + if(!done[x1 + y1*initSize]) field[x1 + y1*initSize].y = v4 + 0.5f * (field[x0 + y1*initSize].y + field[x2 + y1*initSize].y); + + done[x1 + y0*initSize] = true; + done[x0 + y1*initSize] = true; + done[x2 + y1*initSize] = true; + done[x1 + y2*initSize] = true; + done[x1 + y1*initSize] = true; + + // Recurse through 4 corners + value *= 0.5f; + _Compute(done, field, x0, y0, currentSize, value, initSize); + _Compute(done, field, x0, y1, currentSize, value, initSize); + _Compute(done, field, x1, y0, currentSize, value, initSize); + _Compute(done, field, x1, y1, currentSize, value, initSize); + } + }; + + // Fractalize + srand(42); + bool* done = new bool[nbVerts]; + memset(done,0,nbVerts*sizeof(bool)); + verts[0].y = 10.0f; + verts[size-1].y = 10.0f; + verts[size*(size-1)].y = 10.0f; + verts[nbVerts-1].y = 10.0f; + Local::_Compute(done, verts, 0, 0, size, chaos, size); + for(udword i=0;iinit(TERRAIN_SIZE, TERRAIN_OFFSET, TERRAIN_WIDTH, TERRAIN_CHAOS); + + // Build OPCODE model + + gMeshInterface.SetNbTriangles(gTerrainData->nbFaces); + gMeshInterface.SetNbVertices(gTerrainData->nbVerts); + gMeshInterface.SetPointers((const IndexedTriangle*)gTerrainData->faces, gTerrainData->verts); + + OPCODECREATE Create; + Create.mIMesh = &gMeshInterface; + Create.mSettings.mLimit = 1; + Create.mSettings.mRules = SPLIT_SPLATTER_POINTS|SPLIT_GEOM_CENTER; + Create.mNoLeaf = true; + Create.mQuantized = true; + Create.mKeepOriginal = false; + Create.mCanRemap = false; + + gOpcodeModel = new Model; + if(!gOpcodeModel->Build(Create)) + { + } +} + +void RenderTerrain() +{ + if(gTerrainData) + renderTerrain(*gTerrainData, true); +} + +void RenderTerrainTriangles(udword nbTriangles, const udword* indices) +{ + if(gTerrainData) + renderTerrainTriangles(*gTerrainData, nbTriangles, indices); +} diff --git a/Extras/CDTestFramework/Terrain.h b/Extras/CDTestFramework/Terrain.h new file mode 100644 index 0000000..3f5f6f2 --- /dev/null +++ b/Extras/CDTestFramework/Terrain.h @@ -0,0 +1,47 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 TERRAIN_H +#define TERRAIN_H + + class TerrainData + { + public: + TerrainData(); + ~TerrainData(); + + void init(udword size, float offset, float width, float chaos, bool flat=false, const Point* pos=NULL); + void release(); + + udword size; + udword nbVerts; + udword nbFaces; + float offset; + float width; + float chaos; + Point* verts; + Point* colors; + Point* normals; + udword* faces; + }; + + void CreateTerrain(); + void ReleaseTerrain(); + + void RenderTerrain(); + void RenderTerrainTriangles(udword nbTriangles, const udword* indices); + + const Model* GetTerrainModel(); + +#endif diff --git a/Extras/CDTestFramework/convex1.bin b/Extras/CDTestFramework/convex1.bin new file mode 100644 index 0000000000000000000000000000000000000000..c7958bd36d37a97a119dfc3b285a8174d94740a0 GIT binary patch literal 2924 zcmYjRYfO~a7X8FwUD`M#wdshO`2$$ zs@L1g1!;fSq$;As*3S8;HGSDyQz|r2Ypd1PTJKHlBR8?uyH}mvX!3>QI&1H}_Bwmd zZbeay@{}#C+MqVw>$UM&WOh03{%g_d(`QoT3y*eV6 z-0Tq_r%#IC91Y@8W{|k{-eciYXcO+APKjS^cJa{jknk*iBG!GLA}oVJBINKLp)2bb zF~^VFY#x_IiN^)uxMKaA(|6rpa_q^lgOWLmA0udQdGZW4F~q7 zNY+;UpjP%=IO2eQaGFaKCG;aUd(A-!{ovd(2T15gY;ew`gnnqyef(HLKeVN~->)I>x9EjEN00n=uat~Re$!nO-${OJ z`|-z;XQ0Y^Qt}M%&o^j1+kD0h;|va;`K^(YX8^T$HjtBN2DNTP7*(EOoO!nSj2UJQ z&b({L$vcQzyqn0$JBwPpJK*q6A(nRy9Nt013i^%KDatgL>2#of`_(@$`VEIw8#JAw zbJe>IB=?C^{)MWyqNw_7K-~>Sk9P?%5K=?8CO0FYGdyR`0_skvJ-JW5a0%SmUMBB1 zoEc1tqMa`VI%lqrZwGNs6W@=}Fkhha=KJ|m2F;B!)YI*Q0H6U20)rfc>IrS6Og&9N zgF_aEBEwsh!JlqAj{pq|k685j)2E`1cwf^^Qwo$Vj*ME;E%oQQKl()?G&*K!EOBM4 zlUqN53~}ao3wfYrVn`e6XgZrj1dC)udyLswMg$Z@NvW z*GU7=F9}WF4KyP&E4z~-uTdvg>2}|CpgGHyugHBCtxXX6pG2U!dHDsGh)4cv)UiC= z1q~}#tuD-Wa>uFaKmYQ#sJNum*_UPxjyaEw)G1|a)~_1K5a&8oe4p}0{}0tR)zsQ2>3_?K_XXY9ih$PDH#8RCZyDx_*ae-^ z)ZEhg1*wNR>R40H0o~lTr5)2W?dLjjR8eTA3EjGFd&eMg;rdPDZtVbf$Ii}O{Zy^R ziMDwe=)I>e4AHqMBRhJAeh+U~qlZSsCwugSyM`@t_t2}Kd8;M#EugRO5pctnwi&aG z6U4nr+@`X!_^P|WJ-2qu_MVwQynOoNKJ(UU>VbRB@pYMI3QZm#`i){@heqVSP~dYr zch2+oi6UMO@iXXe%CD}3&yTYN1o=G-Z`Ud)zw6n(=G>*=FIXBA92!XZwF2VD(zoXT z@bJY;($$C<;*PZxn$g4hY&XIqqhnK3qLQdy#6Hv6UkPu10=_x7AR#&4nO}MxE<8Kd z2|RK6GHY5=8s$%Y_Nn8)1Gi;lm#q`as9q-Fk@WXzBl2hFtSBkY^75I2ZyM^KwgS)F zWM5gBkNz$6kyh>1X5?8_wXvvlbzbTWGx?y!lP>#rz}J*lZf;-u)iXckxsJK#?#Ccc z#fIvZ=JljSg&yd7XA=CH9lPopYx^iZtLN6)Zz7mk43LidT5sGf!au6g zYeq$J(|Z_a&Ga@+t2(Mztye144Z#5QNE@uJFD1P zOIz6a+EDKq+*PewX|HW;Xl`A1Sb#cL<6 zh}&LYx2tpR9Ix3OhhFpG9<;dGh}%)KDKFO?H-Fwviql;G?Q1EaxQS5QZ85knicrP6 Swe8S;;=d*6L(O?x(f$twJl7Kd literal 0 HcmV?d00001 diff --git a/Extras/CDTestFramework/stdafx.cpp b/Extras/CDTestFramework/stdafx.cpp new file mode 100644 index 0000000..b4e1e25 --- /dev/null +++ b/Extras/CDTestFramework/stdafx.cpp @@ -0,0 +1,23 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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. +*/ + +// stdafx.cpp : source file that includes just the standard includes +// CDTestFramework.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/Extras/CDTestFramework/stdafx.h b/Extras/CDTestFramework/stdafx.h new file mode 100644 index 0000000..64535de --- /dev/null +++ b/Extras/CDTestFramework/stdafx.h @@ -0,0 +1,23 @@ +/* +CDTestFramework http://codercorner.com +Copyright (c) 2007-2008 Pierre Terdiman, pierre@codercorner.com + +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 +#include // For _alloca +#include +#include "GL/glut.h" +#include "AntTweakBar.h" + +#include "Opcode.h" +using namespace Opcode; diff --git a/Extras/CMakeLists.txt b/Extras/CMakeLists.txt new file mode 100644 index 0000000..a92f647 --- /dev/null +++ b/Extras/CMakeLists.txt @@ -0,0 +1,7 @@ +SUBDIRS( Serialize ConvexDecomposition HACD GIMPACTUtils ) + +#Maya Dynamica plugin is moved to http://dynamica.googlecode.com + +IF (USE_GLUT AND GLUT_FOUND) + SUBDIRS (glui) +ENDIF () diff --git a/Extras/CUDA/btCudaBroadphase.cpp b/Extras/CUDA/btCudaBroadphase.cpp new file mode 100644 index 0000000..3f835d1 --- /dev/null +++ b/Extras/CUDA/btCudaBroadphase.cpp @@ -0,0 +1,207 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btQuickprof.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" + +#include "btCudaBroadphase.h" +#include "radixsort.cuh" + + + +#define BT_GPU_PREF(func) btCuda_##func +#include "../../src/BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#include "../../src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h" +#undef BT_GPU_PREF + +extern "C" void btCuda_setParameters(bt3DGridBroadphaseParams* hostParams); + + + +#include + + + + +btCudaBroadphase::btCudaBroadphase( btOverlappingPairCache* overlappingPairCache, + const btVector3& worldAabbMin,const btVector3& worldAabbMax, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerSmallProxy, + int maxSmallProxiesPerCell) : + btGpu3DGridBroadphase(overlappingPairCache, worldAabbMin, worldAabbMax, gridSizeX, gridSizeY, gridSizeZ, maxSmallProxies, maxLargeProxies, maxPairsPerSmallProxy, maxSmallProxiesPerCell) +{ + _initialize(); +} + + + +btCudaBroadphase::~btCudaBroadphase() +{ + //btSimpleBroadphase will free memory of btSortedOverlappingPairCache, because m_ownsPairCache + assert(m_bInitialized); + _finalize(); +} + + + +void btCudaBroadphase::_initialize() +{ + // allocate GPU data + btCuda_allocateArray((void**)&m_dBodiesHash[0], m_maxHandles * 2 * sizeof(unsigned int)); + btCuda_allocateArray((void**)&m_dBodiesHash[1], m_maxHandles * 2 * sizeof(unsigned int)); + + btCuda_allocateArray((void**)&m_dCellStart, m_params.m_numCells * sizeof(unsigned int)); + + btCuda_allocateArray((void**)&m_dPairBuff, m_maxHandles * m_maxPairsPerBody * sizeof(unsigned int)); + btCuda_copyArrayToDevice(m_dPairBuff, m_hPairBuff, m_maxHandles * m_maxPairsPerBody * sizeof(unsigned int)); // needed? + + btCuda_allocateArray((void**)&m_dPairBuffStartCurr, (m_maxHandles * 2 + 1) * sizeof(unsigned int)); + btCuda_copyArrayToDevice(m_dPairBuffStartCurr, m_hPairBuffStartCurr, (m_maxHandles * 2 + 1) * sizeof(unsigned int)); + + unsigned int numAABB = m_maxHandles + m_maxLargeHandles; + btCuda_allocateArray((void**)&m_dAABB, numAABB * sizeof(bt3DGrid3F1U) * 2); + + btCuda_allocateArray((void**)&m_dPairScan, (m_maxHandles + 1) * sizeof(unsigned int)); + + btCuda_allocateArray((void**)&m_dPairOut, m_maxHandles * m_maxPairsPerBody * sizeof(unsigned int)); +} + + + +void btCudaBroadphase::_finalize() +{ + assert(m_bInitialized); + btCuda_freeArray(m_dBodiesHash[0]); + btCuda_freeArray(m_dBodiesHash[1]); + btCuda_freeArray(m_dCellStart); + btCuda_freeArray(m_dPairBuffStartCurr); + btCuda_freeArray(m_dAABB); + btCuda_freeArray(m_dPairBuff); + btCuda_freeArray(m_dPairScan); + btCuda_freeArray(m_dPairOut); +} + + + +// +// overrides for CUDA version +// + + + +void btCudaBroadphase::prepareAABB() +{ + btGpu3DGridBroadphase::prepareAABB(); + btCuda_copyArrayToDevice(m_dAABB, m_hAABB, sizeof(bt3DGrid3F1U) * 2 * (m_numHandles + m_numLargeHandles)); + return; +} + + + +void btCudaBroadphase::setParameters(bt3DGridBroadphaseParams* hostParams) +{ + btCuda_setParameters(hostParams); + return; +} + + + +void btCudaBroadphase::calcHashAABB() +{ + BT_PROFILE("btCuda_calcHashAABB"); + btCuda_calcHashAABB(m_dAABB, m_dBodiesHash[0], m_numHandles); +// btCuda_copyArrayFromDevice((void*)m_hBodiesHash, (void*)m_dBodiesHash[0], sizeof(unsigned int) * 2 * m_numHandles); + return; +} + + + +void btCudaBroadphase::sortHash() +{ + BT_PROFILE("RadixSort-- CUDA"); + RadixSort((KeyValuePair*)m_dBodiesHash[0], (KeyValuePair*)m_dBodiesHash[1], m_numHandles, 32); + return; +} + + + +void btCudaBroadphase::findCellStart() +{ + BT_PROFILE("btCuda_findCellStart"); + btCuda_findCellStart(m_dBodiesHash[0], m_dCellStart, m_numHandles, m_params.m_numCells); +// btCuda_copyArrayFromDevice((void*)m_hBodiesHash, (void*)m_dBodiesHash[0], sizeof(unsigned int) * 2 * m_numHandles); +// btCuda_copyArrayFromDevice((void*)m_hCellStart, (void*)m_dCellStart, sizeof(unsigned int) * m_params.m_numCells); + return; +} + + + +void btCudaBroadphase::findOverlappingPairs() +{ + BT_PROFILE("btCuda_findOverlappingPairs"); + btCuda_findOverlappingPairs(m_dAABB, m_dBodiesHash[0], m_dCellStart, m_dPairBuff, m_dPairBuffStartCurr, m_numHandles); + return; +} + + + +void btCudaBroadphase::findPairsLarge() +{ + BT_PROFILE("btCuda_findPairsLarge"); + btCuda_findPairsLarge(m_dAABB, m_dBodiesHash[0], m_dCellStart, m_dPairBuff, m_dPairBuffStartCurr, m_numHandles, m_numLargeHandles); + return; +} + + + +void btCudaBroadphase::computePairCacheChanges() +{ + BT_PROFILE("btCuda_computePairCacheChanges"); + btCuda_computePairCacheChanges(m_dPairBuff, m_dPairBuffStartCurr, m_dPairScan, m_dAABB, m_numHandles); + return; +} + + + +void btCudaBroadphase::scanOverlappingPairBuff() +{ + btCuda_copyArrayFromDevice(m_hPairScan, m_dPairScan, sizeof(unsigned int)*(m_numHandles + 1)); + btGpu3DGridBroadphase::scanOverlappingPairBuff(); + btCuda_copyArrayToDevice(m_dPairScan, m_hPairScan, sizeof(unsigned int)*(m_numHandles + 1)); + return; +} + + + +void btCudaBroadphase::squeezeOverlappingPairBuff() +{ + BT_PROFILE("btCuda_squeezeOverlappingPairBuff"); + btCuda_squeezeOverlappingPairBuff(m_dPairBuff, m_dPairBuffStartCurr, m_dPairScan, m_dPairOut, m_dAABB, m_numHandles); + btCuda_copyArrayFromDevice(m_hPairOut, m_dPairOut, sizeof(unsigned int) * m_hPairScan[m_numHandles]); + return; +} + + + +void btCudaBroadphase::resetPool(btDispatcher* dispatcher) +{ + btGpu3DGridBroadphase::resetPool(dispatcher); + btCuda_copyArrayToDevice(m_dPairBuffStartCurr, m_hPairBuffStartCurr, (m_maxHandles * 2 + 1) * sizeof(unsigned int)); +} + + diff --git a/Extras/CUDA/btCudaBroadphase.cu b/Extras/CUDA/btCudaBroadphase.cu new file mode 100644 index 0000000..41e4c94 --- /dev/null +++ b/Extras/CUDA/btCudaBroadphase.cu @@ -0,0 +1,74 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +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 +#include +#include + +#include "cutil_math.h" +#include "math_constants.h" + + +#include + + + +#include "btCudaDefines.h" + + + +#include "../../src/BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#include "../../src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h" + + + +__device__ inline bt3DGrid3F1U tex_fetch3F1U(float4 a) { return *((bt3DGrid3F1U*)(&a)); } + + + +void btCuda_exit(int val); + + + +texture particleHashTex; +texture cellStartTex; +texture pAABBTex; + + + +__constant__ bt3DGridBroadphaseParams params; + + + +extern "C" +{ + + + +void btCuda_setParameters(bt3DGridBroadphaseParams* hostParams) +{ + // copy parameters to constant memory + BT_GPU_SAFE_CALL(cudaMemcpyToSymbol(params, hostParams, sizeof(bt3DGridBroadphaseParams))); +} + + + +} // extern "C" + + + +#include "../../src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h" + + diff --git a/Extras/CUDA/btCudaBroadphase.h b/Extras/CUDA/btCudaBroadphase.h new file mode 100644 index 0000000..8e24e22 --- /dev/null +++ b/Extras/CUDA/btCudaBroadphase.h @@ -0,0 +1,69 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +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 CUDA_BROADPHASE_H +#define CUDA_BROADPHASE_H + + + +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" + +#include "../../src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h" +#include "../../src/BulletMultiThreaded/btGpu3DGridBroadphase.h" + + + +///The btCudaBroadphase uses CUDA-capable GPU to compute overlapping pairs + +class btCudaBroadphase : public btGpu3DGridBroadphase +{ +protected: + // GPU data + unsigned int* m_dBodiesHash[2]; + unsigned int* m_dCellStart; + unsigned int* m_dPairBuff; + unsigned int* m_dPairBuffStartCurr; + bt3DGrid3F1U* m_dAABB; + unsigned int* m_dPairScan; + unsigned int* m_dPairOut; +public: + btCudaBroadphase( btOverlappingPairCache* overlappingPairCache, + const btVector3& worldAabbMin,const btVector3& worldAabbMax, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerSmallProxies, + int maxSmallProxiesPerCell = 8); + virtual ~btCudaBroadphase(); +protected: + void _initialize(); + void _finalize(); + void allocateArray(void** devPtr, unsigned int size); + void freeArray(void* devPtr); +// overrides for CUDA version + virtual void setParameters(bt3DGridBroadphaseParams* hostParams); + virtual void prepareAABB(); + virtual void calcHashAABB(); + virtual void sortHash(); + virtual void findCellStart(); + virtual void findOverlappingPairs(); + virtual void findPairsLarge(); + virtual void computePairCacheChanges(); + virtual void scanOverlappingPairBuff(); + virtual void squeezeOverlappingPairBuff(); + virtual void resetPool(btDispatcher* dispatcher); +}; + +#endif //CUDA_BROADPHASE_H \ No newline at end of file diff --git a/Extras/CUDA/btCudaDefines.h b/Extras/CUDA/btCudaDefines.h new file mode 100644 index 0000000..aae8522 --- /dev/null +++ b/Extras/CUDA/btCudaDefines.h @@ -0,0 +1,138 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +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. +*/ + + + +// Common preprocessor definitions for CUDA compiler + + + +#ifndef BTCUDADEFINES_H +#define BTCUDADEFINES_H + + + +#ifdef __DEVICE_EMULATION__ + #define B_CUDA_USE_TEX 0 +#else + #define B_CUDA_USE_TEX 1 +#endif + + +#if B_CUDA_USE_TEX + #define BT_GPU_FETCH(t, i) tex_fetch3F1U(tex1Dfetch(t##Tex, i)) + #define BT_GPU_FETCH4(t, i) tex1Dfetch(t##Tex, i) +#else + #define BT_GPU_FETCH(t, i) t[i] + #define BT_GPU_FETCH4(t, i) t[i] +#endif + + + +#define BT_GPU___device__ __device__ +#define BT_GPU___devdata__ __device__ +#define BT_GPU___constant__ __constant__ +#define BT_GPU_max(a, b) max(a, b) +#define BT_GPU_min(a, b) min(a, b) +#define BT_GPU_params params +#define BT_GPU___mul24(a, b) __mul24(a, b) +#define BT_GPU___global__ __global__ +#define BT_GPU___shared__ __shared__ +#define BT_GPU___syncthreads() __syncthreads() +#define BT_GPU_make_uint2(x, y) make_uint2(x, y) +#define BT_GPU_make_int3(x, y, z) make_int3(x, y, z) +#define BT_GPU_make_float3(x, y, z) make_float3(x, y, z) +#define BT_GPU_make_float34(x) make_float3(x) +#define BT_GPU_make_float31(x) make_float3(x) +#define BT_GPU_make_float42(a, b) make_float4(a, b) +#define BT_GPU_make_float44(a, b, c, d) make_float4(a, b, c, d) +#define BT_GPU_PREF(func) btCuda_##func +#define BT_GPU_Memset cudaMemset +#define BT_GPU_MemcpyToSymbol(a, b, c) cudaMemcpyToSymbol(a, b, c) +#define BT_GPU_blockIdx blockIdx +#define BT_GPU_blockDim blockDim +#define BT_GPU_threadIdx threadIdx +#define BT_GPU_dot(a, b) dot(a, b) +#define BT_GPU_dot4(a, b) dot(a, b) +#define BT_GPU_cross(a, b) cross(a, b) +#define BT_GPU_BindTexture(a, b, c, d) cudaBindTexture(a, b, c, d) +#define BT_GPU_UnbindTexture(a) cudaUnbindTexture(a) +#define BT_GPU_EXECKERNEL(numb, numt, kfunc, args) kfunc<<>>args + + + +//! Check for CUDA error +#define BT_GPU_CHECK_ERROR(errorMessage) \ + do \ + { \ + cudaError_t err = cudaGetLastError(); \ + if(err != cudaSuccess) \ + { \ + fprintf(stderr,"Cuda error: %s in file '%s' in line %i : %s.\n",\ + errorMessage, __FILE__, __LINE__, cudaGetErrorString( err));\ + btCuda_exit(EXIT_FAILURE); \ + } \ + err = cudaThreadSynchronize(); \ + if(err != cudaSuccess) \ + { \ + fprintf(stderr,"Cuda error: %s in file '%s' in line %i : %s.\n",\ + errorMessage, __FILE__, __LINE__, cudaGetErrorString( err));\ + btCuda_exit(EXIT_FAILURE); \ + } \ + } \ + while(0) + + + +#define BT_GPU_SAFE_CALL_NO_SYNC(call) \ + do \ + { \ + cudaError err = call; \ + if(err != cudaSuccess) \ + { \ + fprintf(stderr, "Cuda error in file '%s' in line %i : %s.\n", \ + __FILE__, __LINE__, cudaGetErrorString( err) ); \ + btCuda_exit(EXIT_FAILURE); \ + } \ + } \ + while(0) + + + +#define BT_GPU_SAFE_CALL(call) \ + do \ + { \ + BT_GPU_SAFE_CALL_NO_SYNC(call); \ + cudaError err = cudaThreadSynchronize(); \ + if(err != cudaSuccess) \ + { \ + fprintf(stderr,"Cuda errorSync in file '%s' in line %i : %s.\n",\ + __FILE__, __LINE__, cudaGetErrorString( err) ); \ + btCuda_exit(EXIT_FAILURE); \ + } \ + } while (0) + + + +extern "C" void btCuda_exit(int val); + + + +#endif // BTCUDADEFINES_H + + + + + diff --git a/Extras/CUDA/btCudaUtils.cu b/Extras/CUDA/btCudaUtils.cu new file mode 100644 index 0000000..cdea10b --- /dev/null +++ b/Extras/CUDA/btCudaUtils.cu @@ -0,0 +1,84 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +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 +#include +#include + +#include +#include + +#include "cutil_math.h" +#include "math_constants.h" + +#include + + + + +#include "btCudaDefines.h" +#include "../../src/BulletMultiThreaded/btGpuUtilsSharedDefs.h" + + +void btCuda_exit(int val) +{ + fprintf(stderr, "Press ENTER key to terminate the program\n"); + getchar(); + exit(val); +} + +void btCuda_allocateArray(void** devPtr, unsigned int size) +{ + BT_GPU_SAFE_CALL(cudaMalloc(devPtr, size)); +} + +void btCuda_freeArray(void* devPtr) +{ + BT_GPU_SAFE_CALL(cudaFree(devPtr)); +} + +void btCuda_copyArrayFromDevice(void* host, const void* device, unsigned int size) +{ + BT_GPU_SAFE_CALL(cudaMemcpy(host, device, size, cudaMemcpyDeviceToHost)); +} + +void btCuda_copyArrayToDevice(void* device, const void* host, unsigned int size) +{ + BT_GPU_SAFE_CALL(cudaMemcpy((char*)device, host, size, cudaMemcpyHostToDevice)); +} + + +void btCuda_registerGLBufferObject(unsigned int vbo) +{ + BT_GPU_SAFE_CALL(cudaGLRegisterBufferObject(vbo)); +} + +void* btCuda_mapGLBufferObject(unsigned int vbo) +{ + void *ptr; + BT_GPU_SAFE_CALL(cudaGLMapBufferObject(&ptr, vbo)); + return ptr; +} + +void btCuda_unmapGLBufferObject(unsigned int vbo) +{ + BT_GPU_SAFE_CALL(cudaGLUnmapBufferObject(vbo)); +} + + + +#include "../../src/BulletMultiThreaded/btGpuUtilsSharedCode.h" + + diff --git a/Extras/CUDA/btGpuDemo2dCudaFunc.cu b/Extras/CUDA/btGpuDemo2dCudaFunc.cu new file mode 100644 index 0000000..aae708a --- /dev/null +++ b/Extras/CUDA/btGpuDemo2dCudaFunc.cu @@ -0,0 +1,42 @@ +/* +Impulse based Rigid body simulation using CUDA +Copyright (c) 2007 Takahiro Harada http://www.iii.u-tokyo.ac.jp/~takahiroharada/projects/impulseCUDA.html + +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 +#include +#include + +#include "cutil_math.h" +#include "math_constants.h" + +#include + + + +#include "btCudaDefines.h" + + + +#include "../../src/BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#include "../../Demos/Gpu2dDemo/btGpuDemo2dSharedTypes.h" +#include "../../Demos/Gpu2dDemo/btGpuDemo2dSharedDefs.h" + + + +texture posTex; + + + +#include "../../Demos/Gpu2dDemo/btGpuDemo2dSharedCode.h" + diff --git a/Extras/CUDA/btGpuDemo3dCudaFunc.cu b/Extras/CUDA/btGpuDemo3dCudaFunc.cu new file mode 100644 index 0000000..2ce7006 --- /dev/null +++ b/Extras/CUDA/btGpuDemo3dCudaFunc.cu @@ -0,0 +1,46 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +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 +#include +#include + +#include "../../Extras/CUDA/cutil_math.h" +#include "math_constants.h" + +#include + +//---------------------------------------------------------------------------------------- + +#include "../../Extras/CUDA/btCudaDefines.h" + +//---------------------------------------------------------------------------------------- + +#include "../../src/BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#include "../../Demos/Gpu3dDemo/btGpuDemo3dSharedTypes.h" +#include "../../Demos/Gpu3dDemo/btGpuDemo3dSharedDefs.h" + +//---------------------------------------------------------------------------------------- + +texture posTex; + +//---------------------------------------------------------------------------------------- + +#include "../../Demos/Gpu3dDemo/btGpuDemo3dSharedCode.h" + +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- + diff --git a/Extras/CUDA/cutil_gl_error.h b/Extras/CUDA/cutil_gl_error.h new file mode 100644 index 0000000..3d1a5ad --- /dev/null +++ b/Extras/CUDA/cutil_gl_error.h @@ -0,0 +1,86 @@ +/* +* Copyright 1993-2006 NVIDIA Corporation. All rights reserved. +* +* NOTICE TO USER: +* +* This source code is subject to NVIDIA ownership rights under U.S. and +* international Copyright laws. +* +* NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE +* CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR +* IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH +* REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF +* MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. +* IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, +* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE +* OR PERFORMANCE OF THIS SOURCE CODE. +* +* U.S. Government End Users. This source code is a "commercial item" as +* that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of +* "commercial computer software" and "commercial computer software +* documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) +* and is provided to the U.S. Government only as a commercial end item. +* Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through +* 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the +* source code with only those rights set forth herein. +*/ + +#ifndef CUTIL_GL_ERROR +#define CUTIL_GL_ERROR + +/* CUda UTility Library */ + +// includes, system +#ifdef _WIN32 +# define WINDOWS_LEAN_AND_MEAN +# include +# include +# undef min +# undef max +#endif + +// includes, graphics +#if defined (__APPLE__) || defined(MACOSX) +#include +#include +#else +#include +#include +#endif + +//////////////////////////////////////////////////////////////////////////// +//! Check for OpenGL error +//! @return CUTTrue if no GL error has been encountered, otherwise 0 +//! @param file __FILE__ macro +//! @param line __LINE__ macro +//! @note The GL error is listed on stderr +//! @note This function should be used via the CHECK_ERROR_GL() macro +//////////////////////////////////////////////////////////////////////////// +CUTBoolean CUTIL_API +cutCheckErrorGL( const char* file, const int line) +{ + CUTBoolean ret_val = CUTTrue; + + // check for error + GLenum gl_error = glGetError(); + if (gl_error != GL_NO_ERROR) + { + fprintf(stderr, "GL Error in file '%s' in line %d :\n", file, line); + fprintf(stderr, "%s\n", gluErrorString(gl_error)); + ret_val = CUTFalse; + } + return ret_val; +} + +#ifdef _DEBUG + +#define CUT_CHECK_ERROR_GL() \ + if( CUTFalse == cutCheckErrorGL( __FILE__, __LINE__)) { \ + exit(EXIT_FAILURE); \ + } + +#endif // _DEBUG + +#endif // CUTIL_GL_ERROR diff --git a/Extras/CUDA/cutil_math.h b/Extras/CUDA/cutil_math.h new file mode 100644 index 0000000..55d655d --- /dev/null +++ b/Extras/CUDA/cutil_math.h @@ -0,0 +1,767 @@ + /* + * Copyright 1993-2007 NVIDIA Corporation. All rights reserved. + * + * NOTICE TO USER: + * + * This source code is subject to NVIDIA ownership rights under U.S. and + * international Copyright laws. Users and possessors of this source code + * are hereby granted a nonexclusive, royalty-free license to use this code + * in individual and commercial software. + * + * NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE + * CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR + * IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. + * IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOURCE CODE. + * + * U.S. Government End Users. This source code is a "commercial item" as + * that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of + * "commercial computer software" and "commercial computer software + * documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) + * and is provided to the U.S. Government only as a commercial end item. + * Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through + * 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the + * source code with only those rights set forth herein. + * + * Any use of this source code in individual and commercial software must + * include, in the user documentation and internal comments to the code, + * the above Disclaimer and U.S. Government End Users Notice. + */ + +/* + This file implements common mathematical operations on vector types + (float3, float4 etc.) since these are not provided as standard by CUDA. + + The syntax is modelled on the Cg standard library. +*/ + +#ifndef CUTIL_MATH_H +#define CUTIL_MATH_H + +#include "cuda_runtime.h" + +//////////////////////////////////////////////////////////////////////////////// +typedef unsigned int uint; +typedef unsigned short ushort; + +#ifndef __CUDACC__ +#include + +inline float fminf(float a, float b) +{ + return a < b ? a : b; +} + +inline float fmaxf(float a, float b) +{ + return a < b ? a : b; +} + +inline int max(int a, int b) +{ + return a > b ? a : b; +} + +inline int min(int a, int b) +{ + return a < b ? a : b; +} +#endif + +// float functions +//////////////////////////////////////////////////////////////////////////////// + +// lerp +inline __device__ __host__ float lerp(float a, float b, float t) +{ + return a + t*(b-a); +} + +// clamp +inline __device__ __host__ float clamp(float f, float a, float b) +{ + return fmaxf(a, fminf(f, b)); +} + +// int2 functions +//////////////////////////////////////////////////////////////////////////////// + +// negate +inline __host__ __device__ int2 operator-(int2 &a) +{ + return make_int2(-a.x, -a.y); +} + +// addition +inline __host__ __device__ int2 operator+(int2 a, int2 b) +{ + return make_int2(a.x + b.x, a.y + b.y); +} +inline __host__ __device__ void operator+=(int2 &a, int2 b) +{ + a.x += b.x; a.y += b.y; +} + +// subtract +inline __host__ __device__ int2 operator-(int2 a, int2 b) +{ + return make_int2(a.x - b.x, a.y - b.y); +} +inline __host__ __device__ void operator-=(int2 &a, int2 b) +{ + a.x -= b.x; a.y -= b.y; +} + +// multiply +inline __host__ __device__ int2 operator*(int2 a, int2 b) +{ + return make_int2(a.x * b.x, a.y * b.y); +} +inline __host__ __device__ int2 operator*(int2 a, int s) +{ + return make_int2(a.x * s, a.y * s); +} +inline __host__ __device__ int2 operator*(int s, int2 a) +{ + return make_int2(a.x * s, a.y * s); +} +inline __host__ __device__ void operator*=(int2 &a, int s) +{ + a.x *= s; a.y *= s; +} + +// float2 functions +//////////////////////////////////////////////////////////////////////////////// + +// additional constructors +inline __host__ __device__ float2 make_float2(float s) +{ + return make_float2(s, s); +} +inline __host__ __device__ float2 make_float2(int2 a) +{ + return make_float2(float(a.x), float(a.y)); +} + +// negate +inline __host__ __device__ float2 operator-(float2 &a) +{ + return make_float2(-a.x, -a.y); +} + +// addition +inline __host__ __device__ float2 operator+(float2 a, float2 b) +{ + return make_float2(a.x + b.x, a.y + b.y); +} +inline __host__ __device__ void operator+=(float2 &a, float2 b) +{ + a.x += b.x; a.y += b.y; +} + +// subtract +inline __host__ __device__ float2 operator-(float2 a, float2 b) +{ + return make_float2(a.x - b.x, a.y - b.y); +} +inline __host__ __device__ void operator-=(float2 &a, float2 b) +{ + a.x -= b.x; a.y -= b.y; +} + +// multiply +inline __host__ __device__ float2 operator*(float2 a, float2 b) +{ + return make_float2(a.x * b.x, a.y * b.y); +} +inline __host__ __device__ float2 operator*(float2 a, float s) +{ + return make_float2(a.x * s, a.y * s); +} +inline __host__ __device__ float2 operator*(float s, float2 a) +{ + return make_float2(a.x * s, a.y * s); +} +inline __host__ __device__ void operator*=(float2 &a, float s) +{ + a.x *= s; a.y *= s; +} + +// divide +inline __host__ __device__ float2 operator/(float2 a, float2 b) +{ + return make_float2(a.x / b.x, a.y / b.y); +} +inline __host__ __device__ float2 operator/(float2 a, float s) +{ + float inv = 1.0f / s; + return a * inv; +} +inline __host__ __device__ float2 operator/(float s, float2 a) +{ + float inv = 1.0f / s; + return a * inv; +} +inline __host__ __device__ void operator/=(float2 &a, float s) +{ + float inv = 1.0f / s; + a *= inv; +} + +// lerp +inline __device__ __host__ float2 lerp(float2 a, float2 b, float t) +{ + return a + t*(b-a); +} + +// clamp +inline __device__ __host__ float2 clamp(float2 v, float a, float b) +{ + return make_float2(clamp(v.x, a, b), clamp(v.y, a, b)); +} + +inline __device__ __host__ float2 clamp(float2 v, float2 a, float2 b) +{ + return make_float2(clamp(v.x, a.x, b.x), clamp(v.y, a.y, b.y)); +} + +// dot product +inline __host__ __device__ float dot(float2 a, float2 b) +{ + return a.x * b.x + a.y * b.y; +} + +// length +inline __host__ __device__ float length(float2 v) +{ + return sqrtf(dot(v, v)); +} + +// normalize +inline __host__ __device__ float2 normalize(float2 v) +{ + float invLen = 1.0f / sqrtf(dot(v, v)); + return v * invLen; +} + +// floor +inline __host__ __device__ float2 floor(const float2 v) +{ + return make_float2(floor(v.x), floor(v.y)); +} + +// reflect +inline __host__ __device__ float2 reflect(float2 i, float2 n) +{ + return i - 2.0f * n * dot(n,i); +} + +// float3 functions +//////////////////////////////////////////////////////////////////////////////// + +// additional constructors +inline __host__ __device__ float3 make_float3(float s) +{ + return make_float3(s, s, s); +} +inline __host__ __device__ float3 make_float3(float2 a) +{ + return make_float3(a.x, a.y, 0.0f); +} +inline __host__ __device__ float3 make_float3(float2 a, float s) +{ + return make_float3(a.x, a.y, s); +} +inline __host__ __device__ float3 make_float3(float4 a) +{ + return make_float3(a.x, a.y, a.z); // discards w +} +inline __host__ __device__ float3 make_float3(int3 a) +{ + return make_float3(float(a.x), float(a.y), float(a.z)); +} + +// negate +inline __host__ __device__ float3 operator-(float3 &a) +{ + return make_float3(-a.x, -a.y, -a.z); +} + +// min +static __inline__ __host__ __device__ float3 fminf(float3 a, float3 b) +{ + return make_float3(fminf(a.x,b.x), fminf(a.y,b.y), fminf(a.z,b.z)); +} + +// max +static __inline__ __host__ __device__ float3 fmaxf(float3 a, float3 b) +{ + return make_float3(fmaxf(a.x,b.x), fmaxf(a.y,b.y), fmaxf(a.z,b.z)); +} + +// addition +inline __host__ __device__ float3 operator+(float3 a, float3 b) +{ + return make_float3(a.x + b.x, a.y + b.y, a.z + b.z); +} +inline __host__ __device__ float3 operator+(float3 a, float b) +{ + return make_float3(a.x + b, a.y + b, a.z + b); +} +inline __host__ __device__ void operator+=(float3 &a, float3 b) +{ + a.x += b.x; a.y += b.y; a.z += b.z; +} + +// subtract +inline __host__ __device__ float3 operator-(float3 a, float3 b) +{ + return make_float3(a.x - b.x, a.y - b.y, a.z - b.z); +} +inline __host__ __device__ float3 operator-(float3 a, float b) +{ + return make_float3(a.x - b, a.y - b, a.z - b); +} +inline __host__ __device__ void operator-=(float3 &a, float3 b) +{ + a.x -= b.x; a.y -= b.y; a.z -= b.z; +} + +// multiply +inline __host__ __device__ float3 operator*(float3 a, float3 b) +{ + return make_float3(a.x * b.x, a.y * b.y, a.z * b.z); +} +inline __host__ __device__ float3 operator*(float3 a, float s) +{ + return make_float3(a.x * s, a.y * s, a.z * s); +} +inline __host__ __device__ float3 operator*(float s, float3 a) +{ + return make_float3(a.x * s, a.y * s, a.z * s); +} +inline __host__ __device__ void operator*=(float3 &a, float s) +{ + a.x *= s; a.y *= s; a.z *= s; +} + +// divide +inline __host__ __device__ float3 operator/(float3 a, float3 b) +{ + return make_float3(a.x / b.x, a.y / b.y, a.z / b.z); +} +inline __host__ __device__ float3 operator/(float3 a, float s) +{ + float inv = 1.0f / s; + return a * inv; +} +inline __host__ __device__ float3 operator/(float s, float3 a) +{ + float inv = 1.0f / s; + return a * inv; +} +inline __host__ __device__ void operator/=(float3 &a, float s) +{ + float inv = 1.0f / s; + a *= inv; +} + +// lerp +inline __device__ __host__ float3 lerp(float3 a, float3 b, float t) +{ + return a + t*(b-a); +} + +// clamp +inline __device__ __host__ float3 clamp(float3 v, float a, float b) +{ + return make_float3(clamp(v.x, a, b), clamp(v.y, a, b), clamp(v.z, a, b)); +} + +inline __device__ __host__ float3 clamp(float3 v, float3 a, float3 b) +{ + return make_float3(clamp(v.x, a.x, b.x), clamp(v.y, a.y, b.y), clamp(v.z, a.z, b.z)); +} + +// dot product +inline __host__ __device__ float dot(float3 a, float3 b) +{ + return a.x * b.x + a.y * b.y + a.z * b.z; +} + +// cross product +inline __host__ __device__ float3 cross(float3 a, float3 b) +{ + return make_float3(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x); +} + +// length +inline __host__ __device__ float length(float3 v) +{ + return sqrtf(dot(v, v)); +} + +// normalize +inline __host__ __device__ float3 normalize(float3 v) +{ + float invLen = 1.0f / sqrtf(dot(v, v)); + return v * invLen; +} + +// floor +inline __host__ __device__ float3 floor(const float3 v) +{ + return make_float3(floor(v.x), floor(v.y), floor(v.z)); +} + +// reflect +inline __host__ __device__ float3 reflect(float3 i, float3 n) +{ + return i - 2.0f * n * dot(n,i); +} + +// float4 functions +//////////////////////////////////////////////////////////////////////////////// + +// additional constructors +inline __host__ __device__ float4 make_float4(float s) +{ + return make_float4(s, s, s, s); +} +inline __host__ __device__ float4 make_float4(float3 a) +{ + return make_float4(a.x, a.y, a.z, 0.0f); +} +inline __host__ __device__ float4 make_float4(float3 a, float w) +{ + return make_float4(a.x, a.y, a.z, w); +} +inline __host__ __device__ float4 make_float4(int4 a) +{ + return make_float4(float(a.x), float(a.y), float(a.z), float(a.w)); +} + +// negate +inline __host__ __device__ float4 operator-(float4 &a) +{ + return make_float4(-a.x, -a.y, -a.z, -a.w); +} + +// min +static __inline__ __host__ __device__ float4 fminf(float4 a, float4 b) +{ + return make_float4(fminf(a.x,b.x), fminf(a.y,b.y), fminf(a.z,b.z), fminf(a.w,b.w)); +} + +// max +static __inline__ __host__ __device__ float4 fmaxf(float4 a, float4 b) +{ + return make_float4(fmaxf(a.x,b.x), fmaxf(a.y,b.y), fmaxf(a.z,b.z), fmaxf(a.w,b.w)); +} + +// addition +inline __host__ __device__ float4 operator+(float4 a, float4 b) +{ + return make_float4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); +} +inline __host__ __device__ void operator+=(float4 &a, float4 b) +{ + a.x += b.x; a.y += b.y; a.z += b.z; a.w += b.w; +} + +// subtract +inline __host__ __device__ float4 operator-(float4 a, float4 b) +{ + return make_float4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); +} +inline __host__ __device__ void operator-=(float4 &a, float4 b) +{ + a.x -= b.x; a.y -= b.y; a.z -= b.z; a.w -= b.w; +} + +// multiply +inline __host__ __device__ float4 operator*(float4 a, float s) +{ + return make_float4(a.x * s, a.y * s, a.z * s, a.w * s); +} +inline __host__ __device__ float4 operator*(float s, float4 a) +{ + return make_float4(a.x * s, a.y * s, a.z * s, a.w * s); +} +inline __host__ __device__ void operator*=(float4 &a, float s) +{ + a.x *= s; a.y *= s; a.z *= s; a.w *= s; +} + +// divide +inline __host__ __device__ float4 operator/(float4 a, float4 b) +{ + return make_float4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w); +} +inline __host__ __device__ float4 operator/(float4 a, float s) +{ + float inv = 1.0f / s; + return a * inv; +} +inline __host__ __device__ float4 operator/(float s, float4 a) +{ + float inv = 1.0f / s; + return a * inv; +} +inline __host__ __device__ void operator/=(float4 &a, float s) +{ + float inv = 1.0f / s; + a *= inv; +} + +// lerp +inline __device__ __host__ float4 lerp(float4 a, float4 b, float t) +{ + return a + t*(b-a); +} + +// clamp +inline __device__ __host__ float4 clamp(float4 v, float a, float b) +{ + return make_float4(clamp(v.x, a, b), clamp(v.y, a, b), clamp(v.z, a, b), clamp(v.w, a, b)); +} + +inline __device__ __host__ float4 clamp(float4 v, float4 a, float4 b) +{ + return make_float4(clamp(v.x, a.x, b.x), clamp(v.y, a.y, b.y), clamp(v.z, a.z, b.z), clamp(v.w, a.w, b.w)); +} + +// dot product +inline __host__ __device__ float dot(float4 a, float4 b) +{ + return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; +} + +// length +inline __host__ __device__ float length(float4 r) +{ + return sqrtf(dot(r, r)); +} + +// normalize +inline __host__ __device__ float4 normalize(float4 v) +{ + float invLen = 1.0f / sqrtf(dot(v, v)); + return v * invLen; +} + +// floor +inline __host__ __device__ float4 floor(const float4 v) +{ + return make_float4(floor(v.x), floor(v.y), floor(v.z), floor(v.w)); +} + +// int3 functions +//////////////////////////////////////////////////////////////////////////////// + +// additional constructors +inline __host__ __device__ int3 make_int3(int s) +{ + return make_int3(s, s, s); +} +inline __host__ __device__ int3 make_int3(float3 a) +{ + return make_int3(int(a.x), int(a.y), int(a.z)); +} + +// negate +inline __host__ __device__ int3 operator-(int3 &a) +{ + return make_int3(-a.x, -a.y, -a.z); +} + +// min +inline __host__ __device__ int3 min(int3 a, int3 b) +{ + return make_int3(min(a.x,b.x), min(a.y,b.y), min(a.z,b.z)); +} + +// max +inline __host__ __device__ int3 max(int3 a, int3 b) +{ + return make_int3(max(a.x,b.x), max(a.y,b.y), max(a.z,b.z)); +} + +// addition +inline __host__ __device__ int3 operator+(int3 a, int3 b) +{ + return make_int3(a.x + b.x, a.y + b.y, a.z + b.z); +} +inline __host__ __device__ void operator+=(int3 &a, int3 b) +{ + a.x += b.x; a.y += b.y; a.z += b.z; +} + +// subtract +inline __host__ __device__ int3 operator-(int3 a, int3 b) +{ + return make_int3(a.x - b.x, a.y - b.y, a.z - b.z); +} + +inline __host__ __device__ void operator-=(int3 &a, int3 b) +{ + a.x -= b.x; a.y -= b.y; a.z -= b.z; +} + +// multiply +inline __host__ __device__ int3 operator*(int3 a, int3 b) +{ + return make_int3(a.x * b.x, a.y * b.y, a.z * b.z); +} +inline __host__ __device__ int3 operator*(int3 a, int s) +{ + return make_int3(a.x * s, a.y * s, a.z * s); +} +inline __host__ __device__ int3 operator*(int s, int3 a) +{ + return make_int3(a.x * s, a.y * s, a.z * s); +} +inline __host__ __device__ void operator*=(int3 &a, int s) +{ + a.x *= s; a.y *= s; a.z *= s; +} + +// divide +inline __host__ __device__ int3 operator/(int3 a, int3 b) +{ + return make_int3(a.x / b.x, a.y / b.y, a.z / b.z); +} +inline __host__ __device__ int3 operator/(int3 a, int s) +{ + return make_int3(a.x / s, a.y / s, a.z / s); +} +inline __host__ __device__ int3 operator/(int s, int3 a) +{ + return make_int3(a.x / s, a.y / s, a.z / s); +} +inline __host__ __device__ void operator/=(int3 &a, int s) +{ + a.x /= s; a.y /= s; a.z /= s; +} + +// clamp +inline __device__ __host__ int clamp(int f, int a, int b) +{ + return max(a, min(f, b)); +} + +inline __device__ __host__ int3 clamp(int3 v, int a, int b) +{ + return make_int3(clamp(v.x, a, b), clamp(v.y, a, b), clamp(v.z, a, b)); +} + +inline __device__ __host__ int3 clamp(int3 v, int3 a, int3 b) +{ + return make_int3(clamp(v.x, a.x, b.x), clamp(v.y, a.y, b.y), clamp(v.z, a.z, b.z)); +} + + +// uint3 functions +//////////////////////////////////////////////////////////////////////////////// + +// additional constructors +inline __host__ __device__ uint3 make_uint3(uint s) +{ + return make_uint3(s, s, s); +} +inline __host__ __device__ uint3 make_uint3(float3 a) +{ + return make_uint3(uint(a.x), uint(a.y), uint(a.z)); +} + +// min +inline __host__ __device__ uint3 min(uint3 a, uint3 b) +{ + return make_uint3(min(a.x,b.x), min(a.y,b.y), min(a.z,b.z)); +} + +// max +inline __host__ __device__ uint3 max(uint3 a, uint3 b) +{ + return make_uint3(max(a.x,b.x), max(a.y,b.y), max(a.z,b.z)); +} + +// addition +inline __host__ __device__ uint3 operator+(uint3 a, uint3 b) +{ + return make_uint3(a.x + b.x, a.y + b.y, a.z + b.z); +} +inline __host__ __device__ void operator+=(uint3 &a, uint3 b) +{ + a.x += b.x; a.y += b.y; a.z += b.z; +} + +// subtract +inline __host__ __device__ uint3 operator-(uint3 a, uint3 b) +{ + return make_uint3(a.x - b.x, a.y - b.y, a.z - b.z); +} + +inline __host__ __device__ void operator-=(uint3 &a, uint3 b) +{ + a.x -= b.x; a.y -= b.y; a.z -= b.z; +} + +// multiply +inline __host__ __device__ uint3 operator*(uint3 a, uint3 b) +{ + return make_uint3(a.x * b.x, a.y * b.y, a.z * b.z); +} +inline __host__ __device__ uint3 operator*(uint3 a, uint s) +{ + return make_uint3(a.x * s, a.y * s, a.z * s); +} +inline __host__ __device__ uint3 operator*(uint s, uint3 a) +{ + return make_uint3(a.x * s, a.y * s, a.z * s); +} +inline __host__ __device__ void operator*=(uint3 &a, uint s) +{ + a.x *= s; a.y *= s; a.z *= s; +} + +// divide +inline __host__ __device__ uint3 operator/(uint3 a, uint3 b) +{ + return make_uint3(a.x / b.x, a.y / b.y, a.z / b.z); +} +inline __host__ __device__ uint3 operator/(uint3 a, uint s) +{ + return make_uint3(a.x / s, a.y / s, a.z / s); +} +inline __host__ __device__ uint3 operator/(uint s, uint3 a) +{ + return make_uint3(a.x / s, a.y / s, a.z / s); +} +inline __host__ __device__ void operator/=(uint3 &a, uint s) +{ + a.x /= s; a.y /= s; a.z /= s; +} + +// clamp +inline __device__ __host__ uint clamp(uint f, uint a, uint b) +{ + return max(a, min(f, b)); +} + +inline __device__ __host__ uint3 clamp(uint3 v, uint a, uint b) +{ + return make_uint3(clamp(v.x, a, b), clamp(v.y, a, b), clamp(v.z, a, b)); +} + +inline __device__ __host__ uint3 clamp(uint3 v, uint3 a, uint3 b) +{ + return make_uint3(clamp(v.x, a.x, b.x), clamp(v.y, a.y, b.y), clamp(v.z, a.z, b.z)); +} + +#endif diff --git a/Extras/CUDA/libbulletcuda.vcproj b/Extras/CUDA/libbulletcuda.vcproj new file mode 100644 index 0000000..7e0a3dd --- /dev/null +++ b/Extras/CUDA/libbulletcuda.vcproj @@ -0,0 +1,665 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/CUDA/radixsort.cu b/Extras/CUDA/radixsort.cu new file mode 100644 index 0000000..24c85c6 --- /dev/null +++ b/Extras/CUDA/radixsort.cu @@ -0,0 +1,79 @@ +/* + * Copyright 1993-2006 NVIDIA Corporation. All rights reserved. + * + * NOTICE TO USER: + * + * This source code is subject to NVIDIA ownership rights under U.S. and + * international Copyright laws. + * + * NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE + * CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR + * IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. + * IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOURCE CODE. + * + * U.S. Government End Users. This source code is a "commercial item" as + * that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of + * "commercial computer software" and "commercial computer software + * documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) + * and is provided to the U.S. Government only as a commercial end item. + * Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through + * 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the + * source code with only those rights set forth herein. + */ + +/* Radixsort project with key/value and arbitrary datset size support + * which demonstrates the use of CUDA in a multi phase sorting + * computation. + * Host code. + */ + +#include "radixsort.cuh" +#include "radixsort_kernel.cu" + +extern "C" +{ + +//////////////////////////////////////////////////////////////////////////////// +//! Perform a radix sort +//! Sorting performed in place on passed arrays. +//! +//! @param pData0 input and output array - data will be sorted +//! @param pData1 additional array to allow ping pong computation +//! @param elements number of elements to sort +//////////////////////////////////////////////////////////////////////////////// +void RadixSort(KeyValuePair *pData0, KeyValuePair *pData1, uint elements, uint bits) +{ + // Round element count to total number of threads for efficiency + uint elements_rounded_to_3072; + int modval = elements % 3072; + if( modval == 0 ) + elements_rounded_to_3072 = elements; + else + elements_rounded_to_3072 = elements + (3072 - (modval)); + + // Iterate over n bytes of y bit word, using each byte to sort the list in turn + for (uint shift = 0; shift < bits; shift += RADIX) + { + // Perform one round of radix sorting + + // Generate per radix group sums radix counts across a radix group + RadixSum<<>>(pData0, elements, elements_rounded_to_3072, shift); + // Prefix sum in radix groups, and then between groups throughout a block + RadixPrefixSum<<>>(); + // Sum the block offsets and then shuffle data into bins + RadixAddOffsetsAndShuffle<<>>(pData0, pData1, elements, elements_rounded_to_3072, shift); + + // Exchange data pointers + KeyValuePair* pTemp = pData0; + pData0 = pData1; + pData1 = pTemp; + } +} + +} diff --git a/Extras/CUDA/radixsort.cuh b/Extras/CUDA/radixsort.cuh new file mode 100644 index 0000000..538bb11 --- /dev/null +++ b/Extras/CUDA/radixsort.cuh @@ -0,0 +1,63 @@ +/* + * Copyright 1993-2006 NVIDIA Corporation. All rights reserved. + * + * NOTICE TO USER: + * + * This source code is subject to NVIDIA ownership rights under U.S. and + * international Copyright laws. + * + * NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE + * CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR + * IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. + * IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOURCE CODE. + * + * U.S. Government End Users. This source code is a "commercial item" as + * that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of + * "commercial computer software" and "commercial computer software + * documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) + * and is provided to the U.S. Government only as a commercial end item. + * Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through + * 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the + * source code with only those rights set forth herein. + */ + +/* Radixsort project which demonstrates the use of CUDA in a multi phase + * sorting computation. + * Type definitions. + */ + +#ifndef _RADIXSORT_H_ +#define _RADIXSORT_H_ + +#include + +#define SYNCIT __syncthreads() + +// Use 16 bit keys/values +#define SIXTEEN 0 + +typedef unsigned int uint; +typedef unsigned short ushort; + +#if SIXTEEN +typedef struct __align__(4) { + ushort key; + ushort value; +#else +typedef struct __align__(8) { + uint key; + uint value; +#endif +} KeyValuePair; + +extern "C" { + void RadixSort(KeyValuePair *pData0, KeyValuePair *pData1, uint elements, uint bits); +} + +#endif // #ifndef _RADIXSORT_H_ diff --git a/Extras/CUDA/radixsort_kernel.cu b/Extras/CUDA/radixsort_kernel.cu new file mode 100644 index 0000000..2025841 --- /dev/null +++ b/Extras/CUDA/radixsort_kernel.cu @@ -0,0 +1,577 @@ +/* + * Copyright 1993-2006 NVIDIA Corporation. All rights reserved. + * + * NOTICE TO USER: + * + * This source code is subject to NVIDIA ownership rights under U.S. and + * international Copyright laws. + * + * NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE + * CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR + * IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. + * IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOURCE CODE. + * + * U.S. Government End Users. This source code is a "commercial item" as + * that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of + * "commercial computer software" and "commercial computer software + * documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) + * and is provided to the U.S. Government only as a commercial end item. + * Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through + * 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the + * source code with only those rights set forth herein. + */ + +/* Radixsort project with key/value and arbitrary datset size support + * which demonstrates the use of CUDA in a multi phase sorting + * computation. + * Device code. + */ + +#ifndef _RADIXSORT_KERNEL_H_ +#define _RADIXSORT_KERNEL_H_ + +#include +#include "radixsort.cuh" + +#define SYNCIT __syncthreads() + +static const int NUM_SMS = 16; +static const int NUM_THREADS_PER_SM = 192; +static const int NUM_THREADS_PER_BLOCK = 64; +//static const int NUM_THREADS = NUM_THREADS_PER_SM * NUM_SMS; +static const int NUM_BLOCKS = (NUM_THREADS_PER_SM / NUM_THREADS_PER_BLOCK) * NUM_SMS; +static const int RADIX = 8; // Number of bits per radix sort pass +static const int RADICES = 1 << RADIX; // Number of radices +static const int RADIXMASK = RADICES - 1; // Mask for each radix sort pass +#if SIXTEEN +static const int RADIXBITS = 16; // Number of bits to sort over +#else +static const int RADIXBITS = 32; // Number of bits to sort over +#endif +static const int RADIXTHREADS = 16; // Number of threads sharing each radix counter +static const int RADIXGROUPS = NUM_THREADS_PER_BLOCK / RADIXTHREADS; // Number of radix groups per CTA +static const int TOTALRADIXGROUPS = NUM_BLOCKS * RADIXGROUPS; // Number of radix groups for each radix +static const int SORTRADIXGROUPS = TOTALRADIXGROUPS * RADICES; // Total radix count +static const int GRFELEMENTS = (NUM_THREADS_PER_BLOCK / RADIXTHREADS) * RADICES; +static const int GRFSIZE = GRFELEMENTS * sizeof(uint); + +// Prefix sum variables +static const int PREFIX_NUM_THREADS_PER_SM = NUM_THREADS_PER_SM; +static const int PREFIX_NUM_THREADS_PER_BLOCK = PREFIX_NUM_THREADS_PER_SM; +static const int PREFIX_NUM_BLOCKS = (PREFIX_NUM_THREADS_PER_SM / PREFIX_NUM_THREADS_PER_BLOCK) * NUM_SMS; +static const int PREFIX_BLOCKSIZE = SORTRADIXGROUPS / PREFIX_NUM_BLOCKS; +static const int PREFIX_GRFELEMENTS = PREFIX_BLOCKSIZE + 2 * PREFIX_NUM_THREADS_PER_BLOCK; +static const int PREFIX_GRFSIZE = PREFIX_GRFELEMENTS * sizeof(uint); + +// Shuffle variables +static const int SHUFFLE_GRFOFFSET = RADIXGROUPS * RADICES; +static const int SHUFFLE_GRFELEMENTS = SHUFFLE_GRFOFFSET + PREFIX_NUM_BLOCKS; +static const int SHUFFLE_GRFSIZE = SHUFFLE_GRFELEMENTS * sizeof(uint); + + +#define SDATA( index) CUT_BANK_CHECKER(sdata, index) + +// Prefix sum data +uint gRadixSum[TOTALRADIXGROUPS * RADICES]; +__device__ uint dRadixSum[TOTALRADIXGROUPS * RADICES]; +uint gRadixBlockSum[PREFIX_NUM_BLOCKS]; +__device__ uint dRadixBlockSum[PREFIX_NUM_BLOCKS]; + +extern __shared__ uint sRadixSum[]; + + + +//////////////////////////////////////////////////////////////////////////////// +//! Perform a radix sum on the list to be sorted. Each SM holds a set of +//! radix counters for each group of RADIXGROUPS thread in the GRF. +//! +//! @param pData input data +//! @param elements total number of elements +//! @param elements_rounded_to_3072 total number of elements rounded up to the +//! nearest multiple of 3072 +//! @param shift the shift (0 to 24) that we are using to obtain the correct +//! byte +//////////////////////////////////////////////////////////////////////////////// +__global__ void RadixSum(KeyValuePair *pData, uint elements, uint elements_rounded_to_3072, uint shift) +{ + uint pos = threadIdx.x; + + // Zero radix counts + while (pos < GRFELEMENTS) + { + sRadixSum[pos] = 0; + pos += NUM_THREADS_PER_BLOCK; + } + + // Sum up data + // Source addresses computed so that each thread is reading from a block of + // consecutive addresses so there are no conflicts between threads + // They then loop over their combined region and the next batch works elsewhere. + // So threads 0 to 16 work on memory 0 to 320. + // First reading 0,1,2,3...15 then 16,17,18,19...31 and so on + // optimising parallel access to shared memory by a thread accessing 16*threadID + // The next radix group runs from 320 to 640 and the same applies in that region + uint tmod = threadIdx.x % RADIXTHREADS; + uint tpos = threadIdx.x / RADIXTHREADS; + + // Take the rounded element list size so that all threads have a certain size dataset to work with + // and no zero size datasets confusing the issue + // By using a multiple of 3072 we ensure that all threads have elements + // to work with until the last phase, at which point we individually test + uint element_fraction = elements_rounded_to_3072 / TOTALRADIXGROUPS; + + // Generate range + // Note that it is possible for both pos and end to be past the end of the element set + // which will be caught later. + pos = (blockIdx.x * RADIXGROUPS + tpos) * element_fraction; + uint end = pos + element_fraction; + pos += tmod; + //printf("pos: %d\n", pos); + __syncthreads(); + + while (pos < end ) + { + uint key = 0; + + // Read first data element if we are in the set of elements + //if( pos < elements ) + //key = pData[pos].key; + KeyValuePair kvp; + // Read first data element, both items at once as the memory will want to coalesce like that anyway + if (pos < elements) + kvp = pData[pos]; + else + kvp.key = 0; + key = kvp.key; + + + // Calculate position of radix counter to increment + // There are RADICES radices in each pass (256) + // and hence this many counters for bin grouping + // Multiply by RADIXGROUPS (4) to spread through memory + // and into 4 radix groups + uint p = ((key >> shift) & RADIXMASK) * RADIXGROUPS; + + // Increment radix counters + // Each radix group has its own set of counters + // so we add the thread position [0-3], ie the group index. + // We slow down here and take at least 16 cycles to write to the summation boxes + // but other groups will only conflict with themselves and so can also be writing + // 16 cycles here at least avoids retries. + uint ppos = p + tpos; + + // If we are past the last element we don't want to do anything + // We do have to check each time, however, to ensure that all + // threads sync on each sync here. + if (tmod == 0 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 1 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 2 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 3 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 4 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 5 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 6 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 7 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 8 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 9 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 10 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 11 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 12 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 13 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 14 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 15 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + + pos += RADIXTHREADS; + + } + + __syncthreads(); + + __syncthreads(); + + // Output radix sums into separate memory regions for each radix group + // So this memory then is layed out: + // 0...... 192..... 384 ................ 192*256 + // ie all 256 bins for each radix group + // in there: + // 0.............192 + // 0 4 8 12... - block idx * 4 + // And in the block boxes we see the 4 radix groups for that block + // So 0-192 should contain bin 0 for each radix group, and so on + uint offset = blockIdx.x * RADIXGROUPS; + uint row = threadIdx.x / RADIXGROUPS; + uint column = threadIdx.x % RADIXGROUPS; + while (row < RADICES) + { + dRadixSum[offset + row * TOTALRADIXGROUPS + column] = sRadixSum[row * RADIXGROUPS + column]; + row += NUM_THREADS_PER_BLOCK / RADIXGROUPS; + } +} + +//////////////////////////////////////////////////////////////////////////////// +//! Performs first part of parallel prefix sum - individual sums of each radix +//! count. By the end of this we have prefix sums on a block level in dRadixSum +//! and totals for blocks in dRadixBlockSum. +//////////////////////////////////////////////////////////////////////////////// +__global__ void RadixPrefixSum() +{ + // Read radix groups in offset by one in the GRF so a zero can be inserted at the beginning + // and the final sum of all radix counts summed here is tacked onto the end for reading by + // the next stage + // Each block in this case is the full number of threads per SM (and hence the total number + // of radix groups), 192. We should then have the total set of offsets for an entire radix + // group by the end of this stage + // Device mem addressing + + uint brow = blockIdx.x * (RADICES / PREFIX_NUM_BLOCKS); + uint drow = threadIdx.x / TOTALRADIXGROUPS; // In default parameterisation this is always 0 + uint dcolumn = threadIdx.x % TOTALRADIXGROUPS; // And similarly this is always the same as threadIdx.x + uint dpos = (brow + drow) * TOTALRADIXGROUPS + dcolumn; + uint end = ((blockIdx.x + 1) * (RADICES / PREFIX_NUM_BLOCKS)) * TOTALRADIXGROUPS; + // Shared mem addressing + uint srow = threadIdx.x / (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK); + uint scolumn = threadIdx.x % (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK); + uint spos = srow * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1) + scolumn; + + // Read (RADICES / PREFIX_NUM_BLOCKS) radix counts into the GRF alongside each other + while (dpos < end) + { + sRadixSum[spos] = dRadixSum[dpos]; + spos += (PREFIX_NUM_THREADS_PER_BLOCK / (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK)) * + (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1); + dpos += (TOTALRADIXGROUPS / PREFIX_NUM_THREADS_PER_BLOCK) * TOTALRADIXGROUPS; + } + __syncthreads(); + + // Perform preliminary sum on each thread's stretch of data + // Each thread having a block of 16, with spacers between 0...16 18...33 and so on + int pos = threadIdx.x * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1); + end = pos + (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK); + uint sum = 0; + while (pos < end) + { + sum += sRadixSum[pos]; + sRadixSum[pos] = sum; + pos++; + } + __syncthreads(); + + + // Calculate internal offsets by performing a more traditional parallel + // prefix sum of the topmost member of each thread's work data. Right now, + // these are stored between the work data for each thread, allowing us to + // eliminate GRF conflicts as well as hold the offsets needed to complete the sum + // In other words we have: + // 0....15 16 17....32 33 34.... + // Where this first stage updates the intermediate values (so 16=15, 33=32 etc) + int m = (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1); + pos = threadIdx.x * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1) + + (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK); + sRadixSum[pos] = sRadixSum[pos - 1]; + __syncthreads(); + // This stage then performs a parallel prefix sum (ie use powers of 2 to propagate in log n stages) + // to update 17, 34 etc with the totals to that point (so 34 becomes [34] + [17]) and so on. + while (m < PREFIX_NUM_THREADS_PER_BLOCK * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1)) + { + int p = pos - m; + uint t = ((p > 0) ? sRadixSum[p] : 0); + __syncthreads(); + sRadixSum[pos] += t; + __syncthreads(); + m *= 2; + } + __syncthreads(); + + + + // Add internal offsets to each thread's work data. + // So now we take 17 and add it to all values 18 to 33 so all offsets for that block + // are updated. + pos = threadIdx.x * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1); + end = pos + (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK); + int p = pos - 1; + sum = ((p > 0) ? sRadixSum[p] : 0); + while (pos < end) + { + sRadixSum[pos] += sum; + pos++; + } + __syncthreads(); + + // Write summed data back out to global memory in the same way as we read it in + // We now have prefix sum values internal to groups + brow = blockIdx.x * (RADICES / PREFIX_NUM_BLOCKS); + drow = threadIdx.x / TOTALRADIXGROUPS; + dcolumn = threadIdx.x % TOTALRADIXGROUPS; + srow = threadIdx.x / (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK); + scolumn = threadIdx.x % (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK); + dpos = (brow + drow) * TOTALRADIXGROUPS + dcolumn + 1; + spos = srow * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1) + scolumn; + end = ((blockIdx.x + 1) * RADICES / PREFIX_NUM_BLOCKS) * TOTALRADIXGROUPS; + while (dpos < end) + { + dRadixSum[dpos] = sRadixSum[spos]; + dpos += (TOTALRADIXGROUPS / PREFIX_NUM_THREADS_PER_BLOCK) * TOTALRADIXGROUPS; + spos += (PREFIX_NUM_THREADS_PER_BLOCK / (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK)) * + (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1); + } + + // Write last element to summation + // Storing block sums in a separate array + if (threadIdx.x == 0) { + dRadixBlockSum[blockIdx.x] = sRadixSum[PREFIX_NUM_THREADS_PER_BLOCK * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1) - 1]; + dRadixSum[blockIdx.x * PREFIX_BLOCKSIZE] = 0; + } +} + + +//////////////////////////////////////////////////////////////////////////////// +//! Initially perform prefix sum of block totals to obtain final set of offsets. +//! Then make use of radix sums to perform a shuffling of the data into the +//! correct bins. +//! +//! @param pSrc input data +//! @param pDst output data +//! @param elements total number of elements +//! @param shift the shift (0 to 24) that we are using to obtain the correct +//! byte +//////////////////////////////////////////////////////////////////////////////// +__global__ void RadixAddOffsetsAndShuffle(KeyValuePair* pSrc, KeyValuePair* pDst, uint elements, uint elements_rounded_to_3072, int shift) +{ + // Read offsets from previous blocks + if (threadIdx.x == 0) + sRadixSum[SHUFFLE_GRFOFFSET] = 0; + + if (threadIdx.x < PREFIX_NUM_BLOCKS - 1) + sRadixSum[SHUFFLE_GRFOFFSET + threadIdx.x + 1] = dRadixBlockSum[threadIdx.x]; + __syncthreads(); + + // Parallel prefix sum over block sums + int pos = threadIdx.x; + int n = 1; + while (n < PREFIX_NUM_BLOCKS) + { + int ppos = pos - n; + uint t0 = ((pos < PREFIX_NUM_BLOCKS) && (ppos >= 0)) ? sRadixSum[SHUFFLE_GRFOFFSET + ppos] : 0; + __syncthreads(); + if (pos < PREFIX_NUM_BLOCKS) + sRadixSum[SHUFFLE_GRFOFFSET + pos] += t0; + __syncthreads(); + n *= 2; + } + + // Read radix count data and add appropriate block offset + // for each radix at the memory location for this thread + // (where the other threads in the block will be reading + // as well, hence the large stride). + // There is one counter box per radix group per radix + // per block (4*256*3) + // We use 64 threads to read the 4 radix groups set of radices + // for the block. + int row = threadIdx.x / RADIXGROUPS; + int column = threadIdx.x % RADIXGROUPS; + int spos = row * RADIXGROUPS + column; + int dpos = row * TOTALRADIXGROUPS + column + blockIdx.x * RADIXGROUPS; + while (spos < SHUFFLE_GRFOFFSET) + { + sRadixSum[spos] = dRadixSum[dpos] + sRadixSum[SHUFFLE_GRFOFFSET + dpos / (TOTALRADIXGROUPS * RADICES / PREFIX_NUM_BLOCKS)]; + spos += NUM_THREADS_PER_BLOCK; + dpos += (NUM_THREADS_PER_BLOCK / RADIXGROUPS) * TOTALRADIXGROUPS; + } + __syncthreads(); + + //int pos; + // Shuffle data + // Each of the subbins for a block should be filled via the counters, properly interleaved + // Then, as we now iterate over each data value, we increment the subbins (each thread in the + // radix group in turn to avoid miss writes due to conflicts) and set locations correctly. + uint element_fraction = elements_rounded_to_3072 / TOTALRADIXGROUPS; + int tmod = threadIdx.x % RADIXTHREADS; + int tpos = threadIdx.x / RADIXTHREADS; + + pos = (blockIdx.x * RADIXGROUPS + tpos) * element_fraction; + uint end = pos + element_fraction; //(blockIdx.x * RADIXGROUPS + tpos + 1) * element_fraction; + pos += tmod; + + __syncthreads(); + + while (pos < end ) + { + KeyValuePair kvp; +#if 1 // old load + // Read first data element, both items at once as the memory will want to coalesce like that anyway + if (pos < elements) + { + kvp = pSrc[pos]; + } + else + kvp.key = 0; + +#else // casting to float2 to get it to combine loads + int2 kvpf2; + + // Read first data element, both items at once as the memory will want to coalesce like that anyway + if (pos < elements) + { + // kvp = pSrc[pos]; + kvpf2 = ((int2*)pSrc)[pos]; + // printf("kvp: %f %f kvpf2: %f %f\n", kvp.key, kvp.value, kvpf2.x, kvpf2.y); + } + else + //kvp.key = 0; + kvpf2.x = 0; + + kvp.key = kvpf2.x; + kvp.value = kvpf2.y; +#endif + + uint index; + + // Calculate position of radix counter to increment + uint p = ((kvp.key >> shift) & RADIXMASK) * RADIXGROUPS; + + // Move data, keeping counts updated. + // Increment radix counters, relying on hexadecathread + // warp to prevent this code from stepping all over itself. + uint ppos = p + tpos; + if (tmod == 0 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 1 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 2 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 3 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 4 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 5 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 6 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 7 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 8 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 9 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 10 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 11 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 12 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 13 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 14 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 15 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + + pos += RADIXTHREADS; + } + + __syncthreads(); +} + +#endif // #ifndef _RADIXSORT_KERNEL_H_ diff --git a/Extras/ConvexDecomposition/CMakeLists.txt b/Extras/ConvexDecomposition/CMakeLists.txt new file mode 100644 index 0000000..693e9d2 --- /dev/null +++ b/Extras/ConvexDecomposition/CMakeLists.txt @@ -0,0 +1,64 @@ +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/Extras/ConvexDecomposition ${BULLET_PHYSICS_SOURCE_DIR}/src +) + +SET(ConvexDecomposition_SRCS + bestfitobb.cpp + ConvexBuilder.cpp + cd_wavefront.cpp + fitsphere.cpp + meshvolume.cpp + raytri.cpp + vlookup.cpp + bestfit.cpp + cd_hull.cpp + ConvexDecomposition.cpp + concavity.cpp + float_math.cpp + planetri.cpp + splitplane.cpp +) + +SET(ConvexDecomposition_HDRS + ConvexDecomposition.h + cd_vector.h + concavity.h + bestfitobb.h + ConvexBuilder.h + cd_wavefront.h + fitsphere.h + meshvolume.h + raytri.h + vlookup.h + bestfit.h + cd_hull.h +) + +ADD_LIBRARY(ConvexDecomposition ${ConvexDecomposition_SRCS} ${ConvexDecomposition_HDRS}) +SET_TARGET_PROPERTIES(ConvexDecomposition PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(ConvexDecomposition PROPERTIES SOVERSION ${BULLET_VERSION}) + +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(ConvexDecomposition BulletCollision LinearMath) +ENDIF (BUILD_SHARED_LIBS) + +IF (INSTALL_EXTRA_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + #FILES_MATCHING requires CMake 2.6 + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS ConvexDecomposition DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS ConvexDecomposition DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN +".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(ConvexDecomposition PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(ConvexDecomposition PROPERTIES PUBLIC_HEADER "${ConvexDecomposition_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_EXTRA_LIBS) diff --git a/Extras/ConvexDecomposition/ConvexBuilder.cpp b/Extras/ConvexDecomposition/ConvexBuilder.cpp new file mode 100644 index 0000000..bf576af --- /dev/null +++ b/Extras/ConvexDecomposition/ConvexBuilder.cpp @@ -0,0 +1,373 @@ +#include "float_math.h" +#include "ConvexBuilder.h" +#include "meshvolume.h" +#include "bestfit.h" +#include +#include "cd_hull.h" + +#include "fitsphere.h" +#include "bestfitobb.h" + +unsigned int MAXDEPTH = 8 ; +float CONCAVE_PERCENT = 1.0f ; +float MERGE_PERCENT = 2.0f ; + +CHull::CHull(const ConvexResult &result) +{ + mResult = new ConvexResult(result); + mVolume = computeMeshVolume( result.mHullVertices, result.mHullTcount, result.mHullIndices ); + + mDiagonal = getBoundingRegion( result.mHullVcount, result.mHullVertices, sizeof(float)*3, mMin, mMax ); + + float dx = mMax[0] - mMin[0]; + float dy = mMax[1] - mMin[1]; + float dz = mMax[2] - mMin[2]; + + dx*=0.1f; // inflate 1/10th on each edge + dy*=0.1f; // inflate 1/10th on each edge + dz*=0.1f; // inflate 1/10th on each edge + + mMin[0]-=dx; + mMin[1]-=dy; + mMin[2]-=dz; + + mMax[0]+=dx; + mMax[1]+=dy; + mMax[2]+=dz; + + +} + +CHull::~CHull(void) +{ + delete mResult; +} + +bool CHull::overlap(const CHull &h) const +{ + return overlapAABB(mMin,mMax, h.mMin, h.mMax ); +} + + + + +ConvexBuilder::ConvexBuilder(ConvexDecompInterface *callback) +{ + mCallback = callback; +} + +ConvexBuilder::~ConvexBuilder(void) +{ + int i; + for (i=0;ioverlap(*b) ) return 0; // if their AABB's (with a little slop) don't overlap, then return. + + CHull *ret = 0; + + // ok..we are going to combine both meshes into a single mesh + // and then we are going to compute the concavity... + + VertexLookup vc = Vl_createVertexLookup(); + + UintVector indices; + + getMesh( *a->mResult, vc, indices ); + getMesh( *b->mResult, vc, indices ); + + unsigned int vcount = Vl_getVcount(vc); + const float *vertices = Vl_getVertices(vc); + unsigned int tcount = indices.size()/3; + + //don't do anything if hull is empty + if (!tcount) + { + Vl_releaseVertexLookup (vc); + return 0; + } + + HullResult hresult; + HullLibrary hl; + HullDesc desc; + + desc.SetHullFlag(QF_TRIANGLES); + + desc.mVcount = vcount; + desc.mVertices = vertices; + desc.mVertexStride = sizeof(float)*3; + + HullError hret = hl.CreateConvexHull(desc,hresult); + + if ( hret == QE_OK ) + { + + float combineVolume = computeMeshVolume( hresult.mOutputVertices, hresult.mNumFaces, hresult.mIndices ); + float sumVolume = a->mVolume + b->mVolume; + + float percent = (sumVolume*100) / combineVolume; + if ( percent >= (100.0f-MERGE_PERCENT) ) + { + ConvexResult cr(hresult.mNumOutputVertices, hresult.mOutputVertices, hresult.mNumFaces, hresult.mIndices); + ret = new CHull(cr); + } + } + + + Vl_releaseVertexLookup(vc); + + return ret; +} + +bool ConvexBuilder::combineHulls(void) +{ + + bool combine = false; + + sortChulls(mChulls); // sort the convex hulls, largest volume to least... + + CHullVector output; // the output hulls... + + + int i; + + for (i=0;imResult; // the high resolution hull... + + HullResult result; + HullLibrary hl; + HullDesc hdesc; + + hdesc.SetHullFlag(QF_TRIANGLES); + + hdesc.mVcount = c.mHullVcount; + hdesc.mVertices = c.mHullVertices; + hdesc.mVertexStride = sizeof(float)*3; + hdesc.mMaxVertices = desc.mMaxVertices; // maximum number of vertices allowed in the output + + if ( desc.mSkinWidth ) + { + hdesc.mSkinWidth = desc.mSkinWidth; + hdesc.SetHullFlag(QF_SKIN_WIDTH); // do skin width computation. + } + + HullError ret = hl.CreateConvexHull(hdesc,result); + + if ( ret == QE_OK ) + { + ConvexResult r(result.mNumOutputVertices, result.mOutputVertices, result.mNumFaces, result.mIndices); + + r.mHullVolume = computeMeshVolume( result.mOutputVertices, result.mNumFaces, result.mIndices ); // the volume of the hull. + + // compute the best fit OBB + computeBestFitOBB( result.mNumOutputVertices, result.mOutputVertices, sizeof(float)*3, r.mOBBSides, r.mOBBTransform ); + + r.mOBBVolume = r.mOBBSides[0] * r.mOBBSides[1] *r.mOBBSides[2]; // compute the OBB volume. + + fm_getTranslation( r.mOBBTransform, r.mOBBCenter ); // get the translation component of the 4x4 matrix. + + fm_matrixToQuat( r.mOBBTransform, r.mOBBOrientation ); // extract the orientation as a quaternion. + + r.mSphereRadius = computeBoundingSphere( result.mNumOutputVertices, result.mOutputVertices, r.mSphereCenter ); + r.mSphereVolume = fm_sphereVolume( r.mSphereRadius ); + + + mCallback->ConvexDecompResult(r); + } + + hl.ReleaseResult (result); + + + delete cr; + } + + ret = mChulls.size(); + + mChulls.clear(); + + return ret; +} + + +void ConvexBuilder::ConvexDebugTri(const float *p1,const float *p2,const float *p3,unsigned int color) +{ + mCallback->ConvexDebugTri(p1,p2,p3,color); +} + +void ConvexBuilder::ConvexDebugOBB(const float *sides, const float *matrix,unsigned int color) +{ + mCallback->ConvexDebugOBB(sides,matrix,color); +} +void ConvexBuilder::ConvexDebugPoint(const float *p,float dist,unsigned int color) +{ + mCallback->ConvexDebugPoint(p,dist,color); +} + +void ConvexBuilder::ConvexDebugBound(const float *bmin,const float *bmax,unsigned int color) +{ + mCallback->ConvexDebugBound(bmin,bmax,color); +} + +void ConvexBuilder::ConvexDecompResult(ConvexResult &result) +{ + CHull *ch = new CHull(result); + mChulls.push_back(ch); +} + +void ConvexBuilder::sortChulls(CHullVector &hulls) +{ + hulls.quickSort(CHullSort()); + //hulls.heapSort(CHullSort()); +} + + diff --git a/Extras/ConvexDecomposition/ConvexBuilder.h b/Extras/ConvexDecomposition/ConvexBuilder.h new file mode 100644 index 0000000..b1d98cb --- /dev/null +++ b/Extras/ConvexDecomposition/ConvexBuilder.h @@ -0,0 +1,112 @@ +#ifndef CONVEX_BUILDER_H +#define CONVEX_BUILDER_H + +/*---------------------------------------------------------------------- +Copyright (c) 2004 Open Dynamics Framework Group +www.physicstools.org +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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + + +#include "ConvexDecomposition.h" +#include "vlookup.h" +#include "LinearMath/btAlignedObjectArray.h" + +using namespace ConvexDecomposition; + + +class CHull +{ +public: + CHull(const ConvexResult &result); + + ~CHull(void); + + bool overlap(const CHull &h) const; + + float mMin[3]; + float mMax[3]; + float mVolume; + float mDiagonal; // long edge.. + ConvexResult *mResult; +}; + +// Usage: std::sort( list.begin(), list.end(), StringSortRef() ); +class CHullSort +{ +public: + + inline bool operator()(const CHull *a,const CHull *b) const + { + return a->mVolume < b->mVolume; + } +}; + + +typedef btAlignedObjectArray< CHull * > CHullVector; + + + +class ConvexBuilder : public ConvexDecompInterface +{ +public: + ConvexBuilder(ConvexDecompInterface *callback); + + virtual ~ConvexBuilder(void); + + bool isDuplicate(unsigned int i1,unsigned int i2,unsigned int i3, + unsigned int ci1,unsigned int ci2,unsigned int ci3); + + void getMesh(const ConvexResult &cr,VertexLookup vc,UintVector &indices); + + CHull * canMerge(CHull *a,CHull *b); + + bool combineHulls(void); + + unsigned int process(const DecompDesc &desc); + + virtual void ConvexDebugTri(const float *p1,const float *p2,const float *p3,unsigned int color); + + virtual void ConvexDebugOBB(const float *sides, const float *matrix,unsigned int color); + virtual void ConvexDebugPoint(const float *p,float dist,unsigned int color); + + virtual void ConvexDebugBound(const float *bmin,const float *bmax,unsigned int color); + + virtual void ConvexDecompResult(ConvexResult &result); + + void sortChulls(CHullVector &hulls); + + CHullVector mChulls; + ConvexDecompInterface *mCallback; +}; + +#endif //CONVEX_BUILDER_H + diff --git a/Extras/ConvexDecomposition/ConvexDecomposition.cpp b/Extras/ConvexDecomposition/ConvexDecomposition.cpp new file mode 100644 index 0000000..572d25f --- /dev/null +++ b/Extras/ConvexDecomposition/ConvexDecomposition.cpp @@ -0,0 +1,375 @@ +#include "float_math.h" + +#include +#include +#include +#include + + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + +#include "ConvexDecomposition.h" +#include "cd_vector.h" +#include "cd_hull.h" +#include "bestfit.h" +#include "planetri.h" +#include "vlookup.h" +#include "splitplane.h" +#include "meshvolume.h" +#include "concavity.h" +#include "bestfitobb.h" +#include "float_math.h" +#include "fitsphere.h" + +#define SHOW_MESH 0 +#define MAKE_MESH 1 + + +using namespace ConvexDecomposition; + + + +namespace ConvexDecomposition +{ + +class FaceTri +{ +public: + FaceTri(void) { }; + FaceTri(const float *vertices,unsigned int i1,unsigned int i2,unsigned int i3) + { + mP1.Set( &vertices[i1*3] ); + mP2.Set( &vertices[i2*3] ); + mP3.Set( &vertices[i3*3] ); + } + + Vector3d mP1; + Vector3d mP2; + Vector3d mP3; + Vector3d mNormal; + +}; + + +void addTri(VertexLookup vl,UintVector &list,const Vector3d &p1,const Vector3d &p2,const Vector3d &p3) +{ + unsigned int i1 = Vl_getIndex(vl, p1.Ptr() ); + unsigned int i2 = Vl_getIndex(vl, p2.Ptr() ); + unsigned int i3 = Vl_getIndex(vl, p3.Ptr() ); + + // do *not* process degenerate triangles! + + if ( i1 != i2 && i1 != i3 && i2 != i3 ) + { + list.push_back(i1); + list.push_back(i2); + list.push_back(i3); + } +} + + +void calcConvexDecomposition(unsigned int vcount, + const float *vertices, + unsigned int tcount, + const unsigned int *indices, + ConvexDecompInterface *callback, + float masterVolume, + unsigned int depth) + +{ + + float plane[4]; + + bool split = false; + + + if ( depth < MAXDEPTH ) + { + + float volume; + float c = computeConcavity( vcount, vertices, tcount, indices, callback, plane, volume ); + + if ( depth == 0 ) + { + masterVolume = volume; + } + + float percent = (c*100.0f)/masterVolume; + + if ( percent > CONCAVE_PERCENT ) // if great than 5% of the total volume is concave, go ahead and keep splitting. + { + split = true; + } + + } + + if ( depth >= MAXDEPTH || !split ) + { + +#if 1 + + HullResult result; + HullLibrary hl; + HullDesc desc; + + desc.SetHullFlag(QF_TRIANGLES); + + desc.mVcount = vcount; + desc.mVertices = vertices; + desc.mVertexStride = sizeof(float)*3; + + HullError ret = hl.CreateConvexHull(desc,result); + + if ( ret == QE_OK ) + { + + ConvexResult r(result.mNumOutputVertices, result.mOutputVertices, result.mNumFaces, result.mIndices); + + + callback->ConvexDecompResult(r); + } + + +#else + + static unsigned int colors[8] = + { + 0xFF0000, + 0x00FF00, + 0x0000FF, + 0xFFFF00, + 0x00FFFF, + 0xFF00FF, + 0xFFFFFF, + 0xFF8040 + }; + + static int count = 0; + + count++; + + if ( count == 8 ) count = 0; + + assert( count >= 0 && count < 8 ); + + unsigned int color = colors[count]; + + const unsigned int *source = indices; + + for (unsigned int i=0; iConvexDebugTri( t.mP1.Ptr(), t.mP2.Ptr(), t.mP3.Ptr(), color ); + + } +#endif + + hl.ReleaseResult (result); + return; + + } + + UintVector ifront; + UintVector iback; + + VertexLookup vfront = Vl_createVertexLookup(); + VertexLookup vback = Vl_createVertexLookup(); + + + bool showmesh = false; + #if SHOW_MESH + showmesh = true; + #endif + + if ( 0 ) + { + showmesh = true; + for (float x=-1; x<1; x+=0.10f) + { + for (float y=0; y<1; y+=0.10f) + { + for (float z=-1; z<1; z+=0.04f) + { + float d = x*plane[0] + y*plane[1] + z*plane[2] + plane[3]; + Vector3d p(x,y,z); + if ( d >= 0 ) + callback->ConvexDebugPoint(p.Ptr(), 0.02f, 0x00FF00); + else + callback->ConvexDebugPoint(p.Ptr(), 0.02f, 0xFF0000); + } + } + } + } + + if ( 1 ) + { + // ok..now we are going to 'split' all of the input triangles against this plane! + const unsigned int *source = indices; + for (unsigned int i=0; i 4 || bcount > 4 ) + { + result = planeTriIntersection(plane,t.mP1.Ptr(),sizeof(Vector3d),0.00001f,front[0].Ptr(),fcount,back[0].Ptr(),bcount ); + } + + switch ( result ) + { + case PTR_FRONT: + + assert( fcount == 3 ); + + if ( showmesh ) + callback->ConvexDebugTri( front[0].Ptr(), front[1].Ptr(), front[2].Ptr(), 0x00FF00 ); + + #if MAKE_MESH + + addTri( vfront, ifront, front[0], front[1], front[2] ); + + + #endif + + break; + case PTR_BACK: + assert( bcount == 3 ); + + if ( showmesh ) + callback->ConvexDebugTri( back[0].Ptr(), back[1].Ptr(), back[2].Ptr(), 0xFFFF00 ); + + #if MAKE_MESH + + addTri( vback, iback, back[0], back[1], back[2] ); + + #endif + + break; + case PTR_SPLIT: + + assert( fcount >= 3 && fcount <= 4); + assert( bcount >= 3 && bcount <= 4); + + #if MAKE_MESH + + addTri( vfront, ifront, front[0], front[1], front[2] ); + addTri( vback, iback, back[0], back[1], back[2] ); + + + if ( fcount == 4 ) + { + addTri( vfront, ifront, front[0], front[2], front[3] ); + } + + if ( bcount == 4 ) + { + addTri( vback, iback, back[0], back[2], back[3] ); + } + + #endif + + if ( showmesh ) + { + callback->ConvexDebugTri( front[0].Ptr(), front[1].Ptr(), front[2].Ptr(), 0x00D000 ); + callback->ConvexDebugTri( back[0].Ptr(), back[1].Ptr(), back[2].Ptr(), 0xD0D000 ); + + if ( fcount == 4 ) + { + callback->ConvexDebugTri( front[0].Ptr(), front[2].Ptr(), front[3].Ptr(), 0x00D000 ); + } + if ( bcount == 4 ) + { + callback->ConvexDebugTri( back[0].Ptr(), back[2].Ptr(), back[3].Ptr(), 0xD0D000 ); + } + } + + break; + } + } + + // ok... here we recursively call + if ( ifront.size() ) + { + unsigned int vcount = Vl_getVcount(vfront); + const float *vertices = Vl_getVertices(vfront); + unsigned int tcount = ifront.size()/3; + + calcConvexDecomposition(vcount, vertices, tcount, &ifront[0], callback, masterVolume, depth+1); + + } + + ifront.clear(); + + Vl_releaseVertexLookup(vfront); + + if ( iback.size() ) + { + unsigned int vcount = Vl_getVcount(vback); + const float *vertices = Vl_getVertices(vback); + unsigned int tcount = iback.size()/3; + + calcConvexDecomposition(vcount, vertices, tcount, &iback[0], callback, masterVolume, depth+1); + + } + + iback.clear(); + Vl_releaseVertexLookup(vback); + + } +} + + + + +} diff --git a/Extras/ConvexDecomposition/ConvexDecomposition.h b/Extras/ConvexDecomposition/ConvexDecomposition.h new file mode 100644 index 0000000..2886c39 --- /dev/null +++ b/Extras/ConvexDecomposition/ConvexDecomposition.h @@ -0,0 +1,220 @@ +#ifndef CONVEX_DECOMPOSITION_H + +#define CONVEX_DECOMPOSITION_H + +/*---------------------------------------------------------------------- +Copyright (c) 2004 Open Dynamics Framework Group +www.physicstools.org +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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + + +#ifdef _WIN32 +#include //memcpy +#endif +#include +#include +#include "LinearMath/btAlignedObjectArray.h" + + + +extern unsigned int MAXDEPTH ; +extern float CONCAVE_PERCENT ; +extern float MERGE_PERCENT ; + + +typedef btAlignedObjectArray< unsigned int > UintVector; + + + +namespace ConvexDecomposition +{ + + class ConvexResult + { + public: + ConvexResult(void) + { + mHullVcount = 0; + mHullVertices = 0; + mHullTcount = 0; + mHullIndices = 0; + } + + ConvexResult(unsigned int hvcount,const float *hvertices,unsigned int htcount,const unsigned int *hindices) + { + mHullVcount = hvcount; + if ( mHullVcount ) + { + mHullVertices = new float[mHullVcount*sizeof(float)*3]; + memcpy(mHullVertices, hvertices, sizeof(float)*3*mHullVcount ); + } + else + { + mHullVertices = 0; + } + + mHullTcount = htcount; + + if ( mHullTcount ) + { + mHullIndices = new unsigned int[sizeof(unsigned int)*mHullTcount*3]; + memcpy(mHullIndices,hindices, sizeof(unsigned int)*mHullTcount*3 ); + } + else + { + mHullIndices = 0; + } + + } + + ConvexResult(const ConvexResult &r) + { + mHullVcount = r.mHullVcount; + if ( mHullVcount ) + { + mHullVertices = new float[mHullVcount*sizeof(float)*3]; + memcpy(mHullVertices, r.mHullVertices, sizeof(float)*3*mHullVcount ); + } + else + { + mHullVertices = 0; + } + mHullTcount = r.mHullTcount; + if ( mHullTcount ) + { + mHullIndices = new unsigned int[sizeof(unsigned int)*mHullTcount*3]; + memcpy(mHullIndices, r.mHullIndices, sizeof(unsigned int)*mHullTcount*3 ); + } + else + { + mHullIndices = 0; + } + } + + ~ConvexResult(void) + { + delete [] mHullVertices; + delete [] mHullIndices; + } + + // the convex hull. + unsigned int mHullVcount; + float * mHullVertices; + unsigned int mHullTcount; + unsigned int *mHullIndices; + + float mHullVolume; // the volume of the convex hull. + + float mOBBSides[3]; // the width, height and breadth of the best fit OBB + float mOBBCenter[3]; // the center of the OBB + float mOBBOrientation[4]; // the quaternion rotation of the OBB. + float mOBBTransform[16]; // the 4x4 transform of the OBB. + float mOBBVolume; // the volume of the OBB + + float mSphereRadius; // radius and center of best fit sphere + float mSphereCenter[3]; + float mSphereVolume; // volume of the best fit sphere + + + + }; + + class ConvexDecompInterface + { + public: + virtual ~ConvexDecompInterface() {}; + virtual void ConvexDebugTri(const float *p1,const float *p2,const float *p3,unsigned int color) { }; + virtual void ConvexDebugPoint(const float *p,float dist,unsigned int color) { }; + virtual void ConvexDebugBound(const float *bmin,const float *bmax,unsigned int color) { }; + virtual void ConvexDebugOBB(const float *sides, const float *matrix,unsigned int color) { }; + + virtual void ConvexDecompResult(ConvexResult &result) = 0; + + + + }; + + // just to avoid passing a zillion parameters to the method the + // options are packed into this descriptor. + class DecompDesc + { + public: + DecompDesc(void) + { + mVcount = 0; + mVertices = 0; + mTcount = 0; + mIndices = 0; + mDepth = 5; + mCpercent = 5; + mPpercent = 5; + mMaxVertices = 32; + mSkinWidth = 0; + mCallback = 0; + } + + // describes the input triangle. + unsigned int mVcount; // the number of vertices in the source mesh. + const float *mVertices; // start of the vertex position array. Assumes a stride of 3 floats. + unsigned int mTcount; // the number of triangles in the source mesh. + unsigned int *mIndices; // the indexed triangle list array (zero index based) + + // options + unsigned int mDepth; // depth to split, a maximum of 10, generally not over 7. + float mCpercent; // the concavity threshold percentage. 0=20 is reasonable. + float mPpercent; // the percentage volume conservation threshold to collapse hulls. 0-30 is reasonable. + + // hull output limits. + unsigned int mMaxVertices; // maximum number of vertices in the output hull. Recommended 32 or less. + float mSkinWidth; // a skin width to apply to the output hulls. + + ConvexDecompInterface *mCallback; // the interface to receive back the results. + + }; + + // perform approximate convex decomposition on a mesh. + unsigned int performConvexDecomposition(const DecompDesc &desc); // returns the number of hulls produced. + + + void calcConvexDecomposition(unsigned int vcount, + const float *vertices, + unsigned int tcount, + const unsigned int *indices, + ConvexDecompInterface *callback, + float masterVolume, + unsigned int depth); + + +} + + +#endif diff --git a/Extras/ConvexDecomposition/bestfit.cpp b/Extras/ConvexDecomposition/bestfit.cpp new file mode 100644 index 0000000..e6469f6 --- /dev/null +++ b/Extras/ConvexDecomposition/bestfit.cpp @@ -0,0 +1,466 @@ +#include "float_math.h" +#include +#include +#include +#include +#include + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// +// Geometric Tools, Inc. +// http://www.geometrictools.com +// Copyright (c) 1998-2006. All Rights Reserved +// +// The Wild Magic Library (WM3) source code is supplied under the terms of +// the license agreement +// http://www.geometrictools.com/License/WildMagic3License.pdf +// and may not be copied or disclosed except in accordance with the terms +// of that agreement. + +#include "bestfit.h" + +namespace BestFit +{ + +class Vec3 +{ +public: + Vec3(void) { }; + Vec3(float _x,float _y,float _z) { x = _x; y = _y; z = _z; }; + + + float dot(const Vec3 &v) + { + return x*v.x + y*v.y + z*v.z; // the dot product + } + + float x; + float y; + float z; +}; + + +class Eigen +{ +public: + + + void DecrSortEigenStuff(void) + { + Tridiagonal(); //diagonalize the matrix. + QLAlgorithm(); // + DecreasingSort(); + GuaranteeRotation(); + } + + void Tridiagonal(void) + { + float fM00 = mElement[0][0]; + float fM01 = mElement[0][1]; + float fM02 = mElement[0][2]; + float fM11 = mElement[1][1]; + float fM12 = mElement[1][2]; + float fM22 = mElement[2][2]; + + m_afDiag[0] = fM00; + m_afSubd[2] = 0; + if (fM02 != (float)0.0) + { + float fLength = sqrtf(fM01*fM01+fM02*fM02); + float fInvLength = ((float)1.0)/fLength; + fM01 *= fInvLength; + fM02 *= fInvLength; + float fQ = ((float)2.0)*fM01*fM12+fM02*(fM22-fM11); + m_afDiag[1] = fM11+fM02*fQ; + m_afDiag[2] = fM22-fM02*fQ; + m_afSubd[0] = fLength; + m_afSubd[1] = fM12-fM01*fQ; + mElement[0][0] = (float)1.0; + mElement[0][1] = (float)0.0; + mElement[0][2] = (float)0.0; + mElement[1][0] = (float)0.0; + mElement[1][1] = fM01; + mElement[1][2] = fM02; + mElement[2][0] = (float)0.0; + mElement[2][1] = fM02; + mElement[2][2] = -fM01; + m_bIsRotation = false; + } + else + { + m_afDiag[1] = fM11; + m_afDiag[2] = fM22; + m_afSubd[0] = fM01; + m_afSubd[1] = fM12; + mElement[0][0] = (float)1.0; + mElement[0][1] = (float)0.0; + mElement[0][2] = (float)0.0; + mElement[1][0] = (float)0.0; + mElement[1][1] = (float)1.0; + mElement[1][2] = (float)0.0; + mElement[2][0] = (float)0.0; + mElement[2][1] = (float)0.0; + mElement[2][2] = (float)1.0; + m_bIsRotation = true; + } + } + + bool QLAlgorithm(void) + { + const int iMaxIter = 32; + + for (int i0 = 0; i0 <3; i0++) + { + int i1; + for (i1 = 0; i1 < iMaxIter; i1++) + { + int i2; + for (i2 = i0; i2 <= (3-2); i2++) + { + float fTmp = fabsf(m_afDiag[i2]) + fabsf(m_afDiag[i2+1]); + if ( fabsf(m_afSubd[i2]) + fTmp == fTmp ) + break; + } + if (i2 == i0) + { + break; + } + + float fG = (m_afDiag[i0+1] - m_afDiag[i0])/(((float)2.0) * m_afSubd[i0]); + float fR = sqrtf(fG*fG+(float)1.0); + if (fG < (float)0.0) + { + fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG-fR); + } + else + { + fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG+fR); + } + float fSin = (float)1.0, fCos = (float)1.0, fP = (float)0.0; + for (int i3 = i2-1; i3 >= i0; i3--) + { + float fF = fSin*m_afSubd[i3]; + float fB = fCos*m_afSubd[i3]; + if (fabsf(fF) >= fabsf(fG)) + { + fCos = fG/fF; + fR = sqrtf(fCos*fCos+(float)1.0); + m_afSubd[i3+1] = fF*fR; + fSin = ((float)1.0)/fR; + fCos *= fSin; + } + else + { + fSin = fF/fG; + fR = sqrtf(fSin*fSin+(float)1.0); + m_afSubd[i3+1] = fG*fR; + fCos = ((float)1.0)/fR; + fSin *= fCos; + } + fG = m_afDiag[i3+1]-fP; + fR = (m_afDiag[i3]-fG)*fSin+((float)2.0)*fB*fCos; + fP = fSin*fR; + m_afDiag[i3+1] = fG+fP; + fG = fCos*fR-fB; + for (int i4 = 0; i4 < 3; i4++) + { + fF = mElement[i4][i3+1]; + mElement[i4][i3+1] = fSin*mElement[i4][i3]+fCos*fF; + mElement[i4][i3] = fCos*mElement[i4][i3]-fSin*fF; + } + } + m_afDiag[i0] -= fP; + m_afSubd[i0] = fG; + m_afSubd[i2] = (float)0.0; + } + if (i1 == iMaxIter) + { + return false; + } + } + return true; + } + + void DecreasingSort(void) + { + //sort eigenvalues in decreasing order, e[0] >= ... >= e[iSize-1] + for (int i0 = 0, i1; i0 <= 3-2; i0++) + { + // locate maximum eigenvalue + i1 = i0; + float fMax = m_afDiag[i1]; + int i2; + for (i2 = i0+1; i2 < 3; i2++) + { + if (m_afDiag[i2] > fMax) + { + i1 = i2; + fMax = m_afDiag[i1]; + } + } + + if (i1 != i0) + { + // swap eigenvalues + m_afDiag[i1] = m_afDiag[i0]; + m_afDiag[i0] = fMax; + // swap eigenvectors + for (i2 = 0; i2 < 3; i2++) + { + float fTmp = mElement[i2][i0]; + mElement[i2][i0] = mElement[i2][i1]; + mElement[i2][i1] = fTmp; + m_bIsRotation = !m_bIsRotation; + } + } + } + } + + + void GuaranteeRotation(void) + { + if (!m_bIsRotation) + { + // change sign on the first column + for (int iRow = 0; iRow <3; iRow++) + { + mElement[iRow][0] = -mElement[iRow][0]; + } + } + } + + float mElement[3][3]; + float m_afDiag[3]; + float m_afSubd[3]; + bool m_bIsRotation; +}; + +} + + +using namespace BestFit; + + +bool getBestFitPlane(unsigned int vcount, + const float *points, + unsigned int vstride, + const float *weights, + unsigned int wstride, + float *plane) +{ + bool ret = false; + + Vec3 kOrigin(0,0,0); + + float wtotal = 0; + + if ( 1 ) + { + const char *source = (const char *) points; + const char *wsource = (const char *) weights; + + for (unsigned int i=0; i bmax[0] ) bmax[0] = p[0]; + if ( p[1] > bmax[1] ) bmax[1] = p[1]; + if ( p[2] > bmax[2] ) bmax[2] = p[2]; + + } + + float dx = bmax[0] - bmin[0]; + float dy = bmax[1] - bmin[1]; + float dz = bmax[2] - bmin[2]; + + return sqrtf( dx*dx + dy*dy + dz*dz ); + +} + + +bool overlapAABB(const float *bmin1,const float *bmax1,const float *bmin2,const float *bmax2) // return true if the two AABB's overlap. +{ + if ( bmax2[0] < bmin1[0] ) return false; // if the maximum is less than our minimum on any axis + if ( bmax2[1] < bmin1[1] ) return false; + if ( bmax2[2] < bmin1[2] ) return false; + + if ( bmin2[0] > bmax1[0] ) return false; // if the minimum is greater than our maximum on any axis + if ( bmin2[1] > bmax1[1] ) return false; // if the minimum is greater than our maximum on any axis + if ( bmin2[2] > bmax1[2] ) return false; // if the minimum is greater than our maximum on any axis + + + return true; // the extents overlap +} + + diff --git a/Extras/ConvexDecomposition/bestfit.h b/Extras/ConvexDecomposition/bestfit.h new file mode 100644 index 0000000..f2e78e5 --- /dev/null +++ b/Extras/ConvexDecomposition/bestfit.h @@ -0,0 +1,65 @@ +#ifndef BEST_FIT_H + +#define BEST_FIT_H + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + + +// This routine was released in 'snippet' form +// by John W. Ratcliff mailto:jratcliff@infiniplex.net +// on March 22, 2006. +// +// This routine computes the 'best fit' plane equation to +// a set of input data points with an optional per vertex +// weighting component. +// +// The implementation for this was lifted directly from +// David Eberly's Magic Software implementation. + +// computes the best fit plane to a collection of data points. +// returns the plane equation as A,B,C,D format. (Ax+By+Cz+D) + +bool getBestFitPlane(unsigned int vcount, // number of input data points + const float *points, // starting address of points array. + unsigned int vstride, // stride between input points. + const float *weights, // *optional point weighting values. + unsigned int wstride, // weight stride for each vertex. + float *plane); + + +float getBoundingRegion(unsigned int vcount,const float *points,unsigned int pstride,float *bmin,float *bmax); // returns the diagonal distance +bool overlapAABB(const float *bmin1,const float *bmax1,const float *bmin2,const float *bmax2); // return true if the two AABB's overlap. + +#endif diff --git a/Extras/ConvexDecomposition/bestfitobb.cpp b/Extras/ConvexDecomposition/bestfitobb.cpp new file mode 100644 index 0000000..2d60fd0 --- /dev/null +++ b/Extras/ConvexDecomposition/bestfitobb.cpp @@ -0,0 +1,173 @@ +#include "float_math.h" + +#include +#include +#include +#include +#include + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + +#include "bestfitobb.h" +#include "float_math.h" + +// computes the OBB for this set of points relative to this transform matrix. +void computeOBB(unsigned int vcount,const float *points,unsigned int pstride,float *sides,const float *matrix) +{ + const char *src = (const char *) points; + + float bmin[3] = { 1e9, 1e9, 1e9 }; + float bmax[3] = { -1e9, -1e9, -1e9 }; + + for (unsigned int i=0; i bmax[0] ) bmax[0] = t[0]; + if ( t[1] > bmax[1] ) bmax[1] = t[1]; + if ( t[2] > bmax[2] ) bmax[2] = t[2]; + + src+=pstride; + } + + + sides[0] = bmax[0]; + sides[1] = bmax[1]; + sides[2] = bmax[2]; + + if ( fabsf(bmin[0]) > sides[0] ) sides[0] = fabsf(bmin[0]); + if ( fabsf(bmin[1]) > sides[1] ) sides[1] = fabsf(bmin[1]); + if ( fabsf(bmin[2]) > sides[2] ) sides[2] = fabsf(bmin[2]); + + sides[0]*=2.0f; + sides[1]*=2.0f; + sides[2]*=2.0f; + +} + +void computeBestFitOBB(unsigned int vcount,const float *points,unsigned int pstride,float *sides,float *matrix) +{ + + float bmin[3]; + float bmax[3]; + + fm_getAABB(vcount,points,pstride,bmin,bmax); + + float center[3]; + + center[0] = (bmax[0]-bmin[0])*0.5f + bmin[0]; + center[1] = (bmax[1]-bmin[1])*0.5f + bmin[1]; + center[2] = (bmax[2]-bmin[2])*0.5f + bmin[2]; + + float ax = 0; + float ay = 0; + float az = 0; + + float sweep = 45.0f; // 180 degree sweep on all three axes. + float steps = 8.0f; // 16 steps on each axis. + + float bestVolume = 1e9; + float angle[3]={0.f,0.f,0.f}; + + while ( sweep >= 1 ) + { + + bool found = false; + + float stepsize = sweep / steps; + + for (float x=ax-sweep; x<=ax+sweep; x+=stepsize) + { + for (float y=ay-sweep; y<=ay+sweep; y+=stepsize) + { + for (float z=az-sweep; z<=az+sweep; z+=stepsize) + { + float pmatrix[16]; + + fm_eulerMatrix( x*FM_DEG_TO_RAD, y*FM_DEG_TO_RAD, z*FM_DEG_TO_RAD, pmatrix ); + + pmatrix[3*4+0] = center[0]; + pmatrix[3*4+1] = center[1]; + pmatrix[3*4+2] = center[2]; + + float psides[3]; + + computeOBB( vcount, points, pstride, psides, pmatrix ); + + float volume = psides[0]*psides[1]*psides[2]; // the volume of the cube + + if ( volume <= bestVolume ) + { + bestVolume = volume; + + sides[0] = psides[0]; + sides[1] = psides[1]; + sides[2] = psides[2]; + + angle[0] = ax; + angle[1] = ay; + angle[2] = az; + + memcpy(matrix,pmatrix,sizeof(float)*16); + found = true; // yes, we found an improvement. + } + } + } + } + + if ( found ) + { + + ax = angle[0]; + ay = angle[1]; + az = angle[2]; + + sweep*=0.5f; // sweep 1/2 the distance as the last time. + } + else + { + break; // no improvement, so just + } + + } + +} diff --git a/Extras/ConvexDecomposition/bestfitobb.h b/Extras/ConvexDecomposition/bestfitobb.h new file mode 100644 index 0000000..3141f58 --- /dev/null +++ b/Extras/ConvexDecomposition/bestfitobb.h @@ -0,0 +1,43 @@ +#ifndef BEST_FIT_OBB_H + +#define BEST_FIT_OBB_H + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + + + +void computeBestFitOBB(unsigned int vcount,const float *points,unsigned int pstride,float *sides,float *matrix); + +#endif diff --git a/Extras/ConvexDecomposition/cd_hull.cpp b/Extras/ConvexDecomposition/cd_hull.cpp new file mode 100644 index 0000000..0f7d989 --- /dev/null +++ b/Extras/ConvexDecomposition/cd_hull.cpp @@ -0,0 +1,3261 @@ +#include "float_math.h" + +#include +#include +#include +#include +#include +#include + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + +#include "cd_hull.h" + +using namespace ConvexDecomposition; + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +#define PI 3.14159264f + +//***************************************************** +//***************************************************** +//********* Stan Melax's vector math template needed +//********* to use his hull building code. +//***************************************************** +//***************************************************** + +#define DEG2RAD (PI / 180.0f) +#define RAD2DEG (180.0f / PI) +#define SQRT_OF_2 (1.4142135f) +#define OFFSET(Class,Member) (((char*) (&(((Class*)NULL)-> Member )))- ((char*)NULL)) + +namespace ConvexDecomposition +{ + + +int argmin(float a[],int n); +float sqr(float a); +float clampf(float a) ; +float Round(float a,float precision); +float Interpolate(const float &f0,const float &f1,float alpha) ; + +template +void Swap(T &a,T &b) +{ + T tmp = a; + a=b; + b=tmp; +} + + + +template +T Max(const T &a,const T &b) +{ + return (a>b)?a:b; +} + +template +T Min(const T &a,const T &b) +{ + return (a=0&&i<2);return ((float*)this)[i];} + const float& operator[](int i) const {assert(i>=0&&i<2);return ((float*)this)[i];} +}; +inline float2 operator-( const float2& a, const float2& b ){return float2(a.x-b.x,a.y-b.y);} +inline float2 operator+( const float2& a, const float2& b ){return float2(a.x+b.x,a.y+b.y);} + +//--------- 3D --------- + +class float3 // 3D +{ + public: + float x,y,z; + float3(){x=0;y=0;z=0;}; + float3(float _x,float _y,float _z){x=_x;y=_y;z=_z;}; + //operator float *() { return &x;}; + float& operator[](int i) {assert(i>=0&&i<3);return ((float*)this)[i];} + const float& operator[](int i) const {assert(i>=0&&i<3);return ((float*)this)[i];} +# ifdef PLUGIN_3DSMAX + float3(const Point3 &p):x(p.x),y(p.y),z(p.z){} + operator Point3(){return *((Point3*)this);} +# endif +}; + + +float3& operator+=( float3 &a, const float3& b ); +float3& operator-=( float3 &a ,const float3& b ); +float3& operator*=( float3 &v ,const float s ); +float3& operator/=( float3 &v, const float s ); + +float magnitude( const float3& v ); +float3 normalize( const float3& v ); +float3 safenormalize(const float3 &v); +float3 vabs(const float3 &v); +float3 operator+( const float3& a, const float3& b ); +float3 operator-( const float3& a, const float3& b ); +float3 operator-( const float3& v ); +float3 operator*( const float3& v, const float s ); +float3 operator*( const float s, const float3& v ); +float3 operator/( const float3& v, const float s ); +inline int operator==( const float3 &a, const float3 &b ) { return (a.x==b.x && a.y==b.y && a.z==b.z); } +inline int operator!=( const float3 &a, const float3 &b ) { return (a.x!=b.x || a.y!=b.y || a.z!=b.z); } +// due to ambiguity and inconsistent standards ther are no overloaded operators for mult such as va*vb. +float dot( const float3& a, const float3& b ); +float3 cmul( const float3 &a, const float3 &b); +float3 cross( const float3& a, const float3& b ); +float3 Interpolate(const float3 &v0,const float3 &v1,float alpha); +float3 Round(const float3& a,float precision); +float3 VectorMax(const float3 &a, const float3 &b); +float3 VectorMin(const float3 &a, const float3 &b); + + + +class float3x3 +{ + public: + float3 x,y,z; // the 3 rows of the Matrix + float3x3(){} + float3x3(float xx,float xy,float xz,float yx,float yy,float yz,float zx,float zy,float zz):x(xx,xy,xz),y(yx,yy,yz),z(zx,zy,zz){} + float3x3(float3 _x,float3 _y,float3 _z):x(_x),y(_y),z(_z){} + float3& operator[](int i) {assert(i>=0&&i<3);return (&x)[i];} + const float3& operator[](int i) const {assert(i>=0&&i<3);return (&x)[i];} + float& operator()(int r, int c) {assert(r>=0&&r<3&&c>=0&&c<3);return ((&x)[r])[c];} + const float& operator()(int r, int c) const {assert(r>=0&&r<3&&c>=0&&c<3);return ((&x)[r])[c];} +}; +float3x3 Transpose( const float3x3& m ); +float3 operator*( const float3& v , const float3x3& m ); +float3 operator*( const float3x3& m , const float3& v ); +float3x3 operator*( const float3x3& m , const float& s ); +float3x3 operator*( const float3x3& ma, const float3x3& mb ); +float3x3 operator/( const float3x3& a, const float& s ) ; +float3x3 operator+( const float3x3& a, const float3x3& b ); +float3x3 operator-( const float3x3& a, const float3x3& b ); +float3x3 &operator+=( float3x3& a, const float3x3& b ); +float3x3 &operator-=( float3x3& a, const float3x3& b ); +float3x3 &operator*=( float3x3& a, const float& s ); +float Determinant(const float3x3& m ); +float3x3 Inverse(const float3x3& a); // its just 3x3 so we simply do that cofactor method + + +//-------- 4D Math -------- + +class float4 +{ +public: + float x,y,z,w; + float4(){x=0;y=0;z=0;w=0;}; + float4(float _x,float _y,float _z,float _w){x=_x;y=_y;z=_z;w=_w;} + float4(const float3 &v,float _w){x=v.x;y=v.y;z=v.z;w=_w;} + //operator float *() { return &x;}; + float& operator[](int i) {assert(i>=0&&i<4);return ((float*)this)[i];} + const float& operator[](int i) const {assert(i>=0&&i<4);return ((float*)this)[i];} + const float3& xyz() const { return *((float3*)this);} + float3& xyz() { return *((float3*)this);} +}; + + +struct D3DXMATRIX; + +class float4x4 +{ + public: + float4 x,y,z,w; // the 4 rows + float4x4(){} + float4x4(const float4 &_x, const float4 &_y, const float4 &_z, const float4 &_w):x(_x),y(_y),z(_z),w(_w){} + float4x4(float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33 ) + :x(m00,m01,m02,m03),y(m10,m11,m12,m13),z(m20,m21,m22,m23),w(m30,m31,m32,m33){} + float& operator()(int r, int c) {assert(r>=0&&r<4&&c>=0&&c<4);return ((&x)[r])[c];} + const float& operator()(int r, int c) const {assert(r>=0&&r<4&&c>=0&&c<4);return ((&x)[r])[c];} + operator float* () {return &x.x;} + operator const float* () const {return &x.x;} + operator struct D3DXMATRIX* () { return (struct D3DXMATRIX*) this;} + operator const struct D3DXMATRIX* () const { return (struct D3DXMATRIX*) this;} +}; + + +int operator==( const float4 &a, const float4 &b ); +float4 Homogenize(const float3 &v3,const float &w=1.0f); // Turns a 3D float3 4D vector4 by appending w +float4 cmul( const float4 &a, const float4 &b); +float4 operator*( const float4 &v, float s); +float4 operator*( float s, const float4 &v); +float4 operator+( const float4 &a, const float4 &b); +float4 operator-( const float4 &a, const float4 &b); +float4x4 operator*( const float4x4& a, const float4x4& b ); +float4 operator*( const float4& v, const float4x4& m ); +float4x4 Inverse(const float4x4 &m); +float4x4 MatrixRigidInverse(const float4x4 &m); +float4x4 MatrixTranspose(const float4x4 &m); +float4x4 MatrixPerspectiveFov(float fovy, float Aspect, float zn, float zf ); +float4x4 MatrixTranslation(const float3 &t); +float4x4 MatrixRotationZ(const float angle_radians); +float4x4 MatrixLookAt(const float3& eye, const float3& at, const float3& up); +int operator==( const float4x4 &a, const float4x4 &b ); + + +//-------- Quaternion ------------ + +class Quaternion :public float4 +{ + public: + Quaternion() { x = y = z = 0.0f; w = 1.0f; } + Quaternion( float3 v, float t ) { v = normalize(v); w = cosf(t/2.0f); v = v*sinf(t/2.0f); x = v.x; y = v.y; z = v.z; } + Quaternion(float _x, float _y, float _z, float _w){x=_x;y=_y;z=_z;w=_w;} + float angle() const { return acosf(w)*2.0f; } + float3 axis() const { float3 a(x,y,z); if(fabsf(angle())<0.0000001f) return float3(1,0,0); return a*(1/sinf(angle()/2.0f)); } + float3 xdir() const { return float3( 1-2*(y*y+z*z), 2*(x*y+w*z), 2*(x*z-w*y) ); } + float3 ydir() const { return float3( 2*(x*y-w*z),1-2*(x*x+z*z), 2*(y*z+w*x) ); } + float3 zdir() const { return float3( 2*(x*z+w*y), 2*(y*z-w*x),1-2*(x*x+y*y) ); } + float3x3 getmatrix() const { return float3x3( xdir(), ydir(), zdir() ); } + operator float3x3() { return getmatrix(); } + void Normalize(); +}; + +Quaternion& operator*=(Quaternion& a, float s ); +Quaternion operator*( const Quaternion& a, float s ); +Quaternion operator*( const Quaternion& a, const Quaternion& b); +Quaternion operator+( const Quaternion& a, const Quaternion& b ); +Quaternion normalize( Quaternion a ); +float dot( const Quaternion &a, const Quaternion &b ); +float3 operator*( const Quaternion& q, const float3& v ); +float3 operator*( const float3& v, const Quaternion& q ); +Quaternion slerp( Quaternion a, const Quaternion& b, float interp ); +Quaternion Interpolate(const Quaternion &q0,const Quaternion &q1,float alpha); +Quaternion RotationArc(float3 v0, float3 v1 ); // returns quat q where q*v0=v1 +Quaternion Inverse(const Quaternion &q); +float4x4 MatrixFromQuatVec(const Quaternion &q, const float3 &v); + + +//------ Euler Angle ----- + +Quaternion YawPitchRoll( float yaw, float pitch, float roll ); +float Yaw( const Quaternion& q ); +float Pitch( const Quaternion& q ); +float Roll( Quaternion q ); +float Yaw( const float3& v ); +float Pitch( const float3& v ); + + +//------- Plane ---------- + +class Plane +{ + public: + float3 normal; + float dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0 + Plane(const float3 &n,float d):normal(n),dist(d){} + Plane():normal(),dist(0){} + void Transform(const float3 &position, const Quaternion &orientation); +}; + +inline Plane PlaneFlip(const Plane &plane){return Plane(-plane.normal,-plane.dist);} +inline int operator==( const Plane &a, const Plane &b ) { return (a.normal==b.normal && a.dist==b.dist); } +inline int coplanar( const Plane &a, const Plane &b ) { return (a==b || a==PlaneFlip(b)); } + + +//--------- Utility Functions ------ + +float3 PlaneLineIntersection(const Plane &plane, const float3 &p0, const float3 &p1); +float3 PlaneProject(const Plane &plane, const float3 &point); +float3 LineProject(const float3 &p0, const float3 &p1, const float3 &a); // projects a onto infinite line p0p1 +float LineProjectTime(const float3 &p0, const float3 &p1, const float3 &a); +float3 ThreePlaneIntersection(const Plane &p0,const Plane &p1, const Plane &p2); +int PolyHit(const float3 *vert,const int n,const float3 &v0, const float3 &v1, float3 *impact=NULL, float3 *normal=NULL); +int BoxInside(const float3 &p,const float3 &bmin, const float3 &bmax) ; +int BoxIntersect(const float3 &v0, const float3 &v1, const float3 &bmin, const float3 &bmax, float3 *impact); +float DistanceBetweenLines(const float3 &ustart, const float3 &udir, const float3 &vstart, const float3 &vdir, float3 *upoint=NULL, float3 *vpoint=NULL); +float3 TriNormal(const float3 &v0, const float3 &v1, const float3 &v2); +float3 NormalOf(const float3 *vert, const int n); +Quaternion VirtualTrackBall(const float3 &cop, const float3 &cor, const float3 &dir0, const float3 &dir1); + + +float sqr(float a) {return a*a;} +float clampf(float a) {return Min(1.0f,Max(0.0f,a));} + + +float Round(float a,float precision) +{ + return floorf(0.5f+a/precision)*precision; +} + + +float Interpolate(const float &f0,const float &f1,float alpha) +{ + return f0*(1-alpha) + f1*alpha; +} + + +int argmin(float a[],int n) +{ + int r=0; + for(int i=1;i=1.0) { + return a; + } + float theta = acosf(d); + if(theta==0.0f) { return(a);} + return a*(sinf(theta-interp*theta)/sinf(theta)) + b*(sinf(interp*theta)/sinf(theta)); +} + + +Quaternion Interpolate(const Quaternion &q0,const Quaternion &q1,float alpha) { + return slerp(q0,q1,alpha); +} + + +Quaternion YawPitchRoll( float yaw, float pitch, float roll ) +{ + roll *= DEG2RAD; + yaw *= DEG2RAD; + pitch *= DEG2RAD; + return Quaternion(float3(0.0f,0.0f,1.0f),yaw)*Quaternion(float3(1.0f,0.0f,0.0f),pitch)*Quaternion(float3(0.0f,1.0f,0.0f),roll); +} + +float Yaw( const Quaternion& q ) +{ + float3 v; + v=q.ydir(); + return (v.y==0.0&&v.x==0.0) ? 0.0f: atan2f(-v.x,v.y)*RAD2DEG; +} + +float Pitch( const Quaternion& q ) +{ + float3 v; + v=q.ydir(); + return atan2f(v.z,sqrtf(sqr(v.x)+sqr(v.y)))*RAD2DEG; +} + +float Roll( Quaternion q ) +{ + q = Quaternion(float3(0.0f,0.0f,1.0f),-Yaw(q)*DEG2RAD) *q; + q = Quaternion(float3(1.0f,0.0f,0.0f),-Pitch(q)*DEG2RAD) *q; + return atan2f(-q.xdir().z,q.xdir().x)*RAD2DEG; +} + +float Yaw( const float3& v ) +{ + return (v.y==0.0&&v.x==0.0) ? 0.0f: atan2f(-v.x,v.y)*RAD2DEG; +} + +float Pitch( const float3& v ) +{ + return atan2f(v.z,sqrtf(sqr(v.x)+sqr(v.y)))*RAD2DEG; +} + + +//------------- Plane -------------- + + +void Plane::Transform(const float3 &position, const Quaternion &orientation) { + // Transforms the plane to the space defined by the + // given position/orientation. + float3 newnormal; + float3 origin; + + newnormal = Inverse(orientation)*normal; + origin = Inverse(orientation)*(-normal*dist - position); + + normal = newnormal; + dist = -dot(newnormal, origin); +} + + + + +//--------- utility functions ------------- + +// RotationArc() +// Given two vectors v0 and v1 this function +// returns quaternion q where q*v0==v1. +// Routine taken from game programming gems. +Quaternion RotationArc(float3 v0,float3 v1){ + Quaternion q; + v0 = normalize(v0); // Comment these two lines out if you know its not needed. + v1 = normalize(v1); // If vector is already unit length then why do it again? + float3 c = cross(v0,v1); + float d = dot(v0,v1); + if(d<=-1.0f) { return Quaternion(1,0,0,0);} // 180 about x axis + float s = sqrtf((1+d)*2); + q.x = c.x / s; + q.y = c.y / s; + q.z = c.z / s; + q.w = s /2.0f; + return q; +} + + +float4x4 MatrixFromQuatVec(const Quaternion &q, const float3 &v) +{ + // builds a 4x4 transformation matrix based on orientation q and translation v + float qx2 = q.x*q.x; + float qy2 = q.y*q.y; + float qz2 = q.z*q.z; + + float qxqy = q.x*q.y; + float qxqz = q.x*q.z; + float qxqw = q.x*q.w; + float qyqz = q.y*q.z; + float qyqw = q.y*q.w; + float qzqw = q.z*q.w; + + return float4x4( + 1-2*(qy2+qz2), + 2*(qxqy+qzqw), + 2*(qxqz-qyqw), + 0 , + 2*(qxqy-qzqw), + 1-2*(qx2+qz2), + 2*(qyqz+qxqw), + 0 , + 2*(qxqz+qyqw), + 2*(qyqz-qxqw), + 1-2*(qx2+qy2), + 0 , + v.x , + v.y , + v.z , + 1.0f ); +} + + +float3 PlaneLineIntersection(const Plane &plane, const float3 &p0, const float3 &p1) +{ + // returns the point where the line p0-p1 intersects the plane n&d + float3 dif; + dif = p1-p0; + float dn= dot(plane.normal,dif); + float t = -(plane.dist+dot(plane.normal,p0) )/dn; + return p0 + (dif*t); +} + +float3 PlaneProject(const Plane &plane, const float3 &point) +{ + return point - plane.normal * (dot(point,plane.normal)+plane.dist); +} + +float3 LineProject(const float3 &p0, const float3 &p1, const float3 &a) +{ + float3 w; + w = p1-p0; + float t= dot(w,(a-p0)) / (sqr(w.x)+sqr(w.y)+sqr(w.z)); + return p0+ w*t; +} + + +float LineProjectTime(const float3 &p0, const float3 &p1, const float3 &a) +{ + float3 w; + w = p1-p0; + float t= dot(w,(a-p0)) / (sqr(w.x)+sqr(w.y)+sqr(w.z)); + return t; +} + + + +float3 TriNormal(const float3 &v0, const float3 &v1, const float3 &v2) +{ + // return the normal of the triangle + // inscribed by v0, v1, and v2 + float3 cp=cross(v1-v0,v2-v1); + float m=magnitude(cp); + if(m==0) return float3(1,0,0); + return cp*(1.0f/m); +} + + + +int BoxInside(const float3 &p, const float3 &bmin, const float3 &bmax) +{ + return (p.x >= bmin.x && p.x <=bmax.x && + p.y >= bmin.y && p.y <=bmax.y && + p.z >= bmin.z && p.z <=bmax.z ); +} + + +int BoxIntersect(const float3 &v0, const float3 &v1, const float3 &bmin, const float3 &bmax,float3 *impact) +{ + if(BoxInside(v0,bmin,bmax)) + { + *impact=v0; + return 1; + } + if(v0.x<=bmin.x && v1.x>=bmin.x) + { + float a = (bmin.x-v0.x)/(v1.x-v0.x); + //v.x = bmin.x; + float vy = (1-a) *v0.y + a*v1.y; + float vz = (1-a) *v0.z + a*v1.z; + if(vy>=bmin.y && vy<=bmax.y && vz>=bmin.z && vz<=bmax.z) + { + impact->x = bmin.x; + impact->y = vy; + impact->z = vz; + return 1; + } + } + else if(v0.x >= bmax.x && v1.x <= bmax.x) + { + float a = (bmax.x-v0.x)/(v1.x-v0.x); + //v.x = bmax.x; + float vy = (1-a) *v0.y + a*v1.y; + float vz = (1-a) *v0.z + a*v1.z; + if(vy>=bmin.y && vy<=bmax.y && vz>=bmin.z && vz<=bmax.z) + { + impact->x = bmax.x; + impact->y = vy; + impact->z = vz; + return 1; + } + } + if(v0.y<=bmin.y && v1.y>=bmin.y) + { + float a = (bmin.y-v0.y)/(v1.y-v0.y); + float vx = (1-a) *v0.x + a*v1.x; + //v.y = bmin.y; + float vz = (1-a) *v0.z + a*v1.z; + if(vx>=bmin.x && vx<=bmax.x && vz>=bmin.z && vz<=bmax.z) + { + impact->x = vx; + impact->y = bmin.y; + impact->z = vz; + return 1; + } + } + else if(v0.y >= bmax.y && v1.y <= bmax.y) + { + float a = (bmax.y-v0.y)/(v1.y-v0.y); + float vx = (1-a) *v0.x + a*v1.x; + // vy = bmax.y; + float vz = (1-a) *v0.z + a*v1.z; + if(vx>=bmin.x && vx<=bmax.x && vz>=bmin.z && vz<=bmax.z) + { + impact->x = vx; + impact->y = bmax.y; + impact->z = vz; + return 1; + } + } + if(v0.z<=bmin.z && v1.z>=bmin.z) + { + float a = (bmin.z-v0.z)/(v1.z-v0.z); + float vx = (1-a) *v0.x + a*v1.x; + float vy = (1-a) *v0.y + a*v1.y; + // v.z = bmin.z; + if(vy>=bmin.y && vy<=bmax.y && vx>=bmin.x && vx<=bmax.x) + { + impact->x = vx; + impact->y = vy; + impact->z = bmin.z; + return 1; + } + } + else if(v0.z >= bmax.z && v1.z <= bmax.z) + { + float a = (bmax.z-v0.z)/(v1.z-v0.z); + float vx = (1-a) *v0.x + a*v1.x; + float vy = (1-a) *v0.y + a*v1.y; + // v.z = bmax.z; + if(vy>=bmin.y && vy<=bmax.y && vx>=bmin.x && vx<=bmax.x) + { + impact->x = vx; + impact->y = vy; + impact->z = bmax.z; + return 1; + } + } + return 0; +} + + +float DistanceBetweenLines(const float3 &ustart, const float3 &udir, const float3 &vstart, const float3 &vdir, float3 *upoint, float3 *vpoint) +{ + float3 cp; + cp = normalize(cross(udir,vdir)); + + float distu = -dot(cp,ustart); + float distv = -dot(cp,vstart); + float dist = (float)fabs(distu-distv); + if(upoint) + { + Plane plane; + plane.normal = normalize(cross(vdir,cp)); + plane.dist = -dot(plane.normal,vstart); + *upoint = PlaneLineIntersection(plane,ustart,ustart+udir); + } + if(vpoint) + { + Plane plane; + plane.normal = normalize(cross(udir,cp)); + plane.dist = -dot(plane.normal,ustart); + *vpoint = PlaneLineIntersection(plane,vstart,vstart+vdir); + } + return dist; +} + + +Quaternion VirtualTrackBall(const float3 &cop, const float3 &cor, const float3 &dir1, const float3 &dir2) +{ + // routine taken from game programming gems. + // Implement track ball functionality to spin stuf on the screen + // cop center of projection + // cor center of rotation + // dir1 old mouse direction + // dir2 new mouse direction + // pretend there is a sphere around cor. Then find the points + // where dir1 and dir2 intersect that sphere. Find the + // rotation that takes the first point to the second. + float m; + // compute plane + float3 nrml = cor - cop; + float fudgefactor = 1.0f/(magnitude(nrml) * 0.25f); // since trackball proportional to distance from cop + nrml = normalize(nrml); + float dist = -dot(nrml,cor); + float3 u= PlaneLineIntersection(Plane(nrml,dist),cop,cop+dir1); + u=u-cor; + u=u*fudgefactor; + m= magnitude(u); + if(m>1) + { + u/=m; + } + else + { + u=u - (nrml * sqrtf(1-m*m)); + } + float3 v= PlaneLineIntersection(Plane(nrml,dist),cop,cop+dir2); + v=v-cor; + v=v*fudgefactor; + m= magnitude(v); + if(m>1) + { + v/=m; + } + else + { + v=v - (nrml * sqrtf(1-m*m)); + } + return RotationArc(u,v); +} + + +int countpolyhit=0; +int PolyHit(const float3 *vert, const int n, const float3 &v0, const float3 &v1, float3 *impact, float3 *normal) +{ + countpolyhit++; + int i; + float3 nrml(0,0,0); + for(i=0;i0) + { + return 0; + } + + float3 the_point; + // By using the cached plane distances d0 and d1 + // we can optimize the following: + // the_point = planelineintersection(nrml,dist,v0,v1); + float a = d0/(d0-d1); + the_point = v0*(1-a) + v1*a; + + + int inside=1; + for(int j=0;inside && j= 0.0); + } + if(inside) + { + if(normal){*normal=nrml;} + if(impact){*impact=the_point;} + } + return inside; +} + +//************************************************************************** +//************************************************************************** +//*** Stan Melax's array template, needed to compile his hull generation code +//************************************************************************** +//************************************************************************** + +template class ArrayRet; +template class Array { + public: + Array(int s=0); + Array(Array &array); + Array(ArrayRet &array); + ~Array(); + void allocate(int s); + void SetSize(int s); + void Pack(); + Type& Add(Type); + void AddUnique(Type); + int Contains(Type); + void Insert(Type,int); + int IndexOf(Type); + void Remove(Type); + void DelIndex(int i); + Type * element; + int count; + int array_size; + const Type &operator[](int i) const { assert(i>=0 && i=0 && i &operator=(Array &array); + Array &operator=(ArrayRet &array); + // operator ArrayRet &() { return *(ArrayRet *)this;} // this worked but i suspect could be dangerous +}; + +template class ArrayRet:public Array +{ +}; + +template Array::Array(int s) +{ + count=0; + array_size = 0; + element = NULL; + if(s) + { + allocate(s); + } +} + + +template Array::Array(Array &array) +{ + count=0; + array_size = 0; + element = NULL; + for(int i=0;i Array::Array(ArrayRet &array) +{ + *this = array; +} +template Array &Array::operator=(ArrayRet &array) +{ + count=array.count; + array_size = array.array_size; + element = array.element; + array.element=NULL; + array.count=0; + array.array_size=0; + return *this; +} + + +template Array &Array::operator=(Array &array) +{ + count=0; + for(int i=0;i Array::~Array() +{ + if (element != NULL) + { + free(element); + } + count=0;array_size=0;element=NULL; +} + +template void Array::allocate(int s) +{ + assert(s>0); + assert(s>=count); + Type *old = element; + array_size =s; + element = (Type *) malloc( sizeof(Type)*array_size); + assert(element); + for(int i=0;i void Array::SetSize(int s) +{ + if(s==0) + { + if(element) + { + free(element); + element = NULL; + } + array_size = s; + } + else + { + allocate(s); + } + count=s; +} + +template void Array::Pack() +{ + allocate(count); +} + +template Type& Array::Add(Type t) +{ + assert(count<=array_size); + if(count==array_size) + { + allocate((array_size)?array_size *2:16); + } + element[count++] = t; + return element[count-1]; +} + +template int Array::Contains(Type t) +{ + int i; + int found=0; + for(i=0;i void Array::AddUnique(Type t) +{ + if(!Contains(t)) Add(t); +} + + +template void Array::DelIndex(int i) +{ + assert(i void Array::Remove(Type t) +{ + int i; + for(i=0;i void Array::Insert(Type t,int k) +{ + int i=count; + Add(t); // to allocate space + while(i>k) + { + element[i]=element[i-1]; + i--; + } + assert(i==k); + element[k]=t; +} + + +template int Array::IndexOf(Type t) +{ + int i; + for(i=0;i vertices; + Array edges; + Array facets; + ConvexH(int vertices_size,int edges_size,int facets_size); +}; + +typedef ConvexH::HalfEdge HalfEdge; + +ConvexH::ConvexH(int vertices_size,int edges_size,int facets_size) + :vertices(vertices_size) + ,edges(edges_size) + ,facets(facets_size) +{ + vertices.count=vertices_size; + edges.count = edges_size; + facets.count = facets_size; +} + +ConvexH *ConvexHDup(ConvexH *src) { + ConvexH *dst = new ConvexH(src->vertices.count,src->edges.count,src->facets.count); + memcpy(dst->vertices.element,src->vertices.element,sizeof(float3)*src->vertices.count); + memcpy(dst->edges.element,src->edges.element,sizeof(HalfEdge)*src->edges.count); + memcpy(dst->facets.element,src->facets.element,sizeof(Plane)*src->facets.count); + return dst; +} + + +int PlaneTest(const Plane &p, const REAL3 &v) { + REAL a = dot(v,p.normal)+p.dist; + int flag = (a>planetestepsilon)?OVER:((a<-planetestepsilon)?UNDER:COPLANAR); + return flag; +} + +int SplitTest(ConvexH &convex,const Plane &plane) { + int flag=0; + for(int i=0;i= convex.edges.count || convex.edges[inext].p != convex.edges[i].p) { + inext = estart; + } + assert(convex.edges[inext].p == convex.edges[i].p); + int nb = convex.edges[i].ea; + assert(nb!=255); + if(nb==255 || nb==-1) return 0; + assert(nb!=-1); + assert(i== convex.edges[nb].ea); + } + for(i=0;i= convex.edges.count || convex.edges[i1].p != convex.edges[i].p) { + i1 = estart; + } + int i2 = i1+1; + if(i2>= convex.edges.count || convex.edges[i2].p != convex.edges[i].p) { + i2 = estart; + } + if(i==i2) continue; // i sliced tangent to an edge and created 2 meaningless edges + REAL3 localnormal = TriNormal(convex.vertices[convex.edges[i ].v], + convex.vertices[convex.edges[i1].v], + convex.vertices[convex.edges[i2].v]); + assert(dot(localnormal,convex.facets[convex.edges[i].p].normal)>0); + if(dot(localnormal,convex.facets[convex.edges[i].p].normal)<=0)return 0; + } + return 1; +} + +// back to back quads +ConvexH *test_btbq() { + ConvexH *convex = new ConvexH(4,8,2); + convex->vertices[0] = REAL3(0,0,0); + convex->vertices[1] = REAL3(1,0,0); + convex->vertices[2] = REAL3(1,1,0); + convex->vertices[3] = REAL3(0,1,0); + convex->facets[0] = Plane(REAL3(0,0,1),0); + convex->facets[1] = Plane(REAL3(0,0,-1),0); + convex->edges[0] = HalfEdge(7,0,0); + convex->edges[1] = HalfEdge(6,1,0); + convex->edges[2] = HalfEdge(5,2,0); + convex->edges[3] = HalfEdge(4,3,0); + + convex->edges[4] = HalfEdge(3,0,1); + convex->edges[5] = HalfEdge(2,3,1); + convex->edges[6] = HalfEdge(1,2,1); + convex->edges[7] = HalfEdge(0,1,1); + AssertIntact(*convex); + return convex; +} +ConvexH *test_cube() { + ConvexH *convex = new ConvexH(8,24,6); + convex->vertices[0] = REAL3(0,0,0); + convex->vertices[1] = REAL3(0,0,1); + convex->vertices[2] = REAL3(0,1,0); + convex->vertices[3] = REAL3(0,1,1); + convex->vertices[4] = REAL3(1,0,0); + convex->vertices[5] = REAL3(1,0,1); + convex->vertices[6] = REAL3(1,1,0); + convex->vertices[7] = REAL3(1,1,1); + + convex->facets[0] = Plane(REAL3(-1,0,0),0); + convex->facets[1] = Plane(REAL3(1,0,0),-1); + convex->facets[2] = Plane(REAL3(0,-1,0),0); + convex->facets[3] = Plane(REAL3(0,1,0),-1); + convex->facets[4] = Plane(REAL3(0,0,-1),0); + convex->facets[5] = Plane(REAL3(0,0,1),-1); + + convex->edges[0 ] = HalfEdge(11,0,0); + convex->edges[1 ] = HalfEdge(23,1,0); + convex->edges[2 ] = HalfEdge(15,3,0); + convex->edges[3 ] = HalfEdge(16,2,0); + + convex->edges[4 ] = HalfEdge(13,6,1); + convex->edges[5 ] = HalfEdge(21,7,1); + convex->edges[6 ] = HalfEdge( 9,5,1); + convex->edges[7 ] = HalfEdge(18,4,1); + + convex->edges[8 ] = HalfEdge(19,0,2); + convex->edges[9 ] = HalfEdge( 6,4,2); + convex->edges[10] = HalfEdge(20,5,2); + convex->edges[11] = HalfEdge( 0,1,2); + + convex->edges[12] = HalfEdge(22,3,3); + convex->edges[13] = HalfEdge( 4,7,3); + convex->edges[14] = HalfEdge(17,6,3); + convex->edges[15] = HalfEdge( 2,2,3); + + convex->edges[16] = HalfEdge( 3,0,4); + convex->edges[17] = HalfEdge(14,2,4); + convex->edges[18] = HalfEdge( 7,6,4); + convex->edges[19] = HalfEdge( 8,4,4); + + convex->edges[20] = HalfEdge(10,1,5); + convex->edges[21] = HalfEdge( 5,5,5); + convex->edges[22] = HalfEdge(12,7,5); + convex->edges[23] = HalfEdge( 1,3,5); + + + return convex; +} +ConvexH *ConvexHMakeCube(const REAL3 &bmin, const REAL3 &bmax) { + ConvexH *convex = test_cube(); + convex->vertices[0] = REAL3(bmin.x,bmin.y,bmin.z); + convex->vertices[1] = REAL3(bmin.x,bmin.y,bmax.z); + convex->vertices[2] = REAL3(bmin.x,bmax.y,bmin.z); + convex->vertices[3] = REAL3(bmin.x,bmax.y,bmax.z); + convex->vertices[4] = REAL3(bmax.x,bmin.y,bmin.z); + convex->vertices[5] = REAL3(bmax.x,bmin.y,bmax.z); + convex->vertices[6] = REAL3(bmax.x,bmax.y,bmin.z); + convex->vertices[7] = REAL3(bmax.x,bmax.y,bmax.z); + + convex->facets[0] = Plane(REAL3(-1,0,0), bmin.x); + convex->facets[1] = Plane(REAL3(1,0,0), -bmax.x); + convex->facets[2] = Plane(REAL3(0,-1,0), bmin.y); + convex->facets[3] = Plane(REAL3(0,1,0), -bmax.y); + convex->facets[4] = Plane(REAL3(0,0,-1), bmin.z); + convex->facets[5] = Plane(REAL3(0,0,1), -bmax.z); + return convex; +} +ConvexH *ConvexHCrop(ConvexH &convex,const Plane &slice) +{ + int i; + int vertcountunder=0; + int vertcountover =0; + Array vertscoplanar; // existing vertex members of convex that are coplanar + vertscoplanar.count=0; + Array edgesplit; // existing edges that members of convex that cross the splitplane + edgesplit.count=0; + + assert(convex.edges.count<480); + + EdgeFlag edgeflag[512]; + VertFlag vertflag[256]; + PlaneFlag planeflag[128]; + HalfEdge tmpunderedges[512]; + Plane tmpunderplanes[128]; + Coplanar coplanaredges[512]; + int coplanaredges_num=0; + + Array createdverts; + // do the side-of-plane tests + for(i=0;i= convex.edges.count || convex.edges[e1].p!=currentplane) { + enextface = e1; + e1=estart; + } + HalfEdge &edge0 = convex.edges[e0]; + HalfEdge &edge1 = convex.edges[e1]; + HalfEdge &edgea = convex.edges[edge0.ea]; + + + planeside |= vertflag[edge0.v].planetest; + //if((vertflag[edge0.v].planetest & vertflag[edge1.v].planetest) == COPLANAR) { + // assert(ecop==-1); + // ecop=e; + //} + + + if(vertflag[edge0.v].planetest == OVER && vertflag[edge1.v].planetest == OVER){ + // both endpoints over plane + edgeflag[e0].undermap = -1; + } + else if((vertflag[edge0.v].planetest | vertflag[edge1.v].planetest) == UNDER) { + // at least one endpoint under, the other coplanar or under + + edgeflag[e0].undermap = under_edge_count; + tmpunderedges[under_edge_count].v = vertflag[edge0.v].undermap; + tmpunderedges[under_edge_count].p = underplanescount; + if(edge0.ea < e0) { + // connect the neighbors + assert(edgeflag[edge0.ea].undermap !=-1); + tmpunderedges[under_edge_count].ea = edgeflag[edge0.ea].undermap; + tmpunderedges[edgeflag[edge0.ea].undermap].ea = under_edge_count; + } + under_edge_count++; + } + else if((vertflag[edge0.v].planetest | vertflag[edge1.v].planetest) == COPLANAR) { + // both endpoints coplanar + // must check a 3rd point to see if UNDER + int e2 = e1+1; + if(e2>=convex.edges.count || convex.edges[e2].p!=currentplane) { + e2 = estart; + } + assert(convex.edges[e2].p==currentplane); + HalfEdge &edge2 = convex.edges[e2]; + if(vertflag[edge2.v].planetest==UNDER) { + + edgeflag[e0].undermap = under_edge_count; + tmpunderedges[under_edge_count].v = vertflag[edge0.v].undermap; + tmpunderedges[under_edge_count].p = underplanescount; + tmpunderedges[under_edge_count].ea = -1; + // make sure this edge is added to the "coplanar" list + coplanaredge = under_edge_count; + vout = vertflag[edge0.v].undermap; + vin = vertflag[edge1.v].undermap; + under_edge_count++; + } + else { + edgeflag[e0].undermap = -1; + } + } + else if(vertflag[edge0.v].planetest == UNDER && vertflag[edge1.v].planetest == OVER) { + // first is under 2nd is over + + edgeflag[e0].undermap = under_edge_count; + tmpunderedges[under_edge_count].v = vertflag[edge0.v].undermap; + tmpunderedges[under_edge_count].p = underplanescount; + if(edge0.ea < e0) { + assert(edgeflag[edge0.ea].undermap !=-1); + // connect the neighbors + tmpunderedges[under_edge_count].ea = edgeflag[edge0.ea].undermap; + tmpunderedges[edgeflag[edge0.ea].undermap].ea = under_edge_count; + vout = tmpunderedges[edgeflag[edge0.ea].undermap].v; + } + else { + Plane &p0 = convex.facets[edge0.p]; + Plane &pa = convex.facets[edgea.p]; + createdverts.Add(ThreePlaneIntersection(p0,pa,slice)); + //createdverts.Add(PlaneProject(slice,PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v]))); + //createdverts.Add(PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v])); + vout = vertcountunder++; + } + under_edge_count++; + /// hmmm something to think about: i might be able to output this edge regarless of + // wheter or not we know v-in yet. ok i;ll try this now: + tmpunderedges[under_edge_count].v = vout; + tmpunderedges[under_edge_count].p = underplanescount; + tmpunderedges[under_edge_count].ea = -1; + coplanaredge = under_edge_count; + under_edge_count++; + + if(vin!=-1) { + // we previously processed an edge where we came under + // now we know about vout as well + + // ADD THIS EDGE TO THE LIST OF EDGES THAT NEED NEIGHBOR ON PARTITION PLANE!! + } + + } + else if(vertflag[edge0.v].planetest == COPLANAR && vertflag[edge1.v].planetest == OVER) { + // first is coplanar 2nd is over + + edgeflag[e0].undermap = -1; + vout = vertflag[edge0.v].undermap; + // I hate this but i have to make sure part of this face is UNDER before ouputting this vert + int k=estart; + assert(edge0.p == currentplane); + while(!(planeside&UNDER) && k= vertcountunderold); // for debugging only + } + if(vout!=-1) { + // we previously processed an edge where we went over + // now we know vin too + // ADD THIS EDGE TO THE LIST OF EDGES THAT NEED NEIGHBOR ON PARTITION PLANE!! + } + // output edge + tmpunderedges[under_edge_count].v = vin; + tmpunderedges[under_edge_count].p = underplanescount; + edgeflag[e0].undermap = under_edge_count; + if(e0>edge0.ea) { + assert(edgeflag[edge0.ea].undermap !=-1); + // connect the neighbors + tmpunderedges[under_edge_count].ea = edgeflag[edge0.ea].undermap; + tmpunderedges[edgeflag[edge0.ea].undermap].ea = under_edge_count; + } + assert(edgeflag[e0].undermap == under_edge_count); + under_edge_count++; + } + else if(vertflag[edge0.v].planetest == OVER && vertflag[edge1.v].planetest == COPLANAR) { + // first is over next is coplanar + + edgeflag[e0].undermap = -1; + vin = vertflag[edge1.v].undermap; + assert(vin!=-1); + if(vout!=-1) { + // we previously processed an edge where we came under + // now we know both endpoints + // ADD THIS EDGE TO THE LIST OF EDGES THAT NEED NEIGHBOR ON PARTITION PLANE!! + } + + } + else { + assert(0); + } + + + e0=e1; + e1++; // do the modulo at the beginning of the loop + + } while(e0!=estart) ; + e0 = enextface; + if(planeside&UNDER) { + planeflag[currentplane].undermap = underplanescount; + tmpunderplanes[underplanescount] = convex.facets[currentplane]; + underplanescount++; + } + else { + planeflag[currentplane].undermap = 0; + } + if(vout>=0 && (planeside&UNDER)) { + assert(vin>=0); + assert(coplanaredge>=0); + assert(coplanaredge!=511); + coplanaredges[coplanaredges_num].ea = coplanaredge; + coplanaredges[coplanaredges_num].v0 = vin; + coplanaredges[coplanaredges_num].v1 = vout; + coplanaredges_num++; + } + } + + // add the new plane to the mix: + if(coplanaredges_num>0) { + tmpunderplanes[underplanescount++]=slice; + } + for(i=0;i=coplanaredges_num) + { + assert(jvertices.count;j++) + { + d = Max(d,dot(convex->vertices[j],planes[i].normal)+planes[i].dist); + } + if(i==0 || d>md) + { + p=i; + md=d; + } + } + return (md>epsilon)?p:-1; +} + +template +inline int maxdir(const T *p,int count,const T &dir) +{ + assert(count); + int m=0; + float currDotm = dot(p[0], dir); + for(int i=1;i currDotm) + { + currDotm = currDoti; + m=i; + } + } + return m; +} + + +template +int maxdirfiltered(const T *p,int count,const T &dir,Array &allow) +{ + assert(count); + int m=-1; + float currDotm = dot(p[0], dir); + for(int i=0;icurrDotm) + { + currDotm = currDoti; + m=i; + } + } + } + } + assert(m!=-1); + return m; +} + +float3 orth(const float3 &v) +{ + float3 a=cross(v,float3(0,0,1)); + float3 b=cross(v,float3(0,1,0)); + return normalize((magnitude(a)>magnitude(b))?a:b); +} + + +template +int maxdirsterid(const T *p,int count,const T &dir,Array &allow) +{ + int m=-1; + while(m==-1) + { + m = maxdirfiltered(p,count,dir,allow); + if(allow[m]==3) return m; + T u = orth(dir); + T v = cross(u,dir); + int ma=-1; + for(float x = 0.0f ; x<= 360.0f ; x+= 45.0f) + { + float s = sinf(DEG2RAD*(x)); + float c = cosf(DEG2RAD*(x)); + int mb = maxdirfiltered(p,count,dir+(u*s+v*c)*0.025f,allow); + if(ma==m && mb==m) + { + allow[m]=3; + return m; + } + if(ma!=-1 && ma!=mb) // Yuck - this is really ugly + { + int mc = ma; + for(float xx = x-40.0f ; xx <= x ; xx+= 5.0f) + { + float s = sinf(DEG2RAD*(xx)); + float c = cosf(DEG2RAD*(xx)); + int md = maxdirfiltered(p,count,dir+(u*s+v*c)*0.025f,allow); + if(mc==m && md==m) + { + allow[m]=3; + return m; + } + mc=md; + } + } + ma=mb; + } + allow[m]=0; + m=-1; + } + assert(0); + return m; +} + + + + +int operator ==(const int3 &a,const int3 &b) +{ + for(int i=0;i<3;i++) + { + if(a[i]!=b[i]) return 0; + } + return 1; +} + +int3 roll3(int3 a) +{ + int tmp=a[0]; + a[0]=a[1]; + a[1]=a[2]; + a[2]=tmp; + return a; +} +int isa(const int3 &a,const int3 &b) +{ + return ( a==b || roll3(a)==b || a==roll3(b) ); +} +int b2b(const int3 &a,const int3 &b) +{ + return isa(a,int3(b[2],b[1],b[0])); +} +int above(float3* vertices,const int3& t, const float3 &p, float epsilon) +{ + float3 n=TriNormal(vertices[t[0]],vertices[t[1]],vertices[t[2]]); + return (dot(n,p-vertices[t[0]]) > epsilon); // EPSILON??? +} +int hasedge(const int3 &t, int a,int b) +{ + for(int i=0;i<3;i++) + { + int i1= (i+1)%3; + if(t[i]==a && t[i1]==b) return 1; + } + return 0; +} +int hasvert(const int3 &t, int v) +{ + return (t[0]==v || t[1]==v || t[2]==v) ; +} +int shareedge(const int3 &a,const int3 &b) +{ + int i; + for(i=0;i<3;i++) + { + int i1= (i+1)%3; + if(hasedge(a,b[i1],b[i])) return 1; + } + return 0; +} + +class btHullTriangle; + +//Array tris; + +class btHullTriangle : public int3 +{ +public: + int3 n; + int id; + int vmax; + float rise; + Array* tris; + btHullTriangle(int a,int b,int c, Array* pTris):int3(a,b,c),n(-1,-1,-1) + { + tris = pTris; + id = tris->count; + tris->Add(this); + vmax=-1; + rise = 0.0f; + } + ~btHullTriangle() + { + assert((*tris)[id]==this); + (*tris)[id]=NULL; + } + int &neib(int a,int b); +}; + + +int &btHullTriangle::neib(int a,int b) +{ + static int er=-1; + int i; + for(i=0;i<3;i++) + { + int i1=(i+1)%3; + int i2=(i+2)%3; + if((*this)[i]==a && (*this)[i1]==b) return n[i2]; + if((*this)[i]==b && (*this)[i1]==a) return n[i2]; + } + assert(0); + return er; +} +void b2bfix(btHullTriangle* s,btHullTriangle*t, Array& tris) +{ + int i; + for(i=0;i<3;i++) + { + int i1=(i+1)%3; + int i2=(i+2)%3; + int a = (*s)[i1]; + int b = (*s)[i2]; + assert(tris[s->neib(a,b)]->neib(b,a) == s->id); + assert(tris[t->neib(a,b)]->neib(b,a) == t->id); + tris[s->neib(a,b)]->neib(b,a) = t->neib(b,a); + tris[t->neib(b,a)]->neib(a,b) = s->neib(a,b); + } +} + +void removeb2b(btHullTriangle* s,btHullTriangle*t, Array& tris) +{ + b2bfix(s,t, tris); + delete s; + delete t; +} + +void checkit(btHullTriangle *t, Array& tris) +{ + int i; + assert(tris[t->id]==t); + for(i=0;i<3;i++) + { + int i1=(i+1)%3; + int i2=(i+2)%3; + int a = (*t)[i1]; + int b = (*t)[i2]; + assert(a!=b); + assert( tris[t->n[i]]->neib(b,a) == t->id); + } +} +void extrude(btHullTriangle *t0,int v, Array& tris) +{ + int3 t= *t0; + int n = tris.count; + btHullTriangle* ta = new btHullTriangle(v,t[1],t[2], &tris); + ta->n = int3(t0->n[0],n+1,n+2); + tris[t0->n[0]]->neib(t[1],t[2]) = n+0; + btHullTriangle* tb = new btHullTriangle(v,t[2],t[0], &tris); + tb->n = int3(t0->n[1],n+2,n+0); + tris[t0->n[1]]->neib(t[2],t[0]) = n+1; + btHullTriangle* tc = new btHullTriangle(v,t[0],t[1], &tris); + tc->n = int3(t0->n[2],n+0,n+1); + tris[t0->n[2]]->neib(t[0],t[1]) = n+2; + checkit(ta, tris); + checkit(tb, tris); + checkit(tc, tris); + if(hasvert(*tris[ta->n[0]],v)) removeb2b(ta,tris[ta->n[0]], tris); + if(hasvert(*tris[tb->n[0]],v)) removeb2b(tb,tris[tb->n[0]], tris); + if(hasvert(*tris[tc->n[0]],v)) removeb2b(tc,tris[tc->n[0]], tris); + delete t0; + +} + +btHullTriangle *extrudable(float epsilon, Array& tris) +{ + int i; + btHullTriangle *t=NULL; + for(i=0;iriserise)) + { + t = tris[i]; + } + } + return (t->rise >epsilon)?t:NULL ; +} + +class int4 +{ +public: + int x,y,z,w; + int4(){}; + int4(int _x,int _y, int _z,int _w){x=_x;y=_y;z=_z;w=_w;} + const int& operator[](int i) const {return (&x)[i];} + int& operator[](int i) {return (&x)[i];} +}; + + + +int4 FindSimplex(float3 *verts,int verts_count,Array &allow) +{ + float3 basis[3]; + basis[0] = float3( 0.01f, 0.02f, 1.0f ); + int p0 = maxdirsterid(verts,verts_count, basis[0],allow); + int p1 = maxdirsterid(verts,verts_count,-basis[0],allow); + basis[0] = verts[p0]-verts[p1]; + if(p0==p1 || basis[0]==float3(0,0,0)) + return int4(-1,-1,-1,-1); + basis[1] = cross(float3( 1, 0.02f, 0),basis[0]); + basis[2] = cross(float3(-0.02f, 1, 0),basis[0]); + basis[1] = normalize( (magnitude(basis[1])>magnitude(basis[2])) ? basis[1]:basis[2]); + int p2 = maxdirsterid(verts,verts_count,basis[1],allow); + if(p2 == p0 || p2 == p1) + { + p2 = maxdirsterid(verts,verts_count,-basis[1],allow); + } + if(p2 == p0 || p2 == p1) + return int4(-1,-1,-1,-1); + basis[1] = verts[p2] - verts[p0]; + basis[2] = normalize(cross(basis[1],basis[0])); + int p3 = maxdirsterid(verts,verts_count,basis[2],allow); + if(p3==p0||p3==p1||p3==p2) p3 = maxdirsterid(verts,verts_count,-basis[2],allow); + if(p3==p0||p3==p1||p3==p2) + return int4(-1,-1,-1,-1); + assert(!(p0==p1||p0==p2||p0==p3||p1==p2||p1==p3||p2==p3)); + if(dot(verts[p3]-verts[p0],cross(verts[p1]-verts[p0],verts[p2]-verts[p0])) <0) {Swap(p2,p3);} + return int4(p0,p1,p2,p3); +} + +int calchullgen(float3 *verts,int verts_count, int vlimit,Array& tris) +{ + if(verts_count <4) return 0; + if(vlimit==0) vlimit=1000000000; + int j; + float3 bmin(*verts),bmax(*verts); + Array isextreme(verts_count); + Array allow(verts_count); + for(j=0;jn=int3(2,3,1); + btHullTriangle *t1 = new btHullTriangle(p[3],p[2],p[0], &tris); t1->n=int3(3,2,0); + btHullTriangle *t2 = new btHullTriangle(p[0],p[1],p[3], &tris); t2->n=int3(0,1,3); + btHullTriangle *t3 = new btHullTriangle(p[1],p[0],p[2], &tris); t3->n=int3(1,0,2); + isextreme[p[0]]=isextreme[p[1]]=isextreme[p[2]]=isextreme[p[3]]=1; + checkit(t0, tris);checkit(t1, tris);checkit(t2, tris);checkit(t3, tris); + + for(j=0;jvmax<0); + float3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]); + t->vmax = maxdirsterid(verts,verts_count,n,allow); + t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]); + } + btHullTriangle *te; + vlimit-=4; + while(vlimit >0 && (te=extrudable(epsilon, tris))) + { + int3 ti=*te; + int v=te->vmax; + assert(!isextreme[v]); // wtf we've already done this vertex + isextreme[v]=1; + //if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already + j=tris.count; + while(j--) { + if(!tris[j]) continue; + int3 t=*tris[j]; + if(above(verts,t,verts[v],0.01f*epsilon)) + { + extrude(tris[j],v, tris); + } + } + // now check for those degenerate cases where we have a flipped triangle or a really skinny triangle + j=tris.count; + while(j--) + { + if(!tris[j]) continue; + if(!hasvert(*tris[j],v)) break; + int3 nt=*tris[j]; + if(above(verts,nt,center,0.01f*epsilon) || magnitude(cross(verts[nt[1]]-verts[nt[0]],verts[nt[2]]-verts[nt[1]]))< epsilon*epsilon*0.1f ) + { + btHullTriangle *nb = tris[tris[j]->n[0]]; + assert(nb);assert(!hasvert(*nb,v));assert(nb->idvmax>=0) break; + float3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]); + t->vmax = maxdirsterid(verts,verts_count,n,allow); + if(isextreme[t->vmax]) + { + t->vmax=-1; // already done that vertex - algorithm needs to be able to terminate. + } + else + { + t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]); + } + } + vlimit --; + } + return 1; +} + +int calchull(float3 *verts,int verts_count, int *&tris_out, int &tris_count,int vlimit, Array& tris) +{ + int rc=calchullgen(verts,verts_count, vlimit, tris) ; + if(!rc) return 0; + Array ts; + for(int i=0;i &planes,float bevangle, Array& tris) +{ + int i,j; + planes.count=0; + int rc = calchullgen(verts,verts_count,vlimit, tris); + if(!rc) return 0; + for(i=0;in[j]id) continue; + btHullTriangle *s = tris[t->n[j]]; + REAL3 snormal = TriNormal(verts[(*s)[0]],verts[(*s)[1]],verts[(*s)[2]]); + if(dot(snormal,p.normal)>=cos(bevangle*DEG2RAD)) continue; + REAL3 n = normalize(snormal+p.normal); + planes.Add(Plane(n,-dot(n,verts[maxdir(verts,verts_count,n)]))); + } + } + + for(i=0;i=0) + { + ConvexH *tmp = c; + c = ConvexHCrop(*tmp,planes[k]); + if(c==NULL) {c=tmp; break;} // might want to debug this case better!!! + if(!AssertIntact(*c)) {c=tmp; break;} // might want to debug this case better too!!! + delete tmp; + } + + assert(AssertIntact(*c)); + //return c; + faces_out = (int*)malloc(sizeof(int)*(1+c->facets.count+c->edges.count)); // new int[1+c->facets.count+c->edges.count]; + faces_count_out=0; + i=0; + faces_out[faces_count_out++]=-1; + k=0; + while(iedges.count) + { + j=1; + while(j+iedges.count && c->edges[i].p==c->edges[i+j].p) { j++; } + faces_out[faces_count_out++]=j; + while(j--) + { + faces_out[faces_count_out++] = c->edges[i].v; + i++; + } + k++; + } + faces_out[0]=k; // number of faces. + assert(k==c->facets.count); + assert(faces_count_out == 1+c->facets.count+c->edges.count); + verts_out = c->vertices.element; // new float3[c->vertices.count]; + verts_count_out = c->vertices.count; + for(i=0;ivertices.count;i++) + { + verts_out[i] = float3(c->vertices[i]); + } + c->vertices.count=c->vertices.array_size=0; c->vertices.element=NULL; + delete c; + return 1; +} + +int overhullv(float3 *verts, int verts_count,int maxplanes, + float3 *&verts_out, int &verts_count_out, int *&faces_out, int &faces_count_out ,float inflate,float bevangle,int vlimit, Array& tris) +{ + if(!verts_count) return 0; + extern int calchullpbev(float3 *verts,int verts_count,int vlimit, Array &planes,float bevangle, Array& tris) ; + Array planes; + int rc=calchullpbev(verts,verts_count,vlimit,planes,bevangle, tris) ; + if(!rc) return 0; + return overhull(planes.element,planes.count,verts,verts_count,maxplanes,verts_out,verts_count_out,faces_out,faces_count_out,inflate); +} + + +bool ComputeHull(unsigned int vcount,const float *vertices,PHullResult &result,unsigned int vlimit,float inflate, Array& arrtris) +{ + + int index_count; + int *faces; + float3 *verts_out; + int verts_count_out; + + if(inflate==0.0f) + { + int *tris_out; + int tris_count; + int ret = calchull( (float3 *) vertices, (int) vcount, tris_out, tris_count, vlimit, arrtris ); + if(!ret) return false; + result.mIndexCount = (unsigned int) (tris_count*3); + result.mFaceCount = (unsigned int) tris_count; + result.mVertices = (float*) vertices; + result.mVcount = (unsigned int) vcount; + result.mIndices = (unsigned int *) tris_out; + return true; + } + + int ret = overhullv((float3*)vertices,vcount,35,verts_out,verts_count_out,faces,index_count,inflate,120.0f,vlimit, arrtris); + if(!ret) return false; + + Array tris; + int n=faces[0]; + int k=1; + for(int i=0;i tris; + ok = ComputeHull(ovcount,vsource,hr,desc.mMaxVertices,skinwidth, tris); + + if ( ok ) + { + + // re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table. + float *vscratch = (float *) malloc( sizeof(float)*hr.mVcount*3); + BringOutYourDead(hr.mVertices,hr.mVcount, vscratch, ovcount, hr.mIndices, hr.mIndexCount ); + + ret = QE_OK; + + if ( desc.HasHullFlag(QF_TRIANGLES) ) // if he wants the results as triangle! + { + result.mPolygons = false; + result.mNumOutputVertices = ovcount; + result.mOutputVertices = (float *)malloc( sizeof(float)*ovcount*3); + result.mNumFaces = hr.mFaceCount; + result.mNumIndices = hr.mIndexCount; + + result.mIndices = (unsigned int *) malloc( sizeof(unsigned int)*hr.mIndexCount); + + memcpy(result.mOutputVertices, vscratch, sizeof(float)*3*ovcount ); + + if ( desc.HasHullFlag(QF_REVERSE_ORDER) ) + { + + const unsigned int *source = hr.mIndices; + unsigned int *dest = result.mIndices; + + for (unsigned int i=0; i bmax[j] ) bmax[j] = p[j]; + } + } + } + + float dx = bmax[0] - bmin[0]; + float dy = bmax[1] - bmin[1]; + float dz = bmax[2] - bmin[2]; + + float center[3]; + + center[0] = dx*0.5f + bmin[0]; + center[1] = dy*0.5f + bmin[1]; + center[2] = dz*0.5f + bmin[2]; + + if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || svcount < 3 ) + { + + float len = FLT_MAX; + + if ( dx > EPSILON && dx < len ) len = dx; + if ( dy > EPSILON && dy < len ) len = dy; + if ( dz > EPSILON && dz < len ) len = dz; + + if ( len == FLT_MAX ) + { + dx = dy = dz = 0.01f; // one centimeter + } + else + { + if ( dx < EPSILON ) dx = len * 0.05f; // 1/5th the shortest non-zero edge. + if ( dy < EPSILON ) dy = len * 0.05f; + if ( dz < EPSILON ) dz = len * 0.05f; + } + + float x1 = center[0] - dx; + float x2 = center[0] + dx; + + float y1 = center[1] - dy; + float y2 = center[1] + dy; + + float z1 = center[2] - dz; + float z2 = center[2] + dz; + + addPoint(vcount,vertices,x1,y1,z1); + addPoint(vcount,vertices,x2,y1,z1); + addPoint(vcount,vertices,x2,y2,z1); + addPoint(vcount,vertices,x1,y2,z1); + addPoint(vcount,vertices,x1,y1,z2); + addPoint(vcount,vertices,x2,y1,z2); + addPoint(vcount,vertices,x2,y2,z2); + addPoint(vcount,vertices,x1,y2,z2); + + return true; // return cube + + + } + else + { + if ( scale ) + { + scale[0] = dx; + scale[1] = dy; + scale[2] = dz; + + recip[0] = 1 / dx; + recip[1] = 1 / dy; + recip[2] = 1 / dz; + + center[0]*=recip[0]; + center[1]*=recip[1]; + center[2]*=recip[2]; + + } + + } + + + + vtx = (const char *) svertices; + + for (unsigned int i=0; i dist2 ) + { + v[0] = px; + v[1] = py; + v[2] = pz; + } + + break; + } + } + + if ( j == vcount ) + { + float *dest = &vertices[vcount*3]; + dest[0] = px; + dest[1] = py; + dest[2] = pz; + vcount++; + } + } + } + + // ok..now make sure we didn't prune so many vertices it is now invalid. + if ( 1 ) + { + float bmin[3] = { FLT_MAX, FLT_MAX, FLT_MAX }; + float bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX }; + + for (unsigned int i=0; i bmax[j] ) bmax[j] = p[j]; + } + } + + float dx = bmax[0] - bmin[0]; + float dy = bmax[1] - bmin[1]; + float dz = bmax[2] - bmin[2]; + + if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || vcount < 3) + { + float cx = dx*0.5f + bmin[0]; + float cy = dy*0.5f + bmin[1]; + float cz = dz*0.5f + bmin[2]; + + float len = FLT_MAX; + + if ( dx >= EPSILON && dx < len ) len = dx; + if ( dy >= EPSILON && dy < len ) len = dy; + if ( dz >= EPSILON && dz < len ) len = dz; + + if ( len == FLT_MAX ) + { + dx = dy = dz = 0.01f; // one centimeter + } + else + { + if ( dx < EPSILON ) dx = len * 0.05f; // 1/5th the shortest non-zero edge. + if ( dy < EPSILON ) dy = len * 0.05f; + if ( dz < EPSILON ) dz = len * 0.05f; + } + + float x1 = cx - dx; + float x2 = cx + dx; + + float y1 = cy - dy; + float y2 = cy + dy; + + float z1 = cz - dz; + float z2 = cz + dz; + + vcount = 0; // add box + + addPoint(vcount,vertices,x1,y1,z1); + addPoint(vcount,vertices,x2,y1,z1); + addPoint(vcount,vertices,x2,y2,z1); + addPoint(vcount,vertices,x1,y2,z1); + addPoint(vcount,vertices,x1,y1,z2); + addPoint(vcount,vertices,x2,y1,z2); + addPoint(vcount,vertices,x2,y2,z2); + addPoint(vcount,vertices,x1,y2,z2); + + return true; + } + } + + return true; +} + +void HullLibrary::BringOutYourDead(const float *verts,unsigned int vcount, float *overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount) +{ + unsigned int *used = (unsigned int *)malloc(sizeof(unsigned int)*vcount); + memset(used,0,sizeof(unsigned int)*vcount); + + ocount = 0; + + for (unsigned int i=0; i= 0 && v < vcount ); + + if ( used[v] ) // if already remapped + { + indices[i] = used[v]-1; // index to new array + } + else + { + + indices[i] = ocount; // new index mapping + + overts[ocount*3+0] = verts[v*3+0]; // copy old vert to new vert array + overts[ocount*3+1] = verts[v*3+1]; + overts[ocount*3+2] = verts[v*3+2]; + + ocount++; // increment output vert count + + assert( ocount >=0 && ocount <= vcount ); + + used[v] = ocount; // assign new index remapping + } + } + + free(used); +} + +} diff --git a/Extras/ConvexDecomposition/cd_hull.h b/Extras/ConvexDecomposition/cd_hull.h new file mode 100644 index 0000000..420e241 --- /dev/null +++ b/Extras/ConvexDecomposition/cd_hull.h @@ -0,0 +1,153 @@ +#ifndef CD_HULL_H + +#define CD_HULL_H + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +namespace ConvexDecomposition +{ + +class HullResult +{ +public: + HullResult(void) + { + mPolygons = true; + mNumOutputVertices = 0; + mOutputVertices = 0; + mNumFaces = 0; + mNumIndices = 0; + mIndices = 0; + } + bool mPolygons; // true if indices represents polygons, false indices are triangles + unsigned int mNumOutputVertices; // number of vertices in the output hull + float *mOutputVertices; // array of vertices, 3 floats each x,y,z + unsigned int mNumFaces; // the number of faces produced + unsigned int mNumIndices; // the total number of indices + unsigned int *mIndices; // pointer to indices. + +// If triangles, then indices are array indexes into the vertex list. +// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc.. +}; + +enum HullFlag +{ + QF_TRIANGLES = (1<<0), // report results as triangles, not polygons. + QF_REVERSE_ORDER = (1<<1), // reverse order of the triangle indices. + QF_SKIN_WIDTH = (1<<2), // extrude hull based on this skin width + QF_DEFAULT = 0 +}; + + +class HullDesc +{ +public: + HullDesc(void) + { + mFlags = QF_DEFAULT; + mVcount = 0; + mVertices = 0; + mVertexStride = sizeof(float)*3; + mNormalEpsilon = 0.001f; + mMaxVertices = 4096; // maximum number of points to be considered for a convex hull. + mMaxFaces = 4096; + mSkinWidth = 0.01f; // default is one centimeter + }; + + HullDesc(HullFlag flag, + unsigned int vcount, + const float *vertices, + unsigned int stride) + { + mFlags = flag; + mVcount = vcount; + mVertices = vertices; + mVertexStride = stride; + mNormalEpsilon = 0.001f; + mMaxVertices = 4096; + mSkinWidth = 0.01f; // default is one centimeter + } + + bool HasHullFlag(HullFlag flag) const + { + if ( mFlags & flag ) return true; + return false; + } + + void SetHullFlag(HullFlag flag) + { + mFlags|=flag; + } + + void ClearHullFlag(HullFlag flag) + { + mFlags&=~flag; + } + + unsigned int mFlags; // flags to use when generating the convex hull. + unsigned int mVcount; // number of vertices in the input point cloud + const float *mVertices; // the array of vertices. + unsigned int mVertexStride; // the stride of each vertex, in bytes. + float mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on. + float mSkinWidth; + unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull! + unsigned int mMaxFaces; +}; + +enum HullError +{ + QE_OK, // success! + QE_FAIL // failed. +}; + +class HullLibrary +{ +public: + + HullError CreateConvexHull(const HullDesc &desc, // describes the input request + HullResult &result); // contains the resulst + + HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it. + +private: + + void BringOutYourDead(const float *verts,unsigned int vcount, float *overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount); + + bool CleanupVertices(unsigned int svcount, + const float *svertices, + unsigned int stride, + unsigned int &vcount, // output number of vertices + float *vertices, // location to store the results. + float normalepsilon, + float *scale); +}; + +} + +#endif + diff --git a/Extras/ConvexDecomposition/cd_vector.h b/Extras/ConvexDecomposition/cd_vector.h new file mode 100644 index 0000000..bd1eff2 --- /dev/null +++ b/Extras/ConvexDecomposition/cd_vector.h @@ -0,0 +1,1185 @@ +#ifndef CD_VECTOR_H + +#define CD_VECTOR_H + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + + +#pragma warning(disable:4786) + +#include +#include +#include + +namespace ConvexDecomposition +{ + + +const float DEG_TO_RAD = ((2.0f * 3.14152654f) / 360.0f); +const float RAD_TO_DEG = (360.0f / (2.0f * 3.141592654f)); + +class Vector3d +{ +public: + Vector3d(void) { }; // null constructor, does not inialize point. + + Vector3d(const Vector3d &a) // constructor copies existing vector. + { + x = a.x; + y = a.y; + z = a.z; + }; + + Vector3d(float a,float b,float c) // construct with initial point. + { + x = a; + y = b; + z = c; + }; + + Vector3d(const float *t) + { + x = t[0]; + y = t[1]; + z = t[2]; + }; + + Vector3d(const int *t) + { + x = t[0]; + y = t[1]; + z = t[2]; + }; + + bool operator==(const Vector3d &a) const + { + return( a.x == x && a.y == y && a.z == z ); + }; + + bool operator!=(const Vector3d &a) const + { + return( a.x != x || a.y != y || a.z != z ); + }; + +// Operators + Vector3d& operator = (const Vector3d& A) // ASSIGNMENT (=) + { x=A.x; y=A.y; z=A.z; + return(*this); }; + + Vector3d operator + (const Vector3d& A) const // ADDITION (+) + { Vector3d Sum(x+A.x, y+A.y, z+A.z); + return(Sum); }; + + Vector3d operator - (const Vector3d& A) const // SUBTRACTION (-) + { Vector3d Diff(x-A.x, y-A.y, z-A.z); + return(Diff); }; + + Vector3d operator * (const float s) const // MULTIPLY BY SCALAR (*) + { Vector3d Scaled(x*s, y*s, z*s); + return(Scaled); }; + + + Vector3d operator + (const float s) const // ADD CONSTANT TO ALL 3 COMPONENTS (*) + { Vector3d Scaled(x+s, y+s, z+s); + return(Scaled); }; + + + + + Vector3d operator / (const float s) const // DIVIDE BY SCALAR (/) + { + float r = 1.0f / s; + Vector3d Scaled(x*r, y*r, z*r); + return(Scaled); + }; + + void operator /= (float A) // ACCUMULATED VECTOR ADDITION (/=) + { x/=A; y/=A; z/=A; }; + + void operator += (const Vector3d A) // ACCUMULATED VECTOR ADDITION (+=) + { x+=A.x; y+=A.y; z+=A.z; }; + void operator -= (const Vector3d A) // ACCUMULATED VECTOR SUBTRACTION (+=) + { x-=A.x; y-=A.y; z-=A.z; }; + void operator *= (const float s) // ACCUMULATED SCALAR MULTIPLICATION (*=) (bpc 4/24/2000) + {x*=s; y*=s; z*=s;} + + void operator += (const float A) // ACCUMULATED VECTOR ADDITION (+=) + { x+=A; y+=A; z+=A; }; + + + Vector3d operator - (void) const // NEGATION (-) + { Vector3d Negated(-x, -y, -z); + return(Negated); }; + + float operator [] (const int i) const // ALLOWS VECTOR ACCESS AS AN ARRAY. + { return( (i==0)?x:((i==1)?y:z) ); }; + float & operator [] (const int i) + { return( (i==0)?x:((i==1)?y:z) ); }; +// + + // accessor methods. + float GetX(void) const { return x; }; + float GetY(void) const { return y; }; + float GetZ(void) const { return z; }; + + float X(void) const { return x; }; + float Y(void) const { return y; }; + float Z(void) const { return z; }; + + void SetX(float t) { x = t; }; + void SetY(float t) { y = t; }; + void SetZ(float t) { z = t; }; + + bool IsSame(const Vector3d &v,float epsilon) const + { + float dx = fabsf( x - v.x ); + if ( dx > epsilon ) return false; + float dy = fabsf( y - v.y ); + if ( dy > epsilon ) return false; + float dz = fabsf( z - v.z ); + if ( dz > epsilon ) return false; + return true; + } + + + float ComputeNormal(const Vector3d &A, + const Vector3d &B, + const Vector3d &C) + { + float vx,vy,vz,wx,wy,wz,vw_x,vw_y,vw_z,mag; + + vx = (B.x - C.x); + vy = (B.y - C.y); + vz = (B.z - C.z); + + wx = (A.x - B.x); + wy = (A.y - B.y); + wz = (A.z - B.z); + + vw_x = vy * wz - vz * wy; + vw_y = vz * wx - vx * wz; + vw_z = vx * wy - vy * wx; + + mag = sqrtf((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z)); + + if ( mag < 0.000001f ) + { + mag = 0; + } + else + { + mag = 1.0f/mag; + } + + x = vw_x * mag; + y = vw_y * mag; + z = vw_z * mag; + + return mag; + } + + + void ScaleSumScale(float c0,float c1,const Vector3d &pos) + { + x = (x*c0) + (pos.x*c1); + y = (y*c0) + (pos.y*c1); + z = (z*c0) + (pos.z*c1); + } + + void SwapYZ(void) + { + float t = y; + y = z; + z = t; + }; + + void Get(float *v) const + { + v[0] = x; + v[1] = y; + v[2] = z; + }; + + void Set(const int *p) + { + x = (float) p[0]; + y = (float) p[1]; + z = (float) p[2]; + } + + void Set(const float *p) + { + x = (float) p[0]; + y = (float) p[1]; + z = (float) p[2]; + } + + + void Set(float a,float b,float c) + { + x = a; + y = b; + z = c; + }; + + void Zero(void) + { + x = y = z = 0; + }; + + const float* Ptr() const { return &x; } + float* Ptr() { return &x; } + + +// return -(*this). + Vector3d negative(void) const + { + Vector3d result; + result.x = -x; + result.y = -y; + result.z = -z; + return result; + } + + float Magnitude(void) const + { + return float(sqrt(x * x + y * y + z * z)); + }; + + float FastMagnitude(void) const + { + return float(sqrtf(x * x + y * y + z * z)); + }; + + float FasterMagnitude(void) const + { + return float(sqrtf(x * x + y * y + z * z)); + }; + + void Lerp(const Vector3d& from,const Vector3d& to,float slerp) + { + x = ((to.x - from.x) * slerp) + from.x; + y = ((to.y - from.y) * slerp) + from.y; + z = ((to.z - from.z) * slerp) + from.z; + }; + + // Highly specialized interpolate routine. Will compute the interpolated position + // shifted forward or backwards along the ray defined between (from) and (to). + // Reason for existance is so that when a bullet collides with a wall, for + // example, you can generate a graphic effect slightly *before* it hit the + // wall so that the effect doesn't sort into the wall itself. + void Interpolate(const Vector3d &from,const Vector3d &to,float offset) + { + x = to.x-from.x; + y = to.y-from.y; + z = to.z-from.z; + float d = sqrtf( x*x + y*y + z*z ); + float recip = 1.0f / d; + x*=recip; + y*=recip; + z*=recip; // normalize vector + d+=offset; // shift along ray + x = x*d + from.x; + y = y*d + from.y; + z = z*d + from.z; + }; + + bool BinaryEqual(const Vector3d &p) const + { + const int *source = (const int *) &x; + const int *dest = (const int *) &p.x; + + if ( source[0] == dest[0] && + source[1] == dest[1] && + source[2] == dest[2] ) return true; + + return false; + }; + + /*bool BinaryEqual(const Vector3d &p) const + { + if ( x == p.x && y == p.y && z == p.z ) return true; + return false; + } + */ + + + +/** Computes the reflection vector between two vectors.*/ + void Reflection(const Vector3d &a,const Vector3d &b)// compute reflection vector. + { + Vector3d c; + Vector3d d; + + float dot = a.Dot(b) * 2.0f; + + c = b * dot; + + d = c - a; + + x = -d.x; + y = -d.y; + z = -d.z; + }; + + void AngleAxis(float angle,const Vector3d& axis) + { + x = axis.x*angle; + y = axis.y*angle; + z = axis.z*angle; + }; + + float Length(void) const // length of vector. + { + return float(sqrt( x*x + y*y + z*z )); + }; + + + float ComputePlane(const Vector3d &A, + const Vector3d &B, + const Vector3d &C) + { + float vx,vy,vz,wx,wy,wz,vw_x,vw_y,vw_z,mag; + + vx = (B.x - C.x); + vy = (B.y - C.y); + vz = (B.z - C.z); + + wx = (A.x - B.x); + wy = (A.y - B.y); + wz = (A.z - B.z); + + vw_x = vy * wz - vz * wy; + vw_y = vz * wx - vx * wz; + vw_z = vx * wy - vy * wx; + + mag = sqrtf((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z)); + + if ( mag < 0.000001f ) + { + mag = 0; + } + else + { + mag = 1.0f/mag; + } + + x = vw_x * mag; + y = vw_y * mag; + z = vw_z * mag; + + + float D = 0.0f - ((x*A.x)+(y*A.y)+(z*A.z)); + + return D; + } + + + float FastLength(void) const // length of vector. + { + return float(sqrtf( x*x + y*y + z*z )); + }; + + + float FasterLength(void) const // length of vector. + { + return float(sqrtf( x*x + y*y + z*z )); + }; + + float Length2(void) const // squared distance, prior to square root. + { + float l2 = x*x+y*y+z*z; + return l2; + }; + + float Distance(const Vector3d &a) const // distance between two points. + { + Vector3d d(a.x-x,a.y-y,a.z-z); + return d.Length(); + } + + float FastDistance(const Vector3d &a) const // distance between two points. + { + Vector3d d(a.x-x,a.y-y,a.z-z); + return d.FastLength(); + } + + float FasterDistance(const Vector3d &a) const // distance between two points. + { + Vector3d d(a.x-x,a.y-y,a.z-z); + return d.FasterLength(); + } + + + float DistanceXY(const Vector3d &a) const + { + float dx = a.x - x; + float dy = a.y - y; + float dist = dx*dx + dy*dy; + return dist; + } + + float Distance2(const Vector3d &a) const // squared distance. + { + float dx = a.x - x; + float dy = a.y - y; + float dz = a.z - z; + return dx*dx + dy*dy + dz*dz; + }; + + float Partial(const Vector3d &p) const + { + return (x*p.y) - (p.x*y); + } + + float Area(const Vector3d &p1,const Vector3d &p2) const + { + float A = Partial(p1); + A+= p1.Partial(p2); + A+= p2.Partial(*this); + return A*0.5f; + } + + inline float Normalize(void) // normalize to a unit vector, returns distance. + { + float d = sqrtf( static_cast< float >( x*x + y*y + z*z ) ); + if ( d > 0 ) + { + float r = 1.0f / d; + x *= r; + y *= r; + z *= r; + } + else + { + x = y = z = 1; + } + return d; + }; + + inline float FastNormalize(void) // normalize to a unit vector, returns distance. + { + float d = sqrt( static_cast< float >( x*x + y*y + z*z ) ); + if ( d > 0 ) + { + float r = 1.0f / d; + x *= r; + y *= r; + z *= r; + } + else + { + x = y = z = 1; + } + return d; + }; + + inline float FasterNormalize(void) // normalize to a unit vector, returns distance. + { + float d = sqrtf( static_cast< float >( x*x + y*y + z*z ) ); + if ( d > 0 ) + { + float r = 1.0f / d; + x *= r; + y *= r; + z *= r; + } + else + { + x = y = z = 1; + } + return d; + }; + + + + + float Dot(const Vector3d &a) const // computes dot product. + { + return (x * a.x + y * a.y + z * a.z ); + }; + + + Vector3d Cross( const Vector3d& other ) const + { + Vector3d result( y*other.z - z*other.y, z*other.x - x*other.z, x*other.y - y*other.x ); + + return result; + } + + void Cross(const Vector3d &a,const Vector3d &b) // cross two vectors result in this one. + { + x = a.y*b.z - a.z*b.y; + y = a.z*b.x - a.x*b.z; + z = a.x*b.y - a.y*b.x; + }; + + /******************************************/ + // Check if next edge (b to c) turns inward + // + // Edge from a to b is already in face + // Edge from b to c is being considered for addition to face + /******************************************/ + bool Concave(const Vector3d& a,const Vector3d& b) + { + float vx,vy,vz,wx,wy,wz,vw_x,vw_y,vw_z,mag,nx,ny,nz,mag_a,mag_b; + + wx = b.x - a.x; + wy = b.y - a.y; + wz = b.z - a.z; + + mag_a = (float) sqrtf((wx * wx) + (wy * wy) + (wz * wz)); + + vx = x - b.x; + vy = y - b.y; + vz = z - b.z; + + mag_b = (float) sqrtf((vx * vx) + (vy * vy) + (vz * vz)); + + vw_x = (vy * wz) - (vz * wy); + vw_y = (vz * wx) - (vx * wz); + vw_z = (vx * wy) - (vy * wx); + + mag = (float) sqrtf((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z)); + + // Check magnitude of cross product, which is a sine function + // i.e., mag (a x b) = mag (a) * mag (b) * sin (theta); + // If sin (theta) small, then angle between edges is very close to + // 180, which we may want to call a concavity. Setting the + // CONCAVITY_TOLERANCE value greater than about 0.01 MAY cause + // face consolidation to get stuck on particular face. Most meshes + // convert properly with a value of 0.0 + + if (mag/(mag_a*mag_b) <= 0.0f ) return true; + + mag = 1.0f / mag; + + nx = vw_x * mag; + ny = vw_y * mag; + nz = vw_z * mag; + + // Dot product of tri normal with cross product result will + // yield positive number if edges are convex (+1.0 if two tris + // are coplanar), negative number if edges are concave (-1.0 if + // two tris are coplanar.) + + mag = ( x * nx) + ( y * ny) + ( z * nz); + + if (mag > 0.0f ) return false; + + return(true); + }; + + bool PointTestXY(const Vector3d &i,const Vector3d &j) const + { + if (((( i.y <= y ) && ( y < j.y )) || + (( j.y <= y ) && ( y < i.y ))) && + ( x < (j.x - i.x) * (y - i.y) / (j.y - i.y) + i.x)) return true; + return false; + } + + // test to see if this point is inside the triangle specified by + // these three points on the X/Y plane. + bool PointInTriXY(const Vector3d &p1, + const Vector3d &p2, + const Vector3d &p3) const + { + float ax = p3.x - p2.x; + float ay = p3.y - p2.y; + float bx = p1.x - p3.x; + float by = p1.y - p3.y; + float cx = p2.x - p1.x; + float cy = p2.y - p1.y; + float apx = x - p1.x; + float apy = y - p1.y; + float bpx = x - p2.x; + float bpy = y - p2.y; + float cpx = x - p3.x; + float cpy = y - p3.y; + + float aCROSSbp = ax*bpy - ay*bpx; + float cCROSSap = cx*apy - cy*apx; + float bCROSScp = bx*cpy - by*cpx; + + return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)); + }; + + // test to see if this point is inside the triangle specified by + // these three points on the X/Y plane. + bool PointInTriYZ(const Vector3d &p1, + const Vector3d &p2, + const Vector3d &p3) const + { + float ay = p3.y - p2.y; + float az = p3.z - p2.z; + float by = p1.y - p3.y; + float bz = p1.z - p3.z; + float cy = p2.y - p1.y; + float cz = p2.z - p1.z; + float apy = y - p1.y; + float apz = z - p1.z; + float bpy = y - p2.y; + float bpz = z - p2.z; + float cpy = y - p3.y; + float cpz = z - p3.z; + + float aCROSSbp = ay*bpz - az*bpy; + float cCROSSap = cy*apz - cz*apy; + float bCROSScp = by*cpz - bz*cpy; + + return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)); + }; + + + // test to see if this point is inside the triangle specified by + // these three points on the X/Y plane. + bool PointInTriXZ(const Vector3d &p1, + const Vector3d &p2, + const Vector3d &p3) const + { + float az = p3.z - p2.z; + float ax = p3.x - p2.x; + float bz = p1.z - p3.z; + float bx = p1.x - p3.x; + float cz = p2.z - p1.z; + float cx = p2.x - p1.x; + float apz = z - p1.z; + float apx = x - p1.x; + float bpz = z - p2.z; + float bpx = x - p2.x; + float cpz = z - p3.z; + float cpx = x - p3.x; + + float aCROSSbp = az*bpx - ax*bpz; + float cCROSSap = cz*apx - cx*apz; + float bCROSScp = bz*cpx - bx*cpz; + + return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)); + }; + + // Given a point and a line (defined by two points), compute the closest point + // in the line. (The line is treated as infinitely long.) + void NearestPointInLine(const Vector3d &point, + const Vector3d &line0, + const Vector3d &line1) + { + Vector3d &nearestPoint = *this; + Vector3d lineDelta = line1 - line0; + + // Handle degenerate lines + if ( lineDelta == Vector3d(0, 0, 0) ) + { + nearestPoint = line0; + } + else + { + float delta = (point-line0).Dot(lineDelta) / (lineDelta).Dot(lineDelta); + nearestPoint = line0 + lineDelta*delta; + } + } + + // Given a point and a line segment (defined by two points), compute the closest point + // in the line. Cap the point at the endpoints of the line segment. + void NearestPointInLineSegment(const Vector3d &point, + const Vector3d &line0, + const Vector3d &line1) + { + Vector3d &nearestPoint = *this; + Vector3d lineDelta = line1 - line0; + + // Handle degenerate lines + if ( lineDelta == Vector3d(0, 0, 0) ) + { + nearestPoint = line0; + } + else + { + float delta = (point-line0).Dot(lineDelta) / (lineDelta).Dot(lineDelta); + + // Clamp the point to conform to the segment's endpoints + if ( delta < 0 ) + delta = 0; + else if ( delta > 1 ) + delta = 1; + + nearestPoint = line0 + lineDelta*delta; + } + } + + // Given a point and a plane (defined by three points), compute the closest point + // in the plane. (The plane is unbounded.) + void NearestPointInPlane(const Vector3d &point, + const Vector3d &triangle0, + const Vector3d &triangle1, + const Vector3d &triangle2) + { + Vector3d &nearestPoint = *this; + Vector3d lineDelta0 = triangle1 - triangle0; + Vector3d lineDelta1 = triangle2 - triangle0; + Vector3d pointDelta = point - triangle0; + Vector3d normal; + + // Get the normal of the polygon (doesn't have to be a unit vector) + normal.Cross(lineDelta0, lineDelta1); + + float delta = normal.Dot(pointDelta) / normal.Dot(normal); + nearestPoint = point - normal*delta; + } + + // Given a point and a plane (defined by a coplanar point and a normal), compute the closest point + // in the plane. (The plane is unbounded.) + void NearestPointInPlane(const Vector3d &point, + const Vector3d &planePoint, + const Vector3d &planeNormal) + { + Vector3d &nearestPoint = *this; + Vector3d pointDelta = point - planePoint; + + float delta = planeNormal.Dot(pointDelta) / planeNormal.Dot(planeNormal); + nearestPoint = point - planeNormal*delta; + } + + // Given a point and a triangle (defined by three points), compute the closest point + // in the triangle. Clamp the point so it's confined to the area of the triangle. + void NearestPointInTriangle(const Vector3d &point, + const Vector3d &triangle0, + const Vector3d &triangle1, + const Vector3d &triangle2) + { + static const Vector3d zeroVector(0, 0, 0); + + Vector3d &nearestPoint = *this; + + Vector3d lineDelta0 = triangle1 - triangle0; + Vector3d lineDelta1 = triangle2 - triangle0; + + // Handle degenerate triangles + if ( (lineDelta0 == zeroVector) || (lineDelta1 == zeroVector) ) + { + nearestPoint.NearestPointInLineSegment(point, triangle1, triangle2); + } + else if ( lineDelta0 == lineDelta1 ) + { + nearestPoint.NearestPointInLineSegment(point, triangle0, triangle1); + } + + else + { + Vector3d axis[3]; + axis[0].NearestPointInLine(triangle0, triangle1, triangle2); + axis[1].NearestPointInLine(triangle1, triangle0, triangle2); + axis[2].NearestPointInLine(triangle2, triangle0, triangle1); + + float axisDot[3]; + axisDot[0] = (triangle0-axis[0]).Dot(point-axis[0]); + axisDot[1] = (triangle1-axis[1]).Dot(point-axis[1]); + axisDot[2] = (triangle2-axis[2]).Dot(point-axis[2]); + + bool bForce = true; + float bestMagnitude2 = 0; + float closeMagnitude2; + Vector3d closePoint; + + if ( axisDot[0] < 0 ) + { + closePoint.NearestPointInLineSegment(point, triangle1, triangle2); + closeMagnitude2 = point.Distance2(closePoint); + if ( bForce || (bestMagnitude2 > closeMagnitude2) ) + { + bForce = false; + bestMagnitude2 = closeMagnitude2; + nearestPoint = closePoint; + } + } + if ( axisDot[1] < 0 ) + { + closePoint.NearestPointInLineSegment(point, triangle0, triangle2); + closeMagnitude2 = point.Distance2(closePoint); + if ( bForce || (bestMagnitude2 > closeMagnitude2) ) + { + bForce = false; + bestMagnitude2 = closeMagnitude2; + nearestPoint = closePoint; + } + } + if ( axisDot[2] < 0 ) + { + closePoint.NearestPointInLineSegment(point, triangle0, triangle1); + closeMagnitude2 = point.Distance2(closePoint); + if ( bForce || (bestMagnitude2 > closeMagnitude2) ) + { + bForce = false; + bestMagnitude2 = closeMagnitude2; + nearestPoint = closePoint; + } + } + + // If bForce is true at this point, it means the nearest point lies + // inside the triangle; use the nearest-point-on-a-plane equation + if ( bForce ) + { + Vector3d normal; + + // Get the normal of the polygon (doesn't have to be a unit vector) + normal.Cross(lineDelta0, lineDelta1); + + Vector3d pointDelta = point - triangle0; + float delta = normal.Dot(pointDelta) / normal.Dot(normal); + + nearestPoint = point - normal*delta; + } + } + } + + +//private: + + float x; + float y; + float z; +}; + + +class Vector2d +{ +public: + Vector2d(void) { }; // null constructor, does not inialize point. + + Vector2d(const Vector2d &a) // constructor copies existing vector. + { + x = a.x; + y = a.y; + }; + + Vector2d(const float *t) + { + x = t[0]; + y = t[1]; + }; + + + Vector2d(float a,float b) // construct with initial point. + { + x = a; + y = b; + }; + + const float* Ptr() const { return &x; } + float* Ptr() { return &x; } + + Vector2d & operator+=(const Vector2d &a) // += operator. + { + x+=a.x; + y+=a.y; + return *this; + }; + + Vector2d & operator-=(const Vector2d &a) + { + x-=a.x; + y-=a.y; + return *this; + }; + + Vector2d & operator*=(const Vector2d &a) + { + x*=a.x; + y*=a.y; + return *this; + }; + + Vector2d & operator/=(const Vector2d &a) + { + x/=a.x; + y/=a.y; + return *this; + }; + + bool operator==(const Vector2d &a) const + { + if ( a.x == x && a.y == y ) return true; + return false; + }; + + bool operator!=(const Vector2d &a) const + { + if ( a.x != x || a.y != y ) return true; + return false; + }; + + Vector2d operator+(Vector2d a) const + { + a.x+=x; + a.y+=y; + return a; + }; + + Vector2d operator-(Vector2d a) const + { + a.x = x-a.x; + a.y = y-a.y; + return a; + }; + + Vector2d operator - (void) const + { + return negative(); + }; + + Vector2d operator*(Vector2d a) const + { + a.x*=x; + a.y*=y; + return a; + }; + + Vector2d operator*(float c) const + { + Vector2d a; + + a.x = x * c; + a.y = y * c; + + return a; + }; + + Vector2d operator/(Vector2d a) const + { + a.x = x/a.x; + a.y = y/a.y; + return a; + }; + + + float Dot(const Vector2d &a) const // computes dot product. + { + return (x * a.x + y * a.y ); + }; + + float GetX(void) const { return x; }; + float GetY(void) const { return y; }; + + void SetX(float t) { x = t; }; + void SetY(float t) { y = t; }; + + void Set(float a,float b) + { + x = a; + y = b; + }; + + void Zero(void) + { + x = y = 0; + }; + + Vector2d negative(void) const + { + Vector2d result; + result.x = -x; + result.y = -y; + return result; + } + + float magnitude(void) const + { + return (float) sqrtf(x * x + y * y ); + } + + float fastmagnitude(void) const + { + return (float) sqrtf(x * x + y * y ); + } + + float fastermagnitude(void) const + { + return (float) sqrtf( x * x + y * y ); + } + + void Reflection(Vector2d &a,Vector2d &b); // compute reflection vector. + + float Length(void) const // length of vector. + { + return float(sqrtf( x*x + y*y )); + }; + + float FastLength(void) const // length of vector. + { + return float(sqrtf( x*x + y*y )); + }; + + float FasterLength(void) const // length of vector. + { + return float(sqrtf( x*x + y*y )); + }; + + float Length2(void) // squared distance, prior to square root. + { + return x*x+y*y; + } + + float Distance(const Vector2d &a) const // distance between two points. + { + float dx = a.x - x; + float dy = a.y - y; + float d = dx*dx+dy*dy; + return sqrtf(d); + }; + + float FastDistance(const Vector2d &a) const // distance between two points. + { + float dx = a.x - x; + float dy = a.y - y; + float d = dx*dx+dy*dy; + return sqrtf(d); + }; + + float FasterDistance(const Vector2d &a) const // distance between two points. + { + float dx = a.x - x; + float dy = a.y - y; + float d = dx*dx+dy*dy; + return sqrtf(d); + }; + + float Distance2(Vector2d &a) // squared distance. + { + float dx = a.x - x; + float dy = a.y - y; + return dx*dx + dy *dy; + }; + + void Lerp(const Vector2d& from,const Vector2d& to,float slerp) + { + x = ((to.x - from.x)*slerp) + from.x; + y = ((to.y - from.y)*slerp) + from.y; + }; + + + void Cross(const Vector2d &a,const Vector2d &b) // cross two vectors result in this one. + { + x = a.y*b.x - a.x*b.y; + y = a.x*b.x - a.x*b.x; + }; + + float Normalize(void) // normalize to a unit vector, returns distance. + { + float l = Length(); + if ( l != 0 ) + { + l = float( 1 ) / l; + x*=l; + y*=l; + } + else + { + x = y = 0; + } + return l; + }; + + float FastNormalize(void) // normalize to a unit vector, returns distance. + { + float l = FastLength(); + if ( l != 0 ) + { + l = float( 1 ) / l; + x*=l; + y*=l; + } + else + { + x = y = 0; + } + return l; + }; + + float FasterNormalize(void) // normalize to a unit vector, returns distance. + { + float l = FasterLength(); + if ( l != 0 ) + { + l = float( 1 ) / l; + x*=l; + y*=l; + } + else + { + x = y = 0; + } + return l; + }; + + + float x; + float y; +}; + +class Line +{ +public: + Line(const Vector3d &from,const Vector3d &to) + { + mP1 = from; + mP2 = to; + }; + // JWR Test for the intersection of two lines. + + bool Intersect(const Line& src,Vector3d §); +private: + Vector3d mP1; + Vector3d mP2; + +}; + + +typedef std::vector< Vector3d > Vector3dVector; +typedef std::vector< Vector2d > Vector2dVector; + +inline Vector3d operator * (float s, const Vector3d &v ) +{ + Vector3d Scaled(v.x*s, v.y*s, v.z*s); + return(Scaled); +} + +inline Vector2d operator * (float s, const Vector2d &v ) + { + Vector2d Scaled(v.x*s, v.y*s); + return(Scaled); + } + +} + +#endif diff --git a/Extras/ConvexDecomposition/cd_wavefront.cpp b/Extras/ConvexDecomposition/cd_wavefront.cpp new file mode 100644 index 0000000..54e8bdf --- /dev/null +++ b/Extras/ConvexDecomposition/cd_wavefront.cpp @@ -0,0 +1,860 @@ +#include +#include +#include +#include +#include + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// +#include "float_math.h" + +#include "cd_wavefront.h" + + +using namespace ConvexDecomposition; + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-----------------------------------------------------------------------*/ + +#include + +namespace ConvexDecomposition +{ + +typedef std::vector< int > IntVector; +typedef std::vector< float > FloatVector; + +#if defined(__APPLE__) || defined(__CELLOS_LV2__) +#define stricmp(a, b) strcasecmp((a), (b)) +#endif + +/*******************************************************************/ +/******************** InParser.h ********************************/ +/*******************************************************************/ +class InPlaceParserInterface +{ +public: + virtual ~InPlaceParserInterface () {} ; + + virtual int ParseLine(int lineno,int argc,const char **argv) =0; // return TRUE to continue parsing, return FALSE to abort parsing process +}; + +enum SeparatorType +{ + ST_DATA, // is data + ST_HARD, // is a hard separator + ST_SOFT, // is a soft separator + ST_EOS // is a comment symbol, and everything past this character should be ignored +}; + +class InPlaceParser +{ +public: + InPlaceParser(void) + { + Init(); + } + + InPlaceParser(char *data,int len) + { + Init(); + SetSourceData(data,len); + } + + InPlaceParser(const char *fname) + { + Init(); + SetFile(fname); + } + + ~InPlaceParser(void); + + void Init(void) + { + mQuoteChar = 34; + mData = 0; + mLen = 0; + mMyAlloc = false; + for (int i=0; i<256; i++) + { + mHard[i] = ST_DATA; + mHardString[i*2] = i; + mHardString[i*2+1] = 0; + } + mHard[0] = ST_EOS; + mHard[32] = ST_SOFT; + mHard[9] = ST_SOFT; + mHard[13] = ST_SOFT; + mHard[10] = ST_SOFT; + } + + void SetFile(const char *fname); // use this file as source data to parse. + + void SetSourceData(char *data,int len) + { + mData = data; + mLen = len; + mMyAlloc = false; + }; + + int Parse(InPlaceParserInterface *callback); // returns true if entire file was parsed, false if it aborted for some reason + + int ProcessLine(int lineno,char *line,InPlaceParserInterface *callback); + + const char ** GetArglist(char *source,int &count); // convert source string into an arg list, this is a destructive parse. + + void SetHardSeparator(char c) // add a hard separator + { + mHard[(int)c] = ST_HARD; + } + + void SetHard(char c) // add a hard separator + { + mHard[(int)c] = ST_HARD; + } + + + void SetCommentSymbol(char c) // comment character, treated as 'end of string' + { + mHard[(int)c] = ST_EOS; + } + + void ClearHardSeparator(char c) + { + mHard[(int)c] = ST_DATA; + } + + + void DefaultSymbols(void); // set up default symbols for hard seperator and comment symbol of the '#' character. + + bool EOS(char c) + { + if ( mHard[(int)c] == ST_EOS ) + { + return true; + } + return false; + } + + void SetQuoteChar(char c) + { + mQuoteChar = c; + } + +private: + + + inline char * AddHard(int &argc,const char **argv,char *foo); + inline bool IsHard(char c); + inline char * SkipSpaces(char *foo); + inline bool IsWhiteSpace(char c); + inline bool IsNonSeparator(char c); // non seperator,neither hard nor soft + + bool mMyAlloc; // whether or not *I* allocated the buffer and am responsible for deleting it. + char *mData; // ascii data to parse. + int mLen; // length of data + SeparatorType mHard[256]; + char mHardString[256*2]; + char mQuoteChar; +}; + +/*******************************************************************/ +/******************** InParser.cpp ********************************/ +/*******************************************************************/ +void InPlaceParser::SetFile(const char *fname) +{ + if ( mMyAlloc ) + { + free(mData); + } + mData = 0; + mLen = 0; + mMyAlloc = false; + + + FILE *fph = fopen(fname,"rb"); + if ( fph ) + { + fseek(fph,0L,SEEK_END); + mLen = ftell(fph); + fseek(fph,0L,SEEK_SET); + if ( mLen ) + { + mData = (char *) malloc(sizeof(char)*(mLen+1)); + int ok = fread(mData, mLen, 1, fph); + if ( !ok ) + { + free(mData); + mData = 0; + } + else + { + mData[mLen] = 0; // zero byte terminate end of file marker. + mMyAlloc = true; + } + } + fclose(fph); + } +} + +InPlaceParser::~InPlaceParser(void) +{ + if ( mMyAlloc ) + { + free(mData); + } +} + +#define MAXARGS 512 + +bool InPlaceParser::IsHard(char c) +{ + return mHard[(int)c] == ST_HARD; +} + +char * InPlaceParser::AddHard(int &argc,const char **argv,char *foo) +{ + while ( IsHard(*foo) ) + { + const char *hard = &mHardString[*foo*2]; + if ( argc < MAXARGS ) + { + argv[argc++] = hard; + } + foo++; + } + return foo; +} + +bool InPlaceParser::IsWhiteSpace(char c) +{ + return mHard[(int)c] == ST_SOFT; +} + +char * InPlaceParser::SkipSpaces(char *foo) +{ + while ( !EOS(*foo) && IsWhiteSpace(*foo) ) foo++; + return foo; +} + +bool InPlaceParser::IsNonSeparator(char c) +{ + if ( !IsHard(c) && !IsWhiteSpace(c) && c != 0 ) return true; + return false; +} + + +int InPlaceParser::ProcessLine(int lineno,char *line,InPlaceParserInterface *callback) +{ + int ret = 0; + + const char *argv[MAXARGS]; + int argc = 0; + + char *foo = line; + + while ( !EOS(*foo) && argc < MAXARGS ) + { + + foo = SkipSpaces(foo); // skip any leading spaces + + if ( EOS(*foo) ) break; + + if ( *foo == mQuoteChar ) // if it is an open quote + { + foo++; + if ( argc < MAXARGS ) + { + argv[argc++] = foo; + } + while ( !EOS(*foo) && *foo != mQuoteChar ) foo++; + if ( !EOS(*foo) ) + { + *foo = 0; // replace close quote with zero byte EOS + foo++; + } + } + else + { + + foo = AddHard(argc,argv,foo); // add any hard separators, skip any spaces + + if ( IsNonSeparator(*foo) ) // add non-hard argument. + { + bool quote = false; + if ( *foo == mQuoteChar ) + { + foo++; + quote = true; + } + + if ( argc < MAXARGS ) + { + argv[argc++] = foo; + } + + if ( quote ) + { + while (*foo && *foo != mQuoteChar ) foo++; + if ( *foo ) *foo = 32; + } + + // continue..until we hit an eos .. + while ( !EOS(*foo) ) // until we hit EOS + { + if ( IsWhiteSpace(*foo) ) // if we hit a space, stomp a zero byte, and exit + { + *foo = 0; + foo++; + break; + } + else if ( IsHard(*foo) ) // if we hit a hard separator, stomp a zero byte and store the hard separator argument + { + const char *hard = &mHardString[*foo*2]; + *foo = 0; + if ( argc < MAXARGS ) + { + argv[argc++] = hard; + } + foo++; + break; + } + foo++; + } // end of while loop... + } + } + } + + if ( argc ) + { + ret = callback->ParseLine(lineno, argc, argv ); + } + + return ret; +} + +int InPlaceParser::Parse(InPlaceParserInterface *callback) // returns true if entire file was parsed, false if it aborted for some reason +{ + assert( callback ); + if ( !mData ) return 0; + + int ret = 0; + + int lineno = 0; + + char *foo = mData; + char *begin = foo; + + + while ( *foo ) + { + if ( *foo == 10 || *foo == 13 ) + { + lineno++; + *foo = 0; + + if ( *begin ) // if there is any data to parse at all... + { + int v = ProcessLine(lineno,begin,callback); + if ( v ) ret = v; + } + + foo++; + if ( *foo == 10 ) foo++; // skip line feed, if it is in the carraige-return line-feed format... + begin = foo; + } + else + { + foo++; + } + } + + lineno++; // lasst line. + + int v = ProcessLine(lineno,begin,callback); + if ( v ) ret = v; + return ret; +} + + +void InPlaceParser::DefaultSymbols(void) +{ + SetHardSeparator(','); + SetHardSeparator('('); + SetHardSeparator(')'); + SetHardSeparator('='); + SetHardSeparator('['); + SetHardSeparator(']'); + SetHardSeparator('{'); + SetHardSeparator('}'); + SetCommentSymbol('#'); +} + + +const char ** InPlaceParser::GetArglist(char *line,int &count) // convert source string into an arg list, this is a destructive parse. +{ + const char **ret = 0; + + const char *argv[MAXARGS]; + int argc = 0; + + char *foo = line; + + while ( !EOS(*foo) && argc < MAXARGS ) + { + + foo = SkipSpaces(foo); // skip any leading spaces + + if ( EOS(*foo) ) break; + + if ( *foo == mQuoteChar ) // if it is an open quote + { + foo++; + if ( argc < MAXARGS ) + { + argv[argc++] = foo; + } + while ( !EOS(*foo) && *foo != mQuoteChar ) foo++; + if ( !EOS(*foo) ) + { + *foo = 0; // replace close quote with zero byte EOS + foo++; + } + } + else + { + + foo = AddHard(argc,argv,foo); // add any hard separators, skip any spaces + + if ( IsNonSeparator(*foo) ) // add non-hard argument. + { + bool quote = false; + if ( *foo == mQuoteChar ) + { + foo++; + quote = true; + } + + if ( argc < MAXARGS ) + { + argv[argc++] = foo; + } + + if ( quote ) + { + while (*foo && *foo != mQuoteChar ) foo++; + if ( *foo ) *foo = 32; + } + + // continue..until we hit an eos .. + while ( !EOS(*foo) ) // until we hit EOS + { + if ( IsWhiteSpace(*foo) ) // if we hit a space, stomp a zero byte, and exit + { + *foo = 0; + foo++; + break; + } + else if ( IsHard(*foo) ) // if we hit a hard separator, stomp a zero byte and store the hard separator argument + { + const char *hard = &mHardString[*foo*2]; + *foo = 0; + if ( argc < MAXARGS ) + { + argv[argc++] = hard; + } + foo++; + break; + } + foo++; + } // end of while loop... + } + } + } + + count = argc; + if ( argc ) + { + ret = argv; + } + + return ret; +} + +/*******************************************************************/ +/******************** Geometry.h ********************************/ +/*******************************************************************/ + +class GeometryVertex +{ +public: + float mPos[3]; + float mNormal[3]; + float mTexel[2]; +}; + + +class GeometryInterface +{ +public: + + virtual void NodeTriangle(const GeometryVertex *v1,const GeometryVertex *v2,const GeometryVertex *v3) {} + + virtual ~GeometryInterface () {} +}; + + +/*******************************************************************/ +/******************** Obj.h ********************************/ +/*******************************************************************/ + + +class OBJ : public InPlaceParserInterface +{ +public: + int LoadMesh(const char *fname,GeometryInterface *callback); + int ParseLine(int lineno,int argc,const char **argv); // return TRUE to continue parsing, return FALSE to abort parsing process +private: + + void getVertex(GeometryVertex &v,const char *face) const; + + FloatVector mVerts; + FloatVector mTexels; + FloatVector mNormals; + + GeometryInterface *mCallback; +}; + + +/*******************************************************************/ +/******************** Obj.cpp ********************************/ +/*******************************************************************/ + +int OBJ::LoadMesh(const char *fname,GeometryInterface *iface) +{ + int ret = 0; + + mVerts.clear(); + mTexels.clear(); + mNormals.clear(); + + mCallback = iface; + + InPlaceParser ipp(fname); + + ipp.Parse(this); + + + return ret; +} + +//static const char * GetArg(const char **argv,int i,int argc) +//{ + // const char * ret = 0; + // if ( i < argc ) ret = argv[i]; + // return ret; +//} + +void OBJ::getVertex(GeometryVertex &v,const char *face) const +{ + v.mPos[0] = 0; + v.mPos[1] = 0; + v.mPos[2] = 0; + + v.mTexel[0] = 0; + v.mTexel[1] = 0; + + v.mNormal[0] = 0; + v.mNormal[1] = 1; + v.mNormal[2] = 0; + + int index = atoi( face )-1; + + const char *texel = strstr(face,"/"); + + if ( texel ) + { + int tindex = atoi( texel+1) - 1; + + if ( tindex >=0 && tindex < (int)(mTexels.size()/2) ) + { + const float *t = &mTexels[tindex*2]; + + v.mTexel[0] = t[0]; + v.mTexel[1] = t[1]; + + } + + const char *normal = strstr(texel+1,"/"); + if ( normal ) + { + int nindex = atoi( normal+1 ) - 1; + + if (nindex >= 0 && nindex < (int)(mNormals.size()/3) ) + { + const float *n = &mNormals[nindex*3]; + + v.mNormal[0] = n[0]; + v.mNormal[1] = n[1]; + v.mNormal[2] = n[2]; + } + } + } + + if ( index >= 0 && index < (int)(mVerts.size()/3) ) + { + + const float *p = &mVerts[index*3]; + + v.mPos[0] = p[0]; + v.mPos[1] = p[1]; + v.mPos[2] = p[2]; + } + +} + +int OBJ::ParseLine(int lineno,int argc,const char **argv) // return TRUE to continue parsing, return FALSE to abort parsing process +{ + int ret = 0; + + if ( argc >= 1 ) + { + const char *foo = argv[0]; + if ( *foo != '#' ) + { + if ( strcmp(argv[0],"v") == 0 && argc == 4 ) + + //if ( stricmp(argv[0],"v") == 0 && argc == 4 ) + { + float vx = (float) atof( argv[1] ); + float vy = (float) atof( argv[2] ); + float vz = (float) atof( argv[3] ); + mVerts.push_back(vx); + mVerts.push_back(vy); + mVerts.push_back(vz); + } + else if ( strcmp(argv[0],"vt") == 0 && argc == 3 ) + + // else if ( stricmp(argv[0],"vt") == 0 && argc == 3 ) + { + float tx = (float) atof( argv[1] ); + float ty = (float) atof( argv[2] ); + mTexels.push_back(tx); + mTexels.push_back(ty); + } + // else if ( stricmp(argv[0],"vn") == 0 && argc == 4 ) + + else if ( strcmp(argv[0],"vn") == 0 && argc == 4 ) + { + float normalx = (float) atof(argv[1]); + float normaly = (float) atof(argv[2]); + float normalz = (float) atof(argv[3]); + mNormals.push_back(normalx); + mNormals.push_back(normaly); + mNormals.push_back(normalz); + } +// else if ( stricmp(argv[0],"f") == 0 && argc >= 4 ) + + else if ( strcmp(argv[0],"f") == 0 && argc >= 4 ) + { + GeometryVertex v[32]; + + int vcount = argc-1; + + for (int i=1; i p1( v[0].mPos ); + Vector3d p2( v[1].mPos ); + Vector3d p3( v[2].mPos ); + + Vector3d n; + n.ComputeNormal(p3,p2,p1); + + for (int i=0; iNodeTriangle(&v[0],&v[1],&v[2]); + + if ( vcount >=3 ) // do the fan + { + for (int i=2; i<(vcount-1); i++) + { + mCallback->NodeTriangle(&v[0],&v[i],&v[i+1]); + } + } + + } + } + } + + return ret; +} + + + + +class BuildMesh : public GeometryInterface +{ +public: + + int getIndex(const float *p) + { + + int vcount = mVertices.size()/3; + + if(vcount>0) + { + //New MS STL library checks indices in debug build, so zero causes an assert if it is empty. + const float *v = &mVertices[0]; + + for (int i=0; imPos) ); + mIndices.push_back( getIndex(v2->mPos) ); + mIndices.push_back( getIndex(v3->mPos) ); + } + + const FloatVector& GetVertices(void) const { return mVertices; }; + const IntVector& GetIndices(void) const { return mIndices; }; + +private: + FloatVector mVertices; + IntVector mIndices; +}; + + +WavefrontObj::WavefrontObj(void) +{ + mVertexCount = 0; + mTriCount = 0; + mIndices = 0; + mVertices = 0; +} + +WavefrontObj::~WavefrontObj(void) +{ + delete [] mIndices; + delete [] mVertices; +} + +unsigned int WavefrontObj::loadObj(const char *fname) // load a wavefront obj returns number of triangles that were loaded. Data is persists until the class is destructed. +{ + + unsigned int ret = 0; + + delete [] mVertices; + mVertices = 0; + delete [] mIndices; + mIndices = 0; + mVertexCount = 0; + mTriCount = 0; + + + BuildMesh bm; + + OBJ obj; + + obj.LoadMesh(fname,&bm); + + + const FloatVector &vlist = bm.GetVertices(); + const IntVector &indices = bm.GetIndices(); + if ( vlist.size() ) + { + mVertexCount = vlist.size()/3; + mVertices = new float[mVertexCount*3]; + memcpy( mVertices, &vlist[0], sizeof(float)*mVertexCount*3 ); + mTriCount = indices.size()/3; + mIndices = new int[mTriCount*3*sizeof(int)]; + memcpy(mIndices, &indices[0], sizeof(int)*mTriCount*3); + ret = mTriCount; + } + + + return ret; +} + +} diff --git a/Extras/ConvexDecomposition/cd_wavefront.h b/Extras/ConvexDecomposition/cd_wavefront.h new file mode 100644 index 0000000..ba5f90b --- /dev/null +++ b/Extras/ConvexDecomposition/cd_wavefront.h @@ -0,0 +1,62 @@ +#ifndef CD_WAVEFRONT_OBJ_H + + +#define CD_WAVEFRONT_OBJ_H + + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + + +namespace ConvexDecomposition +{ + +class WavefrontObj +{ +public: + + WavefrontObj(void); + ~WavefrontObj(void); + + unsigned int loadObj(const char *fname); // load a wavefront obj returns number of triangles that were loaded. Data is persists until the class is destructed. + + int mVertexCount; + int mTriCount; + int *mIndices; + float *mVertices; +}; + +} + +#endif diff --git a/Extras/ConvexDecomposition/concavity.cpp b/Extras/ConvexDecomposition/concavity.cpp new file mode 100644 index 0000000..f1a4660 --- /dev/null +++ b/Extras/ConvexDecomposition/concavity.cpp @@ -0,0 +1,795 @@ +#include "float_math.h" +#include +#include +#include +#include + +#include + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + +#include "concavity.h" +#include "raytri.h" +#include "bestfit.h" +#include "cd_hull.h" +#include "meshvolume.h" +#include "cd_vector.h" +#include "splitplane.h" +#include "ConvexDecomposition.h" + + +#define WSCALE 4 +#define CONCAVE_THRESH 0.05f + +namespace ConvexDecomposition +{ + +unsigned int getDebugColor(void) +{ + static unsigned int colors[8] = + { + 0xFF0000, + 0x00FF00, + 0x0000FF, + 0xFFFF00, + 0x00FFFF, + 0xFF00FF, + 0xFFFFFF, + 0xFF8040 + }; + + static int count = 0; + + count++; + + if ( count == 8 ) count = 0; + + assert( count >= 0 && count < 8 ); + + unsigned int color = colors[count]; + + return color; + +} + +class Wpoint +{ +public: + Wpoint(const Vector3d &p,float w) + { + mPoint = p; + mWeight = w; + } + + Vector3d mPoint; + float mWeight; +}; + +typedef std::vector< Wpoint > WpointVector; + + +static inline float DistToPt(const float *p,const float *plane) +{ + float x = p[0]; + float y = p[1]; + float z = p[2]; + float d = x*plane[0] + y*plane[1] + z*plane[2] + plane[3]; + return d; +} + + +static void intersect(const float *p1,const float *p2,float *split,const float *plane) +{ + + float dp1 = DistToPt(p1,plane); + + float dir[3]; + + dir[0] = p2[0] - p1[0]; + dir[1] = p2[1] - p1[1]; + dir[2] = p2[2] - p1[2]; + + float dot1 = dir[0]*plane[0] + dir[1]*plane[1] + dir[2]*plane[2]; + float dot2 = dp1 - plane[3]; + + float t = -(plane[3] + dot2 ) / dot1; + + split[0] = (dir[0]*t)+p1[0]; + split[1] = (dir[1]*t)+p1[1]; + split[2] = (dir[2]*t)+p1[2]; +} + + +class CTri +{ +public: + CTri(void) { }; + + CTri(const float *p1,const float *p2,const float *p3,unsigned int i1,unsigned int i2,unsigned int i3) + { + mProcessed = 0; + mI1 = i1; + mI2 = i2; + mI3 = i3; + + mP1.Set(p1); + mP2.Set(p2); + mP3.Set(p3); + + mPlaneD = mNormal.ComputePlane(mP1,mP2,mP3); + } + + float Facing(const CTri &t) + { + float d = mNormal.Dot(t.mNormal); + return d; + } + + // clip this line segment against this triangle. + bool clip(const Vector3d &start,Vector3d &end) const + { + Vector3d sect; + + bool hit = lineIntersectsTriangle(start.Ptr(), end.Ptr(), mP1.Ptr(), mP2.Ptr(), mP3.Ptr(), sect.Ptr() ); + + if ( hit ) + { + end = sect; + } + return hit; + } + + bool Concave(const Vector3d &p,float &distance,Vector3d &n) const + { + n.NearestPointInTriangle(p,mP1,mP2,mP3); + distance = p.Distance(n); + return true; + } + + void addTri(unsigned int *indices,unsigned int i1,unsigned int i2,unsigned int i3,unsigned int &tcount) const + { + indices[tcount*3+0] = i1; + indices[tcount*3+1] = i2; + indices[tcount*3+2] = i3; + tcount++; + } + + float getVolume(ConvexDecompInterface *callback) const + { + unsigned int indices[8*3]; + + + unsigned int tcount = 0; + + addTri(indices,0,1,2,tcount); + addTri(indices,3,4,5,tcount); + + addTri(indices,0,3,4,tcount); + addTri(indices,0,4,1,tcount); + + addTri(indices,1,4,5,tcount); + addTri(indices,1,5,2,tcount); + + addTri(indices,0,3,5,tcount); + addTri(indices,0,5,2,tcount); + + const float *vertices = mP1.Ptr(); + + if ( callback ) + { + unsigned int color = getDebugColor(); + +#if 0 + Vector3d d1 = mNear1; + Vector3d d2 = mNear2; + Vector3d d3 = mNear3; + + callback->ConvexDebugPoint(mP1.Ptr(),0.01f,0x00FF00); + callback->ConvexDebugPoint(mP2.Ptr(),0.01f,0x00FF00); + callback->ConvexDebugPoint(mP3.Ptr(),0.01f,0x00FF00); + callback->ConvexDebugPoint(d1.Ptr(),0.01f,0xFF0000); + callback->ConvexDebugPoint(d2.Ptr(),0.01f,0xFF0000); + callback->ConvexDebugPoint(d3.Ptr(),0.01f,0xFF0000); + + callback->ConvexDebugTri(mP1.Ptr(), d1.Ptr(), d1.Ptr(),0x00FF00); + callback->ConvexDebugTri(mP2.Ptr(), d2.Ptr(), d2.Ptr(),0x00FF00); + callback->ConvexDebugTri(mP3.Ptr(), d3.Ptr(), d3.Ptr(),0x00FF00); + +#else + for (unsigned int i=0; iConvexDebugTri(p1,p2,p3,color); + + } +#endif + } + + float v = computeMeshVolume(mP1.Ptr(), tcount, indices ); + + return v; + + } + + float raySect(const Vector3d &p,const Vector3d &dir,Vector3d §) const + { + float plane[4]; + + plane[0] = mNormal.x; + plane[1] = mNormal.y; + plane[2] = mNormal.z; + plane[3] = mPlaneD; + + Vector3d dest = p+dir*100000; + + intersect( p.Ptr(), dest.Ptr(), sect.Ptr(), plane ); + + return sect.Distance(p); // return the intersection distance. + + } + + float planeDistance(const Vector3d &p) const + { + float plane[4]; + + plane[0] = mNormal.x; + plane[1] = mNormal.y; + plane[2] = mNormal.z; + plane[3] = mPlaneD; + + return DistToPt( p.Ptr(), plane ); + + } + + bool samePlane(const CTri &t) const + { + const float THRESH = 0.001f; + float dd = fabsf( t.mPlaneD - mPlaneD ); + if ( dd > THRESH ) return false; + dd = fabsf( t.mNormal.x - mNormal.x ); + if ( dd > THRESH ) return false; + dd = fabsf( t.mNormal.y - mNormal.y ); + if ( dd > THRESH ) return false; + dd = fabsf( t.mNormal.z - mNormal.z ); + if ( dd > THRESH ) return false; + return true; + } + + bool hasIndex(unsigned int i) const + { + if ( i == mI1 || i == mI2 || i == mI3 ) return true; + return false; + } + + bool sharesEdge(const CTri &t) const + { + bool ret = false; + unsigned int count = 0; + + if ( t.hasIndex(mI1) ) count++; + if ( t.hasIndex(mI2) ) count++; + if ( t.hasIndex(mI3) ) count++; + + if ( count >= 2 ) ret = true; + + return ret; + } + + void debug(unsigned int color,ConvexDecompInterface *callback) + { + callback->ConvexDebugTri( mP1.Ptr(), mP2.Ptr(), mP3.Ptr(), color ); + callback->ConvexDebugTri( mP1.Ptr(), mP1.Ptr(), mNear1.Ptr(), 0xFF0000 ); + callback->ConvexDebugTri( mP2.Ptr(), mP2.Ptr(), mNear2.Ptr(), 0xFF0000 ); + callback->ConvexDebugTri( mP2.Ptr(), mP3.Ptr(), mNear3.Ptr(), 0xFF0000 ); + callback->ConvexDebugPoint( mNear1.Ptr(), 0.01f, 0xFF0000 ); + callback->ConvexDebugPoint( mNear2.Ptr(), 0.01f, 0xFF0000 ); + callback->ConvexDebugPoint( mNear3.Ptr(), 0.01f, 0xFF0000 ); + } + + float area(void) + { + float a = mConcavity*mP1.Area(mP2,mP3); + return a; + } + + void addWeighted(WpointVector &list,ConvexDecompInterface *callback) + { + + Wpoint p1(mP1,mC1); + Wpoint p2(mP2,mC2); + Wpoint p3(mP3,mC3); + + Vector3d d1 = mNear1 - mP1; + Vector3d d2 = mNear2 - mP2; + Vector3d d3 = mNear3 - mP3; + + d1*=WSCALE; + d2*=WSCALE; + d3*=WSCALE; + + d1 = d1 + mP1; + d2 = d2 + mP2; + d3 = d3 + mP3; + + Wpoint p4(d1,mC1); + Wpoint p5(d2,mC2); + Wpoint p6(d3,mC3); + + list.push_back(p1); + list.push_back(p2); + list.push_back(p3); + + list.push_back(p4); + list.push_back(p5); + list.push_back(p6); + +#if 0 + callback->ConvexDebugPoint(mP1.Ptr(),0.01f,0x00FF00); + callback->ConvexDebugPoint(mP2.Ptr(),0.01f,0x00FF00); + callback->ConvexDebugPoint(mP3.Ptr(),0.01f,0x00FF00); + callback->ConvexDebugPoint(d1.Ptr(),0.01f,0xFF0000); + callback->ConvexDebugPoint(d2.Ptr(),0.01f,0xFF0000); + callback->ConvexDebugPoint(d3.Ptr(),0.01f,0xFF0000); + + callback->ConvexDebugTri(mP1.Ptr(), d1.Ptr(), d1.Ptr(),0x00FF00); + callback->ConvexDebugTri(mP2.Ptr(), d2.Ptr(), d2.Ptr(),0x00FF00); + callback->ConvexDebugTri(mP3.Ptr(), d3.Ptr(), d3.Ptr(),0x00FF00); + + Vector3d np1 = mP1 + mNormal*0.05f; + Vector3d np2 = mP2 + mNormal*0.05f; + Vector3d np3 = mP3 + mNormal*0.05f; + + callback->ConvexDebugTri(mP1.Ptr(), np1.Ptr(), np1.Ptr(), 0xFF00FF ); + callback->ConvexDebugTri(mP2.Ptr(), np2.Ptr(), np2.Ptr(), 0xFF00FF ); + callback->ConvexDebugTri(mP3.Ptr(), np3.Ptr(), np3.Ptr(), 0xFF00FF ); + + callback->ConvexDebugPoint( np1.Ptr(), 0.01F, 0XFF00FF ); + callback->ConvexDebugPoint( np2.Ptr(), 0.01F, 0XFF00FF ); + callback->ConvexDebugPoint( np3.Ptr(), 0.01F, 0XFF00FF ); + +#endif + + + + } + + Vector3d mP1; + Vector3d mP2; + Vector3d mP3; + Vector3d mNear1; + Vector3d mNear2; + Vector3d mNear3; + Vector3d mNormal; + float mPlaneD; + float mConcavity; + float mC1; + float mC2; + float mC3; + unsigned int mI1; + unsigned int mI2; + unsigned int mI3; + int mProcessed; // already been added... +}; + +typedef std::vector< CTri > CTriVector; + +bool featureMatch(CTri &m,const CTriVector &tris,ConvexDecompInterface *callback,const CTriVector &input_mesh) +{ + + bool ret = false; + + float neardot = 0.707f; + + m.mConcavity = 0; + + //gLog->Display("*********** FEATURE MATCH *************\r\n"); + //gLog->Display("Plane: %0.4f,%0.4f,%0.4f %0.4f\r\n", m.mNormal.x, m.mNormal.y, m.mNormal.z, m.mPlaneD ); + //gLog->Display("*********************************************\r\n"); + + CTriVector::const_iterator i; + + CTri nearest; + + + for (i=tris.begin(); i!=tris.end(); ++i) + { + const CTri &t = (*i); + + + //gLog->Display(" HullPlane: %0.4f,%0.4f,%0.4f %0.4f\r\n", t.mNormal.x, t.mNormal.y, t.mNormal.z, t.mPlaneD ); + + if ( t.samePlane(m) ) + { + //gLog->Display("*** PLANE MATCH!!!\r\n"); + ret = false; + break; + } + + float dot = t.mNormal.Dot(m.mNormal); + + if ( dot > neardot ) + { + + float d1 = t.planeDistance( m.mP1 ); + float d2 = t.planeDistance( m.mP2 ); + float d3 = t.planeDistance( m.mP3 ); + + if ( d1 > 0.001f || d2 > 0.001f || d3 > 0.001f ) // can't be near coplaner! + { + + neardot = dot; + + Vector3d n1,n2,n3; + + t.raySect( m.mP1, m.mNormal, m.mNear1 ); + t.raySect( m.mP2, m.mNormal, m.mNear2 ); + t.raySect( m.mP3, m.mNormal, m.mNear3 ); + + nearest = t; + + ret = true; + } + + } + } + + if ( ret ) + { + if ( 0 ) + { + CTriVector::const_iterator i; + for (i=input_mesh.begin(); i!=input_mesh.end(); ++i) + { + const CTri &c = (*i); + if ( c.mI1 != m.mI1 && c.mI2 != m.mI2 && c.mI3 != m.mI3 ) + { + c.clip( m.mP1, m.mNear1 ); + c.clip( m.mP2, m.mNear2 ); + c.clip( m.mP3, m.mNear3 ); + } + } + } + + //gLog->Display("*********************************************\r\n"); + //gLog->Display(" HullPlaneNearest: %0.4f,%0.4f,%0.4f %0.4f\r\n", nearest.mNormal.x, nearest.mNormal.y, nearest.mNormal.z, nearest.mPlaneD ); + + m.mC1 = m.mP1.Distance( m.mNear1 ); + m.mC2 = m.mP2.Distance( m.mNear2 ); + m.mC3 = m.mP3.Distance( m.mNear3 ); + + m.mConcavity = m.mC1; + + if ( m.mC2 > m.mConcavity ) m.mConcavity = m.mC2; + if ( m.mC3 > m.mConcavity ) m.mConcavity = m.mC3; + + #if 0 + callback->ConvexDebugTri( m.mP1.Ptr(), m.mP2.Ptr(), m.mP3.Ptr(), 0x00FF00 ); + callback->ConvexDebugTri( m.mNear1.Ptr(), m.mNear2.Ptr(), m.mNear3.Ptr(), 0xFF0000 ); + + callback->ConvexDebugTri( m.mP1.Ptr(), m.mP1.Ptr(), m.mNear1.Ptr(), 0xFFFF00 ); + callback->ConvexDebugTri( m.mP2.Ptr(), m.mP2.Ptr(), m.mNear2.Ptr(), 0xFFFF00 ); + callback->ConvexDebugTri( m.mP3.Ptr(), m.mP3.Ptr(), m.mNear3.Ptr(), 0xFFFF00 ); + #endif + + } + else + { + //gLog->Display("No match\r\n"); + } + + //gLog->Display("*********************************************\r\n"); + return ret; +} + +bool isFeatureTri(CTri &t,CTriVector &flist,float fc,ConvexDecompInterface *callback,unsigned int color) +{ + bool ret = false; + + if ( t.mProcessed == 0 ) // if not already processed + { + + float c = t.mConcavity / fc; // must be within 80% of the concavity of the parent. + + if ( c > 0.85f ) + { + // see if this triangle is a 'feature' triangle. Meaning it shares an + // edge with any existing feature triangle and is within roughly the same + // concavity of the parent. + if ( flist.size() ) + { + CTriVector::iterator i; + for (i=flist.begin(); i!=flist.end(); ++i) + { + CTri &ftri = (*i); + if ( ftri.sharesEdge(t) ) + { + t.mProcessed = 2; // it is now part of a feature. + flist.push_back(t); // add it to the feature list. +// callback->ConvexDebugTri( t.mP1.Ptr(), t.mP2.Ptr(),t.mP3.Ptr(), color ); + ret = true; + break; + } + } + } + else + { + t.mProcessed = 2; + flist.push_back(t); // add it to the feature list. +// callback->ConvexDebugTri( t.mP1.Ptr(), t.mP2.Ptr(),t.mP3.Ptr(), color ); + ret = true; + } + } + else + { + t.mProcessed = 1; // eliminated for this feature, but might be valid for the next one.. + } + + } + return ret; +} + +float computeConcavity(unsigned int vcount, + const float *vertices, + unsigned int tcount, + const unsigned int *indices, + ConvexDecompInterface *callback, + float *plane, // plane equation to split on + float &volume) +{ + + + float cret = 0; + volume = 1; + + HullResult result; + HullLibrary hl; + HullDesc desc; + + desc.mMaxFaces = 256; + desc.mMaxVertices = 256; + desc.SetHullFlag(QF_TRIANGLES); + + + desc.mVcount = vcount; + desc.mVertices = vertices; + desc.mVertexStride = sizeof(float)*3; + + HullError ret = hl.CreateConvexHull(desc,result); + + if ( ret == QE_OK ) + { +#if 0 + float bmin[3]; + float bmax[3]; + + float dx = bmax[0] - bmin[0]; + float dy = bmax[1] - bmin[1]; + float dz = bmax[2] - bmin[2]; + + Vector3d center; + + center.x = bmin[0] + dx*0.5f; + center.y = bmin[1] + dy*0.5f; + center.z = bmin[2] + dz*0.5f; +#endif + + volume = computeMeshVolume2( result.mOutputVertices, result.mNumFaces, result.mIndices ); + +#if 1 + // ok..now..for each triangle on the original mesh.. + // we extrude the points to the nearest point on the hull. + const unsigned int *source = result.mIndices; + + CTriVector tris; + + for (unsigned int i=0; iConvexDebugTri(p1,p2,p3,0xFFFFFF); + + CTri t(p1,p2,p3,i1,i2,i3); // + tris.push_back(t); + } + + // we have not pre-computed the plane equation for each triangle in the convex hull.. + + float totalVolume = 0; + + CTriVector ftris; // 'feature' triangles. + + const unsigned int *src = indices; + + + float maxc=0; + + + if ( 1 ) + { + CTriVector input_mesh; + if ( 1 ) + { + const unsigned int *src = indices; + for (unsigned int i=0; i CONCAVE_THRESH ) + { + + if ( t.mConcavity > maxc ) + { + maxc = t.mConcavity; + maxctri = t; + } + + float v = t.getVolume(0); + totalVolume+=v; + ftris.push_back(t); + } + + } + } + + if ( ftris.size() && 0 ) + { + + // ok..now we extract the triangles which form the maximum concavity. + CTriVector major_feature; + float maxarea = 0; + + while ( maxc > CONCAVE_THRESH ) + { + + unsigned int color = getDebugColor(); // + + CTriVector flist; + + bool found; + + float totalarea = 0; + + do + { + found = false; + CTriVector::iterator i; + for (i=ftris.begin(); i!=ftris.end(); ++i) + { + CTri &t = (*i); + if ( isFeatureTri(t,flist,maxc,callback,color) ) + { + found = true; + totalarea+=t.area(); + } + } + } while ( found ); + + + if ( totalarea > maxarea ) + { + major_feature = flist; + maxarea = totalarea; + } + + maxc = 0; + + for (unsigned int i=0; i maxc ) + { + maxc = t.mConcavity; + } + } + } + } + + unsigned int color = getDebugColor(); + + WpointVector list; + for (unsigned int i=0; i +#include +#include +#include +#include + +#include "fitsphere.h" + + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// +/* +An Efficient Bounding Sphere +by Jack Ritter +from "Graphics Gems", Academic Press, 1990 +*/ + +/* Routine to calculate tight bounding sphere over */ +/* a set of points in 3D */ +/* This contains the routine find_bounding_sphere(), */ +/* the struct definition, and the globals used for parameters. */ +/* The abs() of all coordinates must be < BIGNUMBER */ +/* Code written by Jack Ritter and Lyle Rains. */ + +#define BIGNUMBER 100000000.0 /* hundred million */ + +static inline void Set(float *n,float x,float y,float z) +{ + n[0] = x; + n[1] = y; + n[2] = z; +} + +static inline void Copy(float *dest,const float *source) +{ + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; +} + +float computeBoundingSphere(unsigned int vcount,const float *points,float *center) +{ + + float mRadius; + float mRadius2; + + float xmin[3]; + float xmax[3]; + float ymin[3]; + float ymax[3]; + float zmin[3]; + float zmax[3]; + float dia1[3]; + float dia2[3]; + + /* FIRST PASS: find 6 minima/maxima points */ + Set(xmin,BIGNUMBER,BIGNUMBER,BIGNUMBER); + Set(xmax,-BIGNUMBER,-BIGNUMBER,-BIGNUMBER); + Set(ymin,BIGNUMBER,BIGNUMBER,BIGNUMBER); + Set(ymax,-BIGNUMBER,-BIGNUMBER,-BIGNUMBER); + Set(zmin,BIGNUMBER,BIGNUMBER,BIGNUMBER); + Set(zmax,-BIGNUMBER,-BIGNUMBER,-BIGNUMBER); + + for (unsigned i=0; ixmax[0]) + Copy(xmax,caller_p); + if (caller_p[1]ymax[1]) + Copy(ymax,caller_p); + if (caller_p[2]zmax[2]) + Copy(zmax,caller_p); + } + + /* Set xspan = distance between the 2 points xmin & xmax (squared) */ + float dx = xmax[0] - xmin[0]; + float dy = xmax[1] - xmin[1]; + float dz = xmax[2] - xmin[2]; + float xspan = dx*dx + dy*dy + dz*dz; + + /* Same for y & z spans */ + dx = ymax[0] - ymin[0]; + dy = ymax[1] - ymin[1]; + dz = ymax[2] - ymin[2]; + float yspan = dx*dx + dy*dy + dz*dz; + + dx = zmax[0] - zmin[0]; + dy = zmax[1] - zmin[1]; + dz = zmax[2] - zmin[2]; + float zspan = dx*dx + dy*dy + dz*dz; + + /* Set points dia1 & dia2 to the maximally separated pair */ + Copy(dia1,xmin); + Copy(dia2,xmax); /* assume xspan biggest */ + float maxspan = xspan; + + if (yspan>maxspan) + { + maxspan = yspan; + Copy(dia1,ymin); + Copy(dia2,ymax); + } + + if (zspan>maxspan) + { + Copy(dia1,zmin); + Copy(dia2,zmax); + } + + + /* dia1,dia2 is a diameter of initial sphere */ + /* calc initial center */ + center[0] = (dia1[0]+dia2[0])*0.5f; + center[1] = (dia1[1]+dia2[1])*0.5f; + center[2] = (dia1[2]+dia2[2])*0.5f; + + /* calculate initial radius**2 and radius */ + + dx = dia2[0]-center[0]; /* x component of radius vector */ + dy = dia2[1]-center[1]; /* y component of radius vector */ + dz = dia2[2]-center[2]; /* z component of radius vector */ + + mRadius2 = dx*dx + dy*dy + dz*dz; + mRadius = float(sqrt(mRadius2)); + + /* SECOND PASS: increment current sphere */ + + if ( 1 ) + { + for (unsigned i=0; i mRadius2) /* do r**2 test first */ + { /* this point is outside of current sphere */ + float old_to_p = float(sqrt(old_to_p_sq)); + /* calc radius of new sphere */ + mRadius = (mRadius + old_to_p) * 0.5f; + mRadius2 = mRadius*mRadius; /* for next r**2 compare */ + float old_to_new = old_to_p - mRadius; + + /* calc center of new sphere */ + + float recip = 1.0f /old_to_p; + + float cx = (mRadius*center[0] + old_to_new*caller_p[0]) * recip; + float cy = (mRadius*center[1] + old_to_new*caller_p[1]) * recip; + float cz = (mRadius*center[2] + old_to_new*caller_p[2]) * recip; + + Set(center,cx,cy,cz); + } + } + } + + return mRadius; +} + + diff --git a/Extras/ConvexDecomposition/fitsphere.h b/Extras/ConvexDecomposition/fitsphere.h new file mode 100644 index 0000000..cd4a565 --- /dev/null +++ b/Extras/ConvexDecomposition/fitsphere.h @@ -0,0 +1,43 @@ +#ifndef FIT_SPHERE_H + +#define FIT_SPHERE_H + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + + + +float computeBoundingSphere(unsigned int vcount,const float *points,float *center); + +#endif diff --git a/Extras/ConvexDecomposition/float_math.cpp b/Extras/ConvexDecomposition/float_math.cpp new file mode 100644 index 0000000..38c699b --- /dev/null +++ b/Extras/ConvexDecomposition/float_math.cpp @@ -0,0 +1,257 @@ +#include "float_math.h" + +#include +#include +#include +#include +#include + + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + +void fm_inverseRT(const float *matrix,const float *pos,float *t) // inverse rotate translate the point. +{ + + float _x = pos[0] - matrix[3*4+0]; + float _y = pos[1] - matrix[3*4+1]; + float _z = pos[2] - matrix[3*4+2]; + + // Multiply inverse-translated source vector by inverted rotation transform + + t[0] = (matrix[0*4+0] * _x) + (matrix[0*4+1] * _y) + (matrix[0*4+2] * _z); + t[1] = (matrix[1*4+0] * _x) + (matrix[1*4+1] * _y) + (matrix[1*4+2] * _z); + t[2] = (matrix[2*4+0] * _x) + (matrix[2*4+1] * _y) + (matrix[2*4+2] * _z); + +} + + +void fm_identity(float *matrix) // set 4x4 matrix to identity. +{ + matrix[0*4+0] = 1; + matrix[1*4+1] = 1; + matrix[2*4+2] = 1; + matrix[3*4+3] = 1; + + matrix[1*4+0] = 0; + matrix[2*4+0] = 0; + matrix[3*4+0] = 0; + + matrix[0*4+1] = 0; + matrix[2*4+1] = 0; + matrix[3*4+1] = 0; + + matrix[0*4+2] = 0; + matrix[1*4+2] = 0; + matrix[3*4+2] = 0; + + matrix[0*4+3] = 0; + matrix[1*4+3] = 0; + matrix[2*4+3] = 0; + +} + +void fm_eulerMatrix(float ax,float ay,float az,float *matrix) // convert euler (in radians) to a dest 4x4 matrix (translation set to zero) +{ + float quat[4]; + fm_eulerToQuat(ax,ay,az,quat); + fm_quatToMatrix(quat,matrix); +} + +void fm_getAABB(unsigned int vcount,const float *points,unsigned int pstride,float *bmin,float *bmax) +{ + + const unsigned char *source = (const unsigned char *) points; + + bmin[0] = points[0]; + bmin[1] = points[1]; + bmin[2] = points[2]; + + bmax[0] = points[0]; + bmax[1] = points[1]; + bmax[2] = points[2]; + + + for (unsigned int i=1; i bmax[0] ) bmax[0] = p[0]; + if ( p[1] > bmax[1] ) bmax[1] = p[1]; + if ( p[2] > bmax[2] ) bmax[2] = p[2]; + + } +} + + +void fm_eulerToQuat(float roll,float pitch,float yaw,float *quat) // convert euler angles to quaternion. +{ + roll *= 0.5f; + pitch *= 0.5f; + yaw *= 0.5f; + + float cr = cosf(roll); + float cp = cosf(pitch); + float cy = cosf(yaw); + + float sr = sinf(roll); + float sp = sinf(pitch); + float sy = sinf(yaw); + + float cpcy = cp * cy; + float spsy = sp * sy; + float spcy = sp * cy; + float cpsy = cp * sy; + + quat[0] = ( sr * cpcy - cr * spsy); + quat[1] = ( cr * spcy + sr * cpsy); + quat[2] = ( cr * cpsy - sr * spcy); + quat[3] = cr * cpcy + sr * spsy; +} + +void fm_quatToMatrix(const float *quat,float *matrix) // convert quaterinion rotation to matrix, zeros out the translation component. +{ + + float xx = quat[0]*quat[0]; + float yy = quat[1]*quat[1]; + float zz = quat[2]*quat[2]; + float xy = quat[0]*quat[1]; + float xz = quat[0]*quat[2]; + float yz = quat[1]*quat[2]; + float wx = quat[3]*quat[0]; + float wy = quat[3]*quat[1]; + float wz = quat[3]*quat[2]; + + matrix[0*4+0] = 1 - 2 * ( yy + zz ); + matrix[1*4+0] = 2 * ( xy - wz ); + matrix[2*4+0] = 2 * ( xz + wy ); + + matrix[0*4+1] = 2 * ( xy + wz ); + matrix[1*4+1] = 1 - 2 * ( xx + zz ); + matrix[2*4+1] = 2 * ( yz - wx ); + + matrix[0*4+2] = 2 * ( xz - wy ); + matrix[1*4+2] = 2 * ( yz + wx ); + matrix[2*4+2] = 1 - 2 * ( xx + yy ); + + matrix[3*4+0] = matrix[3*4+1] = matrix[3*4+2] = 0.0f; + matrix[0*4+3] = matrix[1*4+3] = matrix[2*4+3] = 0.0f; + matrix[3*4+3] = 1.0f; + +} + + +void fm_quatRotate(const float *quat,const float *v,float *r) // rotate a vector directly by a quaternion. +{ + float left[4]; + + left[0] = quat[3]*v[0] + quat[1]*v[2] - v[1]*quat[2]; + left[1] = quat[3]*v[1] + quat[2]*v[0] - v[2]*quat[0]; + left[2] = quat[3]*v[2] + quat[0]*v[1] - v[0]*quat[1]; + left[3] = - quat[0]*v[0] - quat[1]*v[1] - quat[2]*v[2]; + + r[0] = (left[3]*-quat[0]) + (quat[3]*left[0]) + (left[1]*-quat[2]) - (-quat[1]*left[2]); + r[1] = (left[3]*-quat[1]) + (quat[3]*left[1]) + (left[2]*-quat[0]) - (-quat[2]*left[0]); + r[2] = (left[3]*-quat[2]) + (quat[3]*left[2]) + (left[0]*-quat[1]) - (-quat[0]*left[1]); + +} + + +void fm_getTranslation(const float *matrix,float *t) +{ + t[0] = matrix[3*4+0]; + t[1] = matrix[3*4+1]; + t[2] = matrix[3*4+2]; +} + +void fm_matrixToQuat(const float *matrix,float *quat) // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w +{ + + float tr = matrix[0*4+0] + matrix[1*4+1] + matrix[2*4+2]; + + // check the diagonal + + if (tr > 0.0f ) + { + float s = (float) sqrt ( (double) (tr + 1.0f) ); + quat[3] = s * 0.5f; + s = 0.5f / s; + quat[0] = (matrix[1*4+2] - matrix[2*4+1]) * s; + quat[1] = (matrix[2*4+0] - matrix[0*4+2]) * s; + quat[2] = (matrix[0*4+1] - matrix[1*4+0]) * s; + + } + else + { + // diagonal is negative + int nxt[3] = {1, 2, 0}; + float qa[4]; + + int i = 0; + + if (matrix[1*4+1] > matrix[0*4+0]) i = 1; + if (matrix[2*4+2] > matrix[i*4+i]) i = 2; + + int j = nxt[i]; + int k = nxt[j]; + + float s = sqrtf ( ((matrix[i*4+i] - (matrix[j*4+j] + matrix[k*4+k])) + 1.0f) ); + + qa[i] = s * 0.5f; + + if (s != 0.0f ) s = 0.5f / s; + + qa[3] = (matrix[j*4+k] - matrix[k*4+j]) * s; + qa[j] = (matrix[i*4+j] + matrix[j*4+i]) * s; + qa[k] = (matrix[i*4+k] + matrix[k*4+i]) * s; + + quat[0] = qa[0]; + quat[1] = qa[1]; + quat[2] = qa[2]; + quat[3] = qa[3]; + } + + +} + + +float fm_sphereVolume(float radius) // return's the volume of a sphere of this radius (4/3 PI * R cubed ) +{ + return (4.0f / 3.0f ) * FM_PI * radius * radius * radius; +} diff --git a/Extras/ConvexDecomposition/float_math.h b/Extras/ConvexDecomposition/float_math.h new file mode 100644 index 0000000..d6046d3 --- /dev/null +++ b/Extras/ConvexDecomposition/float_math.h @@ -0,0 +1,72 @@ +#ifndef FLOAT_MATH_H + +#define FLOAT_MATH_H + +#ifdef _WIN32 + #pragma warning(disable : 4324) // disable padding warning + #pragma warning(disable : 4244) // disable padding warning + #pragma warning(disable : 4267) // possible loss of data + #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning. + #pragma warning(disable:4996) //Turn off warnings about deprecated C routines + #pragma warning(disable:4786) // Disable the "debug name too long" warning +#endif + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + + +// a set of routines that last you do common 3d math +// operations without any vector, matrix, or quaternion +// classes or templates. +// +// a vector (or point) is a 'float *' to 3 floating point numbers. +// a matrix is a 'float *' to an array of 16 floating point numbers representing a 4x4 transformation matrix compatible with D3D or OGL +// a quaternion is a 'float *' to 4 floats representing a quaternion x,y,z,w + +const float FM_PI = 3.141592654f; +const float FM_DEG_TO_RAD = ((2.0f * FM_PI) / 360.0f); +const float FM_RAD_TO_DEG = (360.0f / (2.0f * FM_PI)); + +void fm_identity(float *matrix); // set 4x4 matrix to identity. +void fm_inverseRT(const float *matrix,const float *pos,float *t); // inverse rotate translate the point. +void fm_eulerMatrix(float ax,float ay,float az,float *matrix); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero) +void fm_getAABB(unsigned int vcount,const float *points,unsigned int pstride,float *bmin,float *bmax); +void fm_eulerToQuat(float roll,float pitch,float yaw,float *quat); // convert euler angles to quaternion. +void fm_quatToMatrix(const float *quat,float *matrix); // convert quaterinion rotation to matrix, translation set to zero. +void fm_quatRotate(const float *quat,const float *v,float *r); // rotate a vector directly by a quaternion. +void fm_getTranslation(const float *matrix,float *t); +void fm_matrixToQuat(const float *matrix,float *quat); // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w +float fm_sphereVolume(float radius); // return's the volume of a sphere of this radius (4/3 PI * R cubed ) + +#endif diff --git a/Extras/ConvexDecomposition/meshvolume.cpp b/Extras/ConvexDecomposition/meshvolume.cpp new file mode 100644 index 0000000..b9dfa17 --- /dev/null +++ b/Extras/ConvexDecomposition/meshvolume.cpp @@ -0,0 +1,128 @@ +#include "float_math.h" +#include "meshvolume.h" + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + +inline float det(const float *p1,const float *p2,const float *p3) +{ + return p1[0]*p2[1]*p3[2] + p2[0]*p3[1]*p1[2] + p3[0]*p1[1]*p2[2] -p1[0]*p3[1]*p2[2] - p2[0]*p1[1]*p3[2] - p3[0]*p2[1]*p1[2]; +} + +float computeMeshVolume(const float *vertices,unsigned int tcount,const unsigned int *indices) +{ + float volume = 0; + + for (unsigned int i=0; i +#include +#include +#include + +#include "planetri.h" + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + +static inline float DistToPt(const float *p,const float *plane) +{ + float x = p[0]; + float y = p[1]; + float z = p[2]; + float d = x*plane[0] + y*plane[1] + z*plane[2] + plane[3]; + return d; +} + + +static PlaneTriResult getSidePlane(const float *p,const float *plane,float epsilon) +{ + + float d = DistToPt(p,plane); + + if ( (d+epsilon) > 0 ) + return PTR_FRONT; // it is 'in front' within the provided epsilon value. + + return PTR_BACK; +} + +static void add(const float *p,float *dest,unsigned int tstride,unsigned int &pcount) +{ + char *d = (char *) dest; + d = d + pcount*tstride; + dest = (float *) d; + dest[0] = p[0]; + dest[1] = p[1]; + dest[2] = p[2]; + pcount++; + assert( pcount <= 4 ); +} + + +// assumes that the points are on opposite sides of the plane! +static void intersect(const float *p1,const float *p2,float *split,const float *plane) +{ + + float dp1 = DistToPt(p1,plane); + + float dir[3]; + + dir[0] = p2[0] - p1[0]; + dir[1] = p2[1] - p1[1]; + dir[2] = p2[2] - p1[2]; + + float dot1 = dir[0]*plane[0] + dir[1]*plane[1] + dir[2]*plane[2]; + float dot2 = dp1 - plane[3]; + + float t = -(plane[3] + dot2 ) / dot1; + + split[0] = (dir[0]*t)+p1[0]; + split[1] = (dir[1]*t)+p1[1]; + split[2] = (dir[2]*t)+p1[2]; + +} + +PlaneTriResult planeTriIntersection(const float *plane, // the plane equation in Ax+By+Cz+D format + const float *triangle, // the source triangle. + unsigned int tstride, // stride in bytes of the input and output triangles + float epsilon, // the co-planer epsilon value. + float *front, // the triangle in front of the + unsigned int &fcount, // number of vertices in the 'front' triangle + float *back, // the triangle in back of the plane + unsigned int &bcount) // the number of vertices in the 'back' triangle. +{ + fcount = 0; + bcount = 0; + + const char *tsource = (const char *) triangle; + + // get the three vertices of the triangle. + const float *p1 = (const float *) (tsource); + const float *p2 = (const float *) (tsource+tstride); + const float *p3 = (const float *) (tsource+tstride*2); + + + PlaneTriResult r1 = getSidePlane(p1,plane,epsilon); // compute the side of the plane each vertex is on + PlaneTriResult r2 = getSidePlane(p2,plane,epsilon); + PlaneTriResult r3 = getSidePlane(p3,plane,epsilon); + + if ( r1 == r2 && r1 == r3 ) // if all three vertices are on the same side of the plane. + { + if ( r1 == PTR_FRONT ) // if all three are in front of the plane, then copy to the 'front' output triangle. + { + add(p1,front,tstride,fcount); + add(p2,front,tstride,fcount); + add(p3,front,tstride,fcount); + } + else + { + add(p1,back,tstride,bcount); // if all three are in 'abck' then copy to the 'back' output triangle. + add(p2,back,tstride,bcount); + add(p3,back,tstride,bcount); + } + return r1; // if all three points are on the same side of the plane return result + } + + // ok.. we need to split the triangle at the plane. + + // First test ray segment P1 to P2 + if ( r1 == r2 ) // if these are both on the same side... + { + if ( r1 == PTR_FRONT ) + { + add( p1, front, tstride, fcount ); + add( p2, front, tstride, fcount ); + } + else + { + add( p1, back, tstride, bcount ); + add( p2, back, tstride, bcount ); + } + } + else + { + float split[3]; // split the point + intersect(p1,p2,split,plane); + + if ( r1 == PTR_FRONT ) + { + + add(p1, front, tstride, fcount ); + add(split, front, tstride, fcount ); + + add(split, back, tstride, bcount ); + add(p2, back, tstride, bcount ); + + } + else + { + add(p1, back, tstride, bcount ); + add(split, back, tstride, bcount ); + + add(split, front, tstride, fcount ); + add(p2, front, tstride, fcount ); + } + + } + + // Next test ray segment P2 to P3 + if ( r2 == r3 ) // if these are both on the same side... + { + if ( r3 == PTR_FRONT ) + { + add( p3, front, tstride, fcount ); + } + else + { + add( p3, back, tstride, bcount ); + } + } + else + { + float split[3]; // split the point + intersect(p2,p3,split,plane); + + if ( r3 == PTR_FRONT ) + { + add(split, front, tstride, fcount ); + add(split, back, tstride, bcount ); + + add(p3, front, tstride, fcount ); + } + else + { + add(split, front, tstride, fcount ); + add(split, back, tstride, bcount ); + + add(p3, back, tstride, bcount ); + } + } + + // Next test ray segment P3 to P1 + if ( r3 != r1 ) // if these are both on the same side... + { + float split[3]; // split the point + + intersect(p3,p1,split,plane); + + if ( r1 == PTR_FRONT ) + { + add(split, front, tstride, fcount ); + add(split, back, tstride, bcount ); + } + else + { + add(split, front, tstride, fcount ); + add(split, back, tstride, bcount ); + } + } + + + + return PTR_SPLIT; +} diff --git a/Extras/ConvexDecomposition/planetri.h b/Extras/ConvexDecomposition/planetri.h new file mode 100644 index 0000000..780ac85 --- /dev/null +++ b/Extras/ConvexDecomposition/planetri.h @@ -0,0 +1,58 @@ +#ifndef PLANE_TRI_H + +#define PLANE_TRI_H + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + + + +enum PlaneTriResult +{ + PTR_FRONT, + PTR_BACK, + PTR_SPLIT +}; + +PlaneTriResult planeTriIntersection(const float *plane, // the plane equation in Ax+By+Cz+D format + const float *triangle, // the source position triangle. + unsigned int tstride, // stride in bytes between vertices of the triangle. + float epsilon, // the co-planer epsilon value. + float *front, // the triangle in front of the + unsigned int &fcount, // number of vertices in the 'front' triangle. + float *back, // the triangle in back of the plane + unsigned int &bcount); // the number of vertices in the 'back' triangle. + + +#endif diff --git a/Extras/ConvexDecomposition/premake4.lua b/Extras/ConvexDecomposition/premake4.lua new file mode 100644 index 0000000..8a91bea --- /dev/null +++ b/Extras/ConvexDecomposition/premake4.lua @@ -0,0 +1,9 @@ + project "ConvexDecomposition" + + kind "StaticLib" + targetdir "../../lib" + includedirs {".","../../src"} + files { + "**.cpp", + "**.h" + } \ No newline at end of file diff --git a/Extras/ConvexDecomposition/raytri.cpp b/Extras/ConvexDecomposition/raytri.cpp new file mode 100644 index 0000000..83b076a --- /dev/null +++ b/Extras/ConvexDecomposition/raytri.cpp @@ -0,0 +1,134 @@ +#include "float_math.h" +#include +#include +#include +#include +#include + +#include "raytri.h" + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + + +/* a = b - c */ +#define vector(a,b,c) \ + (a)[0] = (b)[0] - (c)[0]; \ + (a)[1] = (b)[1] - (c)[1]; \ + (a)[2] = (b)[2] - (c)[2]; + + + +#define innerProduct(v,q) \ + ((v)[0] * (q)[0] + \ + (v)[1] * (q)[1] + \ + (v)[2] * (q)[2]) + +#define crossProduct(a,b,c) \ + (a)[0] = (b)[1] * (c)[2] - (c)[1] * (b)[2]; \ + (a)[1] = (b)[2] * (c)[0] - (c)[2] * (b)[0]; \ + (a)[2] = (b)[0] * (c)[1] - (c)[0] * (b)[1]; + +bool rayIntersectsTriangle(const float *p,const float *d,const float *v0,const float *v1,const float *v2,float &t) +{ + + float e1[3],e2[3],h[3],s[3],q[3]; + float a,f,u,v; + + vector(e1,v1,v0); + vector(e2,v2,v0); + crossProduct(h,d,e2); + a = innerProduct(e1,h); + + if (a > -0.00001 && a < 0.00001) + return(false); + + f = 1/a; + vector(s,p,v0); + u = f * (innerProduct(s,h)); + + if (u < 0.0 || u > 1.0) + return(false); + + crossProduct(q,s,e1); + v = f * innerProduct(d,q); + if (v < 0.0 || u + v > 1.0) + return(false); + // at this stage we can compute t to find out where + // the intersection point is on the line + t = f * innerProduct(e2,q); + if (t > 0) // ray intersection + return(true); + else // this means that there is a line intersection + // but not a ray intersection + return (false); +} + + +bool lineIntersectsTriangle(const float *rayStart,const float *rayEnd,const float *p1,const float *p2,const float *p3,float *sect) +{ + float dir[3]; + + dir[0] = rayEnd[0] - rayStart[0]; + dir[1] = rayEnd[1] - rayStart[1]; + dir[2] = rayEnd[2] - rayStart[2]; + + float d = sqrtf(dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]); + float r = 1.0f / d; + + dir[0]*=r; + dir[1]*=r; + dir[2]*=r; + + + float t; + + bool ret = rayIntersectsTriangle(rayStart, dir, p1, p2, p3, t ); + + if ( ret ) + { + if ( t > d ) + { + sect[0] = rayStart[0] + dir[0]*t; + sect[1] = rayStart[1] + dir[1]*t; + sect[2] = rayStart[2] + dir[2]*t; + } + else + { + ret = false; + } + } + + return ret; +} diff --git a/Extras/ConvexDecomposition/raytri.h b/Extras/ConvexDecomposition/raytri.h new file mode 100644 index 0000000..76370c6 --- /dev/null +++ b/Extras/ConvexDecomposition/raytri.h @@ -0,0 +1,45 @@ +#ifndef RAY_TRI_H + +#define RAY_TRI_H + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + + + +// returns true if the ray intersects the triangle. +bool lineIntersectsTriangle(const float *rayStart,const float *rayEnd,const float *p1,const float *p2,const float *p3,float *sect); +bool rayIntersectsTriangle(const float *p,const float *d,const float *v0,const float *v1,const float *v2,float &t); + +#endif diff --git a/Extras/ConvexDecomposition/splitplane.cpp b/Extras/ConvexDecomposition/splitplane.cpp new file mode 100644 index 0000000..2ae408e --- /dev/null +++ b/Extras/ConvexDecomposition/splitplane.cpp @@ -0,0 +1,306 @@ +#include "float_math.h" +#include +#include +#include +#include +#include +#include + + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + +#include "splitplane.h" +#include "ConvexDecomposition.h" +#include "cd_vector.h" +#include "cd_hull.h" +#include "cd_wavefront.h" +#include "bestfit.h" +#include "planetri.h" +#include "vlookup.h" +#include "meshvolume.h" + +namespace ConvexDecomposition +{ + +static void computePlane(const float *A,const float *B,const float *C,float *plane) +{ + + float vx = (B[0] - C[0]); + float vy = (B[1] - C[1]); + float vz = (B[2] - C[2]); + + float wx = (A[0] - B[0]); + float wy = (A[1] - B[1]); + float wz = (A[2] - B[2]); + + float vw_x = vy * wz - vz * wy; + float vw_y = vz * wx - vx * wz; + float vw_z = vx * wy - vy * wx; + + float mag = sqrtf((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z)); + + if ( mag < 0.000001f ) + { + mag = 0; + } + else + { + mag = 1.0f/mag; + } + + float x = vw_x * mag; + float y = vw_y * mag; + float z = vw_z * mag; + + + float D = 0.0f - ((x*A[0])+(y*A[1])+(z*A[2])); + + plane[0] = x; + plane[1] = y; + plane[2] = z; + plane[3] = D; + +} + +class Rect3d +{ +public: + Rect3d(void) { }; + + Rect3d(const float *bmin,const float *bmax) + { + + mMin[0] = bmin[0]; + mMin[1] = bmin[1]; + mMin[2] = bmin[2]; + + mMax[0] = bmax[0]; + mMax[1] = bmax[1]; + mMax[2] = bmax[2]; + + } + + void SetMin(const float *bmin) + { + mMin[0] = bmin[0]; + mMin[1] = bmin[1]; + mMin[2] = bmin[2]; + } + + void SetMax(const float *bmax) + { + mMax[0] = bmax[0]; + mMax[1] = bmax[1]; + mMax[2] = bmax[2]; + } + + void SetMin(float x,float y,float z) + { + mMin[0] = x; + mMin[1] = y; + mMin[2] = z; + } + + void SetMax(float x,float y,float z) + { + mMax[0] = x; + mMax[1] = y; + mMax[2] = z; + } + + float mMin[3]; + float mMax[3]; +}; + +void splitRect(unsigned int axis, + const Rect3d &source, + Rect3d &b1, + Rect3d &b2, + const float *midpoint) +{ + switch ( axis ) + { + case 0: + b1.SetMin(source.mMin); + b1.SetMax( midpoint[0], source.mMax[1], source.mMax[2] ); + + b2.SetMin( midpoint[0], source.mMin[1], source.mMin[2] ); + b2.SetMax(source.mMax); + + break; + case 1: + b1.SetMin(source.mMin); + b1.SetMax( source.mMax[0], midpoint[1], source.mMax[2] ); + + b2.SetMin( source.mMin[0], midpoint[1], source.mMin[2] ); + b2.SetMax(source.mMax); + + break; + case 2: + b1.SetMin(source.mMin); + b1.SetMax( source.mMax[0], source.mMax[1], midpoint[2] ); + + b2.SetMin( source.mMin[0], source.mMin[1], midpoint[2] ); + b2.SetMax(source.mMax); + + break; + } +} + +bool computeSplitPlane(unsigned int vcount, + const float *vertices, + unsigned int tcount, + const unsigned int *indices, + ConvexDecompInterface *callback, + float *plane) +{ + float bmin[3] = { 1e9, 1e9, 1e9 }; + float bmax[3] = { -1e9, -1e9, -1e9 }; + + for (unsigned int i=0; i bmax[0] ) bmax[0] = p[0]; + if ( p[1] > bmax[1] ) bmax[1] = p[1]; + if ( p[2] > bmax[2] ) bmax[2] = p[2]; + + } + + float dx = bmax[0] - bmin[0]; + float dy = bmax[1] - bmin[1]; + float dz = bmax[2] - bmin[2]; + + + float laxis = dx; + + unsigned int axis = 0; + + if ( dy > dx ) + { + axis = 1; + laxis = dy; + } + + if ( dz > dx && dz > dy ) + { + axis = 2; + laxis = dz; + } + + float p1[3]; + float p2[3]; + float p3[3]; + + p3[0] = p2[0] = p1[0] = bmin[0] + dx*0.5f; + p3[1] = p2[1] = p1[1] = bmin[1] + dy*0.5f; + p3[2] = p2[2] = p1[2] = bmin[2] + dz*0.5f; + + Rect3d b(bmin,bmax); + + Rect3d b1,b2; + + splitRect(axis,b,b1,b2,p1); + + +// callback->ConvexDebugBound(b1.mMin,b1.mMax,0x00FF00); +// callback->ConvexDebugBound(b2.mMin,b2.mMax,0xFFFF00); + + switch ( axis ) + { + case 0: + p2[1] = bmin[1]; + p2[2] = bmin[2]; + + if ( dz > dy ) + { + p3[1] = bmax[1]; + p3[2] = bmin[2]; + } + else + { + p3[1] = bmin[1]; + p3[2] = bmax[2]; + } + + break; + case 1: + p2[0] = bmin[0]; + p2[2] = bmin[2]; + + if ( dx > dz ) + { + p3[0] = bmax[0]; + p3[2] = bmin[2]; + } + else + { + p3[0] = bmin[0]; + p3[2] = bmax[2]; + } + + break; + case 2: + p2[0] = bmin[0]; + p2[1] = bmin[1]; + + if ( dx > dy ) + { + p3[0] = bmax[0]; + p3[1] = bmin[1]; + } + else + { + p3[0] = bmin[0]; + p3[1] = bmax[1]; + } + + break; + } + +// callback->ConvexDebugTri(p1,p2,p3,0xFF0000); + + computePlane(p1,p2,p3,plane); + + return true; + +} + + +} diff --git a/Extras/ConvexDecomposition/splitplane.h b/Extras/ConvexDecomposition/splitplane.h new file mode 100644 index 0000000..26fe2e3 --- /dev/null +++ b/Extras/ConvexDecomposition/splitplane.h @@ -0,0 +1,59 @@ +#ifndef SPLIT_PLANE_H + +#define SPLIT_PLANE_H + +//** Computes an 'optimal' split plane for the supplied mesh. +//** needs much improvement since it currently just splits along +//** the longest side of the AABB. +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + + + +namespace ConvexDecomposition +{ + +class ConvexDecompInterface; + +bool computeSplitPlane(unsigned int vcount, + const float *vertices, + unsigned int tcount, + const unsigned int *indices, + ConvexDecompInterface *callback, + float *plane); + + +} + +#endif diff --git a/Extras/ConvexDecomposition/vlookup.cpp b/Extras/ConvexDecomposition/vlookup.cpp new file mode 100644 index 0000000..3b9e928 --- /dev/null +++ b/Extras/ConvexDecomposition/vlookup.cpp @@ -0,0 +1,326 @@ +#include "float_math.h" +#include +#include +#include +#include + +#pragma warning(disable:4786) + +#include +#include +#include + + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + +// CodeSnippet provided by John W. Ratcliff +// on March 23, 2006. +// +// mailto: jratcliff@infiniplex.net +// +// Personal website: http://jratcliffscarab.blogspot.com +// Coding Website: http://codesuppository.blogspot.com +// FundRaising Blog: http://amillionpixels.blogspot.com +// Fundraising site: http://www.amillionpixels.us +// New Temple Site: http://newtemple.blogspot.com +// +// This snippet shows how to 'hide' the complexity of +// the STL by wrapping some useful piece of functionality +// around a handful of discrete API calls. +// +// This API allows you to create an indexed triangle list +// from a collection of raw input triangles. Internally +// it uses an STL set to build the lookup table very rapidly. +// +// Here is how you would use it to build an indexed triangle +// list from a raw list of triangles. +// +// (1) create a 'VertexLookup' interface by calling +// +// VertexLook vl = Vl_createVertexLookup(); +// +// (2) For each vertice in each triangle call: +// +// unsigned int i1 = Vl_getIndex(vl,p1); +// unsigned int i2 = Vl_getIndex(vl,p2); +// unsigned int i3 = Vl_getIndex(vl,p3); +// +// save the 3 indices into your triangle list array. +// +// (3) Get the vertex array by calling: +// +// const float *vertices = Vl_getVertices(vl); +// +// (4) Get the number of vertices so you can copy them into +// your own buffer. +// unsigned int vcount = Vl_getVcount(vl); +// +// (5) Release the VertexLookup interface when you are done with it. +// Vl_releaseVertexLookup(vl); +// +// Teaches the following lessons: +// +// How to wrap the complexity of STL and C++ classes around a +// simple API interface. +// +// How to use an STL set and custom comparator operator for +// a complex data type. +// +// How to create a template class. +// +// How to achieve significant performance improvements by +// taking advantage of built in STL containers in just +// a few lines of code. +// +// You could easily modify this code to support other vertex +// formats with any number of interpolants. + + + + +#include "vlookup.h" + +namespace Vlookup +{ + +class VertexPosition +{ +public: + VertexPosition(void) { }; + VertexPosition(const float *p) + { + mPos[0] = p[0]; + mPos[1] = p[1]; + mPos[2] = p[2]; + }; + + void Set(int index,const float *pos) + { + const float * p = &pos[index*3]; + + mPos[0] = p[0]; + mPos[1] = p[1]; + mPos[2] = p[2]; + + }; + + float GetX(void) const { return mPos[0]; }; + float GetY(void) const { return mPos[1]; }; + float GetZ(void) const { return mPos[2]; }; + + float mPos[3]; +}; + +typedef std::vector< VertexPosition > VertexVector; + +struct Tracker +{ + VertexPosition mFind; // vertice to locate. + VertexVector *mList; + + Tracker() + { + mList = 0; + } + + void SetSearch(const VertexPosition& match,VertexVector *list) + { + mFind = match; + mList = list; + }; +}; + +struct VertexID +{ + int mID; + Tracker* mTracker; + + VertexID(int ID, Tracker* Tracker) + { + mID = ID; + mTracker = Tracker; + } +}; + +class VertexLess +{ +public: + + bool operator()(VertexID v1,VertexID v2) const; + +private: + const VertexPosition& Get(VertexID index) const + { + if ( index.mID == -1 ) return index.mTracker->mFind; + VertexVector &vlist = *index.mTracker->mList; + return vlist[index.mID]; + } +}; + +template class VertexPool +{ +public: + typedef std::set VertexSet; + typedef std::vector< Type > VertexVector; + + int getVertex(const Type& vtx) + { + mTracker.SetSearch(vtx,&mVtxs); + VertexSet::iterator found; + found = mVertSet.find( VertexID(-1,&mTracker) ); + if ( found != mVertSet.end() ) + { + return found->mID; + } + int idx = (int)mVtxs.size(); + mVtxs.push_back( vtx ); + mVertSet.insert( VertexID(idx,&mTracker) ); + return idx; + }; + + + const float * GetPos(int idx) const + { + return mVtxs[idx].mPos; + } + + const Type& Get(int idx) const + { + return mVtxs[idx]; + }; + + unsigned int GetSize(void) const + { + return mVtxs.size(); + }; + + void Clear(int reservesize) // clear the vertice pool. + { + mVertSet.clear(); + mVtxs.clear(); + mVtxs.reserve(reservesize); + }; + + const VertexVector& GetVertexList(void) const { return mVtxs; }; + + void Set(const Type& vtx) + { + mVtxs.push_back(vtx); + } + + unsigned int GetVertexCount(void) const + { + return mVtxs.size(); + }; + + + Type * getBuffer(void) + { + return &mVtxs[0]; + }; + +private: + VertexSet mVertSet; // ordered list. + VertexVector mVtxs; // set of vertices. + Tracker mTracker; +}; + + +bool VertexLess::operator()(VertexID v1,VertexID v2) const +{ + + const VertexPosition& a = Get(v1); + const VertexPosition& b = Get(v2); + + int ixA = (int) (a.GetX()*10000.0f); + int ixB = (int) (b.GetX()*10000.0f); + + if ( ixA < ixB ) return true; + if ( ixA > ixB ) return false; + + int iyA = (int) (a.GetY()*10000.0f); + int iyB = (int) (b.GetY()*10000.0f); + + if ( iyA < iyB ) return true; + if ( iyA > iyB ) return false; + + int izA = (int) (a.GetZ()*10000.0f); + int izB = (int) (b.GetZ()*10000.0f); + + if ( izA < izB ) return true; + if ( izA > izB ) return false; + + + return false; +} + + + + +} + +using namespace Vlookup; + +VertexLookup Vl_createVertexLookup(void) +{ + VertexLookup ret = new VertexPool< VertexPosition >; + return ret; +} + +void Vl_releaseVertexLookup(VertexLookup vlook) +{ + VertexPool< VertexPosition > *vp = (VertexPool< VertexPosition > *) vlook; + delete vp; +} + +unsigned int Vl_getIndex(VertexLookup vlook,const float *pos) // get index. +{ + VertexPool< VertexPosition > *vp = (VertexPool< VertexPosition > *) vlook; + VertexPosition p(pos); + return vp->getVertex(p); +} + +const float * Vl_getVertices(VertexLookup vlook) +{ + VertexPool< VertexPosition > *vp = (VertexPool< VertexPosition > *) vlook; + return vp->GetPos(0); +} + + +unsigned int Vl_getVcount(VertexLookup vlook) +{ + VertexPool< VertexPosition > *vp = (VertexPool< VertexPosition > *) vlook; + return vp->GetVertexCount(); +} diff --git a/Extras/ConvexDecomposition/vlookup.h b/Extras/ConvexDecomposition/vlookup.h new file mode 100644 index 0000000..1a6e0a9 --- /dev/null +++ b/Extras/ConvexDecomposition/vlookup.h @@ -0,0 +1,119 @@ +#ifndef VLOOKUP_H + +#define VLOOKUP_H + + +/*---------------------------------------------------------------------- + Copyright (c) 2004 Open Dynamics Framework Group + www.physicstools.org + 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 Open Dynamics Framework Group 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 INTEL 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. +-----------------------------------------------------------------------*/ + +// http://codesuppository.blogspot.com +// +// mailto: jratcliff@infiniplex.net +// +// http://www.amillionpixels.us +// + + +// CodeSnippet provided by John W. Ratcliff +// on March 23, 2006. +// +// mailto: jratcliff@infiniplex.net +// +// Personal website: http://jratcliffscarab.blogspot.com +// Coding Website: http://codesuppository.blogspot.com +// FundRaising Blog: http://amillionpixels.blogspot.com +// Fundraising site: http://www.amillionpixels.us +// New Temple Site: http://newtemple.blogspot.com +// +// This snippet shows how to 'hide' the complexity of +// the STL by wrapping some useful piece of functionality +// around a handful of discrete API calls. +// +// This API allows you to create an indexed triangle list +// from a collection of raw input triangles. Internally +// it uses an STL set to build the lookup table very rapidly. +// +// Here is how you would use it to build an indexed triangle +// list from a raw list of triangles. +// +// (1) create a 'VertexLookup' interface by calling +// +// VertexLook vl = Vl_createVertexLookup(); +// +// (2) For each vertice in each triangle call: +// +// unsigned int i1 = Vl_getIndex(vl,p1); +// unsigned int i2 = Vl_getIndex(vl,p2); +// unsigned int i3 = Vl_getIndex(vl,p3); +// +// save the 3 indices into your triangle list array. +// +// (3) Get the vertex array by calling: +// +// const float *vertices = Vl_getVertices(vl); +// +// (4) Get the number of vertices so you can copy them into +// your own buffer. +// unsigned int vcount = Vl_getVcount(vl); +// +// (5) Release the VertexLookup interface when you are done with it. +// Vl_releaseVertexLookup(vl); +// +// Teaches the following lessons: +// +// How to wrap the complexity of STL and C++ classes around a +// simple API interface. +// +// How to use an STL set and custom comparator operator for +// a complex data type. +// +// How to create a template class. +// +// How to achieve significant performance improvements by +// taking advantage of built in STL containers in just +// a few lines of code. +// +// You could easily modify this code to support other vertex +// formats with any number of interpolants. +// +// Hide C++ classes from the rest of your application by +// keeping them in the CPP and wrapping them in a namespace +// Uses an STL set to create an index table for a bunch of vertex positions +// used typically to re-index a collection of raw triangle data. + + +typedef void * VertexLookup; + +VertexLookup Vl_createVertexLookup(void); +void Vl_releaseVertexLookup(VertexLookup vlook); + +unsigned int Vl_getIndex(VertexLookup vlook,const float *pos); // get index. +const float * Vl_getVertices(VertexLookup vlook); +unsigned int Vl_getVcount(VertexLookup vlook); + + +#endif diff --git a/Extras/GIMPACTUtils/CMakeLists.txt b/Extras/GIMPACTUtils/CMakeLists.txt new file mode 100644 index 0000000..5c9480a --- /dev/null +++ b/Extras/GIMPACTUtils/CMakeLists.txt @@ -0,0 +1,37 @@ +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/Extras/GIMPACT/include +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Extras/GIMPACTUtils +${BULLET_PHYSICS_SOURCE_DIR}/Extras/ConvexDecomposition +) + +ADD_LIBRARY(GIMPACTUtils +btGImpactConvexDecompositionShape.cpp btGImpactConvexDecompositionShape.h +) +SET_TARGET_PROPERTIES(GIMPACTUtils PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(GIMPACTUtils PROPERTIES SOVERSION ${BULLET_VERSION}) + +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(GIMPACTUtils ConvexDecomposition BulletCollision) +ENDIF (BUILD_SHARED_LIBS) + +IF (INSTALL_EXTRA_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + #FILES_MATCHING requires CMake 2.6 + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS GIMPACTUtils DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS GIMPACTUtils DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN +".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(GIMPACTUtils PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(GIMPACTUtils PROPERTIES PUBLIC_HEADER "btGImpactConvexDecompositionShape.h") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_EXTRA_LIBS) diff --git a/Extras/GIMPACTUtils/btGImpactConvexDecompositionShape.cpp b/Extras/GIMPACTUtils/btGImpactConvexDecompositionShape.cpp new file mode 100644 index 0000000..44d0a6d --- /dev/null +++ b/Extras/GIMPACTUtils/btGImpactConvexDecompositionShape.cpp @@ -0,0 +1,240 @@ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +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 "btGImpactConvexDecompositionShape.h" +#include "BulletCollision/CollisionShapes/btConvexHullShape.h" + +#include "ConvexBuilder.h" + +class GIM_ConvexDecomposition : public ConvexDecomposition::ConvexDecompInterface +{ +protected: + btGImpactConvexDecompositionShape * m_compoundShape; + + btAlignedObjectArray m_convexShapes; + + +public: + int mBaseCount; + int mHullCount; + bool m_transformSubShapes; + + GIM_ConvexDecomposition(btGImpactConvexDecompositionShape * compoundShape,bool transformSubShapes) + { + mBaseCount = 0; + mHullCount = 0; + m_compoundShape = compoundShape; + m_transformSubShapes = transformSubShapes; + } + + virtual ~GIM_ConvexDecomposition() + { + int i; + for (i=0;i vertices; + + if(m_transformSubShapes) + { + + //const unsigned int *src = result.mHullIndices; + for (unsigned int i=0; isetMargin(m_compoundShape->getMargin()); + + if(m_transformSubShapes) + { + btTransform trans; + trans.setIdentity(); + trans.setOrigin(centroid); + + // add convex shape + + m_compoundShape->addChildShape(trans,convexShape); + } + else + { + btTransform trans; + trans.setIdentity(); + //trans.setOrigin(centroid); + + // add convex shape + + m_compoundShape->addChildShape(trans,convexShape); + + //m_compoundShape->addChildShape(convexShape); + } + } + + void processDecomposition(int part) + { + btGImpactMeshShapePart::TrimeshPrimitiveManager * trimeshInterface = + m_compoundShape->getTrimeshInterface(part); + + + trimeshInterface->lock(); + + //collect vertices + btAlignedObjectArray vertices; + vertices.reserve(trimeshInterface->get_vertex_count()*3); + + for(int vi = 0;viget_vertex_count();vi++) + { + btVector3 vec; + trimeshInterface->get_vertex(vi,vec); + vertices.push_back(vec[0]); + vertices.push_back(vec[1]); + vertices.push_back(vec[2]); + } + + + //collect indices + btAlignedObjectArray indices; + indices.reserve(trimeshInterface->get_primitive_count()*3); + + + for(int i = 0;iget_primitive_count();i++) + { + int i0, i1,i2; + trimeshInterface->get_indices(i,i0,i1,i2); + indices.push_back(i0); + indices.push_back(i1); + indices.push_back(i2); + } + + trimeshInterface->unlock(); + + + + unsigned int depth = 5; + float cpercent = 5; + float ppercent = 15; + unsigned int maxv = 16; + float skinWidth = 0.0; + + + ConvexDecomposition::DecompDesc desc; + desc.mVcount = trimeshInterface->get_vertex_count(); + desc.mVertices = &vertices[0]; + desc.mTcount = trimeshInterface->get_primitive_count(); + desc.mIndices = &indices[0]; + desc.mDepth = depth; + desc.mCpercent = cpercent; + desc.mPpercent = ppercent; + desc.mMaxVertices = maxv; + desc.mSkinWidth = skinWidth; + desc.mCallback = this; + + //convexDecomposition.performConvexDecomposition(desc); + + ConvexBuilder cb(desc.mCallback); + cb.process(desc); + } + + + + +}; + + + +void btGImpactConvexDecompositionShape::buildConvexDecomposition(bool transformSubShapes) +{ + + m_decomposition = new GIM_ConvexDecomposition(this,transformSubShapes); + + int part_count = m_trimeshInterfaces.size(); + for (int i = 0;iprocessDecomposition(i); + } + + postUpdate(); +} + +btGImpactConvexDecompositionShape::~btGImpactConvexDecompositionShape() +{ + delete m_decomposition; +} +void btGImpactConvexDecompositionShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + + int part_count = m_trimeshInterfaces.size(); + for (int part = 0;part(ptr); + + trimeshInterface->lock(); + + btPrimitiveTriangle triangle; + + + int i = trimeshInterface->get_primitive_count(); + while(i--) + { + trimeshInterface->get_primitive_triangle(i,triangle); + callback->processTriangle(triangle.m_vertices,part,i); + } + + trimeshInterface->unlock(); + } + + +} diff --git a/Extras/GIMPACTUtils/btGImpactConvexDecompositionShape.h b/Extras/GIMPACTUtils/btGImpactConvexDecompositionShape.h new file mode 100644 index 0000000..4710861 --- /dev/null +++ b/Extras/GIMPACTUtils/btGImpactConvexDecompositionShape.h @@ -0,0 +1,87 @@ +/*! \file btGImpactConvexDecompositionShape.h +\author Francisco León Nájera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +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 GIMPACT_CONVEX_DECOMPOSITION_SHAPE_H +#define GIMPACT_CONVEX_DECOMPOSITION_SHAPE_H + + +#include "BulletCollision/Gimpact/btGImpactShape.h" // box tree class + + + +//! This class creates a decomposition from a trimesh. +/*! + +*/ +class btGImpactConvexDecompositionShape : public btGImpactCompoundShape +{ +protected: + btAlignedObjectArray m_trimeshInterfaces; + + class GIM_ConvexDecomposition* m_decomposition; + + void buildConvexDecomposition(bool transformSubShapes); +public: + + btGImpactConvexDecompositionShape( + btStridingMeshInterface * meshInterface, + const btVector3 & mesh_scale, + btScalar margin = btScalar(0.01),bool children_has_transform = true) + :btGImpactCompoundShape(children_has_transform) + { + + m_collisionMargin = margin; + + btGImpactMeshShapePart::TrimeshPrimitiveManager triInterface; + triInterface.m_meshInterface = meshInterface; + triInterface.m_scale = mesh_scale; + triInterface.m_margin = btScalar(1.0); + + //add parts + int part_count = meshInterface->getNumSubParts(); + for (int i=0;i< part_count;i++ ) + { + triInterface.m_part = i; + m_trimeshInterfaces.push_back(triInterface); + } + + m_decomposition = 0; + + buildConvexDecomposition(children_has_transform); + } + + virtual ~btGImpactConvexDecompositionShape(); + + SIMD_FORCE_INLINE btGImpactMeshShapePart::TrimeshPrimitiveManager * getTrimeshInterface(int part) + { + return &m_trimeshInterfaces[part]; + } + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + +}; + + + + +#endif //GIMPACT_MESH_SHAPE_H diff --git a/Extras/HACD/CMakeLists.txt b/Extras/HACD/CMakeLists.txt new file mode 100644 index 0000000..389a603 --- /dev/null +++ b/Extras/HACD/CMakeLists.txt @@ -0,0 +1,51 @@ +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/Extras/HACD +) + +SET(HACD_SRCS + hacdGraph.cpp + hacdHACD.cpp + hacdICHull.cpp + hacdManifoldMesh.cpp +) + +SET(HACD_HDRS + hacdCircularList.h + hacdGraph.h + hacdHACD.h + hacdICHull.h + hacdManifoldMesh.h + hacdVector.h + hacdVersion.h + hacdCircularList.inl + hacdVector.inl +) + +ADD_LIBRARY(HACD ${HACD_SRCS} ${HACD_HDRS}) +SET_TARGET_PROPERTIES(HACD PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(HACD PROPERTIES SOVERSION ${BULLET_VERSION}) + +#IF (BUILD_SHARED_LIBS) +# TARGET_LINK_LIBRARIES(HACD BulletCollision LinearMath) +#ENDIF (BUILD_SHARED_LIBS) + +IF (INSTALL_EXTRA_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + #FILES_MATCHING requires CMake 2.6 + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS HACD DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS HACD DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN +".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(HACD PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(HACD PROPERTIES PUBLIC_HEADER "${HACD_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_EXTRA_LIBS) diff --git a/Extras/HACD/hacdCircularList.h b/Extras/HACD/hacdCircularList.h new file mode 100644 index 0000000..d673536 --- /dev/null +++ b/Extras/HACD/hacdCircularList.h @@ -0,0 +1,80 @@ +/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) + All rights reserved. + + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + 2. 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. + + 3. The names of the contributors may not 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 HOLDER 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. + */ +#pragma once +#ifndef HACD_CIRCULAR_LIST_H +#define HACD_CIRCULAR_LIST_H +#include +#include "hacdVersion.h" +namespace HACD +{ + //! CircularListElement class. + template < typename T > class CircularListElement + { + public: + T & GetData() { return m_data; } + const T & GetData() const { return m_data; } + CircularListElement * & GetNext() { return m_next; } + CircularListElement * & GetPrev() { return m_prev; } + const CircularListElement * & GetNext() const { return m_next; } + const CircularListElement * & GetPrev() const { return m_prev; } + //! Constructor + CircularListElement(const T & data) {m_data = data;} + CircularListElement(void){} + //! Destructor + ~CircularListElement(void){} + private: + T m_data; + CircularListElement * m_next; + CircularListElement * m_prev; + + CircularListElement(const CircularListElement & rhs); + }; + + + //! CircularList class. + template < typename T > class CircularList + { + public: + CircularListElement * & GetHead() { return m_head;} + const CircularListElement * GetHead() const { return m_head;} + bool IsEmpty() const { return (m_size == 0);} + size_t GetSize() const { return m_size; } + const T & GetData() const { return m_head->GetData(); } + T & GetData() { return m_head->GetData();} + bool Delete() ; + bool Delete(CircularListElement * element); + CircularListElement * Add(const T * data = 0); + CircularListElement * Add(const T & data); + bool Next(); + bool Prev(); + void Clear() { while(Delete());}; + const CircularList& operator=(const CircularList& rhs); + //! Constructor + CircularList() + { + m_head = 0; + m_size = 0; + } + CircularList(const CircularList& rhs); + //! Destructor + virtual ~CircularList(void) {Clear();}; + private: + CircularListElement * m_head; //!< a pointer to the head of the circular list + size_t m_size; //!< number of element in the circular list + + }; +} +#include "hacdCircularList.inl" +#endif diff --git a/Extras/HACD/hacdCircularList.inl b/Extras/HACD/hacdCircularList.inl new file mode 100644 index 0000000..1d48f4e --- /dev/null +++ b/Extras/HACD/hacdCircularList.inl @@ -0,0 +1,163 @@ +#pragma once +#ifndef HACD_CIRCULAR_LIST_INL +#define HACD_CIRCULAR_LIST_INL +#include +#include "hacdVersion.h" +namespace HACD +{ + template < typename T > + inline bool CircularList::Delete(CircularListElement * element) + { + if (!element) + { + return false; + } + if (m_size > 1) + { + CircularListElement * next = element->GetNext(); + CircularListElement * prev = element->GetPrev(); + delete element; + m_size--; + if (element == m_head) + { + m_head = next; + } + next->GetPrev() = prev; + prev->GetNext() = next; + return true; + } + else if (m_size == 1) + { + delete m_head; + m_size--; + m_head = 0; + return true; + } + else + { + return false; + } + } + + template < typename T > + inline bool CircularList::Delete() + { + if (m_size > 1) + { + CircularListElement * next = m_head->GetNext(); + CircularListElement * prev = m_head->GetPrev(); + delete m_head; + m_size--; + m_head = next; + next->GetPrev() = prev; + prev->GetNext() = next; + return true; + } + else if (m_size == 1) + { + delete m_head; + m_size--; + m_head = 0; + return true; + } + else + { + return false; + } + } + template < typename T > + inline CircularListElement * CircularList::Add(const T * data) + { + if (m_size == 0) + { + if (data) + { + m_head = new CircularListElement(*data); + } + else + { + m_head = new CircularListElement(); + } + m_head->GetNext() = m_head->GetPrev() = m_head; + } + else + { + CircularListElement * next = m_head->GetNext(); + CircularListElement * element = m_head; + if (data) + { + m_head = new CircularListElement(*data); + } + else + { + m_head = new CircularListElement; + } + m_head->GetNext() = next; + m_head->GetPrev() = element; + element->GetNext() = m_head; + next->GetPrev() = m_head; + } + m_size++; + return m_head; + } + template < typename T > + inline CircularListElement * CircularList::Add(const T & data) + { + const T * pData = &data; + return Add(pData); + } + template < typename T > + inline bool CircularList::Next() + { + if (m_size == 0) + { + return false; + } + m_head = m_head->GetNext(); + return true; + } + template < typename T > + inline bool CircularList::Prev() + { + if (m_size == 0) + { + return false; + } + m_head = m_head->GetPrev(); + return true; + } + template < typename T > + inline CircularList::CircularList(const CircularList& rhs) + { + if (rhs.m_size > 0) + { + CircularListElement * current = rhs.m_head; + do + { + current = current->GetNext(); + Add(current->GetData()); + } + while ( current != rhs.m_head ); + } + } + template < typename T > + inline const CircularList& CircularList::operator=(const CircularList& rhs) + { + if (&rhs != this) + { + Clear(); + if (rhs.m_size > 0) + { + CircularListElement * current = rhs.m_head; + do + { + current = current->GetNext(); + Add(current->GetData()); + } + while ( current != rhs.m_head ); + } + } + return (*this); + } +} +#endif diff --git a/Extras/HACD/hacdGraph.cpp b/Extras/HACD/hacdGraph.cpp new file mode 100644 index 0000000..bd7c73e --- /dev/null +++ b/Extras/HACD/hacdGraph.cpp @@ -0,0 +1,292 @@ +/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) + All rights reserved. + + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + 2. 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. + + 3. The names of the contributors may not 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 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "hacdGraph.h" +namespace HACD +{ + + GraphEdge::GraphEdge() + { + m_convexHull = 0; + m_v1 = -1; + m_v2 = -1; + m_name = -1; + m_error = 0; + m_surf = 0; + m_perimeter = 0; + m_concavity = 0; + m_volume = 0; + m_deleted = false; + } + + GraphVertex::GraphVertex() + { + m_convexHull = 0; + m_name = -1; + m_cc = -1; + m_error = 0; + m_surf = 0; + m_perimeter = 0; + m_concavity = 0; + m_volume = 0; + m_deleted = false; + } + + bool GraphVertex::DeleteEdge(long name) + { + std::set::iterator it = m_edges.find(name); + if (it != m_edges.end() ) + { + m_edges.erase(it); + return true; + } + return false; + } + + Graph::Graph() + { + m_nV = 0; + m_nE = 0; + m_nCCs = 0; + } + + Graph::~Graph() + { + } + + void Graph::Allocate(size_t nV, size_t nE) + { + m_nV = nV; + m_edges.reserve(nE); + m_vertices.resize(nV); + for(size_t i = 0; i < nV; i++) + { + m_vertices[i].m_name = static_cast(i); + } + } + + long Graph::AddVertex() + { + size_t name = m_vertices.size(); + m_vertices.resize(name+1); + m_vertices[name].m_name = static_cast(name); + m_nV++; + return static_cast(name); + } + + long Graph::AddEdge(long v1, long v2) + { + size_t name = m_edges.size(); + m_edges.push_back(GraphEdge()); + m_edges[name].m_name = static_cast(name); + m_edges[name].m_v1 = v1; + m_edges[name].m_v2 = v2; + m_vertices[v1].AddEdge(static_cast(name)); + m_vertices[v2].AddEdge(static_cast(name)); + m_nE++; + return static_cast(name); + } + + bool Graph::DeleteEdge(long name) + { + if (name < static_cast(m_edges.size())) + { + long v1 = m_edges[name].m_v1; + long v2 = m_edges[name].m_v2; + m_edges[name].m_deleted = true; + m_vertices[v1].DeleteEdge(name); + m_vertices[v2].DeleteEdge(name); + delete m_edges[name].m_convexHull; + m_edges[name].m_distPoints.clear(); + m_edges[name].m_boudaryEdges.clear(); + m_edges[name].m_convexHull = 0; + m_nE--; + return true; + } + return false; + } + bool Graph::DeleteVertex(long name) + { + if (name < static_cast(m_vertices.size())) + { + m_vertices[name].m_deleted = true; + m_vertices[name].m_edges.clear(); + m_vertices[name].m_ancestors = std::vector(); + delete m_vertices[name].m_convexHull; + m_vertices[name].m_distPoints.clear(); + m_vertices[name].m_boudaryEdges.clear(); + m_vertices[name].m_convexHull = 0; + m_nV--; + return true; + } + return false; + } + bool Graph::EdgeCollapse(long v1, long v2) + { + long edgeToDelete = GetEdgeID(v1, v2); + if (edgeToDelete >= 0) + { + // delete the edge (v1, v2) + DeleteEdge(edgeToDelete); + // add v2 to v1 ancestors + m_vertices[v1].m_ancestors.push_back(v2); + // add v2's ancestors to v1's ancestors + m_vertices[v1].m_ancestors.insert(m_vertices[v1].m_ancestors.begin(), + m_vertices[v2].m_ancestors.begin(), + m_vertices[v2].m_ancestors.end()); + // update adjacency information + std::set & v1Edges = m_vertices[v1].m_edges; + std::set::const_iterator ed(m_vertices[v2].m_edges.begin()); + std::set::const_iterator itEnd(m_vertices[v2].m_edges.end()); + long b = -1; + for(; ed != itEnd; ++ed) + { + if (m_edges[*ed].m_v1 == v2) + { + b = m_edges[*ed].m_v2; + } + else + { + b = m_edges[*ed].m_v1; + } + if (GetEdgeID(v1, b) >= 0) + { + m_edges[*ed].m_deleted = true; + m_vertices[b].DeleteEdge(*ed); + m_nE--; + } + else + { + m_edges[*ed].m_v1 = v1; + m_edges[*ed].m_v2 = b; + v1Edges.insert(*ed); + } + } + // delete the vertex v2 + DeleteVertex(v2); + return true; + } + return false; + } + + long Graph::GetEdgeID(long v1, long v2) const + { + if (v1 < static_cast(m_vertices.size()) && !m_vertices[v1].m_deleted) + { + std::set::const_iterator ed(m_vertices[v1].m_edges.begin()); + std::set::const_iterator itEnd(m_vertices[v1].m_edges.end()); + for(; ed != itEnd; ++ed) + { + if ( (m_edges[*ed].m_v1 == v2) || + (m_edges[*ed].m_v2 == v2) ) + { + return m_edges[*ed].m_name; + } + } + } + return -1; + } + + void Graph::Print() const + { + std::cout << "-----------------------------" << std::endl; + std::cout << "vertices (" << m_nV << ")" << std::endl; + for (size_t v = 0; v < m_vertices.size(); ++v) + { + const GraphVertex & currentVertex = m_vertices[v]; + if (!m_vertices[v].m_deleted) + { + + std::cout << currentVertex.m_name << "\t"; + std::set::const_iterator ed(currentVertex.m_edges.begin()); + std::set::const_iterator itEnd(currentVertex.m_edges.end()); + for(; ed != itEnd; ++ed) + { + std::cout << "(" << m_edges[*ed].m_v1 << "," << m_edges[*ed].m_v2 << ") "; + } + std::cout << std::endl; + } + } + + std::cout << "vertices (" << m_nE << ")" << std::endl; + for (size_t e = 0; e < m_edges.size(); ++e) + { + const GraphEdge & currentEdge = m_edges[e]; + if (!m_edges[e].m_deleted) + { + std::cout << currentEdge.m_name << "\t(" + << m_edges[e].m_v1 << "," + << m_edges[e].m_v2 << ") "<< std::endl; + } + } + } + void Graph::Clear() + { + m_vertices.clear(); + m_edges.clear(); + m_nV = 0; + m_nE = 0; + } + + long Graph::ExtractCCs() + { + // all CCs to -1 + for (size_t v = 0; v < m_vertices.size(); ++v) + { + if (!m_vertices[v].m_deleted) + { + m_vertices[v].m_cc = -1; + } + } + + // we get the CCs + m_nCCs = 0; + long v2 = -1; + std::vector temp; + for (size_t v = 0; v < m_vertices.size(); ++v) + { + if (!m_vertices[v].m_deleted && m_vertices[v].m_cc == -1) + { + m_vertices[v].m_cc = static_cast(m_nCCs); + temp.clear(); + temp.push_back(m_vertices[v].m_name); + while (temp.size()) + { + long vertex = temp[temp.size()-1]; + temp.pop_back(); + std::set::const_iterator ed(m_vertices[vertex].m_edges.begin()); + std::set::const_iterator itEnd(m_vertices[vertex].m_edges.end()); + for(; ed != itEnd; ++ed) + { + if (m_edges[*ed].m_v1 == vertex) + { + v2 = m_edges[*ed].m_v2; + } + else + { + v2 = m_edges[*ed].m_v1; + } + if ( !m_vertices[v2].m_deleted && m_vertices[v2].m_cc == -1) + { + m_vertices[v2].m_cc = static_cast(m_nCCs); + temp.push_back(v2); + } + } + } + m_nCCs++; + } + } + return static_cast(m_nCCs); + } +} diff --git a/Extras/HACD/hacdGraph.h b/Extras/HACD/hacdGraph.h new file mode 100644 index 0000000..12b0d3c --- /dev/null +++ b/Extras/HACD/hacdGraph.h @@ -0,0 +1,120 @@ +/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) + All rights reserved. + + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + 2. 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. + + 3. The names of the contributors may not 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 HOLDER 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. + */ +#pragma once +#ifndef HACD_GRAPH_H +#define HACD_GRAPH_H +#include "hacdVersion.h" +#include "hacdVector.h" +#include "hacdICHull.h" +#include +#include +#include + +namespace HACD +{ + class GraphVertex; + class GraphEdge; + class Graph; + class HACD; + + class GraphVertex + { + public: + bool AddEdge(long name) + { + m_edges.insert(name); + return true; + } + bool DeleteEdge(long name); + GraphVertex(); + ~GraphVertex(){ delete m_convexHull;}; + private: + long m_name; + long m_cc; + std::set m_edges; + bool m_deleted; + std::vector m_ancestors; + std::map m_distPoints; + + Real m_error; + double m_surf; + double m_volume; + double m_perimeter; + double m_concavity; + ICHull * m_convexHull; + std::set m_boudaryEdges; + + + friend class GraphEdge; + friend class Graph; + friend class HACD; + }; + + class GraphEdge + { + public: + GraphEdge(); + ~GraphEdge(){delete m_convexHull;}; + private: + long m_name; + long m_v1; + long m_v2; + std::map m_distPoints; + Real m_error; + double m_surf; + double m_volume; + double m_perimeter; + double m_concavity; + ICHull * m_convexHull; + std::set m_boudaryEdges; + bool m_deleted; + + + + friend class GraphVertex; + friend class Graph; + friend class HACD; + }; + + class Graph + { + public: + size_t GetNEdges() const { return m_nE;} + size_t GetNVertices() const { return m_nV;} + bool EdgeCollapse(long v1, long v2); + long AddVertex(); + long AddEdge(long v1, long v2); + bool DeleteEdge(long name); + bool DeleteVertex(long name); + long GetEdgeID(long v1, long v2) const; + void Clear(); + void Print() const; + long ExtractCCs(); + + Graph(); + virtual ~Graph(); + void Allocate(size_t nV, size_t nE); + + private: + size_t m_nCCs; + size_t m_nV; + size_t m_nE; + std::vector m_edges; + std::vector m_vertices; + + friend class HACD; + }; +} +#endif diff --git a/Extras/HACD/hacdHACD.cpp b/Extras/HACD/hacdHACD.cpp new file mode 100644 index 0000000..b7d16e5 --- /dev/null +++ b/Extras/HACD/hacdHACD.cpp @@ -0,0 +1,847 @@ +/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) + All rights reserved. + + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + 2. 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. + + 3. The names of the contributors may not 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 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif //_CRT_SECURE_NO_WARNINGS + +#include +#include "hacdGraph.h" +#include "hacdHACD.h" +#include "hacdICHull.h" +#include +#include +#include +#include + +bool gCancelRequest=false; +namespace HACD +{ + double HACD::Concavity(ICHull & ch, std::map & distPoints) + { + double concavity = 0.0; + double distance = 0.0; + std::map::iterator itDP(distPoints.begin()); + std::map::iterator itDPEnd(distPoints.end()); + for(; itDP != itDPEnd; ++itDP) + { + if (!(itDP->second).m_computed) + { + if (itDP->first >= 0) + { + distance = ch.ComputeDistance(itDP->first, m_points[itDP->first], m_normals[itDP->first], (itDP->second).m_computed, true); + } + else + { + distance = ch.ComputeDistance(itDP->first, m_facePoints[-itDP->first-1], m_faceNormals[-itDP->first-1], (itDP->second).m_computed, true); + } + } + else + { + distance = (itDP->second).m_dist; + } + if (concavity < distance) + { + concavity = distance; + } + } + return concavity; + } + + void HACD::CreateGraph() + { + // vertex to triangle adjacency information + std::vector< std::set > vertexToTriangles; + vertexToTriangles.resize(m_nPoints); + for(size_t t = 0; t < m_nTriangles; ++t) + { + vertexToTriangles[m_triangles[t].X()].insert(static_cast(t)); + vertexToTriangles[m_triangles[t].Y()].insert(static_cast(t)); + vertexToTriangles[m_triangles[t].Z()].insert(static_cast(t)); + } + + m_graph.Clear(); + m_graph.Allocate(m_nTriangles, 5 * m_nTriangles); + unsigned long long tr1[3]; + unsigned long long tr2[3]; + long i1, j1, k1, i2, j2, k2; + long t1, t2; + for (size_t v = 0; v < m_nPoints; v++) + { + std::set::const_iterator it1(vertexToTriangles[v].begin()), itEnd(vertexToTriangles[v].end()); + for(; it1 != itEnd; ++it1) + { + t1 = *it1; + i1 = m_triangles[t1].X(); + j1 = m_triangles[t1].Y(); + k1 = m_triangles[t1].Z(); + tr1[0] = GetEdgeIndex(i1, j1); + tr1[1] = GetEdgeIndex(j1, k1); + tr1[2] = GetEdgeIndex(k1, i1); + std::set::const_iterator it2(it1); + for(++it2; it2 != itEnd; ++it2) + { + t2 = *it2; + i2 = m_triangles[t2].X(); + j2 = m_triangles[t2].Y(); + k2 = m_triangles[t2].Z(); + tr2[0] = GetEdgeIndex(i2, j2); + tr2[1] = GetEdgeIndex(j2, k2); + tr2[2] = GetEdgeIndex(k2, i2); + int shared = 0; + for(int i = 0; i < 3; ++i) + { + for(int j = 0; j < 3; ++j) + { + if (tr1[i] == tr2[j]) + { + shared++; + } + } + } + if (shared == 1) // two triangles are connected if they share exactly one edge + { + m_graph.AddEdge(t1, t2); + } + } + } + } + if (m_ccConnectDist >= 0.0) + { + m_graph.ExtractCCs(); + if (m_graph.m_nCCs > 1) + { + std::vector< std::set > cc2V; + cc2V.resize(m_graph.m_nCCs); + long cc; + for(size_t t = 0; t < m_nTriangles; ++t) + { + cc = m_graph.m_vertices[t].m_cc; + cc2V[cc].insert(m_triangles[t].X()); + cc2V[cc].insert(m_triangles[t].Y()); + cc2V[cc].insert(m_triangles[t].Z()); + } + + for(size_t cc1 = 0; cc1 < m_graph.m_nCCs; ++cc1) + { + for(size_t cc2 = cc1+1; cc2 < m_graph.m_nCCs; ++cc2) + { + std::set::const_iterator itV1(cc2V[cc1].begin()), itVEnd1(cc2V[cc1].end()); + for(; itV1 != itVEnd1; ++itV1) + { + double distC1C2 = std::numeric_limits::max(); + double dist; + t1 = -1; + t2 = -1; + std::set::const_iterator itV2(cc2V[cc2].begin()), itVEnd2(cc2V[cc2].end()); + for(; itV2 != itVEnd2; ++itV2) + { + dist = (m_points[*itV1] - m_points[*itV2]).GetNorm(); + if (dist < distC1C2) + { + distC1C2 = dist; + t1 = *vertexToTriangles[*itV1].begin(); + + std::set::const_iterator it2(vertexToTriangles[*itV2].begin()), + it2End(vertexToTriangles[*itV2].end()); + t2 = -1; + for(; it2 != it2End; ++it2) + { + if (*it2 != t1) + { + t2 = *it2; + break; + } + } + } + } + if (distC1C2 <= m_ccConnectDist && t1 > 0 && t2 > 0) + { + + m_graph.AddEdge(t1, t2); + } + } + } + } + } + } + } + void HACD::InitializeDualGraph() + { + long i, j, k; + Vec3 u, v, w, normal; + delete [] m_normals; + m_normals = new Vec3[m_nPoints]; + if (m_addFacesPoints) + { + delete [] m_facePoints; + delete [] m_faceNormals; + m_facePoints = new Vec3[m_nTriangles]; + m_faceNormals = new Vec3[m_nTriangles]; + } + memset(m_normals, 0, sizeof(Vec3) * m_nPoints); + for(unsigned long f = 0; f < m_nTriangles; f++) + { + if (m_callBack) (*m_callBack)("+ InitializeDualGraph\n", f, m_nTriangles, 0); + + if (gCancelRequest) + return; + + i = m_triangles[f].X(); + j = m_triangles[f].Y(); + k = m_triangles[f].Z(); + + m_graph.m_vertices[f].m_distPoints[i].m_distOnly = false; + m_graph.m_vertices[f].m_distPoints[j].m_distOnly = false; + m_graph.m_vertices[f].m_distPoints[k].m_distOnly = false; + + ICHull * ch = new ICHull; + m_graph.m_vertices[f].m_convexHull = ch; + ch->AddPoint(m_points[i], i); + ch->AddPoint(m_points[j], j); + ch->AddPoint(m_points[k], k); + ch->SetDistPoints(&m_graph.m_vertices[f].m_distPoints); + + u = m_points[j] - m_points[i]; + v = m_points[k] - m_points[i]; + w = m_points[k] - m_points[j]; + normal = u ^ v; + + m_normals[i] += normal; + m_normals[j] += normal; + m_normals[k] += normal; + + m_graph.m_vertices[f].m_surf = normal.GetNorm(); + m_graph.m_vertices[f].m_perimeter = u.GetNorm() + v.GetNorm() + w.GetNorm(); + + normal.Normalize(); + + m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(i,j)); + m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(j,k)); + m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(k,i)); + if(m_addFacesPoints) + { + m_faceNormals[f] = normal; + m_facePoints[f] = (m_points[i] + m_points[j] + m_points[k]) / 3.0; + m_graph.m_vertices[f].m_distPoints[-static_cast(f)-1].m_distOnly = true; + } + if (m_addExtraDistPoints) + {// we need a kd-tree structure to accelerate this part! + long i1, j1, k1; + Vec3 u1, v1, normal1; + normal = -normal; + double distance = 0.0; + double distMin = 0.0; + size_t faceIndex = m_nTriangles; + Vec3 seedPoint((m_points[i] + m_points[j] + m_points[k]) / 3.0); + long nhit = 0; + for(size_t f1 = 0; f1 < m_nTriangles; f1++) + { + i1 = m_triangles[f1].X(); + j1 = m_triangles[f1].Y(); + k1 = m_triangles[f1].Z(); + u1 = m_points[j1] - m_points[i1]; + v1 = m_points[k1] - m_points[i1]; + normal1 = (u1 ^ v1); + if (normal * normal1 > 0.0) + { + nhit = IntersectRayTriangle(Vec3(seedPoint.X(), seedPoint.Y(), seedPoint.Z()), + Vec3(normal.X(), normal.Y(), normal.Z()), + Vec3(m_points[i1].X(), m_points[i1].Y(), m_points[i1].Z()), + Vec3(m_points[j1].X(), m_points[j1].Y(), m_points[j1].Z()), + Vec3(m_points[k1].X(), m_points[k1].Y(), m_points[k1].Z()), + distance); + if ((nhit==1) && ((distMin > distance) || (faceIndex == m_nTriangles))) + { + distMin = distance; + faceIndex = f1; + } + + } + } + if (faceIndex < m_nTriangles ) + { + i1 = m_triangles[faceIndex].X(); + j1 = m_triangles[faceIndex].Y(); + k1 = m_triangles[faceIndex].Z(); + m_graph.m_vertices[f].m_distPoints[i1].m_distOnly = true; + m_graph.m_vertices[f].m_distPoints[j1].m_distOnly = true; + m_graph.m_vertices[f].m_distPoints[k1].m_distOnly = true; + if (m_addFacesPoints) + { + m_graph.m_vertices[f].m_distPoints[-static_cast(faceIndex)-1].m_distOnly = true; + } + } + } + } + for (size_t v = 0; v < m_nPoints; v++) + { + m_normals[v].Normalize(); + } + } + + void HACD::NormalizeData() + { + if (m_nPoints == 0) + { + return; + } + m_barycenter = m_points[0]; + Vec3 min = m_points[0]; + Vec3 max = m_points[0]; + Real x, y, z; + for (size_t v = 1; v < m_nPoints ; v++) + { + m_barycenter += m_points[v]; + x = m_points[v].X(); + y = m_points[v].Y(); + z = m_points[v].Z(); + if ( x < min.X()) min.X() = x; + else if ( x > max.X()) max.X() = x; + if ( y < min.Y()) min.Y() = y; + else if ( y > max.Y()) max.Y() = y; + if ( z < min.Z()) min.Z() = z; + else if ( z > max.Z()) max.Z() = z; + } + m_barycenter /= static_cast(m_nPoints); + m_diag = (max-min).GetNorm(); + const Real invDiag = static_cast(2.0 * m_scale / m_diag); + if (m_diag != 0.0) + { + for (size_t v = 0; v < m_nPoints ; v++) + { + m_points[v] = (m_points[v] - m_barycenter) * invDiag; + } + } + } + void HACD::DenormalizeData() + { + if (m_nPoints == 0) + { + return; + } + if (m_diag != 0.0) + { + const Real diag = static_cast(m_diag / (2.0 * m_scale)); + for (size_t v = 0; v < m_nPoints ; v++) + { + m_points[v] = m_points[v] * diag + m_barycenter; + } + } + } + HACD::HACD(void) + { + m_convexHulls = 0; + m_triangles = 0; + m_points = 0; + m_normals = 0; + m_nTriangles = 0; + m_nPoints = 0; + m_nClusters = 0; + m_concavity = 0.0; + m_diag = 1.0; + m_barycenter = Vec3(0.0, 0.0,0.0); + m_alpha = 0.1; + m_beta = 0.1; + m_nVerticesPerCH = 30; + m_callBack = 0; + m_addExtraDistPoints = false; + m_addNeighboursDistPoints = false; + m_scale = 1000.0; + m_partition = 0; + m_nMinClusters = 3; + m_facePoints = 0; + m_faceNormals = 0; + m_ccConnectDist = 30; + } + HACD::~HACD(void) + { + delete [] m_normals; + delete [] m_convexHulls; + delete [] m_partition; + delete [] m_facePoints; + delete [] m_faceNormals; + } + int iteration = 0; + void HACD::ComputeEdgeCost(size_t e) + { + GraphEdge & gE = m_graph.m_edges[e]; + long v1 = gE.m_v1; + long v2 = gE.m_v2; + + if (m_graph.m_vertices[v2].m_distPoints.size()>m_graph.m_vertices[v1].m_distPoints.size()) + { + gE.m_v1 = v2; + gE.m_v2 = v1; + //std::swap(v1, v2); + std::swap(v1, v2); + } + GraphVertex & gV1 = m_graph.m_vertices[v1]; + GraphVertex & gV2 = m_graph.m_vertices[v2]; + + // delete old convex-hull + delete gE.m_convexHull; + // create the edge's convex-hull + ICHull * ch = new ICHull; + gE.m_convexHull = ch; + (*ch) = (*gV1.m_convexHull); + + // update distPoints + gE.m_distPoints = gV1.m_distPoints; + std::map::iterator itDP(gV2.m_distPoints.begin()); + std::map::iterator itDPEnd(gV2.m_distPoints.end()); + std::map::iterator itDP1; + + for(; itDP != itDPEnd; ++itDP) + { + itDP1 = gE.m_distPoints.find(itDP->first); + if (itDP1 == gE.m_distPoints.end()) + { + gE.m_distPoints[itDP->first].m_distOnly = (itDP->second).m_distOnly; + if ( !(itDP->second).m_distOnly ) + { + ch->AddPoint(m_points[itDP->first], itDP->first); + } + } + else + { + if ( (itDP1->second).m_distOnly && !(itDP->second).m_distOnly) + { + gE.m_distPoints[itDP->first].m_distOnly = false; + ch->AddPoint(m_points[itDP->first], itDP->first); + } + } + } + + ch->SetDistPoints(&gE.m_distPoints); + // create the convex-hull + while (ch->Process() == ICHullErrorInconsistent) // if we face problems when constructing the visual-hull. really ugly!!!! + { +// if (m_callBack) (*m_callBack)("\t Problem with convex-hull construction [HACD::ComputeEdgeCost]\n", 0.0, 0.0, 0); + ch = new ICHull; + CircularList & verticesCH = (gE.m_convexHull)->GetMesh().m_vertices; + size_t nV = verticesCH.GetSize(); + long ptIndex = 0; + verticesCH.Next(); + for(size_t v = 1; v < nV; ++v) + { + ptIndex = verticesCH.GetHead()->GetData().m_name; + ch->AddPoint(m_points[ptIndex], ptIndex); + verticesCH.Next(); + } + delete gE.m_convexHull; + gE.m_convexHull = ch; + } + double volume = 0.0; + double concavity = 0.0; + if (ch->IsFlat()) + { + bool insideHull; + std::map::iterator itDP(gE.m_distPoints.begin()); + std::map::iterator itDPEnd(gE.m_distPoints.end()); + for(; itDP != itDPEnd; ++itDP) + { + if (itDP->first >= 0) + { + concavity = std::max(concavity, ch->ComputeDistance(itDP->first, m_points[itDP->first], m_normals[itDP->first], insideHull, false)); + } + } + } + else + { + if (m_addNeighboursDistPoints) + { // add distance points from adjacent clusters + std::set eEdges; + std::set_union(gV1.m_edges.begin(), + gV1.m_edges.end(), + gV2.m_edges.begin(), + gV2.m_edges.end(), + std::inserter( eEdges, eEdges.begin() ) ); + + std::set::const_iterator ed(eEdges.begin()); + std::set::const_iterator itEnd(eEdges.end()); + long a, b, c; + for(; ed != itEnd; ++ed) + { + a = m_graph.m_edges[*ed].m_v1; + b = m_graph.m_edges[*ed].m_v2; + if ( a != v2 && a != v1) + { + c = a; + } + else if ( b != v2 && b != v1) + { + c = b; + } + else + { + c = -1; + } + if ( c > 0) + { + GraphVertex & gVC = m_graph.m_vertices[c]; + std::map::iterator itDP(gVC.m_distPoints.begin()); + std::map::iterator itDPEnd(gVC.m_distPoints.end()); + std::map::iterator itDP1; + for(; itDP != itDPEnd; ++itDP) + { + itDP1 = gE.m_distPoints.find(itDP->first); + if (itDP1 == gE.m_distPoints.end()) + { + if (itDP->first >= 0 && itDP1 == gE.m_distPoints.end() && ch->IsInside(m_points[itDP->first])) + { + gE.m_distPoints[itDP->first].m_distOnly = true; + } + else if (itDP->first < 0 && ch->IsInside(m_facePoints[-itDP->first-1])) + { + gE.m_distPoints[itDP->first].m_distOnly = true; + } + } + } + } + } + } + concavity = Concavity(*ch, gE.m_distPoints); + } + + // compute boudary edges + double perimeter = 0.0; + double surf = 1.0; + if (m_alpha > 0.0) + { + gE.m_boudaryEdges.clear(); + std::set_symmetric_difference (gV1.m_boudaryEdges.begin(), + gV1.m_boudaryEdges.end(), + gV2.m_boudaryEdges.begin(), + gV2.m_boudaryEdges.end(), + std::inserter( gE.m_boudaryEdges, + gE.m_boudaryEdges.begin() ) ); + + std::set::const_iterator itBE(gE.m_boudaryEdges.begin()); + std::set::const_iterator itBEEnd(gE.m_boudaryEdges.end()); + for(; itBE != itBEEnd; ++itBE) + { + perimeter += (m_points[static_cast((*itBE) >> 32)] - + m_points[static_cast((*itBE) & 0xFFFFFFFFULL)]).GetNorm(); + } + surf = gV1.m_surf + gV2.m_surf; + } + double ratio = perimeter * perimeter / (4.0 * sc_pi * surf); + gE.m_volume = (m_beta == 0.0)?0.0:ch->ComputeVolume()/pow(m_scale, 3.0); // cluster's volume + gE.m_surf = surf; // cluster's area + gE.m_perimeter = perimeter; // cluster's perimeter + gE.m_concavity = concavity; // cluster's concavity + gE.m_error = static_cast(concavity + m_alpha * ratio + m_beta * volume); // cluster's priority + } + bool HACD::InitializePriorityQueue() + { + m_pqueue.reserve(m_graph.m_nE + 100); + for (size_t e=0; e < m_graph.m_nE; ++e) + { + ComputeEdgeCost(static_cast(e)); + m_pqueue.push(GraphEdgePriorityQueue(static_cast(e), m_graph.m_edges[e].m_error)); + } + return true; + } + void HACD::Simplify() + { + long v1 = -1; + long v2 = -1; + double progressOld = -1.0; + double progress = 0.0; + double globalConcavity = 0.0; + char msg[1024]; + double ptgStep = 1.0; + while ( (globalConcavity < m_concavity) && + (m_graph.GetNVertices() > m_nMinClusters) && + (m_graph.GetNEdges() > 0)) + { + progress = 100.0-m_graph.GetNVertices() * 100.0 / m_nTriangles; + if (fabs(progress-progressOld) > ptgStep && m_callBack) + { + sprintf(msg, "%3.2f %% V = %lu \t C = %f \t \t \r", progress, static_cast(m_graph.GetNVertices()), globalConcavity); + (*m_callBack)(msg, progress, globalConcavity, m_graph.GetNVertices()); + progressOld = progress; + if (progress > 99.0) + { + ptgStep = 0.01; + } + else if (progress > 90.0) + { + ptgStep = 0.1; + } + } + + GraphEdgePriorityQueue currentEdge(0,0.0); + bool done = false; + do + { + done = false; + if (m_pqueue.size() == 0) + { + done = true; + break; + } + currentEdge = m_pqueue.top(); + m_pqueue.pop(); + } + while ( m_graph.m_edges[currentEdge.m_name].m_deleted || + m_graph.m_edges[currentEdge.m_name].m_error != currentEdge.m_priority); + + + if (m_graph.m_edges[currentEdge.m_name].m_concavity < m_concavity && !done) + { + globalConcavity = std::max(globalConcavity ,m_graph.m_edges[currentEdge.m_name].m_concavity); + v1 = m_graph.m_edges[currentEdge.m_name].m_v1; + v2 = m_graph.m_edges[currentEdge.m_name].m_v2; + // update vertex info + m_graph.m_vertices[v1].m_error = m_graph.m_edges[currentEdge.m_name].m_error; + m_graph.m_vertices[v1].m_surf = m_graph.m_edges[currentEdge.m_name].m_surf; + m_graph.m_vertices[v1].m_volume = m_graph.m_edges[currentEdge.m_name].m_volume; + m_graph.m_vertices[v1].m_concavity = m_graph.m_edges[currentEdge.m_name].m_concavity; + m_graph.m_vertices[v1].m_perimeter = m_graph.m_edges[currentEdge.m_name].m_perimeter; + m_graph.m_vertices[v1].m_distPoints = m_graph.m_edges[currentEdge.m_name].m_distPoints; + (*m_graph.m_vertices[v1].m_convexHull) = (*m_graph.m_edges[currentEdge.m_name].m_convexHull); + (m_graph.m_vertices[v1].m_convexHull)->SetDistPoints(&(m_graph.m_vertices[v1].m_distPoints)); + m_graph.m_vertices[v1].m_boudaryEdges = m_graph.m_edges[currentEdge.m_name].m_boudaryEdges; + + // We apply the optimal ecol +// std::cout << "v1 " << v1 << " v2 " << v2 << std::endl; + m_graph.EdgeCollapse(v1, v2); + // recompute the adjacent edges costs + std::set::const_iterator itE(m_graph.m_vertices[v1].m_edges.begin()), + itEEnd(m_graph.m_vertices[v1].m_edges.end()); + for(; itE != itEEnd; ++itE) + { + size_t e = *itE; + ComputeEdgeCost(static_cast(e)); + m_pqueue.push(GraphEdgePriorityQueue(static_cast(e), m_graph.m_edges[e].m_error)); + } + } + else + { + break; + } + } + while (!m_pqueue.empty()) + { + m_pqueue.pop(); + } + + m_cVertices.clear(); + m_nClusters = m_graph.GetNVertices(); + m_cVertices.reserve(m_nClusters); + for (size_t p=0, v = 0; v != m_graph.m_vertices.size(); ++v) + { + if (!m_graph.m_vertices[v].m_deleted) + { + if (m_callBack) + { + char msg[1024]; + sprintf(msg, "\t CH \t %lu \t %lf \t %lf\n", static_cast(p), m_graph.m_vertices[v].m_concavity, m_graph.m_vertices[v].m_error); + (*m_callBack)(msg, 0.0, 0.0, m_nClusters); + p++; + } + m_cVertices.push_back(static_cast(v)); + } + } + if (m_callBack) + { + sprintf(msg, "# clusters = %lu \t C = %f\n", static_cast(m_nClusters), globalConcavity); + (*m_callBack)(msg, progress, globalConcavity, m_graph.GetNVertices()); + } + + } + + bool HACD::Compute(bool fullCH, bool exportDistPoints) + { + gCancelRequest = false; + + if ( !m_points || !m_triangles || !m_nPoints || !m_nTriangles) + { + return false; + } + size_t nV = m_nTriangles; + if (m_callBack) + { + std::ostringstream msg; + msg << "+ Mesh" << std::endl; + msg << "\t # vertices \t" << m_nPoints << std::endl; + msg << "\t # triangles \t" << m_nTriangles << std::endl; + msg << "+ Parameters" << std::endl; + msg << "\t min # of clusters \t" << m_nMinClusters << std::endl; + msg << "\t max concavity \t" << m_concavity << std::endl; + msg << "\t compacity weigth \t" << m_alpha << std::endl; + msg << "\t volume weigth \t" << m_beta << std::endl; + msg << "\t # vertices per convex-hull \t" << m_nVerticesPerCH << std::endl; + msg << "\t scale \t" << m_scale << std::endl; + msg << "\t add extra distance points \t" << m_addExtraDistPoints << std::endl; + msg << "\t add neighbours distance points \t" << m_addNeighboursDistPoints << std::endl; + msg << "\t add face distance points \t" << m_addFacesPoints << std::endl; + msg << "\t produce full convex-hulls \t" << fullCH << std::endl; + msg << "\t max. distance to connect CCs \t" << m_ccConnectDist << std::endl; + (*m_callBack)(msg.str().c_str(), 0.0, 0.0, nV); + } + if (m_callBack) (*m_callBack)("+ Normalizing Data\n", 0.0, 0.0, nV); + NormalizeData(); + if (m_callBack) (*m_callBack)("+ Creating Graph\n", 0.0, 0.0, nV); + CreateGraph(); + // Compute the surfaces and perimeters of all the faces + if (m_callBack) (*m_callBack)("+ Initializing Dual Graph\n", 0.0, 0.0, nV); + if (gCancelRequest) + return false; + + InitializeDualGraph(); + if (m_callBack) (*m_callBack)("+ Initializing Priority Queue\n", 0.0, 0.0, nV); + if (gCancelRequest) + return false; + + InitializePriorityQueue(); + // we simplify the graph + if (m_callBack) (*m_callBack)("+ Simplification ...\n", 0.0, 0.0, m_nTriangles); + Simplify(); + if (m_callBack) (*m_callBack)("+ Denormalizing Data\n", 0.0, 0.0, m_nClusters); + DenormalizeData(); + if (m_callBack) (*m_callBack)("+ Computing final convex-hulls\n", 0.0, 0.0, m_nClusters); + delete [] m_convexHulls; + m_convexHulls = new ICHull[m_nClusters]; + delete [] m_partition; + m_partition = new long [m_nTriangles]; + for (size_t p = 0; p != m_cVertices.size(); ++p) + { + size_t v = m_cVertices[p]; + m_partition[v] = static_cast(p); + for(size_t a = 0; a < m_graph.m_vertices[v].m_ancestors.size(); a++) + { + m_partition[m_graph.m_vertices[v].m_ancestors[a]] = static_cast(p); + } + // compute the convex-hull + const std::map & pointsCH = m_graph.m_vertices[v].m_distPoints; + std::map::const_iterator itCH(pointsCH.begin()); + std::map::const_iterator itCHEnd(pointsCH.end()); + for(; itCH != itCHEnd; ++itCH) + { + if (!(itCH->second).m_distOnly) + { + m_convexHulls[p].AddPoint(m_points[itCH->first], itCH->first); + } + } + m_convexHulls[p].SetDistPoints(&m_graph.m_vertices[v].m_distPoints); + if (fullCH) + { + m_convexHulls[p].Process(); + } + else + { + m_convexHulls[p].Process(static_cast(m_nVerticesPerCH)); + } + if (exportDistPoints) + { + itCH = pointsCH.begin(); + for(; itCH != itCHEnd; ++itCH) + { + if ((itCH->second).m_distOnly) + { + if (itCH->first >= 0) + { + m_convexHulls[p].AddPoint(m_points[itCH->first], itCH->first); + } + else + { + m_convexHulls[p].AddPoint(m_facePoints[-itCH->first-1], itCH->first); + } + } + } + } + } + return true; + } + + size_t HACD::GetNTrianglesCH(size_t numCH) const + { + if (numCH >= m_nClusters) + { + return 0; + } + return m_convexHulls[numCH].GetMesh().GetNTriangles(); + } + size_t HACD::GetNPointsCH(size_t numCH) const + { + if (numCH >= m_nClusters) + { + return 0; + } + return m_convexHulls[numCH].GetMesh().GetNVertices(); + } + + bool HACD::GetCH(size_t numCH, Vec3 * const points, Vec3 * const triangles) + { + if (numCH >= m_nClusters) + { + return false; + } + m_convexHulls[numCH].GetMesh().GetIFS(points, triangles); + return true; + } + + bool HACD::Save(const char * fileName, bool uniColor, long numCluster) const + { + std::ofstream fout(fileName); + if (fout.is_open()) + { + if (m_callBack) + { + char msg[1024]; + sprintf(msg, "Saving %s\n", fileName); + (*m_callBack)(msg, 0.0, 0.0, m_graph.GetNVertices()); + } + Material mat; + if (numCluster < 0) + { + for (size_t p = 0; p != m_nClusters; ++p) + { + if (!uniColor) + { + mat.m_diffuseColor.X() = mat.m_diffuseColor.Y() = mat.m_diffuseColor.Z() = 0.0; + while (mat.m_diffuseColor.X() == mat.m_diffuseColor.Y() || + mat.m_diffuseColor.Z() == mat.m_diffuseColor.Y() || + mat.m_diffuseColor.Z() == mat.m_diffuseColor.X() ) + { + mat.m_diffuseColor.X() = (rand()%100) / 100.0; + mat.m_diffuseColor.Y() = (rand()%100) / 100.0; + mat.m_diffuseColor.Z() = (rand()%100) / 100.0; + } + } + m_convexHulls[p].GetMesh().SaveVRML2(fout, mat); + } + } + else if (numCluster < static_cast(m_cVertices.size())) + { + m_convexHulls[numCluster].GetMesh().SaveVRML2(fout, mat); + } + fout.close(); + return true; + } + else + { + if (m_callBack) + { + char msg[1024]; + sprintf(msg, "Error saving %s\n", fileName); + (*m_callBack)(msg, 0.0, 0.0, m_graph.GetNVertices()); + } + return false; + } + } +} diff --git a/Extras/HACD/hacdHACD.h b/Extras/HACD/hacdHACD.h new file mode 100644 index 0000000..c49e370 --- /dev/null +++ b/Extras/HACD/hacdHACD.h @@ -0,0 +1,282 @@ +/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) + All rights reserved. + + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + 2. 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. + + 3. The names of the contributors may not 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 HOLDER 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. + */ +#pragma once +#ifndef HACD_HACD_H +#define HACD_HACD_H +#include "hacdVersion.h" +#include "hacdVector.h" +#include "hacdGraph.h" +#include "hacdICHull.h" +#include +#include +#include +#include + +namespace HACD +{ + const double sc_pi = 3.14159265; + class HACD; + + // just to be able to set the capcity of the container + + template, class _Pr = std::less > + class reservable_priority_queue: public std::priority_queue<_Ty, _Container, _Pr> + { + typedef typename std::priority_queue<_Ty, _Container, _Pr>::size_type size_type; + public: + reservable_priority_queue(size_type capacity = 0) { reserve(capacity); }; + void reserve(size_type capacity) { this->c.reserve(capacity); } + size_type capacity() const { return this->c.capacity(); } + }; + + //! priority queque element + class GraphEdgePriorityQueue + { + public: + //! Constructor + //! @param name edge's id + //! @param priority edge's priority + GraphEdgePriorityQueue(long name, Real priority) + { + m_name = name; + m_priority = priority; + } + //! Destructor + ~GraphEdgePriorityQueue(void){} + private: + long m_name; //!< edge name + Real m_priority; //!< priority + //! Operator < for GraphEdgePQ + friend bool operator<(const GraphEdgePriorityQueue & lhs, const GraphEdgePriorityQueue & rhs); + //! Operator > for GraphEdgePQ + friend bool operator>(const GraphEdgePriorityQueue & lhs, const GraphEdgePriorityQueue & rhs); + friend class HACD; + }; + inline bool operator<(const GraphEdgePriorityQueue & lhs, const GraphEdgePriorityQueue & rhs) + { + return lhs.m_priority(const GraphEdgePriorityQueue & lhs, const GraphEdgePriorityQueue & rhs) + { + return lhs.m_priority>rhs.m_priority; + } + typedef bool (*CallBackFunction)(const char *, double, double, size_t); + + //! Provides an implementation of the Hierarchical Approximate Convex Decomposition (HACD) technique described in "A Simple and Efficient Approach for 3D Mesh Approximate Convex Decomposition" Game Programming Gems 8 - Chapter 2.8, p.202. A short version of the chapter was published in ICIP09 and is available at ftp://ftp.elet.polimi.it/users/Stefano.Tubaro/ICIP_USB_Proceedings_v2/pdfs/0003501.pdf + class HACD + { + public: + + //! Gives the triangles partitionas an array of size m_nTriangles where the i-th element specifies the cluster to which belong the i-th triangle + //! @return triangles partition + const long * const GetPartition() const { return m_partition;} + //! Sets the scale factor + //! @param scale scale factor + void SetScaleFactor(double scale) { m_scale = scale;} + //! Gives the scale factor + //! @return scale factor + const double GetScaleFactor() const { return m_scale;} + //! Sets the call-back function + //! @param callBack pointer to the call-back function + void SetCallBack(CallBackFunction callBack) { m_callBack = callBack;} + //! Gives the call-back function + //! @return pointer to the call-back function + const CallBackFunction GetCallBack() const { return m_callBack;} + + //! Specifies whether faces points should be added when computing the concavity + //! @param addFacesPoints true = faces points should be added + void SetAddFacesPoints(bool addFacesPoints) { m_addFacesPoints = addFacesPoints;} + //! Specifies wheter faces points should be added when computing the concavity + //! @return true = faces points should be added + const bool GetAddFacesPoints() const { return m_addFacesPoints;} + //! Specifies whether extra points should be added when computing the concavity + //! @param addExteraDistPoints true = extra points should be added + void SetAddExtraDistPoints(bool addExtraDistPoints) { m_addExtraDistPoints = addExtraDistPoints;} + //! Specifies wheter extra points should be added when computing the concavity + //! @return true = extra points should be added + const bool GetAddExtraDistPoints() const { return m_addExtraDistPoints;} + //! Specifies whether extra points should be added when computing the concavity + //! @param addExteraDistPoints true = extra points should be added + void SetAddNeighboursDistPoints(bool addNeighboursDistPoints) { m_addNeighboursDistPoints = addNeighboursDistPoints;} + //! Specifies wheter extra points should be added when computing the concavity + //! @return true = extra points should be added + const bool GetAddNeighboursDistPoints() const { return m_addNeighboursDistPoints;} + //! Sets the points of the input mesh (Remark: the input points will be scaled and shifted. Use DenormalizeData() to invert those operations) + //! @param points pointer to the input points + void SetPoints(Vec3 * points) { m_points = points;} + //! Gives the points of the input mesh (Remark: the input points will be scaled and shifted. Use DenormalizeData() to invert those operations) + //! @return pointer to the input points + const Vec3 * GetPoints() const { return m_points;} + //! Sets the triangles of the input mesh. + //! @param triangles points pointer to the input points + void SetTriangles(Vec3 * triangles) { m_triangles = triangles;} + //! Gives the triangles in the input mesh + //! @return pointer to the input triangles + const Vec3 * GetTriangles() const { return m_triangles;} + //! Sets the number of points in the input mesh. + //! @param nPoints number of points the input mesh + void SetNPoints(size_t nPoints) { m_nPoints = nPoints;} + //! Gives the number of points in the input mesh. + //! @return number of points the input mesh + const size_t GetNPoints() const { return m_nPoints;} + //! Sets the number of triangles in the input mesh. + //! @param nTriangles number of triangles in the input mesh + void SetNTriangles(size_t nTriangles) { m_nTriangles = nTriangles;} + //! Gives the number of triangles in the input mesh. + //! @return number of triangles the input mesh + const size_t GetNTriangles() const { return m_nTriangles;} + //! Sets the minimum number of clusters to be generated. + //! @param nClusters minimum number of clusters + void SetNClusters(size_t nClusters) { m_nMinClusters = nClusters;} + //! Gives the number of generated clusters. + //! @return number of generated clusters + const size_t GetNClusters() const { return m_nClusters;} + //! Sets the maximum allowed concavity. + //! @param concavity maximum concavity + void SetConcavity(double concavity) { m_concavity = concavity;} + //! Gives the maximum allowed concavity. + //! @return maximum concavity + double GetConcavity() const { return m_concavity;} + //! Sets the maximum allowed distance to get CCs connected. + //! @param concavity maximum distance to get CCs connected + void SetConnectDist(double ccConnectDist) { m_ccConnectDist = ccConnectDist;} + //! Gives the maximum allowed distance to get CCs connected. + //! @return maximum distance to get CCs connected + double GetConnectDist() const { return m_ccConnectDist;} + //! Sets the volume weight. + //! @param beta volume weight + void SetVolumeWeight(double beta) { m_beta = beta;} + //! Gives the volume weight. + //! @return volume weight + double GetVolumeWeight() const { return m_beta;} + //! Sets the compacity weight (i.e. parameter alpha in ftp://ftp.elet.polimi.it/users/Stefano.Tubaro/ICIP_USB_Proceedings_v2/pdfs/0003501.pdf). + //! @param alpha compacity weight + void SetCompacityWeight(double alpha) { m_alpha = alpha;} + //! Gives the compacity weight (i.e. parameter alpha in ftp://ftp.elet.polimi.it/users/Stefano.Tubaro/ICIP_USB_Proceedings_v2/pdfs/0003501.pdf). + //! @return compacity weight + double GetCompacityWeight() const { return m_alpha;} + //! Sets the maximum number of vertices for each generated convex-hull. + //! @param nVerticesPerCH maximum # vertices per CH + void SetNVerticesPerCH(size_t nVerticesPerCH) { m_nVerticesPerCH = nVerticesPerCH;} + //! Gives the maximum number of vertices for each generated convex-hull. + //! @return maximum # vertices per CH + const size_t GetNVerticesPerCH() const { return m_nVerticesPerCH;} + //! Gives the number of vertices for the cluster number numCH. + //! @return number of vertices + size_t GetNPointsCH(size_t numCH) const; + //! Gives the number of triangles for the cluster number numCH. + //! @param numCH cluster's number + //! @return number of triangles + size_t GetNTrianglesCH(size_t numCH) const; + //! Gives the vertices and the triangles of the cluster number numCH. + //! @param numCH cluster's number + //! @param points pointer to the vector of points to be filled + //! @param triangles pointer to the vector of triangles to be filled + //! @return true if sucess + bool GetCH(size_t numCH, Vec3 * const points, Vec3 * const triangles); + //! Computes the HACD decomposition. + //! @param fullCH specifies whether to generate convex-hulls with a full or limited (i.e. < m_nVerticesPerCH) number of vertices + //! @param exportDistPoints specifies wheter distance points should ne exported or not (used only for debugging). + //! @return true if sucess + bool Compute(bool fullCH=false, bool exportDistPoints=false); + //! Saves the generated convex-hulls in a VRML 2.0 file. + //! @param fileName the output file name + //! @param uniColor specifies whether the different convex-hulls should have the same color or not + //! @param numCluster specifies the cluster to be saved, if numCluster < 0 export all clusters + //! @return true if sucess + bool Save(const char * fileName, bool uniColor, long numCluster=-1) const; + //! Shifts and scales to the data to have all the coordinates between 0.0 and 1000.0. + void NormalizeData(); + //! Inverse the operations applied by NormalizeData(). + void DenormalizeData(); + //! Constructor. + HACD(void); + //! Destructor. + ~HACD(void); + + private: + //! Gives the edge index. + //! @param a first vertex id + //! @param b second vertex id + //! @return edge's index + static unsigned long long GetEdgeIndex(unsigned long long a, unsigned long long b) + { + if (a > b) return (a << 32) + b; + else return (b << 32) + a; + } + //! Computes the concavity of a cluster. + //! @param ch the cluster's convex-hull + //! @param distPoints the cluster's points + //! @return cluster's concavity + double Concavity(ICHull & ch, std::map & distPoints); + //! Computes the perimeter of a cluster. + //! @param triIndices the cluster's triangles + //! @param distPoints the cluster's points + //! @return cluster's perimeter + double ComputePerimeter(const std::vector & triIndices) const; + //! Creates the Graph by associating to each mesh triangle a vertex in the graph and to each couple of adjacent triangles an edge in the graph. + void CreateGraph(); + //! Initializes the graph costs and computes the vertices normals + void InitializeDualGraph(); + //! Computes the cost of an edge + //! @param e edge's id + void ComputeEdgeCost(size_t e); + //! Initializes the priority queue + //! @param fast specifies whether fast mode is used + //! @return true if success + bool InitializePriorityQueue(); + //! Cleans the intersection between convex-hulls + void CleanClusters(); + //! Computes convex-hulls from partition information + //! @param fullCH specifies whether to generate convex-hulls with a full or limited (i.e. < m_nVerticesPerCH) number of vertices + void ComputeConvexHulls(bool fullCH); + //! Simplifies the graph + //! @param fast specifies whether fast mode is used + void Simplify(); + + private: + double m_scale; //>! scale factor used for NormalizeData() and DenormalizeData() + Vec3 * m_triangles; //>! pointer the triangles array + Vec3 * m_points; //>! pointer the points array + Vec3 * m_facePoints; //>! pointer to the faces points array + Vec3 * m_faceNormals; //>! pointer to the faces normals array + Vec3 * m_normals; //>! pointer the normals array + size_t m_nTriangles; //>! number of triangles in the original mesh + size_t m_nPoints; //>! number of vertices in the original mesh + size_t m_nClusters; //>! number of clusters + size_t m_nMinClusters; //>! minimum number of clusters + double m_ccConnectDist; //>! maximum allowed distance to connect CCs + double m_concavity; //>! maximum concavity + double m_alpha; //>! compacity weigth + double m_beta; //>! volume weigth + double m_diag; //>! length of the BB diagonal + Vec3 m_barycenter; //>! barycenter of the mesh + std::vector< long > m_cVertices; //>! array of vertices each belonging to a different cluster + ICHull * m_convexHulls; //>! convex-hulls associated with the final HACD clusters + Graph m_graph; //>! simplification graph + size_t m_nVerticesPerCH; //>! maximum number of vertices per convex-hull + reservable_priority_queue, + std::greater::value_type> > m_pqueue; //!> priority queue + HACD(const HACD & rhs); + CallBackFunction m_callBack; //>! call-back function + long * m_partition; //>! array of size m_nTriangles where the i-th element specifies the cluster to which belong the i-th triangle + bool m_addFacesPoints; //>! specifies whether to add faces points or not + bool m_addExtraDistPoints; //>! specifies whether to add extra points for concave shapes or not + bool m_addNeighboursDistPoints; //>! specifies whether to add extra points from adjacent clusters or not + + }; +} +#endif diff --git a/Extras/HACD/hacdICHull.cpp b/Extras/HACD/hacdICHull.cpp new file mode 100644 index 0000000..42c50b7 --- /dev/null +++ b/Extras/HACD/hacdICHull.cpp @@ -0,0 +1,1010 @@ +/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) + All rights reserved. + + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + 2. 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. + + 3. The names of the contributors may not 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 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "hacdICHull.h" +#include +namespace HACD +{ + const long ICHull::sc_dummyIndex = std::numeric_limits::max(); + ICHull::ICHull(void) + { + m_distPoints = 0; + m_isFlat = false; + m_dummyVertex = 0; + } + bool ICHull::AddPoints(const Vec3 * points, size_t nPoints) + { + if (!points) + { + return false; + } + CircularListElement * vertex = NULL; + for (size_t i = 0; i < nPoints; i++) + { + vertex = m_mesh.AddVertex(); + vertex->GetData().m_pos.X() = points[i].X(); + vertex->GetData().m_pos.Y() = points[i].Y(); + vertex->GetData().m_pos.Z() = points[i].Z(); + vertex->GetData().m_name = static_cast(i); + } + return true; + } + bool ICHull::AddPoints(std::vector< Vec3 > points) + { + CircularListElement * vertex = NULL; + for (size_t i = 0; i < points.size(); i++) + { + vertex = m_mesh.AddVertex(); + vertex->GetData().m_pos.X() = points[i].X(); + vertex->GetData().m_pos.Y() = points[i].Y(); + vertex->GetData().m_pos.Z() = points[i].Z(); + } + return true; + } + + bool ICHull::AddPoint(const Vec3 & point, long id) + { + if (AddPoints(&point, 1)) + { + m_mesh.m_vertices.GetData().m_name = id; + return true; + } + return false; + } + + ICHullError ICHull::Process() + { + unsigned long addedPoints = 0; + if (m_mesh.GetNVertices() < 3) + { + return ICHullErrorNotEnoughPoints; + } + if (m_mesh.GetNVertices() == 3) + { + m_isFlat = true; + CircularListElement * t1 = m_mesh.AddTriangle(); + CircularListElement * t2 = m_mesh.AddTriangle(); + CircularListElement * v0 = m_mesh.m_vertices.GetHead(); + CircularListElement * v1 = v0->GetNext(); + CircularListElement * v2 = v1->GetNext(); + // Compute the normal to the plane + Vec3 p0 = v0->GetData().m_pos; + Vec3 p1 = v1->GetData().m_pos; + Vec3 p2 = v2->GetData().m_pos; + m_normal = (p1-p0) ^ (p2-p0); + m_normal.Normalize(); + t1->GetData().m_vertices[0] = v0; + t1->GetData().m_vertices[1] = v1; + t1->GetData().m_vertices[2] = v2; + t2->GetData().m_vertices[0] = v1; + t2->GetData().m_vertices[1] = v2; + t2->GetData().m_vertices[2] = v2; + return ICHullErrorOK; + } + if (m_isFlat) + { + m_mesh.m_edges.Clear(); + m_mesh.m_triangles.Clear(); + m_isFlat = false; + } + if (m_mesh.GetNTriangles() == 0) // we have to create the first polyhedron + { + ICHullError res = DoubleTriangle(); + if (res != ICHullErrorOK) + { + return res; + } + else + { + addedPoints += 3; + } + } + CircularList & vertices = m_mesh.GetVertices(); + // go to the first added and not processed vertex + while (!(vertices.GetHead()->GetPrev()->GetData().m_tag)) + { + vertices.Prev(); + } + while (!vertices.GetData().m_tag) // not processed + { + vertices.GetData().m_tag = true; + if (ProcessPoint()) + { + addedPoints++; + CleanUp(addedPoints); + vertices.Next(); + if (!GetMesh().CheckConsistancy()) + { + return ICHullErrorInconsistent; + } + } + } + if (m_isFlat) + { + std::vector< CircularListElement * > trianglesToDuplicate; + size_t nT = m_mesh.GetNTriangles(); + for(size_t f = 0; f < nT; f++) + { + TMMTriangle & currentTriangle = m_mesh.m_triangles.GetHead()->GetData(); + if( currentTriangle.m_vertices[0]->GetData().m_name == sc_dummyIndex || + currentTriangle.m_vertices[1]->GetData().m_name == sc_dummyIndex || + currentTriangle.m_vertices[2]->GetData().m_name == sc_dummyIndex ) + { + m_trianglesToDelete.push_back(m_mesh.m_triangles.GetHead()); + for(int k = 0; k < 3; k++) + { + for(int h = 0; h < 2; h++) + { + if (currentTriangle.m_edges[k]->GetData().m_triangles[h] == m_mesh.m_triangles.GetHead()) + { + currentTriangle.m_edges[k]->GetData().m_triangles[h] = 0; + break; + } + } + } + } + else + { + trianglesToDuplicate.push_back(m_mesh.m_triangles.GetHead()); + } + m_mesh.m_triangles.Next(); + } + size_t nE = m_mesh.GetNEdges(); + for(size_t e = 0; e < nE; e++) + { + TMMEdge & currentEdge = m_mesh.m_edges.GetHead()->GetData(); + if( currentEdge.m_triangles[0] == 0 && currentEdge.m_triangles[1] == 0) + { + m_edgesToDelete.push_back(m_mesh.m_edges.GetHead()); + } + m_mesh.m_edges.Next(); + } + m_mesh.m_vertices.Delete(m_dummyVertex); + m_dummyVertex = 0; + size_t nV = m_mesh.GetNVertices(); + CircularList & vertices = m_mesh.GetVertices(); + for(size_t v = 0; v < nV; ++v) + { + vertices.GetData().m_tag = false; + vertices.Next(); + } + CleanEdges(); + CleanTriangles(); + CircularListElement * newTriangle; + for(size_t t = 0; t < trianglesToDuplicate.size(); t++) + { + newTriangle = m_mesh.AddTriangle(); + newTriangle->GetData().m_vertices[0] = trianglesToDuplicate[t]->GetData().m_vertices[1]; + newTriangle->GetData().m_vertices[1] = trianglesToDuplicate[t]->GetData().m_vertices[0]; + newTriangle->GetData().m_vertices[2] = trianglesToDuplicate[t]->GetData().m_vertices[2]; + } + } + return ICHullErrorOK; + } + ICHullError ICHull::Process(unsigned long nPointsCH) + { + unsigned long addedPoints = 0; + if (nPointsCH < 3 || m_mesh.GetNVertices() < 3) + { + return ICHullErrorNotEnoughPoints; + } + if (m_mesh.GetNVertices() == 3) + { + m_isFlat = true; + CircularListElement * t1 = m_mesh.AddTriangle(); + CircularListElement * t2 = m_mesh.AddTriangle(); + CircularListElement * v0 = m_mesh.m_vertices.GetHead(); + CircularListElement * v1 = v0->GetNext(); + CircularListElement * v2 = v1->GetNext(); + // Compute the normal to the plane + Vec3 p0 = v0->GetData().m_pos; + Vec3 p1 = v1->GetData().m_pos; + Vec3 p2 = v2->GetData().m_pos; + m_normal = (p1-p0) ^ (p2-p0); + m_normal.Normalize(); + t1->GetData().m_vertices[0] = v0; + t1->GetData().m_vertices[1] = v1; + t1->GetData().m_vertices[2] = v2; + t2->GetData().m_vertices[0] = v1; + t2->GetData().m_vertices[1] = v0; + t2->GetData().m_vertices[2] = v2; + return ICHullErrorOK; + } + + if (m_isFlat) + { + m_mesh.m_triangles.Clear(); + m_mesh.m_edges.Clear(); + m_isFlat = false; + } + + if (m_mesh.GetNTriangles() == 0) // we have to create the first polyhedron + { + ICHullError res = DoubleTriangle(); + if (res != ICHullErrorOK) + { + return res; + } + else + { + addedPoints += 3; + } + } + CircularList & vertices = m_mesh.GetVertices(); + while (!vertices.GetData().m_tag && addedPoints < nPointsCH) // not processed + { + if (!FindMaxVolumePoint()) + { + break; + } + vertices.GetData().m_tag = true; + if (ProcessPoint()) + { + addedPoints++; + CleanUp(addedPoints); + if (!GetMesh().CheckConsistancy()) + { + return ICHullErrorInconsistent; + } + vertices.Next(); + } + } + // delete remaining points + while (!vertices.GetData().m_tag) + { + vertices.Delete(); + } + if (m_isFlat) + { + std::vector< CircularListElement * > trianglesToDuplicate; + size_t nT = m_mesh.GetNTriangles(); + for(size_t f = 0; f < nT; f++) + { + TMMTriangle & currentTriangle = m_mesh.m_triangles.GetHead()->GetData(); + if( currentTriangle.m_vertices[0]->GetData().m_name == sc_dummyIndex || + currentTriangle.m_vertices[1]->GetData().m_name == sc_dummyIndex || + currentTriangle.m_vertices[2]->GetData().m_name == sc_dummyIndex ) + { + m_trianglesToDelete.push_back(m_mesh.m_triangles.GetHead()); + for(int k = 0; k < 3; k++) + { + for(int h = 0; h < 2; h++) + { + if (currentTriangle.m_edges[k]->GetData().m_triangles[h] == m_mesh.m_triangles.GetHead()) + { + currentTriangle.m_edges[k]->GetData().m_triangles[h] = 0; + break; + } + } + } + } + else + { + trianglesToDuplicate.push_back(m_mesh.m_triangles.GetHead()); + } + m_mesh.m_triangles.Next(); + } + size_t nE = m_mesh.GetNEdges(); + for(size_t e = 0; e < nE; e++) + { + TMMEdge & currentEdge = m_mesh.m_edges.GetHead()->GetData(); + if( currentEdge.m_triangles[0] == 0 && currentEdge.m_triangles[1] == 0) + { + m_edgesToDelete.push_back(m_mesh.m_edges.GetHead()); + } + m_mesh.m_edges.Next(); + } + m_mesh.m_vertices.Delete(m_dummyVertex); + m_dummyVertex = 0; + size_t nV = m_mesh.GetNVertices(); + CircularList & vertices = m_mesh.GetVertices(); + for(size_t v = 0; v < nV; ++v) + { + vertices.GetData().m_tag = false; + vertices.Next(); + } + CleanEdges(); + CleanTriangles(); + CircularListElement * newTriangle; + for(size_t t = 0; t < trianglesToDuplicate.size(); t++) + { + newTriangle = m_mesh.AddTriangle(); + newTriangle->GetData().m_vertices[0] = trianglesToDuplicate[t]->GetData().m_vertices[1]; + newTriangle->GetData().m_vertices[1] = trianglesToDuplicate[t]->GetData().m_vertices[0]; + newTriangle->GetData().m_vertices[2] = trianglesToDuplicate[t]->GetData().m_vertices[2]; + } + } + return ICHullErrorOK; + } + bool ICHull::FindMaxVolumePoint() + { + CircularList & vertices = m_mesh.GetVertices(); + CircularListElement * vMaxVolume = 0; + CircularListElement * vHeadPrev = vertices.GetHead()->GetPrev(); + + double maxVolume = 0.0; + double volume = 0.0; + + while (!vertices.GetData().m_tag) // not processed + { + if (ComputePointVolume(volume, false)) + { + if ( maxVolume < volume) + { + maxVolume = volume; + vMaxVolume = vertices.GetHead(); + } + vertices.Next(); + } + } + CircularListElement * vHead = vHeadPrev->GetNext(); + vertices.GetHead() = vHead; + + if (!vMaxVolume) + { + return false; + } + + if (vMaxVolume != vHead) + { + Vec3 pos = vHead->GetData().m_pos; + long id = vHead->GetData().m_name; + vHead->GetData().m_pos = vMaxVolume->GetData().m_pos; + vHead->GetData().m_name = vMaxVolume->GetData().m_name; + vMaxVolume->GetData().m_pos = pos; + vHead->GetData().m_name = id; + } + + + return true; + } + ICHullError ICHull::DoubleTriangle() + { + // find three non colinear points + m_isFlat = false; + CircularList & vertices = m_mesh.GetVertices(); + CircularListElement * v0 = vertices.GetHead(); + while( Colinear(v0->GetData().m_pos, + v0->GetNext()->GetData().m_pos, + v0->GetNext()->GetNext()->GetData().m_pos)) + { + if ( (v0 = v0->GetNext()) == vertices.GetHead()) + { + return ICHullErrorCoplanarPoints; + } + } + CircularListElement * v1 = v0->GetNext(); + CircularListElement * v2 = v1->GetNext(); + // mark points as processed + v0->GetData().m_tag = v1->GetData().m_tag = v2->GetData().m_tag = true; + + // create two triangles + CircularListElement * f0 = MakeFace(v0, v1, v2, 0); + MakeFace(v2, v1, v0, f0); + + // find a fourth non-coplanar point to form tetrahedron + CircularListElement * v3 = v2->GetNext(); + vertices.GetHead() = v3; + + double vol = Volume(v0->GetData().m_pos, v1->GetData().m_pos, v2->GetData().m_pos, v3->GetData().m_pos); + while (vol == 0.0 && !v3->GetNext()->GetData().m_tag) + { + v3 = v3->GetNext(); + vol = Volume(v0->GetData().m_pos, v1->GetData().m_pos, v2->GetData().m_pos, v3->GetData().m_pos); + } + if (vol == 0.0) + { + // compute the barycenter + Vec3 bary(0.0,0.0,0.0); + CircularListElement * vBary = v0; + do + { + bary += vBary->GetData().m_pos; + } + while ( (vBary = vBary->GetNext()) != v0); + bary /= static_cast(vertices.GetSize()); + + // Compute the normal to the plane + Vec3 p0 = v0->GetData().m_pos; + Vec3 p1 = v1->GetData().m_pos; + Vec3 p2 = v2->GetData().m_pos; + m_normal = (p1-p0) ^ (p2-p0); + m_normal.Normalize(); + // add dummy vertex placed at (bary + normal) + vertices.GetHead() = v2; + Vec3 newPt = bary + m_normal; + AddPoint(newPt, sc_dummyIndex); + m_dummyVertex = vertices.GetHead(); + m_isFlat = true; + v3 = v2->GetNext(); + vol = Volume(v0->GetData().m_pos, v1->GetData().m_pos, v2->GetData().m_pos, v3->GetData().m_pos); + return ICHullErrorOK; + } + else if (v3 != vertices.GetHead()) + { + TMMVertex temp; + temp.m_name = v3->GetData().m_name; + temp.m_pos = v3->GetData().m_pos; + v3->GetData().m_name = vertices.GetHead()->GetData().m_name; + v3->GetData().m_pos = vertices.GetHead()->GetData().m_pos; + vertices.GetHead()->GetData().m_name = temp.m_name; + vertices.GetHead()->GetData().m_pos = temp.m_pos; + } + return ICHullErrorOK; + } + CircularListElement * ICHull::MakeFace(CircularListElement * v0, + CircularListElement * v1, + CircularListElement * v2, + CircularListElement * fold) + { + CircularListElement * e0; + CircularListElement * e1; + CircularListElement * e2; + long index = 0; + if (!fold) // if first face to be created + { + e0 = m_mesh.AddEdge(); // create the three edges + e1 = m_mesh.AddEdge(); + e2 = m_mesh.AddEdge(); + } + else // otherwise re-use existing edges (in reverse order) + { + e0 = fold->GetData().m_edges[2]; + e1 = fold->GetData().m_edges[1]; + e2 = fold->GetData().m_edges[0]; + index = 1; + } + e0->GetData().m_vertices[0] = v0; e0->GetData().m_vertices[1] = v1; + e1->GetData().m_vertices[0] = v1; e1->GetData().m_vertices[1] = v2; + e2->GetData().m_vertices[0] = v2; e2->GetData().m_vertices[1] = v0; + // create the new face + CircularListElement * f = m_mesh.AddTriangle(); + f->GetData().m_edges[0] = e0; f->GetData().m_edges[1] = e1; f->GetData().m_edges[2] = e2; + f->GetData().m_vertices[0] = v0; f->GetData().m_vertices[1] = v1; f->GetData().m_vertices[2] = v2; + // link edges to face f + e0->GetData().m_triangles[index] = e1->GetData().m_triangles[index] = e2->GetData().m_triangles[index] = f; + return f; + } + CircularListElement * ICHull::MakeConeFace(CircularListElement * e, CircularListElement * p) + { + // create two new edges if they don't already exist + CircularListElement * newEdges[2]; + for(int i = 0; i < 2; ++i) + { + if ( !( newEdges[i] = e->GetData().m_vertices[i]->GetData().m_duplicate ) ) + { // if the edge doesn't exits add it and mark the vertex as duplicated + newEdges[i] = m_mesh.AddEdge(); + newEdges[i]->GetData().m_vertices[0] = e->GetData().m_vertices[i]; + newEdges[i]->GetData().m_vertices[1] = p; + e->GetData().m_vertices[i]->GetData().m_duplicate = newEdges[i]; + } + } + // make the new face + CircularListElement * newFace = m_mesh.AddTriangle(); + newFace->GetData().m_edges[0] = e; + newFace->GetData().m_edges[1] = newEdges[0]; + newFace->GetData().m_edges[2] = newEdges[1]; + MakeCCW(newFace, e, p); + for(int i=0; i < 2; ++i) + { + for(int j=0; j < 2; ++j) + { + if ( ! newEdges[i]->GetData().m_triangles[j] ) + { + newEdges[i]->GetData().m_triangles[j] = newFace; + break; + } + } + } + return newFace; + } + bool ICHull::ComputePointVolume(double &totalVolume, bool markVisibleFaces) + { + // mark visible faces + CircularListElement * fHead = m_mesh.GetTriangles().GetHead(); + CircularListElement * f = fHead; + CircularList & vertices = m_mesh.GetVertices(); + CircularListElement * vertex0 = vertices.GetHead(); + bool visible = false; + Vec3 pos0 = Vec3(vertex0->GetData().m_pos.X(), + vertex0->GetData().m_pos.Y(), + vertex0->GetData().m_pos.Z()); + double vol = 0.0; + totalVolume = 0.0; + Vec3 ver0, ver1, ver2; + do + { + ver0.X() = f->GetData().m_vertices[0]->GetData().m_pos.X(); + ver0.Y() = f->GetData().m_vertices[0]->GetData().m_pos.Y(); + ver0.Z() = f->GetData().m_vertices[0]->GetData().m_pos.Z(); + ver1.X() = f->GetData().m_vertices[1]->GetData().m_pos.X(); + ver1.Y() = f->GetData().m_vertices[1]->GetData().m_pos.Y(); + ver1.Z() = f->GetData().m_vertices[1]->GetData().m_pos.Z(); + ver2.X() = f->GetData().m_vertices[2]->GetData().m_pos.X(); + ver2.Y() = f->GetData().m_vertices[2]->GetData().m_pos.Y(); + ver2.Z() = f->GetData().m_vertices[2]->GetData().m_pos.Z(); + vol = Volume(ver0, ver1, ver2, pos0); + if ( vol < 0.0 ) + { + vol = fabs(vol); + totalVolume += vol; + if (markVisibleFaces) + { + f->GetData().m_visible = true; + m_trianglesToDelete.push_back(f); + } + visible = true; + } + f = f->GetNext(); + } + while (f != fHead); + + if (m_trianglesToDelete.size() == m_mesh.m_triangles.GetSize()) + { + for(size_t i = 0; i < m_trianglesToDelete.size(); i++) + { + m_trianglesToDelete[i]->GetData().m_visible = false; + } + visible = false; + } + // if no faces visible from p then p is inside the hull + if (!visible && markVisibleFaces) + { + vertices.Delete(); + m_trianglesToDelete.clear(); + return false; + } + return true; + } + bool ICHull::ProcessPoint() + { + double totalVolume = 0.0; + if (!ComputePointVolume(totalVolume, true)) + { + return false; + } + // Mark edges in interior of visible region for deletion. + // Create a new face based on each border edge + CircularListElement * v0 = m_mesh.GetVertices().GetHead(); + CircularListElement * eHead = m_mesh.GetEdges().GetHead(); + CircularListElement * e = eHead; + CircularListElement * tmp = 0; + long nvisible = 0; + m_edgesToDelete.clear(); + m_edgesToUpdate.clear(); + do + { + tmp = e->GetNext(); + nvisible = 0; + for(int k = 0; k < 2; k++) + { + if ( e->GetData().m_triangles[k]->GetData().m_visible ) + { + nvisible++; + } + } + if ( nvisible == 2) + { + m_edgesToDelete.push_back(e); + } + else if ( nvisible == 1) + { + e->GetData().m_newFace = MakeConeFace(e, v0); + m_edgesToUpdate.push_back(e); + } + e = tmp; + } + while (e != eHead); + return true; + } + bool ICHull::MakeCCW(CircularListElement * f, + CircularListElement * e, + CircularListElement * v) + { + // the visible face adjacent to e + CircularListElement * fv; + if (e->GetData().m_triangles[0]->GetData().m_visible) + { + fv = e->GetData().m_triangles[0]; + } + else + { + fv = e->GetData().m_triangles[1]; + } + + // set vertex[0] and vertex[1] to have the same orientation as the corresponding vertices of fv. + long i; // index of e->m_vertices[0] in fv + CircularListElement * v0 = e->GetData().m_vertices[0]; + CircularListElement * v1 = e->GetData().m_vertices[1]; + for(i = 0; fv->GetData().m_vertices[i] != v0; i++); + + if ( fv->GetData().m_vertices[(i+1) % 3] != e->GetData().m_vertices[1] ) + { + f->GetData().m_vertices[0] = v1; + f->GetData().m_vertices[1] = v0; + } + else + { + f->GetData().m_vertices[0] = v0; + f->GetData().m_vertices[1] = v1; + // swap edges + CircularListElement * tmp = f->GetData().m_edges[0]; + f->GetData().m_edges[0] = f->GetData().m_edges[1]; + f->GetData().m_edges[1] = tmp; + } + f->GetData().m_vertices[2] = v; + return true; + } + bool ICHull::CleanUp(unsigned long & addedPoints) + { + bool r0 = CleanEdges(); + bool r1 = CleanTriangles(); + bool r2 = CleanVertices(addedPoints); + return r0 && r1 && r2; + } + bool ICHull::CleanEdges() + { + // integrate the new faces into the data structure + CircularListElement * e; + const std::vector *>::iterator itEndUpdate = m_edgesToUpdate.end(); + for(std::vector *>::iterator it = m_edgesToUpdate.begin(); it != itEndUpdate; ++it) + { + e = *it; + if ( e->GetData().m_newFace ) + { + if ( e->GetData().m_triangles[0]->GetData().m_visible) + { + e->GetData().m_triangles[0] = e->GetData().m_newFace; + } + else + { + e->GetData().m_triangles[1] = e->GetData().m_newFace; + } + e->GetData().m_newFace = 0; + } + } + // delete edges maked for deletion + CircularList & edges = m_mesh.GetEdges(); + const std::vector *>::iterator itEndDelete = m_edgesToDelete.end(); + for(std::vector *>::iterator it = m_edgesToDelete.begin(); it != itEndDelete; ++it) + { + edges.Delete(*it); + } + m_edgesToDelete.clear(); + m_edgesToUpdate.clear(); + return true; + } + bool ICHull::CleanTriangles() + { + CircularList & triangles = m_mesh.GetTriangles(); + const std::vector *>::iterator itEndDelete = m_trianglesToDelete.end(); + for(std::vector *>::iterator it = m_trianglesToDelete.begin(); it != itEndDelete; ++it) + { + if (m_distPoints) + { + if (m_isFlat) + { + // to be updated + } + else + { + std::set::const_iterator itPEnd((*it)->GetData().m_incidentPoints.end()); + std::set::const_iterator itP((*it)->GetData().m_incidentPoints.begin()); + std::map::iterator itPoint; + for(; itP != itPEnd; ++itP) + { + itPoint = m_distPoints->find(*itP); + if (itPoint != m_distPoints->end()) + { + itPoint->second.m_computed = false; + } + } + } + } + triangles.Delete(*it); + } + m_trianglesToDelete.clear(); + return true; + } + bool ICHull::CleanVertices(unsigned long & addedPoints) + { + // mark all vertices incident to some undeleted edge as on the hull + CircularList & edges = m_mesh.GetEdges(); + CircularListElement * e = edges.GetHead(); + size_t nE = edges.GetSize(); + for(size_t i = 0; i < nE; i++) + { + e->GetData().m_vertices[0]->GetData().m_onHull = true; + e->GetData().m_vertices[1]->GetData().m_onHull = true; + e = e->GetNext(); + } + // delete all the vertices that have been processed but are not on the hull + CircularList & vertices = m_mesh.GetVertices(); + CircularListElement * vHead = vertices.GetHead(); + CircularListElement * v = vHead; + v = v->GetPrev(); + do + { + if (v->GetData().m_tag && !v->GetData().m_onHull) + { + CircularListElement * tmp = v->GetPrev(); + vertices.Delete(v); + v = tmp; + addedPoints--; + } + else + { + v->GetData().m_duplicate = 0; + v->GetData().m_onHull = false; + v = v->GetPrev(); + } + } + while (v->GetData().m_tag && v != vHead); + return true; + } + void ICHull::Clear() + { + m_mesh.Clear(); + m_edgesToDelete = std::vector *>(); + m_edgesToUpdate = std::vector *>(); + m_trianglesToDelete= std::vector *>(); + m_isFlat = false; + } + const ICHull & ICHull::operator=(ICHull & rhs) + { + if (&rhs != this) + { + m_mesh.Copy(rhs.m_mesh); + m_edgesToDelete = rhs.m_edgesToDelete; + m_edgesToUpdate = rhs.m_edgesToUpdate; + m_trianglesToDelete = rhs.m_trianglesToDelete; + m_isFlat = rhs.m_isFlat; + } + return (*this); + } + double ICHull::ComputeVolume() + { + size_t nV = m_mesh.m_vertices.GetSize(); + if (nV == 0 || m_isFlat) + { + return 0.0; + } + Vec3 bary(0.0, 0.0, 0.0); + for(size_t v = 0; v < nV; v++) + { + bary.X() += m_mesh.m_vertices.GetHead()->GetData().m_pos.X(); + bary.Y() += m_mesh.m_vertices.GetHead()->GetData().m_pos.Y(); + bary.Z() += m_mesh.m_vertices.GetHead()->GetData().m_pos.Z(); + m_mesh.m_vertices.Next(); + } + bary /= static_cast(nV); + + size_t nT = m_mesh.m_triangles.GetSize(); + Vec3 ver0, ver1, ver2; + double totalVolume = 0.0; + for(size_t t = 0; t < nT; t++) + { + ver0.X() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[0]->GetData().m_pos.X(); + ver0.Y() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[0]->GetData().m_pos.Y(); + ver0.Z() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[0]->GetData().m_pos.Z(); + ver1.X() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[1]->GetData().m_pos.X(); + ver1.Y() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[1]->GetData().m_pos.Y(); + ver1.Z() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[1]->GetData().m_pos.Z(); + ver2.X() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[2]->GetData().m_pos.X(); + ver2.Y() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[2]->GetData().m_pos.Y(); + ver2.Z() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[2]->GetData().m_pos.Z(); + totalVolume += Volume(ver0, ver1, ver2, bary); + m_mesh.m_triangles.Next(); + } + return totalVolume; + } + bool ICHull::IsInside(const Vec3 & pt0) + { + const Vec3 pt(pt0.X(), pt0.Y(), pt0.Z()); + if (m_isFlat) + { + size_t nT = m_mesh.m_triangles.GetSize(); + Vec3 ver0, ver1, ver2, a, b, c; + double u,v; + for(size_t t = 0; t < nT; t++) + { + ver0.X() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[0]->GetData().m_pos.X(); + ver0.Y() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[0]->GetData().m_pos.Y(); + ver0.Z() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[0]->GetData().m_pos.Z(); + ver1.X() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[1]->GetData().m_pos.X(); + ver1.Y() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[1]->GetData().m_pos.Y(); + ver1.Z() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[1]->GetData().m_pos.Z(); + ver2.X() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[2]->GetData().m_pos.X(); + ver2.Y() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[2]->GetData().m_pos.Y(); + ver2.Z() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[2]->GetData().m_pos.Z(); + a = ver1 - ver0; + b = ver2 - ver0; + c = pt - ver0; + u = c * a; + v = c * b; + if ( u >= 0.0 && u <= 1.0 && v >= 0.0 && u+v <= 1.0) + { + return true; + } + m_mesh.m_triangles.Next(); + } + return false; + } + else + { + size_t nT = m_mesh.m_triangles.GetSize(); + Vec3 ver0, ver1, ver2; + for(size_t t = 0; t < nT; t++) + { + ver0.X() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[0]->GetData().m_pos.X(); + ver0.Y() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[0]->GetData().m_pos.Y(); + ver0.Z() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[0]->GetData().m_pos.Z(); + ver1.X() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[1]->GetData().m_pos.X(); + ver1.Y() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[1]->GetData().m_pos.Y(); + ver1.Z() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[1]->GetData().m_pos.Z(); + ver2.X() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[2]->GetData().m_pos.X(); + ver2.Y() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[2]->GetData().m_pos.Y(); + ver2.Z() = m_mesh.m_triangles.GetHead()->GetData().m_vertices[2]->GetData().m_pos.Z(); + if (Volume(ver0, ver1, ver2, pt) < 0.0) + { + return false; + } + m_mesh.m_triangles.Next(); + } + return true; + } + } + double ICHull::ComputeDistance(long name, const Vec3 & pt, const Vec3 & normal, bool & insideHull, bool updateIncidentPoints) + { + Vec3 ptNormal(static_cast(normal.X()), + static_cast(normal.Y()), + static_cast(normal.Z())); + Vec3 p0( static_cast(pt.X()), + static_cast(pt.Y()), + static_cast(pt.Z())); + + if (m_isFlat) + { + double distance = 0.0; + Vec3 chNormal(static_cast(m_normal.X()), + static_cast(m_normal.Y()), + static_cast(m_normal.Z())); + ptNormal -= (ptNormal * chNormal) * chNormal; + if (ptNormal.GetNorm() > 0.0) + { + ptNormal.Normalize(); + long nameVE1; + long nameVE2; + Vec3 pa, pb, d0, d1, d2, d3; + Vec3 p1 = p0 + ptNormal; + Vec3 p2, p3; + double mua, mub, s; + const double EPS = 0.00000000001; + size_t nE = m_mesh.GetNEdges(); + for(size_t e = 0; e < nE; e++) + { + TMMEdge & currentEdge = m_mesh.m_edges.GetHead()->GetData(); + nameVE1 = currentEdge.m_vertices[0]->GetData().m_name; + nameVE2 = currentEdge.m_vertices[1]->GetData().m_name; + if (currentEdge.m_triangles[0] == 0 || currentEdge.m_triangles[1] == 0) + { + if ( nameVE1==name || nameVE2==name ) + { + return 0.0; + } + /* + if (debug) std::cout << "V" << name + << " E " << nameVE1 << " " << nameVE2 << std::endl; + */ + + p2.X() = currentEdge.m_vertices[0]->GetData().m_pos.X(); + p2.Y() = currentEdge.m_vertices[0]->GetData().m_pos.Y(); + p2.Z() = currentEdge.m_vertices[0]->GetData().m_pos.Z(); + p3.X() = currentEdge.m_vertices[1]->GetData().m_pos.X(); + p3.Y() = currentEdge.m_vertices[1]->GetData().m_pos.Y(); + p3.Z() = currentEdge.m_vertices[1]->GetData().m_pos.Z(); + d0 = p3 - p2; + if (d0.GetNorm() > 0.0) + { + if (IntersectLineLine(p0, p1, p2, p3, pa, pb, mua, mub)) + { + d1 = pa - p2; + d2 = pa - pb; + d3 = pa - p0; + mua = d1.GetNorm()/d0.GetNorm(); + mub = d1*d0; + s = d3*ptNormal; + if (d2.GetNorm() < EPS && mua <= 1.0 && mub>=0.0 && s>0.0) + { + distance = std::max(distance, d3.GetNorm()); + } + } + } + } + m_mesh.m_edges.Next(); + } + } + return distance; + } + else + { + Vec3 ptNormal(static_cast(normal.X()), + static_cast(normal.Y()), + static_cast(normal.Z())); + + Vec3 impact; + long nhit; + double dist; + double distance = 0.0; + size_t nT = m_mesh.GetNTriangles(); + insideHull = false; + CircularListElement * face = 0; + Vec3 ver0, ver1, ver2; + for(size_t f = 0; f < nT; f++) + { + TMMTriangle & currentTriangle = m_mesh.m_triangles.GetHead()->GetData(); + /* + if (debug) std::cout << "T " << currentTriangle.m_vertices[0]->GetData().m_name << " " + << currentTriangle.m_vertices[1]->GetData().m_name << " " + << currentTriangle.m_vertices[2]->GetData().m_name << std::endl; + */ + if (currentTriangle.m_vertices[0]->GetData().m_name == name || + currentTriangle.m_vertices[1]->GetData().m_name == name || + currentTriangle.m_vertices[2]->GetData().m_name == name) + { + nhit = 1; + dist = 0.0; + } + else + { + ver0.X() = currentTriangle.m_vertices[0]->GetData().m_pos.X(); + ver0.Y() = currentTriangle.m_vertices[0]->GetData().m_pos.Y(); + ver0.Z() = currentTriangle.m_vertices[0]->GetData().m_pos.Z(); + ver1.X() = currentTriangle.m_vertices[1]->GetData().m_pos.X(); + ver1.Y() = currentTriangle.m_vertices[1]->GetData().m_pos.Y(); + ver1.Z() = currentTriangle.m_vertices[1]->GetData().m_pos.Z(); + ver2.X() = currentTriangle.m_vertices[2]->GetData().m_pos.X(); + ver2.Y() = currentTriangle.m_vertices[2]->GetData().m_pos.Y(); + ver2.Z() = currentTriangle.m_vertices[2]->GetData().m_pos.Z(); + nhit = IntersectRayTriangle(p0, ptNormal, ver0, ver1, ver2, dist); + } + + if (nhit == 1 && distance <= dist) + { + distance = dist; + insideHull = true; + face = m_mesh.m_triangles.GetHead(); +/* + std::cout << name << " -> T " << currentTriangle.m_vertices[0]->GetData().m_name << " " + << currentTriangle.m_vertices[1]->GetData().m_name << " " + << currentTriangle.m_vertices[2]->GetData().m_name << " Dist " + << dist << " P " << currentTriangle.m_normal * normal << std::endl; +*/ + if (dist > 0.1) + { + break; + } + } + m_mesh.m_triangles.Next(); + } + if (updateIncidentPoints && face && m_distPoints) + { + (*m_distPoints)[name].m_dist = static_cast(distance); + face->GetData().m_incidentPoints.insert(name); + } + return distance; + } + } +} + diff --git a/Extras/HACD/hacdICHull.h b/Extras/HACD/hacdICHull.h new file mode 100644 index 0000000..fbe4ef6 --- /dev/null +++ b/Extras/HACD/hacdICHull.h @@ -0,0 +1,120 @@ +/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) + All rights reserved. + + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + 2. 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. + + 3. The names of the contributors may not 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 HOLDER 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. + */ +#pragma once +#ifndef HACD_ICHULL_H +#define HACD_ICHULL_H +#include "hacdVersion.h" +#include "hacdManifoldMesh.h" +#include "hacdVector.h" +#include +#include +namespace HACD +{ + class DPoint; + class HACD; + //! Incremental Convex Hull algorithm (cf. http://maven.smith.edu/~orourke/books/ftp.html ). + enum ICHullError + { + ICHullErrorOK = 0, + ICHullErrorCoplanarPoints, + ICHullErrorNoVolume, + ICHullErrorInconsistent, + ICHullErrorNotEnoughPoints + }; + class ICHull + { + public: + //! + bool IsFlat() { return m_isFlat;} + //! + std::map * GetDistPoints() const { return m_distPoints;} + //! + void SetDistPoints(std::map * distPoints) { m_distPoints = distPoints;} + //! Returns the computed mesh + TMMesh & GetMesh() { return m_mesh;} + //! Add one point to the convex-hull + bool AddPoint(const Vec3 & point) {return AddPoints(&point, 1);} + //! Add one point to the convex-hull + bool AddPoint(const Vec3 & point, long id); + //! Add points to the convex-hull + bool AddPoints(const Vec3 * points, size_t nPoints); + bool AddPoints(std::vector< Vec3 > points); + //! + ICHullError Process(); + //! + ICHullError Process(unsigned long nPointsCH); + //! + double ComputeVolume(); + //! + bool IsInside(const Vec3 & pt0); + //! + double ComputeDistance(long name, const Vec3 & pt, const Vec3 & normal, bool & insideHull, bool updateIncidentPoints); + //! + const ICHull & operator=(ICHull & rhs); + + //! Constructor + ICHull(void); + //! Destructor + virtual ~ICHull(void) {}; + + private: + //! DoubleTriangle builds the initial double triangle. It first finds 3 noncollinear points and makes two faces out of them, in opposite order. It then finds a fourth point that is not coplanar with that face. The vertices are stored in the face structure in counterclockwise order so that the volume between the face and the point is negative. Lastly, the 3 newfaces to the fourth point are constructed and the data structures are cleaned up. + ICHullError DoubleTriangle(); + //! MakeFace creates a new face structure from three vertices (in ccw order). It returns a pointer to the face. + CircularListElement * MakeFace(CircularListElement * v0, + CircularListElement * v1, + CircularListElement * v2, + CircularListElement * fold); + //! + CircularListElement * MakeConeFace(CircularListElement * e, CircularListElement * v); + //! + bool ProcessPoint(); + //! + bool ComputePointVolume(double &totalVolume, bool markVisibleFaces); + //! + bool FindMaxVolumePoint(); + //! + bool CleanEdges(); + //! + bool CleanVertices(unsigned long & addedPoints); + //! + bool CleanTriangles(); + //! + bool CleanUp(unsigned long & addedPoints); + //! + bool MakeCCW(CircularListElement * f, + CircularListElement * e, + CircularListElement * v); + void Clear(); + private: + static const long sc_dummyIndex; + static const double sc_distMin; + TMMesh m_mesh; + std::vector *> m_edgesToDelete; + std::vector *> m_edgesToUpdate; + std::vector *> m_trianglesToDelete; + std::map * m_distPoints; + CircularListElement * m_dummyVertex; + Vec3 m_normal; + bool m_isFlat; + + + ICHull(const ICHull & rhs); + + friend class HACD; + }; + +} +#endif diff --git a/Extras/HACD/hacdManifoldMesh.cpp b/Extras/HACD/hacdManifoldMesh.cpp new file mode 100644 index 0000000..399fda0 --- /dev/null +++ b/Extras/HACD/hacdManifoldMesh.cpp @@ -0,0 +1,577 @@ +/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) + All rights reserved. + + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + 2. 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. + + 3. The names of the contributors may not 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 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "hacdManifoldMesh.h" +using namespace std; + + +namespace HACD +{ + Material::Material(void) + { + m_diffuseColor.X() = 0.5; + m_diffuseColor.Y() = 0.5; + m_diffuseColor.Z() = 0.5; + m_specularColor.X() = 0.5; + m_specularColor.Y() = 0.5; + m_specularColor.Z() = 0.5; + m_ambientIntensity = 0.4; + m_emissiveColor.X() = 0.0; + m_emissiveColor.Y() = 0.0; + m_emissiveColor.Z() = 0.0; + m_shininess = 0.4; + m_transparency = 0.0; + } + + TMMVertex::TMMVertex(void) + { + m_name = 0; + m_id = 0; + m_duplicate = 0; + m_onHull = false; + m_tag = false; + } + TMMVertex::~TMMVertex(void) + { + } + TMMEdge::TMMEdge(void) + { + m_id = 0; + m_triangles[0] = m_triangles[1] = m_newFace = 0; + m_vertices[0] = m_vertices[1] = 0; + } + TMMEdge::~TMMEdge(void) + { + } + TMMTriangle::TMMTriangle(void) + { + m_id = 0; + for(int i = 0; i < 3; i++) + { + m_edges[i] = 0; + m_vertices[0] = 0; + } + m_visible = false; + } + TMMTriangle::~TMMTriangle(void) + { + } + TMMesh::TMMesh(void) + { + m_barycenter = Vec3(0,0,0); + m_diag = 1; + } + TMMesh::~TMMesh(void) + { + } + + void TMMesh::Print() + { + size_t nV = m_vertices.GetSize(); + std::cout << "-----------------------------" << std::endl; + std::cout << "vertices (" << nV << ")" << std::endl; + for(size_t v = 0; v < nV; v++) + { + const TMMVertex & currentVertex = m_vertices.GetData(); + std::cout << currentVertex.m_id << ", " + << currentVertex.m_pos.X() << ", " + << currentVertex.m_pos.Y() << ", " + << currentVertex.m_pos.Z() << std::endl; + m_vertices.Next(); + } + + + size_t nE = m_edges.GetSize(); + std::cout << "edges (" << nE << ")" << std::endl; + for(size_t e = 0; e < nE; e++) + { + const TMMEdge & currentEdge = m_edges.GetData(); + const CircularListElement * v0 = currentEdge.m_vertices[0]; + const CircularListElement * v1 = currentEdge.m_vertices[1]; + const CircularListElement * f0 = currentEdge.m_triangles[0]; + const CircularListElement * f1 = currentEdge.m_triangles[1]; + + std::cout << "-> (" << v0->GetData().m_name << ", " << v1->GetData().m_name << ")" << std::endl; + std::cout << "-> F0 (" << f0->GetData().m_vertices[0]->GetData().m_name << ", " + << f0->GetData().m_vertices[1]->GetData().m_name << ", " + << f0->GetData().m_vertices[2]->GetData().m_name <<")" << std::endl; + std::cout << "-> F1 (" << f1->GetData().m_vertices[0]->GetData().m_name << ", " + << f1->GetData().m_vertices[1]->GetData().m_name << ", " + << f1->GetData().m_vertices[2]->GetData().m_name << ")" << std::endl; + m_edges.Next(); + } + size_t nT = m_triangles.GetSize(); + std::cout << "triangles (" << nT << ")" << std::endl; + for(size_t t = 0; t < nT; t++) + { + const TMMTriangle & currentTriangle = m_triangles.GetData(); + const CircularListElement * v0 = currentTriangle.m_vertices[0]; + const CircularListElement * v1 = currentTriangle.m_vertices[1]; + const CircularListElement * v2 = currentTriangle.m_vertices[2]; + const CircularListElement * e0 = currentTriangle.m_edges[0]; + const CircularListElement * e1 = currentTriangle.m_edges[1]; + const CircularListElement * e2 = currentTriangle.m_edges[2]; + + std::cout << "-> (" << v0->GetData().m_name << ", " << v1->GetData().m_name << ", "<< v2->GetData().m_name << ")" << std::endl; + + std::cout << "-> E0 (" << e0->GetData().m_vertices[0]->GetData().m_name << ", " + << e0->GetData().m_vertices[1]->GetData().m_name << ")" << std::endl; + std::cout << "-> E1 (" << e1->GetData().m_vertices[0]->GetData().m_name << ", " + << e1->GetData().m_vertices[1]->GetData().m_name << ")" << std::endl; + std::cout << "-> E2 (" << e2->GetData().m_vertices[0]->GetData().m_name << ", " + << e2->GetData().m_vertices[1]->GetData().m_name << ")" << std::endl; + m_triangles.Next(); + } + } + bool TMMesh::Save(const char *fileName) + { + std::ofstream fout(fileName); + std::cout << "Saving " << fileName << std::endl; + if (SaveVRML2(fout)) + { + fout.close(); + return true; + } + return false; + } + bool TMMesh::SaveVRML2(std::ofstream &fout) + { + return SaveVRML2(fout, Material()); + } + bool TMMesh::SaveVRML2(std::ofstream &fout, const Material & material) + { + if (fout.is_open()) + { + size_t nV = m_vertices.GetSize(); + size_t nT = m_triangles.GetSize(); + fout <<"#VRML V2.0 utf8" << std::endl; + fout <<"" << std::endl; + fout <<"# Vertices: " << nV << std::endl; + fout <<"# Triangles: " << nT << std::endl; + fout <<"" << std::endl; + fout <<"Group {" << std::endl; + fout <<" children [" << std::endl; + fout <<" Shape {" << std::endl; + fout <<" appearance Appearance {" << std::endl; + fout <<" material Material {" << std::endl; + fout <<" diffuseColor " << material.m_diffuseColor.X() << " " + << material.m_diffuseColor.Y() << " " + << material.m_diffuseColor.Z() << std::endl; + fout <<" ambientIntensity " << material.m_ambientIntensity << std::endl; + fout <<" specularColor " << material.m_specularColor.X() << " " + << material.m_specularColor.Y() << " " + << material.m_specularColor.Z() << std::endl; + fout <<" emissiveColor " << material.m_emissiveColor.X() << " " + << material.m_emissiveColor.Y() << " " + << material.m_emissiveColor.Z() << std::endl; + fout <<" shininess " << material.m_shininess << std::endl; + fout <<" transparency " << material.m_transparency << std::endl; + fout <<" }" << std::endl; + fout <<" }" << std::endl; + fout <<" geometry IndexedFaceSet {" << std::endl; + fout <<" ccw TRUE" << std::endl; + fout <<" solid TRUE" << std::endl; + fout <<" convex TRUE" << std::endl; + if (GetNVertices() > 0) { + fout <<" coord DEF co Coordinate {" << std::endl; + fout <<" point [" << std::endl; + for(size_t v = 0; v < nV; v++) + { + TMMVertex & currentVertex = m_vertices.GetData(); + fout <<" " << currentVertex.m_pos.X() << " " + << currentVertex.m_pos.Y() << " " + << currentVertex.m_pos.Z() << "," << std::endl; + currentVertex.m_id = v; + m_vertices.Next(); + } + fout <<" ]" << std::endl; + fout <<" }" << std::endl; + } + if (GetNTriangles() > 0) { + fout <<" coordIndex [ " << std::endl; + for(size_t f = 0; f < nT; f++) + { + TMMTriangle & currentTriangle = m_triangles.GetData(); + fout <<" " << currentTriangle.m_vertices[0]->GetData().m_id << ", " + << currentTriangle.m_vertices[1]->GetData().m_id << ", " + << currentTriangle.m_vertices[2]->GetData().m_id << ", -1," << std::endl; + m_triangles.Next(); + } + fout <<" ]" << std::endl; + } + fout <<" }" << std::endl; + fout <<" }" << std::endl; + fout <<" ]" << std::endl; + fout <<"}" << std::endl; + } + return true; + } + void TMMesh::GetIFS(Vec3 * const points, Vec3 * const triangles) + { + size_t nV = m_vertices.GetSize(); + size_t nT = m_triangles.GetSize(); + + for(size_t v = 0; v < nV; v++) + { + points[v] = m_vertices.GetData().m_pos; + m_vertices.GetData().m_id = v; + m_vertices.Next(); + } + for(size_t f = 0; f < nT; f++) + { + TMMTriangle & currentTriangle = m_triangles.GetData(); + triangles[f].X() = static_cast(currentTriangle.m_vertices[0]->GetData().m_id); + triangles[f].Y() = static_cast(currentTriangle.m_vertices[1]->GetData().m_id); + triangles[f].Z() = static_cast(currentTriangle.m_vertices[2]->GetData().m_id); + m_triangles.Next(); + } + } + void TMMesh::Clear() + { + m_vertices.Clear(); + m_edges.Clear(); + m_triangles.Clear(); + } + void TMMesh::Copy(TMMesh & mesh) + { + Clear(); + // updating the id's + size_t nV = mesh.m_vertices.GetSize(); + size_t nE = mesh. m_edges.GetSize(); + size_t nT = mesh.m_triangles.GetSize(); + for(size_t v = 0; v < nV; v++) + { + mesh.m_vertices.GetData().m_id = v; + mesh.m_vertices.Next(); + } + for(size_t e = 0; e < nE; e++) + { + mesh.m_edges.GetData().m_id = e; + mesh.m_edges.Next(); + + } + for(size_t f = 0; f < nT; f++) + { + mesh.m_triangles.GetData().m_id = f; + mesh.m_triangles.Next(); + } + // copying data + m_vertices = mesh.m_vertices; + m_edges = mesh.m_edges; + m_triangles = mesh.m_triangles; + + // generating mapping + CircularListElement ** vertexMap = new CircularListElement * [nV]; + CircularListElement ** edgeMap = new CircularListElement * [nE]; + CircularListElement ** triangleMap = new CircularListElement * [nT]; + for(size_t v = 0; v < nV; v++) + { + vertexMap[v] = m_vertices.GetHead(); + m_vertices.Next(); + } + for(size_t e = 0; e < nE; e++) + { + edgeMap[e] = m_edges.GetHead(); + m_edges.Next(); + } + for(size_t f = 0; f < nT; f++) + { + triangleMap[f] = m_triangles.GetHead(); + m_triangles.Next(); + } + + // updating pointers + for(size_t v = 0; v < nV; v++) + { + if (vertexMap[v]->GetData().m_duplicate) + { + vertexMap[v]->GetData().m_duplicate = edgeMap[vertexMap[v]->GetData().m_duplicate->GetData().m_id]; + } + } + for(size_t e = 0; e < nE; e++) + { + if (edgeMap[e]->GetData().m_newFace) + { + edgeMap[e]->GetData().m_newFace = triangleMap[edgeMap[e]->GetData().m_newFace->GetData().m_id]; + } + if (nT > 0) + { + for(int f = 0; f < 2; f++) + { + if (edgeMap[e]->GetData().m_triangles[f]) + { + edgeMap[e]->GetData().m_triangles[f] = triangleMap[edgeMap[e]->GetData().m_triangles[f]->GetData().m_id]; + } + } + } + for(int v = 0; v < 2; v++) + { + if (edgeMap[e]->GetData().m_vertices[v]) + { + edgeMap[e]->GetData().m_vertices[v] = vertexMap[edgeMap[e]->GetData().m_vertices[v]->GetData().m_id]; + } + } + } + for(size_t f = 0; f < nT; f++) + { + if (nE > 0) + { + for(int e = 0; e < 3; e++) + { + if (triangleMap[f]->GetData().m_edges[e]) + { + triangleMap[f]->GetData().m_edges[e] = edgeMap[triangleMap[f]->GetData().m_edges[e]->GetData().m_id]; + } + } + } + for(int v = 0; v < 3; v++) + { + if (triangleMap[f]->GetData().m_vertices[v]) + { + triangleMap[f]->GetData().m_vertices[v] = vertexMap[triangleMap[f]->GetData().m_vertices[v]->GetData().m_id]; + } + } + } + delete [] vertexMap; + delete [] edgeMap; + delete [] triangleMap; + + } + long IntersectRayTriangle(const Vec3 & P0, const Vec3 & dir, + const Vec3 & V0, const Vec3 & V1, + const Vec3 & V2, double &t) + { + Vec3 edge1, edge2, edge3; + double det, invDet; + edge1 = V1 - V2; + edge2 = V2 - V0; + Vec3 pvec = dir ^ edge2; + det = edge1 * pvec; + if (det == 0.0) + return 0; + invDet = 1.0/det; + Vec3 tvec = P0 - V0; + Vec3 qvec = tvec ^ edge1; + t = (edge2 * qvec) * invDet; + if (t < 0.0) + { + return 0; + } + edge3 = V0 - V1; + Vec3 I(P0 + t * dir); + Vec3 s0 = (I-V0) ^ edge3; + Vec3 s1 = (I-V1) ^ edge1; + Vec3 s2 = (I-V2) ^ edge2; + if (s0*s1 > -1e-9 && s2*s1 > -1e-9) + { + return 1; + } + return 0; + } + + bool IntersectLineLine(const Vec3 & p1, const Vec3 & p2, + const Vec3 & p3, const Vec3 & p4, + Vec3 & pa, Vec3 & pb, + double & mua, double & mub) + { + Vec3 p13,p43,p21; + double d1343,d4321,d1321,d4343,d2121; + double numer,denom; + + p13.X() = p1.X() - p3.X(); + p13.Y() = p1.Y() - p3.Y(); + p13.Z() = p1.Z() - p3.Z(); + p43.X() = p4.X() - p3.X(); + p43.Y() = p4.Y() - p3.Y(); + p43.Z() = p4.Z() - p3.Z(); + if (p43.X()==0.0 && p43.Y()==0.0 && p43.Z()==0.0) + return false; + p21.X() = p2.X() - p1.X(); + p21.Y() = p2.Y() - p1.Y(); + p21.Z() = p2.Z() - p1.Z(); + if (p21.X()==0.0 && p21.Y()==0.0 && p21.Z()==0.0) + return false; + + d1343 = p13.X() * p43.X() + p13.Y() * p43.Y() + p13.Z() * p43.Z(); + d4321 = p43.X() * p21.X() + p43.Y() * p21.Y() + p43.Z() * p21.Z(); + d1321 = p13.X() * p21.X() + p13.Y() * p21.Y() + p13.Z() * p21.Z(); + d4343 = p43.X() * p43.X() + p43.Y() * p43.Y() + p43.Z() * p43.Z(); + d2121 = p21.X() * p21.X() + p21.Y() * p21.Y() + p21.Z() * p21.Z(); + + denom = d2121 * d4343 - d4321 * d4321; + if (denom==0.0) + return false; + numer = d1343 * d4321 - d1321 * d4343; + + mua = numer / denom; + mub = (d1343 + d4321 * (mua)) / d4343; + + pa.X() = p1.X() + mua * p21.X(); + pa.Y() = p1.Y() + mua * p21.Y(); + pa.Z() = p1.Z() + mua * p21.Z(); + pb.X() = p3.X() + mub * p43.X(); + pb.Y() = p3.Y() + mub * p43.Y(); + pb.Z() = p3.Z() + mub * p43.Z(); + + return true; + } + + long IntersectRayTriangle2(const Vec3 & P0, const Vec3 & dir, + const Vec3 & V0, const Vec3 & V1, + const Vec3 & V2, double &r) + { + Vec3 u, v, n; // triangle vectors + Vec3 w0, w; // ray vectors + double a, b; // params to calc ray-plane intersect + + // get triangle edge vectors and plane normal + u = V1 - V0; + v = V2 - V0; + n = u ^ v; // cross product + if (n.GetNorm() == 0.0) // triangle is degenerate + return -1; // do not deal with this case + + w0 = P0 - V0; + a = - n * w0; + b = n * dir; + if (fabs(b) <= 0.0) { // ray is parallel to triangle plane + if (a == 0.0) // ray lies in triangle plane + return 2; + else return 0; // ray disjoint from plane + } + + // get intersect point of ray with triangle plane + r = a / b; + if (r < 0.0) // ray goes away from triangle + return 0; // => no intersect + // for a segment, also test if (r > 1.0) => no intersect + + Vec3 I = P0 + r * dir; // intersect point of ray and plane + + // is I inside T? + double uu, uv, vv, wu, wv, D; + uu = u * u; + uv = u * v; + vv = v * v; + w = I - V0; + wu = w * u; + wv = w * v; + D = uv * uv - uu * vv; + + // get and test parametric coords + double s, t; + s = (uv * wv - vv * wu) / D; + if (s < 0.0 || s > 1.0) // I is outside T + return 0; + t = (uv * wu - uu * wv) / D; + if (t < 0.0 || (s + t) > 1.0) // I is outside T + return 0; + return 1; // I is in T + } + + + bool TMMesh::CheckConsistancy() + { + size_t nE = m_edges.GetSize(); + size_t nT = m_triangles.GetSize(); + for(size_t e = 0; e < nE; e++) + { + for(int f = 0; f < 2; f++) + { + if (!m_edges.GetHead()->GetData().m_triangles[f]) + { + return false; + } + } + m_edges.Next(); + } + + for(size_t f = 0; f < nT; f++) + { + for(int e = 0; e < 3; e++) + { + int found = 0; + for(int k = 0; k < 2; k++) + { + if (m_triangles.GetHead()->GetData().m_edges[e]->GetData().m_triangles[k] == m_triangles.GetHead()) + { + found++; + } + } + if (found != 1) + { + return false; + } + } + m_triangles.Next(); + } + + return true; + } + bool TMMesh::Normalize() + { + size_t nV = m_vertices.GetSize(); + if (nV == 0) + { + return false; + } + m_barycenter = m_vertices.GetHead()->GetData().m_pos; + Vec3 min = m_barycenter; + Vec3 max = m_barycenter; + Real x, y, z; + for(size_t v = 1; v < nV; v++) + { + m_barycenter += m_vertices.GetHead()->GetData().m_pos; + x = m_vertices.GetHead()->GetData().m_pos.X(); + y = m_vertices.GetHead()->GetData().m_pos.Y(); + z = m_vertices.GetHead()->GetData().m_pos.Z(); + if ( x < min.X()) min.X() = x; + else if ( x > max.X()) max.X() = x; + if ( y < min.Y()) min.Y() = y; + else if ( y > max.Y()) max.Y() = y; + if ( z < min.Z()) min.Z() = z; + else if ( z > max.Z()) max.Z() = z; + m_vertices.Next(); + } + m_barycenter /= static_cast(nV); + m_diag = static_cast(0.001 * (max-min).GetNorm()); + const Real invDiag = static_cast(1.0 / m_diag); + if (m_diag != 0.0) + { + for(size_t v = 0; v < nV; v++) + { + m_vertices.GetHead()->GetData().m_pos = (m_vertices.GetHead()->GetData().m_pos - m_barycenter) * invDiag; + m_vertices.Next(); + } + } + return true; + } + bool TMMesh::Denormalize() + { + size_t nV = m_vertices.GetSize(); + if (nV == 0) + { + return false; + } + if (m_diag != 0.0) + { + for(size_t v = 0; v < nV; v++) + { + m_vertices.GetHead()->GetData().m_pos = m_vertices.GetHead()->GetData().m_pos * m_diag + m_barycenter; + m_vertices.Next(); + } + } + return false; + } +} diff --git a/Extras/HACD/hacdManifoldMesh.h b/Extras/HACD/hacdManifoldMesh.h new file mode 100644 index 0000000..5d2ecec --- /dev/null +++ b/Extras/HACD/hacdManifoldMesh.h @@ -0,0 +1,250 @@ +/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) +All rights reserved. + + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + 2. 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. + + 3. The names of the contributors may not 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 HOLDER 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. +*/ + +/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) + All rights reserved. + + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + 2. 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. + + 3. The names of the contributors may not 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 HOLDER 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. + */ +#pragma once +#ifndef HACD_MANIFOLD_MESH_H +#define HACD_MANIFOLD_MESH_H +#include +#include +#include "hacdVersion.h" +#include "hacdCircularList.h" +#include "hacdVector.h" +#include +namespace HACD +{ + class TMMTriangle; + class TMMEdge; + class TMMesh; + class ICHull; + class HACD; + + class DPoint + { + public: + DPoint(Real dist=0, bool computed=false, bool distOnly=false) + :m_dist(dist), + m_computed(computed), + m_distOnly(distOnly){}; + ~DPoint(){}; + private: + Real m_dist; + bool m_computed; + bool m_distOnly; + friend class TMMTriangle; + friend class TMMesh; + friend class GraphVertex; + friend class GraphEdge; + friend class Graph; + friend class ICHull; + friend class HACD; + }; + + //! Vertex data structure used in a triangular manifold mesh (TMM). + class TMMVertex + { + public: + TMMVertex(void); + ~TMMVertex(void); + + private: + Vec3 m_pos; + long m_name; + size_t m_id; + CircularListElement * m_duplicate; // pointer to incident cone edge (or NULL) + bool m_onHull; + bool m_tag; + TMMVertex(const TMMVertex & rhs); + + friend class HACD; + friend class ICHull; + friend class TMMesh; + friend class TMMTriangle; + friend class TMMEdge; + }; + + //! Edge data structure used in a triangular manifold mesh (TMM). + class TMMEdge + { + public: + TMMEdge(void); + ~TMMEdge(void); + private: + size_t m_id; + CircularListElement * m_triangles[2]; + CircularListElement * m_vertices[2]; + CircularListElement * m_newFace; + + + TMMEdge(const TMMEdge & rhs); + + friend class HACD; + friend class ICHull; + friend class TMMTriangle; + friend class TMMVertex; + friend class TMMesh; + }; + + //! Triangle data structure used in a triangular manifold mesh (TMM). + class TMMTriangle + { + public: + TMMTriangle(void); + ~TMMTriangle(void); + private: + size_t m_id; + CircularListElement * m_edges[3]; + CircularListElement * m_vertices[3]; + std::set m_incidentPoints; + bool m_visible; + + TMMTriangle(const TMMTriangle & rhs); + + friend class HACD; + friend class ICHull; + friend class TMMesh; + friend class TMMVertex; + friend class TMMEdge; + }; + + class Material + { + public: + Material(void); + ~Material(void){} +// private: + Vec3 m_diffuseColor; + double m_ambientIntensity; + Vec3 m_specularColor; + Vec3 m_emissiveColor; + double m_shininess; + double m_transparency; + + friend class TMMesh; + friend class HACD; + }; + + //! triangular manifold mesh data structure. + class TMMesh + { + public: + + //! Returns the number of vertices> + inline size_t GetNVertices() const { return m_vertices.GetSize();} + //! Returns the number of edges + inline size_t GetNEdges() const { return m_edges.GetSize();} + //! Returns the number of triangles + inline size_t GetNTriangles() const { return m_triangles.GetSize();} + //! Returns the vertices circular list + inline const CircularList & GetVertices() const { return m_vertices;} + //! Returns the edges circular list + inline const CircularList & GetEdges() const { return m_edges;} + //! Returns the triangles circular list + inline const CircularList & GetTriangles() const { return m_triangles;} + //! Returns the vertices circular list + inline CircularList & GetVertices() { return m_vertices;} + //! Returns the edges circular list + inline CircularList & GetEdges() { return m_edges;} + //! Returns the triangles circular list + inline CircularList & GetTriangles() { return m_triangles;} + //! Add vertex to the mesh + CircularListElement * AddVertex() {return m_vertices.Add();} + //! Add vertex to the mesh + CircularListElement * AddEdge() {return m_edges.Add();} + //! Add vertex to the mesh + CircularListElement * AddTriangle() {return m_triangles.Add();} + //! Print mesh information + void Print(); + //! + void GetIFS(Vec3 * const points, Vec3 * const triangles); + //! Save mesh + bool Save(const char *fileName); + //! Save mesh to VRML 2.0 format + bool SaveVRML2(std::ofstream &fout); + //! Save mesh to VRML 2.0 format + bool SaveVRML2(std::ofstream &fout, const Material & material); + //! + void Clear(); + //! + void Copy(TMMesh & mesh); + //! + bool CheckConsistancy(); + //! + bool Normalize(); + //! + bool Denormalize(); + //! Constructor + TMMesh(void); + //! Destructor + virtual ~TMMesh(void); + + private: + CircularList m_vertices; + CircularList m_edges; + CircularList m_triangles; + Real m_diag; //>! length of the BB diagonal + Vec3 m_barycenter; //>! barycenter of the mesh + + // not defined + TMMesh(const TMMesh & rhs); + friend class ICHull; + friend class HACD; + }; + //! IntersectRayTriangle(): intersect a ray with a 3D triangle + //! Input: a ray R, and a triangle T + //! Output: *I = intersection point (when it exists) + //! 0 = disjoint (no intersect) + //! 1 = intersect in unique point I1 + long IntersectRayTriangle( const Vec3 & P0, const Vec3 & dir, + const Vec3 & V0, const Vec3 & V1, + const Vec3 & V2, double &t); + + // intersect_RayTriangle(): intersect a ray with a 3D triangle + // Input: a ray R, and a triangle T + // Output: *I = intersection point (when it exists) + // Return: -1 = triangle is degenerate (a segment or point) + // 0 = disjoint (no intersect) + // 1 = intersect in unique point I1 + // 2 = are in the same plane + long IntersectRayTriangle2(const Vec3 & P0, const Vec3 & dir, + const Vec3 & V0, const Vec3 & V1, + const Vec3 & V2, double &r); + + /* + Calculate the line segment PaPb that is the shortest route between + two lines P1P2 and P3P4. Calculate also the values of mua and mub where + Pa = P1 + mua (P2 - P1) + Pb = P3 + mub (P4 - P3) + Return FALSE if no solution exists. + */ + bool IntersectLineLine(const Vec3 & p1, const Vec3 & p2, + const Vec3 & p3, const Vec3 & p4, + Vec3 & pa, Vec3 & pb, + double & mua, double &mub); +} +#endif diff --git a/Extras/HACD/hacdVector.h b/Extras/HACD/hacdVector.h new file mode 100644 index 0000000..4006c4b --- /dev/null +++ b/Extras/HACD/hacdVector.h @@ -0,0 +1,67 @@ +/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) + All rights reserved. + + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + 2. 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. + + 3. The names of the contributors may not 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 HOLDER 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. + */ +#pragma once +#ifndef HACD_VECTOR_H +#define HACD_VECTOR_H +#include +#include +#include "hacdVersion.h" + +namespace HACD +{ + typedef double Real; + //! Vector dim 3. + template < typename T > class Vec3 + { + public: + T & X(); + T & Y(); + T & Z(); + const T & X() const; + const T & Y() const; + const T & Z() const; + void Normalize(); + T GetNorm() const; + void operator= (const Vec3 & rhs); + void operator+=(const Vec3 & rhs); + void operator-=(const Vec3 & rhs); + void operator-=(T a); + void operator+=(T a); + void operator/=(T a); + void operator*=(T a); + Vec3 operator^ (const Vec3 & rhs) const; + T operator* (const Vec3 & rhs) const; + Vec3 operator+ (const Vec3 & rhs) const; + Vec3 operator- (const Vec3 & rhs) const; + Vec3 operator- () const; + Vec3 operator* (T rhs) const; + Vec3 operator/ (T rhs) const; + Vec3(); + Vec3(T a); + Vec3(T x, T y, T z); + Vec3(const Vec3 & rhs); + /*virtual*/ ~Vec3(void); + + private: + T m_data[3]; + }; + template + const bool Colinear(const Vec3 & a, const Vec3 & b, const Vec3 & c); + template + const T Volume(const Vec3 & a, const Vec3 & b, const Vec3 & c, const Vec3 & d); + +} +#include "hacdVector.inl" // template implementation +#endif diff --git a/Extras/HACD/hacdVector.inl b/Extras/HACD/hacdVector.inl new file mode 100644 index 0000000..3532741 --- /dev/null +++ b/Extras/HACD/hacdVector.inl @@ -0,0 +1,178 @@ +#pragma once +#ifndef HACD_VECTOR_INL +#define HACD_VECTOR_INL +namespace HACD +{ + template + inline Vec3 operator*(T lhs, const Vec3 & rhs) + { + return Vec3(lhs * rhs.X(), lhs * rhs.Y(), lhs * rhs.Z()); + } + template + inline T & Vec3::X() + { + return m_data[0]; + } + template + inline T & Vec3::Y() + { + return m_data[1]; + } + template + inline T & Vec3::Z() + { + return m_data[2]; + } + template + inline const T & Vec3::X() const + { + return m_data[0]; + } + template + inline const T & Vec3::Y() const + { + return m_data[1]; + } + template + inline const T & Vec3::Z() const + { + return m_data[2]; + } + template + inline void Vec3::Normalize() + { + T n = sqrt(m_data[0]*m_data[0]+m_data[1]*m_data[1]+m_data[2]*m_data[2]); + if (n != 0.0) (*this) /= n; + } + template + inline T Vec3::GetNorm() const + { + return sqrt(m_data[0]*m_data[0]+m_data[1]*m_data[1]+m_data[2]*m_data[2]); + } + template + inline void Vec3::operator= (const Vec3 & rhs) + { + this->m_data[0] = rhs.m_data[0]; + this->m_data[1] = rhs.m_data[1]; + this->m_data[2] = rhs.m_data[2]; + } + template + inline void Vec3::operator+=(const Vec3 & rhs) + { + this->m_data[0] += rhs.m_data[0]; + this->m_data[1] += rhs.m_data[1]; + this->m_data[2] += rhs.m_data[2]; + } + template + inline void Vec3::operator-=(const Vec3 & rhs) + { + this->m_data[0] -= rhs.m_data[0]; + this->m_data[1] -= rhs.m_data[1]; + this->m_data[2] -= rhs.m_data[2]; + } + template + inline void Vec3::operator-=(T a) + { + this->m_data[0] -= a; + this->m_data[1] -= a; + this->m_data[2] -= a; + } + template + inline void Vec3::operator+=(T a) + { + this->m_data[0] += a; + this->m_data[1] += a; + this->m_data[2] += a; + } + template + inline void Vec3::operator/=(T a) + { + this->m_data[0] /= a; + this->m_data[1] /= a; + this->m_data[2] /= a; + } + template + inline void Vec3::operator*=(T a) + { + this->m_data[0] *= a; + this->m_data[1] *= a; + this->m_data[2] *= a; + } + template + inline Vec3 Vec3::operator^ (const Vec3 & rhs) const + { + return Vec3(m_data[1] * rhs.m_data[2] - m_data[2] * rhs.m_data[1], + m_data[2] * rhs.m_data[0] - m_data[0] * rhs.m_data[2], + m_data[0] * rhs.m_data[1] - m_data[1] * rhs.m_data[0]); + } + template + inline T Vec3::operator*(const Vec3 & rhs) const + { + return (m_data[0] * rhs.m_data[0] + m_data[1] * rhs.m_data[1] + m_data[2] * rhs.m_data[2]); + } + template + inline Vec3 Vec3::operator+(const Vec3 & rhs) const + { + return Vec3(m_data[0] + rhs.m_data[0],m_data[1] + rhs.m_data[1],m_data[2] + rhs.m_data[2]); + } + template + inline Vec3 Vec3::operator-(const Vec3 & rhs) const + { + return Vec3(m_data[0] - rhs.m_data[0],m_data[1] - rhs.m_data[1],m_data[2] - rhs.m_data[2]) ; + } + template + inline Vec3 Vec3::operator-() const + { + return Vec3(-m_data[0],-m_data[1],-m_data[2]) ; + } + + template + inline Vec3 Vec3::operator*(T rhs) const + { + return Vec3(rhs * this->m_data[0], rhs * this->m_data[1], rhs * this->m_data[2]); + } + template + inline Vec3 Vec3::operator/ (T rhs) const + { + return Vec3(m_data[0] / rhs, m_data[1] / rhs, m_data[2] / rhs); + } + template + inline Vec3::Vec3(T a) + { + m_data[0] = m_data[1] = m_data[2] = a; + } + template + inline Vec3::Vec3(T x, T y, T z) + { + m_data[0] = x; + m_data[1] = y; + m_data[2] = z; + } + template + inline Vec3::Vec3(const Vec3 & rhs) + { + m_data[0] = rhs.m_data[0]; + m_data[1] = rhs.m_data[1]; + m_data[2] = rhs.m_data[2]; + } + template + inline Vec3::~Vec3(void){}; + + template + inline Vec3::Vec3() {} + + template + inline const bool Colinear(const Vec3 & a, const Vec3 & b, const Vec3 & c) + { + return ((c.Z() - a.Z()) * (b.Y() - a.Y()) - (b.Z() - a.Z()) * (c.Y() - a.Y()) == 0.0 /*EPS*/) && + ((b.Z() - a.Z()) * (c.X() - a.X()) - (b.X() - a.X()) * (c.Z() - a.Z()) == 0.0 /*EPS*/) && + ((b.X() - a.X()) * (c.Y() - a.Y()) - (b.Y() - a.Y()) * (c.X() - a.X()) == 0.0 /*EPS*/); + } + + template + inline const T Volume(const Vec3 & a, const Vec3 & b, const Vec3 & c, const Vec3 & d) + { + return (a-d) * ((b-d) ^ (c-d)); + } +} +#endif //HACD_VECTOR_INL \ No newline at end of file diff --git a/Extras/HACD/hacdVersion.h b/Extras/HACD/hacdVersion.h new file mode 100644 index 0000000..3ce69b6 --- /dev/null +++ b/Extras/HACD/hacdVersion.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) + All rights reserved. + + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + 2. 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. + + 3. The names of the contributors may not 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 HOLDER 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. + */ +#pragma once +#ifndef HACD_VERSION_H +#define HACD_VERSION_H +#define HACD_VERSION_MAJOR 0 +#define HACD_VERSION_MINOR 0 +#endif \ No newline at end of file diff --git a/Extras/HACD/premake4.lua b/Extras/HACD/premake4.lua new file mode 100644 index 0000000..127d890 --- /dev/null +++ b/Extras/HACD/premake4.lua @@ -0,0 +1,9 @@ + project "HACD" + + kind "StaticLib" + targetdir "../../lib" + includedirs {"."} + files { + "**.cpp", + "**.h" + } \ No newline at end of file diff --git a/Extras/Makefile.am b/Extras/Makefile.am new file mode 100644 index 0000000..f4cd5ea --- /dev/null +++ b/Extras/Makefile.am @@ -0,0 +1,95 @@ +noinst_LIBRARIES = libgimpactutils.a libconvexdecomposition.a libHACD.a libglui.a + +libglui_a_CXXFLAGS = ${CXXFLAGS} -Iglui +libglui_a_SOURCES =\ + glui/glui_spinner.cpp\ + glui/glui_treepanel.cpp\ + glui/arcball.cpp\ + glui/glui_scrollbar.cpp\ + glui/glui_filebrowser.cpp\ + glui/glui_node.cpp\ + glui/glui_edittext.cpp\ + glui/glui_statictext.cpp\ + glui/glui_bitmaps.cpp\ + glui/algebra3.cpp\ + glui/glui_string.cpp\ + glui/glui_button.cpp\ + glui/glui_add_controls.cpp\ + glui/glui_control.cpp\ + glui/glui.cpp\ + glui/glui_listbox.cpp\ + glui/glui_checkbox.cpp\ + glui/glui_commandline.cpp\ + glui/glui_textbox.cpp\ + glui/glui_column.cpp\ + glui/glui_mouse_iaction.cpp\ + glui/glui_radio.cpp\ + glui/glui_translation.cpp\ + glui/glui_tree.cpp\ + glui/glui_rotation.cpp\ + glui/glui_panel.cpp\ + glui/glui_rollout.cpp\ + glui/glui_separator.cpp\ + glui/glui_bitmap_img_data.cpp\ + glui/quaternion.cpp\ + glui/glui_window.cpp\ + glui/glui_list.cpp\ + glui/GL/glui.h\ + glui/quaternion.h\ + glui/glui_internal.h\ + glui/glui_internal_control.h\ + glui/arcball.h\ + glui/algebra3.h + +libconvexdecomposition_a_CXXFLAGS = ${CXXFLAGS} -IConvexDecomposition/ -I../src +libconvexdecomposition_a_SOURCES =\ + ConvexDecomposition/concavity.cpp\ + ConvexDecomposition/ConvexDecomposition.cpp\ + ConvexDecomposition/vlookup.cpp\ + ConvexDecomposition/bestfit.cpp\ + ConvexDecomposition/ConvexBuilder.cpp\ + ConvexDecomposition/cd_hull.cpp\ + ConvexDecomposition/raytri.cpp\ + ConvexDecomposition/splitplane.cpp\ + ConvexDecomposition/float_math.cpp\ + ConvexDecomposition/planetri.cpp\ + ConvexDecomposition/cd_wavefront.cpp\ + ConvexDecomposition/bestfitobb.cpp\ + ConvexDecomposition/meshvolume.cpp\ + ConvexDecomposition/fitsphere.cpp\ + ConvexDecomposition/fitsphere.h\ + ConvexDecomposition/vlookup.h\ + ConvexDecomposition/concavity.h\ + ConvexDecomposition/ConvexDecomposition.h\ + ConvexDecomposition/bestfit.h\ + ConvexDecomposition/cd_vector.h\ + ConvexDecomposition/ConvexBuilder.h\ + ConvexDecomposition/cd_hull.h\ + ConvexDecomposition/raytri.h\ + ConvexDecomposition/splitplane.h\ + ConvexDecomposition/float_math.h\ + ConvexDecomposition/planetri.h\ + ConvexDecomposition/cd_wavefront.h\ + ConvexDecomposition/bestfitobb.h\ + ConvexDecomposition/meshvolume.h + +libHACD_a_CXXFLAGS = ${CXXFLAGS} -IHACD/ -I../src +libHACD_a_SOURCES =\ + HACD/hacdGraph.cpp\ + HACD/hacdHACD.cpp\ + HACD/hacdICHull.cpp\ + HACD/hacdManifoldMesh.cpp\ + HACD/hacdCircularList.h\ + HACD/hacdGraph.h\ + HACD/hacdHACD.h\ + HACD/hacdICHull.h\ + HACD/hacdManifoldMesh.h\ + HACD/hacdVector.h\ + HACD/hacdVersion.h\ + HACD/hacdCircularList.inl\ + HACD/hacdVector.inl + + +libgimpactutils_a_CXXFLAGS = ${CXXFLAGS} -I../src -IGIMPACTUtils -IConvexDecomposition +libgimpactutils_a_SOURCES = GIMPACTUtils/btGImpactConvexDecompositionShape.cpp GIMPACTUtils/btGImpactConvexDecompositionShape.h + diff --git a/Extras/PhysicsEffects/CMakeLists.txt b/Extras/PhysicsEffects/CMakeLists.txt new file mode 100644 index 0000000..23cbe97 --- /dev/null +++ b/Extras/PhysicsEffects/CMakeLists.txt @@ -0,0 +1,344 @@ +cmake_minimum_required(VERSION 2.4.3) +set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) + +#this line has to appear before 'PROJECT' in order to be able to disable incremental linking +SET(MSVC_INCREMENTAL_DEFAULT ON) + +PROJECT(PHYSICS_EFFECTS) +SET(PHYSICS_EFFECTS_VERSION 2.0) + +SET(BULLET_VERSION 2.80) + +SET(BULLET_PHYSICS_SOURCE_DIR "../..") + +IF(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + +INCLUDE_DIRECTORIES( ${PHYSICS_EFFECTS_SOURCE_DIR}/include ) + +IF (NOT CMAKE_BUILD_TYPE) +# SET(CMAKE_BUILD_TYPE "Debug") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF (NOT CMAKE_BUILD_TYPE) + +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG") +#MESSAGE("CMAKE_CXX_FLAGS_DEBUG="+${CMAKE_CXX_FLAGS_DEBUG}) + +OPTION(USE_DOUBLE_PRECISION "Use double precision" OFF) +OPTION(USE_GRAPHICAL_BENCHMARK "Use Graphical Benchmark" ON) +OPTION(USE_MULTITHREADED_BENCHMARK "Use Multithreaded Benchmark" OFF) + +ADD_DEFINITIONS(-DPFX_USE_FREE_VECTORMATH) + +IF (USE_MULTITHREADED_BENCHMARK) + ADD_DEFINITIONS(-DUSE_PARALLEL_SOLVER_BENCHMARK -DUSE_PARALLEL_DISPATCHER_BENCHMARK) +ENDIF() + +OPTION(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC Runtime Library DLL (/MD or /MDd)" ON) +OPTION(USE_MSVC_INCREMENTAL_LINKING "Use MSVC Incremental Linking" OFF) + +OPTION(USE_CUSTOM_VECTOR_MATH "Use custom vectormath library" OFF) + +IF (USE_CUSTOM_VECTOR_MATH) + ADD_DEFINITIONS(-DUSE_SYSTEM_VECTORMATH) + IF(WIN32) + SET (VECTOR_MATH_INCLUDE ${BULLET_PHYSICS_SOURCE_DIR}/src/vectormath/sse CACHE PATH "Vector Math library include path.") + ELSE(WIN32) + SET (VECTOR_MATH_INCLUDE ${BULLET_PHYSICS_SOURCE_DIR}/src/vectormath/scalar CACHE PATH "Vector Math library include path.") + ENDIF(WIN32) +ENDIF(USE_CUSTOM_VECTOR_MATH) + +IF (MSVC) + FIND_PATH(DIRECTX_SDK_BASE_DIR Include/D3D11.h PATH $ENV{DXSDK_DIR} ) + IF(DIRECTX_SDK_BASE_DIR) + OPTION(USE_DX11 "Use DirectX 11" ON) + ELSE() + OPTION(USE_DX11 "Use DirectX 11" OFF) + ENDIF() +ENDIF(MSVC) + + +#SET(CMAKE_EXE_LINKER_FLAGS_INIT "/STACK:10000000 /INCREMENTAL:NO") +#SET(CMAKE_EXE_LINKER_FLAGS "/STACK:10000000 /INCREMENTAL:NO") + +#MESSAGE("MSVC_INCREMENTAL_YES_FLAG"+${MSVC_INCREMENTAL_YES_FLAG}) + + +IF(MSVC) + IF (NOT USE_MSVC_INCREMENTAL_LINKING) + #MESSAGE("MSVC_INCREMENTAL_DEFAULT"+${MSVC_INCREMENTAL_DEFAULT}) + SET( MSVC_INCREMENTAL_YES_FLAG "/INCREMENTAL:NO") + + STRING(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replacementFlags ${CMAKE_EXE_LINKER_FLAGS_DEBUG}) + SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "/INCREMENTAL:NO ${replacementFlags}" ) + MESSAGE("CMAKE_EXE_LINKER_FLAGS_DEBUG=${CMAKE_EXE_LINKER_FLAGS_DEBUG}") + +# STRING(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replacementFlags2 ${CMAKE_EXE_LINKER_FLAGS}) +# SET(CMAKE_EXE_LINKER_FLAGS ${replacementFlag2}) +# STRING(REPLACE "INCREMENTAL:YES" "" replacementFlags3 ${CMAKE_EXTRA_LINK_FLAGS}) +# SET(CMAKE_EXTRA_LINK_FLAGS ${replacementFlag3}) + + + STRING(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replacementFlags3 ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}) + SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO ${replacementFlags3}) + SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/INCREMENTAL:NO ${replacementFlags3}" ) + + ENDIF (NOT USE_MSVC_INCREMENTAL_LINKING) + + IF (NOT USE_MSVC_RUNTIME_LIBRARY_DLL) + #We statically link to reduce dependancies + FOREACH(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + IF(${flag_var} MATCHES "/MD") + STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + ENDIF(${flag_var} MATCHES "/MD") + IF(${flag_var} MATCHES "/MDd") + STRING(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}") + ENDIF(${flag_var} MATCHES "/MDd") + ENDFOREACH(flag_var) + ENDIF (NOT USE_MSVC_RUNTIME_LIBRARY_DLL) + + OPTION(USE_MSVC_SSE "Use MSVC /arch:sse option" ON) + IF (USE_MSVC_SSE) + ADD_DEFINITIONS(/arch:SSE) + ENDIF() + OPTION(USE_MSVC_FAST_FLOATINGPOINT "Use MSVC /fp:fast option" ON) + IF (USE_MSVC_FAST_FLOATINGPOINT) + ADD_DEFINITIONS(/fp:fast) + ENDIF() +ENDIF(MSVC) + + + +IF (WIN32) +OPTION(INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES "Create MSVC projectfiles that can be distributed" OFF) + +IF (INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + SET (LIBRARY_OUTPUT_PATH ${BULLET_PHYSICS_SOURCE_DIR}/lib CACHE PATH "Single output directory for building all libraries.") + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BULLET_PHYSICS_SOURCE_DIR}) + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${BULLET_PHYSICS_SOURCE_DIR}) + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${BULLET_PHYSICS_SOURCE_DIR}) + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${BULLET_PHYSICS_SOURCE_DIR}) + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${BULLET_PHYSICS_SOURCE_DIR}) +ELSE() + SET (LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib CACHE PATH "Single output directory for building all libraries.") +ENDIF() + +OPTION(INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES "Create MSVC projectfiles with relative paths" OFF) +OPTION(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES "Add MSVC postfix for executable names (_Debug)" OFF) + +IF(MSVC) + FIND_PATH(AMD_OPENCL_BASE_DIR include/CL/cl.h PATH $ENV{ATISTREAMSDKROOT} ) + IF(AMD_OPENCL_BASE_DIR) + #AMD adds an extras slash at the end of the ATISTREAMSDKROOT variable + SET(AMD_OPENCL_INCLUDES ${AMD_OPENCL_BASE_DIR}/include ) + MESSAGE(${AMD_OPENCL_INCLUDES}) + IF (CMAKE_CL_64) + SET(CMAKE_ATISTREAMSDK_LIBPATH ${AMD_OPENCL_BASE_DIR}/lib/x86_64 ) + ELSE(CMAKE_CL_64) + SET(CMAKE_ATISTREAMSDK_LIBPATH ${AMD_OPENCL_BASE_DIR}/lib/x86 ) + ENDIF(CMAKE_CL_64) + OPTION(BUILD_AMD_OPENCL_DEMOS "Build OpenCL demos for AMD (GPU or CPU)" ON) + ELSE() + OPTION(BUILD_AMD_OPENCL_DEMOS "Build OpenCL demos for AMD (GPU or CPU)" OFF) + ENDIF() + + FIND_PATH(NVIDIA_OPENCL_BASE_DIR OpenCL/common/inc/CL/cl.h PATH $ENV{NVSDKCOMPUTE_ROOT} ) + IF(NVIDIA_OPENCL_BASE_DIR) + SET(NVIDIA_OPENCL_INCLUDES ${NVIDIA_OPENCL_BASE_DIR}/OpenCL/common/inc ) + MESSAGE(${NVIDIA_OPENCL_INCLUDES}) + IF (CMAKE_CL_64) + SET(CMAKE_NVSDKCOMPUTE_LIBPATH ${NVIDIA_OPENCL_BASE_DIR}/OpenCL/common/lib/x64 ) + ELSE(CMAKE_CL_64) + SET(CMAKE_NVSDKCOMPUTE_LIBPATH ${NVIDIA_OPENCL_BASE_DIR}/OpenCL/common/lib/Win32 ) + ENDIF(CMAKE_CL_64) + SET(NVIDIA_OPENCL_LIBRARIES ${CMAKE_NVSDKCOMPUTE_LIBPATH}/OpenCL.lib) + + OPTION(BUILD_NVIDIA_OPENCL_DEMOS "Build OpenCL demos for NVidia (GPU)" ON) + ELSE() + OPTION(BUILD_NVIDIA_OPENCL_DEMOS "Build OpenCL demos for NVidia (GPU)" OFF) + ENDIF() +ENDIF() + + + +IF (INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES) +SET(CMAKE_SUPPRESS_REGENERATION 1) +SET(CMAKE_USE_RELATIVE_PATHS 1) +ENDIF(INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES) + +ENDIF (WIN32) + +IF (MSVC OR APPLE) + OPTION(BUILD_MINICL_OPENCL_DEMOS "Build OpenCL demos for MiniCL (Generic CPU)" ON) +ELSE() + OPTION(BUILD_MINICL_OPENCL_DEMOS "Build OpenCL demos for MiniCL (Generic CPU)" OFF) + + FIND_PATH(NVIDIA_OPENCL_INCLUDES CL/cl.h) + FIND_LIBRARY(NVIDIA_OPENCL_LIBRARIES OpenCL PATH /usr/lib /usr/local/lib) + IF (NVIDIA_OPENCL_INCLUDES AND NVIDIA_OPENCL_LIBRARIES) + MESSAGE("OPENCL FOUND") + MESSAGE(${NVIDIA_OPENCL_LIBRARIES}) + OPTION(BUILD_NVIDIA_OPENCL_DEMOS "Build OpenCL demos for NVidia (GPU)" ON) + ELSE () + MESSAGE("OPENCL NOT FOUND") + OPTION(BUILD_NVIDIA_OPENCL_DEMOS "Build OpenCL demos for NVidia (GPU)" OFF) + ENDIF () +ENDIF() + +OPTION(BUILD_CPU_DEMOS "Build original Bullet CPU demos" ON) + + + +OPTION(INTERNAL_UPDATE_SERIALIZATION_STRUCTURES "Internal update serialization structures" OFF) +IF (INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) +ADD_DEFINITIONS( -DBT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) +ENDIF (INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) + +IF (USE_DOUBLE_PRECISION) +ADD_DEFINITIONS( -DBT_USE_DOUBLE_PRECISION) +ENDIF (USE_DOUBLE_PRECISION) + +IF(USE_GRAPHICAL_BENCHMARK) +ADD_DEFINITIONS( -DUSE_GRAPHICAL_BENCHMARK) +ENDIF (USE_GRAPHICAL_BENCHMARK) + +IF (WIN32) +OPTION(USE_GLUT "Use Glut" ON) +ADD_DEFINITIONS( -D_IRR_STATIC_LIB_ ) +ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) +ADD_DEFINITIONS( -D_CRT_SECURE_NO_DEPRECATE ) +ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) + +IF (USE_GLUT AND MSVC) + string (REPLACE "/D_WINDOWS" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) + remove_definitions(-D_WINDOWS ) +ENDIF() + + + +ELSE(WIN32) +OPTION(USE_GLUT "Use Glut" ON) +ENDIF(WIN32) + + +IF(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + + +# This is the shortcut to finding GLU, GLUT and OpenGL if they are properly installed on your system +# This should be the case. + +FIND_PACKAGE(OpenGL) +IF (OPENGL_FOUND) + MESSAGE("OPENGL FOUND") + MESSAGE(${OPENGL_LIBRARIES}) +ELSE (OPENGL_FOUND) + MESSAGE("OPENGL NOT FOUND") + SET(OPENGL_gl_LIBRARY opengl32) + SET(OPENGL_glu_LIBRARY glu32) +ENDIF (OPENGL_FOUND) + +# ADD_DEFINITIONS(-DBT_USE_FREEGLUT) + +FIND_PACKAGE(GLU) + +IF (USE_GLUT) + FIND_PACKAGE(GLUT) + IF (GLUT_FOUND) + MESSAGE("GLUT FOUND") + MESSAGE(${GLUT_glut_LIBRARY}) + ELSE (GLUT_FOUND) + IF (MINGW) + MESSAGE ("GLUT NOT FOUND not found, trying to use MINGW glut32") + SET(GLUT_glut_LIBRARY glut32) + #TODO add better GLUT detection for MinGW + SET(GLUT_FOUND TRUE) + ENDIF (MINGW) + IF (MSVC) + SET(GLUT_FOUND TRUE) + IF (CMAKE_CL_64) + message("Win64 using Glut/glut64.lib") + SET(GLUT_glut_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glut64.lib) + ELSE(CMAKE_CL_64) + message("Win32 using Glut/glut32.lib") + SET(GLUT_glut_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glut32.lib) + ENDIF (CMAKE_CL_64) + INCLUDE_DIRECTORIES(${BULLET_PHYSICS_SOURCE_DIR}/Glut) + ELSE() + MESSAGE("GLUT NOT FOUND") + ENDIF (MSVC) + ENDIF (GLUT_FOUND) + + IF(NOT WIN32) + # This is added for linux. This should always work if everything is installed and working fine. + INCLUDE_DIRECTORIES(/usr/include /usr/local/include) + ENDIF() +ENDIF(USE_GLUT) + + +OPTION(BUILD_DEMOS "Set when you want to build the demos" ON) +IF(BUILD_DEMOS) + IF(EXISTS ${PHYSICS_EFFECTS_SOURCE_DIR}/sample AND IS_DIRECTORY ${PHYSICS_EFFECTS_SOURCE_DIR}/sample) + SUBDIRS(sample) + ENDIF() +ENDIF(BUILD_DEMOS) + +# "Demos_ps3") +IF (MSVC) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF(EXISTS ${PHYSICS_EFFECTS_SOURCE_DIR}/Demos_ps3 AND IS_DIRECTORY ${PHYSICS_EFFECTS_SOURCE_DIR}/Demos_ps3) + MESSAGE("Demos_ps3 found") + SUBDIRS(Demos_ps3) + ENDIF() + ENDIF() +ENDIF(MSVC) + + +#OPTION(BUILD_EXTRAS "Set when you want to build the extras" OFF) +#IF(BUILD_EXTRAS) +# SUBDIRS(Extras) +#ENDIF(BUILD_EXTRAS) + +#Maya Dynamica plugin is moved to http://dynamica.googlecode.com + +SUBDIRS(src) + +IF("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles") + OPTION(INSTALL_LIBS "Set when you want to install libraries" OFF) +ELSE() + IF(APPLE AND FRAMEWORK) + OPTION(INSTALL_LIBS "Set when you want to install libraries" ON) + ELSE() +#by default, don't enable the 'INSTALL' option for Xcode and MSVC projectfiles + OPTION(INSTALL_LIBS "Set when you want to install libraries" OFF) + ENDIF() +ENDIF() + +IF(INSTALL_LIBS) + SET (LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) + SET (LIB_DESTINATION "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE STRING "Library directory name") + ## the following are directories where stuff will be installed to + SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include/bullet/" CACHE PATH "The subdirectory to the header prefix") + SET(PKGCONFIG_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/pkgconfig/" CACHE STRING "Base directory for pkgconfig files") + IF(NOT WIN32) + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/bullet.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/bullet.pc @ONLY) + INSTALL( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/bullet.pc + DESTINATION + ${PKGCONFIG_INSTALL_PREFIX}) + ENDIF(NOT WIN32) +ENDIF(INSTALL_LIBS) + +#INSTALL of other files requires CMake 2.6 +IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + OPTION(INSTALL_EXTRA_LIBS "Set when you want extra libraries installed" OFF) +ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + +OPTION(BUILD_UNIT_TESTS "Build Unit Tests" OFF) + +IF (BUILD_UNIT_TESTS) + SUBDIRS(UnitTests) +ENDIF() diff --git a/Extras/PhysicsEffects/README_Android.txt b/Extras/PhysicsEffects/README_Android.txt new file mode 100644 index 0000000..4df7dab --- /dev/null +++ b/Extras/PhysicsEffects/README_Android.txt @@ -0,0 +1,41 @@ +PhysicsEffects can be built and run on Android devices. The Android projects are +a mix of Java and C++ code. The code has been tested using Android NDK r5c. Build files +are provided for the NDK and ANT. Here are some instructions on how +to update the baseline PhysicsEffects branch of Bullet to support Android using the provided +files: + +1. For Windows platforms, download and install Cygwin (if it is not already installed) +2. Download and install the Android SDK. +3. Download and install the Android NDK. (The files provided have been tested with NDK r5c.) + +4. Set up these new environment variables: + + BULLET_PFX_ROOT_CYGWIN = path to your PhysicsEffects folder, for example: + BULLET_PFX_ROOT_CYGWIN=/cygdrive/d/tools/Bullet/Extras/PhysicsEffects + + CYGWIN_ROOT = path to where Cygwin is installed (Windows-style path) + ANDROID_NDK_ROOT = path to where the Android NDK is installed + +5. Open a Cygwin console. Browse to the PhysicsEffects/project/Android + folder. Then, for each package, starting with PfxLibrary, go into the + package folder and run the ndk-build command. For example: + + /PhysicsEffects/project/Android/PfxLibrary> /cygwin/d/tools/android-ndk-r5c/ndk-build + + Build every package using ndk-build. + + (It is possible to configure Eclipse to use ndk-build, but that is somewhat + tedious to do.) + +6. For each application package (PfxApp*) after running ndk-build use + ant compile + ant debug + + If your Android device is connected and setup, you can also run the app using + ant install + +7. If you run the app, you can interact with the touch interface: + + - Tap the screen to change scenes + - Pinch the screen to zoom in/out + - Drag the screen to rotate the camera diff --git a/Extras/PhysicsEffects/build/premake4.lua b/Extras/PhysicsEffects/build/premake4.lua new file mode 100644 index 0000000..ea7fa9d --- /dev/null +++ b/Extras/PhysicsEffects/build/premake4.lua @@ -0,0 +1,40 @@ +solution "00_MySolution" + + configurations {"Debug", "Release"} + configuration "Release" + flags { "Optimize", "StaticRuntime", "NoRTTI", "NoExceptions"} + configuration "Debug" + flags { "Symbols", "StaticRuntime" , "NoRTTI", "NoExceptions"} + platforms {"x32", "x64"} + configuration "x32" + libdirs {"$(ATISTREAMSDKROOT)/lib/x86"} + configuration "x64" + libdirs {"$(ATISTREAMSDKROOT)/lib/x86_64"} + targetsuffix "_64" + + configuration {"x64", "debug"} + targetsuffix "_x64_debug" + configuration {"x64", "release"} + targetsuffix "_x64" + configuration {"x32", "debug"} + targetsuffix "_debug" + + + language "C++" + location "build" + targetdir "bin" + + include "../src/base_level" + include "../src/low_level" + include "../src/util" + + include "../sample/api_physics_effects/0_console" + include "../sample/api_physics_effects/1_simple" + include "../sample/api_physics_effects/2_stable" + include "../sample/api_physics_effects/3_sleep" + include "../sample/api_physics_effects/4_motion_type" + include "../sample/api_physics_effects/5_raycast" + include "../sample/api_physics_effects/6_joint" + + + \ No newline at end of file diff --git a/Extras/PhysicsEffects/build/vs2008.bat b/Extras/PhysicsEffects/build/vs2008.bat new file mode 100644 index 0000000..c8841fe --- /dev/null +++ b/Extras/PhysicsEffects/build/vs2008.bat @@ -0,0 +1,3 @@ +..\..\..\msvc\premake4 clean +..\..\..\msvc\premake4 vs2008 +rename build vs2008 \ No newline at end of file diff --git a/Extras/PhysicsEffects/build/vs2010.bat b/Extras/PhysicsEffects/build/vs2010.bat new file mode 100644 index 0000000..f93b249 --- /dev/null +++ b/Extras/PhysicsEffects/build/vs2010.bat @@ -0,0 +1,3 @@ +..\..\..\msvc\premake4 clean +..\..\..\msvc\premake4 vs2010 +rename build vs2010 \ No newline at end of file diff --git a/Extras/PhysicsEffects/include/BulletPhysicsEffects/btBulletPhysicsEffectsWorld.cpp b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btBulletPhysicsEffectsWorld.cpp new file mode 100644 index 0000000..90752fc --- /dev/null +++ b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btBulletPhysicsEffectsWorld.cpp @@ -0,0 +1,479 @@ +/* +Physics Effects Copyright(C) 2011 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "btBulletPhysicsEffectsWorld.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "BulletDynamics/ConstraintSolver/btContactConstraint.h" +#include "LinearMath/btAabbUtil2.h" +#include "BulletMultiThreaded/SequentialThreadSupport.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "LinearMath/btIDebugDraw.h" +#include "LinearMath/btQuickprof.h" + +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" + +#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h" + + +#include "BulletPhysicsEffects/btLowLevelData.h" +#include +#include +#include "btLowLevelBroadphase.h" + + +#include "BulletCollision/CollisionShapes/btCompoundShape.h"//required for shape conversion +#include "BulletCollision/CollisionShapes/btConvexHullShape.h"//required for shape conversion +#include "BulletCollision/CollisionShapes/btCylinderShape.h"//required for shape conversion +#include "BulletCollision/CollisionShapes/btSphereShape.h"//required for shape conversion +#include "BulletCollision/CollisionShapes/btCapsuleShape.h"//required for shape conversion +#include "BulletCollision/CollisionShapes/btBoxShape.h"//required for shape conversion +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" +#include "BulletMultiThreaded/vectormath2bullet.h" + +#ifdef _WIN32 +#include "BulletMultiThreaded/Win32ThreadSupport.h" +#endif + + +#ifdef USE_PE_GATHER_SCATTER_SPURS_TASK +#include "SpuDispatch/BulletPEGatherScatterSpursSupport.h" +#include "SpuDispatch/SpuPEGatherScatterTaskProcess.h" +#endif + + +btBulletPhysicsEffectsWorld::btBulletPhysicsEffectsWorld(btLowLevelData* lowLevelData, btDispatcher* dispatcher,btLowLevelBroadphase* broadphase,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration, btThreadSupportInterface* threadSupport) +:btDiscreteDynamicsWorld(dispatcher,broadphase,constraintSolver,collisionConfiguration), +m_lowLevelData(lowLevelData) +{ + +#ifdef USE_PE_GATHER_SCATTER_SPURS_TASK + int numGatherScatterSpus = threadSupport->getNumTasks(); + m_PEGatherScatterProcess = new SpuPEGatherScatterTaskProcess(threadSupport,numGatherScatterSpus); +#endif //USE_PE_GATHER_SCATTER_SPURS_TASK + + m_lowLevelStates.resize(broadphase->m_maxHandles);//or use expandNonInitializing? + m_lowLevelBodies.resize(broadphase->m_maxHandles); + m_lowLevelSolverBodies.resize(broadphase->m_maxHandles); + m_lowLevelCollidables.resize(broadphase->m_maxHandles); + + m_lowLevelData->m_states = &m_lowLevelStates[0]; + m_lowLevelData->m_collidables = &m_lowLevelCollidables[0]; + m_lowLevelData->m_bodies = &m_lowLevelBodies[0]; + m_lowLevelData->m_solverBodies = &m_lowLevelSolverBodies[0]; + m_lowLevelData->m_numRigidBodies = broadphase->m_maxHandles; + +} + +btBulletPhysicsEffectsWorld::~btBulletPhysicsEffectsWorld() +{ +#ifdef USE_PE_GATHER_SCATTER_SPURS_TASK + delete m_PEGatherScatterProcess; +#endif + +} + + + +void btBulletPhysicsEffectsWorld::integrateTransforms(btScalar timeStep) +{ + ///integrate transforms +#ifdef USE_PE_GATHER_SCATTER_SPURS_TASK + if (getDispatchInfo().m_enableSPU) + { + BT_PROFILE("integrateTransformsSPU"); + int numRemainingObjects = m_nonStaticRigidBodies.size(); + + int batchSize = PARALLEL_BATCH_SIZE; + int startIndex = 0; + while (numRemainingObjects>0) + { + int currentBatchSize = numRemainingObjects > batchSize? batchSize : numRemainingObjects; + + //issue and flush is likely to be called every frame, move the construction and deletion out of the inner loop (at construction/init etc) + m_PEGatherScatterProcess->issueTask( + CMD_SAMPLE_INTEGRATE_BODIES, + &m_nonStaticRigidBodies[0], + 0, + 0, + startIndex, + currentBatchSize); + numRemainingObjects -= currentBatchSize; + startIndex += currentBatchSize; + } + + m_PEGatherScatterProcess->flush(); + } else +#endif //USE_PE_GATHER_SCATTER_SPURS_TASK + { +// BT_PROFILE("integrateTransforms"); + btDiscreteDynamicsWorld::integrateTransforms(timeStep); + } +} + + +void btBulletPhysicsEffectsWorld::predictUnconstraintMotion(btScalar timeStep) +{ +#ifdef USE_PE_GATHER_SCATTER_SPURS_TASK + if (getDispatchInfo().m_enableSPU) + { + BT_PROFILE("predictUnconstraintMotionSPU"); + int numRemainingObjects = m_nonStaticRigidBodies.size(); + + int batchSize = PARALLEL_BATCH_SIZE; + int startIndex=0; + while (numRemainingObjects>0) + { + int currentBatchSize = numRemainingObjects > batchSize? batchSize : numRemainingObjects; + + //issue and flush is likely to be called every frame, move the construction and deletion out of the inner loop (at construction/init etc) + m_PEGatherScatterProcess->issueTask( + CMD_SAMPLE_PREDICT_MOTION_BODIES, + &m_nonStaticRigidBodies[0], + 0, + 0, + startIndex, + currentBatchSize); + numRemainingObjects -= currentBatchSize; + startIndex += currentBatchSize; + } + + m_PEGatherScatterProcess->flush(); + } + else +#endif //USE_PE_GATHER_SCATTER_SPURS_TASK + { + btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep); + } + + for ( int i=0;isetHitFraction(1.f); + + if (body->isActive() && (!body->isStaticOrKinematicObject())) + { + syncRigidBodyState(body); + } + } +} + + + +void btBulletPhysicsEffectsWorld::solveConstraints(btContactSolverInfo& solverInfo) +{ + BT_PROFILE("solveConstraints"); + + btCollisionDispatcher* disp = (btCollisionDispatcher*) getDispatcher(); + int numBodies = getNumCollisionObjects(); + + btPersistentManifold** manifolds = disp->getInternalManifoldPointer(); + + int numManifolds = disp->getNumManifolds(); + + + if ((getNumCollisionObjects()>0) && (numManifolds + m_constraints.size()>0)) + { + + btCollisionObject** bodies = numBodies ? &getCollisionObjectArray()[0] : 0; + btTypedConstraint** constraints = m_constraints.size() ? &m_constraints[0] : 0; + + getConstraintSolver()->solveGroup( bodies,numBodies, disp->getInternalManifoldPointer(),numManifolds, constraints, m_constraints.size() ,m_solverInfo,m_debugDrawer,m_stackAlloc,disp); + } +} + + +void btBulletPhysicsEffectsWorld::calculateSimulationIslands() +{ + +} + +static void convertShape(btCollisionShape* bulletShape, btAlignedObjectArray& shapes) +{ + switch (bulletShape->getShapeType()) + { + case BOX_SHAPE_PROXYTYPE: + { + btBoxShape* boxshape = (btBoxShape*)bulletShape; + sce::PhysicsEffects::PfxBox box(boxshape->getHalfExtentsWithMargin().getX(),boxshape->getHalfExtentsWithMargin().getY(),boxshape->getHalfExtentsWithMargin().getZ()); + sce::PhysicsEffects::PfxShape& shape = shapes.expand(); + shape.reset(); + shape.setBox(box); + break; + } + + case TRIANGLE_MESH_SHAPE_PROXYTYPE: + { + btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*) bulletShape; + + int numSubParts = trimesh->getMeshInterface()->getNumSubParts(); + btAssert(numSubParts>0); + + for (int i=0;igetMeshInterface()->getLockedVertexIndexBase(&vertexBase,numVerts,vertexType,vertexStride,&indexBase,indexStride,numFaces,indexType,i); + + sce::PhysicsEffects::PfxCreateLargeTriMeshParam param; + btAssert(param.flag&SCE_PFX_MESH_FLAG_16BIT_INDEX); + unsigned short int* copyIndices = new unsigned short int[numFaces*3]; + switch (indexType) + { + case PHY_UCHAR: + { + for (int p=0;pgetRadius()); + sce::PhysicsEffects::PfxShape& shape = shapes.expand(); + shape.reset(); + shape.setSphere(sphere); + break; + } + case CAPSULE_SHAPE_PROXYTYPE: + { + btCapsuleShape* capsuleshape= (btCapsuleShape*)bulletShape;//assume btCapsuleShapeX for now + sce::PhysicsEffects::PfxCapsule capsule(capsuleshape->getHalfHeight(),capsuleshape->getRadius()); + sce::PhysicsEffects::PfxShape& shape = shapes.expand(); + shape.reset(); + shape.setCapsule(capsule); + break; + } + case CYLINDER_SHAPE_PROXYTYPE: + { + btCylinderShape* cylindershape= (btCylinderShape*)bulletShape;//assume btCylinderShapeX for now + sce::PhysicsEffects::PfxCylinder cylinder(cylindershape->getHalfExtentsWithMargin()[0],cylindershape->getRadius()); + sce::PhysicsEffects::PfxShape& shape = shapes.expand(); + shape.reset(); + shape.setCylinder(cylinder); + break; + } + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + btConvexHullShape* convexHullShape = (btConvexHullShape*)bulletShape; + + sce::PhysicsEffects::PfxConvexMesh* convex = new sce::PhysicsEffects::PfxConvexMesh(); + convex->m_numVerts = convexHullShape->getNumPoints(); + convex->m_numIndices = 0;//todo for ray intersection test support + + for (int i=0;im_numVerts;i++) + { + convex->m_verts[i].setX(convexHullShape->getPoints()[i].getX()); + convex->m_verts[i].setY(convexHullShape->getPoints()[i].getY()); + convex->m_verts[i].setZ(convexHullShape->getPoints()[i].getZ()); + } + + convex->updateAABB(); + sce::PhysicsEffects::PfxShape& shape = shapes.expand(); + shape.reset(); + shape.setConvexMesh(convex); + break; + } + case COMPOUND_SHAPE_PROXYTYPE: + { + btCompoundShape* compound = (btCompoundShape*) bulletShape; + + for (int s=0;sgetNumChildShapes();s++) + { + convertShape(compound->getChildShape(s),shapes); + + sce::PhysicsEffects::PfxMatrix3 rotMat = getVmMatrix3(compound->getChildTransform(s).getBasis()); + sce::PhysicsEffects::PfxVector3 translate = getVmVector3(compound->getChildTransform(s).getOrigin()); + sce::PhysicsEffects::PfxTransform3 childtransform(rotMat,translate); + shapes[shapes.size()-1].setOffsetTransform(childtransform); + } + + break; + } + + + default: + { + btAssert(0); + } + }; + +} + +void btBulletPhysicsEffectsWorld::createStateAndCollidable(btRigidBody* body) +{ + + int objectIndex = body->getBroadphaseProxy()->m_uniqueId; + btAssert(objectIndex>=0); + //btAssert(objectIndexreset(); + pfxbody->reset(); + pfxcollidable->reset(); + + + + pfxbody->setFriction(body->getFriction()); + pfxbody->setRestitution(body->getRestitution()); + + if (body->getInvMass()) + { + btScalar mass = 1.f/body->getInvMass(); + pfxbody->setMass(mass); + Vectormath::Aos::Matrix3 inertiaInv = inertiaInv.identity(); + inertiaInv.setElem(0,0,body->getInvInertiaDiagLocal().getX()); + inertiaInv.setElem(1,1,body->getInvInertiaDiagLocal().getY()); + inertiaInv.setElem(2,2,body->getInvInertiaDiagLocal().getZ()); + pfxbody->setInertiaInv(inertiaInv); + pfxstate->setMotionType(sce::PhysicsEffects::kPfxMotionTypeActive); + } else + { + pfxstate->setMotionType(sce::PhysicsEffects::kPfxMotionTypeFixed); + } + + btAlignedObjectArray shapes; + + convertShape(body->getCollisionShape(), shapes); + + btAssert(shapes.size()>0); + + if (shapes.size()==1) + { + pfxcollidable->addShape(shapes[0]); + pfxcollidable->finish(); + } else + { + if (shapes.size()>1) + { + sce::PhysicsEffects::PfxUInt16* ints=new sce::PhysicsEffects::PfxUInt16[shapes.size()]; + sce::PhysicsEffects::PfxShape* pfxshapes = new sce::PhysicsEffects::PfxShape[shapes.size()]; + int p; + for (p=0;preset(pfxshapes,ints,shapes.size()); + + for (p=0;paddShape(pfxshapes[p]); + } + + pfxcollidable->finish(); + } + } + pfxstate->setRigidBodyId(objectIndex); + + syncRigidBodyState(body); + + +} + + + +void btBulletPhysicsEffectsWorld::syncRigidBodyState(btRigidBody* body) +{ + int objectIndex = body->getBroadphaseProxy()->m_uniqueId; + sce::PhysicsEffects::PfxRigidState* pfxstate = &m_lowLevelStates[objectIndex]; + + pfxstate->setPosition(sce::PhysicsEffects::PfxVector3(body->getWorldTransform().getOrigin()[0],body->getWorldTransform().getOrigin()[1],body->getWorldTransform().getOrigin()[2])); + sce::PhysicsEffects::PfxQuat rot(body->getOrientation().getX(),body->getOrientation().getY(),body->getOrientation().getZ(),body->getOrientation().getW()); + pfxstate->setOrientation(rot); + +} + + + +void btBulletPhysicsEffectsWorld::addRigidBody(btRigidBody* body) +{ + + btDiscreteDynamicsWorld::addRigidBody(body); + + //create a state and collidable + + createStateAndCollidable(body); + + + + + +// m_lowLevelData->m_numRigidBodies++; +// btAssert(m_lowLevelData->m_numRigidBodiesm_maxNumRigidBodies); + +} + +void btBulletPhysicsEffectsWorld::addRigidBody(btRigidBody* body, short group, short mask) +{ + btDiscreteDynamicsWorld::addRigidBody(body,group,mask); + +} + +void btBulletPhysicsEffectsWorld::removeRigidBody(btRigidBody* body) +{ + btDiscreteDynamicsWorld::removeRigidBody(body); + +// m_lowLevelData->m_numRigidBodies--; +// btAssert(m_lowLevelData->m_numRigidBodies>=0); +} + diff --git a/Extras/PhysicsEffects/include/BulletPhysicsEffects/btBulletPhysicsEffectsWorld.h b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btBulletPhysicsEffectsWorld.h new file mode 100644 index 0000000..d6ffe34 --- /dev/null +++ b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btBulletPhysicsEffectsWorld.h @@ -0,0 +1,79 @@ +/* +Physics Effects Copyright(C) 2011 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + + #ifndef _BT_PARALLEL_DYNAMICS_WORLD_H +#define _BT_PARALLEL_DYNAMICS_WORLD_H + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +#include "physics_effects/base_level/rigidbody/pfx_rigid_body.h" +#include "physics_effects/base_level/rigidbody/pfx_rigid_state.h" +#include "physics_effects/base_level/collision/pfx_collidable.h" +#include "physics_effects/base_level/solver/pfx_solver_body.h" + +//#define USE_PE_GATHER_SCATTER_SPURS_TASK 1 + + +class btThreadSupportInterface; +class SpuPEGatherScatterTaskProcess; +struct CellSpurs; +class SpuBatchRaycaster; +struct btLowLevelBroadphase; + +#define PARALLEL_BATCH_SIZE 64 + + +///btBulletPhysicsEffectsWorld adds parallel processing for integration/motion prediction +class btBulletPhysicsEffectsWorld : public btDiscreteDynamicsWorld +{ + +protected: + btAlignedObjectArray m_lowLevelStates; + btAlignedObjectArray m_lowLevelBodies; + btAlignedObjectArray m_lowLevelSolverBodies; + btAlignedObjectArray m_lowLevelCollidables; + + //PfxSolverBody solverBodies[NUM_RIGIDBODIES]; + + class SpuPEGatherScatterTaskProcess* m_PEGatherScatterProcess; + + struct btLowLevelData* m_lowLevelData; + + void createStateAndCollidable(btRigidBody* body); + + void syncRigidBodyState(btRigidBody* body); +public: + + btBulletPhysicsEffectsWorld(struct btLowLevelData* lowLevelData, btDispatcher* dispatcher,btLowLevelBroadphase* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration, btThreadSupportInterface* threadSupport); + + virtual ~btBulletPhysicsEffectsWorld(); + + virtual void predictUnconstraintMotion(btScalar timeStep); + + virtual void integrateTransforms(btScalar timeStep); + + virtual void solveConstraints(btContactSolverInfo& solverInfo); + + virtual void calculateSimulationIslands(); + + virtual void addRigidBody(btRigidBody* body); + + virtual void addRigidBody(btRigidBody* body, short group, short mask); + + virtual void removeRigidBody(btRigidBody* body); + + +}; +#endif //_BT_PARALLEL_DYNAMICS_WORLD_H \ No newline at end of file diff --git a/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelBroadphase.cpp b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelBroadphase.cpp new file mode 100644 index 0000000..ff05ed6 --- /dev/null +++ b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelBroadphase.cpp @@ -0,0 +1,431 @@ +/* +Physics Effects Copyright(C) 2011 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "btLowLevelBroadphase.h" + + +#include "BulletMultiThreaded/PlatformDefinitions.h" +#include "BulletCollision/NarrowphaseCollision/btPersistentManifold.h" + +// Include base level headers +#include "physics_effects/base_level/pfx_base_level_include.h" + +// Include low level headers +#include "physics_effects/low_level/broadphase/pfx_broadphase.h" + +#include "physics_effects/low_level/sort/pfx_parallel_sort.h" + +#include "BulletMultiThreaded/vectormath2bullet.h" + +#include "physics_effects/base_level/base/pfx_vec_utils.h" +#include "physics_effects/base_level/collision/pfx_aabb.h" +#include "physics_effects/base_level/rigidbody/pfx_rigid_state.h" +#include "btLowLevelData.h" + +using namespace sce::PhysicsEffects; + +//E Temporary buffers +#define POOL_BYTES (5*1024*1024) +unsigned char SCE_PFX_ALIGNED(128) poolBuff[POOL_BYTES]; + +//E Stack allocator for temporary buffers +PfxHeapManager pool(poolBuff,POOL_BYTES); + + +/////////////////////////////////////////////////////////////////////////////// +// Broadphase + + + + + +// +btLowLevelBroadphase::btLowLevelBroadphase(btLowLevelData* lowLevelData, btOverlappingPairCache* paircache, int maxProxies) +:m_lowLevelData(lowLevelData) +{ + + m_guidGenerator = 1; + m_releasepaircache = (paircache!=0)?false:true; + m_paircache = paircache? paircache : new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); + m_clientData.m_bp = this; + m_clientData.m_dispatcher = 0; + + + m_broadphaseAabbMin.setValue(1e30,1e30,1e30); + m_broadphaseAabbMax.setValue(-1e30,-1e30,-1e30); + + // allocate handles buffer and put all handles on free list + m_pHandlesRawPtr = btAlignedAlloc(sizeof(btLowLevelBroadphaseProxy)*maxProxies,16); + m_pHandles = new(m_pHandlesRawPtr) btLowLevelBroadphaseProxy[maxProxies]; + m_maxHandles = maxProxies; + m_numHandles = 0; + m_firstFreeHandle = 0; + m_LastHandleIndex = -1; + + + { + for (int i = m_firstFreeHandle; i < maxProxies; i++) + { + m_pHandles[i].SetNextFree(i + 1); + m_pHandles[i].m_uniqueId = i;//start from zero, so we can re-use the uid for body ID + } + m_pHandles[maxProxies - 1].SetNextFree(0); + + } + +} + +// +btLowLevelBroadphase::~btLowLevelBroadphase() +{ + if(m_releasepaircache) + { + m_paircache->~btOverlappingPairCache(); + btAlignedFree(m_paircache); + } +} + + +btBroadphaseProxy* btLowLevelBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* /*dispatcher*/,void* multiSapProxy) +{ + if (m_numHandles >= m_maxHandles) + { + btAssert(0); + return 0; //should never happen, but don't let the game crash ;-) + } + btAssert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]); + + int newHandleIndex = allocHandle(); + btLowLevelBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btLowLevelBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy); + m_uid2ptr.insert(proxy->m_uniqueId,proxy); + return proxy; +} + +void btLowLevelBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher) +{ + m_uid2ptr.remove(proxyOrg->m_uniqueId); + + btLowLevelBroadphaseProxy* proxy0 = static_cast(proxyOrg); + freeHandle(proxy0); + + m_paircache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher); + + //validate(); + +} + +void btLowLevelBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const +{ + const btLowLevelBroadphaseProxy* sbp = getLowLevelProxyFromProxy(proxy); + aabbMin = sbp->m_aabbMin; + aabbMax = sbp->m_aabbMax; +} + +void btLowLevelBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* /*dispatcher*/) +{ + btLowLevelBroadphaseProxy* sbp = getLowLevelProxyFromProxy(proxy); + sbp->m_aabbMin = aabbMin; + sbp->m_aabbMax = aabbMax; +} + + +bool btLowLevelBroadphase::aabbOverlap(btLowLevelBroadphaseProxy* proxy0,btLowLevelBroadphaseProxy* proxy1) +{ + return proxy0->m_aabbMin[0] <= proxy1->m_aabbMax[0] && proxy1->m_aabbMin[0] <= proxy0->m_aabbMax[0] && + proxy0->m_aabbMin[1] <= proxy1->m_aabbMax[1] && proxy1->m_aabbMin[1] <= proxy0->m_aabbMax[1] && + proxy0->m_aabbMin[2] <= proxy1->m_aabbMax[2] && proxy1->m_aabbMin[2] <= proxy0->m_aabbMax[2]; + +} + + +PfxBroadphasePair* btLowLevelBroadphase::getCurrentPairs() +{ + return &m_lowLevelData->m_pairsBuff[m_lowLevelData->m_pairSwap][0]; +} + +const PfxBroadphasePair* btLowLevelBroadphase::getCurrentPairs() const +{ + return &m_lowLevelData->m_pairsBuff[m_lowLevelData->m_pairSwap][0]; +} + +int btLowLevelBroadphase::getNumCurrentPairs() const +{ + return m_lowLevelData->m_numPairs[m_lowLevelData->m_pairSwap]; +} + +void btLowLevelBroadphase::broadphase(PfxSortData32* proxies, int numRigidBodies, int axis, btDispatcher* dispatcher) +{ + m_lowLevelData->m_pairSwap = 1-m_lowLevelData->m_pairSwap; + + unsigned int &numPreviousPairs = m_lowLevelData->m_numPairs[1-m_lowLevelData->m_pairSwap]; + unsigned int &numCurrentPairs = m_lowLevelData->m_numPairs[m_lowLevelData->m_pairSwap]; + PfxBroadphasePair *previousPairs = &m_lowLevelData->m_pairsBuff[1-m_lowLevelData->m_pairSwap][0]; + PfxBroadphasePair *currentPairs = &m_lowLevelData->m_pairsBuff[m_lowLevelData->m_pairSwap][0]; + + + //E Create broadpahse proxies + { +// for(int i=0;im_maxPairs); + findPairsParam.pairBuff = pool.allocate(findPairsParam.pairBytes); + findPairsParam.workBytes = pfxGetWorkBytesOfFindPairs(m_lowLevelData->m_maxPairs); + findPairsParam.workBuff = pool.allocate(findPairsParam.workBytes); + findPairsParam.proxies = proxies; + findPairsParam.numProxies = numRigidBodies; + findPairsParam.maxPairs = m_lowLevelData->m_maxPairs; + findPairsParam.axis = axis; + + PfxFindPairsResult findPairsResult; + + + int ret = pfxFindPairs(findPairsParam,findPairsResult); + if(ret != SCE_PFX_OK) + SCE_PFX_PRINTF("pfxFindPairs failed %d\n",ret); + + pool.deallocate(findPairsParam.workBuff); + + //E Decompose overlapped pairs into 3 arrays + PfxDecomposePairsParam decomposePairsParam; + decomposePairsParam.pairBytes = pfxGetPairBytesOfDecomposePairs(numPreviousPairs,findPairsResult.numPairs); + decomposePairsParam.pairBuff = pool.allocate(decomposePairsParam.pairBytes); + decomposePairsParam.workBytes = pfxGetWorkBytesOfDecomposePairs(numPreviousPairs,findPairsResult.numPairs); + decomposePairsParam.workBuff = pool.allocate(decomposePairsParam.workBytes); + decomposePairsParam.previousPairs = previousPairs; + decomposePairsParam.numPreviousPairs = numPreviousPairs; + decomposePairsParam.currentPairs = findPairsResult.pairs; // Set pairs from pfxFindPairs() + decomposePairsParam.numCurrentPairs = findPairsResult.numPairs; // Set the number of pairs from pfxFindPairs() + + PfxDecomposePairsResult decomposePairsResult; + + ret = pfxDecomposePairs(decomposePairsParam,decomposePairsResult); + if(ret != SCE_PFX_OK) + SCE_PFX_PRINTF("pfxDecomposePairs failed %d\n",ret); + + pool.deallocate(decomposePairsParam.workBuff); + + PfxBroadphasePair *outNewPairs = decomposePairsResult.outNewPairs; + PfxBroadphasePair *outKeepPairs = decomposePairsResult.outKeepPairs; + PfxBroadphasePair *outRemovePairs = decomposePairsResult.outRemovePairs; + PfxUInt32 numOutNewPairs = decomposePairsResult.numOutNewPairs; + PfxUInt32 numOutKeepPairs = decomposePairsResult.numOutKeepPairs; + PfxUInt32 numOutRemovePairs = decomposePairsResult.numOutRemovePairs; + + for (int i=0;iremoveOverlappingPair(proxyA,proxyB,dispatcher); + + //free low level contacts + m_lowLevelData->m_contactIdPool[m_lowLevelData->m_numContactIdPool++] = pfxGetContactId(outRemovePairs[i]); + + } + + for (int i=0;iaddOverlappingPair(proxyA,proxyB); + + //initialize low level contacts + int cId = 0; + if(m_lowLevelData->m_numContactIdPool > 0) { + cId = m_lowLevelData->m_contactIdPool[--m_lowLevelData->m_numContactIdPool]; + } + else { + cId = m_lowLevelData->m_numContacts++; + } + if(cId >= m_lowLevelData->m_maxContacts) { + cId = 0; + } + SCE_PFX_ASSERT(cId < m_lowLevelData->m_maxContacts); + pfxSetContactId(outNewPairs[i],cId); + PfxContactManifold &contact = m_lowLevelData->m_contacts[cId]; + int sz = sizeof(PfxContactManifold); + int sz2 = sizeof(btPersistentManifold); + int sz3 = 4*3*sizeof(btConstraintRow); + contact.reset(pfxGetObjectIdA(outNewPairs[i]),pfxGetObjectIdB(outNewPairs[i])); + contact.setCompositeFriction(0.1f); + btpair->m_internalTmpValue = cId; + } + + + //E Merge 'new' and 'keep' pairs + numCurrentPairs = 0; + for(PfxUInt32 i=0;im_aabbMin); + PfxVector3 maxRig = getVmVector3(bulletProxy->m_aabbMax); + + PfxVecInt3 aabbMin,aabbMax; + pfxConvertCoordWorldToLocal(worldCenter,worldExtent,minRig,maxRig,aabbMin,aabbMax); + + pfxSetXMin(proxy,aabbMin.getX()); + pfxSetXMax(proxy,aabbMax.getX()); + pfxSetYMin(proxy,aabbMin.getY()); + pfxSetYMax(proxy,aabbMax.getY()); + pfxSetZMin(proxy,aabbMin.getZ()); + pfxSetZMax(proxy,aabbMax.getZ()); + pfxSetKey(proxy,aabbMin.get(axis)); + pfxSetObjectId(proxy,rigidbodyId); + pfxSetMotionMask(proxy, kPfxMotionTypeActive); + pfxSetSelf(proxy,bulletProxy->m_collisionFilterGroup); + pfxSetTarget(proxy,bulletProxy->m_collisionFilterMask); + + return ret; +} + +void btLowLevelBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + + //set the broadphase proxies + + btAlignedObjectArray proxies; + proxies.reserve(m_LastHandleIndex); + + //E Find the axis along which all rigid bodies are most widely positioned + int axis = 0; + int i; + PfxVector3 s(0.0f),s2(0.0f); + + PfxVector3 worldMin(-1000);//PFX_FLT_MAX); + PfxVector3 worldMax(1000);//-PFX_FLT_MAX); + + int numRigidBodies = 0; + for (i=0; i <= m_LastHandleIndex; i++) + { + btLowLevelBroadphaseProxy* proxy0 = &m_pHandles[i]; + if(!proxy0->m_clientObject) + { + continue; + } + + PfxVector3 pe_pos = getVmVector3(0.5f*(proxy0->m_aabbMax+proxy0->m_aabbMin)); + PfxVector3 pe_min = getVmVector3(proxy0->m_aabbMin); + PfxVector3 pe_max = getVmVector3(proxy0->m_aabbMax); + numRigidBodies++; + //worldMin = minPerElem(worldMin,pe_min); + //worldMax = maxPerElem(worldMax,pe_max); + + s += pe_pos; + s2 += mulPerElem(pe_pos,pe_pos); + } + + + if (numRigidBodies) + { + PfxVector3 v = s2 - mulPerElem(s,s) / (float)numRigidBodies; + if(v[1] > v[0]) + axis = 1; + if(v[2] > v[axis]) + axis = 2; + } + + PfxVector3 worldCenter = 0.5f*(worldMax+worldMin); + PfxVector3 worldExtent = 0.5f*(worldMax-worldMin); + + for (i=0; i <= m_LastHandleIndex; i++) + { + btLowLevelBroadphaseProxy* proxy0 = &m_pHandles[i]; + if(!proxy0->m_clientObject) + { + continue; + } + + PfxBroadphaseProxy& proxy = proxies.expandNonInitializing(); + MyUpdateBroadphaseProxy(proxy,proxy0->m_uniqueId,proxy0,worldCenter,worldExtent,axis); + + } + + //find pairs, and call 'addOverlappingPair' for new pairs and 'removeOverlappingPair' for removed pairs + broadphase(&proxies[0],proxies.size(),axis, dispatcher); +} + + +// +btOverlappingPairCache* btLowLevelBroadphase::getOverlappingPairCache() +{ + return(m_paircache); +} + +// +const btOverlappingPairCache* btLowLevelBroadphase::getOverlappingPairCache() const +{ + return(m_paircache); +} + + +void btLowLevelBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const +{ + aabbMin = m_broadphaseAabbMin; + aabbMax = m_broadphaseAabbMax; +} + +void btLowLevelBroadphase::printStats() +{ +} + +void btLowLevelBroadphase::setNumTasks(int numTasks) +{ +} diff --git a/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelBroadphase.h b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelBroadphase.h new file mode 100644 index 0000000..eb2dccf --- /dev/null +++ b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelBroadphase.h @@ -0,0 +1,182 @@ +/* +Physics Effects Copyright(C) 2011 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +///btLowLevelBroadphase implementation +#ifndef BT_LOW_LEVEL_BROADPHASE_H +#define BT_LOW_LEVEL_BROADPHASE_H + +#include "BulletCollision/BroadphaseCollision/btDbvt.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" + +#include "physics_effects/base_level/broadphase/pfx_broadphase_pair.h" +#include "LinearMath/btHashMap.h" + +struct btLowLevelBroadphase; +struct btLowLevelData; + +namespace sce +{ + namespace PhysicsEffects + { + struct PfxSortData32; + }; +}; + +struct btMyClientData +{ + btDispatcher* m_dispatcher; + btLowLevelBroadphase* m_bp; +}; + +struct btLowLevelBroadphaseProxy : public btBroadphaseProxy +{ + int m_nextFree; + +// int m_handleId; + + + btLowLevelBroadphaseProxy() {}; + + btLowLevelBroadphaseProxy(const btVector3& minpt,const btVector3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy) + :btBroadphaseProxy(minpt,maxpt,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy) + { + (void)shapeType; + } + + + SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;} + SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;} + + + + +}; + +///btLowLevelBroadphase is a binding between Open Physics low-level broadphase and Bullet, through the btBroadphaseInterface + +struct btLowLevelBroadphase : btBroadphaseInterface +{ + + int m_numHandles; // number of active handles + int m_maxHandles; // max number of handles + int m_LastHandleIndex; + + btLowLevelBroadphaseProxy* m_pHandles; // handles pool + + void* m_pHandlesRawPtr; + int m_firstFreeHandle; // free handles list + + btOverlappingPairCache* m_paircache; // Pair cache + bool m_releasepaircache; // Release pair cache on delete + int m_guidGenerator; + btVector3 m_broadphaseAabbMin; + btVector3 m_broadphaseAabbMax; + + btMyClientData m_clientData; + + btLowLevelData* m_lowLevelData; + btHashMap m_uid2ptr; + + + int allocHandle() + { + btAssert(m_numHandles < m_maxHandles); + int freeHandle = m_firstFreeHandle; + m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree(); + m_numHandles++; + if(freeHandle > m_LastHandleIndex) + { + m_LastHandleIndex = freeHandle; + } + return freeHandle; + } + + void freeHandle(btLowLevelBroadphaseProxy* proxy) + { + int handle = int(proxy-m_pHandles); + btAssert(handle >= 0 && handle < m_maxHandles); + if(handle == m_LastHandleIndex) + { + m_LastHandleIndex--; + } + proxy->SetNextFree(m_firstFreeHandle); + m_firstFreeHandle = handle; + + proxy->m_clientObject = 0; + + m_numHandles--; + } + + inline btLowLevelBroadphaseProxy* getLowLevelProxyFromProxy(btBroadphaseProxy* proxy) + { + btLowLevelBroadphaseProxy* proxy0 = static_cast(proxy); + return proxy0; + } + + inline const btLowLevelBroadphaseProxy* getLowLevelProxyFromProxy(btBroadphaseProxy* proxy) const + { + const btLowLevelBroadphaseProxy* proxy0 = static_cast(proxy); + return proxy0; + } + + + + inline bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) + { + btLowLevelBroadphaseProxy* p0 = getLowLevelProxyFromProxy(proxy0); + btLowLevelBroadphaseProxy* p1 = getLowLevelProxyFromProxy(proxy1); + return aabbOverlap(p0,p1); + } + + static bool aabbOverlap(btLowLevelBroadphaseProxy* proxy0,btLowLevelBroadphaseProxy* proxy1); + + void broadphase(sce::PhysicsEffects::PfxSortData32* proxies, int numRigidBodies, int axis, btDispatcher* dispatcher); + + sce::PhysicsEffects::PfxBroadphasePair* getCurrentPairs(); + const sce::PhysicsEffects::PfxBroadphasePair* getCurrentPairs() const; + int getNumCurrentPairs() const; + + + + /* Methods */ + btLowLevelBroadphase(btLowLevelData* lowLevelData, btOverlappingPairCache* paircache, int maxProxies = 16384);//,class PfxAllocator* allocator,class PfxStackAllocator* stackPool,void* spursInstance); + virtual ~btLowLevelBroadphase(); + + /* btBroadphaseInterface Implementation */ + btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); + void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)) + { + } + + virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) + { + } + + + virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; + void calculateOverlappingPairs(btDispatcher* dispatcher); + btOverlappingPairCache* getOverlappingPairCache(); + const btOverlappingPairCache* getOverlappingPairCache() const; + void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const; + virtual void printStats(); + + virtual void setNumTasks(int numTasks); + +}; + +#endif diff --git a/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelCollisionDispatcher.cpp b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelCollisionDispatcher.cpp new file mode 100644 index 0000000000000000000000000000000000000000..76fe8577481fbfb803d9482f1dac5808a08d1189 GIT binary patch literal 17292 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 literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelCollisionDispatcher.h b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelCollisionDispatcher.h new file mode 100644 index 0000000..98b1214 --- /dev/null +++ b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelCollisionDispatcher.h @@ -0,0 +1,127 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BT_LOW_LEVEL_COLLISION__DISPATCHER_H +#define BT_LOW_LEVEL_COLLISION__DISPATCHER_H + +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +struct btLowLevelBroadphase;//struct instead of class? +struct btLowLevelData; +///Tuning value to optimized SPU utilization +///Too small value means Task overhead is large compared to computation (too fine granularity) +///Too big value might render some SPUs are idle, while a few other SPUs are doing all work. +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 8 +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 16 +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 64 +#define SPU_BATCHSIZE_BROADPHASE_PAIRS 128 +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 256 +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 512 +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 1024 +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" + +class btLowLevelCollisionAlgorithm : public btCollisionAlgorithm +{ + btPersistentManifold* m_manifold; + +public: + + btLowLevelCollisionAlgorithm() + :m_manifold(0) + { + } + + btLowLevelCollisionAlgorithm(btPersistentManifold* manifold, btCollisionDispatcher* dispatcher) + :m_manifold(manifold) + { + m_dispatcher = dispatcher; + } + virtual ~btLowLevelCollisionAlgorithm() + { + if (m_manifold) + m_dispatcher->releaseManifold(m_manifold); + } + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) + { + btAssert(0); + } + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) + { + btAssert(0); + return 0.f; + } + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + manifoldArray.push_back(m_manifold); + } + +}; + + +///btLowLevelCollisionDispatcher can use SPU to gather and calculate collision detection +///Time of Impact, Closest Points and Penetration Depth. +class btLowLevelCollisionDispatcher : public btCollisionDispatcher +{ + + btLowLevelData* m_lowLevelData; + + btAlignedObjectArray m_manifoldArray; + btAlignedObjectArray m_algorithms; + +protected: + + void collision(); + +public: + + + btLowLevelCollisionDispatcher (btLowLevelData* lowLevelData, btCollisionConfiguration* collisionConfiguration, int maxNumManifolds); + + virtual ~btLowLevelCollisionDispatcher(); + + bool supportsDispatchPairOnSpu(int proxyType0,int proxyType1); + + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ; + + + + virtual btPersistentManifold* getNewManifold(void* b0,void* b1) + { + btAssert(0); + return 0; + } + virtual void releaseManifold(btPersistentManifold* manifold); + + + virtual void* allocateCollisionAlgorithm(int size) + { + btAssert(0); + return 0; + } + + virtual void freeCollisionAlgorithm(void* ptr) + { + + } + + + +}; + + + +#endif //BT_LOW_LEVEL_COLLISION__DISPATCHER_H + + diff --git a/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelConstraintSolver.cpp b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelConstraintSolver.cpp new file mode 100644 index 0000000..7770da1 --- /dev/null +++ b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelConstraintSolver.cpp @@ -0,0 +1,1410 @@ +/* + Copyright (C) 2010 Sony Computer Entertainment Inc. + All rights reserved. + +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 "btLowLevelConstraintSolver.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" + +#include "LinearMath/btQuickprof.h" +#include "BulletMultiThreaded/btThreadSupportInterface.h" + +#include "vecmath/vmInclude.h" + +#include "BulletMultiThreaded/HeapManager.h" + +#include "BulletMultiThreaded/PlatformDefinitions.h" + +//#include "PfxSimdUtils.h" +#include "LinearMath/btScalar.h" + +#include "BulletMultiThreaded/TrbStateVec.h" + + + +///////////////// + + +#define TMP_BUFF_BYTES (15*1024*1024) +unsigned char ATTRIBUTE_ALIGNED128(tmp_buff[TMP_BUFF_BYTES]); + + +static SIMD_FORCE_INLINE vmVector3 btReadVector3(const double* p) +{ + float tmp[3] = {float(p[0]),float(p[1]),float(p[2])}; + vmVector3 v; + loadXYZ(v, tmp); + return v; +} + +static SIMD_FORCE_INLINE vmQuat btReadQuat(const double* p) +{ + float tmp[4] = {float(p[0]),float(p[1]),float(p[2]),float(p[4])}; + vmQuat vq; + loadXYZW(vq, tmp); + return vq; +} + +static SIMD_FORCE_INLINE void btStoreVector3(const vmVector3 &src, double* p) +{ + float tmp[3]; + vmVector3 v = src; + storeXYZ(v, tmp); + p[0] = tmp[0]; + p[1] = tmp[1]; + p[2] = tmp[2]; +} + + +static SIMD_FORCE_INLINE vmVector3 btReadVector3(const float* p) +{ + vmVector3 v; + loadXYZ(v, p); + return v; +} + +static SIMD_FORCE_INLINE vmQuat btReadQuat(const float* p) +{ + vmQuat vq; + loadXYZW(vq, p); + return vq; +} + +static SIMD_FORCE_INLINE void btStoreVector3(const vmVector3 &src, float* p) +{ + vmVector3 v = src; + storeXYZ(v, p); +} + + + + + +// Project Gauss Seidel or the equivalent Sequential Impulse + inline void resolveSingleConstraintRowGeneric(PfxSolverBody& body1,PfxSolverBody& body2,const btSolverConstraint& c) +{ + + btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm; + const btScalar deltaVel1Dotn = c.m_contactNormal.dot((btVector3&)body1.m_deltaLinearVelocity) + c.m_relpos1CrossNormal.dot((btVector3&)body1.m_deltaAngularVelocity); + const btScalar deltaVel2Dotn = -c.m_contactNormal.dot((btVector3&)body2.m_deltaLinearVelocity) + c.m_relpos2CrossNormal.dot((btVector3&)body2.m_deltaAngularVelocity); + +// const btScalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn; + deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv; + deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv; + + const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse; + if (sum < c.m_lowerLimit) + { + deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_lowerLimit; + } + else if (sum > c.m_upperLimit) + { + deltaImpulse = c.m_upperLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_upperLimit; + } + else + { + c.m_appliedImpulse = sum; + } + + + if (body1.m_massInv) + { + btVector3 linearComponent = c.m_contactNormal*body1.m_massInv; + ((btVector3&)body1.m_deltaLinearVelocity) += linearComponent*deltaImpulse; + ((btVector3&)body1.m_deltaAngularVelocity) += c.m_angularComponentA*(btVector3(deltaImpulse,deltaImpulse,deltaImpulse));//*m_angularFactor); + } + + if (body2.m_massInv) + { + btVector3 linearComponent = -c.m_contactNormal*body2.m_massInv; + ((btVector3&)body2.m_deltaLinearVelocity) += linearComponent*deltaImpulse; + ((btVector3&)body2.m_deltaAngularVelocity) += c.m_angularComponentB*((btVector3(deltaImpulse,deltaImpulse,deltaImpulse)));//*m_angularFactor); + } + + //body1.internalApplyImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse); + //body2.internalApplyImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse); + +} + + +static SIMD_FORCE_INLINE +void pfxSolveLinearConstraintRow(btConstraintRow &constraint, + vmVector3 &deltaLinearVelocityA,vmVector3 &deltaAngularVelocityA, + float massInvA,const vmMatrix3 &inertiaInvA,const vmVector3 &rA, + vmVector3 &deltaLinearVelocityB,vmVector3 &deltaAngularVelocityB, + float massInvB,const vmMatrix3 &inertiaInvB,const vmVector3 &rB) +{ + const vmVector3 normal(btReadVector3(constraint.m_normal)); + btScalar deltaImpulse = constraint.m_rhs; + vmVector3 dVA = deltaLinearVelocityA + cross(deltaAngularVelocityA,rA); + vmVector3 dVB = deltaLinearVelocityB + cross(deltaAngularVelocityB,rB); + deltaImpulse -= constraint.m_jacDiagInv * dot(normal,dVA-dVB); + btScalar oldImpulse = constraint.m_accumImpulse; + constraint.m_accumImpulse = btClamped(oldImpulse + deltaImpulse,constraint.m_lowerLimit,constraint.m_upperLimit); + deltaImpulse = constraint.m_accumImpulse - oldImpulse; + deltaLinearVelocityA += deltaImpulse * massInvA * normal; + deltaAngularVelocityA += deltaImpulse * inertiaInvA * cross(rA,normal); + deltaLinearVelocityB -= deltaImpulse * massInvB * normal; + deltaAngularVelocityB -= deltaImpulse * inertiaInvB * cross(rB,normal); + +} + +void btSolveContactConstraint( + btConstraintRow &constraintResponse, + btConstraintRow &constraintFriction1, + btConstraintRow &constraintFriction2, + const vmVector3 &contactPointA, + const vmVector3 &contactPointB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + float friction + ) +{ + vmVector3 rA = rotate(solverBodyA.m_orientation,contactPointA); + vmVector3 rB = rotate(solverBodyB.m_orientation,contactPointB); + + pfxSolveLinearConstraintRow(constraintResponse, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB); + + float mf = friction*fabsf(constraintResponse.m_accumImpulse); + constraintFriction1.m_lowerLimit = -mf; + constraintFriction1.m_upperLimit = mf; + constraintFriction2.m_lowerLimit = -mf; + constraintFriction2.m_upperLimit = mf; + + pfxSolveLinearConstraintRow(constraintFriction1, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB); + + pfxSolveLinearConstraintRow(constraintFriction2, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB); +} + + +void CustomSolveConstraintsTaskParallel( + const PfxParallelGroup *contactParallelGroup,const PfxParallelBatch *contactParallelBatches, + PfxConstraintPair *contactPairs,uint32_t numContactPairs, + btPersistentManifold* offsetContactManifolds__, + const PfxParallelGroup *jointParallelGroup,const PfxParallelBatch *jointParallelBatches, + PfxConstraintPair *jointPairs,uint32_t numJointPairs, + TrbState *offsetRigStates, + PfxSolverBody *offsetSolverBodies, + uint32_t numRigidBodies, + int iteration,unsigned int taskId,unsigned int numTasks,btBarrier *barrier) +{ + + PfxSolverBody staticBody; + staticBody.m_massInv = 0.f; + staticBody.m_deltaAngularVelocity=vmVector3(0,0,0); + staticBody.m_deltaLinearVelocity =vmVector3(0,0,0); + + + for(int k=0;knumPhases;phaseId++) { + for(uint32_t batchId=0;batchIdnumBatches[phaseId];batchId++) { + uint32_t numPairs = jointParallelGroup->numPairs[phaseId*SCE_PFX_MAX_SOLVER_BATCHES+batchId]; + if(batchId%numTasks == taskId && numPairs > 0) { + const PfxParallelBatch &batch = jointParallelBatches[phaseId*SCE_PFX_MAX_SOLVER_BATCHES+batchId]; + for(uint32_t i=0;isync(); + } + + // Contact + for(uint32_t phaseId=0;phaseIdnumPhases;phaseId++) { + for(uint32_t batchId=0;batchIdnumBatches[phaseId];batchId++) { + uint32_t numPairs = contactParallelGroup->numPairs[phaseId*SCE_PFX_MAX_SOLVER_BATCHES+batchId]; + if(batchId%numTasks == taskId && numPairs > 0) { + const PfxParallelBatch &batch = contactParallelBatches[phaseId*SCE_PFX_MAX_SOLVER_BATCHES+batchId]; + for(uint32_t i=0;isync(); + } + } +} + +void CustomPostSolverTask( + TrbState *states, + PfxSolverBody *solverBodies, + uint32_t numRigidBodies) +{ + for(uint32_t i=0;i 0.707f) { + // choose p in y-z plane + float a = n[1]*n[1] + n[2]*n[2]; + float k = 1.0f/sqrtf(a); + p[0] = 0; + p[1] = -n[2]*k; + p[2] = n[1]*k; + // set q = n x p + q[0] = a*k; + q[1] = -n[0]*p[2]; + q[2] = n[0]*p[1]; + } + else { + // choose p in x-y plane + float a = n[0]*n[0] + n[1]*n[1]; + float k = 1.0f/sqrtf(a); + p[0] = -n[1]*k; + p[1] = n[0]*k; + p[2] = 0; + // set q = n x p + q[0] = -n[2]*p[1]; + q[1] = n[2]*p[0]; + q[2] = a*k; + } +} + + + +#define PFX_CONTACT_SLOP 0.001f + +void btSetupContactConstraint( + btConstraintRow &constraintResponse, + btConstraintRow &constraintFriction1, + btConstraintRow &constraintFriction2, + float penetrationDepth, + float restitution, + float friction, + const vmVector3 &contactNormal, + const vmVector3 &contactPointA, + const vmVector3 &contactPointB, + const TrbState &stateA, + const TrbState &stateB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + float separateBias, + float timeStep + ) +{ + vmVector3 rA = rotate(solverBodyA.m_orientation,contactPointA); + vmVector3 rB = rotate(solverBodyB.m_orientation,contactPointB); + + vmMatrix3 K = vmMatrix3::scale(vmVector3(solverBodyA.m_massInv + solverBodyB.m_massInv)) - + crossMatrix(rA) * solverBodyA.m_inertiaInv * crossMatrix(rA) - + crossMatrix(rB) * solverBodyB.m_inertiaInv * crossMatrix(rB); + + vmVector3 vA = stateA.getLinearVelocity() + cross(stateA.getAngularVelocity(),rA); + vmVector3 vB = stateB.getLinearVelocity() + cross(stateB.getAngularVelocity(),rB); + vmVector3 vAB = vA-vB; + + vmVector3 tangent1,tangent2; + btPlaneSpace1(contactNormal,tangent1,tangent2); + +// constraintResponse.m_accumImpulse = 0.f; +// constraintFriction1.m_accumImpulse = 0.f; +// constraintFriction2.m_accumImpulse = 0.f; + + // Contact Constraint + { + vmVector3 normal = contactNormal; + + float denom = dot(K*normal,normal); + + constraintResponse.m_rhs = -(1.0f+restitution)*dot(vAB,normal); // velocity error + constraintResponse.m_rhs -= (separateBias * btMin(0.0f,penetrationDepth+PFX_CONTACT_SLOP)) / timeStep; // position error + constraintResponse.m_rhs /= denom; + constraintResponse.m_jacDiagInv = 1.0f/denom; + constraintResponse.m_lowerLimit = 0.0f; + constraintResponse.m_upperLimit = SIMD_INFINITY; + btStoreVector3(normal,constraintResponse.m_normal); + } + + // Friction Constraint 1 + { + vmVector3 normal = tangent1; + + float denom = dot(K*normal,normal); + + constraintFriction1.m_jacDiagInv = 1.0f/denom; + constraintFriction1.m_rhs = -dot(vAB,normal); + constraintFriction1.m_rhs *= constraintFriction1.m_jacDiagInv; + constraintFriction1.m_lowerLimit = 0.0f; + constraintFriction1.m_upperLimit = SIMD_INFINITY; + btStoreVector3(normal,constraintFriction1.m_normal); + } + + // Friction Constraint 2 + { + vmVector3 normal = tangent2; + + float denom = dot(K*normal,normal); + + constraintFriction2.m_jacDiagInv = 1.0f/denom; + constraintFriction2.m_rhs = -dot(vAB,normal); + constraintFriction2.m_rhs *= constraintFriction2.m_jacDiagInv; + constraintFriction2.m_lowerLimit = 0.0f; + constraintFriction2.m_upperLimit = SIMD_INFINITY; + btStoreVector3(normal,constraintFriction2.m_normal); + } +} + + +void CustomSetupContactConstraintsTask( + PfxConstraintPair *contactPairs,uint32_t numContactPairs, + TrbState *offsetRigStates, + PfxSolverBody *offsetSolverBodies, + uint32_t numRigidBodies, + float separateBias, + float timeStep) +{ + for(uint32_t i=0;iio); + btCriticalSection* criticalsection = io->setupContactConstraints.criticalSection; + + + //CustomCriticalSection *criticalsection = &io->m_cs; + switch(io->cmd) { + + case PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS: + CustomSolveConstraintsTaskParallel( + io->solveConstraints.contactParallelGroup, + io->solveConstraints.contactParallelBatches, + io->solveConstraints.contactPairs, + io->solveConstraints.numContactPairs, + io->solveConstraints.offsetContactManifolds, + + io->solveConstraints.jointParallelGroup, + io->solveConstraints.jointParallelBatches, + io->solveConstraints.jointPairs, + io->solveConstraints.numJointPairs, + + io->solveConstraints.offsetRigStates, + io->solveConstraints.offsetSolverBodies, + io->solveConstraints.numRigidBodies, + io->solveConstraints.iteration, + + io->solveConstraints.taskId, + io->maxTasks1, + io->solveConstraints.barrier + ); + break; + + case PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER: + CustomPostSolverTask( io->postSolver.states,io->postSolver.solverBodies, io->postSolver.numRigidBodies); + break; + + + case PFX_CONSTRAINT_SOLVER_CMD_SETUP_CONTACT_CONSTRAINTS: + { + bool empty = false; + while(!empty) { + int start,batch; + + criticalsection->lock(); + + start = (int)criticalsection->getSharedParam(0); + batch = (int)criticalsection->getSharedParam(1); + + //PFX_PRINTF("taskId %d start %d num %d\n",arg->taskId,start,batch); + + // ŽŸ‚̃oƒbƒtƒ@‚ðƒZƒbƒg + int nextStart = start + batch; + int rest = btMax((int)io->setupContactConstraints.numContactPairs1 - nextStart,0); + int nextBatch = (rest > batch)?batch:rest; + + criticalsection->setSharedParam(0,nextStart); + criticalsection->setSharedParam(1,nextBatch); + + criticalsection->unlock(); + + if(batch > 0) { + CustomSetupContactConstraintsTask( + io->setupContactConstraints.offsetContactPairs+start,batch, +// io->setupContactConstraints.offsetContactManifolds, + io->setupContactConstraints.offsetRigStates, +// io->setupContactConstraints.offsetRigBodies, + io->setupContactConstraints.offsetSolverBodies, + io->setupContactConstraints.numRigidBodies, + io->setupContactConstraints.separateBias, + io->setupContactConstraints.timeStep); + } + else { + empty = true; + } + } + } + break; + + default: + { + btAssert(0); + } + } + +} + + +void CustomSetupContactConstraintsNew( + PfxConstraintPair *contactPairs1,uint32_t numContactPairs, + btPersistentManifold *offsetContactManifolds, + TrbState *offsetRigStates, + PfxSolverBody *offsetSolverBodies, + uint32_t numRigidBodies, + float separationBias, + float timeStep, + class btThreadSupportInterface* threadSupport, + btCriticalSection* criticalSection, + btConstraintSolverIO *io + ) +{ + int maxTasks = threadSupport->getNumTasks(); + + int div = (int)maxTasks * 4; + int batch = ((int)numContactPairs + div - 1) / div; +#ifdef __PPU__ + BulletPE2ConstraintSolverSpursSupport* spursThread = (BulletPE2ConstraintSolverSpursSupport*) threadSupport; +#endif + if (criticalSection) + { + criticalSection->setSharedParam(0,0); + criticalSection->setSharedParam(1,btMin(batch,64)); // batched number + } else + { +#ifdef __PPU__ + spursThread->setSharedParam(0,0); + spursThread->setSharedParam(1,btMin(batch,64)); // batched number +#endif //__PPU__ + } + + for(int t=0;tgetBarrierAddress(); + io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress(); +#endif + + +//#define SEQUENTIAL_SETUP +#ifdef SEQUENTIAL_SETUP + CustomSetupContactConstraintsTask(contactPairs1,numContactPairs,offsetRigStates,offsetSolverBodies,numRigidBodies,separationBias,timeStep); +#else + threadSupport->sendRequest(1,(ppu_address_t)&io[t],t); +#endif + + } +#ifndef SEQUENTIAL_SETUP + unsigned int arg0,arg1; + for(int t=0;twaitForResponse(&arg0,&arg1); + } +#endif //SEQUENTIAL_SETUP + +} + + +void CustomSplitConstraints( + PfxConstraintPair *pairs,uint32_t numPairs, + PfxParallelGroup &group,PfxParallelBatch *batches, + uint32_t numTasks, + uint32_t numRigidBodies, + void *poolBuff, + uint32_t poolBytes + ) +{ + HeapManager pool((unsigned char*)poolBuff,poolBytes); + + // ƒXƒe[ƒgƒ`ƒFƒbƒN—pƒrƒbƒgƒtƒ‰ƒOƒe[ƒuƒ‹ + int bufSize = sizeof(uint8_t)*numRigidBodies; + bufSize = ((bufSize+127)>>7)<<7; // 128 bytes alignment + uint8_t *bodyTable = (uint8_t*)pool.allocate(bufSize,HeapManager::ALIGN128); + + // ƒyƒAƒ`ƒFƒbƒN—pƒrƒbƒgƒtƒ‰ƒOƒe[ƒuƒ‹ + uint32_t *pairTable; + size_t allocSize = sizeof(uint32_t)*((numPairs+31)/32); + pairTable = (uint32_t*)pool.allocate(allocSize); + memset(pairTable,0,allocSize); + + // –Ú•W‚Æ‚·‚镪Š„” + uint32_t targetCount = btMax(uint32_t(SCE_PFX_MIN_SOLVER_PAIRS),btMin(numPairs / (numTasks*2),uint32_t(SCE_PFX_MAX_SOLVER_PAIRS))); + uint32_t startIndex = 0; + + uint32_t phaseId; + uint32_t batchId; + uint32_t totalCount=0; + + uint32_t maxBatches = btMin(numTasks,uint32_t(SCE_PFX_MAX_SOLVER_BATCHES)); + + for(phaseId=0;phaseId>5; + uint32_t maskP = 1L << (i & 31); + + //pair is already assigned to a phase/batch + if(pairTable[idxP] & maskP) { + continue; + } + + uint32_t idxA = pfxGetObjectIdA(pairs[i]); + uint32_t idxB = pfxGetObjectIdB(pairs[i]); + + // —¼•û‚Æ‚àƒAƒNƒeƒBƒu‚Å‚È‚¢A‚Ü‚½‚͏Փ˓_‚ª‚O‚̃yƒA‚Í“o˜^‘Ώۂ©‚ç‚Í‚¸‚· + if(!pfxGetActive(pairs[i]) || pfxGetNumConstraints(pairs[i]) == 0 || + ((pfxGetMotionMaskA(pairs[i])&PFX_MOTION_MASK_STATIC) && (pfxGetMotionMaskB(pairs[i])&PFX_MOTION_MASK_STATIC)) ) { + if(startIndexCheck) + startIndex++; + //assign pair -> skip it because it has no constraints + pairTable[idxP] |= maskP; + totalCount++; + continue; + } + + // ˆË‘¶«‚̃`ƒFƒbƒN + if( (bodyTable[idxA] != batchId && bodyTable[idxA] != 0xff) || + (bodyTable[idxB] != batchId && bodyTable[idxB] != 0xff) ) { + startIndexCheck = false; + //bodies of the pair are already assigned to another batch within this phase + continue; + } + + // ˆË‘¶«”»’èƒe[ƒuƒ‹‚É“o˜^ + if(pfxGetMotionMaskA(pairs[i])&PFX_MOTION_MASK_DYNAMIC) + bodyTable[idxA] = batchId; + if(pfxGetMotionMaskB(pairs[i])&PFX_MOTION_MASK_DYNAMIC) + bodyTable[idxB] = batchId; + + if(startIndexCheck) + startIndex++; + + pairTable[idxP] |= maskP; + //add the pair 'i' to the current batch + batch.pairIndices[pairId++] = i; + pairCount++; + } + + group.numPairs[phaseId*SCE_PFX_MAX_SOLVER_BATCHES+batchId] = (uint16_t)pairId; + totalCount += pairCount; + } + + group.numBatches[phaseId] = batchId; + } + + group.numPhases = phaseId; + + pool.clear(); +} + + + +void CustomSolveConstraintsParallel( + PfxConstraintPair *contactPairs,uint32_t numContactPairs, + + PfxConstraintPair *jointPairs,uint32_t numJointPairs, + + TrbState *offsetRigStates, + PfxSolverBody *offsetSolverBodies, + uint32_t numRigidBodies, + struct btConstraintSolverIO* io, + class btThreadSupportInterface* threadSupport, + int iteration, + void* poolBuf, + int poolBytes, + class btBarrier* barrier) + { + + int maxTasks = threadSupport->getNumTasks(); +// config.taskManager->setTaskEntry(PFX_SOLVER_ENTRY); + + HeapManager pool((unsigned char*)poolBuf,poolBytes); + + { + PfxParallelGroup *cgroup = (PfxParallelGroup*)pool.allocate(sizeof(PfxParallelGroup)); + PfxParallelBatch *cbatches = (PfxParallelBatch*)pool.allocate(sizeof(PfxParallelBatch)*(SCE_PFX_MAX_SOLVER_PHASES*SCE_PFX_MAX_SOLVER_BATCHES),128); + PfxParallelGroup *jgroup = (PfxParallelGroup*)pool.allocate(sizeof(PfxParallelGroup)); + PfxParallelBatch *jbatches = (PfxParallelBatch*)pool.allocate(sizeof(PfxParallelBatch)*(SCE_PFX_MAX_SOLVER_PHASES*SCE_PFX_MAX_SOLVER_BATCHES),128); + + uint32_t tmpBytes = poolBytes - 2 * (sizeof(PfxParallelGroup) + sizeof(PfxParallelBatch)*(SCE_PFX_MAX_SOLVER_PHASES*SCE_PFX_MAX_SOLVER_BATCHES) + 128); + void *tmpBuff = pool.allocate(tmpBytes); + + { + BT_PROFILE("CustomSplitConstraints"); + CustomSplitConstraints(contactPairs,numContactPairs,*cgroup,cbatches,maxTasks,numRigidBodies,tmpBuff,tmpBytes); + CustomSplitConstraints(jointPairs,numJointPairs,*jgroup,jbatches,maxTasks,numRigidBodies,tmpBuff,tmpBytes); + } + + { + BT_PROFILE("PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS"); +//#define SOLVE_SEQUENTIAL +#ifdef SOLVE_SEQUENTIAL + CustomSolveConstraintsTask( + io->solveConstraints.contactParallelGroup, + io->solveConstraints.contactParallelBatches, + io->solveConstraints.contactPairs, + io->solveConstraints.numContactPairs, + io->solveConstraints.offsetContactManifolds, + + io->solveConstraints.jointParallelGroup, + io->solveConstraints.jointParallelBatches, + io->solveConstraints.jointPairs, + io->solveConstraints.numJointPairs, + io->solveConstraints.offsetJoints, + + io->solveConstraints.offsetRigStates, + io->solveConstraints.offsetSolverBodies, + io->solveConstraints.numRigidBodies, + io->solveConstraints.iteration,0,1,0);//arg->taskId,1,0);//,arg->maxTasks,arg->barrier); +#else + for(int t=0;tgetBarrierAddress(); + io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress(); +#endif + + threadSupport->sendRequest(1,(ppu_address_t)&io[t],t); + } + + unsigned int arg0,arg1; + for(int t=0;twaitForResponse(&arg0,&arg1); + } +#endif + } + pool.clear(); + } + + { + BT_PROFILE("PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER"); + int batch = ((int)numRigidBodies + maxTasks - 1) / maxTasks; + int rest = (int)numRigidBodies; + int start = 0; + + for(int t=0;t 0 ? batch : rest; + io[t].cmd = PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER; + io[t].postSolver.states = offsetRigStates + start; + io[t].postSolver.solverBodies = offsetSolverBodies + start; + io[t].postSolver.numRigidBodies = (uint32_t)num; + io[t].maxTasks1 = maxTasks; +#ifdef __PPU__ + BulletPE2ConstraintSolverSpursSupport* spursThread = (BulletPE2ConstraintSolverSpursSupport*) threadSupport; + io[t].barrierAddr2 = (unsigned int)spursThread->getBarrierAddress(); + io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress(); +#endif + +#ifdef SOLVE_SEQUENTIAL + CustomPostSolverTask( io[t].postSolver.states,io[t].postSolver.solverBodies, io[t].postSolver.numRigidBodies); +#else + threadSupport->sendRequest(1,(ppu_address_t)&io[t],t); +#endif + rest -= num; + start += num; + } + + unsigned int arg0,arg1; + for(int t=0;twaitForResponse(&arg0,&arg1); +#endif + } + } + +} + + + +void BPE_customConstraintSolverSequentialNew(unsigned int new_num, PfxBroadphasePair *new_pairs1 , + TrbState* states,int numRigidBodies, + struct PfxSolverBody* solverBodies, + btPersistentManifold* contacts, + PfxConstraintPair* jointPairs, unsigned int numJoints, + float separateBias, + float timeStep, + int iteration, + btThreadSupportInterface* solverThreadSupport, + btCriticalSection* criticalSection, + struct btConstraintSolverIO* solverIO, + btBarrier* barrier + ) +{ + + { + BT_PROFILE("pfxSetupConstraints"); + + for(uint32_t i=0;i m_mystates; + btAlignedObjectArray m_mysolverbodies; + btAlignedObjectArray m_mypairs; + btAlignedObjectArray m_jointPairs; + +}; + + +btConstraintSolverIO* createSolverIO(int numThreads) +{ + return new btConstraintSolverIO[numThreads]; +} + +btLowLevelConstraintSolver::btLowLevelConstraintSolver(btThreadSupportInterface* solverThreadSupport) +{ + + m_solverThreadSupport = solverThreadSupport;//createSolverThreadSupport(maxNumThreads); + m_solverIO = createSolverIO(m_solverThreadSupport->getNumTasks()); + + m_barrier = m_solverThreadSupport->createBarrier(); + m_criticalSection = m_solverThreadSupport->createCriticalSection(); + + m_memoryCache = new btParallelSolverMemoryCache(); +} + +btLowLevelConstraintSolver::~btLowLevelConstraintSolver() +{ + delete m_memoryCache; + delete m_solverIO; +} + + + +btScalar btLowLevelConstraintSolver::solveGroup(btCollisionObject** bodies1,int numRigidBodies,btPersistentManifold** manifoldPtr,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher) +{ + +/* int sz = sizeof(PfxSolverBody); + int sz2 = sizeof(vmVector3); + int sz3 = sizeof(vmMatrix3); + int sz4 = sizeof(vmQuat); + int sz5 = sizeof(btConstraintRow); + int sz6 = sizeof(btSolverConstraint); + int sz7 = sizeof(TrbState); +*/ + + + m_memoryCache->m_mysolverbodies.resize(numRigidBodies); + m_memoryCache->m_mystates.resize(numRigidBodies); + + { + BT_PROFILE("create states and solver bodies"); + for (int i=0;isetCompanionId(i); + + PfxSolverBody& solverBody = m_memoryCache->m_mysolverbodies[i]; + btRigidBody* rb = btRigidBody::upcast(obj); + TrbState& state = m_memoryCache->m_mystates[i]; + + state.reset(); + const btQuaternion& orgOri = obj->getWorldTransform().getRotation(); + vmQuat orn(orgOri.getX(),orgOri.getY(),orgOri.getZ(),orgOri.getW()); + state.setPosition((vmVector3&) obj->getWorldTransform().getOrigin()); + state.setOrientation(orn); + state.setPosition(state.getPosition()); + state.setRigidBodyId(i); + state.setAngularDamping(0); + state.setLinearDamping(0); + + + solverBody.m_orientation = state.getOrientation(); + solverBody.m_deltaLinearVelocity = vmVector3(0.0f); + solverBody.m_deltaAngularVelocity = vmVector3(0.0f); +#ifdef SOLVERBODY_FRICTION + solverBody.friction = obj->getFriction(); + solverBody.restitution = obj->getRestitution(); +#endif //SOLVERBODY_FRICTION + state.resetSleepCount(); + + //if(state.getMotionMask()&PFX_MOTION_MASK_DYNAMIC) { + if (rb && (rb->getInvMass()>0.f)) + { + state.setAngularVelocity(vmVector3(rb->getAngularVelocity().getX(),rb->getAngularVelocity().getY(),rb->getAngularVelocity().getZ())); + state.setLinearVelocity(vmVector3(rb->getLinearVelocity().getX(),rb->getLinearVelocity().getY(),rb->getLinearVelocity().getZ())); + + state.setMotionType(PfxMotionTypeActive); + vmMatrix3 ori(solverBody.m_orientation); + vmMatrix3 localInvInertia = vmMatrix3::identity(); + localInvInertia.setCol(0,vmVector3(rb->getInvInertiaDiagLocal().getX(),0,0)); + localInvInertia.setCol(1,vmVector3(0, rb->getInvInertiaDiagLocal().getY(),0)); + localInvInertia.setCol(2,vmVector3(0,0, rb->getInvInertiaDiagLocal().getZ())); + + solverBody.m_massInv = rb->getInvMass(); + solverBody.m_inertiaInv = ori * localInvInertia * transpose(ori); + } else + { + state.setAngularVelocity(vmVector3(0)); + state.setLinearVelocity(vmVector3(0)); + + state.setMotionType(PfxMotionTypeFixed); + m_memoryCache->m_mysolverbodies[i].m_massInv = 0.f; + m_memoryCache->m_mysolverbodies[i].m_inertiaInv = vmMatrix3(0.0f); + } + + } + } + + + + int totalPoints = 0; +#ifndef USE_C_ARRAYS + m_memoryCache->m_mypairs.resize(numManifolds); + m_memoryCache->m_jointPairs.resize(numConstraints); +#endif//USE_C_ARRAYS + + int actualNumManifolds= 0; + { + BT_PROFILE("convert manifolds"); + for (int i1=0;i1getNumContacts()>0) + { + btPersistentManifold* m = manifoldPtr[i1]; + btCollisionObject* obA = (btCollisionObject*)m->getBody0(); + btCollisionObject* obB = (btCollisionObject*)m->getBody1(); + bool obAisActive = !obA->isStaticOrKinematicObject() && obA->isActive(); + bool obBisActive = !obB->isStaticOrKinematicObject() && obB->isActive(); + + if (!obAisActive && !obBisActive) + continue; + + + //int contactId = i1;//actualNumManifolds; + + PfxBroadphasePair& pair = m_memoryCache->m_mypairs[actualNumManifolds]; + //init those + float compFric = obA->getFriction()*obB->getFriction();//@todo + int idA = obA->getCompanionId(); + int idB = obB->getCompanionId(); + + m->m_companionIdA = idA; + m->m_companionIdB = idB; + + + // if ((mysolverbodies[idA].m_massInv!=0)&&(mysolverbodies[idB].m_massInv!=0)) + // continue; + int numPosPoints=0; + for (int p=0;pgetNumContacts();p++) + { + //btManifoldPoint& pt = m->getContactPoint(p); + //float dist = pt.getDistance(); + //if (dist<0.001) + numPosPoints++; + } + + + numPosPoints = numPosPoints; + totalPoints+=numPosPoints; + pfxSetObjectIdA(pair,idA); + pfxSetObjectIdB(pair,idB); + pfxSetMotionMaskA(pair,m_memoryCache->m_mystates[idA].getMotionMask()); + pfxSetMotionMaskB(pair,m_memoryCache->m_mystates[idB].getMotionMask()); + pfxSetActive(pair,numPosPoints>0); + + pfxSetBroadphaseFlag(pair,0); + pfxSetContactId(pair,(uint32_t)m);//contactId); + pfxSetNumConstraints(pair,numPosPoints);//manifoldPtr[i]->getNumContacts()); + actualNumManifolds++; + } + + } + } + + PfxConstraintPair* jointPairs=0; + jointPairs = numConstraints? &m_memoryCache->m_jointPairs[0]:0; + int actualNumJoints=0; + + + //if (1) + { + BT_PROFILE("convert constraints"); + { + + int totalNumRows = 0; + int i; + + m_tmpConstraintSizesPool.resize(numConstraints); + //calculate the total number of contraint rows + for (i=0;igetInfo1(&info1); + totalNumRows += info1.m_numConstraintRows; + } + m_tmpSolverNonContactConstraintPool.resize(totalNumRows); + + + ///setup the btSolverConstraints + int currentRow = 0; + + for (i=0;igetRigidBodyA(); + btRigidBody& rbB = constraint->getRigidBodyB(); + + + int j; + for ( j=0;jm_contactNormal; + info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal; + info2.m_J2linearAxis = 0; + info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal; + info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this + ///the size of btSolverConstraint needs be a multiple of btScalar + btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint)); + info2.m_constraintError = ¤tConstraintRow->m_rhs; + currentConstraintRow->m_cfm = infoGlobal.m_globalCfm; + info2.cfm = ¤tConstraintRow->m_cfm; + info2.m_lowerLimit = ¤tConstraintRow->m_lowerLimit; + info2.m_upperLimit = ¤tConstraintRow->m_upperLimit; + info2.m_numIterations = infoGlobal.m_numIterations; + constraints[i]->getInfo2(&info2); + + int idA = constraint->getRigidBodyA().getCompanionId(); + int idB = constraint->getRigidBodyB().getCompanionId(); + + + ///finalize the constraint setup + for ( j=0;jgetRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor(); + } + { + const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal; + solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor(); + } + + { + btVector3 iMJlA = solverConstraint.m_contactNormal*rbA.getInvMass(); + btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal; + btVector3 iMJlB = solverConstraint.m_contactNormal*rbB.getInvMass();//sign of normal? + btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal; + + btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal); + sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal); + sum += iMJlB.dot(solverConstraint.m_contactNormal); + sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal); + + solverConstraint.m_jacDiagABInv = btScalar(1.)/sum; + } + + + ///fix rhs + ///todo: add force/torque accelerators + { + btScalar rel_vel; + btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.getLinearVelocity()) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity()); + btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.getLinearVelocity()) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity()); + + rel_vel = vel1Dotn+vel2Dotn; + + btScalar restitution = 0.f; + btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2 + btScalar velocityError = restitution - rel_vel;// * damping; + btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; + solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; + solverConstraint.m_appliedImpulse = 0.f; + + } + } + + PfxConstraintPair& pair = jointPairs[actualNumJoints]; + + int numConstraintRows= info1.m_numConstraintRows; + pfxSetNumConstraints(pair,numConstraintRows); + + + + pfxSetObjectIdA(pair,idA); + pfxSetObjectIdB(pair,idB); + //is this needed? + pfxSetMotionMaskA(pair,m_memoryCache->m_mystates[idA].getMotionMask()); + pfxSetMotionMaskB(pair,m_memoryCache->m_mystates[idB].getMotionMask()); + + pfxSetActive(pair,true); + pfxSetContactId(pair,(uint32_t)currentConstraintRow);//contactId); + actualNumJoints++; + + + } + currentRow+=m_tmpConstraintSizesPool[i].m_numConstraintRows; + } + } + } + + + + float separateBias=0.1;//info.m_erp;//or m_erp2? + float timeStep=infoGlobal.m_timeStep; + int iteration=infoGlobal.m_numIterations; + + //create a pair for each constraints, copy over info etc + + + + + + { + BT_PROFILE("compute num contacts"); + int totalContacts =0; + + for (int i=0;im_mypairs[i]; + totalContacts += pfxGetNumConstraints(*pair); + } + //printf("numManifolds = %d\n",numManifolds); + //printf("totalContacts=%d\n",totalContacts); + } + + + +// printf("actualNumManifolds=%d\n",actualNumManifolds); + { + BT_PROFILE("BPE_customConstraintSolverSequentialNew"); + if (numRigidBodies>0 && (actualNumManifolds+actualNumJoints)>0) + { +// PFX_PRINTF("num points = %d\n",totalPoints); +// PFX_PRINTF("num points PFX = %d\n",total); + + BPE_customConstraintSolverSequentialNew( + actualNumManifolds, + &m_memoryCache->m_mypairs[0], + &m_memoryCache->m_mystates[0],numRigidBodies, + &m_memoryCache->m_mysolverbodies[0], + 0,//manifoldArray, + jointPairs,actualNumJoints,separateBias,timeStep,iteration, + m_solverThreadSupport,m_criticalSection,m_solverIO,m_barrier); + } + } + + //copy results back to bodies + { + BT_PROFILE("copy back"); + for (int i=0;im_mystates[i]; + if (rb && (rb->getInvMass()>0.f)) + { + rb->setLinearVelocity(btVector3(state.getLinearVelocity().getX(),state.getLinearVelocity().getY(),state.getLinearVelocity().getZ())); + rb->setAngularVelocity(btVector3(state.getAngularVelocity().getX(),state.getAngularVelocity().getY(),state.getAngularVelocity().getZ())); + } + } + } + + + return 0.f; +} diff --git a/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelConstraintSolver.h b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelConstraintSolver.h new file mode 100644 index 0000000..e9b1f27 --- /dev/null +++ b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelConstraintSolver.h @@ -0,0 +1,130 @@ +/* + Copyright (C) 2010 Sony Computer Entertainment Inc. + All rights reserved. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + +#ifndef __BT_LOW_LEVEL_CONSTRAINT_SOLVER_H +#define __BT_LOW_LEVEL_CONSTRAINT_SOLVER_H + +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" + + + + +#include "LinearMath/btScalar.h" +#include "BulletMultiThreaded/PlatformDefinitions.h" +#include "physics_effects/low_level/pfx_low_level_include.h" +#include "../src/low_level/solver/pfx_parallel_group.h" + +using namespace sce::PhysicsEffects; + + +class btPersistentManifold; + +enum { + PFX_CONSTRAINT_SOLVER_CMD_SETUP_SOLVER_BODIES, + PFX_CONSTRAINT_SOLVER_CMD_SETUP_CONTACT_CONSTRAINTS, + PFX_CONSTRAINT_SOLVER_CMD_SETUP_JOINT_CONSTRAINTS, + PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS, + PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER +}; + + +struct PfxSetupContactConstraintsIO { + PfxConstraintPair *offsetContactPairs; + uint32_t numContactPairs1; + class TrbState *offsetRigStates; + struct PfxSolverBody *offsetSolverBodies; + uint32_t numRigidBodies; + float separateBias; + float timeStep; + class btCriticalSection* criticalSection; +}; + + + +struct PfxSolveConstraintsIO { + PfxParallelGroup *contactParallelGroup; + PfxParallelBatch *contactParallelBatches; + PfxConstraintPair *contactPairs; + uint32_t numContactPairs; + btPersistentManifold *offsetContactManifolds; + PfxParallelGroup *jointParallelGroup; + PfxParallelBatch *jointParallelBatches; + PfxConstraintPair *jointPairs; + uint32_t numJointPairs; + TrbState *offsetRigStates; + PfxSolverBody *offsetSolverBodies; + uint32_t numRigidBodies; + uint32_t iteration; + + uint32_t taskId; + + class btBarrier* barrier; + +}; + +struct PfxPostSolverIO { + TrbState *states; + PfxSolverBody *solverBodies; + uint32_t numRigidBodies; +}; + +ATTRIBUTE_ALIGNED16(struct) btConstraintSolverIO { + uint8_t cmd; + union { + PfxSetupContactConstraintsIO setupContactConstraints; + PfxSolveConstraintsIO solveConstraints; + PfxPostSolverIO postSolver; + }; + + //SPU only + uint32_t barrierAddr2; + uint32_t criticalsectionAddr2; + uint32_t maxTasks1; +}; + + + + +void SolverThreadFunc(void* userPtr,void* lsMemory); +void* SolverlsMemoryFunc(); +///The btLowLevelConstraintSolver performs computations on constraint rows in parallel +///Using the cross-platform threading it supports Windows, Linux, Mac OSX and PlayStation 3 Cell SPUs +class btLowLevelConstraintSolver : public btSequentialImpulseConstraintSolver +{ + +protected: + struct btParallelSolverMemoryCache* m_memoryCache; + + class btThreadSupportInterface* m_solverThreadSupport; + + struct btConstraintSolverIO* m_solverIO; + class btBarrier* m_barrier; + class btCriticalSection* m_criticalSection; + + +public: + + btLowLevelConstraintSolver(class btThreadSupportInterface* solverThreadSupport); + + virtual ~btLowLevelConstraintSolver(); + + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher); + +}; + + + +#endif //__BT_LOW_LEVEL_CONSTRAINT_SOLVER_H \ No newline at end of file diff --git a/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelConstraintSolver2.cpp b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelConstraintSolver2.cpp new file mode 100644 index 0000000..e879da4 --- /dev/null +++ b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelConstraintSolver2.cpp @@ -0,0 +1,190 @@ +/* + Copyright (C) 2010 Sony Computer Entertainment Inc. + All rights reserved. + +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 "btLowLevelConstraintSolver2.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" + +#include "LinearMath/btQuickprof.h" +#include "BulletMultiThreaded/btThreadSupportInterface.h" +#include "BulletMultiThreaded/HeapManager.h" +#include "BulletMultiThreaded/PlatformDefinitions.h" +#include "BulletPhysicsEffects/btLowLevelData.h" +#include "BulletMultiThreaded/vectormath2bullet.h" +//#include "PfxSimdUtils.h" +#include "LinearMath/btScalar.h" +#include "BulletMultiThreaded/HeapManager.h" + + + +///////////////// + + +#define TMP_BUFF_BYTES (15*1024*1024) +static unsigned char ATTRIBUTE_ALIGNED128(tmp_buff[TMP_BUFF_BYTES]); + + + + +btLowLevelConstraintSolver2::btLowLevelConstraintSolver2(btLowLevelData* lowLevelData) +:m_lowLevelData(lowLevelData) +{ + +} + +btLowLevelConstraintSolver2::~btLowLevelConstraintSolver2() +{ + +} + + +static void solveConstraints(btLowLevelData* lowLevelData, btScalar timeStep, btScalar separateBias, int iteration) +{ + PfxPerfCounter pc; + HeapManager pool((unsigned char*)tmp_buff,TMP_BUFF_BYTES); + + unsigned int numCurrentPairs = lowLevelData->m_numPairs[lowLevelData->m_pairSwap]; + PfxBroadphasePair *currentPairs = lowLevelData->m_pairsBuff[lowLevelData->m_pairSwap]; + + pc.countBegin("setup solver bodies"); + { + PfxSetupSolverBodiesParam param; + param.states = lowLevelData->m_states; + param.bodies = lowLevelData->m_bodies; + param.solverBodies = lowLevelData->m_solverBodies; + param.numRigidBodies = lowLevelData->m_numRigidBodies; + + int ret = pfxSetupSolverBodies(param); + if(ret != SCE_PFX_OK) + SCE_PFX_PRINTF("pfxSetupSolverBodies failed %d\n",ret); + } + pc.countEnd(); + + pc.countBegin("setup contact constraints"); + { + PfxSetupContactConstraintsParam param; + param.contactPairs = currentPairs; + param.numContactPairs = numCurrentPairs; + param.offsetContactManifolds = lowLevelData->m_contacts; + param.offsetRigidStates = lowLevelData->m_states; + param.offsetRigidBodies = lowLevelData->m_bodies; + param.offsetSolverBodies = lowLevelData->m_solverBodies; + param.numRigidBodies = lowLevelData->m_numRigidBodies; + param.timeStep = timeStep; + param.separateBias = separateBias; + + int ret = pfxSetupContactConstraints(param); + if(ret != SCE_PFX_OK) SCE_PFX_PRINTF("pfxSetupJointConstraints failed %d\n",ret); + } + pc.countEnd(); +#if 0 + pc.countBegin("setup joint constraints"); + { + PfxSetupJointConstraintsParam param; + param.jointPairs = 0;//jointPairs; + param.numJointPairs = 0;//numJoints; + param.offsetJoints = 0;//joints; + param.offsetRigidStates = lowLevelData->m_states; + param.offsetRigidBodies = lowLevelData->m_bodies; + param.offsetSolverBodies = lowLevelData->m_solverBodies; + param.numRigidBodies = lowLevelData->m_numRigidBodies; + param.timeStep = timeStep; + + for(int i=0;im_numRigidBodies,numCurrentPairs,0);//numJoints); + param.workBuff = pool.allocate(param.workBytes); + param.contactPairs = currentPairs; + param.numContactPairs = numCurrentPairs; + param.offsetContactManifolds = lowLevelData->m_contacts; + param.jointPairs = 0;//jointPairs; + param.numJointPairs = 0;//numJoints; + param.offsetJoints = 0;//joints; + param.offsetRigidStates = lowLevelData->m_states; + param.offsetSolverBodies = lowLevelData->m_solverBodies; + param.numRigidBodies = lowLevelData->m_numRigidBodies; + param.iteration = iteration; + + int ret = pfxSolveConstraints(param); + if(ret != SCE_PFX_OK) SCE_PFX_PRINTF("pfxSolveConstraints failed %d\n",ret); + + pool.deallocate(param.workBuff); + } + pc.countEnd(); + + + //pc.printCount(); +} + + + +btScalar btLowLevelConstraintSolver2::solveGroup(btCollisionObject** bodies1,int numRigidBodies,btPersistentManifold** manifoldPtr,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher) +{ + + //copy velocity from BT to PE + { + BT_PROFILE("copy back"); + for (int i=0;igetInvMass()>0.f)) + { + int objectIndex = rb->getBroadphaseProxy()->m_uniqueId; + sce::PhysicsEffects::PfxRigidState& state = m_lowLevelData->m_states[objectIndex]; + + state.setLinearVelocity(getVmVector3(rb->getLinearVelocity())); + state.setAngularVelocity(getVmVector3(rb->getAngularVelocity())); + + } + } + } + + btScalar separateBias = 0.1f; + solveConstraints(m_lowLevelData, infoGlobal.m_timeStep, separateBias, infoGlobal.m_numIterations); + + + //copy resulting velocity back from PE to BT + { + BT_PROFILE("copy back"); + for (int i=0;igetInvMass()>0.f)) + { + int objectIndex = rb->getBroadphaseProxy()->m_uniqueId; + sce::PhysicsEffects::PfxRigidState& state = m_lowLevelData->m_states[objectIndex]; + + rb->setLinearVelocity(btVector3(state.getLinearVelocity().getX(),state.getLinearVelocity().getY(),state.getLinearVelocity().getZ())); + rb->setAngularVelocity(btVector3(state.getAngularVelocity().getX(),state.getAngularVelocity().getY(),state.getAngularVelocity().getZ())); + } + } + } + + return 0.f; +} diff --git a/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelConstraintSolver2.h b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelConstraintSolver2.h new file mode 100644 index 0000000..6fa3921 --- /dev/null +++ b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelConstraintSolver2.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 2010 Sony Computer Entertainment Inc. + All rights reserved. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + +#ifndef __BT_LOW_LEVEL_CONSTRAINT_SOLVER2_H +#define __BT_LOW_LEVEL_CONSTRAINT_SOLVER2_H + +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" + + + + +#include "LinearMath/btScalar.h" +#include "BulletMultiThreaded/PlatformDefinitions.h" +#include "physics_effects/low_level/pfx_low_level_include.h" +#include "../src/low_level/solver/pfx_parallel_group.h" + +using namespace sce::PhysicsEffects; + + +class btPersistentManifold; +struct btLowLevelData; + +class btLowLevelConstraintSolver2 : public btSequentialImpulseConstraintSolver +{ + +protected: + + btLowLevelData* m_lowLevelData; + +public: + + btLowLevelConstraintSolver2(btLowLevelData* lowLevelData); + + virtual ~btLowLevelConstraintSolver2(); + + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher); + +}; + + + +#endif //__BT_LOW_LEVEL_CONSTRAINT_SOLVER2_H \ No newline at end of file diff --git a/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelData.cpp b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelData.cpp new file mode 100644 index 0000000..e69de29 diff --git a/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelData.h b/Extras/PhysicsEffects/include/BulletPhysicsEffects/btLowLevelData.h new file mode 100644 index 0000000000000000000000000000000000000000..949299cff07f2b6b8231b2633936bd49f1c86fdc GIT binary patch literal 4304 zcmbVP+fGwK6y2{i@gF9d7$n9P9x*;pz<{YhC`gPkP3Z+ldLiwpKnUODgCF3l|Kq#5 z*4`av&S7W^IcevdnSELNGHcHH_qQy|@?4(DzMRRmjOAQf_;<1;U0fYJW%|4!L%D#& z2ok4|&16Y7AV`KJF;r)!0pDqB0hHhJ1CPXSwK45p{LOR;tL|CZ21s(o&?1 z)-tkqlqt+@SY@{9-F%$^Ewf=WO^wJfUqaHdf1>LXAnhQk31;7Dq?QRM$Eew%Y|EY; zVRW)CyYdC&G42j<@%a!l%r33cH*?JFb%ZsH5uIzV^dQH)Q-ie`X`VC9DQm_&d_o@` zpu4uG9@eD_BsE1t|E!3U5Bj_d**Y#h??H@|Jj>=9=7Ayh?HI4Lk2??>AwXj?jvHI-vO*0`~RWJ`rIzkBdLz;Dn?eL zsrzvazAjL!zyuA%5;H*qG39$SlPg3^1k2bH9Qk_*sqSvQ3=JJxmXZ}JdFO5Esw>8=K`RGyXdoJ`%)opwoMCdx5p z_Z1~sn5^5xT86zt-eOgTh_j8oX%;nn&oQfocV4e=EV7>D&f@0UCCCz)WYj|FynCEcu`Bcc&QboF&6% z=v05Dy4uIQnD+hLts*DhhH>7StfAB5GbYb#woaCPr$ItA>T;-8IrIJNHi+wOR#r05+$9fA9`4chr zbpl^}Ya~NHHJ;R|8~fn5RQ^voHlN|+ekGQGhwmx&Zh7DS zDKeJf>&4F72^fg)^hDvAhbIodd#%&iH)i?f?)`uo87z#T=kz_`J};)YHZY}UdEyIb zAKM}G`O~7^P^{@VXUFzRqYEcZIN{Rq*~#bo(W3OViQnH|YR>JO+UXg$*jK=R4$Y;R literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/include/physics_effects.h b/Extras/PhysicsEffects/include/physics_effects.h new file mode 100644 index 0000000..e270c47 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects.h @@ -0,0 +1,23 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PHYSICS_EFFECTS_H +#define _SCE_PHYSICS_EFFECTS_H + +#include "physics_effects/low_level/pfx_low_level_include.h" +#include "physics_effects/util/pfx_util_include.h" + +#endif // __PHYSICS_EFFECTS_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_common.h b/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_common.h new file mode 100644 index 0000000..c40b733 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_common.h @@ -0,0 +1,181 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_COMMON_H +#define _SCE_PFX_COMMON_H + +// Include common headers +#ifdef _WIN32 + #include + #include + #include +#else + #include + #include +#endif + +#include +#include +#include + +#if defined(_WIN32) + #include "pfx_vectormath_include.win32.h" +#else + #include "pfx_vectormath_include.h" +#endif + +namespace sce { +namespace PhysicsEffects { +// Basic Types +#if defined(_WIN32) + typedef char PfxInt8; + typedef unsigned char PfxUInt8; + typedef short PfxInt16; + typedef unsigned short PfxUInt16; + typedef int PfxInt32; + typedef unsigned int PfxUInt32; + typedef long long PfxInt64; + typedef unsigned long long PfxUInt64; +#else + typedef int8_t PfxInt8; + typedef uint8_t PfxUInt8; + typedef int16_t PfxInt16; + typedef uint16_t PfxUInt16; + typedef int32_t PfxInt32; + typedef uint32_t PfxUInt32; + typedef int64_t PfxInt64; + typedef uint64_t PfxUInt64; +#endif + +typedef bool PfxBool; +typedef float PfxFloat; +} //namespace PhysicsEffects +} //namespace sce + +// Debug Print +#ifdef _WIN32 +static void pfxOutputDebugString(const char *str, ...) +{ + char strDebug[1024]={0}; + va_list argList; + va_start(argList, str); + vsprintf_s(strDebug,str,argList); + OutputDebugStringA(strDebug); + va_end(argList); +} +#endif + +#if defined(_DEBUG) + #if defined(_WIN32) + #define SCE_PFX_DPRINT pfxOutputDebugString + #else + #define SCE_PFX_DPRINT(...) printf(__VA_ARGS__) + #endif +#else + #ifdef _WIN32 + #define SCE_PFX_DPRINT + #else + #define SCE_PFX_DPRINT(...) + #endif +#endif + +// Printf +#if defined(_WIN32) + #define SCE_PFX_PRINTF pfxOutputDebugString +#else +// ARA begin insert new code + #ifdef __ANDROID__ + #include + #define SCE_PFX_PRINTF(...) __android_log_print(ANDROID_LOG_VERBOSE, "SCE_PFX_PRINTF", __VA_ARGS__) + #else + #define SCE_PFX_PRINTF(...) printf(__VA_ARGS__) + #endif +// ARA end, old baseline code block was: +// #define SCE_PFX_PRINTF(...) printf(__VA_ARGS__) +// +#endif + +#define SCE_PFX_UNLIKELY(a) (a) +#define SCE_PFX_LIKELY(a) (a) + +// Inline +#if defined(_MSC_VER) + #define SCE_PFX_FORCE_INLINE __forceinline +#elif defined(__SNC__) || defined(__GNUC__) + #define SCE_PFX_FORCE_INLINE inline __attribute__((always_inline)) +#endif + +// Assert +#define SCE_PFX_HALT() abort() + +#ifdef _DEBUG + #define SCE_PFX_ASSERT(test) {if(!(test)){SCE_PFX_PRINTF("Assert "__FILE__ ":%u ("#test")\n", __LINE__);SCE_PFX_HALT();}} + #define SCE_PFX_ASSERT_MSG(test,msg) {if(!(test)){SCE_PFX_PRINTF("Assert " msg " " __FILE__ ":%u ("#test")\n",__LINE__);SCE_PFX_HALT();}} +#else + #define SCE_PFX_ASSERT(test) + #define SCE_PFX_ASSERT_MSG(test,msg) +#endif + +#define SCE_PFX_ALWAYS_ASSERT(test) {if(!(test)){SCE_PFX_PRINTF("Assert "__FILE__ ":%u ("#test")\n", __LINE__);SCE_PFX_HALT();}} +#define SCE_PFX_ALWAYS_ASSERT_MSG(test,msg) {if(!(test)){SCE_PFX_PRINTF("Assert:" msg " " __FILE__ ":%u ("#test")\n",__LINE__);SCE_PFX_HALT();}} + +// Aligned +#if defined(_MSC_VER) + #define SCE_PFX_ALIGNED(alignment) __declspec(align(alignment)) +#elif defined(__SNC__) || defined(__GNUC__) + #define SCE_PFX_ALIGNED(alignment) __attribute__((__aligned__((alignment)))) +#endif + +// Etc +#define SCE_PFX_MIN(a,b) (((a)<(b))?(a):(b)) +#define SCE_PFX_MAX(a,b) (((a)>(b))?(a):(b)) +#define SCE_PFX_CLAMP(v,a,b) SCE_PFX_MAX(a,SCE_PFX_MIN(v,b)) +#define SCE_PFX_SWAP(type, x, y) do {type t; t=x; x=y; y=t; } while (0) +#define SCE_PFX_SQR(a) ((a)*(a)) + +#define SCE_PFX_ALIGN16(count,size) ((((((count) * (size)) + 15) & (~15)) + (size)-1) / (size)) +#define SCE_PFX_ALIGN128(count,size) ((((((count) * (size)) + 127) & (~127)) + (size)-1) / (size)) + +#define SCE_PFX_AVAILABLE_BYTES_ALIGN16(ptr,bytes) (bytes-((uintptr_t)(ptr)&0x0f)) +#define SCE_PFX_AVAILABLE_BYTES_ALIGN128(ptr,bytes) (bytes-((uintptr_t)(ptr)&0x7f)) + +#define SCE_PFX_BYTES_ALIGN16(bytes) (((bytes)+15)&(~15)) +#define SCE_PFX_BYTES_ALIGN128(bytes) (((bytes)+127)&(~127)) + +#define SCE_PFX_PTR_ALIGN16(ptr) (((uintptr_t)(ptr)+15)&(~15)) +#define SCE_PFX_PTR_ALIGN128(ptr) (((uintptr_t)(ptr)+127)&(~127)) + +#define SCE_PFX_PTR_IS_ALIGNED16(ptr) (((uintptr_t)(ptr)&0x0f)==0) +#define SCE_PFX_PTR_IS_ALIGNED128(ptr) (((uintptr_t)(ptr)&0x7f)==0) + +#define SCE_PFX_GET_POINTER(offset,stride,id) ((uintptr_t)(offset)+(stride)*(id)) + +#define SCE_PFX_FLT_MAX 1e+38f +#define SCE_PFX_PI 3.14159265358979f + +#define SCE_PFX_RANGE_CHECK(val,minVal,maxVal) (((val)>=(minVal))&&((val)<=(maxVal))) + +#define SCE_PFX_IS_RUNNING_ON_64BIT_ENV() ( ( sizeof(void*)==8 )? true : false ) + +#if defined(__SNC__) || defined(__GNUC__) + #define SCE_PFX_PADDING(count,bytes) PfxUInt8 padding##count[bytes]; +#else + #define SCE_PFX_PADDING(count,bytes) +#endif + +#include "pfx_error_code.h" + +#endif // _SCE_PFX_COMMON_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_error_code.h b/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_error_code.h new file mode 100644 index 0000000..ca117b7 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_error_code.h @@ -0,0 +1,30 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_ERROR_CODE_H +#define _SCE_PFX_ERROR_CODE_H + +#define SCE_PFX_OK 0 +#define SCE_PFX_ERR_INVALID_VALUE 0x80880001 +#define SCE_PFX_ERR_INVALID_ALIGN 0x80880002 +#define SCE_PFX_ERR_OUT_OF_BUFFER 0x80880003 +#define SCE_PFX_ERR_OUT_OF_MAX_PAIRS 0x80880004 +#define SCE_PFX_ERR_OUT_OF_RANGE 0x80880005 +#define SCE_PFX_ERR_OUT_OF_WORLD 0x80880006 +#define SCE_PFX_ERR_INVALID_FLAG 0x80880007 + +#endif // _SCE_PFX_ERROR_CODE_H + diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_heap_manager.h b/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_heap_manager.h new file mode 100644 index 0000000..10ad5af --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_heap_manager.h @@ -0,0 +1,141 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_HEAP_MANAGER_H +#define _SCE_PFX_HEAP_MANAGER_H + +#include "pfx_common.h" + +//J プールされたメモリを管理するスタックのサイズ +//E Size of a stack which used to manage pool memory +#define SCE_PFX_HEAP_STACK_SIZE 64 + +#define SCE_PFX_MIN_ALLOC_SIZE 16 + +#define SCE_PFX_ALLOC_BYTES_ALIGN16(bytes) SCE_PFX_MAX(16,SCE_PFX_BYTES_ALIGN16(bytes)) +#define SCE_PFX_ALLOC_BYTES_ALIGN128(bytes) SCE_PFX_MAX(128,SCE_PFX_BYTES_ALIGN128(bytes)) + +#if defined (_WIN64) || defined (__LP64__) + #define SCE_PFX_ALIGN_MASK_16 0xfffffffffffffff0 + #define SCE_PFX_ALIGN_MASK_128 0xffffffffffffff80 +#else + #define SCE_PFX_ALIGN_MASK_16 0xfffffff0 + #define SCE_PFX_ALIGN_MASK_128 0xffffff80 +#endif + +/////////////////////////////////////////////////////////////////////////////// +// PfxHeapManager + +//J <補足> +//J メモリはスタックで管理されています。取得した順と逆に開放する必要があります。 +//J メモリを一気に開放したい場合はclear()を呼び出してください。 +//J 最小割り当てサイズはSCE_PFX_MIN_ALLOC_SIZEで定義されます。 + +//E +//E Memory is managed as a stack, so deallocate() needs to be called in reverse order. +//E Use clear() to deallocate all allocated memory at once. +//E SCE_PFX_MIN_ALLOC_SIZE defines the smallest amount of buffer. + +namespace sce { +namespace PhysicsEffects { + +class PfxHeapManager +{ +private: + PfxUInt8 *m_heap; + PfxUInt8 *m_poolStack[SCE_PFX_HEAP_STACK_SIZE]; + PfxInt32 m_heapBytes; + PfxInt32 m_curStack; + PfxInt32 m_rest; + +public: + enum {ALIGN16=16,ALIGN128=128}; + + PfxHeapManager(PfxUInt8 *buf,PfxInt32 bytes) + { + m_heap = buf; + m_heapBytes = bytes; + clear(); + } + + ~PfxHeapManager() + { + } + + PfxInt32 getAllocated() + { + return (PfxInt32)(m_poolStack[m_curStack]-m_heap); + } + + PfxInt32 getRest() + { + return m_heapBytes-getAllocated(); + } + + void *allocate(size_t bytes,PfxInt32 alignment = ALIGN16) + { + SCE_PFX_ALWAYS_ASSERT(m_curStack +#endif +// ARA end + +//J パフォーマンス測定する場合はPFX_USE_PERFCOUNTERを定義 +//J ブックマークを使用する場合はPFX_USE_BOOKMARKを定義 + +//E Define SCE_PFX_USE_PERFCOUNTER to check performance +//E Define SCE_PFX_USE_BOOKMARK to use bookmark + + +#define SCE_PFX_MAX_PERF_STR 32 +#define SCE_PFX_MAX_PERF_COUNT 20 + +//#define SCE_PFX_USE_PERFCOUNTER +//#define SCE_PFX_USE_BOOKMARK + +namespace sce { +namespace PhysicsEffects { +#ifdef SCE_PFX_USE_PERFCOUNTER + +class PfxPerfCounter +{ +private: + int m_count,m_strCount; + char m_str[SCE_PFX_MAX_PERF_COUNT][SCE_PFX_MAX_PERF_STR]; + float m_freq; + + SCE_PFX_PADDING(1,4) +#ifdef _WIN32 + LONGLONG m_cnt[SCE_PFX_MAX_PERF_COUNT*2]; +#else +// ARA begin insert new code + timespec m_cnt[SCE_PFX_MAX_PERF_COUNT*2]; +// ARA end +#endif + + void count(int i) + { +#ifdef _WIN32 + QueryPerformanceCounter( (LARGE_INTEGER *)&m_cnt[i] ); +#else +// ARA begin insert new code + clock_gettime(CLOCK_MONOTONIC, &m_cnt[i]); +// ARA end +#endif + } + +public: + PfxPerfCounter() + { +#ifdef _WIN32 + LARGE_INTEGER sPerfCountFreq; + QueryPerformanceFrequency(&sPerfCountFreq); + m_freq = (float)sPerfCountFreq.QuadPart; +#else +// ARA begin insert new code + m_freq = 1000000000.0f; // clock_gettime reports time in nanoseconds (though accuracy is platform dependent) +// ARA end +#endif + resetCount(); + } + + ~PfxPerfCounter() + { + //printCount(); + } + + void countBegin(const char *name) + { + SCE_PFX_ASSERT(m_strCount < SCE_PFX_MAX_PERF_COUNT); + strncpy(m_str[m_strCount],name,SCE_PFX_MAX_PERF_STR-1); + m_str[m_strCount][SCE_PFX_MAX_PERF_STR-1] = 0x00; + m_strCount++; + count(m_count++); + } + + void countEnd() + { + count(m_count++); + } + + void resetCount() + { + m_strCount = 0; + m_count = 0; + } + + float getCountTime(int i) + { +#if _WIN32 + return (float)(m_cnt[i+1]-m_cnt[i]) / m_freq * 1000.0f; +#else +// ARA begin insert new code + return float(m_cnt[i+1].tv_sec - m_cnt[i].tv_sec) + + (float(m_cnt[i+1].tv_nsec - m_cnt[i].tv_nsec) / m_freq); +// ARA end +#endif +} + + void printCount() + { + if(m_count%2 != 0) countEnd(); + SCE_PFX_PRINTF("*** PfxPerfCounter results ***\n"); + float total = 0.0f; + for(int i=0;i+1>1],getCountTime(i),getCountTime(i)/total*100.0f); + } + SCE_PFX_PRINTF(" -- Total %fms\n",total); + } +}; + +#else /* SCE_PFX_USE_PERFCOUNTER */ + +class PfxPerfCounter +{ +public: + PfxPerfCounter() {} + ~PfxPerfCounter() {} + void countBegin(const char *name) {(void) name;} + void countEnd() {} + void resetCount() {} + float getCountTime(int i) {(void)i;return 0.0f;} + void printCount() {} +}; + +#endif /* SCE_PFX_USE_PERFCOUNTER */ + +#define pfxInsertBookmark(bookmark) + +#ifdef SCE_PFX_USE_BOOKMARK + #define SCE_PFX_PUSH_MARKER(name) + #define SCE_PFX_POP_MARKER() +#else + #define SCE_PFX_PUSH_MARKER(name) + #define SCE_PFX_POP_MARKER() +#endif + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_PERF_COUNTER_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_vec_int3.h b/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_vec_int3.h new file mode 100644 index 0000000..2c588bf --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_vec_int3.h @@ -0,0 +1,166 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_VEC_INT3_H +#define _SCE_PFX_VEC_INT3_H + +#include "pfx_common.h" + + + +namespace sce { +namespace PhysicsEffects { + +class SCE_PFX_ALIGNED(16) PfxVecInt3 +{ +private: +PfxInt32 m_x,m_y,m_z,m_w; + +public: +PfxVecInt3() {m_x=m_y=m_z=m_w=0;} +PfxVecInt3(const PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG vec) {m_x=(PfxInt32)vec[0];m_y=(PfxInt32)vec[1];m_z=(PfxInt32)vec[2];m_w=0;} +PfxVecInt3(PfxFloat fx,PfxFloat fy,PfxFloat fz) {m_x=(PfxInt32)fx;m_y=(PfxInt32)fy;m_z=(PfxInt32)fz;m_w=0;} +PfxVecInt3(PfxInt32 iv) {m_x=m_y=m_z=iv;m_w=0;} +PfxVecInt3(PfxInt32 ix,PfxInt32 iy,PfxInt32 iz) {m_x=ix;m_y=iy;m_z=iz;m_w=0;} + + inline PfxVecInt3 &operator =( const PfxVecInt3 &vec); + +inline PfxInt32 get(PfxInt32 i) const {return *(&m_x+i);} +inline PfxInt32 getX() const {return m_x;} +inline PfxInt32 getY() const {return m_y;} +inline PfxInt32 getZ() const {return m_z;} +inline void set(PfxInt32 i,PfxInt32 v) {*(&m_x+i) = v;} +inline void setX(PfxInt32 v) {m_x = v;} +inline void setY(PfxInt32 v) {m_y = v;} +inline void setZ(PfxInt32 v) {m_z = v;} + + inline const PfxVecInt3 operator +( const PfxVecInt3 & vec ) const; + inline const PfxVecInt3 operator -( const PfxVecInt3 & vec ) const; + inline const PfxVecInt3 operator *( PfxInt32 scalar ) const; + inline const PfxVecInt3 operator /( PfxInt32 scalar ) const; + + inline PfxVecInt3 & operator +=( const PfxVecInt3 & vec ); + inline PfxVecInt3 & operator -=( const PfxVecInt3 & vec ); + inline PfxVecInt3 & operator *=( PfxInt32 scalar ); + inline PfxVecInt3 & operator /=( PfxInt32 scalar ); + + inline const PfxVecInt3 operator -() const; + +operator PfxVector3() const +{ + return PfxVector3((PfxFloat)m_x,(PfxFloat)m_y,(PfxFloat)m_z); +} +}; + +inline PfxVecInt3 &PfxVecInt3::operator =( const PfxVecInt3 &vec) +{ + m_x = vec.m_x; + m_y = vec.m_y; + m_z = vec.m_z; + return *this; +} + +inline const PfxVecInt3 PfxVecInt3::operator +( const PfxVecInt3 & vec ) const +{ + return PfxVecInt3(m_x+vec.m_x, m_y+vec.m_y, m_z+vec.m_z); +} + +inline const PfxVecInt3 PfxVecInt3::operator -( const PfxVecInt3 & vec ) const +{ + return PfxVecInt3(m_x-vec.m_x, m_y-vec.m_y, m_z-vec.m_z); +} + +inline const PfxVecInt3 PfxVecInt3::operator *( PfxInt32 scalar ) const +{ + return PfxVecInt3(m_x*scalar, m_y*scalar, m_z*scalar); +} + +inline const PfxVecInt3 PfxVecInt3::operator /( PfxInt32 scalar ) const +{ + return PfxVecInt3(m_x/scalar, m_y/scalar, m_z/scalar); +} + +inline PfxVecInt3 &PfxVecInt3::operator +=( const PfxVecInt3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline PfxVecInt3 &PfxVecInt3::operator -=( const PfxVecInt3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline PfxVecInt3 &PfxVecInt3::operator *=( PfxInt32 scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline PfxVecInt3 &PfxVecInt3::operator /=( PfxInt32 scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const PfxVecInt3 PfxVecInt3::operator -() const +{ +return PfxVecInt3(-m_x,-m_y,-m_z); +} + +inline const PfxVecInt3 operator *( PfxInt32 scalar, const PfxVecInt3 & vec ) +{ + return vec * scalar; +} + +inline const PfxVecInt3 mulPerElem( const PfxVecInt3 & vec0, const PfxVecInt3 & vec1 ) +{ +return PfxVecInt3(vec0.getX()*vec1.getX(), vec0.getY()*vec1.getY(), vec0.getZ()*vec1.getZ()); +} + +inline const PfxVecInt3 divPerElem( const PfxVecInt3 & vec0, const PfxVecInt3 & vec1 ) +{ +return PfxVecInt3(vec0.getX()/vec1.getX(), vec0.getY()/vec1.getY(), vec0.getZ()/vec1.getZ()); +} + +inline const PfxVecInt3 absPerElem( const PfxVecInt3 & vec ) +{ +return PfxVecInt3(abs(vec.getX()), abs(vec.getY()), abs(vec.getZ())); +} + +inline const PfxVecInt3 maxPerElem( const PfxVecInt3 & vec0, const PfxVecInt3 & vec1 ) +{ + return PfxVecInt3( + (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ() + ); +} + +inline const PfxVecInt3 minPerElem( const PfxVecInt3 & vec0, const PfxVecInt3 & vec1 ) +{ + return PfxVecInt3( + (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ() + ); +} +} //namespace PhysicsEffects +} //namespace sce + + +#endif // _SCE_PFX_VEC_INT3_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_vec_utils.h b/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_vec_utils.h new file mode 100644 index 0000000..2b50db5 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_vec_utils.h @@ -0,0 +1,181 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_VEC_UTILS_H +#define _SCE_PFX_VEC_UTILS_H + +#include "pfx_common.h" +#include "pfx_vec_int3.h" + +namespace sce { +namespace PhysicsEffects { +static SCE_PFX_FORCE_INLINE PfxVector3 pfxReadVector3(const PfxFloat* fptr) +{ + PfxVector3 v; + +loadXYZ(v, fptr); + + return v; +} + +static SCE_PFX_FORCE_INLINE PfxPoint3 pfxReadPoint3(const PfxFloat* fptr) +{ + PfxPoint3 v; + +loadXYZ(v, fptr); + + return v; +} + +static SCE_PFX_FORCE_INLINE PfxQuat pfxReadQuat(const PfxFloat* fptr) +{ + PfxQuat vq; + +loadXYZW(vq, fptr); + + return vq; +} + +static SCE_PFX_FORCE_INLINE void pfxStoreVector3(const PfxVector3 &src, PfxFloat* fptr) +{ +storeXYZ(src, fptr); +} + +static SCE_PFX_FORCE_INLINE void pfxStorePoint3(const PfxPoint3 &src, PfxFloat* fptr) +{ +storeXYZ(src, fptr); +} + +static SCE_PFX_FORCE_INLINE void pfxStoreQuat(const PfxQuat &src, PfxFloat* fptr) +{ +storeXYZW(src, fptr); +} + +} // namespace PhysicsEffects +} // namespace sce + +namespace sce { +namespace PhysicsEffects { +static SCE_PFX_FORCE_INLINE +void pfxGetPlaneSpace(const PfxVector3& n, PfxVector3& fptr, PfxVector3& q) +{ + if(fabsf(n[2]) > 0.707f) { + // choose fptr in y-z plane + PfxFloat a = n[1]*n[1] + n[2]*n[2]; + PfxFloat k = 1.0f/sqrtf(a); + fptr[0] = 0; + fptr[1] = -n[2]*k; + fptr[2] = n[1]*k; + // set q = n x fptr + q[0] = a*k; + q[1] = -n[0]*fptr[2]; + q[2] = n[0]*fptr[1]; + } + else { + // choose fptr in x-y plane + PfxFloat a = n[0]*n[0] + n[1]*n[1]; + PfxFloat k = 1.0f/sqrtf(a); + fptr[0] = -n[1]*k; + fptr[1] = n[0]*k; + fptr[2] = 0; + // set q = n x fptr + q[0] = -n[2]*fptr[1]; + q[1] = n[2]*fptr[0]; + q[2] = a*k; + } +} + +static SCE_PFX_FORCE_INLINE +void pfxGetRotationAngleAndAxis(const PfxQuat &unitQuat,PfxFloat &angle,PfxVector3 &axis) +{ + const PfxFloat epsilon=0.00001f; + + if(fabsf(unitQuat.getW()) < 1.0f-epsilon && lengthSqr(unitQuat.getXYZ()) > epsilon) { + PfxFloat angleHalf = acosf(unitQuat.getW()); + PfxFloat sinAngleHalf = sinf(angleHalf); + + if(fabsf(sinAngleHalf) > 1.0e-10f) { + axis = unitQuat.getXYZ()/sinAngleHalf; + } else { + axis = unitQuat.getXYZ(); + } + angle = 2.0f*angleHalf; + } else { + angle = 0.0f; + axis = PfxVector3(1.0f, 0.0f, 0.0f); + } +} + +static SCE_PFX_FORCE_INLINE +PfxFloat pfxSafeAtan2(PfxFloat y,PfxFloat x) +{ + if(SCE_PFX_SQR(x) < 0.000001f || SCE_PFX_SQR(y) < 0.000001f) { + return 0.0f; + } + return atan2f(y,x); +} + +static SCE_PFX_FORCE_INLINE +PfxVector3 pfxSafeNormalize(const PfxVector3 &vec) +{ + float lenSqr = lengthSqr( vec ); + + if( lenSqr > 0.000001f ) { + return normalize(vec); + }else { + return PfxVector3( 1.0f, 0.0f, 0.0f ); + } +} + +static SCE_PFX_FORCE_INLINE +PfxVecInt3 pfxConvertCoordWorldToLocal(const PfxVector3 &coord,const PfxVector3 ¢er,const PfxVector3 &half) +{ + const PfxVector3 sz(65535.0f); + PfxVector3 q = divPerElem(coord - center + half,2.0f*half); + q = minPerElem(maxPerElem(q,PfxVector3(0.0f)),PfxVector3(1.0f)); // clamp 0.0 - 1.0 + q = mulPerElem(q,sz); + return PfxVecInt3(q); +} + +static SCE_PFX_FORCE_INLINE +void pfxConvertCoordWorldToLocal( + const PfxVector3 ¢er,const PfxVector3 &half, + const PfxVector3 &coordMin,const PfxVector3 &coordMax, + PfxVecInt3 &localMin,PfxVecInt3 &localMax) +{ + const PfxVector3 sz(65535.0f); + PfxVector3 qmin = divPerElem(coordMin - center + half,2.0f*half); + qmin = minPerElem(maxPerElem(qmin,PfxVector3(0.0f)),PfxVector3(1.0f)); // clamp 0.0 - 1.0 + qmin = mulPerElem(qmin,sz); + + PfxVector3 qmax = divPerElem(coordMax - center + half,2.0f*half); + qmax = minPerElem(maxPerElem(qmax,PfxVector3(0.0f)),PfxVector3(1.0f)); // clamp 0.0 - 1.0 + qmax = mulPerElem(qmax,sz); +localMin = PfxVecInt3(floorf(qmin[0]),floorf(qmin[1]),floorf(qmin[2])); +localMax = PfxVecInt3(ceilf(qmax[0]),ceilf(qmax[1]),ceilf(qmax[2])); +} + +static SCE_PFX_FORCE_INLINE +PfxVector3 pfxConvertCoordLocalToWorld(const PfxVecInt3 &coord,const PfxVector3 ¢er,const PfxVector3 &half) +{ + PfxVector3 sz(65535.0f),vcoord(coord); + PfxVector3 q = divPerElem(vcoord,sz); + return mulPerElem(q,2.0f*half) + center - half; +} +} // namespace PhysicsEffects +} // namespace sce + +#endif // _SCE_PFX_VEC_UTILS_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_vectormath_include.h b/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_vectormath_include.h new file mode 100644 index 0000000..1cd3590 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_vectormath_include.h @@ -0,0 +1,101 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_VECTORMATH_INCLUDE_H +#define _SCE_PFX_VECTORMATH_INCLUDE_H + +// If you want to use the free/open sourced vectormath, you need to +// put codes in the include/vecmath folder and set following define. +#define SCE_PFX_USE_FREE_VECTORMATH + +// If you want to use vectomath with SIMD, +// following define is needed. +//#define SCE_PFX_USE_SIMD_VECTORMATH + +// This option enables to replace original implementation with +// vector geometry library. +//#define SCE_PFX_USE_GEOMETRY + +// vectormath include +#ifdef SCE_PFX_USE_FREE_VECTORMATH + // ARA begin insert new code + #if defined(SCE_PFX_USE_SIMD_VECTORMATH) && defined(__ANDROID__) && defined(__ARM_NEON__) + // For Android targets supporting NEON instructions, + // use NEON-optimized vector math library + #include "../../../vecmath/neon/vectormath_aos.h" + #include "../../../vecmath/neon/floatInVec.h" + #else + // ARA end + // use standard free vector math library + #include "../../../vecmath/std/vectormath_aos.h" + #include "../../../vecmath/std/floatInVec.h" + // ARA begin insert new code + #endif + // ARA end + #define SCE_VECTORMATH_AOS_VECTOR_ARG + #define SCE_VECTORMATH_AOS_MATRIX_ARG + + namespace sce { + namespace PhysicsEffects { + typedef Vectormath::Aos::Point3 PfxPoint3; + typedef Vectormath::Aos::Vector3 PfxVector3; + typedef Vectormath::Aos::Vector4 PfxVector4; + typedef Vectormath::Aos::Quat PfxQuat; + typedef Vectormath::Aos::Matrix3 PfxMatrix3; + typedef Vectormath::Aos::Matrix4 PfxMatrix4; + typedef Vectormath::Aos::Transform3 PfxTransform3; + typedef Vectormath::floatInVec PfxFloatInVec; + typedef Vectormath::boolInVec PfxBoolInVec; + } //namespace PhysicsEffects + } //namespace sce +#else + #include + #define SCE_GEOMETRY_USE_SCALAR_MATH + #define SCE_VECTORMATH_AOS_VECTOR_ARG SCE_VECTORMATH_SCALAR_AOS_VECTOR_ARG + #define SCE_VECTORMATH_AOS_MATRIX_ARG SCE_VECTORMATH_SCALAR_AOS_MATRIX_ARG + + namespace sce { + namespace PhysicsEffects { + typedef sce::Vectormath::Scalar::Aos::Point3 PfxPoint3; + typedef sce::Vectormath::Scalar::Aos::Vector3 PfxVector3; + typedef sce::Vectormath::Scalar::Aos::Vector4 PfxVector4; + typedef sce::Vectormath::Scalar::Aos::Quat PfxQuat; + typedef sce::Vectormath::Scalar::Aos::Matrix3 PfxMatrix3; + typedef sce::Vectormath::Scalar::Aos::Matrix4 PfxMatrix4; + typedef sce::Vectormath::Scalar::Aos::Transform3 PfxTransform3; + typedef sce::Vectormath::Scalar::floatInVec PfxFloatInVec; + typedef sce::Vectormath::Scalar::boolInVec PfxBoolInVec; + } //namespace PhysicsEffects + } //namespace sce + + #ifdef SCE_PFX_USE_GEOMETRY + #include + namespace sce { + namespace PhysicsEffects { + typedef sce::Geometry::Aos::Line PfxGeomLine; + typedef sce::Geometry::Aos::Segment PfxGeomSegment; + typedef sce::Geometry::Aos::Plane PfxGeomPlane; + typedef sce::Geometry::Aos::Sphere PfxGeomSphere; + typedef sce::Geometry::Aos::Capsule PfxGeomCapsule; + typedef sce::Geometry::Aos::Bounds PfxGeomBounds; + typedef sce::Geometry::Aos::Aabb PfxGeomAabb; + typedef sce::Geometry::Aos::Obb PfxGeomObb; + } //namespace PhysicsEffects + } //namespace sce + #endif +#endif + +#endif // _SCE_PFX_VECTORMATH_INCLUDE_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_vectormath_include.win32.h b/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_vectormath_include.win32.h new file mode 100644 index 0000000..4d5673a --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/base/pfx_vectormath_include.win32.h @@ -0,0 +1,116 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_VECTORMATH_INCLUDE_WIN32_H +#define _SCE_PFX_VECTORMATH_INCLUDE_WIN32_H + +// If you want to use the free/open sourced vectormath, you need to +// put codes in the include/vecmath folder and set following define. +#define SCE_PFX_USE_FREE_VECTORMATH + +// If you want to use vectomath with SIMD, +// following define is needed. +// #define SCE_PFX_USE_SIMD_VECTORMATH + +// This option enables to replace original implementation with +// vector geometry library. +//#define SCE_PFX_USE_GEOMETRY + +// vectormath include +#ifdef SCE_PFX_USE_FREE_VECTORMATH + #ifdef SCE_PFX_USE_SIMD_VECTORMATH + #include "../../../vecmath/sse/vectormath_aos.h" + #include "../../../vecmath/sse/floatInVec.h" + #define SCE_VECTORMATH_AOS_VECTOR_ARG & + #define SCE_VECTORMATH_AOS_MATRIX_ARG & + #else + #include "../../../vecmath/std/vectormath_aos.h" + #include "../../../vecmath/std/floatInVec.h" + #define SCE_VECTORMATH_AOS_VECTOR_ARG + #define SCE_VECTORMATH_AOS_MATRIX_ARG + #endif + + namespace sce { + namespace PhysicsEffects { + typedef Vectormath::Aos::Point3 PfxPoint3; + typedef Vectormath::Aos::Vector3 PfxVector3; + typedef Vectormath::Aos::Vector4 PfxVector4; + typedef Vectormath::Aos::Quat PfxQuat; + typedef Vectormath::Aos::Matrix3 PfxMatrix3; + typedef Vectormath::Aos::Matrix4 PfxMatrix4; + typedef Vectormath::Aos::Transform3 PfxTransform3; + typedef Vectormath::floatInVec PfxFloatInVec; + typedef Vectormath::boolInVec PfxBoolInVec; + } //namespace PhysicsEffects + } //namespace sce +#else + #include + + #ifdef SCE_PFX_USE_SIMD_VECTORMATH + #define SCE_VECTORMATH_AOS_VECTOR_ARG SCE_VECTORMATH_SIMD_AOS_VECTOR_ARG + #define SCE_VECTORMATH_AOS_MATRIX_ARG SCE_VECTORMATH_SIMD_AOS_MATRIX_ARG + + namespace sce { + namespace PhysicsEffects { + typedef sce::Vectormath::Simd::Aos::Point3 PfxPoint3; + typedef sce::Vectormath::Simd::Aos::Vector3 PfxVector3; + typedef sce::Vectormath::Simd::Aos::Vector4 PfxVector4; + typedef sce::Vectormath::Simd::Aos::Quat PfxQuat; + typedef sce::Vectormath::Simd::Aos::Matrix3 PfxMatrix3; + typedef sce::Vectormath::Simd::Aos::Matrix4 PfxMatrix4; + typedef sce::Vectormath::Simd::Aos::Transform3 PfxTransform3; + typedef sce::Vectormath::Simd::floatInVec PfxFloatInVec; + typedef sce::Vectormath::Simd::boolInVec PfxBoolInVec; + } //namespace PhysicsEffects + } //namespace sce + #else + #define SCE_GEOMETRY_USE_SCALAR_MATH + #define SCE_VECTORMATH_AOS_VECTOR_ARG SCE_VECTORMATH_SCALAR_AOS_VECTOR_ARG + #define SCE_VECTORMATH_AOS_MATRIX_ARG SCE_VECTORMATH_SCALAR_AOS_MATRIX_ARG + + namespace sce { + namespace PhysicsEffects { + typedef sce::Vectormath::Scalar::Aos::Point3 PfxPoint3; + typedef sce::Vectormath::Scalar::Aos::Vector3 PfxVector3; + typedef sce::Vectormath::Scalar::Aos::Vector4 PfxVector4; + typedef sce::Vectormath::Scalar::Aos::Quat PfxQuat; + typedef sce::Vectormath::Scalar::Aos::Matrix3 PfxMatrix3; + typedef sce::Vectormath::Scalar::Aos::Matrix4 PfxMatrix4; + typedef sce::Vectormath::Scalar::Aos::Transform3 PfxTransform3; + typedef sce::Vectormath::Scalar::floatInVec PfxFloatInVec; + typedef sce::Vectormath::Scalar::boolInVec PfxBoolInVec; + } //namespace PhysicsEffects + } //namespace sce + #endif +#endif + +#ifdef SCE_PFX_USE_GEOMETRY +#include +namespace sce { +namespace PhysicsEffects { +typedef sce::Geometry::Aos::Line PfxGeomLine; +typedef sce::Geometry::Aos::Segment PfxGeomSegment; +typedef sce::Geometry::Aos::Plane PfxGeomPlane; +typedef sce::Geometry::Aos::Sphere PfxGeomSphere; +typedef sce::Geometry::Aos::Capsule PfxGeomCapsule; +typedef sce::Geometry::Aos::Bounds PfxGeomBounds; +typedef sce::Geometry::Aos::Aabb PfxGeomAabb; +typedef sce::Geometry::Aos::Obb PfxGeomObb; +} //namespace PhysicsEffects +} //namespace sce +#endif + +#endif // _SCE_PFX_VECTORMATH_INCLUDE_WIN32_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/broadphase/pfx_broadphase_pair.h b/Extras/PhysicsEffects/include/physics_effects/base_level/broadphase/pfx_broadphase_pair.h new file mode 100644 index 0000000..5fe10d9 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/broadphase/pfx_broadphase_pair.h @@ -0,0 +1,46 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_BROADPHASE_PAIR_H +#define _SCE_PFX_BROADPHASE_PAIR_H + +#include "../sort/pfx_sort_data.h" + +namespace sce { +namespace PhysicsEffects { + +typedef PfxSortData16 PfxBroadphasePair; + +SCE_PFX_FORCE_INLINE void pfxSetObjectIdA(PfxBroadphasePair &pair,PfxUInt16 i) {pair.set16(0,i);} +SCE_PFX_FORCE_INLINE void pfxSetObjectIdB(PfxBroadphasePair &pair,PfxUInt16 i) {pair.set16(1,i);} +SCE_PFX_FORCE_INLINE void pfxSetMotionMaskA(PfxBroadphasePair &pair,PfxUInt8 i) {pair.set8(4,i);} +SCE_PFX_FORCE_INLINE void pfxSetMotionMaskB(PfxBroadphasePair &pair,PfxUInt8 i) {pair.set8(5,i);} +SCE_PFX_FORCE_INLINE void pfxSetBroadphaseFlag(PfxBroadphasePair &pair,PfxUInt8 f) {pair.set8(6,(pair.get8(6)&0xf0)|(f&0x0f));} +SCE_PFX_FORCE_INLINE void pfxSetActive(PfxBroadphasePair &pair,PfxBool b) {pair.set8(6,(pair.get8(6)&0x0f)|((b?1:0)<<4));} +SCE_PFX_FORCE_INLINE void pfxSetContactId(PfxBroadphasePair &pair,PfxUInt32 i) {pair.set32(2,i);} + +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetObjectIdA(const PfxBroadphasePair &pair) {return pair.get16(0);} +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetObjectIdB(const PfxBroadphasePair &pair) {return pair.get16(1);} +SCE_PFX_FORCE_INLINE PfxUInt8 pfxGetMotionMaskA(const PfxBroadphasePair &pair) {return pair.get8(4);} +SCE_PFX_FORCE_INLINE PfxUInt8 pfxGetMotionMaskB(const PfxBroadphasePair &pair) {return pair.get8(5);} +SCE_PFX_FORCE_INLINE PfxUInt8 pfxGetBroadphaseFlag(const PfxBroadphasePair &pair) {return pair.get8(6)&0x0f;} +SCE_PFX_FORCE_INLINE PfxBool pfxGetActive(const PfxBroadphasePair &pair) {return (pair.get8(6)>>4)!=0;} +SCE_PFX_FORCE_INLINE PfxUInt32 pfxGetContactId(const PfxBroadphasePair &pair) {return pair.get32(2);} + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_BROADPHASE_PAIR_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/broadphase/pfx_broadphase_proxy.h b/Extras/PhysicsEffects/include/physics_effects/base_level/broadphase/pfx_broadphase_proxy.h new file mode 100644 index 0000000..a0b0629 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/broadphase/pfx_broadphase_proxy.h @@ -0,0 +1,42 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_BROADPHASE_PROXY_H +#define _SCE_PFX_BROADPHASE_PROXY_H + +namespace sce { +namespace PhysicsEffects { + +typedef PfxSortData32 PfxBroadphaseProxy; + +//J AABBパラメータはPfxAabbと共通 +//E PfxBroadphaseProxy shares AABB parameters with PfxAabb32 + +SCE_PFX_FORCE_INLINE void pfxSetObjectId(PfxBroadphaseProxy &proxy,PfxUInt16 i) {proxy.set16(6,i);} +SCE_PFX_FORCE_INLINE void pfxSetMotionMask(PfxBroadphaseProxy &proxy,PfxUInt8 i) {proxy.set8(14,i);} +SCE_PFX_FORCE_INLINE void pfxSetProxyFlag(PfxBroadphaseProxy &proxy,PfxUInt8 i) {proxy.set8(15,i);} +SCE_PFX_FORCE_INLINE void pfxSetSelf(PfxBroadphaseProxy &proxy,PfxUInt32 i) {proxy.set32(5,i);} +SCE_PFX_FORCE_INLINE void pfxSetTarget(PfxBroadphaseProxy &proxy,PfxUInt32 i) {proxy.set32(6,i);} + +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetObjectId(const PfxBroadphaseProxy &proxy) {return proxy.get16(6);} +SCE_PFX_FORCE_INLINE PfxUInt8 pfxGetMotionMask(const PfxBroadphaseProxy &proxy) {return proxy.get8(14);} +SCE_PFX_FORCE_INLINE PfxUInt8 pfxGetProxyFlag(const PfxBroadphaseProxy &proxy) {return proxy.get8(15);} +SCE_PFX_FORCE_INLINE PfxUInt32 pfxGetSelf(const PfxBroadphaseProxy &proxy) {return proxy.get32(5);} +SCE_PFX_FORCE_INLINE PfxUInt32 pfxGetTarget(const PfxBroadphaseProxy &proxy) {return proxy.get32(6);} + +} //namespace PhysicsEffects +} //namespace sce +#endif // _SCE_PFX_BROADPHASE_PROXY_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/broadphase/pfx_update_broadphase_proxy.h b/Extras/PhysicsEffects/include/physics_effects/base_level/broadphase/pfx_update_broadphase_proxy.h new file mode 100644 index 0000000..941d595 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/broadphase/pfx_update_broadphase_proxy.h @@ -0,0 +1,80 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_UPDATE_BROADPHASE_PROXY_H +#define _SCE_PFX_UPDATE_BROADPHASE_PROXY_H + +#include "pfx_broadphase_pair.h" +#include "pfx_broadphase_proxy.h" +#include "../rigidbody/pfx_rigid_state.h" +#include "../collision/pfx_collidable.h" + +namespace sce { +namespace PhysicsEffects { + +/////////////////////////////////////////////////////////////////////////////// +// Update Broadphase Proxy + +//E For single axis +//J 単一軸に対して作成 +PfxInt32 pfxUpdateBroadphaseProxy( + PfxBroadphaseProxy &proxy, + const PfxRigidState &state, + const PfxCollidable &coll, + const PfxVector3 &worldCenter, + const PfxVector3 &worldExtent, + PfxUInt32 axis); + +PfxInt32 pfxUpdateBroadphaseProxy( + PfxBroadphaseProxy &proxy, + const PfxRigidState &state, + const PfxVector3 &objectCenter, + const PfxVector3 &objectHalf, + const PfxVector3 &worldCenter, + const PfxVector3 &worldExtent, + PfxUInt32 axis); + +//E For all axes +//J 全軸に対して作成 +PfxInt32 pfxUpdateBroadphaseProxy( + PfxBroadphaseProxy &proxyX, + PfxBroadphaseProxy &proxyY, + PfxBroadphaseProxy &proxyZ, + PfxBroadphaseProxy &proxyXb, + PfxBroadphaseProxy &proxyYb, + PfxBroadphaseProxy &proxyZb, + const PfxRigidState &state, + const PfxCollidable &coll, + const PfxVector3 &worldCenter, + const PfxVector3 &worldExtent); + +PfxInt32 pfxUpdateBroadphaseProxy( + PfxBroadphaseProxy &proxyX, + PfxBroadphaseProxy &proxyY, + PfxBroadphaseProxy &proxyZ, + PfxBroadphaseProxy &proxyXb, + PfxBroadphaseProxy &proxyYb, + PfxBroadphaseProxy &proxyZb, + const PfxRigidState &state, + const PfxVector3 &objectCenter, + const PfxVector3 &objectHalf, + const PfxVector3 &worldCenter, + const PfxVector3 &worldExtent); + +} // namespace PhysicsEffects +} // namespace sce + +#endif // _SCE_PFX_UPDATE_BROADPHASE_PROXY_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_aabb.h b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_aabb.h new file mode 100644 index 0000000..dc238eb --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_aabb.h @@ -0,0 +1,124 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_AABB_H +#define _SCE_PFX_AABB_H + +#include "../sort/pfx_sort_data.h" + +namespace sce { +namespace PhysicsEffects { + +typedef PfxSortData16 PfxAabb16; +typedef PfxSortData32 PfxAabb32; + +SCE_PFX_FORCE_INLINE void pfxSetXMin(PfxAabb16& aabb,PfxUInt16 i) {aabb.set16(0,i);} +SCE_PFX_FORCE_INLINE void pfxSetXMax(PfxAabb16& aabb,PfxUInt16 i) {aabb.set16(1,i);} +SCE_PFX_FORCE_INLINE void pfxSetYMin(PfxAabb16& aabb,PfxUInt16 i) {aabb.set16(2,i);} +SCE_PFX_FORCE_INLINE void pfxSetYMax(PfxAabb16& aabb,PfxUInt16 i) {aabb.set16(3,i);} +SCE_PFX_FORCE_INLINE void pfxSetZMin(PfxAabb16& aabb,PfxUInt16 i) {aabb.set16(4,i);} +SCE_PFX_FORCE_INLINE void pfxSetZMax(PfxAabb16& aabb,PfxUInt16 i) {aabb.set16(5,i);} +SCE_PFX_FORCE_INLINE void pfxSetXYZMin(PfxAabb16 &aabb,PfxUInt16 i,int axis) {aabb.set16(axis<<1,i);} +SCE_PFX_FORCE_INLINE void pfxSetXYZMax(PfxAabb16 &aabb,PfxUInt16 i,int axis) {aabb.set16((axis<<1)+1,i);} + +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetXMin(const PfxAabb16& aabb) {return aabb.get16(0);} +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetXMax(const PfxAabb16& aabb) {return aabb.get16(1);} +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetYMin(const PfxAabb16& aabb) {return aabb.get16(2);} +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetYMax(const PfxAabb16& aabb) {return aabb.get16(3);} +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetZMin(const PfxAabb16& aabb) {return aabb.get16(4);} +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetZMax(const PfxAabb16& aabb) {return aabb.get16(5);} +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetXYZMin(const PfxAabb16 &aabb,int axis) {return aabb.get16(axis<<1);} +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetXYZMax(const PfxAabb16 &aabb,int axis) {return aabb.get16((axis<<1)+1);} + +SCE_PFX_FORCE_INLINE void pfxSetXMin(PfxAabb32& aabb,PfxUInt16 i) {aabb.set16(0,i);} +SCE_PFX_FORCE_INLINE void pfxSetXMax(PfxAabb32& aabb,PfxUInt16 i) {aabb.set16(1,i);} +SCE_PFX_FORCE_INLINE void pfxSetYMin(PfxAabb32& aabb,PfxUInt16 i) {aabb.set16(2,i);} +SCE_PFX_FORCE_INLINE void pfxSetYMax(PfxAabb32& aabb,PfxUInt16 i) {aabb.set16(3,i);} +SCE_PFX_FORCE_INLINE void pfxSetZMin(PfxAabb32& aabb,PfxUInt16 i) {aabb.set16(4,i);} +SCE_PFX_FORCE_INLINE void pfxSetZMax(PfxAabb32& aabb,PfxUInt16 i) {aabb.set16(5,i);} +SCE_PFX_FORCE_INLINE void pfxSetXYZMin(PfxAabb32 &aabb,PfxUInt16 i,int axis) {aabb.set16(axis<<1,i);} +SCE_PFX_FORCE_INLINE void pfxSetXYZMax(PfxAabb32 &aabb,PfxUInt16 i,int axis) {aabb.set16((axis<<1)+1,i);} + +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetXMin(const PfxAabb32& aabb) {return aabb.get16(0);} +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetXMax(const PfxAabb32& aabb) {return aabb.get16(1);} +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetYMin(const PfxAabb32& aabb) {return aabb.get16(2);} +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetYMax(const PfxAabb32& aabb) {return aabb.get16(3);} +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetZMin(const PfxAabb32& aabb) {return aabb.get16(4);} +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetZMax(const PfxAabb32& aabb) {return aabb.get16(5);} +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetXYZMin(const PfxAabb32 &aabb,int axis) {return aabb.get16(axis<<1);} +SCE_PFX_FORCE_INLINE PfxUInt16 pfxGetXYZMax(const PfxAabb32 &aabb,int axis) {return aabb.get16((axis<<1)+1);} + + +#define SCE_PFX_TEST_AABB(aabbA,aabbB) \ +if(pfxGetXMax(aabbA) < pfxGetXMin(aabbB) || pfxGetXMin(aabbA) > pfxGetXMax(aabbB)) return false;\ +if(pfxGetYMax(aabbA) < pfxGetYMin(aabbB) || pfxGetYMin(aabbA) > pfxGetYMax(aabbB)) return false;\ +if(pfxGetZMax(aabbA) < pfxGetZMin(aabbB) || pfxGetZMin(aabbA) > pfxGetZMax(aabbB)) return false;\ +return true; + +SCE_PFX_FORCE_INLINE +bool pfxTestAabb(const PfxAabb16 &aabbA,const PfxAabb16 &aabbB) +{ +SCE_PFX_TEST_AABB(aabbA,aabbB) +} + +SCE_PFX_FORCE_INLINE +bool pfxTestAabb(const PfxAabb32 &aabbA,const PfxAabb32 &aabbB) +{ +SCE_PFX_TEST_AABB(aabbA,aabbB) +} + +SCE_PFX_FORCE_INLINE +bool pfxTestAabb(const PfxAabb32 &aabbA,const PfxAabb16 &aabbB) +{ +SCE_PFX_TEST_AABB(aabbA,aabbB) +} + +SCE_PFX_FORCE_INLINE +bool pfxTestAabb(const PfxAabb16 &aabbA,const PfxAabb32 &aabbB) +{ +SCE_PFX_TEST_AABB(aabbA,aabbB) +} + + +SCE_PFX_FORCE_INLINE +PfxAabb16 pfxMergeAabb(const PfxAabb16 &aabbA,const PfxAabb16 &aabbB) +{ + PfxAabb16 aabb = aabbA; + pfxSetXMin(aabb,SCE_PFX_MIN(pfxGetXMin(aabbA),pfxGetXMin(aabbB))); + pfxSetXMax(aabb,SCE_PFX_MAX(pfxGetXMax(aabbA),pfxGetXMax(aabbB))); + pfxSetYMin(aabb,SCE_PFX_MIN(pfxGetYMin(aabbA),pfxGetYMin(aabbB))); + pfxSetYMax(aabb,SCE_PFX_MAX(pfxGetYMax(aabbA),pfxGetYMax(aabbB))); + pfxSetZMin(aabb,SCE_PFX_MIN(pfxGetZMin(aabbA),pfxGetZMin(aabbB))); + pfxSetZMax(aabb,SCE_PFX_MAX(pfxGetZMax(aabbA),pfxGetZMax(aabbB))); + return aabb; +} + +SCE_PFX_FORCE_INLINE +PfxAabb32 pfxMergeAabb(const PfxAabb32 &aabbA,const PfxAabb32 &aabbB) +{ + PfxAabb32 aabb = aabbA; + pfxSetXMin(aabb,SCE_PFX_MIN(pfxGetXMin(aabbA),pfxGetXMin(aabbB))); + pfxSetXMax(aabb,SCE_PFX_MAX(pfxGetXMax(aabbA),pfxGetXMax(aabbB))); + pfxSetYMin(aabb,SCE_PFX_MIN(pfxGetYMin(aabbA),pfxGetYMin(aabbB))); + pfxSetYMax(aabb,SCE_PFX_MAX(pfxGetYMax(aabbA),pfxGetYMax(aabbB))); + pfxSetZMin(aabb,SCE_PFX_MIN(pfxGetZMin(aabbA),pfxGetZMin(aabbB))); + pfxSetZMax(aabb,SCE_PFX_MAX(pfxGetZMax(aabbA),pfxGetZMax(aabbB))); + return aabb; +} +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_AABB_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_box.h b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_box.h new file mode 100644 index 0000000..4de7976 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_box.h @@ -0,0 +1,61 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_BOX_H +#define _SCE_PFX_BOX_H + +#include "../base/pfx_common.h" + +namespace sce{ +namespace PhysicsEffects{ +struct PfxBox { + PfxVector3 m_half; + + inline PfxBox() {} + inline PfxBox(const PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG half); + inline PfxBox(PfxFloat hx, PfxFloat hy, PfxFloat hz); + + inline void set(const PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG half); + inline void set(PfxFloat hx, PfxFloat hy, PfxFloat hz); +}; + +inline +PfxBox::PfxBox(const PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG half) +{ + set(half); +} + +inline +PfxBox::PfxBox(PfxFloat hx, PfxFloat hy, PfxFloat hz) +{ + set(hx, hy, hz); +} + +inline +void PfxBox::set(const PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG half) +{ + m_half = half; +} + +inline +void PfxBox::set(PfxFloat hx, PfxFloat hy, PfxFloat hz) +{ + m_half = PfxVector3(hx, hy, hz); +} +} // namespace PhysicsEffects +} // namespace sce + +#endif // _SCE_PFX_BOX_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_capsule.h b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_capsule.h new file mode 100644 index 0000000..a1c1af5 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_capsule.h @@ -0,0 +1,53 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CAPSULE_H +#define _SCE_PFX_CAPSULE_H + +#include "../base/pfx_common.h" + +namespace sce { +namespace PhysicsEffects { + +struct PfxCapsule +{ + PfxFloat m_halfLen; + PfxFloat m_radius; + + PfxCapsule() {} + PfxCapsule(PfxFloat halfLength, PfxFloat radius); + + void set(PfxFloat halfLength, PfxFloat radius); +}; + +inline +PfxCapsule::PfxCapsule(PfxFloat halfLength, PfxFloat radius) +{ + m_halfLen = halfLength; + m_radius = radius; +} + +inline +void PfxCapsule::set(PfxFloat halfLength, PfxFloat radius) +{ + m_halfLen = halfLength; + m_radius = radius; +} + +} // namespace PhysicsEffects +} // namespace sce + +#endif // _SCE_PFX_CAPSULE_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_collidable.h b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_collidable.h new file mode 100644 index 0000000..7f65eeb --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_collidable.h @@ -0,0 +1,74 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_COLLIDABLE_H +#define _SCE_PFX_COLLIDABLE_H + +#include "pfx_shape.h" + +namespace sce { +namespace PhysicsEffects { + +#define SCE_PFX_NUMPRIMS 64 + +/////////////////////////////////////////////////////////////////////////////// +// Collidable Object + +class SCE_PFX_ALIGNED(128) PfxCollidable +{ +friend class PfxShapeIterator; + +private: + PfxShape *m_shapeBase; + PfxUInt16 m_shapeIds[SCE_PFX_NUMPRIMS]; + PfxUInt8 m_numShapes; + PfxUInt8 m_maxShapes; + SCE_PFX_PADDING(1,2) + PfxFloat m_center[3]; // AABB center (Local) + PfxFloat m_half[3]; // AABB half (Local) + PfxShape m_defShape; + SCE_PFX_PADDING(2,32) + + inline PfxShape &getNewShape(); + +public: + inline void reset(); + inline void reset(PfxShape *base,PfxUInt16 *ids,int n=1); + + void finish(); + + void addShape(const PfxShape &shape); + + inline PfxUInt32 getNumShapes() const; + const PfxShape& getDefShape() const {return m_defShape;} + PfxShape& getDefShape() {return m_defShape;} + + inline PfxUInt16 getShapeId(int i) const; + + inline const PfxShape& getShape(int i) const; + inline PfxShape& getShape(int i); + + inline PfxVector3 getHalf() const; + inline PfxVector3 getCenter() const; +}; + +#include "pfx_collidable_implementation.h" + +} // namespace PhysicsEffects +} // namespace sce + +#endif // _SCE_PFX_COLLIDABLE_H + diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_collidable_implementation.h b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_collidable_implementation.h new file mode 100644 index 0000000..0e434f6 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_collidable_implementation.h @@ -0,0 +1,114 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_COLLIDABLE_IMPLEMENTATION_H +#define _SCE_PFX_COLLIDABLE_IMPLEMENTATION_H + +inline +void PfxCollidable::reset() +{ + m_shapeBase = NULL; + m_numShapes = 0; + m_maxShapes = 1; + m_center[0] = 0.0f; + m_center[1] = 0.0f; + m_center[2] = 0.0f; + m_half[0] = 0.0f; + m_half[1] = 0.0f; + m_half[2] = 0.0f; +} + +inline +void PfxCollidable::reset(PfxShape *base,PfxUInt16 *ids,int n) +{ + m_shapeBase = base; + m_numShapes = 0; + m_maxShapes = n; + for(int i=0;i0); + return m_shapeIds[i-1]; +} + +inline +const PfxShape& PfxCollidable::getShape(int i) const +{ + SCE_PFX_ASSERT(i0) { + return m_shapeBase[m_shapeIds[i-1]]; + } + else { + return m_defShape; + } +} + +inline +PfxShape& PfxCollidable::getShape(int i) +{ + SCE_PFX_ASSERT(i0) { + return m_shapeBase[m_shapeIds[i-1]]; + } + else { + return m_defShape; + } +} + +inline +PfxShape &PfxCollidable::getNewShape() +{ + SCE_PFX_ASSERT(m_numShapes<=m_maxShapes); + if(m_numShapes == 0) { + m_numShapes++; + return m_defShape; + } + else { + m_numShapes++; + return m_shapeBase[m_shapeIds[m_numShapes-2]]; + } +} + +inline +PfxVector3 PfxCollidable::getHalf() const +{ + return pfxReadVector3(m_half); +} + +inline +PfxVector3 PfxCollidable::getCenter() const +{ + return pfxReadVector3(m_center); +} + +#endif // _SCE_PFX_COLLIDABLE_IMPLEMENTATION_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_contact_manifold.h b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_contact_manifold.h new file mode 100644 index 0000000..f257974 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_contact_manifold.h @@ -0,0 +1,135 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONTACT_MANIFOLD_H +#define _SCE_PFX_CONTACT_MANIFOLD_H + +#include "../base/pfx_common.h" +#include "../base/pfx_vec_utils.h" +#include "pfx_sub_data.h" +#include "../solver/pfx_constraint_row.h" + +namespace sce { +namespace PhysicsEffects { + +#define SCE_PFX_NUMCONTACTS_PER_BODIES 4 + +/////////////////////////////////////////////////////////////////////////////// +// Contact Point + +struct PfxContactPoint +{ + PfxUInt8 m_duration; + PfxUInt8 m_shapeIdA; + PfxUInt8 m_shapeIdB; + SCE_PFX_PADDING(1,1) + PfxSubData m_subData; + PfxFloat m_distance; + PfxFloat m_localPointA[3]; + PfxFloat m_localPointB[3]; + SCE_PFX_PADDING(2,8) + PfxConstraintRow m_constraintRow[3]; + + void reset() + { + m_duration = 0; + m_shapeIdA = m_shapeIdB = 0; + m_subData = PfxSubData(); + m_distance = SCE_PFX_FLT_MAX; + m_constraintRow[0].m_accumImpulse = 0.0f; + m_constraintRow[1].m_accumImpulse = 0.0f; + m_constraintRow[2].m_accumImpulse = 0.0f; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// Contact Manifold + +//J 同一ペアの衝突が続く限り保持されるコンタクト情報 +//E PfxContactManifold keeps contact information until two rigid bodies are separated. + +class SCE_PFX_ALIGNED(128) PfxContactManifold +{ +private: + PfxUInt16 m_rigidBodyIdA,m_rigidBodyIdB; + PfxUInt16 m_duration; + PfxUInt16 m_numContacts; + PfxFloat m_compositeFriction; + PfxUInt32 m_internalFlag; + PfxContactPoint m_contactPoints[SCE_PFX_NUMCONTACTS_PER_BODIES]; + void *m_userData; + PfxUInt32 m_userParam[4]; + SCE_PFX_PADDING(1,28) + + int findNearestContactPoint(const PfxPoint3 &newPoint,const PfxVector3 &newNormal); + int sort4ContactPoints(const PfxPoint3 &newPoint,PfxFloat newDistance); + +public: + // Internal method + PfxFloat getCompositeFriction() const {return m_compositeFriction;} + void setCompositeFriction(PfxFloat f) {m_compositeFriction = f;} + + PfxUInt32 getInternalFlag() const {return m_internalFlag;} + void setInternalFlag(PfxUInt32 f) {m_internalFlag = f;} + +public: + void reset(PfxUInt16 rigidBodyIdA,PfxUInt16 rigidBodyIdB) + { + m_userData = 0; + m_userParam[0] = m_userParam[1] = m_userParam[2] = m_userParam[3] = 0; + m_numContacts = 0; + m_duration = 0; + m_rigidBodyIdA = rigidBodyIdA; + m_rigidBodyIdB = rigidBodyIdB; + } + + void addContactPoint( + PfxFloat newDistance, + const PfxVector3 &newNormal, // world coords + const PfxPoint3 &newPointA, // local coords to the objectA + const PfxPoint3 &newPointB, // local coords to the objectB + PfxSubData subData); + + void addContactPoint(const PfxContactPoint &cp); + + void removeContactPoint(int i) + { + SCE_PFX_ASSERT(i>=0&&i pfxGetXMax(m_aabbList[islandId])) return false; + if(aabbMaxL.getY() < pfxGetYMin(m_aabbList[islandId]) || aabbMinL.getY() > pfxGetYMax(m_aabbList[islandId])) return false; + if(aabbMaxL.getZ() < pfxGetZMin(m_aabbList[islandId]) || aabbMinL.getZ() > pfxGetZMax(m_aabbList[islandId])) return false; + + return true; +} + +inline +PfxVecInt3 PfxLargeTriMesh::getLocalPosition(const PfxVector3 &worldPosition) const +{ + const PfxVector3 sz(65535.0f); + PfxVector3 tmp = divPerElem(worldPosition+m_half,2.0f*m_half); + tmp = mulPerElem(sz,minPerElem(maxPerElem(tmp,PfxVector3(0.0f)),PfxVector3(1.0f))); // clamp 0.0 - 1.0 + return PfxVecInt3(tmp); +} + +inline +void PfxLargeTriMesh::getLocalPosition( + const PfxVector3 &worldMinPosition,const PfxVector3 &worldMaxPosition, + PfxVecInt3 &localMinPosition,PfxVecInt3 &localMaxPosition) const +{ + const PfxVector3 sz(65535.0f); + PfxVector3 qmin = divPerElem(worldMinPosition+m_half,2.0f*m_half); + qmin = mulPerElem(sz,minPerElem(maxPerElem(qmin,PfxVector3(0.0f)),PfxVector3(1.0f))); // clamp 0.0 - 1.0 + + PfxVector3 qmax = divPerElem(worldMaxPosition+m_half,2.0f*m_half); + qmax = mulPerElem(sz,minPerElem(maxPerElem(qmax,PfxVector3(0.0f)),PfxVector3(1.0f))); // clamp 0.0 - 1.0 + +localMinPosition = PfxVecInt3(floorf(qmin[0]),floorf(qmin[1]),floorf(qmin[2])); +localMaxPosition = PfxVecInt3(ceilf(qmax[0]),ceilf(qmax[1]),ceilf(qmax[2])); +} + +inline +PfxVector3 PfxLargeTriMesh::getWorldPosition(const PfxVecInt3 &localPosition) const +{ + PfxVector3 sz(65535.0f),lp(localPosition); + PfxVector3 tmp = divPerElem(lp,sz); + return mulPerElem(tmp,2.0f*m_half) - m_half; +} + +} // namespace PhysicsEffects +} // namespace sce + +#endif // _SCE_PFX_LARGE_TRI_MESH_H \ No newline at end of file diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_ray.h b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_ray.h new file mode 100644 index 0000000..92fc3f2 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_ray.h @@ -0,0 +1,59 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_RAY_H +#define _SCE_PFX_RAY_H + +#include "../base/pfx_common.h" +#include "pfx_sub_data.h" + +namespace sce { +namespace PhysicsEffects { + +#define SCE_PFX_RAY_FACET_MODE_FRONT_ONLY 0 +#define SCE_PFX_RAY_FACET_MODE_BACK_ONLY 1 +#define SCE_PFX_RAY_FACET_MODE_FRONT_AND_BACK 2 + +struct SCE_PFX_ALIGNED(16) PfxRayInput +{ + PfxVector3 m_startPosition; + PfxVector3 m_direction; + PfxUInt32 m_contactFilterSelf; + PfxUInt32 m_contactFilterTarget; + PfxUInt8 m_facetMode; + SCE_PFX_PADDING(1,7) + + void reset() + { + m_contactFilterSelf = m_contactFilterTarget = 0xffffffff; + m_facetMode = SCE_PFX_RAY_FACET_MODE_FRONT_ONLY; + } +}; + +struct SCE_PFX_ALIGNED(16) PfxRayOutput +{ + PfxVector3 m_contactPoint; + PfxVector3 m_contactNormal; + PfxFloat m_variable; + PfxUInt16 m_objectId; + PfxUInt8 m_shapeId; + PfxBool m_contactFlag : 1; + PfxSubData m_subData; +}; +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_RAY_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_shape.h b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_shape.h new file mode 100644 index 0000000..b4f9c2a --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_shape.h @@ -0,0 +1,118 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_SHAPE_H +#define _SCE_PFX_SHAPE_H + +#include "../base/pfx_common.h" +#include "../base/pfx_vec_utils.h" +#include "pfx_box.h" +#include "pfx_sphere.h" +#include "pfx_capsule.h" +#include "pfx_cylinder.h" +#include "pfx_tri_mesh.h" +#include "pfx_large_tri_mesh.h" + +namespace sce { +namespace PhysicsEffects { + +enum ePfxShapeType +{ + kPfxShapeSphere = 0, + kPfxShapeBox, + kPfxShapeCapsule, + kPfxShapeCylinder, + kPfxShapeConvexMesh, + kPfxShapeLargeTriMesh, + kPfxShapeReserved0, + kPfxShapeReserved1, + kPfxShapeReserved2, + kPfxShapeUser0, + kPfxShapeUser1, + kPfxShapeUser2, + kPfxShapeCount // =12 +}; + +class SCE_PFX_ALIGNED(16) PfxShape +{ +friend class PfxCollidable; + +private: + union { + PfxFloat m_vecDataF[3]; + PfxUInt32 m_vecDataI[3]; + void *m_vecDataPtr[2]; + }; + PfxUInt8 m_type; + SCE_PFX_PADDING(1,3) + PfxFloat m_offsetPosition[3]; + PfxFloat m_offsetOrientation[4]; + PfxUInt32 m_contactFilterSelf; + PfxUInt32 m_contactFilterTarget; + SCE_PFX_PADDING(2,12) + +public: + inline void reset(); + + // Shape + inline void setBox(PfxBox SCE_VECTORMATH_AOS_VECTOR_ARG box); + inline void setCapsule(PfxCapsule capsule); + inline void setCylinder(PfxCylinder cylinder); + inline void setSphere(PfxSphere sphere); + inline void setConvexMesh(const PfxConvexMesh *convexMesh); + inline void setLargeTriMesh(const PfxLargeTriMesh *largeMesh); + + inline PfxUInt8 getType() const; + inline PfxBox getBox()const ; + inline PfxCapsule getCapsule() const; + inline PfxCylinder getCylinder() const; + inline PfxSphere getSphere() const; + inline const PfxConvexMesh* getConvexMesh() const; + inline const PfxLargeTriMesh* getLargeTriMesh() const; + + // Offset + inline void setOffsetTransform(const PfxTransform3 & xfrm); + inline void setOffsetOrientation(const PfxQuat SCE_VECTORMATH_AOS_VECTOR_ARG rot) {return pfxStoreQuat(rot,m_offsetOrientation);} + inline void setOffsetPosition(const PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG pos) {return pfxStoreVector3(pos,m_offsetPosition);} + + inline PfxTransform3 getOffsetTransform() const; + inline PfxVector3 getOffsetPosition() const {return pfxReadVector3(m_offsetPosition);} + inline PfxQuat getOffsetOrientation() const {return pfxReadQuat(m_offsetOrientation);} + + // Raw data access + inline void setDataFloat(int i,PfxFloat v) {m_vecDataF[i]=v;} + inline void setDataInteger(int i,PfxUInt32 v) {m_vecDataI[i]=v;} + + inline PfxFloat getDataFloat(int i) const {return m_vecDataF[i];} + inline PfxUInt32 getDataInteger(int i) const {return m_vecDataI[i];} + + // Contact Filter + PfxUInt32 getContactFilterSelf() const {return m_contactFilterSelf;} + void setContactFilterSelf(PfxUInt32 filter) {m_contactFilterSelf = filter;} + + PfxUInt32 getContactFilterTarget() const {return m_contactFilterTarget;} + void setContactFilterTarget(PfxUInt32 filter) {m_contactFilterTarget = filter;} + + // Bouding Volume + void getAabb(PfxVector3 &aabbMin,PfxVector3 &aabbMax) const; +}; + +#include "pfx_shape_implementation.h" + +} // namespace PhysicsEffects +} // namespace sce + +#endif // _SCE_PFX_SHAPE_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_shape_implementation.h b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_shape_implementation.h new file mode 100644 index 0000000..8996141 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_shape_implementation.h @@ -0,0 +1,145 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_SHAPE_IMPLEMENTATION_H +#define _SCE_PFX_SHAPE_IMPLEMENTATION_H + +inline +void PfxShape::reset() +{ + m_type = kPfxShapeSphere; + m_offsetPosition[0] = m_offsetPosition[1] = m_offsetPosition[2]= 0.0f; + m_offsetOrientation[0] = m_offsetOrientation[1] = m_offsetOrientation[2]= 0.0f; + m_offsetOrientation[3] = 1.0f; + m_contactFilterSelf = m_contactFilterTarget = 0xffffffff; +} + +inline +void PfxShape::setBox(PfxBox SCE_VECTORMATH_AOS_VECTOR_ARG box) +{ + m_vecDataF[0] = box.m_half[0]; + m_vecDataF[1] = box.m_half[1]; + m_vecDataF[2] = box.m_half[2]; + m_type = kPfxShapeBox; +} + +inline +void PfxShape::setCapsule(PfxCapsule capsule) +{ + m_vecDataF[0] = capsule.m_halfLen; + m_vecDataF[1] = capsule.m_radius; + m_vecDataF[2] = 0.0f; + m_type = kPfxShapeCapsule; +} + +inline +void PfxShape::setCylinder(PfxCylinder cylinder) +{ + m_vecDataF[0] = cylinder.m_halfLen; + m_vecDataF[1] = cylinder.m_radius; + m_vecDataF[2] = 0.0f; + m_type = kPfxShapeCylinder; +} + +inline +void PfxShape::setSphere(PfxSphere sphere) +{ + m_vecDataF[0] = sphere.m_radius; + m_vecDataF[1] = 0.0f; + m_vecDataF[2] = 0.0f; + m_type = kPfxShapeSphere; +} + +inline +void PfxShape::setConvexMesh(const PfxConvexMesh *convexMesh) +{ + m_vecDataPtr[0] = (void*)convexMesh; + m_vecDataPtr[1] = NULL; + m_type = kPfxShapeConvexMesh; +} + +inline +void PfxShape::setLargeTriMesh(const PfxLargeTriMesh *largeMesh) +{ + m_vecDataPtr[0] = (void*)largeMesh; + m_vecDataPtr[1] = NULL; + m_type = kPfxShapeLargeTriMesh; +} + +inline +void PfxShape::setOffsetTransform(const PfxTransform3 & xfrm) +{ + setOffsetOrientation(PfxQuat(xfrm.getUpper3x3())); + setOffsetPosition(xfrm.getTranslation()); +} + +inline +PfxUInt8 PfxShape::getType() const +{ + return m_type; +} + +inline +PfxBox PfxShape::getBox() const +{ + SCE_PFX_ALWAYS_ASSERT(m_type==kPfxShapeBox); + return PfxBox(m_vecDataF[0],m_vecDataF[1],m_vecDataF[2]); +} + +inline +PfxCapsule PfxShape::getCapsule() const +{ + SCE_PFX_ALWAYS_ASSERT(m_type==kPfxShapeCapsule); + return PfxCapsule(m_vecDataF[0], m_vecDataF[1]); +} + +inline +PfxCylinder PfxShape::getCylinder() const +{ + SCE_PFX_ALWAYS_ASSERT(m_type==kPfxShapeCylinder); + return PfxCylinder(m_vecDataF[0], m_vecDataF[1]); +} + +inline +PfxSphere PfxShape::getSphere() const +{ + SCE_PFX_ALWAYS_ASSERT(m_type==kPfxShapeSphere); + return PfxSphere(m_vecDataF[0]); +} + +inline +const PfxConvexMesh *PfxShape::getConvexMesh() const +{ + SCE_PFX_ALWAYS_ASSERT(m_type==kPfxShapeConvexMesh); + SCE_PFX_ALWAYS_ASSERT(m_vecDataPtr[0]!=NULL); + return (PfxConvexMesh*)m_vecDataPtr[0]; +} + +inline +const PfxLargeTriMesh *PfxShape::getLargeTriMesh() const +{ + SCE_PFX_ALWAYS_ASSERT(m_type==kPfxShapeLargeTriMesh); + SCE_PFX_ALWAYS_ASSERT(m_vecDataPtr[0]!=NULL); + return (PfxLargeTriMesh*)m_vecDataPtr[0]; +} + +inline +PfxTransform3 PfxShape::getOffsetTransform() const +{ + return PfxTransform3(getOffsetOrientation(),getOffsetPosition()); +} + +#endif // _SCE_PFX_SHAPE_IMPLEMENTATION_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_shape_iterator.h b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_shape_iterator.h new file mode 100644 index 0000000..7a0a300 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_shape_iterator.h @@ -0,0 +1,58 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_SHAPE_ITERATOR_H +#define _SCE_PFX_SHAPE_ITERATOR_H + +#include "pfx_collidable.h" + + +namespace sce { +namespace PhysicsEffects { + +class PfxShapeIterator +{ +private: +PfxUInt32 m_numShapes; +PfxShape *m_shapeBase; +const PfxUInt16 *m_shapeIds; +const PfxShape *m_curShape; +PfxUInt32 m_index; + +public: +PfxShapeIterator(const PfxCollidable &coll) : m_shapeIds(coll.m_shapeIds) +{ + m_numShapes = coll.m_numShapes; + m_shapeBase = coll.m_shapeBase; + m_index = 0; + m_curShape = &coll.m_defShape; +} + +~PfxShapeIterator() {} + +inline PfxShapeIterator& operator++() +{ + m_curShape = &m_shapeBase[m_shapeIds[m_index++]]; + return *this; +} + +const PfxShape& operator*() const {return *m_curShape;} +}; + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_SHAPE_ITERATOR_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_sphere.h b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_sphere.h new file mode 100644 index 0000000..477d7f9 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_sphere.h @@ -0,0 +1,49 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_SPHERE_H +#define _SCE_PFX_SPHERE_H + +#include "../base/pfx_common.h" + +namespace sce { +namespace PhysicsEffects { + +struct PfxSphere { + PfxFloat m_radius; + + PfxSphere() {} + PfxSphere( PfxFloat radius ); + + void set( PfxFloat radius ); +}; + +inline +PfxSphere::PfxSphere( PfxFloat radius ) +{ + m_radius = radius; +} + +inline +void PfxSphere::set( PfxFloat radius ) +{ + m_radius = radius; +} + +} // namespace PhysicsEffects +} // namespace sce + +#endif // _SCE_PFX_SPHERE_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_sub_data.h b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_sub_data.h new file mode 100644 index 0000000..82f5c0c --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_sub_data.h @@ -0,0 +1,63 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_SUB_DATA_H +#define _SCE_PFX_SUB_DATA_H + +namespace sce { +namespace PhysicsEffects { + +struct PfxSubData { + enum { + NONE = 0, + MESH_INFO + }; + + union { + struct { + PfxUInt8 m_type; + SCE_PFX_PADDING(1,1) + + struct { + PfxUInt8 islandId; + PfxUInt8 facetId; + PfxUInt16 s; + PfxUInt16 t; + + } m_facetLocal; + }; + PfxUInt32 param[2]; + }; + + PfxSubData() + { + param[0] = param[1] = 0; + } + + void setIslandId(PfxUInt8 i) {m_facetLocal.islandId = i;} + void setFacetId(PfxUInt8 i) {m_facetLocal.facetId = i;} + void setFacetLocalS(PfxFloat s) {m_facetLocal.s = (PfxUInt16)(s * 65535.0f);} + void setFacetLocalT(PfxFloat t) {m_facetLocal.t = (PfxUInt16)(t * 65535.0f);} + + PfxUInt8 getIslandId() {return m_facetLocal.islandId;} + PfxUInt8 getFacetId() {return m_facetLocal.facetId;} + PfxFloat getFacetLocalS() {return m_facetLocal.s / 65535.0f;} + PfxFloat getFacetLocalT() {return m_facetLocal.t / 65535.0f;} +}; + +} //namespace PhysicsEffects +} //namespace sce +#endif // _SCE_PFX_SUB_DATA_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_tri_mesh.h b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_tri_mesh.h new file mode 100644 index 0000000..2370afe --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/collision/pfx_tri_mesh.h @@ -0,0 +1,154 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_TRI_MESH_H +#define _SCE_PFX_TRI_MESH_H + +#include "../base/pfx_common.h" +#include "../base/pfx_vec_utils.h" +#include "pfx_aabb.h" + +namespace sce { +namespace PhysicsEffects { + +//J メッシュのリソース制限 +//E Define some limitations of a triangle mesh +#define SCE_PFX_NUMMESHFACETS 64 +#define SCE_PFX_NUMMESHEDGES 192 +#define SCE_PFX_NUMMESHVERTICES 128 + +//J エッジの角 +//E Edge types +#define SCE_PFX_EDGE_FLAT 0 +#define SCE_PFX_EDGE_CONVEX 1 +#define SCE_PFX_EDGE_CONCAVE 2 + +/////////////////////////////////////////////////////////////////////////////// +// Edge +struct PfxEdge +{ + PfxUInt8 m_vertId[2]; + PfxUInt8 m_angleType; + PfxUInt8 m_tilt; +}; + +inline +bool operator ==(const PfxEdge &e1,const PfxEdge &e2) +{ + return (e1.m_vertId[0] == e2.m_vertId[0] && e1.m_vertId[1] == e2.m_vertId[1]) || + (e1.m_vertId[1] == e2.m_vertId[0] && e1.m_vertId[0] == e2.m_vertId[1]); +} + +/////////////////////////////////////////////////////////////////////////////// +// Facet + +struct PfxFacet +{ + PfxFloat m_normal[3]; + PfxFloat m_thickness; + PfxUInt8 m_group; + PfxUInt8 m_vertIds[3]; + PfxUInt8 m_edgeIds[3]; + PfxUInt8 m_userData; + PfxFloat m_half[3]; + PfxFloat m_center[3]; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Mesh + +struct SCE_PFX_ALIGNED(16) PfxTriMesh +{ + PfxUInt8 m_numVerts; + PfxUInt8 m_numEdges; + PfxUInt8 m_numFacets; + PfxUInt8 m_reserved; + PfxFacet m_facets[SCE_PFX_NUMMESHFACETS]; + PfxEdge m_edges[SCE_PFX_NUMMESHEDGES]; + SCE_PFX_PADDING(1,12) + PfxVector3 m_verts[SCE_PFX_NUMMESHVERTICES]; + PfxVector3 m_half; + + PfxTriMesh() + { + m_numVerts = m_numEdges = m_numFacets = 0; + } + + inline void updateAABB(); +}; + +inline +void PfxTriMesh::updateAABB() +{ + PfxVector3 halfMax(0); + + for(PfxUInt8 i=0;i0.0f?1.0f/mass:0.0f;} + + const PfxMatrix3& getInertia() const {return m_inertia;} + void setInertia(const PfxMatrix3 SCE_VECTORMATH_AOS_MATRIX_ARG inertia) {m_inertia = inertia;m_inertiaInv = inverse(inertia);} + + PfxFloat getRestitution() const {return m_restitution;} + void setRestitution(PfxFloat restitution) {m_restitution = restitution;} + + PfxFloat getFriction() const {return m_friction;} + void setFriction(PfxFloat friction) {m_friction = friction;} +}; + +inline +void PfxRigidBody::reset() +{ + m_mass = 0.0f; + m_restitution = 0.2f; + m_friction = 0.6f; +} + +} // namespace PhysicsEffects +} // namespace sce + +#endif // _SCE_PFX_RIGID_BODY_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/rigidbody/pfx_rigid_state.h b/Extras/PhysicsEffects/include/physics_effects/base_level/rigidbody/pfx_rigid_state.h new file mode 100644 index 0000000..356b67e --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/rigidbody/pfx_rigid_state.h @@ -0,0 +1,196 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_RIGID_STATE_H +#define _SCE_PFX_RIGID_STATE_H + +#include "../base/pfx_common.h" +#include "../base/pfx_vec_utils.h" + +namespace sce { +namespace PhysicsEffects { + +// Motion Type +enum ePfxMotionType { + kPfxMotionTypeFixed = 0, + kPfxMotionTypeActive, + kPfxMotionTypeKeyframe, + kPfxMotionTypeOneWay, + kPfxMotionTypeTrigger, + kPfxMotionTypeCount +}; + +#define SCE_PFX_MOTION_MASK_DYNAMIC(motion) ((1<<(motion))&0x0a) // Active,OneWay +#define SCE_PFX_MOTION_MASK_STATIC(motion) ((1<<(motion))&0x95) // Fixed,Keyframe +#define SCE_PFX_MOTION_MASK_CAN_SLEEP(motion) ((1<<(motion))&0x0e) // Can sleep + +#define SCE_PFX_MOTION_MASK_SLEEPING 0x80 // Is sleeping +#define SCE_PFX_MOTION_MASK_TYPE 0x7f // Motion Type + +class SCE_PFX_ALIGNED(128) PfxRigidState +{ +private: + union { + struct { + PfxUInt8 m_useSleep : 1; + PfxUInt8 m_sleeping : 1; + PfxUInt8 m_reserved1 : 1; + PfxUInt8 m_reserved2 : 1; + PfxUInt8 m_reserved3 : 1; + PfxUInt8 m_reserved4 : 1; + PfxUInt8 m_reserved5 : 1; + PfxUInt8 m_reserved6 : 1; + }; + PfxUInt8 m_flags; + }; + PfxUInt8 m_motionType; + PfxUInt16 m_sleepCount; + PfxUInt16 m_rigidBodyId; + + SCE_PFX_PADDING(1,2) + + PfxUInt32 m_contactFilterSelf; + PfxUInt32 m_contactFilterTarget; + + PfxFloat m_linearDamping; + PfxFloat m_angularDamping; + + PfxFloat m_maxLinearVelocity; + PfxFloat m_maxAngularVelocity; + + PfxVector3 m_position; + PfxQuat m_orientation; + PfxVector3 m_linearVelocity; + PfxVector3 m_angularVelocity; + + void *m_userData; + PfxUInt32 m_userParam[4]; + + SCE_PFX_PADDING(2,12) + +public: + inline void reset(); + + PfxUInt16 getRigidBodyId() const {return m_rigidBodyId;} + void setRigidBodyId(PfxUInt16 i) {m_rigidBodyId = i;} + + PfxUInt32 getContactFilterSelf() const {return m_contactFilterSelf;} + void setContactFilterSelf(PfxUInt32 filter) {m_contactFilterSelf = filter;} + + PfxUInt32 getContactFilterTarget() const {return m_contactFilterTarget;} + void setContactFilterTarget(PfxUInt32 filter) {m_contactFilterTarget = filter;} + + ePfxMotionType getMotionType() const {return (ePfxMotionType)m_motionType;} + void setMotionType(ePfxMotionType t) {SCE_PFX_ALWAYS_ASSERT(t 0.0f); + + setLinearVelocity((pos - getPosition()) / timeStep); +} + +inline +void PfxRigidState::moveOrientation(const PfxQuat &rot,PfxFloat timeStep) +{ + if(getMotionType()!=kPfxMotionTypeKeyframe) return; + + SCE_PFX_ASSERT(timeStep > 0.0f); + + PfxQuat ori1 = getOrientation(); + PfxQuat ori2 = rot; + + if(dot(ori2,ori1) < 0.0f) { + ori2 = -rot; + } + + PfxQuat dq = ( ori2 - ori1 ) / timeStep; + dq = dq * 2.0f * conj(ori1); + PfxVector3 omega = dq.getXYZ(); + + setAngularVelocity(omega); +} +} // namespace PhysicsEffects +} // namespace sce +#endif // _SCE_PFX_RIGID_STATE_H + diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_constraint_pair.h b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_constraint_pair.h new file mode 100644 index 0000000..2663df9 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_constraint_pair.h @@ -0,0 +1,39 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONSTRAINT_PAIR_H +#define _SCE_PFX_CONSTRAINT_PAIR_H + +#include "../sort/pfx_sort_data.h" +#include "../broadphase/pfx_broadphase_pair.h" + +namespace sce { +namespace PhysicsEffects { + +typedef PfxSortData16 PfxConstraintPair; + +//J PfxBroadphasePairと共通 +//E Same as PfxBroadphasePair + +SCE_PFX_FORCE_INLINE void pfxSetConstraintId(PfxConstraintPair &pair,PfxUInt32 i) {pair.set32(2,i);} +SCE_PFX_FORCE_INLINE void pfxSetNumConstraints(PfxConstraintPair &pair,PfxUInt8 n) {pair.set8(7,n);} + +SCE_PFX_FORCE_INLINE PfxUInt32 pfxGetConstraintId(const PfxConstraintPair &pair) {return pair.get32(2);} +SCE_PFX_FORCE_INLINE PfxUInt8 pfxGetNumConstraints(const PfxConstraintPair &pair) {return pair.get8(7);} + +} //namespace PhysicsEffects +} //namespace sce +#endif // _SCE_PFX_CONSTRAINT_PAIR_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_constraint_row.h b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_constraint_row.h new file mode 100644 index 0000000..b5ae656 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_constraint_row.h @@ -0,0 +1,40 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONSTRAINT_ROW_H +#define _SCE_PFX_CONSTRAINT_ROW_H + +#include "../base/pfx_vec_utils.h" + +namespace sce { +namespace PhysicsEffects { + + +#include "../base/pfx_common.h" + +//E Don't change following order of parameters +struct SCE_PFX_ALIGNED(16) PfxConstraintRow { + PfxFloat m_normal[3]; + PfxFloat m_rhs; + PfxFloat m_jacDiagInv; + PfxFloat m_lowerLimit; + PfxFloat m_upperLimit; + PfxFloat m_accumImpulse; +}; + +} //namespace PhysicsEffects +} //namespace sce +#endif // _SCE_PFX_CONSTRAINT_ROW_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_contact_constraint.h b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_contact_constraint.h new file mode 100644 index 0000000..d1b5ceb --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_contact_constraint.h @@ -0,0 +1,59 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONTACT_CONSTRAINT_H +#define _SCE_PFX_CONTACT_CONSTRAINT_H + +#include "../rigidbody/pfx_rigid_state.h" +#include "pfx_constraint_row.h" +#include "pfx_solver_body.h" + +namespace sce { +namespace PhysicsEffects { + +void pfxSetupContactConstraint( + PfxConstraintRow &constraintResponse, + PfxConstraintRow &constraintFriction1, + PfxConstraintRow &constraintFriction2, + PfxFloat penetrationDepth, + PfxFloat restitution, + PfxFloat friction, + const PfxVector3 &contactNormal, + const PfxVector3 &contactPointA, + const PfxVector3 &contactPointB, + const PfxRigidState &stateA, + const PfxRigidState &stateB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + PfxFloat separateBias, + PfxFloat timeStep + ); + +void pfxSolveContactConstraint( + PfxConstraintRow &constraintResponse, + PfxConstraintRow &constraintFriction1, + PfxConstraintRow &constraintFriction2, + const PfxVector3 &contactPointA, + const PfxVector3 &contactPointB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + PfxFloat friction + ); + + +} //namespace PhysicsEffects +} //namespace sce +#endif // _SCE_PFX_CONTACT_CONSTRAINT_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_integrate.h b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_integrate.h new file mode 100644 index 0000000..4253182 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_integrate.h @@ -0,0 +1,121 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_INTEGRATE_H_ +#define _SCE_PFX_INTEGRATE_H_ + +#include "../base/pfx_common.h" +#include "../rigidbody/pfx_rigid_body.h" +#include "../rigidbody/pfx_rigid_state.h" + +namespace sce { +namespace PhysicsEffects { + +template +static SCE_PFX_FORCE_INLINE T pfxRungeKutta(const T &deriv,PfxFloat dt) +{ + T k0, k1, k2, k3; + k0 = deriv * dt; + k1 = (deriv + k0 * 0.5f) * dt; + k2 = (deriv + k1 * 0.5f) * dt; + k3 = (deriv + k2) * dt; + return (k0 + k1*2.0f + k2*2.0f + k3) / 6.0f; +} + +#define SCE_PFX_MOTION_MASK_INTEGRATE ((1< state.getMaxLinearVelocity()) + { + nv = normalize( nv ) * state.getMaxLinearVelocity(); + } + if(length(nw) > state.getMaxAngularVelocity()) + { + nw = normalize( nw ) * state.getMaxAngularVelocity(); + } + + state.setLinearVelocity(nv); + state.setAngularVelocity(nw); +} +} //namespace PhysicsEffects +} //namespace sce + +#endif /* _SCE_PFX_INTEGRATE_H_ */ diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint.h b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint.h new file mode 100644 index 0000000..1c2be07 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint.h @@ -0,0 +1,90 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_JOINT_H +#define _SCE_PFX_JOINT_H + +#include "../rigidbody/pfx_rigid_state.h" +#include "pfx_joint_constraint.h" +#include "pfx_constraint_pair.h" + +namespace sce { +namespace PhysicsEffects { + +// Joint Type +enum ePfxJointType { + kPfxJointBall = 0, + kPfxJointSwingtwist, + kPfxJointHinge, + kPfxJointSlider, + kPfxJointFix, + kPfxJointUniversal, + kPfxJointAnimation, + kPfxJointReserved0, + kPfxJointReserved1, + kPfxJointReserved2, + kPfxJointUser0, + kPfxJointUser1, + kPfxJointUser2, + kPfxJointUser3, + kPfxJointUser4, + kPfxJointCount // = 15 +}; + +// Joint Structure +struct SCE_PFX_ALIGNED(128) PfxJoint { + PfxUInt8 m_active; + PfxUInt8 m_numConstraints; + PfxUInt8 m_type; + SCE_PFX_PADDING(1,1) + PfxUInt16 m_rigidBodyIdA; + PfxUInt16 m_rigidBodyIdB; + SCE_PFX_PADDING(2,8) + PfxJointConstraint m_constraints[6]; + void *m_userData; + SCE_PFX_PADDING(3,12) + PfxVector3 m_param[4]; // Used by some joints for specific features + PfxVector3 m_anchorA; + PfxVector3 m_anchorB; + PfxMatrix3 m_frameA; + PfxMatrix3 m_frameB; + SCE_PFX_PADDING(4,32) +}; + +SCE_PFX_FORCE_INLINE +void pfxUpdateJointPairs( + PfxConstraintPair &pair, + PfxUInt32 jointId, + const PfxJoint &joint, + const PfxRigidState &stateA, + const PfxRigidState &stateB + ) +{ + SCE_PFX_ALWAYS_ASSERT(stateA.getRigidBodyId()==joint.m_rigidBodyIdA); + SCE_PFX_ALWAYS_ASSERT(stateB.getRigidBodyId()==joint.m_rigidBodyIdB); + pfxSetObjectIdA(pair,stateA.getRigidBodyId()); + pfxSetObjectIdB(pair,stateB.getRigidBodyId()); + pfxSetMotionMaskA(pair,stateA.getMotionMask()); + pfxSetMotionMaskB(pair,stateB.getMotionMask()); + pfxSetConstraintId(pair,jointId); + pfxSetNumConstraints(pair,joint.m_numConstraints); + pfxSetActive(pair,joint.m_active>0); +} +} //namespace PhysicsEffects +} //namespace sce + + +#endif // _PFX_JOINT_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_ball.h b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_ball.h new file mode 100644 index 0000000..f18ec8c --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_ball.h @@ -0,0 +1,62 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_JOINT_BALL_H +#define _SCE_PFX_JOINT_BALL_H + +#include "pfx_joint.h" +#include "pfx_solver_body.h" + +namespace sce { +namespace PhysicsEffects { + +struct PfxBallJointInitParam { + PfxVector3 anchorPoint; + + PfxBallJointInitParam() + { + anchorPoint = PfxVector3(0.0f); + } +}; + +PfxInt32 pfxInitializeBallJoint( + PfxJoint &joint, + const PfxRigidState &stateA, + const PfxRigidState &stateB, + const PfxBallJointInitParam ¶m); + +void pfxSetupBallJoint( + PfxJoint &joint, + const PfxRigidState &stateA, + const PfxRigidState &stateB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + PfxFloat timeStep); + +void pfxWarmStartBallJoint( + PfxJoint &joint, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB); + +void pfxSolveBallJoint( + PfxJoint &joint, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_JOINT_BALL_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_constraint.h b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_constraint.h new file mode 100644 index 0000000..2d4b10f --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_constraint.h @@ -0,0 +1,67 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_JOINT_CONSTRAINT_H +#define _SCE_PFX_JOINT_CONSTRAINT_H + +#include "../base/pfx_common.h" +#include "../base/pfx_vec_utils.h" +#include "pfx_constraint_row.h" + +namespace sce { +namespace PhysicsEffects { + +// Lock type +#define SCE_PFX_JOINT_LOCK_FREE 0 +#define SCE_PFX_JOINT_LOCK_LIMIT 1 +#define SCE_PFX_JOINT_LOCK_FIX 2 + +// Slop +#define SCE_PFX_JOINT_LINEAR_SLOP 0.01f +#define SCE_PFX_JOINT_ANGULAR_SLOP 0.01f + +///////////////////////////////////////////////////////////////////////////////// Joint Constraint + +struct PfxJointConstraint { + PfxInt8 m_lock; + PfxInt8 m_warmStarting; + SCE_PFX_PADDING(1,2) + PfxFloat m_movableLowerLimit; + PfxFloat m_movableUpperLimit; + PfxFloat m_bias; + PfxFloat m_weight; + PfxFloat m_damping; + PfxFloat m_maxImpulse; + SCE_PFX_PADDING(2,4) + PfxConstraintRow m_constraintRow; + + void reset() + { + m_lock = SCE_PFX_JOINT_LOCK_FIX; + m_warmStarting = 0; + m_movableLowerLimit = 0.0f; + m_movableUpperLimit = 0.0f; + m_bias = 0.2f; + m_weight = 1.0f; + m_damping = 0.0f; + m_maxImpulse = SCE_PFX_FLT_MAX; + memset(&m_constraintRow,0,sizeof(PfxConstraintRow)); + } +}; +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_JOINT_CONSTRAINT_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_fix.h b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_fix.h new file mode 100644 index 0000000..7d44082 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_fix.h @@ -0,0 +1,49 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_JOINT_FIX_H +#define _SCE_PFX_JOINT_FIX_H + +#include "pfx_joint.h" +#include "pfx_solver_body.h" + +namespace sce { +namespace PhysicsEffects { + +struct PfxFixJointInitParam { + PfxVector3 anchorPoint; + + PfxFixJointInitParam() + { + anchorPoint = PfxVector3(0.0f); + } +}; + +PfxInt32 pfxInitializeFixJoint( + PfxJoint &joint, + const PfxRigidState &stateA, + const PfxRigidState &stateB, + const PfxFixJointInitParam ¶m); + +// pfxSetupFixJoint = pfxSetupSwingTwistJoint + +// pfxWarmStartFixJoint = pfxWarmStartSwingTwistJoint + +// pfxSolveFixJoint = pfxSolveSwingTwistJoint +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_JOINT_FIX_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_hinge.h b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_hinge.h new file mode 100644 index 0000000..357f47e --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_hinge.h @@ -0,0 +1,56 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_JOINT_HINGE_H_ +#define _SCE_PFX_JOINT_HINGE_H_ + +#include "pfx_joint.h" +#include "pfx_solver_body.h" + +namespace sce { +namespace PhysicsEffects { + +struct PfxHingeJointInitParam { + PfxVector3 anchorPoint; + PfxVector3 axis; + PfxFloat lowerAngle; + PfxFloat upperAngle; + SCE_PFX_PADDING(1,8) + + PfxHingeJointInitParam() + { + anchorPoint = PfxVector3(0.0f); + axis = PfxVector3(1.0f,0.0f,0.0f); + lowerAngle = 0.0f; + upperAngle = 0.0f; + } +}; + +PfxInt32 pfxInitializeHingeJoint( + PfxJoint &joint, + const PfxRigidState &stateA, + const PfxRigidState &stateB, + const PfxHingeJointInitParam ¶m); + +// pfxSetupHingeJoint = pfxSetupSwingTwistJoint + +// pfxWarmStartHingeJoint = pfxWarmStartSwingTwistJoint + +// pfxSolveHingeJoint = pfxSolveSwingTwistJoint + +} //namespace PhysicsEffects +} //namespace sce +#endif // _SCE_PFX_JOINT_HINGE_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_slider.h b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_slider.h new file mode 100644 index 0000000..23b5769 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_slider.h @@ -0,0 +1,57 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_JOINT_SLIDER_H +#define _SCE_PFX_JOINT_SLIDER_H + +#include "pfx_joint.h" +#include "pfx_solver_body.h" + +namespace sce { +namespace PhysicsEffects { + +struct PfxSliderJointInitParam { + PfxVector3 anchorPoint; + PfxVector3 direction; + PfxFloat lowerDistance; + PfxFloat upperDistance; + SCE_PFX_PADDING(1,8) + + PfxSliderJointInitParam() + { + anchorPoint = PfxVector3(0.0f); + direction = PfxVector3(1.0f,0.0f,0.0f); + lowerDistance = 0.0f; + upperDistance = 0.0f; + } +}; + +PfxInt32 pfxInitializeSliderJoint( + PfxJoint &joint, + const PfxRigidState &stateA, + const PfxRigidState &stateB, + const PfxSliderJointInitParam ¶m); + +// pfxSetupSliderJoint = pfxSetupSwingTwistJoint + +// pfxWarmStartSliderJoint = pfxWarmStartSwingTwistJoint + +// pfxSolveSliderJoint = pfxSolveSwingTwistJoint + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_JOINT_SLIDER_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_swing_twist.h b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_swing_twist.h new file mode 100644 index 0000000..de0774d --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_swing_twist.h @@ -0,0 +1,70 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_JOINT_SWING_TWIST_H +#define _SCE_PFX_JOINT_SWING_TWIST_H + +#include "pfx_joint.h" +#include "pfx_solver_body.h" +namespace sce { +namespace PhysicsEffects { + +struct PfxSwingTwistJointInitParam { + PfxVector3 anchorPoint; + PfxVector3 twistAxis; + PfxFloat twistLowerAngle; + PfxFloat twistUpperAngle; + PfxFloat swingLowerAngle; + PfxFloat swingUpperAngle; + + PfxSwingTwistJointInitParam() + { + anchorPoint = PfxVector3(0.0f); + twistAxis = PfxVector3(1.0f,0.0f,0.0f); + twistLowerAngle = -0.26f; + twistUpperAngle = 0.26f; + swingLowerAngle = 0.0f; + swingUpperAngle = 0.7f; + } +}; + +PfxInt32 pfxInitializeSwingTwistJoint( + PfxJoint &joint, + const PfxRigidState &stateA, + const PfxRigidState &stateB, + const PfxSwingTwistJointInitParam ¶m); + +void pfxSetupSwingTwistJoint( + PfxJoint &joint, + const PfxRigidState &stateA, + const PfxRigidState &stateB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + PfxFloat timeStep); + +void pfxWarmStartSwingTwistJoint( + PfxJoint &joint, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB); + +void pfxSolveSwingTwistJoint( + PfxJoint &joint, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB); + +} //namespace PhysicsEffects +} //namespace sce +#endif // _SCE_PFX_JOINT_SWING_TWIST_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_universal.h b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_universal.h new file mode 100644 index 0000000..7e9148d --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_joint_universal.h @@ -0,0 +1,65 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_JOINT_UNIVERSAL_H +#define _SCE_PFX_JOINT_UNIVERSAL_H + +#include "pfx_joint.h" +#include "pfx_solver_body.h" + +namespace sce { +namespace PhysicsEffects { + +struct PfxUniversalJointInitParam { + PfxVector3 anchorPoint; + PfxVector3 axis; + PfxFloat swing1LowerAngle; + PfxFloat swing1UpperAngle; + PfxFloat swing2LowerAngle; + PfxFloat swing2UpperAngle; + + PfxUniversalJointInitParam() + { + anchorPoint = PfxVector3(0.0f); + axis = PfxVector3(1.0f,0.0f,0.0f); + swing1LowerAngle = -0.7f; + swing1UpperAngle = 0.7f; + swing2LowerAngle = -0.7f; + swing2UpperAngle = 0.7f; + } +}; + +PfxInt32 pfxInitializeUniversalJoint( + PfxJoint &joint, + const PfxRigidState &stateA, + const PfxRigidState &stateB, + const PfxUniversalJointInitParam ¶m); + +void pfxSetupUniversalJoint( + PfxJoint &joint, + const PfxRigidState &stateA, + const PfxRigidState &stateB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + PfxFloat timeStep); + +// pfxWarmStartUniversalJoint = pfxWarmStartSwingTwistJoint + +// pfxSolveUniversalJoint = pfxSolveSwingTwistJoint + +} //namespace PhysicsEffects +} //namespace sce +#endif // _SCE_PFX_JOINT_UNIVERSAL_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_solver_body.h b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_solver_body.h new file mode 100644 index 0000000..f26370d --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/solver/pfx_solver_body.h @@ -0,0 +1,37 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_SOLVER_BODY_H +#define _SCE_PFX_SOLVER_BODY_H + +#include "../base/pfx_common.h" + +namespace sce { +namespace PhysicsEffects { + +struct SCE_PFX_ALIGNED(128) PfxSolverBody { + PfxVector3 m_deltaLinearVelocity; + PfxVector3 m_deltaAngularVelocity; + PfxQuat m_orientation; + PfxMatrix3 m_inertiaInv; + PfxFloat m_massInv; + PfxUInt32 m_motionType; + SCE_PFX_PADDING(1,24) +}; + +} //namespace PhysicsEffects +} //namespace sce +#endif // _SCE_PFX_SOLVER_BODY_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/sort/pfx_sort.h b/Extras/PhysicsEffects/include/physics_effects/base_level/sort/pfx_sort.h new file mode 100644 index 0000000..346910c --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/sort/pfx_sort.h @@ -0,0 +1,33 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_SORT_H +#define _SCE_PFX_SORT_H + +#include "pfx_sort_data.h" +namespace sce { +namespace PhysicsEffects { + +/////////////////////////////////////////////////////////////////////////////// +// Single Sort + +void pfxSort(PfxSortData16 *data,PfxSortData16 *buff,unsigned int n); +void pfxSort(PfxSortData32 *data,PfxSortData32 *buff,unsigned int n); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_SORT_H diff --git a/Extras/PhysicsEffects/include/physics_effects/base_level/sort/pfx_sort_data.h b/Extras/PhysicsEffects/include/physics_effects/base_level/sort/pfx_sort_data.h new file mode 100644 index 0000000..b048d17 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/base_level/sort/pfx_sort_data.h @@ -0,0 +1,82 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_SORT_DATA_H +#define _SCE_PFX_SORT_DATA_H + +#include "../base/pfx_common.h" + + + +namespace sce { +namespace PhysicsEffects { + +#define SCE_PFX_SENTINEL_KEY 0xffffffff + +struct SCE_PFX_ALIGNED(16) PfxSortData16 { + union { + PfxUInt8 i8data[16]; + PfxUInt16 i16data[8]; + PfxUInt32 i32data[4]; + }; + +void set8(int slot,PfxUInt8 data) {i8data[slot] = data;} +void set16(int slot,PfxUInt16 data) {i16data[slot] = data;} +void set32(int slot,PfxUInt32 data) {i32data[slot] = data;} +PfxUInt8 get8(int slot) const {return i8data[slot];} +PfxUInt16 get16(int slot) const {return i16data[slot];} +PfxUInt32 get32(int slot) const {return i32data[slot];} +}; + +struct SCE_PFX_ALIGNED(16) PfxSortData32 { + union { + PfxUInt8 i8data[32]; + PfxUInt16 i16data[16]; + PfxUInt32 i32data[8]; + }; + +void set8(int slot,PfxUInt8 data) {i8data[slot] = data;} +void set16(int slot,PfxUInt16 data) {i16data[slot] = data;} +void set32(int slot,PfxUInt32 data) {i32data[slot] = data;} +PfxUInt8 get8(int slot) const {return i8data[slot];} +PfxUInt16 get16(int slot) const {return i16data[slot];} +PfxUInt32 get32(int slot) const {return i32data[slot];} +}; + +SCE_PFX_FORCE_INLINE +void pfxSetKey(PfxSortData16 &sortData,PfxUInt32 key) {sortData.set32(3,key);} + +SCE_PFX_FORCE_INLINE +PfxUInt32 pfxGetKey(const PfxSortData16 &sortData) {return sortData.get32(3);} + +SCE_PFX_FORCE_INLINE +void pfxSetKey(PfxSortData32 &sortData,PfxUInt32 key) {sortData.set32(7,key);} + +SCE_PFX_FORCE_INLINE +PfxUInt32 pfxGetKey(const PfxSortData32 &sortData) {return sortData.get32(7);} + +SCE_PFX_FORCE_INLINE +PfxUInt32 pfxCreateUniqueKey(PfxUInt32 i,PfxUInt32 j) +{ + PfxUInt32 minIdx = SCE_PFX_MIN(i,j); + PfxUInt32 maxIdx = SCE_PFX_MAX(i,j); + return (maxIdx<<16)|(minIdx&0xffff); +} + +} // namespace PhysicsEffects +} // namespace sce + +#endif // _SCE_PFX_SORT_DATA_H diff --git a/Extras/PhysicsEffects/include/physics_effects/low_level/broadphase/pfx_broadphase.h b/Extras/PhysicsEffects/include/physics_effects/low_level/broadphase/pfx_broadphase.h new file mode 100644 index 0000000..18832d7 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/low_level/broadphase/pfx_broadphase.h @@ -0,0 +1,124 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_BROADPHASE_H_ +#define _SCE_PFX_BROADPHASE_H_ + +#include "../../base_level/broadphase/pfx_broadphase_pair.h" +#include "../../base_level/broadphase/pfx_broadphase_proxy.h" +#include "../../base_level/rigidbody/pfx_rigid_state.h" +#include "../../base_level/collision/pfx_collidable.h" +#include "../task/pfx_task_manager.h" + +namespace sce { +namespace PhysicsEffects { + +/////////////////////////////////////////////////////////////////////////////// +// Update Broadphase Proxies + +#define SCE_PFX_OUT_OF_WORLD_BEHAVIOR_FIX_MOTION 0x01 +#define SCE_PFX_OUT_OF_WORLD_BEHAVIOR_REMOVE_PROXY 0x02 + +struct PfxUpdateBroadphaseProxiesParam { + void *workBuff; + PfxUInt32 workBytes; + PfxBroadphaseProxy *proxiesX; + PfxBroadphaseProxy *proxiesY; + PfxBroadphaseProxy *proxiesZ; + PfxBroadphaseProxy *proxiesXb; + PfxBroadphaseProxy *proxiesYb; + PfxBroadphaseProxy *proxiesZb; + PfxRigidState *offsetRigidStates; + PfxCollidable *offsetCollidables; + PfxUInt32 numRigidBodies; + PfxUInt32 outOfWorldBehavior; + PfxVector3 worldCenter; + PfxVector3 worldExtent; + + PfxUpdateBroadphaseProxiesParam() : outOfWorldBehavior(0) {} +}; + +struct PfxUpdateBroadphaseProxiesResult { + PfxInt32 numOutOfWorldProxies; +}; + +PfxUInt32 pfxGetWorkBytesOfUpdateBroadphaseProxies(PfxUInt32 numRigidBodies); + +PfxUInt32 pfxGetWorkBytesOfUpdateBroadphaseProxies(PfxUInt32 numRigidBodies,PfxUInt32 maxTasks); + +PfxInt32 pfxUpdateBroadphaseProxies(PfxUpdateBroadphaseProxiesParam ¶m,PfxUpdateBroadphaseProxiesResult &result); + +PfxInt32 pfxUpdateBroadphaseProxies(PfxUpdateBroadphaseProxiesParam ¶m,PfxUpdateBroadphaseProxiesResult &result,PfxTaskManager *taskManager); + +/////////////////////////////////////////////////////////////////////////////// +// Find Pairs + +struct PfxFindPairsParam { + void *workBuff; + PfxUInt32 workBytes; + void *pairBuff; + PfxUInt32 pairBytes; + PfxBroadphaseProxy *proxies; + PfxUInt32 numProxies; + PfxUInt32 maxPairs; + int axis; +}; + +struct PfxFindPairsResult { + PfxBroadphasePair *pairs; + PfxUInt32 numPairs; +}; + +PfxUInt32 pfxGetWorkBytesOfFindPairs(PfxUInt32 maxPairs,PfxUInt32 maxTasks=1); +PfxUInt32 pfxGetPairBytesOfFindPairs(PfxUInt32 maxPairs); + +PfxInt32 pfxFindPairs(PfxFindPairsParam ¶m,PfxFindPairsResult &result); + +PfxInt32 pfxFindPairs(PfxFindPairsParam ¶m,PfxFindPairsResult &result,PfxTaskManager *taskManager); + +/////////////////////////////////////////////////////////////////////////////// +// Decompose Pairs + +struct PfxDecomposePairsParam { + void *workBuff; + PfxUInt32 workBytes; + void *pairBuff; + PfxUInt32 pairBytes; + PfxBroadphasePair *previousPairs; + PfxUInt32 numPreviousPairs; + PfxBroadphasePair *currentPairs; + PfxUInt32 numCurrentPairs; +}; + +struct PfxDecomposePairsResult { + PfxBroadphasePair *outNewPairs; + PfxUInt32 numOutNewPairs; + PfxBroadphasePair *outKeepPairs; + PfxUInt32 numOutKeepPairs; + PfxBroadphasePair *outRemovePairs; + PfxUInt32 numOutRemovePairs; +}; + +PfxUInt32 pfxGetWorkBytesOfDecomposePairs(PfxUInt32 numPreviousPairs,PfxUInt32 numCurrentPairs,int maxTasks=1); +PfxUInt32 pfxGetPairBytesOfDecomposePairs(PfxUInt32 numPreviousPairs,PfxUInt32 numCurrentPairs); + +PfxInt32 pfxDecomposePairs(PfxDecomposePairsParam ¶m,PfxDecomposePairsResult &result); + +PfxInt32 pfxDecomposePairs(PfxDecomposePairsParam ¶m,PfxDecomposePairsResult &result,PfxTaskManager *taskManager); + +} //namespace PhysicsEffects +} //namespace sce +#endif /* _SCE_PFX_BROADPHASE_H_ */ diff --git a/Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_batched_ray_cast.h b/Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_batched_ray_cast.h new file mode 100644 index 0000000..5ecb90c --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_batched_ray_cast.h @@ -0,0 +1,38 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_BATCHED_RAY_CAST_H +#define _SCE_PFX_BATCHED_RAY_CAST_H + +#include "../../base_level/rigidbody/pfx_rigid_state.h" +#include "../../base_level/collision/pfx_collidable.h" +#include "../../base_level/broadphase/pfx_broadphase_proxy.h" +#include "../task/pfx_task_manager.h" +#include "pfx_ray_cast.h" + +/////////////////////////////////////////////////////////////////////////////// +// Batched RayCast +namespace sce { +namespace PhysicsEffects { + +void pfxCastRays(PfxRayInput *rayInputs,PfxRayOutput *rayOutputs,int numRays,PfxRayCastParam ¶m); + +void pfxCastRays(PfxRayInput *rayInputs,PfxRayOutput *rayOutputs,int numRays,PfxRayCastParam ¶m,PfxTaskManager *taskManager); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_BATCHED_RAY_CAST_H diff --git a/Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_collision_detection.h b/Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_collision_detection.h new file mode 100644 index 0000000..3838fb9 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_collision_detection.h @@ -0,0 +1,48 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_COLLISION_DETECTION_H_ +#define _SCE_PFX_COLLISION_DETECTION_H_ + +#include "../../base_level/rigidbody/pfx_rigid_state.h" +#include "../../base_level/collision/pfx_collidable.h" +#include "../../base_level/collision/pfx_contact_manifold.h" +#include "../../base_level/solver/pfx_constraint_pair.h" +#include "../task/pfx_task_manager.h" + +namespace sce { +namespace PhysicsEffects { + +/////////////////////////////////////////////////////////////////////////////// +// Detect Collision + +struct PfxDetectCollisionParam { + PfxConstraintPair *contactPairs; + PfxUInt32 numContactPairs; + PfxContactManifold *offsetContactManifolds; + PfxRigidState *offsetRigidStates; + PfxCollidable *offsetCollidables; + PfxUInt32 numRigidBodies; +}; + +PfxInt32 pfxDetectCollision(PfxDetectCollisionParam ¶m); + +PfxInt32 pfxDetectCollision(PfxDetectCollisionParam ¶m,PfxTaskManager *taskManager); + +} //namespace PhysicsEffects +} //namespace sce + +#endif /* _SCE_PFX_COLLISION_DETECTION_H_ */ diff --git a/Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_island_generation.h b/Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_island_generation.h new file mode 100644 index 0000000..cb01d25 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_island_generation.h @@ -0,0 +1,78 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_ISLAND_GENERATION_H_ +#define _SCE_PFX_ISLAND_GENERATION_H_ + +#include "../../base_level/solver/pfx_constraint_pair.h" +#include "../task/pfx_task_manager.h" + +namespace sce { +namespace PhysicsEffects { + +/////////////////////////////////////////////////////////////////////////////// +// Island Generation + +struct PfxIsland; +struct PfxIslandUnit; + +struct PfxGenerateIslandParam { + void *islandBuff; + PfxUInt32 islandBytes; + PfxConstraintPair *pairs; + PfxUInt32 numPairs; + PfxUInt32 numObjects; +}; + +struct PfxGenerateIslandResult { + PfxIsland *island; +}; + +//J アイランド情報を使い終わるまでislandBuffを破棄しないでください +//E Keep islandBuff while the island is used +PfxUInt32 pfxGetIslandBytesOfGenerateIsland(PfxUInt32 numObjects); + +PfxInt32 pfxGenerateIsland(PfxGenerateIslandParam ¶m,PfxGenerateIslandResult &result); + +//E Access to island information +//J アイランド情報へのアクセス + +//E Get the number of islands +//J アイランド数を取得する +PfxUInt32 pfxGetNumIslands(const PfxIsland *islands); + +//E Get a island unit in a island +//J 指定したアイランドに含まれるユニット(剛体)にアクセス +PfxIslandUnit *pfxGetFirstUnitInIsland(const PfxIsland *islands,PfxUInt32 islandId); +PfxIslandUnit *pfxGetNextUnitInIsland(const PfxIslandUnit *islandUnit); +PfxUInt32 pfxGetUnitId(const PfxIslandUnit *islandUnit); + +//E Get an index of an island which includes a specific unit +//J 指定したユニット(剛体)のアイランドインデックスを取得する +PfxUInt32 pfxGetIslandId(const PfxIsland *islands,PfxUInt32 unitId); + +//E Add pairs and construct islands +//J アイランドにペアを追加する +PfxInt32 pfxAppendPairs(PfxIsland *island,PfxConstraintPair *pairs,PfxUInt32 numPairs); + +//E Reset islands +//J アイランドリセット +void pfxResetIsland(PfxIsland *island); + +} //namespace PhysicsEffects +} //namespace sce + +#endif /* _SCE_PFX_ISLAND_GENERATION_H_ */ diff --git a/Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_ray_cast.h b/Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_ray_cast.h new file mode 100644 index 0000000..3bfba40 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_ray_cast.h @@ -0,0 +1,50 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_RAY_CAST_H +#define _SCE_PFX_RAY_CAST_H + +#include "../../base_level/rigidbody/pfx_rigid_state.h" +#include "../../base_level/collision/pfx_collidable.h" +#include "../../base_level/collision/pfx_ray.h" +#include "../../base_level/broadphase/pfx_broadphase_proxy.h" + +/////////////////////////////////////////////////////////////////////////////// +// RayCast + +namespace sce { +namespace PhysicsEffects { + +struct PfxRayCastParam { + PfxRigidState *offsetRigidStates; + PfxCollidable *offsetCollidables; + PfxBroadphaseProxy *proxiesX; + PfxBroadphaseProxy *proxiesY; + PfxBroadphaseProxy *proxiesZ; + PfxBroadphaseProxy *proxiesXb; + PfxBroadphaseProxy *proxiesYb; + PfxBroadphaseProxy *proxiesZb; + PfxUInt32 numProxies; + SCE_PFX_PADDING(1,12) + PfxVector3 rangeCenter; + PfxVector3 rangeExtent; +}; + +void pfxCastSingleRay(const PfxRayInput &rayInput,PfxRayOutput &rayOutput,const PfxRayCastParam ¶m); + +} //namespace PhysicsEffects +} //namespace sce +#endif // _SCE_PFX_RAY_CAST_H diff --git a/Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_refresh_contacts.h b/Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_refresh_contacts.h new file mode 100644 index 0000000..10cf104 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/low_level/collision/pfx_refresh_contacts.h @@ -0,0 +1,46 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_REFRESH_CONTACTS_H +#define _SCE_PFX_REFRESH_CONTACTS_H + +#include "../../base_level/rigidbody/pfx_rigid_state.h" +#include "../../base_level/solver/pfx_constraint_pair.h" +#include "../../base_level/collision/pfx_contact_manifold.h" +#include "../task/pfx_task_manager.h" + +namespace sce { +namespace PhysicsEffects { + +/////////////////////////////////////////////////////////////////////////////// +// Refresh Contacts + +struct PfxRefreshContactsParam { + PfxConstraintPair *contactPairs; + PfxUInt32 numContactPairs; + PfxContactManifold *offsetContactManifolds; + PfxRigidState *offsetRigidStates; + PfxUInt32 numRigidBodies; +}; + +PfxInt32 pfxRefreshContacts(PfxRefreshContactsParam ¶m); + +PfxInt32 pfxRefreshContacts(PfxRefreshContactsParam ¶m,PfxTaskManager *taskManager); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_REFRESH_CONTACTS_H diff --git a/Extras/PhysicsEffects/include/physics_effects/low_level/pfx_low_level_include.h b/Extras/PhysicsEffects/include/physics_effects/low_level/pfx_low_level_include.h new file mode 100644 index 0000000..5b513c7 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/low_level/pfx_low_level_include.h @@ -0,0 +1,46 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_LOW_LEVEL_INCLUDE_H +#define _SCE_PFX_LOW_LEVEL_INCLUDE_H + +/////////////////////////////////////////////////////////////////////////////// +// Physics Effects Low Level Headers + +// Include base level headers +#include "../base_level/pfx_base_level_include.h" + +// Include low level headers +#include "broadphase/pfx_broadphase.h" + +#include "collision/pfx_collision_detection.h" +#include "collision/pfx_refresh_contacts.h" +#include "collision/pfx_batched_ray_cast.h" +#include "collision/pfx_ray_cast.h" +#include "collision/pfx_island_generation.h" + +#include "solver/pfx_constraint_solver.h" +#include "solver/pfx_update_rigid_states.h" + +#include "sort/pfx_parallel_sort.h" + +// ARA begin insert new code +#ifdef USE_PTHREADS +#include "task/pfx_pthreads.h" +#endif +// ARA end + +#endif // _SCE_PFX_LOW_LEVEL_INCLUDE_H diff --git a/Extras/PhysicsEffects/include/physics_effects/low_level/solver/pfx_constraint_solver.h b/Extras/PhysicsEffects/include/physics_effects/low_level/solver/pfx_constraint_solver.h new file mode 100644 index 0000000..64837d4 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/low_level/solver/pfx_constraint_solver.h @@ -0,0 +1,123 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONSTRAINT_SOLVER_H +#define _SCE_PFX_CONSTRAINT_SOLVER_H + +#include "../../base_level/rigidbody/pfx_rigid_body.h" +#include "../../base_level/rigidbody/pfx_rigid_state.h" +#include "../../base_level/solver/pfx_solver_body.h" +#include "../../base_level/solver/pfx_constraint_pair.h" +#include "../../base_level/solver/pfx_joint.h" +#include "../../base_level/collision/pfx_contact_manifold.h" + +#include "../task/pfx_task_manager.h" + +namespace sce { +namespace PhysicsEffects { + +/////////////////////////////////////////////////////////////////////////////// +// Setup Solver Bodies + +struct PfxSetupSolverBodiesParam { + PfxRigidState *states; + PfxRigidBody *bodies; + PfxSolverBody *solverBodies; + PfxUInt32 numRigidBodies; +}; + +PfxInt32 pfxSetupSolverBodies(PfxSetupSolverBodiesParam ¶m); + +PfxInt32 pfxSetupSolverBodies(PfxSetupSolverBodiesParam ¶m,PfxTaskManager *taskManager); + +/////////////////////////////////////////////////////////////////////////////// +// Setup Constraints + +struct PfxSetupContactConstraintsParam { + PfxConstraintPair *contactPairs; + PfxUInt32 numContactPairs; + PfxContactManifold *offsetContactManifolds; + PfxRigidState *offsetRigidStates; + PfxRigidBody *offsetRigidBodies; + PfxSolverBody *offsetSolverBodies; + PfxUInt32 numRigidBodies; + PfxFloat timeStep; + PfxFloat separateBias; + + PfxSetupContactConstraintsParam() + { + timeStep = 0.016f; + separateBias = 0.2f; + } +}; + +PfxInt32 pfxSetupContactConstraints(PfxSetupContactConstraintsParam ¶m); + +PfxInt32 pfxSetupContactConstraints(PfxSetupContactConstraintsParam ¶m,PfxTaskManager *taskManager); + +struct PfxSetupJointConstraintsParam { + PfxConstraintPair *jointPairs; + PfxUInt32 numJointPairs; + PfxJoint *offsetJoints; + PfxRigidState *offsetRigidStates; + PfxRigidBody *offsetRigidBodies; + PfxSolverBody *offsetSolverBodies; + PfxUInt32 numRigidBodies; + PfxFloat timeStep; + + PfxSetupJointConstraintsParam() + { + timeStep = 0.016f; + } +}; + +PfxInt32 pfxSetupJointConstraints(PfxSetupJointConstraintsParam ¶m); + +PfxInt32 pfxSetupJointConstraints(PfxSetupJointConstraintsParam ¶m,PfxTaskManager *taskManager); + +/////////////////////////////////////////////////////////////////////////////// +// Solve Constraints + +struct PfxSolveConstraintsParam { + void *workBuff; + PfxUInt32 workBytes; + PfxConstraintPair *contactPairs; + PfxUInt32 numContactPairs; + PfxContactManifold *offsetContactManifolds; + PfxConstraintPair *jointPairs; + PfxUInt32 numJointPairs; + PfxJoint *offsetJoints; + PfxRigidState *offsetRigidStates; + PfxSolverBody *offsetSolverBodies; + PfxUInt32 numRigidBodies; + PfxUInt32 iteration; + + PfxSolveConstraintsParam() + { + iteration = 5; + } +}; + +PfxUInt32 pfxGetWorkBytesOfSolveConstraints(PfxUInt32 numRigidBodies,PfxUInt32 numContactPairs,PfxUInt32 numJointPairs,PfxUInt32 maxTasks=1); + +PfxInt32 pfxSolveConstraints(PfxSolveConstraintsParam ¶m); + +PfxInt32 pfxSolveConstraints(PfxSolveConstraintsParam ¶m,PfxTaskManager *taskManager); + +} //namespace PhysicsEffects +} //namespace sce +#endif // _SCE_PFX_CONSTRAINT_SOLVER_H + diff --git a/Extras/PhysicsEffects/include/physics_effects/low_level/solver/pfx_joint_constraint_func.h b/Extras/PhysicsEffects/include/physics_effects/low_level/solver/pfx_joint_constraint_func.h new file mode 100644 index 0000000..d8e6d4e --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/low_level/solver/pfx_joint_constraint_func.h @@ -0,0 +1,69 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_JOINT_CONSTRAINT_FUNC_H_ +#define _SCE_PFX_JOINT_CONSTRAINT_FUNC_H_ + +#include "../../base_level/rigidbody/pfx_rigid_state.h" +#include "../../base_level/solver/pfx_solver_body.h" +#include "../../base_level/solver/pfx_joint.h" +#include "../../base_level/solver/pfx_joint_constraint.h" + +namespace sce { +namespace PhysicsEffects { +/////////////////////////////////////////////////////////////////////////////// +// Setup Joint Constraint Func + +typedef void (*PfxSetupJointConstraintFunc)( + PfxJoint &joint, + const PfxRigidState &stateA, + const PfxRigidState &stateB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + PfxFloat timeStep); + +PfxSetupJointConstraintFunc pfxGetSetupJointConstraintFunc(PfxUInt8 jointType); + +int pfxSetSetupJointConstraintFunc(PfxUInt8 jointType,PfxSetupJointConstraintFunc func); + +/////////////////////////////////////////////////////////////////////////////// +// Warm Start Joint Constraint Func + +typedef void (*PfxWarmStartJointConstraintFunc)( + PfxJoint &joint, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB); + +PfxWarmStartJointConstraintFunc pfxGetWarmStartJointConstraintFunc(PfxUInt8 jointType); + +int pfxSetWarmStartJointConstraintFunc(PfxUInt8 jointType,PfxWarmStartJointConstraintFunc func); + +/////////////////////////////////////////////////////////////////////////////// +// Solve Joint Constraint Func + +typedef void (*PfxSolveJointConstraintFunc)( + PfxJoint &joint, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB); + +PfxSolveJointConstraintFunc pfxGetSolveJointConstraintFunc(PfxUInt8 jointType); + +int pfxSetSolveJointConstraintFunc(PfxUInt8 jointType,PfxSolveJointConstraintFunc func); + +} //namespace PhysicsEffects +} //namespace sce + +#endif /* _PFX_JOINT_CONSTRAINT_FUNC_H_ */ diff --git a/Extras/PhysicsEffects/include/physics_effects/low_level/solver/pfx_update_rigid_states.h b/Extras/PhysicsEffects/include/physics_effects/low_level/solver/pfx_update_rigid_states.h new file mode 100644 index 0000000..b16a81e --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/low_level/solver/pfx_update_rigid_states.h @@ -0,0 +1,45 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_UPDATE_RIGID_STATES_H_ +#define _SCE_PFX_UPDATE_RIGID_STATES_H_ + +#include "../../base_level/rigidbody/pfx_rigid_body.h" +#include "../../base_level/rigidbody/pfx_rigid_state.h" + +#include "../task/pfx_task_manager.h" + +namespace sce { +namespace PhysicsEffects { + +/////////////////////////////////////////////////////////////////////////////// +// Update Rigid Body States + +struct PfxUpdateRigidStatesParam { + PfxRigidState *states; + PfxRigidBody *bodies; + PfxUInt32 numRigidBodies; + PfxFloat timeStep; +}; + +PfxInt32 pfxUpdateRigidStates(PfxUpdateRigidStatesParam ¶m); + +PfxInt32 pfxUpdateRigidStates(PfxUpdateRigidStatesParam ¶m,PfxTaskManager *taskManager); + +} //namespace PhysicsEffects +} //namespace sce + +#endif /* _SCE_PFX_UPDATE_RIGID_STATES_H_ */ diff --git a/Extras/PhysicsEffects/include/physics_effects/low_level/sort/pfx_parallel_sort.h b/Extras/PhysicsEffects/include/physics_effects/low_level/sort/pfx_parallel_sort.h new file mode 100644 index 0000000..66d3b15 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/low_level/sort/pfx_parallel_sort.h @@ -0,0 +1,40 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_PARALLEL_SORT_H +#define _SCE_PFX_PARALLEL_SORT_H + +#include "../../base_level/sort/pfx_sort_data.h" +#include "../task/pfx_task_manager.h" + +/////////////////////////////////////////////////////////////////////////////// +// Parallel Sort +namespace sce { +namespace PhysicsEffects { + +PfxInt32 pfxParallelSort(PfxSortData16 *data,PfxUInt32 numData,void *workBuff,PfxUInt32 workBytes); + +PfxInt32 pfxParallelSort(PfxSortData32 *data,PfxUInt32 numData,void *workBuff,PfxUInt32 workBytes); + +PfxInt32 pfxParallelSort(PfxSortData16 *data,PfxUInt32 numData,void *workBuff,PfxUInt32 workBytes, + PfxTaskManager *taskManager); + +PfxInt32 pfxParallelSort(PfxSortData32 *data,PfxUInt32 numData,void *workBuff,PfxUInt32 workBytes, + PfxTaskManager *taskManager); + +} //namespace PhysicsEffects +} //namespace sce +#endif // _SCE_PFX_PARALLEL_SORT_H diff --git a/Extras/PhysicsEffects/include/physics_effects/low_level/task/pfx_pthreads.h b/Extras/PhysicsEffects/include/physics_effects/low_level/task/pfx_pthreads.h new file mode 100644 index 0000000..3b38fae --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/low_level/task/pfx_pthreads.h @@ -0,0 +1,55 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _SCE_PFX_PTHREADS_H +#define _SCE_PFX_PTHREADS_H + +#include "../../base_level/base/pfx_common.h" +#include + +namespace sce { +namespace PhysicsEffects { + +class PfxBarrier; +class PfxCriticalSection; +class PfxTaskManager; + +#define SCE_PFX_CHECK_PTHREADS_OUTCOME(result) \ + if(0 != result) \ + { \ + SCE_PFX_PRINTF("pthreads problem at line %i in file %s: %i %d\n", __LINE__, __FILE__, result, errno); \ + } + +PfxBarrier *PfxCreateBarrierPthreads(int n); +PfxCriticalSection *PfxCreateCriticalSectionPthreads(); +PfxTaskManager *PfxCreateTaskManagerPthreads(PfxUInt32 numTasks,PfxUInt32 maxTasks,void *workBuff,PfxUInt32 workBytes); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_PTHREADS_H diff --git a/Extras/PhysicsEffects/include/physics_effects/low_level/task/pfx_sync_components.h b/Extras/PhysicsEffects/include/physics_effects/low_level/task/pfx_sync_components.h new file mode 100644 index 0000000..1f64672 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/low_level/task/pfx_sync_components.h @@ -0,0 +1,53 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_SYNC_COMPONENTS_H +#define _SCE_PFX_SYNC_COMPONENTS_H + +#include "../../base_level/base/pfx_common.h" + +//J スレッド間の同期をとるための同期コンポネント +//E Components for threads sychronization +namespace sce { +namespace PhysicsEffects { + +class PfxBarrier { +public: + PfxBarrier() {} + virtual ~PfxBarrier() {} + + virtual void sync() = 0; + virtual void setMaxCount(int n) = 0; + virtual int getMaxCount() = 0; +}; + +class PfxCriticalSection { +public: + PfxCriticalSection() {} + virtual ~PfxCriticalSection() {} + +PfxUInt32 m_commonBuff[32]; + + virtual PfxUInt32 getSharedParam(int i) = 0; + virtual void setSharedParam(int i,PfxUInt32 p) = 0; + + virtual void lock() = 0; + virtual void unlock() = 0; +}; + +} //namespace PhysicsEffects +} //namespace sce +#endif // _SCE_PFX_SYNC_COMPONENTS_H diff --git a/Extras/PhysicsEffects/include/physics_effects/low_level/task/pfx_task_manager.h b/Extras/PhysicsEffects/include/physics_effects/low_level/task/pfx_task_manager.h new file mode 100644 index 0000000..5f398c1 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/low_level/task/pfx_task_manager.h @@ -0,0 +1,96 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_TASK_MANAGER_H +#define _SCE_PFX_TASK_MANAGER_H + +#include "../../base_level/base/pfx_common.h" +#include "../../base_level/base/pfx_heap_manager.h" +#include "pfx_sync_components.h" + +#define SCE_PFX_IO_BUFF_BYTES 1048576 +namespace sce { +namespace PhysicsEffects { + +//J 並列処理するためのタスクマネージャクラス +//E Task manager class for parallel computation + +struct PfxTaskArg +{ + int taskId; + int maxTasks; + PfxBarrier *barrier; + PfxCriticalSection *criticalSection; + void *io; + PfxUInt32 data[4]; +}; + +typedef void (*PfxTaskEntry)(PfxTaskArg *arg); + +class PfxTaskManager +{ +protected: + PfxUInt32 m_numTasks; + PfxUInt32 m_maxTasks; + SCE_PFX_PADDING(1,4) + PfxUInt8 SCE_PFX_ALIGNED(16) m_ioBuff[SCE_PFX_IO_BUFF_BYTES]; + PfxHeapManager m_pool; + PfxHeapManager m_ioPool; + PfxTaskEntry m_taskEntry; + PfxTaskArg *m_taskArg; + SCE_PFX_PADDING(2,8) + + PfxTaskManager() : m_pool(NULL,0),m_ioPool(NULL,0) {} + +public: + void *allocate(size_t bytes) {return m_ioPool.allocate(bytes);} + void deallocate(void *p) {m_ioPool.deallocate(p);} + void clearPool() {m_ioPool.clear();} + + virtual PfxUInt32 getSharedParam(int i) = 0; + virtual void setSharedParam(int i,PfxUInt32 p) = 0; + + virtual void startTask(int taskId,void *io,PfxUInt32 data1,PfxUInt32 data2,PfxUInt32 data3,PfxUInt32 data4) = 0; + virtual void waitTask(int &taskId,PfxUInt32 &data1,PfxUInt32 &data2,PfxUInt32 &data3,PfxUInt32 &data4) = 0; + + virtual void setTaskEntry(void *entry) {m_taskEntry = (PfxTaskEntry)entry;} + +public: + PfxTaskManager(PfxUInt32 numTasks,PfxUInt32 maxTasks,void *workBuff,PfxUInt32 workBytes) + : m_pool((unsigned char*)workBuff,workBytes),m_ioPool(m_ioBuff,SCE_PFX_IO_BUFF_BYTES) + { + SCE_PFX_ASSERT(numTasks>0); + SCE_PFX_ASSERT(numTasks<=maxTasks); + m_numTasks = numTasks; + m_maxTasks = maxTasks; + m_taskArg = (PfxTaskArg*)m_pool.allocate(sizeof(PfxTaskArg)*m_maxTasks); + } + + virtual ~PfxTaskManager() + { + m_pool.clear(); + } + + virtual PfxUInt32 getNumTasks() const {return m_numTasks;} + virtual void setNumTasks(PfxUInt32 tasks) {m_numTasks = SCE_PFX_MIN(tasks,m_maxTasks);} + + virtual void initialize() = 0; + virtual void finalize() = 0; +}; + +} //namespace PhysicsEffects +} //namespace sce +#endif // _SCE_PFX_TASK_MANAGER_H \ No newline at end of file diff --git a/Extras/PhysicsEffects/include/physics_effects/util/pfx_mass.h b/Extras/PhysicsEffects/include/physics_effects/util/pfx_mass.h new file mode 100644 index 0000000..14d70d4 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/util/pfx_mass.h @@ -0,0 +1,60 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +/////////////////////////////////////////////////////////////////////////////// +//E Mass , Inertia tensor calculation +//J 質量・慣性テンソルの算出 + +#ifndef _SCE_PFX_MASS_H +#define _SCE_PFX_MASS_H + +#include "../base_level/base/pfx_common.h" + +namespace sce { +namespace PhysicsEffects { + +// Box +PfxFloat pfxCalcMassBox(PfxFloat density,const PfxVector3 &halfExtent); +PfxMatrix3 pfxCalcInertiaBox(const PfxVector3 &halfExtent,PfxFloat mass); + +// Sphere +PfxFloat pfxCalcMassSphere(PfxFloat density,PfxFloat radius); +PfxMatrix3 pfxCalcInertiaSphere(PfxFloat radius,PfxFloat mass); + +// Cylinder +PfxFloat pfxCalcMassCylinder(PfxFloat density,PfxFloat halfLength,PfxFloat radius); +PfxMatrix3 pfxCalcInertiaCylinderX(PfxFloat halfLength,PfxFloat radius,PfxFloat mass); +PfxMatrix3 pfxCalcInertiaCylinderY(PfxFloat halfLength,PfxFloat radius,PfxFloat mass); +PfxMatrix3 pfxCalcInertiaCylinderZ(PfxFloat halfLength,PfxFloat radius,PfxFloat mass); + +/////////////////////////////////////////////////////////////////////////////// +//E Mass convertion +//J 質量の移動・回転・合成 + +// translation +//E returns translated inertia tensor +//J 移動後の慣性テンソルを返します +PfxMatrix3 pfxMassTranslate(PfxFloat mass,const PfxMatrix3 &inertia,const PfxVector3 &translation); + +// rotation +//E returns rotated inertia tensor +//J 回転後の慣性テンソルを返します +PfxMatrix3 pfxMassRotate(const PfxMatrix3 &inertia,const PfxMatrix3 &rotate); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_MASS_H diff --git a/Extras/PhysicsEffects/include/physics_effects/util/pfx_mesh_creator.h b/Extras/PhysicsEffects/include/physics_effects/util/pfx_mesh_creator.h new file mode 100644 index 0000000..f481dd1 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/util/pfx_mesh_creator.h @@ -0,0 +1,96 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_MESH_CREATOR_H +#define _SCE_PFX_MESH_CREATOR_H + +#include "../base_level/collision/pfx_large_tri_mesh.h" + +namespace sce { +namespace PhysicsEffects { + +//J フラグに指定する値 +//E Specify these values to a flag parameter +#define SCE_PFX_MESH_FLAG_NORMAL_FLIP 0x01 +#define SCE_PFX_MESH_FLAG_16BIT_INDEX 0x02 +#define SCE_PFX_MESH_FLAG_32BIT_INDEX 0x04 +#define SCE_PFX_MESH_FLAG_AUTO_ELIMINATION 0x08 +#define SCE_PFX_MESH_FLAG_AUTO_THICKNESS 0x10 + +/////////////////////////////////////////////////////////////////////////////// +// Convex Mesh + +struct PfxCreateConvexMeshParam { + PfxUInt32 flag; + PfxFloat *verts; + PfxUInt32 numVerts; + void *triangles; + PfxUInt32 numTriangles; + PfxUInt32 vertexStrideBytes; + PfxUInt32 triangleStrideBytes; + + PfxCreateConvexMeshParam() + { + flag = SCE_PFX_MESH_FLAG_16BIT_INDEX|SCE_PFX_MESH_FLAG_AUTO_ELIMINATION; + verts = NULL; + triangles = NULL; + numVerts = 0; + numTriangles = 0; + vertexStrideBytes = sizeof(PfxFloat)*3; + triangleStrideBytes = sizeof(PfxUInt16)*3; + } +}; + +PfxInt32 pfxCreateConvexMesh(PfxConvexMesh &convex,const PfxCreateConvexMeshParam ¶m); + +/////////////////////////////////////////////////////////////////////////////// +// Large Mesh + +struct PfxCreateLargeTriMeshParam { + PfxUInt32 flag; + PfxFloat *verts; + PfxUInt32 numVerts; + void *triangles; + PfxUInt32 numTriangles; + PfxUInt32 vertexStrideBytes; + PfxUInt32 triangleStrideBytes; + PfxUInt32 numFacetsLimit; + PfxFloat islandsRatio; + PfxFloat defaultThickness; + + PfxCreateLargeTriMeshParam() + { + flag = SCE_PFX_MESH_FLAG_16BIT_INDEX|SCE_PFX_MESH_FLAG_AUTO_ELIMINATION; + verts = NULL; + triangles = NULL; + numVerts = 0; + numTriangles = 0; + vertexStrideBytes = sizeof(PfxFloat)*3; + triangleStrideBytes = sizeof(PfxUInt16)*3; + numFacetsLimit = 15; + islandsRatio = 0.2f; + defaultThickness = 0.025f; + } +}; + +PfxInt32 pfxCreateLargeTriMesh(PfxLargeTriMesh &lmesh,const PfxCreateLargeTriMeshParam ¶m); + +void pfxReleaseLargeTriMesh(PfxLargeTriMesh &lmesh); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_MESH_CREATOR_H diff --git a/Extras/PhysicsEffects/include/physics_effects/util/pfx_util_include.h b/Extras/PhysicsEffects/include/physics_effects/util/pfx_util_include.h new file mode 100644 index 0000000..0e637b2 --- /dev/null +++ b/Extras/PhysicsEffects/include/physics_effects/util/pfx_util_include.h @@ -0,0 +1,26 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_UTIL_INCLUDE_H +#define _SCE_PFX_UTIL_INCLUDE_H + +/////////////////////////////////////////////////////////////////////////////// +// Physics Effects Utility Headers + +#include "pfx_mass.h" +#include "pfx_mesh_creator.h" + +#endif // _SCE_PFX_UTIL_INCLUDE_H diff --git a/Extras/PhysicsEffects/include/vecmath/neon/boolInVec.h b/Extras/PhysicsEffects/include/vecmath/neon/boolInVec.h new file mode 100644 index 0000000..7ea380f --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/neon/boolInVec.h @@ -0,0 +1,238 @@ +/* + Copyright (C) 2006-2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _BOOLINVEC_SCALAR_H +#define _BOOLINVEC_SCALAR_H + +#include +namespace Vectormath { + +class floatInVec; + +//-------------------------------------------------------------------------------------------------- +// boolInVec class +// + +class boolInVec +{ +private: + unsigned int mData; + +public: + // Default constructor; does no initialization + // + inline boolInVec( ) { }; + + // Construct from a value converted from float + // + inline boolInVec(floatInVec vec); + + // Explicit cast from bool + // + explicit inline boolInVec(bool scalar); + + // Explicit cast to bool + // + inline bool getAsBool() const; + +#ifndef _VECTORMATH_NO_SCALAR_CAST + // Implicit cast to bool + // + inline operator bool() const; +#endif + + // Boolean negation operator + // + inline const boolInVec operator ! () const; + + // Assignment operator + // + inline boolInVec& operator = (boolInVec vec); + + // Boolean and assignment operator + // + inline boolInVec& operator &= (boolInVec vec); + + // Boolean exclusive or assignment operator + // + inline boolInVec& operator ^= (boolInVec vec); + + // Boolean or assignment operator + // + inline boolInVec& operator |= (boolInVec vec); + +}; + +// Equal operator +// +inline const boolInVec operator == (boolInVec vec0, boolInVec vec1); + +// Not equal operator +// +inline const boolInVec operator != (boolInVec vec0, boolInVec vec1); + +// And operator +// +inline const boolInVec operator & (boolInVec vec0, boolInVec vec1); + +// Exclusive or operator +// +inline const boolInVec operator ^ (boolInVec vec0, boolInVec vec1); + +// Or operator +// +inline const boolInVec operator | (boolInVec vec0, boolInVec vec1); + +// Conditionally select between two values +// +inline const boolInVec select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1); + + +} // namespace Vectormath + + +//-------------------------------------------------------------------------------------------------- +// boolInVec implementation +// + +#include "floatInVec.h" + +namespace Vectormath { + +inline +boolInVec::boolInVec(floatInVec vec) +{ + *this = (vec != floatInVec(0.0f)); +} + +inline +boolInVec::boolInVec(bool scalar) +{ + mData = -(int)scalar; +} + +inline +bool +boolInVec::getAsBool() const +{ + return (mData > 0); +} + +#ifndef _VECTORMATH_NO_SCALAR_CAST +inline +boolInVec::operator bool() const +{ + return getAsBool(); +} +#endif + +inline +const boolInVec +boolInVec::operator ! () const +{ + return boolInVec(!mData); +} + +inline +boolInVec& +boolInVec::operator = (boolInVec vec) +{ + mData = vec.mData; + return *this; +} + +inline +boolInVec& +boolInVec::operator &= (boolInVec vec) +{ + *this = *this & vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator ^= (boolInVec vec) +{ + *this = *this ^ vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator |= (boolInVec vec) +{ + *this = *this | vec; + return *this; +} + +inline +const boolInVec +operator == (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() == vec1.getAsBool()); +} + +inline +const boolInVec +operator != (boolInVec vec0, boolInVec vec1) +{ + return !(vec0 == vec1); +} + +inline +const boolInVec +operator & (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() & vec1.getAsBool()); +} + +inline +const boolInVec +operator | (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() | vec1.getAsBool()); +} + +inline +const boolInVec +operator ^ (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() ^ vec1.getAsBool()); +} + +inline +const boolInVec +select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1) +{ + return (select_vec1.getAsBool() == 0) ? vec0 : vec1; +} + +} // namespace Vectormath + +#endif // boolInVec_h diff --git a/Extras/PhysicsEffects/include/vecmath/neon/floatInVec.h b/Extras/PhysicsEffects/include/vecmath/neon/floatInVec.h new file mode 100644 index 0000000..1aa2ee1 --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/neon/floatInVec.h @@ -0,0 +1,357 @@ +/* + Copyright (C) 2006-2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _FLOATINVEC__SCALAR_H +#define _FLOATINVEC__SCALAR_H + +#include +namespace Vectormath { + +class boolInVec; + +//-------------------------------------------------------------------------------------------------- +// floatInVec class +// + +// A class representing a scalar float value contained in a vector register +// This class does not support fastmath +class floatInVec +{ +private: + float mData; + +public: + // Default constructor; does no initialization + // + inline floatInVec( ) { }; + + // Construct from a value converted from bool + // + inline floatInVec(boolInVec vec); + + // Explicit cast from float + // + explicit inline floatInVec(float scalar); + + // Explicit cast to float + // + inline float getAsFloat() const; + +#ifndef _VECTORMATH_NO_SCALAR_CAST + // Implicit cast to float + // + inline operator float() const; +#endif + + // Post increment (add 1.0f) + // + inline const floatInVec operator ++ (int); + + // Post decrement (subtract 1.0f) + // + inline const floatInVec operator -- (int); + + // Pre increment (add 1.0f) + // + inline floatInVec& operator ++ (); + + // Pre decrement (subtract 1.0f) + // + inline floatInVec& operator -- (); + + // Negation operator + // + inline const floatInVec operator - () const; + + // Assignment operator + // + inline floatInVec& operator = (floatInVec vec); + + // Multiplication assignment operator + // + inline floatInVec& operator *= (floatInVec vec); + + // Division assignment operator + // + inline floatInVec& operator /= (floatInVec vec); + + // Addition assignment operator + // + inline floatInVec& operator += (floatInVec vec); + + // Subtraction assignment operator + // + inline floatInVec& operator -= (floatInVec vec); + +}; + +// Multiplication operator +// +inline const floatInVec operator * (floatInVec vec0, floatInVec vec1); + +// Division operator +// +inline const floatInVec operator / (floatInVec vec0, floatInVec vec1); + +// Addition operator +// +inline const floatInVec operator + (floatInVec vec0, floatInVec vec1); + +// Subtraction operator +// +inline const floatInVec operator - (floatInVec vec0, floatInVec vec1); + +// Less than operator +// +inline const boolInVec operator < (floatInVec vec0, floatInVec vec1); + +// Less than or equal operator +// +inline const boolInVec operator <= (floatInVec vec0, floatInVec vec1); + +// Greater than operator +// +inline const boolInVec operator > (floatInVec vec0, floatInVec vec1); + +// Greater than or equal operator +// +inline const boolInVec operator >= (floatInVec vec0, floatInVec vec1); + +// Equal operator +// +inline const boolInVec operator == (floatInVec vec0, floatInVec vec1); + +// Not equal operator +// +inline const boolInVec operator != (floatInVec vec0, floatInVec vec1); + +// Conditionally select between two values +// +inline const floatInVec select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1); + + +} // namespace Vectormath + + +//-------------------------------------------------------------------------------------------------- +// floatInVec implementation +// + +#include "boolInVec.h" + +namespace Vectormath { + +inline +floatInVec::floatInVec(boolInVec vec) +{ + mData = float(vec.getAsBool()); +} + +inline +floatInVec::floatInVec(float scalar) +{ + mData = scalar; +} + +inline +float +floatInVec::getAsFloat() const +{ + return mData; +} + +#ifndef _VECTORMATH_NO_SCALAR_CAST +inline +floatInVec::operator float() const +{ + return getAsFloat(); +} +#endif + +inline +const floatInVec +floatInVec::operator ++ (int) +{ + float olddata = mData; + operator ++(); + return floatInVec(olddata); +} + +inline +const floatInVec +floatInVec::operator -- (int) +{ + float olddata = mData; + operator --(); + return floatInVec(olddata); +} + +inline +floatInVec& +floatInVec::operator ++ () +{ + *this += floatInVec(1.0f); + return *this; +} + +inline +floatInVec& +floatInVec::operator -- () +{ + *this -= floatInVec(1.0f); + return *this; +} + +inline +const floatInVec +floatInVec::operator - () const +{ + return floatInVec(-mData); +} + +inline +floatInVec& +floatInVec::operator = (floatInVec vec) +{ + mData = vec.mData; + return *this; +} + +inline +floatInVec& +floatInVec::operator *= (floatInVec vec) +{ + *this = *this * vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator /= (floatInVec vec) +{ + *this = *this / vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator += (floatInVec vec) +{ + *this = *this + vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator -= (floatInVec vec) +{ + *this = *this - vec; + return *this; +} + +inline +const floatInVec +operator * (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() * vec1.getAsFloat()); +} + +inline +const floatInVec +operator / (floatInVec num, floatInVec den) +{ + return floatInVec(num.getAsFloat() / den.getAsFloat()); +} + +inline +const floatInVec +operator + (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() + vec1.getAsFloat()); +} + +inline +const floatInVec +operator - (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() - vec1.getAsFloat()); +} + +inline +const boolInVec +operator < (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() < vec1.getAsFloat()); +} + +inline +const boolInVec +operator <= (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 > vec1); +} + +inline +const boolInVec +operator > (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() > vec1.getAsFloat()); +} + +inline +const boolInVec +operator >= (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 < vec1); +} + +inline +const boolInVec +operator == (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() == vec1.getAsFloat()); +} + +inline +const boolInVec +operator != (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 == vec1); +} + +inline +const floatInVec +select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1) +{ + return (select_vec1.getAsBool() == 0) ? vec0 : vec1; +} + +} // namespace Vectormath + +#endif // floatInVec_h diff --git a/Extras/PhysicsEffects/include/vecmath/neon/mat_aos.h b/Extras/PhysicsEffects/include/vecmath/neon/mat_aos.h new file mode 100644 index 0000000..32a6bbe --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/neon/mat_aos.h @@ -0,0 +1,1645 @@ +/* + Copyright (C) 2006-2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_AOS_CPP__SCALAR_H +#define _VECTORMATH_MAT_AOS_CPP__SCALAR_H + +// ARA begin insert new code +#include "vectormath_neon_assembly_prototypes.h" +// ARA end + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// Constants + +#define _VECTORMATH_PI_OVER_2 1.570796327f + +//----------------------------------------------------------------------------- +// Definitions + +inline Matrix3::Matrix3( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; +} + +inline Matrix3::Matrix3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +inline Matrix3::Matrix3( const Quat & unitQuat ) +{ + float qx, qy, qz, qw, qx2, qy2, qz2, qxqx2, qyqy2, qzqz2, qxqy2, qyqz2, qzqw2, qxqz2, qyqw2, qxqw2; + qx = unitQuat.getX(); + qy = unitQuat.getY(); + qz = unitQuat.getZ(); + qw = unitQuat.getW(); + qx2 = ( qx + qx ); + qy2 = ( qy + qy ); + qz2 = ( qz + qz ); + qxqx2 = ( qx * qx2 ); + qxqy2 = ( qx * qy2 ); + qxqz2 = ( qx * qz2 ); + qxqw2 = ( qw * qx2 ); + qyqy2 = ( qy * qy2 ); + qyqz2 = ( qy * qz2 ); + qyqw2 = ( qw * qy2 ); + qzqz2 = ( qz * qz2 ); + qzqw2 = ( qw * qz2 ); + mCol0 = Vector3( ( ( 1.0f - qyqy2 ) - qzqz2 ), ( qxqy2 + qzqw2 ), ( qxqz2 - qyqw2 ) ); + mCol1 = Vector3( ( qxqy2 - qzqw2 ), ( ( 1.0f - qxqx2 ) - qzqz2 ), ( qyqz2 + qxqw2 ) ); + mCol2 = Vector3( ( qxqz2 + qyqw2 ), ( qyqz2 - qxqw2 ), ( ( 1.0f - qxqx2 ) - qyqy2 ) ); +} + +inline Matrix3::Matrix3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; +} + +inline Matrix3 & Matrix3::setCol0( const Vector3 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix3 & Matrix3::setCol1( const Vector3 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix3 & Matrix3::setCol2( const Vector3 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix3 & Matrix3::setCol( int col, const Vector3 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix3 & Matrix3::setRow( int row, const Vector3 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + return *this; +} + +inline Matrix3 & Matrix3::setElem( int col, int row, float val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Matrix3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Matrix3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Matrix3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Matrix3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Matrix3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::getRow( int row ) const +{ + return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); +} + +inline Vector3 & Matrix3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix3 & Matrix3::operator =( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + return *this; +} + +inline const Matrix3 transpose( const Matrix3 & mat ) +{ + return Matrix3( + Vector3( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX() ), + Vector3( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY() ), + Vector3( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ() ) + ); +} + +inline const Matrix3 inverse( const Matrix3 & mat ) +{ + Vector3 tmp0, tmp1, tmp2; + float detinv; + tmp0 = cross( mat.getCol1(), mat.getCol2() ); + tmp1 = cross( mat.getCol2(), mat.getCol0() ); + tmp2 = cross( mat.getCol0(), mat.getCol1() ); + detinv = ( 1.0f / dot( mat.getCol2(), tmp2 ) ); + return Matrix3( + Vector3( ( tmp0.getX() * detinv ), ( tmp1.getX() * detinv ), ( tmp2.getX() * detinv ) ), + Vector3( ( tmp0.getY() * detinv ), ( tmp1.getY() * detinv ), ( tmp2.getY() * detinv ) ), + Vector3( ( tmp0.getZ() * detinv ), ( tmp1.getZ() * detinv ), ( tmp2.getZ() * detinv ) ) + ); +} + +inline float determinant( const Matrix3 & mat ) +{ + return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); +} + +inline const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ) + ); +} + +inline const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix3 Matrix3::operator -( ) const +{ + return Matrix3( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ) + ); +} + +inline const Matrix3 absPerElem( const Matrix3 & mat ) +{ + return Matrix3( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::operator *( float scalar ) const +{ + return Matrix3( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ) + ); +} + +inline Matrix3 & Matrix3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix3 operator *( float scalar, const Matrix3 & mat ) +{ + return mat * scalar; +} + +inline const Vector3 Matrix3::operator *( const Vector3 & vec ) const +{ + return Vector3( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ); +} + +// ARA begin insert new code +inline const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const +{ + Matrix3 __attribute__((__aligned__((64)))) result; + pfxMatrix3Matrix3ProductNEON(*this, mat, result); + return(result); +} +// ARA end + +// ARA begin insert new code +inline Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) +{ + pfxMatrix3Matrix3ProductNEON(*this, mat, *this); + return *this; +} +// ARA end + +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) +{ + return Matrix3( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::identity( ) +{ + return Matrix3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3::xAxis( ), + Vector3( 0.0f, c, s ), + Vector3( 0.0f, -s, c ) + ); +} + +inline const Matrix3 Matrix3::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3( c, 0.0f, -s ), + Vector3::yAxis( ), + Vector3( s, 0.0f, c ) + ); +} + +inline const Matrix3 Matrix3::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3( c, s, 0.0f ), + Vector3( -s, c, 0.0f ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Matrix3( + Vector3( ( cZ * cY ), ( sZ * cY ), -sY ), + Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ), + Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( float radians, const Vector3 & unitVec ) +{ + float x, y, z, s, c, oneMinusC, xy, yz, zx; + s = sinf( radians ); + c = cosf( radians ); + x = unitVec.getX(); + y = unitVec.getY(); + z = unitVec.getZ(); + xy = ( x * y ); + yz = ( y * z ); + zx = ( z * x ); + oneMinusC = ( 1.0f - c ); + return Matrix3( + Vector3( ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ) ), + Vector3( ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ) ), + Vector3( ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( const Quat & unitQuat ) +{ + return Matrix3( unitQuat ); +} + +inline const Matrix3 Matrix3::scale( const Vector3 & scaleVec ) +{ + return Matrix3( + Vector3( scaleVec.getX(), 0.0f, 0.0f ), + Vector3( 0.0f, scaleVec.getY(), 0.0f ), + Vector3( 0.0f, 0.0f, scaleVec.getZ() ) + ); +} + +inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ) +{ + return Matrix3( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ) + ); +} + +inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ) +{ + return Matrix3( + mulPerElem( mat.getCol0(), scaleVec ), + mulPerElem( mat.getCol1(), scaleVec ), + mulPerElem( mat.getCol2(), scaleVec ) + ); +} + +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix3 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); +} + +inline void print( const Matrix3 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Matrix4::Matrix4( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; +} + +inline Matrix4::Matrix4( float scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +inline Matrix4::Matrix4( const Transform3 & mat ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( mat.getCol3(), 1.0f ); +} + +inline Matrix4::Matrix4( const Vector4 & _col0, const Vector4 & _col1, const Vector4 & _col2, const Vector4 & _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Matrix4::Matrix4( const Matrix3 & mat, const Vector3 & translateVec ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +inline Matrix4::Matrix4( const Quat & unitQuat, const Vector3 & translateVec ) +{ + Matrix3 mat; + mat = Matrix3( unitQuat ); + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +inline Matrix4 & Matrix4::setCol0( const Vector4 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix4 & Matrix4::setCol1( const Vector4 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix4 & Matrix4::setCol2( const Vector4 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix4 & Matrix4::setCol3( const Vector4 & _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Matrix4 & Matrix4::setCol( int col, const Vector4 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix4 & Matrix4::setRow( int row, const Vector4 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Matrix4 & Matrix4::setElem( int col, int row, float val ) +{ + Vector4 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Matrix4::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector4 Matrix4::getCol0( ) const +{ + return mCol0; +} + +inline const Vector4 Matrix4::getCol1( ) const +{ + return mCol1; +} + +inline const Vector4 Matrix4::getCol2( ) const +{ + return mCol2; +} + +inline const Vector4 Matrix4::getCol3( ) const +{ + return mCol3; +} + +inline const Vector4 Matrix4::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector4 & Matrix4::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix4 & Matrix4::operator =( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; + return *this; +} + +inline const Matrix4 transpose( const Matrix4 & mat ) +{ + return Matrix4( + Vector4( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX(), mat.getCol3().getX() ), + Vector4( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY(), mat.getCol3().getY() ), + Vector4( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ(), mat.getCol3().getZ() ), + Vector4( mat.getCol0().getW(), mat.getCol1().getW(), mat.getCol2().getW(), mat.getCol3().getW() ) + ); +} + +inline const Matrix4 inverse( const Matrix4 & mat ) +{ + Vector4 res0, res1, res2, res3; + float mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, detInv; + mA = mat.getCol0().getX(); + mB = mat.getCol0().getY(); + mC = mat.getCol0().getZ(); + mD = mat.getCol0().getW(); + mE = mat.getCol1().getX(); + mF = mat.getCol1().getY(); + mG = mat.getCol1().getZ(); + mH = mat.getCol1().getW(); + mI = mat.getCol2().getX(); + mJ = mat.getCol2().getY(); + mK = mat.getCol2().getZ(); + mL = mat.getCol2().getW(); + mM = mat.getCol3().getX(); + mN = mat.getCol3().getY(); + mO = mat.getCol3().getZ(); + mP = mat.getCol3().getW(); + tmp0 = ( ( mK * mD ) - ( mC * mL ) ); + tmp1 = ( ( mO * mH ) - ( mG * mP ) ); + tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); + tmp3 = ( ( mF * mO ) - ( mN * mG ) ); + tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); + tmp5 = ( ( mN * mH ) - ( mF * mP ) ); + res0.setX( ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ) ); + res0.setY( ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ) ); + res0.setZ( ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ) ); + res0.setW( ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ) ); + detInv = ( 1.0f / ( ( ( ( mA * res0.getX() ) + ( mE * res0.getY() ) ) + ( mI * res0.getZ() ) ) + ( mM * res0.getW() ) ) ); + res1.setX( ( mI * tmp1 ) ); + res1.setY( ( mM * tmp0 ) ); + res1.setZ( ( mA * tmp1 ) ); + res1.setW( ( mE * tmp0 ) ); + res3.setX( ( mI * tmp3 ) ); + res3.setY( ( mM * tmp2 ) ); + res3.setZ( ( mA * tmp3 ) ); + res3.setW( ( mE * tmp2 ) ); + res2.setX( ( mI * tmp5 ) ); + res2.setY( ( mM * tmp4 ) ); + res2.setZ( ( mA * tmp5 ) ); + res2.setW( ( mE * tmp4 ) ); + tmp0 = ( ( mI * mB ) - ( mA * mJ ) ); + tmp1 = ( ( mM * mF ) - ( mE * mN ) ); + tmp2 = ( ( mI * mD ) - ( mA * mL ) ); + tmp3 = ( ( mM * mH ) - ( mE * mP ) ); + tmp4 = ( ( mI * mC ) - ( mA * mK ) ); + tmp5 = ( ( mM * mG ) - ( mE * mO ) ); + res2.setX( ( ( ( mL * tmp1 ) - ( mJ * tmp3 ) ) + res2.getX() ) ); + res2.setY( ( ( ( mP * tmp0 ) - ( mN * tmp2 ) ) + res2.getY() ) ); + res2.setZ( ( ( ( mB * tmp3 ) - ( mD * tmp1 ) ) - res2.getZ() ) ); + res2.setW( ( ( ( mF * tmp2 ) - ( mH * tmp0 ) ) - res2.getW() ) ); + res3.setX( ( ( ( mJ * tmp5 ) - ( mK * tmp1 ) ) + res3.getX() ) ); + res3.setY( ( ( ( mN * tmp4 ) - ( mO * tmp0 ) ) + res3.getY() ) ); + res3.setZ( ( ( ( mC * tmp1 ) - ( mB * tmp5 ) ) - res3.getZ() ) ); + res3.setW( ( ( ( mG * tmp0 ) - ( mF * tmp4 ) ) - res3.getW() ) ); + res1.setX( ( ( ( mK * tmp3 ) - ( mL * tmp5 ) ) - res1.getX() ) ); + res1.setY( ( ( ( mO * tmp2 ) - ( mP * tmp4 ) ) - res1.getY() ) ); + res1.setZ( ( ( ( mD * tmp5 ) - ( mC * tmp3 ) ) + res1.getZ() ) ); + res1.setW( ( ( ( mH * tmp4 ) - ( mG * tmp2 ) ) + res1.getW() ) ); + return Matrix4( + ( res0 * detInv ), + ( res1 * detInv ), + ( res2 * detInv ), + ( res3 * detInv ) + ); +} + +inline const Matrix4 affineInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( inverse( affineMat ) ); +} + +inline const Matrix4 orthoInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( orthoInverse( affineMat ) ); +} + +inline float determinant( const Matrix4 & mat ) +{ + float dx, dy, dz, dw, mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + mA = mat.getCol0().getX(); + mB = mat.getCol0().getY(); + mC = mat.getCol0().getZ(); + mD = mat.getCol0().getW(); + mE = mat.getCol1().getX(); + mF = mat.getCol1().getY(); + mG = mat.getCol1().getZ(); + mH = mat.getCol1().getW(); + mI = mat.getCol2().getX(); + mJ = mat.getCol2().getY(); + mK = mat.getCol2().getZ(); + mL = mat.getCol2().getW(); + mM = mat.getCol3().getX(); + mN = mat.getCol3().getY(); + mO = mat.getCol3().getZ(); + mP = mat.getCol3().getW(); + tmp0 = ( ( mK * mD ) - ( mC * mL ) ); + tmp1 = ( ( mO * mH ) - ( mG * mP ) ); + tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); + tmp3 = ( ( mF * mO ) - ( mN * mG ) ); + tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); + tmp5 = ( ( mN * mH ) - ( mF * mP ) ); + dx = ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ); + dy = ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ); + dz = ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ); + dw = ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ); + return ( ( ( ( mA * dx ) + ( mE * dy ) ) + ( mI * dz ) ) + ( mM * dw ) ); +} + +inline const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ), + ( mCol3 + mat.mCol3 ) + ); +} + +inline const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ), + ( mCol3 - mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix4 Matrix4::operator -( ) const +{ + return Matrix4( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ), + ( -mCol3 ) + ); +} + +inline const Matrix4 absPerElem( const Matrix4 & mat ) +{ + return Matrix4( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ), + absPerElem( mat.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::operator *( float scalar ) const +{ + return Matrix4( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ), + ( mCol3 * scalar ) + ); +} + +inline Matrix4 & Matrix4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix4 operator *( float scalar, const Matrix4 & mat ) +{ + return mat * scalar; +} + +inline const Vector4 Matrix4::operator *( const Vector4 & vec ) const +{ + return Vector4( + ( ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ) + ( mCol3.getX() * vec.getW() ) ), + ( ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ) + ( mCol3.getY() * vec.getW() ) ), + ( ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ( mCol3.getZ() * vec.getW() ) ), + ( ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) + ( mCol3.getW() * vec.getW() ) ) + ); +} + +inline const Vector4 Matrix4::operator *( const Vector3 & vec ) const +{ + return Vector4( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ), + ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) + ); +} + +inline const Vector4 Matrix4::operator *( const Point3 & pnt ) const +{ + return Vector4( + ( ( ( ( mCol0.getX() * pnt.getX() ) + ( mCol1.getX() * pnt.getY() ) ) + ( mCol2.getX() * pnt.getZ() ) ) + mCol3.getX() ), + ( ( ( ( mCol0.getY() * pnt.getX() ) + ( mCol1.getY() * pnt.getY() ) ) + ( mCol2.getY() * pnt.getZ() ) ) + mCol3.getY() ), + ( ( ( ( mCol0.getZ() * pnt.getX() ) + ( mCol1.getZ() * pnt.getY() ) ) + ( mCol2.getZ() * pnt.getZ() ) ) + mCol3.getZ() ), + ( ( ( ( mCol0.getW() * pnt.getX() ) + ( mCol1.getW() * pnt.getY() ) ) + ( mCol2.getW() * pnt.getZ() ) ) + mCol3.getW() ) + ); +} + +// ARA begin insert new code +inline const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const +{ + Matrix4 __attribute__((__aligned__((64)))) result; + pfxMatrix4Matrix4ProductNEON(*this, mat, result); + return(result); +} +// ARA end + +// ARA begin insert new code +inline Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) +{ + pfxMatrix4Matrix4ProductNEON(*this, mat, *this); + return *this; +} +// ARA end + +inline const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const +{ + return Matrix4( + ( *this * tfrm.getCol0() ), + ( *this * tfrm.getCol1() ), + ( *this * tfrm.getCol2() ), + ( *this * Point3( tfrm.getCol3() ) ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) +{ + return Matrix4( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ), + mulPerElem( mat0.getCol3(), mat1.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::identity( ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) +{ + mCol0.setXYZ( mat3.getCol0() ); + mCol1.setXYZ( mat3.getCol1() ); + mCol2.setXYZ( mat3.getCol2() ); + return *this; +} + +inline const Matrix3 Matrix4::getUpper3x3( ) const +{ + return Matrix3( + mCol0.getXYZ( ), + mCol1.getXYZ( ), + mCol2.getXYZ( ) + ); +} + +inline Matrix4 & Matrix4::setTranslation( const Vector3 & translateVec ) +{ + mCol3.setXYZ( translateVec ); + return *this; +} + +inline const Vector3 Matrix4::getTranslation( ) const +{ + return mCol3.getXYZ( ); +} + +inline const Matrix4 Matrix4::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4::xAxis( ), + Vector4( 0.0f, c, s, 0.0f ), + Vector4( 0.0f, -s, c, 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4( c, 0.0f, -s, 0.0f ), + Vector4::yAxis( ), + Vector4( s, 0.0f, c, 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4( c, s, 0.0f, 0.0f ), + Vector4( -s, c, 0.0f, 0.0f ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Matrix4( + Vector4( ( cZ * cY ), ( sZ * cY ), -sY, 0.0f ), + Vector4( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ), 0.0f ), + Vector4( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( float radians, const Vector3 & unitVec ) +{ + float x, y, z, s, c, oneMinusC, xy, yz, zx; + s = sinf( radians ); + c = cosf( radians ); + x = unitVec.getX(); + y = unitVec.getY(); + z = unitVec.getZ(); + xy = ( x * y ); + yz = ( y * z ); + zx = ( z * x ); + oneMinusC = ( 1.0f - c ); + return Matrix4( + Vector4( ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ), 0.0f ), + Vector4( ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ), 0.0f ), + Vector4( ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( const Quat & unitQuat ) +{ + return Matrix4( Transform3::rotation( unitQuat ) ); +} + +inline const Matrix4 Matrix4::scale( const Vector3 & scaleVec ) +{ + return Matrix4( + Vector4( scaleVec.getX(), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, scaleVec.getY(), 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, scaleVec.getZ(), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ) +{ + return Matrix4( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ), + mat.getCol3() + ); +} + +inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ) +{ + Vector4 scale4; + scale4 = Vector4( scaleVec, 1.0f ); + return Matrix4( + mulPerElem( mat.getCol0(), scale4 ), + mulPerElem( mat.getCol1(), scale4 ), + mulPerElem( mat.getCol2(), scale4 ), + mulPerElem( mat.getCol3(), scale4 ) + ); +} + +inline const Matrix4 Matrix4::translation( const Vector3 & translateVec ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4( translateVec, 1.0f ) + ); +} + +inline const Matrix4 Matrix4::lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ) +{ + Matrix4 m4EyeFrame; + Vector3 v3X, v3Y, v3Z; + v3Y = normalize( upVec ); + v3Z = normalize( ( eyePos - lookAtPos ) ); + v3X = normalize( cross( v3Y, v3Z ) ); + v3Y = cross( v3Z, v3X ); + m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); + return orthoInverse( m4EyeFrame ); +} + +inline const Matrix4 Matrix4::perspective( float fovyRadians, float aspect, float zNear, float zFar ) +{ + float f, rangeInv; + f = tanf( ( (float)( _VECTORMATH_PI_OVER_2 ) - ( 0.5f * fovyRadians ) ) ); + rangeInv = ( 1.0f / ( zNear - zFar ) ); + return Matrix4( + Vector4( ( f / aspect ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, f, 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, ( ( zNear + zFar ) * rangeInv ), -1.0f ), + Vector4( 0.0f, 0.0f, ( ( ( zNear * zFar ) * rangeInv ) * 2.0f ), 0.0f ) + ); +} + +inline const Matrix4 Matrix4::frustum( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf, n2; + sum_rl = ( right + left ); + sum_tb = ( top + bottom ); + sum_nf = ( zNear + zFar ); + inv_rl = ( 1.0f / ( right - left ) ); + inv_tb = ( 1.0f / ( top - bottom ) ); + inv_nf = ( 1.0f / ( zNear - zFar ) ); + n2 = ( zNear + zNear ); + return Matrix4( + Vector4( ( n2 * inv_rl ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, ( n2 * inv_tb ), 0.0f, 0.0f ), + Vector4( ( sum_rl * inv_rl ), ( sum_tb * inv_tb ), ( sum_nf * inv_nf ), -1.0f ), + Vector4( 0.0f, 0.0f, ( ( n2 * inv_nf ) * zFar ), 0.0f ) + ); +} + +inline const Matrix4 Matrix4::orthographic( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf; + sum_rl = ( right + left ); + sum_tb = ( top + bottom ); + sum_nf = ( zNear + zFar ); + inv_rl = ( 1.0f / ( right - left ) ); + inv_tb = ( 1.0f / ( top - bottom ) ); + inv_nf = ( 1.0f / ( zNear - zFar ) ); + return Matrix4( + Vector4( ( inv_rl + inv_rl ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, ( inv_tb + inv_tb ), 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, ( inv_nf + inv_nf ), 0.0f ), + Vector4( ( -sum_rl * inv_rl ), ( -sum_tb * inv_tb ), ( sum_nf * inv_nf ), 1.0f ) + ); +} + +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix4 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); + print( mat.getRow( 3 ) ); +} + +inline void print( const Matrix4 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Transform3::Transform3( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; +} + +inline Transform3::Transform3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +inline Transform3::Transform3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2, const Vector3 & _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Transform3::Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ) +{ + this->setUpper3x3( tfrm ); + this->setTranslation( translateVec ); +} + +inline Transform3::Transform3( const Quat & unitQuat, const Vector3 & translateVec ) +{ + this->setUpper3x3( Matrix3( unitQuat ) ); + this->setTranslation( translateVec ); +} + +inline Transform3 & Transform3::setCol0( const Vector3 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Transform3 & Transform3::setCol1( const Vector3 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Transform3 & Transform3::setCol2( const Vector3 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Transform3 & Transform3::setCol3( const Vector3 & _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Transform3 & Transform3::setCol( int col, const Vector3 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Transform3 & Transform3::setRow( int row, const Vector4 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Transform3 & Transform3::setElem( int col, int row, float val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Transform3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Transform3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Transform3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Transform3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Transform3::getCol3( ) const +{ + return mCol3; +} + +inline const Vector3 Transform3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Transform3::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector3 & Transform3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Transform3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Transform3 & Transform3::operator =( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; + return *this; +} + +inline const Transform3 inverse( const Transform3 & tfrm ) +{ + Vector3 tmp0, tmp1, tmp2, inv0, inv1, inv2; + float detinv; + tmp0 = cross( tfrm.getCol1(), tfrm.getCol2() ); + tmp1 = cross( tfrm.getCol2(), tfrm.getCol0() ); + tmp2 = cross( tfrm.getCol0(), tfrm.getCol1() ); + detinv = ( 1.0f / dot( tfrm.getCol2(), tmp2 ) ); + inv0 = Vector3( ( tmp0.getX() * detinv ), ( tmp1.getX() * detinv ), ( tmp2.getX() * detinv ) ); + inv1 = Vector3( ( tmp0.getY() * detinv ), ( tmp1.getY() * detinv ), ( tmp2.getY() * detinv ) ); + inv2 = Vector3( ( tmp0.getZ() * detinv ), ( tmp1.getZ() * detinv ), ( tmp2.getZ() * detinv ) ); + return Transform3( + inv0, + inv1, + inv2, + Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) + ); +} + +// ARA begin insert new code +inline const Transform3 orthoInverse( const Transform3 & tfrm ) +{ + Transform3 __attribute__((__aligned__((64)))) result; + pfxTransform3OrthoInverseNEON(tfrm, result); + return(result); +} +// ARA end + +inline const Transform3 absPerElem( const Transform3 & tfrm ) +{ + return Transform3( + absPerElem( tfrm.getCol0() ), + absPerElem( tfrm.getCol1() ), + absPerElem( tfrm.getCol2() ), + absPerElem( tfrm.getCol3() ) + ); +} + +// ARA begin insert new code +inline const Vector3 Transform3::operator *( const Vector3 & vec ) const +{ + Vector3 __attribute__((__aligned__((64)))) result; + pfxTransform3Vector3MultiplyNEON(*this, vec, result); + return(result); +} +// ARA end + +inline const Point3 Transform3::operator *( const Point3 & pnt ) const +{ + return Point3( + ( ( ( ( mCol0.getX() * pnt.getX() ) + ( mCol1.getX() * pnt.getY() ) ) + ( mCol2.getX() * pnt.getZ() ) ) + mCol3.getX() ), + ( ( ( ( mCol0.getY() * pnt.getX() ) + ( mCol1.getY() * pnt.getY() ) ) + ( mCol2.getY() * pnt.getZ() ) ) + mCol3.getY() ), + ( ( ( ( mCol0.getZ() * pnt.getX() ) + ( mCol1.getZ() * pnt.getY() ) ) + ( mCol2.getZ() * pnt.getZ() ) ) + mCol3.getZ() ) + ); +} + +inline const Transform3 Transform3::operator *( const Transform3 & tfrm ) const +{ + return Transform3( + ( *this * tfrm.mCol0 ), + ( *this * tfrm.mCol1 ), + ( *this * tfrm.mCol2 ), + Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) + ); +} + +inline Transform3 & Transform3::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) +{ + return Transform3( + mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), + mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), + mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), + mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) + ); +} + +inline const Transform3 Transform3::identity( ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +inline Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) +{ + mCol0 = tfrm.getCol0(); + mCol1 = tfrm.getCol1(); + mCol2 = tfrm.getCol2(); + return *this; +} + +inline const Matrix3 Transform3::getUpper3x3( ) const +{ + return Matrix3( mCol0, mCol1, mCol2 ); +} + +inline Transform3 & Transform3::setTranslation( const Vector3 & translateVec ) +{ + mCol3 = translateVec; + return *this; +} + +inline const Vector3 Transform3::getTranslation( ) const +{ + return mCol3; +} + +inline const Transform3 Transform3::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3::xAxis( ), + Vector3( 0.0f, c, s ), + Vector3( 0.0f, -s, c ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3( c, 0.0f, -s ), + Vector3::yAxis( ), + Vector3( s, 0.0f, c ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3( c, s, 0.0f ), + Vector3( -s, c, 0.0f ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Transform3( + Vector3( ( cZ * cY ), ( sZ * cY ), -sY ), + Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ), + Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotation( float radians, const Vector3 & unitVec ) +{ + return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( 0.0f ) ); +} + +inline const Transform3 Transform3::rotation( const Quat & unitQuat ) +{ + return Transform3( Matrix3( unitQuat ), Vector3( 0.0f ) ); +} + +inline const Transform3 Transform3::scale( const Vector3 & scaleVec ) +{ + return Transform3( + Vector3( scaleVec.getX(), 0.0f, 0.0f ), + Vector3( 0.0f, scaleVec.getY(), 0.0f ), + Vector3( 0.0f, 0.0f, scaleVec.getZ() ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ) +{ + return Transform3( + ( tfrm.getCol0() * scaleVec.getX( ) ), + ( tfrm.getCol1() * scaleVec.getY( ) ), + ( tfrm.getCol2() * scaleVec.getZ( ) ), + tfrm.getCol3() + ); +} + +inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ) +{ + return Transform3( + mulPerElem( tfrm.getCol0(), scaleVec ), + mulPerElem( tfrm.getCol1(), scaleVec ), + mulPerElem( tfrm.getCol2(), scaleVec ), + mulPerElem( tfrm.getCol3(), scaleVec ) + ); +} + +inline const Transform3 Transform3::translation( const Vector3 & translateVec ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + translateVec + ); +} + +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Transform3 & tfrm ) +{ + print( tfrm.getRow( 0 ) ); + print( tfrm.getRow( 1 ) ); + print( tfrm.getRow( 2 ) ); +} + +inline void print( const Transform3 & tfrm, const char * name ) +{ + printf("%s:\n", name); + print( tfrm ); +} + +#endif + +inline Quat::Quat( const Matrix3 & tfrm ) +{ + float trace, radicand, scale, xx, yx, zx, xy, yy, zy, xz, yz, zz, tmpx, tmpy, tmpz, tmpw, qx, qy, qz, qw; + int negTrace, ZgtX, ZgtY, YgtX; + int largestXorY, largestYorZ, largestZorX; + + xx = tfrm.getCol0().getX(); + yx = tfrm.getCol0().getY(); + zx = tfrm.getCol0().getZ(); + xy = tfrm.getCol1().getX(); + yy = tfrm.getCol1().getY(); + zy = tfrm.getCol1().getZ(); + xz = tfrm.getCol2().getX(); + yz = tfrm.getCol2().getY(); + zz = tfrm.getCol2().getZ(); + + trace = ( ( xx + yy ) + zz ); + + negTrace = ( trace < 0.0f ); + ZgtX = zz > xx; + ZgtY = zz > yy; + YgtX = yy > xx; + largestXorY = ( !ZgtX || !ZgtY ) && negTrace; + largestYorZ = ( YgtX || ZgtX ) && negTrace; + largestZorX = ( ZgtY || !YgtX ) && negTrace; + + if ( largestXorY ) + { + zz = -zz; + xy = -xy; + } + if ( largestYorZ ) + { + xx = -xx; + yz = -yz; + } + if ( largestZorX ) + { + yy = -yy; + zx = -zx; + } + + radicand = ( ( ( xx + yy ) + zz ) + 1.0f ); + scale = ( 0.5f * ( 1.0f / sqrtf( radicand ) ) ); + + tmpx = ( ( zy - yz ) * scale ); + tmpy = ( ( xz - zx ) * scale ); + tmpz = ( ( yx - xy ) * scale ); + tmpw = ( radicand * scale ); + qx = tmpx; + qy = tmpy; + qz = tmpz; + qw = tmpw; + + if ( largestXorY ) + { + qx = tmpw; + qy = tmpz; + qz = tmpy; + qw = tmpx; + } + if ( largestYorZ ) + { + tmpx = qx; + tmpz = qz; + qx = qy; + qy = tmpx; + qz = qw; + qw = tmpz; + } + + mX = qx; + mY = qy; + mZ = qz; + mW = qw; +} + +inline const Matrix3 outer( const Vector3 & tfrm0, const Vector3 & tfrm1 ) +{ + return Matrix3( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ) + ); +} + +inline const Matrix4 outer( const Vector4 & tfrm0, const Vector4 & tfrm1 ) +{ + return Matrix4( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ), + ( tfrm0 * tfrm1.getW( ) ) + ); +} + +inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ) +{ + return Vector3( + ( ( ( vec.getX() * mat.getCol0().getX() ) + ( vec.getY() * mat.getCol0().getY() ) ) + ( vec.getZ() * mat.getCol0().getZ() ) ), + ( ( ( vec.getX() * mat.getCol1().getX() ) + ( vec.getY() * mat.getCol1().getY() ) ) + ( vec.getZ() * mat.getCol1().getZ() ) ), + ( ( ( vec.getX() * mat.getCol2().getX() ) + ( vec.getY() * mat.getCol2().getY() ) ) + ( vec.getZ() * mat.getCol2().getZ() ) ) + ); +} + +inline const Matrix3 crossMatrix( const Vector3 & vec ) +{ + return Matrix3( + Vector3( 0.0f, vec.getZ(), -vec.getY() ), + Vector3( -vec.getZ(), 0.0f, vec.getX() ), + Vector3( vec.getY(), -vec.getX(), 0.0f ) + ); +} + +inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ) +{ + return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); +} + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/PhysicsEffects/include/vecmath/neon/quat_aos.h b/Extras/PhysicsEffects/include/vecmath/neon/quat_aos.h new file mode 100644 index 0000000..6a4a0f2 --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/neon/quat_aos.h @@ -0,0 +1,446 @@ +/* + Copyright (C) 2006-2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_AOS_CPP_H +#define _VECTORMATH_QUAT_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +inline Quat::Quat( const Quat & quat ) +{ + mX = quat.mX; + mY = quat.mY; + mZ = quat.mZ; + mW = quat.mW; +} + +inline Quat::Quat( float _x, float _y, float _z, float _w ) +{ + mX = _x; + mY = _y; + mZ = _z; + mW = _w; +} + +inline Quat::Quat( const Vector3 & xyz, float _w ) +{ + this->setXYZ( xyz ); + this->setW( _w ); +} + +inline Quat::Quat( const Vector4 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + mW = vec.getW(); +} + +inline Quat::Quat( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; + mW = scalar; +} + +inline const Quat Quat::identity( ) +{ + return Quat( 0.0f, 0.0f, 0.0f, 1.0f ); +} + +inline const Quat lerp( float t, const Quat & quat0, const Quat & quat1 ) +{ + return ( quat0 + ( ( quat1 - quat0 ) * t ) ); +} + +inline const Quat slerp( float t, const Quat & unitQuat0, const Quat & unitQuat1 ) +{ + Quat start; + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitQuat0, unitQuat1 ); + if ( cosAngle < 0.0f ) { + cosAngle = -cosAngle; + start = ( -unitQuat0 ); + } else { + start = unitQuat0; + } + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( start * scale0 ) + ( unitQuat1 * scale1 ) ); +} + +inline const Quat squad( float t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ) +{ + Quat tmp0, tmp1; + tmp0 = slerp( t, unitQuat0, unitQuat3 ); + tmp1 = slerp( t, unitQuat1, unitQuat2 ); + return slerp( ( ( 2.0f * t ) * ( 1.0f - t ) ), tmp0, tmp1 ); +} + +inline void loadXYZW( Quat & quat, const float * fptr ) +{ + quat = Quat( fptr[0], fptr[1], fptr[2], fptr[3] ); +} + +inline void storeXYZW( const Quat & quat, float * fptr ) +{ + fptr[0] = quat.getX(); + fptr[1] = quat.getY(); + fptr[2] = quat.getZ(); + fptr[3] = quat.getW(); +} + +inline Quat & Quat::operator =( const Quat & quat ) +{ + mX = quat.mX; + mY = quat.mY; + mZ = quat.mZ; + mW = quat.mW; + return *this; +} + +inline Quat & Quat::setXYZ( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + return *this; +} + +inline const Vector3 Quat::getXYZ( ) const +{ + return Vector3( mX, mY, mZ ); +} + +inline Quat & Quat::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Quat::getX( ) const +{ + return mX; +} + +inline Quat & Quat::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Quat::getY( ) const +{ + return mY; +} + +inline Quat & Quat::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Quat::getZ( ) const +{ + return mZ; +} + +inline Quat & Quat::setW( float _w ) +{ + mW = _w; + return *this; +} + +inline float Quat::getW( ) const +{ + return mW; +} + +inline Quat & Quat::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Quat::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Quat::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Quat::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Quat Quat::operator +( const Quat & quat ) const +{ + return Quat( + ( mX + quat.mX ), + ( mY + quat.mY ), + ( mZ + quat.mZ ), + ( mW + quat.mW ) + ); +} + +inline const Quat Quat::operator -( const Quat & quat ) const +{ + return Quat( + ( mX - quat.mX ), + ( mY - quat.mY ), + ( mZ - quat.mZ ), + ( mW - quat.mW ) + ); +} + +inline const Quat Quat::operator *( float scalar ) const +{ + return Quat( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ), + ( mW * scalar ) + ); +} + +inline Quat & Quat::operator +=( const Quat & quat ) +{ + *this = *this + quat; + return *this; +} + +inline Quat & Quat::operator -=( const Quat & quat ) +{ + *this = *this - quat; + return *this; +} + +inline Quat & Quat::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Quat Quat::operator /( float scalar ) const +{ + return Quat( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ), + ( mW / scalar ) + ); +} + +inline Quat & Quat::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Quat Quat::operator -( ) const +{ + return Quat( + -mX, + -mY, + -mZ, + -mW + ); +} + +inline const Quat operator *( float scalar, const Quat & quat ) +{ + return quat * scalar; +} + +inline float dot( const Quat & quat0, const Quat & quat1 ) +{ + float result; + result = ( quat0.getX() * quat1.getX() ); + result = ( result + ( quat0.getY() * quat1.getY() ) ); + result = ( result + ( quat0.getZ() * quat1.getZ() ) ); + result = ( result + ( quat0.getW() * quat1.getW() ) ); + return result; +} + +inline float norm( const Quat & quat ) +{ + float result; + result = ( quat.getX() * quat.getX() ); + result = ( result + ( quat.getY() * quat.getY() ) ); + result = ( result + ( quat.getZ() * quat.getZ() ) ); + result = ( result + ( quat.getW() * quat.getW() ) ); + return result; +} + +inline float length( const Quat & quat ) +{ + return ::sqrtf( norm( quat ) ); +} + +inline const Quat normalize( const Quat & quat ) +{ + float lenSqr, lenInv; + lenSqr = norm( quat ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Quat( + ( quat.getX() * lenInv ), + ( quat.getY() * lenInv ), + ( quat.getZ() * lenInv ), + ( quat.getW() * lenInv ) + ); +} + +inline const Quat Quat::rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ) +{ + float cosHalfAngleX2, recipCosHalfAngleX2; + cosHalfAngleX2 = sqrtf( ( 2.0f * ( 1.0f + dot( unitVec0, unitVec1 ) ) ) ); + recipCosHalfAngleX2 = ( 1.0f / cosHalfAngleX2 ); + return Quat( ( cross( unitVec0, unitVec1 ) * recipCosHalfAngleX2 ), ( cosHalfAngleX2 * 0.5f ) ); +} + +inline const Quat Quat::rotation( float radians, const Vector3 & unitVec ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( ( unitVec * s ), c ); +} + +inline const Quat Quat::rotationX( float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( s, 0.0f, 0.0f, c ); +} + +inline const Quat Quat::rotationY( float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( 0.0f, s, 0.0f, c ); +} + +inline const Quat Quat::rotationZ( float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( 0.0f, 0.0f, s, c ); +} + +inline const Quat Quat::operator *( const Quat & quat ) const +{ + return Quat( + ( ( ( ( mW * quat.mX ) + ( mX * quat.mW ) ) + ( mY * quat.mZ ) ) - ( mZ * quat.mY ) ), + ( ( ( ( mW * quat.mY ) + ( mY * quat.mW ) ) + ( mZ * quat.mX ) ) - ( mX * quat.mZ ) ), + ( ( ( ( mW * quat.mZ ) + ( mZ * quat.mW ) ) + ( mX * quat.mY ) ) - ( mY * quat.mX ) ), + ( ( ( ( mW * quat.mW ) - ( mX * quat.mX ) ) - ( mY * quat.mY ) ) - ( mZ * quat.mZ ) ) + ); +} + +inline Quat & Quat::operator *=( const Quat & quat ) +{ + *this = *this * quat; + return *this; +} + +inline const Vector3 rotate( const Quat & quat, const Vector3 & vec ) +{ + float tmpX, tmpY, tmpZ, tmpW; + tmpX = ( ( ( quat.getW() * vec.getX() ) + ( quat.getY() * vec.getZ() ) ) - ( quat.getZ() * vec.getY() ) ); + tmpY = ( ( ( quat.getW() * vec.getY() ) + ( quat.getZ() * vec.getX() ) ) - ( quat.getX() * vec.getZ() ) ); + tmpZ = ( ( ( quat.getW() * vec.getZ() ) + ( quat.getX() * vec.getY() ) ) - ( quat.getY() * vec.getX() ) ); + tmpW = ( ( ( quat.getX() * vec.getX() ) + ( quat.getY() * vec.getY() ) ) + ( quat.getZ() * vec.getZ() ) ); + return Vector3( + ( ( ( ( tmpW * quat.getX() ) + ( tmpX * quat.getW() ) ) - ( tmpY * quat.getZ() ) ) + ( tmpZ * quat.getY() ) ), + ( ( ( ( tmpW * quat.getY() ) + ( tmpY * quat.getW() ) ) - ( tmpZ * quat.getX() ) ) + ( tmpX * quat.getZ() ) ), + ( ( ( ( tmpW * quat.getZ() ) + ( tmpZ * quat.getW() ) ) - ( tmpX * quat.getY() ) ) + ( tmpY * quat.getX() ) ) + ); +} + +inline const Quat conj( const Quat & quat ) +{ + return Quat( -quat.getX(), -quat.getY(), -quat.getZ(), quat.getW() ); +} + +inline const Quat select( const Quat & quat0, const Quat & quat1, bool select1 ) +{ + return Quat( + ( select1 )? quat1.getX() : quat0.getX(), + ( select1 )? quat1.getY() : quat0.getY(), + ( select1 )? quat1.getZ() : quat0.getZ(), + ( select1 )? quat1.getW() : quat0.getW() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Quat & quat ) +{ + printf( "( %f %f %f %f )\n", quat.getX(), quat.getY(), quat.getZ(), quat.getW() ); +} + +inline void print( const Quat & quat, const char * name ) +{ + printf( "%s: ( %f %f %f %f )\n", name, quat.getX(), quat.getY(), quat.getZ(), quat.getW() ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/PhysicsEffects/include/vecmath/neon/vec_aos.h b/Extras/PhysicsEffects/include/vecmath/neon/vec_aos.h new file mode 100644 index 0000000..3772dea --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/neon/vec_aos.h @@ -0,0 +1,1526 @@ +/* + Copyright (C) 2006-2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_AOS_CPP_H +#define _VECTORMATH_VEC_AOS_CPP_H + +// ARA begin insert new code +#include "vectormath_neon_assembly_prototypes.h" +// ARA end + +//----------------------------------------------------------------------------- +// Constants + +#define _VECTORMATH_SLERP_TOL 0.999f + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +inline Vector3::Vector3( const Vector3 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; +// ARA begin insert new code + d = 0.0f; +// ARA end +} + +inline Vector3::Vector3( float _x, float _y, float _z ) +{ + mX = _x; + mY = _y; + mZ = _z; +// ARA begin insert new code + d = 0.0f; +// ARA end +} + +inline Vector3::Vector3( const Point3 & pnt ) +{ + mX = pnt.getX(); + mY = pnt.getY(); + mZ = pnt.getZ(); +// ARA begin insert new code + d = 0.0f; +// ARA end +} + +inline Vector3::Vector3( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; +// ARA begin insert new code + d = 0.0f; +// ARA end +} + +inline const Vector3 Vector3::xAxis( ) +{ + return Vector3( 1.0f, 0.0f, 0.0f ); +} + +inline const Vector3 Vector3::yAxis( ) +{ + return Vector3( 0.0f, 1.0f, 0.0f ); +} + +inline const Vector3 Vector3::zAxis( ) +{ + return Vector3( 0.0f, 0.0f, 1.0f ); +} + +inline const Vector3 lerp( float t, const Vector3 & vec0, const Vector3 & vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector3 slerp( float t, const Vector3 & unitVec0, const Vector3 & unitVec1 ) +{ + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitVec0, unitVec1 ); + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); +} + +inline void loadXYZ( Vector3 & vec, const float * fptr ) +{ + vec = Vector3( fptr[0], fptr[1], fptr[2] ); +} + +inline void storeXYZ( const Vector3 & vec, float * fptr ) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); +} + +inline void loadHalfFloats( Vector3 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Vector3 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Vector3 & Vector3::operator =( const Vector3 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + return *this; +} + +inline Vector3 & Vector3::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Vector3::getX( ) const +{ + return mX; +} + +inline Vector3 & Vector3::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Vector3::getY( ) const +{ + return mY; +} + +inline Vector3 & Vector3::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Vector3::getZ( ) const +{ + return mZ; +} + +inline Vector3 & Vector3::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Vector3::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Vector3::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Vector3::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector3 Vector3::operator +( const Vector3 & vec ) const +{ + return Vector3( + ( mX + vec.mX ), + ( mY + vec.mY ), + ( mZ + vec.mZ ) + ); +} + +inline const Vector3 Vector3::operator -( const Vector3 & vec ) const +{ + return Vector3( + ( mX - vec.mX ), + ( mY - vec.mY ), + ( mZ - vec.mZ ) + ); +} + +inline const Point3 Vector3::operator +( const Point3 & pnt ) const +{ + return Point3( + ( mX + pnt.getX() ), + ( mY + pnt.getY() ), + ( mZ + pnt.getZ() ) + ); +} + +inline const Vector3 Vector3::operator *( float scalar ) const +{ + return Vector3( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ) + ); +} + +inline Vector3 & Vector3::operator +=( const Vector3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector3 & Vector3::operator -=( const Vector3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector3 & Vector3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector3 Vector3::operator /( float scalar ) const +{ + return Vector3( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ) + ); +} + +inline Vector3 & Vector3::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector3 Vector3::operator -( ) const +{ + return Vector3( + -mX, + -mY, + -mZ + ); +} + +inline const Vector3 operator *( float scalar, const Vector3 & vec ) +{ + return vec * scalar; +} + +inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec0.getX() * vec1.getX() ), + ( vec0.getY() * vec1.getY() ), + ( vec0.getZ() * vec1.getZ() ) + ); +} + +inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec0.getX() / vec1.getX() ), + ( vec0.getY() / vec1.getY() ), + ( vec0.getZ() / vec1.getZ() ) + ); +} + +inline const Vector3 recipPerElem( const Vector3 & vec ) +{ + return Vector3( + ( 1.0f / vec.getX() ), + ( 1.0f / vec.getY() ), + ( 1.0f / vec.getZ() ) + ); +} + +inline const Vector3 sqrtPerElem( const Vector3 & vec ) +{ + return Vector3( + sqrtf( vec.getX() ), + sqrtf( vec.getY() ), + sqrtf( vec.getZ() ) + ); +} + +inline const Vector3 rsqrtPerElem( const Vector3 & vec ) +{ + return Vector3( + ( 1.0f / sqrtf( vec.getX() ) ), + ( 1.0f / sqrtf( vec.getY() ) ), + ( 1.0f / sqrtf( vec.getZ() ) ) + ); +} + +inline const Vector3 absPerElem( const Vector3 & vec ) +{ + return Vector3( + fabsf( vec.getX() ), + fabsf( vec.getY() ), + fabsf( vec.getZ() ) + ); +} + +inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec1.getX() < 0.0f )? -fabsf( vec0.getX() ) : fabsf( vec0.getX() ), + ( vec1.getY() < 0.0f )? -fabsf( vec0.getY() ) : fabsf( vec0.getY() ), + ( vec1.getZ() < 0.0f )? -fabsf( vec0.getZ() ) : fabsf( vec0.getZ() ) + ); +} + +inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ() + ); +} + +inline float maxElem( const Vector3 & vec ) +{ + float result; + result = (vec.getX() > vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() > result)? vec.getZ() : result; + return result; +} + +inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ() + ); +} + +inline float minElem( const Vector3 & vec ) +{ + float result; + result = (vec.getX() < vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() < result)? vec.getZ() : result; + return result; +} + +inline float sum( const Vector3 & vec ) +{ + float result; + result = ( vec.getX() + vec.getY() ); + result = ( result + vec.getZ() ); + return result; +} + +// ARA begin insert new code +inline float dot( const Vector3 & vec0, const Vector3 & vec1 ) +{ +#if 1 // pure assembly + + float __attribute__((__aligned__((64)))) result[2]; // space for 2 floats since neon vst1.32 wants to store a double register + pfxVector3DotProductNEON(vec0, vec1, result); + return(result[0]); + +#else // inline assembly + // Note that this inline assembly does NOT work correctly though it is *identical* to the dedicated assembly + // version and has (in theory) properly assigned register constraints and clobbers. In fact, it produces a + // correct numerical result, but gcc seems to not properly manage registers and this causes trouble downstream. + // Forum discussions indicate gcc is not great at supporting inline assembly using NEON registers. Even the + // two different but theoretically equivalent clobber lists produce different simulation results! + float __attribute__((__aligned__((64)))) result[2]; // space for 2 floats since neon vst1.32 wants to store a double register + asm volatile + ( + // Note this code is explicitly using register q0-q2 (and corresponding d/s registers) + // so that we can avoid the need to preserve them. We are applying instructions directly + // to s registers, which prevents us from using q8 and above, and would rather not + // use registers that gcc expects us to preserve, to avoid the cost of doing that. + "vld1.32 {d0,d1}, [%1] @ input = d0,d1\n\t" + "vld1.32 {d2,d3}, [%0] @ input = d2,d3\n\t" + "vmul.f32 d4, d0, d2 @ d4 = \n\t" + "vpadd.f32 d4, d4, d4 @ d4 = \n\t" + "vmla.f32 s8, s2, s6 @ s8 = = d18,d19\n\t" + "vld1.32 {d16,d17}, [%0] @ input = d16,d17\n\t" + "vtrn.32 d18,d19 @ q9 = = d18,d19\n\t" + "vrev64.32 d16,d16 @ q8 = = d16,d17\n\t" + "vrev64.32 d18,d18 @ q9 = = d18,d19\n\t" + "vtrn.32 d16,d17 @ q8 = = d16,d17\n\t" + "vmul.f32 q10, q8, q9 @ q10 = \n\t" + "vtrn.32 d18,d19 @ q9 = = d18,d19\n\t" + "vrev64.32 d16,d16 @ q8 = = d16,d17\n\t" + "vrev64.32 d18,d18 @ q9 = = d18,d19\n\t" + "vtrn.32 d16,d17 @ q8 = = d16,d17\n\t" + "vmls.f32 q10, q8, q9 @ q10 = \n\t" + "vst1.32 {q10}, [%2]\n\t" + : // NO explicit outputs! + : "r" (&vec0), "r" (&vec1), "r" (&result) //inputs. output indirectly stored in result + : "memory", "q8", "q9", "q10" // clobbers + ); + return result; +#endif +} +// ARA end + +inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, bool select1 ) +{ + return Vector3( + ( select1 )? vec1.getX() : vec0.getX(), + ( select1 )? vec1.getY() : vec0.getY(), + ( select1 )? vec1.getZ() : vec0.getZ() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Vector3 & vec ) +{ + printf( "( %f %f %f )\n", vec.getX(), vec.getY(), vec.getZ() ); +} + +inline void print( const Vector3 & vec, const char * name ) +{ + printf( "%s: ( %f %f %f )\n", name, vec.getX(), vec.getY(), vec.getZ() ); +} + +#endif + +inline Vector4::Vector4( const Vector4 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + mW = vec.mW; +} + +inline Vector4::Vector4( float _x, float _y, float _z, float _w ) +{ + mX = _x; + mY = _y; + mZ = _z; + mW = _w; +} + +inline Vector4::Vector4( const Vector3 & xyz, float _w ) +{ + this->setXYZ( xyz ); + this->setW( _w ); +} + +inline Vector4::Vector4( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + mW = 0.0f; +} + +inline Vector4::Vector4( const Point3 & pnt ) +{ + mX = pnt.getX(); + mY = pnt.getY(); + mZ = pnt.getZ(); + mW = 1.0f; +} + +inline Vector4::Vector4( const Quat & quat ) +{ + mX = quat.getX(); + mY = quat.getY(); + mZ = quat.getZ(); + mW = quat.getW(); +} + +inline Vector4::Vector4( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; + mW = scalar; +} + +inline const Vector4 Vector4::xAxis( ) +{ + return Vector4( 1.0f, 0.0f, 0.0f, 0.0f ); +} + +inline const Vector4 Vector4::yAxis( ) +{ + return Vector4( 0.0f, 1.0f, 0.0f, 0.0f ); +} + +inline const Vector4 Vector4::zAxis( ) +{ + return Vector4( 0.0f, 0.0f, 1.0f, 0.0f ); +} + +inline const Vector4 Vector4::wAxis( ) +{ + return Vector4( 0.0f, 0.0f, 0.0f, 1.0f ); +} + +inline const Vector4 lerp( float t, const Vector4 & vec0, const Vector4 & vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector4 slerp( float t, const Vector4 & unitVec0, const Vector4 & unitVec1 ) +{ + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitVec0, unitVec1 ); + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); +} + +inline void loadXYZW( Vector4 & vec, const float * fptr ) +{ + vec = Vector4( fptr[0], fptr[1], fptr[2], fptr[3] ); +} + +inline void storeXYZW( const Vector4 & vec, float * fptr ) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); + fptr[3] = vec.getW(); +} + +inline void loadHalfFloats( Vector4 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 4; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Vector4 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 4; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Vector4 & Vector4::operator =( const Vector4 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + mW = vec.mW; + return *this; +} + +inline Vector4 & Vector4::setXYZ( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + return *this; +} + +inline const Vector3 Vector4::getXYZ( ) const +{ + return Vector3( mX, mY, mZ ); +} + +inline Vector4 & Vector4::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Vector4::getX( ) const +{ + return mX; +} + +inline Vector4 & Vector4::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Vector4::getY( ) const +{ + return mY; +} + +inline Vector4 & Vector4::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Vector4::getZ( ) const +{ + return mZ; +} + +inline Vector4 & Vector4::setW( float _w ) +{ + mW = _w; + return *this; +} + +inline float Vector4::getW( ) const +{ + return mW; +} + +inline Vector4 & Vector4::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Vector4::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Vector4::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Vector4::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector4 Vector4::operator +( const Vector4 & vec ) const +{ + return Vector4( + ( mX + vec.mX ), + ( mY + vec.mY ), + ( mZ + vec.mZ ), + ( mW + vec.mW ) + ); +} + +inline const Vector4 Vector4::operator -( const Vector4 & vec ) const +{ + return Vector4( + ( mX - vec.mX ), + ( mY - vec.mY ), + ( mZ - vec.mZ ), + ( mW - vec.mW ) + ); +} + +inline const Vector4 Vector4::operator *( float scalar ) const +{ + return Vector4( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ), + ( mW * scalar ) + ); +} + +inline Vector4 & Vector4::operator +=( const Vector4 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector4 & Vector4::operator -=( const Vector4 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector4 & Vector4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector4 Vector4::operator /( float scalar ) const +{ + return Vector4( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ), + ( mW / scalar ) + ); +} + +inline Vector4 & Vector4::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector4 Vector4::operator -( ) const +{ + return Vector4( + -mX, + -mY, + -mZ, + -mW + ); +} + +inline const Vector4 operator *( float scalar, const Vector4 & vec ) +{ + return vec * scalar; +} + +inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec0.getX() * vec1.getX() ), + ( vec0.getY() * vec1.getY() ), + ( vec0.getZ() * vec1.getZ() ), + ( vec0.getW() * vec1.getW() ) + ); +} + +inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec0.getX() / vec1.getX() ), + ( vec0.getY() / vec1.getY() ), + ( vec0.getZ() / vec1.getZ() ), + ( vec0.getW() / vec1.getW() ) + ); +} + +inline const Vector4 recipPerElem( const Vector4 & vec ) +{ + return Vector4( + ( 1.0f / vec.getX() ), + ( 1.0f / vec.getY() ), + ( 1.0f / vec.getZ() ), + ( 1.0f / vec.getW() ) + ); +} + +inline const Vector4 sqrtPerElem( const Vector4 & vec ) +{ + return Vector4( + sqrtf( vec.getX() ), + sqrtf( vec.getY() ), + sqrtf( vec.getZ() ), + sqrtf( vec.getW() ) + ); +} + +inline const Vector4 rsqrtPerElem( const Vector4 & vec ) +{ + return Vector4( + ( 1.0f / sqrtf( vec.getX() ) ), + ( 1.0f / sqrtf( vec.getY() ) ), + ( 1.0f / sqrtf( vec.getZ() ) ), + ( 1.0f / sqrtf( vec.getW() ) ) + ); +} + +inline const Vector4 absPerElem( const Vector4 & vec ) +{ + return Vector4( + fabsf( vec.getX() ), + fabsf( vec.getY() ), + fabsf( vec.getZ() ), + fabsf( vec.getW() ) + ); +} + +inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec1.getX() < 0.0f )? -fabsf( vec0.getX() ) : fabsf( vec0.getX() ), + ( vec1.getY() < 0.0f )? -fabsf( vec0.getY() ) : fabsf( vec0.getY() ), + ( vec1.getZ() < 0.0f )? -fabsf( vec0.getZ() ) : fabsf( vec0.getZ() ), + ( vec1.getW() < 0.0f )? -fabsf( vec0.getW() ) : fabsf( vec0.getW() ) + ); +} + +inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ(), + (vec0.getW() > vec1.getW())? vec0.getW() : vec1.getW() + ); +} + +inline float maxElem( const Vector4 & vec ) +{ + float result; + result = (vec.getX() > vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() > result)? vec.getZ() : result; + result = (vec.getW() > result)? vec.getW() : result; + return result; +} + +inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ(), + (vec0.getW() < vec1.getW())? vec0.getW() : vec1.getW() + ); +} + +inline float minElem( const Vector4 & vec ) +{ + float result; + result = (vec.getX() < vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() < result)? vec.getZ() : result; + result = (vec.getW() < result)? vec.getW() : result; + return result; +} + +inline float sum( const Vector4 & vec ) +{ + float result; + result = ( vec.getX() + vec.getY() ); + result = ( result + vec.getZ() ); + result = ( result + vec.getW() ); + return result; +} + +// ARA begin insert new code +inline float dot( const Vector4 & vec0, const Vector4 & vec1 ) +{ + float __attribute__((__aligned__((64)))) result[2]; // space for 2 floats since neon vst1.32 wants to store a double register + pfxVector4DotProductNEON(vec0, vec1, result); + return(result[0]); +} +// ARA end + +inline float lengthSqr( const Vector4 & vec ) +{ + float result; + result = ( vec.getX() * vec.getX() ); + result = ( result + ( vec.getY() * vec.getY() ) ); + result = ( result + ( vec.getZ() * vec.getZ() ) ); + result = ( result + ( vec.getW() * vec.getW() ) ); + return result; +} + +inline float length( const Vector4 & vec ) +{ + return ::sqrtf( lengthSqr( vec ) ); +} + +inline const Vector4 normalize( const Vector4 & vec ) +{ + float lenSqr, lenInv; + lenSqr = lengthSqr( vec ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Vector4( + ( vec.getX() * lenInv ), + ( vec.getY() * lenInv ), + ( vec.getZ() * lenInv ), + ( vec.getW() * lenInv ) + ); +} + +inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, bool select1 ) +{ + return Vector4( + ( select1 )? vec1.getX() : vec0.getX(), + ( select1 )? vec1.getY() : vec0.getY(), + ( select1 )? vec1.getZ() : vec0.getZ(), + ( select1 )? vec1.getW() : vec0.getW() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Vector4 & vec ) +{ + printf( "( %f %f %f %f )\n", vec.getX(), vec.getY(), vec.getZ(), vec.getW() ); +} + +inline void print( const Vector4 & vec, const char * name ) +{ + printf( "%s: ( %f %f %f %f )\n", name, vec.getX(), vec.getY(), vec.getZ(), vec.getW() ); +} + +#endif + +inline Point3::Point3( const Point3 & pnt ) +{ + mX = pnt.mX; + mY = pnt.mY; + mZ = pnt.mZ; +// ARA begin insert new code + d = 0.0f; +// ARA end +} + +inline Point3::Point3( float _x, float _y, float _z ) +{ + mX = _x; + mY = _y; + mZ = _z; +// ARA begin insert new code + d = 0.0f; +// ARA end +} + +inline Point3::Point3( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); +// ARA begin insert new code + d = 0.0f; +// ARA end +} + +inline Point3::Point3( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; +// ARA begin insert new code + d = 0.0f; +// ARA end +} + +inline const Point3 lerp( float t, const Point3 & pnt0, const Point3 & pnt1 ) +{ + return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); +} + +inline void loadXYZ( Point3 & pnt, const float * fptr ) +{ + pnt = Point3( fptr[0], fptr[1], fptr[2] ); +} + +inline void storeXYZ( const Point3 & pnt, float * fptr ) +{ + fptr[0] = pnt.getX(); + fptr[1] = pnt.getY(); + fptr[2] = pnt.getZ(); +} + +inline void loadHalfFloats( Point3 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Point3 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Point3 & Point3::operator =( const Point3 & pnt ) +{ + mX = pnt.mX; + mY = pnt.mY; + mZ = pnt.mZ; + return *this; +} + +inline Point3 & Point3::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Point3::getX( ) const +{ + return mX; +} + +inline Point3 & Point3::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Point3::getY( ) const +{ + return mY; +} + +inline Point3 & Point3::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Point3::getZ( ) const +{ + return mZ; +} + +inline Point3 & Point3::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Point3::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Point3::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Point3::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector3 Point3::operator -( const Point3 & pnt ) const +{ + return Vector3( + ( mX - pnt.mX ), + ( mY - pnt.mY ), + ( mZ - pnt.mZ ) + ); +} + +inline const Point3 Point3::operator +( const Vector3 & vec ) const +{ + return Point3( + ( mX + vec.getX() ), + ( mY + vec.getY() ), + ( mZ + vec.getZ() ) + ); +} + +inline const Point3 Point3::operator -( const Vector3 & vec ) const +{ + return Point3( + ( mX - vec.getX() ), + ( mY - vec.getY() ), + ( mZ - vec.getZ() ) + ); +} + +inline Point3 & Point3::operator +=( const Vector3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Point3 & Point3::operator -=( const Vector3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt0.getX() * pnt1.getX() ), + ( pnt0.getY() * pnt1.getY() ), + ( pnt0.getZ() * pnt1.getZ() ) + ); +} + +inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt0.getX() / pnt1.getX() ), + ( pnt0.getY() / pnt1.getY() ), + ( pnt0.getZ() / pnt1.getZ() ) + ); +} + +inline const Point3 recipPerElem( const Point3 & pnt ) +{ + return Point3( + ( 1.0f / pnt.getX() ), + ( 1.0f / pnt.getY() ), + ( 1.0f / pnt.getZ() ) + ); +} + +inline const Point3 sqrtPerElem( const Point3 & pnt ) +{ + return Point3( + sqrtf( pnt.getX() ), + sqrtf( pnt.getY() ), + sqrtf( pnt.getZ() ) + ); +} + +inline const Point3 rsqrtPerElem( const Point3 & pnt ) +{ + return Point3( + ( 1.0f / sqrtf( pnt.getX() ) ), + ( 1.0f / sqrtf( pnt.getY() ) ), + ( 1.0f / sqrtf( pnt.getZ() ) ) + ); +} + +inline const Point3 absPerElem( const Point3 & pnt ) +{ + return Point3( + fabsf( pnt.getX() ), + fabsf( pnt.getY() ), + fabsf( pnt.getZ() ) + ); +} + +inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt1.getX() < 0.0f )? -fabsf( pnt0.getX() ) : fabsf( pnt0.getX() ), + ( pnt1.getY() < 0.0f )? -fabsf( pnt0.getY() ) : fabsf( pnt0.getY() ), + ( pnt1.getZ() < 0.0f )? -fabsf( pnt0.getZ() ) : fabsf( pnt0.getZ() ) + ); +} + +inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + (pnt0.getX() > pnt1.getX())? pnt0.getX() : pnt1.getX(), + (pnt0.getY() > pnt1.getY())? pnt0.getY() : pnt1.getY(), + (pnt0.getZ() > pnt1.getZ())? pnt0.getZ() : pnt1.getZ() + ); +} + +inline float maxElem( const Point3 & pnt ) +{ + float result; + result = (pnt.getX() > pnt.getY())? pnt.getX() : pnt.getY(); + result = (pnt.getZ() > result)? pnt.getZ() : result; + return result; +} + +inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + (pnt0.getX() < pnt1.getX())? pnt0.getX() : pnt1.getX(), + (pnt0.getY() < pnt1.getY())? pnt0.getY() : pnt1.getY(), + (pnt0.getZ() < pnt1.getZ())? pnt0.getZ() : pnt1.getZ() + ); +} + +inline float minElem( const Point3 & pnt ) +{ + float result; + result = (pnt.getX() < pnt.getY())? pnt.getX() : pnt.getY(); + result = (pnt.getZ() < result)? pnt.getZ() : result; + return result; +} + +inline float sum( const Point3 & pnt ) +{ + float result; + result = ( pnt.getX() + pnt.getY() ); + result = ( result + pnt.getZ() ); + return result; +} + +inline const Point3 scale( const Point3 & pnt, float scaleVal ) +{ + return mulPerElem( pnt, Point3( scaleVal ) ); +} + +inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ) +{ + return mulPerElem( pnt, Point3( scaleVec ) ); +} + +inline float projection( const Point3 & pnt, const Vector3 & unitVec ) +{ + float result; + result = ( pnt.getX() * unitVec.getX() ); + result = ( result + ( pnt.getY() * unitVec.getY() ) ); + result = ( result + ( pnt.getZ() * unitVec.getZ() ) ); + return result; +} + +inline float distSqrFromOrigin( const Point3 & pnt ) +{ + return lengthSqr( Vector3( pnt ) ); +} + +inline float distFromOrigin( const Point3 & pnt ) +{ + return length( Vector3( pnt ) ); +} + +inline float distSqr( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return lengthSqr( ( pnt1 - pnt0 ) ); +} + +inline float dist( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return length( ( pnt1 - pnt0 ) ); +} + +inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, bool select1 ) +{ + return Point3( + ( select1 )? pnt1.getX() : pnt0.getX(), + ( select1 )? pnt1.getY() : pnt0.getY(), + ( select1 )? pnt1.getZ() : pnt0.getZ() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Point3 & pnt ) +{ + printf( "( %f %f %f )\n", pnt.getX(), pnt.getY(), pnt.getZ() ); +} + +inline void print( const Point3 & pnt, const char * name ) +{ + printf( "%s: ( %f %f %f )\n", name, pnt.getX(), pnt.getY(), pnt.getZ() ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/PhysicsEffects/include/vecmath/neon/vectormath_aos.h b/Extras/PhysicsEffects/include/vecmath/neon/vectormath_aos.h new file mode 100644 index 0000000..d884e87 --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/neon/vectormath_aos.h @@ -0,0 +1,1893 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_AOS_CPP_SCALAR_H +#define _VECTORMATH_AOS_CPP_SCALAR_H + +#include + +#ifdef _VECTORMATH_DEBUG +#include +#endif + +namespace Vectormath { + +namespace Aos { + +//----------------------------------------------------------------------------- +// Forward Declarations +// + +class Vector3; +class Vector4; +class Point3; +class Quat; +class Matrix3; +class Matrix4; +class Transform3; + +// A 3-D vector in array-of-structures format +// +class Vector3 +{ + float mX; + float mY; + float mZ; +// ARA begin code change +// Removed #ifndef __GNUC__ condition + float d; +// ARA end + +public: + // Default constructor; does no initialization + // + // ARA begin insert new code + // Added explicit initialization of d = 0.0f; + inline Vector3( ) { d = 0.0f; }; + // ARA end + + // Copy a 3-D vector + // + inline Vector3( const Vector3 & vec ); + + // Construct a 3-D vector from x, y, and z elements + // + inline Vector3( float x, float y, float z ); + + // Copy elements from a 3-D point into a 3-D vector + // + explicit inline Vector3( const Point3 & pnt ); + + // Set all elements of a 3-D vector to the same scalar value + // + explicit inline Vector3( float scalar ); + + // Assign one 3-D vector to another + // + inline Vector3 & operator =( const Vector3 & vec ); + + // Set the x element of a 3-D vector + // + inline Vector3 & setX( float x ); + + // Set the y element of a 3-D vector + // + inline Vector3 & setY( float y ); + + // Set the z element of a 3-D vector + // + inline Vector3 & setZ( float z ); + + // Get the x element of a 3-D vector + // + inline float getX( ) const; + + // Get the y element of a 3-D vector + // + inline float getY( ) const; + + // Get the z element of a 3-D vector + // + inline float getZ( ) const; + + // Set an x, y, or z element of a 3-D vector by index + // + inline Vector3 & setElem( int idx, float value ); + + // Get an x, y, or z element of a 3-D vector by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two 3-D vectors + // + inline const Vector3 operator +( const Vector3 & vec ) const; + + // Subtract a 3-D vector from another 3-D vector + // + inline const Vector3 operator -( const Vector3 & vec ) const; + + // Add a 3-D vector to a 3-D point + // + inline const Point3 operator +( const Point3 & pnt ) const; + + // Multiply a 3-D vector by a scalar + // + inline const Vector3 operator *( float scalar ) const; + + // Divide a 3-D vector by a scalar + // + inline const Vector3 operator /( float scalar ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Vector3 & operator +=( const Vector3 & vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Vector3 & operator -=( const Vector3 & vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector3 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector3 & operator /=( float scalar ); + + // Negate all elements of a 3-D vector + // + inline const Vector3 operator -( ) const; + + // Construct x axis + // + static inline const Vector3 xAxis( ); + + // Construct y axis + // + static inline const Vector3 yAxis( ); + + // Construct z axis + // + static inline const Vector3 zAxis( ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a 3-D vector by a scalar +// +inline const Vector3 operator *( float scalar, const Vector3 & vec ); + +// Multiply two 3-D vectors per element +// +inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Divide two 3-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Compute the reciprocal of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector3 recipPerElem( const Vector3 & vec ); + +// Compute the square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector3 sqrtPerElem( const Vector3 & vec ); + +// Compute the reciprocal square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector3 rsqrtPerElem( const Vector3 & vec ); + +// Compute the absolute value of a 3-D vector per element +// +inline const Vector3 absPerElem( const Vector3 & vec ); + +// Copy sign from one 3-D vector to another, per element +// +inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Maximum of two 3-D vectors per element +// +inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Minimum of two 3-D vectors per element +// +inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Maximum element of a 3-D vector +// +inline float maxElem( const Vector3 & vec ); + +// Minimum element of a 3-D vector +// +inline float minElem( const Vector3 & vec ); + +// Compute the sum of all elements of a 3-D vector +// +inline float sum( const Vector3 & vec ); + +// Compute the dot product of two 3-D vectors +// +inline float dot( const Vector3 & vec0, const Vector3 & vec1 ); + +// Compute the square of the length of a 3-D vector +// +inline float lengthSqr( const Vector3 & vec ); + +// Compute the length of a 3-D vector +// +inline float length( const Vector3 & vec ); + +// Normalize a 3-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector3 normalize( const Vector3 & vec ); + +// Compute cross product of two 3-D vectors +// +inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ); + +// Outer product of two 3-D vectors +// +inline const Matrix3 outer( const Vector3 & vec0, const Vector3 & vec1 ); + +// Pre-multiply a row vector by a 3x3 matrix +// +inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ); + +// Cross-product matrix of a 3-D vector +// +inline const Matrix3 crossMatrix( const Vector3 & vec ); + +// Create cross-product matrix and multiply +// NOTE: +// Faster than separately creating a cross-product matrix and multiplying. +// +inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ); + +// Linear interpolation between two 3-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector3 lerp( float t, const Vector3 & vec0, const Vector3 & vec1 ); + +// Spherical linear interpolation between two 3-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector3 slerp( float t, const Vector3 & unitVec0, const Vector3 & unitVec1 ); + +// Conditionally select between two 3-D vectors +// +inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, bool select1 ); + +// Load x, y, and z elements from the first three words of a float array. +// +// +inline void loadXYZ( Vector3 & vec, const float * fptr ); + +// Store x, y, and z elements of a 3-D vector in the first three words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZ( const Vector3 & vec, float * fptr ); + +// Load three-half-floats as a 3-D vector +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Vector3 & vec, const unsigned short * hfptr ); + +// Store a 3-D vector as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Vector3 & vec, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector3 & vec ); + +// Print a 3-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector3 & vec, const char * name ); + +#endif + +// A 4-D vector in array-of-structures format +// +class Vector4 +{ + float mX; + float mY; + float mZ; + float mW; + +public: + // Default constructor; does no initialization + // + inline Vector4( ) { }; + + // Copy a 4-D vector + // + inline Vector4( const Vector4 & vec ); + + // Construct a 4-D vector from x, y, z, and w elements + // + inline Vector4( float x, float y, float z, float w ); + + // Construct a 4-D vector from a 3-D vector and a scalar + // + inline Vector4( const Vector3 & xyz, float w ); + + // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + // + explicit inline Vector4( const Vector3 & vec ); + + // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + // + explicit inline Vector4( const Point3 & pnt ); + + // Copy elements from a quaternion into a 4-D vector + // + explicit inline Vector4( const Quat & quat ); + + // Set all elements of a 4-D vector to the same scalar value + // + explicit inline Vector4( float scalar ); + + // Assign one 4-D vector to another + // + inline Vector4 & operator =( const Vector4 & vec ); + + // Set the x, y, and z elements of a 4-D vector + // NOTE: + // This function does not change the w element. + // + inline Vector4 & setXYZ( const Vector3 & vec ); + + // Get the x, y, and z elements of a 4-D vector + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a 4-D vector + // + inline Vector4 & setX( float x ); + + // Set the y element of a 4-D vector + // + inline Vector4 & setY( float y ); + + // Set the z element of a 4-D vector + // + inline Vector4 & setZ( float z ); + + // Set the w element of a 4-D vector + // + inline Vector4 & setW( float w ); + + // Get the x element of a 4-D vector + // + inline float getX( ) const; + + // Get the y element of a 4-D vector + // + inline float getY( ) const; + + // Get the z element of a 4-D vector + // + inline float getZ( ) const; + + // Get the w element of a 4-D vector + // + inline float getW( ) const; + + // Set an x, y, z, or w element of a 4-D vector by index + // + inline Vector4 & setElem( int idx, float value ); + + // Get an x, y, z, or w element of a 4-D vector by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two 4-D vectors + // + inline const Vector4 operator +( const Vector4 & vec ) const; + + // Subtract a 4-D vector from another 4-D vector + // + inline const Vector4 operator -( const Vector4 & vec ) const; + + // Multiply a 4-D vector by a scalar + // + inline const Vector4 operator *( float scalar ) const; + + // Divide a 4-D vector by a scalar + // + inline const Vector4 operator /( float scalar ) const; + + // Perform compound assignment and addition with a 4-D vector + // + inline Vector4 & operator +=( const Vector4 & vec ); + + // Perform compound assignment and subtraction by a 4-D vector + // + inline Vector4 & operator -=( const Vector4 & vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector4 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector4 & operator /=( float scalar ); + + // Negate all elements of a 4-D vector + // + inline const Vector4 operator -( ) const; + + // Construct x axis + // + static inline const Vector4 xAxis( ); + + // Construct y axis + // + static inline const Vector4 yAxis( ); + + // Construct z axis + // + static inline const Vector4 zAxis( ); + + // Construct w axis + // + static inline const Vector4 wAxis( ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a 4-D vector by a scalar +// +inline const Vector4 operator *( float scalar, const Vector4 & vec ); + +// Multiply two 4-D vectors per element +// +inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Divide two 4-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Compute the reciprocal of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector4 recipPerElem( const Vector4 & vec ); + +// Compute the square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector4 sqrtPerElem( const Vector4 & vec ); + +// Compute the reciprocal square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector4 rsqrtPerElem( const Vector4 & vec ); + +// Compute the absolute value of a 4-D vector per element +// +inline const Vector4 absPerElem( const Vector4 & vec ); + +// Copy sign from one 4-D vector to another, per element +// +inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Maximum of two 4-D vectors per element +// +inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Minimum of two 4-D vectors per element +// +inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Maximum element of a 4-D vector +// +inline float maxElem( const Vector4 & vec ); + +// Minimum element of a 4-D vector +// +inline float minElem( const Vector4 & vec ); + +// Compute the sum of all elements of a 4-D vector +// +inline float sum( const Vector4 & vec ); + +// Compute the dot product of two 4-D vectors +// +inline float dot( const Vector4 & vec0, const Vector4 & vec1 ); + +// Compute the square of the length of a 4-D vector +// +inline float lengthSqr( const Vector4 & vec ); + +// Compute the length of a 4-D vector +// +inline float length( const Vector4 & vec ); + +// Normalize a 4-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector4 normalize( const Vector4 & vec ); + +// Outer product of two 4-D vectors +// +inline const Matrix4 outer( const Vector4 & vec0, const Vector4 & vec1 ); + +// Linear interpolation between two 4-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector4 lerp( float t, const Vector4 & vec0, const Vector4 & vec1 ); + +// Spherical linear interpolation between two 4-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector4 slerp( float t, const Vector4 & unitVec0, const Vector4 & unitVec1 ); + +// Conditionally select between two 4-D vectors +// +inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, bool select1 ); + +// Load x, y, z, and w elements from the first four words of a float array. +// +// +inline void loadXYZW( Vector4 & vec, const float * fptr ); + +// Store x, y, z, and w elements of a 4-D vector in the first four words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZW( const Vector4 & vec, float * fptr ); + +// Load four-half-floats as a 4-D vector +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Vector4 & vec, const unsigned short * hfptr ); + +// Store a 4-D vector as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Vector4 & vec, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector4 & vec ); + +// Print a 4-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector4 & vec, const char * name ); + +#endif + +// A 3-D point in array-of-structures format +// +class Point3 +{ + float mX; + float mY; + float mZ; +// ARA begin code change +// Removed #ifndef __GNUC__ condition + float d; +// ARA end + +public: + // Default constructor; does no initialization + // + // ARA begin insert new code + // Added explicit initialization of d = 0.0f; + inline Point3( ) { d = 0.0f; }; + // ARA end + + // Copy a 3-D point + // + inline Point3( const Point3 & pnt ); + + // Construct a 3-D point from x, y, and z elements + // + inline Point3( float x, float y, float z ); + + // Copy elements from a 3-D vector into a 3-D point + // + explicit inline Point3( const Vector3 & vec ); + + // Set all elements of a 3-D point to the same scalar value + // + explicit inline Point3( float scalar ); + + // Assign one 3-D point to another + // + inline Point3 & operator =( const Point3 & pnt ); + + // Set the x element of a 3-D point + // + inline Point3 & setX( float x ); + + // Set the y element of a 3-D point + // + inline Point3 & setY( float y ); + + // Set the z element of a 3-D point + // + inline Point3 & setZ( float z ); + + // Get the x element of a 3-D point + // + inline float getX( ) const; + + // Get the y element of a 3-D point + // + inline float getY( ) const; + + // Get the z element of a 3-D point + // + inline float getZ( ) const; + + // Set an x, y, or z element of a 3-D point by index + // + inline Point3 & setElem( int idx, float value ); + + // Get an x, y, or z element of a 3-D point by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Subtract a 3-D point from another 3-D point + // + inline const Vector3 operator -( const Point3 & pnt ) const; + + // Add a 3-D point to a 3-D vector + // + inline const Point3 operator +( const Vector3 & vec ) const; + + // Subtract a 3-D vector from a 3-D point + // + inline const Point3 operator -( const Vector3 & vec ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Point3 & operator +=( const Vector3 & vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Point3 & operator -=( const Vector3 & vec ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply two 3-D points per element +// +inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Divide two 3-D points per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Compute the reciprocal of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Point3 recipPerElem( const Point3 & pnt ); + +// Compute the square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Point3 sqrtPerElem( const Point3 & pnt ); + +// Compute the reciprocal square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Point3 rsqrtPerElem( const Point3 & pnt ); + +// Compute the absolute value of a 3-D point per element +// +inline const Point3 absPerElem( const Point3 & pnt ); + +// Copy sign from one 3-D point to another, per element +// +inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Maximum of two 3-D points per element +// +inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Minimum of two 3-D points per element +// +inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Maximum element of a 3-D point +// +inline float maxElem( const Point3 & pnt ); + +// Minimum element of a 3-D point +// +inline float minElem( const Point3 & pnt ); + +// Compute the sum of all elements of a 3-D point +// +inline float sum( const Point3 & pnt ); + +// Apply uniform scale to a 3-D point +// +inline const Point3 scale( const Point3 & pnt, float scaleVal ); + +// Apply non-uniform scale to a 3-D point +// +inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ); + +// Scalar projection of a 3-D point on a unit-length 3-D vector +// +inline float projection( const Point3 & pnt, const Vector3 & unitVec ); + +// Compute the square of the distance of a 3-D point from the coordinate-system origin +// +inline float distSqrFromOrigin( const Point3 & pnt ); + +// Compute the distance of a 3-D point from the coordinate-system origin +// +inline float distFromOrigin( const Point3 & pnt ); + +// Compute the square of the distance between two 3-D points +// +inline float distSqr( const Point3 & pnt0, const Point3 & pnt1 ); + +// Compute the distance between two 3-D points +// +inline float dist( const Point3 & pnt0, const Point3 & pnt1 ); + +// Linear interpolation between two 3-D points +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Point3 lerp( float t, const Point3 & pnt0, const Point3 & pnt1 ); + +// Conditionally select between two 3-D points +// +inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, bool select1 ); + +// Load x, y, and z elements from the first three words of a float array. +// +// +inline void loadXYZ( Point3 & pnt, const float * fptr ); + +// Store x, y, and z elements of a 3-D point in the first three words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZ( const Point3 & pnt, float * fptr ); + +// Load three-half-floats as a 3-D point +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Point3 & pnt, const unsigned short * hfptr ); + +// Store a 3-D point as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Point3 & pnt, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D point +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Point3 & pnt ); + +// Print a 3-D point and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Point3 & pnt, const char * name ); + +#endif + +// A quaternion in array-of-structures format +// +class Quat +{ + float mX; + float mY; + float mZ; + float mW; + +public: + // Default constructor; does no initialization + // + inline Quat( ) { }; + + // Copy a quaternion + // + inline Quat( const Quat & quat ); + + // Construct a quaternion from x, y, z, and w elements + // + inline Quat( float x, float y, float z, float w ); + + // Construct a quaternion from a 3-D vector and a scalar + // + inline Quat( const Vector3 & xyz, float w ); + + // Copy elements from a 4-D vector into a quaternion + // + explicit inline Quat( const Vector4 & vec ); + + // Convert a rotation matrix to a unit-length quaternion + // + explicit inline Quat( const Matrix3 & rotMat ); + + // Set all elements of a quaternion to the same scalar value + // + explicit inline Quat( float scalar ); + + // Assign one quaternion to another + // + inline Quat & operator =( const Quat & quat ); + + // Set the x, y, and z elements of a quaternion + // NOTE: + // This function does not change the w element. + // + inline Quat & setXYZ( const Vector3 & vec ); + + // Get the x, y, and z elements of a quaternion + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a quaternion + // + inline Quat & setX( float x ); + + // Set the y element of a quaternion + // + inline Quat & setY( float y ); + + // Set the z element of a quaternion + // + inline Quat & setZ( float z ); + + // Set the w element of a quaternion + // + inline Quat & setW( float w ); + + // Get the x element of a quaternion + // + inline float getX( ) const; + + // Get the y element of a quaternion + // + inline float getY( ) const; + + // Get the z element of a quaternion + // + inline float getZ( ) const; + + // Get the w element of a quaternion + // + inline float getW( ) const; + + // Set an x, y, z, or w element of a quaternion by index + // + inline Quat & setElem( int idx, float value ); + + // Get an x, y, z, or w element of a quaternion by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two quaternions + // + inline const Quat operator +( const Quat & quat ) const; + + // Subtract a quaternion from another quaternion + // + inline const Quat operator -( const Quat & quat ) const; + + // Multiply two quaternions + // + inline const Quat operator *( const Quat & quat ) const; + + // Multiply a quaternion by a scalar + // + inline const Quat operator *( float scalar ) const; + + // Divide a quaternion by a scalar + // + inline const Quat operator /( float scalar ) const; + + // Perform compound assignment and addition with a quaternion + // + inline Quat & operator +=( const Quat & quat ); + + // Perform compound assignment and subtraction by a quaternion + // + inline Quat & operator -=( const Quat & quat ); + + // Perform compound assignment and multiplication by a quaternion + // + inline Quat & operator *=( const Quat & quat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Quat & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Quat & operator /=( float scalar ); + + // Negate all elements of a quaternion + // + inline const Quat operator -( ) const; + + // Construct an identity quaternion + // + static inline const Quat identity( ); + + // Construct a quaternion to rotate between two unit-length 3-D vectors + // NOTE: + // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + // + static inline const Quat rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ); + + // Construct a quaternion to rotate around a unit-length 3-D vector + // + static inline const Quat rotation( float radians, const Vector3 & unitVec ); + + // Construct a quaternion to rotate around the x axis + // + static inline const Quat rotationX( float radians ); + + // Construct a quaternion to rotate around the y axis + // + static inline const Quat rotationY( float radians ); + + // Construct a quaternion to rotate around the z axis + // + static inline const Quat rotationZ( float radians ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a quaternion by a scalar +// +inline const Quat operator *( float scalar, const Quat & quat ); + +// Compute the conjugate of a quaternion +// +inline const Quat conj( const Quat & quat ); + +// Use a unit-length quaternion to rotate a 3-D vector +// +inline const Vector3 rotate( const Quat & unitQuat, const Vector3 & vec ); + +// Compute the dot product of two quaternions +// +inline float dot( const Quat & quat0, const Quat & quat1 ); + +// Compute the norm of a quaternion +// +inline float norm( const Quat & quat ); + +// Compute the length of a quaternion +// +inline float length( const Quat & quat ); + +// Normalize a quaternion +// NOTE: +// The result is unpredictable when all elements of quat are at or near zero. +// +inline const Quat normalize( const Quat & quat ); + +// Linear interpolation between two quaternions +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Quat lerp( float t, const Quat & quat0, const Quat & quat1 ); + +// Spherical linear interpolation between two quaternions +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +inline const Quat slerp( float t, const Quat & unitQuat0, const Quat & unitQuat1 ); + +// Spherical quadrangle interpolation +// +inline const Quat squad( float t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ); + +// Conditionally select between two quaternions +// +inline const Quat select( const Quat & quat0, const Quat & quat1, bool select1 ); + +// Load x, y, z, and w elements from the first four words of a float array. +// +// +inline void loadXYZW( Quat & quat, const float * fptr ); + +// Store x, y, z, and w elements of a quaternion in the first four words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZW( const Quat & quat, float * fptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a quaternion +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Quat & quat ); + +// Print a quaternion and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Quat & quat, const char * name ); + +#endif + +// A 3x3 matrix in array-of-structures format +// +class Matrix3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + +public: + // Default constructor; does no initialization + // + inline Matrix3( ) { }; + + // Copy a 3x3 matrix + // + inline Matrix3( const Matrix3 & mat ); + + // Construct a 3x3 matrix containing the specified columns + // + inline Matrix3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2 ); + + // Construct a 3x3 rotation matrix from a unit-length quaternion + // + explicit inline Matrix3( const Quat & unitQuat ); + + // Set all elements of a 3x3 matrix to the same scalar value + // + explicit inline Matrix3( float scalar ); + + // Assign one 3x3 matrix to another + // + inline Matrix3 & operator =( const Matrix3 & mat ); + + // Set column 0 of a 3x3 matrix + // + inline Matrix3 & setCol0( const Vector3 & col0 ); + + // Set column 1 of a 3x3 matrix + // + inline Matrix3 & setCol1( const Vector3 & col1 ); + + // Set column 2 of a 3x3 matrix + // + inline Matrix3 & setCol2( const Vector3 & col2 ); + + // Get column 0 of a 3x3 matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x3 matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x3 matrix + // + inline const Vector3 getCol2( ) const; + + // Set the column of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setCol( int col, const Vector3 & vec ); + + // Set the row of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setRow( int row, const Vector3 & vec ); + + // Get the column of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x3 matrix referred to by column and row indices + // + inline Matrix3 & setElem( int col, int row, float val ); + + // Get the element of a 3x3 matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Add two 3x3 matrices + // + inline const Matrix3 operator +( const Matrix3 & mat ) const; + + // Subtract a 3x3 matrix from another 3x3 matrix + // + inline const Matrix3 operator -( const Matrix3 & mat ) const; + + // Negate all elements of a 3x3 matrix + // + inline const Matrix3 operator -( ) const; + + // Multiply a 3x3 matrix by a scalar + // + inline const Matrix3 operator *( float scalar ) const; + + // Multiply a 3x3 matrix by a 3-D vector + // + inline const Vector3 operator *( const Vector3 & vec ) const; + + // Multiply two 3x3 matrices + // + inline const Matrix3 operator *( const Matrix3 & mat ) const; + + // Perform compound assignment and addition with a 3x3 matrix + // + inline Matrix3 & operator +=( const Matrix3 & mat ); + + // Perform compound assignment and subtraction by a 3x3 matrix + // + inline Matrix3 & operator -=( const Matrix3 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix3 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a 3x3 matrix + // + inline Matrix3 & operator *=( const Matrix3 & mat ); + + // Construct an identity 3x3 matrix + // + static inline const Matrix3 identity( ); + + // Construct a 3x3 matrix to rotate around the x axis + // + static inline const Matrix3 rotationX( float radians ); + + // Construct a 3x3 matrix to rotate around the y axis + // + static inline const Matrix3 rotationY( float radians ); + + // Construct a 3x3 matrix to rotate around the z axis + // + static inline const Matrix3 rotationZ( float radians ); + + // Construct a 3x3 matrix to rotate around the x, y, and z axes + // + static inline const Matrix3 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix3 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix3 rotation( const Quat & unitQuat ); + + // Construct a 3x3 matrix to perform scaling + // + static inline const Matrix3 scale( const Vector3 & scaleVec ); + +}; +// Multiply a 3x3 matrix by a scalar +// +inline const Matrix3 operator *( float scalar, const Matrix3 & mat ); + +// Append (post-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ); + +// Multiply two 3x3 matrices per element +// +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); + +// Compute the absolute value of a 3x3 matrix per element +// +inline const Matrix3 absPerElem( const Matrix3 & mat ); + +// Transpose of a 3x3 matrix +// +inline const Matrix3 transpose( const Matrix3 & mat ); + +// Compute the inverse of a 3x3 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix3 inverse( const Matrix3 & mat ); + +// Determinant of a 3x3 matrix +// +inline float determinant( const Matrix3 & mat ); + +// Conditionally select between two 3x3 matrices +// +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x3 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat ); + +// Print a 3x3 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat, const char * name ); + +#endif + +// A 4x4 matrix in array-of-structures format +// +class Matrix4 +{ + Vector4 mCol0; + Vector4 mCol1; + Vector4 mCol2; + Vector4 mCol3; + +public: + // Default constructor; does no initialization + // + inline Matrix4( ) { }; + + // Copy a 4x4 matrix + // + inline Matrix4( const Matrix4 & mat ); + + // Construct a 4x4 matrix containing the specified columns + // + inline Matrix4( const Vector4 & col0, const Vector4 & col1, const Vector4 & col2, const Vector4 & col3 ); + + // Construct a 4x4 matrix from a 3x4 transformation matrix + // + explicit inline Matrix4( const Transform3 & mat ); + + // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + // + inline Matrix4( const Matrix3 & mat, const Vector3 & translateVec ); + + // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + // + inline Matrix4( const Quat & unitQuat, const Vector3 & translateVec ); + + // Set all elements of a 4x4 matrix to the same scalar value + // + explicit inline Matrix4( float scalar ); + + // Assign one 4x4 matrix to another + // + inline Matrix4 & operator =( const Matrix4 & mat ); + + // Set the upper-left 3x3 submatrix + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 4x4 matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setTranslation( const Vector3 & translateVec ); + + // Get the translation component of a 4x4 matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 4x4 matrix + // + inline Matrix4 & setCol0( const Vector4 & col0 ); + + // Set column 1 of a 4x4 matrix + // + inline Matrix4 & setCol1( const Vector4 & col1 ); + + // Set column 2 of a 4x4 matrix + // + inline Matrix4 & setCol2( const Vector4 & col2 ); + + // Set column 3 of a 4x4 matrix + // + inline Matrix4 & setCol3( const Vector4 & col3 ); + + // Get column 0 of a 4x4 matrix + // + inline const Vector4 getCol0( ) const; + + // Get column 1 of a 4x4 matrix + // + inline const Vector4 getCol1( ) const; + + // Get column 2 of a 4x4 matrix + // + inline const Vector4 getCol2( ) const; + + // Get column 3 of a 4x4 matrix + // + inline const Vector4 getCol3( ) const; + + // Set the column of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setCol( int col, const Vector4 & vec ); + + // Set the row of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setRow( int row, const Vector4 & vec ); + + // Get the column of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getCol( int col ) const; + + // Get the row of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector4 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector4 operator []( int col ) const; + + // Set the element of a 4x4 matrix referred to by column and row indices + // + inline Matrix4 & setElem( int col, int row, float val ); + + // Get the element of a 4x4 matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Add two 4x4 matrices + // + inline const Matrix4 operator +( const Matrix4 & mat ) const; + + // Subtract a 4x4 matrix from another 4x4 matrix + // + inline const Matrix4 operator -( const Matrix4 & mat ) const; + + // Negate all elements of a 4x4 matrix + // + inline const Matrix4 operator -( ) const; + + // Multiply a 4x4 matrix by a scalar + // + inline const Matrix4 operator *( float scalar ) const; + + // Multiply a 4x4 matrix by a 4-D vector + // + inline const Vector4 operator *( const Vector4 & vec ) const; + + // Multiply a 4x4 matrix by a 3-D vector + // + inline const Vector4 operator *( const Vector3 & vec ) const; + + // Multiply a 4x4 matrix by a 3-D point + // + inline const Vector4 operator *( const Point3 & pnt ) const; + + // Multiply two 4x4 matrices + // + inline const Matrix4 operator *( const Matrix4 & mat ) const; + + // Multiply a 4x4 matrix by a 3x4 transformation matrix + // + inline const Matrix4 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and addition with a 4x4 matrix + // + inline Matrix4 & operator +=( const Matrix4 & mat ); + + // Perform compound assignment and subtraction by a 4x4 matrix + // + inline Matrix4 & operator -=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix4 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a 4x4 matrix + // + inline Matrix4 & operator *=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Matrix4 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 4x4 matrix + // + static inline const Matrix4 identity( ); + + // Construct a 4x4 matrix to rotate around the x axis + // + static inline const Matrix4 rotationX( float radians ); + + // Construct a 4x4 matrix to rotate around the y axis + // + static inline const Matrix4 rotationY( float radians ); + + // Construct a 4x4 matrix to rotate around the z axis + // + static inline const Matrix4 rotationZ( float radians ); + + // Construct a 4x4 matrix to rotate around the x, y, and z axes + // + static inline const Matrix4 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix4 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix4 rotation( const Quat & unitQuat ); + + // Construct a 4x4 matrix to perform scaling + // + static inline const Matrix4 scale( const Vector3 & scaleVec ); + + // Construct a 4x4 matrix to perform translation + // + static inline const Matrix4 translation( const Vector3 & translateVec ); + + // Construct viewing matrix based on eye position, position looked at, and up direction + // + static inline const Matrix4 lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ); + + // Construct a perspective projection matrix + // + static inline const Matrix4 perspective( float fovyRadians, float aspect, float zNear, float zFar ); + + // Construct a perspective projection matrix based on frustum + // + static inline const Matrix4 frustum( float left, float right, float bottom, float top, float zNear, float zFar ); + + // Construct an orthographic projection matrix + // + static inline const Matrix4 orthographic( float left, float right, float bottom, float top, float zNear, float zFar ); + +}; +// Multiply a 4x4 matrix by a scalar +// +inline const Matrix4 operator *( float scalar, const Matrix4 & mat ); + +// Append (post-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ); + +// Multiply two 4x4 matrices per element +// +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); + +// Compute the absolute value of a 4x4 matrix per element +// +inline const Matrix4 absPerElem( const Matrix4 & mat ); + +// Transpose of a 4x4 matrix +// +inline const Matrix4 transpose( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 inverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 affineInverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. +// +inline const Matrix4 orthoInverse( const Matrix4 & mat ); + +// Determinant of a 4x4 matrix +// +inline float determinant( const Matrix4 & mat ); + +// Conditionally select between two 4x4 matrices +// +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4x4 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat ); + +// Print a 4x4 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat, const char * name ); + +#endif + +// A 3x4 transformation matrix in array-of-structures format +// +class Transform3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + Vector3 mCol3; + +public: + // Default constructor; does no initialization + // + inline Transform3( ) { }; + + // Copy a 3x4 transformation matrix + // + inline Transform3( const Transform3 & tfrm ); + + // Construct a 3x4 transformation matrix containing the specified columns + // + inline Transform3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2, const Vector3 & col3 ); + + // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + // + inline Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ); + + // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + // + inline Transform3( const Quat & unitQuat, const Vector3 & translateVec ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value + // + explicit inline Transform3( float scalar ); + + // Assign one 3x4 transformation matrix to another + // + inline Transform3 & operator =( const Transform3 & tfrm ); + + // Set the upper-left 3x3 submatrix + // + inline Transform3 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // + inline Transform3 & setTranslation( const Vector3 & translateVec ); + + // Get the translation component of a 3x4 transformation matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 3x4 transformation matrix + // + inline Transform3 & setCol0( const Vector3 & col0 ); + + // Set column 1 of a 3x4 transformation matrix + // + inline Transform3 & setCol1( const Vector3 & col1 ); + + // Set column 2 of a 3x4 transformation matrix + // + inline Transform3 & setCol2( const Vector3 & col2 ); + + // Set column 3 of a 3x4 transformation matrix + // + inline Transform3 & setCol3( const Vector3 & col3 ); + + // Get column 0 of a 3x4 transformation matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x4 transformation matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x4 transformation matrix + // + inline const Vector3 getCol2( ) const; + + // Get column 3 of a 3x4 transformation matrix + // + inline const Vector3 getCol3( ) const; + + // Set the column of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setCol( int col, const Vector3 & vec ); + + // Set the row of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setRow( int row, const Vector4 & vec ); + + // Get the column of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x4 transformation matrix referred to by column and row indices + // + inline Transform3 & setElem( int col, int row, float val ); + + // Get the element of a 3x4 transformation matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Multiply a 3x4 transformation matrix by a 3-D vector + // + inline const Vector3 operator *( const Vector3 & vec ) const; + + // Multiply a 3x4 transformation matrix by a 3-D point + // + inline const Point3 operator *( const Point3 & pnt ) const; + + // Multiply two 3x4 transformation matrices + // + inline const Transform3 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Transform3 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 3x4 transformation matrix + // + static inline const Transform3 identity( ); + + // Construct a 3x4 transformation matrix to rotate around the x axis + // + static inline const Transform3 rotationX( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis + // + static inline const Transform3 rotationY( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis + // + static inline const Transform3 rotationZ( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + // + static inline const Transform3 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + // + static inline const Transform3 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Transform3 rotation( const Quat & unitQuat ); + + // Construct a 3x4 transformation matrix to perform scaling + // + static inline const Transform3 scale( const Vector3 & scaleVec ); + + // Construct a 3x4 transformation matrix to perform translation + // + static inline const Transform3 translation( const Vector3 & translateVec ); + +}; +// Append (post-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ); + +// Multiply two 3x4 transformation matrices per element +// +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); + +// Compute the absolute value of a 3x4 transformation matrix per element +// +inline const Transform3 absPerElem( const Transform3 & tfrm ); + +// Inverse of a 3x4 transformation matrix +// NOTE: +// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. +// +inline const Transform3 inverse( const Transform3 & tfrm ); + +// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. +// +inline const Transform3 orthoInverse( const Transform3 & tfrm ); + +// Conditionally select between two 3x4 transformation matrices +// +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x4 transformation matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm ); + +// Print a 3x4 transformation matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm, const char * name ); + +#endif + +} // namespace Aos +} // namespace Vectormath + +#include "vec_aos.h" +#include "quat_aos.h" +#include "mat_aos.h" + +#endif diff --git a/Extras/PhysicsEffects/include/vecmath/neon/vectormath_neon_assembly_implementations.S b/Extras/PhysicsEffects/include/vecmath/neon/vectormath_neon_assembly_implementations.S new file mode 100644 index 0000000..c4c6d12 --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/neon/vectormath_neon_assembly_implementations.S @@ -0,0 +1,310 @@ +@ +@ Applied Research Associates Inc. (c)2011 +@ +@ 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 Applied Research Associates Inc 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. +@ +@---------------------------------------------------------------- +@ +@ This file contains ARM/NEON assembly versions of some vectormath +@ atomic functions. We have implemented here instead of inline assembly +@ because we have found gcc 4.4.3 to be too inconsistent and inadequate +@ to properly support either NEON intrinsics or inline assembly. (See +@ the inline assembly version of the vector3 dot product, which is +@ contained in vec_aos.h but compiled out, for an example of a simple +@ inline assembly function that wreaks havok if used.) +@ +@ Note that the certain NEON registers must be preserved across +@ function calls according to the following document: +@ +@ "Procedure Call Standard for the ARM? Architecture," ARM document +@ number ARM IHI 0042D, current through ABI release 2.08, +@ 16th October, 2009, section 5.1.2.1 +@ +@ The registers are: q4-q7 (and their double-word and single word +@ counterparts) +@ +@ These functions preserve all non-scratch general purpose registers +@ as well as the ones listed, and so we do not need to have extra +@ code to do the register preservation +@ + .syntax unified + .arch armv7-a + .fpu neon + .thumb + .text + .align 2 + +@---------------------------------------------------------------- +@ pfxVector3DotProductNEON +@ +@ Vector3 dot product, result stored directly to memory +@ +@ Result stored in memory pointed to by r2. r2 must point to +@ memory sufficient to store two 32 bit floats, though only the +@ first value is of interest +@---------------------------------------------------------------- + .global pfxVector3DotProductNEON + .thumb_func +pfxVector3DotProductNEON: + .fnstart + vld1.32 {d0,d1}, [r1] @ input = d0,d1\n\t" + vld1.32 {d2,d3}, [r0] @ input = d2,d3\n\t" + vmul.f32 d4, d0, d2 @ d4 = \n\t" + vpadd.f32 d4, d4, d4 @ d4 = \n\t" + vmla.f32 s8, s2, s6 @ s8 = + vld1.32 {d18,d19}, [r1] @ input + vmul.f32 d14, d16, d18 @ d14= + @ non-fused multiple accumulate + vmla.f32 d14, d17, d19 @ d14=d14+= + @ fused multiple accumulate - listed here for reference but we use vmla above + @ instead since the fused version is not recognized by GNU assembler (as part + @ of the gcc 4.4.3 Android distribution) + @ vfma.f32 {d14}, d17, d19 @ d14=d14+= + vpadd.f32 d14, d14, d14 @ add the two halves of d14 together, same result in each lane + vst1.32 {d14}, [r2] + bx lr + .fnend + +@---------------------------------------------------------------- +@ pfxVector3CrossProductNEON +@ +@ Vector3 cross product, result stored directly to memory +@ +@ Result stored in memory pointed to by r2. r2 must point to +@ memory sufficient to store four 32 bit floats, though only the +@ first 3 values are of interest +@---------------------------------------------------------------- + .global pfxVector3CrossProductNEON + .thumb_func +pfxVector3CrossProductNEON: + .fnstart + vld1.32 {d18,d19}, [r1] @ input = d18,d19 + vld1.32 {d16,d17}, [r0] @ input = d16,d17 + @ rearrange inputs into convenient order + vtrn.32 d18,d19 @ q9 = = d18,d19 + vrev64.32 d16,d16 @ q8 = = d16,d17 + vrev64.32 d18,d18 @ q9 = = d18,d19 + vtrn.32 d16,d17 @ q8 = = d16,d17 + @ perform first half of cross product using rearranged inputs + vmul.f32 q10, q8, q9 @ q10 = + @ rearrange inputs again + vtrn.32 d18,d19 @ q9 = = d18,d19 + vrev64.32 d16,d16 @ q8 = = d16,d17 + vrev64.32 d18,d18 @ q9 = = d18,d19 + vtrn.32 d16,d17 @ q8 = = d16,d17 + @ perform last half of cross product using rearranged inputs + vmls.f32 q10, q8, q9 @ q10 = + @ and store the result + vst1.32 {q10}, [r2] + bx lr + .fnend + +@---------------------------------------------------------------- +@ pfxMatrix3Matrix3ProductNEON +@ +@ Matrix3 * Matrix3 product, result stored directly to memory +@ +@ Result stored in memory pointed to by r2. r2 must point to +@ memory sufficient to store 12 32-bit floats. The reason for +@ 12 rather than 9 is that each column vector actually has +@ 4 32-bit floats rather than just 3....since NEON works with +@ double and quad vectors. +@ +@ Note that, since the inputs are loaded into registers then +@ never used again, r2 can point to one of the inputs, e.g., +@ result can be stored back out to one of the input memory +@ locations. +@---------------------------------------------------------------- + .global pfxMatrix3Matrix3ProductNEON + .thumb_func +pfxMatrix3Matrix3ProductNEON: + .fnstart + vld1.32 {d16-d19}, [r0]! @ load first eight elements of matrix 0 + vld1.32 {d20-d21}, [r0] @ load second eight elements of matrix 0 + vld1.32 {d0-d3}, [r1]! @ load first eight elements of matrix 1 + vld1.32 {d4-d5}, [r1] @ load second eight elements of matrix 1 + vmul.f32 q12, q8, d0[0] @ rslt col0 = (mat0 col0) * (mat1 col0 elt0) + vmul.f32 q13, q8, d2[0] @ rslt col1 = (mat0 col0) * (mat1 col1 elt0) + vmul.f32 q14, q8, d4[0] @ rslt col2 = (mat0 col0) * (mat1 col2 elt0) + vmla.f32 q12, q9, d0[1] @ rslt col0 += (mat0 col1) * (mat1 col0 elt1) + vmla.f32 q13, q9, d2[1] @ rslt col1 += (mat0 col1) * (mat1 col1 elt1) + vmla.f32 q14, q9, d4[1] @ rslt col2 += (mat0 col1) * (mat1 col2 elt1) + vmla.f32 q12, q10, d1[0] @ rslt col0 += (mat0 col2) * (mat1 col0 elt2) + vmla.f32 q13, q10, d3[0] @ rslt col1 += (mat0 col2) * (mat1 col1 elt2) + vmla.f32 q14, q10, d5[0] @ rslt col2 += (mat0 col2) * (mat1 col2 elt2) + vst1.32 {d24-d27}, [r2]! @ store first eight elements of result (each column has an extra float as stored) + vst1.32 {d28-d29}, [r2] @ store last four elements of result (each column has an extra float as stored) + bx lr + .fnend + +@---------------------------------------------------------------- +@ pfxMatrix4Matrix4ProductNEON +@ +@ Matrix4 * Matrix4 product, result stored directly to memory +@ +@ Result stored in memory pointed to by r2. r2 must point to +@ memory sufficient to store 16 32 bit floats. +@ +@ Note that, since the inputs are loaded into registers then +@ never used again, r2 can point to one of the inputs, e.g., +@ result can be stored back out to one of the input memory +@ locations. +@---------------------------------------------------------------- + .global pfxMatrix4Matrix4ProductNEON + .thumb_func +pfxMatrix4Matrix4ProductNEON: + .fnstart + vld1.32 {d16-d19}, [r0]! @ load first eight elements of matrix 0 + vld1.32 {d20-d23}, [r0] @ load second eight elements of matrix 0 + vld1.32 {d0-d3}, [r1]! @ load first eight elements of matrix 1 + vld1.32 {d4-d7}, [r1] @ load second eight elements of matrix 1 + vmul.f32 q12, q8, d0[0] @ rslt col0 = (mat0 col0) * (mat1 col0 elt0) + vmul.f32 q13, q8, d2[0] @ rslt col1 = (mat0 col0) * (mat1 col1 elt0) + vmul.f32 q14, q8, d4[0] @ rslt col2 = (mat0 col0) * (mat1 col2 elt0) + vmul.f32 q15, q8, d6[0] @ rslt col3 = (mat0 col0) * (mat1 col3 elt0) + vmla.f32 q12, q9, d0[1] @ rslt col0 += (mat0 col1) * (mat1 col0 elt1) + vmla.f32 q13, q9, d2[1] @ rslt col1 += (mat0 col1) * (mat1 col1 elt1) + vmla.f32 q14, q9, d4[1] @ rslt col2 += (mat0 col1) * (mat1 col2 elt1) + vmla.f32 q15, q9, d6[1] @ rslt col3 += (mat0 col1) * (mat1 col3 elt1) + vmla.f32 q12, q10, d1[0] @ rslt col0 += (mat0 col2) * (mat1 col0 elt2) + vmla.f32 q13, q10, d3[0] @ rslt col1 += (mat0 col2) * (mat1 col1 elt2) + vmla.f32 q14, q10, d5[0] @ rslt col2 += (mat0 col2) * (mat1 col2 elt2) + vmla.f32 q15, q10, d7[0] @ rslt col3 += (mat0 col2) * (mat1 col2 elt2) + vmla.f32 q12, q11, d1[1] @ rslt col0 += (mat0 col3) * (mat1 col0 elt3) + vmla.f32 q13, q11, d3[1] @ rslt col1 += (mat0 col3) * (mat1 col1 elt3) + vmla.f32 q14, q11, d5[1] @ rslt col2 += (mat0 col3) * (mat1 col2 elt3) + vmla.f32 q15, q11, d7[1] @ rslt col3 += (mat0 col3) * (mat1 col3 elt3) + vst1.32 {d24-d27}, [r2]! @ store first eight elements of result + vst1.32 {d28-d31}, [r2] @ store second eight elements of result + bx lr + .fnend + +@---------------------------------------------------------------- +@ pfxTransform3OrthoInverseNEON +@ +@ Computes the ortho inverse of a Transform 3. +@ +@ Result stored in memory pointed to by r1. r1 must point to +@ memory sufficient to store 16 32 bit floats. +@ +@ Note that, since the inputs are loaded into registers then +@ never used again, r1 can point to one of the inputs, e.g., +@ result can be stored back out to one of the input memory +@ locations. +@ +@ Note that this expects the inputs to have 4 floats per row, +@ (to be consistent with NEON quad vector), and the last float +@ in each row should be 0.0 for the math to work out. +@---------------------------------------------------------------- + .global pfxTransform3OrthoInverseNEON + .thumb_func +pfxTransform3OrthoInverseNEON: + .fnstart + @ direct load the first column of the ortho inverse result + vld1.f32 d0[0], [r0]! + vld1.f32 d2[0], [r0]! + vld1.f32 d4[0], [r0]! + vld1.f32 d1[1], [r0]! + + @ direct load the second column of the ortho inverse result + vld1.f32 d0[1], [r0]! + vld1.f32 d2[1], [r0]! + vld1.f32 d4[1], [r0]! + vld1.f32 d3[1], [r0]! + + @ direct load the third column of the ortho inverse result + vld1.f32 d1[0], [r0]! + vld1.f32 d3[0], [r0]! + + vst1.f32 {d0-d3}, [r1]! @ store first eight elements of result (1st two columns) + + vld1.f32 d5[0], [r0]! + vld1.f32 d5[1], [r0]! + + vst1.f32 {d4-d5}, [r1]! @ store next four elements of result (3rd column) + + @ move q0 into q8 so we can reuse q0 to load fourth column + @ of input. We do this to avoid using q4-q7 (which have to + @ be preserved during the function call)....needed to work + @ around some limitation rules that prevent us from accessing + @ single s registers associated with q8 and above. + vmov.f32 q8, q0 + + @ direct load the last column of the input + vld1.f32 {q0}, [r0] + + @ prepare the last column of the output + vmul.f32 q3, q8, d0[0] @ multiply result column 1 by x coord of input column 3 + vmla.f32 q3, q1, d0[1] @ multiply result column 2 by y coord of input column 3 and add + vmla.f32 q3, q2, d1[0] @ multiply result column 3 by z coord of input column 3 and add + vneg.f32 q3, q3 @ negate final column + + vst1.f32 {q3}, [r1] @ store last four elements of result (4th column) + + bx lr + .fnend + +@---------------------------------------------------------------- +@ pfxTransform3Vector3MultiplyNEON +@ +@ Computes the product of a Transform3 and a Vector3, e.g., it +@ applies the transform to the vector. +@ +@ Result stored in memory pointed to by r2. r2 must point to +@ memory sufficient to store 4 32-bit floats. +@---------------------------------------------------------------- + .global pfxTransform3Vector3MultiplyNEON + .thumb_func +pfxTransform3Vector3MultiplyNEON: + .fnstart + + vld1.32 {d16-d19}, [r0]! @ load first eight elements of transform matrix + vld1.32 {d20-d21}, [r0] @ load second eight elements of transform matrix + vld1.32 {d0-d1}, [r1] @ load the four elements of vector3 (last one is just padding) + vmul.f32 q12, q8, d0[0] @ rslt col0 = (mat0 col0) * (mat1 col0 elt0) + vmla.f32 q12, q9, d0[1] @ rslt col0 += (mat0 col1) * (mat1 col0 elt1) + vmla.f32 q12, q10, d1[0] @ rslt col0 += (mat0 col2) * (mat1 col0 elt2) + vst1.32 {d24-d25}, [r2] @ store four elements of result (last one is padding) + + bx lr + .fnend diff --git a/Extras/PhysicsEffects/include/vecmath/neon/vectormath_neon_assembly_prototypes.h b/Extras/PhysicsEffects/include/vecmath/neon/vectormath_neon_assembly_prototypes.h new file mode 100644 index 0000000..e3a9286 --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/neon/vectormath_neon_assembly_prototypes.h @@ -0,0 +1,57 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_NEON_ASSEMBLY_PROTOTYPES_H +#define _VECTORMATH_NEON_ASSEMBLY_PROTOTYPES_H + +// Prototypes for NEON assembly implementations +extern "C" +{ + // NEON assembly implementations of Vector3 functions + void pfxVector3DotProductNEON(const Vectormath::Aos::Vector3 &vec0, const Vectormath::Aos::Vector3 &vec1, float *result); + void pfxVector3CrossProductNEON(const Vectormath::Aos::Vector3 &vec0, const Vectormath::Aos::Vector3 &vec1, + Vectormath::Aos::Vector3 &result); + + // NEON assembly implementations of Matrix3 functions + void pfxMatrix3Matrix3ProductNEON(const Vectormath::Aos::Matrix3 &mat0, const Vectormath::Aos::Matrix3 &mat1, + Vectormath::Aos::Matrix3 &result); + + // NEON assembly implementations of Transform3 functions + void pfxTransform3OrthoInverseNEON(const Vectormath::Aos::Transform3 &trn, Vectormath::Aos::Transform3 &result); + void pfxTransform3Vector3MultiplyNEON(const Vectormath::Aos::Transform3 &trn, const Vectormath::Aos::Vector3 &vec, + Vectormath::Aos::Vector3 &result); + + // NEON assembly implementations of Vector4 functions + void pfxVector4DotProductNEON(const Vectormath::Aos::Vector4 &vec0, const Vectormath::Aos::Vector4 &vec1, float *result); + + // NEON assembly implementations of Matrix4 functions + void pfxMatrix4Matrix4ProductNEON(const Vectormath::Aos::Matrix4 &mat0, const Vectormath::Aos::Matrix4 &mat1, + Vectormath::Aos::Matrix4 &result); +} + +#endif // _VECTORMATH_NEON_ASSEMBLY_PROTOTYPES_H diff --git a/Extras/PhysicsEffects/include/vecmath/sse/boolInVec.h b/Extras/PhysicsEffects/include/vecmath/sse/boolInVec.h new file mode 100644 index 0000000..d18cb15 --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/sse/boolInVec.h @@ -0,0 +1,247 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _BOOLINVEC_H +#define _BOOLINVEC_H + +#include + +namespace Vectormath { + +class floatInVec; + +//-------------------------------------------------------------------------------------------------- +// boolInVec class +// + +class boolInVec +{ + private: + __m128 mData; + + inline boolInVec(__m128 vec); + public: + inline boolInVec() {} + + // matches standard type conversions + // + inline boolInVec(const floatInVec &vec); + + // explicit cast from bool + // + explicit inline boolInVec(bool scalar); + +#ifdef _VECTORMATH_NO_SCALAR_CAST + // explicit cast to bool + // + inline bool getAsBool() const; +#else + // implicit cast to bool + // + inline operator bool() const; +#endif + + // get vector data + // bool value is splatted across all word slots of vector as 0 (false) or -1 (true) + // + inline __m128 get128() const; + + // operators + // + inline const boolInVec operator ! () const; + inline boolInVec& operator = (const boolInVec &vec); + inline boolInVec& operator &= (const boolInVec &vec); + inline boolInVec& operator ^= (const boolInVec &vec); + inline boolInVec& operator |= (const boolInVec &vec); + + // friend functions + // + friend inline const boolInVec operator == (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec operator != (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec operator < (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator <= (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator > (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator >= (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator == (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator != (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator & (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec operator ^ (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec operator | (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec select(const boolInVec &vec0, const boolInVec &vec1, const boolInVec &select_vec1); +}; + +//-------------------------------------------------------------------------------------------------- +// boolInVec functions +// + +// operators +// +inline const boolInVec operator == (const boolInVec &vec0, const boolInVec &vec1); +inline const boolInVec operator != (const boolInVec &vec0, const boolInVec &vec1); +inline const boolInVec operator & (const boolInVec &vec0, const boolInVec &vec1); +inline const boolInVec operator ^ (const boolInVec &vec0, const boolInVec &vec1); +inline const boolInVec operator | (const boolInVec &vec0, const boolInVec &vec1); + +// select between vec0 and vec1 using boolInVec. +// false selects vec0, true selects vec1 +// +inline const boolInVec select(const boolInVec &vec0, const boolInVec &vec1, const boolInVec &select_vec1); + +} // namespace Vectormath + +//-------------------------------------------------------------------------------------------------- +// boolInVec implementation +// + +#include "floatInVec.h" + +namespace Vectormath { + +inline +boolInVec::boolInVec(__m128 vec) +{ + mData = vec; +} + +inline +boolInVec::boolInVec(const floatInVec &vec) +{ + *this = (vec != floatInVec(0.0f)); +} + +inline +boolInVec::boolInVec(bool scalar) +{ + unsigned int mask = -(int)scalar; + mData = _mm_set1_ps(*(float *)&mask); // TODO: Union +} + +#ifdef _VECTORMATH_NO_SCALAR_CAST +inline +bool +boolInVec::getAsBool() const +#else +inline +boolInVec::operator bool() const +#endif +{ + return *(bool *)&mData; +} + +inline +__m128 +boolInVec::get128() const +{ + return mData; +} + +inline +const boolInVec +boolInVec::operator ! () const +{ + return boolInVec(_mm_andnot_ps(mData, _mm_cmpneq_ps(_mm_setzero_ps(),_mm_setzero_ps()))); +} + +inline +boolInVec& +boolInVec::operator = (const boolInVec &vec) +{ + mData = vec.mData; + return *this; +} + +inline +boolInVec& +boolInVec::operator &= (const boolInVec &vec) +{ + *this = *this & vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator ^= (const boolInVec &vec) +{ + *this = *this ^ vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator |= (const boolInVec &vec) +{ + *this = *this | vec; + return *this; +} + +inline +const boolInVec +operator == (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_cmpeq_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator != (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_cmpneq_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator & (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_and_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator | (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_or_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator ^ (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_xor_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +select(const boolInVec &vec0, const boolInVec &vec1, const boolInVec &select_vec1) +{ + return boolInVec(vec_sel(vec0.get128(), vec1.get128(), select_vec1.get128())); +} + +} // namespace Vectormath + +#endif // boolInVec_h diff --git a/Extras/PhysicsEffects/include/vecmath/sse/floatInVec.h b/Extras/PhysicsEffects/include/vecmath/sse/floatInVec.h new file mode 100644 index 0000000..6443865 --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/sse/floatInVec.h @@ -0,0 +1,340 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _FLOATINVEC_H +#define _FLOATINVEC_H + +#include +#include + +namespace Vectormath { + +class boolInVec; + +//-------------------------------------------------------------------------------------------------- +// floatInVec class +// + +class floatInVec +{ + private: + __m128 mData; + + public: + inline floatInVec(__m128 vec); + + inline floatInVec() {} + + // matches standard type conversions + // + inline floatInVec(const boolInVec &vec); + + // construct from a slot of __m128 + // + inline floatInVec(__m128 vec, int slot); + + // explicit cast from float + // + explicit inline floatInVec(float scalar); + +#ifdef _VECTORMATH_NO_SCALAR_CAST + // explicit cast to float + // + inline float getAsFloat() const; +#else + // implicit cast to float + // + inline operator float() const; +#endif + + // get vector data + // float value is splatted across all word slots of vector + // + inline __m128 get128() const; + + // operators + // + inline const floatInVec operator ++ (int); + inline const floatInVec operator -- (int); + inline floatInVec& operator ++ (); + inline floatInVec& operator -- (); + inline const floatInVec operator - () const; + inline floatInVec& operator = (const floatInVec &vec); + inline floatInVec& operator *= (const floatInVec &vec); + inline floatInVec& operator /= (const floatInVec &vec); + inline floatInVec& operator += (const floatInVec &vec); + inline floatInVec& operator -= (const floatInVec &vec); + + // friend functions + // + friend inline const floatInVec operator * (const floatInVec &vec0, const floatInVec &vec1); + friend inline const floatInVec operator / (const floatInVec &vec0, const floatInVec &vec1); + friend inline const floatInVec operator + (const floatInVec &vec0, const floatInVec &vec1); + friend inline const floatInVec operator - (const floatInVec &vec0, const floatInVec &vec1); + friend inline const floatInVec select(const floatInVec &vec0, const floatInVec &vec1, boolInVec select_vec1); +}; + +//-------------------------------------------------------------------------------------------------- +// floatInVec functions +// + +// operators +// +inline const floatInVec operator * (const floatInVec &vec0, const floatInVec &vec1); +inline const floatInVec operator / (const floatInVec &vec0, const floatInVec &vec1); +inline const floatInVec operator + (const floatInVec &vec0, const floatInVec &vec1); +inline const floatInVec operator - (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator < (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator <= (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator > (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator >= (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator == (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator != (const floatInVec &vec0, const floatInVec &vec1); + +// select between vec0 and vec1 using boolInVec. +// false selects vec0, true selects vec1 +// +inline const floatInVec select(const floatInVec &vec0, const floatInVec &vec1, const boolInVec &select_vec1); + +} // namespace Vectormath + +//-------------------------------------------------------------------------------------------------- +// floatInVec implementation +// + +#include "boolInVec.h" + +namespace Vectormath { + +inline +floatInVec::floatInVec(__m128 vec) +{ + mData = vec; +} + +inline +floatInVec::floatInVec(const boolInVec &vec) +{ + mData = vec_sel(_mm_setzero_ps(), _mm_set1_ps(1.0f), vec.get128()); +} + +inline +floatInVec::floatInVec(__m128 vec, int slot) +{ + SSEFloat v; + v.m128 = vec; + mData = _mm_set1_ps(v.f[slot]); +} + +inline +floatInVec::floatInVec(float scalar) +{ + mData = _mm_set1_ps(scalar); +} + +#ifdef _VECTORMATH_NO_SCALAR_CAST +inline +float +floatInVec::getAsFloat() const +#else +inline +floatInVec::operator float() const +#endif +{ + return *((float *)&mData); +} + +inline +__m128 +floatInVec::get128() const +{ + return mData; +} + +inline +const floatInVec +floatInVec::operator ++ (int) +{ + __m128 olddata = mData; + operator ++(); + return floatInVec(olddata); +} + +inline +const floatInVec +floatInVec::operator -- (int) +{ + __m128 olddata = mData; + operator --(); + return floatInVec(olddata); +} + +inline +floatInVec& +floatInVec::operator ++ () +{ + *this += floatInVec(_mm_set1_ps(1.0f)); + return *this; +} + +inline +floatInVec& +floatInVec::operator -- () +{ + *this -= floatInVec(_mm_set1_ps(1.0f)); + return *this; +} + +inline +const floatInVec +floatInVec::operator - () const +{ + return floatInVec(_mm_sub_ps(_mm_setzero_ps(), mData)); +} + +inline +floatInVec& +floatInVec::operator = (const floatInVec &vec) +{ + mData = vec.mData; + return *this; +} + +inline +floatInVec& +floatInVec::operator *= (const floatInVec &vec) +{ + *this = *this * vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator /= (const floatInVec &vec) +{ + *this = *this / vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator += (const floatInVec &vec) +{ + *this = *this + vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator -= (const floatInVec &vec) +{ + *this = *this - vec; + return *this; +} + +inline +const floatInVec +operator * (const floatInVec &vec0, const floatInVec &vec1) +{ + return floatInVec(_mm_mul_ps(vec0.get128(), vec1.get128())); +} + +inline +const floatInVec +operator / (const floatInVec &num, const floatInVec &den) +{ + return floatInVec(_mm_div_ps(num.get128(), den.get128())); +} + +inline +const floatInVec +operator + (const floatInVec &vec0, const floatInVec &vec1) +{ + return floatInVec(_mm_add_ps(vec0.get128(), vec1.get128())); +} + +inline +const floatInVec +operator - (const floatInVec &vec0, const floatInVec &vec1) +{ + return floatInVec(_mm_sub_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator < (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpgt_ps(vec1.get128(), vec0.get128())); +} + +inline +const boolInVec +operator <= (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpge_ps(vec1.get128(), vec0.get128())); +} + +inline +const boolInVec +operator > (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpgt_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator >= (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpge_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator == (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpeq_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator != (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpneq_ps(vec0.get128(), vec1.get128())); +} + +inline +const floatInVec +select(const floatInVec &vec0, const floatInVec &vec1, const boolInVec &select_vec1) +{ + return floatInVec(vec_sel(vec0.get128(), vec1.get128(), select_vec1.get128())); +} + +} // namespace Vectormath + +#endif // floatInVec_h diff --git a/Extras/PhysicsEffects/include/vecmath/sse/mat_aos.h b/Extras/PhysicsEffects/include/vecmath/sse/mat_aos.h new file mode 100644 index 0000000..fe6aa62 --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/sse/mat_aos.h @@ -0,0 +1,2190 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _VECTORMATH_MAT_AOS_CPP_H +#define _VECTORMATH_MAT_AOS_CPP_H + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// Constants +// for shuffles, words are labeled [x,y,z,w] [a,b,c,d] + +#define _VECTORMATH_PERM_ZBWX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XCYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_C, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XYAB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_ZWCD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W, _VECTORMATH_PERM_C, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_XZBX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_CXXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_YAXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XAZC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_YXWZ ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W, _VECTORMATH_PERM_Z }) +#define _VECTORMATH_PERM_YBWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_XYCX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_YCXY ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y }) +#define _VECTORMATH_PERM_CXYC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_ZAYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_BZXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_B, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XZYA ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A }) +#define _VECTORMATH_PERM_ZXXB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_YXXC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_BBYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_B, _VECTORMATH_PERM_B, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PI_OVER_2 1.570796327f + +//----------------------------------------------------------------------------- +// Definitions + +VECTORMATH_FORCE_INLINE Matrix3::Matrix3( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; +} + +VECTORMATH_FORCE_INLINE Matrix3::Matrix3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +VECTORMATH_FORCE_INLINE Matrix3::Matrix3( const floatInVec &scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +VECTORMATH_FORCE_INLINE Matrix3::Matrix3( const Quat &unitQuat ) +{ + __m128 xyzw_2, wwww, yzxw, zxyw, yzxw_2, zxyw_2; + __m128 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + VM_ATTRIBUTE_ALIGN16 unsigned int sx[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int sz[4] = {0, 0, 0xffffffff, 0}; + __m128 select_x = _mm_load_ps((float *)sx); + __m128 select_z = _mm_load_ps((float *)sz); + + xyzw_2 = _mm_add_ps( unitQuat.get128(), unitQuat.get128() ); + wwww = _mm_shuffle_ps( unitQuat.get128(), unitQuat.get128(), _MM_SHUFFLE(3,3,3,3) ); + yzxw = _mm_shuffle_ps( unitQuat.get128(), unitQuat.get128(), _MM_SHUFFLE(3,0,2,1) ); + zxyw = _mm_shuffle_ps( unitQuat.get128(), unitQuat.get128(), _MM_SHUFFLE(3,1,0,2) ); + yzxw_2 = _mm_shuffle_ps( xyzw_2, xyzw_2, _MM_SHUFFLE(3,0,2,1) ); + zxyw_2 = _mm_shuffle_ps( xyzw_2, xyzw_2, _MM_SHUFFLE(3,1,0,2) ); + + tmp0 = _mm_mul_ps( yzxw_2, wwww ); // tmp0 = 2yw, 2zw, 2xw, 2w2 + tmp1 = _mm_sub_ps( _mm_set1_ps(1.0f), _mm_mul_ps(yzxw, yzxw_2) ); // tmp1 = 1 - 2y2, 1 - 2z2, 1 - 2x2, 1 - 2w2 + tmp2 = _mm_mul_ps( yzxw, xyzw_2 ); // tmp2 = 2xy, 2yz, 2xz, 2w2 + tmp0 = _mm_add_ps( _mm_mul_ps(zxyw, xyzw_2), tmp0 ); // tmp0 = 2yw + 2zx, 2zw + 2xy, 2xw + 2yz, 2w2 + 2w2 + tmp1 = _mm_sub_ps( tmp1, _mm_mul_ps(zxyw, zxyw_2) ); // tmp1 = 1 - 2y2 - 2z2, 1 - 2z2 - 2x2, 1 - 2x2 - 2y2, 1 - 2w2 - 2w2 + tmp2 = _mm_sub_ps( tmp2, _mm_mul_ps(zxyw_2, wwww) ); // tmp2 = 2xy - 2zw, 2yz - 2xw, 2xz - 2yw, 2w2 -2w2 + + tmp3 = vec_sel( tmp0, tmp1, select_x ); + tmp4 = vec_sel( tmp1, tmp2, select_x ); + tmp5 = vec_sel( tmp2, tmp0, select_x ); + mCol0 = Vector3( vec_sel( tmp3, tmp2, select_z ) ); + mCol1 = Vector3( vec_sel( tmp4, tmp0, select_z ) ); + mCol2 = Vector3( vec_sel( tmp5, tmp1, select_z ) ); +} + +VECTORMATH_FORCE_INLINE Matrix3::Matrix3( const Vector3 &_col0, const Vector3 &_col1, const Vector3 &_col2 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setCol0( const Vector3 &_col0 ) +{ + mCol0 = _col0; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setCol1( const Vector3 &_col1 ) +{ + mCol1 = _col1; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setCol2( const Vector3 &_col2 ) +{ + mCol2 = _col2; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setCol( int col, const Vector3 &vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setRow( int row, const Vector3 &vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setElem( int col, int row, const floatInVec &val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Matrix3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getCol0( ) const +{ + return mCol0; +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getCol1( ) const +{ + return mCol1; +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getCol2( ) const +{ + return mCol2; +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getRow( int row ) const +{ + return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Matrix3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator =( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 transpose( const Matrix3 & mat ) +{ + __m128 tmp0, tmp1, res0, res1, res2; + tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp1 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); + res0 = vec_mergeh( tmp0, mat.getCol1().get128() ); + //res1 = vec_perm( tmp0, mat.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + res1 = _mm_shuffle_ps( tmp0, tmp0, _MM_SHUFFLE(0,3,2,2)); + res1 = vec_sel(res1, mat.getCol1().get128(), select_y); + //res2 = vec_perm( tmp1, mat.getCol1().get128(), _VECTORMATH_PERM_XCYX ); + res2 = _mm_shuffle_ps( tmp1, tmp1, _MM_SHUFFLE(0,1,1,0)); + res2 = vec_sel(res2, vec_splat(mat.getCol1().get128(), 2), select_y); + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 inverse( const Matrix3 & mat ) +{ + __m128 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet, inv0, inv1, inv2; + tmp2 = _vmathVfCross( mat.getCol0().get128(), mat.getCol1().get128() ); + tmp0 = _vmathVfCross( mat.getCol1().get128(), mat.getCol2().get128() ); + tmp1 = _vmathVfCross( mat.getCol2().get128(), mat.getCol0().get128() ); + dot = _vmathVfDot3( tmp2, mat.getCol2().get128() ); + dot = vec_splat( dot, 0 ); + invdet = recipf4( dot ); + tmp3 = vec_mergeh( tmp0, tmp2 ); + tmp4 = vec_mergel( tmp0, tmp2 ); + inv0 = vec_mergeh( tmp3, tmp1 ); + //inv1 = vec_perm( tmp3, tmp1, _VECTORMATH_PERM_ZBWX ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + inv1 = _mm_shuffle_ps( tmp3, tmp3, _MM_SHUFFLE(0,3,2,2)); + inv1 = vec_sel(inv1, tmp1, select_y); + //inv2 = vec_perm( tmp4, tmp1, _VECTORMATH_PERM_XCYX ); + inv2 = _mm_shuffle_ps( tmp4, tmp4, _MM_SHUFFLE(0,1,1,0)); + inv2 = vec_sel(inv2, vec_splat(tmp1, 2), select_y); + inv0 = vec_mul( inv0, invdet ); + inv1 = vec_mul( inv1, invdet ); + inv2 = vec_mul( inv2, invdet ); + return Matrix3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ) + ); +} + +VECTORMATH_FORCE_INLINE const floatInVec determinant( const Matrix3 & mat ) +{ + return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) +{ + *this = *this + mat; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) +{ + *this = *this - mat; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator -( ) const +{ + return Matrix3( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 absPerElem( const Matrix3 & mat ) +{ + return Matrix3( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator *( const floatInVec &scalar ) const +{ + return Matrix3( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator *=( float scalar ) +{ + return *this *= floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 operator *( float scalar, const Matrix3 & mat ) +{ + return floatInVec(scalar) * mat; +} + +VECTORMATH_FORCE_INLINE const Matrix3 operator *( const floatInVec &scalar, const Matrix3 & mat ) +{ + return mat * scalar; +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::operator *( const Vector3 &vec ) const +{ + __m128 res; + __m128 xxxx, yyyy, zzzz; + xxxx = vec_splat( vec.get128(), 0 ); + yyyy = vec_splat( vec.get128(), 1 ); + zzzz = vec_splat( vec.get128(), 2 ); + res = vec_mul( mCol0.get128(), xxxx ); + res = vec_madd( mCol1.get128(), yyyy, res ); + res = vec_madd( mCol2.get128(), zzzz, res ); + return Vector3( res ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const +{ + return Matrix3( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) +{ + *this = *this * mat; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) +{ + return Matrix3( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::identity( ) +{ + return Matrix3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationX( const floatInVec &radians ) +{ + __m128 s, c, res1, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + return Matrix3( + Vector3::xAxis( ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationY( const floatInVec &radians ) +{ + __m128 s, c, res0, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + return Matrix3( + Vector3( res0 ), + Vector3::yAxis( ), + Vector3( res2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationZ( const floatInVec &radians ) +{ + __m128 s, c, res0, res1; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3::zAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationZYX( const Vector3 &radiansXYZ ) +{ + __m128 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + angles = Vector4( radiansXYZ, 0.0f ).get128(); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; + Z1 = vec_and( Z1, _mm_load_ps( (float *)select_xyz ) ); + Y0 = _mm_shuffle_ps( c, negS, _MM_SHUFFLE(0,1,1,1) ); + Y1 = _mm_shuffle_ps( s, c, _MM_SHUFFLE(0,1,1,1) ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_mul( Z0, Y1 ); + return Matrix3( + Vector3( vec_mul( Z0, Y0 ) ), + Vector3( vec_madd( Z1, X1, vec_mul( tmp, X0 ) ) ), + Vector3( vec_nmsub( Z1, X0, vec_mul( tmp, X1 ) ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotation( float radians, const Vector3 &unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotation( const floatInVec &radians, const Vector3 &unitVec ) +{ + __m128 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2; + axis = unitVec.get128(); + sincosf4( radians.get128(), &s, &c ); + xxxx = vec_splat( axis, 0 ); + yyyy = vec_splat( axis, 1 ); + zzzz = vec_splat( axis, 2 ); + oneMinusC = vec_sub( _mm_set1_ps(1.0f), c ); + axisS = vec_mul( axis, s ); + negAxisS = negatef4( axisS ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + //tmp0 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_XZBX ); + tmp0 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,2,0) ); + tmp0 = vec_sel(tmp0, vec_splat(negAxisS, 1), select_z); + //tmp1 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_CXXX ); + tmp1 = vec_sel( vec_splat(axisS, 0), vec_splat(negAxisS, 2), select_x ); + //tmp2 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_YAXX ); + tmp2 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,0,1) ); + tmp2 = vec_sel(tmp2, vec_splat(negAxisS, 0), select_y); + tmp0 = vec_sel( tmp0, c, select_x ); + tmp1 = vec_sel( tmp1, c, select_y ); + tmp2 = vec_sel( tmp2, c, select_z ); + return Matrix3( + Vector3( vec_madd( vec_mul( axis, xxxx ), oneMinusC, tmp0 ) ), + Vector3( vec_madd( vec_mul( axis, yyyy ), oneMinusC, tmp1 ) ), + Vector3( vec_madd( vec_mul( axis, zzzz ), oneMinusC, tmp2 ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotation( const Quat &unitQuat ) +{ + return Matrix3( unitQuat ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::scale( const Vector3 &scaleVec ) +{ + __m128 zero = _mm_setzero_ps(); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + return Matrix3( + Vector3( vec_sel( zero, scaleVec.get128(), select_x ) ), + Vector3( vec_sel( zero, scaleVec.get128(), select_y ) ), + Vector3( vec_sel( zero, scaleVec.get128(), select_z ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 appendScale( const Matrix3 & mat, const Vector3 &scaleVec ) +{ + return Matrix3( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 prependScale( const Vector3 &scaleVec, const Matrix3 & mat ) +{ + return Matrix3( + mulPerElem( mat.getCol0(), scaleVec ), + mulPerElem( mat.getCol1(), scaleVec ), + mulPerElem( mat.getCol2(), scaleVec ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, const boolInVec &select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Matrix3 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); +} + +VECTORMATH_FORCE_INLINE void print( const Matrix3 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( float scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const floatInVec &scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Transform3 & mat ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( mat.getCol3(), 1.0f ); +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Vector4 &_col0, const Vector4 &_col1, const Vector4 &_col2, const Vector4 &_col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Matrix3 & mat, const Vector3 &translateVec ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Quat &unitQuat, const Vector3 &translateVec ) +{ + Matrix3 mat; + mat = Matrix3( unitQuat ); + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol0( const Vector4 &_col0 ) +{ + mCol0 = _col0; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol1( const Vector4 &_col1 ) +{ + mCol1 = _col1; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol2( const Vector4 &_col2 ) +{ + mCol2 = _col2; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol3( const Vector4 &_col3 ) +{ + mCol3 = _col3; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol( int col, const Vector4 &vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setRow( int row, const Vector4 &vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setElem( int col, int row, const floatInVec &val ) +{ + Vector4 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Matrix4::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol0( ) const +{ + return mCol0; +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol1( ) const +{ + return mCol1; +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol2( ) const +{ + return mCol2; +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol3( ) const +{ + return mCol3; +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Matrix4::operator []( int col ) +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator =( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix4 transpose( const Matrix4 & mat ) +{ + __m128 tmp0, tmp1, tmp2, tmp3, res0, res1, res2, res3; + tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp1 = vec_mergeh( mat.getCol1().get128(), mat.getCol3().get128() ); + tmp2 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp3 = vec_mergel( mat.getCol1().get128(), mat.getCol3().get128() ); + res0 = vec_mergeh( tmp0, tmp1 ); + res1 = vec_mergel( tmp0, tmp1 ); + res2 = vec_mergeh( tmp2, tmp3 ); + res3 = vec_mergel( tmp2, tmp3 ); + return Matrix4( + Vector4( res0 ), + Vector4( res1 ), + Vector4( res2 ), + Vector4( res3 ) + ); +} + +// TODO: Tidy +static VM_ATTRIBUTE_ALIGN16 const unsigned int _vmathPNPN[4] = {0x00000000, 0x80000000, 0x00000000, 0x80000000}; +static VM_ATTRIBUTE_ALIGN16 const unsigned int _vmathNPNP[4] = {0x80000000, 0x00000000, 0x80000000, 0x00000000}; +static VM_ATTRIBUTE_ALIGN16 const float _vmathZERONE[4] = {1.0f, 0.0f, 0.0f, 1.0f}; + +VECTORMATH_FORCE_INLINE const Matrix4 inverse( const Matrix4 & mat ) +{ + __m128 Va,Vb,Vc; + __m128 r1,r2,r3,tt,tt2; + __m128 sum,Det,RDet; + __m128 trns0,trns1,trns2,trns3; + + __m128 _L1 = mat.getCol0().get128(); + __m128 _L2 = mat.getCol1().get128(); + __m128 _L3 = mat.getCol2().get128(); + __m128 _L4 = mat.getCol3().get128(); + // Calculating the minterms for the first line. + + // _mm_ror_ps is just a macro using _mm_shuffle_ps(). + tt = _L4; tt2 = _mm_ror_ps(_L3,1); + Vc = _mm_mul_ps(tt2,_mm_ror_ps(tt,0)); // V3'dot V4 + Va = _mm_mul_ps(tt2,_mm_ror_ps(tt,2)); // V3'dot V4" + Vb = _mm_mul_ps(tt2,_mm_ror_ps(tt,3)); // V3' dot V4^ + + r1 = _mm_sub_ps(_mm_ror_ps(Va,1),_mm_ror_ps(Vc,2)); // V3" dot V4^ - V3^ dot V4" + r2 = _mm_sub_ps(_mm_ror_ps(Vb,2),_mm_ror_ps(Vb,0)); // V3^ dot V4' - V3' dot V4^ + r3 = _mm_sub_ps(_mm_ror_ps(Va,0),_mm_ror_ps(Vc,1)); // V3' dot V4" - V3" dot V4' + + tt = _L2; + Va = _mm_ror_ps(tt,1); sum = _mm_mul_ps(Va,r1); + Vb = _mm_ror_ps(tt,2); sum = _mm_add_ps(sum,_mm_mul_ps(Vb,r2)); + Vc = _mm_ror_ps(tt,3); sum = _mm_add_ps(sum,_mm_mul_ps(Vc,r3)); + + // Calculating the determinant. + Det = _mm_mul_ps(sum,_L1); + Det = _mm_add_ps(Det,_mm_movehl_ps(Det,Det)); + + const __m128 Sign_PNPN = _mm_load_ps((float *)_vmathPNPN); + const __m128 Sign_NPNP = _mm_load_ps((float *)_vmathNPNP); + + __m128 mtL1 = _mm_xor_ps(sum,Sign_PNPN); + + // Calculating the minterms of the second line (using previous results). + tt = _mm_ror_ps(_L1,1); sum = _mm_mul_ps(tt,r1); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); + __m128 mtL2 = _mm_xor_ps(sum,Sign_NPNP); + + // Testing the determinant. + Det = _mm_sub_ss(Det,_mm_shuffle_ps(Det,Det,1)); + + // Calculating the minterms of the third line. + tt = _mm_ror_ps(_L1,1); + Va = _mm_mul_ps(tt,Vb); // V1' dot V2" + Vb = _mm_mul_ps(tt,Vc); // V1' dot V2^ + Vc = _mm_mul_ps(tt,_L2); // V1' dot V2 + + r1 = _mm_sub_ps(_mm_ror_ps(Va,1),_mm_ror_ps(Vc,2)); // V1" dot V2^ - V1^ dot V2" + r2 = _mm_sub_ps(_mm_ror_ps(Vb,2),_mm_ror_ps(Vb,0)); // V1^ dot V2' - V1' dot V2^ + r3 = _mm_sub_ps(_mm_ror_ps(Va,0),_mm_ror_ps(Vc,1)); // V1' dot V2" - V1" dot V2' + + tt = _mm_ror_ps(_L4,1); sum = _mm_mul_ps(tt,r1); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); + __m128 mtL3 = _mm_xor_ps(sum,Sign_PNPN); + + // Dividing is FASTER than rcp_nr! (Because rcp_nr causes many register-memory RWs). + RDet = _mm_div_ss(_mm_load_ss((float *)&_vmathZERONE), Det); // TODO: just 1.0f? + RDet = _mm_shuffle_ps(RDet,RDet,0x00); + + // Devide the first 12 minterms with the determinant. + mtL1 = _mm_mul_ps(mtL1, RDet); + mtL2 = _mm_mul_ps(mtL2, RDet); + mtL3 = _mm_mul_ps(mtL3, RDet); + + // Calculate the minterms of the forth line and devide by the determinant. + tt = _mm_ror_ps(_L3,1); sum = _mm_mul_ps(tt,r1); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); + __m128 mtL4 = _mm_xor_ps(sum,Sign_NPNP); + mtL4 = _mm_mul_ps(mtL4, RDet); + + // Now we just have to transpose the minterms matrix. + trns0 = _mm_unpacklo_ps(mtL1,mtL2); + trns1 = _mm_unpacklo_ps(mtL3,mtL4); + trns2 = _mm_unpackhi_ps(mtL1,mtL2); + trns3 = _mm_unpackhi_ps(mtL3,mtL4); + _L1 = _mm_movelh_ps(trns0,trns1); + _L2 = _mm_movehl_ps(trns1,trns0); + _L3 = _mm_movelh_ps(trns2,trns3); + _L4 = _mm_movehl_ps(trns3,trns2); + + return Matrix4( + Vector4( _L1 ), + Vector4( _L2 ), + Vector4( _L3 ), + Vector4( _L4 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 affineInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( inverse( affineMat ) ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 orthoInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( orthoInverse( affineMat ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec determinant( const Matrix4 & mat ) +{ + __m128 Va,Vb,Vc; + __m128 r1,r2,r3,tt,tt2; + __m128 sum,Det; + + __m128 _L1 = mat.getCol0().get128(); + __m128 _L2 = mat.getCol1().get128(); + __m128 _L3 = mat.getCol2().get128(); + __m128 _L4 = mat.getCol3().get128(); + // Calculating the minterms for the first line. + + // _mm_ror_ps is just a macro using _mm_shuffle_ps(). + tt = _L4; tt2 = _mm_ror_ps(_L3,1); + Vc = _mm_mul_ps(tt2,_mm_ror_ps(tt,0)); // V3' dot V4 + Va = _mm_mul_ps(tt2,_mm_ror_ps(tt,2)); // V3' dot V4" + Vb = _mm_mul_ps(tt2,_mm_ror_ps(tt,3)); // V3' dot V4^ + + r1 = _mm_sub_ps(_mm_ror_ps(Va,1),_mm_ror_ps(Vc,2)); // V3" dot V4^ - V3^ dot V4" + r2 = _mm_sub_ps(_mm_ror_ps(Vb,2),_mm_ror_ps(Vb,0)); // V3^ dot V4' - V3' dot V4^ + r3 = _mm_sub_ps(_mm_ror_ps(Va,0),_mm_ror_ps(Vc,1)); // V3' dot V4" - V3" dot V4' + + tt = _L2; + Va = _mm_ror_ps(tt,1); sum = _mm_mul_ps(Va,r1); + Vb = _mm_ror_ps(tt,2); sum = _mm_add_ps(sum,_mm_mul_ps(Vb,r2)); + Vc = _mm_ror_ps(tt,3); sum = _mm_add_ps(sum,_mm_mul_ps(Vc,r3)); + + // Calculating the determinant. + Det = _mm_mul_ps(sum,_L1); + Det = _mm_add_ps(Det,_mm_movehl_ps(Det,Det)); + + // Calculating the minterms of the second line (using previous results). + tt = _mm_ror_ps(_L1,1); sum = _mm_mul_ps(tt,r1); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); + + // Testing the determinant. + Det = _mm_sub_ss(Det,_mm_shuffle_ps(Det,Det,1)); + return floatInVec(Det, 0); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ), + ( mCol3 + mat.mCol3 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ), + ( mCol3 - mat.mCol3 ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) +{ + *this = *this + mat; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) +{ + *this = *this - mat; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator -( ) const +{ + return Matrix4( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ), + ( -mCol3 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 absPerElem( const Matrix4 & mat ) +{ + return Matrix4( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ), + absPerElem( mat.getCol3() ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator *( const floatInVec &scalar ) const +{ + return Matrix4( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ), + ( mCol3 * scalar ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator *=( float scalar ) +{ + return *this *= floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix4 operator *( float scalar, const Matrix4 & mat ) +{ + return floatInVec(scalar) * mat; +} + +VECTORMATH_FORCE_INLINE const Matrix4 operator *( const floatInVec &scalar, const Matrix4 & mat ) +{ + return mat * scalar; +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::operator *( const Vector4 &vec ) const +{ + return Vector4( + _mm_add_ps( + _mm_add_ps(_mm_mul_ps(mCol0.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(0,0,0,0))), _mm_mul_ps(mCol1.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(1,1,1,1)))), + _mm_add_ps(_mm_mul_ps(mCol2.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(2,2,2,2))), _mm_mul_ps(mCol3.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(3,3,3,3))))) + ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::operator *( const Vector3 &vec ) const +{ + return Vector4( + _mm_add_ps( + _mm_add_ps(_mm_mul_ps(mCol0.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(0,0,0,0))), _mm_mul_ps(mCol1.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(1,1,1,1)))), + _mm_mul_ps(mCol2.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(2,2,2,2)))) + ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::operator *( const Point3 &pnt ) const +{ + return Vector4( + _mm_add_ps( + _mm_add_ps(_mm_mul_ps(mCol0.get128(), _mm_shuffle_ps(pnt.get128(), pnt.get128(), _MM_SHUFFLE(0,0,0,0))), _mm_mul_ps(mCol1.get128(), _mm_shuffle_ps(pnt.get128(), pnt.get128(), _MM_SHUFFLE(1,1,1,1)))), + _mm_add_ps(_mm_mul_ps(mCol2.get128(), _mm_shuffle_ps(pnt.get128(), pnt.get128(), _MM_SHUFFLE(2,2,2,2))), mCol3.get128())) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const +{ + return Matrix4( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ), + ( *this * mat.mCol3 ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) +{ + *this = *this * mat; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const +{ + return Matrix4( + ( *this * tfrm.getCol0() ), + ( *this * tfrm.getCol1() ), + ( *this * tfrm.getCol2() ), + ( *this * Point3( tfrm.getCol3() ) ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) +{ + return Matrix4( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ), + mulPerElem( mat0.getCol3(), mat1.getCol3() ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::identity( ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) +{ + mCol0.setXYZ( mat3.getCol0() ); + mCol1.setXYZ( mat3.getCol1() ); + mCol2.setXYZ( mat3.getCol2() ); + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix4::getUpper3x3( ) const +{ + return Matrix3( + mCol0.getXYZ( ), + mCol1.getXYZ( ), + mCol2.getXYZ( ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setTranslation( const Vector3 &translateVec ) +{ + mCol3.setXYZ( translateVec ); + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix4::getTranslation( ) const +{ + return mCol3.getXYZ( ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationX( const floatInVec &radians ) +{ + __m128 s, c, res1, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + return Matrix4( + Vector4::xAxis( ), + Vector4( res1 ), + Vector4( res2 ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationY( const floatInVec &radians ) +{ + __m128 s, c, res0, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + return Matrix4( + Vector4( res0 ), + Vector4::yAxis( ), + Vector4( res2 ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationZ( const floatInVec &radians ) +{ + __m128 s, c, res0, res1; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + return Matrix4( + Vector4( res0 ), + Vector4( res1 ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationZYX( const Vector3 &radiansXYZ ) +{ + __m128 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + angles = Vector4( radiansXYZ, 0.0f ).get128(); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; + Z1 = vec_and( Z1, _mm_load_ps( (float *)select_xyz ) ); + Y0 = _mm_shuffle_ps( c, negS, _MM_SHUFFLE(0,1,1,1) ); + Y1 = _mm_shuffle_ps( s, c, _MM_SHUFFLE(0,1,1,1) ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_mul( Z0, Y1 ); + return Matrix4( + Vector4( vec_mul( Z0, Y0 ) ), + Vector4( vec_madd( Z1, X1, vec_mul( tmp, X0 ) ) ), + Vector4( vec_nmsub( Z1, X0, vec_mul( tmp, X1 ) ) ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotation( float radians, const Vector3 &unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotation( const floatInVec &radians, const Vector3 &unitVec ) +{ + __m128 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2; + axis = unitVec.get128(); + sincosf4( radians.get128(), &s, &c ); + xxxx = vec_splat( axis, 0 ); + yyyy = vec_splat( axis, 1 ); + zzzz = vec_splat( axis, 2 ); + oneMinusC = vec_sub( _mm_set1_ps(1.0f), c ); + axisS = vec_mul( axis, s ); + negAxisS = negatef4( axisS ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + //tmp0 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_XZBX ); + tmp0 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,2,0) ); + tmp0 = vec_sel(tmp0, vec_splat(negAxisS, 1), select_z); + //tmp1 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_CXXX ); + tmp1 = vec_sel( vec_splat(axisS, 0), vec_splat(negAxisS, 2), select_x ); + //tmp2 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_YAXX ); + tmp2 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,0,1) ); + tmp2 = vec_sel(tmp2, vec_splat(negAxisS, 0), select_y); + tmp0 = vec_sel( tmp0, c, select_x ); + tmp1 = vec_sel( tmp1, c, select_y ); + tmp2 = vec_sel( tmp2, c, select_z ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; + axis = vec_and( axis, _mm_load_ps( (float *)select_xyz ) ); + tmp0 = vec_and( tmp0, _mm_load_ps( (float *)select_xyz ) ); + tmp1 = vec_and( tmp1, _mm_load_ps( (float *)select_xyz ) ); + tmp2 = vec_and( tmp2, _mm_load_ps( (float *)select_xyz ) ); + return Matrix4( + Vector4( vec_madd( vec_mul( axis, xxxx ), oneMinusC, tmp0 ) ), + Vector4( vec_madd( vec_mul( axis, yyyy ), oneMinusC, tmp1 ) ), + Vector4( vec_madd( vec_mul( axis, zzzz ), oneMinusC, tmp2 ) ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotation( const Quat &unitQuat ) +{ + return Matrix4( Transform3::rotation( unitQuat ) ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::scale( const Vector3 &scaleVec ) +{ + __m128 zero = _mm_setzero_ps(); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + return Matrix4( + Vector4( vec_sel( zero, scaleVec.get128(), select_x ) ), + Vector4( vec_sel( zero, scaleVec.get128(), select_y ) ), + Vector4( vec_sel( zero, scaleVec.get128(), select_z ) ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 appendScale( const Matrix4 & mat, const Vector3 &scaleVec ) +{ + return Matrix4( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ), + mat.getCol3() + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 prependScale( const Vector3 &scaleVec, const Matrix4 & mat ) +{ + Vector4 scale4; + scale4 = Vector4( scaleVec, 1.0f ); + return Matrix4( + mulPerElem( mat.getCol0(), scale4 ), + mulPerElem( mat.getCol1(), scale4 ), + mulPerElem( mat.getCol2(), scale4 ), + mulPerElem( mat.getCol3(), scale4 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::translation( const Vector3 &translateVec ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4( translateVec, 1.0f ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::lookAt( const Point3 &eyePos, const Point3 &lookAtPos, const Vector3 &upVec ) +{ + Matrix4 m4EyeFrame; + Vector3 v3X, v3Y, v3Z; + v3Y = normalize( upVec ); + v3Z = normalize( ( eyePos - lookAtPos ) ); + v3X = normalize( cross( v3Y, v3Z ) ); + v3Y = cross( v3Z, v3X ); + m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); + return orthoInverse( m4EyeFrame ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::perspective( float fovyRadians, float aspect, float zNear, float zFar ) +{ + float f, rangeInv; + __m128 zero, col0, col1, col2, col3; + union { __m128 v; float s[4]; } tmp; + f = tanf( _VECTORMATH_PI_OVER_2 - fovyRadians * 0.5f ); + rangeInv = 1.0f / ( zNear - zFar ); + zero = _mm_setzero_ps(); + tmp.v = zero; + tmp.s[0] = f / aspect; + col0 = tmp.v; + tmp.v = zero; + tmp.s[1] = f; + col1 = tmp.v; + tmp.v = zero; + tmp.s[2] = ( zNear + zFar ) * rangeInv; + tmp.s[3] = -1.0f; + col2 = tmp.v; + tmp.v = zero; + tmp.s[2] = zNear * zFar * rangeInv * 2.0f; + col3 = tmp.v; + return Matrix4( + Vector4( col0 ), + Vector4( col1 ), + Vector4( col2 ), + Vector4( col3 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::frustum( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + __m128 lbf, rtn; + __m128 diff, sum, inv_diff; + __m128 diagonal, column, near2; + __m128 zero = _mm_setzero_ps(); + union { __m128 v; float s[4]; } l, f, r, n, b, t; // TODO: Union? + l.s[0] = left; + f.s[0] = zFar; + r.s[0] = right; + n.s[0] = zNear; + b.s[0] = bottom; + t.s[0] = top; + lbf = vec_mergeh( l.v, f.v ); + rtn = vec_mergeh( r.v, n.v ); + lbf = vec_mergeh( lbf, b.v ); + rtn = vec_mergeh( rtn, t.v ); + diff = vec_sub( rtn, lbf ); + sum = vec_add( rtn, lbf ); + inv_diff = recipf4( diff ); + near2 = vec_splat( n.v, 0 ); + near2 = vec_add( near2, near2 ); + diagonal = vec_mul( near2, inv_diff ); + column = vec_mul( sum, inv_diff ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_w[4] = {0, 0, 0, 0xffffffff}; + return Matrix4( + Vector4( vec_sel( zero, diagonal, select_x ) ), + Vector4( vec_sel( zero, diagonal, select_y ) ), + Vector4( vec_sel( column, _mm_set1_ps(-1.0f), select_w ) ), + Vector4( vec_sel( zero, vec_mul( diagonal, vec_splat( f.v, 0 ) ), select_z ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::orthographic( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + __m128 lbf, rtn; + __m128 diff, sum, inv_diff, neg_inv_diff; + __m128 diagonal, column; + __m128 zero = _mm_setzero_ps(); + union { __m128 v; float s[4]; } l, f, r, n, b, t; + l.s[0] = left; + f.s[0] = zFar; + r.s[0] = right; + n.s[0] = zNear; + b.s[0] = bottom; + t.s[0] = top; + lbf = vec_mergeh( l.v, f.v ); + rtn = vec_mergeh( r.v, n.v ); + lbf = vec_mergeh( lbf, b.v ); + rtn = vec_mergeh( rtn, t.v ); + diff = vec_sub( rtn, lbf ); + sum = vec_add( rtn, lbf ); + inv_diff = recipf4( diff ); + neg_inv_diff = negatef4( inv_diff ); + diagonal = vec_add( inv_diff, inv_diff ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_w[4] = {0, 0, 0, 0xffffffff}; + column = vec_mul( sum, vec_sel( neg_inv_diff, inv_diff, select_z ) ); // TODO: no madds with zero + return Matrix4( + Vector4( vec_sel( zero, diagonal, select_x ) ), + Vector4( vec_sel( zero, diagonal, select_y ) ), + Vector4( vec_sel( zero, diagonal, select_z ) ), + Vector4( vec_sel( column, _mm_set1_ps(1.0f), select_w ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, const boolInVec &select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Matrix4 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); + print( mat.getRow( 3 ) ); +} + +VECTORMATH_FORCE_INLINE void print( const Matrix4 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +VECTORMATH_FORCE_INLINE Transform3::Transform3( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; +} + +VECTORMATH_FORCE_INLINE Transform3::Transform3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +VECTORMATH_FORCE_INLINE Transform3::Transform3( const floatInVec &scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +VECTORMATH_FORCE_INLINE Transform3::Transform3( const Vector3 &_col0, const Vector3 &_col1, const Vector3 &_col2, const Vector3 &_col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +VECTORMATH_FORCE_INLINE Transform3::Transform3( const Matrix3 & tfrm, const Vector3 &translateVec ) +{ + this->setUpper3x3( tfrm ); + this->setTranslation( translateVec ); +} + +VECTORMATH_FORCE_INLINE Transform3::Transform3( const Quat &unitQuat, const Vector3 &translateVec ) +{ + this->setUpper3x3( Matrix3( unitQuat ) ); + this->setTranslation( translateVec ); +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol0( const Vector3 &_col0 ) +{ + mCol0 = _col0; + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol1( const Vector3 &_col1 ) +{ + mCol1 = _col1; + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol2( const Vector3 &_col2 ) +{ + mCol2 = _col2; + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol3( const Vector3 &_col3 ) +{ + mCol3 = _col3; + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol( int col, const Vector3 &vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setRow( int row, const Vector4 &vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setElem( int col, int row, const floatInVec &val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Transform3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol0( ) const +{ + return mCol0; +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol1( ) const +{ + return mCol1; +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol2( ) const +{ + return mCol2; +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol3( ) const +{ + return mCol3; +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector4 Transform3::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Transform3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::operator =( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; + return *this; +} + +VECTORMATH_FORCE_INLINE const Transform3 inverse( const Transform3 & tfrm ) +{ + __m128 inv0, inv1, inv2, inv3; + __m128 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet; + __m128 xxxx, yyyy, zzzz; + tmp2 = _vmathVfCross( tfrm.getCol0().get128(), tfrm.getCol1().get128() ); + tmp0 = _vmathVfCross( tfrm.getCol1().get128(), tfrm.getCol2().get128() ); + tmp1 = _vmathVfCross( tfrm.getCol2().get128(), tfrm.getCol0().get128() ); + inv3 = negatef4( tfrm.getCol3().get128() ); + dot = _vmathVfDot3( tmp2, tfrm.getCol2().get128() ); + dot = vec_splat( dot, 0 ); + invdet = recipf4( dot ); + tmp3 = vec_mergeh( tmp0, tmp2 ); + tmp4 = vec_mergel( tmp0, tmp2 ); + inv0 = vec_mergeh( tmp3, tmp1 ); + xxxx = vec_splat( inv3, 0 ); + //inv1 = vec_perm( tmp3, tmp1, _VECTORMATH_PERM_ZBWX ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + inv1 = _mm_shuffle_ps( tmp3, tmp3, _MM_SHUFFLE(0,3,2,2)); + inv1 = vec_sel(inv1, tmp1, select_y); + //inv2 = vec_perm( tmp4, tmp1, _VECTORMATH_PERM_XCYX ); + inv2 = _mm_shuffle_ps( tmp4, tmp4, _MM_SHUFFLE(0,1,1,0)); + inv2 = vec_sel(inv2, vec_splat(tmp1, 2), select_y); + yyyy = vec_splat( inv3, 1 ); + zzzz = vec_splat( inv3, 2 ); + inv3 = vec_mul( inv0, xxxx ); + inv3 = vec_madd( inv1, yyyy, inv3 ); + inv3 = vec_madd( inv2, zzzz, inv3 ); + inv0 = vec_mul( inv0, invdet ); + inv1 = vec_mul( inv1, invdet ); + inv2 = vec_mul( inv2, invdet ); + inv3 = vec_mul( inv3, invdet ); + return Transform3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ), + Vector3( inv3 ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 orthoInverse( const Transform3 & tfrm ) +{ + __m128 inv0, inv1, inv2, inv3; + __m128 tmp0, tmp1; + __m128 xxxx, yyyy, zzzz; + tmp0 = vec_mergeh( tfrm.getCol0().get128(), tfrm.getCol2().get128() ); + tmp1 = vec_mergel( tfrm.getCol0().get128(), tfrm.getCol2().get128() ); + inv3 = negatef4( tfrm.getCol3().get128() ); + inv0 = vec_mergeh( tmp0, tfrm.getCol1().get128() ); + xxxx = vec_splat( inv3, 0 ); + //inv1 = vec_perm( tmp0, tfrm.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + inv1 = _mm_shuffle_ps( tmp0, tmp0, _MM_SHUFFLE(0,3,2,2)); + inv1 = vec_sel(inv1, tfrm.getCol1().get128(), select_y); + //inv2 = vec_perm( tmp1, tfrm.getCol1().get128(), _VECTORMATH_PERM_XCYX ); + inv2 = _mm_shuffle_ps( tmp1, tmp1, _MM_SHUFFLE(0,1,1,0)); + inv2 = vec_sel(inv2, vec_splat(tfrm.getCol1().get128(), 2), select_y); + yyyy = vec_splat( inv3, 1 ); + zzzz = vec_splat( inv3, 2 ); + inv3 = vec_mul( inv0, xxxx ); + inv3 = vec_madd( inv1, yyyy, inv3 ); + inv3 = vec_madd( inv2, zzzz, inv3 ); + return Transform3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ), + Vector3( inv3 ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 absPerElem( const Transform3 & tfrm ) +{ + return Transform3( + absPerElem( tfrm.getCol0() ), + absPerElem( tfrm.getCol1() ), + absPerElem( tfrm.getCol2() ), + absPerElem( tfrm.getCol3() ) + ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::operator *( const Vector3 &vec ) const +{ + __m128 res; + __m128 xxxx, yyyy, zzzz; + xxxx = vec_splat( vec.get128(), 0 ); + yyyy = vec_splat( vec.get128(), 1 ); + zzzz = vec_splat( vec.get128(), 2 ); + res = vec_mul( mCol0.get128(), xxxx ); + res = vec_madd( mCol1.get128(), yyyy, res ); + res = vec_madd( mCol2.get128(), zzzz, res ); + return Vector3( res ); +} + +VECTORMATH_FORCE_INLINE const Point3 Transform3::operator *( const Point3 &pnt ) const +{ + __m128 tmp0, tmp1, res; + __m128 xxxx, yyyy, zzzz; + xxxx = vec_splat( pnt.get128(), 0 ); + yyyy = vec_splat( pnt.get128(), 1 ); + zzzz = vec_splat( pnt.get128(), 2 ); + tmp0 = vec_mul( mCol0.get128(), xxxx ); + tmp1 = vec_mul( mCol1.get128(), yyyy ); + tmp0 = vec_madd( mCol2.get128(), zzzz, tmp0 ); + tmp1 = vec_add( mCol3.get128(), tmp1 ); + res = vec_add( tmp0, tmp1 ); + return Point3( res ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::operator *( const Transform3 & tfrm ) const +{ + return Transform3( + ( *this * tfrm.mCol0 ), + ( *this * tfrm.mCol1 ), + ( *this * tfrm.mCol2 ), + Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) + ); +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +VECTORMATH_FORCE_INLINE const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) +{ + return Transform3( + mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), + mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), + mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), + mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::identity( ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) +{ + mCol0 = tfrm.getCol0(); + mCol1 = tfrm.getCol1(); + mCol2 = tfrm.getCol2(); + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 Transform3::getUpper3x3( ) const +{ + return Matrix3( mCol0, mCol1, mCol2 ); +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setTranslation( const Vector3 &translateVec ) +{ + mCol3 = translateVec; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getTranslation( ) const +{ + return mCol3; +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationX( const floatInVec &radians ) +{ + __m128 s, c, res1, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + return Transform3( + Vector3::xAxis( ), + Vector3( res1 ), + Vector3( res2 ), + Vector3( _mm_setzero_ps() ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationY( const floatInVec &radians ) +{ + __m128 s, c, res0, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + return Transform3( + Vector3( res0 ), + Vector3::yAxis( ), + Vector3( res2 ), + Vector3( 0.0f ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationZ( const floatInVec &radians ) +{ + __m128 s, c, res0, res1; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + __m128 zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + return Transform3( + Vector3( res0 ), + Vector3( res1 ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationZYX( const Vector3 &radiansXYZ ) +{ + __m128 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + angles = Vector4( radiansXYZ, 0.0f ).get128(); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; + Z1 = vec_and( Z1, _mm_load_ps( (float *)select_xyz ) ); + Y0 = _mm_shuffle_ps( c, negS, _MM_SHUFFLE(0,1,1,1) ); + Y1 = _mm_shuffle_ps( s, c, _MM_SHUFFLE(0,1,1,1) ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_mul( Z0, Y1 ); + return Transform3( + Vector3( vec_mul( Z0, Y0 ) ), + Vector3( vec_madd( Z1, X1, vec_mul( tmp, X0 ) ) ), + Vector3( vec_nmsub( Z1, X0, vec_mul( tmp, X1 ) ) ), + Vector3( 0.0f ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotation( float radians, const Vector3 &unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotation( const floatInVec &radians, const Vector3 &unitVec ) +{ + return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( 0.0f ) ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotation( const Quat &unitQuat ) +{ + return Transform3( Matrix3( unitQuat ), Vector3( 0.0f ) ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::scale( const Vector3 &scaleVec ) +{ + __m128 zero = _mm_setzero_ps(); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + return Transform3( + Vector3( vec_sel( zero, scaleVec.get128(), select_x ) ), + Vector3( vec_sel( zero, scaleVec.get128(), select_y ) ), + Vector3( vec_sel( zero, scaleVec.get128(), select_z ) ), + Vector3( 0.0f ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 appendScale( const Transform3 & tfrm, const Vector3 &scaleVec ) +{ + return Transform3( + ( tfrm.getCol0() * scaleVec.getX( ) ), + ( tfrm.getCol1() * scaleVec.getY( ) ), + ( tfrm.getCol2() * scaleVec.getZ( ) ), + tfrm.getCol3() + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 prependScale( const Vector3 &scaleVec, const Transform3 & tfrm ) +{ + return Transform3( + mulPerElem( tfrm.getCol0(), scaleVec ), + mulPerElem( tfrm.getCol1(), scaleVec ), + mulPerElem( tfrm.getCol2(), scaleVec ), + mulPerElem( tfrm.getCol3(), scaleVec ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::translation( const Vector3 &translateVec ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + translateVec + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, const boolInVec &select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Transform3 & tfrm ) +{ + print( tfrm.getRow( 0 ) ); + print( tfrm.getRow( 1 ) ); + print( tfrm.getRow( 2 ) ); +} + +VECTORMATH_FORCE_INLINE void print( const Transform3 & tfrm, const char * name ) +{ + printf("%s:\n", name); + print( tfrm ); +} + +#endif + +VECTORMATH_FORCE_INLINE Quat::Quat( const Matrix3 & tfrm ) +{ + __m128 res; + __m128 col0, col1, col2; + __m128 xx_yy, xx_yy_zz_xx, yy_zz_xx_yy, zz_xx_yy_zz, diagSum, diagDiff; + __m128 zy_xz_yx, yz_zx_xy, sum, diff; + __m128 radicand, invSqrt, scale; + __m128 res0, res1, res2, res3; + __m128 xx, yy, zz; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_w[4] = {0, 0, 0, 0xffffffff}; + + col0 = tfrm.getCol0().get128(); + col1 = tfrm.getCol1().get128(); + col2 = tfrm.getCol2().get128(); + + /* four cases: */ + /* trace > 0 */ + /* else */ + /* xx largest diagonal element */ + /* yy largest diagonal element */ + /* zz largest diagonal element */ + + /* compute quaternion for each case */ + + xx_yy = vec_sel( col0, col1, select_y ); + //xx_yy_zz_xx = vec_perm( xx_yy, col2, _VECTORMATH_PERM_XYCX ); + //yy_zz_xx_yy = vec_perm( xx_yy, col2, _VECTORMATH_PERM_YCXY ); + //zz_xx_yy_zz = vec_perm( xx_yy, col2, _VECTORMATH_PERM_CXYC ); + xx_yy_zz_xx = _mm_shuffle_ps( xx_yy, xx_yy, _MM_SHUFFLE(0,0,1,0) ); + xx_yy_zz_xx = vec_sel( xx_yy_zz_xx, col2, select_z ); // TODO: Ck + yy_zz_xx_yy = _mm_shuffle_ps( xx_yy_zz_xx, xx_yy_zz_xx, _MM_SHUFFLE(1,0,2,1) ); + zz_xx_yy_zz = _mm_shuffle_ps( xx_yy_zz_xx, xx_yy_zz_xx, _MM_SHUFFLE(2,1,0,2) ); + + diagSum = vec_add( vec_add( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); + diagDiff = vec_sub( vec_sub( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); + radicand = vec_add( vec_sel( diagDiff, diagSum, select_w ), _mm_set1_ps(1.0f) ); + // invSqrt = rsqrtf4( radicand ); + invSqrt = newtonrapson_rsqrt4( radicand ); + + + + zy_xz_yx = vec_sel( col0, col1, select_z ); // zy_xz_yx = 00 01 12 03 + //zy_xz_yx = vec_perm( zy_xz_yx, col2, _VECTORMATH_PERM_ZAYX ); + zy_xz_yx = _mm_shuffle_ps( zy_xz_yx, zy_xz_yx, _MM_SHUFFLE(0,1,2,2) ); // zy_xz_yx = 12 12 01 00 + zy_xz_yx = vec_sel( zy_xz_yx, vec_splat(col2, 0), select_y ); // zy_xz_yx = 12 20 01 00 + yz_zx_xy = vec_sel( col0, col1, select_x ); // yz_zx_xy = 10 01 02 03 + //yz_zx_xy = vec_perm( yz_zx_xy, col2, _VECTORMATH_PERM_BZXX ); + yz_zx_xy = _mm_shuffle_ps( yz_zx_xy, yz_zx_xy, _MM_SHUFFLE(0,0,2,0) ); // yz_zx_xy = 10 02 10 10 + yz_zx_xy = vec_sel( yz_zx_xy, vec_splat(col2, 1), select_x ); // yz_zx_xy = 21 02 10 10 + + sum = vec_add( zy_xz_yx, yz_zx_xy ); + diff = vec_sub( zy_xz_yx, yz_zx_xy ); + + scale = vec_mul( invSqrt, _mm_set1_ps(0.5f) ); + + //res0 = vec_perm( sum, diff, _VECTORMATH_PERM_XZYA ); + res0 = _mm_shuffle_ps( sum, sum, _MM_SHUFFLE(0,1,2,0) ); + res0 = vec_sel( res0, vec_splat(diff, 0), select_w ); // TODO: Ck + //res1 = vec_perm( sum, diff, _VECTORMATH_PERM_ZXXB ); + res1 = _mm_shuffle_ps( sum, sum, _MM_SHUFFLE(0,0,0,2) ); + res1 = vec_sel( res1, vec_splat(diff, 1), select_w ); // TODO: Ck + //res2 = vec_perm( sum, diff, _VECTORMATH_PERM_YXXC ); + res2 = _mm_shuffle_ps( sum, sum, _MM_SHUFFLE(0,0,0,1) ); + res2 = vec_sel( res2, vec_splat(diff, 2), select_w ); // TODO: Ck + res3 = diff; + res0 = vec_sel( res0, radicand, select_x ); + res1 = vec_sel( res1, radicand, select_y ); + res2 = vec_sel( res2, radicand, select_z ); + res3 = vec_sel( res3, radicand, select_w ); + res0 = vec_mul( res0, vec_splat( scale, 0 ) ); + res1 = vec_mul( res1, vec_splat( scale, 1 ) ); + res2 = vec_mul( res2, vec_splat( scale, 2 ) ); + res3 = vec_mul( res3, vec_splat( scale, 3 ) ); + + /* determine case and select answer */ + + xx = vec_splat( col0, 0 ); + yy = vec_splat( col1, 1 ); + zz = vec_splat( col2, 2 ); + res = vec_sel( res0, res1, vec_cmpgt( yy, xx ) ); + res = vec_sel( res, res2, vec_and( vec_cmpgt( zz, xx ), vec_cmpgt( zz, yy ) ) ); + res = vec_sel( res, res3, vec_cmpgt( vec_splat( diagSum, 0 ), _mm_setzero_ps() ) ); + mVec128 = res; +} + +VECTORMATH_FORCE_INLINE const Matrix3 outer( const Vector3 &tfrm0, const Vector3 &tfrm1 ) +{ + return Matrix3( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 outer( const Vector4 &tfrm0, const Vector4 &tfrm1 ) +{ + return Matrix4( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ), + ( tfrm0 * tfrm1.getW( ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Vector3 rowMul( const Vector3 &vec, const Matrix3 & mat ) +{ + __m128 tmp0, tmp1, mcol0, mcol1, mcol2, res; + __m128 xxxx, yyyy, zzzz; + tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp1 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); + xxxx = vec_splat( vec.get128(), 0 ); + mcol0 = vec_mergeh( tmp0, mat.getCol1().get128() ); + //mcol1 = vec_perm( tmp0, mat.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + mcol1 = _mm_shuffle_ps( tmp0, tmp0, _MM_SHUFFLE(0,3,2,2)); + mcol1 = vec_sel(mcol1, mat.getCol1().get128(), select_y); + //mcol2 = vec_perm( tmp1, mat.getCol1().get128(), _VECTORMATH_PERM_XCYX ); + mcol2 = _mm_shuffle_ps( tmp1, tmp1, _MM_SHUFFLE(0,1,1,0)); + mcol2 = vec_sel(mcol2, vec_splat(mat.getCol1().get128(), 2), select_y); + yyyy = vec_splat( vec.get128(), 1 ); + res = vec_mul( mcol0, xxxx ); + zzzz = vec_splat( vec.get128(), 2 ); + res = vec_madd( mcol1, yyyy, res ); + res = vec_madd( mcol2, zzzz, res ); + return Vector3( res ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 crossMatrix( const Vector3 &vec ) +{ + __m128 neg, res0, res1, res2; + neg = negatef4( vec.get128() ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + //res0 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_XZBX ); + res0 = _mm_shuffle_ps( vec.get128(), vec.get128(), _MM_SHUFFLE(0,2,2,0) ); + res0 = vec_sel(res0, vec_splat(neg, 1), select_z); + //res1 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_CXXX ); + res1 = vec_sel(vec_splat(vec.get128(), 0), vec_splat(neg, 2), select_x); + //res2 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_YAXX ); + res2 = _mm_shuffle_ps( vec.get128(), vec.get128(), _MM_SHUFFLE(0,0,1,1) ); + res2 = vec_sel(res2, vec_splat(neg, 0), select_y); + VM_ATTRIBUTE_ALIGN16 unsigned int filter_x[4] = {0, 0xffffffff, 0xffffffff, 0xffffffff}; + VM_ATTRIBUTE_ALIGN16 unsigned int filter_y[4] = {0xffffffff, 0, 0xffffffff, 0xffffffff}; + VM_ATTRIBUTE_ALIGN16 unsigned int filter_z[4] = {0xffffffff, 0xffffffff, 0, 0xffffffff}; + res0 = vec_and( res0, _mm_load_ps((float *)filter_x ) ); + res1 = vec_and( res1, _mm_load_ps((float *)filter_y ) ); + res2 = vec_and( res2, _mm_load_ps((float *)filter_z ) ); // TODO: Use selects? + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 crossMatrixMul( const Vector3 &vec, const Matrix3 & mat ) +{ + return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); +} + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/PhysicsEffects/include/vecmath/sse/quat_aos.h b/Extras/PhysicsEffects/include/vecmath/sse/quat_aos.h new file mode 100644 index 0000000..d7091ec --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/sse/quat_aos.h @@ -0,0 +1,579 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _VECTORMATH_QUAT_AOS_CPP_H +#define _VECTORMATH_QUAT_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +VECTORMATH_FORCE_INLINE void Quat::set128(vec_float4 vec) +{ + mVec128 = vec; +} + +VECTORMATH_FORCE_INLINE Quat::Quat( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z, const floatInVec &_w ) +{ + mVec128 = _mm_unpacklo_ps( + _mm_unpacklo_ps( _x.get128(), _z.get128() ), + _mm_unpacklo_ps( _y.get128(), _w.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( const Vector3 &xyz, float _w ) +{ + mVec128 = xyz.get128(); + _vmathVfSetElement(mVec128, _w, 3); +} + + + +VECTORMATH_FORCE_INLINE Quat::Quat(const Quat& quat) +{ + mVec128 = quat.get128(); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( float _x, float _y, float _z, float _w ) +{ + mVec128 = _mm_setr_ps(_x, _y, _z, _w); +} + + + + + +VECTORMATH_FORCE_INLINE Quat::Quat( const Vector3 &xyz, const floatInVec &_w ) +{ + mVec128 = xyz.get128(); + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( const Vector4 &vec ) +{ + mVec128 = vec.get128(); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( const floatInVec &scalar ) +{ + mVec128 = scalar.get128(); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( __m128 vf4 ) +{ + mVec128 = vf4; +} + +VECTORMATH_FORCE_INLINE const Quat Quat::identity( ) +{ + return Quat( _VECTORMATH_UNIT_0001 ); +} + +VECTORMATH_FORCE_INLINE const Quat lerp( float t, const Quat &quat0, const Quat &quat1 ) +{ + return lerp( floatInVec(t), quat0, quat1 ); +} + +VECTORMATH_FORCE_INLINE const Quat lerp( const floatInVec &t, const Quat &quat0, const Quat &quat1 ) +{ + return ( quat0 + ( ( quat1 - quat0 ) * t ) ); +} + +VECTORMATH_FORCE_INLINE const Quat slerp( float t, const Quat &unitQuat0, const Quat &unitQuat1 ) +{ + return slerp( floatInVec(t), unitQuat0, unitQuat1 ); +} + +VECTORMATH_FORCE_INLINE const Quat slerp( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1 ) +{ + Quat start; + vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + __m128 selectMask; + cosAngle = _vmathVfDot4( unitQuat0.get128(), unitQuat1.get128() ); + selectMask = (__m128)vec_cmpgt( _mm_setzero_ps(), cosAngle ); + cosAngle = vec_sel( cosAngle, negatef4( cosAngle ), selectMask ); + start = Quat( vec_sel( unitQuat0.get128(), negatef4( unitQuat0.get128() ), selectMask ) ); + selectMask = (__m128)vec_cmpgt( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = t.get128(); + oneMinusT = vec_sub( _mm_set1_ps(1.0f), tttt ); + angles = vec_mergeh( _mm_set1_ps(1.0f), tttt ); + angles = vec_mergeh( angles, oneMinusT ); + angles = vec_madd( angles, angle, _mm_setzero_ps() ); + sines = sinf4( angles ); + scales = _mm_div_ps( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + return Quat( vec_madd( start.get128(), scale0, vec_mul( unitQuat1.get128(), scale1 ) ) ); +} + +VECTORMATH_FORCE_INLINE const Quat squad( float t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ) +{ + return squad( floatInVec(t), unitQuat0, unitQuat1, unitQuat2, unitQuat3 ); +} + +VECTORMATH_FORCE_INLINE const Quat squad( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ) +{ + return slerp( ( ( floatInVec(2.0f) * t ) * ( floatInVec(1.0f) - t ) ), slerp( t, unitQuat0, unitQuat3 ), slerp( t, unitQuat1, unitQuat2 ) ); +} + +VECTORMATH_FORCE_INLINE __m128 Quat::get128( ) const +{ + return mVec128; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator =( const Quat &quat ) +{ + mVec128 = quat.mVec128; + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setXYZ( const Vector3 &vec ) +{ + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + mVec128 = vec_sel( vec.get128(), mVec128, sw ); + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Quat::getXYZ( ) const +{ + return Vector3( mVec128 ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setX( const floatInVec &_x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setY( const floatInVec &_y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setZ( const floatInVec &_z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setW( float _w ) +{ + _vmathVfSetElement(mVec128, _w, 3); + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setW( const floatInVec &_w ) +{ + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::getW( ) const +{ + return floatInVec( mVec128, 3 ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setElem( int idx, const floatInVec &value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE VecIdx Quat::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator +( const Quat &quat ) const +{ + return Quat( _mm_add_ps( mVec128, quat.mVec128 ) ); +} + + +VECTORMATH_FORCE_INLINE const Quat Quat::operator -( const Quat &quat ) const +{ + return Quat( _mm_sub_ps( mVec128, quat.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator *( const floatInVec &scalar ) const +{ + return Quat( _mm_mul_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator +=( const Quat &quat ) +{ + *this = *this + quat; + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator -=( const Quat &quat ) +{ + *this = *this - quat; + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator /( float scalar ) const +{ + return *this / floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator /( const floatInVec &scalar ) const +{ + return Quat( _mm_div_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator /=( const floatInVec &scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator -( ) const +{ + return Quat(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Quat operator *( float scalar, const Quat &quat ) +{ + return floatInVec(scalar) * quat; +} + +VECTORMATH_FORCE_INLINE const Quat operator *( const floatInVec &scalar, const Quat &quat ) +{ + return quat * scalar; +} + +VECTORMATH_FORCE_INLINE const floatInVec dot( const Quat &quat0, const Quat &quat1 ) +{ + return floatInVec( _vmathVfDot4( quat0.get128(), quat1.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec norm( const Quat &quat ) +{ + return floatInVec( _vmathVfDot4( quat.get128(), quat.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec length( const Quat &quat ) +{ + return floatInVec( _mm_sqrt_ps(_vmathVfDot4( quat.get128(), quat.get128() )), 0 ); +} + +VECTORMATH_FORCE_INLINE const Quat normalize( const Quat &quat ) +{ + vec_float4 dot =_vmathVfDot4( quat.get128(), quat.get128()); + return Quat( _mm_mul_ps( quat.get128(), newtonrapson_rsqrt4( dot ) ) ); +} + + +VECTORMATH_FORCE_INLINE const Quat Quat::rotation( const Vector3 &unitVec0, const Vector3 &unitVec1 ) +{ + Vector3 crossVec; + __m128 cosAngle, cosAngleX2Plus2, recipCosHalfAngleX2, cosHalfAngleX2, res; + cosAngle = _vmathVfDot3( unitVec0.get128(), unitVec1.get128() ); + cosAngleX2Plus2 = vec_madd( cosAngle, _mm_set1_ps(2.0f), _mm_set1_ps(2.0f) ); + recipCosHalfAngleX2 = _mm_rsqrt_ps( cosAngleX2Plus2 ); + cosHalfAngleX2 = vec_mul( recipCosHalfAngleX2, cosAngleX2Plus2 ); + crossVec = cross( unitVec0, unitVec1 ); + res = vec_mul( crossVec.get128(), recipCosHalfAngleX2 ); + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( res, vec_mul( cosHalfAngleX2, _mm_set1_ps(0.5f) ), sw ); + return Quat( res ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotation( float radians, const Vector3 &unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotation( const floatInVec &radians, const Vector3 &unitVec ) +{ + __m128 s, c, angle, res; + angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); + sincosf4( angle, &s, &c ); + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( vec_mul( unitVec.get128(), s ), c, sw ); + return Quat( res ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationX( const floatInVec &radians ) +{ + __m128 s, c, angle, res; + angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); + sincosf4( angle, &s, &c ); + VM_ATTRIBUTE_ALIGN16 unsigned int xsw[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int wsw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( _mm_setzero_ps(), s, xsw ); + res = vec_sel( res, c, wsw ); + return Quat( res ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationY( const floatInVec &radians ) +{ + __m128 s, c, angle, res; + angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); + sincosf4( angle, &s, &c ); + VM_ATTRIBUTE_ALIGN16 unsigned int ysw[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int wsw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( _mm_setzero_ps(), s, ysw ); + res = vec_sel( res, c, wsw ); + return Quat( res ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationZ( const floatInVec &radians ) +{ + __m128 s, c, angle, res; + angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); + sincosf4( angle, &s, &c ); + VM_ATTRIBUTE_ALIGN16 unsigned int zsw[4] = {0, 0, 0xffffffff, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int wsw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( _mm_setzero_ps(), s, zsw ); + res = vec_sel( res, c, wsw ); + return Quat( res ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator *( const Quat &quat ) const +{ + __m128 ldata, rdata, qv, tmp0, tmp1, tmp2, tmp3; + __m128 product, l_wxyz, r_wxyz, xy, qw; + ldata = mVec128; + rdata = quat.mVec128; + tmp0 = _mm_shuffle_ps( ldata, ldata, _MM_SHUFFLE(3,0,2,1) ); + tmp1 = _mm_shuffle_ps( rdata, rdata, _MM_SHUFFLE(3,1,0,2) ); + tmp2 = _mm_shuffle_ps( ldata, ldata, _MM_SHUFFLE(3,1,0,2) ); + tmp3 = _mm_shuffle_ps( rdata, rdata, _MM_SHUFFLE(3,0,2,1) ); + qv = vec_mul( vec_splat( ldata, 3 ), rdata ); + qv = vec_madd( vec_splat( rdata, 3 ), ldata, qv ); + qv = vec_madd( tmp0, tmp1, qv ); + qv = vec_nmsub( tmp2, tmp3, qv ); + product = vec_mul( ldata, rdata ); + l_wxyz = vec_sld( ldata, ldata, 12 ); + r_wxyz = vec_sld( rdata, rdata, 12 ); + qw = vec_nmsub( l_wxyz, r_wxyz, product ); + xy = vec_madd( l_wxyz, r_wxyz, product ); + qw = vec_sub( qw, vec_sld( xy, xy, 8 ) ); + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + return Quat( vec_sel( qv, qw, sw ) ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator *=( const Quat &quat ) +{ + *this = *this * quat; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 rotate( const Quat &quat, const Vector3 &vec ) +{ __m128 qdata, vdata, product, tmp0, tmp1, tmp2, tmp3, wwww, qv, qw, res; + qdata = quat.get128(); + vdata = vec.get128(); + tmp0 = _mm_shuffle_ps( qdata, qdata, _MM_SHUFFLE(3,0,2,1) ); + tmp1 = _mm_shuffle_ps( vdata, vdata, _MM_SHUFFLE(3,1,0,2) ); + tmp2 = _mm_shuffle_ps( qdata, qdata, _MM_SHUFFLE(3,1,0,2) ); + tmp3 = _mm_shuffle_ps( vdata, vdata, _MM_SHUFFLE(3,0,2,1) ); + wwww = vec_splat( qdata, 3 ); + qv = vec_mul( wwww, vdata ); + qv = vec_madd( tmp0, tmp1, qv ); + qv = vec_nmsub( tmp2, tmp3, qv ); + product = vec_mul( qdata, vdata ); + qw = vec_madd( vec_sld( qdata, qdata, 4 ), vec_sld( vdata, vdata, 4 ), product ); + qw = vec_add( vec_sld( product, product, 8 ), qw ); + tmp1 = _mm_shuffle_ps( qv, qv, _MM_SHUFFLE(3,1,0,2) ); + tmp3 = _mm_shuffle_ps( qv, qv, _MM_SHUFFLE(3,0,2,1) ); + res = vec_mul( vec_splat( qw, 0 ), qdata ); + res = vec_madd( wwww, qv, res ); + res = vec_madd( tmp0, tmp1, res ); + res = vec_nmsub( tmp2, tmp3, res ); + return Vector3( res ); +} + +VECTORMATH_FORCE_INLINE const Quat conj( const Quat &quat ) +{ + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0x80000000,0x80000000,0x80000000,0}; + return Quat( vec_xor( quat.get128(), _mm_load_ps((float *)sw) ) ); +} + +VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, bool select1 ) +{ + return select( quat0, quat1, boolInVec(select1) ); +} + +//VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, const boolInVec &select1 ) +//{ +// return Quat( vec_sel( quat0.get128(), quat1.get128(), select1.get128() ) ); +//} + +VECTORMATH_FORCE_INLINE void loadXYZW(Quat& quat, const float* fptr) +{ +#ifdef USE_SSE3_LDDQU + quat = Quat( SSEFloat(_mm_lddqu_si128((const __m128i*)((float*)(fptr)))).m128 ); +#else + SSEFloat fl; + fl.f[0] = fptr[0]; + fl.f[1] = fptr[1]; + fl.f[2] = fptr[2]; + fl.f[3] = fptr[3]; + quat = Quat( fl.m128); +#endif + + +} + +VECTORMATH_FORCE_INLINE void storeXYZW(const Quat& quat, float* fptr) +{ + fptr[0] = quat.getX(); + fptr[1] = quat.getY(); + fptr[2] = quat.getZ(); + fptr[3] = quat.getW(); +// _mm_storeu_ps((float*)quat.get128(),fptr); +} + + + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Quat &quat ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = quat.get128(); + printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +VECTORMATH_FORCE_INLINE void print( const Quat &quat, const char * name ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = quat.get128(); + printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/PhysicsEffects/include/vecmath/sse/vec_aos.h b/Extras/PhysicsEffects/include/vecmath/sse/vec_aos.h new file mode 100644 index 0000000..05ebac5 --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/sse/vec_aos.h @@ -0,0 +1,1455 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_AOS_CPP_H +#define _VECTORMATH_VEC_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Constants +// for permutes words are labeled [x,y,z,w] [a,b,c,d] + +#define _VECTORMATH_PERM_X 0x00010203 +#define _VECTORMATH_PERM_Y 0x04050607 +#define _VECTORMATH_PERM_Z 0x08090a0b +#define _VECTORMATH_PERM_W 0x0c0d0e0f +#define _VECTORMATH_PERM_A 0x10111213 +#define _VECTORMATH_PERM_B 0x14151617 +#define _VECTORMATH_PERM_C 0x18191a1b +#define _VECTORMATH_PERM_D 0x1c1d1e1f +#define _VECTORMATH_PERM_XYZA (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A } +#define _VECTORMATH_PERM_ZXYW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_YZXW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_YZAB (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B } +#define _VECTORMATH_PERM_ZABC (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B, _VECTORMATH_PERM_C } +#define _VECTORMATH_PERM_XYAW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_XAZW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W } +#define _VECTORMATH_MASK_0xF000 (vec_uint4){ 0xffffffff, 0, 0, 0 } +#define _VECTORMATH_MASK_0x0F00 (vec_uint4){ 0, 0xffffffff, 0, 0 } +#define _VECTORMATH_MASK_0x00F0 (vec_uint4){ 0, 0, 0xffffffff, 0 } +#define _VECTORMATH_MASK_0x000F (vec_uint4){ 0, 0, 0, 0xffffffff } +#define _VECTORMATH_UNIT_1000 _mm_setr_ps(1.0f,0.0f,0.0f,0.0f) // (__m128){ 1.0f, 0.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0100 _mm_setr_ps(0.0f,1.0f,0.0f,0.0f) // (__m128){ 0.0f, 1.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0010 _mm_setr_ps(0.0f,0.0f,1.0f,0.0f) // (__m128){ 0.0f, 0.0f, 1.0f, 0.0f } +#define _VECTORMATH_UNIT_0001 _mm_setr_ps(0.0f,0.0f,0.0f,1.0f) // (__m128){ 0.0f, 0.0f, 0.0f, 1.0f } +#define _VECTORMATH_SLERP_TOL 0.999f +//_VECTORMATH_SLERP_TOLF + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#define _vmath_shufps(a, b, immx, immy, immz, immw) _mm_shuffle_ps(a, b, _MM_SHUFFLE(immw, immz, immy, immx)) +static VECTORMATH_FORCE_INLINE __m128 _vmathVfDot3( __m128 vec0, __m128 vec1 ) +{ + __m128 result = _mm_mul_ps( vec0, vec1); + return _mm_add_ps( vec_splat( result, 0 ), _mm_add_ps( vec_splat( result, 1 ), vec_splat( result, 2 ) ) ); +} + +static VECTORMATH_FORCE_INLINE __m128 _vmathVfDot4( __m128 vec0, __m128 vec1 ) +{ + __m128 result = _mm_mul_ps(vec0, vec1); + return _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(0,0,0,0)), + _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(1,1,1,1)), + _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(2,2,2,2)), _mm_shuffle_ps(result, result, _MM_SHUFFLE(3,3,3,3))))); +} + +static VECTORMATH_FORCE_INLINE __m128 _vmathVfCross( __m128 vec0, __m128 vec1 ) +{ + __m128 tmp0, tmp1, tmp2, tmp3, result; + tmp0 = _mm_shuffle_ps( vec0, vec0, _MM_SHUFFLE(3,0,2,1) ); + tmp1 = _mm_shuffle_ps( vec1, vec1, _MM_SHUFFLE(3,1,0,2) ); + tmp2 = _mm_shuffle_ps( vec0, vec0, _MM_SHUFFLE(3,1,0,2) ); + tmp3 = _mm_shuffle_ps( vec1, vec1, _MM_SHUFFLE(3,0,2,1) ); + result = vec_mul( tmp0, tmp1 ); + result = vec_nmsub( tmp2, tmp3, result ); + return result; +} +/* +static VECTORMATH_FORCE_INLINE vec_uint4 _vmathVfToHalfFloatsUnpacked(__m128 v) +{ +#if 0 + vec_int4 bexp; + vec_uint4 mant, sign, hfloat; + vec_uint4 notZero, isInf; + const vec_uint4 hfloatInf = (vec_uint4)(0x00007c00u); + const vec_uint4 mergeMant = (vec_uint4)(0x000003ffu); + const vec_uint4 mergeSign = (vec_uint4)(0x00008000u); + + sign = vec_sr((vec_uint4)v, (vec_uint4)16); + mant = vec_sr((vec_uint4)v, (vec_uint4)13); + bexp = vec_and(vec_sr((vec_int4)v, (vec_uint4)23), (vec_int4)0xff); + + notZero = (vec_uint4)vec_cmpgt(bexp, (vec_int4)112); + isInf = (vec_uint4)vec_cmpgt(bexp, (vec_int4)142); + + bexp = _mm_add_ps(bexp, (vec_int4)-112); + bexp = vec_sl(bexp, (vec_uint4)10); + + hfloat = vec_sel((vec_uint4)bexp, mant, mergeMant); + hfloat = vec_sel((vec_uint4)(0), hfloat, notZero); + hfloat = vec_sel(hfloat, hfloatInf, isInf); + hfloat = vec_sel(hfloat, sign, mergeSign); + + return hfloat; +#else + assert(0); + return _mm_setzero_ps(); +#endif +} + +static VECTORMATH_FORCE_INLINE vec_ushort8 _vmath2VfToHalfFloats(__m128 u, __m128 v) +{ +#if 0 + vec_uint4 hfloat_u, hfloat_v; + const vec_uchar16 pack = (vec_uchar16){2,3,6,7,10,11,14,15,18,19,22,23,26,27,30,31}; + hfloat_u = _vmathVfToHalfFloatsUnpacked(u); + hfloat_v = _vmathVfToHalfFloatsUnpacked(v); + return (vec_ushort8)vec_perm(hfloat_u, hfloat_v, pack); +#else + assert(0); + return _mm_setzero_si128(); +#endif +} +*/ + +static VECTORMATH_FORCE_INLINE __m128 _vmathVfInsert(__m128 dst, __m128 src, int slot) +{ + SSEFloat s; + s.m128 = src; + SSEFloat d; + d.m128 = dst; + d.f[slot] = s.f[slot]; + return d.m128; +} + +#define _vmathVfSetElement(vec, scalar, slot) ((float *)&(vec))[slot] = scalar + +static VECTORMATH_FORCE_INLINE __m128 _vmathVfSplatScalar(float scalar) +{ + return _mm_set1_ps(scalar); +} + +#endif + +namespace Vectormath { +namespace Aos { + + +#ifdef _VECTORMATH_NO_SCALAR_CAST +VECTORMATH_FORCE_INLINE VecIdx::operator floatInVec() const +{ + return floatInVec(ref, i); +} + +VECTORMATH_FORCE_INLINE float VecIdx::getAsFloat() const +#else +VECTORMATH_FORCE_INLINE VecIdx::operator float() const +#endif +{ + return ((float *)&ref)[i]; +} + +VECTORMATH_FORCE_INLINE float VecIdx::operator =( float scalar ) +{ + _vmathVfSetElement(ref, scalar, i); + return scalar; +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator =( const floatInVec &scalar ) +{ + ref = _vmathVfInsert(ref, scalar.get128(), i); + return scalar; +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator =( const VecIdx& scalar ) +{ + return *this = floatInVec(scalar.ref, scalar.i); +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator *=( float scalar ) +{ + return *this *= floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator *=( const floatInVec &scalar ) +{ + return *this = floatInVec(ref, i) * scalar; +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator /=( float scalar ) +{ + return *this /= floatInVec(scalar); +} + +inline floatInVec VecIdx::operator /=( const floatInVec &scalar ) +{ + return *this = floatInVec(ref, i) / scalar; +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator +=( float scalar ) +{ + return *this += floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator +=( const floatInVec &scalar ) +{ + return *this = floatInVec(ref, i) + scalar; +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator -=( float scalar ) +{ + return *this -= floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator -=( const floatInVec &scalar ) +{ + return *this = floatInVec(ref, i) - scalar; +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3(const Vector3& vec) +{ + set128(vec.get128()); +} + +VECTORMATH_FORCE_INLINE void Vector3::set128(vec_float4 vec) +{ + mVec128 = vec; +} + + +VECTORMATH_FORCE_INLINE Vector3::Vector3( float _x, float _y, float _z ) +{ + mVec128 = _mm_setr_ps(_x, _y, _z, 0.0f); +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z ) +{ + __m128 xz = _mm_unpacklo_ps( _x.get128(), _z.get128() ); + mVec128 = _mm_unpacklo_ps( xz, _y.get128() ); +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3( const Point3 &pnt ) +{ + mVec128 = pnt.get128(); +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3( const floatInVec &scalar ) +{ + mVec128 = scalar.get128(); +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3( __m128 vf4 ) +{ + mVec128 = vf4; +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::xAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_1000 ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::yAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_0100 ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::zAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_0010 ); +} + +VECTORMATH_FORCE_INLINE const Vector3 lerp( float t, const Vector3 &vec0, const Vector3 &vec1 ) +{ + return lerp( floatInVec(t), vec0, vec1 ); +} + +VECTORMATH_FORCE_INLINE const Vector3 lerp( const floatInVec &t, const Vector3 &vec0, const Vector3 &vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 slerp( float t, const Vector3 &unitVec0, const Vector3 &unitVec1 ) +{ + return slerp( floatInVec(t), unitVec0, unitVec1 ); +} + +VECTORMATH_FORCE_INLINE const Vector3 slerp( const floatInVec &t, const Vector3 &unitVec0, const Vector3 &unitVec1 ) +{ + __m128 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + cosAngle = _vmathVfDot3( unitVec0.get128(), unitVec1.get128() ); + __m128 selectMask = _mm_cmpgt_ps( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = t.get128(); + oneMinusT = _mm_sub_ps( _mm_set1_ps(1.0f), tttt ); + angles = _mm_unpacklo_ps( _mm_set1_ps(1.0f), tttt ); // angles = 1, t, 1, t + angles = _mm_unpacklo_ps( angles, oneMinusT ); // angles = 1, 1-t, t, 1-t + angles = _mm_mul_ps( angles, angle ); + sines = sinf4( angles ); + scales = _mm_div_ps( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + return Vector3( vec_madd( unitVec0.get128(), scale0, _mm_mul_ps( unitVec1.get128(), scale1 ) ) ); +} + +VECTORMATH_FORCE_INLINE __m128 Vector3::get128( ) const +{ + return mVec128; +} + +VECTORMATH_FORCE_INLINE void loadXYZ(Point3& vec, const float* fptr) +{ +#ifdef USE_SSE3_LDDQU + vec = Point3( SSEFloat(_mm_lddqu_si128((const __m128i*)((float*)(fptr)))).m128 ); +#else + SSEFloat fl; + fl.f[0] = fptr[0]; + fl.f[1] = fptr[1]; + fl.f[2] = fptr[2]; + fl.f[3] = fptr[3]; + vec = Point3( fl.m128); +#endif //USE_SSE3_LDDQU + +} + + + +VECTORMATH_FORCE_INLINE void loadXYZ(Vector3& vec, const float* fptr) +{ +#ifdef USE_SSE3_LDDQU + vec = Vector3( SSEFloat(_mm_lddqu_si128((const __m128i*)((float*)(fptr)))).m128 ); +#else + SSEFloat fl; + fl.f[0] = fptr[0]; + fl.f[1] = fptr[1]; + fl.f[2] = fptr[2]; + fl.f[3] = fptr[3]; + vec = Vector3( fl.m128); +#endif //USE_SSE3_LDDQU + +} + +VECTORMATH_FORCE_INLINE void storeXYZ( const Vector3 &vec, __m128 * quad ) +{ + __m128 dstVec = *quad; + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; // TODO: Centralize + dstVec = vec_sel(vec.get128(), dstVec, sw); + *quad = dstVec; +} + +VECTORMATH_FORCE_INLINE void storeXYZ(const Point3& vec, float* fptr) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); +} + +VECTORMATH_FORCE_INLINE void storeXYZ(const Vector3& vec, float* fptr) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); +} + + +VECTORMATH_FORCE_INLINE void loadXYZArray( Vector3 & vec0, Vector3 & vec1, Vector3 & vec2, Vector3 & vec3, const __m128 * threeQuads ) +{ + const float *quads = (float *)threeQuads; + vec0 = Vector3( _mm_load_ps(quads) ); + vec1 = Vector3( _mm_loadu_ps(quads + 3) ); + vec2 = Vector3( _mm_loadu_ps(quads + 6) ); + vec3 = Vector3( _mm_loadu_ps(quads + 9) ); +} + +VECTORMATH_FORCE_INLINE void storeXYZArray( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, __m128 * threeQuads ) +{ + __m128 xxxx = _mm_shuffle_ps( vec1.get128(), vec1.get128(), _MM_SHUFFLE(0, 0, 0, 0) ); + __m128 zzzz = _mm_shuffle_ps( vec2.get128(), vec2.get128(), _MM_SHUFFLE(2, 2, 2, 2) ); + VM_ATTRIBUTE_ALIGN16 unsigned int xsw[4] = {0, 0, 0, 0xffffffff}; + VM_ATTRIBUTE_ALIGN16 unsigned int zsw[4] = {0xffffffff, 0, 0, 0}; + threeQuads[0] = vec_sel( vec0.get128(), xxxx, xsw ); + threeQuads[1] = _mm_shuffle_ps( vec1.get128(), vec2.get128(), _MM_SHUFFLE(1, 0, 2, 1) ); + threeQuads[2] = vec_sel( _mm_shuffle_ps( vec3.get128(), vec3.get128(), _MM_SHUFFLE(2, 1, 0, 3) ), zzzz, zsw ); +} +/* +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, const Vector3 &vec4, const Vector3 &vec5, const Vector3 &vec6, const Vector3 &vec7, vec_ushort8 * threeQuads ) +{ + assert(0); +#if 0 + __m128 xyz0[3]; + __m128 xyz1[3]; + storeXYZArray( vec0, vec1, vec2, vec3, xyz0 ); + storeXYZArray( vec4, vec5, vec6, vec7, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +#endif +} +*/ +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator =( const Vector3 &vec ) +{ + mVec128 = vec.mVec128; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setX( const floatInVec &_x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector3::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setY( const floatInVec &_y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector3::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setZ( const floatInVec &_z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector3::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setElem( int idx, const floatInVec &value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector3::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE VecIdx Vector3::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector3::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator +( const Vector3 &vec ) const +{ + return Vector3( _mm_add_ps( mVec128, vec.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator -( const Vector3 &vec ) const +{ + return Vector3( _mm_sub_ps( mVec128, vec.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 Vector3::operator +( const Point3 &pnt ) const +{ + return Point3( _mm_add_ps( mVec128, pnt.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator *( const floatInVec &scalar ) const +{ + return Vector3( _mm_mul_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator +=( const Vector3 &vec ) +{ + *this = *this + vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator -=( const Vector3 &vec ) +{ + *this = *this - vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator /( float scalar ) const +{ + return *this / floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator /( const floatInVec &scalar ) const +{ + return Vector3( _mm_div_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator /=( const floatInVec &scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator -( ) const +{ + //return Vector3(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) ); + + VM_ATTRIBUTE_ALIGN16 static const int array[] = {0x80000000, 0x80000000, 0x80000000, 0x80000000}; + __m128 NEG_MASK = SSEFloat(*(const vec_float4*)array).vf; + return Vector3(_mm_xor_ps(get128(),NEG_MASK)); +} + +VECTORMATH_FORCE_INLINE const Vector3 operator *( float scalar, const Vector3 &vec ) +{ + return floatInVec(scalar) * vec; +} + +VECTORMATH_FORCE_INLINE const Vector3 operator *( const floatInVec &scalar, const Vector3 &vec ) +{ + return vec * scalar; +} + +VECTORMATH_FORCE_INLINE const Vector3 mulPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _mm_mul_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 divPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _mm_div_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 recipPerElem( const Vector3 &vec ) +{ + return Vector3( _mm_rcp_ps( vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 absPerElem( const Vector3 &vec ) +{ + return Vector3( fabsf4( vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 copySignPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + __m128 vmask = toM128(0x7fffffff); + return Vector3( _mm_or_ps( + _mm_and_ps ( vmask, vec0.get128() ), // Value + _mm_andnot_ps( vmask, vec1.get128() ) ) ); // Signs +} + +VECTORMATH_FORCE_INLINE const Vector3 maxPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _mm_max_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Vector3 &vec ) +{ + return floatInVec( _mm_max_ps( _mm_max_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 minPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _mm_min_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Vector3 &vec ) +{ + return floatInVec( _mm_min_ps( _mm_min_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec sum( const Vector3 &vec ) +{ + return floatInVec( _mm_add_ps( _mm_add_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec dot( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return floatInVec( _vmathVfDot3( vec0.get128(), vec1.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec lengthSqr( const Vector3 &vec ) +{ + return floatInVec( _vmathVfDot3( vec.get128(), vec.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec length( const Vector3 &vec ) +{ + return floatInVec( _mm_sqrt_ps(_vmathVfDot3( vec.get128(), vec.get128() )), 0 ); +} + + +VECTORMATH_FORCE_INLINE const Vector3 normalizeApprox( const Vector3 &vec ) +{ + return Vector3( _mm_mul_ps( vec.get128(), _mm_rsqrt_ps( _vmathVfDot3( vec.get128(), vec.get128() ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 normalize( const Vector3 &vec ) +{ + return Vector3( _mm_mul_ps( vec.get128(), newtonrapson_rsqrt4( _vmathVfDot3( vec.get128(), vec.get128() ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 cross( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _vmathVfCross( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 select( const Vector3 &vec0, const Vector3 &vec1, bool select1 ) +{ + return select( vec0, vec1, boolInVec(select1) ); +} + + +VECTORMATH_FORCE_INLINE const Vector4 select(const Vector4& vec0, const Vector4& vec1, const boolInVec& select1) +{ + return Vector4(vec_sel(vec0.get128(), vec1.get128(), select1.get128())); +} + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Vector3 &vec ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +VECTORMATH_FORCE_INLINE void print( const Vector3 &vec, const char * name ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +#endif + +VECTORMATH_FORCE_INLINE Vector4::Vector4( float _x, float _y, float _z, float _w ) +{ + mVec128 = _mm_setr_ps(_x, _y, _z, _w); + } + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z, const floatInVec &_w ) +{ + mVec128 = _mm_unpacklo_ps( + _mm_unpacklo_ps( _x.get128(), _z.get128() ), + _mm_unpacklo_ps( _y.get128(), _w.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const Vector3 &xyz, float _w ) +{ + mVec128 = xyz.get128(); + _vmathVfSetElement(mVec128, _w, 3); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const Vector3 &xyz, const floatInVec &_w ) +{ + mVec128 = xyz.get128(); + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const Vector3 &vec ) +{ + mVec128 = vec.get128(); + mVec128 = _vmathVfInsert(mVec128, _mm_setzero_ps(), 3); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const Point3 &pnt ) +{ + mVec128 = pnt.get128(); + mVec128 = _vmathVfInsert(mVec128, _mm_set1_ps(1.0f), 3); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const Quat &quat ) +{ + mVec128 = quat.get128(); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const floatInVec &scalar ) +{ + mVec128 = scalar.get128(); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( __m128 vf4 ) +{ + mVec128 = vf4; +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::xAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_1000 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::yAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0100 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::zAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0010 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::wAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0001 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 lerp( float t, const Vector4 &vec0, const Vector4 &vec1 ) +{ + return lerp( floatInVec(t), vec0, vec1 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 lerp( const floatInVec &t, const Vector4 &vec0, const Vector4 &vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 slerp( float t, const Vector4 &unitVec0, const Vector4 &unitVec1 ) +{ + return slerp( floatInVec(t), unitVec0, unitVec1 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 slerp( const floatInVec &t, const Vector4 &unitVec0, const Vector4 &unitVec1 ) +{ + __m128 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + cosAngle = _vmathVfDot4( unitVec0.get128(), unitVec1.get128() ); + __m128 selectMask = _mm_cmpgt_ps( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = t.get128(); + oneMinusT = _mm_sub_ps( _mm_set1_ps(1.0f), tttt ); + angles = _mm_unpacklo_ps( _mm_set1_ps(1.0f), tttt ); // angles = 1, t, 1, t + angles = _mm_unpacklo_ps( angles, oneMinusT ); // angles = 1, 1-t, t, 1-t + angles = _mm_mul_ps( angles, angle ); + sines = sinf4( angles ); + scales = _mm_div_ps( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + return Vector4( vec_madd( unitVec0.get128(), scale0, _mm_mul_ps( unitVec1.get128(), scale1 ) ) ); +} + +VECTORMATH_FORCE_INLINE __m128 Vector4::get128( ) const +{ + return mVec128; +} +/* +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Vector4 &vec0, const Vector4 &vec1, const Vector4 &vec2, const Vector4 &vec3, vec_ushort8 * twoQuads ) +{ + twoQuads[0] = _vmath2VfToHalfFloats(vec0.get128(), vec1.get128()); + twoQuads[1] = _vmath2VfToHalfFloats(vec2.get128(), vec3.get128()); +} +*/ +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator =( const Vector4 &vec ) +{ + mVec128 = vec.mVec128; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setXYZ( const Vector3 &vec ) +{ + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + mVec128 = vec_sel( vec.get128(), mVec128, sw ); + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector4::getXYZ( ) const +{ + return Vector3( mVec128 ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setX( const floatInVec &_x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setY( const floatInVec &_y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setZ( const floatInVec &_z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setW( float _w ) +{ + _vmathVfSetElement(mVec128, _w, 3); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setW( const floatInVec &_w ) +{ + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::getW( ) const +{ + return floatInVec( mVec128, 3 ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setElem( int idx, const floatInVec &value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE VecIdx Vector4::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator +( const Vector4 &vec ) const +{ + return Vector4( _mm_add_ps( mVec128, vec.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator -( const Vector4 &vec ) const +{ + return Vector4( _mm_sub_ps( mVec128, vec.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator *( const floatInVec &scalar ) const +{ + return Vector4( _mm_mul_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator +=( const Vector4 &vec ) +{ + *this = *this + vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator -=( const Vector4 &vec ) +{ + *this = *this - vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator /( float scalar ) const +{ + return *this / floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator /( const floatInVec &scalar ) const +{ + return Vector4( _mm_div_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator /=( const floatInVec &scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator -( ) const +{ + return Vector4(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 operator *( float scalar, const Vector4 &vec ) +{ + return floatInVec(scalar) * vec; +} + +VECTORMATH_FORCE_INLINE const Vector4 operator *( const floatInVec &scalar, const Vector4 &vec ) +{ + return vec * scalar; +} + +VECTORMATH_FORCE_INLINE const Vector4 mulPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return Vector4( _mm_mul_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 divPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return Vector4( _mm_div_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 recipPerElem( const Vector4 &vec ) +{ + return Vector4( _mm_rcp_ps( vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 absPerElem( const Vector4 &vec ) +{ + return Vector4( fabsf4( vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 copySignPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + __m128 vmask = toM128(0x7fffffff); + return Vector4( _mm_or_ps( + _mm_and_ps ( vmask, vec0.get128() ), // Value + _mm_andnot_ps( vmask, vec1.get128() ) ) ); // Signs +} + +VECTORMATH_FORCE_INLINE const Vector4 maxPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return Vector4( _mm_max_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Vector4 &vec ) +{ + return floatInVec( _mm_max_ps( + _mm_max_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), + _mm_max_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 minPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return Vector4( _mm_min_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Vector4 &vec ) +{ + return floatInVec( _mm_min_ps( + _mm_min_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), + _mm_min_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec sum( const Vector4 &vec ) +{ + return floatInVec( _mm_add_ps( + _mm_add_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), + _mm_add_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec dot( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return floatInVec( _vmathVfDot4( vec0.get128(), vec1.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec lengthSqr( const Vector4 &vec ) +{ + return floatInVec( _vmathVfDot4( vec.get128(), vec.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec length( const Vector4 &vec ) +{ + return floatInVec( _mm_sqrt_ps(_vmathVfDot4( vec.get128(), vec.get128() )), 0 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 normalizeApprox( const Vector4 &vec ) +{ + return Vector4( _mm_mul_ps( vec.get128(), _mm_rsqrt_ps( _vmathVfDot4( vec.get128(), vec.get128() ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 normalize( const Vector4 &vec ) +{ + return Vector4( _mm_mul_ps( vec.get128(), newtonrapson_rsqrt4( _vmathVfDot4( vec.get128(), vec.get128() ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 select( const Vector4 &vec0, const Vector4 &vec1, bool select1 ) +{ + return select( vec0, vec1, boolInVec(select1) ); +} + + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Vector4 &vec ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +VECTORMATH_FORCE_INLINE void print( const Vector4 &vec, const char * name ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +#endif + +VECTORMATH_FORCE_INLINE Point3::Point3( float _x, float _y, float _z ) +{ + mVec128 = _mm_setr_ps(_x, _y, _z, 0.0f); +} + +VECTORMATH_FORCE_INLINE Point3::Point3( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z ) +{ + mVec128 = _mm_unpacklo_ps( _mm_unpacklo_ps( _x.get128(), _z.get128() ), _y.get128() ); +} + +VECTORMATH_FORCE_INLINE Point3::Point3( const Vector3 &vec ) +{ + mVec128 = vec.get128(); +} + +VECTORMATH_FORCE_INLINE Point3::Point3( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +VECTORMATH_FORCE_INLINE Point3::Point3( const floatInVec &scalar ) +{ + mVec128 = scalar.get128(); +} + +VECTORMATH_FORCE_INLINE Point3::Point3( __m128 vf4 ) +{ + mVec128 = vf4; +} + +VECTORMATH_FORCE_INLINE const Point3 lerp( float t, const Point3 &pnt0, const Point3 &pnt1 ) +{ + return lerp( floatInVec(t), pnt0, pnt1 ); +} + +VECTORMATH_FORCE_INLINE const Point3 lerp( const floatInVec &t, const Point3 &pnt0, const Point3 &pnt1 ) +{ + return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); +} + +VECTORMATH_FORCE_INLINE __m128 Point3::get128( ) const +{ + return mVec128; +} + +VECTORMATH_FORCE_INLINE void storeXYZ( const Point3 &pnt, __m128 * quad ) +{ + __m128 dstVec = *quad; + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; // TODO: Centralize + dstVec = vec_sel(pnt.get128(), dstVec, sw); + *quad = dstVec; +} + +VECTORMATH_FORCE_INLINE void loadXYZArray( Point3 & pnt0, Point3 & pnt1, Point3 & pnt2, Point3 & pnt3, const __m128 * threeQuads ) +{ + const float *quads = (float *)threeQuads; + pnt0 = Point3( _mm_load_ps(quads) ); + pnt1 = Point3( _mm_loadu_ps(quads + 3) ); + pnt2 = Point3( _mm_loadu_ps(quads + 6) ); + pnt3 = Point3( _mm_loadu_ps(quads + 9) ); +} + +VECTORMATH_FORCE_INLINE void storeXYZArray( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, __m128 * threeQuads ) +{ + __m128 xxxx = _mm_shuffle_ps( pnt1.get128(), pnt1.get128(), _MM_SHUFFLE(0, 0, 0, 0) ); + __m128 zzzz = _mm_shuffle_ps( pnt2.get128(), pnt2.get128(), _MM_SHUFFLE(2, 2, 2, 2) ); + VM_ATTRIBUTE_ALIGN16 unsigned int xsw[4] = {0, 0, 0, 0xffffffff}; + VM_ATTRIBUTE_ALIGN16 unsigned int zsw[4] = {0xffffffff, 0, 0, 0}; + threeQuads[0] = vec_sel( pnt0.get128(), xxxx, xsw ); + threeQuads[1] = _mm_shuffle_ps( pnt1.get128(), pnt2.get128(), _MM_SHUFFLE(1, 0, 2, 1) ); + threeQuads[2] = vec_sel( _mm_shuffle_ps( pnt3.get128(), pnt3.get128(), _MM_SHUFFLE(2, 1, 0, 3) ), zzzz, zsw ); +} +/* +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, const Point3 &pnt4, const Point3 &pnt5, const Point3 &pnt6, const Point3 &pnt7, vec_ushort8 * threeQuads ) +{ +#if 0 + __m128 xyz0[3]; + __m128 xyz1[3]; + storeXYZArray( pnt0, pnt1, pnt2, pnt3, xyz0 ); + storeXYZArray( pnt4, pnt5, pnt6, pnt7, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +#else + assert(0); +#endif +} +*/ +VECTORMATH_FORCE_INLINE Point3 & Point3::operator =( const Point3 &pnt ) +{ + mVec128 = pnt.mVec128; + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setX( const floatInVec &_x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Point3::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setY( const floatInVec &_y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Point3::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setZ( const floatInVec &_z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Point3::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setElem( int idx, const floatInVec &value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Point3::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE VecIdx Point3::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const floatInVec Point3::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Point3::operator -( const Point3 &pnt ) const +{ + return Vector3( _mm_sub_ps( mVec128, pnt.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 Point3::operator +( const Vector3 &vec ) const +{ + return Point3( _mm_add_ps( mVec128, vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 Point3::operator -( const Vector3 &vec ) const +{ + return Point3( _mm_sub_ps( mVec128, vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::operator +=( const Vector3 &vec ) +{ + *this = *this + vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::operator -=( const Vector3 &vec ) +{ + *this = *this - vec; + return *this; +} + +VECTORMATH_FORCE_INLINE const Point3 mulPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return Point3( _mm_mul_ps( pnt0.get128(), pnt1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 divPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return Point3( _mm_div_ps( pnt0.get128(), pnt1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 recipPerElem( const Point3 &pnt ) +{ + return Point3( _mm_rcp_ps( pnt.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 absPerElem( const Point3 &pnt ) +{ + return Point3( fabsf4( pnt.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 copySignPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + __m128 vmask = toM128(0x7fffffff); + return Point3( _mm_or_ps( + _mm_and_ps ( vmask, pnt0.get128() ), // Value + _mm_andnot_ps( vmask, pnt1.get128() ) ) ); // Signs +} + +VECTORMATH_FORCE_INLINE const Point3 maxPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return Point3( _mm_max_ps( pnt0.get128(), pnt1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Point3 &pnt ) +{ + return floatInVec( _mm_max_ps( _mm_max_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 minPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return Point3( _mm_min_ps( pnt0.get128(), pnt1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Point3 &pnt ) +{ + return floatInVec( _mm_min_ps( _mm_min_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec sum( const Point3 &pnt ) +{ + return floatInVec( _mm_add_ps( _mm_add_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, float scaleVal ) +{ + return scale( pnt, floatInVec( scaleVal ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, const floatInVec &scaleVal ) +{ + return mulPerElem( pnt, Point3( scaleVal ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, const Vector3 &scaleVec ) +{ + return mulPerElem( pnt, Point3( scaleVec ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec projection( const Point3 &pnt, const Vector3 &unitVec ) +{ + return floatInVec( _vmathVfDot3( pnt.get128(), unitVec.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec distSqrFromOrigin( const Point3 &pnt ) +{ + return lengthSqr( Vector3( pnt ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec distFromOrigin( const Point3 &pnt ) +{ + return length( Vector3( pnt ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec distSqr( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return lengthSqr( ( pnt1 - pnt0 ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec dist( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return length( ( pnt1 - pnt0 ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 select( const Point3 &pnt0, const Point3 &pnt1, bool select1 ) +{ + return select( pnt0, pnt1, boolInVec(select1) ); +} + +VECTORMATH_FORCE_INLINE const Point3 select( const Point3 &pnt0, const Point3 &pnt1, const boolInVec &select1 ) +{ + return Point3( vec_sel( pnt0.get128(), pnt1.get128(), select1.get128() ) ); +} + + + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Point3 &pnt ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = pnt.get128(); + printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +VECTORMATH_FORCE_INLINE void print( const Point3 &pnt, const char * name ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = pnt.get128(); + printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/PhysicsEffects/include/vecmath/sse/vecidx_aos.h b/Extras/PhysicsEffects/include/vecmath/sse/vecidx_aos.h new file mode 100644 index 0000000..32e837a --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/sse/vecidx_aos.h @@ -0,0 +1,80 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VECIDX_AOS_H +#define _VECTORMATH_VECIDX_AOS_H + + +#include "floatInVec.h" + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// VecIdx +// Used in setting elements of Vector3, Vector4, Point3, or Quat with the +// subscripting operator. +// + +VM_ATTRIBUTE_ALIGNED_CLASS16 (class) VecIdx +{ +private: + __m128 &ref; + int i; +public: + inline VecIdx( __m128& vec, int idx ): ref(vec) { i = idx; } + + // implicitly casts to float unless _VECTORMATH_NO_SCALAR_CAST defined + // in which case, implicitly casts to floatInVec, and one must call + // getAsFloat to convert to float. + // +#ifdef _VECTORMATH_NO_SCALAR_CAST + inline operator floatInVec() const; + inline float getAsFloat() const; +#else + inline operator float() const; +#endif + + inline float operator =( float scalar ); + inline floatInVec operator =( const floatInVec &scalar ); + inline floatInVec operator =( const VecIdx& scalar ); + inline floatInVec operator *=( float scalar ); + inline floatInVec operator *=( const floatInVec &scalar ); + inline floatInVec operator /=( float scalar ); + inline floatInVec operator /=( const floatInVec &scalar ); + inline floatInVec operator +=( float scalar ); + inline floatInVec operator +=( const floatInVec &scalar ); + inline floatInVec operator -=( float scalar ); + inline floatInVec operator -=( const floatInVec &scalar ); +}; + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/PhysicsEffects/include/vecmath/sse/vectormath_aos.h b/Extras/PhysicsEffects/include/vecmath/sse/vectormath_aos.h new file mode 100644 index 0000000..b802810 --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/sse/vectormath_aos.h @@ -0,0 +1,2547 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _VECTORMATH_AOS_CPP_SSE_H +#define _VECTORMATH_AOS_CPP_SSE_H + +#include +#include +#include +#include + +#define Vector3Ref Vector3& +#define QuatRef Quat& +#define Matrix3Ref Matrix3& + +#if (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) + #define USE_SSE3_LDDQU + + #define VM_ATTRIBUTE_ALIGNED_CLASS16(a) __declspec(align(16)) a + #define VM_ATTRIBUTE_ALIGN16 __declspec(align(16)) + #define VECTORMATH_FORCE_INLINE __forceinline +#else + #define VM_ATTRIBUTE_ALIGNED_CLASS16(a) a __attribute__ ((aligned (16))) + #define VM_ATTRIBUTE_ALIGN16 __attribute__ ((aligned (16))) + #define VECTORMATH_FORCE_INLINE inline + #ifdef __SSE3__ + #define USE_SSE3_LDDQU + #endif //__SSE3__ +#endif//_WIN32 + + +#ifdef USE_SSE3_LDDQU +#include //_mm_lddqu_si128 +#endif //USE_SSE3_LDDQU + + +// TODO: Tidy +typedef __m128 vec_float4; +typedef __m128 vec_uint4; +typedef __m128 vec_int4; +typedef __m128i vec_uchar16; +typedef __m128i vec_ushort8; + +#define vec_splat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e)) + +#define _mm_ror_ps(vec,i) \ + (((i)%4) ? (_mm_shuffle_ps(vec,vec, _MM_SHUFFLE((unsigned char)(i+3)%4,(unsigned char)(i+2)%4,(unsigned char)(i+1)%4,(unsigned char)(i+0)%4))) : (vec)) +#define _mm_rol_ps(vec,i) \ + (((i)%4) ? (_mm_shuffle_ps(vec,vec, _MM_SHUFFLE((unsigned char)(7-i)%4,(unsigned char)(6-i)%4,(unsigned char)(5-i)%4,(unsigned char)(4-i)%4))) : (vec)) + +#define vec_sld(vec,vec2,x) _mm_ror_ps(vec, ((x)/4)) + +#define _mm_abs_ps(vec) _mm_andnot_ps(_MASKSIGN_,vec) +#define _mm_neg_ps(vec) _mm_xor_ps(_MASKSIGN_,vec) + +#define vec_madd(a, b, c) _mm_add_ps(c, _mm_mul_ps(a, b) ) + +union SSEFloat +{ + __m128i vi; + __m128 m128; + __m128 vf; + unsigned int ui[4]; + unsigned short s[8]; + float f[4]; + SSEFloat(__m128 v) : m128(v) {} + SSEFloat(__m128i v) : vi(v) {} + SSEFloat() {}//uninitialized +}; + +static VECTORMATH_FORCE_INLINE __m128 vec_sel(__m128 a, __m128 b, __m128 mask) +{ + return _mm_or_ps(_mm_and_ps(mask, b), _mm_andnot_ps(mask, a)); +} +static VECTORMATH_FORCE_INLINE __m128 vec_sel(__m128 a, __m128 b, const unsigned int *_mask) +{ + return vec_sel(a, b, _mm_load_ps((float *)_mask)); +} +static VECTORMATH_FORCE_INLINE __m128 vec_sel(__m128 a, __m128 b, unsigned int _mask) +{ + return vec_sel(a, b, _mm_set1_ps(*(float *)&_mask)); +} + +static VECTORMATH_FORCE_INLINE __m128 toM128(unsigned int x) +{ + return _mm_set1_ps( *(float *)&x ); +} + +static VECTORMATH_FORCE_INLINE __m128 fabsf4(__m128 x) +{ + return _mm_and_ps( x, toM128( 0x7fffffff ) ); +} +/* +union SSE64 +{ + __m128 m128; + struct + { + __m64 m01; + __m64 m23; + } m64; +}; + +static VECTORMATH_FORCE_INLINE __m128 vec_cts(__m128 x, int a) +{ + assert(a == 0); // Only 2^0 supported + (void)a; + SSE64 sse64; + sse64.m64.m01 = _mm_cvttps_pi32(x); + sse64.m64.m23 = _mm_cvttps_pi32(_mm_ror_ps(x,2)); + _mm_empty(); + return sse64.m128; +} + +static VECTORMATH_FORCE_INLINE __m128 vec_ctf(__m128 x, int a) +{ + assert(a == 0); // Only 2^0 supported + (void)a; + SSE64 sse64; + sse64.m128 = x; + __m128 result =_mm_movelh_ps( + _mm_cvt_pi2ps(_mm_setzero_ps(), sse64.m64.m01), + _mm_cvt_pi2ps(_mm_setzero_ps(), sse64.m64.m23)); + _mm_empty(); + return result; +} +*/ +static VECTORMATH_FORCE_INLINE __m128 vec_cts(__m128 x, int a) +{ + assert(a == 0); // Only 2^0 supported + (void)a; + __m128i result = _mm_cvtps_epi32(x); + return (__m128 &)result; +} + +static VECTORMATH_FORCE_INLINE __m128 vec_ctf(__m128 x, int a) +{ + assert(a == 0); // Only 2^0 supported + (void)a; + return _mm_cvtepi32_ps((__m128i &)x); +} + +#define vec_nmsub(a,b,c) _mm_sub_ps( c, _mm_mul_ps( a, b ) ) +#define vec_sub(a,b) _mm_sub_ps( a, b ) +#define vec_add(a,b) _mm_add_ps( a, b ) +#define vec_mul(a,b) _mm_mul_ps( a, b ) +#define vec_xor(a,b) _mm_xor_ps( a, b ) +#define vec_and(a,b) _mm_and_ps( a, b ) +#define vec_cmpeq(a,b) _mm_cmpeq_ps( a, b ) +#define vec_cmpgt(a,b) _mm_cmpgt_ps( a, b ) + +#define vec_mergeh(a,b) _mm_unpacklo_ps( a, b ) +#define vec_mergel(a,b) _mm_unpackhi_ps( a, b ) + +#define vec_andc(a,b) _mm_andnot_ps( b, a ) + +#define sqrtf4(x) _mm_sqrt_ps( x ) +#define rsqrtf4(x) _mm_rsqrt_ps( x ) +#define recipf4(x) _mm_rcp_ps( x ) +#define negatef4(x) _mm_sub_ps( _mm_setzero_ps(), x ) + +static VECTORMATH_FORCE_INLINE __m128 newtonrapson_rsqrt4( const __m128 v ) +{ +#define _half4 _mm_setr_ps(.5f,.5f,.5f,.5f) +#define _three _mm_setr_ps(3.f,3.f,3.f,3.f) +const __m128 approx = _mm_rsqrt_ps( v ); +const __m128 muls = _mm_mul_ps(_mm_mul_ps(v, approx), approx); +return _mm_mul_ps(_mm_mul_ps(_half4, approx), _mm_sub_ps(_three, muls) ); +} + +static VECTORMATH_FORCE_INLINE __m128 acosf4(__m128 x) +{ + __m128 xabs = fabsf4(x); + __m128 select = _mm_cmplt_ps( x, _mm_setzero_ps() ); + __m128 t1 = sqrtf4(vec_sub(_mm_set1_ps(1.0f), xabs)); + + /* Instruction counts can be reduced if the polynomial was + * computed entirely from nested (dependent) fma's. However, + * to reduce the number of pipeline stalls, the polygon is evaluated + * in two halves (hi amd lo). + */ + __m128 xabs2 = _mm_mul_ps(xabs, xabs); + __m128 xabs4 = _mm_mul_ps(xabs2, xabs2); + __m128 hi = vec_madd(vec_madd(vec_madd(_mm_set1_ps(-0.0012624911f), + xabs, _mm_set1_ps(0.0066700901f)), + xabs, _mm_set1_ps(-0.0170881256f)), + xabs, _mm_set1_ps( 0.0308918810f)); + __m128 lo = vec_madd(vec_madd(vec_madd(_mm_set1_ps(-0.0501743046f), + xabs, _mm_set1_ps(0.0889789874f)), + xabs, _mm_set1_ps(-0.2145988016f)), + xabs, _mm_set1_ps( 1.5707963050f)); + + __m128 result = vec_madd(hi, xabs4, lo); + + // Adjust the result if x is negactive. + return vec_sel( + vec_mul(t1, result), // Positive + vec_nmsub(t1, result, _mm_set1_ps(3.1415926535898f)), // Negative + select); +} + +static VECTORMATH_FORCE_INLINE __m128 sinf4(vec_float4 x) +{ + +// +// Common constants used to evaluate sinf4/cosf4/tanf4 +// +#define _SINCOS_CC0 -0.0013602249f +#define _SINCOS_CC1 0.0416566950f +#define _SINCOS_CC2 -0.4999990225f +#define _SINCOS_SC0 -0.0001950727f +#define _SINCOS_SC1 0.0083320758f +#define _SINCOS_SC2 -0.1666665247f + +#define _SINCOS_KC1 1.57079625129f +#define _SINCOS_KC2 7.54978995489e-8f + + vec_float4 xl,xl2,xl3,res; + + // Range reduction using : xl = angle * TwoOverPi; + // + xl = vec_mul(x, _mm_set1_ps(0.63661977236f)); + + // Find the quadrant the angle falls in + // using: q = (int) (ceil(abs(xl))*sign(xl)) + // + vec_int4 q = vec_cts(xl,0); + + // Compute an offset based on the quadrant that the angle falls in + // + vec_int4 offset = _mm_and_ps(q,toM128(0x3)); + + // Remainder in range [-pi/4..pi/4] + // + vec_float4 qf = vec_ctf(q,0); + xl = vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC2),vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC1),x)); + + // Compute x^2 and x^3 + // + xl2 = vec_mul(xl,xl); + xl3 = vec_mul(xl2,xl); + + // Compute both the sin and cos of the angles + // using a polynomial expression: + // cx = 1.0f + xl2 * ((C0 * xl2 + C1) * xl2 + C2), and + // sx = xl + xl3 * ((S0 * xl2 + S1) * xl2 + S2) + // + + vec_float4 cx = + vec_madd( + vec_madd( + vec_madd(_mm_set1_ps(_SINCOS_CC0),xl2,_mm_set1_ps(_SINCOS_CC1)),xl2,_mm_set1_ps(_SINCOS_CC2)),xl2,_mm_set1_ps(1.0f)); + vec_float4 sx = + vec_madd( + vec_madd( + vec_madd(_mm_set1_ps(_SINCOS_SC0),xl2,_mm_set1_ps(_SINCOS_SC1)),xl2,_mm_set1_ps(_SINCOS_SC2)),xl3,xl); + + // Use the cosine when the offset is odd and the sin + // when the offset is even + // + res = vec_sel(cx,sx,vec_cmpeq(vec_and(offset, + toM128(0x1)), + _mm_setzero_ps())); + + // Flip the sign of the result when (offset mod 4) = 1 or 2 + // + return vec_sel( + vec_xor(toM128(0x80000000U), res), // Negative + res, // Positive + vec_cmpeq(vec_and(offset,toM128(0x2)),_mm_setzero_ps())); +} + +static VECTORMATH_FORCE_INLINE void sincosf4(vec_float4 x, vec_float4* s, vec_float4* c) +{ + vec_float4 xl,xl2,xl3; + vec_int4 offsetSin, offsetCos; + + // Range reduction using : xl = angle * TwoOverPi; + // + xl = vec_mul(x, _mm_set1_ps(0.63661977236f)); + + // Find the quadrant the angle falls in + // using: q = (int) (ceil(abs(xl))*sign(xl)) + // + //vec_int4 q = vec_cts(vec_add(xl,vec_sel(_mm_set1_ps(0.5f),xl,(0x80000000))),0); + vec_int4 q = vec_cts(xl,0); + + // Compute the offset based on the quadrant that the angle falls in. + // Add 1 to the offset for the cosine. + // + offsetSin = vec_and(q,toM128((int)0x3)); + __m128i temp = _mm_add_epi32(_mm_set1_epi32(1),(__m128i &)offsetSin); + offsetCos = (__m128 &)temp; + + // Remainder in range [-pi/4..pi/4] + // + vec_float4 qf = vec_ctf(q,0); + xl = vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC2),vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC1),x)); + + // Compute x^2 and x^3 + // + xl2 = vec_mul(xl,xl); + xl3 = vec_mul(xl2,xl); + + // Compute both the sin and cos of the angles + // using a polynomial expression: + // cx = 1.0f + xl2 * ((C0 * xl2 + C1) * xl2 + C2), and + // sx = xl + xl3 * ((S0 * xl2 + S1) * xl2 + S2) + // + vec_float4 cx = + vec_madd( + vec_madd( + vec_madd(_mm_set1_ps(_SINCOS_CC0),xl2,_mm_set1_ps(_SINCOS_CC1)),xl2,_mm_set1_ps(_SINCOS_CC2)),xl2,_mm_set1_ps(1.0f)); + vec_float4 sx = + vec_madd( + vec_madd( + vec_madd(_mm_set1_ps(_SINCOS_SC0),xl2,_mm_set1_ps(_SINCOS_SC1)),xl2,_mm_set1_ps(_SINCOS_SC2)),xl3,xl); + + // Use the cosine when the offset is odd and the sin + // when the offset is even + // + vec_uint4 sinMask = (vec_uint4)vec_cmpeq(vec_and(offsetSin,toM128(0x1)),_mm_setzero_ps()); + vec_uint4 cosMask = (vec_uint4)vec_cmpeq(vec_and(offsetCos,toM128(0x1)),_mm_setzero_ps()); + *s = vec_sel(cx,sx,sinMask); + *c = vec_sel(cx,sx,cosMask); + + // Flip the sign of the result when (offset mod 4) = 1 or 2 + // + sinMask = vec_cmpeq(vec_and(offsetSin,toM128(0x2)),_mm_setzero_ps()); + cosMask = vec_cmpeq(vec_and(offsetCos,toM128(0x2)),_mm_setzero_ps()); + + *s = vec_sel((vec_float4)vec_xor(toM128(0x80000000),(vec_uint4)*s),*s,sinMask); + *c = vec_sel((vec_float4)vec_xor(toM128(0x80000000),(vec_uint4)*c),*c,cosMask); +} + +#include "vecidx_aos.h" +#include "floatInVec.h" +#include "boolInVec.h" + +#ifdef _VECTORMATH_DEBUG +#include +#endif +namespace Vectormath { + +namespace Aos { + +//----------------------------------------------------------------------------- +// Forward Declarations +// + +class Vector3; +class Vector4; +class Point3; +class Quat; +class Matrix3; +class Matrix4; +class Transform3; + +// A 3-D vector in array-of-structures format +// +class Vector3 +{ + __m128 mVec128; + + VECTORMATH_FORCE_INLINE void set128(vec_float4 vec); + + VECTORMATH_FORCE_INLINE vec_float4& get128Ref(); + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Vector3( ) { }; + + // Default copy constructor + // + VECTORMATH_FORCE_INLINE Vector3(const Vector3& vec); + + // Construct a 3-D vector from x, y, and z elements + // + VECTORMATH_FORCE_INLINE Vector3( float x, float y, float z ); + + // Construct a 3-D vector from x, y, and z elements (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3( const floatInVec &x, const floatInVec &y, const floatInVec &z ); + + // Copy elements from a 3-D point into a 3-D vector + // + explicit VECTORMATH_FORCE_INLINE Vector3( const Point3 &pnt ); + + // Set all elements of a 3-D vector to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Vector3( float scalar ); + + // Set all elements of a 3-D vector to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Vector3( const floatInVec &scalar ); + + // Set vector float data in a 3-D vector + // + explicit VECTORMATH_FORCE_INLINE Vector3( __m128 vf4 ); + + // Get vector float data from a 3-D vector + // + VECTORMATH_FORCE_INLINE __m128 get128( ) const; + + // Assign one 3-D vector to another + // + VECTORMATH_FORCE_INLINE Vector3 & operator =( const Vector3 &vec ); + + // Set the x element of a 3-D vector + // + VECTORMATH_FORCE_INLINE Vector3 & setX( float x ); + + // Set the y element of a 3-D vector + // + VECTORMATH_FORCE_INLINE Vector3 & setY( float y ); + + // Set the z element of a 3-D vector + // + VECTORMATH_FORCE_INLINE Vector3 & setZ( float z ); + + // Set the x element of a 3-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & setX( const floatInVec &x ); + + // Set the y element of a 3-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & setY( const floatInVec &y ); + + // Set the z element of a 3-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & setZ( const floatInVec &z ); + + // Get the x element of a 3-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getX( ) const; + + // Get the y element of a 3-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getY( ) const; + + // Get the z element of a 3-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getZ( ) const; + + // Set an x, y, or z element of a 3-D vector by index + // + VECTORMATH_FORCE_INLINE Vector3 & setElem( int idx, float value ); + + // Set an x, y, or z element of a 3-D vector by index (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & setElem( int idx, const floatInVec &value ); + + // Get an x, y, or z element of a 3-D vector by index + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + VECTORMATH_FORCE_INLINE VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + VECTORMATH_FORCE_INLINE const floatInVec operator []( int idx ) const; + + // Add two 3-D vectors + // + VECTORMATH_FORCE_INLINE const Vector3 operator +( const Vector3 &vec ) const; + + // Subtract a 3-D vector from another 3-D vector + // + VECTORMATH_FORCE_INLINE const Vector3 operator -( const Vector3 &vec ) const; + + // Add a 3-D vector to a 3-D point + // + VECTORMATH_FORCE_INLINE const Point3 operator +( const Point3 &pnt ) const; + + // Multiply a 3-D vector by a scalar + // + VECTORMATH_FORCE_INLINE const Vector3 operator *( float scalar ) const; + + // Divide a 3-D vector by a scalar + // + VECTORMATH_FORCE_INLINE const Vector3 operator /( float scalar ) const; + + // Multiply a 3-D vector by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Vector3 operator *( const floatInVec &scalar ) const; + + // Divide a 3-D vector by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Vector3 operator /( const floatInVec &scalar ) const; + + // Perform compound assignment and addition with a 3-D vector + // + VECTORMATH_FORCE_INLINE Vector3 & operator +=( const Vector3 &vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + VECTORMATH_FORCE_INLINE Vector3 & operator -=( const Vector3 &vec ); + + // Perform compound assignment and multiplication by a scalar + // + VECTORMATH_FORCE_INLINE Vector3 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + VECTORMATH_FORCE_INLINE Vector3 & operator /=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and division by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & operator /=( const floatInVec &scalar ); + + // Negate all elements of a 3-D vector + // + VECTORMATH_FORCE_INLINE const Vector3 operator -( ) const; + + // Construct x axis + // + static VECTORMATH_FORCE_INLINE const Vector3 xAxis( ); + + // Construct y axis + // + static VECTORMATH_FORCE_INLINE const Vector3 yAxis( ); + + // Construct z axis + // + static VECTORMATH_FORCE_INLINE const Vector3 zAxis( ); + +}; + +// Multiply a 3-D vector by a scalar +// +VECTORMATH_FORCE_INLINE const Vector3 operator *( float scalar, const Vector3 &vec ); + +// Multiply a 3-D vector by a scalar (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Vector3 operator *( const floatInVec &scalar, const Vector3 &vec ); + +// Multiply two 3-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector3 mulPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Divide two 3-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +VECTORMATH_FORCE_INLINE const Vector3 divPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Compute the reciprocal of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +VECTORMATH_FORCE_INLINE const Vector3 recipPerElem( const Vector3 &vec ); + +// Compute the absolute value of a 3-D vector per element +// +VECTORMATH_FORCE_INLINE const Vector3 absPerElem( const Vector3 &vec ); + +// Copy sign from one 3-D vector to another, per element +// +VECTORMATH_FORCE_INLINE const Vector3 copySignPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Maximum of two 3-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector3 maxPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Minimum of two 3-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector3 minPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Maximum element of a 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Vector3 &vec ); + +// Minimum element of a 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Vector3 &vec ); + +// Compute the sum of all elements of a 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec sum( const Vector3 &vec ); + +// Compute the dot product of two 3-D vectors +// +VECTORMATH_FORCE_INLINE const floatInVec dot( const Vector3 &vec0, const Vector3 &vec1 ); + +// Compute the square of the length of a 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec lengthSqr( const Vector3 &vec ); + +// Compute the length of a 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec length( const Vector3 &vec ); + +// Normalize a 3-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +VECTORMATH_FORCE_INLINE const Vector3 normalize( const Vector3 &vec ); + +// Compute cross product of two 3-D vectors +// +VECTORMATH_FORCE_INLINE const Vector3 cross( const Vector3 &vec0, const Vector3 &vec1 ); + +// Outer product of two 3-D vectors +// +VECTORMATH_FORCE_INLINE const Matrix3 outer( const Vector3 &vec0, const Vector3 &vec1 ); + +// Pre-multiply a row vector by a 3x3 matrix +// NOTE: +// Slower than column post-multiply. +// +VECTORMATH_FORCE_INLINE const Vector3 rowMul( const Vector3 &vec, const Matrix3 & mat ); + +// Cross-product matrix of a 3-D vector +// +VECTORMATH_FORCE_INLINE const Matrix3 crossMatrix( const Vector3 &vec ); + +// Create cross-product matrix and multiply +// NOTE: +// Faster than separately creating a cross-product matrix and multiplying. +// +VECTORMATH_FORCE_INLINE const Matrix3 crossMatrixMul( const Vector3 &vec, const Matrix3 & mat ); + +// Linear interpolation between two 3-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector3 lerp( float t, const Vector3 &vec0, const Vector3 &vec1 ); + +// Linear interpolation between two 3-D vectors (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector3 lerp( const floatInVec &t, const Vector3 &vec0, const Vector3 &vec1 ); + +// Spherical linear interpolation between two 3-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector3 slerp( float t, const Vector3 &unitVec0, const Vector3 &unitVec1 ); + +// Spherical linear interpolation between two 3-D vectors (scalar data contained in vector data type) +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector3 slerp( const floatInVec &t, const Vector3 &unitVec0, const Vector3 &unitVec1 ); + +// Conditionally select between two 3-D vectors +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Vector3 select( const Vector3 &vec0, const Vector3 &vec1, bool select1 ); + +// Conditionally select between two 3-D vectors (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Vector3 select( const Vector3 &vec0, const Vector3 &vec1, const boolInVec &select1 ); + +// Store x, y, and z elements of 3-D vector in first three words of a quadword, preserving fourth word +// +VECTORMATH_FORCE_INLINE void storeXYZ( const Vector3 &vec, __m128 * quad ); + +// Load four three-float 3-D vectors, stored in three quadwords +// +VECTORMATH_FORCE_INLINE void loadXYZArray( Vector3 & vec0, Vector3 & vec1, Vector3 & vec2, Vector3 & vec3, const __m128 * threeQuads ); + +// Store four 3-D vectors in three quadwords +// +VECTORMATH_FORCE_INLINE void storeXYZArray( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, __m128 * threeQuads ); + +// Store eight 3-D vectors as half-floats +// +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, const Vector3 &vec4, const Vector3 &vec5, const Vector3 &vec6, const Vector3 &vec7, vec_ushort8 * threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Vector3 &vec ); + +// Print a 3-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Vector3 &vec, const char * name ); + +#endif + +// A 4-D vector in array-of-structures format +// +class Vector4 +{ + __m128 mVec128; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Vector4( ) { }; + + // Construct a 4-D vector from x, y, z, and w elements + // + VECTORMATH_FORCE_INLINE Vector4( float x, float y, float z, float w ); + + // Construct a 4-D vector from x, y, z, and w elements (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4( const floatInVec &x, const floatInVec &y, const floatInVec &z, const floatInVec &w ); + + // Construct a 4-D vector from a 3-D vector and a scalar + // + VECTORMATH_FORCE_INLINE Vector4( const Vector3 &xyz, float w ); + + // Construct a 4-D vector from a 3-D vector and a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4( const Vector3 &xyz, const floatInVec &w ); + + // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + // + explicit VECTORMATH_FORCE_INLINE Vector4( const Vector3 &vec ); + + // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + // + explicit VECTORMATH_FORCE_INLINE Vector4( const Point3 &pnt ); + + // Copy elements from a quaternion into a 4-D vector + // + explicit VECTORMATH_FORCE_INLINE Vector4( const Quat &quat ); + + // Set all elements of a 4-D vector to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Vector4( float scalar ); + + // Set all elements of a 4-D vector to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Vector4( const floatInVec &scalar ); + + // Set vector float data in a 4-D vector + // + explicit VECTORMATH_FORCE_INLINE Vector4( __m128 vf4 ); + + // Get vector float data from a 4-D vector + // + VECTORMATH_FORCE_INLINE __m128 get128( ) const; + + // Assign one 4-D vector to another + // + VECTORMATH_FORCE_INLINE Vector4 & operator =( const Vector4 &vec ); + + // Set the x, y, and z elements of a 4-D vector + // NOTE: + // This function does not change the w element. + // + VECTORMATH_FORCE_INLINE Vector4 & setXYZ( const Vector3 &vec ); + + // Get the x, y, and z elements of a 4-D vector + // + VECTORMATH_FORCE_INLINE const Vector3 getXYZ( ) const; + + // Set the x element of a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & setX( float x ); + + // Set the y element of a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & setY( float y ); + + // Set the z element of a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & setZ( float z ); + + // Set the w element of a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & setW( float w ); + + // Set the x element of a 4-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & setX( const floatInVec &x ); + + // Set the y element of a 4-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & setY( const floatInVec &y ); + + // Set the z element of a 4-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & setZ( const floatInVec &z ); + + // Set the w element of a 4-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & setW( const floatInVec &w ); + + // Get the x element of a 4-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getX( ) const; + + // Get the y element of a 4-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getY( ) const; + + // Get the z element of a 4-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getZ( ) const; + + // Get the w element of a 4-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getW( ) const; + + // Set an x, y, z, or w element of a 4-D vector by index + // + VECTORMATH_FORCE_INLINE Vector4 & setElem( int idx, float value ); + + // Set an x, y, z, or w element of a 4-D vector by index (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & setElem( int idx, const floatInVec &value ); + + // Get an x, y, z, or w element of a 4-D vector by index + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + VECTORMATH_FORCE_INLINE VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + VECTORMATH_FORCE_INLINE const floatInVec operator []( int idx ) const; + + // Add two 4-D vectors + // + VECTORMATH_FORCE_INLINE const Vector4 operator +( const Vector4 &vec ) const; + + // Subtract a 4-D vector from another 4-D vector + // + VECTORMATH_FORCE_INLINE const Vector4 operator -( const Vector4 &vec ) const; + + // Multiply a 4-D vector by a scalar + // + VECTORMATH_FORCE_INLINE const Vector4 operator *( float scalar ) const; + + // Divide a 4-D vector by a scalar + // + VECTORMATH_FORCE_INLINE const Vector4 operator /( float scalar ) const; + + // Multiply a 4-D vector by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Vector4 operator *( const floatInVec &scalar ) const; + + // Divide a 4-D vector by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Vector4 operator /( const floatInVec &scalar ) const; + + // Perform compound assignment and addition with a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & operator +=( const Vector4 &vec ); + + // Perform compound assignment and subtraction by a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & operator -=( const Vector4 &vec ); + + // Perform compound assignment and multiplication by a scalar + // + VECTORMATH_FORCE_INLINE Vector4 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + VECTORMATH_FORCE_INLINE Vector4 & operator /=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and division by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & operator /=( const floatInVec &scalar ); + + // Negate all elements of a 4-D vector + // + VECTORMATH_FORCE_INLINE const Vector4 operator -( ) const; + + // Construct x axis + // + static VECTORMATH_FORCE_INLINE const Vector4 xAxis( ); + + // Construct y axis + // + static VECTORMATH_FORCE_INLINE const Vector4 yAxis( ); + + // Construct z axis + // + static VECTORMATH_FORCE_INLINE const Vector4 zAxis( ); + + // Construct w axis + // + static VECTORMATH_FORCE_INLINE const Vector4 wAxis( ); + +}; + +// Multiply a 4-D vector by a scalar +// +VECTORMATH_FORCE_INLINE const Vector4 operator *( float scalar, const Vector4 &vec ); + +// Multiply a 4-D vector by a scalar (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Vector4 operator *( const floatInVec &scalar, const Vector4 &vec ); + +// Multiply two 4-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector4 mulPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Divide two 4-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +VECTORMATH_FORCE_INLINE const Vector4 divPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Compute the reciprocal of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +VECTORMATH_FORCE_INLINE const Vector4 recipPerElem( const Vector4 &vec ); + +// Compute the absolute value of a 4-D vector per element +// +VECTORMATH_FORCE_INLINE const Vector4 absPerElem( const Vector4 &vec ); + +// Copy sign from one 4-D vector to another, per element +// +VECTORMATH_FORCE_INLINE const Vector4 copySignPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Maximum of two 4-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector4 maxPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Minimum of two 4-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector4 minPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Maximum element of a 4-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Vector4 &vec ); + +// Minimum element of a 4-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Vector4 &vec ); + +// Compute the sum of all elements of a 4-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec sum( const Vector4 &vec ); + +// Compute the dot product of two 4-D vectors +// +VECTORMATH_FORCE_INLINE const floatInVec dot( const Vector4 &vec0, const Vector4 &vec1 ); + +// Compute the square of the length of a 4-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec lengthSqr( const Vector4 &vec ); + +// Compute the length of a 4-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec length( const Vector4 &vec ); + +// Normalize a 4-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +VECTORMATH_FORCE_INLINE const Vector4 normalize( const Vector4 &vec ); + +// Outer product of two 4-D vectors +// +VECTORMATH_FORCE_INLINE const Matrix4 outer( const Vector4 &vec0, const Vector4 &vec1 ); + +// Linear interpolation between two 4-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector4 lerp( float t, const Vector4 &vec0, const Vector4 &vec1 ); + +// Linear interpolation between two 4-D vectors (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector4 lerp( const floatInVec &t, const Vector4 &vec0, const Vector4 &vec1 ); + +// Spherical linear interpolation between two 4-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector4 slerp( float t, const Vector4 &unitVec0, const Vector4 &unitVec1 ); + +// Spherical linear interpolation between two 4-D vectors (scalar data contained in vector data type) +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector4 slerp( const floatInVec &t, const Vector4 &unitVec0, const Vector4 &unitVec1 ); + +// Conditionally select between two 4-D vectors +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Vector4 select( const Vector4 &vec0, const Vector4 &vec1, bool select1 ); + +// Conditionally select between two 4-D vectors (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Vector4 select( const Vector4 &vec0, const Vector4 &vec1, const boolInVec &select1 ); + +// Store four 4-D vectors as half-floats +// +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Vector4 &vec0, const Vector4 &vec1, const Vector4 &vec2, const Vector4 &vec3, vec_ushort8 * twoQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Vector4 &vec ); + +// Print a 4-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Vector4 &vec, const char * name ); + +#endif + +// A 3-D point in array-of-structures format +// +class Point3 +{ + __m128 mVec128; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Point3( ) { }; + + // Construct a 3-D point from x, y, and z elements + // + VECTORMATH_FORCE_INLINE Point3( float x, float y, float z ); + + // Construct a 3-D point from x, y, and z elements (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Point3( const floatInVec &x, const floatInVec &y, const floatInVec &z ); + + // Copy elements from a 3-D vector into a 3-D point + // + explicit VECTORMATH_FORCE_INLINE Point3( const Vector3 &vec ); + + // Set all elements of a 3-D point to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Point3( float scalar ); + + // Set all elements of a 3-D point to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Point3( const floatInVec &scalar ); + + // Set vector float data in a 3-D point + // + explicit VECTORMATH_FORCE_INLINE Point3( __m128 vf4 ); + + // Get vector float data from a 3-D point + // + VECTORMATH_FORCE_INLINE __m128 get128( ) const; + + // Assign one 3-D point to another + // + VECTORMATH_FORCE_INLINE Point3 & operator =( const Point3 &pnt ); + + // Set the x element of a 3-D point + // + VECTORMATH_FORCE_INLINE Point3 & setX( float x ); + + // Set the y element of a 3-D point + // + VECTORMATH_FORCE_INLINE Point3 & setY( float y ); + + // Set the z element of a 3-D point + // + VECTORMATH_FORCE_INLINE Point3 & setZ( float z ); + + // Set the x element of a 3-D point (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Point3 & setX( const floatInVec &x ); + + // Set the y element of a 3-D point (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Point3 & setY( const floatInVec &y ); + + // Set the z element of a 3-D point (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Point3 & setZ( const floatInVec &z ); + + // Get the x element of a 3-D point + // + VECTORMATH_FORCE_INLINE const floatInVec getX( ) const; + + // Get the y element of a 3-D point + // + VECTORMATH_FORCE_INLINE const floatInVec getY( ) const; + + // Get the z element of a 3-D point + // + VECTORMATH_FORCE_INLINE const floatInVec getZ( ) const; + + // Set an x, y, or z element of a 3-D point by index + // + VECTORMATH_FORCE_INLINE Point3 & setElem( int idx, float value ); + + // Set an x, y, or z element of a 3-D point by index (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Point3 & setElem( int idx, const floatInVec &value ); + + // Get an x, y, or z element of a 3-D point by index + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + VECTORMATH_FORCE_INLINE VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + VECTORMATH_FORCE_INLINE const floatInVec operator []( int idx ) const; + + // Subtract a 3-D point from another 3-D point + // + VECTORMATH_FORCE_INLINE const Vector3 operator -( const Point3 &pnt ) const; + + // Add a 3-D point to a 3-D vector + // + VECTORMATH_FORCE_INLINE const Point3 operator +( const Vector3 &vec ) const; + + // Subtract a 3-D vector from a 3-D point + // + VECTORMATH_FORCE_INLINE const Point3 operator -( const Vector3 &vec ) const; + + // Perform compound assignment and addition with a 3-D vector + // + VECTORMATH_FORCE_INLINE Point3 & operator +=( const Vector3 &vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + VECTORMATH_FORCE_INLINE Point3 & operator -=( const Vector3 &vec ); + +}; + +// Multiply two 3-D points per element +// +VECTORMATH_FORCE_INLINE const Point3 mulPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Divide two 3-D points per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +VECTORMATH_FORCE_INLINE const Point3 divPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Compute the reciprocal of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +VECTORMATH_FORCE_INLINE const Point3 recipPerElem( const Point3 &pnt ); + +// Compute the absolute value of a 3-D point per element +// +VECTORMATH_FORCE_INLINE const Point3 absPerElem( const Point3 &pnt ); + +// Copy sign from one 3-D point to another, per element +// +VECTORMATH_FORCE_INLINE const Point3 copySignPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Maximum of two 3-D points per element +// +VECTORMATH_FORCE_INLINE const Point3 maxPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Minimum of two 3-D points per element +// +VECTORMATH_FORCE_INLINE const Point3 minPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Maximum element of a 3-D point +// +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Point3 &pnt ); + +// Minimum element of a 3-D point +// +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Point3 &pnt ); + +// Compute the sum of all elements of a 3-D point +// +VECTORMATH_FORCE_INLINE const floatInVec sum( const Point3 &pnt ); + +// Apply uniform scale to a 3-D point +// +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, float scaleVal ); + +// Apply uniform scale to a 3-D point (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, const floatInVec &scaleVal ); + +// Apply non-uniform scale to a 3-D point +// +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, const Vector3 &scaleVec ); + +// Scalar projection of a 3-D point on a unit-length 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec projection( const Point3 &pnt, const Vector3 &unitVec ); + +// Compute the square of the distance of a 3-D point from the coordinate-system origin +// +VECTORMATH_FORCE_INLINE const floatInVec distSqrFromOrigin( const Point3 &pnt ); + +// Compute the distance of a 3-D point from the coordinate-system origin +// +VECTORMATH_FORCE_INLINE const floatInVec distFromOrigin( const Point3 &pnt ); + +// Compute the square of the distance between two 3-D points +// +VECTORMATH_FORCE_INLINE const floatInVec distSqr( const Point3 &pnt0, const Point3 &pnt1 ); + +// Compute the distance between two 3-D points +// +VECTORMATH_FORCE_INLINE const floatInVec dist( const Point3 &pnt0, const Point3 &pnt1 ); + +// Linear interpolation between two 3-D points +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Point3 lerp( float t, const Point3 &pnt0, const Point3 &pnt1 ); + +// Linear interpolation between two 3-D points (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Point3 lerp( const floatInVec &t, const Point3 &pnt0, const Point3 &pnt1 ); + +// Conditionally select between two 3-D points +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Point3 select( const Point3 &pnt0, const Point3 &pnt1, bool select1 ); + +// Conditionally select between two 3-D points (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Point3 select( const Point3 &pnt0, const Point3 &pnt1, const boolInVec &select1 ); + +// Store x, y, and z elements of 3-D point in first three words of a quadword, preserving fourth word +// +VECTORMATH_FORCE_INLINE void storeXYZ( const Point3 &pnt, __m128 * quad ); + +// Load four three-float 3-D points, stored in three quadwords +// +VECTORMATH_FORCE_INLINE void loadXYZArray( Point3 & pnt0, Point3 & pnt1, Point3 & pnt2, Point3 & pnt3, const __m128 * threeQuads ); + +// Store four 3-D points in three quadwords +// +VECTORMATH_FORCE_INLINE void storeXYZArray( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, __m128 * threeQuads ); + +// Store eight 3-D points as half-floats +// +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, const Point3 &pnt4, const Point3 &pnt5, const Point3 &pnt6, const Point3 &pnt7, vec_ushort8 * threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D point +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Point3 &pnt ); + +// Print a 3-D point and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Point3 &pnt, const char * name ); + +#endif + +// A quaternion in array-of-structures format +// +class Quat +{ + __m128 mVec128; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Quat( ) { }; + + VECTORMATH_FORCE_INLINE Quat(const Quat& quat); + + // Construct a quaternion from x, y, z, and w elements + // + VECTORMATH_FORCE_INLINE Quat( float x, float y, float z, float w ); + + // Construct a quaternion from x, y, z, and w elements (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat( const floatInVec &x, const floatInVec &y, const floatInVec &z, const floatInVec &w ); + + // Construct a quaternion from a 3-D vector and a scalar + // + VECTORMATH_FORCE_INLINE Quat( const Vector3 &xyz, float w ); + + // Construct a quaternion from a 3-D vector and a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat( const Vector3 &xyz, const floatInVec &w ); + + // Copy elements from a 4-D vector into a quaternion + // + explicit VECTORMATH_FORCE_INLINE Quat( const Vector4 &vec ); + + // Convert a rotation matrix to a unit-length quaternion + // + explicit VECTORMATH_FORCE_INLINE Quat( const Matrix3 & rotMat ); + + // Set all elements of a quaternion to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Quat( float scalar ); + + // Set all elements of a quaternion to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Quat( const floatInVec &scalar ); + + // Set vector float data in a quaternion + // + explicit VECTORMATH_FORCE_INLINE Quat( __m128 vf4 ); + + // Get vector float data from a quaternion + // + VECTORMATH_FORCE_INLINE __m128 get128( ) const; + + // Set a quaterion from vector float data + // + VECTORMATH_FORCE_INLINE void set128(vec_float4 vec); + + // Assign one quaternion to another + // + VECTORMATH_FORCE_INLINE Quat & operator =( const Quat &quat ); + + // Set the x, y, and z elements of a quaternion + // NOTE: + // This function does not change the w element. + // + VECTORMATH_FORCE_INLINE Quat & setXYZ( const Vector3 &vec ); + + // Get the x, y, and z elements of a quaternion + // + VECTORMATH_FORCE_INLINE const Vector3 getXYZ( ) const; + + // Set the x element of a quaternion + // + VECTORMATH_FORCE_INLINE Quat & setX( float x ); + + // Set the y element of a quaternion + // + VECTORMATH_FORCE_INLINE Quat & setY( float y ); + + // Set the z element of a quaternion + // + VECTORMATH_FORCE_INLINE Quat & setZ( float z ); + + // Set the w element of a quaternion + // + VECTORMATH_FORCE_INLINE Quat & setW( float w ); + + // Set the x element of a quaternion (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & setX( const floatInVec &x ); + + // Set the y element of a quaternion (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & setY( const floatInVec &y ); + + // Set the z element of a quaternion (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & setZ( const floatInVec &z ); + + // Set the w element of a quaternion (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & setW( const floatInVec &w ); + + // Get the x element of a quaternion + // + VECTORMATH_FORCE_INLINE const floatInVec getX( ) const; + + // Get the y element of a quaternion + // + VECTORMATH_FORCE_INLINE const floatInVec getY( ) const; + + // Get the z element of a quaternion + // + VECTORMATH_FORCE_INLINE const floatInVec getZ( ) const; + + // Get the w element of a quaternion + // + VECTORMATH_FORCE_INLINE const floatInVec getW( ) const; + + // Set an x, y, z, or w element of a quaternion by index + // + VECTORMATH_FORCE_INLINE Quat & setElem( int idx, float value ); + + // Set an x, y, z, or w element of a quaternion by index (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & setElem( int idx, const floatInVec &value ); + + // Get an x, y, z, or w element of a quaternion by index + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + VECTORMATH_FORCE_INLINE VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + VECTORMATH_FORCE_INLINE const floatInVec operator []( int idx ) const; + + // Add two quaternions + // + VECTORMATH_FORCE_INLINE const Quat operator +( const Quat &quat ) const; + + // Subtract a quaternion from another quaternion + // + VECTORMATH_FORCE_INLINE const Quat operator -( const Quat &quat ) const; + + // Multiply two quaternions + // + VECTORMATH_FORCE_INLINE const Quat operator *( const Quat &quat ) const; + + // Multiply a quaternion by a scalar + // + VECTORMATH_FORCE_INLINE const Quat operator *( float scalar ) const; + + // Divide a quaternion by a scalar + // + VECTORMATH_FORCE_INLINE const Quat operator /( float scalar ) const; + + // Multiply a quaternion by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Quat operator *( const floatInVec &scalar ) const; + + // Divide a quaternion by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Quat operator /( const floatInVec &scalar ) const; + + // Perform compound assignment and addition with a quaternion + // + VECTORMATH_FORCE_INLINE Quat & operator +=( const Quat &quat ); + + // Perform compound assignment and subtraction by a quaternion + // + VECTORMATH_FORCE_INLINE Quat & operator -=( const Quat &quat ); + + // Perform compound assignment and multiplication by a quaternion + // + VECTORMATH_FORCE_INLINE Quat & operator *=( const Quat &quat ); + + // Perform compound assignment and multiplication by a scalar + // + VECTORMATH_FORCE_INLINE Quat & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + VECTORMATH_FORCE_INLINE Quat & operator /=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and division by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & operator /=( const floatInVec &scalar ); + + // Negate all elements of a quaternion + // + VECTORMATH_FORCE_INLINE const Quat operator -( ) const; + + // Construct an identity quaternion + // + static VECTORMATH_FORCE_INLINE const Quat identity( ); + + // Construct a quaternion to rotate between two unit-length 3-D vectors + // NOTE: + // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + // + static VECTORMATH_FORCE_INLINE const Quat rotation( const Vector3 &unitVec0, const Vector3 &unitVec1 ); + + // Construct a quaternion to rotate around a unit-length 3-D vector + // + static VECTORMATH_FORCE_INLINE const Quat rotation( float radians, const Vector3 &unitVec ); + + // Construct a quaternion to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Quat rotation( const floatInVec &radians, const Vector3 &unitVec ); + + // Construct a quaternion to rotate around the x axis + // + static VECTORMATH_FORCE_INLINE const Quat rotationX( float radians ); + + // Construct a quaternion to rotate around the y axis + // + static VECTORMATH_FORCE_INLINE const Quat rotationY( float radians ); + + // Construct a quaternion to rotate around the z axis + // + static VECTORMATH_FORCE_INLINE const Quat rotationZ( float radians ); + + // Construct a quaternion to rotate around the x axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Quat rotationX( const floatInVec &radians ); + + // Construct a quaternion to rotate around the y axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Quat rotationY( const floatInVec &radians ); + + // Construct a quaternion to rotate around the z axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Quat rotationZ( const floatInVec &radians ); + +}; + +// Multiply a quaternion by a scalar +// +VECTORMATH_FORCE_INLINE const Quat operator *( float scalar, const Quat &quat ); + +// Multiply a quaternion by a scalar (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Quat operator *( const floatInVec &scalar, const Quat &quat ); + +// Compute the conjugate of a quaternion +// +VECTORMATH_FORCE_INLINE const Quat conj( const Quat &quat ); + +// Use a unit-length quaternion to rotate a 3-D vector +// +VECTORMATH_FORCE_INLINE const Vector3 rotate( const Quat &unitQuat, const Vector3 &vec ); + +// Compute the dot product of two quaternions +// +VECTORMATH_FORCE_INLINE const floatInVec dot( const Quat &quat0, const Quat &quat1 ); + +// Compute the norm of a quaternion +// +VECTORMATH_FORCE_INLINE const floatInVec norm( const Quat &quat ); + +// Compute the length of a quaternion +// +VECTORMATH_FORCE_INLINE const floatInVec length( const Quat &quat ); + +// Normalize a quaternion +// NOTE: +// The result is unpredictable when all elements of quat are at or near zero. +// +VECTORMATH_FORCE_INLINE const Quat normalize( const Quat &quat ); + +// Linear interpolation between two quaternions +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Quat lerp( float t, const Quat &quat0, const Quat &quat1 ); + +// Linear interpolation between two quaternions (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Quat lerp( const floatInVec &t, const Quat &quat0, const Quat &quat1 ); + +// Spherical linear interpolation between two quaternions +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Quat slerp( float t, const Quat &unitQuat0, const Quat &unitQuat1 ); + +// Spherical linear interpolation between two quaternions (scalar data contained in vector data type) +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Quat slerp( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1 ); + +// Spherical quadrangle interpolation +// +VECTORMATH_FORCE_INLINE const Quat squad( float t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ); + +// Spherical quadrangle interpolation (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Quat squad( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ); + +// Conditionally select between two quaternions +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, bool select1 ); + +// Conditionally select between two quaternions (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, const boolInVec &select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a quaternion +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Quat &quat ); + +// Print a quaternion and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Quat &quat, const char * name ); + +#endif + +// A 3x3 matrix in array-of-structures format +// +class Matrix3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Matrix3( ) { }; + + // Copy a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3( const Matrix3 & mat ); + + // Construct a 3x3 matrix containing the specified columns + // + VECTORMATH_FORCE_INLINE Matrix3( const Vector3 &col0, const Vector3 &col1, const Vector3 &col2 ); + + // Construct a 3x3 rotation matrix from a unit-length quaternion + // + explicit VECTORMATH_FORCE_INLINE Matrix3( const Quat &unitQuat ); + + // Set all elements of a 3x3 matrix to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Matrix3( float scalar ); + + // Set all elements of a 3x3 matrix to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Matrix3( const floatInVec &scalar ); + + // Assign one 3x3 matrix to another + // + VECTORMATH_FORCE_INLINE Matrix3 & operator =( const Matrix3 & mat ); + + // Set column 0 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & setCol0( const Vector3 &col0 ); + + // Set column 1 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & setCol1( const Vector3 &col1 ); + + // Set column 2 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & setCol2( const Vector3 &col2 ); + + // Get column 0 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol0( ) const; + + // Get column 1 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol1( ) const; + + // Get column 2 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol2( ) const; + + // Set the column of a 3x3 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Matrix3 & setCol( int col, const Vector3 &vec ); + + // Set the row of a 3x3 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Matrix3 & setRow( int row, const Vector3 &vec ); + + // Get the column of a 3x3 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector3 getCol( int col ) const; + + // Get the row of a 3x3 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector3 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + VECTORMATH_FORCE_INLINE Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + VECTORMATH_FORCE_INLINE const Vector3 operator []( int col ) const; + + // Set the element of a 3x3 matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE Matrix3 & setElem( int col, int row, float val ); + + // Set the element of a 3x3 matrix referred to by column and row indices (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Matrix3 & setElem( int col, int row, const floatInVec &val ); + + // Get the element of a 3x3 matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int col, int row ) const; + + // Add two 3x3 matrices + // + VECTORMATH_FORCE_INLINE const Matrix3 operator +( const Matrix3 & mat ) const; + + // Subtract a 3x3 matrix from another 3x3 matrix + // + VECTORMATH_FORCE_INLINE const Matrix3 operator -( const Matrix3 & mat ) const; + + // Negate all elements of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE const Matrix3 operator -( ) const; + + // Multiply a 3x3 matrix by a scalar + // + VECTORMATH_FORCE_INLINE const Matrix3 operator *( float scalar ) const; + + // Multiply a 3x3 matrix by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Matrix3 operator *( const floatInVec &scalar ) const; + + // Multiply a 3x3 matrix by a 3-D vector + // + VECTORMATH_FORCE_INLINE const Vector3 operator *( const Vector3 &vec ) const; + + // Multiply two 3x3 matrices + // + VECTORMATH_FORCE_INLINE const Matrix3 operator *( const Matrix3 & mat ) const; + + // Perform compound assignment and addition with a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & operator +=( const Matrix3 & mat ); + + // Perform compound assignment and subtraction by a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & operator -=( const Matrix3 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + VECTORMATH_FORCE_INLINE Matrix3 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Matrix3 & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and multiplication by a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & operator *=( const Matrix3 & mat ); + + // Construct an identity 3x3 matrix + // + static VECTORMATH_FORCE_INLINE const Matrix3 identity( ); + + // Construct a 3x3 matrix to rotate around the x axis + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationX( float radians ); + + // Construct a 3x3 matrix to rotate around the y axis + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationY( float radians ); + + // Construct a 3x3 matrix to rotate around the z axis + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationZ( float radians ); + + // Construct a 3x3 matrix to rotate around the x axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationX( const floatInVec &radians ); + + // Construct a 3x3 matrix to rotate around the y axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationY( const floatInVec &radians ); + + // Construct a 3x3 matrix to rotate around the z axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationZ( const floatInVec &radians ); + + // Construct a 3x3 matrix to rotate around the x, y, and z axes + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationZYX( const Vector3 &radiansXYZ ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotation( float radians, const Vector3 &unitVec ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotation( const floatInVec &radians, const Vector3 &unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotation( const Quat &unitQuat ); + + // Construct a 3x3 matrix to perform scaling + // + static VECTORMATH_FORCE_INLINE const Matrix3 scale( const Vector3 &scaleVec ); + +}; +// Multiply a 3x3 matrix by a scalar +// +VECTORMATH_FORCE_INLINE const Matrix3 operator *( float scalar, const Matrix3 & mat ); + +// Multiply a 3x3 matrix by a scalar (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Matrix3 operator *( const floatInVec &scalar, const Matrix3 & mat ); + +// Append (post-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Matrix3 appendScale( const Matrix3 & mat, const Vector3 &scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Matrix3 prependScale( const Vector3 &scaleVec, const Matrix3 & mat ); + +// Multiply two 3x3 matrices per element +// +VECTORMATH_FORCE_INLINE const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); + +// Compute the absolute value of a 3x3 matrix per element +// +VECTORMATH_FORCE_INLINE const Matrix3 absPerElem( const Matrix3 & mat ); + +// Transpose of a 3x3 matrix +// +VECTORMATH_FORCE_INLINE const Matrix3 transpose( const Matrix3 & mat ); + +// Compute the inverse of a 3x3 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +VECTORMATH_FORCE_INLINE const Matrix3 inverse( const Matrix3 & mat ); + +// Determinant of a 3x3 matrix +// +VECTORMATH_FORCE_INLINE const floatInVec determinant( const Matrix3 & mat ); + +// Conditionally select between two 3x3 matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ); + +// Conditionally select between two 3x3 matrices (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, const boolInVec &select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x3 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Matrix3 & mat ); + +// Print a 3x3 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Matrix3 & mat, const char * name ); + +#endif + +// A 4x4 matrix in array-of-structures format +// +class Matrix4 +{ + Vector4 mCol0; + Vector4 mCol1; + Vector4 mCol2; + Vector4 mCol3; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Matrix4( ) { }; + + // Copy a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4( const Matrix4 & mat ); + + // Construct a 4x4 matrix containing the specified columns + // + VECTORMATH_FORCE_INLINE Matrix4( const Vector4 &col0, const Vector4 &col1, const Vector4 &col2, const Vector4 &col3 ); + + // Construct a 4x4 matrix from a 3x4 transformation matrix + // + explicit VECTORMATH_FORCE_INLINE Matrix4( const Transform3 & mat ); + + // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + // + VECTORMATH_FORCE_INLINE Matrix4( const Matrix3 & mat, const Vector3 &translateVec ); + + // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + // + VECTORMATH_FORCE_INLINE Matrix4( const Quat &unitQuat, const Vector3 &translateVec ); + + // Set all elements of a 4x4 matrix to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Matrix4( float scalar ); + + // Set all elements of a 4x4 matrix to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Matrix4( const floatInVec &scalar ); + + // Assign one 4x4 matrix to another + // + VECTORMATH_FORCE_INLINE Matrix4 & operator =( const Matrix4 & mat ); + + // Set the upper-left 3x3 submatrix + // NOTE: + // This function does not change the bottom row elements. + // + VECTORMATH_FORCE_INLINE Matrix4 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Matrix3 getUpper3x3( ) const; + + // Set translation component + // NOTE: + // This function does not change the bottom row elements. + // + VECTORMATH_FORCE_INLINE Matrix4 & setTranslation( const Vector3 &translateVec ); + + // Get the translation component of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getTranslation( ) const; + + // Set column 0 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & setCol0( const Vector4 &col0 ); + + // Set column 1 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & setCol1( const Vector4 &col1 ); + + // Set column 2 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & setCol2( const Vector4 &col2 ); + + // Set column 3 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & setCol3( const Vector4 &col3 ); + + // Get column 0 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Vector4 getCol0( ) const; + + // Get column 1 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Vector4 getCol1( ) const; + + // Get column 2 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Vector4 getCol2( ) const; + + // Get column 3 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Vector4 getCol3( ) const; + + // Set the column of a 4x4 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Matrix4 & setCol( int col, const Vector4 &vec ); + + // Set the row of a 4x4 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Matrix4 & setRow( int row, const Vector4 &vec ); + + // Get the column of a 4x4 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector4 getCol( int col ) const; + + // Get the row of a 4x4 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + VECTORMATH_FORCE_INLINE Vector4 & operator []( int col ); + + // Subscripting operator to get a column + // + VECTORMATH_FORCE_INLINE const Vector4 operator []( int col ) const; + + // Set the element of a 4x4 matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE Matrix4 & setElem( int col, int row, float val ); + + // Set the element of a 4x4 matrix referred to by column and row indices (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Matrix4 & setElem( int col, int row, const floatInVec &val ); + + // Get the element of a 4x4 matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int col, int row ) const; + + // Add two 4x4 matrices + // + VECTORMATH_FORCE_INLINE const Matrix4 operator +( const Matrix4 & mat ) const; + + // Subtract a 4x4 matrix from another 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Matrix4 operator -( const Matrix4 & mat ) const; + + // Negate all elements of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Matrix4 operator -( ) const; + + // Multiply a 4x4 matrix by a scalar + // + VECTORMATH_FORCE_INLINE const Matrix4 operator *( float scalar ) const; + + // Multiply a 4x4 matrix by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Matrix4 operator *( const floatInVec &scalar ) const; + + // Multiply a 4x4 matrix by a 4-D vector + // + VECTORMATH_FORCE_INLINE const Vector4 operator *( const Vector4 &vec ) const; + + // Multiply a 4x4 matrix by a 3-D vector + // + VECTORMATH_FORCE_INLINE const Vector4 operator *( const Vector3 &vec ) const; + + // Multiply a 4x4 matrix by a 3-D point + // + VECTORMATH_FORCE_INLINE const Vector4 operator *( const Point3 &pnt ) const; + + // Multiply two 4x4 matrices + // + VECTORMATH_FORCE_INLINE const Matrix4 operator *( const Matrix4 & mat ) const; + + // Multiply a 4x4 matrix by a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Matrix4 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and addition with a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & operator +=( const Matrix4 & mat ); + + // Perform compound assignment and subtraction by a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & operator -=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + VECTORMATH_FORCE_INLINE Matrix4 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Matrix4 & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and multiplication by a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & operator *=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 4x4 matrix + // + static VECTORMATH_FORCE_INLINE const Matrix4 identity( ); + + // Construct a 4x4 matrix to rotate around the x axis + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationX( float radians ); + + // Construct a 4x4 matrix to rotate around the y axis + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationY( float radians ); + + // Construct a 4x4 matrix to rotate around the z axis + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationZ( float radians ); + + // Construct a 4x4 matrix to rotate around the x axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationX( const floatInVec &radians ); + + // Construct a 4x4 matrix to rotate around the y axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationY( const floatInVec &radians ); + + // Construct a 4x4 matrix to rotate around the z axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationZ( const floatInVec &radians ); + + // Construct a 4x4 matrix to rotate around the x, y, and z axes + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationZYX( const Vector3 &radiansXYZ ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotation( float radians, const Vector3 &unitVec ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotation( const floatInVec &radians, const Vector3 &unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotation( const Quat &unitQuat ); + + // Construct a 4x4 matrix to perform scaling + // + static VECTORMATH_FORCE_INLINE const Matrix4 scale( const Vector3 &scaleVec ); + + // Construct a 4x4 matrix to perform translation + // + static VECTORMATH_FORCE_INLINE const Matrix4 translation( const Vector3 &translateVec ); + + // Construct viewing matrix based on eye, position looked at, and up direction + // + static VECTORMATH_FORCE_INLINE const Matrix4 lookAt( const Point3 &eyePos, const Point3 &lookAtPos, const Vector3 &upVec ); + + // Construct a perspective projection matrix + // + static VECTORMATH_FORCE_INLINE const Matrix4 perspective( float fovyRadians, float aspect, float zNear, float zFar ); + + // Construct a perspective projection matrix based on frustum + // + static VECTORMATH_FORCE_INLINE const Matrix4 frustum( float left, float right, float bottom, float top, float zNear, float zFar ); + + // Construct an orthographic projection matrix + // + static VECTORMATH_FORCE_INLINE const Matrix4 orthographic( float left, float right, float bottom, float top, float zNear, float zFar ); + +}; +// Multiply a 4x4 matrix by a scalar +// +VECTORMATH_FORCE_INLINE const Matrix4 operator *( float scalar, const Matrix4 & mat ); + +// Multiply a 4x4 matrix by a scalar (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Matrix4 operator *( const floatInVec &scalar, const Matrix4 & mat ); + +// Append (post-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Matrix4 appendScale( const Matrix4 & mat, const Vector3 &scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Matrix4 prependScale( const Vector3 &scaleVec, const Matrix4 & mat ); + +// Multiply two 4x4 matrices per element +// +VECTORMATH_FORCE_INLINE const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); + +// Compute the absolute value of a 4x4 matrix per element +// +VECTORMATH_FORCE_INLINE const Matrix4 absPerElem( const Matrix4 & mat ); + +// Transpose of a 4x4 matrix +// +VECTORMATH_FORCE_INLINE const Matrix4 transpose( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +VECTORMATH_FORCE_INLINE const Matrix4 inverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. +// +VECTORMATH_FORCE_INLINE const Matrix4 affineInverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. +// +VECTORMATH_FORCE_INLINE const Matrix4 orthoInverse( const Matrix4 & mat ); + +// Determinant of a 4x4 matrix +// +VECTORMATH_FORCE_INLINE const floatInVec determinant( const Matrix4 & mat ); + +// Conditionally select between two 4x4 matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ); + +// Conditionally select between two 4x4 matrices (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, const boolInVec &select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4x4 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Matrix4 & mat ); + +// Print a 4x4 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Matrix4 & mat, const char * name ); + +#endif + +// A 3x4 transformation matrix in array-of-structures format +// +class Transform3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + Vector3 mCol3; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Transform3( ) { }; + + // Copy a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3( const Transform3 & tfrm ); + + // Construct a 3x4 transformation matrix containing the specified columns + // + VECTORMATH_FORCE_INLINE Transform3( const Vector3 &col0, const Vector3 &col1, const Vector3 &col2, const Vector3 &col3 ); + + // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + // + VECTORMATH_FORCE_INLINE Transform3( const Matrix3 & tfrm, const Vector3 &translateVec ); + + // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + // + VECTORMATH_FORCE_INLINE Transform3( const Quat &unitQuat, const Vector3 &translateVec ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Transform3( float scalar ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Transform3( const floatInVec &scalar ); + + // Assign one 3x4 transformation matrix to another + // + VECTORMATH_FORCE_INLINE Transform3 & operator =( const Transform3 & tfrm ); + + // Set the upper-left 3x3 submatrix + // + VECTORMATH_FORCE_INLINE Transform3 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Matrix3 getUpper3x3( ) const; + + // Set translation component + // + VECTORMATH_FORCE_INLINE Transform3 & setTranslation( const Vector3 &translateVec ); + + // Get the translation component of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getTranslation( ) const; + + // Set column 0 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3 & setCol0( const Vector3 &col0 ); + + // Set column 1 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3 & setCol1( const Vector3 &col1 ); + + // Set column 2 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3 & setCol2( const Vector3 &col2 ); + + // Set column 3 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3 & setCol3( const Vector3 &col3 ); + + // Get column 0 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol0( ) const; + + // Get column 1 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol1( ) const; + + // Get column 2 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol2( ) const; + + // Get column 3 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol3( ) const; + + // Set the column of a 3x4 transformation matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Transform3 & setCol( int col, const Vector3 &vec ); + + // Set the row of a 3x4 transformation matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Transform3 & setRow( int row, const Vector4 &vec ); + + // Get the column of a 3x4 transformation matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector3 getCol( int col ) const; + + // Get the row of a 3x4 transformation matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + VECTORMATH_FORCE_INLINE Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + VECTORMATH_FORCE_INLINE const Vector3 operator []( int col ) const; + + // Set the element of a 3x4 transformation matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE Transform3 & setElem( int col, int row, float val ); + + // Set the element of a 3x4 transformation matrix referred to by column and row indices (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Transform3 & setElem( int col, int row, const floatInVec &val ); + + // Get the element of a 3x4 transformation matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int col, int row ) const; + + // Multiply a 3x4 transformation matrix by a 3-D vector + // + VECTORMATH_FORCE_INLINE const Vector3 operator *( const Vector3 &vec ) const; + + // Multiply a 3x4 transformation matrix by a 3-D point + // + VECTORMATH_FORCE_INLINE const Point3 operator *( const Point3 &pnt ) const; + + // Multiply two 3x4 transformation matrices + // + VECTORMATH_FORCE_INLINE const Transform3 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 3x4 transformation matrix + // + static VECTORMATH_FORCE_INLINE const Transform3 identity( ); + + // Construct a 3x4 transformation matrix to rotate around the x axis + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationX( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationY( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationZ( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the x axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationX( const floatInVec &radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationY( const floatInVec &radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationZ( const floatInVec &radians ); + + // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationZYX( const Vector3 &radiansXYZ ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + // + static VECTORMATH_FORCE_INLINE const Transform3 rotation( float radians, const Vector3 &unitVec ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Transform3 rotation( const floatInVec &radians, const Vector3 &unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static VECTORMATH_FORCE_INLINE const Transform3 rotation( const Quat &unitQuat ); + + // Construct a 3x4 transformation matrix to perform scaling + // + static VECTORMATH_FORCE_INLINE const Transform3 scale( const Vector3 &scaleVec ); + + // Construct a 3x4 transformation matrix to perform translation + // + static VECTORMATH_FORCE_INLINE const Transform3 translation( const Vector3 &translateVec ); + +}; +// Append (post-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Transform3 appendScale( const Transform3 & tfrm, const Vector3 &scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Transform3 prependScale( const Vector3 &scaleVec, const Transform3 & tfrm ); + +// Multiply two 3x4 transformation matrices per element +// +VECTORMATH_FORCE_INLINE const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); + +// Compute the absolute value of a 3x4 transformation matrix per element +// +VECTORMATH_FORCE_INLINE const Transform3 absPerElem( const Transform3 & tfrm ); + +// Inverse of a 3x4 transformation matrix +// NOTE: +// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. +// +VECTORMATH_FORCE_INLINE const Transform3 inverse( const Transform3 & tfrm ); + +// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. +// +VECTORMATH_FORCE_INLINE const Transform3 orthoInverse( const Transform3 & tfrm ); + +// Conditionally select between two 3x4 transformation matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ); + +// Conditionally select between two 3x4 transformation matrices (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, const boolInVec &select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x4 transformation matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Transform3 & tfrm ); + +// Print a 3x4 transformation matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Transform3 & tfrm, const char * name ); + +#endif + +} // namespace Aos +} // namespace Vectormath + +#include "vec_aos.h" +#include "quat_aos.h" +#include "mat_aos.h" + +#endif diff --git a/Extras/PhysicsEffects/include/vecmath/std/boolInVec.h b/Extras/PhysicsEffects/include/vecmath/std/boolInVec.h new file mode 100644 index 0000000..7ea380f --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/std/boolInVec.h @@ -0,0 +1,238 @@ +/* + Copyright (C) 2006-2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _BOOLINVEC_SCALAR_H +#define _BOOLINVEC_SCALAR_H + +#include +namespace Vectormath { + +class floatInVec; + +//-------------------------------------------------------------------------------------------------- +// boolInVec class +// + +class boolInVec +{ +private: + unsigned int mData; + +public: + // Default constructor; does no initialization + // + inline boolInVec( ) { }; + + // Construct from a value converted from float + // + inline boolInVec(floatInVec vec); + + // Explicit cast from bool + // + explicit inline boolInVec(bool scalar); + + // Explicit cast to bool + // + inline bool getAsBool() const; + +#ifndef _VECTORMATH_NO_SCALAR_CAST + // Implicit cast to bool + // + inline operator bool() const; +#endif + + // Boolean negation operator + // + inline const boolInVec operator ! () const; + + // Assignment operator + // + inline boolInVec& operator = (boolInVec vec); + + // Boolean and assignment operator + // + inline boolInVec& operator &= (boolInVec vec); + + // Boolean exclusive or assignment operator + // + inline boolInVec& operator ^= (boolInVec vec); + + // Boolean or assignment operator + // + inline boolInVec& operator |= (boolInVec vec); + +}; + +// Equal operator +// +inline const boolInVec operator == (boolInVec vec0, boolInVec vec1); + +// Not equal operator +// +inline const boolInVec operator != (boolInVec vec0, boolInVec vec1); + +// And operator +// +inline const boolInVec operator & (boolInVec vec0, boolInVec vec1); + +// Exclusive or operator +// +inline const boolInVec operator ^ (boolInVec vec0, boolInVec vec1); + +// Or operator +// +inline const boolInVec operator | (boolInVec vec0, boolInVec vec1); + +// Conditionally select between two values +// +inline const boolInVec select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1); + + +} // namespace Vectormath + + +//-------------------------------------------------------------------------------------------------- +// boolInVec implementation +// + +#include "floatInVec.h" + +namespace Vectormath { + +inline +boolInVec::boolInVec(floatInVec vec) +{ + *this = (vec != floatInVec(0.0f)); +} + +inline +boolInVec::boolInVec(bool scalar) +{ + mData = -(int)scalar; +} + +inline +bool +boolInVec::getAsBool() const +{ + return (mData > 0); +} + +#ifndef _VECTORMATH_NO_SCALAR_CAST +inline +boolInVec::operator bool() const +{ + return getAsBool(); +} +#endif + +inline +const boolInVec +boolInVec::operator ! () const +{ + return boolInVec(!mData); +} + +inline +boolInVec& +boolInVec::operator = (boolInVec vec) +{ + mData = vec.mData; + return *this; +} + +inline +boolInVec& +boolInVec::operator &= (boolInVec vec) +{ + *this = *this & vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator ^= (boolInVec vec) +{ + *this = *this ^ vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator |= (boolInVec vec) +{ + *this = *this | vec; + return *this; +} + +inline +const boolInVec +operator == (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() == vec1.getAsBool()); +} + +inline +const boolInVec +operator != (boolInVec vec0, boolInVec vec1) +{ + return !(vec0 == vec1); +} + +inline +const boolInVec +operator & (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() & vec1.getAsBool()); +} + +inline +const boolInVec +operator | (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() | vec1.getAsBool()); +} + +inline +const boolInVec +operator ^ (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() ^ vec1.getAsBool()); +} + +inline +const boolInVec +select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1) +{ + return (select_vec1.getAsBool() == 0) ? vec0 : vec1; +} + +} // namespace Vectormath + +#endif // boolInVec_h diff --git a/Extras/PhysicsEffects/include/vecmath/std/floatInVec.h b/Extras/PhysicsEffects/include/vecmath/std/floatInVec.h new file mode 100644 index 0000000..1aa2ee1 --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/std/floatInVec.h @@ -0,0 +1,357 @@ +/* + Copyright (C) 2006-2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _FLOATINVEC__SCALAR_H +#define _FLOATINVEC__SCALAR_H + +#include +namespace Vectormath { + +class boolInVec; + +//-------------------------------------------------------------------------------------------------- +// floatInVec class +// + +// A class representing a scalar float value contained in a vector register +// This class does not support fastmath +class floatInVec +{ +private: + float mData; + +public: + // Default constructor; does no initialization + // + inline floatInVec( ) { }; + + // Construct from a value converted from bool + // + inline floatInVec(boolInVec vec); + + // Explicit cast from float + // + explicit inline floatInVec(float scalar); + + // Explicit cast to float + // + inline float getAsFloat() const; + +#ifndef _VECTORMATH_NO_SCALAR_CAST + // Implicit cast to float + // + inline operator float() const; +#endif + + // Post increment (add 1.0f) + // + inline const floatInVec operator ++ (int); + + // Post decrement (subtract 1.0f) + // + inline const floatInVec operator -- (int); + + // Pre increment (add 1.0f) + // + inline floatInVec& operator ++ (); + + // Pre decrement (subtract 1.0f) + // + inline floatInVec& operator -- (); + + // Negation operator + // + inline const floatInVec operator - () const; + + // Assignment operator + // + inline floatInVec& operator = (floatInVec vec); + + // Multiplication assignment operator + // + inline floatInVec& operator *= (floatInVec vec); + + // Division assignment operator + // + inline floatInVec& operator /= (floatInVec vec); + + // Addition assignment operator + // + inline floatInVec& operator += (floatInVec vec); + + // Subtraction assignment operator + // + inline floatInVec& operator -= (floatInVec vec); + +}; + +// Multiplication operator +// +inline const floatInVec operator * (floatInVec vec0, floatInVec vec1); + +// Division operator +// +inline const floatInVec operator / (floatInVec vec0, floatInVec vec1); + +// Addition operator +// +inline const floatInVec operator + (floatInVec vec0, floatInVec vec1); + +// Subtraction operator +// +inline const floatInVec operator - (floatInVec vec0, floatInVec vec1); + +// Less than operator +// +inline const boolInVec operator < (floatInVec vec0, floatInVec vec1); + +// Less than or equal operator +// +inline const boolInVec operator <= (floatInVec vec0, floatInVec vec1); + +// Greater than operator +// +inline const boolInVec operator > (floatInVec vec0, floatInVec vec1); + +// Greater than or equal operator +// +inline const boolInVec operator >= (floatInVec vec0, floatInVec vec1); + +// Equal operator +// +inline const boolInVec operator == (floatInVec vec0, floatInVec vec1); + +// Not equal operator +// +inline const boolInVec operator != (floatInVec vec0, floatInVec vec1); + +// Conditionally select between two values +// +inline const floatInVec select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1); + + +} // namespace Vectormath + + +//-------------------------------------------------------------------------------------------------- +// floatInVec implementation +// + +#include "boolInVec.h" + +namespace Vectormath { + +inline +floatInVec::floatInVec(boolInVec vec) +{ + mData = float(vec.getAsBool()); +} + +inline +floatInVec::floatInVec(float scalar) +{ + mData = scalar; +} + +inline +float +floatInVec::getAsFloat() const +{ + return mData; +} + +#ifndef _VECTORMATH_NO_SCALAR_CAST +inline +floatInVec::operator float() const +{ + return getAsFloat(); +} +#endif + +inline +const floatInVec +floatInVec::operator ++ (int) +{ + float olddata = mData; + operator ++(); + return floatInVec(olddata); +} + +inline +const floatInVec +floatInVec::operator -- (int) +{ + float olddata = mData; + operator --(); + return floatInVec(olddata); +} + +inline +floatInVec& +floatInVec::operator ++ () +{ + *this += floatInVec(1.0f); + return *this; +} + +inline +floatInVec& +floatInVec::operator -- () +{ + *this -= floatInVec(1.0f); + return *this; +} + +inline +const floatInVec +floatInVec::operator - () const +{ + return floatInVec(-mData); +} + +inline +floatInVec& +floatInVec::operator = (floatInVec vec) +{ + mData = vec.mData; + return *this; +} + +inline +floatInVec& +floatInVec::operator *= (floatInVec vec) +{ + *this = *this * vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator /= (floatInVec vec) +{ + *this = *this / vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator += (floatInVec vec) +{ + *this = *this + vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator -= (floatInVec vec) +{ + *this = *this - vec; + return *this; +} + +inline +const floatInVec +operator * (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() * vec1.getAsFloat()); +} + +inline +const floatInVec +operator / (floatInVec num, floatInVec den) +{ + return floatInVec(num.getAsFloat() / den.getAsFloat()); +} + +inline +const floatInVec +operator + (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() + vec1.getAsFloat()); +} + +inline +const floatInVec +operator - (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() - vec1.getAsFloat()); +} + +inline +const boolInVec +operator < (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() < vec1.getAsFloat()); +} + +inline +const boolInVec +operator <= (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 > vec1); +} + +inline +const boolInVec +operator > (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() > vec1.getAsFloat()); +} + +inline +const boolInVec +operator >= (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 < vec1); +} + +inline +const boolInVec +operator == (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() == vec1.getAsFloat()); +} + +inline +const boolInVec +operator != (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 == vec1); +} + +inline +const floatInVec +select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1) +{ + return (select_vec1.getAsBool() == 0) ? vec0 : vec1; +} + +} // namespace Vectormath + +#endif // floatInVec_h diff --git a/Extras/PhysicsEffects/include/vecmath/std/mat_aos.h b/Extras/PhysicsEffects/include/vecmath/std/mat_aos.h new file mode 100644 index 0000000..3a6d484 --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/std/mat_aos.h @@ -0,0 +1,1643 @@ +/* + Copyright (C) 2006-2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_AOS_CPP__SCALAR_H +#define _VECTORMATH_MAT_AOS_CPP__SCALAR_H + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// Constants + +#define _VECTORMATH_PI_OVER_2 1.570796327f + +//----------------------------------------------------------------------------- +// Definitions + +inline Matrix3::Matrix3( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; +} + +inline Matrix3::Matrix3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +inline Matrix3::Matrix3( const Quat & unitQuat ) +{ + float qx, qy, qz, qw, qx2, qy2, qz2, qxqx2, qyqy2, qzqz2, qxqy2, qyqz2, qzqw2, qxqz2, qyqw2, qxqw2; + qx = unitQuat.getX(); + qy = unitQuat.getY(); + qz = unitQuat.getZ(); + qw = unitQuat.getW(); + qx2 = ( qx + qx ); + qy2 = ( qy + qy ); + qz2 = ( qz + qz ); + qxqx2 = ( qx * qx2 ); + qxqy2 = ( qx * qy2 ); + qxqz2 = ( qx * qz2 ); + qxqw2 = ( qw * qx2 ); + qyqy2 = ( qy * qy2 ); + qyqz2 = ( qy * qz2 ); + qyqw2 = ( qw * qy2 ); + qzqz2 = ( qz * qz2 ); + qzqw2 = ( qw * qz2 ); + mCol0 = Vector3( ( ( 1.0f - qyqy2 ) - qzqz2 ), ( qxqy2 + qzqw2 ), ( qxqz2 - qyqw2 ) ); + mCol1 = Vector3( ( qxqy2 - qzqw2 ), ( ( 1.0f - qxqx2 ) - qzqz2 ), ( qyqz2 + qxqw2 ) ); + mCol2 = Vector3( ( qxqz2 + qyqw2 ), ( qyqz2 - qxqw2 ), ( ( 1.0f - qxqx2 ) - qyqy2 ) ); +} + +inline Matrix3::Matrix3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; +} + +inline Matrix3 & Matrix3::setCol0( const Vector3 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix3 & Matrix3::setCol1( const Vector3 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix3 & Matrix3::setCol2( const Vector3 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix3 & Matrix3::setCol( int col, const Vector3 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix3 & Matrix3::setRow( int row, const Vector3 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + return *this; +} + +inline Matrix3 & Matrix3::setElem( int col, int row, float val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Matrix3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Matrix3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Matrix3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Matrix3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Matrix3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::getRow( int row ) const +{ + return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); +} + +inline Vector3 & Matrix3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix3 & Matrix3::operator =( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + return *this; +} + +inline const Matrix3 transpose( const Matrix3 & mat ) +{ + return Matrix3( + Vector3( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX() ), + Vector3( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY() ), + Vector3( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ() ) + ); +} + +inline const Matrix3 inverse( const Matrix3 & mat ) +{ + Vector3 tmp0, tmp1, tmp2; + float detinv; + tmp0 = cross( mat.getCol1(), mat.getCol2() ); + tmp1 = cross( mat.getCol2(), mat.getCol0() ); + tmp2 = cross( mat.getCol0(), mat.getCol1() ); + detinv = ( 1.0f / dot( mat.getCol2(), tmp2 ) ); + return Matrix3( + Vector3( ( tmp0.getX() * detinv ), ( tmp1.getX() * detinv ), ( tmp2.getX() * detinv ) ), + Vector3( ( tmp0.getY() * detinv ), ( tmp1.getY() * detinv ), ( tmp2.getY() * detinv ) ), + Vector3( ( tmp0.getZ() * detinv ), ( tmp1.getZ() * detinv ), ( tmp2.getZ() * detinv ) ) + ); +} + +inline float determinant( const Matrix3 & mat ) +{ + return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); +} + +inline const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ) + ); +} + +inline const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix3 Matrix3::operator -( ) const +{ + return Matrix3( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ) + ); +} + +inline const Matrix3 absPerElem( const Matrix3 & mat ) +{ + return Matrix3( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::operator *( float scalar ) const +{ + return Matrix3( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ) + ); +} + +inline Matrix3 & Matrix3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix3 operator *( float scalar, const Matrix3 & mat ) +{ + return mat * scalar; +} + +inline const Vector3 Matrix3::operator *( const Vector3 & vec ) const +{ + return Vector3( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ); +} + +inline const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const +{ + return Matrix3( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) +{ + return Matrix3( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::identity( ) +{ + return Matrix3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3::xAxis( ), + Vector3( 0.0f, c, s ), + Vector3( 0.0f, -s, c ) + ); +} + +inline const Matrix3 Matrix3::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3( c, 0.0f, -s ), + Vector3::yAxis( ), + Vector3( s, 0.0f, c ) + ); +} + +inline const Matrix3 Matrix3::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3( c, s, 0.0f ), + Vector3( -s, c, 0.0f ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Matrix3( + Vector3( ( cZ * cY ), ( sZ * cY ), -sY ), + Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ), + Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( float radians, const Vector3 & unitVec ) +{ + float x, y, z, s, c, oneMinusC, xy, yz, zx; + s = sinf( radians ); + c = cosf( radians ); + x = unitVec.getX(); + y = unitVec.getY(); + z = unitVec.getZ(); + xy = ( x * y ); + yz = ( y * z ); + zx = ( z * x ); + oneMinusC = ( 1.0f - c ); + return Matrix3( + Vector3( ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ) ), + Vector3( ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ) ), + Vector3( ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( const Quat & unitQuat ) +{ + return Matrix3( unitQuat ); +} + +inline const Matrix3 Matrix3::scale( const Vector3 & scaleVec ) +{ + return Matrix3( + Vector3( scaleVec.getX(), 0.0f, 0.0f ), + Vector3( 0.0f, scaleVec.getY(), 0.0f ), + Vector3( 0.0f, 0.0f, scaleVec.getZ() ) + ); +} + +inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ) +{ + return Matrix3( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ) + ); +} + +inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ) +{ + return Matrix3( + mulPerElem( mat.getCol0(), scaleVec ), + mulPerElem( mat.getCol1(), scaleVec ), + mulPerElem( mat.getCol2(), scaleVec ) + ); +} + +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix3 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); +} + +inline void print( const Matrix3 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Matrix4::Matrix4( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; +} + +inline Matrix4::Matrix4( float scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +inline Matrix4::Matrix4( const Transform3 & mat ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( mat.getCol3(), 1.0f ); +} + +inline Matrix4::Matrix4( const Vector4 & _col0, const Vector4 & _col1, const Vector4 & _col2, const Vector4 & _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Matrix4::Matrix4( const Matrix3 & mat, const Vector3 & translateVec ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +inline Matrix4::Matrix4( const Quat & unitQuat, const Vector3 & translateVec ) +{ + Matrix3 mat; + mat = Matrix3( unitQuat ); + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +inline Matrix4 & Matrix4::setCol0( const Vector4 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix4 & Matrix4::setCol1( const Vector4 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix4 & Matrix4::setCol2( const Vector4 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix4 & Matrix4::setCol3( const Vector4 & _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Matrix4 & Matrix4::setCol( int col, const Vector4 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix4 & Matrix4::setRow( int row, const Vector4 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Matrix4 & Matrix4::setElem( int col, int row, float val ) +{ + Vector4 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Matrix4::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector4 Matrix4::getCol0( ) const +{ + return mCol0; +} + +inline const Vector4 Matrix4::getCol1( ) const +{ + return mCol1; +} + +inline const Vector4 Matrix4::getCol2( ) const +{ + return mCol2; +} + +inline const Vector4 Matrix4::getCol3( ) const +{ + return mCol3; +} + +inline const Vector4 Matrix4::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector4 & Matrix4::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix4 & Matrix4::operator =( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; + return *this; +} + +inline const Matrix4 transpose( const Matrix4 & mat ) +{ + return Matrix4( + Vector4( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX(), mat.getCol3().getX() ), + Vector4( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY(), mat.getCol3().getY() ), + Vector4( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ(), mat.getCol3().getZ() ), + Vector4( mat.getCol0().getW(), mat.getCol1().getW(), mat.getCol2().getW(), mat.getCol3().getW() ) + ); +} + +inline const Matrix4 inverse( const Matrix4 & mat ) +{ + Vector4 res0, res1, res2, res3; + float mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, detInv; + mA = mat.getCol0().getX(); + mB = mat.getCol0().getY(); + mC = mat.getCol0().getZ(); + mD = mat.getCol0().getW(); + mE = mat.getCol1().getX(); + mF = mat.getCol1().getY(); + mG = mat.getCol1().getZ(); + mH = mat.getCol1().getW(); + mI = mat.getCol2().getX(); + mJ = mat.getCol2().getY(); + mK = mat.getCol2().getZ(); + mL = mat.getCol2().getW(); + mM = mat.getCol3().getX(); + mN = mat.getCol3().getY(); + mO = mat.getCol3().getZ(); + mP = mat.getCol3().getW(); + tmp0 = ( ( mK * mD ) - ( mC * mL ) ); + tmp1 = ( ( mO * mH ) - ( mG * mP ) ); + tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); + tmp3 = ( ( mF * mO ) - ( mN * mG ) ); + tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); + tmp5 = ( ( mN * mH ) - ( mF * mP ) ); + res0.setX( ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ) ); + res0.setY( ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ) ); + res0.setZ( ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ) ); + res0.setW( ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ) ); + detInv = ( 1.0f / ( ( ( ( mA * res0.getX() ) + ( mE * res0.getY() ) ) + ( mI * res0.getZ() ) ) + ( mM * res0.getW() ) ) ); + res1.setX( ( mI * tmp1 ) ); + res1.setY( ( mM * tmp0 ) ); + res1.setZ( ( mA * tmp1 ) ); + res1.setW( ( mE * tmp0 ) ); + res3.setX( ( mI * tmp3 ) ); + res3.setY( ( mM * tmp2 ) ); + res3.setZ( ( mA * tmp3 ) ); + res3.setW( ( mE * tmp2 ) ); + res2.setX( ( mI * tmp5 ) ); + res2.setY( ( mM * tmp4 ) ); + res2.setZ( ( mA * tmp5 ) ); + res2.setW( ( mE * tmp4 ) ); + tmp0 = ( ( mI * mB ) - ( mA * mJ ) ); + tmp1 = ( ( mM * mF ) - ( mE * mN ) ); + tmp2 = ( ( mI * mD ) - ( mA * mL ) ); + tmp3 = ( ( mM * mH ) - ( mE * mP ) ); + tmp4 = ( ( mI * mC ) - ( mA * mK ) ); + tmp5 = ( ( mM * mG ) - ( mE * mO ) ); + res2.setX( ( ( ( mL * tmp1 ) - ( mJ * tmp3 ) ) + res2.getX() ) ); + res2.setY( ( ( ( mP * tmp0 ) - ( mN * tmp2 ) ) + res2.getY() ) ); + res2.setZ( ( ( ( mB * tmp3 ) - ( mD * tmp1 ) ) - res2.getZ() ) ); + res2.setW( ( ( ( mF * tmp2 ) - ( mH * tmp0 ) ) - res2.getW() ) ); + res3.setX( ( ( ( mJ * tmp5 ) - ( mK * tmp1 ) ) + res3.getX() ) ); + res3.setY( ( ( ( mN * tmp4 ) - ( mO * tmp0 ) ) + res3.getY() ) ); + res3.setZ( ( ( ( mC * tmp1 ) - ( mB * tmp5 ) ) - res3.getZ() ) ); + res3.setW( ( ( ( mG * tmp0 ) - ( mF * tmp4 ) ) - res3.getW() ) ); + res1.setX( ( ( ( mK * tmp3 ) - ( mL * tmp5 ) ) - res1.getX() ) ); + res1.setY( ( ( ( mO * tmp2 ) - ( mP * tmp4 ) ) - res1.getY() ) ); + res1.setZ( ( ( ( mD * tmp5 ) - ( mC * tmp3 ) ) + res1.getZ() ) ); + res1.setW( ( ( ( mH * tmp4 ) - ( mG * tmp2 ) ) + res1.getW() ) ); + return Matrix4( + ( res0 * detInv ), + ( res1 * detInv ), + ( res2 * detInv ), + ( res3 * detInv ) + ); +} + +inline const Matrix4 affineInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( inverse( affineMat ) ); +} + +inline const Matrix4 orthoInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( orthoInverse( affineMat ) ); +} + +inline float determinant( const Matrix4 & mat ) +{ + float dx, dy, dz, dw, mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + mA = mat.getCol0().getX(); + mB = mat.getCol0().getY(); + mC = mat.getCol0().getZ(); + mD = mat.getCol0().getW(); + mE = mat.getCol1().getX(); + mF = mat.getCol1().getY(); + mG = mat.getCol1().getZ(); + mH = mat.getCol1().getW(); + mI = mat.getCol2().getX(); + mJ = mat.getCol2().getY(); + mK = mat.getCol2().getZ(); + mL = mat.getCol2().getW(); + mM = mat.getCol3().getX(); + mN = mat.getCol3().getY(); + mO = mat.getCol3().getZ(); + mP = mat.getCol3().getW(); + tmp0 = ( ( mK * mD ) - ( mC * mL ) ); + tmp1 = ( ( mO * mH ) - ( mG * mP ) ); + tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); + tmp3 = ( ( mF * mO ) - ( mN * mG ) ); + tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); + tmp5 = ( ( mN * mH ) - ( mF * mP ) ); + dx = ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ); + dy = ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ); + dz = ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ); + dw = ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ); + return ( ( ( ( mA * dx ) + ( mE * dy ) ) + ( mI * dz ) ) + ( mM * dw ) ); +} + +inline const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ), + ( mCol3 + mat.mCol3 ) + ); +} + +inline const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ), + ( mCol3 - mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix4 Matrix4::operator -( ) const +{ + return Matrix4( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ), + ( -mCol3 ) + ); +} + +inline const Matrix4 absPerElem( const Matrix4 & mat ) +{ + return Matrix4( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ), + absPerElem( mat.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::operator *( float scalar ) const +{ + return Matrix4( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ), + ( mCol3 * scalar ) + ); +} + +inline Matrix4 & Matrix4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix4 operator *( float scalar, const Matrix4 & mat ) +{ + return mat * scalar; +} + +inline const Vector4 Matrix4::operator *( const Vector4 & vec ) const +{ + return Vector4( + ( ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ) + ( mCol3.getX() * vec.getW() ) ), + ( ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ) + ( mCol3.getY() * vec.getW() ) ), + ( ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ( mCol3.getZ() * vec.getW() ) ), + ( ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) + ( mCol3.getW() * vec.getW() ) ) + ); +} + +inline const Vector4 Matrix4::operator *( const Vector3 & vec ) const +{ + return Vector4( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ), + ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) + ); +} + +inline const Vector4 Matrix4::operator *( const Point3 & pnt ) const +{ + return Vector4( + ( ( ( ( mCol0.getX() * pnt.getX() ) + ( mCol1.getX() * pnt.getY() ) ) + ( mCol2.getX() * pnt.getZ() ) ) + mCol3.getX() ), + ( ( ( ( mCol0.getY() * pnt.getX() ) + ( mCol1.getY() * pnt.getY() ) ) + ( mCol2.getY() * pnt.getZ() ) ) + mCol3.getY() ), + ( ( ( ( mCol0.getZ() * pnt.getX() ) + ( mCol1.getZ() * pnt.getY() ) ) + ( mCol2.getZ() * pnt.getZ() ) ) + mCol3.getZ() ), + ( ( ( ( mCol0.getW() * pnt.getX() ) + ( mCol1.getW() * pnt.getY() ) ) + ( mCol2.getW() * pnt.getZ() ) ) + mCol3.getW() ) + ); +} + +inline const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const +{ + return Matrix4( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ), + ( *this * mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const +{ + return Matrix4( + ( *this * tfrm.getCol0() ), + ( *this * tfrm.getCol1() ), + ( *this * tfrm.getCol2() ), + ( *this * Point3( tfrm.getCol3() ) ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) +{ + return Matrix4( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ), + mulPerElem( mat0.getCol3(), mat1.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::identity( ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) +{ + mCol0.setXYZ( mat3.getCol0() ); + mCol1.setXYZ( mat3.getCol1() ); + mCol2.setXYZ( mat3.getCol2() ); + return *this; +} + +inline const Matrix3 Matrix4::getUpper3x3( ) const +{ + return Matrix3( + mCol0.getXYZ( ), + mCol1.getXYZ( ), + mCol2.getXYZ( ) + ); +} + +inline Matrix4 & Matrix4::setTranslation( const Vector3 & translateVec ) +{ + mCol3.setXYZ( translateVec ); + return *this; +} + +inline const Vector3 Matrix4::getTranslation( ) const +{ + return mCol3.getXYZ( ); +} + +inline const Matrix4 Matrix4::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4::xAxis( ), + Vector4( 0.0f, c, s, 0.0f ), + Vector4( 0.0f, -s, c, 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4( c, 0.0f, -s, 0.0f ), + Vector4::yAxis( ), + Vector4( s, 0.0f, c, 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4( c, s, 0.0f, 0.0f ), + Vector4( -s, c, 0.0f, 0.0f ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Matrix4( + Vector4( ( cZ * cY ), ( sZ * cY ), -sY, 0.0f ), + Vector4( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ), 0.0f ), + Vector4( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( float radians, const Vector3 & unitVec ) +{ + float x, y, z, s, c, oneMinusC, xy, yz, zx; + s = sinf( radians ); + c = cosf( radians ); + x = unitVec.getX(); + y = unitVec.getY(); + z = unitVec.getZ(); + xy = ( x * y ); + yz = ( y * z ); + zx = ( z * x ); + oneMinusC = ( 1.0f - c ); + return Matrix4( + Vector4( ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ), 0.0f ), + Vector4( ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ), 0.0f ), + Vector4( ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( const Quat & unitQuat ) +{ + return Matrix4( Transform3::rotation( unitQuat ) ); +} + +inline const Matrix4 Matrix4::scale( const Vector3 & scaleVec ) +{ + return Matrix4( + Vector4( scaleVec.getX(), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, scaleVec.getY(), 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, scaleVec.getZ(), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ) +{ + return Matrix4( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ), + mat.getCol3() + ); +} + +inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ) +{ + Vector4 scale4; + scale4 = Vector4( scaleVec, 1.0f ); + return Matrix4( + mulPerElem( mat.getCol0(), scale4 ), + mulPerElem( mat.getCol1(), scale4 ), + mulPerElem( mat.getCol2(), scale4 ), + mulPerElem( mat.getCol3(), scale4 ) + ); +} + +inline const Matrix4 Matrix4::translation( const Vector3 & translateVec ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4( translateVec, 1.0f ) + ); +} + +inline const Matrix4 Matrix4::lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ) +{ + Matrix4 m4EyeFrame; + Vector3 v3X, v3Y, v3Z; + v3Y = normalize( upVec ); + v3Z = normalize( ( eyePos - lookAtPos ) ); + v3X = normalize( cross( v3Y, v3Z ) ); + v3Y = cross( v3Z, v3X ); + m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); + return orthoInverse( m4EyeFrame ); +} + +inline const Matrix4 Matrix4::perspective( float fovyRadians, float aspect, float zNear, float zFar ) +{ + float f, rangeInv; + f = tanf( ( (float)( _VECTORMATH_PI_OVER_2 ) - ( 0.5f * fovyRadians ) ) ); + rangeInv = ( 1.0f / ( zNear - zFar ) ); + return Matrix4( + Vector4( ( f / aspect ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, f, 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, ( ( zNear + zFar ) * rangeInv ), -1.0f ), + Vector4( 0.0f, 0.0f, ( ( ( zNear * zFar ) * rangeInv ) * 2.0f ), 0.0f ) + ); +} + +inline const Matrix4 Matrix4::frustum( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf, n2; + sum_rl = ( right + left ); + sum_tb = ( top + bottom ); + sum_nf = ( zNear + zFar ); + inv_rl = ( 1.0f / ( right - left ) ); + inv_tb = ( 1.0f / ( top - bottom ) ); + inv_nf = ( 1.0f / ( zNear - zFar ) ); + n2 = ( zNear + zNear ); + return Matrix4( + Vector4( ( n2 * inv_rl ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, ( n2 * inv_tb ), 0.0f, 0.0f ), + Vector4( ( sum_rl * inv_rl ), ( sum_tb * inv_tb ), ( sum_nf * inv_nf ), -1.0f ), + Vector4( 0.0f, 0.0f, ( ( n2 * inv_nf ) * zFar ), 0.0f ) + ); +} + +inline const Matrix4 Matrix4::orthographic( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf; + sum_rl = ( right + left ); + sum_tb = ( top + bottom ); + sum_nf = ( zNear + zFar ); + inv_rl = ( 1.0f / ( right - left ) ); + inv_tb = ( 1.0f / ( top - bottom ) ); + inv_nf = ( 1.0f / ( zNear - zFar ) ); + return Matrix4( + Vector4( ( inv_rl + inv_rl ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, ( inv_tb + inv_tb ), 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, ( inv_nf + inv_nf ), 0.0f ), + Vector4( ( -sum_rl * inv_rl ), ( -sum_tb * inv_tb ), ( sum_nf * inv_nf ), 1.0f ) + ); +} + +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix4 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); + print( mat.getRow( 3 ) ); +} + +inline void print( const Matrix4 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Transform3::Transform3( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; +} + +inline Transform3::Transform3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +inline Transform3::Transform3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2, const Vector3 & _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Transform3::Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ) +{ + this->setUpper3x3( tfrm ); + this->setTranslation( translateVec ); +} + +inline Transform3::Transform3( const Quat & unitQuat, const Vector3 & translateVec ) +{ + this->setUpper3x3( Matrix3( unitQuat ) ); + this->setTranslation( translateVec ); +} + +inline Transform3 & Transform3::setCol0( const Vector3 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Transform3 & Transform3::setCol1( const Vector3 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Transform3 & Transform3::setCol2( const Vector3 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Transform3 & Transform3::setCol3( const Vector3 & _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Transform3 & Transform3::setCol( int col, const Vector3 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Transform3 & Transform3::setRow( int row, const Vector4 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Transform3 & Transform3::setElem( int col, int row, float val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Transform3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Transform3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Transform3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Transform3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Transform3::getCol3( ) const +{ + return mCol3; +} + +inline const Vector3 Transform3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Transform3::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector3 & Transform3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Transform3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Transform3 & Transform3::operator =( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; + return *this; +} + +inline const Transform3 inverse( const Transform3 & tfrm ) +{ + Vector3 tmp0, tmp1, tmp2, inv0, inv1, inv2; + float detinv; + tmp0 = cross( tfrm.getCol1(), tfrm.getCol2() ); + tmp1 = cross( tfrm.getCol2(), tfrm.getCol0() ); + tmp2 = cross( tfrm.getCol0(), tfrm.getCol1() ); + detinv = ( 1.0f / dot( tfrm.getCol2(), tmp2 ) ); + inv0 = Vector3( ( tmp0.getX() * detinv ), ( tmp1.getX() * detinv ), ( tmp2.getX() * detinv ) ); + inv1 = Vector3( ( tmp0.getY() * detinv ), ( tmp1.getY() * detinv ), ( tmp2.getY() * detinv ) ); + inv2 = Vector3( ( tmp0.getZ() * detinv ), ( tmp1.getZ() * detinv ), ( tmp2.getZ() * detinv ) ); + return Transform3( + inv0, + inv1, + inv2, + Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) + ); +} + +inline const Transform3 orthoInverse( const Transform3 & tfrm ) +{ + Vector3 inv0, inv1, inv2; + inv0 = Vector3( tfrm.getCol0().getX(), tfrm.getCol1().getX(), tfrm.getCol2().getX() ); + inv1 = Vector3( tfrm.getCol0().getY(), tfrm.getCol1().getY(), tfrm.getCol2().getY() ); + inv2 = Vector3( tfrm.getCol0().getZ(), tfrm.getCol1().getZ(), tfrm.getCol2().getZ() ); + return Transform3( + inv0, + inv1, + inv2, + Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) + ); +} + +inline const Transform3 absPerElem( const Transform3 & tfrm ) +{ + return Transform3( + absPerElem( tfrm.getCol0() ), + absPerElem( tfrm.getCol1() ), + absPerElem( tfrm.getCol2() ), + absPerElem( tfrm.getCol3() ) + ); +} + +inline const Vector3 Transform3::operator *( const Vector3 & vec ) const +{ + return Vector3( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ); +} + +inline const Point3 Transform3::operator *( const Point3 & pnt ) const +{ + return Point3( + ( ( ( ( mCol0.getX() * pnt.getX() ) + ( mCol1.getX() * pnt.getY() ) ) + ( mCol2.getX() * pnt.getZ() ) ) + mCol3.getX() ), + ( ( ( ( mCol0.getY() * pnt.getX() ) + ( mCol1.getY() * pnt.getY() ) ) + ( mCol2.getY() * pnt.getZ() ) ) + mCol3.getY() ), + ( ( ( ( mCol0.getZ() * pnt.getX() ) + ( mCol1.getZ() * pnt.getY() ) ) + ( mCol2.getZ() * pnt.getZ() ) ) + mCol3.getZ() ) + ); +} + +inline const Transform3 Transform3::operator *( const Transform3 & tfrm ) const +{ + return Transform3( + ( *this * tfrm.mCol0 ), + ( *this * tfrm.mCol1 ), + ( *this * tfrm.mCol2 ), + Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) + ); +} + +inline Transform3 & Transform3::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) +{ + return Transform3( + mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), + mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), + mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), + mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) + ); +} + +inline const Transform3 Transform3::identity( ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +inline Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) +{ + mCol0 = tfrm.getCol0(); + mCol1 = tfrm.getCol1(); + mCol2 = tfrm.getCol2(); + return *this; +} + +inline const Matrix3 Transform3::getUpper3x3( ) const +{ + return Matrix3( mCol0, mCol1, mCol2 ); +} + +inline Transform3 & Transform3::setTranslation( const Vector3 & translateVec ) +{ + mCol3 = translateVec; + return *this; +} + +inline const Vector3 Transform3::getTranslation( ) const +{ + return mCol3; +} + +inline const Transform3 Transform3::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3::xAxis( ), + Vector3( 0.0f, c, s ), + Vector3( 0.0f, -s, c ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3( c, 0.0f, -s ), + Vector3::yAxis( ), + Vector3( s, 0.0f, c ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3( c, s, 0.0f ), + Vector3( -s, c, 0.0f ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Transform3( + Vector3( ( cZ * cY ), ( sZ * cY ), -sY ), + Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ), + Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotation( float radians, const Vector3 & unitVec ) +{ + return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( 0.0f ) ); +} + +inline const Transform3 Transform3::rotation( const Quat & unitQuat ) +{ + return Transform3( Matrix3( unitQuat ), Vector3( 0.0f ) ); +} + +inline const Transform3 Transform3::scale( const Vector3 & scaleVec ) +{ + return Transform3( + Vector3( scaleVec.getX(), 0.0f, 0.0f ), + Vector3( 0.0f, scaleVec.getY(), 0.0f ), + Vector3( 0.0f, 0.0f, scaleVec.getZ() ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ) +{ + return Transform3( + ( tfrm.getCol0() * scaleVec.getX( ) ), + ( tfrm.getCol1() * scaleVec.getY( ) ), + ( tfrm.getCol2() * scaleVec.getZ( ) ), + tfrm.getCol3() + ); +} + +inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ) +{ + return Transform3( + mulPerElem( tfrm.getCol0(), scaleVec ), + mulPerElem( tfrm.getCol1(), scaleVec ), + mulPerElem( tfrm.getCol2(), scaleVec ), + mulPerElem( tfrm.getCol3(), scaleVec ) + ); +} + +inline const Transform3 Transform3::translation( const Vector3 & translateVec ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + translateVec + ); +} + +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Transform3 & tfrm ) +{ + print( tfrm.getRow( 0 ) ); + print( tfrm.getRow( 1 ) ); + print( tfrm.getRow( 2 ) ); +} + +inline void print( const Transform3 & tfrm, const char * name ) +{ + printf("%s:\n", name); + print( tfrm ); +} + +#endif + +inline Quat::Quat( const Matrix3 & tfrm ) +{ + float trace, radicand, scale, xx, yx, zx, xy, yy, zy, xz, yz, zz, tmpx, tmpy, tmpz, tmpw, qx, qy, qz, qw; + int negTrace, ZgtX, ZgtY, YgtX; + int largestXorY, largestYorZ, largestZorX; + + xx = tfrm.getCol0().getX(); + yx = tfrm.getCol0().getY(); + zx = tfrm.getCol0().getZ(); + xy = tfrm.getCol1().getX(); + yy = tfrm.getCol1().getY(); + zy = tfrm.getCol1().getZ(); + xz = tfrm.getCol2().getX(); + yz = tfrm.getCol2().getY(); + zz = tfrm.getCol2().getZ(); + + trace = ( ( xx + yy ) + zz ); + + negTrace = ( trace < 0.0f ); + ZgtX = zz > xx; + ZgtY = zz > yy; + YgtX = yy > xx; + largestXorY = ( !ZgtX || !ZgtY ) && negTrace; + largestYorZ = ( YgtX || ZgtX ) && negTrace; + largestZorX = ( ZgtY || !YgtX ) && negTrace; + + if ( largestXorY ) + { + zz = -zz; + xy = -xy; + } + if ( largestYorZ ) + { + xx = -xx; + yz = -yz; + } + if ( largestZorX ) + { + yy = -yy; + zx = -zx; + } + + radicand = ( ( ( xx + yy ) + zz ) + 1.0f ); + scale = ( 0.5f * ( 1.0f / sqrtf( radicand ) ) ); + + tmpx = ( ( zy - yz ) * scale ); + tmpy = ( ( xz - zx ) * scale ); + tmpz = ( ( yx - xy ) * scale ); + tmpw = ( radicand * scale ); + qx = tmpx; + qy = tmpy; + qz = tmpz; + qw = tmpw; + + if ( largestXorY ) + { + qx = tmpw; + qy = tmpz; + qz = tmpy; + qw = tmpx; + } + if ( largestYorZ ) + { + tmpx = qx; + tmpz = qz; + qx = qy; + qy = tmpx; + qz = qw; + qw = tmpz; + } + + mX = qx; + mY = qy; + mZ = qz; + mW = qw; +} + +inline const Matrix3 outer( const Vector3 & tfrm0, const Vector3 & tfrm1 ) +{ + return Matrix3( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ) + ); +} + +inline const Matrix4 outer( const Vector4 & tfrm0, const Vector4 & tfrm1 ) +{ + return Matrix4( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ), + ( tfrm0 * tfrm1.getW( ) ) + ); +} + +inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ) +{ + return Vector3( + ( ( ( vec.getX() * mat.getCol0().getX() ) + ( vec.getY() * mat.getCol0().getY() ) ) + ( vec.getZ() * mat.getCol0().getZ() ) ), + ( ( ( vec.getX() * mat.getCol1().getX() ) + ( vec.getY() * mat.getCol1().getY() ) ) + ( vec.getZ() * mat.getCol1().getZ() ) ), + ( ( ( vec.getX() * mat.getCol2().getX() ) + ( vec.getY() * mat.getCol2().getY() ) ) + ( vec.getZ() * mat.getCol2().getZ() ) ) + ); +} + +inline const Matrix3 crossMatrix( const Vector3 & vec ) +{ + return Matrix3( + Vector3( 0.0f, vec.getZ(), -vec.getY() ), + Vector3( -vec.getZ(), 0.0f, vec.getX() ), + Vector3( vec.getY(), -vec.getX(), 0.0f ) + ); +} + +inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ) +{ + return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); +} + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/PhysicsEffects/include/vecmath/std/quat_aos.h b/Extras/PhysicsEffects/include/vecmath/std/quat_aos.h new file mode 100644 index 0000000..6a4a0f2 --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/std/quat_aos.h @@ -0,0 +1,446 @@ +/* + Copyright (C) 2006-2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_AOS_CPP_H +#define _VECTORMATH_QUAT_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +inline Quat::Quat( const Quat & quat ) +{ + mX = quat.mX; + mY = quat.mY; + mZ = quat.mZ; + mW = quat.mW; +} + +inline Quat::Quat( float _x, float _y, float _z, float _w ) +{ + mX = _x; + mY = _y; + mZ = _z; + mW = _w; +} + +inline Quat::Quat( const Vector3 & xyz, float _w ) +{ + this->setXYZ( xyz ); + this->setW( _w ); +} + +inline Quat::Quat( const Vector4 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + mW = vec.getW(); +} + +inline Quat::Quat( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; + mW = scalar; +} + +inline const Quat Quat::identity( ) +{ + return Quat( 0.0f, 0.0f, 0.0f, 1.0f ); +} + +inline const Quat lerp( float t, const Quat & quat0, const Quat & quat1 ) +{ + return ( quat0 + ( ( quat1 - quat0 ) * t ) ); +} + +inline const Quat slerp( float t, const Quat & unitQuat0, const Quat & unitQuat1 ) +{ + Quat start; + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitQuat0, unitQuat1 ); + if ( cosAngle < 0.0f ) { + cosAngle = -cosAngle; + start = ( -unitQuat0 ); + } else { + start = unitQuat0; + } + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( start * scale0 ) + ( unitQuat1 * scale1 ) ); +} + +inline const Quat squad( float t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ) +{ + Quat tmp0, tmp1; + tmp0 = slerp( t, unitQuat0, unitQuat3 ); + tmp1 = slerp( t, unitQuat1, unitQuat2 ); + return slerp( ( ( 2.0f * t ) * ( 1.0f - t ) ), tmp0, tmp1 ); +} + +inline void loadXYZW( Quat & quat, const float * fptr ) +{ + quat = Quat( fptr[0], fptr[1], fptr[2], fptr[3] ); +} + +inline void storeXYZW( const Quat & quat, float * fptr ) +{ + fptr[0] = quat.getX(); + fptr[1] = quat.getY(); + fptr[2] = quat.getZ(); + fptr[3] = quat.getW(); +} + +inline Quat & Quat::operator =( const Quat & quat ) +{ + mX = quat.mX; + mY = quat.mY; + mZ = quat.mZ; + mW = quat.mW; + return *this; +} + +inline Quat & Quat::setXYZ( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + return *this; +} + +inline const Vector3 Quat::getXYZ( ) const +{ + return Vector3( mX, mY, mZ ); +} + +inline Quat & Quat::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Quat::getX( ) const +{ + return mX; +} + +inline Quat & Quat::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Quat::getY( ) const +{ + return mY; +} + +inline Quat & Quat::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Quat::getZ( ) const +{ + return mZ; +} + +inline Quat & Quat::setW( float _w ) +{ + mW = _w; + return *this; +} + +inline float Quat::getW( ) const +{ + return mW; +} + +inline Quat & Quat::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Quat::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Quat::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Quat::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Quat Quat::operator +( const Quat & quat ) const +{ + return Quat( + ( mX + quat.mX ), + ( mY + quat.mY ), + ( mZ + quat.mZ ), + ( mW + quat.mW ) + ); +} + +inline const Quat Quat::operator -( const Quat & quat ) const +{ + return Quat( + ( mX - quat.mX ), + ( mY - quat.mY ), + ( mZ - quat.mZ ), + ( mW - quat.mW ) + ); +} + +inline const Quat Quat::operator *( float scalar ) const +{ + return Quat( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ), + ( mW * scalar ) + ); +} + +inline Quat & Quat::operator +=( const Quat & quat ) +{ + *this = *this + quat; + return *this; +} + +inline Quat & Quat::operator -=( const Quat & quat ) +{ + *this = *this - quat; + return *this; +} + +inline Quat & Quat::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Quat Quat::operator /( float scalar ) const +{ + return Quat( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ), + ( mW / scalar ) + ); +} + +inline Quat & Quat::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Quat Quat::operator -( ) const +{ + return Quat( + -mX, + -mY, + -mZ, + -mW + ); +} + +inline const Quat operator *( float scalar, const Quat & quat ) +{ + return quat * scalar; +} + +inline float dot( const Quat & quat0, const Quat & quat1 ) +{ + float result; + result = ( quat0.getX() * quat1.getX() ); + result = ( result + ( quat0.getY() * quat1.getY() ) ); + result = ( result + ( quat0.getZ() * quat1.getZ() ) ); + result = ( result + ( quat0.getW() * quat1.getW() ) ); + return result; +} + +inline float norm( const Quat & quat ) +{ + float result; + result = ( quat.getX() * quat.getX() ); + result = ( result + ( quat.getY() * quat.getY() ) ); + result = ( result + ( quat.getZ() * quat.getZ() ) ); + result = ( result + ( quat.getW() * quat.getW() ) ); + return result; +} + +inline float length( const Quat & quat ) +{ + return ::sqrtf( norm( quat ) ); +} + +inline const Quat normalize( const Quat & quat ) +{ + float lenSqr, lenInv; + lenSqr = norm( quat ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Quat( + ( quat.getX() * lenInv ), + ( quat.getY() * lenInv ), + ( quat.getZ() * lenInv ), + ( quat.getW() * lenInv ) + ); +} + +inline const Quat Quat::rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ) +{ + float cosHalfAngleX2, recipCosHalfAngleX2; + cosHalfAngleX2 = sqrtf( ( 2.0f * ( 1.0f + dot( unitVec0, unitVec1 ) ) ) ); + recipCosHalfAngleX2 = ( 1.0f / cosHalfAngleX2 ); + return Quat( ( cross( unitVec0, unitVec1 ) * recipCosHalfAngleX2 ), ( cosHalfAngleX2 * 0.5f ) ); +} + +inline const Quat Quat::rotation( float radians, const Vector3 & unitVec ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( ( unitVec * s ), c ); +} + +inline const Quat Quat::rotationX( float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( s, 0.0f, 0.0f, c ); +} + +inline const Quat Quat::rotationY( float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( 0.0f, s, 0.0f, c ); +} + +inline const Quat Quat::rotationZ( float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( 0.0f, 0.0f, s, c ); +} + +inline const Quat Quat::operator *( const Quat & quat ) const +{ + return Quat( + ( ( ( ( mW * quat.mX ) + ( mX * quat.mW ) ) + ( mY * quat.mZ ) ) - ( mZ * quat.mY ) ), + ( ( ( ( mW * quat.mY ) + ( mY * quat.mW ) ) + ( mZ * quat.mX ) ) - ( mX * quat.mZ ) ), + ( ( ( ( mW * quat.mZ ) + ( mZ * quat.mW ) ) + ( mX * quat.mY ) ) - ( mY * quat.mX ) ), + ( ( ( ( mW * quat.mW ) - ( mX * quat.mX ) ) - ( mY * quat.mY ) ) - ( mZ * quat.mZ ) ) + ); +} + +inline Quat & Quat::operator *=( const Quat & quat ) +{ + *this = *this * quat; + return *this; +} + +inline const Vector3 rotate( const Quat & quat, const Vector3 & vec ) +{ + float tmpX, tmpY, tmpZ, tmpW; + tmpX = ( ( ( quat.getW() * vec.getX() ) + ( quat.getY() * vec.getZ() ) ) - ( quat.getZ() * vec.getY() ) ); + tmpY = ( ( ( quat.getW() * vec.getY() ) + ( quat.getZ() * vec.getX() ) ) - ( quat.getX() * vec.getZ() ) ); + tmpZ = ( ( ( quat.getW() * vec.getZ() ) + ( quat.getX() * vec.getY() ) ) - ( quat.getY() * vec.getX() ) ); + tmpW = ( ( ( quat.getX() * vec.getX() ) + ( quat.getY() * vec.getY() ) ) + ( quat.getZ() * vec.getZ() ) ); + return Vector3( + ( ( ( ( tmpW * quat.getX() ) + ( tmpX * quat.getW() ) ) - ( tmpY * quat.getZ() ) ) + ( tmpZ * quat.getY() ) ), + ( ( ( ( tmpW * quat.getY() ) + ( tmpY * quat.getW() ) ) - ( tmpZ * quat.getX() ) ) + ( tmpX * quat.getZ() ) ), + ( ( ( ( tmpW * quat.getZ() ) + ( tmpZ * quat.getW() ) ) - ( tmpX * quat.getY() ) ) + ( tmpY * quat.getX() ) ) + ); +} + +inline const Quat conj( const Quat & quat ) +{ + return Quat( -quat.getX(), -quat.getY(), -quat.getZ(), quat.getW() ); +} + +inline const Quat select( const Quat & quat0, const Quat & quat1, bool select1 ) +{ + return Quat( + ( select1 )? quat1.getX() : quat0.getX(), + ( select1 )? quat1.getY() : quat0.getY(), + ( select1 )? quat1.getZ() : quat0.getZ(), + ( select1 )? quat1.getW() : quat0.getW() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Quat & quat ) +{ + printf( "( %f %f %f %f )\n", quat.getX(), quat.getY(), quat.getZ(), quat.getW() ); +} + +inline void print( const Quat & quat, const char * name ) +{ + printf( "%s: ( %f %f %f %f )\n", name, quat.getX(), quat.getY(), quat.getZ(), quat.getW() ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/PhysicsEffects/include/vecmath/std/vec_aos.h b/Extras/PhysicsEffects/include/vecmath/std/vec_aos.h new file mode 100644 index 0000000..7dcd252 --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/std/vec_aos.h @@ -0,0 +1,1439 @@ +/* + Copyright (C) 2006-2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_AOS_CPP_H +#define _VECTORMATH_VEC_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Constants + +#define _VECTORMATH_SLERP_TOL 0.999f + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +inline Vector3::Vector3( const Vector3 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; +} + +inline Vector3::Vector3( float _x, float _y, float _z ) +{ + mX = _x; + mY = _y; + mZ = _z; +} + +inline Vector3::Vector3( const Point3 & pnt ) +{ + mX = pnt.getX(); + mY = pnt.getY(); + mZ = pnt.getZ(); +} + +inline Vector3::Vector3( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; +} + +inline const Vector3 Vector3::xAxis( ) +{ + return Vector3( 1.0f, 0.0f, 0.0f ); +} + +inline const Vector3 Vector3::yAxis( ) +{ + return Vector3( 0.0f, 1.0f, 0.0f ); +} + +inline const Vector3 Vector3::zAxis( ) +{ + return Vector3( 0.0f, 0.0f, 1.0f ); +} + +inline const Vector3 lerp( float t, const Vector3 & vec0, const Vector3 & vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector3 slerp( float t, const Vector3 & unitVec0, const Vector3 & unitVec1 ) +{ + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitVec0, unitVec1 ); + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); +} + +inline void loadXYZ( Vector3 & vec, const float * fptr ) +{ + vec = Vector3( fptr[0], fptr[1], fptr[2] ); +} + +inline void storeXYZ( const Vector3 & vec, float * fptr ) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); +} + +inline void loadHalfFloats( Vector3 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Vector3 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Vector3 & Vector3::operator =( const Vector3 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + return *this; +} + +inline Vector3 & Vector3::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Vector3::getX( ) const +{ + return mX; +} + +inline Vector3 & Vector3::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Vector3::getY( ) const +{ + return mY; +} + +inline Vector3 & Vector3::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Vector3::getZ( ) const +{ + return mZ; +} + +inline Vector3 & Vector3::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Vector3::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Vector3::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Vector3::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector3 Vector3::operator +( const Vector3 & vec ) const +{ + return Vector3( + ( mX + vec.mX ), + ( mY + vec.mY ), + ( mZ + vec.mZ ) + ); +} + +inline const Vector3 Vector3::operator -( const Vector3 & vec ) const +{ + return Vector3( + ( mX - vec.mX ), + ( mY - vec.mY ), + ( mZ - vec.mZ ) + ); +} + +inline const Point3 Vector3::operator +( const Point3 & pnt ) const +{ + return Point3( + ( mX + pnt.getX() ), + ( mY + pnt.getY() ), + ( mZ + pnt.getZ() ) + ); +} + +inline const Vector3 Vector3::operator *( float scalar ) const +{ + return Vector3( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ) + ); +} + +inline Vector3 & Vector3::operator +=( const Vector3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector3 & Vector3::operator -=( const Vector3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector3 & Vector3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector3 Vector3::operator /( float scalar ) const +{ + return Vector3( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ) + ); +} + +inline Vector3 & Vector3::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector3 Vector3::operator -( ) const +{ + return Vector3( + -mX, + -mY, + -mZ + ); +} + +inline const Vector3 operator *( float scalar, const Vector3 & vec ) +{ + return vec * scalar; +} + +inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec0.getX() * vec1.getX() ), + ( vec0.getY() * vec1.getY() ), + ( vec0.getZ() * vec1.getZ() ) + ); +} + +inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec0.getX() / vec1.getX() ), + ( vec0.getY() / vec1.getY() ), + ( vec0.getZ() / vec1.getZ() ) + ); +} + +inline const Vector3 recipPerElem( const Vector3 & vec ) +{ + return Vector3( + ( 1.0f / vec.getX() ), + ( 1.0f / vec.getY() ), + ( 1.0f / vec.getZ() ) + ); +} + +inline const Vector3 sqrtPerElem( const Vector3 & vec ) +{ + return Vector3( + sqrtf( vec.getX() ), + sqrtf( vec.getY() ), + sqrtf( vec.getZ() ) + ); +} + +inline const Vector3 rsqrtPerElem( const Vector3 & vec ) +{ + return Vector3( + ( 1.0f / sqrtf( vec.getX() ) ), + ( 1.0f / sqrtf( vec.getY() ) ), + ( 1.0f / sqrtf( vec.getZ() ) ) + ); +} + +inline const Vector3 absPerElem( const Vector3 & vec ) +{ + return Vector3( + fabsf( vec.getX() ), + fabsf( vec.getY() ), + fabsf( vec.getZ() ) + ); +} + +inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec1.getX() < 0.0f )? -fabsf( vec0.getX() ) : fabsf( vec0.getX() ), + ( vec1.getY() < 0.0f )? -fabsf( vec0.getY() ) : fabsf( vec0.getY() ), + ( vec1.getZ() < 0.0f )? -fabsf( vec0.getZ() ) : fabsf( vec0.getZ() ) + ); +} + +inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ() + ); +} + +inline float maxElem( const Vector3 & vec ) +{ + float result; + result = (vec.getX() > vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() > result)? vec.getZ() : result; + return result; +} + +inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ() + ); +} + +inline float minElem( const Vector3 & vec ) +{ + float result; + result = (vec.getX() < vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() < result)? vec.getZ() : result; + return result; +} + +inline float sum( const Vector3 & vec ) +{ + float result; + result = ( vec.getX() + vec.getY() ); + result = ( result + vec.getZ() ); + return result; +} + +inline float dot( const Vector3 & vec0, const Vector3 & vec1 ) +{ + float result; + result = ( vec0.getX() * vec1.getX() ); + result = ( result + ( vec0.getY() * vec1.getY() ) ); + result = ( result + ( vec0.getZ() * vec1.getZ() ) ); + return result; +} + +inline float lengthSqr( const Vector3 & vec ) +{ + float result; + result = ( vec.getX() * vec.getX() ); + result = ( result + ( vec.getY() * vec.getY() ) ); + result = ( result + ( vec.getZ() * vec.getZ() ) ); + return result; +} + +inline float length( const Vector3 & vec ) +{ + return ::sqrtf( lengthSqr( vec ) ); +} + +inline const Vector3 normalize( const Vector3 & vec ) +{ + float lenSqr, lenInv; + lenSqr = lengthSqr( vec ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Vector3( + ( vec.getX() * lenInv ), + ( vec.getY() * lenInv ), + ( vec.getZ() * lenInv ) + ); +} + +inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( ( vec0.getY() * vec1.getZ() ) - ( vec0.getZ() * vec1.getY() ) ), + ( ( vec0.getZ() * vec1.getX() ) - ( vec0.getX() * vec1.getZ() ) ), + ( ( vec0.getX() * vec1.getY() ) - ( vec0.getY() * vec1.getX() ) ) + ); +} + +inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, bool select1 ) +{ + return Vector3( + ( select1 )? vec1.getX() : vec0.getX(), + ( select1 )? vec1.getY() : vec0.getY(), + ( select1 )? vec1.getZ() : vec0.getZ() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Vector3 & vec ) +{ + printf( "( %f %f %f )\n", vec.getX(), vec.getY(), vec.getZ() ); +} + +inline void print( const Vector3 & vec, const char * name ) +{ + printf( "%s: ( %f %f %f )\n", name, vec.getX(), vec.getY(), vec.getZ() ); +} + +#endif + +inline Vector4::Vector4( const Vector4 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + mW = vec.mW; +} + +inline Vector4::Vector4( float _x, float _y, float _z, float _w ) +{ + mX = _x; + mY = _y; + mZ = _z; + mW = _w; +} + +inline Vector4::Vector4( const Vector3 & xyz, float _w ) +{ + this->setXYZ( xyz ); + this->setW( _w ); +} + +inline Vector4::Vector4( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + mW = 0.0f; +} + +inline Vector4::Vector4( const Point3 & pnt ) +{ + mX = pnt.getX(); + mY = pnt.getY(); + mZ = pnt.getZ(); + mW = 1.0f; +} + +inline Vector4::Vector4( const Quat & quat ) +{ + mX = quat.getX(); + mY = quat.getY(); + mZ = quat.getZ(); + mW = quat.getW(); +} + +inline Vector4::Vector4( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; + mW = scalar; +} + +inline const Vector4 Vector4::xAxis( ) +{ + return Vector4( 1.0f, 0.0f, 0.0f, 0.0f ); +} + +inline const Vector4 Vector4::yAxis( ) +{ + return Vector4( 0.0f, 1.0f, 0.0f, 0.0f ); +} + +inline const Vector4 Vector4::zAxis( ) +{ + return Vector4( 0.0f, 0.0f, 1.0f, 0.0f ); +} + +inline const Vector4 Vector4::wAxis( ) +{ + return Vector4( 0.0f, 0.0f, 0.0f, 1.0f ); +} + +inline const Vector4 lerp( float t, const Vector4 & vec0, const Vector4 & vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector4 slerp( float t, const Vector4 & unitVec0, const Vector4 & unitVec1 ) +{ + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitVec0, unitVec1 ); + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); +} + +inline void loadXYZW( Vector4 & vec, const float * fptr ) +{ + vec = Vector4( fptr[0], fptr[1], fptr[2], fptr[3] ); +} + +inline void storeXYZW( const Vector4 & vec, float * fptr ) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); + fptr[3] = vec.getW(); +} + +inline void loadHalfFloats( Vector4 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 4; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Vector4 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 4; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Vector4 & Vector4::operator =( const Vector4 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + mW = vec.mW; + return *this; +} + +inline Vector4 & Vector4::setXYZ( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + return *this; +} + +inline const Vector3 Vector4::getXYZ( ) const +{ + return Vector3( mX, mY, mZ ); +} + +inline Vector4 & Vector4::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Vector4::getX( ) const +{ + return mX; +} + +inline Vector4 & Vector4::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Vector4::getY( ) const +{ + return mY; +} + +inline Vector4 & Vector4::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Vector4::getZ( ) const +{ + return mZ; +} + +inline Vector4 & Vector4::setW( float _w ) +{ + mW = _w; + return *this; +} + +inline float Vector4::getW( ) const +{ + return mW; +} + +inline Vector4 & Vector4::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Vector4::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Vector4::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Vector4::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector4 Vector4::operator +( const Vector4 & vec ) const +{ + return Vector4( + ( mX + vec.mX ), + ( mY + vec.mY ), + ( mZ + vec.mZ ), + ( mW + vec.mW ) + ); +} + +inline const Vector4 Vector4::operator -( const Vector4 & vec ) const +{ + return Vector4( + ( mX - vec.mX ), + ( mY - vec.mY ), + ( mZ - vec.mZ ), + ( mW - vec.mW ) + ); +} + +inline const Vector4 Vector4::operator *( float scalar ) const +{ + return Vector4( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ), + ( mW * scalar ) + ); +} + +inline Vector4 & Vector4::operator +=( const Vector4 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector4 & Vector4::operator -=( const Vector4 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector4 & Vector4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector4 Vector4::operator /( float scalar ) const +{ + return Vector4( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ), + ( mW / scalar ) + ); +} + +inline Vector4 & Vector4::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector4 Vector4::operator -( ) const +{ + return Vector4( + -mX, + -mY, + -mZ, + -mW + ); +} + +inline const Vector4 operator *( float scalar, const Vector4 & vec ) +{ + return vec * scalar; +} + +inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec0.getX() * vec1.getX() ), + ( vec0.getY() * vec1.getY() ), + ( vec0.getZ() * vec1.getZ() ), + ( vec0.getW() * vec1.getW() ) + ); +} + +inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec0.getX() / vec1.getX() ), + ( vec0.getY() / vec1.getY() ), + ( vec0.getZ() / vec1.getZ() ), + ( vec0.getW() / vec1.getW() ) + ); +} + +inline const Vector4 recipPerElem( const Vector4 & vec ) +{ + return Vector4( + ( 1.0f / vec.getX() ), + ( 1.0f / vec.getY() ), + ( 1.0f / vec.getZ() ), + ( 1.0f / vec.getW() ) + ); +} + +inline const Vector4 sqrtPerElem( const Vector4 & vec ) +{ + return Vector4( + sqrtf( vec.getX() ), + sqrtf( vec.getY() ), + sqrtf( vec.getZ() ), + sqrtf( vec.getW() ) + ); +} + +inline const Vector4 rsqrtPerElem( const Vector4 & vec ) +{ + return Vector4( + ( 1.0f / sqrtf( vec.getX() ) ), + ( 1.0f / sqrtf( vec.getY() ) ), + ( 1.0f / sqrtf( vec.getZ() ) ), + ( 1.0f / sqrtf( vec.getW() ) ) + ); +} + +inline const Vector4 absPerElem( const Vector4 & vec ) +{ + return Vector4( + fabsf( vec.getX() ), + fabsf( vec.getY() ), + fabsf( vec.getZ() ), + fabsf( vec.getW() ) + ); +} + +inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec1.getX() < 0.0f )? -fabsf( vec0.getX() ) : fabsf( vec0.getX() ), + ( vec1.getY() < 0.0f )? -fabsf( vec0.getY() ) : fabsf( vec0.getY() ), + ( vec1.getZ() < 0.0f )? -fabsf( vec0.getZ() ) : fabsf( vec0.getZ() ), + ( vec1.getW() < 0.0f )? -fabsf( vec0.getW() ) : fabsf( vec0.getW() ) + ); +} + +inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ(), + (vec0.getW() > vec1.getW())? vec0.getW() : vec1.getW() + ); +} + +inline float maxElem( const Vector4 & vec ) +{ + float result; + result = (vec.getX() > vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() > result)? vec.getZ() : result; + result = (vec.getW() > result)? vec.getW() : result; + return result; +} + +inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ(), + (vec0.getW() < vec1.getW())? vec0.getW() : vec1.getW() + ); +} + +inline float minElem( const Vector4 & vec ) +{ + float result; + result = (vec.getX() < vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() < result)? vec.getZ() : result; + result = (vec.getW() < result)? vec.getW() : result; + return result; +} + +inline float sum( const Vector4 & vec ) +{ + float result; + result = ( vec.getX() + vec.getY() ); + result = ( result + vec.getZ() ); + result = ( result + vec.getW() ); + return result; +} + +inline float dot( const Vector4 & vec0, const Vector4 & vec1 ) +{ + float result; + result = ( vec0.getX() * vec1.getX() ); + result = ( result + ( vec0.getY() * vec1.getY() ) ); + result = ( result + ( vec0.getZ() * vec1.getZ() ) ); + result = ( result + ( vec0.getW() * vec1.getW() ) ); + return result; +} + +inline float lengthSqr( const Vector4 & vec ) +{ + float result; + result = ( vec.getX() * vec.getX() ); + result = ( result + ( vec.getY() * vec.getY() ) ); + result = ( result + ( vec.getZ() * vec.getZ() ) ); + result = ( result + ( vec.getW() * vec.getW() ) ); + return result; +} + +inline float length( const Vector4 & vec ) +{ + return ::sqrtf( lengthSqr( vec ) ); +} + +inline const Vector4 normalize( const Vector4 & vec ) +{ + float lenSqr, lenInv; + lenSqr = lengthSqr( vec ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Vector4( + ( vec.getX() * lenInv ), + ( vec.getY() * lenInv ), + ( vec.getZ() * lenInv ), + ( vec.getW() * lenInv ) + ); +} + +inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, bool select1 ) +{ + return Vector4( + ( select1 )? vec1.getX() : vec0.getX(), + ( select1 )? vec1.getY() : vec0.getY(), + ( select1 )? vec1.getZ() : vec0.getZ(), + ( select1 )? vec1.getW() : vec0.getW() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Vector4 & vec ) +{ + printf( "( %f %f %f %f )\n", vec.getX(), vec.getY(), vec.getZ(), vec.getW() ); +} + +inline void print( const Vector4 & vec, const char * name ) +{ + printf( "%s: ( %f %f %f %f )\n", name, vec.getX(), vec.getY(), vec.getZ(), vec.getW() ); +} + +#endif + +inline Point3::Point3( const Point3 & pnt ) +{ + mX = pnt.mX; + mY = pnt.mY; + mZ = pnt.mZ; +} + +inline Point3::Point3( float _x, float _y, float _z ) +{ + mX = _x; + mY = _y; + mZ = _z; +} + +inline Point3::Point3( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); +} + +inline Point3::Point3( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; +} + +inline const Point3 lerp( float t, const Point3 & pnt0, const Point3 & pnt1 ) +{ + return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); +} + +inline void loadXYZ( Point3 & pnt, const float * fptr ) +{ + pnt = Point3( fptr[0], fptr[1], fptr[2] ); +} + +inline void storeXYZ( const Point3 & pnt, float * fptr ) +{ + fptr[0] = pnt.getX(); + fptr[1] = pnt.getY(); + fptr[2] = pnt.getZ(); +} + +inline void loadHalfFloats( Point3 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Point3 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Point3 & Point3::operator =( const Point3 & pnt ) +{ + mX = pnt.mX; + mY = pnt.mY; + mZ = pnt.mZ; + return *this; +} + +inline Point3 & Point3::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Point3::getX( ) const +{ + return mX; +} + +inline Point3 & Point3::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Point3::getY( ) const +{ + return mY; +} + +inline Point3 & Point3::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Point3::getZ( ) const +{ + return mZ; +} + +inline Point3 & Point3::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Point3::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Point3::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Point3::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector3 Point3::operator -( const Point3 & pnt ) const +{ + return Vector3( + ( mX - pnt.mX ), + ( mY - pnt.mY ), + ( mZ - pnt.mZ ) + ); +} + +inline const Point3 Point3::operator +( const Vector3 & vec ) const +{ + return Point3( + ( mX + vec.getX() ), + ( mY + vec.getY() ), + ( mZ + vec.getZ() ) + ); +} + +inline const Point3 Point3::operator -( const Vector3 & vec ) const +{ + return Point3( + ( mX - vec.getX() ), + ( mY - vec.getY() ), + ( mZ - vec.getZ() ) + ); +} + +inline Point3 & Point3::operator +=( const Vector3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Point3 & Point3::operator -=( const Vector3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt0.getX() * pnt1.getX() ), + ( pnt0.getY() * pnt1.getY() ), + ( pnt0.getZ() * pnt1.getZ() ) + ); +} + +inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt0.getX() / pnt1.getX() ), + ( pnt0.getY() / pnt1.getY() ), + ( pnt0.getZ() / pnt1.getZ() ) + ); +} + +inline const Point3 recipPerElem( const Point3 & pnt ) +{ + return Point3( + ( 1.0f / pnt.getX() ), + ( 1.0f / pnt.getY() ), + ( 1.0f / pnt.getZ() ) + ); +} + +inline const Point3 sqrtPerElem( const Point3 & pnt ) +{ + return Point3( + sqrtf( pnt.getX() ), + sqrtf( pnt.getY() ), + sqrtf( pnt.getZ() ) + ); +} + +inline const Point3 rsqrtPerElem( const Point3 & pnt ) +{ + return Point3( + ( 1.0f / sqrtf( pnt.getX() ) ), + ( 1.0f / sqrtf( pnt.getY() ) ), + ( 1.0f / sqrtf( pnt.getZ() ) ) + ); +} + +inline const Point3 absPerElem( const Point3 & pnt ) +{ + return Point3( + fabsf( pnt.getX() ), + fabsf( pnt.getY() ), + fabsf( pnt.getZ() ) + ); +} + +inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt1.getX() < 0.0f )? -fabsf( pnt0.getX() ) : fabsf( pnt0.getX() ), + ( pnt1.getY() < 0.0f )? -fabsf( pnt0.getY() ) : fabsf( pnt0.getY() ), + ( pnt1.getZ() < 0.0f )? -fabsf( pnt0.getZ() ) : fabsf( pnt0.getZ() ) + ); +} + +inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + (pnt0.getX() > pnt1.getX())? pnt0.getX() : pnt1.getX(), + (pnt0.getY() > pnt1.getY())? pnt0.getY() : pnt1.getY(), + (pnt0.getZ() > pnt1.getZ())? pnt0.getZ() : pnt1.getZ() + ); +} + +inline float maxElem( const Point3 & pnt ) +{ + float result; + result = (pnt.getX() > pnt.getY())? pnt.getX() : pnt.getY(); + result = (pnt.getZ() > result)? pnt.getZ() : result; + return result; +} + +inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + (pnt0.getX() < pnt1.getX())? pnt0.getX() : pnt1.getX(), + (pnt0.getY() < pnt1.getY())? pnt0.getY() : pnt1.getY(), + (pnt0.getZ() < pnt1.getZ())? pnt0.getZ() : pnt1.getZ() + ); +} + +inline float minElem( const Point3 & pnt ) +{ + float result; + result = (pnt.getX() < pnt.getY())? pnt.getX() : pnt.getY(); + result = (pnt.getZ() < result)? pnt.getZ() : result; + return result; +} + +inline float sum( const Point3 & pnt ) +{ + float result; + result = ( pnt.getX() + pnt.getY() ); + result = ( result + pnt.getZ() ); + return result; +} + +inline const Point3 scale( const Point3 & pnt, float scaleVal ) +{ + return mulPerElem( pnt, Point3( scaleVal ) ); +} + +inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ) +{ + return mulPerElem( pnt, Point3( scaleVec ) ); +} + +inline float projection( const Point3 & pnt, const Vector3 & unitVec ) +{ + float result; + result = ( pnt.getX() * unitVec.getX() ); + result = ( result + ( pnt.getY() * unitVec.getY() ) ); + result = ( result + ( pnt.getZ() * unitVec.getZ() ) ); + return result; +} + +inline float distSqrFromOrigin( const Point3 & pnt ) +{ + return lengthSqr( Vector3( pnt ) ); +} + +inline float distFromOrigin( const Point3 & pnt ) +{ + return length( Vector3( pnt ) ); +} + +inline float distSqr( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return lengthSqr( ( pnt1 - pnt0 ) ); +} + +inline float dist( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return length( ( pnt1 - pnt0 ) ); +} + +inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, bool select1 ) +{ + return Point3( + ( select1 )? pnt1.getX() : pnt0.getX(), + ( select1 )? pnt1.getY() : pnt0.getY(), + ( select1 )? pnt1.getZ() : pnt0.getZ() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Point3 & pnt ) +{ + printf( "( %f %f %f )\n", pnt.getX(), pnt.getY(), pnt.getZ() ); +} + +inline void print( const Point3 & pnt, const char * name ) +{ + printf( "%s: ( %f %f %f )\n", name, pnt.getX(), pnt.getY(), pnt.getZ() ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/PhysicsEffects/include/vecmath/std/vectormath_aos.h b/Extras/PhysicsEffects/include/vecmath/std/vectormath_aos.h new file mode 100644 index 0000000..c1f3985 --- /dev/null +++ b/Extras/PhysicsEffects/include/vecmath/std/vectormath_aos.h @@ -0,0 +1,1885 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_AOS_CPP_SCALAR_H +#define _VECTORMATH_AOS_CPP_SCALAR_H + +#include + +#ifdef _VECTORMATH_DEBUG +#include +#endif + +namespace Vectormath { + +namespace Aos { + +//----------------------------------------------------------------------------- +// Forward Declarations +// + +class Vector3; +class Vector4; +class Point3; +class Quat; +class Matrix3; +class Matrix4; +class Transform3; + +// A 3-D vector in array-of-structures format +// +class Vector3 +{ + float mX; + float mY; + float mZ; +#ifndef __GNUC__ + float d; +#endif + +public: + // Default constructor; does no initialization + // + inline Vector3( ) { }; + + // Copy a 3-D vector + // + inline Vector3( const Vector3 & vec ); + + // Construct a 3-D vector from x, y, and z elements + // + inline Vector3( float x, float y, float z ); + + // Copy elements from a 3-D point into a 3-D vector + // + explicit inline Vector3( const Point3 & pnt ); + + // Set all elements of a 3-D vector to the same scalar value + // + explicit inline Vector3( float scalar ); + + // Assign one 3-D vector to another + // + inline Vector3 & operator =( const Vector3 & vec ); + + // Set the x element of a 3-D vector + // + inline Vector3 & setX( float x ); + + // Set the y element of a 3-D vector + // + inline Vector3 & setY( float y ); + + // Set the z element of a 3-D vector + // + inline Vector3 & setZ( float z ); + + // Get the x element of a 3-D vector + // + inline float getX( ) const; + + // Get the y element of a 3-D vector + // + inline float getY( ) const; + + // Get the z element of a 3-D vector + // + inline float getZ( ) const; + + // Set an x, y, or z element of a 3-D vector by index + // + inline Vector3 & setElem( int idx, float value ); + + // Get an x, y, or z element of a 3-D vector by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two 3-D vectors + // + inline const Vector3 operator +( const Vector3 & vec ) const; + + // Subtract a 3-D vector from another 3-D vector + // + inline const Vector3 operator -( const Vector3 & vec ) const; + + // Add a 3-D vector to a 3-D point + // + inline const Point3 operator +( const Point3 & pnt ) const; + + // Multiply a 3-D vector by a scalar + // + inline const Vector3 operator *( float scalar ) const; + + // Divide a 3-D vector by a scalar + // + inline const Vector3 operator /( float scalar ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Vector3 & operator +=( const Vector3 & vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Vector3 & operator -=( const Vector3 & vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector3 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector3 & operator /=( float scalar ); + + // Negate all elements of a 3-D vector + // + inline const Vector3 operator -( ) const; + + // Construct x axis + // + static inline const Vector3 xAxis( ); + + // Construct y axis + // + static inline const Vector3 yAxis( ); + + // Construct z axis + // + static inline const Vector3 zAxis( ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a 3-D vector by a scalar +// +inline const Vector3 operator *( float scalar, const Vector3 & vec ); + +// Multiply two 3-D vectors per element +// +inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Divide two 3-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Compute the reciprocal of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector3 recipPerElem( const Vector3 & vec ); + +// Compute the square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector3 sqrtPerElem( const Vector3 & vec ); + +// Compute the reciprocal square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector3 rsqrtPerElem( const Vector3 & vec ); + +// Compute the absolute value of a 3-D vector per element +// +inline const Vector3 absPerElem( const Vector3 & vec ); + +// Copy sign from one 3-D vector to another, per element +// +inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Maximum of two 3-D vectors per element +// +inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Minimum of two 3-D vectors per element +// +inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Maximum element of a 3-D vector +// +inline float maxElem( const Vector3 & vec ); + +// Minimum element of a 3-D vector +// +inline float minElem( const Vector3 & vec ); + +// Compute the sum of all elements of a 3-D vector +// +inline float sum( const Vector3 & vec ); + +// Compute the dot product of two 3-D vectors +// +inline float dot( const Vector3 & vec0, const Vector3 & vec1 ); + +// Compute the square of the length of a 3-D vector +// +inline float lengthSqr( const Vector3 & vec ); + +// Compute the length of a 3-D vector +// +inline float length( const Vector3 & vec ); + +// Normalize a 3-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector3 normalize( const Vector3 & vec ); + +// Compute cross product of two 3-D vectors +// +inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ); + +// Outer product of two 3-D vectors +// +inline const Matrix3 outer( const Vector3 & vec0, const Vector3 & vec1 ); + +// Pre-multiply a row vector by a 3x3 matrix +// +inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ); + +// Cross-product matrix of a 3-D vector +// +inline const Matrix3 crossMatrix( const Vector3 & vec ); + +// Create cross-product matrix and multiply +// NOTE: +// Faster than separately creating a cross-product matrix and multiplying. +// +inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ); + +// Linear interpolation between two 3-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector3 lerp( float t, const Vector3 & vec0, const Vector3 & vec1 ); + +// Spherical linear interpolation between two 3-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector3 slerp( float t, const Vector3 & unitVec0, const Vector3 & unitVec1 ); + +// Conditionally select between two 3-D vectors +// +inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, bool select1 ); + +// Load x, y, and z elements from the first three words of a float array. +// +// +inline void loadXYZ( Vector3 & vec, const float * fptr ); + +// Store x, y, and z elements of a 3-D vector in the first three words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZ( const Vector3 & vec, float * fptr ); + +// Load three-half-floats as a 3-D vector +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Vector3 & vec, const unsigned short * hfptr ); + +// Store a 3-D vector as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Vector3 & vec, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector3 & vec ); + +// Print a 3-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector3 & vec, const char * name ); + +#endif + +// A 4-D vector in array-of-structures format +// +class Vector4 +{ + float mX; + float mY; + float mZ; + float mW; + +public: + // Default constructor; does no initialization + // + inline Vector4( ) { }; + + // Copy a 4-D vector + // + inline Vector4( const Vector4 & vec ); + + // Construct a 4-D vector from x, y, z, and w elements + // + inline Vector4( float x, float y, float z, float w ); + + // Construct a 4-D vector from a 3-D vector and a scalar + // + inline Vector4( const Vector3 & xyz, float w ); + + // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + // + explicit inline Vector4( const Vector3 & vec ); + + // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + // + explicit inline Vector4( const Point3 & pnt ); + + // Copy elements from a quaternion into a 4-D vector + // + explicit inline Vector4( const Quat & quat ); + + // Set all elements of a 4-D vector to the same scalar value + // + explicit inline Vector4( float scalar ); + + // Assign one 4-D vector to another + // + inline Vector4 & operator =( const Vector4 & vec ); + + // Set the x, y, and z elements of a 4-D vector + // NOTE: + // This function does not change the w element. + // + inline Vector4 & setXYZ( const Vector3 & vec ); + + // Get the x, y, and z elements of a 4-D vector + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a 4-D vector + // + inline Vector4 & setX( float x ); + + // Set the y element of a 4-D vector + // + inline Vector4 & setY( float y ); + + // Set the z element of a 4-D vector + // + inline Vector4 & setZ( float z ); + + // Set the w element of a 4-D vector + // + inline Vector4 & setW( float w ); + + // Get the x element of a 4-D vector + // + inline float getX( ) const; + + // Get the y element of a 4-D vector + // + inline float getY( ) const; + + // Get the z element of a 4-D vector + // + inline float getZ( ) const; + + // Get the w element of a 4-D vector + // + inline float getW( ) const; + + // Set an x, y, z, or w element of a 4-D vector by index + // + inline Vector4 & setElem( int idx, float value ); + + // Get an x, y, z, or w element of a 4-D vector by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two 4-D vectors + // + inline const Vector4 operator +( const Vector4 & vec ) const; + + // Subtract a 4-D vector from another 4-D vector + // + inline const Vector4 operator -( const Vector4 & vec ) const; + + // Multiply a 4-D vector by a scalar + // + inline const Vector4 operator *( float scalar ) const; + + // Divide a 4-D vector by a scalar + // + inline const Vector4 operator /( float scalar ) const; + + // Perform compound assignment and addition with a 4-D vector + // + inline Vector4 & operator +=( const Vector4 & vec ); + + // Perform compound assignment and subtraction by a 4-D vector + // + inline Vector4 & operator -=( const Vector4 & vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector4 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector4 & operator /=( float scalar ); + + // Negate all elements of a 4-D vector + // + inline const Vector4 operator -( ) const; + + // Construct x axis + // + static inline const Vector4 xAxis( ); + + // Construct y axis + // + static inline const Vector4 yAxis( ); + + // Construct z axis + // + static inline const Vector4 zAxis( ); + + // Construct w axis + // + static inline const Vector4 wAxis( ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a 4-D vector by a scalar +// +inline const Vector4 operator *( float scalar, const Vector4 & vec ); + +// Multiply two 4-D vectors per element +// +inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Divide two 4-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Compute the reciprocal of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector4 recipPerElem( const Vector4 & vec ); + +// Compute the square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector4 sqrtPerElem( const Vector4 & vec ); + +// Compute the reciprocal square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector4 rsqrtPerElem( const Vector4 & vec ); + +// Compute the absolute value of a 4-D vector per element +// +inline const Vector4 absPerElem( const Vector4 & vec ); + +// Copy sign from one 4-D vector to another, per element +// +inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Maximum of two 4-D vectors per element +// +inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Minimum of two 4-D vectors per element +// +inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Maximum element of a 4-D vector +// +inline float maxElem( const Vector4 & vec ); + +// Minimum element of a 4-D vector +// +inline float minElem( const Vector4 & vec ); + +// Compute the sum of all elements of a 4-D vector +// +inline float sum( const Vector4 & vec ); + +// Compute the dot product of two 4-D vectors +// +inline float dot( const Vector4 & vec0, const Vector4 & vec1 ); + +// Compute the square of the length of a 4-D vector +// +inline float lengthSqr( const Vector4 & vec ); + +// Compute the length of a 4-D vector +// +inline float length( const Vector4 & vec ); + +// Normalize a 4-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector4 normalize( const Vector4 & vec ); + +// Outer product of two 4-D vectors +// +inline const Matrix4 outer( const Vector4 & vec0, const Vector4 & vec1 ); + +// Linear interpolation between two 4-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector4 lerp( float t, const Vector4 & vec0, const Vector4 & vec1 ); + +// Spherical linear interpolation between two 4-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector4 slerp( float t, const Vector4 & unitVec0, const Vector4 & unitVec1 ); + +// Conditionally select between two 4-D vectors +// +inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, bool select1 ); + +// Load x, y, z, and w elements from the first four words of a float array. +// +// +inline void loadXYZW( Vector4 & vec, const float * fptr ); + +// Store x, y, z, and w elements of a 4-D vector in the first four words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZW( const Vector4 & vec, float * fptr ); + +// Load four-half-floats as a 4-D vector +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Vector4 & vec, const unsigned short * hfptr ); + +// Store a 4-D vector as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Vector4 & vec, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector4 & vec ); + +// Print a 4-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector4 & vec, const char * name ); + +#endif + +// A 3-D point in array-of-structures format +// +class Point3 +{ + float mX; + float mY; + float mZ; +#ifndef __GNUC__ + float d; +#endif + +public: + // Default constructor; does no initialization + // + inline Point3( ) { }; + + // Copy a 3-D point + // + inline Point3( const Point3 & pnt ); + + // Construct a 3-D point from x, y, and z elements + // + inline Point3( float x, float y, float z ); + + // Copy elements from a 3-D vector into a 3-D point + // + explicit inline Point3( const Vector3 & vec ); + + // Set all elements of a 3-D point to the same scalar value + // + explicit inline Point3( float scalar ); + + // Assign one 3-D point to another + // + inline Point3 & operator =( const Point3 & pnt ); + + // Set the x element of a 3-D point + // + inline Point3 & setX( float x ); + + // Set the y element of a 3-D point + // + inline Point3 & setY( float y ); + + // Set the z element of a 3-D point + // + inline Point3 & setZ( float z ); + + // Get the x element of a 3-D point + // + inline float getX( ) const; + + // Get the y element of a 3-D point + // + inline float getY( ) const; + + // Get the z element of a 3-D point + // + inline float getZ( ) const; + + // Set an x, y, or z element of a 3-D point by index + // + inline Point3 & setElem( int idx, float value ); + + // Get an x, y, or z element of a 3-D point by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Subtract a 3-D point from another 3-D point + // + inline const Vector3 operator -( const Point3 & pnt ) const; + + // Add a 3-D point to a 3-D vector + // + inline const Point3 operator +( const Vector3 & vec ) const; + + // Subtract a 3-D vector from a 3-D point + // + inline const Point3 operator -( const Vector3 & vec ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Point3 & operator +=( const Vector3 & vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Point3 & operator -=( const Vector3 & vec ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply two 3-D points per element +// +inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Divide two 3-D points per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Compute the reciprocal of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Point3 recipPerElem( const Point3 & pnt ); + +// Compute the square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Point3 sqrtPerElem( const Point3 & pnt ); + +// Compute the reciprocal square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Point3 rsqrtPerElem( const Point3 & pnt ); + +// Compute the absolute value of a 3-D point per element +// +inline const Point3 absPerElem( const Point3 & pnt ); + +// Copy sign from one 3-D point to another, per element +// +inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Maximum of two 3-D points per element +// +inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Minimum of two 3-D points per element +// +inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Maximum element of a 3-D point +// +inline float maxElem( const Point3 & pnt ); + +// Minimum element of a 3-D point +// +inline float minElem( const Point3 & pnt ); + +// Compute the sum of all elements of a 3-D point +// +inline float sum( const Point3 & pnt ); + +// Apply uniform scale to a 3-D point +// +inline const Point3 scale( const Point3 & pnt, float scaleVal ); + +// Apply non-uniform scale to a 3-D point +// +inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ); + +// Scalar projection of a 3-D point on a unit-length 3-D vector +// +inline float projection( const Point3 & pnt, const Vector3 & unitVec ); + +// Compute the square of the distance of a 3-D point from the coordinate-system origin +// +inline float distSqrFromOrigin( const Point3 & pnt ); + +// Compute the distance of a 3-D point from the coordinate-system origin +// +inline float distFromOrigin( const Point3 & pnt ); + +// Compute the square of the distance between two 3-D points +// +inline float distSqr( const Point3 & pnt0, const Point3 & pnt1 ); + +// Compute the distance between two 3-D points +// +inline float dist( const Point3 & pnt0, const Point3 & pnt1 ); + +// Linear interpolation between two 3-D points +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Point3 lerp( float t, const Point3 & pnt0, const Point3 & pnt1 ); + +// Conditionally select between two 3-D points +// +inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, bool select1 ); + +// Load x, y, and z elements from the first three words of a float array. +// +// +inline void loadXYZ( Point3 & pnt, const float * fptr ); + +// Store x, y, and z elements of a 3-D point in the first three words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZ( const Point3 & pnt, float * fptr ); + +// Load three-half-floats as a 3-D point +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Point3 & pnt, const unsigned short * hfptr ); + +// Store a 3-D point as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Point3 & pnt, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D point +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Point3 & pnt ); + +// Print a 3-D point and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Point3 & pnt, const char * name ); + +#endif + +// A quaternion in array-of-structures format +// +class Quat +{ + float mX; + float mY; + float mZ; + float mW; + +public: + // Default constructor; does no initialization + // + inline Quat( ) { }; + + // Copy a quaternion + // + inline Quat( const Quat & quat ); + + // Construct a quaternion from x, y, z, and w elements + // + inline Quat( float x, float y, float z, float w ); + + // Construct a quaternion from a 3-D vector and a scalar + // + inline Quat( const Vector3 & xyz, float w ); + + // Copy elements from a 4-D vector into a quaternion + // + explicit inline Quat( const Vector4 & vec ); + + // Convert a rotation matrix to a unit-length quaternion + // + explicit inline Quat( const Matrix3 & rotMat ); + + // Set all elements of a quaternion to the same scalar value + // + explicit inline Quat( float scalar ); + + // Assign one quaternion to another + // + inline Quat & operator =( const Quat & quat ); + + // Set the x, y, and z elements of a quaternion + // NOTE: + // This function does not change the w element. + // + inline Quat & setXYZ( const Vector3 & vec ); + + // Get the x, y, and z elements of a quaternion + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a quaternion + // + inline Quat & setX( float x ); + + // Set the y element of a quaternion + // + inline Quat & setY( float y ); + + // Set the z element of a quaternion + // + inline Quat & setZ( float z ); + + // Set the w element of a quaternion + // + inline Quat & setW( float w ); + + // Get the x element of a quaternion + // + inline float getX( ) const; + + // Get the y element of a quaternion + // + inline float getY( ) const; + + // Get the z element of a quaternion + // + inline float getZ( ) const; + + // Get the w element of a quaternion + // + inline float getW( ) const; + + // Set an x, y, z, or w element of a quaternion by index + // + inline Quat & setElem( int idx, float value ); + + // Get an x, y, z, or w element of a quaternion by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two quaternions + // + inline const Quat operator +( const Quat & quat ) const; + + // Subtract a quaternion from another quaternion + // + inline const Quat operator -( const Quat & quat ) const; + + // Multiply two quaternions + // + inline const Quat operator *( const Quat & quat ) const; + + // Multiply a quaternion by a scalar + // + inline const Quat operator *( float scalar ) const; + + // Divide a quaternion by a scalar + // + inline const Quat operator /( float scalar ) const; + + // Perform compound assignment and addition with a quaternion + // + inline Quat & operator +=( const Quat & quat ); + + // Perform compound assignment and subtraction by a quaternion + // + inline Quat & operator -=( const Quat & quat ); + + // Perform compound assignment and multiplication by a quaternion + // + inline Quat & operator *=( const Quat & quat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Quat & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Quat & operator /=( float scalar ); + + // Negate all elements of a quaternion + // + inline const Quat operator -( ) const; + + // Construct an identity quaternion + // + static inline const Quat identity( ); + + // Construct a quaternion to rotate between two unit-length 3-D vectors + // NOTE: + // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + // + static inline const Quat rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ); + + // Construct a quaternion to rotate around a unit-length 3-D vector + // + static inline const Quat rotation( float radians, const Vector3 & unitVec ); + + // Construct a quaternion to rotate around the x axis + // + static inline const Quat rotationX( float radians ); + + // Construct a quaternion to rotate around the y axis + // + static inline const Quat rotationY( float radians ); + + // Construct a quaternion to rotate around the z axis + // + static inline const Quat rotationZ( float radians ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a quaternion by a scalar +// +inline const Quat operator *( float scalar, const Quat & quat ); + +// Compute the conjugate of a quaternion +// +inline const Quat conj( const Quat & quat ); + +// Use a unit-length quaternion to rotate a 3-D vector +// +inline const Vector3 rotate( const Quat & unitQuat, const Vector3 & vec ); + +// Compute the dot product of two quaternions +// +inline float dot( const Quat & quat0, const Quat & quat1 ); + +// Compute the norm of a quaternion +// +inline float norm( const Quat & quat ); + +// Compute the length of a quaternion +// +inline float length( const Quat & quat ); + +// Normalize a quaternion +// NOTE: +// The result is unpredictable when all elements of quat are at or near zero. +// +inline const Quat normalize( const Quat & quat ); + +// Linear interpolation between two quaternions +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Quat lerp( float t, const Quat & quat0, const Quat & quat1 ); + +// Spherical linear interpolation between two quaternions +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +inline const Quat slerp( float t, const Quat & unitQuat0, const Quat & unitQuat1 ); + +// Spherical quadrangle interpolation +// +inline const Quat squad( float t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ); + +// Conditionally select between two quaternions +// +inline const Quat select( const Quat & quat0, const Quat & quat1, bool select1 ); + +// Load x, y, z, and w elements from the first four words of a float array. +// +// +inline void loadXYZW( Quat & quat, const float * fptr ); + +// Store x, y, z, and w elements of a quaternion in the first four words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZW( const Quat & quat, float * fptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a quaternion +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Quat & quat ); + +// Print a quaternion and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Quat & quat, const char * name ); + +#endif + +// A 3x3 matrix in array-of-structures format +// +class Matrix3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + +public: + // Default constructor; does no initialization + // + inline Matrix3( ) { }; + + // Copy a 3x3 matrix + // + inline Matrix3( const Matrix3 & mat ); + + // Construct a 3x3 matrix containing the specified columns + // + inline Matrix3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2 ); + + // Construct a 3x3 rotation matrix from a unit-length quaternion + // + explicit inline Matrix3( const Quat & unitQuat ); + + // Set all elements of a 3x3 matrix to the same scalar value + // + explicit inline Matrix3( float scalar ); + + // Assign one 3x3 matrix to another + // + inline Matrix3 & operator =( const Matrix3 & mat ); + + // Set column 0 of a 3x3 matrix + // + inline Matrix3 & setCol0( const Vector3 & col0 ); + + // Set column 1 of a 3x3 matrix + // + inline Matrix3 & setCol1( const Vector3 & col1 ); + + // Set column 2 of a 3x3 matrix + // + inline Matrix3 & setCol2( const Vector3 & col2 ); + + // Get column 0 of a 3x3 matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x3 matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x3 matrix + // + inline const Vector3 getCol2( ) const; + + // Set the column of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setCol( int col, const Vector3 & vec ); + + // Set the row of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setRow( int row, const Vector3 & vec ); + + // Get the column of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x3 matrix referred to by column and row indices + // + inline Matrix3 & setElem( int col, int row, float val ); + + // Get the element of a 3x3 matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Add two 3x3 matrices + // + inline const Matrix3 operator +( const Matrix3 & mat ) const; + + // Subtract a 3x3 matrix from another 3x3 matrix + // + inline const Matrix3 operator -( const Matrix3 & mat ) const; + + // Negate all elements of a 3x3 matrix + // + inline const Matrix3 operator -( ) const; + + // Multiply a 3x3 matrix by a scalar + // + inline const Matrix3 operator *( float scalar ) const; + + // Multiply a 3x3 matrix by a 3-D vector + // + inline const Vector3 operator *( const Vector3 & vec ) const; + + // Multiply two 3x3 matrices + // + inline const Matrix3 operator *( const Matrix3 & mat ) const; + + // Perform compound assignment and addition with a 3x3 matrix + // + inline Matrix3 & operator +=( const Matrix3 & mat ); + + // Perform compound assignment and subtraction by a 3x3 matrix + // + inline Matrix3 & operator -=( const Matrix3 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix3 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a 3x3 matrix + // + inline Matrix3 & operator *=( const Matrix3 & mat ); + + // Construct an identity 3x3 matrix + // + static inline const Matrix3 identity( ); + + // Construct a 3x3 matrix to rotate around the x axis + // + static inline const Matrix3 rotationX( float radians ); + + // Construct a 3x3 matrix to rotate around the y axis + // + static inline const Matrix3 rotationY( float radians ); + + // Construct a 3x3 matrix to rotate around the z axis + // + static inline const Matrix3 rotationZ( float radians ); + + // Construct a 3x3 matrix to rotate around the x, y, and z axes + // + static inline const Matrix3 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix3 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix3 rotation( const Quat & unitQuat ); + + // Construct a 3x3 matrix to perform scaling + // + static inline const Matrix3 scale( const Vector3 & scaleVec ); + +}; +// Multiply a 3x3 matrix by a scalar +// +inline const Matrix3 operator *( float scalar, const Matrix3 & mat ); + +// Append (post-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ); + +// Multiply two 3x3 matrices per element +// +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); + +// Compute the absolute value of a 3x3 matrix per element +// +inline const Matrix3 absPerElem( const Matrix3 & mat ); + +// Transpose of a 3x3 matrix +// +inline const Matrix3 transpose( const Matrix3 & mat ); + +// Compute the inverse of a 3x3 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix3 inverse( const Matrix3 & mat ); + +// Determinant of a 3x3 matrix +// +inline float determinant( const Matrix3 & mat ); + +// Conditionally select between two 3x3 matrices +// +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x3 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat ); + +// Print a 3x3 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat, const char * name ); + +#endif + +// A 4x4 matrix in array-of-structures format +// +class Matrix4 +{ + Vector4 mCol0; + Vector4 mCol1; + Vector4 mCol2; + Vector4 mCol3; + +public: + // Default constructor; does no initialization + // + inline Matrix4( ) { }; + + // Copy a 4x4 matrix + // + inline Matrix4( const Matrix4 & mat ); + + // Construct a 4x4 matrix containing the specified columns + // + inline Matrix4( const Vector4 & col0, const Vector4 & col1, const Vector4 & col2, const Vector4 & col3 ); + + // Construct a 4x4 matrix from a 3x4 transformation matrix + // + explicit inline Matrix4( const Transform3 & mat ); + + // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + // + inline Matrix4( const Matrix3 & mat, const Vector3 & translateVec ); + + // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + // + inline Matrix4( const Quat & unitQuat, const Vector3 & translateVec ); + + // Set all elements of a 4x4 matrix to the same scalar value + // + explicit inline Matrix4( float scalar ); + + // Assign one 4x4 matrix to another + // + inline Matrix4 & operator =( const Matrix4 & mat ); + + // Set the upper-left 3x3 submatrix + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 4x4 matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setTranslation( const Vector3 & translateVec ); + + // Get the translation component of a 4x4 matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 4x4 matrix + // + inline Matrix4 & setCol0( const Vector4 & col0 ); + + // Set column 1 of a 4x4 matrix + // + inline Matrix4 & setCol1( const Vector4 & col1 ); + + // Set column 2 of a 4x4 matrix + // + inline Matrix4 & setCol2( const Vector4 & col2 ); + + // Set column 3 of a 4x4 matrix + // + inline Matrix4 & setCol3( const Vector4 & col3 ); + + // Get column 0 of a 4x4 matrix + // + inline const Vector4 getCol0( ) const; + + // Get column 1 of a 4x4 matrix + // + inline const Vector4 getCol1( ) const; + + // Get column 2 of a 4x4 matrix + // + inline const Vector4 getCol2( ) const; + + // Get column 3 of a 4x4 matrix + // + inline const Vector4 getCol3( ) const; + + // Set the column of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setCol( int col, const Vector4 & vec ); + + // Set the row of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setRow( int row, const Vector4 & vec ); + + // Get the column of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getCol( int col ) const; + + // Get the row of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector4 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector4 operator []( int col ) const; + + // Set the element of a 4x4 matrix referred to by column and row indices + // + inline Matrix4 & setElem( int col, int row, float val ); + + // Get the element of a 4x4 matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Add two 4x4 matrices + // + inline const Matrix4 operator +( const Matrix4 & mat ) const; + + // Subtract a 4x4 matrix from another 4x4 matrix + // + inline const Matrix4 operator -( const Matrix4 & mat ) const; + + // Negate all elements of a 4x4 matrix + // + inline const Matrix4 operator -( ) const; + + // Multiply a 4x4 matrix by a scalar + // + inline const Matrix4 operator *( float scalar ) const; + + // Multiply a 4x4 matrix by a 4-D vector + // + inline const Vector4 operator *( const Vector4 & vec ) const; + + // Multiply a 4x4 matrix by a 3-D vector + // + inline const Vector4 operator *( const Vector3 & vec ) const; + + // Multiply a 4x4 matrix by a 3-D point + // + inline const Vector4 operator *( const Point3 & pnt ) const; + + // Multiply two 4x4 matrices + // + inline const Matrix4 operator *( const Matrix4 & mat ) const; + + // Multiply a 4x4 matrix by a 3x4 transformation matrix + // + inline const Matrix4 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and addition with a 4x4 matrix + // + inline Matrix4 & operator +=( const Matrix4 & mat ); + + // Perform compound assignment and subtraction by a 4x4 matrix + // + inline Matrix4 & operator -=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix4 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a 4x4 matrix + // + inline Matrix4 & operator *=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Matrix4 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 4x4 matrix + // + static inline const Matrix4 identity( ); + + // Construct a 4x4 matrix to rotate around the x axis + // + static inline const Matrix4 rotationX( float radians ); + + // Construct a 4x4 matrix to rotate around the y axis + // + static inline const Matrix4 rotationY( float radians ); + + // Construct a 4x4 matrix to rotate around the z axis + // + static inline const Matrix4 rotationZ( float radians ); + + // Construct a 4x4 matrix to rotate around the x, y, and z axes + // + static inline const Matrix4 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix4 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix4 rotation( const Quat & unitQuat ); + + // Construct a 4x4 matrix to perform scaling + // + static inline const Matrix4 scale( const Vector3 & scaleVec ); + + // Construct a 4x4 matrix to perform translation + // + static inline const Matrix4 translation( const Vector3 & translateVec ); + + // Construct viewing matrix based on eye position, position looked at, and up direction + // + static inline const Matrix4 lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ); + + // Construct a perspective projection matrix + // + static inline const Matrix4 perspective( float fovyRadians, float aspect, float zNear, float zFar ); + + // Construct a perspective projection matrix based on frustum + // + static inline const Matrix4 frustum( float left, float right, float bottom, float top, float zNear, float zFar ); + + // Construct an orthographic projection matrix + // + static inline const Matrix4 orthographic( float left, float right, float bottom, float top, float zNear, float zFar ); + +}; +// Multiply a 4x4 matrix by a scalar +// +inline const Matrix4 operator *( float scalar, const Matrix4 & mat ); + +// Append (post-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ); + +// Multiply two 4x4 matrices per element +// +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); + +// Compute the absolute value of a 4x4 matrix per element +// +inline const Matrix4 absPerElem( const Matrix4 & mat ); + +// Transpose of a 4x4 matrix +// +inline const Matrix4 transpose( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 inverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 affineInverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. +// +inline const Matrix4 orthoInverse( const Matrix4 & mat ); + +// Determinant of a 4x4 matrix +// +inline float determinant( const Matrix4 & mat ); + +// Conditionally select between two 4x4 matrices +// +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4x4 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat ); + +// Print a 4x4 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat, const char * name ); + +#endif + +// A 3x4 transformation matrix in array-of-structures format +// +class Transform3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + Vector3 mCol3; + +public: + // Default constructor; does no initialization + // + inline Transform3( ) { }; + + // Copy a 3x4 transformation matrix + // + inline Transform3( const Transform3 & tfrm ); + + // Construct a 3x4 transformation matrix containing the specified columns + // + inline Transform3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2, const Vector3 & col3 ); + + // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + // + inline Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ); + + // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + // + inline Transform3( const Quat & unitQuat, const Vector3 & translateVec ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value + // + explicit inline Transform3( float scalar ); + + // Assign one 3x4 transformation matrix to another + // + inline Transform3 & operator =( const Transform3 & tfrm ); + + // Set the upper-left 3x3 submatrix + // + inline Transform3 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // + inline Transform3 & setTranslation( const Vector3 & translateVec ); + + // Get the translation component of a 3x4 transformation matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 3x4 transformation matrix + // + inline Transform3 & setCol0( const Vector3 & col0 ); + + // Set column 1 of a 3x4 transformation matrix + // + inline Transform3 & setCol1( const Vector3 & col1 ); + + // Set column 2 of a 3x4 transformation matrix + // + inline Transform3 & setCol2( const Vector3 & col2 ); + + // Set column 3 of a 3x4 transformation matrix + // + inline Transform3 & setCol3( const Vector3 & col3 ); + + // Get column 0 of a 3x4 transformation matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x4 transformation matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x4 transformation matrix + // + inline const Vector3 getCol2( ) const; + + // Get column 3 of a 3x4 transformation matrix + // + inline const Vector3 getCol3( ) const; + + // Set the column of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setCol( int col, const Vector3 & vec ); + + // Set the row of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setRow( int row, const Vector4 & vec ); + + // Get the column of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x4 transformation matrix referred to by column and row indices + // + inline Transform3 & setElem( int col, int row, float val ); + + // Get the element of a 3x4 transformation matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Multiply a 3x4 transformation matrix by a 3-D vector + // + inline const Vector3 operator *( const Vector3 & vec ) const; + + // Multiply a 3x4 transformation matrix by a 3-D point + // + inline const Point3 operator *( const Point3 & pnt ) const; + + // Multiply two 3x4 transformation matrices + // + inline const Transform3 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Transform3 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 3x4 transformation matrix + // + static inline const Transform3 identity( ); + + // Construct a 3x4 transformation matrix to rotate around the x axis + // + static inline const Transform3 rotationX( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis + // + static inline const Transform3 rotationY( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis + // + static inline const Transform3 rotationZ( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + // + static inline const Transform3 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + // + static inline const Transform3 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Transform3 rotation( const Quat & unitQuat ); + + // Construct a 3x4 transformation matrix to perform scaling + // + static inline const Transform3 scale( const Vector3 & scaleVec ); + + // Construct a 3x4 transformation matrix to perform translation + // + static inline const Transform3 translation( const Vector3 & translateVec ); + +}; +// Append (post-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ); + +// Multiply two 3x4 transformation matrices per element +// +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); + +// Compute the absolute value of a 3x4 transformation matrix per element +// +inline const Transform3 absPerElem( const Transform3 & tfrm ); + +// Inverse of a 3x4 transformation matrix +// NOTE: +// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. +// +inline const Transform3 inverse( const Transform3 & tfrm ); + +// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. +// +inline const Transform3 orthoInverse( const Transform3 & tfrm ); + +// Conditionally select between two 3x4 transformation matrices +// +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x4 transformation matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm ); + +// Print a 3x4 transformation matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm, const char * name ); + +#endif + +} // namespace Aos +} // namespace Vectormath + +#include "vec_aos.h" +#include "quat_aos.h" +#include "mat_aos.h" + +#endif diff --git a/Extras/PhysicsEffects/physics_effects_license.txt b/Extras/PhysicsEffects/physics_effects_license.txt new file mode 100644 index 0000000..7921937 --- /dev/null +++ b/Extras/PhysicsEffects/physics_effects_license.txt @@ -0,0 +1,10 @@ +Copyright (c) 2012, Sony Computer Entertainment Inc. +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 Sony Computer Entertainment Inc. 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 HOLDER 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. diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/.classpath b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/.classpath new file mode 100644 index 0000000..98132ca --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/.classpath @@ -0,0 +1,35 @@ + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/.cproject b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/.cproject new file mode 100644 index 0000000..16eca14 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/.cproject @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/.externalToolBuilders/BuildSampleJNICode.launch b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/.externalToolBuilders/BuildSampleJNICode.launch new file mode 100644 index 0000000..381d025 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/.externalToolBuilders/BuildSampleJNICode.launch @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/.project b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/.project new file mode 100644 index 0000000..de96cd7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/.project @@ -0,0 +1,114 @@ + + + + PfxApp_1_Simple + + + PfxLibrary + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + org.eclipse.ui.externaltools.ExternalToolBuilder + auto,full,incremental, + + + LaunchConfigHandle + <project>/.externalToolBuilders/BuildSampleJNICode.launch + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + + + src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java + 1 + PFX_ROOT/project/Android/PfxApp_1_Simple/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java + + + src/pfx/renderingsupport/PhysicsEffectsRenderer.java + 1 + PFX_ROOT/project/Android/PfxApp_1_Simple/src/pfx/renderingsupport/PhysicsEffectsRenderer.java + + + src/pfx/sample1/PfxApp_1_Simple.java + 1 + PFX_ROOT/project/Android/PfxApp_1_Simple/src/pfx/sample1/PfxApp_1_Simple.java + + + + + 1305070288951 + jni + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-.svn + + + + 1305070295995 + src + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-.svn + + + + + + PFX_ROOT + $%7BPARENT-3-PROJECT_LOC%7D + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/AndroidManifest.xml b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/AndroidManifest.xml new file mode 100644 index 0000000..f62261f --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/AndroidManifest.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/build.xml b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/build.xml new file mode 100644 index 0000000..83988f3 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/build.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/default.properties b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/default.properties new file mode 100644 index 0000000..f4b4f17 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/default.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-9 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/jni/Android.mk b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/jni/Android.mk new file mode 100644 index 0000000..5560e77 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/jni/Android.mk @@ -0,0 +1,138 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +# NOTE: The local path here is defined based on an environment +# variable that points to the root of the Bullet/PhysicsEffects +# code base. The variable must be set in the Cygwin style, e.g., +# BULLET_PFX_ROOT_CYGWIN = /cygdrive/d/tools/PhysicsEffectsRootPath +# +# The reason for *not* just setting local path := $(call my-dir) +# is that we wish to access local source files that are *not* +# located in a "jni" subfolder and *not* located in a subfolder +# of the project folder. This enables us to have Eclipse and +# Android NDK projects that fit neatly into the Bullet/PhysicsEffects +# folder structure, enabling a multi platform code base, without +# forcing the "jni" and subfolder structure that Android SDK/NDK +# prefer for pure Android projects. +LOCAL_PATH:= $(BULLET_PFX_ROOT_CYGWIN) + +# Copy the shared static library, libpfxlibrary.a, into the build +include $(CLEAR_VARS) +LOCAL_MODULE := pfxlibrary +LOCAL_SRC_FILES := project/Android/PfxLibrary/obj/local/armeabi-v7a/libpfxlibrary.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +# Warning: do not enable SIMD vector math functions or NEON for running +# in the Android NDK emulator. NEON requires a physical device +# with NEON support. +# +# Note that in theory we can let LOCAL_ARM_NEON := true determine +# that the flags -mfpu=neon and -mfloat-abi=softfp should be applied. +# However, in practice we have seen one case where the ndk-build +# script "forgets" these flags for the occasional *.cpp file, thus +# causing those files to access the std definition of vectormath +# classes, which are completely different, including different size. +# So, we explicitly apply these flags to avoid having a broken +# build. +# +# Include -DSCE_PFX_USE_SIMD_VECTORMATH to build for ARM NEON SIMD +# intrinsics, and leave it off to use NEON for scalar math but without +# SIMD. + +LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -mfpu=neon -mfloat-abi=softfp -DSCE_PFX_USE_SIMD_VECTORMATH +# add the following #define to run standalone NEON speedup potential tests +# -DTEST_NEON_PERFORMANCE +# + +# apply these flags if needed +# -ffast-math -funsafe-math-optimizations + +# apply this to disable optimization +# TARGET_CFLAGS := $(TARGET_CFLAGS) -O0 + +# apply these 2 to turn on assembly output (*.c/*.cpp to *.s file) +# compile-cpp-source = $(eval $(call ev-compile-cpp-source,$1,$(1:%$(LOCAL_CPP_EXTENSION)=%.s))) +# TARGET_CFLAGS := $(TARGET_CFLAGS) -S + +# specify static libraries to link in +LOCAL_STATIC_LIBRARIES := pfxlibrary cpufeatures + +# Enable or disable NEON. Don't forget to apply, or not apply, -mfpu=neon and -mfloat-abi=softfp +# flags in addition, e.g., if this is true both of those need to be included in LOCAL_CFLAGS +# to avoid the possibility that ndk-build will "forget" to add them on some files +LOCAL_ARM_NEON := true +TARGET_CFLAGS := $(filter-out -ffpu=vfp,$(TARGET_CFLAGS)) + +LOCAL_MODULE := PfxApp_1_Simple +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include \ + $(LOCAL_PATH)sample/api_physics_effects/1_simple \ + $(LOCAL_PATH)sample/api_physics_effects/common \ + $(LOCAL_PATH)sample/test_ARM_NEON_performance + +# +# The source files located in the test_ARM_NEON_performance folder are used +# to test the potential performance improvements of atomic vector math +# functions using ARM NEON instructions. Note that these are tested outside +# of the vectormath library, to avoid the overhead associated with that +# library. The assembly files contain pure NEON assembly code. +# +# The test_neon_solve_linear_constraint_row.cpp is not an atomic vector +# math operation. Rather it is a NEON assembly implementation of one of the +# leaf functions in the physics effects low level constraint solver. +# +LOCAL_SRC_FILES := \ + sample/api_physics_effects/common/jni/physicseffects-android.cpp \ + sample/api_physics_effects/1_simple/main.cpp \ + sample/api_physics_effects/1_simple/physics_func.cpp \ + sample/api_physics_effects/common/ctrl_func.android.cpp \ + sample/api_physics_effects/common/render_func.android.cpp \ + sample/api_physics_effects/common/perf_func.android.cpp \ + sample/test_ARM_NEON_performance/neon_dot_product.S \ + sample/test_ARM_NEON_performance/neon_cross_product.S \ + sample/test_ARM_NEON_performance/neon_matrix4_operator_multiply.S \ + sample/test_ARM_NEON_performance/neon_matrix3_operator_multiply.S \ + sample/test_ARM_NEON_performance/neon_orthoInverse_transform3.S \ + sample/test_ARM_NEON_performance/neon_transform3_operator_multiply.S \ + sample/test_ARM_NEON_performance/neon_transpose_matrix3.S \ + sample/test_ARM_NEON_performance/test_neon_cross_product.cpp \ + sample/test_ARM_NEON_performance/test_neon_dot_product.cpp \ + sample/test_ARM_NEON_performance/test_neon_matrix3_operator_multiply.cpp \ + sample/test_ARM_NEON_performance/test_neon_matrix4_operator_multiply.cpp \ + sample/test_ARM_NEON_performance/test_neon_orthoInverse_transform3.cpp \ + sample/test_ARM_NEON_performance/test_neon_transform3_operator_multiply.cpp \ + sample/test_ARM_NEON_performance/test_neon_transpose_matrix3.cpp \ + sample/test_ARM_NEON_performance/test_neon_solve_linear_constraint_row.cpp + +LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -lGLESv1_CM -ldl -lm -llog + +include $(BUILD_SHARED_LIBRARY) + +$(call import-module,android/cpufeatures) + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/jni/Application.mk b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/jni/Application.mk new file mode 100644 index 0000000..2fb23fb --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/jni/Application.mk @@ -0,0 +1,31 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +APP_MODULES := PfxApp_1_Simple +APP_ABI := armeabi-v7a +APP_OPTIM := release diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/local.properties b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/local.properties new file mode 100644 index 0000000..1659ad7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/local.properties @@ -0,0 +1,10 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must *NOT* be checked in Version Control Systems, +# as it contains information specific to your local configuration. + +# location of the SDK. This is only used by Ant +# For customization when using a Version Control System, please read the +# header note. +sdk.dir=F:\\sdks\\Android\\android-sdk diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/proguard.cfg b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/proguard.cfg new file mode 100644 index 0000000..3e84fc7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/proguard.cfg @@ -0,0 +1,36 @@ +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-verbose +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class com.android.vending.licensing.ILicensingService + +-keepclasseswithmembernames class * { + native ; +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/res/drawable-hdpi/icon.png b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/res/drawable-hdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d7753923a3b4ffcb78aceccf782760aa08e7f483 GIT binary patch literal 2472 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 literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/res/drawable-mdpi/icon.png b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/res/drawable-mdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ff7be820f80a465e3be8bd4d46ebd63fe9392682 GIT binary patch literal 1511 zcmVWdKxYbs#b^AWC&?ATls9F(5HEIyE^uGBF@6Ff}kR!;(A100007bV*G` z2ipe~6$LCbh{VhQ000SaNLh0L01m?d01m?e$8V@)00004XF*Lt006O%3;baP000F( zNklr>ESsv@Mi|liH?#%9%QkxJB zVwyeKOwPS??!CYJKWFZ~IO#(X#-(^dZ0fFx(d@gk*dP%*o69dY!d#01#eiZ!F`&h^ z7*Gu8QBC!LzL^R1Uc|t4IQvJYB#YI`+csnQ9vIUeJ5VTy&d>2v4ZP#v;PIp6II@y( za_8mzw0F3|*RY`mf@VR1W~D3?!1Y(rbO=61Lw5Qm?l^F@8$~D3)Z;jQT+ptgJha-4-15`Xt zY==h4Ed}&`h5m+x1B%qpuct^9#r@(IYMa^8B{{fp7;kJwo&^X-he&8SDP>j6nTVU$ za`OZV`O*Jvw5wxCSr(RfwoKlN<#_&MSe^kNrVoasPfvd$$%&IBDJ?B+S+K3peUSz5 zJOnjVTBvjo=&EK-_R@kEqoqW|mK=>}Nfv7`9Sp;Zi5}x7k9(mlI2$QY0(nUno zH%MAFdlNK|*=!mg9}g=gNxqB}J6F99F&vjTv#t5cS~2hn7kPqKOPk;qFruqB0;FGQvW@ zjT_Z?;WMZW(J_9%e_~=Hny=~UX~8vw&hJ>=u+rhdtK||=u5nPsvFf3OszlkBo1&I+ z3nB|9{ph8Rj{s3IW>?|2Q_30zX=op0PS-Fb4qR^?{%l12(&(n8l;XihTaE6t>& zBt7m;j@k4&9i`IkcFWtLaL%CDljE88guFqcQAhst)IFcip-iJvsRBWNm_|^WmX~sW zKlW>1XKxxIw#J^dD4@J+*im%m7JJR+>FO;=YJ<FL?Oe}6+mLs3x?Ek-~jLuO{C z)9Gw)Z;t{IL1krSM@I)qNE@iDtINp9sI9F%c<^9-eLba&Dzdt|n#m%4nez}o$B^cU ziHY>^2LgeVl$5ctF>>hnH zBY}NBAL&g;iN#{U+1!T&S}2SCJ`@9r0mXn8-(o;9p#L2Z_oV$j^%s51@w8w`n1uiU N002ovPDHLkV1lSs(@g*X literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/res/layout/main.xml b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/res/layout/main.xml new file mode 100644 index 0000000..6c06966 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/res/layout/main.xml @@ -0,0 +1,34 @@ + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/res/values/strings.xml b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/res/values/strings.xml new file mode 100644 index 0000000..2310f13 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/res/values/strings.xml @@ -0,0 +1,31 @@ + + + + Pfx 1 Simple + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java new file mode 100644 index 0000000..ec83e64 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java @@ -0,0 +1,113 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.renderingsupport; + +import android.opengl.GLSurfaceView; +import android.content.Context; +import android.view.MotionEvent; + +/** + * Implementation of the OpenGL ES view window and creates/assigns a renderer. + * Handles touch events to allow the user to change scene on tap, move the camera + * around by touch based movement, and allows the user to zoom in and out by pinching. + * @author ahamilton + * + */ +public class PhysicsEffectsGLSurfaceView extends GLSurfaceView { + public PhysicsEffectsGLSurfaceView(Context context) { + super(context); + peRenderer = new PhysicsEffectsRenderer(); + setRenderer(peRenderer); + } + + float x1 = 0, x2, y1 = 0, y2; + long downTime; + + /** + * Function to process touch events for camera and scene control + * + */ + public boolean onTouchEvent(final MotionEvent event) { + switch(event.getAction()) { + case(MotionEvent.ACTION_DOWN): + x1 = event.getX(); + y1 = event.getY(); + downTime = event.getDownTime(); + break; + case(MotionEvent.ACTION_UP): + if(event.getEventTime() - downTime < 100) nativeSceneChange(); + break; + case(MotionEvent.ACTION_MOVE): { + if(event.getPointerCount() == 1){ + x2 = event.getX(); + y2 = event.getY(); + float dx = x2-x1; + float dy = y2-y1; + + // Use dx and dy to determine the direction + if(dx > 0) { + nativeCameraLeft(); + } else { + nativeCameraRight(); + } + if(dy > 0){ + nativeCameraUp(); + } else { + nativeCameraDown(); + } + x1=x2; + y1=y2; + } else if(event.getPointerCount() == 2){ + y2 = event.getY(); + + float dy = y2-y1; + + // Use dy to determine zoom + if(dy > 0){ + nativeCameraZoomIn(); + } else { + nativeCameraZoomOut(); + } + y1=y2; + } + } + } + return true; + } + + PhysicsEffectsRenderer peRenderer; + + private static native void nativeCameraUp(); + private static native void nativeCameraDown(); + private static native void nativeCameraLeft(); + private static native void nativeCameraRight(); + private static native void nativeCameraZoomOut(); + private static native void nativeCameraZoomIn(); + private static native void nativeSceneChange(); +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/src/pfx/renderingsupport/PhysicsEffectsRenderer.java b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/src/pfx/renderingsupport/PhysicsEffectsRenderer.java new file mode 100644 index 0000000..5ca66d4 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/src/pfx/renderingsupport/PhysicsEffectsRenderer.java @@ -0,0 +1,101 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.renderingsupport; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLSurfaceView; +import android.util.Log; + +/** + * Implementation of the renderer. It calls the native physicseffects code + * to run on the init and drawframe allowing the sample to perform its simulation. + * @author ahamilton + * + */ +public class PhysicsEffectsRenderer implements GLSurfaceView.Renderer { + boolean startup = true; + boolean notEnded = true; + static long startuptime; + static long endtime; + int frameCounter; + + /** + * Initilize the physics simulation after the GL surface is created. + * + */ + public void onSurfaceCreated(GL10 gl, EGLConfig config) + { + Log.v("Init physics", "Initing physics"); + nativePhysicsEffectsInit(); + Log.v("Init physics", "Inited physics"); + } + + /** + * Set the viewport for a changed GL surface + * + */ + public void onSurfaceChanged(GL10 gl, int w, int h) + { + gl.glViewport(0, 0, w, h); + } + + /** + * Perform one simulation step and render the scene. + * + */ + public void onDrawFrame(GL10 gl) + { + if(startup){ + startup = false; + frameCounter = 0; + startuptime = System.currentTimeMillis(); + endtime = startuptime + 10000; // sets run time to be 30 seconds + } + + nativePhysicsEffectsSimulate(); + + frameCounter++; + long lCurrentTime = System.currentTimeMillis(); + if(lCurrentTime > endtime && notEnded) { + float fFrameRate = (1000.0f * (float)frameCounter) / ((float)lCurrentTime - startuptime); + Log.v("PHYSICS TIMING STUDY", "Number of Frames: " + Integer.toString(frameCounter)); + Log.v("PHYSICS TIMING STUDY", "Time ellapsed (milliseconds): " + Long.toString(lCurrentTime - startuptime)); + Log.v("PHYSICS TIMING STUDY", "Bullet Frame Rate: " + Float.toString(fFrameRate) + "fps"); + notEnded = false; + } + } + + private static native void nativePhysicsEffectsInit(); + private static native void nativePhysicsEffectsSimulate(); + private static native void nativePhysicsEffectsUpdate(); + private static native void nativePhysicsEffectsPhysStep(); + private static native void nativePhysicsEffectsRender(); +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/src/pfx/sample1/PfxApp_1_Simple.java b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/src/pfx/sample1/PfxApp_1_Simple.java new file mode 100644 index 0000000..00782cd --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple/src/pfx/sample1/PfxApp_1_Simple.java @@ -0,0 +1,64 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.sample1; + +import pfx.renderingsupport.PhysicsEffectsGLSurfaceView; + +import android.app.Activity; +import android.opengl.GLSurfaceView; +import android.os.Bundle; +import android.util.Log; + +/** + * When program loads it creates a OpenGl ES render window for + * the physics effects sample projects to run in and loads the complied + * physics effects libraries. + * @author ahamilton + * + */ +public class PfxApp_1_Simple extends Activity +{ + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + peGLView = new PhysicsEffectsGLSurfaceView(this); + setContentView(peGLView); + int numprocessors = Runtime.getRuntime().availableProcessors(); + Log.v("PFX THREADING", "Number of Processors: " + Integer.toString(numprocessors)); + } + + private GLSurfaceView peGLView; + + // This is where you specify which physics effects sample you would like to load + static + { + System.loadLibrary("PfxApp_1_Simple"); + } +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/.classpath b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/.classpath new file mode 100644 index 0000000..98132ca --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/.classpath @@ -0,0 +1,35 @@ + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/.cproject b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/.cproject new file mode 100644 index 0000000..9ac8cbd --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/.cproject @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/.externalToolBuilders/BuildSampleJNICode.launch b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/.externalToolBuilders/BuildSampleJNICode.launch new file mode 100644 index 0000000..c8e7d6c --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/.externalToolBuilders/BuildSampleJNICode.launch @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/.project b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/.project new file mode 100644 index 0000000..d8a9d61 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/.project @@ -0,0 +1,114 @@ + + + + PfxApp_1_Simple_Parallel + + + PfxLibrary + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + org.eclipse.ui.externaltools.ExternalToolBuilder + auto,full,incremental, + + + LaunchConfigHandle + <project>/.externalToolBuilders/BuildSampleJNICode.launch + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + + + src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java + 1 + PFX_ROOT/project/Android/PfxApp_1_Simple_Parallel/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java + + + src/pfx/renderingsupport/PhysicsEffectsRenderer.java + 1 + PFX_ROOT/project/Android/PfxApp_1_Simple_Parallel/src/pfx/renderingsupport/PhysicsEffectsRenderer.java + + + src/pfx/sample1b/PfxApp_1_Simple_Parallel.java + 1 + PFX_ROOT/project/Android/PfxApp_1_Simple_Parallel/src/pfx/sample1b/PfxApp_1_Simple_Parallel.java + + + + + 1305070288951 + jni + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-.svn + + + + 1305070295995 + src + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-.svn + + + + + + PFX_ROOT + $%7BPARENT-3-PROJECT_LOC%7D + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/AndroidManifest.xml b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/AndroidManifest.xml new file mode 100644 index 0000000..416b892 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/AndroidManifest.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/build.xml b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/build.xml new file mode 100644 index 0000000..0839f70 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/build.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/default.properties b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/default.properties new file mode 100644 index 0000000..f4b4f17 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/default.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-9 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/jni/Android.mk b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/jni/Android.mk new file mode 100644 index 0000000..21bb098 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/jni/Android.mk @@ -0,0 +1,109 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +# NOTE: The local path here is defined based on an environment +# variable that points to the root of the Bullet/PhysicsEffects +# code base. The variable must be set in the Cygwin style, e.g., +# BULLET_PFX_ROOT_CYGWIN = /cygdrive/d/tools/PhysicsEffectsRootPath +# +# The reason for *not* just setting local path := $(call my-dir) +# is that we wish to access local source files that are *not* +# located in a "jni" subfolder and *not* located in a subfolder +# of the project folder. This enables us to have Eclipse and +# Android NDK projects that fit neatly into the Bullet/PhysicsEffects +# folder structure, enabling a multi platform code base, without +# forcing the "jni" and subfolder structure that Android SDK/NDK +# prefer for pure Android projects. +LOCAL_PATH:= $(BULLET_PFX_ROOT_CYGWIN) + +# Copy the shared static library, libpfxlibrary.a, into the build +include $(CLEAR_VARS) +LOCAL_MODULE := pfxlibrary +LOCAL_SRC_FILES := project/Android/PfxLibrary/obj/local/armeabi-v7a/libpfxlibrary.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +# Warning: do not enable SIMD vector math functions or NEON for running +# in the Android NDK emulator. NEON requires a physical device +# with NEON support. +# +# Note that in theory we can let LOCAL_ARM_NEON := true determine +# that the flags -mfpu=neon and -mfloat-abi=softfp should be applied. +# However, in practice we have seen one case where the ndk-build +# script "forgets" these flags for the occasional *.cpp file, thus +# causing those files to access the std definition of vectormath +# classes, which are completely different, including different size. +# So, we explicitly apply these flags to avoid having a broken +# build. +# +# Include -DSCE_PFX_USE_SIMD_VECTORMATH to build for ARM NEON SIMD +# intrinsics, and leave it off to use NEON for scalar math but without +# SIMD. + +LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -DUSE_PTHREADS -mfpu=neon -mfloat-abi=softfp -pthread -DSCE_PFX_USE_SIMD_VECTORMATH + +# apply these flags if needed +# -ffast-math -funsafe-math-optimizations + +# apply this to disable optimization +# TARGET_CFLAGS := $(TARGET_CFLAGS) -O0 + +# apply these 2 to turn on assembly output (*.c/*.cpp to *.s file) +# compile-cpp-source = $(eval $(call ev-compile-cpp-source,$1,$(1:%$(LOCAL_CPP_EXTENSION)=%.s))) +# TARGET_CFLAGS := $(TARGET_CFLAGS) -S + +# specify static libraries to link in +LOCAL_STATIC_LIBRARIES := pfxlibrary cpufeatures + +# Enable or disable NEON. Don't forget to apply, or not apply, -mfpu=neon and -mfloat-abi=softfp +# flags in addition, e.g., if this is true both of those need to be included in LOCAL_CFLAGS +# to avoid the possibility that ndk-build will "forget" to add them on some files +LOCAL_ARM_NEON := true +TARGET_CFLAGS := $(filter-out -ffpu=vfp,$(TARGET_CFLAGS)) + +LOCAL_MODULE := PfxApp_1_Simple_Parallel +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include \ + $(LOCAL_PATH)sample/api_physics_effects/1_simple_parallel \ + $(LOCAL_PATH)sample/api_physics_effects/common \ + $(LOCAL_PATH)sample/test_ARM_NEON_performance + +LOCAL_SRC_FILES := \ + sample/api_physics_effects/common/jni/physicseffects-android.cpp \ + sample/api_physics_effects/1_simple_parallel/main.cpp \ + sample/api_physics_effects/1_simple_parallel/physics_func.cpp \ + sample/api_physics_effects/common/ctrl_func.android.cpp \ + sample/api_physics_effects/common/render_func.android.cpp \ + sample/api_physics_effects/common/perf_func.android.cpp + +LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -lGLESv1_CM -ldl -lm -llog + +include $(BUILD_SHARED_LIBRARY) + +$(call import-module,android/cpufeatures) + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/jni/Application.mk b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/jni/Application.mk new file mode 100644 index 0000000..0187aba --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/jni/Application.mk @@ -0,0 +1,31 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +APP_MODULES := PfxApp_1_Simple_Parallel +APP_ABI := armeabi-v7a +APP_OPTIM := release diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/local.properties b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/local.properties new file mode 100644 index 0000000..1659ad7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/local.properties @@ -0,0 +1,10 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must *NOT* be checked in Version Control Systems, +# as it contains information specific to your local configuration. + +# location of the SDK. This is only used by Ant +# For customization when using a Version Control System, please read the +# header note. +sdk.dir=F:\\sdks\\Android\\android-sdk diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/proguard.cfg b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/proguard.cfg new file mode 100644 index 0000000..3e84fc7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/proguard.cfg @@ -0,0 +1,36 @@ +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-verbose +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class com.android.vending.licensing.ILicensingService + +-keepclasseswithmembernames class * { + native ; +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/res/drawable-hdpi/icon.png b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/res/drawable-hdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d7753923a3b4ffcb78aceccf782760aa08e7f483 GIT binary patch literal 2472 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 literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/res/drawable-mdpi/icon.png b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/res/drawable-mdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ff7be820f80a465e3be8bd4d46ebd63fe9392682 GIT binary patch literal 1511 zcmVWdKxYbs#b^AWC&?ATls9F(5HEIyE^uGBF@6Ff}kR!;(A100007bV*G` z2ipe~6$LCbh{VhQ000SaNLh0L01m?d01m?e$8V@)00004XF*Lt006O%3;baP000F( zNklr>ESsv@Mi|liH?#%9%QkxJB zVwyeKOwPS??!CYJKWFZ~IO#(X#-(^dZ0fFx(d@gk*dP%*o69dY!d#01#eiZ!F`&h^ z7*Gu8QBC!LzL^R1Uc|t4IQvJYB#YI`+csnQ9vIUeJ5VTy&d>2v4ZP#v;PIp6II@y( za_8mzw0F3|*RY`mf@VR1W~D3?!1Y(rbO=61Lw5Qm?l^F@8$~D3)Z;jQT+ptgJha-4-15`Xt zY==h4Ed}&`h5m+x1B%qpuct^9#r@(IYMa^8B{{fp7;kJwo&^X-he&8SDP>j6nTVU$ za`OZV`O*Jvw5wxCSr(RfwoKlN<#_&MSe^kNrVoasPfvd$$%&IBDJ?B+S+K3peUSz5 zJOnjVTBvjo=&EK-_R@kEqoqW|mK=>}Nfv7`9Sp;Zi5}x7k9(mlI2$QY0(nUno zH%MAFdlNK|*=!mg9}g=gNxqB}J6F99F&vjTv#t5cS~2hn7kPqKOPk;qFruqB0;FGQvW@ zjT_Z?;WMZW(J_9%e_~=Hny=~UX~8vw&hJ>=u+rhdtK||=u5nPsvFf3OszlkBo1&I+ z3nB|9{ph8Rj{s3IW>?|2Q_30zX=op0PS-Fb4qR^?{%l12(&(n8l;XihTaE6t>& zBt7m;j@k4&9i`IkcFWtLaL%CDljE88guFqcQAhst)IFcip-iJvsRBWNm_|^WmX~sW zKlW>1XKxxIw#J^dD4@J+*im%m7JJR+>FO;=YJ<FL?Oe}6+mLs3x?Ek-~jLuO{C z)9Gw)Z;t{IL1krSM@I)qNE@iDtINp9sI9F%c<^9-eLba&Dzdt|n#m%4nez}o$B^cU ziHY>^2LgeVl$5ctF>>hnH zBY}NBAL&g;iN#{U+1!T&S}2SCJ`@9r0mXn8-(o;9p#L2Z_oV$j^%s51@w8w`n1uiU N002ovPDHLkV1lSs(@g*X literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/res/layout/main.xml b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/res/layout/main.xml new file mode 100644 index 0000000..6c06966 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/res/layout/main.xml @@ -0,0 +1,34 @@ + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/res/values/strings.xml b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/res/values/strings.xml new file mode 100644 index 0000000..945bf6f --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/res/values/strings.xml @@ -0,0 +1,31 @@ + + + + Pfx 1 Simple Parallel + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java new file mode 100644 index 0000000..ec83e64 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java @@ -0,0 +1,113 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.renderingsupport; + +import android.opengl.GLSurfaceView; +import android.content.Context; +import android.view.MotionEvent; + +/** + * Implementation of the OpenGL ES view window and creates/assigns a renderer. + * Handles touch events to allow the user to change scene on tap, move the camera + * around by touch based movement, and allows the user to zoom in and out by pinching. + * @author ahamilton + * + */ +public class PhysicsEffectsGLSurfaceView extends GLSurfaceView { + public PhysicsEffectsGLSurfaceView(Context context) { + super(context); + peRenderer = new PhysicsEffectsRenderer(); + setRenderer(peRenderer); + } + + float x1 = 0, x2, y1 = 0, y2; + long downTime; + + /** + * Function to process touch events for camera and scene control + * + */ + public boolean onTouchEvent(final MotionEvent event) { + switch(event.getAction()) { + case(MotionEvent.ACTION_DOWN): + x1 = event.getX(); + y1 = event.getY(); + downTime = event.getDownTime(); + break; + case(MotionEvent.ACTION_UP): + if(event.getEventTime() - downTime < 100) nativeSceneChange(); + break; + case(MotionEvent.ACTION_MOVE): { + if(event.getPointerCount() == 1){ + x2 = event.getX(); + y2 = event.getY(); + float dx = x2-x1; + float dy = y2-y1; + + // Use dx and dy to determine the direction + if(dx > 0) { + nativeCameraLeft(); + } else { + nativeCameraRight(); + } + if(dy > 0){ + nativeCameraUp(); + } else { + nativeCameraDown(); + } + x1=x2; + y1=y2; + } else if(event.getPointerCount() == 2){ + y2 = event.getY(); + + float dy = y2-y1; + + // Use dy to determine zoom + if(dy > 0){ + nativeCameraZoomIn(); + } else { + nativeCameraZoomOut(); + } + y1=y2; + } + } + } + return true; + } + + PhysicsEffectsRenderer peRenderer; + + private static native void nativeCameraUp(); + private static native void nativeCameraDown(); + private static native void nativeCameraLeft(); + private static native void nativeCameraRight(); + private static native void nativeCameraZoomOut(); + private static native void nativeCameraZoomIn(); + private static native void nativeSceneChange(); +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/src/pfx/renderingsupport/PhysicsEffectsRenderer.java b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/src/pfx/renderingsupport/PhysicsEffectsRenderer.java new file mode 100644 index 0000000..5ca66d4 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/src/pfx/renderingsupport/PhysicsEffectsRenderer.java @@ -0,0 +1,101 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.renderingsupport; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLSurfaceView; +import android.util.Log; + +/** + * Implementation of the renderer. It calls the native physicseffects code + * to run on the init and drawframe allowing the sample to perform its simulation. + * @author ahamilton + * + */ +public class PhysicsEffectsRenderer implements GLSurfaceView.Renderer { + boolean startup = true; + boolean notEnded = true; + static long startuptime; + static long endtime; + int frameCounter; + + /** + * Initilize the physics simulation after the GL surface is created. + * + */ + public void onSurfaceCreated(GL10 gl, EGLConfig config) + { + Log.v("Init physics", "Initing physics"); + nativePhysicsEffectsInit(); + Log.v("Init physics", "Inited physics"); + } + + /** + * Set the viewport for a changed GL surface + * + */ + public void onSurfaceChanged(GL10 gl, int w, int h) + { + gl.glViewport(0, 0, w, h); + } + + /** + * Perform one simulation step and render the scene. + * + */ + public void onDrawFrame(GL10 gl) + { + if(startup){ + startup = false; + frameCounter = 0; + startuptime = System.currentTimeMillis(); + endtime = startuptime + 10000; // sets run time to be 30 seconds + } + + nativePhysicsEffectsSimulate(); + + frameCounter++; + long lCurrentTime = System.currentTimeMillis(); + if(lCurrentTime > endtime && notEnded) { + float fFrameRate = (1000.0f * (float)frameCounter) / ((float)lCurrentTime - startuptime); + Log.v("PHYSICS TIMING STUDY", "Number of Frames: " + Integer.toString(frameCounter)); + Log.v("PHYSICS TIMING STUDY", "Time ellapsed (milliseconds): " + Long.toString(lCurrentTime - startuptime)); + Log.v("PHYSICS TIMING STUDY", "Bullet Frame Rate: " + Float.toString(fFrameRate) + "fps"); + notEnded = false; + } + } + + private static native void nativePhysicsEffectsInit(); + private static native void nativePhysicsEffectsSimulate(); + private static native void nativePhysicsEffectsUpdate(); + private static native void nativePhysicsEffectsPhysStep(); + private static native void nativePhysicsEffectsRender(); +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/src/pfx/sample1b/PfxApp_1_Simple_Parallel.java b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/src/pfx/sample1b/PfxApp_1_Simple_Parallel.java new file mode 100644 index 0000000..d73eba4 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_1_Simple_Parallel/src/pfx/sample1b/PfxApp_1_Simple_Parallel.java @@ -0,0 +1,64 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.sample1b; + +import pfx.renderingsupport.PhysicsEffectsGLSurfaceView; + +import android.app.Activity; +import android.opengl.GLSurfaceView; +import android.os.Bundle; +import android.util.Log; + +/** + * When program loads it creates a OpenGl ES render window for + * the physics effects sample projects to run in and loads the complied + * physics effects libraries. + * @author ahamilton + * + */ +public class PfxApp_1_Simple_Parallel extends Activity +{ + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + peGLView = new PhysicsEffectsGLSurfaceView(this); + setContentView(peGLView); + int numprocessors = Runtime.getRuntime().availableProcessors(); + Log.v("PFX THREADING", "Number of Processors: " + Integer.toString(numprocessors)); + } + + private GLSurfaceView peGLView; + + // This is where you specify which physics effects sample you would like to load + static + { + System.loadLibrary("PfxApp_1_Simple_Parallel"); + } +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/.classpath b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/.classpath new file mode 100644 index 0000000..98132ca --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/.classpath @@ -0,0 +1,35 @@ + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/.externalToolBuilders/BuildSampleJNICode.launch b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/.externalToolBuilders/BuildSampleJNICode.launch new file mode 100644 index 0000000..8c0ed39 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/.externalToolBuilders/BuildSampleJNICode.launch @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/.project b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/.project new file mode 100644 index 0000000..a45e125 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/.project @@ -0,0 +1,114 @@ + + + + PfxApp_2_Stable + + + PfxLibrary + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + org.eclipse.ui.externaltools.ExternalToolBuilder + auto,full,incremental, + + + LaunchConfigHandle + <project>/.externalToolBuilders/BuildSampleJNICode.launch + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + + + src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java + 1 + PFX_ROOT/project/Android/PfxApp_2_Stable/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java + + + src/pfx/renderingsupport/PhysicsEffectsRenderer.java + 1 + PFX_ROOT/project/Android/PfxApp_2_Stable/src/pfx/renderingsupport/PhysicsEffectsRenderer.java + + + src/pfx/sample2/PfxApp_2_Stable.java + 1 + PFX_ROOT/project/Android/PfxApp_2_Stable/src/pfx/sample/PfxApp_2_Stable.java + + + + + 1305070288951 + jni + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-.svn + + + + 1305070295995 + src + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-.svn + + + + + + PFX_ROOT + $%7BPARENT-3-PROJECT_LOC%7D + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/AndroidManifest.xml b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/AndroidManifest.xml new file mode 100644 index 0000000..fbb3335 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/AndroidManifest.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/build.xml b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/build.xml new file mode 100644 index 0000000..45b1ef6 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/build.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/default.properties b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/default.properties new file mode 100644 index 0000000..25c0280 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/default.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-10 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/jni/Android.mk b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/jni/Android.mk new file mode 100644 index 0000000..4a5175d --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/jni/Android.mk @@ -0,0 +1,107 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +# NOTE: The local path here is defined based on an environment +# variable that points to the root of the Bullet/PhysicsEffects +# code base. The variable must be set in the Cygwin style, e.g., +# BULLET_PFX_ROOT_CYGWIN = /cygdrive/d/tools/PhysicsEffectsRootPath +# +# The reason for *not* just setting local path := $(call my-dir) +# is that we wish to access local source files that are *not* +# located in a "jni" subfolder and *not* located in a subfolder +# of the project folder. This enables us to have Eclipse and +# Android NDK projects that fit neatly into the Bullet/PhysicsEffects +# folder structure, enabling a multi platform code base, without +# forcing the "jni" and subfolder structure that Android SDK/NDK +# prefer for pure Android projects. +LOCAL_PATH:= $(BULLET_PFX_ROOT_CYGWIN) + +# Copy the shared static library, libpfxlibrary.a, into the build +include $(CLEAR_VARS) +LOCAL_MODULE := pfxlibrary +LOCAL_SRC_FILES := project/Android/PfxLibrary/obj/local/armeabi-v7a/libpfxlibrary.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +# Warning: do not enable SIMD vector math functions or NEON for running +# in the Android NDK emulator. NEON requires a physical device +# with NEON support. +# +# Note that in theory we can let LOCAL_ARM_NEON := true determine +# that the flags -mfpu=neon and -mfloat-abi=softfp should be applied. +# However, in practice we have seen one case where the ndk-build +# script "forgets" these flags for the occasional *.cpp file, thus +# causing those files to access the std definition of vectormath +# classes, which are completely different, including different size. +# So, we explicitly apply these flags to avoid having a broken +# build. +# +# Include -DSCE_PFX_USE_SIMD_VECTORMATH to build for ARM NEON SIMD +# intrinsics, and leave it off to use NEON for scalar math but without +# SIMD. + +LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -mfpu=neon -mfloat-abi=softfp -DSCE_PFX_USE_SIMD_VECTORMATH + +# apply these flags if needed +# -ffast-math -funsafe-math-optimizations + +# apply this to disable optimization +# TARGET_CFLAGS := $(TARGET_CFLAGS) -O0 + +# apply these 2 to turn on assembly output (*.c/*.cpp to *.s file) +# compile-cpp-source = $(eval $(call ev-compile-cpp-source,$1,$(1:%$(LOCAL_CPP_EXTENSION)=%.s))) +# TARGET_CFLAGS := $(TARGET_CFLAGS) -S + +# specify static libraries to link in +LOCAL_STATIC_LIBRARIES := pfxlibrary + +# Enable or disable NEON. Don't forget to apply, or not apply, -mfpu=neon and -mfloat-abi=softfp +# flags in addition, e.g., if this is true both of those need to be included in LOCAL_CFLAGS +# to avoid the possibility that ndk-build will "forget" to add them on some files +LOCAL_ARM_NEON := true +TARGET_CFLAGS := $(filter-out -ffpu=vfp,$(TARGET_CFLAGS)) + +LOCAL_MODULE := PfxApp_2_Stable +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include \ + $(LOCAL_PATH)sample/api_physics_effects/2_stable \ + $(LOCAL_PATH)sample/api_physics_effects/common + +LOCAL_SRC_FILES := \ + sample/api_physics_effects/common/jni/physicseffects-android.cpp \ + sample/api_physics_effects/2_stable/main.cpp \ + sample/api_physics_effects/2_stable/physics_func.cpp \ + sample/api_physics_effects/common/ctrl_func.android.cpp \ + sample/api_physics_effects/common/render_func.android.cpp \ + sample/api_physics_effects/common/perf_func.android.cpp + +LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -lGLESv1_CM -ldl -lm -llog + +include $(BUILD_SHARED_LIBRARY) + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/jni/Application.mk b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/jni/Application.mk new file mode 100644 index 0000000..77151c8 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/jni/Application.mk @@ -0,0 +1,31 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +APP_MODULES := PfxApp_2_Stable +APP_ABI := armeabi-v7a +APP_OPTIM := release diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/local.properties b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/local.properties new file mode 100644 index 0000000..1659ad7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/local.properties @@ -0,0 +1,10 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must *NOT* be checked in Version Control Systems, +# as it contains information specific to your local configuration. + +# location of the SDK. This is only used by Ant +# For customization when using a Version Control System, please read the +# header note. +sdk.dir=F:\\sdks\\Android\\android-sdk diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/proguard.cfg b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/proguard.cfg new file mode 100644 index 0000000..3e84fc7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/proguard.cfg @@ -0,0 +1,36 @@ +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-verbose +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class com.android.vending.licensing.ILicensingService + +-keepclasseswithmembernames class * { + native ; +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/res/drawable-hdpi/icon.png b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/res/drawable-hdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d7753923a3b4ffcb78aceccf782760aa08e7f483 GIT binary patch literal 2472 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 literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/res/drawable-mdpi/icon.png b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/res/drawable-mdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ff7be820f80a465e3be8bd4d46ebd63fe9392682 GIT binary patch literal 1511 zcmVWdKxYbs#b^AWC&?ATls9F(5HEIyE^uGBF@6Ff}kR!;(A100007bV*G` z2ipe~6$LCbh{VhQ000SaNLh0L01m?d01m?e$8V@)00004XF*Lt006O%3;baP000F( zNklr>ESsv@Mi|liH?#%9%QkxJB zVwyeKOwPS??!CYJKWFZ~IO#(X#-(^dZ0fFx(d@gk*dP%*o69dY!d#01#eiZ!F`&h^ z7*Gu8QBC!LzL^R1Uc|t4IQvJYB#YI`+csnQ9vIUeJ5VTy&d>2v4ZP#v;PIp6II@y( za_8mzw0F3|*RY`mf@VR1W~D3?!1Y(rbO=61Lw5Qm?l^F@8$~D3)Z;jQT+ptgJha-4-15`Xt zY==h4Ed}&`h5m+x1B%qpuct^9#r@(IYMa^8B{{fp7;kJwo&^X-he&8SDP>j6nTVU$ za`OZV`O*Jvw5wxCSr(RfwoKlN<#_&MSe^kNrVoasPfvd$$%&IBDJ?B+S+K3peUSz5 zJOnjVTBvjo=&EK-_R@kEqoqW|mK=>}Nfv7`9Sp;Zi5}x7k9(mlI2$QY0(nUno zH%MAFdlNK|*=!mg9}g=gNxqB}J6F99F&vjTv#t5cS~2hn7kPqKOPk;qFruqB0;FGQvW@ zjT_Z?;WMZW(J_9%e_~=Hny=~UX~8vw&hJ>=u+rhdtK||=u5nPsvFf3OszlkBo1&I+ z3nB|9{ph8Rj{s3IW>?|2Q_30zX=op0PS-Fb4qR^?{%l12(&(n8l;XihTaE6t>& zBt7m;j@k4&9i`IkcFWtLaL%CDljE88guFqcQAhst)IFcip-iJvsRBWNm_|^WmX~sW zKlW>1XKxxIw#J^dD4@J+*im%m7JJR+>FO;=YJ<FL?Oe}6+mLs3x?Ek-~jLuO{C z)9Gw)Z;t{IL1krSM@I)qNE@iDtINp9sI9F%c<^9-eLba&Dzdt|n#m%4nez}o$B^cU ziHY>^2LgeVl$5ctF>>hnH zBY}NBAL&g;iN#{U+1!T&S}2SCJ`@9r0mXn8-(o;9p#L2Z_oV$j^%s51@w8w`n1uiU N002ovPDHLkV1lSs(@g*X literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/res/layout/main.xml b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/res/layout/main.xml new file mode 100644 index 0000000..6c06966 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/res/layout/main.xml @@ -0,0 +1,34 @@ + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/res/values/strings.xml b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/res/values/strings.xml new file mode 100644 index 0000000..e2114da --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/res/values/strings.xml @@ -0,0 +1,31 @@ + + + + Pfx 2 Stable + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java new file mode 100644 index 0000000..ec83e64 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java @@ -0,0 +1,113 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.renderingsupport; + +import android.opengl.GLSurfaceView; +import android.content.Context; +import android.view.MotionEvent; + +/** + * Implementation of the OpenGL ES view window and creates/assigns a renderer. + * Handles touch events to allow the user to change scene on tap, move the camera + * around by touch based movement, and allows the user to zoom in and out by pinching. + * @author ahamilton + * + */ +public class PhysicsEffectsGLSurfaceView extends GLSurfaceView { + public PhysicsEffectsGLSurfaceView(Context context) { + super(context); + peRenderer = new PhysicsEffectsRenderer(); + setRenderer(peRenderer); + } + + float x1 = 0, x2, y1 = 0, y2; + long downTime; + + /** + * Function to process touch events for camera and scene control + * + */ + public boolean onTouchEvent(final MotionEvent event) { + switch(event.getAction()) { + case(MotionEvent.ACTION_DOWN): + x1 = event.getX(); + y1 = event.getY(); + downTime = event.getDownTime(); + break; + case(MotionEvent.ACTION_UP): + if(event.getEventTime() - downTime < 100) nativeSceneChange(); + break; + case(MotionEvent.ACTION_MOVE): { + if(event.getPointerCount() == 1){ + x2 = event.getX(); + y2 = event.getY(); + float dx = x2-x1; + float dy = y2-y1; + + // Use dx and dy to determine the direction + if(dx > 0) { + nativeCameraLeft(); + } else { + nativeCameraRight(); + } + if(dy > 0){ + nativeCameraUp(); + } else { + nativeCameraDown(); + } + x1=x2; + y1=y2; + } else if(event.getPointerCount() == 2){ + y2 = event.getY(); + + float dy = y2-y1; + + // Use dy to determine zoom + if(dy > 0){ + nativeCameraZoomIn(); + } else { + nativeCameraZoomOut(); + } + y1=y2; + } + } + } + return true; + } + + PhysicsEffectsRenderer peRenderer; + + private static native void nativeCameraUp(); + private static native void nativeCameraDown(); + private static native void nativeCameraLeft(); + private static native void nativeCameraRight(); + private static native void nativeCameraZoomOut(); + private static native void nativeCameraZoomIn(); + private static native void nativeSceneChange(); +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/src/pfx/renderingsupport/PhysicsEffectsRenderer.java b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/src/pfx/renderingsupport/PhysicsEffectsRenderer.java new file mode 100644 index 0000000..5ca66d4 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/src/pfx/renderingsupport/PhysicsEffectsRenderer.java @@ -0,0 +1,101 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.renderingsupport; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLSurfaceView; +import android.util.Log; + +/** + * Implementation of the renderer. It calls the native physicseffects code + * to run on the init and drawframe allowing the sample to perform its simulation. + * @author ahamilton + * + */ +public class PhysicsEffectsRenderer implements GLSurfaceView.Renderer { + boolean startup = true; + boolean notEnded = true; + static long startuptime; + static long endtime; + int frameCounter; + + /** + * Initilize the physics simulation after the GL surface is created. + * + */ + public void onSurfaceCreated(GL10 gl, EGLConfig config) + { + Log.v("Init physics", "Initing physics"); + nativePhysicsEffectsInit(); + Log.v("Init physics", "Inited physics"); + } + + /** + * Set the viewport for a changed GL surface + * + */ + public void onSurfaceChanged(GL10 gl, int w, int h) + { + gl.glViewport(0, 0, w, h); + } + + /** + * Perform one simulation step and render the scene. + * + */ + public void onDrawFrame(GL10 gl) + { + if(startup){ + startup = false; + frameCounter = 0; + startuptime = System.currentTimeMillis(); + endtime = startuptime + 10000; // sets run time to be 30 seconds + } + + nativePhysicsEffectsSimulate(); + + frameCounter++; + long lCurrentTime = System.currentTimeMillis(); + if(lCurrentTime > endtime && notEnded) { + float fFrameRate = (1000.0f * (float)frameCounter) / ((float)lCurrentTime - startuptime); + Log.v("PHYSICS TIMING STUDY", "Number of Frames: " + Integer.toString(frameCounter)); + Log.v("PHYSICS TIMING STUDY", "Time ellapsed (milliseconds): " + Long.toString(lCurrentTime - startuptime)); + Log.v("PHYSICS TIMING STUDY", "Bullet Frame Rate: " + Float.toString(fFrameRate) + "fps"); + notEnded = false; + } + } + + private static native void nativePhysicsEffectsInit(); + private static native void nativePhysicsEffectsSimulate(); + private static native void nativePhysicsEffectsUpdate(); + private static native void nativePhysicsEffectsPhysStep(); + private static native void nativePhysicsEffectsRender(); +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/src/pfx/sample2/PfxApp_2_Stable.java b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/src/pfx/sample2/PfxApp_2_Stable.java new file mode 100644 index 0000000..318754e --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable/src/pfx/sample2/PfxApp_2_Stable.java @@ -0,0 +1,58 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.sample2; + +import pfx.renderingsupport.PhysicsEffectsGLSurfaceView; + +import android.app.Activity; +import android.opengl.GLSurfaceView; +import android.os.Bundle; + +/** + * When program loads it creates a OpenGl ES render window for + * the bullet sample projects to run in and loads the complied + * physics effects libraries. + * @author ahamilton + * + */ +public class PfxApp_2_Stable extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + peGLView = new PhysicsEffectsGLSurfaceView(this); + setContentView(peGLView); + } + + private GLSurfaceView peGLView; + + //This is where you specify which physics effects sample you would like to load + static { + System.loadLibrary("PfxApp_2_Stable"); + } +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/.classpath b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/.classpath new file mode 100644 index 0000000..98132ca --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/.classpath @@ -0,0 +1,35 @@ + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/.externalToolBuilders/BuildSampleJNICode.launch b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/.externalToolBuilders/BuildSampleJNICode.launch new file mode 100644 index 0000000..37635fa --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/.externalToolBuilders/BuildSampleJNICode.launch @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/.project b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/.project new file mode 100644 index 0000000..411ca1a --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/.project @@ -0,0 +1,114 @@ + + + + PfxApp_2_Stable_Parallel + + + PfxLibrary + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + org.eclipse.ui.externaltools.ExternalToolBuilder + auto,full,incremental, + + + LaunchConfigHandle + <project>/.externalToolBuilders/BuildSampleJNICode.launch + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + + + src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java + 1 + PFX_ROOT/project/Android/PfxApp_2_Stable_Parallel/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java + + + src/pfx/renderingsupport/PhysicsEffectsRenderer.java + 1 + PFX_ROOT/project/Android/PfxApp_2_Stable_Parallel/src/pfx/renderingsupport/PhysicsEffectsRenderer.java + + + src/pfx/sample2b/PfxApp_2_Stable_Parallel.java + 1 + PFX_ROOT/project/Android/PfxApp_2_Stable_Parallel/src/pfx/sample2b/PfxApp_2_Stable_Parallel.java + + + + + 1305070288951 + jni + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-.svn + + + + 1305070295995 + src + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-.svn + + + + + + PFX_ROOT + $%7BPARENT-3-PROJECT_LOC%7D + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/AndroidManifest.xml b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/AndroidManifest.xml new file mode 100644 index 0000000..ca47f66 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/AndroidManifest.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/build.xml b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/build.xml new file mode 100644 index 0000000..15bf3cb --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/build.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/default.properties b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/default.properties new file mode 100644 index 0000000..f4b4f17 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/default.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-9 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/jni/Android.mk b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/jni/Android.mk new file mode 100644 index 0000000..24cb431 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/jni/Android.mk @@ -0,0 +1,107 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +# NOTE: The local path here is defined based on an environment +# variable that points to the root of the Bullet/PhysicsEffects +# code base. The variable must be set in the Cygwin style, e.g., +# BULLET_PFX_ROOT_CYGWIN = /cygdrive/d/tools/PhysicsEffectsRootPath +# +# The reason for *not* just setting local path := $(call my-dir) +# is that we wish to access local source files that are *not* +# located in a "jni" subfolder and *not* located in a subfolder +# of the project folder. This enables us to have Eclipse and +# Android NDK projects that fit neatly into the Bullet/PhysicsEffects +# folder structure, enabling a multi platform code base, without +# forcing the "jni" and subfolder structure that Android SDK/NDK +# prefer for pure Android projects. +LOCAL_PATH:= $(BULLET_PFX_ROOT_CYGWIN) + +# Copy the shared static library, libpfxlibrary.a, into the build +include $(CLEAR_VARS) +LOCAL_MODULE := pfxlibrary +LOCAL_SRC_FILES := project/Android/PfxLibrary/obj/local/armeabi-v7a/libpfxlibrary.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +# Warning: do not enable SIMD vector math functions or NEON for running +# in the Android NDK emulator. NEON requires a physical device +# with NEON support. +# +# Note that in theory we can let LOCAL_ARM_NEON := true determine +# that the flags -mfpu=neon and -mfloat-abi=softfp should be applied. +# However, in practice we have seen one case where the ndk-build +# script "forgets" these flags for the occasional *.cpp file, thus +# causing those files to access the std definition of vectormath +# classes, which are completely different, including different size. +# So, we explicitly apply these flags to avoid having a broken +# build. +# +# Include -DSCE_PFX_USE_SIMD_VECTORMATH to build for ARM NEON SIMD +# intrinsics, and leave it off to use NEON for scalar math but without +# SIMD. + +LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -DUSE_PTHREADS -mfpu=neon -mfloat-abi=softfp -pthread -DSCE_PFX_USE_SIMD_VECTORMATH + +# apply these flags if needed +# -ffast-math -funsafe-math-optimizations + +# apply this to disable optimization +# TARGET_CFLAGS := $(TARGET_CFLAGS) -O0 + +# apply these 2 to turn on assembly output (*.c/*.cpp to *.s file) +# compile-cpp-source = $(eval $(call ev-compile-cpp-source,$1,$(1:%$(LOCAL_CPP_EXTENSION)=%.s))) +# TARGET_CFLAGS := $(TARGET_CFLAGS) -S + +# specify static libraries to link in +LOCAL_STATIC_LIBRARIES := pfxlibrary + +# Enable or disable NEON. Don't forget to apply, or not apply, -mfpu=neon and -mfloat-abi=softfp +# flags in addition, e.g., if this is true both of those need to be included in LOCAL_CFLAGS +# to avoid the possibility that ndk-build will "forget" to add them on some files +LOCAL_ARM_NEON := true +TARGET_CFLAGS := $(filter-out -ffpu=vfp,$(TARGET_CFLAGS)) + +LOCAL_MODULE := PfxApp_2_Stable_Parallel +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include \ + $(LOCAL_PATH)sample/api_physics_effects/2_stable_parallel \ + $(LOCAL_PATH)sample/api_physics_effects/common + +LOCAL_SRC_FILES := \ + sample/api_physics_effects/common/jni/physicseffects-android.cpp \ + sample/api_physics_effects/2_stable_parallel/main.cpp \ + sample/api_physics_effects/2_stable_parallel/physics_func.cpp \ + sample/api_physics_effects/common/ctrl_func.android.cpp \ + sample/api_physics_effects/common/render_func.android.cpp \ + sample/api_physics_effects/common/perf_func.android.cpp + +LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -lGLESv1_CM -ldl -lm -llog + +include $(BUILD_SHARED_LIBRARY) + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/jni/Application.mk b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/jni/Application.mk new file mode 100644 index 0000000..acff843 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/jni/Application.mk @@ -0,0 +1,31 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +APP_MODULES := PfxApp_2_Stable_Parallel +APP_ABI := armeabi-v7a +APP_OPTIM := release diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/local.properties b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/local.properties new file mode 100644 index 0000000..1659ad7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/local.properties @@ -0,0 +1,10 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must *NOT* be checked in Version Control Systems, +# as it contains information specific to your local configuration. + +# location of the SDK. This is only used by Ant +# For customization when using a Version Control System, please read the +# header note. +sdk.dir=F:\\sdks\\Android\\android-sdk diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/proguard.cfg b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/proguard.cfg new file mode 100644 index 0000000..3e84fc7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/proguard.cfg @@ -0,0 +1,36 @@ +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-verbose +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class com.android.vending.licensing.ILicensingService + +-keepclasseswithmembernames class * { + native ; +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/res/drawable-hdpi/icon.png b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/res/drawable-hdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d7753923a3b4ffcb78aceccf782760aa08e7f483 GIT binary patch literal 2472 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 literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/res/drawable-mdpi/icon.png b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/res/drawable-mdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ff7be820f80a465e3be8bd4d46ebd63fe9392682 GIT binary patch literal 1511 zcmVWdKxYbs#b^AWC&?ATls9F(5HEIyE^uGBF@6Ff}kR!;(A100007bV*G` z2ipe~6$LCbh{VhQ000SaNLh0L01m?d01m?e$8V@)00004XF*Lt006O%3;baP000F( zNklr>ESsv@Mi|liH?#%9%QkxJB zVwyeKOwPS??!CYJKWFZ~IO#(X#-(^dZ0fFx(d@gk*dP%*o69dY!d#01#eiZ!F`&h^ z7*Gu8QBC!LzL^R1Uc|t4IQvJYB#YI`+csnQ9vIUeJ5VTy&d>2v4ZP#v;PIp6II@y( za_8mzw0F3|*RY`mf@VR1W~D3?!1Y(rbO=61Lw5Qm?l^F@8$~D3)Z;jQT+ptgJha-4-15`Xt zY==h4Ed}&`h5m+x1B%qpuct^9#r@(IYMa^8B{{fp7;kJwo&^X-he&8SDP>j6nTVU$ za`OZV`O*Jvw5wxCSr(RfwoKlN<#_&MSe^kNrVoasPfvd$$%&IBDJ?B+S+K3peUSz5 zJOnjVTBvjo=&EK-_R@kEqoqW|mK=>}Nfv7`9Sp;Zi5}x7k9(mlI2$QY0(nUno zH%MAFdlNK|*=!mg9}g=gNxqB}J6F99F&vjTv#t5cS~2hn7kPqKOPk;qFruqB0;FGQvW@ zjT_Z?;WMZW(J_9%e_~=Hny=~UX~8vw&hJ>=u+rhdtK||=u5nPsvFf3OszlkBo1&I+ z3nB|9{ph8Rj{s3IW>?|2Q_30zX=op0PS-Fb4qR^?{%l12(&(n8l;XihTaE6t>& zBt7m;j@k4&9i`IkcFWtLaL%CDljE88guFqcQAhst)IFcip-iJvsRBWNm_|^WmX~sW zKlW>1XKxxIw#J^dD4@J+*im%m7JJR+>FO;=YJ<FL?Oe}6+mLs3x?Ek-~jLuO{C z)9Gw)Z;t{IL1krSM@I)qNE@iDtINp9sI9F%c<^9-eLba&Dzdt|n#m%4nez}o$B^cU ziHY>^2LgeVl$5ctF>>hnH zBY}NBAL&g;iN#{U+1!T&S}2SCJ`@9r0mXn8-(o;9p#L2Z_oV$j^%s51@w8w`n1uiU N002ovPDHLkV1lSs(@g*X literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/res/layout/main.xml b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/res/layout/main.xml new file mode 100644 index 0000000..6c06966 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/res/layout/main.xml @@ -0,0 +1,34 @@ + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/res/values/strings.xml b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/res/values/strings.xml new file mode 100644 index 0000000..630b300 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/res/values/strings.xml @@ -0,0 +1,31 @@ + + + + Pfx 2 Stable Parallel + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java new file mode 100644 index 0000000..ec83e64 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java @@ -0,0 +1,113 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.renderingsupport; + +import android.opengl.GLSurfaceView; +import android.content.Context; +import android.view.MotionEvent; + +/** + * Implementation of the OpenGL ES view window and creates/assigns a renderer. + * Handles touch events to allow the user to change scene on tap, move the camera + * around by touch based movement, and allows the user to zoom in and out by pinching. + * @author ahamilton + * + */ +public class PhysicsEffectsGLSurfaceView extends GLSurfaceView { + public PhysicsEffectsGLSurfaceView(Context context) { + super(context); + peRenderer = new PhysicsEffectsRenderer(); + setRenderer(peRenderer); + } + + float x1 = 0, x2, y1 = 0, y2; + long downTime; + + /** + * Function to process touch events for camera and scene control + * + */ + public boolean onTouchEvent(final MotionEvent event) { + switch(event.getAction()) { + case(MotionEvent.ACTION_DOWN): + x1 = event.getX(); + y1 = event.getY(); + downTime = event.getDownTime(); + break; + case(MotionEvent.ACTION_UP): + if(event.getEventTime() - downTime < 100) nativeSceneChange(); + break; + case(MotionEvent.ACTION_MOVE): { + if(event.getPointerCount() == 1){ + x2 = event.getX(); + y2 = event.getY(); + float dx = x2-x1; + float dy = y2-y1; + + // Use dx and dy to determine the direction + if(dx > 0) { + nativeCameraLeft(); + } else { + nativeCameraRight(); + } + if(dy > 0){ + nativeCameraUp(); + } else { + nativeCameraDown(); + } + x1=x2; + y1=y2; + } else if(event.getPointerCount() == 2){ + y2 = event.getY(); + + float dy = y2-y1; + + // Use dy to determine zoom + if(dy > 0){ + nativeCameraZoomIn(); + } else { + nativeCameraZoomOut(); + } + y1=y2; + } + } + } + return true; + } + + PhysicsEffectsRenderer peRenderer; + + private static native void nativeCameraUp(); + private static native void nativeCameraDown(); + private static native void nativeCameraLeft(); + private static native void nativeCameraRight(); + private static native void nativeCameraZoomOut(); + private static native void nativeCameraZoomIn(); + private static native void nativeSceneChange(); +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/src/pfx/renderingsupport/PhysicsEffectsRenderer.java b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/src/pfx/renderingsupport/PhysicsEffectsRenderer.java new file mode 100644 index 0000000..5ca66d4 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/src/pfx/renderingsupport/PhysicsEffectsRenderer.java @@ -0,0 +1,101 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.renderingsupport; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLSurfaceView; +import android.util.Log; + +/** + * Implementation of the renderer. It calls the native physicseffects code + * to run on the init and drawframe allowing the sample to perform its simulation. + * @author ahamilton + * + */ +public class PhysicsEffectsRenderer implements GLSurfaceView.Renderer { + boolean startup = true; + boolean notEnded = true; + static long startuptime; + static long endtime; + int frameCounter; + + /** + * Initilize the physics simulation after the GL surface is created. + * + */ + public void onSurfaceCreated(GL10 gl, EGLConfig config) + { + Log.v("Init physics", "Initing physics"); + nativePhysicsEffectsInit(); + Log.v("Init physics", "Inited physics"); + } + + /** + * Set the viewport for a changed GL surface + * + */ + public void onSurfaceChanged(GL10 gl, int w, int h) + { + gl.glViewport(0, 0, w, h); + } + + /** + * Perform one simulation step and render the scene. + * + */ + public void onDrawFrame(GL10 gl) + { + if(startup){ + startup = false; + frameCounter = 0; + startuptime = System.currentTimeMillis(); + endtime = startuptime + 10000; // sets run time to be 30 seconds + } + + nativePhysicsEffectsSimulate(); + + frameCounter++; + long lCurrentTime = System.currentTimeMillis(); + if(lCurrentTime > endtime && notEnded) { + float fFrameRate = (1000.0f * (float)frameCounter) / ((float)lCurrentTime - startuptime); + Log.v("PHYSICS TIMING STUDY", "Number of Frames: " + Integer.toString(frameCounter)); + Log.v("PHYSICS TIMING STUDY", "Time ellapsed (milliseconds): " + Long.toString(lCurrentTime - startuptime)); + Log.v("PHYSICS TIMING STUDY", "Bullet Frame Rate: " + Float.toString(fFrameRate) + "fps"); + notEnded = false; + } + } + + private static native void nativePhysicsEffectsInit(); + private static native void nativePhysicsEffectsSimulate(); + private static native void nativePhysicsEffectsUpdate(); + private static native void nativePhysicsEffectsPhysStep(); + private static native void nativePhysicsEffectsRender(); +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/src/pfx/sample2b/PfxApp_2_Stable_Parallel.java b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/src/pfx/sample2b/PfxApp_2_Stable_Parallel.java new file mode 100644 index 0000000..40ff145 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_2_Stable_Parallel/src/pfx/sample2b/PfxApp_2_Stable_Parallel.java @@ -0,0 +1,58 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.sample2b; + +import pfx.renderingsupport.PhysicsEffectsGLSurfaceView; + +import android.app.Activity; +import android.opengl.GLSurfaceView; +import android.os.Bundle; + +/** + * When program loads it creates a OpenGl ES render window for + * the bullet sample projects to run in and loads the complied + * physics effects libraries. + * @author ahamilton + * + */ +public class PfxApp_2_Stable_Parallel extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + peGLView = new PhysicsEffectsGLSurfaceView(this); + setContentView(peGLView); + } + + private GLSurfaceView peGLView; + + //This is where you specify which physics effects sample you would like to load + static { + System.loadLibrary("PfxApp_2_Stable_Parallel"); + } +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/.classpath b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/.classpath new file mode 100644 index 0000000..98132ca --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/.classpath @@ -0,0 +1,35 @@ + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/.externalToolBuilders/BuildSampleJNICode.launch b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/.externalToolBuilders/BuildSampleJNICode.launch new file mode 100644 index 0000000..dfb6be4 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/.externalToolBuilders/BuildSampleJNICode.launch @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/.project b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/.project new file mode 100644 index 0000000..b255ca0 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/.project @@ -0,0 +1,114 @@ + + + + PfxApp_3_Sleep + + + PfxLibrary + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + org.eclipse.ui.externaltools.ExternalToolBuilder + auto,full,incremental, + + + LaunchConfigHandle + <project>/.externalToolBuilders/BuildSampleJNICode.launch + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + + + src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java + 1 + PFX_ROOT/project/Android/PfxApp_3_Sleep/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java + + + src/pfx/renderingsupport/PhysicsEffectsRenderer.java + 1 + PFX_ROOT/project/Android/PfxApp_3_Sleep/src/pfx/renderingsupport/PhysicsEffectsRenderer.java + + + src/pfx/sample3/PfxApp_3_Sleep.java + 1 + PFX_ROOT/project/Android/PfxApp_3_Sleep/src/pfx/sample/PfxApp_3_Sleep.java + + + + + 1305070288951 + jni + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-.svn + + + + 1305070295995 + src + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-.svn + + + + + + PFX_ROOT + $%7BPARENT-3-PROJECT_LOC%7D + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/AndroidManifest.xml b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/AndroidManifest.xml new file mode 100644 index 0000000..a07242c --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/AndroidManifest.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/build.xml b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/build.xml new file mode 100644 index 0000000..cab642b --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/build.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/default.properties b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/default.properties new file mode 100644 index 0000000..25c0280 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/default.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-10 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/jni/Android.mk b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/jni/Android.mk new file mode 100644 index 0000000..e92d914 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/jni/Android.mk @@ -0,0 +1,107 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +# NOTE: The local path here is defined based on an environment +# variable that points to the root of the Bullet/PhysicsEffects +# code base. The variable must be set in the Cygwin style, e.g., +# BULLET_PFX_ROOT_CYGWIN = /cygdrive/d/tools/PhysicsEffectsRootPath +# +# The reason for *not* just setting local path := $(call my-dir) +# is that we wish to access local source files that are *not* +# located in a "jni" subfolder and *not* located in a subfolder +# of the project folder. This enables us to have Eclipse and +# Android NDK projects that fit neatly into the Bullet/PhysicsEffects +# folder structure, enabling a multi platform code base, without +# forcing the "jni" and subfolder structure that Android SDK/NDK +# prefer for pure Android projects. +LOCAL_PATH:= $(BULLET_PFX_ROOT_CYGWIN) + +# Copy the shared static library, libpfxlibrary.a, into the build +include $(CLEAR_VARS) +LOCAL_MODULE := pfxlibrary +LOCAL_SRC_FILES := project/Android/PfxLibrary/obj/local/armeabi-v7a/libpfxlibrary.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +# Warning: do not enable SIMD vector math functions or NEON for running +# in the Android NDK emulator. NEON requires a physical device +# with NEON support. +# +# Note that in theory we can let LOCAL_ARM_NEON := true determine +# that the flags -mfpu=neon and -mfloat-abi=softfp should be applied. +# However, in practice we have seen one case where the ndk-build +# script "forgets" these flags for the occasional *.cpp file, thus +# causing those files to access the std definition of vectormath +# classes, which are completely different, including different size. +# So, we explicitly apply these flags to avoid having a broken +# build. +# +# Include -DSCE_PFX_USE_SIMD_VECTORMATH to build for ARM NEON SIMD +# intrinsics, and leave it off to use NEON for scalar math but without +# SIMD. + +LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -mfpu=neon -mfloat-abi=softfp -DSCE_PFX_USE_SIMD_VECTORMATH + +# apply these flags if needed +# -ffast-math -funsafe-math-optimizations + +# apply this to disable optimization +# TARGET_CFLAGS := $(TARGET_CFLAGS) -O0 + +# apply these 2 to turn on assembly output (*.c/*.cpp to *.s file) +# compile-cpp-source = $(eval $(call ev-compile-cpp-source,$1,$(1:%$(LOCAL_CPP_EXTENSION)=%.s))) +# TARGET_CFLAGS := $(TARGET_CFLAGS) -S + +# specify static libraries to link in +LOCAL_STATIC_LIBRARIES := pfxlibrary + +# Enable or disable NEON. Don't forget to apply, or not apply, -mfpu=neon and -mfloat-abi=softfp +# flags in addition, e.g., if this is true both of those need to be included in LOCAL_CFLAGS +# to avoid the possibility that ndk-build will "forget" to add them on some files +LOCAL_ARM_NEON := true +TARGET_CFLAGS := $(filter-out -ffpu=vfp,$(TARGET_CFLAGS)) + +LOCAL_MODULE := PfxApp_3_Sleep +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include \ + $(LOCAL_PATH)sample/api_physics_effects/3_sleep \ + $(LOCAL_PATH)sample/api_physics_effects/common + +LOCAL_SRC_FILES := \ + sample/api_physics_effects/common/jni/physicseffects-android.cpp \ + sample/api_physics_effects/3_sleep/main.cpp \ + sample/api_physics_effects/3_sleep/physics_func.cpp \ + sample/api_physics_effects/common/ctrl_func.android.cpp \ + sample/api_physics_effects/common/render_func.android.cpp \ + sample/api_physics_effects/common/perf_func.android.cpp + +LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -lGLESv1_CM -ldl -lm -llog + +include $(BUILD_SHARED_LIBRARY) + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/jni/Application.mk b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/jni/Application.mk new file mode 100644 index 0000000..3fdd58b --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/jni/Application.mk @@ -0,0 +1,31 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +APP_MODULES := PfxApp_3_Sleep +APP_ABI := armeabi-v7a +APP_OPTIM := release diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/local.properties b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/local.properties new file mode 100644 index 0000000..1659ad7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/local.properties @@ -0,0 +1,10 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must *NOT* be checked in Version Control Systems, +# as it contains information specific to your local configuration. + +# location of the SDK. This is only used by Ant +# For customization when using a Version Control System, please read the +# header note. +sdk.dir=F:\\sdks\\Android\\android-sdk diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/proguard.cfg b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/proguard.cfg new file mode 100644 index 0000000..3e84fc7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/proguard.cfg @@ -0,0 +1,36 @@ +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-verbose +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class com.android.vending.licensing.ILicensingService + +-keepclasseswithmembernames class * { + native ; +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/res/drawable-hdpi/icon.png b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/res/drawable-hdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d7753923a3b4ffcb78aceccf782760aa08e7f483 GIT binary patch literal 2472 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 literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/res/drawable-mdpi/icon.png b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/res/drawable-mdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ff7be820f80a465e3be8bd4d46ebd63fe9392682 GIT binary patch literal 1511 zcmVWdKxYbs#b^AWC&?ATls9F(5HEIyE^uGBF@6Ff}kR!;(A100007bV*G` z2ipe~6$LCbh{VhQ000SaNLh0L01m?d01m?e$8V@)00004XF*Lt006O%3;baP000F( zNklr>ESsv@Mi|liH?#%9%QkxJB zVwyeKOwPS??!CYJKWFZ~IO#(X#-(^dZ0fFx(d@gk*dP%*o69dY!d#01#eiZ!F`&h^ z7*Gu8QBC!LzL^R1Uc|t4IQvJYB#YI`+csnQ9vIUeJ5VTy&d>2v4ZP#v;PIp6II@y( za_8mzw0F3|*RY`mf@VR1W~D3?!1Y(rbO=61Lw5Qm?l^F@8$~D3)Z;jQT+ptgJha-4-15`Xt zY==h4Ed}&`h5m+x1B%qpuct^9#r@(IYMa^8B{{fp7;kJwo&^X-he&8SDP>j6nTVU$ za`OZV`O*Jvw5wxCSr(RfwoKlN<#_&MSe^kNrVoasPfvd$$%&IBDJ?B+S+K3peUSz5 zJOnjVTBvjo=&EK-_R@kEqoqW|mK=>}Nfv7`9Sp;Zi5}x7k9(mlI2$QY0(nUno zH%MAFdlNK|*=!mg9}g=gNxqB}J6F99F&vjTv#t5cS~2hn7kPqKOPk;qFruqB0;FGQvW@ zjT_Z?;WMZW(J_9%e_~=Hny=~UX~8vw&hJ>=u+rhdtK||=u5nPsvFf3OszlkBo1&I+ z3nB|9{ph8Rj{s3IW>?|2Q_30zX=op0PS-Fb4qR^?{%l12(&(n8l;XihTaE6t>& zBt7m;j@k4&9i`IkcFWtLaL%CDljE88guFqcQAhst)IFcip-iJvsRBWNm_|^WmX~sW zKlW>1XKxxIw#J^dD4@J+*im%m7JJR+>FO;=YJ<FL?Oe}6+mLs3x?Ek-~jLuO{C z)9Gw)Z;t{IL1krSM@I)qNE@iDtINp9sI9F%c<^9-eLba&Dzdt|n#m%4nez}o$B^cU ziHY>^2LgeVl$5ctF>>hnH zBY}NBAL&g;iN#{U+1!T&S}2SCJ`@9r0mXn8-(o;9p#L2Z_oV$j^%s51@w8w`n1uiU N002ovPDHLkV1lSs(@g*X literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/res/layout/main.xml b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/res/layout/main.xml new file mode 100644 index 0000000..6c06966 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/res/layout/main.xml @@ -0,0 +1,34 @@ + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/res/values/strings.xml b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/res/values/strings.xml new file mode 100644 index 0000000..832910d --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/res/values/strings.xml @@ -0,0 +1,31 @@ + + + + Pfx 3 Sleep + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java new file mode 100644 index 0000000..ec83e64 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java @@ -0,0 +1,113 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.renderingsupport; + +import android.opengl.GLSurfaceView; +import android.content.Context; +import android.view.MotionEvent; + +/** + * Implementation of the OpenGL ES view window and creates/assigns a renderer. + * Handles touch events to allow the user to change scene on tap, move the camera + * around by touch based movement, and allows the user to zoom in and out by pinching. + * @author ahamilton + * + */ +public class PhysicsEffectsGLSurfaceView extends GLSurfaceView { + public PhysicsEffectsGLSurfaceView(Context context) { + super(context); + peRenderer = new PhysicsEffectsRenderer(); + setRenderer(peRenderer); + } + + float x1 = 0, x2, y1 = 0, y2; + long downTime; + + /** + * Function to process touch events for camera and scene control + * + */ + public boolean onTouchEvent(final MotionEvent event) { + switch(event.getAction()) { + case(MotionEvent.ACTION_DOWN): + x1 = event.getX(); + y1 = event.getY(); + downTime = event.getDownTime(); + break; + case(MotionEvent.ACTION_UP): + if(event.getEventTime() - downTime < 100) nativeSceneChange(); + break; + case(MotionEvent.ACTION_MOVE): { + if(event.getPointerCount() == 1){ + x2 = event.getX(); + y2 = event.getY(); + float dx = x2-x1; + float dy = y2-y1; + + // Use dx and dy to determine the direction + if(dx > 0) { + nativeCameraLeft(); + } else { + nativeCameraRight(); + } + if(dy > 0){ + nativeCameraUp(); + } else { + nativeCameraDown(); + } + x1=x2; + y1=y2; + } else if(event.getPointerCount() == 2){ + y2 = event.getY(); + + float dy = y2-y1; + + // Use dy to determine zoom + if(dy > 0){ + nativeCameraZoomIn(); + } else { + nativeCameraZoomOut(); + } + y1=y2; + } + } + } + return true; + } + + PhysicsEffectsRenderer peRenderer; + + private static native void nativeCameraUp(); + private static native void nativeCameraDown(); + private static native void nativeCameraLeft(); + private static native void nativeCameraRight(); + private static native void nativeCameraZoomOut(); + private static native void nativeCameraZoomIn(); + private static native void nativeSceneChange(); +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/src/pfx/renderingsupport/PhysicsEffectsRenderer.java b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/src/pfx/renderingsupport/PhysicsEffectsRenderer.java new file mode 100644 index 0000000..5ca66d4 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/src/pfx/renderingsupport/PhysicsEffectsRenderer.java @@ -0,0 +1,101 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.renderingsupport; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLSurfaceView; +import android.util.Log; + +/** + * Implementation of the renderer. It calls the native physicseffects code + * to run on the init and drawframe allowing the sample to perform its simulation. + * @author ahamilton + * + */ +public class PhysicsEffectsRenderer implements GLSurfaceView.Renderer { + boolean startup = true; + boolean notEnded = true; + static long startuptime; + static long endtime; + int frameCounter; + + /** + * Initilize the physics simulation after the GL surface is created. + * + */ + public void onSurfaceCreated(GL10 gl, EGLConfig config) + { + Log.v("Init physics", "Initing physics"); + nativePhysicsEffectsInit(); + Log.v("Init physics", "Inited physics"); + } + + /** + * Set the viewport for a changed GL surface + * + */ + public void onSurfaceChanged(GL10 gl, int w, int h) + { + gl.glViewport(0, 0, w, h); + } + + /** + * Perform one simulation step and render the scene. + * + */ + public void onDrawFrame(GL10 gl) + { + if(startup){ + startup = false; + frameCounter = 0; + startuptime = System.currentTimeMillis(); + endtime = startuptime + 10000; // sets run time to be 30 seconds + } + + nativePhysicsEffectsSimulate(); + + frameCounter++; + long lCurrentTime = System.currentTimeMillis(); + if(lCurrentTime > endtime && notEnded) { + float fFrameRate = (1000.0f * (float)frameCounter) / ((float)lCurrentTime - startuptime); + Log.v("PHYSICS TIMING STUDY", "Number of Frames: " + Integer.toString(frameCounter)); + Log.v("PHYSICS TIMING STUDY", "Time ellapsed (milliseconds): " + Long.toString(lCurrentTime - startuptime)); + Log.v("PHYSICS TIMING STUDY", "Bullet Frame Rate: " + Float.toString(fFrameRate) + "fps"); + notEnded = false; + } + } + + private static native void nativePhysicsEffectsInit(); + private static native void nativePhysicsEffectsSimulate(); + private static native void nativePhysicsEffectsUpdate(); + private static native void nativePhysicsEffectsPhysStep(); + private static native void nativePhysicsEffectsRender(); +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/src/pfx/sample3/PfxApp_3_Sleep.java b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/src/pfx/sample3/PfxApp_3_Sleep.java new file mode 100644 index 0000000..29e2b96 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_3_Sleep/src/pfx/sample3/PfxApp_3_Sleep.java @@ -0,0 +1,58 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.sample3; + +import pfx.renderingsupport.PhysicsEffectsGLSurfaceView; + +import android.app.Activity; +import android.opengl.GLSurfaceView; +import android.os.Bundle; + +/** + * When program loads it creates a OpenGl ES render window for + * the bullet sample projects to run in and loads the complied + * physics effects libraries. + * @author ahamilton + * + */ +public class PfxApp_3_Sleep extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + peGLView = new PhysicsEffectsGLSurfaceView(this); + setContentView(peGLView); + } + + private GLSurfaceView peGLView; + + //This is where you specify which physics effects sample you would like to load + static { + System.loadLibrary("PfxApp_3_Sleep"); + } +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/.classpath b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/.classpath new file mode 100644 index 0000000..98132ca --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/.classpath @@ -0,0 +1,35 @@ + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/.externalToolBuilders/BuildSampleJNICode.launch b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/.externalToolBuilders/BuildSampleJNICode.launch new file mode 100644 index 0000000..66e0e1c --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/.externalToolBuilders/BuildSampleJNICode.launch @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/.project b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/.project new file mode 100644 index 0000000..90be27d --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/.project @@ -0,0 +1,114 @@ + + + + PfxApp_4_MotionType + + + PfxLibrary + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + org.eclipse.ui.externaltools.ExternalToolBuilder + auto,full,incremental, + + + LaunchConfigHandle + <project>/.externalToolBuilders/BuildSampleJNICode.launch + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + + + src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java + 1 + PFX_ROOT/project/Android/PfxApp_4_MotionType/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java + + + src/pfx/renderingsupport/PhysicsEffectsRenderer.java + 1 + PFX_ROOT/project/Android/PfxApp_4_MotionType/src/pfx/renderingsupport/PhysicsEffectsRenderer.java + + + src/pfx/sample4/PfxApp_4_MotionType.java + 1 + PFX_ROOT/project/Android/PfxApp_4_MotionType/src/pfx/PfxApp_4_MotionType.java + + + + + 1305070288951 + jni + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-.svn + + + + 1305070295995 + src + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-.svn + + + + + + PFX_ROOT + $%7BPARENT-3-PROJECT_LOC%7D + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/AndroidManifest.xml b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/AndroidManifest.xml new file mode 100644 index 0000000..e49f9b6 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/AndroidManifest.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/build.xml b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/build.xml new file mode 100644 index 0000000..bf58c3d --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/build.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/default.properties b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/default.properties new file mode 100644 index 0000000..f4b4f17 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/default.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-9 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/jni/Android.mk b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/jni/Android.mk new file mode 100644 index 0000000..1666da8 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/jni/Android.mk @@ -0,0 +1,107 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +# NOTE: The local path here is defined based on an environment +# variable that points to the root of the Bullet/PhysicsEffects +# code base. The variable must be set in the Cygwin style, e.g., +# BULLET_PFX_ROOT_CYGWIN = /cygdrive/d/tools/PhysicsEffectsRootPath +# +# The reason for *not* just setting local path := $(call my-dir) +# is that we wish to access local source files that are *not* +# located in a "jni" subfolder and *not* located in a subfolder +# of the project folder. This enables us to have Eclipse and +# Android NDK projects that fit neatly into the Bullet/PhysicsEffects +# folder structure, enabling a multi platform code base, without +# forcing the "jni" and subfolder structure that Android SDK/NDK +# prefer for pure Android projects. +LOCAL_PATH:= $(BULLET_PFX_ROOT_CYGWIN) + +# Copy the shared static library, libpfxlibrary.a, into the build +include $(CLEAR_VARS) +LOCAL_MODULE := pfxlibrary +LOCAL_SRC_FILES := project/Android/PfxLibrary/obj/local/armeabi-v7a/libpfxlibrary.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +# Warning: do not enable SIMD vector math functions or NEON for running +# in the Android NDK emulator. NEON requires a physical device +# with NEON support. +# +# Note that in theory we can let LOCAL_ARM_NEON := true determine +# that the flags -mfpu=neon and -mfloat-abi=softfp should be applied. +# However, in practice we have seen one case where the ndk-build +# script "forgets" these flags for the occasional *.cpp file, thus +# causing those files to access the std definition of vectormath +# classes, which are completely different, including different size. +# So, we explicitly apply these flags to avoid having a broken +# build. +# +# Include -DSCE_PFX_USE_SIMD_VECTORMATH to build for ARM NEON SIMD +# intrinsics, and leave it off to use NEON for scalar math but without +# SIMD. + +LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -mfpu=neon -mfloat-abi=softfp -DSCE_PFX_USE_SIMD_VECTORMATH + +# apply these flags if needed +# -ffast-math -funsafe-math-optimizations + +# apply this to disable optimization +# TARGET_CFLAGS := $(TARGET_CFLAGS) -O0 + +# apply these 2 to turn on assembly output (*.c/*.cpp to *.s file) +# compile-cpp-source = $(eval $(call ev-compile-cpp-source,$1,$(1:%$(LOCAL_CPP_EXTENSION)=%.s))) +# TARGET_CFLAGS := $(TARGET_CFLAGS) -S + +# specify static libraries to link in +LOCAL_STATIC_LIBRARIES := pfxlibrary + +# Enable or disable NEON. Don't forget to apply, or not apply, -mfpu=neon and -mfloat-abi=softfp +# flags in addition, e.g., if this is true both of those need to be included in LOCAL_CFLAGS +# to avoid the possibility that ndk-build will "forget" to add them on some files +LOCAL_ARM_NEON := true +TARGET_CFLAGS := $(filter-out -ffpu=vfp,$(TARGET_CFLAGS)) + +LOCAL_MODULE := PfxApp_4_MotionType +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include \ + $(LOCAL_PATH)sample/api_physics_effects/4_motion_type \ + $(LOCAL_PATH)sample/api_physics_effects/common + +LOCAL_SRC_FILES := \ + sample/api_physics_effects/common/jni/physicseffects-android.cpp \ + sample/api_physics_effects/4_motion_type/main.cpp \ + sample/api_physics_effects/4_motion_type/physics_func.cpp \ + sample/api_physics_effects/common/ctrl_func.android.cpp \ + sample/api_physics_effects/common/render_func.android.cpp \ + sample/api_physics_effects/common/perf_func.android.cpp + +LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -lGLESv1_CM -ldl -lm -llog + +include $(BUILD_SHARED_LIBRARY) + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/jni/Application.mk b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/jni/Application.mk new file mode 100644 index 0000000..6f49a4b --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/jni/Application.mk @@ -0,0 +1,31 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +APP_MODULES := PfxApp_4_MotionType +APP_ABI := armeabi-v7a +APP_OPTIM := release diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/local.properties b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/local.properties new file mode 100644 index 0000000..1659ad7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/local.properties @@ -0,0 +1,10 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must *NOT* be checked in Version Control Systems, +# as it contains information specific to your local configuration. + +# location of the SDK. This is only used by Ant +# For customization when using a Version Control System, please read the +# header note. +sdk.dir=F:\\sdks\\Android\\android-sdk diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/proguard.cfg b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/proguard.cfg new file mode 100644 index 0000000..3e84fc7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/proguard.cfg @@ -0,0 +1,36 @@ +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-verbose +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class com.android.vending.licensing.ILicensingService + +-keepclasseswithmembernames class * { + native ; +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/res/drawable-hdpi/icon.png b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/res/drawable-hdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d7753923a3b4ffcb78aceccf782760aa08e7f483 GIT binary patch literal 2472 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 literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/res/drawable-mdpi/icon.png b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/res/drawable-mdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ff7be820f80a465e3be8bd4d46ebd63fe9392682 GIT binary patch literal 1511 zcmVWdKxYbs#b^AWC&?ATls9F(5HEIyE^uGBF@6Ff}kR!;(A100007bV*G` z2ipe~6$LCbh{VhQ000SaNLh0L01m?d01m?e$8V@)00004XF*Lt006O%3;baP000F( zNklr>ESsv@Mi|liH?#%9%QkxJB zVwyeKOwPS??!CYJKWFZ~IO#(X#-(^dZ0fFx(d@gk*dP%*o69dY!d#01#eiZ!F`&h^ z7*Gu8QBC!LzL^R1Uc|t4IQvJYB#YI`+csnQ9vIUeJ5VTy&d>2v4ZP#v;PIp6II@y( za_8mzw0F3|*RY`mf@VR1W~D3?!1Y(rbO=61Lw5Qm?l^F@8$~D3)Z;jQT+ptgJha-4-15`Xt zY==h4Ed}&`h5m+x1B%qpuct^9#r@(IYMa^8B{{fp7;kJwo&^X-he&8SDP>j6nTVU$ za`OZV`O*Jvw5wxCSr(RfwoKlN<#_&MSe^kNrVoasPfvd$$%&IBDJ?B+S+K3peUSz5 zJOnjVTBvjo=&EK-_R@kEqoqW|mK=>}Nfv7`9Sp;Zi5}x7k9(mlI2$QY0(nUno zH%MAFdlNK|*=!mg9}g=gNxqB}J6F99F&vjTv#t5cS~2hn7kPqKOPk;qFruqB0;FGQvW@ zjT_Z?;WMZW(J_9%e_~=Hny=~UX~8vw&hJ>=u+rhdtK||=u5nPsvFf3OszlkBo1&I+ z3nB|9{ph8Rj{s3IW>?|2Q_30zX=op0PS-Fb4qR^?{%l12(&(n8l;XihTaE6t>& zBt7m;j@k4&9i`IkcFWtLaL%CDljE88guFqcQAhst)IFcip-iJvsRBWNm_|^WmX~sW zKlW>1XKxxIw#J^dD4@J+*im%m7JJR+>FO;=YJ<FL?Oe}6+mLs3x?Ek-~jLuO{C z)9Gw)Z;t{IL1krSM@I)qNE@iDtINp9sI9F%c<^9-eLba&Dzdt|n#m%4nez}o$B^cU ziHY>^2LgeVl$5ctF>>hnH zBY}NBAL&g;iN#{U+1!T&S}2SCJ`@9r0mXn8-(o;9p#L2Z_oV$j^%s51@w8w`n1uiU N002ovPDHLkV1lSs(@g*X literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/res/layout/main.xml b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/res/layout/main.xml new file mode 100644 index 0000000..6c06966 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/res/layout/main.xml @@ -0,0 +1,34 @@ + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/res/values/strings.xml b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/res/values/strings.xml new file mode 100644 index 0000000..cdeb98a --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/res/values/strings.xml @@ -0,0 +1,31 @@ + + + + Pfx 4 Motion Type + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java new file mode 100644 index 0000000..ec83e64 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java @@ -0,0 +1,113 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.renderingsupport; + +import android.opengl.GLSurfaceView; +import android.content.Context; +import android.view.MotionEvent; + +/** + * Implementation of the OpenGL ES view window and creates/assigns a renderer. + * Handles touch events to allow the user to change scene on tap, move the camera + * around by touch based movement, and allows the user to zoom in and out by pinching. + * @author ahamilton + * + */ +public class PhysicsEffectsGLSurfaceView extends GLSurfaceView { + public PhysicsEffectsGLSurfaceView(Context context) { + super(context); + peRenderer = new PhysicsEffectsRenderer(); + setRenderer(peRenderer); + } + + float x1 = 0, x2, y1 = 0, y2; + long downTime; + + /** + * Function to process touch events for camera and scene control + * + */ + public boolean onTouchEvent(final MotionEvent event) { + switch(event.getAction()) { + case(MotionEvent.ACTION_DOWN): + x1 = event.getX(); + y1 = event.getY(); + downTime = event.getDownTime(); + break; + case(MotionEvent.ACTION_UP): + if(event.getEventTime() - downTime < 100) nativeSceneChange(); + break; + case(MotionEvent.ACTION_MOVE): { + if(event.getPointerCount() == 1){ + x2 = event.getX(); + y2 = event.getY(); + float dx = x2-x1; + float dy = y2-y1; + + // Use dx and dy to determine the direction + if(dx > 0) { + nativeCameraLeft(); + } else { + nativeCameraRight(); + } + if(dy > 0){ + nativeCameraUp(); + } else { + nativeCameraDown(); + } + x1=x2; + y1=y2; + } else if(event.getPointerCount() == 2){ + y2 = event.getY(); + + float dy = y2-y1; + + // Use dy to determine zoom + if(dy > 0){ + nativeCameraZoomIn(); + } else { + nativeCameraZoomOut(); + } + y1=y2; + } + } + } + return true; + } + + PhysicsEffectsRenderer peRenderer; + + private static native void nativeCameraUp(); + private static native void nativeCameraDown(); + private static native void nativeCameraLeft(); + private static native void nativeCameraRight(); + private static native void nativeCameraZoomOut(); + private static native void nativeCameraZoomIn(); + private static native void nativeSceneChange(); +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/src/pfx/renderingsupport/PhysicsEffectsRenderer.java b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/src/pfx/renderingsupport/PhysicsEffectsRenderer.java new file mode 100644 index 0000000..5ca66d4 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/src/pfx/renderingsupport/PhysicsEffectsRenderer.java @@ -0,0 +1,101 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.renderingsupport; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLSurfaceView; +import android.util.Log; + +/** + * Implementation of the renderer. It calls the native physicseffects code + * to run on the init and drawframe allowing the sample to perform its simulation. + * @author ahamilton + * + */ +public class PhysicsEffectsRenderer implements GLSurfaceView.Renderer { + boolean startup = true; + boolean notEnded = true; + static long startuptime; + static long endtime; + int frameCounter; + + /** + * Initilize the physics simulation after the GL surface is created. + * + */ + public void onSurfaceCreated(GL10 gl, EGLConfig config) + { + Log.v("Init physics", "Initing physics"); + nativePhysicsEffectsInit(); + Log.v("Init physics", "Inited physics"); + } + + /** + * Set the viewport for a changed GL surface + * + */ + public void onSurfaceChanged(GL10 gl, int w, int h) + { + gl.glViewport(0, 0, w, h); + } + + /** + * Perform one simulation step and render the scene. + * + */ + public void onDrawFrame(GL10 gl) + { + if(startup){ + startup = false; + frameCounter = 0; + startuptime = System.currentTimeMillis(); + endtime = startuptime + 10000; // sets run time to be 30 seconds + } + + nativePhysicsEffectsSimulate(); + + frameCounter++; + long lCurrentTime = System.currentTimeMillis(); + if(lCurrentTime > endtime && notEnded) { + float fFrameRate = (1000.0f * (float)frameCounter) / ((float)lCurrentTime - startuptime); + Log.v("PHYSICS TIMING STUDY", "Number of Frames: " + Integer.toString(frameCounter)); + Log.v("PHYSICS TIMING STUDY", "Time ellapsed (milliseconds): " + Long.toString(lCurrentTime - startuptime)); + Log.v("PHYSICS TIMING STUDY", "Bullet Frame Rate: " + Float.toString(fFrameRate) + "fps"); + notEnded = false; + } + } + + private static native void nativePhysicsEffectsInit(); + private static native void nativePhysicsEffectsSimulate(); + private static native void nativePhysicsEffectsUpdate(); + private static native void nativePhysicsEffectsPhysStep(); + private static native void nativePhysicsEffectsRender(); +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/src/pfx/sample4/PfxApp_4_MotionType.java b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/src/pfx/sample4/PfxApp_4_MotionType.java new file mode 100644 index 0000000..9155614 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_4_MotionType/src/pfx/sample4/PfxApp_4_MotionType.java @@ -0,0 +1,58 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.sample4; + +import pfx.renderingsupport.PhysicsEffectsGLSurfaceView; + +import android.app.Activity; +import android.opengl.GLSurfaceView; +import android.os.Bundle; + +/** + * When program loads it creates a OpenGl ES render window for + * the bullet sample projects to run in and loads the complied + * physics effects libraries. + * @author ahamilton + * + */ +public class PfxApp_4_MotionType extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + peGLView = new PhysicsEffectsGLSurfaceView(this); + setContentView(peGLView); + } + + private GLSurfaceView peGLView; + + //This is where you specify which physics effects sample you would like to load + static { + System.loadLibrary("PfxApp_4_MotionType"); + } +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/.classpath b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/.classpath new file mode 100644 index 0000000..98132ca --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/.classpath @@ -0,0 +1,35 @@ + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/.externalToolBuilders/BuildSampleJNICode.launch b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/.externalToolBuilders/BuildSampleJNICode.launch new file mode 100644 index 0000000..ea5ac97 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/.externalToolBuilders/BuildSampleJNICode.launch @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/.project b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/.project new file mode 100644 index 0000000..f8f61f0 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/.project @@ -0,0 +1,114 @@ + + + + PfxApp_5_Raycast + + + PfxLibrary + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + org.eclipse.ui.externaltools.ExternalToolBuilder + auto,full,incremental, + + + LaunchConfigHandle + <project>/.externalToolBuilders/BuildSampleJNICode.launch + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + + + src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java + 1 + PFX_ROOT/project/Android/PfxApp_5_Raycast/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java + + + src/pfx/renderingsupport/PhysicsEffectsRenderer.java + 1 + PFX_ROOT/project/Android/PfxApp_5_Raycast/src/pfx/renderingsupport/PhysicsEffectsRenderer.java + + + src/pfx/sample5/PfxApp_5_Raycast.java + 1 + PFX_ROOT/project/Android/PfxApp_5_Raycast/src/pfx/sample/PfxApp_5_Raycast.java + + + + + 1305070288951 + jni + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-.svn + + + + 1305070295995 + src + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-.svn + + + + + + PFX_ROOT + $%7BPARENT-3-PROJECT_LOC%7D + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/AndroidManifest.xml b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/AndroidManifest.xml new file mode 100644 index 0000000..4fd40ee --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/AndroidManifest.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/build.xml b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/build.xml new file mode 100644 index 0000000..d0ad8b9 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/build.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/default.properties b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/default.properties new file mode 100644 index 0000000..f4b4f17 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/default.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-9 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/jni/Android.mk b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/jni/Android.mk new file mode 100644 index 0000000..502d455 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/jni/Android.mk @@ -0,0 +1,107 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +# NOTE: The local path here is defined based on an environment +# variable that points to the root of the Bullet/PhysicsEffects +# code base. The variable must be set in the Cygwin style, e.g., +# BULLET_PFX_ROOT_CYGWIN = /cygdrive/d/tools/PhysicsEffectsRootPath +# +# The reason for *not* just setting local path := $(call my-dir) +# is that we wish to access local source files that are *not* +# located in a "jni" subfolder and *not* located in a subfolder +# of the project folder. This enables us to have Eclipse and +# Android NDK projects that fit neatly into the Bullet/PhysicsEffects +# folder structure, enabling a multi platform code base, without +# forcing the "jni" and subfolder structure that Android SDK/NDK +# prefer for pure Android projects. +LOCAL_PATH:= $(BULLET_PFX_ROOT_CYGWIN) + +# Copy the shared static library, libpfxlibrary.a, into the build +include $(CLEAR_VARS) +LOCAL_MODULE := pfxlibrary +LOCAL_SRC_FILES := project/Android/PfxLibrary/obj/local/armeabi-v7a/libpfxlibrary.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +# Warning: do not enable SIMD vector math functions or NEON for running +# in the Android NDK emulator. NEON requires a physical device +# with NEON support. +# +# Note that in theory we can let LOCAL_ARM_NEON := true determine +# that the flags -mfpu=neon and -mfloat-abi=softfp should be applied. +# However, in practice we have seen one case where the ndk-build +# script "forgets" these flags for the occasional *.cpp file, thus +# causing those files to access the std definition of vectormath +# classes, which are completely different, including different size. +# So, we explicitly apply these flags to avoid having a broken +# build. +# +# Include -DSCE_PFX_USE_SIMD_VECTORMATH to build for ARM NEON SIMD +# intrinsics, and leave it off to use NEON for scalar math but without +# SIMD. + +LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -mfpu=neon -mfloat-abi=softfp -DSCE_PFX_USE_SIMD_VECTORMATH + +# apply these flags if needed +# -ffast-math -funsafe-math-optimizations + +# apply this to disable optimization +# TARGET_CFLAGS := $(TARGET_CFLAGS) -O0 + +# apply these 2 to turn on assembly output (*.c/*.cpp to *.s file) +# compile-cpp-source = $(eval $(call ev-compile-cpp-source,$1,$(1:%$(LOCAL_CPP_EXTENSION)=%.s))) +# TARGET_CFLAGS := $(TARGET_CFLAGS) -S + +# specify static libraries to link in +LOCAL_STATIC_LIBRARIES := pfxlibrary + +# Enable or disable NEON. Don't forget to apply, or not apply, -mfpu=neon and -mfloat-abi=softfp +# flags in addition, e.g., if this is true both of those need to be included in LOCAL_CFLAGS +# to avoid the possibility that ndk-build will "forget" to add them on some files +LOCAL_ARM_NEON := true +TARGET_CFLAGS := $(filter-out -ffpu=vfp,$(TARGET_CFLAGS)) + +LOCAL_MODULE := PfxApp_5_Raycast +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include \ + $(LOCAL_PATH)sample/api_physics_effects/5_raycast \ + $(LOCAL_PATH)sample/api_physics_effects/common + +LOCAL_SRC_FILES := \ + sample/api_physics_effects/common/jni/physicseffects-android.cpp \ + sample/api_physics_effects/5_raycast/main.cpp \ + sample/api_physics_effects/5_raycast/physics_func.cpp \ + sample/api_physics_effects/common/ctrl_func.android.cpp \ + sample/api_physics_effects/common/render_func.android.cpp \ + sample/api_physics_effects/common/perf_func.android.cpp + +LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -lGLESv1_CM -ldl -lm -llog + +include $(BUILD_SHARED_LIBRARY) + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/jni/Application.mk b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/jni/Application.mk new file mode 100644 index 0000000..024f678 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/jni/Application.mk @@ -0,0 +1,31 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +APP_MODULES := PfxApp_5_Raycast +APP_ABI := armeabi-v7a +APP_OPTIM := release diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/local.properties b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/local.properties new file mode 100644 index 0000000..1659ad7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/local.properties @@ -0,0 +1,10 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must *NOT* be checked in Version Control Systems, +# as it contains information specific to your local configuration. + +# location of the SDK. This is only used by Ant +# For customization when using a Version Control System, please read the +# header note. +sdk.dir=F:\\sdks\\Android\\android-sdk diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/proguard.cfg b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/proguard.cfg new file mode 100644 index 0000000..3e84fc7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/proguard.cfg @@ -0,0 +1,36 @@ +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-verbose +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class com.android.vending.licensing.ILicensingService + +-keepclasseswithmembernames class * { + native ; +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/res/drawable-hdpi/icon.png b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/res/drawable-hdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d7753923a3b4ffcb78aceccf782760aa08e7f483 GIT binary patch literal 2472 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 literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/res/drawable-mdpi/icon.png b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/res/drawable-mdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ff7be820f80a465e3be8bd4d46ebd63fe9392682 GIT binary patch literal 1511 zcmVWdKxYbs#b^AWC&?ATls9F(5HEIyE^uGBF@6Ff}kR!;(A100007bV*G` z2ipe~6$LCbh{VhQ000SaNLh0L01m?d01m?e$8V@)00004XF*Lt006O%3;baP000F( zNklr>ESsv@Mi|liH?#%9%QkxJB zVwyeKOwPS??!CYJKWFZ~IO#(X#-(^dZ0fFx(d@gk*dP%*o69dY!d#01#eiZ!F`&h^ z7*Gu8QBC!LzL^R1Uc|t4IQvJYB#YI`+csnQ9vIUeJ5VTy&d>2v4ZP#v;PIp6II@y( za_8mzw0F3|*RY`mf@VR1W~D3?!1Y(rbO=61Lw5Qm?l^F@8$~D3)Z;jQT+ptgJha-4-15`Xt zY==h4Ed}&`h5m+x1B%qpuct^9#r@(IYMa^8B{{fp7;kJwo&^X-he&8SDP>j6nTVU$ za`OZV`O*Jvw5wxCSr(RfwoKlN<#_&MSe^kNrVoasPfvd$$%&IBDJ?B+S+K3peUSz5 zJOnjVTBvjo=&EK-_R@kEqoqW|mK=>}Nfv7`9Sp;Zi5}x7k9(mlI2$QY0(nUno zH%MAFdlNK|*=!mg9}g=gNxqB}J6F99F&vjTv#t5cS~2hn7kPqKOPk;qFruqB0;FGQvW@ zjT_Z?;WMZW(J_9%e_~=Hny=~UX~8vw&hJ>=u+rhdtK||=u5nPsvFf3OszlkBo1&I+ z3nB|9{ph8Rj{s3IW>?|2Q_30zX=op0PS-Fb4qR^?{%l12(&(n8l;XihTaE6t>& zBt7m;j@k4&9i`IkcFWtLaL%CDljE88guFqcQAhst)IFcip-iJvsRBWNm_|^WmX~sW zKlW>1XKxxIw#J^dD4@J+*im%m7JJR+>FO;=YJ<FL?Oe}6+mLs3x?Ek-~jLuO{C z)9Gw)Z;t{IL1krSM@I)qNE@iDtINp9sI9F%c<^9-eLba&Dzdt|n#m%4nez}o$B^cU ziHY>^2LgeVl$5ctF>>hnH zBY}NBAL&g;iN#{U+1!T&S}2SCJ`@9r0mXn8-(o;9p#L2Z_oV$j^%s51@w8w`n1uiU N002ovPDHLkV1lSs(@g*X literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/res/layout/main.xml b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/res/layout/main.xml new file mode 100644 index 0000000..6c06966 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/res/layout/main.xml @@ -0,0 +1,34 @@ + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/res/values/strings.xml b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/res/values/strings.xml new file mode 100644 index 0000000..c3d96aa --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/res/values/strings.xml @@ -0,0 +1,31 @@ + + + + Pfx 5 Raycast + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java new file mode 100644 index 0000000..ec83e64 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java @@ -0,0 +1,113 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.renderingsupport; + +import android.opengl.GLSurfaceView; +import android.content.Context; +import android.view.MotionEvent; + +/** + * Implementation of the OpenGL ES view window and creates/assigns a renderer. + * Handles touch events to allow the user to change scene on tap, move the camera + * around by touch based movement, and allows the user to zoom in and out by pinching. + * @author ahamilton + * + */ +public class PhysicsEffectsGLSurfaceView extends GLSurfaceView { + public PhysicsEffectsGLSurfaceView(Context context) { + super(context); + peRenderer = new PhysicsEffectsRenderer(); + setRenderer(peRenderer); + } + + float x1 = 0, x2, y1 = 0, y2; + long downTime; + + /** + * Function to process touch events for camera and scene control + * + */ + public boolean onTouchEvent(final MotionEvent event) { + switch(event.getAction()) { + case(MotionEvent.ACTION_DOWN): + x1 = event.getX(); + y1 = event.getY(); + downTime = event.getDownTime(); + break; + case(MotionEvent.ACTION_UP): + if(event.getEventTime() - downTime < 100) nativeSceneChange(); + break; + case(MotionEvent.ACTION_MOVE): { + if(event.getPointerCount() == 1){ + x2 = event.getX(); + y2 = event.getY(); + float dx = x2-x1; + float dy = y2-y1; + + // Use dx and dy to determine the direction + if(dx > 0) { + nativeCameraLeft(); + } else { + nativeCameraRight(); + } + if(dy > 0){ + nativeCameraUp(); + } else { + nativeCameraDown(); + } + x1=x2; + y1=y2; + } else if(event.getPointerCount() == 2){ + y2 = event.getY(); + + float dy = y2-y1; + + // Use dy to determine zoom + if(dy > 0){ + nativeCameraZoomIn(); + } else { + nativeCameraZoomOut(); + } + y1=y2; + } + } + } + return true; + } + + PhysicsEffectsRenderer peRenderer; + + private static native void nativeCameraUp(); + private static native void nativeCameraDown(); + private static native void nativeCameraLeft(); + private static native void nativeCameraRight(); + private static native void nativeCameraZoomOut(); + private static native void nativeCameraZoomIn(); + private static native void nativeSceneChange(); +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/src/pfx/renderingsupport/PhysicsEffectsRenderer.java b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/src/pfx/renderingsupport/PhysicsEffectsRenderer.java new file mode 100644 index 0000000..5ca66d4 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/src/pfx/renderingsupport/PhysicsEffectsRenderer.java @@ -0,0 +1,101 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.renderingsupport; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLSurfaceView; +import android.util.Log; + +/** + * Implementation of the renderer. It calls the native physicseffects code + * to run on the init and drawframe allowing the sample to perform its simulation. + * @author ahamilton + * + */ +public class PhysicsEffectsRenderer implements GLSurfaceView.Renderer { + boolean startup = true; + boolean notEnded = true; + static long startuptime; + static long endtime; + int frameCounter; + + /** + * Initilize the physics simulation after the GL surface is created. + * + */ + public void onSurfaceCreated(GL10 gl, EGLConfig config) + { + Log.v("Init physics", "Initing physics"); + nativePhysicsEffectsInit(); + Log.v("Init physics", "Inited physics"); + } + + /** + * Set the viewport for a changed GL surface + * + */ + public void onSurfaceChanged(GL10 gl, int w, int h) + { + gl.glViewport(0, 0, w, h); + } + + /** + * Perform one simulation step and render the scene. + * + */ + public void onDrawFrame(GL10 gl) + { + if(startup){ + startup = false; + frameCounter = 0; + startuptime = System.currentTimeMillis(); + endtime = startuptime + 10000; // sets run time to be 30 seconds + } + + nativePhysicsEffectsSimulate(); + + frameCounter++; + long lCurrentTime = System.currentTimeMillis(); + if(lCurrentTime > endtime && notEnded) { + float fFrameRate = (1000.0f * (float)frameCounter) / ((float)lCurrentTime - startuptime); + Log.v("PHYSICS TIMING STUDY", "Number of Frames: " + Integer.toString(frameCounter)); + Log.v("PHYSICS TIMING STUDY", "Time ellapsed (milliseconds): " + Long.toString(lCurrentTime - startuptime)); + Log.v("PHYSICS TIMING STUDY", "Bullet Frame Rate: " + Float.toString(fFrameRate) + "fps"); + notEnded = false; + } + } + + private static native void nativePhysicsEffectsInit(); + private static native void nativePhysicsEffectsSimulate(); + private static native void nativePhysicsEffectsUpdate(); + private static native void nativePhysicsEffectsPhysStep(); + private static native void nativePhysicsEffectsRender(); +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/src/pfx/sample5/PfxApp_5_Raycast.java b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/src/pfx/sample5/PfxApp_5_Raycast.java new file mode 100644 index 0000000..2f8b310 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_5_Raycast/src/pfx/sample5/PfxApp_5_Raycast.java @@ -0,0 +1,58 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.sample5; + +import pfx.renderingsupport.PhysicsEffectsGLSurfaceView; + +import android.app.Activity; +import android.opengl.GLSurfaceView; +import android.os.Bundle; + +/** + * When program loads it creates a OpenGl ES render window for + * the bullet sample projects to run in and loads the complied + * physics effects libraries. + * @author ahamilton + * + */ +public class PfxApp_5_Raycast extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + peGLView = new PhysicsEffectsGLSurfaceView(this); + setContentView(peGLView); + } + + private GLSurfaceView peGLView; + + //This is where you specify which physics effects sample you would like to load + static { + System.loadLibrary("PfxApp_5_Raycast"); + } +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/.classpath b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/.classpath new file mode 100644 index 0000000..98132ca --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/.classpath @@ -0,0 +1,35 @@ + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/.externalToolBuilders/BuildSampleJNICode.launch b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/.externalToolBuilders/BuildSampleJNICode.launch new file mode 100644 index 0000000..59c20e3 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/.externalToolBuilders/BuildSampleJNICode.launch @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/.project b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/.project new file mode 100644 index 0000000..07e46eb --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/.project @@ -0,0 +1,114 @@ + + + + PfxApp_6_Joint + + + PfxLibrary + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + org.eclipse.ui.externaltools.ExternalToolBuilder + auto,full,incremental, + + + LaunchConfigHandle + <project>/.externalToolBuilders/BuildSampleJNICode.launch + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + + + src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java + 1 + PFX_ROOT/project/Android/PfxApp_6_Joint/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java + + + src/pfx/renderingsupport/PhysicsEffectsRenderer.java + 1 + PFX_ROOT/project/Android/PfxApp_6_Joint/src/pfx/renderingsupport/PhysicsEffectsRenderer.java + + + src/pfx/sample6/PfxApp_6_Joint.java + 1 + PFX_ROOT/project/Android/PfxApp_6_Joint/src/pfx/sample/PfxApp_6_Joint.java + + + + + 1305070288951 + jni + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-.svn + + + + 1305070295995 + src + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-.svn + + + + + + PFX_ROOT + $%7BPARENT-3-PROJECT_LOC%7D + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/AndroidManifest.xml b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/AndroidManifest.xml new file mode 100644 index 0000000..f8eb602 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/AndroidManifest.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/build.xml b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/build.xml new file mode 100644 index 0000000..20c3a8a --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/build.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/default.properties b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/default.properties new file mode 100644 index 0000000..f4b4f17 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/default.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-9 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/jni/Android.mk b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/jni/Android.mk new file mode 100644 index 0000000..4b00f13 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/jni/Android.mk @@ -0,0 +1,107 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +# NOTE: The local path here is defined based on an environment +# variable that points to the root of the Bullet/PhysicsEffects +# code base. The variable must be set in the Cygwin style, e.g., +# BULLET_PFX_ROOT_CYGWIN = /cygdrive/d/tools/PhysicsEffectsRootPath +# +# The reason for *not* just setting local path := $(call my-dir) +# is that we wish to access local source files that are *not* +# located in a "jni" subfolder and *not* located in a subfolder +# of the project folder. This enables us to have Eclipse and +# Android NDK projects that fit neatly into the Bullet/PhysicsEffects +# folder structure, enabling a multi platform code base, without +# forcing the "jni" and subfolder structure that Android SDK/NDK +# prefer for pure Android projects. +LOCAL_PATH:= $(BULLET_PFX_ROOT_CYGWIN) + +# Copy the shared static library, libpfxlibrary.a, into the build +include $(CLEAR_VARS) +LOCAL_MODULE := pfxlibrary +LOCAL_SRC_FILES := project/Android/PfxLibrary/obj/local/armeabi-v7a/libpfxlibrary.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +# Warning: do not enable SIMD vector math functions or NEON for running +# in the Android NDK emulator. NEON requires a physical device +# with NEON support. +# +# Note that in theory we can let LOCAL_ARM_NEON := true determine +# that the flags -mfpu=neon and -mfloat-abi=softfp should be applied. +# However, in practice we have seen one case where the ndk-build +# script "forgets" these flags for the occasional *.cpp file, thus +# causing those files to access the std definition of vectormath +# classes, which are completely different, including different size. +# So, we explicitly apply these flags to avoid having a broken +# build. +# +# Include -DSCE_PFX_USE_SIMD_VECTORMATH to build for ARM NEON SIMD +# intrinsics, and leave it off to use NEON for scalar math but without +# SIMD. + +LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -mfpu=neon -mfloat-abi=softfp -DSCE_PFX_USE_SIMD_VECTORMATH + +# apply these flags if needed +# -ffast-math -funsafe-math-optimizations + +# apply this to disable optimization +# TARGET_CFLAGS := $(TARGET_CFLAGS) -O0 + +# apply these 2 to turn on assembly output (*.c/*.cpp to *.s file) +# compile-cpp-source = $(eval $(call ev-compile-cpp-source,$1,$(1:%$(LOCAL_CPP_EXTENSION)=%.s))) +# TARGET_CFLAGS := $(TARGET_CFLAGS) -S + +# specify static libraries to link in +LOCAL_STATIC_LIBRARIES := pfxlibrary + +# Enable or disable NEON. Don't forget to apply, or not apply, -mfpu=neon and -mfloat-abi=softfp +# flags in addition, e.g., if this is true both of those need to be included in LOCAL_CFLAGS +# to avoid the possibility that ndk-build will "forget" to add them on some files +LOCAL_ARM_NEON := true +TARGET_CFLAGS := $(filter-out -ffpu=vfp,$(TARGET_CFLAGS)) + +LOCAL_MODULE := PfxApp_6_Joint +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include \ + $(LOCAL_PATH)sample/api_physics_effects/6_joint \ + $(LOCAL_PATH)sample/api_physics_effects/common + +LOCAL_SRC_FILES := \ + sample/api_physics_effects/common/jni/physicseffects-android.cpp \ + sample/api_physics_effects/6_joint/main.cpp \ + sample/api_physics_effects/6_joint/physics_func.cpp \ + sample/api_physics_effects/common/ctrl_func.android.cpp \ + sample/api_physics_effects/common/render_func.android.cpp \ + sample/api_physics_effects/common/perf_func.android.cpp + +LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -lGLESv1_CM -ldl -lm -llog + +include $(BUILD_SHARED_LIBRARY) + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/jni/Application.mk b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/jni/Application.mk new file mode 100644 index 0000000..738b74a --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/jni/Application.mk @@ -0,0 +1,31 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +APP_MODULES := PfxApp_6_Joint +APP_ABI := armeabi-v7a +APP_OPTIM := release diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/local.properties b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/local.properties new file mode 100644 index 0000000..1659ad7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/local.properties @@ -0,0 +1,10 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must *NOT* be checked in Version Control Systems, +# as it contains information specific to your local configuration. + +# location of the SDK. This is only used by Ant +# For customization when using a Version Control System, please read the +# header note. +sdk.dir=F:\\sdks\\Android\\android-sdk diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/proguard.cfg b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/proguard.cfg new file mode 100644 index 0000000..3e84fc7 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/proguard.cfg @@ -0,0 +1,36 @@ +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-verbose +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class com.android.vending.licensing.ILicensingService + +-keepclasseswithmembernames class * { + native ; +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/res/drawable-hdpi/icon.png b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/res/drawable-hdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d7753923a3b4ffcb78aceccf782760aa08e7f483 GIT binary patch literal 2472 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 literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/res/drawable-mdpi/icon.png b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/res/drawable-mdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ff7be820f80a465e3be8bd4d46ebd63fe9392682 GIT binary patch literal 1511 zcmVWdKxYbs#b^AWC&?ATls9F(5HEIyE^uGBF@6Ff}kR!;(A100007bV*G` z2ipe~6$LCbh{VhQ000SaNLh0L01m?d01m?e$8V@)00004XF*Lt006O%3;baP000F( zNklr>ESsv@Mi|liH?#%9%QkxJB zVwyeKOwPS??!CYJKWFZ~IO#(X#-(^dZ0fFx(d@gk*dP%*o69dY!d#01#eiZ!F`&h^ z7*Gu8QBC!LzL^R1Uc|t4IQvJYB#YI`+csnQ9vIUeJ5VTy&d>2v4ZP#v;PIp6II@y( za_8mzw0F3|*RY`mf@VR1W~D3?!1Y(rbO=61Lw5Qm?l^F@8$~D3)Z;jQT+ptgJha-4-15`Xt zY==h4Ed}&`h5m+x1B%qpuct^9#r@(IYMa^8B{{fp7;kJwo&^X-he&8SDP>j6nTVU$ za`OZV`O*Jvw5wxCSr(RfwoKlN<#_&MSe^kNrVoasPfvd$$%&IBDJ?B+S+K3peUSz5 zJOnjVTBvjo=&EK-_R@kEqoqW|mK=>}Nfv7`9Sp;Zi5}x7k9(mlI2$QY0(nUno zH%MAFdlNK|*=!mg9}g=gNxqB}J6F99F&vjTv#t5cS~2hn7kPqKOPk;qFruqB0;FGQvW@ zjT_Z?;WMZW(J_9%e_~=Hny=~UX~8vw&hJ>=u+rhdtK||=u5nPsvFf3OszlkBo1&I+ z3nB|9{ph8Rj{s3IW>?|2Q_30zX=op0PS-Fb4qR^?{%l12(&(n8l;XihTaE6t>& zBt7m;j@k4&9i`IkcFWtLaL%CDljE88guFqcQAhst)IFcip-iJvsRBWNm_|^WmX~sW zKlW>1XKxxIw#J^dD4@J+*im%m7JJR+>FO;=YJ<FL?Oe}6+mLs3x?Ek-~jLuO{C z)9Gw)Z;t{IL1krSM@I)qNE@iDtINp9sI9F%c<^9-eLba&Dzdt|n#m%4nez}o$B^cU ziHY>^2LgeVl$5ctF>>hnH zBY}NBAL&g;iN#{U+1!T&S}2SCJ`@9r0mXn8-(o;9p#L2Z_oV$j^%s51@w8w`n1uiU N002ovPDHLkV1lSs(@g*X literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/res/layout/main.xml b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/res/layout/main.xml new file mode 100644 index 0000000..6c06966 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/res/layout/main.xml @@ -0,0 +1,34 @@ + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/res/values/strings.xml b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/res/values/strings.xml new file mode 100644 index 0000000..548a32f --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/res/values/strings.xml @@ -0,0 +1,31 @@ + + + + Pfx 6 Joint + diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java new file mode 100644 index 0000000..ec83e64 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/src/pfx/renderingsupport/PhysicsEffectsGLSurfaceView.java @@ -0,0 +1,113 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.renderingsupport; + +import android.opengl.GLSurfaceView; +import android.content.Context; +import android.view.MotionEvent; + +/** + * Implementation of the OpenGL ES view window and creates/assigns a renderer. + * Handles touch events to allow the user to change scene on tap, move the camera + * around by touch based movement, and allows the user to zoom in and out by pinching. + * @author ahamilton + * + */ +public class PhysicsEffectsGLSurfaceView extends GLSurfaceView { + public PhysicsEffectsGLSurfaceView(Context context) { + super(context); + peRenderer = new PhysicsEffectsRenderer(); + setRenderer(peRenderer); + } + + float x1 = 0, x2, y1 = 0, y2; + long downTime; + + /** + * Function to process touch events for camera and scene control + * + */ + public boolean onTouchEvent(final MotionEvent event) { + switch(event.getAction()) { + case(MotionEvent.ACTION_DOWN): + x1 = event.getX(); + y1 = event.getY(); + downTime = event.getDownTime(); + break; + case(MotionEvent.ACTION_UP): + if(event.getEventTime() - downTime < 100) nativeSceneChange(); + break; + case(MotionEvent.ACTION_MOVE): { + if(event.getPointerCount() == 1){ + x2 = event.getX(); + y2 = event.getY(); + float dx = x2-x1; + float dy = y2-y1; + + // Use dx and dy to determine the direction + if(dx > 0) { + nativeCameraLeft(); + } else { + nativeCameraRight(); + } + if(dy > 0){ + nativeCameraUp(); + } else { + nativeCameraDown(); + } + x1=x2; + y1=y2; + } else if(event.getPointerCount() == 2){ + y2 = event.getY(); + + float dy = y2-y1; + + // Use dy to determine zoom + if(dy > 0){ + nativeCameraZoomIn(); + } else { + nativeCameraZoomOut(); + } + y1=y2; + } + } + } + return true; + } + + PhysicsEffectsRenderer peRenderer; + + private static native void nativeCameraUp(); + private static native void nativeCameraDown(); + private static native void nativeCameraLeft(); + private static native void nativeCameraRight(); + private static native void nativeCameraZoomOut(); + private static native void nativeCameraZoomIn(); + private static native void nativeSceneChange(); +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/src/pfx/renderingsupport/PhysicsEffectsRenderer.java b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/src/pfx/renderingsupport/PhysicsEffectsRenderer.java new file mode 100644 index 0000000..5ca66d4 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/src/pfx/renderingsupport/PhysicsEffectsRenderer.java @@ -0,0 +1,101 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.renderingsupport; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLSurfaceView; +import android.util.Log; + +/** + * Implementation of the renderer. It calls the native physicseffects code + * to run on the init and drawframe allowing the sample to perform its simulation. + * @author ahamilton + * + */ +public class PhysicsEffectsRenderer implements GLSurfaceView.Renderer { + boolean startup = true; + boolean notEnded = true; + static long startuptime; + static long endtime; + int frameCounter; + + /** + * Initilize the physics simulation after the GL surface is created. + * + */ + public void onSurfaceCreated(GL10 gl, EGLConfig config) + { + Log.v("Init physics", "Initing physics"); + nativePhysicsEffectsInit(); + Log.v("Init physics", "Inited physics"); + } + + /** + * Set the viewport for a changed GL surface + * + */ + public void onSurfaceChanged(GL10 gl, int w, int h) + { + gl.glViewport(0, 0, w, h); + } + + /** + * Perform one simulation step and render the scene. + * + */ + public void onDrawFrame(GL10 gl) + { + if(startup){ + startup = false; + frameCounter = 0; + startuptime = System.currentTimeMillis(); + endtime = startuptime + 10000; // sets run time to be 30 seconds + } + + nativePhysicsEffectsSimulate(); + + frameCounter++; + long lCurrentTime = System.currentTimeMillis(); + if(lCurrentTime > endtime && notEnded) { + float fFrameRate = (1000.0f * (float)frameCounter) / ((float)lCurrentTime - startuptime); + Log.v("PHYSICS TIMING STUDY", "Number of Frames: " + Integer.toString(frameCounter)); + Log.v("PHYSICS TIMING STUDY", "Time ellapsed (milliseconds): " + Long.toString(lCurrentTime - startuptime)); + Log.v("PHYSICS TIMING STUDY", "Bullet Frame Rate: " + Float.toString(fFrameRate) + "fps"); + notEnded = false; + } + } + + private static native void nativePhysicsEffectsInit(); + private static native void nativePhysicsEffectsSimulate(); + private static native void nativePhysicsEffectsUpdate(); + private static native void nativePhysicsEffectsPhysStep(); + private static native void nativePhysicsEffectsRender(); +} diff --git a/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/src/pfx/sample6/PfxApp_6_Joint.java b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/src/pfx/sample6/PfxApp_6_Joint.java new file mode 100644 index 0000000..f2f3593 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxApp_6_Joint/src/pfx/sample6/PfxApp_6_Joint.java @@ -0,0 +1,58 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +package pfx.sample6; + +import pfx.renderingsupport.PhysicsEffectsGLSurfaceView; + +import android.app.Activity; +import android.opengl.GLSurfaceView; +import android.os.Bundle; + +/** + * When program loads it creates a OpenGl ES render window for + * the bullet sample projects to run in and loads the complied + * physics effects libraries. + * @author ahamilton + * + */ +public class PfxApp_6_Joint extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + peGLView = new PhysicsEffectsGLSurfaceView(this); + setContentView(peGLView); + } + + private GLSurfaceView peGLView; + + //This is where you specify which physics effects sample you would like to load + static { + System.loadLibrary("PfxApp_6_Joint"); + } +} diff --git a/Extras/PhysicsEffects/project/Android/PfxLibrary/.cproject b/Extras/PhysicsEffects/project/Android/PfxLibrary/.cproject new file mode 100644 index 0000000..362560c --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxLibrary/.cproject @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + make + + all + true + true + true + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxLibrary/.externalToolBuilders/PfxLibraryBuilder.launch b/Extras/PhysicsEffects/project/Android/PfxLibrary/.externalToolBuilders/PfxLibraryBuilder.launch new file mode 100644 index 0000000..5b0e3ce --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxLibrary/.externalToolBuilders/PfxLibraryBuilder.launch @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxLibrary/.project b/Extras/PhysicsEffects/project/Android/PfxLibrary/.project new file mode 100644 index 0000000..0886016 --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxLibrary/.project @@ -0,0 +1,157 @@ + + + + PfxLibrary + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + ?children? + ?name?=outputEntries\|?children?=?name?=entry\\\\\\\|\\\|\|| + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + org.eclipse.ui.externaltools.ExternalToolBuilder + full,incremental, + + + LaunchConfigHandle + <project>/.externalToolBuilders/PfxLibraryBuilder.launch + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + include + 2 + PFX_ROOT/include + + + src + 2 + PFX_ROOT/src + + + + + 1304973509800 + include + 21 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-*.h + + + + 1304973468596 + src + 21 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-*.cpp + + + + + + PFX_ROOT + $%7BPARENT-3-PROJECT_LOC%7D + + + diff --git a/Extras/PhysicsEffects/project/Android/PfxLibrary/jni/Android.mk b/Extras/PhysicsEffects/project/Android/PfxLibrary/jni/Android.mk new file mode 100644 index 0000000..b342f5b --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxLibrary/jni/Android.mk @@ -0,0 +1,173 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +# NOTE: The local path here is defined based on an environment +# variable that points to the root of the Bullet/PhysicsEffects +# code base. The variable must be set in the Cygwin style, e.g., +# BULLET_PFX_ROOT_CYGWIN = /cygdrive/d/tools/PhysicsEffectsRootPath +# +# The reason for *not* just setting local path := $(call my-dir) +# is that we wish to access local source files that are *not* +# located in a "jni" subfolder and *not* located in a subfolder +# of the project folder. This enables us to have Eclipse and +# Android NDK projects that fit neatly into the Bullet/PhysicsEffects +# folder structure, enabling a multi platform code base, without +# forcing the "jni" and subfolder structure that Android SDK/NDK +# prefer for pure Android projects. +LOCAL_PATH := $(BULLET_PFX_ROOT_CYGWIN) + +include $(CLEAR_VARS) +# Warning: do not enable SIMD vector math functions or NEON for running +# in the Android NDK emulator. NEON requires a physical device +# with NEON support. +# +# Note that in theory we can let LOCAL_ARM_NEON := true determine +# that the flags -mfpu=neon and -mfloat-abi=softfp should be applied. +# However, in practice we have seen one case where the ndk-build +# script "forgets" these flags for the occasional *.cpp file, thus +# causing those files to access the std definition of vectormath +# classes, which are completely different, including different size. +# So, we explicitly apply these flags to avoid having a broken +# build. +# +# Include -DSCE_PFX_USE_SIMD_VECTORMATH to build for ARM NEON SIMD +# intrinsics, and leave it off to use NEON for scalar math but without +# SIMD. +LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -DUSE_PTHREADS -mfpu=neon -mfloat-abi=softfp -pthread -DSCE_PFX_USE_SIMD_VECTORMATH + +# apply these flags if needed +# -ffast-math -funsafe-math-optimizations + +# apply this to disable optimization +# TARGET_CFLAGS := $(TARGET_CFLAGS) -O0 + +# apply these 2 to turn on assembly output (*.c/*.cpp to *.s file) +#compile-cpp-source = $(eval $(call ev-compile-cpp-source,$1,$(1:%$(LOCAL_CPP_EXTENSION)=%.s))) +#TARGET_CFLAGS := $(TARGET_CFLAGS) -S + +# Enable or disable NEON. Don't forget to apply, or not apply, -mfpu=neon and -mfloat-abi=softfp +# flags in addition, e.g., if this is true both of those need to be included in LOCAL_CFLAGS +# to avoid the possibility that ndk-build will "forget" to add them on some files +LOCAL_ARM_NEON := true +TARGET_CFLAGS := $(filter-out -ffpu=vfp,$(TARGET_CFLAGS)) + +# setup to build static library, libpfxlibrary.a +LOCAL_MODULE := libpfxlibrary +LOCAL_C_INCLUDES := \ + include \ + include/physics_effects/base_level \ + include/physics_effects/base_level/base \ + include/physics_effects/base_level/broadphase \ + include/physics_effects/base_level/collision \ + include/physics_effects/base_level/rigidbody \ + include/physics_effects/base_level/solver \ + include/physics_effects/base_level/sort \ + include/physics_effects/low_level \ + include/physics_effects/low_level/broadphase \ + include/physics_effects/low_level/collision \ + include/physics_effects/low_level/solver \ + include/physics_effects/low_level/sort \ + include/physics_effects/low_level/task \ + include/physics_effects/util \ + include/vecmath/neon \ + src/base_level/broadphase \ + src/base_level/collision \ + src/base_level/solver \ + src/base_level/sort \ + src/low_level/broadphase \ + src/low_level/collision \ + src/low_level/solver \ + src/low_level/sort \ + src/low_level/task \ + src/util \ + src + +# Note that vectormath_neon_assembly_implementations.S is needed here in order to compile, link, and use the +# NEON version of the vectormath library +LOCAL_SRC_FILES := \ + src/base_level/broadphase/pfx_update_broadphase_proxy.cpp \ + src/base_level/collision/pfx_collidable.cpp \ + src/base_level/collision/pfx_contact_box_box.cpp \ + src/base_level/collision/pfx_contact_box_capsule.cpp \ + src/base_level/collision/pfx_contact_box_sphere.cpp \ + src/base_level/collision/pfx_contact_cache.cpp \ + src/base_level/collision/pfx_contact_capsule_capsule.cpp \ + src/base_level/collision/pfx_contact_capsule_sphere.cpp \ + src/base_level/collision/pfx_contact_large_tri_mesh.cpp \ + src/base_level/collision/pfx_contact_manifold.cpp \ + src/base_level/collision/pfx_contact_sphere_sphere.cpp \ + src/base_level/collision/pfx_contact_tri_mesh_box.cpp \ + src/base_level/collision/pfx_contact_tri_mesh_capsule.cpp \ + src/base_level/collision/pfx_contact_tri_mesh_convex.cpp \ + src/base_level/collision/pfx_contact_tri_mesh_cylinder.cpp \ + src/base_level/collision/pfx_contact_tri_mesh_sphere.cpp \ + src/base_level/collision/pfx_gjk_solver.cpp \ + src/base_level/collision/pfx_gjk_support_func.cpp \ + src/base_level/collision/pfx_intersect_ray_box.cpp \ + src/base_level/collision/pfx_intersect_ray_capsule.cpp \ + src/base_level/collision/pfx_intersect_ray_convex.cpp \ + src/base_level/collision/pfx_intersect_ray_cylinder.cpp \ + src/base_level/collision/pfx_intersect_ray_large_tri_mesh.cpp \ + src/base_level/collision/pfx_intersect_ray_sphere.cpp \ + src/base_level/collision/pfx_shape.cpp \ + src/base_level/collision/pfx_simplex_solver.cpp \ + src/base_level/solver/pfx_contact_constraint.cpp \ + src/base_level/solver/pfx_joint_ball.cpp \ + src/base_level/solver/pfx_joint_fix.cpp \ + src/base_level/solver/pfx_joint_hinge.cpp \ + src/base_level/solver/pfx_joint_slider.cpp \ + src/base_level/solver/pfx_joint_swing_twist.cpp \ + src/base_level/solver/pfx_joint_universal.cpp \ + src/base_level/solver/pfx_constraint_row_solver_neon.cpp \ + src/base_level/sort/pfx_sort.cpp \ + src/low_level/broadphase/pfx_broadphase_single.cpp \ + src/low_level/collision/pfx_batched_ray_cast_single.cpp \ + src/low_level/collision/pfx_batched_ray_cast_parallel.cpp \ + src/low_level/collision/pfx_collision_detection_single.cpp \ + src/low_level/collision/pfx_collision_detection_parallel.cpp \ + src/low_level/collision/pfx_detect_collision_func.cpp \ + src/low_level/collision/pfx_intersect_ray_func.cpp \ + src/low_level/collision/pfx_island_generation.cpp \ + src/low_level/collision/pfx_ray_cast.cpp \ + src/low_level/collision/pfx_refresh_contacts_single.cpp \ + src/low_level/collision/pfx_refresh_contacts_parallel.cpp \ + src/low_level/solver/pfx_constraint_solver_single.cpp \ + src/low_level/solver/pfx_constraint_solver_parallel.cpp \ + src/low_level/solver/pfx_joint_constraint_func.cpp \ + src/low_level/solver/pfx_update_rigid_states_single.cpp \ + src/low_level/solver/pfx_update_rigid_states_parallel.cpp \ + src/low_level/sort/pfx_parallel_sort_single.cpp \ + src/low_level/task/pfx_task_manager_pthreads.cpp \ + src/low_level/task/pfx_sync_components_pthreads.cpp \ + src/util/pfx_mass.cpp \ + src/util/pfx_mesh_creator.cpp \ + include/vecmath/neon/vectormath_neon_assembly_implementations.S + +LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -lGLESv1_CM -ldl -lm -llog + +include $(BUILD_STATIC_LIBRARY) diff --git a/Extras/PhysicsEffects/project/Android/PfxLibrary/jni/Application.mk b/Extras/PhysicsEffects/project/Android/PfxLibrary/jni/Application.mk new file mode 100644 index 0000000..6c3c6ca --- /dev/null +++ b/Extras/PhysicsEffects/project/Android/PfxLibrary/jni/Application.mk @@ -0,0 +1,31 @@ +# +# Applied Research Associates Inc. (c)2011 +# +# 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 Applied Research Associates Inc 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. +# + +APP_MODULES := libpfxlibrary +APP_ABI := armeabi-v7a +APP_OPTIM := release diff --git a/Extras/PhysicsEffects/project/msvc2008_32/BulletCollision.vcproj b/Extras/PhysicsEffects/project/msvc2008_32/BulletCollision.vcproj new file mode 100644 index 0000000..79e0c88 --- /dev/null +++ b/Extras/PhysicsEffects/project/msvc2008_32/BulletCollision.vcproj @@ -0,0 +1,1206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/msvc2008_32/BulletDynamics.vcproj b/Extras/PhysicsEffects/project/msvc2008_32/BulletDynamics.vcproj new file mode 100644 index 0000000..cfc8b14 --- /dev/null +++ b/Extras/PhysicsEffects/project/msvc2008_32/BulletDynamics.vcproj @@ -0,0 +1,566 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/msvc2008_32/BulletMultiThreaded.vcproj b/Extras/PhysicsEffects/project/msvc2008_32/BulletMultiThreaded.vcproj new file mode 100644 index 0000000..baf77f8 --- /dev/null +++ b/Extras/PhysicsEffects/project/msvc2008_32/BulletMultiThreaded.vcproj @@ -0,0 +1,558 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/msvc2008_32/BulletSoftBody.vcproj b/Extras/PhysicsEffects/project/msvc2008_32/BulletSoftBody.vcproj new file mode 100644 index 0000000..e8f5c40 --- /dev/null +++ b/Extras/PhysicsEffects/project/msvc2008_32/BulletSoftBody.vcproj @@ -0,0 +1,298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/msvc2008_32/LinearMath.vcproj b/Extras/PhysicsEffects/project/msvc2008_32/LinearMath.vcproj new file mode 100644 index 0000000..28bc425 --- /dev/null +++ b/Extras/PhysicsEffects/project/msvc2008_32/LinearMath.vcproj @@ -0,0 +1,478 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/msvc2008_32/MiniCL.vcproj b/Extras/PhysicsEffects/project/msvc2008_32/MiniCL.vcproj new file mode 100644 index 0000000..ccbd8fa --- /dev/null +++ b/Extras/PhysicsEffects/project/msvc2008_32/MiniCL.vcproj @@ -0,0 +1,268 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/project/physics_effects_lib.oss.sln b/Extras/PhysicsEffects/project/physics_effects_lib.oss.sln new file mode 100644 index 0000000..7b10ddc --- /dev/null +++ b/Extras/PhysicsEffects/project/physics_effects_lib.oss.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "physics_effects_lib.oss", "physics_effects_lib.oss.vcproj", "{4908A1B7-06F4-4517-936A-D81D140004F7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Win32 Debug|Win32 = Win32 Debug|Win32 + Win32 Release|Win32 = Win32 Release|Win32 + Win64 Debug|Win32 = Win64 Debug|Win32 + Win64 Release|Win32 = Win64 Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win32 Debug|Win32.ActiveCfg = Win32 Debug|Win32 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win32 Debug|Win32.Build.0 = Win32 Debug|Win32 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win32 Release|Win32.ActiveCfg = Win32 Release|Win32 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win32 Release|Win32.Build.0 = Win32 Release|Win32 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win64 Debug|Win32.ActiveCfg = Win64 Debug|x64 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win64 Debug|Win32.Build.0 = Win64 Debug|x64 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win64 Release|Win32.ActiveCfg = Win64 Release|x64 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win64 Release|Win32.Build.0 = Win64 Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Extras/PhysicsEffects/project/physics_effects_lib.oss.vcproj b/Extras/PhysicsEffects/project/physics_effects_lib.oss.vcproj new file mode 100644 index 0000000..1ba888a --- /dev/null +++ b/Extras/PhysicsEffects/project/physics_effects_lib.oss.vcproj @@ -0,0 +1,1221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/sample/CMakeLists.txt b/Extras/PhysicsEffects/sample/CMakeLists.txt new file mode 100644 index 0000000..434caf2 --- /dev/null +++ b/Extras/PhysicsEffects/sample/CMakeLists.txt @@ -0,0 +1,3 @@ +SUBDIRS( + api_physics_effects +) diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/0_console/CMakeLists.txt b/Extras/PhysicsEffects/sample/api_physics_effects/0_console/CMakeLists.txt new file mode 100644 index 0000000..3fabec5 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/0_console/CMakeLists.txt @@ -0,0 +1,47 @@ +cmake_minimum_required(VERSION 2.4) + + +#this line has to appear before 'PROJECT' in order to be able to disable incremental linking +SET(MSVC_INCREMENTAL_DEFAULT ON) + +PROJECT(App_0_Console) + + +SET(App_0_Console_SRCS + main.cpp + physics_func.cpp + ../common/perf_func.win32.cpp +) + +SET(App_0_Console_HDRS + landscape.h + physics_func.h +) + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/include +) + + +#ADD_DEFINITIONS(-DUNICODE) +#ADD_DEFINITIONS(-D_UNICODE) + +ADD_EXECUTABLE(App_0_Console + ${App_0_Console_SRCS} + ${App_0_Console_HDRS} +) +TARGET_LINK_LIBRARIES(App_0_Console + PfxLowLevel + PfxBaseLevel + PfxUtil +) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(App_0_Console PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(App_0_Console PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(App_0_Console PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF() + + + + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/0_console/barrel.h b/Extras/PhysicsEffects/sample/api_physics_effects/0_console/barrel.h new file mode 100644 index 0000000..6574fa8 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/0_console/barrel.h @@ -0,0 +1,202 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define BarrelVtxCount 57 +#define BarrelIdxCount 180 + +static float BarrelVtx[] = { +0.0f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +-0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +0.0f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +-0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.957307f,-0.289072f,0.0f, +0.404509f,0.0f,-0.293893f, 0.809017f,0.0f,-0.587785f, +0.5f,0.0f,0.0f, 1.0f,0.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.774478f,-0.289072f,-0.562691f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +-0.154509f,0.0f,-0.475528f, -0.309017f,0.0f,-0.951057f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +-0.107853f,-0.5f,-0.331936f, -0.295824f,-0.289072f,-0.910453f, +-0.404509f,0.0f,-0.293893f, -0.809017f,0.0f,-0.587785f, +-0.282362f,-0.5f,-0.205148f, -0.774478f,-0.289072f,-0.562691f, +-0.5f,0.0f,0.0f, -1.0f,0.0f,0.0f, +-0.349018f,-0.5f,0.0f, -0.957307f,-0.289072f,0.0f, +-0.404508f,0.0f,0.293893f, -0.809017f,0.0f,0.587785f, +-0.282362f,-0.5f,0.205148f, -0.774478f,-0.289072f,0.562691f, +-0.154509f,0.0f,0.475528f, -0.309017f,0.0f,0.951056f, +-0.107853f,-0.5f,0.331936f, -0.295824f,-0.289072f,0.910453f, +0.154509f,0.0f,0.475528f, 0.309017f,0.0f,0.951056f, +0.107853f,-0.5f,0.331936f, 0.295824f,-0.289072f,0.910453f, +0.404509f,0.0f,0.293892f, 0.809017f,0.0f,0.587785f, +0.282362f,-0.5f,0.205148f, 0.774478f,-0.289072f,0.562691f, +0.282362f,0.5f,-0.205148f, 0.774478f,0.289072f,-0.562691f, +0.349018f,0.5f,0.0f, 0.957307f,0.289072f,0.0f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.107853f,0.5f,-0.331936f, -0.295824f,0.289072f,-0.910453f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.282362f,0.5f,-0.205148f, -0.774478f,0.289072f,-0.562691f, +-0.349018f,0.5f,0.0f, -0.957307f,0.289072f,0.0f, +-0.282362f,0.5f,0.205148f, -0.774478f,0.289072f,0.562691f, +-0.107853f,0.5f,0.331936f, -0.295824f,0.289072f,0.910453f, +0.107853f,0.5f,0.331936f, 0.295824f,0.289072f,0.910453f, +0.282362f,0.5f,0.205148f, 0.774478f,0.289072f,0.562691f, +}; + +static float BarrelTex[] = { +0.0f,0.5f, +0.0f,0.85f, +0.0f,0.75f, +0.0f,0.95f, +0.0f,0.05f, +0.0f,-0.05f, +0.0f,0.15f, +0.0f,0.25f, +0.0f,0.35f, +0.0f,0.45f, +0.0f,0.55f, +0.0f,0.65f, +1.0f,0.5f, +1.0f,0.75f, +1.0f,0.85f, +1.0f,0.95f, +1.0f,-0.05f, +1.0f,0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +0.0f,0.75f, +0.5f,0.85f, +0.5f,0.75f, +0.0f,0.85f, +0.5f,0.95f, +0.0f,0.95f, +0.0f,-0.05f, +0.5f,0.05f, +0.5f,-0.05f, +0.0f,0.05f, +0.5f,0.15f, +0.0f,0.15f, +0.5f,0.25f, +0.0f,0.25f, +0.5f,0.35f, +0.0f,0.35f, +0.5f,0.45f, +0.0f,0.45f, +0.5f,0.55f, +0.0f,0.55f, +0.5f,0.65f, +0.0f,0.65f, +1.0f,0.85f, +1.0f,0.75f, +1.0f,0.95f, +1.0f,0.05f, +1.0f,-0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +}; + +static unsigned short BarrelIdx[] = { +0,1,2, +0,3,1, +0,4,5, +0,6,4, +0,7,6, +0,8,7, +0,9,8, +0,10,9, +0,11,10, +0,2,11, +12,13,14, +12,14,15, +12,16,17, +12,17,18, +12,18,19, +12,19,20, +12,20,21, +12,21,22, +12,22,23, +12,23,13, +24,25,26, +24,27,25, +27,28,25, +27,29,28, +30,31,32, +30,33,31, +33,34,31, +33,35,34, +35,36,34, +35,37,36, +37,38,36, +37,39,38, +39,40,38, +39,41,40, +41,42,40, +41,43,42, +43,44,42, +43,45,44, +45,26,44, +45,24,26, +26,46,47, +26,25,46, +25,48,46, +25,28,48, +32,49,50, +32,31,49, +31,51,49, +31,34,51, +34,52,51, +34,36,52, +36,53,52, +36,38,53, +38,54,53, +38,40,54, +40,55,54, +40,42,55, +42,56,55, +42,44,56, +44,47,56, +44,26,47, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/0_console/landscape.h b/Extras/PhysicsEffects/sample/api_physics_effects/0_console/landscape.h new file mode 100644 index 0000000..00f6cff --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/0_console/landscape.h @@ -0,0 +1,318 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define LargeMeshVtxCount 81 +#define LargeMeshIdxCount 384 + +static float LargeMeshVtx[] = { +-25.0f,-2.19407f,18.5625f, 0.232976f,0.967754f,0.0957829f, +-25.0f,0.0644502f,24.75f, 0.188094f,0.871343f,-0.45319f, +-18.75f,-4.50287f,18.5625f, -0.0716098f,0.995449f,0.0628767f, +-18.75f,-0.39999f,24.75f, -0.0602794f,0.895848f,-0.440253f, +-12.5f,-1.2166f,18.5625f, -0.269469f,0.961403f,0.0555879f, +-12.5f,-0.942431f,24.75f, -0.0997841f,0.993258f,0.0589987f, +-6.25f,1.93598f,18.5625f, -0.283933f,0.956351f,-0.0691025f, +-6.25f,-0.445954f,24.75f, -0.180725f,0.942766f,0.280233f, +0.0f,2.76983f,18.5625f, 0.171645f,0.984908f,0.0222501f, +0.0f,2.76642f,24.75f, 0.0784993f,0.995428f,-0.0544117f, +6.25f,-2.53736f,18.5625f, 0.248298f,0.965028f,0.0840741f, +6.25f,-0.915645f,24.75f, 0.164311f,0.945856f,-0.279926f, +12.5f,-1.60054f,18.5625f, -0.180435f,0.983586f,0.00115547f, +12.5f,0.831925f,24.75f, -0.0692495f,0.964821f,-0.253623f, +18.75f,-0.800282f,18.5625f, 0.10755f,0.951538f,0.288112f, +18.75f,-1.47284f,24.75f, 0.232178f,0.972664f,0.00429361f, +25.0f,-2.78379f,18.5625f, 0.1833f,0.937477f,0.295867f, +25.0f,-0.967508f,24.75f, -0.0773477f,0.956641f,-0.280812f, +-25.0f,-0.352038f,12.375f, -0.192222f,0.972435f,0.131987f, +-18.75f,0.681228f,12.375f, -0.107779f,0.962569f,0.248686f, +-12.5f,2.72065f,12.375f, 0.0520846f,0.993034f,0.105692f, +-6.25f,-1.78776f,12.375f, -0.0133223f,0.99674f,-0.0795754f, +0.0f,1.57707f,12.375f, -0.129025f,0.969662f,-0.207627f, +6.25f,0.424356f,12.375f, 0.180995f,0.97074f,0.157815f, +12.5f,0.283234f,12.375f, -0.16285f,0.973539f,0.160316f, +18.75f,2.57015f,12.375f, -0.165454f,0.978339f,0.124408f, +25.0f,3.07363f,12.375f, -0.00454559f,0.988151f,0.153417f, +-25.0f,-0.893751f,6.1875f, -0.0836251f,0.990084f,-0.112876f, +-18.75f,0.930932f,6.1875f, 0.00269413f,0.971838f,-0.235633f, +-12.5f,-0.684529f,6.1875f, -0.010319f,0.927048f,-0.3748f, +-6.25f,-0.661383f,6.1875f, 0.012265f,0.999875f,-0.00994222f, +0.0f,0.385718f,6.1875f, -0.15435f,0.984937f,-0.0779465f, +6.25f,0.589796f,6.1875f, 0.0241717f,0.999582f,-0.0158589f, +12.5f,0.47454f,6.1875f, -0.017184f,0.997953f,-0.0616073f, +18.75f,1.59939f,6.1875f, -0.0902706f,0.957309f,-0.274609f, +25.0f,1.13434f,6.1875f, 0.0346006f,0.957441f,-0.286547f, +-25.0f,0.74548f,0.0f, 0.329903f,0.930812f,0.157334f, +-18.75f,-2.47437f,0.0f, 0.247844f,0.968142f,0.0357041f, +-12.5f,-4.16309f,1.81975e-007f, -0.0623898f,0.997626f,-0.0291436f, +-6.25f,-0.700022f,0.0f, -0.217067f,0.974987f,-0.0477624f, +0.0f,-0.0957388f,0.0f, -0.117693f,0.990712f,-0.068098f, +6.25f,0.614077f,0.0f, -0.0713214f,0.997305f,0.01722f, +12.5f,0.299109f,0.0f, 0.218606f,0.968641f,0.118094f, +18.75f,-1.71753f,0.0f, 0.0339493f,0.985612f,-0.165579f, +25.0f,-1.12638f,0.0f, -0.0547573f,0.989177f,-0.136126f, +-25.0f,-0.403319f,-6.1875f, -0.1263f,0.989211f,-0.074223f, +-18.75f,-0.0730335f,-6.1875f, 0.0173428f,0.965382f,0.260261f, +-12.5f,-0.450125f,-6.1875f, 0.0658811f,0.875f,0.479619f, +-6.25f,-0.180204f,-6.1875f, 0.0116584f,0.981445f,0.19139f, +0.0f,-0.632679f,-6.1875f, -0.0557983f,0.993041f,-0.103716f, +6.25f,0.308409f,-6.1875f, -0.191898f,0.96766f,-0.163737f, +12.5f,2.5011f,-6.1875f, 0.0758397f,0.996403f,-0.0378189f, +18.75f,-1.69303f,-6.1875f, 0.16761f,0.974057f,0.15205f, +25.0f,-0.141349f,-6.1875f, -0.204846f,0.978471f,0.0251341f, +-25.0f,-1.10316f,-12.375f, -0.0350644f,0.993748f,-0.106001f, +-18.75f,1.06711f,-12.375f, -0.309806f,0.919244f,-0.242922f, +-12.5f,3.61544f,-12.375f, -0.0506281f,0.998702f,-0.00561657f, +-6.25f,1.6504f,-12.375f, 0.322294f,0.937465f,0.131477f, +0.0f,-1.60595f,-12.375f, 0.086016f,0.995916f,0.0274459f, +6.25f,-0.849859f,-12.375f, -0.0332811f,0.997087f,0.0686255f, +12.5f,-0.942201f,-12.375f, -0.153559f,0.982185f,-0.108312f, +18.75f,0.494873f,-12.375f, 0.0753195f,0.981472f,0.176181f, +25.0f,-0.333828f,-12.375f, 0.035057f,0.987194f,0.155624f, +-25.0f,2.1862f,-18.5625f, 0.612899f,0.782306f,0.111138f, +-18.75f,-3.38259f,-18.5625f, 0.0194078f,0.992789f,-0.118297f, +-12.5f,-0.880916f,-18.5625f, -0.282251f,0.949875f,-0.13443f, +-6.25f,0.818158f,-18.5625f, 0.1476f,0.981788f,-0.119612f, +0.0f,-1.48019f,-18.5625f, -0.044551f,0.996013f,-0.0772824f, +6.25f,1.47123f,-18.5625f, -0.117036f,0.97986f,0.161792f, +12.5f,0.164076f,-18.5625f, -0.0340355f,0.978993f,0.201034f, +18.75f,2.14568f,-18.5625f, -0.0439269f,0.994859f,0.0912435f, +25.0f,0.626506f,-18.5625f, 0.208015f,0.968592f,0.136229f, +-25.0f,0.296889f,-24.75f, 0.46973f,0.844327f,-0.257809f, +-18.75f,-3.18022f,-24.75f, -0.0226758f,0.998794f,-0.0435401f, +-12.5f,1.8927f,-24.75f, -0.202772f,0.919836f,0.335836f, +-6.25f,1.46387f,-24.75f, 0.224904f,0.955746f,0.189652f, +0.0f,-2.52726f,-24.75f, -0.0435882f,0.993572f,-0.10447f, +6.25f,1.30397f,-24.75f, -0.28646f,0.956525f,-0.0547707f, +12.5f,1.85812f,-24.75f, 0.0521949f,0.979796f,0.193067f, +18.75f,1.56331f,-24.75f, -0.0270784f,0.999629f,-0.00293115f, +25.0f,1.05366f,-24.75f, 0.161f,0.986887f,-0.0115473f, +}; + +static float LargeMeshTex[] = { +0.125f,0.0f, +0.0f,0.0f, +0.125f,0.125f, +0.0f,0.125f, +0.125f,0.25f, +0.0f,0.25f, +0.125f,0.375f, +0.0f,0.375f, +0.125f,0.5f, +0.0f,0.5f, +0.125f,0.625f, +0.0f,0.625f, +0.125f,0.75f, +0.0f,0.75f, +0.125f,0.875f, +0.0f,0.875f, +0.125f,1.0f, +0.0f,1.0f, +0.25f,0.0f, +0.25f,0.125f, +0.25f,0.25f, +0.25f,0.375f, +0.25f,0.5f, +0.25f,0.625f, +0.25f,0.75f, +0.25f,0.875f, +0.25f,1.0f, +0.375f,0.0f, +0.375f,0.125f, +0.375f,0.25f, +0.375f,0.375f, +0.375f,0.5f, +0.375f,0.625f, +0.375f,0.75f, +0.375f,0.875f, +0.375f,1.0f, +0.5f,0.0f, +0.5f,0.125f, +0.5f,0.25f, +0.5f,0.375f, +0.5f,0.5f, +0.5f,0.625f, +0.5f,0.75f, +0.5f,0.875f, +0.5f,1.0f, +0.625f,0.0f, +0.625f,0.125f, +0.625f,0.25f, +0.625f,0.375f, +0.625f,0.5f, +0.625f,0.625f, +0.625f,0.75f, +0.625f,0.875f, +0.625f,1.0f, +0.75f,0.0f, +0.75f,0.125f, +0.75f,0.25f, +0.75f,0.375f, +0.75f,0.5f, +0.75f,0.625f, +0.75f,0.75f, +0.75f,0.875f, +0.75f,1.0f, +0.875f,0.0f, +0.875f,0.125f, +0.875f,0.25f, +0.875f,0.375f, +0.875f,0.5f, +0.875f,0.625f, +0.875f,0.75f, +0.875f,0.875f, +0.875f,1.0f, +1.0f,0.0f, +1.0f,0.125f, +1.0f,0.25f, +1.0f,0.375f, +1.0f,0.5f, +1.0f,0.625f, +1.0f,0.75f, +1.0f,0.875f, +1.0f,1.0f, +}; + +static unsigned short LargeMeshIdx[] = { +0,1,2, +3,2,1, +2,3,4, +5,4,3, +4,5,6, +7,6,5, +6,7,8, +9,8,7, +8,9,10, +11,10,9, +10,11,12, +13,12,11, +12,13,14, +15,14,13, +14,15,16, +17,16,15, +18,0,19, +2,19,0, +19,2,20, +4,20,2, +20,4,21, +6,21,4, +21,6,22, +8,22,6, +22,8,23, +10,23,8, +23,10,24, +12,24,10, +24,12,25, +14,25,12, +25,14,26, +16,26,14, +27,18,28, +19,28,18, +28,19,29, +20,29,19, +29,20,30, +21,30,20, +30,21,31, +22,31,21, +31,22,32, +23,32,22, +32,23,33, +24,33,23, +33,24,34, +25,34,24, +34,25,35, +26,35,25, +36,27,37, +28,37,27, +37,28,38, +29,38,28, +38,29,39, +30,39,29, +39,30,40, +31,40,30, +40,31,41, +32,41,31, +41,32,42, +33,42,32, +42,33,43, +34,43,33, +43,34,44, +35,44,34, +45,36,46, +37,46,36, +46,37,47, +38,47,37, +47,38,48, +39,48,38, +48,39,49, +40,49,39, +49,40,50, +41,50,40, +50,41,51, +42,51,41, +51,42,52, +43,52,42, +52,43,53, +44,53,43, +54,45,55, +46,55,45, +55,46,56, +47,56,46, +56,47,57, +48,57,47, +57,48,58, +49,58,48, +58,49,59, +50,59,49, +59,50,60, +51,60,50, +60,51,61, +52,61,51, +61,52,62, +53,62,52, +63,54,64, +55,64,54, +64,55,65, +56,65,55, +65,56,66, +57,66,56, +66,57,67, +58,67,57, +67,58,68, +59,68,58, +68,59,69, +60,69,59, +69,60,70, +61,70,60, +70,61,71, +62,71,61, +72,63,73, +64,73,63, +73,64,74, +65,74,64, +74,65,75, +66,75,65, +75,66,76, +67,76,66, +76,67,77, +68,77,67, +77,68,78, +69,78,68, +78,69,79, +70,79,69, +79,70,80, +71,80,70, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/0_console/main.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/0_console/main.cpp new file mode 100644 index 0000000..361c210 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/0_console/main.cpp @@ -0,0 +1,44 @@ +/* +Physics Effects Copyright(C) 2011 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "physics_effects.h" +#include "physics_func.h" +#include "../common/perf_func.h" + +static int frameCount = 0; +static int sceneId = 2; + +int main() +{ + + perf_init(); + physics_init(); + + physics_create_scene(sceneId); + + frameCount = 0; + + //createScene(); + + while(frameCount<600) { + physics_simulate(); + perf_sync(); + } + + SCE_PFX_PRINTF("program complete\n"); + + return 0; +} diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/0_console/physics_func.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/0_console/physics_func.cpp new file mode 100644 index 0000000..250edac --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/0_console/physics_func.cpp @@ -0,0 +1,861 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "physics_func.h" +#include "../common/perf_func.h" + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Data + +#define NUM_RIGIDBODIES 500 +#define NUM_JOINTS 500 +#define NUM_CONTACTS 4000 + +const float timeStep = 0.016f; +const float separateBias = 0.1f; +int iteration = 5; + +//J ワールドサイズ +//E World size +PfxVector3 worldCenter(0.0f); +PfxVector3 worldExtent(500.0f); + +//J 剛体 +//E Rigid body +PfxRigidState states[NUM_RIGIDBODIES]; +PfxRigidBody bodies[NUM_RIGIDBODIES]; +PfxCollidable collidables[NUM_RIGIDBODIES]; +PfxSolverBody solverBodies[NUM_RIGIDBODIES]; +int numRigidBodies = 0; + +//J 地形を表現するためのラージメッシュ +//E Large mesh for representing a landscape +#include "landscape.h" +PfxLargeTriMesh gLargeMesh; + +//J 凸メッシュ +//E Convex Mesh +#include "barrel.h" +PfxConvexMesh gConvex; + +//J プロキシ +//E Proxies +PfxBroadphaseProxy proxies[NUM_RIGIDBODIES]; + +//J ジョイント +//E Joint +PfxConstraintPair jointPairs[NUM_JOINTS]; +PfxJoint joints[NUM_JOINTS]; +int numJoints = 0; + +//J ペア +//E Pairs +unsigned int pairSwap; +unsigned int numPairs[2]; +PfxBroadphasePair pairsBuff[2][NUM_CONTACTS]; + +//J コンタクト +//E Contacts +PfxContactManifold contacts[NUM_CONTACTS]; +int numContacts; + +PfxUInt32 contactIdPool[NUM_CONTACTS]; +int numContactIdPool; + +//J 一時バッファ +//E Temporary buffers +#define POOL_BYTES (5*1024*1024) +unsigned char SCE_PFX_ALIGNED(128) poolBuff[POOL_BYTES]; + +//J 一時バッファ用スタックアロケータ +//E Stack allocator for temporary buffers +PfxHeapManager pool(poolBuff,POOL_BYTES); + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Function + +int frame = 0; + +void broadphase() +{ + pairSwap = 1-pairSwap; + + unsigned int &numPreviousPairs = numPairs[1-pairSwap]; + unsigned int &numCurrentPairs = numPairs[pairSwap]; + PfxBroadphasePair *previousPairs = pairsBuff[1-pairSwap]; + PfxBroadphasePair *currentPairs = pairsBuff[pairSwap]; + + //J 剛体が最も分散している軸を見つける + //E Find the axis along which all rigid bodies are most widely positioned + int axis = 0; + { + PfxVector3 s(0.0f),s2(0.0f); + for(int i=0;i v[0]) axis = 1; + if(v[2] > v[axis]) axis = 2; + } + + //J ブロードフェーズプロキシの更新 + //E Create broadpahse proxies + { + for(int i=0;i 0) { + cId = contactIdPool[--numContactIdPool]; + } + else { + cId = numContacts++; + } + if(cId >= NUM_CONTACTS) { + cId = 0; + } + SCE_PFX_ASSERT(cId < NUM_CONTACTS); + pfxSetContactId(outNewPairs[i],cId); + PfxContactManifold &contact = contacts[cId]; + contact.reset(pfxGetObjectIdA(outNewPairs[i]),pfxGetObjectIdB(outNewPairs[i])); + } + + //J 新規ペアと維持ペアを合成 + //E Merge 'new' and 'keep' pairs + numCurrentPairs = 0; + for(PfxUInt32 i=0;i 0) { + pfxReleaseLargeTriMesh(gLargeMesh); + } + + PfxInt32 ret = pfxCreateLargeTriMesh(gLargeMesh,param); + if(ret != SCE_PFX_OK) { + SCE_PFX_PRINTF("Can't create large mesh.\n"); + } + + int id = numRigidBodies++; + PfxShape shape; + shape.reset(); + shape.setLargeTriMesh(&gLargeMesh); + collidables[id].reset(); + collidables[id].addShape(shape); + collidables[id].finish(); + bodies[id].reset(); + states[id].reset(); + states[id].setPosition(PfxVector3(0.0f,-5.0f,0.0f)); + states[id].setOrientation(PfxQuat::rotationX(0.5f)*PfxQuat::rotationY(0.7f)); + states[id].setMotionType(kPfxMotionTypeFixed); + states[id].setRigidBodyId(id); +} + +void physics_create_scene(int sceneId) +{ + const int numScenes = 4; + int sid = sceneId % numScenes; + + numRigidBodies= 0; + pairSwap = 0; + numPairs[0] = 0; + numPairs[1] = 0; + numContacts = 0; + numContactIdPool = 0; + numJoints = 0; + frame = 0; + + switch(sid) { + case 0: // simple primitives + createSceneBoxGround(); + createScenePrimitives(); + break; + + case 1: // joints + createSceneBoxGround(); + createSceneJoints(); + break; + + case 2: // stacking + createSceneBoxGround(); + createSceneStacking(); + break; + + case 3: // landscape + createSceneLandscape(); + createScenePrimitives(); + break; + } + + SCE_PFX_PRINTF("----- Size of rigid body buffer ------\n"); + SCE_PFX_PRINTF(" size * num = total\n"); + SCE_PFX_PRINTF("PfxRigidState %5d * %5d = %5d bytes\n",sizeof(PfxRigidState),numRigidBodies,sizeof(PfxRigidState)*numRigidBodies); + SCE_PFX_PRINTF("PfxRigidBody %5d * %5d = %5d bytes\n",sizeof(PfxRigidBody),numRigidBodies,sizeof(PfxRigidBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxCollidable %5d * %5d = %5d bytes\n",sizeof(PfxCollidable),numRigidBodies,sizeof(PfxCollidable)*numRigidBodies); + SCE_PFX_PRINTF("PfxJoint %5d * %5d = %5d bytes\n",sizeof(PfxJoint),numJoints,sizeof(PfxJoint)*numJoints); + SCE_PFX_PRINTF("PfxSolverBody %5d * %5d = %5d bytes\n",sizeof(PfxSolverBody),numRigidBodies,sizeof(PfxSolverBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxBroadphaseProxy %5d * %5d = %5d bytes\n",sizeof(PfxBroadphaseProxy),numRigidBodies,sizeof(PfxBroadphaseProxy)*numRigidBodies); + SCE_PFX_PRINTF("PfxContactManifold %5d * %5d = %5d bytes\n",sizeof(PfxContactManifold),NUM_CONTACTS,sizeof(PfxContactManifold)*NUM_CONTACTS); + SCE_PFX_PRINTF("PfxBroadphasePair %5d * %5d = %5d bytes\n",sizeof(PfxBroadphasePair),NUM_CONTACTS,sizeof(PfxBroadphasePair)*NUM_CONTACTS); + + int totalBytes = + (sizeof(PfxRigidState) + sizeof(PfxRigidBody) + sizeof(PfxCollidable) + sizeof(PfxSolverBody) + sizeof(PfxBroadphaseProxy)) * numRigidBodies + + (sizeof(PfxContactManifold) + sizeof(PfxBroadphasePair)) * NUM_CONTACTS; + SCE_PFX_PRINTF("----------------------------------------------------------\n"); + SCE_PFX_PRINTF("Total %5d bytes\n",totalBytes); +} + +/////////////////////////////////////////////////////////////////////////////// +// Initialize / Finalize Engine + +bool physics_init() +{ + return true; +} + +void physics_release() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Pick + +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2) +{ + return PfxVector3(0.0f); +} + +void physics_pick_update(const PfxVector3 &p) +{ +} + +void physics_pick_end() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Get Information + +int physics_get_num_rigidbodies() +{ + return numRigidBodies; +} + +const PfxRigidState& physics_get_state(int id) +{ + return states[id]; +} + +const PfxRigidBody& physics_get_body(int id) +{ + return bodies[id]; +} + +const PfxCollidable& physics_get_collidable(int id) +{ + return collidables[id]; +} + +int physics_get_num_contacts() +{ + return numPairs[pairSwap]; +} + +const PfxContactManifold &physics_get_contact(int id) +{ + return contacts[pfxGetConstraintId(pairsBuff[pairSwap][id])]; +} diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/0_console/physics_func.h b/Extras/PhysicsEffects/sample/api_physics_effects/0_console/physics_func.h new file mode 100644 index 0000000..0aa7e07 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/0_console/physics_func.h @@ -0,0 +1,49 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef __PHYSICS_FUNC_H__ +#define __PHYSICS_FUNC_H__ + +#define SCE_PFX_USE_PERFCOUNTER + +#include "physics_effects.h" + +using namespace sce::PhysicsEffects; + +//E Simulation +//J シミュレーション +bool physics_init(); +void physics_release(); +void physics_create_scene(int sceneId); +void physics_simulate(); + +//E Picking +//J ピッキング +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2); +void physics_pick_update(const PfxVector3 &p); +void physics_pick_end(); + +//E Change parameters +//J パラメータの取得 +int physics_get_num_rigidbodies(); +const PfxRigidState& physics_get_state(int id); +const PfxRigidBody& physics_get_body(int id); +const PfxCollidable& physics_get_collidable(int id); + +int physics_get_num_contacts(); +const PfxContactManifold &physics_get_contact(int id); + +#endif /* __PHYSICS_FUNC_H__ */ diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/0_console/premake4.lua b/Extras/PhysicsEffects/sample/api_physics_effects/0_console/premake4.lua new file mode 100644 index 0000000..b8e18d6 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/0_console/premake4.lua @@ -0,0 +1,18 @@ + project "0_console_sample" + + kind "ConsoleApp" + targetdir "../../../bin" + includedirs {"../../../include"} + + links { + "physicseffects2_lowlevel", + "physicseffects2_baselevel", + "physicseffects2_util" + } + + files { + "main.cpp", + "physics_func.cpp", + "physics_func.h", + "../common/perf_func.win32.cpp" + } \ No newline at end of file diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/1_simple.windows.vcproj b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/1_simple.windows.vcproj new file mode 100644 index 0000000..3d211cb --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/1_simple.windows.vcproj @@ -0,0 +1,713 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/CMakeLists.txt b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/CMakeLists.txt new file mode 100644 index 0000000..6f38d21 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 2.4) + + +#this line has to appear before 'PROJECT' in order to be able to disable incremental linking +SET(MSVC_INCREMENTAL_DEFAULT ON) + +PROJECT(App_1_Simple) + + +IF (NOT CMAKE_BUILD_TYPE) +# SET(CMAKE_BUILD_TYPE "Debug") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF (NOT CMAKE_BUILD_TYPE) + + +OPTION(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC Runtime Library DLL (/MD or /MDd)" ON) +OPTION(USE_MSVC_INCREMENTAL_LINKING "Use MSVC Incremental Linking" OFF) + + +IF(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + + +SET(App_1_Simple_SRCS + main.cpp + physics_func.cpp + ../common/ctrl_func.win32.cpp + ../common/perf_func.win32.cpp + ../common/render_func.win32.cpp +) + + +SET(App_1_Simple_HDRS + physics_func.h + landscape.h + barrel.h + ../common/render_func.h + ../common/common.h + ../common/ctrl_func.h + ../common/perf_func.h +) + + +INCLUDE_DIRECTORIES( + ${PHYSICS_EFFECTS_SOURCE_DIR}/include +# ${VECTOR_MATH_INCLUDE} +) + +#LINK_DIRECTORIES( +# +#) + +#ADD_DEFINITIONS(-DUNICODE) +#ADD_DEFINITIONS(-D_UNICODE) + +ADD_EXECUTABLE(App_1_Simple WIN32 + ${App_1_Simple_SRCS} + ${App_1_Simple_HDRS} +) +TARGET_LINK_LIBRARIES(App_1_Simple + PfxBaseLevel + PfxLowLevel + PfxUtil + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} +) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(App_1_Simple PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(App_1_Simple PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(App_1_Simple PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF() + + + + \ No newline at end of file diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/barrel.h b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/barrel.h new file mode 100644 index 0000000..6574fa8 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/barrel.h @@ -0,0 +1,202 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define BarrelVtxCount 57 +#define BarrelIdxCount 180 + +static float BarrelVtx[] = { +0.0f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +-0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +0.0f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +-0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.957307f,-0.289072f,0.0f, +0.404509f,0.0f,-0.293893f, 0.809017f,0.0f,-0.587785f, +0.5f,0.0f,0.0f, 1.0f,0.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.774478f,-0.289072f,-0.562691f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +-0.154509f,0.0f,-0.475528f, -0.309017f,0.0f,-0.951057f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +-0.107853f,-0.5f,-0.331936f, -0.295824f,-0.289072f,-0.910453f, +-0.404509f,0.0f,-0.293893f, -0.809017f,0.0f,-0.587785f, +-0.282362f,-0.5f,-0.205148f, -0.774478f,-0.289072f,-0.562691f, +-0.5f,0.0f,0.0f, -1.0f,0.0f,0.0f, +-0.349018f,-0.5f,0.0f, -0.957307f,-0.289072f,0.0f, +-0.404508f,0.0f,0.293893f, -0.809017f,0.0f,0.587785f, +-0.282362f,-0.5f,0.205148f, -0.774478f,-0.289072f,0.562691f, +-0.154509f,0.0f,0.475528f, -0.309017f,0.0f,0.951056f, +-0.107853f,-0.5f,0.331936f, -0.295824f,-0.289072f,0.910453f, +0.154509f,0.0f,0.475528f, 0.309017f,0.0f,0.951056f, +0.107853f,-0.5f,0.331936f, 0.295824f,-0.289072f,0.910453f, +0.404509f,0.0f,0.293892f, 0.809017f,0.0f,0.587785f, +0.282362f,-0.5f,0.205148f, 0.774478f,-0.289072f,0.562691f, +0.282362f,0.5f,-0.205148f, 0.774478f,0.289072f,-0.562691f, +0.349018f,0.5f,0.0f, 0.957307f,0.289072f,0.0f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.107853f,0.5f,-0.331936f, -0.295824f,0.289072f,-0.910453f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.282362f,0.5f,-0.205148f, -0.774478f,0.289072f,-0.562691f, +-0.349018f,0.5f,0.0f, -0.957307f,0.289072f,0.0f, +-0.282362f,0.5f,0.205148f, -0.774478f,0.289072f,0.562691f, +-0.107853f,0.5f,0.331936f, -0.295824f,0.289072f,0.910453f, +0.107853f,0.5f,0.331936f, 0.295824f,0.289072f,0.910453f, +0.282362f,0.5f,0.205148f, 0.774478f,0.289072f,0.562691f, +}; + +static float BarrelTex[] = { +0.0f,0.5f, +0.0f,0.85f, +0.0f,0.75f, +0.0f,0.95f, +0.0f,0.05f, +0.0f,-0.05f, +0.0f,0.15f, +0.0f,0.25f, +0.0f,0.35f, +0.0f,0.45f, +0.0f,0.55f, +0.0f,0.65f, +1.0f,0.5f, +1.0f,0.75f, +1.0f,0.85f, +1.0f,0.95f, +1.0f,-0.05f, +1.0f,0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +0.0f,0.75f, +0.5f,0.85f, +0.5f,0.75f, +0.0f,0.85f, +0.5f,0.95f, +0.0f,0.95f, +0.0f,-0.05f, +0.5f,0.05f, +0.5f,-0.05f, +0.0f,0.05f, +0.5f,0.15f, +0.0f,0.15f, +0.5f,0.25f, +0.0f,0.25f, +0.5f,0.35f, +0.0f,0.35f, +0.5f,0.45f, +0.0f,0.45f, +0.5f,0.55f, +0.0f,0.55f, +0.5f,0.65f, +0.0f,0.65f, +1.0f,0.85f, +1.0f,0.75f, +1.0f,0.95f, +1.0f,0.05f, +1.0f,-0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +}; + +static unsigned short BarrelIdx[] = { +0,1,2, +0,3,1, +0,4,5, +0,6,4, +0,7,6, +0,8,7, +0,9,8, +0,10,9, +0,11,10, +0,2,11, +12,13,14, +12,14,15, +12,16,17, +12,17,18, +12,18,19, +12,19,20, +12,20,21, +12,21,22, +12,22,23, +12,23,13, +24,25,26, +24,27,25, +27,28,25, +27,29,28, +30,31,32, +30,33,31, +33,34,31, +33,35,34, +35,36,34, +35,37,36, +37,38,36, +37,39,38, +39,40,38, +39,41,40, +41,42,40, +41,43,42, +43,44,42, +43,45,44, +45,26,44, +45,24,26, +26,46,47, +26,25,46, +25,48,46, +25,28,48, +32,49,50, +32,31,49, +31,51,49, +31,34,51, +34,52,51, +34,36,52, +36,53,52, +36,38,53, +38,54,53, +38,40,54, +40,55,54, +40,42,55, +42,56,55, +42,44,56, +44,47,56, +44,26,47, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/landscape.h b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/landscape.h new file mode 100644 index 0000000..00f6cff --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/landscape.h @@ -0,0 +1,318 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define LargeMeshVtxCount 81 +#define LargeMeshIdxCount 384 + +static float LargeMeshVtx[] = { +-25.0f,-2.19407f,18.5625f, 0.232976f,0.967754f,0.0957829f, +-25.0f,0.0644502f,24.75f, 0.188094f,0.871343f,-0.45319f, +-18.75f,-4.50287f,18.5625f, -0.0716098f,0.995449f,0.0628767f, +-18.75f,-0.39999f,24.75f, -0.0602794f,0.895848f,-0.440253f, +-12.5f,-1.2166f,18.5625f, -0.269469f,0.961403f,0.0555879f, +-12.5f,-0.942431f,24.75f, -0.0997841f,0.993258f,0.0589987f, +-6.25f,1.93598f,18.5625f, -0.283933f,0.956351f,-0.0691025f, +-6.25f,-0.445954f,24.75f, -0.180725f,0.942766f,0.280233f, +0.0f,2.76983f,18.5625f, 0.171645f,0.984908f,0.0222501f, +0.0f,2.76642f,24.75f, 0.0784993f,0.995428f,-0.0544117f, +6.25f,-2.53736f,18.5625f, 0.248298f,0.965028f,0.0840741f, +6.25f,-0.915645f,24.75f, 0.164311f,0.945856f,-0.279926f, +12.5f,-1.60054f,18.5625f, -0.180435f,0.983586f,0.00115547f, +12.5f,0.831925f,24.75f, -0.0692495f,0.964821f,-0.253623f, +18.75f,-0.800282f,18.5625f, 0.10755f,0.951538f,0.288112f, +18.75f,-1.47284f,24.75f, 0.232178f,0.972664f,0.00429361f, +25.0f,-2.78379f,18.5625f, 0.1833f,0.937477f,0.295867f, +25.0f,-0.967508f,24.75f, -0.0773477f,0.956641f,-0.280812f, +-25.0f,-0.352038f,12.375f, -0.192222f,0.972435f,0.131987f, +-18.75f,0.681228f,12.375f, -0.107779f,0.962569f,0.248686f, +-12.5f,2.72065f,12.375f, 0.0520846f,0.993034f,0.105692f, +-6.25f,-1.78776f,12.375f, -0.0133223f,0.99674f,-0.0795754f, +0.0f,1.57707f,12.375f, -0.129025f,0.969662f,-0.207627f, +6.25f,0.424356f,12.375f, 0.180995f,0.97074f,0.157815f, +12.5f,0.283234f,12.375f, -0.16285f,0.973539f,0.160316f, +18.75f,2.57015f,12.375f, -0.165454f,0.978339f,0.124408f, +25.0f,3.07363f,12.375f, -0.00454559f,0.988151f,0.153417f, +-25.0f,-0.893751f,6.1875f, -0.0836251f,0.990084f,-0.112876f, +-18.75f,0.930932f,6.1875f, 0.00269413f,0.971838f,-0.235633f, +-12.5f,-0.684529f,6.1875f, -0.010319f,0.927048f,-0.3748f, +-6.25f,-0.661383f,6.1875f, 0.012265f,0.999875f,-0.00994222f, +0.0f,0.385718f,6.1875f, -0.15435f,0.984937f,-0.0779465f, +6.25f,0.589796f,6.1875f, 0.0241717f,0.999582f,-0.0158589f, +12.5f,0.47454f,6.1875f, -0.017184f,0.997953f,-0.0616073f, +18.75f,1.59939f,6.1875f, -0.0902706f,0.957309f,-0.274609f, +25.0f,1.13434f,6.1875f, 0.0346006f,0.957441f,-0.286547f, +-25.0f,0.74548f,0.0f, 0.329903f,0.930812f,0.157334f, +-18.75f,-2.47437f,0.0f, 0.247844f,0.968142f,0.0357041f, +-12.5f,-4.16309f,1.81975e-007f, -0.0623898f,0.997626f,-0.0291436f, +-6.25f,-0.700022f,0.0f, -0.217067f,0.974987f,-0.0477624f, +0.0f,-0.0957388f,0.0f, -0.117693f,0.990712f,-0.068098f, +6.25f,0.614077f,0.0f, -0.0713214f,0.997305f,0.01722f, +12.5f,0.299109f,0.0f, 0.218606f,0.968641f,0.118094f, +18.75f,-1.71753f,0.0f, 0.0339493f,0.985612f,-0.165579f, +25.0f,-1.12638f,0.0f, -0.0547573f,0.989177f,-0.136126f, +-25.0f,-0.403319f,-6.1875f, -0.1263f,0.989211f,-0.074223f, +-18.75f,-0.0730335f,-6.1875f, 0.0173428f,0.965382f,0.260261f, +-12.5f,-0.450125f,-6.1875f, 0.0658811f,0.875f,0.479619f, +-6.25f,-0.180204f,-6.1875f, 0.0116584f,0.981445f,0.19139f, +0.0f,-0.632679f,-6.1875f, -0.0557983f,0.993041f,-0.103716f, +6.25f,0.308409f,-6.1875f, -0.191898f,0.96766f,-0.163737f, +12.5f,2.5011f,-6.1875f, 0.0758397f,0.996403f,-0.0378189f, +18.75f,-1.69303f,-6.1875f, 0.16761f,0.974057f,0.15205f, +25.0f,-0.141349f,-6.1875f, -0.204846f,0.978471f,0.0251341f, +-25.0f,-1.10316f,-12.375f, -0.0350644f,0.993748f,-0.106001f, +-18.75f,1.06711f,-12.375f, -0.309806f,0.919244f,-0.242922f, +-12.5f,3.61544f,-12.375f, -0.0506281f,0.998702f,-0.00561657f, +-6.25f,1.6504f,-12.375f, 0.322294f,0.937465f,0.131477f, +0.0f,-1.60595f,-12.375f, 0.086016f,0.995916f,0.0274459f, +6.25f,-0.849859f,-12.375f, -0.0332811f,0.997087f,0.0686255f, +12.5f,-0.942201f,-12.375f, -0.153559f,0.982185f,-0.108312f, +18.75f,0.494873f,-12.375f, 0.0753195f,0.981472f,0.176181f, +25.0f,-0.333828f,-12.375f, 0.035057f,0.987194f,0.155624f, +-25.0f,2.1862f,-18.5625f, 0.612899f,0.782306f,0.111138f, +-18.75f,-3.38259f,-18.5625f, 0.0194078f,0.992789f,-0.118297f, +-12.5f,-0.880916f,-18.5625f, -0.282251f,0.949875f,-0.13443f, +-6.25f,0.818158f,-18.5625f, 0.1476f,0.981788f,-0.119612f, +0.0f,-1.48019f,-18.5625f, -0.044551f,0.996013f,-0.0772824f, +6.25f,1.47123f,-18.5625f, -0.117036f,0.97986f,0.161792f, +12.5f,0.164076f,-18.5625f, -0.0340355f,0.978993f,0.201034f, +18.75f,2.14568f,-18.5625f, -0.0439269f,0.994859f,0.0912435f, +25.0f,0.626506f,-18.5625f, 0.208015f,0.968592f,0.136229f, +-25.0f,0.296889f,-24.75f, 0.46973f,0.844327f,-0.257809f, +-18.75f,-3.18022f,-24.75f, -0.0226758f,0.998794f,-0.0435401f, +-12.5f,1.8927f,-24.75f, -0.202772f,0.919836f,0.335836f, +-6.25f,1.46387f,-24.75f, 0.224904f,0.955746f,0.189652f, +0.0f,-2.52726f,-24.75f, -0.0435882f,0.993572f,-0.10447f, +6.25f,1.30397f,-24.75f, -0.28646f,0.956525f,-0.0547707f, +12.5f,1.85812f,-24.75f, 0.0521949f,0.979796f,0.193067f, +18.75f,1.56331f,-24.75f, -0.0270784f,0.999629f,-0.00293115f, +25.0f,1.05366f,-24.75f, 0.161f,0.986887f,-0.0115473f, +}; + +static float LargeMeshTex[] = { +0.125f,0.0f, +0.0f,0.0f, +0.125f,0.125f, +0.0f,0.125f, +0.125f,0.25f, +0.0f,0.25f, +0.125f,0.375f, +0.0f,0.375f, +0.125f,0.5f, +0.0f,0.5f, +0.125f,0.625f, +0.0f,0.625f, +0.125f,0.75f, +0.0f,0.75f, +0.125f,0.875f, +0.0f,0.875f, +0.125f,1.0f, +0.0f,1.0f, +0.25f,0.0f, +0.25f,0.125f, +0.25f,0.25f, +0.25f,0.375f, +0.25f,0.5f, +0.25f,0.625f, +0.25f,0.75f, +0.25f,0.875f, +0.25f,1.0f, +0.375f,0.0f, +0.375f,0.125f, +0.375f,0.25f, +0.375f,0.375f, +0.375f,0.5f, +0.375f,0.625f, +0.375f,0.75f, +0.375f,0.875f, +0.375f,1.0f, +0.5f,0.0f, +0.5f,0.125f, +0.5f,0.25f, +0.5f,0.375f, +0.5f,0.5f, +0.5f,0.625f, +0.5f,0.75f, +0.5f,0.875f, +0.5f,1.0f, +0.625f,0.0f, +0.625f,0.125f, +0.625f,0.25f, +0.625f,0.375f, +0.625f,0.5f, +0.625f,0.625f, +0.625f,0.75f, +0.625f,0.875f, +0.625f,1.0f, +0.75f,0.0f, +0.75f,0.125f, +0.75f,0.25f, +0.75f,0.375f, +0.75f,0.5f, +0.75f,0.625f, +0.75f,0.75f, +0.75f,0.875f, +0.75f,1.0f, +0.875f,0.0f, +0.875f,0.125f, +0.875f,0.25f, +0.875f,0.375f, +0.875f,0.5f, +0.875f,0.625f, +0.875f,0.75f, +0.875f,0.875f, +0.875f,1.0f, +1.0f,0.0f, +1.0f,0.125f, +1.0f,0.25f, +1.0f,0.375f, +1.0f,0.5f, +1.0f,0.625f, +1.0f,0.75f, +1.0f,0.875f, +1.0f,1.0f, +}; + +static unsigned short LargeMeshIdx[] = { +0,1,2, +3,2,1, +2,3,4, +5,4,3, +4,5,6, +7,6,5, +6,7,8, +9,8,7, +8,9,10, +11,10,9, +10,11,12, +13,12,11, +12,13,14, +15,14,13, +14,15,16, +17,16,15, +18,0,19, +2,19,0, +19,2,20, +4,20,2, +20,4,21, +6,21,4, +21,6,22, +8,22,6, +22,8,23, +10,23,8, +23,10,24, +12,24,10, +24,12,25, +14,25,12, +25,14,26, +16,26,14, +27,18,28, +19,28,18, +28,19,29, +20,29,19, +29,20,30, +21,30,20, +30,21,31, +22,31,21, +31,22,32, +23,32,22, +32,23,33, +24,33,23, +33,24,34, +25,34,24, +34,25,35, +26,35,25, +36,27,37, +28,37,27, +37,28,38, +29,38,28, +38,29,39, +30,39,29, +39,30,40, +31,40,30, +40,31,41, +32,41,31, +41,32,42, +33,42,32, +42,33,43, +34,43,33, +43,34,44, +35,44,34, +45,36,46, +37,46,36, +46,37,47, +38,47,37, +47,38,48, +39,48,38, +48,39,49, +40,49,39, +49,40,50, +41,50,40, +50,41,51, +42,51,41, +51,42,52, +43,52,42, +52,43,53, +44,53,43, +54,45,55, +46,55,45, +55,46,56, +47,56,46, +56,47,57, +48,57,47, +57,48,58, +49,58,48, +58,49,59, +50,59,49, +59,50,60, +51,60,50, +60,51,61, +52,61,51, +61,52,62, +53,62,52, +63,54,64, +55,64,54, +64,55,65, +56,65,55, +65,56,66, +57,66,56, +66,57,67, +58,67,57, +67,58,68, +59,68,58, +68,59,69, +60,69,59, +69,60,70, +61,70,60, +70,61,71, +62,71,61, +72,63,73, +64,73,63, +73,64,74, +65,74,64, +74,65,75, +66,75,65, +75,66,76, +67,76,66, +76,67,77, +68,77,67, +77,68,78, +69,78,68, +78,69,79, +70,79,69, +79,70,80, +71,80,70, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/main.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/main.cpp new file mode 100644 index 0000000..5db906f --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/main.cpp @@ -0,0 +1,495 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../common/common.h" +#include "../common/ctrl_func.h" +#include "../common/render_func.h" +#include "../common/perf_func.h" +#include "physics_func.h" +#include "barrel.h" +#include "landscape.h" + +#ifdef _WIN32 + #include + #include +#endif + +// ARA begin insert new code +#ifdef __ANDROID__ + #include + #include + #include // used to check for presence of NEON on device + #ifdef __ARM_NEON__ + #include +#ifdef TEST_NEON_PERFORMANCE // define this to run NEON performance tests + #include "../../test_ARM_NEON_performance/test_neon.h" +#endif + #endif // __ARM_NEON__ +#endif // __ANDROID__ +// ARA end + +#define SAMPLE_NAME "api_physics_effects/1_simple" + +static bool s_isRunning = true; + +int sceneId = 0; +bool simulating = false; + +int landscapeMeshId; +int convexMeshId; + +void render(void) +{ + render_begin(); + + for(int i=0;i -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_DOWN)) { + angX += 0.05f; + if(angX < -1.4f) angX = -1.4f; + if(angX > -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_LEFT)) { + angY -= 0.05f; + } + + if(ctrl_button_pressed(BTN_RIGHT)) { + angY += 0.05f; + } + + if(ctrl_button_pressed(BTN_ZOOM_OUT)) { + r *= 1.1f; + if(r > 500.0f) r = 500.0f; + } + + if(ctrl_button_pressed(BTN_ZOOM_IN)) { + r *= 0.9f; + if(r < 1.0f) r = 1.0f; + } + + if(ctrl_button_pressed(BTN_SCENE_RESET) == BTN_STAT_DOWN) { + physics_create_scene(sceneId); + } + + if(ctrl_button_pressed(BTN_SCENE_NEXT) == BTN_STAT_DOWN) { + physics_create_scene(++sceneId); + } + + if(ctrl_button_pressed(BTN_SIMULATION) == BTN_STAT_DOWN) { + simulating = !simulating; + } + + if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_DOWN) { + simulating = true; + } + else if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_UP || ctrl_button_pressed(BTN_STEP) == BTN_STAT_KEEP) { + simulating = false; + } + + render_set_view_angle(angX,angY,r); +} + +#ifndef _WIN32 + +// ARA begin insert new code +#ifdef __ANDROID__ + +/////////////////////////////////////////////////////////////////////////////// +// sceneChange +// +/// This function is used to change the physics scene on Android devices +/////////////////////////////////////////////////////////////////////////////// +void sceneChange() +{ + physics_create_scene(sceneId++); +} + +#else // __ANDROID__ +// ARA end + +/////////////////////////////////////////////////////////////////////////////// +// Main + +int main(void) +{ + init(); + + physics_create_scene(sceneId); + + printf("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + while (s_isRunning) { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + + shutdown(); + + printf("## %s: FINISHED ##\n", SAMPLE_NAME); + + return 0; +} + +// ARA begin insert new code +#endif // __ANDROID__ +// ARA end + +#else // _WIN32 + +/////////////////////////////////////////////////////////////////////////////// +// WinMain + +extern HDC hDC; +extern HGLRC hRC; +HWND hWnd; +HINSTANCE hInstance; + +void releaseWindow() +{ + if(hRC) { + wglMakeCurrent(0,0); + wglDeleteContext(hRC); + } + + if(hDC) ReleaseDC(hWnd,hDC); + if(hWnd) DestroyWindow(hWnd); + + UnregisterClass(SAMPLE_NAME,hInstance); +} + +LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + switch(uMsg) { + case WM_SYSCOMMAND: + { + switch (wParam) { + case SC_SCREENSAVE: + case SC_MONITORPOWER: + return 0; + } + break; + } + + case WM_CLOSE: + PostQuitMessage(0); + return 0; + + case WM_SIZE: + render_resize(LOWORD(lParam),HIWORD(lParam)); + return 0; + } + + return DefWindowProc(hWnd,uMsg,wParam,lParam); +} + +bool createWindow(char* title, int width, int height) +{ + WNDCLASS wc; + RECT rect; + rect.left=0; + rect.right=width; + rect.top=0; + rect.bottom=height; + + hInstance = GetModuleHandle(NULL); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = SAMPLE_NAME; + + if(!RegisterClass(&wc)) { + return false; + } + + AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE); + + if(!(hWnd=CreateWindowEx(WS_EX_APPWINDOW|WS_EX_WINDOWEDGE,SAMPLE_NAME,title, + WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS|WS_CLIPCHILDREN, + 0,0,rect.right-rect.left,rect.bottom-rect.top, + NULL,NULL,hInstance,NULL))) { + releaseWindow(); + return false; + } + + static PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + 32, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, + 0, 0, 0, 0, + 32, + 0, + 0, + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + if(!(hDC=GetDC(hWnd))) + { + releaseWindow(); + OutputDebugString(""); + return FALSE; + } + + int pixelformat; + + if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 ){ + OutputDebugString("ChoosePixelFormat Failed...."); + return FALSE; + } + + if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE){ + OutputDebugString("SetPixelFormat Failed...."); + return FALSE; + } + + if (!(hRC=wglCreateContext(hDC))){ + OutputDebugString("Creating HGLRC Failed...."); + return FALSE; + } + + // Set Vsync + //BOOL (WINAPI *wglSwapIntervalEXT)(int) = NULL; + + //if(strstr((char*)glGetString( GL_EXTENSIONS ),"WGL_EXT_swap_control")== 0) { + //} + //else { + //wglSwapIntervalEXT = (BOOL (WINAPI*)(int))wglGetProcAddress("wglSwapIntervalEXT"); + //if(wglSwapIntervalEXT) wglSwapIntervalEXT(1); + //} + + wglMakeCurrent(hDC,hRC); + + ShowWindow(hWnd,SW_SHOW); + SetForegroundWindow(hWnd); + SetFocus(hWnd); + + render_resize(width, height); + + glClearColor(0.0f,0.0f,0.0f,0.0f); + glClearDepth(1.0f); + + return TRUE; +} + +int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) +{ + if(!createWindow(SAMPLE_NAME,DISPLAY_WIDTH,DISPLAY_HEIGHT)) { + MessageBox(NULL,"Can't create gl window.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return 0; + } + + init(); + + physics_create_scene(sceneId); + + SCE_PFX_PRINTF("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + MSG msg; + while(s_isRunning) { + if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + if(msg.message==WM_QUIT) { + s_isRunning = false; + } + else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + } + + shutdown(); + + SCE_PFX_PRINTF("## %s: FINISHED ##\n", SAMPLE_NAME); + + releaseWindow(); + return (msg.wParam); +} + +#endif diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/physics.png b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/physics.png new file mode 100644 index 0000000000000000000000000000000000000000..641c4fc3e739b545c6355f3ec9efd5f1e263b5b0 GIT binary patch literal 24116 zcmd4&_dnbJ_dkv&A=C(p+M^yVwRfaSQ9A4yqh{Kuk%5XmDt5J~s#T*#?Y&}`P@`H@ z6|n_HZK_sPed6_eU%r3C_Xiir-Q|9q+x2>G=XN_Q#@O%ygr0{U002OAwC|b%06;S3 zhvgCt<%!GvqFBl=AkOrGCZKYNZ;kSW+WC&b9RQ%_6~o_0V9NKaNNrOC03bjF0Ki88 z0DmZt@IL_nZ&?6f9RUE`N&^5mJu+KNQ~?0HTAjOh;C}X7S+uEA54;<`hJY}60A98@ zPbO_`O(30c5?GTimyhLAb>v<7e#Z>N-Cn%*{r^@SAL-mgE@4PVw}UO?PysEiKIU7c zmD^^%71l>{%C{Aq16nrLj%Ho!TtlX~U7T~WLVald|MY`!R%oB8P+9?(lxj^uO^ZNey_ArdUwn1Fs(lxQ;i(-&z;_ zZqbgbZrF&-E-F0rto)!;>u$(j_w>Udlqdr`HZ^M6+1Inv7IuHvtdu>4_x%0sK}LhX zZQ4FQTx^LeVSaFXqpso9xia|rs(te}G_=2`~Y|oTKVuH3J> zd)fEB<5jkAnwzP4XXPbE%C2m&n3NrfNre#T`{%FgR^fyfN zRlk3z>nt_Wq3Fko94t0o{hwc5w|5uajkJc(S>eL=*Vja^Xbp zVnw6E3_XLGxC;MuMXRZkdaM^kBnfxM09l;vyOB;?8{KS1ifAkJ`R%>^!C<4LmLr^+ zF{XaON`;G%TMW62vd_aC>m7295g~ggYre#p)$jK zF!M@-ywUqAw0EQ0S6@2(ef)j=Ff-h`veoqHVP$Y$M-kT6ycDR{9z`Pyg%_|#nf1Bi zO||Z!G)x)dtr4T`p9t@br671Q8cj7XSnjF=q6cO9f zfyKZSo}5v9KF3vI&b%L7gBiko2JdiM8C0e+{{4CbiKK_lSx?5BQvRweeE9lQYPAh^ zGF5ZhFJkUmSUSMN?o`^M4|WolgldQZ$)j@C9rKQ2$m>SFS6U8|dQUzM=f zdF8bIbcv@%t~=liD|}&?g1M_ScX|milQ)GYVHA)*KA01{v@#K)+qs#E8^;hyH&?@)#AVG8B|x3E zNOkYb6@!uwxj$y$s}bK$R7*VO!m!+tJUtQpy83-OsdS9VG88*lF+Lq-fU=hRb|*hvxZl{aB5mZiZ9bji~VuC@=o}0 zpwCh`TJkQbQZp4WY&E7#dlQ-ae~3lRVYK?tSQ=%edR9d1?-4x%>_+VuX$5Tm&>d`t z%A8TmhQ-FS>0sIhO1b+NX z*OJ=tciCyk`(!ya|*)aCp!BE(W zNmWXV@+Qy`e6$|%AlFuCTp8~oN1b*2C<4G~i5auLvEzkF$nR2+N_1s&Z#|(LXZ(lf zThkECv?&FEis^pOs^pH99fX*&V?_0}?(k53<2vA`8n*KIgTHwYK-q0d%!3e_8=Lkg zpDokV#|b2R^wd-^6Y9^|uDz%ItL@-AIw0Cb$vsY^;@djJq^S8(3r#{w*ad{0|KkvQ zUs-7~@oL~$nf;R~>lI~D|Evhx)r=WqNL;pChNhjov6i`O@qZ97g+WN9iw?dwOyNqJ z5bvkqn)D1iL$aOktao9Q_t^m{qoMHY9Z1KGx$wh-ribCWcD2jA>3H@$W88F`kj5b7 z`^?oilN>ofT;v7&p(Qn9%M%E_J6ln_Zn9XZeZHiY`^RcpBtKfRaq{QATwUnsp9;EC zWpmUeV`U}kQspa@4_e8tSXqiL6c_>NpbHb|GR1xW0&eGZZ~Hb{?bfm;@_l?)xp?8| zW1x034NN+S7v5Kt5g|Heon!q{69PmP_weTFqp2?>To@4?QHU`<#1UZAiN>ubD;Wkh zUzBMJDj}6?27)cQy2(pgqp0m)Z&?UDps`{7d0Sm5CtM5u|5PFXpzzmGVTv>qyZGO# z9+fl$S3vVpjWdr?4;$wK$|euZzwCq^UG^Nr_TqU#=JA7c<1EFVm`hd^!Qt!ehyG|< zlv~>W390#?5G|$h5+nh(Kv8I`VOrnjAS--^MC_%Vq8Xn>Hft`H>Y0_9Rk9dsBUX?bwo{kLBsA8SsX0U z=lanc1zt5SH?7vq{rr@IZW!wMEr@wxt}MlMU6{&SdIKr#l`!&#!+C(&mw=DFbBKmV z$!hbwbS|mzXWz-|*?<2tublEoE*%%fL+_SQ1W>H?|A=|s3sMAU@>Gw`R7^=XPQ!k*jR$56Y>Eaa{l&C&Zh=*Yq?xL$? zwkFrSaMTy_x6jF7qq22d-VEKZzQKeiS(0kX7xHrtS?em>Zm)b^5GZUINOh+Z&_LzdF z0j<8E7m9N&98J1c%Gk@H8c=vv6bQ;*Si^FGr(!U#`_B#GJHAJ=z7$`b86L;nFw$K} zGjR)91ue65{qM~v$GAl$uG75Kg0hZFa4ozws8H@|9N0ya>$DFYDh~tfG_MNO{WvIu zedy0Gw|;gQ$6h@$f!0nf1sBb9#&TH(loR{S^P>MFL-MW} zxdc4GhtLKl_pY{|47w{#w-pX8FyVO-8}RC+9qp@SZI*`cl+-4M-ri$;PD=QB z-K3iD8nC?H=1t*?vDi*s`Diq_oVxPjSpzCre4K|!aVN$(y+lQhJTbr+$cag`eGBWZ z0Ig6zd800ew$fUyr>bVJ#T^RF6`E!Vms!yvl<$Kc>a0{3hE-gtp7MaygciKG@I|3K zRNuK03ITAc^eKEMm4|!C>GWVjm4RTp=_g(6BB6Lf`Ekw2_;c1Wzb$bK)^I6^RSC45 z&PvR-0I_^i%$DMYD849{hkleRtydFHm6={G2_*WqE%6stEa0l&g51I}L6Qv*droOy z>%k@aw3Es?9QACvS&6z8kFZ44M<}P2R?h!k4^zDI&YCzt*X`TBpH(O|sXU=ABoWsm zox9L+U8Icrm0fEh1y_(&d5eK8)iYb=HkxzjH?<6hT zzG1f`Pbl~8IGuG8Lv!LAA+;mjMT9=bRGwF3rnS}yV<1VE6b%cuYSU%$NQ$lU-H1dN zUsyh)F%ppu`Udw~0sP?0IsLAFW>%L%cpJ8@B&;@u;@11@i_#CWE=wE>+iUqu8FO>q7H}po!FtF77}YZtQQ!tenOR6xo(>0Ayy;MhSj|QC{3Xl%NW2}TB9&b ze`8;LH6mvnu9iyWvjTgtd>Btf_=PmtJQm7KxBFsb_^wFV=lW`MBoT zr9Y80p{SB#QDYit#apdR=Aj=qPUfK+wMsw%;B09Hz~fxz;7_CVN@`@3rbRlna7D%# zbw#(*3YSjrQ@x0Q58P%A1?*S~K#AG)l1Qmxl-NT$$5l`{yg7eq8ABj8%^vkB>IOX_ax1$r|^Sdl5usf29%>%?CKb` zvzzR{lkD^65^roTQRTr6QG>%eqwc!dPT>dh+$#u3`@j zJ`I5Xh(h$$h!QA zAO^}_!Cc#B&+8(rYXSP7KBmN#Ftl5BF9-@Qu2<67Z3#W--+wOmt<>Thms z#8wUT(b_nG1x>U!2PtJ24-)R_P21~)^L0!^@p z!v)Jf=Yr?QeFh=eLZVGeip6)el%c%j*nae&L{y-F47fqhgfM++szA%46rly6=t7~5 z0(UVF%NWfv%O$;_&AGrG=-C+13S?ap+~#O*Gp#x${O}WTB9(9XCF##&LfiIBQVJeR zXI@5Oq1%PPj@21PiBBp6Gk7cIjN`ziG`kHSb3 zqq?9pX18NPc9-FoXw-bIV5C+fB z6~K0a7_?bE>+leGk_F5QnlNta#X~ttOJv6)R-M)Mx!-@F?0cn&@dAv^j8gf~c#&Ih zfqFZ}Q4r%lOKa;8mL$VAnacO10;v;R%ifMB{R0x!hJUp%HzYcWN^Mv%)KBSJ&`;Xp zA(3cCD`ajuy_tdEv%|Vq2pzPI%T|y>FNI6@8zq|8=HA0r zCp%tGtxbg1CI&C73zs`O1ev}MhnKb-h}qc76u3pR=0|P*F+R4AMqFw;L{49_(ZN_y z%rkKiI5~5nB|Y4Xax8zX`FiqqRoy+GqNQ-o*uZ^z^vNsghJx}Rg>Lh1l6O6+d<`c+ zlU7uOZk-Lx4M4KihlhpjdMOWA#{lBB|6Z)$v9upt6enImt|F z8C(5En7HM9T@N_$R4gQ@dielO{`0t@;9`*lC?#4)9F-DHrI>MCWXY+&!=I7VSVwHo za5Cd7hq@L!)7qq{Ed3xDVe%eTWk?D(Hfs|!Vd;xjc(V%f5XYEwln}>0X-d=C7~GQp zW1rheg0aP65HN<()+|RHShACLy50JfvBC~89)UG$^u56>CThY22Q{gAf7zH$$yH5~ zz4G2e>UoiFXg-Uf39*D|5Gl1zqP5lOf5qIC=vUFLnL@P4LlN#|P}MdAc^NDP6^rZz zsZgK#C>ar%j5z8RYlyV2lL%T^&vmk&XIaBwVOuY)G zA%dcuE`aMm6+An0p`Pqv$@ElG1$Dzz4#cFc`Kk>o#g7uQ_miuFdX6u=Oj4QSYyV9f z;%H+K&TVT0UDkmmVu@n_w~p)D^yJaIlAJ^W6^Yiy{s`EZA7{(cU^+Ywn&dj*p{x#G zWPiSH*@2pYUP4Gsq)38mW$$0DEaVeqyj|{ydd*JF zumawNZO_m*QhNw<_wx|P;0>%3Lv&L!330%3=2Ek&kh2X3*!C3AgKGPBZ;>bTa~KM^ z&6@5o9H)!s*tQz?)NS~c*&r`_2<`CD3)iJ;0{YJH`UrXm>zJ~VbumAb5fbM0LOBq^ z3oRjDstGl#g7bO(P*SSo6Nl962FdzqiHuSS#WSYFvEm+VgJ%FACl`tD3k2xaA#Hg< zO1apsVb4>&Bp#;zIAJRI@Owf-W3U3Nn3}dKT0Yh0gm+O*wJp{8_!v7>&^(S_V zVke?Rr&xxg#3zkE{UP5v`~z#>gCI#1cNNnzh6ym?^$>n)8@Ct4^K^!_!4n;}2UKvD zgcU5o=>V(nW*n8}N7HfRCTk1N!RkTq6l;PvaO3ny001Mm_q!C^I;cOP^MGQOdEjna zH8Z2s;#;xH?PHlByT+ng2J&|!^b&+za(8pzUsHjWtdThk=g=#rGWH5LT?f4p9~NbACBj9VfKJ{Mjb^`n1h z=g+cE8beND`|9WW>iq6@!h8(mi!^K&$S`z!rr)fjq1I^OSBudy>bkxTdnJbl0qa;& zo7|;DT|bq;50Yi>D34=qOLQ}9H#9r+c4#aS2KnmL%sx#}I_aE^ zwLe?8^nL1yc>d)0Y$s%1_4lyWio?HUhk=lPt09KJpwP=-KuvdieYuSt4*ukny)Ljd zUC_m=aALIJSf=3?mVcCB{>kQ45{;W#vpdX;YCSl74Vts@a=G$0+JF0cDc>--n?ljc zK?B(As5kR_0ZxWrt@CG<{=1#DgBL(%P^dfCzD&s|WP#ib1C@PyYrk6Czo?LmS*_7*mOpt+XorGrPScrNd@h}h&Wlc#EQeQC zEiX0n;k0bj|D-==?D0hw(Pahw>Q{L?7zEKE8tjNzo$Z|etK!O065#tyH`Eynfc<>- zw4UxhU2>}vc?C~dmGvb`N?=~;!uPn6$DJhf@Dlx2mBOLAAFbVnAsdahtSzE*ORv=D zZ2gy$?VJ?$o+L(Bf4#V1z3n(Z?SOThZMplhmTNvrf2>tx$f}DyNmGdtH($HJPjxxm z4NGsCeq9(`IeLExJgw%^_pf6w)H3m=`ILopiKp=Jm~k`DcrA@rFjg@2-CgrQeNOO3 zhPcc96kM`i#qT{k>(MeUf4p^Kxs_yFPYXZY|Q=HKCgRNGS8FS z4xgrmAT18^$lU`mJ3+5t@l;aqu+){l3ht&6KdC;QF)A5KVF!)oMz+J+|#xK zt&;Ql3aXu`=;oMYG``<0Y7*Oa-~T&%5OnIcu6znQyz;(kqu4C7&skdP2*^{iL4x0! zQt>{`zzr!EeZdqmaCtXihUQP_js~ip9h6CTzPQhGeiU+U`J!rWM*%#?{?dQz&{Nzi zn7HgM=%rU`8&gnT;ZZ;wi>d(2#=Q2y7LpmXtJ?pda2pkkJ{sV3Q5D1&noqr5W;bDA zBb@5fz4`}(e6Xv$;JyT69(ZOdXG1S1vDh~5k8Rw*vhc*0=FYM)U*#(;KBdFl&Y6$g z+D}%t?~oee9g)Y&G9j-2*0TS(T3&<5T#2Lw;L10X)Pn&<8YEb+`!>()%weq&#UM7Q zq^r;xmU*6fRE;7NEo6SM?C|aV0foUHP6y0Ijl#!hRwF%vPvf%){=;2eH6wJUmr{h_ zzuoASRrPcKqq{@@QN3|f3CeW8U!5@l;C#cdWcnuJdX23PC^>~NlXDtcc_+dS*AS|Y zO^{3euvwSdoE_!#^PT5su@&>G0P|JxN3PT3uie7NjIYJ9yRgDU{9m4?1>O?A%m7%8 zsH|G`+)m8J;wvpAEg4!8BgC*|rpaEUATMZhqR*qsiWg=dc)SpuQ8#p}OmCOG(&yHD zzxOb&|JGy(Ac^gBMot-1&RIssNk(Nw7NHB%PX$w?6Z)OL9K$197YcatVz`KGgGx6J z-)>)^IZM8^iP%<3z@1=|0387WhteiF+-<1EdR-y?7#V~(JuM9S%`ZQx}(1@ z%-%Nxbaa#Xt{6Zdd?&LX-dvk1)ABRVuzZGcPGmJzLyTEOMfF-8ei8f9kOwzpM{+Z|+b9Qfp*67RiXNZU2 z?4o&_1)~?w+i0GjF9`n2MTb8?0!HPGYG8AIOH9vsz25g-+PPX}51yf*ZJ(YZL4T2w{Qk;+8=?lya7RE|KfvVuS^raTjSv{E# z^=#Lxg16AEA3ir6QWs7%0%)5?u#6^QpU97*ZvS#WKXh*mel;(+I(0bPaMd2}$%As6kDg-vEkbR<$Ta3BkvkQLi`0(*$?PUZE_j;G6sTeP9^u<`Z|1#+O7vCEa+#lF}y1Bc(;3ex7^9i3gaZLs01#TUF&gzQODDEt6m1- z-m%s+>KxXx9CnVk&*hxHlNPG%h?0DAgj5S`ruM?!Fze~|jurqRTg~Dg4jeAg3i#zH zAI;!YrW5A{j{vBbH$3@7x|GD?6ng;!A09M4zbUgPuX#t6Ys;OUZc_5QNgS)APr*F`zEtVk0T63fYm6p?U+p`am+uHY_|?MjNYF31AKreq z6dSQ^OYh6rboRIXZ&TG$W0 z$*IH(dhwCgp3Z|*>;=7Ln#}e16%_VB{>nn)Kh42dsnNnRkKpZ>43AvbhPm)SDV=yX zCxsfFB!IDF-Pdp0RH^jEIKd^S$(uXa##yCH_Ho}LDnW+8ousMYH9d!^1A&~oBijyt z-TGr2@b?BE5+4(6h>NmT#6?Aqxr+CkwW$RHD&RSq*$1?o+8Z8}BdH;&fLP!(Z5Wk{qb&h1|4++mRIC#nGY;DyvFlOW z&(v}SXGBK%U}{H-JCWIf8-dyfhw2=s&rEZ^G}n-q&vtV(zJd-#1)lp=Fk2~^Gg$Gd z97<~1sgkFwxtY%r6CQ4U<=gkCxLnQD`KP5*2g0VwwW-22wsanp!hoGCBaEXd5TM_D zS&0kZ74T#2b(7>cyHR|bP$GTx3;(bc(9j;ON(OJ#(Qu9mMoMqp3!3Cc_cN;3M+aXc z!O@QQztnz+v`T81y+kSm*RZ$!u$&lh(o}K0G(Fh{=rR=lwQLeG=W8_)6wG=9o0%$U zC(uMEqeISktn~`$SL#O6gOqZzdL4` zOWhe0^_b`F=QW5?J zbz8CR9P|27qMr2HkYGF?%VKBdnR8r-2j?kZ2r>tM=^rUfdd-5qSV zF&RcWvq{9dSD6seShI{t#!R|pkK5DKWqfgppZdw2SIh@jh#$V3E;s`nwaA1x`Rf3~ zn%roBY6`sP$bV)@z}bUI6hgU&wYFF(%hs;@#sM03vv^y0IO_7*lD|Gq>Gl#nti8L2 z(!3yFsARGd!f!iq?ANvWxN*;6k?wDTBV!`5^9|HvG~VpMT~yM|kbb9tnVfj>l5UQK zNo#wp5S%(E|z$bMUKgU@~V|X_g%_|w=87_mn zU}92nEYR^@-hZxOTA;;E|Q?rx;kou8q)tk2vhhE(CZWK|mSjE;E;`Jluudn7r2 zb3fElkAfkI5*T$Hi6T%(&-wShEI^teH-G+0+<&!|5^489jJ?3b3?L1iGSd4Wa*krB z7VANFkeB}Df^}eb!)1wnKY`k;tv(m+kMssKUR5MMI*XZb%;HR{mABH+m*FHz3za)_ zP_WiE?%}W-_cs>&Y4F>vQ@>wtvS+-PsfaV@sxx~EwKsm~1Clq3;@IVYv4Kbj!#7%gyt2%s zF2ih#DU?(cgzHM}mJkaHoQH)8 zT*ZJqI(;+H3s;&#j%25Mu;cT}#f8~!QCCL@ehTgsSvjqB{Y4HB_{jg`>?-^cX%DwQ z9FFb_6b^}`HRr6~tm>}!FU~KyB)84O<8)m6)~vHtkx&Mnl_MXjw{wGJIXO7Fjl3pq zs4fHVvDQ3y{ZX3-lx^UzE@IRL&8Oco8*`NVdS#k`^3^{WXLKN9Dx6PYBo$H!eNY9O zjsDT&cX(pleqQEJbUAqLU-hXN%c~FP?7P2m20c4=aM`Cb(oFggC~;AU?Ft(Jn&bV*L*uU-9G! z;gO!~L05ffMJ6a$B(I?bO2c0V)x2?8vwD_Gsd>Ja>_@I3E$5w<`B(S(9tik5a(-WV zM0IfK_e3fSxCxkf4c1Q=$PN|MR*1Mm=tlE-bS=AzY-rr2 z8}vOrA9U=>%|D2dAzNQnm6Gl-v}w_&?VMz;suqQFTS#@VZNrAZs}Tmw#Kq4COVwIR za)I1CskAJZ$EbYZtw8=GCWnl9+76^{)6MyaJE9UFX;yC=8x8&zcPe~8RAR11Ny7~8 zXP*b{=ij*P%IO$gn_l#|t^HdFA-s_zqd9-dAaq+AfZX4`-nXLN20r$9I^||%%a@6e z4k+hY{7*@s{GmNCsOEIDSkX;??j>_uH%7P&?kldtvClIm{eohux})wDyWqqK+oo-; z^^xFR0txDnJ^YeCjrdVI19~L*nVA>Iw0p?w(nM%XEMI8{HRSOB;eGODz08gM$3?X3 zlKOJ}N2ay#=2W-R`w0=1+{ZdTivia=as^*L$^Lk7wVxr4wX((wv`r${Xann}oVKDKgd^rS%_wTyq)OpX)leY9_(OtLy zc$r0%x_GY&L=nQrkPq1YNJ8f~CUlA!7v+P3rS(VIVf|eA#w#raquW+=uX&dU!xh}^ z?fGT7O)@Xa&S@=s!5*;(j2gX_&ThKDq?=Za9b+ZRfo+LAb7HLzL345d^?!S>cHkmd zMOR79U#z=71P~#42FqzLyxHCbS;*DBjTxMx#m`XfkeKY_Fe}h7k|yaaP-`YEDdZjK zt*Yi0KQH8A&;)cwL-pVh-E_Vrt57u_V`_m3amnzC+@cvZnaK2Om$5JosT&EaOzCM; zBxIOsDpHaY%PP*j`&>cM0DYH;jXBu3X=zYjC3c8bm+|-y%I{RpuHvM%oyR_hk7vpI z4klFPx32?ur*ZyS7VGV^-``buxzc_a-|J!vys}NtEK&T!vTgCoto?Z73ucu~**Z#= zgtrCLoWP&{QDyaRUV+V^FtO~Bf}U=4{pdD}moM=6#~Y*Vcd|Oyug--^ef-U#!aHGj z|G&!6t&eooIuAw1hw~-nuK;CI6zF-ryuHapk9Wu+yz`$*ZU`S0=TH231bw(#0nC zG^HkAGD%iW5)Sf__qcb3O=ao4`-RTbAT1KXA02bp#XoH+3XA>$T3`h3#a%;1o6L^xd|2-Tp&7dr=BFH?`QR)`RY3 z2vPwEdVUgGIbM3TlgRH^d%Z$HuTSaygUHvxpCJ7`*f+JuohB6%y;eA@Poj?>el&tx#(V=hH=jRWf19( znenA>*GP-jt=v!8#+d0uNc$CCZG)F7bF^`Eb5tWkitwbO0JK1YtnYp-0pFNJi6|>0 z-Dwe<{HXDt9WOp;WkwF@Ng_t}CNah)#Mea#HzsL&je$s_8S5cHozWrTy14xP$zrR& zyf5DdsA>#uG^mSrXv3jKeOB(G=DK-NWC>uE(VDK*N+QaVp-rtoLZ{U8%k$o(D)0`^ z!UmNri^z{f&;*Icn{tICZ%TAPlwUV$V^p3*$!&7^1k+(75mY`q;+ zYi$no&0gM=<|D_&)fpQrEYNF(fk@i!%su1`xXzEG>jM;PUMsZDJ6;Ne%r z?`hTmAC$p?-@DI#DP5d^H=_4MduYk+zmmIBmwEwwQ+MAB9*wzhD_dA7axC$`;5SMZ znGDWnUKBfSpe}QdGZg(?5y0zrG`4RzIS~94WZ&uo7+_~bZF5B#sB&F;!)>6S)-757 zNJ)KtcOuC6WwD}?=ZmEnHl$gdf0G3i#sp)tV1tRlxT@X>s&+t4SjWs#V+=)_r@`h z_okxec_N8}G(W$!Q30xTS}mYHP;u^?Z%hW|@ErFHY9ZtT#`QI$kUye$VRD7kn}?v; zM5Q|Fw%`o^pXbv_UeIxkD9Mn(ufK&b3o0~oC9hhIE2Zj`@7<1e4vc7=U+TNKe6+9Y;P+`Sl~qNMTkQ#0>fR;_vT zVkYKWVu5}(T=L$nA%NM`3J^y|jn!5+I5mc1 ze#q;GTx``M_bell1**v#dzq|92i`6j0UsRxL$=!X;C+AM3O845h3^Ta5a0*BT_o$N z;7hPp|G=#kXeh-HV%xYu)w8zmekB!o;q%!bk?rNij9Ap%BMV zc{|iGmw4(;`Mz%zQSZu%QDgyzxq?zVsh$jl_UUNK7ByXvz(Tp{k?Yf^EaPESXSaec zq4A_6=ykhl-Ofhlg@W<@#8Y|m@2$UU^MtQkjpg}C`GxLC16s|Z|L`)5D?<9kEc2X> zlgtd)?z?|`kRIzw6OJ@`9~&xv-d9UA(iZPo_>DG2DaJl{SBY>c9q$taAKVof212`BC~3;>(?-j(>Sa-GW{gbaE|zq_G~pVvI>Sx>EWM z9ks(1VZ&LrEb?$H0kQmYZ-sg%9>m0b-#bS&^QRx? zH&{zub~_PUH&hqsT8XWW1RI+m%S0=vh3*gQK`m6{xg6`ynPYdigEEMN!R}NQ6pUb4 z{5LOzpd2G`)1+VrR=i%P1UE53>*SEv+e%m!JfGfb_2^!a)lfzG&j;^OB&XZxV*5Di zGNGR7^9d23nfc)r1@rsYfmMZ5Qdw}q-5v?>&Ioz>)v0M~#*z^uKANZsUQX*4J#7zK ze@O2Tvuq1$=jbJL`EGs4!1VsYkc=2;V`U+pu6ro|_e+W}G-H4+R35|zFrILV`x z28zEqjn}3N7u*#hgWIL?I0=WrCK)Yt?G%v5R7fukI96;v?bUv}-E-YmtL7aki+kuB z);cYYC)V(m+j*xfZly;mb~fbP6%@ucHz@yuJ)>uilCximMKzi@8v^vwb2^^72#|t?-nxC z9SI_1D%AEe_*DP}=dt>?jr?t1O2}nNfCp>N*9}{mb#P<#qgy{h$Xg`-UZF1p* z9n4At^m+qBtKDynuteZeI0;re%p$E13%VL<#&~TkMlHL{cDE#5EP-EvcCMI4i;U(% zfk889o7Tg@$`<}Vjo_-&BbErWjbJnK7blkoj}s$0A$WRn z{2_kXcpk|_gtQ56(&$YHbH`R=$^79S;z7tal@o0-KzX~DabMy)>&4TQM?3x&fPD_=w7um^|(=-y| z=ESp2#r<6LuM!%xh;Kk?OF_E_oi$b3TENZIKYI8oupD78n5FR{WzPv1_l=LRRRocx zz8O=k8k7dy1Ehrc#!t;!FSVj+Wp)WK4d!Ucqxll$t}A!V%7(&uGbEU)^~XWh#RwjS zBvVSIw{^Dg@zqTFIXT%sn@^8UE9u&`P)(gMK|j4%#(|0elODBY-i(D!&}1YfCy1tz z5!Osxp6WL{Pq7-*Ft1(VNszU${_%3>R||Zvh3pN)!2Sra6cJNjrxs&q0%SwdYf^7Q z|4N^VbG=MFo=>2EMyYX+J?804UdGKe$C?>qCzn5aLl3I1NkcV*yXLRr}4L?2uh7JXlGqRSU`HzzpG zQ!vml3Xn-}Psc7ysRCO`Orn^Mr&5x&SlkF7=3!~!x zWw%#2HK?@gv-VQAxsr0Odcy2*fY!-1I~wb{>D$bcbv8KKcw{2oDXU1^;*c=@LUO^j3IhuOhQSv-%H3g?jH!# z1CPyRVczBRDMS)%ljsbKPU48W^HlU74~VQ5LAvC?uq+4YQyeFE?sYN9YzlDsTjeuM zQ>M$tnxPT;b9?c=Uh#2T4v3@cyosKV+O`NEgvlFv_4M31vfzapM~Ty?ob9db9#lJX zjuJYL&DXfxrO4iQBxiTCkGpU9h#xC|^^aHnnG@c^{cYgo|8WO_TnVBK{Zal_nBlh0 z4n~Dp?b=Z0L8Lh(%{vvr&rLej#wgdRs9DLFgLq+eoe;t8r>wiuIw#f>Egt+Jk4r(! zw|^VsE+(H9zN&t=4chCO4gW8fH4&`Co?iqaf*X=p7DtSgjwlzr798q0%UVxBc%BD+ zj1DBR?`(Z+r1GG0r`j>DHFsEJI?EpHk?t=%Z|b`}q`E9-wC40c{ru!B>|$D7nKFaL zD4u2jQDMFkM5#ymW=tQD9Og?9D=hEBD6=&0q&WueNAq@x^qu~p9PJ8R3?kpI-vyr% zCEix4q^`#ia<+C1K;)6hA=c?hXNlIU+kz62JCwYIDz5wTgS3kVr_A8P$%`hT4FQ&B z>1L7n!-ht0(sjD`ZY7zJSHrSVI}i`-M=oMlw%9@IZ?XF&{TA(hRriD4OB~CDj$Z&& zA1pCq%O0BEzh1F025*BpDMg3DsEL?EBfl=T0ZPBoZ~iMmKVCoZDP64pZm6)Di8Cw; znpA=tYpOvmjGmc@BPf(b6W(@_;x zv6xUyh99RGe_%Z&9a_YLWwT+_3yHf2W7{oNeHs%*0khAB95-yn^iuv^v9zt(H+Es8 zmcnD}xH7K(1f_8)?pz^A06oHY6oZ0=??XjwV%V$M+W_XZ*9{alIenQcny>&|f0eazd; z4+2=Xu<43H&;<7FEouZ!6r&jV|LfsP!;)IRx4|(r&A*kEL!(sA#}bK5t79hvvU0>3 zv$6yc6OWjphpenlX+?q^r!t2WM4Z4(K`ga2MKi%1!Ai*y%5aQ&cfSwsb?vWv@8?;= zz1F(d^DHgN>{a{zBb(Io^%{Y`sA!H$fn7vAuoq6Zkw^ZSuO(!~%|ElzxpQx6aK}xv z@C^9Gqf_`?;QskUe8=9OtaAVL?N81Q!(!!&!!IYAi6EgUPnHw=%-AiBD2lv+hI#AMGvAk~f|-Zy5Pr zK6_Ccx)xY~Ld-~nf;-)O_L6T#d_%fxV2>s+#3Wro@;L4n0UWh$4Le#1F-t1AUx zxY^Wr$EW|aHMZ-W-%MK`lKkX)3x2fgW40v(ot9zZ&YeWHkgJ~Bl6jzLsVXKba@x+B z*uS{we=mYn-{|K3FP36&n8^qWqC58GUh^Q7{{^x7kj@*J@ix`tUNae<@dl#!g#*tr zH>C#%RrN1==jG1PYhHRk5vBbRmQhvg){)*Oeft_8|I?6yPd^AWL@Zvu+P(vtqtnHc zo|^l3afiWO-H2E2nya8g(AHc1vPFKy~QZ!0~DChThnn9t!%YN|TzL z)ot2*FOd3GzAm82%~;P!ZRnF!yxLu6Y9v_@@vI;bq7X$x;1R!09nI>W`MzBz81nig z_)&lO_D)#~<-l>B2725!f$P%X!h;Vz#xJ?YGCm&}su>oSed_43(Sn`~sniSq(_-fT z4y{=ndY17&gb1mp6P7_U%z5R2us#zgq3Ee-=fe7h&kXnm!lZ_^&sYC&kv~OZSaD`gXA=WMNRwrvdDXy$zAY^ku0e$2Z4h&n0mu{;-rSp+|KyzbpssTT(Hf&PHR zT4;M|pNv-9^3LgK&w_0oXX?Oy$Gex0&Txxr&8rgFUihaxiIHA1pO$zx< z{OCsY1@QB$i@QeNPxnw;u0Xv1b!>LNIdVt~vwC^MWM7GdARNPaP8wiiWZ#i95s31- z%qdZI?kbU3Oi`Ne0av<|#6xGqivS27?z+{yBlw=h8l&|KWoL)C9EsZKz$@@K9607*lZ@MXH~o8ELHD}8UP#@hBh<9NfB6UquO-{iJmy^Smw zRC3Mxmj3M4pk6ASlCTya0Xf@VR~1BzXjb7+i?|!@nI&i4-+Tif;PjO?lQ4PgA~6g) zVX7wiU7uVK1mSYC&Rahgbxu3P&zlIWJ$c18GRvWXKOdE>VqWyo572Z-qZlhVRQwQ*I89^`q0-FbDT-ipq-J<$X^$28*c4+INW-@(m}IPYpLQw z(G&YIs}1~}AQ*GGFr>Prr}t!KuZ^`89>(@nBBe}d+v&jYK6Jy}ud4(DkiB_}8)(52 zqbG5t*xoHWtDRfxUHo9JOBc(Ny<$3cZ?WyJ(vBeXl$N2DN#B6@)HnnhElF(Z>DrthXrfSFML$jaZD_jvq}<;% zpphtMn_vgfvOQggvf?1dV^W#Tc=T|TB^UW_#@BFZ8|xO#&^|_LKtT^2^-nD$Kl* z*m4CrJ7MBWXdfKSwz+uw8;4H(MX(G@e(eEHKg|8|VsTz&I^$Jh<7W0!u@? z09X`w#=FTkx_!WwBx3b zeff1e=B70j*@7V-`JTnTWh6Ecin^0M#p_-I9r6vesLH!qb)&$ZYn?o@NquV)k9%^` z5@dgLnNE=hQY)}gT!#p^!$5N{;!|J`3M3Ew*yy25iAOIGJ!UN+3^aAz2KaxwpWA=J zWaaeBGrIng%XWQkXU+7^;-R@}80jH;%!R{qcUD)TWJVnR5H+qCj7bMLSsr2AO92Tu zjMKPnzc+_xaT*~ui?4AMH^hsAdSmT$Bn~+Ps)TJBu9Zkkon+Srz6m!j%KGik#xV!b zY9`^DybyANA6saIK$~2~q?gMwsk`*f>H&^vw1iyG{4>0f2z^&+&YHMXvcs20-NN%y zV0Q;Zwk6`M?E{}qnR}Od305+4yao!+WcapJZRfr+PXhrI6s|oX`m!WBq@rj(IXR%a z(N0U@C1{`@U^})Wbuk_yrVi%zh|L!B=YAsVDj=n{4gRrJTD2l=$h<2vx-7w0=R;O_x0hG5`dkOLlN_>i$yF zxw#zVU1VDlG?P7KwQmo_`_ro`dR(bV1xrk_M4(Ys`OrQ>hNZjPAMq@ii*5p5Dyopt z;;XXt8hiZ-tnt5!ZDr6_^0TPX4Qo(F0l$$!gD{<6C zd1(zl4~UR3i)JJidUNk6EOjP}y!jc9ViP9(sdL1!{H=B8G5Coa%T zBU_S_)r}pcOi%exxePOF;ilgukg5%#Wx-kzQD ze!$P~tTLoqNz15v+mlY`RXSckt!A>1*FVrAL#Y*xANeLz{jl&eg+sJ7W$=p$Qcr5W z8la}3nTgZ?Ic&W9lvdt*+b^3=ytA0nbuyqH0?uWmC9hlWeOPwic2+$`XPkM~MI9~q zbL5n*B;lz364t+))AwTn**NH%=BObxlj>LH;8_))3A2f#_&dtzYvYaL1oj3$ilx>| zqrXFgN@|&D-eb%MU(3M~Xh1io6qDY+$S?E=6ee*U?d*oXJOCAbdu!~a%$ zz|?iyF|+V2qpDEm^NMl+G7+T9$5jLRVH4U2mecjuS4I#ou~OCZvikI*_;MiXLUBnr zPHxttsEtp_=fH=Y%)$}dPl01@7csRYk4#$W;#^DC(q5d#w2GVue0`M^#w* z*IUHbH*bPwt^qp;DEwSXFTbcieFbqFZBm8lV{a0`1{zff8JYyg0k%3e zog=|v`qgMf!F&E%P78cTeT+KzEWyrj5e&!^LNgP2%?F`A`r@ZZ8wA8_B+GcBH}CQO za{&9o%Z41!{u&yY$8M>x)xnf#Afmn)g1Y~+b=kO%1a7ogqF3h!4ZNE}xEoCec&p~X z3aTLIRkZM3JJyzgHj&dPfLu+=LMm)<_0$bsn_x}#>l7ZAy)YhJY8U3AD@kFPqabY1gW?fGuQAP}w;Bb^F54_&1n zpXu+9Da=$h7JXp1q#Pevp|fW{`}5eVmw&?&D%Ji7%`P&)6W9y1bf}8+J%L>^YjeX3 z&z(0UCxZ-bUzY6+phjH3H?YVx0E(pIk9=HBe$GmsUsE{f;Q>ep@gj`vp%mwjA9BC_ zAflQUQBvb*%-A?j%a|atWIvl;e{5D+I8MHL-E*0$O|3d-A;W&zjJS6Z(N+T#P1E&0 zT?9)d^PRljXM$*{ymN5DG7POs1l!z*J`q7Yk?MOQ7p4J#yZBjR@z+r;iTkQ6>i9R0 zW)f0!-G!^qj`**{P}M$~1$4U(1?cfTRCBClS{(1GT>>H<)&dGOA`?G!!NYl+tWAjZ ztRe>5d2~q1)Wd*&0JBKW{b8NRSj*Hh%=$8KJhc+%hU!M2;MU&2|B^#rqERYr-w&kJ zI`V}lW3Fzu(i&W8KY!(<>fa49c8ZCP7_HLY8`(5Fqf!e!sCCHT`n%Y=T+aSHQ*u*u z)b3jQp(~wJ~~$%F3Cb2GY)t<8guCH+z@ni^Yu zaCx1)W?eJ4dGVc7CbTsL(8SwB`gzxWpF|7Krutc#3&;R0?=`_*FC8tm2!y^}Ml~F9 z&`fuL)O~(LFjxv)GenI1Mfer1$eUXXUQb3bFgg_IzQ>R$G?fei#|UR+d1u!;=^fPI zw-AbPhR?I2{OY%$?HvE*LId#O5Aajswb&4HKWgSTa)@hlHhcwl8;T0v4*b8l0j)uZ%SzP zitX9MB;(o*0T36iN1^tT9iFkl+|-fvG0MLFtxN8x?D>PHaf#GD^=NXU7)=?HAPzB5-s z^?)H67+X-*6d3|sULNQU1$GQLu4~{b@Rs*{;wn3`TONWUS>u>hX4CPVkfbLiN5t`<9)S(yTEa zKy+Ixexw}kliT05*SgD_3BsKeOjSQA21PUKwu*8J`M>jGZ$4)KIfOrTYj>c!anyik zI>a3s*zKWO5fR$I6>?rK0;4>?sy{bYhz+Op5w#t@;k6rbQF;#-4(^%8on##O2gJr=G3*NoZ#MCmtNgO$piGXl==m_vu9n z7IZFXFfo*|!eYtijcOh0XVH~b#^k!E53H(0|BvmWqJdkzN?XMULL1clq4R;Md?@8 z)*rtn&q^n}cyPYxN&HJ%Up(Ck6WLbdqe31G5dq2Tbp3H96B<`A(EYyHJ$ovv^AbYq zyWMZ&DbR;vJ$VHkKy>Ukk>fiSnQ7FgRmB72Si2>ph+Q;VCoY%uUT{bGHsNMfHj(@S z9U!MAfy~q-hOMT$qk%>&EUMm$ZE#-1+4? z<0}AYyck;ro(>Ggglq7LP9GlCyb=YL%YZrux}GhrNWp1TvggpaIkxTTZ(ToGfnXG< z(MQw}@fL0Y1eMi|yKbva4Rp=naFzMcPkf?(clK0&R^0Df(in#`N2_nm{suYQ@CH6) zi}Ul@h50Ds+I0f>SkRp*R&%V7Hrd#vfb2l2jdJ!%B3$Icw1o?YhWdf-lAtbbrtY}1 zA!0QEr$%Lg^J||FQ(=zc99%SEZvyTFSJ#sdFWEBwC7SjsK3c((+zogK$njCd`Lot2 z;|_711;jmDTr(lK(Ys3<*O?-&eUfzvfLQ>m+_JGY?_v!+`GBWk6~ALX1v+NU0jjgF zNN*M0&LxncDuc8YHAxV-)=lr;>1oErf6=v;;Ng6PL!KScMrBPChNVdKF5`+n86X_VjJ+T)y8N!C5E zC&BIQ9d2`Mv<`alzhVJ;FrvDd)Tn`YpCT?_W%;VGyD>EGV^r2Q(Id)u#E~T1FWJ(Z z_pud_0Y-COGkV`A^dQ!2aQce=ZFKJo37xF;KIeQ60a*M%ck!$Yj=FywP+@|bFX7bN zdU^uk&hnh8^Ye5Bdhjv^fLNBycy(mx-|B(xCdZ(4QphXVd2(3k6ibu8<3AyaF|S{h z*RO?{UFH)lCH2yvnibIu*_WvbexW))xkRW~`z1v8z=lRB=iypkUV(zPJ7D0GI6F$& zYM=71$I0sjg%LO4wX=YToVe)B)q~kka727_jTC8?(DCC(!E110?r>;r4MN` zYXFcP-7U)5|Jx@^ZEdS^+!}(RORixS>YLgQ1}hI&417g81J8mr=P_hHrFe>Duo_VF zqtp-7fZzS>CrgyNuSCm#EzoNiaoaHbDCR^X>9(S)I7OC5$Z&cH{|FSGcIRABW7g>^ zB-o~%Oy7;cUsIKD`6aSB+M)HoCAa%QGq(&pR}5dqM85RB^$o8umw%nHk^*2Iw&E}b z?_+NeWG~c2s0b__|LotK(Zb(Vnt7&;^$%IGZAruoqbS7)`je>_HdBuer&h$aBm?!s zVyFL3;|{;-i4%P6!aV;4rU4suwCq2MNS+GC9tD=?5yJZO6M%F{Z|@fsAFtn+?^)YB zE}T=Uf|9uML1_d1g(Tvz-2Ba%7r%(WkN*Oj>5dNba)I`M(~?2f_Ab1$%&W;&`htxb zYsh>~n1wd=1~d^Np^>ivDWS24?OlF0C_x4{2wyY`hv~#i$%MTCHxvXNTJ{`*Zz9Vw zR-Kg2p|P3gM&-fju%dSKASg8P2Z;&JHRTu3iP7UZ`v=?2H?0Nv61eh=X$(Vr{x yv!0~L7%Gu4r2_ubTC=i5RSv&iph5Yy?FizVnCkzB9x&D&g!t>!v5G&#QvV-EqxWtA literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/physics_func.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/physics_func.cpp new file mode 100644 index 0000000..b45e331 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/physics_func.cpp @@ -0,0 +1,769 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "physics_func.h" +#include "../common/perf_func.h" + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Data + +#define NUM_RIGIDBODIES 500 +#define NUM_JOINTS 500 +#define NUM_CONTACTS 4000 + +const float timeStep = 0.016f; +const float separateBias = 0.1f; +int iteration = 5; + +//J ワールドサイズ +//E World size +PfxVector3 worldCenter(0.0f); +PfxVector3 worldExtent(500.0f); + +//J 剛体 +//E Rigid body +PfxRigidState states[NUM_RIGIDBODIES]; +PfxRigidBody bodies[NUM_RIGIDBODIES]; +PfxCollidable collidables[NUM_RIGIDBODIES]; +PfxSolverBody solverBodies[NUM_RIGIDBODIES]; +int numRigidBodies = 0; + +//J 地形を表現するためのラージメッシュ +//E Large mesh for representing a landscape +#include "landscape.h" +PfxLargeTriMesh gLargeMesh; + +//J 凸メッシュ +//E Convex Mesh +#include "barrel.h" +PfxConvexMesh gConvex; + +//J プロキシ +//E Proxies +PfxBroadphaseProxy proxies[NUM_RIGIDBODIES]; + +//J ジョイント +//E Joint +PfxConstraintPair jointPairs[NUM_JOINTS]; +PfxJoint joints[NUM_JOINTS]; +int numJoints = 0; + +//J ペア +//E Pairs +unsigned int numPairs; +PfxBroadphasePair pairs[NUM_CONTACTS]; + +//J コンタクト +//E Contacts +PfxContactManifold contacts[NUM_CONTACTS]; +int numContacts; + +//J 一時バッファ +//E Temporary buffers +#define POOL_BYTES (5*1024*1024) +unsigned char SCE_PFX_ALIGNED(128) poolBuff[POOL_BYTES]; + +//J 一時バッファ用スタックアロケータ +//E Stack allocator for temporary buffers +PfxHeapManager pool(poolBuff,POOL_BYTES); + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Function + +int frame = 0; + +void broadphase() +{ + //J 剛体が最も分散している軸を見つける + //E Find the axis along which all rigid bodies are most widely positioned + int axis = 0; + { + PfxVector3 s(0.0f),s2(0.0f); + for(int i=0;i v[0]) axis = 1; + if(v[2] > v[axis]) axis = 2; + } + + //J ブロードフェーズプロキシの更新 + //E Create broadpahse proxies + { + for(int i=0;i 0) { + pfxReleaseLargeTriMesh(gLargeMesh); + } + + PfxInt32 ret = pfxCreateLargeTriMesh(gLargeMesh,param); + if(ret != SCE_PFX_OK) { + SCE_PFX_PRINTF("Can't create large mesh.\n"); + } + + int id = numRigidBodies++; + PfxShape shape; + shape.reset(); + shape.setLargeTriMesh(&gLargeMesh); + collidables[id].reset(); + collidables[id].addShape(shape); + collidables[id].finish(); + bodies[id].reset(); + states[id].reset(); + states[id].setPosition(PfxVector3(0.0f,-5.0f,0.0f)); + states[id].setOrientation(PfxQuat::rotationX(0.5f)*PfxQuat::rotationY(0.7f)); + states[id].setMotionType(kPfxMotionTypeFixed); + states[id].setRigidBodyId(id); +} + +void physics_create_scene(int sceneId) +{ + const int numScenes = 4; + int sid = sceneId % numScenes; + + numRigidBodies= 0; + numPairs = 0; + numContacts = 0; + numJoints = 0; + frame = 0; + + switch(sid) { + case 0: // simple primitives + createSceneBoxGround(); + createScenePrimitives(); + break; + + case 1: // joints + createSceneBoxGround(); + createSceneJoints(); + break; + + case 2: // stacking + createSceneBoxGround(); + createSceneStacking(); + break; + + case 3: // landscape + createSceneLandscape(); + createScenePrimitives(); + break; + } + + SCE_PFX_PRINTF("----- Size of rigid body buffer ------\n"); + SCE_PFX_PRINTF(" size * num = total\n"); + SCE_PFX_PRINTF("PfxRigidState %5d * %5d = %5d bytes\n",sizeof(PfxRigidState),numRigidBodies,sizeof(PfxRigidState)*numRigidBodies); + SCE_PFX_PRINTF("PfxRigidBody %5d * %5d = %5d bytes\n",sizeof(PfxRigidBody),numRigidBodies,sizeof(PfxRigidBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxCollidable %5d * %5d = %5d bytes\n",sizeof(PfxCollidable),numRigidBodies,sizeof(PfxCollidable)*numRigidBodies); + SCE_PFX_PRINTF("PfxJoint %5d * %5d = %5d bytes\n",sizeof(PfxJoint),numJoints,sizeof(PfxJoint)*numJoints); + SCE_PFX_PRINTF("PfxSolverBody %5d * %5d = %5d bytes\n",sizeof(PfxSolverBody),numRigidBodies,sizeof(PfxSolverBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxBroadphaseProxy %5d * %5d = %5d bytes\n",sizeof(PfxBroadphaseProxy),numRigidBodies,sizeof(PfxBroadphaseProxy)*numRigidBodies); + SCE_PFX_PRINTF("PfxContactManifold %5d * %5d = %5d bytes\n",sizeof(PfxContactManifold),NUM_CONTACTS,sizeof(PfxContactManifold)*NUM_CONTACTS); + SCE_PFX_PRINTF("PfxBroadphasePair %5d * %5d = %5d bytes\n",sizeof(PfxBroadphasePair),NUM_CONTACTS,sizeof(PfxBroadphasePair)*NUM_CONTACTS); + + int totalBytes = + (sizeof(PfxRigidState) + sizeof(PfxRigidBody) + sizeof(PfxCollidable) + sizeof(PfxSolverBody) + sizeof(PfxBroadphaseProxy)) * numRigidBodies + + (sizeof(PfxContactManifold) + sizeof(PfxBroadphasePair)) * NUM_CONTACTS; + SCE_PFX_PRINTF("----------------------------------------------------------\n"); + SCE_PFX_PRINTF("Total %5d bytes\n",totalBytes); +} + +/////////////////////////////////////////////////////////////////////////////// +// Initialize / Finalize Engine + +bool physics_init() +{ + return true; +} + +void physics_release() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Pick + +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2) +{ + return PfxVector3(0.0f); +} + +void physics_pick_update(const PfxVector3 &p) +{ +} + +void physics_pick_end() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Get Information + +int physics_get_num_rigidbodies() +{ + return numRigidBodies; +} + +const PfxRigidState& physics_get_state(int id) +{ + return states[id]; +} + +const PfxRigidBody& physics_get_body(int id) +{ + return bodies[id]; +} + +const PfxCollidable& physics_get_collidable(int id) +{ + return collidables[id]; +} + +int physics_get_num_contacts() +{ + return numPairs; +} + +const PfxContactManifold &physics_get_contact(int id) +{ + return contacts[pfxGetConstraintId(pairs[id])]; +} + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/physics_func.h b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/physics_func.h new file mode 100644 index 0000000..0aa7e07 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/physics_func.h @@ -0,0 +1,49 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef __PHYSICS_FUNC_H__ +#define __PHYSICS_FUNC_H__ + +#define SCE_PFX_USE_PERFCOUNTER + +#include "physics_effects.h" + +using namespace sce::PhysicsEffects; + +//E Simulation +//J シミュレーション +bool physics_init(); +void physics_release(); +void physics_create_scene(int sceneId); +void physics_simulate(); + +//E Picking +//J ピッキング +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2); +void physics_pick_update(const PfxVector3 &p); +void physics_pick_end(); + +//E Change parameters +//J パラメータの取得 +int physics_get_num_rigidbodies(); +const PfxRigidState& physics_get_state(int id); +const PfxRigidBody& physics_get_body(int id); +const PfxCollidable& physics_get_collidable(int id); + +int physics_get_num_contacts(); +const PfxContactManifold &physics_get_contact(int id); + +#endif /* __PHYSICS_FUNC_H__ */ diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/premake4.lua b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/premake4.lua new file mode 100644 index 0000000..4bd42a3 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple/premake4.lua @@ -0,0 +1,22 @@ + project "1_simple" + + kind "WindowedApp" + targetdir "../../../bin" + includedirs {"../../../include"} + + links { + "physicseffects2_lowlevel", + "physicseffects2_baselevel", + "physicseffects2_util", + "opengl32" + } + + flags {"WinMain"} + + files { + "main.cpp", + "physics_func.cpp", + "../common/ctrl_func.win32.cpp", + "../common/perf_func.win32.cpp", + "../common/render_func.win32.cpp" + } \ No newline at end of file diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/barrel.h b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/barrel.h new file mode 100644 index 0000000..6574fa8 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/barrel.h @@ -0,0 +1,202 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define BarrelVtxCount 57 +#define BarrelIdxCount 180 + +static float BarrelVtx[] = { +0.0f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +-0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +0.0f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +-0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.957307f,-0.289072f,0.0f, +0.404509f,0.0f,-0.293893f, 0.809017f,0.0f,-0.587785f, +0.5f,0.0f,0.0f, 1.0f,0.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.774478f,-0.289072f,-0.562691f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +-0.154509f,0.0f,-0.475528f, -0.309017f,0.0f,-0.951057f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +-0.107853f,-0.5f,-0.331936f, -0.295824f,-0.289072f,-0.910453f, +-0.404509f,0.0f,-0.293893f, -0.809017f,0.0f,-0.587785f, +-0.282362f,-0.5f,-0.205148f, -0.774478f,-0.289072f,-0.562691f, +-0.5f,0.0f,0.0f, -1.0f,0.0f,0.0f, +-0.349018f,-0.5f,0.0f, -0.957307f,-0.289072f,0.0f, +-0.404508f,0.0f,0.293893f, -0.809017f,0.0f,0.587785f, +-0.282362f,-0.5f,0.205148f, -0.774478f,-0.289072f,0.562691f, +-0.154509f,0.0f,0.475528f, -0.309017f,0.0f,0.951056f, +-0.107853f,-0.5f,0.331936f, -0.295824f,-0.289072f,0.910453f, +0.154509f,0.0f,0.475528f, 0.309017f,0.0f,0.951056f, +0.107853f,-0.5f,0.331936f, 0.295824f,-0.289072f,0.910453f, +0.404509f,0.0f,0.293892f, 0.809017f,0.0f,0.587785f, +0.282362f,-0.5f,0.205148f, 0.774478f,-0.289072f,0.562691f, +0.282362f,0.5f,-0.205148f, 0.774478f,0.289072f,-0.562691f, +0.349018f,0.5f,0.0f, 0.957307f,0.289072f,0.0f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.107853f,0.5f,-0.331936f, -0.295824f,0.289072f,-0.910453f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.282362f,0.5f,-0.205148f, -0.774478f,0.289072f,-0.562691f, +-0.349018f,0.5f,0.0f, -0.957307f,0.289072f,0.0f, +-0.282362f,0.5f,0.205148f, -0.774478f,0.289072f,0.562691f, +-0.107853f,0.5f,0.331936f, -0.295824f,0.289072f,0.910453f, +0.107853f,0.5f,0.331936f, 0.295824f,0.289072f,0.910453f, +0.282362f,0.5f,0.205148f, 0.774478f,0.289072f,0.562691f, +}; + +static float BarrelTex[] = { +0.0f,0.5f, +0.0f,0.85f, +0.0f,0.75f, +0.0f,0.95f, +0.0f,0.05f, +0.0f,-0.05f, +0.0f,0.15f, +0.0f,0.25f, +0.0f,0.35f, +0.0f,0.45f, +0.0f,0.55f, +0.0f,0.65f, +1.0f,0.5f, +1.0f,0.75f, +1.0f,0.85f, +1.0f,0.95f, +1.0f,-0.05f, +1.0f,0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +0.0f,0.75f, +0.5f,0.85f, +0.5f,0.75f, +0.0f,0.85f, +0.5f,0.95f, +0.0f,0.95f, +0.0f,-0.05f, +0.5f,0.05f, +0.5f,-0.05f, +0.0f,0.05f, +0.5f,0.15f, +0.0f,0.15f, +0.5f,0.25f, +0.0f,0.25f, +0.5f,0.35f, +0.0f,0.35f, +0.5f,0.45f, +0.0f,0.45f, +0.5f,0.55f, +0.0f,0.55f, +0.5f,0.65f, +0.0f,0.65f, +1.0f,0.85f, +1.0f,0.75f, +1.0f,0.95f, +1.0f,0.05f, +1.0f,-0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +}; + +static unsigned short BarrelIdx[] = { +0,1,2, +0,3,1, +0,4,5, +0,6,4, +0,7,6, +0,8,7, +0,9,8, +0,10,9, +0,11,10, +0,2,11, +12,13,14, +12,14,15, +12,16,17, +12,17,18, +12,18,19, +12,19,20, +12,20,21, +12,21,22, +12,22,23, +12,23,13, +24,25,26, +24,27,25, +27,28,25, +27,29,28, +30,31,32, +30,33,31, +33,34,31, +33,35,34, +35,36,34, +35,37,36, +37,38,36, +37,39,38, +39,40,38, +39,41,40, +41,42,40, +41,43,42, +43,44,42, +43,45,44, +45,26,44, +45,24,26, +26,46,47, +26,25,46, +25,48,46, +25,28,48, +32,49,50, +32,31,49, +31,51,49, +31,34,51, +34,52,51, +34,36,52, +36,53,52, +36,38,53, +38,54,53, +38,40,54, +40,55,54, +40,42,55, +42,56,55, +42,44,56, +44,47,56, +44,26,47, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/landscape.h b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/landscape.h new file mode 100644 index 0000000..00f6cff --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/landscape.h @@ -0,0 +1,318 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define LargeMeshVtxCount 81 +#define LargeMeshIdxCount 384 + +static float LargeMeshVtx[] = { +-25.0f,-2.19407f,18.5625f, 0.232976f,0.967754f,0.0957829f, +-25.0f,0.0644502f,24.75f, 0.188094f,0.871343f,-0.45319f, +-18.75f,-4.50287f,18.5625f, -0.0716098f,0.995449f,0.0628767f, +-18.75f,-0.39999f,24.75f, -0.0602794f,0.895848f,-0.440253f, +-12.5f,-1.2166f,18.5625f, -0.269469f,0.961403f,0.0555879f, +-12.5f,-0.942431f,24.75f, -0.0997841f,0.993258f,0.0589987f, +-6.25f,1.93598f,18.5625f, -0.283933f,0.956351f,-0.0691025f, +-6.25f,-0.445954f,24.75f, -0.180725f,0.942766f,0.280233f, +0.0f,2.76983f,18.5625f, 0.171645f,0.984908f,0.0222501f, +0.0f,2.76642f,24.75f, 0.0784993f,0.995428f,-0.0544117f, +6.25f,-2.53736f,18.5625f, 0.248298f,0.965028f,0.0840741f, +6.25f,-0.915645f,24.75f, 0.164311f,0.945856f,-0.279926f, +12.5f,-1.60054f,18.5625f, -0.180435f,0.983586f,0.00115547f, +12.5f,0.831925f,24.75f, -0.0692495f,0.964821f,-0.253623f, +18.75f,-0.800282f,18.5625f, 0.10755f,0.951538f,0.288112f, +18.75f,-1.47284f,24.75f, 0.232178f,0.972664f,0.00429361f, +25.0f,-2.78379f,18.5625f, 0.1833f,0.937477f,0.295867f, +25.0f,-0.967508f,24.75f, -0.0773477f,0.956641f,-0.280812f, +-25.0f,-0.352038f,12.375f, -0.192222f,0.972435f,0.131987f, +-18.75f,0.681228f,12.375f, -0.107779f,0.962569f,0.248686f, +-12.5f,2.72065f,12.375f, 0.0520846f,0.993034f,0.105692f, +-6.25f,-1.78776f,12.375f, -0.0133223f,0.99674f,-0.0795754f, +0.0f,1.57707f,12.375f, -0.129025f,0.969662f,-0.207627f, +6.25f,0.424356f,12.375f, 0.180995f,0.97074f,0.157815f, +12.5f,0.283234f,12.375f, -0.16285f,0.973539f,0.160316f, +18.75f,2.57015f,12.375f, -0.165454f,0.978339f,0.124408f, +25.0f,3.07363f,12.375f, -0.00454559f,0.988151f,0.153417f, +-25.0f,-0.893751f,6.1875f, -0.0836251f,0.990084f,-0.112876f, +-18.75f,0.930932f,6.1875f, 0.00269413f,0.971838f,-0.235633f, +-12.5f,-0.684529f,6.1875f, -0.010319f,0.927048f,-0.3748f, +-6.25f,-0.661383f,6.1875f, 0.012265f,0.999875f,-0.00994222f, +0.0f,0.385718f,6.1875f, -0.15435f,0.984937f,-0.0779465f, +6.25f,0.589796f,6.1875f, 0.0241717f,0.999582f,-0.0158589f, +12.5f,0.47454f,6.1875f, -0.017184f,0.997953f,-0.0616073f, +18.75f,1.59939f,6.1875f, -0.0902706f,0.957309f,-0.274609f, +25.0f,1.13434f,6.1875f, 0.0346006f,0.957441f,-0.286547f, +-25.0f,0.74548f,0.0f, 0.329903f,0.930812f,0.157334f, +-18.75f,-2.47437f,0.0f, 0.247844f,0.968142f,0.0357041f, +-12.5f,-4.16309f,1.81975e-007f, -0.0623898f,0.997626f,-0.0291436f, +-6.25f,-0.700022f,0.0f, -0.217067f,0.974987f,-0.0477624f, +0.0f,-0.0957388f,0.0f, -0.117693f,0.990712f,-0.068098f, +6.25f,0.614077f,0.0f, -0.0713214f,0.997305f,0.01722f, +12.5f,0.299109f,0.0f, 0.218606f,0.968641f,0.118094f, +18.75f,-1.71753f,0.0f, 0.0339493f,0.985612f,-0.165579f, +25.0f,-1.12638f,0.0f, -0.0547573f,0.989177f,-0.136126f, +-25.0f,-0.403319f,-6.1875f, -0.1263f,0.989211f,-0.074223f, +-18.75f,-0.0730335f,-6.1875f, 0.0173428f,0.965382f,0.260261f, +-12.5f,-0.450125f,-6.1875f, 0.0658811f,0.875f,0.479619f, +-6.25f,-0.180204f,-6.1875f, 0.0116584f,0.981445f,0.19139f, +0.0f,-0.632679f,-6.1875f, -0.0557983f,0.993041f,-0.103716f, +6.25f,0.308409f,-6.1875f, -0.191898f,0.96766f,-0.163737f, +12.5f,2.5011f,-6.1875f, 0.0758397f,0.996403f,-0.0378189f, +18.75f,-1.69303f,-6.1875f, 0.16761f,0.974057f,0.15205f, +25.0f,-0.141349f,-6.1875f, -0.204846f,0.978471f,0.0251341f, +-25.0f,-1.10316f,-12.375f, -0.0350644f,0.993748f,-0.106001f, +-18.75f,1.06711f,-12.375f, -0.309806f,0.919244f,-0.242922f, +-12.5f,3.61544f,-12.375f, -0.0506281f,0.998702f,-0.00561657f, +-6.25f,1.6504f,-12.375f, 0.322294f,0.937465f,0.131477f, +0.0f,-1.60595f,-12.375f, 0.086016f,0.995916f,0.0274459f, +6.25f,-0.849859f,-12.375f, -0.0332811f,0.997087f,0.0686255f, +12.5f,-0.942201f,-12.375f, -0.153559f,0.982185f,-0.108312f, +18.75f,0.494873f,-12.375f, 0.0753195f,0.981472f,0.176181f, +25.0f,-0.333828f,-12.375f, 0.035057f,0.987194f,0.155624f, +-25.0f,2.1862f,-18.5625f, 0.612899f,0.782306f,0.111138f, +-18.75f,-3.38259f,-18.5625f, 0.0194078f,0.992789f,-0.118297f, +-12.5f,-0.880916f,-18.5625f, -0.282251f,0.949875f,-0.13443f, +-6.25f,0.818158f,-18.5625f, 0.1476f,0.981788f,-0.119612f, +0.0f,-1.48019f,-18.5625f, -0.044551f,0.996013f,-0.0772824f, +6.25f,1.47123f,-18.5625f, -0.117036f,0.97986f,0.161792f, +12.5f,0.164076f,-18.5625f, -0.0340355f,0.978993f,0.201034f, +18.75f,2.14568f,-18.5625f, -0.0439269f,0.994859f,0.0912435f, +25.0f,0.626506f,-18.5625f, 0.208015f,0.968592f,0.136229f, +-25.0f,0.296889f,-24.75f, 0.46973f,0.844327f,-0.257809f, +-18.75f,-3.18022f,-24.75f, -0.0226758f,0.998794f,-0.0435401f, +-12.5f,1.8927f,-24.75f, -0.202772f,0.919836f,0.335836f, +-6.25f,1.46387f,-24.75f, 0.224904f,0.955746f,0.189652f, +0.0f,-2.52726f,-24.75f, -0.0435882f,0.993572f,-0.10447f, +6.25f,1.30397f,-24.75f, -0.28646f,0.956525f,-0.0547707f, +12.5f,1.85812f,-24.75f, 0.0521949f,0.979796f,0.193067f, +18.75f,1.56331f,-24.75f, -0.0270784f,0.999629f,-0.00293115f, +25.0f,1.05366f,-24.75f, 0.161f,0.986887f,-0.0115473f, +}; + +static float LargeMeshTex[] = { +0.125f,0.0f, +0.0f,0.0f, +0.125f,0.125f, +0.0f,0.125f, +0.125f,0.25f, +0.0f,0.25f, +0.125f,0.375f, +0.0f,0.375f, +0.125f,0.5f, +0.0f,0.5f, +0.125f,0.625f, +0.0f,0.625f, +0.125f,0.75f, +0.0f,0.75f, +0.125f,0.875f, +0.0f,0.875f, +0.125f,1.0f, +0.0f,1.0f, +0.25f,0.0f, +0.25f,0.125f, +0.25f,0.25f, +0.25f,0.375f, +0.25f,0.5f, +0.25f,0.625f, +0.25f,0.75f, +0.25f,0.875f, +0.25f,1.0f, +0.375f,0.0f, +0.375f,0.125f, +0.375f,0.25f, +0.375f,0.375f, +0.375f,0.5f, +0.375f,0.625f, +0.375f,0.75f, +0.375f,0.875f, +0.375f,1.0f, +0.5f,0.0f, +0.5f,0.125f, +0.5f,0.25f, +0.5f,0.375f, +0.5f,0.5f, +0.5f,0.625f, +0.5f,0.75f, +0.5f,0.875f, +0.5f,1.0f, +0.625f,0.0f, +0.625f,0.125f, +0.625f,0.25f, +0.625f,0.375f, +0.625f,0.5f, +0.625f,0.625f, +0.625f,0.75f, +0.625f,0.875f, +0.625f,1.0f, +0.75f,0.0f, +0.75f,0.125f, +0.75f,0.25f, +0.75f,0.375f, +0.75f,0.5f, +0.75f,0.625f, +0.75f,0.75f, +0.75f,0.875f, +0.75f,1.0f, +0.875f,0.0f, +0.875f,0.125f, +0.875f,0.25f, +0.875f,0.375f, +0.875f,0.5f, +0.875f,0.625f, +0.875f,0.75f, +0.875f,0.875f, +0.875f,1.0f, +1.0f,0.0f, +1.0f,0.125f, +1.0f,0.25f, +1.0f,0.375f, +1.0f,0.5f, +1.0f,0.625f, +1.0f,0.75f, +1.0f,0.875f, +1.0f,1.0f, +}; + +static unsigned short LargeMeshIdx[] = { +0,1,2, +3,2,1, +2,3,4, +5,4,3, +4,5,6, +7,6,5, +6,7,8, +9,8,7, +8,9,10, +11,10,9, +10,11,12, +13,12,11, +12,13,14, +15,14,13, +14,15,16, +17,16,15, +18,0,19, +2,19,0, +19,2,20, +4,20,2, +20,4,21, +6,21,4, +21,6,22, +8,22,6, +22,8,23, +10,23,8, +23,10,24, +12,24,10, +24,12,25, +14,25,12, +25,14,26, +16,26,14, +27,18,28, +19,28,18, +28,19,29, +20,29,19, +29,20,30, +21,30,20, +30,21,31, +22,31,21, +31,22,32, +23,32,22, +32,23,33, +24,33,23, +33,24,34, +25,34,24, +34,25,35, +26,35,25, +36,27,37, +28,37,27, +37,28,38, +29,38,28, +38,29,39, +30,39,29, +39,30,40, +31,40,30, +40,31,41, +32,41,31, +41,32,42, +33,42,32, +42,33,43, +34,43,33, +43,34,44, +35,44,34, +45,36,46, +37,46,36, +46,37,47, +38,47,37, +47,38,48, +39,48,38, +48,39,49, +40,49,39, +49,40,50, +41,50,40, +50,41,51, +42,51,41, +51,42,52, +43,52,42, +52,43,53, +44,53,43, +54,45,55, +46,55,45, +55,46,56, +47,56,46, +56,47,57, +48,57,47, +57,48,58, +49,58,48, +58,49,59, +50,59,49, +59,50,60, +51,60,50, +60,51,61, +52,61,51, +61,52,62, +53,62,52, +63,54,64, +55,64,54, +64,55,65, +56,65,55, +65,56,66, +57,66,56, +66,57,67, +58,67,57, +67,58,68, +59,68,58, +68,59,69, +60,69,59, +69,60,70, +61,70,60, +70,61,71, +62,71,61, +72,63,73, +64,73,63, +73,64,74, +65,74,64, +74,65,75, +66,75,65, +75,66,76, +67,76,66, +76,67,77, +68,77,67, +77,68,78, +69,78,68, +78,69,79, +70,79,69, +79,70,80, +71,80,70, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/main.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/main.cpp new file mode 100644 index 0000000..63b82cd --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/main.cpp @@ -0,0 +1,448 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../common/common.h" +#include "../common/ctrl_func.h" +#include "../common/render_func.h" +#include "../common/perf_func.h" +#include "physics_func.h" +#include "barrel.h" +#include "landscape.h" + +#ifdef _WIN32 + #include + #include +#endif + +// ARA begin insert new code +#ifdef __ANDROID__ + #include + #include +#endif // __ANDROID__ +// ARA end + +#define SAMPLE_NAME "api_physics_effects/1_simple" + +static bool s_isRunning = true; + +int sceneId = 0; +bool simulating = false; + +int landscapeMeshId; +int convexMeshId; + +void render(void) +{ + render_begin(); + + for(int i=0;i -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_DOWN)) { + angX += 0.05f; + if(angX < -1.4f) angX = -1.4f; + if(angX > -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_LEFT)) { + angY -= 0.05f; + } + + if(ctrl_button_pressed(BTN_RIGHT)) { + angY += 0.05f; + } + + if(ctrl_button_pressed(BTN_ZOOM_OUT)) { + r *= 1.1f; + if(r > 500.0f) r = 500.0f; + } + + if(ctrl_button_pressed(BTN_ZOOM_IN)) { + r *= 0.9f; + if(r < 1.0f) r = 1.0f; + } + + if(ctrl_button_pressed(BTN_SCENE_RESET) == BTN_STAT_DOWN) { + physics_create_scene(sceneId); + } + + if(ctrl_button_pressed(BTN_SCENE_NEXT) == BTN_STAT_DOWN) { + physics_create_scene(++sceneId); + } + + if(ctrl_button_pressed(BTN_SIMULATION) == BTN_STAT_DOWN) { + simulating = !simulating; + } + + if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_DOWN) { + simulating = true; + } + else if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_UP || ctrl_button_pressed(BTN_STEP) == BTN_STAT_KEEP) { + simulating = false; + } + + render_set_view_angle(angX,angY,r); +} + +#ifndef _WIN32 + +// ARA begin insert new code +#ifdef __ANDROID__ + +/////////////////////////////////////////////////////////////////////////////// +// sceneChange +// +/// This function is used to change the physics scene on Android devices +/////////////////////////////////////////////////////////////////////////////// +void sceneChange() +{ + physics_create_scene(sceneId++); +} + +#else // __ANDROID__ +// ARA end + +/////////////////////////////////////////////////////////////////////////////// +// Main + +int main(void) +{ + init(); + + physics_create_scene(sceneId); + + printf("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + while (s_isRunning) { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + + shutdown(); + + printf("## %s: FINISHED ##\n", SAMPLE_NAME); + + return 0; +} + +// ARA begin insert new code +#endif // __ANDROID__ +// ARA end + +#else // _WIN32 + +/////////////////////////////////////////////////////////////////////////////// +// WinMain + +extern HDC hDC; +extern HGLRC hRC; +HWND hWnd; +HINSTANCE hInstance; + +void releaseWindow() +{ + if(hRC) { + wglMakeCurrent(0,0); + wglDeleteContext(hRC); + } + + if(hDC) ReleaseDC(hWnd,hDC); + if(hWnd) DestroyWindow(hWnd); + + UnregisterClass(SAMPLE_NAME,hInstance); +} + +LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + switch(uMsg) { + case WM_SYSCOMMAND: + { + switch (wParam) { + case SC_SCREENSAVE: + case SC_MONITORPOWER: + return 0; + } + break; + } + + case WM_CLOSE: + PostQuitMessage(0); + return 0; + + case WM_SIZE: + render_resize(LOWORD(lParam),HIWORD(lParam)); + return 0; + } + + return DefWindowProc(hWnd,uMsg,wParam,lParam); +} + +bool createWindow(char* title, int width, int height) +{ + WNDCLASS wc; + RECT rect; + rect.left=0; + rect.right=width; + rect.top=0; + rect.bottom=height; + + hInstance = GetModuleHandle(NULL); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = SAMPLE_NAME; + + if(!RegisterClass(&wc)) { + return false; + } + + AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE); + + if(!(hWnd=CreateWindowEx(WS_EX_APPWINDOW|WS_EX_WINDOWEDGE,SAMPLE_NAME,title, + WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS|WS_CLIPCHILDREN, + 0,0,rect.right-rect.left,rect.bottom-rect.top, + NULL,NULL,hInstance,NULL))) { + releaseWindow(); + return false; + } + + static PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + 32, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, + 0, 0, 0, 0, + 32, + 0, + 0, + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + if(!(hDC=GetDC(hWnd))) + { + releaseWindow(); + OutputDebugString(""); + return FALSE; + } + + int pixelformat; + + if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 ){ + OutputDebugString("ChoosePixelFormat Failed...."); + return FALSE; + } + + if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE){ + OutputDebugString("SetPixelFormat Failed...."); + return FALSE; + } + + if (!(hRC=wglCreateContext(hDC))){ + OutputDebugString("Creating HGLRC Failed...."); + return FALSE; + } + + // Set Vsync + //BOOL (WINAPI *wglSwapIntervalEXT)(int) = NULL; + + //if(strstr((char*)glGetString( GL_EXTENSIONS ),"WGL_EXT_swap_control")== 0) { + //} + //else { + //wglSwapIntervalEXT = (BOOL (WINAPI*)(int))wglGetProcAddress("wglSwapIntervalEXT"); + //if(wglSwapIntervalEXT) wglSwapIntervalEXT(1); + //} + + wglMakeCurrent(hDC,hRC); + + ShowWindow(hWnd,SW_SHOW); + SetForegroundWindow(hWnd); + SetFocus(hWnd); + + render_resize(width, height); + + glClearColor(0.0f,0.0f,0.0f,0.0f); + glClearDepth(1.0f); + + return TRUE; +} + +int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) +{ + if(!createWindow(SAMPLE_NAME,DISPLAY_WIDTH,DISPLAY_HEIGHT)) { + MessageBox(NULL,"Can't create gl window.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return 0; + } + + init(); + + physics_create_scene(sceneId); + + SCE_PFX_PRINTF("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + MSG msg; + while(s_isRunning) { + if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + if(msg.message==WM_QUIT) { + s_isRunning = false; + } + else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + } + + shutdown(); + + SCE_PFX_PRINTF("## %s: FINISHED ##\n", SAMPLE_NAME); + + releaseWindow(); + return (msg.wParam); +} + +#endif diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/physics_func.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/physics_func.cpp new file mode 100644 index 0000000..7954c54 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/physics_func.cpp @@ -0,0 +1,857 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "physics_func.h" +#include "../common/perf_func.h" + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Data + +#define NUM_RIGIDBODIES 1000 +#define NUM_JOINTS 500 +#define NUM_CONTACTS 4000 + +const float timeStep = 0.016f; +const float separateBias = 0.1f; +int iteration = 5; + +//J ??????? +//E World size +PfxVector3 worldCenter(0.0f); +PfxVector3 worldExtent(500.0f); + +//J ?? +//E Rigid body +PfxRigidState states[NUM_RIGIDBODIES]; +PfxRigidBody bodies[NUM_RIGIDBODIES]; +PfxCollidable collidables[NUM_RIGIDBODIES]; +PfxSolverBody solverBodies[NUM_RIGIDBODIES]; +int numRigidBodies = 0; + +//J ????????????????? +//E Large mesh for representing a landscape +#include "landscape.h" +PfxLargeTriMesh gLargeMesh; + +//J ????? +//E Convex Mesh +#include "barrel.h" +PfxConvexMesh gConvex; + +//J ???? +//E Proxies +PfxBroadphaseProxy proxies[NUM_RIGIDBODIES]; + +//J ????? +//E Joint +PfxConstraintPair jointPairs[NUM_JOINTS]; +PfxJoint joints[NUM_JOINTS]; +int numJoints = 0; + +//J ?? +//E Pairs +unsigned int numPairs; +PfxBroadphasePair pairs[NUM_CONTACTS]; + +//J ????? +//E Contacts +PfxContactManifold contacts[NUM_CONTACTS]; +int numContacts; + +//J ?????? +//E Temporary buffers +#define POOL_BYTES (5*1024*1024) +unsigned char SCE_PFX_ALIGNED(128) poolBuff[POOL_BYTES]; + +//J ???????????????? +//E Stack allocator for temporary buffers +PfxHeapManager pool(poolBuff,POOL_BYTES); + +// ARA begin insert new code +//E task manager for parallel demo +#define NUM_THREADS 2 +PfxTaskManager *taskManager = NULL; +//E need enough bytes for NUM_THREADS PfxTaskArg objects, with the space rounded up to fill a 16-bit aligned space +#define TASK_MANAGER_POOL_BYTES 1024 +unsigned char SCE_PFX_ALIGNED(16) taskPoolBuff[TASK_MANAGER_POOL_BYTES]; +// ARA end + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Function + +int frame = 0; + +void broadphase() +{ + //J ????????????????? + //E Find the axis along which all rigid bodies are most widely positioned + int axis = 0; + { + PfxVector3 s(0.0f),s2(0.0f); + for(int i=0;i v[0]) axis = 1; + if(v[2] > v[axis]) axis = 2; + } + + //J ??????????????? + //E Create broadpahse proxies + { + for(int i=0;i 0) { + pfxReleaseLargeTriMesh(gLargeMesh); + } + + PfxInt32 ret = pfxCreateLargeTriMesh(gLargeMesh,param); + if(ret != SCE_PFX_OK) { + SCE_PFX_PRINTF("Can't create large mesh.\n"); + } + + int id = numRigidBodies++; + PfxShape shape; + shape.reset(); + shape.setLargeTriMesh(&gLargeMesh); + collidables[id].reset(); + collidables[id].addShape(shape); + collidables[id].finish(); + bodies[id].reset(); + states[id].reset(); + states[id].setPosition(PfxVector3(0.0f,-5.0f,0.0f)); + states[id].setOrientation(PfxQuat::rotationX(0.5f)*PfxQuat::rotationY(0.7f)); + states[id].setMotionType(kPfxMotionTypeFixed); + states[id].setRigidBodyId(id); +} + +void physics_create_scene(int sceneId) +{ + const int numScenes = 4; + int sid = sceneId % numScenes; + + numRigidBodies= 0; + numPairs = 0; + numContacts = 0; + numJoints = 0; + frame = 0; + + switch(sid) { + case 0: // simple primitives + createSceneBoxGround(); + createScenePrimitives(); + break; + + case 1: // joints + createSceneBoxGround(); + createSceneJoints(); + break; + + case 2: // stacking + createSceneBoxGround(); + createSceneStacking(); + break; + + case 3: // landscape + createSceneLandscape(); + createScenePrimitives(); + break; + } + + SCE_PFX_PRINTF("----- Size of rigid body buffer ------\n"); + SCE_PFX_PRINTF(" size * num = total\n"); + SCE_PFX_PRINTF("PfxRigidState %5d * %5d = %5d bytes\n",sizeof(PfxRigidState),numRigidBodies,sizeof(PfxRigidState)*numRigidBodies); + SCE_PFX_PRINTF("PfxRigidBody %5d * %5d = %5d bytes\n",sizeof(PfxRigidBody),numRigidBodies,sizeof(PfxRigidBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxCollidable %5d * %5d = %5d bytes\n",sizeof(PfxCollidable),numRigidBodies,sizeof(PfxCollidable)*numRigidBodies); + SCE_PFX_PRINTF("PfxJoint %5d * %5d = %5d bytes\n",sizeof(PfxJoint),numJoints,sizeof(PfxJoint)*numJoints); + SCE_PFX_PRINTF("PfxSolverBody %5d * %5d = %5d bytes\n",sizeof(PfxSolverBody),numRigidBodies,sizeof(PfxSolverBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxBroadphaseProxy %5d * %5d = %5d bytes\n",sizeof(PfxBroadphaseProxy),numRigidBodies,sizeof(PfxBroadphaseProxy)*numRigidBodies); + SCE_PFX_PRINTF("PfxContactManifold %5d * %5d = %5d bytes\n",sizeof(PfxContactManifold),NUM_CONTACTS,sizeof(PfxContactManifold)*NUM_CONTACTS); + SCE_PFX_PRINTF("PfxBroadphasePair %5d * %5d = %5d bytes\n",sizeof(PfxBroadphasePair),NUM_CONTACTS,sizeof(PfxBroadphasePair)*NUM_CONTACTS); + + int totalBytes = + (sizeof(PfxRigidState) + sizeof(PfxRigidBody) + sizeof(PfxCollidable) + sizeof(PfxSolverBody) + sizeof(PfxBroadphaseProxy)) * numRigidBodies + + (sizeof(PfxContactManifold) + sizeof(PfxBroadphasePair)) * NUM_CONTACTS; + SCE_PFX_PRINTF("----------------------------------------------------------\n"); + SCE_PFX_PRINTF("Total %5d bytes\n",totalBytes); + +// ARA begin insert new code +#ifdef USE_PTHREADS + if (!taskManager) + { + taskManager = PfxCreateTaskManagerPthreads(NUM_THREADS, NUM_THREADS, taskPoolBuff, TASK_MANAGER_POOL_BYTES); + taskManager->initialize(); + } +#endif +// ARA end +} + +/////////////////////////////////////////////////////////////////////////////// +// Initialize / Finalize Engine + +bool physics_init() +{ + return true; +} + +void physics_release() +{ +// ARA begin insert new code + if (taskManager) + taskManager->finalize(); +// ARA end +} + +/////////////////////////////////////////////////////////////////////////////// +// Pick + +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2) +{ + return PfxVector3(0.0f); +} + +void physics_pick_update(const PfxVector3 &p) +{ +} + +void physics_pick_end() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Get Information + +int physics_get_num_rigidbodies() +{ + return numRigidBodies; +} + +const PfxRigidState& physics_get_state(int id) +{ + return states[id]; +} + +const PfxRigidBody& physics_get_body(int id) +{ + return bodies[id]; +} + +const PfxCollidable& physics_get_collidable(int id) +{ + return collidables[id]; +} + +int physics_get_num_contacts() +{ + return numPairs; +} + +const PfxContactManifold &physics_get_contact(int id) +{ + return contacts[pfxGetConstraintId(pairs[id])]; +} + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/physics_func.h b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/physics_func.h new file mode 100644 index 0000000..0a6d2fe --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/1_simple_parallel/physics_func.h @@ -0,0 +1,49 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef __PHYSICS_FUNC_H__ +#define __PHYSICS_FUNC_H__ + +#define SCE_PFX_USE_PERFCOUNTER + +#include "physics_effects.h" + +using namespace sce::PhysicsEffects; + +//E Simulation +//J ???????? +bool physics_init(); +void physics_release(); +void physics_create_scene(int sceneId); +void physics_simulate(); + +//E Picking +//J ????? +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2); +void physics_pick_update(const PfxVector3 &p); +void physics_pick_end(); + +//E Change parameters +//J ???????? +int physics_get_num_rigidbodies(); +const PfxRigidState& physics_get_state(int id); +const PfxRigidBody& physics_get_body(int id); +const PfxCollidable& physics_get_collidable(int id); + +int physics_get_num_contacts(); +const PfxContactManifold &physics_get_contact(int id); + +#endif /* __PHYSICS_FUNC_H__ */ diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/2_stable.winsows.vcproj b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/2_stable.winsows.vcproj new file mode 100644 index 0000000..791d0d6 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/2_stable.winsows.vcproj @@ -0,0 +1,713 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/CMakeLists.txt b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/CMakeLists.txt new file mode 100644 index 0000000..61076de --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 2.4) + + +#this line has to appear before 'PROJECT' in order to be able to disable incremental linking +SET(MSVC_INCREMENTAL_DEFAULT ON) + +PROJECT(App_2_Stable) + + +IF (NOT CMAKE_BUILD_TYPE) +# SET(CMAKE_BUILD_TYPE "Debug") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF (NOT CMAKE_BUILD_TYPE) + + +OPTION(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC Runtime Library DLL (/MD or /MDd)" ON) +OPTION(USE_MSVC_INCREMENTAL_LINKING "Use MSVC Incremental Linking" OFF) + + +IF(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + + +SET(App_2_Stable_SRCS + main.cpp + physics_func.cpp + ../common/ctrl_func.win32.cpp + ../common/perf_func.win32.cpp + ../common/render_func.win32.cpp +) + + +SET(App_2_Stable_HDRS + physics_func.h + landscape.h + barrel.h + ../common/render_func.h + ../common/common.h + ../common/ctrl_func.h + ../common/perf_func.h +) + + +INCLUDE_DIRECTORIES( + ${PHYSICS_EFFECTS_SOURCE_DIR}/include +# ${VECTOR_MATH_INCLUDE} +) + +#LINK_DIRECTORIES( +# +#) + +#ADD_DEFINITIONS(-DUNICODE) +#ADD_DEFINITIONS(-D_UNICODE) + +ADD_EXECUTABLE(App_2_Stable WIN32 + ${App_2_Stable_SRCS} + ${App_2_Stable_HDRS} +) +TARGET_LINK_LIBRARIES(App_2_Stable + PfxBaseLevel + PfxLowLevel + PfxUtil + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} +) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(App_2_Stable PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(App_2_Stable PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(App_2_Stable PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF() + + + + \ No newline at end of file diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/barrel.h b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/barrel.h new file mode 100644 index 0000000..6574fa8 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/barrel.h @@ -0,0 +1,202 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define BarrelVtxCount 57 +#define BarrelIdxCount 180 + +static float BarrelVtx[] = { +0.0f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +-0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +0.0f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +-0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.957307f,-0.289072f,0.0f, +0.404509f,0.0f,-0.293893f, 0.809017f,0.0f,-0.587785f, +0.5f,0.0f,0.0f, 1.0f,0.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.774478f,-0.289072f,-0.562691f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +-0.154509f,0.0f,-0.475528f, -0.309017f,0.0f,-0.951057f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +-0.107853f,-0.5f,-0.331936f, -0.295824f,-0.289072f,-0.910453f, +-0.404509f,0.0f,-0.293893f, -0.809017f,0.0f,-0.587785f, +-0.282362f,-0.5f,-0.205148f, -0.774478f,-0.289072f,-0.562691f, +-0.5f,0.0f,0.0f, -1.0f,0.0f,0.0f, +-0.349018f,-0.5f,0.0f, -0.957307f,-0.289072f,0.0f, +-0.404508f,0.0f,0.293893f, -0.809017f,0.0f,0.587785f, +-0.282362f,-0.5f,0.205148f, -0.774478f,-0.289072f,0.562691f, +-0.154509f,0.0f,0.475528f, -0.309017f,0.0f,0.951056f, +-0.107853f,-0.5f,0.331936f, -0.295824f,-0.289072f,0.910453f, +0.154509f,0.0f,0.475528f, 0.309017f,0.0f,0.951056f, +0.107853f,-0.5f,0.331936f, 0.295824f,-0.289072f,0.910453f, +0.404509f,0.0f,0.293892f, 0.809017f,0.0f,0.587785f, +0.282362f,-0.5f,0.205148f, 0.774478f,-0.289072f,0.562691f, +0.282362f,0.5f,-0.205148f, 0.774478f,0.289072f,-0.562691f, +0.349018f,0.5f,0.0f, 0.957307f,0.289072f,0.0f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.107853f,0.5f,-0.331936f, -0.295824f,0.289072f,-0.910453f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.282362f,0.5f,-0.205148f, -0.774478f,0.289072f,-0.562691f, +-0.349018f,0.5f,0.0f, -0.957307f,0.289072f,0.0f, +-0.282362f,0.5f,0.205148f, -0.774478f,0.289072f,0.562691f, +-0.107853f,0.5f,0.331936f, -0.295824f,0.289072f,0.910453f, +0.107853f,0.5f,0.331936f, 0.295824f,0.289072f,0.910453f, +0.282362f,0.5f,0.205148f, 0.774478f,0.289072f,0.562691f, +}; + +static float BarrelTex[] = { +0.0f,0.5f, +0.0f,0.85f, +0.0f,0.75f, +0.0f,0.95f, +0.0f,0.05f, +0.0f,-0.05f, +0.0f,0.15f, +0.0f,0.25f, +0.0f,0.35f, +0.0f,0.45f, +0.0f,0.55f, +0.0f,0.65f, +1.0f,0.5f, +1.0f,0.75f, +1.0f,0.85f, +1.0f,0.95f, +1.0f,-0.05f, +1.0f,0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +0.0f,0.75f, +0.5f,0.85f, +0.5f,0.75f, +0.0f,0.85f, +0.5f,0.95f, +0.0f,0.95f, +0.0f,-0.05f, +0.5f,0.05f, +0.5f,-0.05f, +0.0f,0.05f, +0.5f,0.15f, +0.0f,0.15f, +0.5f,0.25f, +0.0f,0.25f, +0.5f,0.35f, +0.0f,0.35f, +0.5f,0.45f, +0.0f,0.45f, +0.5f,0.55f, +0.0f,0.55f, +0.5f,0.65f, +0.0f,0.65f, +1.0f,0.85f, +1.0f,0.75f, +1.0f,0.95f, +1.0f,0.05f, +1.0f,-0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +}; + +static unsigned short BarrelIdx[] = { +0,1,2, +0,3,1, +0,4,5, +0,6,4, +0,7,6, +0,8,7, +0,9,8, +0,10,9, +0,11,10, +0,2,11, +12,13,14, +12,14,15, +12,16,17, +12,17,18, +12,18,19, +12,19,20, +12,20,21, +12,21,22, +12,22,23, +12,23,13, +24,25,26, +24,27,25, +27,28,25, +27,29,28, +30,31,32, +30,33,31, +33,34,31, +33,35,34, +35,36,34, +35,37,36, +37,38,36, +37,39,38, +39,40,38, +39,41,40, +41,42,40, +41,43,42, +43,44,42, +43,45,44, +45,26,44, +45,24,26, +26,46,47, +26,25,46, +25,48,46, +25,28,48, +32,49,50, +32,31,49, +31,51,49, +31,34,51, +34,52,51, +34,36,52, +36,53,52, +36,38,53, +38,54,53, +38,40,54, +40,55,54, +40,42,55, +42,56,55, +42,44,56, +44,47,56, +44,26,47, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/landscape.h b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/landscape.h new file mode 100644 index 0000000..00f6cff --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/landscape.h @@ -0,0 +1,318 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define LargeMeshVtxCount 81 +#define LargeMeshIdxCount 384 + +static float LargeMeshVtx[] = { +-25.0f,-2.19407f,18.5625f, 0.232976f,0.967754f,0.0957829f, +-25.0f,0.0644502f,24.75f, 0.188094f,0.871343f,-0.45319f, +-18.75f,-4.50287f,18.5625f, -0.0716098f,0.995449f,0.0628767f, +-18.75f,-0.39999f,24.75f, -0.0602794f,0.895848f,-0.440253f, +-12.5f,-1.2166f,18.5625f, -0.269469f,0.961403f,0.0555879f, +-12.5f,-0.942431f,24.75f, -0.0997841f,0.993258f,0.0589987f, +-6.25f,1.93598f,18.5625f, -0.283933f,0.956351f,-0.0691025f, +-6.25f,-0.445954f,24.75f, -0.180725f,0.942766f,0.280233f, +0.0f,2.76983f,18.5625f, 0.171645f,0.984908f,0.0222501f, +0.0f,2.76642f,24.75f, 0.0784993f,0.995428f,-0.0544117f, +6.25f,-2.53736f,18.5625f, 0.248298f,0.965028f,0.0840741f, +6.25f,-0.915645f,24.75f, 0.164311f,0.945856f,-0.279926f, +12.5f,-1.60054f,18.5625f, -0.180435f,0.983586f,0.00115547f, +12.5f,0.831925f,24.75f, -0.0692495f,0.964821f,-0.253623f, +18.75f,-0.800282f,18.5625f, 0.10755f,0.951538f,0.288112f, +18.75f,-1.47284f,24.75f, 0.232178f,0.972664f,0.00429361f, +25.0f,-2.78379f,18.5625f, 0.1833f,0.937477f,0.295867f, +25.0f,-0.967508f,24.75f, -0.0773477f,0.956641f,-0.280812f, +-25.0f,-0.352038f,12.375f, -0.192222f,0.972435f,0.131987f, +-18.75f,0.681228f,12.375f, -0.107779f,0.962569f,0.248686f, +-12.5f,2.72065f,12.375f, 0.0520846f,0.993034f,0.105692f, +-6.25f,-1.78776f,12.375f, -0.0133223f,0.99674f,-0.0795754f, +0.0f,1.57707f,12.375f, -0.129025f,0.969662f,-0.207627f, +6.25f,0.424356f,12.375f, 0.180995f,0.97074f,0.157815f, +12.5f,0.283234f,12.375f, -0.16285f,0.973539f,0.160316f, +18.75f,2.57015f,12.375f, -0.165454f,0.978339f,0.124408f, +25.0f,3.07363f,12.375f, -0.00454559f,0.988151f,0.153417f, +-25.0f,-0.893751f,6.1875f, -0.0836251f,0.990084f,-0.112876f, +-18.75f,0.930932f,6.1875f, 0.00269413f,0.971838f,-0.235633f, +-12.5f,-0.684529f,6.1875f, -0.010319f,0.927048f,-0.3748f, +-6.25f,-0.661383f,6.1875f, 0.012265f,0.999875f,-0.00994222f, +0.0f,0.385718f,6.1875f, -0.15435f,0.984937f,-0.0779465f, +6.25f,0.589796f,6.1875f, 0.0241717f,0.999582f,-0.0158589f, +12.5f,0.47454f,6.1875f, -0.017184f,0.997953f,-0.0616073f, +18.75f,1.59939f,6.1875f, -0.0902706f,0.957309f,-0.274609f, +25.0f,1.13434f,6.1875f, 0.0346006f,0.957441f,-0.286547f, +-25.0f,0.74548f,0.0f, 0.329903f,0.930812f,0.157334f, +-18.75f,-2.47437f,0.0f, 0.247844f,0.968142f,0.0357041f, +-12.5f,-4.16309f,1.81975e-007f, -0.0623898f,0.997626f,-0.0291436f, +-6.25f,-0.700022f,0.0f, -0.217067f,0.974987f,-0.0477624f, +0.0f,-0.0957388f,0.0f, -0.117693f,0.990712f,-0.068098f, +6.25f,0.614077f,0.0f, -0.0713214f,0.997305f,0.01722f, +12.5f,0.299109f,0.0f, 0.218606f,0.968641f,0.118094f, +18.75f,-1.71753f,0.0f, 0.0339493f,0.985612f,-0.165579f, +25.0f,-1.12638f,0.0f, -0.0547573f,0.989177f,-0.136126f, +-25.0f,-0.403319f,-6.1875f, -0.1263f,0.989211f,-0.074223f, +-18.75f,-0.0730335f,-6.1875f, 0.0173428f,0.965382f,0.260261f, +-12.5f,-0.450125f,-6.1875f, 0.0658811f,0.875f,0.479619f, +-6.25f,-0.180204f,-6.1875f, 0.0116584f,0.981445f,0.19139f, +0.0f,-0.632679f,-6.1875f, -0.0557983f,0.993041f,-0.103716f, +6.25f,0.308409f,-6.1875f, -0.191898f,0.96766f,-0.163737f, +12.5f,2.5011f,-6.1875f, 0.0758397f,0.996403f,-0.0378189f, +18.75f,-1.69303f,-6.1875f, 0.16761f,0.974057f,0.15205f, +25.0f,-0.141349f,-6.1875f, -0.204846f,0.978471f,0.0251341f, +-25.0f,-1.10316f,-12.375f, -0.0350644f,0.993748f,-0.106001f, +-18.75f,1.06711f,-12.375f, -0.309806f,0.919244f,-0.242922f, +-12.5f,3.61544f,-12.375f, -0.0506281f,0.998702f,-0.00561657f, +-6.25f,1.6504f,-12.375f, 0.322294f,0.937465f,0.131477f, +0.0f,-1.60595f,-12.375f, 0.086016f,0.995916f,0.0274459f, +6.25f,-0.849859f,-12.375f, -0.0332811f,0.997087f,0.0686255f, +12.5f,-0.942201f,-12.375f, -0.153559f,0.982185f,-0.108312f, +18.75f,0.494873f,-12.375f, 0.0753195f,0.981472f,0.176181f, +25.0f,-0.333828f,-12.375f, 0.035057f,0.987194f,0.155624f, +-25.0f,2.1862f,-18.5625f, 0.612899f,0.782306f,0.111138f, +-18.75f,-3.38259f,-18.5625f, 0.0194078f,0.992789f,-0.118297f, +-12.5f,-0.880916f,-18.5625f, -0.282251f,0.949875f,-0.13443f, +-6.25f,0.818158f,-18.5625f, 0.1476f,0.981788f,-0.119612f, +0.0f,-1.48019f,-18.5625f, -0.044551f,0.996013f,-0.0772824f, +6.25f,1.47123f,-18.5625f, -0.117036f,0.97986f,0.161792f, +12.5f,0.164076f,-18.5625f, -0.0340355f,0.978993f,0.201034f, +18.75f,2.14568f,-18.5625f, -0.0439269f,0.994859f,0.0912435f, +25.0f,0.626506f,-18.5625f, 0.208015f,0.968592f,0.136229f, +-25.0f,0.296889f,-24.75f, 0.46973f,0.844327f,-0.257809f, +-18.75f,-3.18022f,-24.75f, -0.0226758f,0.998794f,-0.0435401f, +-12.5f,1.8927f,-24.75f, -0.202772f,0.919836f,0.335836f, +-6.25f,1.46387f,-24.75f, 0.224904f,0.955746f,0.189652f, +0.0f,-2.52726f,-24.75f, -0.0435882f,0.993572f,-0.10447f, +6.25f,1.30397f,-24.75f, -0.28646f,0.956525f,-0.0547707f, +12.5f,1.85812f,-24.75f, 0.0521949f,0.979796f,0.193067f, +18.75f,1.56331f,-24.75f, -0.0270784f,0.999629f,-0.00293115f, +25.0f,1.05366f,-24.75f, 0.161f,0.986887f,-0.0115473f, +}; + +static float LargeMeshTex[] = { +0.125f,0.0f, +0.0f,0.0f, +0.125f,0.125f, +0.0f,0.125f, +0.125f,0.25f, +0.0f,0.25f, +0.125f,0.375f, +0.0f,0.375f, +0.125f,0.5f, +0.0f,0.5f, +0.125f,0.625f, +0.0f,0.625f, +0.125f,0.75f, +0.0f,0.75f, +0.125f,0.875f, +0.0f,0.875f, +0.125f,1.0f, +0.0f,1.0f, +0.25f,0.0f, +0.25f,0.125f, +0.25f,0.25f, +0.25f,0.375f, +0.25f,0.5f, +0.25f,0.625f, +0.25f,0.75f, +0.25f,0.875f, +0.25f,1.0f, +0.375f,0.0f, +0.375f,0.125f, +0.375f,0.25f, +0.375f,0.375f, +0.375f,0.5f, +0.375f,0.625f, +0.375f,0.75f, +0.375f,0.875f, +0.375f,1.0f, +0.5f,0.0f, +0.5f,0.125f, +0.5f,0.25f, +0.5f,0.375f, +0.5f,0.5f, +0.5f,0.625f, +0.5f,0.75f, +0.5f,0.875f, +0.5f,1.0f, +0.625f,0.0f, +0.625f,0.125f, +0.625f,0.25f, +0.625f,0.375f, +0.625f,0.5f, +0.625f,0.625f, +0.625f,0.75f, +0.625f,0.875f, +0.625f,1.0f, +0.75f,0.0f, +0.75f,0.125f, +0.75f,0.25f, +0.75f,0.375f, +0.75f,0.5f, +0.75f,0.625f, +0.75f,0.75f, +0.75f,0.875f, +0.75f,1.0f, +0.875f,0.0f, +0.875f,0.125f, +0.875f,0.25f, +0.875f,0.375f, +0.875f,0.5f, +0.875f,0.625f, +0.875f,0.75f, +0.875f,0.875f, +0.875f,1.0f, +1.0f,0.0f, +1.0f,0.125f, +1.0f,0.25f, +1.0f,0.375f, +1.0f,0.5f, +1.0f,0.625f, +1.0f,0.75f, +1.0f,0.875f, +1.0f,1.0f, +}; + +static unsigned short LargeMeshIdx[] = { +0,1,2, +3,2,1, +2,3,4, +5,4,3, +4,5,6, +7,6,5, +6,7,8, +9,8,7, +8,9,10, +11,10,9, +10,11,12, +13,12,11, +12,13,14, +15,14,13, +14,15,16, +17,16,15, +18,0,19, +2,19,0, +19,2,20, +4,20,2, +20,4,21, +6,21,4, +21,6,22, +8,22,6, +22,8,23, +10,23,8, +23,10,24, +12,24,10, +24,12,25, +14,25,12, +25,14,26, +16,26,14, +27,18,28, +19,28,18, +28,19,29, +20,29,19, +29,20,30, +21,30,20, +30,21,31, +22,31,21, +31,22,32, +23,32,22, +32,23,33, +24,33,23, +33,24,34, +25,34,24, +34,25,35, +26,35,25, +36,27,37, +28,37,27, +37,28,38, +29,38,28, +38,29,39, +30,39,29, +39,30,40, +31,40,30, +40,31,41, +32,41,31, +41,32,42, +33,42,32, +42,33,43, +34,43,33, +43,34,44, +35,44,34, +45,36,46, +37,46,36, +46,37,47, +38,47,37, +47,38,48, +39,48,38, +48,39,49, +40,49,39, +49,40,50, +41,50,40, +50,41,51, +42,51,41, +51,42,52, +43,52,42, +52,43,53, +44,53,43, +54,45,55, +46,55,45, +55,46,56, +47,56,46, +56,47,57, +48,57,47, +57,48,58, +49,58,48, +58,49,59, +50,59,49, +59,50,60, +51,60,50, +60,51,61, +52,61,51, +61,52,62, +53,62,52, +63,54,64, +55,64,54, +64,55,65, +56,65,55, +65,56,66, +57,66,56, +66,57,67, +58,67,57, +67,58,68, +59,68,58, +68,59,69, +60,69,59, +69,60,70, +61,70,60, +70,61,71, +62,71,61, +72,63,73, +64,73,63, +73,64,74, +65,74,64, +74,65,75, +66,75,65, +75,66,76, +67,76,66, +76,67,77, +68,77,67, +77,68,78, +69,78,68, +78,69,79, +70,79,69, +79,70,80, +71,80,70, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/main.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/main.cpp new file mode 100644 index 0000000..e005c87 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/main.cpp @@ -0,0 +1,448 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../common/common.h" +#include "../common/ctrl_func.h" +#include "../common/render_func.h" +#include "../common/perf_func.h" +#include "physics_func.h" +#include "barrel.h" +#include "landscape.h" + +#ifdef _WIN32 + #include + #include +#endif + +// ARA begin insert new code +#ifdef __ANDROID__ + #include + #include +#endif +// ARA end + +#define SAMPLE_NAME "api_physics_effects/2_stable" + +static bool s_isRunning = true; + +int sceneId = 2; +bool simulating = false; + +int landscapeMeshId; +int convexMeshId; + +void render(void) +{ + render_begin(); + + for(int i=0;i -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_DOWN)) { + angX += 0.05f; + if(angX < -1.4f) angX = -1.4f; + if(angX > -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_LEFT)) { + angY -= 0.05f; + } + + if(ctrl_button_pressed(BTN_RIGHT)) { + angY += 0.05f; + } + + if(ctrl_button_pressed(BTN_ZOOM_OUT)) { + r *= 1.1f; + if(r > 500.0f) r = 500.0f; + } + + if(ctrl_button_pressed(BTN_ZOOM_IN)) { + r *= 0.9f; + if(r < 1.0f) r = 1.0f; + } + + if(ctrl_button_pressed(BTN_SCENE_RESET) == BTN_STAT_DOWN) { + physics_create_scene(sceneId); + } + + if(ctrl_button_pressed(BTN_SCENE_NEXT) == BTN_STAT_DOWN) { + physics_create_scene(++sceneId); + } + + if(ctrl_button_pressed(BTN_SIMULATION) == BTN_STAT_DOWN) { + simulating = !simulating; + } + + if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_DOWN) { + simulating = true; + } + else if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_UP || ctrl_button_pressed(BTN_STEP) == BTN_STAT_KEEP) { + simulating = false; + } + + render_set_view_angle(angX,angY,r); +} + +#ifndef _WIN32 + +// ARA begin insert new code +#ifdef __ANDROID__ + +/////////////////////////////////////////////////////////////////////////////// +// sceneChange +// +/// This function is used to change the physics scene on Android devices +/////////////////////////////////////////////////////////////////////////////// +void sceneChange() +{ + physics_create_scene(sceneId++); +} + +#else // __ANDROID__ +// ARA end + +/////////////////////////////////////////////////////////////////////////////// +// Main + +int main(void) +{ + init(); + + physics_create_scene(sceneId); + + printf("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + while (s_isRunning) { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + + shutdown(); + + printf("## %s: FINISHED ##\n", SAMPLE_NAME); + + return 0; +} + +// ARA begin insert new code +#endif // __ANDROID__ +// ARA end + +#else // _WIN32 + +/////////////////////////////////////////////////////////////////////////////// +// WinMain + +extern HDC hDC; +extern HGLRC hRC; +HWND hWnd; +HINSTANCE hInstance; + +void releaseWindow() +{ + if(hRC) { + wglMakeCurrent(0,0); + wglDeleteContext(hRC); + } + + if(hDC) ReleaseDC(hWnd,hDC); + if(hWnd) DestroyWindow(hWnd); + + UnregisterClass(SAMPLE_NAME,hInstance); +} + +LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + switch(uMsg) { + case WM_SYSCOMMAND: + { + switch (wParam) { + case SC_SCREENSAVE: + case SC_MONITORPOWER: + return 0; + } + break; + } + + case WM_CLOSE: + PostQuitMessage(0); + return 0; + + case WM_SIZE: + render_resize(LOWORD(lParam),HIWORD(lParam)); + return 0; + } + + return DefWindowProc(hWnd,uMsg,wParam,lParam); +} + +bool createWindow(char* title, int width, int height) +{ + WNDCLASS wc; + RECT rect; + rect.left=0; + rect.right=width; + rect.top=0; + rect.bottom=height; + + hInstance = GetModuleHandle(NULL); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = SAMPLE_NAME; + + if(!RegisterClass(&wc)) { + return false; + } + + AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE); + + if(!(hWnd=CreateWindowEx(WS_EX_APPWINDOW|WS_EX_WINDOWEDGE,SAMPLE_NAME,title, + WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS|WS_CLIPCHILDREN, + 0,0,rect.right-rect.left,rect.bottom-rect.top, + NULL,NULL,hInstance,NULL))) { + releaseWindow(); + return false; + } + + static PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + 32, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, + 0, 0, 0, 0, + 32, + 0, + 0, + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + if(!(hDC=GetDC(hWnd))) + { + releaseWindow(); + OutputDebugString(""); + return FALSE; + } + + int pixelformat; + + if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 ){ + OutputDebugString("ChoosePixelFormat Failed...."); + return FALSE; + } + + if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE){ + OutputDebugString("SetPixelFormat Failed...."); + return FALSE; + } + + if (!(hRC=wglCreateContext(hDC))){ + OutputDebugString("Creating HGLRC Failed...."); + return FALSE; + } + + // Set Vsync + //BOOL (WINAPI *wglSwapIntervalEXT)(int) = NULL; + + //if(strstr((char*)glGetString( GL_EXTENSIONS ),"WGL_EXT_swap_control")== 0) { + //} + //else { + //wglSwapIntervalEXT = (BOOL (WINAPI*)(int))wglGetProcAddress("wglSwapIntervalEXT"); + //if(wglSwapIntervalEXT) wglSwapIntervalEXT(1); + //} + + wglMakeCurrent(hDC,hRC); + + ShowWindow(hWnd,SW_SHOW); + SetForegroundWindow(hWnd); + SetFocus(hWnd); + + render_resize(width, height); + + glClearColor(0.0f,0.0f,0.0f,0.0f); + glClearDepth(1.0f); + + return TRUE; +} + +int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) +{ + if(!createWindow(SAMPLE_NAME,DISPLAY_WIDTH,DISPLAY_HEIGHT)) { + MessageBox(NULL,"Can't create gl window.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return 0; + } + + init(); + + physics_create_scene(sceneId); + + SCE_PFX_PRINTF("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + MSG msg; + while(s_isRunning) { + if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + if(msg.message==WM_QUIT) { + s_isRunning = false; + } + else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + } + + shutdown(); + + SCE_PFX_PRINTF("## %s: FINISHED ##\n", SAMPLE_NAME); + + releaseWindow(); + return (msg.wParam); +} + +#endif diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/physics.png b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/physics.png new file mode 100644 index 0000000000000000000000000000000000000000..483e6e806026e2cadc4f342dcc11f1d03cdc4599 GIT binary patch literal 34719 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 FV1nTr2@?PS literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/physics_func.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/physics_func.cpp new file mode 100644 index 0000000..7ed69e9 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/physics_func.cpp @@ -0,0 +1,869 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "physics_func.h" +#include "../common/perf_func.h" + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Data + +#define NUM_RIGIDBODIES 5000 +#define NUM_JOINTS 5000 +#define NUM_CONTACTS 4000 + +const float timeStep = 0.016f; +const float separateBias = 0.1f; +int iteration = 5; + +//J ワールドサイズ +//E World size +PfxVector3 worldCenter(0.0f); +PfxVector3 worldExtent(500.0f); + +//J 剛体 +//E Rigid body +PfxRigidState states[NUM_RIGIDBODIES]; +PfxRigidBody bodies[NUM_RIGIDBODIES]; +PfxCollidable collidables[NUM_RIGIDBODIES]; +PfxSolverBody solverBodies[NUM_RIGIDBODIES]; +int numRigidBodies = 0; + +//J 地形を表現するためのラージメッシュ +//E Large mesh for representing a landscape +#include "landscape.h" +PfxLargeTriMesh gLargeMesh; + +//J 凸メッシュ +//E Convex Mesh +#include "barrel.h" +PfxConvexMesh gConvex; + +//J プロキシ +//E Proxies +PfxBroadphaseProxy proxies[NUM_RIGIDBODIES]; + +//J ジョイント +//E Joint +PfxConstraintPair jointPairs[NUM_JOINTS]; +PfxJoint joints[NUM_JOINTS]; +int numJoints = 0; + +//J ペア +//E Pairs +unsigned int pairSwap; +unsigned int numPairs[2]; +PfxBroadphasePair pairsBuff[2][NUM_CONTACTS]; + +//J コンタクト +//E Contacts +PfxContactManifold contacts[NUM_CONTACTS]; +int numContacts; + +PfxUInt32 contactIdPool[NUM_CONTACTS]; +int numContactIdPool; + +//J 一時バッファ +//E Temporary buffers +#define POOL_BYTES (5*1024*1024) +unsigned char SCE_PFX_ALIGNED(128) poolBuff[POOL_BYTES]; + +//J 一時バッファ用スタックアロケータ +//E Stack allocator for temporary buffers +PfxHeapManager pool(poolBuff,POOL_BYTES); + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Function + +int frame = 0; + +void broadphase() +{ + pairSwap = 1-pairSwap; + + unsigned int &numPreviousPairs = numPairs[1-pairSwap]; + unsigned int &numCurrentPairs = numPairs[pairSwap]; + PfxBroadphasePair *previousPairs = pairsBuff[1-pairSwap]; + PfxBroadphasePair *currentPairs = pairsBuff[pairSwap]; + + //J 剛体が最も分散している軸を見つける + //E Find the axis along which all rigid bodies are most widely positioned + int axis = 0; + { + PfxVector3 s(0.0f),s2(0.0f); + for(int i=0;i v[0]) axis = 1; + if(v[2] > v[axis]) axis = 2; + } + + //J ブロードフェーズプロキシの更新 + //E Create broadpahse proxies + { + for(int i=0;i 0) { + cId = contactIdPool[--numContactIdPool]; + } + else { + cId = numContacts++; + } + if(cId >= NUM_CONTACTS) { + cId = 0; + } + SCE_PFX_ASSERT(cId < NUM_CONTACTS); + pfxSetContactId(outNewPairs[i],cId); + PfxContactManifold &contact = contacts[cId]; + contact.reset(pfxGetObjectIdA(outNewPairs[i]),pfxGetObjectIdB(outNewPairs[i])); + } + + //J 新規ペアと維持ペアを合成 + //E Merge 'new' and 'keep' pairs + numCurrentPairs = 0; + for(PfxUInt32 i=0;i 0) { + pfxReleaseLargeTriMesh(gLargeMesh); + } + + PfxInt32 ret = pfxCreateLargeTriMesh(gLargeMesh,param); + if(ret != SCE_PFX_OK) { + SCE_PFX_PRINTF("Can't create large mesh.\n"); + } + + int id = numRigidBodies++; + PfxShape shape; + shape.reset(); + shape.setLargeTriMesh(&gLargeMesh); + collidables[id].reset(); + collidables[id].addShape(shape); + collidables[id].finish(); + bodies[id].reset(); + states[id].reset(); + states[id].setPosition(PfxVector3(0.0f,-5.0f,0.0f)); + states[id].setOrientation(PfxQuat::rotationX(0.5f)*PfxQuat::rotationY(0.7f)); + states[id].setMotionType(kPfxMotionTypeFixed); + states[id].setRigidBodyId(id); +} + +void physics_create_scene(int sceneId) +{ + const int numScenes = 4; + int sid = sceneId % numScenes; + + numRigidBodies= 0; + pairSwap = 0; + numPairs[0] = 0; + numPairs[1] = 0; + numContacts = 0; + numContactIdPool = 0; + numJoints = 0; + frame = 0; + + switch(sid) { + case 0: // simple primitives + createSceneBoxGround(); + createScenePrimitives(); + break; + + case 1: // joints + createSceneBoxGround(); + createSceneJoints(); + break; + + case 2: // stacking + createSceneBoxGround(); + createSceneStacking(); + break; + + case 3: // landscape + createSceneLandscape(); + createScenePrimitives(); + break; + } + + SCE_PFX_PRINTF("----- Size of rigid body buffer ------\n"); + SCE_PFX_PRINTF(" size * num = total\n"); + SCE_PFX_PRINTF("PfxRigidState %5d * %5d = %5d bytes\n",sizeof(PfxRigidState),numRigidBodies,sizeof(PfxRigidState)*numRigidBodies); + SCE_PFX_PRINTF("PfxRigidBody %5d * %5d = %5d bytes\n",sizeof(PfxRigidBody),numRigidBodies,sizeof(PfxRigidBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxCollidable %5d * %5d = %5d bytes\n",sizeof(PfxCollidable),numRigidBodies,sizeof(PfxCollidable)*numRigidBodies); + SCE_PFX_PRINTF("PfxJoint %5d * %5d = %5d bytes\n",sizeof(PfxJoint),numJoints,sizeof(PfxJoint)*numJoints); + SCE_PFX_PRINTF("PfxSolverBody %5d * %5d = %5d bytes\n",sizeof(PfxSolverBody),numRigidBodies,sizeof(PfxSolverBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxBroadphaseProxy %5d * %5d = %5d bytes\n",sizeof(PfxBroadphaseProxy),numRigidBodies,sizeof(PfxBroadphaseProxy)*numRigidBodies); + SCE_PFX_PRINTF("PfxContactManifold %5d * %5d = %5d bytes\n",sizeof(PfxContactManifold),NUM_CONTACTS,sizeof(PfxContactManifold)*NUM_CONTACTS); + SCE_PFX_PRINTF("PfxBroadphasePair %5d * %5d = %5d bytes\n",sizeof(PfxBroadphasePair),NUM_CONTACTS,sizeof(PfxBroadphasePair)*NUM_CONTACTS); + + int totalBytes = + (sizeof(PfxRigidState) + sizeof(PfxRigidBody) + sizeof(PfxCollidable) + sizeof(PfxSolverBody) + sizeof(PfxBroadphaseProxy)) * numRigidBodies + + (sizeof(PfxContactManifold) + sizeof(PfxBroadphasePair)) * NUM_CONTACTS; + SCE_PFX_PRINTF("----------------------------------------------------------\n"); + SCE_PFX_PRINTF("Total %5d bytes\n",totalBytes); +} + +/////////////////////////////////////////////////////////////////////////////// +// Initialize / Finalize Engine + +bool physics_init() +{ + return true; +} + +void physics_release() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Pick + +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2) +{ + return PfxVector3(0.0f); +} + +void physics_pick_update(const PfxVector3 &p) +{ +} + +void physics_pick_end() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Get Information + +int physics_get_num_rigidbodies() +{ + return numRigidBodies; +} + +const PfxRigidState& physics_get_state(int id) +{ + return states[id]; +} + +const PfxRigidBody& physics_get_body(int id) +{ + return bodies[id]; +} + +const PfxCollidable& physics_get_collidable(int id) +{ + return collidables[id]; +} + +int physics_get_num_contacts() +{ + return numPairs[pairSwap]; +} + +const PfxContactManifold &physics_get_contact(int id) +{ + return contacts[pfxGetConstraintId(pairsBuff[pairSwap][id])]; +} diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/physics_func.h b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/physics_func.h new file mode 100644 index 0000000..0aa7e07 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/physics_func.h @@ -0,0 +1,49 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef __PHYSICS_FUNC_H__ +#define __PHYSICS_FUNC_H__ + +#define SCE_PFX_USE_PERFCOUNTER + +#include "physics_effects.h" + +using namespace sce::PhysicsEffects; + +//E Simulation +//J シミュレーション +bool physics_init(); +void physics_release(); +void physics_create_scene(int sceneId); +void physics_simulate(); + +//E Picking +//J ピッキング +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2); +void physics_pick_update(const PfxVector3 &p); +void physics_pick_end(); + +//E Change parameters +//J パラメータの取得 +int physics_get_num_rigidbodies(); +const PfxRigidState& physics_get_state(int id); +const PfxRigidBody& physics_get_body(int id); +const PfxCollidable& physics_get_collidable(int id); + +int physics_get_num_contacts(); +const PfxContactManifold &physics_get_contact(int id); + +#endif /* __PHYSICS_FUNC_H__ */ diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/premake4.lua b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/premake4.lua new file mode 100644 index 0000000..ab36703 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable/premake4.lua @@ -0,0 +1,22 @@ + project "2_stable" + + kind "WindowedApp" + targetdir "../../../bin" + includedirs {"../../../include"} + + links { + "physicseffects2_lowlevel", + "physicseffects2_baselevel", + "physicseffects2_util", + "opengl32" + } + + flags {"WinMain"} + + files { + "main.cpp", + "physics_func.cpp", + "../common/ctrl_func.win32.cpp", + "../common/perf_func.win32.cpp", + "../common/render_func.win32.cpp" + } \ No newline at end of file diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/barrel.h b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/barrel.h new file mode 100644 index 0000000..6574fa8 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/barrel.h @@ -0,0 +1,202 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define BarrelVtxCount 57 +#define BarrelIdxCount 180 + +static float BarrelVtx[] = { +0.0f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +-0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +0.0f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +-0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.957307f,-0.289072f,0.0f, +0.404509f,0.0f,-0.293893f, 0.809017f,0.0f,-0.587785f, +0.5f,0.0f,0.0f, 1.0f,0.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.774478f,-0.289072f,-0.562691f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +-0.154509f,0.0f,-0.475528f, -0.309017f,0.0f,-0.951057f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +-0.107853f,-0.5f,-0.331936f, -0.295824f,-0.289072f,-0.910453f, +-0.404509f,0.0f,-0.293893f, -0.809017f,0.0f,-0.587785f, +-0.282362f,-0.5f,-0.205148f, -0.774478f,-0.289072f,-0.562691f, +-0.5f,0.0f,0.0f, -1.0f,0.0f,0.0f, +-0.349018f,-0.5f,0.0f, -0.957307f,-0.289072f,0.0f, +-0.404508f,0.0f,0.293893f, -0.809017f,0.0f,0.587785f, +-0.282362f,-0.5f,0.205148f, -0.774478f,-0.289072f,0.562691f, +-0.154509f,0.0f,0.475528f, -0.309017f,0.0f,0.951056f, +-0.107853f,-0.5f,0.331936f, -0.295824f,-0.289072f,0.910453f, +0.154509f,0.0f,0.475528f, 0.309017f,0.0f,0.951056f, +0.107853f,-0.5f,0.331936f, 0.295824f,-0.289072f,0.910453f, +0.404509f,0.0f,0.293892f, 0.809017f,0.0f,0.587785f, +0.282362f,-0.5f,0.205148f, 0.774478f,-0.289072f,0.562691f, +0.282362f,0.5f,-0.205148f, 0.774478f,0.289072f,-0.562691f, +0.349018f,0.5f,0.0f, 0.957307f,0.289072f,0.0f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.107853f,0.5f,-0.331936f, -0.295824f,0.289072f,-0.910453f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.282362f,0.5f,-0.205148f, -0.774478f,0.289072f,-0.562691f, +-0.349018f,0.5f,0.0f, -0.957307f,0.289072f,0.0f, +-0.282362f,0.5f,0.205148f, -0.774478f,0.289072f,0.562691f, +-0.107853f,0.5f,0.331936f, -0.295824f,0.289072f,0.910453f, +0.107853f,0.5f,0.331936f, 0.295824f,0.289072f,0.910453f, +0.282362f,0.5f,0.205148f, 0.774478f,0.289072f,0.562691f, +}; + +static float BarrelTex[] = { +0.0f,0.5f, +0.0f,0.85f, +0.0f,0.75f, +0.0f,0.95f, +0.0f,0.05f, +0.0f,-0.05f, +0.0f,0.15f, +0.0f,0.25f, +0.0f,0.35f, +0.0f,0.45f, +0.0f,0.55f, +0.0f,0.65f, +1.0f,0.5f, +1.0f,0.75f, +1.0f,0.85f, +1.0f,0.95f, +1.0f,-0.05f, +1.0f,0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +0.0f,0.75f, +0.5f,0.85f, +0.5f,0.75f, +0.0f,0.85f, +0.5f,0.95f, +0.0f,0.95f, +0.0f,-0.05f, +0.5f,0.05f, +0.5f,-0.05f, +0.0f,0.05f, +0.5f,0.15f, +0.0f,0.15f, +0.5f,0.25f, +0.0f,0.25f, +0.5f,0.35f, +0.0f,0.35f, +0.5f,0.45f, +0.0f,0.45f, +0.5f,0.55f, +0.0f,0.55f, +0.5f,0.65f, +0.0f,0.65f, +1.0f,0.85f, +1.0f,0.75f, +1.0f,0.95f, +1.0f,0.05f, +1.0f,-0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +}; + +static unsigned short BarrelIdx[] = { +0,1,2, +0,3,1, +0,4,5, +0,6,4, +0,7,6, +0,8,7, +0,9,8, +0,10,9, +0,11,10, +0,2,11, +12,13,14, +12,14,15, +12,16,17, +12,17,18, +12,18,19, +12,19,20, +12,20,21, +12,21,22, +12,22,23, +12,23,13, +24,25,26, +24,27,25, +27,28,25, +27,29,28, +30,31,32, +30,33,31, +33,34,31, +33,35,34, +35,36,34, +35,37,36, +37,38,36, +37,39,38, +39,40,38, +39,41,40, +41,42,40, +41,43,42, +43,44,42, +43,45,44, +45,26,44, +45,24,26, +26,46,47, +26,25,46, +25,48,46, +25,28,48, +32,49,50, +32,31,49, +31,51,49, +31,34,51, +34,52,51, +34,36,52, +36,53,52, +36,38,53, +38,54,53, +38,40,54, +40,55,54, +40,42,55, +42,56,55, +42,44,56, +44,47,56, +44,26,47, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/landscape.h b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/landscape.h new file mode 100644 index 0000000..00f6cff --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/landscape.h @@ -0,0 +1,318 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define LargeMeshVtxCount 81 +#define LargeMeshIdxCount 384 + +static float LargeMeshVtx[] = { +-25.0f,-2.19407f,18.5625f, 0.232976f,0.967754f,0.0957829f, +-25.0f,0.0644502f,24.75f, 0.188094f,0.871343f,-0.45319f, +-18.75f,-4.50287f,18.5625f, -0.0716098f,0.995449f,0.0628767f, +-18.75f,-0.39999f,24.75f, -0.0602794f,0.895848f,-0.440253f, +-12.5f,-1.2166f,18.5625f, -0.269469f,0.961403f,0.0555879f, +-12.5f,-0.942431f,24.75f, -0.0997841f,0.993258f,0.0589987f, +-6.25f,1.93598f,18.5625f, -0.283933f,0.956351f,-0.0691025f, +-6.25f,-0.445954f,24.75f, -0.180725f,0.942766f,0.280233f, +0.0f,2.76983f,18.5625f, 0.171645f,0.984908f,0.0222501f, +0.0f,2.76642f,24.75f, 0.0784993f,0.995428f,-0.0544117f, +6.25f,-2.53736f,18.5625f, 0.248298f,0.965028f,0.0840741f, +6.25f,-0.915645f,24.75f, 0.164311f,0.945856f,-0.279926f, +12.5f,-1.60054f,18.5625f, -0.180435f,0.983586f,0.00115547f, +12.5f,0.831925f,24.75f, -0.0692495f,0.964821f,-0.253623f, +18.75f,-0.800282f,18.5625f, 0.10755f,0.951538f,0.288112f, +18.75f,-1.47284f,24.75f, 0.232178f,0.972664f,0.00429361f, +25.0f,-2.78379f,18.5625f, 0.1833f,0.937477f,0.295867f, +25.0f,-0.967508f,24.75f, -0.0773477f,0.956641f,-0.280812f, +-25.0f,-0.352038f,12.375f, -0.192222f,0.972435f,0.131987f, +-18.75f,0.681228f,12.375f, -0.107779f,0.962569f,0.248686f, +-12.5f,2.72065f,12.375f, 0.0520846f,0.993034f,0.105692f, +-6.25f,-1.78776f,12.375f, -0.0133223f,0.99674f,-0.0795754f, +0.0f,1.57707f,12.375f, -0.129025f,0.969662f,-0.207627f, +6.25f,0.424356f,12.375f, 0.180995f,0.97074f,0.157815f, +12.5f,0.283234f,12.375f, -0.16285f,0.973539f,0.160316f, +18.75f,2.57015f,12.375f, -0.165454f,0.978339f,0.124408f, +25.0f,3.07363f,12.375f, -0.00454559f,0.988151f,0.153417f, +-25.0f,-0.893751f,6.1875f, -0.0836251f,0.990084f,-0.112876f, +-18.75f,0.930932f,6.1875f, 0.00269413f,0.971838f,-0.235633f, +-12.5f,-0.684529f,6.1875f, -0.010319f,0.927048f,-0.3748f, +-6.25f,-0.661383f,6.1875f, 0.012265f,0.999875f,-0.00994222f, +0.0f,0.385718f,6.1875f, -0.15435f,0.984937f,-0.0779465f, +6.25f,0.589796f,6.1875f, 0.0241717f,0.999582f,-0.0158589f, +12.5f,0.47454f,6.1875f, -0.017184f,0.997953f,-0.0616073f, +18.75f,1.59939f,6.1875f, -0.0902706f,0.957309f,-0.274609f, +25.0f,1.13434f,6.1875f, 0.0346006f,0.957441f,-0.286547f, +-25.0f,0.74548f,0.0f, 0.329903f,0.930812f,0.157334f, +-18.75f,-2.47437f,0.0f, 0.247844f,0.968142f,0.0357041f, +-12.5f,-4.16309f,1.81975e-007f, -0.0623898f,0.997626f,-0.0291436f, +-6.25f,-0.700022f,0.0f, -0.217067f,0.974987f,-0.0477624f, +0.0f,-0.0957388f,0.0f, -0.117693f,0.990712f,-0.068098f, +6.25f,0.614077f,0.0f, -0.0713214f,0.997305f,0.01722f, +12.5f,0.299109f,0.0f, 0.218606f,0.968641f,0.118094f, +18.75f,-1.71753f,0.0f, 0.0339493f,0.985612f,-0.165579f, +25.0f,-1.12638f,0.0f, -0.0547573f,0.989177f,-0.136126f, +-25.0f,-0.403319f,-6.1875f, -0.1263f,0.989211f,-0.074223f, +-18.75f,-0.0730335f,-6.1875f, 0.0173428f,0.965382f,0.260261f, +-12.5f,-0.450125f,-6.1875f, 0.0658811f,0.875f,0.479619f, +-6.25f,-0.180204f,-6.1875f, 0.0116584f,0.981445f,0.19139f, +0.0f,-0.632679f,-6.1875f, -0.0557983f,0.993041f,-0.103716f, +6.25f,0.308409f,-6.1875f, -0.191898f,0.96766f,-0.163737f, +12.5f,2.5011f,-6.1875f, 0.0758397f,0.996403f,-0.0378189f, +18.75f,-1.69303f,-6.1875f, 0.16761f,0.974057f,0.15205f, +25.0f,-0.141349f,-6.1875f, -0.204846f,0.978471f,0.0251341f, +-25.0f,-1.10316f,-12.375f, -0.0350644f,0.993748f,-0.106001f, +-18.75f,1.06711f,-12.375f, -0.309806f,0.919244f,-0.242922f, +-12.5f,3.61544f,-12.375f, -0.0506281f,0.998702f,-0.00561657f, +-6.25f,1.6504f,-12.375f, 0.322294f,0.937465f,0.131477f, +0.0f,-1.60595f,-12.375f, 0.086016f,0.995916f,0.0274459f, +6.25f,-0.849859f,-12.375f, -0.0332811f,0.997087f,0.0686255f, +12.5f,-0.942201f,-12.375f, -0.153559f,0.982185f,-0.108312f, +18.75f,0.494873f,-12.375f, 0.0753195f,0.981472f,0.176181f, +25.0f,-0.333828f,-12.375f, 0.035057f,0.987194f,0.155624f, +-25.0f,2.1862f,-18.5625f, 0.612899f,0.782306f,0.111138f, +-18.75f,-3.38259f,-18.5625f, 0.0194078f,0.992789f,-0.118297f, +-12.5f,-0.880916f,-18.5625f, -0.282251f,0.949875f,-0.13443f, +-6.25f,0.818158f,-18.5625f, 0.1476f,0.981788f,-0.119612f, +0.0f,-1.48019f,-18.5625f, -0.044551f,0.996013f,-0.0772824f, +6.25f,1.47123f,-18.5625f, -0.117036f,0.97986f,0.161792f, +12.5f,0.164076f,-18.5625f, -0.0340355f,0.978993f,0.201034f, +18.75f,2.14568f,-18.5625f, -0.0439269f,0.994859f,0.0912435f, +25.0f,0.626506f,-18.5625f, 0.208015f,0.968592f,0.136229f, +-25.0f,0.296889f,-24.75f, 0.46973f,0.844327f,-0.257809f, +-18.75f,-3.18022f,-24.75f, -0.0226758f,0.998794f,-0.0435401f, +-12.5f,1.8927f,-24.75f, -0.202772f,0.919836f,0.335836f, +-6.25f,1.46387f,-24.75f, 0.224904f,0.955746f,0.189652f, +0.0f,-2.52726f,-24.75f, -0.0435882f,0.993572f,-0.10447f, +6.25f,1.30397f,-24.75f, -0.28646f,0.956525f,-0.0547707f, +12.5f,1.85812f,-24.75f, 0.0521949f,0.979796f,0.193067f, +18.75f,1.56331f,-24.75f, -0.0270784f,0.999629f,-0.00293115f, +25.0f,1.05366f,-24.75f, 0.161f,0.986887f,-0.0115473f, +}; + +static float LargeMeshTex[] = { +0.125f,0.0f, +0.0f,0.0f, +0.125f,0.125f, +0.0f,0.125f, +0.125f,0.25f, +0.0f,0.25f, +0.125f,0.375f, +0.0f,0.375f, +0.125f,0.5f, +0.0f,0.5f, +0.125f,0.625f, +0.0f,0.625f, +0.125f,0.75f, +0.0f,0.75f, +0.125f,0.875f, +0.0f,0.875f, +0.125f,1.0f, +0.0f,1.0f, +0.25f,0.0f, +0.25f,0.125f, +0.25f,0.25f, +0.25f,0.375f, +0.25f,0.5f, +0.25f,0.625f, +0.25f,0.75f, +0.25f,0.875f, +0.25f,1.0f, +0.375f,0.0f, +0.375f,0.125f, +0.375f,0.25f, +0.375f,0.375f, +0.375f,0.5f, +0.375f,0.625f, +0.375f,0.75f, +0.375f,0.875f, +0.375f,1.0f, +0.5f,0.0f, +0.5f,0.125f, +0.5f,0.25f, +0.5f,0.375f, +0.5f,0.5f, +0.5f,0.625f, +0.5f,0.75f, +0.5f,0.875f, +0.5f,1.0f, +0.625f,0.0f, +0.625f,0.125f, +0.625f,0.25f, +0.625f,0.375f, +0.625f,0.5f, +0.625f,0.625f, +0.625f,0.75f, +0.625f,0.875f, +0.625f,1.0f, +0.75f,0.0f, +0.75f,0.125f, +0.75f,0.25f, +0.75f,0.375f, +0.75f,0.5f, +0.75f,0.625f, +0.75f,0.75f, +0.75f,0.875f, +0.75f,1.0f, +0.875f,0.0f, +0.875f,0.125f, +0.875f,0.25f, +0.875f,0.375f, +0.875f,0.5f, +0.875f,0.625f, +0.875f,0.75f, +0.875f,0.875f, +0.875f,1.0f, +1.0f,0.0f, +1.0f,0.125f, +1.0f,0.25f, +1.0f,0.375f, +1.0f,0.5f, +1.0f,0.625f, +1.0f,0.75f, +1.0f,0.875f, +1.0f,1.0f, +}; + +static unsigned short LargeMeshIdx[] = { +0,1,2, +3,2,1, +2,3,4, +5,4,3, +4,5,6, +7,6,5, +6,7,8, +9,8,7, +8,9,10, +11,10,9, +10,11,12, +13,12,11, +12,13,14, +15,14,13, +14,15,16, +17,16,15, +18,0,19, +2,19,0, +19,2,20, +4,20,2, +20,4,21, +6,21,4, +21,6,22, +8,22,6, +22,8,23, +10,23,8, +23,10,24, +12,24,10, +24,12,25, +14,25,12, +25,14,26, +16,26,14, +27,18,28, +19,28,18, +28,19,29, +20,29,19, +29,20,30, +21,30,20, +30,21,31, +22,31,21, +31,22,32, +23,32,22, +32,23,33, +24,33,23, +33,24,34, +25,34,24, +34,25,35, +26,35,25, +36,27,37, +28,37,27, +37,28,38, +29,38,28, +38,29,39, +30,39,29, +39,30,40, +31,40,30, +40,31,41, +32,41,31, +41,32,42, +33,42,32, +42,33,43, +34,43,33, +43,34,44, +35,44,34, +45,36,46, +37,46,36, +46,37,47, +38,47,37, +47,38,48, +39,48,38, +48,39,49, +40,49,39, +49,40,50, +41,50,40, +50,41,51, +42,51,41, +51,42,52, +43,52,42, +52,43,53, +44,53,43, +54,45,55, +46,55,45, +55,46,56, +47,56,46, +56,47,57, +48,57,47, +57,48,58, +49,58,48, +58,49,59, +50,59,49, +59,50,60, +51,60,50, +60,51,61, +52,61,51, +61,52,62, +53,62,52, +63,54,64, +55,64,54, +64,55,65, +56,65,55, +65,56,66, +57,66,56, +66,57,67, +58,67,57, +67,58,68, +59,68,58, +68,59,69, +60,69,59, +69,60,70, +61,70,60, +70,61,71, +62,71,61, +72,63,73, +64,73,63, +73,64,74, +65,74,64, +74,65,75, +66,75,65, +75,66,76, +67,76,66, +76,67,77, +68,77,67, +77,68,78, +69,78,68, +78,69,79, +70,79,69, +79,70,80, +71,80,70, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/main.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/main.cpp new file mode 100644 index 0000000..e005c87 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/main.cpp @@ -0,0 +1,448 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../common/common.h" +#include "../common/ctrl_func.h" +#include "../common/render_func.h" +#include "../common/perf_func.h" +#include "physics_func.h" +#include "barrel.h" +#include "landscape.h" + +#ifdef _WIN32 + #include + #include +#endif + +// ARA begin insert new code +#ifdef __ANDROID__ + #include + #include +#endif +// ARA end + +#define SAMPLE_NAME "api_physics_effects/2_stable" + +static bool s_isRunning = true; + +int sceneId = 2; +bool simulating = false; + +int landscapeMeshId; +int convexMeshId; + +void render(void) +{ + render_begin(); + + for(int i=0;i -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_DOWN)) { + angX += 0.05f; + if(angX < -1.4f) angX = -1.4f; + if(angX > -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_LEFT)) { + angY -= 0.05f; + } + + if(ctrl_button_pressed(BTN_RIGHT)) { + angY += 0.05f; + } + + if(ctrl_button_pressed(BTN_ZOOM_OUT)) { + r *= 1.1f; + if(r > 500.0f) r = 500.0f; + } + + if(ctrl_button_pressed(BTN_ZOOM_IN)) { + r *= 0.9f; + if(r < 1.0f) r = 1.0f; + } + + if(ctrl_button_pressed(BTN_SCENE_RESET) == BTN_STAT_DOWN) { + physics_create_scene(sceneId); + } + + if(ctrl_button_pressed(BTN_SCENE_NEXT) == BTN_STAT_DOWN) { + physics_create_scene(++sceneId); + } + + if(ctrl_button_pressed(BTN_SIMULATION) == BTN_STAT_DOWN) { + simulating = !simulating; + } + + if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_DOWN) { + simulating = true; + } + else if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_UP || ctrl_button_pressed(BTN_STEP) == BTN_STAT_KEEP) { + simulating = false; + } + + render_set_view_angle(angX,angY,r); +} + +#ifndef _WIN32 + +// ARA begin insert new code +#ifdef __ANDROID__ + +/////////////////////////////////////////////////////////////////////////////// +// sceneChange +// +/// This function is used to change the physics scene on Android devices +/////////////////////////////////////////////////////////////////////////////// +void sceneChange() +{ + physics_create_scene(sceneId++); +} + +#else // __ANDROID__ +// ARA end + +/////////////////////////////////////////////////////////////////////////////// +// Main + +int main(void) +{ + init(); + + physics_create_scene(sceneId); + + printf("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + while (s_isRunning) { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + + shutdown(); + + printf("## %s: FINISHED ##\n", SAMPLE_NAME); + + return 0; +} + +// ARA begin insert new code +#endif // __ANDROID__ +// ARA end + +#else // _WIN32 + +/////////////////////////////////////////////////////////////////////////////// +// WinMain + +extern HDC hDC; +extern HGLRC hRC; +HWND hWnd; +HINSTANCE hInstance; + +void releaseWindow() +{ + if(hRC) { + wglMakeCurrent(0,0); + wglDeleteContext(hRC); + } + + if(hDC) ReleaseDC(hWnd,hDC); + if(hWnd) DestroyWindow(hWnd); + + UnregisterClass(SAMPLE_NAME,hInstance); +} + +LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + switch(uMsg) { + case WM_SYSCOMMAND: + { + switch (wParam) { + case SC_SCREENSAVE: + case SC_MONITORPOWER: + return 0; + } + break; + } + + case WM_CLOSE: + PostQuitMessage(0); + return 0; + + case WM_SIZE: + render_resize(LOWORD(lParam),HIWORD(lParam)); + return 0; + } + + return DefWindowProc(hWnd,uMsg,wParam,lParam); +} + +bool createWindow(char* title, int width, int height) +{ + WNDCLASS wc; + RECT rect; + rect.left=0; + rect.right=width; + rect.top=0; + rect.bottom=height; + + hInstance = GetModuleHandle(NULL); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = SAMPLE_NAME; + + if(!RegisterClass(&wc)) { + return false; + } + + AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE); + + if(!(hWnd=CreateWindowEx(WS_EX_APPWINDOW|WS_EX_WINDOWEDGE,SAMPLE_NAME,title, + WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS|WS_CLIPCHILDREN, + 0,0,rect.right-rect.left,rect.bottom-rect.top, + NULL,NULL,hInstance,NULL))) { + releaseWindow(); + return false; + } + + static PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + 32, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, + 0, 0, 0, 0, + 32, + 0, + 0, + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + if(!(hDC=GetDC(hWnd))) + { + releaseWindow(); + OutputDebugString(""); + return FALSE; + } + + int pixelformat; + + if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 ){ + OutputDebugString("ChoosePixelFormat Failed...."); + return FALSE; + } + + if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE){ + OutputDebugString("SetPixelFormat Failed...."); + return FALSE; + } + + if (!(hRC=wglCreateContext(hDC))){ + OutputDebugString("Creating HGLRC Failed...."); + return FALSE; + } + + // Set Vsync + //BOOL (WINAPI *wglSwapIntervalEXT)(int) = NULL; + + //if(strstr((char*)glGetString( GL_EXTENSIONS ),"WGL_EXT_swap_control")== 0) { + //} + //else { + //wglSwapIntervalEXT = (BOOL (WINAPI*)(int))wglGetProcAddress("wglSwapIntervalEXT"); + //if(wglSwapIntervalEXT) wglSwapIntervalEXT(1); + //} + + wglMakeCurrent(hDC,hRC); + + ShowWindow(hWnd,SW_SHOW); + SetForegroundWindow(hWnd); + SetFocus(hWnd); + + render_resize(width, height); + + glClearColor(0.0f,0.0f,0.0f,0.0f); + glClearDepth(1.0f); + + return TRUE; +} + +int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) +{ + if(!createWindow(SAMPLE_NAME,DISPLAY_WIDTH,DISPLAY_HEIGHT)) { + MessageBox(NULL,"Can't create gl window.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return 0; + } + + init(); + + physics_create_scene(sceneId); + + SCE_PFX_PRINTF("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + MSG msg; + while(s_isRunning) { + if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + if(msg.message==WM_QUIT) { + s_isRunning = false; + } + else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + } + + shutdown(); + + SCE_PFX_PRINTF("## %s: FINISHED ##\n", SAMPLE_NAME); + + releaseWindow(); + return (msg.wParam); +} + +#endif diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/physics_func.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/physics_func.cpp new file mode 100644 index 0000000..eaf4903 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/physics_func.cpp @@ -0,0 +1,968 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "physics_func.h" +#include "../common/perf_func.h" + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Data + +#define NUM_RIGIDBODIES 5000 +#define NUM_JOINTS 5000 +#define NUM_CONTACTS 4000 + +const float timeStep = 0.016f; +const float separateBias = 0.1f; +int iteration = 5; + +//J ??????? +//E World size +PfxVector3 worldCenter(0.0f); +PfxVector3 worldExtent(500.0f); + +//J ?? +//E Rigid body +PfxRigidState states[NUM_RIGIDBODIES]; +PfxRigidBody bodies[NUM_RIGIDBODIES]; +PfxCollidable collidables[NUM_RIGIDBODIES]; +PfxSolverBody solverBodies[NUM_RIGIDBODIES]; +int numRigidBodies = 0; + +//J ????????????????? +//E Large mesh for representing a landscape +#include "landscape.h" +PfxLargeTriMesh gLargeMesh; + +//J ????? +//E Convex Mesh +#include "barrel.h" +PfxConvexMesh gConvex; + +//J ???? +//E Proxies +PfxBroadphaseProxy proxies[NUM_RIGIDBODIES]; + +//J ????? +//E Joint +PfxConstraintPair jointPairs[NUM_JOINTS]; +PfxJoint joints[NUM_JOINTS]; +int numJoints = 0; + +//J ?? +//E Pairs +unsigned int pairSwap; +unsigned int numPairs[2]; +PfxBroadphasePair pairsBuff[2][NUM_CONTACTS]; + +//J ????? +//E Contacts +PfxContactManifold contacts[NUM_CONTACTS]; +int numContacts; + +PfxUInt32 contactIdPool[NUM_CONTACTS]; +int numContactIdPool; + +//J ?????? +//E Temporary buffers +#define POOL_BYTES (5*1024*1024) +unsigned char SCE_PFX_ALIGNED(128) poolBuff[POOL_BYTES]; + +//J ???????????????? +//E Stack allocator for temporary buffers +PfxHeapManager pool(poolBuff,POOL_BYTES); + +// ARA begin insert new code +//E task manager for parallel demo +#define NUM_THREADS 1 +PfxTaskManager *taskManager = NULL; +//E need enough bytes for NUM_THREADS PfxTaskArg objects, with the space rounded up to fill a 16-bit aligned space +#define TASK_MANAGER_POOL_BYTES 1024 +unsigned char SCE_PFX_ALIGNED(16) taskPoolBuff[TASK_MANAGER_POOL_BYTES]; +// ARA end + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Function + +int frame = 0; + +void broadphase() +{ + pairSwap = 1-pairSwap; + + unsigned int &numPreviousPairs = numPairs[1-pairSwap]; + unsigned int &numCurrentPairs = numPairs[pairSwap]; + PfxBroadphasePair *previousPairs = pairsBuff[1-pairSwap]; + PfxBroadphasePair *currentPairs = pairsBuff[pairSwap]; + + //J ????????????????? + //E Find the axis along which all rigid bodies are most widely positioned + int axis = 0; + { + PfxVector3 s(0.0f),s2(0.0f); + for(int i=0;i v[0]) axis = 1; + if(v[2] > v[axis]) axis = 2; + } + + //J ??????????????? + //E Create broadpahse proxies + { + for(int i=0;i 0) { + cId = contactIdPool[--numContactIdPool]; + } + else { + cId = numContacts++; + } + if(cId >= NUM_CONTACTS) { + cId = 0; + } + SCE_PFX_ASSERT(cId < NUM_CONTACTS); + pfxSetContactId(outNewPairs[i],cId); + PfxContactManifold &contact = contacts[cId]; + contact.reset(pfxGetObjectIdA(outNewPairs[i]),pfxGetObjectIdB(outNewPairs[i])); + } + + //J ???????????? + //E Merge 'new' and 'keep' pairs + numCurrentPairs = 0; + for(PfxUInt32 i=0;i 0) { + pfxReleaseLargeTriMesh(gLargeMesh); + } + + PfxInt32 ret = pfxCreateLargeTriMesh(gLargeMesh,param); + if(ret != SCE_PFX_OK) { + SCE_PFX_PRINTF("Can't create large mesh.\n"); + } + + int id = numRigidBodies++; + PfxShape shape; + shape.reset(); + shape.setLargeTriMesh(&gLargeMesh); + collidables[id].reset(); + collidables[id].addShape(shape); + collidables[id].finish(); + bodies[id].reset(); + states[id].reset(); + states[id].setPosition(PfxVector3(0.0f,-5.0f,0.0f)); + states[id].setOrientation(PfxQuat::rotationX(0.5f)*PfxQuat::rotationY(0.7f)); + states[id].setMotionType(kPfxMotionTypeFixed); + states[id].setRigidBodyId(id); +} + +void physics_create_scene(int sceneId) +{ + const int numScenes = 4; + int sid = sceneId % numScenes; + + numRigidBodies= 0; + pairSwap = 0; + numPairs[0] = 0; + numPairs[1] = 0; + numContacts = 0; + numContactIdPool = 0; + numJoints = 0; + frame = 0; + + switch(sid) { + case 0: // simple primitives + createSceneBoxGround(); + createScenePrimitives(); + break; + + case 1: // joints + createSceneBoxGround(); + createSceneJoints(); + break; + + case 2: // stacking + createSceneBoxGround(); + createSceneStacking(); + break; + + case 3: // landscape + createSceneLandscape(); + createScenePrimitives(); + break; + } + + SCE_PFX_PRINTF("----- Size of rigid body buffer ------\n"); + SCE_PFX_PRINTF(" size * num = total\n"); + SCE_PFX_PRINTF("PfxRigidState %5d * %5d = %5d bytes\n",sizeof(PfxRigidState),numRigidBodies,sizeof(PfxRigidState)*numRigidBodies); + SCE_PFX_PRINTF("PfxRigidBody %5d * %5d = %5d bytes\n",sizeof(PfxRigidBody),numRigidBodies,sizeof(PfxRigidBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxCollidable %5d * %5d = %5d bytes\n",sizeof(PfxCollidable),numRigidBodies,sizeof(PfxCollidable)*numRigidBodies); + SCE_PFX_PRINTF("PfxJoint %5d * %5d = %5d bytes\n",sizeof(PfxJoint),numJoints,sizeof(PfxJoint)*numJoints); + SCE_PFX_PRINTF("PfxSolverBody %5d * %5d = %5d bytes\n",sizeof(PfxSolverBody),numRigidBodies,sizeof(PfxSolverBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxBroadphaseProxy %5d * %5d = %5d bytes\n",sizeof(PfxBroadphaseProxy),numRigidBodies,sizeof(PfxBroadphaseProxy)*numRigidBodies); + SCE_PFX_PRINTF("PfxContactManifold %5d * %5d = %5d bytes\n",sizeof(PfxContactManifold),NUM_CONTACTS,sizeof(PfxContactManifold)*NUM_CONTACTS); + SCE_PFX_PRINTF("PfxBroadphasePair %5d * %5d = %5d bytes\n",sizeof(PfxBroadphasePair),NUM_CONTACTS,sizeof(PfxBroadphasePair)*NUM_CONTACTS); + + int totalBytes = + (sizeof(PfxRigidState) + sizeof(PfxRigidBody) + sizeof(PfxCollidable) + sizeof(PfxSolverBody) + sizeof(PfxBroadphaseProxy)) * numRigidBodies + + (sizeof(PfxContactManifold) + sizeof(PfxBroadphasePair)) * NUM_CONTACTS; + SCE_PFX_PRINTF("----------------------------------------------------------\n"); + SCE_PFX_PRINTF("Total %5d bytes\n",totalBytes); + +// ARA begin insert new code +#ifdef USE_PTHREADS + if (!taskManager) + { + taskManager = PfxCreateTaskManagerPthreads(NUM_THREADS, NUM_THREADS, taskPoolBuff, TASK_MANAGER_POOL_BYTES); + taskManager->initialize(); + } +#endif +// ARA end +} + +/////////////////////////////////////////////////////////////////////////////// +// Initialize / Finalize Engine + +bool physics_init() +{ + return true; +} + +void physics_release() +{ +// ARA begin insert new code + if (taskManager) + taskManager->finalize(); +// ARA end +} + +/////////////////////////////////////////////////////////////////////////////// +// Pick + +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2) +{ + return PfxVector3(0.0f); +} + +void physics_pick_update(const PfxVector3 &p) +{ +} + +void physics_pick_end() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Get Information + +int physics_get_num_rigidbodies() +{ + return numRigidBodies; +} + +const PfxRigidState& physics_get_state(int id) +{ + return states[id]; +} + +const PfxRigidBody& physics_get_body(int id) +{ + return bodies[id]; +} + +const PfxCollidable& physics_get_collidable(int id) +{ + return collidables[id]; +} + +int physics_get_num_contacts() +{ + return numPairs[pairSwap]; +} + +const PfxContactManifold &physics_get_contact(int id) +{ + return contacts[pfxGetConstraintId(pairsBuff[pairSwap][id])]; +} diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/physics_func.h b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/physics_func.h new file mode 100644 index 0000000..0a6d2fe --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/2_stable_parallel/physics_func.h @@ -0,0 +1,49 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef __PHYSICS_FUNC_H__ +#define __PHYSICS_FUNC_H__ + +#define SCE_PFX_USE_PERFCOUNTER + +#include "physics_effects.h" + +using namespace sce::PhysicsEffects; + +//E Simulation +//J ???????? +bool physics_init(); +void physics_release(); +void physics_create_scene(int sceneId); +void physics_simulate(); + +//E Picking +//J ????? +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2); +void physics_pick_update(const PfxVector3 &p); +void physics_pick_end(); + +//E Change parameters +//J ???????? +int physics_get_num_rigidbodies(); +const PfxRigidState& physics_get_state(int id); +const PfxRigidBody& physics_get_body(int id); +const PfxCollidable& physics_get_collidable(int id); + +int physics_get_num_contacts(); +const PfxContactManifold &physics_get_contact(int id); + +#endif /* __PHYSICS_FUNC_H__ */ diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/3_sleep.windows.vcproj b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/3_sleep.windows.vcproj new file mode 100644 index 0000000..d3c7857 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/3_sleep.windows.vcproj @@ -0,0 +1,713 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/CMakeLists.txt b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/CMakeLists.txt new file mode 100644 index 0000000..d54bb9a --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 2.4) + + +#this line has to appear before 'PROJECT' in order to be able to disable incremental linking +SET(MSVC_INCREMENTAL_DEFAULT ON) + +PROJECT(App_3_Sleep) + + +IF (NOT CMAKE_BUILD_TYPE) +# SET(CMAKE_BUILD_TYPE "Debug") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF (NOT CMAKE_BUILD_TYPE) + + +OPTION(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC Runtime Library DLL (/MD or /MDd)" ON) +OPTION(USE_MSVC_INCREMENTAL_LINKING "Use MSVC Incremental Linking" OFF) + + +IF(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + + +SET(App_3_Sleep_SRCS + main.cpp + physics_func.cpp + ../common/ctrl_func.win32.cpp + ../common/perf_func.win32.cpp + ../common/render_func.win32.cpp +) + + +SET(App_3_Sleep_HDRS + physics_func.h + landscape.h + barrel.h + ../common/render_func.h + ../common/common.h + ../common/ctrl_func.h + ../common/perf_func.h +) + + +INCLUDE_DIRECTORIES( + ${PHYSICS_EFFECTS_SOURCE_DIR}/include +# ${VECTOR_MATH_INCLUDE} +) + +#LINK_DIRECTORIES( +# +#) + +#ADD_DEFINITIONS(-DUNICODE) +#ADD_DEFINITIONS(-D_UNICODE) + +ADD_EXECUTABLE(App_3_Sleep WIN32 + ${App_3_Sleep_SRCS} + ${App_3_Sleep_HDRS} +) +TARGET_LINK_LIBRARIES(App_3_Sleep + PfxBaseLevel + PfxLowLevel + PfxUtil + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} +) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(App_3_Sleep PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(App_3_Sleep PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(App_3_Sleep PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF() + + + + \ No newline at end of file diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/barrel.h b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/barrel.h new file mode 100644 index 0000000..6574fa8 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/barrel.h @@ -0,0 +1,202 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define BarrelVtxCount 57 +#define BarrelIdxCount 180 + +static float BarrelVtx[] = { +0.0f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +-0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +0.0f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +-0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.957307f,-0.289072f,0.0f, +0.404509f,0.0f,-0.293893f, 0.809017f,0.0f,-0.587785f, +0.5f,0.0f,0.0f, 1.0f,0.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.774478f,-0.289072f,-0.562691f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +-0.154509f,0.0f,-0.475528f, -0.309017f,0.0f,-0.951057f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +-0.107853f,-0.5f,-0.331936f, -0.295824f,-0.289072f,-0.910453f, +-0.404509f,0.0f,-0.293893f, -0.809017f,0.0f,-0.587785f, +-0.282362f,-0.5f,-0.205148f, -0.774478f,-0.289072f,-0.562691f, +-0.5f,0.0f,0.0f, -1.0f,0.0f,0.0f, +-0.349018f,-0.5f,0.0f, -0.957307f,-0.289072f,0.0f, +-0.404508f,0.0f,0.293893f, -0.809017f,0.0f,0.587785f, +-0.282362f,-0.5f,0.205148f, -0.774478f,-0.289072f,0.562691f, +-0.154509f,0.0f,0.475528f, -0.309017f,0.0f,0.951056f, +-0.107853f,-0.5f,0.331936f, -0.295824f,-0.289072f,0.910453f, +0.154509f,0.0f,0.475528f, 0.309017f,0.0f,0.951056f, +0.107853f,-0.5f,0.331936f, 0.295824f,-0.289072f,0.910453f, +0.404509f,0.0f,0.293892f, 0.809017f,0.0f,0.587785f, +0.282362f,-0.5f,0.205148f, 0.774478f,-0.289072f,0.562691f, +0.282362f,0.5f,-0.205148f, 0.774478f,0.289072f,-0.562691f, +0.349018f,0.5f,0.0f, 0.957307f,0.289072f,0.0f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.107853f,0.5f,-0.331936f, -0.295824f,0.289072f,-0.910453f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.282362f,0.5f,-0.205148f, -0.774478f,0.289072f,-0.562691f, +-0.349018f,0.5f,0.0f, -0.957307f,0.289072f,0.0f, +-0.282362f,0.5f,0.205148f, -0.774478f,0.289072f,0.562691f, +-0.107853f,0.5f,0.331936f, -0.295824f,0.289072f,0.910453f, +0.107853f,0.5f,0.331936f, 0.295824f,0.289072f,0.910453f, +0.282362f,0.5f,0.205148f, 0.774478f,0.289072f,0.562691f, +}; + +static float BarrelTex[] = { +0.0f,0.5f, +0.0f,0.85f, +0.0f,0.75f, +0.0f,0.95f, +0.0f,0.05f, +0.0f,-0.05f, +0.0f,0.15f, +0.0f,0.25f, +0.0f,0.35f, +0.0f,0.45f, +0.0f,0.55f, +0.0f,0.65f, +1.0f,0.5f, +1.0f,0.75f, +1.0f,0.85f, +1.0f,0.95f, +1.0f,-0.05f, +1.0f,0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +0.0f,0.75f, +0.5f,0.85f, +0.5f,0.75f, +0.0f,0.85f, +0.5f,0.95f, +0.0f,0.95f, +0.0f,-0.05f, +0.5f,0.05f, +0.5f,-0.05f, +0.0f,0.05f, +0.5f,0.15f, +0.0f,0.15f, +0.5f,0.25f, +0.0f,0.25f, +0.5f,0.35f, +0.0f,0.35f, +0.5f,0.45f, +0.0f,0.45f, +0.5f,0.55f, +0.0f,0.55f, +0.5f,0.65f, +0.0f,0.65f, +1.0f,0.85f, +1.0f,0.75f, +1.0f,0.95f, +1.0f,0.05f, +1.0f,-0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +}; + +static unsigned short BarrelIdx[] = { +0,1,2, +0,3,1, +0,4,5, +0,6,4, +0,7,6, +0,8,7, +0,9,8, +0,10,9, +0,11,10, +0,2,11, +12,13,14, +12,14,15, +12,16,17, +12,17,18, +12,18,19, +12,19,20, +12,20,21, +12,21,22, +12,22,23, +12,23,13, +24,25,26, +24,27,25, +27,28,25, +27,29,28, +30,31,32, +30,33,31, +33,34,31, +33,35,34, +35,36,34, +35,37,36, +37,38,36, +37,39,38, +39,40,38, +39,41,40, +41,42,40, +41,43,42, +43,44,42, +43,45,44, +45,26,44, +45,24,26, +26,46,47, +26,25,46, +25,48,46, +25,28,48, +32,49,50, +32,31,49, +31,51,49, +31,34,51, +34,52,51, +34,36,52, +36,53,52, +36,38,53, +38,54,53, +38,40,54, +40,55,54, +40,42,55, +42,56,55, +42,44,56, +44,47,56, +44,26,47, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/landscape.h b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/landscape.h new file mode 100644 index 0000000..00f6cff --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/landscape.h @@ -0,0 +1,318 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define LargeMeshVtxCount 81 +#define LargeMeshIdxCount 384 + +static float LargeMeshVtx[] = { +-25.0f,-2.19407f,18.5625f, 0.232976f,0.967754f,0.0957829f, +-25.0f,0.0644502f,24.75f, 0.188094f,0.871343f,-0.45319f, +-18.75f,-4.50287f,18.5625f, -0.0716098f,0.995449f,0.0628767f, +-18.75f,-0.39999f,24.75f, -0.0602794f,0.895848f,-0.440253f, +-12.5f,-1.2166f,18.5625f, -0.269469f,0.961403f,0.0555879f, +-12.5f,-0.942431f,24.75f, -0.0997841f,0.993258f,0.0589987f, +-6.25f,1.93598f,18.5625f, -0.283933f,0.956351f,-0.0691025f, +-6.25f,-0.445954f,24.75f, -0.180725f,0.942766f,0.280233f, +0.0f,2.76983f,18.5625f, 0.171645f,0.984908f,0.0222501f, +0.0f,2.76642f,24.75f, 0.0784993f,0.995428f,-0.0544117f, +6.25f,-2.53736f,18.5625f, 0.248298f,0.965028f,0.0840741f, +6.25f,-0.915645f,24.75f, 0.164311f,0.945856f,-0.279926f, +12.5f,-1.60054f,18.5625f, -0.180435f,0.983586f,0.00115547f, +12.5f,0.831925f,24.75f, -0.0692495f,0.964821f,-0.253623f, +18.75f,-0.800282f,18.5625f, 0.10755f,0.951538f,0.288112f, +18.75f,-1.47284f,24.75f, 0.232178f,0.972664f,0.00429361f, +25.0f,-2.78379f,18.5625f, 0.1833f,0.937477f,0.295867f, +25.0f,-0.967508f,24.75f, -0.0773477f,0.956641f,-0.280812f, +-25.0f,-0.352038f,12.375f, -0.192222f,0.972435f,0.131987f, +-18.75f,0.681228f,12.375f, -0.107779f,0.962569f,0.248686f, +-12.5f,2.72065f,12.375f, 0.0520846f,0.993034f,0.105692f, +-6.25f,-1.78776f,12.375f, -0.0133223f,0.99674f,-0.0795754f, +0.0f,1.57707f,12.375f, -0.129025f,0.969662f,-0.207627f, +6.25f,0.424356f,12.375f, 0.180995f,0.97074f,0.157815f, +12.5f,0.283234f,12.375f, -0.16285f,0.973539f,0.160316f, +18.75f,2.57015f,12.375f, -0.165454f,0.978339f,0.124408f, +25.0f,3.07363f,12.375f, -0.00454559f,0.988151f,0.153417f, +-25.0f,-0.893751f,6.1875f, -0.0836251f,0.990084f,-0.112876f, +-18.75f,0.930932f,6.1875f, 0.00269413f,0.971838f,-0.235633f, +-12.5f,-0.684529f,6.1875f, -0.010319f,0.927048f,-0.3748f, +-6.25f,-0.661383f,6.1875f, 0.012265f,0.999875f,-0.00994222f, +0.0f,0.385718f,6.1875f, -0.15435f,0.984937f,-0.0779465f, +6.25f,0.589796f,6.1875f, 0.0241717f,0.999582f,-0.0158589f, +12.5f,0.47454f,6.1875f, -0.017184f,0.997953f,-0.0616073f, +18.75f,1.59939f,6.1875f, -0.0902706f,0.957309f,-0.274609f, +25.0f,1.13434f,6.1875f, 0.0346006f,0.957441f,-0.286547f, +-25.0f,0.74548f,0.0f, 0.329903f,0.930812f,0.157334f, +-18.75f,-2.47437f,0.0f, 0.247844f,0.968142f,0.0357041f, +-12.5f,-4.16309f,1.81975e-007f, -0.0623898f,0.997626f,-0.0291436f, +-6.25f,-0.700022f,0.0f, -0.217067f,0.974987f,-0.0477624f, +0.0f,-0.0957388f,0.0f, -0.117693f,0.990712f,-0.068098f, +6.25f,0.614077f,0.0f, -0.0713214f,0.997305f,0.01722f, +12.5f,0.299109f,0.0f, 0.218606f,0.968641f,0.118094f, +18.75f,-1.71753f,0.0f, 0.0339493f,0.985612f,-0.165579f, +25.0f,-1.12638f,0.0f, -0.0547573f,0.989177f,-0.136126f, +-25.0f,-0.403319f,-6.1875f, -0.1263f,0.989211f,-0.074223f, +-18.75f,-0.0730335f,-6.1875f, 0.0173428f,0.965382f,0.260261f, +-12.5f,-0.450125f,-6.1875f, 0.0658811f,0.875f,0.479619f, +-6.25f,-0.180204f,-6.1875f, 0.0116584f,0.981445f,0.19139f, +0.0f,-0.632679f,-6.1875f, -0.0557983f,0.993041f,-0.103716f, +6.25f,0.308409f,-6.1875f, -0.191898f,0.96766f,-0.163737f, +12.5f,2.5011f,-6.1875f, 0.0758397f,0.996403f,-0.0378189f, +18.75f,-1.69303f,-6.1875f, 0.16761f,0.974057f,0.15205f, +25.0f,-0.141349f,-6.1875f, -0.204846f,0.978471f,0.0251341f, +-25.0f,-1.10316f,-12.375f, -0.0350644f,0.993748f,-0.106001f, +-18.75f,1.06711f,-12.375f, -0.309806f,0.919244f,-0.242922f, +-12.5f,3.61544f,-12.375f, -0.0506281f,0.998702f,-0.00561657f, +-6.25f,1.6504f,-12.375f, 0.322294f,0.937465f,0.131477f, +0.0f,-1.60595f,-12.375f, 0.086016f,0.995916f,0.0274459f, +6.25f,-0.849859f,-12.375f, -0.0332811f,0.997087f,0.0686255f, +12.5f,-0.942201f,-12.375f, -0.153559f,0.982185f,-0.108312f, +18.75f,0.494873f,-12.375f, 0.0753195f,0.981472f,0.176181f, +25.0f,-0.333828f,-12.375f, 0.035057f,0.987194f,0.155624f, +-25.0f,2.1862f,-18.5625f, 0.612899f,0.782306f,0.111138f, +-18.75f,-3.38259f,-18.5625f, 0.0194078f,0.992789f,-0.118297f, +-12.5f,-0.880916f,-18.5625f, -0.282251f,0.949875f,-0.13443f, +-6.25f,0.818158f,-18.5625f, 0.1476f,0.981788f,-0.119612f, +0.0f,-1.48019f,-18.5625f, -0.044551f,0.996013f,-0.0772824f, +6.25f,1.47123f,-18.5625f, -0.117036f,0.97986f,0.161792f, +12.5f,0.164076f,-18.5625f, -0.0340355f,0.978993f,0.201034f, +18.75f,2.14568f,-18.5625f, -0.0439269f,0.994859f,0.0912435f, +25.0f,0.626506f,-18.5625f, 0.208015f,0.968592f,0.136229f, +-25.0f,0.296889f,-24.75f, 0.46973f,0.844327f,-0.257809f, +-18.75f,-3.18022f,-24.75f, -0.0226758f,0.998794f,-0.0435401f, +-12.5f,1.8927f,-24.75f, -0.202772f,0.919836f,0.335836f, +-6.25f,1.46387f,-24.75f, 0.224904f,0.955746f,0.189652f, +0.0f,-2.52726f,-24.75f, -0.0435882f,0.993572f,-0.10447f, +6.25f,1.30397f,-24.75f, -0.28646f,0.956525f,-0.0547707f, +12.5f,1.85812f,-24.75f, 0.0521949f,0.979796f,0.193067f, +18.75f,1.56331f,-24.75f, -0.0270784f,0.999629f,-0.00293115f, +25.0f,1.05366f,-24.75f, 0.161f,0.986887f,-0.0115473f, +}; + +static float LargeMeshTex[] = { +0.125f,0.0f, +0.0f,0.0f, +0.125f,0.125f, +0.0f,0.125f, +0.125f,0.25f, +0.0f,0.25f, +0.125f,0.375f, +0.0f,0.375f, +0.125f,0.5f, +0.0f,0.5f, +0.125f,0.625f, +0.0f,0.625f, +0.125f,0.75f, +0.0f,0.75f, +0.125f,0.875f, +0.0f,0.875f, +0.125f,1.0f, +0.0f,1.0f, +0.25f,0.0f, +0.25f,0.125f, +0.25f,0.25f, +0.25f,0.375f, +0.25f,0.5f, +0.25f,0.625f, +0.25f,0.75f, +0.25f,0.875f, +0.25f,1.0f, +0.375f,0.0f, +0.375f,0.125f, +0.375f,0.25f, +0.375f,0.375f, +0.375f,0.5f, +0.375f,0.625f, +0.375f,0.75f, +0.375f,0.875f, +0.375f,1.0f, +0.5f,0.0f, +0.5f,0.125f, +0.5f,0.25f, +0.5f,0.375f, +0.5f,0.5f, +0.5f,0.625f, +0.5f,0.75f, +0.5f,0.875f, +0.5f,1.0f, +0.625f,0.0f, +0.625f,0.125f, +0.625f,0.25f, +0.625f,0.375f, +0.625f,0.5f, +0.625f,0.625f, +0.625f,0.75f, +0.625f,0.875f, +0.625f,1.0f, +0.75f,0.0f, +0.75f,0.125f, +0.75f,0.25f, +0.75f,0.375f, +0.75f,0.5f, +0.75f,0.625f, +0.75f,0.75f, +0.75f,0.875f, +0.75f,1.0f, +0.875f,0.0f, +0.875f,0.125f, +0.875f,0.25f, +0.875f,0.375f, +0.875f,0.5f, +0.875f,0.625f, +0.875f,0.75f, +0.875f,0.875f, +0.875f,1.0f, +1.0f,0.0f, +1.0f,0.125f, +1.0f,0.25f, +1.0f,0.375f, +1.0f,0.5f, +1.0f,0.625f, +1.0f,0.75f, +1.0f,0.875f, +1.0f,1.0f, +}; + +static unsigned short LargeMeshIdx[] = { +0,1,2, +3,2,1, +2,3,4, +5,4,3, +4,5,6, +7,6,5, +6,7,8, +9,8,7, +8,9,10, +11,10,9, +10,11,12, +13,12,11, +12,13,14, +15,14,13, +14,15,16, +17,16,15, +18,0,19, +2,19,0, +19,2,20, +4,20,2, +20,4,21, +6,21,4, +21,6,22, +8,22,6, +22,8,23, +10,23,8, +23,10,24, +12,24,10, +24,12,25, +14,25,12, +25,14,26, +16,26,14, +27,18,28, +19,28,18, +28,19,29, +20,29,19, +29,20,30, +21,30,20, +30,21,31, +22,31,21, +31,22,32, +23,32,22, +32,23,33, +24,33,23, +33,24,34, +25,34,24, +34,25,35, +26,35,25, +36,27,37, +28,37,27, +37,28,38, +29,38,28, +38,29,39, +30,39,29, +39,30,40, +31,40,30, +40,31,41, +32,41,31, +41,32,42, +33,42,32, +42,33,43, +34,43,33, +43,34,44, +35,44,34, +45,36,46, +37,46,36, +46,37,47, +38,47,37, +47,38,48, +39,48,38, +48,39,49, +40,49,39, +49,40,50, +41,50,40, +50,41,51, +42,51,41, +51,42,52, +43,52,42, +52,43,53, +44,53,43, +54,45,55, +46,55,45, +55,46,56, +47,56,46, +56,47,57, +48,57,47, +57,48,58, +49,58,48, +58,49,59, +50,59,49, +59,50,60, +51,60,50, +60,51,61, +52,61,51, +61,52,62, +53,62,52, +63,54,64, +55,64,54, +64,55,65, +56,65,55, +65,56,66, +57,66,56, +66,57,67, +58,67,57, +67,58,68, +59,68,58, +68,59,69, +60,69,59, +69,60,70, +61,70,60, +70,61,71, +62,71,61, +72,63,73, +64,73,63, +73,64,74, +65,74,64, +74,65,75, +66,75,65, +75,66,76, +67,76,66, +76,67,77, +68,77,67, +77,68,78, +69,78,68, +78,69,79, +70,79,69, +79,70,80, +71,80,70, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/main.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/main.cpp new file mode 100644 index 0000000..6c25d5c --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/main.cpp @@ -0,0 +1,512 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../common/common.h" +#include "../common/ctrl_func.h" +#include "../common/render_func.h" +#include "../common/perf_func.h" +#include "physics_func.h" +#include "barrel.h" +#include "landscape.h" + +#ifdef _WIN32 + #include + #include +#endif + +// ARA begin insert new code +#ifdef __ANDROID__ + #include + #include +#endif +// ARA end + +#define SAMPLE_NAME "api_physics_effects/3_sleep" + +#define ENABLE_DEBUG_DRAW + +#ifdef ENABLE_DEBUG_DRAW + //#define ENABLE_DEBUG_DRAW_CONTACT + //#define ENABLE_DEBUG_DRAW_AABB + #define ENABLE_DEBUG_DRAW_ISLAND +#endif + +static bool s_isRunning = true; + +int sceneId = 0; +bool simulating = false; + +int landscapeMeshId; +int convexMeshId; + +void render(void) +{ + render_begin(); + + const PfxVector3 colorWhite(1.0f); + const PfxVector3 colorGray(0.7f); + + for(int i=0;i -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_DOWN)) { + angX += 0.05f; + if(angX < -1.4f) angX = -1.4f; + if(angX > -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_LEFT)) { + angY -= 0.05f; + } + + if(ctrl_button_pressed(BTN_RIGHT)) { + angY += 0.05f; + } + + if(ctrl_button_pressed(BTN_ZOOM_OUT)) { + r *= 1.1f; + if(r > 500.0f) r = 500.0f; + } + + if(ctrl_button_pressed(BTN_ZOOM_IN)) { + r *= 0.9f; + if(r < 1.0f) r = 1.0f; + } + + if(ctrl_button_pressed(BTN_SCENE_RESET) == BTN_STAT_DOWN) { + physics_create_scene(sceneId); + } + + if(ctrl_button_pressed(BTN_SCENE_NEXT) == BTN_STAT_DOWN) { + physics_create_scene(++sceneId); + } + + if(ctrl_button_pressed(BTN_SIMULATION) == BTN_STAT_DOWN) { + simulating = !simulating; + } + + if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_DOWN) { + simulating = true; + } + else if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_UP || ctrl_button_pressed(BTN_STEP) == BTN_STAT_KEEP) { + simulating = false; + } + + render_set_view_angle(angX,angY,r); +} + +#ifndef _WIN32 + +// ARA begin insert new code +#ifdef __ANDROID__ + +/////////////////////////////////////////////////////////////////////////////// +// sceneChange +// +/// This function is used to change the physics scene on Android devices +/////////////////////////////////////////////////////////////////////////////// +void sceneChange() +{ + physics_create_scene(sceneId++); +} + +#else // __ANDROID__ +// ARA end + +/////////////////////////////////////////////////////////////////////////////// +// Main + +int main(void) +{ + init(); + + physics_create_scene(sceneId); + + printf("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + while (s_isRunning) { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + + shutdown(); + + printf("## %s: FINISHED ##\n", SAMPLE_NAME); + + return 0; +} + +// ARA begin insert new code +#endif // __ANDROID__ +// ARA end + +#else // _WIN32 + +/////////////////////////////////////////////////////////////////////////////// +// WinMain + +extern HDC hDC; +extern HGLRC hRC; +HWND hWnd; +HINSTANCE hInstance; + +void releaseWindow() +{ + if(hRC) { + wglMakeCurrent(0,0); + wglDeleteContext(hRC); + } + + if(hDC) ReleaseDC(hWnd,hDC); + if(hWnd) DestroyWindow(hWnd); + + UnregisterClass(SAMPLE_NAME,hInstance); +} + +LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + switch(uMsg) { + case WM_SYSCOMMAND: + { + switch (wParam) { + case SC_SCREENSAVE: + case SC_MONITORPOWER: + return 0; + } + break; + } + + case WM_CLOSE: + PostQuitMessage(0); + return 0; + + case WM_SIZE: + render_resize(LOWORD(lParam),HIWORD(lParam)); + return 0; + } + + return DefWindowProc(hWnd,uMsg,wParam,lParam); +} + +bool createWindow(char* title, int width, int height) +{ + WNDCLASS wc; + RECT rect; + rect.left=0; + rect.right=width; + rect.top=0; + rect.bottom=height; + + hInstance = GetModuleHandle(NULL); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = SAMPLE_NAME; + + if(!RegisterClass(&wc)) { + return false; + } + + AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE); + + if(!(hWnd=CreateWindowEx(WS_EX_APPWINDOW|WS_EX_WINDOWEDGE,SAMPLE_NAME,title, + WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS|WS_CLIPCHILDREN, + 0,0,rect.right-rect.left,rect.bottom-rect.top, + NULL,NULL,hInstance,NULL))) { + releaseWindow(); + return false; + } + + static PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + 32, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, + 0, 0, 0, 0, + 32, + 0, + 0, + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + if(!(hDC=GetDC(hWnd))) + { + releaseWindow(); + OutputDebugString(""); + return FALSE; + } + + int pixelformat; + + if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 ){ + OutputDebugString("ChoosePixelFormat Failed...."); + return FALSE; + } + + if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE){ + OutputDebugString("SetPixelFormat Failed...."); + return FALSE; + } + + if (!(hRC=wglCreateContext(hDC))){ + OutputDebugString("Creating HGLRC Failed...."); + return FALSE; + } + + // Set Vsync + //BOOL (WINAPI *wglSwapIntervalEXT)(int) = NULL; + + //if(strstr((char*)glGetString( GL_EXTENSIONS ),"WGL_EXT_swap_control")== 0) { + //} + //else { + //wglSwapIntervalEXT = (BOOL (WINAPI*)(int))wglGetProcAddress("wglSwapIntervalEXT"); + //if(wglSwapIntervalEXT) wglSwapIntervalEXT(1); + //} + + wglMakeCurrent(hDC,hRC); + + ShowWindow(hWnd,SW_SHOW); + SetForegroundWindow(hWnd); + SetFocus(hWnd); + + render_resize(width, height); + + glClearColor(0.0f,0.0f,0.0f,0.0f); + glClearDepth(1.0f); + + return TRUE; +} + +int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) +{ + if(!createWindow(SAMPLE_NAME,DISPLAY_WIDTH,DISPLAY_HEIGHT)) { + MessageBox(NULL,"Can't create gl window.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return 0; + } + + init(); + + physics_create_scene(sceneId); + + SCE_PFX_PRINTF("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + MSG msg; + while(s_isRunning) { + if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + if(msg.message==WM_QUIT) { + s_isRunning = false; + } + else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + } + + shutdown(); + + SCE_PFX_PRINTF("## %s: FINISHED ##\n", SAMPLE_NAME); + + releaseWindow(); + return (msg.wParam); +} + +#endif diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/physics.png b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/physics.png new file mode 100644 index 0000000000000000000000000000000000000000..7230a6617cde6788afcb93db4d1fe56bdf5c0a57 GIT binary patch literal 24292 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�N)t4{B}LO{+hBA`u!4~~6HjZuzl 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 sS>6#(6e&-=7g#ss37S5!mww3sh0WwP4P5=M^ literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/physics_func.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/physics_func.cpp new file mode 100644 index 0000000..f549d73 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/physics_func.cpp @@ -0,0 +1,1016 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "physics_func.h" +#include "../common/perf_func.h" + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Data + +#define NUM_RIGIDBODIES 500 +#define NUM_JOINTS 500 +#define NUM_CONTACTS 4000 + +const float timeStep = 0.016f; +const float separateBias = 0.1f; +int iteration = 5; + +//J ワールドサイズ +//E World size +PfxVector3 worldCenter(0.0f); +PfxVector3 worldExtent(500.0f); + +//J 剛体 +//E Rigid body +PfxRigidState states[NUM_RIGIDBODIES]; +PfxRigidBody bodies[NUM_RIGIDBODIES]; +PfxCollidable collidables[NUM_RIGIDBODIES]; +PfxSolverBody solverBodies[NUM_RIGIDBODIES]; +int numRigidBodies = 0; + +//J 地形を表現するためのラージメッシュ +//E Large mesh for representing a landscape +#include "landscape.h" +PfxLargeTriMesh gLargeMesh; + +//J 凸メッシュ +//E Convex Mesh +#include "barrel.h" +PfxConvexMesh gConvex; + +//J プロキシ +//E Proxies +PfxBroadphaseProxy proxies[NUM_RIGIDBODIES]; + +//J ジョイント +//E Joint +PfxConstraintPair jointPairs[NUM_JOINTS]; +PfxJoint joints[NUM_JOINTS]; +int numJoints = 0; + +//J ペア +//E Pairs +unsigned int pairSwap; +unsigned int numPairs[2]; +PfxBroadphasePair pairsBuff[2][NUM_CONTACTS]; + +//J コンタクト +//E Contacts +PfxContactManifold contacts[NUM_CONTACTS]; +int numContacts; + +PfxUInt32 contactIdPool[NUM_CONTACTS]; +int numContactIdPool; + +//J シミュレーションアイランド +//E Island generation +PfxIsland *island=NULL; +PfxUInt8 SCE_PFX_ALIGNED(16) islandBuff[32*NUM_RIGIDBODIES]; // Island buffer should be 32 * the number of rigid bodies. + +//J スリープ制御 +//E Sleep control +/* + A sleeping object wakes up, when + * a new pair related to this rigid body is created + * a pair releated to this rigid body is removed + * a rigid body's velocity or position are updated + */ + +//J スリープに入るカウント +//E Count to enter sleeping +const PfxUInt32 sleepCount = 180; + +//J 速度が閾値以下ならばスリープカウントが増加 +//E If velocity is under the following value, sleep count is increased. +const PfxFloat sleepVelocity = 0.1f; + +//J 一時バッファ +//E Temporary buffers +#define POOL_BYTES (5*1024*1024) +unsigned char SCE_PFX_ALIGNED(128) poolBuff[POOL_BYTES]; + +//J 一時バッファ用スタックアロケータ +//E Stack allocator for temporary buffers +PfxHeapManager pool(poolBuff,POOL_BYTES); + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Function + +int frame = 0; + +void broadphase() +{ + pairSwap = 1-pairSwap; + + unsigned int &numPreviousPairs = numPairs[1-pairSwap]; + unsigned int &numCurrentPairs = numPairs[pairSwap]; + PfxBroadphasePair *previousPairs = pairsBuff[1-pairSwap]; + PfxBroadphasePair *currentPairs = pairsBuff[pairSwap]; + + //J 剛体が最も分散している軸を見つける + //E Find the axis along which all rigid bodies are most widely positioned + int axis = 0; + { + PfxVector3 s(0.0f),s2(0.0f); + for(int i=0;i v[0]) axis = 1; + if(v[2] > v[axis]) axis = 2; + } + + //J ブロードフェーズプロキシの更新 + //E Create broadpahse proxies + { + for(int i=0;i 0) { + cId = contactIdPool[--numContactIdPool]; + } + else { + cId = numContacts++; + } + if(cId >= NUM_CONTACTS) { + cId = 0; + } + SCE_PFX_ASSERT(cId < NUM_CONTACTS); + pfxSetContactId(outNewPairs[i],cId); + PfxContactManifold &contact = contacts[cId]; + contact.reset(pfxGetObjectIdA(outNewPairs[i]),pfxGetObjectIdB(outNewPairs[i])); + + //J 寝てる剛体を起こす + //E Wake up sleeping rigid bodies + PfxRigidState &stateA = states[pfxGetObjectIdA(outNewPairs[i])]; + PfxRigidState &stateB = states[pfxGetObjectIdB(outNewPairs[i])]; + if(stateA.isAsleep()) { + stateA.wakeup(); + SCE_PFX_PRINTF("wakeup %u\n",stateA.getRigidBodyId()); + } + if(stateB.isAsleep()) { + stateB.wakeup(); + SCE_PFX_PRINTF("wakeup %u\n",stateB.getRigidBodyId()); + } + } + + //J 新規ペアと維持ペアを合成 + //E Merge 'new' and 'keep' pairs + numCurrentPairs = 0; + for(PfxUInt32 i=0;i sleepCount) { + numCanSleep++; + } + } + } + } + + // Deactivate Island + if(numCanSleep > 0 && numCanSleep == numActive + numSleep) { + PfxIslandUnit *islandUnit = pfxGetFirstUnitInIsland(island,(PfxUInt32)i); + for(;islandUnit!=NULL;islandUnit=pfxGetNextUnitInIsland(islandUnit)) { + if(!(SCE_PFX_MOTION_MASK_CAN_SLEEP(states[pfxGetUnitId(islandUnit)].getMotionType()))) continue; + states[pfxGetUnitId(islandUnit)].sleep(); + } + } + + // Activate Island + else if(numSleep > 0 && numActive > 0) { + PfxIslandUnit *islandUnit = pfxGetFirstUnitInIsland(island,(PfxUInt32)i); + for(;islandUnit!=NULL;islandUnit=pfxGetNextUnitInIsland(islandUnit)) { + if(!(SCE_PFX_MOTION_MASK_CAN_SLEEP(states[pfxGetUnitId(islandUnit)].getMotionType()))) continue; + states[pfxGetUnitId(islandUnit)].wakeup(); + } + } + } + } +} + +void integrate() +{ + PfxUpdateRigidStatesParam param; + param.states = states; + param.bodies = bodies; + param.numRigidBodies = numRigidBodies; + param.timeStep = timeStep; + + pfxUpdateRigidStates(param); +} + +void physics_simulate() +{ + PfxPerfCounter pc; + + for(int i=1;i 0) { + pfxReleaseLargeTriMesh(gLargeMesh); + } + + PfxInt32 ret = pfxCreateLargeTriMesh(gLargeMesh,param); + if(ret != SCE_PFX_OK) { + SCE_PFX_PRINTF("Can't create large mesh.\n"); + } + + int id = numRigidBodies++; + PfxShape shape; + shape.reset(); + shape.setLargeTriMesh(&gLargeMesh); + collidables[id].reset(); + collidables[id].addShape(shape); + collidables[id].finish(); + bodies[id].reset(); + states[id].reset(); + states[id].setPosition(PfxVector3(0.0f,-5.0f,0.0f)); + states[id].setOrientation(PfxQuat::rotationX(0.5f)*PfxQuat::rotationY(0.7f)); + states[id].setMotionType(kPfxMotionTypeFixed); + states[id].setRigidBodyId(id); +} + +void physics_create_scene(int sceneId) +{ + const int numScenes = 4; + int sid = sceneId % numScenes; + + numRigidBodies= 0; + pairSwap = 0; + numPairs[0] = 0; + numPairs[1] = 0; + numContacts = 0; + numContactIdPool = 0; + numJoints = 0; + island = NULL; + frame = 0; + + switch(sid) { + case 0: // simple primitives + createSceneBoxGround(); + createScenePrimitives(); + break; + + case 1: // joints + createSceneBoxGround(); + createSceneJoints(); + break; + + case 2: // stacking + createSceneBoxGround(); + createSceneStacking(); + break; + + case 3: // landscape + createSceneLandscape(); + createScenePrimitives(); + break; + } + + SCE_PFX_PRINTF("----- Size of rigid body buffer ------\n"); + SCE_PFX_PRINTF(" size * num = total\n"); + SCE_PFX_PRINTF("PfxRigidState %5d * %5d = %5d bytes\n",sizeof(PfxRigidState),numRigidBodies,sizeof(PfxRigidState)*numRigidBodies); + SCE_PFX_PRINTF("PfxRigidBody %5d * %5d = %5d bytes\n",sizeof(PfxRigidBody),numRigidBodies,sizeof(PfxRigidBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxCollidable %5d * %5d = %5d bytes\n",sizeof(PfxCollidable),numRigidBodies,sizeof(PfxCollidable)*numRigidBodies); + SCE_PFX_PRINTF("PfxJoint %5d * %5d = %5d bytes\n",sizeof(PfxJoint),numJoints,sizeof(PfxJoint)*numJoints); + SCE_PFX_PRINTF("PfxSolverBody %5d * %5d = %5d bytes\n",sizeof(PfxSolverBody),numRigidBodies,sizeof(PfxSolverBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxBroadphaseProxy %5d * %5d = %5d bytes\n",sizeof(PfxBroadphaseProxy),numRigidBodies,sizeof(PfxBroadphaseProxy)*numRigidBodies); + SCE_PFX_PRINTF("PfxContactManifold %5d * %5d = %5d bytes\n",sizeof(PfxContactManifold),NUM_CONTACTS,sizeof(PfxContactManifold)*NUM_CONTACTS); + SCE_PFX_PRINTF("PfxBroadphasePair %5d * %5d = %5d bytes\n",sizeof(PfxBroadphasePair),NUM_CONTACTS,sizeof(PfxBroadphasePair)*NUM_CONTACTS); + + int totalBytes = + (sizeof(PfxRigidState) + sizeof(PfxRigidBody) + sizeof(PfxCollidable) + sizeof(PfxSolverBody) + sizeof(PfxBroadphaseProxy)) * numRigidBodies + + (sizeof(PfxContactManifold) + sizeof(PfxBroadphasePair)) * NUM_CONTACTS; + SCE_PFX_PRINTF("----------------------------------------------------------\n"); + SCE_PFX_PRINTF("Total %5d bytes\n",totalBytes); +} + +/////////////////////////////////////////////////////////////////////////////// +// Initialize / Finalize Engine + +bool physics_init() +{ + return true; +} + +void physics_release() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Pick + +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2) +{ + return PfxVector3(0.0f); +} + +void physics_pick_update(const PfxVector3 &p) +{ +} + +void physics_pick_end() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Get Information + +int physics_get_num_rigidbodies() +{ + return numRigidBodies; +} + +const PfxRigidState& physics_get_state(int id) +{ + return states[id]; +} + +const PfxRigidBody& physics_get_body(int id) +{ + return bodies[id]; +} + +const PfxCollidable& physics_get_collidable(int id) +{ + return collidables[id]; +} + +int physics_get_num_contacts() +{ + return numPairs[pairSwap]; +} + +const PfxContactManifold &physics_get_contact(int id) +{ + return contacts[pfxGetConstraintId(pairsBuff[pairSwap][id])]; +} + +const PfxIsland* physics_get_islands() +{ + return island; +} diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/physics_func.h b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/physics_func.h new file mode 100644 index 0000000..bde4189 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/physics_func.h @@ -0,0 +1,53 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef __PHYSICS_FUNC_H__ +#define __PHYSICS_FUNC_H__ + +#define SCE_PFX_USE_PERFCOUNTER + +#include "physics_effects.h" + +using namespace sce::PhysicsEffects; + +//E Simulation +//J シミュレーション +bool physics_init(); +void physics_release(); +void physics_create_scene(int sceneId); +void physics_simulate(); + +//E Picking +//J ピッキング +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2); +void physics_pick_update(const PfxVector3 &p); +void physics_pick_end(); + +//E Change parameters +//J パラメータの取得 +int physics_get_num_rigidbodies(); +const PfxRigidState& physics_get_state(int id); +const PfxRigidBody& physics_get_body(int id); +const PfxCollidable& physics_get_collidable(int id); + +// Get contact information +int physics_get_num_contacts(); +const PfxContactManifold &physics_get_contact(int id); + +// Get simulation island +const PfxIsland* physics_get_islands(); + +#endif /* __PHYSICS_FUNC_H__ */ diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/premake4.lua b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/premake4.lua new file mode 100644 index 0000000..c59b51b --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/3_sleep/premake4.lua @@ -0,0 +1,22 @@ + project "3_sleep" + + kind "WindowedApp" + targetdir "../../../bin" + includedirs {"../../../include"} + + links { + "physicseffects2_lowlevel", + "physicseffects2_baselevel", + "physicseffects2_util", + "opengl32" + } + + flags {"WinMain"} + + files { + "main.cpp", + "physics_func.cpp", + "../common/ctrl_func.win32.cpp", + "../common/perf_func.win32.cpp", + "../common/render_func.win32.cpp" + } \ No newline at end of file diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/4_motion_type.windows.vcproj b/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/4_motion_type.windows.vcproj new file mode 100644 index 0000000..f6d81a2 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/4_motion_type.windows.vcproj @@ -0,0 +1,721 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/CMakeLists.txt b/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/CMakeLists.txt new file mode 100644 index 0000000..bb31f7b --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 2.4) + + +#this line has to appear before 'PROJECT' in order to be able to disable incremental linking +SET(MSVC_INCREMENTAL_DEFAULT ON) + +PROJECT(App_4_MotionType) + + +IF (NOT CMAKE_BUILD_TYPE) +# SET(CMAKE_BUILD_TYPE "Debug") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF (NOT CMAKE_BUILD_TYPE) + + +OPTION(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC Runtime Library DLL (/MD or /MDd)" ON) +OPTION(USE_MSVC_INCREMENTAL_LINKING "Use MSVC Incremental Linking" OFF) + + +IF(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + + +SET(App_3_Sleep_SRCS + main.cpp + physics_func.cpp + ../common/ctrl_func.win32.cpp + ../common/perf_func.win32.cpp + ../common/render_func.win32.cpp +) + + +SET(App_3_Sleep_HDRS + physics_func.h + ../common/render_func.h + ../common/common.h + ../common/ctrl_func.h + ../common/perf_func.h +) + + +INCLUDE_DIRECTORIES( + ${PHYSICS_EFFECTS_SOURCE_DIR}/include +# ${VECTOR_MATH_INCLUDE} +) + +#LINK_DIRECTORIES( +# +#) + +#ADD_DEFINITIONS(-DUNICODE) +#ADD_DEFINITIONS(-D_UNICODE) + +ADD_EXECUTABLE(App_4_MotionType WIN32 + ${App_3_Sleep_SRCS} + ${App_3_Sleep_HDRS} +) +TARGET_LINK_LIBRARIES(App_4_MotionType + PfxBaseLevel + PfxLowLevel + PfxUtil + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} +) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(App_4_MotionType PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(App_4_MotionType PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(App_4_MotionType PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF() + + + + \ No newline at end of file diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/main.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/main.cpp new file mode 100644 index 0000000..62a5310 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/main.cpp @@ -0,0 +1,481 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../common/common.h" +#include "../common/ctrl_func.h" +#include "../common/render_func.h" +#include "../common/perf_func.h" +#include "physics_func.h" + +#ifdef _WIN32 + #include + #include +#endif + +// ARA begin insert new code +#ifdef __ANDROID__ + #include + #include +#endif +// ARA end + +#define SAMPLE_NAME "api_physics_effects/4_motion_type" + +//#define ENABLE_DEBUG_DRAW + +#ifdef ENABLE_DEBUG_DRAW + #define ENABLE_DEBUG_DRAW_CONTACT + #define ENABLE_DEBUG_DRAW_AABB + #define ENABLE_DEBUG_DRAW_ISLAND +#endif + +static bool s_isRunning = true; + +int sceneId = 0; +bool simulating = false; + +void render(void) +{ + render_begin(); + + const PfxVector3 colorWhite(1.0f); + const PfxVector3 colorGray(0.7f); + + for(int i=0;i -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_DOWN)) { + angX += 0.05f; + if(angX < -1.4f) angX = -1.4f; + if(angX > -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_LEFT)) { + angY -= 0.05f; + } + + if(ctrl_button_pressed(BTN_RIGHT)) { + angY += 0.05f; + } + + if(ctrl_button_pressed(BTN_ZOOM_OUT)) { + r *= 1.1f; + if(r > 500.0f) r = 500.0f; + } + + if(ctrl_button_pressed(BTN_ZOOM_IN)) { + r *= 0.9f; + if(r < 1.0f) r = 1.0f; + } + + if(ctrl_button_pressed(BTN_SCENE_RESET) == BTN_STAT_DOWN) { + physics_create_scene(sceneId); + } + + if(ctrl_button_pressed(BTN_SCENE_NEXT) == BTN_STAT_DOWN) { + physics_create_scene(++sceneId); + } + + if(ctrl_button_pressed(BTN_SIMULATION) == BTN_STAT_DOWN) { + simulating = !simulating; + } + + if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_DOWN) { + simulating = true; + } + else if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_UP || ctrl_button_pressed(BTN_STEP) == BTN_STAT_KEEP) { + simulating = false; + } + + render_set_view_angle(angX,angY,r); +} + +#ifndef _WIN32 + +// ARA begin insert new code +#ifdef __ANDROID__ + +/////////////////////////////////////////////////////////////////////////////// +// sceneChange +// +/// This function is used to change the physics scene on Android devices +/////////////////////////////////////////////////////////////////////////////// +void sceneChange() +{ + physics_create_scene(sceneId++); +} + +#else // __ANDROID__ +// ARA end + +/////////////////////////////////////////////////////////////////////////////// +// Main + +int main(void) +{ + init(); + + physics_create_scene(sceneId); + + printf("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + while (s_isRunning) { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + + shutdown(); + + printf("## %s: FINISHED ##\n", SAMPLE_NAME); + + return 0; +} + +// ARA begin insert new code +#endif // __ANDROID__ +// ARA end + +#else // _WIN32 + +/////////////////////////////////////////////////////////////////////////////// +// WinMain + +extern HDC hDC; +extern HGLRC hRC; +HWND hWnd; +HINSTANCE hInstance; + +void releaseWindow() +{ + if(hRC) { + wglMakeCurrent(0,0); + wglDeleteContext(hRC); + } + + if(hDC) ReleaseDC(hWnd,hDC); + if(hWnd) DestroyWindow(hWnd); + + UnregisterClass(SAMPLE_NAME,hInstance); +} + +LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + switch(uMsg) { + case WM_SYSCOMMAND: + { + switch (wParam) { + case SC_SCREENSAVE: + case SC_MONITORPOWER: + return 0; + } + break; + } + + case WM_CLOSE: + PostQuitMessage(0); + return 0; + + case WM_SIZE: + render_resize(LOWORD(lParam),HIWORD(lParam)); + return 0; + } + + return DefWindowProc(hWnd,uMsg,wParam,lParam); +} + +bool createWindow(char* title, int width, int height) +{ + WNDCLASS wc; + RECT rect; + rect.left=0; + rect.right=width; + rect.top=0; + rect.bottom=height; + + hInstance = GetModuleHandle(NULL); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = SAMPLE_NAME; + + if(!RegisterClass(&wc)) { + return false; + } + + AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE); + + if(!(hWnd=CreateWindowEx(WS_EX_APPWINDOW|WS_EX_WINDOWEDGE,SAMPLE_NAME,title, + WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS|WS_CLIPCHILDREN, + 0,0,rect.right-rect.left,rect.bottom-rect.top, + NULL,NULL,hInstance,NULL))) { + releaseWindow(); + return false; + } + + static PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + 32, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, + 0, 0, 0, 0, + 32, + 0, + 0, + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + if(!(hDC=GetDC(hWnd))) + { + releaseWindow(); + OutputDebugString(""); + return FALSE; + } + + int pixelformat; + + if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 ){ + OutputDebugString("ChoosePixelFormat Failed...."); + return FALSE; + } + + if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE){ + OutputDebugString("SetPixelFormat Failed...."); + return FALSE; + } + + if (!(hRC=wglCreateContext(hDC))){ + OutputDebugString("Creating HGLRC Failed...."); + return FALSE; + } + + // Set Vsync + //BOOL (WINAPI *wglSwapIntervalEXT)(int) = NULL; + + //if(strstr((char*)glGetString( GL_EXTENSIONS ),"WGL_EXT_swap_control")== 0) { + //} + //else { + //wglSwapIntervalEXT = (BOOL (WINAPI*)(int))wglGetProcAddress("wglSwapIntervalEXT"); + //if(wglSwapIntervalEXT) wglSwapIntervalEXT(1); + //} + + wglMakeCurrent(hDC,hRC); + + ShowWindow(hWnd,SW_SHOW); + SetForegroundWindow(hWnd); + SetFocus(hWnd); + + render_resize(width, height); + + glClearColor(0.0f,0.0f,0.0f,0.0f); + glClearDepth(1.0f); + + return TRUE; +} + +int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) +{ + if(!createWindow(SAMPLE_NAME,DISPLAY_WIDTH,DISPLAY_HEIGHT)) { + MessageBox(NULL,"Can't create gl window.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return 0; + } + + init(); + + physics_create_scene(sceneId); + + SCE_PFX_PRINTF("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + MSG msg; + while(s_isRunning) { + if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + if(msg.message==WM_QUIT) { + s_isRunning = false; + } + else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + } + + shutdown(); + + SCE_PFX_PRINTF("## %s: FINISHED ##\n", SAMPLE_NAME); + + releaseWindow(); + return (msg.wParam); +} + +#endif diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/physics.png b/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/physics.png new file mode 100644 index 0000000000000000000000000000000000000000..c1da418b4a072528d36969aa78ea9515221ad19c GIT binary patch literal 16126 zcmeHuWmHsM`0orI(kas2p^Va{kYQnq(wQBme+_Oj}FM2mk;n#j`fl4PIdL{} z4no3HH%3h9rUJp?=7>9*yVT*8$3>nrhE?-c6R;$>Z+m-apL})}sq`5!Pb#tuo}YG9 z6z##>S^>>E={)iO|Kz&*R6d^tGa zUnepz!U5U4)QXA7QEi(w?AwaO*lf8l;%l!xka^?F3j&-v@9 zUQmJQUqK^=g$%g4N^z)DXWJikyi`#B@Ak0(U{UDkiy7gci^cDnfBqG}(*!|cCrWF0 zoH4P#`9Buxl%drEgmu&8Q1;^Ek2i-++ckvW~Fs;ykCc{)<_RLVM^E1(11aiTt)} z7pVqrg3W(wPQ=jign_HD|qGCn$SP=iFj6 z$kZGbc=9=yrL~Cw&A2WxGQAnB@Z1cOh~uLKd;83UtLEcr)|wpO5j5v=cJ0O7p#149 zjl<7IkNE}f&9aggMc(7;4ACZ{t$W>x3$$zbEHpLzd%c-Lp~p*mxZyY$I

    e{;9iUV<{PyNLc;Fj@Ewe-a!oBd(h2SoH2HI0I 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 V7T;d%IdlL(TU}4BO2sbne*w9MAYT9g literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/physics_func.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/physics_func.cpp new file mode 100644 index 0000000..405c95f --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/physics_func.cpp @@ -0,0 +1,822 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "physics_func.h" +#include "../common/perf_func.h" + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Data + +#define NUM_RIGIDBODIES 500 +#define NUM_JOINTS 500 +#define NUM_CONTACTS 4000 + +const float timeStep = 0.016f; +const float separateBias = 0.1f; +int iteration = 5; + +//J ワールドサイズ +//E World size +PfxVector3 worldCenter(0.0f); +PfxVector3 worldExtent(500.0f); + +//J 剛体 +//E Rigid body +PfxRigidState states[NUM_RIGIDBODIES]; +PfxRigidBody bodies[NUM_RIGIDBODIES]; +PfxCollidable collidables[NUM_RIGIDBODIES]; +PfxSolverBody solverBodies[NUM_RIGIDBODIES]; +int numRigidBodies = 0; + +//J プロキシ +//E Proxies +PfxBroadphaseProxy proxies[NUM_RIGIDBODIES]; + +//J ジョイント +//E Joint +PfxConstraintPair jointPairs[NUM_JOINTS]; +PfxJoint joints[NUM_JOINTS]; +int numJoints = 0; + +//J ペア +//E Pairs +unsigned int pairSwap; +unsigned int numPairs[2]; +PfxBroadphasePair pairsBuff[2][NUM_CONTACTS]; + +//J コンタクト +//E Contacts +PfxContactManifold contacts[NUM_CONTACTS]; +int numContacts; + +PfxUInt32 contactIdPool[NUM_CONTACTS]; +int numContactIdPool; + +//J シミュレーションアイランド +//E Island generation +PfxIsland *island=NULL; +PfxUInt8 SCE_PFX_ALIGNED(16) islandBuff[32*NUM_RIGIDBODIES]; // Island buffer should be 32 * the number of rigid bodies. + +//J スリープ制御 +//E Sleep control +/* + A sleeping object wakes up, when + * a new pair related to this rigid body is created + * a pair releated to this rigid body is removed + * a rigid body's velocity or position are updated + */ + +//J スリープに入るカウント +//E Count to enter sleeping +const PfxUInt32 sleepCount = 180; + +//J 速度が閾値以下ならばスリープカウントが増加 +//E If velocity is under the following value, sleep count is increased. +const PfxFloat sleepVelocity = 0.1f; + +//J 一時バッファ +//E Temporary buffers +#define POOL_BYTES (5*1024*1024) +unsigned char SCE_PFX_ALIGNED(128) poolBuff[POOL_BYTES]; + +//J 一時バッファ用スタックアロケータ +//E Stack allocator for temporary buffers +PfxHeapManager pool(poolBuff,POOL_BYTES); + +// Keyframe +void updateKeyframe(); +int keyframeId; + +// Trigger +void updateTrigger(); +int triggerId; + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Function + +int frame = 0; + +void broadphase() +{ + pairSwap = 1-pairSwap; + + unsigned int &numPreviousPairs = numPairs[1-pairSwap]; + unsigned int &numCurrentPairs = numPairs[pairSwap]; + PfxBroadphasePair *previousPairs = pairsBuff[1-pairSwap]; + PfxBroadphasePair *currentPairs = pairsBuff[pairSwap]; + + //J 剛体が最も分散している軸を見つける + //E Find the axis along which all rigid bodies are most widely positioned + int axis = 0; + { + PfxVector3 s(0.0f),s2(0.0f); + for(int i=0;i v[0]) axis = 1; + if(v[2] > v[axis]) axis = 2; + } + + //J ブロードフェーズプロキシの更新 + //E Create broadpahse proxies + { + for(int i=0;i 0) { + cId = contactIdPool[--numContactIdPool]; + } + else { + cId = numContacts++; + } + if(cId >= NUM_CONTACTS) { + cId = 0; + } + SCE_PFX_ASSERT(cId < NUM_CONTACTS); + pfxSetContactId(outNewPairs[i],cId); + PfxContactManifold &contact = contacts[cId]; + contact.reset(pfxGetObjectIdA(outNewPairs[i]),pfxGetObjectIdB(outNewPairs[i])); + + //J 寝てる剛体を起こす + //E Wake up sleeping rigid bodies + PfxRigidState &stateA = states[pfxGetObjectIdA(outNewPairs[i])]; + PfxRigidState &stateB = states[pfxGetObjectIdB(outNewPairs[i])]; + if(stateA.isAsleep()) { + stateA.wakeup(); + } + if(stateB.isAsleep()) { + stateB.wakeup(); + } + } + + //J 新規ペアと維持ペアを合成 + //E Merge 'new' and 'keep' pairs + numCurrentPairs = 0; + for(PfxUInt32 i=0;i sleepCount) { + numCanSleep++; + } + } + } + } + + // Deactivate Island + if(numCanSleep > 0 && numCanSleep == numActive + numSleep) { + PfxIslandUnit *islandUnit = pfxGetFirstUnitInIsland(island,(PfxUInt32)i); + for(;islandUnit!=NULL;islandUnit=pfxGetNextUnitInIsland(islandUnit)) { + if(!(SCE_PFX_MOTION_MASK_CAN_SLEEP(states[pfxGetUnitId(islandUnit)].getMotionType()))) continue; + states[pfxGetUnitId(islandUnit)].sleep(); + } + } + + // Activate Island + else if(numSleep > 0 && numActive > 0) { + PfxIslandUnit *islandUnit = pfxGetFirstUnitInIsland(island,(PfxUInt32)i); + for(;islandUnit!=NULL;islandUnit=pfxGetNextUnitInIsland(islandUnit)) { + if(!(SCE_PFX_MOTION_MASK_CAN_SLEEP(states[pfxGetUnitId(islandUnit)].getMotionType()))) continue; + states[pfxGetUnitId(islandUnit)].wakeup(); + } + } + } + } +} + +void integrate() +{ + PfxUpdateRigidStatesParam param; + param.states = states; + param.bodies = bodies; + param.numRigidBodies = numRigidBodies; + param.timeStep = timeStep; + + pfxUpdateRigidStates(param); +} + +void physics_simulate() +{ + PfxPerfCounter pc; + + for(int i=1;i=0) updateKeyframe(); + if(triggerId>=0) updateTrigger(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Create Scene + +int createBrick(int id,const PfxVector3 &pos,const PfxQuat &rot,const PfxVector3 &boxSize,PfxFloat mass) +{ + PfxBox box(boxSize); + PfxShape shape; + shape.reset(); + shape.setBox(box); + collidables[id].reset(); + collidables[id].addShape(shape); + collidables[id].finish(); + bodies[id].reset(); + bodies[id].setRestitution(0.0f); + bodies[id].setMass(mass); + bodies[id].setInertia(pfxCalcInertiaBox(boxSize,mass)); + states[id].reset(); + states[id].setPosition(pos); + states[id].setOrientation(rot); + states[id].setMotionType(kPfxMotionTypeActive); + states[id].setUseSleep(1); // sleep mode ON + states[id].setRigidBodyId(id); + + return id; +} + +void createWall(const PfxVector3 &offsetPosition,int stackSize,const PfxVector3 &boxSize) +{ + PfxFloat bodyMass = 0.5f; + + PfxFloat diffX = boxSize[0] * 1.02f; + PfxFloat diffY = boxSize[1] * 1.02f; + PfxFloat diffZ = boxSize[2] * 1.02f; + + PfxFloat offset = -stackSize * (diffZ * 2.0f) * 0.5f; + PfxVector3 pos(0.0f, diffY, 0.0f); + + while(stackSize) { + for(int i=0;i 0) { + SCE_PFX_PRINTF("Find Contact %u\n",pfxGetObjectIdB(pair)); + } + } + if(pfxGetObjectIdB(pair) == triggerId) { + if(contact.getNumContacts() > 0) { + SCE_PFX_PRINTF("Find Contact %u\n",pfxGetObjectIdA(pair)); + } + } + } +} + +void createSceneBoxGround() +{ + int id = numRigidBodies++; + PfxBox box(150.0f,2.5f,150.0f); + PfxShape shape; + shape.reset(); + shape.setBox(box); + collidables[id].reset(); + collidables[id].addShape(shape); + collidables[id].finish(); + bodies[id].reset(); + states[id].reset(); + states[id].setPosition(PfxVector3(0.0f,-2.5f,0.0f)); + states[id].setMotionType(kPfxMotionTypeFixed); + states[id].setRigidBodyId(id); +} + +void physics_create_scene(int sceneId) +{ + const int numScenes = 3; + int sid = sceneId % numScenes; + + numRigidBodies= 0; + pairSwap = 0; + numPairs[0] = 0; + numPairs[1] = 0; + numContacts = 0; + numContactIdPool = 0; + numJoints = 0; + island = NULL; + frame = 0; + + keyframeId = -1; + triggerId = -1; + + switch(sid) { + case 0: + createSceneBoxGround(); + createSceneKeyframe(); + createWall(PfxVector3(0.0f,1.0f,0.0f),5,PfxVector3(0.5f)); + break; + + case 1: + createSceneBoxGround(); + createSceneOneWay(); + break; + + case 2: + createSceneBoxGround(); + createSceneTrigger(); + break; + } + + SCE_PFX_PRINTF("----- Size of rigid body buffer ------\n"); + SCE_PFX_PRINTF(" size * num = total\n"); + SCE_PFX_PRINTF("PfxRigidState %5d * %5d = %5d bytes\n",sizeof(PfxRigidState),numRigidBodies,sizeof(PfxRigidState)*numRigidBodies); + SCE_PFX_PRINTF("PfxRigidBody %5d * %5d = %5d bytes\n",sizeof(PfxRigidBody),numRigidBodies,sizeof(PfxRigidBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxCollidable %5d * %5d = %5d bytes\n",sizeof(PfxCollidable),numRigidBodies,sizeof(PfxCollidable)*numRigidBodies); + SCE_PFX_PRINTF("PfxJoint %5d * %5d = %5d bytes\n",sizeof(PfxJoint),numJoints,sizeof(PfxJoint)*numJoints); + SCE_PFX_PRINTF("PfxSolverBody %5d * %5d = %5d bytes\n",sizeof(PfxSolverBody),numRigidBodies,sizeof(PfxSolverBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxBroadphaseProxy %5d * %5d = %5d bytes\n",sizeof(PfxBroadphaseProxy),numRigidBodies,sizeof(PfxBroadphaseProxy)*numRigidBodies); + SCE_PFX_PRINTF("PfxContactManifold %5d * %5d = %5d bytes\n",sizeof(PfxContactManifold),NUM_CONTACTS,sizeof(PfxContactManifold)*NUM_CONTACTS); + SCE_PFX_PRINTF("PfxBroadphasePair %5d * %5d = %5d bytes\n",sizeof(PfxBroadphasePair),NUM_CONTACTS,sizeof(PfxBroadphasePair)*NUM_CONTACTS); + + int totalBytes = + (sizeof(PfxRigidState) + sizeof(PfxRigidBody) + sizeof(PfxCollidable) + sizeof(PfxSolverBody) + sizeof(PfxBroadphaseProxy)) * numRigidBodies + + (sizeof(PfxContactManifold) + sizeof(PfxBroadphasePair)) * NUM_CONTACTS; + SCE_PFX_PRINTF("----------------------------------------------------------\n"); + SCE_PFX_PRINTF("Total %5d bytes\n",totalBytes); +} + +/////////////////////////////////////////////////////////////////////////////// +// Initialize / Finalize Engine + +bool physics_init() +{ + return true; +} + +void physics_release() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Pick + +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2) +{ + return PfxVector3(0.0f); +} + +void physics_pick_update(const PfxVector3 &p) +{ +} + +void physics_pick_end() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Get Information + +int physics_get_num_rigidbodies() +{ + return numRigidBodies; +} + +const PfxRigidState& physics_get_state(int id) +{ + return states[id]; +} + +const PfxRigidBody& physics_get_body(int id) +{ + return bodies[id]; +} + +const PfxCollidable& physics_get_collidable(int id) +{ + return collidables[id]; +} + +int physics_get_num_contacts() +{ + return numPairs[pairSwap]; +} + +const PfxContactManifold &physics_get_contact(int id) +{ + return contacts[pfxGetConstraintId(pairsBuff[pairSwap][id])]; +} + +const PfxIsland* physics_get_islands() +{ + return island; +} diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/physics_func.h b/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/physics_func.h new file mode 100644 index 0000000..bde4189 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/physics_func.h @@ -0,0 +1,53 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef __PHYSICS_FUNC_H__ +#define __PHYSICS_FUNC_H__ + +#define SCE_PFX_USE_PERFCOUNTER + +#include "physics_effects.h" + +using namespace sce::PhysicsEffects; + +//E Simulation +//J シミュレーション +bool physics_init(); +void physics_release(); +void physics_create_scene(int sceneId); +void physics_simulate(); + +//E Picking +//J ピッキング +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2); +void physics_pick_update(const PfxVector3 &p); +void physics_pick_end(); + +//E Change parameters +//J パラメータの取得 +int physics_get_num_rigidbodies(); +const PfxRigidState& physics_get_state(int id); +const PfxRigidBody& physics_get_body(int id); +const PfxCollidable& physics_get_collidable(int id); + +// Get contact information +int physics_get_num_contacts(); +const PfxContactManifold &physics_get_contact(int id); + +// Get simulation island +const PfxIsland* physics_get_islands(); + +#endif /* __PHYSICS_FUNC_H__ */ diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/premake4.lua b/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/premake4.lua new file mode 100644 index 0000000..dc19454 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/4_motion_type/premake4.lua @@ -0,0 +1,22 @@ + project "4_motion_type" + + kind "WindowedApp" + targetdir "../../../bin" + includedirs {"../../../include"} + + links { + "physicseffects2_lowlevel", + "physicseffects2_baselevel", + "physicseffects2_util", + "opengl32" + } + + flags {"WinMain"} + + files { + "main.cpp", + "physics_func.cpp", + "../common/ctrl_func.win32.cpp", + "../common/perf_func.win32.cpp", + "../common/render_func.win32.cpp" + } \ No newline at end of file diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/5_raycast.windows.vcproj b/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/5_raycast.windows.vcproj new file mode 100644 index 0000000..c92d915 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/5_raycast.windows.vcproj @@ -0,0 +1,721 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/CMakeLists.txt b/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/CMakeLists.txt new file mode 100644 index 0000000..f8687f7 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 2.4) + + +#this line has to appear before 'PROJECT' in order to be able to disable incremental linking +SET(MSVC_INCREMENTAL_DEFAULT ON) + +PROJECT(App_5_Raycast) + + +IF (NOT CMAKE_BUILD_TYPE) +# SET(CMAKE_BUILD_TYPE "Debug") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF (NOT CMAKE_BUILD_TYPE) + + +OPTION(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC Runtime Library DLL (/MD or /MDd)" ON) +OPTION(USE_MSVC_INCREMENTAL_LINKING "Use MSVC Incremental Linking" OFF) + + +IF(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + + +SET(App_5_Raycast_SRCS + main.cpp + physics_func.cpp + ../common/ctrl_func.win32.cpp + ../common/perf_func.win32.cpp + ../common/render_func.win32.cpp +) + + +SET(App_5_Raycast_HDRS + physics_func.h + landscape.h + barrel.h + ../common/render_func.h + ../common/common.h + ../common/ctrl_func.h + ../common/perf_func.h +) + + +INCLUDE_DIRECTORIES( + ${PHYSICS_EFFECTS_SOURCE_DIR}/include +# ${VECTOR_MATH_INCLUDE} +) + +#LINK_DIRECTORIES( +# +#) + +#ADD_DEFINITIONS(-DUNICODE) +#ADD_DEFINITIONS(-D_UNICODE) + +ADD_EXECUTABLE(App_5_Raycast WIN32 + ${App_5_Raycast_SRCS} + ${App_5_Raycast_HDRS} +) +TARGET_LINK_LIBRARIES(App_5_Raycast + PfxBaseLevel + PfxLowLevel + PfxUtil + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} +) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(App_5_Raycast PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(App_5_Raycast PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(App_5_Raycast PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF() + + + + \ No newline at end of file diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/barrel.h b/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/barrel.h new file mode 100644 index 0000000..6574fa8 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/barrel.h @@ -0,0 +1,202 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define BarrelVtxCount 57 +#define BarrelIdxCount 180 + +static float BarrelVtx[] = { +0.0f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +-0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +0.0f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +-0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.957307f,-0.289072f,0.0f, +0.404509f,0.0f,-0.293893f, 0.809017f,0.0f,-0.587785f, +0.5f,0.0f,0.0f, 1.0f,0.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.774478f,-0.289072f,-0.562691f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +-0.154509f,0.0f,-0.475528f, -0.309017f,0.0f,-0.951057f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +-0.107853f,-0.5f,-0.331936f, -0.295824f,-0.289072f,-0.910453f, +-0.404509f,0.0f,-0.293893f, -0.809017f,0.0f,-0.587785f, +-0.282362f,-0.5f,-0.205148f, -0.774478f,-0.289072f,-0.562691f, +-0.5f,0.0f,0.0f, -1.0f,0.0f,0.0f, +-0.349018f,-0.5f,0.0f, -0.957307f,-0.289072f,0.0f, +-0.404508f,0.0f,0.293893f, -0.809017f,0.0f,0.587785f, +-0.282362f,-0.5f,0.205148f, -0.774478f,-0.289072f,0.562691f, +-0.154509f,0.0f,0.475528f, -0.309017f,0.0f,0.951056f, +-0.107853f,-0.5f,0.331936f, -0.295824f,-0.289072f,0.910453f, +0.154509f,0.0f,0.475528f, 0.309017f,0.0f,0.951056f, +0.107853f,-0.5f,0.331936f, 0.295824f,-0.289072f,0.910453f, +0.404509f,0.0f,0.293892f, 0.809017f,0.0f,0.587785f, +0.282362f,-0.5f,0.205148f, 0.774478f,-0.289072f,0.562691f, +0.282362f,0.5f,-0.205148f, 0.774478f,0.289072f,-0.562691f, +0.349018f,0.5f,0.0f, 0.957307f,0.289072f,0.0f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.107853f,0.5f,-0.331936f, -0.295824f,0.289072f,-0.910453f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.282362f,0.5f,-0.205148f, -0.774478f,0.289072f,-0.562691f, +-0.349018f,0.5f,0.0f, -0.957307f,0.289072f,0.0f, +-0.282362f,0.5f,0.205148f, -0.774478f,0.289072f,0.562691f, +-0.107853f,0.5f,0.331936f, -0.295824f,0.289072f,0.910453f, +0.107853f,0.5f,0.331936f, 0.295824f,0.289072f,0.910453f, +0.282362f,0.5f,0.205148f, 0.774478f,0.289072f,0.562691f, +}; + +static float BarrelTex[] = { +0.0f,0.5f, +0.0f,0.85f, +0.0f,0.75f, +0.0f,0.95f, +0.0f,0.05f, +0.0f,-0.05f, +0.0f,0.15f, +0.0f,0.25f, +0.0f,0.35f, +0.0f,0.45f, +0.0f,0.55f, +0.0f,0.65f, +1.0f,0.5f, +1.0f,0.75f, +1.0f,0.85f, +1.0f,0.95f, +1.0f,-0.05f, +1.0f,0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +0.0f,0.75f, +0.5f,0.85f, +0.5f,0.75f, +0.0f,0.85f, +0.5f,0.95f, +0.0f,0.95f, +0.0f,-0.05f, +0.5f,0.05f, +0.5f,-0.05f, +0.0f,0.05f, +0.5f,0.15f, +0.0f,0.15f, +0.5f,0.25f, +0.0f,0.25f, +0.5f,0.35f, +0.0f,0.35f, +0.5f,0.45f, +0.0f,0.45f, +0.5f,0.55f, +0.0f,0.55f, +0.5f,0.65f, +0.0f,0.65f, +1.0f,0.85f, +1.0f,0.75f, +1.0f,0.95f, +1.0f,0.05f, +1.0f,-0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +}; + +static unsigned short BarrelIdx[] = { +0,1,2, +0,3,1, +0,4,5, +0,6,4, +0,7,6, +0,8,7, +0,9,8, +0,10,9, +0,11,10, +0,2,11, +12,13,14, +12,14,15, +12,16,17, +12,17,18, +12,18,19, +12,19,20, +12,20,21, +12,21,22, +12,22,23, +12,23,13, +24,25,26, +24,27,25, +27,28,25, +27,29,28, +30,31,32, +30,33,31, +33,34,31, +33,35,34, +35,36,34, +35,37,36, +37,38,36, +37,39,38, +39,40,38, +39,41,40, +41,42,40, +41,43,42, +43,44,42, +43,45,44, +45,26,44, +45,24,26, +26,46,47, +26,25,46, +25,48,46, +25,28,48, +32,49,50, +32,31,49, +31,51,49, +31,34,51, +34,52,51, +34,36,52, +36,53,52, +36,38,53, +38,54,53, +38,40,54, +40,55,54, +40,42,55, +42,56,55, +42,44,56, +44,47,56, +44,26,47, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/landscape.h b/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/landscape.h new file mode 100644 index 0000000..00f6cff --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/landscape.h @@ -0,0 +1,318 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define LargeMeshVtxCount 81 +#define LargeMeshIdxCount 384 + +static float LargeMeshVtx[] = { +-25.0f,-2.19407f,18.5625f, 0.232976f,0.967754f,0.0957829f, +-25.0f,0.0644502f,24.75f, 0.188094f,0.871343f,-0.45319f, +-18.75f,-4.50287f,18.5625f, -0.0716098f,0.995449f,0.0628767f, +-18.75f,-0.39999f,24.75f, -0.0602794f,0.895848f,-0.440253f, +-12.5f,-1.2166f,18.5625f, -0.269469f,0.961403f,0.0555879f, +-12.5f,-0.942431f,24.75f, -0.0997841f,0.993258f,0.0589987f, +-6.25f,1.93598f,18.5625f, -0.283933f,0.956351f,-0.0691025f, +-6.25f,-0.445954f,24.75f, -0.180725f,0.942766f,0.280233f, +0.0f,2.76983f,18.5625f, 0.171645f,0.984908f,0.0222501f, +0.0f,2.76642f,24.75f, 0.0784993f,0.995428f,-0.0544117f, +6.25f,-2.53736f,18.5625f, 0.248298f,0.965028f,0.0840741f, +6.25f,-0.915645f,24.75f, 0.164311f,0.945856f,-0.279926f, +12.5f,-1.60054f,18.5625f, -0.180435f,0.983586f,0.00115547f, +12.5f,0.831925f,24.75f, -0.0692495f,0.964821f,-0.253623f, +18.75f,-0.800282f,18.5625f, 0.10755f,0.951538f,0.288112f, +18.75f,-1.47284f,24.75f, 0.232178f,0.972664f,0.00429361f, +25.0f,-2.78379f,18.5625f, 0.1833f,0.937477f,0.295867f, +25.0f,-0.967508f,24.75f, -0.0773477f,0.956641f,-0.280812f, +-25.0f,-0.352038f,12.375f, -0.192222f,0.972435f,0.131987f, +-18.75f,0.681228f,12.375f, -0.107779f,0.962569f,0.248686f, +-12.5f,2.72065f,12.375f, 0.0520846f,0.993034f,0.105692f, +-6.25f,-1.78776f,12.375f, -0.0133223f,0.99674f,-0.0795754f, +0.0f,1.57707f,12.375f, -0.129025f,0.969662f,-0.207627f, +6.25f,0.424356f,12.375f, 0.180995f,0.97074f,0.157815f, +12.5f,0.283234f,12.375f, -0.16285f,0.973539f,0.160316f, +18.75f,2.57015f,12.375f, -0.165454f,0.978339f,0.124408f, +25.0f,3.07363f,12.375f, -0.00454559f,0.988151f,0.153417f, +-25.0f,-0.893751f,6.1875f, -0.0836251f,0.990084f,-0.112876f, +-18.75f,0.930932f,6.1875f, 0.00269413f,0.971838f,-0.235633f, +-12.5f,-0.684529f,6.1875f, -0.010319f,0.927048f,-0.3748f, +-6.25f,-0.661383f,6.1875f, 0.012265f,0.999875f,-0.00994222f, +0.0f,0.385718f,6.1875f, -0.15435f,0.984937f,-0.0779465f, +6.25f,0.589796f,6.1875f, 0.0241717f,0.999582f,-0.0158589f, +12.5f,0.47454f,6.1875f, -0.017184f,0.997953f,-0.0616073f, +18.75f,1.59939f,6.1875f, -0.0902706f,0.957309f,-0.274609f, +25.0f,1.13434f,6.1875f, 0.0346006f,0.957441f,-0.286547f, +-25.0f,0.74548f,0.0f, 0.329903f,0.930812f,0.157334f, +-18.75f,-2.47437f,0.0f, 0.247844f,0.968142f,0.0357041f, +-12.5f,-4.16309f,1.81975e-007f, -0.0623898f,0.997626f,-0.0291436f, +-6.25f,-0.700022f,0.0f, -0.217067f,0.974987f,-0.0477624f, +0.0f,-0.0957388f,0.0f, -0.117693f,0.990712f,-0.068098f, +6.25f,0.614077f,0.0f, -0.0713214f,0.997305f,0.01722f, +12.5f,0.299109f,0.0f, 0.218606f,0.968641f,0.118094f, +18.75f,-1.71753f,0.0f, 0.0339493f,0.985612f,-0.165579f, +25.0f,-1.12638f,0.0f, -0.0547573f,0.989177f,-0.136126f, +-25.0f,-0.403319f,-6.1875f, -0.1263f,0.989211f,-0.074223f, +-18.75f,-0.0730335f,-6.1875f, 0.0173428f,0.965382f,0.260261f, +-12.5f,-0.450125f,-6.1875f, 0.0658811f,0.875f,0.479619f, +-6.25f,-0.180204f,-6.1875f, 0.0116584f,0.981445f,0.19139f, +0.0f,-0.632679f,-6.1875f, -0.0557983f,0.993041f,-0.103716f, +6.25f,0.308409f,-6.1875f, -0.191898f,0.96766f,-0.163737f, +12.5f,2.5011f,-6.1875f, 0.0758397f,0.996403f,-0.0378189f, +18.75f,-1.69303f,-6.1875f, 0.16761f,0.974057f,0.15205f, +25.0f,-0.141349f,-6.1875f, -0.204846f,0.978471f,0.0251341f, +-25.0f,-1.10316f,-12.375f, -0.0350644f,0.993748f,-0.106001f, +-18.75f,1.06711f,-12.375f, -0.309806f,0.919244f,-0.242922f, +-12.5f,3.61544f,-12.375f, -0.0506281f,0.998702f,-0.00561657f, +-6.25f,1.6504f,-12.375f, 0.322294f,0.937465f,0.131477f, +0.0f,-1.60595f,-12.375f, 0.086016f,0.995916f,0.0274459f, +6.25f,-0.849859f,-12.375f, -0.0332811f,0.997087f,0.0686255f, +12.5f,-0.942201f,-12.375f, -0.153559f,0.982185f,-0.108312f, +18.75f,0.494873f,-12.375f, 0.0753195f,0.981472f,0.176181f, +25.0f,-0.333828f,-12.375f, 0.035057f,0.987194f,0.155624f, +-25.0f,2.1862f,-18.5625f, 0.612899f,0.782306f,0.111138f, +-18.75f,-3.38259f,-18.5625f, 0.0194078f,0.992789f,-0.118297f, +-12.5f,-0.880916f,-18.5625f, -0.282251f,0.949875f,-0.13443f, +-6.25f,0.818158f,-18.5625f, 0.1476f,0.981788f,-0.119612f, +0.0f,-1.48019f,-18.5625f, -0.044551f,0.996013f,-0.0772824f, +6.25f,1.47123f,-18.5625f, -0.117036f,0.97986f,0.161792f, +12.5f,0.164076f,-18.5625f, -0.0340355f,0.978993f,0.201034f, +18.75f,2.14568f,-18.5625f, -0.0439269f,0.994859f,0.0912435f, +25.0f,0.626506f,-18.5625f, 0.208015f,0.968592f,0.136229f, +-25.0f,0.296889f,-24.75f, 0.46973f,0.844327f,-0.257809f, +-18.75f,-3.18022f,-24.75f, -0.0226758f,0.998794f,-0.0435401f, +-12.5f,1.8927f,-24.75f, -0.202772f,0.919836f,0.335836f, +-6.25f,1.46387f,-24.75f, 0.224904f,0.955746f,0.189652f, +0.0f,-2.52726f,-24.75f, -0.0435882f,0.993572f,-0.10447f, +6.25f,1.30397f,-24.75f, -0.28646f,0.956525f,-0.0547707f, +12.5f,1.85812f,-24.75f, 0.0521949f,0.979796f,0.193067f, +18.75f,1.56331f,-24.75f, -0.0270784f,0.999629f,-0.00293115f, +25.0f,1.05366f,-24.75f, 0.161f,0.986887f,-0.0115473f, +}; + +static float LargeMeshTex[] = { +0.125f,0.0f, +0.0f,0.0f, +0.125f,0.125f, +0.0f,0.125f, +0.125f,0.25f, +0.0f,0.25f, +0.125f,0.375f, +0.0f,0.375f, +0.125f,0.5f, +0.0f,0.5f, +0.125f,0.625f, +0.0f,0.625f, +0.125f,0.75f, +0.0f,0.75f, +0.125f,0.875f, +0.0f,0.875f, +0.125f,1.0f, +0.0f,1.0f, +0.25f,0.0f, +0.25f,0.125f, +0.25f,0.25f, +0.25f,0.375f, +0.25f,0.5f, +0.25f,0.625f, +0.25f,0.75f, +0.25f,0.875f, +0.25f,1.0f, +0.375f,0.0f, +0.375f,0.125f, +0.375f,0.25f, +0.375f,0.375f, +0.375f,0.5f, +0.375f,0.625f, +0.375f,0.75f, +0.375f,0.875f, +0.375f,1.0f, +0.5f,0.0f, +0.5f,0.125f, +0.5f,0.25f, +0.5f,0.375f, +0.5f,0.5f, +0.5f,0.625f, +0.5f,0.75f, +0.5f,0.875f, +0.5f,1.0f, +0.625f,0.0f, +0.625f,0.125f, +0.625f,0.25f, +0.625f,0.375f, +0.625f,0.5f, +0.625f,0.625f, +0.625f,0.75f, +0.625f,0.875f, +0.625f,1.0f, +0.75f,0.0f, +0.75f,0.125f, +0.75f,0.25f, +0.75f,0.375f, +0.75f,0.5f, +0.75f,0.625f, +0.75f,0.75f, +0.75f,0.875f, +0.75f,1.0f, +0.875f,0.0f, +0.875f,0.125f, +0.875f,0.25f, +0.875f,0.375f, +0.875f,0.5f, +0.875f,0.625f, +0.875f,0.75f, +0.875f,0.875f, +0.875f,1.0f, +1.0f,0.0f, +1.0f,0.125f, +1.0f,0.25f, +1.0f,0.375f, +1.0f,0.5f, +1.0f,0.625f, +1.0f,0.75f, +1.0f,0.875f, +1.0f,1.0f, +}; + +static unsigned short LargeMeshIdx[] = { +0,1,2, +3,2,1, +2,3,4, +5,4,3, +4,5,6, +7,6,5, +6,7,8, +9,8,7, +8,9,10, +11,10,9, +10,11,12, +13,12,11, +12,13,14, +15,14,13, +14,15,16, +17,16,15, +18,0,19, +2,19,0, +19,2,20, +4,20,2, +20,4,21, +6,21,4, +21,6,22, +8,22,6, +22,8,23, +10,23,8, +23,10,24, +12,24,10, +24,12,25, +14,25,12, +25,14,26, +16,26,14, +27,18,28, +19,28,18, +28,19,29, +20,29,19, +29,20,30, +21,30,20, +30,21,31, +22,31,21, +31,22,32, +23,32,22, +32,23,33, +24,33,23, +33,24,34, +25,34,24, +34,25,35, +26,35,25, +36,27,37, +28,37,27, +37,28,38, +29,38,28, +38,29,39, +30,39,29, +39,30,40, +31,40,30, +40,31,41, +32,41,31, +41,32,42, +33,42,32, +42,33,43, +34,43,33, +43,34,44, +35,44,34, +45,36,46, +37,46,36, +46,37,47, +38,47,37, +47,38,48, +39,48,38, +48,39,49, +40,49,39, +49,40,50, +41,50,40, +50,41,51, +42,51,41, +51,42,52, +43,52,42, +52,43,53, +44,53,43, +54,45,55, +46,55,45, +55,46,56, +47,56,46, +56,47,57, +48,57,47, +57,48,58, +49,58,48, +58,49,59, +50,59,49, +59,50,60, +51,60,50, +60,51,61, +52,61,51, +61,52,62, +53,62,52, +63,54,64, +55,64,54, +64,55,65, +56,65,55, +65,56,66, +57,66,56, +66,57,67, +58,67,57, +67,58,68, +59,68,58, +68,59,69, +60,69,59, +69,60,70, +61,70,60, +70,61,71, +62,71,61, +72,63,73, +64,73,63, +73,64,74, +65,74,64, +74,65,75, +66,75,65, +75,66,76, +67,76,66, +76,67,77, +68,77,67, +77,68,78, +69,78,68, +78,69,79, +70,79,69, +79,70,80, +71,80,70, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/main.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/main.cpp new file mode 100644 index 0000000..9ec4e5e --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/main.cpp @@ -0,0 +1,544 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../common/common.h" +#include "../common/ctrl_func.h" +#include "../common/render_func.h" +#include "../common/perf_func.h" +#include "physics_func.h" +#include "barrel.h" +#include "landscape.h" + +#ifdef _WIN32 + #include + #include +#endif + +// ARA begin insert new code +#ifdef __ANDROID__ + #include + #include +#endif +// ARA end + +#define SAMPLE_NAME "api_physics_effects/5_raycast" + +//#define ENABLE_DEBUG_DRAW + +#ifdef ENABLE_DEBUG_DRAW + #define ENABLE_DEBUG_DRAW_CONTACT + #define ENABLE_DEBUG_DRAW_AABB + #define ENABLE_DEBUG_DRAW_ISLAND +#endif + +static bool s_isRunning = true; + +int sceneId = 0; +bool simulating = false; + +int landscapeMeshId; +int convexMeshId; + +void render(void) +{ + render_begin(); + + const PfxVector3 colorWhite(1.0f); + const PfxVector3 colorGray(0.7f); + + for(int i=0;i -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_DOWN)) { + angX += 0.05f; + if(angX < -1.4f) angX = -1.4f; + if(angX > -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_LEFT)) { + angY -= 0.05f; + } + + if(ctrl_button_pressed(BTN_RIGHT)) { + angY += 0.05f; + } + + if(ctrl_button_pressed(BTN_ZOOM_OUT)) { + r *= 1.1f; + if(r > 500.0f) r = 500.0f; + } + + if(ctrl_button_pressed(BTN_ZOOM_IN)) { + r *= 0.9f; + if(r < 1.0f) r = 1.0f; + } + + if(ctrl_button_pressed(BTN_SCENE_RESET) == BTN_STAT_DOWN) { + physics_create_scene(sceneId); + } + + if(ctrl_button_pressed(BTN_SCENE_NEXT) == BTN_STAT_DOWN) { + physics_create_scene(++sceneId); + } + + if(ctrl_button_pressed(BTN_SIMULATION) == BTN_STAT_DOWN) { + simulating = !simulating; + } + + if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_DOWN) { + simulating = true; + } + else if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_UP || ctrl_button_pressed(BTN_STEP) == BTN_STAT_KEEP) { + simulating = false; + } + + render_set_view_angle(angX,angY,r); +} + +#ifndef _WIN32 + +// ARA begin insert new code +#ifdef __ANDROID__ + +/////////////////////////////////////////////////////////////////////////////// +// sceneChange +// +/// This function is used to change the physics scene on Android devices +/////////////////////////////////////////////////////////////////////////////// +void sceneChange() +{ + physics_create_scene(sceneId++); +} + +#else // __ANDROID__ +// ARA end + +/////////////////////////////////////////////////////////////////////////////// +// Main + +int main(void) +{ + init(); + + physics_create_scene(sceneId); + + printf("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + while (s_isRunning) { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + + shutdown(); + + printf("## %s: FINISHED ##\n", SAMPLE_NAME); + + return 0; +} + +// ARA begin insert new code +#endif // __ANDROID__ +// ARA end + +#else // _WIN32 + +/////////////////////////////////////////////////////////////////////////////// +// WinMain + +extern HDC hDC; +extern HGLRC hRC; +HWND hWnd; +HINSTANCE hInstance; + +void releaseWindow() +{ + if(hRC) { + wglMakeCurrent(0,0); + wglDeleteContext(hRC); + } + + if(hDC) ReleaseDC(hWnd,hDC); + if(hWnd) DestroyWindow(hWnd); + + UnregisterClass(SAMPLE_NAME,hInstance); +} + +LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + switch(uMsg) { + case WM_SYSCOMMAND: + { + switch (wParam) { + case SC_SCREENSAVE: + case SC_MONITORPOWER: + return 0; + } + break; + } + + case WM_CLOSE: + PostQuitMessage(0); + return 0; + + case WM_SIZE: + render_resize(LOWORD(lParam),HIWORD(lParam)); + return 0; + } + + return DefWindowProc(hWnd,uMsg,wParam,lParam); +} + +bool createWindow(char* title, int width, int height) +{ + WNDCLASS wc; + RECT rect; + rect.left=0; + rect.right=width; + rect.top=0; + rect.bottom=height; + + hInstance = GetModuleHandle(NULL); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = SAMPLE_NAME; + + if(!RegisterClass(&wc)) { + return false; + } + + AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE); + + if(!(hWnd=CreateWindowEx(WS_EX_APPWINDOW|WS_EX_WINDOWEDGE,SAMPLE_NAME,title, + WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS|WS_CLIPCHILDREN, + 0,0,rect.right-rect.left,rect.bottom-rect.top, + NULL,NULL,hInstance,NULL))) { + releaseWindow(); + return false; + } + + static PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + 32, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, + 0, 0, 0, 0, + 32, + 0, + 0, + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + if(!(hDC=GetDC(hWnd))) + { + releaseWindow(); + OutputDebugString(""); + return FALSE; + } + + int pixelformat; + + if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 ){ + OutputDebugString("ChoosePixelFormat Failed...."); + return FALSE; + } + + if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE){ + OutputDebugString("SetPixelFormat Failed...."); + return FALSE; + } + + if (!(hRC=wglCreateContext(hDC))){ + OutputDebugString("Creating HGLRC Failed...."); + return FALSE; + } + + // Set Vsync + //BOOL (WINAPI *wglSwapIntervalEXT)(int) = NULL; + + //if(strstr((char*)glGetString( GL_EXTENSIONS ),"WGL_EXT_swap_control")== 0) { + //} + //else { + //wglSwapIntervalEXT = (BOOL (WINAPI*)(int))wglGetProcAddress("wglSwapIntervalEXT"); + //if(wglSwapIntervalEXT) wglSwapIntervalEXT(1); + //} + + wglMakeCurrent(hDC,hRC); + + ShowWindow(hWnd,SW_SHOW); + SetForegroundWindow(hWnd); + SetFocus(hWnd); + + render_resize(width, height); + + glClearColor(0.0f,0.0f,0.0f,0.0f); + glClearDepth(1.0f); + + return TRUE; +} + +int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) +{ + if(!createWindow(SAMPLE_NAME,DISPLAY_WIDTH,DISPLAY_HEIGHT)) { + MessageBox(NULL,"Can't create gl window.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return 0; + } + + init(); + + physics_create_scene(sceneId); + + SCE_PFX_PRINTF("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + MSG msg; + while(s_isRunning) { + if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + if(msg.message==WM_QUIT) { + s_isRunning = false; + } + else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + } + + shutdown(); + + SCE_PFX_PRINTF("## %s: FINISHED ##\n", SAMPLE_NAME); + + releaseWindow(); + return (msg.wParam); +} + +#endif diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/physics.png b/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/physics.png new file mode 100644 index 0000000000000000000000000000000000000000..ffe16ab6d732e2d38176d02af28adac9bcc78cd0 GIT binary patch literal 38457 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 UPM)2|L%;`n^!SnTKTan89~;oU!2kdN literal 0 HcmV?d00001 diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/physics_func.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/physics_func.cpp new file mode 100644 index 0000000..e317df5 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/5_raycast/physics_func.cpp @@ -0,0 +1,1085 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "physics_func.h" +#include "../common/perf_func.h" + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Data + +#define NUM_RIGIDBODIES 500 +#define NUM_JOINTS 500 +#define NUM_CONTACTS 4000 +#define NUM_RAYS 100 + +const float timeStep = 0.016f; +const float separateBias = 0.1f; +int iteration = 5; + +//J ワールドサイズ +//E World size +PfxVector3 worldCenter(0.0f); +PfxVector3 worldExtent(500.0f); + +//J 剛体 +//E Rigid body +PfxRigidState states[NUM_RIGIDBODIES]; +PfxRigidBody bodies[NUM_RIGIDBODIES]; +PfxCollidable collidables[NUM_RIGIDBODIES]; +PfxSolverBody solverBodies[NUM_RIGIDBODIES]; +int numRigidBodies = 0; + +//J 地形を表現するためのラージメッシュ +//E Large mesh for representing a landscape +#include "landscape.h" +PfxLargeTriMesh gLargeMesh; + +//J 凸メッシュ +//E Convex Mesh +#include "barrel.h" +PfxConvexMesh gConvex; + +//J プロキシ +//E Proxies +PfxBroadphaseProxy proxies[6][NUM_RIGIDBODIES]; // shared by simulation and raycast + +//J ジョイント +//E Joint +PfxConstraintPair jointPairs[NUM_JOINTS]; +PfxJoint joints[NUM_JOINTS]; +int numJoints = 0; + +//J ペア +//E Pairs +unsigned int pairSwap; +unsigned int numPairs[2]; +PfxBroadphasePair pairsBuff[2][NUM_CONTACTS]; + +//J コンタクト +//E Contacts +PfxContactManifold contacts[NUM_CONTACTS]; +int numContacts; + +PfxUInt32 contactIdPool[NUM_CONTACTS]; +int numContactIdPool; + +//J シミュレーションアイランド +//E Island generation +PfxIsland *island=NULL; +PfxUInt8 SCE_PFX_ALIGNED(16) islandBuff[32*NUM_RIGIDBODIES]; // Island buffer should be 32 * the number of rigid bodies. + +//J スリープ制御 +//E Sleep control +/* + A sleeping object wakes up, when + * a new pair related to this rigid body is created + * a pair releated to this rigid body is removed + * a rigid body's velocity or position are updated + */ + +//J スリープに入るカウント +//E Count to enter sleeping +const PfxUInt32 sleepCount = 180; + +//J 速度が閾値以下ならばスリープカウントが増加 +//E If velocity is under the following value, sleep count is increased. +const PfxFloat sleepVelocity = 0.1f; + +//J 一時バッファ +//E Temporary buffers +#define POOL_BYTES (5*1024*1024) +unsigned char SCE_PFX_ALIGNED(128) poolBuff[POOL_BYTES]; + +//J 一時バッファ用スタックアロケータ +//E Stack allocator for temporary buffers +PfxHeapManager pool(poolBuff,POOL_BYTES); + +//J レイ +//E Ray +PfxRayInput SCE_PFX_ALIGNED(128) rayInputs[NUM_RAYS]; +PfxRayOutput SCE_PFX_ALIGNED(128) rayOutputs[NUM_RAYS]; +int numRays; + +/* + doAreaRaycastがtrueの場合、指定された領域内の剛体のみ判定対象とする +*/ +bool doAreaRaycast; +PfxVector3 areaCenter(0.0f); +PfxVector3 areaExtent(5.0f); + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Function + +int frame = 0; + +void broadphase() +{ + pairSwap = 1-pairSwap; + + unsigned int &numPreviousPairs = numPairs[1-pairSwap]; + unsigned int &numCurrentPairs = numPairs[pairSwap]; + PfxBroadphasePair *previousPairs = pairsBuff[1-pairSwap]; + PfxBroadphasePair *currentPairs = pairsBuff[pairSwap]; + + //J 剛体が最も分散している軸を見つける + //E Find the axis along which all rigid bodies are most widely positioned + int axis = 0; + { + PfxVector3 s(0.0f),s2(0.0f); + for(int i=0;i v[0]) axis = 1; + if(v[2] > v[axis]) axis = 2; + } + + //J ブロードフェーズプロキシの更新 + //E Create broadpahse proxies + { + //J レイキャストと共用するため、全ての軸に対するプロキシ配列を作成する + //E To share with ray casting, create proxy arrays for all axis + + PfxUpdateBroadphaseProxiesParam param; + param.workBytes = pfxGetWorkBytesOfUpdateBroadphaseProxies(numRigidBodies); + param.workBuff = pool.allocate(param.workBytes,128); + param.numRigidBodies = numRigidBodies; + param.offsetRigidStates = states; + param.offsetCollidables = collidables; + param.proxiesX = proxies[0]; + param.proxiesY = proxies[1]; + param.proxiesZ = proxies[2]; + param.proxiesXb = proxies[3]; + param.proxiesYb = proxies[4]; + param.proxiesZb = proxies[5]; + param.worldCenter = worldCenter; + param.worldExtent = worldExtent; + + PfxUpdateBroadphaseProxiesResult result; + + int ret = pfxUpdateBroadphaseProxies(param,result); + if(ret != SCE_PFX_OK) SCE_PFX_PRINTF("pfxUpdateBroadphaseProxies failed %d\n",ret); + + pool.deallocate(param.workBuff); + } + + //J 交差ペア探索 + //E Find overlapped pairs + { + PfxFindPairsParam findPairsParam; + findPairsParam.pairBytes = pfxGetPairBytesOfFindPairs(NUM_CONTACTS); + findPairsParam.pairBuff = pool.allocate(findPairsParam.pairBytes); + findPairsParam.workBytes = pfxGetWorkBytesOfFindPairs(NUM_CONTACTS); + findPairsParam.workBuff = pool.allocate(findPairsParam.workBytes); + findPairsParam.proxies = proxies[axis]; + findPairsParam.numProxies = numRigidBodies; + findPairsParam.maxPairs = NUM_CONTACTS; + findPairsParam.axis = axis; + + PfxFindPairsResult findPairsResult; + + int ret = pfxFindPairs(findPairsParam,findPairsResult); + if(ret != SCE_PFX_OK) SCE_PFX_PRINTF("pfxFindPairs failed %d\n",ret); + + pool.deallocate(findPairsParam.workBuff); + + //J 交差ペア合成 + //E Decompose overlapped pairs into 3 arrays + PfxDecomposePairsParam decomposePairsParam; + decomposePairsParam.pairBytes = pfxGetPairBytesOfDecomposePairs(numPreviousPairs,findPairsResult.numPairs); + decomposePairsParam.pairBuff = pool.allocate(decomposePairsParam.pairBytes); + decomposePairsParam.workBytes = pfxGetWorkBytesOfDecomposePairs(numPreviousPairs,findPairsResult.numPairs); + decomposePairsParam.workBuff = pool.allocate(decomposePairsParam.workBytes); + decomposePairsParam.previousPairs = previousPairs; + decomposePairsParam.numPreviousPairs = numPreviousPairs; + decomposePairsParam.currentPairs = findPairsResult.pairs; // Set pairs from pfxFindPairs() + decomposePairsParam.numCurrentPairs = findPairsResult.numPairs; // Set the number of pairs from pfxFindPairs() + + PfxDecomposePairsResult decomposePairsResult; + + ret = pfxDecomposePairs(decomposePairsParam,decomposePairsResult); + if(ret != SCE_PFX_OK) SCE_PFX_PRINTF("pfxDecomposePairs failed %d\n",ret); + + pool.deallocate(decomposePairsParam.workBuff); + + PfxBroadphasePair *outNewPairs = decomposePairsResult.outNewPairs; + PfxBroadphasePair *outKeepPairs = decomposePairsResult.outKeepPairs; + PfxBroadphasePair *outRemovePairs = decomposePairsResult.outRemovePairs; + PfxUInt32 numOutNewPairs = decomposePairsResult.numOutNewPairs; + PfxUInt32 numOutKeepPairs = decomposePairsResult.numOutKeepPairs; + PfxUInt32 numOutRemovePairs = decomposePairsResult.numOutRemovePairs; + + //J 廃棄ペアのコンタクトをプールに戻す + //E Put removed contacts into the contact pool + for(PfxUInt32 i=0;i 0) { + cId = contactIdPool[--numContactIdPool]; + } + else { + cId = numContacts++; + } + if(cId >= NUM_CONTACTS) { + cId = 0; + } + SCE_PFX_ASSERT(cId < NUM_CONTACTS); + pfxSetContactId(outNewPairs[i],cId); + PfxContactManifold &contact = contacts[cId]; + contact.reset(pfxGetObjectIdA(outNewPairs[i]),pfxGetObjectIdB(outNewPairs[i])); + + //J 寝てる剛体を起こす + //E Wake up sleeping rigid bodies + PfxRigidState &stateA = states[pfxGetObjectIdA(outNewPairs[i])]; + PfxRigidState &stateB = states[pfxGetObjectIdB(outNewPairs[i])]; + if(stateA.isAsleep()) { + stateA.wakeup(); + } + if(stateB.isAsleep()) { + stateB.wakeup(); + } + } + + //J 新規ペアと維持ペアを合成 + //E Merge 'new' and 'keep' pairs + numCurrentPairs = 0; + for(PfxUInt32 i=0;i sleepCount) { + numCanSleep++; + } + } + } + } + + // Deactivate Island + if(numCanSleep > 0 && numCanSleep == numActive + numSleep) { + PfxIslandUnit *islandUnit = pfxGetFirstUnitInIsland(island,(PfxUInt32)i); + for(;islandUnit!=NULL;islandUnit=pfxGetNextUnitInIsland(islandUnit)) { + if(!(SCE_PFX_MOTION_MASK_CAN_SLEEP(states[pfxGetUnitId(islandUnit)].getMotionType()))) continue; + states[pfxGetUnitId(islandUnit)].sleep(); + } + } + + // Activate Island + else if(numSleep > 0 && numActive > 0) { + PfxIslandUnit *islandUnit = pfxGetFirstUnitInIsland(island,(PfxUInt32)i); + for(;islandUnit!=NULL;islandUnit=pfxGetNextUnitInIsland(islandUnit)) { + if(!(SCE_PFX_MOTION_MASK_CAN_SLEEP(states[pfxGetUnitId(islandUnit)].getMotionType()))) continue; + states[pfxGetUnitId(islandUnit)].wakeup(); + } + } + } + } +} + +void integrate() +{ + PfxUpdateRigidStatesParam param; + param.states = states; + param.bodies = bodies; + param.numRigidBodies = numRigidBodies; + param.timeStep = timeStep; + + pfxUpdateRigidStates(param); +} + +int gatherBroadphaseProxiesInArea(const PfxVector3 ¢er,const PfxVector3 &extent) +{ + PfxUpdateBroadphaseProxiesParam param; + param.workBytes = pfxGetWorkBytesOfUpdateBroadphaseProxies(numRigidBodies); + param.workBuff = pool.allocate(param.workBytes,128); + param.numRigidBodies = numRigidBodies; + param.offsetRigidStates = states; + param.offsetCollidables = collidables; + param.proxiesX = proxies[0]; + param.proxiesY = proxies[1]; + param.proxiesZ = proxies[2]; + param.proxiesXb = proxies[3]; + param.proxiesYb = proxies[4]; + param.proxiesZb = proxies[5]; + param.worldCenter = center; + param.worldExtent = extent; + param.outOfWorldBehavior = SCE_PFX_OUT_OF_WORLD_BEHAVIOR_REMOVE_PROXY; + + PfxUpdateBroadphaseProxiesResult result; + + int ret = pfxUpdateBroadphaseProxies(param,result); + if(ret != SCE_PFX_OK) SCE_PFX_PRINTF("pfxUpdateBroadphaseProxies failed %d\n",ret); + + pool.deallocate(param.workBuff); + + return numRigidBodies - result.numOutOfWorldProxies; +} + +void castRays() +{ + PfxRayCastParam param; + + if(doAreaRaycast) { + static PfxFloat deltaRotY = 0.0f; + PfxQuat rotY = PfxQuat::rotationY(deltaRotY); + areaCenter = rotate(rotY,PfxVector3(15.0f,0.0f,0.0f)); + deltaRotY += 0.02f; + + int num = gatherBroadphaseProxiesInArea(areaCenter,areaExtent); + param.offsetRigidStates = states; + param.offsetCollidables = collidables; + param.proxiesX = proxies[0]; + param.proxiesY = proxies[1]; + param.proxiesZ = proxies[2]; + param.proxiesXb = proxies[3]; + param.proxiesYb = proxies[4]; + param.proxiesZb = proxies[5]; + param.numProxies = num; + param.rangeCenter = areaCenter; + param.rangeExtent = areaExtent; + } + else { + param.offsetRigidStates = states; + param.offsetCollidables = collidables; + param.proxiesX = proxies[0]; + param.proxiesY = proxies[1]; + param.proxiesZ = proxies[2]; + param.proxiesXb = proxies[3]; + param.proxiesYb = proxies[4]; + param.proxiesZb = proxies[5]; + param.numProxies = numRigidBodies; + param.rangeCenter = worldCenter; + param.rangeExtent = worldExtent; + } + + pfxCastRays(rayInputs,rayOutputs,numRays,param); +} + +void physics_simulate() +{ + PfxPerfCounter pc; + + for(int i=1;i 0) { + pfxReleaseLargeTriMesh(gLargeMesh); + } + + PfxInt32 ret = pfxCreateLargeTriMesh(gLargeMesh,param); + if(ret != SCE_PFX_OK) { + SCE_PFX_PRINTF("Can't create large mesh.\n"); + } + + int id = numRigidBodies++; + PfxShape shape; + shape.reset(); + shape.setLargeTriMesh(&gLargeMesh); + collidables[id].reset(); + collidables[id].addShape(shape); + collidables[id].finish(); + bodies[id].reset(); + states[id].reset(); + states[id].setPosition(PfxVector3(0.0f,0.0f,0.0f)); + states[id].setMotionType(kPfxMotionTypeFixed); + states[id].setRigidBodyId(id); +} + +void initRays(const PfxVector3 &p1,const PfxVector3 &p2) +{ + numRays = NUM_RAYS; + PfxQuat rot = PfxQuat::rotationY(2.0f*SCE_PFX_PI/(float)numRays); + PfxVector3 startPosition = p1; + PfxVector3 targetPosition = p2; + + for(int i=0;i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/CMakeLists.txt b/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/CMakeLists.txt new file mode 100644 index 0000000..4145941 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 2.4) + + +#this line has to appear before 'PROJECT' in order to be able to disable incremental linking +SET(MSVC_INCREMENTAL_DEFAULT ON) + +PROJECT(App_6_Joint) + + +IF (NOT CMAKE_BUILD_TYPE) +# SET(CMAKE_BUILD_TYPE "Debug") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF (NOT CMAKE_BUILD_TYPE) + + +OPTION(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC Runtime Library DLL (/MD or /MDd)" ON) +OPTION(USE_MSVC_INCREMENTAL_LINKING "Use MSVC Incremental Linking" OFF) + + +IF(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + + +SET(App_6_Joint_SRCS + main.cpp + physics_func.cpp + ../common/ctrl_func.win32.cpp + ../common/perf_func.win32.cpp + ../common/render_func.win32.cpp +) + + +SET(App_6_Joint_HDRS + physics_func.h + landscape.h + barrel.h + ../common/render_func.h + ../common/common.h + ../common/ctrl_func.h + ../common/perf_func.h +) + + +INCLUDE_DIRECTORIES( + ${PHYSICS_EFFECTS_SOURCE_DIR}/include +# ${VECTOR_MATH_INCLUDE} +) + +#LINK_DIRECTORIES( +# +#) + +#ADD_DEFINITIONS(-DUNICODE) +#ADD_DEFINITIONS(-D_UNICODE) + +ADD_EXECUTABLE(App_6_Joint WIN32 + ${App_6_Joint_SRCS} + ${App_6_Joint_HDRS} +) +TARGET_LINK_LIBRARIES(App_6_Joint + PfxBaseLevel + PfxLowLevel + PfxUtil + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} +) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(App_6_Joint PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(App_6_Joint PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(App_6_Joint PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF() + + + + \ No newline at end of file diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/barrel.h b/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/barrel.h new file mode 100644 index 0000000..6574fa8 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/barrel.h @@ -0,0 +1,202 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define BarrelVtxCount 57 +#define BarrelIdxCount 180 + +static float BarrelVtx[] = { +0.0f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +-0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +0.0f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +-0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.957307f,-0.289072f,0.0f, +0.404509f,0.0f,-0.293893f, 0.809017f,0.0f,-0.587785f, +0.5f,0.0f,0.0f, 1.0f,0.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.774478f,-0.289072f,-0.562691f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +-0.154509f,0.0f,-0.475528f, -0.309017f,0.0f,-0.951057f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +-0.107853f,-0.5f,-0.331936f, -0.295824f,-0.289072f,-0.910453f, +-0.404509f,0.0f,-0.293893f, -0.809017f,0.0f,-0.587785f, +-0.282362f,-0.5f,-0.205148f, -0.774478f,-0.289072f,-0.562691f, +-0.5f,0.0f,0.0f, -1.0f,0.0f,0.0f, +-0.349018f,-0.5f,0.0f, -0.957307f,-0.289072f,0.0f, +-0.404508f,0.0f,0.293893f, -0.809017f,0.0f,0.587785f, +-0.282362f,-0.5f,0.205148f, -0.774478f,-0.289072f,0.562691f, +-0.154509f,0.0f,0.475528f, -0.309017f,0.0f,0.951056f, +-0.107853f,-0.5f,0.331936f, -0.295824f,-0.289072f,0.910453f, +0.154509f,0.0f,0.475528f, 0.309017f,0.0f,0.951056f, +0.107853f,-0.5f,0.331936f, 0.295824f,-0.289072f,0.910453f, +0.404509f,0.0f,0.293892f, 0.809017f,0.0f,0.587785f, +0.282362f,-0.5f,0.205148f, 0.774478f,-0.289072f,0.562691f, +0.282362f,0.5f,-0.205148f, 0.774478f,0.289072f,-0.562691f, +0.349018f,0.5f,0.0f, 0.957307f,0.289072f,0.0f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.107853f,0.5f,-0.331936f, -0.295824f,0.289072f,-0.910453f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.282362f,0.5f,-0.205148f, -0.774478f,0.289072f,-0.562691f, +-0.349018f,0.5f,0.0f, -0.957307f,0.289072f,0.0f, +-0.282362f,0.5f,0.205148f, -0.774478f,0.289072f,0.562691f, +-0.107853f,0.5f,0.331936f, -0.295824f,0.289072f,0.910453f, +0.107853f,0.5f,0.331936f, 0.295824f,0.289072f,0.910453f, +0.282362f,0.5f,0.205148f, 0.774478f,0.289072f,0.562691f, +}; + +static float BarrelTex[] = { +0.0f,0.5f, +0.0f,0.85f, +0.0f,0.75f, +0.0f,0.95f, +0.0f,0.05f, +0.0f,-0.05f, +0.0f,0.15f, +0.0f,0.25f, +0.0f,0.35f, +0.0f,0.45f, +0.0f,0.55f, +0.0f,0.65f, +1.0f,0.5f, +1.0f,0.75f, +1.0f,0.85f, +1.0f,0.95f, +1.0f,-0.05f, +1.0f,0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +0.0f,0.75f, +0.5f,0.85f, +0.5f,0.75f, +0.0f,0.85f, +0.5f,0.95f, +0.0f,0.95f, +0.0f,-0.05f, +0.5f,0.05f, +0.5f,-0.05f, +0.0f,0.05f, +0.5f,0.15f, +0.0f,0.15f, +0.5f,0.25f, +0.0f,0.25f, +0.5f,0.35f, +0.0f,0.35f, +0.5f,0.45f, +0.0f,0.45f, +0.5f,0.55f, +0.0f,0.55f, +0.5f,0.65f, +0.0f,0.65f, +1.0f,0.85f, +1.0f,0.75f, +1.0f,0.95f, +1.0f,0.05f, +1.0f,-0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +}; + +static unsigned short BarrelIdx[] = { +0,1,2, +0,3,1, +0,4,5, +0,6,4, +0,7,6, +0,8,7, +0,9,8, +0,10,9, +0,11,10, +0,2,11, +12,13,14, +12,14,15, +12,16,17, +12,17,18, +12,18,19, +12,19,20, +12,20,21, +12,21,22, +12,22,23, +12,23,13, +24,25,26, +24,27,25, +27,28,25, +27,29,28, +30,31,32, +30,33,31, +33,34,31, +33,35,34, +35,36,34, +35,37,36, +37,38,36, +37,39,38, +39,40,38, +39,41,40, +41,42,40, +41,43,42, +43,44,42, +43,45,44, +45,26,44, +45,24,26, +26,46,47, +26,25,46, +25,48,46, +25,28,48, +32,49,50, +32,31,49, +31,51,49, +31,34,51, +34,52,51, +34,36,52, +36,53,52, +36,38,53, +38,54,53, +38,40,54, +40,55,54, +40,42,55, +42,56,55, +42,44,56, +44,47,56, +44,26,47, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/landscape.h b/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/landscape.h new file mode 100644 index 0000000..00f6cff --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/landscape.h @@ -0,0 +1,318 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define LargeMeshVtxCount 81 +#define LargeMeshIdxCount 384 + +static float LargeMeshVtx[] = { +-25.0f,-2.19407f,18.5625f, 0.232976f,0.967754f,0.0957829f, +-25.0f,0.0644502f,24.75f, 0.188094f,0.871343f,-0.45319f, +-18.75f,-4.50287f,18.5625f, -0.0716098f,0.995449f,0.0628767f, +-18.75f,-0.39999f,24.75f, -0.0602794f,0.895848f,-0.440253f, +-12.5f,-1.2166f,18.5625f, -0.269469f,0.961403f,0.0555879f, +-12.5f,-0.942431f,24.75f, -0.0997841f,0.993258f,0.0589987f, +-6.25f,1.93598f,18.5625f, -0.283933f,0.956351f,-0.0691025f, +-6.25f,-0.445954f,24.75f, -0.180725f,0.942766f,0.280233f, +0.0f,2.76983f,18.5625f, 0.171645f,0.984908f,0.0222501f, +0.0f,2.76642f,24.75f, 0.0784993f,0.995428f,-0.0544117f, +6.25f,-2.53736f,18.5625f, 0.248298f,0.965028f,0.0840741f, +6.25f,-0.915645f,24.75f, 0.164311f,0.945856f,-0.279926f, +12.5f,-1.60054f,18.5625f, -0.180435f,0.983586f,0.00115547f, +12.5f,0.831925f,24.75f, -0.0692495f,0.964821f,-0.253623f, +18.75f,-0.800282f,18.5625f, 0.10755f,0.951538f,0.288112f, +18.75f,-1.47284f,24.75f, 0.232178f,0.972664f,0.00429361f, +25.0f,-2.78379f,18.5625f, 0.1833f,0.937477f,0.295867f, +25.0f,-0.967508f,24.75f, -0.0773477f,0.956641f,-0.280812f, +-25.0f,-0.352038f,12.375f, -0.192222f,0.972435f,0.131987f, +-18.75f,0.681228f,12.375f, -0.107779f,0.962569f,0.248686f, +-12.5f,2.72065f,12.375f, 0.0520846f,0.993034f,0.105692f, +-6.25f,-1.78776f,12.375f, -0.0133223f,0.99674f,-0.0795754f, +0.0f,1.57707f,12.375f, -0.129025f,0.969662f,-0.207627f, +6.25f,0.424356f,12.375f, 0.180995f,0.97074f,0.157815f, +12.5f,0.283234f,12.375f, -0.16285f,0.973539f,0.160316f, +18.75f,2.57015f,12.375f, -0.165454f,0.978339f,0.124408f, +25.0f,3.07363f,12.375f, -0.00454559f,0.988151f,0.153417f, +-25.0f,-0.893751f,6.1875f, -0.0836251f,0.990084f,-0.112876f, +-18.75f,0.930932f,6.1875f, 0.00269413f,0.971838f,-0.235633f, +-12.5f,-0.684529f,6.1875f, -0.010319f,0.927048f,-0.3748f, +-6.25f,-0.661383f,6.1875f, 0.012265f,0.999875f,-0.00994222f, +0.0f,0.385718f,6.1875f, -0.15435f,0.984937f,-0.0779465f, +6.25f,0.589796f,6.1875f, 0.0241717f,0.999582f,-0.0158589f, +12.5f,0.47454f,6.1875f, -0.017184f,0.997953f,-0.0616073f, +18.75f,1.59939f,6.1875f, -0.0902706f,0.957309f,-0.274609f, +25.0f,1.13434f,6.1875f, 0.0346006f,0.957441f,-0.286547f, +-25.0f,0.74548f,0.0f, 0.329903f,0.930812f,0.157334f, +-18.75f,-2.47437f,0.0f, 0.247844f,0.968142f,0.0357041f, +-12.5f,-4.16309f,1.81975e-007f, -0.0623898f,0.997626f,-0.0291436f, +-6.25f,-0.700022f,0.0f, -0.217067f,0.974987f,-0.0477624f, +0.0f,-0.0957388f,0.0f, -0.117693f,0.990712f,-0.068098f, +6.25f,0.614077f,0.0f, -0.0713214f,0.997305f,0.01722f, +12.5f,0.299109f,0.0f, 0.218606f,0.968641f,0.118094f, +18.75f,-1.71753f,0.0f, 0.0339493f,0.985612f,-0.165579f, +25.0f,-1.12638f,0.0f, -0.0547573f,0.989177f,-0.136126f, +-25.0f,-0.403319f,-6.1875f, -0.1263f,0.989211f,-0.074223f, +-18.75f,-0.0730335f,-6.1875f, 0.0173428f,0.965382f,0.260261f, +-12.5f,-0.450125f,-6.1875f, 0.0658811f,0.875f,0.479619f, +-6.25f,-0.180204f,-6.1875f, 0.0116584f,0.981445f,0.19139f, +0.0f,-0.632679f,-6.1875f, -0.0557983f,0.993041f,-0.103716f, +6.25f,0.308409f,-6.1875f, -0.191898f,0.96766f,-0.163737f, +12.5f,2.5011f,-6.1875f, 0.0758397f,0.996403f,-0.0378189f, +18.75f,-1.69303f,-6.1875f, 0.16761f,0.974057f,0.15205f, +25.0f,-0.141349f,-6.1875f, -0.204846f,0.978471f,0.0251341f, +-25.0f,-1.10316f,-12.375f, -0.0350644f,0.993748f,-0.106001f, +-18.75f,1.06711f,-12.375f, -0.309806f,0.919244f,-0.242922f, +-12.5f,3.61544f,-12.375f, -0.0506281f,0.998702f,-0.00561657f, +-6.25f,1.6504f,-12.375f, 0.322294f,0.937465f,0.131477f, +0.0f,-1.60595f,-12.375f, 0.086016f,0.995916f,0.0274459f, +6.25f,-0.849859f,-12.375f, -0.0332811f,0.997087f,0.0686255f, +12.5f,-0.942201f,-12.375f, -0.153559f,0.982185f,-0.108312f, +18.75f,0.494873f,-12.375f, 0.0753195f,0.981472f,0.176181f, +25.0f,-0.333828f,-12.375f, 0.035057f,0.987194f,0.155624f, +-25.0f,2.1862f,-18.5625f, 0.612899f,0.782306f,0.111138f, +-18.75f,-3.38259f,-18.5625f, 0.0194078f,0.992789f,-0.118297f, +-12.5f,-0.880916f,-18.5625f, -0.282251f,0.949875f,-0.13443f, +-6.25f,0.818158f,-18.5625f, 0.1476f,0.981788f,-0.119612f, +0.0f,-1.48019f,-18.5625f, -0.044551f,0.996013f,-0.0772824f, +6.25f,1.47123f,-18.5625f, -0.117036f,0.97986f,0.161792f, +12.5f,0.164076f,-18.5625f, -0.0340355f,0.978993f,0.201034f, +18.75f,2.14568f,-18.5625f, -0.0439269f,0.994859f,0.0912435f, +25.0f,0.626506f,-18.5625f, 0.208015f,0.968592f,0.136229f, +-25.0f,0.296889f,-24.75f, 0.46973f,0.844327f,-0.257809f, +-18.75f,-3.18022f,-24.75f, -0.0226758f,0.998794f,-0.0435401f, +-12.5f,1.8927f,-24.75f, -0.202772f,0.919836f,0.335836f, +-6.25f,1.46387f,-24.75f, 0.224904f,0.955746f,0.189652f, +0.0f,-2.52726f,-24.75f, -0.0435882f,0.993572f,-0.10447f, +6.25f,1.30397f,-24.75f, -0.28646f,0.956525f,-0.0547707f, +12.5f,1.85812f,-24.75f, 0.0521949f,0.979796f,0.193067f, +18.75f,1.56331f,-24.75f, -0.0270784f,0.999629f,-0.00293115f, +25.0f,1.05366f,-24.75f, 0.161f,0.986887f,-0.0115473f, +}; + +static float LargeMeshTex[] = { +0.125f,0.0f, +0.0f,0.0f, +0.125f,0.125f, +0.0f,0.125f, +0.125f,0.25f, +0.0f,0.25f, +0.125f,0.375f, +0.0f,0.375f, +0.125f,0.5f, +0.0f,0.5f, +0.125f,0.625f, +0.0f,0.625f, +0.125f,0.75f, +0.0f,0.75f, +0.125f,0.875f, +0.0f,0.875f, +0.125f,1.0f, +0.0f,1.0f, +0.25f,0.0f, +0.25f,0.125f, +0.25f,0.25f, +0.25f,0.375f, +0.25f,0.5f, +0.25f,0.625f, +0.25f,0.75f, +0.25f,0.875f, +0.25f,1.0f, +0.375f,0.0f, +0.375f,0.125f, +0.375f,0.25f, +0.375f,0.375f, +0.375f,0.5f, +0.375f,0.625f, +0.375f,0.75f, +0.375f,0.875f, +0.375f,1.0f, +0.5f,0.0f, +0.5f,0.125f, +0.5f,0.25f, +0.5f,0.375f, +0.5f,0.5f, +0.5f,0.625f, +0.5f,0.75f, +0.5f,0.875f, +0.5f,1.0f, +0.625f,0.0f, +0.625f,0.125f, +0.625f,0.25f, +0.625f,0.375f, +0.625f,0.5f, +0.625f,0.625f, +0.625f,0.75f, +0.625f,0.875f, +0.625f,1.0f, +0.75f,0.0f, +0.75f,0.125f, +0.75f,0.25f, +0.75f,0.375f, +0.75f,0.5f, +0.75f,0.625f, +0.75f,0.75f, +0.75f,0.875f, +0.75f,1.0f, +0.875f,0.0f, +0.875f,0.125f, +0.875f,0.25f, +0.875f,0.375f, +0.875f,0.5f, +0.875f,0.625f, +0.875f,0.75f, +0.875f,0.875f, +0.875f,1.0f, +1.0f,0.0f, +1.0f,0.125f, +1.0f,0.25f, +1.0f,0.375f, +1.0f,0.5f, +1.0f,0.625f, +1.0f,0.75f, +1.0f,0.875f, +1.0f,1.0f, +}; + +static unsigned short LargeMeshIdx[] = { +0,1,2, +3,2,1, +2,3,4, +5,4,3, +4,5,6, +7,6,5, +6,7,8, +9,8,7, +8,9,10, +11,10,9, +10,11,12, +13,12,11, +12,13,14, +15,14,13, +14,15,16, +17,16,15, +18,0,19, +2,19,0, +19,2,20, +4,20,2, +20,4,21, +6,21,4, +21,6,22, +8,22,6, +22,8,23, +10,23,8, +23,10,24, +12,24,10, +24,12,25, +14,25,12, +25,14,26, +16,26,14, +27,18,28, +19,28,18, +28,19,29, +20,29,19, +29,20,30, +21,30,20, +30,21,31, +22,31,21, +31,22,32, +23,32,22, +32,23,33, +24,33,23, +33,24,34, +25,34,24, +34,25,35, +26,35,25, +36,27,37, +28,37,27, +37,28,38, +29,38,28, +38,29,39, +30,39,29, +39,30,40, +31,40,30, +40,31,41, +32,41,31, +41,32,42, +33,42,32, +42,33,43, +34,43,33, +43,34,44, +35,44,34, +45,36,46, +37,46,36, +46,37,47, +38,47,37, +47,38,48, +39,48,38, +48,39,49, +40,49,39, +49,40,50, +41,50,40, +50,41,51, +42,51,41, +51,42,52, +43,52,42, +52,43,53, +44,53,43, +54,45,55, +46,55,45, +55,46,56, +47,56,46, +56,47,57, +48,57,47, +57,48,58, +49,58,48, +58,49,59, +50,59,49, +59,50,60, +51,60,50, +60,51,61, +52,61,51, +61,52,62, +53,62,52, +63,54,64, +55,64,54, +64,55,65, +56,65,55, +65,56,66, +57,66,56, +66,57,67, +58,67,57, +67,58,68, +59,68,58, +68,59,69, +60,69,59, +69,60,70, +61,70,60, +70,61,71, +62,71,61, +72,63,73, +64,73,63, +73,64,74, +65,74,64, +74,65,75, +66,75,65, +75,66,76, +67,76,66, +76,67,77, +68,77,67, +77,68,78, +69,78,68, +78,69,79, +70,79,69, +79,70,80, +71,80,70, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/main.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/main.cpp new file mode 100644 index 0000000..e78f4fa --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/main.cpp @@ -0,0 +1,513 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../common/common.h" +#include "../common/ctrl_func.h" +#include "../common/render_func.h" +#include "../common/perf_func.h" +#include "physics_func.h" + +#ifdef _WIN32 + #include + #include +#endif + +// ARA begin insert new code +#ifdef __ANDROID__ + #include + #include +#endif +// ARA end + +#define SAMPLE_NAME "api_physics_effects/6_joint" + +//#define ENABLE_DEBUG_DRAW + +#ifdef ENABLE_DEBUG_DRAW + #define ENABLE_DEBUG_DRAW_CONTACT + #define ENABLE_DEBUG_DRAW_AABB + #define ENABLE_DEBUG_DRAW_ISLAND +#endif + +static bool s_isRunning = true; + +int sceneId = 0; +bool simulating = false; + +void render(void) +{ + render_begin(); + + const PfxVector3 colorWhite(1.0f); + const PfxVector3 colorGray(0.7f); + + for(int i=0;i -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_DOWN)) { + angX += 0.05f; + if(angX < -1.4f) angX = -1.4f; + if(angX > -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_LEFT)) { + angY -= 0.05f; + } + + if(ctrl_button_pressed(BTN_RIGHT)) { + angY += 0.05f; + } + + if(ctrl_button_pressed(BTN_ZOOM_OUT)) { + r *= 1.1f; + if(r > 500.0f) r = 500.0f; + } + + if(ctrl_button_pressed(BTN_ZOOM_IN)) { + r *= 0.9f; + if(r < 1.0f) r = 1.0f; + } + + if(ctrl_button_pressed(BTN_SCENE_RESET) == BTN_STAT_DOWN) { + physics_create_scene(sceneId); + } + + if(ctrl_button_pressed(BTN_SCENE_NEXT) == BTN_STAT_DOWN) { + physics_create_scene(++sceneId); + } + + if(ctrl_button_pressed(BTN_SIMULATION) == BTN_STAT_DOWN) { + simulating = !simulating; + } + + if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_DOWN) { + simulating = true; + } + else if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_UP || ctrl_button_pressed(BTN_STEP) == BTN_STAT_KEEP) { + simulating = false; + } + + int w,h; + render_get_screent_size(w,h); + ctrl_set_screen_size(w,h); + + static PfxVector3 pickPos(0.0f); + + if(ctrl_button_pressed(BTN_PICK) == BTN_STAT_DOWN) { + int sx,sy; + ctrl_get_cursor_position(sx,sy); + PfxVector3 wp1((float)sx,(float)sy,0.0f); + PfxVector3 wp2((float)sx,(float)sy,1.0f); + wp1 = render_get_world_position(wp1); + wp2 = render_get_world_position(wp2); + pickPos = physics_pick_start(wp1,wp2); + } + else if(ctrl_button_pressed(BTN_PICK) == BTN_STAT_KEEP) { + int sx,sy; + ctrl_get_cursor_position(sx,sy); + PfxVector3 sp = render_get_screen_position(pickPos); + PfxVector3 wp((float)sx,(float)sy,sp[2]); + wp = render_get_world_position(wp); + physics_pick_update(wp); + } + else if(ctrl_button_pressed(BTN_PICK) == BTN_STAT_UP) { + physics_pick_end(); + } + + render_set_view_angle(angX,angY,r); +} + +#ifndef _WIN32 + +// ARA begin insert new code +#ifdef __ANDROID__ + +/////////////////////////////////////////////////////////////////////////////// +// sceneChange +// +/// This function is used to change the physics scene on Android devices +/////////////////////////////////////////////////////////////////////////////// +void sceneChange() +{ + physics_create_scene(sceneId++); +} + +#else // __ANDROID__ +// ARA end + +/////////////////////////////////////////////////////////////////////////////// +// Main + +int main(void) +{ + init(); + + physics_create_scene(sceneId); + + printf("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + while (s_isRunning) { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + + shutdown(); + + printf("## %s: FINISHED ##\n", SAMPLE_NAME); + + return 0; +} + +// ARA begin insert new code +#endif // __ANDROID__ +// ARA end + +#else // _WIN32 + +/////////////////////////////////////////////////////////////////////////////// +// WinMain + +extern HDC hDC; +extern HGLRC hRC; +HWND hWnd; +HINSTANCE hInstance; + +void releaseWindow() +{ + if(hRC) { + wglMakeCurrent(0,0); + wglDeleteContext(hRC); + } + + if(hDC) ReleaseDC(hWnd,hDC); + if(hWnd) DestroyWindow(hWnd); + + UnregisterClass(SAMPLE_NAME,hInstance); +} + +LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + switch(uMsg) { + case WM_SYSCOMMAND: + { + switch (wParam) { + case SC_SCREENSAVE: + case SC_MONITORPOWER: + return 0; + } + break; + } + + case WM_CLOSE: + PostQuitMessage(0); + return 0; + + case WM_SIZE: + render_resize(LOWORD(lParam),HIWORD(lParam)); + return 0; + } + + return DefWindowProc(hWnd,uMsg,wParam,lParam); +} + +bool createWindow(char* title, int width, int height) +{ + WNDCLASS wc; + RECT rect; + rect.left=0; + rect.right=width; + rect.top=0; + rect.bottom=height; + + hInstance = GetModuleHandle(NULL); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = SAMPLE_NAME; + + if(!RegisterClass(&wc)) { + return false; + } + + AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE); + + if(!(hWnd=CreateWindowEx(WS_EX_APPWINDOW|WS_EX_WINDOWEDGE,SAMPLE_NAME,title, + WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS|WS_CLIPCHILDREN, + 0,0,rect.right-rect.left,rect.bottom-rect.top, + NULL,NULL,hInstance,NULL))) { + releaseWindow(); + return false; + } + + static PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + 32, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, + 0, 0, 0, 0, + 32, + 0, + 0, + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + if(!(hDC=GetDC(hWnd))) + { + releaseWindow(); + OutputDebugString(""); + return FALSE; + } + + int pixelformat; + + if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 ){ + OutputDebugString("ChoosePixelFormat Failed...."); + return FALSE; + } + + if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE){ + OutputDebugString("SetPixelFormat Failed...."); + return FALSE; + } + + if (!(hRC=wglCreateContext(hDC))){ + OutputDebugString("Creating HGLRC Failed...."); + return FALSE; + } + + // Set Vsync + //BOOL (WINAPI *wglSwapIntervalEXT)(int) = NULL; + + //if(strstr((char*)glGetString( GL_EXTENSIONS ),"WGL_EXT_swap_control")== 0) { + //} + //else { + //wglSwapIntervalEXT = (BOOL (WINAPI*)(int))wglGetProcAddress("wglSwapIntervalEXT"); + //if(wglSwapIntervalEXT) wglSwapIntervalEXT(1); + //} + + wglMakeCurrent(hDC,hRC); + + ShowWindow(hWnd,SW_SHOW); + SetForegroundWindow(hWnd); + SetFocus(hWnd); + + render_resize(width, height); + + glClearColor(0.0f,0.0f,0.0f,0.0f); + glClearDepth(1.0f); + + return TRUE; +} + +int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) +{ + if(!createWindow(SAMPLE_NAME,DISPLAY_WIDTH,DISPLAY_HEIGHT)) { + MessageBox(NULL,"Can't create gl window.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return 0; + } + + init(); + + physics_create_scene(sceneId); + + SCE_PFX_PRINTF("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + MSG msg; + while(s_isRunning) { + if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + if(msg.message==WM_QUIT) { + s_isRunning = false; + } + else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + } + + shutdown(); + + SCE_PFX_PRINTF("## %s: FINISHED ##\n", SAMPLE_NAME); + + releaseWindow(); + return (msg.wParam); +} + +#endif diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/physics.png b/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/physics.png new file mode 100644 index 0000000000000000000000000000000000000000..d4813595d1507b9babce5da729ca9f2a0dc7e3f5 GIT binary patch literal 28854 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 v[0]) axis = 1; + if(v[2] > v[axis]) axis = 2; + } + + //J ブロードフェーズプロキシの更新 + //E Create broadpahse proxies + { + //J レイキャストと共用するため、全ての軸に対するプロキシ配列を作成する + //E To share with ray casting, create proxy arrays for all axis + + PfxUpdateBroadphaseProxiesParam param; + param.workBytes = pfxGetWorkBytesOfUpdateBroadphaseProxies(numRigidBodies); + param.workBuff = pool.allocate(param.workBytes,128); + param.numRigidBodies = numRigidBodies; + param.offsetRigidStates = states; + param.offsetCollidables = collidables; + param.proxiesX = proxies[0]; + param.proxiesY = proxies[1]; + param.proxiesZ = proxies[2]; + param.proxiesXb = proxies[3]; + param.proxiesYb = proxies[4]; + param.proxiesZb = proxies[5]; + param.worldCenter = worldCenter; + param.worldExtent = worldExtent; + + PfxUpdateBroadphaseProxiesResult result; + + int ret = pfxUpdateBroadphaseProxies(param,result); + if(ret != SCE_PFX_OK) SCE_PFX_PRINTF("pfxUpdateBroadphaseProxies failed %d\n",ret); + + pool.deallocate(param.workBuff); + } + + //J 交差ペア探索 + //E Find overlapped pairs + { + PfxFindPairsParam findPairsParam; + findPairsParam.pairBytes = pfxGetPairBytesOfFindPairs(NUM_CONTACTS); + findPairsParam.pairBuff = pool.allocate(findPairsParam.pairBytes); + findPairsParam.workBytes = pfxGetWorkBytesOfFindPairs(NUM_CONTACTS); + findPairsParam.workBuff = pool.allocate(findPairsParam.workBytes); + findPairsParam.proxies = proxies[axis]; + findPairsParam.numProxies = numRigidBodies; + findPairsParam.maxPairs = NUM_CONTACTS; + findPairsParam.axis = axis; + + PfxFindPairsResult findPairsResult; + + int ret = pfxFindPairs(findPairsParam,findPairsResult); + if(ret != SCE_PFX_OK) SCE_PFX_PRINTF("pfxFindPairs failed %d\n",ret); + + pool.deallocate(findPairsParam.workBuff); + + //J 交差ペア合成 + //E Decompose overlapped pairs into 3 arrays + PfxDecomposePairsParam decomposePairsParam; + decomposePairsParam.pairBytes = pfxGetPairBytesOfDecomposePairs(numPreviousPairs,findPairsResult.numPairs); + decomposePairsParam.pairBuff = pool.allocate(decomposePairsParam.pairBytes); + decomposePairsParam.workBytes = pfxGetWorkBytesOfDecomposePairs(numPreviousPairs,findPairsResult.numPairs); + decomposePairsParam.workBuff = pool.allocate(decomposePairsParam.workBytes); + decomposePairsParam.previousPairs = previousPairs; + decomposePairsParam.numPreviousPairs = numPreviousPairs; + decomposePairsParam.currentPairs = findPairsResult.pairs; // Set pairs from pfxFindPairs() + decomposePairsParam.numCurrentPairs = findPairsResult.numPairs; // Set the number of pairs from pfxFindPairs() + + PfxDecomposePairsResult decomposePairsResult; + + ret = pfxDecomposePairs(decomposePairsParam,decomposePairsResult); + if(ret != SCE_PFX_OK) SCE_PFX_PRINTF("pfxDecomposePairs failed %d\n",ret); + + pool.deallocate(decomposePairsParam.workBuff); + + PfxBroadphasePair *outNewPairs = decomposePairsResult.outNewPairs; + PfxBroadphasePair *outKeepPairs = decomposePairsResult.outKeepPairs; + PfxBroadphasePair *outRemovePairs = decomposePairsResult.outRemovePairs; + PfxUInt32 numOutNewPairs = decomposePairsResult.numOutNewPairs; + PfxUInt32 numOutKeepPairs = decomposePairsResult.numOutKeepPairs; + PfxUInt32 numOutRemovePairs = decomposePairsResult.numOutRemovePairs; + + //J 廃棄ペアのコンタクトをプールに戻す + //E Put removed contacts into the contact pool + for(PfxUInt32 i=0;i 0) { + cId = contactIdPool[--numContactIdPool]; + } + else { + cId = numContacts++; + } + if(cId >= NUM_CONTACTS) { + cId = 0; + } + SCE_PFX_ASSERT(cId < NUM_CONTACTS); + pfxSetContactId(outNewPairs[i],cId); + PfxContactManifold &contact = contacts[cId]; + contact.reset(pfxGetObjectIdA(outNewPairs[i]),pfxGetObjectIdB(outNewPairs[i])); + + //J 寝てる剛体を起こす + //E Wake up sleeping rigid bodies + PfxRigidState &stateA = states[pfxGetObjectIdA(outNewPairs[i])]; + PfxRigidState &stateB = states[pfxGetObjectIdB(outNewPairs[i])]; + if(stateA.isAsleep()) { + stateA.wakeup(); + SCE_PFX_PRINTF("wakeup %u\n",stateA.getRigidBodyId()); + } + if(stateB.isAsleep()) { + stateB.wakeup(); + SCE_PFX_PRINTF("wakeup %u\n",stateB.getRigidBodyId()); + } + } + + //J 新規ペアと維持ペアを合成 + //E Merge 'new' and 'keep' pairs + numCurrentPairs = 0; + for(PfxUInt32 i=0;i sleepCount) { + numCanSleep++; + } + } + } + } + + // Deactivate Island + if(numCanSleep > 0 && numCanSleep == numActive + numSleep) { + PfxIslandUnit *islandUnit = pfxGetFirstUnitInIsland(island,(PfxUInt32)i); + for(;islandUnit!=NULL;islandUnit=pfxGetNextUnitInIsland(islandUnit)) { + if(!(SCE_PFX_MOTION_MASK_CAN_SLEEP(states[pfxGetUnitId(islandUnit)].getMotionType()))) continue; + states[pfxGetUnitId(islandUnit)].sleep(); + } + } + + // Activate Island + else if(numSleep > 0 && numActive > 0) { + PfxIslandUnit *islandUnit = pfxGetFirstUnitInIsland(island,(PfxUInt32)i); + for(;islandUnit!=NULL;islandUnit=pfxGetNextUnitInIsland(islandUnit)) { + if(!(SCE_PFX_MOTION_MASK_CAN_SLEEP(states[pfxGetUnitId(islandUnit)].getMotionType()))) continue; + states[pfxGetUnitId(islandUnit)].wakeup(); + } + } + } + } +} + +void integrate() +{ + PfxUpdateRigidStatesParam param; + param.states = states; + param.bodies = bodies; + param.numRigidBodies = numRigidBodies; + param.timeStep = timeStep; + + pfxUpdateRigidStates(param); +} + +void physics_simulate() +{ + PfxPerfCounter pc; + + for(int i=1;i0) { + PfxRigidState &stateA = states[id-1]; + PfxRigidState &stateB = states[id]; + int jointId = numJoints++; + PfxSwingTwistJointInitParam jparam; + jparam.twistLowerAngle = -0.5f; + jparam.twistUpperAngle = 0.5f; + jparam.anchorPoint = (stateA.getPosition() + stateB.getPosition())*0.5f; + jparam.twistAxis = PfxVector3(1.0f,0.0f,0.0f); + pfxInitializeSwingTwistJoint(joints[jointId],stateA,stateB,jparam); + pfxUpdateJointPairs(jointPairs[jointId],jointId,joints[jointId],stateA,stateB); + + joints[jointId].m_constraints[3].m_damping = 0.1f; + } + + if(i==0) { + firstRope = id; + } + else if(i==numRopes-1) { + lastRope = id; + } + } + } + + const PfxFloat sphereRad = 2.0f; + + { + PfxShape shapeSphere; + shapeSphere.reset(); + shapeSphere.setSphere(PfxSphere(sphereRad)); + + { + PfxVector3 pos = states[firstRope].getPosition() - PfxVector3(ropeLen+sphereRad,0.0f,0.0f); + + int id2 = numRigidBodies++; + collidables[id2].reset(); + collidables[id2].addShape(shapeSphere); + collidables[id2].finish(); + bodies[id2].reset(); + bodies[id2].setMass(10.0f); + bodies[id2].setInertia(pfxCalcInertiaSphere(sphereRad,15.0f)); + states[id2].reset(); + states[id2].setPosition(pos); + states[id2].setMotionType(kPfxMotionTypeActive); + states[id2].setUseSleep(1); + states[id2].setRigidBodyId(id2); + states[id2].setContactFilterSelf(0x00000001); + states[id2].setContactFilterTarget(0xfffffffe); + + int jointId = numJoints++; + PfxBallJointInitParam jparam; + jparam.anchorPoint = states[firstRope].getPosition() - PfxVector3(ropeLen,0.0f,0.0f); + pfxInitializeBallJoint(joints[jointId],states[id2],states[firstRope],jparam); + pfxUpdateJointPairs(jointPairs[jointId],jointId,joints[jointId],states[id2],states[firstRope]); + } + + { + PfxVector3 pos = states[lastRope].getPosition() + PfxVector3(ropeLen+sphereRad,0.0f,0.0f); + + int id2 = numRigidBodies++; + collidables[id2].reset(); + collidables[id2].addShape(shapeSphere); + collidables[id2].finish(); + bodies[id2].reset(); + bodies[id2].setMass(2.0f); + bodies[id2].setInertia(pfxCalcInertiaSphere(sphereRad,5.0f)); + states[id2].reset(); + states[id2].setPosition(pos); + states[id2].setMotionType(kPfxMotionTypeActive); + states[id2].setUseSleep(1); + states[id2].setRigidBodyId(id2); + states[id2].setContactFilterSelf(0x00000001); + states[id2].setContactFilterTarget(0xfffffffe); + + int jointId = numJoints++; + PfxBallJointInitParam jparam; + jparam.anchorPoint = states[lastRope].getPosition() + PfxVector3(ropeLen,0.0f,0.0f); + pfxInitializeBallJoint(joints[jointId],states[id2],states[lastRope],jparam); + pfxUpdateJointPairs(jointPairs[jointId],jointId,joints[jointId],states[id2],states[lastRope]); + } + } +} + +void createSceneBoxGround() +{ + int id = numRigidBodies++; + PfxBox box(150.0f,2.5f,150.0f); + PfxShape shape; + shape.reset(); + shape.setBox(box); + collidables[id].reset(); + collidables[id].addShape(shape); + collidables[id].finish(); + bodies[id].reset(); + states[id].reset(); + states[id].setPosition(PfxVector3(0.0f,-2.5f,0.0f)); + states[id].setMotionType(kPfxMotionTypeFixed); + states[id].setRigidBodyId(id); +} + +void physics_create_scene(int sceneId) +{ + const int numScenes = 3; + int sid = sceneId % numScenes; + + numRigidBodies= 0; + pairSwap = 0; + numPairs[0] = 0; + numPairs[1] = 0; + numContacts = 0; + numContactIdPool = 0; + numJoints = 0; + island = NULL; + frame = 0; + + //E Keep a first joint as a pick joint + //J 最初のジョイントをピッキング用にキープ + numJoints = 1; + joints[0].m_active = 0; + pfxSetActive(jointPairs[0],false); + + switch(sid) { + case 0: // basic joints + createSceneBoxGround(); + createSceneBasicJoints(); + break; + + case 1: // ragdolls + createSceneBoxGround(); + createSceneRagdolls(); + break; + + case 2: // complex machine + createSceneBoxGround(); + createSceneComplexMachine(); + break; + } + + SCE_PFX_PRINTF("----- Size of rigid body buffer ------\n"); + SCE_PFX_PRINTF(" size * num = total\n"); + SCE_PFX_PRINTF("PfxRigidState %5d * %5d = %5d bytes\n",sizeof(PfxRigidState),numRigidBodies,sizeof(PfxRigidState)*numRigidBodies); + SCE_PFX_PRINTF("PfxRigidBody %5d * %5d = %5d bytes\n",sizeof(PfxRigidBody),numRigidBodies,sizeof(PfxRigidBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxCollidable %5d * %5d = %5d bytes\n",sizeof(PfxCollidable),numRigidBodies,sizeof(PfxCollidable)*numRigidBodies); + SCE_PFX_PRINTF("PfxJoint %5d * %5d = %5d bytes\n",sizeof(PfxJoint),numJoints,sizeof(PfxJoint)*numJoints); + SCE_PFX_PRINTF("PfxSolverBody %5d * %5d = %5d bytes\n",sizeof(PfxSolverBody),numRigidBodies,sizeof(PfxSolverBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxBroadphaseProxy %5d * %5d = %5d bytes\n",sizeof(PfxBroadphaseProxy),numRigidBodies,sizeof(PfxBroadphaseProxy)*numRigidBodies); + SCE_PFX_PRINTF("PfxContactManifold %5d * %5d = %5d bytes\n",sizeof(PfxContactManifold),NUM_CONTACTS,sizeof(PfxContactManifold)*NUM_CONTACTS); + SCE_PFX_PRINTF("PfxBroadphasePair %5d * %5d = %5d bytes\n",sizeof(PfxBroadphasePair),NUM_CONTACTS,sizeof(PfxBroadphasePair)*NUM_CONTACTS); + + int totalBytes = + (sizeof(PfxRigidState) + sizeof(PfxRigidBody) + sizeof(PfxCollidable) + sizeof(PfxSolverBody) + sizeof(PfxBroadphaseProxy)) * numRigidBodies + + (sizeof(PfxContactManifold) + sizeof(PfxBroadphasePair)) * NUM_CONTACTS; + SCE_PFX_PRINTF("----------------------------------------------------------\n"); + SCE_PFX_PRINTF("Total %5d bytes\n",totalBytes); +} + +/////////////////////////////////////////////////////////////////////////////// +// Initialize / Finalize Engine + +bool physics_init() +{ + return true; +} + +void physics_release() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// Pick + +inline PfxVector3 calcLocalCoord(const PfxRigidState &state,const PfxVector3 &coord) +{ + return rotate(conj(state.getOrientation()),(coord - state.getPosition())); +} + +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2) +{ + PfxJoint &pickJoint = joints[0]; + + PfxRayCastParam param; + param.offsetRigidStates = states; + param.offsetCollidables = collidables; + param.proxiesX = proxies[0]; + param.proxiesY = proxies[1]; + param.proxiesZ = proxies[2]; + param.proxiesXb = proxies[3]; + param.proxiesYb = proxies[4]; + param.proxiesZb = proxies[5]; + param.numProxies = numRigidBodies; + param.rangeCenter = worldCenter; + param.rangeExtent = worldExtent; + + PfxRayInput pickRay; + PfxRayOutput pickOut; + + pickRay.m_contactFilterSelf = pickRay.m_contactFilterTarget = 0xffffffff; + pickRay.m_startPosition = p1; + pickRay.m_direction = p2-p1; + pickRay.m_facetMode = SCE_PFX_RAY_FACET_MODE_FRONT_ONLY; + pfxCastSingleRay(pickRay,pickOut,param); + + if(pickOut.m_contactFlag) { + PfxRigidState &stateA = states[0]; + PfxRigidState &stateB = states[pickOut.m_objectId]; + PfxRigidBody &bodyB = bodies[pickOut.m_objectId]; + + /* Connect a picked rigid body and the ground with a ball joint. + * Weaken pick power by adjusting a m_maxImpulse parameter so that impulse doesn't exceeds m_maxImpulse. + * It is needed, because constraint power is too strong. + */ + + PfxBallJointInitParam jparam; + jparam.anchorPoint = pickOut.m_contactPoint; + + pfxInitializeBallJoint(pickJoint,stateA,stateB,jparam); + pickJoint.m_constraints[0].m_maxImpulse = bodyB.getMass() * 2.0f; + pickJoint.m_constraints[1].m_maxImpulse = bodyB.getMass() * 2.0f; + pickJoint.m_constraints[2].m_maxImpulse = bodyB.getMass() * 2.0f; + + pfxUpdateJointPairs(jointPairs[0],0,pickJoint,stateA,stateB); + + SCE_PFX_PRINTF("pick objId %d ",pickOut.m_objectId); + if(pickOut.m_subData.m_type == PfxSubData::MESH_INFO) { + SCE_PFX_PRINTF("mesh islandId %d facetId %d",pickOut.m_subData.getIslandId(),pickOut.m_subData.getFacetId()); + } + SCE_PFX_PRINTF("\n"); + + return pickOut.m_contactPoint; + } + + return PfxVector3(0.0f); +} + +void physics_pick_update(const PfxVector3 &p) +{ + PfxJoint &pickJoint = joints[0]; + + if(pickJoint.m_active>0) { + pickJoint.m_anchorA = calcLocalCoord(states[pickJoint.m_rigidBodyIdA],p); + if(states[pickJoint.m_rigidBodyIdB].isAsleep()) { + states[pickJoint.m_rigidBodyIdB].wakeup(); + } + } +} + +void physics_pick_end() +{ + PfxJoint &pickJoint = joints[0]; + + if(pickJoint.m_active>0) { + pickJoint.m_active = 0; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Get Information + +int physics_get_num_rigidbodies() +{ + return numRigidBodies; +} + +const PfxRigidState& physics_get_state(int id) +{ + return states[id]; +} + +const PfxRigidBody& physics_get_body(int id) +{ + return bodies[id]; +} + +const PfxCollidable& physics_get_collidable(int id) +{ + return collidables[id]; +} + +int physics_get_num_contacts() +{ + return numPairs[pairSwap]; +} + +const PfxContactManifold &physics_get_contact(int id) +{ + return contacts[pfxGetConstraintId(pairsBuff[pairSwap][id])]; +} + +const PfxIsland* physics_get_islands() +{ + return island; +} diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/physics_func.h b/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/physics_func.h new file mode 100644 index 0000000..bde4189 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/physics_func.h @@ -0,0 +1,53 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef __PHYSICS_FUNC_H__ +#define __PHYSICS_FUNC_H__ + +#define SCE_PFX_USE_PERFCOUNTER + +#include "physics_effects.h" + +using namespace sce::PhysicsEffects; + +//E Simulation +//J シミュレーション +bool physics_init(); +void physics_release(); +void physics_create_scene(int sceneId); +void physics_simulate(); + +//E Picking +//J ピッキング +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2); +void physics_pick_update(const PfxVector3 &p); +void physics_pick_end(); + +//E Change parameters +//J パラメータの取得 +int physics_get_num_rigidbodies(); +const PfxRigidState& physics_get_state(int id); +const PfxRigidBody& physics_get_body(int id); +const PfxCollidable& physics_get_collidable(int id); + +// Get contact information +int physics_get_num_contacts(); +const PfxContactManifold &physics_get_contact(int id); + +// Get simulation island +const PfxIsland* physics_get_islands(); + +#endif /* __PHYSICS_FUNC_H__ */ diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/premake4.lua b/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/premake4.lua new file mode 100644 index 0000000..80dad31 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/6_joint/premake4.lua @@ -0,0 +1,22 @@ + project "5_joint" + + kind "WindowedApp" + targetdir "../../../bin" + includedirs {"../../../include"} + + links { + "physicseffects2_lowlevel", + "physicseffects2_baselevel", + "physicseffects2_util", + "opengl32" + } + + flags {"WinMain"} + + files { + "main.cpp", + "physics_func.cpp", + "../common/ctrl_func.win32.cpp", + "../common/perf_func.win32.cpp", + "../common/render_func.win32.cpp" + } \ No newline at end of file diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/99_BulletPhysicsEffects.vcproj b/Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/99_BulletPhysicsEffects.vcproj new file mode 100644 index 0000000..c1903de --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/99_BulletPhysicsEffects.vcproj @@ -0,0 +1,280 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/CMakeLists.txt b/Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/CMakeLists.txt new file mode 100644 index 0000000..4d210b9 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/CMakeLists.txt @@ -0,0 +1,89 @@ +cmake_minimum_required(VERSION 2.4) + + +#this line has to appear before 'PROJECT' in order to be able to disable incremental linking +SET(MSVC_INCREMENTAL_DEFAULT ON) + +PROJECT(App_99_BulletPhysicsEffects) + + +IF (NOT CMAKE_BUILD_TYPE) +# SET(CMAKE_BUILD_TYPE "Debug") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF (NOT CMAKE_BUILD_TYPE) + + +OPTION(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC Runtime Library DLL (/MD or /MDd)" ON) +OPTION(USE_MSVC_INCREMENTAL_LINKING "Use MSVC Incremental Linking" OFF) + + +IF(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + + +SET(App_99_BulletPhysicsEffects_SRCS + main.cpp + bullet_physics_func.cpp + ../common/ctrl_func.win32.cpp + ../common/perf_func.win32.cpp + ../common/render_func.win32.cpp + ${PHYSICS_EFFECTS_SOURCE_DIR}/include/BulletPhysicsEffects/btBulletPhysicsEffectsWorld.cpp + ${PHYSICS_EFFECTS_SOURCE_DIR}/include/BulletPhysicsEffects/btLowLevelConstraintSolver2.cpp + ${PHYSICS_EFFECTS_SOURCE_DIR}/include/BulletPhysicsEffects/btLowLevelCollisionDispatcher.cpp + ${PHYSICS_EFFECTS_SOURCE_DIR}/include/BulletPhysicsEffects/btLowLevelBroadphase.cpp + +) + + +SET(App_99_BulletPhysicsEffects_HDRS + physics_func.h + landscape.h + barrel.h + ../common/render_func.h + ../common/common.h + ../common/ctrl_func.h + ../common/perf_func.h + ${PHYSICS_EFFECTS_SOURCE_DIR}/include/BulletPhysicsEffects/btBulletPhysicsEffectsWorld.h + ${PHYSICS_EFFECTS_SOURCE_DIR}/include/BulletPhysicsEffects/btLowLevelConstraintSolver2.h + ${PHYSICS_EFFECTS_SOURCE_DIR}/include/BulletPhysicsEffects/btLowLevelCollisionDispatcher.h + ${PHYSICS_EFFECTS_SOURCE_DIR}/include/BulletPhysicsEffects/btLowLevelBroadphase.h +) + + +INCLUDE_DIRECTORIES( + ../../../../../src +# ${VECTOR_MATH_INCLUDE} +) + +#LINK_DIRECTORIES( +# +#) + +#ADD_DEFINITIONS(-DUNICODE) +#ADD_DEFINITIONS(-D_UNICODE) + +ADD_EXECUTABLE(App_99_BulletPhysicsEffects WIN32 + ${App_99_BulletPhysicsEffects_SRCS} + ${App_99_BulletPhysicsEffects_HDRS} +) +TARGET_LINK_LIBRARIES(App_99_BulletPhysicsEffects + PfxBaseLevel + PfxLowLevel + PfxUtil + BulletDynamics + BulletCollision + LinearMath + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} +) + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(App_99_BulletPhysicsEffects PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(App_99_BulletPhysicsEffects PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(App_99_BulletPhysicsEffects PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF() + + + + \ No newline at end of file diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/barrel.h b/Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/barrel.h new file mode 100644 index 0000000..ade7bb5 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/barrel.h @@ -0,0 +1,202 @@ +/* +Physics Effects Copyright(C) 2011 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define BarrelVtxCount 57 +#define BarrelIdxCount 180 + +static float BarrelVtx[] = { +0.0f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +-0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +0.0f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +-0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.957307f,-0.289072f,0.0f, +0.404509f,0.0f,-0.293893f, 0.809017f,0.0f,-0.587785f, +0.5f,0.0f,0.0f, 1.0f,0.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.774478f,-0.289072f,-0.562691f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +-0.154509f,0.0f,-0.475528f, -0.309017f,0.0f,-0.951057f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +-0.107853f,-0.5f,-0.331936f, -0.295824f,-0.289072f,-0.910453f, +-0.404509f,0.0f,-0.293893f, -0.809017f,0.0f,-0.587785f, +-0.282362f,-0.5f,-0.205148f, -0.774478f,-0.289072f,-0.562691f, +-0.5f,0.0f,0.0f, -1.0f,0.0f,0.0f, +-0.349018f,-0.5f,0.0f, -0.957307f,-0.289072f,0.0f, +-0.404508f,0.0f,0.293893f, -0.809017f,0.0f,0.587785f, +-0.282362f,-0.5f,0.205148f, -0.774478f,-0.289072f,0.562691f, +-0.154509f,0.0f,0.475528f, -0.309017f,0.0f,0.951056f, +-0.107853f,-0.5f,0.331936f, -0.295824f,-0.289072f,0.910453f, +0.154509f,0.0f,0.475528f, 0.309017f,0.0f,0.951056f, +0.107853f,-0.5f,0.331936f, 0.295824f,-0.289072f,0.910453f, +0.404509f,0.0f,0.293892f, 0.809017f,0.0f,0.587785f, +0.282362f,-0.5f,0.205148f, 0.774478f,-0.289072f,0.562691f, +0.282362f,0.5f,-0.205148f, 0.774478f,0.289072f,-0.562691f, +0.349018f,0.5f,0.0f, 0.957307f,0.289072f,0.0f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.107853f,0.5f,-0.331936f, -0.295824f,0.289072f,-0.910453f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.282362f,0.5f,-0.205148f, -0.774478f,0.289072f,-0.562691f, +-0.349018f,0.5f,0.0f, -0.957307f,0.289072f,0.0f, +-0.282362f,0.5f,0.205148f, -0.774478f,0.289072f,0.562691f, +-0.107853f,0.5f,0.331936f, -0.295824f,0.289072f,0.910453f, +0.107853f,0.5f,0.331936f, 0.295824f,0.289072f,0.910453f, +0.282362f,0.5f,0.205148f, 0.774478f,0.289072f,0.562691f, +}; + +static float BarrelTex[] = { +0.0f,0.5f, +0.0f,0.85f, +0.0f,0.75f, +0.0f,0.95f, +0.0f,0.05f, +0.0f,-0.05f, +0.0f,0.15f, +0.0f,0.25f, +0.0f,0.35f, +0.0f,0.45f, +0.0f,0.55f, +0.0f,0.65f, +1.0f,0.5f, +1.0f,0.75f, +1.0f,0.85f, +1.0f,0.95f, +1.0f,-0.05f, +1.0f,0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +0.0f,0.75f, +0.5f,0.85f, +0.5f,0.75f, +0.0f,0.85f, +0.5f,0.95f, +0.0f,0.95f, +0.0f,-0.05f, +0.5f,0.05f, +0.5f,-0.05f, +0.0f,0.05f, +0.5f,0.15f, +0.0f,0.15f, +0.5f,0.25f, +0.0f,0.25f, +0.5f,0.35f, +0.0f,0.35f, +0.5f,0.45f, +0.0f,0.45f, +0.5f,0.55f, +0.0f,0.55f, +0.5f,0.65f, +0.0f,0.65f, +1.0f,0.85f, +1.0f,0.75f, +1.0f,0.95f, +1.0f,0.05f, +1.0f,-0.05f, +1.0f,0.15f, +1.0f,0.25f, +1.0f,0.35f, +1.0f,0.45f, +1.0f,0.55f, +1.0f,0.65f, +}; + +static unsigned short BarrelIdx[] = { +0,1,2, +0,3,1, +0,4,5, +0,6,4, +0,7,6, +0,8,7, +0,9,8, +0,10,9, +0,11,10, +0,2,11, +12,13,14, +12,14,15, +12,16,17, +12,17,18, +12,18,19, +12,19,20, +12,20,21, +12,21,22, +12,22,23, +12,23,13, +24,25,26, +24,27,25, +27,28,25, +27,29,28, +30,31,32, +30,33,31, +33,34,31, +33,35,34, +35,36,34, +35,37,36, +37,38,36, +37,39,38, +39,40,38, +39,41,40, +41,42,40, +41,43,42, +43,44,42, +43,45,44, +45,26,44, +45,24,26, +26,46,47, +26,25,46, +25,48,46, +25,28,48, +32,49,50, +32,31,49, +31,51,49, +31,34,51, +34,52,51, +34,36,52, +36,53,52, +36,38,53, +38,54,53, +38,40,54, +40,55,54, +40,42,55, +42,56,55, +42,44,56, +44,47,56, +44,26,47, +}; + diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/bullet_physics_func.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/bullet_physics_func.cpp new file mode 100644 index 0000000..e342e2a --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/bullet_physics_func.cpp @@ -0,0 +1,1241 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "physics_func.h" +#include "../common/perf_func.h" + +#include "BulletPhysicsEffects/btBulletPhysicsEffectsWorld.h" +#include "BulletPhysicsEffects/btLowLevelBroadphase.h" +#include "BulletPhysicsEffects/btLowLevelCollisionDispatcher.h" +#include "BulletPhysicsEffects/btLowLevelData.h" +#include "BulletPhysicsEffects/btLowLevelConstraintSolver.h" +#include "BulletPhysicsEffects/btLowLevelConstraintSolver2.h" + + +#include "LinearMath/btIDebugDraw.h" +#include "BulletMultiThreaded/vectormath2bullet.h" +#include "../common/render_func.h" +#if 0 +#ifdef _WIN32 +#include "BulletMultiThreaded/Win32ThreadSupport.h" +#endif + +btThreadSupportInterface* createSolverThreadSupport(int maxNumThreads) +{ +#define SEQUENTIAL +#ifdef SEQUENTIAL + SequentialThreadSupport::SequentialThreadConstructionInfo tci("solverThreads",SolverThreadFunc,SolverlsMemoryFunc); + SequentialThreadSupport* threadSupport = new SequentialThreadSupport(tci); + threadSupport->startSPU(); +#else + +#ifdef _WIN32 + Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("solverThreads",SolverThreadFunc,SolverlsMemoryFunc,maxNumThreads); + Win32ThreadSupport* threadSupport = new Win32ThreadSupport(threadConstructionInfo); + threadSupport->startSPU(); +#elif defined (USE_PTHREADS) + PosixThreadSupport::ThreadConstructionInfo solverConstructionInfo("solver", SolverThreadFunc, + SolverlsMemoryFunc, maxNumThreads); + + PosixThreadSupport* threadSupport = new PosixThreadSupport(solverConstructionInfo); + +#else + SequentialThreadSupport::SequentialThreadConstructionInfo tci("solverThreads",SolverThreadFunc,SolverlsMemoryFunc); + SequentialThreadSupport* threadSupport = new SequentialThreadSupport(tci); + threadSupport->startSPU(); +#endif + +#endif + + return threadSupport; +} +#endif + + +class PEDebugDrawer : public btIDebugDraw +{ + int m_debugMode; + +public: + + PEDebugDrawer() + :m_debugMode(0) + { + } + virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& clr) + { + PfxVector3 position1 = getVmVector3(from); + PfxVector3 position2 = getVmVector3(to); + PfxVector3 color = getVmVector3(clr); + render_debug_line(position1,position2,color); + } + virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color) + { + + } + + virtual void reportErrorWarning(const char* warningString) + { + SCE_PFX_PRINTF(warningString); + } + + virtual void draw3dText(const btVector3& location,const char* textString) + { + } + + virtual void setDebugMode(int debugMode) + { + m_debugMode = debugMode; + } + + virtual int getDebugMode() const + { + return m_debugMode; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Data + +#define NUM_RIGIDBODIES 5000 +#define NUM_JOINTS 500 +#define NUM_CONTACTS 20000 + +const float timeStep = 0.016f; +const float separateBias = 0.1f; +int iteration = 5; + + +//J ワールドサイズ +//E World size +PfxVector3 worldCenter(0.0f); +PfxVector3 worldExtent(500.0f); + +//J 剛体 +//E Rigid body +PfxRigidState states[NUM_RIGIDBODIES]; +PfxRigidBody bodies[NUM_RIGIDBODIES]; +PfxCollidable collidables[NUM_RIGIDBODIES]; +PfxSolverBody solverBodies[NUM_RIGIDBODIES]; +int numRigidBodies = 0; +//PfxConstraintPair jointPairs[NUM_JOINTS]; +PfxJoint joints[NUM_JOINTS]; +int numJoints = 0; + +//J 地形を表現するためのラージメッシュ +//E Large mesh for representing a landscape +#include "landscape.h" +PfxLargeTriMesh gLargeMesh; + +//J 凸メッシュ +//E Convex Mesh +#include "barrel.h" +PfxConvexMesh gConvex; + + + +int physics_get_num_rigidbodies() +{ + return numRigidBodies; +} + +const PfxRigidState& physics_get_state(int id) +{ + return states[id]; +} + +const PfxRigidBody& physics_get_body(int id) +{ + return bodies[id]; +} + +const PfxCollidable& physics_get_collidable(int id) +{ + return collidables[id]; +} + + + + + +/////////////////////////////////////////////////////////////////////////////// +// Create Scene + +void createBrick(int id,const PfxVector3 &pos,const PfxQuat &rot,const PfxVector3 &boxSize,PfxFloat mass) +{ + PfxBox box(boxSize); + PfxShape shape; + shape.reset(); + shape.setBox(box); + collidables[id].reset(); + collidables[id].addShape(shape); + collidables[id].finish(); + bodies[id].reset(); + bodies[id].setRestitution(0.0f); + bodies[id].setMass(mass); + bodies[id].setInertia(pfxCalcInertiaBox(boxSize,mass)); + states[id].reset(); + states[id].setPosition(pos); + states[id].setOrientation(rot); + states[id].setMotionType(kPfxMotionTypeActive); + states[id].setRigidBodyId(id); +} + +void createWall(const PfxVector3 &offsetPosition,int stackSize,const PfxVector3 &boxSize) +{ + PfxFloat bodyMass = 0.5f; + + PfxFloat diffX = boxSize[0] * 1.02f; + PfxFloat diffY = boxSize[1] * 1.02f; + PfxFloat diffZ = boxSize[2] * 1.02f; + + PfxFloat offset = -stackSize * (diffZ * 2.0f) * 0.5f; + PfxVector3 pos(0.0f, diffY, 0.0f); + + while(stackSize) { + for(int i=0;i 0) { + pfxReleaseLargeTriMesh(gLargeMesh); + } + + PfxInt32 ret = pfxCreateLargeTriMesh(gLargeMesh,param); + if(ret != SCE_PFX_OK) { + SCE_PFX_PRINTF("Can't create large mesh.\n"); + } + + int id = numRigidBodies++; + PfxShape shape; + shape.reset(); + shape.setLargeTriMesh(&gLargeMesh); + collidables[id].reset(); + collidables[id].addShape(shape); + collidables[id].finish(); + bodies[id].reset(); + states[id].reset(); + states[id].setPosition(PfxVector3(0.0f,-5.0f,0.0f)); + states[id].setOrientation(PfxQuat::rotationX(0.5f)*PfxQuat::rotationY(0.7f)); + states[id].setMotionType(kPfxMotionTypeFixed); + states[id].setRigidBodyId(id); +} + +#include +#include "BulletMultiThreaded/vectormath2bullet.h" + +btDefaultCollisionConfiguration* m_config=0; +btCollisionDispatcher* m_dispatcher=0; +btBroadphaseInterface* m_broadphase=0; +btConstraintSolver* m_solver=0; +btDiscreteDynamicsWorld* m_dynamicsWorld=0; +btThreadSupportInterface* sThreadSupport=0; + +void debugRenderPhysics() +{ + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); +} + +static void cleanupBullet(void) +{ + if (m_dynamicsWorld) + { + delete m_dynamicsWorld; + delete m_solver; +// delete sThreadSupport; + delete m_broadphase; + delete m_dispatcher; + delete m_config; + } +} + +void physics_simulate() +{ + //run the simulation + + static btClock clock; + static bool first = true; + if (first) + { + first=false; + clock.reset(); + } + btScalar dt = (btScalar)clock.getTimeMicroseconds(); + clock.reset(); + + + + m_dynamicsWorld->stepSimulation(dt/1000000.f); + + int i; + for (i=0;igetNumCollisionObjects();i++) + { + btRigidBody* body = btRigidBody::upcast(m_dynamicsWorld->getCollisionObjectArray()[i]); + if (body) + { + + PfxRigidState* state = (PfxRigidState*) body->getUserPointer(); + + PfxVector3 pe_pos = getVmVector3(body->getWorldTransform().getOrigin()); + PfxQuat pe_orn = getVmQuat(body->getWorldTransform().getRotation()); + PfxVector3 pe_lvel = getVmVector3(body->getLinearVelocity()); + PfxVector3 pe_avel = getVmVector3(body->getAngularVelocity()); + + state->setPosition(pe_pos); + state->setOrientation(pe_orn); + state->setLinearVelocity(pe_lvel); + state->setAngularVelocity(pe_avel); + } + } + + +} + +btRigidBody* addRigidBody(btCollisionShape* shape, btScalar mass, const btTransform& startTransform) +{ + btVector3 localInertia; + localInertia.setZero(); + + if (mass) + shape->calculateLocalInertia(mass,localInertia); + + btRigidBody* body = new btRigidBody(mass,0,shape,localInertia); + body->setWorldTransform(startTransform); + body->setActivationState(DISABLE_DEACTIVATION); + //body->setFriction(2); + m_dynamicsWorld->addRigidBody(body); + return body; +} + +static void convertToBullet(void) +{ + + cleanupBullet(); + + m_config = new btDefaultCollisionConfiguration(); + + btHashedOverlappingPairCache* pairCache = new btHashedOverlappingPairCache(); + //m_broadphase = new btDbvtBroadphase(); + btLowLevelData* lowLevelData = new btLowLevelData; + + lowLevelData->m_maxContacts = NUM_CONTACTS;//8024; + lowLevelData->m_contactIdPool = (int*) btAlignedAlloc(sizeof(int)*lowLevelData->m_maxContacts ,16); + lowLevelData->m_contacts = (PfxContactManifold*) btAlignedAlloc(sizeof(PfxContactManifold)*lowLevelData->m_maxContacts,16); + lowLevelData->m_maxPairs = lowLevelData->m_maxContacts;//?? + lowLevelData->m_pairsBuff[0] = (PfxBroadphasePair*) btAlignedAlloc(sizeof(PfxBroadphasePair)*lowLevelData->m_maxPairs,16); + lowLevelData->m_pairsBuff[1] = (PfxBroadphasePair*) btAlignedAlloc(sizeof(PfxBroadphasePair)*lowLevelData->m_maxPairs,16); + +#define USE_LL_BP +#ifdef USE_LL_BP + btLowLevelBroadphase* llbp = new btLowLevelBroadphase(lowLevelData,pairCache); + m_broadphase = llbp; +#else //USE_LL_BP + m_broadphase = new btDbvtBroadphase(); +#endif //USE_LL_BP + + //m_dispatcher = new btCollisionDispatcher(m_config); + m_dispatcher = new btLowLevelCollisionDispatcher(lowLevelData,m_config,NUM_CONTACTS); + +//#ifdef USE_PARALLEL_SOLVER +// m_solver = new btSequentialImpulseConstraintSolver(); +//#else + //sThreadSupport = createSolverThreadSupport(4); + //m_solver = new btLowLevelConstraintSolver(sThreadSupport); + m_solver = new btLowLevelConstraintSolver2(lowLevelData); +//#endif //USE_PARALLEL_SOLVER + + //m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_config); + m_dynamicsWorld = new btBulletPhysicsEffectsWorld(lowLevelData, m_dispatcher,llbp,m_solver,m_config,0); + PEDebugDrawer* drawer = new PEDebugDrawer(); + drawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe+btIDebugDraw::DBG_DrawAabb); + + m_dynamicsWorld->setDebugDrawer(drawer); + + m_dynamicsWorld ->getSolverInfo().m_splitImpulse = true; + + for(int i=0;i shapes; + btAlignedObjectArray childTtransforms; + + PfxRigidState &state = states[i];//physics_get_state(i); + state.setUserData(0); + + + const PfxCollidable &coll = physics_get_collidable(i); + + PfxTransform3 rbT(state.getOrientation(), state.getPosition()); + + PfxShapeIterator itrShape(coll); + for(int j=0;jm_verts[0]; + btConvexHullShape* convexHull = new btConvexHullShape(vertices,convex->m_numVerts, sizeof(PfxVector3)); + shapes.push_back(convexHull); + } + break; + + case kPfxShapeLargeTriMesh: + { + const PfxLargeTriMesh* mesh = shape.getLargeTriMesh(); + btTriangleIndexVertexArray* meshInterface = new btTriangleIndexVertexArray(); + int i; + for (i= 0; i < mesh->m_numIslands;i++) + { + PfxTriMesh* island = &mesh->m_islands[i]; + + //mesh->m_islands + //mesh->m_numIslands + btIndexedMesh indexedMesh; + indexedMesh.m_indexType = PHY_UCHAR; + indexedMesh.m_numTriangles = island->m_numFacets; + indexedMesh.m_triangleIndexBase = &island->m_facets[0].m_vertIds[0]; + indexedMesh.m_triangleIndexStride = sizeof(PfxFacet); + indexedMesh.m_vertexBase = (const unsigned char*) &island->m_verts[0]; + indexedMesh.m_numVertices = island->m_numVerts;//unused + indexedMesh.m_vertexStride = sizeof(PfxVector3); + meshInterface->addIndexedMesh(indexedMesh,PHY_UCHAR); + } + + btBvhTriangleMeshShape* trimesh = new btBvhTriangleMeshShape(meshInterface,true); + shapes.push_back(trimesh); + } + + break; + + default: + { + printf("unknown\n"); + } + break; + } + } + + if(shapes.size()>0) + { + printf("shapes!\n"); + btCollisionShape* colShape = 0; + if (shapes.size()==1 && childTtransforms[0].getOrigin().fuzzyZero()) +//todo: also check orientation + { + colShape = shapes[0]; + } + else + { + btCompoundShape* compound = new btCompoundShape(); + for (int i=0;iaddChildShape(childTtransforms[i],shapes[i]); + } + colShape = compound; + + } + + btTransform worldTransform; + worldTransform.setIdentity(); + worldTransform.setOrigin(getBtVector3(rbT.getTranslation())); + PfxQuat quat(rbT.getUpper3x3()); + worldTransform.setBasis(btMatrix3x3(getBtQuat(quat))); + + btScalar mass = physics_get_body(i).getMass(); + btRigidBody* body = addRigidBody(colShape,mass,worldTransform); + void* ptr = (void*)&state; + body->setUserPointer(ptr); + state.setUserData(body); + } + + } + + //very basic joint conversion (only limits of PFX_JOINT_SWINGTWIST joint) + for (int i=0;isetLimit(i,0,0); + break; + } + case SCE_PFX_JOINT_LOCK_FREE: + { + dof6->setLimit(i,1,0); + break; + } + case SCE_PFX_JOINT_LOCK_LIMIT: + { + //deal with the case where angular limits of Y-axis are free and/or beyond -PI/2 and PI/2 + if ((i==4) && ((joint.m_constraints[i].m_movableLowerLimit<-SIMD_PI/2)||(joint.m_constraints[i].m_movableUpperLimit>SIMD_PI/2))) + { + printf("error with joint limits, forcing DOF to fixed\n"); + dof6->setLimit(i,0,0); + } else + { + dof6->setLimit(i,joint.m_constraints[i].m_movableLowerLimit,joint.m_constraints[i].m_movableUpperLimit); + } + + break; + } + default: + { + printf("unknown joint lock state\n"); + } + } + + } + + m_dynamicsWorld->addConstraint(dof6,true); + + } else + { + printf("error: missing bodies during joint conversion\n"); + } + break; + }; + case kPfxJointBall: + case kPfxJointHinge: + case kPfxJointSlider: + case kPfxJointFix: + case kPfxJointUniversal: + case kPfxJointAnimation: + default: + { + printf("unknown joint\n"); + } + } + } + + //create a large enough buffer. There is no method to pre-calculate the buffer size yet. + int maxSerializeBufferSize = 1024*1024*5; + + btDefaultSerializer* serializer = new btDefaultSerializer(maxSerializeBufferSize); + m_dynamicsWorld->serialize(serializer); + + FILE* file = fopen("testFile.bullet","wb"); + fwrite(serializer->getBufferPointer(),serializer->getCurrentBufferSize(),1, file); + fclose(file); + +} + +void physics_create_scene(int sceneId) +{ + const int numScenes = 4; + int sid = sceneId % numScenes; + + numRigidBodies= 0; +// numPairs = 0; +// numContacts = 0; + numJoints = 0; +// //frame = 0; + + switch(sid) { + case 0: // simple primitives + createSceneBoxGround(); + createScenePrimitives(); + break; + + case 1: // joints + createSceneBoxGround(); + createSceneJoints(); + break; + + case 2: // stacking + createSceneBoxGround(); + createSceneStacking(); + break; + + case 3: // landscape + createSceneLandscape(); + createScenePrimitives(); + break; + } + + SCE_PFX_PRINTF("----- Size of rigid body buffer ------\n"); + SCE_PFX_PRINTF(" size * num = total\n"); + SCE_PFX_PRINTF("PfxRigidState %5d * %5d = %5d bytes\n",sizeof(PfxRigidState),numRigidBodies,sizeof(PfxRigidState)*numRigidBodies); + SCE_PFX_PRINTF("PfxRigidBody %5d * %5d = %5d bytes\n",sizeof(PfxRigidBody),numRigidBodies,sizeof(PfxRigidBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxCollidable %5d * %5d = %5d bytes\n",sizeof(PfxCollidable),numRigidBodies,sizeof(PfxCollidable)*numRigidBodies); + //SCE_PFX_PRINTF("PfxJoint %5d * %5d = %5d bytes\n",sizeof(PfxJoint),numJoints,sizeof(PfxJoint)*numJoints); + SCE_PFX_PRINTF("PfxSolverBody %5d * %5d = %5d bytes\n",sizeof(PfxSolverBody),numRigidBodies,sizeof(PfxSolverBody)*numRigidBodies); + SCE_PFX_PRINTF("PfxBroadphaseProxy %5d * %5d = %5d bytes\n",sizeof(PfxBroadphaseProxy),numRigidBodies,sizeof(PfxBroadphaseProxy)*numRigidBodies); + SCE_PFX_PRINTF("PfxContactManifold %5d * %5d = %5d bytes\n",sizeof(PfxContactManifold),NUM_CONTACTS,sizeof(PfxContactManifold)*NUM_CONTACTS); + SCE_PFX_PRINTF("PfxBroadphasePair %5d * %5d = %5d bytes\n",sizeof(PfxBroadphasePair),NUM_CONTACTS,sizeof(PfxBroadphasePair)*NUM_CONTACTS); + + int totalBytes = + (sizeof(PfxRigidState) + sizeof(PfxRigidBody) + sizeof(PfxCollidable) + sizeof(PfxSolverBody) + sizeof(PfxBroadphaseProxy)) * numRigidBodies + + (sizeof(PfxContactManifold) + sizeof(PfxBroadphasePair)) * NUM_CONTACTS; + + //convert to Bullet + convertToBullet(); + + + SCE_PFX_PRINTF("----------------------------------------------------------\n"); + SCE_PFX_PRINTF("Total %5d bytes\n",totalBytes); +} + +bool physics_init() +{ + return true; +} + +void physics_release() +{ +} + + +#if 0 + +//J プロキシ +//E Proxies +PfxBroadphaseProxy proxies[NUM_RIGIDBODIES]; + +//J ジョイント +//E Joint +PfxConstraintPair jointPairs[NUM_JOINTS]; +PfxJoint joints[NUM_JOINTS]; +int numJoints = 0; + +//J ペア +//E Pairs +unsigned int numPairs; +PfxBroadphasePair pairs[NUM_CONTACTS]; + +//J コンタクト +//E Contacts +PfxContactManifold contacts[NUM_CONTACTS]; +int numContacts; + +//J 一時バッファ +//E Temporary buffers +#define POOL_BYTES (5*1024*1024) +unsigned char PFX_ALIGNED(128) poolBuff[POOL_BYTES]; + +//J 一時バッファ用スタックアロケータ +//E Stack allocator for temporary buffers +PfxHeapManager pool(poolBuff,POOL_BYTES); + +/////////////////////////////////////////////////////////////////////////////// +// Simulation Function + +int frame = 0; + +void broadphase() +{ + //J 剛体が最も分散している軸を見つける + //E Find the axis along which all rigid bodies are most widely positioned + int axis = 0; + { + PfxVector3 s(0.0f),s2(0.0f); + for(int i=0;i v[0]) axis = 1; + if(v[2] > v[axis]) axis = 2; + } + + //J ブロードフェーズプロキシの更新 + //E Create broadpahse proxies + { + for(int i=0;i + #include +#endif + +#define SAMPLE_NAME "api_physics_effects/1_simple" + +static bool s_isRunning = true; + +int sceneId = 2; +bool simulating = false; + +int landscapeMeshId; +int convexMeshId; + +/* + kPfxShapeSphere = 0, + kPfxShapeBox, + kPfxShapeCapsule, + kPfxShapeCylinder, + kPfxShapeConvexMesh, + kPfxShapeLargeTriMesh, + kPfxShapeReserved0, + kPfxShapeReserved1, + kPfxShapeReserved2, + kPfxShapeUser0, + kPfxShapeUser1, + kPfxShapeUser2, + kPfxShapeCount // =12 + */ + +extern void debugRenderPhysics(); + +static void render(void) +{ + + render_begin(); + + for(int i=0;i -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_DOWN)) { + angX += 0.05f*dt; + if(angX < -1.4f) angX = -1.4f; + if(angX > -0.01f) angX = -0.01f; + } + + if(ctrl_button_pressed(BTN_LEFT)) { + angY -= 0.05f*dt; + } + + if(ctrl_button_pressed(BTN_RIGHT)) { + angY += 0.05f*dt; + } + + if(ctrl_button_pressed(BTN_ZOOM_OUT)) { + r *= (1.f+0.2*dt); + if(r > 500.0f) r = 500.0f; + } + + if(ctrl_button_pressed(BTN_ZOOM_IN)) { + r *= (1.f-0.2*dt); + if(r < 1.0f) r = 1.0f; + } + + if(ctrl_button_pressed(BTN_SCENE_RESET) == BTN_STAT_DOWN) { + physics_create_scene(sceneId); + } + + if(ctrl_button_pressed(BTN_SCENE_NEXT) == BTN_STAT_DOWN) { + physics_create_scene(++sceneId); + } + + if(ctrl_button_pressed(BTN_SIMULATION) == BTN_STAT_DOWN) { + simulating = !simulating; + } + + if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_DOWN) { + simulating = true; + } + else if(ctrl_button_pressed(BTN_STEP) == BTN_STAT_UP || ctrl_button_pressed(BTN_STEP) == BTN_STAT_KEEP) { + simulating = false; + } + + render_set_view_angle(angX,angY,r); +} + +#ifndef WIN32 + +/////////////////////////////////////////////////////////////////////////////// +// Main + +int main(void) +{ + init(); + + physics_create_scene(sceneId); + + printf("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + while (s_isRunning) { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + + shutdown(); + + printf("## %s: FINISHED ##\n", SAMPLE_NAME); + + return 0; +} + +#else + + +#include +#include + +static jmp_buf buf; + +void second(void) { + printf("second\n"); // prints + longjmp(buf,1); // jumps back to where setjmp was called - making setjmp now return 1 +} + +void first(void) { + second(); + printf("first\n"); // does not print +} + +int main2() { + if ( ! setjmp(buf) ) { + first(); // when executed, setjmp returns 0 + } else { // when longjmp jumps back, setjmp returns 1 + printf("main\n"); // prints + } + + return 0; +} + + +/////////////////////////////////////////////////////////////////////////////// +// WinMain + +extern HDC hDC; +extern HGLRC hRC; +HWND hWnd; +HINSTANCE hInstance; + +void releaseWindow() +{ + if(hRC) { + wglMakeCurrent(0,0); + wglDeleteContext(hRC); + } + + if(hDC) ReleaseDC(hWnd,hDC); + if(hWnd) DestroyWindow(hWnd); + + UnregisterClass(SAMPLE_NAME,hInstance); +} + +LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + switch(uMsg) { + case WM_SYSCOMMAND: + { + switch (wParam) { + case SC_SCREENSAVE: + case SC_MONITORPOWER: + return 0; + } + break; + } + + case WM_CLOSE: + PostQuitMessage(0); + return 0; + + case WM_SIZE: + render_resize(LOWORD(lParam),HIWORD(lParam)); + return 0; + } + + return DefWindowProc(hWnd,uMsg,wParam,lParam); +} + +bool createWindow(char* title, int width, int height) +{ + WNDCLASS wc; + RECT rect; + rect.left=0; + rect.right=width; + rect.top=0; + rect.bottom=height; + + hInstance = GetModuleHandle(NULL); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = SAMPLE_NAME; + + if(!RegisterClass(&wc)) { + return false; + } + + AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE); + + if(!(hWnd=CreateWindowEx(WS_EX_APPWINDOW|WS_EX_WINDOWEDGE,SAMPLE_NAME,title, + WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS|WS_CLIPCHILDREN, + 0,0,rect.right-rect.left,rect.bottom-rect.top, + NULL,NULL,hInstance,NULL))) { + releaseWindow(); + return false; + } + + static PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + 32, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, + 0, 0, 0, 0, + 32, + 0, + 0, + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + if(!(hDC=GetDC(hWnd))) + { + releaseWindow(); + OutputDebugString(""); + return FALSE; + } + + int pixelformat; + + if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 ){ + OutputDebugString("ChoosePixelFormat Failed...."); + return FALSE; + } + + if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE){ + OutputDebugString("SetPixelFormat Failed...."); + return FALSE; + } + + if (!(hRC=wglCreateContext(hDC))){ + OutputDebugString("Creating HGLRC Failed...."); + return FALSE; + } + + // Set Vsync + //BOOL (WINAPI *wglSwapIntervalEXT)(int) = NULL; + + //if(strstr((char*)glGetString( GL_EXTENSIONS ),"WGL_EXT_swap_control")== 0) { + //} + //else { + //wglSwapIntervalEXT = (BOOL (WINAPI*)(int))wglGetProcAddress("wglSwapIntervalEXT"); + //if(wglSwapIntervalEXT) wglSwapIntervalEXT(1); + //} + + wglMakeCurrent(hDC,hRC); + + ShowWindow(hWnd,SW_SHOW); + SetForegroundWindow(hWnd); + SetFocus(hWnd); + + render_resize(width, height); + + glClearColor(0.0f,0.0f,0.0f,0.0f); + glClearDepth(1.0f); + + return TRUE; +} + +int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) +{ + main2(); + + if(!createWindow(SAMPLE_NAME,DISPLAY_WIDTH,DISPLAY_HEIGHT)) { + MessageBox(NULL,"Can't create gl window.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return 0; + } + + init(); + + physics_create_scene(sceneId); + + SCE_PFX_PRINTF("## %s: INIT SUCCEEDED ##\n", SAMPLE_NAME); + + MSG msg; + while(s_isRunning) { + if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + if(msg.message==WM_QUIT) { + s_isRunning = false; + } + else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else { + update(); + if(simulating) physics_simulate(); + render(); + + perf_sync(); + } + } + + shutdown(); + + SCE_PFX_PRINTF("## %s: FINISHED ##\n", SAMPLE_NAME); + + releaseWindow(); + return (msg.wParam); +} + +#endif diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/physics_func.h b/Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/physics_func.h new file mode 100644 index 0000000..898ce2c --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/99_bullet_highlevel/physics_func.h @@ -0,0 +1,49 @@ +/* +Physics Effects Copyright(C) 2011 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef __PHYSICS_FUNC_H__ +#define __PHYSICS_FUNC_H__ + +#define SCE_PFX_USE_PERFCOUNTER + +#include "physics_effects.h" + +using namespace sce::PhysicsEffects; + +//E Simulation +//J シミュレーション +bool physics_init(); +void physics_release(); +void physics_create_scene(int sceneId); +void physics_simulate(); + +//E Picking +//J ピッキング +PfxVector3 physics_pick_start(const PfxVector3 &p1,const PfxVector3 &p2); +void physics_pick_update(const PfxVector3 &p); +void physics_pick_end(); + +//E Change parameters +//J パラメータの取得 +int physics_get_num_rigidbodies(); +const PfxRigidState& physics_get_state(int id); +const PfxRigidBody& physics_get_body(int id); +const PfxCollidable& physics_get_collidable(int id); + +int physics_get_num_contacts(); +const PfxContactManifold &physics_get_contact(int id); + +#endif /* __PHYSICS_FUNC_H__ */ diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/CMakeLists.txt b/Extras/PhysicsEffects/sample/api_physics_effects/CMakeLists.txt new file mode 100644 index 0000000..5439223 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/CMakeLists.txt @@ -0,0 +1,16 @@ +SUBDIRS( + 0_console +) + +IF (WIN32) + SUBDIRS( + 1_simple + 2_stable + 3_sleep + 4_motion_type + 5_raycast + 6_joint + 99_bullet_highlevel +# common + ) +ENDIF() \ No newline at end of file diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/api_physics_effects.windows.sln b/Extras/PhysicsEffects/sample/api_physics_effects/api_physics_effects.windows.sln new file mode 100644 index 0000000..f337433 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/api_physics_effects.windows.sln @@ -0,0 +1,164 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "1_simple.windows", "1_simple\1_simple.windows.vcproj", "{C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}" + ProjectSection(ProjectDependencies) = postProject + {4908A1B7-06F4-4517-936A-D81D140004F7} = {4908A1B7-06F4-4517-936A-D81D140004F7} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "2_stable.windows", "2_stable\2_stable.winsows.vcproj", "{4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}" + ProjectSection(ProjectDependencies) = postProject + {4908A1B7-06F4-4517-936A-D81D140004F7} = {4908A1B7-06F4-4517-936A-D81D140004F7} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "3_sleep.windows", "3_sleep\3_sleep.windows.vcproj", "{97E051D8-9233-410D-8123-E5ED749D6640}" + ProjectSection(ProjectDependencies) = postProject + {4908A1B7-06F4-4517-936A-D81D140004F7} = {4908A1B7-06F4-4517-936A-D81D140004F7} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "4_motion_type.windows", "4_motion_type\4_motion_type.windows.vcproj", "{B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}" + ProjectSection(ProjectDependencies) = postProject + {4908A1B7-06F4-4517-936A-D81D140004F7} = {4908A1B7-06F4-4517-936A-D81D140004F7} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "5_raycast.windows", "5_raycast\5_raycast.windows.vcproj", "{96B87A78-C8E3-43C5-B0E4-9A30999B2712}" + ProjectSection(ProjectDependencies) = postProject + {4908A1B7-06F4-4517-936A-D81D140004F7} = {4908A1B7-06F4-4517-936A-D81D140004F7} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "6_joint.windows", "6_joint\6_joint.windows.vcproj", "{A296A166-9E6A-44DE-BF58-30131687A117}" + ProjectSection(ProjectDependencies) = postProject + {4908A1B7-06F4-4517-936A-D81D140004F7} = {4908A1B7-06F4-4517-936A-D81D140004F7} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "physics_effects_lib.oss", "..\..\project\physics_effects_lib.oss.vcproj", "{4908A1B7-06F4-4517-936A-D81D140004F7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Win32 Debug|Win32 = Win32 Debug|Win32 + Win32 Debug|x64 = Win32 Debug|x64 + Win32 Release|Win32 = Win32 Release|Win32 + Win32 Release|x64 = Win32 Release|x64 + Win64 Debug|Win32 = Win64 Debug|Win32 + Win64 Debug|x64 = Win64 Debug|x64 + Win64 Release|Win32 = Win64 Release|Win32 + Win64 Release|x64 = Win64 Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}.Win32 Debug|Win32.ActiveCfg = Win32 Debug|Win32 + {C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}.Win32 Debug|Win32.Build.0 = Win32 Debug|Win32 + {C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}.Win32 Debug|x64.ActiveCfg = Win32 Debug|x64 + {C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}.Win32 Debug|x64.Build.0 = Win32 Debug|x64 + {C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}.Win32 Release|Win32.ActiveCfg = Win32 Release|Win32 + {C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}.Win32 Release|Win32.Build.0 = Win32 Release|Win32 + {C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}.Win32 Release|x64.ActiveCfg = Win32 Release|x64 + {C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}.Win32 Release|x64.Build.0 = Win32 Release|x64 + {C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}.Win64 Debug|Win32.ActiveCfg = Win64 Debug|x64 + {C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}.Win64 Debug|Win32.Build.0 = Win64 Debug|x64 + {C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}.Win64 Debug|x64.ActiveCfg = Win64 Debug|x64 + {C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}.Win64 Debug|x64.Build.0 = Win64 Debug|x64 + {C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}.Win64 Release|Win32.ActiveCfg = Win64 Release|x64 + {C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}.Win64 Release|Win32.Build.0 = Win64 Release|x64 + {C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}.Win64 Release|x64.ActiveCfg = Win64 Release|x64 + {C74B57DB-C7EF-4718-8BD9-9F6AE6478FAC}.Win64 Release|x64.Build.0 = Win64 Release|x64 + {4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}.Win32 Debug|Win32.ActiveCfg = Win32 Debug|Win32 + {4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}.Win32 Debug|Win32.Build.0 = Win32 Debug|Win32 + {4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}.Win32 Debug|x64.ActiveCfg = Win32 Debug|x64 + {4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}.Win32 Debug|x64.Build.0 = Win32 Debug|x64 + {4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}.Win32 Release|Win32.ActiveCfg = Win32 Release|Win32 + {4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}.Win32 Release|Win32.Build.0 = Win32 Release|Win32 + {4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}.Win32 Release|x64.ActiveCfg = Win32 Release|x64 + {4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}.Win32 Release|x64.Build.0 = Win32 Release|x64 + {4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}.Win64 Debug|Win32.ActiveCfg = Win64 Debug|x64 + {4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}.Win64 Debug|Win32.Build.0 = Win64 Debug|x64 + {4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}.Win64 Debug|x64.ActiveCfg = Win64 Debug|x64 + {4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}.Win64 Debug|x64.Build.0 = Win64 Debug|x64 + {4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}.Win64 Release|Win32.ActiveCfg = Win64 Release|x64 + {4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}.Win64 Release|Win32.Build.0 = Win64 Release|x64 + {4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}.Win64 Release|x64.ActiveCfg = Win64 Release|x64 + {4CEE7D0E-6C26-4E94-9682-6ECB73091DF7}.Win64 Release|x64.Build.0 = Win64 Release|x64 + {97E051D8-9233-410D-8123-E5ED749D6640}.Win32 Debug|Win32.ActiveCfg = Win32 Debug|Win32 + {97E051D8-9233-410D-8123-E5ED749D6640}.Win32 Debug|Win32.Build.0 = Win32 Debug|Win32 + {97E051D8-9233-410D-8123-E5ED749D6640}.Win32 Debug|x64.ActiveCfg = Win32 Debug|x64 + {97E051D8-9233-410D-8123-E5ED749D6640}.Win32 Debug|x64.Build.0 = Win32 Debug|x64 + {97E051D8-9233-410D-8123-E5ED749D6640}.Win32 Release|Win32.ActiveCfg = Win32 Release|Win32 + {97E051D8-9233-410D-8123-E5ED749D6640}.Win32 Release|Win32.Build.0 = Win32 Release|Win32 + {97E051D8-9233-410D-8123-E5ED749D6640}.Win32 Release|x64.ActiveCfg = Win32 Release|x64 + {97E051D8-9233-410D-8123-E5ED749D6640}.Win32 Release|x64.Build.0 = Win32 Release|x64 + {97E051D8-9233-410D-8123-E5ED749D6640}.Win64 Debug|Win32.ActiveCfg = Win64 Debug|x64 + {97E051D8-9233-410D-8123-E5ED749D6640}.Win64 Debug|Win32.Build.0 = Win64 Debug|x64 + {97E051D8-9233-410D-8123-E5ED749D6640}.Win64 Debug|x64.ActiveCfg = Win64 Debug|x64 + {97E051D8-9233-410D-8123-E5ED749D6640}.Win64 Debug|x64.Build.0 = Win64 Debug|x64 + {97E051D8-9233-410D-8123-E5ED749D6640}.Win64 Release|Win32.ActiveCfg = Win64 Release|x64 + {97E051D8-9233-410D-8123-E5ED749D6640}.Win64 Release|Win32.Build.0 = Win64 Release|x64 + {97E051D8-9233-410D-8123-E5ED749D6640}.Win64 Release|x64.ActiveCfg = Win64 Release|x64 + {97E051D8-9233-410D-8123-E5ED749D6640}.Win64 Release|x64.Build.0 = Win64 Release|x64 + {B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}.Win32 Debug|Win32.ActiveCfg = Win32 Debug|Win32 + {B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}.Win32 Debug|Win32.Build.0 = Win32 Debug|Win32 + {B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}.Win32 Debug|x64.ActiveCfg = Win32 Debug|x64 + {B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}.Win32 Debug|x64.Build.0 = Win32 Debug|x64 + {B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}.Win32 Release|Win32.ActiveCfg = Win32 Release|Win32 + {B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}.Win32 Release|Win32.Build.0 = Win32 Release|Win32 + {B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}.Win32 Release|x64.ActiveCfg = Win32 Release|x64 + {B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}.Win32 Release|x64.Build.0 = Win32 Release|x64 + {B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}.Win64 Debug|Win32.ActiveCfg = Win64 Debug|x64 + {B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}.Win64 Debug|Win32.Build.0 = Win64 Debug|x64 + {B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}.Win64 Debug|x64.ActiveCfg = Win64 Debug|x64 + {B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}.Win64 Debug|x64.Build.0 = Win64 Debug|x64 + {B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}.Win64 Release|Win32.ActiveCfg = Win64 Release|x64 + {B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}.Win64 Release|Win32.Build.0 = Win64 Release|x64 + {B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}.Win64 Release|x64.ActiveCfg = Win64 Release|x64 + {B4B4695B-055A-48F5-B9AC-A49F6BCAFCE2}.Win64 Release|x64.Build.0 = Win64 Release|x64 + {96B87A78-C8E3-43C5-B0E4-9A30999B2712}.Win32 Debug|Win32.ActiveCfg = Win32 Debug|Win32 + {96B87A78-C8E3-43C5-B0E4-9A30999B2712}.Win32 Debug|Win32.Build.0 = Win32 Debug|Win32 + {96B87A78-C8E3-43C5-B0E4-9A30999B2712}.Win32 Debug|x64.ActiveCfg = Win32 Debug|x64 + {96B87A78-C8E3-43C5-B0E4-9A30999B2712}.Win32 Debug|x64.Build.0 = Win32 Debug|x64 + {96B87A78-C8E3-43C5-B0E4-9A30999B2712}.Win32 Release|Win32.ActiveCfg = Win32 Release|Win32 + {96B87A78-C8E3-43C5-B0E4-9A30999B2712}.Win32 Release|Win32.Build.0 = Win32 Release|Win32 + {96B87A78-C8E3-43C5-B0E4-9A30999B2712}.Win32 Release|x64.ActiveCfg = Win32 Release|x64 + {96B87A78-C8E3-43C5-B0E4-9A30999B2712}.Win32 Release|x64.Build.0 = Win32 Release|x64 + {96B87A78-C8E3-43C5-B0E4-9A30999B2712}.Win64 Debug|Win32.ActiveCfg = Win64 Debug|x64 + {96B87A78-C8E3-43C5-B0E4-9A30999B2712}.Win64 Debug|Win32.Build.0 = Win64 Debug|x64 + {96B87A78-C8E3-43C5-B0E4-9A30999B2712}.Win64 Debug|x64.ActiveCfg = Win64 Debug|x64 + {96B87A78-C8E3-43C5-B0E4-9A30999B2712}.Win64 Debug|x64.Build.0 = Win64 Debug|x64 + {96B87A78-C8E3-43C5-B0E4-9A30999B2712}.Win64 Release|Win32.ActiveCfg = Win64 Release|x64 + {96B87A78-C8E3-43C5-B0E4-9A30999B2712}.Win64 Release|Win32.Build.0 = Win64 Release|x64 + {96B87A78-C8E3-43C5-B0E4-9A30999B2712}.Win64 Release|x64.ActiveCfg = Win64 Release|x64 + {96B87A78-C8E3-43C5-B0E4-9A30999B2712}.Win64 Release|x64.Build.0 = Win64 Release|x64 + {A296A166-9E6A-44DE-BF58-30131687A117}.Win32 Debug|Win32.ActiveCfg = Win32 Debug|Win32 + {A296A166-9E6A-44DE-BF58-30131687A117}.Win32 Debug|Win32.Build.0 = Win32 Debug|Win32 + {A296A166-9E6A-44DE-BF58-30131687A117}.Win32 Debug|x64.ActiveCfg = Win32 Debug|x64 + {A296A166-9E6A-44DE-BF58-30131687A117}.Win32 Debug|x64.Build.0 = Win32 Debug|x64 + {A296A166-9E6A-44DE-BF58-30131687A117}.Win32 Release|Win32.ActiveCfg = Win32 Release|Win32 + {A296A166-9E6A-44DE-BF58-30131687A117}.Win32 Release|Win32.Build.0 = Win32 Release|Win32 + {A296A166-9E6A-44DE-BF58-30131687A117}.Win32 Release|x64.ActiveCfg = Win32 Release|x64 + {A296A166-9E6A-44DE-BF58-30131687A117}.Win32 Release|x64.Build.0 = Win32 Release|x64 + {A296A166-9E6A-44DE-BF58-30131687A117}.Win64 Debug|Win32.ActiveCfg = Win64 Debug|x64 + {A296A166-9E6A-44DE-BF58-30131687A117}.Win64 Debug|Win32.Build.0 = Win64 Debug|x64 + {A296A166-9E6A-44DE-BF58-30131687A117}.Win64 Debug|x64.ActiveCfg = Win64 Debug|x64 + {A296A166-9E6A-44DE-BF58-30131687A117}.Win64 Debug|x64.Build.0 = Win64 Debug|x64 + {A296A166-9E6A-44DE-BF58-30131687A117}.Win64 Release|Win32.ActiveCfg = Win64 Release|x64 + {A296A166-9E6A-44DE-BF58-30131687A117}.Win64 Release|Win32.Build.0 = Win64 Release|x64 + {A296A166-9E6A-44DE-BF58-30131687A117}.Win64 Release|x64.ActiveCfg = Win64 Release|x64 + {A296A166-9E6A-44DE-BF58-30131687A117}.Win64 Release|x64.Build.0 = Win64 Release|x64 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win32 Debug|Win32.ActiveCfg = Win32 Debug|Win32 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win32 Debug|Win32.Build.0 = Win32 Debug|Win32 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win32 Debug|x64.ActiveCfg = Win32 Debug|x64 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win32 Debug|x64.Build.0 = Win32 Debug|x64 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win32 Release|Win32.ActiveCfg = Win32 Release|Win32 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win32 Release|Win32.Build.0 = Win32 Release|Win32 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win32 Release|x64.ActiveCfg = Win32 Release|x64 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win32 Release|x64.Build.0 = Win32 Release|x64 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win64 Debug|Win32.ActiveCfg = Win64 Debug|Win32 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win64 Debug|Win32.Build.0 = Win64 Debug|Win32 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win64 Debug|x64.ActiveCfg = Win64 Debug|x64 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win64 Debug|x64.Build.0 = Win64 Debug|x64 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win64 Release|Win32.ActiveCfg = Win64 Release|x64 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win64 Release|Win32.Build.0 = Win64 Release|x64 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win64 Release|x64.ActiveCfg = Win64 Release|x64 + {4908A1B7-06F4-4517-936A-D81D140004F7}.Win64 Release|x64.Build.0 = Win64 Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/common/box.h b/Extras/PhysicsEffects/sample/api_physics_effects/common/box.h new file mode 100644 index 0000000..716ee8e --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/common/box.h @@ -0,0 +1,70 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define NUM_BOX_VTX 36 +#define NUM_BOX_IDX 36 +const float box_vtx[] = { + -0.500000f,-0.500000f,-0.500000f,0.000000f,0.000000f,-1.000000f, + -0.500000f,0.500000f,-0.500000f,0.000000f,0.000000f,-1.000000f, + 0.500000f,0.500000f,-0.500000f,0.000000f,0.000000f,-1.000000f, + -0.500000f,-0.500000f,-0.500000f,0.000000f,0.000000f,-1.000000f, + 0.500000f,0.500000f,-0.500000f,0.000000f,0.000000f,-1.000000f, + 0.500000f,-0.500000f,-0.500000f,0.000000f,0.000000f,-1.000000f, + -0.500000f,-0.500000f,-0.500000f,0.000000f,-1.000000f,0.000000f, + 0.500000f,-0.500000f,-0.500000f,0.000000f,-1.000000f,0.000000f, + 0.500000f,-0.500000f,0.500000f,0.000000f,-1.000000f,0.000000f, + -0.500000f,-0.500000f,-0.500000f,0.000000f,-1.000000f,0.000000f, + 0.500000f,-0.500000f,0.500000f,0.000000f,-1.000000f,0.000000f, + -0.500000f,-0.500000f,0.500000f,0.000000f,-1.000000f,0.000000f, + -0.500000f,-0.500000f,-0.500000f,-1.000000f,0.000000f,0.000000f, + -0.500000f,-0.500000f,0.500000f,-1.000000f,0.000000f,0.000000f, + -0.500000f,0.500000f,0.500000f,-1.000000f,0.000000f,0.000000f, + -0.500000f,-0.500000f,-0.500000f,-1.000000f,0.000000f,0.000000f, + -0.500000f,0.500000f,0.500000f,-1.000000f,0.000000f,0.000000f, + -0.500000f,0.500000f,-0.500000f,-1.000000f,0.000000f,0.000000f, + -0.500000f,-0.500000f,0.500000f,0.000000f,0.000000f,1.000000f, + 0.500000f,-0.500000f,0.500000f,0.000000f,0.000000f,1.000000f, + 0.500000f,0.500000f,0.500000f,0.000000f,0.000000f,1.000000f, + -0.500000f,-0.500000f,0.500000f,0.000000f,0.000000f,1.000000f, + 0.500000f,0.500000f,0.500000f,0.000000f,0.000000f,1.000000f, + -0.500000f,0.500000f,0.500000f,0.000000f,0.000000f,1.000000f, + -0.500000f,0.500000f,-0.500000f,0.000000f,1.000000f,0.000000f, + -0.500000f,0.500000f,0.500000f,0.000000f,1.000000f,0.000000f, + 0.500000f,0.500000f,0.500000f,0.000000f,1.000000f,0.000000f, + -0.500000f,0.500000f,-0.500000f,0.000000f,1.000000f,0.000000f, + 0.500000f,0.500000f,0.500000f,0.000000f,1.000000f,0.000000f, + 0.500000f,0.500000f,-0.500000f,0.000000f,1.000000f,0.000000f, + 0.500000f,-0.500000f,-0.500000f,1.000000f,0.000000f,0.000000f, + 0.500000f,0.500000f,-0.500000f,1.000000f,0.000000f,0.000000f, + 0.500000f,0.500000f,0.500000f,1.000000f,0.000000f,0.000000f, + 0.500000f,-0.500000f,-0.500000f,1.000000f,0.000000f,0.000000f, + 0.500000f,0.500000f,0.500000f,1.000000f,0.000000f,0.000000f, + 0.500000f,-0.500000f,0.500000f,1.000000f,0.000000f,0.000000f, +}; +const unsigned short box_idx[] = { + 0,1,2, + 3,4,5, + 6,7,8, + 9,10,11, + 12,13,14, + 15,16,17, + 18,19,20, + 21,22,23, + 24,25,26, + 27,28,29, + 30,31,32, + 33,34,35, +}; diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/common/common.h b/Extras/PhysicsEffects/sample/api_physics_effects/common/common.h new file mode 100644 index 0000000..a1bdea2 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/common/common.h @@ -0,0 +1,31 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include +#include +#include +#include +#include + +// Platform specific +#ifdef _WIN32 + #include +#endif + +#endif /* __COMMON_H__ */ diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/common/ctrl_func.android.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/common/ctrl_func.android.cpp new file mode 100644 index 0000000..aa56a3a --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/common/ctrl_func.android.cpp @@ -0,0 +1,57 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "common.h" +#include "ctrl_func.h" + +int keyState[2][BTN_NUM] = {0}; +int keySw = 0; + +void ctrl_init() +{ + keySw = 0; +} + +void ctrl_release() +{ +} + +void ctrl_update() +{ +} + +ButtonStatus ctrl_button_pressed(ButtonID btnId) +{ + if(keyState[1-keySw][btnId] && !keyState[keySw][btnId]) { + return BTN_STAT_DOWN; + } + else if(keyState[1-keySw][btnId] && keyState[keySw][btnId]) { + return BTN_STAT_KEEP; + } + else if(!keyState[1-keySw][btnId] && keyState[keySw][btnId]) { + return BTN_STAT_UP; + } + + return BTN_STAT_NONE; +} + +void ctrl_set_screen_size(int w,int h) +{ +} + +void ctrl_get_cursor_position(int &cursorX,int &cursorY) +{ +} diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/common/ctrl_func.h b/Extras/PhysicsEffects/sample/api_physics_effects/common/ctrl_func.h new file mode 100644 index 0000000..2cf2fb7 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/common/ctrl_func.h @@ -0,0 +1,51 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef __CTRL_FUNC_H__ +#define __CTRL_FUNC_H__ + +enum ButtonID { + BTN_SCENE_RESET=0, + BTN_SCENE_NEXT, + BTN_SIMULATION, + BTN_STEP, + BTN_UP, + BTN_DOWN, + BTN_LEFT, + BTN_RIGHT, + BTN_ZOOM_IN, + BTN_ZOOM_OUT, + BTN_PICK, + BTN_NUM +}; + +enum ButtonStatus { + BTN_STAT_NONE = 0, + BTN_STAT_DOWN, + BTN_STAT_UP, + BTN_STAT_KEEP +}; + +void ctrl_init(); +void ctrl_release(); +void ctrl_update(); + +void ctrl_set_screen_size(int w,int h); +void ctrl_get_cursor_position(int &cursorX,int &cursorY); + +ButtonStatus ctrl_button_pressed(ButtonID btnId); + +#endif /* __CTRL_FUNC_H__ */ diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/common/ctrl_func.win32.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/common/ctrl_func.win32.cpp new file mode 100644 index 0000000..ce31098 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/common/ctrl_func.win32.cpp @@ -0,0 +1,78 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "common.h" +#include "ctrl_func.h" + +int keyState[2][BTN_NUM] = {0}; +int keySw = 0; + +void ctrl_init() +{ + keySw = 0; +} + +void ctrl_release() +{ +} + +void ctrl_update() +{ + keyState[keySw][BTN_SCENE_RESET] = GetAsyncKeyState(VK_F1); + keyState[keySw][BTN_SCENE_NEXT] = GetAsyncKeyState(VK_F2); + keyState[keySw][BTN_SIMULATION] = GetAsyncKeyState(VK_F3); + keyState[keySw][BTN_STEP] = GetAsyncKeyState(VK_F4); + keyState[keySw][BTN_UP] = GetAsyncKeyState(VK_UP); + keyState[keySw][BTN_DOWN] = GetAsyncKeyState(VK_DOWN); + keyState[keySw][BTN_LEFT] = GetAsyncKeyState(VK_LEFT); + keyState[keySw][BTN_RIGHT] = GetAsyncKeyState(VK_RIGHT); + keyState[keySw][BTN_ZOOM_IN] = GetAsyncKeyState(VK_INSERT); + keyState[keySw][BTN_ZOOM_OUT] = GetAsyncKeyState(VK_DELETE); + keyState[keySw][BTN_PICK] = GetAsyncKeyState(VK_LBUTTON); + keySw = 1-keySw; +} + +ButtonStatus ctrl_button_pressed(ButtonID btnId) +{ + if(keyState[1-keySw][btnId] && !keyState[keySw][btnId]) { + return BTN_STAT_DOWN; + } + else if(keyState[1-keySw][btnId] && keyState[keySw][btnId]) { + return BTN_STAT_KEEP; + } + else if(!keyState[1-keySw][btnId] && keyState[keySw][btnId]) { + return BTN_STAT_UP; + } + + return BTN_STAT_NONE; +} + +void ctrl_set_screen_size(int w,int h) +{ +} + +void ctrl_get_cursor_position(int &cursorX,int &cursorY) +{ + HWND hWnd = ::GetActiveWindow(); + + POINT pnt; + RECT rect; + ::GetCursorPos(&pnt); + ::ScreenToClient(hWnd,&pnt); + ::GetClientRect(hWnd,&rect); + cursorX = pnt.x - (rect.right - rect.left) / 2; + cursorY = (rect.bottom-rect.top) / 2 - pnt.y; +} diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/common/cylinder.h b/Extras/PhysicsEffects/sample/api_physics_effects/common/cylinder.h new file mode 100644 index 0000000..bba5d2a --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/common/cylinder.h @@ -0,0 +1,154 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#define NUM_CYLINDER_VTX 68 +#define NUM_CYLINDER_IDX 192 +const float cylinder_vtx[] = { +-1.0f,0.0f,0.0f, -1.0f,0.0f,0.0f, +-1.0f,-0.923879f,-0.382683f, -1.0f,0.0f,0.0f, +-1.0f,-1.0f,1.62921e-007f, -1.0f,0.0f,0.0f, +-1.0f,-0.707107f,-0.707107f, -1.0f,0.0f,0.0f, +-1.0f,-0.382683f,-0.923879f, -1.0f,0.0f,0.0f, +-1.0f,0.0f,-1.0f, -1.0f,0.0f,0.0f, +-1.0f,0.382684f,-0.923879f, -1.0f,0.0f,0.0f, +-1.0f,0.707107f,-0.707107f, -1.0f,0.0f,0.0f, +-1.0f,0.92388f,-0.382683f, -1.0f,0.0f,0.0f, +-1.0f,1.0f,-1.62921e-007f, -1.0f,0.0f,0.0f, +-1.0f,0.92388f,0.382683f, -1.0f,0.0f,0.0f, +-1.0f,0.707107f,0.707107f, -1.0f,0.0f,0.0f, +-1.0f,0.382684f,0.92388f, -1.0f,0.0f,0.0f, +-1.0f,1.50996e-007f,1.0f, -1.0f,0.0f,0.0f, +-1.0f,-0.382683f,0.92388f, -1.0f,0.0f,0.0f, +-1.0f,-0.707107f,0.707107f, -1.0f,0.0f,0.0f, +-1.0f,-0.92388f,0.382683f, -1.0f,0.0f,0.0f, +1.0f,0.0f,0.0f, 1.0f,0.0f,0.0f, +1.0f,-1.0f,0.0f, 1.0f,0.0f,0.0f, +1.0f,-0.92388f,-0.382683f, 1.0f,0.0f,0.0f, +1.0f,-0.707107f,-0.707107f, 1.0f,0.0f,0.0f, +1.0f,-0.382684f,-0.92388f, 1.0f,0.0f,0.0f, +1.0f,-1.19209e-007f,-1.0f, 1.0f,0.0f,0.0f, +1.0f,0.382683f,-0.92388f, 1.0f,0.0f,0.0f, +1.0f,0.707107f,-0.707107f, 1.0f,0.0f,0.0f, +1.0f,0.923879f,-0.382684f, 1.0f,0.0f,0.0f, +1.0f,1.0f,-3.13917e-007f, 1.0f,0.0f,0.0f, +1.0f,0.92388f,0.382683f, 1.0f,0.0f,0.0f, +1.0f,0.707107f,0.707106f, 1.0f,0.0f,0.0f, +1.0f,0.382684f,0.923879f, 1.0f,0.0f,0.0f, +1.0f,0.0f,1.0f, 1.0f,0.0f,0.0f, +1.0f,-0.382684f,0.923879f, 1.0f,0.0f,0.0f, +1.0f,-0.707107f,0.707107f, 1.0f,0.0f,0.0f, +1.0f,-0.92388f,0.382683f, 1.0f,0.0f,0.0f, +-1.0f,-1.0f,1.62921e-007f, 0.0f,-1.0f,0.0f, +1.0f,-0.92388f,-0.382683f, 0.0f,-0.92388f,-0.382683f, +1.0f,-1.0f,0.0f, 0.0f,-1.0f,0.0f, +-1.0f,-0.923879f,-0.382683f, 0.0f,-0.92388f,-0.382683f, +1.0f,-0.707107f,-0.707107f, 0.0f,-0.707107f,-0.707107f, +-1.0f,-0.707107f,-0.707107f, 0.0f,-0.707107f,-0.707107f, +1.0f,-0.382684f,-0.92388f, 0.0f,-0.382684f,-0.92388f, +-1.0f,-0.382683f,-0.923879f, 0.0f,-0.382683f,-0.92388f, +1.0f,-1.19209e-007f,-1.0f, 0.0f,0.0f,-1.0f, +-1.0f,0.0f,-1.0f, 0.0f,0.0f,-1.0f, +-1.0f,0.0f,-1.0f, 0.0f,0.0f,-1.0f, +1.0f,0.382683f,-0.92388f, 0.0f,0.382683f,-0.92388f, +1.0f,-1.19209e-007f,-1.0f, 0.0f,0.0f,-1.0f, +-1.0f,0.382684f,-0.923879f, 0.0f,0.382683f,-0.92388f, +1.0f,0.707107f,-0.707107f, 0.0f,0.707107f,-0.707107f, +-1.0f,0.707107f,-0.707107f, 0.0f,0.707107f,-0.707107f, +1.0f,0.923879f,-0.382684f, 0.0f,0.923879f,-0.382684f, +-1.0f,0.92388f,-0.382683f, 0.0f,0.923879f,-0.382684f, +1.0f,1.0f,-3.13917e-007f, 0.0f,1.0f,-2.03489e-007f, +-1.0f,1.0f,-1.62921e-007f, 0.0f,1.0f,-2.13162e-007f, +1.0f,0.92388f,0.382683f, 0.0f,0.92388f,0.382683f, +-1.0f,0.92388f,0.382683f, 0.0f,0.92388f,0.382683f, +1.0f,0.707107f,0.707106f, 0.0f,0.707107f,0.707107f, +-1.0f,0.707107f,0.707107f, 0.0f,0.707107f,0.707107f, +1.0f,0.382684f,0.923879f, 0.0f,0.382684f,0.923879f, +-1.0f,0.382684f,0.92388f, 0.0f,0.382684f,0.923879f, +1.0f,0.0f,1.0f, 0.0f,0.0f,1.0f, +-1.0f,1.50996e-007f,1.0f, 0.0f,0.0f,1.0f, +1.0f,-0.382684f,0.923879f, 0.0f,-0.382684f,0.92388f, +-1.0f,-0.382683f,0.92388f, 0.0f,-0.382683f,0.92388f, +1.0f,-0.707107f,0.707107f, 0.0f,-0.707107f,0.707107f, +-1.0f,-0.707107f,0.707107f, 0.0f,-0.707107f,0.707107f, +1.0f,-0.92388f,0.382683f, 0.0f,-0.92388f,0.382683f, +-1.0f,-0.92388f,0.382683f, 0.0f,-0.92388f,0.382683f, +}; +const unsigned short cylinder_idx[] = { +0,1,2, +0,3,1, +0,4,3, +0,5,4, +0,6,5, +0,7,6, +0,8,7, +0,9,8, +0,10,9, +0,11,10, +0,12,11, +0,13,12, +0,14,13, +0,15,14, +0,16,15, +0,2,16, +17,18,19, +17,19,20, +17,20,21, +17,21,22, +17,22,23, +17,23,24, +17,24,25, +17,25,26, +17,26,27, +17,27,28, +17,28,29, +17,29,30, +17,30,31, +17,31,32, +17,32,33, +17,33,18, +34,35,36, +34,37,35, +37,38,35, +37,39,38, +39,40,38, +39,41,40, +41,42,40, +41,43,42, +44,45,46, +44,47,45, +47,48,45, +47,49,48, +49,50,48, +49,51,50, +51,52,50, +51,53,52, +53,54,52, +53,55,54, +55,56,54, +55,57,56, +57,58,56, +57,59,58, +59,60,58, +59,61,60, +61,62,60, +61,63,62, +63,64,62, +63,65,64, +65,66,64, +65,67,66, +67,36,66, +67,34,36, +}; diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/common/jni/physicseffects-android.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/common/jni/physicseffects-android.cpp new file mode 100644 index 0000000..9a42ad3 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/common/jni/physicseffects-android.cpp @@ -0,0 +1,241 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include "physicseffects-android.h" +#include "../render_func.h" +#include "../perf_func.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//---------------------------------------------------------------------------- +// Java_pfx_renderingsupport_PhysicsEffectsRenderer_nativePhysicsEffectsInit +// +/// Implementation of JNI function to initilize the simulation and start the +/// first scene. +/// +/// @param env Pointer to JNI environment +//---------------------------------------------------------------------------- +void +Java_pfx_renderingsupport_PhysicsEffectsRenderer_nativePhysicsEffectsInit( JNIEnv* env ) +{ + init(); + sceneChange(); +} + +//---------------------------------------------------------------------------- +// Java_pfx_renderingsupport_PhysicsEffectsRenderer_nativePhysicsEffectsSimulate +// +/// Implementation of JNI function to update the simulation and view parameters, +/// perform one simulation step, and redraw the scene. +/// +/// @param env Pointer to JNI environment +//---------------------------------------------------------------------------- +void +Java_pfx_renderingsupport_PhysicsEffectsRenderer_nativePhysicsEffectsSimulate( JNIEnv* env ) +{ + update(); + physics_simulate(); + render(); + perf_sync(); +} + +//---------------------------------------------------------------------------- +// Java_pfx_renderingsupport_PhysicsEffectsRenderer_nativePhysicsEffectsUpdate +// +/// Implementation of JNI function to update the camera view and simulation +/// parameters. +/// +/// @param env Pointer to JNI environment +//---------------------------------------------------------------------------- +void +Java_pfx_renderingsupport_PhysicsEffectsRenderer_nativePhysicsEffectsUpdate( JNIEnv* env ) +{ + update(); +} + +//---------------------------------------------------------------------------- +// Java_pfx_renderingsupport_PhysicsEffectsRenderer_nativePhysicsEffectsPhysStep +// +/// Implementation of JNI function to perform one simulation step. +/// +/// @param env Pointer to JNI environment +//---------------------------------------------------------------------------- +void +Java_pfx_renderingsupport_PhysicsEffectsRenderer_nativePhysicsEffectsPhysStep( JNIEnv* env ) +{ + physics_simulate(); +} + +//---------------------------------------------------------------------------- +// Java_pfx_renderingsupport_PhysicsEffectsRenderer_nativePhysicsEffectsRender +// +/// Implementation of JNI function to render the scene. +/// +/// @param env Pointer to JNI environment +//---------------------------------------------------------------------------- +void +Java_pfx_renderingsupport_PhysicsEffectsRenderer_nativePhysicsEffectsRender( JNIEnv* env ) +{ + render(); +} + +//---------------------------------------------------------------------------- +// Java_pfx_renderingsupport_PhysicsEffectsGLSurfaceView_nativeSceneChange +// +/// Implementation of JNI function to change to the next scene. +/// +/// @param env Pointer to JNI environment +//---------------------------------------------------------------------------- +void +Java_pfx_renderingsupport_PhysicsEffectsGLSurfaceView_nativeSceneChange( JNIEnv* env ) +{ + sceneChange(); +} + +//---------------------------------------------------------------------------- +// Java_pfx_renderingsupport_PhysicsEffectsGLSurfaceView_nativeCameraUp +// +/// Implementation of JNI function to tilt the camera up +/// +/// @param env Pointer to JNI environment +//---------------------------------------------------------------------------- +void +Java_pfx_renderingsupport_PhysicsEffectsGLSurfaceView_nativeCameraUp( JNIEnv* env ) +{ + float angX, angY, r; + render_get_view_angle(angX, angY, r); + + angX -= 0.05f; + if(angX < -1.4f) angX = -1.4f; + if(angX > -0.01f) angX = -0.01f; + + render_set_view_angle(angX, angY, r); +} + +//---------------------------------------------------------------------------- +// Java_pfx_renderingsupport_PhysicsEffectsGLSurfaceView_nativeCameraDown +// +/// Implementation of JNI function to tilt the camera down +/// +/// @param env Pointer to JNI environment +//---------------------------------------------------------------------------- +void +Java_pfx_renderingsupport_PhysicsEffectsGLSurfaceView_nativeCameraDown( JNIEnv* env ) +{ + float angX, angY, r; + render_get_view_angle(angX, angY, r); + + angX += 0.05f; + if(angX < -1.4f) angX = -1.4f; + if(angX > -0.01f) angX = -0.01f; + + render_set_view_angle(angX, angY, r); +} + +//---------------------------------------------------------------------------- +// Java_pfx_renderingsupport_PhysicsEffectsGLSurfaceView_nativeCameraLeft +// +/// Implementation of JNI function to tilt the camera left +/// +/// @param env Pointer to JNI environment +//---------------------------------------------------------------------------- +void +Java_pfx_renderingsupport_PhysicsEffectsGLSurfaceView_nativeCameraLeft( JNIEnv* env ) +{ + float angX, angY, r; + render_get_view_angle(angX, angY, r); + + angY -= 0.05f; + + render_set_view_angle(angX, angY, r); +} + +//---------------------------------------------------------------------------- +// Java_pfx_renderingsupport_PhysicsEffectsGLSurfaceView_nativeCameraRight +// +/// Implementation of JNI function to tilt the camera right +/// +/// @param env Pointer to JNI environment +//---------------------------------------------------------------------------- +void +Java_pfx_renderingsupport_PhysicsEffectsGLSurfaceView_nativeCameraRight( JNIEnv* env ) +{ + float angX, angY, r; + render_get_view_angle(angX, angY, r); + + angY += 0.05f; + + render_set_view_angle(angX, angY, r); +} + +//---------------------------------------------------------------------------- +// Java_pfx_renderingsupport_PhysicsEffectsGLSurfaceView_nativeCameraZoomOut +// +/// Implementation of JNI function to dolly the camera away from scene, +/// effectively zooming out. +/// +/// @param env Pointer to JNI environment +//---------------------------------------------------------------------------- +void +Java_pfx_renderingsupport_PhysicsEffectsGLSurfaceView_nativeCameraZoomOut( JNIEnv* env ) +{ + float angX, angY, r; + render_get_view_angle(angX, angY, r); + + r *= 1.1f; + if(r > 500.0f) r = 500.0f; + + render_set_view_angle(angX, angY, r); +} + +//---------------------------------------------------------------------------- +// Java_pfx_renderingsupport_PhysicsEffectsGLSurfaceView_nativeCameraZoomIn +// +/// Implementation of JNI function to dolly the camera towards scene, +/// effectively zooming in. +/// +/// @param env Pointer to JNI environment +//---------------------------------------------------------------------------- +void +Java_pfx_renderingsupport_PhysicsEffectsGLSurfaceView_nativeCameraZoomIn( JNIEnv* env ) +{ + float angX, angY, r; + render_get_view_angle(angX, angY, r); + + r *= 0.9f; + if(r < 1.0f) r = 1.0f; + + render_set_view_angle(angX, angY, r); +} + +#ifdef __cplusplus +} +#endif diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/common/jni/physicseffects-android.h b/Extras/PhysicsEffects/sample/api_physics_effects/common/jni/physicseffects-android.h new file mode 100644 index 0000000..1229cdf --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/common/jni/physicseffects-android.h @@ -0,0 +1,40 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef PHYSICSEFFECTS_ANDROID_H +#define PHYSICSEFFECTS_ANDROID_H + +// The following C++ functions must be provided by the +// sample application. +extern int init(); +extern void render(void); +extern void sceneChange(); +extern void update(void); +extern void physics_simulate(); + +#endif // !PHYSICSEFFECTS_ANDROID_H diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/common/perf_func.android.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/common/perf_func.android.cpp new file mode 100644 index 0000000..2b3d565 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/common/perf_func.android.cpp @@ -0,0 +1,38 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "common.h" +#include "perf_func.h" + +void perf_init() +{ +} + +void perf_release() +{ +} + +void perf_push_marker(char *str) +{ +} + +void perf_pop_marker() +{ +} + +void perf_sync() +{ +} diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/common/perf_func.h b/Extras/PhysicsEffects/sample/api_physics_effects/common/perf_func.h new file mode 100644 index 0000000..2868fe2 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/common/perf_func.h @@ -0,0 +1,26 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef __PERF_FUNC_H__ +#define __PERF_FUNC_H__ + +void perf_init(); +void perf_release(); +void perf_push_marker(char *str); +void perf_pop_marker(); +void perf_sync(); + +#endif /* __PERF_FUNC_H__ */ diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/common/perf_func.win32.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/common/perf_func.win32.cpp new file mode 100644 index 0000000..2b3d565 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/common/perf_func.win32.cpp @@ -0,0 +1,38 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "common.h" +#include "perf_func.h" + +void perf_init() +{ +} + +void perf_release() +{ +} + +void perf_push_marker(char *str) +{ +} + +void perf_pop_marker() +{ +} + +void perf_sync() +{ +} diff --git a/Extras/PhysicsEffects/sample/api_physics_effects/common/render_func.android.cpp b/Extras/PhysicsEffects/sample/api_physics_effects/common/render_func.android.cpp new file mode 100644 index 0000000..cadc809 --- /dev/null +++ b/Extras/PhysicsEffects/sample/api_physics_effects/common/render_func.android.cpp @@ -0,0 +1,486 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "render_func.h" + +#include "box.h" +#include "sphere.h" +#include "cylinder.h" + +#include +#include + +// local variables +static int screen_width,screen_height; +static PfxMatrix4 g_pMat,g_vMat; +static PfxVector3 g_viewPos,g_lightPos,g_viewTgt; +static float lightRadius,lightRadX,lightRadY; +static float viewRadius,viewRadX,viewRadY,viewHeight; + +static unsigned short *box_wire_idx; +static unsigned short *sphere_wire_idx; +static unsigned short *cylinder_wire_idx; + +#define MAX_MESH 5 + +static struct MeshBuff { + float *vtx; + float *nml; + int numVtx; + unsigned short *idx; + unsigned short *wire_idx; + int numIdx; +} meshBuff[MAX_MESH]; +int numMesh; + +void render_init() +{ + screen_width = DISPLAY_WIDTH; + screen_height = DISPLAY_HEIGHT; + + // initalize matrix + g_pMat = PfxMatrix4::perspective(3.1415f/4.0f, (float)screen_width/(float)screen_height,0.1f, 1000.0f); + + // initalize parameters + lightRadius = 40.0f; + lightRadX = -0.6f; + lightRadY = 0.6f; + viewRadius = 40.0f; + viewRadX = -0.01f; + viewRadY = 0.0f; + viewHeight = 1.0f; + + g_viewTgt = PfxVector3(0.0f,viewHeight,0.0f); + + box_wire_idx = new unsigned short [NUM_BOX_IDX*2]; + sphere_wire_idx = new unsigned short [NUM_SPHERE_IDX*2]; + cylinder_wire_idx = new unsigned short [NUM_CYLINDER_IDX*2]; + + for(int i=0;i 0) { + for(int i=0;i=0&&meshId + +#include "box.h" +#include "sphere.h" +#include "cylinder.h" + +// context +HDC hDC; +HGLRC hRC; + +// local variables +static int screen_width,screen_height; +static PfxMatrix4 g_pMat,g_vMat; +static PfxVector3 g_viewPos,g_lightPos,g_viewTgt; +static float lightRadius,lightRadX,lightRadY; +static float viewRadius,viewRadX,viewRadY,viewHeight; + +static unsigned short *box_wire_idx; +static unsigned short *sphere_wire_idx; +static unsigned short *cylinder_wire_idx; + +#define MAX_MESH 5 + +static struct MeshBuff { + float *vtx; + float *nml; + int numVtx; + unsigned short *idx; + unsigned short *wire_idx; + int numIdx; +} meshBuff[MAX_MESH]; +int numMesh; + +void render_init() +{ + screen_width = DISPLAY_WIDTH; + screen_height = DISPLAY_HEIGHT; + + // initalize matrix + g_pMat = PfxMatrix4::perspective(3.1415f/4.0f, (float)screen_width/(float)screen_height,0.1f, 1000.0f); + + // initalize parameters + lightRadius = 40.0f; + lightRadX = -0.6f; + lightRadY = 0.6f; + viewRadius = 40.0f; + viewRadX = -0.01f; + viewRadY = 0.0f; + viewHeight = 1.0f; + + g_viewTgt = PfxVector3(0.0f,viewHeight,0.0f); + + box_wire_idx = new unsigned short [NUM_BOX_IDX*2]; + sphere_wire_idx = new unsigned short [NUM_SPHERE_IDX*2]; + cylinder_wire_idx = new unsigned short [NUM_CYLINDER_IDX*2]; + + for(int i=0;i 0) { + for(int i=0;i=0&&meshId = d18,d19 + vld1.32 {d16,d17}, [r0] @ input = d16,d17 +@ rearrange inputs into convenient order + vtrn.32 d18,d19 @ q9 = = d18,d19 + vrev64.32 d16,d16 @ q8 = = d16,d17 + vrev64.32 d18,d18 @ q9 = = d18,d19 + vtrn.32 d16,d17 @ q8 = = d16,d17 +@ perform first half of cross product using rearranged inputs + vmul.f32 q10, q8, q9 @ q10 = +@ rearrange inputs again + vtrn.32 d18,d19 @ q9 = = d18,d19 + vrev64.32 d16,d16 @ q8 = = d16,d17 + vrev64.32 d18,d18 @ q9 = = d18,d19 + vtrn.32 d16,d17 @ q8 = = d16,d17 +@ perform last half of cross product using rearranged inputs + vmls.f32 q10, q8, q9 @ q10 = +@ and store the result + vst1.32 {q10}, [r2] + bx lr + .fnend + +@ cross product, result stored directly to memory, version 2 + + .global CrossProductNeonResultInMemoryAssembly2 + .thumb_func +CrossProductNeonResultInMemoryAssembly2: + .fnstart + vld1.32 {d18[1]}, [r1]! + vld1.32 {d19[0]}, [r1]! + vld1.32 {d18[0]}, [r1]! + vld1.32 {d19[1]}, [r1] @ q9 = = d18,d19 + vld1.32 {d17[0]}, [r0]! + vld1.32 {d16}, [r0]! + vld1.32 {d17[1]}, [r0] @ q8 = = d16,d17 +@ perform first half of cross product using rearranged inputs + vmul.f32 q10, q8, q9 @ q10 = +@ rearrange inputs for second half + vtrn.32 d18,d19 @ q9 = = d18,d19 + vrev64.32 d16,d16 @ q8 = = d16,d17 + vrev64.32 d18,d18 @ q9 = = d18,d19 + vtrn.32 d16,d17 @ q8 = = d16,d17 +@ perform last half of cross product using rearranged inputs + vmls.f32 q10, q8, q9 @ q10 = +@ and store the result + vst1.32 {q10}, [r2] + bx lr + .fnend + + .global CrossProductNeonResultInMemoryAssembly3 + .thumb_func +CrossProductNeonResultInMemoryAssembly3: + .fnstart + vld1.32 {d18[1]}, [r1]! + vld1.32 {d19[0]}, [r1]! + vld1.32 {d18[0]}, [r1]! + vld1.32 {d19[1]}, [r1]! @ q9 = = d18,d19 + vld1.32 {d17[0]}, [r0]! + vld1.32 {d16}, [r0]! + vld1.32 {d17[1]}, [r0]! @ q8 = = d16,d17 +@ perform first half of cross product using rearranged inputs + vmul.f32 q10, q8, q9 @ q10 = + vld1.32 {d18[1]}, [r0]! + vld1.32 {d19[0]}, [r0]! + vld1.32 {d18[0]}, [r0]! + vld1.32 {d19[1]}, [r0]! @ q9 = = d18,d19 + vld1.32 {d17[0]}, [r1]! + vld1.32 {d16}, [r1]! + vld1.32 {d17[1]}, [r1]! @ q8 = = d16,d17 +@ perform last half of cross product using rearranged inputs + vmls.f32 q10, q8, q9 @ q10 = +@ and store the result + vst1.32 {q10}, [r2] + bx lr + .fnend + +@ cross product, result stored directly to memory, version 3 + +@ .global CrossProductNeonResultInMemoryAssembly3 +@ .thumb_func +@CrossProductNeonResultInMemoryAssembly3: +@ .fnstart +@ ldr r3, table +@ vld1.32 {d18,d19}, [r1] @ input = d18,d19 +@ vld1.32 {d16,d17}, [r0] @ input = d16,d17 +@ rearrange inputs into convenient order +@ vld1.32 {q10}, [r3]! +@ vld1.32 {q11}, [r3] +@ vtbl.8 q12, {d18,d19}, q10 +@ vtbl.8 q13, {d16,d17}, q11 +@ perform first half of cross product using rearranged inputs +@ vmul.f32 q14, q12, q13 +@ rearrange inputs again +@ vtbl.8 q12, {d18,d19}, q11 +@ vtbl.8 q13, {d16,d17}, q10 +@ perform last half of cross product using rearranged inputs +@ vmls.f32 q14, q12, q13 +@ and store the result +@ vst1.32 {q14}, [r2] +@ bx lr +@ .fnend + +@table: +@z2,x2,y2,w2 +@ dcb 08,09,10,11,00,01,02,03,04,05,06,07,00,00,00,00 +@y1,z1,x1,w1 +@ dcb 04,05,06,07,08,09,10,11,00,01,02,03,00,00,00,00 diff --git a/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_dot_product.S b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_dot_product.S new file mode 100644 index 0000000..56aedfc --- /dev/null +++ b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_dot_product.S @@ -0,0 +1,98 @@ +@ +@ Applied Research Associates Inc. (c)2011 +@ +@ 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 Applied Research Associates Inc 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. +@ + .syntax unified + .arch armv7-a + .fpu neon + .thumb + .text + .align 2 + +@ dot product, result returned in register + + .global DotProductNeonResultInRegisterAssembly + .thumb_func +DotProductNeonResultInRegisterAssembly: + .fnstart + vld1.32 {d16,d17}, [r0] @ input + vld1.32 {d18,d19}, [r1] @ input + vmul.f32 d14, d16, d18 @ d14= + vmla.f32 d14, d17, d19 @ d14=d14+= + vpadd.f32 d14, d14, d14 @ add the two halves of d14 together, result in each lane + vmov.f32 r0, s28 @ s28 aliases the first lane of d14 + bx lr + .fnend + +@ dot product, result stored directly to memory + + .global DotProductNeonResultInMemoryAssembly + .thumb_func +DotProductNeonResultInMemoryAssembly: + .fnstart + vld1.32 {d16,d17}, [r0] @ input + vld1.32 {d18,d19}, [r1] @ input + vmul.f32 d14, d16, d18 @ d14= +@ non-fused multiple accumulate + vmla.f32 d14, d17, d19 @ d14=d14+= +@ fused multiple accumulate - not recognized by GNU assembler +@@ vfma.f32 {d14}, d17, d19 @ d14=d14+= + vpadd.f32 d14, d14, d14 @ add the two halves of d14 together, same result in each lane + vst1.32 {d14}, [r2] + bx lr + .fnend + +@ dot product, result stored directly to memory, all inputs are contiguous in memory + + .global DotProductNeonResultInMemoryAssembly2 + .thumb_func +DotProductNeonResultInMemoryAssembly2: + .fnstart + vld1.32 {d16-d19}, [r0] @ input q8=, q9= + vmul.f32 d14, d16, d18 @ d14= +@ non-fused multiple accumulate + vmla.f32 d14, d17, d19 @ d14=d14+= +@ fused multiple accumulate - not recognized by GNU assembler +@@ vfma.f32 d14, d17, d19 @ d14=d14+= + vpadd.f32 d14, d14, d14 @ add the two halves of d14 together, same result in each lane + vst1.32 {d14}, [r1] + bx lr + .fnend + +@ same as DotProductNeonResultInMemoryAssembly2, but alternate methodology to compute result + + .global DotProductNeonResultInMemoryAssembly2b + .thumb_func +DotProductNeonResultInMemoryAssembly2b: + .fnstart + vld1.32 {d14-d17}, [r0] @ input q7=, q8= + vmul.f32 q7, q7, q8 @ q7 = = d14,d15 = s28,s29,s30,s31 + vpadd.f32 d14,d14,d14 @ add elements of d14 together= + vpadd.f32 d15,d15,d15 @ add elements of d14 together= + vadd.f32 d14,d14,d15 @ add d14 and d15 together, final result in both lanes + vst1.32 {d14}, [r1] + bx lr + .fnend diff --git a/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_matrix3_operator_multiply.S b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_matrix3_operator_multiply.S new file mode 100644 index 0000000..2c4470e --- /dev/null +++ b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_matrix3_operator_multiply.S @@ -0,0 +1,62 @@ +@ +@ Applied Research Associates Inc. (c)2011 +@ +@ 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 Applied Research Associates Inc 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. +@ + .syntax unified + .arch armv7-a + .fpu neon + .thumb + .text + .align 2 + +@ matrix3 operator *, result stored directly to memory + + .global Matrix3OperatorMultiplyNeon + .thumb_func +Matrix3OperatorMultiplyNeon: + .fnstart + vld1.32 {d16-d19}, [r0]! @ load first eight elements of matrix 0 + vld1.32 {d20-d21}, [r0] @ load second eight elements of matrix 0 + vld1.32 {d0-d3}, [r1]! @ load first eight elements of matrix 1 + vld1.32 {d4-d5}, [r1] @ load second eight elements of matrix 1 + + vmul.f32 q12, q8, d0[0] @ rslt col0 = (mat0 col0) * (mat1 col0 elt0) + vmul.f32 q13, q8, d2[0] @ rslt col1 = (mat0 col0) * (mat1 col1 elt0) + vmul.f32 q14, q8, d4[0] @ rslt col2 = (mat0 col0) * (mat1 col2 elt0) + + vmla.f32 q12, q9, d0[1] @ rslt col0 += (mat0 col1) * (mat1 col0 elt1) + vmla.f32 q13, q9, d2[1] @ rslt col1 += (mat0 col1) * (mat1 col1 elt1) + vmla.f32 q14, q9, d4[1] @ rslt col2 += (mat0 col1) * (mat1 col2 elt1) + + vmla.f32 q12, q10, d1[0] @ rslt col0 += (mat0 col2) * (mat1 col0 elt2) + vmla.f32 q13, q10, d3[0] @ rslt col1 += (mat0 col2) * (mat1 col1 elt2) + vmla.f32 q14, q10, d5[0] @ rslt col2 += (mat0 col2) * (mat1 col2 elt2) + + vst1.32 {d24-d27}, [r2]! @ store first eight elements of result + vst1.32 {d28-d29}, [r2] @ store second eight elements of result + + bx lr + .fnend diff --git a/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_matrix4_operator_multiply.S b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_matrix4_operator_multiply.S new file mode 100644 index 0000000..848e998 --- /dev/null +++ b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_matrix4_operator_multiply.S @@ -0,0 +1,71 @@ +@ +@ Applied Research Associates Inc. (c)2011 +@ +@ 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 Applied Research Associates Inc 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. +@ + .syntax unified + .arch armv7-a + .fpu neon + .thumb + .text + .align 2 + +@ matrix4 operator *, result stored directly to memory + + .global Matrix4OperatorMultiplyNeon + .thumb_func +Matrix4OperatorMultiplyNeon: + .fnstart + + vld1.32 {d16-d19}, [r0]! @ load first eight elements of matrix 0 + vld1.32 {d20-d23}, [r0] @ load second eight elements of matrix 0 + vld1.32 {d0-d3}, [r1]! @ load first eight elements of matrix 1 + vld1.32 {d4-d7}, [r1] @ load second eight elements of matrix 1 + + vmul.f32 q12, q8, d0[0] @ rslt col0 = (mat0 col0) * (mat1 col0 elt0) + vmul.f32 q13, q8, d2[0] @ rslt col1 = (mat0 col0) * (mat1 col1 elt0) + vmul.f32 q14, q8, d4[0] @ rslt col2 = (mat0 col0) * (mat1 col2 elt0) + vmul.f32 q15, q8, d6[0] @ rslt col3 = (mat0 col0) * (mat1 col3 elt0) + + vmla.f32 q12, q9, d0[1] @ rslt col0 += (mat0 col1) * (mat1 col0 elt1) + vmla.f32 q13, q9, d2[1] @ rslt col1 += (mat0 col1) * (mat1 col1 elt1) + vmla.f32 q14, q9, d4[1] @ rslt col2 += (mat0 col1) * (mat1 col2 elt1) + vmla.f32 q15, q9, d6[1] @ rslt col3 += (mat0 col1) * (mat1 col3 elt1) + + vmla.f32 q12, q10, d1[0] @ rslt col0 += (mat0 col2) * (mat1 col0 elt2) + vmla.f32 q13, q10, d3[0] @ rslt col1 += (mat0 col2) * (mat1 col1 elt2) + vmla.f32 q14, q10, d5[0] @ rslt col2 += (mat0 col2) * (mat1 col2 elt2) + vmla.f32 q15, q10, d7[0] @ rslt col3 += (mat0 col2) * (mat1 col2 elt2) + + vmla.f32 q12, q11, d1[1] @ rslt col0 += (mat0 col3) * (mat1 col0 elt3) + vmla.f32 q13, q11, d3[1] @ rslt col1 += (mat0 col3) * (mat1 col1 elt3) + vmla.f32 q14, q11, d5[1] @ rslt col2 += (mat0 col3) * (mat1 col2 elt3) + vmla.f32 q15, q11, d7[1] @ rslt col3 += (mat0 col3) * (mat1 col3 elt3) + + vst1.32 {d24-d27}, [r2]! @ store first eight elements of result + vst1.32 {d28-d31}, [r2] @ store second eight elements of result + + bx lr + .fnend diff --git a/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_orthoInverse_transform3.S b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_orthoInverse_transform3.S new file mode 100644 index 0000000..161fde6 --- /dev/null +++ b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_orthoInverse_transform3.S @@ -0,0 +1,81 @@ +@ +@ Applied Research Associates Inc. (c)2011 +@ +@ 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 Applied Research Associates Inc 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. +@ + .syntax unified + .arch armv7-a + .fpu neon + .thumb + .text + .align 2 + +@ orthoInverse of a transform3, result stored directly to memory + + .global OrthoInverseTransform3Neon + .thumb_func +OrthoInverseTransform3Neon: + .fnstart +@way 1 +@ vld1.f32 {d0-d3}, [r0]! @ load first eight elements of result +@ vld1.f32 {d4-d7}, [r0] @ load second eight elements of result + +@ vzip.f32 d0, d2 +@ vzip.f32 d1, d3 +@ vswp.f32 d1, d4 +@ vzip.f32 d1, d3 + +@way 2 (faster) +@ +@ +@ NOTE NOTE! This is broken! It does not use the last column of the input! Please see +@ implementation of pfxTransform3OrthoInverseNEON in vectormath_neon_assembly_implementations.S, in +@ include/vecmath/neon, for a correct implementation! +@ + vld1.f32 d0[0], [r0]! + vld1.f32 d2[0], [r0]! + vld1.f32 d4[0], [r0]! + vld1.f32 d1[1], [r0]! + + vld1.f32 d0[1], [r0]! + vld1.f32 d2[1], [r0]! + vld1.f32 d4[1], [r0]! + vld1.f32 d3[1], [r0]! + + vld1.f32 d1[0], [r0]! + vld1.f32 d3[0], [r0]! + vld1.f32 d5[0], [r0]! + vld1.f32 d5[1], [r0] + + vmul.f32 q3, q0, d1[0] + vmla.f32 q3, q1, d3[0] + vmla.f32 q3, q2, d5[0] + vneg.f32 q3, q3 + + vst1.f32 {d0-d3}, [r1]! @ store first eight elements of result + vst1.f32 {d4-d7}, [r1] @ store second eight elements of result + + bx lr + .fnend diff --git a/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_transform3_operator_multiply.S b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_transform3_operator_multiply.S new file mode 100644 index 0000000..09c655e --- /dev/null +++ b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_transform3_operator_multiply.S @@ -0,0 +1,51 @@ +@ +@ Applied Research Associates Inc. (c)2011 +@ +@ 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 Applied Research Associates Inc 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. +@ + .syntax unified + .arch armv7-a + .fpu neon + .thumb + .text + .align 2 + +@ transform3 operator *, result stored directly to memory + + .global Transform3OperatorMultiplyNeon + .thumb_func +Transform3OperatorMultiplyNeon: + .fnstart + + vld1.32 {d16-d19}, [r0]! @ load first eight elements of transform matrix + vld1.32 {d20-d21}, [r0] @ load second eight elements of transform matrix + vld1.32 {d0-d1}, [r1] @ load the four elements of vector3 + vmul.f32 q12, q8, d0[0] @ rslt col0 = (mat0 col0) * (mat1 col0 elt0) + vmla.f32 q12, q9, d0[1] @ rslt col0 += (mat0 col1) * (mat1 col0 elt1) + vmla.f32 q12, q10, d1[0] @ rslt col0 += (mat0 col2) * (mat1 col0 elt2) + vst1.32 {d24-d25}, [r2] @ store first eight elements of result + + bx lr + .fnend diff --git a/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_transpose_matrix3.S b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_transpose_matrix3.S new file mode 100644 index 0000000..3d586bb --- /dev/null +++ b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/neon_transpose_matrix3.S @@ -0,0 +1,81 @@ +@ +@ Applied Research Associates Inc. (c)2011 +@ +@ 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 Applied Research Associates Inc 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. +@ + .syntax unified + .arch armv7-a + .fpu neon + .thumb + .text + .align 2 + +@ transpose a matrix3, result stored directly to memory + + .global TransposeMatrix3Neon + .thumb_func +TransposeMatrix3Neon: + .fnstart + +@way1 +@ vld1.f32 d0[0], [r0]! +@ vld1.f32 d2[0], [r0]! +@ vld1.f32 d4[0], [r0]! +@ vld1.f32 d1[1], [r0]! + +@ vld1.f32 d0[1], [r0]! +@ vld1.f32 d2[1], [r0]! +@ vld1.f32 d4[1], [r0]! +@ vld1.f32 d3[1], [r0]! + +@ vld1.f32 d1[0], [r0]! +@ vld1.f32 d3[0], [r0]! +@ vld1.f32 d5[0], [r0]! +@ vld1.f32 d5[1], [r0] + +@way2 +@ vld2.f32 {d0-d1}, [r0]! +@ vld2.f32 {d2-d3}, [r0]! +@ vld2.f32 {d4-d5}, [r0] + +@ vzip.f32 q0, q1 +@ vswp.f32 d1, d4 +@ vswp.f32 d3, d5 +@ vzip.f32 d1, d5 + +@way3 (Fastest) + vld1.f32 {d0-d3}, [r0]! @ store first eight elements of result + vld1.f32 {d4-d5}, [r0] @ store second eight elements of result + + vzip.f32 d0, d2 + vzip.f32 d1, d3 + vswp.f32 d1, d4 + vzip.f32 d1, d3 + + vst1.f32 {d0-d3}, [r1]! @ store first eight elements of result + vst1.f32 {d4-d5}, [r1] @ store second eight elements of result + + bx lr + .fnend diff --git a/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon.h b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon.h new file mode 100644 index 0000000..04f059e --- /dev/null +++ b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon.h @@ -0,0 +1,43 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef TEST_NEON_H +#define TEST_NEON_H + +//Neon functions to test +void TestNeonDotProduct(); +void TestNeonCrossProduct(); +void TestNeonMatrix3OperatorMultiply(); +void TestNeonMatrix4OperatorMultiply(); +void TestNeonOrthoInverseTransform3(); +void TestNeonTransform3OperatorMultiply(); +void TestNeonTransposeMatrix3(); +void TestNeonSolveLinearConstraintRow(); + +#endif // TEST_NEON_H diff --git a/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_cross_product.cpp b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_cross_product.cpp new file mode 100644 index 0000000..1350e27 --- /dev/null +++ b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_cross_product.cpp @@ -0,0 +1,229 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "test_neon.h" +#define SCE_PFX_USE_PERFCOUNTER +#include "physics_effects.h" +#include +#include +#include +#include +#include + +// This works with gcc +#define SET_ALIGNMENT(alignment) __attribute__((__aligned__((alignment)))) + +//#define PRINT_COMPUTED_VECTOR_RESULTS + +// assembly implementations +extern "C" +{ + void CrossProductNeonResultInMemoryAssembly(float *a, float *b, float *pfResult); + void CrossProductNeonResultInMemoryAssembly2(float *a, float *b, float *pfResult); + void CrossProductNeonResultInMemoryAssembly3(float *a, float *b, float *pfResult); +} + +//---------------------------------------------------------------------------- +// CrossProductNeonResultInMemory +// +/// Performs a Vector3 style cross product using NEON intrinsics, storing the +/// result directly into system memory. +/// +/// @param a Input vector 1. Must point to 4 float values +/// @param b Input vector 2. Must point to 4 float values +/// @param pfResult [in] must point to an array of at least *4* +/// float values. [out] The result of the cross +/// product is contained in the first 3 lanes. +/// +/// NOTE: The parameter types here are floats, not float32_t's. gcc +/// sometimes doesn't interpret float32_t's correctly. In particular, +/// if the type of pfResult is set to float32_t*, gcc will throw an +/// internal compiler error (ICE) for this code. In memory, float32_t +/// and float are equivalent, so can cast between them explicitly. +//---------------------------------------------------------------------------- +void CrossProductNeonResultInMemory(float *a, float *b, float *pfResult) +{ + float32x4_t v1 = {a[1],a[2],a[0], 0.0f}; + float32x4_t v2 = {b[2],b[0],b[1], 0.0f}; + float32x4_t v3 = {a[2],a[0],a[1], 0.0f}; + float32x4_t v4 = {b[1],b[2],b[0], 0.0f}; + v1 = vmulq_f32(v1, v2); + v1 = vmlsq_f32(v1, v3, v4); + vst1q_f32((float32_t*)pfResult, v1); +} + +void CrossProductNeonResultInMemoryCPPAssembly(float *a, float *b, float *result) { + asm volatile( + "vld1.32 {d18[1]}, [r1]! \n\t" + "vld1.32 {d19[0]}, [r1]! \n\t" + "vld1.32 {d18[0]}, [r1]! \n\t" + "vld1.32 {d19[1]}, [r1] \n\t" + "vld1.32 {d17[0]}, [r0]! \n\t" + "vld1.32 {d16}, [r0]! \n\t" + "vld1.32 {d17[1]}, [r0] \n\t" + "vmul.f32 q10, q8, q9 \n\t" + "vtrn.32 d18,d19 \n\t" + "vrev64.32 d16,d16 \n\t" + "vrev64.32 d18,d18 \n\t" + "vtrn.32 d16,d17 \n\t" + "vmls.f32 q10, q8, q9 \n\t" + "vst1.32 {q10}, [r2] \n\t" + ); +} + +//---------------------------------------------------------------------------- +// CrossProductScalarResultInMemory +// +/// Performs a Vector3 style cross product using scalar math, storing the +/// result directly into system memory. +/// +/// @param a Input vector 1. Must point to 4 float values +/// @param b Input vector 2. Must point to 4 float values +/// @param pfResult [in] pointer to a float. [out] Contains the +/// result, dotproduct(a,b) +//---------------------------------------------------------------------------- +void CrossProductScalarResultInMemory(float *a, float *b, float *pfResult) +{ + pfResult[0] = a[1]*b[2] - a[2]*b[1]; + pfResult[1] = a[2]*b[0] - a[0]*b[2]; + pfResult[2] = a[0]*b[1] - a[1]*b[0]; +} + +//---------------------------------------------------------------------------- +// TestFastNeonCrossProduct +// +/// Run timing study of the cross product functions above, writing the +/// results to the Android verbose log. +//---------------------------------------------------------------------------- +void TestNeonCrossProduct() +{ + float SET_ALIGNMENT(64) data[] = {float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f, + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f}; + + float *a = &data[0]; + float *b = &data[4]; + + char szMsg[256]; + + sprintf(szMsg, ""); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg,"---------------------------------------"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "Cross product test inputs A=<%f,%f,%f>, B=<%f,%f,%f>", + a[0], a[1], a[2], b[0], b[1], b[2]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + float SET_ALIGNMENT(64) fResult[4]; + + double dTimeSpan, dRefTimeSpan;; + unsigned int uiNumTries = 10000000; + unsigned int i; + + sce::PhysicsEffects::PfxPerfCounter pc; + +// profile scalar cross product with direct memory return + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + CrossProductScalarResultInMemory(a, b, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + dRefTimeSpan = dTimeSpan; + sprintf(szMsg, "Time to do %i calls for CrossProductScalarResultInMemory: %f secs, speedup: %5.2f, result value=<%f,%f,%f>", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan, fResult[0], fResult[1], fResult[2]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + + +// profile NEON assembly volatile cross product with direct memory return + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + CrossProductNeonResultInMemoryCPPAssembly(a, b, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + sprintf(szMsg, "Time to do %i calls for CrossProductNeonResultInMemoryFast: %f secs, speedup: %5.2f, result value=<%f,%f,%f>", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan, fResult[0], fResult[1], fResult[2]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + + +// profile NEON cross product with direct memory return, assembly version + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + CrossProductNeonResultInMemoryAssembly(a, b, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + sprintf(szMsg, "Time to do %i calls for CrossProductNeonResultInMemoryAssembly: %f secs, speedup: %5.2f, result value=<%f,%f,%f>", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan, fResult[0], fResult[1], fResult[2]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + + +// profile NEON cross product with direct memory return, assembly version 2 + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + CrossProductNeonResultInMemoryAssembly2(a, b, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + + sprintf(szMsg, "Time to do %i calls for CrossProductNeonResultInMemoryAssembly2: %f secs, speedup: %5.2f, result value=<%f,%f,%f>", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan, fResult[0], fResult[1], fResult[2]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + + +// profile NEON cross product with direct memory return, assembly version 3 + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + CrossProductNeonResultInMemoryAssembly3(a, b, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + + sprintf(szMsg, "Time to do %i calls for CrossProductNeonResultInMemoryAssembly3: %f secs, speedup: %5.2f, result value=<%f,%f,%f>", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan, fResult[0], fResult[1], fResult[2]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); +} diff --git a/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_dot_product.cpp b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_dot_product.cpp new file mode 100644 index 0000000..e1f5c1f --- /dev/null +++ b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_dot_product.cpp @@ -0,0 +1,330 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "test_neon.h" +#define SCE_PFX_USE_PERFCOUNTER +#include "physics_effects.h" +#include +#include +#include +#include +#include + +// This works with gcc +#define SET_ALIGNMENT(alignment) __attribute__((__aligned__((alignment)))) + +//#define PRINT_COMPUTED_VECTOR_RESULTS + +// assembly implementations +extern "C" +{ + float32_t DotProductNeonResultInRegisterAssembly(float *a, float *b); + void DotProductNeonResultInMemoryAssembly(float *a, float *b, float *pfResult); + void DotProductNeonResultInMemoryAssembly2(float *data, float *pfResult); + void DotProductNeonResultInMemoryAssembly2b(float *data, float *pfResult); +} + +//---------------------------------------------------------------------------- +// DotProductNeonResultInRegister +// +/// Performs a Vector4 style dot product using NEON intrinsics, returning +/// the result in an ARM register. +/// +/// @param a Input vector 1. Must point to 4 float values +/// @param b Input vector 2. Must point to 4 float values +/// +/// @return dotproduct(a,b) +//---------------------------------------------------------------------------- +float32_t DotProductNeonResultInRegister(float *a, float *b) +{ + float32_t result[2]; + float32x2_t v1a = vld1_f32((float32_t*)a); + float32x2_t v1b = vld1_f32((float32_t*)(a + 2)); + float32x2_t v2a = vld1_f32((float32_t*)b); + float32x2_t v2b = vld1_f32((float32_t*)(b + 2)); + v1a = vmul_f32(v1a, v2a); + v1a = vmla_f32(v1a, v1b, v2b); + v1a = vpadd_f32(v1a, v1a); + vst1_f32(result, v1a); + return(result[0]); +} + +// pfResult must point to memory large enough to store *two* +// float32_t values +//---------------------------------------------------------------------------- +// DotProductNeonResultInMemory +// +/// Performs a Vector4 style dot product using NEON intrinsics, storing the +/// result directly into system memory. +/// +/// @param a Input vector 1. Must point to 4 float values +/// @param b Input vector 2. Must point to 4 float values +/// @param pfResult [in] must point to an array of at least *2* +/// float values. [out] The result of the dot +/// product is contained in both slots of the array. +/// Recommended to use the first one though they +/// have the same value +/// +/// NOTE: The parameter types here are floats, not float32_t's. gcc +/// sometimes doesn't interpret float32_t's correctly. In particular, +/// if the type of pfResult is set to float32_t*, gcc will throw an +/// internal compiler error (ICE) for this code. In memory, float32_t +/// and float are equivalent, so can cast between them explicitly. +//---------------------------------------------------------------------------- +void DotProductNeonResultInMemory(float *a, float *b, float *pfResult) +{ + float32x2_t v1a = vld1_f32((float32_t*)a); + float32x2_t v1b = vld1_f32((float32_t*)(a + 2)); + float32x2_t v2a = vld1_f32((float32_t*)b); + float32x2_t v2b = vld1_f32((float32_t*)(b + 2)); + v1a = vmul_f32(v1a, v2a); + v1a = vmla_f32(v1a, v1b, v2b); + v1a = vpadd_f32(v1a, v1a); + vst1_f32((float32_t*)pfResult, v1a); +} + +//---------------------------------------------------------------------------- +// DotProductScalarResultInRegister +// +/// Performs a Vector4 style dot product using scalar math, and returning +/// the result in an ARM register. +/// +/// @param a Input vector 1. Must point to 4 float values +/// @param b Input vector 2. Must point to 4 float values +/// +/// @return dotproduct(a,b) +//---------------------------------------------------------------------------- +float DotProductScalarResultInRegister(float *a, float *b) +{ + return(a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3]); +} + +//---------------------------------------------------------------------------- +// DotProductScalarResultInMemory +// +/// Performs a Vector4 style dot product using scalar math, storing the +/// result directly into system memory. +/// +/// @param a Input vector 1. Must point to 4 float values +/// @param b Input vector 2. Must point to 4 float values +/// @param pfResult [in] pointer to a float. [out] Contains the +/// result, dotproduct(a,b) +//---------------------------------------------------------------------------- +void DotProductScalarResultInMemory(float *a, float *b, float *pfResult) +{ + *pfResult = a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3]; +} + +//---------------------------------------------------------------------------- +// TestFastNeonDotProduct +// +/// Run timing study of the four dot product functions above, writing the +/// results to the Android verbose log. +//---------------------------------------------------------------------------- +void TestNeonDotProduct() +{ + float SET_ALIGNMENT(64) data[] = {float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX), + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX)}; + + float *a = &data[0]; + float *b = &data[4]; + + char szMsg[256]; + + sprintf(szMsg, ""); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg,"---------------------------------------"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + +#ifdef PRINT_COMPUTED_VECTOR_RESULTS + sprintf(szMsg, "Dot product test inputs A=<%f,%f,%f>, B=<%f,%f,%f>", + a[0], a[1], a[2], b[0], b[1], b[2]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); +#endif + + float SET_ALIGNMENT(64) fResult[2]; + + sce::PhysicsEffects::PfxPerfCounter pc; + double dTimeSpan, dRefTimeSpan; + unsigned int uiNumTries = 10000000; + unsigned int i; + + // profile scalar dot product with register return + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + fResult[0] = DotProductScalarResultInRegister(a, b); // C++ + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + dRefTimeSpan = dTimeSpan; +#ifdef PRINT_COMPUTED_VECTOR_RESULTS + sprintf(szMsg, "Time to do %i calls to scalar dot product return in register: %f, result value=%f", + uiNumTries, dTimeSpan, fResult[0]); +#else + sprintf(szMsg, "Sclr C++ Dot Product Register Return: %10.7f secs, REF TIME", dTimeSpan); +#endif + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + // profile NEON dot product with register return + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + fResult[0] = DotProductNeonResultInRegister(a, b); // C++ + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); +#ifdef PRINT_COMPUTED_VECTOR_RESULTS + sprintf(szMsg, "Time to do %i calls to NEON dot product return in register: %f, result value=%f", + uiNumTries, dTimeSpan, fResult[0]); +#else + sprintf(szMsg, "Neon C++ Dot Product Register Return: %10.7f secs, speedup: %5.2f", dTimeSpan, dRefTimeSpan/dTimeSpan); +#endif + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + // profile NEON dot product with register return, assembly version + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + fResult[0] = DotProductNeonResultInRegisterAssembly(a, b); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + +#ifdef PRINT_COMPUTED_VECTOR_RESULTS + sprintf(szMsg, "Time to do %i calls to NEON dot product return in register (assembly version): %f, result value=%f", + uiNumTries, dTimeSpan, fResult[0]); +#else + sprintf(szMsg, "Neon Asm Dot Product Register Return: %10.7f secs, speedup: %5.2f", dTimeSpan, dRefTimeSpan/dTimeSpan); +#endif + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + // profile scalar dot product with direct memory return + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + DotProductScalarResultInMemory(a, b, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + + dRefTimeSpan = dTimeSpan; +#ifdef PRINT_COMPUTED_VECTOR_RESULTS + sprintf(szMsg, "Time to do %i calls to scalar dot product return in memory: %f, result value=%f", + uiNumTries, dTimeSpan, fResult[0]); +#else + sprintf(szMsg, " Sclr C++ Dot Product Memory Return: %10.7f secs, REF TIME", dTimeSpan); +#endif + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + // profile NEON dot product with direct memory return + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + DotProductNeonResultInMemory(a, b, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + +#ifdef PRINT_COMPUTED_VECTOR_RESULTS + sprintf(szMsg, "Time to do %i calls to NEON dot product return in memory: %f, result value=%f", + uiNumTries, dTimeSpan, fResult[0]); +#else + sprintf(szMsg, " Neon C++ Dot Product Memory Return: %10.7f secs, speedup: %5.2f", dTimeSpan, dRefTimeSpan/dTimeSpan); +#endif + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + // profile NEON dot product with direct memory return, assembly version + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + DotProductNeonResultInMemoryAssembly(a, b, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + +#ifdef PRINT_COMPUTED_VECTOR_RESULTS + sprintf(szMsg, "Time to do %i calls to NEON dot product return in memory (assembly version): %f, result value=%f", + uiNumTries, dTimeSpan, fResult[0]); +#else + sprintf(szMsg, " Neon Asm Dot Product Memory Return: %10.7f secs, speedup: %5.2f", dTimeSpan, dRefTimeSpan/dTimeSpan); +#endif + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + // profile NEON dot product with direct memory return, assembly version with both + // inputs in contiguous memory block (array of structures) + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + DotProductNeonResultInMemoryAssembly2(data, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + +#ifdef PRINT_COMPUTED_VECTOR_RESULTS + sprintf(szMsg, "Time to do %i calls to NEON dot product return in memory (assembly version - array of structures): %f, result value=%f", + uiNumTries, dTimeSpan, fResult[0]); +#else + sprintf(szMsg, " Neon Asm2 Dot Product Memory Return: %10.7f secs, speedup: %5.2f", dTimeSpan, dRefTimeSpan/dTimeSpan); +#endif + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + // profile NEON dot product with direct memory return, assembly version with both + // inputs in contiguous memory block (array of structures), alternate methodology + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + DotProductNeonResultInMemoryAssembly2b(data, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + +#ifdef PRINT_COMPUTED_VECTOR_RESULTS + sprintf(szMsg, "Time to do %i calls to NEON dot product return in memory (assembly version - alternate methodology): %f, result value=%f", + uiNumTries, dTimeSpan, fResult[0]); +#else + sprintf(szMsg, " Neon Asm3 Dot Product Memory Return: %10.7f secs, speedup: %5.2f", dTimeSpan, dRefTimeSpan/dTimeSpan); +#endif + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); +} diff --git a/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_matrix3_operator_multiply.cpp b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_matrix3_operator_multiply.cpp new file mode 100644 index 0000000..58d5589 --- /dev/null +++ b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_matrix3_operator_multiply.cpp @@ -0,0 +1,173 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "test_neon.h" +#define SCE_PFX_USE_PERFCOUNTER +#include "physics_effects.h" +#include +#include +#include +#include +#include + +// This works with gcc +#define SET_ALIGNMENT(alignment) __attribute__((__aligned__((alignment)))) + +// assembly implementations +extern "C" +{ + void Matrix3OperatorMultiplyNeon(float *mCol, float *mat, float *pfResult); +} + +//---------------------------------------------------------------------------- +// Matrix3OperatorMultiplyScalar +// +/// Performs a Matrix3 Vector3 multiply using scalar math, storing the +/// result directly into system memory. +/// +/// @param mCol Matrix3 Columns. Must point to 3x 4 float values +/// @param mat Matrix3 Columns. Must point to 3x 4 float values +/// @param pfResult [in] pointer to a float(matrix 3). [out] Contains the result +//---------------------------------------------------------------------------- +//inline const Vector3 Matrix3::operator *( const Vector3 & vec ) const +//{ +// return Vector3( +// ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), +// ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), +// ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) +// ); +//} +// +//inline const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const +//{ +// return Matrix3( +// ( *this * mat.mCol0 ), +// ( *this * mat.mCol1 ), +// ( *this * mat.mCol2 ) +// ); +//} +void Matrix3OperatorMultiplyScalar(float *mCol, float *mat, float *pfResult) +{ + pfResult[0] = ( ( ( mCol[0] * mat[0] ) + ( mCol[4] * mat[1] ) ) + ( mCol[8] * mat[2] ) ); + pfResult[1] = ( ( ( mCol[1] * mat[0] ) + ( mCol[5] * mat[1] ) ) + ( mCol[9] * mat[2] ) ); + pfResult[2] = ( ( ( mCol[2] * mat[0] ) + ( mCol[6] * mat[1] ) ) + ( mCol[10] * mat[2] ) ); + pfResult[3] = 0.0f; + + pfResult[4] = ( ( ( mCol[0] * mat[4] ) + ( mCol[4] * mat[5] ) ) + ( mCol[8] * mat[6] ) ); + pfResult[5] = ( ( ( mCol[1] * mat[4] ) + ( mCol[5] * mat[5] ) ) + ( mCol[9] * mat[6] ) ); + pfResult[6] = ( ( ( mCol[2] * mat[4] ) + ( mCol[6] * mat[5] ) ) + ( mCol[10] * mat[6] ) ); + pfResult[7] = 0.0f; + + pfResult[8] = ( ( ( mCol[0] * mat[8] ) + ( mCol[4] * mat[9] ) ) + ( mCol[8] * mat[10] ) ); + pfResult[9] = ( ( ( mCol[1] * mat[8] ) + ( mCol[5] * mat[9] ) ) + ( mCol[9] * mat[10] ) ); + pfResult[10] = ( ( ( mCol[2] * mat[8] ) + ( mCol[6] * mat[9] ) ) + ( mCol[10] * mat[10] ) ); + pfResult[11] = 0.0f; +} + +//---------------------------------------------------------------------------- +// TestNeonMatrix3OperatorMultiply +// +/// Run timing study of the NeonMatrix3OperatorMultiply product functions above, writing the +/// results to the Android verbose log. +//---------------------------------------------------------------------------- +void TestNeonMatrix3OperatorMultiply() +{ + float SET_ALIGNMENT(64) data1[] = {float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f, + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f, + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f}; + float SET_ALIGNMENT(64) data2[] = {float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f, + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f, + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f}; + float *mCol = &data1[0]; + float *mat = &data2[0]; + float SET_ALIGNMENT(64) fResult[12]; + + sce::PhysicsEffects::PfxPerfCounter pc; + double dTimeSpan, dRefTimeSpan;; + unsigned int uiNumTries = 10000000; + unsigned int i; + + char szMsg[256]; + + sprintf(szMsg, ""); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg,"---------------------------------------"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg,"TestNeonMatrix3OperatorMultiply Start"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "Test input mCol: <%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f>", + mCol[0], mCol[1], mCol[2], mCol[3], + mCol[4], mCol[5], mCol[6], mCol[7], + mCol[8], mCol[9], mCol[10], mCol[11]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "Test input mat: <%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f>", + mat[0], mat[1], mat[2], mat[3], + mat[4], mat[5], mat[6], mat[7], + mat[8], mat[9], mat[10], mat[11]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + + +// profile scalar NeonMatrix3OperatorMultiplyScalar with direct memory return, c++ version + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + Matrix3OperatorMultiplyScalar(mCol, mat, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + dRefTimeSpan = dTimeSpan; + sprintf(szMsg, "Time to do %i calls for Matrix3OperatorMultiplyScalar: %f secs, speedup: %5.2f, result value=<%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f>", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan, fResult[0], fResult[1], fResult[2], fResult[3], + fResult[4], fResult[5], fResult[6], fResult[7], + fResult[8], fResult[9], fResult[10], fResult[11]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + +// profile NEON Matrix3OperatorMultiplyNeon with direct memory return, assembly version + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + Matrix3OperatorMultiplyNeon(mCol, mat, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + sprintf(szMsg, "Time to do %i calls for Matrix3OperatorMultiplyNeon: %f secs, speedup: %5.2f, result value=<%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f>", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan, fResult[0], fResult[1], fResult[2], fResult[3], + fResult[4], fResult[5], fResult[6], fResult[7], + fResult[8], fResult[9], fResult[10], fResult[11]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + + sprintf(szMsg,"TestNeonMatrix3OperatorMultiply End"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); +} diff --git a/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_matrix4_operator_multiply.cpp b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_matrix4_operator_multiply.cpp new file mode 100644 index 0000000..9c88e80 --- /dev/null +++ b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_matrix4_operator_multiply.cpp @@ -0,0 +1,188 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "test_neon.h" +#define SCE_PFX_USE_PERFCOUNTER +#include "physics_effects.h" +#include +#include +#include +#include +#include + +// This works with gcc +#define SET_ALIGNMENT(alignment) __attribute__((__aligned__((alignment)))) + +// assembly implementations +extern "C" +{ + void Matrix4OperatorMultiplyNeon(float *mCol, float *mat, float *pfResult); +} + +//---------------------------------------------------------------------------- +// Matrix4OperatorMultiplyScalar +// +/// Performs a Matrix4 vector3 multiply using scalar math, storing the +/// result directly into system memory. +/// +/// @param mCol Input matrix 1. Must point to 4x 4 float values +/// @param mat Input matrix 2. Must point to 4x 4 float values +/// @param pfResult [in] pointer to a float(matrix). [out] Contains the result +//---------------------------------------------------------------------------- +//inline const Vector4 Matrix4::operator *( const Vector4 & vec ) const +//{ +// return Vector4( +// ( ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ) + ( mCol3.getX() * vec.getW() ) ), +// ( ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ) + ( mCol3.getY() * vec.getW() ) ), +// ( ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ( mCol3.getZ() * vec.getW() ) ), +// ( ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) + ( mCol3.getW() * vec.getW() ) ) +// ); +//} +//inline const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const +//{ +// return Matrix4( +// ( *this * mat.mCol0 ), +// ( *this * mat.mCol1 ), +// ( *this * mat.mCol2 ), +// ( *this * mat.mCol3 ) +// ); +//} +void Matrix4OperatorMultiplyScalar(float *mCol, float *mat, float *pfResult) +{ + pfResult[0] = ( ( ( mCol[0] * mat[0] ) + ( mCol[4] * mat[1] ) ) + ( mCol[8] * mat[2] ) + ( mCol[12] * mat[3] ) ); + pfResult[1] = ( ( ( mCol[1] * mat[0] ) + ( mCol[5] * mat[1] ) ) + ( mCol[9] * mat[2] ) + ( mCol[13] * mat[3] ) ); + pfResult[2] = ( ( ( mCol[2] * mat[0] ) + ( mCol[6] * mat[1] ) ) + ( mCol[10] * mat[2] ) + ( mCol[14] * mat[3] ) ); + pfResult[3] = ( ( ( mCol[3] * mat[0] ) + ( mCol[7] * mat[1] ) ) + ( mCol[11] * mat[2] ) + ( mCol[15] * mat[3] ) ); + + pfResult[4] = ( ( ( mCol[0] * mat[4] ) + ( mCol[4] * mat[5] ) ) + ( mCol[8] * mat[6] ) + ( mCol[12] * mat[7] ) ); + pfResult[5] = ( ( ( mCol[1] * mat[4] ) + ( mCol[5] * mat[5] ) ) + ( mCol[9] * mat[6] ) + ( mCol[13] * mat[7] ) ); + pfResult[6] = ( ( ( mCol[2] * mat[4] ) + ( mCol[6] * mat[5] ) ) + ( mCol[10] * mat[6] ) + ( mCol[14] * mat[7] ) ); + pfResult[7] = ( ( ( mCol[3] * mat[4] ) + ( mCol[7] * mat[5] ) ) + ( mCol[11] * mat[6] ) + ( mCol[15] * mat[7] ) ); + + pfResult[8] = ( ( ( mCol[0] * mat[8] ) + ( mCol[4] * mat[9] ) ) + ( mCol[8] * mat[10] ) + ( mCol[12] * mat[11] ) ); + pfResult[9] = ( ( ( mCol[1] * mat[8] ) + ( mCol[5] * mat[9] ) ) + ( mCol[9] * mat[10] ) + ( mCol[13] * mat[11] ) ); + pfResult[10] = ( ( ( mCol[2] * mat[8] ) + ( mCol[6] * mat[9] ) ) + ( mCol[10] * mat[10] ) + ( mCol[14] * mat[11] ) ); + pfResult[11] = ( ( ( mCol[3] * mat[8] ) + ( mCol[7] * mat[9] ) ) + ( mCol[11] * mat[10] ) + ( mCol[15] * mat[11] ) ); + + pfResult[12] = ( ( ( mCol[0] * mat[12] ) + ( mCol[4] * mat[13] ) ) + ( mCol[8] * mat[14] ) + ( mCol[12] * mat[15] ) ); + pfResult[13] = ( ( ( mCol[1] * mat[12] ) + ( mCol[5] * mat[13] ) ) + ( mCol[9] * mat[14] ) + ( mCol[13] * mat[15] ) ); + pfResult[14] = ( ( ( mCol[2] * mat[12] ) + ( mCol[6] * mat[13] ) ) + ( mCol[10] * mat[14] ) + ( mCol[14] * mat[15] ) ); + pfResult[15] = ( ( ( mCol[3] * mat[12] ) + ( mCol[7] * mat[13] ) ) + ( mCol[11] * mat[14] ) + ( mCol[15] * mat[15] ) ); +} + +//---------------------------------------------------------------------------- +// TestNeonMatrix4OperatorMultiply +// +/// Run timing study of the matrix4 vector3 multiply operator from above, writing the +/// results to the Android verbose log. +//---------------------------------------------------------------------------- +void TestNeonMatrix4OperatorMultiply() +{ + float SET_ALIGNMENT(64) data1[] = {float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX), + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX), + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX), + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX)}; + float SET_ALIGNMENT(64) data2[] = {float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX), + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX), + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX), + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX)}; + float *mCol = &data1[0]; + float *mat = &data2[0]; + + char szMsg[256]; + + sprintf(szMsg, ""); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg,"---------------------------------------"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg,"TestNeonMatrix4OperatorMultiply Start"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "Test input mCol: <%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f>", + mCol[0], mCol[1], mCol[2], mCol[3], + mCol[4], mCol[5], mCol[6], mCol[7], + mCol[8], mCol[9], mCol[10], mCol[11], + mCol[12], mCol[13], mCol[14], mCol[15]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "Test input mat: <%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f>", + mat[0], mat[1], mat[2], mat[3], + mat[4], mat[5], mat[6], mat[7], + mat[8], mat[9], mat[10], mat[11], + mCol[12], mCol[13], mCol[14], mCol[15]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + float SET_ALIGNMENT(64) fResult[16]; + + + sce::PhysicsEffects::PfxPerfCounter pc; + double dTimeSpan, dRefTimeSpan;; + unsigned int uiNumTries = 10000000; + unsigned int i; + +// profile scalar Matrix4OperatorMultiplyScalar with direct memory return, c++ version + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + Matrix4OperatorMultiplyScalar(mCol, mat, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + dRefTimeSpan = dTimeSpan; + sprintf(szMsg, "Time to do %i calls for Matrix4OperatorMultiplyScalar: %f secs, speedup: %5.2f", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "result value: <%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f>", + fResult[0], fResult[1], fResult[2], fResult[3], + fResult[4], fResult[5], fResult[6], fResult[7], + fResult[8], fResult[9], fResult[10], fResult[11], + fResult[12], fResult[13], fResult[14], fResult[15]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + +// profile NEON Matrix4OperatorMultiplyNeon with direct memory return, assembly version + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + Matrix4OperatorMultiplyNeon(mCol, mat, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + sprintf(szMsg, "Time to do %i calls for Matrix4OperatorMultiplyNeon: %f secs, speedup: %5.2f, result value=<%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f>", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan, fResult[0], fResult[1], fResult[2], fResult[3], + fResult[4], fResult[5], fResult[6], fResult[7], + fResult[8], fResult[9], fResult[10], fResult[11], + fResult[12], fResult[13], fResult[14], fResult[15]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + + sprintf(szMsg,"TestNeonMatrix4OperatorMultiply End"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); +} diff --git a/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_orthoInverse_transform3.cpp b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_orthoInverse_transform3.cpp new file mode 100644 index 0000000..216b350 --- /dev/null +++ b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_orthoInverse_transform3.cpp @@ -0,0 +1,173 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "test_neon.h" +#define SCE_PFX_USE_PERFCOUNTER +#include "physics_effects.h" +#include +#include +#include +#include +#include + +// This works with gcc +#define SET_ALIGNMENT(alignment) __attribute__((__aligned__((alignment)))) + +// assembly implementations +extern "C" +{ + void OrthoInverseTransform3Neon(float *trfm, float *pfResult); +} + +//---------------------------------------------------------------------------- +// OrthoInverseTransform3Scalar +// +/// Performs a ortho inverse of a transform3 using scalar math, storing the +/// result directly into system memory. +/// +/// @param trfm Input transform3. Must point to 4x 4 float values +/// @param pfResult [in] pointer to a float(tranform3). [out] Contains the result +//---------------------------------------------------------------------------- +//inline const Transform3 orthoInverse( const Transform3 & tfrm ) +//{ +// Vector3 inv0, inv1, inv2; +// inv0 = Vector3( tfrm.getCol0().getX(), tfrm.getCol1().getX(), tfrm.getCol2().getX() ); +// inv1 = Vector3( tfrm.getCol0().getY(), tfrm.getCol1().getY(), tfrm.getCol2().getY() ); +// inv2 = Vector3( tfrm.getCol0().getZ(), tfrm.getCol1().getZ(), tfrm.getCol2().getZ() ); +// return Transform3( +// inv0, +// inv1, +// inv2, +// Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) +// ); +//} +void OrthoInverseTransform3Scalar(float *trfm, float *pfResult) +{ + pfResult[0] = trfm[0]; + pfResult[1] = trfm[4]; + pfResult[2] = trfm[8]; + pfResult[3] = 0.0f; + + pfResult[4] = trfm[1]; + pfResult[5] = trfm[5]; + pfResult[6] = trfm[9]; + pfResult[7] = 0.0f; + + pfResult[8] = trfm[2]; + pfResult[9] = trfm[6]; + pfResult[10] = trfm[10]; + pfResult[11] = 0.0f; + + pfResult[12] = ( -( ( trfm[0] * trfm[8]) + ( ( trfm[1] * trfm[9]) + ( trfm[2] * trfm[10]) ) ) ); + pfResult[13] = ( -( ( trfm[4] * trfm[8]) + ( ( trfm[5] * trfm[9]) + ( trfm[6] * trfm[10]) ) ) ); + pfResult[14] = ( -( ( trfm[8] * trfm[8]) + ( ( trfm[9] * trfm[9]) + ( trfm[10] * trfm[10]) ) ) ); + pfResult[15] = 0.0f; +} + +//---------------------------------------------------------------------------- +// TestNeonOrthoInverseTransform3 +// +/// Run timing study of the orthoinverse on transform3 functions above, writing the +/// results to the Android verbose log. +//---------------------------------------------------------------------------- +void TestNeonOrthoInverseTransform3() +{ + float SET_ALIGNMENT(64) data1[] = {float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f, + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f, + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f, + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f}; + float *trfm = &data1[0]; + + char szMsg[256]; + + sprintf(szMsg, ""); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg,"---------------------------------------"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg,"TestNeonOrthoInverseTransform3 Start"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "Test input trfm: <%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f>>", + trfm[0], trfm[1], trfm[2], trfm[3], + trfm[4], trfm[5], trfm[6], trfm[7], + trfm[8], trfm[9], trfm[10], trfm[11], + trfm[12], trfm[13], trfm[14], trfm[15]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + float SET_ALIGNMENT(64) fResult[16]; + + + sce::PhysicsEffects::PfxPerfCounter pc; + double dTimeSpan, dRefTimeSpan;; + unsigned int uiNumTries = 10000000; + unsigned int i; + +// profile scalar OrthoInverseTransform3Scalar with direct memory return, c++ version + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + OrthoInverseTransform3Scalar(trfm, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + dRefTimeSpan = dTimeSpan; + sprintf(szMsg, "Time to do %i calls for OrthoInverseTransform3Scalar: %f secs, speedup: %5.2f", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "result value=<%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f>", + fResult[0], fResult[1], fResult[2], fResult[3], + fResult[4], fResult[5], fResult[6], fResult[7], + fResult[8], fResult[9], fResult[10], fResult[11], + fResult[12], fResult[13], fResult[14], fResult[15]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + +// profile NEON OrthoInverseTransform3Neon with direct memory return, assembly version + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + OrthoInverseTransform3Neon(trfm, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + sprintf(szMsg, "Time to do %i calls for OrthoInverseTransform3Neon: %f secs, speedup: %5.2f", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "result value=<%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f>", + fResult[0], fResult[1], fResult[2], fResult[3], + fResult[4], fResult[5], fResult[6], fResult[7], + fResult[8], fResult[9], fResult[10], fResult[11], + fResult[12], fResult[13], fResult[14], fResult[15]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + sprintf(szMsg,"TestNeonOrthoInverseTransform3 End"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); +} diff --git a/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_solve_linear_constraint_row.cpp b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_solve_linear_constraint_row.cpp new file mode 100644 index 0000000..a98d8f9 --- /dev/null +++ b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_solve_linear_constraint_row.cpp @@ -0,0 +1,477 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "test_neon.h" +#define SCE_PFX_USE_PERFCOUNTER +#include "physics_effects.h" +#include +#include +#include +#include +#include + +// This works with gcc +#define SET_ALIGNMENT(alignment) __attribute__((__aligned__((alignment)))) + +//---------------------------------------------------------------------------- +// pfxSolveLinearConstraintRowScalar +// +/// Performs +/// +/// @param Input +//---------------------------------------------------------------------------- +void pfxSolveLinearConstraintRowScalar(float *constraint, // 8 floats + float *deltaLinearVelocityA, // 4 floats + float *deltaAngularVelocityA, // 4 floats + float massInvA, // 1 floats + float *inertiaInvA, // 12 floats + float *rA, // 4 floats + float *deltaLinearVelocityB, // 4 floats + float *deltaAngularVelocityB, // 4 floats + float massInvB, // 1 floats + float *inertiaInvB, // 12 floats + float *rB) // 4 floats +{ +//const PfxVector3 normal(pfxReadVector3(constraint.m_normal)); //fourth element is not zero and it need to be in assembly + float SET_ALIGNMENT(64) normalRead[] = {constraint[0],constraint[1],constraint[2],0.0f}; + float *normal = &normalRead[0]; +//PfxFloat deltaImpulse = constraint.m_rhs; + float deltaImpulse = constraint[4]; +//PfxVector3 dVA = deltaLinearVelocityA + cross(deltaAngularVelocityA,rA); + float SET_ALIGNMENT(64) dVARead[] = {deltaLinearVelocityA[0] + (deltaAngularVelocityA[1]*rA[2] - deltaAngularVelocityA[2]*rA[1]), + deltaLinearVelocityA[1] + (deltaAngularVelocityA[2]*rA[0] - deltaAngularVelocityA[0]*rA[2]), + deltaLinearVelocityA[2] + (deltaAngularVelocityA[0]*rA[1] - deltaAngularVelocityA[1]*rA[0]), + 0.0f}; + float *dVA = &dVARead[0]; +//PfxVector3 dVB = deltaLinearVelocityB + cross(deltaAngularVelocityB,rB); + float SET_ALIGNMENT(64) dVBRead[] = {deltaLinearVelocityB[0] + (deltaAngularVelocityB[1]*rB[2] - deltaAngularVelocityB[2]*rB[1]), + deltaLinearVelocityB[1] + (deltaAngularVelocityB[2]*rB[0] - deltaAngularVelocityB[0]*rB[2]), + deltaLinearVelocityB[2] + (deltaAngularVelocityB[0]*rB[1] - deltaAngularVelocityB[1]*rB[0]), + 0.0f}; + float *dVB = &dVBRead[0]; +//deltaImpulse -= constraint.m_jacDiagInv * dot(normal,dVA-dVB); + deltaImpulse -= constraint[4] * (normal[0]*(dVA[0]-dVB[0]) + normal[1]*(dVA[1]-dVB[1]) + normal[2]*(dVA[2]-dVB[2])); +//PfxFloat oldImpulse = constraint.m_accumImpulse; + float oldImpulse = constraint[7]; +//constraint.m_accumImpulse = SCE_PFX_CLAMP(oldImpulse + deltaImpulse,constraint.m_lowerLimit,constraint.m_upperLimit); + if((oldImpulse + deltaImpulse) > constraint[6]){ + if(constraint[6] > constraint[5]){ + constraint[7] = constraint[6]; + }else { + constraint[7] = constraint[5]; + } + } else { + if(oldImpulse + deltaImpulse > constraint[5]){ + constraint[7] = oldImpulse + deltaImpulse; + }else { + constraint[7] = constraint[5]; + } + } +//deltaImpulse = constraint.m_accumImpulse - oldImpulse; + deltaImpulse = constraint[7] - oldImpulse; +//deltaLinearVelocityA += deltaImpulse * massInvA * normal; + deltaLinearVelocityA[0] += deltaImpulse * massInvA * normal[0]; + deltaLinearVelocityA[1] += deltaImpulse * massInvA * normal[1]; + deltaLinearVelocityA[2] += deltaImpulse * massInvA * normal[2]; + deltaLinearVelocityA[3] += deltaImpulse * massInvA * normal[3]; + +//deltaAngularVelocityA += deltaImpulse * inertiaInvA * cross(rA,normal); + deltaAngularVelocityA[0] += deltaImpulse * ((inertiaInvA[0] * (rA[1]*normal[2] - rA[2]*normal[1])) + + (inertiaInvA[4] * (rA[2]*normal[0] - rA[0]*normal[2])) +// + (inertiaInvA[8] * (rA[0]*normal[1] - rA[1]*normal[0]))); + deltaAngularVelocityA[1] += deltaImpulse * ((inertiaInvA[1] * (rA[1]*normal[2] - rA[2]*normal[1])) + + (inertiaInvA[5] * (rA[2]*normal[0] - rA[0]*normal[2])) + + (inertiaInvA[9] * (rA[0]*normal[1] - rA[1]*normal[0]))); + deltaAngularVelocityA[2] += deltaImpulse * ((inertiaInvA[2] * (rA[1]*normal[2] - rA[2]*normal[1])) + + (inertiaInvA[6] * (rA[2]*normal[0] - rA[0]*normal[2])) + + (inertiaInvA[10] * (rA[0]*normal[1] - rA[1]*normal[0]))); + deltaAngularVelocityA[3] += deltaImpulse * ((inertiaInvA[3] * (rA[1]*normal[2] - rA[2]*normal[1])) + + (inertiaInvA[7] * (rA[2]*normal[0] - rA[0]*normal[2])) + + (inertiaInvA[11] * (rA[0]*normal[1] - rA[1]*normal[0]))); +//deltaLinearVelocityB -= deltaImpulse * massInvB * normal; + deltaLinearVelocityB[0] -= deltaImpulse * massInvB * normal[0]; + deltaLinearVelocityB[1] -= deltaImpulse * massInvB * normal[1]; + deltaLinearVelocityB[2] -= deltaImpulse * massInvB * normal[2]; + deltaLinearVelocityB[3] -= deltaImpulse * massInvB * normal[3]; + +//deltaAngularVelocityB -= deltaImpulse * inertiaInvB * cross(rB,normal); + deltaAngularVelocityB[0] -= deltaImpulse * ((inertiaInvB[0] * (rB[1]*normal[2] - rB[2]*normal[1])) + + (inertiaInvB[4] * (rB[2]*normal[0] - rB[0]*normal[2])) + + (inertiaInvB[8] * (rB[0]*normal[1] - rB[1]*normal[0]))); + deltaAngularVelocityB[1] -= deltaImpulse * ((inertiaInvB[1] * (rB[1]*normal[2] - rB[2]*normal[1])) + + (inertiaInvB[5] * (rB[2]*normal[0] - rB[0]*normal[2])) + + (inertiaInvB[9] * (rB[0]*normal[1] - rB[1]*normal[0]))); + deltaAngularVelocityB[2] -= deltaImpulse * ((inertiaInvB[2] * (rB[1]*normal[2] - rB[2]*normal[1])) + + (inertiaInvB[6] * (rB[2]*normal[0] - rB[0]*normal[2])) + + (inertiaInvB[10] * (rB[0]*normal[1] - rB[1]*normal[0]))); + deltaAngularVelocityB[3] -= deltaImpulse * ((inertiaInvB[3] * (rB[1]*normal[2] - rB[2]*normal[1])) + + (inertiaInvB[7] * (rB[2]*normal[0] - rB[0]*normal[2])) + + (inertiaInvB[11] * (rB[0]*normal[1] - rB[1]*normal[0]))); +} + +/*//////////////////////////////////////Source Code/////////////////////////////////////// +void pfxSolveLinearConstraintRow( + PfxConstraintRow &constraint, // 8 floats + PfxVector3 &deltaLinearVelocityA, // 4 floats + PfxVector3 &deltaAngularVelocityA, // 4 floats + PfxFloat massInvA, // 1 float +const PfxMatrix3 &inertiaInvA, // 12 floats +const PfxVector3 &rA, // 4 floats + PfxVector3 &deltaLinearVelocityB, // 4 floats + PfxVector3 &deltaAngularVelocityB, // 4 floats + PfxFloat massInvB, // 1 float +const PfxMatrix3 &inertiaInvB, // 12 floats +const PfxVector3 &rB) // 4 floats +{ + // PfxConstraintRow structure: + // PfxFloat m_normal[3]; + // PfxFloat m_rhs; + // PfxFloat m_jacDiagInv; + // PfxFloat m_lowerLimit; + // PfxFloat m_upperLimit; + // PfxFloat m_accumImpulse; +const PfxVector3 normal(pfxReadVector3(constraint.m_normal)); +PfxFloat deltaImpulse = constraint.m_rhs; +PfxVector3 dVA = deltaLinearVelocityA + cross(deltaAngularVelocityA,rA); +PfxVector3 dVB = deltaLinearVelocityB + cross(deltaAngularVelocityB,rB); +deltaImpulse -= constraint.m_jacDiagInv * dot(normal,dVA-dVB); +PfxFloat oldImpulse = constraint.m_accumImpulse; +constraint.m_accumImpulse = SCE_PFX_CLAMP(oldImpulse + deltaImpulse,constraint.m_lowerLimit,constraint.m_upperLimit); +deltaImpulse = constraint.m_accumImpulse - oldImpulse; +deltaLinearVelocityA += deltaImpulse * massInvA * normal; +deltaAngularVelocityA += deltaImpulse * inertiaInvA * cross(rA,normal); +deltaLinearVelocityB -= deltaImpulse * massInvB * normal; +deltaAngularVelocityB -= deltaImpulse * inertiaInvB * cross(rB,normal); +} +*/ + +void pfxSolveLinearConstraintRowNeonInline(float *constraint, // 8 floats + float *deltaLinearVelocityA, // 4 floats + float *deltaAngularVelocityA, // 4 floats + float *massInvA, // 1 floats + float *inertiaInvA, // 12 floats + float *rA, // 4 floats + float *deltaLinearVelocityB, // 4 floats + float *deltaAngularVelocityB, // 4 floats + float *massInvB, // 1 floats + float *inertiaInvB, // 12 floats + float *rB) // 4 floats +{ +// "r" (constraint), //%0 +// "r" (deltaLinearVelocityA), //%1 +// "r" (deltaAngularVelocityA), //%2 +// "r" (massInvA), //%3 +// "r" (inertiaInvA), //%4 +// "r" (rA), //%5 +// "r" (deltaLinearVelocityB), //%6 +// "r" (deltaAngularVelocityB), //%7 +// "r" (massInvB), //%8 +// "r" (inertiaInvB), //%9 +// "r" (rB) //%10 + asm volatile + ( + //Loads beforehand so the normal vector will be able to have zero in the 4th element + "vld1.32 {q0}, [%1] \n\t" //LOAD => deltaLinearVelocityA ----------------> q0 + "vld1.32 {q1}, [%2] \n\t" //LOAD => deltaAngularVelocityA ---------------> q1 + "vld1.32 {q2}, [%6] \n\t" //LOAD => deltaLinearVelocityB ----------------> q2 + "vld1.32 {q3}, [%7] \n\t" //LOAD => deltaAngularVelocityB ---------------> q3 + //const PfxVector3 normal(pfxReadVector3(constraint.m_normal)); + "vld1.32 {q4}, [%0]! \n\t" //LOAD => constraint normal--------------------> q4 + "vdup.32 d10, d1[1] \n\t" //set 4th element on normal vector to zero + "vtrn.32 d9, d10 \n\t" //LOAD => deltaImpulse ------------------------> q5 (d10[0] only) + //PfxFloat deltaImpulse = constraint.m_rhs; + "vld1.32 {d12}, [%0]! \n\t" //LOAD => constraint variables ----------------> q6 + "vld1.32 {d13[0]}, [%0]! \n\t" //constraint variables + "vld1.32 {d13[1]}, [%0] \n\t" //constraint load of remaining variables loaded this way keep pointer to m_accumilate in order to store back in later + //PfxVector3 dVA = deltaLinearVelocityA + cross(deltaAngularVelocityA,rA); + //PfxVector3 dVB = deltaLinearVelocityB + cross(deltaAngularVelocityB,rB); + "vld1.32 {d14[1]}, [%5] \n\t" //LOAD => rA for cross product use 1A ---------> q7 (save these for use later) + "vld1.32 {d18[1]}, [%10] \n\t" //LOAD => rB for cross product use 1B ---------> q9 + "vld1.32 {d17[0]}, [%5]! \n\t" //LOAD => rA for cross product use 2A ---------> q8 + "vld1.32 {d21[0]}, [%10]! \n\t" //LOAD => rB for cross product use 2B ---------> q10 + "vld1.32 {d16}, [%5] \n\t" //rA 2 + "vld1.32 {d20}, [%10] \n\t" //rB 2 + "vld1.32 {d15[0]}, [%5]! \n\t" //rA 1 + "vld1.32 {d19[0]}, [%10]! \n\t" //rB 1 + "vld1.32 {d14[0]}, [%5]! \n\t" //rA 1 + "vld1.32 {d18[0]}, [%10]! \n\t" //rB 1 + "vld1.32 {d15[1]}, [%5] \n\t" //rA 1 + "vld1.32 {d19[1]}, [%10] \n\t" //rB 1 + "vld1.32 {d17[1]}, [%5]! \n\t" //rA 2 + "vld1.32 {d21[1]}, [%10]! \n\t" //rB 2 + "vdup.32 q12, d1[1] \n\t" //set deltaAngularVelocityB 2 + "vdup.32 q13, d1[1] \n\t" //set deltaAngularVelocityB 1 + "vdup.32 q14, d1[1] \n\t" //set deltaAngularVelocityA 1 + "vdup.32 q15, d1[1] \n\t" //set deltaAngularVelocityA 2 + "vadd.f32 q14, q14, q1 \n\t" + "vadd.f32 q13, q13, q3 \n\t" + "vadd.f32 q15, q15, q1 \n\t" + "vadd.f32 q12, q12, q3 \n\t" + "vrev64.32 d28, d28 \n\t" //set deltaAngularVelocityA 1 + "vrev64.32 d26, d26 \n\t" //set deltaAngularVelocityB 1 + "vtrn.32 d30, d31 \n\t" //set deltaAngularVelocityA 2 + "vtrn.32 d24, d25 \n\t" //set deltaAngularVelocityB 2 + "vtrn.32 d28, d29 \n\t" //set deltaAngularVelocityA 1 + "vtrn.32 d26, d27 \n\t" //set deltaAngularVelocityB 1 + "vrev64.32 d30, d30 \n\t" //set deltaAngularVelocityA 2 + "vrev64.32 d24, d24 \n\t" //set deltaAngularVelocityB 2 + "vmul.f32 q14, q7, q14 \n\t" //operation for cross product 1A + "vmul.f32 q13, q9, q13 \n\t" //operation for cross product 1B + "vmls.f32 q14, q8, q15 \n\t" //operation for cross product 2A + "vmls.f32 q13, q10, q12 \n\t" //operation for cross product 2B + "vadd.f32 q14, q14, q0 \n\t" //operation for adding cross to linearVelocityA + "vadd.f32 q13, q13, q2 \n\t" //operation for adding cross to linearVelocityB + //LOAD => dVA --------------------------------> q14 + //LOAD => dVB --------------------------------> q13 + //FREE q11, q12, q15, d11 + //deltaImpulse -= constraint.m_jacDiagInv * dot(normal,dVA-dVB); + "vsub.f32 q11, q14, q13 \n\t" //TEMP q11 => dVA-dVB for dot product + /*find*/ "vmul.f32 q11, q11, q4 \n\t" //operation for dot product + /*fastest*/ "vpadd.f32 d22, d22, d22 \n\t" //operation for dot product + /*dot*/ "vpadd.f32 d23, d23, d23 \n\t" //operation for dot product + "vadd.f32 d22, d22, d23 \n\t" //operation for dot product + "vmul.f32 d22, d22, d12[0] \n\t" //m_jacDiagInv times dot product result + "vsub.f32 d10, d10, d22 \n\t" //subtract result from deltaImpule + //PfxFloat oldImpulse = constraint.m_accumImpulse; + "vdup.32 d11, d13[1] \n\t" //LOAD => oldImpulse -------------------------> q5 (d11 only) + //constraint.m_accumImpulse = SCE_PFX_CLAMP(oldImpulse + deltaImpulse,constraint.m_lowerLimit,constraint.m_upperLimit); + "vdup.32 d23, d13[0] \n\t" //TEMP q11 => m_upperLimit (d23 only) + "vdup.32 d24, d12[1] \n\t" //TEMP q12 => m_lowerLimit (d34 only) + "vadd.f32 d25, d10, d11 \n\t" //TEMP q12 => deltaImpulse + oldImplues (d25 only) + "vmin.f32 d25, d25, d23 \n\t" //operation MIN(v,b) + "vmax.f32 d22, d25, d24 \n\t" //operation MAX(a,MIN(v,b) + "vst1.32 {d22[0]}, [%0] \n\t" //store m_accumImpulse (incremented so that it can be reloaded for cross product later) + //deltaImpulse = constraint.m_accumImpulse - oldImpulse; + "vsub.f32 d10, d22, d11 \n\t" //operation to calculate new deltaImpule + //FREE q6, q11, q12, q13, q14, q15, d11 + //deltaLinearVelocityB -= deltaImpulse * massInvB * normal; + //deltaLinearVelocityA += deltaImpulse * massInvA * normal; + "vld1.32 {d11[0]}, [%3] \n\t" //LOAD => massInvA ---------------------------> q5 (d11[0] only) + "vld1.32 {d11[1]}, [%8] \n\t" //LOAD => massInvB ---------------------------> q5 (d11[1] only) + "vmul.f32 q11, q4, d11[0] \n\t" //TEMP q11 => operation normal times massInvA A + "vmul.f32 q12, q4, d11[1] \n\t" //TEMP q12 => operation normal times massInvB B + "vmul.f32 q11, q11, d10[0] \n\t" //TEMP q11 => operation result times DeltaImpulse A + "vmul.f32 q12, q12, d10[0] \n\t" //TEMP q12 => operation result times DeltaImpulse B + "vadd.f32 q0, q0, q11 \n\t" //operation create new deltaLinearVelocityA A + "vsub.f32 q2, q2, q12 \n\t" //operation create new deltaLinearVelocityB B + "vst1.32 {q0}, [%1] \n\t" //store the new deltaLinearVelocityA A + "vst1.32 {q2}, [%6] \n\t" //store the new deltaLinearVelocityB B + //FREE q0, q2, q6, q11, q12, q13, q14, q15, d11 + //deltaAngularVelocityA += deltaImpulse * inertiaInvA * cross(rA,normal); + //deltaAngularVelocityB -= deltaImpulse * inertiaInvB * cross(rB,normal); + "vdup.32 q14, d1[1] \n\t" //set normal cross load + "vdup.32 q15, d1[1] \n\t" // + "vadd.f32 q14, q14, q4 \n\t" // + "vadd.f32 q15, q15, q4 \n\t" // + "vrev64.32 d28, d28 \n\t" // + "vtrn.32 d30, d31 \n\t" // + "vtrn.32 d28, d29 \n\t" // + "vrev64.32 d30, d30 \n\t" // + "vmul.f32 q0, q8, q15 \n\t" //operation for cross product A + "vmul.f32 q2, q10, q15 \n\t" //operation for cross product B + "vmls.f32 q0, q14, q7 \n\t" //operation for cross product A + "vmls.f32 q2, q14, q9 \n\t" //operation for cross product B + //LOAD => cross product result A ------------> q0 + //LOAD => cross product result B ------------> q2 + //FREE q6, q7, q8, q9, q10, q11, q12, q13, q14, q15, d11 + + "vld1.32 {q13-q14}, [%4]! \n\t" //LOAD => inertiaInvA col0, col1 A ----------> q13, q14 + "vld1.32 {q9-q10}, [%9]! \n\t" //LOAD => inertiaInvB col0, col1 B -----------> q9, q10 + "vld1.32 {q15}, [%4] \n\t" //LOAD => inertiaInvA col2 A ----------------> q5 + "vld1.32 {q11}, [%9] \n\t" //LOAD => inertiaInvB col2 B -----------------> q11 + "vmul.f32 q13, q13, d0[0] \n\t" //operation inertiaInvA col0 = (col0) * (crossA elem0) A + "vmul.f32 q9, q9, d4[0] \n\t" //operation inertiaInvB col0 = (col0) * (crossB elem0) B + "vmla.f32 q13, q14, d0[1] \n\t" //operation inertiaInvA col1 = (col1) * (crossA elem1) A + "vmla.f32 q9, q10, d4[1] \n\t" //operation inertiaInvB col1 = (col1) * (crossB elem1) B + "vmla.f32 q13, q15, d1[0] \n\t" //operation inertiaInvA col2 = (col2) * (crossA elem2) A + "vmla.f32 q9, q11, d5[0] \n\t" //operation inertiaInvB col2 = (col2) * (crossB elem2) B + "vmul.f32 q13, q13, d10[0] \n\t" //operation inertiaInvA times deltaImpulse A + "vmul.f32 q9, q9, d10[0] \n\t" //operation inertiaInvB times deltaImpulse B + "vadd.f32 q1, q1, q13 \n\t" //operation accumulate the deltaAngularVelocityA A + "vsub.f32 q3, q3, q9 \n\t" //operation accumulate the deltaAngularVelocityB B + "vst1.32 {q1}, [%2] \n\t" //store deltaAngularVelocityA A + "vst1.32 {q3}, [%7] \n\t" //store deltaAngularVelocityB B + : // NO outputs! It is important to *not* put anything here. (Putting something here forces use of r0, which wreak havok + : "r" (constraint), "r" (deltaLinearVelocityA), "r" (deltaAngularVelocityA), "r" (massInvA), "r" (inertiaInvA), "r" (rA), "r" (deltaLinearVelocityB), "r" (deltaAngularVelocityB), "r" (massInvB), "r" (inertiaInvB), "r" (rB) //inputs + : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" // clobbers + ); +} + +//---------------------------------------------------------------------------- +// TestNeonSolveLinearConstraintRow +// +/// Run timing study of the Linear Constraint Row Solver from above, writing the +/// results to the Android verbose log. +//---------------------------------------------------------------------------- +void TestNeonSolveLinearConstraintRow() +{ + //Scalar + float SET_ALIGNMENT(64) constraintDataScalar[] = {0.0f,1.0f,2.0f,3.0f,1.0f,2.0f,3.0f,4.0f}; + float SET_ALIGNMENT(64) deltaLinearVelocityADataScalar[] = {1.0f,2.0f,3.0f,0.0f}; + float SET_ALIGNMENT(64) deltaAngularVelocityADataScalar[] = {2.0f,3.0f,4.0f,0.0f}; + float SET_ALIGNMENT(64) inertiaInvADataScalar[] = {4.0f,5.0f,6.0f,0.0f,5.0f,6.0f,7.0f,0.0f,6.0f,7.0f,8.0f,0.0f}; + float SET_ALIGNMENT(64) rADataScalar[] = {5.0f,6.0f,7.0f,0.0f}; + float SET_ALIGNMENT(64) deltaLinearVelocityBDataScalar[] = {6.0f,7.0f,8.0f,0.0f}; + float SET_ALIGNMENT(64) deltaAngularVelocityBDataScalar[] = {9.0f,8.0f,7.0f,0.0f}; + float SET_ALIGNMENT(64) inertiaInvBDataScalar[] = {7.0f,6.0f,5.0f,0.0f,9.0f,8.0f,7.0f,0.0f,6.0f,7.0f,8.0f,0.0f}; + float SET_ALIGNMENT(64) rBDataScalar[] = {6.0f,5.0f,4.0f,0.0f}; + + float *constraintScalar = &constraintDataScalar[0]; + float *deltaLinearVelocityAScalar = &deltaLinearVelocityADataScalar[0]; + float *deltaAngularVelocityAScalar = &deltaAngularVelocityADataScalar[0]; + float massInvAScalar = 3.0f; + float *inertiaInvAScalar = &inertiaInvADataScalar[0]; + float *rAScalar = &rADataScalar[0]; + float *deltaLinearVelocityBScalar = &deltaLinearVelocityBDataScalar[0]; + float *deltaAngularVelocityBScalar = &deltaAngularVelocityBDataScalar[0]; + float massInvBScalar = 8.0f; + float *inertiaInvBScalar = &inertiaInvBDataScalar[0]; + float *rBScalar = &rBDataScalar[0]; + + //Neon + float SET_ALIGNMENT(64) constraintDataNeon[] = {0.0f,1.0f,2.0f,3.0f,1.0f,2.0f,3.0f,4.0f}; + float SET_ALIGNMENT(64) deltaLinearVelocityADataNeon[] = {1.0f,2.0f,3.0f,0.0f}; + float SET_ALIGNMENT(64) deltaAngularVelocityADataNeon[] = {2.0f,3.0f,4.0f,0.0f}; + float SET_ALIGNMENT(64) massInvADataNeon[] = {3.0f}; + float SET_ALIGNMENT(64) inertiaInvADataNeon[] = {4.0f,5.0f,6.0f,0.0f,5.0f,6.0f,7.0f,0.0f,6.0f,7.0f,8.0f,0.0f}; + float SET_ALIGNMENT(64) rADataNeon[] = {5.0f,6.0f,7.0f,0.0f}; + float SET_ALIGNMENT(64) deltaLinearVelocityBDataNeon[] = {6.0f,7.0f,8.0f,0.0f}; + float SET_ALIGNMENT(64) deltaAngularVelocityBDataNeon[] = {9.0f,8.0f,7.0f,0.0f}; + float SET_ALIGNMENT(64) massInvBDataNeon[] = {8.0f}; + float SET_ALIGNMENT(64) inertiaInvBDataNeon[] = {7.0f,6.0f,5.0f,0.0f,9.0f,8.0f,7.0f,0.0f,6.0f,7.0f,8.0f,0.0f}; + float SET_ALIGNMENT(64) rBDataNeon[] = {6.0f,5.0f,4.0f,0.0f}; + + float *constraintNeon = &constraintDataNeon[0]; + float *deltaLinearVelocityANeon = &deltaLinearVelocityADataNeon[0]; + float *deltaAngularVelocityANeon = &deltaAngularVelocityADataNeon[0]; + float *massInvANeon = &massInvADataNeon[0]; + float *inertiaInvANeon = &inertiaInvADataNeon[0]; + float *rANeon = &rADataNeon[0]; + float *deltaLinearVelocityBNeon = &deltaLinearVelocityBDataNeon[0]; + float *deltaAngularVelocityBNeon = &deltaAngularVelocityBDataNeon[0]; + float *massInvBNeon = &massInvBDataNeon[0]; + float *inertiaInvBNeon = &inertiaInvBDataNeon[0]; + float *rBNeon = &rBDataNeon[0]; + + char szMsg[256]; + + sprintf(szMsg, ""); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg,"---------------------------------------"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg,"TestNeonSolveLinearConstraintRow Start"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + + sce::PhysicsEffects::PfxPerfCounter pc; + double dTimeSpan, dRefTimeSpan;; + unsigned int uiNumTries = 10000000; + unsigned int i; + +// profile pfxSolveLinearConstraintRowScalar with direct memory return, c++ version + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + pfxSolveLinearConstraintRowScalar( + constraintScalar, + deltaLinearVelocityAScalar, + deltaAngularVelocityAScalar, + massInvAScalar, + inertiaInvAScalar, + rAScalar, + deltaLinearVelocityBScalar, + deltaAngularVelocityBScalar, + massInvBScalar, + inertiaInvBScalar, + rBScalar + ); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + dRefTimeSpan = dTimeSpan; + sprintf(szMsg, "Time to do %i calls for pfxSolveLinearConstraintRowScalar: %f secs, speedup: %5.2f", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "constraint.m_accumImpulse = <%f>", constraintScalar[7]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "deltaLinearVelocityA = <%f,%f,%f,%f>", + deltaLinearVelocityAScalar[0], deltaLinearVelocityAScalar[1], deltaLinearVelocityAScalar[2], deltaLinearVelocityAScalar[3]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "deltaAngularVelocityA = <%f,%f,%f,%f>", + deltaAngularVelocityAScalar[0], deltaAngularVelocityAScalar[1], deltaAngularVelocityAScalar[2], deltaAngularVelocityAScalar[3]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "deltaLinearVelocityB = <%f,%f,%f,%f>", + deltaLinearVelocityBScalar[0], deltaLinearVelocityBScalar[1], deltaLinearVelocityBScalar[2], deltaLinearVelocityBScalar[3]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "deltaAngularVelocityB = <%f,%f,%f,%f>", + deltaAngularVelocityBScalar[0], deltaAngularVelocityBScalar[1], deltaAngularVelocityBScalar[2], deltaAngularVelocityBScalar[3]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + +// profile NEON pfxSolveLinearConstraintRowNeonInline with direct memory return, inline assembly version + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + pfxSolveLinearConstraintRowNeonInline(constraintNeon, + deltaLinearVelocityANeon, + deltaAngularVelocityANeon, + massInvANeon, + inertiaInvANeon, + rANeon, + deltaLinearVelocityBNeon, + deltaAngularVelocityBNeon, + massInvBNeon, + inertiaInvBNeon, + rBNeon); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + sprintf(szMsg, "Time to do %i calls for pfxSolveLinearConstraintRowNeon: %f secs, speedup: %5.2f", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "constraint.m_accumImpulse = <%f>", constraintNeon[7]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "deltaLinearVelocityA = <%f,%f,%f,%f>", + deltaLinearVelocityANeon[0], deltaLinearVelocityANeon[1], deltaLinearVelocityANeon[2], deltaLinearVelocityANeon[3]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "deltaAngularVelocityA = <%f,%f,%f,%f>", + deltaAngularVelocityANeon[0], deltaAngularVelocityANeon[1], deltaAngularVelocityANeon[2], deltaAngularVelocityANeon[3]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "deltaLinearVelocityB = <%f,%f,%f,%f>", + deltaLinearVelocityBNeon[0], deltaLinearVelocityBNeon[1], deltaLinearVelocityBNeon[2], deltaLinearVelocityBNeon[3]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "deltaAngularVelocityB = <%f,%f,%f,%f>", + deltaAngularVelocityBNeon[0], deltaAngularVelocityBNeon[1], deltaAngularVelocityBNeon[2], deltaAngularVelocityBNeon[3]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + + sprintf(szMsg,"TestNeonSolveLinearConstraintRow End"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); +} diff --git a/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_transform3_operator_multiply.cpp b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_transform3_operator_multiply.cpp new file mode 100644 index 0000000..fc3d178 --- /dev/null +++ b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_transform3_operator_multiply.cpp @@ -0,0 +1,150 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "test_neon.h" +#define SCE_PFX_USE_PERFCOUNTER +#include "physics_effects.h" +#include +#include +#include +#include +#include + +// This works with gcc +#define SET_ALIGNMENT(alignment) __attribute__((__aligned__((alignment)))) + +// assembly implementations +extern "C" +{ + void Transform3OperatorMultiplyNeon(float *trfm, float *vec3, float *pfResult); +} + +//---------------------------------------------------------------------------- +// Transform3OperatorMultiplyScalar +// +/// Performs a multiply operation on a tranform3 using scalar math, storing the +/// result directly into system memory. +/// +/// @param trfm Input transform. Must point to 4x 4 float values +/// @param vec3 Input vector3. Must point to 4 float values +/// @param pfResult [in] pointer to a float(vector3). [out] Contains the result +//---------------------------------------------------------------------------- +//inline const Vector3 Transform3::operator *( const Vector3 & vec ) const +//{ +// return Vector3( +// ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), +// ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), +// ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) +// ); +//} +void Transform3OperatorMultiplyScalar(float *trfm, float *vec3, float *pfResult) +{ + pfResult[0] = ( ( ( trfm[0] * vec3[0] ) + ( trfm[4] * vec3[1] ) ) + ( trfm[8] * vec3[2] ) ); + pfResult[1] = ( ( ( trfm[1] * vec3[0] ) + ( trfm[5] * vec3[1] ) ) + ( trfm[9] * vec3[2] ) ); + pfResult[2] = ( ( ( trfm[2] * vec3[0] ) + ( trfm[6] * vec3[1] ) ) + ( trfm[10] * vec3[2] ) ); + pfResult[3] = 0.0f; +} + +//---------------------------------------------------------------------------- +// TestNeonTransform3OperatorMultiply +// +/// Run timing study of the Tranform3 multiply operator from above, writing the +/// results to the Android verbose log. +//---------------------------------------------------------------------------- +void TestNeonTransform3OperatorMultiply() +{ + float SET_ALIGNMENT(64) data1[] = {float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f, + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f, + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f, + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f}; + float SET_ALIGNMENT(64) data2[] = {float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f}; + + float *trfm = &data1[0]; + float *vec3 = &data2[0]; + + + char szMsg[256]; + + sprintf(szMsg, ""); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg,"---------------------------------------"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg,"TestNeonTransform3OperatorMultiply Start"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "Test input vec3: <%f,%f,%f,%f>", + vec3[0], vec3[1], vec3[2], vec3[3]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "Test input trfm: <%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f>>", + trfm[0], trfm[1], trfm[2], trfm[3], + trfm[4], trfm[5], trfm[6], trfm[7], + trfm[8], trfm[9], trfm[10], trfm[11], + trfm[12], trfm[13], trfm[14], trfm[15]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + float SET_ALIGNMENT(64) fResult[4]; + + + sce::PhysicsEffects::PfxPerfCounter pc; + double dTimeSpan, dRefTimeSpan;; + unsigned int uiNumTries = 10000000; + unsigned int i; + +// profile scalar Transform3OperatorMultiplyScalar with direct memory return, c++ version + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + Transform3OperatorMultiplyScalar(trfm, vec3, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + dRefTimeSpan = dTimeSpan; + sprintf(szMsg, "Time to do %i calls for Transform3OperatorMultiplyScalar: %f secs, speedup: %5.2f, result value=<%f,%f,%f,%f>", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan, fResult[0], fResult[1], fResult[2], fResult[3]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + +// profile NEON Transform3OperatorMultiplyNeon with direct memory return, assembly version + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + Transform3OperatorMultiplyNeon(trfm, vec3, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + sprintf(szMsg, "Time to do %i calls for Transform3OperatorMultiplyNeon: %f secs, speedup: %5.2f, result value=<%f,%f,%f,%f>", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan, fResult[0], fResult[1], fResult[2], fResult[3]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + + sprintf(szMsg,"TestNeonTransform3OperatorMultiply End"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); +} diff --git a/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_transpose_matrix3.cpp b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_transpose_matrix3.cpp new file mode 100644 index 0000000..bfadd83 --- /dev/null +++ b/Extras/PhysicsEffects/sample/test_ARM_NEON_performance/test_neon_transpose_matrix3.cpp @@ -0,0 +1,154 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "test_neon.h" +#define SCE_PFX_USE_PERFCOUNTER +#include "physics_effects.h" +#include +#include +#include +#include +#include + +// This works with gcc +#define SET_ALIGNMENT(alignment) __attribute__((__aligned__((alignment)))) + +// assembly implementations +extern "C" +{ + void TransposeMatrix3Neon(float *mCol, float *pfResult); +} + +//---------------------------------------------------------------------------- +// TransposeMatrix3Scalar +// +/// Performs a transpose on a matrix3 using scalar math, storing the +/// result directly into system memory. +/// +/// @param mCol Input matrix. Must point to 3x 4 float values +/// @param pfResult [in] pointer to a float(matrix3). [out] Contains the result +//---------------------------------------------------------------------------- +//inline const Matrix3 transpose( const Matrix3 & mat ) +//{ +// return Matrix3( +// Vector3( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX() ), +// Vector3( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY() ), +// Vector3( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ() ) +// ); +//} +void TransposeMatrix3Scalar(float *mCol, float *pfResult) +{ + pfResult[0] = mCol[0]; + pfResult[1] = mCol[4]; + pfResult[2] = mCol[8]; + pfResult[3] = 0.0f; + + pfResult[4] = mCol[1]; + pfResult[5] = mCol[5]; + pfResult[6] = mCol[9]; + pfResult[7] = 0.0f; + + pfResult[8] = mCol[2]; + pfResult[9] = mCol[6]; + pfResult[10] = mCol[10]; + pfResult[11] = 0.0f; +} + +//---------------------------------------------------------------------------- +// TestNeonTransposeMatrix3 +// +/// Run timing study of the matrix3 transpose functions above, writing the +/// results to the Android verbose log. +//---------------------------------------------------------------------------- +void TestNeonTransposeMatrix3() +{ + float SET_ALIGNMENT(64) data[] = {float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f, + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f, + float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),float(rand())/float(RAND_MAX),0.0f}; + float *mCol = &data[0]; + + char szMsg[256]; + + sprintf(szMsg, ""); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg,"---------------------------------------"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg,"TestNeonTransposeMatrix3 Start"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + sprintf(szMsg, "Test input mCol: <%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f>", + mCol[0], mCol[1], mCol[2], mCol[3], + mCol[4], mCol[5], mCol[6], mCol[7], + mCol[8], mCol[9], mCol[10], mCol[11]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + float SET_ALIGNMENT(64) fResult[12]; + + + sce::PhysicsEffects::PfxPerfCounter pc; + double dTimeSpan, dRefTimeSpan;; + unsigned int uiNumTries = 10000000; + unsigned int i; + +// profile scalar TransposeMatrix3Scalar with direct memory return, c++ version + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + TransposeMatrix3Scalar(mCol, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + dRefTimeSpan = dTimeSpan; + sprintf(szMsg, "Time to do %i calls for TransposeMatrix3Scalar: %f secs, speedup: %5.2f, result value=<%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f>", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan, fResult[0], fResult[1], fResult[2], fResult[3], + fResult[4], fResult[5], fResult[6], fResult[7], + fResult[8], fResult[9], fResult[10], fResult[11]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + +// profile NEON TransposeMatrix3Neon with direct memory return, assembly version + fResult[0] = 0.0f; + pc.countBegin(""); + for(i = 0; i < uiNumTries; i++) + { + TransposeMatrix3Neon(mCol, fResult); + } + pc.countEnd(); + dTimeSpan = pc.getCountTime(0); + pc.resetCount(); + sprintf(szMsg, "Time to do %i calls for TransposeMatrix3Neon: %f secs, speedup: %5.2f, result value=<%f,%f,%f,%f> <%f,%f,%f,%f> <%f,%f,%f,%f>", + uiNumTries, dTimeSpan, dRefTimeSpan/dTimeSpan, fResult[0], fResult[1], fResult[2], fResult[3], + fResult[4], fResult[5], fResult[6], fResult[7], + fResult[8], fResult[9], fResult[10], fResult[11]); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); + + + sprintf(szMsg,"TestNeonTransposeMatrix3 End"); + __android_log_write(ANDROID_LOG_VERBOSE,"PHYSICS TIMING STUDY", szMsg); +} diff --git a/Extras/PhysicsEffects/src/CMakeLists.txt b/Extras/PhysicsEffects/src/CMakeLists.txt new file mode 100644 index 0000000..4f73bd4 --- /dev/null +++ b/Extras/PhysicsEffects/src/CMakeLists.txt @@ -0,0 +1,11 @@ +SUBDIRS( + base_level + low_level + util +) + +SUBDIRS( + ../../../src/BulletDynamics + ../../../src/BulletCollision + ../../../src/LinearMath +) \ No newline at end of file diff --git a/Extras/PhysicsEffects/src/base_level/CMakeLists.txt b/Extras/PhysicsEffects/src/base_level/CMakeLists.txt new file mode 100644 index 0000000..433b3ad --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/CMakeLists.txt @@ -0,0 +1,77 @@ +INCLUDE_DIRECTORIES( ${PHYSICS_EFFECTS_SOURCE_DIR}/include ) + +SET(PfxBaseLevel_SRCS + broadphase/pfx_update_broadphase_proxy.cpp + collision/pfx_collidable.cpp + collision/pfx_contact_box_box.cpp + collision/pfx_contact_box_capsule.cpp + collision/pfx_contact_box_sphere.cpp + collision/pfx_contact_cache.cpp + collision/pfx_contact_capsule_capsule.cpp + collision/pfx_contact_capsule_sphere.cpp + collision/pfx_contact_large_tri_mesh.cpp + collision/pfx_contact_manifold.cpp + collision/pfx_contact_sphere_sphere.cpp + collision/pfx_contact_tri_mesh_box.cpp + collision/pfx_contact_tri_mesh_capsule.cpp + collision/pfx_contact_tri_mesh_convex.cpp + collision/pfx_contact_tri_mesh_cylinder.cpp + collision/pfx_contact_tri_mesh_sphere.cpp + collision/pfx_gjk_solver.cpp + collision/pfx_gjk_support_func.cpp + collision/pfx_intersect_ray_box.cpp + collision/pfx_intersect_ray_capsule.cpp + collision/pfx_intersect_ray_convex.cpp + collision/pfx_intersect_ray_cylinder.cpp + collision/pfx_intersect_ray_large_tri_mesh.cpp + collision/pfx_intersect_ray_sphere.cpp + collision/pfx_shape.cpp + collision/pfx_simplex_solver.cpp + solver/pfx_contact_constraint.cpp + solver/pfx_joint_ball.cpp + solver/pfx_joint_fix.cpp + solver/pfx_joint_hinge.cpp + solver/pfx_joint_slider.cpp + solver/pfx_joint_swing_twist.cpp + solver/pfx_joint_universal.cpp + sort/pfx_sort.cpp + +) + +SET(PfxBaseLevel_HDRS + broadphase/pfx_check_collidable.h + collision/pfx_contact_box_box.h + collision/pfx_contact_box_capsule.h + collision/pfx_contact_box_sphere.h + collision/pfx_contact_cache.h + collision/pfx_contact_capsule_capsule.h + collision/pfx_contact_capsule_sphere.h + collision/pfx_contact_large_tri_mesh.h + collision/pfx_contact_sphere_sphere.h + collision/pfx_contact_tri_mesh_box.h + collision/pfx_contact_tri_mesh_capsule.h + collision/pfx_contact_tri_mesh_convex.h + collision/pfx_contact_tri_mesh_cylinder.h + collision/pfx_contact_tri_mesh_sphere.h + collision/pfx_gjk_solver.h + collision/pfx_gjk_support_func.h + collision/pfx_intersect_common.h + collision/pfx_intersect_ray_box.h + collision/pfx_intersect_ray_capsule.h + collision/pfx_intersect_ray_convex.h + collision/pfx_intersect_ray_cylinder.h + collision/pfx_intersect_ray_large_tri_mesh.h + collision/pfx_intersect_ray_sphere.h + collision/pfx_mesh_common.h + collision/pfx_simplex_solver.h + solver/pfx_check_solver.h + solver/pfx_constraint_row_solver.h +) + + + + +ADD_LIBRARY(PfxBaseLevel ${PfxBaseLevel_SRCS} ${PfxBaseLevel_HDRS}) + +SET_TARGET_PROPERTIES(PfxBaseLevel PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(PfxBaseLevel PROPERTIES SOVERSION ${BULLET_VERSION}) diff --git a/Extras/PhysicsEffects/src/base_level/broadphase/pfx_check_collidable.h b/Extras/PhysicsEffects/src/base_level/broadphase/pfx_check_collidable.h new file mode 100644 index 0000000..9a69bb2 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/broadphase/pfx_check_collidable.h @@ -0,0 +1,80 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CHECK_COLLIDABLE_H +#define _SCE_PFX_CHECK_COLLIDABLE_H + +#include "../../../include/physics_effects/base_level/rigidbody/pfx_rigid_state.h" +#include "../../../include/physics_effects/base_level/collision/pfx_aabb.h" +#include "../../../include/physics_effects/base_level/broadphase/pfx_broadphase_proxy.h" +#include "../../../include/physics_effects/base_level/broadphase/pfx_broadphase_pair.h" + +namespace sce { +namespace PhysicsEffects { + +// Collidable check table +/* + -----------------MotionTypeA + |0 1 0 1 1 + |1 1 1 1 1 + |0 1 0 1 1 + |1 1 1 0 1 + |1 1 1 1 0 +MotionTypeB + */ + +static SCE_PFX_FORCE_INLINE +PfxBool pfxCheckCollidableTable(ePfxMotionType i,ePfxMotionType j) +{ + const PfxUInt32 collidableTable = 0x00bfafbe; + + SCE_PFX_ASSERT(i < kPfxMotionTypeCount); + SCE_PFX_ASSERT(j < kPfxMotionTypeCount); + + PfxUInt32 idx = j * kPfxMotionTypeCount + i; + PfxUInt32 mask = 1 << (kPfxMotionTypeCount*kPfxMotionTypeCount-1-idx); + + return (collidableTable & mask) != 0; +} + +static SCE_PFX_FORCE_INLINE +PfxBool pfxCheckCollidableInBroadphase(const PfxBroadphaseProxy &proxyA, const PfxBroadphaseProxy &proxyB) +{ + ePfxMotionType motionA = (ePfxMotionType)(pfxGetMotionMask(proxyA)&SCE_PFX_MOTION_MASK_TYPE); + ePfxMotionType motionB = (ePfxMotionType)(pfxGetMotionMask(proxyB)&SCE_PFX_MOTION_MASK_TYPE); + + return + pfxCheckCollidableTable(motionA,motionB) && // モーションタイプ別衝突判定テーブル + ((pfxGetSelf(proxyA)&pfxGetTarget(proxyB)) && (pfxGetTarget(proxyA)&pfxGetSelf(proxyB))) && // 衝突フィルター + pfxTestAabb(proxyA,proxyB); // AABB交差判定 +} + +static SCE_PFX_FORCE_INLINE +PfxBool pfxCheckCollidableInCollision(const PfxBroadphasePair &pair) +{ + PfxUInt32 motionA = pfxGetMotionMaskA(pair)&SCE_PFX_MOTION_MASK_TYPE; + PfxUInt32 motionB = pfxGetMotionMaskB(pair)&SCE_PFX_MOTION_MASK_TYPE; + PfxUInt32 sleepA = pfxGetMotionMaskA(pair)&SCE_PFX_MOTION_MASK_SLEEPING; + PfxUInt32 sleepB = pfxGetMotionMaskB(pair)&SCE_PFX_MOTION_MASK_SLEEPING; + + return + pfxCheckCollidableTable((ePfxMotionType)motionA,(ePfxMotionType)motionB) && // モーションタイプ別衝突判定テーブル + !((sleepA != 0 && sleepB != 0) || (sleepA != 0 && motionB == kPfxMotionTypeFixed) || (sleepB != 0 && motionA == kPfxMotionTypeFixed)); // スリープ時のチェック +} +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_CHECK_COLLIDABLE_H diff --git a/Extras/PhysicsEffects/src/base_level/broadphase/pfx_update_broadphase_proxy.cpp b/Extras/PhysicsEffects/src/base_level/broadphase/pfx_update_broadphase_proxy.cpp new file mode 100644 index 0000000..9de1d91 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/broadphase/pfx_update_broadphase_proxy.cpp @@ -0,0 +1,234 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_perf_counter.h" +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "../../../include/physics_effects/base_level/collision/pfx_aabb.h" +#include "../../../include/physics_effects/base_level/broadphase/pfx_update_broadphase_proxy.h" + +namespace sce { +namespace PhysicsEffects { + +static SCE_PFX_FORCE_INLINE +PfxBool operator < (const PfxVector3 &v1,const PfxVector3 &v2) +{ + return maxElem(v2-v1) > 0.0f; +} + +PfxInt32 pfxUpdateBroadphaseProxy( + PfxBroadphaseProxy &proxy, + const PfxRigidState &state, + const PfxCollidable &coll, + const PfxVector3 &worldCenter, + const PfxVector3 &worldExtent, + PfxUInt32 axis) +{ + SCE_PFX_ALWAYS_ASSERT(axis<3); + + PfxInt32 ret = SCE_PFX_OK; + + PfxVector3 center = state.getPosition() + coll.getCenter(); + PfxVector3 half = absPerElem(PfxMatrix3(state.getOrientation())) * coll.getHalf(); + + PfxVector3 minRig = center - half; + PfxVector3 maxRig = center + half; + + PfxVector3 minWld = worldCenter - worldExtent; + PfxVector3 maxWld = worldCenter + worldExtent; + + if(maxWld < minRig || maxRig < minWld) { + ret = SCE_PFX_ERR_OUT_OF_WORLD; + } + + PfxVecInt3 aabbMin,aabbMax; + pfxConvertCoordWorldToLocal(worldCenter,worldExtent,minRig,maxRig,aabbMin,aabbMax); + + pfxSetXMin(proxy,aabbMin.getX()); + pfxSetXMax(proxy,aabbMax.getX()); + pfxSetYMin(proxy,aabbMin.getY()); + pfxSetYMax(proxy,aabbMax.getY()); + pfxSetZMin(proxy,aabbMin.getZ()); + pfxSetZMax(proxy,aabbMax.getZ()); + pfxSetKey(proxy,aabbMin.get(axis)); + pfxSetObjectId(proxy,state.getRigidBodyId()); + pfxSetMotionMask(proxy,state.getMotionMask()); + pfxSetSelf(proxy,state.getContactFilterSelf()); + pfxSetTarget(proxy,state.getContactFilterTarget()); + + return ret; +} + +PfxInt32 pfxUpdateBroadphaseProxy( + PfxBroadphaseProxy &proxy, + const PfxRigidState &state, + const PfxVector3 &objectCenter, + const PfxVector3 &objectHalf, + const PfxVector3 &worldCenter, + const PfxVector3 &worldExtent, + PfxUInt32 axis) +{ + SCE_PFX_ALWAYS_ASSERT(axis<3); + + PfxInt32 ret = SCE_PFX_OK; + + PfxVector3 minRig = objectCenter - objectHalf; + PfxVector3 maxRig = objectCenter + objectHalf; + + PfxVector3 minWld = worldCenter - worldExtent; + PfxVector3 maxWld = worldCenter + worldExtent; + + if(maxWld < minRig || maxRig < minWld) { + ret = SCE_PFX_ERR_OUT_OF_WORLD; + } + + PfxVecInt3 aabbMin,aabbMax; + pfxConvertCoordWorldToLocal(worldCenter,worldExtent,minRig,maxRig,aabbMin,aabbMax); + + pfxSetXMin(proxy,aabbMin.getX()); + pfxSetXMax(proxy,aabbMax.getX()); + pfxSetYMin(proxy,aabbMin.getY()); + pfxSetYMax(proxy,aabbMax.getY()); + pfxSetZMin(proxy,aabbMin.getZ()); + pfxSetZMax(proxy,aabbMax.getZ()); + pfxSetKey(proxy,aabbMin.get(axis)); + pfxSetObjectId(proxy,state.getRigidBodyId()); + pfxSetMotionMask(proxy,state.getMotionMask()); + pfxSetSelf(proxy,state.getContactFilterSelf()); + pfxSetTarget(proxy,state.getContactFilterTarget()); + + return ret; +} + +PfxInt32 pfxUpdateBroadphaseProxy( + PfxBroadphaseProxy &proxyX, + PfxBroadphaseProxy &proxyY, + PfxBroadphaseProxy &proxyZ, + PfxBroadphaseProxy &proxyXb, + PfxBroadphaseProxy &proxyYb, + PfxBroadphaseProxy &proxyZb, + const PfxRigidState &state, + const PfxCollidable &coll, + const PfxVector3 &worldCenter, + const PfxVector3 &worldExtent) +{ + PfxInt32 ret = SCE_PFX_OK; + + PfxVector3 center = state.getPosition() + coll.getCenter(); + PfxVector3 half = absPerElem(PfxMatrix3(state.getOrientation())) * coll.getHalf(); + + PfxVector3 minRig = center - half; + PfxVector3 maxRig = center + half; + + PfxVector3 minWld = worldCenter - worldExtent; + PfxVector3 maxWld = worldCenter + worldExtent; + + if(maxWld < minRig || maxRig < minWld) { + ret = SCE_PFX_ERR_OUT_OF_WORLD; + } + + PfxVecInt3 aabbMin,aabbMax; + pfxConvertCoordWorldToLocal(worldCenter,worldExtent,minRig,maxRig,aabbMin,aabbMax); + + PfxBroadphaseProxy proxy; + + pfxSetXMin(proxy,aabbMin.getX()); + pfxSetXMax(proxy,aabbMax.getX()); + pfxSetYMin(proxy,aabbMin.getY()); + pfxSetYMax(proxy,aabbMax.getY()); + pfxSetZMin(proxy,aabbMin.getZ()); + pfxSetZMax(proxy,aabbMax.getZ()); + pfxSetObjectId(proxy,state.getRigidBodyId()); + pfxSetMotionMask(proxy,state.getMotionMask()); + pfxSetSelf(proxy,state.getContactFilterSelf()); + pfxSetTarget(proxy,state.getContactFilterTarget()); + + proxyX = proxy; + proxyXb = proxy; + proxyY = proxy; + proxyYb = proxy; + proxyZ = proxy; + proxyZb = proxy; + + pfxSetKey(proxyX ,aabbMin.getX()); + pfxSetKey(proxyXb,aabbMax.getX()); + pfxSetKey(proxyY ,aabbMin.getY()); + pfxSetKey(proxyYb,aabbMax.getY()); + pfxSetKey(proxyZ ,aabbMin.getZ()); + pfxSetKey(proxyZb,aabbMax.getZ()); + + return ret; +} + +PfxInt32 pfxUpdateBroadphaseProxy( + PfxBroadphaseProxy &proxyX, + PfxBroadphaseProxy &proxyY, + PfxBroadphaseProxy &proxyZ, + PfxBroadphaseProxy &proxyXb, + PfxBroadphaseProxy &proxyYb, + PfxBroadphaseProxy &proxyZb, + const PfxRigidState &state, + const PfxVector3 &objectCenter, + const PfxVector3 &objectHalf, + const PfxVector3 &worldCenter, + const PfxVector3 &worldExtent) +{ + PfxInt32 ret = SCE_PFX_OK; + + PfxVector3 minRig = objectCenter - objectHalf; + PfxVector3 maxRig = objectCenter + objectHalf; + + PfxVector3 minWld = worldCenter - worldExtent; + PfxVector3 maxWld = worldCenter + worldExtent; + + if(maxWld < minRig || maxRig < minWld) { + ret = SCE_PFX_ERR_OUT_OF_WORLD; + } + + PfxVecInt3 aabbMin,aabbMax; + pfxConvertCoordWorldToLocal(worldCenter,worldExtent,minRig,maxRig,aabbMin,aabbMax); + + PfxBroadphaseProxy proxy; + + pfxSetXMin(proxy,aabbMin.getX()); + pfxSetXMax(proxy,aabbMax.getX()); + pfxSetYMin(proxy,aabbMin.getY()); + pfxSetYMax(proxy,aabbMax.getY()); + pfxSetZMin(proxy,aabbMin.getZ()); + pfxSetZMax(proxy,aabbMax.getZ()); + pfxSetObjectId(proxy,state.getRigidBodyId()); + pfxSetMotionMask(proxy,state.getMotionMask()); + pfxSetSelf(proxy,state.getContactFilterSelf()); + pfxSetTarget(proxy,state.getContactFilterTarget()); + + proxyX = proxy; + proxyXb = proxy; + proxyY = proxy; + proxyYb = proxy; + proxyZ = proxy; + proxyZb = proxy; + + pfxSetKey(proxyX ,aabbMin.getX()); + pfxSetKey(proxyXb,aabbMax.getX()); + pfxSetKey(proxyY ,aabbMin.getY()); + pfxSetKey(proxyYb,aabbMax.getY()); + pfxSetKey(proxyZ ,aabbMin.getZ()); + pfxSetKey(proxyZb,aabbMax.getZ()); + + return ret; +} + +} // namespace PhysicsEffects +} // namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_collidable.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_collidable.cpp new file mode 100644 index 0000000..9a8f596 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_collidable.cpp @@ -0,0 +1,56 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/collision/pfx_collidable.h" + +namespace sce { +namespace PhysicsEffects { + +void PfxCollidable::addShape(const PfxShape &shape) +{ + if(m_numShapes distanceThreshold ) return gap; \ + axisType = A_AXIS; \ + faceDimA = dim; \ + axisA = ident[dim]; \ + } \ + else \ + { \ + gap = gapsA.get##letter(); \ + if ( gap > distanceThreshold ) return gap; \ + else if ( gap > maxGap ) \ + { \ + maxGap = gap; \ + axisType = A_AXIS; \ + faceDimA = dim; \ + axisA = ident[dim]; \ + } \ + } \ +} + + +#define BaxisTest( dim, letter ) \ +{ \ + gap = gapsB.get##letter(); \ + if ( gap > distanceThreshold ) return gap; \ + else if ( gap > maxGap ) \ + { \ + maxGap = gap; \ + axisType = B_AXIS; \ + faceDimB = dim; \ + axisB = ident[dim]; \ + } \ +} + +#define CrossAxisTest( dima, dimb, letterb ) \ +{ \ + const PfxFloat lsqr_tolerance = 1.0e-30f; \ + PfxFloat lsqr; \ + \ + lsqr = lsqrs.getCol##dima().get##letterb(); \ + \ + if ( lsqr > lsqr_tolerance ) \ + { \ + PfxFloat l_recip = 1.0f / sqrtf( lsqr ); \ + gap = PfxFloat(gapsAxB.getCol##dima().get##letterb()) * l_recip; \ + \ + if ( gap > distanceThreshold ) \ + { \ + return gap; \ + } \ + \ + if ( gap > maxGap ) \ + { \ + maxGap = gap; \ + axisType = CROSS_AXIS; \ + edgeDimA = dima; \ + edgeDimB = dimb; \ + axisA = cross(ident[dima],matrixAB.getCol##dimb()) * l_recip; \ + } \ + } \ +} + +//------------------------------------------------------------------------------------------------- +// tests whether a vertex of box B and a face of box A are the closest features +//------------------------------------------------------------------------------------------------- + +inline +PfxFloat +VertexBFaceATest( + PfxBool & inVoronoi, + PfxFloat & t0, + PfxFloat & t1, + const PfxVector3 & hA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetAB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetBA, + const PfxMatrix3 & matrixAB, + const PfxMatrix3 & matrixBA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesB ) +{ + // compute a corner of box B in A's coordinate system + + PfxVector3 corner = + PfxVector3( faceOffsetAB + matrixAB.getCol0() * scalesB.getX() + matrixAB.getCol1() * scalesB.getY() ); + + // compute the parameters of the point on A, closest to this corner + + t0 = corner[0]; + t1 = corner[1]; + + if ( t0 > hA[0] ) + t0 = hA[0]; + else if ( t0 < -hA[0] ) + t0 = -hA[0]; + if ( t1 > hA[1] ) + t1 = hA[1]; + else if ( t1 < -hA[1] ) + t1 = -hA[1]; + + // do the Voronoi test: already know the point on B is in the Voronoi region of the + // point on A, check the reverse. + + PfxVector3 facePointB = + PfxVector3( mulPerElem( faceOffsetBA + matrixBA.getCol0() * t0 + matrixBA.getCol1() * t1 - scalesB, signsB ) ); + + inVoronoi = ( ( facePointB[0] >= voronoiTol * facePointB[2] ) && + ( facePointB[1] >= voronoiTol * facePointB[0] ) && + ( facePointB[2] >= voronoiTol * facePointB[1] ) ); + + return (SCE_PFX_SQR( corner[0] - t0 ) + SCE_PFX_SQR( corner[1] - t1 ) + SCE_PFX_SQR( corner[2] )); +} + +#define VertexBFaceA_SetNewMin() \ +{ \ + minDistSqr = distSqr; \ + localPointA.setX(t0); \ + localPointA.setY(t1); \ + localPointB.setX( scalesB.getX() ); \ + localPointB.setY( scalesB.getY() ); \ +} + +void +VertexBFaceATests( + PfxBool & done, + PfxFloat & minDistSqr, + PfxPoint3 & localPointA, + PfxPoint3 & localPointB, + const PfxVector3 & hA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetAB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetBA, + const PfxMatrix3 & matrixAB, + const PfxMatrix3 & matrixBA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesB, + PfxBool first ) +{ + PfxFloat t0, t1; + PfxFloat distSqr; + + distSqr = VertexBFaceATest( done, t0, t1, hA, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsB, scalesB ); + + if ( first ) { + VertexBFaceA_SetNewMin(); + } else { + if ( distSqr < minDistSqr ) { + VertexBFaceA_SetNewMin(); + } + } + + if ( done ) + return; + + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = VertexBFaceATest( done, t0, t1, hA, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsB, scalesB ); + + if ( distSqr < minDistSqr ) { + VertexBFaceA_SetNewMin(); + } + + if ( done ) + return; + + signsB.setY( -signsB.getY() ); + scalesB.setY( -scalesB.getY() ); + + distSqr = VertexBFaceATest( done, t0, t1, hA, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsB, scalesB ); + + if ( distSqr < minDistSqr ) { + VertexBFaceA_SetNewMin(); + } + + if ( done ) + return; + + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = VertexBFaceATest( done, t0, t1, hA, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsB, scalesB ); + + if ( distSqr < minDistSqr ) { + VertexBFaceA_SetNewMin(); + } +} + +//------------------------------------------------------------------------------------------------- +// VertexAFaceBTest: tests whether a vertex of box A and a face of box B are the closest features +//------------------------------------------------------------------------------------------------- + +inline +PfxFloat +VertexAFaceBTest( + PfxBool & inVoronoi, + PfxFloat & t0, + PfxFloat & t1, + const PfxVector3 & hB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetAB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetBA, + const PfxMatrix3 & matrixAB, + const PfxMatrix3 & matrixBA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesA ) +{ + PfxVector3 corner = + PfxVector3( faceOffsetBA + matrixBA.getCol0() * scalesA.getX() + matrixBA.getCol1() * scalesA.getY() ); + + t0 = corner[0]; + t1 = corner[1]; + + if ( t0 > hB[0] ) + t0 = hB[0]; + else if ( t0 < -hB[0] ) + t0 = -hB[0]; + if ( t1 > hB[1] ) + t1 = hB[1]; + else if ( t1 < -hB[1] ) + t1 = -hB[1]; + + PfxVector3 facePointA = + PfxVector3( mulPerElem( faceOffsetAB + matrixAB.getCol0() * t0 + matrixAB.getCol1() * t1 - scalesA, signsA ) ); + + inVoronoi = ( ( facePointA[0] >= voronoiTol * facePointA[2] ) && + ( facePointA[1] >= voronoiTol * facePointA[0] ) && + ( facePointA[2] >= voronoiTol * facePointA[1] ) ); + + return (SCE_PFX_SQR( corner[0] - t0 ) + SCE_PFX_SQR( corner[1] - t1 ) + SCE_PFX_SQR( corner[2] )); +} + +#define VertexAFaceB_SetNewMin() \ +{ \ + minDistSqr = distSqr; \ + localPointB.setX(t0); \ + localPointB.setY(t1); \ + localPointA.setX( scalesA.getX() ); \ + localPointA.setY( scalesA.getY() ); \ +} + +void +VertexAFaceBTests( + PfxBool & done, + PfxFloat & minDistSqr, + PfxPoint3 & localPointA, + PfxPoint3 & localPointB, + const PfxVector3 & hB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetAB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetBA, + const PfxMatrix3 & matrixAB, + const PfxMatrix3 & matrixBA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesA, + PfxBool first ) +{ + PfxFloat t0, t1; + PfxFloat distSqr; + + distSqr = VertexAFaceBTest( done, t0, t1, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, scalesA ); + + if ( first ) { + VertexAFaceB_SetNewMin(); + } else { + if ( distSqr < minDistSqr ) { + VertexAFaceB_SetNewMin(); + } + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = VertexAFaceBTest( done, t0, t1, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, scalesA ); + + if ( distSqr < minDistSqr ) { + VertexAFaceB_SetNewMin(); + } + + if ( done ) + return; + + signsA.setY( -signsA.getY() ); + scalesA.setY( -scalesA.getY() ); + + distSqr = VertexAFaceBTest( done, t0, t1, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, scalesA ); + + if ( distSqr < minDistSqr ) { + VertexAFaceB_SetNewMin(); + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = VertexAFaceBTest( done, t0, t1, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, scalesA ); + + if ( distSqr < minDistSqr ) { + VertexAFaceB_SetNewMin(); + } +} + +//------------------------------------------------------------------------------------------------- +// EdgeEdgeTest: +// +// tests whether a pair of edges are the closest features +// +// note on the shorthand: +// 'a' & 'b' refer to the edges. +// 'c' is the dimension of the axis that points from the face center to the edge Center +// 'd' is the dimension of the edge Direction +// the dimension of the face normal is 2 +//------------------------------------------------------------------------------------------------- + +#define EdgeEdgeTest( ac, ac_letter, ad, ad_letter, bc, bc_letter, bd, bd_letter ) \ +{ \ + PfxVector3 edgeOffsetAB; \ + PfxVector3 edgeOffsetBA; \ + \ + edgeOffsetAB = faceOffsetAB + matrixAB.getCol##bc() * scalesB.get##bc_letter(); \ + edgeOffsetAB.set##ac_letter( edgeOffsetAB.get##ac_letter() - scalesA.get##ac_letter() ); \ + \ + edgeOffsetBA = faceOffsetBA + matrixBA.getCol##ac() * scalesA.get##ac_letter(); \ + edgeOffsetBA.set##bc_letter( edgeOffsetBA.get##bc_letter() - scalesB.get##bc_letter() ); \ + \ + PfxFloat dirDot = matrixAB.getCol##bd().get##ad_letter(); \ + PfxFloat denom = 1.0f - dirDot*dirDot; \ + PfxFloat edgeOffsetAB_ad = edgeOffsetAB.get##ad_letter(); \ + PfxFloat edgeOffsetBA_bd = edgeOffsetBA.get##bd_letter(); \ + \ + if ( denom == 0.0f ) \ + { \ + tA = 0.0f; \ + } \ + else \ + { \ + tA = ( edgeOffsetAB_ad + edgeOffsetBA_bd * dirDot ) / denom; \ + } \ + \ + if ( tA < -hA[ad] ) tA = -hA[ad]; \ + else if ( tA > hA[ad] ) tA = hA[ad]; \ + \ + tB = tA * dirDot + edgeOffsetBA_bd; \ + \ + if ( tB < -hB[bd] ) \ + { \ + tB = -hB[bd]; \ + tA = tB * dirDot + edgeOffsetAB_ad; \ + \ + if ( tA < -hA[ad] ) tA = -hA[ad]; \ + else if ( tA > hA[ad] ) tA = hA[ad]; \ + } \ + else if ( tB > hB[bd] ) \ + { \ + tB = hB[bd]; \ + tA = tB * dirDot + edgeOffsetAB_ad; \ + \ + if ( tA < -hA[ad] ) tA = -hA[ad]; \ + else if ( tA > hA[ad] ) tA = hA[ad]; \ + } \ + \ + PfxVector3 edgeOffAB = PfxVector3( mulPerElem( edgeOffsetAB + matrixAB.getCol##bd() * tB, signsA ) );\ + PfxVector3 edgeOffBA = PfxVector3( mulPerElem( edgeOffsetBA + matrixBA.getCol##ad() * tA, signsB ) );\ + \ + inVoronoi = ( edgeOffAB[ac] >= voronoiTol * edgeOffAB[2] ) && \ + ( edgeOffAB[2] >= voronoiTol * edgeOffAB[ac] ) && \ + ( edgeOffBA[bc] >= voronoiTol * edgeOffBA[2] ) && \ + ( edgeOffBA[2] >= voronoiTol * edgeOffBA[bc] ); \ + \ + edgeOffAB[ad] -= tA; \ + edgeOffBA[bd] -= tB; \ + \ + return dot(edgeOffAB,edgeOffAB); \ +} + +PfxFloat +EdgeEdgeTest_0101( + PfxBool & inVoronoi, + PfxFloat & tA, + PfxFloat & tB, + const PfxVector3 & hA, + const PfxVector3 & hB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetAB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetBA, + const PfxMatrix3 & matrixAB, + const PfxMatrix3 & matrixBA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesB ) +{ + EdgeEdgeTest( 0, X, 1, Y, 0, X, 1, Y ); +} + +PfxFloat +EdgeEdgeTest_0110( + PfxBool & inVoronoi, + PfxFloat & tA, + PfxFloat & tB, + const PfxVector3 & hA, + const PfxVector3 & hB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetAB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetBA, + const PfxMatrix3 & matrixAB, + const PfxMatrix3 & matrixBA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesB ) +{ + EdgeEdgeTest( 0, X, 1, Y, 1, Y, 0, X ); +} + +PfxFloat +EdgeEdgeTest_1001( + PfxBool & inVoronoi, + PfxFloat & tA, + PfxFloat & tB, + const PfxVector3 & hA, + const PfxVector3 & hB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetAB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetBA, + const PfxMatrix3 & matrixAB, + const PfxMatrix3 & matrixBA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesB ) +{ + EdgeEdgeTest( 1, Y, 0, X, 0, X, 1, Y ); +} + +PfxFloat +EdgeEdgeTest_1010( + PfxBool & inVoronoi, + PfxFloat & tA, + PfxFloat & tB, + const PfxVector3 & hA, + const PfxVector3 & hB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetAB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetBA, + const PfxMatrix3 & matrixAB, + const PfxMatrix3 & matrixBA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesB ) +{ + EdgeEdgeTest( 1, Y, 0, X, 1, Y, 0, X ); +} + +#define EdgeEdge_SetNewMin( ac_letter, ad_letter, bc_letter, bd_letter ) \ +{ \ + minDistSqr = distSqr; \ + localPointA.set##ac_letter(scalesA.get##ac_letter()); \ + localPointA.set##ad_letter(tA); \ + localPointB.set##bc_letter(scalesB.get##bc_letter()); \ + localPointB.set##bd_letter(tB); \ + otherFaceDimA = testOtherFaceDimA; \ + otherFaceDimB = testOtherFaceDimB; \ +} + +void +EdgeEdgeTests( + PfxBool & done, + PfxFloat & minDistSqr, + PfxPoint3 & localPointA, + PfxPoint3 & localPointB, + int & otherFaceDimA, + int & otherFaceDimB, + const PfxVector3 & hA, + const PfxVector3 & hB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetAB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG faceOffsetBA, + const PfxMatrix3 & matrixAB, + const PfxMatrix3 & matrixBA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesB, + PfxBool first ) +{ + PfxFloat distSqr; + PfxFloat tA, tB; + + int testOtherFaceDimA, testOtherFaceDimB; + + testOtherFaceDimA = 0; + testOtherFaceDimB = 0; + + distSqr = EdgeEdgeTest_0101( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( first ) { + EdgeEdge_SetNewMin( X, Y, X, Y ); + } else { + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, X, Y ); + } + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = EdgeEdgeTest_0101( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, X, Y ); + } + + if ( done ) + return; + + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = EdgeEdgeTest_0101( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, X, Y ); + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = EdgeEdgeTest_0101( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, X, Y ); + } + + if ( done ) + return; + + testOtherFaceDimA = 1; + testOtherFaceDimB = 0; + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = EdgeEdgeTest_1001( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, X, Y ); + } + + if ( done ) + return; + + signsA.setY( -signsA.getY() ); + scalesA.setY( -scalesA.getY() ); + + distSqr = EdgeEdgeTest_1001( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, X, Y ); + } + + if ( done ) + return; + + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = EdgeEdgeTest_1001( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, X, Y ); + } + + if ( done ) + return; + + signsA.setY( -signsA.getY() ); + scalesA.setY( -scalesA.getY() ); + + distSqr = EdgeEdgeTest_1001( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, X, Y ); + } + + if ( done ) + return; + + testOtherFaceDimA = 0; + testOtherFaceDimB = 1; + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = EdgeEdgeTest_0110( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, Y, X ); + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = EdgeEdgeTest_0110( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, Y, X ); + } + + if ( done ) + return; + + signsB.setY( -signsB.getY() ); + scalesB.setY( -scalesB.getY() ); + + distSqr = EdgeEdgeTest_0110( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, Y, X ); + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = EdgeEdgeTest_0110( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, Y, X ); + } + + if ( done ) + return; + + testOtherFaceDimA = 1; + testOtherFaceDimB = 1; + signsB.setY( -signsB.getY() ); + scalesB.setY( -scalesB.getY() ); + + distSqr = EdgeEdgeTest_1010( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, Y, X ); + } + + if ( done ) + return; + + signsA.setY( -signsA.getY() ); + scalesA.setY( -scalesA.getY() ); + + distSqr = EdgeEdgeTest_1010( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, Y, X ); + } + + if ( done ) + return; + + signsB.setY( -signsB.getY() ); + scalesB.setY( -scalesB.getY() ); + + distSqr = EdgeEdgeTest_1010( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, Y, X ); + } + + if ( done ) + return; + + signsA.setY( -signsA.getY() ); + scalesA.setY( -scalesA.getY() ); + + distSqr = EdgeEdgeTest_1010( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, Y, X ); + } +} + +PfxFloat pfxContactBoxBox( + PfxVector3 &normal,PfxPoint3 &pointA,PfxPoint3 &pointB, + void *shapeA,const PfxTransform3 &transformA, + void *shapeB,const PfxTransform3 &transformB, + PfxFloat distanceThreshold) +{ + PfxBox &boxA = *((PfxBox*)shapeA); + PfxBox &boxB = *((PfxBox*)shapeB); + + PfxVector3 ident[3] = { + PfxVector3(1.0,0.0,0.0), + PfxVector3(0.0,1.0,0.0), + PfxVector3(0.0,0.0,1.0), + }; + + // get relative transformations + + PfxTransform3 transformAB, transformBA; + PfxMatrix3 matrixAB, matrixBA; + PfxVector3 offsetAB, offsetBA; + + transformAB = orthoInverse(transformA) * transformB; + transformBA = orthoInverse(transformAB); + + matrixAB = transformAB.getUpper3x3(); + offsetAB = transformAB.getTranslation(); + matrixBA = transformBA.getUpper3x3(); + offsetBA = transformBA.getTranslation(); + + PfxMatrix3 absMatrixAB = absPerElem(matrixAB); + PfxMatrix3 absMatrixBA = absPerElem(matrixBA); + + // find separating axis with largest gap between projections + + BoxSepAxisType axisType; + PfxVector3 axisA(0.0f), axisB(0.0f); + PfxFloat gap, maxGap; + int faceDimA = 0, faceDimB = 0, edgeDimA = 0, edgeDimB = 0; + + // face axes + + PfxVector3 gapsA = absPerElem(offsetAB) - boxA.m_half - absMatrixAB * boxB.m_half; + + AaxisTest(0,X,true); + AaxisTest(1,Y,false); + AaxisTest(2,Z,false); + + PfxVector3 gapsB = absPerElem(offsetBA) - boxB.m_half - absMatrixBA * boxA.m_half; + + BaxisTest(0,X); + BaxisTest(1,Y); + BaxisTest(2,Z); + + // cross product axes + + // 外積が0のときの対策 + absMatrixAB += PfxMatrix3(1.0e-5f); + absMatrixBA += PfxMatrix3(1.0e-5f); + + PfxMatrix3 lsqrs, projOffset, projAhalf, projBhalf; + + lsqrs.setCol0( mulPerElem( matrixBA.getCol2(), matrixBA.getCol2() ) + + mulPerElem( matrixBA.getCol1(), matrixBA.getCol1() ) ); + lsqrs.setCol1( mulPerElem( matrixBA.getCol2(), matrixBA.getCol2() ) + + mulPerElem( matrixBA.getCol0(), matrixBA.getCol0() ) ); + lsqrs.setCol2( mulPerElem( matrixBA.getCol1(), matrixBA.getCol1() ) + + mulPerElem( matrixBA.getCol0(), matrixBA.getCol0() ) ); + + projOffset.setCol0(matrixBA.getCol1() * offsetAB.getZ() - matrixBA.getCol2() * offsetAB.getY()); + projOffset.setCol1(matrixBA.getCol2() * offsetAB.getX() - matrixBA.getCol0() * offsetAB.getZ()); + projOffset.setCol2(matrixBA.getCol0() * offsetAB.getY() - matrixBA.getCol1() * offsetAB.getX()); + + projAhalf.setCol0(absMatrixBA.getCol1() * boxA.m_half.getZ() + absMatrixBA.getCol2() * boxA.m_half.getY()); + projAhalf.setCol1(absMatrixBA.getCol2() * boxA.m_half.getX() + absMatrixBA.getCol0() * boxA.m_half.getZ()); + projAhalf.setCol2(absMatrixBA.getCol0() * boxA.m_half.getY() + absMatrixBA.getCol1() * boxA.m_half.getX()); + + projBhalf.setCol0(absMatrixAB.getCol1() * boxB.m_half.getZ() + absMatrixAB.getCol2() * boxB.m_half.getY()); + projBhalf.setCol1(absMatrixAB.getCol2() * boxB.m_half.getX() + absMatrixAB.getCol0() * boxB.m_half.getZ()); + projBhalf.setCol2(absMatrixAB.getCol0() * boxB.m_half.getY() + absMatrixAB.getCol1() * boxB.m_half.getX()); + + PfxMatrix3 gapsAxB = absPerElem(projOffset) - projAhalf - transpose(projBhalf); + + CrossAxisTest(0,0,X); + CrossAxisTest(0,1,Y); + CrossAxisTest(0,2,Z); + CrossAxisTest(1,0,X); + CrossAxisTest(1,1,Y); + CrossAxisTest(1,2,Z); + CrossAxisTest(2,0,X); + CrossAxisTest(2,1,Y); + CrossAxisTest(2,2,Z); + + // need to pick the face on each box whose normal best matches the separating axis. + // will transform vectors to be in the coordinate system of this face to simplify things later. + // for this, a permutation matrix can be used, which the next section computes. + + int dimA[3], dimB[3]; + + if ( axisType == A_AXIS ) { + if ( dot(axisA,offsetAB) < 0.0f ) + axisA = -axisA; + axisB = matrixBA * -axisA; + + PfxVector3 absAxisB = PfxVector3(absPerElem(axisB)); + + if ( ( absAxisB[0] > absAxisB[1] ) && ( absAxisB[0] > absAxisB[2] ) ) + faceDimB = 0; + else if ( absAxisB[1] > absAxisB[2] ) + faceDimB = 1; + else + faceDimB = 2; + } else if ( axisType == B_AXIS ) { + if ( dot(axisB,offsetBA) < 0.0f ) + axisB = -axisB; + axisA = matrixAB * -axisB; + + PfxVector3 absAxisA = PfxVector3(absPerElem(axisA)); + + if ( ( absAxisA[0] > absAxisA[1] ) && ( absAxisA[0] > absAxisA[2] ) ) + faceDimA = 0; + else if ( absAxisA[1] > absAxisA[2] ) + faceDimA = 1; + else + faceDimA = 2; + } + + if ( axisType == CROSS_AXIS ) { + if ( dot(axisA,offsetAB) < 0.0f ) + axisA = -axisA; + axisB = matrixBA * -axisA; + + PfxVector3 absAxisA = PfxVector3(absPerElem(axisA)); + PfxVector3 absAxisB = PfxVector3(absPerElem(axisB)); + + dimA[1] = edgeDimA; + dimB[1] = edgeDimB; + + if ( edgeDimA == 0 ) { + if ( absAxisA[1] > absAxisA[2] ) { + dimA[0] = 2; + dimA[2] = 1; + } else { + dimA[0] = 1; + dimA[2] = 2; + } + } else if ( edgeDimA == 1 ) { + if ( absAxisA[2] > absAxisA[0] ) { + dimA[0] = 0; + dimA[2] = 2; + } else { + dimA[0] = 2; + dimA[2] = 0; + } + } else { + if ( absAxisA[0] > absAxisA[1] ) { + dimA[0] = 1; + dimA[2] = 0; + } else { + dimA[0] = 0; + dimA[2] = 1; + } + } + + if ( edgeDimB == 0 ) { + if ( absAxisB[1] > absAxisB[2] ) { + dimB[0] = 2; + dimB[2] = 1; + } else { + dimB[0] = 1; + dimB[2] = 2; + } + } else if ( edgeDimB == 1 ) { + if ( absAxisB[2] > absAxisB[0] ) { + dimB[0] = 0; + dimB[2] = 2; + } else { + dimB[0] = 2; + dimB[2] = 0; + } + } else { + if ( absAxisB[0] > absAxisB[1] ) { + dimB[0] = 1; + dimB[2] = 0; + } else { + dimB[0] = 0; + dimB[2] = 1; + } + } + } else { + dimA[2] = faceDimA; + dimA[0] = (faceDimA+1)%3; + dimA[1] = (faceDimA+2)%3; + dimB[2] = faceDimB; + dimB[0] = (faceDimB+1)%3; + dimB[1] = (faceDimB+2)%3; + } + + PfxMatrix3 aperm_col, bperm_col; + + aperm_col.setCol0(ident[dimA[0]]); + aperm_col.setCol1(ident[dimA[1]]); + aperm_col.setCol2(ident[dimA[2]]); + + bperm_col.setCol0(ident[dimB[0]]); + bperm_col.setCol1(ident[dimB[1]]); + bperm_col.setCol2(ident[dimB[2]]); + + PfxMatrix3 aperm_row, bperm_row; + + aperm_row = transpose(aperm_col); + bperm_row = transpose(bperm_col); + + // permute all box parameters to be in the face coordinate systems + + PfxMatrix3 matrixAB_perm = aperm_row * matrixAB * bperm_col; + PfxMatrix3 matrixBA_perm = transpose(matrixAB_perm); + + PfxVector3 offsetAB_perm, offsetBA_perm; + + offsetAB_perm = aperm_row * offsetAB; + offsetBA_perm = bperm_row * offsetBA; + + PfxVector3 halfA_perm, halfB_perm; + + halfA_perm = aperm_row * boxA.m_half; + halfB_perm = bperm_row * boxB.m_half; + + // compute the vector between the centers of each face, in each face's coordinate frame + + PfxVector3 signsA_perm, signsB_perm, scalesA_perm, scalesB_perm, faceOffsetAB_perm, faceOffsetBA_perm; + + signsA_perm = copySignPerElem(PfxVector3(1.0f),aperm_row * axisA); + signsB_perm = copySignPerElem(PfxVector3(1.0f),bperm_row * axisB); + scalesA_perm = mulPerElem( signsA_perm, halfA_perm ); + scalesB_perm = mulPerElem( signsB_perm, halfB_perm ); + + faceOffsetAB_perm = offsetAB_perm + matrixAB_perm.getCol2() * scalesB_perm.getZ(); + faceOffsetAB_perm.setZ( faceOffsetAB_perm.getZ() - scalesA_perm.getZ() ); + + faceOffsetBA_perm = offsetBA_perm + matrixBA_perm.getCol2() * scalesA_perm.getZ(); + faceOffsetBA_perm.setZ( faceOffsetBA_perm.getZ() - scalesB_perm.getZ() ); + + if ( maxGap < 0.0f ) { + // if boxes overlap, this will separate the faces for finding points of penetration. + + faceOffsetAB_perm -= aperm_row * axisA * maxGap * 1.01f; + faceOffsetBA_perm -= bperm_row * axisB * maxGap * 1.01f; + } + + // for each vertex/face or edge/edge pair of the two faces, find the closest points. + // + // these points each have an associated box feature (vertex, edge, or face). if each + // point is in the external Voronoi region of the other's feature, they are the + // closest points of the boxes, and the algorithm can exit. + // + // the feature pairs are arranged so that in the general case, the first test will + // succeed. degenerate cases (parallel faces) may require up to all tests in the + // worst case. + // + // if for some reason no case passes the Voronoi test, the features with the minimum + // distance are returned. + + PfxPoint3 localPointA_perm, localPointB_perm; + PfxFloat minDistSqr; + PfxBool done; + + PfxVector3 hA_perm( halfA_perm ), hB_perm( halfB_perm ); + + localPointA_perm.setZ( scalesA_perm.getZ() ); + localPointB_perm.setZ( scalesB_perm.getZ() ); + scalesA_perm.setZ(0.0f); + scalesB_perm.setZ(0.0f); + + int otherFaceDimA, otherFaceDimB; + + if ( axisType == CROSS_AXIS ) { + EdgeEdgeTests( done, minDistSqr, localPointA_perm, localPointB_perm, + otherFaceDimA, otherFaceDimB, + hA_perm, hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, signsB_perm, + scalesA_perm, scalesB_perm, true ); + + if ( !done ) { + VertexBFaceATests( done, minDistSqr, localPointA_perm, localPointB_perm, + hA_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsB_perm, scalesB_perm, false ); + + if ( !done ) { + VertexAFaceBTests( done, minDistSqr, localPointA_perm, localPointB_perm, + hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, scalesA_perm, false ); + } + } + } else if ( axisType == B_AXIS ) { + VertexAFaceBTests( done, minDistSqr, localPointA_perm, localPointB_perm, + hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, scalesA_perm, true ); + + if ( !done ) { + VertexBFaceATests( done, minDistSqr, localPointA_perm, localPointB_perm, + hA_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsB_perm, scalesB_perm, false ); + + if ( !done ) { + EdgeEdgeTests( done, minDistSqr, localPointA_perm, localPointB_perm, + otherFaceDimA, otherFaceDimB, + hA_perm, hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, signsB_perm, + scalesA_perm, scalesB_perm, false ); + } + } + } else { + VertexBFaceATests( done, minDistSqr, localPointA_perm, localPointB_perm, + hA_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsB_perm, scalesB_perm, true ); + + if ( !done ) { + VertexAFaceBTests( done, minDistSqr, localPointA_perm, localPointB_perm, + hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, scalesA_perm, false ); + + if ( !done ) { + EdgeEdgeTests( done, minDistSqr, localPointA_perm, localPointB_perm, + otherFaceDimA, otherFaceDimB, + hA_perm, hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, signsB_perm, + scalesA_perm, scalesB_perm, false ); + } + } + } + + // convert local points from face-local to box-local coordinate system + + pointA = PfxPoint3( aperm_col * PfxVector3( localPointA_perm ) ); + pointB = PfxPoint3( bperm_col * PfxVector3( localPointB_perm ) ); + + normal = transformA * axisA; + + //SCE_PFX_PRINTF("minDistSqr %f maxGap %f\n",minDistSqr,maxGap); + //SCE_PFX_PRINTF("normal %f %f %f\n",normal[0],normal[1],normal[2]); + //SCE_PFX_PRINTF("pointA %f %f %f\n",pointA[0],pointA[1],pointA[2]); + //SCE_PFX_PRINTF("pointB %f %f %f\n",pointB[0],pointB[1],pointB[2]); + + if ( maxGap < 0.0f ) { + return (maxGap); + } else { + return (sqrtf( minDistSqr )); + } +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_box.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_box.h new file mode 100644 index 0000000..69ff530 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_box.h @@ -0,0 +1,33 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONTACT_BOX_BOX_H +#define _SCE_PFX_CONTACT_BOX_BOX_H + +#include "../../../include/physics_effects/base_level/base/pfx_common.h" +namespace sce { +namespace PhysicsEffects { + +PfxFloat pfxContactBoxBox( + PfxVector3 &normal,PfxPoint3 &pointA,PfxPoint3 &pointB, + void *shapeA,const PfxTransform3 &transformA, + void *shapeB,const PfxTransform3 &transformB, + PfxFloat distanceThreshold = SCE_PFX_FLT_MAX); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_CONTACT_BOX_BOX_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_capsule.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_capsule.cpp new file mode 100644 index 0000000..3509533 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_capsule.cpp @@ -0,0 +1,608 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/collision/pfx_box.h" +#include "../../../include/physics_effects/base_level/collision/pfx_capsule.h" +#include "pfx_contact_box_capsule.h" + +namespace sce { +namespace PhysicsEffects { + +enum BoxCapsSepAxisType +{ + BOX_AXIS, CROSS_AXIS +}; + +//------------------------------------------------------------------------------------------------- +// voronoiTol: bevels Voronoi planes slightly which helps when features are parallel. +//------------------------------------------------------------------------------------------------- + +static const PfxFloat voronoiTol = -1.0e-5f; + +//------------------------------------------------------------------------------------------------- +// lenSqrTol: minimum square of length for safe normalize. +//------------------------------------------------------------------------------------------------- + +static const PfxFloat lenSqrTol = 1.0e-30f; + +//------------------------------------------------------------------------------------------------- +// separating axis tests: gaps along each axis are computed, and the axis with the maximum +// gap is stored. cross product axes are normalized. +//------------------------------------------------------------------------------------------------- + +#define AaxisTest( dim, letter, first ) \ +{ \ + if ( first ) \ + { \ + maxGap = gapsA.get##letter(); \ + if ( maxGap - capsuleB.m_radius > distanceThreshold ) return maxGap - capsuleB.m_radius; \ + axisType = BOX_AXIS; \ + faceDimA = dim; \ + axisA = ident[dim]; \ + } \ + else \ + { \ + PfxFloat gap = gapsA.get##letter(); \ + if ( gap - capsuleB.m_radius > distanceThreshold ) return gap - capsuleB.m_radius; \ + else if ( gap > maxGap ) \ + { \ + maxGap = gap; \ + axisType = BOX_AXIS; \ + faceDimA = dim; \ + axisA = ident[dim]; \ + } \ + } \ +} + +#define CrossAxisTest( dima, lettera ) \ +{ \ + const PfxFloat lsqr_tolerance = 1.0e-30f; \ + PfxFloat lsqr; \ + \ + lsqr = lsqrs.get##lettera(); \ + \ + if ( lsqr > lsqr_tolerance ) \ + { \ + PfxFloat l_recip = 1.0f / sqrtf( lsqr ); \ + PfxFloat gap = PfxFloat(gapsAxB.get##lettera()) * l_recip; \ + \ + if ( gap - capsuleB.m_radius > distanceThreshold ) \ + { \ + return gap - capsuleB.m_radius; \ + } \ + \ + if ( gap > maxGap ) \ + { \ + maxGap = gap; \ + axisType = CROSS_AXIS; \ + edgeDimA = dima; \ + axisA = crossProdMat.getCol##dima() * l_recip; \ + } \ + } \ +} + +//------------------------------------------------------------------------------------------------- +// tests whether a vertex of box B and a face of box A are the closest features +//------------------------------------------------------------------------------------------------- + +inline +PfxFloat +VertexBFaceATest( + PfxBool& inVoronoi, + PfxFloat& t0, + PfxFloat& t1, + PfxVector3& ptsVec, + const PfxVector3& hA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG offsetAB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG capsDirection, + PfxFloat signB, + PfxFloat scaleB ) +{ + // compute endpoint of capsule in box's coordinate system + + PfxVector3 endpoint = PfxVector3( offsetAB + capsDirection * scaleB ); + + // compute the parameters of the point on the box face closest to this corner. + + t0 = endpoint[0]; + t1 = endpoint[1]; + + if ( t0 > hA[0] ) + t0 = hA[0]; + else if ( t0 < -hA[0] ) + t0 = -hA[0]; + if ( t1 > hA[1] ) + t1 = hA[1]; + else if ( t1 < -hA[1] ) + t1 = -hA[1]; + + // get vector from face point to capsule endpoint + + endpoint[0] -= t0; + endpoint[1] -= t1; + ptsVec = PfxVector3(endpoint); + + // do the Voronoi test: already know the point on B is in the Voronoi region of the + // point on A, check the reverse. + + inVoronoi = ( -signB * dot(ptsVec,capsDirection) >= voronoiTol ); + + return (lengthSqr(ptsVec)); +} + +#define VertexBFaceA_SetNewMin() \ +{ \ + minDistSqr = distSqr; \ + closestPtsVec = ptsVec; \ + localPointA.setX(t0); \ + localPointA.setY(t1); \ + segmentParamB = scaleB; \ +} + +void +VertexBFaceATests( + PfxBool& done, + PfxFloat& minDistSqr, + PfxVector3& closestPtsVec, + PfxPoint3& localPointA, + PfxFloat& segmentParamB, + const PfxVector3& hA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG offsetAB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG capsDirection, + PfxFloat signB, PfxFloat scaleB, + PfxBool first ) +{ + PfxVector3 ptsVec; + PfxFloat t0, t1; + PfxFloat distSqr; + + // test endpoint of capsule nearest to face + + distSqr = VertexBFaceATest( done, t0, t1, ptsVec, hA, offsetAB, capsDirection, signB, scaleB ); + + if ( first ) { + VertexBFaceA_SetNewMin(); + } else { + if ( distSqr < minDistSqr ) { + VertexBFaceA_SetNewMin(); + } + } + + if ( done ) + return; + + signB = -signB; + scaleB = -scaleB; + + // test other endpoint if necessary + + distSqr = VertexBFaceATest( done, t0, t1, ptsVec, hA, offsetAB, capsDirection, signB, scaleB ); + + if ( distSqr < minDistSqr ) { + VertexBFaceA_SetNewMin(); + } +} + +//------------------------------------------------------------------------------------------------- +// EdgeEdgeTest: +// +// tests whether a pair of edges are the closest features +// +// note on the shorthand: +// 'a' & 'b' refer to the edges. +// 'c' is the dimension of the axis that points from the face center to the edge Center +// 'd' is the dimension of the edge Direction +// the dimension of the face normal is 2 +//------------------------------------------------------------------------------------------------- + +#define EdgeEdgeTest( ac, ac_letter, ad, ad_letter ) \ +{ \ + /* get vector between edge centers */ \ + \ + ptsVec = offsetAB; \ + ptsVec.set##ac_letter( ptsVec.get##ac_letter() - scalesA.get##ac_letter() ); \ + \ + /* find parameters of closest points on line segments. */ \ + \ + PfxFloat capsDirection_ad = capsDirection.get##ad_letter(); \ + PfxFloat ptsVec_ad = ptsVec.get##ad_letter(); \ + PfxFloat capsDirDotPtsVec = dot(capsDirection,ptsVec); \ + PfxFloat denom = 1.0f - capsDirection_ad * capsDirection_ad; \ + \ + if ( denom == 0.0f ) \ + { \ + tA = 0.0f; \ + } \ + else \ + { \ + tA = ( ptsVec_ad - capsDirDotPtsVec * capsDirection_ad ) / denom; \ + if ( tA < -hA[ad] ) tA = -hA[ad]; \ + else if ( tA > hA[ad] ) tA = hA[ad]; \ + } \ + \ + tB = tA * capsDirection_ad - capsDirDotPtsVec; \ + \ + if ( tB < -hB ) \ + { \ + tB = -hB; \ + tA = tB * capsDirection_ad + ptsVec_ad; \ + \ + if ( tA < -hA[ad] ) tA = -hA[ad]; \ + else if ( tA > hA[ad] ) tA = hA[ad]; \ + } \ + else if ( tB > hB ) \ + { \ + tB = hB; \ + tA = tB * capsDirection_ad + ptsVec_ad; \ + \ + if ( tA < -hA[ad] ) tA = -hA[ad]; \ + else if ( tA > hA[ad] ) tA = hA[ad]; \ + } \ + \ + /* make vector to point at tB on edge B from the center of edge A. */ \ + /* test that it lies inside edge A's voronoi region. */ \ + \ + ptsVec += capsDirection * tB; \ + \ + PfxVector3 cptsVec( mulPerElem( ptsVec, signsA ) ); \ + \ + inVoronoi = ( cptsVec[ac] >= voronoiTol * cptsVec[2] ) && \ + ( cptsVec[2] >= voronoiTol * cptsVec[ac] ); \ + \ + ptsVec.set##ad_letter( ptsVec.get##ad_letter() - tA ); \ + \ + return lengthSqr(ptsVec); \ +} + +PfxFloat +EdgeEdgeTest_01( + PfxBool& inVoronoi, + PfxFloat& tA, + PfxFloat& tB, + PfxVector3& ptsVec, + const PfxVector3& hA, + PfxFloat hB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG offsetAB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG capsDirection, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesA ) +{ + EdgeEdgeTest( 0, X, 1, Y ); +} + +PfxFloat +EdgeEdgeTest_10( + PfxBool& inVoronoi, + PfxFloat& tA, + PfxFloat& tB, + PfxVector3& ptsVec, + const PfxVector3& hA, + PfxFloat hB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG offsetAB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG capsDirection, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesA ) +{ + EdgeEdgeTest( 1, Y, 0, X ); +} + +#define EdgeEdge_SetNewMin( ac_letter, ad_letter ) \ +{ \ + minDistSqr = distSqr; \ + closestPtsVec = ptsVec; \ + localPointA.set##ac_letter(scalesA.get##ac_letter()); \ + localPointA.set##ad_letter(tA); \ + segmentParamB = tB; \ + otherFaceDimA = testOtherFaceDimA; \ +} + +void +EdgeEdgeTests( + PfxBool& done, + PfxFloat& minDistSqr, + PfxVector3& closestPtsVec, + PfxPoint3& localPointA, + PfxFloat& segmentParamB, + int & otherFaceDimA, + const PfxVector3& hA, + PfxFloat hB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG offsetAB, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG capsDirection, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG signsA, + PfxVector3 SCE_VECTORMATH_AOS_VECTOR_ARG scalesA, + PfxBool first ) +{ + PfxVector3 ptsVec; + PfxFloat tA, tB; + int testOtherFaceDimA; + + testOtherFaceDimA = 0; + + PfxFloat distSqr = EdgeEdgeTest_01( done, tA, tB, ptsVec, hA, hB, + offsetAB, capsDirection, signsA, scalesA ); + + if ( first ) { + EdgeEdge_SetNewMin( X, Y ); + } else { + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y ); + } + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = EdgeEdgeTest_01( done, tA, tB, ptsVec, hA, hB, + offsetAB, capsDirection, signsA, scalesA ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y ); + } + + if ( done ) + return; + + testOtherFaceDimA = 1; + + distSqr = EdgeEdgeTest_10( done, tA, tB, ptsVec, hA, hB, + offsetAB, capsDirection, signsA, scalesA ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X ); + } + + if ( done ) + return; + + signsA.setY( -signsA.getY() ); + scalesA.setY( -scalesA.getY() ); + + distSqr = EdgeEdgeTest_10( done, tA, tB, ptsVec, hA, hB, + offsetAB, capsDirection, signsA, scalesA ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X ); + } +} + +PfxFloat pfxContactBoxCapsule( + PfxVector3 &normal,PfxPoint3 &pointA,PfxPoint3 &pointB, + void *shapeA,const PfxTransform3 &transformA, + void *shapeB,const PfxTransform3 &transformB, + PfxFloat distanceThreshold) +{ + PfxBox boxA = *((PfxBox*)shapeA); + PfxCapsule capsuleB = *((PfxCapsule*)shapeB); + + PfxVector3 ident[3] = { + PfxVector3(1.0,0.0,0.0), + PfxVector3(0.0,1.0,0.0), + PfxVector3(0.0,0.0,1.0), + }; + + // get capsule position and direction in box's coordinate system + + PfxMatrix3 matrixA = transformA.getUpper3x3(); + PfxMatrix3 matrixAinv = transpose(matrixA); + + PfxVector3 directionB = transformB.getUpper3x3().getCol0(); + PfxVector3 translationB = transformB.getTranslation(); + + PfxVector3 capsDirection = matrixAinv * directionB; + PfxVector3 absCapsDirection = absPerElem(capsDirection); + PfxVector3 offsetAB = matrixAinv * (translationB - transformA.getTranslation()); + + // find separating axis with largest gap between projections + + BoxCapsSepAxisType axisType; + PfxVector3 axisA; + PfxFloat maxGap; + int faceDimA = 0, edgeDimA = 0; + + // face axes + + // can compute all the gaps at once with VU0 + + PfxVector3 gapsA = absPerElem(offsetAB) - boxA.m_half - absCapsDirection * capsuleB.m_halfLen; + + AaxisTest( 0, X, true ); + AaxisTest( 1, Y, false ); + AaxisTest( 2, Z, false ); + + // cross product axes + + // compute gaps on all cross product axes using some VU0 math. suppose there's a tradeoff + // between doing this with SIMD all at once or without SIMD in each cross product test, since + // some test might exit early. + + PfxVector3 lsqrs, projOffset, projAhalf; + + PfxMatrix3 crossProdMat = crossMatrix(capsDirection) * PfxMatrix3::identity(); + PfxMatrix3 crossProdMatT = crossMatrix(-capsDirection) * PfxMatrix3::identity(); + + lsqrs = mulPerElem( crossProdMatT.getCol0(), crossProdMatT.getCol0() ) + + mulPerElem( crossProdMatT.getCol1(), crossProdMatT.getCol1() ) + + mulPerElem( crossProdMatT.getCol2(), crossProdMatT.getCol2() ); + + projOffset = crossProdMatT * offsetAB; + projAhalf = absPerElem(crossProdMatT) * boxA.m_half; + + PfxVector3 gapsAxB = absPerElem(projOffset) - projAhalf; + + CrossAxisTest( 0, X ); + CrossAxisTest( 1, Y ); + CrossAxisTest( 2, Z ); + + // make axis point from box center towards capsule center. + + if ( dot(axisA,offsetAB) < 0.0f ) + axisA = -axisA; + + // find the face on box whose normal best matches the separating axis. will use the entire + // face only in degenerate cases. + // + // to make things simpler later, change the coordinate system so that the face normal is the z + // direction. if an edge cross product axis was chosen above, also align the box edge to the y + // axis. this saves the later tests from having to know which face was chosen. changing the + // coordinate system involves permuting vector elements, so construct a permutation matrix. + // I believe this is a faster way to permute a bunch of vectors than using arrays. + + int dimA[3]; + + if ( axisType == CROSS_AXIS ) { + PfxVector3 absAxisA = PfxVector3(absPerElem(axisA)); + + dimA[1] = edgeDimA; + + if ( edgeDimA == 0 ) { + if ( absAxisA[1] > absAxisA[2] ) { + dimA[0] = 2; + dimA[2] = 1; + } else { + dimA[0] = 1; + dimA[2] = 2; + } + } else if ( edgeDimA == 1 ) { + if ( absAxisA[2] > absAxisA[0] ) { + dimA[0] = 0; + dimA[2] = 2; + } else { + dimA[0] = 2; + dimA[2] = 0; + } + } else { + if ( absAxisA[0] > absAxisA[1] ) { + dimA[0] = 1; + dimA[2] = 0; + } else { + dimA[0] = 0; + dimA[2] = 1; + } + } + } else { + dimA[2] = faceDimA; + dimA[0] = (faceDimA+1)%3; + dimA[1] = (faceDimA+2)%3; + } + + PfxMatrix3 aperm_col; + + aperm_col.setCol0(ident[dimA[0]]); + aperm_col.setCol1(ident[dimA[1]]); + aperm_col.setCol2(ident[dimA[2]]); + + PfxMatrix3 aperm_row = transpose(aperm_col); + + // permute vectors to be in face coordinate system. + + PfxVector3 offsetAB_perm = aperm_row * offsetAB; + PfxVector3 halfA_perm = aperm_row * boxA.m_half; + PfxVector3 signsA_perm = copySignPerElem(PfxVector3(1.0f), aperm_row * axisA); + PfxVector3 scalesA_perm = mulPerElem( signsA_perm, halfA_perm ); + PfxVector3 capsDirection_perm = aperm_row * capsDirection; + PfxFloat signB = (-dot(capsDirection,axisA) > 0.0f)? 1.0f : -1.0f; + PfxFloat scaleB = signB * capsuleB.m_halfLen; + + // compute the vector between the center of the box face and the capsule center + + offsetAB_perm.setZ( offsetAB_perm.getZ() - scalesA_perm.getZ() ); + + // if box and capsule overlap, this will separate them for finding points of penetration. + + if ( maxGap < 0.0f ) { + offsetAB_perm -= aperm_row * axisA * maxGap * 1.01f; + } + + // for each vertex/face or edge/edge pair of box face and line segment, find the closest + // points. + // + // these points each have an associated feature (vertex, edge, or face). if each + // point is in the external Voronoi region of the other's feature, they are the + // closest points of the objects, and the algorithm can exit. + // + // the feature pairs are arranged so that in the general case, the first test will + // succeed. degenerate cases (line segment parallel to face) may require up to all tests + // in the worst case. + // + // if for some reason no case passes the Voronoi test, the features with the minimum + // distance are returned. + + PfxVector3 closestPtsVec_perm; + PfxPoint3 localPointA_perm; + PfxFloat minDistSqr; + PfxFloat segmentParamB; + PfxBool done; + + localPointA_perm.setZ( scalesA_perm.getZ() ); + scalesA_perm.setZ(0.0f); + + PfxVector3 hA_perm( halfA_perm ); + + int otherFaceDimA; + + if ( axisType == CROSS_AXIS ) { + EdgeEdgeTests( done, minDistSqr, closestPtsVec_perm, localPointA_perm, segmentParamB, + otherFaceDimA, + hA_perm, capsuleB.m_halfLen, offsetAB_perm, capsDirection_perm, signsA_perm, + scalesA_perm, true ); + + if ( !done ) { + VertexBFaceATests( done, minDistSqr, closestPtsVec_perm, localPointA_perm, segmentParamB, + hA_perm, offsetAB_perm, capsDirection_perm, signB, scaleB, false ); + } + } else { + VertexBFaceATests( done, minDistSqr, closestPtsVec_perm, localPointA_perm, segmentParamB, + hA_perm, offsetAB_perm, capsDirection_perm, signB, scaleB, true ); + + if ( !done ) { + EdgeEdgeTests( done, minDistSqr, closestPtsVec_perm, localPointA_perm, segmentParamB, + otherFaceDimA, + hA_perm, capsuleB.m_halfLen, offsetAB_perm, capsDirection_perm, signsA_perm, + scalesA_perm, false ); + } + } + + // compute normal + + PfxBool centerInside = ( signsA_perm.getZ() * closestPtsVec_perm.getZ() < 0.0f ); + + if ( centerInside || ( minDistSqr < lenSqrTol ) ) { + normal = matrixA * axisA; + } else { + PfxVector3 closestPtsVec = aperm_col * closestPtsVec_perm; + normal = matrixA * ( closestPtsVec * (1.0f/sqrtf( minDistSqr )) ); + } + + // compute box point + + pointA = PfxPoint3( aperm_col * PfxVector3( localPointA_perm ) ); + + // compute capsule point + + pointB = PfxPoint3( transpose(transformB.getUpper3x3()) * ( directionB * segmentParamB - normal * capsuleB.m_radius ) ); + + if ( centerInside ) { + return (-sqrtf( minDistSqr ) - capsuleB.m_radius); + } else { + return (sqrtf( minDistSqr ) - capsuleB.m_radius); + } +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_capsule.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_capsule.h new file mode 100644 index 0000000..72e8aa7 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_capsule.h @@ -0,0 +1,34 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONTACT_BOX_CAPSULE_H +#define _SCE_PFX_CONTACT_BOX_CAPSULE_H + +#include "../../../include/physics_effects/base_level/base/pfx_common.h" + +namespace sce { +namespace PhysicsEffects { + +PfxFloat pfxContactBoxCapsule( + PfxVector3 &normal,PfxPoint3 &pointA,PfxPoint3 &pointB, + void *shapeA,const PfxTransform3 &transformA, + void *shapeB,const PfxTransform3 &transformB, + PfxFloat distanceThreshold = SCE_PFX_FLT_MAX); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_CONTACT_BOX_CAPSULE_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_sphere.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_sphere.cpp new file mode 100644 index 0000000..82a015e --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_sphere.cpp @@ -0,0 +1,236 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/collision/pfx_box.h" +#include "../../../include/physics_effects/base_level/collision/pfx_sphere.h" +#include "pfx_contact_box_sphere.h" + +namespace sce { +namespace PhysicsEffects { + +static const PfxFloat lenSqrTol = 1.0e-30f; + +inline +PfxFloat +VertexBFaceATest( + PfxVector3& ptsVec, + PfxFloat& t0, + PfxFloat& t1, + const PfxVector3& hA, + const PfxVector3 &offsetAB ) +{ + // compute center of sphere in box's coordinate system + + PfxVector3 cptsVec = PfxVector3(offsetAB); + + // compute the parameters of the point on the face + + t0 = cptsVec[0]; + t1 = cptsVec[1]; + + if ( t0 > hA[0] ) + t0 = hA[0]; + else if ( t0 < -hA[0] ) + t0 = -hA[0]; + if ( t1 > hA[1] ) + t1 = hA[1]; + else if ( t1 < -hA[1] ) + t1 = -hA[1]; + + cptsVec[0] -= t0; + cptsVec[1] -= t1; + + ptsVec = PfxVector3( cptsVec ); + + return dot(ptsVec,ptsVec); +} + +PfxFloat pfxContactBoxSphere( + PfxVector3 &normal,PfxPoint3 &pointA,PfxPoint3 &pointB, + void *shapeA,const PfxTransform3 &transformA, + void *shapeB,const PfxTransform3 &transformB, + PfxFloat distanceThreshold) +{ + PfxBox &boxA = *((PfxBox*)shapeA); + PfxSphere &sphereB = *((PfxSphere*)shapeB); + + PfxVector3 ident[3] = { + PfxVector3(1.0,0.0,0.0), + PfxVector3(0.0,1.0,0.0), + PfxVector3(0.0,0.0,1.0), + }; + + //{ + // PfxMatrix3 identity = PfxMatrix3::identity(); + // ident[0] = identity.getCol0(); + // ident[1] = identity.getCol1(); + // ident[2] = identity.getCol2(); + //} + + // offsetAB is vector from A's center to B's center, in A's coordinate system + + PfxVector3 translationB = transformB.getTranslation(); + PfxVector3 offsetAB = transpose(transformA.getUpper3x3()) * ( translationB - + transformA.getTranslation() ); + + // find separating axis with largest gap between objects + + PfxVector3 axisA; + int faceDimA; + PfxFloat maxGap; + + PfxVector3 gapsA = absPerElem(offsetAB) - boxA.m_half - PfxVector3(sphereB.m_radius); + PfxVector3 signsA = copySignPerElem(PfxVector3(1.0f),offsetAB); + + { + PfxFloat gap = gapsA[0]; + + if( gap > distanceThreshold ) { + return gap; + } + + maxGap = gap; + faceDimA = 0; + axisA = mulPerElem( ident[0], signsA ); + + if( gap > maxGap ) { + maxGap = gap; + faceDimA = 0; + axisA = mulPerElem( ident[0], signsA ); + } + + gap = gapsA[1]; + + if( gap > distanceThreshold ) { + return gap; + } + + if( gap > maxGap ) { + maxGap = gap; + faceDimA = 1; + axisA = mulPerElem( ident[1], signsA ); + } + + gap = gapsA[2]; + + if( gap > distanceThreshold ) { + return gap; + } + + if( gap > maxGap ) { + maxGap = gap; + faceDimA = 2; + axisA = mulPerElem( ident[2], signsA ); + } + } + + // choose face in this direction, and make a new coordinate system which the z axis = face + // normal, x and y axes tangent to the face. to transform vectors into this coordinate + // system, will use a permutation matrix. + + int dimA[3]; + + dimA[2] = faceDimA; + dimA[0] = (faceDimA+1)%3; + dimA[1] = (faceDimA+2)%3; + + PfxMatrix3 apermCol; + + apermCol.setCol0(ident[dimA[0]]); + apermCol.setCol1(ident[dimA[1]]); + apermCol.setCol2(ident[dimA[2]]); + + PfxMatrix3 apermRow = transpose(apermCol); + + // permute vectors + + PfxVector3 halfA_perm = apermRow * boxA.m_half; + PfxVector3 offsetAB_perm = apermRow * offsetAB; + PfxVector3 signsA_perm = apermRow * signsA; + + // compute the vector between the center of the box face and the sphere center + + PfxFloat signA2 = signsA_perm.getZ(); + PfxFloat scaleA2 = halfA_perm.getZ() * signA2; + offsetAB_perm.setZ( offsetAB_perm.getZ() - scaleA2 ); + + // find point on face closest to sphere center + + PfxFloat t0, t1; + PfxFloat minDistSqr; + PfxVector3 closestPtsVec_perm; + PfxPoint3 localPointA_perm; + + minDistSqr = VertexBFaceATest( closestPtsVec_perm, t0, t1, PfxVector3( halfA_perm ), offsetAB_perm ); + + //SCE_PFX_PRINTF("faceDimA %d dimA %d %d %d\n",faceDimA,dimA[0],dimA[1],dimA[2]); + //SCE_PFX_PRINTF("boxA.m_half %f %f %f\n",boxA.m_half[0],boxA.m_half[1],boxA.m_half[2]); + //SCE_PFX_PRINTF("ident %f %f %f | %f %f %f | %f %f %f\n", + // ident[0][0],ident[0][1],ident[0][2], + // ident[1][0],ident[1][1],ident[1][2], + // ident[2][0],ident[2][1],ident[2][2]); + //SCE_PFX_PRINTF("apermCol %f %f %f | %f %f %f | %f %f %f\n", + // apermCol[0][0],apermCol[0][1],apermCol[0][2], + // apermCol[1][0],apermCol[1][1],apermCol[1][2], + // apermCol[2][0],apermCol[2][1],apermCol[2][2]); + //SCE_PFX_PRINTF("apermRow %f %f %f | %f %f %f | %f %f %f\n", + // apermRow[0][0],apermRow[0][1],apermRow[0][2], + // apermRow[1][0],apermRow[1][1],apermRow[1][2], + // apermRow[2][0],apermRow[2][1],apermRow[2][2]); + + //SCE_PFX_PRINTF("closestPtsVec_perm %f %f %f\n",closestPtsVec_perm[0],closestPtsVec_perm[1],closestPtsVec_perm[2]); + //SCE_PFX_PRINTF("halfA_perm %f %f %f\n",halfA_perm[0],halfA_perm[1],halfA_perm[2]); + //SCE_PFX_PRINTF("offsetAB_perm %f %f %f\n",offsetAB_perm[0],offsetAB_perm[1],offsetAB_perm[2]); + //SCE_PFX_PRINTF("t0 %f t1 %f scaleA2 %f\n",t0,t1,scaleA2); + + //SCE_PFX_PRINTF("minDistSqr %f sphereB.m_radius %f\n",minDistSqr,sphereB.m_radius); + + localPointA_perm = PfxPoint3( t0, t1, scaleA2 ); + + // compute normal + + bool centerInside = ( signA2 * closestPtsVec_perm.getZ() < 0.0f ); + + if ( centerInside || ( minDistSqr < lenSqrTol ) ) { + normal = transformA * axisA; + } else { + PfxVector3 closestPtsVec = apermCol * closestPtsVec_perm; + normal = transformA * ( closestPtsVec * ( 1.0f / sqrtf( minDistSqr ) ) ); + } + + // compute box point + + pointA = PfxPoint3( apermCol * PfxVector3( localPointA_perm ) ); + + // compute sphere point + + pointB = PfxPoint3( transpose(transformB.getUpper3x3()) * ( -normal * sphereB.m_radius ) ); + + // return distance + + //SCE_PFX_PRINTF("normal %f %f %f\n",(float)normal[0],(float)normal[1],(float)normal[2]); + //SCE_PFX_PRINTF("pointA %f %f %f\n",(float)pointA[0],(float)pointA[1],(float)pointA[2]); + //SCE_PFX_PRINTF("pointB %f %f %f\n",(float)pointB[0],(float)pointB[1],(float)pointB[2]); + + if ( centerInside ) { + return -sqrtf( minDistSqr ) - sphereB.m_radius; + } else { + return sqrtf( minDistSqr ) - sphereB.m_radius; + } +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_sphere.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_sphere.h new file mode 100644 index 0000000..24279d1 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_box_sphere.h @@ -0,0 +1,34 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONTACT_BOX_SPHERE_H +#define _SCE_PFX_CONTACT_BOX_SPHERE_H + +#include "../../../include/physics_effects/base_level/base/pfx_common.h" + +namespace sce { +namespace PhysicsEffects { + +PfxFloat pfxContactBoxSphere( + PfxVector3 &normal,PfxPoint3 &pointA,PfxPoint3 &pointB, + void *shapeA,const PfxTransform3 &transformA, + void *shapeB,const PfxTransform3 &transformB, + PfxFloat distanceThreshold = SCE_PFX_FLT_MAX); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_CONTACT_BOXSPHERE_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_cache.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_cache.cpp new file mode 100644 index 0000000..24e945e --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_cache.cpp @@ -0,0 +1,164 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "pfx_contact_cache.h" + +namespace sce { +namespace PhysicsEffects { + +#define SCE_PFX_CONTACT_SAME_POINT 0.01f + +int PfxContactCache::findNearestContactPoint(const PfxPoint3 &newPoint,const PfxVector3 &newNormal) +{ + int nearestIdx = -1; + PfxFloat minDiff = SCE_PFX_CONTACT_SAME_POINT; + for(PfxUInt32 i=0;i 0.99f) { + minDiff = diff; + nearestIdx = i; + } + } + return nearestIdx; +} + +int PfxContactCache::sort4ContactPoints(const PfxPoint3 &newCP,PfxFloat newDistance) +{ + int maxPenetrationIndex = -1; + PfxFloat maxPenetration = newDistance; + + // 最も深い衝突点は排除対象からはずす + for(int i=0;i maxVal) { + maxIndex = 1; + maxVal = res[1]; + } + + if (res[2] > maxVal) { + maxIndex = 2; + maxVal = res[2]; + } + + if (res[3] > maxVal) { + maxIndex = 3; + maxVal = res[3]; + } + + return maxIndex; +} + +void PfxContactCache::addContactPoint( + PfxFloat newDistance, + const PfxVector3 &newNormal, // world coords + const PfxPoint3 &newPointA, // local to the objectA + const PfxPoint3 &newPointB, // local to the objectB + PfxSubData subData) +{ + int id = findNearestContactPoint(newPointA,newNormal); + + if(id < 0 && m_numContacts < SCE_PFX_MAX_CACHED_CONTACT_POINTS) { + // 衝突点を新規追加 + id = m_numContacts++; + m_cachedContactPoints[id].reset(); + } + else if(id < 0){ + // ソート + id = sort4ContactPoints(newPointA,newDistance); + m_cachedContactPoints[id].reset(); + } + + m_cachedContactPoints[id].m_distance = newDistance; + m_cachedContactPoints[id].m_subData = subData; + m_cachedContactPoints[id].m_normal = newNormal; + m_cachedContactPoints[id].m_localPointA = newPointA; + m_cachedContactPoints[id].m_localPointB = newPointB; +} + +void PfxContactCache::addContactPoint(const PfxCachedContactPoint &cp) +{ + PfxPoint3 pA = cp.m_localPointA; + + int id = findNearestContactPoint(pA,cp.m_normal); + + if(id >= 0) { + if(m_cachedContactPoints[id].m_distance > cp.m_distance) { + // 同一点を発見、衝突点情報を更新 + m_cachedContactPoints[id].m_distance = cp.m_distance; + m_cachedContactPoints[id].m_normal = cp.m_normal; + m_cachedContactPoints[id].m_localPointA = cp.m_localPointA; + m_cachedContactPoints[id].m_localPointB = cp.m_localPointB; + } + } + else if(m_numContacts < SCE_PFX_MAX_CACHED_CONTACT_POINTS) { + // 衝突点を新規追加 + m_cachedContactPoints[m_numContacts++] = cp; + } + else { + // ソート + id = sort4ContactPoints(pA,cp.m_distance); + + // コンタクトポイント入れ替え + m_cachedContactPoints[id] = cp; + } +} + +} //namespace PhysicsEffects +} //namespace sce + diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_cache.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_cache.h new file mode 100644 index 0000000..5093b79 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_cache.h @@ -0,0 +1,100 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONTACT_CACHE_H +#define _SCE_PFX_CONTACT_CACHE_H + +#include "../../../include/physics_effects/base_level/base/pfx_common.h" +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "../../../include/physics_effects/base_level/collision/pfx_sub_data.h" + +namespace sce { +namespace PhysicsEffects { + +#define SCE_PFX_MAX_CACHED_CONTACT_POINTS 4 + +/* + 内部の衝突判定に使う軽量なコンタクトキャッシュ +*/ + +/////////////////////////////////////////////////////////////////////////////// +// Contact Point + +struct PfxCachedContactPoint +{ + PfxSubData m_subData; + PfxUInt8 m_shapeIdA; + PfxUInt8 m_shapeIdB; + SCE_PFX_PADDING(1,2) + PfxFloat m_distance; + PfxVector3 m_normal; + PfxPoint3 m_localPointA; + PfxPoint3 m_localPointB; + + void reset() + { + m_shapeIdA = m_shapeIdB = 0; + m_subData = PfxSubData(); + m_distance = SCE_PFX_FLT_MAX; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// Contact Point + +class PfxContactCache +{ +private: + PfxUInt32 m_numContacts; + SCE_PFX_PADDING(1,12) + PfxCachedContactPoint m_cachedContactPoints[SCE_PFX_MAX_CACHED_CONTACT_POINTS]; + + int findNearestContactPoint(const PfxPoint3 &newPoint,const PfxVector3 &newNormal); + int sort4ContactPoints(const PfxPoint3 &newPoint,PfxFloat newDistance); + +public: + PfxContactCache() : m_numContacts(0) {} + + void addContactPoint( + PfxFloat newDistance, + const PfxVector3 &newNormal, // world normal vector + const PfxPoint3 &newPointA, // local contact point to the objectA + const PfxPoint3 &newPointB, // local contact point to the objectB + PfxSubData m_subData); + + void addContactPoint(const PfxCachedContactPoint &cp); + + int getNumContacts() const {return (int)m_numContacts;} + + PfxCachedContactPoint &getContactPoint(int i) {return m_cachedContactPoints[i];} + + const PfxCachedContactPoint &getContactPoint(int i) const {return m_cachedContactPoints[i];} + + PfxFloat getDistance(int i) {return m_cachedContactPoints[i].m_distance;} + + const PfxVector3 &getNormal(int i) const {return m_cachedContactPoints[i].m_normal;} + + const PfxPoint3 &getLocalPointA(int i) const {return m_cachedContactPoints[i].m_localPointA;} + + const PfxPoint3 &getLocalPointB(int i) const {return m_cachedContactPoints[i].m_localPointB;} + + const PfxSubData &getSubData(int i) const {return m_cachedContactPoints[i].m_subData;} +}; + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_CONTACT_CACHE_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_capsule_capsule.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_capsule_capsule.cpp new file mode 100644 index 0000000..e4e07ee --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_capsule_capsule.cpp @@ -0,0 +1,144 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "../../../include/physics_effects/base_level/collision/pfx_capsule.h" +#include "pfx_contact_capsule_capsule.h" + +namespace sce { +namespace PhysicsEffects { + +inline +void +segmentsClosestPoints( + PfxVector3& ptsVector, + PfxVector3& offsetA, + PfxVector3& offsetB, + PfxFloat& tA, PfxFloat& tB, + const PfxVector3 &translation, + const PfxVector3 &dirA, PfxFloat hlenA, + const PfxVector3 &dirB, PfxFloat hlenB ) +{ + // compute the parameters of the closest points on each line segment + + PfxFloat dirA_dot_dirB = dot(dirA,dirB); + PfxFloat dirA_dot_trans = dot(dirA,translation); + PfxFloat dirB_dot_trans = dot(dirB,translation); + + PfxFloat denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB; + + if ( denom == 0.0f ) { + tA = 0.0f; + } else { + tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom; + if ( tA < -hlenA ) + tA = -hlenA; + else if ( tA > hlenA ) + tA = hlenA; + } + + tB = tA * dirA_dot_dirB - dirB_dot_trans; + + if ( tB < -hlenB ) { + tB = -hlenB; + tA = tB * dirA_dot_dirB + dirA_dot_trans; + + if ( tA < -hlenA ) + tA = -hlenA; + else if ( tA > hlenA ) + tA = hlenA; + } else if ( tB > hlenB ) { + tB = hlenB; + tA = tB * dirA_dot_dirB + dirA_dot_trans; + + if ( tA < -hlenA ) + tA = -hlenA; + else if ( tA > hlenA ) + tA = hlenA; + } + + // compute the closest points relative to segment centers. + + offsetA = dirA * tA; + offsetB = dirB * tB; + + ptsVector = translation - offsetA + offsetB; +} + +inline +void +segmentsNormal( PfxVector3& normal, const PfxVector3 &ptsVector ) +{ + // compute the unit direction vector between the closest points. + // with convex objects, you want the unit direction providing the largest gap between the + // objects when they're projected onto it. So, if you have a few candidates covering different + // configurations of the objects, you can compute them all, test the gaps and pick best axis + // based on this. Some directions might be degenerate, and the normalized() function tests for + // degeneracy and returns an arbitrary unit vector in that case. + + PfxVector3 testDir; + + // closest points vector + + normal = pfxSafeNormalize(ptsVector); +} + +PfxFloat pfxContactCapsuleCapsule( + PfxVector3 &normal,PfxPoint3 &pointA,PfxPoint3 &pointB, + void *shapeA,const PfxTransform3 &transformA, + void *shapeB,const PfxTransform3 &transformB, + PfxFloat distanceThreshold) +{ + PfxCapsule &capsuleA = *((PfxCapsule*)shapeA); + PfxCapsule &capsuleB = *((PfxCapsule*)shapeB); + + PfxVector3 directionA = transformA.getUpper3x3().getCol0(); + PfxVector3 translationA = transformA.getTranslation(); + PfxVector3 directionB = transformB.getUpper3x3().getCol0(); + PfxVector3 translationB = transformB.getTranslation(); + + // translation between centers + + PfxVector3 translation = translationB - translationA; + + // compute the closest points of the capsule line segments + + PfxVector3 ptsVector; // the vector between the closest points + PfxVector3 offsetA, offsetB; // offsets from segment centers to their closest points + PfxFloat tA, tB; // parameters on line segment + + segmentsClosestPoints( ptsVector, offsetA, offsetB, tA, tB, translation, + directionA, capsuleA.m_halfLen, directionB, capsuleB.m_halfLen ); + + PfxFloat distance = length(ptsVector) - capsuleA.m_radius - capsuleB.m_radius; + + if ( distance > distanceThreshold ) + return distance; + + // compute the contact normal + + segmentsNormal( normal, ptsVector ); + + // compute points on capsules + + pointA = PfxPoint3( transpose(transformA.getUpper3x3()) * ( offsetA + normal * capsuleA.m_radius ) ); + pointB = PfxPoint3( transpose(transformB.getUpper3x3()) * ( offsetB - normal * capsuleB.m_radius ) ); + + return distance; +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_capsule_capsule.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_capsule_capsule.h new file mode 100644 index 0000000..744e7a0 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_capsule_capsule.h @@ -0,0 +1,34 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONTACT_CAPSULE_CAPSULE_H +#define _SCE_PFX_CONTACT_CAPSULE_CAPSULE_H + +#include "../../../include/physics_effects/base_level/base/pfx_common.h" + +namespace sce { +namespace PhysicsEffects { + +PfxFloat pfxContactCapsuleCapsule( + PfxVector3 &normal,PfxPoint3 &pointA,PfxPoint3 &pointB, + void *shapeA,const PfxTransform3 &transformA, + void *shapeB,const PfxTransform3 &transformB, + PfxFloat distanceThreshold = SCE_PFX_FLT_MAX); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_CONTACT_CAPSULE_CAPSULE_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_capsule_sphere.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_capsule_sphere.cpp new file mode 100644 index 0000000..7102ac0 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_capsule_sphere.cpp @@ -0,0 +1,108 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "../../../include/physics_effects/base_level/collision/pfx_capsule.h" +#include "../../../include/physics_effects/base_level/collision/pfx_sphere.h" +#include "pfx_contact_capsule_sphere.h" + +namespace sce { +namespace PhysicsEffects { + +inline +void +segmentPointClosestPoints( + PfxVector3& ptsVector, + PfxVector3& offsetA, + PfxFloat& tA, + const PfxVector3 &translation, + const PfxVector3 &dirA, PfxFloat hLenA ) +{ + // compute the parameters of the closest points on each line segment + + tA = dot(dirA,translation); + + if ( tA < -hLenA ) + tA = -hLenA; + else if ( tA > hLenA ) + tA = hLenA; + + // compute the closest point on segment relative to its center. + + offsetA = dirA * tA; + ptsVector = translation - offsetA; +} + +inline +void +segmentPointNormal( PfxVector3& normal, const PfxVector3 &ptsVector ) +{ + // compute the unit direction vector between the closest points. + // with convex objects, you want the unit direction providing the largest gap between the + // objects when they're projected onto it. So, if you have a few candidates covering different + // configurations of the objects, you can compute them all, test the gaps and pick best axis + // based on this. Some directions might be degenerate, and the normalized() function tests for + // degeneracy and returns an arbitrary unit vector in that case. + + // closest points vector + + normal = pfxSafeNormalize(ptsVector); +} + +PfxFloat pfxContactCapsuleSphere( + PfxVector3 &normal,PfxPoint3 &pointA,PfxPoint3 &pointB, + void *shapeA,const PfxTransform3 &transformA, + void *shapeB,const PfxTransform3 &transformB, + PfxFloat distanceThreshold) +{ + PfxCapsule &capsuleA = *((PfxCapsule*)shapeA); + PfxSphere &sphereB = *((PfxSphere*)shapeB); + + PfxVector3 directionA = transformA.getUpper3x3().getCol0(); + PfxVector3 translationA = transformA.getTranslation(); + PfxVector3 translationB = transformB.getTranslation(); + + // translation between centers of capsule and sphere + + PfxVector3 translation = translationB - translationA; + + // compute the closest point on the capsule line segment to the sphere center + + PfxVector3 ptsVector; + PfxVector3 offsetA; + PfxFloat tA; + + segmentPointClosestPoints( ptsVector, offsetA, tA, translation, directionA, capsuleA.m_halfLen ); + + PfxFloat distance = length(ptsVector) - capsuleA.m_radius - sphereB.m_radius; + + if ( distance > distanceThreshold ) + return distance; + + // compute the contact normal + + segmentPointNormal( normal, ptsVector ); + + // compute points on capsule and sphere + + pointA = PfxPoint3( transpose(transformA.getUpper3x3()) * ( offsetA + normal * capsuleA.m_radius ) ); + pointB = PfxPoint3( transpose(transformB.getUpper3x3()) * ( -normal * sphereB.m_radius ) ); + + return distance; +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_capsule_sphere.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_capsule_sphere.h new file mode 100644 index 0000000..653a8e4 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_capsule_sphere.h @@ -0,0 +1,34 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONTACT_CAPSULE_SPHERE_H +#define _SCE_PFX_CONTACT_CAPSULE_SPHERE_H + +#include "../../../include/physics_effects/base_level/base/pfx_common.h" + +namespace sce { +namespace PhysicsEffects { + +PfxFloat pfxContactCapsuleSphere( + PfxVector3 &normal,PfxPoint3 &pointA,PfxPoint3 &pointB, + void *shapeA,const PfxTransform3 &transformA, + void *shapeB,const PfxTransform3 &transformB, + PfxFloat distanceThreshold = SCE_PFX_FLT_MAX); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_CONTACT_CAPSULE_SPHERE_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_large_tri_mesh.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_large_tri_mesh.cpp new file mode 100644 index 0000000..764a738 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_large_tri_mesh.cpp @@ -0,0 +1,152 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "pfx_contact_tri_mesh_sphere.h" +#include "pfx_contact_tri_mesh_box.h" +#include "pfx_contact_tri_mesh_capsule.h" +#include "pfx_contact_tri_mesh_cylinder.h" +#include "pfx_contact_tri_mesh_convex.h" +#include "pfx_contact_large_tri_mesh.h" +#include "pfx_intersect_common.h" +#include "pfx_mesh_common.h" + + +namespace sce { +namespace PhysicsEffects { + + +PfxInt32 pfxContactLargeTriMesh( + PfxContactCache &contacts, + const PfxLargeTriMesh *lmeshA, + const PfxTransform3 &transformA, + const PfxShape &shapeB, + const PfxTransform3 &transformB, + PfxFloat distanceThreshold) +{ + PfxTransform3 transformAB; + PfxMatrix3 matrixAB; + PfxVector3 offsetAB; + + // Bローカル→Aローカルへの変換 + transformAB = orthoInverse(transformA) * transformB; + matrixAB = transformAB.getUpper3x3(); + offsetAB = transformAB.getTranslation(); + + // ----------------------------------------------------- + // LargeTriMeshに含まれるTriMeshのAABBと凸体のAABBを判定し、 + // 交差するものを個別に衝突判定する。※LargeMesh座標系 + + PfxVector3 shapeHalf(0.0f); + PfxVector3 shapeCenter = offsetAB; + + + switch(shapeB.getType()) { + case kPfxShapeSphere: + shapeHalf = PfxVector3(shapeB.getSphere().m_radius); + break; + + case kPfxShapeCapsule: + { + PfxCapsule capsule = shapeB.getCapsule(); + shapeHalf = absPerElem(matrixAB) * PfxVector3(capsule.m_halfLen+capsule.m_radius,capsule.m_radius,capsule.m_radius); + } + break; + + case kPfxShapeCylinder: + { + PfxCylinder cylinder = shapeB.getCylinder(); + shapeHalf = absPerElem(matrixAB) * PfxVector3(cylinder.m_halfLen,cylinder.m_radius,cylinder.m_radius); + } + break; + + case kPfxShapeBox: + shapeHalf = absPerElem(matrixAB) * shapeB.getBox().m_half; + break; + + case kPfxShapeConvexMesh: + shapeHalf = absPerElem(matrixAB) * shapeB.getConvexMesh()->m_half; + break; + + default: + break; + } + + // ----------------------------------------------------- + // アイランドとの衝突判定 + + PfxVecInt3 aabbMinL,aabbMaxL; + lmeshA->getLocalPosition((shapeCenter-shapeHalf),(shapeCenter+shapeHalf),aabbMinL,aabbMaxL); + + PfxUInt32 numIslands = lmeshA->m_numIslands; + + { + for(PfxUInt32 i=0;im_aabbList[i]; + if(aabbMaxL.getX() < pfxGetXMin(aabbB) || aabbMinL.getX() > pfxGetXMax(aabbB)) continue; + if(aabbMaxL.getY() < pfxGetYMin(aabbB) || aabbMinL.getY() > pfxGetYMax(aabbB)) continue; + if(aabbMaxL.getZ() < pfxGetZMin(aabbB) || aabbMinL.getZ() > pfxGetZMax(aabbB)) continue; + + PfxTriMesh *island = &lmeshA->m_islands[i]; + + // 衝突判定 + PfxContactCache localContacts; + switch(shapeB.getType()) { + case kPfxShapeSphere: + pfxContactTriMeshSphere(localContacts,island,transformA,shapeB.getSphere(),transformB,distanceThreshold); + break; + + case kPfxShapeCapsule: + pfxContactTriMeshCapsule(localContacts,island,transformA,shapeB.getCapsule(),transformB,distanceThreshold); + break; + + case kPfxShapeBox: + pfxContactTriMeshBox(localContacts,island,transformA,shapeB.getBox(),transformB,distanceThreshold); + break; + + case kPfxShapeCylinder: + pfxContactTriMeshCylinder(localContacts,island,transformA,shapeB.getCylinder(),transformB,distanceThreshold); + break; + + case kPfxShapeConvexMesh: + pfxContactTriMeshConvex(localContacts,island,transformA,*shapeB.getConvexMesh(),transformB,distanceThreshold); + break; + + default: + break; + } + + + // 衝突点を追加 + for(int j=0;j 0.99f) { + minDiff = diff; + nearestIdx = i; + } + } + return nearestIdx; +} + +int PfxContactManifold::sort4ContactPoints(const PfxPoint3 &newCP,PfxFloat newDistance) +{ + int maxPenetrationIndex = -1; + PfxFloat maxPenetration = newDistance; + + // 最も深い衝突点は排除対象からはずす + for(int i=0;i maxVal) { + maxIndex = 1; + maxVal = res[1]; + } + + if (res[2] > maxVal) { + maxIndex = 2; + maxVal = res[2]; + } + + if (res[3] > maxVal) { + maxIndex = 3; + maxVal = res[3]; + } + + return maxIndex; +} + +void PfxContactManifold::addContactPoint( + PfxFloat newDistance, + const PfxVector3 &newNormal, // world coords + const PfxPoint3 &newPointA, // local to the objectA + const PfxPoint3 &newPointB, // local to the objectB + PfxSubData subData) +{ + int id = findNearestContactPoint(newPointA,newNormal); + + if(id < 0 && m_numContacts < SCE_PFX_NUMCONTACTS_PER_BODIES) { + // 衝突点を新規追加 + id = m_numContacts++; + m_contactPoints[id].reset(); + } + else if(id < 0){ + // ソート + id = sort4ContactPoints(newPointA,newDistance); + m_contactPoints[id].reset(); + } + + m_contactPoints[id].m_distance = newDistance; + m_contactPoints[id].m_subData = subData; + pfxStorePoint3(newPointA,m_contactPoints[id].m_localPointA); + pfxStorePoint3(newPointB,m_contactPoints[id].m_localPointB); + pfxStoreVector3(newNormal,m_contactPoints[id].m_constraintRow[0].m_normal); +} + +void PfxContactManifold::addContactPoint(const PfxContactPoint &cp) +{ + PfxPoint3 pA = pfxReadPoint3(cp.m_localPointA); + + int id = findNearestContactPoint(pA,pfxReadVector3(cp.m_constraintRow[0].m_normal)); + + if(id >= 0) { +#if 1 + PfxVector3 nml1(pfxReadVector3(m_contactPoints[id].m_constraintRow[0].m_normal)); + PfxVector3 nml2(pfxReadVector3(cp.m_constraintRow[0].m_normal)); + if(fabsf(dot(nml1,nml2)) > 0.99f ) { + // 同一点を発見、蓄積された情報を継続 + m_contactPoints[id].m_distance = cp.m_distance; + m_contactPoints[id].m_localPointA[0] = cp.m_localPointA[0]; + m_contactPoints[id].m_localPointA[1] = cp.m_localPointA[1]; + m_contactPoints[id].m_localPointA[2] = cp.m_localPointA[2]; + m_contactPoints[id].m_localPointB[0] = cp.m_localPointB[0]; + m_contactPoints[id].m_localPointB[1] = cp.m_localPointB[1]; + m_contactPoints[id].m_localPointB[2] = cp.m_localPointB[2]; + m_contactPoints[id].m_constraintRow[0].m_normal[0] = cp.m_constraintRow[0].m_normal[0]; + m_contactPoints[id].m_constraintRow[0].m_normal[1] = cp.m_constraintRow[0].m_normal[1]; + m_contactPoints[id].m_constraintRow[0].m_normal[2] = cp.m_constraintRow[0].m_normal[2]; + } + else { + // 同一点ではあるが法線が違うため更新 + m_contactPoints[id] = cp; + } +#else + if(m_contactPoints[id].m_distance > cp.m_distance) { + // 同一点を発見、衝突点情報を更新 + m_contactPoints[id].m_distance = cp.m_distance; + m_contactPoints[id].m_localPointA[0] = cp.m_localPointA[0]; + m_contactPoints[id].m_localPointA[1] = cp.m_localPointA[1]; + m_contactPoints[id].m_localPointA[2] = cp.m_localPointA[2]; + m_contactPoints[id].m_localPointB[0] = cp.m_localPointB[0]; + m_contactPoints[id].m_localPointB[1] = cp.m_localPointB[1]; + m_contactPoints[id].m_localPointB[2] = cp.m_localPointB[2]; + m_contactPoints[id].m_constraintRow[0].m_normal[0] = cp.m_constraintRow[0].m_normal[0]; + m_contactPoints[id].m_constraintRow[0].m_normal[1] = cp.m_constraintRow[0].m_normal[1]; + m_contactPoints[id].m_constraintRow[0].m_normal[2] = cp.m_constraintRow[0].m_normal[2]; + } +#endif + } + else if(m_numContacts < SCE_PFX_NUMCONTACTS_PER_BODIES) { + // 衝突点を新規追加 + m_contactPoints[m_numContacts++] = cp; + } + else { + // ソート + id = sort4ContactPoints(pA,cp.m_distance); + + // コンタクトポイント入れ替え + m_contactPoints[id] = cp; + } +} + +void PfxContactManifold::merge(const PfxContactManifold &contact) +{ + SCE_PFX_ALWAYS_ASSERT(m_rigidBodyIdA == contact.getRigidBodyIdA()); + SCE_PFX_ALWAYS_ASSERT(m_rigidBodyIdB == contact.getRigidBodyIdB()); + + for(int i=0;i 0) { + PfxVector3 normal = pfxReadVector3(m_contactPoints[i].m_constraintRow[0].m_normal); + PfxVector3 cpA = pA + rotate(qA,pfxReadVector3(m_contactPoints[i].m_localPointA)); + PfxVector3 cpB = pB + rotate(qB,pfxReadVector3(m_contactPoints[i].m_localPointB)); + + // 貫通深度がプラスに転じたかどうかをチェック + PfxFloat distance = dot(normal,(cpA - cpB)); + if(distance > SCE_PFX_CONTACT_THRESHOLD_NORMAL) { + removeContactPoint(i); + i--; + continue; + } + m_contactPoints[i].m_distance = distance; + + // 深度方向を除去して両点の距離をチェック + cpA = cpA - m_contactPoints[i].m_distance * normal; + PfxFloat distanceAB = lengthSqr(cpA - cpB); + if(distanceAB > SCE_PFX_CONTACT_THRESHOLD_TANGENT) { + removeContactPoint(i); + i--; + continue; + } + } + if(m_contactPoints[i].m_duration < 255) m_contactPoints[i].m_duration++; + } + if(m_numContacts > 0 && m_duration < 65535) m_duration++; +} +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_sphere_sphere.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_sphere_sphere.cpp new file mode 100644 index 0000000..f55f096 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_sphere_sphere.cpp @@ -0,0 +1,76 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/collision/pfx_sphere.h" +#include "pfx_contact_sphere_sphere.h" + +namespace sce { +namespace PhysicsEffects { + +const PfxFloat lenSqrTol = 1.0e-30f; + +PfxFloat pfxContactSphereSphere( + PfxVector3 &normal,PfxPoint3 &pointA,PfxPoint3 &pointB, + void *shapeA,const PfxTransform3 &transformA, + void *shapeB,const PfxTransform3 &transformB, + PfxFloat distanceThreshold) +{ + PfxSphere &sphereA = *((PfxSphere*)shapeA); + PfxSphere &sphereB = *((PfxSphere*)shapeB); + + PfxVector3 direction(0.0f); + + PfxVector3 translationA = transformA.getTranslation(); + PfxVector3 translationB = transformB.getTranslation(); + + // get the offset vector between sphere centers + + PfxVector3 offsetAB; + + offsetAB = translationB - translationA; + + // normalize the offset to compute the direction vector + + PfxFloat distSqr = dot(offsetAB,offsetAB); + PfxFloat dist = sqrtf(distSqr); + PfxFloat sphereDist = dist - sphereA.m_radius - sphereB.m_radius; + + if ( sphereDist > distanceThreshold ) { + return sphereDist; + } + + if ( distSqr > lenSqrTol ) { + PfxFloat distInv = 1.0f / dist; + + direction = offsetAB * distInv; + } else { + direction = PfxVector3(0.0f, 0.0f, 1.0f); + } + + normal = direction; + + // compute the points on the spheres, in world space + + pointA = PfxPoint3( transpose(transformA.getUpper3x3()) * ( direction * sphereA.m_radius ) ); + pointB = PfxPoint3( transpose(transformB.getUpper3x3()) * ( -direction * sphereB.m_radius ) ); + + // return the distance between the spheres + + return sphereDist; +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_sphere_sphere.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_sphere_sphere.h new file mode 100644 index 0000000..03def35 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_sphere_sphere.h @@ -0,0 +1,33 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONTACT_SPHERE_SPHERE_H +#define _SCE_PFX_CONTACT_SPHERE_SPHERE_H + +#include "../../../include/physics_effects/base_level/base/pfx_common.h" +namespace sce { +namespace PhysicsEffects { + +PfxFloat pfxContactSphereSphere( + PfxVector3 &normal,PfxPoint3 &pointA,PfxPoint3 &pointB, + void *shapeA,const PfxTransform3 &transformA, + void *shapeB,const PfxTransform3 &transformB, + PfxFloat distanceThreshold = SCE_PFX_FLT_MAX); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_CONTACT_SPHERE_SPHERE_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_box.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_box.cpp new file mode 100644 index 0000000..199d762 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_box.cpp @@ -0,0 +1,456 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "pfx_contact_tri_mesh_box.h" +#include "pfx_intersect_common.h" +#include "pfx_mesh_common.h" + +namespace sce { +namespace PhysicsEffects { + +static SCE_PFX_FORCE_INLINE +bool checkSAT(const PfxVector3 &axis,PfxFloat AMin,PfxFloat AMax,PfxFloat BMin,PfxFloat BMax,PfxFloat &distMin,PfxVector3 &axisMin) +{ + // ■ 非接触. + + // A: +----+ + // B:+----+ + if(BMax <= AMin) { + return true; + } + + // A:+----+ + // B: +----+ + else if(AMax <= BMin) { + return true; + } + + // ■ 内包 + + //A: +--+ + //B: +------+ + if(BMin < AMin && AMax < BMax) { + PfxFloat d = AMin-BMax; + if(distMin < d) { + distMin = d; + axisMin = axis; + } + } + + //A: +------+ + //B: +--+ + else if(AMin < BMin && BMax < AMax) { + PfxFloat d = AMin-BMax; + if(distMin < d) { + distMin = d; + axisMin = axis; + } + } + + // ■ 接触 + + // A: +----+ + // B:+----+ + else if(BMin < AMin && AMin < BMax) { + PfxFloat d = AMin-BMax; + if(distMin < d) { + distMin = d; + axisMin = axis; + } + } + + // A: +----+ + // B: +----+ + else if(AMin < BMin && BMin < AMax) { + PfxFloat d = BMin-AMax; + if(distMin < d) { + distMin = d; + axisMin = -axis; + } + } + + return false; +} + +static SCE_PFX_FORCE_INLINE +bool pfxContactTriangleBox(PfxContactCache &contacts,PfxUInt32 facetId, + const PfxVector3 &normal,const PfxVector3 &p0,const PfxVector3 &p1,const PfxVector3 &p2, + const PfxFloat thickness,const PfxFloat angle0,const PfxFloat angle1,const PfxFloat angle2, + PfxUInt32 edgeChk, + const PfxVector3 &boxHalf) +{ + const PfxFloat epsilon = 0.00001f; + + // 最も浅い貫通深度とそのときの分離軸 + PfxFloat distMin = -SCE_PFX_FLT_MAX; + PfxVector3 axisMin(0.0f); + + //------------------------------------------- + // 1.分離軸判定 + { + PfxVector3 facetPnts[6] = { + p0,p1,p2,p0-thickness*normal,p1-thickness*normal,p2-thickness*normal + }; + + PfxVector3 sideNml[3] = { + normalize(cross((facetPnts[1] - facetPnts[0]),normal)), + normalize(cross((facetPnts[2] - facetPnts[1]),normal)), + normalize(cross((facetPnts[0] - facetPnts[2]),normal)), + }; + + + // Trianglesの面 -> Box + { + // 分離軸 + const PfxVector3 sepAxis = normal; + + // 分離平面 + PfxPlane planeA(sepAxis,p0); + + // Boxを分離軸に投影して範囲を取得 + PfxFloat r = dot(boxHalf,absPerElem(sepAxis)); + PfxFloat boxOffset = planeA.onPlane(PfxVector3(0.0f)); + PfxFloat boxMax = boxOffset + r; + PfxFloat boxMin = boxOffset - r; + + // 判定 + if(boxMin > 0.0f || boxMax < -thickness) { + return false; + } + + if(distMin < boxMin) { + distMin = boxMin; + axisMin = -sepAxis; + } + } + + // Box -> Triangles + for(int bf=0;bf<3;bf++) { + // 分離軸 + PfxVector3 sepAxis(0.0f); + sepAxis[bf] = 1.0f; + + // 分離軸の方向をチェック + if(dot(normal,sepAxis) > 0.0f) + sepAxis = -sepAxis; + + // Trianglesを分離軸に投影して範囲を取得 + PfxFloat triMin,triMax; + pfxGetProjAxisPnts6(facetPnts,sepAxis,triMin,triMax); + + // Boxを分離軸に投影して範囲を取得 + PfxFloat boxMin = -boxHalf[bf]; + PfxFloat boxMax = boxHalf[bf]; + + if(checkSAT(sepAxis,triMin,triMax,boxMin,boxMax,distMin,axisMin)) { + return false; + } + } + + // エッジ Triangles面のエッジ(x3)×Boxのエッジ(x3) + for(int e=0;e<3;e++) { + PfxVector3 dir = normalize(facetPnts[(e+1)%3] - facetPnts[e]); + + for(int i=0;i<3;i++) { + PfxVector3 boxEdge(0.0f); + boxEdge[i] = 1.0f; + + // エッジが平行であれば判定しない + if(pfxIsSameDirection(dir,boxEdge)) continue; + + PfxVector3 sepAxis = normalize(cross(dir,boxEdge)); + + // 分離軸の方向をチェック + if(dot(normal,sepAxis) > 0.0f) + sepAxis = -sepAxis; + + // Trianglesを分離軸に投影して範囲を取得 + PfxFloat triMin,triMax; + pfxGetProjAxisPnts6(facetPnts,sepAxis,triMin,triMax); + + // Boxを分離軸に投影して範囲を取得 + PfxFloat r = dot(boxHalf,absPerElem(sepAxis)); + PfxFloat boxMin = -r; + PfxFloat boxMax = r; + + if(checkSAT(sepAxis,triMin,triMax,boxMin,boxMax,distMin,axisMin)) { + return false; + } + } + } + + // 面に厚みがある場合の補助的な判定(交差するかしないかだけを判定) + if(thickness > 0.0f) { + // 厚み側面の法線 + for(int i=0;i<3;i++) { + // 分離平面 + PfxPlane planeA(sideNml[i],facetPnts[i]); + + // Boxを分離軸に投影して範囲を取得 + PfxFloat r = dot(boxHalf,absPerElem(sideNml[i])); + PfxFloat boxOffset = planeA.onPlane(PfxVector3(0.0f)); + PfxFloat boxMin = boxOffset - r; + + if(boxMin > 0.0f) { + return false; + } + } + + // 2つの厚み側面のなすエッジ3×ボックスのエッジ3 + for(int e=0;e<3;e++) { + PfxVector3 edgeVec = normalize(cross(sideNml[(e+1)%3],sideNml[e])); + + for(int i=0;i<3;i++) { + PfxVector3 boxEdge(0.0f); + boxEdge[i] = 1.0f; + + // エッジが平行であれば判定しない + if(pfxIsSameDirection(edgeVec,boxEdge)) continue; + + PfxVector3 sepAxis = normalize(cross(edgeVec,boxEdge)); + + // Trianglesを分離軸に投影して範囲を取得 + PfxFloat triMin,triMax; + pfxGetProjAxisPnts3(facetPnts,sepAxis,triMin,triMax); + + // Boxを分離軸に投影して範囲を取得 + PfxFloat r = dot(boxHalf,absPerElem(sepAxis)); + PfxFloat boxMin = -r; + PfxFloat boxMax = r; + + if(triMax < boxMin || boxMax < triMin) { + return false; + } + } + } + } + } + + //------------------------------------------- + // 2.衝突点の探索 + { + // 分離軸方向に引き離す(最近接を判定するため、交差回避させる) + PfxVector3 sepAxis = 1.1f * fabsf(distMin) * axisMin; + + const PfxVector3 facetPnts[3] = { + p0 + sepAxis, + p1 + sepAxis, + p2 + sepAxis, + }; + + const PfxVector3 boxPnts[8] = { + mulPerElem(PfxVector3(-1.0f,-1.0f,-1.0f),boxHalf), + mulPerElem(PfxVector3(-1.0f,-1.0f, 1.0f),boxHalf), + mulPerElem(PfxVector3( 1.0f,-1.0f, 1.0f),boxHalf), + mulPerElem(PfxVector3( 1.0f,-1.0f,-1.0f),boxHalf), + mulPerElem(PfxVector3(-1.0f, 1.0f,-1.0f),boxHalf), + mulPerElem(PfxVector3(-1.0f, 1.0f, 1.0f),boxHalf), + mulPerElem(PfxVector3( 1.0f, 1.0f, 1.0f),boxHalf), + mulPerElem(PfxVector3( 1.0f, 1.0f,-1.0f),boxHalf), + }; + + //-------------------------------------------------------------------- + // 衝突点の探索 + + PfxClosestPoints cp; + PfxVector3 sA,sB; + + // エッジ間の最短距離と座標値を算出 + { + const int boxIds[] = { + 0,1, + 1,2, + 2,3, + 3,0, + 4,5, + 5,6, + 6,7, + 7,4, + 0,4, + 3,7, + 2,6, + 1,5, + }; + + for(int i=0;i<3;i++) { + for(int j=0;j<12;j++) { + pfxClosestTwoLines(facetPnts[i],facetPnts[(i+1)%3],boxPnts[boxIds[j*2]],boxPnts[boxIds[j*2+1]],sA,sB); + cp.add(PfxPoint3(sA),PfxPoint3(sB),lengthSqr(sA-sB)); + } + } + } + + // Triangleの頂点 -> Boxの面 + { +#ifdef SCE_PFX_USE_GEOMETRY + PfxFloatInVec sqrDist; + PfxGeomAabb aabb(PfxPoint3(0.0f),boxHalf); + { + PfxPoint3 closestPoint = sce::Geometry::Aos::closestPoint(PfxPoint3(facetPnts[0]),aabb,&sqrDist); + cp.add(PfxPoint3(facetPnts[0]),closestPoint,sqrDist); + } + { + PfxPoint3 closestPoint = sce::Geometry::Aos::closestPoint(PfxPoint3(facetPnts[1]),aabb,&sqrDist); + cp.add(PfxPoint3(facetPnts[1]),closestPoint,sqrDist); + } + { + PfxPoint3 closestPoint = sce::Geometry::Aos::closestPoint(PfxPoint3(facetPnts[2]),aabb,&sqrDist); + cp.add(PfxPoint3(facetPnts[2]),closestPoint,sqrDist); + } +#else + pfxClosestPointAABB(facetPnts[0],boxHalf,sB); + cp.add(PfxPoint3(facetPnts[0]),PfxPoint3(sB),lengthSqr(sB-facetPnts[0])); + + pfxClosestPointAABB(facetPnts[1],boxHalf,sB); + cp.add(PfxPoint3(facetPnts[1]),PfxPoint3(sB),lengthSqr(sB-facetPnts[1])); + + pfxClosestPointAABB(facetPnts[2],boxHalf,sB); + cp.add(PfxPoint3(facetPnts[2]),PfxPoint3(sB),lengthSqr(sB-facetPnts[2])); +#endif + } + + // Boxの頂点 -> Trianglesの面 + PfxTriangle triangleA(facetPnts[0],facetPnts[1],facetPnts[2]); + for(int i=0;i<8;i++) { + pfxClosestPointTriangle(boxPnts[i],triangleA,sA); + cp.add(PfxPoint3(sA),PfxPoint3(boxPnts[i]),lengthSqr(sA-boxPnts[i])); + } + + for(int i=0;im_facets[selFacets[f]]; + + PfxVector3 facetNormal = matrixBA * pfxReadVector3(facet.m_normal); + + PfxVector3 facetPntsA[3] = { + offsetBA + matrixBA * meshA->m_verts[facet.m_vertIds[0]], + offsetBA + matrixBA * meshA->m_verts[facet.m_vertIds[1]], + offsetBA + matrixBA * meshA->m_verts[facet.m_vertIds[2]], + }; + + const PfxEdge *edge[3] = { + &meshA->m_edges[facet.m_edgeIds[0]], + &meshA->m_edges[facet.m_edgeIds[1]], + &meshA->m_edges[facet.m_edgeIds[2]], + }; + + PfxUInt32 edgeChk = + ((edge[0]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x01) | + ((edge[1]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x02) | + ((edge[2]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x04); + + pfxContactTriangleBox(localContacts,selFacets[f], + facetNormal,facetPntsA[0],facetPntsA[1],facetPntsA[2], + facet.m_thickness, + 0.5f*SCE_PFX_PI*(edge[0]->m_tilt/255.0f), + 0.5f*SCE_PFX_PI*(edge[1]->m_tilt/255.0f), + 0.5f*SCE_PFX_PI*(edge[2]->m_tilt/255.0f), + edgeChk,boxB.m_half); + } + + for(int i=0;im_facets[subData.getFacetId()]; + + PfxTriangle triangleA( + meshA->m_verts[facet.m_vertIds[0]], + meshA->m_verts[facet.m_vertIds[1]], + meshA->m_verts[facet.m_vertIds[2]]); + + PfxFloat s=0.0f,t=0.0f; + pfxGetLocalCoords(PfxVector3(localContacts.getLocalPointA(i)),triangleA,s,t); + subData.m_type = PfxSubData::MESH_INFO; + subData.setFacetLocalS(s); + subData.setFacetLocalT(t); + + contacts.addContactPoint( + localContacts.getDistance(i), + transformB.getUpper3x3() * localContacts.getNormal(i), + transformAB * localContacts.getLocalPointA(i), + localContacts.getLocalPointB(i), + subData); + } + + return contacts.getNumContacts(); +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_box.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_box.h new file mode 100644 index 0000000..60584b4 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_box.h @@ -0,0 +1,38 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONTACT_TRI_MESH_BOX_H +#define _SCE_PFX_CONTACT_TRI_MESH_BOX_H + +#include "../../../include/physics_effects/base_level/collision/pfx_tri_mesh.h" +#include "../../../include/physics_effects/base_level/collision/pfx_box.h" +#include "pfx_contact_cache.h" + +namespace sce { +namespace PhysicsEffects { + +PfxInt32 pfxContactTriMeshBox( + PfxContactCache &contacts, + const PfxTriMesh *meshA, + const PfxTransform3 &transformA, + const PfxBox &boxB, + const PfxTransform3 &transformB, + PfxFloat distanceThreshold = SCE_PFX_FLT_MAX ); + +} // namespace PhysicsEffects +} // namespace sce + +#endif // _SCE_PFX_CONTACT_TRI_MESH_BOX_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_capsule.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_capsule.cpp new file mode 100644 index 0000000..e5fcb50 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_capsule.cpp @@ -0,0 +1,570 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "pfx_contact_tri_mesh_capsule.h" +#include "pfx_intersect_common.h" +#include "pfx_mesh_common.h" + +namespace sce { +namespace PhysicsEffects { + +// 分離軸が見つかった場合はすぐに処理を抜けるため最短距離が返されるわけではないことに注意 + +/* + ○ カプセル分離軸(x19) + 面法線 + カプセル軸 x エッジ0 + カプセル軸 x エッジ1 + カプセル軸 x エッジ2 + ((カプセル点0-面点0) x エッジ0) x エッジ0 + ((カプセル点0-面点1) x エッジ1) x エッジ1 + ((カプセル点0-面点2) x エッジ2) x エッジ2 + ((カプセル点1-面点0) x エッジ0) x エッジ0 + ((カプセル点1-面点1) x エッジ1) x エッジ1 + ((カプセル点1-面点2) x エッジ2) x エッジ2 + ((面点0-カプセル点0) x カプセル軸) x カプセル軸 + ((面点1-カプセル点0) x カプセル軸) x カプセル軸 + ((面点2-カプセル点0) x カプセル軸) x カプセル軸 + 面点0-カプセル点0 + 面点1-カプセル点0 + 面点2-カプセル点0 + 面点0-カプセル点1 + 面点1-カプセル点1 + 面点2-カプセル点1 + */ + +static SCE_PFX_FORCE_INLINE +bool checkSAT(const PfxVector3 &axis,PfxFloat AMin,PfxFloat AMax,PfxFloat BMin,PfxFloat BMax,PfxFloat &distMin,PfxVector3 &axisMin) +{ + // ■ 非接触. + + // A: +----+ + // B:+----+ + if(BMax <= AMin) { + return true; + } + + // A:+----+ + // B: +----+ + else if(AMax <= BMin) { + return true; + } + + // ■ 内包 + + //A: +--+ + //B: +------+ + if(BMin < AMin && AMax < BMax) { + PfxFloat d = AMin-BMax; + if(distMin < d) { + distMin = d; + axisMin = axis; + } + } + + //A: +------+ + //B: +--+ + else if(AMin < BMin && BMax < AMax) { + PfxFloat d = AMin-BMax; + if(distMin < d) { + distMin = d; + axisMin = axis; + } + } + + // ■ 接触 + + // A: +----+ + // B:+----+ + else if(BMin < AMin && AMin < BMax) { + PfxFloat d = AMin-BMax; + if(distMin < d) { + distMin = d; + axisMin = axis; + } + } + + // A: +----+ + // B: +----+ + else if(AMin < BMin && BMin < AMax) { + PfxFloat d = BMin-AMax; + if(distMin < d) { + distMin = d; + axisMin = -axis; + } + } + + return false; +} + +static SCE_PFX_FORCE_INLINE +bool pfxContactTriangleCapsule(PfxContactCache &contacts,PfxUInt32 facetId, + const PfxVector3 &normal,const PfxVector3 &p0,const PfxVector3 &p1,const PfxVector3 &p2, + const PfxFloat thickness,const PfxFloat angle0,const PfxFloat angle1,const PfxFloat angle2, + PfxUInt32 edgeChk, + PfxFloat capsuleRadius,const PfxVector3 &capP0,const PfxVector3 &capP1) +{ + const PfxFloat epsilon = 0.00001f; + + // 最も浅い貫通深度とそのときの分離軸 + PfxFloat distMin = -SCE_PFX_FLT_MAX; + PfxVector3 axisMin(0.0f); + + //------------------------------------------- + // 1.分離軸判定 + { + PfxVector3 facetPnts[6] = { + p0,p1,p2,p0-thickness*normal,p1-thickness*normal,p2-thickness*normal + }; + + PfxVector3 sideNml[3] = { + normalize(cross((facetPnts[1] - facetPnts[0]),normal)), + normalize(cross((facetPnts[2] - facetPnts[1]),normal)), + normalize(cross((facetPnts[0] - facetPnts[2]),normal)), + }; + + + const PfxVector3 capPnts[2] = { + capP0,capP1 + }; + + { + const PfxVector3 &sepAxis = normal; + + // 分離平面 + PfxPlane plane(sepAxis,facetPnts[0]); + + // Capsule(B)を分離軸に投影して範囲を取得 + PfxFloat test1,test2,BMin,BMax; + test1 = plane.onPlane(capP0); + test2 = plane.onPlane(capP1); + BMax = SCE_PFX_MAX(test1,test2) + capsuleRadius; + BMin = SCE_PFX_MIN(test1,test2) - capsuleRadius; + + // 判定 + if(BMin > 0.0f || BMax < -thickness) { + return false; + } + + if(distMin < BMin) { + distMin = BMin; + axisMin = -sepAxis; + } + } + + //------------------------------------------- + // カプセル軸 x 面エッジ0,1,2 + // ※Triangles座標系 (Aローカル) + + { + for(int e=0;e<3;e++) { + PfxVector3 sepAxis = cross(capP1-capP0,facetPnts[(e+1)%3]-facetPnts[e]); + PfxFloat l=length(sepAxis); + if(l < 0.00001f) continue; + sepAxis /= l; + + if(dot(normal,sepAxis) > 0.0f) + sepAxis = -sepAxis; + + // Triangleを分離軸に投影 + PfxFloat AMin=SCE_PFX_FLT_MAX,AMax=-SCE_PFX_FLT_MAX; + pfxGetProjAxisPnts6(facetPnts,sepAxis,AMin,AMax); + + // カプセルを分離軸に投影 + PfxFloat BMin=SCE_PFX_FLT_MAX,BMax=-SCE_PFX_FLT_MAX; + pfxGetProjAxisPnts2(capPnts,sepAxis,BMin,BMax); + BMin -= capsuleRadius; + BMax += capsuleRadius; + + if(checkSAT(sepAxis,AMin,AMax,BMin,BMax,distMin,axisMin)) { + return false; + } + } + } + + //------------------------------------------- + // ((カプセル点0-面点0,1,2) x エッジ0,1,2) x エッジ0,1,2 + // ※Triangles座標系 (Aローカル) + + { + for(int e=0;e<3;e++) { + PfxVector3 edge = facetPnts[(e+1)%3]-facetPnts[e]; + PfxVector3 sepAxis = normalize(cross(cross(capP0-facetPnts[e],edge),edge)); + + if(dot(normal,sepAxis) > 0.0f) + sepAxis = -sepAxis; + + // Triangleを分離軸に投影 + PfxFloat AMin=SCE_PFX_FLT_MAX,AMax=-SCE_PFX_FLT_MAX; + pfxGetProjAxisPnts6(facetPnts,sepAxis,AMin,AMax); + + // カプセルを分離軸に投影 + PfxFloat BMin=SCE_PFX_FLT_MAX,BMax=-SCE_PFX_FLT_MAX; + pfxGetProjAxisPnts2(capPnts,sepAxis,BMin,BMax); + BMin -= capsuleRadius; + BMax += capsuleRadius; + + if(checkSAT(sepAxis,AMin,AMax,BMin,BMax,distMin,axisMin)) { + return false; + } + } + } + + //------------------------------------------- + // ((カプセル点1-面点0,1,2) x エッジ0,1,2) x エッジ0,1,2 + // ※Triangles座標系 (Aローカル) + + { + for(int e=0;e<3;e++) { + PfxVector3 edge = facetPnts[(e+1)%3]-facetPnts[e]; + PfxVector3 sepAxis = normalize(cross(cross(capP1-facetPnts[e],edge),edge)); + + if(dot(normal,sepAxis) > 0.0f) + sepAxis = -sepAxis; + + // Triangleを分離軸に投影 + PfxFloat AMin=SCE_PFX_FLT_MAX,AMax=-SCE_PFX_FLT_MAX; + pfxGetProjAxisPnts6(facetPnts,sepAxis,AMin,AMax); + + // カプセルを分離軸に投影 + PfxFloat BMin=SCE_PFX_FLT_MAX,BMax=-SCE_PFX_FLT_MAX; + pfxGetProjAxisPnts2(capPnts,sepAxis,BMin,BMax); + BMin -= capsuleRadius; + BMax += capsuleRadius; + + if(checkSAT(sepAxis,AMin,AMax,BMin,BMax,distMin,axisMin)) { + return false; + } + } + } + + //------------------------------------------- + // ((面点0,1,2-カプセル点0) x カプセル軸) x カプセル軸 + // ※Triangles座標系 (Aローカル) + + { + for(int e=0;e<3;e++) { + PfxVector3 capdir = capP1-capP0; + PfxVector3 sepAxis = cross(cross(facetPnts[e]-capP0,capdir),capdir); + PfxFloat l=length(sepAxis); + if(l < 0.00001f) continue; + sepAxis /= l; + + if(dot(normal,sepAxis) > 0.0f) + sepAxis = -sepAxis; + + // Triangleを分離軸に投影 + PfxFloat AMin=SCE_PFX_FLT_MAX,AMax=-SCE_PFX_FLT_MAX; + pfxGetProjAxisPnts6(facetPnts,sepAxis,AMin,AMax); + + // カプセルを分離軸に投影 + PfxFloat BMin=SCE_PFX_FLT_MAX,BMax=-SCE_PFX_FLT_MAX; + pfxGetProjAxisPnts2(capPnts,sepAxis,BMin,BMax); + BMin -= capsuleRadius; + BMax += capsuleRadius; + + if(checkSAT(sepAxis,AMin,AMax,BMin,BMax,distMin,axisMin)) { + return false; + } + } + } + + //------------------------------------------- + // 面点0,1,2-カプセル点0 + // ※Triangles座標系 (Aローカル) + + { + for(int e=0;e<3;e++) { + PfxVector3 sepAxis = normalize(facetPnts[e]-capP0); + + // Triangleを分離軸に投影 + PfxFloat AMin=SCE_PFX_FLT_MAX,AMax=-SCE_PFX_FLT_MAX; + pfxGetProjAxisPnts6(facetPnts,sepAxis,AMin,AMax); + + // カプセルを分離軸に投影 + PfxFloat BMin=SCE_PFX_FLT_MAX,BMax=-SCE_PFX_FLT_MAX; + pfxGetProjAxisPnts2(capPnts,sepAxis,BMin,BMax); + BMin -= capsuleRadius; + BMax += capsuleRadius; + + if(checkSAT(sepAxis,AMin,AMax,BMin,BMax,distMin,axisMin)) { + return false; + } + } + } + + //------------------------------------------- + // 面点0,1,2-カプセル点1 + // ※Triangles座標系 (Aローカル) + + { + for(int e=0;e<3;e++) { + PfxVector3 sepAxis = normalize(facetPnts[e]-capP1); + + // Triangleを分離軸に投影 + PfxFloat AMin=SCE_PFX_FLT_MAX,AMax=-SCE_PFX_FLT_MAX; + pfxGetProjAxisPnts6(facetPnts,sepAxis,AMin,AMax); + + // カプセルを分離軸に投影 + PfxFloat BMin=SCE_PFX_FLT_MAX,BMax=-SCE_PFX_FLT_MAX; + pfxGetProjAxisPnts2(capPnts,sepAxis,BMin,BMax); + BMin -= capsuleRadius; + BMax += capsuleRadius; + + if(checkSAT(sepAxis,AMin,AMax,BMin,BMax,distMin,axisMin)) { + return false; + } + } + } + + // 面に厚みがある場合の補助的な判定(面法線 x カプセル軸) + // 交差するかしないかだけを判定 + if(thickness > 0.0f) { + // 厚み側面の法線 + for(int i=0;i<3;i++) { + // 分離平面 + PfxPlane plane(sideNml[i],facetPnts[i]); + + // カプセルを分離軸に投影して範囲を取得 + PfxFloat test1,test2,BMin; + test1 = plane.onPlane(capP0); + test2 = plane.onPlane(capP1); + BMin = SCE_PFX_MIN(test1,test2) - capsuleRadius; + + if(BMin > 0.0f) { + return false; + } + } + + // 2つの厚み側面のなすエッジ3×カプセル軸 + for(int e=0;e<3;e++) { + PfxVector3 edgeVec = normalize(cross(sideNml[(e+1)%3],sideNml[e])); + PfxVector3 capVec = capP1-capP0; + + // エッジが平行であれば判定しない + if(pfxIsSameDirection(edgeVec,capVec)) continue; + + PfxVector3 sepAxis = normalize(cross(edgeVec,capVec)); + + // Trianglesを分離軸に投影して範囲を取得 + PfxFloat triMin,triMax; + pfxGetProjAxisPnts3(facetPnts,sepAxis,triMin,triMax); + + // カプセルを分離軸に投影して範囲を取得 + PfxFloat BMin=SCE_PFX_FLT_MAX,BMax=-SCE_PFX_FLT_MAX; + pfxGetProjAxisPnts2(capPnts,sepAxis,BMin,BMax); + BMin -= capsuleRadius; + BMax += capsuleRadius; + + if(triMax < BMin || BMax < triMin) { + return false; + } + } + } + } + + //------------------------------------------- + // 2.衝突点の探索 + + { + // 分離軸方向に引き離す(最近接を判定するため、交差回避させる) + PfxVector3 sepAxis = 1.1f * fabsf(distMin) * axisMin; + + const PfxVector3 facetPnts[3] = { + p0 + sepAxis, + p1 + sepAxis, + p2 + sepAxis, + }; + + //-------------------------------------------------------------------- + // 衝突点の探索 + + PfxClosestPoints cp; + PfxVector3 sA,sB; + + //-------------------------------------------------------------------- + //Triangleの頂点 -> Capsule + + // カプセルの線分と面のエッジx3の最近接点の算出 +#ifdef SCE_PFX_USE_GEOMETRY + PfxGeomSegment segmentC((PfxPoint3)capP0,(PfxPoint3)capP1); + + { + PfxGeomSegment segmentF((PfxPoint3)facetPnts[0],(PfxPoint3)facetPnts[1]); + PfxPoint3 closestPointA,closestPointB; + PfxFloatInVec sqrDist = closestPoints(segmentC,segmentF,closestPointB,closestPointA); + cp.add(closestPointA,closestPointB + normalize(closestPointA-closestPointB)*capsuleRadius,sqrDist); + } + { + PfxGeomSegment segmentF((PfxPoint3)facetPnts[1],(PfxPoint3)facetPnts[2]); + PfxPoint3 closestPointA,closestPointB; + PfxFloatInVec sqrDist = closestPoints(segmentC,segmentF,closestPointB,closestPointA); + cp.add(closestPointA,closestPointB + normalize(closestPointA-closestPointB)*capsuleRadius,sqrDist); + } + { + PfxGeomSegment segmentF((PfxPoint3)facetPnts[2],(PfxPoint3)facetPnts[0]); + PfxPoint3 closestPointA,closestPointB; + PfxFloatInVec sqrDist = closestPoints(segmentC,segmentF,closestPointB,closestPointA); + cp.add(closestPointA,closestPointB + normalize(closestPointA-closestPointB)*capsuleRadius,sqrDist); + } +#else + pfxClosestTwoLines(capP0,capP1,facetPnts[0],facetPnts[1],sB,sA); + cp.add(PfxPoint3(sA),PfxPoint3(sB + normalize(sA-sB)*capsuleRadius),lengthSqr(sA-sB)); + + pfxClosestTwoLines(capP0,capP1,facetPnts[1],facetPnts[2],sB,sA); + cp.add(PfxPoint3(sA),PfxPoint3(sB + normalize(sA-sB)*capsuleRadius),lengthSqr(sA-sB)); + + pfxClosestTwoLines(capP0,capP1,facetPnts[2],facetPnts[0],sB,sA); + cp.add(PfxPoint3(sA),PfxPoint3(sB + normalize(sA-sB)*capsuleRadius),lengthSqr(sA-sB)); +#endif + + // カプセルの端点と面の最近接点の算出 + PfxTriangle triangleA(facetPnts[0],facetPnts[1],facetPnts[2]); + pfxClosestPointTriangle(capP0,triangleA,sA); + cp.add(PfxPoint3(sA),PfxPoint3(capP0+normalize(sA-capP0)*capsuleRadius),lengthSqr(sA-capP0)); + + pfxClosestPointTriangle(capP1,triangleA,sA); + cp.add(PfxPoint3(sA),PfxPoint3(capP1+normalize(sA-capP1)*capsuleRadius),lengthSqr(sA-capP1)); + + for(int i=0;im_facets[selFacets[f]]; + + PfxVector3 facetNormal = matrixBA * pfxReadVector3(facet.m_normal); + + PfxVector3 facetPntsA[3] = { + offsetBA + matrixBA * meshA->m_verts[facet.m_vertIds[0]], + offsetBA + matrixBA * meshA->m_verts[facet.m_vertIds[1]], + offsetBA + matrixBA * meshA->m_verts[facet.m_vertIds[2]], + }; + + const PfxEdge *edge[3] = { + &meshA->m_edges[facet.m_edgeIds[0]], + &meshA->m_edges[facet.m_edgeIds[1]], + &meshA->m_edges[facet.m_edgeIds[2]], + }; + + PfxUInt32 edgeChk = + ((edge[0]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x01) | + ((edge[1]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x02) | + ((edge[2]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x04); + + pfxContactTriangleCapsule(localContacts,selFacets[f], + facetNormal,facetPntsA[0],facetPntsA[1],facetPntsA[2], + facet.m_thickness, + 0.5f*SCE_PFX_PI*(edge[0]->m_tilt/255.0f), + 0.5f*SCE_PFX_PI*(edge[1]->m_tilt/255.0f), + 0.5f*SCE_PFX_PI*(edge[2]->m_tilt/255.0f), + edgeChk,capsuleB.m_radius,vCapAB[0],vCapAB[1]); + } + + for(int i=0;im_facets[subData.getFacetId()]; + + PfxTriangle triangleA( + meshA->m_verts[facet.m_vertIds[0]], + meshA->m_verts[facet.m_vertIds[1]], + meshA->m_verts[facet.m_vertIds[2]]); + + PfxFloat s=0.0f,t=0.0f; + pfxGetLocalCoords(PfxVector3(localContacts.getLocalPointA(i)),triangleA,s,t); + subData.m_type = PfxSubData::MESH_INFO; + subData.setFacetLocalS(s); + subData.setFacetLocalT(t); + + contacts.addContactPoint( + localContacts.getDistance(i), + transformB.getUpper3x3() * localContacts.getNormal(i), + transformAB * localContacts.getLocalPointA(i), + localContacts.getLocalPointB(i), + subData); + } + + return contacts.getNumContacts(); +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_capsule.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_capsule.h new file mode 100644 index 0000000..9e392ff --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_capsule.h @@ -0,0 +1,39 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONTACT_TRI_MESH_CAPSULE_H +#define _SCE_PFX_CONTACT_TRI_MESH_CAPSULE_H + +#include "../../../include/physics_effects/base_level/collision/pfx_tri_mesh.h" +#include "../../../include/physics_effects/base_level/collision/pfx_capsule.h" +#include "pfx_contact_cache.h" + +namespace sce { +namespace PhysicsEffects { + +PfxInt32 pfxContactTriMeshCapsule( + PfxContactCache &contacts, + const PfxTriMesh *meshA, + const PfxTransform3 &transformA, + const PfxCapsule &capsuleB, + const PfxTransform3 &transformB, + PfxFloat distanceThreshold = SCE_PFX_FLT_MAX ); + + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_CONTACT_TRI_MESH_CAPSULE_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_convex.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_convex.cpp new file mode 100644 index 0000000..545186f --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_convex.cpp @@ -0,0 +1,167 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "pfx_contact_tri_mesh_convex.h" +#include "pfx_intersect_common.h" +#include "pfx_mesh_common.h" +#include "pfx_gjk_solver.h" +#include "pfx_gjk_support_func.h" + +namespace sce { +namespace PhysicsEffects { + + +static SCE_PFX_FORCE_INLINE +bool pfxContactTriangleConvex(PfxContactCache &contacts,PfxUInt32 facetId, + const PfxVector3 &normal,const PfxVector3 &p0,const PfxVector3 &p1,const PfxVector3 &p2, + const PfxFloat thickness,const PfxFloat angle0,const PfxFloat angle1,const PfxFloat angle2, + PfxUInt32 edgeChk, + const PfxConvexMesh &convex) +{ + PfxVector3 facetPnts[6] = { + p0,p1,p2,p0-thickness*normal,p1-thickness*normal,p2-thickness*normal + }; + + + PfxPoint3 pA(0.0f),pB(0.0f); + PfxVector3 nml(0.0f); + PfxGjkSolver gjk; + + gjk.setup((void*)facetPnts,(void*)&convex,pfxGetSupportVertexTriangleWithThickness,pfxGetSupportVertexConvex); + PfxFloat d = gjk.collide(nml,pA,pB,PfxTransform3::identity(),PfxTransform3::identity(),SCE_PFX_FLT_MAX); + if(d >= 0.0f) return false; + + PfxVector3 pointsOnTriangle = PfxVector3(pA); + PfxVector3 pointsOnConvex = PfxVector3(pB); + PfxVector3 axis = nml; + + // 面上の最近接点が凸エッジ上でない場合は法線を変える + if( ((edgeChk&0x01)&&pfxPointOnLine(pointsOnTriangle,p0,p1)) || + ((edgeChk&0x02)&&pfxPointOnLine(pointsOnTriangle,p1,p2)) || + ((edgeChk&0x04)&&pfxPointOnLine(pointsOnTriangle,p2,p0)) ) { + axis=-normal; + } + + PfxSubData subData; + subData.setFacetId(facetId); + contacts.addContactPoint(-length(pointsOnTriangle-pointsOnConvex),axis,pA,pB,subData); + + return true; +} + +PfxInt32 pfxContactTriMeshConvex( + PfxContactCache &contacts, + const PfxTriMesh *meshA, + const PfxTransform3 &transformA, + const PfxConvexMesh &convexB, + const PfxTransform3 &transformB, + PfxFloat distanceThreshold) +{ + (void) distanceThreshold; + + PfxTransform3 transformAB, transformBA; + PfxMatrix3 matrixBA; + PfxVector3 offsetBA; + + // Bローカル→Aローカルへの変換. + transformAB = orthoInverse(transformA) * transformB; + + // Aローカル→Bローカルへの変換. + transformBA = orthoInverse(transformAB); + + matrixBA = transformBA.getUpper3x3(); + offsetBA = transformBA.getTranslation(); + + //------------------------------------------- + // 判定する面を絞り込む. + + PfxUInt8 SCE_PFX_ALIGNED(16) selFacets[SCE_PFX_NUMMESHFACETS] = { 0 }; + PfxUInt32 numSelFacets = 0; + + // ※convexB座標系 + PfxVector3 aabbB(convexB.m_half); + numSelFacets = pfxGatherFacets(meshA,(PfxFloat*)&aabbB,offsetBA,matrixBA,selFacets); + + if(numSelFacets == 0) { + return 0; + } + + //------------------------------------------- + // 面ごとに衝突を検出 + + PfxContactCache localContacts; + + for(PfxUInt32 f = 0; f < numSelFacets; f++) { + const PfxFacet &facet = meshA->m_facets[selFacets[f]]; + + PfxVector3 facetNormal = matrixBA * pfxReadVector3(facet.m_normal); + + PfxVector3 facetPntsA[3] = { + offsetBA + matrixBA * meshA->m_verts[facet.m_vertIds[0]], + offsetBA + matrixBA * meshA->m_verts[facet.m_vertIds[1]], + offsetBA + matrixBA * meshA->m_verts[facet.m_vertIds[2]], + }; + + const PfxEdge *edge[3] = { + &meshA->m_edges[facet.m_edgeIds[0]], + &meshA->m_edges[facet.m_edgeIds[1]], + &meshA->m_edges[facet.m_edgeIds[2]], + }; + + PfxUInt32 edgeChk = + ((edge[0]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x01) | + ((edge[1]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x02) | + ((edge[2]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x04); + + pfxContactTriangleConvex(localContacts,selFacets[f], + facetNormal,facetPntsA[0],facetPntsA[1],facetPntsA[2], + facet.m_thickness, + 0.5f*SCE_PFX_PI*(edge[0]->m_tilt/255.0f), + 0.5f*SCE_PFX_PI*(edge[1]->m_tilt/255.0f), + 0.5f*SCE_PFX_PI*(edge[2]->m_tilt/255.0f), + edgeChk,convexB); + } + + for(int i=0;im_facets[subData.getFacetId()]; + + PfxTriangle triangleA( + meshA->m_verts[facet.m_vertIds[0]], + meshA->m_verts[facet.m_vertIds[1]], + meshA->m_verts[facet.m_vertIds[2]]); + + PfxFloat s=0.0f,t=0.0f; + pfxGetLocalCoords(PfxVector3(localContacts.getLocalPointA(i)),triangleA,s,t); + subData.m_type = PfxSubData::MESH_INFO; + subData.setFacetLocalS(s); + subData.setFacetLocalT(t); + + contacts.addContactPoint( + localContacts.getDistance(i), + transformB.getUpper3x3() * localContacts.getNormal(i), + transformAB * localContacts.getLocalPointA(i), + localContacts.getLocalPointB(i), + subData); + } + + return contacts.getNumContacts(); +} +} //namespace PhysicsEffects +} //namespace sce + diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_convex.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_convex.h new file mode 100644 index 0000000..e653670 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_convex.h @@ -0,0 +1,37 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONTACT_TRI_MESH_CONVEX_H +#define _SCE_PFX_CONTACT_TRI_MESH_CONVEX_H + +#include "../../../include/physics_effects/base_level/collision/pfx_tri_mesh.h" +#include "pfx_contact_cache.h" + +namespace sce { +namespace PhysicsEffects { + +PfxInt32 pfxContactTriMeshConvex( + PfxContactCache &contacts, + const PfxTriMesh *meshA, + const PfxTransform3 &transformA, + const PfxConvexMesh &convexB, + const PfxTransform3 &transformB, + PfxFloat distanceThreshold = SCE_PFX_FLT_MAX ); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_CONTACT_TRI_MESH_CONVEX_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_cylinder.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_cylinder.cpp new file mode 100644 index 0000000..608e99c --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_cylinder.cpp @@ -0,0 +1,165 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "pfx_contact_tri_mesh_cylinder.h" +#include "pfx_intersect_common.h" +#include "pfx_mesh_common.h" +#include "pfx_gjk_solver.h" +#include "pfx_gjk_support_func.h" + +namespace sce { +namespace PhysicsEffects { + +static SCE_PFX_FORCE_INLINE +bool pfxContactTriangleCylinder(PfxContactCache &contacts,PfxUInt32 facetId, + const PfxVector3 &normal,const PfxVector3 &p0,const PfxVector3 &p1,const PfxVector3 &p2, + const PfxFloat thickness,const PfxFloat angle0,const PfxFloat angle1,const PfxFloat angle2, + PfxUInt32 edgeChk, + const PfxCylinder &cylinder) +{ + PfxVector3 facetPnts[6] = { + p0,p1,p2,p0-thickness*normal,p1-thickness*normal,p2-thickness*normal + }; + + + PfxPoint3 pA(0.0f),pB(0.0f); + PfxVector3 nml(0.0f); + PfxGjkSolver gjk; + + gjk.setup((void*)facetPnts,(void*)&cylinder,pfxGetSupportVertexTriangleWithThickness,pfxGetSupportVertexCylinder); + PfxFloat d = gjk.collide(nml,pA,pB,PfxTransform3::identity(),PfxTransform3::identity(),SCE_PFX_FLT_MAX); + if(d >= 0.0f) return false; + + PfxVector3 pointsOnTriangle = PfxVector3(pA); + PfxVector3 pointsOnConvex = PfxVector3(pB); + PfxVector3 axis = nml; + + // 面上の最近接点が凸エッジ上でない場合は法線を変える + if( ((edgeChk&0x01)&&pfxPointOnLine(pointsOnTriangle,p0,p1)) || + ((edgeChk&0x02)&&pfxPointOnLine(pointsOnTriangle,p1,p2)) || + ((edgeChk&0x04)&&pfxPointOnLine(pointsOnTriangle,p2,p0)) ) { + axis=-normal; + } + + PfxSubData subData; + subData.setFacetId(facetId); + contacts.addContactPoint(-length(pointsOnTriangle-pointsOnConvex),axis,pA,pB,subData); + + return true; +} + +PfxInt32 pfxContactTriMeshCylinder( + PfxContactCache &contacts, + const PfxTriMesh *meshA, + const PfxTransform3 &transformA, + const PfxCylinder &cylinderB, + const PfxTransform3 &transformB, + PfxFloat distanceThreshold) +{ + (void) distanceThreshold; + + PfxTransform3 transformAB, transformBA; + PfxMatrix3 matrixBA; + PfxVector3 offsetBA; + + // Bローカル→Aローカルへの変換. + transformAB = orthoInverse(transformA) * transformB; + + // Aローカル→Bローカルへの変換. + transformBA = orthoInverse(transformAB); + + matrixBA = transformBA.getUpper3x3(); + offsetBA = transformBA.getTranslation(); + + //------------------------------------------- + // 判定する面を絞り込む. + + PfxUInt8 SCE_PFX_ALIGNED(16) selFacets[SCE_PFX_NUMMESHFACETS] = { 0 }; + PfxUInt32 numSelFacets = 0; + + // ※cylinderB座標系 + PfxVector3 aabbB(cylinderB.m_halfLen,cylinderB.m_radius,cylinderB.m_radius); + numSelFacets = pfxGatherFacets(meshA,(PfxFloat*)&aabbB,offsetBA,matrixBA,selFacets); + + if(numSelFacets == 0) { + return 0; + } + + //------------------------------------------- + // 面ごとに衝突を検出 + + PfxContactCache localContacts; + + for(PfxUInt32 f = 0; f < numSelFacets; f++) { + const PfxFacet &facet = meshA->m_facets[selFacets[f]]; + + PfxVector3 facetNormal = matrixBA * pfxReadVector3(facet.m_normal); + + PfxVector3 facetPntsA[3] = { + offsetBA + matrixBA * meshA->m_verts[facet.m_vertIds[0]], + offsetBA + matrixBA * meshA->m_verts[facet.m_vertIds[1]], + offsetBA + matrixBA * meshA->m_verts[facet.m_vertIds[2]], + }; + + const PfxEdge *edge[3] = { + &meshA->m_edges[facet.m_edgeIds[0]], + &meshA->m_edges[facet.m_edgeIds[1]], + &meshA->m_edges[facet.m_edgeIds[2]], + }; + + PfxUInt32 edgeChk = + ((edge[0]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x01) | + ((edge[1]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x02) | + ((edge[2]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x04); + + pfxContactTriangleCylinder(localContacts,selFacets[f], + facetNormal,facetPntsA[0],facetPntsA[1],facetPntsA[2], + facet.m_thickness, + 0.5f*SCE_PFX_PI*(edge[0]->m_tilt/255.0f), + 0.5f*SCE_PFX_PI*(edge[1]->m_tilt/255.0f), + 0.5f*SCE_PFX_PI*(edge[2]->m_tilt/255.0f), + edgeChk,cylinderB); + } + + for(int i=0;im_facets[subData.getFacetId()]; + + PfxTriangle triangleA( + meshA->m_verts[facet.m_vertIds[0]], + meshA->m_verts[facet.m_vertIds[1]], + meshA->m_verts[facet.m_vertIds[2]]); + + PfxFloat s=0.0f,t=0.0f; + pfxGetLocalCoords(PfxVector3(localContacts.getLocalPointA(i)),triangleA,s,t); + subData.m_type = PfxSubData::MESH_INFO; + subData.setFacetLocalS(s); + subData.setFacetLocalT(t); + + contacts.addContactPoint( + localContacts.getDistance(i), + transformB.getUpper3x3() * localContacts.getNormal(i), + transformAB * localContacts.getLocalPointA(i), + localContacts.getLocalPointB(i), + subData); + } + + return contacts.getNumContacts(); +} +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_cylinder.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_cylinder.h new file mode 100644 index 0000000..5d9c9db --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_cylinder.h @@ -0,0 +1,38 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONTACT_TRI_MESH_CYLINDER_H +#define _SCE_PFX_CONTACT_TRI_MESH_CYLINDER_H + +#include "../../../include/physics_effects/base_level/collision/pfx_tri_mesh.h" +#include "../../../include/physics_effects/base_level/collision/pfx_cylinder.h" +#include "pfx_contact_cache.h" + +namespace sce { +namespace PhysicsEffects { + +PfxInt32 pfxContactTriMeshCylinder( + PfxContactCache &contacts, + const PfxTriMesh *meshA, + const PfxTransform3 &transformA, + const PfxCylinder &cylinderB, + const PfxTransform3 &transformB, + PfxFloat distanceThreshold = SCE_PFX_FLT_MAX ); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_CONTACT_TRI_MESH_CYLINDER_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_sphere.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_sphere.cpp new file mode 100644 index 0000000..39d248b --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_sphere.cpp @@ -0,0 +1,239 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "pfx_contact_tri_mesh_sphere.h" +#include "pfx_intersect_common.h" +#include "pfx_mesh_common.h" + +namespace sce { +namespace PhysicsEffects { + +static SCE_PFX_FORCE_INLINE +bool pfxContactTriangleSphere(PfxContactCache &contacts,PfxUInt32 facetId, + const PfxVector3 &normal,const PfxVector3 &p0,const PfxVector3 &p1,const PfxVector3 &p2, + const PfxFloat thickness,const PfxFloat angle0,const PfxFloat angle1,const PfxFloat angle2, + PfxUInt32 edgeChk, + PfxFloat sphereRadius,const PfxVector3 &spherePos) +{ + PfxVector3 facetPnts[3] = { + p0,p1,p2, + }; + + // 早期判定 + { + PfxPlane planeA(normal,p0); + PfxFloat len1 = planeA.onPlane(spherePos); + + if(len1 >= sphereRadius || len1 < -thickness-sphereRadius) return false; + + } + + // 球と面の最近接点を計算 + { + PfxTriangle triangleA(p0,p1,p2); + PfxVector3 pntA; + // pfxClosestPointTriangle(spherePos,triangleA,pntA); + bool insideTriangle = false; + while(1) { + PfxVector3 ab = p1 - p0; + PfxVector3 ac = p2 - p0; + PfxVector3 ap = spherePos - p0; + PfxFloat d1 = dot(ab, ap); + PfxFloat d2 = dot(ac, ap); + if(d1 <= 0.0f && d2 <= 0.0f) { + pntA = p0; + break; + } + + PfxVector3 bp = spherePos - p1; + PfxFloat d3 = dot(ab, bp); + PfxFloat d4 = dot(ac, bp); + if (d3 >= 0.0f && d4 <= d3) { + pntA = p1; + break; + } + + PfxFloat vc = d1*d4 - d3*d2; + if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) { + PfxFloat v = d1 / (d1 - d3); + pntA = p0 + v * ab; + break; + } + + PfxVector3 cp = spherePos - p2; + PfxFloat d5 = dot(ab, cp); + PfxFloat d6 = dot(ac, cp); + if (d6 >= 0.0f && d5 <= d6) { + pntA = p2; + break; + } + + PfxFloat vb = d5*d2 - d1*d6; + if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) { + PfxFloat w = d2 / (d2 - d6); + pntA = p0 + w * ac; + break; + } + + PfxFloat va = d3*d6 - d5*d4; + if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) { + PfxFloat w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); + pntA = p1 + w * (p2 - p1); + break; + } + + PfxFloat den = 1.0f / (va + vb + vc); + PfxFloat v = vb * den; + PfxFloat w = vc * den; + pntA = p0 + ab * v + ac * w; + insideTriangle = true; + break; + } + PfxVector3 distVec = pntA - spherePos; + PfxFloat l = length(distVec); + + if(!insideTriangle && l >= sphereRadius) return false; + + // 分離軸 + PfxVector3 sepAxis = (l < 0.00001f || insideTriangle) ? -normal : distVec / l; + + // 球上の衝突点 + PfxVector3 pointsOnSphere = spherePos + sphereRadius * sepAxis; + PfxVector3 pointsOnTriangle = pntA; + + // 面上の最近接点が凸エッジ上でない場合は法線を変える + if( ((edgeChk&0x01)&&pfxPointOnLine(pointsOnTriangle,p0,p1)) || + ((edgeChk&0x02)&&pfxPointOnLine(pointsOnTriangle,p1,p2)) || + ((edgeChk&0x04)&&pfxPointOnLine(pointsOnTriangle,p2,p0)) ) { + sepAxis=-normal; + } + + PfxSubData subData; + subData.setFacetId(facetId); + contacts.addContactPoint(-length(pointsOnSphere-pointsOnTriangle),sepAxis,PfxPoint3(pointsOnTriangle),PfxPoint3(pointsOnSphere),subData); + } + + return true; +} + +PfxInt32 pfxContactTriMeshSphere( + PfxContactCache &contacts, + const PfxTriMesh *meshA, + const PfxTransform3 &transformA, + const PfxSphere &sphereB, + const PfxTransform3 &transformB, + PfxFloat distanceThreshold) +{ + (void) distanceThreshold; + + PfxTransform3 transformAB,transformBA; + PfxMatrix3 matrixBA; + PfxVector3 offsetBA; + + // Bローカル→Aローカルへの変換 + transformAB = orthoInverse(transformA) * transformB; + + // Aローカル→Bローカルへの変換 + transformBA = orthoInverse(transformAB); + + matrixBA = transformBA.getUpper3x3(); + offsetBA = transformBA.getTranslation(); + + //------------------------------------------- + // 判定する面を絞り込む + + PfxUInt8 SCE_PFX_ALIGNED(16) selFacets[SCE_PFX_NUMMESHFACETS] = {0}; + PfxUInt32 numSelFacets = 0; + + PfxVector3 aabbB(sphereB.m_radius); + numSelFacets = pfxGatherFacets(meshA,(PfxFloat*)&aabbB,offsetBA,matrixBA,selFacets); + + if(numSelFacets == 0) { + return 0; + } + + //----------------------------------------------- + // 判定 + + PfxContactCache localContacts; + + // TriangleMeshの面->sphereの判定 + // ※TriangleMesh座標系 + { + for(PfxUInt32 f = 0; f < numSelFacets; f++ ) { + const PfxFacet &facet = meshA->m_facets[selFacets[f]]; + + const PfxVector3 facetNormal = pfxReadVector3(facet.m_normal); + + const PfxVector3 facetPnts[3] = { + meshA->m_verts[facet.m_vertIds[0]], + meshA->m_verts[facet.m_vertIds[1]], + meshA->m_verts[facet.m_vertIds[2]], + }; + + const PfxEdge *edge[3] = { + &meshA->m_edges[facet.m_edgeIds[0]], + &meshA->m_edges[facet.m_edgeIds[1]], + &meshA->m_edges[facet.m_edgeIds[2]], + }; + + PfxVector3 sepAxis,pntA,pntB; + + PfxUInt32 edgeChk = + ((edge[0]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x01) | + ((edge[1]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x02) | + ((edge[2]->m_angleType==SCE_PFX_EDGE_CONVEX)?0x00:0x04); + + pfxContactTriangleSphere(localContacts,selFacets[f], + facetNormal,facetPnts[0],facetPnts[1],facetPnts[2], + facet.m_thickness, + 0.5f*SCE_PFX_PI*(edge[0]->m_tilt/255.0f), + 0.5f*SCE_PFX_PI*(edge[1]->m_tilt/255.0f), + 0.5f*SCE_PFX_PI*(edge[2]->m_tilt/255.0f), + edgeChk, + sphereB.m_radius,transformAB.getTranslation()); + } + } + + for(int i=0;im_facets[subData.getFacetId()]; + + PfxTriangle triangleA( + meshA->m_verts[facet.m_vertIds[0]], + meshA->m_verts[facet.m_vertIds[1]], + meshA->m_verts[facet.m_vertIds[2]]); + + PfxFloat s=0.0f,t=0.0f; + pfxGetLocalCoords(PfxVector3(localContacts.getLocalPointA(i)),triangleA,s,t); + subData.m_type = PfxSubData::MESH_INFO; + subData.setFacetLocalS(s); + subData.setFacetLocalT(t); + + contacts.addContactPoint( + localContacts.getDistance(i), + transformA.getUpper3x3() * localContacts.getNormal(i), + localContacts.getLocalPointA(i), + transformBA * localContacts.getLocalPointB(i), + subData); + } + + return contacts.getNumContacts(); +} +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_sphere.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_sphere.h new file mode 100644 index 0000000..5dc3bba --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_contact_tri_mesh_sphere.h @@ -0,0 +1,38 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONTACT_TRI_MESH_SPHERE_H +#define _SCE_PFX_CONTACT_TRI_MESH_SPHERE_H + +#include "../../../include/physics_effects/base_level/collision/pfx_tri_mesh.h" +#include "../../../include/physics_effects/base_level/collision/pfx_sphere.h" +#include "pfx_contact_cache.h" + +namespace sce { +namespace PhysicsEffects { + +PfxInt32 pfxContactTriMeshSphere( + PfxContactCache &contacts, + const PfxTriMesh *meshA, + const PfxTransform3 &transformA, + const PfxSphere &sphereB, + const PfxTransform3 &transformB, + PfxFloat distanceThreshold = SCE_PFX_FLT_MAX ); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_CONTACT_TRI_MESH_SPHERE_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_gjk_solver.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_gjk_solver.cpp new file mode 100644 index 0000000..e7c4c24 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_gjk_solver.cpp @@ -0,0 +1,485 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "pfx_gjk_solver.h" +#include "pfx_intersect_common.h" + + +namespace sce { +namespace PhysicsEffects { + + +template +struct PfxGjkStack { + int cur; + T data[maxData]; + + PfxGjkStack() : cur(0) {} + + void push(const T &d) + { + SCE_PFX_ASSERT(cur gs; + + gs.push(PfxGjkEdge(facet,i)); + + do { + PfxGjkEdge stk = gs.pop(); + PfxGjkFacet *ft = stk.f; + + if(ft->obsolete==0) { + // wから見えるかどうかを判定 + if(dot(ft->normal,w-ft->closest) < 0.0f) { + // 見えないのでエッジを登録 + SCE_PFX_ASSERT(numEdges<=(int)MAX_FACETS); + edges[numEdges] = stk; + numEdges++; + } + else { + ft->obsolete = 1; + gs.push(PfxGjkEdge(ft->adj[(stk.i+2)%3],ft->j[(stk.i+2)%3])); + gs.push(PfxGjkEdge(ft->adj[(stk.i+1)%3],ft->j[(stk.i+1)%3])); + } + } + } while(SCE_PFX_UNLIKELY(!gs.isEmpty())); +} + +/////////////////////////////////////////////////////////////////////////////// +// Detect Penetration Depth (EPA) + +PfxFloat PfxGjkSolver::detectPenetrationDepth( + const PfxTransform3 &transformA,const PfxTransform3 &transformB, + PfxVector3 &pA,PfxVector3 &pB,PfxVector3 &normal) +{ + PfxMatrix3 invRotA = transpose(transformA.getUpper3x3()); + PfxMatrix3 invRotB = transpose(transformB.getUpper3x3()); + + int epaIterationCount = 0; + PfxFloat distance = SCE_PFX_FLT_MAX; + + numFacets = 0; + numFacetsHead = 0; + + // 初期状態の判定 + if(m_simplex.numVertices <= 1) { + return distance; + } + else if(m_simplex.numVertices == 2) { + PfxVector3 v0 = m_simplex.W[0]; + PfxVector3 v1 = m_simplex.W[1]; + PfxVector3 dir = normalize(v1-v0); + PfxMatrix3 rot = PfxMatrix3::rotation(2.0943951023932f,dir);//120 deg + int axis; + if(dir[0] < dir[1]) { + if(dir[0] < dir[2]) { + axis = 0; + } + else { + axis = 2; + } + } + else { + if(dir[1] < dir[2]) { + axis = 1; + } + else { + axis = 2; + } + } + PfxVector3 vec(0.0f); + vec[axis] = 1.0f; + + PfxVector3 aux[3]; + aux[0] = cross(dir,vec); + aux[1] = rot * aux[0]; + aux[2] = rot * aux[1]; + + PfxVector3 p[3],q[3],w[3]; + + for(int i=0;i<3;i++) { + PfxVector3 pInA,qInB; + getSupportVertexShapeA(shapeA,invRotA * aux[i],pInA); + getSupportVertexShapeB(shapeB,invRotB * (-aux[i]),qInB); + p[i] = transformA.getTranslation() + transformA.getUpper3x3() * pInA; + q[i] = transformB.getTranslation() + transformB.getUpper3x3() * qInB; + w[i] = p[i] - q[i]; + vertsP[i] = p[i]; + vertsQ[i] = q[i]; + vertsW[i] = w[i]; + } + + if(originInTetrahedron(w[0],w[1],w[2],v0)) { + vertsP[3] = m_simplex.P[0]; + vertsQ[3] = m_simplex.Q[0]; + vertsW[3] = m_simplex.W[0]; + numVerts = 4; + } + else if(originInTetrahedron(w[0],w[1],w[2],v1)){ + vertsP[3] = m_simplex.P[1]; + vertsQ[3] = m_simplex.Q[1]; + vertsW[3] = m_simplex.W[1]; + numVerts = 4; + } + else { + return distance; + } + } + else if(m_simplex.numVertices == 3) { + numVerts = 3; + for(int i=0;i 0.0f) { + PfxVector3 vertsP1,vertsQ1,vertsW1; + PfxVector3 vertsP3,vertsQ3,vertsW3; + vertsQ1=vertsQ[1];vertsW1=vertsW[1];vertsP1=vertsP[1]; + vertsQ3=vertsQ[3];vertsW3=vertsW[3];vertsP3=vertsP[3]; + vertsQ[1]=vertsQ3;vertsW[1]=vertsW3;vertsP[1]=vertsP3; + vertsQ[3]=vertsQ1;vertsW[3]=vertsW1;vertsP[3]=vertsP1; + } + + { + PfxGjkFacet *f0 = addFacet(0,1,2); + PfxGjkFacet *f1 = addFacet(0,3,1); + PfxGjkFacet *f2 = addFacet(0,2,3); + PfxGjkFacet *f3 = addFacet(1,3,2); + + if(SCE_PFX_UNLIKELY(!f0 || !f1 || !f2 || !f3)) return distance; + + linkFacets(f0,0,f1,2); + linkFacets(f0,1,f3,2); + linkFacets(f0,2,f2,0); + linkFacets(f1,0,f2,2); + linkFacets(f1,1,f3,0); + linkFacets(f2,1,f3,1); + } + + // 探索 + PfxGjkFacet *facetMin = NULL; + + do { + // 原点から一番近い点を算出し、そのベクトルと支点を返す + int minFacetIdx = 0; + { + PfxFloat minDistSqr = SCE_PFX_FLT_MAX; + for(int i=0;iobsolete==0 && facetsHead[i]->distSqr < minDistSqr) { + minDistSqr = facetsHead[i]->distSqr; + facetMin = facetsHead[i]; + minFacetIdx = i; + } + } + } + + // リストからはずす + facetsHead[minFacetIdx] = facetsHead[--numFacetsHead]; + + PfxVector3 pInA(0.0f),qInB(0.0f); + getSupportVertexShapeA(shapeA,invRotA * facetMin->normal,pInA); + getSupportVertexShapeB(shapeB,invRotB * (-facetMin->normal),qInB); + PfxVector3 p = transformA.getTranslation() + transformA.getUpper3x3() * pInA; + PfxVector3 q = transformB.getTranslation() + transformB.getUpper3x3() * qInB; + PfxVector3 w = p - q; + PfxVector3 v = facetMin->closest; + + // 最近接点チェック + PfxFloat l0 = length(v); + PfxFloat l1 = dot(facetMin->normal,w); + + if((l1 - l0) < SCE_PFX_GJK_EPSILON) { + break; + } + + // 求めた点を追加して面を分割 + { + SCE_PFX_ASSERT(numVerts<(int)MAX_VERTS); + int vId = numVerts++; + vertsP[vId] = p; + vertsQ[vId] = q; + vertsW[vId] = w; + + facetMin->obsolete = 1; + + numEdges = 0; + + silhouette(facetMin->adj[0],facetMin->j[0],w); + silhouette(facetMin->adj[1],facetMin->j[1],w); + silhouette(facetMin->adj[2],facetMin->j[2],w); + + if(SCE_PFX_UNLIKELY(numEdges == 0)) break; + + bool edgeCheck = true; + PfxGjkFacet *firstFacet,*lastFacet; + { + PfxGjkEdge &edge = edges[0]; + int v0 = edge.f->v[(edge.i+1)%3]; + int v1 = edge.f->v[edge.i]; + firstFacet = addFacet(v0,v1,vId); + if(SCE_PFX_UNLIKELY(!firstFacet)) { + edgeCheck = false; + break; + } + linkFacets(edge.f,edge.i,firstFacet,0); + lastFacet = firstFacet; + } + + if(SCE_PFX_UNLIKELY(!edgeCheck)) break; + + for(int e=1;ev[(edge.i+1)%3]; + int v1 = edge.f->v[edge.i]; + PfxGjkFacet *f = addFacet(v0,v1,vId); + if(SCE_PFX_UNLIKELY(!f)) {edgeCheck=false;break;} + linkFacets(edge.f,edge.i,f,0); + linkFacets(f,2,lastFacet,1); + lastFacet = f; + } + if(SCE_PFX_UNLIKELY(!edgeCheck)) break; + + linkFacets(lastFacet,1,firstFacet,2); + } + + epaIterationCount++; + if(SCE_PFX_UNLIKELY(epaIterationCount > SCE_PFX_EPA_ITERATION_MAX || numFacetsHead == 0)) { + break; + } + } while(1); + + // 衝突点計算 + int v1 = facetMin->v[0]; + int v2 = facetMin->v[1]; + int v3 = facetMin->v[2]; + + PfxVector3 p0 = vertsW[v2]-vertsW[v1]; + PfxVector3 p1 = vertsW[v3]-vertsW[v1]; + PfxVector3 p2 = facetMin->closest-vertsW[v1]; + + PfxVector3 v = cross( p0, p1 ); + PfxVector3 crS = cross( v, p0 ); + PfxVector3 crT = cross( v, p1 ); + PfxFloat d0 = dot( crT, p0 ); + PfxFloat d1 = dot( crS, p1 ); + + if(fabsf(d0) < SCE_PFX_GJK_EPSILON || fabsf(d1) < SCE_PFX_GJK_EPSILON) return distance; + + PfxFloat lamda1 = dot( crT, p2 ) / d0; + PfxFloat lamda2 = dot( crS, p2 ) / d1; + + pA = vertsP[v1] + lamda1*(vertsP[v2]-vertsP[v1]) + lamda2*(vertsP[v3]-vertsP[v1]); + pB = vertsQ[v1] + lamda1*(vertsQ[v2]-vertsQ[v1]) + lamda2*(vertsQ[v3]-vertsQ[v1]); + + PfxFloat lenSqr = lengthSqr(pB-pA); + normal = normalize(pB-pA); + + return -sqrtf(lenSqr); +} + +/////////////////////////////////////////////////////////////////////////////// +// Gjk + +PfxFloat PfxGjkSolver::collide( PfxVector3& normal, PfxPoint3 &pointA, PfxPoint3 &pointB, + const PfxTransform3 & transformA, + const PfxTransform3 & transformB, + PfxFloat distanceThreshold) +{ + (void) distanceThreshold; + + int gjkIterationCount = 0; + + m_simplex.reset(); + + PfxTransform3 cTransformA = transformA; + PfxTransform3 cTransformB = transformB; + PfxMatrix3 invRotA = transpose(cTransformA.getUpper3x3()); + PfxMatrix3 invRotB = transpose(cTransformB.getUpper3x3()); + + PfxVector3 offset = (cTransformA.getTranslation() + cTransformB.getTranslation())*0.5f; + cTransformA.setTranslation(cTransformA.getTranslation()-offset); + cTransformB.setTranslation(cTransformB.getTranslation()-offset); + + PfxVector3 separatingAxis(-cTransformA.getTranslation()); + if(lengthSqr(separatingAxis) < 0.000001f) separatingAxis = PfxVector3(1.0,0.0,0.0); + PfxFloat squaredDistance = SCE_PFX_FLT_MAX; + PfxFloat delta = 0.0f; + PfxFloat distance = SCE_PFX_FLT_MAX; + + for(;;) { + // サポート頂点の取得 + PfxVector3 pInA,qInB; + + getSupportVertexShapeA(shapeA,invRotA * (-separatingAxis),pInA); + getSupportVertexShapeB(shapeB,invRotB * separatingAxis,qInB); + + PfxVector3 p = cTransformA.getTranslation() + cTransformA.getUpper3x3() * pInA; + PfxVector3 q = cTransformB.getTranslation() + cTransformB.getUpper3x3() * qInB; + PfxVector3 w = p - q; + + delta = dot(separatingAxis,w); + + // 早期終了チェック + if(SCE_PFX_UNLIKELY(delta > 0.0f)) { + normal = separatingAxis; + return distance; + } + + if(SCE_PFX_UNLIKELY(m_simplex.inSimplex(w))) { + break; + } + + PfxFloat f0 = squaredDistance - delta; + PfxFloat f1 = squaredDistance * SCE_PFX_GJK_EPSILON; + + if (SCE_PFX_UNLIKELY(f0 <= f1)) { + break; + } + + // 頂点を単体に追加 + m_simplex.addVertex(w,p,q); + + // 原点と単体の最近接点を求め、分離軸を返す + if(SCE_PFX_UNLIKELY(!m_simplex.closest(separatingAxis))) { + normal = separatingAxis; + return distance; + } + + squaredDistance = lengthSqr(separatingAxis); + + if(SCE_PFX_UNLIKELY(gjkIterationCount >= SCE_PFX_GJK_ITERATION_MAX || m_simplex.fullSimplex())) { + break; + } + + gjkIterationCount++; + } + + PfxVector3 pA(0.0f),pB(0.0f); + + // 2つのConvexは交差しているので、接触点を探索する + PfxFloat dist = detectPenetrationDepth(cTransformA,cTransformB,pA,pB,normal); + + //マージン考慮 + if(dist < 0.0f) { + pA += normal * SCE_PFX_GJK_MARGIN; + pB -= normal * SCE_PFX_GJK_MARGIN; + dist = dot(normal,pA-pB); + pointA = orthoInverse(transformA)*PfxPoint3(pA+offset); + pointB = orthoInverse(transformB)*PfxPoint3(pB+offset); + } + + return dist; +} +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_gjk_solver.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_gjk_solver.h new file mode 100644 index 0000000..9d980a3 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_gjk_solver.h @@ -0,0 +1,190 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_GJK_SOLVER_H +#define _SCE_PFX_GJK_SOLVER_H + +#include "../../../include/physics_effects/base_level/base/pfx_common.h" +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "pfx_simplex_solver.h" + +namespace sce { +namespace PhysicsEffects { + +#define SCE_PFX_GJK_EPSILON 1e-04f +#define SCE_PFX_GJK_MARGIN 0.025f +#define SCE_PFX_GJK_ITERATION_MAX 10 +#define SCE_PFX_EPA_ITERATION_MAX 10 + +/////////////////////////////////////////////////////////////////////////////// +// Support Function + +typedef void (*PfxGetSupportVertexFunc)(void *shape,const PfxVector3 &seperatingAxis,PfxVector3 &supportVertex); + +/////////////////////////////////////////////////////////////////////////////// +// Gjk +class PfxSimplexSolver; + +class PfxGjkSolver +{ +private: + static const PfxUInt32 MAX_VERTS = 128; + static const PfxUInt32 MAX_EDGES = 128; + static const PfxUInt32 MAX_FACETS = 64; + + PfxSimplexSolver m_simplex; + + // 面 + struct PfxGjkFacet { + PfxVector3 normal; // 面の法線 + PfxVector3 closest; // 原点からの最短ベクトル + PfxUInt32 obsolete; // 廃棄面判定 + PfxFloat distSqr; // 原点からの距離 + PfxInt32 v[3]; // 頂点 + PfxInt32 j[3]; // 隣接面から見たIndex + PfxGjkFacet *adj[3]; // 隣接面 + SCE_PFX_PADDING(1,4) + }; + + // エッジ + struct PfxGjkEdge { + PfxGjkFacet *f; + PfxInt32 i; + PfxGjkEdge() {} + PfxGjkEdge(PfxGjkFacet *f_,PfxInt32 i_) + { + f = f_; + i= i_; + } + }; + + PfxVector3 g_vertsP[MAX_VERTS]; + PfxVector3 g_vertsQ[MAX_VERTS]; + PfxVector3 g_vertsW[MAX_VERTS]; + PfxGjkFacet g_facets[MAX_FACETS]; + PfxGjkFacet *g_facetsHead[MAX_FACETS]; + PfxGjkEdge g_edges[MAX_EDGES]; + + PfxVector3 SCE_PFX_ALIGNED(16) *vertsP; + SCE_PFX_PADDING(1,12) + PfxVector3 SCE_PFX_ALIGNED(16) *vertsQ; + SCE_PFX_PADDING(2,12) + PfxVector3 SCE_PFX_ALIGNED(16) *vertsW; + SCE_PFX_PADDING(3,12) + PfxGjkFacet SCE_PFX_ALIGNED(16) *facets; + SCE_PFX_PADDING(4,12) + PfxGjkFacet SCE_PFX_ALIGNED(16) **facetsHead; + SCE_PFX_PADDING(5,12) + PfxGjkEdge SCE_PFX_ALIGNED(16) *edges; + + int numVerts; + int numEdges; + int numFacets; + int numFacetsHead; + SCE_PFX_PADDING(6,12) + + inline PfxGjkFacet *addFacet(int v1,int v2,int v3); + + inline void linkFacets(PfxGjkFacet *f1,int e1,PfxGjkFacet *f2,int e2); + void silhouette(PfxGjkFacet *facet,int i,PfxVector3 &w); + + inline bool originInTetrahedron(const PfxVector3& p0,const PfxVector3& p1,const PfxVector3& p2,const PfxVector3& p3); + + PfxFloat detectPenetrationDepth( + const PfxTransform3 &transformA,const PfxTransform3 &transformB, + PfxVector3 &pA,PfxVector3 &pB,PfxVector3 &normal); + + void *shapeA; + void *shapeB; + PfxGetSupportVertexFunc getSupportVertexShapeA; + PfxGetSupportVertexFunc getSupportVertexShapeB; + +public: + PfxGjkSolver(); + ~PfxGjkSolver(); + + void setup(void *sA,void *sB,PfxGetSupportVertexFunc fA,PfxGetSupportVertexFunc fB); + + PfxFloat collide( PfxVector3& normal, PfxPoint3 &pointA, PfxPoint3 &pointB, + const PfxTransform3 & transformA, + const PfxTransform3 & transformB, + PfxFloat distanceThreshold = SCE_PFX_FLT_MAX); +}; + +inline +PfxGjkSolver::PfxGjkFacet *PfxGjkSolver::addFacet(int v1,int v2,int v3) +{ + if(SCE_PFX_UNLIKELY(numFacets == (int)MAX_FACETS)) + return NULL; + + PfxGjkFacet &facet = facets[numFacets]; + + PfxVector3 V1 = vertsW[v1]; + PfxVector3 V2 = vertsW[v2]; + PfxVector3 V3 = vertsW[v3]; + facet.obsolete = 0; + facet.v[0] = v1; + facet.v[1] = v2; + facet.v[2] = v3; + + PfxVector3 normal = cross(V3-V1,V2-V1); + + PfxFloat l = lengthSqr(normal); + + if(l < SCE_PFX_GJK_EPSILON * SCE_PFX_GJK_EPSILON) { + return NULL; + } + + normal /= sqrtf(l); + facet.closest = dot(V1,normal)*normal; + facet.normal =normal; + + facet.distSqr = lengthSqr(facet.closest); + + facetsHead[numFacetsHead++] = &facet; + numFacets++; + + return &facet; +} + +inline +void PfxGjkSolver::linkFacets(PfxGjkFacet *f1,int e1,PfxGjkFacet *f2,int e2) +{ + f1->adj[e1] = f2; + f2->adj[e2] = f1; + f1->j[e1] = e2; + f2->j[e2] = e1; +} + +inline +bool PfxGjkSolver::originInTetrahedron(const PfxVector3& p0,const PfxVector3& p1,const PfxVector3& p2,const PfxVector3& p3) +{ + PfxVector3 n0 = cross((p1-p0),(p2-p0)); + PfxVector3 n1 = cross((p2-p1),(p3-p1)); + PfxVector3 n2 = cross((p3-p2),(p0-p2)); + PfxVector3 n3 = cross((p0-p3),(p1-p3)); + + return + dot(n0,p0) * dot(n0,p3-p0) <= 0.0f && + dot(n1,p1) * dot(n1,p0-p1) <= 0.0f && + dot(n2,p2) * dot(n2,p1-p2) <= 0.0f && + dot(n3,p3) * dot(n3,p2-p3) <= 0.0f; +} + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_GJK_SOLVER_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_gjk_support_func.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_gjk_support_func.cpp new file mode 100644 index 0000000..b252b3f --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_gjk_support_func.cpp @@ -0,0 +1,134 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "pfx_gjk_support_func.h" +#include "../../../include/physics_effects/base_level/collision/pfx_tri_mesh.h" +#include "../../../include/physics_effects/base_level/collision/pfx_box.h" +#include "../../../include/physics_effects/base_level/collision/pfx_capsule.h" +#include "../../../include/physics_effects/base_level/collision/pfx_cylinder.h" +#include "../../../include/physics_effects/base_level/collision/pfx_sphere.h" + +namespace sce { +namespace PhysicsEffects { + +#define SCE_PFX_GJK_MARGIN 0.025f + +/////////////////////////////////////////////////////////////////////////////// +// Support Function + +void pfxGetSupportVertexTriangle(void *shape,const PfxVector3 &seperatingAxis,PfxVector3 &supportVertex) +{ + PfxVector3 *vtx = (PfxVector3*)shape; + +PfxFloat d0 = dot(vtx[0],seperatingAxis); +PfxFloat d1 = dot(vtx[1],seperatingAxis); +PfxFloat d2 = dot(vtx[2],seperatingAxis); + +int reti = 2; + +if(d0 > d1 && d0 > d2) { + reti = 0; +} +else if(d1 > d2) { + reti = 1; +} + + supportVertex = vtx[reti] + SCE_PFX_GJK_MARGIN * normalize(seperatingAxis); +} + +void pfxGetSupportVertexTriangleWithThickness(void *shape,const PfxVector3 &seperatingAxis,PfxVector3 &supportVertex) +{ + PfxVector3 *vtx = (PfxVector3*)shape; + +PfxFloat d[6]; +d[0] = dot(vtx[0],seperatingAxis); +d[1] = dot(vtx[1],seperatingAxis); +d[2] = dot(vtx[2],seperatingAxis); +d[3] = dot(vtx[3],seperatingAxis); +d[4] = dot(vtx[4],seperatingAxis); +d[5] = dot(vtx[5],seperatingAxis); + +int reti = 0; +for(int i=1;i<6;i++) { + if(d[reti] < d[i]) { + reti = i; + } +} + + supportVertex = vtx[reti] + SCE_PFX_GJK_MARGIN * normalize(seperatingAxis); +} + +void pfxGetSupportVertexConvex(void *shape,const PfxVector3 &seperatingAxis,PfxVector3 &supportVertex) +{ + PfxConvexMesh *mesh = (PfxConvexMesh*)shape; + int reti = 0; +PfxFloat dmax = dot(mesh->m_verts[0],seperatingAxis); +for(int i=1;im_numVerts;i++) { + PfxFloat d = dot(mesh->m_verts[i],seperatingAxis); + if(d > dmax) { + dmax =d; + reti = i; + } +} + supportVertex = mesh->m_verts[reti] + SCE_PFX_GJK_MARGIN * normalize(seperatingAxis); +} + +void pfxGetSupportVertexBox(void *shape,const PfxVector3 &seperatingAxis,PfxVector3 &supportVertex) +{ + PfxBox *box = (PfxBox*)shape; + PfxVector3 boxHalf = box->m_half + PfxVector3(SCE_PFX_GJK_MARGIN); + supportVertex[0] = seperatingAxis[0]>0.0f?boxHalf[0]:-boxHalf[0]; + supportVertex[1] = seperatingAxis[1]>0.0f?boxHalf[1]:-boxHalf[1]; + supportVertex[2] = seperatingAxis[2]>0.0f?boxHalf[2]:-boxHalf[2]; +} + +void pfxGetSupportVertexCapsule(void *shape,const PfxVector3 &seperatingAxis,PfxVector3 &supportVertex) +{ + PfxCapsule *capsule = (PfxCapsule*)shape; + PfxVector3 u(1.0f,0.0f,0.0f); + + PfxFloat udotv = dot(seperatingAxis,u); + PfxVector3 dir = u * (udotv > 0.0f ? capsule->m_halfLen : -capsule->m_halfLen); + supportVertex = dir + normalize(seperatingAxis) * (capsule->m_radius + SCE_PFX_GJK_MARGIN); +} + +void pfxGetSupportVertexSphere(void *shape,const PfxVector3 &seperatingAxis,PfxVector3 &supportVertex) +{ + PfxSphere *sphere = (PfxSphere*)shape; + supportVertex = normalize(seperatingAxis) * (sphere->m_radius + SCE_PFX_GJK_MARGIN); +} + +void pfxGetSupportVertexCylinder(void *shape,const PfxVector3 &seperatingAxis,PfxVector3 &supportVertex) +{ + PfxCylinder *cylinder = (PfxCylinder*)shape; + PfxVector3 u(1.0f,0.0f,0.0f); + + PfxFloat udotv = dot(seperatingAxis,u); + PfxFloat s = seperatingAxis[1]*seperatingAxis[1]+seperatingAxis[2]*seperatingAxis[2]; + if(s < 0.000001f) { + supportVertex = u * (udotv > 0.0f ? cylinder->m_halfLen + SCE_PFX_GJK_MARGIN : -cylinder->m_halfLen-SCE_PFX_GJK_MARGIN); + } + else { + PfxVector3 dir = u * (udotv > 0.0f ? cylinder->m_halfLen : -cylinder->m_halfLen); + PfxVector3 vYZ = seperatingAxis; + vYZ[0] = 0.0f; + vYZ /= sqrtf(s); + supportVertex = dir + vYZ * (cylinder->m_radius) + normalize(seperatingAxis) * SCE_PFX_GJK_MARGIN; + } +} +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_gjk_support_func.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_gjk_support_func.h new file mode 100644 index 0000000..b7ede87 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_gjk_support_func.h @@ -0,0 +1,36 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_GJK_SUPPORT_FUNC_H +#define _SCE_PFX_GJK_SUPPORT_FUNC_H + +namespace sce { +namespace PhysicsEffects { + +#include "../../../include/physics_effects/base_level/base/pfx_common.h" + +void pfxGetSupportVertexTriangle(void *shape,const PfxVector3 &seperatingAxis,PfxVector3 &supportVertex); +void pfxGetSupportVertexTriangleWithThickness(void *shape,const PfxVector3 &seperatingAxis,PfxVector3 &supportVertex); +void pfxGetSupportVertexConvex(void *shape,const PfxVector3 &seperatingAxis,PfxVector3 &supportVertex); +void pfxGetSupportVertexBox(void *shape,const PfxVector3 &seperatingAxis,PfxVector3 &supportVertex); +void pfxGetSupportVertexCapsule(void *shape,const PfxVector3 &seperatingAxis,PfxVector3 &supportVertex); +void pfxGetSupportVertexSphere(void *shape,const PfxVector3 &seperatingAxis,PfxVector3 &supportVertex); +void pfxGetSupportVertexCylinder(void *shape,const PfxVector3 &seperatingAxis,PfxVector3 &supportVertex); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_GJK_SUPPORT_FUNC_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_common.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_common.h new file mode 100644 index 0000000..b7cfd75 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_common.h @@ -0,0 +1,427 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_INTERSECT_COMMON_H +#define _SCE_PFX_INTERSECT_COMMON_H + +#include "../../../include/physics_effects/base_level/collision/pfx_ray.h" + +namespace sce { +namespace PhysicsEffects { + +#define SCE_PFX_INTERSECT_COMMON_EPSILON 0.00001f +#define SCE_PFX_RAY_TRIANGLE_EPSILON 0.00001f + +// Internally used intersect functions + +struct PfxTriangle +{ + PfxVector3 points[3]; + + PfxTriangle(const PfxVector3 &p0,const PfxVector3 &p1,const PfxVector3 &p2) + { + points[0] = p0; + points[1] = p1; + points[2] = p2; + } +}; + +struct PfxPlane +{ + PfxVector3 normal; // normal + PfxVector3 point; // point on the plane + + PfxPlane(const PfxVector3 &n,const PfxVector3 &q) + { + normal = n; + point = q; + } + + PfxPlane(const PfxTriangle &triangle) + { + normal = normalize(cross(triangle.points[1]-triangle.points[0],triangle.points[2]-triangle.points[0])); + point = triangle.points[0]; + } + + PfxFloat onPlane(const PfxVector3 &p) const + { + return dot((p-point),normal); + } +}; + +static SCE_PFX_FORCE_INLINE +PfxBool pfxIntersectRayAABBFast( + const PfxVector3 &rayStartPosition, + const PfxVector3 &rayDirection, + const PfxVector3 &AABBcenter, + const PfxVector3 &AABBhalf, + PfxFloat &variable) +{ + PfxVector3 AABBmin = AABBcenter - AABBhalf; + PfxVector3 AABBmax = AABBcenter + AABBhalf; + + PfxVector3 dir = rayDirection; + PfxVector3 absDir = absPerElem(dir); + PfxVector3 sign = copySignPerElem(PfxVector3(1.0),dir); + +if(absDir[0] < SCE_PFX_INTERSECT_COMMON_EPSILON) { + if(rayStartPosition[0] < AABBmin[0] || rayStartPosition[0] > AABBmax[0]) { + return false; + } + dir[0] = sign[0] * SCE_PFX_INTERSECT_COMMON_EPSILON; +} + +if(absDir[1] < SCE_PFX_INTERSECT_COMMON_EPSILON) { + if(rayStartPosition[1] < AABBmin[1] || rayStartPosition[1] > AABBmax[1]) { + return false; + } + dir[1] = sign[1] * SCE_PFX_INTERSECT_COMMON_EPSILON; +} + +if(absDir[2] < SCE_PFX_INTERSECT_COMMON_EPSILON) { + if(rayStartPosition[2] < AABBmin[2] || rayStartPosition[2] > AABBmax[2]) { + return false; + } + dir[2] = sign[2] * SCE_PFX_INTERSECT_COMMON_EPSILON; +} + + PfxVector3 t1 = divPerElem(AABBmin - rayStartPosition, dir); + PfxVector3 t2 = divPerElem(AABBmax - rayStartPosition, dir); + + PfxVector3 tmin = minPerElem(t1,t2); + PfxVector3 tmax = maxPerElem(t1,t2); + +if(maxElem(tmin) > minElem(tmax)) return false; + +if(tmin[0] > tmin[1]) { + if(tmin[0] > tmin[2]) { + variable = tmin[0]; + } + else { + variable = tmin[2]; + } +} +else { + if(tmin[1] > tmin[2]) { + variable = tmin[1]; + } + else { + variable = tmin[2]; + } +} + + return true; +} + +static SCE_PFX_FORCE_INLINE +PfxBool pfxIntersectRayAABB( + const PfxVector3 &rayStartPosition, + const PfxVector3 &rayDirection, + const PfxVector3 &AABBcenter, + const PfxVector3 &AABBhalf, + PfxFloat &variable, + PfxVector3 &normal) +{ + PfxVector3 AABBmin = AABBcenter - AABBhalf; + PfxVector3 AABBmax = AABBcenter + AABBhalf; + + PfxVector3 dir = rayDirection; + PfxVector3 absDir = absPerElem(dir); + PfxVector3 sign = copySignPerElem(PfxVector3(1.0),dir); + + // 始点がBoxの内側にあるか判定 + if( AABBmin[0] < rayStartPosition[0] && rayStartPosition[0] < AABBmax[0] && + AABBmin[1] < rayStartPosition[1] && rayStartPosition[1] < AABBmax[1] && + AABBmin[2] < rayStartPosition[2] && rayStartPosition[2] < AABBmax[2]) { + return false; + } + +if(absDir[0] < SCE_PFX_INTERSECT_COMMON_EPSILON) { + if(rayStartPosition[0] < AABBmin[0] || rayStartPosition[0] > AABBmax[0]) { + return false; + } + dir[0] = sign[0] * SCE_PFX_INTERSECT_COMMON_EPSILON; +} + +if(absDir[1] < SCE_PFX_INTERSECT_COMMON_EPSILON) { + if(rayStartPosition[1] < AABBmin[1] || rayStartPosition[1] > AABBmax[1]) { + return false; + } + dir[1] = sign[1] * SCE_PFX_INTERSECT_COMMON_EPSILON; +} + +if(absDir[2] < SCE_PFX_INTERSECT_COMMON_EPSILON) { + if(rayStartPosition[2] < AABBmin[2] || rayStartPosition[2] > AABBmax[2]) { + return false; + } + dir[2] = sign[2] * SCE_PFX_INTERSECT_COMMON_EPSILON; +} + + PfxVector3 t1 = divPerElem(AABBmin - rayStartPosition, dir); + PfxVector3 t2 = divPerElem(AABBmax - rayStartPosition, dir); + + PfxVector3 tmin = minPerElem(t1,t2); + PfxVector3 tmax = maxPerElem(t1,t2); + + normal = PfxVector3(0); + +if(maxElem(tmin) > minElem(tmax)) return false; + +if(tmin[0] > tmin[1]) { + if(tmin[0] > tmin[2]) { + variable = tmin[0]; + normal[0] = -sign[0]; + } + else { + variable = tmin[2]; + normal[2] = -sign[2]; + } +} +else { + if(tmin[1] > tmin[2]) { + variable = tmin[1]; + normal[1] = -sign[1]; + } + else { + variable = tmin[2]; + normal[2] = -sign[2]; + } +} + + return true; +} + +static SCE_PFX_FORCE_INLINE +void pfxClosestTwoLines( + const PfxVector3 &p1,const PfxVector3 &q1, // line1 + const PfxVector3 &p2,const PfxVector3 &q2, // line2 + PfxVector3 &s1,PfxVector3 &s2) +{ + PfxVector3 v1 = q1-p1; + PfxVector3 v2 = q2-p2; + PfxVector3 r = p1 - p2; + + PfxFloat a = dot(v1,v1); + PfxFloat e = dot(v2,v2); + PfxFloat f = dot(v2,r); + PfxFloat b = dot(v1,v2); + PfxFloat c = dot(v1,r); + PfxFloat den = a*e-b*b; + + PfxFloat s,t; + + if(den != 0.0f) { + s = SCE_PFX_CLAMP((b*f-c*e)/den,0.0f,1.0f); + } + else { + s = 0.0f; + } + + t = (b*s+f)/e; + + if(t < 0.0f) { + t = 0.0f; + s = SCE_PFX_CLAMP(-c/a,0.0f,1.0f); + } + else if(t > 1.0f) { + t = 1.0f; + s = SCE_PFX_CLAMP((b-c)/a,0.0f,1.0f); + } + + s1 = p1 + s * v1; + s2 = p2 + t * v2; +} + +static SCE_PFX_FORCE_INLINE +void pfxClosestPointAABB( + const PfxVector3 &point, + const PfxVector3 &AABBhalf, + PfxVector3 &s) +{ + s = point; + s = maxPerElem(s,-AABBhalf); + s = minPerElem(s,AABBhalf); +} + +static SCE_PFX_FORCE_INLINE +void pfxClosestPointTriangle( + const PfxVector3 &point, + const PfxTriangle &triangle, + PfxVector3 &s) +{ + PfxVector3 a = triangle.points[0]; + PfxVector3 b = triangle.points[1]; + PfxVector3 c = triangle.points[2]; + PfxVector3 ab = b - a; + PfxVector3 ac = c - a; + PfxVector3 ap = point - a; + PfxFloat d1 = dot(ab, ap); + PfxFloat d2 = dot(ac, ap); + if(d1 <= 0.0f && d2 <= 0.0f) { + s = a; + return; + } + + PfxVector3 bp = point - b; + PfxFloat d3 = dot(ab, bp); + PfxFloat d4 = dot(ac, bp); + if (d3 >= 0.0f && d4 <= d3) { + s = b; + return; + } + + PfxFloat vc = d1*d4 - d3*d2; + if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) { + PfxFloat v = d1 / (d1 - d3); + s = a + v * ab; + return; + } + + PfxVector3 cp = point - c; + PfxFloat d5 = dot(ab, cp); + PfxFloat d6 = dot(ac, cp); + if (d6 >= 0.0f && d5 <= d6) { + s = c; + return; + } + + PfxFloat vb = d5*d2 - d1*d6; + if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) { + PfxFloat w = d2 / (d2 - d6); + s = a + w * ac; + return; + } + + PfxFloat va = d3*d6 - d5*d4; + if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) { + PfxFloat w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); + s = b + w * (c - b); + return; + } + + PfxFloat den = 1.0f / (va + vb + vc); + PfxFloat v = vb * den; + PfxFloat w = vc * den; + s = a + ab * v + ac * w; +} + +static SCE_PFX_FORCE_INLINE +PfxBool pfxIntersectRayTriangle( + const PfxVector3 &rayStartPosition, + const PfxVector3 &rayDirection, + const PfxTriangle &triangle, + PfxFloat &variable) +{ + PfxFloat v,w; + PfxVector3 ab = triangle.points[1] - triangle.points[0]; + PfxVector3 ac = triangle.points[2] - triangle.points[0]; + + PfxVector3 n = cross(ab,ac); + + PfxFloat d = dot(-rayDirection,n); + + if(fabsf(d) < 0.00001f) return false; + + PfxVector3 ap = rayStartPosition - triangle.points[0]; + PfxFloat t = dot(ap,n) / d; + + if(t <= 0.0f || t >= 1.0f) return false; + + variable = t; + + PfxVector3 e = cross(-rayDirection,ap); + v = dot(ac,e) / d; + if(v < -SCE_PFX_RAY_TRIANGLE_EPSILON || v > 1.0f+SCE_PFX_RAY_TRIANGLE_EPSILON) return false; + + w = -dot(ab,e) / d; + if(w < -SCE_PFX_RAY_TRIANGLE_EPSILON || v+w > 1.0f+SCE_PFX_RAY_TRIANGLE_EPSILON) return false; + + return true; +} + +static SCE_PFX_FORCE_INLINE +PfxBool pfxIntersectRayTriangleWithoutFrontFace( + const PfxVector3 &rayStartPosition, + const PfxVector3 &rayDirection, + const PfxTriangle &triangle, + PfxFloat &variable) +{ + PfxFloat v,w; + PfxVector3 ab = triangle.points[1] - triangle.points[0]; + PfxVector3 ac = triangle.points[2] - triangle.points[0]; + + PfxVector3 n = cross(ab,ac); + + PfxFloat d = dot(-rayDirection,n); + + if(d >= 0.0f) return false; + + PfxVector3 ap = rayStartPosition - triangle.points[0]; + PfxFloat t = dot(ap,n) / d; + + if(t <= 0.0f || t >= 1.0f) return false; + + variable = t; + + PfxVector3 e = cross(-rayDirection,ap); + v = dot(ac,e) / d; + if(v < -SCE_PFX_RAY_TRIANGLE_EPSILON || v > 1.0f+SCE_PFX_RAY_TRIANGLE_EPSILON) return false; + + w = -dot(ab,e) / d; + if(w < -SCE_PFX_RAY_TRIANGLE_EPSILON || v+w > 1.0f+SCE_PFX_RAY_TRIANGLE_EPSILON) return false; + + return true; +} + +static SCE_PFX_FORCE_INLINE +PfxBool pfxIntersectRayTriangleWithoutBackFace( + const PfxVector3 &rayStartPosition, + const PfxVector3 &rayDirection, + const PfxTriangle &triangle, + PfxFloat &variable) +{ + PfxFloat v,w; + PfxVector3 ab = triangle.points[1] - triangle.points[0]; + PfxVector3 ac = triangle.points[2] - triangle.points[0]; + + PfxVector3 n = cross(ab,ac); + + PfxFloat d = dot(-rayDirection,n); + + if(d <= 0.0f) return false; + + PfxVector3 ap = rayStartPosition - triangle.points[0]; + PfxFloat t = dot(ap,n) / d; + + if(t <= 0.0f || t >= 1.0f) return false; + + variable = t; + + PfxVector3 e = cross(-rayDirection,ap); + v = dot(ac,e) / d; + if(v < -SCE_PFX_RAY_TRIANGLE_EPSILON || v > 1.0f+SCE_PFX_RAY_TRIANGLE_EPSILON) return false; + + w = -dot(ab,e) / d; + if(w < -SCE_PFX_RAY_TRIANGLE_EPSILON || v+w > 1.0f+SCE_PFX_RAY_TRIANGLE_EPSILON) return false; + + return true; +} + +} //namespace PhysicsEffects +} //namespace sce + + +#endif // _SCE_PFX_INTERSECT_COMMON_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_box.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_box.cpp new file mode 100644 index 0000000..9d109f2 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_box.cpp @@ -0,0 +1,47 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "pfx_intersect_common.h" +#include "pfx_intersect_ray_box.h" + +namespace sce { +namespace PhysicsEffects { + +PfxBool pfxIntersectRayBox(const PfxRayInput &ray,PfxRayOutput &out,const PfxBox &box,const PfxTransform3 &transform) +{ + // レイをBoxのローカル座標へ変換 + PfxTransform3 transformBox = orthoInverse(transform); + PfxVector3 rayStartPosition = transformBox.getUpper3x3() * ray.m_startPosition + transformBox.getTranslation(); + PfxVector3 rayDirection = transformBox.getUpper3x3() * ray.m_direction; + + // 交差判定 + PfxFloat tmpVariable=0.0f; + PfxVector3 tmpNormal(0.0f); + if(pfxIntersectRayAABB(rayStartPosition,rayDirection,PfxVector3(0.0f),box.m_half,tmpVariable,tmpNormal)) { + if(tmpVariable > 0.0f && tmpVariable < out.m_variable) { + out.m_contactFlag = true; + out.m_variable = tmpVariable; + out.m_contactPoint = ray.m_startPosition + tmpVariable * ray.m_direction; + out.m_contactNormal = transform.getUpper3x3() * tmpNormal; + out.m_subData.m_type = PfxSubData::NONE; + return true; + } + } + + return false; +} +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_box.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_box.h new file mode 100644 index 0000000..dfd7141 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_box.h @@ -0,0 +1,31 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_INTERSECT_RAYBOX_H +#define _SCE_PFX_INTERSECT_RAYBOX_H + +#include "../../../include/physics_effects/base_level/collision/pfx_ray.h" +#include "../../../include/physics_effects/base_level/collision/pfx_box.h" + +namespace sce { +namespace PhysicsEffects { + +PfxBool pfxIntersectRayBox(const PfxRayInput &ray,PfxRayOutput &out,const PfxBox &box,const PfxTransform3 &transform); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_INTERSECT_RAYBOX_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_capsule.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_capsule.cpp new file mode 100644 index 0000000..78b8fc4 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_capsule.cpp @@ -0,0 +1,136 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "pfx_intersect_common.h" +#include "pfx_intersect_ray_capsule.h" + +namespace sce { +namespace PhysicsEffects { +PfxBool pfxIntersectRayCapsule(const PfxRayInput &ray,PfxRayOutput &out,const PfxCapsule &capsule,const PfxTransform3 &transform) +{ + // レイをCapsuleのローカル座標へ変換 + PfxTransform3 transformCapsule = orthoInverse(transform); + PfxVector3 startPosL = transformCapsule.getUpper3x3() * ray.m_startPosition + transformCapsule.getTranslation(); + PfxVector3 rayDirL = transformCapsule.getUpper3x3() * ray.m_direction; + + PfxFloat radSqr = capsule.m_radius * capsule.m_radius; + + // 始点がカプセルの内側にあるか判定 + { + PfxFloat h = fabsf(startPosL[0]); + if(h > capsule.m_halfLen) h = capsule.m_halfLen; + PfxVector3 Px(out.m_variable,0,0); + PfxFloat sqrLen = lengthSqr(startPosL-Px); + if(sqrLen <= radSqr) return false; + } + + // カプセルの胴体との交差判定 + do { + PfxVector3 P(startPosL); + PfxVector3 D(rayDirL); + + P[0] = 0.0f; + D[0] = 0.0f; + + PfxFloat a = dot(D,D); + PfxFloat b = dot(P,D); + PfxFloat c = dot(P,P) - radSqr; + + PfxFloat d = b * b - a * c; + + if(d < 0.0f || fabs(a) < 0.00001f) return false; + + PfxFloat tt = ( -b - sqrtf(d) ) / a; + + if(tt < 0.0f) + break; + else if(tt > 1.0f) + return false; + + if(tt < out.m_variable) { + PfxVector3 cp = startPosL + tt * rayDirL; + + if(fabsf(cp[0]) <= capsule.m_halfLen) { + out.m_contactFlag = true; + out.m_variable = tt; + out.m_contactPoint = PfxVector3(transform * PfxPoint3(cp)); + out.m_contactNormal = transform.getUpper3x3() * normalize(cp); + out.m_subData.m_type = PfxSubData::NONE; + return true; + } + } + } while(0); + + // カプセルの両端にある球体との交差判定 + PfxFloat a = dot(rayDirL,rayDirL); + if(fabs(a) < 0.00001f) return false; + + do { + PfxVector3 center(capsule.m_halfLen,0.0f,0.0f); + PfxVector3 v = startPosL - center; + + PfxFloat b = dot(v,rayDirL); + PfxFloat c = dot(v,v) - radSqr; + + PfxFloat d = b * b - a * c; + + if(d < 0.0f) break; + + PfxFloat tt = ( -b - sqrtf(d) ) / a; + + if(tt < 0.0f || tt > 1.0f) break; + + if(tt < out.m_variable) { + PfxVector3 cp = startPosL + tt * rayDirL; + out.m_contactFlag = true; + out.m_variable = tt; + out.m_contactPoint = ray.m_startPosition + tt * ray.m_direction; + out.m_contactNormal = transform.getUpper3x3() * normalize(cp-center); + out.m_subData.m_type = PfxSubData::NONE; + return true; + } + } while(0); + + { + PfxVector3 center(-capsule.m_halfLen,0.0f,0.0f); + PfxVector3 v = startPosL - center; + + PfxFloat b = dot(v,rayDirL); + PfxFloat c = dot(v,v) - radSqr; + + PfxFloat d = b * b - a * c; + + if(d < 0.0f) return false; + + PfxFloat tt = ( -b - sqrtf(d) ) / a; + + if(tt < 0.0f || tt > 1.0f) return false; + + if(tt < out.m_variable) { + PfxVector3 cp = startPosL + out.m_variable * rayDirL; + out.m_contactFlag = true; + out.m_variable = tt; + out.m_contactPoint = ray.m_startPosition + tt * ray.m_direction; + out.m_contactNormal = transform.getUpper3x3() * normalize(cp-center); + out.m_subData.m_type = PfxSubData::NONE; + return true; + } + } + + return false; +} +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_capsule.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_capsule.h new file mode 100644 index 0000000..559ebf5 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_capsule.h @@ -0,0 +1,31 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_INTERSECT_RAYCAPSULE_H +#define _SCE_PFX_INTERSECT_RAYCAPSULE_H + +#include "../../../include/physics_effects/base_level/collision/pfx_ray.h" +#include "../../../include/physics_effects/base_level/collision/pfx_capsule.h" + +namespace sce { +namespace PhysicsEffects { + +PfxBool pfxIntersectRayCapsule(const PfxRayInput &ray,PfxRayOutput &out,const PfxCapsule &capsule,const PfxTransform3 &transform); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_INTERSECT_RAYCAPSULE_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_convex.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_convex.cpp new file mode 100644 index 0000000..303ae73 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_convex.cpp @@ -0,0 +1,56 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/collision/pfx_tri_mesh.h" +#include "pfx_intersect_common.h" +#include "pfx_intersect_ray_convex.h" + +namespace sce { +namespace PhysicsEffects { + +PfxBool pfxIntersectRayConvex(const PfxRayInput &ray,PfxRayOutput &out,const void *shape,const PfxTransform3 &transform) +{ + const PfxConvexMesh *convex = (const PfxConvexMesh*)shape; + + // レイをConvexのローカル座標へ変換 + PfxTransform3 transformConvex = orthoInverse(transform); + PfxVector3 startPosL = transformConvex.getUpper3x3() * ray.m_startPosition + transformConvex.getTranslation(); + PfxVector3 rayDirL = transformConvex.getUpper3x3() * ray.m_direction; + + // レイとConvexの交差判定 + PfxFloat tmpVariable(0.0f); + PfxVector3 tmpNormal; + bool ret = false; + for(PfxUInt32 f=0;f<(PfxUInt32)convex->m_numIndices/3;f++) { + PfxTriangle triangle( + convex->m_verts[convex->m_indices[f*3 ]], + convex->m_verts[convex->m_indices[f*3+1]], + convex->m_verts[convex->m_indices[f*3+2]]); + + if(pfxIntersectRayTriangleWithoutBackFace(startPosL,rayDirL,triangle,tmpVariable) && tmpVariable < out.m_variable) { + out.m_contactFlag = true; + out.m_variable = tmpVariable; + out.m_contactPoint = ray.m_startPosition + tmpVariable * ray.m_direction; + out.m_contactNormal = transform.getUpper3x3() * normalize(cross(triangle.points[2]-triangle.points[1],triangle.points[0]-triangle.points[1])); + out.m_subData.m_type = PfxSubData::NONE; + ret = true; + } + } + + return ret; +} +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_convex.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_convex.h new file mode 100644 index 0000000..5482900 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_convex.h @@ -0,0 +1,30 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_INTERSECT_RAYCONVEX_H +#define _SCE_PFX_INTERSECT_RAYCONVEX_H + +#include "../../../include/physics_effects/base_level/collision/pfx_ray.h" + +namespace sce { +namespace PhysicsEffects { + +PfxBool pfxIntersectRayConvex(const PfxRayInput &ray,PfxRayOutput &out,const void *shape,const PfxTransform3 &transform); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_INTERSECT_RAYCONVEX_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_cylinder.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_cylinder.cpp new file mode 100644 index 0000000..8b28dfc --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_cylinder.cpp @@ -0,0 +1,106 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "pfx_intersect_common.h" +#include "pfx_intersect_ray_cylinder.h" + +namespace sce { +namespace PhysicsEffects { + +PfxBool pfxIntersectRayCylinder(const PfxRayInput &ray,PfxRayOutput &out,const PfxCylinder &cylinder,const PfxTransform3 &transform) +{ + // レイを円柱のローカル座標へ変換 + PfxTransform3 transformCapsule = orthoInverse(transform); + PfxVector3 startPosL = transformCapsule.getUpper3x3() * ray.m_startPosition + transformCapsule.getTranslation(); + PfxVector3 rayDirL = transformCapsule.getUpper3x3() * ray.m_direction; + + PfxFloat radSqr = cylinder.m_radius * cylinder.m_radius; + + // 始点が円柱の内側にあるか判定 + { + PfxFloat h = fabsf(startPosL[0]); + if(h > cylinder.m_halfLen) h = cylinder.m_halfLen; + PfxVector3 Px(out.m_variable,0,0); + PfxFloat sqrLen = lengthSqr(startPosL-Px); + if(sqrLen <= radSqr) return false; + } + + // 円柱の胴体との交差判定 + do { + PfxVector3 P(startPosL); + PfxVector3 D(rayDirL); + + P[0] = 0.0f; + D[0] = 0.0f; + + PfxFloat a = dot(D,D); + PfxFloat b = dot(P,D); + PfxFloat c = dot(P,P) - radSqr; + + PfxFloat d = b * b - a * c; + + if(d < 0.0f || fabs(a) < 0.00001f) return false; + + PfxFloat tt = ( -b - sqrtf(d) ) / a; + + if(tt < 0.0f) + break; + else if(tt > 1.0f) + return false; + + if(tt < out.m_variable) { + PfxVector3 cp = startPosL + tt * rayDirL; + + if(fabsf(cp[0]) <= cylinder.m_halfLen) { + out.m_contactFlag = true; + out.m_variable = tt; + out.m_contactPoint = PfxVector3(transform * PfxPoint3(cp)); + out.m_contactNormal = transform.getUpper3x3() * normalize(cp); + out.m_subData.m_type = PfxSubData::NONE; + return true; + } + } + } while(0); + + // 円柱の両端にある平面との交差判定 + { + if(fabsf(rayDirL[0]) < 0.00001f) return false; + + PfxFloat t1 = ( cylinder.m_halfLen - startPosL[0] ) / rayDirL[0]; + PfxFloat t2 = ( - cylinder.m_halfLen - startPosL[0] ) / rayDirL[0]; + + PfxFloat tt = SCE_PFX_MIN(t1,t2); + + if(tt < 0.0f || tt > 1.0f) return false; + + PfxVector3 p = startPosL + tt * rayDirL; + p[0] = 0.0f; + + if(lengthSqr(p) < radSqr && tt < out.m_variable) { + PfxVector3 cp = startPosL + tt * rayDirL; + out.m_contactFlag = true; + out.m_variable = tt; + out.m_contactPoint = ray.m_startPosition + tt * ray.m_direction; + out.m_contactNormal = transform.getUpper3x3() * ((cp[0]>0.0f)?PfxVector3(1.0,0.0,0.0):PfxVector3(-1.0,0.0,0.0)); + out.m_subData.m_type = PfxSubData::NONE; + return true; + } + } + + return false; +} +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_cylinder.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_cylinder.h new file mode 100644 index 0000000..ccee5ff --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_cylinder.h @@ -0,0 +1,31 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_INTERSECT_RAYCYLINDER_H +#define _SCE_PFX_INTERSECT_RAYCYLINDER_H + +#include "../../../include/physics_effects/base_level/collision/pfx_ray.h" +#include "../../../include/physics_effects/base_level/collision/pfx_cylinder.h" + +namespace sce { +namespace PhysicsEffects { + +PfxBool pfxIntersectRayCylinder(const PfxRayInput &ray,PfxRayOutput &out,const PfxCylinder &cylinder,const PfxTransform3 &transform); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_INTERSECT_RAYCYLINDER_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_large_tri_mesh.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_large_tri_mesh.cpp new file mode 100644 index 0000000..a1e1c9f --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_large_tri_mesh.cpp @@ -0,0 +1,169 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/collision/pfx_large_tri_mesh.h" +#include "pfx_intersect_common.h" +#include "pfx_mesh_common.h" +#include "pfx_intersect_ray_large_tri_mesh.h" + + +namespace sce { +namespace PhysicsEffects { + + +static SCE_PFX_FORCE_INLINE +PfxBool pfxIntersectRayTriMesh(const PfxTriMesh &mesh,const PfxVector3 &rayStart,const PfxVector3 &rayDir, + PfxUInt32 facetMode,PfxFloat &variable,PfxVector3 &normal,PfxSubData &subData) +{ + bool ret = false; + PfxFloat nearest_t = variable; + PfxVector3 nearest_nml(0.0f); + PfxUInt32 nearest_f = 0; + + for(PfxUInt32 f=0;f pfxGetXMax(aabbB)) continue; + if(aabbMaxL.getY() < pfxGetYMin(aabbB) || aabbMinL.getY() > pfxGetYMax(aabbB)) continue; + if(aabbMaxL.getZ() < pfxGetZMin(aabbB) || aabbMinL.getZ() > pfxGetZMax(aabbB)) continue; + // Todo:早期終了チェック + + PfxVector3 aabbMin,aabbMax; + aabbMin = largeMesh.getWorldPosition(PfxVecInt3((PfxFloat)pfxGetXMin(aabbB),(PfxFloat)pfxGetYMin(aabbB),(PfxFloat)pfxGetZMin(aabbB))); + aabbMax = largeMesh.getWorldPosition(PfxVecInt3((PfxFloat)pfxGetXMax(aabbB),(PfxFloat)pfxGetYMax(aabbB),(PfxFloat)pfxGetZMax(aabbB))); + + PfxFloat tmpVariable = 1.0f; + PfxVector3 tmpNormal; + + if( !pfxIntersectRayAABBFast( + rayStartPosition,rayDirection, + (aabbMax+aabbMin)*0.5f, + (aabbMax-aabbMin)*0.5f, + tmpVariable) ) + continue; + + if( out.m_variable <= tmpVariable ) continue; + + // アイランドとの交差チェック + const PfxTriMesh *island = &largeMesh.m_islands[i]; + + PfxSubData subData; + tmpVariable = out.m_variable; + + if( pfxIntersectRayTriMesh(*island,rayStartPosition,rayDirection,ray.m_facetMode,tmpVariable,tmpNormal,subData) && + tmpVariable < out.m_variable ) { + out.m_contactFlag = true; + out.m_variable = tmpVariable; + out.m_contactPoint = ray.m_startPosition + tmpVariable * ray.m_direction; + out.m_contactNormal = transform.getUpper3x3() * tmpNormal; + subData.setIslandId(i); + out.m_subData = subData; + ret = true; + } + + } + } + + return ret; +} +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_large_tri_mesh.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_large_tri_mesh.h new file mode 100644 index 0000000..5bb4970 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_large_tri_mesh.h @@ -0,0 +1,30 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_INTERSECT_RAYLARGETRIMESH_H +#define _SCE_PFX_INTERSECT_RAYLARGETRIMESH_H + +#include "../../../include/physics_effects/base_level/collision/pfx_ray.h" + +namespace sce { +namespace PhysicsEffects { + +PfxBool pfxIntersectRayLargeTriMesh(const PfxRayInput &ray,PfxRayOutput &out,const void *shape,const PfxTransform3 &transform); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_INTERSECT_RAYLARGETRIMESH_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_sphere.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_sphere.cpp new file mode 100644 index 0000000..6de422b --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_sphere.cpp @@ -0,0 +1,55 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/collision/pfx_sphere.h" +#include "pfx_intersect_common.h" +#include "pfx_intersect_ray_sphere.h" + +namespace sce { +namespace PhysicsEffects { + +PfxBool pfxIntersectRaySphere(const PfxRayInput &ray,PfxRayOutput &out,const PfxSphere &sphere,const PfxTransform3 &transform) +{ + PfxVector3 v = ray.m_startPosition - transform.getTranslation(); + + PfxFloat a = dot(ray.m_direction,ray.m_direction); + PfxFloat b = dot(v,ray.m_direction); + PfxFloat c = dot(v,v) - sphere.m_radius * sphere.m_radius; + + if(c < 0.0f) return false; + + PfxFloat d = b * b - a * c; + + if(d < 0.0f || fabsf(a) < 0.00001f) return false; + + PfxFloat tt = ( -b - sqrtf(d) ) / a; + + if(tt < 0.0f || tt > 1.0f) return false; + + if(tt < out.m_variable) { + out.m_contactFlag = true; + out.m_variable = tt; + out.m_contactPoint = ray.m_startPosition + tt * ray.m_direction; + out.m_contactNormal = normalize(out.m_contactPoint - transform.getTranslation()); + out.m_subData.m_type = PfxSubData::NONE; + return true; + } + + return false; +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_sphere.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_sphere.h new file mode 100644 index 0000000..5df2971 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_intersect_ray_sphere.h @@ -0,0 +1,31 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_INTERSECT_RAYSPHERE_H +#define _SCE_PFX_INTERSECT_RAYSPHERE_H + +#include "../../../include/physics_effects/base_level/collision/pfx_ray.h" +#include "../../../include/physics_effects/base_level/collision/pfx_sphere.h" + +namespace sce { +namespace PhysicsEffects { + +PfxBool pfxIntersectRaySphere(const PfxRayInput &ray,PfxRayOutput &out,const PfxSphere &sphere,const PfxTransform3 &transform); + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_INTERSECT_RAYSPHERE_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_mesh_common.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_mesh_common.h new file mode 100644 index 0000000..bd2d8ff --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_mesh_common.h @@ -0,0 +1,194 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_MESH_COMMON_H +#define _SCE_PFX_MESH_COMMON_H + +#include "../../../include/physics_effects/base_level/base/pfx_common.h" +#include "../../../include/physics_effects/base_level/collision/pfx_tri_mesh.h" + +namespace sce { +namespace PhysicsEffects { + + +struct PfxClosestPoints { + PfxPoint3 pA[4],pB[4]; + PfxFloat distSqr[4]; + PfxFloat closestDistSqr; + int numPoints; + SCE_PFX_PADDING(1,8) + + PfxClosestPoints() + { + numPoints = 0; + closestDistSqr = SCE_PFX_FLT_MAX; + } + + void set(int i,const PfxPoint3 &pointA,const PfxPoint3 &pointB,PfxFloat d) + { + pA[i] = pointA; + pB[i] = pointB; + distSqr[i] = d; + } + + void add(const PfxPoint3 &pointA,const PfxPoint3 &pointB,PfxFloat d) + { + const PfxFloat epsilon = 0.00001f; + if(closestDistSqr < d) return; + + closestDistSqr = d + epsilon; + + int replaceId = -1; + PfxFloat distMax = -SCE_PFX_FLT_MAX; + for(int i=0;im_numFacets;f++) { + const PfxFacet &facet = mesh->m_facets[f]; + + PfxVector3 facetCenter = absPerElem(offsetPos + offsetRot * pfxReadVector3(facet.m_center)); + PfxVector3 halfBA = absOffsetRot * pfxReadVector3(facet.m_half); + + // ConvexBのAABBとチェック + if(facetCenter[0] > (halfBA[0]+aabbHalf[0])) continue; + if(facetCenter[1] > (halfBA[1]+aabbHalf[1])) continue; + if(facetCenter[2] > (halfBA[2]+aabbHalf[2])) continue; + + // この面は判定 + selFacets[numSelFacets++] = (PfxUInt8)f; +} + + return numSelFacets; +} + +static SCE_PFX_FORCE_INLINE +void pfxGetProjAxisPnts6( + const PfxVector3 *verts,const PfxVector3 &axis, + PfxFloat &distMin,PfxFloat &distMax) +{ +PfxFloat p0 = dot(axis, verts[0]); +PfxFloat p1 = dot(axis, verts[1]); +PfxFloat p2 = dot(axis, verts[2]); +PfxFloat p3 = dot(axis, verts[3]); +PfxFloat p4 = dot(axis, verts[4]); +PfxFloat p5 = dot(axis, verts[5]); +distMin = SCE_PFX_MIN(p5,SCE_PFX_MIN(p4,SCE_PFX_MIN(p3,SCE_PFX_MIN(p2,SCE_PFX_MIN(p0,p1))))); +distMax = SCE_PFX_MAX(p5,SCE_PFX_MAX(p4,SCE_PFX_MAX(p3,SCE_PFX_MAX(p2,SCE_PFX_MAX(p0,p1))))); +} + +static SCE_PFX_FORCE_INLINE +void pfxGetProjAxisPnts3( + const PfxVector3 *verts,const PfxVector3 &axis, + PfxFloat &distMin,PfxFloat &distMax) +{ +PfxFloat p0 = dot(axis, verts[0]); +PfxFloat p1 = dot(axis, verts[1]); +PfxFloat p2 = dot(axis, verts[2]); +distMin = SCE_PFX_MIN(p2,SCE_PFX_MIN(p0,p1)); +distMax = SCE_PFX_MAX(p2,SCE_PFX_MAX(p0,p1)); +} + +static SCE_PFX_FORCE_INLINE +void pfxGetProjAxisPnts2( + const PfxVector3 *verts,const PfxVector3 &axis, + PfxFloat &distMin,PfxFloat &distMax) +{ +PfxFloat p0 = dot(axis, verts[0]); +PfxFloat p1 = dot(axis, verts[1]); +distMin = SCE_PFX_MIN(p0,p1); +distMax = SCE_PFX_MAX(p0,p1); +} + +/////////////////////////////////////////////////////////////////////////////// +// 2つのベクトルの向きをチェック + +static SCE_PFX_FORCE_INLINE +bool pfxIsSameDirection(const PfxVector3 &vecA,const PfxVector3 &vecB) +{ +return fabsf(dot(vecA,vecB)) > 0.9999f; +} + +/////////////////////////////////////////////////////////////////////////////// +// 面ローカルの座標を算出 + +static SCE_PFX_FORCE_INLINE +void pfxGetLocalCoords( + const PfxVector3 &pointOnTriangle, + const PfxTriangle &triangle, + PfxFloat &s,PfxFloat &t) +{ + PfxVector3 v0 = triangle.points[1] - triangle.points[0]; + PfxVector3 v1 = triangle.points[2] - triangle.points[0]; + PfxVector3 dir = pointOnTriangle - triangle.points[0]; + PfxVector3 v = cross( v0, v1 ); + PfxVector3 crS = cross( v, v0 ); + PfxVector3 crT = cross( v, v1 ); + s = dot( crT, dir ) / dot( crT, v0 ); + t = dot( crS, dir ) / dot( crS, v1 ); +} + +// a,bからなる直線上に点pがあるかどうかを判定 +static SCE_PFX_FORCE_INLINE +bool pfxPointOnLine(const PfxVector3 &p,const PfxVector3 &a,const PfxVector3 &b) +{ + PfxVector3 ab = normalize(b-a); + PfxVector3 q = a + ab * dot(p-a,ab); + return lengthSqr(p-q) < 0.00001f; +} + +// 線分a,b上に点pがあるかどうかを判定 +static SCE_PFX_FORCE_INLINE +bool pfxPointOnSegment(const PfxVector3 &p,const PfxVector3 &a,const PfxVector3 &b) +{ + PfxVector3 ab = b-a; + PfxVector3 ap = p-a; + PfxFloat denom = dot(ab,ab); + PfxFloat num = dot(ap,ab); + PfxFloat t = num/denom; + if(t < 0.0f || t > 1.0f) return false; + return (dot(ap,ap)-num*t) < 0.00001f; +} + + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_MESH_COMMON_H diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_shape.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_shape.cpp new file mode 100644 index 0000000..0f9ef88 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_shape.cpp @@ -0,0 +1,95 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/collision/pfx_shape.h" + +namespace sce { +namespace PhysicsEffects { +void pfxGetShapeAabbDummy(const PfxShape &shape,PfxVector3 &aabbMin,PfxVector3 &aabbMax) +{ + (void)shape,(void)aabbMin,(void)aabbMax; +} + +void pfxGetShapeAabbSphere(const PfxShape &shape,PfxVector3 &aabbMin,PfxVector3 &aabbMax) +{ + aabbMin = shape.getOffsetPosition() - PfxVector3(shape.getSphere().m_radius); + aabbMax = shape.getOffsetPosition() + PfxVector3(shape.getSphere().m_radius); +} + +void pfxGetShapeAabbBox(const PfxShape &shape,PfxVector3 &aabbMin,PfxVector3 &aabbMax) +{ + PfxVector3 boxSize = absPerElem(PfxMatrix3(shape.getOffsetOrientation())) * shape.getBox().m_half; + aabbMin = shape.getOffsetPosition() - boxSize; + aabbMax = shape.getOffsetPosition() + boxSize; +} + +void pfxGetShapeAabbCapsule(const PfxShape &shape,PfxVector3 &aabbMin,PfxVector3 &aabbMax) +{ + PfxVector3 dir = rotate(shape.getOffsetOrientation(),PfxVector3(1.0f,0.0f,0.0f)); + PfxVector3 capSize = absPerElem(dir) * shape.getCapsule().m_halfLen + + PfxVector3(shape.getCapsule().m_radius); + aabbMin = shape.getOffsetPosition() - capSize; + aabbMax = shape.getOffsetPosition() + capSize; +} + +void pfxGetShapeAabbCylinder(const PfxShape &shape,PfxVector3 &aabbMin,PfxVector3 &aabbMax) +{ + PfxVector3 capSize = absPerElem(PfxMatrix3(shape.getOffsetOrientation())) * + PfxVector3(shape.getCylinder().m_halfLen,shape.getCylinder().m_radius,shape.getCylinder().m_radius); + aabbMin = shape.getOffsetPosition() - capSize; + aabbMax = shape.getOffsetPosition() + capSize; +} + +void pfxGetShapeAabbConvexMesh(const PfxShape &shape,PfxVector3 &aabbMin,PfxVector3 &aabbMax) +{ + const PfxConvexMesh *convex = shape.getConvexMesh(); + PfxVector3 half = absPerElem(PfxMatrix3(shape.getOffsetOrientation())) * convex->m_half; + aabbMin = shape.getOffsetPosition() - half; + aabbMax = shape.getOffsetPosition() + half; +} + +void pfxGetShapeAabbLargeTriMesh(const PfxShape &shape,PfxVector3 &aabbMin,PfxVector3 &aabbMax) +{ + const PfxLargeTriMesh *largemesh = shape.getLargeTriMesh(); + PfxVector3 half = absPerElem(PfxMatrix3(shape.getOffsetOrientation())) * largemesh->m_half; + aabbMin = shape.getOffsetPosition() - half; + aabbMax = shape.getOffsetPosition() + half; +} + +typedef void (*PfxFuncGetShapeAabb)(const PfxShape &shape,PfxVector3 &aabbMin,PfxVector3 &aabbMax); + +PfxFuncGetShapeAabb pfxFuncGetShapeAabb[kPfxShapeCount] = { + pfxGetShapeAabbSphere, + pfxGetShapeAabbBox, + pfxGetShapeAabbCapsule, + pfxGetShapeAabbCylinder, + pfxGetShapeAabbConvexMesh, + pfxGetShapeAabbLargeTriMesh, + pfxGetShapeAabbDummy, + pfxGetShapeAabbDummy, + pfxGetShapeAabbDummy, + pfxGetShapeAabbDummy, + pfxGetShapeAabbDummy, + pfxGetShapeAabbDummy, +}; + +void PfxShape::getAabb(PfxVector3 &aabbMin,PfxVector3 &aabbMax) const +{ + return pfxFuncGetShapeAabb[m_type](*this,aabbMin,aabbMax); +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_simplex_solver.cpp b/Extras/PhysicsEffects/src/base_level/collision/pfx_simplex_solver.cpp new file mode 100644 index 0000000..197555d --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_simplex_solver.cpp @@ -0,0 +1,284 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "pfx_simplex_solver.h" +#include "pfx_gjk_solver.h" + +namespace sce { +namespace PhysicsEffects { +inline static +bool operator ==(const PfxVector3 &a,const PfxVector3 &b) +{ + return lengthSqr(a-b) < (SCE_PFX_GJK_EPSILON * SCE_PFX_GJK_EPSILON); +} + +bool PfxSimplexSolver::closest(PfxVector3& v) +{ + bool ret = false; + + bc.reset(); + + switch(numVertices) { + case 0: + ret = false; + break; + + case 1: + { + PfxVector3 tmpP = P[0]; + PfxVector3 tmpQ = Q[0]; + v = tmpP-tmpQ; + bc.reset(); + bc.setBarycentricCoordinates(1.0f,0.0f,0.0f,0.0f); + ret = bc.isValid(); + } + break; + + case 2: + { + PfxVector3 dir = W[1] - W[0]; + PfxFloat t = dot(-W[0],dir) / dot(dir,dir); + + if(t < 0.0f) t = 0.0f; + if(t > 1.0f) t = 1.0f; + + bc.setBarycentricCoordinates(1-t,t,0.0f,0.0f); + + PfxVector3 tmpP = P[0] + t * (P[1] - P[0]); + PfxVector3 tmpQ = Q[0] + t * (Q[1] - Q[0]); + v = tmpP - tmpQ; + + reduceVertices(); + + ret = bc.isValid(); + break; + } + + case 3: + { + const PfxVector3& a = W[0]; + const PfxVector3& b = W[1]; + const PfxVector3& c = W[2]; + + closestPointTriangleFromOrigin(a,b,c,bc); + + PfxVector3 tmpP = P[0] * bc.barycentricCoords[0] + + P[1] * bc.barycentricCoords[1] + + P[2] * bc.barycentricCoords[2]; + + PfxVector3 tmpQ = Q[0] * bc.barycentricCoords[0] + + Q[1] * bc.barycentricCoords[1] + + Q[2] * bc.barycentricCoords[2]; + + v = tmpP-tmpQ; + + reduceVertices(); + ret = bc.isValid(); + break; + } + + case 4: + { + const PfxVector3& a = W[0]; + const PfxVector3& b = W[1]; + const PfxVector3& c = W[2]; + const PfxVector3& d = W[3]; + + if(closestPointTetrahedronFromOrigin(a,b,c,d,bc)) { + PfxVector3 tmpP = P[0] * bc.barycentricCoords[0] + + P[1] * bc.barycentricCoords[1] + + P[2] * bc.barycentricCoords[2] + + P[3] * bc.barycentricCoords[3]; + + PfxVector3 tmpQ = Q[0] * bc.barycentricCoords[0] + + Q[1] * bc.barycentricCoords[1] + + Q[2] * bc.barycentricCoords[2] + + Q[3] * bc.barycentricCoords[3]; + v = tmpP-tmpQ; + + reduceVertices(); + ret = bc.isValid(); + } else { + // 原点が内部に存在→交差している + ret = true; + v = PfxVector3(0.0f); + } + break; + } + }; + + return ret; +} + +bool PfxSimplexSolver::inSimplex(const PfxVector3& w) +{ + for(int i=0;i= 0.0f && d4 <= d3) { + result.closest = b; + result.setBarycentricCoordinates(0.0f,1.0f,0.0f,0.0f); + return true; + } + + PfxFloat vc = d1*d4 - d3*d2; + if(vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) { + PfxFloat v = d1 / (d1 - d3); + result.closest = a + v * ab; + result.setBarycentricCoordinates(1.0f-v,v,0.0f,0.0f); + return true; + } + + PfxVector3 cp = p - c; + PfxFloat d5 = dot(ab,cp); + PfxFloat d6 = dot(ac,cp); + if(d6 >= 0.0f && d5 <= d6) { + result.closest = c; + result.setBarycentricCoordinates(0.0f,0.0f,1.0f,0.0f); + return true; + } + + PfxFloat vb = d5*d2 - d1*d6; + if(vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) { + PfxFloat w = d2 / (d2 - d6); + result.closest = a + w * ac; + result.setBarycentricCoordinates(1.0f-w,0.0f,w,0.0f); + return true; + } + + PfxFloat va = d3*d6 - d5*d4; + if(va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) { + PfxFloat w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); + result.closest = b + w * (c - b); + result.setBarycentricCoordinates(0.0f,1.0f-w,w,0.0f); + return true; + } + + PfxFloat denom = PfxFloat(1.0) / (va + vb + vc); + PfxFloat v = vb * denom; + PfxFloat w = vc * denom; + + result.closest = a + ab * v + ac * w; + result.setBarycentricCoordinates(1.0f-v-w,v,w,0.0f); + + return true; +} + +bool PfxSimplexSolver::closestPointTetrahedronFromOrigin(const PfxVector3 &a,const PfxVector3 &b,const PfxVector3 &c,const PfxVector3 &d,PfxBarycentricCoords& finalResult) +{ + PfxBarycentricCoords tempResult; + PfxVector3 p(0.0f); + + finalResult.closest = p; + finalResult.usedVertices = 0; + + bool pointOutsideABC = originOutsideOfPlane(a, b, c, d); + bool pointOutsideACD = originOutsideOfPlane(a, c, d, b); + bool pointOutsideADB = originOutsideOfPlane(a, d, b, c); + bool pointOutsideBDC = originOutsideOfPlane(b, d, c, a); + + if(!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC) + return false; + + PfxFloat bestSqDist = SCE_PFX_FLT_MAX; + + if(pointOutsideABC) { + closestPointTriangleFromOrigin(a, b, c,tempResult); + PfxVector3 q = tempResult.closest; + PfxFloat sqDist = dot((q - p),(q - p)); + if(sqDist < bestSqDist) { + bestSqDist = sqDist; + finalResult.closest = q; + finalResult.setBarycentricCoordinates( + tempResult.barycentricCoords[0], + tempResult.barycentricCoords[1], + tempResult.barycentricCoords[2], + 0); + } + } + + if(pointOutsideACD) { + closestPointTriangleFromOrigin(a, c, d,tempResult); + PfxVector3 q = tempResult.closest; + PfxFloat sqDist = dot((q - p),(q - p)); + if(sqDist < bestSqDist) { + bestSqDist = sqDist; + finalResult.closest = q; + finalResult.setBarycentricCoordinates( + tempResult.barycentricCoords[0], + 0, + tempResult.barycentricCoords[1], + tempResult.barycentricCoords[2]); + } + } + + if(pointOutsideADB) { + closestPointTriangleFromOrigin(a, d, b,tempResult); + PfxVector3 q = tempResult.closest; + PfxFloat sqDist = dot((q - p),(q - p)); + if(sqDist < bestSqDist) { + bestSqDist = sqDist; + finalResult.closest = q; + finalResult.setBarycentricCoordinates( + tempResult.barycentricCoords[0], + tempResult.barycentricCoords[2], + 0, + tempResult.barycentricCoords[1]); + } + } + + if(pointOutsideBDC) { + closestPointTriangleFromOrigin(b, d, c,tempResult); + PfxVector3 q = tempResult.closest; + PfxFloat sqDist = dot((q - p),(q - p)); + if(sqDist < bestSqDist) { + bestSqDist = sqDist; + finalResult.closest = q; + finalResult.setBarycentricCoordinates( + 0, + tempResult.barycentricCoords[0], + tempResult.barycentricCoords[2], + tempResult.barycentricCoords[1]); + } + } + + return true; +} +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/collision/pfx_simplex_solver.h b/Extras/PhysicsEffects/src/base_level/collision/pfx_simplex_solver.h new file mode 100644 index 0000000..a8aa1a5 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/collision/pfx_simplex_solver.h @@ -0,0 +1,153 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_SIMPLEX_SOLVER_H +#define _SCE_PFX_SIMPLEX_SOLVER_H + +#include "../../../include/physics_effects/base_level/base/pfx_common.h" + +namespace sce { +namespace PhysicsEffects { + + +/////////////////////////////////////////////////////////////////////////////// +// Voronoi Simplex Solver + +struct SCE_PFX_ALIGNED(16) PfxBarycentricCoords { + PfxVector3 closest; +PfxFloat barycentricCoords[4]; + unsigned int usedVertices; + SCE_PFX_PADDING(1,12) + + void reset() + { + barycentricCoords[0] = 0.0f; + barycentricCoords[1] = 0.0f; + barycentricCoords[2] = 0.0f; + barycentricCoords[3] = 0.0f; + usedVertices = 0; + } + + bool isValid() + { + return (barycentricCoords[0] >= 0.0f) && + (barycentricCoords[1] >= 0.0f) && + (barycentricCoords[2] >= 0.0f) && + (barycentricCoords[3] >= 0.0f); + } + +void setBarycentricCoordinates(PfxFloat a,PfxFloat b,PfxFloat c,PfxFloat d) +{ + barycentricCoords[0] = a; + barycentricCoords[1] = b; + barycentricCoords[2] = c; + barycentricCoords[3] = d; + if(a != 0.0f) usedVertices |= 1<<3; + if(b != 0.0f) usedVertices |= 1<<2; + if(c != 0.0f) usedVertices |= 1<<1; + if(d != 0.0f) usedVertices |= 1; +} +}; + +class PfxSimplexSolver { +private: + static const int MAX_VERTS = 4; + +public: + int numVertices; + SCE_PFX_PADDING(1,12) + PfxVector3 W[MAX_VERTS]; + PfxVector3 P[MAX_VERTS]; + PfxVector3 Q[MAX_VERTS]; + + PfxBarycentricCoords bc; + + inline void removeVertex(int index); + inline void reduceVertices (); + + inline bool originOutsideOfPlane(const PfxVector3& a, const PfxVector3& b, const PfxVector3& c, const PfxVector3& d); + bool closestPointTetrahedronFromOrigin(const PfxVector3 &a,const PfxVector3 &b,const PfxVector3 &c,const PfxVector3 &d, PfxBarycentricCoords& result); + bool closestPointTriangleFromOrigin(const PfxVector3 &a,const PfxVector3 &b,const PfxVector3 &c,PfxBarycentricCoords& result); + +public: + void reset() + { + numVertices = 0; + bc.reset(); + } + + inline void addVertex(const PfxVector3& w_, const PfxVector3& p_, const PfxVector3& q_); + + bool closest(PfxVector3& v); + + bool fullSimplex() const + { + return (numVertices == 4); + } + + bool inSimplex(const PfxVector3& w); +}; + +inline +void PfxSimplexSolver::removeVertex(int index) +{ + SCE_PFX_ASSERT(numVertices>0); + numVertices--; + W[index] = W[numVertices]; + P[index] = P[numVertices]; + Q[index] = Q[numVertices]; +} + +inline +void PfxSimplexSolver::reduceVertices () +{ + if ((numVertices >= 4) && (!(bc.usedVertices&0x01))) + removeVertex(3); + + if ((numVertices >= 3) && (!(bc.usedVertices&0x02))) + removeVertex(2); + + if ((numVertices >= 2) && (!(bc.usedVertices&0x04))) + removeVertex(1); + + if ((numVertices >= 1) && (!(bc.usedVertices&0x08))) + removeVertex(0); +} + +inline +void PfxSimplexSolver::addVertex(const PfxVector3& w, const PfxVector3& p, const PfxVector3& q) +{ + W[numVertices] = w; + P[numVertices] = p; + Q[numVertices] = q; + numVertices++; +} + +inline +bool PfxSimplexSolver::originOutsideOfPlane(const PfxVector3& a, const PfxVector3& b, const PfxVector3& c, const PfxVector3& d) +{ + PfxVector3 normal = cross((b-a),(c-a)); + + PfxFloat signp = dot(-a,normal); + PfxFloat signd = dot((d - a),normal); + + return signp * signd < 0.0f; +} + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_SIMPLEX_SOLVER_H diff --git a/Extras/PhysicsEffects/src/base_level/premake4.lua b/Extras/PhysicsEffects/src/base_level/premake4.lua new file mode 100644 index 0000000..112a875 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/premake4.lua @@ -0,0 +1,12 @@ + project "physicseffects2_baselevel" + + kind "StaticLib" + targetdir "../../build/lib" + includedirs { + ".", + } + files { + "**.cpp", + "../../include/physics_effects/base_level/**.h" + + } \ No newline at end of file diff --git a/Extras/PhysicsEffects/src/base_level/solver/pfx_check_solver.h b/Extras/PhysicsEffects/src/base_level/solver/pfx_check_solver.h new file mode 100644 index 0000000..417998b --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/solver/pfx_check_solver.h @@ -0,0 +1,67 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CHECK_SOLVER_H_ +#define _SCE_PFX_CHECK_SOLVER_H_ + +#include "../../../include/physics_effects/base_level/rigidbody/pfx_rigid_state.h" +#include "../../../include/physics_effects/base_level/solver/pfx_constraint_pair.h" + +namespace sce { +namespace PhysicsEffects { + +// Solver check table +/* + -----------------MotionTypeA + |0 1 0 1 0 + |1 1 1 1 0 + |0 1 0 1 0 + |1 1 1 0 0 + |0 0 0 0 0 +MotionTypeB + */ + +static SCE_PFX_FORCE_INLINE +PfxBool pfxCheckSolverTable(ePfxMotionType i,ePfxMotionType j) +{ + const PfxUInt32 solverTable = 0x00af2b80; + + SCE_PFX_ASSERT(i < kPfxMotionTypeCount); + SCE_PFX_ASSERT(j < kPfxMotionTypeCount); + + PfxUInt32 idx = j * kPfxMotionTypeCount + i; + PfxUInt32 mask = 1 << (kPfxMotionTypeCount*kPfxMotionTypeCount-1-idx); + return (solverTable & mask) != 0; +} + +static SCE_PFX_FORCE_INLINE +PfxBool pfxCheckSolver(const PfxConstraintPair &pair) +{ + PfxUInt32 motionA = pfxGetMotionMaskA(pair)&SCE_PFX_MOTION_MASK_TYPE; + PfxUInt32 motionB = pfxGetMotionMaskB(pair)&SCE_PFX_MOTION_MASK_TYPE; + PfxUInt32 sleepA = pfxGetMotionMaskA(pair)&SCE_PFX_MOTION_MASK_SLEEPING; + PfxUInt32 sleepB = pfxGetMotionMaskB(pair)&SCE_PFX_MOTION_MASK_SLEEPING; + + return + pfxGetActive(pair) && + pfxCheckSolverTable((ePfxMotionType)motionA,(ePfxMotionType)motionB) && // モーションタイプ別衝突判定テーブル + !((sleepA != 0 && sleepB != 0) || (sleepA != 0 && motionB == kPfxMotionTypeFixed) || (sleepB != 0 && motionA == kPfxMotionTypeFixed));// スリープ時のチェック +} + +} //namespace PhysicsEffects +} //namespace sce + +#endif /* _SCE_PFX_CHECK_SOLVER_H_ */ diff --git a/Extras/PhysicsEffects/src/base_level/solver/pfx_constraint_row_solver.h b/Extras/PhysicsEffects/src/base_level/solver/pfx_constraint_row_solver.h new file mode 100644 index 0000000..146fc41 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/solver/pfx_constraint_row_solver.h @@ -0,0 +1,296 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_CONSTRAINT_ROW_SOLVER_H +#define _SCE_PFX_CONSTRAINT_ROW_SOLVER_H + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "../../../include/physics_effects/base_level/solver/pfx_constraint_row.h" +#include "../../../include/physics_effects/base_level/solver/pfx_joint_constraint.h" + +namespace sce { +namespace PhysicsEffects { + +/////////////////////////////////////////////////////////////////////////////// +// Constraint Row Solver + +// ARA begin insert new code +#ifdef __ARM_NEON__ +// prototype for inline NEON assembly version +void pfxSolveLinearConstraintRowNEON(PfxConstraintRow &constraint, + PfxVector3 &deltaLinearVelocityA,PfxVector3 &deltaAngularVelocityA, + PfxFloat &massInvA,const PfxMatrix3 &inertiaInvA,const PfxVector3 &rA, + PfxVector3 &deltaLinearVelocityB,PfxVector3 &deltaAngularVelocityB, + PfxFloat &massInvB,const PfxMatrix3 &inertiaInvB,const PfxVector3 &rB); +#endif // __ARM_NEON__ +// ARA end + +static SCE_PFX_FORCE_INLINE +void pfxSolveLinearConstraintRow(PfxConstraintRow &constraint, + PfxVector3 &deltaLinearVelocityA,PfxVector3 &deltaAngularVelocityA, + PfxFloat massInvA,const PfxMatrix3 &inertiaInvA,const PfxVector3 &rA, + PfxVector3 &deltaLinearVelocityB,PfxVector3 &deltaAngularVelocityB, + PfxFloat massInvB,const PfxMatrix3 &inertiaInvB,const PfxVector3 &rB) +{ +const PfxVector3 normal(pfxReadVector3(constraint.m_normal)); +PfxFloat deltaImpulse = constraint.m_rhs; +PfxVector3 dVA = deltaLinearVelocityA + cross(deltaAngularVelocityA,rA); +PfxVector3 dVB = deltaLinearVelocityB + cross(deltaAngularVelocityB,rB); +deltaImpulse -= constraint.m_jacDiagInv * dot(normal,dVA-dVB); +PfxFloat oldImpulse = constraint.m_accumImpulse; +constraint.m_accumImpulse = SCE_PFX_CLAMP(oldImpulse + deltaImpulse,constraint.m_lowerLimit,constraint.m_upperLimit); +deltaImpulse = constraint.m_accumImpulse - oldImpulse; +deltaLinearVelocityA += deltaImpulse * massInvA * normal; +deltaAngularVelocityA += deltaImpulse * inertiaInvA * cross(rA,normal); +deltaLinearVelocityB -= deltaImpulse * massInvB * normal; +deltaAngularVelocityB -= deltaImpulse * inertiaInvB * cross(rB,normal); +} + +static SCE_PFX_FORCE_INLINE +void pfxSolveAngularConstraintRow(PfxConstraintRow &constraint, + PfxVector3 &deltaAngularVelocityA, + const PfxMatrix3 &inertiaInvA,const PfxVector3 &rA, + PfxVector3 &deltaAngularVelocityB, + const PfxMatrix3 &inertiaInvB,const PfxVector3 &rB) +{ + (void)rA,(void)rB; +const PfxVector3 normal(pfxReadVector3(constraint.m_normal)); +PfxFloat deltaImpulse = constraint.m_rhs; +deltaImpulse -= constraint.m_jacDiagInv * dot(normal,deltaAngularVelocityA-deltaAngularVelocityB); +PfxFloat oldImpulse = constraint.m_accumImpulse; +constraint.m_accumImpulse = SCE_PFX_CLAMP(oldImpulse + deltaImpulse,constraint.m_lowerLimit,constraint.m_upperLimit); +deltaImpulse = constraint.m_accumImpulse - oldImpulse; +deltaAngularVelocityA += deltaImpulse * inertiaInvA * normal; +deltaAngularVelocityB -= deltaImpulse * inertiaInvB * normal; +} + + +/////////////////////////////////////////////////////////////////////////////// +// Calc Joint Angle + +static SCE_PFX_FORCE_INLINE +void pfxCalcJointAngleSwingTwist(PfxMatrix3 &worldFrameA,PfxMatrix3 &worldFrameB,PfxFloat *angle,PfxVector3 *axis) +{ + // フレームA座標系への変換マトリクス + PfxMatrix3 frameBA = transpose(worldFrameA) * worldFrameB; + + // クォータニオン回転をtwistとswingに分離 + PfxQuat swing,twist,qBA(frameBA); + swing = PfxQuat::rotation(PfxVector3(1.0f,0.0f,0.0f),frameBA.getCol0()); + twist = qBA * conj(swing); + + if(dot(twist,PfxQuat::rotationX(0.0f)) < 0.0f) { + twist = -twist; + } + + // それぞれの回転軸と回転角度を算出 + pfxGetRotationAngleAndAxis(normalize(twist),angle[0],axis[0]); + pfxGetRotationAngleAndAxis(normalize(swing),angle[1],axis[1]); + + if(angle[1] < 0.00001f) { + axis[1] = PfxVector3(0.0f,1.0f,0.0f); + } + + // twistの軸方向のチェック + if(dot(axis[0],frameBA.getCol0()) < 0.0f) { + angle[0] = -angle[0]; + } + + axis[0] = worldFrameB.getCol0(); + axis[1] = worldFrameA * axis[1]; + axis[2] = cross(axis[0],axis[1]); + angle[2] = 0.0f; +} + +static SCE_PFX_FORCE_INLINE +void pfxCalcJointAngleSwing1Swing2Twist(PfxMatrix3 &worldFrameA,PfxMatrix3 &worldFrameB,PfxFloat *angle,PfxVector3 *axis) +{ + // フレームA座標系への変換マトリクス + PfxMatrix3 frameBA = transpose(worldFrameA) * worldFrameB; + + // クォータニオン回転をtwistとswingに分離 + PfxQuat swing,twist,qBA(frameBA); + swing = PfxQuat::rotation(PfxVector3(1.0f,0.0f,0.0f),frameBA.getCol0()); + twist = qBA * conj(swing); + + if(dot(twist,PfxQuat::rotationX(0.0f)) < 0.0f) { + twist = -twist; + } + + PfxQuat swing1,swing2; + + PfxVector3 pXY = frameBA.getCol0();pXY[2] = 0.0f; + PfxVector3 pXZ = frameBA.getCol0();pXZ[1] = 0.0f; + + if(fabsf(frameBA.getCol0()[1]) < fabsf(frameBA.getCol0()[2])) { + swing1 = PfxQuat::rotation(PfxVector3(1.0f,0.0f,0.0f),pXZ); + swing2 = swing * conj(swing1); + } + else { + swing2 = PfxQuat::rotation(PfxVector3(1.0f,0.0f,0.0f),pXY); + swing1 = conj(swing2) * swing; + } + + // それぞれの回転軸と回転角度を算出 + pfxGetRotationAngleAndAxis(normalize(twist),angle[0],axis[0]); + pfxGetRotationAngleAndAxis(normalize(swing2),angle[1],axis[1]); + pfxGetRotationAngleAndAxis(normalize(swing1),angle[2],axis[2]); + + if(angle[1] < 0.00001f) { + angle[1] = 0.0f; + axis[1] = PfxVector3(0.0f,1.0f,0.0f); + } + + if(angle[2] < 0.00001f) { + angle[2] = 0.0f; + axis[2] = PfxVector3(0.0f,0.0f,1.0f); + } + + // twistの軸方向のチェック + if(dot(axis[0],frameBA.getCol0()) < 0.0f) { + angle[0] = -angle[0]; + } + + axis[0] = worldFrameB.getCol0(); + axis[1] = worldFrameA * axis[1]; + axis[2] = worldFrameA * axis[2]; +} + +static SCE_PFX_FORCE_INLINE +void pfxCalcJointAngleUniversal(PfxMatrix3 &worldFrameA,PfxMatrix3 &worldFrameB,PfxFloat *angle,PfxVector3 *axis) +{ + // フレームA座標系への変換マトリクス + PfxMatrix3 frameBA = transpose(worldFrameA) * worldFrameB; + + // クォータニオン回転をtwistとswingに分離 + PfxQuat swing,swing1,swing2,twist,qBA(frameBA); + PfxVector3 Pxy(frameBA.getCol0()); + Pxy[2] = 0.0f; + swing1 = PfxQuat::rotation(PfxVector3(1.0f,0.0f,0.0f),normalize(Pxy)); + swing = PfxQuat::rotation(PfxVector3(1.0f,0.0f,0.0f),frameBA.getCol0()); + swing2 = swing * conj(swing1); + twist = conj(swing) * qBA; + + if(dot(twist,PfxQuat::rotationX(0.0f)) < 0.0f) { + twist = -twist; + } + + pfxGetRotationAngleAndAxis(normalize(twist),angle[0],axis[0]); + pfxGetRotationAngleAndAxis(normalize(swing1),angle[1],axis[1]); + pfxGetRotationAngleAndAxis(normalize(swing2),angle[2],axis[2]); + + if(axis[1].getZ() < 0.0f) { + axis[1] = -axis[1]; + angle[1] = -angle[1]; + } + + PfxVector3 chkY = cross(PfxVector3(0.0f,0.0f,1.0f),frameBA.getCol0()); + if(dot(chkY,axis[2]) < 0.0f) { + axis[2] = -axis[2]; + angle[2] = -angle[2]; + } + + // twistの軸方向のチェック + if(dot(axis[0],frameBA.getCol0()) < 0.0f) { + angle[0] = -angle[0]; + } + + axis[0] = worldFrameB.getCol0(); + axis[1] = worldFrameA * axis[1]; + axis[2] = worldFrameA * axis[2]; +} + +/////////////////////////////////////////////////////////////////////////////// +// Calc Joint Limit + +static SCE_PFX_FORCE_INLINE +void pfxCalcLinearLimit( + const PfxJointConstraint &jointConstraint, + PfxFloat &posErr,PfxFloat &velocityAmp,PfxFloat &lowerLimit,PfxFloat &upperLimit) +{ + switch(jointConstraint.m_lock) { + case SCE_PFX_JOINT_LOCK_FREE: + posErr = 0.0f; + velocityAmp *= jointConstraint.m_damping; + break; + + case SCE_PFX_JOINT_LOCK_LIMIT: + if(posErr >= jointConstraint.m_movableLowerLimit && posErr <= jointConstraint.m_movableUpperLimit) { + posErr = 0.0f; + velocityAmp *= jointConstraint.m_damping; + } + else { + if(posErr < jointConstraint.m_movableLowerLimit) { + posErr = posErr - jointConstraint.m_movableLowerLimit; + posErr = SCE_PFX_MIN(0.0f,posErr+SCE_PFX_JOINT_LINEAR_SLOP); + upperLimit = SCE_PFX_MIN(0.0f,upperLimit); + velocityAmp = 1.0f; + } + else { // posErr > movableUpperLimit + posErr = posErr - jointConstraint.m_movableUpperLimit; + posErr = SCE_PFX_MAX(0.0f,posErr-SCE_PFX_JOINT_LINEAR_SLOP); + lowerLimit = SCE_PFX_MAX(0.0f,lowerLimit); + velocityAmp = 1.0f; + } + } + break; + + default: // SCE_PFX_JOINT_LOCK_FIX + break; + } +} + +static SCE_PFX_FORCE_INLINE +void pfxCalcAngularLimit( + const PfxJointConstraint &jointConstraint, + PfxFloat &posErr,PfxFloat &velocityAmp,PfxFloat &lowerLimit,PfxFloat &upperLimit) +{ + switch(jointConstraint.m_lock) { + case SCE_PFX_JOINT_LOCK_FREE: + posErr = 0.0f; + velocityAmp *= jointConstraint.m_damping; + break; + + case SCE_PFX_JOINT_LOCK_LIMIT: + if(posErr >= jointConstraint.m_movableLowerLimit && posErr <= jointConstraint.m_movableUpperLimit) { + posErr = 0.0f; + velocityAmp *= jointConstraint.m_damping; + } + else { + if(posErr < jointConstraint.m_movableLowerLimit) { + posErr = posErr - jointConstraint.m_movableLowerLimit; + posErr = SCE_PFX_MIN(0.0f,posErr+SCE_PFX_JOINT_ANGULAR_SLOP); + upperLimit = SCE_PFX_MIN(0.0f,upperLimit); + velocityAmp = 1.0f; + } + else { // posErr > movableUpperLimit + posErr = posErr - jointConstraint.m_movableUpperLimit; + posErr = SCE_PFX_MAX(0.0f,posErr-SCE_PFX_JOINT_ANGULAR_SLOP); + lowerLimit = SCE_PFX_MAX(0.0f,lowerLimit); + velocityAmp = 1.0f; + } + } + break; + + default: // SCE_PFX_JOINT_LOCK_FIX + break; + } +} + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_CONSTRAINT_ROW_SOLVER_H diff --git a/Extras/PhysicsEffects/src/base_level/solver/pfx_constraint_row_solver_neon.cpp b/Extras/PhysicsEffects/src/base_level/solver/pfx_constraint_row_solver_neon.cpp new file mode 100644 index 0000000..c07a144 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/solver/pfx_constraint_row_solver_neon.cpp @@ -0,0 +1,186 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ +#ifdef __ANDROID__ + +#include "../../../include/physics_effects.h" +#include + +namespace sce { +namespace PhysicsEffects { + +//---------------------------------------------------------------------------- +// pfxSolveLinearConstraintRowNEON +// +/// NEON inline assembly implementation of the pfxSolveLinearConstraintRow +/// function. +/// +/// @param constraint Constraint row to be solved +/// @param deltaLinearVelocityA Change in linear velocity for object A +/// @param deltaAngularVelocityA Change in angular velocity for object A +/// @param massInvA Mass inverse for object A +/// @param inertiaInvA Inertia tensor inverse for object A +/// @param rA Position of contact point for object A +/// @param deltaLinearVelocityB Change in linear velocity for object B +/// @param deltaAngularVelocityB Change in angular velocity for object B +/// @param massInvB Mass inverse for object B +/// @param inertiaInvB Inertia tensor inverse for object B +/// @param rB Position of contact point for object B +//---------------------------------------------------------------------------- +//GSR version +void pfxSolveLinearConstraintRowNEON(PfxConstraintRow &constraint, + PfxVector3 &deltaLinearVelocityA,PfxVector3 &deltaAngularVelocityA, + PfxFloat &massInvA,const PfxMatrix3 &inertiaInvA,const PfxVector3 &rA, + PfxVector3 &deltaLinearVelocityB,PfxVector3 &deltaAngularVelocityB, + PfxFloat &massInvB,const PfxMatrix3 &inertiaInvB,const PfxVector3 &rB) +{ + asm volatile + ( + //Loads beforehand so the normal vector will be able to have zero in the 4th element + "vld1.32 {q0}, [%1] \n\t" //LOAD => deltaLinearVelocityA ----------------> q0 + "vld1.32 {q1}, [%2] \n\t" //LOAD => deltaAngularVelocityA ---------------> q1 + "vld1.32 {q2}, [%6] \n\t" //LOAD => deltaLinearVelocityB ----------------> q2 + "vld1.32 {q3}, [%7] \n\t" //LOAD => deltaAngularVelocityB ---------------> q3 + //const PfxVector3 normal(pfxReadVector3(constraint.m_normal)); + "vld1.32 {q4}, [%0]! \n\t" //LOAD => constraint normal--------------------> q4 + "vdup.32 d10, d1[1] \n\t" //set 4th element on normal vector to zero. It is zero since q0 holds a vec3...d1[1] is 4th element and on C++ side we set this to zero + "vtrn.32 d9, d10 \n\t" //LOAD => deltaImpulse ------------------------> q5 (d10[0] only) + //PfxFloat deltaImpulse = constraint.m_rhs; + "vld1.32 {d12}, [%0]! \n\t" //LOAD => constraint variables ----------------> q6 + "vld1.32 {d13[0]}, [%0]! \n\t" //constraint variables + "vld1.32 {d13[1]}, [%0] \n\t" //constraint load of remaining variables loaded this way keep pointer to m_accumulate in order to store back in later + //PfxVector3 dVA = deltaLinearVelocityA + cross(deltaAngularVelocityA,rA); + //PfxVector3 dVB = deltaLinearVelocityB + cross(deltaAngularVelocityB,rB); + "vld1.32 {d14[1]}, [%5] \n\t" //LOAD => rA for cross product use 1A ---------> q7 (save these for use later) + "vld1.32 {d18[1]}, [%10] \n\t" //LOAD => rB for cross product use 1B ---------> q9 + "vld1.32 {d17[0]}, [%5]! \n\t" //LOAD => rA for cross product use 2A ---------> q8 + "vld1.32 {d21[0]}, [%10]! \n\t" //LOAD => rB for cross product use 2B ---------> q10 + "vld1.32 {d16}, [%5] \n\t" //rA 2 + "vld1.32 {d20}, [%10] \n\t" //rB 2 + "vld1.32 {d15[0]}, [%5]! \n\t" //rA 1 + "vld1.32 {d19[0]}, [%10]! \n\t" //rB 1 + "vld1.32 {d14[0]}, [%5]! \n\t" //rA 1 + "vld1.32 {d18[0]}, [%10]! \n\t" //rB 1 + "vld1.32 {d15[1]}, [%5] \n\t" //rA 1 + "vld1.32 {d19[1]}, [%10] \n\t" //rB 1 + "vld1.32 {d17[1]}, [%5]! \n\t" //rA 2 + "vld1.32 {d21[1]}, [%10]! \n\t" //rB 2 + "vmov.f32 q14, q1 \n\t" + "vmov.f32 q13, q3 \n\t" + "vmov.f32 q15, q1 \n\t" + "vmov.f32 q12, q3 \n\t" + "vrev64.32 d28, d28 \n\t" //set deltaAngularVelocityA 1 + "vtrn.32 d28, d29 \n\t" //set deltaAngularVelocityA 1 + "vrev64.32 d26, d26 \n\t" //set deltaAngularVelocityB 1 + "vmul.f32 q14, q7, q14 \n\t" //operation for cross product 1A + "vtrn.32 d26, d27 \n\t" //set deltaAngularVelocityB 1 + "vtrn.32 d30, d31 \n\t" //set deltaAngularVelocityA 2 + "vmul.f32 q13, q9, q13 \n\t" //operation for cross product 1B + "vtrn.32 d24, d25 \n\t" //set deltaAngularVelocityB 2 + "vrev64.32 d30, d30 \n\t" //set deltaAngularVelocityA 2 + "vrev64.32 d24, d24 \n\t" //set deltaAngularVelocityB 2 + "vmls.f32 q14, q8, q15 \n\t" //operation for cross product 2A + "vmls.f32 q13, q10, q12 \n\t" //operation for cross product 2B + "vadd.f32 q14, q14, q0 \n\t" //operation for adding cross to linearVelocityA + "vadd.f32 q13, q13, q2 \n\t" //operation for adding cross to linearVelocityB + //LOAD => dVA --------------------------------> q14 + //LOAD => dVB --------------------------------> q13 + //FREE q11, q12, q15, d11 + //deltaImpulse -= constraint.m_jacDiagInv * dot(normal,dVA-dVB); + "vsub.f32 q11, q14, q13 \n\t" //TEMP q11 => dVA-dVB for dot product + "vmul.f32 q11, q11, q4 \n\t" //operation for dot product + "vpadd.f32 d22, d22, d22 \n\t" //operation for dot product + "vpadd.f32 d23, d23, d23 \n\t" //operation for dot product + "vadd.f32 d22, d22, d23 \n\t" //operation for dot product + "vmul.f32 d22, d22, d12[0] \n\t" //m_jacDiagInv times dot product result + "vsub.f32 d10, d10, d22 \n\t" //subtract result from deltaImpule + //PfxFloat oldImpulse = constraint.m_accumImpulse; + "vdup.32 d11, d13[1] \n\t" //LOAD => oldImpulse -------------------------> q5 (d11 only) + //constraint.m_accumImpulse = SCE_PFX_CLAMP(oldImpulse + deltaImpulse,constraint.m_lowerLimit,constraint.m_upperLimit); + "vdup.32 d23, d13[0] \n\t" //TEMP q11 => m_upperLimit (d23 only) + "vdup.32 d24, d12[1] \n\t" //TEMP q12 => m_lowerLimit (d34 only) + "vadd.f32 d25, d10, d11 \n\t" //TEMP q12 => deltaImpulse + oldImplues (d25 only) + "vmin.f32 d25, d25, d23 \n\t" //operation MIN(v,b) + "vmax.f32 d22, d25, d24 \n\t" //operation MAX(a,MIN(v,b) + "vst1.32 {d22[0]}, [%0] \n\t" //store m_accumImpulse (incremented so that it can be reloaded for cross product later) + //deltaImpulse = constraint.m_accumImpulse - oldImpulse; + "vsub.f32 d10, d22, d11 \n\t" //operation to calculate new deltaImpule + //FREE q6, q11, q12, q13, q14, q15, d11 + //deltaLinearVelocityB -= deltaImpulse * massInvB * normal; + //deltaLinearVelocityA += deltaImpulse * massInvA * normal; + "vld1.32 {d11[0]}, [%3] \n\t" //LOAD => massInvA ---------------------------> q5 (d11[0] only) + "vld1.32 {d11[1]}, [%8] \n\t" //LOAD => massInvB ---------------------------> q5 (d11[1] only) + "vmul.f32 q11, q4, d11[0] \n\t" //TEMP q11 => operation normal times massInvA A + "vmul.f32 q12, q4, d11[1] \n\t" //TEMP q12 => operation normal times massInvB B + "vmul.f32 q11, q11, d10[0] \n\t" //TEMP q11 => operation result times DeltaImpulse A + "vmul.f32 q12, q12, d10[0] \n\t" //TEMP q12 => operation result times DeltaImpulse B + "vadd.f32 q0, q0, q11 \n\t" //operation create new deltaLinearVelocityA A + "vst1.32 {q0}, [%1] \n\t" //store the new deltaLinearVelocityA A + "vsub.f32 q2, q2, q12 \n\t" //operation create new deltaLinearVelocityB B + "vst1.32 {q2}, [%6] \n\t" //store the new deltaLinearVelocityB B + //FREE q0, q2, q6, q11, q12, q13, q14, q15, d11 + //deltaAngularVelocityA += deltaImpulse * inertiaInvA * cross(rA,normal); + //deltaAngularVelocityB -= deltaImpulse * inertiaInvB * cross(rB,normal); + "vmov.f32 q14, q4 \n\t" // + "vmov.f32 q15, q4 \n\t" // + "vtrn.32 d30, d31 \n\t" // + "vrev64.32 d30, d30 \n\t" // + "vmul.f32 q0, q8, q15 \n\t" //operation for cross product A + "vrev64.32 d28, d28 \n\t" // + "vmul.f32 q2, q10, q15 \n\t" //operation for cross product B + "vtrn.32 d28, d29 \n\t" // + "vmls.f32 q0, q14, q7 \n\t" //operation for cross product A + "vmls.f32 q2, q14, q9 \n\t" //operation for cross product B + //LOAD => cross product result A ------------> q0 + //LOAD => cross product result B ------------> q2 + //FREE q6, q7, q8, q9, q10, q11, q12, q13, q14, q15, d11 + + "vld1.32 {q13-q14}, [%4]! \n\t" //LOAD => inertiaInvA col0, col1 A ----------> q13, q14 + "vld1.32 {q9-q10}, [%9]! \n\t" //LOAD => inertiaInvB col0, col1 B -----------> q9, q10 + "vld1.32 {q15}, [%4] \n\t" //LOAD => inertiaInvA col2 A ----------------> q5 + "vld1.32 {q11}, [%9] \n\t" //LOAD => inertiaInvB col2 B -----------------> q11 + "vmul.f32 q13, q13, d0[0] \n\t" //operation inertiaInvA col0 = (col0) * (crossA elem0) A + "vmul.f32 q9, q9, d4[0] \n\t" //operation inertiaInvB col0 = (col0) * (crossB elem0) B + "vmla.f32 q13, q14, d0[1] \n\t" //operation inertiaInvA col1 = (col1) * (crossA elem1) A + "vmla.f32 q9, q10, d4[1] \n\t" //operation inertiaInvB col1 = (col1) * (crossB elem1) B + "vmla.f32 q13, q15, d1[0] \n\t" //operation inertiaInvA col2 = (col2) * (crossA elem2) A + "vmla.f32 q9, q11, d5[0] \n\t" //operation inertiaInvB col2 = (col2) * (crossB elem2) B + "vmul.f32 q13, q13, d10[0] \n\t" //operation inertiaInvA times deltaImpulse A + "vmul.f32 q9, q9, d10[0] \n\t" //operation inertiaInvB times deltaImpulse B + "vadd.f32 q1, q1, q13 \n\t" //operation accumulate the deltaAngularVelocityA A + "vst1.32 {q1}, [%2] \n\t" //store deltaAngularVelocityA A + "vsub.f32 q3, q3, q9 \n\t" //operation accumulate the deltaAngularVelocityB B + "vst1.32 {q3}, [%7] \n\t" //store deltaAngularVelocityB B + : // NO direct outputs! It is important to *not* put anything here. Real output is written directly to memory pointed to by inputs + : "r" (&constraint), "r" (&deltaLinearVelocityA), "r" (&deltaAngularVelocityA), "r" (&massInvA), "r" (&inertiaInvA), "r" (&rA), "r" (&deltaLinearVelocityB), "r" (&deltaAngularVelocityB), "r" (&massInvB), "r" (&inertiaInvB), "r" (&rB) //inputs + : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" // clobbers + ); +} + +} //namespace PhysicsEffects +} //namespace sce +#endif //__ANDROID__ diff --git a/Extras/PhysicsEffects/src/base_level/solver/pfx_contact_constraint.cpp b/Extras/PhysicsEffects/src/base_level/solver/pfx_contact_constraint.cpp new file mode 100644 index 0000000..494d97d --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/solver/pfx_contact_constraint.cpp @@ -0,0 +1,194 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "../../../include/physics_effects/base_level/solver/pfx_contact_constraint.h" +#include "pfx_constraint_row_solver.h" + +namespace sce { +namespace PhysicsEffects { + +#define SCE_PFX_CONTACT_SLOP 0.001f + +void pfxSetupContactConstraint( + PfxConstraintRow &constraintResponse, + PfxConstraintRow &constraintFriction1, + PfxConstraintRow &constraintFriction2, + PfxFloat penetrationDepth, + PfxFloat restitution, + PfxFloat friction, + const PfxVector3 &contactNormal, + const PfxVector3 &contactPointA, + const PfxVector3 &contactPointB, + const PfxRigidState &stateA, + const PfxRigidState &stateB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + PfxFloat separateBias, + PfxFloat timeStep + ) +{ + (void)friction; + + PfxVector3 rA = rotate(solverBodyA.m_orientation,contactPointA); + PfxVector3 rB = rotate(solverBodyB.m_orientation,contactPointB); + + PfxFloat massInvA = solverBodyA.m_massInv; + PfxFloat massInvB = solverBodyB.m_massInv; + PfxMatrix3 inertiaInvA = solverBodyA.m_inertiaInv; + PfxMatrix3 inertiaInvB = solverBodyB.m_inertiaInv; + + if(solverBodyA.m_motionType == kPfxMotionTypeOneWay) { + massInvB = 0.0f; + inertiaInvB = PfxMatrix3(0.0f); + } + if(solverBodyB.m_motionType == kPfxMotionTypeOneWay) { + massInvA = 0.0f; + inertiaInvA = PfxMatrix3(0.0f); + } + + PfxMatrix3 K = PfxMatrix3::scale(PfxVector3(massInvA + massInvB)) - + crossMatrix(rA) * inertiaInvA * crossMatrix(rA) - + crossMatrix(rB) * inertiaInvB * crossMatrix(rB); + + PfxVector3 vA = stateA.getLinearVelocity() + cross(stateA.getAngularVelocity(),rA); + PfxVector3 vB = stateB.getLinearVelocity() + cross(stateB.getAngularVelocity(),rB); + PfxVector3 vAB = vA-vB; + + PfxVector3 tangent1,tangent2; + pfxGetPlaneSpace(contactNormal,tangent1,tangent2); + + // Contact Constraint + { + PfxVector3 normal = contactNormal; + + PfxFloat denom = dot(K*normal,normal); + + constraintResponse.m_rhs = -(1.0f+restitution)*dot(vAB,normal); // velocity error + constraintResponse.m_rhs -= (separateBias * SCE_PFX_MIN(0.0f,penetrationDepth+SCE_PFX_CONTACT_SLOP)) / timeStep; // position error + constraintResponse.m_rhs /= denom; + constraintResponse.m_jacDiagInv = 1.0f/denom; + constraintResponse.m_lowerLimit = 0.0f; + constraintResponse.m_upperLimit = SCE_PFX_FLT_MAX; + pfxStoreVector3(normal,constraintResponse.m_normal); + } + + // Friction Constraint 1 + { + PfxVector3 normal = tangent1; + + PfxFloat denom = dot(K*normal,normal); + + constraintFriction1.m_jacDiagInv = 1.0f/denom; + constraintFriction1.m_rhs = -dot(vAB,normal); + constraintFriction1.m_rhs *= constraintFriction1.m_jacDiagInv; + constraintFriction1.m_lowerLimit = 0.0f; + constraintFriction1.m_upperLimit = SCE_PFX_FLT_MAX; + pfxStoreVector3(normal,constraintFriction1.m_normal); + } + + // Friction Constraint 2 + { + PfxVector3 normal = tangent2; + + PfxFloat denom = dot(K*normal,normal); + + constraintFriction2.m_jacDiagInv = 1.0f/denom; + constraintFriction2.m_rhs = -dot(vAB,normal); + constraintFriction2.m_rhs *= constraintFriction2.m_jacDiagInv; + constraintFriction2.m_lowerLimit = 0.0f; + constraintFriction2.m_upperLimit = SCE_PFX_FLT_MAX; + pfxStoreVector3(normal,constraintFriction2.m_normal); + } +} + +void pfxSolveContactConstraint( + PfxConstraintRow &constraintResponse, + PfxConstraintRow &constraintFriction1, + PfxConstraintRow &constraintFriction2, + const PfxVector3 &contactPointA, + const PfxVector3 &contactPointB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + PfxFloat friction + ) +{ + PfxVector3 rA = rotate(solverBodyA.m_orientation,contactPointA); + PfxVector3 rB = rotate(solverBodyB.m_orientation,contactPointB); + + PfxFloat massInvA = solverBodyA.m_massInv; + PfxFloat massInvB = solverBodyB.m_massInv; + PfxMatrix3 inertiaInvA = solverBodyA.m_inertiaInv; + PfxMatrix3 inertiaInvB = solverBodyB.m_inertiaInv; + + if(solverBodyA.m_motionType == kPfxMotionTypeOneWay) { + massInvB = 0.0f; + inertiaInvB = PfxMatrix3(0.0f); + } + if(solverBodyB.m_motionType == kPfxMotionTypeOneWay) { + massInvA = 0.0f; + inertiaInvA = PfxMatrix3(0.0f); + } + +// ARA begin insert new code +#ifdef __ARM_NEON__ + pfxSolveLinearConstraintRowNEON(constraintResponse, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,massInvA,inertiaInvA,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,massInvB,inertiaInvB,rB); +#else // __ARM_NEON__ +// ARA end + + pfxSolveLinearConstraintRow(constraintResponse, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,massInvA,inertiaInvA,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,massInvB,inertiaInvB,rB); + +// ARA begin insert new code +#endif // __ARM_NEON__ +// ARA end + + PfxFloat mf = friction*fabsf(constraintResponse.m_accumImpulse); + constraintFriction1.m_lowerLimit = -mf; + constraintFriction1.m_upperLimit = mf; + constraintFriction2.m_lowerLimit = -mf; + constraintFriction2.m_upperLimit = mf; + +// ARA begin insert new code +#ifdef __ARM_NEON__ + pfxSolveLinearConstraintRowNEON(constraintFriction1, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,massInvA,inertiaInvA,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,massInvB,inertiaInvB,rB); + + pfxSolveLinearConstraintRowNEON(constraintFriction2, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,massInvA,inertiaInvA,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,massInvB,inertiaInvB,rB); +#else // __ARM_NEON__ +// ARA end + + pfxSolveLinearConstraintRow(constraintFriction1, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,massInvA,inertiaInvA,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,massInvB,inertiaInvB,rB); + + pfxSolveLinearConstraintRow(constraintFriction2, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,massInvA,inertiaInvA,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,massInvB,inertiaInvB,rB); + +// ARA begin insert new code +#endif // __ARM_NEON__ +// ARA end +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_ball.cpp b/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_ball.cpp new file mode 100644 index 0000000..37ca867 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_ball.cpp @@ -0,0 +1,179 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "../../../include/physics_effects/base_level/solver/pfx_joint_ball.h" +#include "pfx_constraint_row_solver.h" + +namespace sce { +namespace PhysicsEffects { + +PfxInt32 pfxInitializeBallJoint(PfxJoint &joint, + const PfxRigidState &stateA,const PfxRigidState &stateB, + const PfxBallJointInitParam ¶m) +{ + joint.m_active = 1; + joint.m_numConstraints = 3; + joint.m_userData = NULL; + joint.m_type = kPfxJointBall; + joint.m_rigidBodyIdA = stateA.getRigidBodyId(); + joint.m_rigidBodyIdB = stateB.getRigidBodyId(); + + for(int i=0;i<3;i++) { + joint.m_constraints[i].reset(); + } + + joint.m_constraints[0].m_lock = SCE_PFX_JOINT_LOCK_FIX; + joint.m_constraints[1].m_lock = SCE_PFX_JOINT_LOCK_FIX; + joint.m_constraints[2].m_lock = SCE_PFX_JOINT_LOCK_FIX; + + PfxMatrix3 rotA = transpose(PfxMatrix3(stateA.getOrientation())); + PfxMatrix3 rotB = transpose(PfxMatrix3(stateB.getOrientation())); + + joint.m_anchorA = rotA * (param.anchorPoint - stateA.getPosition()); + joint.m_anchorB = rotB * (param.anchorPoint - stateB.getPosition()); + + joint.m_frameA = PfxMatrix3::identity(); + joint.m_frameB = rotB * PfxMatrix3(stateA.getOrientation()) * joint.m_frameA; + + return SCE_PFX_OK; +} + +void pfxSetupBallJoint( + PfxJoint &joint, + const PfxRigidState &stateA, + const PfxRigidState &stateB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + PfxFloat timeStep + ) +{ + PfxVector3 rA = rotate(solverBodyA.m_orientation,joint.m_anchorA); + PfxVector3 rB = rotate(solverBodyB.m_orientation,joint.m_anchorB); + + PfxVector3 vA = stateA.getLinearVelocity() + cross(stateA.getAngularVelocity(),rA); + PfxVector3 vB = stateB.getLinearVelocity() + cross(stateB.getAngularVelocity(),rB); + PfxVector3 vAB = vA-vB; + + PfxVector3 distance = (stateA.getPosition() + rA) - (stateB.getPosition() + rB); + + PfxMatrix3 worldFrameA,worldFrameB; + worldFrameA = PfxMatrix3(solverBodyA.m_orientation) * joint.m_frameA; + worldFrameB = PfxMatrix3(solverBodyB.m_orientation) * joint.m_frameB; + + // Linear Constraint + PfxMatrix3 K = PfxMatrix3::scale(PfxVector3(solverBodyA.m_massInv + solverBodyB.m_massInv)) - + crossMatrix(rA) * solverBodyA.m_inertiaInv * crossMatrix(rA) - + crossMatrix(rB) * solverBodyB.m_inertiaInv * crossMatrix(rB); + + for(int c=0;c<3;c++) { + PfxJointConstraint &jointConstraint = joint.m_constraints[c]; + PfxConstraintRow &constraint = jointConstraint.m_constraintRow; + + PfxVector3 normal = worldFrameA[c]; + + PfxFloat posErr = dot(distance,-normal); + PfxFloat lowerLimit = -jointConstraint.m_maxImpulse; + PfxFloat upperLimit = jointConstraint.m_maxImpulse; + PfxFloat velocityAmp = 1.0f; + + pfxCalcLinearLimit(jointConstraint,posErr,velocityAmp,lowerLimit,upperLimit); + + PfxFloat denom = dot(K*normal,normal); + + constraint.m_rhs = -velocityAmp*dot(vAB,normal); + constraint.m_rhs -= (jointConstraint.m_bias * (-posErr)) / timeStep; + constraint.m_rhs *= jointConstraint.m_weight/denom; + constraint.m_jacDiagInv = jointConstraint.m_weight*velocityAmp/denom; + constraint.m_lowerLimit = lowerLimit; + constraint.m_upperLimit = upperLimit; + pfxStoreVector3(normal,constraint.m_normal); + } +} + +void pfxWarmStartBallJoint( + PfxJoint &joint, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB + ) +{ + PfxVector3 rA = rotate(solverBodyA.m_orientation,joint.m_anchorA); + PfxVector3 rB = rotate(solverBodyB.m_orientation,joint.m_anchorB); + + // Linear Constraint + for(int c=0;c<3;c++) { + PfxJointConstraint &jointConstraint = joint.m_constraints[c]; + PfxConstraintRow &constraint = jointConstraint.m_constraintRow; + + if(jointConstraint.m_warmStarting == 0) { + constraint.m_accumImpulse = 0.0f; + } + else { + PfxVector3 normal = pfxReadVector3(constraint.m_normal); + PfxFloat deltaImpulse = constraint.m_accumImpulse; + solverBodyA.m_deltaLinearVelocity += deltaImpulse * solverBodyA.m_massInv * normal; + solverBodyA.m_deltaAngularVelocity += deltaImpulse * solverBodyA.m_inertiaInv * cross(rA,normal); + solverBodyB.m_deltaLinearVelocity -= deltaImpulse * solverBodyB.m_massInv * normal; + solverBodyB.m_deltaAngularVelocity -= deltaImpulse * solverBodyB.m_inertiaInv * cross(rB,normal); + } + } +} + +void pfxSolveBallJoint( + PfxJoint &joint, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB + ) +{ + PfxVector3 rA = rotate(solverBodyA.m_orientation,joint.m_anchorA); + PfxVector3 rB = rotate(solverBodyB.m_orientation,joint.m_anchorB); + + // Linear Constraint +// ARA begin insert new code +#ifdef __ARM_NEON__ + pfxSolveLinearConstraintRowNEON(joint.m_constraints[0].m_constraintRow, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB); + + pfxSolveLinearConstraintRowNEON(joint.m_constraints[1].m_constraintRow, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB); + + pfxSolveLinearConstraintRowNEON(joint.m_constraints[2].m_constraintRow, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB); +#else // __ARM_NEON__ +// ARA end + + pfxSolveLinearConstraintRow(joint.m_constraints[0].m_constraintRow, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB); + + pfxSolveLinearConstraintRow(joint.m_constraints[1].m_constraintRow, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB); + + pfxSolveLinearConstraintRow(joint.m_constraints[2].m_constraintRow, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB); + +// ARA begin insert new code +#endif // __ARM_NEON__ +// ARA end +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_fix.cpp b/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_fix.cpp new file mode 100644 index 0000000..bb5509f --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_fix.cpp @@ -0,0 +1,54 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "../../../include/physics_effects/base_level/solver/pfx_joint_fix.h" +#include "pfx_constraint_row_solver.h" + +namespace sce { +namespace PhysicsEffects { + +PfxInt32 pfxInitializeFixJoint(PfxJoint &joint, + const PfxRigidState &stateA,const PfxRigidState &stateB, + const PfxFixJointInitParam ¶m) +{ + joint.m_active = 1; + joint.m_numConstraints = 6; + joint.m_userData = NULL; + joint.m_type = kPfxJointFix; + joint.m_rigidBodyIdA = stateA.getRigidBodyId(); + joint.m_rigidBodyIdB = stateB.getRigidBodyId(); + + for(int i=0;i<6;i++) { + joint.m_constraints[i].reset(); + joint.m_constraints[i].m_lock = SCE_PFX_JOINT_LOCK_FIX; + } + + // Calc joint frame + PfxMatrix3 rotA = transpose(PfxMatrix3(stateA.getOrientation())); + PfxMatrix3 rotB = transpose(PfxMatrix3(stateB.getOrientation())); + + joint.m_anchorA = rotA * (param.anchorPoint - stateA.getPosition()); + joint.m_anchorB = rotB * (param.anchorPoint - stateB.getPosition()); + + joint.m_frameA = PfxMatrix3::identity(); + joint.m_frameB = rotB * PfxMatrix3(stateA.getOrientation()) * joint.m_frameA; + + return SCE_PFX_OK; +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_hinge.cpp b/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_hinge.cpp new file mode 100644 index 0000000..c913a36 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_hinge.cpp @@ -0,0 +1,80 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "../../../include/physics_effects/base_level/solver/pfx_joint_hinge.h" +#include "pfx_constraint_row_solver.h" + +namespace sce { +namespace PhysicsEffects { + +PfxInt32 pfxInitializeHingeJoint(PfxJoint &joint, + const PfxRigidState &stateA,const PfxRigidState &stateB, + const PfxHingeJointInitParam ¶m) +{ + joint.m_active = 1; + joint.m_numConstraints = 6; + joint.m_userData = NULL; + joint.m_type = kPfxJointHinge; + joint.m_rigidBodyIdA = stateA.getRigidBodyId(); + joint.m_rigidBodyIdB = stateB.getRigidBodyId(); + + for(int i=0;i<6;i++) { + joint.m_constraints[i].reset(); + } + + joint.m_constraints[0].m_lock = SCE_PFX_JOINT_LOCK_FIX; + joint.m_constraints[1].m_lock = SCE_PFX_JOINT_LOCK_FIX; + joint.m_constraints[2].m_lock = SCE_PFX_JOINT_LOCK_FIX; + if(param.lowerAngle == 0.0f && param.upperAngle == 0.0f) { + joint.m_constraints[3].m_lock = SCE_PFX_JOINT_LOCK_FREE; + } + else { + joint.m_constraints[3].m_lock = SCE_PFX_JOINT_LOCK_LIMIT; + } + joint.m_constraints[4].m_lock = SCE_PFX_JOINT_LOCK_FIX; + joint.m_constraints[5].m_lock = SCE_PFX_JOINT_LOCK_FIX; + + // Set twist angle limit + if(param.lowerAngle > param.upperAngle || + !SCE_PFX_RANGE_CHECK(param.lowerAngle,-SCE_PFX_PI,SCE_PFX_PI) || + !SCE_PFX_RANGE_CHECK(param.upperAngle,-SCE_PFX_PI,SCE_PFX_PI)) { + return SCE_PFX_ERR_OUT_OF_RANGE; + } + joint.m_constraints[3].m_movableLowerLimit = param.lowerAngle; + joint.m_constraints[3].m_movableUpperLimit = param.upperAngle; + + // Calc joint frame + PfxMatrix3 rotA = transpose(PfxMatrix3(stateA.getOrientation())); + PfxMatrix3 rotB = transpose(PfxMatrix3(stateB.getOrientation())); + + PfxVector3 axisInA = rotA * normalize(param.axis); + + joint.m_anchorA = rotA * (param.anchorPoint - stateA.getPosition()); + joint.m_anchorB = rotB * (param.anchorPoint - stateB.getPosition()); + + PfxVector3 axis1, axis2; + + pfxGetPlaneSpace(axisInA, axis1, axis2 ); + + joint.m_frameA = PfxMatrix3(axisInA, axis1, axis2); + joint.m_frameB = rotB * PfxMatrix3(stateA.getOrientation()) * joint.m_frameA; + + return SCE_PFX_OK; +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_slider.cpp b/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_slider.cpp new file mode 100644 index 0000000..8b843cc --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_slider.cpp @@ -0,0 +1,78 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "../../../include/physics_effects/base_level/solver/pfx_joint_slider.h" +#include "pfx_constraint_row_solver.h" + +namespace sce { +namespace PhysicsEffects { + +PfxInt32 pfxInitializeSliderJoint(PfxJoint &joint, + const PfxRigidState &stateA,const PfxRigidState &stateB, + const PfxSliderJointInitParam ¶m) +{ + joint.m_active = 1; + joint.m_numConstraints = 6; + joint.m_userData = NULL; + joint.m_type = kPfxJointSlider; + joint.m_rigidBodyIdA = stateA.getRigidBodyId(); + joint.m_rigidBodyIdB = stateB.getRigidBodyId(); + + for(int i=0;i<6;i++) { + joint.m_constraints[i].reset(); + } + + if(param.lowerDistance == 0.0f && param.upperDistance == 0.0f) { + joint.m_constraints[0].m_lock = SCE_PFX_JOINT_LOCK_FREE; + } + else { + joint.m_constraints[0].m_lock = SCE_PFX_JOINT_LOCK_LIMIT; + } + joint.m_constraints[1].m_lock = SCE_PFX_JOINT_LOCK_FIX; + joint.m_constraints[2].m_lock = SCE_PFX_JOINT_LOCK_FIX; + joint.m_constraints[3].m_lock = SCE_PFX_JOINT_LOCK_FIX; + joint.m_constraints[4].m_lock = SCE_PFX_JOINT_LOCK_FIX; + joint.m_constraints[5].m_lock = SCE_PFX_JOINT_LOCK_FIX; + + if(param.lowerDistance > param.upperDistance ) { + return SCE_PFX_ERR_OUT_OF_RANGE; + } + + joint.m_constraints[0].m_movableLowerLimit = param.lowerDistance; + joint.m_constraints[0].m_movableUpperLimit = param.upperDistance; + + // Calc joint frame + PfxMatrix3 rotA = transpose(PfxMatrix3(stateA.getOrientation())); + PfxMatrix3 rotB = transpose(PfxMatrix3(stateB.getOrientation())); + + PfxVector3 axisInA = rotA * normalize(param.direction); + + joint.m_anchorA = rotA * (param.anchorPoint - stateA.getPosition()); + joint.m_anchorB = rotB * (param.anchorPoint - stateB.getPosition()); + + PfxVector3 axis1, axis2; + + pfxGetPlaneSpace(axisInA, axis1, axis2 ); + + joint.m_frameA = PfxMatrix3(axisInA, axis1, axis2); + joint.m_frameB = rotB * PfxMatrix3(stateA.getOrientation()) * joint.m_frameA; + + return SCE_PFX_OK; +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_swing_twist.cpp b/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_swing_twist.cpp new file mode 100644 index 0000000..f19b5c3 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_swing_twist.cpp @@ -0,0 +1,268 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "../../../include/physics_effects/base_level/solver/pfx_joint_swing_twist.h" +#include "pfx_constraint_row_solver.h" + + +namespace sce { +namespace PhysicsEffects { + +PfxInt32 pfxInitializeSwingTwistJoint(PfxJoint &joint, + const PfxRigidState &stateA,const PfxRigidState &stateB, + const PfxSwingTwistJointInitParam ¶m) +{ + joint.m_active = 1; + joint.m_numConstraints = 6; + joint.m_userData = NULL; + joint.m_type = kPfxJointSwingtwist; + joint.m_rigidBodyIdA = stateA.getRigidBodyId(); + joint.m_rigidBodyIdB = stateB.getRigidBodyId(); + + for(int i=0;i<6;i++) { + joint.m_constraints[i].reset(); + } + + joint.m_constraints[0].m_lock = SCE_PFX_JOINT_LOCK_FIX; + joint.m_constraints[1].m_lock = SCE_PFX_JOINT_LOCK_FIX; + joint.m_constraints[2].m_lock = SCE_PFX_JOINT_LOCK_FIX; + joint.m_constraints[3].m_lock = SCE_PFX_JOINT_LOCK_LIMIT; + joint.m_constraints[4].m_lock = SCE_PFX_JOINT_LOCK_LIMIT; + joint.m_constraints[5].m_lock = SCE_PFX_JOINT_LOCK_FREE; + + // Set twist angle limit + if(param.twistLowerAngle > param.twistUpperAngle || + !SCE_PFX_RANGE_CHECK(param.twistLowerAngle,-SCE_PFX_PI,SCE_PFX_PI) || + !SCE_PFX_RANGE_CHECK(param.twistUpperAngle,-SCE_PFX_PI,SCE_PFX_PI)) { + return SCE_PFX_ERR_OUT_OF_RANGE; + } + joint.m_constraints[3].m_movableLowerLimit = param.twistLowerAngle; + joint.m_constraints[3].m_movableUpperLimit = param.twistUpperAngle; + + // Set swing angle limit + if(param.swingLowerAngle > param.swingUpperAngle || + !SCE_PFX_RANGE_CHECK(param.swingLowerAngle,0.0f,SCE_PFX_PI) || + !SCE_PFX_RANGE_CHECK(param.swingUpperAngle,0.0f,SCE_PFX_PI)) { + return SCE_PFX_ERR_OUT_OF_RANGE; + } + joint.m_constraints[4].m_movableLowerLimit = param.swingLowerAngle; + joint.m_constraints[4].m_movableUpperLimit = param.swingUpperAngle; + + // Calc joint frame + PfxMatrix3 rotA = transpose(PfxMatrix3(stateA.getOrientation())); + PfxMatrix3 rotB = transpose(PfxMatrix3(stateB.getOrientation())); + + PfxVector3 axisInA = rotA * normalize(param.twistAxis); + + joint.m_anchorA = rotA * (param.anchorPoint - stateA.getPosition()); + joint.m_anchorB = rotB * (param.anchorPoint - stateB.getPosition()); + + PfxVector3 axis1, axis2; + + pfxGetPlaneSpace(axisInA, axis1, axis2 ); + + joint.m_frameA = PfxMatrix3(axisInA, axis1, axis2); + joint.m_frameB = rotB * PfxMatrix3(stateA.getOrientation()) * joint.m_frameA; + + return SCE_PFX_OK; +} + +void pfxSetupSwingTwistJoint( + PfxJoint &joint, + const PfxRigidState &stateA, + const PfxRigidState &stateB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + PfxFloat timeStep + ) +{ + PfxVector3 rA = rotate(solverBodyA.m_orientation,joint.m_anchorA); + PfxVector3 rB = rotate(solverBodyB.m_orientation,joint.m_anchorB); + + PfxVector3 vA = stateA.getLinearVelocity() + cross(stateA.getAngularVelocity(),rA); + PfxVector3 vB = stateB.getLinearVelocity() + cross(stateB.getAngularVelocity(),rB); + PfxVector3 vAB = vA-vB; + + PfxVector3 angAB = stateA.getAngularVelocity() - stateB.getAngularVelocity(); + + PfxVector3 distance = (stateA.getPosition() + rA) - (stateB.getPosition() + rB); + + PfxMatrix3 worldFrameA,worldFrameB; + worldFrameA = PfxMatrix3(solverBodyA.m_orientation) * joint.m_frameA; + worldFrameB = PfxMatrix3(solverBodyB.m_orientation) * joint.m_frameB; + + // Linear Constraint + PfxMatrix3 K = PfxMatrix3::scale(PfxVector3(solverBodyA.m_massInv + solverBodyB.m_massInv)) - + crossMatrix(rA) * solverBodyA.m_inertiaInv * crossMatrix(rA) - + crossMatrix(rB) * solverBodyB.m_inertiaInv * crossMatrix(rB); + + for(int c=0;c<3;c++) { + PfxJointConstraint &jointConstraint = joint.m_constraints[c]; + PfxConstraintRow &constraint = jointConstraint.m_constraintRow; + + PfxVector3 normal = worldFrameA[c]; + + PfxFloat posErr = dot(distance,-normal); + PfxFloat lowerLimit = -jointConstraint.m_maxImpulse; + PfxFloat upperLimit = jointConstraint.m_maxImpulse; + PfxFloat velocityAmp = 1.0f; + + pfxCalcLinearLimit(jointConstraint,posErr,velocityAmp,lowerLimit,upperLimit); + + PfxFloat denom = dot(K*normal,normal); + + constraint.m_rhs = -velocityAmp*dot(vAB,normal); + constraint.m_rhs -= (jointConstraint.m_bias * (-posErr)) / timeStep; + constraint.m_rhs *= jointConstraint.m_weight/denom; + constraint.m_jacDiagInv = jointConstraint.m_weight*velocityAmp/denom; + constraint.m_lowerLimit = lowerLimit; + constraint.m_upperLimit = upperLimit; + pfxStoreVector3(normal,constraint.m_normal); + } + + PfxVector3 axis[3]; + PfxFloat angle[3]; + pfxCalcJointAngleSwingTwist(worldFrameA,worldFrameB,angle,axis); + + // Angular Constraint + for(int c=3;c<6;c++) { + PfxJointConstraint &jointConstraint = joint.m_constraints[c]; + PfxConstraintRow &constraint = jointConstraint.m_constraintRow; + + PfxVector3 normal = axis[c-3]; + + PfxFloat posErr = angle[c-3]; + PfxFloat lowerLimit = -jointConstraint.m_maxImpulse; + PfxFloat upperLimit = jointConstraint.m_maxImpulse; + PfxFloat velocityAmp = 1.0f; + + pfxCalcAngularLimit(jointConstraint,posErr,velocityAmp,lowerLimit,upperLimit); + + PfxFloat denom = dot((solverBodyA.m_inertiaInv+solverBodyB.m_inertiaInv)*normal,normal); + + constraint.m_rhs = -velocityAmp*dot(angAB,normal); // velocity error + constraint.m_rhs -= (jointConstraint.m_bias * (-posErr)) / timeStep; // position error + constraint.m_rhs *= jointConstraint.m_weight/denom; + constraint.m_jacDiagInv = jointConstraint.m_weight*velocityAmp/denom; + constraint.m_lowerLimit = lowerLimit; + constraint.m_upperLimit = upperLimit; + pfxStoreVector3(normal,constraint.m_normal); + } +} + +void pfxWarmStartSwingTwistJoint( + PfxJoint &joint, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB + ) +{ + PfxVector3 rA = rotate(solverBodyA.m_orientation,joint.m_anchorA); + PfxVector3 rB = rotate(solverBodyB.m_orientation,joint.m_anchorB); + + // Linear Constraint + for(int c=0;c<3;c++) { + PfxJointConstraint &jointConstraint = joint.m_constraints[c]; + PfxConstraintRow &constraint = jointConstraint.m_constraintRow; + + if(jointConstraint.m_warmStarting == 0) { + constraint.m_accumImpulse = 0.0f; + } + else { + PfxVector3 normal = pfxReadVector3(constraint.m_normal); + PfxFloat deltaImpulse = constraint.m_accumImpulse; + solverBodyA.m_deltaLinearVelocity += deltaImpulse * solverBodyA.m_massInv * normal; + solverBodyA.m_deltaAngularVelocity += deltaImpulse * solverBodyA.m_inertiaInv * cross(rA,normal); + solverBodyB.m_deltaLinearVelocity -= deltaImpulse * solverBodyB.m_massInv * normal; + solverBodyB.m_deltaAngularVelocity -= deltaImpulse * solverBodyB.m_inertiaInv * cross(rB,normal); + } + } + + // Angular Constraint + for(int c=3;c<6;c++) { + PfxJointConstraint &jointConstraint = joint.m_constraints[c]; + PfxConstraintRow &constraint = jointConstraint.m_constraintRow; + + if(jointConstraint.m_warmStarting == 0) { + constraint.m_accumImpulse = 0.0f; + } + else { + PfxVector3 normal = pfxReadVector3(constraint.m_normal); + PfxFloat deltaImpulse = constraint.m_accumImpulse; + solverBodyA.m_deltaAngularVelocity += deltaImpulse * solverBodyA.m_inertiaInv * normal; + solverBodyB.m_deltaAngularVelocity -= deltaImpulse * solverBodyB.m_inertiaInv * normal; + } + } +} + +void pfxSolveSwingTwistJoint( + PfxJoint &joint, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB + ) +{ + PfxVector3 rA = rotate(solverBodyA.m_orientation,joint.m_anchorA); + PfxVector3 rB = rotate(solverBodyB.m_orientation,joint.m_anchorB); + + // Linear Constraint +// ARA begin insert new code +#ifdef __ARM_NEON__ + pfxSolveLinearConstraintRowNEON(joint.m_constraints[0].m_constraintRow, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB); + + pfxSolveLinearConstraintRowNEON(joint.m_constraints[1].m_constraintRow, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB); + + pfxSolveLinearConstraintRowNEON(joint.m_constraints[2].m_constraintRow, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB); +#else // __ARM_NEON__ +// ARA end + + pfxSolveLinearConstraintRow(joint.m_constraints[0].m_constraintRow, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB); + + pfxSolveLinearConstraintRow(joint.m_constraints[1].m_constraintRow, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB); + + pfxSolveLinearConstraintRow(joint.m_constraints[2].m_constraintRow, + solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB); + +// ARA begin insert new code +#endif // __ARM_NEON__ +// ARA end + + // Angular Constraint + pfxSolveAngularConstraintRow(joint.m_constraints[3].m_constraintRow, + solverBodyA.m_deltaAngularVelocity,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaAngularVelocity,solverBodyB.m_inertiaInv,rB); + + pfxSolveAngularConstraintRow(joint.m_constraints[4].m_constraintRow, + solverBodyA.m_deltaAngularVelocity,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaAngularVelocity,solverBodyB.m_inertiaInv,rB); + + pfxSolveAngularConstraintRow(joint.m_constraints[5].m_constraintRow, + solverBodyA.m_deltaAngularVelocity,solverBodyA.m_inertiaInv,rA, + solverBodyB.m_deltaAngularVelocity,solverBodyB.m_inertiaInv,rB); +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_universal.cpp b/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_universal.cpp new file mode 100644 index 0000000..0e8a39c --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/solver/pfx_joint_universal.cpp @@ -0,0 +1,163 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "../../../include/physics_effects/base_level/solver/pfx_joint_universal.h" +#include "pfx_constraint_row_solver.h" + +namespace sce { +namespace PhysicsEffects { + +PfxInt32 pfxInitializeUniversalJoint(PfxJoint &joint, + const PfxRigidState &stateA,const PfxRigidState &stateB, + const PfxUniversalJointInitParam ¶m) +{ + joint.m_active = 1; + joint.m_numConstraints = 6; + joint.m_userData = NULL; + joint.m_type = kPfxJointUniversal; + joint.m_rigidBodyIdA = stateA.getRigidBodyId(); + joint.m_rigidBodyIdB = stateB.getRigidBodyId(); + + for(int i=0;i<6;i++) { + joint.m_constraints[i].reset(); + } + + joint.m_constraints[0].m_lock = SCE_PFX_JOINT_LOCK_FIX; + joint.m_constraints[1].m_lock = SCE_PFX_JOINT_LOCK_FIX; + joint.m_constraints[2].m_lock = SCE_PFX_JOINT_LOCK_FIX; + joint.m_constraints[3].m_lock = SCE_PFX_JOINT_LOCK_FIX; + joint.m_constraints[4].m_lock = SCE_PFX_JOINT_LOCK_LIMIT; + joint.m_constraints[5].m_lock = SCE_PFX_JOINT_LOCK_LIMIT; + + // Set swing angle limit + if(param.swing1LowerAngle > param.swing1UpperAngle || + !SCE_PFX_RANGE_CHECK(param.swing1LowerAngle,-SCE_PFX_PI,SCE_PFX_PI) || + !SCE_PFX_RANGE_CHECK(param.swing1UpperAngle,-SCE_PFX_PI,SCE_PFX_PI) || + param.swing2LowerAngle > param.swing2UpperAngle || + !SCE_PFX_RANGE_CHECK(param.swing2LowerAngle,-SCE_PFX_PI,SCE_PFX_PI) || + !SCE_PFX_RANGE_CHECK(param.swing2UpperAngle,-SCE_PFX_PI,SCE_PFX_PI)) { + return SCE_PFX_ERR_OUT_OF_RANGE; + } + + joint.m_constraints[4].m_movableLowerLimit = param.swing1LowerAngle; + joint.m_constraints[4].m_movableUpperLimit = param.swing1UpperAngle; + joint.m_constraints[5].m_movableLowerLimit = param.swing2LowerAngle; + joint.m_constraints[5].m_movableUpperLimit = param.swing2UpperAngle; + + // Calc joint frame + PfxMatrix3 rotA = transpose(PfxMatrix3(stateA.getOrientation())); + PfxMatrix3 rotB = transpose(PfxMatrix3(stateB.getOrientation())); + + PfxVector3 axisInA = rotA * normalize(param.axis); + + joint.m_anchorA = rotA * (param.anchorPoint - stateA.getPosition()); + joint.m_anchorB = rotB * (param.anchorPoint - stateB.getPosition()); + + PfxVector3 axis1, axis2; + + pfxGetPlaneSpace(axisInA, axis1, axis2 ); + + joint.m_frameA = PfxMatrix3(axisInA, axis1, axis2); + joint.m_frameB = rotB * PfxMatrix3(stateA.getOrientation()) * joint.m_frameA; + + return SCE_PFX_OK; +} + +void pfxSetupUniversalJoint( + PfxJoint &joint, + const PfxRigidState &stateA, + const PfxRigidState &stateB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + PfxFloat timeStep + ) +{ + PfxVector3 rA = rotate(solverBodyA.m_orientation,joint.m_anchorA); + PfxVector3 rB = rotate(solverBodyB.m_orientation,joint.m_anchorB); + + PfxVector3 vA = stateA.getLinearVelocity() + cross(stateA.getAngularVelocity(),rA); + PfxVector3 vB = stateB.getLinearVelocity() + cross(stateB.getAngularVelocity(),rB); + PfxVector3 vAB = vA-vB; + + PfxVector3 angAB = stateA.getAngularVelocity() - stateB.getAngularVelocity(); + + PfxVector3 distance = (stateA.getPosition() + rA) - (stateB.getPosition() + rB); + + PfxMatrix3 worldFrameA,worldFrameB; + worldFrameA = PfxMatrix3(solverBodyA.m_orientation) * joint.m_frameA; + worldFrameB = PfxMatrix3(solverBodyB.m_orientation) * joint.m_frameB; + + // Linear Constraint + PfxMatrix3 K = PfxMatrix3::scale(PfxVector3(solverBodyA.m_massInv + solverBodyB.m_massInv)) - + crossMatrix(rA) * solverBodyA.m_inertiaInv * crossMatrix(rA) - + crossMatrix(rB) * solverBodyB.m_inertiaInv * crossMatrix(rB); + + for(int c=0;c<3;c++) { + PfxJointConstraint &jointConstraint = joint.m_constraints[c]; + PfxConstraintRow &constraint = jointConstraint.m_constraintRow; + + PfxVector3 normal = worldFrameA[c]; + + PfxFloat posErr = dot(distance,-normal); + PfxFloat lowerLimit = -jointConstraint.m_maxImpulse; + PfxFloat upperLimit = jointConstraint.m_maxImpulse; + PfxFloat velocityAmp = 1.0f; + + pfxCalcLinearLimit(jointConstraint,posErr,velocityAmp,lowerLimit,upperLimit); + + PfxFloat denom = dot(K*normal,normal); + + constraint.m_rhs = -velocityAmp*dot(vAB,normal); + constraint.m_rhs -= (jointConstraint.m_bias * (-posErr)) / timeStep; + constraint.m_rhs *= jointConstraint.m_weight/denom; + constraint.m_jacDiagInv = jointConstraint.m_weight*velocityAmp/denom; + constraint.m_lowerLimit = lowerLimit; + constraint.m_upperLimit = upperLimit; + pfxStoreVector3(normal,constraint.m_normal); + } + + PfxVector3 axis[3]; + PfxFloat angle[3]; + pfxCalcJointAngleUniversal(worldFrameA,worldFrameB,angle,axis); + + // Angular Constraint + for(int c=3;c<6;c++) { + PfxJointConstraint &jointConstraint = joint.m_constraints[c]; + PfxConstraintRow &constraint = jointConstraint.m_constraintRow; + + PfxVector3 normal = axis[c-3]; + + PfxFloat posErr = angle[c-3]; + PfxFloat lowerLimit = -jointConstraint.m_maxImpulse; + PfxFloat upperLimit = jointConstraint.m_maxImpulse; + PfxFloat velocityAmp = 1.0f; + + pfxCalcAngularLimit(jointConstraint,posErr,velocityAmp,lowerLimit,upperLimit); + + PfxFloat denom = dot((solverBodyA.m_inertiaInv+solverBodyB.m_inertiaInv)*normal,normal); + + constraint.m_rhs = -velocityAmp*dot(angAB,normal); // velocity error + constraint.m_rhs -= (jointConstraint.m_bias * (-posErr)) / timeStep; // position error + constraint.m_rhs *= jointConstraint.m_weight/denom; + constraint.m_jacDiagInv = jointConstraint.m_weight*velocityAmp/denom; + constraint.m_lowerLimit = lowerLimit; + constraint.m_upperLimit = upperLimit; + pfxStoreVector3(normal,constraint.m_normal); + } +} +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/base_level/sort/pfx_sort.cpp b/Extras/PhysicsEffects/src/base_level/sort/pfx_sort.cpp new file mode 100644 index 0000000..7ce6509 --- /dev/null +++ b/Extras/PhysicsEffects/src/base_level/sort/pfx_sort.cpp @@ -0,0 +1,267 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/sort/pfx_sort.h" + +namespace sce { +namespace PhysicsEffects { + + +#define Key(a) pfxGetKey(a) + +/////////////////////////////////////////////////////////////////////////////// +// Merge Sort + + + +template +SCE_PFX_FORCE_INLINE +void pfxCompareAndSwap(SortData &d1,SortData &d2) +{ +if(Key(d1) > Key(d2)) { + SortData tmp = d1; + d1 = d2; + d2 = tmp; +} +} + +template +SCE_PFX_FORCE_INLINE +void pfxMergeTwoBuffers11(SortData* d1,int n1,SortData* d2,int n2) +{ +(void)n1,(void)n2,(void)d2; +pfxCompareAndSwap(d1[0],d1[1]); +} + +template +SCE_PFX_FORCE_INLINE +void pfxMergeTwoBuffers12(SortData* d1,int n1,SortData* d2,int n2) +{ +(void)n1,(void)d2,(void)n2; +pfxCompareAndSwap(d1[0],d1[1]); +pfxCompareAndSwap(d1[1],d1[2]); +} + +template +SCE_PFX_FORCE_INLINE +void pfxMergeTwoBuffers22(SortData* d1,int n1,SortData* d2,int n2) +{ +(void)n1,(void)d2,(void)n2; +pfxCompareAndSwap(d1[0],d1[2]); +pfxCompareAndSwap(d1[1],d1[3]); +pfxCompareAndSwap(d1[1],d1[2]); +} + +template +SCE_PFX_FORCE_INLINE +void pfxMergeTwoBuffers23(SortData* d1,int n1,SortData* d2,int n2) +{ +(void)n1,(void)d2,(void)n2; +pfxCompareAndSwap(d1[0],d1[2]); +pfxCompareAndSwap(d1[1],d1[4]); +pfxCompareAndSwap(d1[2],d1[3]); +pfxCompareAndSwap(d1[1],d1[2]); +pfxCompareAndSwap(d1[2],d1[3]); +} + +template +SCE_PFX_FORCE_INLINE +void pfxMergeTwoBuffers33(SortData* d1,int n1,SortData* d2,int n2) +{ +(void)n1,(void)d2,(void)n2; +pfxCompareAndSwap(d1[0],d1[3]); +pfxCompareAndSwap(d1[2],d1[5]); +pfxCompareAndSwap(d1[1],d1[2]); +pfxCompareAndSwap(d1[3],d1[4]); +pfxCompareAndSwap(d1[1],d1[3]); +pfxCompareAndSwap(d1[2],d1[4]); +pfxCompareAndSwap(d1[2],d1[3]); +} + +template +void pfxMergeTwoBuffers(SortData* d1,unsigned int n1,SortData* d2,unsigned int n2,SortData *buff) +{ +unsigned int i=0,j=0; + +while(i +void pfxMergeSort(SortData *d,SortData *buff,int n) +{ +int n1 = n>>1; +int n2 = n-n1; +if(n1>1) pfxMergeSort(d,buff,n1); +if(n2>1) pfxMergeSort(d+n1,buff,n2); + +int nadd = n1+n2; + +if(nadd==2) { + pfxMergeTwoBuffers11(d,n1,d+n1,n2); +} +else if(nadd==3) { + pfxMergeTwoBuffers12(d,n1,d+n1,n2); +} +else if(nadd==4) { + pfxMergeTwoBuffers22(d,n1,d+n1,n2); +} +else if(nadd==5) { + pfxMergeTwoBuffers23(d,n1,d+n1,n2); +} +else if(nadd==6) { + pfxMergeTwoBuffers33(d,n1,d+n1,n2); +} +else { + pfxMergeTwoBuffers(d,n1,d+n1,n2,buff); +} +} + + +/////////////////////////////////////////////////////////////////////////////// +// Bitonic Sort + + +template +void pfxBitonicMerge(SortData *d,unsigned int n,int dir) +{ +if(n > 1) { + unsigned int k = n>>1; + for(unsigned int i=0;i Key(d[i+k])) { + SortData t = d[i+k]; + d[i+k] = d[i]; + d[i] = t; + } + if(dir==1 && Key(d[i]) < Key(d[i+k])) { + SortData t = d[i+k]; + d[i+k] = d[i]; + d[i] = t; + } + } + pfxBitonicMerge(d,k,dir); + pfxBitonicMerge(d+k,k,dir); +} +} + +template +void pfxBitonicSortInternal(SortData *d,unsigned int n,unsigned int dir=0) +{ +if(n > 1) { + unsigned int k = n>>1; + pfxBitonicSortInternal(d,k,0); + pfxBitonicSortInternal(d+k,k,1); + pfxBitonicMerge(d,n,dir); +} +} + +template +void pfxBitonicSort(SortData *d,SortData *buff,unsigned int n) +{ +pfxBitonicSortInternal(d,n,0); +memcpy(buff,d,sizeof(SortData)*n); +} + + +/////////////////////////////////////////////////////////////////////////////// +// Hybrid Sort (Bitonic + Merge) + +struct PfxDiv2n { + unsigned int id; + unsigned int num; + + PfxDiv2n() {} + + PfxDiv2n(unsigned int i,unsigned int n) + { + id = i; + num = n; + } +}; + +template +void pfxHybridSort(SortData *data,SortData *buff,unsigned int n) +{ + unsigned int numDiv = 0; + PfxDiv2n divData[32]; + + unsigned int id = 0; + unsigned int rest = n; + unsigned int mask = 0x01; + + while(rest>0) { + if((mask&n)>0) { + divData[numDiv++] = PfxDiv2n(id,mask); + pfxBitonicSort(data+id,buff+id,mask); + rest ^= mask; + id += mask; + } + mask <<= 1; + } + + if(numDiv==1) { + for(unsigned int i=0;i 2 || param.axis < 0) return SCE_PFX_ERR_INVALID_VALUE; + if(!SCE_PFX_PTR_IS_ALIGNED16(param.proxies) || !SCE_PFX_PTR_IS_ALIGNED16(param.pairBuff)) return SCE_PFX_ERR_INVALID_ALIGN; + if(SCE_PFX_AVAILABLE_BYTES_ALIGN16(param.workBuff,param.workBytes) < pfxGetWorkBytesOfFindPairs(param.maxPairs,maxTasks) ) return SCE_PFX_ERR_OUT_OF_BUFFER; + if(SCE_PFX_AVAILABLE_BYTES_ALIGN16(param.pairBuff,param.pairBytes) < pfxGetPairBytesOfFindPairs(param.maxPairs) ) return SCE_PFX_ERR_OUT_OF_BUFFER; + return SCE_PFX_OK; +} + +PfxUInt32 pfxGetPairBytesOfDecomposePairs(PfxUInt32 numPreviousPairs,PfxUInt32 numCurrentPairs) +{ + return sizeof(PfxBroadphasePair)*(numPreviousPairs*2+numCurrentPairs); +} + +PfxInt32 pfxCheckParamOfDecomposePairs(const PfxDecomposePairsParam ¶m,int maxTasks) +{ + if(!param.workBuff || !param.pairBuff || !param.previousPairs || !param.currentPairs) return SCE_PFX_ERR_INVALID_VALUE; + if(!SCE_PFX_PTR_IS_ALIGNED16(param.previousPairs) || !SCE_PFX_PTR_IS_ALIGNED16(param.currentPairs) || !SCE_PFX_PTR_IS_ALIGNED16(param.pairBuff) ) return SCE_PFX_ERR_INVALID_ALIGN; + if(SCE_PFX_AVAILABLE_BYTES_ALIGN16(param.workBuff,param.workBytes) < pfxGetWorkBytesOfDecomposePairs(param.numPreviousPairs,param.numCurrentPairs,maxTasks)) return SCE_PFX_ERR_OUT_OF_BUFFER; + if(SCE_PFX_AVAILABLE_BYTES_ALIGN16(param.pairBuff,param.pairBytes) < pfxGetPairBytesOfDecomposePairs(param.numPreviousPairs,param.numCurrentPairs)) return SCE_PFX_ERR_OUT_OF_BUFFER; + return SCE_PFX_OK; +} + +/////////////////////////////////////////////////////////////////////////////// +// SINGLE THREAD + +PfxInt32 pfxUpdateBroadphaseProxies(PfxUpdateBroadphaseProxiesParam ¶m,PfxUpdateBroadphaseProxiesResult &result) +{ + PfxInt32 ret = pfxCheckParamOfUpdateBroadphaseProxies(param); + if(ret != SCE_PFX_OK) return ret; + + SCE_PFX_PUSH_MARKER("pfxUpdateBroadphaseProxies") + + result.numOutOfWorldProxies = 0; + + for(int i=0;i<(int)param.numRigidBodies;i++) { + PfxInt32 chk = pfxUpdateBroadphaseProxy( + param.proxiesX[i], + param.proxiesY[i], + param.proxiesZ[i], + param.proxiesXb[i], + param.proxiesYb[i], + param.proxiesZb[i], + param.offsetRigidStates[i], + param.offsetCollidables[i], + param.worldCenter, + param.worldExtent); + + if(chk == SCE_PFX_ERR_OUT_OF_WORLD) { + result.numOutOfWorldProxies++; + + if(param.outOfWorldBehavior & SCE_PFX_OUT_OF_WORLD_BEHAVIOR_FIX_MOTION) { + PfxRigidState &state = param.offsetRigidStates[i]; + state.setMotionType(kPfxMotionTypeFixed); + pfxSetMotionMask(param.proxiesX[i],state.getMotionMask()); + pfxSetMotionMask(param.proxiesY[i],state.getMotionMask()); + pfxSetMotionMask(param.proxiesZ[i],state.getMotionMask()); + pfxSetMotionMask(param.proxiesXb[i],state.getMotionMask()); + pfxSetMotionMask(param.proxiesYb[i],state.getMotionMask()); + pfxSetMotionMask(param.proxiesZb[i],state.getMotionMask()); + } + + if(param.outOfWorldBehavior & SCE_PFX_OUT_OF_WORLD_BEHAVIOR_REMOVE_PROXY) { + pfxSetKey(param.proxiesX[i],SCE_PFX_SENTINEL_KEY); + pfxSetKey(param.proxiesY[i],SCE_PFX_SENTINEL_KEY); + pfxSetKey(param.proxiesZ[i],SCE_PFX_SENTINEL_KEY); + pfxSetKey(param.proxiesXb[i],SCE_PFX_SENTINEL_KEY); + pfxSetKey(param.proxiesYb[i],SCE_PFX_SENTINEL_KEY); + pfxSetKey(param.proxiesZb[i],SCE_PFX_SENTINEL_KEY); + } + } + } + + PfxHeapManager pool((unsigned char*)param.workBuff,param.workBytes); + PfxBroadphaseProxy *workProxies = (PfxBroadphaseProxy*)pool.allocate(sizeof(PfxBroadphaseProxy)*param.numRigidBodies,PfxHeapManager::ALIGN128); + + pfxSort(param.proxiesX,workProxies,param.numRigidBodies); + pfxSort(param.proxiesY,workProxies,param.numRigidBodies); + pfxSort(param.proxiesZ,workProxies,param.numRigidBodies); + pfxSort(param.proxiesXb,workProxies,param.numRigidBodies); + pfxSort(param.proxiesYb,workProxies,param.numRigidBodies); + pfxSort(param.proxiesZb,workProxies,param.numRigidBodies); + + pool.deallocate(workProxies); + + SCE_PFX_POP_MARKER(); + + return SCE_PFX_OK; +} + +PfxInt32 pfxFindPairs(PfxFindPairsParam ¶m,PfxFindPairsResult &result) +{ + PfxInt32 ret = pfxCheckParamOfFindPairs(param,0); + if(ret != SCE_PFX_OK) return ret; + + SCE_PFX_PUSH_MARKER("pfxFindPairs") + + void *workBuff = param.workBuff; + PfxUInt32 workBytes = param.workBytes; + PfxBroadphaseProxy *proxies = param.proxies; + PfxUInt32 numProxies = param.numProxies; + PfxUInt32 maxPairs = param.maxPairs; + int axis = param.axis; + + (void) workBytes; + + PfxBroadphasePair *pairs = (PfxBroadphasePair*)SCE_PFX_PTR_ALIGN16(param.pairBuff); + PfxUInt32 numPairs = 0; + + for(PfxUInt32 i=0;i= maxPairs) + return SCE_PFX_ERR_OUT_OF_MAX_PAIRS; + + PfxBroadphasePair &pair = pairs[numPairs++]; + pfxSetActive(pair,true); + pfxSetObjectIdA(pair,pfxGetObjectId(proxyA)); + pfxSetObjectIdB(pair,pfxGetObjectId(proxyB)); + pfxSetMotionMaskA(pair,pfxGetMotionMask(proxyA)); + pfxSetMotionMaskB(pair,pfxGetMotionMask(proxyB)); + + pfxSetKey(pair,pfxCreateUniqueKey(pfxGetObjectId(proxyA),pfxGetObjectId(proxyB))); + } + } + } + + pfxSort(pairs,(PfxBroadphasePair*)workBuff,numPairs); + + result.pairs = pairs; + result.numPairs = numPairs; + + SCE_PFX_POP_MARKER(); + + return SCE_PFX_OK; +} + +PfxInt32 pfxDecomposePairs(PfxDecomposePairsParam ¶m,PfxDecomposePairsResult &result) +{ + PfxInt32 ret = pfxCheckParamOfDecomposePairs(param,0); + if(ret != SCE_PFX_OK) return ret; + + SCE_PFX_PUSH_MARKER("pfxDecomposePairs") + + PfxBroadphasePair *previousPairs = param.previousPairs; + PfxUInt32 numPreviousPairs = param.numPreviousPairs; + PfxBroadphasePair *currentPairs = param.currentPairs; + PfxUInt32 numCurrentPairs = param.numCurrentPairs; + + PfxBroadphasePair *outNewPairs = (PfxBroadphasePair*)SCE_PFX_PTR_ALIGN16(param.pairBuff); + PfxBroadphasePair *outKeepPairs = outNewPairs + numCurrentPairs; + PfxBroadphasePair *outRemovePairs = outKeepPairs + numPreviousPairs; + + PfxUInt32 nNew = 0; + PfxUInt32 nKeep = 0; + PfxUInt32 nRemove = 0; + + PfxUInt32 oldId = 0,newId = 0; + + while(oldId pfxGetKey(previousPairs[oldId])) { + // remove + SCE_PFX_ASSERT(nRemove<=numPreviousPairs); + outRemovePairs[nRemove] = previousPairs[oldId]; + nRemove++; + oldId++; + } + else if(pfxGetKey(currentPairs[newId]) == pfxGetKey(previousPairs[oldId])) { + // keep + SCE_PFX_ASSERT(nKeep<=numPreviousPairs); + outKeepPairs[nKeep] = currentPairs[newId]; + pfxSetContactId(outKeepPairs[nKeep],pfxGetContactId(previousPairs[oldId])); + nKeep++; + oldId++; + newId++; + } + else { + // new + SCE_PFX_ASSERT(nNew<=numCurrentPairs); + outNewPairs[nNew] = currentPairs[newId]; + nNew++; + newId++; + } + }; + + if(newIdio); + + PfxRayInput *rayInputs = (PfxRayInput*)arg->data[0]; + PfxRayOutput *rayOutputs = (PfxRayOutput*)arg->data[1]; + PfxUInt32 iFirstRay = arg->data[2]; + PfxUInt32 iEndRay = arg->data[3]; + + for(PfxUInt32 i = iFirstRay; i < iEndRay; i++) + { + pfxCastSingleRay(rayInputs[i], rayOutputs[i], param); + } +} + +//---------------------------------------------------------------------------- +// pfxCastRays +// +/// Perform cast rays in parallel using a task manager. +/// +/// @param rayInputs [in] Array of rays to cast +/// @param rayOutputs [out] On return contains output of ray casts +/// @param param Information about ray cast +/// @param taskManager Pointer to the thread task manager to use +//---------------------------------------------------------------------------- +void pfxCastRays(PfxRayInput *rayInputs,PfxRayOutput *rayOutputs,int numRays, + PfxRayCastParam ¶m,PfxTaskManager *taskManager) +{ + SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesX)); + SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesY)); + SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesZ)); + SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesXb)); + SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesYb)); + SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesZb)); + SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.offsetRigidStates)); + SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.offsetCollidables)); + + SCE_PFX_PUSH_MARKER("pfxCastRays"); + + PfxUInt32 maxBatchSize = numRays / (PfxUInt32)(taskManager->getNumTasks()); + PfxUInt32 iEnd = maxBatchSize, iStart = 0; + int task = 0; + taskManager->setTaskEntry((void*)pfxCastRaysStartTaskEntry); + + for (task = 0; task < taskManager->getNumTasks() - 1; task++, iStart += maxBatchSize, iEnd += maxBatchSize) + { + taskManager->startTask(task, static_cast(¶m), (PfxUInt32)rayInputs, (PfxUInt32)rayOutputs, iStart, iEnd); + } + + // send final task + iEnd = numRays; + taskManager->startTask(taskManager->getNumTasks() - 1, static_cast(¶m), iStart, iEnd, 0, 0); + + // wait for tasks to complete + PfxUInt32 data1, data2, data3, data4; + for (PfxUInt32 i = 0; i < taskManager->getNumTasks(); i++) + taskManager->waitTask(task, data1, data2, data3, data4); + + SCE_PFX_POP_MARKER(); +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/low_level/collision/pfx_batched_ray_cast_single.cpp b/Extras/PhysicsEffects/src/low_level/collision/pfx_batched_ray_cast_single.cpp new file mode 100644 index 0000000..49a4c43 --- /dev/null +++ b/Extras/PhysicsEffects/src/low_level/collision/pfx_batched_ray_cast_single.cpp @@ -0,0 +1,47 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/low_level/collision/pfx_batched_ray_cast.h" + +namespace sce { +namespace PhysicsEffects { + +/////////////////////////////////////////////////////////////////////////////// +// SINGLE THREAD + +void pfxCastRaysStart(PfxRayInput *rayInputs,PfxRayOutput *rayOutputs,int numRays,PfxRayCastParam ¶m) +{ + for(int i=0;iio); + + PfxUInt32 iFirstContactPair = arg->data[0]; + PfxUInt32 iEndContactPair = arg->data[1]; + + PfxConstraintPair *contactPairs = param.contactPairs; + PfxContactManifold *offsetContactManifolds = param.offsetContactManifolds; + PfxRigidState *offsetRigidStates = param.offsetRigidStates; + PfxCollidable *offsetCollidables = param.offsetCollidables; + PfxUInt32 numRigidBodies = param.numRigidBodies; + + for(PfxUInt32 i = iFirstContactPair; i < iEndContactPair; i++) + { + const PfxBroadphasePair &pair = contactPairs[i]; + if(!pfxCheckCollidableInCollision(pair)) + continue; + + PfxUInt32 iContact = pfxGetContactId(pair); + PfxUInt32 iA = pfxGetObjectIdA(pair); + PfxUInt32 iB = pfxGetObjectIdB(pair); + + PfxContactManifold &contact = offsetContactManifolds[iContact]; + + SCE_PFX_ALWAYS_ASSERT(iA==contact.getRigidBodyIdA()); + SCE_PFX_ALWAYS_ASSERT(iB==contact.getRigidBodyIdB()); + + PfxRigidState &stateA = offsetRigidStates[iA]; + PfxRigidState &stateB = offsetRigidStates[iB]; + PfxCollidable &collA = offsetCollidables[iA]; + PfxCollidable &collB = offsetCollidables[iB]; + PfxTransform3 tA0(stateA.getOrientation(), stateA.getPosition()); + PfxTransform3 tB0(stateB.getOrientation(), stateB.getPosition()); + + PfxContactCache contactCache; + + PfxShapeIterator itrShapeA(collA); + for(PfxUInt32 j=0;jgetNumTasks()); + PfxUInt32 iEnd = maxBatchSize, iStart = 0; + int task = 0; + taskManager->setTaskEntry((void*)pfxDetectCollisionTaskEntry); + + for (task = 0; task < taskManager->getNumTasks() - 1; task++, iStart += maxBatchSize, iEnd += maxBatchSize) + { + taskManager->startTask(task, static_cast(¶m), iStart, iEnd, 0, 0); + } + + // send final task + iEnd = param.numContactPairs; + taskManager->startTask(taskManager->getNumTasks() - 1, static_cast(¶m), iStart, iEnd, 0, 0); + + // wait for tasks to complete + PfxUInt32 data1, data2, data3, data4; + for (PfxUInt32 i = 0; i < taskManager->getNumTasks(); i++) + taskManager->waitTask(task, data1, data2, data3, data4); + + SCE_PFX_POP_MARKER(); + + return SCE_PFX_OK; +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/low_level/collision/pfx_collision_detection_single.cpp b/Extras/PhysicsEffects/src/low_level/collision/pfx_collision_detection_single.cpp new file mode 100644 index 0000000..424230f --- /dev/null +++ b/Extras/PhysicsEffects/src/low_level/collision/pfx_collision_detection_single.cpp @@ -0,0 +1,125 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_perf_counter.h" +#include "../../../include/physics_effects/base_level/collision/pfx_shape_iterator.h" +#include "../../../include/physics_effects/low_level/collision/pfx_collision_detection.h" +#include "../../base_level/broadphase/pfx_check_collidable.h" +#include "../../base_level/collision/pfx_contact_cache.h" +#include "pfx_detect_collision_func.h" + +namespace sce { +namespace PhysicsEffects { + +/////////////////////////////////////////////////////////////////////////////// + +int pfxCheckParamOfDetectCollision(PfxDetectCollisionParam ¶m) +{ + if(!param.contactPairs || !param.offsetContactManifolds || !param.offsetRigidStates|| !param.offsetCollidables ) return SCE_PFX_ERR_INVALID_VALUE; + if(!SCE_PFX_PTR_IS_ALIGNED16(param.contactPairs) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetContactManifolds) || + !SCE_PFX_PTR_IS_ALIGNED16(param.offsetRigidStates) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetCollidables)) return SCE_PFX_ERR_INVALID_ALIGN; + return SCE_PFX_OK; +} + +/////////////////////////////////////////////////////////////////////////////// +// SINGLE THREAD + +#define SCE_PFX_CONTACT_THRESHOLD 0.0f + +PfxInt32 pfxDetectCollision(PfxDetectCollisionParam ¶m) +{ + PfxInt32 ret = pfxCheckParamOfDetectCollision(param); + if(ret != SCE_PFX_OK) + return ret; + + SCE_PFX_PUSH_MARKER("pfxDetectCollision"); + + PfxConstraintPair *contactPairs = param.contactPairs; + PfxUInt32 numContactPairs = param.numContactPairs; + PfxContactManifold *offsetContactManifolds = param.offsetContactManifolds; + PfxRigidState *offsetRigidStates = param.offsetRigidStates; + PfxCollidable *offsetCollidables = param.offsetCollidables; + PfxUInt32 numRigidBodies = param.numRigidBodies; + + for(PfxUInt32 i=0;i= kPfxShapeCount || shapeTypeB >= kPfxShapeCount) { + return SCE_PFX_ERR_OUT_OF_RANGE; + } + + funcTbl_detectCollision[shapeTypeA][shapeTypeB] = func; + + return SCE_PFX_OK; +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/low_level/collision/pfx_detect_collision_func.h b/Extras/PhysicsEffects/src/low_level/collision/pfx_detect_collision_func.h new file mode 100644 index 0000000..77a5a46 --- /dev/null +++ b/Extras/PhysicsEffects/src/low_level/collision/pfx_detect_collision_func.h @@ -0,0 +1,37 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_DETECT_COLLISION_FUNC_H +#define _SCE_PFX_DETECT_COLLISION_FUNC_H + +#include "../../base_level/collision/pfx_contact_cache.h" + +namespace sce { +namespace PhysicsEffects { + +typedef void (*pfx_detect_collision_func)( + PfxContactCache &contacts, + const PfxShape & shapeA,const PfxTransform3 &offsetTransformA,const PfxTransform3 &worldTransformA,int shapeIdA, + const PfxShape & shapeB,const PfxTransform3 &offsetTransformB,const PfxTransform3 &worldTransformB,int shapeIdB, + float contactThreshold); + +pfx_detect_collision_func pfxGetDetectCollisionFunc(PfxUInt8 shapeTypeA,PfxUInt8 shapeTypeB); + +int pfxSetDetectCollisionFunc(PfxUInt8 shapeTypeA,PfxUInt8 shapeTypeB,pfx_detect_collision_func func); + +} //namespace PhysicsEffects +} //namespace sce +#endif // _SCE_PFX_DETECT_COLLISION_FUNC_H diff --git a/Extras/PhysicsEffects/src/low_level/collision/pfx_intersect_ray_func.cpp b/Extras/PhysicsEffects/src/low_level/collision/pfx_intersect_ray_func.cpp new file mode 100644 index 0000000..78467cd --- /dev/null +++ b/Extras/PhysicsEffects/src/low_level/collision/pfx_intersect_ray_func.cpp @@ -0,0 +1,129 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/collision/pfx_shape.h" +#include "../../base_level/collision/pfx_intersect_ray_box.h" +#include "../../base_level/collision/pfx_intersect_ray_sphere.h" +#include "../../base_level/collision/pfx_intersect_ray_capsule.h" +#include "../../base_level/collision/pfx_intersect_ray_cylinder.h" +#include "../../base_level/collision/pfx_intersect_ray_convex.h" +#include "../../base_level/collision/pfx_intersect_ray_large_tri_mesh.h" +#include "pfx_intersect_ray_func.h" + + +namespace sce { +namespace PhysicsEffects { + + +/////////////////////////////////////////////////////////////////////////////// +// Ray Intersection Function Table + +PfxBool intersectRayFuncDummy( + const PfxRayInput &ray,PfxRayOutput &out, + const PfxShape &shape,const PfxTransform3 &transform) +{ + (void)ray,(void)out,(void)shape,(void)transform; + return false; +} + +PfxBool intersectRayFuncBox( + const PfxRayInput &ray,PfxRayOutput &out, + const PfxShape &shape,const PfxTransform3 &transform) +{ + return pfxIntersectRayBox(ray,out,shape.getBox(),transform); +} + +PfxBool intersectRayFuncSphere( + const PfxRayInput &ray,PfxRayOutput &out, + const PfxShape &shape,const PfxTransform3 &transform) +{ + return pfxIntersectRaySphere(ray,out,shape.getSphere(),transform); +} + +PfxBool intersectRayFuncCapsule( + const PfxRayInput &ray,PfxRayOutput &out, + const PfxShape &shape,const PfxTransform3 &transform) +{ + return pfxIntersectRayCapsule(ray,out,shape.getCapsule(),transform); +} + +PfxBool intersectRayFuncCylinder( + const PfxRayInput &ray,PfxRayOutput &out, + const PfxShape &shape,const PfxTransform3 &transform) +{ + return pfxIntersectRayCylinder(ray,out,shape.getCylinder(),transform); +} + +PfxBool intersectRayFuncConvex( + const PfxRayInput &ray,PfxRayOutput &out, + const PfxShape &shape,const PfxTransform3 &transform) +{ +const PfxConvexMesh *convex = shape.getConvexMesh(); + + PfxBool ret = pfxIntersectRayConvex(ray,out,(const void*)convex,transform); + + + return ret; +} + +PfxBool intersectRayFuncLargeTriMesh( + const PfxRayInput &ray,PfxRayOutput &out, + const PfxShape &shape,const PfxTransform3 &transform) +{ +const PfxLargeTriMesh *lmesh = shape.getLargeTriMesh(); + + PfxBool ret = pfxIntersectRayLargeTriMesh(ray,out,(const void*)lmesh,transform); + + + return ret; +} + +PfxIntersectRayFunc funcTbl_intersectRay[kPfxShapeCount] = { + intersectRayFuncSphere, + intersectRayFuncBox, + intersectRayFuncCapsule, + intersectRayFuncCylinder, + intersectRayFuncConvex, + intersectRayFuncLargeTriMesh, + intersectRayFuncDummy, + intersectRayFuncDummy, + intersectRayFuncDummy, + intersectRayFuncDummy, + intersectRayFuncDummy, + intersectRayFuncDummy, +}; + +/////////////////////////////////////////////////////////////////////////////// +// Ray Intersection Function Table Interface + +PfxIntersectRayFunc pfxGetIntersectRayFunc(PfxUInt8 shapeType) +{ + return funcTbl_intersectRay[shapeType]; +} + +PfxInt32 pfxSetIntersectRayFunc(PfxUInt8 shapeType,PfxIntersectRayFunc func) +{ + if(shapeType >= kPfxShapeCount) { + return SCE_PFX_ERR_OUT_OF_RANGE; + } + + funcTbl_intersectRay[shapeType] = func; + + return SCE_PFX_OK; +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/low_level/collision/pfx_intersect_ray_func.h b/Extras/PhysicsEffects/src/low_level/collision/pfx_intersect_ray_func.h new file mode 100644 index 0000000..e0e53f9 --- /dev/null +++ b/Extras/PhysicsEffects/src/low_level/collision/pfx_intersect_ray_func.h @@ -0,0 +1,36 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_INTERSECT_RAY_FUNC_H +#define _SCE_PFX_INTERSECT_RAY_FUNC_H + +#include "../../../include/physics_effects/base_level/collision/pfx_ray.h" + +namespace sce { +namespace PhysicsEffects { + +typedef PfxBool (*PfxIntersectRayFunc)( + const PfxRayInput &ray,PfxRayOutput &out, + const PfxShape &shape,const PfxTransform3 &transform); + +PfxIntersectRayFunc pfxGetIntersectRayFunc(PfxUInt8 shapeType); + +PfxInt32 pfxSetIntersectRayFunc(PfxUInt8 shapeType,PfxIntersectRayFunc func); + +} //namespace PhysicsEffects +} //namespace sce + +#endif /* _SCE_PFX_INTERSECT_RAY_FUNC_H */ diff --git a/Extras/PhysicsEffects/src/low_level/collision/pfx_island_generation.cpp b/Extras/PhysicsEffects/src/low_level/collision/pfx_island_generation.cpp new file mode 100644 index 0000000..bb65583 --- /dev/null +++ b/Extras/PhysicsEffects/src/low_level/collision/pfx_island_generation.cpp @@ -0,0 +1,231 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/rigidbody/pfx_rigid_state.h" +#include "../../../include/physics_effects/low_level/collision/pfx_island_generation.h" + +namespace sce { +namespace PhysicsEffects { + +struct PfxIslandNode { + PfxUInt32 rootId; + PfxUInt32 rank; + PfxUInt32 islandId; + PfxUInt32 isRoot; +}; + +struct PfxIslandUnit +{ + PfxUInt32 id; + PfxIslandUnit *next; +}; + +struct PfxIsland +{ + PfxUInt32 numNodes; + PfxUInt32 numIslands; + PfxIslandNode *nodes; + PfxIslandUnit *islandsUnits; + PfxIslandUnit **islandsHeads; +}; + +PfxUInt32 pfxIslandNodeFind(PfxUInt32 i,PfxIsland *island) +{ + if( i != island->nodes[i].rootId ) { + island->nodes[i].rootId = pfxIslandNodeFind(island->nodes[i].rootId,island); + } + return island->nodes[i].rootId; +} + +void pfxIslandNodeLink(PfxUInt32 iA,PfxUInt32 iB,PfxIsland *island) +{ + if(island->nodes[iA].rank > island->nodes[iB].rank) { + island->nodes[iB].rootId = iA; + } + else if(island->nodes[iA].rank == island->nodes[iB].rank) { + island->nodes[iA].rootId = iB; + island->nodes[iB].rank++; + } + else { + island->nodes[iA].rootId = iB; + } +} + +void pfxIslandNodeUnion(PfxUInt32 iA,PfxUInt32 iB,PfxIsland *island) +{ + SCE_PFX_ALWAYS_ASSERT(iAnumNodes); + SCE_PFX_ALWAYS_ASSERT(iBnumNodes); + + pfxIslandNodeLink(pfxIslandNodeFind(iA,island),pfxIslandNodeFind(iB,island),island); +} + +PfxUInt32 pfxGetIslandBytesOfGenerateIsland(PfxUInt32 numObjects) +{ + return 16 + + SCE_PFX_ALLOC_BYTES_ALIGN16(sizeof(PfxIsland)) + + SCE_PFX_ALLOC_BYTES_ALIGN16(sizeof(PfxIslandNode)*numObjects) + + SCE_PFX_ALLOC_BYTES_ALIGN16(sizeof(PfxIslandUnit*)*numObjects) + + SCE_PFX_ALLOC_BYTES_ALIGN16(sizeof(PfxIslandUnit)*numObjects); +} + +SCE_PFX_FORCE_INLINE int pfxCheckParamOfGenerateIsland(const PfxGenerateIslandParam ¶m) +{ + if(!param.islandBuff || !param.pairs) return SCE_PFX_ERR_INVALID_VALUE; + if(!SCE_PFX_PTR_IS_ALIGNED16(param.pairs)) return SCE_PFX_ERR_INVALID_ALIGN; + if(SCE_PFX_AVAILABLE_BYTES_ALIGN16(param.islandBuff,param.islandBytes) < pfxGetIslandBytesOfGenerateIsland(param.numObjects) ) return SCE_PFX_ERR_OUT_OF_BUFFER; + return SCE_PFX_OK; +} + +PfxInt32 pfxGenerateIsland(PfxGenerateIslandParam ¶m,PfxGenerateIslandResult &result) +{ + int ret = pfxCheckParamOfGenerateIsland(param); + if(ret != SCE_PFX_OK) return ret; + + PfxConstraintPair *pairs = param.pairs; + PfxUInt32 numPairs = param.numPairs; + PfxUInt32 numUnits = param.numObjects; + + memset(param.islandBuff,0,param.islandBytes); + + PfxHeapManager pool((unsigned char*)param.islandBuff,param.islandBytes); + + PfxIsland *island = (PfxIsland*)pool.allocate(sizeof(PfxIsland)); + island->numIslands = 0; + island->numNodes = numUnits; + island->nodes = (PfxIslandNode*)pool.allocate(sizeof(PfxIslandNode)*numUnits); + island->islandsHeads = (PfxIslandUnit**)pool.allocate(sizeof(PfxIslandUnit*)*numUnits); + island->islandsUnits = (PfxIslandUnit*)pool.allocate(sizeof(PfxIslandUnit)*numUnits); + + result.island = island; + + // 初期化 + for(PfxUInt32 i=0;inumNodes;i++) { + island->nodes[i].rootId = i; + island->nodes[i].rank = 0; + } + + return pfxAppendPairs(island,pairs,numPairs); +} + +PfxUInt32 pfxGetNumIslands(const PfxIsland *islands) +{ + SCE_PFX_ALWAYS_ASSERT(islands); + return islands->numIslands; +} + +PfxIslandUnit *pfxGetFirstUnitInIsland(const PfxIsland *islands,PfxUInt32 islandId) +{ + SCE_PFX_ALWAYS_ASSERT(islands); + SCE_PFX_ALWAYS_ASSERT(islandId < islands->numIslands); + return islands->islandsHeads[islandId]; +} + +PfxIslandUnit *pfxGetNextUnitInIsland(const PfxIslandUnit *islandUnit) +{ + SCE_PFX_ALWAYS_ASSERT(islandUnit); + return islandUnit->next; +} + +PfxUInt32 pfxGetUnitId(const PfxIslandUnit *islandUnit) +{ + SCE_PFX_ALWAYS_ASSERT(islandUnit); + return islandUnit->id; +} + +PfxUInt32 pfxGetIslandId(const PfxIsland *islands,PfxUInt32 unitId) +{ + SCE_PFX_ALWAYS_ASSERT(islands&&unitIdnumNodes); + return islands->nodes[unitId].islandId; +} + +PfxInt32 pfxAppendPairs(PfxIsland *island,PfxConstraintPair *pairs,PfxUInt32 numPairs) +{ + if(numPairs == 0) { + return SCE_PFX_OK; + } + + if(!island || !pairs) return SCE_PFX_ERR_INVALID_VALUE; + if(!SCE_PFX_PTR_IS_ALIGNED16(island) || !SCE_PFX_PTR_IS_ALIGNED16(pairs)) return SCE_PFX_ERR_INVALID_ALIGN; + + // 統合 + for(PfxUInt32 i=0;inumNodes); + SCE_PFX_ALWAYS_ASSERT(iBnumNodes); + + if( (SCE_PFX_MOTION_MASK_DYNAMIC(pfxGetMotionMaskA(pair)&SCE_PFX_MOTION_MASK_TYPE)) && + (SCE_PFX_MOTION_MASK_DYNAMIC(pfxGetMotionMaskB(pair)&SCE_PFX_MOTION_MASK_TYPE)) ) { + pfxIslandNodeUnion(iA,iB,island); + } + } + } + + // アイランド生成のための初期化 + for(PfxUInt32 i=0;inumNodes;i++) { + island->nodes[i].islandId = 0; + island->nodes[i].isRoot = 0; + island->islandsHeads[i] = NULL; + } + + // 親へ直結 + PfxUInt32 id = 0; + for(PfxUInt32 i=0;inumNodes;i++) { + PfxUInt32 rootId = pfxIslandNodeFind(i,island); + if( island->nodes[rootId].isRoot == 0 ) { + island->nodes[rootId].islandId = id++; + island->nodes[rootId].isRoot = 1; + } + island->nodes[i].islandId = island->nodes[rootId].islandId; + } + + // アイランド作成 + PfxUInt32 n = 0; + for(PfxUInt32 i=0;inumNodes;i++) { + PfxUInt32 islandId = island->nodes[i].islandId; + PfxIslandUnit *newUnit = &island->islandsUnits[n++]; + newUnit->id = i; + + if(!island->islandsHeads[islandId]) { + island->islandsHeads[islandId] = newUnit; + continue; + } + + PfxIslandUnit *unit=island->islandsHeads[islandId]; + island->islandsHeads[islandId] = newUnit; + newUnit->next = unit; + } + + island->numIslands = id; + + return SCE_PFX_OK; +} + +void pfxResetIsland(PfxIsland *island) +{ + SCE_PFX_ALWAYS_ASSERT(island); + island->numIslands = 0; + for(PfxUInt32 i=0;inumNodes;i++) { + island->nodes[i].rootId = i; + island->nodes[i].rank = 0; + } +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/low_level/collision/pfx_ray_cast.cpp b/Extras/PhysicsEffects/src/low_level/collision/pfx_ray_cast.cpp new file mode 100644 index 0000000..20b8446 --- /dev/null +++ b/Extras/PhysicsEffects/src/low_level/collision/pfx_ray_cast.cpp @@ -0,0 +1,228 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h" +#include "../../../include/physics_effects/low_level/collision/pfx_ray_cast.h" +#include "../../../include/physics_effects/base_level/collision/pfx_shape_iterator.h" +#include "pfx_intersect_ray_func.h" +#include "../../base_level/collision/pfx_intersect_common.h" + + +namespace sce { +namespace PhysicsEffects { + + +void pfxRayTraverseForward( + const PfxRayInput &ray,PfxRayOutput &out,const PfxAabb16 &rayAABB, + PfxBroadphaseProxy *proxies,int numProxies, + PfxRigidState *offsetRigidStates, + PfxCollidable *offsetCollidables, + int axis,const PfxVector3 ¢er,const PfxVector3 &half) +{ +#ifdef SCE_PFX_USE_GEOMETRY + PfxGeomSegment segment((PfxPoint3)ray.m_startPosition,ray.m_direction); +#endif + + for(int i=0;i=0;i--) { + PfxBroadphaseProxy &proxy = proxies[i]; + + // 終了条件のチェック + if(pfxGetXYZMax(proxy,axis) < pfxGetXYZMin(rayAABB,axis)) { + return; + } + + PfxVector3 boundOnRay = ray.m_startPosition + out.m_variable * ray.m_direction; + PfxVector3 AABBmin = pfxConvertCoordLocalToWorld(PfxVecInt3((PfxInt32)pfxGetXMin(proxy),(PfxInt32)pfxGetYMin(proxy),(PfxInt32)pfxGetZMin(proxy)),center,half); + PfxVector3 AABBmax = pfxConvertCoordLocalToWorld(PfxVecInt3((PfxInt32)pfxGetXMax(proxy),(PfxInt32)pfxGetYMax(proxy),(PfxInt32)pfxGetZMax(proxy)),center,half); + + if(AABBmax[axis] < boundOnRay[axis]) { + return; + } + + // スキップ + if(pfxGetXYZMax(rayAABB,axis) < pfxGetXYZMin(proxy,axis)) { + continue; + } + + PfxUInt16 rigidbodyId = pfxGetObjectId(proxy); + PfxUInt32 contactFilterSelf = pfxGetSelf(proxy); + PfxUInt32 contactFilterTarget = pfxGetTarget(proxy); + +#ifdef SCE_PFX_USE_GEOMETRY + PfxFloatInVec t_(1.0f); + PfxGeomAabb aabb((PfxPoint3)AABBmin,(PfxPoint3)AABBmax); + if( (ray.m_contactFilterSelf&contactFilterTarget) && (ray.m_contactFilterTarget&contactFilterSelf) && pfxTestAabb(rayAABB,proxy) && + intersectionPoint(segment,aabb,&t_) && t_ < out.m_variable ) { +#else + float t_=1.0f; + if( (ray.m_contactFilterSelf&contactFilterTarget) && (ray.m_contactFilterTarget&contactFilterSelf) && pfxTestAabb(rayAABB,proxy) && + pfxIntersectRayAABBFast(ray.m_startPosition,ray.m_direction,(AABBmax+AABBmin)*0.5f,(AABBmax-AABBmin)*0.5f,t_) && t_ < out.m_variable ) { +#endif + + PfxRigidState &state = offsetRigidStates[rigidbodyId]; + PfxCollidable &coll = offsetCollidables[rigidbodyId]; + PfxTransform3 transform(state.getOrientation(), state.getPosition()); + + PfxRayOutput tout = out; + + PfxShapeIterator itrShape(coll); + for(PfxUInt32 j=0;j 0) { + pfxRayTraverseForward( + ray,out,rayAABB, + proxies[axis],param.numProxies, + param.offsetRigidStates,param.offsetCollidables, + axis,param.rangeCenter,param.rangeExtent); + } + else { + pfxRayTraverseBackward( + ray,out,rayAABB, + proxies[axis+3],param.numProxies, + param.offsetRigidStates,param.offsetCollidables, + axis,param.rangeCenter,param.rangeExtent); + } +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/low_level/collision/pfx_refresh_contacts_parallel.cpp b/Extras/PhysicsEffects/src/low_level/collision/pfx_refresh_contacts_parallel.cpp new file mode 100644 index 0000000..4c167ab --- /dev/null +++ b/Extras/PhysicsEffects/src/low_level/collision/pfx_refresh_contacts_parallel.cpp @@ -0,0 +1,115 @@ +/* +Applied Research Associates Inc. (c)2011 + +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_perf_counter.h" +#include "../../../include/physics_effects/base_level/sort/pfx_sort.h" +#include "../../../include/physics_effects/low_level/collision/pfx_refresh_contacts.h" + +namespace sce { +namespace PhysicsEffects { + +/////////////////////////////////////////////////////////////////////////////// +// This function is implemented in pfx_refresh_contacts_single.cpp +extern int pfxCheckParamOfRefreshContacts(PfxRefreshContactsParam ¶m); + +/////////////////////////////////////////////////////////////////////////////// +// MULTIPLE THREADS + +//---------------------------------------------------------------------------- +// pfxRefreshContactsTaskEntry +// +/// The thread PfxTaskEntry function used to perform refresh contacts in +/// parallel +//---------------------------------------------------------------------------- +void pfxRefreshContactsTaskEntry(PfxTaskArg *arg) +{ + PfxRefreshContactsParam ¶m = *((PfxRefreshContactsParam*)arg->io); + + PfxUInt32 iFirstContactPair = arg->data[0]; + PfxUInt32 iEndContactPair = arg->data[1]; + + PfxConstraintPair *contactPairs = param.contactPairs; + PfxContactManifold *offsetContactManifolds = param.offsetContactManifolds; + PfxRigidState *offsetRigidStates = param.offsetRigidStates; + PfxUInt32 numRigidBodies = param.numRigidBodies; + + for(PfxUInt32 i = iFirstContactPair; i < iEndContactPair; i++) + { + PfxBroadphasePair &pair = contactPairs[i]; + + PfxUInt32 iContact = pfxGetContactId(pair); + PfxUInt32 iA = pfxGetObjectIdA(pair); + PfxUInt32 iB = pfxGetObjectIdB(pair); + + PfxContactManifold &contact = offsetContactManifolds[iContact]; + + SCE_PFX_ALWAYS_ASSERT(iA==contact.getRigidBodyIdA()); + SCE_PFX_ALWAYS_ASSERT(iB==contact.getRigidBodyIdB()); + + PfxRigidState &instA = offsetRigidStates[iA]; + PfxRigidState &instB = offsetRigidStates[iB]; + + contact.refresh( + instA.getPosition(),instA.getOrientation(), + instB.getPosition(),instB.getOrientation() ); + } +} + +//---------------------------------------------------------------------------- +// pfxRefreshContacts +// +/// Perform refresh contacts in parallel using a task manager. +/// +/// @param param Information about contact pairs +/// @param taskManager Pointer to the thread task manager to use +/// +/// @return SCE_PFX_OK if successful, otherwise, returns an error code. +//---------------------------------------------------------------------------- +PfxInt32 pfxRefreshContacts(PfxRefreshContactsParam ¶m, PfxTaskManager *taskManager) +{ + PfxInt32 ret = pfxCheckParamOfRefreshContacts(param); + if(ret != SCE_PFX_OK) return ret; + + SCE_PFX_PUSH_MARKER("pfxRefreshContacts"); + + PfxUInt32 maxBatchSize = param.numContactPairs / (PfxUInt32)(taskManager->getNumTasks()); + PfxUInt32 iEnd = maxBatchSize, iStart = 0; + int task = 0; + taskManager->setTaskEntry((void*)pfxRefreshContactsTaskEntry); + + for (task = 0; task < taskManager->getNumTasks() - 1; task++, iStart += maxBatchSize, iEnd += maxBatchSize) + { + taskManager->startTask(task, static_cast(¶m), iStart, iEnd, 0, 0); + } + + // send final task + iEnd = param.numContactPairs; + taskManager->startTask(taskManager->getNumTasks() - 1, static_cast(¶m), iStart, iEnd, 0, 0); + + // wait for tasks to complete + PfxUInt32 data1, data2, data3, data4; + for (PfxUInt32 i = 0; i < taskManager->getNumTasks(); i++) + taskManager->waitTask(task, data1, data2, data3, data4); + + SCE_PFX_POP_MARKER(); + + return SCE_PFX_OK; +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/low_level/collision/pfx_refresh_contacts_single.cpp b/Extras/PhysicsEffects/src/low_level/collision/pfx_refresh_contacts_single.cpp new file mode 100644 index 0000000..8bce7d5 --- /dev/null +++ b/Extras/PhysicsEffects/src/low_level/collision/pfx_refresh_contacts_single.cpp @@ -0,0 +1,76 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_perf_counter.h" +#include "../../../include/physics_effects/base_level/sort/pfx_sort.h" +#include "../../../include/physics_effects/low_level/collision/pfx_refresh_contacts.h" + +namespace sce { +namespace PhysicsEffects { + +int pfxCheckParamOfRefreshContacts(PfxRefreshContactsParam ¶m) +{ + if(!param.contactPairs || !param.offsetContactManifolds || !param.offsetRigidStates ) return SCE_PFX_ERR_INVALID_VALUE; + if(!SCE_PFX_PTR_IS_ALIGNED16(param.contactPairs) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetContactManifolds) || + !SCE_PFX_PTR_IS_ALIGNED16(param.offsetRigidStates)) return SCE_PFX_ERR_INVALID_ALIGN; + return SCE_PFX_OK; +} + +/////////////////////////////////////////////////////////////////////////////// +// SINGLE THREAD + +PfxInt32 pfxRefreshContacts(PfxRefreshContactsParam ¶m) +{ + PfxInt32 ret = pfxCheckParamOfRefreshContacts(param); + if(ret != SCE_PFX_OK) return ret; + + SCE_PFX_PUSH_MARKER("pfxRefreshContacts"); + + PfxConstraintPair *contactPairs = param.contactPairs; + PfxUInt32 numContactPairs = param.numContactPairs; + PfxContactManifold *offsetContactManifolds = param.offsetContactManifolds; + PfxRigidState *offsetRigidStates = param.offsetRigidStates; + PfxUInt32 numRigidBodies = param.numRigidBodies; + + for(PfxUInt32 i=0;i0&&(!param.contactPairs||!param.offsetContactManifolds)) || + (param.numJointPairs>0&&(!param.jointPairs||!param.offsetJoints)) || !param.offsetRigidStates || !param.offsetSolverBodies) return SCE_PFX_ERR_INVALID_VALUE; + if(!SCE_PFX_PTR_IS_ALIGNED16(param.contactPairs) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetContactManifolds) || + !SCE_PFX_PTR_IS_ALIGNED16(param.jointPairs) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetJoints) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetRigidStates) || + !SCE_PFX_PTR_IS_ALIGNED16(param.offsetSolverBodies)) return SCE_PFX_ERR_INVALID_ALIGN; + if(SCE_PFX_AVAILABLE_BYTES_ALIGN16(param.workBuff,param.workBytes) < pfxGetWorkBytesOfSolveConstraints(param.numRigidBodies,param.numContactPairs,param.numJointPairs, taskManager->getNumTasks()) ) return SCE_PFX_ERR_OUT_OF_BUFFER; + return SCE_PFX_OK; +} + +/////////////////////////////////////////////////////////////////////////////// +// MULTIPLE THREADS + +//---------------------------------------------------------------------------- +// pfxSetupSolverBodiesTaskEntry +// +/// The thread PfxTaskEntry function used to setup solver bodies in parallel. +//---------------------------------------------------------------------------- +void pfxSetupSolverBodiesTaskEntry(PfxTaskArg *arg) +{ + PfxSetupSolverBodiesParam ¶m = *((PfxSetupSolverBodiesParam*)arg->io); + + PfxUInt32 iFirstBody = arg->data[0]; + PfxUInt32 iEndBody = arg->data[1]; + + PfxRigidState *states = param.states; + PfxRigidBody *bodies = param.bodies; + PfxSolverBody *solverBodies = param.solverBodies; + + for(PfxUInt32 i = iFirstBody; i < iEndBody; i++) + { + PfxRigidState &state = states[i]; + PfxRigidBody &body = bodies[i]; + PfxSolverBody &solverBody = solverBodies[i]; + + solverBody.m_orientation = state.getOrientation(); + solverBody.m_deltaLinearVelocity = PfxVector3(0.0f); + solverBody.m_deltaAngularVelocity = PfxVector3(0.0f); + solverBody.m_motionType = state.getMotionMask(); + + if(SCE_PFX_MOTION_MASK_DYNAMIC(state.getMotionType())) { + PfxMatrix3 ori(solverBody.m_orientation); + solverBody.m_massInv = body.getMassInv(); + solverBody.m_inertiaInv = ori * body.getInertiaInv() * transpose(ori); + } + else { + solverBody.m_massInv = 0.0f; + solverBody.m_inertiaInv = PfxMatrix3(0.0f); + } + } + + SCE_PFX_POP_MARKER(); +} + +//---------------------------------------------------------------------------- +// pfxSetupSolverBodies +// +/// Perform setup solver bodies in parallel using a task manager. +/// +/// @param param Information about rigid bodies +/// @param taskManager Pointer to the thread task manager to use +/// +/// @return SCE_PFX_OK if successful, otherwise, returns an error code. +//---------------------------------------------------------------------------- +PfxInt32 pfxSetupSolverBodies(PfxSetupSolverBodiesParam ¶m, + PfxTaskManager *taskManager) +{ + PfxInt32 ret = pfxCheckParamOfSetupSolverBodies(param); + if(ret != SCE_PFX_OK) return ret; + + SCE_PFX_PUSH_MARKER("pfxSetupSolverBodies"); + + PfxUInt32 maxBatchSize = param.numRigidBodies / (PfxUInt32)(taskManager->getNumTasks()); + PfxUInt32 iEnd = maxBatchSize, iStart = 0; + int task = 0; + taskManager->setTaskEntry((void*)pfxSetupSolverBodiesTaskEntry); + + for (task = 0; task < taskManager->getNumTasks() - 1; task++, iStart += maxBatchSize, iEnd += maxBatchSize) + { + taskManager->startTask(task, static_cast(¶m), iStart, iEnd, 0, 0); + } + + // send final task + iEnd = param.numRigidBodies; + taskManager->startTask(taskManager->getNumTasks() - 1, static_cast(¶m), iStart, iEnd, 0, 0); + + // wait for tasks to complete + PfxUInt32 data1, data2, data3, data4; + for (PfxUInt32 i = 0; i < taskManager->getNumTasks(); i++) + taskManager->waitTask(task, data1, data2, data3, data4); + + SCE_PFX_POP_MARKER(); + + return SCE_PFX_OK; +} + +//---------------------------------------------------------------------------- +// pfxSetupContactConstraintsTaskEntry +// +/// The thread PfxTaskEntry function used to setup contact constraints in +/// parallel. +//---------------------------------------------------------------------------- +void pfxSetupContactConstraintsTaskEntry(PfxTaskArg *arg) +{ + PfxSetupContactConstraintsParam ¶m = *((PfxSetupContactConstraintsParam*)arg->io); + + PfxUInt32 iFirstContactPair = arg->data[0]; + PfxUInt32 iEndContactPair = arg->data[1]; + + PfxConstraintPair *contactPairs = param.contactPairs; + PfxUInt32 numContactPairs = param.numContactPairs; + PfxContactManifold *offsetContactManifolds = param.offsetContactManifolds; + PfxRigidState *offsetRigidStates = param.offsetRigidStates; + PfxRigidBody *offsetRigidBodies = param.offsetRigidBodies; + PfxSolverBody *offsetSolverBodies = param.offsetSolverBodies; + + for(PfxUInt32 i = iFirstContactPair; i < iEndContactPair; i++) + { + PfxConstraintPair &pair = contactPairs[i]; + if(!pfxCheckSolver(pair)) + { + continue; + } + + PfxUInt16 iA = pfxGetObjectIdA(pair); + PfxUInt16 iB = pfxGetObjectIdB(pair); + PfxUInt32 iConstraint = pfxGetConstraintId(pair); + + PfxContactManifold &contact = offsetContactManifolds[iConstraint]; + + SCE_PFX_ALWAYS_ASSERT(iA==contact.getRigidBodyIdA()); + SCE_PFX_ALWAYS_ASSERT(iB==contact.getRigidBodyIdB()); + + PfxRigidState &stateA = offsetRigidStates[iA]; + PfxRigidBody &bodyA = offsetRigidBodies[iA]; + PfxSolverBody &solverBodyA = offsetSolverBodies[iA]; + + PfxRigidState &stateB = offsetRigidStates[iB]; + PfxRigidBody &bodyB = offsetRigidBodies[iB]; + PfxSolverBody &solverBodyB = offsetSolverBodies[iB]; + + contact.setInternalFlag(0); + + PfxFloat restitution = 0.5f * (bodyA.getRestitution() + bodyB.getRestitution()); + if(contact.getDuration() > 1) restitution = 0.0f; + + PfxFloat friction = sqrtf(bodyA.getFriction() * bodyB.getFriction()); + + for(int j=0;jgetNumTasks()); + PfxUInt32 iEnd = maxBatchSize, iStart = 0; + int task = 0; + taskManager->setTaskEntry((void*)pfxSetupContactConstraintsTaskEntry); + + for (task = 0; task < taskManager->getNumTasks() - 1; task++, iStart += maxBatchSize, iEnd += maxBatchSize) + { + taskManager->startTask(task, static_cast(¶m), iStart, iEnd, 0, 0); + } + + // send final task + iEnd = param.numContactPairs; + taskManager->startTask(taskManager->getNumTasks() - 1, static_cast(¶m), iStart, iEnd, 0, 0); + + // wait for tasks to complete + PfxUInt32 data1, data2, data3, data4; + for (PfxUInt32 i = 0; i < taskManager->getNumTasks(); i++) + taskManager->waitTask(task, data1, data2, data3, data4); + + SCE_PFX_POP_MARKER(); + + return SCE_PFX_OK; +} + +//---------------------------------------------------------------------------- +// pfxSetupJointConstraintsTaskEntry +// +/// The thread PfxTaskEntry function used to setup joint constraints in +/// parallel. +//---------------------------------------------------------------------------- +void pfxSetupJointConstraintsTaskEntry(PfxTaskArg *arg) +{ + PfxSetupJointConstraintsParam ¶m = *((PfxSetupJointConstraintsParam*)arg->io); + + PfxUInt32 iFirstJointPair = arg->data[0]; + PfxUInt32 iEndJointPair = arg->data[1]; + + PfxConstraintPair *jointPairs = param.jointPairs; + PfxUInt32 numJointPairs = param.numJointPairs; + PfxJoint *offsetJoints = param.offsetJoints; + PfxRigidState *offsetRigidStates = param.offsetRigidStates; + PfxSolverBody *offsetSolverBodies = param.offsetSolverBodies; + + for(PfxUInt32 i = iFirstJointPair; i < iEndJointPair; i++) + { + PfxConstraintPair &pair = jointPairs[i]; + if(!pfxCheckSolver(pair)) + { + continue; + } + + PfxUInt16 iA = pfxGetObjectIdA(pair); + PfxUInt16 iB = pfxGetObjectIdB(pair); + PfxUInt32 iConstraint = pfxGetConstraintId(pair); + + PfxJoint &joint = offsetJoints[iConstraint]; + + SCE_PFX_ALWAYS_ASSERT(iA==joint.m_rigidBodyIdA); + SCE_PFX_ALWAYS_ASSERT(iB==joint.m_rigidBodyIdB); + + PfxRigidState &stateA = offsetRigidStates[iA]; + PfxSolverBody &solverBodyA = offsetSolverBodies[iA]; + + PfxRigidState &stateB = offsetRigidStates[iB]; + PfxSolverBody &solverBodyB = offsetSolverBodies[iB]; + + pfxGetSetupJointConstraintFunc(joint.m_type)( + joint, + stateA, + stateB, + solverBodyA, + solverBodyB, + param.timeStep); + } +} + +//---------------------------------------------------------------------------- +// pfxSetupJointConstraints +// +/// Perform setup joint constraints in parallel using a task manager. +/// +/// @param param Information about joint constraints +/// @param taskManager Pointer to the thread task manager to use +/// +/// @return SCE_PFX_OK if successful, otherwise, returns an error code. +//---------------------------------------------------------------------------- +PfxInt32 pfxSetupJointConstraints(PfxSetupJointConstraintsParam ¶m, + PfxTaskManager *taskManager) +{ + PfxInt32 ret = pfxCheckParamOfSetupJointConstraints(param); + if(ret != SCE_PFX_OK) return ret; + + SCE_PFX_PUSH_MARKER("pfxSetupJointConstraints"); + + PfxUInt32 maxBatchSize = param.numJointPairs / (PfxUInt32)(taskManager->getNumTasks()); + PfxUInt32 iEnd = maxBatchSize, iStart = 0; + int task = 0; + taskManager->setTaskEntry((void*)pfxSetupJointConstraintsTaskEntry); + + for (task = 0; task < taskManager->getNumTasks() - 1; task++, iStart += maxBatchSize, iEnd += maxBatchSize) + { + taskManager->startTask(task, static_cast(¶m), iStart, iEnd, 0, 0); + } + + // send final task + iEnd = param.numJointPairs; + taskManager->startTask(taskManager->getNumTasks() - 1, static_cast(¶m), iStart, iEnd, 0, 0); + + // wait for tasks to complete + PfxUInt32 data1, data2, data3, data4; + for (PfxUInt32 i = 0; i < taskManager->getNumTasks(); i++) + taskManager->waitTask(task, data1, data2, data3, data4); + + SCE_PFX_POP_MARKER(); + + return SCE_PFX_OK; +} + +//---------------------------------------------------------------------------- +// pfxSplitConstraints +// +/// Given a set of constraints to be solved, split the constraints into +/// a collection of phases, with each phase having one or more independent +/// batches that can be solved in parallel. The phases must be solved +/// sequentially. +/// +/// @param numRigidBodies [in] Total number of rigid bodies referenced +/// in the given set of constraints +/// @param constraintpairs [in] Pointer to array of constraints to split. +/// For clarity, note that the pairs always stay +/// together. Some pairs are split to be solved +/// in parallel with other pairs. +/// @param numConstraints [in] Number of constraints to split +/// @param taskManager [in] Pointer to the thread task manager that will +/// eventually be used to solve the constraints. +/// @param group [out] On return, contains information about +/// the phases and batches that define the splitting +/// @param batches [out] Caller should pass a pointer to a pre- +/// allocated array of SCE_PFX_MAX_SOLVER_BATCHES +/// PfxParallelBatch objects. On output, these will +/// be populated with the correct number of pairs +/// for each batch. + +/// +/// @return SCE_PFX_OK if successful, otherwise, returns an error code. +//---------------------------------------------------------------------------- +void pfxSplitConstraints(PfxUInt32 numRigidBodies, PfxConstraintPair *constraintPairs, + PfxUInt32 numConstraints, PfxTaskManager *taskManager, PfxParallelGroup *group, + PfxParallelBatch *batches) +{ + SCE_PFX_PUSH_MARKER("pfxSplitConstraints"); + + // allocate a table that will be used to indicate, for a given phase being + // populated, which batch a given body belongs to. + PfxInt32 bufSize = sizeof(PfxUInt8) * numRigidBodies; + bufSize = ((bufSize + 127) >> 7) << 7; // 128 bytes alignment + PfxUInt8 *bodyTable = (PfxUInt8*)taskManager->allocate(bufSize); + + // allocate a table that will be used to indicate, for a given phase being + // populated, which batch a given pair of bodies belongs to. + PfxUInt32 *pairTable; + size_t allocSize = sizeof(PfxUInt32)*((numConstraints + 31) / 32); + pairTable = (PfxUInt32*)taskManager->allocate(allocSize); + memset(pairTable, 0, allocSize); + + // + PfxUInt32 numTasks = taskManager->getNumTasks(); + PfxUInt32 targetCount = SCE_PFX_MAX(PfxUInt32(SCE_PFX_MIN_SOLVER_PAIRS), + SCE_PFX_MIN(numConstraints / (numTasks * 2), PfxUInt32(SCE_PFX_MAX_SOLVER_PAIRS))); + PfxUInt32 startIndex = 0; + + PfxUInt32 phaseId; + PfxUInt32 batchId; + PfxUInt32 totalCount = 0; + + PfxUInt32 maxBatches = SCE_PFX_MIN(numTasks, PfxUInt32(SCE_PFX_MAX_SOLVER_BATCHES)); + + // accumulate phases and batches until group resources are exhausted or all incoming + // pairs are accounted for. + for (phaseId = 0; phaseId < SCE_PFX_MAX_SOLVER_PHASES && totalCount < numConstraints; phaseId++) + { + bool startIndexCheck = true; + + group->numBatches[phaseId] = 0; + + PfxUInt32 i = startIndex; + // Initialize body table such that no body is assigned to any batch. (0xff is explicitly assumed to + // mean no batch assigned) + memset(bodyTable, 0xff, bufSize); + + // accumulate batches within the current phase. This code creates batches that are + // independent, e.g., no batch on this phase will touch the same bodies as any other + // batch on the phase. Batches within a phase can be solved in parallel on shared memory + // multiprocessor hardware. + for (batchId = 0; i < numConstraints && totalCount < numConstraints && batchId < maxBatches; batchId++) + { + PfxUInt32 pairCount=0; + PfxParallelBatch &batch = batches[(phaseId * SCE_PFX_MAX_SOLVER_BATCHES) + batchId]; + PfxUInt32 pairId = 0; + + // iterate through pairs, and assigns the pairs to batches + for (; i < numConstraints && pairCount < targetCount; i++) + { + PfxUInt32 idxP = i >> 5; + PfxUInt32 maskP = 1L << (i & 31); + + if(pairTable[idxP] & maskP) // pair is already assigned to a phase/batch + continue; + + PfxUInt16 idxA = pfxGetObjectIdA(constraintPairs[i]); + PfxUInt16 idxB = pfxGetObjectIdB(constraintPairs[i]); + + // It is possible an incoming constraint pair can be skipped. For example, if the pair is inactive, + // or if both its objects are static, unmoving objects and therefore would be unaffected by constraints. + // This conditional statement addresses constraints to be skipped. + if (!pfxGetActive(constraintPairs[i]) || + (SCE_PFX_MOTION_MASK_STATIC(pfxGetMotionMaskA(constraintPairs[i])&SCE_PFX_MOTION_MASK_TYPE) && + SCE_PFX_MOTION_MASK_STATIC(pfxGetMotionMaskB(constraintPairs[i])&SCE_PFX_MOTION_MASK_TYPE)) ) + { + if (startIndexCheck) + startIndex++; + + //assign pair -> skip it because it has no constraints + pairTable[idxP] |= maskP; + totalCount++; + continue; + } + + // If either body of the current pair belongs to another batch already, we cannot add the current + // pair to the current batch. Must defer to another phase + if( (bodyTable[idxA] != batchId && bodyTable[idxA] != 0xff) || + (bodyTable[idxB] != batchId && bodyTable[idxB] != 0xff) ) + { + startIndexCheck = false; // so we will revisit this during allocation of next phase + continue; + } + + // Dynamic bodies for current pair are assigned to the current batch in this phase. + // Static bodies are not assigned. Since they never move, and their corresponding solver + // bodies are therefore never touched, they can actually be used by any batch. + if (SCE_PFX_MOTION_MASK_DYNAMIC(pfxGetMotionMaskA(constraintPairs[i])&SCE_PFX_MOTION_MASK_TYPE)) + bodyTable[idxA] = batchId; + + if (SCE_PFX_MOTION_MASK_DYNAMIC(pfxGetMotionMaskB(constraintPairs[i])&SCE_PFX_MOTION_MASK_TYPE)) + bodyTable[idxB] = batchId; + + if(startIndexCheck) + startIndex++; + + pairTable[idxP] |= maskP; // pair has been handled + + //add the pair 'i' to the current batch + batch.pairIndices[pairId++] = i; + pairCount++; + } + + group->numPairs[(phaseId * SCE_PFX_MAX_SOLVER_BATCHES) + batchId] = (PfxUInt16)pairId; + totalCount += pairCount; + } + group->numBatches[phaseId] = batchId; + } + + group->numPhases = phaseId; + + taskManager->deallocate(bodyTable); + taskManager->deallocate(pairTable); + + SCE_PFX_POP_MARKER(); +} + +//---------------------------------------------------------------------------- +// pfxSolveConstraintsTaskEntry +// +/// The thread PfxTaskEntry function used to solve constraints in parallel. +//---------------------------------------------------------------------------- +void pfxSolveConstraintsTaskEntry(PfxTaskArg *arg) +{ + PfxSolveConstraintsParam ¶m = *((PfxSolveConstraintsParam*)arg->io); + + PfxConstraintPair *contactPairs = param.contactPairs; + PfxContactManifold *offsetContactManifolds = param.offsetContactManifolds; + PfxConstraintPair *jointPairs = param.jointPairs; + PfxJoint *offsetJoints = param.offsetJoints; + PfxRigidState *offsetRigidStates = param.offsetRigidStates; + PfxSolverBody *offsetSolverBodies = param.offsetSolverBodies; + + PfxParallelGroup *jointgroup = (PfxParallelGroup*)arg->data[0]; + PfxParallelBatch *jointbatches = (PfxParallelBatch*)arg->data[1]; + PfxParallelGroup *contactgroup = (PfxParallelGroup*)arg->data[2]; + PfxParallelBatch *contactbatches = (PfxParallelBatch*)arg->data[3]; + + // Warm Starting + { + // Joints + for (PfxUInt16 phase = 0; phase < jointgroup->numPhases; phase++) + { + for (PfxUInt16 batchId = 0; batchId < jointgroup->numBatches[phase]; batchId++) + { + PfxUInt16 numJointPairs = jointgroup->numPairs[(phase * SCE_PFX_MAX_SOLVER_BATCHES) + batchId]; + if ((arg->taskId == (batchId % arg->maxTasks)) && numJointPairs > 0) // only spend time on batches meant for this task + { + const PfxParallelBatch &batch = jointbatches[(phase * SCE_PFX_MAX_SOLVER_BATCHES) + batchId]; + for (PfxUInt16 i = 0; i < numJointPairs; i++) + { + PfxConstraintPair &pair = jointPairs[batch.pairIndices[i]]; + if(!pfxCheckSolver(pair)) + continue; + + PfxUInt16 iA = pfxGetObjectIdA(pair); + PfxUInt16 iB = pfxGetObjectIdB(pair); + + PfxJoint &joint = offsetJoints[pfxGetConstraintId(pair)]; + + SCE_PFX_ASSERT(iA==joint.m_rigidBodyIdA); + SCE_PFX_ASSERT(iB==joint.m_rigidBodyIdB); + + PfxSolverBody &solverBodyA = offsetSolverBodies[iA]; + PfxSolverBody &solverBodyB = offsetSolverBodies[iB]; + + pfxGetWarmStartJointConstraintFunc(joint.m_type)( + joint, + solverBodyA, + solverBodyB); + } + } + + arg->barrier->sync(); // block until all threads are ready to go to next phase + } + } + + // Contacts + for (PfxUInt16 phase = 0; phase < contactgroup->numPhases; phase++) + { + for (PfxUInt16 batchId = 0; batchId < contactgroup->numBatches[phase]; batchId++) + { + PfxUInt16 numContactPairs = contactgroup->numPairs[(phase * SCE_PFX_MAX_SOLVER_BATCHES) + batchId]; + if ((arg->taskId == (batchId % arg->maxTasks)) && numContactPairs > 0) // only spend time on batches meant for this task + { + const PfxParallelBatch &batch = contactbatches[(phase * SCE_PFX_MAX_SOLVER_BATCHES) + batchId]; + for (PfxUInt16 i = 0; i < numContactPairs; i++) + { + PfxConstraintPair &pair = contactPairs[batch.pairIndices[i]]; + if(!pfxCheckSolver(pair)) + { + continue; + } + + PfxUInt16 iA = pfxGetObjectIdA(pair); + PfxUInt16 iB = pfxGetObjectIdB(pair); + + PfxContactManifold &contact = offsetContactManifolds[pfxGetConstraintId(pair)]; + + SCE_PFX_ASSERT(iA==contact.getRigidBodyIdA()); + SCE_PFX_ASSERT(iB==contact.getRigidBodyIdB()); + + PfxSolverBody &solverBodyA = offsetSolverBodies[iA]; + PfxSolverBody &solverBodyB = offsetSolverBodies[iB]; + + PfxFloat massInvA = solverBodyA.m_massInv; + PfxFloat massInvB = solverBodyB.m_massInv; + PfxMatrix3 inertiaInvA = solverBodyA.m_inertiaInv; + PfxMatrix3 inertiaInvB = solverBodyB.m_inertiaInv; + + if(solverBodyA.m_motionType == kPfxMotionTypeOneWay) + { + massInvB = 0.0f; + inertiaInvB = PfxMatrix3(0.0f); + } + + if(solverBodyB.m_motionType == kPfxMotionTypeOneWay) + { + massInvA = 0.0f; + inertiaInvA = PfxMatrix3(0.0f); + } + + for(int j = 0; j < contact.getNumContacts(); j++) + { + PfxContactPoint &cp = contact.getContactPoint(j); + + PfxVector3 rA = rotate(solverBodyA.m_orientation,pfxReadVector3(cp.m_localPointA)); + PfxVector3 rB = rotate(solverBodyB.m_orientation,pfxReadVector3(cp.m_localPointB)); + + for(int k = 0; k < 3; k++) + { + PfxVector3 normal = pfxReadVector3(cp.m_constraintRow[k].m_normal); + PfxFloat deltaImpulse = cp.m_constraintRow[k].m_accumImpulse; + solverBodyA.m_deltaLinearVelocity += deltaImpulse * massInvA * normal; + solverBodyA.m_deltaAngularVelocity += deltaImpulse * inertiaInvA * cross(rA,normal); + solverBodyB.m_deltaLinearVelocity -= deltaImpulse * massInvB * normal; + solverBodyB.m_deltaAngularVelocity -= deltaImpulse * inertiaInvB * cross(rB,normal); + } + } + } + } + } + + arg->barrier->sync(); // block until all threads are ready to go to next phase + } + } + + // Solver + for(PfxUInt32 iteration = 0; iteration < param.iteration; iteration++) + { + // Joints + for (PfxUInt16 phase = 0; phase < jointgroup->numPhases; phase++) + { + for (PfxUInt16 batchId = 0; batchId < jointgroup->numBatches[phase]; batchId++) + { + PfxUInt16 numJointPairs = jointgroup->numPairs[(phase * SCE_PFX_MAX_SOLVER_BATCHES) + batchId]; + if ((arg->taskId == (batchId % arg->maxTasks)) && numJointPairs > 0) // only spend time on batches meant for this task + { + const PfxParallelBatch &batch = jointbatches[(phase * SCE_PFX_MAX_SOLVER_BATCHES) + batchId]; + for(PfxUInt16 i = 0; i < numJointPairs; i++) + { + PfxConstraintPair &pair = jointPairs[batch.pairIndices[i]]; + if(!pfxCheckSolver(pair)) + continue; + + PfxUInt16 iA = pfxGetObjectIdA(pair); + PfxUInt16 iB = pfxGetObjectIdB(pair); + + PfxJoint &joint = offsetJoints[pfxGetConstraintId(pair)]; + + SCE_PFX_ASSERT(iA==joint.m_rigidBodyIdA); + SCE_PFX_ASSERT(iB==joint.m_rigidBodyIdB); + + PfxSolverBody &solverBodyA = offsetSolverBodies[iA]; + PfxSolverBody &solverBodyB = offsetSolverBodies[iB]; + + pfxGetSolveJointConstraintFunc(joint.m_type)( + joint, + solverBodyA, + solverBodyB); + } + } + } + + arg->barrier->sync(); // block until all threads are ready to go to next phase + } + + // Contacts + for (PfxUInt32 phase = 0; phase < contactgroup->numPhases; phase++) + { + for (PfxUInt32 batchId = 0; batchId < contactgroup->numBatches[phase]; batchId++) + { + PfxUInt32 numContactPairs = contactgroup->numPairs[(phase * SCE_PFX_MAX_SOLVER_BATCHES) + batchId]; + if ((arg->taskId == (batchId % arg->maxTasks)) && numContactPairs > 0) // only spend time on batches meant for this task + { + const PfxParallelBatch &batch = contactbatches[(phase * SCE_PFX_MAX_SOLVER_BATCHES) + batchId]; + for(PfxUInt32 i = 0; i < numContactPairs; i++) + { + PfxConstraintPair &pair = contactPairs[batch.pairIndices[i]]; + if(!pfxCheckSolver(pair)) + continue; + + PfxUInt16 iA = pfxGetObjectIdA(pair); + PfxUInt16 iB = pfxGetObjectIdB(pair); + + PfxContactManifold &contact = offsetContactManifolds[pfxGetConstraintId(pair)]; + + SCE_PFX_ASSERT(iA==contact.getRigidBodyIdA()); + SCE_PFX_ASSERT(iB==contact.getRigidBodyIdB()); + + PfxSolverBody &solverBodyA = offsetSolverBodies[iA]; + PfxSolverBody &solverBodyB = offsetSolverBodies[iB]; + + for(int j = 0; j < contact.getNumContacts(); j++) + { + PfxContactPoint &cp = contact.getContactPoint(j); + + pfxSolveContactConstraint( + cp.m_constraintRow[0], + cp.m_constraintRow[1], + cp.m_constraintRow[2], + pfxReadVector3(cp.m_localPointA), + pfxReadVector3(cp.m_localPointB), + solverBodyA, + solverBodyB, + contact.getCompositeFriction() + ); + } + } + } + } + + arg->barrier->sync(); // block until all threads are ready to go to next phase + } + } +} + +//---------------------------------------------------------------------------- +// pfxSolveConstraints +// +/// Perform setup joint constraints in parallel using a task manager. +/// +/// @param param Information about constraints +/// @param taskManager Pointer to the thread task manager to use +/// +/// @return SCE_PFX_OK if successful, otherwise, returns an error code. +//---------------------------------------------------------------------------- +PfxInt32 pfxSolveConstraints(PfxSolveConstraintsParam ¶m, + PfxTaskManager *taskManager) +{ + PfxInt32 ret = pfxCheckParamOfSolveConstraints(param); + if(ret != SCE_PFX_OK) return ret; + + SCE_PFX_PUSH_MARKER("pfxSolveConstraints"); + + PfxParallelGroup *contactgroup = (PfxParallelGroup*)taskManager->allocate(sizeof(PfxParallelGroup)); + PfxParallelBatch *contactbatches = (PfxParallelBatch*)taskManager->allocate(sizeof(PfxParallelBatch) * (SCE_PFX_MAX_SOLVER_PHASES * SCE_PFX_MAX_SOLVER_BATCHES)); + PfxParallelGroup *jointgroup = (PfxParallelGroup*)taskManager->allocate(sizeof(PfxParallelGroup)); + PfxParallelBatch *jointbatches = (PfxParallelBatch*)taskManager->allocate(sizeof(PfxParallelBatch) * (SCE_PFX_MAX_SOLVER_PHASES * SCE_PFX_MAX_SOLVER_BATCHES)); + + // split constraints into independent phases and batches. Phases allow + // a set of non-independent constraints to be solved in parallel. One + // phase may have dependencies within another phase, but the phases are + // solved sequentially. Within a phases, there are multiple batches, and + // the batches are independent. Since they are independent, they can be + // distributed to different processors and solved in parallel. + pfxSplitConstraints(param.numRigidBodies, param.contactPairs, param.numContactPairs, + taskManager, contactgroup, contactbatches); + pfxSplitConstraints(param.numRigidBodies, param.jointPairs, param.numJointPairs, + taskManager, jointgroup, jointbatches); + + // parallel solve + taskManager->setTaskEntry((void*)pfxSolveConstraintsTaskEntry); + int task = 0; + for (; task < taskManager->getNumTasks(); task++) + { + taskManager->startTask(task, static_cast(¶m), (PfxUInt32)jointgroup, (PfxUInt32)jointbatches, + (PfxUInt32)contactgroup, (PfxUInt32)contactbatches); + } + + // wait for tasks to complete + PfxUInt32 data1, data2, data3, data4; + for (PfxUInt32 i = 0; i < taskManager->getNumTasks(); i++) + taskManager->waitTask(task, data1, data2, data3, data4); + + // post solve + PfxRigidState *offsetRigidStates = param.offsetRigidStates; + PfxSolverBody *offsetSolverBodies = param.offsetSolverBodies; + for (PfxUInt32 i = 0; i < param.numRigidBodies; i++) + { + param.offsetRigidStates[i].setLinearVelocity(param.offsetRigidStates[i].getLinearVelocity() + + param.offsetSolverBodies[i].m_deltaLinearVelocity); + param.offsetRigidStates[i].setAngularVelocity(param.offsetRigidStates[i].getAngularVelocity() + + param.offsetSolverBodies[i].m_deltaAngularVelocity); + } + + taskManager->clearPool(); + + SCE_PFX_POP_MARKER(); + + return SCE_PFX_OK; +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/low_level/solver/pfx_constraint_solver_single.cpp b/Extras/PhysicsEffects/src/low_level/solver/pfx_constraint_solver_single.cpp new file mode 100644 index 0000000..49bd6fa --- /dev/null +++ b/Extras/PhysicsEffects/src/low_level/solver/pfx_constraint_solver_single.cpp @@ -0,0 +1,399 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_perf_counter.h" +#include "../../../include/physics_effects/base_level/solver/pfx_contact_constraint.h" +#include "../../../include/physics_effects/low_level/solver/pfx_joint_constraint_func.h" +#include "../../../include/physics_effects/low_level/solver/pfx_constraint_solver.h" +#include "../../base_level/solver/pfx_check_solver.h" +#include "pfx_parallel_group.h" + +namespace sce { +namespace PhysicsEffects { + +PfxUInt32 pfxGetWorkBytesOfSolveConstraints(PfxUInt32 numRigidBodies,PfxUInt32 numContactPairs,PfxUInt32 numJointPairs,PfxUInt32 maxTasks) +{ + (void)maxTasks; + PfxUInt32 workBytes = SCE_PFX_ALLOC_BYTES_ALIGN16(sizeof(PfxUInt8) * numRigidBodies) + + SCE_PFX_ALLOC_BYTES_ALIGN16(sizeof(PfxUInt32)*((SCE_PFX_MAX(numContactPairs,numJointPairs)+31)/32)); + + workBytes += 128 + (SCE_PFX_ALLOC_BYTES_ALIGN16(sizeof(PfxParallelGroup)) + + SCE_PFX_ALLOC_BYTES_ALIGN128(sizeof(PfxParallelBatch)*(SCE_PFX_MAX_SOLVER_PHASES*SCE_PFX_MAX_SOLVER_BATCHES))) * 2; + + return workBytes; +} + +PfxInt32 pfxCheckParamOfSetupSolverBodies(const PfxSetupSolverBodiesParam ¶m) +{ + if(!param.states || !param.bodies || !param.solverBodies ) return SCE_PFX_ERR_INVALID_VALUE; + if(!SCE_PFX_PTR_IS_ALIGNED16(param.states) || !SCE_PFX_PTR_IS_ALIGNED16(param.bodies) || !SCE_PFX_PTR_IS_ALIGNED16(param.solverBodies)) return SCE_PFX_ERR_INVALID_ALIGN; + return SCE_PFX_OK; +} + +PfxInt32 pfxCheckParamOfSetupContactConstraints(const PfxSetupContactConstraintsParam ¶m) +{ + if((param.numContactPairs>0&&(!param.contactPairs||!param.offsetContactManifolds)) || !param.offsetRigidStates || + !param.offsetRigidBodies || !param.offsetSolverBodies || param.timeStep <= 0.0f) return SCE_PFX_ERR_INVALID_VALUE; + if(!SCE_PFX_PTR_IS_ALIGNED16(param.contactPairs) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetContactManifolds) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetRigidStates) || + !SCE_PFX_PTR_IS_ALIGNED16(param.offsetRigidBodies) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetSolverBodies)) return SCE_PFX_ERR_INVALID_ALIGN; + return SCE_PFX_OK; +} + +PfxInt32 pfxCheckParamOfSetupJointConstraints(const PfxSetupJointConstraintsParam ¶m) +{ + if((param.numJointPairs>0&&(!param.jointPairs||!param.offsetJoints)) || !param.offsetRigidStates || + !param.offsetRigidBodies || !param.offsetSolverBodies || param.timeStep <= 0.0f) return SCE_PFX_ERR_INVALID_VALUE; + if(!SCE_PFX_PTR_IS_ALIGNED16(param.jointPairs) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetJoints) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetRigidStates) || + !SCE_PFX_PTR_IS_ALIGNED16(param.offsetRigidBodies) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetSolverBodies)) return SCE_PFX_ERR_INVALID_ALIGN; + return SCE_PFX_OK; +} + +PfxInt32 pfxCheckParamOfSolveConstraints(const PfxSolveConstraintsParam ¶m) +{ + if((param.numContactPairs>0&&(!param.contactPairs||!param.offsetContactManifolds)) || + (param.numJointPairs>0&&(!param.jointPairs||!param.offsetJoints)) || !param.offsetRigidStates || !param.offsetSolverBodies) return SCE_PFX_ERR_INVALID_VALUE; + if(!SCE_PFX_PTR_IS_ALIGNED16(param.contactPairs) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetContactManifolds) || + !SCE_PFX_PTR_IS_ALIGNED16(param.jointPairs) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetJoints) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetRigidStates) || + !SCE_PFX_PTR_IS_ALIGNED16(param.offsetSolverBodies)) return SCE_PFX_ERR_INVALID_ALIGN; + if(SCE_PFX_AVAILABLE_BYTES_ALIGN16(param.workBuff,param.workBytes) < pfxGetWorkBytesOfSolveConstraints(param.numRigidBodies,param.numContactPairs,param.numJointPairs) ) return SCE_PFX_ERR_OUT_OF_BUFFER; + return SCE_PFX_OK; +} + +/////////////////////////////////////////////////////////////////////////////// +// SINGLE THREAD + +PfxInt32 pfxSetupSolverBodies(PfxSetupSolverBodiesParam ¶m) +{ + PfxInt32 ret = pfxCheckParamOfSetupSolverBodies(param); + if(ret != SCE_PFX_OK) return ret; + + SCE_PFX_PUSH_MARKER("pfxSetupSolverBodies"); + + PfxRigidState *states = param.states; + PfxRigidBody *bodies = param.bodies; + PfxSolverBody *solverBodies = param.solverBodies; + PfxUInt32 numRigidBodies = param.numRigidBodies; + + for(PfxUInt32 i=0;i 1) restitution = 0.0f; + + PfxFloat friction = sqrtf(bodyA.getFriction() * bodyB.getFriction()); + + for(int j=0;j= kPfxJointCount) { + return SCE_PFX_ERR_OUT_OF_RANGE; + } + + funcTbl_setupJointConstraint[jointType] = func; + + return SCE_PFX_OK; +} + +/////////////////////////////////////////////////////////////////////////////// +// Warm Start Joint Constraint Function Table + +void warmStartJointConstraintDummy( + PfxJoint &joint, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB) +{ + (void)joint,(void)solverBodyA,(void)solverBodyB; +} + +PfxWarmStartJointConstraintFunc funcTbl_warmStartJointConstraint[kPfxJointCount] = { + pfxWarmStartBallJoint, + pfxWarmStartSwingTwistJoint, + pfxWarmStartSwingTwistJoint, + pfxWarmStartSwingTwistJoint, + pfxWarmStartSwingTwistJoint, + pfxWarmStartSwingTwistJoint, + warmStartJointConstraintDummy, + warmStartJointConstraintDummy, + warmStartJointConstraintDummy, + warmStartJointConstraintDummy, + warmStartJointConstraintDummy, + warmStartJointConstraintDummy, + warmStartJointConstraintDummy, + warmStartJointConstraintDummy, + warmStartJointConstraintDummy, +}; + +/////////////////////////////////////////////////////////////////////////////// +// Warm Start Joint Constraint Function Table Interface + +PfxWarmStartJointConstraintFunc pfxGetWarmStartJointConstraintFunc(PfxUInt8 jointType) +{ + SCE_PFX_ASSERT(jointType= kPfxJointCount) { + return SCE_PFX_ERR_OUT_OF_RANGE; + } + + funcTbl_warmStartJointConstraint[jointType] = func; + + return SCE_PFX_OK; +} + +/////////////////////////////////////////////////////////////////////////////// +// Solve Joint Constraint Function Table + +void solveJointConstraintDummy( + PfxJoint &joint, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB) +{ + (void)joint,(void)solverBodyA,(void)solverBodyB; +} + +PfxSolveJointConstraintFunc funcTbl_solveJointConstraint[kPfxJointCount] = { + pfxSolveBallJoint, + pfxSolveSwingTwistJoint, + pfxSolveSwingTwistJoint, + pfxSolveSwingTwistJoint, + pfxSolveSwingTwistJoint, + pfxSolveSwingTwistJoint, + solveJointConstraintDummy, + solveJointConstraintDummy, + solveJointConstraintDummy, + solveJointConstraintDummy, + solveJointConstraintDummy, + solveJointConstraintDummy, + solveJointConstraintDummy, + solveJointConstraintDummy, + solveJointConstraintDummy, +}; + +/////////////////////////////////////////////////////////////////////////////// +// Solve Joint Constraint Function Table Interface + +PfxSolveJointConstraintFunc pfxGetSolveJointConstraintFunc(PfxUInt8 jointType) +{ + SCE_PFX_ASSERT(jointType= kPfxJointCount) { + return SCE_PFX_ERR_OUT_OF_RANGE; + } + + funcTbl_solveJointConstraint[jointType] = func; + + return SCE_PFX_OK; +} +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/low_level/solver/pfx_parallel_group.h b/Extras/PhysicsEffects/src/low_level/solver/pfx_parallel_group.h new file mode 100644 index 0000000..6b4664c --- /dev/null +++ b/Extras/PhysicsEffects/src/low_level/solver/pfx_parallel_group.h @@ -0,0 +1,44 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_PARALLEL_GROUP_H +#define _SCE_PFX_PARALLEL_GROUP_H + +/////////////////////////////////////////////////////////////////////////////// +// Parallel Group + +#define SCE_PFX_MAX_SOLVER_PHASES 64 // 最大フェーズ数 +#define SCE_PFX_MAX_SOLVER_BATCHES 32 // 1フェーズに含まれる最大並列処理バッチ +#define SCE_PFX_MAX_SOLVER_PAIRS 64 // 1バッチに含まれる最大ペア数 +#define SCE_PFX_MIN_SOLVER_PAIRS 16 // 1バッチに含まれる最小ペア数 + +namespace sce { +namespace PhysicsEffects { + +struct SCE_PFX_ALIGNED(128) PfxParallelBatch { + PfxUInt16 pairIndices[SCE_PFX_MAX_SOLVER_PAIRS]; +}; + +struct SCE_PFX_ALIGNED(128) PfxParallelGroup { + PfxUInt16 numPhases; + PfxUInt16 numBatches[SCE_PFX_MAX_SOLVER_PHASES]; // 各フェーズの保持する並列実行可能なバッチの数 + PfxUInt16 numPairs[SCE_PFX_MAX_SOLVER_PHASES*SCE_PFX_MAX_SOLVER_BATCHES]; // 各バッチの保持するペアの数 +SCE_PFX_PADDING(1,126) +}; + +} //namespace PhysicsEffects +} //namespace sce +#endif // _SCE_PFX_PARALLEL_GROUP_H diff --git a/Extras/PhysicsEffects/src/low_level/solver/pfx_update_rigid_states_parallel.cpp b/Extras/PhysicsEffects/src/low_level/solver/pfx_update_rigid_states_parallel.cpp new file mode 100644 index 0000000..1c90e21 --- /dev/null +++ b/Extras/PhysicsEffects/src/low_level/solver/pfx_update_rigid_states_parallel.cpp @@ -0,0 +1,94 @@ +/* +Applied Research Associates Inc. (c)2011 + +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_perf_counter.h" +#include "../../../include/physics_effects/base_level/solver/pfx_integrate.h" +#include "../../../include/physics_effects/low_level/solver/pfx_update_rigid_states.h" + +namespace sce { +namespace PhysicsEffects { + +/////////////////////////////////////////////////////////////////////////////// +// This function is implemented in pfx_update_rigid_states_single.cpp +extern PfxInt32 pfxCheckParamOfUpdateRigidStates(const PfxUpdateRigidStatesParam ¶m); + +/////////////////////////////////////////////////////////////////////////////// +// MULTIPLE THREADS + +//---------------------------------------------------------------------------- +// pfxUpdateRigidStatesTaskEntry +// +/// The thread PfxTaskEntry function used to update rigid body states in +/// parallel. +//---------------------------------------------------------------------------- +void pfxUpdateRigidStatesTaskEntry(PfxTaskArg *arg) +{ + PfxUpdateRigidStatesParam ¶m = *((PfxUpdateRigidStatesParam*)arg->io); + + PfxUInt32 iFirstBody = arg->data[0]; + PfxUInt32 iEndBody = arg->data[1]; + + for(PfxUInt32 i = iFirstBody; i < iEndBody; i++) + { + pfxIntegrate(param.states[i],param.bodies[i],param.timeStep); + } +} + +//---------------------------------------------------------------------------- +// pfxUpdateRigidStates +// +/// Perform update rigid states in parallel using a task manager. +/// +/// @param param Information about rigid bodies +/// @param taskManager Pointer to the thread task manager to use +/// +/// @return SCE_PFX_OK if successful, otherwise, returns an error code. +//---------------------------------------------------------------------------- +PfxInt32 pfxUpdateRigidStates(PfxUpdateRigidStatesParam ¶m, PfxTaskManager *taskManager) +{ + PfxInt32 ret = pfxCheckParamOfUpdateRigidStates(param); + if(ret != SCE_PFX_OK) return ret; + + SCE_PFX_PUSH_MARKER("pfxUpdateRigidStates"); + + PfxUInt32 maxBatchSize = param.numRigidBodies / (PfxUInt32)(taskManager->getNumTasks()); + PfxUInt32 iEnd = maxBatchSize, iStart = 0; + int task = 0; + taskManager->setTaskEntry((void*)pfxUpdateRigidStatesTaskEntry); + + for (task = 0; task < taskManager->getNumTasks() - 1; task++, iStart += maxBatchSize, iEnd += maxBatchSize) + { + taskManager->startTask(task, static_cast(¶m), iStart, iEnd, 0, 0); + } + + // send final task + iEnd = param.numRigidBodies; + taskManager->startTask(taskManager->getNumTasks() - 1, static_cast(¶m), iStart, iEnd, 0, 0); + + // wait for tasks to complete + PfxUInt32 data1, data2, data3, data4; + for (PfxUInt32 i = 0; i < taskManager->getNumTasks(); i++) + taskManager->waitTask(task, data1, data2, data3, data4); + + SCE_PFX_POP_MARKER(); + + return SCE_PFX_OK; +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/low_level/solver/pfx_update_rigid_states_single.cpp b/Extras/PhysicsEffects/src/low_level/solver/pfx_update_rigid_states_single.cpp new file mode 100644 index 0000000..827daff --- /dev/null +++ b/Extras/PhysicsEffects/src/low_level/solver/pfx_update_rigid_states_single.cpp @@ -0,0 +1,51 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../../include/physics_effects/base_level/base/pfx_perf_counter.h" +#include "../../../include/physics_effects/base_level/solver/pfx_integrate.h" +#include "../../../include/physics_effects/low_level/solver/pfx_update_rigid_states.h" + +namespace sce { +namespace PhysicsEffects { + +PfxInt32 pfxCheckParamOfUpdateRigidStates(const PfxUpdateRigidStatesParam ¶m) +{ + if(!param.states || !param.bodies || param.timeStep <= 0.0f) return SCE_PFX_ERR_INVALID_VALUE; + if(!SCE_PFX_PTR_IS_ALIGNED16(param.states) || !SCE_PFX_PTR_IS_ALIGNED16(param.bodies)) return SCE_PFX_ERR_INVALID_ALIGN; + return SCE_PFX_OK; +} + +/////////////////////////////////////////////////////////////////////////////// +// SINGLE THREAD + +PfxInt32 pfxUpdateRigidStates(PfxUpdateRigidStatesParam ¶m) +{ + PfxInt32 ret = pfxCheckParamOfUpdateRigidStates(param); + if(ret != SCE_PFX_OK) return ret; + + SCE_PFX_PUSH_MARKER("pfxUpdateRigidStates"); + + for(PfxUInt32 i=0;i 0) + { + SCE_PFX_CHECK_PTHREADS_OUTCOME(pthread_mutex_destroy(&m_mutex)); + SCE_PFX_CHECK_PTHREADS_OUTCOME(pthread_cond_destroy(&m_cond)); + } +} + +//---------------------------------------------------------------------------- +// PfxPthreadsBarrier::sync +// +/// This function is used to sync m_numThreads worker threads. Each worker +/// should call sync() when it finishes a task. All workers will block until +/// the last worker also calls sync(). +//---------------------------------------------------------------------------- +void PfxPthreadsBarrier::sync() +{ + SCE_PFX_CHECK_PTHREADS_OUTCOME(pthread_mutex_lock(&m_mutex)); + + m_called++; + + if (m_called == m_maxThreads) + { + // last thread to join broadcasts a condition that will release + // all the threads waiting at the barrier. The barrier is reset + // to be ready for the next sync point. + m_called = 0; + SCE_PFX_CHECK_PTHREADS_OUTCOME(pthread_cond_broadcast(&m_cond)); + } + else + { + // First m_numThreads - 1 worker threads block on the condition. + SCE_PFX_CHECK_PTHREADS_OUTCOME(pthread_cond_wait(&m_cond, &m_mutex)); + } + + SCE_PFX_CHECK_PTHREADS_OUTCOME(pthread_mutex_unlock(&m_mutex)); +} + +//---------------------------------------------------------------------------- +// PfxPthreadsBarrier::setMaxCount +// +/// Set the number of threads that the barrier should wait for. This also +/// initializes a mutex and condition variable that are used to implement +/// the barrier. +/// +/// @param n Number of threads that should wait at the barrier. +//---------------------------------------------------------------------------- +void PfxPthreadsBarrier::setMaxCount(int n) +{ + if (m_maxThreads > 0) + { + SCE_PFX_CHECK_PTHREADS_OUTCOME(pthread_mutex_destroy(&m_mutex)); + SCE_PFX_CHECK_PTHREADS_OUTCOME(pthread_cond_destroy(&m_cond)); + } + + m_called = 0; + + if (0 < n) + { + SCE_PFX_CHECK_PTHREADS_OUTCOME(pthread_mutex_init(&m_mutex,NULL)); + SCE_PFX_CHECK_PTHREADS_OUTCOME(pthread_cond_init(&m_cond,NULL)); + } + + m_maxThreads = n; +} + +//---------------------------------------------------------------------------- +// PfxPthreadsBarrier::getMaxCount +// +/// Get the number of threads that the barrier will wait for. +/// +/// @return The number of threads the barrier waits for +//---------------------------------------------------------------------------- +int PfxPthreadsBarrier::getMaxCount() +{ + return m_maxThreads; +} + +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +// PfxPthreadsCriticalSection::PfxPthreadsCriticalSection +// +/// Default constructor +//---------------------------------------------------------------------------- +PfxPthreadsCriticalSection::PfxPthreadsCriticalSection() +{ + SCE_PFX_CHECK_PTHREADS_OUTCOME(pthread_mutex_init(&m_mutex,NULL)); +} + +//---------------------------------------------------------------------------- +// PfxPthreadsCriticalSection::~PfxPthreadsCriticalSection +// +/// Destructor +//---------------------------------------------------------------------------- +PfxPthreadsCriticalSection::~PfxPthreadsCriticalSection() +{ + SCE_PFX_CHECK_PTHREADS_OUTCOME(pthread_mutex_destroy(&m_mutex)); +} + +//---------------------------------------------------------------------------- +// PfxPthreadsCriticalSection::getSharedParam +// +/// Get the value of a shared parameter. Note that user must lock the +/// critical section before performing this action. +/// +/// @param i index of shared parameter to retrieve. Must have value +/// between 0 and 31 +/// +/// @return Shared parameter value +//---------------------------------------------------------------------------- +PfxUInt32 PfxPthreadsCriticalSection::getSharedParam(int i) +{ + return(m_commonBuff[i]); +} + +//---------------------------------------------------------------------------- +// PfxPthreadsCriticalSection::setSharedParam +// +/// Set the value of a shared parameter. Note that user must lock the +/// critical section before performing this action. +/// +/// @param i index of shared parameter to set. Must have value +/// between 0 and 31 +/// @param p Value to assign to shared parameter +//---------------------------------------------------------------------------- +void PfxPthreadsCriticalSection::setSharedParam(int i,PfxUInt32 p) +{ + m_commonBuff[i] = p; +} + +//---------------------------------------------------------------------------- +// PfxPthreadsCriticalSection::lock +// +/// Lock the critical section +//---------------------------------------------------------------------------- +void PfxPthreadsCriticalSection::lock() +{ + SCE_PFX_CHECK_PTHREADS_OUTCOME(pthread_mutex_lock(&m_mutex)); +} + +//---------------------------------------------------------------------------- +// PfxPthreadsCriticalSection::lock +// +/// Unlock the critical section +//---------------------------------------------------------------------------- +void PfxPthreadsCriticalSection::unlock() +{ + SCE_PFX_CHECK_PTHREADS_OUTCOME(pthread_mutex_unlock(&m_mutex)); +} + +//---------------------------------------------------------------------------- +// Factory functions +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +// PfxCreateBarrierPthreads +// +/// Factory function to create a pthreads-based barrier +/// +/// @param n Max number of tasks +//---------------------------------------------------------------------------- +PfxBarrier *PfxCreateBarrierPthreads(int n) +{ + PfxPthreadsBarrier *barrier = new PfxPthreadsBarrier; + barrier->setMaxCount(n); + return(barrier); +} + +//---------------------------------------------------------------------------- +// PfxCreateCriticalSectionPthreads +// +/// Factory function to create a pthreads-based critical section +//---------------------------------------------------------------------------- +PfxCriticalSection *PfxCreateCriticalSectionPthreads() +{ + PfxPthreadsCriticalSection *cs = new PfxPthreadsCriticalSection; + return(cs); +} + +} //namespace PhysicsEffects +} //namespace sce + +#endif //__ANDROID__ diff --git a/Extras/PhysicsEffects/src/low_level/task/pfx_sync_components_pthreads.h b/Extras/PhysicsEffects/src/low_level/task/pfx_sync_components_pthreads.h new file mode 100644 index 0000000..1bc4052 --- /dev/null +++ b/Extras/PhysicsEffects/src/low_level/task/pfx_sync_components_pthreads.h @@ -0,0 +1,93 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _SCE_PFX_SYNC_COMPONENTS_PTHREADS_H +#define _SCE_PFX_SYNC_COMPONENTS_PTHREADS_H + +#include "../../../include/physics_effects/base_level/base/pfx_common.h" +#include "../../../include/physics_effects/low_level/task/pfx_pthreads.h" +#include "../../../include/physics_effects/low_level/task/pfx_sync_components.h" +#include +#include + +namespace sce { +namespace PhysicsEffects { + +//---------------------------------------------------------------------------- +// PfxPthreadsBarrier +// +/// Implementation of a barrier using pthreads. This version uses a mutex +/// and condition variable rather than using native pthreads barrier, which +/// enables it to be used on platforms that don't support pthreads barriers +/// (such as Android 2.3x) +//---------------------------------------------------------------------------- +class PfxPthreadsBarrier : public PfxBarrier +{ + public: + PfxPthreadsBarrier(); + virtual ~PfxPthreadsBarrier(); + + // from PfxBarrier + virtual void sync(); + virtual void setMaxCount(int n); + virtual int getMaxCount(); + + private: + pthread_mutex_t m_mutex; ///< Mutex used to block worker threads + pthread_cond_t m_cond; ///< Condition variable + + int m_maxThreads; ///< Maximum number of worker threads + int m_called; ///< Number of worker threads waiting at barrier +}; + +//---------------------------------------------------------------------------- +// PfxPthreadsBarrier +// +/// Implementation of a critical section using pthreads. +//---------------------------------------------------------------------------- +class PfxPthreadsCriticalSection : public PfxCriticalSection +{ + public: + PfxPthreadsCriticalSection(); + virtual ~PfxPthreadsCriticalSection(); + + // from PfxCriticalSection + virtual PfxUInt32 getSharedParam(int i); + virtual void setSharedParam(int i,PfxUInt32 p); + + virtual void lock(); + virtual void unlock(); + + private: + pthread_mutex_t m_mutex; ///< Mutex used to implement lock +}; + +} //namespace PhysicsEffects +} //namespace sce + +#endif // _SCE_PFX_SYNC_COMPONENTS_PTHREADS_H diff --git a/Extras/PhysicsEffects/src/low_level/task/pfx_task_manager_pthreads.cpp b/Extras/PhysicsEffects/src/low_level/task/pfx_task_manager_pthreads.cpp new file mode 100644 index 0000000..cecc5aa --- /dev/null +++ b/Extras/PhysicsEffects/src/low_level/task/pfx_task_manager_pthreads.cpp @@ -0,0 +1,311 @@ +/* + Applied Research Associates Inc. (c)2011 + + 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 Applied Research Associates Inc 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. +*/ + +#ifdef __ANDROID__ + +#include "../../../include/physics_effects/base_level/base/pfx_common.h" +#include "../../../include/physics_effects/low_level/task/pfx_pthreads.h" +#include "../../../include/physics_effects/low_level/task/pfx_task_manager.h" +#include "../../../include/physics_effects/low_level/task/pfx_sync_components.h" +#include "pfx_sync_components_pthreads.h" + +namespace sce { +namespace PhysicsEffects { + +//---------------------------------------------------------------------------- +// Standalone functions and structs +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +// PfxPthreadsThreadData +// +/// Struct to store information needed by worker threads +//---------------------------------------------------------------------------- +struct PfxPthreadsThreadData +{ + // task runner information + PfxTaskArg *taskargument; ///< Pointer to argument for the task entry function + PfxTaskEntry taskEntry; ///< Pointer to current task entry function + + // pthreads synchronization and thread info + pthread_t thread; ///< Current thread + sem_t semaphore; ///< Semaphore used to wake the thread + sem_t *taskmanagersemaphore; ///< Semaphore used to notify parent thread +}; + +//---------------------------------------------------------------------------- +// PfxPthreadsThreadFunction +// +/// The thread function used for threads created and managed using a +/// PfxPthreadsThreadPool +//---------------------------------------------------------------------------- +void *PfxPthreadsThreadFunction(void *argument) +{ + PfxPthreadsThreadData *threaddata = (PfxPthreadsThreadData*)argument; + + while (1) + { + // wait until a task is available + SCE_PFX_CHECK_PTHREADS_OUTCOME(sem_wait(&threaddata->semaphore)); + + // do work + if (threaddata->taskEntry) + threaddata->taskEntry(threaddata->taskargument); + + // notify threadpool that task is done + SCE_PFX_CHECK_PTHREADS_OUTCOME(sem_post(threaddata->taskmanagersemaphore)); + + // If no task, then exit + if (!threaddata->taskEntry) + pthread_exit(0); + } + + return 0; +} + +//---------------------------------------------------------------------------- +// Class definitions +//---------------------------------------------------------------------------- +class PfxPthreadsTaskManager : public PfxTaskManager +{ + public: + PfxPthreadsTaskManager(PfxUInt32 numTasks, PfxUInt32 maxTasks, void *workBuff, PfxUInt32 workBytes) : + PfxTaskManager(numTasks, maxTasks, workBuff, workBytes), + m_threads(NULL) {} + + // from PfxTaskManager + virtual PfxUInt32 getSharedParam(int i); + virtual void setSharedParam(int i, PfxUInt32 p); + virtual void startTask(int taskId, void *io, PfxUInt32 data1, PfxUInt32 data2, + PfxUInt32 data3, PfxUInt32 data4); + virtual void waitTask(int &taskId, PfxUInt32 &data1, PfxUInt32 &data2, + PfxUInt32 &data3, PfxUInt32 &data4); + + virtual void initialize(); + virtual void finalize(); + + protected: + PfxPthreadsTaskManager() : PfxTaskManager(), m_threads(NULL) {} + + private: + PfxPthreadsThreadData *m_threads; ///< Pointer to array of running threads (count is m_numThreads); + PfxPthreadsBarrier m_barrier; ///< Barrier used to sync task groups + PfxPthreadsCriticalSection m_cs; ///< Critical section used to manage shared parameters + sem_t m_taskmanagersemaphore; ///< Synchronization semaphore for task manager +}; + +//---------------------------------------------------------------------------- +// PfxPthreadsTaskManager +// +/// Implementation of a task manager using pthreads. +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +// PfxPthreadsTaskManager::initialize +// +/// Initialize the task manager +//---------------------------------------------------------------------------- +void PfxPthreadsTaskManager::initialize() +{ + if (0 == m_maxTasks) + return; + + if (m_threads) // already started + { + SCE_PFX_PRINTF("PfxPthreadsThreadPool attempt to start threads when they are already started, line %i, file %s\n", __LINE__, __FILE__); + return; + } + + m_threads = (PfxPthreadsThreadData*)m_pool.allocate(sizeof(PfxPthreadsThreadData)*m_maxTasks); + if (!m_threads) + { + SCE_PFX_PRINTF("PfxPthreadsThreadPool unable to allocate threads at line %i in file %s\n", __LINE__, __FILE__); + return; + } + + m_barrier.setMaxCount(m_maxTasks); + + // Initialize sync semaphore + SCE_PFX_CHECK_PTHREADS_OUTCOME(sem_init(&m_taskmanagersemaphore, 0, 0)); + + // Allocate and start the threads + for (unsigned int i = 0; i < m_maxTasks; i++) + { + // Prepare argument data structure for task entry functions. Mostly, this is + // setting parameters that are fixed until the simulation ends + m_taskArg[i].taskId = i; + m_taskArg[i].maxTasks = m_maxTasks; + m_taskArg[i].barrier = &m_barrier; + m_taskArg[i].criticalSection = &m_cs; + m_taskArg[i].io = NULL; + + // Prepare other per-thread data + m_threads[i].taskEntry = NULL; + m_threads[i].taskargument = &m_taskArg[i]; + m_threads[i].taskmanagersemaphore = &m_taskmanagersemaphore; + + // Now create the thread's semaphore, then start the thread + SCE_PFX_CHECK_PTHREADS_OUTCOME(sem_init(&m_threads[i].semaphore, 0, 0)); + SCE_PFX_CHECK_PTHREADS_OUTCOME(pthread_create(&m_threads[i].thread, NULL, PfxPthreadsThreadFunction, (void*)&m_threads[i])); + } +} + +//---------------------------------------------------------------------------- +// PfxPthreadsTaskManager::finalize +// +/// Finalize the task manager +//---------------------------------------------------------------------------- +void PfxPthreadsTaskManager::finalize() +{ + // stop the threads + for (unsigned int i = 0; i < m_maxTasks; i++) + { + m_threads[i].taskEntry = NULL; // NULL task tells thread to exit + SCE_PFX_CHECK_PTHREADS_OUTCOME(sem_post(&m_threads[i].semaphore)); + } + + // wait for them all to exit + for (unsigned int i = 0; i < m_maxTasks; i++) + SCE_PFX_CHECK_PTHREADS_OUTCOME(sem_wait(&m_taskmanagersemaphore)); + + // destroy per-thread semaphores + for (unsigned int i = 0; i < m_maxTasks; i++) + SCE_PFX_CHECK_PTHREADS_OUTCOME(sem_destroy(&m_threads[i].semaphore)); + + // delete thread pool + delete [] m_threads; + m_threads = NULL; + + // destroy task manager semaphore and reset barrier + SCE_PFX_CHECK_PTHREADS_OUTCOME(sem_destroy(&m_taskmanagersemaphore)); + + m_barrier.setMaxCount(0); +} + +//---------------------------------------------------------------------------- +// PfxPthreadsTaskManager::startTask +// +/// Start a task +/// +/// @param taskId [in] task thread identifier/index +/// @param io [in, out] task input and output buffer +/// @param data1 [in] first of four user parameter data values for the task +/// @param data2 [in] second of four user parameter data values for the task +/// @param data3 [in] third of four user parameter data values for the task +/// @param data4 [in] fourth of four user parameter data values for the task +//---------------------------------------------------------------------------- +void PfxPthreadsTaskManager::startTask(int taskId,void *io,PfxUInt32 data1, + PfxUInt32 data2,PfxUInt32 data3,PfxUInt32 data4) +{ + m_threads[taskId].taskEntry = m_taskEntry; + m_taskArg[taskId].io = io; + m_taskArg[taskId].data[0] = data1; + m_taskArg[taskId].data[1] = data2; + m_taskArg[taskId].data[2] = data3; + m_taskArg[taskId].data[3] = data4; + SCE_PFX_CHECK_PTHREADS_OUTCOME(sem_post(&m_threads[taskId].semaphore)); +} + +//---------------------------------------------------------------------------- +// PfxPthreadsTaskManager::waitTask +// +/// Wait for a task to finish +/// +/// @param taskId [out] task thread identifier/index +/// @param data1 [out] first of four data values from the task +/// @param data2 [out] second of four data values from the task +/// @param data3 [out] third of four data values from the task +/// @param data4 [out] fourth of four data values from the task +//---------------------------------------------------------------------------- +void PfxPthreadsTaskManager::waitTask(int &taskId,PfxUInt32 &data1,PfxUInt32 &data2, + PfxUInt32 &data3,PfxUInt32 &data4) +{ + SCE_PFX_CHECK_PTHREADS_OUTCOME(sem_wait(&m_taskmanagersemaphore)); +} + +//---------------------------------------------------------------------------- +// PfxPthreadsTaskManager::getSharedParam +// +/// Get the value of a shared parameter +/// +/// @param i index of shared parameter to retrieve. Must have value +/// between 0 and 31 +/// +/// @return Shared parameter value +//---------------------------------------------------------------------------- +PfxUInt32 PfxPthreadsTaskManager::getSharedParam(int i) +{ + m_cs.lock(); + PfxUInt32 paramval = m_cs.getSharedParam(i); + m_cs.unlock(); + return(paramval); +} + +//---------------------------------------------------------------------------- +// PfxPthreadsTaskManager::setSharedParam +// +/// Set the value of a shared parameter +/// +/// @param i index of shared parameter to set. Must have value +/// between 0 and 31 +/// @param p Value to assign to shared parameter +//---------------------------------------------------------------------------- +void PfxPthreadsTaskManager::setSharedParam(int i, PfxUInt32 p) +{ + m_cs.lock(); + PfxUInt32 paramval = m_cs.getSharedParam(i); + m_cs.setSharedParam(i, p); + m_cs.unlock(); +} + +//---------------------------------------------------------------------------- +// Factory functions +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +// PfxCreateTaskManagerPthreads +// +/// Factory function to create a pthreads-based task manager +/// +/// @param numTasks number of tasks +/// @param maxTasks max number of tasks +/// @param workBuff work buffer +/// @param workBytes size of work buffer, in bytes +//---------------------------------------------------------------------------- +PfxTaskManager *PfxCreateTaskManagerPthreads(PfxUInt32 numTasks,PfxUInt32 maxTasks, + void *workBuff,PfxUInt32 workBytes) +{ + PfxTaskManager *taskmanager = new PfxPthreadsTaskManager(numTasks, maxTasks, + workBuff, workBytes); + return(taskmanager); +} + +} //namespace PhysicsEffects +} //namespace sce + +#endif //__ANDROID__ diff --git a/Extras/PhysicsEffects/src/util/CMakeLists.txt b/Extras/PhysicsEffects/src/util/CMakeLists.txt new file mode 100644 index 0000000..223cfa4 --- /dev/null +++ b/Extras/PhysicsEffects/src/util/CMakeLists.txt @@ -0,0 +1,20 @@ +INCLUDE_DIRECTORIES( ${PHYSICS_EFFECTS_SOURCE_DIR}/include ) + +SET(PfxUtil_SRCS + pfx_mass.cpp + pfx_mesh_creator.cpp +) + +SET(PfxUtil_HDRS + pfx_array.h + pfx_array_implementation.h + pfx_util_common.h +) + + + + +ADD_LIBRARY(PfxUtil ${PfxUtil_SRCS} ${PfxUtil_HDRS}) + +SET_TARGET_PROPERTIES(PfxUtil PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(PfxUtil PROPERTIES SOVERSION ${BULLET_VERSION}) diff --git a/Extras/PhysicsEffects/src/util/pfx_array.h b/Extras/PhysicsEffects/src/util/pfx_array.h new file mode 100644 index 0000000..b258346 --- /dev/null +++ b/Extras/PhysicsEffects/src/util/pfx_array.h @@ -0,0 +1,187 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#ifndef _SCE_PFX_ARRAY_H +#define _SCE_PFX_ARRAY_H + +#include "../../include/physics_effects/base_level/base/pfx_common.h" +#include "pfx_util_common.h" + +namespace sce { +namespace PhysicsEffects { + +/////////////////////////////////////////////////////////////////////////////// +// 基本的なコンテナクラス + +/////////////////////////////////////////////////////////////////////////////// +// PfxArray + +/* + 可変配列 +*/ + +template +class PfxArray +{ +private: + PfxUInt32 m_numData; + PfxUInt32 m_maxData; + SCE_PFX_PADDING(1,8) + T SCE_PFX_ALIGNED(16) *m_data; + SCE_PFX_PADDING(2,12) + +public: + PfxArray() : m_numData(0),m_maxData(100) + { + m_data = (T*)SCE_PFX_UTIL_ALLOC(16,sizeof(T)*m_maxData); + } + + PfxArray(PfxUInt32 maxData) : m_numData(0),m_maxData(maxData) + { + m_data = (T*)SCE_PFX_UTIL_ALLOC(16,sizeof(T)*m_maxData); + } + + ~PfxArray() + { + SCE_PFX_UTIL_FREE(m_data); + } + + PfxUInt32 size() const {return m_numData;} + + inline T& operator[](PfxUInt32 i); + + inline const T& operator[](PfxUInt32 i) const; + + inline const PfxArray& operator=(const PfxArray &array); + + // 指定数分のデータを準備する + inline void assign(PfxUInt32 num,const T &initData); + + // データを追加 + inline PfxUInt32 push(const T& data); + + // i番目のデータを消去 + inline bool remove(PfxUInt32 i); + + inline bool empty() const {return m_numData==0;} + + inline void clear() {m_numData = 0;} +}; + +/////////////////////////////////////////////////////////////////////////////// +// PfxQueue + +/* + キュー(最大数固定) +*/ + +template +class PfxQueue +{ +private: + PfxUInt32 m_numData; + PfxUInt32 m_maxData; + PfxUInt32 m_head; + PfxUInt32 m_tail; + T SCE_PFX_ALIGNED(16) *m_data; + SCE_PFX_PADDING(1,12) + + PfxQueue() {} + +public: + + PfxQueue(PfxUInt32 maxData) : m_numData(0),m_maxData(maxData),m_head(0),m_tail(0) + { + m_data = (T*)SCE_PFX_UTIL_ALLOC(16,sizeof(T)*m_maxData); + } + + ~PfxQueue() + { + SCE_PFX_UTIL_FREE(m_data); + } + + PfxUInt32 size() const {return m_numData;} + + // データをキューに入れる + inline PfxUInt32 push(const T& data); + + // 最後尾のデータを消去 + inline void pop(); + + // 先頭のデータを参照 + inline T& front(); + + // 先頭のデータを参照 + inline const T& front() const; + + inline bool empty() const {return m_numData==0;} + + inline void clear() {m_numData = 0;} +}; + +/////////////////////////////////////////////////////////////////////////////// +// PfxStack + +/* + スタック(最大数固定) +*/ + +template +class PfxStack +{ +private: + PfxUInt32 m_numData; + PfxUInt32 m_maxData; + T SCE_PFX_ALIGNED(16) *m_data; + + PfxStack() {} + +public: + + PfxStack(PfxUInt32 maxData) : m_numData(0),m_maxData(maxData) + { + m_data = (T*)SCE_PFX_UTIL_ALLOC(16,sizeof(T)*m_maxData); + } + + ~PfxStack() + { + SCE_PFX_UTIL_FREE(m_data); + } + + PfxUInt32 size() const {return m_numData;} + + // データをスタックに入れる + inline PfxUInt32 push(const T& data); + + // 末尾のデータを消去 + inline void pop(); + + // 末尾のデータを参照 + inline T& top(); + + // 末尾のデータを参照 + inline const T& top() const; + + inline bool empty() const {return m_numData==0;} + + inline void clear() {m_numData = 0;} +}; + +} //namespace PhysicsEffects +} //namespace sce +#include "pfx_array_implementation.h" + +#endif // _SCE_PFX_ARRAY_H diff --git a/Extras/PhysicsEffects/src/util/pfx_array_implementation.h b/Extras/PhysicsEffects/src/util/pfx_array_implementation.h new file mode 100644 index 0000000..2137408 --- /dev/null +++ b/Extras/PhysicsEffects/src/util/pfx_array_implementation.h @@ -0,0 +1,159 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +/////////////////////////////////////////////////////////////////////////////// +// PfxArray + +namespace sce { +namespace PhysicsEffects { +template +inline T& PfxArray::operator[](PfxUInt32 i) +{ + return m_data[i]; +} + +template +inline const T& PfxArray::operator[](PfxUInt32 i) const +{ + return m_data[i]; +} + +template +inline const PfxArray& PfxArray::operator=(const PfxArray &array) +{ + clear(); + if(array.size() > m_maxData) { + m_maxData = array.size(); + m_data = (T*)SCE_PFX_UTIL_REALLOC(m_data,16,sizeof(T)*m_maxData); + SCE_PFX_ASSERT(m_data); + } + for(PfxUInt32 i=0;i +inline void PfxArray::assign(PfxUInt32 num,const T &initData) +{ + clear(); + if(num > m_maxData) { + m_maxData = num; + m_data = (T*)SCE_PFX_UTIL_REALLOC(m_data,16,sizeof(T)*m_maxData); + SCE_PFX_ASSERT(m_data); + } + for(PfxUInt32 i=0;i +inline PfxUInt32 PfxArray::push(const T& data) +{ + if(m_numData == m_maxData) { + m_maxData<<=1; + m_data = (T*)SCE_PFX_UTIL_REALLOC(m_data,16,sizeof(T)*m_maxData); + SCE_PFX_ASSERT(m_data); + } + + PfxUInt32 id = m_numData++; + m_data[id] = data; + return id; +} + +template +inline bool PfxArray::remove(PfxUInt32 i) +{ + if(i>=m_numData) { + return false; + } + + m_numData--; + m_data[i] = m_data[m_numData]; + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// PfxQueue + +template +inline PfxUInt32 PfxQueue::push(const T& data) +{ + SCE_PFX_ASSERT(m_numData +inline void PfxQueue::pop() +{ + SCE_PFX_ASSERT(m_numData>0); + m_head = (m_head+1)%m_maxData; + m_numData--; +} + +template +inline T& PfxQueue::front() +{ + SCE_PFX_ASSERT(m_numData>0); + return m_data[m_head]; +} + +template +inline const T& PfxQueue::front() const +{ + SCE_PFX_ASSERT(m_numData>0); + return m_data[m_head]; +} + +/////////////////////////////////////////////////////////////////////////////// +// PfxStack + +template +inline PfxUInt32 PfxStack::push(const T& data) +{ + SCE_PFX_ASSERT(m_numData +inline void PfxStack::pop() +{ + SCE_PFX_ASSERT(m_numData>0); + m_numData--; +} + +template +inline T& PfxStack::top() +{ + SCE_PFX_ASSERT(m_numData>0); + return m_data[m_numData-1]; +} + +template +inline const T& PfxStack::top() const +{ + SCE_PFX_ASSERT(m_numData>0); + return m_data[m_numData-1]; +} +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/util/pfx_mass.cpp b/Extras/PhysicsEffects/src/util/pfx_mass.cpp new file mode 100644 index 0000000..ef274bc --- /dev/null +++ b/Extras/PhysicsEffects/src/util/pfx_mass.cpp @@ -0,0 +1,102 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../include/physics_effects/util/pfx_mass.h" + +namespace sce { +namespace PhysicsEffects { + +/////////////////////////////////////////////////////////////////////////////// +// Box + +PfxFloat pfxCalcMassBox(PfxFloat density,const PfxVector3 &halfExtent) +{ + return density * halfExtent[0] * halfExtent[1] * halfExtent[2] * 8; +} + +PfxMatrix3 pfxCalcInertiaBox(const PfxVector3 &halfExtent,PfxFloat mass) +{ + PfxVector3 sqrSz = halfExtent * 2.0f; + sqrSz = mulPerElem(sqrSz,sqrSz); + PfxMatrix3 inertia = PfxMatrix3::identity(); + inertia[0][0] = (mass*(sqrSz[1]+sqrSz[2]))/12.0f; + inertia[1][1] = (mass*(sqrSz[0]+sqrSz[2]))/12.0f; + inertia[2][2] = (mass*(sqrSz[0]+sqrSz[1]))/12.0f; + return inertia; +} + +/////////////////////////////////////////////////////////////////////////////// +// Sphere + +PfxFloat pfxCalcMassSphere(PfxFloat density,PfxFloat radius) +{ + return (4.0f/3.0f) * SCE_PFX_PI * radius * radius * radius * density; +} + +PfxMatrix3 pfxCalcInertiaSphere(PfxFloat radius,PfxFloat mass) +{ + PfxMatrix3 inertia = PfxMatrix3::identity(); + inertia[0][0] = inertia[1][1] = inertia[2][2] = 0.4f * mass * radius * radius; + return inertia; +} + +/////////////////////////////////////////////////////////////////////////////// +// Cylinder + +PfxFloat pfxCalcMassCylinder(PfxFloat density,PfxFloat halfLength,PfxFloat radius) +{ + return SCE_PFX_PI * radius * radius * 2.0f * halfLength * density; +} + +static inline +PfxMatrix3 pfxCalcInertiaCylinder(PfxFloat halfLength,PfxFloat radius,PfxFloat mass,int axis) +{ + PfxMatrix3 inertia = PfxMatrix3::identity(); + inertia[0][0] = inertia[1][1] = inertia[2][2] = 0.25f * mass * radius * radius + 0.33f * mass * halfLength * halfLength; + inertia[axis][axis] = 0.5f * mass * radius * radius; + return inertia; +} + +PfxMatrix3 pfxCalcInertiaCylinderX(PfxFloat halfLength,PfxFloat radius,PfxFloat mass) +{ + return pfxCalcInertiaCylinder(radius,halfLength,mass,0); +} + +PfxMatrix3 pfxCalcInertiaCylinderY(PfxFloat halfLength,PfxFloat radius,PfxFloat mass) +{ + return pfxCalcInertiaCylinder(radius,halfLength,mass,1); +} + +PfxMatrix3 pfxCalcInertiaCylinderZ(PfxFloat halfLength,PfxFloat radius,PfxFloat mass) +{ + return pfxCalcInertiaCylinder(radius,halfLength,mass,2); +} + +/////////////////////////////////////////////////////////////////////////////// + +PfxMatrix3 pfxMassTranslate(PfxFloat mass,const PfxMatrix3 &inertia,const PfxVector3 &translation) +{ + PfxMatrix3 m = crossMatrix(translation); + return inertia + mass * (-m*m); +} + +PfxMatrix3 pfxMassRotate(const PfxMatrix3 &inertia,const PfxMatrix3 &rotate) +{ + return rotate * inertia * transpose(rotate); +} + +} //namespace PhysicsEffects +} //namespace sce diff --git a/Extras/PhysicsEffects/src/util/pfx_mesh_creator.cpp b/Extras/PhysicsEffects/src/util/pfx_mesh_creator.cpp new file mode 100644 index 0000000..6613cb1 --- /dev/null +++ b/Extras/PhysicsEffects/src/util/pfx_mesh_creator.cpp @@ -0,0 +1,944 @@ +/* +Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc. +All rights reserved. + +Physics Effects is open software; you can redistribute it and/or +modify it under the terms of the BSD License. + +Physics Effects is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the BSD License for more details. + +A copy of the BSD License is distributed with +Physics Effects under the filename: physics_effects_license.txt +*/ + +#include "../../include/physics_effects/util/pfx_mesh_creator.h" +#include "pfx_array.h" +#include "../base_level/collision/pfx_intersect_common.h" + +namespace sce { +namespace PhysicsEffects { + +#define SCE_PFX_LARGETRIMESH_MAX_ISLANDS 256 + +/////////////////////////////////////////////////////////////////////////////// +// 凸メッシュ作成時に使用する関数 + +PfxInt32 pfxCreateConvexMesh(PfxConvexMesh &convex,const PfxCreateConvexMeshParam ¶m) +{ + // Check input + if(param.numVerts == 0 || param.numTriangles == 0 || !param.verts || !param.triangles) + return SCE_PFX_ERR_INVALID_VALUE; + + if(param.numVerts >= SCE_PFX_NUMMESHVERTICES || param.numTriangles >= SCE_PFX_NUMMESHFACETS) + return SCE_PFX_ERR_OUT_OF_RANGE; + + PfxArray vertList; + for(PfxUInt32 i=0;i facetList; + for(PfxUInt32 i=0;i facetsInIsland[SCE_PFX_MAX_LARGETRIMESH_ISLANDS]; + PfxUInt32 numIslands; + SCE_PFX_PADDING(1,12) + + PfxMcIslands() + { + numIslands = 0; + } + + void add(PfxArray &facets) + { + facetsInIsland[numIslands++] = facets; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// ラージメッシュ作成時に使用する補助関数 + +static +bool intersect(const PfxMcFacet &facetA,const PfxMcFacet &facetB,PfxFloat &closestDistance) +{ + const PfxFloat epsilon = 0.00001f; + + PfxVector3 pA[3] = { + facetA.v[0]->coord, + facetA.v[1]->coord, + facetA.v[2]->coord + }; + + PfxVector3 pB[3] = { + facetB.v[0]->coord, + facetB.v[1]->coord, + facetB.v[2]->coord + }; + + // 面Bが面Aの厚みを考慮した範囲内に有るかどうかチェック + + // 上下面 + { + PfxPlane planeA(facetA.n,pA[0]); + PfxFloat dmin = SCE_PFX_FLT_MAX; + PfxFloat dmax = -SCE_PFX_FLT_MAX; + for(int i=0;i<3;i++) { + PfxFloat d = planeA.onPlane(pB[i]); + dmin = SCE_PFX_MIN(dmin,d); + dmax = SCE_PFX_MAX(dmax,d); + } + + if(dmin > -epsilon || dmax < -facetA.thickness) return false; + + // 面Aと面Bの最近接距離 + if(dmax > 0.0f) { + // 面A,Bは交差 + return false; + } + else if(dmax > -epsilon) { + // 隣接面 + return false; + } + else { + closestDistance = -dmax; + } + } + + // 側面 + for(int p=0;p<3;p++) { + PfxVector3 sideVec = normalize(cross((pA[(p+1)%3]-pA[p]),facetA.n)); + PfxPlane planeA(sideVec,pA[p]); + + PfxFloat dmin = SCE_PFX_FLT_MAX; + for(int i=0;i<3;i++) { + PfxFloat d = planeA.onPlane(pB[i]); + dmin = SCE_PFX_MIN(dmin,d); + } + + if(dmin > -epsilon) return false; + } + + return true; +} + +static +void divideMeshes( + PfxUInt32 numFacetsLimit,PfxFloat islandsRatio, + PfxMcIslands &islands, + PfxArray &facets, + const PfxVector3 ¢er,const PfxVector3 &half) +{ + PfxFloat halfLimit = length(half) * islandsRatio; + + // 含まれる面数が規定値以下であれば、アイランドに登録 + if((facets.size() <= SCE_PFX_NUMMESHFACETS && length(half) < halfLimit) || + (facets.size() <= numFacetsLimit ) ) { + islands.add(facets); + return; + } + + // さらに分割 + PfxVector3 newCenter0,newCenter1; + PfxVector3 newHalf0,newHalf1; + PfxArray newFacets0; + PfxArray newFacets1; + + // 最も適切と思われる分離軸を探す + int divAxis; + { + if(half[0] > half[1]) { + if(half[0] > half[2]) { + divAxis = 0; + } + else if(half[1] > half[2]) { + divAxis = 1; + } + else { + divAxis = 2; + } + } + else { + if(half[1] > half[2]) { + divAxis = 1; + } + else if(half[0] > half[2]) { + divAxis = 0; + } + else { + divAxis = 2; + } + } + } + + // 中心で分割して、さらに再帰的に処理を続ける + { + PfxVector3 movCenter(0.0f); + movCenter[divAxis] = 0.5f*half[divAxis]; + + newCenter0 = center + movCenter; + newCenter1 = center - movCenter; + newHalf0 = half; + newHalf0[divAxis] *= 0.5f; + newHalf1 = newHalf0; + } + + // 新しいAABBに含まれる面をそれぞれの領域に分配 + for(PfxUInt32 f=0;faabbMin + facets[f]->aabbMax) * 0.5f; + PfxVector3 facetHalf = (facets[f]->aabbMax - facets[f]->aabbMin) * 0.5f; + + // AABB判定 + if(!(fabsf(newCenter0[divAxis]-facetCenter[divAxis]) > (newHalf0[divAxis]+facetHalf[divAxis]))) { + // この面はAABB0に登録 + newFacets0.push(facets[f]); + } + else { + // この面はAABB1に登録 + newFacets1.push(facets[f]); + } + } + + if(newFacets0.size() < newFacets1.size()) { + if(newFacets0.size() > 0) + divideMeshes(numFacetsLimit,islandsRatio,islands,newFacets0,newCenter0,newHalf0); + if(newFacets1.size() > 0) + divideMeshes(numFacetsLimit,islandsRatio,islands,newFacets1,newCenter1,newHalf1); + } + else { + if(newFacets1.size() > 0) + divideMeshes(numFacetsLimit,islandsRatio,islands,newFacets1,newCenter1,newHalf1); + if(newFacets0.size() > 0) + divideMeshes(numFacetsLimit,islandsRatio,islands,newFacets0,newCenter0,newHalf0); + } +} + +static +int addIslandToLargeTriMesh(PfxLargeTriMesh &lmesh,PfxTriMesh &island) +{ + SCE_PFX_ASSERT(island.m_numFacets <= SCE_PFX_NUMMESHFACETS); + + int newIsland = lmesh.m_numIslands++; + lmesh.m_islands[newIsland] = island; + + // アイランドローカルのAABBを計算 + if(island.m_numFacets > 0) { + PfxVector3 aabbMin(SCE_PFX_FLT_MAX),aabbMax(-SCE_PFX_FLT_MAX); + + for(PfxUInt32 i=0;i &facets) +{ + if(facets.empty()) return; + + island.m_numFacets = facets.size(); + + PfxUInt32 vertsFlag[(0xff*SCE_PFX_NUMMESHFACETS*3+31)/32]; + memset(vertsFlag,0,sizeof(PfxUInt32)*((0xff*SCE_PFX_NUMMESHFACETS*3+31)/32)); + + PfxArray edgeHead(facets.size()*3); + PfxArray edgeList(facets.size()*3); + + PfxMcEdgeEntry* nl = NULL; + edgeHead.assign(facets.size()*3,nl); + edgeList.assign(facets.size()*3,PfxMcEdgeEntry()); + + int vcnt = 0; + int ecnt = 0; + for(PfxUInt32 f=0;fv[v]; + PfxUInt32 idx = vert->i; + PfxUInt32 mask = 1 << (idx & 31); + if((vertsFlag[idx>>5] & mask) == 0) { + SCE_PFX_ASSERT(vcnt>5] |= mask; + island.m_verts[vcnt] = vert->coord; + vert->flag = vcnt;// 新しいインデックス + vcnt++; + } + oFacet.m_vertIds[v] = (PfxUInt8)vert->flag; + } + + // Edge + for(int v=0;v<3;v++) { + PfxUInt8 viMin = SCE_PFX_MIN(oFacet.m_vertIds[v],oFacet.m_vertIds[(v+1)%3]); + PfxUInt8 viMax = SCE_PFX_MAX(oFacet.m_vertIds[v],oFacet.m_vertIds[(v+1)%3]); + int key = ((0x8da6b343*viMin+0xd8163841*viMax)%(island.m_numFacets*3)); + for(PfxMcEdgeEntry *e=edgeHead[key];;e=e->next) { + if(!e) { + edgeList[ecnt].vertId[0] = viMin; + edgeList[ecnt].vertId[1] = viMax; + edgeList[ecnt].facetId[0] = f; + edgeList[ecnt].numFacets = 1; + edgeList[ecnt].edgeNum[0] = v; + edgeList[ecnt].edgeId = ecnt; + edgeList[ecnt].dir = normalize(island.m_verts[viMax]-island.m_verts[viMin]); + edgeList[ecnt].next = edgeHead[key]; + edgeHead[key] = &edgeList[ecnt]; + + PfxEdge edge; + edge.m_angleType = iEdge[v]->angleType; + // 厚み角の設定 0~πを0~255の整数値に変換して格納 + edge.m_tilt = (PfxUInt8)((iEdge[v]->angle/(0.5f*SCE_PFX_PI))*255.0f); + edge.m_vertId[0] = viMin; + edge.m_vertId[1] = viMax; + + oFacet.m_edgeIds[v] = ecnt; + island.m_edges[ecnt] = edge; + SCE_PFX_ASSERT(ecnt <= SCE_PFX_NUMMESHEDGES); + ecnt++; + break; + } + + if(e->vertId[0] == viMin && e->vertId[1] == viMax) { + SCE_PFX_ASSERT(e->numFacets==1); + e->facetId[1] = f; + e->edgeNum[1] = v; + e->numFacets = 2; + oFacet.m_edgeIds[v] = e->edgeId; + break; + } + } + } + } + + island.m_numEdges = ecnt; + island.m_numVerts = vcnt; + + island.updateAABB(); +} + +/////////////////////////////////////////////////////////////////////////////// +// ラージメッシュ + +PfxInt32 pfxCreateLargeTriMesh(PfxLargeTriMesh &lmesh,const PfxCreateLargeTriMeshParam ¶m) +{ + // Check input + if(param.numVerts == 0 || param.numTriangles == 0 || !param.verts || !param.triangles) + return SCE_PFX_ERR_INVALID_VALUE; + + if(param.islandsRatio < 0.0f || param.islandsRatio > 1.0f) + return SCE_PFX_ERR_OUT_OF_RANGE; + + if(param.numFacetsLimit == 0 || param.numFacetsLimit > SCE_PFX_NUMMESHFACETS) + return SCE_PFX_ERR_OUT_OF_RANGE; + + const PfxFloat epsilon = 0.00001f; + + PfxArray vertList(param.numVerts); // 頂点配列 + PfxArray facetList(param.numTriangles); // 面配列 + PfxArray edgeList(param.numTriangles*3); // エッジ配列 + PfxArray edgeHead(param.numTriangles*3); + + //J 頂点配列作成 + for(PfxUInt32 i=0;i triEntry(numTriangles*3); + PfxArray triHead(numTriangles*3); // 頂点から面への参照リスト + PfxInt32 cnt = 0; + + PfxMcTriList* nl = NULL; + triEntry.assign(numTriangles*3,PfxMcTriList()); + triHead.assign(numTriangles*3,nl); + + // 頂点から面への参照リストを作成 + for(PfxUInt32 i=0;ii; + triEntry[cnt].facet = &facetList[i]; + triEntry[cnt].next = triHead[vertId]; + triHead[vertId] = &triEntry[cnt++]; + } + } + + // 同一頂点をまとめる + if(param.flag & SCE_PFX_MESH_FLAG_AUTO_ELIMINATION) { + for(PfxUInt32 i=0;inext) { + for(PfxInt32 k=0;k<3;k++) { + if(f->facet->v[k] == &vertList[j]) { + f->facet->v[k] = &vertList[i]; // 頂点を付け替える + break; + } + } + } + } + } + } + } + } + + // 接続面間の角度を算出して面にセット + PfxMcEdge *nl = NULL; + edgeHead.assign(numTriangles*3,nl); + edgeList.assign(numTriangles*3,PfxMcEdge()); + + // エッジ配列の作成 + PfxUInt32 ecnt = 0; + for(PfxUInt32 i=0;inext) { + if(!e) { + edgeList[ecnt].vertId[0] = viMin; + edgeList[ecnt].vertId[1] = viMax; + edgeList[ecnt].facetId[0] = i; + edgeList[ecnt].edgeId[0] = v; + edgeList[ecnt].numFacets = 1; + edgeList[ecnt].next = edgeHead[key]; + edgeList[ecnt].angleType = SCE_PFX_EDGE_CONVEX; + edgeList[ecnt].angle = 0.0f; + edgeHead[key] = &edgeList[ecnt]; + f.e[v] = &edgeList[ecnt]; + ecnt++; + break; + } + + if(e->vertId[0] == viMin && e->vertId[1] == viMax) { + SCE_PFX_ALWAYS_ASSERT_MSG(e->numFacets == 1,"An edge connected with over 2 triangles is invalid"); + e->facetId[1] = i; + e->edgeId[1] = v; + e->numFacets = 2; + f.e[v] = e; + f.neighbor[v] = e->facetId[0]; + f.neighborEdgeId[v] = e->edgeId[0]; + facetList[e->facetId[0]].neighbor[e->edgeId[0]] = i; + facetList[e->facetId[0]].neighborEdgeId[e->edgeId[0]] = e->edgeId[1]; + break; + } + } + } + } + + // 角度を計算 + for(PfxUInt32 i=0;i cqueue(ecnt); + + for(PfxUInt32 j=0;j<3;j++) { + if(facetA.neighbor[j] >= 0) { + cqueue.push(PfxMcFacetLink( + j, + facetA.e[j]->vertId[0],facetA.e[j]->vertId[1], + i,j, + facetA.neighbor[j],facetA.neighborEdgeId[j])); + } + } + + while(!cqueue.empty()) { + PfxMcFacetLink link = cqueue.front(); + cqueue.pop(); + + PfxMcFacet &ofacet = facetList[link.ofacetId]; + PfxMcEdge *edge = ofacet.e[link.oedgeId]; + + // facetAとのなす角を計算 + { + // 面に含まれるが、このエッジに含まれない点 + PfxUInt32 ids[3] = {2,0,1}; + PfxVector3 v1 = facetA.v[ids[link.baseEdgeId]]->coord; + PfxVector3 v2 = ofacet.v[ids[link.oedgeId]]->coord; + + // エッジの凹凸判定 + PfxVector3 midPnt = (v1 + v2) * 0.5f; + PfxVector3 pntOnEdge = facetA.v[link.baseEdgeId]->coord; + + PfxFloat chk1 = dot(facetA.n,midPnt-pntOnEdge); + PfxFloat chk2 = dot(ofacet.n,midPnt-pntOnEdge); + + if(chk1 < -epsilon && chk2 < -epsilon) { + if(link.ifacetId == i) edge->angleType = SCE_PFX_EDGE_CONVEX; + + // 厚み角の判定に使う角度をセット + if(param.flag & SCE_PFX_MESH_FLAG_AUTO_THICKNESS) { + edge->angle = 0.5f*acosf(dot(facetA.n,ofacet.n)); + } + } + else if(chk1 > epsilon && chk2 > epsilon) { + if(link.ifacetId == i) edge->angleType = SCE_PFX_EDGE_CONCAVE; + } + else { + if(link.ifacetId == i) edge->angleType = SCE_PFX_EDGE_FLAT; + } + } + + // 次の接続面を登録(コメントアウトすると頂点で接続された面を考慮しない) + if(param.flag & SCE_PFX_MESH_FLAG_AUTO_THICKNESS) { + PfxInt32 nextEdgeId = (link.oedgeId+1)%3; + PfxMcEdge *nextEdge = ofacet.e[nextEdgeId]; + if(ofacet.neighbor[nextEdgeId] >= 0 && ofacet.neighbor[nextEdgeId] != i && + ((PfxInt32)nextEdge->vertId[0] == link.vid1 || (PfxInt32)nextEdge->vertId[0] == link.vid2 || + (PfxInt32)nextEdge->vertId[1] == link.vid1 || (PfxInt32)nextEdge->vertId[1] == link.vid2) ) { + cqueue.push(PfxMcFacetLink( + link.baseEdgeId, + link.vid1,link.vid2, + link.ofacetId,link.iedgeId, + ofacet.neighbor[nextEdgeId],ofacet.neighborEdgeId[nextEdgeId])); + } + nextEdgeId = (link.oedgeId+2)%3; + nextEdge = ofacet.e[nextEdgeId]; + if(ofacet.neighbor[nextEdgeId] >= 0 && ofacet.neighbor[nextEdgeId] != i && + ((PfxInt32)nextEdge->vertId[0] == link.vid1 || (PfxInt32)nextEdge->vertId[0] == link.vid2 || + (PfxInt32)nextEdge->vertId[1] == link.vid1 || (PfxInt32)nextEdge->vertId[1] == link.vid2) ) { + cqueue.push(PfxMcFacetLink( + link.baseEdgeId, + link.vid1,link.vid2, + link.ofacetId,link.iedgeId, + ofacet.neighbor[nextEdgeId],ofacet.neighborEdgeId[nextEdgeId])); + } + } + } + } + + // 面に厚みを付ける + if(param.flag & SCE_PFX_MESH_FLAG_AUTO_THICKNESS) { + for(PfxUInt32 i=0;ifacetId[0] || + j == (PfxInt32)facetA.e[0]->facetId[1] || + j == (PfxInt32)facetA.e[1]->facetId[0] || + j == (PfxInt32)facetA.e[1]->facetId[1] || + j == (PfxInt32)facetA.e[2]->facetId[0] || + j == (PfxInt32)facetA.e[2]->facetId[1]) { + continue; + } + + PfxMcFacet &facetB = facetList[j]; + + // 交差判定 + PfxFloat closestDistance=0; + if(intersect(facetA,facetB,closestDistance)) { + // 最近接距離/2を厚みとして採用 + facetA.thickness = SCE_PFX_MAX(param.defaultThickness,SCE_PFX_MIN(facetA.thickness,closestDistance * 0.5f)); + } + } + + } + } + + // 面の面積によって3種類に分類する + PfxFloat areaMin=SCE_PFX_FLT_MAX,areaMax=-SCE_PFX_FLT_MAX; + for(PfxUInt32 f=0;f<(PfxUInt32)numTriangles;f++) { + PfxVector3 pnts[3] = { + facetList[f].v[0]->coord, + facetList[f].v[1]->coord, + facetList[f].v[2]->coord, + }; + areaMin = SCE_PFX_MIN(areaMin,facetList[f].area); + areaMax = SCE_PFX_MAX(areaMax,facetList[f].area); + + // 面のAABBを算出 + facetList[f].aabbMin = minPerElem(pnts[2],minPerElem(pnts[1],pnts[0])); + facetList[f].aabbMax = maxPerElem(pnts[2],maxPerElem(pnts[1],pnts[0])); + } + + PfxFloat areaDiff = (areaMax-areaMin)/3.0f; + PfxFloat areaLevel0,areaLevel1; + areaLevel0 = areaMin + areaDiff; + areaLevel1 = areaMin + areaDiff * 2.0f; + + PfxArray facetsLv0(numTriangles); + PfxArray facetsLv1(numTriangles); + PfxArray facetsLv2(numTriangles); + + for(PfxUInt32 f=0;f areaLevel1) { + facetsLv2.push(fct); + } + else { + facetsLv1.push(fct); + } + } + + // アイランドの配列 + PfxMcIslands islands; + PfxVector3 lmeshSize; + + // レベル毎にPfxTriMeshを作成 + if(!facetsLv0.empty()) { + // 全体のAABBを求める + PfxVector3 aabbMin,aabbMax,center,half; + aabbMin =facetsLv0[0]->aabbMin; + aabbMax = facetsLv0[0]->aabbMax; + for(PfxUInt32 f=1;faabbMin,aabbMin); + aabbMax = maxPerElem(facetsLv0[f]->aabbMax,aabbMax); + } + center = ( aabbMin + aabbMax ) * 0.5f; + half = ( aabbMax - aabbMin ) * 0.5f; + + // 再帰的に処理 + divideMeshes( + param.numFacetsLimit,param.islandsRatio, + islands, + facetsLv0, + center,half); + + lmeshSize = maxPerElem(lmeshSize,maxPerElem(absPerElem(aabbMin),absPerElem(aabbMax))); + } + + if(!facetsLv1.empty()) { + // 全体のAABBを求める + PfxVector3 aabbMin,aabbMax,center,half; + aabbMin =facetsLv1[0]->aabbMin; + aabbMax = facetsLv1[0]->aabbMax; + for(PfxUInt32 f=1;faabbMin,aabbMin); + aabbMax = maxPerElem(facetsLv1[f]->aabbMax,aabbMax); + } + center = ( aabbMin + aabbMax ) * 0.5f; + half = ( aabbMax - aabbMin ) * 0.5f; + + // 再帰的に処理 + divideMeshes( + param.numFacetsLimit,param.islandsRatio, + islands, + facetsLv1, + center,half); + + lmeshSize = maxPerElem(lmeshSize,maxPerElem(absPerElem(aabbMin),absPerElem(aabbMax))); + } + + if(!facetsLv2.empty()) { + // 全体のAABBを求める + PfxVector3 aabbMin,aabbMax,center,half; + aabbMin =facetsLv2[0]->aabbMin; + aabbMax = facetsLv2[0]->aabbMax; + for(PfxUInt32 f=1;faabbMin,aabbMin); + aabbMax = maxPerElem(facetsLv2[f]->aabbMax,aabbMax); + } + center = ( aabbMin + aabbMax ) * 0.5f; + half = ( aabbMax - aabbMin ) * 0.5f; + + // 再帰的に処理 + divideMeshes( + param.numFacetsLimit,param.islandsRatio, + islands, + facetsLv2, + center,half); + + lmeshSize = maxPerElem(lmeshSize,maxPerElem(absPerElem(aabbMin),absPerElem(aabbMax))); + } + + lmesh.m_half = lmeshSize; + + // Check Islands + //for(PfxInt32 i=0;iv[0]->i,facet->v[1]->i,facet->v[2]->i); + // } + //} + + // PfxLargeTriMeshの生成 + if(islands.numIslands > 0) { + lmesh.m_numIslands = 0; + lmesh.m_aabbList = (PfxAabb16*)SCE_PFX_UTIL_ALLOC(128,sizeof(PfxAabb16)*islands.numIslands); + lmesh.m_islands = (PfxTriMesh*)SCE_PFX_UTIL_ALLOC(128,sizeof(PfxTriMesh)*islands.numIslands); + + PfxInt32 maxFacets=0,maxVerts=0,maxEdges=0; + for(PfxUInt32 i=0;i + +#ifdef _WIN32 + #define SCE_PFX_UTIL_ALLOC(align,size) _aligned_malloc(size,align) + #define SCE_PFX_UTIL_REALLOC(ptr,align,size) _aligned_realloc(ptr,size,align) + #define SCE_PFX_UTIL_FREE(ptr) if(ptr) {_aligned_free(ptr);ptr=NULL;} +#else + #define SCE_PFX_UTIL_ALLOC(align,size) malloc(size) + #define SCE_PFX_UTIL_REALLOC(ptr,align,size) realloc(ptr,size) + #define SCE_PFX_UTIL_FREE(ptr) if(ptr) {free(ptr);ptr=NULL;} +#endif + +#endif // _SCE_PFX_UTIL_COMMON_H diff --git a/Extras/PhysicsEffects/src/util/premake4.lua b/Extras/PhysicsEffects/src/util/premake4.lua new file mode 100644 index 0000000..483f817 --- /dev/null +++ b/Extras/PhysicsEffects/src/util/premake4.lua @@ -0,0 +1,12 @@ + project "physicseffects2_util" + + kind "StaticLib" + targetdir "../../build/lib" + includedirs { + ".", + } + files { + "**.cpp", + "../../include/physics_effects/util/**.h" + + } \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/bin/glut32.dll b/Extras/RigidBodyGpuPipeline/bin/glut32.dll new file mode 100644 index 0000000000000000000000000000000000000000..3297bd0783b702755a952ad50e518d3e1a922595 GIT binary patch literal 160256 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 G;J*P491%kR literal 0 HcmV?d00001 diff --git a/Extras/RigidBodyGpuPipeline/build/findDirectX11.lua b/Extras/RigidBodyGpuPipeline/build/findDirectX11.lua new file mode 100644 index 0000000..68771c4 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/build/findDirectX11.lua @@ -0,0 +1,36 @@ +function findDirectX11() + local dx11path = os.getenv("DXSDK_DIR") + if (dx11path) then + local filepath = string.format("%s%s",dx11path,"Include/D3D11.h") + headerdx11 = io.open(filepath, "r") + if (headerdx11) then + printf("Found DX11: '%s'", filepath) + return true + end + end + return false + end + +function initDirectX11() + configuration {} + + local dx11path = os.getenv("DXSDK_DIR") + defines { "ADL_ENABLE_DX11"} + includedirs {"$(DXSDK_DIR)/include"} + + configuration "x32" + libdirs {"$(DXSDK_DIR)/Lib/x86"} + configuration "x64" + libdirs {"$(DXSDK_DIR)/Lib/x64"} + configuration {} + links {"d3dcompiler", + "dxerr", + "dxguid", + "d3dx9", + "d3d9", + "winmm", + "comctl32", + "d3dx11" + } + return true +end \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/build/findOpenCL.lua b/Extras/RigidBodyGpuPipeline/build/findOpenCL.lua new file mode 100644 index 0000000..913b840 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/build/findOpenCL.lua @@ -0,0 +1,84 @@ + -- todo: add Apple OpenCL environment vars + + function findOpenCL_AMD() + local amdopenclpath = os.getenv("AMDAPPSDKROOT") + if (amdopenclpath) then + return true + end + return false + end + + function findOpenCL_NVIDIA() + local nvidiaopenclpath = os.getenv("CUDA_PATH") + if (nvidiaopenclpath) then + return true + end + return false + end + + function findOpenCL_Intel() + local intelopenclpath = os.getenv("INTELOCLSDKROOT") + if (intelopenclpath) then + return true + end + return false + end + + function initOpenCL_AMD() + configuration {} + local amdopenclpath = os.getenv("AMDAPPSDKROOT") + if (amdopenclpath) then + defines { "ADL_ENABLE_CL" , "CL_PLATFORM_AMD"} + includedirs { + "$(AMDAPPSDKROOT)/include" + } + configuration "x32" + libdirs {"$(AMDAPPSDKROOT)/lib/x86"} + configuration "x64" + libdirs {"$(AMDAPPSDKROOT)/lib/x86_64"} + configuration {} + links {"OpenCL"} + return true + end + return false + end + + + function initOpenCL_NVIDIA() + configuration {} + local nvidiaopenclpath = os.getenv("CUDA_PATH") + if (nvidiaopenclpath) then + defines { "ADL_ENABLE_CL" , "CL_PLATFORM_NVIDIA"} + includedirs { + "$(CUDA_PATH)/include" + } + configuration "x32" + libdirs {"$(CUDA_PATH)/lib/Win32"} + configuration "x64" + libdirs {"$(CUDA_PATH)/lib/x64"} + configuration {} + links {"OpenCL"} + return true + end + return false + end + + function initOpenCL_Intel() + configuration {} + local intelopenclpath = os.getenv("INTELOCLSDKROOT") + if (intelopenclpath) then + defines { "ADL_ENABLE_CL" , "CL_PLATFORM_INTEL"} + includedirs { + "$(INTELOCLSDKROOT)/include" + } + configuration "x32" + libdirs {"$(INTELOCLSDKROOT)/lib/x86"} + configuration "x64" + libdirs {"$(INTELOCLSDKROOT)/lib/x64"} + configuration {} + links {"OpenCL"} + return true + end + return false + end + \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/build/findOpenGLGlewGlut.lua b/Extras/RigidBodyGpuPipeline/build/findOpenGLGlewGlut.lua new file mode 100644 index 0000000..2a04c6d --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/build/findOpenGLGlewGlut.lua @@ -0,0 +1,52 @@ + -- todo: add Apple OpenCL environment vars + + function initOpenGL() + configuration {} + configuration {"Windows"} + links {"opengl32"} + configuration {"MacOSX"} + links { "Carbon.framework","OpenGL.framework","AGL.framework"} + configuration {"not Windows", "not MacOSX"} + links {"GL","GLU"} + configuration{} + end + + function initGlut() + configuration {} + configuration {"Windows"} + + includedirs { + projectRootDir .. "../../Glut" + } + libdirs { projectRootDir .. "../../Glut"} + configuration {"Windows", "x32"} + links {"glut32"} + configuration {"Windows", "x64"} + links {"glut64"} + + configuration {"MacOSX"} + links { "Glut.framework" } + + configuration {"not Windows", "not MacOSX"} + links {"glut"} + configuration{} + end + + function initGlew() + configuration {} + configuration {"Windows"} + defines { "GLEW_STATIC"} + includedirs { + projectRootDir .. "../../Glut" + } + libdirs { projectRootDir .. "../../Glut"} + configuration {"Windows", "x32"} + links {"glew32s"} + configuration {"Windows", "x64"} + links {"glew64s"} + + configuration{} + end + + + diff --git a/Extras/RigidBodyGpuPipeline/build/premake4.lua b/Extras/RigidBodyGpuPipeline/build/premake4.lua new file mode 100644 index 0000000..b317d35 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/build/premake4.lua @@ -0,0 +1,55 @@ +solution "0MySolution" + + -- Multithreaded compiling + if _ACTION == "vs2010" then + buildoptions { "/MP" } + end + + + + configurations {"Release", "Debug"} + configuration "Release" + flags { "Optimize", "StaticRuntime", "NoMinimalRebuild", "FloatFast"} + configuration "Debug" + flags { "Symbols", "StaticRuntime" , "NoMinimalRebuild", "NoEditAndContinue" ,"FloatFast"} + + platforms {"x32", "x64"} + + configuration "x64" + targetsuffix "_64" + configuration {"x64", "debug"} + targetsuffix "_x64_debug" + configuration {"x64", "release"} + targetsuffix "_x64" + configuration {"x32", "debug"} + targetsuffix "_debug" + + configuration{} + + flags { "NoRTTI", "NoExceptions"} + defines { "_HAS_EXCEPTIONS=0" } + targetdir "../bin" + location("./" .. _ACTION) + + + projectRootDir = os.getcwd() .. "/../" + print("Project root directroy: " .. projectRootDir); + + dofile ("findOpenCL.lua") + dofile ("findDirectX11.lua") + dofile ("findOpenGLGlewGlut.lua") + + language "C++" + + include "../opencl/gpu_rigidbody_pipeline2" + include "../opencl/gpu_rigidbody_pipeline" + + include "../opencl/basic_initialize" + include "../opencl/vector_add" + + include "../opencl/primitives/AdlTest" + include "../opencl/primitives/benchmark" + include "../opencl/3dGridBroadphase" + include "../opencl/broadphase_benchmark" + + \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/build/vs2008.bat b/Extras/RigidBodyGpuPipeline/build/vs2008.bat new file mode 100644 index 0000000..02665f9 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/build/vs2008.bat @@ -0,0 +1,10 @@ + +rem premake4 --no-pelibs vs2008 +rem premake4 --no-pedemos vs2008 +rem premake4 --no-bulletlibs --no-pelibs vs2008 +rem premake4 --with-nacl vs2008 + +..\..\..\msvc\premake4 vs2008 +mkdir vs2008\cache + +pause \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/build/vs2010.bat b/Extras/RigidBodyGpuPipeline/build/vs2010.bat new file mode 100644 index 0000000..9122bab --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/build/vs2010.bat @@ -0,0 +1,5 @@ + +..\..\..\msvc\premake4 vs2010 + +mkdir vs2010\cache +pause \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/AMD/premake4.lua b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/AMD/premake4.lua new file mode 100644 index 0000000..159e25f --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/AMD/premake4.lua @@ -0,0 +1,45 @@ +if os.is("Windows") then + + hasCL = findOpenCL_AMD() + + if (hasCL) then + + project "basic_bullet2_demo_AMD" + + initOpenCL_AMD() + + language "C++" + + kind "ConsoleApp" + targetdir "../../../bin" + + includedirs { + "..", + "../../../bullet2", + "../../testbed", + "../../../rendering/Gwen", + "../../../opencl/basic_initialize", + "../../../opencl/primitives" + } + + + links { "testbed", + "bullet2", + "gwen" + } + + + initOpenGL() + initGlut() + + + files { + "../**.cpp", + "../**.h", + "../../../opencl/basic_initialize/btOpenCLUtils.cpp", + "../../../opencl/basic_initialize/btOpenCLUtils.h" + } + + end + +end diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/BasicDemo.cpp b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/BasicDemo.cpp new file mode 100644 index 0000000..0b6d452 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/BasicDemo.cpp @@ -0,0 +1,538 @@ +/* +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 "BasicDemo.h" +#include "GlutStuff.h" +///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files. +#include "btBulletDynamicsCommon.h" +#include "CustomConvexShape.h" +#include "CustomConvexPairCollision.h" +#include "CustomCollisionDispatcher.h" + +#include "ConvexHeightFieldShape.h" +#include "GLDebugDrawer.h" +static GLDebugDrawer sDebugDraw; + +#include //printf debugging + +#ifdef CL_PLATFORM_AMD +#include "../../opencl/basic_initialize/btOpenCLUtils.h" + +cl_context g_cxMainContext=0; +cl_command_queue g_cqCommandQue=0; +cl_device_id g_clDevice=0; +#endif + +///create 125 (5x5x5) dynamic object +#define ARRAY_SIZE_X 6 +#define ARRAY_SIZE_Y 6 +#define ARRAY_SIZE_Z 4 + +//maximum number of objects (and allow user to shoot additional boxes) +#define MAX_PROXIES (ARRAY_SIZE_X*ARRAY_SIZE_Y*ARRAY_SIZE_Z + 1024) + +///scaling of the objects (0.1 = 20 centimeter boxes ) +#define SCALING 1. +#define START_POS_X 0 +#define START_POS_Y -0.8 +#define START_POS_Z 0 + +#define BoxVtxCount 8 + +static float BoxVtx[] = { +-0.5,-0.5,-0.5, +-0.5,-0.5,0.5, +-0.5,0.5,-0.5, +-0.5,0.5,0.5, +0.5,-0.5,-0.5, +0.5,-0.5,0.5, +0.5,0.5,-0.5, +0.5,0.5,0.5, +}; + +static float BoxVtx2[] = { +-20.3,-10.3,-20.3, +-20.3,-10.3,20.3, +-20.3,10.3,-20.3, +-20.3,10.3,20.3, +20.3,-10.3,-20.3, +20.3,-10.3,20.3, +20.3,10.3,-20.3, +20.3,10.3,20.3, +}; + + +#define BarrelVtxCount2 57 + +static float BarrelVtx2[] = { +0.0f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,-0.331936f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,-0.205148f, 0.0f,-1.0f,0.0f, +-0.349018f,-0.5f,0.0f, 0.0f,-1.0f,0.0f, +-0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +-0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.107853f,-0.5f,0.331936f, 0.0f,-1.0f,0.0f, +0.282362f,-0.5f,0.205148f, 0.0f,-1.0f,0.0f, +0.0f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,-0.331936f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,-0.205148f, 0.0f,1.0f,0.0f, +-0.349018f,0.5f,0.0f, 0.0f,1.0f,0.0f, +-0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +-0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.107853f,0.5f,0.331936f, 0.0f,1.0f,0.0f, +0.282362f,0.5f,0.205148f, 0.0f,1.0f,0.0f, +0.349018f,-0.5f,0.0f, 0.957307f,-0.289072f,0.0f, +0.404509f,0.0f,-0.293893f, 0.809017f,0.0f,-0.587785f, +0.5f,0.0f,0.0f, 1.0f,0.0f,0.0f, +0.282362f,-0.5f,-0.205148f, 0.774478f,-0.289072f,-0.562691f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +0.107853f,-0.5f,-0.331936f, 0.295824f,-0.289072f,-0.910453f, +-0.154509f,0.0f,-0.475528f, -0.309017f,0.0f,-0.951057f, +0.154508f,0.0f,-0.475528f, 0.309017f,0.0f,-0.951057f, +-0.107853f,-0.5f,-0.331936f, -0.295824f,-0.289072f,-0.910453f, +-0.404509f,0.0f,-0.293893f, -0.809017f,0.0f,-0.587785f, +-0.282362f,-0.5f,-0.205148f, -0.774478f,-0.289072f,-0.562691f, +-0.5f,0.0f,0.0f, -1.0f,0.0f,0.0f, +-0.349018f,-0.5f,0.0f, -0.957307f,-0.289072f,0.0f, +-0.404508f,0.0f,0.293893f, -0.809017f,0.0f,0.587785f, +-0.282362f,-0.5f,0.205148f, -0.774478f,-0.289072f,0.562691f, +-0.154509f,0.0f,0.475528f, -0.309017f,0.0f,0.951056f, +-0.107853f,-0.5f,0.331936f, -0.295824f,-0.289072f,0.910453f, +0.154509f,0.0f,0.475528f, 0.309017f,0.0f,0.951056f, +0.107853f,-0.5f,0.331936f, 0.295824f,-0.289072f,0.910453f, +0.404509f,0.0f,0.293892f, 0.809017f,0.0f,0.587785f, +0.282362f,-0.5f,0.205148f, 0.774478f,-0.289072f,0.562691f, +0.282362f,0.5f,-0.205148f, 0.774478f,0.289072f,-0.562691f, +0.349018f,0.5f,0.0f, 0.957307f,0.289072f,0.0f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.107853f,0.5f,-0.331936f, -0.295824f,0.289072f,-0.910453f, +0.107853f,0.5f,-0.331936f, 0.295824f,0.289072f,-0.910453f, +-0.282362f,0.5f,-0.205148f, -0.774478f,0.289072f,-0.562691f, +-0.349018f,0.5f,0.0f, -0.957307f,0.289072f,0.0f, +-0.282362f,0.5f,0.205148f, -0.774478f,0.289072f,0.562691f, +-0.107853f,0.5f,0.331936f, -0.295824f,0.289072f,0.910453f, +0.107853f,0.5f,0.331936f, 0.295824f,0.289072f,0.910453f, +0.282362f,0.5f,0.205148f, 0.774478f,0.289072f,0.562691f, +}; + + +static int BarrelIdx[] = { +0,1,2, +0,3,1, +0,4,5, +0,6,4, +0,7,6, +0,8,7, +0,9,8, +0,10,9, +0,11,10, +0,2,11, +12,13,14, +12,14,15, +12,16,17, +12,17,18, +12,18,19, +12,19,20, +12,20,21, +12,21,22, +12,22,23, +12,23,13, +24,25,26, +24,27,25, +27,28,25, +27,29,28, +30,31,32, +30,33,31, +33,34,31, +33,35,34, +35,36,34, +35,37,36, +37,38,36, +37,39,38, +39,40,38, +39,41,40, +41,42,40, +41,43,42, +43,44,42, +43,45,44, +45,26,44, +45,24,26, +26,46,47, +26,25,46, +25,48,46, +25,28,48, +32,49,50, +32,31,49, +31,51,49, +31,34,51, +34,52,51, +34,36,52, +36,53,52, +36,38,53, +38,54,53, +38,40,54, +40,55,54, +40,42,55, +42,56,55, +42,44,56, +44,47,56, +44,26,47, +}; + + +__inline void glVertexFloat4( const float4& v ) +{ + glVertex3f( v.x, v.y, v.z ); +} + +__inline void drawPointListTransformed(const float4* vtx, int nVtx, const float4& translation, const Quaternion& quat) +{ + glPushMatrix(); + + Matrix3x3 rotMat = mtTranspose( qtGetRotationMatrix( quat ) ); + float transformMat[16] = + { + rotMat.m_row[0].x, rotMat.m_row[0].y, rotMat.m_row[0].z, 0, + rotMat.m_row[1].x, rotMat.m_row[1].y, rotMat.m_row[1].z, 0, + rotMat.m_row[2].x, rotMat.m_row[2].y, rotMat.m_row[2].z, 0, + translation.x, translation.y, translation.z,1 + }; + + glMultMatrixf( transformMat ); + + float4 c = make_float4(1,1,0,0); + + glPointSize(3.f); + glBegin(GL_POINTS); + for(int i=0; igetDebugDrawer()->getDebugMode()& btIDebugDraw::DBG_DrawContactPoints) + for (int i=0;igetCollisionObjectArray().size();i++) + { + btCollisionObject* ob = m_dynamicsWorld->getCollisionObjectArray()[i]; + if (ob->getCollisionShape()->getShapeType() == CUSTOM_POLYHEDRAL_SHAPE_TYPE) + { + CustomConvexShape* customConvex = (CustomConvexShape*)ob->getCollisionShape(); + ConvexHeightField* cvxShape= customConvex->m_ConvexHeightField; + if (!cvxShape) + { + printf("aargh\n"); + } + + float4 bodyApos; + Quaternion bodyAquat; + + + const btVector3& pA = ob->getWorldTransform().getOrigin(); + btQuaternion qA = ob->getWorldTransform().getRotation(); + + bodyApos.x = pA.getX(); + bodyApos.y = pA.getY(); + bodyApos.z = pA.getZ(); + bodyApos.w = 0.f; + bodyAquat.x = qA.getX(); + bodyAquat.y = qA.getY(); + bodyAquat.z = qA.getZ(); + bodyAquat.w = qA.getW(); + + + displaySamples(cvxShape->getSamplePoints(),cvxShape->getNumSamplePoints(),bodyApos,bodyAquat); + + } + + } +} +void BasicDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //simple dynamics world doesn't handle fixed-time-stepping + float ms = getDeltaTimeMicroseconds(); + + ///step the simulation + if (m_dynamicsWorld) + { + m_dynamicsWorld->stepSimulation(ms / 1000000.f); + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + } + + renderme(); + + renderSurfacePoints(); + + + glFlush(); + + swapBuffers(); + +} + + + +void BasicDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + renderSurfacePoints(); + + //optional but useful: debug drawing to detect problems + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + glFlush(); + swapBuffers(); +} + + + + + +void BasicDemo::initPhysics() +{ + setTexturing(true); + setShadows(true); + + m_acceleratedRigidBodies = 0; + + setCameraDistance(btScalar(SCALING*20.)); + + ///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); + + +#ifdef CL_PLATFORM_AMD + m_dispatcher = new CustomCollisionDispatcher(m_collisionConfiguration, g_cxMainContext,g_clDevice,g_cqCommandQue); +#else + m_dispatcher = new CustomCollisionDispatcher(m_collisionConfiguration); +#endif + + m_dispatcher->registerCollisionCreateFunc(CUSTOM_POLYHEDRAL_SHAPE_TYPE,CUSTOM_POLYHEDRAL_SHAPE_TYPE,new CustomConvexConvexPairCollision::CreateFunc(m_collisionConfiguration->getSimplexSolver(), m_collisionConfiguration->getPenetrationDepthSolver())); + + 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->setGravity(btVector3(0,-10,0)); + + m_dynamicsWorld->setDebugDrawer(&sDebugDraw); + + ///create a few basic rigid bodies + //btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); +#if 1 + CustomConvexShape* groundShape = new CustomConvexShape(BoxVtx2,BoxVtxCount,3*sizeof(float)); + //btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),0); + + m_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-11,0)); + + //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here: + { + btScalar mass(0.); + + //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) + groundShape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + //add the body to the dynamics world + m_dynamicsWorld->addRigidBody(body); + } +#endif + + + { + //create a few dynamic rigidbodies + // Re-using the same collision is better for memory usage and performance + + //btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,SCALING*1)); + //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); +#define USE_CUSTOM_HEIGHTFIELD_SHAPE +#ifdef USE_CUSTOM_HEIGHTFIELD_SHAPE + CustomConvexShape* colShape = new CustomConvexShape(BarrelVtx2,BarrelVtxCount2,6*sizeof(float)); + + //CustomConvexShape* colShape = new CustomConvexShape(BoxVtx,BoxVtxCount,3*sizeof(float)); +#else + btConvexHullShape* colShape = new btConvexHullShape(BarrelVtx2,BarrelVtxCount2,6*sizeof(float)); + colShape->setLocalScaling(btVector3(0.9,0.9,0.9)); + +#endif //USE_CUSTOM_HEIGHTFIELD_SHAPE + btScalar scale = 0.5f; + + //btScalar scale = 1.f; + + //next line is already called inside the CustomConvexShape constructor + //colShape->initializePolyhedralFeatures(); + + m_collisionShapes.push_back(colShape); + + /// Create Dynamic Objects + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + + //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) + colShape->calculateLocalInertia(mass,localInertia); + + float start_x = START_POS_X - ARRAY_SIZE_X/2; + float start_y = START_POS_Y; + float start_z = START_POS_Z - ARRAY_SIZE_Z/2; + + for (int k=0;k0) && ((j<2) || (j>(ARRAY_SIZE_Z-3)))) + // continue; + // if ((k>0) && ((i<2) || (i>(ARRAY_SIZE_X-3)))) + // continue; + + startTransform.setOrigin(SCALING*btVector3( + btScalar(scale*2.0*i + start_x), + btScalar(scale*1+scale*2.0*k + start_y), + btScalar(scale*2.0*j + start_z))); + + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + btRigidBody* body=0; + + if (0)//k==0) + { + btVector3 zeroInertia(0,0,0); + btRigidBody::btRigidBodyConstructionInfo rbInfo(0.f,myMotionState,colShape,zeroInertia); + body = new btRigidBody(rbInfo); + } else + { + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia); + body = new btRigidBody(rbInfo); + } + + //m_acceleratedRigidBodies is used as a mapping to the accelerated rigid body index + body->setCompanionId(m_acceleratedRigidBodies++); + m_dynamicsWorld->addRigidBody(body); + + } + } + } + } + } + + +} +void BasicDemo::clientResetScene() +{ + exitPhysics(); + initPhysics(); +} + + +void BasicDemo::exitPhysics() +{ + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int 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;j m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + int m_acceleratedRigidBodies; + + public: + + BasicDemo() + { + } + virtual ~BasicDemo() + { + exitPhysics(); + } + void initPhysics(); + + void exitPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + virtual void clientResetScene(); + + static DemoApplication* Create() + { + BasicDemo* demo = new BasicDemo; + demo->myinit(); + demo->initPhysics(); + return demo; + } + + void renderSurfacePoints(); + + +}; + +#endif //BASIC_DEMO_H + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/ConvexHeightFieldShape.cpp b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/ConvexHeightFieldShape.cpp new file mode 100644 index 0000000..e5e0d64 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/ConvexHeightFieldShape.cpp @@ -0,0 +1,507 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#include "ConvexHeightFieldShape.h" +#include "Stubs/AdlCollideUtils.h" +#include "CubeMapUtils.h" +//#include +//#include +//#include "GlutStuff.h" + +//#define USE_OLD + +ConvexHeightField::ConvexHeightField(const float4* vtxBuffer, const int4* idxBuffer, int nTriangles) +: CollisionShape( SHAPE_CONVEX_HEIGHT_FIELD ) +{ + create( vtxBuffer, idxBuffer, nTriangles ); +} + +void ConvexHeightField::create( const float4* vtxBuffer, const int4* idxBuffer, int nTriangles ) +{ + { + float maxDx2 = -1.f; + int maxIdx = -1; + for(int i=0; i maxDx2 ) + { + maxDx2 = dx2; + maxIdx = idx.s[j]; + } + } + } + ADLASSERT( maxIdx != -1 ); + m_scale = sqrtf( maxDx2 ); + } + + // cast ray to find intersectPlaneLineions + { + for(u32 faceIdx=0; faceIdx<6; faceIdx++) + { + for(int i=0; i 0.f ) + { + minFraction = min2( minFraction, fraction ); // todo. have to check if this is the min to replace normal? + float4 ab = vtxBuffer[idxBuffer[itri].y]-vtxBuffer[idxBuffer[itri].x]; + float4 ac = vtxBuffer[idxBuffer[itri].z]-vtxBuffer[idxBuffer[itri].x]; + minNormal = cross3( ab, ac ); + minBCrd = bCrd; + } + } + + if( minFraction == FLT_MAX ) + minFraction = 0.f; + + { + u8 quantizedHeight = (u8)(minFraction*255.f); + sample( (Face)faceIdx, i,j ) = quantizedHeight; + sampleNormal( (Face)faceIdx, i,j ) = normalize3(minNormal); + float minValue = 3.f*(1.f/3.f)*(1.f/3.f); + sampleNormal( (Face)faceIdx, i,j ).w = (dot3F4( minBCrd, minBCrd ) - minValue )/(1.f-minValue); + } + } + } + } + + calcSamplePoints( m_samplePoints ); + + // calc support height using m_samplePoints + { + for(u32 faceIdx=0; faceIdx<6; faceIdx++) for(int i=0; i maxHeight ) maxHeight = h; + } + + { + u8 quantizedHeight = min2((u8)(maxHeight*255.f)+1, 255); + sampleSupport( (Face)faceIdx, i, j ) = quantizedHeight; + } + } + } + + m_aabb.setEmpty(); + for(int i=0; i 0.f ) + { + if( fraction < minFraction ) + { + minFraction = fraction; + minNormal = iEqn; + } + } + } + + ADLASSERT( minFraction != FLT_MAX ); + + minNormal.w = minFraction; + sampleNormal( (Face)faceIdx, i, j ) = minNormal; + } + } + } + + { + m_scale = -FLT_MAX; + for(u32 faceIdx=0; faceIdx<6; faceIdx++) + { + for(int i=0; i1.f) + h=1.f; +// ADLASSERT( h <= 1.f ); + if( h > maxHeight ) maxHeight = h; + } + + { + u8 quantizedHeight = min2((u8)(maxHeight*255.f)+1, 255); + sampleSupport( (Face)faceIdx, i, j ) = quantizedHeight; + } + } + } + + for(int i=0; i<6; i++) + { + m_faceAabbs[i].setEmpty(); + for(int j=0; jm_type == ADL_SHAPE_SPHERE ) + { + SphereShape* sphere = (SphereShape*)shape; + + m_scale = sphere->m_radius; + for(u32 faceIdx=0; faceIdx<6; faceIdx++) + { + for(int i=0; im_radius ); + m_aabb.m_min = make_float4( -sphere->m_radius ); + + m_aabb.expandBy( make_float4( m_collisionMargin ) ); + + for(int i=0; i<6; i++) + { + m_faceAabbs[i].setEmpty(); + for(int j=0; jgetVertexBuffer(), s->getTriangleBuffer(), s->getNumTris() ); + } +} +#endif + +ConvexHeightField::~ConvexHeightField() +{ + +} + +float ConvexHeightField::queryDistance(const float4& p ) const +{ + const float4 majorAxes[] = {make_float4(1,0,0,0), make_float4(0,1,0,0), make_float4(0,0,1,0)}; + + if( dot3F4( p, p ) >= m_scale*m_scale ) return FLT_MAX; + + int faceIdx; + float x, y; + CubeMapUtils::calcCrd( p, faceIdx, x, y ); + x = (x*HEIGHT_RES) - 0.5f; + y = (y*HEIGHT_RES) - 0.5f; + + float height; + { + int xi = (int)(x); + int yi = (int)(y); + float dx = x-xi; + float dy = y-yi; + + { + int xip = min2((int)(HEIGHT_RES-1), xi+1); + int yip = min2((int)(HEIGHT_RES-1), yi+1); + + u8 xy = sample( (Face)faceIdx, xi, yi ); + u8 xpy = sample( (Face)faceIdx, xip, yi ); + u8 xpyp = sample( (Face)faceIdx, xip, yip ); + u8 xyp = sample( (Face)faceIdx, xi, yip ); + + height = (xy*(1.f-dx)+xpy*dx)*(1.f-dy) + (xyp*(1.f-dx)+xpyp*dx)*dy; + height = height/255.f*m_scale; + + height = length3( p ) - height; + } + } + + return height; +} + +float ConvexHeightField::querySupportHeight(const float4& p ) const +{ + const float4 majorAxes[] = {make_float4(1,0,0,0), make_float4(0,1,0,0), make_float4(0,0,1,0)}; + +// if( dot3F4( p, p ) >= m_scale*m_scale ) return FLT_MAX; + + int faceIdx; + float x, y; + CubeMapUtils::calcCrd( p, faceIdx, x, y ); + x = (x*HEIGHT_RES) - 0.5f; + y = (y*HEIGHT_RES) - 0.5f; + + float height; + { + int xi = (int)(x); + int yi = (int)(y); + float dx = x-xi; + float dy = y-yi; + + { + int xip = min2((int)(HEIGHT_RES-1), xi+1); + int yip = min2((int)(HEIGHT_RES-1), yi+1); + + u8 xy = sampleSupport( (Face)faceIdx, xi, yi ); + u8 xpy = sampleSupport( (Face)faceIdx, xip, yi ); + u8 xpyp = sampleSupport( (Face)faceIdx, xip, yip ); + u8 xyp = sampleSupport( (Face)faceIdx, xi, yip ); + + height = max2( xy, max2( xpy, max2( xpyp, xyp ) ) ); + height = height/255.f*m_scale; + } + } + + return height; +} + +float ConvexHeightField::queryW(const float4& p ) const +{ + const float4 majorAxes[] = {make_float4(1,0,0,0), make_float4(0,1,0,0), make_float4(0,0,1,0)}; + + float value; + if( dot3F4( p, p ) >= m_scale*m_scale ) return 0; + + int faceIdx; + float x, y; + CubeMapUtils::calcCrd( p, faceIdx, x, y ); + x = (x*HEIGHT_RES) - 0.5f; + y = (y*HEIGHT_RES) - 0.5f; + + { + int xi = (int)(x); + int yi = (int)(y); + + value = sampleNormal( (Face)faceIdx, xi, yi ).w; + } + return value; +} + +bool ConvexHeightField::queryDistanceWithNormal( const float4& p, float4& normalOut ) const +{ + int faceIdx; + float x, y; + CubeMapUtils::calcCrd( p, faceIdx, x, y ); + x = (x*HEIGHT_RES) - 0.5f; + y = (y*HEIGHT_RES) - 0.5f; + + { + int xi = (int)(x); + int yi = (int)(y); + + normalOut = sampleNormal( (Face)faceIdx, xi, yi ); + } + return true; +} + +void ConvexHeightField::calcSamplePoints(float4* points) const +{ + for(u32 faceIdx=0; faceIdx<6; faceIdx++) + { + for(int i=0; ir2[0])? 1:0; + idx = (r2[2]>r2[idx])? 2:idx; + majorAxis = majorAxes[idx]; + + bool isNeg = dot3F4( p, majorAxis ) < 0.f; + + faceIdxOut = (idx*2+((isNeg)? 0:1)); +//== + float4 abs = make_float4( fabs(p.x), fabs(p.y), fabs(p.z), 0.f ); + + float d; + if( idx == 0 ) + { + x = p.y; + y = p.z; + d = abs.x; + } + else if( idx == 1 ) + { + x = p.z; + y = p.x; + d = abs.y; + } + else + { + x = p.x; + y = p.y; + d = abs.z; + } + + float dInv = (d==0.f)? 0.f: (1.f/d); + x = (x*dInv+1.f)*0.5f; + y = (y*dInv+1.f)*0.5f; + } +} + +__inline +float4 CubeMapUtils::calcVector(int faceIdx, float x, float y) +{ + int dir = faceIdx/2; + float z = (faceIdx%2 == 0)? -1.f:1.f; + + x = x*2.f-1.f; + y = y*2.f-1.f; + + if( dir == 0 ) + { + return make_float4(z, x, y); + } + else if( dir == 1 ) + { + return make_float4(y,z,x); + } + else + { + return make_float4(x,y,z); + } +} + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomCollisionDispatcher.cpp b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomCollisionDispatcher.cpp new file mode 100644 index 0000000..762afd2 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomCollisionDispatcher.cpp @@ -0,0 +1,699 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + +#include "CustomCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "CustomConvexShape.h" +#include "CustomConvexPairCollision.h" +#include "LinearMath/btQuickprof.h" + + + +#ifdef CL_PLATFORM_AMD + +#include "Adl/Adl.h" +#include "Stubs/AdlMath.h" +#include "Stubs/AdlContact4.h" +#include "Stubs/AdlQuaternion.h" +#include "Stubs/ChNarrowPhase.h" + +#include "Stubs/Solver.h" + + +struct CustomDispatchData +{ + adl::DeviceCL* m_ddcl; + adl::Device* m_deviceHost; + ShapeDataType m_ShapeBuffer; + + adl::HostBuffer* m_pBufPairsCPU; + adl::Buffer* m_pBufPairsGPU; + adl::Buffer* m_pBufContactOutGPU; + adl::HostBuffer* m_pBufContactOutCPU; + adl::ChNarrowphase::Data* m_Data; + + adl::HostBuffer* m_pBufRBodiesCPU; + adl::Buffer* m_pBufRBodiesGPU; + + adl::Buffer* m_bodyInfoBufferCPU; + adl::Buffer* m_bodyInfoBufferGPU; + + adl::Solver::Data* m_solverDataGPU; + SolverData m_contactCGPU; + void* m_frictionCGPU; + + int m_numAcceleratedShapes; +}; +#endif //CL_PLATFORM_AMD + +CustomCollisionDispatcher::CustomCollisionDispatcher(btCollisionConfiguration* collisionConfiguration +#ifdef CL_PLATFORM_AMD + , cl_context context,cl_device_id device,cl_command_queue queue +#endif //CL_PLATFORM_AMD +):btCollisionDispatcher(collisionConfiguration), +m_internalData(0) +{ +#ifdef CL_PLATFORM_AMD + + if (context && queue) + { + m_internalData = new CustomDispatchData(); + memset(m_internalData,0,sizeof(CustomDispatchData)); + + adl::DeviceUtils::Config cfg; + m_internalData->m_ddcl = new adl::DeviceCL(); + m_internalData->m_ddcl->m_deviceIdx = device; + m_internalData->m_ddcl->m_context = context; + m_internalData->m_ddcl->m_commandQueue = queue; + m_internalData->m_ddcl->m_kernelManager = new adl::KernelManager; + + + m_internalData->m_deviceHost = adl::DeviceUtils::allocate( adl::TYPE_HOST, cfg ); + m_internalData->m_pBufPairsCPU = new adl::HostBuffer(m_internalData->m_deviceHost, MAX_BROADPHASE_COLLISION_CL); + m_internalData->m_pBufContactOutCPU = new adl::HostBuffer(m_internalData->m_deviceHost, MAX_BROADPHASE_COLLISION_CL); + m_internalData->m_pBufRBodiesCPU = new adl::HostBuffer(m_internalData->m_deviceHost, MAX_CONVEX_BODIES_CL); + + m_internalData->m_bodyInfoBufferCPU = new adl::Buffer(m_internalData->m_deviceHost,MAX_CONVEX_BODIES_CL); + m_internalData->m_pBufContactOutGPU = new adl::Buffer(m_internalData->m_ddcl, MAX_BROADPHASE_COLLISION_CL); + m_internalData->m_bodyInfoBufferGPU = new adl::Buffer(m_internalData->m_ddcl,MAX_CONVEX_BODIES_CL); + m_internalData->m_pBufPairsGPU = new adl::Buffer(m_internalData->m_ddcl, MAX_BROADPHASE_COLLISION_CL); + m_internalData->m_solverDataGPU = adl::Solver::allocate( m_internalData->m_ddcl, MAX_BROADPHASE_COLLISION_CL); + m_internalData->m_pBufRBodiesGPU = new adl::Buffer(m_internalData->m_ddcl, MAX_CONVEX_BODIES_CL); + m_internalData->m_Data = adl::ChNarrowphase::allocate(m_internalData->m_ddcl); + m_internalData->m_ShapeBuffer = adl::ChNarrowphase::allocateShapeBuffer(m_internalData->m_ddcl, MAX_CONVEX_SHAPES_CL); + m_internalData->m_numAcceleratedShapes = 0; + + m_internalData->m_contactCGPU = adl::Solver::allocateConstraint4( m_internalData->m_ddcl, MAX_BROADPHASE_COLLISION_CL); + m_internalData->m_frictionCGPU = adl::Solver::allocateFrictionConstraint( m_internalData->m_ddcl, MAX_BROADPHASE_COLLISION_CL); + + } + + + +#endif //CL_PLATFORM_AMD +} + +CustomCollisionDispatcher::~CustomCollisionDispatcher(void) +{ +#ifdef CL_PLATFORM_AMD + if (m_internalData) + { + delete m_internalData->m_pBufPairsCPU; + delete m_internalData->m_pBufPairsGPU; + delete m_internalData->m_pBufContactOutGPU; + delete m_internalData->m_pBufContactOutCPU; + + adl::Solver::deallocateConstraint4( m_internalData->m_contactCGPU ); + adl::Solver::deallocateFrictionConstraint( m_internalData->m_frictionCGPU ); + + + adl::Solver::deallocate(m_internalData->m_solverDataGPU); + + adl::DeviceUtils::deallocate(m_internalData->m_deviceHost); + delete m_internalData->m_ddcl; + delete m_internalData; + } + +#endif //CL_PLATFORM_AMD + +} + + +#ifdef CL_PLATFORM_AMD +#include "BulletDynamics/Dynamics/btRigidBody.h" + +RigidBodyBase::Shape CreateBodyInfo(const btCollisionObject& colObj) +{ + RigidBodyBase::Shape shape; + const btRigidBody* bulletBody = btRigidBody::upcast(&colObj); + if( colObj.isStaticOrKinematicObject() || !bulletBody) + { + + //body.m_quat = qtGetIdentity(); + //body.m_invMass = 0.f; + shape.m_initInvInertia = mtZero(); + shape.m_invInertia = mtZero(); + } + else + { + + btVector3 invLocalInertia = bulletBody->getInvInertiaDiagLocal(); + shape.m_initInvInertia = mtZero(); + shape.m_initInvInertia.m_row[0].x = invLocalInertia.x(); + shape.m_initInvInertia.m_row[1].y = invLocalInertia.y(); + shape.m_initInvInertia.m_row[2].z = invLocalInertia.z(); + + btQuaternion q = colObj.getWorldTransform().getRotation(); + Quaternion qBody; + qBody.x = q.getX(); + qBody.y = q.getY(); + qBody.z = q.getZ(); + qBody.w = q.getW(); + + Matrix3x3 m = qtGetRotationMatrix( qBody); + Matrix3x3 mT = mtTranspose( m ); + shape.m_invInertia = mtMul( mtMul( m, shape.m_initInvInertia ), mT ); + //bulletBody->getInvInertiaTensorWorld(); + + + + + // shape.m_initInvInertia = mtInvert( localInertia ); + } + return shape; +} + +RigidBodyBase::Body CreateRBodyCL(const btCollisionObject& colObj, int shapeIdx) +{ + RigidBodyBase::Body bodyCL; + + + // position + const btVector3& p = colObj.getWorldTransform().getOrigin(); + bodyCL.m_pos.x = p.getX(); + bodyCL.m_pos.y = p.getY(); + bodyCL.m_pos.z = p.getZ(); + bodyCL.m_pos.w = 0.0f; + + // quaternion + btQuaternion q = colObj.getWorldTransform().getRotation(); + bodyCL.m_quat.x = q.getX(); + bodyCL.m_quat.y = q.getY(); + bodyCL.m_quat.z = q.getZ(); + bodyCL.m_quat.w = q.getW(); + + const btRigidBody* bulletBody = btRigidBody::upcast(&colObj); + if( colObj.isStaticOrKinematicObject() || !bulletBody) + { + // linear velocity + bodyCL.m_linVel = make_float4(0.0f, 0.0f, 0.0f); + + // angular velocity + bodyCL.m_angVel = make_float4(0.0f, 0.0f, 0.0f); + bodyCL.m_invMass = 0.f; + } else + { + // linear velocity + const btVector3& lv = bulletBody->getLinearVelocity(); + const btVector3& av = bulletBody->getAngularVelocity(); + + bodyCL.m_linVel = make_float4(lv.x(),lv.y(),lv.z(),0.0f); + // angular velocity + bodyCL.m_angVel = make_float4(av.x(),av.y(),av.z(),0.0f); + bodyCL.m_invMass = bulletBody->getInvMass(); + } + // shape index + bodyCL.m_shapeIdx = shapeIdx; + + + // restituition coefficient + bodyCL.m_restituitionCoeff = colObj.getRestitution(); + + // friction coefficient + bodyCL.m_frictionCoeff = colObj.getFriction(); + + return bodyCL; +} +#endif //CL_PLATFORM_AMD + +void CustomCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) +{ + BT_PROFILE("CustomCollisionDispatcher::dispatchAllCollisionPairs"); + { + btBroadphasePairArray& overlappingPairArray = pairCache->getOverlappingPairArray(); + bool bGPU = (m_internalData != 0); +#ifdef CL_PLATFORM_AMD + if ( !bGPU ) +#endif //CL_PLATFORM_AMD + { + BT_PROFILE("btCollisionDispatcher::dispatchAllCollisionPairs"); + btCollisionDispatcher::dispatchAllCollisionPairs(pairCache,dispatchInfo,dispatcher); + } +#ifdef CL_PLATFORM_AMD + + else + { + { + BT_PROFILE("refreshContactPoints"); + //---------------------------------------------------------------- + // GPU version of convex heightmap narrowphase collision detection + //---------------------------------------------------------------- + for ( int i = 0; i < getNumManifolds(); i++ ) + { + btPersistentManifold* manifold = getManifoldByIndexInternal(i); + + + btCollisionObject* body0 = (btCollisionObject*)manifold->getBody0(); + btCollisionObject* body1 = (btCollisionObject*)manifold->getBody1(); + + manifold->refreshContactPoints(body0->getWorldTransform(),body1->getWorldTransform()); + } + } + + // OpenCL + int nColPairsFromBP = overlappingPairArray.size(); + btAssert(MAX_BROADPHASE_COLLISION_CL >= nColPairsFromBP); + + int maxBodyIndex = -1; + + { + BT_PROFILE("CreateRBodyCL and GPU pairs"); + for ( int i=0; im_pProxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)pair->m_pProxy1->m_clientObject; + + int bodyIndex0 = colObj0->getCompanionId(); + int bodyIndex1 = colObj1->getCompanionId(); + + //keep a one-to-one mapping between Bullet and Adl broadphase pairs + (*m_internalData->m_pBufPairsCPU)[i].x = bodyIndex0; + (*m_internalData->m_pBufPairsCPU)[i].y = bodyIndex1; + + if (bodyIndex0>=0 && bodyIndex1>=0) + { + //create companion shapes (if necessary) + + btAssert(colObj0->getCollisionShape()->getShapeType() == CUSTOM_POLYHEDRAL_SHAPE_TYPE); + btAssert(colObj1->getCollisionShape()->getShapeType() == CUSTOM_POLYHEDRAL_SHAPE_TYPE); + + CustomConvexShape* convexShape0 = (CustomConvexShape*)colObj0->getCollisionShape(); + CustomConvexShape* convexShape1 = (CustomConvexShape*)colObj1->getCollisionShape(); + + if (convexShape0->m_acceleratedCompanionShapeIndex<0) + { + convexShape0->m_acceleratedCompanionShapeIndex = m_internalData->m_numAcceleratedShapes; + adl::ChNarrowphase::setShape(m_internalData->m_ShapeBuffer, convexShape0->m_ConvexHeightField, convexShape0->m_acceleratedCompanionShapeIndex, 0.0f); + m_internalData->m_numAcceleratedShapes++; + } + if (convexShape1->m_acceleratedCompanionShapeIndex<0) + { + convexShape1->m_acceleratedCompanionShapeIndex = m_internalData->m_numAcceleratedShapes; + adl::ChNarrowphase::setShape(m_internalData->m_ShapeBuffer, convexShape1->m_ConvexHeightField, convexShape1->m_acceleratedCompanionShapeIndex, 0.0f); + m_internalData->m_numAcceleratedShapes++; + } + + btAssert(m_internalData->m_numAcceleratedShapesmaxBodyIndex) + maxBodyIndex = bodyIndex0; + if (bodyIndex1>maxBodyIndex) + maxBodyIndex = bodyIndex1; + + btAssert(maxBodyIndex=MAX_CONVEX_BODIES_CL) + { + printf("error: maxBodyIndex(%d)>MAX_CONVEX_BODIES_CL(%d)\n",maxBodyIndex,MAX_CONVEX_BODIES_CL); + } + + (*m_internalData->m_pBufRBodiesCPU)[bodyIndex0] = CreateRBodyCL(*colObj0, convexShape0->m_acceleratedCompanionShapeIndex); + m_internalData->m_bodyInfoBufferCPU->m_ptr[bodyIndex0] = CreateBodyInfo(*colObj0); + (*m_internalData->m_pBufRBodiesCPU)[bodyIndex1] = CreateRBodyCL(*colObj1, convexShape0->m_acceleratedCompanionShapeIndex); + m_internalData->m_bodyInfoBufferCPU->m_ptr[bodyIndex1] = CreateBodyInfo(*colObj1); + } else + { + //TODO: dispatch using default dispatcher + btAssert(0); + } + } + } + + + if (maxBodyIndex>=0) + { + + int numOfConvexRBodies = maxBodyIndex+1; + + + + adl::ChNarrowphaseBase::Config cfgNP; + cfgNP.m_collisionMargin = 0.01f; + int nContactOut = 0; + + { + BT_PROFILE("ChNarrowphase::execute"); + adl::ChNarrowphase::execute(m_internalData->m_Data, m_internalData->m_pBufPairsGPU, nColPairsFromBP, m_internalData->m_pBufRBodiesGPU, m_internalData->m_ShapeBuffer, m_internalData->m_pBufContactOutGPU, nContactOut, cfgNP); + adl::DeviceUtils::waitForCompletion(m_internalData->m_ddcl); + } + + + bool useCpu = false;//true; + bool useSolver = true;//true;//false; + + if (useSolver) + { + float dt=1./60.; + adl::SolverBase::ConstraintCfg csCfg( dt ); + csCfg.m_enableParallelSolve = true; + csCfg.m_averageExtent = 0.2f;//@TODO m_averageObjExtent; + csCfg.m_staticIdx = -1;//numOfConvexRBodies-1;//m_nBodies-1; + + + if (useCpu) + { + + { + BT_PROFILE("read m_pBufContactOutGPU"); + m_internalData->m_pBufContactOutGPU->read(m_internalData->m_pBufContactOutCPU->m_ptr, nContactOut);//MAX_BROADPHASE_COLLISION_CL); + adl::DeviceUtils::waitForCompletion(m_internalData->m_ddcl); + } + + BT_PROFILE("CPU stuff"); + adl::Solver::Data* solverData = adl::Solver::allocate( m_internalData->m_deviceHost, nContactOut); + + SolverData contactCPU = adl::Solver::allocateConstraint4( + m_internalData->m_deviceHost, + numOfConvexRBodies*MAX_PAIRS_PER_BODY_CL ); + + void* frictionCPU = adl::Solver::allocateFrictionConstraint( + m_internalData->m_deviceHost, + numOfConvexRBodies*MAX_PAIRS_PER_BODY_CL ); + + //write body with current linear/angluar velocities to GPU + m_internalData->m_bodyInfoBufferGPU->write(m_internalData->m_bodyInfoBufferCPU->m_ptr,numOfConvexRBodies); + adl::DeviceUtils::waitForCompletion(m_internalData->m_ddcl); + + + if (nContactOut) + { + reorderConvertToConstraints2( + solverData, + m_internalData->m_pBufRBodiesCPU, + m_internalData->m_bodyInfoBufferCPU, + m_internalData->m_pBufContactOutCPU, + contactCPU, + frictionCPU, + nContactOut, + csCfg ); + + bool forceGPU = true; + + if (forceGPU) + { + + SolverData contactCPUcopy = adl::Solver::allocateConstraint4( + m_internalData->m_deviceHost, + numOfConvexRBodies*MAX_PAIRS_PER_BODY_CL ); + + adl::Solver::reorderConvertToConstraints( + m_internalData->m_solverDataGPU, + m_internalData->m_pBufRBodiesGPU, + m_internalData->m_bodyInfoBufferGPU, + m_internalData->m_pBufContactOutGPU, + m_internalData->m_contactCGPU, + m_internalData->m_frictionCGPU, + nContactOut, + csCfg ); + + adl::DeviceUtils::waitForCompletion(m_internalData->m_ddcl); + m_internalData->m_contactCGPU->read(contactCPUcopy->m_ptr,nContactOut); + adl::DeviceUtils::waitForCompletion(m_internalData->m_ddcl); + + + //m_internalData->m_contactCGPU->write(contactCPU->m_ptr,nContactOut); + adl::DeviceUtils::waitForCompletion(m_internalData->m_ddcl); + m_internalData->m_solverDataGPU->m_nIterations = 4; + + adl::Solver::solveContactConstraint( m_internalData->m_solverDataGPU, + m_internalData->m_pBufRBodiesGPU, + m_internalData->m_bodyInfoBufferGPU, + m_internalData->m_contactCGPU, + 0, + nContactOut ); + + adl::DeviceUtils::waitForCompletion( m_internalData->m_ddcl ); + + //read body updated linear/angular velocities back to CPU + m_internalData->m_pBufRBodiesGPU->read( + m_internalData->m_pBufRBodiesCPU->m_ptr,numOfConvexRBodies); + adl::DeviceUtils::waitForCompletion( m_internalData->m_ddcl ); + + } else + { + solverData->m_nIterations = 4; + adl::Solver::solveContactConstraint( solverData, + m_internalData->m_pBufRBodiesCPU, + m_internalData->m_bodyInfoBufferCPU, + contactCPU, + 0, + nContactOut ); + } + + + + } + + adl::Solver::deallocateConstraint4( contactCPU ); + adl::Solver::deallocateFrictionConstraint( frictionCPU ); + adl::Solver::deallocate( solverData ); + + + + } + else + { + + { + BT_PROFILE("rigid body data to GPU buffer"); + // Transfer rigid body data from CPU buffer to GPU buffer + m_internalData->m_pBufRBodiesGPU->write(m_internalData->m_pBufRBodiesCPU->m_ptr, numOfConvexRBodies); + m_internalData->m_pBufPairsGPU->write(m_internalData->m_pBufPairsCPU->m_ptr, MAX_BROADPHASE_COLLISION_CL); + //write body with current linear/angluar velocities to GPU + m_internalData->m_bodyInfoBufferGPU->write(m_internalData->m_bodyInfoBufferCPU->m_ptr,numOfConvexRBodies); + adl::DeviceUtils::waitForCompletion(m_internalData->m_ddcl); + } + { + BT_PROFILE("GPU reorderConvertToConstraints"); + adl::Solver::reorderConvertToConstraints( + m_internalData->m_solverDataGPU, + m_internalData->m_pBufRBodiesGPU, + m_internalData->m_bodyInfoBufferGPU, + m_internalData->m_pBufContactOutGPU, + m_internalData->m_contactCGPU, + m_internalData->m_frictionCGPU, + nContactOut, + csCfg ); + } + + { + BT_PROFILE("GPU solveContactConstraint"); + m_internalData->m_solverDataGPU->m_nIterations = 4; + + adl::Solver::solveContactConstraint( m_internalData->m_solverDataGPU, + m_internalData->m_pBufRBodiesGPU, + m_internalData->m_bodyInfoBufferGPU, + m_internalData->m_contactCGPU, + 0, + nContactOut ); + + adl::DeviceUtils::waitForCompletion( m_internalData->m_ddcl ); + } + { + BT_PROFILE("read body velocities back to CPU"); + //read body updated linear/angular velocities back to CPU + m_internalData->m_pBufRBodiesGPU->read( + m_internalData->m_pBufRBodiesCPU->m_ptr,numOfConvexRBodies); + adl::DeviceUtils::waitForCompletion( m_internalData->m_ddcl ); + } + + + } + +#if 0 + if( !m_useGPUPipeline ) + { // CPU + BT_PROFILE("CPU solve"); + { + BT_PROFILE("CPU reorderConvertToConstraints"); + + SOLVER_CLASS::reorderConvertToConstraints( solver, m_bodyBuffer, m_bodyInfoBufferCPU, (Buffer*)m_contactBuffer, + contactC, frictionC, m_numContacts, csCfg ); + } + { + BT_PROFILE("CPU solveContactConstraint"); + + solver->m_nIterations = 4; + SOLVER_CLASS::solveContactConstraint( solver, m_bodyBuffer, m_bodyInfoBufferCPU, contactC, 0, m_numContacts ); + } + } + else + { + BT_PROFILE("GPU solve"); + { // GPU using host buffers + { + BT_PROFILE("GPU reorderConvertToConstraints"); + + Solver::reorderConvertToConstraints( m_solver, m_bodyBuffer, m_bodyInfoBufferCPU, (Buffer*)m_contactBuffer, + contactC, frictionC, m_numContacts, csCfg ); + } + timerEnd(); + + timerStart(0); + //for(int iter=0; iter<4; iter++) + { + BT_PROFILE("GPU solveContactConstraint"); + + Solver::solveContactConstraint( m_solver, m_bodyBuffer, m_bodyInfoBufferCPU, contactC, frictionC, m_numContacts ); + } + DeviceUtils::waitForCompletion( m_device ); + } + } + timerEnd(); +#endif + + + } + + //if we ran the solver, it will overwrite the batchIdx so we cannot write back the results + //try to make it work by writing velocity back to rigid body + + if (useSolver) + { + + BT_PROFILE("writing velocity back to btRigidBody"); + + for ( int i=0; im_pProxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)pair->m_pProxy1->m_clientObject; + + int bodyIndex0 = colObj0->getCompanionId(); + int bodyIndex1 = colObj1->getCompanionId(); + + RigidBodyBase::Body* bA = &m_internalData->m_pBufRBodiesCPU->m_ptr[bodyIndex0]; + RigidBodyBase::Body* bB = &m_internalData->m_pBufRBodiesCPU->m_ptr[bodyIndex1]; + btRigidBody* bodyA = btRigidBody::upcast(colObj0); + if (bodyA && !bodyA->isStaticOrKinematicObject()) + { + bodyA->setLinearVelocity(btVector3( + bA->m_linVel.x, + bA->m_linVel.y, + bA->m_linVel.z)); + + bodyA->setAngularVelocity(btVector3( + bA->m_angVel.x, + bA->m_angVel.y, + bA->m_angVel.z)); + } + btRigidBody* bodyB = btRigidBody::upcast(colObj1); + if (bodyB && !bodyB->isStaticOrKinematicObject()) + { + bodyB->setLinearVelocity(btVector3( + bB->m_linVel.x, + bB->m_linVel.y, + bB->m_linVel.z)); + bodyB->setAngularVelocity(btVector3( + bB->m_angVel.x, + bB->m_angVel.y, + bB->m_angVel.z)); + + } + + + + + } + } else + { + BT_PROFILE("copy Contact4 to btPersistentManifold"); + // Now we got the narrowphase info from GPU and need to update rigid bodies with the info and go back to the original pipeline in Bullet physics. + for ( int i = 0; i < nContactOut; i++ ) + { + Contact4 contact = (*m_internalData->m_pBufContactOutCPU)[i]; + + int idxBodyA = contact.m_bodyAPtr; + int idxBodyB = contact.m_bodyBPtr; + + btAssert(contact.m_batchIdx>=0); + btAssert(contact.m_batchIdxm_pProxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)pair->m_pProxy1->m_clientObject; + + if (!pair->m_algorithm) + { + pair->m_algorithm = findAlgorithm(colObj0,colObj1,0); + } + + btManifoldResult contactPointResult(colObj0, colObj1); + + + CustomConvexConvexPairCollision* pairAlgo = (CustomConvexConvexPairCollision*) pair->m_algorithm; + + if (!pairAlgo->getManifoldPtr()) + { + pairAlgo->createManifoldPtr(colObj0,colObj1,dispatchInfo); + } + + contactPointResult.setPersistentManifold(pairAlgo->getManifoldPtr()); + + contactPointResult.getPersistentManifold()->refreshContactPoints(colObj0->getWorldTransform(),colObj1->getWorldTransform()); + + const btTransform& transA = colObj0->getWorldTransform(); + const btTransform& transB = colObj1->getWorldTransform(); + + int numPoints = contact.getNPoints(); + + for ( int k=0; k < numPoints; k++ ) + { + btVector3 normalOnBInWorld( + contact.m_worldNormal.x, + contact.m_worldNormal.y, + contact.m_worldNormal.z); + btVector3 pointInWorldOnB( + contact.m_worldPos[k].x, + contact.m_worldPos[k].y, + contact.m_worldPos[k].z); + + btScalar depth = contact.m_worldPos[k].w; + + if (depth<0) + { + const btVector3 deltaC = transB.getOrigin() - transA.getOrigin(); + + normalOnBInWorld.normalize(); + + if((deltaC.dot(normalOnBInWorld))>0.0f) + { + normalOnBInWorld= -normalOnBInWorld; + + contactPointResult.addContactPoint(normalOnBInWorld, pointInWorldOnB, depth); + } + else + { + contactPointResult.addContactPoint(normalOnBInWorld, pointInWorldOnB-normalOnBInWorld*depth, depth); + } + } + } + } + } + } + } +#endif //CL_PLATFORM_AMD + } + +} + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomCollisionDispatcher.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomCollisionDispatcher.h new file mode 100644 index 0000000..315a4ba --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomCollisionDispatcher.h @@ -0,0 +1,70 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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 CUSTOM_COLLISION_DISPATCHER_H +#define CUSTOM_COLLISION_DISPATCHER_H + + +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" + + +#define MAX_CONVEX_BODIES_CL 64*1024 +#define MAX_PAIRS_PER_BODY_CL 32 +#define MAX_CONVEX_SHAPES_CL 8192 +#define MAX_BROADPHASE_COLLISION_CL (MAX_CONVEX_BODIES_CL*MAX_PAIRS_PER_BODY_CL) + + + +struct CustomDispatchData; + +#ifdef CL_PLATFORM_AMD +#ifdef __APPLE__ + #ifdef USE_MINICL + #include + #else + #include + #endif +#else //__APPLE__ + #ifdef USE_MINICL + #include + #else + #include + #endif +#endif //__APPLE__ +#endif + +class CustomCollisionDispatcher : public btCollisionDispatcher +{ +public: + CustomCollisionDispatcher (btCollisionConfiguration* collisionConfiguration +#ifdef CL_PLATFORM_AMD + , cl_context context = NULL,cl_device_id device = NULL,cl_command_queue queue = NULL +#endif //CL_PLATFORM_AMD + ); + + virtual ~CustomCollisionDispatcher(void); + +protected: + + CustomDispatchData* m_internalData; + + btBroadphasePair* GetPair(btBroadphasePairArray& pairArray, int idxBodyA, int idxBodyB); + +public: + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher); +}; + +#endif //CUSTOM_COLLISION_DISPATCHER_H diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomConvexPairCollision.cpp b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomConvexPairCollision.cpp new file mode 100644 index 0000000..d0fd32c --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomConvexPairCollision.cpp @@ -0,0 +1,409 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + +#include "CustomConvexPairCollision.h" +#include "ConvexHeightFieldShape.h" +#include "CustomConvexShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "Stubs/AdlContact4.h" +#include "Stubs/AdlTransform.h" + + +CustomConvexConvexPairCollision::CustomConvexConvexPairCollision(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold) +:btConvexConvexAlgorithm(mf,ci,body0,body1,simplexSolver,pdSolver,numPerturbationIterations, minimumPointsPerturbationThreshold) +{ + +} + +CustomConvexConvexPairCollision::~CustomConvexConvexPairCollision() +{ + +} + + +#include + +template +T atomAdd(const T* ptr, int value) +{ + return (T)InterlockedExchangeAdd((LONG*)ptr, value); +} + + + +#define PARALLEL_SUM(v, n) for(int j=1; j v[i+offset].y)? v[i]: v[i+offset]; } +#define REDUCE_MIN(v, n) {int i=0;\ + for(int offset=0; offset a[ie].x )? a[0].x: a[ie].x; + a[0].y = (a[0].y > a[ie].y )? a[0].y: a[ie].y; + a[0].z = (a[0].z > a[ie].z )? a[0].z: a[ie].z; + a[0].w = (a[0].w > a[ie].w )? a[0].w: a[ie].w; + } + + idx[0] = (int)a[0].x & 0xff; + idx[1] = (int)a[0].y & 0xff; + idx[2] = (int)a[0].z & 0xff; + idx[3] = (int)a[0].w & 0xff; + } + } + + { + float2 h[64]; + PARALLEL_DO( h[ie] = make_float2((float)ie, p[ie].w), nPoints ); + REDUCE_MIN( h, nPoints ); + max00 = h[0]; + } + } + + contactIdx[0] = idx[0]; + contactIdx[1] = idx[1]; + contactIdx[2] = idx[2]; + contactIdx[3] = idx[3]; + +// if( max00.y < 0.0f ) +// contactIdx[0] = (int)max00.x; + + std::sort( contactIdx, contactIdx+4 ); + + return 4; + } +} + +#undef PARALLEL_SUM +#undef PARALLEL_DO +#undef REDUCE_MAX +#undef REDUCE_MIX + +int collideStraight(const ConvexHeightField* shapeA,const ConvexHeightField* shapeB, + const float4& bodyApos, Quaternion& bodyAquat,const float4& bodyBpos,const Quaternion& bodyBquat, + ContactPoint4* contactsOut, int& numContacts, int contactCapacity, + float collisionMargin ) +{ +// Stopwatch sw; + + Transform trA; + trA = trSetTransform(bodyApos,bodyAquat); + Transform trB; + trB = trSetTransform(bodyBpos, bodyBquat); + + Transform B2A; + { + Transform invTrA = trInvert( trA ); + B2A = trMul( invTrA, trB ); + } + + int nContacts = 0; + { // testB against A + float4 p[ConvexHeightField::HEIGHT_RES*ConvexHeightField::HEIGHT_RES*6]; + int nHits = 0; + + const float4* pInB = shapeB->getSamplePoints(); + + float4 baInB = qtInvRotate( bodyBquat, bodyApos - bodyBpos ); + if( shapeA->m_type == CollisionShape::SHAPE_HEIGHT_FIELD ) + baInB = make_float4(0,0,0,0); + +// sw.start(); + for(int iface=0; iface<6; iface++) + { + Aabb aabb = shapeB->m_faceAabbs[iface]; + + aabb.transform( B2A.m_translation, B2A.m_rotation ); + + if( !shapeA->m_aabb.overlaps( aabb ) ) continue; + + for(int ip=0; ipm_aabb.overlaps( pInA ) ) + { +// Stopwatch sw1; +// sw1.start(); + float dist = shapeA->queryDistance( pInA ); +// sw1.stop(); +// m_times[TIME_SAMPLE] += sw1.getMs(); + + if( dist < collisionMargin ) + { + p[nHits] = make_float4(pInA.x, pInA.y, pInA.z, dist); + nHits++; + } + } + } + } +// sw.stop(); +// m_times[TIME_TEST] += sw.getMs(); + +// sw.start(); + if( nHits ) + { + float4 ab = bodyBpos - bodyApos; + ab = qtInvRotate( bodyAquat, ab ); + if( shapeA->m_type == CollisionShape::SHAPE_HEIGHT_FIELD ) + { + //todo. sample normal from height field but just fake here + ab = make_float4(0,1,0,0); + } + + int cIdx[4]; + float4 center; + + nContacts = extractManifold( p, nHits, ab, center, cIdx ); + + float4 contactNormal; + { + shapeA->queryDistanceWithNormal( center, contactNormal ); + contactNormal = normalize3( contactNormal ); + +// u32 cmp = u8vCompress( contactNormal ); +// contactNormal = make_float4( u8vGetX(cmp), u8vGetY(cmp), u8vGetZ(cmp), 0 ); + } + + int writeIdx = atomAdd( &numContacts, 1 ); + if( writeIdx+1 < contactCapacity ) + { + ContactPoint4& c = contactsOut[writeIdx]; + nContacts = min2( nContacts, 4 ); + for(int i=0; igetNewManifold(body0,body1); + m_ownManifold = true; +} + + +void CustomConvexConvexPairCollision::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ +#if 1 + if (!m_manifoldPtr) + { + //swapped? + m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1); + m_ownManifold = true; + } + resultOut->setPersistentManifold(m_manifoldPtr); + + + CustomConvexShape* convex0 = (CustomConvexShape*)body0->getCollisionShape(); + CustomConvexShape* convex1 = (CustomConvexShape*)body1->getCollisionShape(); + + + float4 bodyApos; + float4 bodyBpos; + Quaternion bodyAquat; + Quaternion bodyBquat; + + const btTransform& transA = body0->getWorldTransform(); + const btTransform& transB = body1->getWorldTransform(); + + const btVector3& pA = body0->getWorldTransform().getOrigin(); + const btVector3& pB = body1->getWorldTransform().getOrigin(); + + btQuaternion qA = body0->getWorldTransform().getRotation(); + btQuaternion qB = body1->getWorldTransform().getRotation(); + + bodyApos.x = pA.getX(); + bodyApos.y = pA.getY(); + bodyApos.z = pA.getZ(); + bodyApos.w = 0.f; + + bodyBpos.x = pB.getX(); + bodyBpos.y = pB.getY(); + bodyBpos.z = pB.getZ(); + bodyBpos.w = 0.f; + + bodyAquat.x = qA.getX(); + bodyAquat.y = qA.getY(); + bodyAquat.z = qA.getZ(); + bodyAquat.w = qA.getW(); + + bodyBquat.x = qB.getX(); + bodyBquat.y = qB.getY(); + bodyBquat.z = qB.getZ(); + bodyBquat.w = qB.getW(); + + +#define CAPACITY_CONTACTS 4 + + ContactPoint4 contactsOut[CAPACITY_CONTACTS]; + int freeContactIndex = 0; + int contactCapacity = CAPACITY_CONTACTS; + float collisionMargin = 0.001f; + + m_manifoldPtr->refreshContactPoints(body0->getWorldTransform(),body1->getWorldTransform()); + + collideStraight(convex0->m_ConvexHeightField,convex1->m_ConvexHeightField, + bodyApos, bodyAquat,bodyBpos,bodyBquat, + contactsOut, freeContactIndex, contactCapacity, + collisionMargin ); + collideStraight(convex1->m_ConvexHeightField,convex0->m_ConvexHeightField, + bodyBpos, bodyBquat,bodyApos,bodyAquat, + contactsOut, freeContactIndex, contactCapacity, + collisionMargin ); + + //copy points into manifold + //refresh manifold + + btAssert(freeContactIndex<3); + for (int j=0;j0.0f) + { + normalOnBInWorld= -normalOnBInWorld; + } + normalOnBInWorld.normalize(); + if (j) + { + resultOut->addContactPoint(normalOnBInWorld, pointInWorldOnB, depth); + } else + { + resultOut->addContactPoint(normalOnBInWorld, pointInWorldOnB-normalOnBInWorld*depth, depth); + } + } + } + } +#else + btConvexConvexAlgorithm::processCollision(body0,body1,dispatchInfo,resultOut); +#endif +} + + + +CustomConvexConvexPairCollision::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) +:btConvexConvexAlgorithm::CreateFunc(simplexSolver,pdSolver) +{ +} + +CustomConvexConvexPairCollision::CreateFunc::~CreateFunc() +{ + +} \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomConvexPairCollision.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomConvexPairCollision.h new file mode 100644 index 0000000..bd3a085 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomConvexPairCollision.h @@ -0,0 +1,56 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + +#ifndef CUSTOM_CONVEX_CONVEX_PAIR_COLLISION_H +#define CUSTOM_CONVEX_CONVEX_PAIR_COLLISION_H + + +#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" + +class CustomConvexConvexPairCollision : public btConvexConvexAlgorithm +{ + public: + + CustomConvexConvexPairCollision(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold); + virtual ~CustomConvexConvexPairCollision(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btPersistentManifold* getManifoldPtr() + { + return m_manifoldPtr; + } + + void createManifoldPtr(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo); + + struct CreateFunc :public btConvexConvexAlgorithm::CreateFunc + { + + CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); + + virtual ~CreateFunc(); + + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(CustomConvexConvexPairCollision)); + return new(mem) CustomConvexConvexPairCollision(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); + } + }; + + +}; + + +#endif //CUSTOM_CONVEX_CONVEX_PAIR_COLLISION_H diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomConvexShape.cpp b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomConvexShape.cpp new file mode 100644 index 0000000..de7d74d --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomConvexShape.cpp @@ -0,0 +1,45 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + +#include "CustomConvexShape.h" +#include "ConvexHeightFieldShape.h" +#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h" + + +CustomConvexShape::CustomConvexShape(const btScalar* points,int numPoints, int stride) +:btConvexHullShape(points,numPoints,stride), +m_acceleratedCompanionShapeIndex(-1) +{ + m_shapeType = CUSTOM_POLYHEDRAL_SHAPE_TYPE; + + initializePolyhedralFeatures(); + int numFaces= m_polyhedron->m_faces.size(); + float4* eqn = new float4[numFaces]; + for (int i=0;im_faces[i].m_plane[0]; + eqn[i].y = m_polyhedron->m_faces[i].m_plane[1]; + eqn[i].z = m_polyhedron->m_faces[i].m_plane[2]; + eqn[i].w = m_polyhedron->m_faces[i].m_plane[3]; + } + + m_ConvexHeightField = new ConvexHeightField(eqn,numFaces); + +} + +CustomConvexShape::~CustomConvexShape() +{ + delete m_ConvexHeightField; +} \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomConvexShape.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomConvexShape.h new file mode 100644 index 0000000..a514c94 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/CustomConvexShape.h @@ -0,0 +1,35 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + +#ifndef CUSTOM_CONVEX_SHAPE_H +#define CUSTOM_CONVEX_SHAPE_H + +#include "BulletCollision/CollisionShapes/btConvexHullShape.h" + +class CustomConvexShape : public btConvexHullShape +{ + public: + + class ConvexHeightField* m_ConvexHeightField; + + int m_acceleratedCompanionShapeIndex; + + CustomConvexShape(const btScalar* points,int numPoints,int stride); + virtual ~CustomConvexShape(); + +}; + +#endif //CUSTOM_CONVEX_SHAPE_H + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlAabb.cpp b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlAabb.cpp new file mode 100644 index 0000000..e69de29 diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlAabb.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlAabb.h new file mode 100644 index 0000000..0c67090 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlAabb.h @@ -0,0 +1,230 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + +#ifndef AABB_H +#define AABB_H + +#include "Stubs/AdlMath.h" +#include "Stubs/AdlQuaternion.h" + +enum AdlCollisionShapeTypes +{ + ADL_SHAPE_SPHERE=2, + ADL_SHAPE_HEIGHT_FIELD, + SHAPE_CONVEX_HEIGHT_FIELD, +}; + +_MEM_CLASSALIGN16 +struct Aabb +{ + public: + _MEM_ALIGNED_ALLOCATOR16; + + __inline + void setEmpty(); + __inline + void includeVolume( const Aabb& aabb ); + __inline + void includePoint( const float4& p ); + __inline + bool overlaps( const float4& p ) const; + __inline + bool overlaps( const Aabb& aabb ) const; + __inline + float4 center() const; + __inline + int getMajorAxis() const; + __inline + float4 getExtent() const; + __inline + void expandBy( const float4& r ); + + __inline + static bool overlaps( const Aabb& a, const Aabb& b ); + + __inline + bool intersect(const float4* from, const float4* to, const float4* invRay) const; + + __inline + void transform(const float4& translation, const Quaternion& quat); + + __inline + void transform(const float4& translation, const Matrix3x3& rot); + + public: + float4 m_max; + float4 m_min; +}; + +void Aabb::setEmpty() +{ + m_max = make_float4( -FLT_MAX ); + m_min = make_float4( FLT_MAX ); +} + +void Aabb::includeVolume(const Aabb& aabb) +{ + m_max.x = max2( m_max.x, aabb.m_max.x ); + m_min.x = min2( m_min.x, aabb.m_min.x ); + + m_max.y = max2( m_max.y, aabb.m_max.y ); + m_min.y = min2( m_min.y, aabb.m_min.y ); + + m_max.z = max2( m_max.z, aabb.m_max.z ); + m_min.z = min2( m_min.z, aabb.m_min.z ); +} + +void Aabb::includePoint( const float4& p ) +{ + m_max.x = max2( m_max.x, p.x ); + m_min.x = min2( m_min.x, p.x ); + + m_max.y = max2( m_max.y, p.y ); + m_min.y = min2( m_min.y, p.y ); + + m_max.z = max2( m_max.z, p.z ); + m_min.z = min2( m_min.z, p.z ); +} + +bool Aabb::overlaps( const float4& p ) const +{ + float4 dx = m_max-p; + float4 dm = p-m_min; + + return (dx.x >= 0 && dx.y >= 0 && dx.z >= 0) + && (dm.x >= 0 && dm.y >= 0 && dm.z >= 0); +} + +bool Aabb::overlaps( const Aabb& in ) const +{ +/* + if( m_max.x < in.m_min.x || m_min.x > in.m_max.x ) return false; + if( m_max.y < in.m_min.y || m_min.y > in.m_max.y ) return false; + if( m_max.z < in.m_min.z || m_min.z > in.m_max.z ) return false; + + return true; +*/ + return overlaps( *this, in ); +} + +bool Aabb::overlaps( const Aabb& a, const Aabb& b ) +{ + if( a.m_max.x < b.m_min.x || a.m_min.x > b.m_max.x ) return false; + if( a.m_max.y < b.m_min.y || a.m_min.y > b.m_max.y ) return false; + if( a.m_max.z < b.m_min.z || a.m_min.z > b.m_max.z ) return false; + + return true; +} + +float4 Aabb::center() const +{ + return 0.5f*(m_max+m_min); +} + +int Aabb::getMajorAxis() const +{ + float4 extent = getExtent(); + + int majorAxis = 0; + if( extent.s[1] > extent.s[0] ) + majorAxis = 1; + if( extent.s[2] > extent.s[majorAxis] ) + majorAxis = 2; + + return majorAxis; +} + +float4 Aabb::getExtent() const +{ + return m_max-m_min; +} + +void Aabb::expandBy( const float4& r ) +{ + m_max += r; + m_min -= r; +} + +bool Aabb::intersect(const float4* from, const float4* to, const float4* invRay) const +{ + float4 dFar; + dFar = (m_max - *from); + dFar *= *invRay; + float4 dNear; + dNear = (m_min - *from); + dNear *= *invRay; + + float4 tFar; + tFar = max2(dFar, dNear); + float4 tNear; + tNear = min2(dFar, dNear); + + float farf[] = { tFar.x, tFar.y, tFar.z }; + + float nearf[] = { tNear.x, tNear.y, tNear.z }; + + float minFar = min2(farf[0], min2(farf[1], farf[2])); + float maxNear = max2(nearf[0], max2(nearf[1], nearf[2])); + + minFar = min2(1.0f, minFar ); + maxNear = max2(0.0f, maxNear); + + return (minFar >= maxNear); +} + +void Aabb::transform(const float4& translation, const Matrix3x3& m) +{ + float4 c = center(); + + Aabb& ans = *this; + + float4 e[] = { m.m_row[0]*m_min, m.m_row[1]*m_min, m.m_row[2]*m_min }; + float4 f[] = { m.m_row[0]*m_max, m.m_row[1]*m_max, m.m_row[2]*m_max }; + ans.m_max = ans.m_min = translation; + + { int j=0; + float4 mi = make_float4( min2( e[j].x, f[j].x ), min2( e[j].y, f[j].y ), min2( e[j].z, f[j].z ) ); + float4 ma = make_float4( max2( e[j].x, f[j].x ), max2( e[j].y, f[j].y ), max2( e[j].z, f[j].z ) ); + + ans.m_min.x += mi.x+mi.y+mi.z; + ans.m_max.x += ma.x+ma.y+ma.z; + } + + { int j=1; + float4 mi = make_float4( min2( e[j].x, f[j].x ), min2( e[j].y, f[j].y ), min2( e[j].z, f[j].z ) ); + float4 ma = make_float4( max2( e[j].x, f[j].x ), max2( e[j].y, f[j].y ), max2( e[j].z, f[j].z ) ); + + ans.m_min.y += mi.x+mi.y+mi.z; + ans.m_max.y += ma.x+ma.y+ma.z; + } + + { int j=2; + float4 mi = make_float4( min2( e[j].x, f[j].x ), min2( e[j].y, f[j].y ), min2( e[j].z, f[j].z ) ); + float4 ma = make_float4( max2( e[j].x, f[j].x ), max2( e[j].y, f[j].y ), max2( e[j].z, f[j].z ) ); + + ans.m_min.z += mi.x+mi.y+mi.z; + ans.m_max.z += ma.x+ma.y+ma.z; + } +} + +void Aabb::transform(const float4& translation, const Quaternion& quat) +{ + Matrix3x3 m = qtGetRotationMatrix( quat ); + + transform( translation, m ); +} + +#endif + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlArray.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlArray.h new file mode 100644 index 0000000..e7fe5e3 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlArray.h @@ -0,0 +1,212 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#ifndef ARRAY_H +#define ARRAY_H + +#include +#include +#include +#include + + +template +class Array +{ + public: + __inline + Array(); + __inline + Array(int size); + __inline + ~Array(); + __inline + T& operator[] (int idx); + __inline + const T& operator[] (int idx) const; + __inline + void pushBack(const T& elem); + __inline + void popBack(); + __inline + void clear(); + __inline + void setSize(int size); + __inline + int getSize() const; + __inline + T* begin(); + __inline + const T* begin() const; + __inline + int indexOf(const T& data) const; + __inline + void removeAt(int idx); + __inline + T& expandOne(); + + private: + Array(const Array& a){} + + private: + enum + { + DEFAULT_SIZE = 128, + INCREASE_SIZE = 128, + }; + + T* m_data; + int m_size; + int m_capacity; +}; + +template +Array::Array() +{ + m_size = 0; + m_capacity = DEFAULT_SIZE; +// m_data = new T[ m_capacity ]; + m_data = (T*)_aligned_malloc(sizeof(T)*m_capacity, 16); + for(int i=0; i +Array::Array(int size) +{ + m_size = size; + m_capacity = size; +// m_data = new T[ m_capacity ]; + m_data = (T*)_aligned_malloc(sizeof(T)*m_capacity, 16); + for(int i=0; i +Array::~Array() +{ + if( m_data ) + { +// delete [] m_data; + _aligned_free( m_data ); + m_data = NULL; + } +} + +template +T& Array::operator[](int idx) +{ + CLASSERT(idx +const T& Array::operator[](int idx) const +{ + CLASSERT(idx +void Array::pushBack(const T& elem) +{ + if( m_size == m_capacity ) + { + int oldCap = m_capacity; + m_capacity += INCREASE_SIZE; +// T* s = new T[m_capacity]; + T* s = (T*)_aligned_malloc(sizeof(T)*m_capacity, 16); + memcpy( s, m_data, sizeof(T)*oldCap ); +// delete [] m_data; + _aligned_free( m_data ); + m_data = s; + } + m_data[ m_size++ ] = elem; +} + +template +void Array::popBack() +{ + CLASSERT( m_size>0 ); + m_size--; +} + +template +void Array::clear() +{ + m_size = 0; +} + +template +void Array::setSize(int size) +{ + if( size > m_capacity ) + { + int oldCap = m_capacity; + m_capacity = size; +// T* s = new T[m_capacity]; + T* s = (T*)_aligned_malloc(sizeof(T)*m_capacity, 16); + for(int i=0; i +int Array::getSize() const +{ + return m_size; +} + +template +const T* Array::begin() const +{ + return m_data; +} + +template +T* Array::begin() +{ + return m_data; +} + +template +int Array::indexOf(const T& data) const +{ + for(int i=0; i +void Array::removeAt(int idx) +{ + CLASSERT(idx +T& Array::expandOne() +{ + setSize( m_size+1 ); + return m_data[ m_size-1 ]; +} + +#endif + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlCollideUtils.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlCollideUtils.h new file mode 100644 index 0000000..84d6583 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlCollideUtils.h @@ -0,0 +1,111 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#ifndef COLLIDE_UTILS_H +#define COLLIDE_UTILS_H + +#include "Stubs/AdlMath.h" + + +class CollideUtils +{ + public: + template + static bool collide(const float4& a, const float4& b, const float4& c, const float4& p, float4& normalOut, float margin = 0.f); + + __inline + static float castRay(const float4& v0, const float4& v1, const float4& v2, + const float4& rayFrom, const float4& rayTo, float margin = 0.0f, float4* bCrdOut = NULL); + +}; + + +template +bool CollideUtils::collide(const float4& a, const float4& b, const float4& c, const float4& p, float4& normalOut, float margin) +{ + float4 ab, bc, ca; + ab = b-a; + bc = c-b; + ca = a-c; + + float4 ap, bp, cp; + ap = p-a; + bp = p-b; + cp = p-c; + + float4 n; + n = cross3(ab, -1.f*ca); + + float4 abp = cross3( ab, ap ); + float4 bcp = cross3( bc, bp ); + float4 cap = cross3( ca, cp ); + + float s0 = dot3F4(n,abp); + float s1 = dot3F4(n,bcp); + float s2 = dot3F4(n,cap); + +// if(( s0<0.f && s1<0.f && s2<0.f ) || ( s0>0.f && s1>0.f && s2>0.f )) + if(( s0-margin && s1>-margin && s2>-margin )) + { + n = normalize3( n ); + n.w = dot3F4(n,ap); + + normalOut = (FLIPSIGN)? -n : n; + return true; + } + + return false; +} + +__inline +float CollideUtils::castRay(const float4& v0, const float4& v1, const float4& v2, + const float4& rayFrom, const float4& rayTo, float margin, float4* bCrdOut) +{ + float t, v, w; + float4 ab; ab = v1 - v0; + float4 ac; ac = v2 - v0; + float4 qp; qp = rayFrom - rayTo; + float4 normal = cross3( ab, ac ); + float d = dot3F4( qp, normal ); + float odd = 1.f/d; + float4 ap; ap = rayFrom - v0; + t = dot3F4( ap, normal ); + t *= odd; +// if( t < 0.f || t > 1.f ) return -1; + + float4 e = cross3( qp, ap ); + v = dot3F4( ac, e ); + v *= odd; + if( v < -margin || v > 1.f+margin ) return -1; + w = -dot3F4( ab, e ); + w *= odd; +// if( w < 0.f || w > 1.f ) return -1; + if( w < -margin || w > 1.f+margin ) return -1; + + float u = 1.f-v-w; + if( u < -margin || u > 1.f+margin ) return -1; + + if( bCrdOut ) + { + bCrdOut->x = u; + bCrdOut->y = v; + bCrdOut->z = w; + } + return t; +} + +#endif + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlCollisionShape.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlCollisionShape.h new file mode 100644 index 0000000..834c88c --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlCollisionShape.h @@ -0,0 +1,49 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#ifndef COLLISION_SHAPE_H +#define COLLISION_SHAPE_H + +#include "Stubs/AdlMath.h" +#include "Stubs/AdlAabb.h" + + +_MEM_CLASSALIGN16 +class CollisionShape +{ + public: + _MEM_ALIGNED_ALLOCATOR16; + + enum Type + { + SHAPE_HEIGHT_FIELD, + SHAPE_CONVEX_HEIGHT_FIELD, + SHAPE_PLANE, + MAX_NUM_SHAPE_TYPES, + }; + + CollisionShape( Type type, float collisionMargin = 0.0025f ) : m_type( type ){ m_collisionMargin = collisionMargin; } + virtual ~CollisionShape(){} + virtual float queryDistance(const float4& p) const = 0; + virtual bool queryDistanceWithNormal(const float4& p, float4& normalOut) const = 0; + + public: + Type m_type; + Aabb m_aabb; + float m_collisionMargin; +}; + +#endif diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlConstraint4.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlConstraint4.h new file mode 100644 index 0000000..8f50781 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlConstraint4.h @@ -0,0 +1,49 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#ifndef ADL_CONSTRAINT4_H +#define ADL_CONSTRAINT4_H + + + +struct Constraint4 + { + _MEM_ALIGNED_ALLOCATOR16; + + float4 m_linear; + float4 m_worldPos[4]; + float4 m_center; // friction + float m_jacCoeffInv[4]; + float m_b[4]; + float m_appliedRambdaDt[4]; + + float m_fJacCoeffInv[2]; // friction + float m_fAppliedRambdaDt[2]; // friction + + u32 m_bodyA; + u32 m_bodyB; + + u32 m_batchIdx; + u32 m_paddings[1]; + + __inline + void setFrictionCoeff(float value) { m_linear.w = value; } + __inline + float getFrictionCoeff() const { return m_linear.w; } + }; + +#endif //ADL_CONSTRAINT4_H + \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlContact4.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlContact4.h new file mode 100644 index 0000000..29e36ad --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlContact4.h @@ -0,0 +1,102 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#ifndef ADL_CONTACT4_H +#define ADL_CONTACT4_H + +#ifdef CL_PLATFORM_AMD +#include "AdlConstraint4.h" +#include "Adl/Adl.h" + +typedef adl::Buffer* SolverData; +#else +typedef void* SolverData; +#endif + +typedef void* ShapeDataType; + + +struct Contact4 +{ + _MEM_ALIGNED_ALLOCATOR16; + + float4 m_worldPos[4]; + float4 m_worldNormal; +// float m_restituitionCoeff; +// float m_frictionCoeff; + u16 m_restituitionCoeffCmp; + u16 m_frictionCoeffCmp; + int m_batchIdx; + + u32 m_bodyAPtr; + u32 m_bodyBPtr; + + // todo. make it safer + int& getBatchIdx() { return m_batchIdx; } + float getRestituitionCoeff() const { return ((float)m_restituitionCoeffCmp/(float)0xffff); } + void setRestituitionCoeff( float c ) { ADLASSERT( c >= 0.f && c <= 1.f ); m_restituitionCoeffCmp = (u16)(c*0xffff); } + float getFrictionCoeff() const { return ((float)m_frictionCoeffCmp/(float)0xffff); } + void setFrictionCoeff( float c ) { ADLASSERT( c >= 0.f && c <= 1.f ); m_frictionCoeffCmp = (u16)(c*0xffff); } + + float& getNPoints() { return m_worldNormal.w; } + float getNPoints() const { return m_worldNormal.w; } + + float getPenetration(int idx) const { return m_worldPos[idx].w; } + + bool isInvalid() const { return ((u32)m_bodyAPtr+(u32)m_bodyBPtr) == 0; } +}; + +struct ContactPoint4 + { + float4 m_worldPos[4]; + union + { + float4 m_worldNormal; + + struct Data + { + int m_padding[3]; + float m_nPoints; // for cl + }m_data; + + }; + float m_restituitionCoeff; + float m_frictionCoeff; +// int m_nPoints; +// int m_padding0; + + void* m_bodyAPtr; + void* m_bodyBPtr; +// int m_padding1; +// int m_padding2; + + float& getNPoints() { return m_data.m_nPoints; } + float getNPoints() const { return m_data.m_nPoints; } + + float getPenetration(int idx) const { return m_worldPos[idx].w; } + +// __inline +// void load(int idx, const ContactPoint& src); +// __inline +// void store(int idx, ContactPoint& dst) const; + + bool isInvalid() const { return ((u32)m_bodyAPtr+(u32)m_bodyBPtr) == 0; } + + }; + + +#endif //ADL_CONTACT4_H + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlError.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlError.h new file mode 100644 index 0000000..e1f9ad8 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlError.h @@ -0,0 +1,80 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#ifndef CL_ERROR_H +#define CL_ERROR_H + +#ifdef DX11RENDER +#include +#endif + +#ifdef _DEBUG + #include + #define CLASSERT(x) if(!(x)){__debugbreak(); } + #define ADLASSERT(x) if(!(x)){__debugbreak(); } +#else + #define CLASSERT(x) if(x){} + #define ADLASSERT(x) if(x){} + +#endif + + + + +#ifdef _DEBUG + #define COMPILE_TIME_ASSERT(x) {int compileTimeAssertFailed[x]; compileTimeAssertFailed[0];} +#else + #define COMPILE_TIME_ASSERT(x) +#endif + +#ifdef _DEBUG + #include + #include + __inline + void debugPrintf(const char *fmt, ...) + { + va_list arg; + va_start(arg, fmt); +#ifdef DX11RENDER + char buf[256]; + vsprintf_s( buf, 256, fmt, arg ); +#ifdef UNICODE + WCHAR wbuf[256]; + int sizeWide = MultiByteToWideChar(0,0,buf,-1,wbuf,0); + MultiByteToWideChar(0,0,buf,-1,wbuf,sizeWide); + +// swprintf_s( wbuf, 256, L"%s", buf ); + OutputDebugString( wbuf ); +#else + OutputDebugString( buf ); +#endif +#else + vprintf(fmt, arg); +#endif + va_end(arg); + } +#else + __inline + void debugPrintf(const char *fmt, ...) + { + } +#endif + + +#define WARN(msg) debugPrintf("WARNING: %s\n", msg); + +#endif + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlMath.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlMath.h new file mode 100644 index 0000000..a724220 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlMath.h @@ -0,0 +1,216 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#ifndef CL_MATH_H +#define CL_MATH_H + +#include +#include +#include +#include + + +#include "AdlError.h" +#include +#define pxSort std::sort + +#define PI 3.14159265358979323846f +#define NEXTMULTIPLEOF(num, alignment) (((num)/(alignment) + (((num)%(alignment)==0)?0:1))*(alignment)) + + +#define _MEM_CLASSALIGN16 __declspec(align(16)) +#define _MEM_ALIGNED_ALLOCATOR16 void* operator new(size_t size) { return _aligned_malloc( size, 16 ); } \ + void operator delete(void *p) { _aligned_free( p ); } \ + void* operator new[](size_t size) { return _aligned_malloc( size, 16 ); } \ + void operator delete[](void *p) { _aligned_free( p ); } \ + void* operator new(size_t size, void* p) { return p; } \ + void operator delete(void *p, void* pp) {} + + + +template +T nextPowerOf2(T n) +{ + n -= 1; + for(int i=0; i>i); + return n+1; +} + + +_MEM_CLASSALIGN16 +struct float4 +{ + _MEM_ALIGNED_ALLOCATOR16; + union + { + struct + { + float x,y,z,w; + }; + struct + { + float s[4]; + }; + __m128 m_quad; + }; +}; + +__forceinline +unsigned int isZero(const float4& a) +{ + return (a.x == 0.f) & (a.y == 0.f) & (a.z == 0.f) & (a.w == 0.f); +} + +_MEM_CLASSALIGN16 +struct int4 +{ + _MEM_ALIGNED_ALLOCATOR16; + union + { + struct + { + int x,y,z,w; + }; + struct + { + int s[4]; + }; + }; +}; + +struct int2 +{ + union + { + struct + { + int x,y; + }; + struct + { + int s[2]; + }; + }; +}; + +struct float2 +{ + union + { + struct + { + float x,y; + }; + struct + { + float s[2]; + }; + }; +}; + + +typedef unsigned int u32; +typedef unsigned short u16; +typedef unsigned char u8; + + + +#include "Adlfloat4.inl" +//#include + + + + +template +void swap2(T& a, T& b) +{ + T tmp = a; + a = b; + b = tmp; +} + + +__inline +void randSeed(int seed) +{ + srand( seed ); +} + +template +__inline +T randRange(const T& minV, const T& maxV) +{ + float r = (rand()%10000)/10000.f; + T range = maxV - minV; + return (T)(minV + r*range); +} + +template<> +__inline +float4 randRange(const float4& minV, const float4& maxV) +{ + float4 r = make_float4( (rand()%10000)/10000.f, (rand()%10000)/10000.f, (rand()%10000)/10000.f, (rand()%10000)/10000.f ); + float4 range = maxV - minV; + return (minV + r*range); +} + + +struct SortData +{ + union + { + u32 m_key; + struct { u16 m_key16[2]; }; + }; + u32 m_value; + + friend bool operator <(const SortData& a, const SortData& b) + { + return a.m_key < b.m_key; + } +}; + + + +template +T* addByteOffset(void* baseAddr, u32 offset) +{ + return (T*)(((u32)baseAddr)+offset); +} + + +struct Pair32 +{ + Pair32(){} + Pair32(u32 a, u32 b) : m_a(a), m_b(b){} + + u32 m_a; + u32 m_b; +}; + +struct PtrPair +{ + PtrPair(){} + PtrPair(void* a, void* b) : m_a(a), m_b(b){} + template + PtrPair(T* a, T* b) : m_a((void*)a), m_b((void*)b){} + + void* m_a; + void* m_b; +}; + +#endif diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlMatrix3x3.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlMatrix3x3.h new file mode 100644 index 0000000..fbd82aa --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlMatrix3x3.h @@ -0,0 +1,194 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#ifndef MATRIX3X3_H +#define MATRIX3X3_H + +#include "AdlMath.h" + +/////////////////////////////////////// +// Matrix3x3 +/////////////////////////////////////// + +typedef +_MEM_CLASSALIGN16 struct +{ + _MEM_ALIGNED_ALLOCATOR16; + float4 m_row[3]; +}Matrix3x3; + +__inline +Matrix3x3 mtZero(); + +__inline +Matrix3x3 mtIdentity(); + +__inline +Matrix3x3 mtDiagonal(float a, float b, float c); + +__inline +Matrix3x3 mtTranspose(const Matrix3x3& m); + +__inline +Matrix3x3 mtMul(const Matrix3x3& a, const Matrix3x3& b); + +__inline +float4 mtMul1(const Matrix3x3& a, const float4& b); + +__inline +Matrix3x3 mtMul2(float a, const Matrix3x3& b); + +__inline +float4 mtMul3(const float4& b, const Matrix3x3& a); + +__inline +Matrix3x3 mtInvert(const Matrix3x3& m); + +__inline +Matrix3x3 mtZero() +{ + Matrix3x3 m; + m.m_row[0] = make_float4(0.f); + m.m_row[1] = make_float4(0.f); + m.m_row[2] = make_float4(0.f); + return m; +} + +__inline +Matrix3x3 mtIdentity() +{ + Matrix3x3 m; + m.m_row[0] = make_float4(1,0,0); + m.m_row[1] = make_float4(0,1,0); + m.m_row[2] = make_float4(0,0,1); + return m; +} + +__inline +Matrix3x3 mtDiagonal(float a, float b, float c) +{ + Matrix3x3 m; + m.m_row[0] = make_float4(a,0,0); + m.m_row[1] = make_float4(0,b,0); + m.m_row[2] = make_float4(0,0,c); + return m; +} + +__inline +Matrix3x3 mtTranspose(const Matrix3x3& m) +{ + Matrix3x3 out; + out.m_row[0] = make_float4(m.m_row[0].s[0], m.m_row[1].s[0], m.m_row[2].s[0], 0.f); + out.m_row[1] = make_float4(m.m_row[0].s[1], m.m_row[1].s[1], m.m_row[2].s[1], 0.f); + out.m_row[2] = make_float4(m.m_row[0].s[2], m.m_row[1].s[2], m.m_row[2].s[2], 0.f); + return out; +} + +__inline +Matrix3x3 mtMul(const Matrix3x3& a, const Matrix3x3& b) +{ + Matrix3x3 transB; + transB = mtTranspose( b ); + Matrix3x3 ans; + for(int i=0; i<3; i++) + { + ans.m_row[i].s[0] = dot3F4(a.m_row[i],transB.m_row[0]); + ans.m_row[i].s[1] = dot3F4(a.m_row[i],transB.m_row[1]); + ans.m_row[i].s[2] = dot3F4(a.m_row[i],transB.m_row[2]); + } + return ans; +} + +__inline +float4 mtMul1(const Matrix3x3& a, const float4& b) +{ + float4 ans; + ans.s[0] = dot3F4( a.m_row[0], b ); + ans.s[1] = dot3F4( a.m_row[1], b ); + ans.s[2] = dot3F4( a.m_row[2], b ); + return ans; +} + +__inline +Matrix3x3 mtMul2(float a, const Matrix3x3& b) +{ + Matrix3x3 ans; + ans.m_row[0] = a*b.m_row[0]; + ans.m_row[1] = a*b.m_row[1]; + ans.m_row[2] = a*b.m_row[2]; + return ans; +} + +__inline +float4 mtMul3(const float4& a, const Matrix3x3& b) +{ + float4 ans; + ans.x = a.x*b.m_row[0].x + a.y*b.m_row[1].x + a.z*b.m_row[2].x; + ans.y = a.x*b.m_row[0].y + a.y*b.m_row[1].y + a.z*b.m_row[2].y; + ans.z = a.x*b.m_row[0].z + a.y*b.m_row[1].z + a.z*b.m_row[2].z; + return ans; +} + +__inline +Matrix3x3 mtInvert(const Matrix3x3& m) +{ + float det = m.m_row[0].s[0]*m.m_row[1].s[1]*m.m_row[2].s[2]+m.m_row[1].s[0]*m.m_row[2].s[1]*m.m_row[0].s[2]+m.m_row[2].s[0]*m.m_row[0].s[1]*m.m_row[1].s[2] + -m.m_row[0].s[0]*m.m_row[2].s[1]*m.m_row[1].s[2]-m.m_row[2].s[0]*m.m_row[1].s[1]*m.m_row[0].s[2]-m.m_row[1].s[0]*m.m_row[0].s[1]*m.m_row[2].s[2]; + + CLASSERT( det ); + + Matrix3x3 ans; + ans.m_row[0].s[0] = m.m_row[1].s[1]*m.m_row[2].s[2] - m.m_row[1].s[2]*m.m_row[2].s[1]; + ans.m_row[0].s[1] = m.m_row[0].s[2]*m.m_row[2].s[1] - m.m_row[0].s[1]*m.m_row[2].s[2]; + ans.m_row[0].s[2] = m.m_row[0].s[1]*m.m_row[1].s[2] - m.m_row[0].s[2]*m.m_row[1].s[1]; + ans.m_row[0].w = 0.f; + + ans.m_row[1].s[0] = m.m_row[1].s[2]*m.m_row[2].s[0] - m.m_row[1].s[0]*m.m_row[2].s[2]; + ans.m_row[1].s[1] = m.m_row[0].s[0]*m.m_row[2].s[2] - m.m_row[0].s[2]*m.m_row[2].s[0]; + ans.m_row[1].s[2] = m.m_row[0].s[2]*m.m_row[1].s[0] - m.m_row[0].s[0]*m.m_row[1].s[2]; + ans.m_row[1].w = 0.f; + + ans.m_row[2].s[0] = m.m_row[1].s[0]*m.m_row[2].s[1] - m.m_row[1].s[1]*m.m_row[2].s[0]; + ans.m_row[2].s[1] = m.m_row[0].s[1]*m.m_row[2].s[0] - m.m_row[0].s[0]*m.m_row[2].s[1]; + ans.m_row[2].s[2] = m.m_row[0].s[0]*m.m_row[1].s[1] - m.m_row[0].s[1]*m.m_row[1].s[0]; + ans.m_row[2].w = 0.f; + + ans = mtMul2((1.0f/det), ans); + return ans; +} + +__inline +Matrix3x3 mtSet( const float4& a, const float4& b, const float4& c ) +{ + Matrix3x3 m; + m.m_row[0] = a; + m.m_row[1] = b; + m.m_row[2] = c; + return m; +} + +__inline +Matrix3x3 operator+(const Matrix3x3& a, const Matrix3x3& b) +{ + Matrix3x3 out; + out.m_row[0] = a.m_row[0] + b.m_row[0]; + out.m_row[1] = a.m_row[1] + b.m_row[1]; + out.m_row[2] = a.m_row[2] + b.m_row[2]; + return out; +} + +#endif + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlQuaternion.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlQuaternion.h new file mode 100644 index 0000000..979e5fe --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlQuaternion.h @@ -0,0 +1,155 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#ifndef QUATERNION_H +#define QUATERNION_H + +#include "AdlMatrix3x3.h" + + +typedef float4 Quaternion; + +__inline +Quaternion qtSet(const float4& axis, float angle); + +__inline +Quaternion qtMul(const Quaternion& a, const Quaternion& b); + +__inline +float4 qtRotate(const Quaternion& q, const float4& vec); + +__inline +float4 qtInvRotate(const Quaternion& q, const float4& vec); + +__inline +Quaternion qtInvert(const Quaternion& q); + +__inline +Matrix3x3 qtGetRotationMatrix(const Quaternion& quat); + +__inline +Quaternion qtNormalize(const Quaternion& q); + +__inline +Quaternion qtGetIdentity() { return make_float4(0,0,0,1); } + +__inline +Quaternion qtSet(const float4& axis, float angle) +{ + float4 nAxis = normalize3( axis ); + + Quaternion q; + q.s[0] = nAxis.s[0]*sin(angle/2); + q.s[1] = nAxis.s[1]*sin(angle/2); + q.s[2] = nAxis.s[2]*sin(angle/2); + q.s[3] = cos(angle/2); + return q; +} + +__inline +Quaternion qtMul(const Quaternion& a, const Quaternion& b) +{ + Quaternion ans; + ans = cross3( a, b ); + ans += a.s[3]*b + b.s[3]*a; + ans.s[3] = a.s[3]*b.s[3] - (a.s[0]*b.s[0]+a.s[1]*b.s[1]+a.s[2]*b.s[2]); + return ans; +} + +__inline +float4 qtRotate(const Quaternion& q, const float4& vec) +{ + Quaternion vecQ = vec; + vecQ.s[3] = 0.f; + Quaternion qInv = qtInvert( q ); + float4 out = qtMul(qtMul(q,vecQ),qInv); + return out; +} + +__inline +float4 qtInvRotate(const Quaternion& q, const float4& vec) +{ + return qtRotate( qtInvert( q ), vec ); +} + +__inline +Quaternion qtInvert(const Quaternion& q) +{ + Quaternion ans; + ans.s[0] = -q.s[0]; + ans.s[1] = -q.s[1]; + ans.s[2] = -q.s[2]; + ans.s[3] = q.s[3]; + return ans; +} + +__inline +Matrix3x3 qtGetRotationMatrix(const Quaternion& quat) +{ + float4 quat2 = make_float4(quat.s[0]*quat.s[0], quat.s[1]*quat.s[1], quat.s[2]*quat.s[2], 0.f); + Matrix3x3 out; + + out.m_row[0].s[0]=1-2*quat2.s[1]-2*quat2.s[2]; + out.m_row[0].s[1]=2*quat.s[0]*quat.s[1]-2*quat.s[3]*quat.s[2]; + out.m_row[0].s[2]=2*quat.s[0]*quat.s[2]+2*quat.s[3]*quat.s[1]; + out.m_row[0].s[3] = 0.f; + + out.m_row[1].s[0]=2*quat.s[0]*quat.s[1]+2*quat.s[3]*quat.s[2]; + out.m_row[1].s[1]=1-2*quat2.s[0]-2*quat2.s[2]; + out.m_row[1].s[2]=2*quat.s[1]*quat.s[2]-2*quat.s[3]*quat.s[0]; + out.m_row[1].s[3] = 0.f; + + out.m_row[2].s[0]=2*quat.s[0]*quat.s[2]-2*quat.s[3]*quat.s[1]; + out.m_row[2].s[1]=2*quat.s[1]*quat.s[2]+2*quat.s[3]*quat.s[0]; + out.m_row[2].s[2]=1-2*quat2.s[0]-2*quat2.s[1]; + out.m_row[2].s[3] = 0.f; + + return out; +} + +__inline +Quaternion qtGetQuaternion(const Matrix3x3* m) +{ + Quaternion q; + q.w = sqrtf( m[0].m_row[0].x + m[0].m_row[1].y + m[0].m_row[2].z + 1 ) * 0.5f; + float inv4w = 1.f/(4.f*q.w); + q.x = (m[0].m_row[2].y-m[0].m_row[1].z)*inv4w; + q.y = (m[0].m_row[0].z-m[0].m_row[2].x)*inv4w; + q.z = (m[0].m_row[1].x-m[0].m_row[0].y)*inv4w; + + return q; +} + +__inline +Quaternion qtNormalize(const Quaternion& q) +{ + return normalize4(q); +} + +__inline +float4 transform(const float4& p, const float4& translation, const Quaternion& orientation) +{ + return qtRotate( orientation, p ) + translation; +} + +__inline +float4 invTransform(const float4& p, const float4& translation, const Quaternion& orientation) +{ + return qtRotate( qtInvert( orientation ), p-translation ); // use qtInvRotate +} + +#endif + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlRigidBody.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlRigidBody.h new file mode 100644 index 0000000..b374cd0 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlRigidBody.h @@ -0,0 +1,59 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#ifndef ADL_RIGID_BODY_H +#define ADL_RIGID_BODY_H + +#include "AdlQuaternion.h" + +class RigidBodyBase +{ + public: + + _MEM_CLASSALIGN16 + struct Body + { + _MEM_ALIGNED_ALLOCATOR16; + + float4 m_pos; + Quaternion m_quat; + float4 m_linVel; + float4 m_angVel; + + u32 m_shapeIdx; + u32 m_shapeType; + + float m_invMass; + float m_restituitionCoeff; + float m_frictionCoeff; + + }; + + struct Inertia + { +/* u16 m_shapeType; + u16 m_shapeIdx; + float m_restituitionCoeff; + float m_frictionCoeff; + int m_padding; +*/ + Matrix3x3 m_invInertia; + Matrix3x3 m_initInvInertia; + }; +}; + +#endif// ADL_RIGID_BODY_H + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlTransform.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlTransform.h new file mode 100644 index 0000000..d9464ba --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/AdlTransform.h @@ -0,0 +1,61 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#ifndef _ADL_TRANSFORM_H +#define _ADL_TRANSFORM_H + +#include "AdlMath.h" +#include "AdlQuaternion.h" +#include "AdlMatrix3x3.h" + +struct Transform +{ + float4 m_translation; + Matrix3x3 m_rotation; +}; + +Transform trSetTransform(const float4& translation, const Quaternion& quat) +{ + Transform tr; + tr.m_translation = translation; + tr.m_rotation = qtGetRotationMatrix( quat ); + return tr; +} + +Transform trInvert( const Transform& tr ) +{ + Transform ans; + ans.m_rotation = mtTranspose( tr.m_rotation ); + ans.m_translation = mtMul1( ans.m_rotation, -tr.m_translation ); + return ans; +} + +Transform trMul(const Transform& trA, const Transform& trB) +{ + Transform ans; + ans.m_rotation = mtMul( trA.m_rotation, trB.m_rotation ); + ans.m_translation = mtMul1( trA.m_rotation, trB.m_translation ) + trA.m_translation; + return ans; +} + +float4 trMul1(const Transform& tr, const float4& p) +{ + return mtMul1( tr.m_rotation, p ) + tr.m_translation; +} + + +#endif //_ADL_TRANSFORM_H + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/Adlfloat4.inl b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/Adlfloat4.inl new file mode 100644 index 0000000..4e98a08 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/Adlfloat4.inl @@ -0,0 +1,373 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +//#define CHECK_ALIGNMENT(a) CLASSERT((u32(&(a)) & 0xf) == 0); +#define CHECK_ALIGNMENT(a) a; + + +__inline +float4 make_float4(float x, float y, float z, float w = 0.f) +{ + float4 v; + v.x = x; v.y = y; v.z = z; v.w = w; + return v; +} + +__inline +float4 make_float4(float x) +{ + return make_float4(x,x,x,x); +} + +__inline +float4 make_float4(const int4& x) +{ + return make_float4((float)x.s[0], (float)x.s[1], (float)x.s[2], (float)x.s[3]); +} + +__inline +float2 make_float2(float x, float y) +{ + float2 v; + v.s[0] = x; v.s[1] = y; + return v; +} + +__inline +float2 make_float2(float x) +{ + return make_float2(x,x); +} + +__inline +float2 make_float2(const int2& x) +{ + return make_float2((float)x.s[0], (float)x.s[1]); +} + +__inline +int4 make_int4(int x, int y, int z, int w = 0) +{ + int4 v; + v.s[0] = x; v.s[1] = y; v.s[2] = z; v.s[3] = w; + return v; +} + +__inline +int4 make_int4(int x) +{ + return make_int4(x,x,x,x); +} + +__inline +int4 make_int4(const float4& x) +{ + return make_int4((int)x.x, (int)x.y, (int)x.z, (int)x.w); +} + +__inline +int2 make_int2(int a, int b) +{ + int2 ans; ans.x = a; ans.y = b; + return ans; +} + +__inline +float4 operator-(const float4& a) +{ + return make_float4(-a.x, -a.y, -a.z, -a.w); +} + +__inline +float4 operator*(const float4& a, const float4& b) +{ + CLASSERT((u32(&a) & 0xf) == 0); + + float4 out; + out.s[0] = a.s[0]*b.s[0]; + out.s[1] = a.s[1]*b.s[1]; + out.s[2] = a.s[2]*b.s[2]; + out.s[3] = a.s[3]*b.s[3]; + return out; +} + +__inline +float4 operator*(float a, const float4& b) +{ + return make_float4(a*b.s[0], a*b.s[1], a*b.s[2], a*b.s[3]); +} + +__inline +float4 operator*(const float4& b, float a) +{ + CHECK_ALIGNMENT(b); + + return make_float4(a*b.s[0], a*b.s[1], a*b.s[2], a*b.s[3]); +} + +__inline +void operator*=(float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + a.s[0]*=b.s[0]; + a.s[1]*=b.s[1]; + a.s[2]*=b.s[2]; + a.s[3]*=b.s[3]; +} + +__inline +void operator*=(float4& a, float b) +{ + CHECK_ALIGNMENT(a); + + a.s[0]*=b; + a.s[1]*=b; + a.s[2]*=b; + a.s[3]*=b; +} + +// +__inline +float4 operator/(const float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + float4 out; + out.s[0] = a.s[0]/b.s[0]; + out.s[1] = a.s[1]/b.s[1]; + out.s[2] = a.s[2]/b.s[2]; + out.s[3] = a.s[3]/b.s[3]; + return out; +} + +__inline +float4 operator/(const float4& b, float a) +{ + CHECK_ALIGNMENT(b); + + return make_float4(b.s[0]/a, b.s[1]/a, b.s[2]/a, b.s[3]/a); +} + +__inline +void operator/=(float4& a, const float4& b) +{ + a.s[0]/=b.s[0]; + a.s[1]/=b.s[1]; + a.s[2]/=b.s[2]; + a.s[3]/=b.s[3]; +} + +__inline +void operator/=(float4& a, float b) +{ + CLASSERT((u32(&a) & 0xf) == 0); + + a.s[0]/=b; + a.s[1]/=b; + a.s[2]/=b; + a.s[3]/=b; +} +// + +__inline +float4 operator+(const float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + float4 out; + out.s[0] = a.s[0]+b.s[0]; + out.s[1] = a.s[1]+b.s[1]; + out.s[2] = a.s[2]+b.s[2]; + out.s[3] = a.s[3]+b.s[3]; + return out; +} + +__inline +float4 operator+(const float4& a, float b) +{ + CHECK_ALIGNMENT(a); + + float4 out; + out.s[0] = a.s[0]+b; + out.s[1] = a.s[1]+b; + out.s[2] = a.s[2]+b; + out.s[3] = a.s[3]+b; + return out; +} + +__inline +float4 operator-(const float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + float4 out; + out.s[0] = a.s[0]-b.s[0]; + out.s[1] = a.s[1]-b.s[1]; + out.s[2] = a.s[2]-b.s[2]; + out.s[3] = a.s[3]-b.s[3]; + return out; +} + +__inline +float4 operator-(const float4& a, float b) +{ + CHECK_ALIGNMENT(a); + + float4 out; + out.s[0] = a.s[0]-b; + out.s[1] = a.s[1]-b; + out.s[2] = a.s[2]-b; + out.s[3] = a.s[3]-b; + return out; +} + +__inline +void operator+=(float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + a.s[0]+=b.s[0]; + a.s[1]+=b.s[1]; + a.s[2]+=b.s[2]; + a.s[3]+=b.s[3]; +} + +__inline +void operator+=(float4& a, float b) +{ + CHECK_ALIGNMENT(a); + + a.s[0]+=b; + a.s[1]+=b; + a.s[2]+=b; + a.s[3]+=b; +} + +__inline +void operator-=(float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + a.s[0]-=b.s[0]; + a.s[1]-=b.s[1]; + a.s[2]-=b.s[2]; + a.s[3]-=b.s[3]; +} + +__inline +void operator-=(float4& a, float b) +{ + CHECK_ALIGNMENT(a); + + a.s[0]-=b; + a.s[1]-=b; + a.s[2]-=b; + a.s[3]-=b; +} + + + + + +__inline +float4 cross3(const float4& a, const float4& b) +{ + return make_float4(a.s[1]*b.s[2]-a.s[2]*b.s[1], + a.s[2]*b.s[0]-a.s[0]*b.s[2], + a.s[0]*b.s[1]-a.s[1]*b.s[0], + 0); +} + +__inline +float dot3F4(const float4& a, const float4& b) +{ + return a.x*b.x+a.y*b.y+a.z*b.z; +} + +__inline +float length3(const float4& a) +{ + return sqrtf(dot3F4(a,a)); +} + +__inline +float dot4(const float4& a, const float4& b) +{ + return a.x*b.x+a.y*b.y+a.z*b.z+a.w*b.w; +} + +// for height +__inline +float dot3w1(const float4& point, const float4& eqn) +{ + return point.x*eqn.x+point.y*eqn.y+point.z*eqn.z+eqn.w; +} + +__inline +float4 normalize3(const float4& a) +{ + float length = sqrtf(dot3F4(a, a)); + return 1.f/length * a; +} + +__inline +float4 normalize4(const float4& a) +{ + float length = sqrtf(dot4(a, a)); + return 1.f/length * a; +} + +__inline +float4 createEquation(const float4& a, const float4& b, const float4& c) +{ + float4 eqn; + float4 ab = b-a; + float4 ac = c-a; + eqn = normalize3( cross3(ab, ac) ); + eqn.w = -dot3F4(eqn,a); + return eqn; +} + + +template +__inline +T max2(const T& a, const T& b) +{ + return (a>b)? a:b; +} + +template +__inline +T min2(const T& a, const T& b) +{ + return (a +__inline +float4 max2(const float4& a, const float4& b) +{ + return make_float4( max2(a.x,b.x), max2(a.y,b.y), max2(a.z,b.z), max2(a.w,b.w) ); +} + +template<> +__inline +float4 min2(const float4& a, const float4& b) +{ + return make_float4( min2(a.x,b.x), min2(a.y,b.y), min2(a.z,b.z), min2(a.w,b.w) ); +} + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/Adlfloat4SSE.inl b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/Adlfloat4SSE.inl new file mode 100644 index 0000000..a10211e --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/Adlfloat4SSE.inl @@ -0,0 +1,381 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +//#define CHECK_ALIGNMENT(a) CLASSERT((u32(&(a)) & 0xf) == 0); +#define CHECK_ALIGNMENT(a) a; + + +__inline +float4 make_float4(float x, float y, float z, float w = 0.f) +{ + float4 v; + v.m_quad = _mm_set_ps(w,z,y,x); + + return v; +} + +__inline +float4 make_float4(float x) +{ + return make_float4(x,x,x,x); +} + +__inline +float4 make_float4(const int4& x) +{ + return make_float4((float)x.s[0], (float)x.s[1], (float)x.s[2], (float)x.s[3]); +} + +__inline +float2 make_float2(float x, float y) +{ + float2 v; + v.s[0] = x; v.s[1] = y; + return v; +} + +__inline +float2 make_float2(float x) +{ + return make_float2(x,x); +} + +__inline +float2 make_float2(const int2& x) +{ + return make_float2((float)x.s[0], (float)x.s[1]); +} + +__inline +int4 make_int4(int x, int y, int z, int w = 0) +{ + int4 v; + v.s[0] = x; v.s[1] = y; v.s[2] = z; v.s[3] = w; + return v; +} + +__inline +int4 make_int4(int x) +{ + return make_int4(x,x,x,x); +} + +__inline +int4 make_int4(const float4& x) +{ + return make_int4((int)x.x, (int)x.y, (int)x.z, (int)x.w); +} + +__inline +int2 make_int2(int a, int b) +{ + int2 ans; ans.x = a; ans.y = b; + return ans; +} + +__inline +float4 operator-(const float4& a) +{ + float4 zero; zero.m_quad = _mm_setzero_ps(); + float4 ans; ans.m_quad = _mm_sub_ps( zero.m_quad, a.m_quad ); + return ans; +} + +__inline +float4 operator*(const float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + float4 out; + out.m_quad = _mm_mul_ps( a.m_quad, b.m_quad ); + return out; +} + +__inline +float4 operator*(float a, const float4& b) +{ + float4 av; av.m_quad = _mm_set1_ps( a ); + return av*b; +} + +__inline +float4 operator*(const float4& b, float a) +{ + CHECK_ALIGNMENT(b); + + float4 av; av.m_quad = _mm_set1_ps( a ); + return av*b; +} + +__inline +void operator*=(float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + a = a*b; +} + +__inline +void operator*=(float4& a, float b) +{ + CHECK_ALIGNMENT(a); + + float4 bv; bv.m_quad = _mm_set1_ps( b ); + a = a*bv; +} + +// +__inline +float4 operator/(const float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + float4 out; + out.m_quad = _mm_div_ps( a.m_quad, b.m_quad ); + return out; +} + +__inline +float4 operator/(const float4& b, float a) +{ + CHECK_ALIGNMENT(b); + + float4 av; av.m_quad = _mm_set1_ps( a ); + float4 out; + out = b/av; + return out; +} + +__inline +void operator/=(float4& a, const float4& b) +{ + a = a/b; +} + +__inline +void operator/=(float4& a, float b) +{ + CLASSERT((u32(&a) & 0xf) == 0); + + float4 bv; bv.m_quad = _mm_set1_ps( b ); + a = a/bv; +} +// + +__inline +float4 operator+(const float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + float4 out; + out.m_quad = _mm_add_ps( a.m_quad, b.m_quad ); + return out; +} + +__inline +float4 operator+(const float4& a, float b) +{ + CHECK_ALIGNMENT(a); + + float4 bv; bv.m_quad = _mm_set1_ps( b ); + return a+bv; +} + +__inline +float4 operator-(const float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + float4 out; + out.m_quad = _mm_sub_ps( a.m_quad, b.m_quad ); + return out; +} + +__inline +float4 operator-(const float4& a, float b) +{ + CHECK_ALIGNMENT(a); + + float4 bv; bv.m_quad = _mm_set1_ps( b ); + return a-bv; +} + +__inline +void operator+=(float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + a = a + b; +} + +__inline +void operator+=(float4& a, float b) +{ + CHECK_ALIGNMENT(a); + + float4 bv; bv.m_quad = _mm_set1_ps( b ); + + a = a + bv; +} + +__inline +void operator-=(float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + a = a - b; +} + +__inline +void operator-=(float4& a, float b) +{ + CHECK_ALIGNMENT(a); + + float4 bv; bv.m_quad = _mm_set1_ps( b ); + + a = a - bv; +} + + + + + +__inline +float4 cross3(const float4& a, const float4& b) +{ // xnamathvector.inl + union IntVec + { + unsigned int m_i[4]; + __m128 m_v; + }; + + IntVec mask3 = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000}; + __m128 V1 = a.m_quad; + __m128 V2 = b.m_quad; + + __m128 vTemp1 = _mm_shuffle_ps(V1,V1,_MM_SHUFFLE(3,0,2,1)); + // z2,x2,y2,w2 + __m128 vTemp2 = _mm_shuffle_ps(V2,V2,_MM_SHUFFLE(3,1,0,2)); + // Perform the left operation + __m128 vResult = _mm_mul_ps(vTemp1,vTemp2); + // z1,x1,y1,w1 + vTemp1 = _mm_shuffle_ps(vTemp1,vTemp1,_MM_SHUFFLE(3,0,2,1)); + // y2,z2,x2,w2 + vTemp2 = _mm_shuffle_ps(vTemp2,vTemp2,_MM_SHUFFLE(3,1,0,2)); + // Perform the right operation + vTemp1 = _mm_mul_ps(vTemp1,vTemp2); + // Subract the right from left, and return answer + vResult = _mm_sub_ps(vResult,vTemp1); + // Set w to zero + float4 ans; ans.m_quad = _mm_and_ps(vResult,mask3.m_v); + return ans; +} + +__inline +float dot3F4(const float4& a, const float4& b) +{ +// return a.x*b.x+a.y*b.y+a.z*b.z; + // Perform the dot product + __m128 V1 = a.m_quad; + __m128 V2 = b.m_quad; + + __m128 vDot = _mm_mul_ps(V1,V2); + // x=Dot.vector4_f32[1], y=Dot.vector4_f32[2] + __m128 vTemp = _mm_shuffle_ps(vDot,vDot,_MM_SHUFFLE(2,1,2,1)); + // Result.vector4_f32[0] = x+y + vDot = _mm_add_ss(vDot,vTemp); + // x=Dot.vector4_f32[2] + vTemp = _mm_shuffle_ps(vTemp,vTemp,_MM_SHUFFLE(1,1,1,1)); + // Result.vector4_f32[0] = (x+y)+z + vDot = _mm_add_ss(vDot,vTemp); + // Splat x + float4 ans; ans.m_quad = _mm_shuffle_ps(vDot,vDot,_MM_SHUFFLE(0,0,0,0)); + return ans.x; +} + +__inline +float length3(const float4& a) +{ + return sqrtf(dot3F4(a,a)); +} + +__inline +float dot4(const float4& a, const float4& b) +{ + return a.x*b.x+a.y*b.y+a.z*b.z+a.w*b.w; +} + +// for height +__inline +float dot3w1(const float4& point, const float4& eqn) +{ + return point.x*eqn.x+point.y*eqn.y+point.z*eqn.z+eqn.w; +} + +__inline +float4 normalize3(const float4& a) +{ + float length = sqrtf(dot3F4(a, a)); + return 1.f/length * a; +} + +__inline +float4 normalize4(const float4& a) +{ + float length = sqrtf(dot4(a, a)); + return 1.f/length * a; +} + +__inline +float4 createEquation(const float4& a, const float4& b, const float4& c) +{ + float4 eqn; + float4 ab = b-a; + float4 ac = c-a; + eqn = normalize3( cross3(ab, ac) ); + eqn.w = -dot3F4(eqn,a); + return eqn; +} + + +template +__inline +T max2(const T& a, const T& b) +{ + return (a>b)? a:b; +} + +template +__inline +T min2(const T& a, const T& b) +{ + return (a +__inline +float4 max2(const float4& a, const float4& b) +{ + return make_float4( max2(a.x,b.x), max2(a.y,b.y), max2(a.z,b.z), max2(a.w,b.w) ); +} + +template<> +__inline +float4 min2(const float4& a, const float4& b) +{ + return make_float4( min2(a.x,b.x), min2(a.y,b.y), min2(a.z,b.z), min2(a.w,b.w) ); +} + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/ChNarrowPhase.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/ChNarrowPhase.h new file mode 100644 index 0000000..4ad551f --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/ChNarrowPhase.h @@ -0,0 +1,154 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#pragma once + +#include +//#include + +#include "AdlMath.h" +#include "AdlContact4.h" +#include "AdlRigidBody.h" + +#include "../ConvexHeightFieldShape.h" + +//#include "TypeDefinition.h" +//#include "RigidBody.h" +//#include "ConvexHeightFieldShape.h" + +namespace adl +{ +class ShapeBase; + +class ChNarrowphaseBase +{ + public: + struct Config + { + float m_collisionMargin; + }; +/* + typedef struct + { + // m_normal.w == height in u8 + float4 m_normal[HEIGHT_RES*HEIGHT_RES*6]; + u32 m_height4[HEIGHT_RES*HEIGHT_RES*6]; + + float m_scale; + float m_padding0; + float m_padding1; + float m_padding2; + } ShapeData; +*/ +}; + +template +class ChNarrowphase : public ChNarrowphaseBase +{ + public: + typedef Launcher::BufferInfo BufferInfo; + + struct Data + { + const Device* m_device; + Kernel* m_supportCullingKernel; + Kernel* m_narrowphaseKernel; + Kernel* m_narrowphaseWithPlaneKernel; + + Buffer* m_counterBuffer; + }; + + enum + { + N_TASKS = 4, + HEIGHT_RES = ConvexHeightField::HEIGHT_RES, + }; + + struct ShapeData + { + float4 m_normal[HEIGHT_RES*HEIGHT_RES*6]; + u32 m_height4[HEIGHT_RES*HEIGHT_RES*6]; + u32 m_supportHeight4[HEIGHT_RES*HEIGHT_RES*6]; + + float m_scale; + float m_padding0; + float m_padding1; + float m_padding2; + }; + + struct ConstData + { + int m_nPairs; + float m_collisionMargin; + int m_capacity; + int m_paddings[1]; + }; + + static + Data* allocate( const Device* device ); + + static + void deallocate( Data* data ); +/* + static + Buffer* allocateShapeBuffer( const Device* device, int capacity ); + + static + void deallocateShapeBuffer( Buffer* shapeBuf ); + + static + void setShape( Buffer* shapeBuf, ShapeBase* shape, int idx, float collisionMargin ); +*/ + static + ShapeDataType allocateShapeBuffer( const Device* device, int capacity ); + + static + void deallocateShapeBuffer( ShapeDataType shapeBuf ); + + static + void setShape( ShapeDataType shapeBuf, ShapeBase* shape, int idx, float collisionMargin = 0.f ); + + static + void setShape( ShapeDataType shapeBuf, ConvexHeightField* cvxShape, int idx, float collisionMargin = 0.f ); + + // Run NarrowphaseKernel + //template + static + void execute( Data* data, const Buffer* pairs, int nPairs, + const Buffer* bodyBuf, const ShapeDataType shapeBuf, + Buffer* contactOut, int& nContacts, const Config& cfg ); + + // Run NarrowphaseWithPlaneKernel + //template + static + void execute( Data* data, const Buffer* pairs, int nPairs, + const Buffer* bodyBuf, const ShapeDataType shapeBuf, + const Buffer* vtxBuf, const Buffer* idxBuf, + Buffer* contactOut, int& nContacts, const Config& cfg ); + + // Run SupportCullingKernel + //template + static + int culling( Data* data, const Buffer* pairs, int nPairs, const Buffer* bodyBuf, + const ShapeDataType shapeBuf, const Buffer* pairsOut, const Config& cfg ); +}; + +//#include +//#include + +#include "ChNarrowphase.inl" + +}; diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/ChNarrowphase.inl b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/ChNarrowphase.inl new file mode 100644 index 0000000..00ffbda --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/ChNarrowphase.inl @@ -0,0 +1,303 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +//#define PATH "..\\..\\dynamics\\basic_demo\\Stubs\\ChNarrowphaseKernels" +#define PATH "..\\..\\dynamics\\basic_demo\\Stubs\\ChNarrowphaseKernels" +#define KERNEL0 "SupportCullingKernel" +#define KERNEL1 "NarrowphaseKernel" + +#include "ChNarrowphaseKernels.h" + +class ChNarrowphaseImp +{ +public: + static + __inline + u32 u32Pack(u8 x, u8 y, u8 z, u8 w) + { + return (x) | (y<<8) | (z<<16) | (w<<24); + } + +}; + +template +typename ChNarrowphase::Data* ChNarrowphase::allocate( const Device* device ) +{ + char options[100]; + + const char* src[] = +#if defined(ADL_LOAD_KERNEL_FROM_STRING) + {narrowphaseKernelsCL, 0}; +#else + {0,0}; +#endif + + + + + //sprintf(options, "-I ..\\..\\ -Wf,--c++"); + sprintf(options, "-I .\\NarrowPhaseCL\\"); + + Data* data = new Data; + data->m_device = device; + data->m_supportCullingKernel = device->getKernel( PATH, KERNEL0, options,src[TYPE] ); + data->m_narrowphaseKernel = device->getKernel( PATH, KERNEL1, options, src[TYPE]); + data->m_narrowphaseWithPlaneKernel = device->getKernel( PATH, "NarrowphaseWithPlaneKernel", options,src[TYPE]); + data->m_counterBuffer = new Buffer( device, 1 ); + + return data; +} + + +template +void ChNarrowphase::deallocate( Data* data ) +{ + delete data->m_counterBuffer; + + delete data; +} + +template +ShapeDataType ChNarrowphase::allocateShapeBuffer( const Device* device, int capacity ) +{ + ADLASSERT( device->m_type == TYPE ); + + return new Buffer( device, capacity ); +} + +template +void ChNarrowphase::deallocateShapeBuffer( ShapeDataType shapeBuf ) +{ + Buffer* s = (Buffer*)shapeBuf; + delete s; +} + +template +void ChNarrowphase::setShape( ShapeDataType shapeBuf, ShapeBase* shape, int idx, float collisionMargin ) +{ + ConvexHeightField* cvxShape = new ConvexHeightField( shape ); + Buffer* dst = (Buffer*)shapeBuf; + cvxShape->m_aabb.expandBy( make_float4( collisionMargin ) ); + { + ShapeData s; + { + for(int j=0; jm_normal[j]; + } + for(int j=0; jm_data[4*j], cvxShape->m_data[4*j+1], cvxShape->m_data[4*j+2], cvxShape->m_data[4*j+3] ); + s.m_supportHeight4[j] = ChNarrowphaseImp::u32Pack( cvxShape->m_supportHeight[4*j], cvxShape->m_supportHeight[4*j+1], cvxShape->m_supportHeight[4*j+2], cvxShape->m_supportHeight[4*j+3] ); + } + s.m_scale = cvxShape->m_scale; + } + dst->write( &s, 1, idx ); + DeviceUtils::waitForCompletion( dst->m_device ); + } + delete cvxShape; +} + +template +void ChNarrowphase::setShape( ShapeDataType shapeBuf, ConvexHeightField* cvxShape, int idx, float collisionMargin ) +{ + Buffer* dst = (Buffer*)shapeBuf; + cvxShape->m_aabb.expandBy( make_float4( collisionMargin ) ); + { + ShapeData s; + { + for(int j=0; jm_normal[j]; + } + for(int j=0; jm_data[4*j], cvxShape->m_data[4*j+1], cvxShape->m_data[4*j+2], cvxShape->m_data[4*j+3] ); + s.m_supportHeight4[j] = ChNarrowphaseImp::u32Pack( cvxShape->m_supportHeight[4*j], cvxShape->m_supportHeight[4*j+1], cvxShape->m_supportHeight[4*j+2], cvxShape->m_supportHeight[4*j+3] ); + } + s.m_scale = cvxShape->m_scale; + } + dst->write( &s, 1, idx ); + DeviceUtils::waitForCompletion( dst->m_device ); + } +} + +// Run NarrowphaseKernel +template +//template +void ChNarrowphase::execute( Data* data, const Buffer* pairs, int nPairs, const Buffer* bodyBuf, + const ShapeDataType shapeBuf, + Buffer* contactOut, int& nContacts, const Config& cfg ) +{ + if( nPairs == 0 ) return; + + Buffer* shapeBuffer = (Buffer*)shapeBuf; + ADLASSERT( shapeBuffer->getType() == TYPE ); + + const Device* device = data->m_device; + + Buffer* gPairsInNative + = BufferUtils::map( data->m_device, pairs ); + Buffer* gBodyInNative + = BufferUtils::map( data->m_device, bodyBuf ); + Buffer* gContactOutNative + = BufferUtils::map( data->m_device, contactOut ); // this might not be empty + + Buffer constBuffer( device, 1, BufferBase::BUFFER_CONST ); + + ConstData cdata; + cdata.m_nPairs = nPairs; + cdata.m_collisionMargin = cfg.m_collisionMargin; + cdata.m_capacity = contactOut->getSize() - nContacts; + + u32 n = nContacts; + data->m_counterBuffer->write( &n, 1 ); +// DeviceUtils::waitForCompletion( device ); + + { + BufferInfo bInfo[] = { BufferInfo( gPairsInNative, true ), BufferInfo( shapeBuffer ), BufferInfo( gBodyInNative ), + BufferInfo( gContactOutNative ), + BufferInfo( data->m_counterBuffer ) }; + Launcher launcher( data->m_device, data->m_narrowphaseKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( constBuffer, cdata ); + launcher.launch1D( nPairs*64, 64 ); + } + + data->m_counterBuffer->read( &n, 1 ); + DeviceUtils::waitForCompletion( device ); + + BufferUtils::unmap( gPairsInNative, pairs ); + BufferUtils::unmap( gBodyInNative, bodyBuf ); + BufferUtils::unmap( gContactOutNative, contactOut ); + + nContacts = min2((int)n, contactOut->getSize() ); +} + +// Run NarrowphaseWithPlaneKernel +template +//template +void ChNarrowphase::execute( Data* data, const Buffer* pairs, int nPairs, + const Buffer* bodyBuf, const ShapeDataType shapeBuf, + const Buffer* vtxBuf, const Buffer* idxBuf, + Buffer* contactOut, int& nContacts, const Config& cfg ) +{ + if( nPairs == 0 ) return; + + Buffer* shapeBuffer = (Buffer*)shapeBuf; + ADLASSERT( shapeBuffer->getType() == TYPE ); + + const Device* device = data->m_device; + + Buffer* gPairsInNative + = BufferUtils::map( data->m_device, pairs ); + Buffer* gBodyInNative + = BufferUtils::map( data->m_device, bodyBuf ); + Buffer* gContactOutNative + = BufferUtils::map( data->m_device, contactOut ); // this might not be empty + + Buffer constBuffer( device, 1, BufferBase::BUFFER_CONST ); + + ConstData cdata; + cdata.m_nPairs = nPairs; + cdata.m_collisionMargin = cfg.m_collisionMargin; + cdata.m_capacity = contactOut->getSize() - nContacts; + + u32 n = nContacts; + data->m_counterBuffer->write( &n, 1 ); +// DeviceUtils::waitForCompletion( device ); + + { + BufferInfo bInfo[] = { BufferInfo( gPairsInNative, true ), BufferInfo( shapeBuffer ), BufferInfo( gBodyInNative ), + BufferInfo( gContactOutNative ), + BufferInfo( data->m_counterBuffer ) }; + Launcher launcher( data->m_device, data->m_narrowphaseWithPlaneKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( constBuffer, cdata ); + launcher.launch1D( nPairs*64, 64 ); + } + + data->m_counterBuffer->read( &n, 1 ); + DeviceUtils::waitForCompletion( device ); + + BufferUtils::unmap( gPairsInNative, pairs ); + BufferUtils::unmap( gBodyInNative, bodyBuf ); + BufferUtils::unmap( gContactOutNative, contactOut ); + + nContacts = min2((int)n, contactOut->getSize() ); +} + +// Run SupportCullingKernel +template +//template +int ChNarrowphase::culling( Data* data, const Buffer* pairs, int nPairs, const Buffer* bodyBuf, + const ShapeDataType shapeBuf, const Buffer* pairsOut, const Config& cfg ) +{ + if( nPairs == 0 ) return 0; + + Buffer* shapeBuffer = (Buffer*)shapeBuf; + ADLASSERT( shapeBuffer->getType() == TYPE ); + + const Device* device = data->m_device; + + Buffer* gPairsInNative + = BufferUtils::map( data->m_device, pairs ); + Buffer* gBodyInNative + = BufferUtils::map( data->m_device, bodyBuf ); + Buffer* gPairsOutNative + = BufferUtils::map( data->m_device, pairsOut ); + + // + Buffer constBuffer( device, 1, BufferBase::BUFFER_CONST ); + + ConstData cdata; + cdata.m_nPairs = nPairs; + cdata.m_collisionMargin = cfg.m_collisionMargin; + cdata.m_capacity = pairsOut->getSize(); + + u32 n = 0; + data->m_counterBuffer->write( &n, 1 ); +// DeviceUtils::waitForCompletion( device ); + { + BufferInfo bInfo[] = { BufferInfo( gPairsInNative, true ), BufferInfo( shapeBuffer ), BufferInfo( gBodyInNative ), + BufferInfo( gPairsOutNative ), BufferInfo( data->m_counterBuffer ) }; + Launcher launcher( data->m_device, data->m_supportCullingKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( constBuffer, cdata ); + launcher.launch1D( nPairs, 64 ); + } + data->m_counterBuffer->read( &n, 1 ); + DeviceUtils::waitForCompletion( device ); +/* + if( gPairsInNative != pairs ) delete gPairsInNative; + if( gBodyInNative != bodyBuf ) delete gBodyInNative; + if( gPairsOutNative != pairsOut ) + { + gPairsOutNative->read( pairsOut->m_ptr, n ); + DeviceUtils::waitForCompletion( device ); + delete gPairsOutNative; + } +*/ + BufferUtils::unmap( gPairsInNative, pairs ); + BufferUtils::unmap( gBodyInNative, bodyBuf ); + BufferUtils::unmap( gPairsOutNative, pairsOut ); + + return min2((int)n, pairsOut->getSize() ); +} + +#undef PATH +#undef KERNEL0 +#undef KERNEL1 \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/ChNarrowphaseKernels.cl b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/ChNarrowphaseKernels.cl new file mode 100644 index 0000000..af177a8 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/ChNarrowphaseKernels.cl @@ -0,0 +1,1629 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#pragma OPENCL EXTENSION cl_amd_printf : enable +#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable +#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable +#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable +#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable + +#ifdef cl_ext_atomic_counters_32 +#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable +#else +#define counter32_t volatile global int* +#endif + + +typedef unsigned int u32; +typedef unsigned short u16; +typedef unsigned char u8; + +#define GET_GROUP_IDX get_group_id(0) +#define GET_LOCAL_IDX get_local_id(0) +#define GET_GLOBAL_IDX get_global_id(0) +#define GET_GROUP_SIZE get_local_size(0) +#define GET_NUM_GROUPS get_num_groups(0) +#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE) +#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE) +#define AtomInc(x) atom_inc(&(x)) +#define AtomInc1(x, out) out = atom_inc(&(x)) +#define AppendInc(x, out) out = atomic_inc(x) +#define AtomAdd(x, value) atom_add(&(x), value) +#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value ) +#define AtomXhg(x, value) atom_xchg ( &(x), value ) + + +#define SELECT_UINT4( b, a, condition ) select( b,a,condition ) + +#define make_float4 (float4) +#define make_float2 (float2) +#define make_uint4 (uint4) +#define make_int4 (int4) +#define make_uint2 (uint2) +#define make_int2 (int2) + + +#define max2 max +#define min2 min + + +/////////////////////////////////////// +// Vector +/////////////////////////////////////// +__inline +float fastDiv(float numerator, float denominator) +{ + return native_divide(numerator, denominator); +// return numerator/denominator; +} + +__inline +float4 fastDiv4(float4 numerator, float4 denominator) +{ + return native_divide(numerator, denominator); +} + +__inline +float fastSqrtf(float f2) +{ + return native_sqrt(f2); +// return sqrt(f2); +} + +__inline +float fastRSqrt(float f2) +{ + return native_rsqrt(f2); +} + +__inline +float fastLength4(float4 v) +{ + return fast_length(v); +} + +__inline +float4 fastNormalize4(float4 v) +{ + return fast_normalize(v); +} + + +__inline +float sqrtf(float a) +{ +// return sqrt(a); + return native_sqrt(a); +} + +__inline +float4 cross3(float4 a, float4 b) +{ + return cross(a,b); +} + +__inline +float dot3F4(float4 a, float4 b) +{ + float4 a1 = make_float4(a.xyz,0.f); + float4 b1 = make_float4(b.xyz,0.f); + return dot(a1, b1); +} + +__inline +float length3(const float4 a) +{ + return sqrtf(dot3F4(a,a)); +} + +__inline +float dot4(const float4 a, const float4 b) +{ + return dot( a, b ); +} + +// for height +__inline +float dot3w1(const float4 point, const float4 eqn) +{ + return dot3F4(point,eqn) + eqn.w; +} + +__inline +float4 normalize3(const float4 a) +{ + float4 n = make_float4(a.x, a.y, a.z, 0.f); + return fastNormalize4( n ); +// float length = sqrtf(dot3F4(a, a)); +// return 1.f/length * a; +} + +__inline +float4 normalize4(const float4 a) +{ + float length = sqrtf(dot4(a, a)); + return 1.f/length * a; +} + +__inline +float4 createEquation(const float4 a, const float4 b, const float4 c) +{ + float4 eqn; + float4 ab = b-a; + float4 ac = c-a; + eqn = normalize3( cross3(ab, ac) ); + eqn.w = -dot3F4(eqn,a); + return eqn; +} + +/////////////////////////////////////// +// Matrix3x3 +/////////////////////////////////////// + +typedef struct +{ + float4 m_row[3]; +}Matrix3x3; + +__inline +Matrix3x3 mtZero(); + +__inline +Matrix3x3 mtIdentity(); + +__inline +Matrix3x3 mtTranspose(Matrix3x3 m); + +__inline +Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b); + +__inline +float4 mtMul1(Matrix3x3 a, float4 b); + +__inline +float4 mtMul3(float4 a, Matrix3x3 b); + +__inline +Matrix3x3 mtZero() +{ + Matrix3x3 m; + m.m_row[0] = (float4)(0.f); + m.m_row[1] = (float4)(0.f); + m.m_row[2] = (float4)(0.f); + return m; +} + +__inline +Matrix3x3 mtIdentity() +{ + Matrix3x3 m; + m.m_row[0] = (float4)(1,0,0,0); + m.m_row[1] = (float4)(0,1,0,0); + m.m_row[2] = (float4)(0,0,1,0); + return m; +} + +__inline +Matrix3x3 mtTranspose(Matrix3x3 m) +{ + Matrix3x3 out; + out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f); + out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f); + out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f); + return out; +} + +__inline +Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b) +{ + Matrix3x3 transB; + transB = mtTranspose( b ); + Matrix3x3 ans; + // why this doesn't run when 0ing in the for{} + a.m_row[0].w = 0.f; + a.m_row[1].w = 0.f; + a.m_row[2].w = 0.f; + for(int i=0; i<3; i++) + { +// a.m_row[i].w = 0.f; + ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]); + ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]); + ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]); + ans.m_row[i].w = 0.f; + } + return ans; +} + +__inline +float4 mtMul1(Matrix3x3 a, float4 b) +{ + float4 ans; + ans.x = dot3F4( a.m_row[0], b ); + ans.y = dot3F4( a.m_row[1], b ); + ans.z = dot3F4( a.m_row[2], b ); + ans.w = 0.f; + return ans; +} + +__inline +float4 mtMul3(float4 a, Matrix3x3 b) +{ + float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0); + float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0); + float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0); + + float4 ans; + ans.x = dot3F4( a, colx ); + ans.y = dot3F4( a, coly ); + ans.z = dot3F4( a, colz ); + return ans; +} + +/////////////////////////////////////// +// Quaternion +/////////////////////////////////////// + +typedef float4 Quaternion; + +__inline +Quaternion qtMul(Quaternion a, Quaternion b); + +__inline +Quaternion qtNormalize(Quaternion in); + +__inline +float4 qtRotate(Quaternion q, float4 vec); + +__inline +Quaternion qtInvert(Quaternion q); + +__inline +Matrix3x3 qtGetRotationMatrix(Quaternion q); + + + +__inline +Quaternion qtMul(Quaternion a, Quaternion b) +{ + Quaternion ans; + ans = cross3( a, b ); + ans += a.w*b+b.w*a; +// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z); + ans.w = a.w*b.w - dot3F4(a, b); + return ans; +} + +__inline +Quaternion qtNormalize(Quaternion in) +{ + return fastNormalize4(in); +// in /= length( in ); +// return in; +} +__inline +float4 qtRotate(Quaternion q, float4 vec) +{ + Quaternion qInv = qtInvert( q ); + float4 vcpy = vec; + vcpy.w = 0.f; + float4 out = qtMul(qtMul(q,vcpy),qInv); + return out; +} + +__inline +Quaternion qtInvert(Quaternion q) +{ + return (Quaternion)(-q.xyz, q.w); +} + +__inline +float4 qtInvRotate(const Quaternion q, float4 vec) +{ + return qtRotate( qtInvert( q ), vec ); +} + +__inline +Matrix3x3 qtGetRotationMatrix(Quaternion quat) +{ + float4 quat2 = (float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f); + Matrix3x3 out; + + out.m_row[0].x=1-2*quat2.y-2*quat2.z; + out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z; + out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y; + out.m_row[0].w = 0.f; + + out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z; + out.m_row[1].y=1-2*quat2.x-2*quat2.z; + out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x; + out.m_row[1].w = 0.f; + + out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y; + out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x; + out.m_row[2].z=1-2*quat2.x-2*quat2.y; + out.m_row[2].w = 0.f; + + return out; +} + + +#define WG_SIZE 64 +#define HEIGHT_RES 4 +#define SHAPE_CONVEX_HEIGHT_FIELD 1//keep this in sync with AdlCollisionShape.h! + +typedef struct +{ + float4 m_normal[HEIGHT_RES*HEIGHT_RES*6]; + u32 m_height4[HEIGHT_RES*HEIGHT_RES*6]; + u32 m_supportHeight4[HEIGHT_RES*HEIGHT_RES*6]; + + float m_scale; + float m_padding0; + float m_padding1; + float m_padding2; +} ShapeData; + +typedef struct +{ + u32 m_height4[HEIGHT_RES*HEIGHT_RES*6/4]; + + float m_scale; +} ShapeDeviceData; + +typedef struct +{ + float4 m_pos; + float4 m_quat; + float4 m_linVel; + float4 m_angVel; + + u32 m_shapeIdx; + u32 m_shapeType; + + float m_invMass; + float m_restituitionCoeff; + float m_frictionCoeff; +} BodyData; + +typedef struct +{ + float4 m_worldPos[4]; + float4 m_worldNormal; // w: m_nPoints +// float m_restituitionCoeff; +// float m_frictionCoeff; + u32 m_coeffs; + u32 m_batchIdx; +// int m_nPoints; +// int m_padding0; + + u32 m_bodyAPtr;//x:m_bodyAPtr, y:m_bodyBPtr + u32 m_bodyBPtr; +} Contact4; + +#define GET_NPOINTS(x) (x).m_worldNormal.w + + +typedef struct +{ + int m_nPairs; + float m_collisionMargin; + int m_capacity; + int m_paddings[1]; +} ConstBuffer; + +__inline +float4 transform(const float4* p, const float4* translation, const Quaternion* orientation) +{ + return qtRotate( *orientation, *p ) + (*translation); +} + +__inline +float4 invTransform(const float4* p, const float4* translation, const Quaternion* orientation) +{ + return qtRotate( qtInvert( *orientation ), (*p)-(*translation) ); // use qtInvRotate +} + +void CubeMapUtilsCalcCrd(const float4 p, int* faceIdxOut, float* x, float* y) +{ + { + int idx; + float r2[] = {p.x*p.x, p.y*p.y, p.z*p.z}; + + if (r2[1]>r2[0]) + { + if (r2[2]>r2[1]) + { + idx = 2; + + } else + { + idx = 1; + } + + } else + { + if (r2[2]>r2[0]) + { + idx = 2; + } else + { + idx = 0; + } + } + + *faceIdxOut = (idx*2); +//== + float4 abs = make_float4( fabs(p.x), fabs(p.y), fabs(p.z), 0.f ); + + float d; + if( idx == 0 ) + { + *x = p.y; + *y = p.z; + d = abs.x; + *faceIdxOut += (p.x < 0.f)? 0: 1.f; + } + else if( idx == 1 ) + { + *x = p.z; + *y = p.x; + d = abs.y; + *faceIdxOut += (p.y < 0.f)? 0: 1.f; + } + else + { + *x = p.x; + *y = p.y; + d = abs.z; + *faceIdxOut += (p.z < 0.f)? 0: 1.f; + } + + float dInv = (d==0.f)? 0.f: fastDiv(1.f,d); + *x = (*x*dInv+1.f)*0.5f; + *y = (*y*dInv+1.f)*0.5f; + } +} + +float4 CubeMapUtilsCalcVector(int faceIdx, float x, float y) +{ + int dir = faceIdx/2; + float z = (faceIdx%2 == 0)? -1.f:1.f; + + x = x*2.f-1.f; + y = y*2.f-1.f; + + if( dir == 0 ) + { + return make_float4(z, x, y, 0.f); + } + else if( dir == 1 ) + { + return make_float4(y,z,x, 0.f); + } + else + { + return make_float4(x,y,z, 0.f); + } +} + +typedef int Face; + +u32 sample(__local ShapeDeviceData* shape, int face, int x, int y) +{ + + int idx = HEIGHT_RES*HEIGHT_RES*face + x + y*HEIGHT_RES; + __local u8* height = (__local u8*)shape->m_height4; + return height[idx]; +} + +u32 sampleSupportGlobal(__global ShapeData* shape, int face, int x, int y) +{ + + int idx = HEIGHT_RES*HEIGHT_RES*face + x + y*HEIGHT_RES; + __global u8* height = (__global u8*)shape->m_supportHeight4; + return height[idx]; +} + +float4 sampleNormal(__local ShapeData* shape, int face, int x, int y) +{ + return shape->m_normal[HEIGHT_RES*HEIGHT_RES*face + x + y*HEIGHT_RES]; +} + +float4 sampleNormalGlobal(const __global ShapeData* shape, int face, int x, int y) +{ + return shape->m_normal[HEIGHT_RES*HEIGHT_RES*face + x + y*HEIGHT_RES]; +} + +float4 ShapeDataCalcSamplePoint( __local const ShapeDeviceData* shape, int sIdx )//u8 height, int sIdx, float scale ) +{ + const float oneOver255 = 1.f/255.f; + + int faceIdx = fastDiv(sIdx,(HEIGHT_RES*HEIGHT_RES)); + int r = (sIdx%(HEIGHT_RES*HEIGHT_RES)); + int i = r/HEIGHT_RES; + int j = r%HEIGHT_RES; + + float4 v; + float x = fastDiv((i+0.5f),(float)HEIGHT_RES); + float y = fastDiv((j+0.5f),(float)HEIGHT_RES); + v = CubeMapUtilsCalcVector(faceIdx, x, y); + v = normalize3( v ); + + int quantizedHeight = sample( shape, faceIdx, i, j ); + float rheight = quantizedHeight*oneOver255*shape->m_scale; + return rheight*v; +} + +float ShapeDataQueryDistance(__local const ShapeDeviceData* shape, float4 p ) +{ + if( dot3F4( p, p ) >= shape->m_scale*shape->m_scale ) return FLT_MAX; + + const float oneOver255 = 1.f/255.f; + + int faceIdx; + float x, y; + CubeMapUtilsCalcCrd( p, &faceIdx, &x, &y ); + x = (x*HEIGHT_RES) - 0.5f; + y = (y*HEIGHT_RES) - 0.5f; + + float height; + { + int xi = (int)(x); + int yi = (int)(y); + float dx = x-xi; + float dy = y-yi; + + { + int xip = min2((int)(HEIGHT_RES-1), xi+1); + int yip = min2((int)(HEIGHT_RES-1), yi+1); + + u32 xy = sample( shape, faceIdx, xi, yi ); + u32 xpy = sample( shape, faceIdx, xip, yi ); + u32 xpyp = sample( shape, faceIdx, xip, yip ); + u32 xyp = sample( shape, faceIdx, xi, yip ); + + height = (xy*(1.f-dx)+xpy*dx)*(1.f-dy) + (xyp*(1.f-dx)+xpyp*dx)*dy; + height = height*oneOver255*shape->m_scale; + + p.w = 0.f; + + height = fastLength4( p ) - height; + } + } + + return height; +} + +float ShapeDataQuerySupportHeight(__global ShapeData* shape, float4 p ) +{ + int faceIdx; + float x, y; + CubeMapUtilsCalcCrd( p, &faceIdx, &x, &y ); + x = (x*HEIGHT_RES) - 0.5f; + y = (y*HEIGHT_RES) - 0.5f; + + float height; + { + int xi = (int)(x); + int yi = (int)(y); + + { + int xip = min2((int)(HEIGHT_RES-1), xi+1); + int yip = min2((int)(HEIGHT_RES-1), yi+1); + + u32 xy = sampleSupportGlobal( shape, faceIdx, xi, yi ); + u32 xpy = sampleSupportGlobal( shape, faceIdx, xip, yi ); + u32 xpyp = sampleSupportGlobal( shape, faceIdx, xip, yip ); + u32 xyp = sampleSupportGlobal( shape, faceIdx, xi, yip ); + + height = max2( xy, max2( xpy, max2( xpyp, xyp ) ) ); + height = height/255.f*shape->m_scale; + } + } + + return height; + +} + +float4 ShapeDataQueryNormal(__global const ShapeData* shape, float4 p ) +{ + int faceIdx; + float x, y; + CubeMapUtilsCalcCrd( p, &faceIdx, &x, &y ); + x = (x*HEIGHT_RES) - 0.5f; + y = (y*HEIGHT_RES) - 0.5f; + + float4 normalOut; + { + int xi = (int)(x); + int yi = (int)(y); + + normalOut = sampleNormalGlobal( shape, faceIdx, xi, yi ); + } + return normalOut; +} + + + +// kernels + + +__kernel +__attribute__((reqd_work_group_size(WG_SIZE,1,1))) +void SupportCullingKernel( __global int2* restrict gPairsIn, __global ShapeData* gShapes, + __global BodyData* gBodies, + __global int2* gPairsOut, + counter32_t gNPairs, + ConstBuffer cb ) +{ + int gIdx = GET_GLOBAL_IDX; + if( gIdx >= cb.m_nPairs ) return; + + const float collisionMargin = cb.m_collisionMargin; + const int capacity = cb.m_capacity; + + int2 pair = gPairsIn[gIdx]; + BodyData bodyA = gBodies[pair.x]; + BodyData bodyB = gBodies[pair.y]; + int shapeAIdx = bodyA.m_shapeIdx; + int shapeBIdx = bodyB.m_shapeIdx; + + + bool collide = false; + + //only collide if one of the two bodies has a non-zero mass + if (bodyA.m_invMass==0.f && bodyB.m_invMass==0.f) + return; + + + if (bodyA.m_shapeType == SHAPE_CONVEX_HEIGHT_FIELD && bodyB.m_shapeType==SHAPE_CONVEX_HEIGHT_FIELD) + { + float4 abInA, baInB; + float4 ab = bodyB.m_pos - bodyA.m_pos; + { + abInA = qtInvRotate( bodyA.m_quat, ab ); + baInB = qtInvRotate( bodyB.m_quat, -ab ); + } + float hA = ShapeDataQuerySupportHeight( gShapes+shapeAIdx, abInA ); + float hB = ShapeDataQuerySupportHeight( gShapes+shapeBIdx, baInB ); + + float h2 = dot3F4( ab, ab ); + + collide = ( hA + hB + collisionMargin > sqrtf(h2) ); + } + + if( collide ) + { + int dstIdx; + AppendInc( gNPairs, dstIdx ); + if( dstIdx < capacity ) + gPairsOut[dstIdx] = pair; + } +} + + +#define PARALLEL_DO(execution, n) for(int ie=0; ie h[lIdx+1].y)? h[lIdx]: h[lIdx+1];\ + mem_fence( CLK_LOCAL_MEM_FENCE );\ + h[lIdx] = (h[lIdx].y > h[lIdx+2].y)? h[lIdx]: h[lIdx+2];\ + mem_fence( CLK_LOCAL_MEM_FENCE );\ + h[lIdx] = (h[lIdx].y > h[lIdx+4].y)? h[lIdx]: h[lIdx+4];\ + mem_fence( CLK_LOCAL_MEM_FENCE );\ + h[lIdx] = (h[lIdx].y > h[lIdx+8].y)? h[lIdx]: h[lIdx+8];\ + mem_fence( CLK_LOCAL_MEM_FENCE );\ + h[lIdx] = (h[lIdx].y > h[lIdx+16].y)? h[lIdx]: h[lIdx+16];\ + }} + +#define PARALLEL_REDUCE32(h) \ + {int lIdx = GET_LOCAL_IDX;\ + if( lIdx < 32 )\ + {\ + h[lIdx] += h[lIdx+1];\ + mem_fence( CLK_LOCAL_MEM_FENCE );\ + h[lIdx] += h[lIdx+2];\ + mem_fence( CLK_LOCAL_MEM_FENCE );\ + h[lIdx] += h[lIdx+4];\ + mem_fence( CLK_LOCAL_MEM_FENCE );\ + h[lIdx] += h[lIdx+8];\ + mem_fence( CLK_LOCAL_MEM_FENCE );\ + h[lIdx] += h[lIdx+16];\ + }} + + +float4 extractManifold(__local float4* p, __local float4* h, __local int* nPointsPtr, float4 nearNormal) +{ + int nPoints = *nPointsPtr; + float4 center = make_float4(0,0,0,0); + { // calculate center + nPoints = min2( nPoints, 32 ); + { + int lIdx = GET_LOCAL_IDX; + h[lIdx] = p[lIdx]; + h[lIdx] = (lIdx= nPoints ) a[ie] = make_int4(-0xfffffff, -0xfffffff, -0xfffffff, -0xfffffff); + } + } + + GROUP_LDS_BARRIER; + + { // vector reduce, h[64] + int lIdx = GET_LOCAL_IDX; + if( lIdx < 32 ) + { + h[lIdx] = max2( h[lIdx], h[lIdx+1] ); + mem_fence( CLK_LOCAL_MEM_FENCE ); + h[lIdx] = max2( h[lIdx], h[lIdx+2] ); + mem_fence( CLK_LOCAL_MEM_FENCE ); + h[lIdx] = max2( h[lIdx], h[lIdx+4] ); + mem_fence( CLK_LOCAL_MEM_FENCE ); + h[lIdx] = max2( h[lIdx], h[lIdx+8] ); + mem_fence( CLK_LOCAL_MEM_FENCE ); + h[lIdx] = max2( h[lIdx], h[lIdx+16] ); + } + } + + GROUP_LDS_BARRIER; + } + { + { // set to idx + idx[0] = (int)a[0].x & 0xff; + idx[1] = (int)a[0].y & 0xff; + idx[2] = (int)a[0].z & 0xff; + idx[3] = (int)a[0].w & 0xff; + } + + GROUP_LDS_BARRIER; + float4 selection; + if( GET_LOCAL_IDX < 4 ) selection = p[idx[GET_LOCAL_IDX]]; + + GROUP_LDS_BARRIER; + if( GET_LOCAL_IDX < 4 ) p[GET_LOCAL_IDX] = selection; + } + + + return center; +} + +void extractManifold1(__local float4* p, __local float4* h, __local int* nPointsPtr, float4 center) +{ + __local int* a = (__local int*)h; + { + GROUP_LDS_BARRIER; + float4 selection; + if( GET_LOCAL_IDX < 4 ) + { + int idx = (int)a[GET_LOCAL_IDX] & 0xff; + selection = p[idx]; + } + + GROUP_LDS_BARRIER; + if( GET_LOCAL_IDX < 4 ) p[GET_LOCAL_IDX] = selection; + } + +} + +void extractManifold2( __local float4* p0, __local int* nPointsPtr0, float4 nearNormal0, + __local float4* p1, __local int* nPointsPtr1, float4 nearNormal1, + __local float4* h, float4 centerOut[2]) +{ + + int nPoints[2]; + nPoints[0] = *nPointsPtr0; + nPoints[1] = *nPointsPtr1; + float4 center[2]; + center[0] = make_float4(0,0,0,0); + center[1] = make_float4(0,0,0,0); + { // calculate center + nPoints[0] = min2( nPoints[0], 32 ); + nPoints[1] = min2( nPoints[1], 32 ); + { + int lIdx = GET_LOCAL_IDX; + h[lIdx] = (lIdx= nPoints[setIdx] ) a[ie + setIdx*64] = make_int4(-0xfffffff, -0xfffffff, -0xfffffff, -0xfffffff); + + a[ie + 32] = make_int4(-0xfffffff, -0xfffffff, -0xfffffff, -0xfffffff); + } + } + } + GROUP_LDS_BARRIER; + + { // vector reduce, h[64] + int bIdx = GET_LOCAL_IDX/32; + int eIdx = GET_LOCAL_IDX%32; + int lIdx = eIdx + bIdx*64; + { + h[lIdx] = max2( h[lIdx], h[lIdx+1] ); + mem_fence( CLK_LOCAL_MEM_FENCE ); + h[lIdx] = max2( h[lIdx], h[lIdx+2] ); + mem_fence( CLK_LOCAL_MEM_FENCE ); + h[lIdx] = max2( h[lIdx], h[lIdx+4] ); + mem_fence( CLK_LOCAL_MEM_FENCE ); + h[lIdx] = max2( h[lIdx], h[lIdx+8] ); + mem_fence( CLK_LOCAL_MEM_FENCE ); + h[lIdx] = max2( h[lIdx], h[lIdx+16] ); + } + } + + GROUP_LDS_BARRIER; + } + __local int* a = (__local int*)h; + { + GROUP_LDS_BARRIER; + + float4 selection; + + int bIdx = GET_LOCAL_IDX/32; + int eIdx = GET_LOCAL_IDX%32; + + if( eIdx < 4 ) + { + int idx = (int)a[eIdx+64*4*bIdx] & 0xff; + selection = p0[idx+32*bIdx]; + } + + GROUP_LDS_BARRIER; + if( eIdx < 4 ) p0[eIdx+32*bIdx] = selection; + } +} + +/* +1. Query Normal +2. Fill Normal +3. A->B, B->A +*/ + +void testVtx(__local BodyData* bodyAPtr, __local BodyData* bodyBPtr, + __local ShapeDeviceData* shapeAPtr, __local ShapeDeviceData* shapeBPtr, + __local int* lNContacts, __local float4* lCPoints) +{ + int pIdx = GET_LOCAL_IDX; + float4 bodyAPos = bodyAPtr->m_pos; + float4 bodyBPos = bodyBPtr->m_pos; + Quaternion bodyAQuat = bodyAPtr->m_quat; + Quaternion bodyBQuat = bodyBPtr->m_quat; + while( pIdx < HEIGHT_RES*HEIGHT_RES*6 ) + { + float4 pInB = ShapeDataCalcSamplePoint( shapeBPtr, pIdx ); + + float4 pInW = transform( &pInB, &bodyBPos, &bodyBQuat ); +// Aabb bodyAAabb = bodyAPtr->m_aabb; +// if( AabbOverlapsPoint( &bodyAAabb, pInW ) ) + { + float4 pInA = invTransform( &pInW, &bodyAPos, &bodyAQuat ); + + float dist = ShapeDataQueryDistance( shapeAPtr, pInA ); + if( dist < 0.010f ) + { + int dstIdx = atom_add( lNContacts, 1 ); + if( dstIdx < 32 ) + { + lCPoints[ dstIdx ] = make_float4( pInA.x, pInA.y, pInA.z, dist ); + } + } + } + + pIdx += GET_GROUP_SIZE; + } +} + +void testVtx2(__local const BodyData* bodyA, __local const BodyData* bodyB, + __local const ShapeDeviceData* shapeA, __local const ShapeDeviceData* shapeB, + __local int* lNContactsA, __local float4* lCPointsA, + __local int* lNContactsB, __local float4* lCPointsB, float collisionMargin ) +{ + int pIdx = GET_LOCAL_IDX; + + while( pIdx < HEIGHT_RES*HEIGHT_RES*6*2 ) + { + __local const BodyData* bodyAPtr =( pIdx < HEIGHT_RES*HEIGHT_RES*6 )?bodyA:bodyB; + __local const BodyData* bodyBPtr =( pIdx < HEIGHT_RES*HEIGHT_RES*6 )?bodyB:bodyA; + __local const ShapeDeviceData* shapeAPtr =( pIdx < HEIGHT_RES*HEIGHT_RES*6 )?shapeA:shapeB; + __local const ShapeDeviceData* shapeBPtr =( pIdx < HEIGHT_RES*HEIGHT_RES*6 )?shapeB:shapeA; + __local int* lNContacts =( pIdx < HEIGHT_RES*HEIGHT_RES*6 )?lNContactsA:lNContactsB; + __local float4* lCPoints =( pIdx < HEIGHT_RES*HEIGHT_RES*6 )?lCPointsA:lCPointsB; + + float4 bodyAPos = bodyAPtr->m_pos; + float4 bodyBPos = bodyBPtr->m_pos; + Quaternion bodyAQuat = bodyAPtr->m_quat; + Quaternion bodyBQuat = bodyBPtr->m_quat; + + float4 pInB = ShapeDataCalcSamplePoint( shapeBPtr, pIdx%(HEIGHT_RES*HEIGHT_RES*6) ); + + float4 pInW = transform( &pInB, &bodyBPos, &bodyBQuat ); +// Aabb bodyAAabb = bodyAPtr->m_aabb; +// if( AabbOverlapsPoint( &bodyAAabb, pInW ) ) + { + float4 pInA = invTransform( &pInW, &bodyAPos, &bodyAQuat ); + + float dist = ShapeDataQueryDistance( shapeAPtr, pInA ); + if( dist < collisionMargin ) + { + int dstIdx = atom_add( lNContacts, 1 ); + if( dstIdx < 32 ) + { + lCPoints[ dstIdx ] = make_float4( pInA.x, pInA.y, pInA.z, dist ); + } + } + } + + pIdx += GET_GROUP_SIZE; + } +} + +void testVtxWithPlane(__local BodyData* bodyA, __local BodyData* bodyB, + float4 nA, __local ShapeDeviceData* shapeB, + __local int* lNContactsA, __local float4* lCPointsA, float collisionMargin) +{ + int pIdx = GET_LOCAL_IDX; + + while( pIdx < HEIGHT_RES*HEIGHT_RES*6 ) + { + __local BodyData* bodyAPtr =bodyA; + __local BodyData* bodyBPtr =bodyB; + __local ShapeDeviceData* shapeBPtr =shapeB; + __local int* lNContacts =lNContactsA; + __local float4* lCPoints =lCPointsA; + + float4 bodyAPos = bodyAPtr->m_pos; + float4 bodyBPos = bodyBPtr->m_pos; + Quaternion bodyAQuat = bodyAPtr->m_quat; + Quaternion bodyBQuat = bodyBPtr->m_quat; + + float4 pInB = ShapeDataCalcSamplePoint( shapeBPtr, pIdx%(HEIGHT_RES*HEIGHT_RES*6) ); + + float4 pInW = transform( &pInB, &bodyBPos, &bodyBQuat ); + { + float4 pInA = invTransform( &pInW, &bodyAPos, &bodyAQuat ); + + float dist = dot3w1( pInA, nA );//ShapeDataQueryDistance( shapeAPtr, pInA ); + if( dist < collisionMargin ) + { + int dstIdx = atom_add( lNContacts, 1 ); + if( dstIdx < 32 ) + { + lCPoints[ dstIdx ] = make_float4( pInA.x, pInA.y, pInA.z, dist ); + } + } + } + + pIdx += GET_GROUP_SIZE; + } +} + +#define GET_SHAPE_IDX(x) (int)((x).m_shapeIdx) + +void output(__local BodyData* bodyAPtr, __local BodyData* bodyBPtr, + __local int2* iPair, + __local int* lNContacts, __local float4* lCPoints, + float4 center, + __global ShapeData* shapeData, __global Contact4* contactsOut, float collisionMargin) +{ + if( *lNContacts != 0 ) + { + int nContacts = min2( *lNContacts, 4 ); + + __global Contact4* c = contactsOut; + + if( GET_LOCAL_IDX < nContacts ) + { + int i = GET_LOCAL_IDX; + float4 p = lCPoints[i]; + float4 bodyAPos = bodyAPtr->m_pos; + Quaternion bodyAQuat = bodyAPtr->m_quat; + + c->m_worldPos[i] = transform( &p, &bodyAPos, &bodyAQuat ); + c->m_worldPos[i].w = lCPoints[i].w - collisionMargin; + } + + if( GET_LOCAL_IDX == 0 ) + { + float4 contactNormal; + contactNormal = ShapeDataQueryNormal( &shapeData[GET_SHAPE_IDX(*bodyAPtr)], center ); + contactNormal = normalize3( qtRotate( bodyAPtr->m_quat, contactNormal ) ); + + c->m_worldNormal = contactNormal; +// c->m_restituitionCoeff = 0.f; +// c->m_frictionCoeff = 0.7f; + c->m_coeffs = (u32)(0.f*0xffff) | ((u32)(0.7f*0xffff)<<16); + GET_NPOINTS(*c) = nContacts; + c->m_bodyAPtr = iPair[0].x; + c->m_bodyBPtr = iPair[0].y; + } + } + else + { + if( GET_LOCAL_IDX == 0 ) + GET_NPOINTS(contactsOut[0]) = 0; + } +} + +// todo. make it better +void output2(__local BodyData* bodyAPtr, __local BodyData* bodyBPtr, + int pair0, int pair1, + __local int* lNContacts, __local float4* lCPoints, + float4 center, + const __global ShapeData* shapeData, __global Contact4* contactsOut, counter32_t nContactsOut, int capacity, + float collisionMargin ) +{ + int lIdx = GET_LOCAL_IDX%32; + int nContacts = min2( *lNContacts, 4 ); + + GROUP_LDS_BARRIER; + + if( lIdx == 0 && nContacts) + { + int dstIdx; + AppendInc( nContactsOut, dstIdx ); + *lNContacts = dstIdx; + + if( dstIdx >= capacity ) + *lNContacts = -1; + } + + GROUP_LDS_BARRIER; + + bool canWrite = (*lNContacts!=-1); + + if( nContacts && canWrite ) + { + __global Contact4* c = contactsOut + (*lNContacts); + + if( lIdx < nContacts ) + { + int i = lIdx; + float4 p = lCPoints[i]; + float4 bodyAPos = bodyAPtr->m_pos; + Quaternion bodyAQuat = bodyAPtr->m_quat; + + p = transform( &p, &bodyAPos, &bodyAQuat ); + p.w = lCPoints[i].w - collisionMargin; + c->m_worldPos[i] = p; + } + + if( lIdx == 0 ) + { + if( nContacts ) + { + float4 contactNormal; + contactNormal = ShapeDataQueryNormal( &shapeData[GET_SHAPE_IDX(*bodyAPtr)], center ); + contactNormal = normalize3( qtRotate( bodyAPtr->m_quat, contactNormal ) ); + + c->m_worldNormal = contactNormal; +// c->m_restituitionCoeff = 0.f; +// c->m_frictionCoeff = 0.7f; + c->m_coeffs = (u32)(0.f*0xffff) | ((u32)(0.7f*0xffff)<<16); + c->m_bodyAPtr = pair0; + c->m_bodyBPtr = pair1; + } + GET_NPOINTS(*c) = nContacts; + } + } +} + +__inline +void output2LDS(__local BodyData* bodyAPtr, __local BodyData* bodyBPtr, + int pair0, int pair1, + int lNContacts, __local float4* lCPoints, + float4 center, + const __global ShapeData* shapeData, __local Contact4* contactsOut, + float collisionMargin ) +{ + int lIdx = GET_LOCAL_IDX%32; +// int lIdx = GET_LOCAL_IDX; +// int groupIdx = 0; + + int nContacts = min2( lNContacts, 4 ); + + GROUP_LDS_BARRIER; + + if( nContacts != 0 ) + { + if( lIdx < nContacts ) + { + int i = lIdx; + float4 p = lCPoints[i]; + float4 bodyAPos = bodyAPtr->m_pos; + Quaternion bodyAQuat = bodyAPtr->m_quat; + + p = transform( &p, &bodyAPos, &bodyAQuat ); + p.w = lCPoints[i].w - collisionMargin; + contactsOut->m_worldPos[i] = p; + } + } + + if( lIdx == 0 ) + { + if( nContacts != 0 ) + { + float4 contactNormal; + contactNormal = ShapeDataQueryNormal( &shapeData[GET_SHAPE_IDX(*bodyAPtr)], center ); + contactNormal = normalize3( qtRotate( bodyAPtr->m_quat, contactNormal ) ); + + contactsOut->m_worldNormal = contactNormal; +// contactsOut->m_worldNormal = make_float4(1.5f,1.4f,1.3f,0.f); +// contactsOut->m_restituitionCoeff = 0.f; +// contactsOut->m_frictionCoeff = 0.7f; + contactsOut->m_coeffs = (u32)(0.f*0xffff) | ((u32)(0.7f*0xffff)<<16); + contactsOut->m_bodyAPtr = pair0; + contactsOut->m_bodyBPtr = pair1; + } + GET_NPOINTS(*contactsOut) = nContacts;//nContacts; + } + +// contactsOut[groupIdx].m_worldNormal = make_float4(1.5f,1.4f,1.3f,0.f); +} + +void output2_1(__local BodyData* bodyAPtr, __local BodyData* bodyBPtr, + int pair0, int pair1, + __local int* lNContacts, __local float4* lCPoints, + float4 center, float4 nA, + const __global ShapeData* shapeData, __global Contact4* contactsOut, counter32_t nContactsOut, int capacity, float collisionMargin ) +{ + int lIdx = GET_LOCAL_IDX; + int nContacts = min2( *lNContacts, 4 ); + + GROUP_LDS_BARRIER; + + if( lIdx == 0 && nContacts) + { + int dstIdx; + AppendInc( nContactsOut, dstIdx ); + *lNContacts = dstIdx; + + if( dstIdx >= capacity ) + *lNContacts = -1; + } + + GROUP_LDS_BARRIER; + + bool canWrite = (*lNContacts!=-1); + + if( nContacts && canWrite ) + { + __global Contact4* c = contactsOut + (*lNContacts); + + if( lIdx < nContacts ) + { + int i = lIdx; + float4 p = lCPoints[i]; + float4 bodyAPos = bodyAPtr->m_pos; + Quaternion bodyAQuat = bodyAPtr->m_quat; + + p = transform( &p, &bodyAPos, &bodyAQuat ); + p.w = lCPoints[i].w - collisionMargin; + c->m_worldPos[i] = p; + } + + if( lIdx == 0 ) + { + if( nContacts ) + { + float4 contactNormal; + contactNormal = nA;//ShapeDataQueryNormal( &shapeData[GET_SHAPE_IDX(*bodyAPtr)], center ); + contactNormal = normalize3( qtRotate( bodyAPtr->m_quat, contactNormal ) ); + + c->m_worldNormal = contactNormal; +// c->m_restituitionCoeff = 0.f; +// c->m_frictionCoeff = 0.7f; + c->m_coeffs = (u32)(0.f*0xffff) | ((u32)(0.7f*0xffff)<<16); + c->m_bodyAPtr = pair0; + c->m_bodyBPtr = pair1; + } + GET_NPOINTS(*c) = nContacts; + } + } +} + +__kernel +void manifold(__global float4* vIn, __global float4* vOut) +{ + __local float4 lCPoints[32]; + __local float4 lManifoldBuffer[64]; + __local int lNContacts; + __local float4 ab; + + if( GET_LOCAL_IDX<32 ) + { + lCPoints[GET_LOCAL_IDX] = vIn[GET_GLOBAL_IDX]; + } + + if( GET_LOCAL_IDX == 0 ) + { + lNContacts = 32; + ab = vIn[GET_GLOBAL_IDX]; + } + + GROUP_LDS_BARRIER; + + float4 center = extractManifold( lCPoints, lManifoldBuffer, &lNContacts, ab ); + + if( GET_LOCAL_IDX < lNContacts ) + { + vOut[4*GET_GROUP_IDX+GET_LOCAL_IDX] = lCPoints[GET_LOCAL_IDX]; + } + +} + +//#define COMBINE_REDUCTION + +__kernel +__attribute__((reqd_work_group_size(64, 1, 1))) +void NarrowphaseKernel( const __global int2* restrict pairs, const __global ShapeData* shapeData, const __global BodyData* restrict bodyDatas, + __global Contact4* restrict contactsOut, + counter32_t nContactsOut, ConstBuffer cb ) +{ + // 2.5K LDS + __local Contact4 ldsContacts[2]; + __local BodyData bodyA; + __local BodyData bodyB; + __local ShapeDeviceData shapeA; + __local ShapeDeviceData shapeB; + __local float4 lCPointsA[32*2]; + __local int lNContactsA; + __local float4* lCPointsB = lCPointsA+32; + __local int lNContactsB; +#ifdef COMBINE_REDUCTION + __local float4 lManifoldBuffer[64*2]; +#else + __local float4 lManifoldBuffer[64]; +#endif + __local int2 iPairAB; + + const int capacity = cb.m_capacity; + const float collisionMargin = cb.m_collisionMargin; + + + int pairIdx = GET_GROUP_IDX; +// for(int pairIdx = GET_GROUP_IDX; pairIdxm_height4[idx] = shapeData[ myShapeIdx ].m_height4[idx]; + + idx+=32; + } + } + + GROUP_LDS_BARRIER; + + testVtx2( &bodyA, &bodyB, &shapeA, &shapeB, &lNContactsA, lCPointsA, &lNContactsB, lCPointsB, collisionMargin ); + + GROUP_LDS_BARRIER; + + float4 ab = bodyB.m_pos - bodyA.m_pos; + float4 center[2]; + + if( lNContactsA != 0 || lNContactsB != 0 ) + { + float4 abInA; + abInA = qtInvRotate( bodyA.m_quat, ab ); + + float4 abInB; + abInB = qtInvRotate( bodyB.m_quat, ab ); + +#ifdef COMBINE_REDUCTION + extractManifold2( lCPointsA, &lNContactsA, abInA, + lCPointsB, &lNContactsB, abInB, + lManifoldBuffer, center ); +#else + if( lNContactsA != 0 ) + center[0] = extractManifold( lCPointsA, lManifoldBuffer, &lNContactsA, abInA ); + if( lNContactsB != 0 ) + center[1] = extractManifold( lCPointsB, lManifoldBuffer, &lNContactsB, abInB ); +#endif + } + + int firstSet = GET_LOCAL_IDX/32; + +/* + if( GET_LOCAL_IDX == 0 ) // for debug + { + ldsContacts[0].m_worldNormal = make_float4(-1,-1,-1,0); + ldsContacts[0].m_bodyAPtr = 0; + ldsContacts[0].m_bodyBPtr = 0; + ldsContacts[0].m_batchIdx = 111; + ldsContacts[1].m_worldNormal = make_float4(-1,-1,-1,0); + ldsContacts[1].m_bodyAPtr = 0; + ldsContacts[1].m_bodyBPtr = 0; + ldsContacts[1].m_batchIdx = 111; + } +*/ + bool doReduction = true; + if( doReduction ) + { + GROUP_LDS_BARRIER; + + output2LDS( (firstSet)?&bodyA: &bodyB, (firstSet)?&bodyB : &bodyA, + (firstSet)?iPairAB.x : iPairAB.y, (firstSet)?iPairAB.y : iPairAB.x, + (firstSet)?lNContactsA : lNContactsB, (firstSet)?lCPointsA:lCPointsB, + (firstSet)?center[0] : center[1], shapeData, (firstSet)?&ldsContacts[0]: &ldsContacts[1], collisionMargin ); + + GROUP_LDS_BARRIER; + + if( GET_LOCAL_IDX == 0 ) + { + if( lNContactsA && lNContactsB ) + { + float nDotn = dot3F4( ldsContacts[0].m_worldNormal, ldsContacts[1].m_worldNormal ); + if( nDotn < -(1.f-0.01f) ) + { + if( ldsContacts[0].m_bodyAPtr > ldsContacts[1].m_bodyAPtr ) + lNContactsA = 0; + else + lNContactsB = 0; + } + } + } + + if( GET_LOCAL_IDX == 0 ) + { + int n = lNContactsA; + if( n != 0 ) + { + int dstIdx; + AppendInc( nContactsOut, dstIdx ); + if( dstIdx < capacity ) + { int idx = 0; + contactsOut[ dstIdx ] = ldsContacts[idx]; + contactsOut[ dstIdx].m_batchIdx = pairIdx; + } + } + + n = lNContactsB; + if( n != 0 ) + { + int dstIdx; + AppendInc( nContactsOut, dstIdx ); + if( dstIdx < capacity ) + { int idx = 1; + contactsOut[ dstIdx ] = ldsContacts[idx]; + contactsOut[ dstIdx].m_batchIdx = pairIdx; + } + } + } + + GROUP_LDS_BARRIER; + } + else + { + //output2( (firstSet)?&bodyA: &bodyB, (firstSet)?&bodyB : &bodyA, + // (firstSet)?iPairAB.x : iPairAB.y, (firstSet)?iPairAB.y : iPairAB.x, + // (firstSet)?&lNContactsA : &lNContactsB, (firstSet)?lCPointsA:lCPointsB, + // (firstSet)?center[0] : center[1], shapeData, contactsOut, nContactsOut, capacity, collisionMargin ); + } + } +} + + +__kernel +__attribute__((reqd_work_group_size(64, 1, 1))) +void NarrowphaseWithPlaneKernel( const __global int2* restrict pairs, const __global ShapeData* shapeData, const __global BodyData* restrict bodyDatas, + __global Contact4* restrict contactsOut, + counter32_t nContactsOut, ConstBuffer cb ) +{ + // 2.5K LDS + __local BodyData bodyA; + __local BodyData bodyB; + __local ShapeDeviceData shapeA; + __local ShapeDeviceData shapeB; + __local float4 lCPointsA[32*2]; + __local int lNContactsA; +// __local float4* lCPointsB = lCPointsA+32; +// __local int lNContactsB; + __local float4 lManifoldBuffer[64]; + __local int2 iPairAB; + + const int capacity = cb.m_capacity; + const float collisionMargin = cb.m_collisionMargin; + + int pairIdx = GET_GROUP_IDX; + { + if( GET_LOCAL_IDX == 0 ) // load Bodies + { + int2 pair = pairs[pairIdx]; + iPairAB = make_int2(pair.x, pair.y); + bodyA = bodyDatas[ pair.x ]; + bodyB = bodyDatas[ pair.y ]; + shapeA.m_scale = shapeData[ GET_SHAPE_IDX(bodyA) ].m_scale; + shapeB.m_scale = shapeData[ GET_SHAPE_IDX(bodyB) ].m_scale; + lNContactsA = 0; +// lNContactsB = 0; + } + + GROUP_LDS_BARRIER; + + if (bodyB.m_invMass == 0.f) + return; + + // todo. can check if the shape is the same to previous one. If same, dont read + { // load shape data + int idx = GET_LOCAL_IDX%32; + int bIdx = GET_LOCAL_IDX/32; + __local ShapeDeviceData* myShape = (bIdx==0)?&shapeA: &shapeB; + int myShapeIdx = (bIdx==0)?GET_SHAPE_IDX(bodyA): GET_SHAPE_IDX(bodyB); + + while( idx < HEIGHT_RES*HEIGHT_RES*6/4 ) + { + myShape->m_height4[idx] = shapeData[ myShapeIdx ].m_height4[idx]; + + idx+=32; + } + } + + GROUP_LDS_BARRIER; + + float4 nA = make_float4(0,1,0,0); + + +// testVtx2( &bodyA, &bodyB, &shapeA, &shapeB, &lNContactsA, lCPointsA, &lNContactsB, lCPointsB ); + testVtxWithPlane( &bodyA, &bodyB, nA, &shapeB, &lNContactsA, lCPointsA, collisionMargin ); + + GROUP_LDS_BARRIER; + +// float4 ab = bodyB.m_pos - bodyA.m_pos; + float4 center[2]; + + if( lNContactsA != 0 ) + { + float4 abInA; + abInA = nA;//qtInvRotate( bodyA.m_quat, ab ); + + if( lNContactsA != 0 ) + center[0] = extractManifold( lCPointsA, lManifoldBuffer, &lNContactsA, abInA ); + } + +// int firstSet = GET_LOCAL_IDX/32; + + output2_1( &bodyA, &bodyB, + iPairAB.x, iPairAB.y, + &lNContactsA, lCPointsA, + center[0], nA, shapeData, contactsOut, nContactsOut, capacity, collisionMargin ); + } +} \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/ChNarrowphaseKernels.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/ChNarrowphaseKernels.h new file mode 100644 index 0000000..ff846cb --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/ChNarrowphaseKernels.h @@ -0,0 +1,1616 @@ +static const char* narrowphaseKernelsCL= \ +"\n" +"#pragma OPENCL EXTENSION cl_amd_printf : enable\n" +"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n" +"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n" +"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n" +"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n" +"\n" +"#ifdef cl_ext_atomic_counters_32\n" +"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n" +"#else\n" +"#define counter32_t volatile global int*\n" +"#endif\n" +"\n" +"\n" +"typedef unsigned int u32;\n" +"typedef unsigned short u16;\n" +"typedef unsigned char u8;\n" +"\n" +"#define GET_GROUP_IDX get_group_id(0)\n" +"#define GET_LOCAL_IDX get_local_id(0)\n" +"#define GET_GLOBAL_IDX get_global_id(0)\n" +"#define GET_GROUP_SIZE get_local_size(0)\n" +"#define GET_NUM_GROUPS get_num_groups(0)\n" +"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n" +"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n" +"#define AtomInc(x) atom_inc(&(x))\n" +"#define AtomInc1(x, out) out = atom_inc(&(x))\n" +"#define AppendInc(x, out) out = atomic_inc(x)\n" +"#define AtomAdd(x, value) atom_add(&(x), value)\n" +"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n" +"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n" +"\n" +"\n" +"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n" +"\n" +"#define make_float4 (float4)\n" +"#define make_float2 (float2)\n" +"#define make_uint4 (uint4)\n" +"#define make_int4 (int4)\n" +"#define make_uint2 (uint2)\n" +"#define make_int2 (int2)\n" +"\n" +"\n" +"#define max2 max\n" +"#define min2 min\n" +"\n" +"\n" +"///////////////////////////////////////\n" +"// Vector\n" +"///////////////////////////////////////\n" +"__inline\n" +"float fastDiv(float numerator, float denominator)\n" +"{\n" +" return native_divide(numerator, denominator); \n" +"// return numerator/denominator; \n" +"}\n" +"\n" +"__inline\n" +"float4 fastDiv4(float4 numerator, float4 denominator)\n" +"{\n" +" return native_divide(numerator, denominator); \n" +"}\n" +"\n" +"__inline\n" +"float fastSqrtf(float f2)\n" +"{\n" +" return native_sqrt(f2);\n" +"// return sqrt(f2);\n" +"}\n" +"\n" +"__inline\n" +"float fastRSqrt(float f2)\n" +"{\n" +" return native_rsqrt(f2);\n" +"}\n" +"\n" +"__inline\n" +"float fastLength4(float4 v)\n" +"{\n" +" return fast_length(v);\n" +"}\n" +"\n" +"__inline\n" +"float4 fastNormalize4(float4 v)\n" +"{\n" +" return fast_normalize(v);\n" +"}\n" +"\n" +"\n" +"__inline\n" +"float sqrtf(float a)\n" +"{\n" +"// return sqrt(a);\n" +" return native_sqrt(a);\n" +"}\n" +"\n" +"__inline\n" +"float4 cross3(float4 a, float4 b)\n" +"{\n" +" return cross(a,b);\n" +"}\n" +"\n" +"__inline\n" +"float dot3F4(float4 a, float4 b)\n" +"{\n" +" float4 a1 = make_float4(a.xyz,0.f);\n" +" float4 b1 = make_float4(b.xyz,0.f);\n" +" return dot(a1, b1);\n" +"}\n" +"\n" +"__inline\n" +"float length3(const float4 a)\n" +"{\n" +" return sqrtf(dot3F4(a,a));\n" +"}\n" +"\n" +"__inline\n" +"float dot4(const float4 a, const float4 b)\n" +"{\n" +" return dot( a, b );\n" +"}\n" +"\n" +"// for height\n" +"__inline\n" +"float dot3w1(const float4 point, const float4 eqn)\n" +"{\n" +" return dot3F4(point,eqn) + eqn.w;\n" +"}\n" +"\n" +"__inline\n" +"float4 normalize3(const float4 a)\n" +"{\n" +" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n" +" return fastNormalize4( n );\n" +"// float length = sqrtf(dot3F4(a, a));\n" +"// return 1.f/length * a;\n" +"}\n" +"\n" +"__inline\n" +"float4 normalize4(const float4 a)\n" +"{\n" +" float length = sqrtf(dot4(a, a));\n" +" return 1.f/length * a;\n" +"}\n" +"\n" +"__inline\n" +"float4 createEquation(const float4 a, const float4 b, const float4 c)\n" +"{\n" +" float4 eqn;\n" +" float4 ab = b-a;\n" +" float4 ac = c-a;\n" +" eqn = normalize3( cross3(ab, ac) );\n" +" eqn.w = -dot3F4(eqn,a);\n" +" return eqn;\n" +"}\n" +"\n" +"///////////////////////////////////////\n" +"// Matrix3x3\n" +"///////////////////////////////////////\n" +"\n" +"typedef struct\n" +"{\n" +" float4 m_row[3];\n" +"}Matrix3x3;\n" +"\n" +"__inline\n" +"Matrix3x3 mtZero();\n" +"\n" +"__inline\n" +"Matrix3x3 mtIdentity();\n" +"\n" +"__inline\n" +"Matrix3x3 mtTranspose(Matrix3x3 m);\n" +"\n" +"__inline\n" +"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);\n" +"\n" +"__inline\n" +"float4 mtMul1(Matrix3x3 a, float4 b);\n" +"\n" +"__inline\n" +"float4 mtMul3(float4 a, Matrix3x3 b);\n" +"\n" +"__inline\n" +"Matrix3x3 mtZero()\n" +"{\n" +" Matrix3x3 m;\n" +" m.m_row[0] = (float4)(0.f);\n" +" m.m_row[1] = (float4)(0.f);\n" +" m.m_row[2] = (float4)(0.f);\n" +" return m;\n" +"}\n" +"\n" +"__inline\n" +"Matrix3x3 mtIdentity()\n" +"{\n" +" Matrix3x3 m;\n" +" m.m_row[0] = (float4)(1,0,0,0);\n" +" m.m_row[1] = (float4)(0,1,0,0);\n" +" m.m_row[2] = (float4)(0,0,1,0);\n" +" return m;\n" +"}\n" +"\n" +"__inline\n" +"Matrix3x3 mtTranspose(Matrix3x3 m)\n" +"{\n" +" Matrix3x3 out;\n" +" out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n" +" out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n" +" out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n" +" return out;\n" +"}\n" +"\n" +"__inline\n" +"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)\n" +"{\n" +" Matrix3x3 transB;\n" +" transB = mtTranspose( b );\n" +" Matrix3x3 ans;\n" +" // why this doesn't run when 0ing in the for{}\n" +" a.m_row[0].w = 0.f;\n" +" a.m_row[1].w = 0.f;\n" +" a.m_row[2].w = 0.f;\n" +" for(int i=0; i<3; i++)\n" +" {\n" +"// a.m_row[i].w = 0.f;\n" +" ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);\n" +" ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);\n" +" ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);\n" +" ans.m_row[i].w = 0.f;\n" +" }\n" +" return ans;\n" +"}\n" +"\n" +"__inline\n" +"float4 mtMul1(Matrix3x3 a, float4 b)\n" +"{\n" +" float4 ans;\n" +" ans.x = dot3F4( a.m_row[0], b );\n" +" ans.y = dot3F4( a.m_row[1], b );\n" +" ans.z = dot3F4( a.m_row[2], b );\n" +" ans.w = 0.f;\n" +" return ans;\n" +"}\n" +"\n" +"__inline\n" +"float4 mtMul3(float4 a, Matrix3x3 b)\n" +"{\n" +" float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n" +" float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n" +" float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n" +"\n" +" float4 ans;\n" +" ans.x = dot3F4( a, colx );\n" +" ans.y = dot3F4( a, coly );\n" +" ans.z = dot3F4( a, colz );\n" +" return ans;\n" +"}\n" +"\n" +"///////////////////////////////////////\n" +"// Quaternion\n" +"///////////////////////////////////////\n" +"\n" +"typedef float4 Quaternion;\n" +"\n" +"__inline\n" +"Quaternion qtMul(Quaternion a, Quaternion b);\n" +"\n" +"__inline\n" +"Quaternion qtNormalize(Quaternion in);\n" +"\n" +"__inline\n" +"float4 qtRotate(Quaternion q, float4 vec);\n" +"\n" +"__inline\n" +"Quaternion qtInvert(Quaternion q);\n" +"\n" +"__inline\n" +"Matrix3x3 qtGetRotationMatrix(Quaternion q);\n" +"\n" +"\n" +"\n" +"__inline\n" +"Quaternion qtMul(Quaternion a, Quaternion b)\n" +"{\n" +" Quaternion ans;\n" +" ans = cross3( a, b );\n" +" ans += a.w*b+b.w*a;\n" +"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n" +" ans.w = a.w*b.w - dot3F4(a, b);\n" +" return ans;\n" +"}\n" +"\n" +"__inline\n" +"Quaternion qtNormalize(Quaternion in)\n" +"{\n" +" return fastNormalize4(in);\n" +"// in /= length( in );\n" +"// return in;\n" +"}\n" +"__inline\n" +"float4 qtRotate(Quaternion q, float4 vec)\n" +"{\n" +" Quaternion qInv = qtInvert( q );\n" +" float4 vcpy = vec;\n" +" vcpy.w = 0.f;\n" +" float4 out = qtMul(qtMul(q,vcpy),qInv);\n" +" return out;\n" +"}\n" +"\n" +"__inline\n" +"Quaternion qtInvert(Quaternion q)\n" +"{\n" +" return (Quaternion)(-q.xyz, q.w);\n" +"}\n" +"\n" +"__inline\n" +"float4 qtInvRotate(const Quaternion q, float4 vec)\n" +"{\n" +" return qtRotate( qtInvert( q ), vec );\n" +"}\n" +"\n" +"__inline\n" +"Matrix3x3 qtGetRotationMatrix(Quaternion quat)\n" +"{\n" +" float4 quat2 = (float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n" +" Matrix3x3 out;\n" +"\n" +" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n" +" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n" +" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n" +" out.m_row[0].w = 0.f;\n" +"\n" +" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n" +" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n" +" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n" +" out.m_row[1].w = 0.f;\n" +"\n" +" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n" +" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n" +" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n" +" out.m_row[2].w = 0.f;\n" +"\n" +" return out;\n" +"}\n" +"\n" +"\n" +"#define WG_SIZE 64\n" +"#define HEIGHT_RES 4\n" +"#define SHAPE_CONVEX_HEIGHT_FIELD 1//keep this in sync with AdlCollisionShape.h!\n" +"\n" +"typedef struct\n" +"{\n" +" float4 m_normal[HEIGHT_RES*HEIGHT_RES*6];\n" +" u32 m_height4[HEIGHT_RES*HEIGHT_RES*6];\n" +" u32 m_supportHeight4[HEIGHT_RES*HEIGHT_RES*6];\n" +"\n" +" float m_scale;\n" +" float m_padding0;\n" +" float m_padding1;\n" +" float m_padding2;\n" +"} ShapeData;\n" +"\n" +"typedef struct\n" +"{\n" +" u32 m_height4[HEIGHT_RES*HEIGHT_RES*6/4];\n" +"\n" +" float m_scale;\n" +"} ShapeDeviceData;\n" +"\n" +"typedef struct\n" +"{\n" +" float4 m_pos;\n" +" float4 m_quat;\n" +" float4 m_linVel;\n" +" float4 m_angVel;\n" +"\n" +" u32 m_shapeIdx;\n" +" u32 m_shapeType;\n" +" \n" +" float m_invMass;\n" +" float m_restituitionCoeff;\n" +" float m_frictionCoeff;\n" +"} BodyData;\n" +"\n" +"typedef struct\n" +"{\n" +" float4 m_worldPos[4];\n" +" float4 m_worldNormal; // w: m_nPoints\n" +"// float m_restituitionCoeff;\n" +"// float m_frictionCoeff;\n" +" u32 m_coeffs;\n" +" u32 m_batchIdx;\n" +"// int m_nPoints;\n" +"// int m_padding0;\n" +"\n" +" u32 m_bodyAPtr;//x:m_bodyAPtr, y:m_bodyBPtr\n" +" u32 m_bodyBPtr;\n" +"} Contact4;\n" +"\n" +"#define GET_NPOINTS(x) (x).m_worldNormal.w\n" +"\n" +"\n" +"typedef struct\n" +"{\n" +" int m_nPairs;\n" +" float m_collisionMargin;\n" +" int m_capacity;\n" +" int m_paddings[1];\n" +"} ConstBuffer;\n" +"\n" +"__inline\n" +"float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n" +"{\n" +" return qtRotate( *orientation, *p ) + (*translation);\n" +"}\n" +"\n" +"__inline\n" +"float4 invTransform(const float4* p, const float4* translation, const Quaternion* orientation)\n" +"{\n" +" return qtRotate( qtInvert( *orientation ), (*p)-(*translation) ); // use qtInvRotate\n" +"}\n" +"\n" +"void CubeMapUtilsCalcCrd(const float4 p, int* faceIdxOut, float* x, float* y)\n" +"{\n" +" {\n" +" int idx;\n" +" float r2[] = {p.x*p.x, p.y*p.y, p.z*p.z};\n" +"\n" +" if (r2[1]>r2[0])\n" +" {\n" +" if (r2[2]>r2[1])\n" +" {\n" +" idx = 2;\n" +" \n" +" } else\n" +" {\n" +" idx = 1;\n" +" }\n" +" \n" +" } else\n" +" {\n" +" if (r2[2]>r2[0])\n" +" {\n" +" idx = 2;\n" +" } else\n" +" {\n" +" idx = 0;\n" +" }\n" +" }\n" +"\n" +" *faceIdxOut = (idx*2);\n" +"//==\n" +" float4 abs = make_float4( fabs(p.x), fabs(p.y), fabs(p.z), 0.f );\n" +"\n" +" float d;\n" +" if( idx == 0 )\n" +" {\n" +" *x = p.y;\n" +" *y = p.z;\n" +" d = abs.x;\n" +" *faceIdxOut += (p.x < 0.f)? 0: 1.f;\n" +" }\n" +" else if( idx == 1 )\n" +" {\n" +" *x = p.z;\n" +" *y = p.x;\n" +" d = abs.y;\n" +" *faceIdxOut += (p.y < 0.f)? 0: 1.f;\n" +" }\n" +" else\n" +" {\n" +" *x = p.x;\n" +" *y = p.y;\n" +" d = abs.z;\n" +" *faceIdxOut += (p.z < 0.f)? 0: 1.f;\n" +" }\n" +"\n" +" float dInv = (d==0.f)? 0.f: fastDiv(1.f,d);\n" +" *x = (*x*dInv+1.f)*0.5f;\n" +" *y = (*y*dInv+1.f)*0.5f;\n" +" }\n" +"}\n" +"\n" +"float4 CubeMapUtilsCalcVector(int faceIdx, float x, float y)\n" +"{\n" +" int dir = faceIdx/2;\n" +" float z = (faceIdx%2 == 0)? -1.f:1.f;\n" +"\n" +" x = x*2.f-1.f;\n" +" y = y*2.f-1.f;\n" +" \n" +" if( dir == 0 )\n" +" {\n" +" return make_float4(z, x, y, 0.f);\n" +" }\n" +" else if( dir == 1 )\n" +" {\n" +" return make_float4(y,z,x, 0.f);\n" +" }\n" +" else\n" +" {\n" +" return make_float4(x,y,z, 0.f);\n" +" }\n" +"}\n" +"\n" +"typedef int Face;\n" +"\n" +"u32 sample(__local ShapeDeviceData* shape, int face, int x, int y)\n" +"{\n" +"\n" +" int idx = HEIGHT_RES*HEIGHT_RES*face + x + y*HEIGHT_RES;\n" +" __local u8* height = (__local u8*)shape->m_height4;\n" +" return height[idx];\n" +"}\n" +"\n" +"u32 sampleSupportGlobal(__global ShapeData* shape, int face, int x, int y)\n" +"{\n" +"\n" +" int idx = HEIGHT_RES*HEIGHT_RES*face + x + y*HEIGHT_RES;\n" +" __global u8* height = (__global u8*)shape->m_supportHeight4;\n" +" return height[idx];\n" +"}\n" +"\n" +"float4 sampleNormal(__local ShapeData* shape, int face, int x, int y)\n" +"{\n" +" return shape->m_normal[HEIGHT_RES*HEIGHT_RES*face + x + y*HEIGHT_RES];\n" +"}\n" +"\n" +"float4 sampleNormalGlobal(const __global ShapeData* shape, int face, int x, int y)\n" +"{\n" +" return shape->m_normal[HEIGHT_RES*HEIGHT_RES*face + x + y*HEIGHT_RES];\n" +"}\n" +"\n" +"float4 ShapeDataCalcSamplePoint( __local const ShapeDeviceData* shape, int sIdx )//u8 height, int sIdx, float scale )\n" +"{\n" +" const float oneOver255 = 1.f/255.f;\n" +"\n" +" int faceIdx = fastDiv(sIdx,(HEIGHT_RES*HEIGHT_RES));\n" +" int r = (sIdx%(HEIGHT_RES*HEIGHT_RES));\n" +" int i = r/HEIGHT_RES;\n" +" int j = r%HEIGHT_RES;\n" +"\n" +" float4 v;\n" +" float x = fastDiv((i+0.5f),(float)HEIGHT_RES);\n" +" float y = fastDiv((j+0.5f),(float)HEIGHT_RES);\n" +" v = CubeMapUtilsCalcVector(faceIdx, x, y);\n" +" v = normalize3( v );\n" +"\n" +" int quantizedHeight = sample( shape, faceIdx, i, j );\n" +" float rheight = quantizedHeight*oneOver255*shape->m_scale;\n" +" return rheight*v;\n" +"}\n" +"\n" +"float ShapeDataQueryDistance(__local const ShapeDeviceData* shape, float4 p )\n" +"{\n" +" if( dot3F4( p, p ) >= shape->m_scale*shape->m_scale ) return FLT_MAX;\n" +"\n" +" const float oneOver255 = 1.f/255.f;\n" +"\n" +" int faceIdx;\n" +" float x, y;\n" +" CubeMapUtilsCalcCrd( p, &faceIdx, &x, &y );\n" +" x = (x*HEIGHT_RES) - 0.5f;\n" +" y = (y*HEIGHT_RES) - 0.5f;\n" +"\n" +" float height;\n" +" {\n" +" int xi = (int)(x);\n" +" int yi = (int)(y);\n" +" float dx = x-xi;\n" +" float dy = y-yi;\n" +"\n" +" {\n" +" int xip = min2((int)(HEIGHT_RES-1), xi+1);\n" +" int yip = min2((int)(HEIGHT_RES-1), yi+1);\n" +"\n" +" u32 xy = sample( shape, faceIdx, xi, yi );\n" +" u32 xpy = sample( shape, faceIdx, xip, yi );\n" +" u32 xpyp = sample( shape, faceIdx, xip, yip );\n" +" u32 xyp = sample( shape, faceIdx, xi, yip );\n" +"\n" +" height = (xy*(1.f-dx)+xpy*dx)*(1.f-dy) + (xyp*(1.f-dx)+xpyp*dx)*dy;\n" +" height = height*oneOver255*shape->m_scale;\n" +"\n" +" p.w = 0.f;\n" +"\n" +" height = fastLength4( p ) - height;\n" +" }\n" +" }\n" +"\n" +" return height;\n" +"}\n" +"\n" +"float ShapeDataQuerySupportHeight(__global ShapeData* shape, float4 p )\n" +"{\n" +" int faceIdx;\n" +" float x, y;\n" +" CubeMapUtilsCalcCrd( p, &faceIdx, &x, &y );\n" +" x = (x*HEIGHT_RES) - 0.5f;\n" +" y = (y*HEIGHT_RES) - 0.5f;\n" +"\n" +" float height;\n" +" {\n" +" int xi = (int)(x);\n" +" int yi = (int)(y);\n" +"\n" +" {\n" +" int xip = min2((int)(HEIGHT_RES-1), xi+1);\n" +" int yip = min2((int)(HEIGHT_RES-1), yi+1);\n" +"\n" +" u32 xy = sampleSupportGlobal( shape, faceIdx, xi, yi );\n" +" u32 xpy = sampleSupportGlobal( shape, faceIdx, xip, yi );\n" +" u32 xpyp = sampleSupportGlobal( shape, faceIdx, xip, yip );\n" +" u32 xyp = sampleSupportGlobal( shape, faceIdx, xi, yip );\n" +"\n" +" height = max2( xy, max2( xpy, max2( xpyp, xyp ) ) );\n" +" height = height/255.f*shape->m_scale;\n" +" }\n" +" }\n" +"\n" +" return height;\n" +"\n" +"}\n" +"\n" +"float4 ShapeDataQueryNormal(__global const ShapeData* shape, float4 p )\n" +"{\n" +" int faceIdx;\n" +" float x, y;\n" +" CubeMapUtilsCalcCrd( p, &faceIdx, &x, &y );\n" +" x = (x*HEIGHT_RES) - 0.5f;\n" +" y = (y*HEIGHT_RES) - 0.5f;\n" +"\n" +" float4 normalOut;\n" +" {\n" +" int xi = (int)(x);\n" +" int yi = (int)(y);\n" +"\n" +" normalOut = sampleNormalGlobal( shape, faceIdx, xi, yi );\n" +" }\n" +" return normalOut;\n" +"}\n" +"\n" +"\n" +"\n" +"// kernels\n" +"\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n" +"void SupportCullingKernel( __global int2* restrict gPairsIn, __global ShapeData* gShapes, \n" +" __global BodyData* gBodies, \n" +" __global int2* gPairsOut, \n" +" counter32_t gNPairs,\n" +" ConstBuffer cb )\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +" if( gIdx >= cb.m_nPairs ) return;\n" +"\n" +" const float collisionMargin = cb.m_collisionMargin;\n" +" const int capacity = cb.m_capacity;\n" +"\n" +" int2 pair = gPairsIn[gIdx];\n" +" BodyData bodyA = gBodies[pair.x];\n" +" BodyData bodyB = gBodies[pair.y];\n" +" int shapeAIdx = bodyA.m_shapeIdx;\n" +" int shapeBIdx = bodyB.m_shapeIdx;\n" +"\n" +"\n" +" bool collide = false;\n" +" \n" +" //only collide if one of the two bodies has a non-zero mass\n" +" if (bodyA.m_invMass==0.f && bodyB.m_invMass==0.f)\n" +" return;\n" +" \n" +" \n" +" if (bodyA.m_shapeType == SHAPE_CONVEX_HEIGHT_FIELD && bodyB.m_shapeType==SHAPE_CONVEX_HEIGHT_FIELD)\n" +" {\n" +" float4 abInA, baInB;\n" +" float4 ab = bodyB.m_pos - bodyA.m_pos;\n" +" {\n" +" abInA = qtInvRotate( bodyA.m_quat, ab );\n" +" baInB = qtInvRotate( bodyB.m_quat, -ab );\n" +" }\n" +" float hA = ShapeDataQuerySupportHeight( gShapes+shapeAIdx, abInA );\n" +" float hB = ShapeDataQuerySupportHeight( gShapes+shapeBIdx, baInB );\n" +"\n" +" float h2 = dot3F4( ab, ab );\n" +"\n" +" collide = ( hA + hB + collisionMargin > sqrtf(h2) );\n" +" }\n" +"\n" +" if( collide )\n" +" {\n" +" int dstIdx;\n" +" AppendInc( gNPairs, dstIdx );\n" +" if( dstIdx < capacity )\n" +" gPairsOut[dstIdx] = pair;\n" +" }\n" +"}\n" +"\n" +"\n" +"#define PARALLEL_DO(execution, n) for(int ie=0; ie h[lIdx+1].y)? h[lIdx]: h[lIdx+1];" +" mem_fence( CLK_LOCAL_MEM_FENCE );" +" h[lIdx] = (h[lIdx].y > h[lIdx+2].y)? h[lIdx]: h[lIdx+2];" +" mem_fence( CLK_LOCAL_MEM_FENCE );" +" h[lIdx] = (h[lIdx].y > h[lIdx+4].y)? h[lIdx]: h[lIdx+4];" +" mem_fence( CLK_LOCAL_MEM_FENCE );" +" h[lIdx] = (h[lIdx].y > h[lIdx+8].y)? h[lIdx]: h[lIdx+8];" +" mem_fence( CLK_LOCAL_MEM_FENCE );" +" h[lIdx] = (h[lIdx].y > h[lIdx+16].y)? h[lIdx]: h[lIdx+16];" +" }}\n" +"\n" +"#define PARALLEL_REDUCE32(h) " +" {int lIdx = GET_LOCAL_IDX;" +" if( lIdx < 32 )" +" {" +" h[lIdx] += h[lIdx+1];" +" mem_fence( CLK_LOCAL_MEM_FENCE );" +" h[lIdx] += h[lIdx+2];" +" mem_fence( CLK_LOCAL_MEM_FENCE );" +" h[lIdx] += h[lIdx+4];" +" mem_fence( CLK_LOCAL_MEM_FENCE );" +" h[lIdx] += h[lIdx+8];" +" mem_fence( CLK_LOCAL_MEM_FENCE );" +" h[lIdx] += h[lIdx+16];" +" }}\n" +"\n" +"\n" +"float4 extractManifold(__local float4* p, __local float4* h, __local int* nPointsPtr, float4 nearNormal)\n" +"{\n" +" int nPoints = *nPointsPtr;\n" +" float4 center = make_float4(0,0,0,0);\n" +" { // calculate center\n" +" nPoints = min2( nPoints, 32 );\n" +" {\n" +" int lIdx = GET_LOCAL_IDX;\n" +" h[lIdx] = p[lIdx];\n" +" h[lIdx] = (lIdx= nPoints ) a[ie] = make_int4(-0xfffffff, -0xfffffff, -0xfffffff, -0xfffffff);\n" +" }\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" { // vector reduce, h[64]\n" +" int lIdx = GET_LOCAL_IDX;\n" +" if( lIdx < 32 )\n" +" {\n" +" h[lIdx] = max2( h[lIdx], h[lIdx+1] );\n" +" mem_fence( CLK_LOCAL_MEM_FENCE );\n" +" h[lIdx] = max2( h[lIdx], h[lIdx+2] );\n" +" mem_fence( CLK_LOCAL_MEM_FENCE );\n" +" h[lIdx] = max2( h[lIdx], h[lIdx+4] );\n" +" mem_fence( CLK_LOCAL_MEM_FENCE );\n" +" h[lIdx] = max2( h[lIdx], h[lIdx+8] );\n" +" mem_fence( CLK_LOCAL_MEM_FENCE );\n" +" h[lIdx] = max2( h[lIdx], h[lIdx+16] );\n" +" }\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" }\n" +" {\n" +" { // set to idx\n" +" idx[0] = (int)a[0].x & 0xff;\n" +" idx[1] = (int)a[0].y & 0xff;\n" +" idx[2] = (int)a[0].z & 0xff;\n" +" idx[3] = (int)a[0].w & 0xff;\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" float4 selection;\n" +" if( GET_LOCAL_IDX < 4 ) selection = p[idx[GET_LOCAL_IDX]];\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" if( GET_LOCAL_IDX < 4 ) p[GET_LOCAL_IDX] = selection;\n" +" }\n" +"\n" +"\n" +" return center;\n" +"}\n" +"\n" +"void extractManifold1(__local float4* p, __local float4* h, __local int* nPointsPtr, float4 center)\n" +"{\n" +" __local int* a = (__local int*)h;\n" +" {\n" +" GROUP_LDS_BARRIER;\n" +" float4 selection;\n" +" if( GET_LOCAL_IDX < 4 )\n" +" {\n" +" int idx = (int)a[GET_LOCAL_IDX] & 0xff;\n" +" selection = p[idx];\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" if( GET_LOCAL_IDX < 4 ) p[GET_LOCAL_IDX] = selection;\n" +" }\n" +"\n" +"}\n" +"\n" +"void extractManifold2( __local float4* p0, __local int* nPointsPtr0, float4 nearNormal0,\n" +" __local float4* p1, __local int* nPointsPtr1, float4 nearNormal1,\n" +" __local float4* h, float4 centerOut[2])\n" +"{\n" +"\n" +" int nPoints[2];\n" +" nPoints[0] = *nPointsPtr0;\n" +" nPoints[1] = *nPointsPtr1;\n" +" float4 center[2];\n" +" center[0] = make_float4(0,0,0,0);\n" +" center[1] = make_float4(0,0,0,0);\n" +" { // calculate center\n" +" nPoints[0] = min2( nPoints[0], 32 );\n" +" nPoints[1] = min2( nPoints[1], 32 );\n" +" {\n" +" int lIdx = GET_LOCAL_IDX;\n" +" h[lIdx] = (lIdx= nPoints[setIdx] ) a[ie + setIdx*64] = make_int4(-0xfffffff, -0xfffffff, -0xfffffff, -0xfffffff);\n" +"\n" +" a[ie + 32] = make_int4(-0xfffffff, -0xfffffff, -0xfffffff, -0xfffffff);\n" +" }\n" +" }\n" +" }\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" { // vector reduce, h[64]\n" +" int bIdx = GET_LOCAL_IDX/32;\n" +" int eIdx = GET_LOCAL_IDX%32;\n" +" int lIdx = eIdx + bIdx*64;\n" +" {\n" +" h[lIdx] = max2( h[lIdx], h[lIdx+1] );\n" +" mem_fence( CLK_LOCAL_MEM_FENCE );\n" +" h[lIdx] = max2( h[lIdx], h[lIdx+2] );\n" +" mem_fence( CLK_LOCAL_MEM_FENCE );\n" +" h[lIdx] = max2( h[lIdx], h[lIdx+4] );\n" +" mem_fence( CLK_LOCAL_MEM_FENCE );\n" +" h[lIdx] = max2( h[lIdx], h[lIdx+8] );\n" +" mem_fence( CLK_LOCAL_MEM_FENCE );\n" +" h[lIdx] = max2( h[lIdx], h[lIdx+16] );\n" +" }\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" }\n" +" __local int* a = (__local int*)h;\n" +" {\n" +" GROUP_LDS_BARRIER;\n" +" \n" +" float4 selection;\n" +"\n" +" int bIdx = GET_LOCAL_IDX/32;\n" +" int eIdx = GET_LOCAL_IDX%32;\n" +"\n" +" if( eIdx < 4 )\n" +" {\n" +" int idx = (int)a[eIdx+64*4*bIdx] & 0xff;\n" +" selection = p0[idx+32*bIdx];\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" if( eIdx < 4 ) p0[eIdx+32*bIdx] = selection;\n" +" }\n" +"}\n" +"\n" +"/*\n" +"1. Query Normal\n" +"2. Fill Normal\n" +"3. A->B, B->A\n" +"*/\n" +"\n" +"void testVtx(__local BodyData* bodyAPtr, __local BodyData* bodyBPtr,\n" +" __local ShapeDeviceData* shapeAPtr, __local ShapeDeviceData* shapeBPtr,\n" +" __local int* lNContacts, __local float4* lCPoints)\n" +"{\n" +" int pIdx = GET_LOCAL_IDX;\n" +" float4 bodyAPos = bodyAPtr->m_pos;\n" +" float4 bodyBPos = bodyBPtr->m_pos;\n" +" Quaternion bodyAQuat = bodyAPtr->m_quat;\n" +" Quaternion bodyBQuat = bodyBPtr->m_quat;\n" +" while( pIdx < HEIGHT_RES*HEIGHT_RES*6 )\n" +" {\n" +" float4 pInB = ShapeDataCalcSamplePoint( shapeBPtr, pIdx );\n" +"\n" +" float4 pInW = transform( &pInB, &bodyBPos, &bodyBQuat );\n" +"// Aabb bodyAAabb = bodyAPtr->m_aabb;\n" +"// if( AabbOverlapsPoint( &bodyAAabb, pInW ) )\n" +" {\n" +" float4 pInA = invTransform( &pInW, &bodyAPos, &bodyAQuat );\n" +"\n" +" float dist = ShapeDataQueryDistance( shapeAPtr, pInA );\n" +" if( dist < 0.010f )\n" +" {\n" +" int dstIdx = atom_add( lNContacts, 1 );\n" +" if( dstIdx < 32 )\n" +" {\n" +" lCPoints[ dstIdx ] = make_float4( pInA.x, pInA.y, pInA.z, dist );\n" +" }\n" +" }\n" +" }\n" +"\n" +" pIdx += GET_GROUP_SIZE;\n" +" }\n" +"}\n" +"\n" +"void testVtx2(__local const BodyData* bodyA, __local const BodyData* bodyB,\n" +" __local const ShapeDeviceData* shapeA, __local const ShapeDeviceData* shapeB,\n" +" __local int* lNContactsA, __local float4* lCPointsA,\n" +" __local int* lNContactsB, __local float4* lCPointsB, float collisionMargin )\n" +"{\n" +" int pIdx = GET_LOCAL_IDX;\n" +"\n" +" while( pIdx < HEIGHT_RES*HEIGHT_RES*6*2 )\n" +" {\n" +" __local const BodyData* bodyAPtr =( pIdx < HEIGHT_RES*HEIGHT_RES*6 )?bodyA:bodyB;\n" +" __local const BodyData* bodyBPtr =( pIdx < HEIGHT_RES*HEIGHT_RES*6 )?bodyB:bodyA;\n" +" __local const ShapeDeviceData* shapeAPtr =( pIdx < HEIGHT_RES*HEIGHT_RES*6 )?shapeA:shapeB;\n" +" __local const ShapeDeviceData* shapeBPtr =( pIdx < HEIGHT_RES*HEIGHT_RES*6 )?shapeB:shapeA;\n" +" __local int* lNContacts =( pIdx < HEIGHT_RES*HEIGHT_RES*6 )?lNContactsA:lNContactsB;\n" +" __local float4* lCPoints =( pIdx < HEIGHT_RES*HEIGHT_RES*6 )?lCPointsA:lCPointsB;\n" +"\n" +" float4 bodyAPos = bodyAPtr->m_pos;\n" +" float4 bodyBPos = bodyBPtr->m_pos;\n" +" Quaternion bodyAQuat = bodyAPtr->m_quat;\n" +" Quaternion bodyBQuat = bodyBPtr->m_quat;\n" +"\n" +" float4 pInB = ShapeDataCalcSamplePoint( shapeBPtr, pIdx%(HEIGHT_RES*HEIGHT_RES*6) );\n" +"\n" +" float4 pInW = transform( &pInB, &bodyBPos, &bodyBQuat );\n" +"// Aabb bodyAAabb = bodyAPtr->m_aabb;\n" +"// if( AabbOverlapsPoint( &bodyAAabb, pInW ) )\n" +" {\n" +" float4 pInA = invTransform( &pInW, &bodyAPos, &bodyAQuat );\n" +"\n" +" float dist = ShapeDataQueryDistance( shapeAPtr, pInA );\n" +" if( dist < collisionMargin )\n" +" {\n" +" int dstIdx = atom_add( lNContacts, 1 );\n" +" if( dstIdx < 32 )\n" +" {\n" +" lCPoints[ dstIdx ] = make_float4( pInA.x, pInA.y, pInA.z, dist );\n" +" }\n" +" }\n" +" }\n" +"\n" +" pIdx += GET_GROUP_SIZE;\n" +" }\n" +"}\n" +"\n" +"void testVtxWithPlane(__local BodyData* bodyA, __local BodyData* bodyB,\n" +" float4 nA, __local ShapeDeviceData* shapeB,\n" +" __local int* lNContactsA, __local float4* lCPointsA, float collisionMargin)\n" +"{\n" +" int pIdx = GET_LOCAL_IDX;\n" +"\n" +" while( pIdx < HEIGHT_RES*HEIGHT_RES*6 )\n" +" {\n" +" __local BodyData* bodyAPtr =bodyA;\n" +" __local BodyData* bodyBPtr =bodyB;\n" +" __local ShapeDeviceData* shapeBPtr =shapeB;\n" +" __local int* lNContacts =lNContactsA;\n" +" __local float4* lCPoints =lCPointsA;\n" +"\n" +" float4 bodyAPos = bodyAPtr->m_pos;\n" +" float4 bodyBPos = bodyBPtr->m_pos;\n" +" Quaternion bodyAQuat = bodyAPtr->m_quat;\n" +" Quaternion bodyBQuat = bodyBPtr->m_quat;\n" +"\n" +" float4 pInB = ShapeDataCalcSamplePoint( shapeBPtr, pIdx%(HEIGHT_RES*HEIGHT_RES*6) );\n" +"\n" +" float4 pInW = transform( &pInB, &bodyBPos, &bodyBQuat );\n" +" {\n" +" float4 pInA = invTransform( &pInW, &bodyAPos, &bodyAQuat );\n" +"\n" +" float dist = dot3w1( pInA, nA );//ShapeDataQueryDistance( shapeAPtr, pInA );\n" +" if( dist < collisionMargin )\n" +" {\n" +" int dstIdx = atom_add( lNContacts, 1 );\n" +" if( dstIdx < 32 )\n" +" {\n" +" lCPoints[ dstIdx ] = make_float4( pInA.x, pInA.y, pInA.z, dist );\n" +" }\n" +" }\n" +" }\n" +"\n" +" pIdx += GET_GROUP_SIZE;\n" +" }\n" +"}\n" +"\n" +"#define GET_SHAPE_IDX(x) (int)((x).m_shapeIdx)\n" +"\n" +"void output(__local BodyData* bodyAPtr, __local BodyData* bodyBPtr,\n" +" __local int2* iPair,\n" +" __local int* lNContacts, __local float4* lCPoints,\n" +" float4 center, \n" +" __global ShapeData* shapeData, __global Contact4* contactsOut, float collisionMargin)\n" +"{\n" +" if( *lNContacts != 0 )\n" +" {\n" +" int nContacts = min2( *lNContacts, 4 );\n" +"\n" +" __global Contact4* c = contactsOut;\n" +"\n" +" if( GET_LOCAL_IDX < nContacts )\n" +" {\n" +" int i = GET_LOCAL_IDX;\n" +" float4 p = lCPoints[i];\n" +" float4 bodyAPos = bodyAPtr->m_pos;\n" +" Quaternion bodyAQuat = bodyAPtr->m_quat;\n" +"\n" +" c->m_worldPos[i] = transform( &p, &bodyAPos, &bodyAQuat );\n" +" c->m_worldPos[i].w = lCPoints[i].w - collisionMargin;\n" +" }\n" +"\n" +" if( GET_LOCAL_IDX == 0 )\n" +" {\n" +" float4 contactNormal;\n" +" contactNormal = ShapeDataQueryNormal( &shapeData[GET_SHAPE_IDX(*bodyAPtr)], center );\n" +" contactNormal = normalize3( qtRotate( bodyAPtr->m_quat, contactNormal ) );\n" +"\n" +" c->m_worldNormal = contactNormal;\n" +"// c->m_restituitionCoeff = 0.f;\n" +"// c->m_frictionCoeff = 0.7f;\n" +" c->m_coeffs = (u32)(0.f*0xffff) | ((u32)(0.7f*0xffff)<<16);\n" +" GET_NPOINTS(*c) = nContacts;\n" +" c->m_bodyAPtr = iPair[0].x;\n" +" c->m_bodyBPtr = iPair[0].y;\n" +" }\n" +" }\n" +" else\n" +" {\n" +" if( GET_LOCAL_IDX == 0 )\n" +" GET_NPOINTS(contactsOut[0]) = 0;\n" +" }\n" +"}\n" +"\n" +"// todo. make it better\n" +"void output2(__local BodyData* bodyAPtr, __local BodyData* bodyBPtr,\n" +" int pair0, int pair1,\n" +" __local int* lNContacts, __local float4* lCPoints,\n" +" float4 center, \n" +" const __global ShapeData* shapeData, __global Contact4* contactsOut, counter32_t nContactsOut, int capacity,\n" +" float collisionMargin )\n" +"{\n" +" int lIdx = GET_LOCAL_IDX%32;\n" +" int nContacts = min2( *lNContacts, 4 );\n" +" \n" +" GROUP_LDS_BARRIER;\n" +"\n" +" if( lIdx == 0 && nContacts)\n" +" {\n" +" int dstIdx;\n" +" AppendInc( nContactsOut, dstIdx );\n" +" *lNContacts = dstIdx;\n" +"\n" +" if( dstIdx >= capacity )\n" +" *lNContacts = -1;\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" bool canWrite = (*lNContacts!=-1);\n" +"\n" +" if( nContacts && canWrite )\n" +" {\n" +" __global Contact4* c = contactsOut + (*lNContacts);\n" +"\n" +" if( lIdx < nContacts )\n" +" {\n" +" int i = lIdx;\n" +" float4 p = lCPoints[i];\n" +" float4 bodyAPos = bodyAPtr->m_pos;\n" +" Quaternion bodyAQuat = bodyAPtr->m_quat;\n" +"\n" +" p = transform( &p, &bodyAPos, &bodyAQuat );\n" +" p.w = lCPoints[i].w - collisionMargin;\n" +" c->m_worldPos[i] = p;\n" +" }\n" +"\n" +" if( lIdx == 0 )\n" +" {\n" +" if( nContacts )\n" +" {\n" +" float4 contactNormal;\n" +" contactNormal = ShapeDataQueryNormal( &shapeData[GET_SHAPE_IDX(*bodyAPtr)], center );\n" +" contactNormal = normalize3( qtRotate( bodyAPtr->m_quat, contactNormal ) );\n" +"\n" +" c->m_worldNormal = contactNormal;\n" +"// c->m_restituitionCoeff = 0.f;\n" +"// c->m_frictionCoeff = 0.7f;\n" +" c->m_coeffs = (u32)(0.f*0xffff) | ((u32)(0.7f*0xffff)<<16);\n" +" c->m_bodyAPtr = pair0;\n" +" c->m_bodyBPtr = pair1;\n" +" }\n" +" GET_NPOINTS(*c) = nContacts;\n" +" }\n" +" }\n" +"}\n" +"\n" +"__inline\n" +"void output2LDS(__local BodyData* bodyAPtr, __local BodyData* bodyBPtr,\n" +" int pair0, int pair1,\n" +" int lNContacts, __local float4* lCPoints,\n" +" float4 center, \n" +" const __global ShapeData* shapeData, __local Contact4* contactsOut,\n" +" float collisionMargin )\n" +"{\n" +" int lIdx = GET_LOCAL_IDX%32;\n" +"// int lIdx = GET_LOCAL_IDX;\n" +"// int groupIdx = 0;\n" +"\n" +" int nContacts = min2( lNContacts, 4 );\n" +" \n" +" GROUP_LDS_BARRIER;\n" +"\n" +" if( nContacts != 0 )\n" +" {\n" +" if( lIdx < nContacts )\n" +" {\n" +" int i = lIdx;\n" +" float4 p = lCPoints[i];\n" +" float4 bodyAPos = bodyAPtr->m_pos;\n" +" Quaternion bodyAQuat = bodyAPtr->m_quat;\n" +"\n" +" p = transform( &p, &bodyAPos, &bodyAQuat );\n" +" p.w = lCPoints[i].w - collisionMargin;\n" +" contactsOut->m_worldPos[i] = p;\n" +" }\n" +" }\n" +"\n" +" if( lIdx == 0 )\n" +" {\n" +" if( nContacts != 0 )\n" +" {\n" +" float4 contactNormal;\n" +" contactNormal = ShapeDataQueryNormal( &shapeData[GET_SHAPE_IDX(*bodyAPtr)], center );\n" +" contactNormal = normalize3( qtRotate( bodyAPtr->m_quat, contactNormal ) );\n" +"\n" +" contactsOut->m_worldNormal = contactNormal;\n" +"// contactsOut->m_worldNormal = make_float4(1.5f,1.4f,1.3f,0.f);\n" +"// contactsOut->m_restituitionCoeff = 0.f;\n" +"// contactsOut->m_frictionCoeff = 0.7f;\n" +" contactsOut->m_coeffs = (u32)(0.f*0xffff) | ((u32)(0.7f*0xffff)<<16);\n" +" contactsOut->m_bodyAPtr = pair0;\n" +" contactsOut->m_bodyBPtr = pair1;\n" +" }\n" +" GET_NPOINTS(*contactsOut) = nContacts;//nContacts;\n" +" }\n" +"\n" +"// contactsOut[groupIdx].m_worldNormal = make_float4(1.5f,1.4f,1.3f,0.f);\n" +"}\n" +"\n" +"void output2_1(__local BodyData* bodyAPtr, __local BodyData* bodyBPtr,\n" +" int pair0, int pair1,\n" +" __local int* lNContacts, __local float4* lCPoints,\n" +" float4 center, float4 nA, \n" +" const __global ShapeData* shapeData, __global Contact4* contactsOut, counter32_t nContactsOut, int capacity, float collisionMargin )\n" +"{\n" +" int lIdx = GET_LOCAL_IDX;\n" +" int nContacts = min2( *lNContacts, 4 );\n" +" \n" +" GROUP_LDS_BARRIER;\n" +"\n" +" if( lIdx == 0 && nContacts)\n" +" {\n" +" int dstIdx;\n" +" AppendInc( nContactsOut, dstIdx );\n" +" *lNContacts = dstIdx;\n" +"\n" +" if( dstIdx >= capacity )\n" +" *lNContacts = -1;\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" bool canWrite = (*lNContacts!=-1);\n" +"\n" +" if( nContacts && canWrite )\n" +" {\n" +" __global Contact4* c = contactsOut + (*lNContacts);\n" +"\n" +" if( lIdx < nContacts )\n" +" {\n" +" int i = lIdx;\n" +" float4 p = lCPoints[i];\n" +" float4 bodyAPos = bodyAPtr->m_pos;\n" +" Quaternion bodyAQuat = bodyAPtr->m_quat;\n" +"\n" +" p = transform( &p, &bodyAPos, &bodyAQuat );\n" +" p.w = lCPoints[i].w - collisionMargin;\n" +" c->m_worldPos[i] = p;\n" +" }\n" +"\n" +" if( lIdx == 0 )\n" +" {\n" +" if( nContacts )\n" +" {\n" +" float4 contactNormal;\n" +" contactNormal = nA;//ShapeDataQueryNormal( &shapeData[GET_SHAPE_IDX(*bodyAPtr)], center );\n" +" contactNormal = normalize3( qtRotate( bodyAPtr->m_quat, contactNormal ) );\n" +"\n" +" c->m_worldNormal = contactNormal;\n" +"// c->m_restituitionCoeff = 0.f;\n" +"// c->m_frictionCoeff = 0.7f;\n" +" c->m_coeffs = (u32)(0.f*0xffff) | ((u32)(0.7f*0xffff)<<16);\n" +" c->m_bodyAPtr = pair0;\n" +" c->m_bodyBPtr = pair1;\n" +" }\n" +" GET_NPOINTS(*c) = nContacts;\n" +" }\n" +" }\n" +"}\n" +"\n" +"__kernel\n" +"void manifold(__global float4* vIn, __global float4* vOut)\n" +"{\n" +" __local float4 lCPoints[32];\n" +" __local float4 lManifoldBuffer[64];\n" +" __local int lNContacts;\n" +" __local float4 ab;\n" +"\n" +" if( GET_LOCAL_IDX<32 )\n" +" {\n" +" lCPoints[GET_LOCAL_IDX] = vIn[GET_GLOBAL_IDX];\n" +" }\n" +"\n" +" if( GET_LOCAL_IDX == 0 ) \n" +" {\n" +" lNContacts = 32;\n" +" ab = vIn[GET_GLOBAL_IDX];\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" float4 center = extractManifold( lCPoints, lManifoldBuffer, &lNContacts, ab );\n" +"\n" +" if( GET_LOCAL_IDX < lNContacts )\n" +" {\n" +" vOut[4*GET_GROUP_IDX+GET_LOCAL_IDX] = lCPoints[GET_LOCAL_IDX];\n" +" }\n" +"\n" +"}\n" +"\n" +"//#define COMBINE_REDUCTION \n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(64, 1, 1)))\n" +"void NarrowphaseKernel( const __global int2* restrict pairs, const __global ShapeData* shapeData, const __global BodyData* restrict bodyDatas, \n" +" __global Contact4* restrict contactsOut,\n" +" counter32_t nContactsOut, ConstBuffer cb ) \n" +"{\n" +" // 2.5K LDS\n" +" __local Contact4 ldsContacts[2];\n" +" __local BodyData bodyA;\n" +" __local BodyData bodyB;\n" +" __local ShapeDeviceData shapeA;\n" +" __local ShapeDeviceData shapeB;\n" +" __local float4 lCPointsA[32*2];\n" +" __local int lNContactsA;\n" +" __local float4* lCPointsB = lCPointsA+32;\n" +" __local int lNContactsB;\n" +"#ifdef COMBINE_REDUCTION\n" +" __local float4 lManifoldBuffer[64*2];\n" +"#else\n" +" __local float4 lManifoldBuffer[64];\n" +"#endif\n" +" __local int2 iPairAB;\n" +"\n" +" const int capacity = cb.m_capacity;\n" +" const float collisionMargin = cb.m_collisionMargin;\n" +"\n" +"\n" +" int pairIdx = GET_GROUP_IDX;\n" +"// for(int pairIdx = GET_GROUP_IDX; pairIdxm_height4[idx] = shapeData[ myShapeIdx ].m_height4[idx];\n" +"\n" +" idx+=32;\n" +" }\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" testVtx2( &bodyA, &bodyB, &shapeA, &shapeB, &lNContactsA, lCPointsA, &lNContactsB, lCPointsB, collisionMargin );\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" float4 ab = bodyB.m_pos - bodyA.m_pos;\n" +" float4 center[2];\n" +"\n" +" if( lNContactsA != 0 || lNContactsB != 0 )\n" +" {\n" +" float4 abInA;\n" +" abInA = qtInvRotate( bodyA.m_quat, ab );\n" +"\n" +" float4 abInB;\n" +" abInB = qtInvRotate( bodyB.m_quat, ab );\n" +"\n" +"#ifdef COMBINE_REDUCTION\n" +" extractManifold2( lCPointsA, &lNContactsA, abInA,\n" +" lCPointsB, &lNContactsB, abInB,\n" +" lManifoldBuffer, center );\n" +"#else\n" +" if( lNContactsA != 0 )\n" +" center[0] = extractManifold( lCPointsA, lManifoldBuffer, &lNContactsA, abInA );\n" +" if( lNContactsB != 0 )\n" +" center[1] = extractManifold( lCPointsB, lManifoldBuffer, &lNContactsB, abInB );\n" +"#endif\n" +" }\n" +"\n" +" int firstSet = GET_LOCAL_IDX/32;\n" +"\n" +"/*\n" +" if( GET_LOCAL_IDX == 0 ) // for debug\n" +" {\n" +" ldsContacts[0].m_worldNormal = make_float4(-1,-1,-1,0);\n" +" ldsContacts[0].m_bodyAPtr = 0;\n" +" ldsContacts[0].m_bodyBPtr = 0;\n" +" ldsContacts[0].m_batchIdx = 111;\n" +" ldsContacts[1].m_worldNormal = make_float4(-1,-1,-1,0);\n" +" ldsContacts[1].m_bodyAPtr = 0;\n" +" ldsContacts[1].m_bodyBPtr = 0;\n" +" ldsContacts[1].m_batchIdx = 111;\n" +" }\n" +"*/\n" +" bool doReduction = true;\n" +" if( doReduction )\n" +" {\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" output2LDS( (firstSet)?&bodyA: &bodyB, (firstSet)?&bodyB : &bodyA, \n" +" (firstSet)?iPairAB.x : iPairAB.y, (firstSet)?iPairAB.y : iPairAB.x, \n" +" (firstSet)?lNContactsA : lNContactsB, (firstSet)?lCPointsA:lCPointsB, \n" +" (firstSet)?center[0] : center[1], shapeData, (firstSet)?&ldsContacts[0]: &ldsContacts[1], collisionMargin );\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" \n" +" if( GET_LOCAL_IDX == 0 )\n" +" {\n" +" if( lNContactsA && lNContactsB )\n" +" {\n" +" float nDotn = dot3F4( ldsContacts[0].m_worldNormal, ldsContacts[1].m_worldNormal );\n" +" if( nDotn < -(1.f-0.01f) )\n" +" {\n" +" if( ldsContacts[0].m_bodyAPtr > ldsContacts[1].m_bodyAPtr )\n" +" lNContactsA = 0;\n" +" else\n" +" lNContactsB = 0;\n" +" }\n" +" }\n" +" }\n" +" \n" +" if( GET_LOCAL_IDX == 0 )\n" +" {\n" +" int n = lNContactsA;\n" +" if( n != 0 )\n" +" {\n" +" int dstIdx;\n" +" AppendInc( nContactsOut, dstIdx );\n" +" if( dstIdx < capacity )\n" +" { int idx = 0;\n" +" contactsOut[ dstIdx ] = ldsContacts[idx];\n" +" contactsOut[ dstIdx].m_batchIdx = pairIdx;\n" +" }\n" +" }\n" +"\n" +" n = lNContactsB;\n" +" if( n != 0 )\n" +" {\n" +" int dstIdx;\n" +" AppendInc( nContactsOut, dstIdx );\n" +" if( dstIdx < capacity )\n" +" { int idx = 1;\n" +" contactsOut[ dstIdx ] = ldsContacts[idx];\n" +" contactsOut[ dstIdx].m_batchIdx = pairIdx;\n" +" }\n" +" }\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" }\n" +" else\n" +" {\n" +" //output2( (firstSet)?&bodyA: &bodyB, (firstSet)?&bodyB : &bodyA, \n" +" // (firstSet)?iPairAB.x : iPairAB.y, (firstSet)?iPairAB.y : iPairAB.x, \n" +" // (firstSet)?&lNContactsA : &lNContactsB, (firstSet)?lCPointsA:lCPointsB, \n" +" // (firstSet)?center[0] : center[1], shapeData, contactsOut, nContactsOut, capacity, collisionMargin );\n" +" }\n" +" }\n" +"}\n" +"\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(64, 1, 1)))\n" +"void NarrowphaseWithPlaneKernel( const __global int2* restrict pairs, const __global ShapeData* shapeData, const __global BodyData* restrict bodyDatas, \n" +" __global Contact4* restrict contactsOut,\n" +" counter32_t nContactsOut, ConstBuffer cb ) \n" +"{\n" +" // 2.5K LDS\n" +" __local BodyData bodyA;\n" +" __local BodyData bodyB;\n" +" __local ShapeDeviceData shapeA;\n" +" __local ShapeDeviceData shapeB;\n" +" __local float4 lCPointsA[32*2];\n" +" __local int lNContactsA;\n" +"// __local float4* lCPointsB = lCPointsA+32;\n" +"// __local int lNContactsB;\n" +" __local float4 lManifoldBuffer[64];\n" +" __local int2 iPairAB;\n" +"\n" +" const int capacity = cb.m_capacity;\n" +" const float collisionMargin = cb.m_collisionMargin;\n" +"\n" +" int pairIdx = GET_GROUP_IDX;\n" +" {\n" +" if( GET_LOCAL_IDX == 0 ) // load Bodies\n" +" {\n" +" int2 pair = pairs[pairIdx];\n" +" iPairAB = make_int2(pair.x, pair.y);\n" +" bodyA = bodyDatas[ pair.x ];\n" +" bodyB = bodyDatas[ pair.y ];\n" +" shapeA.m_scale = shapeData[ GET_SHAPE_IDX(bodyA) ].m_scale;\n" +" shapeB.m_scale = shapeData[ GET_SHAPE_IDX(bodyB) ].m_scale;\n" +" lNContactsA = 0;\n" +"// lNContactsB = 0;\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" if (bodyB.m_invMass == 0.f)\n" +" return;\n" +" \n" +" // todo. can check if the shape is the same to previous one. If same, dont read\n" +" { // load shape data\n" +" int idx = GET_LOCAL_IDX%32;\n" +" int bIdx = GET_LOCAL_IDX/32;\n" +" __local ShapeDeviceData* myShape = (bIdx==0)?&shapeA: &shapeB;\n" +" int myShapeIdx = (bIdx==0)?GET_SHAPE_IDX(bodyA): GET_SHAPE_IDX(bodyB);\n" +"\n" +" while( idx < HEIGHT_RES*HEIGHT_RES*6/4 )\n" +" {\n" +" myShape->m_height4[idx] = shapeData[ myShapeIdx ].m_height4[idx];\n" +"\n" +" idx+=32;\n" +" }\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" float4 nA = make_float4(0,1,0,0);\n" +"\n" +"\n" +"// testVtx2( &bodyA, &bodyB, &shapeA, &shapeB, &lNContactsA, lCPointsA, &lNContactsB, lCPointsB );\n" +" testVtxWithPlane( &bodyA, &bodyB, nA, &shapeB, &lNContactsA, lCPointsA, collisionMargin );\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +"// float4 ab = bodyB.m_pos - bodyA.m_pos;\n" +" float4 center[2];\n" +"\n" +" if( lNContactsA != 0 )\n" +" {\n" +" float4 abInA;\n" +" abInA = nA;//qtInvRotate( bodyA.m_quat, ab );\n" +"\n" +" if( lNContactsA != 0 )\n" +" center[0] = extractManifold( lCPointsA, lManifoldBuffer, &lNContactsA, abInA );\n" +" }\n" +"\n" +"// int firstSet = GET_LOCAL_IDX/32;\n" +"\n" +" output2_1( &bodyA, &bodyB, \n" +" iPairAB.x, iPairAB.y, \n" +" &lNContactsA, lCPointsA, \n" +" center[0], nA, shapeData, contactsOut, nContactsOut, capacity, collisionMargin );\n" +" }\n" +"}\n" +; diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/Solver.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/Solver.h new file mode 100644 index 0000000..2a2382a --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/Solver.h @@ -0,0 +1,203 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#pragma once +#ifndef __ADL_SOLVER_H +#define __ADL_SOLVER_H + + +#include +#include +#include +#include +#include +#include + +//#include +#include "AdlRigidBody.h" +#include "AdlContact4.h" + +//#include "AdlPhysics/Batching/Batching.h> + + +#define MYF4 float4 +#define MAKE_MYF4 make_float4 + +//#define MYF4 float4sse +//#define MAKE_MYF4 make_float4sse + +#include "AdlConstraint4.h" + +namespace adl +{ +class SolverBase +{ + public: + + + struct ConstraintData + { + ConstraintData(): m_b(0.f), m_appliedRambdaDt(0.f) {} + + float4 m_linear; // have to be normalized + float4 m_angular0; + float4 m_angular1; + float m_jacCoeffInv; + float m_b; + float m_appliedRambdaDt; + + u32 m_bodyAPtr; + u32 m_bodyBPtr; + + bool isInvalid() const { return ((u32)m_bodyAPtr+(u32)m_bodyBPtr) == 0; } + float getFrictionCoeff() const { return m_linear.w; } + void setFrictionCoeff(float coeff) { m_linear.w = coeff; } + }; + + struct ConstraintCfg + { + ConstraintCfg( float dt = 0.f ): m_positionDrift( 0.005f ), m_positionConstraintCoeff( 0.2f ), m_dt(dt), m_staticIdx(-1) {} + + float m_positionDrift; + float m_positionConstraintCoeff; + float m_dt; + bool m_enableParallelSolve; + float m_averageExtent; + int m_staticIdx; + }; + + static + __inline + Buffer* allocateContact4( const Device* device, int capacity ) + { + return new Buffer( device, capacity ); + } + + static + __inline + void deallocateContact4( Buffer* data ) { delete data; } + + static + __inline + SolverData allocateConstraint4( const Device* device, int capacity ) + { + return new Buffer( device, capacity ); + } + + static + __inline + void deallocateConstraint4( SolverData data ) { delete (Buffer*)data; } + + static + __inline + void* allocateFrictionConstraint( const Device* device, int capacity, u32 type = 0 ) + { + return 0; + } + + static + __inline + void deallocateFrictionConstraint( void* data ) + { + } + + enum + { + N_SPLIT = 16, + N_BATCHES = 4, + N_OBJ_PER_SPLIT = 10, + N_TASKS_PER_BATCH = N_SPLIT*N_SPLIT, + }; +}; + +template +class Solver : public SolverBase +{ + public: + typedef Launcher::BufferInfo BufferInfo; + + struct Data + { + Data() : m_nIterations(4){} + + const Device* m_device; + void* m_parallelSolveData; + int m_nIterations; + Kernel* m_batchingKernel; + Kernel* m_batchSolveKernel; + Kernel* m_contactToConstraintKernel; + Kernel* m_setSortDataKernel; + Kernel* m_reorderContactKernel; + Kernel* m_copyConstraintKernel; + //typename RadixSort::Data* m_sort; + typename RadixSort32::Data* m_sort32; + typename BoundSearch::Data* m_search; + typename PrefixScan::Data* m_scan; + Buffer* m_sortDataBuffer; + Buffer* m_contactBuffer; + }; + + enum + { + DYNAMIC_CONTACT_ALLOCATION_THRESHOLD = 2000000, + }; + + static + Data* allocate( const Device* device, int pairCapacity ); + + static + void deallocate( Data* data ); + + static + void reorderConvertToConstraints( Data* data, const Buffer* bodyBuf, + const Buffer* shapeBuf, + Buffer* contactsIn, SolverData contactCOut, void* additionalData, + int nContacts, const ConstraintCfg& cfg ); + + static + void solveContactConstraint( Data* data, const Buffer* bodyBuf, const Buffer* inertiaBuf, + SolverData constraint, void* additionalData, int n ); + +// static +// int createSolveTasks( int batchIdx, Data* data, const Buffer* bodyBuf, const Buffer* shapeBuf, +// SolverData constraint, int n, ThreadPool::Task* tasksOut[], int taskCapacity ); + + + //private: + static + void convertToConstraints( Data* data, const Buffer* bodyBuf, + const Buffer* shapeBuf, + Buffer* contactsIn, SolverData contactCOut, void* additionalData, + int nContacts, const ConstraintCfg& cfg ); + + static + void sortContacts( Data* data, const Buffer* bodyBuf, + Buffer* contactsIn, void* additionalData, + int nContacts, const ConstraintCfg& cfg ); + + static + void batchContacts( Data* data, Buffer* contacts, int nContacts, Buffer* n, Buffer* offsets, int staticIdx ); + +}; + +#include "Solver.inl" +#include "SolverHost.inl" +}; + +#undef MYF4 +#undef MAKE_MYF4 + +#endif //__ADL_SOLVER_H diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/Solver.inl b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/Solver.inl new file mode 100644 index 0000000..3fc5a2f --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/Solver.inl @@ -0,0 +1,762 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#define PATH "..\\..\\dynamics\\basic_demo\\Stubs\\SolverKernels" +#define BATCHING_PATH "..\\..\\dynamics\\basic_demo\\Stubs\\batchingKernels" + +#define KERNEL1 "SingleBatchSolveKernel" +#define KERNEL2 "BatchSolveKernel" + +#define KERNEL3 "ContactToConstraintKernel" +#define KERNEL4 "SetSortDataKernel" +#define KERNEL5 "ReorderContactKernel" +#include "SolverKernels.h" + +#include "batchingKernels.h" + + +struct SolverDebugInfo +{ + int m_valInt0; + int m_valInt1; + int m_valInt2; + int m_valInt3; + + int m_valInt4; + int m_valInt5; + int m_valInt6; + int m_valInt7; + + int m_valInt8; + int m_valInt9; + int m_valInt10; + int m_valInt11; + + int m_valInt12; + int m_valInt13; + int m_valInt14; + int m_valInt15; + + + float m_val0; + float m_val1; + float m_val2; + float m_val3; +}; + + + + +class SolverDeviceInl +{ +public: + struct ParallelSolveData + { + Buffer* m_numConstraints; + Buffer* m_offsets; + }; +}; + +template +typename Solver::Data* Solver::allocate( const Device* device, int pairCapacity ) +{ + const char* src[] = +#if defined(ADL_LOAD_KERNEL_FROM_STRING) + {solverKernelsCL, 0}; +#else + {0,0}; +#endif + + const char* src2[] = +#if defined(ADL_LOAD_KERNEL_FROM_STRING) + {batchingKernelsCL, 0}; +#else + {0,0}; +#endif + + + + + Data* data = new Data; + data->m_device = device; + bool cacheBatchingKernel = true; + data->m_batchingKernel = device->getKernel( BATCHING_PATH, "CreateBatches", "-I ..\\..\\ ", src2[TYPE],cacheBatchingKernel); + //data->m_batchingKernel = device->getKernel( BATCHING_PATH, "CreateBatches", "-I ..\\..\\ ", 0,cacheBatchingKernel); + bool cacheSolverKernel = true; + + data->m_batchSolveKernel = device->getKernel( PATH, KERNEL2, "-I ..\\..\\ ", src[TYPE],cacheSolverKernel ); + data->m_contactToConstraintKernel = device->getKernel( PATH, KERNEL3, + "-I ..\\..\\ ", src[TYPE] ); + data->m_setSortDataKernel = device->getKernel( PATH, KERNEL4, + "-I ..\\..\\ ", src[TYPE] ); + data->m_reorderContactKernel = device->getKernel( PATH, KERNEL5, + "-I ..\\..\\ ", src[TYPE] ); + + data->m_copyConstraintKernel = device->getKernel( PATH, "CopyConstraintKernel", + "-I ..\\..\\ ", src[TYPE] ); + + data->m_parallelSolveData = new SolverDeviceInl::ParallelSolveData; + { + SolverDeviceInl::ParallelSolveData* solveData = (SolverDeviceInl::ParallelSolveData*)data->m_parallelSolveData; + solveData->m_numConstraints = new Buffer( device, N_SPLIT*N_SPLIT ); + solveData->m_offsets = new Buffer( device, N_SPLIT*N_SPLIT ); + } + const int sortSize = NEXTMULTIPLEOF( pairCapacity, 512 ); + + + //data->m_sort = RadixSort::allocate( data->m_device, sortSize );//todo. remove hardcode this + data->m_sort32 = RadixSort32::allocate( data->m_device, sortSize );//todo. remove hardcode this + + data->m_search = BoundSearch::allocate( data->m_device, N_SPLIT*N_SPLIT ); + data->m_scan = PrefixScan::allocate( data->m_device, N_SPLIT*N_SPLIT ); + + data->m_sortDataBuffer = new Buffer( data->m_device, sortSize ); + + if( pairCapacity < DYNAMIC_CONTACT_ALLOCATION_THRESHOLD ) + data->m_contactBuffer = new Buffer( data->m_device, pairCapacity ); + else + data->m_contactBuffer = 0; + + return data; +} + +template +void Solver::deallocate( Data* data ) +{ + { + SolverDeviceInl::ParallelSolveData* solveData = (SolverDeviceInl::ParallelSolveData*)data->m_parallelSolveData; + delete solveData->m_numConstraints; + delete solveData->m_offsets; + delete solveData; + } + +// RadixSort::deallocate( data->m_sort ); + RadixSort32::deallocate(data->m_sort32); + BoundSearch::deallocate( data->m_search ); + PrefixScan::deallocate( data->m_scan ); + + delete data->m_sortDataBuffer; + if( data->m_contactBuffer ) delete data->m_contactBuffer; + + delete data; +} + +template +void Solver::reorderConvertToConstraints( typename Solver::Data* data, const Buffer* bodyBuf, + const Buffer* shapeBuf, + Buffer* contactsIn, SolverData contactCOut, void* additionalData, + int nContacts, const typename Solver::ConstraintCfg& cfg ) +{ + if( data->m_contactBuffer ) + { + if( data->m_contactBuffer->getSize() < nContacts ) + { + BT_PROFILE("delete data->m_contactBuffer;"); + delete data->m_contactBuffer; + data->m_contactBuffer = 0; + } + } + if( data->m_contactBuffer == 0 ) + { + BT_PROFILE("new data->m_contactBuffer;"); + + data->m_contactBuffer = new Buffer( data->m_device, nContacts ); + } + Stopwatch sw; + + Buffer* contactNative = BufferUtils::map( data->m_device, contactsIn, nContacts ); + + //DeviceUtils::Config dhCfg; + //Device* deviceHost = DeviceUtils::allocate( TYPE_HOST, dhCfg ); + if( cfg.m_enableParallelSolve ) + { + SolverDeviceInl::ParallelSolveData* nativeSolveData = (SolverDeviceInl::ParallelSolveData*)data->m_parallelSolveData; + + DeviceUtils::waitForCompletion( data->m_device ); + sw.start(); + // contactsIn -> data->m_contactBuffer + { + BT_PROFILE("sortContacts"); + Solver::sortContacts( data, bodyBuf, contactNative, additionalData, nContacts, cfg ); + DeviceUtils::waitForCompletion( data->m_device ); + } + sw.split(); + if(0) + { + Contact4* tmp = new Contact4[nContacts]; + data->m_contactBuffer->read( tmp, nContacts ); + DeviceUtils::waitForCompletion( data->m_contactBuffer->m_device ); + contactNative->write( tmp, nContacts ); + DeviceUtils::waitForCompletion( contactNative->m_device ); + delete [] tmp; + } + else + { + BT_PROFILE("m_copyConstraintKernel"); + + Buffer constBuffer( data->m_device, 1, BufferBase::BUFFER_CONST ); + + int4 cdata; cdata.x = nContacts; + BufferInfo bInfo[] = { BufferInfo( data->m_contactBuffer ), BufferInfo( contactNative ) }; +// Launcher launcher( data->m_device, data->m_device->getKernel( PATH, "CopyConstraintKernel", "-I ..\\..\\ -Wf,--c++", 0 ) ); + Launcher launcher( data->m_device, data->m_copyConstraintKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( constBuffer, cdata ); + launcher.launch1D( nContacts, 64 ); + DeviceUtils::waitForCompletion( data->m_device ); + } + { + BT_PROFILE("batchContacts"); + Solver::batchContacts( data, contactNative, nContacts, nativeSolveData->m_numConstraints, nativeSolveData->m_offsets, cfg.m_staticIdx ); + + } + } + { + BT_PROFILE("waitForCompletion (batchContacts)"); + DeviceUtils::waitForCompletion( data->m_device ); + } + sw.split(); + //================ + if(0) + { +// Solver::Data* solverHost = Solver::allocate( deviceHost, nContacts ); +// Solver::convertToConstraints( solverHost, bodyBuf, shapeBuf, contactNative, contactCOut, additionalData, nContacts, cfg ); +// Solver::deallocate( solverHost ); + } + else + { + BT_PROFILE("convertToConstraints"); + Solver::convertToConstraints( data, bodyBuf, shapeBuf, contactNative, contactCOut, additionalData, nContacts, cfg ); + } + { + BT_PROFILE("convertToConstraints waitForCompletion"); + DeviceUtils::waitForCompletion( data->m_device ); + } + sw.stop(); + + { + BT_PROFILE("printf"); + + float t[5]; + sw.getMs( t, 3 ); +// printf("%3.2f, %3.2f, %3.2f, ", t[0], t[1], t[2]); + } + + { + BT_PROFILE("deallocate and unmap"); + + //DeviceUtils::deallocate( deviceHost ); + + BufferUtils::unmap( contactNative, contactsIn, nContacts ); + } +} + + +template +void Solver::solveContactConstraint( typename Solver::Data* data, const Buffer* bodyBuf, const Buffer* shapeBuf, + SolverData constraint, void* additionalData, int n ) +{ + if(0) + { + DeviceUtils::Config dhCfg; + Device* deviceHost = DeviceUtils::allocate( TYPE_HOST, dhCfg ); + { + Solver::Data* hostData = Solver::allocate( deviceHost, 0 ); + Solver::solveContactConstraint( hostData, bodyBuf, shapeBuf, constraint, additionalData, n ); + Solver::deallocate( hostData ); + } + DeviceUtils::deallocate( deviceHost ); + return; + } + + ADLASSERT( data ); + + Buffer* cBuffer =0; + + Buffer* gBodyNative=0; + Buffer* gShapeNative =0; + Buffer* gConstraintNative =0; + + + { + BT_PROFILE("map"); + cBuffer = (Buffer*)constraint; + + gBodyNative= BufferUtils::map( data->m_device, bodyBuf ); + gShapeNative= BufferUtils::map( data->m_device, shapeBuf ); + gConstraintNative = BufferUtils::map( data->m_device, cBuffer ); + DeviceUtils::waitForCompletion( data->m_device ); + } + + Buffer constBuffer; + int4 cdata = make_int4( n, 0, 0, 0 ); + { + SolverDeviceInl::ParallelSolveData* solveData = (SolverDeviceInl::ParallelSolveData*)data->m_parallelSolveData; + const int nn = N_SPLIT*N_SPLIT; + + cdata.x = 0; + cdata.y = 250; + +#if 0 +//check how the cells are filled + unsigned int* hostCounts = new unsigned int[N_SPLIT*N_SPLIT]; + solveData->m_numConstraints->read(hostCounts,N_SPLIT*N_SPLIT); + DeviceUtils::waitForCompletion( data->m_device ); + for (int i=0;i gpuDebugInfo(data->m_device,numWorkItems); +#endif + + + + { + + BT_PROFILE("m_batchSolveKernel iterations"); + for(int iter=0; iterm_nIterations; iter++) + { + for(int ib=0; ibm_numConstraints ), + BufferInfo( solveData->m_offsets ) +#ifdef DEBUG_ME + , BufferInfo(&gpuDebugInfo) +#endif + }; + + Launcher launcher( data->m_device, data->m_batchSolveKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( constBuffer, cdata ); + + launcher.launch1D( numWorkItems, 64 ); + +#ifdef DEBUG_ME + DeviceUtils::waitForCompletion( data->m_device ); + gpuDebugInfo.read(debugInfo,numWorkItems); + DeviceUtils::waitForCompletion( data->m_device ); + for (int i=0;i0) + { + printf("debugInfo[i].m_valInt2 = %d\n",i,debugInfo[i].m_valInt2); + } + + if (debugInfo[i].m_valInt3>0) + { + printf("debugInfo[i].m_valInt3 = %d\n",i,debugInfo[i].m_valInt3); + } + } +#endif //DEBUG_ME + + + } + } + + DeviceUtils::waitForCompletion( data->m_device ); + + + } + + cdata.x = 1; + { + BT_PROFILE("m_batchSolveKernel iterations2"); + for(int iter=0; iterm_nIterations; iter++) + { + for(int ib=0; ibm_numConstraints ), + BufferInfo( solveData->m_offsets ) +#ifdef DEBUG_ME + ,BufferInfo(&gpuDebugInfo) +#endif //DEBUG_ME + }; + Launcher launcher( data->m_device, data->m_batchSolveKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( constBuffer, cdata ); + launcher.launch1D( 64*nn/N_BATCHES, 64 ); + } + } + DeviceUtils::waitForCompletion( data->m_device ); + + } +#ifdef DEBUG_ME + delete[] debugInfo; +#endif //DEBUG_ME + } + + { + BT_PROFILE("unmap"); + BufferUtils::unmap( gBodyNative, bodyBuf ); + BufferUtils::unmap( gShapeNative, shapeBuf ); + BufferUtils::unmap( gConstraintNative, cBuffer ); + DeviceUtils::waitForCompletion( data->m_device ); + } +} + +template +void Solver::convertToConstraints( typename Solver::Data* data, const Buffer* bodyBuf, + const Buffer* shapeBuf, + Buffer* contactsIn, SolverData contactCOut, void* additionalData, + int nContacts, const ConstraintCfg& cfg ) +{ + ADLASSERT( data->m_device->m_type == TYPE_CL ); + + Buffer* bodyNative =0; + Buffer* shapeNative =0; + Buffer* contactNative =0; + Buffer* constraintNative =0; + + { + BT_PROFILE("map buffers"); + + bodyNative = BufferUtils::map( data->m_device, bodyBuf ); + shapeNative = BufferUtils::map( data->m_device, shapeBuf ); + contactNative= BufferUtils::map( data->m_device, contactsIn ); + constraintNative = BufferUtils::map( data->m_device, (Buffer*)contactCOut ); + } + struct CB + { + int m_nContacts; + float m_dt; + float m_positionDrift; + float m_positionConstraintCoeff; + }; + + { + BT_PROFILE("m_contactToConstraintKernel"); + CB cdata; + cdata.m_nContacts = nContacts; + cdata.m_dt = cfg.m_dt; + cdata.m_positionDrift = cfg.m_positionDrift; + cdata.m_positionConstraintCoeff = cfg.m_positionConstraintCoeff; + + Buffer constBuffer( data->m_device, 1, BufferBase::BUFFER_CONST ); + BufferInfo bInfo[] = { BufferInfo( contactNative ), BufferInfo( bodyNative ), BufferInfo( shapeNative ), + BufferInfo( constraintNative )}; + Launcher launcher( data->m_device, data->m_contactToConstraintKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( constBuffer, cdata ); + launcher.launch1D( nContacts, 64 ); + DeviceUtils::waitForCompletion( data->m_device ); + + } + + { + BT_PROFILE("unmap"); + BufferUtils::unmap( bodyNative, bodyBuf ); + BufferUtils::unmap( shapeNative, shapeBuf ); + BufferUtils::unmap( contactNative, contactsIn ); + BufferUtils::unmap( constraintNative, (Buffer*)contactCOut ); + } +} + +template +void Solver::sortContacts( typename Solver::Data* data, const Buffer* bodyBuf, + Buffer* contactsIn, void* additionalData, + int nContacts, const typename Solver::ConstraintCfg& cfg ) +{ + ADLASSERT( data->m_device->m_type == TYPE_CL ); + Buffer* bodyNative + = BufferUtils::map( data->m_device, bodyBuf ); + Buffer* contactNative + = BufferUtils::map( data->m_device, contactsIn ); + + const int sortAlignment = 512; // todo. get this out of sort + if( cfg.m_enableParallelSolve ) + { + SolverDeviceInl::ParallelSolveData* nativeSolveData = (SolverDeviceInl::ParallelSolveData*)data->m_parallelSolveData; + + int sortSize = NEXTMULTIPLEOF( nContacts, sortAlignment ); + + Buffer* countsNative = nativeSolveData->m_numConstraints;//BufferUtils::map( data->m_device, &countsHost ); + Buffer* offsetsNative = nativeSolveData->m_offsets;//BufferUtils::map( data->m_device, &offsetsHost ); + + { // 2. set cell idx + struct CB + { + int m_nContacts; + int m_staticIdx; + float m_scale; + int m_nSplit; + }; + + ADLASSERT( sortSize%64 == 0 ); + CB cdata; + cdata.m_nContacts = nContacts; + cdata.m_staticIdx = cfg.m_staticIdx; + cdata.m_scale = 1.f/(N_OBJ_PER_SPLIT*cfg.m_averageExtent); + cdata.m_nSplit = N_SPLIT; + + Buffer constBuffer( data->m_device, 1, BufferBase::BUFFER_CONST ); + BufferInfo bInfo[] = { BufferInfo( contactNative ), BufferInfo( bodyNative ), BufferInfo( data->m_sortDataBuffer ) }; + Launcher launcher( data->m_device, data->m_setSortDataKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( constBuffer, cdata ); + launcher.launch1D( sortSize, 64 ); + } + + { // 3. sort by cell idx + int n = N_SPLIT*N_SPLIT; + int sortBit = 32; + //if( n <= 0xffff ) sortBit = 16; + //if( n <= 0xff ) sortBit = 8; + RadixSort32::execute( data->m_sort32, *data->m_sortDataBuffer,sortSize); + } + { // 4. find entries + BoundSearch::execute( data->m_search, *data->m_sortDataBuffer, nContacts, *countsNative, N_SPLIT*N_SPLIT, BoundSearchBase::COUNT ); + + PrefixScan::execute( data->m_scan, *countsNative, *offsetsNative, N_SPLIT*N_SPLIT ); + } + + { // 5. sort constraints by cellIdx + // todo. preallocate this +// ADLASSERT( contactsIn->getType() == TYPE_HOST ); +// Buffer* out = BufferUtils::map( data->m_device, contactsIn ); // copying contacts to this buffer + + { + Buffer constBuffer( data->m_device, 1, BufferBase::BUFFER_CONST ); + + int4 cdata; cdata.x = nContacts; + BufferInfo bInfo[] = { BufferInfo( contactNative ), BufferInfo( data->m_contactBuffer ), BufferInfo( data->m_sortDataBuffer ) }; + Launcher launcher( data->m_device, data->m_reorderContactKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( constBuffer, cdata ); + launcher.launch1D( nContacts, 64 ); + } +// BufferUtils::unmap( out, contactsIn, nContacts ); + } + } + + BufferUtils::unmap( bodyNative, bodyBuf ); + BufferUtils::unmap( contactNative, contactsIn ); +} + +template +void Solver::batchContacts( typename Solver::Data* data, Buffer* contacts, int nContacts, Buffer* n, Buffer* offsets, int staticIdx ) +{ + ADLASSERT( data->m_device->m_type == TYPE_CL ); + + if(0) + { + BT_PROFILE("CPU classTestKernel/Kernel (batch generation?)"); + + DeviceUtils::Config dhCfg; + Device* deviceHost = DeviceUtils::allocate( TYPE_HOST, dhCfg ); + { + Solver::Data* hostData = Solver::allocate( deviceHost, 0 ); + Solver::batchContacts( hostData, contacts, nContacts, n, offsets, staticIdx ); + Solver::deallocate( hostData ); + } + DeviceUtils::deallocate( deviceHost ); + return; + } + + Buffer* contactNative + = BufferUtils::map( data->m_device, contacts, nContacts ); + Buffer* nNative + = BufferUtils::map( data->m_device, n ); + Buffer* offsetsNative + = BufferUtils::map( data->m_device, offsets ); + + { + BT_PROFILE("GPU classTestKernel/Kernel (batch generation?)"); + Buffer constBuffer( data->m_device, 1, BufferBase::BUFFER_CONST ); + int4 cdata; + cdata.x = nContacts; + cdata.y = 0; + cdata.z = staticIdx; + + int numWorkItems = 64*N_SPLIT*N_SPLIT; +#ifdef BATCH_DEBUG + SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems]; + adl::Buffer gpuDebugInfo(data->m_device,numWorkItems); + memset(debugInfo,0,sizeof(SolverDebugInfo)*numWorkItems); + gpuDebugInfo.write(debugInfo,numWorkItems); +#endif + + + BufferInfo bInfo[] = { + BufferInfo( contactNative ), + BufferInfo( data->m_contactBuffer ), + BufferInfo( nNative ), + BufferInfo( offsetsNative ) +#ifdef BATCH_DEBUG + , BufferInfo(&gpuDebugInfo) +#endif + }; + + + + Launcher launcher( data->m_device, data->m_batchingKernel); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( constBuffer, cdata ); + launcher.launch1D( numWorkItems, 64 ); + DeviceUtils::waitForCompletion( data->m_device ); + +#ifdef BATCH_DEBUG + aaaa + Contact4* hostContacts = new Contact4[nContacts]; + data->m_contactBuffer->read(hostContacts,nContacts); + DeviceUtils::waitForCompletion( data->m_device ); + + gpuDebugInfo.read(debugInfo,numWorkItems); + DeviceUtils::waitForCompletion( data->m_device ); + + for (int i=0;i0) + { + printf("catch\n"); + } + if (debugInfo[i].m_valInt2>0) + { + printf("catch22\n"); + } + + if (debugInfo[i].m_valInt3>0) + { + printf("catch666\n"); + } + + if (debugInfo[i].m_valInt4>0) + { + printf("catch777\n"); + } + } + delete[] debugInfo; +#endif //BATCH_DEBUG + + } + + if(0) + { + u32* nhost = new u32[N_SPLIT*N_SPLIT]; + + nNative->read( nhost, N_SPLIT*N_SPLIT ); + + Contact4* chost = new Contact4[nContacts]; + data->m_contactBuffer->read( chost, nContacts ); + DeviceUtils::waitForCompletion( data->m_device ); + printf(">>"); + int nonzero = 0; + u32 maxn = 0; + for(int i=0; iwrite( *data->m_contactBuffer, nContacts ); + DeviceUtils::waitForCompletion( data->m_device ); + + if(0) + { + DeviceUtils::Config dhCfg; + Device* deviceHost = DeviceUtils::allocate( TYPE_HOST, dhCfg ); + { + HostBuffer host( deviceHost, nContacts ); + contactNative->read( host.m_ptr, nContacts ); + DeviceUtils::waitForCompletion( data->m_device ); + + for(int i=0; i( contactNative, contacts ); + BufferUtils::unmap( nNative, n ); + BufferUtils::unmap( offsetsNative, offsets ); +} + +#undef PATH +#undef KERNEL1 +#undef KERNEL2 + +#undef KERNEL3 +#undef KERNEL4 +#undef KERNEL5 diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/SolverHost.inl b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/SolverHost.inl new file mode 100644 index 0000000..a79205d --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/SolverHost.inl @@ -0,0 +1,848 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +class SolverInl +{ +public: + typedef SolverBase::ConstraintData ConstraintData; + + + static + __forceinline + void setLinearAndAngular(const MYF4& n, const MYF4& r0, const MYF4& r1, + MYF4& linear, MYF4& angular0, MYF4& angular1) + { + linear = -n; + angular0 = -cross3(r0, n); + angular1 = cross3(r1, n); + } + + static + __forceinline + float calcJacCoeff(const MYF4& linear0, const MYF4& linear1, const MYF4& angular0, const MYF4& angular1, + float invMass0, const Matrix3x3& invInertia0, float invMass1, const Matrix3x3& invInertia1) + { + // linear0,1 are normlized + float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0; + float jmj1 = dot3F4(mtMul3(angular0,invInertia0), angular0); + float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1; + float jmj3 = dot3F4(mtMul3(angular1,invInertia1), angular1); + return -1.f/(jmj0+jmj1+jmj2+jmj3); + } + static + __forceinline + float calcRelVel(const MYF4& l0, const MYF4& l1, const MYF4& a0, const MYF4& a1, + const MYF4& linVel0, const MYF4& angVel0, const MYF4& linVel1, const MYF4& angVel1) + { + return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1); + } + + static + __forceinline + void setConstraint4( const MYF4& posA, const MYF4& linVelA, const MYF4& angVelA, float invMassA, const Matrix3x3& invInertiaA, + const MYF4& posB, const MYF4& linVelB, const MYF4& angVelB, float invMassB, const Matrix3x3& invInertiaB, + const Contact4& src, const SolverBase::ConstraintCfg& cfg, + Constraint4& dstC ) + { + dstC.m_bodyA = (u32)src.m_bodyAPtr; + dstC.m_bodyB = (u32)src.m_bodyBPtr; + + float dtInv = 1.f/cfg.m_dt; + for(int ic=0; ic<4; ic++) + { + dstC.m_appliedRambdaDt[ic] = 0.f; + } + dstC.m_fJacCoeffInv[0] = dstC.m_fJacCoeffInv[1] = 0.f; + + + const MYF4& n = src.m_worldNormal; + dstC.m_linear = -n; + dstC.setFrictionCoeff( src.getFrictionCoeff() ); + for(int ic=0; ic<4; ic++) + { + MYF4 r0 = src.m_worldPos[ic] - posA; + MYF4 r1 = src.m_worldPos[ic] - posB; + + if( ic >= src.getNPoints() ) + { + dstC.m_jacCoeffInv[ic] = 0.f; + continue; + } + + float relVelN; + { + MYF4 linear, angular0, angular1; + setLinearAndAngular(n, r0, r1, linear, angular0, angular1); + + dstC.m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1, + invMassA, invInertiaA, invMassB, invInertiaB ); + + relVelN = calcRelVel(linear, -linear, angular0, angular1, + linVelA, angVelA, linVelB, angVelB); + + float e = src.getRestituitionCoeff(); + if( relVelN*relVelN < 0.004f ) e = 0.f; + + dstC.m_b[ic] = e*relVelN; + dstC.m_b[ic] += (src.getPenetration(ic) + cfg.m_positionDrift)*cfg.m_positionConstraintCoeff*dtInv; + dstC.m_appliedRambdaDt[ic] = 0.f; + } + } + + if( src.getNPoints() > 1 ) + { // prepare friction + MYF4 center = MAKE_MYF4(0.f); + for(int i=0; i 0.95f || (invMassA == 0.f || invMassB == 0.f)) + { + float angNA = dot3F4( n, angVelA ); + float angNB = dot3F4( n, angVelB ); + + angVelA -= (angNA*0.1f)*n; + angVelB -= (angNB*0.1f)*n; + } + } + } + + template + static + __inline + void solveContact(Constraint4& cs, + const MYF4& posA, MYF4& linVelA, MYF4& angVelA, float invMassA, const Matrix3x3& invInertiaA, + const MYF4& posB, MYF4& linVelB, MYF4& angVelB, float invMassB, const Matrix3x3& invInertiaB, + float maxRambdaDt[4], float minRambdaDt[4]) + { + MYF4 dLinVelA = MAKE_MYF4(0.f); + MYF4 dAngVelA = MAKE_MYF4(0.f); + MYF4 dLinVelB = MAKE_MYF4(0.f); + MYF4 dAngVelB = MAKE_MYF4(0.f); + + for(int ic=0; ic<4; ic++) + { + // dont necessary because this makes change to 0 + if( cs.m_jacCoeffInv[ic] == 0.f ) continue; + + { + MYF4 angular0, angular1, linear; + MYF4 r0 = cs.m_worldPos[ic] - posA; + MYF4 r1 = cs.m_worldPos[ic] - posB; + setLinearAndAngular( -cs.m_linear, r0, r1, linear, angular0, angular1 ); + + float rambdaDt = calcRelVel(cs.m_linear, -cs.m_linear, angular0, angular1, + linVelA, angVelA, linVelB, angVelB ) + cs.m_b[ic]; + rambdaDt *= cs.m_jacCoeffInv[ic]; + + { + float prevSum = cs.m_appliedRambdaDt[ic]; + float updated = prevSum; + updated += rambdaDt; + updated = max2( updated, minRambdaDt[ic] ); + updated = min2( updated, maxRambdaDt[ic] ); + rambdaDt = updated - prevSum; + cs.m_appliedRambdaDt[ic] = updated; + } + + MYF4 linImp0 = invMassA*linear*rambdaDt; + MYF4 linImp1 = invMassB*(-linear)*rambdaDt; + MYF4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt; + MYF4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt; + + if( JACOBI ) + { + dLinVelA += linImp0; + dAngVelA += angImp0; + dLinVelB += linImp1; + dAngVelB += angImp1; + } + else + { + linVelA += linImp0; + angVelA += angImp0; + linVelB += linImp1; + angVelB += angImp1; + } + } + } + + if( JACOBI ) + { + linVelA += dLinVelA; + angVelA += dAngVelA; + linVelB += dLinVelB; + angVelB += dAngVelB; + } + } + + enum + { + N_SPLIT = SolverBase::N_SPLIT, + }; + + // for parallel solve + struct ParallelSolveData + { + u32 m_n[N_SPLIT*N_SPLIT]; + u32 m_offset[N_SPLIT*N_SPLIT]; + }; + + static + __inline + int sortConstraintByBatch(Contact4* cs, int n, int ignoreIdx, int simdWidth = -1) + { + SortData* sortData; + { + BT_PROFILE("new"); + sortData = new SortData[n]; + } + + u32* idxBuffer = new u32[n]; + u32* idxSrc = idxBuffer; + u32* idxDst = idxBuffer; + int nIdxSrc, nIdxDst; + + const int N_FLG = 256; + const int FLG_MASK = N_FLG-1; + u32 flg[N_FLG/32]; +#if defined(_DEBUG) + for(int i=0; i sortBuffer; sortBuffer.setRawPtr( deviceHost, sortData, n ); + RadixSort::Data* sort = RadixSort::allocate( deviceHost, n ); + + RadixSort::execute( sort, sortBuffer, n ); + + RadixSort::deallocate( sort ); + } + DeviceUtils::deallocate( deviceHost ); + } + + { + BT_PROFILE("reorder"); + // reorder + Contact4* old = new Contact4[n]; + memcpy( old, cs, sizeof(Contact4)*n); + for(int i=0; i* bodies, const Buffer* shapes, const Buffer* constraints, + int start, int nConstraints) + : m_bodies( bodies ), m_shapes( shapes ), m_constraints( constraints ), m_start( start ), m_nConstraints( nConstraints ), + m_solveFriction( true ){} + + u16 getType(){ return 0; } + + void run(int tIdx) + { + HostBuffer& hBody = *(HostBuffer*)m_bodies; + HostBuffer& hShape = *(HostBuffer*)m_shapes; + HostBuffer& hc = *(HostBuffer*)m_constraints; + + for(int ic=0; ic( hc[i], bodyA.m_pos, (MYF4&)bodyA.m_linVel, (MYF4&)bodyA.m_angVel, bodyA.m_invMass, hShape[aIdx].m_invInertia, + bodyB.m_pos, (MYF4&)bodyB.m_linVel, (MYF4&)bodyB.m_angVel, bodyB.m_invMass, hShape[bIdx].m_invInertia, + maxRambdaDt, minRambdaDt ); + } + else + { + float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX}; + float minRambdaDt[4] = {0.f,0.f,0.f,0.f}; + + float sum = 0; + for(int j=0; j<4; j++) + { + sum +=hc[i].m_appliedRambdaDt[j]; + } + frictionCoeff = 0.7f; + for(int j=0; j<4; j++) + { + maxRambdaDt[j] = frictionCoeff*sum; + minRambdaDt[j] = -maxRambdaDt[j]; + } + + SolverInl::solveFriction( hc[i], bodyA.m_pos, (MYF4&)bodyA.m_linVel, (MYF4&)bodyA.m_angVel, bodyA.m_invMass, hShape[aIdx].m_invInertia, + bodyB.m_pos, (MYF4&)bodyB.m_linVel, (MYF4&)bodyB.m_angVel, bodyB.m_invMass, hShape[bIdx].m_invInertia, + maxRambdaDt, minRambdaDt ); + } + } + } + + const Buffer* m_bodies; + const Buffer* m_shapes; + const Buffer* m_constraints; + int m_start; + int m_nConstraints; + bool m_solveFriction; +}; + + +template<> +static Solver::Data* Solver::allocate( const Device* device, int pairCapacity ) +{ + Solver::Data* data = new Data; + data->m_device = device; + data->m_parallelSolveData = 0; + + return data; +} + +template<> +static void Solver::deallocate( Solver::Data* data ) +{ + if( data->m_parallelSolveData ) delete (SolverInl::ParallelSolveData*)data->m_parallelSolveData; + delete data; +} + + +void sortContacts2( Solver::Data* data, const Buffer* bodyBuf, + Buffer* contactsIn, void* additionalData, + int nContacts, const Solver::ConstraintCfg& cfg ) +{ + ADLASSERT( data->m_device->m_type == TYPE_HOST ); + HostBuffer* bodyNative + = (HostBuffer*)BufferUtils::map( data->m_device, bodyBuf ); + HostBuffer* contactNative + = (HostBuffer*)BufferUtils::map( data->m_device, contactsIn); + + if( cfg.m_enableParallelSolve ) + { + ADLASSERT( data->m_parallelSolveData == 0 ); + data->m_parallelSolveData = new SolverInl::ParallelSolveData; + SolverInl::ParallelSolveData* solveData = (SolverInl::ParallelSolveData*)data->m_parallelSolveData; + + HostBuffer sortData( data->m_device, nContacts ); + { // 2. set cell idx + float spacing = adl::SolverBase::N_OBJ_PER_SPLIT*cfg.m_averageExtent; + float xScale = 1.f/spacing; + for(int i=0; i= 0 && xIdx < adl::SolverBase::N_SPLIT ); + ADLASSERT( zIdx >= 0 && zIdx < adl::SolverBase::N_SPLIT ); + sortData[i].m_key = (xIdx+zIdx*adl::SolverBase::N_SPLIT); + sortData[i].m_value = i; + } + } + + { // 3. sort by cell idx + RadixSort::Data* sData = RadixSort::allocate( data->m_device, nContacts ); + + RadixSort::execute( sData, sortData, nContacts ); + + RadixSort::deallocate( sData ); + } + + { // 4. find entries + HostBuffer counts; counts.setRawPtr( data->m_device, solveData->m_n, adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT ); + HostBuffer offsets; offsets.setRawPtr( data->m_device, solveData->m_offset, adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT ); + { + BoundSearch::Data* sData = BoundSearch::allocate( data->m_device ); + PrefixScan::Data* pData = PrefixScan::allocate( data->m_device, adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT ); + + BoundSearch::execute( sData, sortData, nContacts, counts, adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT, BoundSearchBase::COUNT ); + + PrefixScan::execute( pData, counts, offsets, adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT ); + + BoundSearch::deallocate( sData ); + PrefixScan::deallocate( pData ); + } +#if defined(_DEBUG) + { + HostBuffer n0( data->m_device, adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT ); + HostBuffer offset0( data->m_device, adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT ); + for(int i=0; im_ptr, sizeof(Contact4)*nContacts ); + for(int i=0; i( bodyNative, bodyBuf ); + BufferUtils::unmap( contactNative, contactsIn ); +} + +static void reorderConvertToConstraints2( Solver::Data* data, const Buffer* bodyBuf, + const Buffer* shapeBuf, + adl::Buffer* contactsIn, SolverData contactCOut, void* additionalData, + int nContacts, const Solver::ConstraintCfg& cfg ) +{ + + + sortContacts2( data, bodyBuf, contactsIn, additionalData, nContacts, cfg ); + + { + SolverInl::ParallelSolveData* solveData = (SolverInl::ParallelSolveData*)data->m_parallelSolveData; + Buffer n; n.setRawPtr( data->m_device, solveData->m_n, adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT ); + Buffer offsets; offsets.setRawPtr( data->m_device, solveData->m_offset, adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT ); + Solver::batchContacts( data, contactsIn, nContacts, &n, &offsets, cfg.m_staticIdx ); + printf("hello\n"); + } + + Solver::convertToConstraints( data, bodyBuf, shapeBuf, contactsIn, contactCOut, additionalData, nContacts, cfg ); +} + +template +static void solveContactConstraint( Solver::Data* data, const Buffer* bodyBuf, const Buffer* shapeBuf, + SolverData constraint, void* additionalData, int n ) +{ + + Buffer* bodyNative + = BufferUtils::map( data->m_device, bodyBuf ); + Buffer* shapeNative + = BufferUtils::map( data->m_device, shapeBuf ); + Buffer* constraintNative + = BufferUtils::map( data->m_device, (const Buffer*)constraint ); + + for(int iter=0; iterm_nIterations; iter++) + { + SolveTask task( bodyNative, shapeNative, constraintNative, 0, n ); + task.m_solveFriction = false; + task.run(0); + } + + for(int iter=0; iterm_nIterations; iter++) + { + SolveTask task( bodyNative, shapeNative, constraintNative, 0, n ); + task.m_solveFriction = true; + task.run(0); + } + + BufferUtils::unmap( bodyNative, bodyBuf ); + BufferUtils::unmap( shapeNative, shapeBuf ); + BufferUtils::unmap( constraintNative, (const Buffer*)constraint ); +} + +#if 0 +static +int createSolveTasks( int batchIdx, Data* data, const Buffer* bodyBuf, const Buffer* shapeBuf, + SolverData constraint, int n, ThreadPool::Task* tasksOut[], int taskCapacity ) +{ +/* + ADLASSERT( (N_SPLIT&1) == 0 ); + ADLASSERT( batchIdx < N_BATCHES ); + ADLASSERT( data->m_device->m_type == TYPE_HOST ); + ADLASSERT( data->m_parallelSolveData ); + + SolverInl::ParallelSolveData* solveData = (SolverInl::ParallelSolveData*)data->m_parallelSolveData; + data->m_batchIdx = 0; + + const int nx = N_SPLIT/2; + + int nTasksCreated = 0; + +// for(int ii=0; ii<2; ii++) + for(batchIdx=0; batchIdx<4; batchIdx++) + { + int2 offset = make_int2( batchIdx&1, batchIdx>>1 ); + for(int ix=0; ixm_n[cellIdx]; + int start = solveData->m_offset[cellIdx]; + + if( n == 0 ) continue; + + SolveTask* task = new SolveTask( bodyBuf, shapeBuf, (const Buffer*)constraint, start, n ); +// task->m_solveFriction = (ii==0)? false:true; + tasksOut[nTasksCreated++] = task; + } + } + + return nTasksCreated; +*/ + ADLASSERT(0); + return 0; +} +#endif + + + +static void convertToConstraints2( Solver::Data* data, const Buffer* bodyBuf, + const Buffer* shapeBuf, + Buffer* contactsIn, SolverData contactCOut, void* additionalData, + int nContacts, const Solver::ConstraintCfg& cfg ) +{ + ADLASSERT( data->m_device->m_type == TYPE_HOST ); + + HostBuffer* bodyNative + = (HostBuffer*)BufferUtils::map( data->m_device, bodyBuf ); + HostBuffer* shapeNative + = (HostBuffer*)BufferUtils::map( data->m_device, shapeBuf ); + HostBuffer* contactNative + = (HostBuffer*)BufferUtils::map( data->m_device, contactsIn ); + HostBuffer* constraintNative + = (HostBuffer*)BufferUtils::map( data->m_device, (Buffer*)contactCOut ); + + { +#if !defined(_DEBUG) +#pragma omp parallel for +#endif + for(int i=0; i( bodyNative, bodyBuf ); + BufferUtils::unmap( shapeNative, shapeBuf ); + BufferUtils::unmap( contactNative, contactsIn ); + BufferUtils::unmap( constraintNative, (Buffer*)contactCOut ); +} + + + + + +static void batchContacts2( Solver::Data* data, Buffer* contacts, int nContacts, Buffer* n, Buffer* offsets, int staticIdx ) +{ + ADLASSERT( data->m_device->m_type == TYPE_HOST ); + + HostBuffer* contactNative =0; + HostBuffer* nNative =0; + HostBuffer* offsetsNative =0; + + int sz = sizeof(Contact4); + int sz2 = sizeof(int2); + { + BT_PROFILE("BufferUtils::map"); + contactNative = (HostBuffer*)BufferUtils::map( data->m_device, contacts, nContacts ); + } + { + BT_PROFILE("BufferUtils::map2"); + nNative = (HostBuffer*)BufferUtils::map( data->m_device, n ); + offsetsNative= (HostBuffer*)BufferUtils::map( data->m_device, offsets ); + } + + + { + BT_PROFILE("sortConstraintByBatch"); + int numNonzeroGrid=0; + int maxNumBatches = 0; + + for(int i=0; im_ptr+offset, n, staticIdx,-1 ); // on GPU + maxNumBatches = max(numBatches,maxNumBatches); + + // SolverInl::sortConstraintByBatch( contactNative->m_ptr+offset, n, staticIdx ); // on CPU + } + } + + printf("maxNumBatches = %d\n", maxNumBatches); + } + + { + BT_PROFILE("BufferUtils::unmap"); + BufferUtils::unmap( contactNative, contacts, nContacts ); + } + { + BT_PROFILE("BufferUtils::unmap2"); + BufferUtils::unmap( nNative, n ); + BufferUtils::unmap( offsetsNative, offsets ); + } + + +} + + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/SolverKernels.cl b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/SolverKernels.cl new file mode 100644 index 0000000..e461943 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/SolverKernels.cl @@ -0,0 +1,1051 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#pragma OPENCL EXTENSION cl_amd_printf : enable +#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable +#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable +#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable +#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable + + +#ifdef cl_ext_atomic_counters_32 +#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable +#else +#define counter32_t volatile global int* +#endif + +typedef unsigned int u32; +typedef unsigned short u16; +typedef unsigned char u8; + +#define GET_GROUP_IDX get_group_id(0) +#define GET_LOCAL_IDX get_local_id(0) +#define GET_GLOBAL_IDX get_global_id(0) +#define GET_GROUP_SIZE get_local_size(0) +#define GET_NUM_GROUPS get_num_groups(0) +#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE) +#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE) +#define AtomInc(x) atom_inc(&(x)) +#define AtomInc1(x, out) out = atom_inc(&(x)) +#define AppendInc(x, out) out = atomic_inc(x) +#define AtomAdd(x, value) atom_add(&(x), value) +#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value ) +#define AtomXhg(x, value) atom_xchg ( &(x), value ) + + +#define SELECT_UINT4( b, a, condition ) select( b,a,condition ) + +#define make_float4 (float4) +#define make_float2 (float2) +#define make_uint4 (uint4) +#define make_int4 (int4) +#define make_uint2 (uint2) +#define make_int2 (int2) + + +#define max2 max +#define min2 min + + +/////////////////////////////////////// +// Vector +/////////////////////////////////////// +__inline +float fastDiv(float numerator, float denominator) +{ + return native_divide(numerator, denominator); +// return numerator/denominator; +} + +__inline +float4 fastDiv4(float4 numerator, float4 denominator) +{ + return native_divide(numerator, denominator); +} + +__inline +float fastSqrtf(float f2) +{ + return native_sqrt(f2); +// return sqrt(f2); +} + +__inline +float fastRSqrt(float f2) +{ + return native_rsqrt(f2); +} + +__inline +float fastLength4(float4 v) +{ + return fast_length(v); +} + +__inline +float4 fastNormalize4(float4 v) +{ + return fast_normalize(v); +} + + +__inline +float sqrtf(float a) +{ +// return sqrt(a); + return native_sqrt(a); +} + +__inline +float4 cross3(float4 a, float4 b) +{ + return cross(a,b); +} + +__inline +float dot3F4(float4 a, float4 b) +{ + float4 a1 = make_float4(a.xyz,0.f); + float4 b1 = make_float4(b.xyz,0.f); + return dot(a1, b1); +} + +__inline +float length3(const float4 a) +{ + return sqrtf(dot3F4(a,a)); +} + +__inline +float dot4(const float4 a, const float4 b) +{ + return dot( a, b ); +} + +// for height +__inline +float dot3w1(const float4 point, const float4 eqn) +{ + return dot3F4(point,eqn) + eqn.w; +} + +__inline +float4 normalize3(const float4 a) +{ + float4 n = make_float4(a.x, a.y, a.z, 0.f); + return fastNormalize4( n ); +// float length = sqrtf(dot3F4(a, a)); +// return 1.f/length * a; +} + +__inline +float4 normalize4(const float4 a) +{ + float length = sqrtf(dot4(a, a)); + return 1.f/length * a; +} + +__inline +float4 createEquation(const float4 a, const float4 b, const float4 c) +{ + float4 eqn; + float4 ab = b-a; + float4 ac = c-a; + eqn = normalize3( cross3(ab, ac) ); + eqn.w = -dot3F4(eqn,a); + return eqn; +} + +/////////////////////////////////////// +// Matrix3x3 +/////////////////////////////////////// + +typedef struct +{ + float4 m_row[3]; +}Matrix3x3; + +__inline +Matrix3x3 mtZero(); + +__inline +Matrix3x3 mtIdentity(); + +__inline +Matrix3x3 mtTranspose(Matrix3x3 m); + +__inline +Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b); + +__inline +float4 mtMul1(Matrix3x3 a, float4 b); + +__inline +float4 mtMul3(float4 a, Matrix3x3 b); + +__inline +Matrix3x3 mtZero() +{ + Matrix3x3 m; + m.m_row[0] = (float4)(0.f); + m.m_row[1] = (float4)(0.f); + m.m_row[2] = (float4)(0.f); + return m; +} + +__inline +Matrix3x3 mtIdentity() +{ + Matrix3x3 m; + m.m_row[0] = (float4)(1,0,0,0); + m.m_row[1] = (float4)(0,1,0,0); + m.m_row[2] = (float4)(0,0,1,0); + return m; +} + +__inline +Matrix3x3 mtTranspose(Matrix3x3 m) +{ + Matrix3x3 out; + out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f); + out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f); + out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f); + return out; +} + +__inline +Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b) +{ + Matrix3x3 transB; + transB = mtTranspose( b ); + Matrix3x3 ans; + // why this doesn't run when 0ing in the for{} + a.m_row[0].w = 0.f; + a.m_row[1].w = 0.f; + a.m_row[2].w = 0.f; + for(int i=0; i<3; i++) + { +// a.m_row[i].w = 0.f; + ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]); + ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]); + ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]); + ans.m_row[i].w = 0.f; + } + return ans; +} + +__inline +float4 mtMul1(Matrix3x3 a, float4 b) +{ + float4 ans; + ans.x = dot3F4( a.m_row[0], b ); + ans.y = dot3F4( a.m_row[1], b ); + ans.z = dot3F4( a.m_row[2], b ); + ans.w = 0.f; + return ans; +} + +__inline +float4 mtMul3(float4 a, Matrix3x3 b) +{ + float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0); + float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0); + float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0); + + float4 ans; + ans.x = dot3F4( a, colx ); + ans.y = dot3F4( a, coly ); + ans.z = dot3F4( a, colz ); + return ans; +} + +/////////////////////////////////////// +// Quaternion +/////////////////////////////////////// + +typedef float4 Quaternion; + +__inline +Quaternion qtMul(Quaternion a, Quaternion b); + +__inline +Quaternion qtNormalize(Quaternion in); + +__inline +float4 qtRotate(Quaternion q, float4 vec); + +__inline +Quaternion qtInvert(Quaternion q); + +__inline +Matrix3x3 qtGetRotationMatrix(Quaternion q); + + + +__inline +Quaternion qtMul(Quaternion a, Quaternion b) +{ + Quaternion ans; + ans = cross3( a, b ); + ans += a.w*b+b.w*a; +// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z); + ans.w = a.w*b.w - dot3F4(a, b); + return ans; +} + +__inline +Quaternion qtNormalize(Quaternion in) +{ + return fastNormalize4(in); +// in /= length( in ); +// return in; +} +__inline +float4 qtRotate(Quaternion q, float4 vec) +{ + Quaternion qInv = qtInvert( q ); + float4 vcpy = vec; + vcpy.w = 0.f; + float4 out = qtMul(qtMul(q,vcpy),qInv); + return out; +} + +__inline +Quaternion qtInvert(Quaternion q) +{ + return (Quaternion)(-q.xyz, q.w); +} + +__inline +float4 qtInvRotate(const Quaternion q, float4 vec) +{ + return qtRotate( qtInvert( q ), vec ); +} + +__inline +Matrix3x3 qtGetRotationMatrix(Quaternion quat) +{ + float4 quat2 = (float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f); + Matrix3x3 out; + + out.m_row[0].x=1-2*quat2.y-2*quat2.z; + out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z; + out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y; + out.m_row[0].w = 0.f; + + out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z; + out.m_row[1].y=1-2*quat2.x-2*quat2.z; + out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x; + out.m_row[1].w = 0.f; + + out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y; + out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x; + out.m_row[2].z=1-2*quat2.x-2*quat2.y; + out.m_row[2].w = 0.f; + + return out; +} + + + + +#define WG_SIZE 64 + +typedef struct +{ + float4 m_pos; + Quaternion m_quat; + float4 m_linVel; + float4 m_angVel; + + u32 m_shapeIdx; + u32 m_shapeType; + float m_invMass; + float m_restituitionCoeff; + float m_frictionCoeff; +} Body; + +typedef struct +{ + Matrix3x3 m_invInertia; + Matrix3x3 m_initInvInertia; +} Shape; + +typedef struct +{ + float4 m_linear; + float4 m_worldPos[4]; + float4 m_center; + float m_jacCoeffInv[4]; + float m_b[4]; + float m_appliedRambdaDt[4]; + + float m_fJacCoeffInv[2]; + float m_fAppliedRambdaDt[2]; + + u32 m_bodyA; + u32 m_bodyB; + + int m_batchIdx; + u32 m_paddings[1]; +} Constraint4; + +typedef struct +{ + float4 m_worldPos[4]; + float4 m_worldNormal; + u32 m_coeffs; + int m_batchIdx; + + u32 m_bodyAPtr; + u32 m_bodyBPtr; +} Contact4; + +typedef struct +{ + int m_nConstraints; + int m_start; + int m_batchIdx; + int m_nSplit; +// int m_paddings[1]; +} ConstBuffer; + +typedef struct +{ + int m_solveFriction; + int m_maxBatch; // long batch really kills the performance + int m_batchIdx; + int m_nSplit; +// int m_paddings[1]; +} ConstBufferBatchSolve; + + +void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1) +{ + *linear = -n; + *angular0 = -cross3(r0, n); + *angular1 = cross3(r1, n); +} + + +float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 ) +{ + return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1); +} + + +float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1, + float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1) +{ + // linear0,1 are normlized + float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0; + float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0); + float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1; + float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1); + return -1.f/(jmj0+jmj1+jmj2+jmj3); +} + + + +void solveContact(__global Constraint4* cs, + float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA, + float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB) +{ + float minRambdaDt = 0; + float maxRambdaDt = FLT_MAX; + + for(int ic=0; ic<4; ic++) + { + if( cs->m_jacCoeffInv[ic] == 0.f ) continue; + + float4 angular0, angular1, linear; + float4 r0 = cs->m_worldPos[ic] - posA; + float4 r1 = cs->m_worldPos[ic] - posB; + setLinearAndAngular( -cs->m_linear, r0, r1, &linear, &angular0, &angular1 ); + + float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1, + *linVelA, *angVelA, *linVelB, *angVelB ) + cs->m_b[ic]; + rambdaDt *= cs->m_jacCoeffInv[ic]; + + { + float prevSum = cs->m_appliedRambdaDt[ic]; + float updated = prevSum; + updated += rambdaDt; + updated = max2( updated, minRambdaDt ); + updated = min2( updated, maxRambdaDt ); + rambdaDt = updated - prevSum; + cs->m_appliedRambdaDt[ic] = updated; + } + + float4 linImp0 = invMassA*linear*rambdaDt; + float4 linImp1 = invMassB*(-linear)*rambdaDt; + float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt; + float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt; + + *linVelA += linImp0; + *angVelA += angImp0; + *linVelB += linImp1; + *angVelB += angImp1; + } +} + + +void solveFriction(__global Constraint4* cs, + float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA, + float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB, + float maxRambdaDt[4], float minRambdaDt[4]) +{ + if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return; + const float4 center = cs->m_center; + + float4 n = -cs->m_linear; + + float4 tangent[2]; + tangent[0] = cross3( n, cs->m_worldPos[0]-center ); + tangent[1] = cross3( tangent[0], n ); + tangent[0] = normalize3( tangent[0] ); + tangent[1] = normalize3( tangent[1] ); + + float4 angular0, angular1, linear; + float4 r0 = center - posA; + float4 r1 = center - posB; + for(int i=0; i<2; i++) + { + setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 ); + float rambdaDt = calcRelVel(linear, -linear, angular0, angular1, + *linVelA, *angVelA, *linVelB, *angVelB ); + rambdaDt *= cs->m_fJacCoeffInv[i]; + + { + float prevSum = cs->m_fAppliedRambdaDt[i]; + float updated = prevSum; + updated += rambdaDt; + updated = max2( updated, minRambdaDt[i] ); + updated = min2( updated, maxRambdaDt[i] ); + rambdaDt = updated - prevSum; + cs->m_fAppliedRambdaDt[i] = updated; + } + + float4 linImp0 = invMassA*linear*rambdaDt; + float4 linImp1 = invMassB*(-linear)*rambdaDt; + float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt; + float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt; + + *linVelA += linImp0; + *angVelA += angImp0; + *linVelB += linImp1; + *angVelB += angImp1; + } + { // angular damping for point constraint + float4 ab = normalize3( posB - posA ); + float4 ac = normalize3( center - posA ); + if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f)) + { + float angNA = dot3F4( n, *angVelA ); + float angNB = dot3F4( n, *angVelB ); + + *angVelA -= (angNA*0.1f)*n; + *angVelB -= (angNB*0.1f)*n; + } + } +} + +void solveAConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs) +{ + float frictionCoeff = ldsCs[0].m_linear.w; + int aIdx = ldsCs[0].m_bodyA; + int bIdx = ldsCs[0].m_bodyB; + + float4 posA = gBodies[aIdx].m_pos; + float4 linVelA = gBodies[aIdx].m_linVel; + float4 angVelA = gBodies[aIdx].m_angVel; + float invMassA = gBodies[aIdx].m_invMass; + Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia; + + float4 posB = gBodies[bIdx].m_pos; + float4 linVelB = gBodies[bIdx].m_linVel; + float4 angVelB = gBodies[bIdx].m_angVel; + float invMassB = gBodies[bIdx].m_invMass; + Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia; + + + { + solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA, + posB, &linVelB, &angVelB, invMassB, invInertiaB ); + } + + { + float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX}; + float minRambdaDt[4] = {0.f,0.f,0.f,0.f}; + + float sum = 0; + for(int j=0; j<4; j++) + { + sum +=ldsCs[0].m_appliedRambdaDt[j]; + } + frictionCoeff = 0.7f; + for(int j=0; j<4; j++) + { + maxRambdaDt[j] = frictionCoeff*sum; + minRambdaDt[j] = -maxRambdaDt[j]; + } + + solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA, + posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt ); + } + + gBodies[aIdx].m_linVel = linVelA; + gBodies[aIdx].m_angVel = angVelA; + gBodies[bIdx].m_linVel = linVelB; + gBodies[bIdx].m_angVel = angVelB; +} + +void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs) +{ + float frictionCoeff = ldsCs[0].m_linear.w; + int aIdx = ldsCs[0].m_bodyA; + int bIdx = ldsCs[0].m_bodyB; + + float4 posA = gBodies[aIdx].m_pos; + float4 linVelA = gBodies[aIdx].m_linVel; + float4 angVelA = gBodies[aIdx].m_angVel; + float invMassA = gBodies[aIdx].m_invMass; + Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia; + + float4 posB = gBodies[bIdx].m_pos; + float4 linVelB = gBodies[bIdx].m_linVel; + float4 angVelB = gBodies[bIdx].m_angVel; + float invMassB = gBodies[bIdx].m_invMass; + Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia; + + solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA, + posB, &linVelB, &angVelB, invMassB, invInertiaB ); + + gBodies[aIdx].m_linVel = linVelA; + gBodies[aIdx].m_angVel = angVelA; + gBodies[bIdx].m_linVel = linVelB; + gBodies[bIdx].m_angVel = angVelB; +} + +void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs) +{ + float frictionCoeff = ldsCs[0].m_linear.w; + int aIdx = ldsCs[0].m_bodyA; + int bIdx = ldsCs[0].m_bodyB; + + float4 posA = gBodies[aIdx].m_pos; + float4 linVelA = gBodies[aIdx].m_linVel; + float4 angVelA = gBodies[aIdx].m_angVel; + float invMassA = gBodies[aIdx].m_invMass; + Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia; + + float4 posB = gBodies[bIdx].m_pos; + float4 linVelB = gBodies[bIdx].m_linVel; + float4 angVelB = gBodies[bIdx].m_angVel; + float invMassB = gBodies[bIdx].m_invMass; + Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia; + + { + float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX}; + float minRambdaDt[4] = {0.f,0.f,0.f,0.f}; + + float sum = 0; + for(int j=0; j<4; j++) + { + sum +=ldsCs[0].m_appliedRambdaDt[j]; + } + frictionCoeff = 0.7f; + for(int j=0; j<4; j++) + { + maxRambdaDt[j] = frictionCoeff*sum; + minRambdaDt[j] = -maxRambdaDt[j]; + } + + solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA, + posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt ); + } + + gBodies[aIdx].m_linVel = linVelA; + gBodies[aIdx].m_angVel = angVelA; + gBodies[bIdx].m_linVel = linVelB; + gBodies[bIdx].m_angVel = angVelB; +} + +typedef struct +{ + int m_valInt0; + int m_valInt1; + int m_valInt2; + int m_valInt3; + + float m_val0; + float m_val1; + float m_val2; + float m_val3; +} SolverDebugInfo; + + +__kernel +__attribute__((reqd_work_group_size(WG_SIZE,1,1))) +//void BatchSolveKernel(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* gConstraints, __global int* gN, __global int* gOffsets, __global SolverDebugInfo* debugInfo, ConstBufferBatchSolve cb) +void BatchSolveKernel(__global Body* gBodies, +__global Shape* gShapes, +__global Constraint4* gConstraints, +__global int* gN, +__global int* gOffsets, +ConstBufferBatchSolve cb) +{ + __local int ldsBatchIdx[WG_SIZE+1]; + + __local int ldsCurBatch; + __local int ldsNextBatch; + __local int ldsStart; + + int lIdx = GET_LOCAL_IDX; + int wgIdx = GET_GROUP_IDX; + + int gIdx = GET_GLOBAL_IDX; +// debugInfo[gIdx].m_valInt0 = gIdx; + //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE; + + const int solveFriction = cb.m_solveFriction; + const int maxBatch = cb.m_maxBatch; + const int bIdx = cb.m_batchIdx; + const int nSplit = cb.m_nSplit; + + int xIdx = (wgIdx/(nSplit/2))*2 + (bIdx&1); + int yIdx = (wgIdx%(nSplit/2))*2 + (bIdx>>1); + int cellIdx = xIdx+yIdx*nSplit; + + if( gN[cellIdx] == 0 ) + return; + + const int start = gOffsets[cellIdx]; + const int end = start + gN[cellIdx]; + + + if( lIdx == 0 ) + { + ldsCurBatch = 0; + ldsNextBatch = 0; + ldsStart = start; + } + + + GROUP_LDS_BARRIER; + + int idx=ldsStart+lIdx; + while (ldsCurBatch < maxBatch) + { + for(; idxm_bodyA = src.m_bodyAPtr; + dstC->m_bodyB = src.m_bodyBPtr; + + float dtInv = 1.f/dt; + for(int ic=0; ic<4; ic++) + { + dstC->m_appliedRambdaDt[ic] = 0.f; + } + dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f; + + + dstC->m_linear = -src.m_worldNormal; + dstC->m_linear.w = 0.7f ;//src.getFrictionCoeff() ); + for(int ic=0; ic<4; ic++) + { + float4 r0 = src.m_worldPos[ic] - posA; + float4 r1 = src.m_worldPos[ic] - posB; + + if( ic >= src.m_worldNormal.w )//npoints + { + dstC->m_jacCoeffInv[ic] = 0.f; + continue; + } + + float relVelN; + { + float4 linear, angular0, angular1; + setLinearAndAngular(src.m_worldNormal, r0, r1, &linear, &angular0, &angular1); + + dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1, + invMassA, &invInertiaA, invMassB, &invInertiaB ); + + relVelN = calcRelVel(linear, -linear, angular0, angular1, + linVelA, angVelA, linVelB, angVelB); + + float e = 0.f;//src.getRestituitionCoeff(); + if( relVelN*relVelN < 0.004f ) e = 0.f; + + dstC->m_b[ic] = e*relVelN; + //float penetration = src.m_worldPos[ic].w; + dstC->m_b[ic] += (src.m_worldPos[ic].w + positionDrift)*positionConstraintCoeff*dtInv; + dstC->m_appliedRambdaDt[ic] = 0.f; + } + } + + if( src.m_worldNormal.w > 1 )//npoints + { // prepare friction + float4 center = make_float4(0.f); + for(int i=0; im_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1, + invMassA, &invInertiaA, invMassB, &invInertiaB ); + dstC->m_fAppliedRambdaDt[i] = 0.f; + } + dstC->m_center = center; + } + else + { + // single point constraint + } + + for(int i=0; i<4; i++) + { + if( im_worldPos[i] = src.m_worldPos[i]; + } + else + { + dstC->m_worldPos[i] = make_float4(0.f); + } + } +} + +typedef struct +{ + int m_nContacts; + float m_dt; + float m_positionDrift; + float m_positionConstraintCoeff; +} ConstBufferCTC; + +__kernel +__attribute__((reqd_work_group_size(WG_SIZE,1,1))) +void ContactToConstraintKernel(__global Contact4* gContact, __global Body* gBodies, __global Shape* gShapes, __global Constraint4* gConstraintOut, ConstBufferCTC cb) +{ + int gIdx = GET_GLOBAL_IDX; + int nContacts = cb.m_nContacts; + float dt = cb.m_dt; + float positionDrift = cb.m_positionDrift; + float positionConstraintCoeff = cb.m_positionConstraintCoeff; + + if( gIdx < nContacts ) + { + int aIdx = gContact[gIdx].m_bodyAPtr; + int bIdx = gContact[gIdx].m_bodyBPtr; + + float4 posA = gBodies[aIdx].m_pos; + float4 linVelA = gBodies[aIdx].m_linVel; + float4 angVelA = gBodies[aIdx].m_angVel; + float invMassA = gBodies[aIdx].m_invMass; + Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia; + + float4 posB = gBodies[bIdx].m_pos; + float4 linVelB = gBodies[bIdx].m_linVel; + float4 angVelB = gBodies[bIdx].m_angVel; + float invMassB = gBodies[bIdx].m_invMass; + Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia; + + Constraint4 cs; + + setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB, + gContact[gIdx], dt, positionDrift, positionConstraintCoeff, + &cs ); + + cs.m_batchIdx = gContact[gIdx].m_batchIdx; + + gConstraintOut[gIdx] = cs; + } +} + +__kernel +__attribute__((reqd_work_group_size(WG_SIZE,1,1))) +void CopyConstraintKernel(__global Contact4* gIn, __global Contact4* gOut, int4 cb ) +{ + int gIdx = GET_GLOBAL_IDX; + if( gIdx < cb.x ) + { + gOut[gIdx] = gIn[gIdx]; + } +} \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/SolverKernels.h b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/SolverKernels.h new file mode 100644 index 0000000..c80a6ae --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/SolverKernels.h @@ -0,0 +1,1037 @@ +static const char* solverKernelsCL= \ +"#pragma OPENCL EXTENSION cl_amd_printf : enable\n" +"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n" +"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n" +"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n" +"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n" +"\n" +"\n" +"#ifdef cl_ext_atomic_counters_32\n" +"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n" +"#else\n" +"#define counter32_t volatile global int*\n" +"#endif\n" +"\n" +"typedef unsigned int u32;\n" +"typedef unsigned short u16;\n" +"typedef unsigned char u8;\n" +"\n" +"#define GET_GROUP_IDX get_group_id(0)\n" +"#define GET_LOCAL_IDX get_local_id(0)\n" +"#define GET_GLOBAL_IDX get_global_id(0)\n" +"#define GET_GROUP_SIZE get_local_size(0)\n" +"#define GET_NUM_GROUPS get_num_groups(0)\n" +"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n" +"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n" +"#define AtomInc(x) atom_inc(&(x))\n" +"#define AtomInc1(x, out) out = atom_inc(&(x))\n" +"#define AppendInc(x, out) out = atomic_inc(x)\n" +"#define AtomAdd(x, value) atom_add(&(x), value)\n" +"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n" +"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n" +"\n" +"\n" +"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n" +"\n" +"#define make_float4 (float4)\n" +"#define make_float2 (float2)\n" +"#define make_uint4 (uint4)\n" +"#define make_int4 (int4)\n" +"#define make_uint2 (uint2)\n" +"#define make_int2 (int2)\n" +"\n" +"\n" +"#define max2 max\n" +"#define min2 min\n" +"\n" +"\n" +"///////////////////////////////////////\n" +"// Vector\n" +"///////////////////////////////////////\n" +"__inline\n" +"float fastDiv(float numerator, float denominator)\n" +"{\n" +" return native_divide(numerator, denominator); \n" +"// return numerator/denominator; \n" +"}\n" +"\n" +"__inline\n" +"float4 fastDiv4(float4 numerator, float4 denominator)\n" +"{\n" +" return native_divide(numerator, denominator); \n" +"}\n" +"\n" +"__inline\n" +"float fastSqrtf(float f2)\n" +"{\n" +" return native_sqrt(f2);\n" +"// return sqrt(f2);\n" +"}\n" +"\n" +"__inline\n" +"float fastRSqrt(float f2)\n" +"{\n" +" return native_rsqrt(f2);\n" +"}\n" +"\n" +"__inline\n" +"float fastLength4(float4 v)\n" +"{\n" +" return fast_length(v);\n" +"}\n" +"\n" +"__inline\n" +"float4 fastNormalize4(float4 v)\n" +"{\n" +" return fast_normalize(v);\n" +"}\n" +"\n" +"\n" +"__inline\n" +"float sqrtf(float a)\n" +"{\n" +"// return sqrt(a);\n" +" return native_sqrt(a);\n" +"}\n" +"\n" +"__inline\n" +"float4 cross3(float4 a, float4 b)\n" +"{\n" +" return cross(a,b);\n" +"}\n" +"\n" +"__inline\n" +"float dot3F4(float4 a, float4 b)\n" +"{\n" +" float4 a1 = make_float4(a.xyz,0.f);\n" +" float4 b1 = make_float4(b.xyz,0.f);\n" +" return dot(a1, b1);\n" +"}\n" +"\n" +"__inline\n" +"float length3(const float4 a)\n" +"{\n" +" return sqrtf(dot3F4(a,a));\n" +"}\n" +"\n" +"__inline\n" +"float dot4(const float4 a, const float4 b)\n" +"{\n" +" return dot( a, b );\n" +"}\n" +"\n" +"// for height\n" +"__inline\n" +"float dot3w1(const float4 point, const float4 eqn)\n" +"{\n" +" return dot3F4(point,eqn) + eqn.w;\n" +"}\n" +"\n" +"__inline\n" +"float4 normalize3(const float4 a)\n" +"{\n" +" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n" +" return fastNormalize4( n );\n" +"// float length = sqrtf(dot3F4(a, a));\n" +"// return 1.f/length * a;\n" +"}\n" +"\n" +"__inline\n" +"float4 normalize4(const float4 a)\n" +"{\n" +" float length = sqrtf(dot4(a, a));\n" +" return 1.f/length * a;\n" +"}\n" +"\n" +"__inline\n" +"float4 createEquation(const float4 a, const float4 b, const float4 c)\n" +"{\n" +" float4 eqn;\n" +" float4 ab = b-a;\n" +" float4 ac = c-a;\n" +" eqn = normalize3( cross3(ab, ac) );\n" +" eqn.w = -dot3F4(eqn,a);\n" +" return eqn;\n" +"}\n" +"\n" +"///////////////////////////////////////\n" +"// Matrix3x3\n" +"///////////////////////////////////////\n" +"\n" +"typedef struct\n" +"{\n" +" float4 m_row[3];\n" +"}Matrix3x3;\n" +"\n" +"__inline\n" +"Matrix3x3 mtZero();\n" +"\n" +"__inline\n" +"Matrix3x3 mtIdentity();\n" +"\n" +"__inline\n" +"Matrix3x3 mtTranspose(Matrix3x3 m);\n" +"\n" +"__inline\n" +"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);\n" +"\n" +"__inline\n" +"float4 mtMul1(Matrix3x3 a, float4 b);\n" +"\n" +"__inline\n" +"float4 mtMul3(float4 a, Matrix3x3 b);\n" +"\n" +"__inline\n" +"Matrix3x3 mtZero()\n" +"{\n" +" Matrix3x3 m;\n" +" m.m_row[0] = (float4)(0.f);\n" +" m.m_row[1] = (float4)(0.f);\n" +" m.m_row[2] = (float4)(0.f);\n" +" return m;\n" +"}\n" +"\n" +"__inline\n" +"Matrix3x3 mtIdentity()\n" +"{\n" +" Matrix3x3 m;\n" +" m.m_row[0] = (float4)(1,0,0,0);\n" +" m.m_row[1] = (float4)(0,1,0,0);\n" +" m.m_row[2] = (float4)(0,0,1,0);\n" +" return m;\n" +"}\n" +"\n" +"__inline\n" +"Matrix3x3 mtTranspose(Matrix3x3 m)\n" +"{\n" +" Matrix3x3 out;\n" +" out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n" +" out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n" +" out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n" +" return out;\n" +"}\n" +"\n" +"__inline\n" +"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)\n" +"{\n" +" Matrix3x3 transB;\n" +" transB = mtTranspose( b );\n" +" Matrix3x3 ans;\n" +" // why this doesn't run when 0ing in the for{}\n" +" a.m_row[0].w = 0.f;\n" +" a.m_row[1].w = 0.f;\n" +" a.m_row[2].w = 0.f;\n" +" for(int i=0; i<3; i++)\n" +" {\n" +"// a.m_row[i].w = 0.f;\n" +" ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);\n" +" ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);\n" +" ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);\n" +" ans.m_row[i].w = 0.f;\n" +" }\n" +" return ans;\n" +"}\n" +"\n" +"__inline\n" +"float4 mtMul1(Matrix3x3 a, float4 b)\n" +"{\n" +" float4 ans;\n" +" ans.x = dot3F4( a.m_row[0], b );\n" +" ans.y = dot3F4( a.m_row[1], b );\n" +" ans.z = dot3F4( a.m_row[2], b );\n" +" ans.w = 0.f;\n" +" return ans;\n" +"}\n" +"\n" +"__inline\n" +"float4 mtMul3(float4 a, Matrix3x3 b)\n" +"{\n" +" float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n" +" float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n" +" float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n" +"\n" +" float4 ans;\n" +" ans.x = dot3F4( a, colx );\n" +" ans.y = dot3F4( a, coly );\n" +" ans.z = dot3F4( a, colz );\n" +" return ans;\n" +"}\n" +"\n" +"///////////////////////////////////////\n" +"// Quaternion\n" +"///////////////////////////////////////\n" +"\n" +"typedef float4 Quaternion;\n" +"\n" +"__inline\n" +"Quaternion qtMul(Quaternion a, Quaternion b);\n" +"\n" +"__inline\n" +"Quaternion qtNormalize(Quaternion in);\n" +"\n" +"__inline\n" +"float4 qtRotate(Quaternion q, float4 vec);\n" +"\n" +"__inline\n" +"Quaternion qtInvert(Quaternion q);\n" +"\n" +"__inline\n" +"Matrix3x3 qtGetRotationMatrix(Quaternion q);\n" +"\n" +"\n" +"\n" +"__inline\n" +"Quaternion qtMul(Quaternion a, Quaternion b)\n" +"{\n" +" Quaternion ans;\n" +" ans = cross3( a, b );\n" +" ans += a.w*b+b.w*a;\n" +"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n" +" ans.w = a.w*b.w - dot3F4(a, b);\n" +" return ans;\n" +"}\n" +"\n" +"__inline\n" +"Quaternion qtNormalize(Quaternion in)\n" +"{\n" +" return fastNormalize4(in);\n" +"// in /= length( in );\n" +"// return in;\n" +"}\n" +"__inline\n" +"float4 qtRotate(Quaternion q, float4 vec)\n" +"{\n" +" Quaternion qInv = qtInvert( q );\n" +" float4 vcpy = vec;\n" +" vcpy.w = 0.f;\n" +" float4 out = qtMul(qtMul(q,vcpy),qInv);\n" +" return out;\n" +"}\n" +"\n" +"__inline\n" +"Quaternion qtInvert(Quaternion q)\n" +"{\n" +" return (Quaternion)(-q.xyz, q.w);\n" +"}\n" +"\n" +"__inline\n" +"float4 qtInvRotate(const Quaternion q, float4 vec)\n" +"{\n" +" return qtRotate( qtInvert( q ), vec );\n" +"}\n" +"\n" +"__inline\n" +"Matrix3x3 qtGetRotationMatrix(Quaternion quat)\n" +"{\n" +" float4 quat2 = (float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n" +" Matrix3x3 out;\n" +"\n" +" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n" +" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n" +" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n" +" out.m_row[0].w = 0.f;\n" +"\n" +" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n" +" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n" +" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n" +" out.m_row[1].w = 0.f;\n" +"\n" +" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n" +" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n" +" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n" +" out.m_row[2].w = 0.f;\n" +"\n" +" return out;\n" +"}\n" +"\n" +"\n" +"\n" +"\n" +"#define WG_SIZE 64\n" +"\n" +"typedef struct\n" +"{\n" +" float4 m_pos;\n" +" Quaternion m_quat;\n" +" float4 m_linVel;\n" +" float4 m_angVel;\n" +"\n" +" u32 m_shapeIdx;\n" +" u32 m_shapeType;\n" +" float m_invMass;\n" +" float m_restituitionCoeff;\n" +" float m_frictionCoeff;\n" +"} Body;\n" +"\n" +"typedef struct\n" +"{\n" +" Matrix3x3 m_invInertia;\n" +" Matrix3x3 m_initInvInertia;\n" +"} Shape;\n" +"\n" +"typedef struct\n" +"{\n" +" float4 m_linear;\n" +" float4 m_worldPos[4];\n" +" float4 m_center; \n" +" float m_jacCoeffInv[4];\n" +" float m_b[4];\n" +" float m_appliedRambdaDt[4];\n" +"\n" +" float m_fJacCoeffInv[2]; \n" +" float m_fAppliedRambdaDt[2]; \n" +"\n" +" u32 m_bodyA;\n" +" u32 m_bodyB;\n" +"\n" +" int m_batchIdx;\n" +" u32 m_paddings[1];\n" +"} Constraint4;\n" +"\n" +"typedef struct\n" +"{\n" +" float4 m_worldPos[4];\n" +" float4 m_worldNormal;\n" +" u32 m_coeffs;\n" +" int m_batchIdx;\n" +"\n" +" u32 m_bodyAPtr;\n" +" u32 m_bodyBPtr;\n" +"} Contact4;\n" +"\n" +"typedef struct\n" +"{\n" +" int m_nConstraints;\n" +" int m_start;\n" +" int m_batchIdx;\n" +" int m_nSplit;\n" +"// int m_paddings[1];\n" +"} ConstBuffer;\n" +"\n" +"typedef struct\n" +"{\n" +" int m_solveFriction;\n" +" int m_maxBatch; // long batch really kills the performance\n" +" int m_batchIdx;\n" +" int m_nSplit;\n" +"// int m_paddings[1];\n" +"} ConstBufferBatchSolve;\n" +"\n" +"\n" +"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n" +"{\n" +" *linear = -n;\n" +" *angular0 = -cross3(r0, n);\n" +" *angular1 = cross3(r1, n);\n" +"}\n" +"\n" +"\n" +"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n" +"{\n" +" return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n" +"}\n" +"\n" +"\n" +"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n" +" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)\n" +"{\n" +" // linear0,1 are normlized\n" +" float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n" +" float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n" +" float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n" +" float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n" +" return -1.f/(jmj0+jmj1+jmj2+jmj3);\n" +"}\n" +"\n" +"\n" +"\n" +"void solveContact(__global Constraint4* cs,\n" +" float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n" +" float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB)\n" +"{\n" +" float minRambdaDt = 0;\n" +" float maxRambdaDt = FLT_MAX;\n" +"\n" +" for(int ic=0; ic<4; ic++)\n" +" {\n" +" if( cs->m_jacCoeffInv[ic] == 0.f ) continue;\n" +"\n" +" float4 angular0, angular1, linear;\n" +" float4 r0 = cs->m_worldPos[ic] - posA;\n" +" float4 r1 = cs->m_worldPos[ic] - posB;\n" +" setLinearAndAngular( -cs->m_linear, r0, r1, &linear, &angular0, &angular1 );\n" +"\n" +" float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1, \n" +" *linVelA, *angVelA, *linVelB, *angVelB ) + cs->m_b[ic];\n" +" rambdaDt *= cs->m_jacCoeffInv[ic];\n" +"\n" +" {\n" +" float prevSum = cs->m_appliedRambdaDt[ic];\n" +" float updated = prevSum;\n" +" updated += rambdaDt;\n" +" updated = max2( updated, minRambdaDt );\n" +" updated = min2( updated, maxRambdaDt );\n" +" rambdaDt = updated - prevSum;\n" +" cs->m_appliedRambdaDt[ic] = updated;\n" +" }\n" +"\n" +" float4 linImp0 = invMassA*linear*rambdaDt;\n" +" float4 linImp1 = invMassB*(-linear)*rambdaDt;\n" +" float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n" +" float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n" +"\n" +" *linVelA += linImp0;\n" +" *angVelA += angImp0;\n" +" *linVelB += linImp1;\n" +" *angVelB += angImp1;\n" +" }\n" +"}\n" +"\n" +"\n" +"void solveFriction(__global Constraint4* cs,\n" +" float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n" +" float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB,\n" +" float maxRambdaDt[4], float minRambdaDt[4])\n" +"{\n" +" if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;\n" +" const float4 center = cs->m_center;\n" +"\n" +" float4 n = -cs->m_linear;\n" +"\n" +" float4 tangent[2];\n" +" tangent[0] = cross3( n, cs->m_worldPos[0]-center );\n" +" tangent[1] = cross3( tangent[0], n );\n" +" tangent[0] = normalize3( tangent[0] );\n" +" tangent[1] = normalize3( tangent[1] );\n" +"\n" +" float4 angular0, angular1, linear;\n" +" float4 r0 = center - posA;\n" +" float4 r1 = center - posB;\n" +" for(int i=0; i<2; i++)\n" +" {\n" +" setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );\n" +" float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,\n" +" *linVelA, *angVelA, *linVelB, *angVelB );\n" +" rambdaDt *= cs->m_fJacCoeffInv[i];\n" +"\n" +" {\n" +" float prevSum = cs->m_fAppliedRambdaDt[i];\n" +" float updated = prevSum;\n" +" updated += rambdaDt;\n" +" updated = max2( updated, minRambdaDt[i] );\n" +" updated = min2( updated, maxRambdaDt[i] );\n" +" rambdaDt = updated - prevSum;\n" +" cs->m_fAppliedRambdaDt[i] = updated;\n" +" }\n" +"\n" +" float4 linImp0 = invMassA*linear*rambdaDt;\n" +" float4 linImp1 = invMassB*(-linear)*rambdaDt;\n" +" float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n" +" float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n" +"\n" +" *linVelA += linImp0;\n" +" *angVelA += angImp0;\n" +" *linVelB += linImp1;\n" +" *angVelB += angImp1;\n" +" }\n" +" { // angular damping for point constraint\n" +" float4 ab = normalize3( posB - posA );\n" +" float4 ac = normalize3( center - posA );\n" +" if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))\n" +" {\n" +" float angNA = dot3F4( n, *angVelA );\n" +" float angNB = dot3F4( n, *angVelB );\n" +"\n" +" *angVelA -= (angNA*0.1f)*n;\n" +" *angVelB -= (angNB*0.1f)*n;\n" +" }\n" +" }\n" +"}\n" +"\n" +"void solveAConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)\n" +"{\n" +" float frictionCoeff = ldsCs[0].m_linear.w;\n" +" int aIdx = ldsCs[0].m_bodyA;\n" +" int bIdx = ldsCs[0].m_bodyB;\n" +"\n" +" float4 posA = gBodies[aIdx].m_pos;\n" +" float4 linVelA = gBodies[aIdx].m_linVel;\n" +" float4 angVelA = gBodies[aIdx].m_angVel;\n" +" float invMassA = gBodies[aIdx].m_invMass;\n" +" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n" +"\n" +" float4 posB = gBodies[bIdx].m_pos;\n" +" float4 linVelB = gBodies[bIdx].m_linVel;\n" +" float4 angVelB = gBodies[bIdx].m_angVel;\n" +" float invMassB = gBodies[bIdx].m_invMass;\n" +" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n" +" \n" +" \n" +" {\n" +" solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n" +" posB, &linVelB, &angVelB, invMassB, invInertiaB );\n" +" }\n" +"\n" +" {\n" +" float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};\n" +" float minRambdaDt[4] = {0.f,0.f,0.f,0.f};\n" +"\n" +" float sum = 0;\n" +" for(int j=0; j<4; j++)\n" +" {\n" +" sum +=ldsCs[0].m_appliedRambdaDt[j];\n" +" }\n" +" frictionCoeff = 0.7f;\n" +" for(int j=0; j<4; j++)\n" +" {\n" +" maxRambdaDt[j] = frictionCoeff*sum;\n" +" minRambdaDt[j] = -maxRambdaDt[j];\n" +" }\n" +"\n" +" solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n" +" posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );\n" +" }\n" +"\n" +" gBodies[aIdx].m_linVel = linVelA;\n" +" gBodies[aIdx].m_angVel = angVelA;\n" +" gBodies[bIdx].m_linVel = linVelB;\n" +" gBodies[bIdx].m_angVel = angVelB;\n" +"}\n" +"\n" +"void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)\n" +"{\n" +" float frictionCoeff = ldsCs[0].m_linear.w;\n" +" int aIdx = ldsCs[0].m_bodyA;\n" +" int bIdx = ldsCs[0].m_bodyB;\n" +"\n" +" float4 posA = gBodies[aIdx].m_pos;\n" +" float4 linVelA = gBodies[aIdx].m_linVel;\n" +" float4 angVelA = gBodies[aIdx].m_angVel;\n" +" float invMassA = gBodies[aIdx].m_invMass;\n" +" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n" +"\n" +" float4 posB = gBodies[bIdx].m_pos;\n" +" float4 linVelB = gBodies[bIdx].m_linVel;\n" +" float4 angVelB = gBodies[bIdx].m_angVel;\n" +" float invMassB = gBodies[bIdx].m_invMass;\n" +" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n" +"\n" +" solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n" +" posB, &linVelB, &angVelB, invMassB, invInertiaB );\n" +"\n" +" gBodies[aIdx].m_linVel = linVelA;\n" +" gBodies[aIdx].m_angVel = angVelA;\n" +" gBodies[bIdx].m_linVel = linVelB;\n" +" gBodies[bIdx].m_angVel = angVelB;\n" +"}\n" +"\n" +"void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)\n" +"{\n" +" float frictionCoeff = ldsCs[0].m_linear.w;\n" +" int aIdx = ldsCs[0].m_bodyA;\n" +" int bIdx = ldsCs[0].m_bodyB;\n" +"\n" +" float4 posA = gBodies[aIdx].m_pos;\n" +" float4 linVelA = gBodies[aIdx].m_linVel;\n" +" float4 angVelA = gBodies[aIdx].m_angVel;\n" +" float invMassA = gBodies[aIdx].m_invMass;\n" +" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n" +"\n" +" float4 posB = gBodies[bIdx].m_pos;\n" +" float4 linVelB = gBodies[bIdx].m_linVel;\n" +" float4 angVelB = gBodies[bIdx].m_angVel;\n" +" float invMassB = gBodies[bIdx].m_invMass;\n" +" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n" +"\n" +" {\n" +" float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};\n" +" float minRambdaDt[4] = {0.f,0.f,0.f,0.f};\n" +"\n" +" float sum = 0;\n" +" for(int j=0; j<4; j++)\n" +" {\n" +" sum +=ldsCs[0].m_appliedRambdaDt[j];\n" +" }\n" +" frictionCoeff = 0.7f;\n" +" for(int j=0; j<4; j++)\n" +" {\n" +" maxRambdaDt[j] = frictionCoeff*sum;\n" +" minRambdaDt[j] = -maxRambdaDt[j];\n" +" }\n" +"\n" +" solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n" +" posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );\n" +" }\n" +"\n" +" gBodies[aIdx].m_linVel = linVelA;\n" +" gBodies[aIdx].m_angVel = angVelA;\n" +" gBodies[bIdx].m_linVel = linVelB;\n" +" gBodies[bIdx].m_angVel = angVelB;\n" +"}\n" +"\n" +"typedef struct \n" +"{\n" +" int m_valInt0;\n" +" int m_valInt1;\n" +" int m_valInt2;\n" +" int m_valInt3;\n" +"\n" +" float m_val0;\n" +" float m_val1;\n" +" float m_val2;\n" +" float m_val3;\n" +"} SolverDebugInfo;\n" +"\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n" +"//void BatchSolveKernel(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* gConstraints, __global int* gN, __global int* gOffsets, __global SolverDebugInfo* debugInfo, ConstBufferBatchSolve cb)\n" +"void BatchSolveKernel(__global Body* gBodies, \n" +"__global Shape* gShapes, \n" +"__global Constraint4* gConstraints, \n" +"__global int* gN, \n" +"__global int* gOffsets, \n" +"ConstBufferBatchSolve cb)\n" +"{\n" +" __local int ldsBatchIdx[WG_SIZE+1];\n" +"\n" +" __local int ldsCurBatch;\n" +" __local int ldsNextBatch;\n" +" __local int ldsStart;\n" +"\n" +" int lIdx = GET_LOCAL_IDX;\n" +" int wgIdx = GET_GROUP_IDX;\n" +"\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"// debugInfo[gIdx].m_valInt0 = gIdx;\n" +" //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;\n" +"\n" +" const int solveFriction = cb.m_solveFriction;\n" +" const int maxBatch = cb.m_maxBatch;\n" +" const int bIdx = cb.m_batchIdx;\n" +" const int nSplit = cb.m_nSplit;\n" +"\n" +" int xIdx = (wgIdx/(nSplit/2))*2 + (bIdx&1);\n" +" int yIdx = (wgIdx%(nSplit/2))*2 + (bIdx>>1);\n" +" int cellIdx = xIdx+yIdx*nSplit;\n" +" \n" +" if( gN[cellIdx] == 0 ) \n" +" return;\n" +"\n" +" const int start = gOffsets[cellIdx];\n" +" const int end = start + gN[cellIdx];\n" +"\n" +" \n" +" if( lIdx == 0 )\n" +" {\n" +" ldsCurBatch = 0;\n" +" ldsNextBatch = 0;\n" +" ldsStart = start;\n" +" }\n" +"\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" int idx=ldsStart+lIdx;\n" +" while (ldsCurBatch < maxBatch)\n" +" {\n" +" for(; idxm_bodyA = src.m_bodyAPtr;\n" +" dstC->m_bodyB = src.m_bodyBPtr;\n" +"\n" +" float dtInv = 1.f/dt;\n" +" for(int ic=0; ic<4; ic++)\n" +" {\n" +" dstC->m_appliedRambdaDt[ic] = 0.f;\n" +" }\n" +" dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;\n" +"\n" +"\n" +" dstC->m_linear = -src.m_worldNormal;\n" +" dstC->m_linear.w = 0.7f ;//src.getFrictionCoeff() );\n" +" for(int ic=0; ic<4; ic++)\n" +" {\n" +" float4 r0 = src.m_worldPos[ic] - posA;\n" +" float4 r1 = src.m_worldPos[ic] - posB;\n" +"\n" +" if( ic >= src.m_worldNormal.w )//npoints\n" +" {\n" +" dstC->m_jacCoeffInv[ic] = 0.f;\n" +" continue;\n" +" }\n" +"\n" +" float relVelN;\n" +" {\n" +" float4 linear, angular0, angular1;\n" +" setLinearAndAngular(src.m_worldNormal, r0, r1, &linear, &angular0, &angular1);\n" +"\n" +" dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,\n" +" invMassA, &invInertiaA, invMassB, &invInertiaB );\n" +"\n" +" relVelN = calcRelVel(linear, -linear, angular0, angular1,\n" +" linVelA, angVelA, linVelB, angVelB);\n" +"\n" +" float e = 0.f;//src.getRestituitionCoeff();\n" +" if( relVelN*relVelN < 0.004f ) e = 0.f;\n" +"\n" +" dstC->m_b[ic] = e*relVelN;\n" +" //float penetration = src.m_worldPos[ic].w;\n" +" dstC->m_b[ic] += (src.m_worldPos[ic].w + positionDrift)*positionConstraintCoeff*dtInv;\n" +" dstC->m_appliedRambdaDt[ic] = 0.f;\n" +" }\n" +" }\n" +"\n" +" if( src.m_worldNormal.w > 1 )//npoints\n" +" { // prepare friction\n" +" float4 center = make_float4(0.f);\n" +" for(int i=0; im_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,\n" +" invMassA, &invInertiaA, invMassB, &invInertiaB );\n" +" dstC->m_fAppliedRambdaDt[i] = 0.f;\n" +" }\n" +" dstC->m_center = center;\n" +" }\n" +" else\n" +" {\n" +" // single point constraint\n" +" }\n" +"\n" +" for(int i=0; i<4; i++)\n" +" {\n" +" if( im_worldPos[i] = src.m_worldPos[i];\n" +" }\n" +" else\n" +" {\n" +" dstC->m_worldPos[i] = make_float4(0.f);\n" +" }\n" +" }\n" +"}\n" +"\n" +"typedef struct\n" +"{\n" +" int m_nContacts;\n" +" float m_dt;\n" +" float m_positionDrift;\n" +" float m_positionConstraintCoeff;\n" +"} ConstBufferCTC;\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n" +"void ContactToConstraintKernel(__global Contact4* gContact, __global Body* gBodies, __global Shape* gShapes, __global Constraint4* gConstraintOut, ConstBufferCTC cb)\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +" int nContacts = cb.m_nContacts;\n" +" float dt = cb.m_dt;\n" +" float positionDrift = cb.m_positionDrift;\n" +" float positionConstraintCoeff = cb.m_positionConstraintCoeff;\n" +"\n" +" if( gIdx < nContacts )\n" +" {\n" +" int aIdx = gContact[gIdx].m_bodyAPtr;\n" +" int bIdx = gContact[gIdx].m_bodyBPtr;\n" +"\n" +" float4 posA = gBodies[aIdx].m_pos;\n" +" float4 linVelA = gBodies[aIdx].m_linVel;\n" +" float4 angVelA = gBodies[aIdx].m_angVel;\n" +" float invMassA = gBodies[aIdx].m_invMass;\n" +" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n" +"\n" +" float4 posB = gBodies[bIdx].m_pos;\n" +" float4 linVelB = gBodies[bIdx].m_linVel;\n" +" float4 angVelB = gBodies[bIdx].m_angVel;\n" +" float invMassB = gBodies[bIdx].m_invMass;\n" +" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n" +"\n" +" Constraint4 cs;\n" +"\n" +" setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,\n" +" gContact[gIdx], dt, positionDrift, positionConstraintCoeff, \n" +" &cs );\n" +" \n" +" cs.m_batchIdx = gContact[gIdx].m_batchIdx;\n" +"\n" +" gConstraintOut[gIdx] = cs;\n" +" }\n" +"}\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n" +"void CopyConstraintKernel(__global Contact4* gIn, __global Contact4* gOut, int4 cb )\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +" if( gIdx < cb.x )\n" +" {\n" +" gOut[gIdx] = gIn[gIdx];\n" +" }\n" +"}\n" +; diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/batchingKernels.cl b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/batchingKernels.cl new file mode 100644 index 0000000..eee80c1 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/batchingKernels.cl @@ -0,0 +1,338 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#pragma OPENCL EXTENSION cl_amd_printf : enable +#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable +#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable +#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable +#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable + +#ifdef cl_ext_atomic_counters_32 +#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable +#else +#define counter32_t volatile __global int* +#endif + + +typedef unsigned int u32; +typedef unsigned short u16; +typedef unsigned char u8; + +#define GET_GROUP_IDX get_group_id(0) +#define GET_LOCAL_IDX get_local_id(0) +#define GET_GLOBAL_IDX get_global_id(0) +#define GET_GROUP_SIZE get_local_size(0) +#define GET_NUM_GROUPS get_num_groups(0) +#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE) +#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE) +#define AtomInc(x) atom_inc(&(x)) +#define AtomInc1(x, out) out = atom_inc(&(x)) +#define AppendInc(x, out) out = atomic_inc(x) +#define AtomAdd(x, value) atom_add(&(x), value) +#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value ) +#define AtomXhg(x, value) atom_xchg ( &(x), value ) + + +#define SELECT_UINT4( b, a, condition ) select( b,a,condition ) + +#define make_float4 (float4) +#define make_float2 (float2) +#define make_uint4 (uint4) +#define make_int4 (int4) +#define make_uint2 (uint2) +#define make_int2 (int2) + + +#define max2 max +#define min2 min + + +#define WG_SIZE 64 + + + +typedef struct +{ + float4 m_worldPos[4]; + float4 m_worldNormal; + u32 m_coeffs; + int m_batchIdx; + + u32 m_bodyA; + u32 m_bodyB; +}Contact4; + +typedef struct +{ + int m_n; + int m_start; + int m_staticIdx; + int m_paddings[1]; +} ConstBuffer; + +typedef struct +{ + u32 m_a; + u32 m_b; + u32 m_idx; +}Elem; + +#define STACK_SIZE (WG_SIZE*10) +//#define STACK_SIZE (WG_SIZE) +#define RING_SIZE 1024 +#define RING_SIZE_MASK (RING_SIZE-1) +#define CHECK_SIZE (WG_SIZE) + + +#define GET_RING_CAPACITY (RING_SIZE - ldsRingEnd) +#define RING_END ldsTmp + +u32 readBuf(__local u32* buff, int idx) +{ + idx = idx % (32*CHECK_SIZE); + int bitIdx = idx%32; + int bufIdx = idx/32; + return buff[bufIdx] & (1<> bitIdx)&1) == 0; +} + +// batching on the GPU +__kernel void CreateBatches( __global Contact4* gConstraints, __global Contact4* gConstraintsOut, + __global u32* gN, __global u32* gStart, + ConstBuffer cb ) +{ + __local u32 ldsStackIdx[STACK_SIZE]; + __local u32 ldsStackEnd; + __local Elem ldsRingElem[RING_SIZE]; + __local u32 ldsRingEnd; + __local u32 ldsTmp; + __local u32 ldsCheckBuffer[CHECK_SIZE]; + __local u32 ldsFixedBuffer[CHECK_SIZE]; + __local u32 ldsGEnd; + __local u32 ldsDstEnd; + + int wgIdx = GET_GROUP_IDX; + int lIdx = GET_LOCAL_IDX; + + const int m_n = gN[wgIdx]; + const int m_start = gStart[wgIdx]; + const int m_staticIdx = cb.m_staticIdx; + + if( lIdx == 0 ) + { + ldsRingEnd = 0; + ldsGEnd = 0; + ldsStackEnd = 0; + ldsDstEnd = m_start; + } + +// while(1) + for(int ie=0; ie<250; ie++) + { + ldsFixedBuffer[lIdx] = 0; + + for(int giter=0; giter<4; giter++) + { + int ringCap = GET_RING_CAPACITY; + + // 1. fill ring + if( ldsGEnd < m_n ) + { + while( ringCap > WG_SIZE ) + { + if( ldsGEnd >= m_n ) break; + if( lIdx < ringCap - WG_SIZE ) + { + int srcIdx; + AtomInc1( ldsGEnd, srcIdx ); + if( srcIdx < m_n ) + { + int dstIdx; + AtomInc1( ldsRingEnd, dstIdx ); + + int a = gConstraints[m_start+srcIdx].m_bodyA; + int b = gConstraints[m_start+srcIdx].m_bodyB; + ldsRingElem[dstIdx].m_a = (a>b)? b:a; + ldsRingElem[dstIdx].m_b = (a>b)? a:b; + ldsRingElem[dstIdx].m_idx = srcIdx; + } + } + ringCap = GET_RING_CAPACITY; + } + } + + GROUP_LDS_BARRIER; + + // 2. fill stack + __local Elem* dst = ldsRingElem; + if( lIdx == 0 ) RING_END = 0; + + int srcIdx=lIdx; + int end = ldsRingEnd; + + { + for(int ii=0; ii> bitIdx)&1) == 0;\n" +"}\n" +"\n" +"typedef struct \n" +"{\n" +" int m_valInt0;\n" +" int m_valInt1;\n" +" int m_valInt2;\n" +" int m_valInt3;\n" +"\n" +" int m_valInt4;\n" +" int m_valInt5;\n" +" int m_valInt6;\n" +" int m_valInt7;\n" +"\n" +" int m_valInt8;\n" +" int m_valInt9;\n" +" int m_valInt10;\n" +" int m_valInt11;\n" +" \n" +" int m_valInt12;\n" +" int m_valInt13;\n" +" int m_valInt14;\n" +" int m_valInt15;\n" +"\n" +"\n" +" float m_fval0;\n" +" float m_fval1;\n" +" float m_fval2;\n" +" float m_fval3;\n" +"} SolverDebugInfo;\n" +"\n" +"// batching on the GPU\n" +"__kernel void CreateBatches( __global Contact4* gConstraints, __global Contact4* gConstraintsOut, //__global u32* gRes, \n" +" __global u32* gN, __global u32* gStart, \n" +"// __global SolverDebugInfo* debugInfo, \n" +" ConstBuffer cb )\n" +"{\n" +" __local u32 ldsStackIdx[STACK_SIZE];\n" +" __local u32 ldsStackEnd;\n" +" __local Elem ldsRingElem[RING_SIZE];\n" +" __local u32 ldsRingEnd;\n" +" __local u32 ldsTmp;\n" +" __local u32 ldsCheckBuffer[CHECK_SIZE];\n" +" __local u32 ldsFixedBuffer[CHECK_SIZE];\n" +" __local u32 ldsGEnd;\n" +" __local u32 ldsDstEnd;\n" +"\n" +" int wgIdx = GET_GROUP_IDX;\n" +" int lIdx = GET_LOCAL_IDX;\n" +" \n" +" const int m_n = gN[wgIdx];\n" +" const int m_start = gStart[wgIdx];\n" +" const int m_staticIdx = cb.m_staticIdx;\n" +" \n" +" if( lIdx == 0 )\n" +" {\n" +" ldsRingEnd = 0;\n" +" ldsGEnd = 0;\n" +" ldsStackEnd = 0;\n" +" ldsDstEnd = m_start;\n" +" }\n" +" \n" +"// while(1)\n" +" for(int ie=0; ie<250; ie++)\n" +" {\n" +" ldsFixedBuffer[lIdx] = 0;\n" +"\n" +" for(int giter=0; giter<4; giter++)\n" +" {\n" +" int ringCap = GET_RING_CAPACITY;\n" +" \n" +" // 1. fill ring\n" +" if( ldsGEnd < m_n )\n" +" {\n" +" while( ringCap > WG_SIZE )\n" +" {\n" +" if( ldsGEnd >= m_n ) break;\n" +" if( lIdx < ringCap - WG_SIZE )\n" +" {\n" +" int srcIdx;\n" +" AtomInc1( ldsGEnd, srcIdx );\n" +" if( srcIdx < m_n )\n" +" {\n" +" int dstIdx;\n" +" AtomInc1( ldsRingEnd, dstIdx );\n" +" \n" +" int a = gConstraints[m_start+srcIdx].m_bodyA;\n" +" int b = gConstraints[m_start+srcIdx].m_bodyB;\n" +" ldsRingElem[dstIdx].m_a = (a>b)? b:a;\n" +" ldsRingElem[dstIdx].m_b = (a>b)? a:b;\n" +" ldsRingElem[dstIdx].m_idx = srcIdx;\n" +" }\n" +" }\n" +" ringCap = GET_RING_CAPACITY;\n" +" }\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" \n" +" // 2. fill stack\n" +" __local Elem* dst = ldsRingElem;\n" +" if( lIdx == 0 ) RING_END = 0;\n" +"\n" +" int srcIdx=lIdx;\n" +" int end = ldsRingEnd;\n" +"\n" +" {\n" +" for(int ii=0; iiChNarrowphaseKernels.h + + +@echo Warning: +@echo You might still need to find/replace for \\n (due to macros) and replace #include statements by their content +pause diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernelsAll.bat b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernelsAll.bat new file mode 100644 index 0000000..9854d93 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernelsAll.bat @@ -0,0 +1,10 @@ +stringify.py ChNarrowphaseKernels.cl narrowphaseKernelsCL >ChNarrowphaseKernels.h +stringify.py SolverKernels.cl solverKernelsCL >SolverKernels.h +stringify.py batchingKernels.cl batchingKernelsCL >batchingKernels.h + + + + +@echo Warning: +@echo You might still need to find/replace for \\n (due to macros) and replace #include statements by their content +pause diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernelsBatching.bat b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernelsBatching.bat new file mode 100644 index 0000000..1282f7e --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernelsBatching.bat @@ -0,0 +1,8 @@ +stringify.py batchingKernels.cl batchingKernelsCL >batchingKernels.h + + + + +@echo Warning: +@echo You might still need to find/replace for \\n (due to macros) and replace #include statements by their content +pause diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernelsNarrowphase.bat b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernelsNarrowphase.bat new file mode 100644 index 0000000..20a0d3e --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernelsNarrowphase.bat @@ -0,0 +1,8 @@ +stringify.py ChNarrowphaseKernels.cl narrowphaseKernelsCL >ChNarrowphaseKernels.h + + + + +@echo Warning: +@echo You might still need to find/replace for \\n (due to macros) and replace #include statements by their content +pause diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernelsSolver.bat b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernelsSolver.bat new file mode 100644 index 0000000..ff483de --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/Stubs/stringifykernelsSolver.bat @@ -0,0 +1,8 @@ +stringify.py SolverKernels.cl solverKernelsCL >SolverKernels.h + + + + +@echo Warning: +@echo You might still need to find/replace for \\n (due to macros) and replace #include statements by their content +pause diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/main.cpp b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/main.cpp new file mode 100644 index 0000000..26846f9 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/main.cpp @@ -0,0 +1,77 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + +#include "BasicDemo.h" +#include "GlutStuff.h" +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btHashMap.h" + +#ifdef CL_PLATFORM_AMD +#include "../../opencl/basic_initialize/btOpenCLUtils.h" +extern cl_context g_cxMainContext; +extern cl_command_queue g_cqCommandQue; +extern cl_device_id g_clDevice; +#endif + + + +int main(int argc,char** argv) +{ + + #ifdef CL_PLATFORM_AMD + int ciErrNum = 0; + const char* vendorSDK = btOpenCLUtils::getSdkVendorName(); + printf("This program was compiled using the %s OpenCL SDK\n",vendorSDK); + + cl_device_type deviceType = CL_DEVICE_TYPE_GPU;//CPU;//GPU; + + + void* glCtx=0; + void* glDC = 0; + g_cxMainContext = btOpenCLUtils::createContextFromType(deviceType, &ciErrNum, glCtx, glDC); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + int numDev = btOpenCLUtils::getNumDevices(g_cxMainContext); + + if (numDev>0) + { + int deviceIndex =0; + g_clDevice = btOpenCLUtils::getDevice(g_cxMainContext,deviceIndex); + btOpenCLDeviceInfo clInfo; + btOpenCLUtils::getDeviceInfo(g_clDevice,clInfo); + btOpenCLUtils::printDeviceInfo(g_clDevice); + // create a command-queue + g_cqCommandQue = clCreateCommandQueue(g_cxMainContext, g_clDevice, 0, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } +#endif //#ifdef CL_PLATFORM_AMD + + + BasicDemo ccdDemo; + ccdDemo.initPhysics(); + + +#ifdef CHECK_MEMORY_LEAKS + ccdDemo.exitPhysics(); +#else + glutmain(argc, argv,1024,600,"Bullet Physics Demo. http://bulletphysics.org",&ccdDemo); +#endif + + //setupGUI(1024,768); + glutMainLoop(); + //default glut doesn't return from mainloop + return 0; +} + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/premake4.lua b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/premake4.lua new file mode 100644 index 0000000..c779ff9 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/basic_demo/premake4.lua @@ -0,0 +1,34 @@ + +-- include "AMD" + +if os.is("Windows") then + + project "basic_bullet2_demo" + + language "C++" + + kind "ConsoleApp" + targetdir "../../bin" + + includedirs { + ".", + "../../bullet2", + "../testbed", + "../../rendering/Gwen", + } + + + links { "testbed", + "bullet2", + "gwen" + } + + initOpenGL() + initGlut() + + files { + "**.cpp", + "**.h" + } + +end diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/DebugCastResult.h b/Extras/RigidBodyGpuPipeline/dynamics/testbed/DebugCastResult.h new file mode 100644 index 0000000..ef3befe --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/DebugCastResult.h @@ -0,0 +1,88 @@ +/* +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 DEBUG_CAST_RESULT_H +#define DEBUG_CAST_RESULT_H + +#include "BulletCollision/NarrowPhaseCollision/btConvexCast.h" +#include "LinearMath/btTransform.h" +#include "GL_ShapeDrawer.h" +#include "GlutStuff.h" +#ifdef WIN32 +#include +#endif +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#else +#include +#endif +struct btDebugCastResult : public btConvexCast::CastResult +{ + + btTransform m_fromTrans; + const btPolyhedralConvexShape* m_shape; + btVector3 m_linVel; + btVector3 m_angVel; + GL_ShapeDrawer* m_shapeDrawer; + + btDebugCastResult(const btTransform& fromTrans,const btPolyhedralConvexShape* shape, + const btVector3& linVel,const btVector3& angVel,GL_ShapeDrawer* drawer) + :m_fromTrans(fromTrans), + m_shape(shape), + m_linVel(linVel), + m_angVel(angVel), + m_shapeDrawer(drawer) + { + } + + virtual void drawCoordSystem(const btTransform& tr) + { + btScalar m[16]; + tr.getOpenGLMatrix(m); + glPushMatrix(); + btglLoadMatrix(m); + glBegin(GL_LINES); + btglColor3(1, 0, 0); + btglVertex3(0, 0, 0); + btglVertex3(1, 0, 0); + btglColor3(0, 1, 0); + btglVertex3(0, 0, 0); + btglVertex3(0, 1, 0); + btglColor3(0, 0, 1); + btglVertex3(0, 0, 0); + btglVertex3(0, 0, 1); + glEnd(); + glPopMatrix(); + } + + virtual void DebugDraw(btScalar fraction) + { + btVector3 worldBoundsMin(-1000,-1000,-1000); + btVector3 worldBoundsMax(1000,1000,1000); + + + btScalar m[16]; + btTransform hitTrans; + btTransformUtil::integrateTransform(m_fromTrans,m_linVel,m_angVel,fraction,hitTrans); + hitTrans.getOpenGLMatrix(m); + if (m_shapeDrawer) + m_shapeDrawer->drawOpenGL(m,m_shape,btVector3(1,0,0),btIDebugDraw::DBG_NoDebug,worldBoundsMin,worldBoundsMax); + } +}; + + +#endif //DEBUG_CAST_RESULT_H diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/DemoApplication.cpp b/Extras/RigidBodyGpuPipeline/dynamics/testbed/DemoApplication.cpp new file mode 100644 index 0000000..d582570 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/DemoApplication.cpp @@ -0,0 +1,1375 @@ +/* +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 "DemoApplication.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletDynamics/Dynamics/btDynamicsWorld.h" + +#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"//picking +#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"//picking + +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/CollisionShapes/btUniformScalingShape.h" +#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h" +#include "GL_ShapeDrawer.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btDefaultMotionState.h" +#include "LinearMath/btSerializer.h" +#include "GLDebugFont.h" + +static bool use6Dof = false; +extern bool gDisableDeactivation; +int numObjects = 0; +const int maxNumObjects = 16384; +btTransform startTransforms[maxNumObjects]; +btCollisionShape* gShapePtr[maxNumObjects];//1 rigidbody has 1 shape (no re-use of shapes) +#define SHOW_NUM_DEEP_PENETRATIONS 1 + +extern int gNumClampedCcdMotions; + +#ifdef SHOW_NUM_DEEP_PENETRATIONS +extern int gNumDeepPenetrationChecks; + +extern int gNumSplitImpulseRecoveries; +extern int gNumGjkChecks; +extern int gNumAlignedAllocs; +extern int gNumAlignedFree; +extern int gTotalBytesAlignedAllocs; + +#endif // + + +DemoApplication::DemoApplication() +//see btIDebugDraw.h for modes +: +m_dynamicsWorld(0), +m_pickConstraint(0), +m_shootBoxShape(0), +m_cameraDistance(15.0), +m_debugMode(0), +m_ele(20.f), +m_azi(0.f), +m_cameraPosition(0.f,0.f,0.f), +m_cameraTargetPosition(0.f,0.f,0.f), +m_mouseOldX(0), +m_mouseOldY(0), +m_mouseButtons(0), +m_modifierKeys(0), +m_scaleBottom(0.5f), +m_scaleFactor(2.f), +m_cameraUp(0,1,0), +m_forwardAxis(2), +m_glutScreenWidth(0), +m_glutScreenHeight(0), +m_frustumZNear(1.f), +m_frustumZFar(10000.f), +m_ortho(0), +m_ShootBoxInitialSpeed(40.f), +m_stepping(true), +m_singleStep(false), +m_idle(false), + +m_enableshadows(false), +m_sundirection(btVector3(1,-2,1)*1000), +m_defaultContactProcessingThreshold(BT_LARGE_FLOAT) +{ +#ifndef BT_NO_PROFILE + m_profileIterator = CProfileManager::Get_Iterator(); +#endif //BT_NO_PROFILE + + m_shapeDrawer = new GL_ShapeDrawer (); + m_shapeDrawer->enableTexture(true); + m_enableshadows = false; +} + + + +DemoApplication::~DemoApplication() +{ +#ifndef BT_NO_PROFILE + CProfileManager::Release_Iterator(m_profileIterator); +#endif //BT_NO_PROFILE + + if (m_shootBoxShape) + delete m_shootBoxShape; + + if (m_shapeDrawer) + delete m_shapeDrawer; +} + + +void DemoApplication::overrideGLShapeDrawer (GL_ShapeDrawer* shapeDrawer) +{ + shapeDrawer->enableTexture (m_shapeDrawer->hasTextureEnabled()); + delete m_shapeDrawer; + m_shapeDrawer = shapeDrawer; +} + +void DemoApplication::myinit(void) +{ + + 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 )}; + /* light_position is NOT default value */ + GLfloat light_position0[] = { btScalar(1.0), btScalar(10.0), btScalar(1.0), btScalar(0.0 )}; + GLfloat light_position1[] = { btScalar(-1.0), btScalar(-10.0), btScalar(-1.0), btScalar(0.0) }; + + glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT0, GL_POSITION, light_position0); + + glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT1, GL_POSITION, light_position1); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + + + glShadeModel(GL_SMOOTH); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + glClearColor(btScalar(0.7),btScalar(0.7),btScalar(0.7),btScalar(0)); + + // glEnable(GL_CULL_FACE); + // glCullFace(GL_BACK); +} + + +void DemoApplication::setCameraDistance(float dist) +{ + m_cameraDistance = dist; +} + +float DemoApplication::getCameraDistance() +{ + return m_cameraDistance; +} + + + +void DemoApplication::toggleIdle() { + if (m_idle) { + m_idle = false; + } + else { + m_idle = true; + } +} + + + + +void DemoApplication::updateCamera() { + + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + btScalar rele = m_ele * btScalar(0.01745329251994329547);// rads per deg + btScalar razi = m_azi * btScalar(0.01745329251994329547);// rads per deg + + + btQuaternion rot(m_cameraUp,razi); + + + btVector3 eyePos(0,0,0); + eyePos[m_forwardAxis] = -m_cameraDistance; + + btVector3 forward(eyePos[0],eyePos[1],eyePos[2]); + if (forward.length2() < SIMD_EPSILON) + { + forward.setValue(1.f,0.f,0.f); + } + btVector3 right = m_cameraUp.cross(forward); + btQuaternion roll(right,-rele); + + eyePos = btMatrix3x3(rot) * btMatrix3x3(roll) * eyePos; + + m_cameraPosition[0] = eyePos.getX(); + m_cameraPosition[1] = eyePos.getY(); + m_cameraPosition[2] = eyePos.getZ(); + m_cameraPosition += m_cameraTargetPosition; + + if (m_glutScreenWidth == 0 && m_glutScreenHeight == 0) + return; + + btScalar aspect; + btVector3 extents; + + aspect = m_glutScreenWidth / (btScalar)m_glutScreenHeight; + extents.setValue(aspect * 1.0f, 1.0f,0); + + + if (m_ortho) + { + // reset matrix + glLoadIdentity(); + + + extents *= m_cameraDistance; + btVector3 lower = m_cameraTargetPosition - extents; + btVector3 upper = m_cameraTargetPosition + extents; + //gluOrtho2D(lower.x, upper.x, lower.y, upper.y); + glOrtho(lower.getX(), upper.getX(), lower.getY(), upper.getY(),-1000,1000); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + //glTranslatef(100,210,0); + } else + { +// glFrustum (-aspect, aspect, -1.0, 1.0, 1.0, 10000.0); + glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(m_cameraPosition[0], m_cameraPosition[1], m_cameraPosition[2], + m_cameraTargetPosition[0], m_cameraTargetPosition[1], m_cameraTargetPosition[2], + m_cameraUp.getX(),m_cameraUp.getY(),m_cameraUp.getZ()); + } + +} + + + +const float STEPSIZE = 5; + +void DemoApplication::stepLeft() +{ + m_azi -= STEPSIZE; if (m_azi < 0) m_azi += 360; updateCamera(); +} +void DemoApplication::stepRight() +{ + m_azi += STEPSIZE; if (m_azi >= 360) m_azi -= 360; updateCamera(); +} +void DemoApplication::stepFront() +{ + m_ele += STEPSIZE; if (m_ele >= 360) m_ele -= 360; updateCamera(); +} +void DemoApplication::stepBack() +{ + m_ele -= STEPSIZE; if (m_ele < 0) m_ele += 360; updateCamera(); +} +void DemoApplication::zoomIn() +{ + m_cameraDistance -= btScalar(0.4); updateCamera(); + if (m_cameraDistance < btScalar(0.1)) + m_cameraDistance = btScalar(0.1); + +} +void DemoApplication::zoomOut() +{ + m_cameraDistance += btScalar(0.4); updateCamera(); + +} + + + + + + + + + + +void DemoApplication::reshape(int w, int h) +{ + GLDebugResetFont(w,h); + + m_glutScreenWidth = w; + m_glutScreenHeight = h; + + glViewport(0, 0, w, h); + updateCamera(); +} + + +void DemoApplication::keyboardCallback(unsigned char key, int x, int y) +{ + (void)x; + (void)y; + + m_lastKey = 0; + +#ifndef BT_NO_PROFILE + if (key >= 0x31 && key <= 0x39) + { + int child = key-0x31; + m_profileIterator->Enter_Child(child); + } + if (key==0x30) + { + m_profileIterator->Enter_Parent(); + } +#endif //BT_NO_PROFILE + + switch (key) + { + case 'q' : +#ifdef BT_USE_FREEGLUT + //return from glutMainLoop(), detect memory leaks etc. + glutLeaveMainLoop(); +#else + exit(0); +#endif + break; + + case 'l' : stepLeft(); break; + case 'r' : stepRight(); break; + case 'f' : stepFront(); break; + case 'b' : stepBack(); break; + case 'z' : zoomIn(); break; + case 'x' : zoomOut(); break; + case 'i' : toggleIdle(); break; + case 'g' : m_enableshadows=!m_enableshadows;break; + case 'u' : m_shapeDrawer->enableTexture(!m_shapeDrawer->enableTexture(false));break; + case 'h': + if (m_debugMode & btIDebugDraw::DBG_NoHelpText) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_NoHelpText); + else + m_debugMode |= btIDebugDraw::DBG_NoHelpText; + break; + + case 'w': + if (m_debugMode & btIDebugDraw::DBG_DrawWireframe) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawWireframe); + else + m_debugMode |= btIDebugDraw::DBG_DrawWireframe; + break; + + case 'p': + if (m_debugMode & btIDebugDraw::DBG_ProfileTimings) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_ProfileTimings); + else + m_debugMode |= btIDebugDraw::DBG_ProfileTimings; + break; + + case '=': + { + int maxSerializeBufferSize = 1024*1024*5; + btDefaultSerializer* serializer = new btDefaultSerializer(maxSerializeBufferSize); + //serializer->setSerializationFlags(BT_SERIALIZE_NO_DUPLICATE_ASSERT); + m_dynamicsWorld->serialize(serializer); + FILE* f2 = fopen("testFile.bullet","wb"); + fwrite(serializer->getBufferPointer(),serializer->getCurrentBufferSize(),1,f2); + fclose(f2); + delete serializer; + break; + + } + + case 'm': + if (m_debugMode & btIDebugDraw::DBG_EnableSatComparison) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_EnableSatComparison); + else + m_debugMode |= btIDebugDraw::DBG_EnableSatComparison; + break; + + case 'n': + if (m_debugMode & btIDebugDraw::DBG_DisableBulletLCP) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DisableBulletLCP); + else + m_debugMode |= btIDebugDraw::DBG_DisableBulletLCP; + break; + + case 't' : + if (m_debugMode & btIDebugDraw::DBG_DrawText) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawText); + else + m_debugMode |= btIDebugDraw::DBG_DrawText; + break; + case 'y': + if (m_debugMode & btIDebugDraw::DBG_DrawFeaturesText) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawFeaturesText); + else + m_debugMode |= btIDebugDraw::DBG_DrawFeaturesText; + break; + case 'a': + if (m_debugMode & btIDebugDraw::DBG_DrawAabb) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawAabb); + else + m_debugMode |= btIDebugDraw::DBG_DrawAabb; + break; + case 'c' : + if (m_debugMode & btIDebugDraw::DBG_DrawContactPoints) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawContactPoints); + else + m_debugMode |= btIDebugDraw::DBG_DrawContactPoints; + break; + case 'C' : + if (m_debugMode & btIDebugDraw::DBG_DrawConstraints) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawConstraints); + else + m_debugMode |= btIDebugDraw::DBG_DrawConstraints; + break; + case 'L' : + if (m_debugMode & btIDebugDraw::DBG_DrawConstraintLimits) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_DrawConstraintLimits); + else + m_debugMode |= btIDebugDraw::DBG_DrawConstraintLimits; + break; + + case 'd' : + if (m_debugMode & btIDebugDraw::DBG_NoDeactivation) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_NoDeactivation); + else + m_debugMode |= btIDebugDraw::DBG_NoDeactivation; + if (m_debugMode & btIDebugDraw::DBG_NoDeactivation) + { + gDisableDeactivation = true; + } else + { + gDisableDeactivation = false; + } + break; + + + + + case 'o' : + { + m_ortho = !m_ortho;//m_stepping = !m_stepping; + break; + } + case 's' : clientMoveAndDisplay(); break; + // case ' ' : newRandom(); break; + case ' ': + clientResetScene(); + break; + case '1': + { + if (m_debugMode & btIDebugDraw::DBG_EnableCCD) + m_debugMode = m_debugMode & (~btIDebugDraw::DBG_EnableCCD); + else + m_debugMode |= btIDebugDraw::DBG_EnableCCD; + break; + } + + case '.': + { + shootBox(getRayTo(x,y));//getCameraTargetPosition()); + break; + } + + case '+': + { + m_ShootBoxInitialSpeed += 10.f; + break; + } + case '-': + { + m_ShootBoxInitialSpeed -= 10.f; + break; + } + + default: + // std::cout << "unused key : " << key << std::endl; + break; + } + + if (getDynamicsWorld() && getDynamicsWorld()->getDebugDrawer()) + getDynamicsWorld()->getDebugDrawer()->setDebugMode(m_debugMode); + + + +} + +void DemoApplication::setDebugMode(int mode) +{ + m_debugMode = mode; + if (getDynamicsWorld() && getDynamicsWorld()->getDebugDrawer()) + getDynamicsWorld()->getDebugDrawer()->setDebugMode(mode); +} + + + + + + +void DemoApplication::moveAndDisplay() +{ + if (!m_idle) + clientMoveAndDisplay(); + else + displayCallback(); +} + + + + +void DemoApplication::displayCallback() +{ +} + +#define NUM_SPHERES_ON_DIAGONAL 9 + +void DemoApplication::setShootBoxShape () +{ + if (!m_shootBoxShape) + { + btBoxShape* box = new btBoxShape(btVector3(.5f,.5f,.5f)); + box->initializePolyhedralFeatures(); + m_shootBoxShape = box; + } +} + +void DemoApplication::shootBox(const btVector3& destination) +{ + + if (m_dynamicsWorld) + { + float mass = 1.f; + btTransform startTransform; + startTransform.setIdentity(); + btVector3 camPos = getCameraPosition(); + startTransform.setOrigin(camPos); + + setShootBoxShape (); + + btRigidBody* body = this->localCreateRigidBody(mass, startTransform,m_shootBoxShape); + body->setLinearFactor(btVector3(1,1,1)); + //body->setRestitution(1); + + btVector3 linVel(destination[0]-camPos[0],destination[1]-camPos[1],destination[2]-camPos[2]); + linVel.normalize(); + linVel*=m_ShootBoxInitialSpeed; + + body->getWorldTransform().setOrigin(camPos); + body->getWorldTransform().setRotation(btQuaternion(0,0,0,1)); + body->setLinearVelocity(linVel); + body->setAngularVelocity(btVector3(0,0,0)); + body->setCcdMotionThreshold(0.5); + body->setCcdSweptSphereRadius(0.9f); +// printf("shootBox uid=%d\n", body->getBroadphaseHandle()->getUid()); +// printf("camPos=%f,%f,%f\n",camPos.getX(),camPos.getY(),camPos.getZ()); +// printf("destination=%f,%f,%f\n",destination.getX(),destination.getY(),destination.getZ()); + + } +} + + +int gPickingConstraintId = 0; +btVector3 gOldPickingPos; +btVector3 gHitPos(-1,-1,-1); +float gOldPickingDist = 0.f; +btRigidBody* pickedBody = 0;//for deactivation state + + +btVector3 DemoApplication::getRayTo(int x,int y) +{ + + + + if (m_ortho) + { + + btScalar aspect; + btVector3 extents; + aspect = m_glutScreenWidth / (btScalar)m_glutScreenHeight; + extents.setValue(aspect * 1.0f, 1.0f,0); + + extents *= m_cameraDistance; + btVector3 lower = m_cameraTargetPosition - extents; + btVector3 upper = m_cameraTargetPosition + extents; + + btScalar u = x / btScalar(m_glutScreenWidth); + btScalar v = (m_glutScreenHeight - y) / btScalar(m_glutScreenHeight); + + btVector3 p(0,0,0); + p.setValue((1.0f - u) * lower.getX() + u * upper.getX(),(1.0f - v) * lower.getY() + v * upper.getY(),m_cameraTargetPosition.getZ()); + return p; + } + + 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 rayFrom = getCameraPosition(); + btVector3 rayForward = (getCameraTargetPosition()-getCameraPosition()); + rayForward.normalize(); + float farPlane = 10000.f; + rayForward*= farPlane; + + btVector3 rightOffset; + btVector3 vertical = m_cameraUp; + + btVector3 hor; + hor = rayForward.cross(vertical); + hor.normalize(); + vertical = hor.cross(rayForward); + vertical.normalize(); + + float tanfov = tanf(0.5f*fov); + + + hor *= 2.f * farPlane * tanfov; + vertical *= 2.f * farPlane * tanfov; + + btScalar aspect; + + aspect = m_glutScreenWidth / (btScalar)m_glutScreenHeight; + + hor*=aspect; + + + btVector3 rayToCenter = rayFrom + rayForward; + btVector3 dHor = hor * 1.f/float(m_glutScreenWidth); + btVector3 dVert = vertical * 1.f/float(m_glutScreenHeight); + + + btVector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical; + rayTo += btScalar(x) * dHor; + rayTo -= btScalar(y) * dVert; + return rayTo; +} + +btScalar mousePickClamping = 30.f; + + +void DemoApplication::mouseFunc(int button, int state, int x, int y) +{ + if (state == 0) + { + m_mouseButtons |= 1<rayTest(m_cameraPosition,rayTo,rayCallback); + if (rayCallback.hasHit()) + { + + btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject); + if (body) + { + body->setActivationState(ACTIVE_TAG); + btVector3 impulse = rayTo; + impulse.normalize(); + float impulseStrength = 10.f; + impulse *= impulseStrength; + btVector3 relPos = rayCallback.m_hitPointWorld - body->getCenterOfMassPosition(); + body->applyImpulse(impulse,relPos); + } + } + } +#endif + + + + } else + { + + } + break; + } + case 0: + { + if (state==0) + { + + + //add a point to point constraint for picking + if (m_dynamicsWorld) + { + + btVector3 rayFrom; + if (m_ortho) + { + rayFrom = rayTo; + rayFrom.setZ(-100.f); + } else + { + rayFrom = m_cameraPosition; + } + + btCollisionWorld::ClosestRayResultCallback rayCallback(rayFrom,rayTo); + m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback); + if (rayCallback.hasHit()) + { + + + btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject); + if (body) + { + //other exclusions? + if (!(body->isStaticObject() || body->isKinematicObject())) + { + pickedBody = body; + pickedBody->setActivationState(DISABLE_DEACTIVATION); + + + btVector3 pickPos = rayCallback.m_hitPointWorld; + //printf("pickPos=%f,%f,%f\n",pickPos.getX(),pickPos.getY(),pickPos.getZ()); + + + btVector3 localPivot = body->getCenterOfMassTransform().inverse() * pickPos; + + + + + + + if (use6Dof) + { + btTransform tr; + tr.setIdentity(); + tr.setOrigin(localPivot); + btGeneric6DofConstraint* dof6 = new btGeneric6DofConstraint(*body, tr,false); + dof6->setLinearLowerLimit(btVector3(0,0,0)); + dof6->setLinearUpperLimit(btVector3(0,0,0)); + dof6->setAngularLowerLimit(btVector3(0,0,0)); + dof6->setAngularUpperLimit(btVector3(0,0,0)); + + m_dynamicsWorld->addConstraint(dof6); + m_pickConstraint = dof6; + + dof6->setParam(BT_CONSTRAINT_STOP_CFM,0.8,0); + dof6->setParam(BT_CONSTRAINT_STOP_CFM,0.8,1); + dof6->setParam(BT_CONSTRAINT_STOP_CFM,0.8,2); + dof6->setParam(BT_CONSTRAINT_STOP_CFM,0.8,3); + dof6->setParam(BT_CONSTRAINT_STOP_CFM,0.8,4); + dof6->setParam(BT_CONSTRAINT_STOP_CFM,0.8,5); + + dof6->setParam(BT_CONSTRAINT_STOP_ERP,0.1,0); + dof6->setParam(BT_CONSTRAINT_STOP_ERP,0.1,1); + dof6->setParam(BT_CONSTRAINT_STOP_ERP,0.1,2); + dof6->setParam(BT_CONSTRAINT_STOP_ERP,0.1,3); + dof6->setParam(BT_CONSTRAINT_STOP_ERP,0.1,4); + dof6->setParam(BT_CONSTRAINT_STOP_ERP,0.1,5); + } else + { + btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*body,localPivot); + m_dynamicsWorld->addConstraint(p2p); + m_pickConstraint = p2p; + p2p->m_setting.m_impulseClamp = mousePickClamping; + //very weak constraint for picking + p2p->m_setting.m_tau = 0.001f; +/* + p2p->setParam(BT_CONSTRAINT_CFM,0.8,0); + p2p->setParam(BT_CONSTRAINT_CFM,0.8,1); + p2p->setParam(BT_CONSTRAINT_CFM,0.8,2); + p2p->setParam(BT_CONSTRAINT_ERP,0.1,0); + p2p->setParam(BT_CONSTRAINT_ERP,0.1,1); + p2p->setParam(BT_CONSTRAINT_ERP,0.1,2); + */ + + + } + use6Dof = !use6Dof; + + //save mouse position for dragging + gOldPickingPos = rayTo; + gHitPos = pickPos; + + gOldPickingDist = (pickPos-rayFrom).length(); + } + } + } + } + + } else + { + removePickingConstraint(); + } + + break; + + } + default: + { + } + } + +} + +void DemoApplication::removePickingConstraint() +{ + if (m_pickConstraint && m_dynamicsWorld) + { + m_dynamicsWorld->removeConstraint(m_pickConstraint); + delete m_pickConstraint; + //printf("removed constraint %i",gPickingConstraintId); + m_pickConstraint = 0; + pickedBody->forceActivationState(ACTIVE_TAG); + pickedBody->setDeactivationTime( 0.f ); + pickedBody = 0; + } +} + +void DemoApplication::mouseMotionFunc(int x,int y) +{ + + if (m_pickConstraint) + { + //move the constraint pivot + + if (m_pickConstraint->getConstraintType() == D6_CONSTRAINT_TYPE) + { + btGeneric6DofConstraint* pickCon = static_cast(m_pickConstraint); + if (pickCon) + { + //keep it at the same picking distance + + btVector3 newRayTo = getRayTo(x,y); + btVector3 rayFrom; + btVector3 oldPivotInB = pickCon->getFrameOffsetA().getOrigin(); + + btVector3 newPivotB; + if (m_ortho) + { + newPivotB = oldPivotInB; + newPivotB.setX(newRayTo.getX()); + newPivotB.setY(newRayTo.getY()); + } else + { + rayFrom = m_cameraPosition; + btVector3 dir = newRayTo-rayFrom; + dir.normalize(); + dir *= gOldPickingDist; + + newPivotB = rayFrom + dir; + } + pickCon->getFrameOffsetA().setOrigin(newPivotB); + } + + } else + { + btPoint2PointConstraint* pickCon = static_cast(m_pickConstraint); + if (pickCon) + { + //keep it at the same picking distance + + btVector3 newRayTo = getRayTo(x,y); + btVector3 rayFrom; + btVector3 oldPivotInB = pickCon->getPivotInB(); + btVector3 newPivotB; + if (m_ortho) + { + newPivotB = oldPivotInB; + newPivotB.setX(newRayTo.getX()); + newPivotB.setY(newRayTo.getY()); + } else + { + rayFrom = m_cameraPosition; + btVector3 dir = newRayTo-rayFrom; + dir.normalize(); + dir *= gOldPickingDist; + + newPivotB = rayFrom + dir; + } + pickCon->setPivotB(newPivotB); + } + } + } + + float dx, dy; + dx = btScalar(x) - m_mouseOldX; + dy = btScalar(y) - m_mouseOldY; + + + ///only if ALT key is pressed (Maya style) + if (m_modifierKeys& BT_ACTIVE_ALT) + { + if(m_mouseButtons & 2) + { + btVector3 hor = getRayTo(0,0)-getRayTo(1,0); + btVector3 vert = getRayTo(0,0)-getRayTo(0,1); + btScalar multiplierX = btScalar(0.001); + btScalar multiplierY = btScalar(0.001); + if (m_ortho) + { + multiplierX = 1; + multiplierY = 1; + } + + + m_cameraTargetPosition += hor* dx * multiplierX; + m_cameraTargetPosition += vert* dy * multiplierY; + } + + if(m_mouseButtons & (2 << 2) && m_mouseButtons & 1) + { + } + else if(m_mouseButtons & 1) + { + m_azi += dx * btScalar(0.2); + m_azi = fmodf(m_azi, btScalar(360.f)); + m_ele += dy * btScalar(0.2); + m_ele = fmodf(m_ele, btScalar(180.f)); + } + else if(m_mouseButtons & 4) + { + m_cameraDistance -= dy * btScalar(0.02f); + if (m_cameraDistancegetShapeType() != 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// + + m_dynamicsWorld->addRigidBody(body); + + return body; +} + +//See http://www.lighthouse3d.com/opengl/glut/index.php?bmpfontortho +void DemoApplication::setOrthographicProjection() +{ + + // switch to projection mode + glMatrixMode(GL_PROJECTION); + + // save previous matrix which contains the + //settings for the perspective projection + glPushMatrix(); + // reset matrix + glLoadIdentity(); + // set a 2D orthographic projection + gluOrtho2D(0, m_glutScreenWidth, 0, m_glutScreenHeight); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // invert the y axis, down is positive + glScalef(1, -1, 1); + // mover the origin from the bottom left corner + // to the upper left corner + glTranslatef(btScalar(0), btScalar(-m_glutScreenHeight), btScalar(0)); + +} + +void DemoApplication::resetPerspectiveProjection() +{ + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + updateCamera(); +} + + + + +extern CProfileIterator * m_profileIterator; + +void DemoApplication::displayProfileString(int xOffset,int yStart,char* message) +{ + glRasterPos3f(btScalar(xOffset),btScalar(yStart),btScalar(0)); + GLDebugDrawString(xOffset,yStart,message); +} + + +float DemoApplication::showProfileInfo(int& xOffset,int& yStart, int yIncr) +{ +#ifndef BT_NO_PROFILE + + static double time_since_reset = 0.f; + if (!m_idle) + { + time_since_reset = CProfileManager::Get_Time_Since_Reset(); + } + + + { + //recompute profiling data, and store profile strings + + char blockTime[128]; + + double totalTime = 0; + + int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset(); + + m_profileIterator->First(); + + double parent_time = m_profileIterator->Is_Root() ? time_since_reset : m_profileIterator->Get_Current_Parent_Total_Time(); + + { + sprintf(blockTime,"--- Profiling: %s (total running time: %.3f ms) ---", m_profileIterator->Get_Current_Parent_Name(), parent_time ); + displayProfileString(xOffset,yStart,blockTime); + yStart += yIncr; + sprintf(blockTime,"press (1,2...) to display child timings, or 0 for parent" ); + displayProfileString(xOffset,yStart,blockTime); + yStart += yIncr; + + } + + + double accumulated_time = 0.f; + + for (int i = 0; !m_profileIterator->Is_Done(); m_profileIterator->Next()) + { + double current_total_time = m_profileIterator->Get_Current_Total_Time(); + accumulated_time += current_total_time; + double fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f; + + sprintf(blockTime,"%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)", + ++i, m_profileIterator->Get_Current_Name(), fraction, + (current_total_time / (double)frames_since_reset),m_profileIterator->Get_Current_Total_Calls()); + displayProfileString(xOffset,yStart,blockTime); + yStart += yIncr; + totalTime += current_total_time; + } + + sprintf(blockTime,"%s (%.3f %%) :: %.3f ms", "Unaccounted", + // (min(0, time_since_reset - totalTime) / time_since_reset) * 100); + parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time); + + displayProfileString(xOffset,yStart,blockTime); + yStart += yIncr; + + + + sprintf(blockTime,"-------------------------------------------------"); + displayProfileString(xOffset,yStart,blockTime); + yStart += yIncr; + + } +#endif//BT_NO_PROFILE + + return time_since_reset; + + +} + + +// +void DemoApplication::renderscene(int pass) +{ + btScalar m[16]; + btMatrix3x3 rot;rot.setIdentity(); + const int numObjects=m_dynamicsWorld->getNumCollisionObjects(); + btVector3 wireColor(1,0,0); + for(int i=0;igetCollisionObjectArray()[i]; + btRigidBody* body=btRigidBody::upcast(colObj); + if(body&&body->getMotionState()) + { + btDefaultMotionState* myMotionState = (btDefaultMotionState*)body->getMotionState(); + myMotionState->m_graphicsWorldTrans.getOpenGLMatrix(m); + rot=myMotionState->m_graphicsWorldTrans.getBasis(); + } + else + { + colObj->getWorldTransform().getOpenGLMatrix(m); + rot=colObj->getWorldTransform().getBasis(); + } + btVector3 wireColor(1.f,1.0f,0.5f); //wants deactivation + if(i&1) wireColor=btVector3(0.f,0.0f,1.f); + ///color differently for active, sleeping, wantsdeactivation states + if (colObj->getActivationState() == 1) //active + { + if (i & 1) + { + wireColor += btVector3 (1.f,0.f,0.f); + } + else + { + wireColor += btVector3 (.5f,0.f,0.f); + } + } + if(colObj->getActivationState()==2) //ISLAND_SLEEPING + { + if(i&1) + { + wireColor += btVector3 (0.f,1.f, 0.f); + } + else + { + wireColor += btVector3 (0.f,0.5f,0.f); + } + } + + btVector3 aabbMin,aabbMax; + m_dynamicsWorld->getBroadphase()->getBroadphaseAabb(aabbMin,aabbMax); + + aabbMin-=btVector3(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); + aabbMax+=btVector3(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); +// printf("aabbMin=(%f,%f,%f)\n",aabbMin.getX(),aabbMin.getY(),aabbMin.getZ()); +// printf("aabbMax=(%f,%f,%f)\n",aabbMax.getX(),aabbMax.getY(),aabbMax.getZ()); +// m_dynamicsWorld->getDebugDrawer()->drawAabb(aabbMin,aabbMax,btVector3(1,1,1)); + + + if (!(getDebugMode()& btIDebugDraw::DBG_DrawWireframe)) + { + switch(pass) + { + case 0: m_shapeDrawer->drawOpenGL(m,colObj->getCollisionShape(),wireColor,getDebugMode(),aabbMin,aabbMax);break; + case 1: m_shapeDrawer->drawShadow(m,m_sundirection*rot,colObj->getCollisionShape(),aabbMin,aabbMax);break; + case 2: m_shapeDrawer->drawOpenGL(m,colObj->getCollisionShape(),wireColor*btScalar(0.3),0,aabbMin,aabbMax);break; + } + } + } +} + +// +void DemoApplication::renderme() +{ + myinit(); + + updateCamera(); + + if (m_dynamicsWorld) + { + if(m_enableshadows) + { + glClear(GL_STENCIL_BUFFER_BIT); + glEnable(GL_CULL_FACE); + renderscene(0); + + glDisable(GL_LIGHTING); + glDepthMask(GL_FALSE); + glDepthFunc(GL_LEQUAL); + glEnable(GL_STENCIL_TEST); + glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); + glStencilFunc(GL_ALWAYS,1,0xFFFFFFFFL); + glFrontFace(GL_CCW); + glStencilOp(GL_KEEP,GL_KEEP,GL_INCR); + renderscene(1); + glFrontFace(GL_CW); + glStencilOp(GL_KEEP,GL_KEEP,GL_DECR); + renderscene(1); + glFrontFace(GL_CCW); + + glPolygonMode(GL_FRONT,GL_FILL); + glPolygonMode(GL_BACK,GL_FILL); + glShadeModel(GL_SMOOTH); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_LIGHTING); + glDepthMask(GL_TRUE); + glCullFace(GL_BACK); + glFrontFace(GL_CCW); + glEnable(GL_CULL_FACE); + glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); + + glDepthFunc(GL_LEQUAL); + glStencilFunc( GL_NOTEQUAL, 0, 0xFFFFFFFFL ); + glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); + glDisable(GL_LIGHTING); + renderscene(2); + glEnable(GL_LIGHTING); + glDepthFunc(GL_LESS); + glDisable(GL_STENCIL_TEST); + glDisable(GL_CULL_FACE); + } + else + { + glDisable(GL_CULL_FACE); + renderscene(0); + } + + int xOffset = 10; + int yStart = 20; + int yIncr = 20; + + + glDisable(GL_LIGHTING); + glColor3f(0, 0, 0); + + if ((m_debugMode & btIDebugDraw::DBG_NoHelpText)==0) + { + setOrthographicProjection(); + + showProfileInfo(xOffset,yStart,yIncr); + +#ifdef USE_QUICKPROF + + + if ( getDebugMode() & btIDebugDraw::DBG_ProfileTimings) + { + static int counter = 0; + counter++; + std::map::iterator iter; + for (iter = btProfiler::mProfileBlocks.begin(); iter != btProfiler::mProfileBlocks.end(); ++iter) + { + char blockTime[128]; + sprintf(blockTime, "%s: %lf",&((*iter).first[0]),btProfiler::getBlockTime((*iter).first, btProfiler::BLOCK_CYCLE_SECONDS));//BLOCK_TOTAL_PERCENT)); + glRasterPos3f(xOffset,yStart,0); + GLDebugDrawString(BMF_GetFont(BMF_kHelvetica10),blockTime); + yStart += yIncr; + + } + + } +#endif //USE_QUICKPROF + + + + + resetPerspectiveProjection(); + } + + glDisable(GL_LIGHTING); + + + } + + updateCamera(); + +} + +#include "BulletCollision/BroadphaseCollision/btAxisSweep3.h" + + +void DemoApplication::clientResetScene() +{ + removePickingConstraint(); + +#ifdef SHOW_NUM_DEEP_PENETRATIONS + gNumDeepPenetrationChecks = 0; + gNumGjkChecks = 0; +#endif //SHOW_NUM_DEEP_PENETRATIONS + + gNumClampedCcdMotions = 0; + int numObjects = 0; + int i; + + if (m_dynamicsWorld) + { + int numConstraints = m_dynamicsWorld->getNumConstraints(); + for (i=0;igetConstraint(0)->setEnabled(true); + } + numObjects = m_dynamicsWorld->getNumCollisionObjects(); + + ///create a copy of the array, not a reference! + btCollisionObjectArray copyArray = m_dynamicsWorld->getCollisionObjectArray(); + + + + + for (i=0;igetMotionState()) + { + btDefaultMotionState* myMotionState = (btDefaultMotionState*)body->getMotionState(); + myMotionState->m_graphicsWorldTrans = myMotionState->m_startWorldTrans; + body->setCenterOfMassTransform( myMotionState->m_graphicsWorldTrans ); + colObj->setInterpolationWorldTransform( myMotionState->m_startWorldTrans ); + colObj->forceActivationState(ACTIVE_TAG); + colObj->activate(); + colObj->setDeactivationTime(0); + //colObj->setActivationState(WANTS_DEACTIVATION); + } + //removed cached contact points (this is not necessary if all objects have been removed from the dynamics world) + if (m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()) + m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(colObj->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher()); + + btRigidBody* body = btRigidBody::upcast(colObj); + if (body && !body->isStaticObject()) + { + btRigidBody::upcast(colObj)->setLinearVelocity(btVector3(0,0,0)); + btRigidBody::upcast(colObj)->setAngularVelocity(btVector3(0,0,0)); + } + } + + } + + ///reset some internal cached data in the broadphase + m_dynamicsWorld->getBroadphase()->resetPool(getDynamicsWorld()->getDispatcher()); + m_dynamicsWorld->getConstraintSolver()->reset(); + + } + +} diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/DemoApplication.h b/Extras/RigidBodyGpuPipeline/dynamics/testbed/DemoApplication.h new file mode 100644 index 0000000..42903e3 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/DemoApplication.h @@ -0,0 +1,257 @@ +/* +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 DEMO_APPLICATION_H +#define DEMO_APPLICATION_H + + +#include "GlutStuff.h" +#include "GL_ShapeDrawer.h" + +#include +#include +#include + + +#include "LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btAlignedObjectArray.h" + +class btCollisionShape; +class btDynamicsWorld; +class btRigidBody; +class btTypedConstraint; + + + +class DemoApplication +{ +protected: + void displayProfileString(int xOffset,int yStart,char* message); + class CProfileIterator* m_profileIterator; + + protected: +#ifdef USE_BT_CLOCK + btClock m_clock; +#endif //USE_BT_CLOCK + + ///this is the most important class + btDynamicsWorld* m_dynamicsWorld; + + ///constraint for mouse picking + btTypedConstraint* m_pickConstraint; + + virtual void removePickingConstraint(); + + btCollisionShape* m_shootBoxShape; + + float m_cameraDistance; + int m_debugMode; + + float m_ele; + float m_azi; + btVector3 m_cameraPosition; + btVector3 m_cameraTargetPosition;//look at + + int m_mouseOldX; + int m_mouseOldY; + int m_mouseButtons; +public: + int m_modifierKeys; +protected: + + float m_scaleBottom; + float m_scaleFactor; + btVector3 m_cameraUp; + int m_forwardAxis; + + int m_glutScreenWidth; + int m_glutScreenHeight; + + float m_frustumZNear; + float m_frustumZFar; + + int m_ortho; + + float m_ShootBoxInitialSpeed; + + bool m_stepping; + bool m_singleStep; + bool m_idle; + int m_lastKey; + + virtual float showProfileInfo(int& xOffset,int& yStart, int yIncr); + void renderscene(int pass); + + GL_ShapeDrawer* m_shapeDrawer; + bool m_enableshadows; + btVector3 m_sundirection; + btScalar m_defaultContactProcessingThreshold; + +public: + + DemoApplication(); + + virtual ~DemoApplication(); + + btDynamicsWorld* getDynamicsWorld() + { + return m_dynamicsWorld; + } + + virtual void initPhysics() = 0; + + virtual void setDrawClusters(bool drawClusters) + { + + } + + void overrideGLShapeDrawer (GL_ShapeDrawer* shapeDrawer); + + void setOrthographicProjection(); + void resetPerspectiveProjection(); + + bool setTexturing(bool enable) { return(m_shapeDrawer->enableTexture(enable)); } + bool setShadows(bool enable) { bool p=m_enableshadows;m_enableshadows=enable;return(p); } + bool getTexturing() const + { + return m_shapeDrawer->hasTextureEnabled(); + } + bool getShadows() const + { + return m_enableshadows; + } + + + int getDebugMode() + { + return m_debugMode ; + } + + void setDebugMode(int mode); + + void setAzi(float azi) + { + m_azi = azi; + } + + void setCameraUp(const btVector3& camUp) + { + m_cameraUp = camUp; + } + void setCameraForwardAxis(int axis) + { + m_forwardAxis = axis; + } + + virtual void myinit(); + + void toggleIdle(); + + virtual void updateCamera(); + + btVector3 getCameraPosition() + { + return m_cameraPosition; + } + btVector3 getCameraTargetPosition() + { + return m_cameraTargetPosition; + } + + btScalar getDeltaTimeMicroseconds() + { +#ifdef USE_BT_CLOCK + btScalar dt = (btScalar)m_clock.getTimeMicroseconds(); + m_clock.reset(); + return dt; +#else + return btScalar(16666.); +#endif + } + void setFrustumZPlanes(float zNear, float zFar) + { + m_frustumZNear = zNear; + m_frustumZFar = zFar; + } + + ///glut callbacks + + float getCameraDistance(); + void setCameraDistance(float dist); + void moveAndDisplay(); + + virtual void clientMoveAndDisplay() = 0; + + virtual void clientResetScene(); + + ///Demo functions + virtual void setShootBoxShape (); + virtual void shootBox(const btVector3& destination); + + + btVector3 getRayTo(int x,int y); + + btRigidBody* localCreateRigidBody(float mass, const btTransform& startTransform,btCollisionShape* shape); + + ///callback methods by glut + + virtual void keyboardCallback(unsigned char key, int x, int y); + + virtual void keyboardUpCallback(unsigned char key, int x, int y) {} + + virtual void specialKeyboard(int key, int x, int y){} + + virtual void specialKeyboardUp(int key, int x, int y){} + + virtual void reshape(int w, int h); + + virtual void mouseFunc(int button, int state, int x, int y); + + virtual void mouseMotionFunc(int x,int y); + + virtual void displayCallback(); + + virtual void renderme(); + + virtual void swapBuffers() = 0; + + virtual void updateModifierKeys() = 0; + + void stepLeft(); + void stepRight(); + void stepFront(); + void stepBack(); + void zoomIn(); + void zoomOut(); + + bool isIdle() const + { + return m_idle; + } + + void setIdle(bool idle) + { + m_idle = idle; + } + + +}; + +#endif //DEMO_APPLICATION_H + + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/GLDebugDrawer.cpp b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GLDebugDrawer.cpp new file mode 100644 index 0000000..79758df --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GLDebugDrawer.cpp @@ -0,0 +1,139 @@ + +#include "GLDebugDrawer.h" +#include "GLDebugFont.h" +#include "GlutStuff.h" + + + +#include //printf debugging +GLDebugDrawer::GLDebugDrawer() +:m_debugMode(0) +{ + +} + +void GLDebugDrawer::drawLine(const btVector3& from,const btVector3& to,const btVector3& fromColor, const btVector3& toColor) +{ + glBegin(GL_LINES); + glColor3f(fromColor.getX(), fromColor.getY(), fromColor.getZ()); + glVertex3d(from.getX(), from.getY(), from.getZ()); + glColor3f(toColor.getX(), toColor.getY(), toColor.getZ()); + glVertex3d(to.getX(), to.getY(), to.getZ()); + glEnd(); +} + +void GLDebugDrawer::drawLine(const btVector3& from,const btVector3& to,const btVector3& color) +{ + drawLine(from,to,color,color); +} + +void GLDebugDrawer::drawSphere (const btVector3& p, btScalar radius, const btVector3& color) +{ + glColor4f (color.getX(), color.getY(), color.getZ(), btScalar(1.0f)); + glPushMatrix (); + glTranslatef (p.getX(), p.getY(), p.getZ()); + + int lats = 5; + int longs = 5; + + int i, j; + for(i = 0; i <= lats; i++) { + btScalar lat0 = SIMD_PI * (-btScalar(0.5) + (btScalar) (i - 1) / lats); + btScalar z0 = radius*sin(lat0); + btScalar zr0 = radius*cos(lat0); + + btScalar lat1 = SIMD_PI * (-btScalar(0.5) + (btScalar) i / lats); + btScalar z1 = radius*sin(lat1); + btScalar zr1 = radius*cos(lat1); + + glBegin(GL_QUAD_STRIP); + for(j = 0; j <= longs; j++) { + btScalar lng = 2 * SIMD_PI * (btScalar) (j - 1) / longs; + btScalar x = cos(lng); + btScalar y = sin(lng); + + glNormal3f(x * zr0, y * zr0, z0); + glVertex3f(x * zr0, y * zr0, z0); + glNormal3f(x * zr1, y * zr1, z1); + glVertex3f(x * zr1, y * zr1, z1); + } + glEnd(); + } + + glPopMatrix(); +} + +void GLDebugDrawer::drawBox (const btVector3& boxMin, const btVector3& boxMax, const btVector3& color, btScalar alpha) +{ + btVector3 halfExtent = (boxMax - boxMin) * btScalar(0.5f); + btVector3 center = (boxMax + boxMin) * btScalar(0.5f); + //glEnable(GL_BLEND); // Turn blending On + //glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glColor4f (color.getX(), color.getY(), color.getZ(), alpha); + glPushMatrix (); + glTranslatef (center.getX(), center.getY(), center.getZ()); + glScaled(2*halfExtent[0], 2*halfExtent[1], 2*halfExtent[2]); +// glutSolidCube(1.0); + glPopMatrix (); + //glDisable(GL_BLEND); +} + +void GLDebugDrawer::drawTriangle(const btVector3& a,const btVector3& b,const btVector3& c,const btVector3& color,btScalar alpha) +{ +// if (m_debugMode > 0) + { + const btVector3 n=btCross(b-a,c-a).normalized(); + glBegin(GL_TRIANGLES); + glColor4f(color.getX(), color.getY(), color.getZ(),alpha); + glNormal3d(n.getX(),n.getY(),n.getZ()); + glVertex3d(a.getX(),a.getY(),a.getZ()); + glVertex3d(b.getX(),b.getY(),b.getZ()); + glVertex3d(c.getX(),c.getY(),c.getZ()); + glEnd(); + } +} + +void GLDebugDrawer::setDebugMode(int debugMode) +{ + m_debugMode = debugMode; + +} + +void GLDebugDrawer::draw3dText(const btVector3& location,const char* textString) +{ + glRasterPos3f(location.x(), location.y(), location.z()); + //BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),textString); +} + +void GLDebugDrawer::reportErrorWarning(const char* warningString) +{ + printf("%s\n",warningString); +} + +void GLDebugDrawer::drawContactPoint(const btVector3& pointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color) +{ + + { + btVector3 to=pointOnB+normalOnB*1;//distance; + const btVector3&from = pointOnB; + glColor4f(color.getX(), color.getY(), color.getZ(),1.f); + //glColor4f(0,0,0,1.f); + glBegin(GL_LINES); + glVertex3d(from.getX(), from.getY(), from.getZ()); + glVertex3d(to.getX(), to.getY(), to.getZ()); + glEnd(); + + +// glRasterPos3f(from.x(), from.y(), from.z()); +// char buf[12]; +// sprintf(buf," %d",lifeTime); + //BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); + + + } +} + + + + + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/GLDebugDrawer.h b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GLDebugDrawer.h new file mode 100644 index 0000000..2a05405 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GLDebugDrawer.h @@ -0,0 +1,38 @@ +#ifndef GL_DEBUG_DRAWER_H +#define GL_DEBUG_DRAWER_H + +#include "LinearMath/btIDebugDraw.h" + + + +class GLDebugDrawer : public btIDebugDraw +{ + int m_debugMode; + +public: + + GLDebugDrawer(); + + + virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& fromColor, const btVector3& toColor); + + virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color); + + virtual void drawSphere (const btVector3& p, btScalar radius, const btVector3& color); + virtual void drawBox (const btVector3& boxMin, const btVector3& boxMax, const btVector3& color, btScalar alpha); + + virtual void drawTriangle(const btVector3& a,const btVector3& b,const btVector3& c,const btVector3& color,btScalar alpha); + + virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color); + + virtual void reportErrorWarning(const char* warningString); + + virtual void draw3dText(const btVector3& location,const char* textString); + + virtual void setDebugMode(int debugMode); + + virtual int getDebugMode() const { return m_debugMode;} + +}; + +#endif//GL_DEBUG_DRAWER_H diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/GLDebugFont.cpp b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GLDebugFont.cpp new file mode 100644 index 0000000..b629731 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GLDebugFont.cpp @@ -0,0 +1,1000 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "GLDebugFont.h" + + +#ifdef _WIN32//for glut.h +#include +#endif + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#if (defined (TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || (defined (TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR) +#import +#define glOrtho glOrthof +#else +#include +#include +#include +#endif +#else + + + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif +#endif + +#include +#include //for memset + +extern unsigned char sFontData[]; +static bool sTexturesInitialized = false; + +static GLuint sTexture = -1; +static int sScreenWidth = -1; +static int sScreenHeight = -1; + + +void GLDebugResetFont(int screenWidth,int screenHeight) +{ + + if ((sScreenWidth == screenWidth) && (sScreenHeight == screenHeight)) + return; + + sScreenWidth = screenWidth; + sScreenHeight = screenHeight; + + if (!sTexturesInitialized) + { + sTexturesInitialized = true; + glGenTextures(1, &sTexture); + glBindTexture(GL_TEXTURE_2D, sTexture); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, 3, 256 , 256 , 0, GL_RGB, GL_UNSIGNED_BYTE, &sFontData[0]); + } + + printf("generating font at resolution %d,%d\n",screenWidth,screenHeight); + +} + +#define USE_ARRAYS 1 + +void GLDebugDrawStringInternal(int x,int y,const char* string, const btVector3& rgb) +{ + GLDebugDrawStringInternal(x,y,string,rgb,true,10); +} + +void GLDebugDrawStringInternal(int x,int y,const char* string, const btVector3& rgb, bool enableBlend, int spacing) +{ + + if (!sTexturesInitialized) + { + GLDebugResetFont(sScreenWidth,sScreenHeight); + } + if (strlen(string)) + { + + glColor4f(rgb.getX(),rgb.getY(),rgb.getZ(),1.f); + float cx; + float cy; + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); + + glEnable(GL_TEXTURE_2D); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + glDepthFunc (GL_LEQUAL); + + if (enableBlend) + { + glEnable(GL_BLEND); + } else + { + glDisable(GL_BLEND); + } + glEnable (GL_DEPTH_TEST); + glBindTexture(GL_TEXTURE_2D, sTexture); + glDisable(GL_DEPTH_TEST); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glOrtho(0,sScreenWidth,0,sScreenHeight,-1,1); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glTranslatef(btScalar(x),btScalar(sScreenHeight - y),btScalar(0)); + +#if USE_ARRAYS + + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState (GL_TEXTURE_COORD_ARRAY); +#endif + + GLfloat verts[] ={ + 0.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, + 0.f,0.f,0.f + }; + + GLfloat uv_texcoords[] = { + 0,0, + 0,0, + 0,0, + 0,0 + }; + verts[0] = 0; verts[1] = 0; verts[2] = 0; + verts[3] = 16-1; verts[4] = 0; verts[5] = 0; + verts[6] = 16-1; verts[7] = 16-1; verts[8] = 0; + verts[9] = 0; verts[10] = 16-1; verts[11] = 0; + + for (int i=0;i=0) + { + cx=float(ch%16) * btScalar(1./16.f); + cy=float(ch/16) * btScalar(1./16.f); + + uv_texcoords[0] = cx; uv_texcoords[1] = btScalar(1-cy-1./16.f); + uv_texcoords[2] = btScalar(cx+1./16.f); uv_texcoords[3] = btScalar(1-cy-1./16.f); + uv_texcoords[4] = btScalar(cx+1./16.f); uv_texcoords[5] = btScalar(1-cy); + uv_texcoords[6] = cx; uv_texcoords[7] = btScalar(1-cy); +#if USE_ARRAYS + glTexCoordPointer(2,GL_FLOAT,0,uv_texcoords); + glVertexPointer(3, GL_FLOAT, 0, verts); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +#else + glBegin(GL_QUADS); + glTexCoord2f(cx,1-cy-1./16.f); + + glVertex2i(0,0); + glTexCoord2f(cx+1./16.f,1-cy-1./16.f); + + glVertex2i(16 - 1,0); + glTexCoord2f(cx+1./16.f,1-cy); + + glVertex2i(16 - 1,16 -1); + glTexCoord2f(cx,1-cy); + + glVertex2i(0,16 -1); + glEnd(); +#endif + + glTranslatef(spacing,0,0); + } + } + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +#if 1 + glEnable(GL_DEPTH_TEST); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + glDepthFunc (GL_LEQUAL); + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glScalef(btScalar(0.025),btScalar(0.025),btScalar(0.025)); +#endif + glMatrixMode(GL_MODELVIEW); +#if USE_ARRAYS + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState (GL_TEXTURE_COORD_ARRAY); +#endif + //glDisable(GL_TEXTURE_2D); + } +} + +void GLDebugDrawString(int x,int y,const char* string) +{ + + btVector3 rgb(1,1,1); + GLDebugDrawStringInternal(x,y,string,rgb); +} + + +unsigned char sFontData[] = +{ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,145,145,145,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,213,213,213,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,103,103,103,2,2,2,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213, + 213,213,255,255,255,255,255,255,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,213,213,213,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,213,213,213,255,255,255,255,255,255,255,255,255,213,213,213,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,178,178,178,178,178,178,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,0,0,0,0,0,0,0,0,0,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,103,103,103,103,103,103,178,178,178,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,145,145,145,178,178,178,255,255,255,255,255,255,255,255,255,145,145,145,103,103,103,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,2,2,2,255,255,255,178,178,178,103,103,103,145,145,145,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,103,103,103,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,103,103,103,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255, + 255,255,145,145,145,103,103,103,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,178,178,178,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,178,178,178,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,145,145,145,255,255,255,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,103,103,103,103,103,103,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,145,145,145,178,178,178,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,103,103,103,145,145,145,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,0,0,0,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,70,70,70,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70, + 70,70,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,255,255,255,70,70, + 70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,213,213,213,255,255,255,255,255,255,0,0,0,0,0,0,70,70,70,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,103,103,103,255,255,255,213,213,213,70,70,70,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,255,255,255,246,246,246,178,178,178,246,246,246,70,70,70,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37, + 37,37,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,178,178,178,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,255,255,255,213,213, + 213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,255,255,255,255,255,255,103,103,103,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,255,255,255,103,103,103,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,178,178,178,255,255,255,37,37,37,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,255,255,255,255,255,255,145,145,145,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2,2,2,145,145,145,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255, + 255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,103,103,103,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,145,145,145,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,70,70,70,255,255,255,70,70,70,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,213,213,213,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,70,70,70,255,255,255,37,37,37,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,103,103,103,246,246,246,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,70,70,70,255,255,255,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,255,255,255,145,145,145,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,0,0,0,37,37,37,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,0,0,0,37,37,37,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,70,70,70,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,103,103,103,213,213,213,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,37,37,37,255,255,255,178,178,178,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,70,70,70,0,0,0,70,70,70,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,145,145,145,213,213,213,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,70,70,70,255,255,255,37,37,37,0,0,0,145,145,145,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,178,178,178,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,0,0,0,103,103,103,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,0,0,0,103,103,103,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255, + 255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,255,255,255,213,213,213,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,103,103,103,103,103,103,103,103,103,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,246,246,246,103,103,103,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,37,37,37,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,246,246,246,103,103,103,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,103,103,103,70,70,70,0,0,0,103,103,103,255,255, + 255,246,246,246,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,145,145,145,103,103,103,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,2,2,2,255,255,255,255,255, + 255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,178,178,178,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,255,255,255,246,246, + 246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,103,103,103,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,213,213,213,213,213,213,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,213,213,213,213,213,213,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255, + 255,255,255,255,255,213,213,213,213,213,213,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,178,178,178,213,213,213,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,103,103,103,145,145,145,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,178,178,178,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,103,103,103,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178, + 178,178,103,103,103,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,145,145,145,145,145,145,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,145,145,145,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,103,103,103,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,103,103,103,103,103,103,178,178,178,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,103,103,103,178,178,178,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,255,255,255,145,145,145,0,0,0,37,37,37,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,145,145,145,0,0,0,37,37,37,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2, + 2,2,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2,2,2,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103, + 103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,103,103,103,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,103,103,103,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,103,103,103,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,103,103,103,103,103,103,255,255,255,178,178, + 178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,103,103,103,103,103,103,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,103,103,103,103,103,103,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37, + 37,37,103,103,103,103,103,103,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,103,103,103,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246, + 246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,0,0,0,37,37,37,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,246,246,246,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,103,103,103,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,103,103, + 103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,0,0,0,103,103,103,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103, + 103,103,246,246,246,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,103,103,103,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,103,103,103,145,145,145,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,213,213,213,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,213,213,213,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,70,70,70,70,70,70,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,37,37,37,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,37,37,37,70,70,70,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,178,178,178,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,246,246,246,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,145,145,145,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,213,213,213,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,213,213,213,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,213,213,213,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246, + 246,246,255,255,255,255,255,255,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,145,145,145,178,178,178,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,178,178,178,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,246,246,246,103,103,103,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,103,103,103,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255, + 255,255,213,213,213,178,178,178,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,178,178,178,0,0,0,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,178,178,178,255,255,255,255,255,255,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,103,103,103,103,103,103,178,178,178,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,70,70,70,0,0,0,0,0,0,37,37,37,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,0,0,0,2,2,2,37,37,37,145,145,145,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255, + 255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,70,70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,145,145,145,255,255,255,103,103,103,255,255,255,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,178,178,178,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,246,246,246,0,0,0,0,0,0,246,246,246,70,70, + 70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,2,2,2,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,2,2,2,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,178,178,178,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,70,70,70,2,2,2,2,2,2,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,103,103,103,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,255,255,255,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,178,178,178,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,103,103,103,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,145,145,145,255,255,255,103,103,103,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,178,178,178,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,246,246,246,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,255,255,255,246,246,246,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,145,145,145,103,103,103,178,178,178,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,103,103,103,103,103,103,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255, + 255,255,213,213,213,0,0,0,37,37,37,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,213,213,213,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,246,246,246,70,70,70,103,103,103,246,246,246,0,0,0,213,213,213,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,103,103,103,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,103,103,103,103,103,103,255,255,255,255,255,255,246,246, + 246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,213,213,213,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,145,145,145,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,70,70,70,178,178,178,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255, + 255,255,255,255,255,0,0,0,103,103,103,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,145,145,145,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,103,103,103,103,103,103,145,145,145,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,178,178,178,103,103,103,178,178,178,255,255,255,145,145,145,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,213,213,213,213,213,213,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,213,213,213,213,213,213,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,213,213,213,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,213,213,213,213,213,213,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213, + 213,213,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,213,213,213,145,145,145,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,213,213,213,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,255,255,255,145,145,145,178,178,178,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,178,178,178,255,255,255,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246, + 246,246,103,103,103,103,103,103,103,103,103,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,178,178,178,255,255,255,178,178,178,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,178,178,178,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,0,0,0,178,178,178,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,0,0,0,70,70,70,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,37,37,37,178,178,178,255,255,255,37,37,37,178,178,178,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,0,0,0,70,70,70,178,178,178,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,213,213,213,103,103,103,103,103,103,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,70,70,70,0,0,0,0,0,0,37,37,37,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,103,103,103,255,255,255,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246, + 246,246,103,103,103,103,103,103,103,103,103,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,255,255,255,2,2,2,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,103,103,103,103,103,103,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255, + 255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,103,103,103,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,103,103,103,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,103,103,103,213,213,213,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,246,246,246,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,213,213,213,255,255,255,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,37,37,37,255,255,255,255,255,255,70,70,70,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,103,103,103,145,145,145,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,178,178,178,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,213,213,213,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,145,145,145,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,145,145,145,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,178,178,178,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,178,178,178,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,37,37, + 37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,246,246,246,255,255,255,145,145,145,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,213,213,213,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246, + 246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,246,246,246,178,178,178,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,103,103,103,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255, + 255,255,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,0,0,0,103,103,103,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,103,103,103,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255, + 255,255,145,145,145,103,103,103,178,178,178,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,213,213,213,255,255,255,246,246,246,2,2,2,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,103,103,103,103,103,103,178,178,178,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37, + 37,37,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,2,2,2,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,145,145,145,0,0,0,0,0,0,255,255,255,103,103, + 103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,103,103,103,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2, + 2,2,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,37,37,37,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,255,255,255,2,2,2,246,246,246,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,70,70,70,0,0,0,145,145,145,103,103, + 103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,213,213,213,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,246,246,246,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103, + 103,103,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,103,103,103,246,246,246,255,255,255,103,103,103,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,70,70,70,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,2,2,2,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,145,145,145,2,2,2,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,70,70,70,255,255,255,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213, + 213,213,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,255,255,255,255,255,255,2,2,2,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,70,70,70,0,0,0,255,255,255,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,37,37,37,0,0,0,255,255,255,37,37,37,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255, + 255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,103,103,103,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,37,37,37,0,0,0,103,103,103,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,255,255,255,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,103,103,103,103,103,103,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,246,246,246,103,103,103,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,103,103,103,103,103,103,103,103,103,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,103,103,103,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,255,255,255,246,246,246,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255, + 255,255,103,103,103,103,103,103,0,0,0,70,70,70,103,103,103,255,255,255,246,246,246,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,246,246,246,2,2,2,0,0,0,0,0,0,213,213,213,255,255,255,213,213,213,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,0,0,0,213,213,213,255,255,255,145,145,145,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,145,145,145,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,103,103,103,213,213,213,255,255,255,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255, + 255,255,255,255,255,255,255,255,2,2,2,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,178,178,178,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,213,213,213,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,213,213,213,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,213,213,213,103,103,103,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,103,103,103,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,145,145,145,0,0,0,0,0,0,37,37,37,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,178,178,178,103,103,103,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,103,103,103,145,145,145,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255, + 255,255,103,103,103,103,103,103,103,103,103,178,178,178,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,103,103,103,103,103,103,213,213,213,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,103,103,103,0,0,0,178,178,178,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,145,145,145,103,103,103,255,255,255,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,70,70,70,0,0,0,37,37,37,255,255,255,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,103,103,103,103,103,103,103,103,103,178,178,178,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,255,255,255,103,103,103,0,0,0,2,2,2,178,178,178,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,255,255,255,103,103,103,0,0,0,70,70,70,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,103,103,103,145,145,145,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,103,103,103,255,255,255,255,255,255,178,178,178,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255, + 255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,145,145,145,178,178,178,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,246,246,246,255,255,255,2,2,2,213,213,213,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,103,103,103,103,103,103,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,178,178,178,103,103,103,255,255,255,213,213,213,70,70,70,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,103,103,103,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,103,103,103,103,103,103,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,2,2,2,178,178,178,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,246,246,246,255,255,255,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,255,255,255,213,213,213,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,37,37,37,255,255,255,178,178,178,37,37,37,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,246,246,246,255,255,255,178,178,178,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,70,70,70,255,255,255,70,70,70,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,145,145,145,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246, + 246,246,213,213,213,0,0,0,70,70,70,255,255,255,37,37,37,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,70,70,70,255,255,255,37,37,37,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,246,246,246,103,103,103,255,255,255,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,213,213,213,255,255,255,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145, + 145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37, + 37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,2,2,2,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,246,246,246,2,2,2,103,103,103,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,246,246,246,103,103,103,103,103,103,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,213,213,213,255,255,255,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,103,103,103,103,103,103,103,103,103,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,103,103,103,103,103,103,103,103,103,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213, + 213,213,255,255,255,103,103,103,103,103,103,103,103,103,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,103,103,103,103,103,103,103,103,103,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,103,103,103,0,0,0,103,103,103,255,255,255,246,246,246,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,103,103,103,255,255,255,246,246,246,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,255,255,255,246,246, + 246,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,103,103,103,103,103,103,0,0,0,255,255,255,255,255,255,145,145,145,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,213,213,213,255,255,255,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,2,2,2,0,0,0,255,255,255,255,255,255,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,70,70,70,0,0,0,103,103,103,255,255,255,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,145,145,145,103,103,103,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,70,70,70,246,246,246,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,2,2,2,0,0,0,103,103,103,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255, + 255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,178,178,178,255,255,255,178,178,178,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,103,103,103,178,178,178,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,255,255,255,178,178,178,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213, + 213,213,103,103,103,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,103,103,103,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,103,103,103,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,246,246,246,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,213,213,213,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,103,103,103,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,37,37,37,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,213,213,213,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,213,213,213,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,178,178,178,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246, + 246,246,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,246,246,246,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,178,178,178,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145, + 145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,37,37,37,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,37,37,37,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,246,246,246,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37, + 37,37,255,255,255,103,103,103,103,103,103,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,103,103,103,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,103,103,103,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,213,213,213,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,213,213,213,103,103,103,103,103,103,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,246,246,246,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,178,178,178,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,246,246,246,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,246,246,246,213,213,213,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,145,145,145,213,213,213,255,255,255,255,255,255,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,178, + 178,178,0,0,0,0,0,0,213,213,213,213,213,213,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,2,2,2,178,178,178,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,178,178,178,255,255,255,178,178,178,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,145,145,145,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103, + 103,103,255,255,255,178,178,178,0,0,0,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,103,103,103,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,246,246,246,255,255,255,255,255,255,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,2,2,2,178,178,178,255,255,255,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,213,213,213,37,37,37,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,213,213,213,255,255,255,37,37, + 37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,103,103,103,213,213,213,255,255,255,145,145,145,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255, + 255,255,255,255,255,145,145,145,0,0,0,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,37,37,37,103,103,103,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,145,145,145,70,70,70,2,2,2,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255, + 255,255,0,0,0,255,255,255,2,2,2,0,0,0,2,2,2,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,145,145,145,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255, + 255,255,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,2,2,2,255,255,255,145,145,145,70,70, + 70,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,2,2,2,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70, + 70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,145,145,145,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,37,37,37,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,255,255, + 255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,246,246,246,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37, + 37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,37,37,37,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,37,37,37,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0, + 0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,213,213,213,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,2,2,2,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,213,213,213,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,37,37,37,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,2,2,2,255,255,255,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,246,246,246,103,103,103,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,103,103,103,246,246,246,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,246,246,246,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,2,2,2,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,103,103,103,255,255,255,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,213,213,213,246,246,246,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,145,145,145,246,246,246,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,103,103,103,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,103,103,103,255,255,255,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37, + 37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,37,37,37,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,145,145,145,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,37,37,37,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,37,37,37,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,70,70,70,0,0,0,2,2,2,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,37,37,37,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0, + 0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,145,145,145,0,0,0,70,70,70,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,178,178,178,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0, + 0,145,145,145,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,213,213,213,145,145,145,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,70,70,70,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,255,255, + 255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,159,159,159,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,246,246,246,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,255,255,255,255,255,255,37,37,37,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,255,255,255,255,255,255,255,255, + 255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,37,37,37,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,213,213,213,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,213,213,213,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,246,246,246,0,0,0,0,0,0,213,213,213,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,213,213,213,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,178,178,178,0,0,0,0,0,0,0,0, + 0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103, + 103,103,255,255,255,37,37,37,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,246,246,246,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,178,178,178,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,178,178,178,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,2,2,2,178,178,178,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,178,178,178,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,246,246,246,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,246,246,246,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,246,246,246,246,246,246,255,255, + 255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,0,0,0,145,145, + 145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,70,70,70,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255, + 255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,145,145,145,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,145,145,145,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,213,213,213,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,178,178, + 178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,70,70,70,0,0,0,0,0,0,2,2,2,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,37,37,37,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,70,70,70,0,0,0,2,2,2,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,37,37,37,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,2,2,2,0,0,0,70,70,70,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,37,37,37,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,145,145,145,0,0,0,70,70,70,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,246,246,246,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,70,70,70,0,0,0,145,145,145,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,145,145,145,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,213,213,213,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,70,70,70,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,37,37,37,246,246,246,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,255,255,255,37,37,37,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,70,70,70,0,0,0,37,37,37,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,213,213,213,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,145,145,145,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,213,213,213,0,0,0,145,145,145,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,213,213,213,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,255,255,255,0,0,0,255,255,255,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,145,145,145,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,246,246,246,0,0,0,255,255,255,0,0,0,213,213,213,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,213,213,213,0,0,0,103,103,103,246,246,246,255,255,255,0,0,0,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178, + 178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,255,255,255,37,37,37,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,2,2,2,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,255,255,255,70,70,70,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,2,2,2,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255, + 255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,70,70,70,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,246,246,246,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,37,37,37,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,213,213,213,255,255,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,37,37,37,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,37,37,37,246,246,246,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,70,70,70,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,246,246,246,103,103,103,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,213,213,213,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,37,37,37,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,37,37,37,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37, + 37,37,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,37,37,37,255,255,255,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,246,246,246,103,103,103,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,246,246,246,103,103,103,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,246,246,246,103,103,103,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,178,178,178,246,246,246,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255, + 255,255,255,255,255,246,246,246,246,246,246,246,246,246,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,246,246,246,103,103,103,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213, + 213,213,178,178,178,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,213,213,213,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,37,37,37,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,246,246,246,246,246,246,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,255,255,255,37,37,37,70,70,70,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,70,70,70,0,0,0,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,2,2,2,0,0,0,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,246,246,246,2,2,2,145,145,145,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,70,70,70,255,255,255,246,246,246,178,178,178,213,213,213,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,246,246,246,2,2,2,145,145,145,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,37,37,37,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,145,145,145,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,2,2,2,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,178,178,178,145,145,145,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,37,37,37,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,246,246,246,255,255,255,0,0,0,178,178,178,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,37,37,37,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,246,246,246,103,103,103,103,103,103,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,37,37,37,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,246,246,246,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,255,255,255,255,255,255,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37,37,0,0,0,145,145,145,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,103,103,103,0,0,0,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,246,246,246,0,0,0,255,255,255,213,213,213,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,37,37,37,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,255,255,255,0,0,0,255,255,255,2,2,2,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,255,255,255,103,103,103,255,255,255,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,70,70,70,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,246,246,246,255,255,255,178,178,178,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,178,178,178,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,103,103,103,255,255,255,103,103,103,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,37,37,37,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,37,37, + 37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,70,70,70,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,2,2,2,246,246,246,0,0,0,0,0,0,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,178,178,178,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255, + 255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,103,103,103,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,37,37,37,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,213,213,213,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,178,178,178,255,255,255,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,178,178, + 178,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,213,213,213,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,145,145,145,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,246,246,246,246,246,246,246,246,246,246,246,246,246,246, + 246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,103,103,103,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,246,246,246,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,37,37, + 37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,103,103,103,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,213,213,213,0,0,0,0,0,0,103,103,103,0,0,0,70,70,70,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,255,255,255,178,178,178,178,178,178,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255, + 255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,103,103,103,255,255,255,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,2,2,2,255,255,255,0,0,0,178,178,178,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255, + 255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,246,246,246,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,2,2,2,246,246,246,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,255,255,255,246,246,246,246,246,246,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,246,246,246,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255, + 255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,213,213,213,178,178,178,255,255,255,70,70,70,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,103,103,103,255,255,255,2,2,2,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,145,145,145,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255, + 255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,255,255,255,2,2,2,103,103,103,213,213,213,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,255,255,255,178,178,178,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,103,103,103,0,0,0,145,145,145,103,103,103,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255, + 255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,255,255,255,0,0,0,0,0,0,255,255,255,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,246,246,246,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,103,103,103,246,246,246,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255, + 255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,37,37,37,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,70,70,70,0,0,0,0,0,0,2,2,2,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,70,70,70,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,178,178,178,255,255,255,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,103,103,103,255,255, + 255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,246,246,246,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,213,213,213,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,246,246,246,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246, + 246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,213,213,213,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,70,70,70,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,246,246,246,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,246,246,246,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,246,246,246,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,103,103,103,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,246,246,246,255,255,255,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,70,70,70,103,103,103,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,37,37,37,246,246,246,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,246,246,246,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,213,213,213,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,178,178,178,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,103,103,103,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,178,178,178,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,246,246,246,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,213,213,213,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,2,2,2,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,246,246,246,246,246,246,103,103,103,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,103,103,103,103,103,103,145,145,145,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,2,2,2,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,2,2,2,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,213,213,213,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,255,255,255,255,255,255,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,145,145,145,246,246,246,246,246,246,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,255,255,255,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,70,70,70,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,255,255,255,255,255,255,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,178, + 178,178,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,255,255,255,255,255,255,103,103,103,145,145,145,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,2,2,2,0,0,0,255,255,255,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246, + 246,246,37,37,37,0,0,0,37,37,37,246,246,246,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,103,103,103,0,0,0,0,0,0,246,246,246,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,103,103,103,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,255,255,0,0,0,103,103,103,103,103,103,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,246,246,246,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,255,255,255,246,246,246,255,255,255,255,255,255,246,246,246,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,70,70,70,246,246,246,37,37,37,246,246,246,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,246,246,246,255,255,255,0,0,0,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,246,246,246,255,255,255,255,255,255,246,246,246,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,103,103,103,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,213,213,213,103,103,103,145,145,145,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,70,70,70,255,255,255,2,2,2,0,0,0,246,246,246,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,255,255,255,103,103,103,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,37,37,37,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,2,2,2,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,255,255,255,246,246,246,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,255,255, + 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,246,246,246,246,246,246,103,103,103,255,255,255,178,178,178,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255, + 255,255,145,145,145,255,255,255,37,37,37,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,255,255,255,145,145,145,178,178, + 178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,255,255,255,103,103,103,213,213,213,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0, + 0,0,0,0,0,255,255,255,255,255,255,145,145,145,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,145,145,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,2,2,2,0,0,0,70,70, + 70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,2,2,2,0,0,0,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,255,255,255,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0, + 0,0,0,0,0,103,103,103,103,103,103,0,0,0,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,103,103,103,2,2,2,70,70,70,70,70, + 70,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,70,70,70,0,0,0,178,178,178,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,70,70,70,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,255,255,255,103,103,103,255,255,255,2,2,2,103,103,103,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,213,213,103, + 103,103,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,213,213,213,0,0,0,255,255,255,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,178,178,178,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,103,103,103,0,0,0,246,246,246,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,103,103,103,0,0,0,103,103,103,37,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,213,213,213,255,255,255,246,246,246,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178, + 178,178,246,246,246,37,37,37,0,0,0,0,0,0,0,0,0,103,103,103,213,213,213,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,178,178,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,255,255,255,255,255,255,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178,178,178,255,255,255,145,145,145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,145,145,145,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,70,70,70,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,2,2,2,0,0,0,70,70,70,70,70,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,37,37,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,103,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,70,70,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/GLDebugFont.h b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GLDebugFont.h new file mode 100644 index 0000000..bf2c257 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GLDebugFont.h @@ -0,0 +1,29 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_DEBUG_FONT_H +#define BT_DEBUG_FONT_H + +#include "LinearMath/btVector3.h" + + +void GLDebugDrawStringInternal(int x,int y,const char* string,const btVector3& rgb, bool enableBlend, int spacing); +void GLDebugDrawStringInternal(int x,int y,const char* string,const btVector3& rgb); +void GLDebugDrawString(int x,int y,const char* string); +void GLDebugResetFont(int screenWidth,int screenHeight); + +#endif //BT_DEBUG_FONT_H + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/GL_ShapeDrawer.cpp b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GL_ShapeDrawer.cpp new file mode 100644 index 0000000..7beb19f --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GL_ShapeDrawer.cpp @@ -0,0 +1,1058 @@ +/* +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. +*/ + +#ifdef _WIN32 //needed for glut.h +#include +#endif +#include "GLDebugFont.h" + + + +#include "GlutStuff.h" +#include "GL_ShapeDrawer.h" +#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" +#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btConeShape.h" +#include "BulletCollision/CollisionShapes/btCylinderShape.h" +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btUniformScalingShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h" + + +/// +#include "BulletCollision/CollisionShapes/btShapeHull.h" + +#include "LinearMath/btTransformUtil.h" + + +#include "LinearMath/btIDebugDraw.h" +//for debugmodes + +#include //printf debugging + +//#define USE_DISPLAY_LISTS 1 +#ifdef USE_DISPLAY_LISTS + +#include + +using namespace std; + +//Set for storing Display list per trimesh +struct TRIMESH_KEY +{ + btCollisionShape* m_shape; + GLuint m_dlist;//OpenGL display list +}; + +typedef map TRIMESH_KEY_MAP; + +typedef pair TRIMESH_KEY_PAIR; + +TRIMESH_KEY_MAP g_display_lists; + +class GlDisplaylistDrawcallback : public btTriangleCallback +{ +public: + + virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex) + { + + btVector3 diff1 = triangle[1] - triangle[0]; + btVector3 diff2 = triangle[2] - triangle[0]; + btVector3 normal = diff1.cross(diff2); + + normal.normalize(); + + glBegin(GL_TRIANGLES); + glColor3f(1, 1, 1); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + + //glColor3f(0, 1, 0); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + + //glColor3f(0, 1, 0); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glEnd(); + + /*glBegin(GL_LINES); + glColor3f(1, 1, 0); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glColor3f(1, 1, 0); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glColor3f(1, 1, 0); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glNormal3d(normal.getX(),normal.getY(),normal.getZ()); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glEnd();*/ + + + } +}; + +GLuint OGL_get_displaylist_for_shape(btCollisionShape * shape) +{ + TRIMESH_KEY_MAP::iterator map_iter; + + unsigned long key = (unsigned long)shape; + map_iter = g_display_lists.find(key); + if(map_iter!=g_display_lists.end()) + { + return map_iter->second.m_dlist; + } + + return 0; +} + +void OGL_displaylist_clean() +{ + TRIMESH_KEY_MAP::iterator map_iter,map_itend; + + map_iter = g_display_lists.begin(); + + while(map_iter!=map_itend) + { + glDeleteLists(map_iter->second.m_dlist,1); + map_iter++; + } + + g_display_lists.clear(); +} + + +void OGL_displaylist_register_shape(btCollisionShape * shape) +{ + btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + btVector3 aabbMin(-btScalar(BT_LARGE_FLOAT),-btScalar(BT_LARGE_FLOAT),-btScalar(BT_LARGE_FLOAT)); + GlDisplaylistDrawcallback drawCallback; + TRIMESH_KEY dlist; + + dlist.m_dlist = glGenLists(1); + dlist.m_shape = shape; + + unsigned long key = (unsigned long)shape; + + g_display_lists.insert(TRIMESH_KEY_PAIR(key,dlist)); + + glNewList(dlist.m_dlist,GL_COMPILE); + +// glEnable(GL_CULL_FACE); + + glCullFace(GL_BACK); + + if (shape->isConcave()) + { + btConcaveShape* concaveMesh = (btConcaveShape*) shape; + //todo pass camera, for some culling + concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax); + } + +// glDisable(GL_CULL_FACE); + + glEndList(); +} +#endif //USE_DISPLAY_LISTS + +void GL_ShapeDrawer::drawCoordSystem() { + glBegin(GL_LINES); + glColor3f(1, 0, 0); + glVertex3d(0, 0, 0); + glVertex3d(1, 0, 0); + glColor3f(0, 1, 0); + glVertex3d(0, 0, 0); + glVertex3d(0, 1, 0); + glColor3f(0, 0, 1); + glVertex3d(0, 0, 0); + glVertex3d(0, 0, 1); + glEnd(); + +} + + + + + +class GlDrawcallback : public btTriangleCallback +{ + +public: + + bool m_wireframe; + + GlDrawcallback() + :m_wireframe(false) + { + } + + virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex) + { + + (void)triangleIndex; + (void)partId; + + + if (m_wireframe) + { + glBegin(GL_LINES); + glColor3f(1, 0, 0); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glColor3f(0, 1, 0); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glColor3f(0, 0, 1); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glEnd(); + } else + { + glBegin(GL_TRIANGLES); + //glColor3f(1, 1, 1); + + + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glEnd(); + } + } +}; + +class TriangleGlDrawcallback : public btInternalTriangleIndexCallback +{ +public: + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + (void)triangleIndex; + (void)partId; + + + glBegin(GL_TRIANGLES);//LINES); + glColor3f(1, 0, 0); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glColor3f(0, 1, 0); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); + glColor3f(0, 0, 1); + glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); + glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); + glEnd(); + } +}; + + +void GL_ShapeDrawer::drawSphere(btScalar radius, int lats, int longs) +{ + int i, j; + for(i = 0; i <= lats; i++) { + btScalar lat0 = SIMD_PI * (-btScalar(0.5) + (btScalar) (i - 1) / lats); + btScalar z0 = radius*sin(lat0); + btScalar zr0 = radius*cos(lat0); + + btScalar lat1 = SIMD_PI * (-btScalar(0.5) + (btScalar) i / lats); + btScalar z1 = radius*sin(lat1); + btScalar zr1 = radius*cos(lat1); + + glBegin(GL_QUAD_STRIP); + for(j = 0; j <= longs; j++) { + btScalar lng = 2 * SIMD_PI * (btScalar) (j - 1) / longs; + btScalar x = cos(lng); + btScalar y = sin(lng); + glNormal3f(x * zr1, y * zr1, z1); + glVertex3f(x * zr1, y * zr1, z1); + glNormal3f(x * zr0, y * zr0, z0); + glVertex3f(x * zr0, y * zr0, z0); + } + glEnd(); + } +} + +void GL_ShapeDrawer::drawCylinder(float radius,float halfHeight, int upAxis) +{ + + + glPushMatrix(); + switch (upAxis) + { + case 0: + glRotatef(-90.0, 0.0, 1.0, 0.0); + glTranslatef(0.0, 0.0, -halfHeight); + break; + case 1: + glRotatef(-90.0, 1.0, 0.0, 0.0); + glTranslatef(0.0, 0.0, -halfHeight); + break; + case 2: + + glTranslatef(0.0, 0.0, -halfHeight); + break; + default: + { + btAssert(0); + } + + } + + GLUquadricObj *quadObj = gluNewQuadric(); + + //The gluCylinder subroutine draws a cylinder that is oriented along the z axis. + //The base of the cylinder is placed at z = 0; the top of the cylinder is placed at z=height. + //Like a sphere, the cylinder is subdivided around the z axis into slices and along the z axis into stacks. + + gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL); + gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH); + + gluDisk(quadObj,0,radius,15, 10); + + gluCylinder(quadObj, radius, radius, 2.f*halfHeight, 15, 10); + glTranslatef(0.0f, 0.0f, 2.f*halfHeight); + glRotatef(-180.0f, 0.0f, 1.0f, 0.0f); + gluDisk(quadObj,0.f,radius,15, 10); + + glPopMatrix(); + gluDeleteQuadric(quadObj); +} + +GL_ShapeDrawer::ShapeCache* GL_ShapeDrawer::cache(btConvexShape* shape) +{ + ShapeCache* sc=(ShapeCache*)shape->getUserPointer(); + if(!sc) + { + sc=new(btAlignedAlloc(sizeof(ShapeCache),16)) ShapeCache(shape); + + m_shapecaches.push_back(sc); + shape->setUserPointer(sc); + + const btConvexPolyhedron* poly = shape->isPolyhedral() ? ((btPolyhedralConvexShape*) shape)->getConvexPolyhedron() : 0; + if (poly) + { + int i; + /* Build edges */ + const int nv= poly->m_vertices.size(); + if (nv) + { + const btVector3* pv=&poly->m_vertices[0]; + btAlignedObjectArray edges; + edges.resize(nv*nv,0); + + int maxIndices = 0; + for (i=0;im_faces.size();i++) + { + maxIndices += poly->m_faces[i].m_indices.size(); + } + sc->m_edges.reserve(maxIndices); + + for (i=0;im_faces.size();i++) + { + int numVerts = poly->m_faces[i].m_indices.size(); + if (numVerts>2) + { + int index0 = poly->m_faces[i].m_indices[0]; + int index1 = poly->m_faces[i].m_indices[1]; + int index2 = poly->m_faces[i].m_indices[2]; + int j = poly->m_faces[i].m_indices.size()-1; + const btVector3 nrm=btCross(pv[index1]-pv[index0],pv[index2]-pv[index0]).normalized(); + + for (int v=0;vm_faces[i].m_indices.size();j=v++) + { + { + const unsigned int a=poly->m_faces[i].m_indices[j]; + const unsigned int b=poly->m_faces[i].m_indices[v]; + int edgeIndex = btMin(a,b)*nv+btMax(a,b); + ShapeCache::Edge*& e=edges[edgeIndex]; + if(!e) + { + sc->m_edges.push_back(ShapeCache::Edge()); + e=&sc->m_edges[sc->m_edges.size()-1]; + e->n[0]=nrm;e->n[1]=-nrm; + e->v[0]=a;e->v[1]=b; + } + else + { + e->n[1]=nrm; + } + } + } + } + } + } + + } else + { + + sc->m_shapehull.buildHull(shape->getMargin()); + + + /* Build edges */ + const int ni=sc->m_shapehull.numIndices(); + const int nv=sc->m_shapehull.numVertices(); + const unsigned int* pi=sc->m_shapehull.getIndexPointer(); + const btVector3* pv=sc->m_shapehull.getVertexPointer(); + btAlignedObjectArray edges; + sc->m_edges.reserve(ni); + edges.resize(nv*nv,0); + for(int i=0;im_edges.push_back(ShapeCache::Edge()); + e=&sc->m_edges[sc->m_edges.size()-1]; + e->n[0]=nrm;e->n[1]=-nrm; + e->v[0]=a;e->v[1]=b; + } + else + { + e->n[1]=nrm; + } + } + } + } + } + return(sc); +} + +void renderSquareA(float x, float y, float z) +{ + glBegin(GL_LINE_LOOP); + glVertex3f(x, y, z); + glVertex3f(x + 10.f, y, z); + glVertex3f(x + 10.f, y + 10.f, z); + glVertex3f(x, y + 10.f, z); + glEnd(); +} + +inline void glDrawVector(const btVector3& v) { glVertex3d(v[0], v[1], v[2]); } + + +void GL_ShapeDrawer::drawOpenGL(btScalar* m, const btCollisionShape* shape, const btVector3& color,int debugMode,const btVector3& worldBoundsMin,const btVector3& worldBoundsMax) +{ + + if (shape->getShapeType() == CUSTOM_CONVEX_SHAPE_TYPE) + { + btVector3 org(m[12], m[13], m[14]); + btVector3 dx(m[0], m[1], m[2]); + btVector3 dy(m[4], m[5], m[6]); +// btVector3 dz(m[8], m[9], m[10]); + const btBoxShape* boxShape = static_cast(shape); + btVector3 halfExtent = boxShape->getHalfExtentsWithMargin(); + dx *= halfExtent[0]; + dy *= halfExtent[1]; +// dz *= halfExtent[2]; + glColor3f(1,1,1); + glDisable(GL_LIGHTING); + glLineWidth(2); + + glBegin(GL_LINE_LOOP); + glDrawVector(org - dx - dy); + glDrawVector(org - dx + dy); + glDrawVector(org + dx + dy); + glDrawVector(org + dx - dy); + glEnd(); + return; + } + else if((shape->getShapeType() == BOX_SHAPE_PROXYTYPE) && (debugMode & btIDebugDraw::DBG_FastWireframe)) + { + btVector3 org(m[12], m[13], m[14]); + btVector3 dx(m[0], m[1], m[2]); + btVector3 dy(m[4], m[5], m[6]); + btVector3 dz(m[8], m[9], m[10]); + const btBoxShape* boxShape = static_cast(shape); + btVector3 halfExtent = boxShape->getHalfExtentsWithMargin(); + dx *= halfExtent[0]; + dy *= halfExtent[1]; + dz *= halfExtent[2]; + glBegin(GL_LINE_LOOP); + glDrawVector(org - dx - dy - dz); + glDrawVector(org + dx - dy - dz); + glDrawVector(org + dx + dy - dz); + glDrawVector(org - dx + dy - dz); + glDrawVector(org - dx + dy + dz); + glDrawVector(org + dx + dy + dz); + glDrawVector(org + dx - dy + dz); + glDrawVector(org - dx - dy + dz); + glEnd(); + glBegin(GL_LINES); + glDrawVector(org + dx - dy - dz); + glDrawVector(org + dx - dy + dz); + glDrawVector(org + dx + dy - dz); + glDrawVector(org + dx + dy + dz); + glDrawVector(org - dx - dy - dz); + glDrawVector(org - dx + dy - dz); + glDrawVector(org - dx - dy + dz); + glDrawVector(org - dx + dy + dz); + glEnd(); + return; + } + + glPushMatrix(); + btglMultMatrix(m); + + + if (shape->getShapeType() == UNIFORM_SCALING_SHAPE_PROXYTYPE) + { + const btUniformScalingShape* scalingShape = static_cast(shape); + const btConvexShape* convexShape = scalingShape->getChildShape(); + float scalingFactor = (float)scalingShape->getUniformScalingFactor(); + { + btScalar tmpScaling[4][4]={{scalingFactor,0,0,0}, + {0,scalingFactor,0,0}, + {0,0,scalingFactor,0}, + {0,0,0,1}}; + + drawOpenGL( (btScalar*)tmpScaling,convexShape,color,debugMode,worldBoundsMin,worldBoundsMax); + } + glPopMatrix(); + return; + } + + if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) + { + const btCompoundShape* compoundShape = static_cast(shape); + for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* colShape = compoundShape->getChildShape(i); + btScalar childMat[16]; + childTrans.getOpenGLMatrix(childMat); + drawOpenGL(childMat,colShape,color,debugMode,worldBoundsMin,worldBoundsMax); + } + + } else + { + if(m_textureenabled&&(!m_textureinitialized)) + { + GLubyte* image=new GLubyte[256*256*3]; + for(int y=0;y<256;++y) + { + const int t=y>>4; + GLubyte* pi=image+y*256*3; + for(int x=0;x<256;++x) + { + const int s=x>>4; + const GLubyte b=180; + GLubyte c=b+((s+t&1)&1)*(255-b); + pi[0]=pi[1]=pi[2]=c;pi+=3; + } + } + + glGenTextures(1,(GLuint*)&m_texturehandle); + glBindTexture(GL_TEXTURE_2D,m_texturehandle); + glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); + gluBuild2DMipmaps(GL_TEXTURE_2D,3,256,256,GL_RGB,GL_UNSIGNED_BYTE,image); + delete[] image; + + + } + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glScalef(0.025f,0.025f,0.025f); + glMatrixMode(GL_MODELVIEW); + + static const GLfloat planex[]={1,0,0,0}; + // static const GLfloat planey[]={0,1,0,0}; + static const GLfloat planez[]={0,0,1,0}; + glTexGenfv(GL_S,GL_OBJECT_PLANE,planex); + glTexGenfv(GL_T,GL_OBJECT_PLANE,planez); + glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR); + glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + m_textureinitialized=true; + + + + + //drawCoordSystem(); + + //glPushMatrix(); + glEnable(GL_COLOR_MATERIAL); + if(m_textureenabled) + { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,m_texturehandle); + } else + { + glDisable(GL_TEXTURE_2D); + } + + + glColor3f(color.x(),color.y(), color.z()); + + bool useWireframeFallback = true; + + if (!(debugMode & btIDebugDraw::DBG_DrawWireframe)) + { + ///you can comment out any of the specific cases, and use the default + + ///the benefit of 'default' is that it approximates the actual collision shape including collision margin + //int shapetype=m_textureenabled?MAX_BROADPHASE_COLLISION_TYPES:shape->getShapeType(); + int shapetype=shape->getShapeType(); + switch (shapetype) + { + + case SPHERE_SHAPE_PROXYTYPE: + { + const btSphereShape* sphereShape = static_cast(shape); + float radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin + drawSphere(radius,10,10); + useWireframeFallback = false; + break; + } + + case BOX_SHAPE_PROXYTYPE: + { + const btBoxShape* boxShape = static_cast(shape); + btVector3 halfExtent = boxShape->getHalfExtentsWithMargin(); + + static int indices[36] = { + 0,1,2, + 3,2,1, + 4,0,6, + 6,0,2, + 5,1,4, + 4,1,0, + 7,3,1, + 7,1,5, + 5,4,7, + 7,4,6, + 7,2,3, + 7,6,2}; + + btVector3 vertices[8]={ + btVector3(halfExtent[0],halfExtent[1],halfExtent[2]), + btVector3(-halfExtent[0],halfExtent[1],halfExtent[2]), + btVector3(halfExtent[0],-halfExtent[1],halfExtent[2]), + btVector3(-halfExtent[0],-halfExtent[1],halfExtent[2]), + btVector3(halfExtent[0],halfExtent[1],-halfExtent[2]), + btVector3(-halfExtent[0],halfExtent[1],-halfExtent[2]), + btVector3(halfExtent[0],-halfExtent[1],-halfExtent[2]), + btVector3(-halfExtent[0],-halfExtent[1],-halfExtent[2])}; +#if 1 + glBegin (GL_TRIANGLES); + int si=36; + for (int i=0;i(shape); + int upIndex = coneShape->getConeUpIndex(); + float radius = coneShape->getRadius();//+coneShape->getMargin(); + float height = coneShape->getHeight();//+coneShape->getMargin(); + switch (upIndex) + { + case 0: + glRotatef(90.0, 0.0, 1.0, 0.0); + break; + case 1: + glRotatef(-90.0, 1.0, 0.0, 0.0); + break; + case 2: + break; + default: + { + } + }; + + glTranslatef(0.0, 0.0, -0.5*height); + glutSolidCone(radius,height,10,10); + useWireframeFallback = false; + break; + + } +#endif + + case STATIC_PLANE_PROXYTYPE: + { + const btStaticPlaneShape* staticPlaneShape = static_cast(shape); + btScalar planeConst = staticPlaneShape->getPlaneConstant(); + const btVector3& planeNormal = staticPlaneShape->getPlaneNormal(); + btVector3 planeOrigin = planeNormal * planeConst; + btVector3 vec0,vec1; + btPlaneSpace1(planeNormal,vec0,vec1); + btScalar vecLen = 100.f; + btVector3 pt0 = planeOrigin + vec0*vecLen; + btVector3 pt1 = planeOrigin - vec0*vecLen; + btVector3 pt2 = planeOrigin + vec1*vecLen; + btVector3 pt3 = planeOrigin - vec1*vecLen; + glBegin(GL_LINES); + glVertex3f(pt0.getX(),pt0.getY(),pt0.getZ()); + glVertex3f(pt1.getX(),pt1.getY(),pt1.getZ()); + glVertex3f(pt2.getX(),pt2.getY(),pt2.getZ()); + glVertex3f(pt3.getX(),pt3.getY(),pt3.getZ()); + glEnd(); + + + break; + + } + +/* + case CYLINDER_SHAPE_PROXYTYPE: + { + const btCylinderShape* cylinder = static_cast(shape); + int upAxis = cylinder->getUpAxis(); + + + float radius = cylinder->getRadius(); + float halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis]; + + drawCylinder(radius,halfHeight,upAxis); + + break; + } +*/ + + case MULTI_SPHERE_SHAPE_PROXYTYPE: + { + const btMultiSphereShape* multiSphereShape = static_cast(shape); + + btTransform childTransform; + childTransform.setIdentity(); + + + for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--) + { + btSphereShape sc(multiSphereShape->getSphereRadius(i)); + childTransform.setOrigin(multiSphereShape->getSpherePosition(i)); + btScalar childMat[16]; + childTransform.getOpenGLMatrix(childMat); + drawOpenGL(childMat,&sc,color,debugMode,worldBoundsMin,worldBoundsMax); + } + + break; + } + + default: + { + if (shape->isConvex()) + { + const btConvexPolyhedron* poly = shape->isPolyhedral() ? ((btPolyhedralConvexShape*) shape)->getConvexPolyhedron() : 0; + if (poly) + { + int i; + glBegin (GL_TRIANGLES); + for (i=0;im_faces.size();i++) + { + btVector3 centroid(0,0,0); + int numVerts = poly->m_faces[i].m_indices.size(); + if (numVerts>2) + { + btVector3 v1 = poly->m_vertices[poly->m_faces[i].m_indices[0]]; + for (int v=0;vm_faces[i].m_indices.size()-2;v++) + { + + btVector3 v2 = poly->m_vertices[poly->m_faces[i].m_indices[v+1]]; + btVector3 v3 = poly->m_vertices[poly->m_faces[i].m_indices[v+2]]; + btVector3 normal = (v3-v1).cross(v2-v1); + normal.normalize (); + glNormal3f(normal.getX(),normal.getY(),normal.getZ()); + glVertex3f (v1.x(), v1.y(), v1.z()); + glVertex3f (v2.x(), v2.y(), v2.z()); + glVertex3f (v3.x(), v3.y(), v3.z()); + } + } + } + glEnd (); + } else + { + ShapeCache* sc=cache((btConvexShape*)shape); + //glutSolidCube(1.0); + btShapeHull* hull = &sc->m_shapehull/*(btShapeHull*)shape->getUserPointer()*/; + + if (hull && hull->numTriangles () > 0) + { + int index = 0; + const unsigned int* idx = hull->getIndexPointer(); + const btVector3* vtx = hull->getVertexPointer(); + + glBegin (GL_TRIANGLES); + + for (int i = 0; i < hull->numTriangles (); i++) + { + int i1 = index++; + int i2 = index++; + int i3 = index++; + btAssert(i1 < hull->numIndices () && + i2 < hull->numIndices () && + i3 < hull->numIndices ()); + + int index1 = idx[i1]; + int index2 = idx[i2]; + int index3 = idx[i3]; + btAssert(index1 < hull->numVertices () && + index2 < hull->numVertices () && + index3 < hull->numVertices ()); + + btVector3 v1 = vtx[index1]; + btVector3 v2 = vtx[index2]; + btVector3 v3 = vtx[index3]; + btVector3 normal = (v3-v1).cross(v2-v1); + normal.normalize (); + glNormal3f(normal.getX(),normal.getY(),normal.getZ()); + glVertex3f (v1.x(), v1.y(), v1.z()); + glVertex3f (v2.x(), v2.y(), v2.z()); + glVertex3f (v3.x(), v3.y(), v3.z()); + + } + glEnd (); + + } + } + } + } + } + + } + + + glNormal3f(0,1,0); + + + /// for polyhedral shapes + if (debugMode==btIDebugDraw::DBG_DrawFeaturesText && (shape->isPolyhedral())) + { + btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape; + + { + + glColor3f(1.f, 1.f, 1.f); + int i; + for (i=0;igetNumVertices();i++) + { + btVector3 vtx; + polyshape->getVertex(i,vtx); + char buf[12]; + sprintf(buf," %d",i); + //btDrawString(BMF_GetFont(BMF_kHelvetica10),buf); + } + + for (i=0;igetNumPlanes();i++) + { + btVector3 normal; + btVector3 vtx; + polyshape->getPlane(normal,vtx,i); + //btScalar d = vtx.dot(normal); + + //char buf[12]; + //sprintf(buf," plane %d",i); + //btDrawString(BMF_GetFont(BMF_kHelvetica10),buf); + + } + } + + } + + +#ifdef USE_DISPLAY_LISTS + + if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE||shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE) + { + GLuint dlist = OGL_get_displaylist_for_shape((btCollisionShape * )shape); + if (dlist) + { + glCallList(dlist); + } + else + { +#else + if (shape->isConcave() && !shape->isInfinite()) + { + btConcaveShape* concaveMesh = (btConcaveShape*) shape; + + GlDrawcallback drawCallback; + drawCallback.m_wireframe = (debugMode & btIDebugDraw::DBG_DrawWireframe)!=0; + + concaveMesh->processAllTriangles(&drawCallback,worldBoundsMin,worldBoundsMax); + + } +#endif + +#ifdef USE_DISPLAY_LISTS + } +} +#endif + + + + + + } + glPopMatrix(); + +} + +// +void GL_ShapeDrawer::drawShadow(btScalar* m,const btVector3& extrusion,const btCollisionShape* shape,const btVector3& worldBoundsMin,const btVector3& worldBoundsMax) +{ + glPushMatrix(); + btglMultMatrix(m); + if(shape->getShapeType() == UNIFORM_SCALING_SHAPE_PROXYTYPE) + { + const btUniformScalingShape* scalingShape = static_cast(shape); + const btConvexShape* convexShape = scalingShape->getChildShape(); + float scalingFactor = (float)scalingShape->getUniformScalingFactor(); + btScalar tmpScaling[4][4]={ {scalingFactor,0,0,0}, + {0,scalingFactor,0,0}, + {0,0,scalingFactor,0}, + {0,0,0,1}}; + drawShadow((btScalar*)tmpScaling,extrusion,convexShape,worldBoundsMin,worldBoundsMax); + glPopMatrix(); + return; + } + else if(shape->getShapeType()==COMPOUND_SHAPE_PROXYTYPE) + { + const btCompoundShape* compoundShape = static_cast(shape); + for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* colShape = compoundShape->getChildShape(i); + btScalar childMat[16]; + childTrans.getOpenGLMatrix(childMat); + drawShadow(childMat,extrusion*childTrans.getBasis(),colShape,worldBoundsMin,worldBoundsMax); + } + } + else + { + // bool useWireframeFallback = true; + if (shape->isConvex()) + { + + const btConvexPolyhedron* poly = shape->isPolyhedral() ? ((btPolyhedralConvexShape*) shape)->getConvexPolyhedron() : 0; + ShapeCache* sc=cache((btConvexShape*)shape); + btShapeHull* hull =&sc->m_shapehull; + const btVector3* vertexPointer = 0; + + vertexPointer = (poly && poly->m_vertices.size())? &poly->m_vertices[0] : 0; + if (!vertexPointer) + vertexPointer = hull->numVertices() ? hull->getVertexPointer():0; + + if (vertexPointer) + { + glBegin(GL_QUADS); + for(int i=0;im_edges.size();++i) + { + const btScalar d=btDot(sc->m_edges[i].n[0],extrusion); + if((d*btDot(sc->m_edges[i].n[1],extrusion))<0) + { + const int q= d<0?1:0; + const btVector3& a= vertexPointer[sc->m_edges[i].v[q]]; + const btVector3& b= vertexPointer[sc->m_edges[i].v[1-q]]; + glVertex3f(a[0],a[1],a[2]); + glVertex3f(b[0],b[1],b[2]); + glVertex3f(b[0]+extrusion[0],b[1]+extrusion[1],b[2]+extrusion[2]); + glVertex3f(a[0]+extrusion[0],a[1]+extrusion[1],a[2]+extrusion[2]); + } + } + glEnd(); + } + } + } + + + if (shape->isConcave())//>getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE||shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE) + // if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + btConcaveShape* concaveMesh = (btConcaveShape*) shape; + + GlDrawcallback drawCallback; + drawCallback.m_wireframe = false; + + concaveMesh->processAllTriangles(&drawCallback,worldBoundsMin,worldBoundsMax); + + } + glPopMatrix(); + +} + +// +GL_ShapeDrawer::GL_ShapeDrawer() +{ + m_texturehandle = 0; + m_textureenabled = false; + m_textureinitialized = false; +} + +GL_ShapeDrawer::~GL_ShapeDrawer() +{ + int i; + for (i=0;i~ShapeCache(); + btAlignedFree(m_shapecaches[i]); + } + m_shapecaches.clear(); + if(m_textureinitialized) + { + glDeleteTextures(1,(const GLuint*) &m_texturehandle); + } +} + + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/GL_ShapeDrawer.h b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GL_ShapeDrawer.h new file mode 100644 index 0000000..65bf29d --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GL_ShapeDrawer.h @@ -0,0 +1,70 @@ +/* +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 GL_SHAPE_DRAWER_H +#define GL_SHAPE_DRAWER_H + +class btCollisionShape; +class btShapeHull; +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btVector3.h" + +#include "BulletCollision/CollisionShapes/btShapeHull.h" + +/// OpenGL shape drawing +class GL_ShapeDrawer +{ +protected: + struct ShapeCache + { + struct Edge { btVector3 n[2];int v[2]; }; + ShapeCache(btConvexShape* s) : m_shapehull(s) {} + btShapeHull m_shapehull; + btAlignedObjectArray m_edges; + }; + //clean-up memory of dynamically created shape hulls + btAlignedObjectArray m_shapecaches; + unsigned int m_texturehandle; + bool m_textureenabled; + bool m_textureinitialized; + + + ShapeCache* cache(btConvexShape*); + +public: + GL_ShapeDrawer(); + + virtual ~GL_ShapeDrawer(); + + ///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); + virtual void drawShadow(btScalar* m, const btVector3& extrusion,const btCollisionShape* shape,const btVector3& worldBoundsMin,const btVector3& worldBoundsMax); + + bool enableTexture(bool enable) { bool p=m_textureenabled;m_textureenabled=enable;return(p); } + bool hasTextureEnabled() const + { + return m_textureenabled; + } + + static void drawCylinder(float radius,float halfHeight, int upAxis); + void drawSphere(btScalar r, int lats, int longs); + static void drawCoordSystem(); + +}; + +void OGL_displaylist_register_shape(btCollisionShape * shape); +void OGL_displaylist_clean(); + +#endif //GL_SHAPE_DRAWER_H + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/GL_Simplex1to4.cpp b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GL_Simplex1to4.cpp new file mode 100644 index 0000000..b364a1b --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GL_Simplex1to4.cpp @@ -0,0 +1,76 @@ +/* +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 "GL_Simplex1to4.h" +#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" +#include "GL_ShapeDrawer.h" +#ifdef _WIN32 +#include +#endif + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#else +#include +#endif +#include "GlutStuff.h" +#include "LinearMath/btTransform.h" + +GL_Simplex1to4::GL_Simplex1to4() +:m_simplexSolver(0) +{ +} + +/// +/// Debugging method calcClosest calculates the closest point to the origin, using m_simplexSolver +/// +void GL_Simplex1to4::calcClosest(btScalar* m) +{ + btTransform tr; + tr.setFromOpenGLMatrix(m); + + + + GL_ShapeDrawer::drawCoordSystem(); + + if (m_simplexSolver) + { + m_simplexSolver->reset(); + bool res; + + btVector3 v; + + for (int i=0;iaddVertex(v,v,btVector3(0.f,0.f,0.f)); + res = m_simplexSolver->closest(v); + } + + //draw v? + glDisable(GL_LIGHTING); + glBegin(GL_LINES); + btglColor3(1.f, 0.f, 0.f); + btglVertex3(0.f, 0.f, 0.f); + btglVertex3(v.x(),v.y(),v.z()); + glEnd(); + + glEnable(GL_LIGHTING); + + + } + +} diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/GL_Simplex1to4.h b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GL_Simplex1to4.h new file mode 100644 index 0000000..c75e357 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GL_Simplex1to4.h @@ -0,0 +1,40 @@ +/* +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 GL_SIMPLEX_1TO4_H +#define GL_SIMPLEX_1TO4_H + +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" + +#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" + +///GL_Simplex1to4 is a class to debug a Simplex Solver with 1 to 4 points. +///Can be used by GJK. +class GL_Simplex1to4 : public btBU_Simplex1to4 +{ + btSimplexSolverInterface* m_simplexSolver; + + public: + + GL_Simplex1to4(); + + void calcClosest(btScalar* m); + + void setSimplexSolver(btSimplexSolverInterface* simplexSolver) { + m_simplexSolver = simplexSolver; + } + +}; + +#endif //GL_SIMPLEX_1TO4_H diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/GlutDemoApplication.cpp b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GlutDemoApplication.cpp new file mode 100644 index 0000000..0ceaede --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GlutDemoApplication.cpp @@ -0,0 +1,87 @@ + +#ifndef _WINDOWS + +#include "GlutDemoApplication.h" + +#include "GlutStuff.h" + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" + +void GlutDemoApplication::updateModifierKeys() +{ + m_modifierKeys = 0; + if (glutGetModifiers() & GLUT_ACTIVE_ALT) + m_modifierKeys |= BT_ACTIVE_ALT; + + if (glutGetModifiers() & GLUT_ACTIVE_CTRL) + m_modifierKeys |= BT_ACTIVE_CTRL; + + if (glutGetModifiers() & GLUT_ACTIVE_SHIFT) + m_modifierKeys |= BT_ACTIVE_SHIFT; +} + +void GlutDemoApplication::specialKeyboard(int key, int x, int y) +{ + (void)x; + (void)y; + + switch (key) + { + case GLUT_KEY_F1: + { + + break; + } + + case GLUT_KEY_F2: + { + + break; + } + + + case GLUT_KEY_END: + { + int numObj = getDynamicsWorld()->getNumCollisionObjects(); + if (numObj) + { + btCollisionObject* obj = getDynamicsWorld()->getCollisionObjectArray()[numObj-1]; + + getDynamicsWorld()->removeCollisionObject(obj); + btRigidBody* body = btRigidBody::upcast(obj); + if (body && body->getMotionState()) + { + delete body->getMotionState(); + } + delete obj; + + + } + break; + } + case GLUT_KEY_LEFT : stepLeft(); break; + case GLUT_KEY_RIGHT : stepRight(); break; + case GLUT_KEY_UP : stepFront(); break; + case GLUT_KEY_DOWN : stepBack(); break; + case GLUT_KEY_PAGE_UP : zoomIn(); break; + case GLUT_KEY_PAGE_DOWN : zoomOut(); break; + case GLUT_KEY_HOME : toggleIdle(); break; + default: + // std::cout << "unused (special) key : " << key << std::endl; + break; + } + + glutPostRedisplay(); + +} + +void GlutDemoApplication::swapBuffers() +{ + glutSwapBuffers(); + +} + +#endif //_WINDOWS + + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/GlutDemoApplication.h b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GlutDemoApplication.h new file mode 100644 index 0000000..e2727a7 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GlutDemoApplication.h @@ -0,0 +1,34 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 GLUT_DEMO_APPLICATION_H +#define GLUT_DEMO_APPLICATION_H + +#include "DemoApplication.h" + +class GlutDemoApplication : public DemoApplication +{ +public: + + void specialKeyboard(int key, int x, int y); + + virtual void swapBuffers(); + + virtual void updateModifierKeys(); + +}; +#endif //GLUT_DEMO_APPLICATION_H + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/GlutStuff.cpp b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GlutStuff.cpp new file mode 100644 index 0000000..92872a1 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GlutStuff.cpp @@ -0,0 +1,119 @@ +/* +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 _WINDOWS + +#include "DemoApplication.h" + +//glut is C code, this global gDemoApplication links glut to the C++ demo +static DemoApplication* gDemoApplication = 0; + + +#include "GlutStuff.h" + +static void glutKeyboardCallback(unsigned char key, int x, int y) +{ + gDemoApplication->keyboardCallback(key,x,y); +} + +static void glutKeyboardUpCallback(unsigned char key, int x, int y) +{ + gDemoApplication->keyboardUpCallback(key,x,y); +} + +static void glutSpecialKeyboardCallback(int key, int x, int y) +{ + gDemoApplication->specialKeyboard(key,x,y); +} + +static void glutSpecialKeyboardUpCallback(int key, int x, int y) +{ + gDemoApplication->specialKeyboardUp(key,x,y); +} + + +static void glutReshapeCallback(int w, int h) +{ + gDemoApplication->reshape(w,h); +} + +static void glutMoveAndDisplayCallback() +{ + gDemoApplication->moveAndDisplay(); +} + +static void glutMouseFuncCallback(int button, int state, int x, int y) +{ + gDemoApplication->mouseFunc(button,state,x,y); +} + + +static void glutMotionFuncCallback(int x,int y) +{ + gDemoApplication->mouseMotionFunc(x,y); +} + + +static void glutDisplayCallback(void) +{ + gDemoApplication->displayCallback(); +} + + +int glutmain(int argc, char **argv,int width,int height,const char* title,DemoApplication* demoApp) { + + gDemoApplication = demoApp; + + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL); + glutInitWindowPosition(0, 0); + glutInitWindowSize(width, height); + glutCreateWindow(title); +#ifdef BT_USE_FREEGLUT + glutSetOption (GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS); +#endif + + gDemoApplication->myinit(); + + glutKeyboardFunc(glutKeyboardCallback); + glutKeyboardUpFunc(glutKeyboardUpCallback); + glutSpecialFunc(glutSpecialKeyboardCallback); + glutSpecialUpFunc(glutSpecialKeyboardUpCallback); + + glutReshapeFunc(glutReshapeCallback); + //createMenu(); + glutIdleFunc(glutMoveAndDisplayCallback); + glutMouseFunc(glutMouseFuncCallback); + glutPassiveMotionFunc(glutMotionFuncCallback); + glutMotionFunc(glutMotionFuncCallback); + glutDisplayFunc( glutDisplayCallback ); + + glutMoveAndDisplayCallback(); + +//enable vsync to avoid tearing on Apple (todo: for Windows) + +#if defined(__APPLE__) && !defined (VMDMESA) +int swap_interval = 1; +CGLContextObj cgl_context = CGLGetCurrentContext(); +CGLSetParameter(cgl_context, kCGLCPSwapInterval, &swap_interval); +#endif + + + + return 0; +} + + +#endif //_WINDOWS diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/GlutStuff.h b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GlutStuff.h new file mode 100644 index 0000000..5891e76 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/GlutStuff.h @@ -0,0 +1,86 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2012 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 GLUT_STUFF_H +#define GLUT_STUFF_H + +#ifdef _WIN32//for glut.h +#include +#endif + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#include +#else + + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif //_WINDOWS +#endif //APPLE + +#ifdef _WINDOWS +#define BT_ACTIVE_ALT VK_LMENU + +#else +#define BT_KEY_K 'k' +#define BT_KEY_LEFT GLUT_KEY_LEFT +#define BT_KEY_RIGHT GLUT_KEY_RIGHT +#define BT_KEY_UP GLUT_KEY_UP +#define BT_KEY_DOWN GLUT_KEY_DOWN +#define BT_KEY_F1 GLUT_KEY_F1 +#define BT_KEY_F2 GLUT_KEY_F2 +#define BT_KEY_F3 GLUT_KEY_F3 +#define BT_KEY_F4 GLUT_KEY_F4 +#define BT_KEY_F5 GLUT_KEY_F5 +#define BT_KEY_PAGEUP GLUT_KEY_PAGE_UP +#define BT_KEY_PAGEDOWN GLUT_KEY_PAGE_DOWN +#define BT_KEY_END GLUT_KEY_END +#define BT_KEY_HOME GLUT_KEY_HOME +#define BT_ACTIVE_ALT GLUT_ACTIVE_ALT +#define BT_ACTIVE_CTRL GLUT_ACTIVE_ALT +#define BT_ACTIVE_SHIFT GLUT_ACTIVE_SHIFT +#endif + +#if BT_USE_FREEGLUT +#include "GL/freeglut_ext.h" //to be able to return from glutMainLoop() +#endif + + + +class DemoApplication; + +int glutmain(int argc, char **argv,int width,int height,const char* title,DemoApplication* demoApp); + +#if defined(BT_USE_DOUBLE_PRECISION) +#define btglLoadMatrix glLoadMatrixd +#define btglMultMatrix glMultMatrixd +#define btglColor3 glColor3d +#define btglVertex3 glVertex3d +#else +#define btglLoadMatrix glLoadMatrixf +#define btglMultMatrix glMultMatrixf +#define btglColor3 glColor3f +#define btglVertex3 glVertex3d +#endif + +#endif //GLUT_STUFF_H diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/RenderTexture.cpp b/Extras/RigidBodyGpuPipeline/dynamics/testbed/RenderTexture.cpp new file mode 100644 index 0000000..2c8b88b --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/RenderTexture.cpp @@ -0,0 +1,86 @@ +/* +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 "RenderTexture.h" +#include + + +renderTexture::renderTexture(int width,int height) +:m_height(height),m_width(width) +{ + m_buffer = new unsigned char[m_width*m_height*4]; + + //clear screen + memset(m_buffer,0,m_width*m_height*4); + + //clear screen version 2 + for (int x=0;x>=1; + y++; + } + x++; + } + //xx+=16; + xx+=10; + } +} + +renderTexture::~renderTexture() +{ + delete [] m_buffer; +} + + + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/RenderTexture.h b/Extras/RigidBodyGpuPipeline/dynamics/testbed/RenderTexture.h new file mode 100644 index 0000000..1aee51d --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/RenderTexture.h @@ -0,0 +1,73 @@ +/* +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 RENDER_TEXTURE_H +#define RENDER_TEXTURE_H + +#include "LinearMath/btVector3.h" +#include "GLDebugFont.h" + +/// +///renderTexture provides a software-render context (setpixel/printf) +/// +class renderTexture +{ + int m_height; + int m_width; + unsigned char* m_buffer; + +public: + + renderTexture(int width,int height); + ~renderTexture(); + + ///rgba input is in range [0..1] for each component + inline void setPixel(int x,int y,const btVector4& rgba) + { + unsigned char* pixel = &m_buffer[ (x+y*m_width) * 4]; + + pixel[0] = (unsigned char)(255.*rgba.getX()); + pixel[1] = (unsigned char)(255.*rgba.getY()); + pixel[2] = (unsigned char)(255.*rgba.getZ()); + pixel[3] = (unsigned char)(255.*rgba.getW()); + } + + inline void addPixel(int x,int y,const btVector4& rgba) + { + unsigned char* pixel = &m_buffer[ (x+y*m_width) * 4]; + pixel[0] = (unsigned char)btMin(btScalar(255.f),((btScalar)pixel[0] + btScalar(255.f)*rgba.getX())); + pixel[1] = (unsigned char)btMin(btScalar(255.f),((btScalar)pixel[1] + btScalar(255.f)*rgba.getY())); + pixel[2] = (unsigned char)btMin(btScalar(255.f),((btScalar)pixel[2] + btScalar(255.f)*rgba.getZ())); +// pixel[3] = (unsigned char)btMin(btScalar(255.f),((btScalar)pixel[3] + btScalar(255.f)*rgba.getW())); + } + + inline btVector4 getPixel(int x,int y) + { + unsigned char* pixel = &m_buffer[ (x+y*m_width) * 4]; + return btVector4(pixel[0]*1.f/255.f, + pixel[1]*1.f/255.f, + pixel[2]*1.f/255.f, + pixel[3]*1.f/255.f); + } + + const unsigned char* getBuffer() const { return m_buffer;} + int getWidth() const { return m_width;} + int getHeight() const { return m_height;} + void grapicalPrintf(char* str, void* fontData, int startx = 0,int starty=0); + +}; + +#endif //RENDER_TEXTURE_H + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/Win32AppMain.cpp b/Extras/RigidBodyGpuPipeline/dynamics/testbed/Win32AppMain.cpp new file mode 100644 index 0000000..84f48a3 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/Win32AppMain.cpp @@ -0,0 +1,405 @@ +#ifdef _WINDOWS +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2010 Erwin Coumans http://bulletphysics.org + +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 +#include + + +#include "DemoApplication.h" + +#include "GLDebugDrawer.h" +#include "GLDebugFont.h" + +#include "BulletDynamics/Dynamics/btDynamicsWorld.h" + +/// This Win32AppMain is shared code between all demos. +/// The actual demo, derived from DemoApplication is created using 'createDemo', in a separate .cpp file +DemoApplication* gDemoApplication = 0; +DemoApplication* createDemo(); + + +// Function Declarations + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC); +void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC); +static bool sOpenGLInitialized = false; +static int sWidth = 0; +static int sHeight =0; +static int quitRequest = 0; + +// WinMain + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPSTR lpCmdLine, int iCmdShow) +{ + WNDCLASS wc; + HWND hWnd; + HDC hDC; + HGLRC hRC; + MSG msg; + BOOL quit = FALSE; + float theta = 0.0f; + + gDemoApplication = createDemo(); + + + // register window class + wc.style = CS_OWNDC; + wc.lpfnWndProc = WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); + wc.hCursor = LoadCursor( NULL, IDC_ARROW ); + wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ); + wc.lpszMenuName = NULL; + wc.lpszClassName = "BulletPhysics"; + RegisterClass( &wc ); + + // create main window + hWnd = CreateWindow( + "BulletPhysics", "Bullet Physics Sample. http://bulletphysics.org", + WS_CAPTION | WS_VISIBLE | WS_OVERLAPPEDWINDOW, +// 0, 0, 640, 480, + 0, 0, 1024, 768, + NULL, NULL, hInstance, NULL ); + + // enable OpenGL for the window + EnableOpenGL( hWnd, &hDC, &hRC ); + + + GLDebugDrawer debugDraw; + gDemoApplication->myinit(); + //gDemoApplication->reshape(1024, 768); + gDemoApplication->initPhysics(); + if (gDemoApplication->getDynamicsWorld()) + gDemoApplication->getDynamicsWorld()->setDebugDrawer(&debugDraw); + + gDemoApplication->reshape(sWidth,sHeight); + + // program main loop + while ( !quit ) + { + + // check for messages + if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) + { + + // handle or dispatch messages + if ( msg.message == WM_QUIT ) + { + quit = TRUE; + } + else + { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + +// gDemoApplication->displayCallback(); + + + }; + + // OpenGL animation code goes here + + glClearColor( .7f, 0.7f, 0.7f, 1.f ); + + gDemoApplication->moveAndDisplay(); + + + SwapBuffers( hDC ); + + theta += 1.0f; + + + } + + + + // shutdown OpenGL + DisableOpenGL( hWnd, hDC, hRC ); + + // destroy the window explicitly + DestroyWindow( hWnd ); + + delete gDemoApplication; + + return msg.wParam; + +} + +// Window Procedure + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + + + + switch (message) + { + + case WM_SYSKEYDOWN: + { + if (lParam & 1<<29) + { + gDemoApplication->m_modifierKeys = VK_LMENU; + } + break; + } + case WM_SYSKEYUP: + { + if (lParam & 1<<29) + { + gDemoApplication->m_modifierKeys = VK_LMENU; + } else + { + gDemoApplication->m_modifierKeys = 0; + } + + break; + } + + + case WM_SIZE: // Size Action Has Taken Place + + switch (wParam) // Evaluate Size Action + { + case SIZE_MINIMIZED: // Was Window Minimized? + return 0; // Return + + case SIZE_MAXIMIZED: // Was Window Maximized? + sWidth = LOWORD (lParam); + sHeight = HIWORD (lParam); + if (sOpenGLInitialized) + { + gDemoApplication->reshape(sWidth,sHeight); + } + return 0; // Return + + case SIZE_RESTORED: // Was Window Restored? + sWidth = LOWORD (lParam); + sHeight = HIWORD (lParam); + if (sOpenGLInitialized) + { + gDemoApplication->reshape(sWidth,sHeight); + } + return 0; // Return + } + break; + + case WM_CREATE: + return 0; + + case WM_MBUTTONUP: + { + int xPos = LOWORD(lParam); + int yPos = HIWORD(lParam); + gDemoApplication->mouseFunc(1,1,xPos,yPos); + break; + } + case WM_MBUTTONDOWN: + { + int xPos = LOWORD(lParam); + int yPos = HIWORD(lParam); + gDemoApplication->mouseFunc(1,0,xPos,yPos); + break; + } + + case WM_LBUTTONUP: + { + int xPos = LOWORD(lParam); + int yPos = HIWORD(lParam); + gDemoApplication->mouseFunc(0,1,xPos,yPos); + break; + } + case 0x020A://WM_MOUSEWHEEL: + { + + int zDelta = (short)HIWORD(wParam); + int xPos = LOWORD(lParam); + int yPos = HIWORD(lParam); + if (zDelta>0) + gDemoApplication->zoomIn(); + else + gDemoApplication->zoomOut(); + break; + } + + case WM_MOUSEMOVE: + { + int xPos = LOWORD(lParam); + int yPos = HIWORD(lParam); + gDemoApplication->mouseMotionFunc(xPos,yPos); + break; + } + case WM_RBUTTONUP: + { + int xPos = LOWORD(lParam); + int yPos = HIWORD(lParam); + gDemoApplication->mouseFunc(2,1,xPos,yPos); + break; + } + case WM_RBUTTONDOWN: + { + int xPos = LOWORD(lParam); + int yPos = HIWORD(lParam); + gDemoApplication->mouseFunc(2,0,xPos,yPos); + break; + } + case WM_LBUTTONDOWN: + { + int xPos = LOWORD(lParam); + int yPos = HIWORD(lParam); + gDemoApplication->mouseFunc(0,0,xPos,yPos); + break; + } +/*#define WM_LBUTTONUP 0x0202 +#define WM_LBUTTONDBLCLK 0x0203 +#define WM_RBUTTONDOWN 0x0204 +#define WM_RBUTTONUP 0x0205 +#define WM_RBUTTONDBLCLK 0x0206 +#define WM_MBUTTONDOWN 0x0207 +#define WM_MBUTTONUP 0x0208 +#define WM_MBUTTONDBLCLK 0x0209 +*/ + + + + case WM_CLOSE: + PostQuitMessage( 0 ); + return 0; + + case WM_DESTROY: + return 0; + + case WM_KEYUP: + switch ( wParam ) + { + + case VK_PRIOR: + case VK_NEXT: + case VK_END: + case VK_HOME: + case VK_LEFT: + case VK_UP: + case VK_RIGHT: + case VK_DOWN: + { + if (gDemoApplication) + gDemoApplication->specialKeyboardUp(wParam,0,0); + return 0; + } + default: + { + gDemoApplication->keyboardUpCallback(tolower(wParam),0,0); + } + return DefWindowProc( hWnd, message, wParam, lParam ); + } + + case WM_KEYDOWN: + printf("bla\n"); + switch ( wParam ) + { + case VK_CONTROL: + case VK_PRIOR: + case VK_NEXT: + case VK_END: + case VK_HOME: + case VK_LEFT: + case VK_UP: + case VK_RIGHT: + case VK_DOWN: + { + if (gDemoApplication) + gDemoApplication->specialKeyboard(wParam,0,0); + break; + } + + case ' ': + { + if (gDemoApplication) + gDemoApplication->clientResetScene(); + break; + } + case 'Q': + case VK_ESCAPE: + { + quitRequest = 1; + PostQuitMessage(0); + } + return 0; + + } + return 0; + + case WM_CHAR: + if (!quitRequest) + gDemoApplication->keyboardCallback(wParam,0,0); + break; + + default: + return DefWindowProc( hWnd, message, wParam, lParam ); + + } + return 0; +} + +// Enable OpenGL + +void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC) +{ + PIXELFORMATDESCRIPTOR pfd; + int format; + + // get the device context (DC) + *hDC = GetDC( hWnd ); + + // set the pixel format for the DC + ZeroMemory( &pfd, sizeof( pfd ) ); + pfd.nSize = sizeof( pfd ); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 24; + pfd.cDepthBits = 16; + pfd.cStencilBits = 1; + pfd.iLayerType = PFD_MAIN_PLANE; + format = ChoosePixelFormat( *hDC, &pfd ); + SetPixelFormat( *hDC, format, &pfd ); + + // create and enable the render context (RC) + *hRC = wglCreateContext( *hDC ); + wglMakeCurrent( *hDC, *hRC ); + sOpenGLInitialized = true; + + +} + +// Disable OpenGL + +void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC) +{ + sOpenGLInitialized = false; + + wglMakeCurrent( NULL, NULL ); + wglDeleteContext( hRC ); + ReleaseDC( hWnd, hDC ); +} + +#endif //_WINDOWS diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/Win32DemoApplication.cpp b/Extras/RigidBodyGpuPipeline/dynamics/testbed/Win32DemoApplication.cpp new file mode 100644 index 0000000..f959cbf --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/Win32DemoApplication.cpp @@ -0,0 +1,79 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +#ifdef _WINDOWS + +#include "Win32DemoApplication.h" + + + + +#if 0 +void Win32DemoApplication::renderme() +{ +} +void Win32DemoApplication::setTexturing(bool useTexture) +{ +} + +void Win32DemoApplication::setShadows(bool useShadows) +{ +} + +void Win32DemoApplication::setCameraDistance(float camDist) +{ +} +void Win32DemoApplication::clientResetScene() +{ + +} +#endif + +void Win32DemoApplication::updateModifierKeys() +{ + //not yet +} + + + +void Win32DemoApplication::specialKeyboard(int key, int x, int y) +{ + (void)x; + (void)y; + + switch (key) + { + case VK_LEFT : stepLeft(); break; + case VK_RIGHT : stepRight(); break; + case VK_UP : stepFront(); break; + case VK_DOWN : stepBack(); break; + +// case GLUT_KEY_PAGE_UP : zoomIn(); break; +// case GLUT_KEY_PAGE_DOWN : zoomOut(); break; +// case GLUT_KEY_HOME : toggleIdle(); break; + + default: + // std::cout << "unused (special) key : " << key << std::endl; + break; + } + +} + +void Win32DemoApplication::swapBuffers() +{ +} + +#endif + diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/Win32DemoApplication.h b/Extras/RigidBodyGpuPipeline/dynamics/testbed/Win32DemoApplication.h new file mode 100644 index 0000000..0c2a1ee --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/Win32DemoApplication.h @@ -0,0 +1,40 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 WIN32_DEMO_APPLICATION_H +#define WIN32_DEMO_APPLICATION_H + + +#include "DemoApplication.h" + +class Win32DemoApplication : public DemoApplication +{ +protected: + + +public: + + + virtual void swapBuffers(); + + void specialKeyboard(int key, int x, int y); + + virtual void updateModifierKeys(); + + +}; + +#endif //WIN32_DEMO_APPLICATION_H \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/dynamics/testbed/premake4.lua b/Extras/RigidBodyGpuPipeline/dynamics/testbed/premake4.lua new file mode 100644 index 0000000..576aa0f --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/dynamics/testbed/premake4.lua @@ -0,0 +1,18 @@ + project "testbed" + + kind "StaticLib" + targetdir "../../build/lib" + includedirs { + ".", + "../../bullet2" + } + configuration {"Windows"} + includedirs { + "../../rendering/GlutGlewWindows" + } + configuration{} + + files { + "**.cpp", + "**.h" + } diff --git a/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/AMD/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/AMD/premake4.lua new file mode 100644 index 0000000..2ae27f6 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/AMD/premake4.lua @@ -0,0 +1,29 @@ + + hasCL = findOpenCL_AMD() + + if (hasCL) then + + project "OpenCL_bt3dGridBroadphase_AMD" + + initOpenCL_AMD() + + language "C++" + + kind "StaticLib" + targetdir "../../../bin" + + libdirs {"../../../rendering/GlutGlewWindows"} + + includedirs { +-- "../../../rendering/GlutGlewWindows", + "../../../opencl/3dGridBroadphase/Shared", + "../../../../../src", + "../../primitives" + } + + files { + "../Shared/*.cpp", + "../Shared/*.h" + } + + end \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/MiniCL/MiniCLTaskWrap.cpp b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/MiniCL/MiniCLTaskWrap.cpp new file mode 100644 index 0000000..1398190 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/MiniCL/MiniCLTaskWrap.cpp @@ -0,0 +1,23 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +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 + +extern "C" +{ + #define MSTRINGIFY(A) A + #include "bt3dGridBroadphaseOCL.cl" + #undef MSTRINGIFY +} diff --git a/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.cl b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.cl new file mode 100644 index 0000000..f66b6e2 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.cl @@ -0,0 +1,349 @@ + +MSTRINGIFY( + +int getPosHash(int4 gridPos, __global float4* pParams) +{ + int4 gridDim = *((__global int4*)(pParams + 1)); + gridPos.x &= gridDim.x - 1; + gridPos.y &= gridDim.y - 1; + gridPos.z &= gridDim.z - 1; + int hash = gridPos.z * gridDim.y * gridDim.x + gridPos.y * gridDim.x + gridPos.x; + return hash; +} + +int4 getGridPos(float4 worldPos, __global float4* pParams) +{ + int4 gridPos; + int4 gridDim = *((__global int4*)(pParams + 1)); + gridPos.x = (int)floor(worldPos.x * pParams[0].x) & (gridDim.x - 1); + gridPos.y = (int)floor(worldPos.y * pParams[0].y) & (gridDim.y - 1); + gridPos.z = (int)floor(worldPos.z * pParams[0].z) & (gridDim.z - 1); + return gridPos; +} + + +// calculate grid hash value for each body using its AABB +__kernel void kCalcHashAABB(int numObjects, __global float4* pAABB, __global int2* pHash, __global float4* pParams GUID_ARG) +{ + int index = get_global_id(0); + if(index >= numObjects) + { + return; + } + float4 bbMin = pAABB[index*2]; + float4 bbMax = pAABB[index*2 + 1]; + float4 pos; + pos.x = (bbMin.x + bbMax.x) * 0.5f; + pos.y = (bbMin.y + bbMax.y) * 0.5f; + pos.z = (bbMin.z + bbMax.z) * 0.5f; + pos.w = 0.f; + // get address in grid + int4 gridPos = getGridPos(pos, pParams); + int gridHash = getPosHash(gridPos, pParams); + // store grid hash and body index + int2 hashVal; + hashVal.x = gridHash; + hashVal.y = index; + pHash[index] = hashVal; +} + +__kernel void kClearCellStart( int numCells, + __global int* pCellStart GUID_ARG) +{ + int index = get_global_id(0); + if(index >= numCells) + { + return; + } + pCellStart[index] = -1; +} + +__kernel void kFindCellStart(int numObjects, __global int2* pHash, __global int* cellStart GUID_ARG) +{ + __local int sharedHash[513]; + int index = get_global_id(0); + int2 sortedData; + if(index < numObjects) + { + sortedData = pHash[index]; + // Load hash data into shared memory so that we can look + // at neighboring body's hash value without loading + // two hash values per thread + sharedHash[get_local_id(0) + 1] = sortedData.x; + if((index > 0) && (get_local_id(0) == 0)) + { + // first thread in block must load neighbor body hash + sharedHash[0] = pHash[index-1].x; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + if(index < numObjects) + { + if((index == 0) || (sortedData.x != sharedHash[get_local_id(0)])) + { + cellStart[sortedData.x] = index; + } + } +} + +int testAABBOverlap(float4 min0, float4 max0, float4 min1, float4 max1) +{ + return (min0.x <= max1.x)&& (min1.x <= max0.x) && + (min0.y <= max1.y)&& (min1.y <= max0.y) && + (min0.z <= max1.z)&& (min1.z <= max0.z); +} + + + + + +void findPairsInCell( int numObjects, + int4 gridPos, + int index, + __global int2* pHash, + __global int* pCellStart, + __global float4* pAABB, + __global int* pPairBuff, + __global int2* pPairBuffStartCurr, + __global float4* pParams) +{ + int4 pGridDim = *((__global int4*)(pParams + 1)); + int maxBodiesPerCell = pGridDim.w; + int gridHash = getPosHash(gridPos, pParams); + // get start of bucket for this cell + int bucketStart = pCellStart[gridHash]; + if (bucketStart == -1) + { + return; // cell empty + } + // iterate over bodies in this cell + int2 sortedData = pHash[index]; + int unsorted_indx = sortedData.y; + float4 min0 = pAABB[unsorted_indx*2 + 0]; + float4 max0 = pAABB[unsorted_indx*2 + 1]; + int handleIndex = as_int(min0.w); + int2 start_curr = pPairBuffStartCurr[handleIndex]; + int start = start_curr.x; + int curr = start_curr.y; + int2 start_curr_next = pPairBuffStartCurr[handleIndex+1]; + int curr_max = start_curr_next.x - start - 1; + int bucketEnd = bucketStart + maxBodiesPerCell; + bucketEnd = (bucketEnd > numObjects) ? numObjects : bucketEnd; + for(int index2 = bucketStart; index2 < bucketEnd; index2++) + { + int2 cellData = pHash[index2]; + if (cellData.x != gridHash) + { + break; // no longer in same bucket + } + int unsorted_indx2 = cellData.y; + if (unsorted_indx2 < unsorted_indx) // check not colliding with self + { + float4 min1 = pAABB[unsorted_indx2*2 + 0]; + float4 max1 = pAABB[unsorted_indx2*2 + 1]; + if(testAABBOverlap(min0, max0, min1, max1)) + { + int handleIndex2 = as_int(min1.w); + int k; + for(k = 0; k < curr; k++) + { + int old_pair = pPairBuff[start+k] & (~0x60000000); + if(old_pair == handleIndex2) + { + pPairBuff[start+k] |= 0x40000000; + break; + } + } + if(k == curr) + { + if(curr >= curr_max) + { // not a good solution, but let's avoid crash + break; + } + pPairBuff[start+curr] = handleIndex2 | 0x20000000; + curr++; + } + } + } + } + int2 newStartCurr; + newStartCurr.x = start; + newStartCurr.y = curr; + pPairBuffStartCurr[handleIndex] = newStartCurr; + return; +} + +__kernel void kFindOverlappingPairs( int numObjects, + __global float4* pAABB, + __global int2* pHash, + __global int* pCellStart, + __global int* pPairBuff, + __global int2* pPairBuffStartCurr, + __global float4* pParams GUID_ARG) + +{ + int index = get_global_id(0); + if(index >= numObjects) + { + return; + } + int2 sortedData = pHash[index]; + int unsorted_indx = sortedData.y; + float4 bbMin = pAABB[unsorted_indx*2 + 0]; + float4 bbMax = pAABB[unsorted_indx*2 + 1]; + float4 pos; + pos.x = (bbMin.x + bbMax.x) * 0.5f; + pos.y = (bbMin.y + bbMax.y) * 0.5f; + pos.z = (bbMin.z + bbMax.z) * 0.5f; + // get address in grid + int4 gridPosA = getGridPos(pos, pParams); + int4 gridPosB; + // examine only neighbouring cells + for(int z=-1; z<=1; z++) + { + gridPosB.z = gridPosA.z + z; + for(int y=-1; y<=1; y++) + { + gridPosB.y = gridPosA.y + y; + for(int x=-1; x<=1; x++) + { + gridPosB.x = gridPosA.x + x; + findPairsInCell(numObjects, gridPosB, index, pHash, pCellStart, pAABB, pPairBuff, pPairBuffStartCurr, pParams); + } + } + } +} + + +__kernel void kFindPairsLarge( int numObjects, + __global float4* pAABB, + __global int2* pHash, + __global int* pCellStart, + __global int* pPairBuff, + __global int2* pPairBuffStartCurr, + uint numLarge GUID_ARG) +{ + int index = get_global_id(0); + if(index >= numObjects) + { + return; + } + int2 sortedData = pHash[index]; + int unsorted_indx = sortedData.y; + float4 min0 = pAABB[unsorted_indx*2 + 0]; + float4 max0 = pAABB[unsorted_indx*2 + 1]; + int handleIndex = as_int(min0.w); + int2 start_curr = pPairBuffStartCurr[handleIndex]; + int start = start_curr.x; + int curr = start_curr.y; + int2 start_curr_next = pPairBuffStartCurr[handleIndex+1]; + int curr_max = start_curr_next.x - start - 1; + for(uint i = 0; i < numLarge; i++) + { + int indx2 = numObjects + i; + float4 min1 = pAABB[indx2*2 + 0]; + float4 max1 = pAABB[indx2*2 + 1]; + if(testAABBOverlap(min0, max0, min1, max1)) + { + int k; + int handleIndex2 = as_int(min1.w); + for(k = 0; k < curr; k++) + { + int old_pair = pPairBuff[start+k] & (~0x60000000); + if(old_pair == handleIndex2) + { + pPairBuff[start+k] |= 0x40000000; + break; + } + } + if(k == curr) + { + pPairBuff[start+curr] = handleIndex2 | 0x20000000; + if(curr >= curr_max) + { // not a good solution, but let's avoid crash + break; + } + curr++; + } + } + } + int2 newStartCurr; + newStartCurr.x = start; + newStartCurr.y = curr; + pPairBuffStartCurr[handleIndex] = newStartCurr; + return; +} + +__kernel void kComputePairCacheChanges( int numObjects, + __global int* pPairBuff, + __global int2* pPairBuffStartCurr, + __global int* pPairScan, + __global float4* pAABB GUID_ARG) +{ + int index = get_global_id(0); + if(index >= numObjects) + { + return; + } + float4 bbMin = pAABB[index * 2]; + int handleIndex = as_int(bbMin.w); + int2 start_curr = pPairBuffStartCurr[handleIndex]; + int start = start_curr.x; + int curr = start_curr.y; + __global int *pInp = pPairBuff + start; + int num_changes = 0; + for(int k = 0; k < curr; k++, pInp++) + { + if(!((*pInp) & 0x40000000)) + { + num_changes++; + } + } + pPairScan[index+1] = num_changes; +} + +__kernel void kSqueezeOverlappingPairBuff( int numObjects, + __global int* pPairBuff, + __global int2* pPairBuffStartCurr, + __global int* pPairScan, + __global int* pPairOut, + __global float4* pAABB GUID_ARG) +{ + int index = get_global_id(0); + if(index >= numObjects) + { + return; + } + float4 bbMin = pAABB[index * 2]; + int handleIndex = as_int(bbMin.w); + int2 start_curr = pPairBuffStartCurr[handleIndex]; + int start = start_curr.x; + int curr = start_curr.y; + __global int* pInp = pPairBuff + start; + __global int* pOut = pPairOut + pPairScan[index+1]; + __global int* pOut2 = pInp; + int num = 0; + for(int k = 0; k < curr; k++, pInp++) + { + if(!((*pInp) & 0x40000000)) + { + *pOut = *pInp; + pOut++; + } + if((*pInp) & 0x60000000) + { + *pOut2 = (*pInp) & (~0x60000000); + pOut2++; + num++; + } + } + int2 newStartCurr; + newStartCurr.x = start; + newStartCurr.y = num; + pPairBuffStartCurr[handleIndex] = newStartCurr; +} + + + + +); \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.cpp b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.cpp new file mode 100644 index 0000000..7229b8e --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.cpp @@ -0,0 +1,697 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006 - 2009 Sony Computer Entertainment Inc. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btQuickprof.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "../basic_initialize/btOpenCLUtils.h" + +#include "bt3dGridBroadphaseOCL.h" + +#include +#include +#include "Adl/Adl.h" +#include +#include +#include + +#define ADD_BLOCKING_CL_FINISH_FOR_BENCHMARK + +#define GRID_OCL_PATH "..\\..\\opencl\\3dGridBroadphase\\Shared\\bt3dGridBroadphaseOCL.cl" + + +#define MSTRINGIFY(A) #A + +static const char* spProgramSource = +#include "bt3dGridBroadphaseOCL.cl" + +adl::PrefixScan::Data* gData1=0; +adl::Buffer* m_srcClBuffer=0; + +struct MySortData +{ + int key; + int value; +}; + +adl::RadixSort32::Data* dataC = 0; +adl::RadixSort::Data* dataHost = 0; + + +static unsigned int infElem = 0x2fffffff; + +static unsigned int zeroEl = 0; +static unsigned int minusOne= -1; + + +bt3dGridBroadphaseOCL::bt3dGridBroadphaseOCL( btOverlappingPairCache* overlappingPairCache, + const btVector3& cellSize, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerSmallProxy, + btScalar maxSmallProxySize, + int maxSmallProxiesPerCell, + cl_context context, cl_device_id device, cl_command_queue queue, + adl::DeviceCL* deviceCL + ) : + btGpu3DGridBroadphase(overlappingPairCache, cellSize, gridSizeX, gridSizeY, gridSizeZ, maxSmallProxies, maxLargeProxies, maxPairsPerSmallProxy, maxSmallProxySize, maxSmallProxiesPerCell) +{ + + + initCL(context, device, queue); + allocateBuffers(); + + prefillBuffers(); + + initKernels(); + + //create an Adl device host and OpenCL device + + adl::DeviceUtils::Config cfg; + m_deviceHost = adl::DeviceUtils::allocate( adl::TYPE_HOST, cfg ); + m_ownsDevice = false; + if (!deviceCL) + { + m_ownsDevice = true; + deviceCL = new adl::DeviceCL; + deviceCL->m_context = context; + deviceCL->m_deviceIdx = device; + deviceCL->m_commandQueue = queue; + deviceCL->m_kernelManager = new adl::KernelManager; + } + + m_deviceCL = deviceCL; + + int minSize = 256*1024; + int maxSortBuffer = maxSmallProxies < minSize ? minSize :maxSmallProxies; + + m_srcClBuffer = new adl::Buffer (m_deviceCL,maxSmallProxies+2); + m_srcClBuffer->write(&zeroEl,1,0); + + //m_srcClBuffer->write(&infElem,maxSmallProxies,0); + m_srcClBuffer->write(&infElem,1,maxSmallProxies); + m_srcClBuffer->write(&zeroEl,1,maxSmallProxies+1); + m_deviceCL->waitForCompletion(); + + gData1 = adl::PrefixScan::allocate( m_deviceCL, maxSortBuffer+2,adl::PrefixScanBase::EXCLUSIVE ); + dataHost = adl::RadixSort::allocate( m_deviceHost, maxSmallProxies+2 ); + dataC = adl::RadixSort32::allocate( m_deviceCL, maxSortBuffer+2 ); + +} + + + +bt3dGridBroadphaseOCL::~bt3dGridBroadphaseOCL() +{ + //btSimpleBroadphase will free memory of btSortedOverlappingPairCache, because m_ownsPairCache + assert(m_bInitialized); + adl::RadixSort::deallocate(dataHost); + adl::PrefixScan::deallocate(gData1); + adl::RadixSort32::deallocate(dataC); + adl::DeviceUtils::deallocate(m_deviceHost); + delete m_srcClBuffer; + if (m_ownsDevice) + { + delete m_deviceCL->m_kernelManager; + delete m_deviceCL; + } +} + +#ifdef CL_PLATFORM_MINI_CL +// there is a problem with MSVC9 : static constructors are not called if variables defined in library and are not used +// looks like it is because of optimization +// probably this will happen with other compilers as well +// so to make it robust, register kernels again (it is safe) +#define MINICL_DECLARE(a) extern "C" void a(); +MINICL_DECLARE(kCalcHashAABB) +MINICL_DECLARE(kClearCellStart) +MINICL_DECLARE(kFindCellStart) +MINICL_DECLARE(kFindOverlappingPairs) +MINICL_DECLARE(kFindPairsLarge) +MINICL_DECLARE(kComputePairCacheChanges) +MINICL_DECLARE(kSqueezeOverlappingPairBuff) +#undef MINICL_DECLARE +#endif + +void bt3dGridBroadphaseOCL::initCL(cl_context context, cl_device_id device, cl_command_queue queue) +{ + + #ifdef CL_PLATFORM_MINI_CL + // call constructors here + MINICL_REGISTER(kCalcHashAABB) + MINICL_REGISTER(kClearCellStart) + MINICL_REGISTER(kFindCellStart) + MINICL_REGISTER(kFindOverlappingPairs) + MINICL_REGISTER(kFindPairsLarge) + MINICL_REGISTER(kComputePairCacheChanges) + MINICL_REGISTER(kSqueezeOverlappingPairBuff) + #endif + + cl_int ciErrNum; + + btAssert(context); + m_cxMainContext = context; + btAssert(device); + m_cdDevice = device; + btAssert(queue); + m_cqCommandQue = queue; + + //adl::Kernel kern = m_deviceCL->getKernel(fileName,funcName,options,src); + + m_cpProgram = btOpenCLUtils::compileCLProgramFromString(m_cxMainContext,m_cdDevice,spProgramSource, &ciErrNum,"-DGUID_ARG=""""",GRID_OCL_PATH); + + printf("OK\n"); +} + + +void bt3dGridBroadphaseOCL::initKernels() +{ + initKernel(GRID3DOCL_KERNEL_CALC_HASH_AABB, "kCalcHashAABB"); + setKernelArg(GRID3DOCL_KERNEL_CALC_HASH_AABB, 1, sizeof(cl_mem),(void*)&m_dAABB); + setKernelArg(GRID3DOCL_KERNEL_CALC_HASH_AABB, 2, sizeof(cl_mem),(void*)&m_dBodiesHash); + setKernelArg(GRID3DOCL_KERNEL_CALC_HASH_AABB, 3, sizeof(cl_mem),(void*)&m_dBpParams); + + initKernel(GRID3DOCL_KERNEL_CLEAR_CELL_START, "kClearCellStart"); + setKernelArg(GRID3DOCL_KERNEL_CLEAR_CELL_START, 1, sizeof(cl_mem),(void*)&m_dCellStart); + + initKernel(GRID3DOCL_KERNEL_FIND_CELL_START, "kFindCellStart"); + setKernelArg(GRID3DOCL_KERNEL_FIND_CELL_START, 1, sizeof(cl_mem),(void*)&m_dBodiesHash); + setKernelArg(GRID3DOCL_KERNEL_FIND_CELL_START, 2, sizeof(cl_mem),(void*)&m_dCellStart); + + initKernel(GRID3DOCL_KERNEL_FIND_OVERLAPPING_PAIRS, "kFindOverlappingPairs"); + setKernelArg(GRID3DOCL_KERNEL_FIND_OVERLAPPING_PAIRS, 1, sizeof(cl_mem),(void*)&m_dAABB); + setKernelArg(GRID3DOCL_KERNEL_FIND_OVERLAPPING_PAIRS, 2, sizeof(cl_mem),(void*)&m_dBodiesHash); + setKernelArg(GRID3DOCL_KERNEL_FIND_OVERLAPPING_PAIRS, 3, sizeof(cl_mem),(void*)&m_dCellStart); + setKernelArg(GRID3DOCL_KERNEL_FIND_OVERLAPPING_PAIRS, 4, sizeof(cl_mem),(void*)&m_dPairBuff); + setKernelArg(GRID3DOCL_KERNEL_FIND_OVERLAPPING_PAIRS, 5, sizeof(cl_mem),(void*)&m_dPairBuffStartCurr); + setKernelArg(GRID3DOCL_KERNEL_FIND_OVERLAPPING_PAIRS, 6, sizeof(cl_mem),(void*)&m_dBpParams); + + initKernel(GRID3DOCL_KERNEL_FIND_PAIRS_LARGE, "kFindPairsLarge"); + setKernelArg(GRID3DOCL_KERNEL_FIND_PAIRS_LARGE, 1, sizeof(cl_mem),(void*)&m_dAABB); + setKernelArg(GRID3DOCL_KERNEL_FIND_PAIRS_LARGE, 2, sizeof(cl_mem),(void*)&m_dBodiesHash); + setKernelArg(GRID3DOCL_KERNEL_FIND_PAIRS_LARGE, 3, sizeof(cl_mem),(void*)&m_dCellStart); + setKernelArg(GRID3DOCL_KERNEL_FIND_PAIRS_LARGE, 4, sizeof(cl_mem),(void*)&m_dPairBuff); + setKernelArg(GRID3DOCL_KERNEL_FIND_PAIRS_LARGE, 5, sizeof(cl_mem),(void*)&m_dPairBuffStartCurr); + + initKernel(GRID3DOCL_KERNEL_COMPUTE_CACHE_CHANGES, "kComputePairCacheChanges"); + setKernelArg(GRID3DOCL_KERNEL_COMPUTE_CACHE_CHANGES, 1, sizeof(cl_mem),(void*)&m_dPairBuff); + setKernelArg(GRID3DOCL_KERNEL_COMPUTE_CACHE_CHANGES, 2, sizeof(cl_mem),(void*)&m_dPairBuffStartCurr); + setKernelArg(GRID3DOCL_KERNEL_COMPUTE_CACHE_CHANGES, 3, sizeof(cl_mem),(void*)&m_dPairScanChanged); + setKernelArg(GRID3DOCL_KERNEL_COMPUTE_CACHE_CHANGES, 4, sizeof(cl_mem),(void*)&m_dAABB); + + initKernel(GRID3DOCL_KERNEL_SQUEEZE_PAIR_BUFF, "kSqueezeOverlappingPairBuff"); + setKernelArg(GRID3DOCL_KERNEL_SQUEEZE_PAIR_BUFF, 1, sizeof(cl_mem),(void*)&m_dPairBuff); + setKernelArg(GRID3DOCL_KERNEL_SQUEEZE_PAIR_BUFF, 2, sizeof(cl_mem),(void*)&m_dPairBuffStartCurr); + setKernelArg(GRID3DOCL_KERNEL_SQUEEZE_PAIR_BUFF, 3, sizeof(cl_mem),(void*)&m_dPairScanChanged); + setKernelArg(GRID3DOCL_KERNEL_SQUEEZE_PAIR_BUFF, 4, sizeof(cl_mem),(void*)&m_dPairsChanged); + setKernelArg(GRID3DOCL_KERNEL_SQUEEZE_PAIR_BUFF, 5, sizeof(cl_mem),(void*)&m_dAABB); + +} + + +void bt3dGridBroadphaseOCL::allocateBuffers() +{ + cl_int ciErrNum; + unsigned int memSize; + // current version of bitonic sort works for power of 2 arrays only, so ... + m_hashSize = 1; + for(int bit = 1; bit < 32; bit++) + { + if(m_hashSize >= m_maxHandles) + { + break; + } + m_hashSize <<= 1; + } + memSize = m_hashSize * 2 * sizeof(unsigned int); + if (memSize < 1024*1024) + memSize = 1024*1024; + + m_dBodiesHash = clCreateBuffer(m_cxMainContext, CL_MEM_READ_WRITE, memSize, NULL, &ciErrNum); + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); + + memSize = m_numCells * sizeof(unsigned int); + m_dCellStart = clCreateBuffer(m_cxMainContext, CL_MEM_READ_WRITE, memSize, NULL, &ciErrNum); + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); + + memSize = m_maxHandles * m_maxPairsPerBody * sizeof(unsigned int); + m_dPairBuff = clCreateBuffer(m_cxMainContext, CL_MEM_READ_WRITE, memSize, NULL, &ciErrNum); + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); + + memSize = (m_maxHandles * 2 + 1) * sizeof(unsigned int); + m_dPairBuffStartCurr = clCreateBuffer(m_cxMainContext, CL_MEM_READ_WRITE, memSize, NULL, &ciErrNum); + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); + + unsigned int numAABB = m_maxHandles + m_maxLargeHandles; + memSize = numAABB * sizeof(float) * 4 * 2; + m_dAABB = clCreateBuffer(m_cxMainContext, CL_MEM_READ_WRITE, memSize, NULL, &ciErrNum); + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); + + memSize = (m_maxHandles + 2) * sizeof(unsigned int); + m_dPairScanChanged = clCreateBuffer(m_cxMainContext, CL_MEM_READ_WRITE, memSize, NULL, &ciErrNum); + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); + + memSize = m_maxHandles * m_maxPairsPerBody * sizeof(unsigned int); + m_dPairsChanged = clCreateBuffer(m_cxMainContext, CL_MEM_READ_WRITE, memSize, NULL, &ciErrNum); + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); + + m_dPairsContiguous = clCreateBuffer(m_cxMainContext, CL_MEM_READ_WRITE, memSize, NULL, &ciErrNum); + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); + + memSize = 3 * 4 * sizeof(float); + m_dBpParams = clCreateBuffer(m_cxMainContext, CL_MEM_READ_WRITE, memSize, NULL, &ciErrNum); + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); +} + +void bt3dGridBroadphaseOCL::prefillBuffers() +{ + memset(m_hBodiesHash, 0xFF, m_maxHandles*2*sizeof(unsigned int)); + copyArrayToDevice(m_dBodiesHash, m_hBodiesHash, m_maxHandles * 2 * sizeof(unsigned int)); + // now fill the rest (bitonic sorting works with size == pow of 2) + int remainder = m_hashSize - m_maxHandles; + if(remainder) + { + copyArrayToDevice(m_dBodiesHash, m_hBodiesHash, remainder * 2 * sizeof(unsigned int), m_maxHandles * 2 * sizeof(unsigned int), 0); + } + copyArrayToDevice(m_dPairBuffStartCurr, m_hPairBuffStartCurr, (m_maxHandles * 2 + 1) * sizeof(unsigned int)); + memset(m_hPairBuff, 0x00, m_maxHandles * m_maxPairsPerBody * sizeof(unsigned int)); + copyArrayToDevice(m_dPairBuff, m_hPairBuff, m_maxHandles * m_maxPairsPerBody * sizeof(unsigned int)); +} + + +void bt3dGridBroadphaseOCL::initKernel(int kernelId, char* pName) +{ + + cl_int ciErrNum; + cl_kernel kernel = clCreateKernel(m_cpProgram, pName, &ciErrNum); + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); + size_t wgSize; + ciErrNum = clGetKernelWorkGroupInfo(kernel, m_cdDevice, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &wgSize, NULL); + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); + m_kernels[kernelId].m_Id = kernelId; + m_kernels[kernelId].m_kernel = kernel; + m_kernels[kernelId].m_name = pName; + m_kernels[kernelId].m_workgroupSize = (int)wgSize; + return; +} + +void bt3dGridBroadphaseOCL::runKernelWithWorkgroupSize(int kernelId, int globalSize) +{ + if(globalSize <= 0) + { + return; + } + cl_kernel kernelFunc = m_kernels[kernelId].m_kernel; + cl_int ciErrNum = clSetKernelArg(kernelFunc, 0, sizeof(int), (void*)&globalSize); + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); + int workgroupSize = btMin(64,m_kernels[kernelId].m_workgroupSize); + + if(workgroupSize <= 0) + { // let OpenCL library calculate workgroup size + size_t globalWorkSize[2]; + globalWorkSize[0] = globalSize; + globalWorkSize[1] = 1; + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, kernelFunc, 1, NULL, globalWorkSize, NULL, 0,0,0 ); + } + else + { + size_t localWorkSize[2], globalWorkSize[2]; + //workgroupSize = btMin(workgroupSize, globalSize); + int num_t = globalSize / workgroupSize; + int num_g = num_t * workgroupSize; + if(num_g < globalSize) + { + num_t++; + } + localWorkSize[0] = workgroupSize; + globalWorkSize[0] = num_t * workgroupSize; + localWorkSize[1] = 1; + globalWorkSize[1] = 1; + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, kernelFunc, 1, NULL, globalWorkSize, localWorkSize, 0,0,0 ); + } + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); + ciErrNum = clFlush(m_cqCommandQue); + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); +} + + +void bt3dGridBroadphaseOCL::setKernelArg(int kernelId, int argNum, int argSize, void* argPtr) +{ + cl_int ciErrNum; + ciErrNum = clSetKernelArg(m_kernels[kernelId].m_kernel, argNum, argSize, argPtr); + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); +} + + +void bt3dGridBroadphaseOCL::copyArrayToDevice(cl_mem device, const void* host, unsigned int size, int devOffs, int hostOffs) +{ + if (size) + { + cl_int ciErrNum; + char* pHost = (char*)host + hostOffs; + ciErrNum = clEnqueueWriteBuffer(m_cqCommandQue, device, CL_TRUE, devOffs, size, pHost, 0, NULL, NULL); + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); + } +} + +void bt3dGridBroadphaseOCL::copyArrayFromDevice(void* host, const cl_mem device, unsigned int size, int hostOffs, int devOffs) +{ + if (size) + { + cl_int ciErrNum; + char* pHost = (char*)host + hostOffs; + ciErrNum = clEnqueueReadBuffer(m_cqCommandQue, device, CL_TRUE, devOffs, size, pHost, 0, NULL, NULL); + GRID3DOCL_CHECKERROR(ciErrNum, CL_SUCCESS); + } +} + + + +// +// overrides +// + + +void bt3dGridBroadphaseOCL::prepareAABB() +{ + btGpu3DGridBroadphase::prepareAABB(); + copyArrayToDevice(m_dAABB, m_hAABB, sizeof(bt3DGrid3F1U) * 2 * (m_numHandles + m_numLargeHandles)); + return; +} + +void bt3dGridBroadphaseOCL::setParameters(bt3DGridBroadphaseParams* hostParams) +{ + btGpu3DGridBroadphase::setParameters(hostParams); + struct btParamsBpOCL + { + float m_invCellSize[4]; + int m_gridSize[4]; + }; + btParamsBpOCL hParams; + hParams.m_invCellSize[0] = m_params.m_invCellSizeX; + hParams.m_invCellSize[1] = m_params.m_invCellSizeY; + hParams.m_invCellSize[2] = m_params.m_invCellSizeZ; + hParams.m_invCellSize[3] = 0.f; + hParams.m_gridSize[0] = m_params.m_gridSizeX; + hParams.m_gridSize[1] = m_params.m_gridSizeY; + hParams.m_gridSize[2] = m_params.m_gridSizeZ; + hParams.m_gridSize[3] = m_params.m_maxBodiesPerCell; + copyArrayToDevice(m_dBpParams, &hParams, sizeof(btParamsBpOCL)); + return; +} + + +void bt3dGridBroadphaseOCL::calcHashAABB() +{ + BT_PROFILE("calcHashAABB"); +#if 1 + runKernelWithWorkgroupSize(GRID3DOCL_KERNEL_CALC_HASH_AABB, m_numHandles); +#ifdef ADD_BLOCKING_CL_FINISH_FOR_BENCHMARK + clFinish(m_cqCommandQue); +#endif //ADD_BLOCKING_CL_FINISH_FOR_BENCHMARK + +#else + btGpu3DGridBroadphase::calcHashAABB(); +#endif + + return; +} + + +void bt3dGridBroadphaseOCL::sortHash() +{ + BT_PROFILE("sortHash"); +#ifdef CL_PLATFORM_MINI_CL + //copyArrayFromDevice(m_hBodiesHash, m_dBodiesHash, m_numHandles * 2 * sizeof(unsigned int)); + btGpu3DGridBroadphase::sortHash(); + copyArrayToDevice(m_dBodiesHash, m_hBodiesHash, m_numHandles * 2 * sizeof(unsigned int)); +#else + +//#define USE_HOST +#ifdef USE_HOST + copyArrayFromDevice(m_hBodiesHash, m_dBodiesHash, m_numHandles * 2 * sizeof(unsigned int)); + //adl::Buffer keysIn,keysOut,valuesIn,valuesOut; + ///adl::RadixSort32::execute(dataC,keysIn,keysOut,valuesIn,valuesOut,m_numHandles); + adl::HostBuffer inoutHost; + inoutHost.m_device = m_deviceHost; + inoutHost.m_ptr = (adl::SortData*)m_hBodiesHash; + inoutHost.m_size = m_numHandles; + adl::RadixSort::execute(dataHost, inoutHost,m_numHandles); + copyArrayToDevice(m_dBodiesHash, m_hBodiesHash, m_numHandles * 2 * sizeof(unsigned int)); +#else + { + clFinish(m_cqCommandQue); + BT_PROFILE("RadixSort32::execute"); + adl::Buffer inout; + inout.m_device = this->m_deviceCL; + inout.m_size = m_numHandles; + inout.m_ptr = (adl::SortData*)m_dBodiesHash; + int actualHandles = m_numHandles; + int dataAlignment = adl::RadixSort32::DATA_ALIGNMENT; + + if (actualHandles%dataAlignment) + { + actualHandles += dataAlignment-(actualHandles%dataAlignment); + } + + adl::RadixSort32::execute(dataC,inout, actualHandles); +#ifdef ADD_BLOCKING_CL_FINISH_FOR_BENCHMARK + clFinish(m_cqCommandQue); +#endif //ADD_BLOCKING_CL_FINISH_FOR_BENCHMARK + } + { + //BT_PROFILE("copyArrayFromDevice"); + //copyArrayFromDevice(m_hBodiesHash, m_dBodiesHash, m_numHandles * 2 * sizeof(unsigned int)); +#ifdef ADD_BLOCKING_CL_FINISH_FOR_BENCHMARK + clFinish(m_cqCommandQue); +#endif //ADD_BLOCKING_CL_FINISH_FOR_BENCHMARK + } + + +#endif //USE_HOST +#endif + + return; +} + + + +void bt3dGridBroadphaseOCL::findCellStart() +{ +#if 1 + BT_PROFILE("findCellStart"); + + #if defined(CL_PLATFORM_MINI_CL) + btGpu3DGridBroadphase::findCellStart(); + copyArrayToDevice(m_dCellStart, m_hCellStart, m_numCells * sizeof(unsigned int)); + #else + runKernelWithWorkgroupSize(GRID3DOCL_KERNEL_CLEAR_CELL_START, m_numCells); + runKernelWithWorkgroupSize(GRID3DOCL_KERNEL_FIND_CELL_START, m_numHandles); + #endif +#ifdef ADD_BLOCKING_CL_FINISH_FOR_BENCHMARK + clFinish(m_cqCommandQue); +#endif + +#else + btGpu3DGridBroadphase::findCellStart(); +#endif + + return; +} + + + +void bt3dGridBroadphaseOCL::findOverlappingPairs() +{ +#if 1 + BT_PROFILE("findOverlappingPairs"); + runKernelWithWorkgroupSize(GRID3DOCL_KERNEL_FIND_OVERLAPPING_PAIRS, m_numHandles); +#ifdef ADD_BLOCKING_CL_FINISH_FOR_BENCHMARK + clFinish(m_cqCommandQue); +#endif + +#else + btGpu3DGridBroadphase::findOverlappingPairs(); + copyArrayToDevice(m_dPairBuffStartCurr, m_hPairBuffStartCurr, (m_maxHandles * 2 + 1) * sizeof(unsigned int)); + copyArrayToDevice(m_dPairBuff, m_hPairBuff, m_maxHandles * m_maxPairsPerBody * sizeof(unsigned int)); +#endif + return; +} + + +void bt3dGridBroadphaseOCL::findPairsLarge() +{ + BT_PROFILE("findPairsLarge"); +#if 1 + if(m_numLargeHandles) + { + setKernelArg(GRID3DOCL_KERNEL_FIND_PAIRS_LARGE, 6, sizeof(int),(void*)&m_numLargeHandles); + runKernelWithWorkgroupSize(GRID3DOCL_KERNEL_FIND_PAIRS_LARGE, m_numHandles); + } +#ifdef ADD_BLOCKING_CL_FINISH_FOR_BENCHMARK + clFinish(m_cqCommandQue); +#endif + +#else + btGpu3DGridBroadphase::findPairsLarge(); +#endif + return; +} + + + +void bt3dGridBroadphaseOCL::computePairCacheChanges() +{ + BT_PROFILE("computePairCacheChanges"); +#if 1 + runKernelWithWorkgroupSize(GRID3DOCL_KERNEL_COMPUTE_CACHE_CHANGES, m_numHandles); +#ifdef ADD_BLOCKING_CL_FINISH_FOR_BENCHMARK + clFinish(m_cqCommandQue); +#endif + copyArrayFromDevice( m_hPairScanChanged,m_dPairScanChanged, sizeof(unsigned int)*(m_numHandles + 2)); + +#else + btGpu3DGridBroadphase::computePairCacheChanges(); + copyArrayToDevice(m_dPairScanChanged, m_hPairScanChanged, sizeof(unsigned int)*(m_numHandles + 2)); + + +#endif + return; +} + + + + +extern cl_device_type deviceType; + +void bt3dGridBroadphaseOCL::scanOverlappingPairBuff(bool copyToCpu) +{ + + //Intel/CPU version doesn't handlel Adl scan well +#if 0 + { + copyArrayFromDevice(m_hPairScanChanged, m_dPairScanChanged, sizeof(unsigned int)*(m_numHandles + 2)); + btGpu3DGridBroadphase::scanOverlappingPairBuff(); + copyArrayToDevice(m_dPairScanChanged, m_hPairScanChanged, sizeof(unsigned int)*(m_numHandles + 2)); + m_numPrefixSum = m_hPairScanChanged[m_numHandles+1]; + clFinish(m_cqCommandQue); + //memset(m_hPairScanChanged,0,sizeof(int)*m_maxHandles + 2); + } +#else + { + + // copyArrayFromDevice(m_hPairScanChanged, m_dPairScanChanged, sizeof(unsigned int)*(m_numHandles + 2)); + // btGpu3DGridBroadphase::scanOverlappingPairBuff(); + + adl::Buffer destBuffer; + + { + BT_PROFILE("copy GPU->GPU"); + + destBuffer.m_ptr = (unsigned int*)m_dPairScanChanged; + destBuffer.m_device = m_deviceCL; + destBuffer.m_size = sizeof(unsigned int)*(m_numHandles+2); + m_deviceCL->copy(m_srcClBuffer, &destBuffer,m_numHandles,1,1); + +#ifdef ADD_BLOCKING_CL_FINISH_FOR_BENCHMARK + clFinish(m_cqCommandQue); +#endif + + } + + { + BT_PROFILE("PrefixScan"); + + adl::PrefixScan::execute(gData1,*m_srcClBuffer,destBuffer, m_numHandles+2,&m_numPrefixSum); + +#ifdef ADD_BLOCKING_CL_FINISH_FOR_BENCHMARK + clFinish(m_cqCommandQue); +#endif + //if (m_numPrefixSum>0x1000) + // { + // printf("error m_numPrefixSum==%d\n",m_numPrefixSum); + // } + + } + +#if 0 + unsigned int* verifyhPairScanChanged = new unsigned int[m_maxHandles + 2]; + memset(verifyhPairScanChanged,0,sizeof(int)*m_maxHandles + 2); + + copyArrayFromDevice(verifyhPairScanChanged, m_dPairScanChanged, sizeof(unsigned int)*(m_numHandles + 2)); + clFinish(m_cqCommandQue); + + /*for (int i=0;i CPU"); + copyArrayFromDevice(m_hPairScanChanged, m_dPairScanChanged, sizeof(unsigned int)*(m_numHandles + 2)); +#ifdef ADD_BLOCKING_CL_FINISH_FOR_BENCHMARK + clFinish(m_cqCommandQue); +#endif + } + + } + + } +#endif + + +} + + + +void bt3dGridBroadphaseOCL::squeezeOverlappingPairBuff() +{ + BT_PROFILE("btCuda_squeezeOverlappingPairBuff"); +#if 1 + runKernelWithWorkgroupSize(GRID3DOCL_KERNEL_SQUEEZE_PAIR_BUFF, m_numHandles); +// btCuda_squeezeOverlappingPairBuff(m_dPairBuff, m_dPairBuffStartCurr, m_dPairScanChanged, m_dPairsChanged, m_dAABB, m_numHandles); + + //copyArrayFromDevice(m_hPairsChanged, m_dPairsChanged, sizeof(unsigned int) * m_numPrefixSum);//m_hPairScanChanged[m_numHandles+1]); //gSum +#ifdef ADD_BLOCKING_CL_FINISH_FOR_BENCHMARK + clFinish(m_cqCommandQue); +#endif + +#else + btGpu3DGridBroadphase::squeezeOverlappingPairBuff(); +#endif + return; +} + + + +void bt3dGridBroadphaseOCL::resetPool(btDispatcher* dispatcher) +{ + btGpu3DGridBroadphase::resetPool(dispatcher); + prefillBuffers(); +} + + diff --git a/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.h b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.h new file mode 100644 index 0000000..dee297c --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.h @@ -0,0 +1,146 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006 - 2009 Sony Computer Entertainment Inc. + +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 BT3DGRIDBROADPHASEOCL_H +#define BT3DGRIDBROADPHASEOCL_H + +#ifdef __APPLE__ +#ifdef USE_MINICL + #include +#else + #include +#endif +//CL_PLATFORM_MINI_CL could be defined in build system +#else +//#include +// standard utility and system includes +#ifdef USE_MINICL + #include +#else + #include +#endif +// Extra CL/GL include +//#include +#endif //__APPLE__ + +namespace adl +{ + struct Device; + struct DeviceCL; +}; + +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "btGpu3DGridBroadphaseSharedTypes.h" +#include "btGpu3DGridBroadphase.h" + + +#define GRID3DOCL_CHECKERROR(a, b) if((a)!=(b)) { printf("3D GRID OCL Error : %d\n", (a)); btAssert((a) == (b)); } + +enum +{ + GRID3DOCL_KERNEL_CALC_HASH_AABB = 0, + GRID3DOCL_KERNEL_CLEAR_CELL_START, + GRID3DOCL_KERNEL_FIND_CELL_START, + GRID3DOCL_KERNEL_FIND_OVERLAPPING_PAIRS, + GRID3DOCL_KERNEL_FIND_PAIRS_LARGE, + GRID3DOCL_KERNEL_COMPUTE_CACHE_CHANGES, + GRID3DOCL_KERNEL_SQUEEZE_PAIR_BUFF, + GRID3DOCL_KERNEL_TOTAL +}; + +struct bt3dGridOCLKernelInfo +{ + int m_Id; + cl_kernel m_kernel; + char* m_name; + int m_workgroupSize; +}; + + +///The bt3dGridBroadphaseOCL uses OpenCL-capable GPU to compute overlapping pairs + +class bt3dGridBroadphaseOCL : public btGpu3DGridBroadphase +{ +protected: + int m_hashSize; + cl_context m_cxMainContext; + cl_device_id m_cdDevice; + cl_command_queue m_cqCommandQue; + cl_program m_cpProgram; + bt3dGridOCLKernelInfo m_kernels[GRID3DOCL_KERNEL_TOTAL]; + // data buffers + cl_mem m_dBodiesHash; + cl_mem m_dCellStart; + cl_mem m_dPairBuff; + cl_mem m_dPairBuffStartCurr; +public: + cl_mem m_dAABB; +protected: + cl_mem m_dPairScanChanged; + cl_mem m_dPairsChanged; + cl_mem m_dPairsContiguous; + cl_mem m_dBpParams; + + adl::Device* m_deviceHost; + adl::DeviceCL* m_deviceCL; + bool m_ownsDevice; + + +public: + unsigned int m_numPrefixSum; + + bt3dGridBroadphaseOCL( btOverlappingPairCache* overlappingPairCache, + const btVector3& cellSize, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerSmallProxy, + btScalar maxSmallProxySize, + int maxSmallProxiesPerCell = 8, + cl_context context = NULL, + cl_device_id device = NULL, + cl_command_queue queue = NULL, + adl::DeviceCL* deviceCL = 0 + ); + virtual ~bt3dGridBroadphaseOCL(); + +protected: + void initCL(cl_context context, cl_device_id device, cl_command_queue queue); + void initKernels(); + void allocateBuffers(); + void prefillBuffers(); + void initKernel(int kernelId, char* pName); + void allocateArray(void** devPtr, unsigned int size); + void freeArray(void* devPtr); + void runKernelWithWorkgroupSize(int kernelId, int globalSize); + void setKernelArg(int kernelId, int argNum, int argSize, void* argPtr); + void copyArrayToDevice(cl_mem device, const void* host, unsigned int size, int devOffs = 0, int hostOffs = 0); + void copyArrayFromDevice(void* host, const cl_mem device, unsigned int size, int hostOffs = 0, int devOffs = 0); + +// overrides + virtual void setParameters(bt3DGridBroadphaseParams* hostParams); + virtual void prepareAABB(); + virtual void calcHashAABB(); + virtual void sortHash(); + virtual void findCellStart(); + virtual void findOverlappingPairs(); + virtual void findPairsLarge(); + virtual void computePairCacheChanges(); + virtual void scanOverlappingPairBuff(bool copyToCpu=true); + virtual void squeezeOverlappingPairBuff(); + virtual void resetPool(btDispatcher* dispatcher); +}; + +#endif //BT3DGRIDBROADPHASEOCL_H \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphase.cpp b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphase.cpp new file mode 100644 index 0000000..3ecb6a2 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphase.cpp @@ -0,0 +1,626 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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. +*/ + +///The 3 following lines include the CPU implementation of the kernels, keep them in this order. +#include "btGpuDefines.h" +#include "btGpuUtilsSharedDefs.h" +#include "btGpuUtilsSharedCode.h" + + + +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btQuickprof.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" + + + +#include "btGpuDefines.h" +#include "btGpuUtilsSharedDefs.h" + +#include "btGpu3DGridBroadphaseSharedDefs.h" + +#include "btGpu3DGridBroadphase.h" +#include //for memset + + +#include + + + +static bt3DGridBroadphaseParams s3DGridBroadphaseParams; + + + +btGpu3DGridBroadphase::btGpu3DGridBroadphase( const btVector3& cellSize, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + btScalar maxSmallProxySize, + int maxBodiesPerCell) : + btSimpleBroadphase(maxSmallProxies, +// new (btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16)) btSortedOverlappingPairCache), + new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache), + m_bInitialized(false), + m_numBodies(0) +{ + _initialize(cellSize, gridSizeX, gridSizeY, gridSizeZ, + maxSmallProxies, maxLargeProxies, maxPairsPerBody, + maxSmallProxySize, maxBodiesPerCell); +} + + + +btGpu3DGridBroadphase::btGpu3DGridBroadphase( btOverlappingPairCache* overlappingPairCache, + const btVector3& cellSize, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + btScalar maxSmallProxySize, + int maxBodiesPerCell) : + btSimpleBroadphase(maxSmallProxies, overlappingPairCache), + m_bInitialized(false), + m_numBodies(0) +{ + _initialize(cellSize, gridSizeX, gridSizeY, gridSizeZ, + maxSmallProxies, maxLargeProxies, maxPairsPerBody, + maxSmallProxySize, maxBodiesPerCell); +} + + + +btGpu3DGridBroadphase::~btGpu3DGridBroadphase() +{ + //btSimpleBroadphase will free memory of btSortedOverlappingPairCache, because m_ownsPairCache + assert(m_bInitialized); + _finalize(); + + +} + +// returns 2^n : 2^(n+1) > val >= 2^n +int btGpu3DGridBroadphase::getFloorPowOfTwo(int val) +{ + int mask = 0x40000000; + for(int k = 0; k < 30; k++, mask >>= 1) + { + if(mask & val) + { + break; + } + } + return mask; +} + + + +void btGpu3DGridBroadphase::_initialize( const btVector3& cellSize, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + btScalar maxSmallProxySize, + int maxBodiesPerCell) +{ + // set various paramerers + m_ownsPairCache = true; + m_params.m_gridSizeX = getFloorPowOfTwo(gridSizeX); + m_params.m_gridSizeY = getFloorPowOfTwo(gridSizeY); + m_params.m_gridSizeZ = getFloorPowOfTwo(gridSizeZ); + m_params.m_numCells = m_params.m_gridSizeX * m_params.m_gridSizeY * m_params.m_gridSizeZ; + m_numCells = m_params.m_numCells; + m_params.m_invCellSizeX = btScalar(1.f) / cellSize[0]; + m_params.m_invCellSizeY = btScalar(1.f) / cellSize[1]; + m_params.m_invCellSizeZ = btScalar(1.f) / cellSize[2]; + m_maxRadius = maxSmallProxySize * btScalar(0.5f); + m_params.m_numBodies = m_numBodies; + m_params.m_maxBodiesPerCell = maxBodiesPerCell; + + m_numLargeHandles = 0; + m_maxLargeHandles = maxLargeProxies; + + m_maxPairsPerBody = maxPairsPerBody; + + m_LastLargeHandleIndex = -1; + + assert(!m_bInitialized); + + // allocate host storage + m_hBodiesHash = new unsigned int[m_maxHandles * 2]; + memset(m_hBodiesHash, 0x00, m_maxHandles*2*sizeof(unsigned int)); + + m_hCellStart = new unsigned int[m_params.m_numCells]; + memset(m_hCellStart, 0x00, m_params.m_numCells * sizeof(unsigned int)); + + m_hPairBuffStartCurr = new unsigned int[m_maxHandles * 2 + 2]; + // --------------- for now, init with m_maxPairsPerBody for each body + m_hPairBuffStartCurr[0] = 0; + m_hPairBuffStartCurr[1] = 0; + for(int i = 1; i <= m_maxHandles; i++) + { + m_hPairBuffStartCurr[i * 2] = m_hPairBuffStartCurr[(i-1) * 2] + m_maxPairsPerBody; + m_hPairBuffStartCurr[i * 2 + 1] = 0; + } + //---------------- + unsigned int numAABB = m_maxHandles + m_maxLargeHandles; + m_hAABB = new bt3DGrid3F1U[numAABB * 2]; // AABB Min & Max + + m_hPairBuff = new unsigned int[m_maxHandles * m_maxPairsPerBody]; + memset(m_hPairBuff, 0x00, m_maxHandles * m_maxPairsPerBody * sizeof(unsigned int)); // needed? + + m_hPairScanChanged = new unsigned int[m_maxHandles + 2]; + memset(m_hPairScanChanged,0,sizeof(int)*m_maxHandles + 2); + + m_hPairsChanged = new unsigned int[m_maxHandles * m_maxPairsPerBody]; + memset(m_hPairsChanged,0,sizeof(int)*(m_maxHandles * m_maxPairsPerBody)); + + m_hAllOverlappingPairs= new MyUint2[m_maxHandles * m_maxPairsPerBody]; + memset(m_hAllOverlappingPairs,0,sizeof(MyUint2)*(m_maxHandles * m_maxPairsPerBody)); + + +// large proxies + + // allocate handles buffer and put all handles on free list + m_pLargeHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy) * m_maxLargeHandles, 16); + m_pLargeHandles = new(m_pLargeHandlesRawPtr) btSimpleBroadphaseProxy[m_maxLargeHandles]; + m_firstFreeLargeHandle = 0; + { + for (int i = m_firstFreeLargeHandle; i < m_maxLargeHandles; i++) + { + m_pLargeHandles[i].SetNextFree(i + 1); + m_pLargeHandles[i].m_uniqueId = m_maxHandles+2+i; + } + m_pLargeHandles[m_maxLargeHandles - 1].SetNextFree(0); + } + +// debug data + m_numPairsAdded = 0; + m_numOverflows = 0; + + + m_bInitialized = true; +} + + + +void btGpu3DGridBroadphase::_finalize() +{ + assert(m_bInitialized); + delete [] m_hBodiesHash; + delete [] m_hCellStart; + delete [] m_hPairBuffStartCurr; + delete [] m_hAABB; + delete [] m_hPairBuff; + delete [] m_hPairScanChanged; + delete [] m_hPairsChanged; + delete [] m_hAllOverlappingPairs; + btAlignedFree(m_pLargeHandlesRawPtr); + m_bInitialized = false; +} + + + +void btGpu3DGridBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + btSimpleBroadphase::calculateOverlappingPairs(dispatcher); + + if(m_numHandles <= 0) + { + BT_PROFILE("addLarge2LargePairsToCache"); + addLarge2LargePairsToCache(dispatcher); + return; + } + // update constants + { + BT_PROFILE("setParameters"); + setParameters(&m_params); + } + + // prepare AABB array + { + BT_PROFILE("prepareAABB"); + prepareAABB(); + } + // calculate hash + { + BT_PROFILE("calcHashAABB"); + calcHashAABB(); + } + { + BT_PROFILE("sortHash"); + // sort bodies based on hash + sortHash(); + } + // find start of each cell + { + BT_PROFILE("findCellStart"); + findCellStart(); + } + { + BT_PROFILE("findOverlappingPairs"); + // findOverlappingPairs (small/small) + findOverlappingPairs(); + } + // findOverlappingPairs (small/large) + { + BT_PROFILE("findPairsLarge"); + findPairsLarge(); + } + // add pairs to CPU cache + { + BT_PROFILE("computePairCacheChanges"); + computePairCacheChanges(); + } + { + BT_PROFILE("scanOverlappingPairBuff"); + scanOverlappingPairBuff(); + } + { + BT_PROFILE("squeezeOverlappingPairBuff"); + squeezeOverlappingPairBuff(); + } + { + BT_PROFILE("addPairsToCache"); + addPairsToCache(dispatcher); + } + // find and add large/large pairs to CPU cache + { + BT_PROFILE("addLarge2LargePairsToCache"); + addLarge2LargePairsToCache(dispatcher); + } + return; +} + + + +void btGpu3DGridBroadphase::addPairsToCache(btDispatcher* dispatcher) +{ + m_numPairsAdded = 0; + m_numPairsRemoved = 0; + for(int i = 0; i < m_numHandles; i++) + { + unsigned int num = m_hPairScanChanged[i+2] - m_hPairScanChanged[i+1]; + if(!num) + { + continue; + } + unsigned int* pInp = m_hPairsChanged + m_hPairScanChanged[i+1]; + unsigned int index0 = m_hAABB[i * 2].uw; + btSimpleBroadphaseProxy* proxy0 = &m_pHandles[index0]; + for(unsigned int j = 0; j < num; j++) + { + unsigned int indx1_s = pInp[j]; + unsigned int index1 = indx1_s & (~BT_3DGRID_PAIR_ANY_FLG); + btSimpleBroadphaseProxy* proxy1; + if(index1 < (unsigned int)m_maxHandles) + { + proxy1 = &m_pHandles[index1]; + } + else + { + index1 -= m_maxHandles; + btAssert((index1 >= 0) && (index1 < (unsigned int)m_maxLargeHandles)); + proxy1 = &m_pLargeHandles[index1]; + } + if(indx1_s & BT_3DGRID_PAIR_NEW_FLG) + { + m_pairCache->addOverlappingPair(proxy0,proxy1); + m_numPairsAdded++; + } + else + { + m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); + m_numPairsRemoved++; + } + } + } +} + + + +btBroadphaseProxy* btGpu3DGridBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) +{ + btBroadphaseProxy* proxy; + bool bIsLarge = isLargeProxy(aabbMin, aabbMax); + if(bIsLarge) + { + if (m_numLargeHandles >= m_maxLargeHandles) + { + ///you have to increase the cell size, so 'large' proxies become 'small' proxies (fitting a cell) + btAssert(0); + return 0; //should never happen, but don't let the game crash ;-) + } + btAssert((aabbMin[0]<= aabbMax[0]) && (aabbMin[1]<= aabbMax[1]) && (aabbMin[2]<= aabbMax[2])); + int newHandleIndex = allocLargeHandle(); + proxy = new (&m_pLargeHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy); + } + else + { + proxy = btSimpleBroadphase::createProxy(aabbMin, aabbMax, shapeType, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher, multiSapProxy); + } + return proxy; +} + + + +void btGpu3DGridBroadphase::destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher) +{ + bool bIsLarge = isLargeProxy(proxy); + if(bIsLarge) + { + + btSimpleBroadphaseProxy* proxy0 = static_cast(proxy); + freeLargeHandle(proxy0); + m_pairCache->removeOverlappingPairsContainingProxy(proxy,dispatcher); + } + else + { + btSimpleBroadphase::destroyProxy(proxy, dispatcher); + } + return; +} + + + +void btGpu3DGridBroadphase::resetPool(btDispatcher* dispatcher) +{ + m_hPairBuffStartCurr[0] = 0; + m_hPairBuffStartCurr[1] = 0; + for(int i = 1; i <= m_maxHandles; i++) + { + m_hPairBuffStartCurr[i * 2] = m_hPairBuffStartCurr[(i-1) * 2] + m_maxPairsPerBody; + m_hPairBuffStartCurr[i * 2 + 1] = 0; + } +} + + + +bool btGpu3DGridBroadphase::isLargeProxy(const btVector3& aabbMin, const btVector3& aabbMax) +{ + btVector3 diag = aabbMax - aabbMin; + ///use the bounding sphere radius of this bounding box, to include rotation + btScalar radius = diag.length() * btScalar(0.5f); + return (radius > m_maxRadius); +} + + + +bool btGpu3DGridBroadphase::isLargeProxy(btBroadphaseProxy* proxy) +{ + return (proxy->getUid() >= (m_maxHandles+2)); +} + + + +void btGpu3DGridBroadphase::addLarge2LargePairsToCache(btDispatcher* dispatcher) +{ + int i,j; + if (m_numLargeHandles <= 0) + { + return; + } + int new_largest_index = -1; + for(i = 0; i <= m_LastLargeHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy0 = &m_pLargeHandles[i]; + new_largest_index = i; + for(j = i + 1; j <= m_LastLargeHandleIndex; j++) + { + btSimpleBroadphaseProxy* proxy1 = &m_pLargeHandles[j]; + btAssert(proxy0 != proxy1); + btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); + btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); + if(aabbOverlap(p0,p1)) + { + if (!m_pairCache->findPair(proxy0,proxy1)) + { + m_pairCache->addOverlappingPair(proxy0,proxy1); + } + } + else + { + if(m_pairCache->findPair(proxy0,proxy1)) + { + m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); + } + } + } + } + m_LastLargeHandleIndex = new_largest_index; + return; +} + + + +void btGpu3DGridBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback) +{ + btSimpleBroadphase::rayTest(rayFrom, rayTo, rayCallback); + for (int i=0; i <= m_LastLargeHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy = &m_pLargeHandles[i]; + rayCallback.process(proxy); + } +} + + + +// +// overrides for CPU version +// + + + +void btGpu3DGridBroadphase::prepareAABB() +{ + BT_PROFILE("prepareAABB"); + bt3DGrid3F1U* pBB = m_hAABB; + int i; + int new_largest_index = -1; + unsigned int num_small = 0; + for(i = 0; i <= m_LastHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i]; + new_largest_index = i; + pBB->fx = proxy0->m_aabbMin.getX(); + pBB->fy = proxy0->m_aabbMin.getY(); + pBB->fz = proxy0->m_aabbMin.getZ(); + pBB->uw = i; + pBB++; + pBB->fx = proxy0->m_aabbMax.getX(); + pBB->fy = proxy0->m_aabbMax.getY(); + pBB->fz = proxy0->m_aabbMax.getZ(); + pBB->uw = num_small; + pBB++; + num_small++; + } + m_LastHandleIndex = new_largest_index; + new_largest_index = -1; + unsigned int num_large = 0; + for(i = 0; i <= m_LastLargeHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy0 = &m_pLargeHandles[i]; + new_largest_index = i; + pBB->fx = proxy0->m_aabbMin.getX(); + pBB->fy = proxy0->m_aabbMin.getY(); + pBB->fz = proxy0->m_aabbMin.getZ(); + pBB->uw = i + m_maxHandles; + pBB++; + pBB->fx = proxy0->m_aabbMax.getX(); + pBB->fy = proxy0->m_aabbMax.getY(); + pBB->fz = proxy0->m_aabbMax.getZ(); + pBB->uw = num_large + m_maxHandles; + pBB++; + num_large++; + } + m_LastLargeHandleIndex = new_largest_index; + // paranoid checks + btAssert(num_small == m_numHandles); + btAssert(num_large == m_numLargeHandles); + return; +} + + + +void btGpu3DGridBroadphase::setParameters(bt3DGridBroadphaseParams* hostParams) +{ + s3DGridBroadphaseParams = *hostParams; + return; +} + + + +void btGpu3DGridBroadphase::calcHashAABB() +{ + BT_PROFILE("bt3DGrid_calcHashAABB"); + btGpu_calcHashAABB(m_hAABB, m_hBodiesHash, m_numHandles); + return; +} + + + +void btGpu3DGridBroadphase::sortHash() +{ + class bt3DGridHashKey + { + public: + unsigned int hash; + unsigned int index; + void quickSort(bt3DGridHashKey* pData, int lo, int hi) + { + int i=lo, j=hi; + bt3DGridHashKey x = pData[(lo+hi)/2]; + do + { + while(pData[i].hash > x.hash) i++; + while(x.hash > pData[j].hash) j--; + if(i <= j) + { + bt3DGridHashKey t = pData[i]; + pData[i] = pData[j]; + pData[j] = t; + i++; j--; + } + } while(i <= j); + if(lo < j) pData->quickSort(pData, lo, j); + if(i < hi) pData->quickSort(pData, i, hi); + } + }; + BT_PROFILE("bt3DGrid_sortHash"); + bt3DGridHashKey* pHash = (bt3DGridHashKey*)m_hBodiesHash; + pHash->quickSort(pHash, 0, m_numHandles - 1); + return; +} + + + +void btGpu3DGridBroadphase::findCellStart() +{ + BT_PROFILE("bt3DGrid_findCellStart"); + btGpu_findCellStart(m_hBodiesHash, m_hCellStart, m_numHandles, m_params.m_numCells); + return; +} + + + +void btGpu3DGridBroadphase::findOverlappingPairs() +{ + BT_PROFILE("bt3DGrid_findOverlappingPairs"); + btGpu_findOverlappingPairs(m_hAABB, m_hBodiesHash, m_hCellStart, m_hPairBuff, m_hPairBuffStartCurr, m_numHandles); + return; +} + + + +void btGpu3DGridBroadphase::findPairsLarge() +{ + BT_PROFILE("bt3DGrid_findPairsLarge"); + btGpu_findPairsLarge(m_hAABB, m_hBodiesHash, m_hCellStart, m_hPairBuff, m_hPairBuffStartCurr, m_numHandles, m_numLargeHandles); + return; +} + + + +void btGpu3DGridBroadphase::computePairCacheChanges() +{ + BT_PROFILE("bt3DGrid_computePairCacheChanges"); + btGpu_computePairCacheChanges(m_hPairBuff, m_hPairBuffStartCurr, m_hPairScanChanged, m_hAABB, m_numHandles); + return; +} + + +void btGpu3DGridBroadphase::scanOverlappingPairBuff(bool copyToCpu) +{ + BT_PROFILE("bt3DGrid_scanOverlappingPairBuff"); + unsigned int sum = 0; + m_hPairScanChanged[0]=0; + for(int i = 0; i <= m_numHandles+1; i++) + { + unsigned int delta = m_hPairScanChanged[i]; + m_hPairScanChanged[i] = sum; + sum += delta; + } + return; +} + + + +void btGpu3DGridBroadphase::squeezeOverlappingPairBuff() +{ + BT_PROFILE("bt3DGrid_squeezeOverlappingPairBuff"); + //btGpu_squeezeOverlappingPairBuff(m_hPairBuff, m_hPairBuffStartCurr, m_hPairScanChanged, m_hPairsChanged, m_hAABB, m_numHandles); + btGpu_squeezeOverlappingPairBuff(m_hPairBuff, m_hPairBuffStartCurr, m_hPairScanChanged, (unsigned int*)m_hAllOverlappingPairs, m_hAABB, m_numHandles); + + return; +} + + + +#include "btGpu3DGridBroadphaseSharedCode.h" + diff --git a/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphase.h b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphase.h new file mode 100644 index 0000000..8441151 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphase.h @@ -0,0 +1,154 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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 BTGPU3DGRIDBROADPHASE_H +#define BTGPU3DGRIDBROADPHASE_H + +//---------------------------------------------------------------------------------------- + +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" + +#include "btGpu3DGridBroadphaseSharedTypes.h" +struct MyUint2 +{ + int x; + int y; +}; + +//---------------------------------------------------------------------------------------- + +///The btGpu3DGridBroadphase uses GPU-style code compiled for CPU to compute overlapping pairs + +class btGpu3DGridBroadphase : public btSimpleBroadphase +{ +protected: + bool m_bInitialized; + unsigned int m_numBodies; + unsigned int m_numCells; + unsigned int m_maxPairsPerBody; + unsigned int m_maxBodiesPerCell; + bt3DGridBroadphaseParams m_params; + btScalar m_maxRadius; + // CPU data + unsigned int* m_hBodiesHash; + unsigned int* m_hCellStart; + unsigned int* m_hPairBuffStartCurr; + bt3DGrid3F1U* m_hAABB; + unsigned int* m_hPairBuff; + unsigned int* m_hPairScanChanged; + unsigned int* m_hPairsChanged; + MyUint2* m_hAllOverlappingPairs; +// large proxies + int m_numLargeHandles; + int m_maxLargeHandles; + int m_LastLargeHandleIndex; + btSimpleBroadphaseProxy* m_pLargeHandles; + void* m_pLargeHandlesRawPtr; + int m_firstFreeLargeHandle; + int allocLargeHandle() + { + btAssert(m_numLargeHandles < m_maxLargeHandles); + int freeLargeHandle = m_firstFreeLargeHandle; + m_firstFreeLargeHandle = m_pLargeHandles[freeLargeHandle].GetNextFree(); + m_numLargeHandles++; + if(freeLargeHandle > m_LastLargeHandleIndex) + { + m_LastLargeHandleIndex = freeLargeHandle; + } + return freeLargeHandle; + } + void freeLargeHandle(btSimpleBroadphaseProxy* proxy) + { + int handle = int(proxy - m_pLargeHandles); + btAssert((handle >= 0) && (handle < m_maxHandles)); + if(handle == m_LastLargeHandleIndex) + { + m_LastLargeHandleIndex--; + } + proxy->SetNextFree(m_firstFreeLargeHandle); + m_firstFreeLargeHandle = handle; + proxy->m_clientObject = 0; + m_numLargeHandles--; + } + bool isLargeProxy(const btVector3& aabbMin, const btVector3& aabbMax); + bool isLargeProxy(btBroadphaseProxy* proxy); +// debug + unsigned int m_numPairsAdded; + unsigned int m_numPairsRemoved; + unsigned int m_numOverflows; +// +public: + virtual int getNumOverlap() + { + return m_hPairScanChanged[m_numHandles+1]; + } + virtual MyUint2* getOverlap() + { + return m_hAllOverlappingPairs; + } + // NOTE : for better results gridSizeX, gridSizeY and gridSizeZ should be powers of 2 + btGpu3DGridBroadphase(const btVector3& cellSize, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + btScalar maxSmallProxySize, + int maxBodiesPerCell = 8); + btGpu3DGridBroadphase( btOverlappingPairCache* overlappingPairCache, + const btVector3& cellSize, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + btScalar maxSmallProxySize, + int maxBodiesPerCell = 8); + virtual ~btGpu3DGridBroadphase(); + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); + + virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback); + virtual void resetPool(btDispatcher* dispatcher); + + static int getFloorPowOfTwo(int val); // returns 2^n : 2^(n+1) > val >= 2^n + +protected: + void _initialize( const btVector3& cellSize, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + btScalar maxSmallProxySize, + int maxBodiesPerCell); + void _finalize(); + void addPairsToCache(btDispatcher* dispatcher); + void addLarge2LargePairsToCache(btDispatcher* dispatcher); + +// overrides for CPU version + virtual void setParameters(bt3DGridBroadphaseParams* hostParams); + virtual void prepareAABB(); + virtual void calcHashAABB(); + virtual void sortHash(); + virtual void findCellStart(); + virtual void findOverlappingPairs(); + virtual void findPairsLarge(); + virtual void computePairCacheChanges(); + virtual void scanOverlappingPairBuff(bool copyToCpu=true); + virtual void squeezeOverlappingPairBuff(); +}; + +//---------------------------------------------------------------------------------------- + +#endif //BTGPU3DGRIDBROADPHASE_H + +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- diff --git a/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphaseSharedCode.h b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphaseSharedCode.h new file mode 100644 index 0000000..08df68a --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphaseSharedCode.h @@ -0,0 +1,428 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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. +*/ + +//---------------------------------------------------------------------------------------- + +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +// K E R N E L F U N C T I O N S +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- + +// calculate position in uniform grid +BT_GPU___device__ int3 bt3DGrid_calcGridPos(float4 p) +{ + int3 gridPos; + gridPos.x = (int)floor(p.x * BT_GPU_params.m_invCellSizeX) & (BT_GPU_params.m_gridSizeX - 1); + gridPos.y = (int)floor(p.y * BT_GPU_params.m_invCellSizeY) & (BT_GPU_params.m_gridSizeY - 1); + gridPos.z = (int)floor(p.z * BT_GPU_params.m_invCellSizeZ) & (BT_GPU_params.m_gridSizeZ - 1); + return gridPos; +} // bt3DGrid_calcGridPos() + +//---------------------------------------------------------------------------------------- + +// calculate address in grid from position (clamping to edges) +BT_GPU___device__ uint bt3DGrid_calcGridHash(int3 gridPos) +{ + gridPos.x &= (BT_GPU_params.m_gridSizeX - 1); + gridPos.y &= (BT_GPU_params.m_gridSizeY - 1); + gridPos.z &= (BT_GPU_params.m_gridSizeZ - 1); + return BT_GPU___mul24(BT_GPU___mul24(gridPos.z, BT_GPU_params.m_gridSizeY), BT_GPU_params.m_gridSizeX) + BT_GPU___mul24(gridPos.y, BT_GPU_params.m_gridSizeX) + gridPos.x; +} // bt3DGrid_calcGridHash() + +//---------------------------------------------------------------------------------------- + +// calculate grid hash value for each body using its AABB +BT_GPU___global__ void calcHashAABBD(bt3DGrid3F1U* pAABB, uint2* pHash, uint numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + bt3DGrid3F1U bbMin = pAABB[index*2]; + bt3DGrid3F1U bbMax = pAABB[index*2 + 1]; + float4 pos; + pos.x = (bbMin.fx + bbMax.fx) * 0.5f; + pos.y = (bbMin.fy + bbMax.fy) * 0.5f; + pos.z = (bbMin.fz + bbMax.fz) * 0.5f; + // get address in grid + int3 gridPos = bt3DGrid_calcGridPos(pos); + uint gridHash = bt3DGrid_calcGridHash(gridPos); + // store grid hash and body index + pHash[index] = BT_GPU_make_uint2(gridHash, index); +} // calcHashAABBD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void findCellStartD(uint2* pHash, uint* cellStart, uint numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + uint2 sortedData = pHash[index]; + // Load hash data into shared memory so that we can look + // at neighboring body's hash value without loading + // two hash values per thread + BT_GPU___shared__ uint sharedHash[257]; + sharedHash[BT_GPU_threadIdx.x+1] = sortedData.x; + if((index > 0) && (BT_GPU_threadIdx.x == 0)) + { + // first thread in block must load neighbor body hash + volatile uint2 prevData = pHash[index-1]; + sharedHash[0] = prevData.x; + } + BT_GPU___syncthreads(); + if((index == 0) || (sortedData.x != sharedHash[BT_GPU_threadIdx.x])) + { + cellStart[sortedData.x] = index; + } +} // findCellStartD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___device__ uint cudaTestAABBOverlap(bt3DGrid3F1U min0, bt3DGrid3F1U max0, bt3DGrid3F1U min1, bt3DGrid3F1U max1) +{ + return (min0.fx <= max1.fx)&& (min1.fx <= max0.fx) && + (min0.fy <= max1.fy)&& (min1.fy <= max0.fy) && + (min0.fz <= max1.fz)&& (min1.fz <= max0.fz); +} // cudaTestAABBOverlap() + +//---------------------------------------------------------------------------------------- + +BT_GPU___device__ void findPairsInCell( int3 gridPos, + uint index, + uint2* pHash, + uint* pCellStart, + bt3DGrid3F1U* pAABB, + uint* pPairBuff, + uint2* pPairBuffStartCurr, + uint numBodies) +{ + uint gridHash = bt3DGrid_calcGridHash(gridPos); + // get start of bucket for this cell + uint bucketStart = pCellStart[gridHash]; + if (bucketStart == 0xffffffff) + { + return; // cell empty + } + // iterate over bodies in this cell + uint2 sortedData = pHash[index]; + uint unsorted_indx = sortedData.y; + bt3DGrid3F1U min0 = BT_GPU_FETCH(pAABB, unsorted_indx*2); + bt3DGrid3F1U max0 = BT_GPU_FETCH(pAABB, unsorted_indx*2 + 1); + uint handleIndex = min0.uw; + uint2 start_curr = pPairBuffStartCurr[handleIndex]; + uint start = start_curr.x; + uint curr = start_curr.y; + uint2 start_curr_next = pPairBuffStartCurr[handleIndex+1]; + uint curr_max = start_curr_next.x - start - 1; + uint bucketEnd = bucketStart + BT_GPU_params.m_maxBodiesPerCell; + bucketEnd = (bucketEnd > numBodies) ? numBodies : bucketEnd; + for(uint index2 = bucketStart; index2 < bucketEnd; index2++) + { + uint2 cellData = pHash[index2]; + if (cellData.x != gridHash) + { + break; // no longer in same bucket + } + uint unsorted_indx2 = cellData.y; + if (unsorted_indx2 < unsorted_indx) // check not colliding with self + { + bt3DGrid3F1U min1 = BT_GPU_FETCH(pAABB, unsorted_indx2*2); + bt3DGrid3F1U max1 = BT_GPU_FETCH(pAABB, unsorted_indx2*2 + 1); + if(cudaTestAABBOverlap(min0, max0, min1, max1)) + { + uint handleIndex2 = min1.uw; + uint k; + for(k = 0; k < curr; k++) + { + uint old_pair = pPairBuff[start+k] & (~BT_3DGRID_PAIR_ANY_FLG); + if(old_pair == handleIndex2) + { + pPairBuff[start+k] |= BT_3DGRID_PAIR_FOUND_FLG; + break; + } + } + if(k == curr) + { + if(curr >= curr_max) + { // not a good solution, but let's avoid crash + break; + } + pPairBuff[start+curr] = handleIndex2 | BT_3DGRID_PAIR_NEW_FLG; + curr++; + } + } + } + } + pPairBuffStartCurr[handleIndex] = BT_GPU_make_uint2(start, curr); + return; +} // findPairsInCell() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void findOverlappingPairsD( bt3DGrid3F1U* pAABB, uint2* pHash, uint* pCellStart, + uint* pPairBuff, uint2* pPairBuffStartCurr, uint numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + uint2 sortedData = pHash[index]; + uint unsorted_indx = sortedData.y; + bt3DGrid3F1U bbMin = BT_GPU_FETCH(pAABB, unsorted_indx*2); + bt3DGrid3F1U bbMax = BT_GPU_FETCH(pAABB, unsorted_indx*2 + 1); + float4 pos; + pos.x = (bbMin.fx + bbMax.fx) * 0.5f; + pos.y = (bbMin.fy + bbMax.fy) * 0.5f; + pos.z = (bbMin.fz + bbMax.fz) * 0.5f; + // get address in grid + int3 gridPos = bt3DGrid_calcGridPos(pos); + // examine only neighbouring cells + for(int z=-1; z<=1; z++) { + for(int y=-1; y<=1; y++) { + for(int x=-1; x<=1; x++) { + findPairsInCell(gridPos + BT_GPU_make_int3(x, y, z), index, pHash, pCellStart, pAABB, pPairBuff, pPairBuffStartCurr, numBodies); + } + } + } +} // findOverlappingPairsD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void findPairsLargeD( bt3DGrid3F1U* pAABB, uint2* pHash, uint* pCellStart, uint* pPairBuff, + uint2* pPairBuffStartCurr, uint numBodies, uint numLarge) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + uint2 sortedData = pHash[index]; + uint unsorted_indx = sortedData.y; + bt3DGrid3F1U min0 = BT_GPU_FETCH(pAABB, unsorted_indx*2); + bt3DGrid3F1U max0 = BT_GPU_FETCH(pAABB, unsorted_indx*2 + 1); + uint handleIndex = min0.uw; + uint2 start_curr = pPairBuffStartCurr[handleIndex]; + uint start = start_curr.x; + uint curr = start_curr.y; + uint2 start_curr_next = pPairBuffStartCurr[handleIndex+1]; + uint curr_max = start_curr_next.x - start - 1; + for(uint i = 0; i < numLarge; i++) + { + uint indx2 = numBodies + i; + bt3DGrid3F1U min1 = BT_GPU_FETCH(pAABB, indx2*2); + bt3DGrid3F1U max1 = BT_GPU_FETCH(pAABB, indx2*2 + 1); + if(cudaTestAABBOverlap(min0, max0, min1, max1)) + { + uint k; + uint handleIndex2 = min1.uw; + for(k = 0; k < curr; k++) + { + uint old_pair = pPairBuff[start+k] & (~BT_3DGRID_PAIR_ANY_FLG); + if(old_pair == handleIndex2) + { + pPairBuff[start+k] |= BT_3DGRID_PAIR_FOUND_FLG; + break; + } + } + if(k == curr) + { + pPairBuff[start+curr] = handleIndex2 | BT_3DGRID_PAIR_NEW_FLG; + if(curr >= curr_max) + { // not a good solution, but let's avoid crash + break; + } + curr++; + } + } + } + pPairBuffStartCurr[handleIndex] = BT_GPU_make_uint2(start, curr); + return; +} // findPairsLargeD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void computePairCacheChangesD(uint* pPairBuff, uint2* pPairBuffStartCurr, + uint* pPairScan, bt3DGrid3F1U* pAABB, uint numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + bt3DGrid3F1U bbMin = pAABB[index * 2]; + uint handleIndex = bbMin.uw; + uint2 start_curr = pPairBuffStartCurr[handleIndex]; + uint start = start_curr.x; + uint curr = start_curr.y; + uint *pInp = pPairBuff + start; + uint num_changes = 0; + for(uint k = 0; k < curr; k++, pInp++) + { + //if(!((*pInp) & BT_3DGRID_PAIR_FOUND_FLG)) + if(((*pInp) & BT_3DGRID_PAIR_ANY_FLG)) + { + num_changes++; + } + } + pPairScan[index+1] = num_changes; +} // computePairCacheChangesD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void squeezeOverlappingPairBuffD(uint* pPairBuff, uint2* pPairBuffStartCurr, uint* pPairScan, + uint2* pPairOut, bt3DGrid3F1U* pAABB, uint numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + bt3DGrid3F1U bbMin = pAABB[index * 2]; + uint handleIndex = bbMin.uw; + uint2 start_curr = pPairBuffStartCurr[handleIndex]; + uint start = start_curr.x; + uint curr = start_curr.y; + uint* pInp = pPairBuff + start; + uint2* pOut = pPairOut + pPairScan[index+1]; + uint* pOut2 = pInp; + uint num = 0; + for(uint k = 0; k < curr; k++, pInp++) + { + if((*pInp) & BT_3DGRID_PAIR_ANY_FLG) + //if(!((*pInp) & BT_3DGRID_PAIR_FOUND_FLG)) + { + pOut->x = handleIndex; + pOut->y = (*pInp) & (~BT_3DGRID_PAIR_ANY_FLG); + + pOut++; + } + if((*pInp) & BT_3DGRID_PAIR_ANY_FLG) + { + *pOut2 = (*pInp) & (~BT_3DGRID_PAIR_ANY_FLG); + pOut2++; + num++; + } + } + pPairBuffStartCurr[handleIndex] = BT_GPU_make_uint2(start, num); +} // squeezeOverlappingPairBuffD() + + +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +// E N D O F K E R N E L F U N C T I O N S +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- + +extern "C" +{ + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(calcHashAABB)(bt3DGrid3F1U* pAABB, unsigned int* hash, unsigned int numBodies) +{ + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); + // execute the kernel + BT_GPU_EXECKERNEL(numBlocks, numThreads, calcHashAABBD, (pAABB, (uint2*)hash, numBodies)); + // check if kernel invocation generated an error + BT_GPU_CHECK_ERROR("calcHashAABBD kernel execution failed"); +} // calcHashAABB() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(findCellStart(unsigned int* hash, unsigned int* cellStart, unsigned int numBodies, unsigned int numCells)) +{ + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); + BT_GPU_SAFE_CALL(BT_GPU_Memset(cellStart, 0xffffffff, numCells*sizeof(uint))); + BT_GPU_EXECKERNEL(numBlocks, numThreads, findCellStartD, ((uint2*)hash, (uint*)cellStart, numBodies)); + BT_GPU_CHECK_ERROR("Kernel execution failed: findCellStartD"); +} // findCellStart() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(findOverlappingPairs(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies)) +{ +#if B_CUDA_USE_TEX + BT_GPU_SAFE_CALL(cudaBindTexture(0, pAABBTex, pAABB, numBodies * 2 * sizeof(bt3DGrid3F1U))); +#endif + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 64, numBlocks, numThreads); + BT_GPU_EXECKERNEL(numBlocks, numThreads, findOverlappingPairsD, (pAABB,(uint2*)pHash,(uint*)pCellStart,(uint*)pPairBuff,(uint2*)pPairBuffStartCurr,numBodies)); + BT_GPU_CHECK_ERROR("Kernel execution failed: bt_CudaFindOverlappingPairsD"); +#if B_CUDA_USE_TEX + BT_GPU_SAFE_CALL(cudaUnbindTexture(pAABBTex)); +#endif +} // findOverlappingPairs() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(findPairsLarge(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies, unsigned int numLarge)) +{ +#if B_CUDA_USE_TEX + BT_GPU_SAFE_CALL(cudaBindTexture(0, pAABBTex, pAABB, (numBodies+numLarge) * 2 * sizeof(bt3DGrid3F1U))); +#endif + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 64, numBlocks, numThreads); + BT_GPU_EXECKERNEL(numBlocks, numThreads, findPairsLargeD, (pAABB,(uint2*)pHash,(uint*)pCellStart,(uint*)pPairBuff,(uint2*)pPairBuffStartCurr,numBodies,numLarge)); + BT_GPU_CHECK_ERROR("Kernel execution failed: btCuda_findPairsLargeD"); +#if B_CUDA_USE_TEX + BT_GPU_SAFE_CALL(cudaUnbindTexture(pAABBTex)); +#endif +} // findPairsLarge() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(computePairCacheChanges(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, bt3DGrid3F1U* pAABB, unsigned int numBodies)) +{ + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); + BT_GPU_EXECKERNEL(numBlocks, numThreads, computePairCacheChangesD, ((uint*)pPairBuff,(uint2*)pPairBuffStartCurr,(uint*)pPairScan,pAABB,numBodies)); + BT_GPU_CHECK_ERROR("Kernel execution failed: btCudaComputePairCacheChangesD"); +} // computePairCacheChanges() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(squeezeOverlappingPairBuff(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, unsigned int* pPairOut, bt3DGrid3F1U* pAABB, unsigned int numBodies)) +{ + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); + BT_GPU_EXECKERNEL(numBlocks, numThreads, squeezeOverlappingPairBuffD, ((uint*)pPairBuff,(uint2*)pPairBuffStartCurr,(uint*)pPairScan,(uint2*)pPairOut,pAABB,numBodies)); + BT_GPU_CHECK_ERROR("Kernel execution failed: btCudaSqueezeOverlappingPairBuffD"); +} // btCuda_squeezeOverlappingPairBuff() + +//------------------------------------------------------------------------------------------------ + +} // extern "C" + +//------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------ diff --git a/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphaseSharedDefs.h b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphaseSharedDefs.h new file mode 100644 index 0000000..607bda7 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphaseSharedDefs.h @@ -0,0 +1,61 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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. +*/ + +//---------------------------------------------------------------------------------------- + +// Shared definitions for GPU-based 3D Grid collision detection broadphase + +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// Keep this file free from Bullet headers +// it is included into both CUDA and CPU code +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +//---------------------------------------------------------------------------------------- + +#ifndef BTGPU3DGRIDBROADPHASESHAREDDEFS_H +#define BTGPU3DGRIDBROADPHASESHAREDDEFS_H + +//---------------------------------------------------------------------------------------- + +#include "btGpu3DGridBroadphaseSharedTypes.h" + +//---------------------------------------------------------------------------------------- + +extern "C" +{ + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(calcHashAABB)(bt3DGrid3F1U* pAABB, unsigned int* hash, unsigned int numBodies); + +void BT_GPU_PREF(findCellStart)(unsigned int* hash, unsigned int* cellStart, unsigned int numBodies, unsigned int numCells); + +void BT_GPU_PREF(findOverlappingPairs)(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies); + +void BT_GPU_PREF(findPairsLarge)(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies, unsigned int numLarge); + +void BT_GPU_PREF(computePairCacheChanges)(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, bt3DGrid3F1U* pAABB, unsigned int numBodies); + +void BT_GPU_PREF(squeezeOverlappingPairBuff)(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, unsigned int* pPairOut, bt3DGrid3F1U* pAABB, unsigned int numBodies); + + +//---------------------------------------------------------------------------------------- + +} // extern "C" + +//---------------------------------------------------------------------------------------- + +#endif // BTGPU3DGRIDBROADPHASESHAREDDEFS_H + diff --git a/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphaseSharedTypes.h b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphaseSharedTypes.h new file mode 100644 index 0000000..5b2e65e --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpu3DGridBroadphaseSharedTypes.h @@ -0,0 +1,64 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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. +*/ + +//---------------------------------------------------------------------------------------- + +// Shared definitions for GPU-based 3D Grid collision detection broadphase + +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// Keep this file free from Bullet headers +// it is included into both CUDA and CPU code +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +//---------------------------------------------------------------------------------------- + +#ifndef BTGPU3DGRIDBROADPHASESHAREDTYPES_H +#define BTGPU3DGRIDBROADPHASESHAREDTYPES_H + +//---------------------------------------------------------------------------------------- + +#define BT_3DGRID_PAIR_FOUND_FLG (0x40000000) +#define BT_3DGRID_PAIR_NEW_FLG (0x20000000) +#define BT_3DGRID_PAIR_ANY_FLG (BT_3DGRID_PAIR_FOUND_FLG | BT_3DGRID_PAIR_NEW_FLG) + +//---------------------------------------------------------------------------------------- + +struct bt3DGridBroadphaseParams +{ + unsigned int m_gridSizeX; + unsigned int m_gridSizeY; + unsigned int m_gridSizeZ; + unsigned int m_numCells; + float m_invCellSizeX; + float m_invCellSizeY; + float m_invCellSizeZ; + unsigned int m_numBodies; + unsigned int m_maxBodiesPerCell; +}; + +//---------------------------------------------------------------------------------------- + +struct bt3DGrid3F1U +{ + float fx; + float fy; + float fz; + unsigned int uw; +}; + +//---------------------------------------------------------------------------------------- + +#endif // BTGPU3DGRIDBROADPHASESHAREDTYPES_H + diff --git a/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpuDefines.h b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpuDefines.h new file mode 100644 index 0000000..f9315ab --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/3dGridBroadphase/Shared/btGpuDefines.h @@ -0,0 +1,211 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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. +*/ + + + +// definitions for "GPU on CPU" code + + +#ifndef BT_GPU_DEFINES_H +#define BT_GPU_DEFINES_H + +typedef unsigned int uint; + +struct int2 +{ + int x, y; +}; + +struct uint2 +{ + unsigned int x, y; +}; + +struct int3 +{ + int x, y, z; +}; + +struct uint3 +{ + unsigned int x, y, z; +}; + +struct float4 +{ + float x, y, z, w; +}; + +struct float3 +{ + float x, y, z; +}; + + +#define BT_GPU___device__ inline +#define BT_GPU___devdata__ +#define BT_GPU___constant__ +#define BT_GPU_max(a, b) ((a) > (b) ? (a) : (b)) +#define BT_GPU_min(a, b) ((a) < (b) ? (a) : (b)) +#define BT_GPU_params s3DGridBroadphaseParams +#define BT_GPU___mul24(a, b) ((a)*(b)) +#define BT_GPU___global__ inline +#define BT_GPU___shared__ static +#define BT_GPU___syncthreads() +#define CUDART_PI_F SIMD_PI + +static inline uint2 bt3dGrid_make_uint2(unsigned int x, unsigned int y) +{ + uint2 t; t.x = x; t.y = y; return t; +} +#define BT_GPU_make_uint2(x, y) bt3dGrid_make_uint2(x, y) + +static inline int3 bt3dGrid_make_int3(int x, int y, int z) +{ + int3 t; t.x = x; t.y = y; t.z = z; return t; +} +#define BT_GPU_make_int3(x, y, z) bt3dGrid_make_int3(x, y, z) + +static inline float3 bt3dGrid_make_float3(float x, float y, float z) +{ + float3 t; t.x = x; t.y = y; t.z = z; return t; +} +#define BT_GPU_make_float3(x, y, z) bt3dGrid_make_float3(x, y, z) + +static inline float3 bt3dGrid_make_float34(float4 f) +{ + float3 t; t.x = f.x; t.y = f.y; t.z = f.z; return t; +} +#define BT_GPU_make_float34(f) bt3dGrid_make_float34(f) + +static inline float3 bt3dGrid_make_float31(float f) +{ + float3 t; t.x = t.y = t.z = f; return t; +} +#define BT_GPU_make_float31(x) bt3dGrid_make_float31(x) + +static inline float4 bt3dGrid_make_float42(float3 v, float f) +{ + float4 t; t.x = v.x; t.y = v.y; t.z = v.z; t.w = f; return t; +} +#define BT_GPU_make_float42(a, b) bt3dGrid_make_float42(a, b) + +static inline float4 bt3dGrid_make_float44(float a, float b, float c, float d) +{ + float4 t; t.x = a; t.y = b; t.z = c; t.w = d; return t; +} +#define BT_GPU_make_float44(a, b, c, d) bt3dGrid_make_float44(a, b, c, d) + +inline int3 operator+(int3 a, int3 b) +{ + return bt3dGrid_make_int3(a.x + b.x, a.y + b.y, a.z + b.z); +} + +inline float4 operator+(const float4& a, const float4& b) +{ + float4 r; r.x = a.x+b.x; r.y = a.y+b.y; r.z = a.z+b.z; r.w = a.w+b.w; return r; +} +inline float4 operator*(const float4& a, float fact) +{ + float4 r; r.x = a.x*fact; r.y = a.y*fact; r.z = a.z*fact; r.w = a.w*fact; return r; +} +inline float4 operator*(float fact, float4& a) +{ + return (a * fact); +} +inline float4& operator*=(float4& a, float fact) +{ + a = fact * a; + return a; +} +inline float4& operator+=(float4& a, const float4& b) +{ + a = a + b; + return a; +} + +inline float3 operator+(const float3& a, const float3& b) +{ + float3 r; r.x = a.x+b.x; r.y = a.y+b.y; r.z = a.z+b.z; return r; +} +inline float3 operator-(const float3& a, const float3& b) +{ + float3 r; r.x = a.x-b.x; r.y = a.y-b.y; r.z = a.z-b.z; return r; +} +static inline float bt3dGrid_dot(float3& a, float3& b) +{ + return a.x*b.x+a.y*b.y+a.z*b.z; +} +#define BT_GPU_dot(a,b) bt3dGrid_dot(a,b) + +static inline float bt3dGrid_dot4(float4& a, float4& b) +{ + return a.x*b.x+a.y*b.y+a.z*b.z+a.w*b.w; +} +#define BT_GPU_dot4(a,b) bt3dGrid_dot4(a,b) + +static inline float3 bt3dGrid_cross(const float3& a, const float3& b) +{ + float3 r; r.x = a.y*b.z-a.z*b.y; r.y = -a.x*b.z+a.z*b.x; r.z = a.x*b.y-a.y*b.x; return r; +} +#define BT_GPU_cross(a,b) bt3dGrid_cross(a,b) + + +inline float3 operator*(const float3& a, float fact) +{ + float3 r; r.x = a.x*fact; r.y = a.y*fact; r.z = a.z*fact; return r; +} + + +inline float3& operator+=(float3& a, const float3& b) +{ + a = a + b; + return a; +} +inline float3& operator-=(float3& a, const float3& b) +{ + a = a - b; + return a; +} +inline float3& operator*=(float3& a, float fact) +{ + a = a * fact; + return a; +} +inline float3 operator-(const float3& v) +{ + float3 r; r.x = -v.x; r.y = -v.y; r.z = -v.z; return r; +} + + +#define BT_GPU_FETCH(a, b) a[b] +#define BT_GPU_FETCH4(a, b) a[b] +#define BT_GPU_PREF(func) btGpu_##func +#define BT_GPU_SAFE_CALL(func) func +#define BT_GPU_Memset memset +#define BT_GPU_MemcpyToSymbol(a, b, c) memcpy(&a, b, c) +#define BT_GPU_BindTexture(a, b, c, d) +#define BT_GPU_UnbindTexture(a) + +static uint2 s_blockIdx, s_blockDim, s_threadIdx; +#define BT_GPU_blockIdx s_blockIdx +#define BT_GPU_blockDim s_blockDim +#define BT_GPU_threadIdx s_threadIdx +#define BT_GPU_EXECKERNEL(numb, numt, kfunc, args) {s_blockDim.x=numt;for(int nb=0;nb +#else +#include +#endif +#else +#ifdef USE_MINICL +#include +#else +#include +#ifdef _WIN32 +#include "CL/cl_gl.h" +#endif //_WIN32 +#endif +#endif //__APPLE__ + +#include +#include +#define oclCHECKERROR(a, b) if((a)!=(b)) { printf("OCL Error : %d\n", (a)); assert((a) == (b)); } + + +#endif //BT_OPENCL_INCLUDE_H + diff --git a/Extras/RigidBodyGpuPipeline/opencl/basic_initialize/btOpenCLUtils.cpp b/Extras/RigidBodyGpuPipeline/opencl/basic_initialize/btOpenCLUtils.cpp new file mode 100644 index 0000000..e278401 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/basic_initialize/btOpenCLUtils.cpp @@ -0,0 +1,731 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006 - 2011 Sony Computer Entertainment Inc. + +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. +*/ + +//original author: Roman Ponomarev +//cleanup by Erwin Coumans + +#include + +#include "btOpenCLUtils.h" +#include +#include + +#define BT_MAX_CL_DEVICES 16 //who needs 16 devices? + +#ifdef _WIN32 +#include +#include + +#define btAssert assert +#endif + +//Set the preferred platform vendor using the OpenCL SDK +static char* spPlatformVendor = +#if defined(CL_PLATFORM_MINI_CL) +"MiniCL, SCEA"; +#elif defined(CL_PLATFORM_AMD) +"Advanced Micro Devices, Inc."; +#elif defined(CL_PLATFORM_NVIDIA) +"NVIDIA Corporation"; +#elif defined(CL_PLATFORM_INTEL) +"Intel(R) Corporation"; +#else +"Unknown Vendor"; +#endif + +#ifndef CL_PLATFORM_MINI_CL +#ifdef _WIN32 +#include "CL/cl_gl.h" +#endif //_WIN32 +#endif + +int btOpenCLUtils::getNumPlatforms(cl_int* pErrNum) +{ + cl_uint numPlatforms=0; + cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms); + + if(ciErrNum != CL_SUCCESS) + { + if(pErrNum != NULL) + *pErrNum = ciErrNum; + } + return numPlatforms; +} + +const char* btOpenCLUtils::getSdkVendorName() +{ + return spPlatformVendor; +} + +cl_platform_id btOpenCLUtils::getPlatform(int platformIndex, cl_int* pErrNum) +{ + cl_platform_id platform = 0; + + cl_uint numPlatforms; + cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms); + + if (platformIndex>=0 && platformIndex=0 && preferredDeviceIndex 0) + { + cl_platform_id* platforms = new cl_platform_id[numPlatforms]; + ciErrNum = clGetPlatformIDs(numPlatforms, platforms, NULL); + if(ciErrNum != CL_SUCCESS) + { + if(pErrNum != NULL) *pErrNum = ciErrNum; + return NULL; + } + int i; + + + for ( i = 0; i < numPlatforms; ++i) + { + char pbuf[128]; + ciErrNum = clGetPlatformInfo( platforms[i], + CL_PLATFORM_VENDOR, + sizeof(pbuf), + pbuf, + NULL); + if(ciErrNum != CL_SUCCESS) + { + if(pErrNum != NULL) *pErrNum = ciErrNum; + return NULL; + } + + if (preferredPlatformIndex>=0 && i==preferredPlatformIndex) + { + cl_platform_id tmpPlatform = platforms[0]; + platforms[0] = platforms[i]; + platforms[i] = tmpPlatform; + break; + } else + { + if(!strcmp(pbuf, spPlatformVendor)) + { + cl_platform_id tmpPlatform = platforms[0]; + platforms[0] = platforms[i]; + platforms[i] = tmpPlatform; + break; + } + } + } + + for (i = 0; i < numPlatforms; ++i) + { + cl_platform_id platform = platforms[i]; + assert(platform); + + retContext = btOpenCLUtils::createContextFromPlatform(platform,deviceType,pErrNum,pGLContext,pGLDC,preferredDeviceIndex); + + if (retContext) + { +// printf("OpenCL platform details:\n"); + btOpenCLPlatformInfo platformInfo; + + btOpenCLUtils::getPlatformInfo(platform, platformInfo); + + printf(" CL_PLATFORM_VENDOR: \t\t\t%s\n",platformInfo.m_platformVendor); + printf(" CL_PLATFORM_NAME: \t\t\t%s\n",platformInfo.m_platformName); + printf(" CL_PLATFORM_VERSION: \t\t\t%s\n",platformInfo.m_platformVersion); + + break; + } + } + + delete[] platforms; + } + return retContext; +} + + +////////////////////////////////////////////////////////////////////////////// +//! Gets the id of the nth device from the context +//! +//! @return the id or -1 when out of range +//! @param cxMainContext OpenCL context +//! @param device_idx index of the device of interest +////////////////////////////////////////////////////////////////////////////// +cl_device_id btOpenCLUtils::getDevice(cl_context cxMainContext, int deviceIndex) +{ + size_t szParmDataBytes; + cl_device_id* cdDevices; + + // get the list of devices associated with context + clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, 0, NULL, &szParmDataBytes); + + if( szParmDataBytes / sizeof(cl_device_id) < deviceIndex ) { + return (cl_device_id)-1; + } + + cdDevices = (cl_device_id*) malloc(szParmDataBytes); + + clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, szParmDataBytes, cdDevices, NULL); + + cl_device_id device = cdDevices[deviceIndex]; + free(cdDevices); + + return device; +} + +int btOpenCLUtils::getNumDevices(cl_context cxMainContext) +{ + size_t szParamDataBytes; + clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, 0, NULL, &szParamDataBytes); + int device_count = (int) szParamDataBytes/ sizeof(cl_device_id); + return device_count; +} + +void btOpenCLUtils::printDeviceInfo(cl_device_id device) +{ + btOpenCLDeviceInfo info; + getDeviceInfo(device,info); + + printf(" CL_DEVICE_NAME: \t\t\t%s\n", info.m_deviceName); + printf(" CL_DEVICE_VENDOR: \t\t\t%s\n", info.m_deviceVendor); + printf(" CL_DRIVER_VERSION: \t\t\t%s\n", info.m_driverVersion); + + if( info.m_deviceType & CL_DEVICE_TYPE_CPU ) + printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_CPU"); + if( info.m_deviceType & CL_DEVICE_TYPE_GPU ) + printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_GPU"); + if( info.m_deviceType & CL_DEVICE_TYPE_ACCELERATOR ) + printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_ACCELERATOR"); + if( info.m_deviceType & CL_DEVICE_TYPE_DEFAULT ) + printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_DEFAULT"); + + printf(" CL_DEVICE_MAX_COMPUTE_UNITS:\t\t%u\n", info.m_computeUnits); + printf(" CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:\t%u\n", info.m_workitemDims); + printf(" CL_DEVICE_MAX_WORK_ITEM_SIZES:\t%u / %u / %u \n", info.m_workItemSize[0], info.m_workItemSize[1], info.m_workItemSize[2]); + printf(" CL_DEVICE_MAX_WORK_GROUP_SIZE:\t%u\n", info.m_workgroupSize); + printf(" CL_DEVICE_MAX_CLOCK_FREQUENCY:\t%u MHz\n", info.m_clockFrequency); + printf(" CL_DEVICE_ADDRESS_BITS:\t\t%u\n", info.m_addressBits); + printf(" CL_DEVICE_MAX_MEM_ALLOC_SIZE:\t\t%u MByte\n", (unsigned int)(info.m_maxMemAllocSize/ (1024 * 1024))); + printf(" CL_DEVICE_GLOBAL_MEM_SIZE:\t\t%u MByte\n", (unsigned int)(info.m_globalMemSize/ (1024 * 1024))); + printf(" CL_DEVICE_ERROR_CORRECTION_SUPPORT:\t%s\n", info.m_errorCorrectionSupport== CL_TRUE ? "yes" : "no"); + printf(" CL_DEVICE_LOCAL_MEM_TYPE:\t\t%s\n", info.m_localMemType == 1 ? "local" : "global"); + printf(" CL_DEVICE_LOCAL_MEM_SIZE:\t\t%u KByte\n", (unsigned int)(info.m_localMemSize / 1024)); + printf(" CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:\t%u KByte\n", (unsigned int)(info.m_constantBufferSize / 1024)); + if( info.m_queueProperties & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE ) + printf(" CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE"); + if( info.m_queueProperties & CL_QUEUE_PROFILING_ENABLE ) + printf(" CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_PROFILING_ENABLE"); + + printf(" CL_DEVICE_IMAGE_SUPPORT:\t\t%u\n", info.m_imageSupport); + + printf(" CL_DEVICE_MAX_READ_IMAGE_ARGS:\t%u\n", info.m_maxReadImageArgs); + printf(" CL_DEVICE_MAX_WRITE_IMAGE_ARGS:\t%u\n", info.m_maxWriteImageArgs); + printf("\n CL_DEVICE_IMAGE "); + printf("\t\t\t2D_MAX_WIDTH\t %u\n", info.m_image2dMaxWidth); + printf("\t\t\t\t\t2D_MAX_HEIGHT\t %u\n", info.m_image2dMaxHeight); + printf("\t\t\t\t\t3D_MAX_WIDTH\t %u\n", info.m_image3dMaxWidth); + printf("\t\t\t\t\t3D_MAX_HEIGHT\t %u\n", info.m_image3dMaxHeight); + printf("\t\t\t\t\t3D_MAX_DEPTH\t %u\n", info.m_image3dMaxDepth); + if (info.m_deviceExtensions != 0) + printf("\n CL_DEVICE_EXTENSIONS:%s\n",info.m_deviceExtensions); + else + printf(" CL_DEVICE_EXTENSIONS: None\n"); + printf(" CL_DEVICE_PREFERRED_VECTOR_WIDTH_\t"); + printf("CHAR %u, SHORT %u, INT %u,LONG %u, FLOAT %u, DOUBLE %u\n\n\n", + info.m_vecWidthChar, info.m_vecWidthShort, info.m_vecWidthInt, info.m_vecWidthLong,info.m_vecWidthFloat, info.m_vecWidthDouble); + + +} + +void btOpenCLUtils::getDeviceInfo(cl_device_id device, btOpenCLDeviceInfo& info) +{ + + // CL_DEVICE_NAME + clGetDeviceInfo(device, CL_DEVICE_NAME, BT_MAX_STRING_LENGTH, &info.m_deviceName, NULL); + + // CL_DEVICE_VENDOR + clGetDeviceInfo(device, CL_DEVICE_VENDOR, BT_MAX_STRING_LENGTH, &info.m_deviceVendor, NULL); + + // CL_DRIVER_VERSION + clGetDeviceInfo(device, CL_DRIVER_VERSION, BT_MAX_STRING_LENGTH, &info.m_driverVersion, NULL); + + // CL_DEVICE_INFO + clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(cl_device_type), &info.m_deviceType, NULL); + + // CL_DEVICE_MAX_COMPUTE_UNITS + clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(info.m_computeUnits), &info.m_computeUnits, NULL); + + // CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS + clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(info.m_workitemDims), &info.m_workitemDims, NULL); + + // CL_DEVICE_MAX_WORK_ITEM_SIZES + clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(info.m_workItemSize), &info.m_workItemSize, NULL); + + // CL_DEVICE_MAX_WORK_GROUP_SIZE + clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(info.m_workgroupSize), &info.m_workgroupSize, NULL); + + // CL_DEVICE_MAX_CLOCK_FREQUENCY + clGetDeviceInfo(device, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(info.m_clockFrequency), &info.m_clockFrequency, NULL); + + // CL_DEVICE_ADDRESS_BITS + clGetDeviceInfo(device, CL_DEVICE_ADDRESS_BITS, sizeof(info.m_addressBits), &info.m_addressBits, NULL); + + // CL_DEVICE_MAX_MEM_ALLOC_SIZE + clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(info.m_maxMemAllocSize), &info.m_maxMemAllocSize, NULL); + + // CL_DEVICE_GLOBAL_MEM_SIZE + clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(info.m_globalMemSize), &info.m_globalMemSize, NULL); + + // CL_DEVICE_ERROR_CORRECTION_SUPPORT + clGetDeviceInfo(device, CL_DEVICE_ERROR_CORRECTION_SUPPORT, sizeof(info.m_errorCorrectionSupport), &info.m_errorCorrectionSupport, NULL); + + // CL_DEVICE_LOCAL_MEM_TYPE + clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_TYPE, sizeof(info.m_localMemType), &info.m_localMemType, NULL); + + // CL_DEVICE_LOCAL_MEM_SIZE + clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(info.m_localMemSize), &info.m_localMemSize, NULL); + + // CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE + clGetDeviceInfo(device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(info.m_constantBufferSize), &info.m_constantBufferSize, NULL); + + // CL_DEVICE_QUEUE_PROPERTIES + clGetDeviceInfo(device, CL_DEVICE_QUEUE_PROPERTIES, sizeof(info.m_queueProperties), &info.m_queueProperties, NULL); + + // CL_DEVICE_IMAGE_SUPPORT + clGetDeviceInfo(device, CL_DEVICE_IMAGE_SUPPORT, sizeof(info.m_imageSupport), &info.m_imageSupport, NULL); + + // CL_DEVICE_MAX_READ_IMAGE_ARGS + clGetDeviceInfo(device, CL_DEVICE_MAX_READ_IMAGE_ARGS, sizeof(info.m_maxReadImageArgs), &info.m_maxReadImageArgs, NULL); + + // CL_DEVICE_MAX_WRITE_IMAGE_ARGS + clGetDeviceInfo(device, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, sizeof(info.m_maxWriteImageArgs), &info.m_maxWriteImageArgs, NULL); + + // CL_DEVICE_IMAGE2D_MAX_WIDTH, CL_DEVICE_IMAGE2D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_WIDTH, CL_DEVICE_IMAGE3D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_DEPTH + clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(size_t), &info.m_image2dMaxWidth, NULL); + clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(size_t), &info.m_image2dMaxHeight, NULL); + clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof(size_t), &info.m_image3dMaxWidth, NULL); + clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof(size_t), &info.m_image3dMaxHeight, NULL); + clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(size_t), &info.m_image3dMaxDepth, NULL); + + // CL_DEVICE_EXTENSIONS: get device extensions, and if any then parse & log the string onto separate lines + clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, BT_MAX_STRING_LENGTH, &info.m_deviceExtensions, NULL); + + // CL_DEVICE_PREFERRED_VECTOR_WIDTH_ + clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &info.m_vecWidthChar, NULL); + clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, sizeof(cl_uint), &info.m_vecWidthShort, NULL); + clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, sizeof(cl_uint), &info.m_vecWidthInt, NULL); + clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, sizeof(cl_uint), &info.m_vecWidthLong, NULL); + clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, sizeof(cl_uint), &info.m_vecWidthFloat, NULL); + clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, sizeof(cl_uint), &info.m_vecWidthDouble, NULL); +} + +static const char* strip2(const char* name, const char* pattern) +{ + size_t const patlen = strlen(pattern); + size_t patcnt = 0; + const char * oriptr; + const char * patloc; + // find how many times the pattern occurs in the original string + for (oriptr = name; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen) + { + patcnt++; + } + return oriptr; +} + +cl_program btOpenCLUtils::compileCLProgramFromString(cl_context clContext, cl_device_id device, const char* kernelSource, cl_int* pErrNum, const char* additionalMacros , const char* clFileNameForCaching) +{ + + cl_program m_cpProgram=0; + cl_int status; + + char binaryFileName[522]; + + if (clFileNameForCaching) + { + + char deviceName[256]; + char driverVersion[256]; + clGetDeviceInfo(device, CL_DEVICE_NAME, 256, &deviceName, NULL); + clGetDeviceInfo(device, CL_DRIVER_VERSION, 256, &driverVersion, NULL); + + + const char* strippedName = strip2(clFileNameForCaching,"\\"); + strippedName = strip2(strippedName,"/"); + + sprintf_s(binaryFileName,"cache/%s.%s.%s.bin",strippedName, deviceName,driverVersion ); + //printf("searching for %s\n", binaryFileName); + + bool fileUpToDate = false; + bool binaryFileValid=false; + + FILETIME modtimeBinary; + +#ifdef _WIN32 + CreateDirectory("cache",0); + { + + HANDLE binaryFileHandle = CreateFile(binaryFileName,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); + if (binaryFileHandle ==INVALID_HANDLE_VALUE) + { + DWORD errorCode; + errorCode = GetLastError(); + switch (errorCode) + { + case ERROR_FILE_NOT_FOUND: + { + printf("\nCached file not found %s\n", binaryFileName); + break; + } + case ERROR_PATH_NOT_FOUND: + { + printf("\nCached file path not found %s\n", binaryFileName); + break; + } + default: + { + printf("\nFailed reading cached file with errorCode = %d\n", errorCode); + } + } + } else + { + if (GetFileTime(binaryFileHandle, NULL, NULL, &modtimeBinary)==0) + { + DWORD errorCode; + errorCode = GetLastError(); + printf("\nGetFileTime errorCode = %d\n", errorCode); + } else + { + binaryFileValid = true; + } + CloseHandle(binaryFileHandle); + } + + if (binaryFileValid) + { + HANDLE srcFileHandle = CreateFile(clFileNameForCaching,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); + if (srcFileHandle!=INVALID_HANDLE_VALUE) + { + FILETIME modtimeSrc; + if (GetFileTime(srcFileHandle, NULL, NULL, &modtimeSrc)==0) + { + DWORD errorCode; + errorCode = GetLastError(); + printf("\nGetFileTime errorCode = %d\n", errorCode); + } + if ( ( modtimeSrc.dwHighDateTime < modtimeBinary.dwHighDateTime) + ||(( modtimeSrc.dwHighDateTime == modtimeBinary.dwHighDateTime)&&(modtimeSrc.dwLowDateTime <= modtimeBinary.dwLowDateTime))) + { + fileUpToDate=true; + } else + { + printf("\nCached binary file out-of-date (%s)\n",binaryFileName); + } + CloseHandle(srcFileHandle); + } + else + { +#ifdef _DEBUG + DWORD errorCode; + errorCode = GetLastError(); + switch (errorCode) + { + case ERROR_FILE_NOT_FOUND: + { + printf("\nSrc file not found %s\n", clFileNameForCaching); + break; + } + case ERROR_PATH_NOT_FOUND: + { + printf("\nSrc path not found %s\n", clFileNameForCaching); + break; + } + default: + { + printf("\nnSrc file reading errorCode = %d\n", errorCode); + } + } + + //we should make sure the src file exists so we can verify the timestamp with binary + assert(0); +#else + //if we cannot find the source, assume it is OK in release builds + fileUpToDate = true; +#endif + } + } + + + } + + if( fileUpToDate) + { + FILE* file = fopen(binaryFileName, "rb"); + if (file) + { + fseek( file, 0L, SEEK_END ); + size_t binarySize = ftell( file ); + rewind( file ); + char* binary = new char[binarySize]; + fread( binary, sizeof(char), binarySize, file ); + fclose( file ); + + m_cpProgram = clCreateProgramWithBinary( clContext, 1,&device, &binarySize, (const unsigned char**)&binary, 0, &status ); + btAssert( status == CL_SUCCESS ); + status = clBuildProgram( m_cpProgram, 1, &device, additionalMacros, 0, 0 ); + btAssert( status == CL_SUCCESS ); + + if( status != CL_SUCCESS ) + { + char *build_log; + size_t ret_val_size; + clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size); + build_log = new char[ret_val_size+1]; + clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL); + build_log[ret_val_size] = '\0'; + printf("%s\n", build_log); + delete build_log; + btAssert(0); + m_cpProgram = 0; + } + delete[] binary; + } + } +#endif //_WIN32 + + } + + if (!m_cpProgram) + { + cl_kernel kernel; + cl_int localErrNum; + size_t program_length = strlen(kernelSource); + + m_cpProgram = clCreateProgramWithSource(clContext, 1, (const char**)&kernelSource, &program_length, &localErrNum); + if (localErrNum!= CL_SUCCESS) + { + if (pErrNum) + *pErrNum = localErrNum; + return 0; + } + + // Build the program with 'mad' Optimization option + + + #ifdef MAC + char* flags = "-cl-mad-enable -DMAC -DGUID_ARG"; + #else + //const char* flags = "-DGUID_ARG= -fno-alias"; + const char* flags = "-DGUID_ARG= "; + #endif + + char* compileFlags = new char[strlen(additionalMacros) + strlen(flags) + 5]; + sprintf(compileFlags, "%s %s", flags, additionalMacros); + localErrNum = clBuildProgram(m_cpProgram, 1, &device, compileFlags, NULL, NULL); + if (localErrNum!= CL_SUCCESS) + { + char *build_log; + size_t ret_val_size; + clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size); + build_log = new char[ret_val_size+1]; + clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL); + + // to be carefully, terminate with \0 + // there's no information in the reference whether the string is 0 terminated or not + build_log[ret_val_size] = '\0'; + + + printf("Error in clBuildProgram, Line %u in file %s, Log: \n%s\n !!!\n\n", __LINE__, __FILE__, build_log); + delete[] build_log; + if (pErrNum) + *pErrNum = localErrNum; + return 0; + } + + if( clFileNameForCaching ) + { // write to binary + + cl_uint numAssociatedDevices; + status = clGetProgramInfo( m_cpProgram, CL_PROGRAM_NUM_DEVICES, sizeof(cl_uint), &numAssociatedDevices, 0 ); + btAssert( status == CL_SUCCESS ); + if (numAssociatedDevices==1) + { + + size_t binarySize; + status = clGetProgramInfo( m_cpProgram, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &binarySize, 0 ); + btAssert( status == CL_SUCCESS ); + + char* binary = new char[binarySize]; + + status = clGetProgramInfo( m_cpProgram, CL_PROGRAM_BINARIES, sizeof(char*), &binary, 0 ); + btAssert( status == CL_SUCCESS ); + + { + FILE* file = fopen(binaryFileName, "wb"); + if (file) + { + fwrite( binary, sizeof(char), binarySize, file ); + fclose( file ); + } else + { + printf("cannot write file %s\n", binaryFileName); + } + } + + delete [] binary; + } + } + delete [] compileFlags; + } + + return m_cpProgram; +} + + +cl_kernel btOpenCLUtils::compileCLKernelFromString(cl_context clContext, cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum, cl_program prog, const char* additionalMacros ) +{ + printf("compiling kernel %s ",kernelName); + cl_kernel kernel; + cl_int localErrNum; + size_t program_length = strlen(kernelSource); + + + cl_program m_cpProgram = prog; + if (!m_cpProgram) + { + m_cpProgram = compileCLProgramFromString(clContext,device,kernelSource,pErrNum, additionalMacros); + } + + + // Create the kernel + kernel = clCreateKernel(m_cpProgram, kernelName, &localErrNum); + if (localErrNum != CL_SUCCESS) + { + printf("Error in clCreateKernel, Line %u in file %s, cannot find kernel function %s !!!\n\n", __LINE__, __FILE__, kernelName); + if (pErrNum) + *pErrNum = localErrNum; + return 0; + } + + if (!prog && m_cpProgram) + { + clReleaseProgram(m_cpProgram); + } + printf("ready. \n"); + + + if (pErrNum) + *pErrNum = CL_SUCCESS; + return kernel; + +} diff --git a/Extras/RigidBodyGpuPipeline/opencl/basic_initialize/btOpenCLUtils.h b/Extras/RigidBodyGpuPipeline/opencl/basic_initialize/btOpenCLUtils.h new file mode 100644 index 0000000..4e41b41 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/basic_initialize/btOpenCLUtils.h @@ -0,0 +1,104 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006 - 2011 Sony Computer Entertainment Inc. + +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. +*/ + +//original author: Roman Ponomarev +//cleanup by Erwin Coumans + +#ifndef BT_OPENCL_UTILS_H +#define BT_OPENCL_UTILS_H + +#include "btOpenCLInclude.h" + + +#define BT_MAX_STRING_LENGTH 1024 + +struct btOpenCLDeviceInfo +{ + char m_deviceName[BT_MAX_STRING_LENGTH]; + char m_deviceVendor[BT_MAX_STRING_LENGTH]; + char m_driverVersion[BT_MAX_STRING_LENGTH]; + char m_deviceExtensions[BT_MAX_STRING_LENGTH]; + + cl_device_type m_deviceType; + cl_uint m_computeUnits; + size_t m_workitemDims; + size_t m_workItemSize[3]; + size_t m_image2dMaxWidth; + size_t m_image2dMaxHeight; + size_t m_image3dMaxWidth; + size_t m_image3dMaxHeight; + size_t m_image3dMaxDepth; + size_t m_workgroupSize; + cl_uint m_clockFrequency; + cl_ulong m_constantBufferSize; + cl_ulong m_localMemSize; + cl_ulong m_globalMemSize; + cl_bool m_errorCorrectionSupport; + cl_device_local_mem_type m_localMemType; + cl_uint m_maxReadImageArgs; + cl_uint m_maxWriteImageArgs; + + + + cl_uint m_addressBits; + cl_ulong m_maxMemAllocSize; + cl_command_queue_properties m_queueProperties; + cl_bool m_imageSupport; + cl_uint m_vecWidthChar; + cl_uint m_vecWidthShort; + cl_uint m_vecWidthInt; + cl_uint m_vecWidthLong; + cl_uint m_vecWidthFloat; + cl_uint m_vecWidthDouble; + +}; + +struct btOpenCLPlatformInfo +{ + char m_platformVendor[BT_MAX_STRING_LENGTH]; + char m_platformName[BT_MAX_STRING_LENGTH]; + char m_platformVersion[BT_MAX_STRING_LENGTH]; +}; + +class btOpenCLUtils +{ +public: + + /// CL Context optionally takes a GL context. This is a generic type because we don't really want this code + /// to have to understand GL types. It is a HGLRC in _WIN32 or a GLXContext otherwise. + static cl_context createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx = 0, void* pGLDC = 0, int preferredDeviceIndex = -1, int preferredPlatformIndex= - 1); + + static int getNumDevices(cl_context cxMainContext); + static cl_device_id getDevice(cl_context cxMainContext, int nr); + static void getDeviceInfo(cl_device_id device, btOpenCLDeviceInfo& info); + static void printDeviceInfo(cl_device_id device); + + static cl_kernel compileCLKernelFromString( cl_context clContext,cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum=0, cl_program prog=0,const char* additionalMacros = "" ); + + //optional + static cl_program compileCLProgramFromString( cl_context clContext,cl_device_id device, const char* kernelSource, cl_int* pErrNum=0,const char* additionalMacros = "" , const char* srcFileNameForCaching=0); + + //the following optional APIs provide access using specific platform information + static int getNumPlatforms(cl_int* pErrNum=0); + ///get the nr'th platform, where nr is in the range [0..getNumPlatforms) + static cl_platform_id getPlatform(int nr, cl_int* pErrNum=0); + static void getPlatformInfo(cl_platform_id platform, btOpenCLPlatformInfo& platformInfo); + static const char* getSdkVendorName(); + static cl_context createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx = 0, void* pGLDC = 0,int preferredDeviceIndex = -1, int preferredPlatformIndex= -1); +}; + + + +#endif // BT_OPENCL_UTILS_H diff --git a/Extras/RigidBodyGpuPipeline/opencl/basic_initialize/main.cpp b/Extras/RigidBodyGpuPipeline/opencl/basic_initialize/main.cpp new file mode 100644 index 0000000..2890d7d --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/basic_initialize/main.cpp @@ -0,0 +1,92 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +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. +*/ + +///original author: Erwin Coumans + +#include "btOpenCLUtils.h" +#include + +cl_context g_cxMainContext; +cl_command_queue g_cqCommandQue; + + + +int main(int argc, char* argv[]) +{ + int ciErrNum = 0; + + cl_device_type deviceType = CL_DEVICE_TYPE_ALL; + const char* vendorSDK = btOpenCLUtils::getSdkVendorName(); + + printf("This program was compiled using the %s OpenCL SDK\n",vendorSDK); + int numPlatforms = btOpenCLUtils::getNumPlatforms(); + printf("Num Platforms = %d\n", numPlatforms); + + for (int i=0;i=0) + { + btAABBCL minAabb = plocalShapeAABB[shapeIndex*2]; + btAABBCL maxAabb = plocalShapeAABB[shapeIndex*2+1]; + + float4 halfExtents = ((float4)(maxAabb.fx - minAabb.fx,maxAabb.fy - minAabb.fy,maxAabb.fz - minAabb.fz,0.f))*0.5f; + + Matrix3x3 abs_b = qtGetRotationMatrix(orientation); + float4 extent = (float4) ( dot(abs_b.m_row[0],halfExtents),dot(abs_b.m_row[1],halfExtents),dot(abs_b.m_row[2],halfExtents),0.f); + + + pAABB[nodeID*2].fx = position.x-extent.x; + pAABB[nodeID*2].fy = position.y-extent.y; + pAABB[nodeID*2].fz = position.z-extent.z; + pAABB[nodeID*2].uw = nodeID; + + pAABB[nodeID*2+1].fx = position.x+extent.x; + pAABB[nodeID*2+1].fy = position.y+extent.y; + pAABB[nodeID*2+1].fz = position.z+extent.z; + pAABB[nodeID*2+1].uw = nodeID; + } + } +} + + +__kernel void + broadphaseColorKernel( const int startOffset, const int numNodes, __global float4 *g_vertexBuffer, __global int2* pOverlappingPairs, const int numOverlap) +{ + int nodeID = get_global_id(0); + if( nodeID < numOverlap ) + { + int2 pair = pOverlappingPairs[nodeID]; + float4 red = (float4)(1.f,0.4f,0.4f,1.f); + + g_vertexBuffer[pair.x + startOffset/4+numNodes+numNodes] = red; + g_vertexBuffer[pair.y + startOffset/4+numNodes+numNodes] = red; + } +} + + + +__kernel void + broadphaseKernel( const int startOffset, const int numNodes, __global float4 *g_vertexBuffer) +{ + int nodeID = get_global_id(0); + +// float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254); + + if( nodeID < numNodes ) + { + float4 position = g_vertexBuffer[nodeID + startOffset/4]; + //float4 orientation = g_vertexBuffer[nodeID + startOffset/4+numNodes]; + float4 color = g_vertexBuffer[nodeID + startOffset/4+numNodes+numNodes]; + + float4 red = (float4)(1.f,0.f,0.f,0.f); + float4 green = (float4)(0.f,1.f,0.f,0.f); + float4 blue = (float4)(0.f,0.f,1.f,0.f); + float overlap=0; + int equal = 0; + + g_vertexBuffer[nodeID + startOffset/4+numNodes+numNodes] = green; + + for (int i=0;i0.f) + g_vertexBuffer[nodeID + startOffset/4+numNodes+numNodes]=red*overlap; + else + g_vertexBuffer[nodeID + startOffset/4+numNodes+numNodes]=green; + } + } +} + +); \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/btGridBroadphaseCL.cpp b/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/btGridBroadphaseCL.cpp new file mode 100644 index 0000000..9e0ea62 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/btGridBroadphaseCL.cpp @@ -0,0 +1,231 @@ + +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Roman Ponomarev, Erwin Coumans + +#ifdef RELEASE_ME +#define COMPUTE_AABB_KERNEL_PATH "computeAabbKernelOCL.cl" +#else +#define COMPUTE_AABB_KERNEL_PATH "..\\..\\opencl\\broadphase_benchmark\\computeAabbKernelOCL" +#endif + + +#include "btGridBroadphaseCl.h" +#include "LinearMath/btQuickprof.h" +#include "Adl/Adl.h" +#include "AdlPrimitives/Math/Math.h" + +#include "Adl/AdlKernel.h" +#include "../basic_initialize/btOpenCLUtils.h" +#define MSTRINGIFY(A) #A +static const char* spComputeAabbSource= +#include "computeAabbKernelOCL.cl" + +struct btTmpAabb +{ + float minfx; + float minfy; + float minfz; + unsigned int index0; + float maxfx; + float maxfy; + float maxfz; + unsigned int index1; +} ; + + + + +btGridBroadphaseCl::btGridBroadphaseCl( btOverlappingPairCache* overlappingPairCache, + const btVector3& cellSize, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerSmallProxy, + btScalar maxSmallProxySize, + int maxSmallProxiesPerCell, + cl_context context, + cl_device_id device, + cl_command_queue queue, + adl::DeviceCL* deviceCL) +:bt3dGridBroadphaseOCL(overlappingPairCache,cellSize, + gridSizeX, gridSizeY, gridSizeZ, + maxSmallProxies, maxLargeProxies, maxPairsPerSmallProxy, + maxSmallProxySize,maxSmallProxiesPerCell, + context,device,queue,deviceCL) +{ + m_computeAabbKernel = m_deviceCL->getKernel(COMPUTE_AABB_KERNEL_PATH,"computeAabb","",spComputeAabbSource); + + m_countOverlappingPairs = m_deviceCL->getKernel(COMPUTE_AABB_KERNEL_PATH,"countOverlappingpairs","",spComputeAabbSource); + + m_squeezePairCaches = m_deviceCL->getKernel(COMPUTE_AABB_KERNEL_PATH,"squeezePairCaches","",spComputeAabbSource); + + m_aabbConstBuffer = new adl::Buffer(m_deviceCL,1,adl::BufferBase::BUFFER_CONST); + + size_t memSize = m_maxHandles * m_maxPairsPerBody * sizeof(unsigned int)*2; + cl_int ciErrNum=0; + m_dAllOverlappingPairs = clCreateBuffer(m_cxMainContext, CL_MEM_READ_WRITE, memSize, NULL, &ciErrNum); + + memset(m_hAllOverlappingPairs, 0x00, sizeof(MyUint2)*m_maxHandles * m_maxPairsPerBody); + copyArrayToDevice(m_dAllOverlappingPairs, m_hAllOverlappingPairs, m_maxHandles * m_maxPairsPerBody * sizeof(MyUint2)); + + + + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + + +} + +btGridBroadphaseCl::~btGridBroadphaseCl() +{ + clReleaseMemObject(m_dAllOverlappingPairs); + + delete m_aabbConstBuffer; + +} + + + +void btGridBroadphaseCl::prepareAABB(float* positions, int numObjects) +{ + return; +#if 0 +bt3dGridBroadphaseOCL::prepareAABB(); +#else + BT_PROFILE("prepareAABB"); + bt3DGrid3F1U* pBB = m_hAABB; + + int new_largest_index = numObjects; + unsigned int num_small = numObjects; + m_LastHandleIndex = new_largest_index; + new_largest_index = -1; + unsigned int num_large = 0; + m_LastLargeHandleIndex = new_largest_index; + // paranoid checks + //btAssert(num_small == m_numHandles); + //btAssert(num_large == m_numLargeHandles); + + //copyArrayFromDevice( m_hAABB, m_dAABB, sizeof(bt3DGrid3F1U) * 2 * (m_numHandles + m_numLargeHandles)); + //clFinish(m_cqCommandQue); +#endif + +} +void btGridBroadphaseCl::calcHashAABB() +{ + bt3dGridBroadphaseOCL::calcHashAABB(); +} + + +void btGridBroadphaseCl::calculateOverlappingPairs(float* positions, int numObjects) +{ + btDispatcher* dispatcher=0; + + // update constants + { + BT_PROFILE("setParameters"); + setParameters(&m_params); + } + + // prepare AABB array + { + BT_PROFILE("prepareAABB"); + prepareAABB(positions, numObjects); + } + // calculate hash + { + BT_PROFILE("calcHashAABB"); + calcHashAABB(); + } + + { + BT_PROFILE("sortHash"); + // sort bodies based on hash + sortHash(); + } + + // find start of each cell + { + BT_PROFILE("findCellStart"); + findCellStart(); + } + + { + BT_PROFILE("findOverlappingPairs"); + // findOverlappingPairs (small/small) + findOverlappingPairs(); + } + + // add pairs to CPU cache + { + BT_PROFILE("computePairCacheChanges"); +#if 0 + computePairCacheChanges(); +#else + int ciErrNum=0; + + ciErrNum=clSetKernelArg((cl_kernel)m_countOverlappingPairs->m_kernel, 0, sizeof(int), (void*)&numObjects); + ciErrNum=clSetKernelArg((cl_kernel)m_countOverlappingPairs->m_kernel, 1, sizeof(cl_mem),(void*)&m_dPairBuff); + ciErrNum=clSetKernelArg((cl_kernel)m_countOverlappingPairs->m_kernel, 2, sizeof(cl_mem),(void*)&m_dPairBuffStartCurr); + ciErrNum=clSetKernelArg((cl_kernel)m_countOverlappingPairs->m_kernel, 3, sizeof(cl_mem),(void*)&m_dPairScanChanged); + ciErrNum=clSetKernelArg((cl_kernel)m_countOverlappingPairs->m_kernel, 4, sizeof(cl_mem),(void*)&m_dAABB); + + + size_t localWorkSize=64; + size_t numWorkItems = localWorkSize*((numObjects+ (localWorkSize)) / localWorkSize); + + + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, (cl_kernel)m_countOverlappingPairs->m_kernel, 1, NULL, &numWorkItems, &localWorkSize, 0,0,0 ); +oclCHECKERROR(ciErrNum, CL_SUCCESS); + ciErrNum = clFlush(m_cqCommandQue); +#endif + + + } + { + BT_PROFILE("scanOverlappingPairBuff"); + scanOverlappingPairBuff(false); + } + { + BT_PROFILE("squeezeOverlappingPairBuff"); +//#define FORCE_CPU +#ifdef FORCE_CPU + bt3dGridBroadphaseOCL::squeezeOverlappingPairBuff(); + copyArrayToDevice(m_dPairsChangedXY, m_hPairsChangedXY, sizeof( MyUint2) * m_numPrefixSum); //gSum +#else + //squeezeOverlappingPairBuff(); + int ciErrNum = 0; + ciErrNum=clSetKernelArg((cl_kernel)m_squeezePairCaches->m_kernel, 0, sizeof(int), (void*)&numObjects); + ciErrNum=clSetKernelArg((cl_kernel)m_squeezePairCaches->m_kernel, 1, sizeof(cl_mem),(void*)&m_dPairBuff); + ciErrNum=clSetKernelArg((cl_kernel)m_squeezePairCaches->m_kernel, 2, sizeof(cl_mem),(void*)&m_dPairBuffStartCurr); + ciErrNum=clSetKernelArg((cl_kernel)m_squeezePairCaches->m_kernel, 3, sizeof(cl_mem),(void*)&m_dPairScanChanged); + ciErrNum=clSetKernelArg((cl_kernel)m_squeezePairCaches->m_kernel, 4, sizeof(cl_mem),(void*)&m_dAllOverlappingPairs); + ciErrNum=clSetKernelArg((cl_kernel)m_squeezePairCaches->m_kernel, 5, sizeof(cl_mem),(void*)&m_dAABB); + + size_t workGroupSize = 64; + size_t numWorkItems = workGroupSize*((numObjects+ (workGroupSize)) / workGroupSize); + + + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, (cl_kernel)m_squeezePairCaches->m_kernel, 1, NULL, &numWorkItems, &workGroupSize, 0,0,0 ); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + +// copyArrayFromDevice(m_hAllOverlappingPairs, m_dAllOverlappingPairs, sizeof(unsigned int) * m_numPrefixSum*2); //gSum +// clFinish(m_cqCommandQue); +#endif + + } + + + return; +} + diff --git a/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/btGridBroadphaseCL.h b/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/btGridBroadphaseCL.h new file mode 100644 index 0000000..7f06448 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/btGridBroadphaseCL.h @@ -0,0 +1,73 @@ + +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Roman Ponomarev, Erwin Coumans + +#ifndef GRID_BROADPHASE_CL_H +#define GRID_BROADPHASE_CL_H + +#include "../3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.h" + +#include "Adl/Adl.h" +#include "Adl/AdlKernel.h" + + +struct MyAabbConstData +{ + int bla; + int numElem; +}; + + + +class btGridBroadphaseCl : public bt3dGridBroadphaseOCL +{ +protected: + + adl::Kernel* m_computeAabbKernel; + adl::Kernel* m_countOverlappingPairs; + adl::Kernel* m_squeezePairCaches; + + + adl::Buffer* m_aabbConstBuffer; + + + public: + + cl_mem m_dAllOverlappingPairs; + + + btGridBroadphaseCl( btOverlappingPairCache* overlappingPairCache, + const btVector3& cellSize, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerSmallProxy, + btScalar maxSmallProxySize, + int maxSmallProxiesPerCell = 4, + cl_context context = NULL, + cl_device_id device = NULL, + cl_command_queue queue = NULL, + adl::DeviceCL* deviceCL=0 + ); + + virtual void prepareAABB(float* positions, int numObjects); + virtual void calcHashAABB(); + + void calculateOverlappingPairs(float* positions, int numObjects); + + virtual ~btGridBroadphaseCl(); + +}; + +#endif //GRID_BROADPHASE_CL_H + diff --git a/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/computeAabbKernelOCL.cl b/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/computeAabbKernelOCL.cl new file mode 100644 index 0000000..3cf7550 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/computeAabbKernelOCL.cl @@ -0,0 +1,112 @@ +MSTRINGIFY( + +typedef struct +{ + int bla; + int numElem; +} MyAabbConstDataCL ; + +typedef struct +{ + float minfx; + float minfy; + float minfz; + unsigned int index0; + float maxfx; + float maxfy; + float maxfz; + unsigned int index1; +} btAabbCL; + + +__kernel void computeAabb( __global btAabbCL* aabbs,__global float4* positions, MyAabbConstDataCL cb) +{ + int nodeID = get_global_id(0); + + if( nodeID < cb.numElem ) + { + aabbs[nodeID].minfx = positions[nodeID].x -1.f; + aabbs[nodeID].minfy = positions[nodeID].y -1.f; + aabbs[nodeID].minfz = positions[nodeID].z -1.f; + aabbs[nodeID].index0 = nodeID; + aabbs[nodeID].maxfx = positions[nodeID].x +1.f; + aabbs[nodeID].maxfy = positions[nodeID].y +1.f; + aabbs[nodeID].maxfz = positions[nodeID].z +1.f; + aabbs[nodeID].index1 = nodeID; + } +} + + +__kernel void countOverlappingpairs( int numObjects, + __global int* pPairBuff, + __global int2* pPairBuffStartCurr, + __global int* pPairScan, + __global float4* pAABB ) +{ + int index = get_global_id(0); + if(index >= numObjects) + { + return; + } + float4 bbMin = pAABB[index * 2]; + int handleIndex = as_int(bbMin.w); + int2 start_curr = pPairBuffStartCurr[handleIndex]; + int start = start_curr.x; + int curr = start_curr.y; + __global int *pInp = pPairBuff + start; + int num_changes = 0; + for(int k = 0; k < curr; k++, pInp++) + { + if(((*pInp) & 0x60000000))//either new or existing pairs (ignore old non-overlapping pairs) + { + num_changes++; + } + } + pPairScan[index+1] = num_changes; +} + + +__kernel void squeezePairCaches( int numObjects, + __global int* pPairBuff, + __global int2* pPairBuffStartCurr, + __global int* pPairScan, + __global int2* pPairOut, + __global float4* pAABB ) +{ + int index = get_global_id(0); + if(index >= numObjects) + { + return; + } + float4 bbMin = pAABB[index * 2]; + int handleIndex = as_int(bbMin.w); + int2 start_curr = pPairBuffStartCurr[handleIndex]; + int start = start_curr.x; + int curr = start_curr.y; + __global int* pInp = pPairBuff + start; + __global int2* pOut = pPairOut + pPairScan[index+1]; + __global int* pOut2 = pInp; + int num = 0; + for(int k = 0; k < curr; k++, pInp++) + { + if(((*pInp) & 0x60000000)) + { + int2 newpair; + newpair.x = handleIndex; + newpair.y = (*pInp) & (~0x60000000); + *pOut = newpair; + pOut++; + } + if((*pInp) & 0x60000000) + { + *pOut2 = (*pInp) & (~0x60000000); + pOut2++; + num++; + } + } + int2 newStartCurr; + newStartCurr.x = start; + newStartCurr.y = num; + pPairBuffStartCurr[handleIndex] = newStartCurr; +} +); \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/findPairsOpenCL.cpp b/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/findPairsOpenCL.cpp new file mode 100644 index 0000000..d90e370 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/findPairsOpenCL.cpp @@ -0,0 +1,204 @@ + +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Roman Ponomarev, Erwin Coumans + +#include "findPairsOpenCL.h" +#include "../basic_initialize/btOpenCLUtils.h" + +#define MSTRINGIFY(A) #A +static char* broadphaseKernelString = +#include "broadphaseKernel.cl" + +#define GRID_BROADPHASE_PATH "..\\..\\opencl\\broadphase_benchmark\\broadphaseKernel.cl" + + + + +void initFindPairs(btFindPairsIO& fpio,cl_context cxMainContext, cl_device_id device, cl_command_queue commandQueue, int maxHandles, int maxPairsPerBody) +{ + + //m_proxies.push_back( proxy ); + + fpio.m_mainContext = cxMainContext; + fpio.m_cqCommandQue = commandQueue; + fpio.m_device = device; + cl_int pErrNum; + cl_program prog = btOpenCLUtils::compileCLProgramFromString(cxMainContext, device, broadphaseKernelString, &pErrNum ,"",GRID_BROADPHASE_PATH); + + fpio.m_broadphaseBruteForceKernel = btOpenCLUtils::compileCLKernelFromString(cxMainContext,device, broadphaseKernelString, "broadphaseKernel" ,&pErrNum,prog); + fpio.m_initializeGpuAabbsKernelSimple = btOpenCLUtils::compileCLKernelFromString(cxMainContext,device, broadphaseKernelString, "initializeGpuAabbsSimple" ,&pErrNum,prog); + fpio.m_initializeGpuAabbsKernelFull = btOpenCLUtils::compileCLKernelFromString(cxMainContext,device, broadphaseKernelString, "initializeGpuAabbsFull" ,&pErrNum,prog); + + fpio.m_broadphaseColorKernel = btOpenCLUtils::compileCLKernelFromString(cxMainContext,device, broadphaseKernelString, "broadphaseColorKernel" ,&pErrNum,prog); + + fpio.m_setupBodiesKernel = btOpenCLUtils::compileCLKernelFromString(cxMainContext,device, broadphaseKernelString, "setupBodiesKernel" ,&pErrNum,prog); + fpio.m_copyVelocitiesKernel = btOpenCLUtils::compileCLKernelFromString(cxMainContext,device, broadphaseKernelString, "copyVelocitiesKernel" ,&pErrNum,prog); + + + +} + +void findPairsOpenCLBruteForce(btFindPairsIO& fpio) +{ + + int ciErrNum = 0; + + int numObjects = fpio.m_numObjects; + int offset = fpio.m_positionOffset; + + ciErrNum = clSetKernelArg(fpio.m_broadphaseBruteForceKernel, 0, sizeof(int), &offset); + ciErrNum = clSetKernelArg(fpio.m_broadphaseBruteForceKernel, 1, sizeof(int), &numObjects); + ciErrNum = clSetKernelArg(fpio.m_broadphaseBruteForceKernel, 2, sizeof(cl_mem), (void*)&fpio.m_clObjectsBuffer); + + size_t numWorkItems = numObjects;///workGroupSize*((NUM_OBJECTS + (workGroupSize)) / workGroupSize); + size_t workGroupSize = 64; + ciErrNum = clEnqueueNDRangeKernel(fpio.m_cqCommandQue, fpio.m_broadphaseBruteForceKernel, 1, NULL, &numWorkItems, &workGroupSize,0 ,0 ,0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); +} + +void setupGpuAabbsFull(btFindPairsIO& fpio, cl_mem bodies) +{ + + int ciErrNum = 0; + + int numObjects = fpio.m_numObjects; + int offset = fpio.m_positionOffset; + + ciErrNum = clSetKernelArg(fpio.m_initializeGpuAabbsKernelFull, 0, sizeof(int), &offset); + ciErrNum = clSetKernelArg(fpio.m_initializeGpuAabbsKernelFull, 1, sizeof(int), &numObjects); + ciErrNum = clSetKernelArg(fpio.m_initializeGpuAabbsKernelFull, 2, sizeof(cl_mem), (void*)&fpio.m_clObjectsBuffer); + ciErrNum = clSetKernelArg(fpio.m_initializeGpuAabbsKernelFull, 3, sizeof(cl_mem), (void*)&bodies); + ciErrNum = clSetKernelArg(fpio.m_initializeGpuAabbsKernelFull, 4, sizeof(cl_mem), (void*)&fpio.m_dlocalShapeAABB); + ciErrNum = clSetKernelArg(fpio.m_initializeGpuAabbsKernelFull, 5, sizeof(cl_mem), (void*)&fpio.m_dAABB); + size_t workGroupSize = 64; + size_t numWorkItems = workGroupSize*((numObjects+ (workGroupSize)) / workGroupSize); + + ciErrNum = clEnqueueNDRangeKernel(fpio.m_cqCommandQue, fpio.m_initializeGpuAabbsKernelFull, 1, NULL, &numWorkItems, &workGroupSize,0 ,0 ,0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); +} + +void setupGpuAabbsSimple(btFindPairsIO& fpio) +{ + + int ciErrNum = 0; + + int numObjects = fpio.m_numObjects; + int offset = fpio.m_positionOffset; + + ciErrNum = clSetKernelArg(fpio.m_initializeGpuAabbsKernelSimple, 0, sizeof(int), &offset); + ciErrNum = clSetKernelArg(fpio.m_initializeGpuAabbsKernelSimple, 1, sizeof(int), &numObjects); + ciErrNum = clSetKernelArg(fpio.m_initializeGpuAabbsKernelSimple, 2, sizeof(cl_mem), (void*)&fpio.m_clObjectsBuffer); + ciErrNum = clSetKernelArg(fpio.m_initializeGpuAabbsKernelSimple, 3, sizeof(cl_mem), (void*)&fpio.m_dAABB); + size_t workGroupSize = 64; + size_t numWorkItems = workGroupSize*((numObjects+ (workGroupSize)) / workGroupSize); + + ciErrNum = clEnqueueNDRangeKernel(fpio.m_cqCommandQue, fpio.m_initializeGpuAabbsKernelSimple, 1, NULL, &numWorkItems, &workGroupSize,0 ,0 ,0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); +} + + +void setupBodies(btFindPairsIO& fpio, cl_mem linVelMem, cl_mem angVelMem, cl_mem bodies, cl_mem bodyInertias) +{ + int ciErrNum = 0; + + int numObjects = fpio.m_numObjects; + int offset = fpio.m_positionOffset; + + ciErrNum = clSetKernelArg(fpio.m_setupBodiesKernel, 0, sizeof(int), &offset); + ciErrNum = clSetKernelArg(fpio.m_setupBodiesKernel, 1, sizeof(int), &fpio.m_numObjects); + ciErrNum = clSetKernelArg(fpio.m_setupBodiesKernel, 2, sizeof(cl_mem), (void*)&fpio.m_clObjectsBuffer); + + ciErrNum = clSetKernelArg(fpio.m_setupBodiesKernel, 3, sizeof(cl_mem), (void*)&linVelMem); + ciErrNum = clSetKernelArg(fpio.m_setupBodiesKernel, 4, sizeof(cl_mem), (void*)&angVelMem); + ciErrNum = clSetKernelArg(fpio.m_setupBodiesKernel, 5, sizeof(cl_mem), (void*)&bodies); + ciErrNum = clSetKernelArg(fpio.m_setupBodiesKernel, 6, sizeof(cl_mem), (void*)&bodyInertias); + + if (numObjects) + { + size_t workGroupSize = 64; + size_t numWorkItems = workGroupSize*((numObjects+ (workGroupSize)) / workGroupSize); + + ciErrNum = clEnqueueNDRangeKernel(fpio.m_cqCommandQue, fpio.m_setupBodiesKernel, 1, NULL, &numWorkItems, &workGroupSize,0 ,0 ,0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + +} + + +void copyBodyVelocities(btFindPairsIO& fpio, cl_mem linVelMem, cl_mem angVelMem, cl_mem bodies, cl_mem bodyInertias) +{ + int ciErrNum = 0; + + int numObjects = fpio.m_numObjects; + int offset = fpio.m_positionOffset; + + ciErrNum = clSetKernelArg(fpio.m_copyVelocitiesKernel, 0, sizeof(int), &offset); + ciErrNum = clSetKernelArg(fpio.m_copyVelocitiesKernel, 1, sizeof(int), &fpio.m_numObjects); + ciErrNum = clSetKernelArg(fpio.m_copyVelocitiesKernel, 2, sizeof(cl_mem), (void*)&fpio.m_clObjectsBuffer); + + ciErrNum = clSetKernelArg(fpio.m_copyVelocitiesKernel, 3, sizeof(cl_mem), (void*)&linVelMem); + ciErrNum = clSetKernelArg(fpio.m_copyVelocitiesKernel, 4, sizeof(cl_mem), (void*)&angVelMem); + ciErrNum = clSetKernelArg(fpio.m_copyVelocitiesKernel, 5, sizeof(cl_mem), (void*)&bodies); + ciErrNum = clSetKernelArg(fpio.m_copyVelocitiesKernel, 6, sizeof(cl_mem), (void*)&bodyInertias); + + if (numObjects) + { + size_t workGroupSize = 64; + size_t numWorkItems = workGroupSize*((numObjects+ (workGroupSize)) / workGroupSize); + + ciErrNum = clEnqueueNDRangeKernel(fpio.m_cqCommandQue, fpio.m_copyVelocitiesKernel, 1, NULL, &numWorkItems, &workGroupSize,0 ,0 ,0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + +} + +void colorPairsOpenCL(btFindPairsIO& fpio) +{ + int ciErrNum = 0; + + int numObjects = fpio.m_numObjects; + int offset = fpio.m_positionOffset; + + ciErrNum = clSetKernelArg(fpio.m_broadphaseColorKernel, 0, sizeof(int), &offset); + ciErrNum = clSetKernelArg(fpio.m_broadphaseColorKernel, 1, sizeof(int), &fpio.m_numObjects); + ciErrNum = clSetKernelArg(fpio.m_broadphaseColorKernel, 2, sizeof(cl_mem), (void*)&fpio.m_clObjectsBuffer); + ciErrNum = clSetKernelArg(fpio.m_broadphaseColorKernel, 3, sizeof(cl_mem), (void*)&fpio.m_dAllOverlappingPairs); + ciErrNum = clSetKernelArg(fpio.m_broadphaseColorKernel, 4, sizeof(int), &fpio.m_numOverlap); + + + if (fpio.m_numOverlap) + { + size_t workGroupSize = 64; + size_t numWorkItems = workGroupSize*((fpio.m_numOverlap+ (workGroupSize)) / workGroupSize); + + ciErrNum = clEnqueueNDRangeKernel(fpio.m_cqCommandQue, fpio.m_broadphaseColorKernel, 1, NULL, &numWorkItems, &workGroupSize,0 ,0 ,0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } +} + + + +void releaseFindPairs(btFindPairsIO& fpio) +{ + clReleaseKernel(fpio.m_initializeGpuAabbsKernelSimple); + clReleaseKernel(fpio.m_initializeGpuAabbsKernelFull); + clReleaseKernel(fpio.m_broadphaseColorKernel); + clReleaseKernel(fpio.m_broadphaseBruteForceKernel); + clReleaseKernel(fpio.m_setupBodiesKernel); + clReleaseKernel(fpio.m_copyVelocitiesKernel); + + +} + diff --git a/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/findPairsOpenCL.h b/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/findPairsOpenCL.h new file mode 100644 index 0000000..7715436 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/findPairsOpenCL.h @@ -0,0 +1,90 @@ + +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Roman Ponomarev, Erwin Coumans + +#ifndef FIND_PAIRS_H +#define FIND_PAIRS_H + +#include "../basic_initialize/btOpenCLInclude.h" + +struct btKernelInfo +{ + int m_Id; + cl_kernel m_kernel; + char* m_name; + int m_workgroupSize; +}; + + + +struct btFindPairsIO +{ + int m_numObjects; + + cl_mem m_clObjectsBuffer; //for memory layout details see main.cpp (todo, make it flexible) + int m_positionOffset;//offset in m_clObjectsBuffer where position array starts + + cl_command_queue m_cqCommandQue; + cl_kernel m_initializeGpuAabbsKernelSimple; + cl_kernel m_initializeGpuAabbsKernelFull; + cl_kernel m_broadphaseColorKernel; + cl_kernel m_broadphaseBruteForceKernel; + + cl_kernel m_setupBodiesKernel; + cl_kernel m_copyVelocitiesKernel; + + cl_context m_mainContext; + cl_device_id m_device; + + cl_kernel m_calcHashAabbKernel; + cl_kernel m_clearCellStartKernel; + cl_kernel m_findCellStartKernel; + cl_kernel m_findOverlappingPairsKernel; + cl_kernel m_computePairChangeKernel; + cl_kernel m_squeezePairBuffKernel; + + + cl_mem m_dAllOverlappingPairs; + int m_numOverlap; + + cl_mem m_dBpParams; + cl_mem m_dBodiesHash; + cl_mem m_dCellStart; + cl_mem m_dPairBuff; + cl_mem m_dPairBuffStartCurr; + cl_mem m_dlocalShapeAABB; + cl_mem m_dAABB; + cl_mem m_dPairScan; + cl_mem m_dPairOut; +}; + + +void initFindPairs(btFindPairsIO& fpio,cl_context cxMainContext, cl_device_id device, cl_command_queue commandQueue, int maxHandles,int maxPairsPerBody = 16); + +void findPairsOpenCLBruteForce(btFindPairsIO& fpio); + +void setupGpuAabbsSimple(btFindPairsIO& fpio); + +void setupGpuAabbsFull(btFindPairsIO& fpio, cl_mem bodies); + + +void colorPairsOpenCL(btFindPairsIO& fpio); + +void setupBodies(btFindPairsIO& fpio, cl_mem linVelMem, cl_mem angVelMem, cl_mem bodies, cl_mem bodyInertias); +void copyBodyVelocities(btFindPairsIO& fpio, cl_mem linVelMem, cl_mem angVelMem, cl_mem bodies, cl_mem bodyInertias); + +void releaseFindPairs(btFindPairsIO& fpio); + +#endif //FIND_PAIRS_H diff --git a/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/integrateKernel.cl b/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/integrateKernel.cl new file mode 100644 index 0000000..87d2b25 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/integrateKernel.cl @@ -0,0 +1,116 @@ +MSTRINGIFY( + +float4 quatMult(float4 q1, float4 q2) +{ + float4 q; + q.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y; + q.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z; + q.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x; + q.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z; + return q; +} + +float4 quatNorm(float4 q) +{ + float len = native_sqrt(dot(q, q)); + if(len > 0.f) + { + q *= 1.f / len; + } + else + { + q.x = q.y = q.z = 0.f; + q.w = 1.f; + } + return q; +} + + + + + +__kernel void + integrateTransformsKernel( const int startOffset, const int numNodes, __global float4 *g_vertexBuffer, + __global float4 *linVel, + __global float4 *pAngVel, + __global float* pBodyTimes) +{ + int nodeID = get_global_id(0); + + + + float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f); + float mAmplitude = 66.f; + float timeStep = 0.0166666f; + + if( nodeID < numNodes ) + { + + //g_vertexBuffer[nodeID + startOffset/4+numNodes] += pAngVel[nodeID]; + if (1) + { + float4 axis; + //add some hardcoded angular damping + pAngVel[nodeID].x *= 0.99f; + pAngVel[nodeID].y *= 0.99f; + pAngVel[nodeID].z *= 0.99f; + + float4 angvel = pAngVel[nodeID]; + float fAngle = native_sqrt(dot(angvel, angvel)); + //limit the angular motion + if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD) + { + fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep; + } + if(fAngle < 0.001f) + { + // use Taylor's expansions of sync function + axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle); + } + else + { + // sync(fAngle) = sin(c*fAngle)/t + axis = angvel * ( native_sin(0.5f * fAngle * timeStep) / fAngle); + } + float4 dorn = axis; + dorn.w = native_cos(fAngle * timeStep * 0.5f); + float4 orn0 = g_vertexBuffer[nodeID + startOffset/4+numNodes]; + float4 predictedOrn = quatMult(dorn, orn0); + predictedOrn = quatNorm(predictedOrn); + g_vertexBuffer[nodeID + startOffset/4+numNodes]=predictedOrn; + } + + //linear velocity + g_vertexBuffer[nodeID + startOffset/4] += linVel[nodeID] * timeStep; + + } +} + + +__kernel void + sineWaveKernel( const int startOffset, const int numNodes, __global float4 *g_vertexBuffer, + __global float4 *linVel, + __global float4 *pAngVel, + __global float* pBodyTimes) +{ + int nodeID = get_global_id(0); + float timeStepPos = 0.000166666; + + float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f); + float mAmplitude = 166.f; + + + if( nodeID < numNodes ) + { + pBodyTimes[nodeID] += timeStepPos; + float4 position = g_vertexBuffer[nodeID + startOffset/4]; + position.x = native_cos(pBodyTimes[nodeID]*2.17f)*mAmplitude + native_sin(pBodyTimes[nodeID])*mAmplitude*0.5f; + position.y = native_cos(pBodyTimes[nodeID]*1.38f)*mAmplitude + native_sin(pBodyTimes[nodeID]*mAmplitude); + position.z = native_cos(pBodyTimes[nodeID]*2.17f)*mAmplitude + native_sin(pBodyTimes[nodeID]*0.777f)*mAmplitude; + g_vertexBuffer[nodeID + startOffset/4] = position; + } +} + + + +); \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/main.cpp b/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/main.cpp new file mode 100644 index 0000000..3e52c19 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/broadphase_benchmark/main.cpp @@ -0,0 +1,1565 @@ + +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + +//starts crashing when more than 32700 objects on my Geforce 260, unless _USE_SUB_DATA is defined (still unstable though) +//runs fine with fewer objects + +#define NUM_OBJECTS_X 42 +//327 +#define NUM_OBJECTS_Y 42 +#define NUM_OBJECTS_Z 42 +//#define NUM_OBJECTS_Z 20 + +//#define _USE_SUB_DATA + +//#define NUM_OBJECTS_X 100 +//#define NUM_OBJECTS_Y 100 +//#define NUM_OBJECTS_Z 100 + +///RECREATE_CL_AND_SHADERS_ON_RESIZE will delete and re-create OpenCL and GLSL shaders/buffers at each resize +//#define RECREATE_CL_AND_SHADERS_ON_RESIZE + +/// +/// OpenCL - OpenGL interop example. Updating transforms of many cubes on GPU, without going through main memory/using the PCIe bus +/// Create all OpenGL resources AFTER create OpenCL context! +/// + + +#include +#include + +#include "btGlutInclude.h" +#include "../opengl_interop/btStopwatch.h" + + +#include "LinearMath/btVector3.h" +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btMatrix3x3.h" +static float sAngle(0); + +#include + +#ifdef _WIN32 +#include +#endif + +#include +#include +#include "../3dGridBroadphase/Shared/btGpu3DGridBroadphase.h" +#include "../3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.h" +#include "btGridBroadphaseCl.h" + +#define USE_NEW +#ifdef USE_NEW +btGridBroadphaseCl* sBroadphase=0; +#else +btGpu3DGridBroadphase* sBroadphase=0; +#endif + +btAlignedObjectArray proxyArray; + + +#define RS_SCALE (1.0 / (1.0 + RAND_MAX)) + + +int randbiased (double x) { + for (;;) { + double p = rand () * RS_SCALE; + if (p >= x) return 0; + if (p+RS_SCALE <= x) return 1; + /* p < x < p+RS_SCALE */ + x = (x - p) * (1.0 + RAND_MAX); + } +} + +size_t randrange (size_t n) +{ + double xhi; + double resolution = n * RS_SCALE; + double x = resolution * rand (); /* x in [0,n) */ + size_t lo = (size_t) floor (x); + + xhi = x + resolution; + + for (;;) { + lo++; + if (lo >= xhi || randbiased ((lo - x) / (xhi - x))) return lo-1; + x = lo; + } +} + +//OpenCL stuff +#include "../basic_initialize/btOpenCLUtils.h" +#include "../opengl_interop/btOpenCLGLInteropBuffer.h" +#include "findPairsOpenCL.h" + +btFindPairsIO gFpIO; + +cl_context g_cxMainContext; +cl_command_queue g_cqCommandQue; +cl_device_id g_device; +static const size_t workGroupSize = 64; +cl_mem gLinVelMem; +cl_mem gAngVelMem; +cl_mem gBodyTimes; + +btVector3 m_cameraPosition(142,220,142); +btVector3 m_cameraTargetPosition(0,-30,0); +btScalar m_cameraDistance = 200; +btVector3 m_cameraUp(0,1,0); +float m_azi=-50.f; +float m_ele=0.f; + + + + +btOpenCLGLInteropBuffer* g_interopBuffer = 0; +cl_kernel g_sineWaveKernel; + + + +////for Adl +#include + +adl::DeviceCL* g_deviceCL=0; + + + +bool useCPU = false; +bool printStats = false; +bool runOpenCLKernels = true; + +#define MSTRINGIFY(A) #A +static char* interopKernelString = +#include "integrateKernel.cl" + + +btStopwatch gStopwatch; +int m_glutScreenWidth = 640; +int m_glutScreenHeight= 480; + +bool m_ortho = false; + +static GLuint instancingShader; // The instancing renderer +static GLuint cube_vao; +static GLuint cube_vbo; +static GLuint index_vbo; +static GLuint m_texturehandle; + +static bool done = false; +static GLint angle_loc = 0; +static GLint ModelViewMatrix; +static GLint ProjectionMatrix; + +void writeTransforms(); + +static GLint uniform_texture_diffuse = 0; + +//used for dynamic loading from disk (default switched off) +#define MAX_SHADER_LENGTH 8192 +static GLubyte shaderText[MAX_SHADER_LENGTH]; + +static const char* vertexShader= \ +"#version 330\n" +"precision highp float;\n" +"\n" +"\n" +"\n" +"layout (location = 0) in vec4 position;\n" +"layout (location = 1) in vec4 instance_position;\n" +"layout (location = 2) in vec4 instance_quaternion;\n" +"layout (location = 3) in vec2 uvcoords;\n" +"layout (location = 4) in vec3 vertexnormal;\n" +"layout (location = 5) in vec4 instance_color;\n" +"layout (location = 6) in vec3 instance_scale;\n" +"\n" +"\n" +"uniform float angle = 0.0;\n" +"uniform mat4 ModelViewMatrix;\n" +"uniform mat4 ProjectionMatrix;\n" +"\n" +"out Fragment\n" +"{\n" +" vec4 color;\n" +"} fragment;\n" +"\n" +"out Vert\n" +"{\n" +" vec2 texcoord;\n" +"} vert;\n" +"\n" +"\n" +"vec4 quatMul ( in vec4 q1, in vec4 q2 )\n" +"{\n" +" vec3 im = q1.w * q2.xyz + q1.xyz * q2.w + cross ( q1.xyz, q2.xyz );\n" +" vec4 dt = q1 * q2;\n" +" float re = dot ( dt, vec4 ( -1.0, -1.0, -1.0, 1.0 ) );\n" +" return vec4 ( im, re );\n" +"}\n" +"\n" +"vec4 quatFromAxisAngle(vec4 axis, in float angle)\n" +"{\n" +" float cah = cos(angle*0.5);\n" +" float sah = sin(angle*0.5);\n" +" float d = inversesqrt(dot(axis,axis));\n" +" vec4 q = vec4(axis.x*sah*d,axis.y*sah*d,axis.z*sah*d,cah);\n" +" return q;\n" +"}\n" +"//\n" +"// vector rotation via quaternion\n" +"//\n" +"vec4 quatRotate3 ( in vec3 p, in vec4 q )\n" +"{\n" +" vec4 temp = quatMul ( q, vec4 ( p, 0.0 ) );\n" +" return quatMul ( temp, vec4 ( -q.x, -q.y, -q.z, q.w ) );\n" +"}\n" +"vec4 quatRotate ( in vec4 p, in vec4 q )\n" +"{\n" +" vec4 temp = quatMul ( q, p );\n" +" return quatMul ( temp, vec4 ( -q.x, -q.y, -q.z, q.w ) );\n" +"}\n" +"\n" +"out vec3 lightDir,normal,ambient;\n" +"\n" +"void main(void)\n" +"{\n" +" vec4 q = instance_quaternion;\n" +" ambient = vec3(0.2,0.2,0.2);\n" +" \n" +" \n" +" vec4 local_normal = (quatRotate3( vertexnormal,q));\n" +" vec3 light_pos = vec3(10000,10000,10000);\n" +" normal = normalize(ModelViewMatrix * local_normal).xyz;\n" +"\n" +" lightDir = normalize(light_pos);//gl_LightSource[0].position.xyz));\n" +"// lightDir = normalize(vec3(gl_LightSource[0].position));\n" +" \n" +" vec4 axis = vec4(1,1,1,0);\n" +" vec4 localcoord = quatRotate3( position.xyz*instance_scale,q);\n" +" vec4 vertexPos = ProjectionMatrix * ModelViewMatrix *(instance_position+localcoord);\n" +"\n" +" gl_Position = vertexPos;\n" +" \n" +" fragment.color = instance_color;\n" +" vert.texcoord = uvcoords;\n" +"}\n" +; + + +static const char* fragmentShader= \ +"#version 330\n" +"precision highp float;\n" +"\n" +"in Fragment\n" +"{\n" +" vec4 color;\n" +"} fragment;\n" +"\n" +"in Vert\n" +"{\n" +" vec2 texcoord;\n" +"} vert;\n" +"\n" +"uniform sampler2D Diffuse;\n" +"\n" +"in vec3 lightDir,normal,ambient;\n" +"\n" +"out vec4 color;\n" +"\n" +"void main_textured(void)\n" +"{\n" +" color = texture2D(Diffuse,vert.texcoord);//fragment.color;\n" +"}\n" +"\n" +"void main(void)\n" +"{\n" +" vec4 texel = fragment.color*texture2D(Diffuse,vert.texcoord);//fragment.color;\n" +" vec3 ct,cf;\n" +" float intensity,at,af;\n" +" intensity = max(dot(lightDir,normalize(normal)),0.5);\n" +" cf = intensity*vec3(1.0,1.0,1.0);//intensity * (gl_FrontMaterial.diffuse).rgb+ambient;//gl_FrontMaterial.ambient.rgb;\n" +" af = 1.0;\n" +" \n" +" ct = texel.rgb;\n" +" at = texel.a;\n" +" \n" +" color = vec4(ct * cf, at * af); \n" +"}\n" +; + + +// Load the shader from the source text +void gltLoadShaderSrc(const char *szShaderSrc, GLuint shader) +{ + GLchar *fsStringPtr[1]; + + fsStringPtr[0] = (GLchar *)szShaderSrc; + glShaderSource(shader, 1, (const GLchar **)fsStringPtr, NULL); +} + + +//////////////////////////////////////////////////////////////// +// Load the shader from the specified file. Returns false if the +// shader could not be loaded +bool gltLoadShaderFile(const char *szFile, GLuint shader) +{ + GLint shaderLength = 0; + FILE *fp; + + // Open the shader file + fp = fopen(szFile, "r"); + if(fp != NULL) + { + // See how long the file is + while (fgetc(fp) != EOF) + shaderLength++; + + // Allocate a block of memory to send in the shader + assert(shaderLength < MAX_SHADER_LENGTH); // make me bigger! + if(shaderLength > MAX_SHADER_LENGTH) + { + fclose(fp); + return false; + } + + // Go back to beginning of file + rewind(fp); + + // Read the whole file in + if (shaderText != NULL) + fread(shaderText, 1, shaderLength, fp); + + // Make sure it is null terminated and close the file + shaderText[shaderLength] = '\0'; + fclose(fp); + } + else + return false; + + // printf(shaderText); + // Load the string + gltLoadShaderSrc((const char *)shaderText, shader); + + return true; +} + + +///////////////////////////////////////////////////////////////// +// Load a pair of shaders, compile, and link together. Specify the complete +// file path for each shader. Note, there is no support for +// just loading say a vertex program... you have to do both. +GLuint gltLoadShaderPair(const char *szVertexProg, const char *szFragmentProg, bool loadFromFile) +{ + // Temporary Shader objects + GLuint hVertexShader; + GLuint hFragmentShader; + GLuint hReturn = 0; + GLint testVal; + + // Create shader objects + hVertexShader = glCreateShader(GL_VERTEX_SHADER); + hFragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + + if (loadFromFile) + { + + if(gltLoadShaderFile(szVertexProg, hVertexShader) == false) + { + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + + if(gltLoadShaderFile(szFragmentProg, hFragmentShader) == false) + { + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + } else + { + gltLoadShaderSrc(vertexShader, hVertexShader); + gltLoadShaderSrc(fragmentShader, hFragmentShader); + } + // Compile them + glCompileShader(hVertexShader); + glCompileShader(hFragmentShader); + + // Check for errors + glGetShaderiv(hVertexShader, GL_COMPILE_STATUS, &testVal); + if(testVal == GL_FALSE) + { + char temp[256] = ""; + glGetShaderInfoLog( hVertexShader, 256, NULL, temp); + fprintf( stderr, "Compile failed:\n%s\n", temp); + assert(0); + exit(0); + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + + glGetShaderiv(hFragmentShader, GL_COMPILE_STATUS, &testVal); + if(testVal == GL_FALSE) + { + char temp[256] = ""; + glGetShaderInfoLog( hFragmentShader, 256, NULL, temp); + fprintf( stderr, "Compile failed:\n%s\n", temp); + assert(0); + exit(0); + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + + // Link them - assuming it works... + hReturn = glCreateProgram(); + glAttachShader(hReturn, hVertexShader); + glAttachShader(hReturn, hFragmentShader); + + glLinkProgram(hReturn); + + // These are no longer needed + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + + // Make sure link worked too + glGetProgramiv(hReturn, GL_LINK_STATUS, &testVal); + if(testVal == GL_FALSE) + { + glDeleteProgram(hReturn); + return (GLuint)NULL; + } + + return hReturn; +} + +///position xyz, unused w, normal, uv +static const GLfloat cube_vertices[] = +{ + -1.0f, -1.0f, 1.0f, 0.0f, 0,0,1, 0,0,//0 + 1.0f, -1.0f, 1.0f, 0.0f, 0,0,1, 1,0,//1 + 1.0f, 1.0f, 1.0f, 0.0f, 0,0,1, 1,1,//2 + -1.0f, 1.0f, 1.0f, 0.0f, 0,0,1, 0,1 ,//3 + + -1.0f, -1.0f, -1.0f, 1.0f, 0,0,-1, 0,0,//4 + 1.0f, -1.0f, -1.0f, 1.0f, 0,0,-1, 1,0,//5 + 1.0f, 1.0f, -1.0f, 1.0f, 0,0,-1, 1,1,//6 + -1.0f, 1.0f, -1.0f, 1.0f, 0,0,-1, 0,1,//7 + + -1.0f, -1.0f, -1.0f, 1.0f, -1,0,0, 0,0, + -1.0f, 1.0f, -1.0f, 1.0f, -1,0,0, 1,0, + -1.0f, 1.0f, 1.0f, 1.0f, -1,0,0, 1,1, + -1.0f, -1.0f, 1.0f, 1.0f, -1,0,0, 0,1, + + 1.0f, -1.0f, -1.0f, 1.0f, 1,0,0, 0,0, + 1.0f, 1.0f, -1.0f, 1.0f, 1,0,0, 1,0, + 1.0f, 1.0f, 1.0f, 1.0f, 1,0,0, 1,1, + 1.0f, -1.0f, 1.0f, 1.0f, 1,0,0, 0,1, + + -1.0f, -1.0f, -1.0f, 1.0f, 0,-1,0, 0,0, + -1.0f, -1.0f, 1.0f, 1.0f, 0,-1,0, 1,0, + 1.0f, -1.0f, 1.0f, 1.0f, 0,-1,0, 1,1, + 1.0f,-1.0f, -1.0f, 1.0f, 0,-1,0, 0,1, + + -1.0f, 1.0f, -1.0f, 1.0f, 0,1,0, 0,0, + -1.0f, 1.0f, 1.0f, 1.0f, 0,1,0, 1,0, + 1.0f, 1.0f, 1.0f, 1.0f, 0,1,0, 1,1, + 1.0f,1.0f, -1.0f, 1.0f, 0,1,0, 0,1, +}; + +static const int cube_indices[]= +{ + 0,1,2,0,2,3,//ground face + 4,5,6,4,6,7,//top face + 8,9,10,8,10,11, + 12,13,14,12,14,15, + 16,17,18,16,18,19, + 20,21,22,20,22,23 +}; + +int m_mouseOldX = -1; +int m_mouseOldY = -1; +int m_mouseButtons = 0; + + +void mouseFunc(int button, int state, int x, int y) +{ + if (state == 0) + { + m_mouseButtons |= 1<0) + { + g_device= btOpenCLUtils::getDevice(g_cxMainContext,0); + btOpenCLDeviceInfo clInfo; + btOpenCLUtils::getDeviceInfo(g_device,clInfo); + btOpenCLUtils::printDeviceInfo(g_device); + // create a command-queue + g_cqCommandQue = clCreateCommandQueue(g_cxMainContext, g_device, 0, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + //normally you would create and execute kernels using this command queue + + } + + +} + +#define NUM_OBJECTS (NUM_OBJECTS_X*NUM_OBJECTS_Y*NUM_OBJECTS_Z) +#define POSITION_BUFFER_SIZE (NUM_OBJECTS*sizeof(float)*4) +#define ORIENTATION_BUFFER_SIZE (NUM_OBJECTS*sizeof(float)*4) +#define COLOR_BUFFER_SIZE (NUM_OBJECTS*sizeof(float)*4) +#define SCALE_BUFFER_SIZE (NUM_OBJECTS*sizeof(float)*3) + + +GLfloat* instance_positions_ptr = 0; +GLfloat* instance_quaternion_ptr = 0; +GLfloat* instance_colors_ptr = 0; +GLfloat* instance_scale_ptr= 0; + + +void DeleteShaders() +{ + glDeleteVertexArrays(1, &cube_vao); + glDeleteBuffers(1,&index_vbo); + glDeleteBuffers(1,&cube_vbo); + glDeleteProgram(instancingShader); +} + + +void InitShaders() +{ + + btOverlappingPairCache* overlappingPairCache=0; +#ifdef USE_NEW + sBroadphase = new btGridBroadphaseCl(overlappingPairCache,btVector3(3.f, 3.f, 3.f), 32, 32, 32,NUM_OBJECTS, NUM_OBJECTS, 64, 100.f, 16, + g_cxMainContext ,g_device,g_cqCommandQue); +#else + sBroadphase = new btGpu3DGridBroadphase(btVector3(10.f, 10.f, 10.f), 32, 32, 32,NUM_OBJECTS, NUM_OBJECTS, 64, 100.f, 16); +#endif + + + +// sBroadphase = new bt3dGridBroadphaseOCL(overlappingPairCache,btVector3(10.f, 10.f, 10.f), 32, 32, 32,NUM_OBJECTS, NUM_OBJECTS, 64, 100.f, 16, +// g_cxMainContext ,g_device,g_cqCommandQue); + + + + bool loadFromFile = false; + instancingShader = gltLoadShaderPair("instancing.vs","instancing.fs", loadFromFile); + + glLinkProgram(instancingShader); + glUseProgram(instancingShader); + angle_loc = glGetUniformLocation(instancingShader, "angle"); + ModelViewMatrix = glGetUniformLocation(instancingShader, "ModelViewMatrix"); + ProjectionMatrix = glGetUniformLocation(instancingShader, "ProjectionMatrix"); + uniform_texture_diffuse = glGetUniformLocation(instancingShader, "Diffuse"); + + GLuint offset = 0; + + + glGenBuffers(1, &cube_vbo); + glBindBuffer(GL_ARRAY_BUFFER, cube_vbo); + + instance_positions_ptr = (GLfloat*)new float[NUM_OBJECTS*4]; + instance_quaternion_ptr = (GLfloat*)new float[NUM_OBJECTS*4]; + instance_colors_ptr = (GLfloat*)new float[NUM_OBJECTS*4]; + instance_scale_ptr = (GLfloat*)new float[NUM_OBJECTS*3]; + + int index=0; + for (int i=0;icreateProxy(aabbMin,aabbMax,shapeType,myptr,1,1,0,0);//m_dispatcher); + proxyArray.push_back(proxy); + + instance_quaternion_ptr[index*4]=0; + instance_quaternion_ptr[index*4+1]=0; + instance_quaternion_ptr[index*4+2]=0; + instance_quaternion_ptr[index*4+3]=1; + + instance_colors_ptr[index*4]=j m_glutScreenHeight) + { + aspect = m_glutScreenWidth / (float)m_glutScreenHeight; + extents.setValue(aspect * 1.0f, 1.0f,0); + } else + { + aspect = m_glutScreenHeight / (float)m_glutScreenWidth; + extents.setValue(1.0f, aspect*1.f,0); + } + + + if (m_ortho) + { + // reset matrix + glLoadIdentity(); + extents *= m_cameraDistance; + btVector3 lower = m_cameraTargetPosition - extents; + btVector3 upper = m_cameraTargetPosition + extents; + glOrtho(lower.getX(), upper.getX(), lower.getY(), upper.getY(),-1000,1000); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + } else + { + if (m_glutScreenWidth > m_glutScreenHeight) + { + glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar); + } else + { + glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar); + } + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(m_cameraPosition[0], m_cameraPosition[1], m_cameraPosition[2], + m_cameraTargetPosition[0], m_cameraTargetPosition[1], m_cameraTargetPosition[2], + m_cameraUp.getX(),m_cameraUp.getY(),m_cameraUp.getZ()); + } + +} + + + +void myinit() +{ + + + + // GLfloat light_ambient[] = { btScalar(0.2), btScalar(0.2), btScalar(0.2), btScalar(1.0) }; + GLfloat light_ambient[] = { btScalar(1.0), btScalar(1.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 )}; + /* light_position is NOT default value */ + GLfloat light_position0[] = { btScalar(10000.0), btScalar(10000.0), btScalar(10000.0), btScalar(0.0 )}; + GLfloat light_position1[] = { btScalar(-1.0), btScalar(-10.0), btScalar(-1.0), btScalar(0.0) }; + + glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT0, GL_POSITION, light_position0); + + glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT1, GL_POSITION, light_position1); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + + + // glShadeModel(GL_FLAT);//GL_SMOOTH); + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + glClearColor(float(0.7),float(0.7),float(0.7),float(0)); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + + static bool m_textureenabled = true; + static bool m_textureinitialized = false; + + + if(m_textureenabled) + { + if(!m_textureinitialized) + { + glActiveTexture(GL_TEXTURE0); + + GLubyte* image=new GLubyte[256*256*3]; + for(int y=0;y<256;++y) + { + const int t=y>>5; + GLubyte* pi=image+y*256*3; + for(int x=0;x<256;++x) + { + const int s=x>>5; + const GLubyte b=180; + GLubyte c=b+((s+t&1)&1)*(255-b); + pi[0]=c; + pi[1]=c; + pi[2]=c; + pi+=3; + } + } + + glGenTextures(1,(GLuint*)&m_texturehandle); + glBindTexture(GL_TEXTURE_2D,m_texturehandle); + glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); + gluBuild2DMipmaps(GL_TEXTURE_2D,3,256,256,GL_RGB,GL_UNSIGNED_BYTE,image); + delete[] image; + m_textureinitialized=true; + } + // glMatrixMode(GL_TEXTURE); + // glLoadIdentity(); + // glMatrixMode(GL_MODELVIEW); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,m_texturehandle); + + } else + { + glDisable(GL_TEXTURE_2D); + } + + glEnable(GL_COLOR_MATERIAL); + + + // glEnable(GL_CULL_FACE); + // glCullFace(GL_BACK); +} + +//#pragma optimize( "g", off ) + + + +void writeTransforms() +{ + + + glFlush(); + char* bla = (char*)glMapBuffer( GL_ARRAY_BUFFER,GL_READ_WRITE);//GL_WRITE_ONLY + + float* positions = (float*)(bla+sizeof(cube_vertices)); + float* orientations = (float*)(bla+sizeof(cube_vertices) + POSITION_BUFFER_SIZE); + float* colors= (float*)(bla+sizeof(cube_vertices) + POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE); + float* scaling= (float*)(bla+sizeof(cube_vertices) + POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE+COLOR_BUFFER_SIZE); + + // positions[0]+=0.001f; + + static int offset=0; + //offset++; + + static btVector3 axis(1,0,0); + sAngle += 0.01f; + int index=0; + btQuaternion orn(axis,sAngle); + for (int i=0;igetCLBUffer(); + cl_int ciErrNum = CL_SUCCESS; + ciErrNum = clEnqueueAcquireGLObjects(g_cqCommandQue, 1, &clBuffer, 0, 0, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + if (runOpenCLKernels) + { + int numObjects = NUM_OBJECTS; + int offset = (sizeof(cube_vertices) )/4; + + ciErrNum = clSetKernelArg(g_sineWaveKernel, 0, sizeof(int), &offset); + ciErrNum = clSetKernelArg(g_sineWaveKernel, 1, sizeof(int), &numObjects); + ciErrNum = clSetKernelArg(g_sineWaveKernel, 2, sizeof(cl_mem), (void*)&clBuffer ); + + ciErrNum = clSetKernelArg(g_sineWaveKernel, 3, sizeof(cl_mem), (void*)&gLinVelMem); + ciErrNum = clSetKernelArg(g_sineWaveKernel, 4, sizeof(cl_mem), (void*)&gAngVelMem); + ciErrNum = clSetKernelArg(g_sineWaveKernel, 5, sizeof(cl_mem), (void*)&gBodyTimes); + + + + + + size_t numWorkItems = workGroupSize*((NUM_OBJECTS + (workGroupSize)) / workGroupSize); + ciErrNum = clEnqueueNDRangeKernel(g_cqCommandQue, g_sineWaveKernel, 1, NULL, &numWorkItems, &workGroupSize,0 ,0 ,0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + + ciErrNum = clEnqueueReleaseGLObjects(g_cqCommandQue, 1, &clBuffer, 0, 0, 0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + clFinish(g_cqCommandQue); + + } + +} + + +void cpuBroadphase() +{ + glFlush(); + char* bla = (char*)glMapBuffer( GL_ARRAY_BUFFER,GL_READ_WRITE);//GL_WRITE_ONLY + + float* positions = (float*)(bla+sizeof(cube_vertices)); + float* orientations = (float*)(bla+sizeof(cube_vertices) + POSITION_BUFFER_SIZE); + float* colors= (float*)(bla+sizeof(cube_vertices) + POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE); + float* scaling= (float*)(bla+sizeof(cube_vertices) + POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE+COLOR_BUFFER_SIZE); + + int index=0; + + for (int i=0;isetAabb(proxyArray[index],aabbMin,aabbMax,0); + + index++; + } + } + } + +#ifdef USE_NEW + + +#else + sBroadphase->calculateOverlappingPairs(0); + int overlap = sBroadphase->getOverlappingPairCache()->getNumOverlappingPairs(); + for (int i=0;igetOverlappingPairCache()->getOverlappingPairArray()[i]; + int indexA = (int)pair.m_pProxy0->m_clientObject; + int indexB = (int)pair.m_pProxy1->m_clientObject; + colors[indexA*4] = 1.f; + colors[indexA*4+1] = 0.f; + colors[indexA*4+2] = 0.f; + colors[indexA*4+3] = 1.f; + + colors[indexB*4] = 1.f; + colors[indexB*4+1] = 0.f; + colors[indexB*4+2] = 0.f; + colors[indexB*4+3] = 1.f; + } +#endif + + //now color the overlap + + + + glUnmapBuffer( GL_ARRAY_BUFFER); + //if this glFinish is removed, the animation is not always working/blocks + //@todo: figure out why + glFlush(); +} + +void broadphase() +{ + if (useCPU) + { + cpuBroadphase(); + + } + else + { + + glFinish(); + + cl_mem clBuffer = g_interopBuffer->getCLBUffer(); + cl_int ciErrNum = CL_SUCCESS; + ciErrNum = clEnqueueAcquireGLObjects(g_cqCommandQue, 1, &clBuffer, 0, 0, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + if (runOpenCLKernels) + { + + gFpIO.m_numObjects = NUM_OBJECTS; + gFpIO.m_positionOffset = (sizeof(cube_vertices) )/4; + gFpIO.m_clObjectsBuffer = clBuffer; + gFpIO.m_dAABB = sBroadphase->m_dAABB; + setupGpuAabbsSimple(gFpIO); + + sBroadphase->calculateOverlappingPairs(0, NUM_OBJECTS); + + + gFpIO.m_dAllOverlappingPairs = sBroadphase->m_dAllOverlappingPairs; + gFpIO.m_numOverlap = sBroadphase->m_numPrefixSum; + + colorPairsOpenCL(gFpIO); + + } + + ciErrNum = clEnqueueReleaseGLObjects(g_cqCommandQue, 1, &clBuffer, 0, 0, 0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + clFinish(g_cqCommandQue); + + + + } +} + + +//#pragma optimize( "g", on ) + +void RenderScene(void) +{ + +#if 0 + float modelview[20]={0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9}; + // get the current modelview matrix + glGetFloatv(GL_MODELVIEW_MATRIX , modelview); + float projection[20]={0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9}; + glGetFloatv(GL_PROJECTION_MATRIX, projection); +#endif + + myinit(); + + updateCamera(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //render coordinate system + glBegin(GL_LINES); + glColor3f(1,0,0); + glVertex3f(0,0,0); + glVertex3f(1,0,0); + glColor3f(0,1,0); + glVertex3f(0,0,0); + glVertex3f(0,1,0); + glColor3f(0,0,1); + glVertex3f(0,0,0); + glVertex3f(0,0,1); + glEnd(); + + //do a finish, to make sure timings are clean + // glFinish(); + + float start = gStopwatch.getTimeMilliseconds(); + + // glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, cube_vbo); + glFlush(); + + updatePos(); + + broadphase(); + + //useCPU = true; + + float stop = gStopwatch.getTimeMilliseconds(); + gStopwatch.reset(); + + if (printStats) + { + printf("updatePos=%f ms on ",stop-start); + + if (useCPU) + { + printf("CPU \n"); + } else + { + printf("OpenCL "); + if (runOpenCLKernels) + printf("running the kernels"); + else + printf("without running the kernels"); + printf("\n"); + } + } + + glBindVertexArray(cube_vao); + + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 9*sizeof(float), 0); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(sizeof(cube_vertices))); + glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(sizeof(cube_vertices)+POSITION_BUFFER_SIZE)); + int uvoffset = 7*sizeof(float); + int normaloffset = 4*sizeof(float); + + glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid *)uvoffset); + glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid *)normaloffset); + glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(sizeof(cube_vertices)+POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE)); + glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(sizeof(cube_vertices)+POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE+COLOR_BUFFER_SIZE)); + + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glEnableVertexAttribArray(2); + glEnableVertexAttribArray(3); + glEnableVertexAttribArray(4); + glEnableVertexAttribArray(5); + glEnableVertexAttribArray(6); + + glVertexAttribDivisor(0, 0); + glVertexAttribDivisor(1, 1); + glVertexAttribDivisor(2, 1); + glVertexAttribDivisor(3, 0); + glVertexAttribDivisor(4, 0); + glVertexAttribDivisor(5, 1); + glVertexAttribDivisor(6, 1); + + glUseProgram(instancingShader); + glUniform1f(angle_loc, 0); + GLfloat pm[16]; + glGetFloatv(GL_PROJECTION_MATRIX, pm); + glUniformMatrix4fv(ProjectionMatrix, 1, false, &pm[0]); + + GLfloat mvm[16]; + glGetFloatv(GL_MODELVIEW_MATRIX, mvm); + glUniformMatrix4fv(ModelViewMatrix, 1, false, &mvm[0]); + + glUniform1i(uniform_texture_diffuse, 0); + + glFlush(); + int numInstances = NUM_OBJECTS; + int indexCount = sizeof(cube_indices)/sizeof(int); + int indexOffset = 0; + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_vbo); + glDrawElementsInstanced(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, (void*)indexOffset, numInstances); + + glUseProgram(0); + glBindBuffer(GL_ARRAY_BUFFER,0); + glBindVertexArray(0); + + glutSwapBuffers(); + glutPostRedisplay(); + + GLint err = glGetError(); + assert(err==GL_NO_ERROR); +} + + +void ChangeSize(int w, int h) +{ + m_glutScreenWidth = w; + m_glutScreenHeight = h; + +#ifdef RECREATE_CL_AND_SHADERS_ON_RESIZE + delete g_interopBuffer; + clReleaseKernel(g_sineWaveKernel); + releaseFindPairs(fpio); + DeleteCL(); + DeleteShaders(); +#endif //RECREATE_CL_AND_SHADERS_ON_RESIZE + + // Set Viewport to window dimensions + glViewport(0, 0, w, h); + +#ifdef RECREATE_CL_AND_SHADERS_ON_RESIZE + InitCL(); + InitShaders(); + + g_interopBuffer = new btOpenCLGLInteropBuffer(g_cxMainContext,g_cqCommandQue,cube_vbo); + clFinish(g_cqCommandQue); + g_sineWaveKernel = btOpenCLUtils::compileCLKernelFromString(g_cxMainContext, interopKernelString, "interopKernel" ); + initFindPairs(...); +#endif //RECREATE_CL_AND_SHADERS_ON_RESIZE + +} + +void Keyboard(unsigned char key, int x, int y) +{ + switch (key) + { + case 27: + done = true; + break; + case 'O': + case 'o': + { + m_ortho = !m_ortho; + break; + } + case 'c': + case 'C': + { + useCPU = !useCPU; + if (useCPU) + printf("using CPU\n"); + else + printf("using OpenCL\n"); + break; + } + case 's': + case 'S': + { + printStats = !printStats; + break; + } + case 'k': + case 'K': + { + runOpenCLKernels=!runOpenCLKernels; + break; + } + case 'q': + case 'Q': + exit(0); + default: + break; + } +} + +// Cleanup +void ShutdownRC(void) +{ + glDeleteBuffers(1, &cube_vbo); + glDeleteVertexArrays(1, &cube_vao); +} + +int main(int argc, char* argv[]) +{ + srand(0); + // printf("vertexShader = \n%s\n",vertexShader); + // printf("fragmentShader = \n%s\n",fragmentShader); + + glutInit(&argc, argv); + + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); + + + glutInitWindowSize(m_glutScreenWidth, m_glutScreenHeight); + char buf[1024]; + sprintf(buf,"OpenCL broadphase benchmark, %d cubes on the GPU", NUM_OBJECTS); + glutCreateWindow(buf); + + glutReshapeFunc(ChangeSize); + + glutMouseFunc(mouseFunc); + glutMotionFunc(mouseMotionFunc); + + glutKeyboardFunc(Keyboard); + glutDisplayFunc(RenderScene); + + GLenum err = glewInit(); + if (GLEW_OK != err) + { + /* Problem: glewInit failed, something is seriously wrong. */ + fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); + } + + //ChangeSize(m_glutScreenWidth,m_glutScreenHeight); + + InitCL(); + + +#define CUSTOM_CL_INITIALIZATION +#ifdef CUSTOM_CL_INITIALIZATION + g_deviceCL = new adl::DeviceCL(); + g_deviceCL->m_deviceIdx = g_device; + g_deviceCL->m_context = g_cxMainContext; + g_deviceCL->m_commandQueue = g_cqCommandQue; + +#else + DeviceUtils::Config cfg; + cfg.m_type = DeviceUtils::Config::DEVICE_CPU; + g_deviceCL = DeviceUtils::allocate( TYPE_CL, cfg ); +#endif + + int size = NUM_OBJECTS; + adl::Buffer linvelBuf( g_deviceCL, size ); + adl::Buffer angvelBuf( g_deviceCL, size ); + adl::Buffer bodyTimes(g_deviceCL,size); + + gLinVelMem = (cl_mem)linvelBuf.m_ptr; + gAngVelMem = (cl_mem)angvelBuf.m_ptr; + gBodyTimes = (cl_mem)bodyTimes.m_ptr; + + btVector3* linVelHost= new btVector3[size]; + btVector3* angVelHost = new btVector3[size]; + float* bodyTimesHost = new float[size]; + + for (int i=0;i + +cl_context g_cxMainContext; +cl_command_queue g_cqCommandQue; +cl_kernel g_atomicsKernel; +static const size_t workGroupSize = 128;//todo figure out an appropriate workgroup size suitable for the OpenCL platform/context/device/kernel +#define NUM_OBJECTS 1024 + +#include "globalAtomicsKernel.h" + + +char * findAndReplace( char const * const original, char const * const pattern, char const * const replacement); + + +#include +#include + + +int main(int argc, char* argv[]) +{ + int ciErrNum = 0; + + printf("press a key to start\n"); + getchar(); + + const char* vendorSDK = btOpenCLUtils::getSdkVendorName(); + printf("This program was compiled using the %s OpenCL SDK\n",vendorSDK); + + cl_device_type deviceType = CL_DEVICE_TYPE_GPU;//CL_DEVICE_TYPE_ALL + + void* glCtx=0; + void* glDC = 0; + printf("Initialize OpenCL using btOpenCLUtils::createContextFromType for CL_DEVICE_TYPE_GPU\n"); + g_cxMainContext = btOpenCLUtils::createContextFromType(deviceType, &ciErrNum, glCtx, glDC); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + int numDev = btOpenCLUtils::getNumDevices(g_cxMainContext); + + if (numDev>0) + { + int deviceIndex=0; + + cl_device_id device; + device = btOpenCLUtils::getDevice(g_cxMainContext,deviceIndex); + btOpenCLDeviceInfo clInfo; + btOpenCLUtils::getDeviceInfo(device,clInfo); + btOpenCLUtils::printDeviceInfo(device); + + + const char* globalAtomicsKernelStringPatched = globalAtomicsKernelString; + if (!strstr(clInfo.m_deviceExtensions,"cl_ext_atomic_counters_32")) + { + globalAtomicsKernelStringPatched = findAndReplace(globalAtomicsKernelString,"counter32_t", "volatile __global int*"); + } + + + + // create a command-queue + g_cqCommandQue = clCreateCommandQueue(g_cxMainContext, device, 0, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + cl_mem counterBuffer = clCreateBuffer(g_cxMainContext, CL_MEM_READ_WRITE, sizeof(int), NULL, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + char* kernelMethods[] = + { + "globalAtomicKernelOpenCL1_1", + "counterAtomicKernelExt", + "globalAtomicKernelExt", + "globalAtomicKernelCounters32Broken" + }; + int numKernelMethods = sizeof(kernelMethods)/sizeof(char*); + + for (int i=0;i +#include + +char * findAndReplace( + char const * const original, + char const * const pattern, + char const * const replacement +) { + size_t const replen = strlen(replacement); + size_t const patlen = strlen(pattern); + size_t const orilen = strlen(original); + + size_t patcnt = 0; + const char * oriptr; + const char * patloc; + + // find how many times the pattern occurs in the original string + for (oriptr = original; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen) + { + patcnt++; + } + + { + // allocate memory for the new string + size_t const retlen = orilen + patcnt * (replen - patlen); + char * const returned = (char *) malloc( sizeof(char) * (retlen + 1) ); + + if (returned != NULL) + { + // copy the original string, + // replacing all the instances of the pattern + char * retptr = returned; + for (oriptr = original; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen) + { + size_t const skplen = patloc - oriptr; + // copy the section until the occurence of the pattern + strncpy(retptr, oriptr, skplen); + retptr += skplen; + // copy the replacement + strncpy(retptr, replacement, replen); + retptr += replen; + } + // copy the rest of the string. + strcpy(retptr, oriptr); + } + return returned; + } +} + +#ifdef _WIN32 +#pragma warning( pop ) +#endif //_WIN32 diff --git a/Extras/RigidBodyGpuPipeline/opencl/global_atomics/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/global_atomics/premake4.lua new file mode 100644 index 0000000..3a926c9 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/global_atomics/premake4.lua @@ -0,0 +1,4 @@ + + include "AMD" + --include "Intel" + --include "NVIDIA" diff --git a/Extras/RigidBodyGpuPipeline/opencl/global_atomics/stringify.py b/Extras/RigidBodyGpuPipeline/opencl/global_atomics/stringify.py new file mode 100644 index 0000000..e79e281 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/global_atomics/stringify.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +import sys +import os +import shutil + +arg = sys.argv[1] +fh = open(arg) + +print 'static const char* '+sys.argv[2]+'= \\' +for line in fh.readlines(): + a = line.strip('\n') + print '"'+a+'\\n"' +print ';' diff --git a/Extras/RigidBodyGpuPipeline/opencl/global_atomics/stringifykernels.bat b/Extras/RigidBodyGpuPipeline/opencl/global_atomics/stringifykernels.bat new file mode 100644 index 0000000..1415f8e --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/global_atomics/stringifykernels.bat @@ -0,0 +1,5 @@ +stringify.py global_atomics.cl globalAtomicsKernelString >globalAtomicsKernel.h + + + + diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/AMD/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/AMD/premake4.lua new file mode 100644 index 0000000..2000f3e --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/AMD/premake4.lua @@ -0,0 +1,58 @@ + + hasCL = findOpenCL_AMD() + + if (hasCL) then + + project "OpenCL_gpu_rigidbody_pipeline_AMD" + + initOpenCL_AMD() + + language "C++" + + kind "ConsoleApp" + targetdir "../../../bin" + + initOpenGL() + initGlut() + initGlew() + + + includedirs { + "../../../rendering/BulletMath", + "../../primitives", + "../../../../../src" + } + + files { + "../main.cpp", + "../btConvexUtility.cpp", + "../btConvexUtility.h", + "../btGpuNarrowPhaseAndSolver.cpp", + "../btGpuNarrowPhaseAndSolver.h", + "../../../dynamics/basic_demo/ConvexHeightFieldShape.cpp", + "../../../dynamics/basic_demo/ConvexHeightFieldShape.h", + "../../../../../src/LinearMath/btConvexHullComputer.cpp", + "../../../../../src/LinearMath/btConvexHullComputer.h", + "../../broadphase_benchmark/findPairsOpenCL.cpp", + "../../broadphase_benchmark/findPairsOpenCL.h", + "../../broadphase_benchmark/btGridBroadphaseCL.cpp", + "../../broadphase_benchmark/btGridBroadphaseCL.h", + "../../3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.cpp", + "../../3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.h", + "../../3dGridBroadphase/Shared/btGpu3DGridBroadphase.cpp", + "../../3dGridBroadphase/Shared/btGpu3DGridBroadphase.h", + "../../../../../src/LinearMath/btAlignedAllocator.cpp", + "../../../../../src/LinearMath/btQuickprof.cpp", + "../../../../../src/LinearMath/btQuickprof.h", + "../../../../../src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp", + "../../../../../src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp", + "../../../../../src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp", + "../../basic_initialize/btOpenCLUtils.cpp", + "../../basic_initialize/btOpenCLUtils.h", + "../../opengl_interop/btOpenCLGLInteropBuffer.cpp", + "../../opengl_interop/btOpenCLGLInteropBuffer.h", + "../../opengl_interop/btStopwatch.cpp", + "../../opengl_interop/btStopwatch.h" + } + + end \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/CommandLineArgs.h b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/CommandLineArgs.h new file mode 100644 index 0000000..b646103 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/CommandLineArgs.h @@ -0,0 +1,91 @@ +#ifndef COMMAND_LINE_ARGS_H +#define COMMAND_LINE_ARGS_H + +/****************************************************************************** + * Command-line parsing + ******************************************************************************/ +#include +#include +#include +#include +class CommandLineArgs +{ +protected: + + std::map pairs; + +public: + + // Constructor + CommandLineArgs(int argc, char **argv) + { + using namespace std; + + for (int i = 1; i < argc; i++) + { + string arg = argv[i]; + + if ((arg[0] != '-') || (arg[1] != '-')) { + continue; + } + + string::size_type pos; + string key, val; + if ((pos = arg.find( '=')) == string::npos) { + key = string(arg, 2, arg.length() - 2); + val = ""; + } else { + key = string(arg, 2, pos - 2); + val = string(arg, pos + 1, arg.length() - 1); + } + pairs[key] = val; + } + } + + bool CheckCmdLineFlag(const char* arg_name) + { + using namespace std; + map::iterator itr; + if ((itr = pairs.find(arg_name)) != pairs.end()) { + return true; + } + return false; + } + + template + void GetCmdLineArgument(const char *arg_name, T &val); + + int ParsedArgc() + { + return pairs.size(); + } +}; + +template +void CommandLineArgs::GetCmdLineArgument(const char *arg_name, T &val) +{ + using namespace std; + map::iterator itr; + if ((itr = pairs.find(arg_name)) != pairs.end()) { + istringstream strstream(itr->second); + strstream >> val; + } +} + +template <> +void CommandLineArgs::GetCmdLineArgument(const char* arg_name, char* &val) +{ + using namespace std; + map::iterator itr; + if ((itr = pairs.find(arg_name)) != pairs.end()) { + + string s = itr->second; + val = (char*) malloc(sizeof(char) * (s.length() + 1)); + strcpy(val, s.c_str()); + + } else { + val = NULL; + } +} + +#endif //COMMAND_LINE_ARGS_H diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/Intel/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/Intel/premake4.lua new file mode 100644 index 0000000..541dc79 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/Intel/premake4.lua @@ -0,0 +1,58 @@ + + hasCL = findOpenCL_Intel() + + if (hasCL) then + + project "OpenCL_gpu_rigidbody_pipeline_Intel" + + initOpenCL_Intel() + + language "C++" + + kind "ConsoleApp" + targetdir "../../../bin" + + initOpenGL() + initGlut() + initGlew() + + + includedirs { + "../../../rendering/BulletMath", + "../../primitives", + "../../../../../src" + } + + files { + "../main.cpp", + "../btConvexUtility.cpp", + "../btConvexUtility.h", + "../btGpuNarrowPhaseAndSolver.cpp", + "../btGpuNarrowPhaseAndSolver.h", + "../../../dynamics/basic_demo/ConvexHeightFieldShape.cpp", + "../../../dynamics/basic_demo/ConvexHeightFieldShape.h", + "../../../../../src/LinearMath/btConvexHullComputer.cpp", + "../../../../../src/LinearMath/btConvexHullComputer.h", + "../../broadphase_benchmark/findPairsOpenCL.cpp", + "../../broadphase_benchmark/findPairsOpenCL.h", + "../../broadphase_benchmark/btGridBroadphaseCL.cpp", + "../../broadphase_benchmark/btGridBroadphaseCL.h", + "../../3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.cpp", + "../../3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.h", + "../../3dGridBroadphase/Shared/btGpu3DGridBroadphase.cpp", + "../../3dGridBroadphase/Shared/btGpu3DGridBroadphase.h", + "../../../../../src/LinearMath/btAlignedAllocator.cpp", + "../../../../../src/LinearMath/btQuickprof.cpp", + "../../../../../src/LinearMath/btQuickprof.h", + "../../../../../src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp", + "../../../../../src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp", + "../../../../../src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp", + "../../basic_initialize/btOpenCLUtils.cpp", + "../../basic_initialize/btOpenCLUtils.h", + "../../opengl_interop/btOpenCLGLInteropBuffer.cpp", + "../../opengl_interop/btOpenCLGLInteropBuffer.h", + "../../opengl_interop/btStopwatch.cpp", + "../../opengl_interop/btStopwatch.h" + } + + end \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/NVIDIA/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/NVIDIA/premake4.lua new file mode 100644 index 0000000..095e08f --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/NVIDIA/premake4.lua @@ -0,0 +1,57 @@ + + hasCL = findOpenCL_NVIDIA() + + if (hasCL) then + + project "OpenCL_gpu_rigidbody_pipeline_NVIDIA" + + initOpenCL_NVIDIA() + + language "C++" + + kind "ConsoleApp" + targetdir "../../../bin" + + initOpenGL() + initGlut() + initGlew() + + includedirs { + "../../../rendering/BulletMath", + "../../primitives", + "../../../../../src" + } + + files { + "../main.cpp", + "../btConvexUtility.cpp", + "../btConvexUtility.h", + "../btGpuNarrowPhaseAndSolver.cpp", + "../btGpuNarrowPhaseAndSolver.h", + "../../../dynamics/basic_demo/ConvexHeightFieldShape.cpp", + "../../../dynamics/basic_demo/ConvexHeightFieldShape.h", + "../../../../../src/LinearMath/btConvexHullComputer.cpp", + "../../../../../src/LinearMath/btConvexHullComputer.h", + "../../broadphase_benchmark/findPairsOpenCL.cpp", + "../../broadphase_benchmark/findPairsOpenCL.h", + "../../broadphase_benchmark/btGridBroadphaseCL.cpp", + "../../broadphase_benchmark/btGridBroadphaseCL.h", + "../../3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.cpp", + "../../3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.h", + "../../3dGridBroadphase/Shared/btGpu3DGridBroadphase.cpp", + "../../3dGridBroadphase/Shared/btGpu3DGridBroadphase.h", + "../../../../../src/LinearMath/btAlignedAllocator.cpp", + "../../../../../src/LinearMath/btQuickprof.cpp", + "../../../../../src/LinearMath/btQuickprof.h", + "../../../../../src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp", + "../../../../../src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp", + "../../../../../src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp", + "../../basic_initialize/btOpenCLUtils.cpp", + "../../basic_initialize/btOpenCLUtils.h", + "../../opengl_interop/btOpenCLGLInteropBuffer.cpp", + "../../opengl_interop/btOpenCLGLInteropBuffer.h", + "../../opengl_interop/btStopwatch.cpp", + "../../opengl_interop/btStopwatch.h" + } + + end \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/btConvexUtility.cpp b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/btConvexUtility.cpp new file mode 100644 index 0000000..7f24449 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/btConvexUtility.cpp @@ -0,0 +1,240 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + + +#include "btConvexUtility.h" +#include "LinearMath/btConvexHullComputer.h" +#include "LinearMath/btGrahamScan2dConvexHull.h" +#include "LinearMath/btQuaternion.h" + +bool btConvexUtility::initializePolyhedralFeatures(const btAlignedObjectArray& orgVertices, bool mergeCoplanarTriangles) +{ + + + btConvexHullComputer conv; + conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f); + + btAlignedObjectArray faceNormals; + int numFaces = conv.faces.size(); + faceNormals.resize(numFaces); + btConvexHullComputer* convexUtil = &conv; + + + btAlignedObjectArray tmpFaces; + tmpFaces.resize(numFaces); + + int numVertices = convexUtil->vertices.size(); + m_vertices.resize(numVertices); + for (int p=0;pvertices[p]; + } + + + for (int i=0;ifaces[i]; + //printf("face=%d\n",face); + const btConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face]; + const btConvexHullComputer::Edge* edge = firstEdge; + + btVector3 edges[3]; + int numEdges = 0; + //compute face normals + + btScalar maxCross2 = 0.f; + int chosenEdge = -1; + + do + { + + int src = edge->getSourceVertex(); + tmpFaces[i].m_indices.push_back(src); + int targ = edge->getTargetVertex(); + btVector3 wa = convexUtil->vertices[src]; + + btVector3 wb = convexUtil->vertices[targ]; + btVector3 newEdge = wb-wa; + newEdge.normalize(); + if (numEdges<2) + edges[numEdges++] = newEdge; + + edge = edge->getNextEdgeOfFace(); + } while (edge!=firstEdge); + + btScalar planeEq = 1e30f; + + + if (numEdges==2) + { + faceNormals[i] = edges[0].cross(edges[1]); + faceNormals[i].normalize(); + tmpFaces[i].m_plane[0] = faceNormals[i].getX(); + tmpFaces[i].m_plane[1] = faceNormals[i].getY(); + tmpFaces[i].m_plane[2] = faceNormals[i].getZ(); + tmpFaces[i].m_plane[3] = planeEq; + + } + else + { + btAssert(0);//degenerate? + faceNormals[i].setZero(); + } + + for (int v=0;veq) + { + planeEq=eq; + } + } + tmpFaces[i].m_plane[3] = -planeEq; + } + + //merge coplanar faces + + btScalar faceWeldThreshold= 0.999f; + btAlignedObjectArray todoFaces; + for (int i=0;i coplanarFaceGroup; + int refFace = todoFaces[todoFaces.size()-1]; + + coplanarFaceGroup.push_back(refFace); + btFace& faceA = tmpFaces[refFace]; + todoFaces.pop_back(); + + btVector3 faceNormalA(faceA.m_plane[0],faceA.m_plane[1],faceA.m_plane[2]); + for (int j=todoFaces.size()-1;j>=0;j--) + { + int i = todoFaces[j]; + btFace& faceB = tmpFaces[i]; + btVector3 faceNormalB(faceB.m_plane[0],faceB.m_plane[1],faceB.m_plane[2]); + if (faceNormalA.dot(faceNormalB)>faceWeldThreshold) + { + coplanarFaceGroup.push_back(i); + todoFaces.remove(i); + } + } + + + bool did_merge = false; + if (mergeCoplanarTriangles && coplanarFaceGroup.size()>1) + { + //do the merge: use Graham Scan 2d convex hull + + btAlignedObjectArray orgpoints; + + for (int i=0;i hull; + GrahamScanConvexHull2D(orgpoints,hull); + + for (int i=0;i m_indices; +// btAlignedObjectArray m_connectedFaces; + btScalar m_plane[4]; +}; + +class btConvexUtility +{ + public: + + btAlignedObjectArray m_vertices; + btAlignedObjectArray m_faces; + + bool initializePolyhedralFeatures(const btAlignedObjectArray& orgVertices, bool mergeCoplanarTriangles); + +}; +#endif + \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/btGpuNarrowPhaseAndSolver.cpp b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/btGpuNarrowPhaseAndSolver.cpp new file mode 100644 index 0000000..6f377af --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/btGpuNarrowPhaseAndSolver.cpp @@ -0,0 +1,730 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + +#include "btGpuNarrowphaseAndSolver.h" + +//#include "CustomConvexShape.h" +//#include "CustomConvexPairCollision.h" +#include "LinearMath/btQuickprof.h" + + +//#include "BulletDynamics/Dynamics/btRigidBody.h" + +#include "Adl/Adl.h" +#include "../../dynamics/basic_demo/Stubs/AdlMath.h" +#include "../../dynamics/basic_demo/Stubs/AdlContact4.h" +#include "../../dynamics/basic_demo/Stubs/AdlQuaternion.h" +#include "../../dynamics/basic_demo/Stubs/ChNarrowPhase.h" +#include "../../dynamics/basic_demo/Stubs/Solver.h" +#include + +int gpuBatchContacts = 1; + +int numPairsOut =0; +struct CPUSolveData +{ + u32 m_n[adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT]; + u32 m_offset[adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT]; +}; + + +struct ParallelSolveData +{ + adl::Buffer* m_numConstraints; + adl::Buffer* m_offsets; +}; + +struct CustomDispatchData +{ + adl::DeviceCL* m_deviceCL; + adl::Device* m_deviceHost; + ShapeDataType m_ShapeBuffer; + adl::HostBuffer* m_shapePointers; + + adl::HostBuffer* m_pBufPairsCPU; + + adl::Buffer* m_convexPairsOutGPU; + adl::Buffer* m_planePairs; + + adl::Buffer* m_pBufContactOutGPU; + adl::HostBuffer* m_pBufContactOutCPU; + adl::ChNarrowphase::Data* m_Data; + + + + adl::HostBuffer* m_bodyBufferCPU; + adl::Buffer* m_bodyBufferGPU; + + adl::Buffer* m_inertiaBufferCPU; + adl::Buffer* m_inertiaBufferGPU; + + adl::Solver::Data* m_solverDataGPU; + SolverData m_contactCGPU; + void* m_frictionCGPU; + + int m_numAcceleratedShapes; + int m_numAcceleratedRigidBodies; +}; + + +btGpuNarrowphaseAndSolver::btGpuNarrowphaseAndSolver(adl::DeviceCL* deviceCL) + :m_internalData(0) ,m_planeBodyIndex(-1) +{ + + if (deviceCL) + { + m_internalData = new CustomDispatchData(); + memset(m_internalData,0,sizeof(CustomDispatchData)); + + adl::DeviceUtils::Config cfg; + m_internalData->m_deviceCL = deviceCL; + + + m_internalData->m_deviceHost = adl::DeviceUtils::allocate( adl::TYPE_HOST, cfg ); + m_internalData->m_pBufPairsCPU = new adl::HostBuffer(m_internalData->m_deviceHost, MAX_BROADPHASE_COLLISION_CL); + + m_internalData->m_convexPairsOutGPU = new adl::Buffer(m_internalData->m_deviceCL,MAX_BROADPHASE_COLLISION_CL); + m_internalData->m_planePairs = new adl::Buffer(m_internalData->m_deviceCL,MAX_BROADPHASE_COLLISION_CL); + + m_internalData->m_pBufContactOutCPU = new adl::HostBuffer(m_internalData->m_deviceHost, MAX_BROADPHASE_COLLISION_CL); + m_internalData->m_bodyBufferCPU = new adl::HostBuffer(m_internalData->m_deviceHost, MAX_CONVEX_BODIES_CL); + + m_internalData->m_inertiaBufferCPU = new adl::Buffer(m_internalData->m_deviceHost,MAX_CONVEX_BODIES_CL); + m_internalData->m_pBufContactOutGPU = new adl::Buffer(m_internalData->m_deviceCL, MAX_BROADPHASE_COLLISION_CL); + m_internalData->m_inertiaBufferGPU = new adl::Buffer(m_internalData->m_deviceCL,MAX_CONVEX_BODIES_CL); + + m_internalData->m_solverDataGPU = adl::Solver::allocate( m_internalData->m_deviceCL, MAX_BROADPHASE_COLLISION_CL); + m_internalData->m_bodyBufferGPU = new adl::Buffer(m_internalData->m_deviceCL, MAX_CONVEX_BODIES_CL); + m_internalData->m_Data = adl::ChNarrowphase::allocate(m_internalData->m_deviceCL); +// m_internalData->m_DataCPU = adl::ChNarrowphase::allocate(m_internalData->m_deviceHost); + + + m_internalData->m_ShapeBuffer = adl::ChNarrowphase::allocateShapeBuffer(m_internalData->m_deviceCL, MAX_CONVEX_SHAPES_CL); + + m_internalData->m_shapePointers = new adl::HostBuffer(m_internalData->m_deviceHost,MAX_CONVEX_SHAPES_CL); + + m_internalData->m_numAcceleratedShapes = 0; + m_internalData->m_numAcceleratedRigidBodies = 0; + + m_internalData->m_contactCGPU = adl::Solver::allocateConstraint4( m_internalData->m_deviceCL, MAX_BROADPHASE_COLLISION_CL); + m_internalData->m_frictionCGPU = adl::Solver::allocateFrictionConstraint( m_internalData->m_deviceCL, MAX_BROADPHASE_COLLISION_CL); + + } +} + +int btGpuNarrowphaseAndSolver::registerShape(ConvexHeightField* convexShape) +{ + (*m_internalData->m_shapePointers)[m_internalData->m_numAcceleratedShapes] = convexShape; + adl::ChNarrowphase::setShape(m_internalData->m_ShapeBuffer, convexShape, m_internalData->m_numAcceleratedShapes, 0.01f); + return m_internalData->m_numAcceleratedShapes++; +} + +cl_mem btGpuNarrowphaseAndSolver::getBodiesGpu() +{ + return (cl_mem)m_internalData->m_bodyBufferGPU->m_ptr; +} + +cl_mem btGpuNarrowphaseAndSolver::getBodyInertiasGpu() +{ + return (cl_mem)m_internalData->m_inertiaBufferGPU->m_ptr; +} + + +int btGpuNarrowphaseAndSolver::registerRigidBody(int shapeIndex, float mass, const float* position, const float* orientation , bool writeToGpu) +{ + assert(m_internalData->m_numAcceleratedRigidBodies< (MAX_CONVEX_BODIES_CL-1)); + + RigidBodyBase::Body& body = m_internalData->m_bodyBufferCPU->m_ptr[m_internalData->m_numAcceleratedRigidBodies]; + + float friction = 1.f; + float restitution = 0.f; + + body.m_frictionCoeff = friction; + body.m_restituitionCoeff = restitution; + body.m_angVel = make_float4(0.f); + body.m_linVel = make_float4(0.f); + body.m_pos = make_float4(position[0],position[1],position[2],0.f); + body.m_quat = make_float4(orientation[0],orientation[1],orientation[2],orientation[3]); + body.m_shapeIdx = shapeIndex; + if (shapeIndex<0) + { + body.m_shapeType = CollisionShape::SHAPE_PLANE; + m_planeBodyIndex = m_internalData->m_numAcceleratedRigidBodies; + } else + { + body.m_shapeType = CollisionShape::SHAPE_CONVEX_HEIGHT_FIELD; + } + + body.m_invMass = mass? 1.f/mass : 0.f; + + if (writeToGpu) + m_internalData->m_bodyBufferGPU->write(&body,1,m_internalData->m_numAcceleratedRigidBodies); + + RigidBodyBase::Inertia& shapeInfo = m_internalData->m_inertiaBufferCPU->m_ptr[m_internalData->m_numAcceleratedRigidBodies]; + + if (mass==0.f) + { + shapeInfo.m_initInvInertia = mtZero(); + shapeInfo.m_invInertia = mtZero(); + } else + { + + assert(body.m_shapeIdx>=0); + + //approximate using the aabb of the shape + + Aabb aabb = (*m_internalData->m_shapePointers)[shapeIndex]->m_aabb; + float4 halfExtents = (aabb.m_max - aabb.m_min); + + float4 localInertia; + + float lx=2.f*halfExtents.x; + float ly=2.f*halfExtents.y; + float lz=2.f*halfExtents.z; + + localInertia = make_float4( (mass/12.0f) * (ly*ly + lz*lz), + (mass/12.0f) * (lx*lx + lz*lz), + (mass/12.0f) * (lx*lx + ly*ly)); + + float4 invLocalInertia; + invLocalInertia.x = 1.f/localInertia.x; + invLocalInertia.y = 1.f/localInertia.y; + invLocalInertia.z = 1.f/localInertia.z; + invLocalInertia.w = 0.f; + + shapeInfo.m_initInvInertia = mtZero(); + shapeInfo.m_initInvInertia.m_row[0].x = invLocalInertia.x; + shapeInfo.m_initInvInertia.m_row[1].y = invLocalInertia.y; + shapeInfo.m_initInvInertia.m_row[2].z = invLocalInertia.z; + + Matrix3x3 m = qtGetRotationMatrix( body.m_quat); + Matrix3x3 mT = mtTranspose( m ); + shapeInfo.m_invInertia = mtMul( mtMul( m, shapeInfo.m_initInvInertia ), mT ); + + } + + if (writeToGpu) + m_internalData->m_inertiaBufferGPU->write(&shapeInfo,1,m_internalData->m_numAcceleratedRigidBodies); + return m_internalData->m_numAcceleratedRigidBodies++; +} + +void btGpuNarrowphaseAndSolver::writeAllBodiesToGpu() +{ + m_internalData->m_bodyBufferGPU->write(m_internalData->m_bodyBufferCPU->m_ptr,m_internalData->m_numAcceleratedRigidBodies); + m_internalData->m_inertiaBufferGPU->write( m_internalData->m_inertiaBufferCPU->m_ptr,m_internalData->m_numAcceleratedRigidBodies); +} + + + +btGpuNarrowphaseAndSolver::~btGpuNarrowphaseAndSolver(void) +{ + if (m_internalData) + { + delete m_internalData->m_pBufPairsCPU; + delete m_internalData->m_convexPairsOutGPU; + delete m_internalData->m_planePairs; + delete m_internalData->m_pBufContactOutGPU; + delete m_internalData->m_inertiaBufferGPU; + delete m_internalData->m_pBufContactOutCPU; + delete m_internalData->m_shapePointers; + adl::ChNarrowphase::deallocateShapeBuffer(m_internalData->m_ShapeBuffer); + delete m_internalData->m_inertiaBufferCPU; + adl::Solver::deallocateConstraint4( m_internalData->m_contactCGPU ); + adl::Solver::deallocateFrictionConstraint( m_internalData->m_frictionCGPU ); + + delete m_internalData->m_bodyBufferGPU; + adl::Solver::deallocate( m_internalData->m_solverDataGPU); + delete m_internalData->m_bodyBufferCPU; + adl::ChNarrowphase::deallocate(m_internalData->m_Data); + + + + adl::DeviceUtils::deallocate(m_internalData->m_deviceHost); + + delete m_internalData; + } + +} + + + + + +void btGpuNarrowphaseAndSolver::computeContactsAndSolver(cl_mem broadphasePairs, int numBroadphasePairs) +{ + + BT_PROFILE("computeContactsAndSolver"); + bool bGPU = (m_internalData != 0); + int maxBodyIndex = m_internalData->m_numAcceleratedRigidBodies; + + if (!maxBodyIndex) + return; + int numOfConvexRBodies = maxBodyIndex; + + adl::ChNarrowphaseBase::Config cfgNP; + cfgNP.m_collisionMargin = 0.01f; + int nContactOut = 0; + //printf("convexPairsOut.m_size = %d\n",m_internalData->m_convexPairsOutGPU->m_size); + + + adl::Buffer broadphasePairsGPU; + broadphasePairsGPU.m_ptr = (int2*)broadphasePairs; + broadphasePairsGPU.m_size = numBroadphasePairs; + broadphasePairsGPU.m_device = m_internalData->m_deviceCL; + + + bool useCulling = true; + if (useCulling) + { + BT_PROFILE("ChNarrowphase::culling"); + adl::DeviceUtils::waitForCompletion(m_internalData->m_deviceCL); + + numPairsOut = adl::ChNarrowphase::culling( + m_internalData->m_Data, + &broadphasePairsGPU, + numBroadphasePairs, + m_internalData->m_bodyBufferGPU, m_internalData->m_ShapeBuffer, + m_internalData->m_convexPairsOutGPU, + cfgNP); + } + + { + BT_PROFILE("ChNarrowphase::execute"); + if (useCulling) + { + + if (m_planeBodyIndex>=0) + { + BT_PROFILE("ChNarrowphase:: plane versus convex"); + //todo: get rid of this dynamic allocation + int2* hostPairs = new int2[m_internalData->m_numAcceleratedRigidBodies-1]; + int index=0; + for (int i=0;im_numAcceleratedRigidBodies;i++) + { + if (i!=m_planeBodyIndex) + { + hostPairs[index].x = m_planeBodyIndex; + hostPairs[index].y = i; + index++; + } + } + assert(m_internalData->m_numAcceleratedRigidBodies-1 == index); + m_internalData->m_planePairs->write(hostPairs,index); + adl::DeviceUtils::waitForCompletion(m_internalData->m_deviceCL); + delete[]hostPairs; + //convex versus plane + adl::ChNarrowphase::execute(m_internalData->m_Data, m_internalData->m_planePairs, index, m_internalData->m_bodyBufferGPU, m_internalData->m_ShapeBuffer, + 0,0,m_internalData->m_pBufContactOutGPU, nContactOut, cfgNP); + } + + //convex versus convex + adl::ChNarrowphase::execute(m_internalData->m_Data, m_internalData->m_convexPairsOutGPU,numPairsOut, m_internalData->m_bodyBufferGPU, m_internalData->m_ShapeBuffer, m_internalData->m_pBufContactOutGPU, nContactOut, cfgNP); + } else + { + adl::ChNarrowphase::execute(m_internalData->m_Data, &broadphasePairsGPU, numBroadphasePairs, m_internalData->m_bodyBufferGPU, m_internalData->m_ShapeBuffer, m_internalData->m_pBufContactOutGPU, nContactOut, cfgNP); + } + + adl::DeviceUtils::waitForCompletion(m_internalData->m_deviceCL); + } + + if (!nContactOut) + return; + + + bool useSolver = true;//true;//false; + + if (useSolver) + { + float dt=1./60.; + adl::SolverBase::ConstraintCfg csCfg( dt ); + csCfg.m_enableParallelSolve = true; + csCfg.m_averageExtent = 0.2f;//@TODO m_averageObjExtent; + csCfg.m_staticIdx = m_planeBodyIndex; + + + bool exposeInternalBatchImplementation=true; + + adl::Solver::Data* cpuSolverData = 0; + if (exposeInternalBatchImplementation) + { + BT_PROFILE("Batching"); + + cpuSolverData = adl::Solver::allocate( m_internalData->m_deviceHost, nContactOut); + + adl::Buffer* contactsIn = m_internalData->m_pBufContactOutGPU; + const adl::Buffer* bodyBuf = m_internalData->m_bodyBufferGPU; + void* additionalData = m_internalData->m_frictionCGPU; + const adl::Buffer* shapeBuf = m_internalData->m_inertiaBufferGPU; + SolverData contactCOut = m_internalData->m_contactCGPU; + int nContacts = nContactOut; + + bool useCPU=false; + + if (useCPU) + { + BT_PROFILE("CPU batch"); + { + BT_PROFILE("CPU sortContacts2"); + sortContacts2( cpuSolverData, bodyBuf, contactsIn, additionalData, nContacts, csCfg ); + } + + CPUSolveData* dataCPU = (CPUSolveData*)cpuSolverData->m_parallelSolveData; + { + BT_PROFILE("CPU batchContacts2"); + + adl::Buffer n; n.setRawPtr( cpuSolverData->m_device, dataCPU->m_n, adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT ); + adl::Buffer offsets; offsets.setRawPtr( cpuSolverData->m_device, dataCPU->m_offset, adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT ); + batchContacts2( cpuSolverData, contactsIn, nContacts, &n, &offsets, csCfg.m_staticIdx ); + } + + { + BT_PROFILE("CPU convertToConstraints2"); + convertToConstraints2( cpuSolverData, bodyBuf, shapeBuf, contactsIn, contactCOut, additionalData, nContacts, csCfg ); + } + + { + BT_PROFILE("CPU -> GPU copy"); + ParallelSolveData* dataGPU = (ParallelSolveData*)m_internalData->m_solverDataGPU->m_parallelSolveData; + dataGPU->m_numConstraints->write(dataCPU->m_n,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + dataGPU->m_offsets->write(dataCPU->m_offset,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + adl::DeviceUtils::waitForCompletion( m_internalData->m_deviceCL); + } + + } + else + { + BT_PROFILE("GPU batch"); + + adl::Solver::Data* data = m_internalData->m_solverDataGPU; + + { + if( data->m_contactBuffer ) + { + if( data->m_contactBuffer->getSize() < nContacts ) + { + BT_PROFILE("delete data->m_contactBuffer;"); + delete data->m_contactBuffer; + data->m_contactBuffer = 0; + } + } + if( data->m_contactBuffer == 0 ) + { + data->m_contactBuffer = new adl::Buffer( data->m_device, nContacts ); + } + + adl::Buffer* contactNative = contactsIn; + + ParallelSolveData* nativeSolveData = (ParallelSolveData*)data->m_parallelSolveData; + + { + + ADLASSERT( data->m_device->m_type == adl::TYPE_CL ); + adl::Buffer* bodyNative = adl::BufferUtils::map( data->m_device, bodyBuf ); + adl::Buffer* contactNative = adl::BufferUtils::map( data->m_device, contactsIn ); + + const int sortAlignment = 512; // todo. get this out of sort + if( csCfg.m_enableParallelSolve ) + { + ParallelSolveData* nativeSolveData = (ParallelSolveData*)data->m_parallelSolveData; + + int sortSize = NEXTMULTIPLEOF( nContacts, sortAlignment ); + + adl::Buffer* countsNative = nativeSolveData->m_numConstraints;//BufferUtils::map( data->m_device, &countsHost ); + adl::Buffer* offsetsNative = nativeSolveData->m_offsets;//BufferUtils::map( data->m_device, &offsetsHost ); + + { // 2. set cell idx + BT_PROFILE("GPU set cell idx"); + struct CB + { + int m_nContacts; + int m_staticIdx; + float m_scale; + int m_nSplit; + }; + + ADLASSERT( sortSize%64 == 0 ); + CB cdata; + cdata.m_nContacts = nContacts; + cdata.m_staticIdx = csCfg.m_staticIdx; + cdata.m_scale = 1.f/(adl::SolverBase::N_OBJ_PER_SPLIT*csCfg.m_averageExtent); + cdata.m_nSplit = adl::SolverBase::N_SPLIT; + + adl::Buffer constBuffer( data->m_device, 1, adl::BufferBase::BUFFER_CONST ); + adl::Launcher::BufferInfo bInfo[] = { adl::Launcher::BufferInfo( contactNative ), adl::Launcher::BufferInfo( bodyNative ), adl::Launcher::BufferInfo( data->m_sortDataBuffer ) }; + adl::Launcher launcher( data->m_device, data->m_setSortDataKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(adl::Launcher::BufferInfo) ); + launcher.setConst( constBuffer, cdata ); + launcher.launch1D( sortSize, 64 ); + } + bool gpuRadixSort=true; + if (gpuRadixSort) + { // 3. sort by cell idx + BT_PROFILE("gpuRadixSort"); + int n = adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT; + int sortBit = 32; + //if( n <= 0xffff ) sortBit = 16; + //if( n <= 0xff ) sortBit = 8; + //adl::RadixSort::execute( data->m_sort, *data->m_sortDataBuffer, sortSize ); + adl::RadixSort32::execute( data->m_sort32, *data->m_sortDataBuffer, sortSize ); + + } else + { + BT_PROFILE("cpu RadixSort"); + adl::HostBuffer sortData(m_internalData->m_deviceHost,nContacts); + data->m_sortDataBuffer->read(sortData.m_ptr,nContacts); + adl::DeviceUtils::waitForCompletion( m_internalData->m_deviceCL); + + adl::RadixSort::Data* sData = adl::RadixSort::allocate( m_internalData->m_deviceHost, nContacts ); + adl::RadixSort::execute( sData, sortData, nContacts ); + adl::RadixSort::deallocate( sData ); + + data->m_sortDataBuffer->write(sortData.m_ptr,nContacts); + adl::DeviceUtils::waitForCompletion( m_internalData->m_deviceCL); + } + + + + bool gpuBoundSearch=true; + if (gpuBoundSearch) + { // 4. find entries + BT_PROFILE("gpuBoundSearch"); + adl::BoundSearch::execute( data->m_search, *data->m_sortDataBuffer, nContacts, *countsNative, + adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT, adl::BoundSearchBase::COUNT ); + + adl::PrefixScan::execute( data->m_scan, *countsNative, *offsetsNative, + adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT ); + } else + { + BT_PROFILE("cpuBoundSearch"); + adl::HostBuffer sortData(m_internalData->m_deviceHost,nContacts); + data->m_sortDataBuffer->read(sortData.m_ptr,nContacts); + adl::DeviceUtils::waitForCompletion( m_internalData->m_deviceCL); + + adl::HostBuffer n0( m_internalData->m_deviceHost, adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT ); + adl::HostBuffer offset0( m_internalData->m_deviceHost, adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT ); + for(int i=0; i=0); + assert(idxwrite(n0.m_ptr,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + offsetsNative->write(offset0.m_ptr,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + adl::DeviceUtils::waitForCompletion( data->m_device ); + + } + { // 5. sort constraints by cellIdx + { + BT_PROFILE("gpu m_reorderContactKernel"); + adl::Buffer constBuffer( data->m_device, 1, adl::BufferBase::BUFFER_CONST ); + + int4 cdata; cdata.x = nContacts; + adl::Launcher::BufferInfo bInfo[] = { adl::Launcher::BufferInfo( contactNative ), adl::Launcher::BufferInfo( data->m_contactBuffer ), adl::Launcher::BufferInfo( data->m_sortDataBuffer ) }; + adl::Launcher launcher( data->m_device, data->m_reorderContactKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(adl::Launcher::BufferInfo) ); + launcher.setConst( constBuffer, cdata ); + launcher.launch1D( nContacts, 64 ); + } + } + + } + + adl::BufferUtils::unmap( bodyNative, bodyBuf ); + adl::BufferUtils::unmap( contactNative, contactsIn ); + + } + + adl::DeviceUtils::waitForCompletion( m_internalData->m_deviceCL); + + { + BT_PROFILE("gpu m_copyConstraintKernel"); + adl::Buffer constBuffer( data->m_device, 1, adl::BufferBase::BUFFER_CONST ); + int4 cdata; cdata.x = nContacts; + adl::Launcher::BufferInfo bInfo[] = { adl::Launcher::BufferInfo( data->m_contactBuffer ), adl::Launcher::BufferInfo( contactNative ) }; + adl::Launcher launcher( data->m_device, data->m_copyConstraintKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(adl::Launcher::BufferInfo) ); + launcher.setConst( constBuffer, cdata ); + launcher.launch1D( nContacts, 64 ); + adl::DeviceUtils::waitForCompletion( data->m_device ); + } + + bool compareGPU = false; + if (gpuBatchContacts) + { + BT_PROFILE("gpu batchContacts"); + adl::Solver::batchContacts( data, contactNative, nContacts, nativeSolveData->m_numConstraints, nativeSolveData->m_offsets, csCfg.m_staticIdx ); + } + else + { + BT_PROFILE("cpu batchContacts2"); + cpuSolverData->m_parallelSolveData = 0;// + ParallelSolveData* dataGPU = (ParallelSolveData*)m_internalData->m_solverDataGPU->m_parallelSolveData; + adl::Buffer numConstraints(cpuSolverData->m_device,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + adl::Buffer offsets(cpuSolverData->m_device,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + + { + BT_PROFILE("gpu->cpu read m_numConstraints"); + dataGPU->m_numConstraints->read(numConstraints.m_ptr,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + dataGPU->m_offsets->read(offsets.m_ptr,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + adl::DeviceUtils::waitForCompletion( data->m_device ); + } + + adl::Buffer gpunumConstraints(cpuSolverData->m_device,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + adl::Buffer gpuoffsets(cpuSolverData->m_device,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + + if (compareGPU) + { + adl::Buffer contactNativeCopy (data->m_device,contactNative->getSize()); + contactNativeCopy.write(*contactNative,contactNative->getSize()); + adl::DeviceUtils::waitForCompletion( data->m_device ); + + adl::Buffer tmpNumGPU(data->m_device,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + adl::Buffer tmpOffsetGPU(data->m_device,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + tmpNumGPU.write(numConstraints.m_ptr,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + tmpOffsetGPU.write(offsets.m_ptr,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + adl::DeviceUtils::waitForCompletion( data->m_device ); + + BT_PROFILE("gpu batchContacts"); + //adl::Solver::batchContacts( data, contactNative, nContacts, nativeSolveData->m_numConstraints, nativeSolveData->m_offsets, csCfg.m_staticIdx ); + adl::Solver::batchContacts( data, &contactNativeCopy, nContacts, &tmpNumGPU, &tmpOffsetGPU, csCfg.m_staticIdx ); + + + adl::DeviceUtils::waitForCompletion( data->m_device ); + + //compare now + tmpNumGPU.read(gpunumConstraints,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + tmpOffsetGPU.read(gpuoffsets,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + adl::DeviceUtils::waitForCompletion( data->m_device ); + + } + + CPUSolveData* dataCPU = (CPUSolveData*)cpuSolverData->m_parallelSolveData; + + { + BT_PROFILE("cpu batchContacts2"); + batchContacts2( cpuSolverData, contactNative, nContacts, &numConstraints, &offsets, csCfg.m_staticIdx ); + } + + + if (compareGPU) + { + adl::DeviceUtils::waitForCompletion( data->m_device ); + dataGPU->m_numConstraints->write(numConstraints.m_ptr,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + dataGPU->m_offsets->write(offsets.m_ptr,adl::SolverBase::N_SPLIT*adl::SolverBase::N_SPLIT); + adl::DeviceUtils::waitForCompletion( data->m_device ); + + + for (int i=0;i::convertToConstraints( data, bodyBuf, shapeBuf, contactNative, contactCOut, additionalData, nContacts, csCfg ); + adl::DeviceUtils::waitForCompletion( data->m_device ); + } + if (compareGPU) + { + adl::Buffer contactNativeCPU(cpuSolverData->m_device,contactNative->getSize()); + contactNative->read(contactNativeCPU,nContacts); + adl::DeviceUtils::waitForCompletion( data->m_device ); + for (int i=0;i::reorderConvertToConstraints( + m_internalData->m_solverDataGPU, + m_internalData->m_bodyBufferGPU, + m_internalData->m_inertiaBufferGPU, + m_internalData->m_pBufContactOutGPU, + m_internalData->m_contactCGPU, + m_internalData->m_frictionCGPU, + nContactOut, + csCfg ); + adl::DeviceUtils::waitForCompletion( m_internalData->m_deviceCL ); + } + + + if (1) + { + BT_PROFILE("GPU solveContactConstraint"); + m_internalData->m_solverDataGPU->m_nIterations = 5; + + adl::Solver::solveContactConstraint( m_internalData->m_solverDataGPU, + m_internalData->m_bodyBufferGPU, + m_internalData->m_inertiaBufferGPU, + m_internalData->m_contactCGPU, + 0, + nContactOut ); + + adl::DeviceUtils::waitForCompletion( m_internalData->m_deviceCL ); + } + + if (cpuSolverData) + adl::Solver::deallocate( cpuSolverData ); + + if (0) + { + BT_PROFILE("read body velocities back to CPU"); + //read body updated linear/angular velocities back to CPU + m_internalData->m_bodyBufferGPU->read( + m_internalData->m_bodyBufferCPU->m_ptr,numOfConvexRBodies); + adl::DeviceUtils::waitForCompletion( m_internalData->m_deviceCL ); + } + } + +} diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/btGpuNarrowPhaseAndSolver.h b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/btGpuNarrowPhaseAndSolver.h new file mode 100644 index 0000000..9d59413 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/btGpuNarrowPhaseAndSolver.h @@ -0,0 +1,72 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + +#ifndef GPU_NARROWPHASE_SOLVER_H +#define GPU_NARROWPHASE_SOLVER_H + + + +//#define MAX_CONVEX_BODIES_CL 8*1024 +#define MAX_CONVEX_BODIES_CL 128*1024 +#define MAX_PAIRS_PER_BODY_CL 16 +#define MAX_CONVEX_SHAPES_CL 8192 +#define MAX_BROADPHASE_COLLISION_CL (MAX_CONVEX_BODIES_CL*MAX_PAIRS_PER_BODY_CL) + +/* +#define MAX_CONVEX_BODIES_CL 1024 +#define MAX_PAIRS_PER_BODY_CL 32 +#define MAX_CONVEX_SHAPES_CL 8192 +#define MAX_BROADPHASE_COLLISION_CL (MAX_CONVEX_BODIES_CL*MAX_PAIRS_PER_BODY_CL) +*/ + +namespace adl +{ + struct DeviceCL; +}; + + +struct CustomDispatchData; + +#include "../basic_initialize/btOpenCLInclude.h" + + +class btGpuNarrowphaseAndSolver +{ +protected: + + CustomDispatchData* m_internalData; + int m_acceleratedCompanionShapeIndex; + int m_planeBodyIndex; + +public: + btGpuNarrowphaseAndSolver(adl::DeviceCL* deviceCL); + + virtual ~btGpuNarrowphaseAndSolver(void); + + int registerShape(class ConvexHeightField* convexShape); + int registerRigidBody(int shapeIndex, float mass, const float* position, const float* orientation, bool writeToGpu = true); + void writeAllBodiesToGpu(); + + //btBroadphasePair* GetPair(btBroadphasePairArray& pairArray, int idxBodyA, int idxBodyB); + + virtual void computeContactsAndSolver(cl_mem broadphasePairs, int numBroadphasePairs); + + cl_mem getBodiesGpu(); + + cl_mem getBodyInertiasGpu(); + +}; + +#endif //GPU_NARROWPHASE_SOLVER_H diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/main.cpp b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/main.cpp new file mode 100644 index 0000000..07dfc82 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/main.cpp @@ -0,0 +1,1775 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + + +int NUM_OBJECTS_X = 54; +int NUM_OBJECTS_Y = 35; +int NUM_OBJECTS_Z = 54; + +float X_GAP = 12.f; +float Y_GAP = 2.f; +float Z_GAP = 2.f; + +int preferredGPU = -1; +int preferredPlatform=-1; +int USE_GL_CL_INTEROP=1; +extern int gpuBatchContacts; + + +#include +#include + +#include "btGlutInclude.h" +#include "../opengl_interop/btStopwatch.h" +#include "../../dynamics/basic_demo/ConvexHeightFieldShape.h" +#include "../../dynamics/basic_demo/Stubs/AdlRigidBody.h" + +#include "btGpuNarrowphaseAndSolver.h" + +#include "LinearMath/btQuickprof.h" + +#include "LinearMath/btVector3.h" +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btMatrix3x3.h" +static float sAngle(0); + +#include + +#ifdef _WIN32 +#include +#endif + +#include +#include +#include "../3dGridBroadphase/Shared/btGpu3DGridBroadphase.h" +#include "../3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.h" +#include "../broadphase_benchmark/btGridBroadphaseCl.h" +#include "btConvexUtility.h" + +#define USE_NEW +#ifdef USE_NEW +btGridBroadphaseCl* sBroadphase=0; +#else +btGpu3DGridBroadphase* sBroadphase=0; +#endif + +btAlignedObjectArray proxyArray; + +int gShapeIndex=0; + + +#define RS_SCALE (1.0 / (1.0 + RAND_MAX)) + + +int randbiased (double x) { + for (;;) { + double p = rand () * RS_SCALE; + if (p >= x) return 0; + if (p+RS_SCALE <= x) return 1; + /* p < x < p+RS_SCALE */ + x = (x - p) * (1.0 + RAND_MAX); + } +} + +size_t randrange (size_t n) +{ + double xhi; + double resolution = n * RS_SCALE; + double x = resolution * rand (); /* x in [0,n) */ + size_t lo = (size_t) floor (x); + + xhi = x + resolution; + + for (;;) { + lo++; + if (lo >= xhi || randbiased ((lo - x) / (xhi - x))) return lo-1; + x = lo; + } +} + +//OpenCL stuff +#include "../basic_initialize/btOpenCLUtils.h" +#include "../opengl_interop/btOpenCLGLInteropBuffer.h" + +#include "../broadphase_benchmark/findPairsOpenCL.h" + +btFindPairsIO gFpIO; + +cl_context g_cxMainContext; +cl_command_queue g_cqCommandQue; +cl_device_id g_device; + +cl_mem gLinVelMem; +cl_mem gAngVelMem; +cl_mem gBodyTimes; + +btVector3 m_cameraPosition(142,20,142); +btVector3 m_cameraTargetPosition(0,10,0); +btScalar m_cameraDistance = 55; +btVector3 m_cameraUp(0,1,0); +float m_azi=30.f; +float m_ele=5.f; + + + + +btOpenCLGLInteropBuffer* g_interopBuffer = 0; +cl_mem clBuffer=0; +char* hostPtr=0; +cl_bool blocking= CL_TRUE; + + +cl_kernel g_integrateTransformsKernel; + + + +////for Adl +#include + +adl::DeviceCL* g_deviceCL=0; + + + +bool useCPU = false; +bool printStats = true; +bool runOpenCLKernels = true; + +#define MSTRINGIFY(A) #A +static char* interopKernelString = +#include "../broadphase_benchmark/integrateKernel.cl" + +#define INTEROPKERNEL_SRC_PATH "../../opencl/broadphase_benchmark/integrateKernel.cl" + + +ConvexHeightField* s_convexHeightField = 0 ; +btGpuNarrowphaseAndSolver* narrowphaseAndSolver =0; + + +btStopwatch gStopwatch; +int m_glutScreenWidth = 640; +int m_glutScreenHeight= 480; + +bool m_ortho = false; + +static GLuint instancingShader; // The instancing renderer +static GLuint cube_vao; +static GLuint cube_vbo; +static GLuint index_vbo; +static GLuint m_texturehandle; + +static bool done = false; +static GLint angle_loc = 0; +static GLint ModelViewMatrix; +static GLint ProjectionMatrix; + +void writeTransforms(); + +static GLint uniform_texture_diffuse = 0; + +//used for dynamic loading from disk (default switched off) +#define MAX_SHADER_LENGTH 8192 +static GLubyte shaderText[MAX_SHADER_LENGTH]; + +static const char* vertexShader= \ +"#version 330\n" +"precision highp float;\n" +"\n" +"\n" +"\n" +"layout (location = 0) in vec4 position;\n" +"layout (location = 1) in vec4 instance_position;\n" +"layout (location = 2) in vec4 instance_quaternion;\n" +"layout (location = 3) in vec2 uvcoords;\n" +"layout (location = 4) in vec3 vertexnormal;\n" +"layout (location = 5) in vec4 instance_color;\n" +"layout (location = 6) in vec3 instance_scale;\n" +"\n" +"\n" +"uniform float angle = 0.0;\n" +"uniform mat4 ModelViewMatrix;\n" +"uniform mat4 ProjectionMatrix;\n" +"\n" +"out Fragment\n" +"{\n" +" vec4 color;\n" +"} fragment;\n" +"\n" +"out Vert\n" +"{\n" +" vec2 texcoord;\n" +"} vert;\n" +"\n" +"\n" +"vec4 quatMul ( in vec4 q1, in vec4 q2 )\n" +"{\n" +" vec3 im = q1.w * q2.xyz + q1.xyz * q2.w + cross ( q1.xyz, q2.xyz );\n" +" vec4 dt = q1 * q2;\n" +" float re = dot ( dt, vec4 ( -1.0, -1.0, -1.0, 1.0 ) );\n" +" return vec4 ( im, re );\n" +"}\n" +"\n" +"vec4 quatFromAxisAngle(vec4 axis, in float angle)\n" +"{\n" +" float cah = cos(angle*0.5);\n" +" float sah = sin(angle*0.5);\n" +" float d = inversesqrt(dot(axis,axis));\n" +" vec4 q = vec4(axis.x*sah*d,axis.y*sah*d,axis.z*sah*d,cah);\n" +" return q;\n" +"}\n" +"//\n" +"// vector rotation via quaternion\n" +"//\n" +"vec4 quatRotate3 ( in vec3 p, in vec4 q )\n" +"{\n" +" vec4 temp = quatMul ( q, vec4 ( p, 0.0 ) );\n" +" return quatMul ( temp, vec4 ( -q.x, -q.y, -q.z, q.w ) );\n" +"}\n" +"vec4 quatRotate ( in vec4 p, in vec4 q )\n" +"{\n" +" vec4 temp = quatMul ( q, p );\n" +" return quatMul ( temp, vec4 ( -q.x, -q.y, -q.z, q.w ) );\n" +"}\n" +"\n" +"out vec3 lightDir,normal,ambient;\n" +"\n" +"void main(void)\n" +"{\n" +" vec4 q = instance_quaternion;\n" +" ambient = vec3(0.3,.3,0.3);\n" +" \n" +" \n" +" vec4 local_normal = (quatRotate3( vertexnormal,q));\n" +" vec3 light_pos = vec3(-0.8,1,-0.6);\n" +" normal = local_normal.xyz;\n"//normalize(ModelViewMatrix * local_normal).xyz;\n" +"\n" +" lightDir = normalize(light_pos);//gl_LightSource[0].position.xyz));\n" +"// lightDir = normalize(vec3(gl_LightSource[0].position));\n" +" \n" +" vec4 axis = vec4(1,1,1,0);\n" +" vec4 localcoord = quatRotate3( position.xyz*instance_scale,q);\n" +" vec4 vertexPos = ProjectionMatrix * ModelViewMatrix *(instance_position+localcoord);\n" +"\n" +" gl_Position = vertexPos;\n" +" \n" +" fragment.color = instance_color;\n" +" vert.texcoord = uvcoords;\n" +"}\n" +; + + +static const char* fragmentShader= \ +"#version 330\n" +"precision highp float;\n" +"\n" +"in Fragment\n" +"{\n" +" vec4 color;\n" +"} fragment;\n" +"\n" +"in Vert\n" +"{\n" +" vec2 texcoord;\n" +"} vert;\n" +"\n" +"uniform sampler2D Diffuse;\n" +"\n" +"in vec3 lightDir,normal,ambient;\n" +"\n" +"out vec4 color;\n" +"\n" +"void main_textured(void)\n" +"{\n" +" color = texture2D(Diffuse,vert.texcoord);//fragment.color;\n" +"}\n" +"\n" +"void main(void)\n" +"{\n" +" vec4 texel = fragment.color*texture2D(Diffuse,vert.texcoord);//fragment.color;\n" +" vec3 ct,cf;\n" +" float intensity,at,af;\n" +" intensity = max(dot(lightDir,normalize(normal)),.2);\n" +" cf = intensity*vec3(1.0,1.0,1.0)+ambient;" +" af = 1.0;\n" +" \n" +" ct = texel.rgb;\n" +" at = texel.a;\n" +" \n" +" color = vec4(ct * cf, at * af); \n" +"}\n" +; + + +// Load the shader from the source text +void gltLoadShaderSrc(const char *szShaderSrc, GLuint shader) +{ + GLchar *fsStringPtr[1]; + + fsStringPtr[0] = (GLchar *)szShaderSrc; + glShaderSource(shader, 1, (const GLchar **)fsStringPtr, NULL); +} + + +//////////////////////////////////////////////////////////////// +// Load the shader from the specified file. Returns false if the +// shader could not be loaded +bool gltLoadShaderFile(const char *szFile, GLuint shader) +{ + GLint shaderLength = 0; + FILE *fp; + + // Open the shader file + fp = fopen(szFile, "r"); + if(fp != NULL) + { + // See how long the file is + while (fgetc(fp) != EOF) + shaderLength++; + + // Allocate a block of memory to send in the shader + assert(shaderLength < MAX_SHADER_LENGTH); // make me bigger! + if(shaderLength > MAX_SHADER_LENGTH) + { + fclose(fp); + return false; + } + + // Go back to beginning of file + rewind(fp); + + // Read the whole file in + if (shaderText != NULL) + fread(shaderText, 1, shaderLength, fp); + + // Make sure it is null terminated and close the file + shaderText[shaderLength] = '\0'; + fclose(fp); + } + else + return false; + + // printf(shaderText); + // Load the string + gltLoadShaderSrc((const char *)shaderText, shader); + + return true; +} + + +///////////////////////////////////////////////////////////////// +// Load a pair of shaders, compile, and link together. Specify the complete +// file path for each shader. Note, there is no support for +// just loading say a vertex program... you have to do both. +GLuint gltLoadShaderPair(const char *szVertexProg, const char *szFragmentProg, bool loadFromFile) +{ + // Temporary Shader objects + GLuint hVertexShader; + GLuint hFragmentShader; + GLuint hReturn = 0; + GLint testVal; + + // Create shader objects + hVertexShader = glCreateShader(GL_VERTEX_SHADER); + hFragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + + if (loadFromFile) + { + + if(gltLoadShaderFile(szVertexProg, hVertexShader) == false) + { + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + + if(gltLoadShaderFile(szFragmentProg, hFragmentShader) == false) + { + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + } else + { + gltLoadShaderSrc(vertexShader, hVertexShader); + gltLoadShaderSrc(fragmentShader, hFragmentShader); + } + // Compile them + glCompileShader(hVertexShader); + glCompileShader(hFragmentShader); + + // Check for errors + glGetShaderiv(hVertexShader, GL_COMPILE_STATUS, &testVal); + if(testVal == GL_FALSE) + { + char temp[256] = ""; + glGetShaderInfoLog( hVertexShader, 256, NULL, temp); + fprintf( stderr, "Compile failed:\n%s\n", temp); + assert(0); + exit(0); + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + + glGetShaderiv(hFragmentShader, GL_COMPILE_STATUS, &testVal); + if(testVal == GL_FALSE) + { + char temp[256] = ""; + glGetShaderInfoLog( hFragmentShader, 256, NULL, temp); + fprintf( stderr, "Compile failed:\n%s\n", temp); + assert(0); + exit(0); + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + + // Link them - assuming it works... + hReturn = glCreateProgram(); + glAttachShader(hReturn, hVertexShader); + glAttachShader(hReturn, hFragmentShader); + + glLinkProgram(hReturn); + + // These are no longer needed + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + + // Make sure link worked too + glGetProgramiv(hReturn, GL_LINK_STATUS, &testVal); + if(testVal == GL_FALSE) + { + glDeleteProgram(hReturn); + return (GLuint)NULL; + } + + return hReturn; +} + +///position xyz, unused w, normal, uv +static const GLfloat cube_vertices[] = +{ + -1.0f, -1.0f, 1.0f, 0.0f, 0,0,1, 0,0,//0 + 1.0f, -1.0f, 1.0f, 0.0f, 0,0,1, 1,0,//1 + 1.0f, 1.0f, 1.0f, 0.0f, 0,0,1, 1,1,//2 + -1.0f, 1.0f, 1.0f, 0.0f, 0,0,1, 0,1 ,//3 + + -1.0f, -1.0f, -1.0f, 1.0f, 0,0,-1, 0,0,//4 + 1.0f, -1.0f, -1.0f, 1.0f, 0,0,-1, 1,0,//5 + 1.0f, 1.0f, -1.0f, 1.0f, 0,0,-1, 1,1,//6 + -1.0f, 1.0f, -1.0f, 1.0f, 0,0,-1, 0,1,//7 + + -1.0f, -1.0f, -1.0f, 1.0f, -1,0,0, 0,0, + -1.0f, 1.0f, -1.0f, 1.0f, -1,0,0, 1,0, + -1.0f, 1.0f, 1.0f, 1.0f, -1,0,0, 1,1, + -1.0f, -1.0f, 1.0f, 1.0f, -1,0,0, 0,1, + + 1.0f, -1.0f, -1.0f, 1.0f, 1,0,0, 0,0, + 1.0f, 1.0f, -1.0f, 1.0f, 1,0,0, 1,0, + 1.0f, 1.0f, 1.0f, 1.0f, 1,0,0, 1,1, + 1.0f, -1.0f, 1.0f, 1.0f, 1,0,0, 0,1, + + -1.0f, -1.0f, -1.0f, 1.0f, 0,-1,0, 0,0, + -1.0f, -1.0f, 1.0f, 1.0f, 0,-1,0, 1,0, + 1.0f, -1.0f, 1.0f, 1.0f, 0,-1,0, 1,1, + 1.0f,-1.0f, -1.0f, 1.0f, 0,-1,0, 0,1, + + -1.0f, 1.0f, -1.0f, 1.0f, 0,1,0, 0,0, + -1.0f, 1.0f, 1.0f, 1.0f, 0,1,0, 1,0, + 1.0f, 1.0f, 1.0f, 1.0f, 0,1,0, 1,1, + 1.0f,1.0f, -1.0f, 1.0f, 0,1,0, 0,1, +}; + +static const int cube_indices[]= +{ + 0,1,2,0,2,3,//ground face + 4,5,6,4,6,7,//top face + 8,9,10,8,10,11, + 12,13,14,12,14,15, + 16,17,18,16,18,19, + 20,21,22,20,22,23 +}; + +int m_mouseOldX = -1; +int m_mouseOldY = -1; +int m_mouseButtons = 0; + + +void mouseFunc(int button, int state, int x, int y) +{ + if (state == 0) + { + m_mouseButtons |= 1<0) + { + g_device= btOpenCLUtils::getDevice(g_cxMainContext,0); + btOpenCLDeviceInfo clInfo; + btOpenCLUtils::getDeviceInfo(g_device,clInfo); + btOpenCLUtils::printDeviceInfo(g_device); + // create a command-queue + g_cqCommandQue = clCreateCommandQueue(g_cxMainContext, g_device, 0, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + //normally you would create and execute kernels using this command queue + + } + + +} + +int NUM_OBJECTS = NUM_OBJECTS_X*NUM_OBJECTS_Y*NUM_OBJECTS_Z; +int POSITION_BUFFER_SIZE = (NUM_OBJECTS*sizeof(float)*4); +int ORIENTATION_BUFFER_SIZE = (NUM_OBJECTS*sizeof(float)*4); +int COLOR_BUFFER_SIZE = (NUM_OBJECTS*sizeof(float)*4); +int SCALE_BUFFER_SIZE = (NUM_OBJECTS*sizeof(float)*3); + +int VBOsize =0; + + +GLfloat* instance_positions_ptr = 0; +GLfloat* instance_quaternion_ptr = 0; +GLfloat* instance_colors_ptr = 0; +GLfloat* instance_scale_ptr= 0; + + +void DeleteShaders() +{ + glDeleteVertexArrays(1, &cube_vao); + glDeleteBuffers(1,&index_vbo); + glDeleteBuffers(1,&cube_vbo); + glDeleteProgram(instancingShader); +} + + +void InitShaders() +{ + + btOverlappingPairCache* overlappingPairCache=0; + int maxObjects = btMax(256,NUM_OBJECTS); +#ifdef USE_NEW + int maxPairsSmallProxy = 32; + + sBroadphase = new btGridBroadphaseCl(overlappingPairCache,btVector3(4.f, 4.f, 4.f), 128, 128, 128,maxObjects, maxObjects, maxPairsSmallProxy, 100.f, 128, + g_cxMainContext ,g_device,g_cqCommandQue, g_deviceCL); +#else + sBroadphase = new btGpu3DGridBroadphase(btVector3(2.f, 2.f, 2.f), 32, 32, 32,maxObjects, maxObjects, 64, 100.f, 64); +#endif + + + +// sBroadphase = new bt3dGridBroadphaseOCL(overlappingPairCache,btVector3(10.f, 10.f, 10.f), 32, 32, 32,NUM_OBJECTS, NUM_OBJECTS, 64, 100.f, 16, +// g_cxMainContext ,g_device,g_cqCommandQue); + + + + bool loadFromFile = false; + instancingShader = gltLoadShaderPair("instancing.vs","instancing.fs", loadFromFile); + + glLinkProgram(instancingShader); + glUseProgram(instancingShader); + angle_loc = glGetUniformLocation(instancingShader, "angle"); + ModelViewMatrix = glGetUniformLocation(instancingShader, "ModelViewMatrix"); + ProjectionMatrix = glGetUniformLocation(instancingShader, "ProjectionMatrix"); + uniform_texture_diffuse = glGetUniformLocation(instancingShader, "Diffuse"); + + GLuint offset = 0; + + + glGenBuffers(1, &cube_vbo); + glBindBuffer(GL_ARRAY_BUFFER, cube_vbo); + + instance_positions_ptr = (GLfloat*)new float[NUM_OBJECTS*4]; + instance_quaternion_ptr = (GLfloat*)new float[NUM_OBJECTS*4]; + instance_colors_ptr = (GLfloat*)new float[NUM_OBJECTS*4]; + instance_scale_ptr = (GLfloat*)new float[NUM_OBJECTS*3]; + + + + int index=0; + for (int i=0;icreateProxy(aabbMin,aabbMax,shapeType,myptr,1,1,0,0);//m_dispatcher); + proxyArray.push_back(proxy); + + instance_quaternion_ptr[index*4]=0; + instance_quaternion_ptr[index*4+1]=0; + instance_quaternion_ptr[index*4+2]=0; + instance_quaternion_ptr[index*4+3]=1; + + instance_colors_ptr[index*4]=jregisterRigidBody(gShapeIndex,mass,&instance_positions_ptr[index*4],&instance_quaternion_ptr[index*4],writeToGpu); + + index++; + } + } + } + + float posZero[4] = {0,-NUM_OBJECTS_Y/2-1,0,0}; + float ornZero[4] = {0,0,0,1}; + + //register a 'plane' + if (narrowphaseAndSolver) + narrowphaseAndSolver->registerRigidBody(-1, 0.f, posZero,ornZero,false); + + + + if (narrowphaseAndSolver) + narrowphaseAndSolver->writeAllBodiesToGpu(); + + + int size = sizeof(cube_vertices) + POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE+COLOR_BUFFER_SIZE+SCALE_BUFFER_SIZE; + VBOsize = size; + + char* bla = (char*)malloc(size); + int szc = sizeof(cube_vertices); + memcpy(bla,&cube_vertices[0],szc); + memcpy(bla+sizeof(cube_vertices),instance_positions_ptr,POSITION_BUFFER_SIZE); + memcpy(bla+sizeof(cube_vertices)+POSITION_BUFFER_SIZE,instance_quaternion_ptr,ORIENTATION_BUFFER_SIZE); + memcpy(bla+sizeof(cube_vertices)+POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE,instance_colors_ptr, COLOR_BUFFER_SIZE); + memcpy(bla+sizeof(cube_vertices)+POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE+COLOR_BUFFER_SIZE,instance_scale_ptr, SCALE_BUFFER_SIZE); + + glBufferData(GL_ARRAY_BUFFER, size, bla, GL_DYNAMIC_DRAW);//GL_STATIC_DRAW); + + ///initialize parts of the buffer +#ifdef _USE_SUB_DATA + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(cube_vertices)+ 16384, bla);//cube_vertices); +#endif + + char* dest= (char*)glMapBuffer( GL_ARRAY_BUFFER,GL_WRITE_ONLY);//GL_WRITE_ONLY + memcpy(dest,cube_vertices,sizeof(cube_vertices)); + //memcpy(dest+sizeof(cube_vertices),instance_colors,sizeof(instance_colors)); + glUnmapBuffer( GL_ARRAY_BUFFER); + + + + writeTransforms(); + + /* + glBufferSubData(GL_ARRAY_BUFFER, sizeof(cube_vertices) + sizeof(instance_colors), POSITION_BUFFER_SIZE, instance_positions_ptr); + glBufferSubData(GL_ARRAY_BUFFER, sizeof(cube_vertices) + sizeof(instance_colors)+POSITION_BUFFER_SIZE,ORIENTATION_BUFFER_SIZE , instance_quaternion_ptr); + */ + + glGenVertexArrays(1, &cube_vao); + glBindVertexArray(cube_vao); + glBindBuffer(GL_ARRAY_BUFFER, cube_vbo); + glBindVertexArray(0); + + glGenBuffers(1, &index_vbo); + int indexBufferSize = sizeof(cube_indices); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_vbo); + + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBufferSize, NULL, GL_STATIC_DRAW); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,0,indexBufferSize,cube_indices); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER,0); + glBindVertexArray(0); + +} + + + +void updateCamera() +{ + + + + btVector3 m_cameraUp(0,1,0); + int m_forwardAxis=2; + + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + btScalar rele = m_ele * btScalar(0.01745329251994329547);// rads per deg + btScalar razi = m_azi * btScalar(0.01745329251994329547);// rads per deg + + + btQuaternion rot(m_cameraUp,razi); + + + btVector3 eyePos(0,0,0); + eyePos[m_forwardAxis] = -m_cameraDistance; + + btVector3 forward(eyePos[0],eyePos[1],eyePos[2]); + if (forward.length2() < SIMD_EPSILON) + { + forward.setValue(1.f,0.f,0.f); + } + btVector3 right = m_cameraUp.cross(forward); + btQuaternion roll(right,-rele); + + eyePos = btMatrix3x3(rot) * btMatrix3x3(roll) * eyePos; + + m_cameraPosition[0] = eyePos.getX(); + m_cameraPosition[1] = eyePos.getY(); + m_cameraPosition[2] = eyePos.getZ(); + m_cameraPosition += m_cameraTargetPosition; + + + float m_frustumZNear=1; + float m_frustumZFar=1000; + + if (m_glutScreenWidth == 0 && m_glutScreenHeight == 0) + return; + + float aspect; + btVector3 extents; + + if (m_glutScreenWidth > m_glutScreenHeight) + { + aspect = m_glutScreenWidth / (float)m_glutScreenHeight; + extents.setValue(aspect * 1.0f, 1.0f,0); + } else + { + aspect = m_glutScreenHeight / (float)m_glutScreenWidth; + extents.setValue(1.0f, aspect*1.f,0); + } + + + if (m_ortho) + { + // reset matrix + glLoadIdentity(); + extents *= m_cameraDistance; + btVector3 lower = m_cameraTargetPosition - extents; + btVector3 upper = m_cameraTargetPosition + extents; + glOrtho(lower.getX(), upper.getX(), lower.getY(), upper.getY(),-1000,1000); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + } else + { + if (m_glutScreenWidth > m_glutScreenHeight) + { + glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar); + } else + { + glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar); + } + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(m_cameraPosition[0], m_cameraPosition[1], m_cameraPosition[2], + m_cameraTargetPosition[0], m_cameraTargetPosition[1], m_cameraTargetPosition[2], + m_cameraUp.getX(),m_cameraUp.getY(),m_cameraUp.getZ()); + } + +} + + + +void myinit() +{ + GLint err = glGetError(); + + // GLfloat light_ambient[] = { btScalar(0.2), btScalar(0.2), btScalar(0.2), btScalar(1.0) }; + GLfloat light_ambient[] = { btScalar(1.0), btScalar(1.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 )}; + /* light_position is NOT default value */ + GLfloat light_position0[] = { btScalar(10000.0), btScalar(10000.0), btScalar(10000.0), btScalar(0.0 )}; + GLfloat light_position1[] = { btScalar(-1.0), btScalar(-10.0), btScalar(-1.0), btScalar(0.0) }; + + glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT0, GL_POSITION, light_position0); + + glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT1, GL_POSITION, light_position1); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + + + // glShadeModel(GL_FLAT);//GL_SMOOTH); + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + glClearColor(float(0.7),float(0.7),float(0.7),float(0)); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + + static bool m_textureenabled = true; + static bool m_textureinitialized = false; + + + if(m_textureenabled) + { + if(!m_textureinitialized) + { + glActiveTexture(GL_TEXTURE0); + + GLubyte* image=new GLubyte[256*256*3]; + for(int y=0;y<256;++y) + { + const int t=y>>5; + GLubyte* pi=image+y*256*3; + for(int x=0;x<256;++x) + { + if (x<2||y<2||x>253||y>253) + { + pi[0]=0; + pi[1]=0; + pi[2]=0; + } else + { + pi[0]=255; + pi[1]=255; + pi[2]=255; + } + + /* + const int s=x>>5; + const GLubyte b=180; + GLubyte c=b+((s+t&1)&1)*(255-b); + pi[0]=c; + pi[1]=c; + pi[2]=c; + */ + + pi+=3; + } + } + + glGenTextures(1,(GLuint*)&m_texturehandle); + glBindTexture(GL_TEXTURE_2D,m_texturehandle); + glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); + gluBuild2DMipmaps(GL_TEXTURE_2D,3,256,256,GL_RGB,GL_UNSIGNED_BYTE,image); + delete[] image; + m_textureinitialized=true; + } + // glMatrixMode(GL_TEXTURE); + // glLoadIdentity(); + // glMatrixMode(GL_MODELVIEW); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,m_texturehandle); + + } else + { + glDisable(GL_TEXTURE_2D); + } + + glEnable(GL_COLOR_MATERIAL); + + err = glGetError(); + assert(err==GL_NO_ERROR); + + // glEnable(GL_CULL_FACE); + // glCullFace(GL_BACK); +} + +//#pragma optimize( "g", off ) + + + +void writeTransforms() +{ + + + glFlush(); + char* bla = (char*)glMapBuffer( GL_ARRAY_BUFFER,GL_READ_WRITE);//GL_WRITE_ONLY + + float* positions = (float*)(bla+sizeof(cube_vertices)); + float* orientations = (float*)(bla+sizeof(cube_vertices) + POSITION_BUFFER_SIZE); + float* colors= (float*)(bla+sizeof(cube_vertices) + POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE); + float* scaling= (float*)(bla+sizeof(cube_vertices) + POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE+COLOR_BUFFER_SIZE); + + // positions[0]+=0.001f; + + static int offset=0; + //offset++; + + static btVector3 axis(1,0,0); + sAngle += 0.01f; + int index=0; + btQuaternion orn(axis,sAngle); + for (int i=0;igetCLBUffer(); + BT_PROFILE("clEnqueueAcquireGLObjects"); + ciErrNum = clEnqueueAcquireGLObjects(g_cqCommandQue, 1, &clBuffer, 0, 0, NULL); + adl::DeviceUtils::waitForCompletion( g_deviceCL ); + } else + { + + BT_PROFILE("glMapBuffer and clEnqueueWriteBuffer"); + + blocking= CL_TRUE; + hostPtr= (char*)glMapBuffer( GL_ARRAY_BUFFER,GL_READ_WRITE);//GL_WRITE_ONLY + if (!clBuffer) + { + clBuffer = clCreateBuffer(g_cxMainContext, CL_MEM_READ_WRITE, VBOsize, 0, &ciErrNum); + } + adl::DeviceUtils::waitForCompletion( g_deviceCL ); + ciErrNum = clEnqueueWriteBuffer ( g_cqCommandQue, + clBuffer, + blocking, + 0, + VBOsize, + hostPtr,0,0,0 + ); + adl::DeviceUtils::waitForCompletion( g_deviceCL ); + } + + + + oclCHECKERROR(ciErrNum, CL_SUCCESS); + if (runOpenCLKernels) + { + +#ifdef USE_NEW + gFpIO.m_numObjects = NUM_OBJECTS; + gFpIO.m_positionOffset = (sizeof(cube_vertices) )/4; + gFpIO.m_clObjectsBuffer = clBuffer; + gFpIO.m_dAABB = sBroadphase->m_dAABB; + + + { + BT_PROFILE("setupGpuAabbs"); + setupGpuAabbsSimple(gFpIO); + } + { + BT_PROFILE("calculateOverlappingPairs"); + sBroadphase->calculateOverlappingPairs(0, NUM_OBJECTS); + } + gFpIO.m_dAllOverlappingPairs = sBroadphase->m_dAllOverlappingPairs; + gFpIO.m_numOverlap = sBroadphase->m_numPrefixSum; + //printf("gFpIO.m_numOverlap = %d\n",gFpIO.m_numOverlap ); + if (gFpIO.m_numOverlap>=0 && gFpIO.m_numOverlapgetBodiesGpu(), narrowphaseAndSolver->getBodyInertiasGpu()); + } + if (gFpIO.m_numOverlap) + { + BT_PROFILE("computeContactsAndSolver"); + if (narrowphaseAndSolver) + narrowphaseAndSolver->computeContactsAndSolver(gFpIO.m_dAllOverlappingPairs,gFpIO.m_numOverlap); + } + + { + BT_PROFILE("copyBodyVelocities"); + if (narrowphaseAndSolver) + copyBodyVelocities(gFpIO, gLinVelMem, gAngVelMem, narrowphaseAndSolver->getBodiesGpu(), narrowphaseAndSolver->getBodyInertiasGpu()); + } + } else + { + printf("error, gFpIO.m_numOverlap = %d\n",gFpIO.m_numOverlap); + btAssert(0); + } + +#else + +#endif + { + BT_PROFILE("integrateTransforms"); + + if (runOpenCLKernels) + { + int numObjects = NUM_OBJECTS; + int offset = (sizeof(cube_vertices) )/4; + + ciErrNum = clSetKernelArg(g_integrateTransformsKernel, 0, sizeof(int), &offset); + ciErrNum = clSetKernelArg(g_integrateTransformsKernel, 1, sizeof(int), &numObjects); + ciErrNum = clSetKernelArg(g_integrateTransformsKernel, 2, sizeof(cl_mem), (void*)&clBuffer ); + + ciErrNum = clSetKernelArg(g_integrateTransformsKernel, 3, sizeof(cl_mem), (void*)&gLinVelMem); + ciErrNum = clSetKernelArg(g_integrateTransformsKernel, 4, sizeof(cl_mem), (void*)&gAngVelMem); + ciErrNum = clSetKernelArg(g_integrateTransformsKernel, 5, sizeof(cl_mem), (void*)&gBodyTimes); + + + + + size_t workGroupSize = 64; + size_t numWorkItems = workGroupSize*((NUM_OBJECTS + (workGroupSize)) / workGroupSize); + + if (workGroupSize>numWorkItems) + workGroupSize=numWorkItems; + + ciErrNum = clEnqueueNDRangeKernel(g_cqCommandQue, g_integrateTransformsKernel, 1, NULL, &numWorkItems, &workGroupSize,0 ,0 ,0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + } + + + } + + if (USE_GL_CL_INTEROP) + { + BT_PROFILE("clEnqueueReleaseGLObjects"); + ciErrNum = clEnqueueReleaseGLObjects(g_cqCommandQue, 1, &clBuffer, 0, 0, 0); + adl::DeviceUtils::waitForCompletion( g_deviceCL ); + } + else + { + BT_PROFILE("clEnqueueReadBuffer clReleaseMemObject and glUnmapBuffer"); + ciErrNum = clEnqueueReadBuffer ( g_cqCommandQue, + clBuffer, + blocking, + 0, + VBOsize, + hostPtr,0,0,0); + + //clReleaseMemObject(clBuffer); + adl::DeviceUtils::waitForCompletion( g_deviceCL ); + glUnmapBuffer( GL_ARRAY_BUFFER); + glFlush(); + } + + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + + if (runOpenCLKernels) + { + BT_PROFILE("clFinish"); + clFinish(g_cqCommandQue); + } + + + + + } +} + + +//#pragma optimize( "g", on ) + + +void RenderScene(void) +{ + BT_PROFILE("GlutDisplayFunc"); + + +#if 0 + float modelview[20]={0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9}; + // get the current modelview matrix + glGetFloatv(GL_MODELVIEW_MATRIX , modelview); + float projection[20]={0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9}; + glGetFloatv(GL_PROJECTION_MATRIX, projection); +#endif + + myinit(); + + updateCamera(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //render coordinate system + glBegin(GL_LINES); + glColor3f(1,0,0); + glVertex3f(0,0,0); + glVertex3f(1,0,0); + glColor3f(0,1,0); + glVertex3f(0,0,0); + glVertex3f(0,1,0); + glColor3f(0,0,1); + glVertex3f(0,0,0); + glVertex3f(0,0,1); + glEnd(); + + //do a finish, to make sure timings are clean + // glFinish(); + + float start = gStopwatch.getTimeMilliseconds(); + + // glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, cube_vbo); + glFlush(); + + //updatePos(); + + simulationLoop(); + + //useCPU = true; + + float stop = gStopwatch.getTimeMilliseconds(); + gStopwatch.reset(); + + if (0)//printStats) + { + printf("updatePos=%f ms on ",stop-start); + + if (useCPU) + { + printf("CPU \n"); + } else + { + printf("OpenCL "); + if (runOpenCLKernels) + printf("running the kernels"); + else + printf("without running the kernels"); + printf("\n"); + } + } + + glBindVertexArray(cube_vao); + + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 9*sizeof(float), 0); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(sizeof(cube_vertices))); + glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(sizeof(cube_vertices)+POSITION_BUFFER_SIZE)); + int uvoffset = 7*sizeof(float); + int normaloffset = 4*sizeof(float); + + glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid *)uvoffset); + glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid *)normaloffset); + glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(sizeof(cube_vertices)+POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE)); + glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(sizeof(cube_vertices)+POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE+COLOR_BUFFER_SIZE)); + + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glEnableVertexAttribArray(2); + glEnableVertexAttribArray(3); + glEnableVertexAttribArray(4); + glEnableVertexAttribArray(5); + glEnableVertexAttribArray(6); + + glVertexAttribDivisor(0, 0); + glVertexAttribDivisor(1, 1); + glVertexAttribDivisor(2, 1); + glVertexAttribDivisor(3, 0); + glVertexAttribDivisor(4, 0); + glVertexAttribDivisor(5, 1); + glVertexAttribDivisor(6, 1); + + glUseProgram(instancingShader); + glUniform1f(angle_loc, 0); + GLfloat pm[16]; + glGetFloatv(GL_PROJECTION_MATRIX, pm); + glUniformMatrix4fv(ProjectionMatrix, 1, false, &pm[0]); + + GLfloat mvm[16]; + glGetFloatv(GL_MODELVIEW_MATRIX, mvm); + glUniformMatrix4fv(ModelViewMatrix, 1, false, &mvm[0]); + + glUniform1i(uniform_texture_diffuse, 0); + + glFlush(); + int numInstances = NUM_OBJECTS; + int indexCount = sizeof(cube_indices)/sizeof(int); + int indexOffset = 0; + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_vbo); + { + BT_PROFILE("glDrawElementsInstanced"); + glDrawElementsInstanced(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, (void*)indexOffset, numInstances); + } + glUseProgram(0); + glBindBuffer(GL_ARRAY_BUFFER,0); + glBindVertexArray(0); + + glutSwapBuffers(); + glutPostRedisplay(); + + GLint err = glGetError(); + assert(err==GL_NO_ERROR); +} + +extern int numPairsOut; +void mainloop(void) +{ + CProfileManager::Reset(); + RenderScene(); + CProfileManager::Increment_Frame_Counter(); + + if (printStats && runOpenCLKernels) + { + static int count = 10; + count--; + if (count<0) + { + CProfileManager::dumpAll(); + printf("total broadphase pairs= %d\n", gFpIO.m_numOverlap); + printf("numPairsOut (culled) = %d\n", numPairsOut); + + printStats = false; + } + } +} + + +void ChangeSize(int w, int h) +{ + m_glutScreenWidth = w; + m_glutScreenHeight = h; + +#ifdef RECREATE_CL_AND_SHADERS_ON_RESIZE + delete g_interopBuffer; + clReleaseKernel(g_integrateTransformsKernel); + releaseFindPairs(fpio); + DeleteCL(); + DeleteShaders(); +#endif //RECREATE_CL_AND_SHADERS_ON_RESIZE + + // Set Viewport to window dimensions + glViewport(0, 0, w, h); + +#ifdef RECREATE_CL_AND_SHADERS_ON_RESIZE + InitCL(); + InitShaders(); + + g_interopBuffer = new btOpenCLGLInteropBuffer(g_cxMainContext,g_cqCommandQue,cube_vbo); + clFinish(g_cqCommandQue); + g_integrateTransformsKernel = btOpenCLUtils::compileCLKernelFromString(g_cxMainContext, interopKernelString, "interopKernel" ); + initFindPairs(...); +#endif //RECREATE_CL_AND_SHADERS_ON_RESIZE + +} + +void Keyboard(unsigned char key, int x, int y) +{ + switch (key) + { + case 27: + done = true; + break; + case 'O': + case 'o': + { + m_ortho = !m_ortho; + break; + } + case 'c': + case 'C': + { + useCPU = !useCPU; + if (useCPU) + printf("using CPU\n"); + else + printf("using OpenCL\n"); + break; + } + case 's': + case 'S': + { + printStats = !printStats; + break; + } + case 'k': + case 'K': + { + runOpenCLKernels=!runOpenCLKernels; + break; + } + case 'q': + case 'Q': + exit(0); + default: + break; + } +} + +// Cleanup +void ShutdownRC(void) +{ + glDeleteBuffers(1, &cube_vbo); + glDeleteVertexArrays(1, &cube_vao); +} + +#include "CommandlineArgs.h" + +void Usage() +{ + printf("\nprogram.exe [--preferred_gpu=] [--batch_gpu=<0,1>] [--preferred_platform=] [--enable_interop=<0 or 1>] [--x_dim=] [--y_dim=] [--z_dim=] [--x_gap=] [--y_gap=] [--z_gap=]\n"); + printf("\n"); + printf("preferred_gpu : the index used for OpenCL, in case multiple OpenCL-capable GPU are available. This is ignored if interop is enabled"); + printf("preferred_platform : the platform index used for OpenCL, in case multiple OpenCL-capable platforms are available. This is ignored if interop is enabled"); + printf("enable_interop : Use OpenGL/OpenCL interoperability, avoiding memory copy between GPU and main memory"); + printf("batch_gpu : Use GPU to created solver batches. Set to zero to disable to improve compatibility with many GPUs"); + + +} + +int main(int argc, char* argv[]) +{ + + CommandLineArgs args(argc,argv); + + if (args.CheckCmdLineFlag("help")) + { + Usage(); + return 0; + } + + args.GetCmdLineArgument("x_dim", NUM_OBJECTS_X); + args.GetCmdLineArgument("y_dim", NUM_OBJECTS_Y); + args.GetCmdLineArgument("z_dim", NUM_OBJECTS_Z); + + args.GetCmdLineArgument("x_gap", X_GAP); + args.GetCmdLineArgument("y_gap", Y_GAP); + args.GetCmdLineArgument("z_gap", Z_GAP); + + args.GetCmdLineArgument("enable_interop", USE_GL_CL_INTEROP); + args.GetCmdLineArgument("preferred_gpu", preferredGPU); + args.GetCmdLineArgument("preferred_platform", preferredPlatform); + args.GetCmdLineArgument("batch_gpu", gpuBatchContacts); + + + + + printf("Dimensions (%d,%d,%d) with gap (%f,%f,%f), using interop=%d, gpu %d, cl platform %d, gpuBatchContacts %d \n",NUM_OBJECTS_X,NUM_OBJECTS_Y,NUM_OBJECTS_Z,X_GAP,Y_GAP,Z_GAP,USE_GL_CL_INTEROP,preferredGPU, preferredPlatform,gpuBatchContacts); + + + + + { + NUM_OBJECTS = NUM_OBJECTS_X*NUM_OBJECTS_Y*NUM_OBJECTS_Z; + POSITION_BUFFER_SIZE = (NUM_OBJECTS*sizeof(float)*4); + ORIENTATION_BUFFER_SIZE = (NUM_OBJECTS*sizeof(float)*4); + COLOR_BUFFER_SIZE = (NUM_OBJECTS*sizeof(float)*4); + SCALE_BUFFER_SIZE = (NUM_OBJECTS*sizeof(float)*3); + } + + srand(0); + // printf("vertexShader = \n%s\n",vertexShader); + // printf("fragmentShader = \n%s\n",fragmentShader); + + glutInit(&argc, argv); + + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); + + + glutInitWindowSize(m_glutScreenWidth, m_glutScreenHeight); + char buf[1024]; + if (USE_GL_CL_INTEROP) + { + sprintf(buf,"GPU rigid body pipeline using OpenCL - OpenGL interop, simulates %d cubes on the GPU (use c to toggle CPU/CL)", NUM_OBJECTS); + } else + { + sprintf(buf,"GPU rigid body pipeline, simulates %d cubes on the GPU (use c to toggle CPU/CL)", NUM_OBJECTS); + } + + glutCreateWindow(buf); + + glutReshapeFunc(ChangeSize); + + glutMouseFunc(mouseFunc); + glutMotionFunc(mouseMotionFunc); + + glutKeyboardFunc(Keyboard); + glutDisplayFunc(mainloop); + + GLenum err = glewInit(); + if (GLEW_OK != err) + { + /* Problem: glewInit failed, something is seriously wrong. */ + fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); + } + + //ChangeSize(m_glutScreenWidth,m_glutScreenHeight); + + + InitCL(preferredGPU, preferredPlatform); + + +#define CUSTOM_CL_INITIALIZATION +#ifdef CUSTOM_CL_INITIALIZATION + g_deviceCL = new adl::DeviceCL(); + g_deviceCL->m_deviceIdx = g_device; + g_deviceCL->m_context = g_cxMainContext; + g_deviceCL->m_commandQueue = g_cqCommandQue; + g_deviceCL->m_kernelManager = new adl::KernelManager; + +#else + DeviceUtils::Config cfg; + cfg.m_type = DeviceUtils::Config::DEVICE_CPU; + g_deviceCL = DeviceUtils::allocate( TYPE_CL, cfg ); +#endif + + int size = NUM_OBJECTS; + adl::Buffer linvelBuf( g_deviceCL, size ); + adl::Buffer angvelBuf( g_deviceCL, size ); + adl::Buffer bodyTimes(g_deviceCL,size); + + gLinVelMem = (cl_mem)linvelBuf.m_ptr; + gAngVelMem = (cl_mem)angvelBuf.m_ptr; + gBodyTimes = (cl_mem)bodyTimes.m_ptr; + + btVector3* linVelHost= new btVector3[size]; + btVector3* angVelHost = new btVector3[size]; + float* bodyTimesHost = new float[size]; + + { + int index=0; + for (int i=0;i verts; + int numVertices = (sizeof(cube_vertices) )/(9*sizeof(GLfloat)); + + for (int i=0;iregisterShape(s_convexHeightField); + + InitShaders(); + + if (USE_GL_CL_INTEROP) + { + g_interopBuffer = new btOpenCLGLInteropBuffer(g_cxMainContext,g_cqCommandQue,cube_vbo); + clFinish(g_cqCommandQue); + } + + + cl_program prog = btOpenCLUtils::compileCLProgramFromString(g_cxMainContext,g_device,interopKernelString,0,"",INTEROPKERNEL_SRC_PATH); + g_integrateTransformsKernel = btOpenCLUtils::compileCLKernelFromString(g_cxMainContext, g_device,interopKernelString, "integrateTransformsKernel" ,0,prog); + + + initFindPairs(gFpIO, g_cxMainContext, g_device, g_cqCommandQue, NUM_OBJECTS); + + + + + + glutMainLoop(); + ShutdownRC(); + + return 0; +} diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/premake4.lua new file mode 100644 index 0000000..d2fbbc8 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline/premake4.lua @@ -0,0 +1,5 @@ + + include "AMD" +-- include "Intel" + include "NVIDIA" + \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/AMD/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/AMD/premake4.lua new file mode 100644 index 0000000..8abbebb --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/AMD/premake4.lua @@ -0,0 +1,64 @@ + + hasCL = findOpenCL_AMD() + + if (hasCL) then + + project "OpenCL_gpu_rigidbody_pipeline2_AMD" + + initOpenCL_AMD() + + language "C++" + + kind "ConsoleApp" + targetdir "../../../bin" + + + initOpenGL() + initGlew() + + includedirs { + "../../primitives", + "../../../../../src" + } + + files { + "../main.cpp", + "../CLPhysicsDemo.cpp", + "../CLPhysicsDemo.h", + "../GLInstancingRenderer.cpp", + "../GLInstancingRenderer.h", + "../GlutRenderer.cpp", + "../GlutRenderer.h", + "../Win32OpenGLRenderManager.cpp", + "../Win32OpenGLRenderManager.h", + "../../gpu_rigidbody_pipeline/btConvexUtility.cpp", + "../../gpu_rigidbody_pipeline/btConvexUtility.h", + "../../gpu_rigidbody_pipeline/btGpuNarrowPhaseAndSolver.cpp", + "../../gpu_rigidbody_pipeline/btGpuNarrowPhaseAndSolver.h", + "../../../dynamics/basic_demo/ConvexHeightFieldShape.cpp", + "../../../dynamics/basic_demo/ConvexHeightFieldShape.h", + "../../../../../src/LinearMath/btConvexHullComputer.cpp", + "../../../../../src/LinearMath/btConvexHullComputer.h", + "../../broadphase_benchmark/findPairsOpenCL.cpp", + "../../broadphase_benchmark/findPairsOpenCL.h", + "../../broadphase_benchmark/btGridBroadphaseCL.cpp", + "../../broadphase_benchmark/btGridBroadphaseCL.h", + "../../3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.cpp", + "../../3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.h", + "../../3dGridBroadphase/Shared/btGpu3DGridBroadphase.cpp", + "../../3dGridBroadphase/Shared/btGpu3DGridBroadphase.h", + "../../../../../src/LinearMath/btAlignedAllocator.cpp", + "../../../../../src/LinearMath/btQuickprof.cpp", + "../../../../../src/LinearMath/btQuickprof.h", + "../../../../../src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp", + "../../../../../src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp", + "../../../../../src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp", + "../../basic_initialize/btOpenCLUtils.cpp", + "../../basic_initialize/btOpenCLUtils.h", + "../../opengl_interop/btOpenCLGLInteropBuffer.cpp", + "../../opengl_interop/btOpenCLGLInteropBuffer.h", + "../../opengl_interop/btStopwatch.cpp", + "../../opengl_interop/btStopwatch.h" + } + + end diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/CLPhysicsDemo.cpp b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/CLPhysicsDemo.cpp new file mode 100644 index 0000000..363f575 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/CLPhysicsDemo.cpp @@ -0,0 +1,529 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + +#include "OpenGLInclude.h" + +#include "CLPhysicsDemo.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "DemoSettings.h" +#include "../basic_initialize/btOpenCLUtils.h" +#include "../opengl_interop/btOpenCLGLInteropBuffer.h" +#include "../broadphase_benchmark/findPairsOpenCL.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btMatrix3x3.h" +#include "../../opencl/gpu_rigidbody_pipeline/btGpuNarrowPhaseAndSolver.h" +#include "../../opencl/gpu_rigidbody_pipeline/btConvexUtility.h" +#include "../../dynamics/basic_demo/ConvexHeightFieldShape.h" +#include "../broadphase_benchmark/btGridBroadphaseCl.h" +#include "LinearMath/btQuickprof.h" + + +#define MSTRINGIFY(A) #A +static char* interopKernelString = +#include "../broadphase_benchmark/integrateKernel.cl" + +#define INTEROPKERNEL_SRC_PATH "../../opencl/broadphase_benchmark/integrateKernel.cl" + +cl_kernel g_integrateTransformsKernel; + + + +bool runOpenCLKernels = true; + + +btGpuNarrowphaseAndSolver* narrowphaseAndSolver = 0; +ConvexHeightField* s_convexHeightField = 0 ; +btOpenCLGLInteropBuffer* g_interopBuffer = 0; + +extern GLuint cube_vbo; +extern int VBOsize; + +cl_mem clBuffer=0; +char* hostPtr=0; +cl_bool blocking= CL_TRUE; + + + +btFindPairsIO gFpIO; + +cl_context g_cxMainContext; +cl_command_queue g_cqCommandQue; +cl_device_id g_device; + +cl_mem gLinVelMem=0; +cl_mem gAngVelMem=0; +cl_mem gBodyTimes=0; + +#include + +adl::DeviceCL* g_deviceCL=0; + +struct btAABBHost //keep this in sync with btAABBCL! +{ + float fx; + float fy; + float fz; + unsigned int uw; +}; + +struct InternalData +{ + adl::Buffer* m_linVelBuf; + adl::Buffer* m_angVelBuf; + adl::Buffer* m_bodyTimes; + bool m_useInterop; + btGridBroadphaseCl* m_Broadphase; + + adl::Buffer* m_localShapeAABB; + + btVector3* m_linVelHost; + btVector3* m_angVelHost; + float* m_bodyTimesHost; + + InternalData():m_linVelBuf(0),m_angVelBuf(0),m_bodyTimes(0),m_useInterop(0),m_Broadphase(0) + { + m_linVelHost= new btVector3[MAX_CONVEX_BODIES_CL]; + m_angVelHost = new btVector3[MAX_CONVEX_BODIES_CL]; + m_bodyTimesHost = new float[MAX_CONVEX_BODIES_CL]; + } + ~InternalData() + { + delete[] m_linVelHost; + delete[] m_angVelHost; + delete[] m_bodyTimesHost; + + } +}; + + +void InitCL(int preferredDeviceIndex, int preferredPlatformIndex, bool useInterop) +{ + void* glCtx=0; + void* glDC = 0; + +#ifdef _WIN32 + glCtx = wglGetCurrentContext(); +#else //!_WIN32 + GLXContext glCtx = glXGetCurrentContext(); +#endif //!_WIN32 + glDC = wglGetCurrentDC(); + + int ciErrNum = 0; +#ifdef CL_PLATFORM_INTEL + cl_device_type deviceType = CL_DEVICE_TYPE_ALL; +#else + cl_device_type deviceType = CL_DEVICE_TYPE_GPU; +#endif + + + + if (useInterop) + { + g_cxMainContext = btOpenCLUtils::createContextFromType(deviceType, &ciErrNum, glCtx, glDC); + } else + { + g_cxMainContext = btOpenCLUtils::createContextFromType(deviceType, &ciErrNum, 0,0,preferredDeviceIndex, preferredPlatformIndex); + } + + + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + int numDev = btOpenCLUtils::getNumDevices(g_cxMainContext); + + if (numDev>0) + { + g_device= btOpenCLUtils::getDevice(g_cxMainContext,0); + btOpenCLDeviceInfo clInfo; + btOpenCLUtils::getDeviceInfo(g_device,clInfo); + btOpenCLUtils::printDeviceInfo(g_device); + g_cqCommandQue = clCreateCommandQueue(g_cxMainContext, g_device, 0, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + +} + + + + +CLPhysicsDemo::CLPhysicsDemo(Win32OpenGLWindow* renderer) +{ + m_numCollisionShapes=0; + m_numPhysicsInstances=0; + + m_data = new InternalData; +} + +CLPhysicsDemo::~CLPhysicsDemo() +{ + +} + + +void CLPhysicsDemo::writeBodiesToGpu() +{ + if (narrowphaseAndSolver) + narrowphaseAndSolver->writeAllBodiesToGpu(); +} + +int CLPhysicsDemo::registerCollisionShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling) +{ + btAlignedObjectArray verts; + + unsigned char* vts = (unsigned char*) vertices; + for (int i=0;iregisterShape(s_convexHeightField); + + if (shapeIndex>=0) + { + btAABBHost aabbMin, aabbMax; + aabbMin.fx = s_convexHeightField->m_aabb.m_min.x; + aabbMin.fy = s_convexHeightField->m_aabb.m_min.y; + aabbMin.fz= s_convexHeightField->m_aabb.m_min.z; + aabbMin.uw = shapeIndex; + + aabbMax.fx = s_convexHeightField->m_aabb.m_max.x; + aabbMax.fy = s_convexHeightField->m_aabb.m_max.y; + aabbMax.fz= s_convexHeightField->m_aabb.m_max.z; + aabbMax.uw = shapeIndex; + + m_data->m_localShapeAABB->write(&aabbMin,1,shapeIndex*2); + m_data->m_localShapeAABB->write(&aabbMax,1,shapeIndex*2+1); + adl::DeviceUtils::waitForCompletion( g_deviceCL ); + } + + m_numCollisionShapes++; + delete[] eqn; + return shapeIndex; +} + +int CLPhysicsDemo::registerPhysicsInstance(float mass, const float* position, const float* orientation, int collisionShapeIndex, void* userPointer) +{ + btVector3 aabbMin(position[0],position[0],position[0]); + btVector3 aabbMax = aabbMin; + aabbMin -= btVector3(1.f,1.f,1.f); + aabbMax += btVector3(1.f,1.f,1.f); + + if (collisionShapeIndex>=0) + { + btBroadphaseProxy* proxy = m_data->m_Broadphase->createProxy(aabbMin,aabbMax,collisionShapeIndex,userPointer,1,1,0,0);//m_dispatcher); + } + + bool writeToGpu = false; + int bodyIndex = -1; + + if (narrowphaseAndSolver) + bodyIndex = narrowphaseAndSolver->registerRigidBody(collisionShapeIndex,mass,position,orientation,writeToGpu); + + m_numPhysicsInstances++; + return bodyIndex; +} + + + +void CLPhysicsDemo::init(int preferredDevice, int preferredPlatform, bool useInterop) +{ + + InitCL(-1,-1,useInterop); + +#define CUSTOM_CL_INITIALIZATION +#ifdef CUSTOM_CL_INITIALIZATION + g_deviceCL = new adl::DeviceCL(); + g_deviceCL->m_deviceIdx = g_device; + g_deviceCL->m_context = g_cxMainContext; + g_deviceCL->m_commandQueue = g_cqCommandQue; + g_deviceCL->m_kernelManager = new adl::KernelManager; + +#else + DeviceUtils::Config cfg; + cfg.m_type = DeviceUtils::Config::DEVICE_CPU; + g_deviceCL = DeviceUtils::allocate( TYPE_CL, cfg ); +#endif + + //adl::Solver::allocate(g_deviceCL->allocate( + m_data->m_linVelBuf = new adl::Buffer(g_deviceCL,MAX_CONVEX_BODIES_CL); + m_data->m_angVelBuf = new adl::Buffer(g_deviceCL,MAX_CONVEX_BODIES_CL); + m_data->m_bodyTimes = new adl::Buffer(g_deviceCL,MAX_CONVEX_BODIES_CL); + + m_data->m_localShapeAABB = new adl::Buffer(g_deviceCL,MAX_CONVEX_SHAPES_CL); + + gLinVelMem = (cl_mem)m_data->m_linVelBuf->m_ptr; + gAngVelMem = (cl_mem)m_data->m_angVelBuf->m_ptr; + gBodyTimes = (cl_mem)m_data->m_bodyTimes->m_ptr; + + + + + narrowphaseAndSolver = new btGpuNarrowphaseAndSolver(g_deviceCL); + + + + int maxObjects = btMax(256,MAX_CONVEX_BODIES_CL); + int maxPairsSmallProxy = 32; + btOverlappingPairCache* overlappingPairCache=0; + + m_data->m_Broadphase = new btGridBroadphaseCl(overlappingPairCache,btVector3(4.f, 4.f, 4.f), 128, 128, 128,maxObjects, maxObjects, maxPairsSmallProxy, 100.f, 128, + g_cxMainContext ,g_device,g_cqCommandQue, g_deviceCL); + + + + cl_program prog = btOpenCLUtils::compileCLProgramFromString(g_cxMainContext,g_device,interopKernelString,0,"",INTEROPKERNEL_SRC_PATH); + g_integrateTransformsKernel = btOpenCLUtils::compileCLKernelFromString(g_cxMainContext, g_device,interopKernelString, "integrateTransformsKernel" ,0,prog); + + + initFindPairs(gFpIO, g_cxMainContext, g_device, g_cqCommandQue, MAX_CONVEX_BODIES_CL); + + + + +} + + + +void CLPhysicsDemo::writeVelocitiesToGpu() +{ + m_data->m_linVelBuf->write(m_data->m_linVelHost,MAX_CONVEX_BODIES_CL); + m_data->m_angVelBuf->write(m_data->m_angVelHost,MAX_CONVEX_BODIES_CL); + m_data->m_bodyTimes->write(m_data->m_bodyTimesHost,MAX_CONVEX_BODIES_CL); + adl::DeviceUtils::waitForCompletion( g_deviceCL ); +} + + +void CLPhysicsDemo::setupInterop() +{ + m_data->m_useInterop = true; + + g_interopBuffer = new btOpenCLGLInteropBuffer(g_cxMainContext,g_cqCommandQue,cube_vbo); + clFinish(g_cqCommandQue); +} + +void CLPhysicsDemo::cleanup() +{ + delete narrowphaseAndSolver; + + delete m_data->m_linVelBuf; + delete m_data->m_angVelBuf; + delete m_data->m_bodyTimes; + delete m_data->m_localShapeAABB; + + delete m_data->m_Broadphase; + delete m_data; + + delete g_deviceCL->m_kernelManager; + delete g_deviceCL; + + m_data=0; + g_deviceCL=0; + delete g_interopBuffer; + delete s_convexHeightField; +} + + + + + +void CLPhysicsDemo::stepSimulation() +{ + BT_PROFILE("simulationLoop"); + + { + BT_PROFILE("glFinish"); + glFinish(); + } + cl_int ciErrNum = CL_SUCCESS; + + + if(m_data->m_useInterop) + { + clBuffer = g_interopBuffer->getCLBUffer(); + BT_PROFILE("clEnqueueAcquireGLObjects"); + ciErrNum = clEnqueueAcquireGLObjects(g_cqCommandQue, 1, &clBuffer, 0, 0, NULL); + adl::DeviceUtils::waitForCompletion( g_deviceCL ); + } else + { + + glBindBuffer(GL_ARRAY_BUFFER, cube_vbo); + glFlush(); + + BT_PROFILE("glMapBuffer and clEnqueueWriteBuffer"); + + blocking= CL_TRUE; + hostPtr= (char*)glMapBuffer( GL_ARRAY_BUFFER,GL_READ_WRITE);//GL_WRITE_ONLY + if (!clBuffer) + { + clBuffer = clCreateBuffer(g_cxMainContext, CL_MEM_READ_WRITE, VBOsize, 0, &ciErrNum); + } + adl::DeviceUtils::waitForCompletion( g_deviceCL ); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + ciErrNum = clEnqueueWriteBuffer ( g_cqCommandQue, + clBuffer, + blocking, + 0, + VBOsize, + hostPtr,0,0,0 + ); + adl::DeviceUtils::waitForCompletion( g_deviceCL ); + } + + + + oclCHECKERROR(ciErrNum, CL_SUCCESS); + if (runOpenCLKernels && m_numPhysicsInstances) + { + + gFpIO.m_numObjects = m_numPhysicsInstances; + gFpIO.m_positionOffset = SHAPE_VERTEX_BUFFER_SIZE/4; + gFpIO.m_clObjectsBuffer = clBuffer; + gFpIO.m_dAABB = m_data->m_Broadphase->m_dAABB; + gFpIO.m_dlocalShapeAABB = (cl_mem)m_data->m_localShapeAABB->m_ptr; + gFpIO.m_numOverlap = 0; + { + BT_PROFILE("setupGpuAabbs"); + setupGpuAabbsFull(gFpIO,narrowphaseAndSolver->getBodiesGpu() ); + } + if (1) + { + BT_PROFILE("calculateOverlappingPairs"); + m_data->m_Broadphase->calculateOverlappingPairs(0, m_numPhysicsInstances); + gFpIO.m_dAllOverlappingPairs = m_data->m_Broadphase->m_dAllOverlappingPairs; + gFpIO.m_numOverlap = m_data->m_Broadphase->m_numPrefixSum; + } + + //printf("gFpIO.m_numOverlap = %d\n",gFpIO.m_numOverlap ); + if (gFpIO.m_numOverlap>=0 && gFpIO.m_numOverlapgetBodiesGpu(), narrowphaseAndSolver->getBodyInertiasGpu()); + } + if (gFpIO.m_numOverlap) + { + BT_PROFILE("computeContactsAndSolver"); + if (narrowphaseAndSolver) + narrowphaseAndSolver->computeContactsAndSolver(gFpIO.m_dAllOverlappingPairs,gFpIO.m_numOverlap); + } + + { + BT_PROFILE("copyBodyVelocities"); + if (narrowphaseAndSolver) + copyBodyVelocities(gFpIO, gLinVelMem, gAngVelMem, narrowphaseAndSolver->getBodiesGpu(), narrowphaseAndSolver->getBodyInertiasGpu()); + } + } + + } else + { + printf("error, gFpIO.m_numOverlap = %d\n",gFpIO.m_numOverlap); + btAssert(0); + } + + + { + BT_PROFILE("integrateTransforms"); + + if (runOpenCLKernels) + { + int numObjects = m_numPhysicsInstances; + int offset = SHAPE_VERTEX_BUFFER_SIZE/4; + + ciErrNum = clSetKernelArg(g_integrateTransformsKernel, 0, sizeof(int), &offset); + ciErrNum = clSetKernelArg(g_integrateTransformsKernel, 1, sizeof(int), &numObjects); + ciErrNum = clSetKernelArg(g_integrateTransformsKernel, 2, sizeof(cl_mem), (void*)&clBuffer ); + + ciErrNum = clSetKernelArg(g_integrateTransformsKernel, 3, sizeof(cl_mem), (void*)&gLinVelMem); + ciErrNum = clSetKernelArg(g_integrateTransformsKernel, 4, sizeof(cl_mem), (void*)&gAngVelMem); + ciErrNum = clSetKernelArg(g_integrateTransformsKernel, 5, sizeof(cl_mem), (void*)&gBodyTimes); + + + + + size_t workGroupSize = 64; + size_t numWorkItems = workGroupSize*((m_numPhysicsInstances + (workGroupSize)) / workGroupSize); + + if (workGroupSize>numWorkItems) + workGroupSize=numWorkItems; + + ciErrNum = clEnqueueNDRangeKernel(g_cqCommandQue, g_integrateTransformsKernel, 1, NULL, &numWorkItems, &workGroupSize,0 ,0 ,0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + } + + + } + + if(m_data->m_useInterop) + { + BT_PROFILE("clEnqueueReleaseGLObjects"); + ciErrNum = clEnqueueReleaseGLObjects(g_cqCommandQue, 1, &clBuffer, 0, 0, 0); + adl::DeviceUtils::waitForCompletion( g_deviceCL ); + } + else + { + BT_PROFILE("clEnqueueReadBuffer clReleaseMemObject and glUnmapBuffer"); + ciErrNum = clEnqueueReadBuffer ( g_cqCommandQue, + clBuffer, + blocking, + 0, + VBOsize, + hostPtr,0,0,0); + + //clReleaseMemObject(clBuffer); + adl::DeviceUtils::waitForCompletion( g_deviceCL ); + glUnmapBuffer( GL_ARRAY_BUFFER); + glFlush(); + } + + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + + if (runOpenCLKernels) + { + BT_PROFILE("clFinish"); + clFinish(g_cqCommandQue); + } + + +} diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/CLPhysicsDemo.h b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/CLPhysicsDemo.h new file mode 100644 index 0000000..0ed2e73 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/CLPhysicsDemo.h @@ -0,0 +1,53 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + +#ifndef CL_PHYSICS_DEMO_H +#define CL_PHYSICS_DEMO_H + +class Win32OpenGLWindow; + +struct CLPhysicsDemo +{ + Win32OpenGLWindow* m_renderer; + + int m_numCollisionShapes; + + int m_numPhysicsInstances; + + struct InternalData* m_data; + + CLPhysicsDemo(Win32OpenGLWindow* renderer); + + virtual ~CLPhysicsDemo(); + + //btOpenCLGLInteropBuffer* m_interopBuffer; + + void init(int preferredDevice, int preferredPlatform, bool useInterop); + + void setupInterop(); + + int registerCollisionShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling); + + int registerPhysicsInstance(float mass, const float* position, const float* orientation, int collisionShapeIndex, void* userPointer); + + void writeVelocitiesToGpu(); + void writeBodiesToGpu(); + + void cleanup(); + + void stepSimulation(); +}; + +#endif//CL_PHYSICS_DEMO_H \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/DemoSettings.h b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/DemoSettings.h new file mode 100644 index 0000000..5b55e00 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/DemoSettings.h @@ -0,0 +1,24 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + +#ifndef DEMO_SETTINGS_H +#define DEMO_SETTINGS_H + +#define SHAPE_VERTEX_BUFFER_SIZE 1024*1024 + +#define SHAPE_BUFFER_SIZE (SHAPE_VERTEX_BUFFER_SIZE) + + +#endif //DEMO_SETTINGS_H \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/GLInstancingRenderer.cpp b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/GLInstancingRenderer.cpp new file mode 100644 index 0000000..9e75253 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/GLInstancingRenderer.cpp @@ -0,0 +1,861 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + +#include "OpenGLInclude.h" +#include "GLInstancingRenderer.h" + +#include +#include "DemoSettings.h" +#include +#include +#include "LinearMath/btVector3.h" +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btMatrix3x3.h" + +#include "../../opencl/gpu_rigidbody_pipeline/btGpuNarrowphaseAndSolver.h"//for MAX_CONVEX_BODIES_CL + +struct btGraphicsInstance +{ + GLuint m_cube_vao; + GLuint m_index_vbo; + int m_numIndices; + int m_numVertices; + + int m_numGraphicsInstances; + + int m_instanceOffset; + int m_vertexArrayOffset; + + btGraphicsInstance() :m_cube_vao(-1),m_index_vbo(-1),m_numIndices(-1),m_numVertices(-1),m_numGraphicsInstances(0),m_instanceOffset(0),m_vertexArrayOffset(0) + { + } + +}; + + + +bool m_ortho = false; +int m_glutScreenWidth = 1024; +int m_glutScreenHeight = 768; + + + +extern int gShapeIndex; + + +btVector3 m_cameraPosition(0,0,0);//will be overridden by a position computed from azi/ele +btVector3 m_cameraTargetPosition(30,-5,-20); +btScalar m_cameraDistance = 95; +btVector3 m_cameraUp(0,1,0); +float m_azi=95.f; +float m_ele=15.f; + + + + +int VBOsize =0; + + + +struct InternalDataRenderer +{ + GLfloat* m_instance_positions_ptr; + GLfloat* m_instance_quaternion_ptr; + GLfloat* m_instance_colors_ptr; + GLfloat* m_instance_scale_ptr; + + InternalDataRenderer() :m_instance_positions_ptr (0),m_instance_quaternion_ptr(0),m_instance_colors_ptr(0),m_instance_scale_ptr(0) + { + } + +}; + +static GLuint instancingShader; // The instancing renderer + +GLuint cube_vbo; + +static GLuint m_texturehandle; + +static bool done = false; +static GLint angle_loc = 0; +static GLint ModelViewMatrix; +static GLint ProjectionMatrix; + + + +GLInstancingRenderer::GLInstancingRenderer() +{ + + m_data = new InternalDataRenderer; + + m_data->m_instance_positions_ptr = (GLfloat*)new float[MAX_CONVEX_BODIES_CL*4]; + m_data->m_instance_quaternion_ptr = (GLfloat*)new float[MAX_CONVEX_BODIES_CL*4]; + m_data->m_instance_colors_ptr = (GLfloat*)new float[MAX_CONVEX_BODIES_CL*4]; + m_data->m_instance_scale_ptr = (GLfloat*)new float[MAX_CONVEX_BODIES_CL*3]; + +} + +GLInstancingRenderer::~GLInstancingRenderer() +{ + delete m_data; +} + + +static GLint uniform_texture_diffuse = 0; + +//used for dynamic loading from disk (default switched off) +#define MAX_SHADER_LENGTH 8192 +static GLubyte shaderText[MAX_SHADER_LENGTH]; + +static const char* vertexShader= \ +"#version 330\n" +"precision highp float;\n" +"\n" +"\n" +"\n" +"layout (location = 0) in vec4 position;\n" +"layout (location = 1) in vec4 instance_position;\n" +"layout (location = 2) in vec4 instance_quaternion;\n" +"layout (location = 3) in vec2 uvcoords;\n" +"layout (location = 4) in vec3 vertexnormal;\n" +"layout (location = 5) in vec4 instance_color;\n" +"layout (location = 6) in vec3 instance_scale;\n" +"\n" +"\n" +"uniform float angle = 0.0;\n" +"uniform mat4 ModelViewMatrix;\n" +"uniform mat4 ProjectionMatrix;\n" +"\n" +"out Fragment\n" +"{\n" +" vec4 color;\n" +"} fragment;\n" +"\n" +"out Vert\n" +"{\n" +" vec2 texcoord;\n" +"} vert;\n" +"\n" +"\n" +"vec4 quatMul ( in vec4 q1, in vec4 q2 )\n" +"{\n" +" vec3 im = q1.w * q2.xyz + q1.xyz * q2.w + cross ( q1.xyz, q2.xyz );\n" +" vec4 dt = q1 * q2;\n" +" float re = dot ( dt, vec4 ( -1.0, -1.0, -1.0, 1.0 ) );\n" +" return vec4 ( im, re );\n" +"}\n" +"\n" +"vec4 quatFromAxisAngle(vec4 axis, in float angle)\n" +"{\n" +" float cah = cos(angle*0.5);\n" +" float sah = sin(angle*0.5);\n" +" float d = inversesqrt(dot(axis,axis));\n" +" vec4 q = vec4(axis.x*sah*d,axis.y*sah*d,axis.z*sah*d,cah);\n" +" return q;\n" +"}\n" +"//\n" +"// vector rotation via quaternion\n" +"//\n" +"vec4 quatRotate3 ( in vec3 p, in vec4 q )\n" +"{\n" +" vec4 temp = quatMul ( q, vec4 ( p, 0.0 ) );\n" +" return quatMul ( temp, vec4 ( -q.x, -q.y, -q.z, q.w ) );\n" +"}\n" +"vec4 quatRotate ( in vec4 p, in vec4 q )\n" +"{\n" +" vec4 temp = quatMul ( q, p );\n" +" return quatMul ( temp, vec4 ( -q.x, -q.y, -q.z, q.w ) );\n" +"}\n" +"\n" +"out vec3 lightDir,normal,ambient;\n" +"\n" +"void main(void)\n" +"{\n" +" vec4 q = instance_quaternion;\n" +" ambient = vec3(0.3,.3,0.3);\n" +" \n" +" \n" +" vec4 local_normal = (quatRotate3( vertexnormal,q));\n" +" vec3 light_pos = vec3(-0.8,1,-0.6);\n" +" normal = local_normal.xyz;\n"//normalize(ModelViewMatrix * local_normal).xyz;\n" +"\n" +" lightDir = normalize(light_pos);//gl_LightSource[0].position.xyz));\n" +"// lightDir = normalize(vec3(gl_LightSource[0].position));\n" +" \n" +" vec4 axis = vec4(1,1,1,0);\n" +" vec4 localcoord = quatRotate3( position.xyz*instance_scale,q);\n" +" vec4 vertexPos = ProjectionMatrix * ModelViewMatrix *(instance_position+localcoord);\n" +"\n" +" gl_Position = vertexPos;\n" +" \n" +" fragment.color = instance_color;\n" +" vert.texcoord = uvcoords;\n" +"}\n" +; + + +static const char* fragmentShader= \ +"#version 330\n" +"precision highp float;\n" +"\n" +"in Fragment\n" +"{\n" +" vec4 color;\n" +"} fragment;\n" +"\n" +"in Vert\n" +"{\n" +" vec2 texcoord;\n" +"} vert;\n" +"\n" +"uniform sampler2D Diffuse;\n" +"\n" +"in vec3 lightDir,normal,ambient;\n" +"\n" +"out vec4 color;\n" +"\n" +"void main_textured(void)\n" +"{\n" +" color = texture2D(Diffuse,vert.texcoord);//fragment.color;\n" +"}\n" +"\n" +"void main(void)\n" +"{\n" +" vec4 texel = fragment.color*texture2D(Diffuse,vert.texcoord);//fragment.color;\n" +" vec3 ct,cf;\n" +" float intensity,at,af;\n" +" intensity = max(dot(lightDir,normalize(normal)),.2);\n" +" cf = intensity*vec3(1.0,1.0,1.0)+ambient;" +" af = 1.0;\n" +" \n" +" ct = texel.rgb;\n" +" at = texel.a;\n" +" \n" +" color = vec4(ct * cf, at * af); \n" +"}\n" +; + + +// Load the shader from the source text +void gltLoadShaderSrc(const char *szShaderSrc, GLuint shader) +{ + GLchar *fsStringPtr[1]; + + fsStringPtr[0] = (GLchar *)szShaderSrc; + glShaderSource(shader, 1, (const GLchar **)fsStringPtr, NULL); +} + + +GLuint gltLoadShaderPair(const char *szVertexProg, const char *szFragmentProg) +{ + // Temporary Shader objects + GLuint hVertexShader; + GLuint hFragmentShader; + GLuint hReturn = 0; + GLint testVal; + + // Create shader objects + hVertexShader = glCreateShader(GL_VERTEX_SHADER); + hFragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + + gltLoadShaderSrc(vertexShader, hVertexShader); + gltLoadShaderSrc(fragmentShader, hFragmentShader); + + // Compile them + glCompileShader(hVertexShader); + glCompileShader(hFragmentShader); + + // Check for errors + glGetShaderiv(hVertexShader, GL_COMPILE_STATUS, &testVal); + if(testVal == GL_FALSE) + { + char temp[256] = ""; + glGetShaderInfoLog( hVertexShader, 256, NULL, temp); + fprintf( stderr, "Compile failed:\n%s\n", temp); + assert(0); + exit(0); + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + + glGetShaderiv(hFragmentShader, GL_COMPILE_STATUS, &testVal); + if(testVal == GL_FALSE) + { + char temp[256] = ""; + glGetShaderInfoLog( hFragmentShader, 256, NULL, temp); + fprintf( stderr, "Compile failed:\n%s\n", temp); + assert(0); + exit(0); + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + + // Link them - assuming it works... + hReturn = glCreateProgram(); + glAttachShader(hReturn, hVertexShader); + glAttachShader(hReturn, hFragmentShader); + + glLinkProgram(hReturn); + + // These are no longer needed + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + + // Make sure link worked too + glGetProgramiv(hReturn, GL_LINK_STATUS, &testVal); + if(testVal == GL_FALSE) + { + glDeleteProgram(hReturn); + return (GLuint)NULL; + } + + return hReturn; +} + + +void GLInstancingRenderer::writeTransforms() +{ + glBindBuffer(GL_ARRAY_BUFFER, cube_vbo); + glFlush(); + + char* orgBase = (char*)glMapBuffer( GL_ARRAY_BUFFER,GL_READ_WRITE); + + int totalNumInstances= 0; + + for (int k=0;km_numGraphicsInstances; + } + + + + for (int k=0;km_numGraphicsInstances;i++) + { + + int srcIndex=i+gfxObj->m_instanceOffset; + + positions[srcIndex*4] = m_data->m_instance_positions_ptr[srcIndex*4]; + positions[srcIndex*4+1] = m_data->m_instance_positions_ptr[srcIndex*4+1]; + positions[srcIndex*4+2] = m_data->m_instance_positions_ptr[srcIndex*4+2]; + positions[srcIndex*4+3] = m_data->m_instance_positions_ptr[srcIndex*4+3]; + + orientations[srcIndex*4]=m_data->m_instance_quaternion_ptr[srcIndex*4]; + orientations[srcIndex*4+1]=m_data->m_instance_quaternion_ptr[srcIndex*4+1]; + orientations[srcIndex*4+2]=m_data->m_instance_quaternion_ptr[srcIndex*4+2]; + orientations[srcIndex*4+3]=m_data->m_instance_quaternion_ptr[srcIndex*4+3]; + + colors[srcIndex*4]=m_data->m_instance_colors_ptr[srcIndex*4]; + colors[srcIndex*4+1]=m_data->m_instance_colors_ptr[srcIndex*4+1]; + colors[srcIndex*4+2]=m_data->m_instance_colors_ptr[srcIndex*4+2]; + colors[srcIndex*4+3]=m_data->m_instance_colors_ptr[srcIndex*4+3]; + + scaling[srcIndex*3]=m_data->m_instance_scale_ptr[srcIndex*3]; + scaling[srcIndex*3+1]=m_data->m_instance_scale_ptr[srcIndex*3+1]; + scaling[srcIndex*3+2]=m_data->m_instance_scale_ptr[srcIndex*3+2]; + + } + } + + glUnmapBuffer( GL_ARRAY_BUFFER); + //if this glFinish is removed, the animation is not always working/blocks + //@todo: figure out why + glFlush(); +} + +int GLInstancingRenderer::registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling) +{ + btGraphicsInstance* gfxObj = m_graphicsInstances[shapeIndex]; + + int index = gfxObj->m_numGraphicsInstances + gfxObj->m_instanceOffset; + + + + m_data->m_instance_positions_ptr[index*4]=position[0]; + m_data->m_instance_positions_ptr[index*4+1]=position[1]; + m_data->m_instance_positions_ptr[index*4+2]=position[2]; + m_data->m_instance_positions_ptr[index*4+3]=1; + + m_data->m_instance_quaternion_ptr[index*4]=quaternion[0]; + m_data->m_instance_quaternion_ptr[index*4+1]=quaternion[1]; + m_data->m_instance_quaternion_ptr[index*4+2]=quaternion[2]; + m_data->m_instance_quaternion_ptr[index*4+3]=quaternion[3]; + + m_data->m_instance_colors_ptr[index*4]=color[0]; + m_data->m_instance_colors_ptr[index*4+1]=color[1]; + m_data->m_instance_colors_ptr[index*4+2]=color[2]; + m_data->m_instance_colors_ptr[index*4+3]=color[3]; + + m_data->m_instance_scale_ptr[index*3] = scaling[0]; + m_data->m_instance_scale_ptr[index*3+1] = scaling[1]; + m_data->m_instance_scale_ptr[index*3+2] = scaling[2]; + + gfxObj->m_numGraphicsInstances++; + return gfxObj->m_numGraphicsInstances; +} + + +int GLInstancingRenderer::registerShape(const float* vertices, int numvertices, const int* indices, int numIndices) +{ + btGraphicsInstance* gfxObj = new btGraphicsInstance; + + if (m_graphicsInstances.size()) + { + btGraphicsInstance* prevObj = m_graphicsInstances[m_graphicsInstances.size()-1]; + gfxObj->m_instanceOffset = prevObj->m_instanceOffset + prevObj->m_numGraphicsInstances; + gfxObj->m_vertexArrayOffset = prevObj->m_vertexArrayOffset + prevObj->m_numVertices; + } else + { + gfxObj->m_instanceOffset = 0; + } + + m_graphicsInstances.push_back(gfxObj); + gfxObj->m_numIndices = numIndices; + gfxObj->m_numVertices = numvertices; + + + glBindBuffer(GL_ARRAY_BUFFER, cube_vbo); + char* dest= (char*)glMapBuffer( GL_ARRAY_BUFFER,GL_WRITE_ONLY);//GL_WRITE_ONLY + int vertexStrideInBytes = 9*sizeof(float); + int sz = numvertices*vertexStrideInBytes; + memcpy(dest+vertexStrideInBytes*gfxObj->m_vertexArrayOffset,vertices,sz); + glUnmapBuffer( GL_ARRAY_BUFFER); + + glGenBuffers(1, &gfxObj->m_index_vbo); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gfxObj->m_index_vbo); + int indexBufferSizeInBytes = gfxObj->m_numIndices*sizeof(int); + + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBufferSizeInBytes, NULL, GL_STATIC_DRAW); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,0,indexBufferSizeInBytes,indices); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glGenVertexArrays(1, &gfxObj->m_cube_vao); + glBindVertexArray(gfxObj->m_cube_vao); + glBindBuffer(GL_ARRAY_BUFFER, cube_vbo); + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER,0); + glBindVertexArray(0); + + + return m_graphicsInstances.size()-1; +} + + + + +void GLInstancingRenderer::InitShaders() +{ + + int POSITION_BUFFER_SIZE = (MAX_CONVEX_BODIES_CL*sizeof(float)*4); + int ORIENTATION_BUFFER_SIZE = (MAX_CONVEX_BODIES_CL*sizeof(float)*4); + int COLOR_BUFFER_SIZE = (MAX_CONVEX_BODIES_CL*sizeof(float)*4); + int SCALE_BUFFER_SIZE = (MAX_CONVEX_BODIES_CL*sizeof(float)*3); + + + instancingShader = gltLoadShaderPair(vertexShader,fragmentShader); + + glLinkProgram(instancingShader); + glUseProgram(instancingShader); + angle_loc = glGetUniformLocation(instancingShader, "angle"); + ModelViewMatrix = glGetUniformLocation(instancingShader, "ModelViewMatrix"); + ProjectionMatrix = glGetUniformLocation(instancingShader, "ProjectionMatrix"); + uniform_texture_diffuse = glGetUniformLocation(instancingShader, "Diffuse"); + + GLuint offset = 0; + + + glGenBuffers(1, &cube_vbo); + glBindBuffer(GL_ARRAY_BUFFER, cube_vbo); + + + int size = SHAPE_BUFFER_SIZE + POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE+COLOR_BUFFER_SIZE+SCALE_BUFFER_SIZE; + VBOsize = size; + + glBufferData(GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW);//GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER,0); + glBindVertexArray(0); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + +} + + +void myinit() +{ + GLint err = glGetError(); + + // GLfloat light_ambient[] = { btScalar(0.2), btScalar(0.2), btScalar(0.2), btScalar(1.0) }; + GLfloat light_ambient[] = { btScalar(1.0), btScalar(1.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 )}; + /* light_position is NOT default value */ + GLfloat light_position0[] = { btScalar(10000.0), btScalar(10000.0), btScalar(10000.0), btScalar(0.0 )}; + GLfloat light_position1[] = { btScalar(-1.0), btScalar(-10.0), btScalar(-1.0), btScalar(0.0) }; + + glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT0, GL_POSITION, light_position0); + + glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT1, GL_POSITION, light_position1); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + + + // glShadeModel(GL_FLAT);//GL_SMOOTH); + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + glClearColor(float(0.7),float(0.7),float(0.7),float(0)); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + + static bool m_textureenabled = true; + static bool m_textureinitialized = false; + + + if(m_textureenabled) + { + if(!m_textureinitialized) + { + glActiveTexture(GL_TEXTURE0); + + GLubyte* image=new GLubyte[256*256*3]; + for(int y=0;y<256;++y) + { + const int t=y>>5; + GLubyte* pi=image+y*256*3; + for(int x=0;x<256;++x) + { + if (x<2||y<2||x>253||y>253) + { + pi[0]=0; + pi[1]=0; + pi[2]=0; + } else + { + pi[0]=255; + pi[1]=255; + pi[2]=255; + } + + /* + const int s=x>>5; + const GLubyte b=180; + GLubyte c=b+((s+t&1)&1)*(255-b); + pi[0]=c; + pi[1]=c; + pi[2]=c; + */ + + pi+=3; + } + } + + glGenTextures(1,(GLuint*)&m_texturehandle); + glBindTexture(GL_TEXTURE_2D,m_texturehandle); + glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); + gluBuild2DMipmaps(GL_TEXTURE_2D,3,256,256,GL_RGB,GL_UNSIGNED_BYTE,image); + delete[] image; + m_textureinitialized=true; + } + // glMatrixMode(GL_TEXTURE); + // glLoadIdentity(); + // glMatrixMode(GL_MODELVIEW); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,m_texturehandle); + + } else + { + glDisable(GL_TEXTURE_2D); + } + + glEnable(GL_COLOR_MATERIAL); + + err = glGetError(); + assert(err==GL_NO_ERROR); + + // glEnable(GL_CULL_FACE); + // glCullFace(GL_BACK); +} + +void updateCamera() +{ + + + + btVector3 m_cameraUp(0,1,0); + int m_forwardAxis=2; + + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + + //m_azi+=0.0f; + + btScalar rele = m_ele * btScalar(0.01745329251994329547);// rads per deg + btScalar razi = m_azi * btScalar(0.01745329251994329547);// rads per deg + + + btQuaternion rot(m_cameraUp,razi); + + + btVector3 eyePos(0,0,0); + eyePos[m_forwardAxis] = -m_cameraDistance; + + btVector3 forward(eyePos[0],eyePos[1],eyePos[2]); + if (forward.length2() < SIMD_EPSILON) + { + forward.setValue(1.f,0.f,0.f); + } + btVector3 right = m_cameraUp.cross(forward); + btQuaternion roll(right,-rele); + + eyePos = btMatrix3x3(rot) * btMatrix3x3(roll) * eyePos; + + m_cameraPosition[0] = eyePos.getX(); + m_cameraPosition[1] = eyePos.getY(); + m_cameraPosition[2] = eyePos.getZ(); + m_cameraPosition += m_cameraTargetPosition; + + + float m_frustumZNear=1; + float m_frustumZFar=1000; + + if (m_glutScreenWidth == 0 && m_glutScreenHeight == 0) + return; + + float aspect; + btVector3 extents; + + if (m_glutScreenWidth > m_glutScreenHeight) + { + aspect = m_glutScreenWidth / (float)m_glutScreenHeight; + extents.setValue(aspect * 1.0f, 1.0f,0); + } else + { + aspect = m_glutScreenHeight / (float)m_glutScreenWidth; + extents.setValue(1.0f, aspect*1.f,0); + } + + + if (m_ortho) + { + // reset matrix + glLoadIdentity(); + extents *= m_cameraDistance; + btVector3 lower = m_cameraTargetPosition - extents; + btVector3 upper = m_cameraTargetPosition + extents; + glOrtho(lower.getX(), upper.getX(), lower.getY(), upper.getY(),-1000,1000); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + } else + { + if (m_glutScreenWidth > m_glutScreenHeight) + { + glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar); + } else + { + glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar); + } + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(m_cameraPosition[0], m_cameraPosition[1], m_cameraPosition[2], + m_cameraTargetPosition[0], m_cameraTargetPosition[1], m_cameraTargetPosition[2], + m_cameraUp.getX(),m_cameraUp.getY(),m_cameraUp.getZ()); + } + +} + + +void GLInstancingRenderer::RenderScene(void) +{ + BT_PROFILE("GlutDisplayFunc"); + + myinit(); + + updateCamera(); + + //render coordinate system + glBegin(GL_LINES); + glColor3f(1,0,0); + glVertex3f(0,0,0); + glVertex3f(1,0,0); + glColor3f(0,1,0); + glVertex3f(0,0,0); + glVertex3f(0,1,0); + glColor3f(0,0,1); + glVertex3f(0,0,0); + glVertex3f(0,0,1); + glEnd(); + + //do a finish, to make sure timings are clean + // glFinish(); + + + + // glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, cube_vbo); + glFlush(); + + //updatePos(); + +// simulationLoop(); + + //useCPU = true; + + int totalNumInstances = 0; + + for (int i=0;im_numGraphicsInstances; + } + + int curOffset = 0; + + for (int i=0;im_instanceOffset*4*sizeof(float); + + int POSITION_BUFFER_SIZE = (totalNumInstances*sizeof(float)*4); + int ORIENTATION_BUFFER_SIZE = (totalNumInstances*sizeof(float)*4); + int COLOR_BUFFER_SIZE = (totalNumInstances*sizeof(float)*4); + int SCALE_BUFFER_SIZE = (totalNumInstances*sizeof(float)*3); + + glBindVertexArray(gfxObj->m_cube_vao); + + + int vertexStride = 9*sizeof(float); + int vertexBase = gfxObj->m_vertexArrayOffset*vertexStride; + + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid*)vertexBase); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(curOffset*4*sizeof(float)+SHAPE_BUFFER_SIZE)); + glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(curOffset*4*sizeof(float)+SHAPE_BUFFER_SIZE+POSITION_BUFFER_SIZE)); + int uvoffset = 7*sizeof(float)+vertexBase; + int normaloffset = 4*sizeof(float)+vertexBase; + + glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid *)uvoffset); + glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid *)normaloffset); + glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(curOffset*4*sizeof(float)+SHAPE_BUFFER_SIZE+POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE)); + glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(curOffset*3*sizeof(float)+SHAPE_BUFFER_SIZE+POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE+COLOR_BUFFER_SIZE)); + + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glEnableVertexAttribArray(2); + glEnableVertexAttribArray(3); + glEnableVertexAttribArray(4); + glEnableVertexAttribArray(5); + glEnableVertexAttribArray(6); + + glVertexAttribDivisor(0, 0); + glVertexAttribDivisor(1, 1); + glVertexAttribDivisor(2, 1); + glVertexAttribDivisor(3, 0); + glVertexAttribDivisor(4, 0); + glVertexAttribDivisor(5, 1); + glVertexAttribDivisor(6, 1); + + glUseProgram(instancingShader); + glUniform1f(angle_loc, 0); + GLfloat pm[16]; + glGetFloatv(GL_PROJECTION_MATRIX, pm); + glUniformMatrix4fv(ProjectionMatrix, 1, false, &pm[0]); + + GLfloat mvm[16]; + glGetFloatv(GL_MODELVIEW_MATRIX, mvm); + glUniformMatrix4fv(ModelViewMatrix, 1, false, &mvm[0]); + + glUniform1i(uniform_texture_diffuse, 0); + + glFlush(); + + if (gfxObj->m_numGraphicsInstances) + { + int indexCount = gfxObj->m_numIndices; + int indexOffset = 0; + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gfxObj->m_index_vbo); + { + BT_PROFILE("glDrawElementsInstanced"); + glDrawElementsInstanced(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, (void*)indexOffset, gfxObj->m_numGraphicsInstances); + } + } + curOffset+= gfxObj->m_numGraphicsInstances; + } + glUseProgram(0); + glBindBuffer(GL_ARRAY_BUFFER,0); + glBindVertexArray(0); + + + GLint err = glGetError(); + assert(err==GL_NO_ERROR); +} + + +void GLInstancingRenderer::CleanupShaders() +{ + + delete []m_data->m_instance_positions_ptr; + delete []m_data->m_instance_quaternion_ptr; + delete []m_data->m_instance_colors_ptr; + delete []m_data->m_instance_scale_ptr; +} \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/GLInstancingRenderer.h b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/GLInstancingRenderer.h new file mode 100644 index 0000000..b592438 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/GLInstancingRenderer.h @@ -0,0 +1,45 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + +#ifndef GL_INSTANCING_RENDERER_H +#define GL_INSTANCING_RENDERER_H + +#include "LinearMath/btAlignedObjectArray.h" + +class GLInstancingRenderer +{ + + btAlignedObjectArray m_graphicsInstances; + + struct InternalDataRenderer* m_data; + +public: + GLInstancingRenderer(); + virtual ~GLInstancingRenderer(); + + void InitShaders(); + void RenderScene(void); + void CleanupShaders(); + + ///vertices must be in the format x,y,z, nx,ny,nz, u,v + int registerShape(const float* vertices, int numvertices, const int* indices, int numIndices); + + ///position x,y,z, quaternion x,y,z,w, color r,g,b,a, scaling x,y,z + int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling); + + void writeTransforms(); +}; + +#endif //GL_INSTANCING_RENDERER_H diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/GlutRenderer.cpp b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/GlutRenderer.cpp new file mode 100644 index 0000000..3cb02c2 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/GlutRenderer.cpp @@ -0,0 +1,107 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + + +#include +#include "GlutRenderer.h" +#include + + +GlutRenderer* GlutRenderer::gDemoApplication; + + + +void GlutRenderer::runMainLoop() +{ + glutMainLoop(); + +} + + +static void glutKeyboardCallback(unsigned char key, int x, int y) { GlutRenderer::gDemoApplication->keyboardCallback(key,x,y); } +static void glutKeyboardUpCallback(unsigned char key, int x, int y){ GlutRenderer::gDemoApplication->keyboardUpCallback(key,x,y);} +static void glutSpecialKeyboardCallback(int key, int x, int y){ GlutRenderer::gDemoApplication->specialKeyboard(key,x,y);} +static void glutSpecialKeyboardUpCallback(int key, int x, int y){ GlutRenderer::gDemoApplication->specialKeyboardUp(key,x,y);} +static void glutReshapeCallback(int w, int h){ GlutRenderer::gDemoApplication->resize(w,h);} +static void glutIdleCallback(){ glutPostRedisplay (); } +static void glutMouseFuncCallback(int button, int state, int x, int y){ GlutRenderer::gDemoApplication->mouseFunc(button,state,x,y);} +static void glutMotionFuncCallback(int x,int y){ GlutRenderer::gDemoApplication->mouseMotionFunc(x,y);} +static void glutDisplayCallback(void){ GlutRenderer::gDemoApplication->displayCallback();} + + +void GlutRenderer::resize(int width, int height) +{ + m_glutScreenWidth = width; + m_glutScreenHeight = height; +} + +void GlutRenderer::mouseFunc(int button, int state, int x, int y) +{ +} +void GlutRenderer::mouseMotionFunc(int x,int y) +{ +} + +void GlutRenderer::renderScene() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glutSwapBuffers(); + glutPostRedisplay(); + + GLint err = glGetError(); + assert(err==GL_NO_ERROR); +} + +void GlutRenderer::displayCallback() +{ + updateScene(); + + renderScene(); +} + +GlutRenderer::GlutRenderer(int argc, char* argv[]) +{ + glutInit(&argc, argv); + gDemoApplication = this; +} + +void GlutRenderer::initGraphics(int width, int height) +{ + m_glutScreenWidth = width; + m_glutScreenHeight = height; + + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); + + glutInitWindowSize(m_glutScreenWidth, m_glutScreenHeight); + glutCreateWindow("GPU rigid body pipeline2"); + glutKeyboardFunc(glutKeyboardCallback); + glutKeyboardUpFunc(glutKeyboardUpCallback); + glutSpecialFunc(glutSpecialKeyboardCallback); + glutSpecialUpFunc(glutSpecialKeyboardUpCallback); + glutReshapeFunc(glutReshapeCallback); + glutIdleFunc(glutIdleCallback); + glutMouseFunc(glutMouseFuncCallback); + glutPassiveMotionFunc(glutMotionFuncCallback); + glutMotionFunc(glutMotionFuncCallback); + glutDisplayFunc( glutDisplayCallback ); + + GLenum err = glewInit(); + if (GLEW_OK != err) + { + printf("Error: %s\n", glewGetErrorString(err)); + } + + glClearColor(0.6f,0.6f,1.f,1.f); +} \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/GlutRenderer.h b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/GlutRenderer.h new file mode 100644 index 0000000..3596ad4 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/GlutRenderer.h @@ -0,0 +1,59 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + +#ifndef GLUT_RENDERER_H +#define GLUT_RENDERER_H + +#include "btGlutInclude.h" +#include "LinearMath/btVector3.h" + +struct GlutRenderer +{ + static GlutRenderer* gDemoApplication; + int m_glutScreenWidth; + int m_glutScreenHeight; + + btVector3 m_cameraPosition; + btVector3 m_cameraTargetPosition; + btScalar m_cameraDistance; + btVector3 m_cameraUp; + float m_azimuth; + float m_elevation; + + + GlutRenderer(int argc, char* argv[]); + + virtual void initGraphics(int width, int height); + virtual void cleanup() {} + + void runMainLoop(); + + virtual void updateScene(){}; + + virtual void renderScene(); + + virtual void keyboardCallback(unsigned char key, int x, int y) {}; + virtual void keyboardUpCallback(unsigned char key, int x, int y) {} + virtual void specialKeyboard(int key, int x, int y){} + virtual void specialKeyboardUp(int key, int x, int y){} + virtual void resize(int w, int h); + virtual void mouseFunc(int button, int state, int x, int y); + virtual void mouseMotionFunc(int x,int y); + virtual void displayCallback(); + + +}; + +#endif //GLUT_RENDERER_H diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/NVIDIA/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/NVIDIA/premake4.lua new file mode 100644 index 0000000..8ccc57e --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/NVIDIA/premake4.lua @@ -0,0 +1,64 @@ + + hasCL = findOpenCL_NVIDIA() + + if (hasCL) then + + project "OpenCL_gpu_rigidbody_pipeline2_NVIDIA" + + initOpenCL_NVIDIA() + + language "C++" + + kind "ConsoleApp" + targetdir "../../../bin" + + initOpenGL() + initGlew() + + + includedirs { + "../../primitives", + "../../../bullet2" + } + + files { + "../main.cpp", + "../CLPhysicsDemo.cpp", + "../CLPhysicsDemo.h", + "../GLInstancingRenderer.cpp", + "../GLInstancingRenderer.h", + "../GlutRenderer.cpp", + "../GlutRenderer.h", + "../Win32OpenGLRenderManager.cpp", + "../Win32OpenGLRenderManager.h", + "../../gpu_rigidbody_pipeline/btConvexUtility.cpp", + "../../gpu_rigidbody_pipeline/btConvexUtility.h", + "../../gpu_rigidbody_pipeline/btGpuNarrowPhaseAndSolver.cpp", + "../../gpu_rigidbody_pipeline/btGpuNarrowPhaseAndSolver.h", + "../../../dynamics/basic_demo/ConvexHeightFieldShape.cpp", + "../../../dynamics/basic_demo/ConvexHeightFieldShape.h", + "../../../bullet2/LinearMath/btConvexHullComputer.cpp", + "../../../bullet2/LinearMath/btConvexHullComputer.h", + "../../broadphase_benchmark/findPairsOpenCL.cpp", + "../../broadphase_benchmark/findPairsOpenCL.h", + "../../broadphase_benchmark/btGridBroadphaseCL.cpp", + "../../broadphase_benchmark/btGridBroadphaseCL.h", + "../../3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.cpp", + "../../3dGridBroadphase/Shared/bt3dGridBroadphaseOCL.h", + "../../3dGridBroadphase/Shared/btGpu3DGridBroadphase.cpp", + "../../3dGridBroadphase/Shared/btGpu3DGridBroadphase.h", + "../../../bullet2/LinearMath/btAlignedAllocator.cpp", + "../../../bullet2/LinearMath/btQuickprof.cpp", + "../../../bullet2/LinearMath/btQuickprof.h", + "../../../bullet2/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp", + "../../../bullet2/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp", + "../../../bullet2/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp", + "../../basic_initialize/btOpenCLUtils.cpp", + "../../basic_initialize/btOpenCLUtils.h", + "../../opengl_interop/btOpenCLGLInteropBuffer.cpp", + "../../opengl_interop/btOpenCLGLInteropBuffer.h", + "../../opengl_interop/btStopwatch.cpp", + "../../opengl_interop/btStopwatch.h" + } + + end diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/OpenGLInclude.h b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/OpenGLInclude.h new file mode 100644 index 0000000..2b3060b --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/OpenGLInclude.h @@ -0,0 +1,41 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + + +#ifndef __OPENGL_INCLUDE_H +#define __OPENGL_INCLUDE_H + +#include + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#else + + +#ifdef _WINDOWS +#include +#include +#include +#else +#include + +#endif //_WINDOWS +#endif //APPLE + +#endif //__OPENGL_INCLUDE_H + diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/ShapeData.h b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/ShapeData.h new file mode 100644 index 0000000..e77affe --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/ShapeData.h @@ -0,0 +1,210 @@ +#ifndef SHAPE_DATA_H +#define SHAPE_DATA_H + +static float barrel_vertices[] = { +0.0f,-0.5f,0.0f, 1.0f, 0.0f,-1.0f,0.0f, 0.5f, 0.5f, +0.282362f,-0.5f,-0.205148f, 1.0f, 0.0f,-1.0f,0.0f, 0.5f, 0.5f, +0.349018f,-0.5f,0.0f, 1.0f, 0.0f,-1.0f,0.0f, 0.5f, 0.5f, +0.107853f,-0.5f,-0.331936f, 1.0f, 0.0f,-1.0f,0.0f, 0.5f, 0.5f, +-0.107853f,-0.5f,-0.331936f, 1.0f, 0.0f,-1.0f,0.0f, 0.5f, 0.5f, +0.107853f,-0.5f,-0.331936f, 1.0f, 0.0f,-1.0f,0.0f, 0.5f, 0.5f, +-0.282362f,-0.5f,-0.205148f, 1.0f, 0.0f,-1.0f,0.0f, 0.5f, 0.5f, +-0.349018f,-0.5f,0.0f, 1.0f, 0.0f,-1.0f,0.0f, 0.5f, 0.5f, +-0.282362f,-0.5f,0.205148f, 1.0f, 0.0f,-1.0f,0.0f, 0.5f, 0.5f, +-0.107853f,-0.5f,0.331936f, 1.0f, 0.0f,-1.0f,0.0f, 0.5f, 0.5f, +0.107853f,-0.5f,0.331936f, 1.0f, 0.0f,-1.0f,0.0f, 0.5f, 0.5f, +0.282362f,-0.5f,0.205148f, 1.0f, 0.0f,-1.0f,0.0f, 0.5f, 0.5f, +0.0f,0.5f,0.0f, 1.0f, 0.0f,1.0f,0.0f, 0.5f, 0.5f, +0.349018f,0.5f,0.0f, 1.0f, 0.0f,1.0f,0.0f, 0.5f, 0.5f, +0.282362f,0.5f,-0.205148f, 1.0f, 0.0f,1.0f,0.0f, 0.5f, 0.5f, +0.107853f,0.5f,-0.331936f, 1.0f, 0.0f,1.0f,0.0f, 0.5f, 0.5f, +0.107853f,0.5f,-0.331936f, 1.0f, 0.0f,1.0f,0.0f, 0.5f, 0.5f, +-0.107853f,0.5f,-0.331936f, 1.0f, 0.0f,1.0f,0.0f, 0.5f, 0.5f, +-0.282362f,0.5f,-0.205148f, 1.0f, 0.0f,1.0f,0.0f, 0.5f, 0.5f, +-0.349018f,0.5f,0.0f, 1.0f, 0.0f,1.0f,0.0f, 0.5f, 0.5f, +-0.282362f,0.5f,0.205148f, 1.0f, 0.0f,1.0f,0.0f, 0.5f, 0.5f, +-0.107853f,0.5f,0.331936f, 1.0f, 0.0f,1.0f,0.0f, 0.5f, 0.5f, +0.107853f,0.5f,0.331936f, 1.0f, 0.0f,1.0f,0.0f, 0.5f, 0.5f, +0.282362f,0.5f,0.205148f, 1.0f, 0.0f,1.0f,0.0f, 0.5f, 0.5f, +0.349018f,-0.5f,0.0f, 1.0f, 0.957307f,-0.289072f,0.0f, 0.5f, 0.5f, +0.404509f,0.0f,-0.293893f, 1.0f, 0.809017f,0.0f,-0.587785f, 0.5f, 0.5f, +0.5f,0.0f,0.0f, 1.0f, 1.0f,0.0f,0.0f, 0.5f, 0.5f, +0.282362f,-0.5f,-0.205148f, 1.0f, 0.774478f,-0.289072f,-0.562691f, 0.5f, 0.5f, +0.154508f,0.0f,-0.475528f, 1.0f, 0.309017f,0.0f,-0.951057f, 0.5f, 0.5f, +0.107853f,-0.5f,-0.331936f, 1.0f, 0.295824f,-0.289072f,-0.910453f, 0.5f, 0.5f, +0.107853f,-0.5f,-0.331936f, 1.0f, 0.295824f,-0.289072f,-0.910453f, 0.5f, 0.5f, +-0.154509f,0.0f,-0.475528f, 1.0f, -0.309017f,0.0f,-0.951057f, 0.5f, 0.5f, +0.154508f,0.0f,-0.475528f, 1.0f, 0.309017f,0.0f,-0.951057f, 0.5f, 0.5f, +-0.107853f,-0.5f,-0.331936f, 1.0f, -0.295824f,-0.289072f,-0.910453f, 0.5f, 0.5f, +-0.404509f,0.0f,-0.293893f, 1.0f, -0.809017f,0.0f,-0.587785f, 0.5f, 0.5f, +-0.282362f,-0.5f,-0.205148f, 1.0f, -0.774478f,-0.289072f,-0.562691f, 0.5f, 0.5f, +-0.5f,0.0f,0.0f, 1.0f, -1.0f,0.0f,0.0f, 0.5f, 0.5f, +-0.349018f,-0.5f,0.0f, 1.0f, -0.957307f,-0.289072f,0.0f, 0.5f, 0.5f, +-0.404508f,0.0f,0.293893f, 1.0f, -0.809017f,0.0f,0.587785f, 0.5f, 0.5f, +-0.282362f,-0.5f,0.205148f, 1.0f, -0.774478f,-0.289072f,0.562691f, 0.5f, 0.5f, +-0.154509f,0.0f,0.475528f, 1.0f, -0.309017f,0.0f,0.951056f, 0.5f, 0.5f, +-0.107853f,-0.5f,0.331936f, 1.0f, -0.295824f,-0.289072f,0.910453f, 0.5f, 0.5f, +0.154509f,0.0f,0.475528f, 1.0f, 0.309017f,0.0f,0.951056f, 0.5f, 0.5f, +0.107853f,-0.5f,0.331936f, 1.0f, 0.295824f,-0.289072f,0.910453f, 0.5f, 0.5f, +0.404509f,0.0f,0.293892f, 1.0f, 0.809017f,0.0f,0.587785f, 0.5f, 0.5f, +0.282362f,-0.5f,0.205148f, 1.0f, 0.774478f,-0.289072f,0.562691f, 0.5f, 0.5f, +0.282362f,0.5f,-0.205148f, 1.0f, 0.774478f,0.289072f,-0.562691f, 0.5f, 0.5f, +0.349018f,0.5f,0.0f, 1.0f, 0.957307f,0.289072f,0.0f, 0.5f, 0.5f, +0.107853f,0.5f,-0.331936f, 1.0f, 0.295824f,0.289072f,-0.910453f, 0.5f, 0.5f, +-0.107853f,0.5f,-0.331936f, 1.0f, -0.295824f,0.289072f,-0.910453f, 0.5f, 0.5f, +0.107853f,0.5f,-0.331936f, 1.0f, 0.295824f,0.289072f,-0.910453f, 0.5f, 0.5f, +-0.282362f,0.5f,-0.205148f, 1.0f, -0.774478f,0.289072f,-0.562691f, 0.5f, 0.5f, +-0.349018f,0.5f,0.0f, 1.0f, -0.957307f,0.289072f,0.0f, 0.5f, 0.5f, +-0.282362f,0.5f,0.205148f, 1.0f, -0.774478f,0.289072f,0.562691f, 0.5f, 0.5f, +-0.107853f,0.5f,0.331936f, 1.0f, -0.295824f,0.289072f,0.910453f, 0.5f, 0.5f, +0.107853f,0.5f,0.331936f, 1.0f, 0.295824f,0.289072f,0.910453f, 0.5f, 0.5f, +0.282362f,0.5f,0.205148f, 1.0f, 0.774478f,0.289072f,0.562691f, 0.5f, 0.5f +}; + + + +static int barrel_indices[] = { +0,1,2, +0,3,1, +0,4,5, +0,6,4, +0,7,6, +0,8,7, +0,9,8, +0,10,9, +0,11,10, +0,2,11, +12,13,14, +12,14,15, +12,16,17, +12,17,18, +12,18,19, +12,19,20, +12,20,21, +12,21,22, +12,22,23, +12,23,13, +24,25,26, +24,27,25, +27,28,25, +27,29,28, +30,31,32, +30,33,31, +33,34,31, +33,35,34, +35,36,34, +35,37,36, +37,38,36, +37,39,38, +39,40,38, +39,41,40, +41,42,40, +41,43,42, +43,44,42, +43,45,44, +45,26,44, +45,24,26, +26,46,47, +26,25,46, +25,48,46, +25,28,48, +32,49,50, +32,31,49, +31,51,49, +31,34,51, +34,52,51, +34,36,52, +36,53,52, +36,38,53, +38,54,53, +38,40,54, +40,55,54, +40,42,55, +42,56,55, +42,44,56, +44,47,56, +44,26,47, +}; + + +///position xyz, unused w, normal, uv +static const float cube_vertices[] = +{ + -0.5f, -0.5f, 0.5f, 0.0f, 0,0,1, 0,0,//0 + 0.5f, -0.5f, 0.5f, 0.0f, 0,0,1, 1,0,//1 + 0.5f, 0.5f, 0.5f, 0.0f, 0,0,1, 1,1,//2 + -0.5f, 0.5f, 0.5f, 0.0f, 0,0,1, 0,1 ,//3 + + -0.5f, -0.5f, -0.5f, 0.5f, 0,0,-1, 0,0,//4 + 0.5f, -0.5f, -0.5f, 0.5f, 0,0,-1, 1,0,//5 + 0.5f, 0.5f, -0.5f, 0.5f, 0,0,-1, 1,1,//6 + -0.5f, 0.5f, -0.5f, 0.5f, 0,0,-1, 0,1,//7 + + -0.5f, -0.5f, -0.5f, 0.5f, -1,0,0, 0,0, + -0.5f, 0.5f, -0.5f, 0.5f, -1,0,0, 1,0, + -0.5f, 0.5f, 0.5f, 0.5f, -1,0,0, 1,1, + -0.5f, -0.5f, 0.5f, 0.5f, -1,0,0, 0,1, + + 0.5f, -0.5f, -0.5f, 0.5f, 1,0,0, 0,0, + 0.5f, 0.5f, -0.5f, 0.5f, 1,0,0, 1,0, + 0.5f, 0.5f, 0.5f, 0.5f, 1,0,0, 1,1, + 0.5f, -0.5f, 0.5f, 0.5f, 1,0,0, 0,1, + + -0.5f, -0.5f, -0.5f, 0.5f, 0,-1,0, 0,0, + -0.5f, -0.5f, 0.5f, 0.5f, 0,-1,0, 1,0, + 0.5f, -0.5f, 0.5f, 0.5f, 0,-1,0, 1,1, + 0.5f,-0.5f, -0.5f, 0.5f, 0,-1,0, 0,1, + + -0.5f, 0.5f, -0.5f, 0.5f, 0,1,0, 0,0, + -0.5f, 0.5f, 0.5f, 0.5f, 0,1,0, 1,0, + 0.5f, 0.5f, 0.5f, 0.5f, 0,1,0, 1,1, + 0.5f,0.5f, -0.5f, 0.5f, 0,1,0, 0,1, +}; + + +///position xyz, unused w, normal, uv +static const float cube_vertices2[] = +{ + -1.5f, -0.5f, 0.5f, 0.0f, 0,0,1, 0,0,//0 + 1.5f, -0.5f, 0.5f, 0.0f, 0,0,1, 1,0,//1 + 1.5f, 0.5f, 0.5f, 0.0f, 0,0,1, 1,1,//2 + -1.5f, 0.5f, 0.5f, 0.0f, 0,0,1, 0,1 ,//3 + + -1.5f, -0.5f, -0.5f, 0.5f, 0,0,-1, 0,0,//4 + 1.5f, -0.5f, -0.5f, 0.5f, 0,0,-1, 1,0,//5 + 1.5f, 0.5f, -0.5f, 0.5f, 0,0,-1, 1,1,//6 + -1.5f, 0.5f, -0.5f, 0.5f, 0,0,-1, 0,1,//7 + + -1.5f, -0.5f, -0.5f, 0.5f, -1,0,0, 0,0, + -1.5f, 0.5f, -0.5f, 0.5f, -1,0,0, 1,0, + -1.5f, 0.5f, 0.5f, 0.5f, -1,0,0, 1,1, + -1.5f, -0.5f, 0.5f, 0.5f, -1,0,0, 0,1, + + 1.5f, -0.5f, -0.5f, 0.5f, 1,0,0, 0,0, + 1.5f, 0.5f, -0.5f, 0.5f, 1,0,0, 1,0, + 1.5f, 0.5f, 0.5f, 0.5f, 1,0,0, 1,1, + 1.5f, -0.5f, 0.5f, 0.5f, 1,0,0, 0,1, + + -1.5f, -0.5f, -0.5f, 0.5f, 0,-1,0, 0,0, + -1.5f, -0.5f, 0.5f, 0.5f, 0,-1,0, 1,0, + 1.5f, -0.5f, 0.5f, 0.5f, 0,-1,0, 1,1, + 1.5f, -0.5f, -0.5f, 0.5f, 0,-1,0, 0,1, + + -1.5f, 0.5f, -0.5f, 0.5f, 0,1,0, 0,0, + -1.5f, 0.5f, 0.5f, 0.5f, 0,1,0, 1,0, + 1.5f, 0.5f, 0.5f, 0.5f, 0,1,0, 1,1, + 1.5f, 0.5f, -0.5f, 0.5f, 0,1,0, 0,1, +}; + + +static const int cube_indices[]= +{ + 0,1,2,0,2,3,//ground face + 4,5,6,4,6,7,//top face + 8,9,10,8,10,11, + 12,13,14,12,14,15, + 16,17,18,16,18,19, + 20,21,22,20,22,23 +}; + +#endif //SHAPE_DATA_H diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/Win32OpenGLRenderManager.cpp b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/Win32OpenGLRenderManager.cpp new file mode 100644 index 0000000..c3b9f25 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/Win32OpenGLRenderManager.cpp @@ -0,0 +1,465 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + + +#include "Win32OpenGLRenderManager.h" + +#include +#include + +static InternalData2* sData = 0; + +struct InternalData2 +{ + HWND m_hWnd;; + int m_width; + int m_height; + HDC m_hDC; + HGLRC m_hRC; + bool m_OpenGLInitialized; + int m_oldScreenWidth; + int m_oldHeight; + int m_oldBitsPerPel; + bool m_quit; + + + InternalData2() + { + m_hWnd = 0; + m_width = 0; + m_height = 0; + m_hDC = 0; + m_hRC = 0; + m_OpenGLInitialized = false; + m_oldScreenWidth = 0; + m_oldHeight = 0; + m_oldBitsPerPel = 0; + m_quit = false; + } +}; + + +void Win32OpenGLWindow::enableOpenGL() +{ + + + + PIXELFORMATDESCRIPTOR pfd; + int format; + + // get the device context (DC) + m_data->m_hDC = GetDC( m_data->m_hWnd ); + + // set the pixel format for the DC + ZeroMemory( &pfd, sizeof( pfd ) ); + pfd.nSize = sizeof( pfd ); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 24; + pfd.cDepthBits = 16; + pfd.cStencilBits = 1; + pfd.iLayerType = PFD_MAIN_PLANE; + format = ChoosePixelFormat( m_data->m_hDC, &pfd ); + SetPixelFormat( m_data->m_hDC, format, &pfd ); + + // create and enable the render context (RC) + m_data->m_hRC = wglCreateContext( m_data->m_hDC ); + wglMakeCurrent( m_data->m_hDC, m_data->m_hRC ); + m_data->m_OpenGLInitialized = true; + + +} + + +void Win32OpenGLWindow::disableOpenGL() +{ + m_data->m_OpenGLInitialized = false; + + wglMakeCurrent( NULL, NULL ); + wglDeleteContext( m_data->m_hRC ); + ReleaseDC( m_data->m_hWnd, m_data->m_hDC ); +} + +void Win32OpenGLWindow::pumpMessage() +{ + MSG msg; + // check for messages + if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) + { + + // handle or dispatch messages + if ( msg.message == WM_QUIT ) + { + m_data->m_quit = TRUE; + } + else + { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + +// gDemoApplication->displayCallback(); + + + }; +} + + + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint(hWnd, &ps); + EndPaint(hWnd, &ps); + } + return 0; + + case WM_ERASEBKGND: + return 0; + + case WM_DESTROY: + PostQuitMessage(0); + return 0; + + case WM_KEYDOWN: + { + switch ( wParam ) + { + case 'Q': + case VK_ESCAPE: + { + PostQuitMessage(0); + } + return 0; + } + break; + } + + case WM_SIZE: // Size Action Has Taken Place + + switch (wParam) // Evaluate Size Action + { + case SIZE_MINIMIZED: // Was Window Minimized? + return 0; // Return + + case SIZE_MAXIMIZED: // Was Window Maximized? + + sData->m_width = LOWORD (lParam); + sData->m_height = HIWORD (lParam); + //if (sOpenGLInitialized) + //{ + // //gDemoApplication->reshape(sWidth,sHeight); + //} + glViewport(0, 0, sData->m_width, sData->m_height); + return 0; // Return + + case SIZE_RESTORED: // Was Window Restored? + sData->m_width = LOWORD (lParam); + sData->m_height = HIWORD (lParam); + //if (sOpenGLInitialized) + //{ + // gDemoApplication->reshape(sWidth,sHeight); + //} + glViewport(0, 0, sData->m_width, sData->m_height); + return 0; // Return + } + break; + + default:{ + + } + }; + + return DefWindowProc(hWnd, message, wParam, lParam); +} + + + + +void Win32OpenGLWindow::init(int width,int height, bool fullscreen,int colorBitsPerPixel, void* windowHandle) +{ + // get handle to exe file + HINSTANCE hInstance = GetModuleHandle(0); + + // create the window if we need to and we do not use the null device + if (!windowHandle) + { + const char* ClassName = "DeviceWin32"; + + // Register Class + WNDCLASSEX wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon( NULL, IDI_APPLICATION ); //(HICON)LoadImage(hInstance, "bullet_ico.ico", IMAGE_ICON, 0,0, LR_LOADTRANSPARENT);//LR_LOADFROMFILE); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = 0; + wcex.lpszClassName = ClassName; + wcex.hIconSm = 0; + + // if there is an icon, load it + wcex.hIcon = (HICON)LoadImage(hInstance, "irrlicht.ico", IMAGE_ICON, 0,0, LR_LOADFROMFILE); + + RegisterClassEx(&wcex); + + // calculate client size + + RECT clientSize; + clientSize.top = 0; + clientSize.left = 0; + clientSize.right = width; + clientSize.bottom = height; + + DWORD style = WS_POPUP; + + if (!fullscreen) + style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX; + + AdjustWindowRect(&clientSize, style, FALSE); + + m_data->m_width = clientSize.right - clientSize.left; + m_data->m_height = clientSize.bottom - clientSize.top; + + int windowLeft = (GetSystemMetrics(SM_CXSCREEN) - m_data->m_width) / 2; + int windowTop = (GetSystemMetrics(SM_CYSCREEN) - m_data->m_height) / 2; + + if (fullscreen) + { + windowLeft = 0; + windowTop = 0; + } + + // create window + + m_data->m_hWnd = CreateWindow( ClassName, "", style, windowLeft, windowTop, + m_data->m_width, m_data->m_height, NULL, NULL, hInstance, NULL); + + ShowWindow(m_data->m_hWnd, SW_SHOW); + UpdateWindow(m_data->m_hWnd); + + MoveWindow(m_data->m_hWnd, windowLeft, windowTop, m_data->m_width, m_data->m_height, TRUE); + } + else if (windowHandle) + { + // attach external window + m_data->m_hWnd = static_cast(windowHandle); + RECT r; + GetWindowRect(m_data->m_hWnd, &r); + m_data->m_width = r.right - r.left; + m_data->m_height = r.bottom - r.top; + //sFullScreen = false; + //sExternalWindow = true; + } + + + if (fullscreen) + { + DEVMODE dm; + memset(&dm, 0, sizeof(dm)); + dm.dmSize = sizeof(dm); + // use default values from current setting + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm); + m_data->m_oldScreenWidth = dm.dmPelsWidth; + m_data->m_oldHeight = dm.dmPelsHeight; + m_data->m_oldBitsPerPel = dm.dmBitsPerPel; + + dm.dmPelsWidth = width; + dm.dmPelsHeight = height; + if (colorBitsPerPixel) + { + dm.dmBitsPerPel = colorBitsPerPixel; + } + dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; + + LONG res = ChangeDisplaySettings(&dm, CDS_FULLSCREEN); + if (res != DISP_CHANGE_SUCCESSFUL) + { // try again without forcing display frequency + dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + res = ChangeDisplaySettings(&dm, CDS_FULLSCREEN); + } + + } + + //VideoDriver = video::createOpenGLDriver(CreationParams, FileSystem, this); + enableOpenGL(); + + + const wchar_t* text= L"OpenCL rigid body demo"; + + DWORD dwResult; + +#ifdef _WIN64 + SetWindowTextW(m_data->m_hWnd, text); +#else + SendMessageTimeoutW(m_data->m_hWnd, WM_SETTEXT, 0, + reinterpret_cast(text), + SMTO_ABORTIFHUNG, 2000, &dwResult); +#endif + + +} + + +void Win32OpenGLWindow::switchFullScreen(bool fullscreen,int width,int height,int colorBitsPerPixel) +{ + LONG res; + DEVMODE dm; + memset(&dm, 0, sizeof(dm)); + dm.dmSize = sizeof(dm); + // use default values from current setting + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm); + + dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; + + if (fullscreen && !m_data->m_oldScreenWidth) + { + m_data->m_oldScreenWidth = dm.dmPelsWidth; + m_data->m_oldHeight = dm.dmPelsHeight; + m_data->m_oldBitsPerPel = dm.dmBitsPerPel; + + if (width && height) + { + dm.dmPelsWidth = width; + dm.dmPelsHeight = height; + } else + { + dm.dmPelsWidth = m_data->m_width; + dm.dmPelsHeight = m_data->m_height; + } + if (colorBitsPerPixel) + { + dm.dmBitsPerPel = colorBitsPerPixel; + } + } else + { + if (m_data->m_oldScreenWidth) + { + dm.dmPelsWidth = m_data->m_oldScreenWidth; + dm.dmPelsHeight= m_data->m_oldHeight; + dm.dmBitsPerPel = m_data->m_oldBitsPerPel; + } + } + + if (fullscreen) + { + res = ChangeDisplaySettings(&dm, CDS_FULLSCREEN); + } else + { + res = ChangeDisplaySettings(&dm, 0); + } +} + + + +Win32OpenGLWindow::Win32OpenGLWindow() +{ + m_data = new InternalData2(); + sData = m_data; +} + +Win32OpenGLWindow::~Win32OpenGLWindow() +{ + delete m_data; + sData = 0; +} + +void Win32OpenGLWindow::init() +{ + init(640,480,false); +} + + +void Win32OpenGLWindow::exit() +{ + disableOpenGL(); + DestroyWindow(this->m_data->m_hWnd); +} + + + + + +void Win32OpenGLWindow::startRendering() +{ + pumpMessage(); + + //glClearColor(1.f,0.f,0.f,1.f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); //clear buffers + + //glCullFace(GL_BACK); + //glFrontFace(GL_CCW); + glEnable(GL_DEPTH_TEST); + + + float aspect; + //btVector3 extents; + + if (m_data->m_width > m_data->m_height) + { + aspect = (float)m_data->m_width / (float)m_data->m_height; + //extents.setValue(aspect * 1.0f, 1.0f,0); + } else + { + aspect = (float)m_data->m_height / (float)m_data->m_width; + //extents.setValue(1.0f, aspect*1.f,0); + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + if (m_data->m_width > m_data->m_height) + { + glFrustum (-aspect, aspect, -1.0, 1.0, 1.0, 10000.0); + } else + { + glFrustum (-1.0, 1.0, -aspect, aspect, 1.0, 10000.0); + } + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + +} + + +void Win32OpenGLWindow::renderAllObjects() +{ +} + +void Win32OpenGLWindow::endRendering() +{ + SwapBuffers( m_data->m_hDC ); +} + +float Win32OpenGLWindow::getTimeInSeconds() +{ + return 0.f; +} + +void Win32OpenGLWindow::setDebugMessage(int x,int y,const char* message) +{ +} + +bool Win32OpenGLWindow::requestedExit() +{ + return m_data->m_quit; +} \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/Win32OpenGLRenderManager.h b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/Win32OpenGLRenderManager.h new file mode 100644 index 0000000..861c6f5 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/Win32OpenGLRenderManager.h @@ -0,0 +1,70 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + + +#ifndef _WIN32_OPENGL_RENDER_MANAGER_H +#define _WIN32_OPENGL_RENDER_MANAGER_H + + +#define RM_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name + +RM_DECLARE_HANDLE(RenderObjectHandle); + +struct InternalData2; + +class Win32OpenGLWindow +{ + protected: + + struct InternalData2* m_data; + + void enableOpenGL(); + + void disableOpenGL(); + + void pumpMessage(); + + + +public: + + Win32OpenGLWindow(); + + virtual ~Win32OpenGLWindow(); + + virtual void init(); //default implementation uses default settings for width/height/fullscreen + + void init(int width,int height, bool fullscreen=false, int colorBitsPerPixel=0, void* windowHandle=0); + + void switchFullScreen(bool fullscreen,int width=0,int height=0,int colorBitsPerPixel=0); + + virtual void exit(); + + + virtual void startRendering(); + + virtual void renderAllObjects(); + + virtual void endRendering(); + + virtual float getTimeInSeconds(); + + virtual void setDebugMessage(int x,int y,const char* message); + + virtual bool requestedExit(); + +}; + +#endif //_WIN32_OPENGL_RENDER_MANAGER_H diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/main.cpp b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/main.cpp new file mode 100644 index 0000000..b4de178 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/main.cpp @@ -0,0 +1,224 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Erwin Coumans + +// +//#include "vld.h" +#include + +#include "GLInstancingRenderer.h" + + +#include "GLInstancingRenderer.h" +#include "../opengl_interop/btOpenCLGLInteropBuffer.h" +#include "Win32OpenGLRenderManager.h" +#include "CLPhysicsDemo.h" +#include "../broadphase_benchmark/btGridBroadphaseCl.h" +#include "../../opencl/gpu_rigidbody_pipeline/btGpuNarrowPhaseAndSolver.h" +#include "ShapeData.h" +#include "LinearMath/btQuickprof.h" + +int NUM_OBJECTS_X = 32; +int NUM_OBJECTS_Y = 24; +int NUM_OBJECTS_Z = 32; + + +float X_GAP = 2.f; +float Y_GAP = 2.f; +float Z_GAP = 2.f; + +extern int numPairsOut; + + +void createScene(GLInstancingRenderer& renderer,CLPhysicsDemo& physicsSim) +{ + int strideInBytes = sizeof(float)*9; + + int barrelShapeIndex = -1; + int cubeShapeIndex = -1; + + float position[4]={0,0,0,0}; + float orn[4] = {0,0,0,1}; + float color[4] = {1,1,1,1}; + int index=0; +#if 1 + { + int numVertices = sizeof(barrel_vertices)/strideInBytes; + int numIndices = sizeof(barrel_indices)/sizeof(int); + barrelShapeIndex = renderer.registerShape(&barrel_vertices[0],numVertices,barrel_indices,numIndices); + } + + + float barrelScaling[4] = {2,2,2,1}; + + + int barrelCollisionShapeIndex = physicsSim.registerCollisionShape(&barrel_vertices[0],strideInBytes, sizeof(barrel_vertices)/strideInBytes,&barrelScaling[0]); + + + + for (int i=0;iinit(1024,768); + GLenum err = glewInit(); + window->startRendering(); + window->endRendering(); + + GLInstancingRenderer render; + + + + + + CLPhysicsDemo demo(window); + + bool useInterop = true; + demo.init(-1,-1,useInterop); + + render.InitShaders(); + + if (useInterop) + demo.setupInterop(); + + createScene(render, demo); + + + printf("num objects = %d\n", NUM_OBJECTS_X*NUM_OBJECTS_Y*NUM_OBJECTS_Z); + + + render.writeTransforms(); + + + while (!window->requestedExit()) + { + CProfileManager::Reset(); + + demo.stepSimulation(); + + + window->startRendering(); + render.RenderScene(); + window->endRendering(); + + CProfileManager::Increment_Frame_Counter(); + + static bool printStats = true; + + if (printStats) + { + static int count = 10; + count--; + if (count<0) + { + CProfileManager::dumpAll(); + //printf("total broadphase pairs= %d\n", gFpIO.m_numOverlap); + printf("numPairsOut (culled) = %d\n", numPairsOut); + printStats = false; + } + } + + } + + + demo.cleanup(); + + render.CleanupShaders(); + window->exit(); + delete window; + + + + return 0; +} \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/premake4.lua new file mode 100644 index 0000000..e78f276 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/gpu_rigidbody_pipeline2/premake4.lua @@ -0,0 +1,5 @@ + +include "AMD" +-- include "Intel" +-- include "NVIDIA" + \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/integration/AMD/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/integration/AMD/premake4.lua new file mode 100644 index 0000000..a8b029e --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/integration/AMD/premake4.lua @@ -0,0 +1,34 @@ + + hasCL = findOpenCL_AMD() + + if (hasCL) then + + project "OpenCL_integration_AMD" + + initOpenCL_AMD() + + language "C++" + + kind "ConsoleApp" + targetdir "../../../bin" + + initOpenGL() + initGlut() + initGlew() + + includedirs { + "../../../rendering/BulletMath", + "../../primitives" + } + + files { + "../main.cpp", + "../../basic_initialize/btOpenCLUtils.cpp", + "../../basic_initialize/btOpenCLUtils.h", + "../../opengl_interop/btOpenCLGLInteropBuffer.cpp", + "../../opengl_interop/btOpenCLGLInteropBuffer.h", + "../../opengl_interop/btStopwatch.cpp", + "../../opengl_interop/btStopwatch.h" + } + + end \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/integration/Intel/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/integration/Intel/premake4.lua new file mode 100644 index 0000000..27c0866 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/integration/Intel/premake4.lua @@ -0,0 +1,36 @@ + + hasCL = findOpenCL_Intel() + + if (hasCL) then + + project "OpenCL_integration_Intel" + + initOpenCL_Intel() + + language "C++" + + kind "ConsoleApp" + targetdir "../../../bin" + + + initOpenGL() + initGlut() + initGlew() + + + includedirs { + "../../../rendering/BulletMath", + "../../primitives" + } + + files { + "../main.cpp", + "../../basic_initialize/btOpenCLUtils.cpp", + "../../basic_initialize/btOpenCLUtils.h", + "../../opengl_interop/btOpenCLGLInteropBuffer.cpp", + "../../opengl_interop/btOpenCLGLInteropBuffer.h", + "../../opengl_interop/btStopwatch.cpp", + "../../opengl_interop/btStopwatch.h" + } + + end \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/integration/NVIDIA/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/integration/NVIDIA/premake4.lua new file mode 100644 index 0000000..b6b5272 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/integration/NVIDIA/premake4.lua @@ -0,0 +1,35 @@ + + hasCL = findOpenCL_NVIDIA() + + if (hasCL) then + + project "OpenCL_integration_NVIDIA" + + initOpenCL_NVIDIA() + + language "C++" + + kind "ConsoleApp" + targetdir "../../../bin" + + initOpenGL() + initGlut() + initGlew() + + + includedirs { + "../../../rendering/BulletMath", + "../../primitives" + } + + files { + "../main.cpp", + "../../basic_initialize/btOpenCLUtils.cpp", + "../../basic_initialize/btOpenCLUtils.h", + "../../opengl_interop/btOpenCLGLInteropBuffer.cpp", + "../../opengl_interop/btOpenCLGLInteropBuffer.h", + "../../opengl_interop/btStopwatch.cpp", + "../../opengl_interop/btStopwatch.h" + } + + end \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/integration/integrateKernel.cl b/Extras/RigidBodyGpuPipeline/opencl/integration/integrateKernel.cl new file mode 100644 index 0000000..fbb16be --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/integration/integrateKernel.cl @@ -0,0 +1,73 @@ +MSTRINGIFY( + +float4 quatMult(float4 q1, float4 q2) +{ + float4 q; + q.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y; + q.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z; + q.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x; + q.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z; + return q; +} + +float4 quatNorm(float4 q) +{ + float len = native_sqrt(dot(q, q)); + if(len > 0.f) + { + q *= 1.f / len; + } + else + { + q.x = q.y = q.z = 0.f; + q.w = 1.f; + } + return q; +} + + + +__kernel void + interopKernel( const int startOffset, const int numNodes, __global float4 *g_vertexBuffer, + __global float4 *linVel, + __global float4 *pAngVel) +{ + int nodeID = get_global_id(0); + float timeStep = 0.0166666; + + float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254); + + if( nodeID < numNodes ) + { + g_vertexBuffer[nodeID + startOffset/4] += linVel[nodeID]*timeStep; + + // g_vertexBuffer[nodeID + startOffset/4+numNodes] += angVel[nodeID]; + + float4 axis; + float4 angvel = pAngVel[nodeID]; + float fAngle = native_sqrt(dot(angvel, angvel)); + //limit the angular motion + if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD) + { + fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep; + } + if(fAngle < 0.001f) + { + // use Taylor's expansions of sync function + axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle); + } + else + { + // sync(fAngle) = sin(c*fAngle)/t + axis = angvel * ( native_sin(0.5f * fAngle * timeStep) / fAngle); + } + float4 dorn = axis; + dorn.w = native_cos(fAngle * timeStep * 0.5f); + float4 orn0 = g_vertexBuffer[nodeID + startOffset/4+numNodes]; + float4 predictedOrn = quatMult(dorn, orn0); + predictedOrn = quatNorm(predictedOrn); + g_vertexBuffer[nodeID + startOffset/4+numNodes]=predictedOrn; + } +} + +); \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/integration/main.cpp b/Extras/RigidBodyGpuPipeline/opencl/integration/main.cpp new file mode 100644 index 0000000..26e44b6 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/integration/main.cpp @@ -0,0 +1,1106 @@ + +//starts crashing when more than 32700 objects on my Geforce 260, unless _USE_SUB_DATA is defined (still unstable though) +//runs fine with fewer objects + +#define NUM_OBJECTS_X 327 +#define NUM_OBJECTS_Y 20 +#define NUM_OBJECTS_Z 20 +//#define NUM_OBJECTS_Z 20 + +//#define _USE_SUB_DATA + +//#define NUM_OBJECTS_X 100 +//#define NUM_OBJECTS_Y 100 +//#define NUM_OBJECTS_Z 100 + +///RECREATE_CL_AND_SHADERS_ON_RESIZE will delete and re-create OpenCL and GLSL shaders/buffers at each resize +//#define RECREATE_CL_AND_SHADERS_ON_RESIZE + +/// +/// OpenCL - OpenGL interop example. Updating transforms of many cubes on GPU, without going through main memory/using the PCIe bus +/// Create all OpenGL resources AFTER create OpenCL context! +/// + + +#include +#include + +#include "btGlutInclude.h" +#include "../opengl_interop/btStopwatch.h" + + +#include "btVector3.h" +#include "btQuaternion.h" +#include "btMatrix3x3.h" +static float angle(0); + +#include + +#ifdef _WIN32 +#include +#endif + +//OpenCL stuff +#include "../basic_initialize/btOpenCLUtils.h" +#include "../opengl_interop/btOpenCLGLInteropBuffer.h" + +cl_context g_cxMainContext; +cl_command_queue g_cqCommandQue; +cl_device_id g_device; +static const size_t workGroupSize = 128; +cl_mem gLinVelMem; +cl_mem gAngVelMem; + + +btOpenCLGLInteropBuffer* g_interopBuffer = 0; +cl_kernel g_interopKernel; + +////for Adl +#include + +adl::DeviceCL* g_deviceCL=0; + + + +bool useCPU = false; +bool printStats = false; +bool runOpenCLKernels = true; + +#define MSTRINGIFY(A) #A +static char* interopKernelString = +#include "integrateKernel.cl" + +btStopwatch gStopwatch; +int m_glutScreenWidth = 640; +int m_glutScreenHeight= 480; + +bool m_ortho = false; + +static GLuint instancingShader; // The instancing renderer +static GLuint cube_vao; +static GLuint cube_vbo; +static GLuint index_vbo; +static GLuint m_texturehandle; + +static bool done = false; +static GLint angle_loc = 0; +static GLint ModelViewMatrix; +static GLint ProjectionMatrix; + + +static GLint uniform_texture_diffuse = 0; + +//used for dynamic loading from disk (default switched off) +#define MAX_SHADER_LENGTH 8192 +static GLubyte shaderText[MAX_SHADER_LENGTH]; + +static const char* vertexShader= \ +"#version 330\n" +"precision highp float;\n" +"\n" +"\n" +"\n" +"layout (location = 0) in vec4 position;\n" +"layout (location = 1) in vec4 instance_position;\n" +"layout (location = 2) in vec4 instance_quaternion;\n" +"layout (location = 3) in vec2 uvcoords;\n" +"layout (location = 4) in vec3 vertexnormal;\n" +"\n" +"\n" +"uniform float angle = 0.0;\n" +"uniform mat4 ModelViewMatrix;\n" +"uniform mat4 ProjectionMatrix;\n" +"\n" +"out Fragment\n" +"{\n" +" vec4 color;\n" +"} fragment;\n" +"\n" +"out Vert\n" +"{\n" +" vec2 texcoord;\n" +"} vert;\n" +"\n" +"\n" +"vec4 quatMul ( in vec4 q1, in vec4 q2 )\n" +"{\n" +" vec3 im = q1.w * q2.xyz + q1.xyz * q2.w + cross ( q1.xyz, q2.xyz );\n" +" vec4 dt = q1 * q2;\n" +" float re = dot ( dt, vec4 ( -1.0, -1.0, -1.0, 1.0 ) );\n" +" return vec4 ( im, re );\n" +"}\n" +"\n" +"vec4 quatFromAxisAngle(vec4 axis, in float angle)\n" +"{\n" +" float cah = cos(angle*0.5);\n" +" float sah = sin(angle*0.5);\n" +" float d = inversesqrt(dot(axis,axis));\n" +" vec4 q = vec4(axis.x*sah*d,axis.y*sah*d,axis.z*sah*d,cah);\n" +" return q;\n" +"}\n" +"//\n" +"// vector rotation via quaternion\n" +"//\n" +"vec4 quatRotate3 ( in vec3 p, in vec4 q )\n" +"{\n" +" vec4 temp = quatMul ( q, vec4 ( p, 0.0 ) );\n" +" return quatMul ( temp, vec4 ( -q.x, -q.y, -q.z, q.w ) );\n" +"}\n" +"vec4 quatRotate ( in vec4 p, in vec4 q )\n" +"{\n" +" vec4 temp = quatMul ( q, p );\n" +" return quatMul ( temp, vec4 ( -q.x, -q.y, -q.z, q.w ) );\n" +"}\n" +"\n" +"out vec3 lightDir,normal,ambient;\n" +"\n" +"void main(void)\n" +"{\n" +" vec4 q = instance_quaternion;\n" +" ambient = vec3(0.2,0.2,0.2);\n" +" \n" +" \n" +" vec4 local_normal = (quatRotate3( vertexnormal,q));\n" +" vec3 light_pos = vec3(1000,1000,1000);\n" +" normal = normalize(ModelViewMatrix * local_normal).xyz;\n" +"\n" +" lightDir = normalize(light_pos);//gl_LightSource[0].position.xyz));\n" +"// lightDir = normalize(vec3(gl_LightSource[0].position));\n" +" \n" +" vec4 axis = vec4(1,1,1,0);\n" +" vec4 localcoord = quatRotate3( position.xyz,q);\n" +" vec4 vertexPos = ProjectionMatrix * ModelViewMatrix *(instance_position+localcoord);\n" +"\n" +" gl_Position = vertexPos;\n" +" \n" +"// fragment.color = instance_color;\n" +" vert.texcoord = uvcoords;\n" +"}\n" +; + + +static const char* fragmentShader= \ +"#version 330\n" +"precision highp float;\n" +"\n" +"in Fragment\n" +"{\n" +" vec4 color;\n" +"} fragment;\n" +"\n" +"in Vert\n" +"{\n" +" vec2 texcoord;\n" +"} vert;\n" +"\n" +"uniform sampler2D Diffuse;\n" +"\n" +"in vec3 lightDir,normal,ambient;\n" +"\n" +"out vec4 color;\n" +"\n" +"void main_textured(void)\n" +"{\n" +" color = texture2D(Diffuse,vert.texcoord);//fragment.color;\n" +"}\n" +"\n" +"void main(void)\n" +"{\n" +" vec4 texel = texture2D(Diffuse,vert.texcoord);//fragment.color;\n" +" vec3 ct,cf;\n" +" float intensity,at,af;\n" +" intensity = max(dot(lightDir,normalize(normal)),0.0);\n" +" cf = intensity*vec3(1.0,1.0,1.0);//intensity * (gl_FrontMaterial.diffuse).rgb+ambient;//gl_FrontMaterial.ambient.rgb;\n" +" af = 1.0;\n" +" \n" +" ct = texel.rgb;\n" +" at = texel.a;\n" +" \n" +" color = vec4(ct * cf, at * af); \n" +"}\n" +; + + +// Load the shader from the source text +void gltLoadShaderSrc(const char *szShaderSrc, GLuint shader) +{ + GLchar *fsStringPtr[1]; + + fsStringPtr[0] = (GLchar *)szShaderSrc; + glShaderSource(shader, 1, (const GLchar **)fsStringPtr, NULL); +} + + +//////////////////////////////////////////////////////////////// +// Load the shader from the specified file. Returns false if the +// shader could not be loaded +bool gltLoadShaderFile(const char *szFile, GLuint shader) +{ + GLint shaderLength = 0; + FILE *fp; + + // Open the shader file + fp = fopen(szFile, "r"); + if(fp != NULL) + { + // See how long the file is + while (fgetc(fp) != EOF) + shaderLength++; + + // Allocate a block of memory to send in the shader + assert(shaderLength < MAX_SHADER_LENGTH); // make me bigger! + if(shaderLength > MAX_SHADER_LENGTH) + { + fclose(fp); + return false; + } + + // Go back to beginning of file + rewind(fp); + + // Read the whole file in + if (shaderText != NULL) + fread(shaderText, 1, shaderLength, fp); + + // Make sure it is null terminated and close the file + shaderText[shaderLength] = '\0'; + fclose(fp); + } + else + return false; + + // printf(shaderText); + // Load the string + gltLoadShaderSrc((const char *)shaderText, shader); + + return true; +} + + +///////////////////////////////////////////////////////////////// +// Load a pair of shaders, compile, and link together. Specify the complete +// file path for each shader. Note, there is no support for +// just loading say a vertex program... you have to do both. +GLuint gltLoadShaderPair(const char *szVertexProg, const char *szFragmentProg, bool loadFromFile) +{ + // Temporary Shader objects + GLuint hVertexShader; + GLuint hFragmentShader; + GLuint hReturn = 0; + GLint testVal; + + // Create shader objects + hVertexShader = glCreateShader(GL_VERTEX_SHADER); + hFragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + + if (loadFromFile) + { + + if(gltLoadShaderFile(szVertexProg, hVertexShader) == false) + { + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + + if(gltLoadShaderFile(szFragmentProg, hFragmentShader) == false) + { + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + } else + { + gltLoadShaderSrc(vertexShader, hVertexShader); + gltLoadShaderSrc(fragmentShader, hFragmentShader); + } + // Compile them + glCompileShader(hVertexShader); + glCompileShader(hFragmentShader); + + // Check for errors + glGetShaderiv(hVertexShader, GL_COMPILE_STATUS, &testVal); + if(testVal == GL_FALSE) + { + char temp[256] = ""; + glGetShaderInfoLog( hVertexShader, 256, NULL, temp); + fprintf( stderr, "Compile failed:\n%s\n", temp); + assert(0); + exit(0); + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + + glGetShaderiv(hFragmentShader, GL_COMPILE_STATUS, &testVal); + if(testVal == GL_FALSE) + { + char temp[256] = ""; + glGetShaderInfoLog( hFragmentShader, 256, NULL, temp); + fprintf( stderr, "Compile failed:\n%s\n", temp); + assert(0); + exit(0); + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + + // Link them - assuming it works... + hReturn = glCreateProgram(); + glAttachShader(hReturn, hVertexShader); + glAttachShader(hReturn, hFragmentShader); + + glLinkProgram(hReturn); + + // These are no longer needed + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + + // Make sure link worked too + glGetProgramiv(hReturn, GL_LINK_STATUS, &testVal); + if(testVal == GL_FALSE) + { + glDeleteProgram(hReturn); + return (GLuint)NULL; + } + + return hReturn; +} + +///position xyz, unused w, normal, uv +static const GLfloat cube_vertices[] = +{ + -1.0f, -1.0f, 1.0f, 0.0f, 0,0,1, 0,0,//0 + 1.0f, -1.0f, 1.0f, 0.0f, 0,0,1, 1,0,//1 + 1.0f, 1.0f, 1.0f, 0.0f, 0,0,1, 1,1,//2 + -1.0f, 1.0f, 1.0f, 0.0f, 0,0,1, 0,1 ,//3 + + -1.0f, -1.0f, -1.0f, 1.0f, 0,0,-1, 0,0,//4 + 1.0f, -1.0f, -1.0f, 1.0f, 0,0,-1, 1,0,//5 + 1.0f, 1.0f, -1.0f, 1.0f, 0,0,-1, 1,1,//6 + -1.0f, 1.0f, -1.0f, 1.0f, 0,0,-1, 0,1,//7 + + -1.0f, -1.0f, -1.0f, 1.0f, -1,0,0, 0,0, + -1.0f, 1.0f, -1.0f, 1.0f, -1,0,0, 1,0, + -1.0f, 1.0f, 1.0f, 1.0f, -1,0,0, 1,1, + -1.0f, -1.0f, 1.0f, 1.0f, -1,0,0, 0,1, + + 1.0f, -1.0f, -1.0f, 1.0f, 1,0,0, 0,0, + 1.0f, 1.0f, -1.0f, 1.0f, 1,0,0, 1,0, + 1.0f, 1.0f, 1.0f, 1.0f, 1,0,0, 1,1, + 1.0f, -1.0f, 1.0f, 1.0f, 1,0,0, 0,1, + + -1.0f, -1.0f, -1.0f, 1.0f, 0,-1,0, 0,0, + -1.0f, -1.0f, 1.0f, 1.0f, 0,-1,0, 1,0, + 1.0f, -1.0f, 1.0f, 1.0f, 0,-1,0, 1,1, + 1.0f,-1.0f, -1.0f, 1.0f, 0,-1,0, 0,1, + + -1.0f, 1.0f, -1.0f, 1.0f, 0,1,0, 0,0, + -1.0f, 1.0f, 1.0f, 1.0f, 0,1,0, 1,0, + 1.0f, 1.0f, 1.0f, 1.0f, 0,1,0, 1,1, + 1.0f,1.0f, -1.0f, 1.0f, 0,1,0, 0,1, +}; + +static const int cube_indices[]= +{ + 0,1,2,0,2,3,//ground face + 4,5,6,4,6,7,//top face + 8,9,10,8,10,11, + 12,13,14,12,14,15, + 16,17,18,16,18,19, + 20,21,22,20,22,23 +}; + + + + + +void DeleteCL() +{ + clReleaseContext(g_cxMainContext); + clReleaseCommandQueue(g_cqCommandQue); +} + +void InitCL() +{ + void* glCtx=0; + void* glDC = 0; + +#ifdef _WIN32 + glCtx = wglGetCurrentContext(); +#else //!_WIN32 + GLXContext glCtx = glXGetCurrentContext(); +#endif //!_WIN32 + glDC = wglGetCurrentDC(); + + int ciErrNum = 0; + cl_device_type deviceType = CL_DEVICE_TYPE_ALL;//GPU; + g_cxMainContext = btOpenCLUtils::createContextFromType(deviceType, &ciErrNum, glCtx, glDC); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + int numDev = btOpenCLUtils::getNumDevices(g_cxMainContext); + + if (numDev>0) + { + g_device= btOpenCLUtils::getDevice(g_cxMainContext,0); + btOpenCLDeviceInfo clInfo; + btOpenCLUtils::getDeviceInfo(g_device,clInfo); + btOpenCLUtils::printDeviceInfo(g_device); + // create a command-queue + g_cqCommandQue = clCreateCommandQueue(g_cxMainContext, g_device, 0, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + //normally you would create and execute kernels using this command queue + + } + + +} + +#define NUM_OBJECTS (NUM_OBJECTS_X*NUM_OBJECTS_Y*NUM_OBJECTS_Z) +#define POSITION_BUFFER_SIZE (NUM_OBJECTS*sizeof(float)*4) +#define ORIENTATION_BUFFER_SIZE (NUM_OBJECTS*sizeof(float)*4) + + +GLfloat* instance_positions_ptr = 0; +GLfloat* instance_quaternion_ptr = 0; + +void DeleteShaders() +{ + glDeleteVertexArrays(1, &cube_vao); + glDeleteBuffers(1,&index_vbo); + glDeleteBuffers(1,&cube_vbo); + glDeleteProgram(instancingShader); +} + +void writeTransforms() +{ + + + glFlush(); + char* bla = (char*)glMapBuffer( GL_ARRAY_BUFFER,GL_READ_WRITE);//GL_WRITE_ONLY + + float* positions = (float*)(bla+sizeof(cube_vertices)); + float* orientations = (float*)(bla+sizeof(cube_vertices) + POSITION_BUFFER_SIZE); + // positions[0]+=0.001f; + + static int offset=0; + //offset++; + + static btVector3 axis(1,0,0); + angle += 0.01f; + int index=0; + btQuaternion orn(axis,angle); + for (int i=0;i m_glutScreenHeight) + { + aspect = m_glutScreenWidth / (float)m_glutScreenHeight; + extents.setValue(aspect * 1.0f, 1.0f,0); + } else + { + aspect = m_glutScreenHeight / (float)m_glutScreenWidth; + extents.setValue(1.0f, aspect*1.f,0); + } + + + if (m_ortho) + { + // reset matrix + glLoadIdentity(); + extents *= m_cameraDistance; + btVector3 lower = m_cameraTargetPosition - extents; + btVector3 upper = m_cameraTargetPosition + extents; + glOrtho(lower.getX(), upper.getX(), lower.getY(), upper.getY(),-1000,1000); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + } else + { + if (m_glutScreenWidth > m_glutScreenHeight) + { + glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar); + } else + { + glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar); + } + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(m_cameraPosition[0], m_cameraPosition[1], m_cameraPosition[2], + m_cameraTargetPosition[0], m_cameraTargetPosition[1], m_cameraTargetPosition[2], + m_cameraUp.getX(),m_cameraUp.getY(),m_cameraUp.getZ()); + } + +} + + + +void myinit() +{ + + + // GLfloat light_ambient[] = { btScalar(0.2), btScalar(0.2), btScalar(0.2), btScalar(1.0) }; + GLfloat light_ambient[] = { btScalar(1.0), btScalar(1.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 )}; + /* light_position is NOT default value */ + GLfloat light_position0[] = { btScalar(1000.0), btScalar(1000.0), btScalar(1000.0), btScalar(0.0 )}; + GLfloat light_position1[] = { btScalar(-1.0), btScalar(-10.0), btScalar(-1.0), btScalar(0.0) }; + + glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT0, GL_POSITION, light_position0); + + glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT1, GL_POSITION, light_position1); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + + + // glShadeModel(GL_FLAT);//GL_SMOOTH); + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + glClearColor(float(0.7),float(0.7),float(0.7),float(0)); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + + static bool m_textureenabled = true; + static bool m_textureinitialized = false; + + + if(m_textureenabled) + { + if(!m_textureinitialized) + { + glActiveTexture(GL_TEXTURE0); + + GLubyte* image=new GLubyte[256*256*3]; + for(int y=0;y<256;++y) + { + const int t=y>>5; + GLubyte* pi=image+y*256*3; + for(int x=0;x<256;++x) + { + const int s=x>>5; + const GLubyte b=180; + GLubyte c=b+((s+t&1)&1)*(255-b); + pi[0]=255; + pi[1]=c; + pi[2]=c; + pi+=3; + } + } + + glGenTextures(1,(GLuint*)&m_texturehandle); + glBindTexture(GL_TEXTURE_2D,m_texturehandle); + glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); + gluBuild2DMipmaps(GL_TEXTURE_2D,3,256,256,GL_RGB,GL_UNSIGNED_BYTE,image); + delete[] image; + m_textureinitialized=true; + } + // glMatrixMode(GL_TEXTURE); + // glLoadIdentity(); + // glMatrixMode(GL_MODELVIEW); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,m_texturehandle); + + } else + { + glDisable(GL_TEXTURE_2D); + } + + glEnable(GL_COLOR_MATERIAL); + + + // glEnable(GL_CULL_FACE); + // glCullFace(GL_BACK); +} + +//#pragma optimize( "g", off ) + +void updatePos() +{ + + + if (useCPU) + { + int index=0; + for (int i=0;igetCLBUffer(); + cl_int ciErrNum = CL_SUCCESS; + ciErrNum = clEnqueueAcquireGLObjects(g_cqCommandQue, 1, &clBuffer, 0, 0, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + if (runOpenCLKernels) + { + int numObjects = NUM_OBJECTS; + int offset = (sizeof(cube_vertices) )/4; + + ciErrNum = clSetKernelArg(g_interopKernel, 0, sizeof(int), &offset); + ciErrNum = clSetKernelArg(g_interopKernel, 1, sizeof(int), &numObjects); + ciErrNum = clSetKernelArg(g_interopKernel, 2, sizeof(cl_mem), (void*)&clBuffer ); + + ciErrNum = clSetKernelArg(g_interopKernel, 3, sizeof(cl_mem), (void*)&gLinVelMem); + ciErrNum = clSetKernelArg(g_interopKernel, 4, sizeof(cl_mem), (void*)&gAngVelMem); + + size_t numWorkItems = workGroupSize*((NUM_OBJECTS + (workGroupSize-1)) / workGroupSize); + ciErrNum = clEnqueueNDRangeKernel(g_cqCommandQue, g_interopKernel, 1, NULL, &numWorkItems, &workGroupSize,0 ,0 ,0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + + ciErrNum = clEnqueueReleaseGLObjects(g_cqCommandQue, 1, &clBuffer, 0, 0, 0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + clFinish(g_cqCommandQue); + + } + +} +//#pragma optimize( "g", on ) + +void RenderScene(void) +{ + +#if 0 + float modelview[20]={0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9}; + // get the current modelview matrix + glGetFloatv(GL_MODELVIEW_MATRIX , modelview); + float projection[20]={0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9}; + glGetFloatv(GL_PROJECTION_MATRIX, projection); +#endif + + myinit(); + + updateCamera(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //render coordinate system + glBegin(GL_LINES); + glColor3f(1,0,0); + glVertex3f(0,0,0); + glVertex3f(1,0,0); + glColor3f(0,1,0); + glVertex3f(0,0,0); + glVertex3f(0,1,0); + glColor3f(0,0,1); + glVertex3f(0,0,0); + glVertex3f(0,0,1); + glEnd(); + + //do a finish, to make sure timings are clean + // glFinish(); + + float start = gStopwatch.getTimeMilliseconds(); + + // glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, cube_vbo); + glFlush(); + updatePos(); + + float stop = gStopwatch.getTimeMilliseconds(); + gStopwatch.reset(); + + if (printStats) + { + printf("updatePos=%f ms on ",stop-start); + + if (useCPU) + { + printf("CPU \n"); + } else + { + printf("OpenCL "); + if (runOpenCLKernels) + printf("running the kernels"); + else + printf("without running the kernels"); + printf("\n"); + } + } + + glBindVertexArray(cube_vao); + + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 9*sizeof(float), 0); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(sizeof(cube_vertices))); + glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(sizeof(cube_vertices)+POSITION_BUFFER_SIZE)); + int uvoffset = 7*sizeof(float); + int normaloffset = 4*sizeof(float); + + glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid *)uvoffset); + glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid *)normaloffset); + + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glEnableVertexAttribArray(2); + glEnableVertexAttribArray(3); + glEnableVertexAttribArray(4); + + glVertexAttribDivisor(1, 1); + glVertexAttribDivisor(2, 1); + glVertexAttribDivisor(3, 0); + glVertexAttribDivisor(4, 0); + + glUseProgram(instancingShader); + glUniform1f(angle_loc, 0); + GLfloat pm[16]; + glGetFloatv(GL_PROJECTION_MATRIX, pm); + glUniformMatrix4fv(ProjectionMatrix, 1, false, &pm[0]); + + GLfloat mvm[16]; + glGetFloatv(GL_MODELVIEW_MATRIX, mvm); + glUniformMatrix4fv(ModelViewMatrix, 1, false, &mvm[0]); + + glUniform1i(uniform_texture_diffuse, 0); + + glFlush(); + int numInstances = NUM_OBJECTS; + int indexCount = sizeof(cube_indices)/sizeof(int); + int indexOffset = 0; + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_vbo); + glDrawElementsInstanced(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, (void*)indexOffset, numInstances); + + glUseProgram(0); + glBindBuffer(GL_ARRAY_BUFFER,0); + glBindVertexArray(0); + + glutSwapBuffers(); + glutPostRedisplay(); + + GLint err = glGetError(); + assert(err==GL_NO_ERROR); +} + + +void ChangeSize(int w, int h) +{ + m_glutScreenWidth = w; + m_glutScreenHeight = h; + +#ifdef RECREATE_CL_AND_SHADERS_ON_RESIZE + delete g_interopBuffer; + clReleaseKernel(g_interopKernel); + DeleteCL(); + DeleteShaders(); +#endif //RECREATE_CL_AND_SHADERS_ON_RESIZE + + // Set Viewport to window dimensions + glViewport(0, 0, w, h); + +#ifdef RECREATE_CL_AND_SHADERS_ON_RESIZE + InitCL(); + InitShaders(); + + g_interopBuffer = new btOpenCLGLInteropBuffer(g_cxMainContext,g_cqCommandQue,cube_vbo); + clFinish(g_cqCommandQue); + g_interopKernel = btOpenCLUtils::compileCLKernelFromString(g_cxMainContext, interopKernelString, "interopKernel" ); +#endif //RECREATE_CL_AND_SHADERS_ON_RESIZE + +} + +void Keyboard(unsigned char key, int x, int y) +{ + switch (key) + { + case 27: + done = true; + break; + case 'O': + case 'o': + { + m_ortho = !m_ortho; + break; + } + case 'c': + case 'C': + { + useCPU = !useCPU; + if (useCPU) + printf("using CPU\n"); + else + printf("using OpenCL\n"); + break; + } + case 's': + case 'S': + { + printStats = !printStats; + break; + } + case 'k': + case 'K': + { + runOpenCLKernels=!runOpenCLKernels; + break; + } + case 'q': + case 'Q': + exit(0); + default: + break; + } +} + +// Cleanup +void ShutdownRC(void) +{ + glDeleteBuffers(1, &cube_vbo); + glDeleteVertexArrays(1, &cube_vao); +} + +int main(int argc, char* argv[]) +{ + // printf("vertexShader = \n%s\n",vertexShader); + // printf("fragmentShader = \n%s\n",fragmentShader); + + glutInit(&argc, argv); + + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); + + + glutInitWindowSize(m_glutScreenWidth, m_glutScreenHeight); + char buf[1024]; + sprintf(buf,"OpenCL - OpenGL interop, transforms %d cubes on the GPU (use c to toggle CPU/CL)", NUM_OBJECTS); + glutCreateWindow(buf); + + glutReshapeFunc(ChangeSize); + + glutKeyboardFunc(Keyboard); + glutDisplayFunc(RenderScene); + + GLenum err = glewInit(); + if (GLEW_OK != err) + { + /* Problem: glewInit failed, something is seriously wrong. */ + fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); + } + + //ChangeSize(m_glutScreenWidth,m_glutScreenHeight); + + InitCL(); + + +#define CUSTOM_CL_INITIALIZATION +#ifdef CUSTOM_CL_INITIALIZATION + g_deviceCL = new adl::DeviceCL(); + g_deviceCL->m_deviceIdx = g_device; + g_deviceCL->m_context = g_cxMainContext; + g_deviceCL->m_commandQueue = g_cqCommandQue; + +#else + DeviceUtils::Config cfg; + cfg.m_type = DeviceUtils::Config::DEVICE_CPU; + g_deviceCL = DeviceUtils::allocate( TYPE_CL, cfg ); +#endif + + int size = NUM_OBJECTS; + adl::Buffer linvelBuf( g_deviceCL, size ); + adl::Buffer angvelBuf( g_deviceCL, size ); + + gLinVelMem = (cl_mem)linvelBuf.m_ptr; + gAngVelMem = (cl_mem)angvelBuf.m_ptr; + + btVector3* linVelHost= new btVector3[size]; + btVector3* angVelHost = new btVector3[size]; + + for (int i=0;i +#include +#include +#endif + +#if defined (SUNOS) || defined (__SUNOS__) +#include +#endif + +#if defined(WIN32) || defined(_WIN32) + +#define BT_USE_WINDOWS_TIMERS +#define WIN32_LEAN_AND_MEAN +#define NOWINRES +#define NOMCX +#define NOIME + +#ifdef _XBOX + #include +#else //_XBOX + #include +#endif //_XBOX + +#include + + +#else //_WIN32 +#include +#endif //_WIN32 + +#define mymin(a,b) (a > b ? a : b) + +struct btStopwatchData +{ + +#ifdef BT_USE_WINDOWS_TIMERS + LARGE_INTEGER mClockFrequency; + DWORD mStartTick; + LONGLONG mPrevElapsedTime; + LARGE_INTEGER mStartTime; +#else +#ifdef __CELLOS_LV2__ + uint64_t mStartTime; +#else + struct timeval mStartTime; +#endif +#endif //__CELLOS_LV2__ + +}; + + +btStopwatch::btStopwatch() +{ + m_data = new btStopwatchData; +#ifdef BT_USE_WINDOWS_TIMERS + QueryPerformanceFrequency(&m_data->mClockFrequency); +#endif + reset(); +} + +btStopwatch::~btStopwatch() +{ + delete m_data; +} + +btStopwatch::btStopwatch(const btStopwatch& other) +{ + m_data = new btStopwatchData; + *m_data = *other.m_data; +} + +btStopwatch& btStopwatch::operator=(const btStopwatch& other) +{ + *m_data = *other.m_data; + return *this; +} + + + /// Resets the initial reference time. +void btStopwatch::reset() +{ +#ifdef BT_USE_WINDOWS_TIMERS + QueryPerformanceCounter(&m_data->mStartTime); + m_data->mStartTick = GetTickCount(); + m_data->mPrevElapsedTime = 0; +#else +#ifdef __CELLOS_LV2__ + + typedef uint64_t ClockSize; + ClockSize newTime; + //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + SYS_TIMEBASE_GET( newTime ); + m_data->mStartTime = newTime; +#else + gettimeofday(&m_data->mStartTime, 0); +#endif +#endif +} + +/// Returns the time in ms since the last call to reset or since +/// the btStopwatch was created. +float btStopwatch::getTimeMilliseconds() +{ + return getTimeMicroseconds()/1000.f; +} + + /// Returns the time in us since the last call to reset or since + /// the stopwatch was created. +unsigned long int btStopwatch::getTimeMicroseconds() +{ +#ifdef BT_USE_WINDOWS_TIMERS + LARGE_INTEGER currentTime; + QueryPerformanceCounter(¤tTime); + LONGLONG elapsedTime = currentTime.QuadPart - m_data->mStartTime.QuadPart; + + // Compute the number of millisecond ticks elapsed. + unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / m_data->mClockFrequency.QuadPart); + + // Check for unexpected leaps in the Win32 performance counter. + // (This is caused by unexpected data across the PCI to ISA + // bridge, aka south bridge. See Microsoft KB274323.) + unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick; + signed long msecOff = (signed long)(msecTicks - elapsedTicks); + if (msecOff < -100 || msecOff > 100) + { + // Adjust the starting time forwards. + LONGLONG msecAdjustment = mymin(msecOff * + m_data->mClockFrequency.QuadPart / 1000, elapsedTime - + m_data->mPrevElapsedTime); + m_data->mStartTime.QuadPart += msecAdjustment; + elapsedTime -= msecAdjustment; + } + + // Store the current elapsed time for adjustments next time. + m_data->mPrevElapsedTime = elapsedTime; + + // Convert to microseconds. + unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / + m_data->mClockFrequency.QuadPart); + + return usecTicks; +#else + +#ifdef __CELLOS_LV2__ + uint64_t freq=sys_time_get_timebase_frequency(); + double dFreq=((double) freq)/ 1000000.0; + typedef uint64_t ClockSize; + ClockSize newTime; + //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + SYS_TIMEBASE_GET( newTime ); + + return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq); +#else + + struct timeval currentTime; + gettimeofday(¤tTime, 0); + return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 + (currentTime.tv_usec - m_data->mStartTime.tv_usec); +#endif//__CELLOS_LV2__ +#endif +} + + + diff --git a/Extras/RigidBodyGpuPipeline/opencl/opengl_interop/btStopwatch.h b/Extras/RigidBodyGpuPipeline/opencl/opengl_interop/btStopwatch.h new file mode 100644 index 0000000..19e8d37 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/opengl_interop/btStopwatch.h @@ -0,0 +1,45 @@ +/* +Stopwatch for timing and profiling for the Bullet Physics Library, http://bulletphysics.org +Copyright (c) 2003-2011 Erwin Coumans + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_STOPWATCH_H +#define BT_STOPWATCH_H + +///The btStopwatch is a portable basic clock that measures real-time, use for profiling etc. +class btStopwatch +{ +public: + btStopwatch(); + + btStopwatch(const btStopwatch& other); + btStopwatch& operator=(const btStopwatch& other); + + ~btStopwatch(); + + /// Resets the initial reference time. + void reset(); + + /// Returns the time in ms since the last call to reset or since + /// the btStopwatch was created. + float getTimeMilliseconds(); + + /// Returns the time in us since the last call to reset or since + /// the Clock was created. + unsigned long int getTimeMicroseconds(); +private: + struct btStopwatchData* m_data; +}; + + +#endif //BT_STOPWATCH_H \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/opengl_interop/interopKernel.cl b/Extras/RigidBodyGpuPipeline/opencl/opengl_interop/interopKernel.cl new file mode 100644 index 0000000..e65da56 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/opengl_interop/interopKernel.cl @@ -0,0 +1,13 @@ +MSTRINGIFY( + +__kernel void +interopKernel( const int startOffset, const int numNodes, __global float *g_vertexBuffer) +{ + int nodeID = get_global_id(0); + if( nodeID < numNodes ) + { + g_vertexBuffer[nodeID*4 + startOffset+1] += 0.01; + } +} + +); \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/opengl_interop/main.cpp b/Extras/RigidBodyGpuPipeline/opencl/opengl_interop/main.cpp new file mode 100644 index 0000000..9ee3921 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/opengl_interop/main.cpp @@ -0,0 +1,1057 @@ + +//starts crashing when more than 32700 objects on my Geforce 260, unless _USE_SUB_DATA is defined (still unstable though) +//runs fine with fewer objects + +#define NUM_OBJECTS_X 327 +#define NUM_OBJECTS_Y 10 +#define NUM_OBJECTS_Z 10 +//#define NUM_OBJECTS_Z 20 + +//#define _USE_SUB_DATA + +//#define NUM_OBJECTS_X 100 +//#define NUM_OBJECTS_Y 100 +//#define NUM_OBJECTS_Z 100 + +///RECREATE_CL_AND_SHADERS_ON_RESIZE will delete and re-create OpenCL and GLSL shaders/buffers at each resize +//#define RECREATE_CL_AND_SHADERS_ON_RESIZE + +/// +/// OpenCL - OpenGL interop example. Updating transforms of many cubes on GPU, without going through main memory/using the PCIe bus +/// Create all OpenGL resources AFTER create OpenCL context! +/// + + +#include +#include + +#include "btGlutInclude.h" +#include "btStopwatch.h" + + +#include "btVector3.h" +#include "btQuaternion.h" +#include "btMatrix3x3.h" +static float angle(0); + +#include + +#ifdef _WIN32 +#include +#endif + +//OpenCL stuff +#include "../basic_initialize/btOpenCLUtils.h" +#include "btOpenCLGLInteropBuffer.h" + +cl_context g_cxMainContext; +cl_command_queue g_cqCommandQue; +cl_device_id g_device; +static const size_t workGroupSize = 128; + + +btOpenCLGLInteropBuffer* g_interopBuffer = 0; +cl_kernel g_interopKernel; + +bool useCPU = false; +bool printStats = false; +bool runOpenCLKernels = true; + +#define MSTRINGIFY(A) #A +static char* interopKernelString = +#include "interopKernel.cl" + +btStopwatch gStopwatch; +int m_glutScreenWidth = 640; +int m_glutScreenHeight= 480; + +bool m_ortho = false; + +static GLuint instancingShader; // The instancing renderer +static GLuint cube_vao; +static GLuint cube_vbo; +static GLuint index_vbo; +static GLuint m_texturehandle; + +static bool done = false; +static GLint angle_loc = 0; +static GLint ModelViewMatrix; +static GLint ProjectionMatrix; + + +static GLint uniform_texture_diffuse = 0; + +//used for dynamic loading from disk (default switched off) +#define MAX_SHADER_LENGTH 8192 +static GLubyte shaderText[MAX_SHADER_LENGTH]; + +static const char* vertexShader= \ +"#version 330\n" +"precision highp float;\n" +"\n" +"\n" +"\n" +"layout (location = 0) in vec4 position;\n" +"layout (location = 1) in vec4 instance_position;\n" +"layout (location = 2) in vec4 instance_quaternion;\n" +"layout (location = 3) in vec2 uvcoords;\n" +"layout (location = 4) in vec3 vertexnormal;\n" +"\n" +"\n" +"uniform float angle = 0.0;\n" +"uniform mat4 ModelViewMatrix;\n" +"uniform mat4 ProjectionMatrix;\n" +"\n" +"out Fragment\n" +"{\n" +" vec4 color;\n" +"} fragment;\n" +"\n" +"out Vert\n" +"{\n" +" vec2 texcoord;\n" +"} vert;\n" +"\n" +"\n" +"vec4 quatMul ( in vec4 q1, in vec4 q2 )\n" +"{\n" +" vec3 im = q1.w * q2.xyz + q1.xyz * q2.w + cross ( q1.xyz, q2.xyz );\n" +" vec4 dt = q1 * q2;\n" +" float re = dot ( dt, vec4 ( -1.0, -1.0, -1.0, 1.0 ) );\n" +" return vec4 ( im, re );\n" +"}\n" +"\n" +"vec4 quatFromAxisAngle(vec4 axis, in float angle)\n" +"{\n" +" float cah = cos(angle*0.5);\n" +" float sah = sin(angle*0.5);\n" +" float d = inversesqrt(dot(axis,axis));\n" +" vec4 q = vec4(axis.x*sah*d,axis.y*sah*d,axis.z*sah*d,cah);\n" +" return q;\n" +"}\n" +"//\n" +"// vector rotation via quaternion\n" +"//\n" +"vec4 quatRotate3 ( in vec3 p, in vec4 q )\n" +"{\n" +" vec4 temp = quatMul ( q, vec4 ( p, 0.0 ) );\n" +" return quatMul ( temp, vec4 ( -q.x, -q.y, -q.z, q.w ) );\n" +"}\n" +"vec4 quatRotate ( in vec4 p, in vec4 q )\n" +"{\n" +" vec4 temp = quatMul ( q, p );\n" +" return quatMul ( temp, vec4 ( -q.x, -q.y, -q.z, q.w ) );\n" +"}\n" +"\n" +"out vec3 lightDir,normal,ambient;\n" +"\n" +"void main(void)\n" +"{\n" +" vec4 q = instance_quaternion;\n" +" ambient = vec3(0.2,0.2,0.2);\n" +" \n" +" \n" +" vec4 local_normal = (quatRotate3( vertexnormal,q));\n" +" vec3 light_pos = vec3(1000,1000,1000);\n" +" normal = normalize(ModelViewMatrix * local_normal).xyz;\n" +"\n" +" lightDir = normalize(light_pos);//gl_LightSource[0].position.xyz));\n" +"// lightDir = normalize(vec3(gl_LightSource[0].position));\n" +" \n" +" vec4 axis = vec4(1,1,1,0);\n" +" vec4 localcoord = quatRotate3( position.xyz,q);\n" +" vec4 vertexPos = ProjectionMatrix * ModelViewMatrix *(instance_position+localcoord);\n" +"\n" +" gl_Position = vertexPos;\n" +" \n" +"// fragment.color = instance_color;\n" +" vert.texcoord = uvcoords;\n" +"}\n" +; + + +static const char* fragmentShader= \ +"#version 330\n" +"precision highp float;\n" +"\n" +"in Fragment\n" +"{\n" +" vec4 color;\n" +"} fragment;\n" +"\n" +"in Vert\n" +"{\n" +" vec2 texcoord;\n" +"} vert;\n" +"\n" +"uniform sampler2D Diffuse;\n" +"\n" +"in vec3 lightDir,normal,ambient;\n" +"\n" +"out vec4 color;\n" +"\n" +"void main_textured(void)\n" +"{\n" +" color = texture2D(Diffuse,vert.texcoord);//fragment.color;\n" +"}\n" +"\n" +"void main(void)\n" +"{\n" +" vec4 texel = texture2D(Diffuse,vert.texcoord);//fragment.color;\n" +" vec3 ct,cf;\n" +" float intensity,at,af;\n" +" intensity = max(dot(lightDir,normalize(normal)),0.0);\n" +" cf = intensity*vec3(1.0,1.0,1.0);//intensity * (gl_FrontMaterial.diffuse).rgb+ambient;//gl_FrontMaterial.ambient.rgb;\n" +" af = 1.0;\n" +" \n" +" ct = texel.rgb;\n" +" at = texel.a;\n" +" \n" +" color = vec4(ct * cf, at * af); \n" +"}\n" +; + + +// Load the shader from the source text +void gltLoadShaderSrc(const char *szShaderSrc, GLuint shader) +{ + GLchar *fsStringPtr[1]; + + fsStringPtr[0] = (GLchar *)szShaderSrc; + glShaderSource(shader, 1, (const GLchar **)fsStringPtr, NULL); +} + + +//////////////////////////////////////////////////////////////// +// Load the shader from the specified file. Returns false if the +// shader could not be loaded +bool gltLoadShaderFile(const char *szFile, GLuint shader) +{ + GLint shaderLength = 0; + FILE *fp; + + // Open the shader file + fp = fopen(szFile, "r"); + if(fp != NULL) + { + // See how long the file is + while (fgetc(fp) != EOF) + shaderLength++; + + // Allocate a block of memory to send in the shader + assert(shaderLength < MAX_SHADER_LENGTH); // make me bigger! + if(shaderLength > MAX_SHADER_LENGTH) + { + fclose(fp); + return false; + } + + // Go back to beginning of file + rewind(fp); + + // Read the whole file in + if (shaderText != NULL) + fread(shaderText, 1, shaderLength, fp); + + // Make sure it is null terminated and close the file + shaderText[shaderLength] = '\0'; + fclose(fp); + } + else + return false; + + // printf(shaderText); + // Load the string + gltLoadShaderSrc((const char *)shaderText, shader); + + return true; +} + + +///////////////////////////////////////////////////////////////// +// Load a pair of shaders, compile, and link together. Specify the complete +// file path for each shader. Note, there is no support for +// just loading say a vertex program... you have to do both. +GLuint gltLoadShaderPair(const char *szVertexProg, const char *szFragmentProg, bool loadFromFile) +{ + // Temporary Shader objects + GLuint hVertexShader; + GLuint hFragmentShader; + GLuint hReturn = 0; + GLint testVal; + + // Create shader objects + hVertexShader = glCreateShader(GL_VERTEX_SHADER); + hFragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + + if (loadFromFile) + { + + if(gltLoadShaderFile(szVertexProg, hVertexShader) == false) + { + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + + if(gltLoadShaderFile(szFragmentProg, hFragmentShader) == false) + { + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + } else + { + gltLoadShaderSrc(vertexShader, hVertexShader); + gltLoadShaderSrc(fragmentShader, hFragmentShader); + } + // Compile them + glCompileShader(hVertexShader); + glCompileShader(hFragmentShader); + + // Check for errors + glGetShaderiv(hVertexShader, GL_COMPILE_STATUS, &testVal); + if(testVal == GL_FALSE) + { + char temp[256] = ""; + glGetShaderInfoLog( hVertexShader, 256, NULL, temp); + fprintf( stderr, "Compile failed:\n%s\n", temp); + assert(0); + exit(0); + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + + glGetShaderiv(hFragmentShader, GL_COMPILE_STATUS, &testVal); + if(testVal == GL_FALSE) + { + char temp[256] = ""; + glGetShaderInfoLog( hFragmentShader, 256, NULL, temp); + fprintf( stderr, "Compile failed:\n%s\n", temp); + assert(0); + exit(0); + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + return (GLuint)NULL; + } + + // Link them - assuming it works... + hReturn = glCreateProgram(); + glAttachShader(hReturn, hVertexShader); + glAttachShader(hReturn, hFragmentShader); + + glLinkProgram(hReturn); + + // These are no longer needed + glDeleteShader(hVertexShader); + glDeleteShader(hFragmentShader); + + // Make sure link worked too + glGetProgramiv(hReturn, GL_LINK_STATUS, &testVal); + if(testVal == GL_FALSE) + { + glDeleteProgram(hReturn); + return (GLuint)NULL; + } + + return hReturn; +} + +///position xyz, unused w, normal, uv +static const GLfloat cube_vertices[] = +{ + -1.0f, -1.0f, 1.0f, 0.0f, 0,0,1, 0,0,//0 + 1.0f, -1.0f, 1.0f, 0.0f, 0,0,1, 1,0,//1 + 1.0f, 1.0f, 1.0f, 0.0f, 0,0,1, 1,1,//2 + -1.0f, 1.0f, 1.0f, 0.0f, 0,0,1, 0,1 ,//3 + + -1.0f, -1.0f, -1.0f, 1.0f, 0,0,-1, 0,0,//4 + 1.0f, -1.0f, -1.0f, 1.0f, 0,0,-1, 1,0,//5 + 1.0f, 1.0f, -1.0f, 1.0f, 0,0,-1, 1,1,//6 + -1.0f, 1.0f, -1.0f, 1.0f, 0,0,-1, 0,1,//7 + + -1.0f, -1.0f, -1.0f, 1.0f, -1,0,0, 0,0, + -1.0f, 1.0f, -1.0f, 1.0f, -1,0,0, 1,0, + -1.0f, 1.0f, 1.0f, 1.0f, -1,0,0, 1,1, + -1.0f, -1.0f, 1.0f, 1.0f, -1,0,0, 0,1, + + 1.0f, -1.0f, -1.0f, 1.0f, 1,0,0, 0,0, + 1.0f, 1.0f, -1.0f, 1.0f, 1,0,0, 1,0, + 1.0f, 1.0f, 1.0f, 1.0f, 1,0,0, 1,1, + 1.0f, -1.0f, 1.0f, 1.0f, 1,0,0, 0,1, + + -1.0f, -1.0f, -1.0f, 1.0f, 0,-1,0, 0,0, + -1.0f, -1.0f, 1.0f, 1.0f, 0,-1,0, 1,0, + 1.0f, -1.0f, 1.0f, 1.0f, 0,-1,0, 1,1, + 1.0f,-1.0f, -1.0f, 1.0f, 0,-1,0, 0,1, + + -1.0f, 1.0f, -1.0f, 1.0f, 0,1,0, 0,0, + -1.0f, 1.0f, 1.0f, 1.0f, 0,1,0, 1,0, + 1.0f, 1.0f, 1.0f, 1.0f, 0,1,0, 1,1, + 1.0f,1.0f, -1.0f, 1.0f, 0,1,0, 0,1, +}; + +static const int cube_indices[]= +{ + 0,1,2,0,2,3,//ground face + 4,5,6,4,6,7,//top face + 8,9,10,8,10,11, + 12,13,14,12,14,15, + 16,17,18,16,18,19, + 20,21,22,20,22,23 +}; + + + + + +void DeleteCL() +{ + clReleaseContext(g_cxMainContext); + clReleaseCommandQueue(g_cqCommandQue); +} + +void InitCL() +{ + void* glCtx=0; + void* glDC = 0; + +#ifdef _WIN32 + glCtx = wglGetCurrentContext(); +#else //!_WIN32 + GLXContext glCtx = glXGetCurrentContext(); +#endif //!_WIN32 + glDC = wglGetCurrentDC(); + + int ciErrNum = 0; + cl_device_type deviceType = CL_DEVICE_TYPE_ALL;//CPU; + g_cxMainContext = btOpenCLUtils::createContextFromType(deviceType, &ciErrNum, glCtx, glDC); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + + int numDev = btOpenCLUtils::getNumDevices(g_cxMainContext); + + if (numDev>0) + { + g_device= btOpenCLUtils::getDevice(g_cxMainContext,0); + btOpenCLDeviceInfo clInfo; + btOpenCLUtils::getDeviceInfo(g_device,clInfo); + btOpenCLUtils::printDeviceInfo(g_device); + // create a command-queue + g_cqCommandQue = clCreateCommandQueue(g_cxMainContext, g_device, 0, &ciErrNum); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + //normally you would create and execute kernels using this command queue + + } + + +} + +#define NUM_OBJECTS (NUM_OBJECTS_X*NUM_OBJECTS_Y*NUM_OBJECTS_Z) +#define POSITION_BUFFER_SIZE (NUM_OBJECTS*sizeof(float)*4) +#define ORIENTATION_BUFFER_SIZE (NUM_OBJECTS*sizeof(float)*4) + + +GLfloat* instance_positions_ptr = 0; +GLfloat* instance_quaternion_ptr = 0; + +void DeleteShaders() +{ + glDeleteVertexArrays(1, &cube_vao); + glDeleteBuffers(1,&index_vbo); + glDeleteBuffers(1,&cube_vbo); + glDeleteProgram(instancingShader); +} + +void writeTransforms() +{ + + + glFlush(); + char* bla = (char*)glMapBuffer( GL_ARRAY_BUFFER,GL_READ_WRITE);//GL_WRITE_ONLY + + float* positions = (float*)(bla+sizeof(cube_vertices)); + float* orientations = (float*)(bla+sizeof(cube_vertices) + POSITION_BUFFER_SIZE); + // positions[0]+=0.001f; + + static int offset=0; + //offset++; + + static btVector3 axis(1,0,0); + angle += 0.01f; + int index=0; + btQuaternion orn(axis,angle); + for (int i=0;i m_glutScreenHeight) + { + aspect = m_glutScreenWidth / (float)m_glutScreenHeight; + extents.setValue(aspect * 1.0f, 1.0f,0); + } else + { + aspect = m_glutScreenHeight / (float)m_glutScreenWidth; + extents.setValue(1.0f, aspect*1.f,0); + } + + + if (m_ortho) + { + // reset matrix + glLoadIdentity(); + extents *= m_cameraDistance; + btVector3 lower = m_cameraTargetPosition - extents; + btVector3 upper = m_cameraTargetPosition + extents; + glOrtho(lower.getX(), upper.getX(), lower.getY(), upper.getY(),-1000,1000); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + } else + { + if (m_glutScreenWidth > m_glutScreenHeight) + { + glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar); + } else + { + glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar); + } + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(m_cameraPosition[0], m_cameraPosition[1], m_cameraPosition[2], + m_cameraTargetPosition[0], m_cameraTargetPosition[1], m_cameraTargetPosition[2], + m_cameraUp.getX(),m_cameraUp.getY(),m_cameraUp.getZ()); + } + +} + + + +void myinit() +{ + + + // GLfloat light_ambient[] = { btScalar(0.2), btScalar(0.2), btScalar(0.2), btScalar(1.0) }; + GLfloat light_ambient[] = { btScalar(1.0), btScalar(1.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 )}; + /* light_position is NOT default value */ + GLfloat light_position0[] = { btScalar(1000.0), btScalar(1000.0), btScalar(1000.0), btScalar(0.0 )}; + GLfloat light_position1[] = { btScalar(-1.0), btScalar(-10.0), btScalar(-1.0), btScalar(0.0) }; + + glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT0, GL_POSITION, light_position0); + + glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular); + glLightfv(GL_LIGHT1, GL_POSITION, light_position1); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + + + // glShadeModel(GL_FLAT);//GL_SMOOTH); + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + glClearColor(float(0.7),float(0.7),float(0.7),float(0)); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + + static bool m_textureenabled = true; + static bool m_textureinitialized = false; + + + if(m_textureenabled) + { + if(!m_textureinitialized) + { + glActiveTexture(GL_TEXTURE0); + + GLubyte* image=new GLubyte[256*256*3]; + for(int y=0;y<256;++y) + { + const int t=y>>5; + GLubyte* pi=image+y*256*3; + for(int x=0;x<256;++x) + { + const int s=x>>5; + const GLubyte b=180; + GLubyte c=b+((s+t&1)&1)*(255-b); + pi[0]=255; + pi[1]=c; + pi[2]=c; + pi+=3; + } + } + + glGenTextures(1,(GLuint*)&m_texturehandle); + glBindTexture(GL_TEXTURE_2D,m_texturehandle); + glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); + gluBuild2DMipmaps(GL_TEXTURE_2D,3,256,256,GL_RGB,GL_UNSIGNED_BYTE,image); + delete[] image; + m_textureinitialized=true; + } + // glMatrixMode(GL_TEXTURE); + // glLoadIdentity(); + // glMatrixMode(GL_MODELVIEW); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D,m_texturehandle); + + } else + { + glDisable(GL_TEXTURE_2D); + } + + glEnable(GL_COLOR_MATERIAL); + + + // glEnable(GL_CULL_FACE); + // glCullFace(GL_BACK); +} + +//#pragma optimize( "g", off ) + +void updatePos() +{ + + + if (useCPU) + { + int index=0; + for (int i=0;igetCLBUffer(); + cl_int ciErrNum = CL_SUCCESS; + ciErrNum = clEnqueueAcquireGLObjects(g_cqCommandQue, 1, &clBuffer, 0, 0, NULL); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + if (runOpenCLKernels) + { + int numObjects = NUM_OBJECTS; + int offset = (sizeof(cube_vertices) )/4; + + ciErrNum = clSetKernelArg(g_interopKernel, 0, sizeof(int), &offset); + ciErrNum = clSetKernelArg(g_interopKernel, 1, sizeof(int), &numObjects); + ciErrNum = clSetKernelArg(g_interopKernel, 2, sizeof(cl_mem), (void*)&clBuffer ); + size_t numWorkItems = workGroupSize*((NUM_OBJECTS + (workGroupSize-1)) / workGroupSize); + ciErrNum = clEnqueueNDRangeKernel(g_cqCommandQue, g_interopKernel, 1, NULL, &numWorkItems, &workGroupSize,0 ,0 ,0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + } + ciErrNum = clEnqueueReleaseGLObjects(g_cqCommandQue, 1, &clBuffer, 0, 0, 0); + oclCHECKERROR(ciErrNum, CL_SUCCESS); + clFinish(g_cqCommandQue); + + } + +} +//#pragma optimize( "g", on ) + +void RenderScene(void) +{ + +#if 0 + float modelview[20]={0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9}; + // get the current modelview matrix + glGetFloatv(GL_MODELVIEW_MATRIX , modelview); + float projection[20]={0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9}; + glGetFloatv(GL_PROJECTION_MATRIX, projection); +#endif + + myinit(); + + updateCamera(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //render coordinate system + glBegin(GL_LINES); + glColor3f(1,0,0); + glVertex3f(0,0,0); + glVertex3f(1,0,0); + glColor3f(0,1,0); + glVertex3f(0,0,0); + glVertex3f(0,1,0); + glColor3f(0,0,1); + glVertex3f(0,0,0); + glVertex3f(0,0,1); + glEnd(); + + //do a finish, to make sure timings are clean + // glFinish(); + + float start = gStopwatch.getTimeMilliseconds(); + + // glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, cube_vbo); + glFlush(); + updatePos(); + + float stop = gStopwatch.getTimeMilliseconds(); + gStopwatch.reset(); + + if (printStats) + { + printf("updatePos=%f ms on ",stop-start); + + if (useCPU) + { + printf("CPU \n"); + } else + { + printf("OpenCL "); + if (runOpenCLKernels) + printf("running the kernels"); + else + printf("without running the kernels"); + printf("\n"); + } + } + + glBindVertexArray(cube_vao); + + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 9*sizeof(float), 0); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(sizeof(cube_vertices))); + glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(sizeof(cube_vertices)+POSITION_BUFFER_SIZE)); + int uvoffset = 7*sizeof(float); + int normaloffset = 4*sizeof(float); + + glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid *)uvoffset); + glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid *)normaloffset); + + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glEnableVertexAttribArray(2); + glEnableVertexAttribArray(3); + glEnableVertexAttribArray(4); + + glVertexAttribDivisor(1, 1); + glVertexAttribDivisor(2, 1); + glVertexAttribDivisor(3, 0); + glVertexAttribDivisor(4, 0); + + glUseProgram(instancingShader); + glUniform1f(angle_loc, 0); + GLfloat pm[16]; + glGetFloatv(GL_PROJECTION_MATRIX, pm); + glUniformMatrix4fv(ProjectionMatrix, 1, false, &pm[0]); + + GLfloat mvm[16]; + glGetFloatv(GL_MODELVIEW_MATRIX, mvm); + glUniformMatrix4fv(ModelViewMatrix, 1, false, &mvm[0]); + + glUniform1i(uniform_texture_diffuse, 0); + + glFlush(); + int numInstances = NUM_OBJECTS; + int indexCount = sizeof(cube_indices)/sizeof(int); + int indexOffset = 0; + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_vbo); + glDrawElementsInstanced(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, (void*)indexOffset, numInstances); + + glUseProgram(0); + glBindBuffer(GL_ARRAY_BUFFER,0); + glBindVertexArray(0); + + glutSwapBuffers(); + glutPostRedisplay(); + + GLint err = glGetError(); + assert(err==GL_NO_ERROR); +} + + +void ChangeSize(int w, int h) +{ + m_glutScreenWidth = w; + m_glutScreenHeight = h; + +#ifdef RECREATE_CL_AND_SHADERS_ON_RESIZE + delete g_interopBuffer; + clReleaseKernel(g_interopKernel); + DeleteCL(); + DeleteShaders(); +#endif //RECREATE_CL_AND_SHADERS_ON_RESIZE + + // Set Viewport to window dimensions + glViewport(0, 0, w, h); + +#ifdef RECREATE_CL_AND_SHADERS_ON_RESIZE + InitCL(); + InitShaders(); + + g_interopBuffer = new btOpenCLGLInteropBuffer(g_cxMainContext,g_cqCommandQue,cube_vbo); + clFinish(g_cqCommandQue); + g_interopKernel = btOpenCLUtils::compileCLKernelFromString(g_cxMainContext, interopKernelString, "interopKernel" ); +#endif //RECREATE_CL_AND_SHADERS_ON_RESIZE + +} + +void Keyboard(unsigned char key, int x, int y) +{ + switch (key) + { + case 27: + done = true; + break; + case 'O': + case 'o': + { + m_ortho = !m_ortho; + break; + } + case 'c': + case 'C': + { + useCPU = !useCPU; + if (useCPU) + printf("using CPU\n"); + else + printf("using OpenCL\n"); + break; + } + case 's': + case 'S': + { + printStats = !printStats; + break; + } + case 'k': + case 'K': + { + runOpenCLKernels=!runOpenCLKernels; + break; + } + case 'q': + case 'Q': + exit(0); + default: + break; + } +} + +// Cleanup +void ShutdownRC(void) +{ + glDeleteBuffers(1, &cube_vbo); + glDeleteVertexArrays(1, &cube_vao); +} + +int main(int argc, char* argv[]) +{ + // printf("vertexShader = \n%s\n",vertexShader); + // printf("fragmentShader = \n%s\n",fragmentShader); + + glutInit(&argc, argv); + + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); + + + glutInitWindowSize(m_glutScreenWidth, m_glutScreenHeight); + char buf[1024]; + sprintf(buf,"OpenCL - OpenGL interop, transforms %d cubes on the GPU (use c to toggle CPU/CL)", NUM_OBJECTS); + glutCreateWindow(buf); + + glutReshapeFunc(ChangeSize); + + glutKeyboardFunc(Keyboard); + glutDisplayFunc(RenderScene); + + GLenum err = glewInit(); + if (GLEW_OK != err) + { + /* Problem: glewInit failed, something is seriously wrong. */ + fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); + } + + //ChangeSize(m_glutScreenWidth,m_glutScreenHeight); + + InitCL(); + + + InitShaders(); + + g_interopBuffer = new btOpenCLGLInteropBuffer(g_cxMainContext,g_cqCommandQue,cube_vbo); + clFinish(g_cqCommandQue); + + + g_interopKernel = btOpenCLUtils::compileCLKernelFromString(g_cxMainContext, g_device,interopKernelString, "interopKernel" ); + + glutMainLoop(); + ShutdownRC(); + + return 0; +} diff --git a/Extras/RigidBodyGpuPipeline/opencl/opengl_interop/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/opengl_interop/premake4.lua new file mode 100644 index 0000000..422952b --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/opengl_interop/premake4.lua @@ -0,0 +1,5 @@ + + include "AMD" + include "Intel" +-- include "NVIDIA" + \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Adl.cpp b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Adl.cpp new file mode 100644 index 0000000..fdd5ed3 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Adl.cpp @@ -0,0 +1,19 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#include + +//KernelManager* KernelManager::s_kManager = NULL; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Adl.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Adl.h new file mode 100644 index 0000000..5d51abe --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Adl.h @@ -0,0 +1,235 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#ifndef ADL_H +#define ADL_H + +#pragma warning( disable : 4996 ) +#include +#include +#include + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +namespace adl +{ + +enum DeviceType +{ + TYPE_CL = 0, + TYPE_DX11 = 1, + TYPE_HOST, +}; + + +struct Device; + +struct BufferBase +{ + enum BufferType + { + BUFFER, + + // for dx + BUFFER_CONST, + BUFFER_STAGING, + BUFFER_APPEND, + BUFFER_RAW, + BUFFER_W_COUNTER, + BUFFER_INDEX, + BUFFER_VERTEX, + + // for cl + BUFFER_ZERO_COPY, + + }; +}; + +class DeviceUtils +{ + public: + struct Config + { + enum DeviceType + { + DEVICE_GPU, + DEVICE_CPU, + }; + + // for CL + enum DeviceVendor + { + VD_AMD, + VD_INTEL, + VD_NV, + }; + + Config() : m_type(DEVICE_GPU), m_deviceIdx(0), m_vendor(VD_AMD){} + + DeviceType m_type; + int m_deviceIdx; + DeviceVendor m_vendor; + }; + + __inline + static + int getNDevices( DeviceType type ); + __inline + static Device* allocate( DeviceType type, Config& cfg ); + __inline + static void deallocate( Device* deviceData ); + __inline + static void waitForCompletion( const Device* deviceData ); +}; + +//========================== +// DeviceData +//========================== +struct Kernel; + +struct Device +{ + typedef DeviceUtils::Config Config; + + Device( DeviceType type ) : m_type( type ), m_memoryUsage(0) + { + } + + virtual void* getContext() const { return 0; } + virtual void initialize(const Config& cfg){} + virtual void release(){} + virtual void waitForCompletion() const {} + virtual void getDeviceName( char nameOut[128] ) const {} + virtual Kernel* getKernel(const char* fileName, const char* funcName, const char* option = NULL, const char* src = NULL, bool cacheKernel = true ) const { ADLASSERT(0); return 0;} + virtual unsigned int getUsedMemory() const { return m_memoryUsage; } + + DeviceType m_type; + unsigned int m_memoryUsage; +}; + +//========================== +// Buffer +//========================== + +template +struct HostBuffer; +// overload each deviceDatas +template +struct Buffer : public BufferBase +{ + __inline + Buffer(); + __inline + Buffer(const Device* device, int nElems, BufferType type = BUFFER ); + __inline + virtual ~Buffer(); + + __inline + void setRawPtr( const Device* device, T* ptr, int size, BufferType type = BUFFER ); + __inline + void allocate(const Device* device, int nElems, BufferType type = BUFFER ); + __inline + void write(T* hostSrcPtr, int nElems, int dstOffsetNElems = 0); + __inline + void read(T* hostDstPtr, int nElems, int srcOffsetNElems = 0) const; + __inline + void write(Buffer& src, int nElems); + __inline + void read(Buffer& dst, int nElems) const; +// __inline +// Buffer& operator = (const Buffer& buffer); + __inline + int getSize() const { return m_size; } + + DeviceType getType() const { ADLASSERT( m_device ); return m_device->m_type; } + + + const Device* m_device; + int m_size; + T* m_ptr; + // for DX11 + void* m_uav; + void* m_srv; + bool m_allocated; // todo. move this to a bit +}; + +class BufferUtils +{ +public: + template + __inline + static + typename Buffer* map(const Device* device, const Buffer* in, int copySize = -1); + + template + __inline + static + void unmap( Buffer* native, const Buffer* orig, int copySize = -1 ); +}; + +//========================== +// HostBuffer +//========================== +struct DeviceHost; + +template +struct HostBuffer : public Buffer +{ + __inline + HostBuffer():Buffer(){} + __inline + HostBuffer(const Device* device, int nElems, BufferType type = BUFFER ) : Buffer(device, nElems, type) {} +// HostBuffer(const Device* deviceData, T* rawPtr, int nElems); + + + __inline + T& operator[](int idx); + __inline + const T& operator[](int idx) const; + __inline + T* begin() { return m_ptr; } + + __inline + HostBuffer& operator = (const Buffer& device); +}; + +}; + +#include +#if defined(ADL_ENABLE_CL) + #include +#endif +#if defined(ADL_ENABLE_DX11) + #include +#endif + +#include +#include +#include + + +#include + +#include +#include + +#endif diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Adl.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Adl.inl new file mode 100644 index 0000000..d732e86 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Adl.inl @@ -0,0 +1,344 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +namespace adl +{ + +int DeviceUtils::getNDevices( DeviceType type ) +{ + switch( type ) + { +#if defined(ADL_ENABLE_CL) + case TYPE_CL: + return DeviceCL::getNDevices(); +#endif +#if defined(ADL_ENABLE_DX11) + case TYPE_DX11: + return DeviceDX11::getNDevices(); +#endif + default: + return 1; + }; +} + +Device* DeviceUtils::allocate( DeviceType type, Config& cfg ) +{ + Device* deviceData; + switch( type ) + { +#if defined(ADL_ENABLE_CL) + case TYPE_CL: + deviceData = new DeviceCL(); + break; +#endif +#if defined(ADL_ENABLE_DX11) + case TYPE_DX11: + deviceData = new DeviceDX11(); + break; +#endif + case TYPE_HOST: + deviceData = new DeviceHost(); + break; + default: + ADLASSERT( 0 ); + break; + }; + deviceData->initialize( cfg ); + return deviceData; +} + +void DeviceUtils::deallocate( Device* deviceData ) +{ + ADLASSERT( deviceData->getUsedMemory() == 0 ); + deviceData->release(); + delete deviceData; +} + +void DeviceUtils::waitForCompletion( const Device* deviceData ) +{ + deviceData->waitForCompletion(); +} + +#if defined(ADL_ENABLE_DX11) + #if defined(ADL_ENABLE_CL) + #define SELECT_DEVICEDATA( type, func ) \ + switch( type ) \ + { \ + case TYPE_CL: ((DeviceCL*)m_device)->func; break; \ + case TYPE_DX11: ((DeviceDX11*)m_device)->func; break; \ + case TYPE_HOST: ((DeviceHost*)m_device)->func; break; \ + default: ADLASSERT(0); break; \ + } + + #define SELECT_DEVICEDATA1( deviceData, func ) \ + switch( deviceData->m_type ) \ + { \ + case TYPE_CL: ((DeviceCL*)deviceData)->func; break; \ + case TYPE_DX11: ((DeviceDX11*)deviceData)->func; break; \ + case TYPE_HOST: ((DeviceHost*)deviceData)->func; break; \ + default: ADLASSERT(0); break; \ + } + #else + #define SELECT_DEVICEDATA( type, func ) \ + switch( type ) \ + { \ + case TYPE_DX11: ((DeviceDX11*)m_device)->func; break; \ + case TYPE_HOST: ((DeviceHost*)m_device)->func; break; \ + default: ADLASSERT(0); break; \ + } + + #define SELECT_DEVICEDATA1( deviceData, func ) \ + switch( deviceData->m_type ) \ + { \ + case TYPE_DX11: ((DeviceDX11*)deviceData)->func; break; \ + case TYPE_HOST: ((DeviceHost*)deviceData)->func; break; \ + default: ADLASSERT(0); break; \ + } + #endif +#else + #if defined(ADL_ENABLE_CL) + #define SELECT_DEVICEDATA( type, func ) \ + switch( type ) \ + { \ + case TYPE_CL: ((DeviceCL*)m_device)->func; break; \ + case TYPE_HOST: ((DeviceHost*)m_device)->func; break; \ + default: ADLASSERT(0); break; \ + } + + #define SELECT_DEVICEDATA1( deviceData, func ) \ + switch( deviceData->m_type ) \ + { \ + case TYPE_CL: ((DeviceCL*)deviceData)->func; break; \ + case TYPE_HOST: ((DeviceHost*)deviceData)->func; break; \ + default: ADLASSERT(0); break; \ + } + #else + #define SELECT_DEVICEDATA( type, func ) \ + switch( type ) \ + { \ + case TYPE_HOST: ((DeviceHost*)m_device)->func; break; \ + default: ADLASSERT(0); break; \ + } + + #define SELECT_DEVICEDATA1( deviceData, func ) \ + switch( deviceData->m_type ) \ + { \ + case TYPE_HOST: ((DeviceHost*)deviceData)->func; break; \ + default: ADLASSERT(0); break; \ + } + #endif +#endif + +template +Buffer::Buffer() +{ + m_device = 0; + m_size = 0; + m_ptr = 0; + + m_uav = 0; + m_srv = 0; + + m_allocated = false; +} + +template +Buffer::Buffer(const Device* deviceData, int nElems, BufferType type ) +{ + m_device = 0; + allocate( deviceData, nElems, type ); +} + +template +Buffer::~Buffer() +{ + if( m_allocated ) + { + if( m_device ) + SELECT_DEVICEDATA( m_device->m_type, deallocate( this ) ); + } + + m_device = 0; + m_ptr = 0; + m_size = 0; +} + +template +void Buffer::setRawPtr( const Device* device, T* ptr, int size, BufferType type ) +{ + ADLASSERT( m_device == 0 ); + ADLASSERT( type == BUFFER ); // todo. implement + ADLASSERT( device->m_type != TYPE_DX11 ); // todo. implement set srv, uav + + m_device = device; + m_ptr = ptr; + m_size = size; +} + +template +void Buffer::allocate(const Device* deviceData, int nElems, BufferType type ) +{ + ADLASSERT( m_device == 0 ); + m_device = deviceData; + m_size = 0; + m_ptr = 0; + + m_uav = 0; + m_srv = 0; + + SELECT_DEVICEDATA( m_device->m_type, allocate( this, nElems, type ) ); + m_allocated = true; +} + +template +void Buffer::write(T* hostPtr, int nElems, int offsetNElems) +{ + ADLASSERT( nElems+offsetNElems <= m_size ); + SELECT_DEVICEDATA( m_device->m_type, copy(this, hostPtr, nElems, offsetNElems) ); +} + +template +void Buffer::read(T* hostPtr, int nElems, int offsetNElems) const +{ + SELECT_DEVICEDATA( m_device->m_type, copy(hostPtr,this, nElems, offsetNElems) ); +} + +template +void Buffer::write(Buffer& src, int nElems) +{ + ADLASSERT( nElems <= m_size ); + SELECT_DEVICEDATA( m_device->m_type, copy(this, &src, nElems) ); +} + +template +void Buffer::read(Buffer& dst, int nElems) const +{ + SELECT_DEVICEDATA( m_device->m_type, copy(&dst, this, nElems) ); +} +/* +template +Buffer& Buffer::operator = ( const Buffer& buffer ) +{ +// ADLASSERT( buffer.m_size <= m_size ); + + SELECT_DEVICEDATA( m_device->m_type, copy(this, &buffer, min2( m_size, buffer.m_size) ) ); + + return *this; +} +*/ + +template +__inline +static +typename Buffer* BufferUtils::map(const Device* device, const Buffer* in, int copySize) +{ + Buffer* native; + ADLASSERT( device->m_type == TYPE ); + + if( in->getType() == TYPE ) + native = (Buffer*)in; + else + { + ADLASSERT( copySize <= in->getSize() ); + copySize = (copySize==-1)? in->getSize() : copySize; + + native = new Buffer( device, copySize ); + if( COPY ) + { + if( in->getType() == TYPE_HOST ) + native->write( in->m_ptr, copySize ); + else if( native->getType() == TYPE_HOST ) + { + in->read( native->m_ptr, copySize ); + DeviceUtils::waitForCompletion( in->m_device ); + } + else + { + T* tmp = new T[copySize]; + in->read( tmp, copySize ); + DeviceUtils::waitForCompletion( in->m_device ); + native->write( tmp, copySize ); + DeviceUtils::waitForCompletion( native->m_device ); + delete [] tmp; + } + } + } + return native; +} + +template +__inline +static +void BufferUtils::unmap( Buffer* native, const Buffer* orig, int copySize ) +{ + if( native != orig ) + { + if( COPY ) + { + copySize = (copySize==-1)? orig->getSize() : copySize; + ADLASSERT( copySize <= orig->getSize() ); + if( orig->getType() == TYPE_HOST ) + { + native->read( orig->m_ptr, copySize ); + DeviceUtils::waitForCompletion( native->m_device ); + } + else if( native->getType() == TYPE_HOST ) + { + Buffer* dst = (Buffer*)orig; + dst->write( native->m_ptr, copySize ); + DeviceUtils::waitForCompletion( dst->m_device ); + } + else + { + T* tmp = new T[copySize]; + native->read( tmp, copySize ); + DeviceUtils::waitForCompletion( native->m_device ); + Buffer* dst = (Buffer*)orig; + dst->write( tmp, copySize ); + DeviceUtils::waitForCompletion( dst->m_device ); + delete [] tmp; + } + } + delete native; + } +} + + +template +T& HostBuffer::operator[](int idx) +{ + return m_ptr[idx]; +} + +template +const T& HostBuffer::operator[](int idx) const +{ + return m_ptr[idx]; +} + +template +HostBuffer& HostBuffer::operator = ( const Buffer& device ) +{ + ADLASSERT( device.m_size <= m_size ); + + SELECT_DEVICEDATA1( device.m_device, copy( m_ptr, &device, device.m_size ) ); + + return *this; +} + +#undef SELECT_DEVICEDATA + +}; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlConfig.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlConfig.h new file mode 100644 index 0000000..141c874 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlConfig.h @@ -0,0 +1,27 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + + +//ADL_ENABLE_CL and ADL_ENABLE_DX11 can be set in the build system using C/C++ preprocessor defines +//#define ADL_ENABLE_CL +//#define ADL_ENABLE_DX11 + +//#define ADL_CL_FORCE_UNCACHE_KERNEL +#define ADL_CL_DUMP_MEMORY_LOG + +//load the kernels from string instead of loading them from file +#define ADL_LOAD_KERNEL_FROM_STRING +#define ADL_DUMP_DX11_ERROR diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlError.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlError.h new file mode 100644 index 0000000..6d08e95 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlError.h @@ -0,0 +1,80 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#ifndef ADL_ERROR_H +#define ADL_ERROR_H + +#if defined(ADL_DUMP_DX11_ERROR) + #include +#endif +#ifdef _DEBUG + #include + #include + #include +#endif + + +namespace adl +{ + +#ifdef _DEBUG + #define ADLASSERT(x) if(!(x)){__debugbreak(); } +#else + #define ADLASSERT(x) if(x){} +#endif + +#ifdef _DEBUG + #define COMPILE_TIME_ASSERT(x) {int compileTimeAssertFailed[x]; compileTimeAssertFailed[0];} +#else + #define COMPILE_TIME_ASSERT(x) +#endif + +#ifdef _DEBUG + __inline + void debugPrintf(const char *fmt, ...) + { + va_list arg; + va_start(arg, fmt); +#if defined(ADL_DUMP_DX11_ERROR) + const int size = 1024*10; + char buf[size]; + vsprintf_s( buf, size, fmt, arg ); +#ifdef UNICODE + WCHAR wbuf[size]; + int sizeWide = MultiByteToWideChar(0,0,buf,-1,wbuf,0); + MultiByteToWideChar(0,0,buf,-1,wbuf,sizeWide); + +// swprintf_s( wbuf, 256, L"%s", buf ); + OutputDebugString( wbuf ); +#else + OutputDebugString( buf ); +#endif +#else + vprintf(fmt, arg); +#endif + va_end(arg); + } +#else + __inline + void debugPrintf(const char *fmt, ...) + { + } +#endif + +}; + +#endif + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlKernel.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlKernel.h new file mode 100644 index 0000000..1a785c1 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlKernel.h @@ -0,0 +1,142 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#ifndef ADL_KERNEL_H +#define ADL_KERNEL_H + +#include +#include +#include + +namespace adl +{ + +//========================== +// Kernel +//========================== +struct Kernel +{ + DeviceType m_type; + void* m_kernel; +}; + +//========================== +// KernelManager +//========================== +class KernelManager +{ + public: + typedef std::map KMap; + + __inline + ~KernelManager(); + + __inline +// static + Kernel* query(const Device* dd, const char* fileName, const char* funcName, const char* option = NULL, const char* src = NULL, + bool cacheKernel = true); + + public: + KMap m_map; +}; + +//========================== +// Launcher +//========================== +class Launcher +{ + public: + struct BufferInfo + { + BufferInfo(){} + template + BufferInfo(Buffer* buff, bool isReadOnly = false): m_buffer(buff), m_isReadOnly(isReadOnly){} + + void* m_buffer; + bool m_isReadOnly; + }; + + __inline + Launcher(const Device* dd, char* fileName, char* funcName, char* option = NULL); + __inline + Launcher(const Device* dd, Kernel* kernel); + __inline + void setBuffers( BufferInfo* buffInfo, int n ); + template + __inline + void setConst( Buffer& constBuff, const T& consts ); + __inline + void launch1D( int numThreads, int localSize = 64 ); + __inline + void launch2D( int numThreadsX, int numThreadsY, int localSizeX = 8, int localSizeY = 8 ); + + public: + enum + { + CONST_BUFFER_SIZE = 512, + }; + + const Device* m_deviceData; + Kernel* m_kernel; + int m_idx; + int m_idxRw; +}; + +template +class KernelBuilder +{ + public: + + __inline + KernelBuilder(): m_ptr(0){} + + __inline + void setFromFile( const Device* deviceData, const char* fileName, const char* option = NULL, bool addExtension = false, + bool cacheKernel = true); + + __inline + void setFromSrc( const Device* deviceData, const char* src, const char* option = NULL ); + + __inline + void setFromSrcCached( const Device* deviceData, const char* src, const char* fileName, const char* option ); + + + __inline + void createKernel( const char* funcName, Kernel& kernelOut ); + + __inline + ~KernelBuilder(); + // todo. implemement in kernel destructor? + __inline + static void deleteKernel( Kernel& kernel ); + + private: + enum + { + MAX_PATH_LENGTH = 260, + }; + const Device* m_deviceData; +#ifdef UNICODE + wchar_t m_path[MAX_PATH_LENGTH]; +#else + char m_path[MAX_PATH_LENGTH]; +#endif + void* m_ptr; +}; + +}; + +#endif //ADL_KERNEL_H diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlKernel.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlKernel.inl new file mode 100644 index 0000000..9752b8c --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlKernel.inl @@ -0,0 +1,223 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + + +#ifdef ADL_ENABLE_CL + #include +#endif +#ifdef ADL_ENABLE_DX11 + #include +#endif + +namespace adl +{ + +//========================== +// KernelManager +//========================== +Kernel* KernelManager::query(const Device* dd, const char* fileName, const char* funcName, const char* option, const char* src, + bool cacheKernel) +{ + printf("compiling kernel %s",funcName); + const int charSize = 1024*2; + KernelManager* s_kManager = this; + + char fullFineName[charSize]; + switch( dd->m_type ) + { + case TYPE_CL: +#if defined(ADL_ENABLE_CL) + sprintf_s(fullFineName,charSize,"%s.cl", fileName); + break; +#endif +#if defined(ADL_ENABLE_DX11) + case TYPE_DX11: + sprintf_s(fullFineName,charSize,"%s.hlsl", fileName); + break; +#endif + default: + ADLASSERT(0); + break; + }; + + char mapName[charSize]; + { + if( option ) + sprintf_s(mapName, charSize, "%d%s%s%s", (int)dd->getContext(), fullFineName, funcName, option); + else + sprintf_s(mapName, charSize, "%d%s%s", (int)dd->getContext(), fullFineName, funcName); + } + + std::string str(mapName); + + KMap::iterator iter = s_kManager->m_map.find( str ); + + Kernel* kernelOut; + if( iter == s_kManager->m_map.end() ) + { + kernelOut = new Kernel(); + + switch( dd->m_type ) + { +#if defined(ADL_ENABLE_CL) + case TYPE_CL: + { + KernelBuilder builder; + if( src ) + if (cacheKernel) + { + builder.setFromSrcCached( dd, src, fileName, option ); + } else + { + builder.setFromSrc( dd, src, option ); + } + else + builder.setFromFile( dd, fileName, option, true, cacheKernel ); + builder.createKernel( funcName, *kernelOut ); + } + break; +#endif +#if defined(ADL_ENABLE_DX11) + case TYPE_DX11: + { + KernelBuilder builder; + if( src ) + builder.setFromSrc( dd, src, option ); + else + builder.setFromFile( dd, fileName, option, true, cacheKernel ); + builder.createKernel( funcName, *kernelOut ); + } + break; +#endif + default: + ADLASSERT(0); + break; + }; + s_kManager->m_map.insert( KMap::value_type(str,kernelOut) ); + } + else + { + kernelOut = iter->second; + } + + printf(" ready\n"); + return kernelOut; +} + +KernelManager::~KernelManager() +{ + for(KMap::iterator iter = m_map.begin(); iter != m_map.end(); iter++) + { + Kernel* k = iter->second; + switch( k->m_type ) + { +#if defined(ADL_ENABLE_CL) + case TYPE_CL: + KernelBuilder::deleteKernel( *k ); + delete k; + break; +#endif +#if defined(ADL_ENABLE_DX11) + case TYPE_DX11: + KernelBuilder::deleteKernel( *k ); + delete k; + break; +#endif + default: + ADLASSERT(0); + break; + }; + } +} + +//========================== +// Launcher +//========================== + +#if defined(ADL_ENABLE_DX11) + #if defined(ADL_ENABLE_CL) + #define SELECT_LAUNCHER( type, func ) \ + switch( type ) \ + { \ + case TYPE_CL: LauncherCL::func; break; \ + case TYPE_DX11: LauncherDX11::func; break; \ + default: ADLASSERT(0); break; \ + }; + #else + #define SELECT_LAUNCHER( type, func ) \ + switch( type ) \ + { \ + case TYPE_DX11: LauncherDX11::func; break; \ + default: ADLASSERT(0); break; \ + }; + #endif +#else + #if defined(ADL_ENABLE_CL) + #define SELECT_LAUNCHER( type, func ) \ + switch( type ) \ + { \ + case TYPE_CL: LauncherCL::func; break; \ + default: ADLASSERT(0); break; \ + }; + #else + #define SELECT_LAUNCHER( type, func ) \ + switch( type ) \ + { \ + default: ADLASSERT(0); break; \ + }; + #endif +#endif + +Launcher::Launcher(const Device *dd, char *fileName, char *funcName, char *option) +{ + m_kernel = dd->getKernel( fileName, funcName, option ); + m_deviceData = dd; + m_idx = 0; + m_idxRw = 0; +} + +Launcher::Launcher(const Device* dd, Kernel* kernel) +{ + m_kernel = kernel; + m_deviceData = dd; + m_idx = 0; + m_idxRw = 0; +} + +void Launcher::setBuffers( BufferInfo* buffInfo, int n ) +{ + SELECT_LAUNCHER( m_deviceData->m_type, setBuffers( this, buffInfo, n ) ); +} + +template +void Launcher::setConst( Buffer& constBuff, const T& consts ) +{ + SELECT_LAUNCHER( m_deviceData->m_type, setConst( this, constBuff, consts ) ); +} + +void Launcher::launch1D( int numThreads, int localSize ) +{ + SELECT_LAUNCHER( m_deviceData->m_type, launch2D( this, numThreads, 1, localSize, 1 ) ); +} + +void Launcher::launch2D( int numThreadsX, int numThreadsY, int localSizeX, int localSizeY ) +{ + SELECT_LAUNCHER( m_deviceData->m_type, launch2D( this, numThreadsX, numThreadsY, localSizeX, localSizeY ) ); +} + +#undef SELECT_LAUNCHER + +}; \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlStopwatch.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlStopwatch.h new file mode 100644 index 0000000..034f044 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlStopwatch.h @@ -0,0 +1,81 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + + +#include + +namespace adl +{ + +struct StopwatchBase +{ + __inline + StopwatchBase(): m_device(0){} + __inline + StopwatchBase( const Device* deviceData ){ init(deviceData); } + __inline + virtual ~StopwatchBase(){} + + __inline + virtual void init( const Device* deviceData ) = 0; + __inline + virtual void start() = 0; + __inline + virtual void split() = 0; + __inline + virtual void stop() = 0; + __inline + virtual float getMs(int index=0) = 0; + __inline + virtual void getMs( float* times, int capacity ) = 0; + __inline + int getNIntervals() const{ return m_idx-1;} + + enum + { + CAPACITY = 64, + }; + + const Device* m_device; + int m_idx; +}; + +struct Stopwatch +{ + __inline + Stopwatch( const Device* deviceData = NULL ) { m_impl=0; if(deviceData) init(deviceData);} + __inline + ~Stopwatch(); + + __inline + void init( const Device* deviceData ); + __inline + void start(){if(!m_impl) init(0); m_impl->start();} + __inline + void split(){m_impl->split();} + __inline + void stop(){m_impl->stop();} + __inline + float getMs(){ return m_impl->getMs();} + __inline + void getMs( float* times, int capacity ){m_impl->getMs(times, capacity);} + __inline + int getNIntervals() const{return m_impl->getNIntervals();} + + StopwatchBase* m_impl; +}; + +}; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlStopwatch.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlStopwatch.inl new file mode 100644 index 0000000..a825ec2 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/AdlStopwatch.inl @@ -0,0 +1,59 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +namespace adl +{ + +void Stopwatch::init( const Device* deviceData ) +{ + ADLASSERT( m_impl == 0 ); + + if( deviceData ) + { + switch( deviceData->m_type ) + { +#if defined(ADL_ENABLE_CL) + case TYPE_CL: + m_impl = new StopwatchHost;//StopwatchCL + break; +#endif +#if defined(ADL_ENABLE_DX11) + case TYPE_DX11: + m_impl = new StopwatchHost;//StopwatchDX11; + break; +#endif + case TYPE_HOST: + m_impl = new StopwatchHost; + break; + default: + ADLASSERT(0); + break; + }; + } + else + { + m_impl = new StopwatchHost; + } + m_impl->init( deviceData ); +} + +Stopwatch::~Stopwatch() +{ + if( m_impl == 0 ) return; + delete m_impl; +} + +}; \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/CL/AdlCL.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/CL/AdlCL.inl new file mode 100644 index 0000000..1b603a9 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/CL/AdlCL.inl @@ -0,0 +1,384 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + + +#pragma comment(lib,"OpenCL.lib") +#include +#include +#include + +namespace adl +{ + +struct DeviceCL : public Device +{ + typedef DeviceUtils::Config Config; + + + __inline + DeviceCL() : Device( TYPE_CL ), m_kernelManager(0){} + __inline + void* getContext() const { return m_context; } + __inline + void initialize(const Config& cfg); + __inline + void release(); + + template + __inline + void allocate(Buffer* buf, int nElems, BufferBase::BufferType type); + + template + __inline + void deallocate(Buffer* buf); + + template + __inline + void copy(Buffer* dst, const Buffer* src, int nElems,int srcOffsetNElems = 0,int dstOffsetNElems = 0); + + template + __inline + void copy(T* dst, const Buffer* src, int nElems, int srcOffsetNElems = 0); + + template + __inline + void copy(Buffer* dst, const T* src, int nElems, int dstOffsetNElems = 0); + + __inline + void waitForCompletion() const; + + __inline + void getDeviceName( char nameOut[128] ) const; + + __inline + static + int getNDevices(); + + __inline + Kernel* getKernel(const char* fileName, const char* funcName, const char* option = NULL, const char* src = NULL, bool cacheKernel = true )const; + + + enum + { + MAX_NUM_DEVICES = 6, + }; + + cl_context m_context; + cl_command_queue m_commandQueue; + + cl_device_id m_deviceIdx; + + KernelManager* m_kernelManager; +}; + +//=== +//=== + +void DeviceCL::initialize(const Config& cfg) +{ +// DeviceUtils::create( cfg, (DeviceCL*)this ); + { +// dd = new DeviceCL(); + + DeviceCL* deviceData = (DeviceCL*)this; + +// cl_device_type deviceType = (driverType == DRIVER_HARDWARE)? CL_DEVICE_TYPE_GPU:CL_DEVICE_TYPE_CPU; + cl_device_type deviceType = (cfg.m_type== Config::DEVICE_GPU)? CL_DEVICE_TYPE_GPU: CL_DEVICE_TYPE_CPU; +// int numContextQueuePairsToCreate = 1; + bool enableProfiling = false; +#ifdef _DEBUG + enableProfiling = true; +#endif + cl_int status; + + cl_platform_id platform; + { + cl_uint nPlatforms = 0; + status = clGetPlatformIDs(0, NULL, &nPlatforms); + ADLASSERT( status == CL_SUCCESS ); + + cl_platform_id pIdx[5]; + status = clGetPlatformIDs(nPlatforms, pIdx, NULL); + ADLASSERT( status == CL_SUCCESS ); + + cl_uint atiIdx = -1; + cl_uint intelIdx = -1; + cl_uint nvIdx = -1; + + for(cl_uint i=0; i0) + { + if( strcmp( buff, "NVIDIA Corporation" )==0 ) nvIdx = i; + if( strcmp( buff, "Advanced Micro Devices, Inc." )==0 ) atiIdx = i; + if( strcmp( buff, "Intel(R) Corporation" )==0 ) intelIdx = i; + } + } + + if( deviceType == CL_DEVICE_TYPE_GPU ) + { + switch( cfg.m_vendor ) + { + case DeviceUtils::Config::VD_AMD: + if( atiIdx == -1 && nvIdx != -1 ) goto USE_NV_GPU; +USE_AMD_GPU: + ADLASSERT(atiIdx != -1 ); + platform = pIdx[atiIdx]; + break; + case DeviceUtils::Config::VD_NV: + if( atiIdx != -1 && nvIdx == -1 ) goto USE_AMD_GPU; +USE_NV_GPU: + ADLASSERT(nvIdx != -1 ); + platform = pIdx[nvIdx]; + break; + default: + ADLASSERT(0); + break; + }; + } + else if( deviceType == CL_DEVICE_TYPE_CPU ) + { + switch( cfg.m_vendor ) + { + case DeviceUtils::Config::VD_AMD: + ADLASSERT(atiIdx != -1 ); + platform = pIdx[atiIdx]; + break; + case DeviceUtils::Config::VD_INTEL: + ADLASSERT(intelIdx != -1 ); + platform = pIdx[intelIdx]; + break; + default: + ADLASSERT(0); + break; + }; + } + } + + cl_uint numDevice; + status = clGetDeviceIDs( platform, deviceType, 0, NULL, &numDevice ); + +// ADLASSERT( cfg.m_deviceIdx < (int)numDevice ); + + debugPrintf("CL: %d %s Devices ", numDevice, (deviceType==CL_DEVICE_TYPE_GPU)? "GPU":"CPU"); + +// numContextQueuePairsToCreate = min( (int)numDevice, numContextQueuePairsToCreate ); +// numContextQueuePairsToCreate = ( (int)numDevice < numContextQueuePairsToCreate )? numDevice : numContextQueuePairsToCreate; + + cl_device_id deviceIds[ MAX_NUM_DEVICES ]; + + status = clGetDeviceIDs( platform, deviceType, numDevice, deviceIds, NULL ); + ADLASSERT( status == CL_SUCCESS ); + + { int i = min( (int)numDevice-1, cfg.m_deviceIdx ); + m_deviceIdx = deviceIds[i]; + deviceData->m_context = clCreateContext( NULL, 1, &deviceData->m_deviceIdx, NULL, NULL, &status ); + ADLASSERT( status == CL_SUCCESS ); + + char buff[512]; + status = clGetDeviceInfo( deviceData->m_deviceIdx, CL_DEVICE_NAME, sizeof(buff), &buff, NULL ); + ADLASSERT( status == CL_SUCCESS ); + + debugPrintf("[%s]\n", buff); + + deviceData->m_commandQueue = clCreateCommandQueue( deviceData->m_context, deviceData->m_deviceIdx, (enableProfiling)?CL_QUEUE_PROFILING_ENABLE:NULL, NULL ); + + ADLASSERT( status == CL_SUCCESS ); + + // status = clSetCommandQueueProperty( commandQueue, CL_QUEUE_PROFILING_ENABLE, CL_TRUE, 0 ); + // CLASSERT( status == CL_SUCCESS ); + + if(0) + { + cl_bool image_support; + clGetDeviceInfo(deviceData->m_deviceIdx, CL_DEVICE_IMAGE_SUPPORT, sizeof(image_support), &image_support, NULL); + debugPrintf(" CL_DEVICE_IMAGE_SUPPORT : %s\n", image_support?"Yes":"No"); + } + } + } + + m_kernelManager = new KernelManager; +} + +void DeviceCL::release() +{ + clReleaseCommandQueue( m_commandQueue ); + clReleaseContext( m_context ); + + if( m_kernelManager ) delete m_kernelManager; +} + +template +void DeviceCL::allocate(Buffer* buf, int nElems, BufferBase::BufferType type) +{ + buf->m_device = this; + buf->m_size = nElems; + buf->m_ptr = 0; + + if( type == BufferBase::BUFFER_CONST ) return; + +#if defined(ADL_CL_DUMP_MEMORY_LOG) + char deviceName[256]; + getDeviceName( deviceName ); + printf( "adlCLMemoryLog %s : %3.2fMB Allocation: %3.2fKB ", deviceName, m_memoryUsage/1024.f/1024.f, sizeof(T)*nElems/1024.f ); + fflush( stdout ); +#endif + + int sz=sizeof(T)*nElems; + + cl_int status = 0; + if( type == BufferBase::BUFFER_ZERO_COPY ) + buf->m_ptr = (T*)clCreateBuffer( m_context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, sz, 0, &status ); + else if( type == BufferBase::BUFFER_RAW ) + buf->m_ptr = (T*)clCreateBuffer( m_context, CL_MEM_WRITE_ONLY, sz, 0, &status ); + else + buf->m_ptr = (T*)clCreateBuffer( m_context, CL_MEM_READ_WRITE, sz, 0, &status ); + + m_memoryUsage += buf->m_size*sizeof(T); +#if defined(ADL_CL_DUMP_MEMORY_LOG) + printf( "%s\n", (status==CL_SUCCESS)? "Succeed": "Failed" ); + fflush( stdout ); +#endif + ADLASSERT( status == CL_SUCCESS ); +} + +template +void DeviceCL::deallocate(Buffer* buf) +{ + if( buf->m_ptr ) + { + m_memoryUsage -= buf->m_size*sizeof(T); + clReleaseMemObject( (cl_mem)buf->m_ptr ); + } + buf->m_device = 0; + buf->m_size = 0; + buf->m_ptr = 0; +} + +template +void DeviceCL::copy(Buffer* dst, const Buffer* src, int nElems,int srcOffsetNElems,int dstOffsetNElems ) +{ + if( dst->m_device->m_type == TYPE_CL && src->m_device->m_type == TYPE_CL ) + { + cl_int status = 0; + status = clEnqueueCopyBuffer( m_commandQueue, (cl_mem)src->m_ptr, (cl_mem)dst->m_ptr, sizeof(T)*srcOffsetNElems, sizeof(T)*dstOffsetNElems, sizeof(T)*nElems, 0, 0, 0 ); + ADLASSERT( status == CL_SUCCESS ); + } + else if( src->m_device->m_type == TYPE_HOST ) + { + ADLASSERT( dst->getType() == TYPE_CL ); + dst->write( src->m_ptr, nElems ); + } + else if( dst->m_device->m_type == TYPE_HOST ) + { + ADLASSERT( src->getType() == TYPE_CL ); + src->read( dst->m_ptr, nElems ); + } + else + { + ADLASSERT( 0 ); + } +} + +template +void DeviceCL::copy(T* dst, const Buffer* src, int nElems, int srcOffsetNElems ) +{ + cl_int status = 0; + status = clEnqueueReadBuffer( m_commandQueue, (cl_mem)src->m_ptr, 0, sizeof(T)*srcOffsetNElems, sizeof(T)*nElems, + dst, 0,0,0 ); + ADLASSERT( status == CL_SUCCESS ); +} + +template +void DeviceCL::copy(Buffer* dst, const T* src, int nElems, int dstOffsetNElems ) +{ + cl_int status = 0; + int sz=sizeof(T)*nElems; + status = clEnqueueWriteBuffer( m_commandQueue, (cl_mem)dst->m_ptr, 0, sizeof(T)*dstOffsetNElems, sz, + src, 0,0,0 ); + ADLASSERT( status == CL_SUCCESS ); +} + +void DeviceCL::waitForCompletion() const +{ + clFinish( m_commandQueue ); +} + +int DeviceCL::getNDevices() +{ + cl_device_type deviceType = CL_DEVICE_TYPE_GPU; + cl_int status; + + cl_platform_id platform; + { + cl_uint nPlatforms = 0; + status = clGetPlatformIDs(0, NULL, &nPlatforms); + ADLASSERT( status == CL_SUCCESS ); + + cl_platform_id pIdx[5]; + status = clGetPlatformIDs(nPlatforms, pIdx, NULL); + ADLASSERT( status == CL_SUCCESS ); + + cl_uint nvIdx = -1; + cl_uint atiIdx = -1; + for(cl_uint i=0; iquery( this, fileName, funcName, option, src, cacheKernel ); +} + +}; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/CL/AdlKernelUtilsCL.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/CL/AdlKernelUtilsCL.inl new file mode 100644 index 0000000..513478a --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/CL/AdlKernelUtilsCL.inl @@ -0,0 +1,541 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + + + + +namespace adl +{ + +struct KernelCL : public Kernel +{ + cl_kernel& getKernel() { return (cl_kernel&)m_kernel; } +}; + +static const char* strip(const char* name, const char* pattern) +{ + size_t const patlen = strlen(pattern); + size_t patcnt = 0; + const char * oriptr; + const char * patloc; + // find how many times the pattern occurs in the original string + for (oriptr = name; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen) + { + patcnt++; + } + return oriptr; +} + +static bool isFileUpToDate(const char* binaryFileName,const char* srcFileName) + +{ + bool fileUpToDate = false; + + bool binaryFileValid=false; + FILETIME modtimeBinary; + + int nameLength = (int)strlen(binaryFileName)+1; +#ifdef UNICODE + WCHAR* fName = new WCHAR[nameLength]; + MultiByteToWideChar(CP_ACP,0,binaryFileName,-1, fName, nameLength); + HANDLE binaryFileHandle = CreateFile(fName,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); + delete [] fName; +#else + HANDLE binaryFileHandle = CreateFile(binaryFileName,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); +#endif + if (binaryFileHandle ==INVALID_HANDLE_VALUE) + { + DWORD errorCode; + errorCode = GetLastError(); + switch (errorCode) + { + case ERROR_FILE_NOT_FOUND: + { + debugPrintf("\nCached file not found %s\n", binaryFileName); + break; + } + case ERROR_PATH_NOT_FOUND: + { + debugPrintf("\nCached file path not found %s\n", binaryFileName); + break; + } + default: + { + debugPrintf("\nFailed reading cached file with errorCode = %d\n", errorCode); + } + } + } else + { + if (GetFileTime(binaryFileHandle, NULL, NULL, &modtimeBinary)==0) + { + DWORD errorCode; + errorCode = GetLastError(); + debugPrintf("\nGetFileTime errorCode = %d\n", errorCode); + } else + { + binaryFileValid = true; + } + CloseHandle(binaryFileHandle); + } + + if (binaryFileValid) + { +#ifdef UNICODE + int nameLength = (int)strlen(srcFileName)+1; + WCHAR* fName = new WCHAR[nameLength]; + MultiByteToWideChar(CP_ACP,0,srcFileName,-1, fName, nameLength); + HANDLE srcFileHandle = CreateFile(fName,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); + delete [] fName; +#else + HANDLE srcFileHandle = CreateFile(srcFileName,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); +#endif + if (srcFileHandle!=INVALID_HANDLE_VALUE) + { + FILETIME modtimeSrc; + if (GetFileTime(srcFileHandle, NULL, NULL, &modtimeSrc)==0) + { + DWORD errorCode; + errorCode = GetLastError(); + debugPrintf("\nGetFileTime errorCode = %d\n", errorCode); + } + if ( ( modtimeSrc.dwHighDateTime < modtimeBinary.dwHighDateTime) + ||(( modtimeSrc.dwHighDateTime == modtimeBinary.dwHighDateTime)&&(modtimeSrc.dwLowDateTime <= modtimeBinary.dwLowDateTime))) + { + fileUpToDate=true; + } else + { + debugPrintf("\nCached binary file found (%s), but out-of-date\n",binaryFileName); + } + CloseHandle(srcFileHandle); + } + else + { +#ifdef _DEBUG + DWORD errorCode; + errorCode = GetLastError(); + switch (errorCode) + { + case ERROR_FILE_NOT_FOUND: + { + debugPrintf("\nSrc file not found %s\n", srcFileName); + break; + } + case ERROR_PATH_NOT_FOUND: + { + debugPrintf("\nSrc path not found %s\n", srcFileName); + break; + } + default: + { + debugPrintf("\nnSrc file reading errorCode = %d\n", errorCode); + } + } + ADLASSERT(0); +#else + //if we cannot find the source, assume it is OK in release builds + fileUpToDate = true; +#endif + } + } + + + return fileUpToDate; +} + +template<> +void KernelBuilder::setFromFile( const Device* deviceData, const char* fileName, const char* option, bool addExtension, + bool cacheKernel) +{ + m_deviceData = deviceData; + + char fileNameWithExtension[256]; + + if( addExtension ) + sprintf_s( fileNameWithExtension, "%s.cl", fileName ); + else + sprintf_s( fileNameWithExtension, "%s", fileName ); + + class File + { + public: + __inline + bool open(const char* fileNameWithExtension) + { + size_t size; + char* str; + + // Open file stream + std::fstream f(fileNameWithExtension, (std::fstream::in | std::fstream::binary)); + + // Check if we have opened file stream + if (f.is_open()) { + size_t sizeFile; + // Find the stream size + f.seekg(0, std::fstream::end); + size = sizeFile = (size_t)f.tellg(); + f.seekg(0, std::fstream::beg); + + str = new char[size + 1]; + if (!str) { + f.close(); + return NULL; + } + + // Read file + f.read(str, sizeFile); + f.close(); + str[size] = '\0'; + + m_source = str; + + delete[] str; + + return true; + } + + return false; + } + const std::string& getSource() const {return m_source;} + + private: + std::string m_source; + }; + + cl_program& program = (cl_program&)m_ptr; + cl_int status = 0; + + bool cacheBinary = cacheKernel; +#if defined(ADL_CL_FORCE_UNCACHE_KERNEL) + cacheBinary = false; +#endif + + char binaryFileName[512]; + { + char deviceName[256]; + deviceData->getDeviceName(deviceName); + char driverVersion[256]; + const DeviceCL* dd = (const DeviceCL*) deviceData; + clGetDeviceInfo(dd->m_deviceIdx, CL_DRIVER_VERSION, 256, &driverVersion, NULL); + const char* strippedFileName = strip(fileName,"\\"); + strippedFileName = strip(strippedFileName,"/"); + + sprintf_s(binaryFileName,"cache/%s.%s.%s.bin",strippedFileName, deviceName,driverVersion ); + } + + bool upToDate = isFileUpToDate(binaryFileName,fileNameWithExtension); + + if( cacheBinary && upToDate) + { + FILE* file = fopen(binaryFileName, "rb"); + + if( file ) + { + fseek( file, 0L, SEEK_END ); + size_t binarySize = ftell( file ); + + rewind( file ); + char* binary = new char[binarySize]; + fread( binary, sizeof(char), binarySize, file ); + fclose( file ); + + if (binarySize) + { + const DeviceCL* dd = (const DeviceCL*) deviceData; + program = clCreateProgramWithBinary( dd->m_context, 1, &dd->m_deviceIdx, &binarySize, (const unsigned char**)&binary, 0, &status ); + ADLASSERT( status == CL_SUCCESS ); + status = clBuildProgram( program, 1, &dd->m_deviceIdx, option, 0, 0 ); + ADLASSERT( status == CL_SUCCESS ); + if( status != CL_SUCCESS ) + { + char *build_log; + size_t ret_val_size; + clGetProgramBuildInfo(program, dd->m_deviceIdx, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size); + build_log = new char[ret_val_size+1]; + clGetProgramBuildInfo(program, dd->m_deviceIdx, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL); + + build_log[ret_val_size] = '\0'; + + debugPrintf("%s\n", build_log); + + delete build_log; + ADLASSERT(0); + } + + } + } + } + if( !m_ptr ) + { + File kernelFile; + ADLASSERT( kernelFile.open( fileNameWithExtension ) ); + const char* source = kernelFile.getSource().c_str(); + setFromSrc( m_deviceData, source, option ); + + if( cacheBinary ) + { // write to binary + size_t binarySize; + status = clGetProgramInfo( program, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &binarySize, 0 ); + ADLASSERT( status == CL_SUCCESS ); + + char* binary = new char[binarySize]; + + status = clGetProgramInfo( program, CL_PROGRAM_BINARIES, sizeof(char*), &binary, 0 ); + ADLASSERT( status == CL_SUCCESS ); + + { + FILE* file = fopen(binaryFileName, "wb"); + if (file) + { + fwrite( binary, sizeof(char), binarySize, file ); + fclose( file ); + } + } + + delete [] binary; + } + } +} + + + +template<> +void KernelBuilder::setFromSrcCached( const Device* deviceData, const char* src, const char* fileName, const char* option ) +{ + m_deviceData = deviceData; + + bool cacheBinary = true; + cl_program& program = (cl_program&)m_ptr; + cl_int status = 0; + + char binaryFileName[512]; + { + char deviceName[256]; + deviceData->getDeviceName(deviceName); + char driverVersion[256]; + const DeviceCL* dd = (const DeviceCL*) deviceData; + clGetDeviceInfo(dd->m_deviceIdx, CL_DRIVER_VERSION, 256, &driverVersion, NULL); + + const char* strippedFileName = strip(fileName,"\\"); + strippedFileName = strip(strippedFileName,"/"); + + sprintf_s(binaryFileName,"cache/%s.%s.%s.bin",strippedFileName, deviceName,driverVersion ); + } + + + char fileNameWithExtension[256]; + sprintf_s(fileNameWithExtension,"%s.cl",fileName, ".cl"); + + bool upToDate = isFileUpToDate(binaryFileName,fileNameWithExtension); + + + if( cacheBinary ) + { + + bool fileUpToDate = isFileUpToDate(binaryFileName,fileNameWithExtension); + + if( fileUpToDate) + { + FILE* file = fopen(binaryFileName, "rb"); + if (file) + { + fseek( file, 0L, SEEK_END ); + size_t binarySize = ftell( file ); + rewind( file ); + char* binary = new char[binarySize]; + fread( binary, sizeof(char), binarySize, file ); + fclose( file ); + + const DeviceCL* dd = (const DeviceCL*) deviceData; + program = clCreateProgramWithBinary( dd->m_context, 1, &dd->m_deviceIdx, &binarySize, (const unsigned char**)&binary, 0, &status ); + ADLASSERT( status == CL_SUCCESS ); + status = clBuildProgram( program, 1, &dd->m_deviceIdx, option, 0, 0 ); + ADLASSERT( status == CL_SUCCESS ); + + if( status != CL_SUCCESS ) + { + char *build_log; + size_t ret_val_size; + clGetProgramBuildInfo(program, dd->m_deviceIdx, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size); + build_log = new char[ret_val_size+1]; + clGetProgramBuildInfo(program, dd->m_deviceIdx, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL); + + build_log[ret_val_size] = '\0'; + + debugPrintf("%s\n", build_log); + + delete build_log; + ADLASSERT(0); + } + delete[] binary; + } + } + } + + + if( !m_ptr ) + { + + setFromSrc( deviceData, src, option ); + + if( cacheBinary ) + { // write to binary + cl_uint numAssociatedDevices; + status = clGetProgramInfo( program, CL_PROGRAM_NUM_DEVICES, sizeof(cl_uint), &numAssociatedDevices, 0 ); + ADLASSERT( status == CL_SUCCESS ); + if (numAssociatedDevices==1) + { + + + size_t binarySize; + status = clGetProgramInfo( program, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &binarySize, 0 ); + ADLASSERT( status == CL_SUCCESS ); + + char* binary = new char[binarySize]; + + status = clGetProgramInfo( program, CL_PROGRAM_BINARIES, sizeof(char*), &binary, 0 ); + ADLASSERT( status == CL_SUCCESS ); + + { + FILE* file = fopen(binaryFileName, "wb"); + if (file) + { + fwrite( binary, sizeof(char), binarySize, file ); + fclose( file ); + } + } + + delete [] binary; + } + } + } +} + + +template<> +void KernelBuilder::setFromSrc( const Device* deviceData, const char* src, const char* option ) +{ + ADLASSERT( deviceData->m_type == TYPE_CL ); + m_deviceData = deviceData; + const DeviceCL* dd = (const DeviceCL*) deviceData; + + cl_program& program = (cl_program&)m_ptr; + cl_int status = 0; + size_t srcSize[] = {strlen( src )}; + program = clCreateProgramWithSource( dd->m_context, 1, &src, srcSize, &status ); + ADLASSERT( status == CL_SUCCESS ); + status = clBuildProgram( program, 1, &dd->m_deviceIdx, option, NULL, NULL ); + if( status != CL_SUCCESS ) + { + char *build_log; + size_t ret_val_size; + clGetProgramBuildInfo(program, dd->m_deviceIdx, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size); + build_log = new char[ret_val_size+1]; + clGetProgramBuildInfo(program, dd->m_deviceIdx, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL); + + build_log[ret_val_size] = '\0'; + + debugPrintf("%s\n", build_log); + printf("%s\n", build_log); + + ADLASSERT(0); + delete build_log; + + } +} + +template<> +KernelBuilder::~KernelBuilder() +{ + cl_program program = (cl_program)m_ptr; + clReleaseProgram( program ); +} + +template<> +void KernelBuilder::createKernel( const char* funcName, Kernel& kernelOut ) +{ + KernelCL* clKernel = (KernelCL*)&kernelOut; + + cl_program program = (cl_program)m_ptr; + cl_int status = 0; + clKernel->getKernel() = clCreateKernel(program, funcName, &status ); + ADLASSERT( status == CL_SUCCESS ); + + kernelOut.m_type = TYPE_CL; +} + +template<> +void KernelBuilder::deleteKernel( Kernel& kernel ) +{ + KernelCL* clKernel = (KernelCL*)&kernel; + clReleaseKernel( clKernel->getKernel() ); +} + + + +class LauncherCL +{ + public: + typedef Launcher::BufferInfo BufferInfo; + + __inline + static void setBuffers( Launcher* launcher, BufferInfo* buffInfo, int n ); + template + __inline + static void setConst( Launcher* launcher, Buffer& constBuff, const T& consts ); + __inline + static void launch2D( Launcher* launcher, int numThreadsX, int numThreadsY, int localSizeX, int localSizeY ); +}; + +void LauncherCL::setBuffers( Launcher* launcher, BufferInfo* buffInfo, int n ) +{ + KernelCL* clKernel = (KernelCL*)launcher->m_kernel; + for(int i=0; i* buff = (Buffer*)buffInfo[i].m_buffer; + cl_int status = clSetKernelArg( clKernel->getKernel(), launcher->m_idx++, sizeof(cl_mem), &buff->m_ptr ); + ADLASSERT( status == CL_SUCCESS ); + } +} + +template +void LauncherCL::setConst( Launcher* launcher, Buffer& constBuff, const T& consts ) +{ + KernelCL* clKernel = (KernelCL*)launcher->m_kernel; + int sz=sizeof(T); + cl_int status = clSetKernelArg( clKernel->getKernel(), launcher->m_idx++, sz, &consts ); + ADLASSERT( status == CL_SUCCESS ); +} + +void LauncherCL::launch2D( Launcher* launcher, int numThreadsX, int numThreadsY, int localSizeX, int localSizeY ) +{ + KernelCL* clKernel = (KernelCL*)launcher->m_kernel; + const DeviceCL* ddcl = (const DeviceCL*)launcher->m_deviceData; + size_t gRange[3] = {1,1,1}; + size_t lRange[3] = {1,1,1}; + lRange[0] = localSizeX; + lRange[1] = localSizeY; + gRange[0] = max((size_t)1, (numThreadsX/lRange[0])+(!(numThreadsX%lRange[0])?0:1)); + gRange[0] *= lRange[0]; + gRange[1] = max((size_t)1, (numThreadsY/lRange[1])+(!(numThreadsY%lRange[1])?0:1)); + gRange[1] *= lRange[1]; + + cl_int status = clEnqueueNDRangeKernel( ddcl->m_commandQueue, + clKernel->getKernel(), 2, NULL, gRange, lRange, 0,0,0 ); + ADLASSERT( status == CL_SUCCESS ); +} + + +}; \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/DX11/AdlDX11.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/DX11/AdlDX11.inl new file mode 100644 index 0000000..66abde9 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/DX11/AdlDX11.inl @@ -0,0 +1,512 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#include +#include +#include +#include +#include +#pragma comment(lib,"d3dx11.lib") +#pragma comment(lib,"d3d11.lib") +#pragma comment(lib,"DXGI.lib") + +namespace adl +{ + +#define u32 unsigned int + +struct DeviceDX11 : public Device +{ + typedef DeviceUtils::Config Config; + + + __inline + DeviceDX11() : Device( TYPE_DX11 ), m_kernelManager(0){} + __inline + void* getContext() const { return m_context; } + __inline + void initialize(const Config& cfg); + __inline + void release(); + + template + __inline + void allocate(Buffer* buf, int nElems, BufferBase::BufferType type); + + template + __inline + void deallocate(Buffer* buf); + + template + __inline + void copy(Buffer* dst, const Buffer* src, int nElems); + + template + __inline + void copy(T* dst, const Buffer* src, int nElems, int srcOffsetNElems = 0); + + template + __inline + void copy(Buffer* dst, const T* src, int nElems, int dstOffsetNElems = 0); + + __inline + void waitForCompletion() const; + + __inline + void getDeviceName( char nameOut[128] ) const; + + __inline + static + int getNDevices(); + + __inline + Kernel* getKernel(const char* fileName, const char* funcName, const char* option = NULL, const char* src = NULL, bool cacheKernel = true )const; + + + ID3D11DeviceContext* m_context; + ID3D11Device* m_device; + IDXGISwapChain* m_swapChain; + + KernelManager* m_kernelManager; +}; + +template +struct BufferDX11 : public Buffer +{ + ID3D11Buffer* getBuffer() { return (ID3D11Buffer*)m_ptr; } + ID3D11UnorderedAccessView* getUAV() { return (ID3D11UnorderedAccessView*)m_uav; } + ID3D11ShaderResourceView* getSRV() { return (ID3D11ShaderResourceView*)m_srv; } + + ID3D11Buffer** getBufferPtr() { return (ID3D11Buffer**)&m_ptr; } + ID3D11UnorderedAccessView** getUAVPtr() { return (ID3D11UnorderedAccessView**)&m_uav; } + ID3D11ShaderResourceView** getSRVPtr() { return (ID3D11ShaderResourceView**)&m_srv; } +}; + +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + +void DeviceDX11::initialize(const Config& cfg) +{ + DeviceDX11* deviceData = this; + + HRESULT hr = S_OK; + UINT createDeviceFlg = 0; +#ifdef _DEBUG + createDeviceFlg |= D3D11_CREATE_DEVICE_DEBUG; +#endif + D3D_FEATURE_LEVEL fl[] = { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0 + }; + +typedef HRESULT (WINAPI * LPD3D11CREATEDEVICE)( IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, u32, D3D_FEATURE_LEVEL*, UINT, u32, ID3D11Device**, D3D_FEATURE_LEVEL*, ID3D11DeviceContext** ); + + HMODULE moduleD3D11 = 0; +#ifdef UNICODE + moduleD3D11 = LoadLibrary( L"d3d11.dll" ); +#else + moduleD3D11 = LoadLibrary( "d3d11.dll" ); +#endif + ADLASSERT( moduleD3D11 ); + + LPD3D11CREATEDEVICE _DynamicD3D11CreateDevice; + _DynamicD3D11CreateDevice = ( LPD3D11CREATEDEVICE )GetProcAddress( moduleD3D11, "D3D11CreateDevice" ); + + D3D_DRIVER_TYPE type = D3D_DRIVER_TYPE_HARDWARE; + // http://msdn.microsoft.com/en-us/library/ff476082(v=VS.85).aspx + // If you set the pAdapter parameter to a non-NULL value, you must also set the DriverType parameter to the D3D_DRIVER_TYPE_UNKNOWN value. If you set the pAdapter parameter to a non-NULL value and the DriverType parameter to the D3D_DRIVER_TYPE_HARDWARE value, D3D11CreateDevice returns an HRESULT of E_INVALIDARG. + type = D3D_DRIVER_TYPE_UNKNOWN; +/* + // Create a hardware Direct3D 11 device + hr = _DynamicD3D11CreateDevice( NULL, + type, NULL, createDeviceFlg, + fl, _countof(fl), D3D11_SDK_VERSION, &deviceData->m_device, NULL, &deviceData->m_context ); +*/ + IDXGIAdapter* adapter = NULL; + {// get adapter of the index + IDXGIFactory* factory = NULL; + int targetAdapterIdx = cfg.m_deviceIdx;//min( cfg.m_deviceIdx, getNDevices()-1 ); + CreateDXGIFactory( __uuidof(IDXGIFactory), (void**)&factory ); + + u32 i = 0; + while( factory->EnumAdapters( i, &adapter ) != DXGI_ERROR_NOT_FOUND ) + { + if( i== targetAdapterIdx ) break; + i++; + } + factory->Release(); + } + + // Create a hardware Direct3D 11 device + hr = D3D11CreateDevice( adapter, + type, + NULL, createDeviceFlg, + fl, _countof(fl), D3D11_SDK_VERSION, &deviceData->m_device, NULL, &deviceData->m_context ); + + ADLASSERT( hr == S_OK ); + + // Check if the hardware device supports Compute Shader 4.0 + D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS hwopts; + deviceData->m_device->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts)); + + if( !hwopts.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x ) + { + SAFE_RELEASE( deviceData->m_context ); + SAFE_RELEASE( deviceData->m_device ); + + debugPrintf("DX11 GPU is not present\n"); + ADLASSERT( 0 ); + } + + m_kernelManager = new KernelManager; +} + +void DeviceDX11::release() +{ + SAFE_RELEASE( m_context ); + SAFE_RELEASE( m_device ); + + if( m_kernelManager ) delete m_kernelManager; +} + +template +void DeviceDX11::allocate(Buffer* buf, int nElems, BufferBase::BufferType type) +{ + ADLASSERT( type != BufferBase::BUFFER_ZERO_COPY ); + + DeviceDX11* deviceData = this; + buf->m_device = deviceData; + buf->m_size = nElems; + BufferDX11* dBuf = (BufferDX11*)buf; + +// if( type & BufferBase::BUFFER ) + { + HRESULT hr = S_OK; + + if( type == BufferBase::BUFFER_CONST ) + { + ADLASSERT( nElems == 1 ); + D3D11_BUFFER_DESC constant_buffer_desc; + ZeroMemory( &constant_buffer_desc, sizeof(constant_buffer_desc) ); +// constant_buffer_desc.ByteWidth = NEXTMULTIPLEOF( sizeof(T), 16 ); + constant_buffer_desc.ByteWidth = (((sizeof(T))/(16) + (((sizeof(T))%(16)==0)?0:1))*(16)); +// constant_buffer_desc.Usage = D3D11_USAGE_DYNAMIC; +// constant_buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; +// constant_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + constant_buffer_desc.Usage = D3D11_USAGE_DEFAULT; + constant_buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constant_buffer_desc.CPUAccessFlags = 0; + + hr = deviceData->m_device->CreateBuffer( &constant_buffer_desc, NULL, dBuf->getBufferPtr() ); + ADLASSERT( hr == S_OK ); + return; + } + + D3D11_BUFFER_DESC buffer_desc; + ZeroMemory(&buffer_desc, sizeof(buffer_desc)); + buffer_desc.ByteWidth = nElems * sizeof(T); + + if( type != BufferBase::BUFFER_RAW ) + { + buffer_desc.StructureByteStride = sizeof(T); +// buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + } + + if( type == BufferBase::BUFFER_STAGING ) + { + buffer_desc.Usage = D3D11_USAGE_STAGING; + buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + } + else if( type == BufferBase::BUFFER_INDEX ) + { + buffer_desc.Usage = D3D11_USAGE_DEFAULT; + buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + } + else if( type == BufferBase::BUFFER_VERTEX ) + { + buffer_desc.Usage = D3D11_USAGE_DEFAULT; + buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + } + else + { + buffer_desc.Usage = D3D11_USAGE_DEFAULT; + + buffer_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE; + buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + +// check this + if(type == BufferBase::BUFFER_RAW) + { +// buffer_desc.BindFlags |= D3D11_BIND_INDEX_BUFFER | D3D11_BIND_VERTEX_BUFFER; + buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS | D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS; // need this to be used for DispatchIndirect + } + } + hr = deviceData->m_device->CreateBuffer(&buffer_desc, NULL, dBuf->getBufferPtr()); + + ADLASSERT( hr == S_OK ); + + if( type == BufferBase::BUFFER_INDEX ) return; + + if( type == BufferBase::BUFFER || + type == BufferBase::BUFFER_RAW || + type == BufferBase::BUFFER_W_COUNTER ) + { + // Create UAVs for all CS buffers + D3D11_UNORDERED_ACCESS_VIEW_DESC uavbuffer_desc; + ZeroMemory(&uavbuffer_desc, sizeof(uavbuffer_desc)); + uavbuffer_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + + if( type == BufferBase::BUFFER_RAW ) + { + uavbuffer_desc.Format = DXGI_FORMAT_R32_TYPELESS; + uavbuffer_desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW; + uavbuffer_desc.Buffer.NumElements = buffer_desc.ByteWidth / 4; + } + else + { + uavbuffer_desc.Format = DXGI_FORMAT_UNKNOWN; + uavbuffer_desc.Buffer.NumElements = nElems; + } + + if( type == BufferBase::BUFFER_W_COUNTER ) + { + uavbuffer_desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_COUNTER; + } + + hr = deviceData->m_device->CreateUnorderedAccessView(dBuf->getBuffer(), &uavbuffer_desc, dBuf->getUAVPtr()); + ADLASSERT( hr == S_OK ); + + // Create SRVs for all CS buffers + D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc; + ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc)); + if( type == BufferBase::BUFFER_RAW ) + { + ADLASSERT( sizeof(T) <= 16 ); + srvbuffer_desc.Format = DXGI_FORMAT_R32_UINT; + srvbuffer_desc.Buffer.ElementWidth = nElems; +// if ( buffer_desc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS ) +// { +// srvbuffer_desc.Format = DXGI_FORMAT_R32_TYPELESS; +// srvbuffer_desc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW; +// srvbuffer_desc.BufferEx.NumElements = buffer_desc.ByteWidth / 4; + } + else + { + srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN; + srvbuffer_desc.Buffer.ElementWidth = nElems; + } + srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + + hr = deviceData->m_device->CreateShaderResourceView(dBuf->getBuffer(), &srvbuffer_desc, dBuf->getSRVPtr()); + ADLASSERT( hr == S_OK ); + } + else if( type == BufferBase::BUFFER_APPEND ) + { + D3D11_UNORDERED_ACCESS_VIEW_DESC desc; + ZeroMemory( &desc, sizeof(desc) ); + desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + desc.Buffer.FirstElement = 0; + + desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_APPEND; + + desc.Format = DXGI_FORMAT_UNKNOWN; // Format must be must be DXGI_FORMAT_UNKNOWN, when creating a View of a Structured Buffer + desc.Buffer.NumElements = buffer_desc.ByteWidth / buffer_desc.StructureByteStride; + + hr = deviceData->m_device->CreateUnorderedAccessView( dBuf->getBuffer(), &desc, dBuf->getUAVPtr() ); + ADLASSERT( hr == S_OK ); + } + } +// else +// { +// ADLASSERT(0); +// } +} + +template +void DeviceDX11::deallocate(Buffer* buf) +{ + BufferDX11* dBuf = (BufferDX11*)buf; + + if( dBuf->getBuffer() ) + { + dBuf->getBuffer()->Release(); + dBuf->m_ptr = NULL; + } + if( dBuf->getUAV() ) + { + dBuf->getUAV()->Release(); + dBuf->m_uav = NULL; + } + if( dBuf->getSRV() ) + { + dBuf->getSRV()->Release(); + dBuf->m_srv = NULL; + } + buf->m_device = 0; +} + +template +void DeviceDX11::copy(Buffer* dst, const Buffer* src, int nElems) +{ + if( dst->m_device->m_type == TYPE_DX11 || src->m_device->m_type == TYPE_DX11 ) + { + DeviceDX11* deviceData = this; + BufferDX11* dDst = (BufferDX11*)dst; + BufferDX11* dSrc = (BufferDX11*)src; + + D3D11_MAPPED_SUBRESOURCE MappedVelResource = {0}; + + D3D11_BOX destRegion; + destRegion.left = 0*sizeof(T); + destRegion.front = 0; + destRegion.top = 0; + destRegion.bottom = 1; + destRegion.back = 1; + destRegion.right = (0+nElems)*sizeof(T); + + deviceData->m_context->CopySubresourceRegion( + dDst->getBuffer(), + 0, 0, 0, 0, + dSrc->getBuffer(), + 0, + &destRegion ); + + } + else if( src->m_device->m_type == TYPE_HOST ) + { + ADLASSERT( dst->getType() == TYPE_DX11 ); + dst->write( src->m_ptr, nElems ); + } + else if( dst->m_device->m_type == TYPE_HOST ) + { + ADLASSERT( src->getType() == TYPE_DX11 ); + src->read( dst->m_ptr, nElems ); + } + else + { + ADLASSERT( 0 ); + } +} + +template +void DeviceDX11::copy(T* dst, const Buffer* src, int nElems, int srcOffsetNElems) +{ + DeviceDX11* deviceData = this; + BufferDX11* dSrc = (BufferDX11*)src; + Buffer sBuf( deviceData, nElems, BufferBase::BUFFER_STAGING ); + BufferDX11* dStagingBuf = (BufferDX11*)&sBuf; + + + ID3D11Buffer *StagingBuffer = dStagingBuf->getBuffer(); + D3D11_MAPPED_SUBRESOURCE MappedVelResource = {0}; + + D3D11_BOX destRegion; + destRegion.left = srcOffsetNElems*sizeof(T); + destRegion.front = 0; + destRegion.top = 0; + destRegion.bottom = 1; + destRegion.back = 1; + destRegion.right = (srcOffsetNElems+nElems)*sizeof(T); + + deviceData->m_context->CopySubresourceRegion( + StagingBuffer, + 0, 0, 0, 0, + dSrc->getBuffer(), + 0, + &destRegion); + + deviceData->m_context->Map(StagingBuffer, 0, D3D11_MAP_READ, 0, &MappedVelResource); + memcpy(dst, MappedVelResource.pData, nElems*sizeof(T)); + deviceData->m_context->Unmap(StagingBuffer, 0); +} + +template +void DeviceDX11::copy(Buffer* dst, const T* src, int nElems, int dstOffsetNElems) +{ + BufferDX11* dBuf = (BufferDX11*)dst; + + DeviceDX11* deviceData = this; + + D3D11_BOX destRegion; + destRegion.left = dstOffsetNElems*sizeof(T); + destRegion.front = 0; + destRegion.top = 0; + destRegion.bottom = 1; + destRegion.back = 1; + destRegion.right = (dstOffsetNElems+nElems)*sizeof(T); + deviceData->m_context->UpdateSubresource(dBuf->getBuffer(), 0, &destRegion, src, 0, 0); +} + +void DeviceDX11::waitForCompletion() const +{ + const DeviceDX11* deviceData = this; + + ID3D11Query* syncQuery; + D3D11_QUERY_DESC qDesc; + qDesc.Query = D3D11_QUERY_EVENT; + qDesc.MiscFlags = 0; + deviceData->m_device->CreateQuery( &qDesc, &syncQuery ); + deviceData->m_context->End( syncQuery ); + while( deviceData->m_context->GetData( syncQuery, 0,0,0 ) == S_FALSE ){} + syncQuery->Release(); +} + +int DeviceDX11::getNDevices() +{ + IDXGIFactory1* factory = NULL; + IDXGIAdapter1* adapter = NULL; + CreateDXGIFactory1( __uuidof(IDXGIFactory1), (void**)&factory ); + + u32 i = 0; + while( factory->EnumAdapters1( i, &adapter ) != DXGI_ERROR_NOT_FOUND ) + { + i++; + } + + factory->Release(); + return i; +} + +void DeviceDX11::getDeviceName( char nameOut[128] ) const +{ + IDXGIAdapter* adapter;// = getAdapterFromDevice( this ); + { + IDXGIDevice* pDXGIDevice; + + ADLASSERT( m_device->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice) == S_OK ); + ADLASSERT( pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&adapter) == S_OK ); + + pDXGIDevice->Release(); + } + DXGI_ADAPTER_DESC adapterDesc; + adapter->GetDesc( &adapterDesc ); + +// wcstombs( nameOut, adapterDesc.Description, 128 ); + size_t i; + wcstombs_s( &i, nameOut, 128, adapterDesc.Description, 128 ); +} + +Kernel* DeviceDX11::getKernel(const char* fileName, const char* funcName, const char* option, const char* src, bool cacheKernel ) const +{ + return m_kernelManager->query( this, fileName, funcName, option, src, cacheKernel ); +} + +#undef u32 + +#undef SAFE_RELEASE + +}; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/DX11/AdlKernelUtilsDX11.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/DX11/AdlKernelUtilsDX11.inl new file mode 100644 index 0000000..d4e2999 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/DX11/AdlKernelUtilsDX11.inl @@ -0,0 +1,348 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + + +namespace adl +{ + +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + +struct KernelDX11 : public Kernel +{ + ID3D11ComputeShader* getKernel() { return (ID3D11ComputeShader*)m_kernel; } + ID3D11ComputeShader** getKernelPtr() { return (ID3D11ComputeShader**)&m_kernel; } +}; + + +__inline +#ifdef UNICODE +HRESULT FindDXSDKShaderFileCch( __in_ecount(cchDest) WCHAR* strDestPath, + int cchDest, + __in LPCWSTR strFilename ) +#else +HRESULT FindDXSDKShaderFileCch( __in_ecount(cchDest) CHAR* strDestPath, + int cchDest, + __in LPCSTR strFilename ) +#endif +{ + if( NULL == strFilename || strFilename[0] == 0 || NULL == strDestPath || cchDest < 10 ) + return E_INVALIDARG; + + // Get the exe name, and exe path +#ifdef UNICODE + WCHAR strExePath[MAX_PATH] = +#else + CHAR strExePath[MAX_PATH] = +#endif + { + 0 + }; +#ifdef UNICODE + WCHAR strExeName[MAX_PATH] = +#else + CHAR strExeName[MAX_PATH] = +#endif + { + 0 + }; +#ifdef UNICODE + WCHAR* strLastSlash = NULL; +#else + CHAR* strLastSlash = NULL; +#endif + GetModuleFileName( NULL, strExePath, MAX_PATH ); + strExePath[MAX_PATH - 1] = 0; +#ifdef UNICODE + strLastSlash = wcsrchr( strExePath, TEXT( '\\' ) ); +#else + strLastSlash = strrchr( strExePath, TEXT( '\\' ) ); +#endif + if( strLastSlash ) + { +#ifdef UNICODE + wcscpy_s( strExeName, MAX_PATH, &strLastSlash[1] ); +#else + +#endif + // Chop the exe name from the exe path + *strLastSlash = 0; + + // Chop the .exe from the exe name +#ifdef UNICODE + strLastSlash = wcsrchr( strExeName, TEXT( '.' ) ); +#else + strLastSlash = strrchr( strExeName, TEXT( '.' ) ); +#endif + if( strLastSlash ) + *strLastSlash = 0; + } + + // Search in directories: + // .\ + // %EXE_DIR%\..\..\%EXE_NAME% +#ifdef UNICODE + wcscpy_s( strDestPath, cchDest, strFilename ); +#else + strcpy_s( strDestPath, cchDest, strFilename ); +#endif + if( GetFileAttributes( strDestPath ) != 0xFFFFFFFF ) + return S_OK; + +// swprintf_s( strDestPath, cchDest, L"%s\\..\\..\\%s\\%s", strExePath, strExeName, strFilename ); +#ifdef UNICODE + swprintf_s( strDestPath, cchDest, L"%s\\..\\%s\\%s", strExePath, strExeName, strFilename ); +#else + sprintf_s( strDestPath, cchDest, "%s\\..\\%s\\%s", strExePath, strExeName, strFilename ); +#endif + if( GetFileAttributes( strDestPath ) != 0xFFFFFFFF ) + return S_OK; + + // On failure, return the file as the path but also return an error code +#ifdef UNICODE + wcscpy_s( strDestPath, cchDest, strFilename ); +#else + strcpy_s( strDestPath, cchDest, strFilename ); +#endif + + ADLASSERT( 0 ); + + return E_FAIL; +} + + + + +template<> +void KernelBuilder::setFromFile( const Device* deviceData, const char* fileName, const char* option, bool addExtension, + bool cacheKernel) +{ + char fileNameWithExtension[256]; + + if( addExtension ) + sprintf_s( fileNameWithExtension, "%s.hlsl", fileName ); + else + sprintf_s( fileNameWithExtension, "%s", fileName ); + + m_deviceData = deviceData; + + int nameLength = (int)strlen(fileNameWithExtension)+1; +#ifdef UNICODE + WCHAR* wfileNameWithExtension = new WCHAR[nameLength]; +#else + CHAR* wfileNameWithExtension = new CHAR[nameLength]; +#endif + memset(wfileNameWithExtension,0,nameLength); +#ifdef UNICODE + MultiByteToWideChar(CP_ACP,0,fileNameWithExtension,-1, wfileNameWithExtension, nameLength); +#else + sprintf_s(wfileNameWithExtension, nameLength, "%s", fileNameWithExtension); +#endif +// swprintf_s(wfileNameWithExtension, nameLength*2, L"%s", fileNameWithExtension); + + HRESULT hr; + + // Finds the correct path for the shader file. + // This is only required for this sample to be run correctly from within the Sample Browser, + // in your own projects, these lines could be removed safely + hr = FindDXSDKShaderFileCch( m_path, MAX_PATH, wfileNameWithExtension ); + + delete [] wfileNameWithExtension; + + ADLASSERT( hr == S_OK ); +} + +template<> +void KernelBuilder::setFromSrc( const Device* deviceData, const char* src, const char* option ) +{ + m_deviceData = deviceData; + m_ptr = (void*)src; + m_path[0] = '0'; +} + +template<> +KernelBuilder::~KernelBuilder() +{ + +} + +template<> +void KernelBuilder::createKernel( const char* funcName, Kernel& kernelOut ) +{ + const DeviceDX11* deviceData = (const DeviceDX11*)m_deviceData; + KernelDX11* dxKernel = (KernelDX11*)&kernelOut; + HRESULT hr; + + DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS; +#if defined( DEBUG ) || defined( _DEBUG ) + // Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders. + // Setting this flag improves the shader debugging experience, but still allows + // the shaders to be optimized and to run exactly the way they will run in + // the release configuration of this program. + dwShaderFlags |= D3DCOMPILE_DEBUG; +#endif + + const D3D_SHADER_MACRO defines[] = + { +#ifdef USE_STRUCTURED_BUFFERS + "USE_STRUCTURED_BUFFERS", "1", +#endif + +#ifdef TEST_DOUBLE + "TEST_DOUBLE", "1", +#endif + NULL, NULL + }; + + // We generally prefer to use the higher CS shader profile when possible as CS 5.0 is better performance on 11-class hardware + LPCSTR pProfile = ( deviceData->m_device->GetFeatureLevel() >= D3D_FEATURE_LEVEL_11_0 ) ? "cs_5_0" : "cs_4_0"; + + ID3DBlob* pErrorBlob = NULL; + ID3DBlob* pBlob = NULL; + if( m_path[0] == '0' ) + { + char* src = (char*)m_ptr; + hr = D3DX11CompileFromMemory( src, strlen(src), 0, defines, NULL, funcName, pProfile, + dwShaderFlags, NULL, NULL, &pBlob, &pErrorBlob, NULL ); + } + else + { + hr = D3DX11CompileFromFile( m_path, defines, NULL, funcName, pProfile, + dwShaderFlags, NULL, NULL, &pBlob, &pErrorBlob, NULL ); + } + + if ( FAILED(hr) ) + { + debugPrintf("%s", (char*)pErrorBlob->GetBufferPointer()); + } + ADLASSERT( hr == S_OK ); + + hr = deviceData->m_device->CreateComputeShader( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), NULL, + dxKernel->getKernelPtr() ); + +#if defined(DEBUG) || defined(PROFILE) + if ( kernelOut.m_kernel ) + kernelOut.m_kernel->SetPrivateData( WKPDID_D3DDebugObjectName, lstrlenA(pFunctionName), pFunctionName ); +#endif + + SAFE_RELEASE( pErrorBlob ); + SAFE_RELEASE( pBlob ); + + kernelOut.m_type = TYPE_DX11; +} + +template<> +void KernelBuilder::deleteKernel( Kernel& kernel ) +{ + KernelDX11* dxKernel = (KernelDX11*)&kernel; + + if( kernel.m_kernel ) + { + dxKernel->getKernel()->Release(); + kernel.m_kernel = NULL; + } +} + + + +class LauncherDX11 +{ + public: + typedef Launcher::BufferInfo BufferInfo; + + __inline + static void setBuffers( Launcher* launcher, BufferInfo* buffInfo, int n ); + template + __inline + static void setConst( Launcher* launcher, Buffer& constBuff, const T& consts ); + __inline + static void launch2D( Launcher* launcher, int numThreadsX, int numThreadsY, int localSizeX, int localSizeY ); +}; + +void LauncherDX11::setBuffers( Launcher* launcher, BufferInfo* buffInfo, int n ) +{ + KernelDX11* dxKernel = (KernelDX11*)launcher->m_kernel; + const DeviceDX11* dddx = (const DeviceDX11*)launcher->m_deviceData; + + for(int i=0; i* dBuf = (BufferDX11*)buffInfo[i].m_buffer; + if( buffInfo[i].m_isReadOnly ) + { + dddx->m_context->CSSetShaderResources( launcher->m_idx++, 1, dBuf->getSRVPtr() ); + } + else + { + // todo. cannot initialize append buffer with proper counter value which is the last arg + dddx->m_context->CSSetUnorderedAccessViews( launcher->m_idxRw++, 1, dBuf->getUAVPtr(), 0 ); + } + } +} + +template +void LauncherDX11::setConst( Launcher* launcher, Buffer& constBuff, const T& consts ) +{ + KernelDX11* dxKernel = (KernelDX11*)launcher->m_kernel; + const DeviceDX11* dddx = (const DeviceDX11*)launcher->m_deviceData; + BufferDX11* dBuf = (BufferDX11*)&constBuff; +/* + D3D11_MAPPED_SUBRESOURCE MappedResource; + dddx->m_context->Map( dBuf->getBuffer(), 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &consts, sizeof(T) ); + dddx->m_context->Unmap( dBuf->getBuffer(), 0 ); +*/ + + dddx->m_context->UpdateSubresource( dBuf->getBuffer(), 0, NULL, &consts, 0, 0 ); + + dddx->m_context->CSSetConstantBuffers( 0, 1, dBuf->getBufferPtr() ); +} + +void LauncherDX11::launch2D( Launcher* launcher, int numThreadsX, int numThreadsY, int localSizeX, int localSizeY ) +{ + KernelDX11* dxKernel = (KernelDX11*)launcher->m_kernel; + const DeviceDX11* dddx = (const DeviceDX11*)launcher->m_deviceData; + + dddx->m_context->CSSetShader( dxKernel->getKernel(), NULL, 0 ); + + int nx, ny, nz; + nx = max( 1, (numThreadsX/localSizeX)+(!(numThreadsX%localSizeX)?0:1) ); + ny = max( 1, (numThreadsY/localSizeY)+(!(numThreadsY%localSizeY)?0:1) ); + nz = 1; + + dddx->m_context->Dispatch( nx, ny, nz ); + + // set 0 to registers + { + dddx->m_context->CSSetShader( NULL, NULL, 0 ); + + if( launcher->m_idxRw ) + { + ID3D11UnorderedAccessView* aUAViewsNULL[ 16 ] = { 0 }; + dddx->m_context->CSSetUnorderedAccessViews( 0, + min( (unsigned int)launcher->m_idxRw, sizeof(aUAViewsNULL)/sizeof(*aUAViewsNULL) ), aUAViewsNULL, NULL ); + } + + if( launcher->m_idx ) + { + ID3D11ShaderResourceView* ppSRVNULL[16] = { 0 }; + dddx->m_context->CSSetShaderResources( 0, + min( (unsigned int)launcher->m_idx, sizeof(ppSRVNULL)/sizeof(*ppSRVNULL) ), ppSRVNULL ); + } + } +} + +#undef SAFE_RELEASE + +}; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/DX11/AdlStopwatchDX11.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/DX11/AdlStopwatchDX11.inl new file mode 100644 index 0000000..15b79aa --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/DX11/AdlStopwatchDX11.inl @@ -0,0 +1,131 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + + +namespace adl +{ + +struct StopwatchDX11 : public StopwatchBase +{ + public: + __inline + StopwatchDX11() : StopwatchBase(){} + __inline + ~StopwatchDX11(); + + __inline + void init( const Device* deviceData ); + __inline + void start(); + __inline + void split(); + __inline + void stop(); + __inline + float getMs(int index=0); + __inline + void getMs( float* times, int capacity ); + + public: + ID3D11Query* m_tQuery[CAPACITY+1]; + ID3D11Query* m_fQuery; + UINT64 m_t[CAPACITY]; +}; + +void StopwatchDX11::init( const Device* deviceData ) +{ + ADLASSERT( deviceData->m_type == TYPE_DX11 ); + m_device = deviceData; + { + D3D11_QUERY_DESC qDesc; + qDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT; + qDesc.MiscFlags = 0; + ((const DeviceDX11*)m_device)->m_device->CreateQuery( &qDesc, &m_fQuery ); + } + for(int i=0; im_device->CreateQuery( &qDesc, &m_tQuery[i] ); + } +} + +StopwatchDX11::~StopwatchDX11() +{ + m_fQuery->Release(); + for(int i=0; iRelease(); + } +} + +void StopwatchDX11::start() +{ + m_idx = 0; + ((const DeviceDX11*)m_device)->m_context->Begin( m_fQuery ); + ((const DeviceDX11*)m_device)->m_context->End( m_tQuery[m_idx++] ); +} + +void StopwatchDX11::split() +{ + if( m_idx < CAPACITY ) + ((const DeviceDX11*)m_device)->m_context->End( m_tQuery[m_idx++] ); +} + +void StopwatchDX11::stop() +{ + ((const DeviceDX11*)m_device)->m_context->End( m_tQuery[m_idx++] ); + ((const DeviceDX11*)m_device)->m_context->End( m_fQuery ); +} + +float StopwatchDX11::getMs(int index) +{ + D3D11_QUERY_DATA_TIMESTAMP_DISJOINT d; +// m_deviceData->m_context->End( m_fQuery ); + while( ((const DeviceDX11*)m_device)->m_context->GetData( m_fQuery, &d,sizeof(D3D11_QUERY_DATA_TIMESTAMP_DISJOINT),0 ) == S_FALSE ) {} + + while( ((const DeviceDX11*)m_device)->m_context->GetData( m_tQuery[0], &m_t[index],sizeof(UINT64),0 ) == S_FALSE ){} + while( ((const DeviceDX11*)m_device)->m_context->GetData( m_tQuery[1], &m_t[index+1],sizeof(UINT64),0 ) == S_FALSE ){} + + ADLASSERT( d.Disjoint == false ); + + float elapsedMs = (m_t[index+1] - m_t[index])/(float)d.Frequency*1000; + return elapsedMs; + +} + +void StopwatchDX11::getMs( float* times, int capacity ) +{ + ADLASSERT( capacity <= CAPACITY ); + + D3D11_QUERY_DATA_TIMESTAMP_DISJOINT d; + while( ((const DeviceDX11*)m_device)->m_context->GetData( m_fQuery, &d,sizeof(D3D11_QUERY_DATA_TIMESTAMP_DISJOINT),0 ) == S_FALSE ) {} + + for(int i=0; im_context->GetData( m_tQuery[i], &m_t[i],sizeof(UINT64),0 ) == S_FALSE ){} + } + + ADLASSERT( d.Disjoint == false ); + + for(int i=0; i + __inline + void allocate(Buffer* buf, int nElems, BufferBase::BufferType type); + + template + __inline + void deallocate(Buffer* buf); + + template + __inline + void copy(Buffer* dst, const Buffer* src, int nElems); + + template + __inline + void copy(T* dst, const Buffer* src, int nElems, int offsetNElems = 0); + + template + __inline + void copy(Buffer* dst, const T* src, int nElems, int offsetNElems = 0); + + __inline + void waitForCompletion() const; +}; + +void DeviceHost::initialize(const Config& cfg) +{ + +} + +void DeviceHost::release() +{ + +} + +template +void DeviceHost::allocate(Buffer* buf, int nElems, BufferBase::BufferType type) +{ + buf->m_device = this; + + if( type == BufferBase::BUFFER_CONST ) return; + + buf->m_ptr = new T[nElems]; + ADLASSERT( buf->m_ptr ); + buf->m_size = nElems; +} + +template +void DeviceHost::deallocate(Buffer* buf) +{ + if( buf->m_ptr ) delete [] buf->m_ptr; +} + +template +void DeviceHost::copy(Buffer* dst, const Buffer* src, int nElems) +{ + copy( dst, src->m_ptr, nElems ); +} + +template +void DeviceHost::copy(T* dst, const Buffer* src, int nElems, int srcOffsetNElems) +{ + ADLASSERT( src->getType() == TYPE_HOST ); + memcpy( dst, src->m_ptr+srcOffsetNElems, nElems*sizeof(T) ); +} + +template +void DeviceHost::copy(Buffer* dst, const T* src, int nElems, int dstOffsetNElems) +{ + ADLASSERT( dst->getType() == TYPE_HOST ); + memcpy( dst->m_ptr+dstOffsetNElems, src, nElems*sizeof(T) ); +} + +void DeviceHost::waitForCompletion() const +{ + +} + +}; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Host/AdlStopwatchHost.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Host/AdlStopwatchHost.inl new file mode 100644 index 0000000..bb6eb57 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/Adl/Host/AdlStopwatchHost.inl @@ -0,0 +1,119 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + +#ifdef _WIN32 + #include +#else + #include +#endif + +namespace adl +{ + +class StopwatchHost : public StopwatchBase +{ + public: + __inline + StopwatchHost(); + __inline + void init( const Device* deviceData ); + __inline + void start(); + __inline + void split(); + __inline + void stop(); + __inline + float getMs(int index=0); + __inline + void getMs( float* times, int capacity ); + + private: +#ifdef _WIN32 + LARGE_INTEGER m_frequency; + LARGE_INTEGER m_t[CAPACITY]; +#else + struct timeval mStartTime; + timeval m_t[CAPACITY]; +#endif +}; + +__inline +StopwatchHost::StopwatchHost() + : StopwatchBase() +{ +} + +__inline +void StopwatchHost::init( const Device* deviceData ) +{ + m_device = deviceData; +#ifdef _WIN32 + QueryPerformanceFrequency( &m_frequency ); +#else + gettimeofday(&mStartTime, 0); +#endif +} + +__inline +void StopwatchHost::start() +{ + m_idx = 0; +#ifdef _WIN32 + QueryPerformanceCounter(&m_t[m_idx++]); +#else + gettimeofday(&m_t[m_idx++], 0); +#endif +} + +__inline +void StopwatchHost::split() +{ +#ifdef _WIN32 + QueryPerformanceCounter(&m_t[m_idx++]); +#else + gettimeofday(&m_t[m_idx++], 0); +#endif +} + +__inline +void StopwatchHost::stop() +{ + split(); +} + +__inline +float StopwatchHost::getMs(int index) +{ +#ifdef _WIN32 + return (float)(1000*(m_t[index+1].QuadPart - m_t[index].QuadPart))/m_frequency.QuadPart; +#else + return (m_t[index+1].tv_sec - m_t[index].tv_sec) * 1000 + + (m_t[index+1].tv_usec - m_t[index].tv_usec) / 1000; +#endif +} + +__inline +void StopwatchHost::getMs(float* times, int capacity) +{ + for(int i=0; i +#include + +namespace adl +{ + +class CopyBase +{ + public: + enum Option + { + PER_WI_1, + PER_WI_2, + PER_WI_4, + }; +}; + +template +class Copy : public CopyBase +{ + public: + typedef Launcher::BufferInfo BufferInfo; + + struct Data + { + const Device* m_device; + Kernel* m_copy1F4Kernel; + Kernel* m_copy2F4Kernel; + Kernel* m_copy4F4Kernel; + Kernel* m_copyF1Kernel; + Kernel* m_copyF2Kernel; + Buffer* m_constBuffer; + }; + + static + Data* allocate(const Device* deviceData); + + static + void deallocate(Data* data); + + static + void execute( Data* data, Buffer& dst, Buffer& src, int n, Option option = PER_WI_1); + + static + void execute( Data* data, Buffer& dst, Buffer& src, int n); + + static + void execute( Data* data, Buffer& dst, Buffer& src, int n); +}; + + +#include +#include + +}; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/Copy.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/Copy.inl new file mode 100644 index 0000000..ee6d3f0 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/Copy.inl @@ -0,0 +1,151 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + + +#define PATH "..\\..\\opencl\\primitives\\AdlPrimitives\\Copy\\CopyKernels" +#define KERNEL0 "Copy1F4Kernel" +#define KERNEL1 "Copy2F4Kernel" +#define KERNEL2 "Copy4F4Kernel" +#define KERNEL3 "CopyF1Kernel" +#define KERNEL4 "CopyF2Kernel" + +#include +#include + + +template +typename Copy::Data* Copy::allocate( const Device* device ) +{ + ADLASSERT( TYPE == device->m_type ); + + + const char* src[] = +#if defined(ADL_LOAD_KERNEL_FROM_STRING) + {copyKernelsCL, copyKernelsDX11}; +// ADLASSERT(0); +#else + {0,0}; +#endif + + Data* data = new Data; + data->m_device = device; + data->m_copy1F4Kernel = device->getKernel( PATH, KERNEL0, 0, src[TYPE] ); + data->m_copy2F4Kernel = device->getKernel( PATH, KERNEL1, 0, src[TYPE] ); + data->m_copy4F4Kernel = device->getKernel( PATH, KERNEL2, 0, src[TYPE] ); + data->m_copyF1Kernel = device->getKernel( PATH, KERNEL3, 0, src[TYPE] ); + data->m_copyF2Kernel = device->getKernel( PATH, KERNEL4, 0, src[TYPE] ); + data->m_constBuffer = new Buffer( device, 1, BufferBase::BUFFER_CONST ); + + return data; +} + +template +void Copy::deallocate( Data* data ) +{ + delete data->m_constBuffer; + delete data; +} + +template +void Copy::execute( Data* data, Buffer& dst, Buffer& src, int n, Option option ) +{ + ADLASSERT( TYPE == dst.getType() ); + ADLASSERT( TYPE == src.getType() ); + + int4 constBuffer; + constBuffer.x = n; + + switch (option) + { + case PER_WI_1: + { + BufferInfo bInfo[] = { BufferInfo( &dst ), BufferInfo( &src, true ) }; + + Launcher launcher( data->m_device, data->m_copy1F4Kernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer, constBuffer ); + launcher.launch1D( n/1 ); + } + break; + case PER_WI_2: + { + ADLASSERT( n%2 == 0 ); + BufferInfo bInfo[] = { BufferInfo( &dst ), BufferInfo( &src, true ) }; + + Launcher launcher( data->m_device, data->m_copy2F4Kernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer, constBuffer ); + launcher.launch1D( n/2 ); + } + break; + case PER_WI_4: + { + ADLASSERT( n%4 == 0 ); + BufferInfo bInfo[] = { BufferInfo( &dst ), BufferInfo( &src, true ) }; + + Launcher launcher( data->m_device, data->m_copy4F4Kernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer, constBuffer ); + launcher.launch1D( n/4 ); + } + break; + default: + ADLASSERT(0); + break; + }; +} + +template +void Copy::execute( Data* data, Buffer& dst, Buffer& src, int n ) +{ + ADLASSERT( TYPE == dst.getType() ); + ADLASSERT( TYPE == src.getType() ); + + int4 constBuffer; + constBuffer.x = n; + + BufferInfo bInfo[] = { BufferInfo( &dst ), BufferInfo( &src, true ) }; + + Launcher launcher( data->m_device, data->m_copyF2Kernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer, constBuffer ); + launcher.launch1D( n/1 ); +} + +template +void Copy::execute( Data* data, Buffer& dst, Buffer& src, int n ) +{ + ADLASSERT( TYPE == dst.getType() ); + ADLASSERT( TYPE == src.getType() ); + + int4 constBuffer; + constBuffer.x = n; + + BufferInfo bInfo[] = { BufferInfo( &dst ), BufferInfo( &src, true ) }; + + Launcher launcher( data->m_device, data->m_copyF1Kernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer, constBuffer ); + launcher.launch1D( n/1 ); +} + + +#undef PATH +#undef KERNEL0 +#undef KERNEL1 +#undef KERNEL2 +#undef KERNEL3 +#undef KERNEL4 diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/CopyHost.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/CopyHost.inl new file mode 100644 index 0000000..2f8562a --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/CopyHost.inl @@ -0,0 +1,85 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +template<> +class Copy : public CopyBase +{ + public: + typedef Launcher::BufferInfo BufferInfo; + + struct Data + { + }; + + static + Data* allocate(const Device* deviceData) + { + ADLASSERT( TYPE_HOST == deviceData->m_type ); + return 0; + } + + static + void deallocate(Data* data) + { + return; + } + + static + void execute( Data* data, Buffer& dst, Buffer& src, int n, Option option = PER_WI_1) + { + ADLASSERT( TYPE_HOST == dst.getType() ); + ADLASSERT( TYPE_HOST == src.getType() ); + + HostBuffer& dstH = (HostBuffer&)dst; + HostBuffer& srcH = (HostBuffer&)src; + + for(int i=0; i& dst, Buffer& src, int n) + { + ADLASSERT( TYPE_HOST == dst.getType() ); + ADLASSERT( TYPE_HOST == src.getType() ); + + HostBuffer& dstH = (HostBuffer&)dst; + HostBuffer& srcH = (HostBuffer&)src; + + for(int i=0; i& dst, Buffer& src, int n) + { + ADLASSERT( TYPE_HOST == dst.getType() ); + ADLASSERT( TYPE_HOST == src.getType() ); + + HostBuffer& dstH = (HostBuffer&)dst; + HostBuffer& srcH = (HostBuffer&)src; + + for(int i=0; i dst : register( u0 ); +StructuredBuffer src : register( t0 ); + +[numthreads(WG_SIZE, 1, 1)] +void Copy1F4Kernel( DEFAULT_ARGS ) +{ + int gIdx = GET_GLOBAL_IDX; + + if( gIdx < m_n ) + { + float4 a0 = src[gIdx]; + + dst[ gIdx ] = a0; + } +} + +[numthreads(WG_SIZE, 1, 1)] +void Copy2F4Kernel( DEFAULT_ARGS ) +{ + int gIdx = GET_GLOBAL_IDX; + + if( 2*gIdx <= m_n ) + { + float4 a0 = src[gIdx*2+0]; + float4 a1 = src[gIdx*2+1]; + + dst[ gIdx*2+0 ] = a0; + dst[ gIdx*2+1 ] = a1; + } +} + +[numthreads(WG_SIZE, 1, 1)] +void Copy4F4Kernel( DEFAULT_ARGS ) +{ + int gIdx = GET_GLOBAL_IDX; + + if( 4*gIdx <= m_n ) + { + int idx0 = gIdx*4+0; + int idx1 = gIdx*4+1; + int idx2 = gIdx*4+2; + int idx3 = gIdx*4+3; + + float4 a0 = src[idx0]; + float4 a1 = src[idx1]; + float4 a2 = src[idx2]; + float4 a3 = src[idx3]; + + dst[ idx0 ] = a0; + dst[ idx1 ] = a1; + dst[ idx2 ] = a2; + dst[ idx3 ] = a3; + } +} + +RWStructuredBuffer dstF1 : register( u0 ); +StructuredBuffer srcF1 : register( t0 ); + +[numthreads(WG_SIZE, 1, 1)] +void CopyF1Kernel( DEFAULT_ARGS ) +{ + int gIdx = GET_GLOBAL_IDX; + + if( gIdx < m_n ) + { + float a0 = srcF1[gIdx]; + + dstF1[ gIdx ] = a0; + } + +} + +RWStructuredBuffer dstF2 : register( u0 ); +StructuredBuffer srcF2 : register( t0 ); + +[numthreads(WG_SIZE, 1, 1)] +void CopyF2Kernel( DEFAULT_ARGS ) +{ + int gIdx = GET_GLOBAL_IDX; + + if( gIdx < m_n ) + { + float2 a0 = srcF2[gIdx]; + + dstF2[ gIdx ] = a0; + } +} diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/CopyKernelsCL.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/CopyKernelsCL.h new file mode 100644 index 0000000..3b67892 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/CopyKernelsCL.h @@ -0,0 +1,119 @@ +static const char* copyKernelsCL= \ +"/*\n" +" 2011 Takahiro Harada\n" +"*/\n" +"\n" +"#pragma OPENCL EXTENSION cl_amd_printf : enable\n" +"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n" +"\n" +"typedef unsigned int u32;\n" +"#define GET_GROUP_IDX get_group_id(0)\n" +"#define GET_LOCAL_IDX get_local_id(0)\n" +"#define GET_GLOBAL_IDX get_global_id(0)\n" +"#define GET_GROUP_SIZE get_local_size(0)\n" +"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n" +"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n" +"#define AtomInc(x) atom_inc(&(x))\n" +"#define AtomInc1(x, out) out = atom_inc(&(x))\n" +"\n" +"#define make_uint4 (uint4)\n" +"#define make_uint2 (uint2)\n" +"#define make_int2 (int2)\n" +"\n" +"typedef struct\n" +"{\n" +" int m_n;\n" +" int m_padding[3];\n" +"} ConstBuffer;\n" +"\n" +"\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(64,1,1)))\n" +"void Copy1F4Kernel(__global float4* dst, __global float4* src, \n" +" ConstBuffer cb)\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"\n" +" if( gIdx < cb.m_n )\n" +" {\n" +" float4 a0 = src[gIdx];\n" +"\n" +" dst[ gIdx ] = a0;\n" +" }\n" +"}\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(64,1,1)))\n" +"void Copy2F4Kernel(__global float4* dst, __global float4* src, \n" +" ConstBuffer cb)\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"\n" +" if( 2*gIdx <= cb.m_n )\n" +" {\n" +" float4 a0 = src[gIdx*2+0];\n" +" float4 a1 = src[gIdx*2+1];\n" +"\n" +" dst[ gIdx*2+0 ] = a0;\n" +" dst[ gIdx*2+1 ] = a1;\n" +" }\n" +"}\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(64,1,1)))\n" +"void Copy4F4Kernel(__global float4* dst, __global float4* src, \n" +" ConstBuffer cb)\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"\n" +" if( 4*gIdx <= cb.m_n )\n" +" {\n" +" int idx0 = gIdx*4+0;\n" +" int idx1 = gIdx*4+1;\n" +" int idx2 = gIdx*4+2;\n" +" int idx3 = gIdx*4+3;\n" +"\n" +" float4 a0 = src[idx0];\n" +" float4 a1 = src[idx1];\n" +" float4 a2 = src[idx2];\n" +" float4 a3 = src[idx3];\n" +"\n" +" dst[ idx0 ] = a0;\n" +" dst[ idx1 ] = a1;\n" +" dst[ idx2 ] = a2;\n" +" dst[ idx3 ] = a3;\n" +" }\n" +"}\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(64,1,1)))\n" +"void CopyF1Kernel(__global float* dstF1, __global float* srcF1, \n" +" ConstBuffer cb)\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"\n" +" if( gIdx < cb.m_n )\n" +" {\n" +" float a0 = srcF1[gIdx];\n" +"\n" +" dstF1[ gIdx ] = a0;\n" +" }\n" +"}\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(64,1,1)))\n" +"void CopyF2Kernel(__global float2* dstF2, __global float2* srcF2, \n" +" ConstBuffer cb)\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"\n" +" if( gIdx < cb.m_n )\n" +" {\n" +" float2 a0 = srcF2[gIdx];\n" +"\n" +" dstF2[ gIdx ] = a0;\n" +" }\n" +"}\n" +"\n" +; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/CopyKernelsDX11.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/CopyKernelsDX11.h new file mode 100644 index 0000000..6abcda4 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Copy/CopyKernelsDX11.h @@ -0,0 +1,120 @@ +static const char* copyKernelsDX11= \ +"/*\n" +" 2011 Takahiro Harada\n" +"*/\n" +"\n" +"typedef uint u32;\n" +"\n" +"#define GET_GROUP_IDX groupIdx.x\n" +"#define GET_LOCAL_IDX localIdx.x\n" +"#define GET_GLOBAL_IDX globalIdx.x\n" +"#define GROUP_LDS_BARRIER GroupMemoryBarrierWithGroupSync()\n" +"#define GROUP_MEM_FENCE\n" +"#define DEFAULT_ARGS uint3 globalIdx : SV_DispatchThreadID, uint3 localIdx : SV_GroupThreadID, uint3 groupIdx : SV_GroupID\n" +"#define AtomInc(x) InterlockedAdd(x, 1)\n" +"#define AtomInc1(x, out) InterlockedAdd(x, 1, out)\n" +"\n" +"#define make_uint4 uint4\n" +"#define make_uint2 uint2\n" +"#define make_int2 int2\n" +"\n" +"#define WG_SIZE 64\n" +"\n" +"#define GET_GROUP_SIZE WG_SIZE\n" +"\n" +"\n" +"\n" +"cbuffer CB : register( b0 )\n" +"{\n" +" int m_n;\n" +" int m_padding[3];\n" +"};\n" +"\n" +"RWStructuredBuffer dst : register( u0 );\n" +"StructuredBuffer src : register( t0 );\n" +"\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void Copy1F4Kernel( DEFAULT_ARGS )\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"\n" +" if( gIdx < m_n )\n" +" {\n" +" float4 a0 = src[gIdx];\n" +"\n" +" dst[ gIdx ] = a0;\n" +" }\n" +"}\n" +"\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void Copy2F4Kernel( DEFAULT_ARGS )\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"\n" +" if( 2*gIdx <= m_n )\n" +" {\n" +" float4 a0 = src[gIdx*2+0];\n" +" float4 a1 = src[gIdx*2+1];\n" +"\n" +" dst[ gIdx*2+0 ] = a0;\n" +" dst[ gIdx*2+1 ] = a1;\n" +" }\n" +"}\n" +"\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void Copy4F4Kernel( DEFAULT_ARGS )\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"\n" +" if( 4*gIdx <= m_n )\n" +" {\n" +" int idx0 = gIdx*4+0;\n" +" int idx1 = gIdx*4+1;\n" +" int idx2 = gIdx*4+2;\n" +" int idx3 = gIdx*4+3;\n" +"\n" +" float4 a0 = src[idx0];\n" +" float4 a1 = src[idx1];\n" +" float4 a2 = src[idx2];\n" +" float4 a3 = src[idx3];\n" +"\n" +" dst[ idx0 ] = a0;\n" +" dst[ idx1 ] = a1;\n" +" dst[ idx2 ] = a2;\n" +" dst[ idx3 ] = a3;\n" +" }\n" +"}\n" +"\n" +"RWStructuredBuffer dstF1 : register( u0 );\n" +"StructuredBuffer srcF1 : register( t0 );\n" +"\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void CopyF1Kernel( DEFAULT_ARGS )\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"\n" +" if( gIdx < m_n )\n" +" {\n" +" float a0 = srcF1[gIdx];\n" +"\n" +" dstF1[ gIdx ] = a0;\n" +" }\n" +"\n" +"}\n" +"\n" +"RWStructuredBuffer dstF2 : register( u0 );\n" +"StructuredBuffer srcF2 : register( t0 );\n" +"\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void CopyF2Kernel( DEFAULT_ARGS )\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"\n" +" if( gIdx < m_n )\n" +" {\n" +" float2 a0 = srcF2[gIdx];\n" +"\n" +" dstF2[ gIdx ] = a0;\n" +" }\n" +"}\n" +; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/Fill.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/Fill.h new file mode 100644 index 0000000..35957e8 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/Fill.h @@ -0,0 +1,77 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + +#pragma once + +#include +#include + +namespace adl +{ + +class FillBase +{ + public: + enum Option + { + + }; +}; + +template +class Fill +{ + public: + typedef Launcher::BufferInfo BufferInfo; + + struct ConstData + { + int4 m_data; + int m_offset; + int m_n; + int m_padding[2]; + }; + + struct Data + { + const Device* m_device; + Kernel* m_fillIntKernel; + Kernel* m_fillInt2Kernel; + Kernel* m_fillInt4Kernel; + Buffer* m_constBuffer; + }; + + static + Data* allocate(const Device* deviceData); + + static + void deallocate(Data* data); + + static + void execute(Data* data, Buffer& src, const int& value, int n, int offset = 0); + + static + void execute(Data* data, Buffer& src, const int2& value, int n, int offset = 0); + + static + void execute(Data* data, Buffer& src, const int4& value, int n, int offset = 0); + +}; + + +#include +#include + +}; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/Fill.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/Fill.inl new file mode 100644 index 0000000..913db9b --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/Fill.inl @@ -0,0 +1,123 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +//#define PATH "..\\..\\AdlPrimitives\\Fill\\FillKernels" +#define PATH "..\\..\\opencl\\primitives\\AdlPrimitives\\Fill\\FillKernels" +#define KERNEL0 "FillIntKernel" +#define KERNEL1 "FillInt2Kernel" +#define KERNEL2 "FillInt4Kernel" + +#include +#include + + +template +typename Fill::Data* Fill::allocate( const Device* device ) +{ + ADLASSERT( TYPE == device->m_type ); + + const char* src[] = +#if defined(ADL_LOAD_KERNEL_FROM_STRING) + {fillKernelsCL, fillKernelsDX11}; +#else + {0,0}; +#endif + + Data* data = new Data; + data->m_device = device; + data->m_fillIntKernel = device->getKernel( PATH, KERNEL0, 0, src[TYPE] ); + data->m_fillInt2Kernel = device->getKernel( PATH, KERNEL1, 0, src[TYPE] ); + data->m_fillInt4Kernel = device->getKernel( PATH, KERNEL2, 0, src[TYPE] ); + data->m_constBuffer = new Buffer( device, 1, BufferBase::BUFFER_CONST ); + + return data; +} + +template +void Fill::deallocate( Data* data ) +{ + delete data->m_constBuffer; + delete data; +} + +template +void Fill::execute(Data* data, Buffer& src, const int& value, int n, int offset) +{ + ADLASSERT( n>0 ); + ConstData constBuffer; + { + constBuffer.m_offset = offset; + constBuffer.m_n = n; + constBuffer.m_data = make_int4( value ); + } + + { + BufferInfo bInfo[] = { BufferInfo( &src ) }; + + Launcher launcher( data->m_device, data->m_fillIntKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer, constBuffer ); + launcher.launch1D( n ); + } +} + +template +void Fill::execute(Data* data, Buffer& src, const int2& value, int n, int offset) +{ + ADLASSERT( n>0 ); + ConstData constBuffer; + { + constBuffer.m_offset = offset; + constBuffer.m_n = n; + constBuffer.m_data = make_int4( value.x, value.y, 0, 0 ); + } + + { + BufferInfo bInfo[] = { BufferInfo( &src ) }; + + Launcher launcher( data->m_device, data->m_fillInt2Kernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer, constBuffer ); + launcher.launch1D( n ); + } +} + +template +void Fill::execute(Data* data, Buffer& src, const int4& value, int n, int offset) +{ + ADLASSERT( n>0 ); + ConstData constBuffer; + { + constBuffer.m_offset = offset; + constBuffer.m_n = n; + constBuffer.m_data = value; + } + + { + BufferInfo bInfo[] = { BufferInfo( &src ) }; + + Launcher launcher( data->m_device, data->m_fillInt4Kernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer, constBuffer ); + launcher.launch1D( n ); + } +} + +#undef PATH +#undef KERNEL0 +#undef KERNEL1 +#undef KERNEL2 + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillHost.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillHost.inl new file mode 100644 index 0000000..c6205fa --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillHost.inl @@ -0,0 +1,99 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + +template<> +class Fill +{ + public: + struct Data + { + }; + + static + Data* allocate(const Device* deviceData) + { + return 0; + } + + static + void deallocate(Data* data) + { + + } + + template + static + void executeImpl(Data* data, Buffer& src, const T& value, int n, int offset = 0) + { + ADLASSERT( src.getType() == TYPE_HOST ); + ADLASSERT( src.m_size >= offset+n ); + HostBuffer& hSrc = (HostBuffer&)src; + + for(int idx=offset; idx& src, const int& value, int n, int offset = 0) + { + executeImpl( data, src, value, n, offset ); + } + + static + void execute(Data* data, Buffer& src, const int2& value, int n, int offset = 0) + { + executeImpl( data, src, value, n, offset ); + } + + static + void execute(Data* data, Buffer& src, const int4& value, int n, int offset = 0) + { + executeImpl( data, src, value, n, offset ); + } + +/* + static + void execute(Data* data, Buffer& src, int value, int n, int offset = 0) + { + ADLASSERT( src.getType() == TYPE_HOST ); + ADLASSERT( src.m_size <= offset+n ); + HostBuffer& hSrc = (HostBuffer&)src; + + for(int idx=offset; idx& src, const int2& value, int n, int offset = 0) + { + ADLASSERT( src.getType() == TYPE_HOST ); + ADLASSERT( src.m_size <= offset+n ); + + } + + static + void execute(Data* data, Buffer& src, const int4& value, int n, int offset = 0) + { + ADLASSERT( src.getType() == TYPE_HOST ); + ADLASSERT( src.m_size <= offset+n ); + + } +*/ +}; + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillKernels.cl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillKernels.cl new file mode 100644 index 0000000..11a31b0 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillKernels.cl @@ -0,0 +1,81 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#pragma OPENCL EXTENSION cl_amd_printf : enable +#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable + +typedef unsigned int u32; +#define GET_GROUP_IDX get_group_id(0) +#define GET_LOCAL_IDX get_local_id(0) +#define GET_GLOBAL_IDX get_global_id(0) +#define GET_GROUP_SIZE get_local_size(0) +#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE) +#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE) +#define AtomInc(x) atom_inc(&(x)) +#define AtomInc1(x, out) out = atom_inc(&(x)) + +#define make_uint4 (uint4) +#define make_uint2 (uint2) +#define make_int2 (int2) + +typedef struct +{ + int4 m_data; + int m_offset; + int m_n; + int m_padding[2]; +} ConstBuffer; + + +__kernel +__attribute__((reqd_work_group_size(64,1,1))) +void FillIntKernel(__global int* dstInt, + ConstBuffer cb) +{ + int gIdx = GET_GLOBAL_IDX; + + if( gIdx < cb.m_n ) + { + dstInt[ cb.m_offset+gIdx ] = cb.m_data.x; + } +} + +__kernel +__attribute__((reqd_work_group_size(64,1,1))) +void FillInt2Kernel(__global int2* dstInt2, + ConstBuffer cb) +{ + int gIdx = GET_GLOBAL_IDX; + + if( gIdx < cb.m_n ) + { + dstInt2[ cb.m_offset+gIdx ] = make_int2( cb.m_data.x, cb.m_data.y ); + } +} + +__kernel +__attribute__((reqd_work_group_size(64,1,1))) +void FillInt4Kernel(__global int4* dstInt4, + ConstBuffer cb) +{ + int gIdx = GET_GLOBAL_IDX; + + if( gIdx < cb.m_n ) + { + dstInt4[ cb.m_offset+gIdx ] = cb.m_data; + } +} + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillKernels.hlsl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillKernels.hlsl new file mode 100644 index 0000000..ead907d --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillKernels.hlsl @@ -0,0 +1,79 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +typedef uint u32; + +#define GET_GROUP_IDX groupIdx.x +#define GET_LOCAL_IDX localIdx.x +#define GET_GLOBAL_IDX globalIdx.x +#define GROUP_LDS_BARRIER GroupMemoryBarrierWithGroupSync() +#define GROUP_MEM_FENCE +#define DEFAULT_ARGS uint3 globalIdx : SV_DispatchThreadID, uint3 localIdx : SV_GroupThreadID, uint3 groupIdx : SV_GroupID +#define AtomInc(x) InterlockedAdd(x, 1) +#define AtomInc1(x, out) InterlockedAdd(x, 1, out) + +#define make_uint4 uint4 +#define make_uint2 uint2 +#define make_int2 int2 + + +cbuffer CB : register( b0 ) +{ + int4 m_data; + int m_offset; + int m_n; + int m_padding[2]; +}; + + +RWStructuredBuffer dstInt : register( u0 ); + +[numthreads(64, 1, 1)] +void FillIntKernel( DEFAULT_ARGS ) +{ + int gIdx = GET_GLOBAL_IDX; + + if( gIdx < m_n ) + { + dstInt[ m_offset+gIdx ] = m_data.x; + } +} + +RWStructuredBuffer dstInt2 : register( u0 ); + +[numthreads(64, 1, 1)] +void FillInt2Kernel( DEFAULT_ARGS ) +{ + int gIdx = GET_GLOBAL_IDX; + + if( gIdx < m_n ) + { + dstInt2[ m_offset+gIdx ] = make_int2( m_data.x, m_data.y ); + } +} + +RWStructuredBuffer dstInt4 : register( u0 ); + +[numthreads(64, 1, 1)] +void FillInt4Kernel( DEFAULT_ARGS ) +{ + int gIdx = GET_GLOBAL_IDX; + + if( gIdx < m_n ) + { + dstInt4[ m_offset+gIdx ] = m_data; + } +} diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillKernelsCL.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillKernelsCL.h new file mode 100644 index 0000000..e2899ff --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillKernelsCL.h @@ -0,0 +1,71 @@ +static const char* fillKernelsCL= \ +"/*\n" +" 2011 Takahiro Harada\n" +"*/\n" +"\n" +"#pragma OPENCL EXTENSION cl_amd_printf : enable\n" +"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n" +"\n" +"typedef unsigned int u32;\n" +"#define GET_GROUP_IDX get_group_id(0)\n" +"#define GET_LOCAL_IDX get_local_id(0)\n" +"#define GET_GLOBAL_IDX get_global_id(0)\n" +"#define GET_GROUP_SIZE get_local_size(0)\n" +"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n" +"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n" +"#define AtomInc(x) atom_inc(&(x))\n" +"#define AtomInc1(x, out) out = atom_inc(&(x))\n" +"\n" +"#define make_uint4 (uint4)\n" +"#define make_uint2 (uint2)\n" +"#define make_int2 (int2)\n" +"\n" +"typedef struct\n" +"{\n" +" int4 m_data;\n" +" int m_offset;\n" +" int m_n;\n" +" int m_padding[2];\n" +"} ConstBuffer;\n" +"\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(64,1,1)))\n" +"void FillIntKernel(__global int* dstInt, \n" +" ConstBuffer cb)\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"\n" +" if( gIdx < cb.m_n )\n" +" {\n" +" dstInt[ cb.m_offset+gIdx ] = cb.m_data.x;\n" +" }\n" +"}\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(64,1,1)))\n" +"void FillInt2Kernel(__global int2* dstInt2, \n" +" ConstBuffer cb)\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"\n" +" if( gIdx < cb.m_n )\n" +" {\n" +" dstInt2[ cb.m_offset+gIdx ] = make_int2( cb.m_data.x, cb.m_data.y );\n" +" }\n" +"}\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(64,1,1)))\n" +"void FillInt4Kernel(__global int4* dstInt4, \n" +" ConstBuffer cb)\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"\n" +" if( gIdx < cb.m_n )\n" +" {\n" +" dstInt4[ cb.m_offset+gIdx ] = cb.m_data;\n" +" }\n" +"}\n" +"\n" +; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillKernelsDX11.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillKernelsDX11.h new file mode 100644 index 0000000..1cdc6ab --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Fill/FillKernelsDX11.h @@ -0,0 +1,69 @@ +static const char* fillKernelsDX11= \ +"/*\n" +" 2011 Takahiro Harada\n" +"*/\n" +"\n" +"typedef uint u32;\n" +"\n" +"#define GET_GROUP_IDX groupIdx.x\n" +"#define GET_LOCAL_IDX localIdx.x\n" +"#define GET_GLOBAL_IDX globalIdx.x\n" +"#define GROUP_LDS_BARRIER GroupMemoryBarrierWithGroupSync()\n" +"#define GROUP_MEM_FENCE\n" +"#define DEFAULT_ARGS uint3 globalIdx : SV_DispatchThreadID, uint3 localIdx : SV_GroupThreadID, uint3 groupIdx : SV_GroupID\n" +"#define AtomInc(x) InterlockedAdd(x, 1)\n" +"#define AtomInc1(x, out) InterlockedAdd(x, 1, out)\n" +"\n" +"#define make_uint4 uint4\n" +"#define make_uint2 uint2\n" +"#define make_int2 int2\n" +"\n" +"\n" +"cbuffer CB : register( b0 )\n" +"{\n" +" int4 m_data;\n" +" int m_offset;\n" +" int m_n;\n" +" int m_padding[2];\n" +"};\n" +"\n" +"\n" +"RWStructuredBuffer dstInt : register( u0 );\n" +"\n" +"[numthreads(64, 1, 1)]\n" +"void FillIntKernel( DEFAULT_ARGS )\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"\n" +" if( gIdx < m_n )\n" +" {\n" +" dstInt[ m_offset+gIdx ] = m_data.x;\n" +" }\n" +"}\n" +"\n" +"RWStructuredBuffer dstInt2 : register( u0 );\n" +"\n" +"[numthreads(64, 1, 1)]\n" +"void FillInt2Kernel( DEFAULT_ARGS )\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"\n" +" if( gIdx < m_n )\n" +" {\n" +" dstInt2[ m_offset+gIdx ] = make_int2( m_data.x, m_data.y );\n" +" }\n" +"}\n" +"\n" +"RWStructuredBuffer dstInt4 : register( u0 );\n" +"\n" +"[numthreads(64, 1, 1)]\n" +"void FillInt4Kernel( DEFAULT_ARGS )\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +"\n" +" if( gIdx < m_n )\n" +" {\n" +" dstInt4[ m_offset+gIdx ] = m_data;\n" +" }\n" +"}\n" +; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Array.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Array.h new file mode 100644 index 0000000..5a63eee --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Array.h @@ -0,0 +1,231 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + +#ifndef ARRAY_H +#define ARRAY_H + +#include +#include +#include +#include + +namespace adl +{ + +template +class Array +{ + public: + __inline + Array(); + __inline + Array(int size); + __inline + ~Array(); + __inline + T& operator[] (int idx); + __inline + const T& operator[] (int idx) const; + __inline + void pushBack(const T& elem); + __inline + void popBack(); + __inline + void clear(); + __inline + void setSize(int size); + __inline + int getSize() const; + __inline + T* begin(); + __inline + const T* begin() const; + __inline + T* end(); + __inline + const T* end() const; + __inline + int indexOf(const T& data) const; + __inline + void removeAt(int idx); + __inline + T& expandOne(); + + private: + Array(const Array& a){} + + private: + enum + { + DEFAULT_SIZE = 128, + INCREASE_SIZE = 128, + }; + + T* m_data; + int m_size; + int m_capacity; +}; + +template +Array::Array() +{ + m_size = 0; + m_capacity = DEFAULT_SIZE; +// m_data = new T[ m_capacity ]; + m_data = (T*)_aligned_malloc(sizeof(T)*m_capacity, 16); + for(int i=0; i +Array::Array(int size) +{ + m_size = size; + m_capacity = size; +// m_data = new T[ m_capacity ]; + m_data = (T*)_aligned_malloc(sizeof(T)*m_capacity, 16); + for(int i=0; i +Array::~Array() +{ + if( m_data ) + { +// delete [] m_data; + _aligned_free( m_data ); + m_data = NULL; + } +} + +template +T& Array::operator[](int idx) +{ + ADLASSERT(idx +const T& Array::operator[](int idx) const +{ + ADLASSERT(idx +void Array::pushBack(const T& elem) +{ + if( m_size == m_capacity ) + { + int oldCap = m_capacity; + m_capacity += INCREASE_SIZE; +// T* s = new T[m_capacity]; + T* s = (T*)_aligned_malloc(sizeof(T)*m_capacity, 16); + memcpy( s, m_data, sizeof(T)*oldCap ); +// delete [] m_data; + _aligned_free( m_data ); + m_data = s; + } + m_data[ m_size++ ] = elem; +} + +template +void Array::popBack() +{ + ADLASSERT( m_size>0 ); + m_size--; +} + +template +void Array::clear() +{ + m_size = 0; +} + +template +void Array::setSize(int size) +{ + if( size > m_capacity ) + { + int oldCap = m_capacity; + m_capacity = size; +// T* s = new T[m_capacity]; + T* s = (T*)_aligned_malloc(sizeof(T)*m_capacity, 16); + for(int i=0; i +int Array::getSize() const +{ + return m_size; +} + +template +const T* Array::begin() const +{ + return m_data; +} + +template +T* Array::begin() +{ + return m_data; +} + +template +T* Array::end() +{ + return m_data+m_size; +} + +template +const T* Array::end() const +{ + return m_data+m_size; +} + +template +int Array::indexOf(const T& data) const +{ + for(int i=0; i +void Array::removeAt(int idx) +{ + ADLASSERT(idx +T& Array::expandOne() +{ + setSize( m_size+1 ); + return m_data[ m_size-1 ]; +} + +}; + +#endif + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Float2.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Float2.inl new file mode 100644 index 0000000..4b2a9e7 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Float2.inl @@ -0,0 +1,173 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +__inline +float2 make_float2(float x, float y) +{ + float2 v; + v.s[0] = x; v.s[1] = y; + return v; +} + +__inline +float2 make_float2(float x) +{ + return make_float2(x,x); +} + +__inline +float2 make_float2(const int2& x) +{ + return make_float2((float)x.s[0], (float)x.s[1]); +} + + + + +__inline +float2 operator-(const float2& a) +{ + return make_float2(-a.x, -a.y); +} + +__inline +float2 operator*(const float2& a, const float2& b) +{ + float2 out; + out.s[0] = a.s[0]*b.s[0]; + out.s[1] = a.s[1]*b.s[1]; + return out; +} + +__inline +float2 operator*(float a, const float2& b) +{ + return make_float2(a*b.s[0], a*b.s[1]); +} + +__inline +float2 operator*(const float2& b, float a) +{ + return make_float2(a*b.s[0], a*b.s[1]); +} + +__inline +void operator*=(float2& a, const float2& b) +{ + a.s[0]*=b.s[0]; + a.s[1]*=b.s[1]; +} + +__inline +void operator*=(float2& a, float b) +{ + a.s[0]*=b; + a.s[1]*=b; +} + +__inline +float2 operator/(const float2& a, const float2& b) +{ + float2 out; + out.s[0] = a.s[0]/b.s[0]; + out.s[1] = a.s[1]/b.s[1]; + return out; +} + +__inline +float2 operator/(const float2& b, float a) +{ + return make_float2(b.s[0]/a, b.s[1]/a); +} + +__inline +void operator/=(float2& a, const float2& b) +{ + a.s[0]/=b.s[0]; + a.s[1]/=b.s[1]; +} + +__inline +void operator/=(float2& a, float b) +{ + a.s[0]/=b; + a.s[1]/=b; +} +// + +__inline +float2 operator+(const float2& a, const float2& b) +{ + float2 out; + out.s[0] = a.s[0]+b.s[0]; + out.s[1] = a.s[1]+b.s[1]; + return out; +} + +__inline +float2 operator+(const float2& a, float b) +{ + float2 out; + out.s[0] = a.s[0]+b; + out.s[1] = a.s[1]+b; + return out; +} + +__inline +float2 operator-(const float2& a, const float2& b) +{ + float2 out; + out.s[0] = a.s[0]-b.s[0]; + out.s[1] = a.s[1]-b.s[1]; + return out; +} + +__inline +float2 operator-(const float2& a, float b) +{ + float2 out; + out.s[0] = a.s[0]-b; + out.s[1] = a.s[1]-b; + return out; +} + +__inline +void operator+=(float2& a, const float2& b) +{ + a.s[0]+=b.s[0]; + a.s[1]+=b.s[1]; +} + +__inline +void operator+=(float2& a, float b) +{ + a.s[0]+=b; + a.s[1]+=b; +} + +__inline +void operator-=(float2& a, const float2& b) +{ + a.s[0]-=b.s[0]; + a.s[1]-=b.s[1]; +} + +__inline +void operator-=(float2& a, float b) +{ + a.s[0]-=b; + a.s[1]-=b; +} diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Float4.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Float4.inl new file mode 100644 index 0000000..458a91f --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Float4.inl @@ -0,0 +1,375 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +//#define CHECK_ALIGNMENT(a) ADLASSERT((u32(&(a)) & 0xf) == 0); +#define CHECK_ALIGNMENT(a) a; + + +__inline +float4 make_float4(float x, float y, float z, float w = 0.f) +{ + float4 v; + v.x = x; v.y = y; v.z = z; v.w = w; + return v; +} + +__inline +float4 make_float4(float x) +{ + return make_float4(x,x,x,x); +} + +__inline +float4 make_float4(const int4& x) +{ + return make_float4((float)x.s[0], (float)x.s[1], (float)x.s[2], (float)x.s[3]); +} + +__inline +int4 make_int4(int x, int y, int z, int w = 0) +{ + int4 v; + v.s[0] = x; v.s[1] = y; v.s[2] = z; v.s[3] = w; + return v; +} + +__inline +int4 make_int4(int x) +{ + return make_int4(x,x,x,x); +} + +__inline +int4 make_int4(const float4& x) +{ + return make_int4((int)x.x, (int)x.y, (int)x.z, (int)x.w); +} + +__inline +int2 make_int2(int a, int b) +{ + int2 ans; ans.x = a; ans.y = b; + return ans; +} + +__inline +bool operator ==(const int2& a, const int2& b) +{ + return a.x==b.x && a.y==b.y; +} + +__inline +bool operator ==(const int4& a, const int4& b) +{ + return a.x==b.x && a.y==b.y && a.z==b.z && a.w==b.w; +} + +__inline +bool operator ==(const float2& a, const float2& b) +{ + return a.x==b.x && a.y==b.y; +} + +__inline +bool operator ==(const float4& a, const float4& b) +{ + return a.x==b.x && a.y==b.y && a.z==b.z && a.w==b.w; +} + +__inline +float4 operator-(const float4& a) +{ + return make_float4(-a.x, -a.y, -a.z, -a.w); +} + +__inline +float4 operator*(const float4& a, const float4& b) +{ +// ADLASSERT((u32(&a) & 0xf) == 0); + + float4 out; + out.s[0] = a.s[0]*b.s[0]; + out.s[1] = a.s[1]*b.s[1]; + out.s[2] = a.s[2]*b.s[2]; + out.s[3] = a.s[3]*b.s[3]; + return out; +} + +__inline +float4 operator*(float a, const float4& b) +{ + return make_float4(a*b.s[0], a*b.s[1], a*b.s[2], a*b.s[3]); +} + +__inline +float4 operator*(const float4& b, float a) +{ + CHECK_ALIGNMENT(b); + + return make_float4(a*b.s[0], a*b.s[1], a*b.s[2], a*b.s[3]); +} + +__inline +void operator*=(float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + a.s[0]*=b.s[0]; + a.s[1]*=b.s[1]; + a.s[2]*=b.s[2]; + a.s[3]*=b.s[3]; +} + +__inline +void operator*=(float4& a, float b) +{ + CHECK_ALIGNMENT(a); + + a.s[0]*=b; + a.s[1]*=b; + a.s[2]*=b; + a.s[3]*=b; +} +/* +__inline +bool operator ==(const float4& a, const float4& b) +{ + + +} +*/ +// +__inline +float4 operator/(const float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + float4 out; + out.s[0] = a.s[0]/b.s[0]; + out.s[1] = a.s[1]/b.s[1]; + out.s[2] = a.s[2]/b.s[2]; + out.s[3] = a.s[3]/b.s[3]; + return out; +} + +__inline +float4 operator/(const float4& b, float a) +{ + CHECK_ALIGNMENT(b); + + return make_float4(b.s[0]/a, b.s[1]/a, b.s[2]/a, b.s[3]/a); +} + +__inline +void operator/=(float4& a, const float4& b) +{ + a.s[0]/=b.s[0]; + a.s[1]/=b.s[1]; + a.s[2]/=b.s[2]; + a.s[3]/=b.s[3]; +} + +__inline +void operator/=(float4& a, float b) +{ + ADLASSERT((u32(&a) & 0xf) == 0); + + a.s[0]/=b; + a.s[1]/=b; + a.s[2]/=b; + a.s[3]/=b; +} +// + +__inline +float4 operator+(const float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + float4 out; + out.s[0] = a.s[0]+b.s[0]; + out.s[1] = a.s[1]+b.s[1]; + out.s[2] = a.s[2]+b.s[2]; + out.s[3] = a.s[3]+b.s[3]; + return out; +} + +__inline +float4 operator+(const float4& a, float b) +{ + CHECK_ALIGNMENT(a); + + float4 out; + out.s[0] = a.s[0]+b; + out.s[1] = a.s[1]+b; + out.s[2] = a.s[2]+b; + out.s[3] = a.s[3]+b; + return out; +} + +__inline +float4 operator-(const float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + float4 out; + out.s[0] = a.s[0]-b.s[0]; + out.s[1] = a.s[1]-b.s[1]; + out.s[2] = a.s[2]-b.s[2]; + out.s[3] = a.s[3]-b.s[3]; + return out; +} + +__inline +float4 operator-(const float4& a, float b) +{ + CHECK_ALIGNMENT(a); + + float4 out; + out.s[0] = a.s[0]-b; + out.s[1] = a.s[1]-b; + out.s[2] = a.s[2]-b; + out.s[3] = a.s[3]-b; + return out; +} + +__inline +void operator+=(float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + a.s[0]+=b.s[0]; + a.s[1]+=b.s[1]; + a.s[2]+=b.s[2]; + a.s[3]+=b.s[3]; +} + +__inline +void operator+=(float4& a, float b) +{ + CHECK_ALIGNMENT(a); + + a.s[0]+=b; + a.s[1]+=b; + a.s[2]+=b; + a.s[3]+=b; +} + +__inline +void operator-=(float4& a, const float4& b) +{ + CHECK_ALIGNMENT(a); + + a.s[0]-=b.s[0]; + a.s[1]-=b.s[1]; + a.s[2]-=b.s[2]; + a.s[3]-=b.s[3]; +} + +__inline +void operator-=(float4& a, float b) +{ + CHECK_ALIGNMENT(a); + + a.s[0]-=b; + a.s[1]-=b; + a.s[2]-=b; + a.s[3]-=b; +} + + + + + +__inline +float4 cross3(const float4& a, const float4& b) +{ + return make_float4(a.s[1]*b.s[2]-a.s[2]*b.s[1], + a.s[2]*b.s[0]-a.s[0]*b.s[2], + a.s[0]*b.s[1]-a.s[1]*b.s[0], + 0); +} + +__inline +float dot3F4(const float4& a, const float4& b) +{ + return a.x*b.x+a.y*b.y+a.z*b.z; +} + +__inline +float length3(const float4& a) +{ + return sqrtf(dot3F4(a,a)); +} + +__inline +float dot4(const float4& a, const float4& b) +{ + return a.x*b.x+a.y*b.y+a.z*b.z+a.w*b.w; +} + +// for height +__inline +float dot3w1(const float4& point, const float4& eqn) +{ + return point.x*eqn.x+point.y*eqn.y+point.z*eqn.z+eqn.w; +} + +__inline +float4 normalize3(const float4& a) +{ + float length = sqrtf(dot3F4(a, a)); + return 1.f/length * a; +} + +__inline +float4 normalize4(const float4& a) +{ + float length = sqrtf(dot4(a, a)); + return 1.f/length * a; +} + +__inline +float4 createEquation(const float4& a, const float4& b, const float4& c) +{ + float4 eqn; + float4 ab = b-a; + float4 ac = c-a; + eqn = normalize3( cross3(ab, ac) ); + eqn.w = -dot3F4(eqn,a); + return eqn; +} + +__inline +float intersectPlaneLine( const float4& planeEqn, const float4& vec, const float4& orig ) +{ + return (-planeEqn.w - dot3F4(planeEqn, orig))/dot3F4(planeEqn, vec); +} + +template<> +__inline +float4 max2(const float4& a, const float4& b) +{ + return make_float4( max2(a.x,b.x), max2(a.y,b.y), max2(a.z,b.z), max2(a.w,b.w) ); +} + +template<> +__inline +float4 min2(const float4& a, const float4& b) +{ + return make_float4( min2(a.x,b.x), min2(a.y,b.y), min2(a.z,b.z), min2(a.w,b.w) ); +} + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Math.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Math.h new file mode 100644 index 0000000..0126e72 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Math.h @@ -0,0 +1,224 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#ifndef CL_MATH_H +#define CL_MATH_H + +#include +#include +#include +#include + + +#include + +#include +#define pxSort std::sort + +#define PI 3.14159265358979323846f +#define NEXTMULTIPLEOF(num, alignment) (((num)/(alignment) + (((num)%(alignment)==0)?0:1))*(alignment)) + + +#define _MEM_CLASSALIGN16 __declspec(align(16)) +#define _MEM_ALIGNED_ALLOCATOR16 void* operator new(size_t size) { return _aligned_malloc( size, 16 ); } \ + void operator delete(void *p) { _aligned_free( p ); } \ + void* operator new[](size_t size) { return _aligned_malloc( size, 16 ); } \ + void operator delete[](void *p) { _aligned_free( p ); } \ + void* operator new(size_t size, void* p) { return p; } \ + void operator delete(void *p, void* pp) {} + +namespace adl +{ + +template +T nextPowerOf2(T n) +{ + n -= 1; + for(int i=0; i>i); + return n+1; +} + +typedef unsigned int u32; +typedef unsigned short u16; +typedef unsigned char u8; + +_MEM_CLASSALIGN16 +struct float4 +{ + _MEM_ALIGNED_ALLOCATOR16; + union + { + struct + { + float x,y,z,w; + }; + struct + { + float s[4]; + }; + __m128 m_quad; + }; +}; + +_MEM_CLASSALIGN16 +struct int4 +{ + _MEM_ALIGNED_ALLOCATOR16; + union + { + struct + { + int x,y,z,w; + }; + struct + { + int s[4]; + }; + }; +}; + +_MEM_CLASSALIGN16 +struct uint4 +{ + _MEM_ALIGNED_ALLOCATOR16; + union + { + struct + { + u32 x,y,z,w; + }; + struct + { + u32 s[4]; + }; + }; +}; + +struct int2 +{ + union + { + struct + { + int x,y; + }; + struct + { + int s[2]; + }; + }; +}; + +struct float2 +{ + union + { + struct + { + float x,y; + }; + struct + { + float s[2]; + }; + }; +}; + +template +__inline +T max2(const T& a, const T& b) +{ + return (a>b)? a:b; +} + +template +__inline +T min2(const T& a, const T& b) +{ + return (a +#include + + +template +void swap2(T& a, T& b) +{ + T tmp = a; + a = b; + b = tmp; +} + + +__inline +void seedRandom(int seed) +{ + srand( seed ); +} + +template +__inline +T getRandom(const T& minV, const T& maxV) +{ + float r = (rand()%10000)/10000.f; + T range = maxV - minV; + return (T)(minV + r*range); +} + +template<> +__inline +float4 getRandom(const float4& minV, const float4& maxV) +{ + float4 r = make_float4( (rand()%10000)/10000.f, (rand()%10000)/10000.f, (rand()%10000)/10000.f, (rand()%10000)/10000.f ); + float4 range = maxV - minV; + return (minV + r*range); +} + + + +template +T* addByteOffset(void* baseAddr, u32 offset) +{ + return (T*)(((u32)baseAddr)+offset); +} + + +struct Pair32 +{ + Pair32(){} + Pair32(u32 a, u32 b) : m_a(a), m_b(b){} + + u32 m_a; + u32 m_b; +}; + +struct PtrPair +{ + PtrPair(){} + PtrPair(void* a, void* b) : m_a(a), m_b(b){} + template + PtrPair(T* a, T* b) : m_a((void*)a), m_b((void*)b){} + + void* m_a; + void* m_b; +}; + +}; + +#endif diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/MathCL.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/MathCL.h new file mode 100644 index 0000000..6e36881 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/MathCL.h @@ -0,0 +1,357 @@ + +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#pragma OPENCL EXTENSION cl_amd_printf : enable +#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable +#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable +#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable +#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable +#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable + +typedef unsigned int u32; +typedef unsigned short u16; +typedef unsigned char u8; + +#define GET_GROUP_IDX get_group_id(0) +#define GET_LOCAL_IDX get_local_id(0) +#define GET_GLOBAL_IDX get_global_id(0) +#define GET_GROUP_SIZE get_local_size(0) +#define GET_NUM_GROUPS get_num_groups(0) +#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE) +#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE) +#define AtomInc(x) atom_inc(&(x)) +#define AtomInc1(x, out) out = atom_inc(&(x)) +#define AppendInc(x, out) out = atomic_inc(x) +#define AtomAdd(x, value) atom_add(&(x), value) +#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value ) +#define AtomXhg(x, value) atom_xchg ( &(x), value ) + + +#define SELECT_UINT4( b, a, condition ) select( b,a,condition ) + +#define make_float4 (float4) +#define make_float2 (float2) +#define make_uint4 (uint4) +#define make_int4 (int4) +#define make_uint2 (uint2) +#define make_int2 (int2) + + +#define max2 max +#define min2 min + + +/////////////////////////////////////// +// Vector +/////////////////////////////////////// +__inline +float fastDiv(float numerator, float denominator) +{ + return native_divide(numerator, denominator); +// return numerator/denominator; +} + +__inline +float4 fastDiv4(float4 numerator, float4 denominator) +{ + return native_divide(numerator, denominator); +} + +__inline +float fastSqrtf(float f2) +{ + return native_sqrt(f2); +// return sqrt(f2); +} + +__inline +float fastRSqrt(float f2) +{ + return native_rsqrt(f2); +} + +__inline +float fastLength4(float4 v) +{ + return fast_length(v); +} + +__inline +float4 fastNormalize4(float4 v) +{ + return fast_normalize(v); +} + + +__inline +float sqrtf(float a) +{ +// return sqrt(a); + return native_sqrt(a); +} + +__inline +float4 cross3(float4 a, float4 b) +{ + return cross(a,b); +} + +__inline +float dot3F4(float4 a, float4 b) +{ + float4 a1 = make_float4(a.xyz,0.f); + float4 b1 = make_float4(b.xyz,0.f); + return dot(a1, b1); +} + +__inline +float length3(const float4 a) +{ + return sqrtf(dot3F4(a,a)); +} + +__inline +float dot4(const float4 a, const float4 b) +{ + return dot( a, b ); +} + +// for height +__inline +float dot3w1(const float4 point, const float4 eqn) +{ + return dot3F4(point,eqn) + eqn.w; +} + +__inline +float4 normalize3(const float4 a) +{ + float4 n = make_float4(a.x, a.y, a.z, 0.f); + return fastNormalize4( n ); +// float length = sqrtf(dot3F4(a, a)); +// return 1.f/length * a; +} + +__inline +float4 normalize4(const float4 a) +{ + float length = sqrtf(dot4(a, a)); + return 1.f/length * a; +} + +__inline +float4 createEquation(const float4 a, const float4 b, const float4 c) +{ + float4 eqn; + float4 ab = b-a; + float4 ac = c-a; + eqn = normalize3( cross3(ab, ac) ); + eqn.w = -dot3F4(eqn,a); + return eqn; +} + +/////////////////////////////////////// +// Matrix3x3 +/////////////////////////////////////// + +typedef struct +{ + float4 m_row[3]; +}Matrix3x3; + +__inline +Matrix3x3 mtZero(); + +__inline +Matrix3x3 mtIdentity(); + +__inline +Matrix3x3 mtTranspose(Matrix3x3 m); + +__inline +Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b); + +__inline +float4 mtMul1(Matrix3x3 a, float4 b); + +__inline +float4 mtMul3(float4 a, Matrix3x3 b); + +__inline +Matrix3x3 mtZero() +{ + Matrix3x3 m; + m.m_row[0] = (float4)(0.f); + m.m_row[1] = (float4)(0.f); + m.m_row[2] = (float4)(0.f); + return m; +} + +__inline +Matrix3x3 mtIdentity() +{ + Matrix3x3 m; + m.m_row[0] = (float4)(1,0,0,0); + m.m_row[1] = (float4)(0,1,0,0); + m.m_row[2] = (float4)(0,0,1,0); + return m; +} + +__inline +Matrix3x3 mtTranspose(Matrix3x3 m) +{ + Matrix3x3 out; + out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f); + out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f); + out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f); + return out; +} + +__inline +Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b) +{ + Matrix3x3 transB; + transB = mtTranspose( b ); + Matrix3x3 ans; + // why this doesn't run when 0ing in the for{} + a.m_row[0].w = 0.f; + a.m_row[1].w = 0.f; + a.m_row[2].w = 0.f; + for(int i=0; i<3; i++) + { +// a.m_row[i].w = 0.f; + ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]); + ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]); + ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]); + ans.m_row[i].w = 0.f; + } + return ans; +} + +__inline +float4 mtMul1(Matrix3x3 a, float4 b) +{ + float4 ans; + ans.x = dot3F4( a.m_row[0], b ); + ans.y = dot3F4( a.m_row[1], b ); + ans.z = dot3F4( a.m_row[2], b ); + ans.w = 0.f; + return ans; +} + +__inline +float4 mtMul3(float4 a, Matrix3x3 b) +{ + float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0); + float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0); + float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0); + + float4 ans; + ans.x = dot3F4( a, colx ); + ans.y = dot3F4( a, coly ); + ans.z = dot3F4( a, colz ); + return ans; +} + +/////////////////////////////////////// +// Quaternion +/////////////////////////////////////// + +typedef float4 Quaternion; + +__inline +Quaternion qtMul(Quaternion a, Quaternion b); + +__inline +Quaternion qtNormalize(Quaternion in); + +__inline +float4 qtRotate(Quaternion q, float4 vec); + +__inline +Quaternion qtInvert(Quaternion q); + +__inline +Matrix3x3 qtGetRotationMatrix(Quaternion q); + + + +__inline +Quaternion qtMul(Quaternion a, Quaternion b) +{ + Quaternion ans; + ans = cross3( a, b ); + ans += a.w*b+b.w*a; +// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z); + ans.w = a.w*b.w - dot3F4(a, b); + return ans; +} + +__inline +Quaternion qtNormalize(Quaternion in) +{ + return fastNormalize4(in); +// in /= length( in ); +// return in; +} +__inline +float4 qtRotate(Quaternion q, float4 vec) +{ + Quaternion qInv = qtInvert( q ); + float4 vcpy = vec; + vcpy.w = 0.f; + float4 out = qtMul(qtMul(q,vcpy),qInv); + return out; +} + +__inline +Quaternion qtInvert(Quaternion q) +{ + return (Quaternion)(-q.xyz, q.w); +} + +__inline +float4 qtInvRotate(const Quaternion q, float4 vec) +{ + return qtRotate( qtInvert( q ), vec ); +} + +__inline +Matrix3x3 qtGetRotationMatrix(Quaternion quat) +{ + float4 quat2 = (float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f); + Matrix3x3 out; + + out.m_row[0].x=1-2*quat2.y-2*quat2.z; + out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z; + out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y; + out.m_row[0].w = 0.f; + + out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z; + out.m_row[1].y=1-2*quat2.x-2*quat2.z; + out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x; + out.m_row[1].w = 0.f; + + out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y; + out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x; + out.m_row[2].z=1-2*quat2.x-2*quat2.y; + out.m_row[2].w = 0.f; + + return out; +} + + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Matrix3x3.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Matrix3x3.h new file mode 100644 index 0000000..d681768 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Matrix3x3.h @@ -0,0 +1,197 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + +#ifndef MATRIX3X3_H +#define MATRIX3X3_H + +#include + +/////////////////////////////////////// +// Matrix3x3 +/////////////////////////////////////// +namespace adl +{ + +typedef +_MEM_CLASSALIGN16 struct +{ + _MEM_ALIGNED_ALLOCATOR16; + float4 m_row[3]; +}Matrix3x3; + +__inline +Matrix3x3 mtZero(); + +__inline +Matrix3x3 mtIdentity(); + +__inline +Matrix3x3 mtDiagonal(float a, float b, float c); + +__inline +Matrix3x3 mtTranspose(const Matrix3x3& m); + +__inline +Matrix3x3 mtMul(const Matrix3x3& a, const Matrix3x3& b); + +__inline +float4 mtMul1(const Matrix3x3& a, const float4& b); + +__inline +Matrix3x3 mtMul2(float a, const Matrix3x3& b); + +__inline +float4 mtMul3(const float4& b, const Matrix3x3& a); + +__inline +Matrix3x3 mtInvert(const Matrix3x3& m); + +__inline +Matrix3x3 mtZero() +{ + Matrix3x3 m; + m.m_row[0] = make_float4(0.f); + m.m_row[1] = make_float4(0.f); + m.m_row[2] = make_float4(0.f); + return m; +} + +__inline +Matrix3x3 mtIdentity() +{ + Matrix3x3 m; + m.m_row[0] = make_float4(1,0,0); + m.m_row[1] = make_float4(0,1,0); + m.m_row[2] = make_float4(0,0,1); + return m; +} + +__inline +Matrix3x3 mtDiagonal(float a, float b, float c) +{ + Matrix3x3 m; + m.m_row[0] = make_float4(a,0,0); + m.m_row[1] = make_float4(0,b,0); + m.m_row[2] = make_float4(0,0,c); + return m; +} + +__inline +Matrix3x3 mtTranspose(const Matrix3x3& m) +{ + Matrix3x3 out; + out.m_row[0] = make_float4(m.m_row[0].s[0], m.m_row[1].s[0], m.m_row[2].s[0], 0.f); + out.m_row[1] = make_float4(m.m_row[0].s[1], m.m_row[1].s[1], m.m_row[2].s[1], 0.f); + out.m_row[2] = make_float4(m.m_row[0].s[2], m.m_row[1].s[2], m.m_row[2].s[2], 0.f); + return out; +} + +__inline +Matrix3x3 mtMul(const Matrix3x3& a, const Matrix3x3& b) +{ + Matrix3x3 transB; + transB = mtTranspose( b ); + Matrix3x3 ans; + for(int i=0; i<3; i++) + { + ans.m_row[i].s[0] = dot3F4(a.m_row[i],transB.m_row[0]); + ans.m_row[i].s[1] = dot3F4(a.m_row[i],transB.m_row[1]); + ans.m_row[i].s[2] = dot3F4(a.m_row[i],transB.m_row[2]); + } + return ans; +} + +__inline +float4 mtMul1(const Matrix3x3& a, const float4& b) +{ + float4 ans; + ans.s[0] = dot3F4( a.m_row[0], b ); + ans.s[1] = dot3F4( a.m_row[1], b ); + ans.s[2] = dot3F4( a.m_row[2], b ); + return ans; +} + +__inline +Matrix3x3 mtMul2(float a, const Matrix3x3& b) +{ + Matrix3x3 ans; + ans.m_row[0] = a*b.m_row[0]; + ans.m_row[1] = a*b.m_row[1]; + ans.m_row[2] = a*b.m_row[2]; + return ans; +} + +__inline +float4 mtMul3(const float4& a, const Matrix3x3& b) +{ + float4 ans; + ans.x = a.x*b.m_row[0].x + a.y*b.m_row[1].x + a.z*b.m_row[2].x; + ans.y = a.x*b.m_row[0].y + a.y*b.m_row[1].y + a.z*b.m_row[2].y; + ans.z = a.x*b.m_row[0].z + a.y*b.m_row[1].z + a.z*b.m_row[2].z; + return ans; +} + +__inline +Matrix3x3 mtInvert(const Matrix3x3& m) +{ + float det = m.m_row[0].s[0]*m.m_row[1].s[1]*m.m_row[2].s[2]+m.m_row[1].s[0]*m.m_row[2].s[1]*m.m_row[0].s[2]+m.m_row[2].s[0]*m.m_row[0].s[1]*m.m_row[1].s[2] + -m.m_row[0].s[0]*m.m_row[2].s[1]*m.m_row[1].s[2]-m.m_row[2].s[0]*m.m_row[1].s[1]*m.m_row[0].s[2]-m.m_row[1].s[0]*m.m_row[0].s[1]*m.m_row[2].s[2]; + + ADLASSERT( det ); + + Matrix3x3 ans; + ans.m_row[0].s[0] = m.m_row[1].s[1]*m.m_row[2].s[2] - m.m_row[1].s[2]*m.m_row[2].s[1]; + ans.m_row[0].s[1] = m.m_row[0].s[2]*m.m_row[2].s[1] - m.m_row[0].s[1]*m.m_row[2].s[2]; + ans.m_row[0].s[2] = m.m_row[0].s[1]*m.m_row[1].s[2] - m.m_row[0].s[2]*m.m_row[1].s[1]; + ans.m_row[0].w = 0.f; + + ans.m_row[1].s[0] = m.m_row[1].s[2]*m.m_row[2].s[0] - m.m_row[1].s[0]*m.m_row[2].s[2]; + ans.m_row[1].s[1] = m.m_row[0].s[0]*m.m_row[2].s[2] - m.m_row[0].s[2]*m.m_row[2].s[0]; + ans.m_row[1].s[2] = m.m_row[0].s[2]*m.m_row[1].s[0] - m.m_row[0].s[0]*m.m_row[1].s[2]; + ans.m_row[1].w = 0.f; + + ans.m_row[2].s[0] = m.m_row[1].s[0]*m.m_row[2].s[1] - m.m_row[1].s[1]*m.m_row[2].s[0]; + ans.m_row[2].s[1] = m.m_row[0].s[1]*m.m_row[2].s[0] - m.m_row[0].s[0]*m.m_row[2].s[1]; + ans.m_row[2].s[2] = m.m_row[0].s[0]*m.m_row[1].s[1] - m.m_row[0].s[1]*m.m_row[1].s[0]; + ans.m_row[2].w = 0.f; + + ans = mtMul2((1.0f/det), ans); + return ans; +} + +__inline +Matrix3x3 mtSet( const float4& a, const float4& b, const float4& c ) +{ + Matrix3x3 m; + m.m_row[0] = a; + m.m_row[1] = b; + m.m_row[2] = c; + return m; +} + +__inline +Matrix3x3 operator+(const Matrix3x3& a, const Matrix3x3& b) +{ + Matrix3x3 out; + out.m_row[0] = a.m_row[0] + b.m_row[0]; + out.m_row[1] = a.m_row[1] + b.m_row[1]; + out.m_row[2] = a.m_row[2] + b.m_row[2]; + return out; +} + +}; + +#endif + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Quaternion.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Quaternion.h new file mode 100644 index 0000000..3eeef44 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Math/Quaternion.h @@ -0,0 +1,159 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#ifndef QUATERNION_H +#define QUATERNION_H + +#include + +namespace adl +{ + +typedef float4 Quaternion; + +__inline +Quaternion qtSet(const float4& axis, float angle); + +__inline +Quaternion qtMul(const Quaternion& a, const Quaternion& b); + +__inline +float4 qtRotate(const Quaternion& q, const float4& vec); + +__inline +float4 qtInvRotate(const Quaternion& q, const float4& vec); + +__inline +Quaternion qtInvert(const Quaternion& q); + +__inline +Matrix3x3 qtGetRotationMatrix(const Quaternion& quat); + +__inline +Quaternion qtNormalize(const Quaternion& q); + +__inline +Quaternion qtGetIdentity() { return make_float4(0,0,0,1); } + +__inline +Quaternion qtSet(const float4& axis, float angle) +{ + float4 nAxis = normalize3( axis ); + + Quaternion q; + q.s[0] = nAxis.s[0]*sin(angle/2); + q.s[1] = nAxis.s[1]*sin(angle/2); + q.s[2] = nAxis.s[2]*sin(angle/2); + q.s[3] = cos(angle/2); + return q; +} + +__inline +Quaternion qtMul(const Quaternion& a, const Quaternion& b) +{ + Quaternion ans; + ans = cross3( a, b ); + ans += a.s[3]*b + b.s[3]*a; + ans.s[3] = a.s[3]*b.s[3] - (a.s[0]*b.s[0]+a.s[1]*b.s[1]+a.s[2]*b.s[2]); + return ans; +} + +__inline +float4 qtRotate(const Quaternion& q, const float4& vec) +{ + Quaternion vecQ = vec; + vecQ.s[3] = 0.f; + Quaternion qInv = qtInvert( q ); + float4 out = qtMul(qtMul(q,vecQ),qInv); + return out; +} + +__inline +float4 qtInvRotate(const Quaternion& q, const float4& vec) +{ + return qtRotate( qtInvert( q ), vec ); +} + +__inline +Quaternion qtInvert(const Quaternion& q) +{ + Quaternion ans; + ans.s[0] = -q.s[0]; + ans.s[1] = -q.s[1]; + ans.s[2] = -q.s[2]; + ans.s[3] = q.s[3]; + return ans; +} + +__inline +Matrix3x3 qtGetRotationMatrix(const Quaternion& quat) +{ + float4 quat2 = make_float4(quat.s[0]*quat.s[0], quat.s[1]*quat.s[1], quat.s[2]*quat.s[2], 0.f); + Matrix3x3 out; + + out.m_row[0].s[0]=1-2*quat2.s[1]-2*quat2.s[2]; + out.m_row[0].s[1]=2*quat.s[0]*quat.s[1]-2*quat.s[3]*quat.s[2]; + out.m_row[0].s[2]=2*quat.s[0]*quat.s[2]+2*quat.s[3]*quat.s[1]; + out.m_row[0].s[3] = 0.f; + + out.m_row[1].s[0]=2*quat.s[0]*quat.s[1]+2*quat.s[3]*quat.s[2]; + out.m_row[1].s[1]=1-2*quat2.s[0]-2*quat2.s[2]; + out.m_row[1].s[2]=2*quat.s[1]*quat.s[2]-2*quat.s[3]*quat.s[0]; + out.m_row[1].s[3] = 0.f; + + out.m_row[2].s[0]=2*quat.s[0]*quat.s[2]-2*quat.s[3]*quat.s[1]; + out.m_row[2].s[1]=2*quat.s[1]*quat.s[2]+2*quat.s[3]*quat.s[0]; + out.m_row[2].s[2]=1-2*quat2.s[0]-2*quat2.s[1]; + out.m_row[2].s[3] = 0.f; + + return out; +} + +__inline +Quaternion qtGetQuaternion(const Matrix3x3* m) +{ + Quaternion q; + q.w = sqrtf( m[0].m_row[0].x + m[0].m_row[1].y + m[0].m_row[2].z + 1 ) * 0.5f; + float inv4w = 1.f/(4.f*q.w); + q.x = (m[0].m_row[2].y-m[0].m_row[1].z)*inv4w; + q.y = (m[0].m_row[0].z-m[0].m_row[2].x)*inv4w; + q.z = (m[0].m_row[1].x-m[0].m_row[0].y)*inv4w; + + return q; +} + +__inline +Quaternion qtNormalize(const Quaternion& q) +{ + return normalize4(q); +} + +__inline +float4 transform(const float4& p, const float4& translation, const Quaternion& orientation) +{ + return qtRotate( orientation, p ) + translation; +} + +__inline +float4 invTransform(const float4& p, const float4& translation, const Quaternion& orientation) +{ + return qtRotate( qtInvert( orientation ), p-translation ); // use qtInvRotate +} + +}; + +#endif + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Scan/PrefixScan.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Scan/PrefixScan.h new file mode 100644 index 0000000..db7566e --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Scan/PrefixScan.h @@ -0,0 +1,73 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + +#pragma once + +#include +#include + +namespace adl +{ + +class PrefixScanBase +{ + public: + enum Option + { + INCLUSIVE, + EXCLUSIVE + }; +}; + + +template +class PrefixScan : public PrefixScanBase +{ + public: + typedef Launcher::BufferInfo BufferInfo; + + enum + { + BLOCK_SIZE = 128 + }; + + struct Data + { + Option m_option; + const Device* m_device; + Kernel* m_localScanKernel; + Kernel* m_blockSumKernel; + Kernel* m_propagationKernel; + Buffer* m_workBuffer; + Buffer* m_constBuffer[3];// todo. dx need one for each + int m_maxSize; + }; + + static + Data* allocate(const Device* deviceData, int maxSize, Option option = EXCLUSIVE); + + static + void deallocate(Data* data); + + static + void execute(Data* data, Buffer& src, Buffer& dst, int n, u32* sum = 0); +}; + + + +#include +#include + +}; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Scan/PrefixScan.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Scan/PrefixScan.inl new file mode 100644 index 0000000..65e8c06 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Scan/PrefixScan.inl @@ -0,0 +1,125 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#define PATH "..\\..\\opencl\\primitives\\AdlPrimitives\\Scan\\PrefixScanKernels" +#define KERNEL0 "LocalScanKernel" +#define KERNEL1 "TopLevelScanKernel" +#define KERNEL2 "AddOffsetKernel" + +#include +#include + +template +typename PrefixScan::Data* PrefixScan::allocate(const Device* device, int maxSize, Option option) +{ + ADLASSERT( TYPE == device->m_type ); + + ADLASSERT( maxSize <= BLOCK_SIZE*2*2048 ); + + const char* src[] = +#if defined(ADL_LOAD_KERNEL_FROM_STRING) + {prefixScanKernelsCL, prefixScanKernelsDX11}; +#else + {0,0}; +#endif + Data* data = new Data; + data->m_device = device; + data->m_localScanKernel = device->getKernel( PATH, KERNEL0, 0, src[TYPE] ); + data->m_blockSumKernel = device->getKernel( PATH, KERNEL1, 0, src[TYPE] ); + data->m_propagationKernel = device->getKernel( PATH, KERNEL2, 0, src[TYPE] ); + + int bufSize = (NEXTMULTIPLEOF( max2( maxSize/BLOCK_SIZE, (int)BLOCK_SIZE ), BLOCK_SIZE )+1); + data->m_workBuffer = new Buffer( device, bufSize ); + data->m_constBuffer[0] = new Buffer( device, 1, BufferBase::BUFFER_CONST ); + data->m_constBuffer[1] = new Buffer( device, 1, BufferBase::BUFFER_CONST ); + data->m_constBuffer[2] = new Buffer( device, 1, BufferBase::BUFFER_CONST ); + + data->m_maxSize = maxSize; + data->m_option = option; + + return data; +} + +template +void PrefixScan::deallocate(Data* data) +{ + delete data->m_workBuffer; + delete data->m_constBuffer[0]; + delete data->m_constBuffer[1]; + delete data->m_constBuffer[2]; + delete data; +} + +template +void PrefixScan::execute(Data* data, Buffer& src, Buffer& dst, int n, u32* sum) +{ + ADLASSERT( data ); + ADLASSERT( n <= data->m_maxSize ); + ADLASSERT( data->m_option == EXCLUSIVE ); + const u32 numBlocks = u32( (n+BLOCK_SIZE*2-1)/(BLOCK_SIZE*2) ); + + + int4 constBuffer; + constBuffer.x = n; + constBuffer.y = numBlocks; + constBuffer.z = (int)nextPowerOf2( numBlocks ); + + Buffer* srcNative = BufferUtils::map( data->m_device, &src ); + Buffer* dstNative = BufferUtils::map( data->m_device, &dst ); + + { + BufferInfo bInfo[] = { BufferInfo( dstNative ), BufferInfo( srcNative ), BufferInfo( data->m_workBuffer ) }; + + Launcher launcher( data->m_device, data->m_localScanKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[0], constBuffer ); + launcher.launch1D( numBlocks*BLOCK_SIZE, BLOCK_SIZE ); + } + + { + BufferInfo bInfo[] = { BufferInfo( data->m_workBuffer ) }; + + Launcher launcher( data->m_device, data->m_blockSumKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[1], constBuffer ); + launcher.launch1D( BLOCK_SIZE, BLOCK_SIZE ); + } + + + if( numBlocks > 1 ) + { + BufferInfo bInfo[] = { BufferInfo( dstNative ), BufferInfo( data->m_workBuffer ) }; + Launcher launcher( data->m_device, data->m_propagationKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[2], constBuffer ); + launcher.launch1D( (numBlocks-1)*BLOCK_SIZE, BLOCK_SIZE ); + } + + DeviceUtils::waitForCompletion( data->m_device ); + if( sum ) + { + dstNative->read( sum, 1, n-1); + } + DeviceUtils::waitForCompletion( data->m_device ); + + BufferUtils::unmap( srcNative, &src ); + BufferUtils::unmap( dstNative, &dst ); +} + +#undef PATH +#undef KERNEL0 +#undef KERNEL1 +#undef KERNEL2 \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Scan/PrefixScanHost.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Scan/PrefixScanHost.inl new file mode 100644 index 0000000..44987f5 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Scan/PrefixScanHost.inl @@ -0,0 +1,74 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +template<> +class PrefixScan : public PrefixScanBase +{ + public: + struct Data + { + Option m_option; + }; + + static + Data* allocate(const Device* deviceData, int maxSize, Option option = EXCLUSIVE) + { + ADLASSERT( deviceData->m_type == TYPE_HOST ); + + Data* data = new Data; + data->m_option = option; + return data; + } + + static + void deallocate(Data* data) + { + delete data; + } + + static + void execute(Data* data, Buffer& src, Buffer& dst, int n, u32* sum = 0) + { + ADLASSERT( src.getType() == TYPE_HOST && dst.getType() == TYPE_HOST ); + HostBuffer& hSrc = (HostBuffer&)src; + HostBuffer& hDst = (HostBuffer&)dst; + + u32 s = 0; + if( data->m_option == EXCLUSIVE ) + { + for(int i=0; i>1; nActive>0; nActive>>=1, offset<<=1) + { + GROUP_LDS_BARRIER; + for(int iIdx=lIdx; iIdx>= 1; + for(int nActive=1; nActive>=1 ) + { + GROUP_LDS_BARRIER; + for( int iIdx = lIdx; iIdx dst : register( u0 ); +RWStructuredBuffer src : register( u1 ); +RWStructuredBuffer sumBuffer : register( u2 ); + + +groupshared u32 ldsData[2048]; + +u32 ScanExclusive(u32 n, int lIdx, int lSize) +{ + u32 blocksum; + int offset = 1; + for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1) + { + GROUP_LDS_BARRIER; + for(int iIdx=lIdx; iIdx>= 1; + for(int nActive=1; nActive>=1 ) + { + GROUP_LDS_BARRIER; + for( int iIdx = lIdx; iIdx blockSum2 : register( u1 ); + +[numthreads(WG_SIZE, 1, 1)] +void AddOffsetKernel(uint3 globalIdx : SV_DispatchThreadID, uint3 localIdx : SV_GroupThreadID, uint3 groupIdx : SV_GroupID) +{ + const u32 blockSize = WG_SIZE*2; + + int myIdx = GET_GROUP_IDX+1; + int llIdx = GET_LOCAL_IDX; + + u32 iBlockSum = blockSum2[myIdx]; + + int endValue = min((myIdx+1)*(blockSize), m_numElems); + for(int i=myIdx*blockSize+llIdx; i>1; nActive>0; nActive>>=1, offset<<=1)\n" +" {\n" +" GROUP_LDS_BARRIER;\n" +" for(int iIdx=lIdx; iIdx>= 1;\n" +" for(int nActive=1; nActive>=1 )\n" +" {\n" +" GROUP_LDS_BARRIER;\n" +" for( int iIdx = lIdx; iIdx dst : register( u0 );\n" +"RWStructuredBuffer src : register( u1 );\n" +"RWStructuredBuffer sumBuffer : register( u2 );\n" +"\n" +"\n" +"groupshared u32 ldsData[2048];\n" +"\n" +"u32 ScanExclusive(u32 n, int lIdx, int lSize)\n" +"{\n" +" u32 blocksum;\n" +" int offset = 1;\n" +" for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)\n" +" {\n" +" GROUP_LDS_BARRIER;\n" +" for(int iIdx=lIdx; iIdx>= 1;\n" +" for(int nActive=1; nActive>=1 )\n" +" {\n" +" GROUP_LDS_BARRIER;\n" +" for( int iIdx = lIdx; iIdx blockSum2 : register( u1 );\n" +"\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void AddOffsetKernel(uint3 globalIdx : SV_DispatchThreadID, uint3 localIdx : SV_GroupThreadID, uint3 groupIdx : SV_GroupID)\n" +"{\n" +" const u32 blockSize = WG_SIZE*2;\n" +"\n" +" int myIdx = GET_GROUP_IDX+1;\n" +" int llIdx = GET_LOCAL_IDX;\n" +"\n" +" u32 iBlockSum = blockSum2[myIdx];\n" +"\n" +" int endValue = min((myIdx+1)*(blockSize), m_numElems);\n" +" for(int i=myIdx*blockSize+llIdx; i +#include +#include +#include + +namespace adl +{ + +class BoundSearchBase +{ + public: + enum Option + { + BOUND_LOWER, + BOUND_UPPER, + COUNT, + }; +}; + +template +class BoundSearch : public BoundSearchBase +{ + public: + typedef Launcher::BufferInfo BufferInfo; + + struct Data + { + const Device* m_device; + Kernel* m_lowerSortDataKernel; + Kernel* m_upperSortDataKernel; + Kernel* m_subtractKernel; + Buffer* m_constBuffer; + Buffer* m_lower; + Buffer* m_upper; + typename Fill::Data* m_fillData; + }; + + static + Data* allocate(const Device* deviceData, int maxSize = 0); + + static + void deallocate(Data* data); + + // src has to be src[i].m_key <= src[i+1].m_key + static + void execute(Data* data, Buffer& src, u32 nSrc, Buffer& dst, u32 nDst, Option option = BOUND_LOWER ); + +// static +// void execute(Data* data, Buffer& src, Buffer& dst, int n, Option option = ); +}; + +#include +#include + +}; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Search/BoundSearch.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Search/BoundSearch.inl new file mode 100644 index 0000000..33138b4 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Search/BoundSearch.inl @@ -0,0 +1,128 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + +#define PATH "..\\..\\opencl\\primitives\\AdlPrimitives\\Search\\BoundSearchKernels" +#define KERNEL0 "SearchSortDataLowerKernel" +#define KERNEL1 "SearchSortDataUpperKernel" +#define KERNEL2 "SubtractKernel" + +#include +#include + +template +typename BoundSearch::Data* BoundSearch::allocate(const Device* device, int maxSize) +{ + ADLASSERT( TYPE == device->m_type ); + + const char* src[] = +#if defined(ADL_LOAD_KERNEL_FROM_STRING) + {boundSearchKernelsCL, boundSearchKernelsDX11}; +#else + {0,0}; +#endif + + Data* data = new Data; + + data->m_device = device; + data->m_lowerSortDataKernel = device->getKernel( PATH, KERNEL0, 0, src[TYPE] ); + data->m_upperSortDataKernel = device->getKernel( PATH, KERNEL1, 0, src[TYPE] ); + data->m_constBuffer = new Buffer( device, 1, BufferBase::BUFFER_CONST ); + if( maxSize ) + { + data->m_subtractKernel = device->getKernel( PATH, KERNEL2, 0, src[TYPE] ); + } + data->m_lower = (maxSize == 0)? 0: new Buffer( device, maxSize ); + data->m_upper = (maxSize == 0)? 0: new Buffer( device, maxSize ); + data->m_fillData = (maxSize == 0)? 0: Fill::allocate( device ); + + return data; +} + +template +void BoundSearch::deallocate(Data* data) +{ + delete data->m_constBuffer; + if( data->m_lower ) delete data->m_lower; + if( data->m_upper ) delete data->m_upper; + if( data->m_fillData ) Fill::deallocate( data->m_fillData ); + delete data; +} + +template +void BoundSearch::execute(Data* data, Buffer& src, u32 nSrc, Buffer& dst, u32 nDst, Option option ) +{ + int4 constBuffer; + constBuffer.x = nSrc; + constBuffer.y = nDst; + + Buffer* srcNative = BufferUtils::map( data->m_device, &src ); + Buffer* dstNative = BufferUtils::map( data->m_device, &dst ); + + if( option == BOUND_LOWER ) + { + BufferInfo bInfo[] = { BufferInfo( srcNative, true ), BufferInfo( dstNative ) }; + + Launcher launcher( data->m_device, data->m_lowerSortDataKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer, constBuffer ); + launcher.launch1D( nSrc, 64 ); + } + else if( option == BOUND_UPPER ) + { + BufferInfo bInfo[] = { BufferInfo( srcNative, true ), BufferInfo( dstNative ) }; + + Launcher launcher( data->m_device, data->m_upperSortDataKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer, constBuffer ); + launcher.launch1D( nSrc+1, 64 ); + } + else if( option == COUNT ) + { + ADLASSERT( data->m_lower ); + ADLASSERT( data->m_upper ); + ADLASSERT( data->m_lower->getSize() <= (int)nDst ); + ADLASSERT( data->m_upper->getSize() <= (int)nDst ); + + int zero = 0; + Fill::execute( data->m_fillData, (Buffer&)*data->m_lower, zero, nDst ); + Fill::execute( data->m_fillData, (Buffer&)*data->m_upper, zero, nDst ); + + execute( data, src, nSrc, *data->m_lower, nDst, BOUND_LOWER ); + execute( data, src, nSrc, *data->m_upper, nDst, BOUND_UPPER ); + + { + BufferInfo bInfo[] = { BufferInfo( data->m_upper, true ), BufferInfo( data->m_lower, true ), BufferInfo( dstNative ) }; + + Launcher launcher( data->m_device, data->m_subtractKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer, constBuffer ); + launcher.launch1D( nDst, 64 ); + } + } + else + { + ADLASSERT( 0 ); + } + + BufferUtils::unmap( srcNative, &src ); + BufferUtils::unmap( dstNative, &dst ); +} + + +#undef PATH +#undef KERNEL0 +#undef KERNEL1 +#undef KERNEL2 + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Search/BoundSearchHost.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Search/BoundSearchHost.inl new file mode 100644 index 0000000..b53b3ba --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Search/BoundSearchHost.inl @@ -0,0 +1,111 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +template<> +class BoundSearch : public BoundSearchBase +{ + public: + typedef Launcher::BufferInfo BufferInfo; + + struct Data + { + const Device* m_device; + }; + + static + Data* allocate(const Device* deviceData, int maxSize = 0) + { + ADLASSERT( deviceData->m_type == TYPE_HOST ); + Data* data = new Data; + data->m_device = deviceData; + return data; + } + + static + void deallocate(Data* data) + { + delete data; + } + + static + void execute(Data* data, Buffer& rawSrc, u32 nSrc, Buffer& rawDst, u32 nDst, Option option = BOUND_LOWER) + { + ADLASSERT( rawSrc.getType() == TYPE_HOST ); + ADLASSERT( rawDst.getType() == TYPE_HOST ); + + HostBuffer& src = *(HostBuffer*)&rawSrc; + HostBuffer& dst = *(HostBuffer*)&rawDst; + + for(int i=0; i lower( data->m_device, nDst ); + HostBuffer upper( data->m_device, nDst ); + + for(u32 i=0; i& src, Buffer& dst, int n, Option option = ); +}; + + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Search/BoundSearchKernels.cl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Search/BoundSearchKernels.cl new file mode 100644 index 0000000..105a17a --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Search/BoundSearchKernels.cl @@ -0,0 +1,112 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +typedef unsigned int u32; +#define GET_GROUP_IDX get_group_id(0) +#define GET_LOCAL_IDX get_local_id(0) +#define GET_GLOBAL_IDX get_global_id(0) +#define GET_GROUP_SIZE get_local_size(0) +#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE) + +typedef struct +{ + u32 m_key; + u32 m_value; +}SortData; + + + +typedef struct +{ + u32 m_nSrc; + u32 m_nDst; + u32 m_padding[2]; +} ConstBuffer; + + + +__attribute__((reqd_work_group_size(64,1,1))) +__kernel +void SearchSortDataLowerKernel(__global SortData* src, __global u32 *dst, + ConstBuffer cb) +{ + int gIdx = GET_GLOBAL_IDX; + u32 nSrc = cb.m_nSrc; + u32 nDst = cb.m_nDst; + + if( gIdx < nSrc ) + { + SortData first; first.m_key = (u32)(-1); first.m_value = (u32)(-1); + SortData end; end.m_key = nDst; end.m_value = nDst; + + SortData iData = (gIdx==0)? first: src[gIdx-1]; + SortData jData = (gIdx==nSrc)? end: src[gIdx]; + + if( iData.m_key != jData.m_key ) + { +// for(u32 k=iData.m_key+1; k<=min(jData.m_key, nDst-1); k++) + u32 k = jData.m_key; + { + dst[k] = gIdx; + } + } + } +} + + +__attribute__((reqd_work_group_size(64,1,1))) +__kernel +void SearchSortDataUpperKernel(__global SortData* src, __global u32 *dst, + ConstBuffer cb) +{ + int gIdx = GET_GLOBAL_IDX; + u32 nSrc = cb.m_nSrc; + u32 nDst = cb.m_nDst; + + if( gIdx < nSrc+1 ) + { + SortData first; first.m_key = 0; first.m_value = 0; + SortData end; end.m_key = nDst; end.m_value = nDst; + + SortData iData = (gIdx==0)? first: src[gIdx-1]; + SortData jData = (gIdx==nSrc)? end: src[gIdx]; + + if( iData.m_key != jData.m_key ) + { +// for(u32 k=iData.m_key; k src : register( t0 ); +RWStructuredBuffer dst : register( u0 ); + + +[numthreads(64, 1, 1)] +void SearchSortDataLowerKernel( DEFAULT_ARGS ) +{ + int gIdx = GET_GLOBAL_IDX; + u32 nSrc = m_nSrc; + u32 nDst = m_nDst; + + if( gIdx < nSrc ) + { + SortData iData; + SortData jData; + if( gIdx==0 ) iData.m_key = iData.m_value = (u32)-1; + else iData = src[gIdx-1]; + + if( gIdx==nSrc ) jData.m_key = jData.m_value = nDst; + else jData = src[gIdx]; + + if( iData.m_key != jData.m_key ) + { +// for(u32 k=iData.m_key+1; k<=min(jData.m_key, nDst-1); k++) + u32 k = jData.m_key; + { + dst[k] = gIdx; + } + } + } +} + +[numthreads(64, 1, 1)] +void SearchSortDataUpperKernel( DEFAULT_ARGS ) +{ + int gIdx = GET_GLOBAL_IDX; + u32 nSrc = m_nSrc; + u32 nDst = m_nDst; + + if( gIdx < nSrc+1 ) + { + SortData iData; + SortData jData; + if( gIdx==0 ) iData.m_key = iData.m_value = 0; + else iData = src[gIdx-1]; + + if( gIdx==nSrc ) jData.m_key = jData.m_value = nDst; + else jData = src[gIdx]; + + if( iData.m_key != jData.m_key ) + { +// for(u32 k=iData.m_key; k src : register( t0 );\n" +"RWStructuredBuffer dst : register( u0 );\n" +"\n" +"\n" +"[numthreads(64, 1, 1)]\n" +"void SearchSortDataLowerKernel( DEFAULT_ARGS )\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +" u32 nSrc = m_nSrc;\n" +" u32 nDst = m_nDst;\n" +"\n" +" if( gIdx < nSrc )\n" +" {\n" +" SortData iData;\n" +" SortData jData;\n" +" if( gIdx==0 ) iData.m_key = iData.m_value = (u32)-1;\n" +" else iData = src[gIdx-1];\n" +"\n" +" if( gIdx==nSrc ) jData.m_key = jData.m_value = nDst;\n" +" else jData = src[gIdx];\n" +"\n" +" if( iData.m_key != jData.m_key )\n" +" {\n" +"// for(u32 k=iData.m_key+1; k<=min(jData.m_key, nDst-1); k++)\n" +" u32 k = jData.m_key;\n" +" {\n" +" dst[k] = gIdx;\n" +" }\n" +" }\n" +" }\n" +"}\n" +"\n" +"[numthreads(64, 1, 1)]\n" +"void SearchSortDataUpperKernel( DEFAULT_ARGS )\n" +"{\n" +" int gIdx = GET_GLOBAL_IDX;\n" +" u32 nSrc = m_nSrc;\n" +" u32 nDst = m_nDst;\n" +"\n" +" if( gIdx < nSrc+1 )\n" +" {\n" +" SortData iData;\n" +" SortData jData;\n" +" if( gIdx==0 ) iData.m_key = iData.m_value = 0;\n" +" else iData = src[gIdx-1];\n" +"\n" +" if( gIdx==nSrc ) jData.m_key = jData.m_value = nDst;\n" +" else jData = src[gIdx];\n" +"\n" +" if( iData.m_key != jData.m_key )\n" +" {\n" +"// for(u32 k=iData.m_key; k +#include +#include +#include + +namespace adl +{ + +class RadixSortBase +{ + public: + enum Option + { + SORT_SIMPLE, + SORT_STANDARD, + SORT_ADVANCED + }; +}; + +template +class RadixSort : public RadixSortBase +{ + public: + struct Data + { + Option m_option; + const Device* m_deviceData; + typename PrefixScan::Data* m_scanData; + int m_maxSize; + }; + + + static + Data* allocate(const Device* deviceData, int maxSize, Option option = SORT_STANDARD); + + static + void deallocate(Data* data); + + static + void execute(Data* data, Buffer& inout, int n, int sortBits = 32); +}; + + +#include +#include + +}; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort.inl new file mode 100644 index 0000000..f7da098 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort.inl @@ -0,0 +1,58 @@ +/* + 2011 Takahiro Harada +*/ + +#include +#include +#include + + +#define DISPATCH_IMPL(x) \ + switch( data->m_option ) \ + { \ + case SORT_SIMPLE: RadixSortSimple::x; break; \ + case SORT_STANDARD: RadixSortStandard::x; break; \ + case SORT_ADVANCED: RadixSortAdvanced::x; break; \ + default:ADLASSERT(0);break; \ + } + +template +typename RadixSort::Data* RadixSort::allocate(const Device* deviceData, int maxSize, Option option) +{ + ADLASSERT( TYPE == deviceData->m_type ); + + void* dataOut; + switch( option ) + { + case SORT_SIMPLE: + dataOut = RadixSortSimple::allocate( deviceData, maxSize, option ); + break; + case SORT_STANDARD: + dataOut = RadixSortStandard::allocate( deviceData, maxSize, option ); + break; + case SORT_ADVANCED: + dataOut = RadixSortAdvanced::allocate( deviceData, maxSize, option ); + break; + default: + ADLASSERT(0); + break; + } + return (typename RadixSort::Data*)dataOut; +} + +template +void RadixSort::deallocate(Data* data) +{ + DISPATCH_IMPL( deallocate( data ) ); +} + +template +void RadixSort::execute(Data* data, Buffer& inout, int n, int sortBits) +{ + DISPATCH_IMPL( execute( data, inout, n, sortBits ) ); +} + + +#undef DISPATCH_IMPL + + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32.h new file mode 100644 index 0000000..c5433e7 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32.h @@ -0,0 +1,98 @@ +/* + 2011 Takahiro Harada +*/ + +#pragma once + +#include +#include +#include +#include + +namespace adl +{ + +class RadixSort32Base +{ + public: +// enum Option +// { +// SORT_SIMPLE, +// SORT_STANDARD, +// SORT_ADVANCED +// }; +}; + +template +class RadixSort32 : public RadixSort32Base +{ + public: + typedef Launcher::BufferInfo BufferInfo; + + enum + { + DATA_ALIGNMENT = 256, + WG_SIZE = 64, + ELEMENTS_PER_WORK_ITEM = (256/WG_SIZE), + BITS_PER_PASS = 4, + + // if you change this, change nPerWI in kernel as well + NUM_WGS = 20*6, // cypress +// NUM_WGS = 24*6, // cayman +// NUM_WGS = 32*4, // nv + }; + + struct ConstData + { + int m_n; + int m_nWGs; + int m_startBit; + int m_nBlocksPerWG; + }; + + struct Data + { + const Device* m_device; + int m_maxSize; + + Kernel* m_streamCountKernel; + Kernel* m_streamCountSortDataKernel; + Kernel* m_prefixScanKernel; + Kernel* m_sortAndScatterKernel; + Kernel* m_sortAndScatterKeyValueKernel; + Kernel* m_sortAndScatterSortDataKernel; + + Buffer* m_workBuffer0; + Buffer* m_workBuffer1; + Buffer* m_workBuffer2; + Buffer* m_workBuffer3; + + Buffer* m_constBuffer[32/BITS_PER_PASS]; + + typename Copy::Data* m_copyData; + }; + + static + Data* allocate(const Device* device, int maxSize); + + static + void deallocate(Data* data); + + static + void execute(Data* data, Buffer& inout, int n, int sortBits = 32); + + static + void execute(Data* data, Buffer& in, Buffer& out, int n, int sortBits = 32); + + static + void execute(Data* data, Buffer& keysIn, Buffer& keysOut, Buffer& valuesIn, Buffer& valuesOut, int n, int sortBits = 32); + + static + void execute(Data* data, Buffer& keyValuesInOut, int n, int sortBits = 32 ); +}; + + +#include +#include + +}; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32.inl new file mode 100644 index 0000000..4689432 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32.inl @@ -0,0 +1,346 @@ +/* + 2011 Takahiro Harada +*/ + +#define PATH "..\\..\\opencl\\primitives\\AdlPrimitives\\Sort\\RadixSort32Kernels" +#define RADIXSORT32_KERNEL0 "StreamCountKernel" +#define RADIXSORT32_KERNEL1 "PrefixScanKernel" +#define RADIXSORT32_KERNEL2 "SortAndScatterKernel" +#define RADIXSORT32_KERNEL3 "SortAndScatterKeyValueKernel" +#define RADIXSORT32_KERNEL4 "SortAndScatterSortDataKernel" +#define RADIXSORT32_KERNEL5 "StreamCountSortDataKernel" + +#include "RadixSort32KernelsCL.h" +#include "RadixSort32KernelsDX11.h" + +// todo. Shader compiler (2010JuneSDK) doesn't allow me to place Barriers in SortAndScatterKernel... +// So it only works on a GPU with 64 wide SIMD. + +template +typename RadixSort32::Data* RadixSort32::allocate( const Device* device, int maxSize ) +{ + ADLASSERT( TYPE == device->m_type ); + + const char* src[] = +#if defined(ADL_LOAD_KERNEL_FROM_STRING) + {radixSort32KernelsCL, radixSort32KernelsDX11}; +#else + {0,0}; +#endif + + Data* data = new Data; + data->m_device = device; + data->m_maxSize = maxSize; + data->m_streamCountKernel = device->getKernel( PATH, RADIXSORT32_KERNEL0, 0, src[TYPE] ); + data->m_streamCountSortDataKernel = device->getKernel( PATH, RADIXSORT32_KERNEL5, 0, src[TYPE] ); + + + + data->m_prefixScanKernel = device->getKernel( PATH, RADIXSORT32_KERNEL1, 0, src[TYPE] ); + data->m_sortAndScatterKernel = device->getKernel( PATH, RADIXSORT32_KERNEL2, 0, src[TYPE] ); + data->m_sortAndScatterKeyValueKernel = device->getKernel( PATH, RADIXSORT32_KERNEL3, 0, src[TYPE] ); + data->m_sortAndScatterSortDataKernel = device->getKernel( PATH, RADIXSORT32_KERNEL4, 0, src[TYPE] ); + + int wtf = NUM_WGS*(1<m_workBuffer0 = new Buffer( device, maxSize ); + data->m_workBuffer1 = new Buffer( device , wtf ); + data->m_workBuffer2 = new Buffer( device, maxSize ); + data->m_workBuffer3 = new Buffer(device,maxSize); + + + for(int i=0; i<32/BITS_PER_PASS; i++) + data->m_constBuffer[i] = new Buffer( device, 1, BufferBase::BUFFER_CONST ); + + data->m_copyData = Copy::allocate( device ); + + return data; +} + +template +void RadixSort32::deallocate( Data* data ) +{ + delete data->m_workBuffer0; + delete data->m_workBuffer1; + delete data->m_workBuffer2; + delete data->m_workBuffer3; + + for(int i=0; i<32/BITS_PER_PASS; i++) + delete data->m_constBuffer[i]; + + Copy::deallocate( data->m_copyData ); + + delete data; +} + +template +void RadixSort32::execute(Data* data, Buffer& inout, int n, int sortBits /* = 32 */ ) +{ + ADLASSERT( n%DATA_ALIGNMENT == 0 ); + ADLASSERT( n <= data->m_maxSize ); +// ADLASSERT( ELEMENTS_PER_WORK_ITEM == 4 ); + ADLASSERT( BITS_PER_PASS == 4 ); + ADLASSERT( WG_SIZE == 64 ); + ADLASSERT( (sortBits&0x3) == 0 ); + + Buffer* src = &inout; + Buffer* dst = data->m_workBuffer0; + Buffer* histogramBuffer = data->m_workBuffer1; + + int nWGs = NUM_WGS; + ConstData cdata; + { + int nBlocks = (n+ELEMENTS_PER_WORK_ITEM*WG_SIZE-1)/(ELEMENTS_PER_WORK_ITEM*WG_SIZE); + + cdata.m_n = n; + cdata.m_nWGs = NUM_WGS; + cdata.m_startBit = 0; + cdata.m_nBlocksPerWG = (nBlocks + cdata.m_nWGs - 1)/cdata.m_nWGs; + + if( nBlocks < NUM_WGS ) + { + cdata.m_nBlocksPerWG = 1; + nWGs = nBlocks; + } + } + + for(int ib=0; ibm_device, data->m_streamCountKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[ib/4], cdata ); + launcher.launch1D( NUM_WGS*WG_SIZE, WG_SIZE ); + } + {// prefix scan group histogram + BufferInfo bInfo[] = { BufferInfo( histogramBuffer ) }; + Launcher launcher( data->m_device, data->m_prefixScanKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[ib/4], cdata ); + launcher.launch1D( 128, 128 ); + } + {// local sort and distribute + BufferInfo bInfo[] = { BufferInfo( src, true ), BufferInfo( histogramBuffer, true ), BufferInfo( dst ) }; + Launcher launcher( data->m_device, data->m_sortAndScatterKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[ib/4], cdata ); + launcher.launch1D( nWGs*WG_SIZE, WG_SIZE ); + } + swap2( src, dst ); + } + + if( src != &inout ) + { + Copy::execute( data->m_copyData, (Buffer&)inout, (Buffer&)*src, n ); + } +} + +template +void RadixSort32::execute(Data* data, Buffer& in, Buffer& out, int n, int sortBits /* = 32 */ ) +{ + ADLASSERT( n%DATA_ALIGNMENT == 0 ); + ADLASSERT( n <= data->m_maxSize ); +// ADLASSERT( ELEMENTS_PER_WORK_ITEM == 4 ); + ADLASSERT( BITS_PER_PASS == 4 ); + ADLASSERT( WG_SIZE == 64 ); + ADLASSERT( (sortBits&0x3) == 0 ); + + Buffer* src = ∈ + Buffer* dst = data->m_workBuffer0; + Buffer* histogramBuffer = data->m_workBuffer1; + + int nWGs = NUM_WGS; + ConstData cdata; + { + int nBlocks = (n+ELEMENTS_PER_WORK_ITEM*WG_SIZE-1)/(ELEMENTS_PER_WORK_ITEM*WG_SIZE); + cdata.m_n = n; + cdata.m_nWGs = NUM_WGS; + cdata.m_startBit = 0; + cdata.m_nBlocksPerWG = (nBlocks + cdata.m_nWGs - 1)/cdata.m_nWGs; + if( nBlocks < NUM_WGS ) + { + cdata.m_nBlocksPerWG = 1; + nWGs = nBlocks; + } + } + + if( sortBits == 4 ) dst = &out; + + for(int ib=0; ibm_device, data->m_streamCountKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[ib/4], cdata ); + launcher.launch1D( NUM_WGS*WG_SIZE, WG_SIZE ); + } + {// prefix scan group histogram + BufferInfo bInfo[] = { BufferInfo( histogramBuffer ) }; + Launcher launcher( data->m_device, data->m_prefixScanKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[ib/4], cdata ); + launcher.launch1D( 128, 128 ); + } + {// local sort and distribute + BufferInfo bInfo[] = { BufferInfo( src, true ), BufferInfo( histogramBuffer, true ), BufferInfo( dst ) }; + Launcher launcher( data->m_device, data->m_sortAndScatterKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[ib/4], cdata ); + launcher.launch1D( nWGs*WG_SIZE, WG_SIZE ); + } + swap2( src, dst ); + } +} + +template +void RadixSort32::execute(Data* data, Buffer& keysIn, Buffer& keysOut, Buffer& valuesIn, Buffer& valuesOut, int n, int sortBits /* = 32 */) +{ + ADLASSERT( n%DATA_ALIGNMENT == 0 ); + ADLASSERT( n <= data->m_maxSize ); +// ADLASSERT( ELEMENTS_PER_WORK_ITEM == 4 ); + ADLASSERT( BITS_PER_PASS == 4 ); + ADLASSERT( WG_SIZE == 64 ); + ADLASSERT( (sortBits&0x3) == 0 ); + + Buffer* src = &keysIn; + Buffer* srcVal = &valuesIn; + Buffer* dst = data->m_workBuffer0; + Buffer* dstVal = data->m_workBuffer2; + Buffer* histogramBuffer = data->m_workBuffer1; + + int nWGs = NUM_WGS; + ConstData cdata; + { + int nBlocks = (n+ELEMENTS_PER_WORK_ITEM*WG_SIZE-1)/(ELEMENTS_PER_WORK_ITEM*WG_SIZE); + cdata.m_n = n; + cdata.m_nWGs = NUM_WGS; + cdata.m_startBit = 0; + cdata.m_nBlocksPerWG = (nBlocks + cdata.m_nWGs - 1)/cdata.m_nWGs; + if( nBlocks < NUM_WGS ) + { + cdata.m_nBlocksPerWG = 1; + nWGs = nBlocks; + } + } + + if( sortBits == 4 ) + { + dst = &keysOut; + dstVal = &valuesOut; + } + + for(int ib=0; ibm_device, data->m_streamCountKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[ib/4], cdata ); + launcher.launch1D( NUM_WGS*WG_SIZE, WG_SIZE ); + } + {// prefix scan group histogram + BufferInfo bInfo[] = { BufferInfo( histogramBuffer ) }; + Launcher launcher( data->m_device, data->m_prefixScanKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[ib/4], cdata ); + launcher.launch1D( 128, 128 ); + } + {// local sort and distribute + BufferInfo bInfo[] = { BufferInfo( src, true ), BufferInfo( srcVal, true ), BufferInfo( histogramBuffer, true ), BufferInfo( dst ), BufferInfo( dstVal ) }; + Launcher launcher( data->m_device, data->m_sortAndScatterKeyValueKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[ib/4], cdata ); + launcher.launch1D( nWGs*WG_SIZE, WG_SIZE ); + } + swap2( src, dst ); + swap2( srcVal, dstVal ); + } +} + +template +void RadixSort32::execute(Data* data, Buffer& keyValuesInOut, int n, int sortBits /* = 32 */) +{ + ADLASSERT( n%DATA_ALIGNMENT == 0 ); + ADLASSERT( n <= data->m_maxSize ); +// ADLASSERT( ELEMENTS_PER_WORK_ITEM == 4 ); + ADLASSERT( BITS_PER_PASS == 4 ); + ADLASSERT( WG_SIZE == 64 ); + ADLASSERT( (sortBits&0x3) == 0 ); + + Buffer* src = &keyValuesInOut; + Buffer* dst = data->m_workBuffer3; + + Buffer* histogramBuffer = data->m_workBuffer1; + + int nWGs = NUM_WGS; + ConstData cdata; + { + int nBlocks = (n+ELEMENTS_PER_WORK_ITEM*WG_SIZE-1)/(ELEMENTS_PER_WORK_ITEM*WG_SIZE); + cdata.m_n = n; + cdata.m_nWGs = NUM_WGS; + cdata.m_startBit = 0; + cdata.m_nBlocksPerWG = (nBlocks + cdata.m_nWGs - 1)/cdata.m_nWGs; + if( nBlocks < NUM_WGS ) + { + cdata.m_nBlocksPerWG = 1; + nWGs = nBlocks; + } + } + + int count=0; + for(int ib=0; ibm_device, data->m_streamCountSortDataKernel); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[ib/4], cdata ); + launcher.launch1D( NUM_WGS*WG_SIZE, WG_SIZE ); + } + {// prefix scan group histogram + BufferInfo bInfo[] = { BufferInfo( histogramBuffer ) }; + Launcher launcher( data->m_device, data->m_prefixScanKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[ib/4], cdata ); + launcher.launch1D( 128, 128 ); + } + {// local sort and distribute + BufferInfo bInfo[] = { BufferInfo( src, true ), BufferInfo( histogramBuffer, true ), BufferInfo( dst )}; + Launcher launcher( data->m_device, data->m_sortAndScatterSortDataKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[ib/4], cdata ); + launcher.launch1D( nWGs*WG_SIZE, WG_SIZE ); + } + swap2( src, dst ); + count++; + } + + if (count&1) + { + ADLASSERT(0);//need to copy from workbuffer to keyValuesInOut + + } +} +#undef PATH +#undef RADIXSORT32_KERNEL0 +#undef RADIXSORT32_KERNEL1 +#undef RADIXSORT32_KERNEL2 +#undef RADIXSORT32_KERNEL3 + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32Host.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32Host.inl new file mode 100644 index 0000000..7e174f4 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32Host.inl @@ -0,0 +1,163 @@ +/* + 2011 Takahiro Harada +*/ + +template<> +class RadixSort32 : public RadixSort32Base +{ + public: + typedef Launcher::BufferInfo BufferInfo; + + enum + { + BITS_PER_PASS = 8, + NUM_TABLES = (1<* m_workBuffer; + }; + + static + Data* allocate(const Device* device, int maxSize) + { + ADLASSERT( device->m_type == TYPE_HOST ); + + Data* data = new Data; + data->m_workBuffer = new HostBuffer( device, maxSize ); + return data; + } + + static + void deallocate(Data* data) + { + delete data->m_workBuffer; + delete data; + } + + static + void execute(Data* data, Buffer& inout, int n, int sortBits = 32) + { + ADLASSERT( inout.getType() == TYPE_HOST ); + + int tables[NUM_TABLES]; + int counter[NUM_TABLES]; + + u32* src = inout.m_ptr; + u32* dst = data->m_workBuffer->m_ptr; + + for(int startBit=0; startBit> startBit) & (NUM_TABLES-1); + tables[tableIdx]++; + } + + // prefix scan + int sum = 0; + for(int i=0; i> startBit) & (NUM_TABLES-1); + + dst[tables[tableIdx] + counter[tableIdx]] = src[i]; + counter[tableIdx] ++; + } + + swap2( src, dst ); + } + + { + if( src != inout.m_ptr ) + { + memcpy( dst, src, sizeof(u32)*n ); + } + } + + } + + static + void execute(Data* data, Buffer& keyInout, const Buffer& valueInout, int n, int sortBits = 32) + { + ADLASSERT( keyInout.getType() == TYPE_HOST ); + + int tables[NUM_TABLES]; + int counter[NUM_TABLES]; + + u32* src = keyInout.m_ptr; + u32* dst = data->m_workBuffer->m_ptr; + + HostBuffer bufVal(valueInout.m_device, valueInout.m_size); + bufVal.write(valueInout.m_ptr, valueInout.m_size); + + u32* srcVal = valueInout.m_ptr; + u32* dstVal = bufVal.m_ptr; + + for(int startBit=0; startBit> startBit) & (NUM_TABLES-1); + tables[tableIdx]++; + } + + // prefix scan + int sum = 0; + for(int i=0; i> startBit) & (NUM_TABLES-1); + int newIdx = tables[tableIdx] + counter[tableIdx]; + dst[newIdx] = src[i]; + dstVal[newIdx] = srcVal[i]; + counter[tableIdx]++; + } + + swap2( src, dst ); + swap2( srcVal, dstVal ); + } + + { + if( src != keyInout.m_ptr ) + { + memcpy( dst, src, sizeof(u32)*n ); + } + + if( srcVal != valueInout.m_ptr ) + { + memcpy( dstVal, srcVal, sizeof(u32)*n ); + } + } + + } +}; + + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32Kernels.cl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32Kernels.cl new file mode 100644 index 0000000..44dd9a9 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSort32Kernels.cl @@ -0,0 +1,1104 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +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. +*/ +//Author Takahiro Harada + + +//#pragma OPENCL EXTENSION cl_amd_printf : enable +#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable +#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable + +typedef unsigned int u32; +#define GET_GROUP_IDX get_group_id(0) +#define GET_LOCAL_IDX get_local_id(0) +#define GET_GLOBAL_IDX get_global_id(0) +#define GET_GROUP_SIZE get_local_size(0) +#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE) +#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE) +#define AtomInc(x) atom_inc(&(x)) +#define AtomInc1(x, out) out = atom_inc(&(x)) +#define AtomAdd(x, value) atom_add(&(x), value) + +#define SELECT_UINT4( b, a, condition ) select( b,a,condition ) + + +#define make_uint4 (uint4) +#define make_uint2 (uint2) +#define make_int2 (int2) + +#define WG_SIZE 64 +#define ELEMENTS_PER_WORK_ITEM (256/WG_SIZE) +#define BITS_PER_PASS 4 +#define NUM_BUCKET (1< 64 ) + { + sorterSharedMemory[idx] += sorterSharedMemory[idx-64]; + GROUP_MEM_FENCE; + } + + sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2]; + GROUP_MEM_FENCE; + } +#else + if( lIdx < 64 ) + { + sorterSharedMemory[idx] += sorterSharedMemory[idx-1]; + GROUP_MEM_FENCE; + sorterSharedMemory[idx] += sorterSharedMemory[idx-2]; + GROUP_MEM_FENCE; + sorterSharedMemory[idx] += sorterSharedMemory[idx-4]; + GROUP_MEM_FENCE; + sorterSharedMemory[idx] += sorterSharedMemory[idx-8]; + GROUP_MEM_FENCE; + sorterSharedMemory[idx] += sorterSharedMemory[idx-16]; + GROUP_MEM_FENCE; + sorterSharedMemory[idx] += sorterSharedMemory[idx-32]; + GROUP_MEM_FENCE; + if( wgSize > 64 ) + { + sorterSharedMemory[idx] += sorterSharedMemory[idx-64]; + GROUP_MEM_FENCE; + } + + sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2]; + GROUP_MEM_FENCE; + } +#endif + } + + GROUP_LDS_BARRIER; + + *totalSum = sorterSharedMemory[wgSize*2-1]; + u32 addValue = sorterSharedMemory[lIdx+wgSize-1]; + return addValue; +} + +//__attribute__((reqd_work_group_size(128,1,1))) +uint4 localPrefixSum128V( uint4 pData, uint lIdx, uint* totalSum, __local u32 sorterSharedMemory[] ) +{ + u32 s4 = prefixScanVectorEx( &pData ); + u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 128 ); + return pData + make_uint4( rank, rank, rank, rank ); +} + + +//__attribute__((reqd_work_group_size(64,1,1))) +uint4 localPrefixSum64V( uint4 pData, uint lIdx, uint* totalSum, __local u32 sorterSharedMemory[] ) +{ + u32 s4 = prefixScanVectorEx( &pData ); + u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 64 ); + return pData + make_uint4( rank, rank, rank, rank ); +} + +u32 unpack4Key( u32 key, int keyIdx ){ return (key>>(keyIdx*8)) & 0xff;} + +u32 bit8Scan(u32 v) +{ + return (v<<8) + (v<<16) + (v<<24); +} + +//=== + + + + +#define MY_HISTOGRAM(idx) localHistogramMat[(idx)*WG_SIZE+lIdx] + + +__kernel +__attribute__((reqd_work_group_size(WG_SIZE,1,1))) +void StreamCountKernel( __global u32* gSrc, __global u32* histogramOut, ConstBuffer cb ) +{ + __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE]; + + u32 gIdx = GET_GLOBAL_IDX; + u32 lIdx = GET_LOCAL_IDX; + u32 wgIdx = GET_GROUP_IDX; + u32 wgSize = GET_GROUP_SIZE; + const int startBit = cb.m_startBit; + const int n = cb.m_n; + const int nWGs = cb.m_nWGs; + const int nBlocksPerWG = cb.m_nBlocksPerWG; + + for(int i=0; i>startBit) & 0xf; +#if defined(NV_GPU) + MY_HISTOGRAM( localKey )++; +#else + AtomInc( MY_HISTOGRAM( localKey ) ); +#endif + } + } + } + + GROUP_LDS_BARRIER; + + if( lIdx < NUM_BUCKET ) + { + u32 sum = 0; + for(int i=0; i>startBit) & 0xf; +#if defined(NV_GPU) + MY_HISTOGRAM( localKey )++; +#else + AtomInc( MY_HISTOGRAM( localKey ) ); +#endif + } + } + } + + GROUP_LDS_BARRIER; + + if( lIdx < NUM_BUCKET ) + { + u32 sum = 0; + for(int i=0; i>startBit) & mask, (sortData[1]>>startBit) & mask, (sortData[2]>>startBit) & mask, (sortData[3]>>startBit) & mask ); + uint4 prefixSum = SELECT_UINT4( make_uint4(1,1,1,1), make_uint4(0,0,0,0), cmpResult != make_uint4(0,0,0,0) ); + u32 total; + prefixSum = localPrefixSum64V( prefixSum, lIdx, &total, ldsSortData ); + { + uint4 localAddr = make_uint4(lIdx*4+0,lIdx*4+1,lIdx*4+2,lIdx*4+3); + uint4 dstAddr = localAddr - prefixSum + make_uint4( total, total, total, total ); + dstAddr = SELECT_UINT4( prefixSum, dstAddr, cmpResult != make_uint4(0, 0, 0, 0) ); + + GROUP_LDS_BARRIER; + + ldsSortData[dstAddr.x] = sortData[0]; + ldsSortData[dstAddr.y] = sortData[1]; + ldsSortData[dstAddr.z] = sortData[2]; + ldsSortData[dstAddr.w] = sortData[3]; + + GROUP_LDS_BARRIER; + + sortData[0] = ldsSortData[localAddr.x]; + sortData[1] = ldsSortData[localAddr.y]; + sortData[2] = ldsSortData[localAddr.z]; + sortData[3] = ldsSortData[localAddr.w]; + + GROUP_LDS_BARRIER; + } + } +} + +// 2 scan, 2 exchange +void sort4Bits1(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData) +{ + for(uint ibit=0; ibit>(startBit+ibit)) & 0x3, + (sortData[1]>>(startBit+ibit)) & 0x3, + (sortData[2]>>(startBit+ibit)) & 0x3, + (sortData[3]>>(startBit+ibit)) & 0x3); + + u32 key4; + u32 sKeyPacked[4] = { 0, 0, 0, 0 }; + { + sKeyPacked[0] |= 1<<(8*b.x); + sKeyPacked[1] |= 1<<(8*b.y); + sKeyPacked[2] |= 1<<(8*b.z); + sKeyPacked[3] |= 1<<(8*b.w); + + key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3]; + } + + u32 rankPacked; + u32 sumPacked; + { + rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE ); + } + + GROUP_LDS_BARRIER; + + u32 newOffset[4] = { 0,0,0,0 }; + { + u32 sumScanned = bit8Scan( sumPacked ); + + u32 scannedKeys[4]; + scannedKeys[0] = 1<<(8*b.x); + scannedKeys[1] = 1<<(8*b.y); + scannedKeys[2] = 1<<(8*b.z); + scannedKeys[3] = 1<<(8*b.w); + { // 4 scans at once + u32 sum4 = 0; + for(int ie=0; ie<4; ie++) + { + u32 tmp = scannedKeys[ie]; + scannedKeys[ie] = sum4; + sum4 += tmp; + } + } + + { + u32 sumPlusRank = sumScanned + rankPacked; + { u32 ie = b.x; + scannedKeys[0] += sumPlusRank; + newOffset[0] = unpack4Key( scannedKeys[0], ie ); + } + { u32 ie = b.y; + scannedKeys[1] += sumPlusRank; + newOffset[1] = unpack4Key( scannedKeys[1], ie ); + } + { u32 ie = b.z; + scannedKeys[2] += sumPlusRank; + newOffset[2] = unpack4Key( scannedKeys[2], ie ); + } + { u32 ie = b.w; + scannedKeys[3] += sumPlusRank; + newOffset[3] = unpack4Key( scannedKeys[3], ie ); + } + } + } + + + GROUP_LDS_BARRIER; + + { + ldsSortData[newOffset[0]] = sortData[0]; + ldsSortData[newOffset[1]] = sortData[1]; + ldsSortData[newOffset[2]] = sortData[2]; + ldsSortData[newOffset[3]] = sortData[3]; + + GROUP_LDS_BARRIER; + + u32 dstAddr = 4*lIdx; + sortData[0] = ldsSortData[dstAddr+0]; + sortData[1] = ldsSortData[dstAddr+1]; + sortData[2] = ldsSortData[dstAddr+2]; + sortData[3] = ldsSortData[dstAddr+3]; + + GROUP_LDS_BARRIER; + } + } +} + +#define SET_HISTOGRAM(setIdx, key) ldsSortData[(setIdx)*NUM_BUCKET+key] + +__kernel +__attribute__((reqd_work_group_size(WG_SIZE,1,1))) +void SortAndScatterKernel( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, ConstBuffer cb ) +{ + __local u32 ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16]; + __local u32 localHistogramToCarry[NUM_BUCKET]; + __local u32 localHistogram[NUM_BUCKET*2]; + + u32 gIdx = GET_GLOBAL_IDX; + u32 lIdx = GET_LOCAL_IDX; + u32 wgIdx = GET_GROUP_IDX; + u32 wgSize = GET_GROUP_SIZE; + + const int n = cb.m_n; + const int nWGs = cb.m_nWGs; + const int startBit = cb.m_startBit; + const int nBlocksPerWG = cb.m_nBlocksPerWG; + + if( lIdx < (NUM_BUCKET) ) + { + localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx]; + } + + GROUP_LDS_BARRIER; + + const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE; + + int nBlocks = n/blockSize - nBlocksPerWG*wgIdx; + + int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx; + + for(int iblock=0; iblock>startBit) & 0xf; + + { // create histogram + u32 setIdx = lIdx/16; + if( lIdx < NUM_BUCKET ) + { + localHistogram[lIdx] = 0; + } + ldsSortData[lIdx] = 0; + GROUP_LDS_BARRIER; + + for(int i=0; i>(startBit+ibit)) & 0x3, + (sortData[1]>>(startBit+ibit)) & 0x3, + (sortData[2]>>(startBit+ibit)) & 0x3, + (sortData[3]>>(startBit+ibit)) & 0x3); + + u32 key4; + u32 sKeyPacked[4] = { 0, 0, 0, 0 }; + { + sKeyPacked[0] |= 1<<(8*b.x); + sKeyPacked[1] |= 1<<(8*b.y); + sKeyPacked[2] |= 1<<(8*b.z); + sKeyPacked[3] |= 1<<(8*b.w); + + key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3]; + } + + u32 rankPacked; + u32 sumPacked; + { + rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE ); + } + + GROUP_LDS_BARRIER; + + u32 newOffset[4] = { 0,0,0,0 }; + { + u32 sumScanned = bit8Scan( sumPacked ); + + u32 scannedKeys[4]; + scannedKeys[0] = 1<<(8*b.x); + scannedKeys[1] = 1<<(8*b.y); + scannedKeys[2] = 1<<(8*b.z); + scannedKeys[3] = 1<<(8*b.w); + { // 4 scans at once + u32 sum4 = 0; + for(int ie=0; ie<4; ie++) + { + u32 tmp = scannedKeys[ie]; + scannedKeys[ie] = sum4; + sum4 += tmp; + } + } + + { + u32 sumPlusRank = sumScanned + rankPacked; + { u32 ie = b.x; + scannedKeys[0] += sumPlusRank; + newOffset[0] = unpack4Key( scannedKeys[0], ie ); + } + { u32 ie = b.y; + scannedKeys[1] += sumPlusRank; + newOffset[1] = unpack4Key( scannedKeys[1], ie ); + } + { u32 ie = b.z; + scannedKeys[2] += sumPlusRank; + newOffset[2] = unpack4Key( scannedKeys[2], ie ); + } + { u32 ie = b.w; + scannedKeys[3] += sumPlusRank; + newOffset[3] = unpack4Key( scannedKeys[3], ie ); + } + } + } + + + GROUP_LDS_BARRIER; + + { + ldsSortData[newOffset[0]] = sortData[0]; + ldsSortData[newOffset[1]] = sortData[1]; + ldsSortData[newOffset[2]] = sortData[2]; + ldsSortData[newOffset[3]] = sortData[3]; + + ldsSortVal[newOffset[0]] = sortVal[0]; + ldsSortVal[newOffset[1]] = sortVal[1]; + ldsSortVal[newOffset[2]] = sortVal[2]; + ldsSortVal[newOffset[3]] = sortVal[3]; + + GROUP_LDS_BARRIER; + + u32 dstAddr = 4*lIdx; + sortData[0] = ldsSortData[dstAddr+0]; + sortData[1] = ldsSortData[dstAddr+1]; + sortData[2] = ldsSortData[dstAddr+2]; + sortData[3] = ldsSortData[dstAddr+3]; + + sortVal[0] = ldsSortVal[dstAddr+0]; + sortVal[1] = ldsSortVal[dstAddr+1]; + sortVal[2] = ldsSortVal[dstAddr+2]; + sortVal[3] = ldsSortVal[dstAddr+3]; + + GROUP_LDS_BARRIER; + } + } +} + + + +__kernel +__attribute__((reqd_work_group_size(WG_SIZE,1,1))) +void SortAndScatterKeyValueKernel( __global const u32* restrict gSrc, __global const int* restrict gSrcVal, __global const u32* rHistogram, __global u32* restrict gDst, __global int* restrict gDstVal, ConstBuffer cb) +{ + __local u32 ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16]; + __local int ldsSortVal[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16]; + __local u32 localHistogramToCarry[NUM_BUCKET]; + __local u32 localHistogram[NUM_BUCKET*2]; + + u32 gIdx = GET_GLOBAL_IDX; + u32 lIdx = GET_LOCAL_IDX; + u32 wgIdx = GET_GROUP_IDX; + u32 wgSize = GET_GROUP_SIZE; + + const int n = cb.m_n; + const int nWGs = cb.m_nWGs; + const int startBit = cb.m_startBit; + const int nBlocksPerWG = cb.m_nBlocksPerWG; + + if( lIdx < (NUM_BUCKET) ) + { + localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx]; + } + + GROUP_LDS_BARRIER; + + const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE; + + int nBlocks = n/blockSize - nBlocksPerWG*wgIdx; + + int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx; + + for(int iblock=0; iblock>startBit) & 0xf; + + { // create histogram + u32 setIdx = lIdx/16; + if( lIdx < NUM_BUCKET ) + { + localHistogram[lIdx] = 0; + } + ldsSortData[lIdx] = 0; + GROUP_LDS_BARRIER; + + for(int i=0; i>startBit) & 0xf; + + { // create histogram + u32 setIdx = lIdx/16; + if( lIdx < NUM_BUCKET ) + { + localHistogram[lIdx] = 0; + } + ldsSortData[lIdx] = 0; + GROUP_LDS_BARRIER; + + for(int i=0; i gSrc : register( t0 ); +StructuredBuffer gSrcVal : register( t1 ); +StructuredBuffer rHistogram : register( t1 ); +StructuredBuffer rHistogram2 : register( t2 ); +RWStructuredBuffer histogramOut : register( u0 ); +RWStructuredBuffer wHistogram1 : register( u0 ); +RWStructuredBuffer gDst : register( u0 ); +RWStructuredBuffer gDstVal : register( u1 ); + +groupshared u32 localHistogramMat[NUM_BUCKET*WG_SIZE]; +#define MY_HISTOGRAM(idx) localHistogramMat[(idx)*WG_SIZE+lIdx] + + +[numthreads(WG_SIZE, 1, 1)] +void StreamCountKernel( DEFAULT_ARGS ) +{ + u32 gIdx = GET_GLOBAL_IDX; + u32 lIdx = GET_LOCAL_IDX; + u32 wgIdx = GET_GROUP_IDX; + u32 wgSize = GET_GROUP_SIZE; + const int startBit = m_startBit; + + const int n = m_n; + const int nWGs = m_nWGs; + const int nBlocksPerWG = m_nBlocksPerWG; + + for(int i=0; i>startBit) & 0xf; +#if defined(NV_GPU) + MY_HISTOGRAM( localKey )++; +#else + AtomInc( MY_HISTOGRAM( localKey ) ); +#endif + } + } + } + + GROUP_LDS_BARRIER; + + if( lIdx < NUM_BUCKET ) + { + u32 sum = 0; + for(int i=0; i 64 ) + { + ldsSortData[idx] += ldsSortData[idx-64]; + GROUP_MEM_FENCE; + } + + ldsSortData[idx-1] += ldsSortData[idx-2]; + GROUP_MEM_FENCE; + } +#else + if( lIdx < 64 ) + { + ldsSortData[idx] += ldsSortData[idx-1]; + GROUP_MEM_FENCE; + ldsSortData[idx] += ldsSortData[idx-2]; + GROUP_MEM_FENCE; + ldsSortData[idx] += ldsSortData[idx-4]; + GROUP_MEM_FENCE; + ldsSortData[idx] += ldsSortData[idx-8]; + GROUP_MEM_FENCE; + ldsSortData[idx] += ldsSortData[idx-16]; + GROUP_MEM_FENCE; + ldsSortData[idx] += ldsSortData[idx-32]; + GROUP_MEM_FENCE; + if( wgSize > 64 ) + { + ldsSortData[idx] += ldsSortData[idx-64]; + GROUP_MEM_FENCE; + } + + ldsSortData[idx-1] += ldsSortData[idx-2]; + GROUP_MEM_FENCE; + } +#endif + } + + GROUP_LDS_BARRIER; + + totalSum = ldsSortData[wgSize*2-1]; + u32 addValue = ldsSortData[lIdx+wgSize-1]; + return addValue; +} + +//__attribute__((reqd_work_group_size(128,1,1))) +uint4 localPrefixSum128V( uint4 pData, uint lIdx, inout uint totalSum ) +{ + u32 s4 = prefixScanVectorEx( pData ); + u32 rank = localPrefixSum( s4, lIdx, totalSum, 128 ); + return pData + make_uint4( rank, rank, rank, rank ); +} + +//__attribute__((reqd_work_group_size(64,1,1))) +uint4 localPrefixSum64V( uint4 pData, uint lIdx, inout uint totalSum ) +{ + u32 s4 = prefixScanVectorEx( pData ); + u32 rank = localPrefixSum( s4, lIdx, totalSum, 64 ); + return pData + make_uint4( rank, rank, rank, rank ); +} + + + + + +#define nPerLane (nPerWI/4) + +// NUM_BUCKET*nWGs < 128*nPerWI +[numthreads(128, 1, 1)] +void PrefixScanKernel( DEFAULT_ARGS ) +{ + u32 lIdx = GET_LOCAL_IDX; + u32 wgIdx = GET_GROUP_IDX; + const int nWGs = m_nWGs; + + u32 data[nPerWI]; + for(int i=0; i>(keyIdx*8)) & 0xff;} + +u32 bit8Scan(u32 v) +{ + return (v<<8) + (v<<16) + (v<<24); +} + + + + +void sort4Bits1(inout u32 sortData[4], int startBit, int lIdx) +{ +/* + for(uint ibit=0; ibit>(startBit+ibit)) & 0x3, + (sortData[1]>>(startBit+ibit)) & 0x3, + (sortData[2]>>(startBit+ibit)) & 0x3, + (sortData[3]>>(startBit+ibit)) & 0x3); + + u32 key4; + u32 sKeyPacked[4] = { 0, 0, 0, 0 }; + { + sKeyPacked[0] |= 1<<(8*b.x); + sKeyPacked[1] |= 1<<(8*b.y); + sKeyPacked[2] |= 1<<(8*b.z); + sKeyPacked[3] |= 1<<(8*b.w); + + key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3]; + } + + u32 rankPacked; + u32 sumPacked; + { + rankPacked = localPrefixSum64VSingle( key4, lIdx, sumPacked ); + } + +// GROUP_LDS_BARRIER; + + u32 sum[4] = { unpack4Key( sumPacked,0 ), unpack4Key( sumPacked,1 ), unpack4Key( sumPacked,2 ), unpack4Key( sumPacked,3 ) }; + + { + u32 sum4 = 0; + for(int ie=0; ie<4; ie++) + { + u32 tmp = sum[ie]; + sum[ie] = sum4; + sum4 += tmp; + } + } + + u32 newOffset[4] = { 0,0,0,0 }; + + for(int ie=0; ie<4; ie++) + { + uint4 key = extractKeys( b, ie ); + uint4 scannedKey = key; + prefixScanVectorEx( scannedKey ); + uint offset = sum[ie] + unpack4Key( rankPacked, ie ); + uint4 dstAddress = make_uint4( offset, offset, offset, offset ) + scannedKey; + + newOffset[0] += dstAddress.x*key.x; + newOffset[1] += dstAddress.y*key.y; + newOffset[2] += dstAddress.z*key.z; + newOffset[3] += dstAddress.w*key.w; + } + + + + { + ldsSortData[newOffset[0]] = sortData[0]; + ldsSortData[newOffset[1]] = sortData[1]; + ldsSortData[newOffset[2]] = sortData[2]; + ldsSortData[newOffset[3]] = sortData[3]; + +// GROUP_LDS_BARRIER; + + sortData[0] = ldsSortData[lIdx*4+0]; + sortData[1] = ldsSortData[lIdx*4+1]; + sortData[2] = ldsSortData[lIdx*4+2]; + sortData[3] = ldsSortData[lIdx*4+3]; + +// GROUP_LDS_BARRIER; + } + } +*/ + for(uint ibit=0; ibit>(startBit+ibit)) & 0x3, + (sortData[1]>>(startBit+ibit)) & 0x3, + (sortData[2]>>(startBit+ibit)) & 0x3, + (sortData[3]>>(startBit+ibit)) & 0x3); + + u32 key4; + u32 sKeyPacked[4] = { 0, 0, 0, 0 }; + { + sKeyPacked[0] |= 1<<(8*b.x); + sKeyPacked[1] |= 1<<(8*b.y); + sKeyPacked[2] |= 1<<(8*b.z); + sKeyPacked[3] |= 1<<(8*b.w); + + key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3]; + } + + u32 rankPacked; + u32 sumPacked; + { + rankPacked = localPrefixSum( key4, lIdx, sumPacked, WG_SIZE ); + } + + GROUP_LDS_BARRIER; + + u32 newOffset[4] = { 0,0,0,0 }; + { + u32 sumScanned = bit8Scan( sumPacked ); + + u32 scannedKeys[4]; + scannedKeys[0] = 1<<(8*b.x); + scannedKeys[1] = 1<<(8*b.y); + scannedKeys[2] = 1<<(8*b.z); + scannedKeys[3] = 1<<(8*b.w); + { // 4 scans at once + u32 sum4 = 0; + for(int ie=0; ie<4; ie++) + { + u32 tmp = scannedKeys[ie]; + scannedKeys[ie] = sum4; + sum4 += tmp; + } + } + + { + u32 sumPlusRank = sumScanned + rankPacked; + { u32 ie = b.x; + scannedKeys[0] += sumPlusRank; + newOffset[0] = unpack4Key( scannedKeys[0], ie ); + } + { u32 ie = b.y; + scannedKeys[1] += sumPlusRank; + newOffset[1] = unpack4Key( scannedKeys[1], ie ); + } + { u32 ie = b.z; + scannedKeys[2] += sumPlusRank; + newOffset[2] = unpack4Key( scannedKeys[2], ie ); + } + { u32 ie = b.w; + scannedKeys[3] += sumPlusRank; + newOffset[3] = unpack4Key( scannedKeys[3], ie ); + } + } + } + + + GROUP_LDS_BARRIER; + + { + ldsSortData[newOffset[0]] = sortData[0]; + ldsSortData[newOffset[1]] = sortData[1]; + ldsSortData[newOffset[2]] = sortData[2]; + ldsSortData[newOffset[3]] = sortData[3]; + + GROUP_LDS_BARRIER; + + u32 dstAddr = 4*lIdx; + sortData[0] = ldsSortData[dstAddr+0]; + sortData[1] = ldsSortData[dstAddr+1]; + sortData[2] = ldsSortData[dstAddr+2]; + sortData[3] = ldsSortData[dstAddr+3]; + + GROUP_LDS_BARRIER; + } + } +} + + +groupshared u32 localHistogramToCarry[NUM_BUCKET]; +groupshared u32 localHistogram[NUM_BUCKET*2]; +#define SET_HISTOGRAM(setIdx, key) ldsSortData[(setIdx)*NUM_BUCKET+key] + + +[numthreads(WG_SIZE, 1, 1)] +void SortAndScatterKernel( DEFAULT_ARGS ) +{ + u32 gIdx = GET_GLOBAL_IDX; + u32 lIdx = GET_LOCAL_IDX; + u32 wgIdx = GET_GROUP_IDX; + u32 wgSize = GET_GROUP_SIZE; + + const int n = m_n; + const int nWGs = m_nWGs; + const int startBit = m_startBit; + const int nBlocksPerWG = m_nBlocksPerWG; + + if( lIdx < (NUM_BUCKET) ) + { + localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx]; + } + + GROUP_LDS_BARRIER; + + const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE; + + int nBlocks = n/blockSize - nBlocksPerWG*wgIdx; + + int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx; + + for(int iblock=0; iblock>startBit) & 0xf; + + { // create histogram + u32 setIdx = lIdx/16; + if( lIdx < NUM_BUCKET ) + { + localHistogram[lIdx] = 0; + } + ldsSortData[lIdx] = 0; + GROUP_LDS_BARRIER; + + for(int i=0; i>startBit) & 0xf; + + { // create histogram + if( lIdx < NUM_BUCKET ) + { + localHistogram[lIdx] = 0; + localHistogram[NUM_BUCKET+lIdx] = 0; + } +// GROUP_LDS_BARRIER; + + AtomInc( localHistogram[NUM_BUCKET+keys[0]] ); + AtomInc( localHistogram[NUM_BUCKET+keys[1]] ); + AtomInc( localHistogram[NUM_BUCKET+keys[2]] ); + AtomInc( localHistogram[NUM_BUCKET+keys[3]] ); + +// GROUP_LDS_BARRIER; + + uint hIdx = NUM_BUCKET+lIdx; + if( lIdx < NUM_BUCKET ) + { + myHistogram = localHistogram[hIdx]; + } +// GROUP_LDS_BARRIER; + +#if defined(USE_2LEVEL_REDUCE) + if( lIdx < NUM_BUCKET ) + { + localHistogram[hIdx] = localHistogram[hIdx-1]; + GROUP_MEM_FENCE; + + u32 u0, u1, u2; + u0 = localHistogram[hIdx-3]; + u1 = localHistogram[hIdx-2]; + u2 = localHistogram[hIdx-1]; + AtomAdd( localHistogram[hIdx], u0 + u1 + u2 ); + GROUP_MEM_FENCE; + u0 = localHistogram[hIdx-12]; + u1 = localHistogram[hIdx-8]; + u2 = localHistogram[hIdx-4]; + AtomAdd( localHistogram[hIdx], u0 + u1 + u2 ); + GROUP_MEM_FENCE; + } +#else + if( lIdx < NUM_BUCKET ) + { + localHistogram[hIdx] = localHistogram[hIdx-1]; + GROUP_MEM_FENCE; + localHistogram[hIdx] += localHistogram[hIdx-1]; + GROUP_MEM_FENCE; + localHistogram[hIdx] += localHistogram[hIdx-2]; + GROUP_MEM_FENCE; + localHistogram[hIdx] += localHistogram[hIdx-4]; + GROUP_MEM_FENCE; + localHistogram[hIdx] += localHistogram[hIdx-8]; + GROUP_MEM_FENCE; + } +#endif + +// GROUP_LDS_BARRIER; + } + + { + for(int ie=0; ie>(startBit+ibit)) & 0x3, + (sortData[1]>>(startBit+ibit)) & 0x3, + (sortData[2]>>(startBit+ibit)) & 0x3, + (sortData[3]>>(startBit+ibit)) & 0x3); + + u32 key4; + u32 sKeyPacked[4] = { 0, 0, 0, 0 }; + { + sKeyPacked[0] |= 1<<(8*b.x); + sKeyPacked[1] |= 1<<(8*b.y); + sKeyPacked[2] |= 1<<(8*b.z); + sKeyPacked[3] |= 1<<(8*b.w); + + key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3]; + } + + u32 rankPacked; + u32 sumPacked; + { + rankPacked = localPrefixSum( key4, lIdx, sumPacked, WG_SIZE ); + } + + GROUP_LDS_BARRIER; + + u32 newOffset[4] = { 0,0,0,0 }; + { + u32 sumScanned = bit8Scan( sumPacked ); + + u32 scannedKeys[4]; + scannedKeys[0] = 1<<(8*b.x); + scannedKeys[1] = 1<<(8*b.y); + scannedKeys[2] = 1<<(8*b.z); + scannedKeys[3] = 1<<(8*b.w); + { // 4 scans at once + u32 sum4 = 0; + for(int ie=0; ie<4; ie++) + { + u32 tmp = scannedKeys[ie]; + scannedKeys[ie] = sum4; + sum4 += tmp; + } + } + + { + u32 sumPlusRank = sumScanned + rankPacked; + { u32 ie = b.x; + scannedKeys[0] += sumPlusRank; + newOffset[0] = unpack4Key( scannedKeys[0], ie ); + } + { u32 ie = b.y; + scannedKeys[1] += sumPlusRank; + newOffset[1] = unpack4Key( scannedKeys[1], ie ); + } + { u32 ie = b.z; + scannedKeys[2] += sumPlusRank; + newOffset[2] = unpack4Key( scannedKeys[2], ie ); + } + { u32 ie = b.w; + scannedKeys[3] += sumPlusRank; + newOffset[3] = unpack4Key( scannedKeys[3], ie ); + } + } + } + + + GROUP_LDS_BARRIER; + + { + ldsSortData[newOffset[0]] = sortData[0]; + ldsSortData[newOffset[1]] = sortData[1]; + ldsSortData[newOffset[2]] = sortData[2]; + ldsSortData[newOffset[3]] = sortData[3]; + + ldsSortVal[newOffset[0]] = sortVal[0]; + ldsSortVal[newOffset[1]] = sortVal[1]; + ldsSortVal[newOffset[2]] = sortVal[2]; + ldsSortVal[newOffset[3]] = sortVal[3]; + + GROUP_LDS_BARRIER; + + u32 dstAddr = 4*lIdx; + sortData[0] = ldsSortData[dstAddr+0]; + sortData[1] = ldsSortData[dstAddr+1]; + sortData[2] = ldsSortData[dstAddr+2]; + sortData[3] = ldsSortData[dstAddr+3]; + + sortVal[0] = ldsSortVal[dstAddr+0]; + sortVal[1] = ldsSortVal[dstAddr+1]; + sortVal[2] = ldsSortVal[dstAddr+2]; + sortVal[3] = ldsSortVal[dstAddr+3]; + + GROUP_LDS_BARRIER; + } + } +} + + + +[numthreads(WG_SIZE, 1, 1)] +void SortAndScatterKeyValueKernel( DEFAULT_ARGS ) +{ + u32 gIdx = GET_GLOBAL_IDX; + u32 lIdx = GET_LOCAL_IDX; + u32 wgIdx = GET_GROUP_IDX; + u32 wgSize = GET_GROUP_SIZE; + + const int n = m_n; + const int nWGs = m_nWGs; + const int startBit = m_startBit; + const int nBlocksPerWG = m_nBlocksPerWG; + + if( lIdx < (NUM_BUCKET) ) + { + localHistogramToCarry[lIdx] = rHistogram2[lIdx*nWGs + wgIdx]; + } + + GROUP_LDS_BARRIER; + + const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE; + + int nBlocks = n/blockSize - nBlocksPerWG*wgIdx; + + int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx; + + for(int iblock=0; iblock>startBit) & 0xf; + + { // create histogram + u32 setIdx = lIdx/16; + if( lIdx < NUM_BUCKET ) + { + localHistogram[lIdx] = 0; + } + ldsSortData[lIdx] = 0; + GROUP_LDS_BARRIER; + + for(int i=0; i 64 )\n" +" {\n" +" sorterSharedMemory[idx] += sorterSharedMemory[idx-64];\n" +" GROUP_MEM_FENCE;\n" +" }\n" +"\n" +" sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];\n" +" GROUP_MEM_FENCE;\n" +" }\n" +"#else\n" +" if( lIdx < 64 )\n" +" {\n" +" sorterSharedMemory[idx] += sorterSharedMemory[idx-1];\n" +" GROUP_MEM_FENCE;\n" +" sorterSharedMemory[idx] += sorterSharedMemory[idx-2]; \n" +" GROUP_MEM_FENCE;\n" +" sorterSharedMemory[idx] += sorterSharedMemory[idx-4];\n" +" GROUP_MEM_FENCE;\n" +" sorterSharedMemory[idx] += sorterSharedMemory[idx-8];\n" +" GROUP_MEM_FENCE;\n" +" sorterSharedMemory[idx] += sorterSharedMemory[idx-16];\n" +" GROUP_MEM_FENCE;\n" +" sorterSharedMemory[idx] += sorterSharedMemory[idx-32];\n" +" GROUP_MEM_FENCE;\n" +" if( wgSize > 64 )\n" +" {\n" +" sorterSharedMemory[idx] += sorterSharedMemory[idx-64];\n" +" GROUP_MEM_FENCE;\n" +" }\n" +"\n" +" sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];\n" +" GROUP_MEM_FENCE;\n" +" }\n" +"#endif\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" *totalSum = sorterSharedMemory[wgSize*2-1];\n" +" u32 addValue = sorterSharedMemory[lIdx+wgSize-1];\n" +" return addValue;\n" +"}\n" +"\n" +"//__attribute__((reqd_work_group_size(128,1,1)))\n" +"uint4 localPrefixSum128V( uint4 pData, uint lIdx, uint* totalSum, __local u32 sorterSharedMemory[] )\n" +"{\n" +" u32 s4 = prefixScanVectorEx( &pData );\n" +" u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 128 );\n" +" return pData + make_uint4( rank, rank, rank, rank );\n" +"}\n" +"\n" +"\n" +"//__attribute__((reqd_work_group_size(64,1,1)))\n" +"uint4 localPrefixSum64V( uint4 pData, uint lIdx, uint* totalSum, __local u32 sorterSharedMemory[] )\n" +"{\n" +" u32 s4 = prefixScanVectorEx( &pData );\n" +" u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 64 );\n" +" return pData + make_uint4( rank, rank, rank, rank );\n" +"}\n" +"\n" +"u32 unpack4Key( u32 key, int keyIdx ){ return (key>>(keyIdx*8)) & 0xff;}\n" +"\n" +"u32 bit8Scan(u32 v)\n" +"{\n" +" return (v<<8) + (v<<16) + (v<<24);\n" +"}\n" +"\n" +"//===\n" +"\n" +"\n" +"\n" +"\n" +"#define MY_HISTOGRAM(idx) localHistogramMat[(idx)*WG_SIZE+lIdx]\n" +"\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n" +"void StreamCountKernel( __global u32* gSrc, __global u32* histogramOut, ConstBuffer cb )\n" +"{\n" +" __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];\n" +"\n" +" u32 gIdx = GET_GLOBAL_IDX;\n" +" u32 lIdx = GET_LOCAL_IDX;\n" +" u32 wgIdx = GET_GROUP_IDX;\n" +" u32 wgSize = GET_GROUP_SIZE;\n" +" const int startBit = cb.m_startBit;\n" +" const int n = cb.m_n;\n" +" const int nWGs = cb.m_nWGs;\n" +" const int nBlocksPerWG = cb.m_nBlocksPerWG;\n" +"\n" +" for(int i=0; i>startBit) & 0xf;\n" +"#if defined(NV_GPU)\n" +" MY_HISTOGRAM( localKey )++;\n" +"#else\n" +" AtomInc( MY_HISTOGRAM( localKey ) );\n" +"#endif\n" +" }\n" +" }\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" \n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" u32 sum = 0;\n" +" for(int i=0; i>startBit) & 0xf;\n" +"#if defined(NV_GPU)\n" +" MY_HISTOGRAM( localKey )++;\n" +"#else\n" +" AtomInc( MY_HISTOGRAM( localKey ) );\n" +"#endif\n" +" }\n" +" }\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" \n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" u32 sum = 0;\n" +" for(int i=0; i>startBit) & mask, (sortData[1]>>startBit) & mask, (sortData[2]>>startBit) & mask, (sortData[3]>>startBit) & mask );\n" +" uint4 prefixSum = SELECT_UINT4( make_uint4(1,1,1,1), make_uint4(0,0,0,0), cmpResult != make_uint4(0,0,0,0) );\n" +" u32 total;\n" +" prefixSum = localPrefixSum64V( prefixSum, lIdx, &total, ldsSortData );\n" +" {\n" +" uint4 localAddr = make_uint4(lIdx*4+0,lIdx*4+1,lIdx*4+2,lIdx*4+3);\n" +" uint4 dstAddr = localAddr - prefixSum + make_uint4( total, total, total, total );\n" +" dstAddr = SELECT_UINT4( prefixSum, dstAddr, cmpResult != make_uint4(0, 0, 0, 0) );\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" ldsSortData[dstAddr.x] = sortData[0];\n" +" ldsSortData[dstAddr.y] = sortData[1];\n" +" ldsSortData[dstAddr.z] = sortData[2];\n" +" ldsSortData[dstAddr.w] = sortData[3];\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" sortData[0] = ldsSortData[localAddr.x];\n" +" sortData[1] = ldsSortData[localAddr.y];\n" +" sortData[2] = ldsSortData[localAddr.z];\n" +" sortData[3] = ldsSortData[localAddr.w];\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" }\n" +" }\n" +"}\n" +"\n" +"// 2 scan, 2 exchange\n" +"void sort4Bits1(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)\n" +"{\n" +" for(uint ibit=0; ibit>(startBit+ibit)) & 0x3, \n" +" (sortData[1]>>(startBit+ibit)) & 0x3, \n" +" (sortData[2]>>(startBit+ibit)) & 0x3, \n" +" (sortData[3]>>(startBit+ibit)) & 0x3);\n" +"\n" +" u32 key4;\n" +" u32 sKeyPacked[4] = { 0, 0, 0, 0 };\n" +" {\n" +" sKeyPacked[0] |= 1<<(8*b.x);\n" +" sKeyPacked[1] |= 1<<(8*b.y);\n" +" sKeyPacked[2] |= 1<<(8*b.z);\n" +" sKeyPacked[3] |= 1<<(8*b.w);\n" +"\n" +" key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];\n" +" }\n" +"\n" +" u32 rankPacked;\n" +" u32 sumPacked;\n" +" {\n" +" rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" u32 newOffset[4] = { 0,0,0,0 };\n" +" {\n" +" u32 sumScanned = bit8Scan( sumPacked );\n" +"\n" +" u32 scannedKeys[4];\n" +" scannedKeys[0] = 1<<(8*b.x);\n" +" scannedKeys[1] = 1<<(8*b.y);\n" +" scannedKeys[2] = 1<<(8*b.z);\n" +" scannedKeys[3] = 1<<(8*b.w);\n" +" { // 4 scans at once\n" +" u32 sum4 = 0;\n" +" for(int ie=0; ie<4; ie++)\n" +" {\n" +" u32 tmp = scannedKeys[ie];\n" +" scannedKeys[ie] = sum4;\n" +" sum4 += tmp;\n" +" }\n" +" }\n" +"\n" +" {\n" +" u32 sumPlusRank = sumScanned + rankPacked;\n" +" { u32 ie = b.x;\n" +" scannedKeys[0] += sumPlusRank;\n" +" newOffset[0] = unpack4Key( scannedKeys[0], ie );\n" +" }\n" +" { u32 ie = b.y;\n" +" scannedKeys[1] += sumPlusRank;\n" +" newOffset[1] = unpack4Key( scannedKeys[1], ie );\n" +" }\n" +" { u32 ie = b.z;\n" +" scannedKeys[2] += sumPlusRank;\n" +" newOffset[2] = unpack4Key( scannedKeys[2], ie );\n" +" }\n" +" { u32 ie = b.w;\n" +" scannedKeys[3] += sumPlusRank;\n" +" newOffset[3] = unpack4Key( scannedKeys[3], ie );\n" +" }\n" +" }\n" +" }\n" +"\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" {\n" +" ldsSortData[newOffset[0]] = sortData[0];\n" +" ldsSortData[newOffset[1]] = sortData[1];\n" +" ldsSortData[newOffset[2]] = sortData[2];\n" +" ldsSortData[newOffset[3]] = sortData[3];\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" u32 dstAddr = 4*lIdx;\n" +" sortData[0] = ldsSortData[dstAddr+0];\n" +" sortData[1] = ldsSortData[dstAddr+1];\n" +" sortData[2] = ldsSortData[dstAddr+2];\n" +" sortData[3] = ldsSortData[dstAddr+3];\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" }\n" +" }\n" +"}\n" +"\n" +"#define SET_HISTOGRAM(setIdx, key) ldsSortData[(setIdx)*NUM_BUCKET+key]\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n" +"void SortAndScatterKernel( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, ConstBuffer cb )\n" +"{\n" +" __local u32 ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n" +" __local u32 localHistogramToCarry[NUM_BUCKET];\n" +" __local u32 localHistogram[NUM_BUCKET*2];\n" +"\n" +" u32 gIdx = GET_GLOBAL_IDX;\n" +" u32 lIdx = GET_LOCAL_IDX;\n" +" u32 wgIdx = GET_GROUP_IDX;\n" +" u32 wgSize = GET_GROUP_SIZE;\n" +"\n" +" const int n = cb.m_n;\n" +" const int nWGs = cb.m_nWGs;\n" +" const int startBit = cb.m_startBit;\n" +" const int nBlocksPerWG = cb.m_nBlocksPerWG;\n" +"\n" +" if( lIdx < (NUM_BUCKET) )\n" +" {\n" +" localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n" +"\n" +" int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;\n" +"\n" +" int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n" +"\n" +" for(int iblock=0; iblock>startBit) & 0xf;\n" +"\n" +" { // create histogram\n" +" u32 setIdx = lIdx/16;\n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" localHistogram[lIdx] = 0;\n" +" }\n" +" ldsSortData[lIdx] = 0;\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" for(int i=0; i>(startBit+ibit)) & 0x3, \n" +" (sortData[1]>>(startBit+ibit)) & 0x3, \n" +" (sortData[2]>>(startBit+ibit)) & 0x3, \n" +" (sortData[3]>>(startBit+ibit)) & 0x3);\n" +"\n" +" u32 key4;\n" +" u32 sKeyPacked[4] = { 0, 0, 0, 0 };\n" +" {\n" +" sKeyPacked[0] |= 1<<(8*b.x);\n" +" sKeyPacked[1] |= 1<<(8*b.y);\n" +" sKeyPacked[2] |= 1<<(8*b.z);\n" +" sKeyPacked[3] |= 1<<(8*b.w);\n" +"\n" +" key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];\n" +" }\n" +"\n" +" u32 rankPacked;\n" +" u32 sumPacked;\n" +" {\n" +" rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" u32 newOffset[4] = { 0,0,0,0 };\n" +" {\n" +" u32 sumScanned = bit8Scan( sumPacked );\n" +"\n" +" u32 scannedKeys[4];\n" +" scannedKeys[0] = 1<<(8*b.x);\n" +" scannedKeys[1] = 1<<(8*b.y);\n" +" scannedKeys[2] = 1<<(8*b.z);\n" +" scannedKeys[3] = 1<<(8*b.w);\n" +" { // 4 scans at once\n" +" u32 sum4 = 0;\n" +" for(int ie=0; ie<4; ie++)\n" +" {\n" +" u32 tmp = scannedKeys[ie];\n" +" scannedKeys[ie] = sum4;\n" +" sum4 += tmp;\n" +" }\n" +" }\n" +"\n" +" {\n" +" u32 sumPlusRank = sumScanned + rankPacked;\n" +" { u32 ie = b.x;\n" +" scannedKeys[0] += sumPlusRank;\n" +" newOffset[0] = unpack4Key( scannedKeys[0], ie );\n" +" }\n" +" { u32 ie = b.y;\n" +" scannedKeys[1] += sumPlusRank;\n" +" newOffset[1] = unpack4Key( scannedKeys[1], ie );\n" +" }\n" +" { u32 ie = b.z;\n" +" scannedKeys[2] += sumPlusRank;\n" +" newOffset[2] = unpack4Key( scannedKeys[2], ie );\n" +" }\n" +" { u32 ie = b.w;\n" +" scannedKeys[3] += sumPlusRank;\n" +" newOffset[3] = unpack4Key( scannedKeys[3], ie );\n" +" }\n" +" }\n" +" }\n" +"\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" {\n" +" ldsSortData[newOffset[0]] = sortData[0];\n" +" ldsSortData[newOffset[1]] = sortData[1];\n" +" ldsSortData[newOffset[2]] = sortData[2];\n" +" ldsSortData[newOffset[3]] = sortData[3];\n" +"\n" +" ldsSortVal[newOffset[0]] = sortVal[0];\n" +" ldsSortVal[newOffset[1]] = sortVal[1];\n" +" ldsSortVal[newOffset[2]] = sortVal[2];\n" +" ldsSortVal[newOffset[3]] = sortVal[3];\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" u32 dstAddr = 4*lIdx;\n" +" sortData[0] = ldsSortData[dstAddr+0];\n" +" sortData[1] = ldsSortData[dstAddr+1];\n" +" sortData[2] = ldsSortData[dstAddr+2];\n" +" sortData[3] = ldsSortData[dstAddr+3];\n" +"\n" +" sortVal[0] = ldsSortVal[dstAddr+0];\n" +" sortVal[1] = ldsSortVal[dstAddr+1];\n" +" sortVal[2] = ldsSortVal[dstAddr+2];\n" +" sortVal[3] = ldsSortVal[dstAddr+3];\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" }\n" +" }\n" +"}\n" +"\n" +"\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n" +"void SortAndScatterKeyValueKernel( __global const u32* restrict gSrc, __global const int* restrict gSrcVal, __global const u32* rHistogram, __global u32* restrict gDst, __global int* restrict gDstVal, ConstBuffer cb)\n" +"{\n" +" __local u32 ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n" +" __local int ldsSortVal[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n" +" __local u32 localHistogramToCarry[NUM_BUCKET];\n" +" __local u32 localHistogram[NUM_BUCKET*2];\n" +"\n" +" u32 gIdx = GET_GLOBAL_IDX;\n" +" u32 lIdx = GET_LOCAL_IDX;\n" +" u32 wgIdx = GET_GROUP_IDX;\n" +" u32 wgSize = GET_GROUP_SIZE;\n" +"\n" +" const int n = cb.m_n;\n" +" const int nWGs = cb.m_nWGs;\n" +" const int startBit = cb.m_startBit;\n" +" const int nBlocksPerWG = cb.m_nBlocksPerWG;\n" +"\n" +" if( lIdx < (NUM_BUCKET) )\n" +" {\n" +" localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n" +"\n" +" int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;\n" +"\n" +" int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n" +"\n" +" for(int iblock=0; iblock>startBit) & 0xf;\n" +"\n" +" { // create histogram\n" +" u32 setIdx = lIdx/16;\n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" localHistogram[lIdx] = 0;\n" +" }\n" +" ldsSortData[lIdx] = 0;\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" for(int i=0; i>startBit) & 0xf;\n" +"\n" +" { // create histogram\n" +" u32 setIdx = lIdx/16;\n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" localHistogram[lIdx] = 0;\n" +" }\n" +" ldsSortData[lIdx] = 0;\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" for(int i=0; i gSrc : register( t0 );\n" +"StructuredBuffer gSrcVal : register( t1 );\n" +"StructuredBuffer rHistogram : register( t1 );\n" +"StructuredBuffer rHistogram2 : register( t2 );\n" +"RWStructuredBuffer histogramOut : register( u0 );\n" +"RWStructuredBuffer wHistogram1 : register( u0 );\n" +"RWStructuredBuffer gDst : register( u0 );\n" +"RWStructuredBuffer gDstVal : register( u1 );\n" +"\n" +"groupshared u32 localHistogramMat[NUM_BUCKET*WG_SIZE];\n" +"#define MY_HISTOGRAM(idx) localHistogramMat[(idx)*WG_SIZE+lIdx]\n" +"\n" +"\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void StreamCountKernel( DEFAULT_ARGS )\n" +"{\n" +" u32 gIdx = GET_GLOBAL_IDX;\n" +" u32 lIdx = GET_LOCAL_IDX;\n" +" u32 wgIdx = GET_GROUP_IDX;\n" +" u32 wgSize = GET_GROUP_SIZE;\n" +" const int startBit = m_startBit;\n" +"\n" +" const int n = m_n;\n" +" const int nWGs = m_nWGs;\n" +" const int nBlocksPerWG = m_nBlocksPerWG;\n" +"\n" +" for(int i=0; i>startBit) & 0xf;\n" +"#if defined(NV_GPU)\n" +" MY_HISTOGRAM( localKey )++;\n" +"#else\n" +" AtomInc( MY_HISTOGRAM( localKey ) );\n" +"#endif\n" +" }\n" +" }\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" \n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" u32 sum = 0;\n" +" for(int i=0; i 64 )\n" +" {\n" +" ldsSortData[idx] += ldsSortData[idx-64];\n" +" GROUP_MEM_FENCE;\n" +" }\n" +"\n" +" ldsSortData[idx-1] += ldsSortData[idx-2];\n" +" GROUP_MEM_FENCE;\n" +" }\n" +"#else\n" +" if( lIdx < 64 )\n" +" {\n" +" ldsSortData[idx] += ldsSortData[idx-1];\n" +" GROUP_MEM_FENCE;\n" +" ldsSortData[idx] += ldsSortData[idx-2]; \n" +" GROUP_MEM_FENCE;\n" +" ldsSortData[idx] += ldsSortData[idx-4];\n" +" GROUP_MEM_FENCE;\n" +" ldsSortData[idx] += ldsSortData[idx-8];\n" +" GROUP_MEM_FENCE;\n" +" ldsSortData[idx] += ldsSortData[idx-16];\n" +" GROUP_MEM_FENCE;\n" +" ldsSortData[idx] += ldsSortData[idx-32];\n" +" GROUP_MEM_FENCE;\n" +" if( wgSize > 64 )\n" +" {\n" +" ldsSortData[idx] += ldsSortData[idx-64];\n" +" GROUP_MEM_FENCE;\n" +" }\n" +"\n" +" ldsSortData[idx-1] += ldsSortData[idx-2];\n" +" GROUP_MEM_FENCE;\n" +" }\n" +"#endif\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" totalSum = ldsSortData[wgSize*2-1];\n" +" u32 addValue = ldsSortData[lIdx+wgSize-1];\n" +" return addValue;\n" +"}\n" +"\n" +"//__attribute__((reqd_work_group_size(128,1,1)))\n" +"uint4 localPrefixSum128V( uint4 pData, uint lIdx, inout uint totalSum )\n" +"{\n" +" u32 s4 = prefixScanVectorEx( pData );\n" +" u32 rank = localPrefixSum( s4, lIdx, totalSum, 128 );\n" +" return pData + make_uint4( rank, rank, rank, rank );\n" +"}\n" +"\n" +"//__attribute__((reqd_work_group_size(64,1,1)))\n" +"uint4 localPrefixSum64V( uint4 pData, uint lIdx, inout uint totalSum )\n" +"{\n" +" u32 s4 = prefixScanVectorEx( pData );\n" +" u32 rank = localPrefixSum( s4, lIdx, totalSum, 64 );\n" +" return pData + make_uint4( rank, rank, rank, rank );\n" +"}\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"#define nPerLane (nPerWI/4)\n" +"\n" +"// NUM_BUCKET*nWGs < 128*nPerWI\n" +"[numthreads(128, 1, 1)]\n" +"void PrefixScanKernel( DEFAULT_ARGS )\n" +"{\n" +" u32 lIdx = GET_LOCAL_IDX;\n" +" u32 wgIdx = GET_GROUP_IDX;\n" +" const int nWGs = m_nWGs;\n" +"\n" +" u32 data[nPerWI];\n" +" for(int i=0; i>(keyIdx*8)) & 0xff;}\n" +"\n" +"u32 bit8Scan(u32 v)\n" +"{\n" +" return (v<<8) + (v<<16) + (v<<24);\n" +"}\n" +"\n" +"\n" +"\n" +"\n" +"void sort4Bits1(inout u32 sortData[4], int startBit, int lIdx)\n" +"{\n" +"/*\n" +" for(uint ibit=0; ibit>(startBit+ibit)) & 0x3, \n" +" (sortData[1]>>(startBit+ibit)) & 0x3, \n" +" (sortData[2]>>(startBit+ibit)) & 0x3, \n" +" (sortData[3]>>(startBit+ibit)) & 0x3);\n" +"\n" +" u32 key4;\n" +" u32 sKeyPacked[4] = { 0, 0, 0, 0 };\n" +" {\n" +" sKeyPacked[0] |= 1<<(8*b.x);\n" +" sKeyPacked[1] |= 1<<(8*b.y);\n" +" sKeyPacked[2] |= 1<<(8*b.z);\n" +" sKeyPacked[3] |= 1<<(8*b.w);\n" +"\n" +" key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];\n" +" }\n" +"\n" +" u32 rankPacked;\n" +" u32 sumPacked;\n" +" {\n" +" rankPacked = localPrefixSum64VSingle( key4, lIdx, sumPacked );\n" +" }\n" +"\n" +"// GROUP_LDS_BARRIER;\n" +"\n" +" u32 sum[4] = { unpack4Key( sumPacked,0 ), unpack4Key( sumPacked,1 ), unpack4Key( sumPacked,2 ), unpack4Key( sumPacked,3 ) };\n" +"\n" +" {\n" +" u32 sum4 = 0;\n" +" for(int ie=0; ie<4; ie++)\n" +" {\n" +" u32 tmp = sum[ie];\n" +" sum[ie] = sum4;\n" +" sum4 += tmp;\n" +" }\n" +" }\n" +"\n" +" u32 newOffset[4] = { 0,0,0,0 };\n" +"\n" +" for(int ie=0; ie<4; ie++)\n" +" {\n" +" uint4 key = extractKeys( b, ie );\n" +" uint4 scannedKey = key;\n" +" prefixScanVectorEx( scannedKey );\n" +" uint offset = sum[ie] + unpack4Key( rankPacked, ie );\n" +" uint4 dstAddress = make_uint4( offset, offset, offset, offset ) + scannedKey;\n" +"\n" +" newOffset[0] += dstAddress.x*key.x;\n" +" newOffset[1] += dstAddress.y*key.y;\n" +" newOffset[2] += dstAddress.z*key.z;\n" +" newOffset[3] += dstAddress.w*key.w;\n" +" }\n" +"\n" +"\n" +"\n" +" {\n" +" ldsSortData[newOffset[0]] = sortData[0];\n" +" ldsSortData[newOffset[1]] = sortData[1];\n" +" ldsSortData[newOffset[2]] = sortData[2];\n" +" ldsSortData[newOffset[3]] = sortData[3];\n" +"\n" +"// GROUP_LDS_BARRIER;\n" +"\n" +" sortData[0] = ldsSortData[lIdx*4+0];\n" +" sortData[1] = ldsSortData[lIdx*4+1];\n" +" sortData[2] = ldsSortData[lIdx*4+2];\n" +" sortData[3] = ldsSortData[lIdx*4+3];\n" +"\n" +"// GROUP_LDS_BARRIER;\n" +" }\n" +" }\n" +"*/\n" +" for(uint ibit=0; ibit>(startBit+ibit)) & 0x3, \n" +" (sortData[1]>>(startBit+ibit)) & 0x3, \n" +" (sortData[2]>>(startBit+ibit)) & 0x3, \n" +" (sortData[3]>>(startBit+ibit)) & 0x3);\n" +"\n" +" u32 key4;\n" +" u32 sKeyPacked[4] = { 0, 0, 0, 0 };\n" +" {\n" +" sKeyPacked[0] |= 1<<(8*b.x);\n" +" sKeyPacked[1] |= 1<<(8*b.y);\n" +" sKeyPacked[2] |= 1<<(8*b.z);\n" +" sKeyPacked[3] |= 1<<(8*b.w);\n" +"\n" +" key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];\n" +" }\n" +"\n" +" u32 rankPacked;\n" +" u32 sumPacked;\n" +" {\n" +" rankPacked = localPrefixSum( key4, lIdx, sumPacked, WG_SIZE );\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" u32 newOffset[4] = { 0,0,0,0 };\n" +" {\n" +" u32 sumScanned = bit8Scan( sumPacked );\n" +"\n" +" u32 scannedKeys[4];\n" +" scannedKeys[0] = 1<<(8*b.x);\n" +" scannedKeys[1] = 1<<(8*b.y);\n" +" scannedKeys[2] = 1<<(8*b.z);\n" +" scannedKeys[3] = 1<<(8*b.w);\n" +" { // 4 scans at once\n" +" u32 sum4 = 0;\n" +" for(int ie=0; ie<4; ie++)\n" +" {\n" +" u32 tmp = scannedKeys[ie];\n" +" scannedKeys[ie] = sum4;\n" +" sum4 += tmp;\n" +" }\n" +" }\n" +"\n" +" {\n" +" u32 sumPlusRank = sumScanned + rankPacked;\n" +" { u32 ie = b.x;\n" +" scannedKeys[0] += sumPlusRank;\n" +" newOffset[0] = unpack4Key( scannedKeys[0], ie );\n" +" }\n" +" { u32 ie = b.y;\n" +" scannedKeys[1] += sumPlusRank;\n" +" newOffset[1] = unpack4Key( scannedKeys[1], ie );\n" +" }\n" +" { u32 ie = b.z;\n" +" scannedKeys[2] += sumPlusRank;\n" +" newOffset[2] = unpack4Key( scannedKeys[2], ie );\n" +" }\n" +" { u32 ie = b.w;\n" +" scannedKeys[3] += sumPlusRank;\n" +" newOffset[3] = unpack4Key( scannedKeys[3], ie );\n" +" }\n" +" }\n" +" }\n" +"\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" {\n" +" ldsSortData[newOffset[0]] = sortData[0];\n" +" ldsSortData[newOffset[1]] = sortData[1];\n" +" ldsSortData[newOffset[2]] = sortData[2];\n" +" ldsSortData[newOffset[3]] = sortData[3];\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" u32 dstAddr = 4*lIdx;\n" +" sortData[0] = ldsSortData[dstAddr+0];\n" +" sortData[1] = ldsSortData[dstAddr+1];\n" +" sortData[2] = ldsSortData[dstAddr+2];\n" +" sortData[3] = ldsSortData[dstAddr+3];\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" }\n" +" }\n" +"}\n" +"\n" +"\n" +"groupshared u32 localHistogramToCarry[NUM_BUCKET];\n" +"groupshared u32 localHistogram[NUM_BUCKET*2];\n" +"#define SET_HISTOGRAM(setIdx, key) ldsSortData[(setIdx)*NUM_BUCKET+key]\n" +"\n" +"\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void SortAndScatterKernel( DEFAULT_ARGS )\n" +"{\n" +" u32 gIdx = GET_GLOBAL_IDX;\n" +" u32 lIdx = GET_LOCAL_IDX;\n" +" u32 wgIdx = GET_GROUP_IDX;\n" +" u32 wgSize = GET_GROUP_SIZE;\n" +"\n" +" const int n = m_n;\n" +" const int nWGs = m_nWGs;\n" +" const int startBit = m_startBit;\n" +" const int nBlocksPerWG = m_nBlocksPerWG;\n" +"\n" +" if( lIdx < (NUM_BUCKET) )\n" +" {\n" +" localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n" +"\n" +" int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;\n" +"\n" +" int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n" +"\n" +" for(int iblock=0; iblock>startBit) & 0xf;\n" +"\n" +" { // create histogram\n" +" u32 setIdx = lIdx/16;\n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" localHistogram[lIdx] = 0;\n" +" }\n" +" ldsSortData[lIdx] = 0;\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" for(int i=0; i>startBit) & 0xf;\n" +"\n" +" { // create histogram\n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" localHistogram[lIdx] = 0;\n" +" localHistogram[NUM_BUCKET+lIdx] = 0;\n" +" }\n" +"// GROUP_LDS_BARRIER;\n" +"\n" +" AtomInc( localHistogram[NUM_BUCKET+keys[0]] );\n" +" AtomInc( localHistogram[NUM_BUCKET+keys[1]] );\n" +" AtomInc( localHistogram[NUM_BUCKET+keys[2]] );\n" +" AtomInc( localHistogram[NUM_BUCKET+keys[3]] );\n" +" \n" +"// GROUP_LDS_BARRIER;\n" +" \n" +" uint hIdx = NUM_BUCKET+lIdx;\n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" myHistogram = localHistogram[hIdx];\n" +" }\n" +"// GROUP_LDS_BARRIER;\n" +"\n" +"#if defined(USE_2LEVEL_REDUCE)\n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" localHistogram[hIdx] = localHistogram[hIdx-1];\n" +" GROUP_MEM_FENCE;\n" +"\n" +" u32 u0, u1, u2;\n" +" u0 = localHistogram[hIdx-3];\n" +" u1 = localHistogram[hIdx-2];\n" +" u2 = localHistogram[hIdx-1];\n" +" AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n" +" GROUP_MEM_FENCE;\n" +" u0 = localHistogram[hIdx-12];\n" +" u1 = localHistogram[hIdx-8];\n" +" u2 = localHistogram[hIdx-4];\n" +" AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n" +" GROUP_MEM_FENCE;\n" +" }\n" +"#else\n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" localHistogram[hIdx] = localHistogram[hIdx-1];\n" +" GROUP_MEM_FENCE;\n" +" localHistogram[hIdx] += localHistogram[hIdx-1];\n" +" GROUP_MEM_FENCE;\n" +" localHistogram[hIdx] += localHistogram[hIdx-2];\n" +" GROUP_MEM_FENCE;\n" +" localHistogram[hIdx] += localHistogram[hIdx-4];\n" +" GROUP_MEM_FENCE;\n" +" localHistogram[hIdx] += localHistogram[hIdx-8];\n" +" GROUP_MEM_FENCE;\n" +" }\n" +"#endif\n" +"\n" +"// GROUP_LDS_BARRIER;\n" +" }\n" +"\n" +" {\n" +" for(int ie=0; ie>(startBit+ibit)) & 0x3, \n" +" (sortData[1]>>(startBit+ibit)) & 0x3, \n" +" (sortData[2]>>(startBit+ibit)) & 0x3, \n" +" (sortData[3]>>(startBit+ibit)) & 0x3);\n" +"\n" +" u32 key4;\n" +" u32 sKeyPacked[4] = { 0, 0, 0, 0 };\n" +" {\n" +" sKeyPacked[0] |= 1<<(8*b.x);\n" +" sKeyPacked[1] |= 1<<(8*b.y);\n" +" sKeyPacked[2] |= 1<<(8*b.z);\n" +" sKeyPacked[3] |= 1<<(8*b.w);\n" +"\n" +" key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];\n" +" }\n" +"\n" +" u32 rankPacked;\n" +" u32 sumPacked;\n" +" {\n" +" rankPacked = localPrefixSum( key4, lIdx, sumPacked, WG_SIZE );\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" u32 newOffset[4] = { 0,0,0,0 };\n" +" {\n" +" u32 sumScanned = bit8Scan( sumPacked );\n" +"\n" +" u32 scannedKeys[4];\n" +" scannedKeys[0] = 1<<(8*b.x);\n" +" scannedKeys[1] = 1<<(8*b.y);\n" +" scannedKeys[2] = 1<<(8*b.z);\n" +" scannedKeys[3] = 1<<(8*b.w);\n" +" { // 4 scans at once\n" +" u32 sum4 = 0;\n" +" for(int ie=0; ie<4; ie++)\n" +" {\n" +" u32 tmp = scannedKeys[ie];\n" +" scannedKeys[ie] = sum4;\n" +" sum4 += tmp;\n" +" }\n" +" }\n" +"\n" +" {\n" +" u32 sumPlusRank = sumScanned + rankPacked;\n" +" { u32 ie = b.x;\n" +" scannedKeys[0] += sumPlusRank;\n" +" newOffset[0] = unpack4Key( scannedKeys[0], ie );\n" +" }\n" +" { u32 ie = b.y;\n" +" scannedKeys[1] += sumPlusRank;\n" +" newOffset[1] = unpack4Key( scannedKeys[1], ie );\n" +" }\n" +" { u32 ie = b.z;\n" +" scannedKeys[2] += sumPlusRank;\n" +" newOffset[2] = unpack4Key( scannedKeys[2], ie );\n" +" }\n" +" { u32 ie = b.w;\n" +" scannedKeys[3] += sumPlusRank;\n" +" newOffset[3] = unpack4Key( scannedKeys[3], ie );\n" +" }\n" +" }\n" +" }\n" +"\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" {\n" +" ldsSortData[newOffset[0]] = sortData[0];\n" +" ldsSortData[newOffset[1]] = sortData[1];\n" +" ldsSortData[newOffset[2]] = sortData[2];\n" +" ldsSortData[newOffset[3]] = sortData[3];\n" +"\n" +" ldsSortVal[newOffset[0]] = sortVal[0];\n" +" ldsSortVal[newOffset[1]] = sortVal[1];\n" +" ldsSortVal[newOffset[2]] = sortVal[2];\n" +" ldsSortVal[newOffset[3]] = sortVal[3];\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" u32 dstAddr = 4*lIdx;\n" +" sortData[0] = ldsSortData[dstAddr+0];\n" +" sortData[1] = ldsSortData[dstAddr+1];\n" +" sortData[2] = ldsSortData[dstAddr+2];\n" +" sortData[3] = ldsSortData[dstAddr+3];\n" +"\n" +" sortVal[0] = ldsSortVal[dstAddr+0];\n" +" sortVal[1] = ldsSortVal[dstAddr+1];\n" +" sortVal[2] = ldsSortVal[dstAddr+2];\n" +" sortVal[3] = ldsSortVal[dstAddr+3];\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" }\n" +" }\n" +"}\n" +"\n" +"\n" +"\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void SortAndScatterKeyValueKernel( DEFAULT_ARGS )\n" +"{\n" +" u32 gIdx = GET_GLOBAL_IDX;\n" +" u32 lIdx = GET_LOCAL_IDX;\n" +" u32 wgIdx = GET_GROUP_IDX;\n" +" u32 wgSize = GET_GROUP_SIZE;\n" +"\n" +" const int n = m_n;\n" +" const int nWGs = m_nWGs;\n" +" const int startBit = m_startBit;\n" +" const int nBlocksPerWG = m_nBlocksPerWG;\n" +"\n" +" if( lIdx < (NUM_BUCKET) )\n" +" {\n" +" localHistogramToCarry[lIdx] = rHistogram2[lIdx*nWGs + wgIdx];\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n" +"\n" +" int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;\n" +"\n" +" int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n" +"\n" +" for(int iblock=0; iblock>startBit) & 0xf;\n" +"\n" +" { // create histogram\n" +" u32 setIdx = lIdx/16;\n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" localHistogram[lIdx] = 0;\n" +" }\n" +" ldsSortData[lIdx] = 0;\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" for(int i=0; i rHistogram : register(t0); + +RWStructuredBuffer dataToSort : register( u0 ); +RWStructuredBuffer dataToSortOut : register( u1 ); + + + +#define WG_SIZE 128 +#define ELEMENTS_PER_WORK_ITEM 4 +#define BITS_PER_PASS 4 +#define NUM_BUCKET (1<> targetKey; + key.y = (data.y & mask) >> targetKey; + key.z = (data.z & mask) >> targetKey; + key.w = (data.w & mask) >> targetKey; + return key; +} + +uint packKeys(uint lower, uint upper) +{ + return lower|(upper<<16); +} + +uint4 packKeys(uint4 lower, uint4 upper) +{ + return uint4( lower.x|(upper.x<<16), lower.y|(upper.y<<16), lower.z|(upper.z<<16), lower.w|(upper.w<<16) ); +} + +uint extractLower( uint data ) +{ + return data&0xffff; +} + +uint extractUpper( uint data ) +{ + return (data>>16)&0xffff; +} + +uint4 extractLower( uint4 data ) +{ + return uint4( data.x&0xffff, data.y&0xffff, data.z&0xffff, data.w&0xffff ); +} + +uint4 extractUpper( uint4 data ) +{ + return uint4( (data.x>>16)&0xffff, (data.y>>16)&0xffff, (data.z>>16)&0xffff, (data.w>>16)&0xffff ); +} + +[numthreads(WG_SIZE, 1, 1)] +void SortAndScatterKernel( DEFAULT_ARGS ) +{ + u32 lIdx = GET_LOCAL_IDX; + u32 wgIdx = GET_GROUP_IDX; + + if( lIdx < (NUM_BUCKET) ) + { + localHistogramToCarry[lIdx] = rHistogram[lIdx*m_nWorkGroupsToExecute + wgIdx]; + } + + GROUP_LDS_BARRIER; + + for(uint igroup=wgIdx*m_nBlocksPerGroup; igroup>m_startBit) & 0xf, (myData[1].key>>m_startBit) & 0xf, (myData[2].key>>m_startBit) & 0xf, (myData[3].key>>m_startBit) & 0xf); + for(uint targetKey=0; targetKey<(NUM_BUCKET); targetKey+=4) + { + uint4 key[4]; + uint keySet[2]; + { // pack 4 + uint4 scannedKey[4]; + key[0] = scannedKey[0] = extractKeys( b, targetKey+0 ); + key[1] = scannedKey[1] = extractKeys( b, targetKey+1 ); + key[2] = scannedKey[2] = extractKeys( b, targetKey+2 ); + key[3] = scannedKey[3] = extractKeys( b, targetKey+3 ); + { + uint s[4]; + s[0] = prefixScanVectorEx( scannedKey[0] ); + s[1] = prefixScanVectorEx( scannedKey[1] ); + s[2] = prefixScanVectorEx( scannedKey[2] ); + s[3] = prefixScanVectorEx( scannedKey[3] ); + keySet[0] = packKeys( s[0], s[1] ); + keySet[1] = packKeys( s[2], s[3] ); + } + } + + uint dstAddressBase[4]; + { + + uint totalSumPacked[2]; + uint dstAddressPacked[2]; + + localPrefixScan128Dual( keySet[0], keySet[1], lIdx, dstAddressPacked[0], dstAddressPacked[1], totalSumPacked[0], totalSumPacked[1] ); + + dstAddressBase[0] = extractLower( dstAddressPacked[0] ); + dstAddressBase[1] = extractUpper( dstAddressPacked[0] ); + dstAddressBase[2] = extractLower( dstAddressPacked[1] ); + dstAddressBase[3] = extractUpper( dstAddressPacked[1] ); + + uint4 histogram; + histogram.x = extractLower(totalSumPacked[0]); + histogram.y = extractUpper(totalSumPacked[0]); + histogram.z = extractLower(totalSumPacked[1]); + histogram.w = extractUpper(totalSumPacked[1]); + + if( lIdx == targetKey + 0 ) myHistogram = histogram.x; + else if( lIdx == targetKey + 1 ) myHistogram = histogram.y; + else if( lIdx == targetKey + 2 ) myHistogram = histogram.z; + else if( lIdx == targetKey + 3 ) myHistogram = histogram.w; + + uint histogramSum = prefixScanVectorEx( histogram ); + + if( lIdx == targetKey + 0 ) localPrefixSum[targetKey+0] = localOffset+histogram.x; + else if( lIdx == targetKey + 1 ) localPrefixSum[targetKey+1] = localOffset+histogram.y; + else if( lIdx == targetKey + 2 ) localPrefixSum[targetKey+2] = localOffset+histogram.z; + else if( lIdx == targetKey + 3 ) localPrefixSum[targetKey+3] = localOffset+histogram.w; + + localOffset += histogramSum; + } + + GROUP_LDS_BARRIER; + + + for(int ie=0; ie<4; ie++) + { + uint4 scannedKey = key[ie]; + prefixScanVectorEx( scannedKey ); + + uint offset = localPrefixSum[targetKey + ie] + dstAddressBase[ie]; + uint4 dstAddress = uint4( offset, offset, offset, offset ) + scannedKey; + + newOffset[0] += dstAddress.x*key[ie].x; + newOffset[1] += dstAddress.y*key[ie].y; + newOffset[2] += dstAddress.z*key[ie].z; + newOffset[3] += dstAddress.w*key[ie].w; + } + } + + { // local scatter + SET_LOCAL_SORT_DATA(newOffset[0], myData[0]); + SET_LOCAL_SORT_DATA(newOffset[1], myData[1]); + SET_LOCAL_SORT_DATA(newOffset[2], myData[2]); + SET_LOCAL_SORT_DATA(newOffset[3], myData[3]); + } + + GROUP_LDS_BARRIER; + + { // write data + for(int i=0; i> m_startBit) & 0xf; + int groupOffset = localHistogramToCarry[binIdx]; + int myIdx = dataIdx - localPrefixSum[binIdx]; + + dataToSortOut[ groupOffset + myIdx ] = localData; + } + } + + GROUP_LDS_BARRIER; + if( lIdx < NUM_BUCKET ) + { + localHistogramToCarry[lIdx] += myHistogram; + } + GROUP_LDS_BARRIER; + } +} + + +[numthreads(WG_SIZE, 1, 1)] +void SortAndScatterKernel1( DEFAULT_ARGS ) +{ + u32 lIdx = GET_LOCAL_IDX; + u32 wgIdx = GET_GROUP_IDX; + + if( lIdx < (NUM_BUCKET) ) + { + localHistogramToCarry[lIdx] = rHistogram[lIdx*m_nWorkGroupsToExecute + wgIdx.x]; + } + + GROUP_LDS_BARRIER; + + for(uint igroup=wgIdx.x*m_nBlocksPerGroup; igroup>ib) & 0x1, ~(myData[1].key>>ib) & 0x1, ~(myData[2].key>>ib) & 0x1, ~(myData[3].key>>ib) & 0x1); + uint total; + uint4 rankOfP = localPrefixSum128V( keys, lIdx, total ); + uint4 rankOfN = uint4(startAddrBlock, startAddrBlock+1, startAddrBlock+2, startAddrBlock+3) - rankOfP + uint4( total, total, total, total ); + + uint4 myAddr = (keys==uint4(1,1,1,1))? rankOfP: rankOfN; + + GROUP_LDS_BARRIER; + + SET_LOCAL_SORT_DATA( myAddr.x, myData[0] ); + SET_LOCAL_SORT_DATA( myAddr.y, myData[1] ); + SET_LOCAL_SORT_DATA( myAddr.z, myData[2] ); + SET_LOCAL_SORT_DATA( myAddr.w, myData[3] ); + + GROUP_LDS_BARRIER; + + GET_LOCAL_SORT_DATA( startAddrBlock+0, myData[0] ); + GET_LOCAL_SORT_DATA( startAddrBlock+1, myData[1] ); + GET_LOCAL_SORT_DATA( startAddrBlock+2, myData[2] ); + GET_LOCAL_SORT_DATA( startAddrBlock+3, myData[3] ); + } + + {// create histogram -> prefix sum + if( lIdx < NUM_BUCKET ) + { + localHistogram[lIdx] = 0; + localHistogram[NUM_BUCKET+lIdx] = 0; + } + GROUP_LDS_BARRIER; + uint4 keys = uint4((myData[0].key>>m_startBit) & 0xf, (myData[1].key>>m_startBit) & 0xf, (myData[2].key>>m_startBit) & 0xf, (myData[3].key>>m_startBit) & 0xf); + + InterlockedAdd( localHistogram[NUM_BUCKET+keys.x], 1 ); + InterlockedAdd( localHistogram[NUM_BUCKET+keys.y], 1 ); + InterlockedAdd( localHistogram[NUM_BUCKET+keys.z], 1 ); + InterlockedAdd( localHistogram[NUM_BUCKET+keys.w], 1 ); + + GROUP_LDS_BARRIER; + + uint hIdx = NUM_BUCKET+lIdx; + if( lIdx < NUM_BUCKET ) + { + myHistogram = localHistogram[hIdx]; + } + GROUP_LDS_BARRIER; + + if( lIdx < NUM_BUCKET ) + { + localHistogram[hIdx] = localHistogram[hIdx-1]; + + localHistogram[hIdx] += localHistogram[hIdx-1]; + localHistogram[hIdx] += localHistogram[hIdx-2]; + localHistogram[hIdx] += localHistogram[hIdx-4]; + localHistogram[hIdx] += localHistogram[hIdx-8]; + } + + GROUP_LDS_BARRIER; + } +/* + {// write back + int numLocalElements = WG_SIZE*ELEMENTS_PER_WORK_ITEM; + startAddrBlock = lIdx*4; + uint startAddress = igroup*numLocalElements + startAddrBlock; + + for(int ie=0; ie>m_startBit)&0xf; + int groupOffset = localHistogramToCarry[binIdx]; + int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx]; + dataToSortOut[ groupOffset + myIdx ] = myData[ie]; + } + } + + GROUP_LDS_BARRIER; + if( lIdx < NUM_BUCKET ) + { + localHistogramToCarry[lIdx] += myHistogram; + } + GROUP_LDS_BARRIER; + + } +} + +/* +[numthreads(WG_SIZE, 1, 1)] +void SortAndScatterKernel1( uint3 gIdx : SV_GroupID, uint3 lIdx : SV_GroupThreadID ) +{ + if( lIdx.x < (NUM_BUCKET) ) + { + localHistogramToCarry[lIdx.x] = rHistogram[lIdx.x*m_nWorkGroupsToExecute + gIdx.x]; + } + + GROUP_LDS_BARRIER; + + for(uint igroup=gIdx.x*m_nBlocksPerGroup; igroup>ib) & 0x1, ~(myData[1].key>>ib) & 0x1, ~(myData[2].key>>ib) & 0x1, ~(myData[3].key>>ib) & 0x1); + uint total; + uint4 rankOfP = localPrefixSum128V( keys, lIdx.x, total ); + uint4 rankOfN = uint4(startAddrBlock, startAddrBlock+1, startAddrBlock+2, startAddrBlock+3) - rankOfP + uint4( total, total, total, total ); + + uint4 myAddr = (keys==uint4(1,1,1,1))? rankOfP: rankOfN; + + GROUP_LDS_BARRIER; + + SET_LOCAL_SORT_DATA( myAddr.x, myData[0] ); + SET_LOCAL_SORT_DATA( myAddr.y, myData[1] ); + SET_LOCAL_SORT_DATA( myAddr.z, myData[2] ); + SET_LOCAL_SORT_DATA( myAddr.w, myData[3] ); + + GROUP_LDS_BARRIER; + + GET_LOCAL_SORT_DATA( startAddrBlock+0, myData[0] ); + GET_LOCAL_SORT_DATA( startAddrBlock+1, myData[1] ); + GET_LOCAL_SORT_DATA( startAddrBlock+2, myData[2] ); + GET_LOCAL_SORT_DATA( startAddrBlock+3, myData[3] ); + } + + {// create histogram -> prefix sum + if( lIdx.x < NUM_BUCKET ) + { + localHistogram[lIdx.x] = 0; + localHistogram[NUM_BUCKET+lIdx.x] = 0; + } + GROUP_LDS_BARRIER; + uint4 keys = uint4((myData[0].key>>m_startBit) & 0xf, (myData[1].key>>m_startBit) & 0xf, (myData[2].key>>m_startBit) & 0xf, (myData[3].key>>m_startBit) & 0xf); + + InterlockedAdd( localHistogram[NUM_BUCKET+keys.x], 1 ); + InterlockedAdd( localHistogram[NUM_BUCKET+keys.y], 1 ); + InterlockedAdd( localHistogram[NUM_BUCKET+keys.z], 1 ); + InterlockedAdd( localHistogram[NUM_BUCKET+keys.w], 1 ); + + GROUP_LDS_BARRIER; + + uint hIdx = NUM_BUCKET+lIdx.x; + if( lIdx.x < NUM_BUCKET ) + { + myHistogram = localHistogram[hIdx]; + } + GROUP_LDS_BARRIER; + + + if( lIdx.x < NUM_BUCKET ) + { + localHistogram[hIdx] = localHistogram[hIdx-1]; + + localHistogram[hIdx] += localHistogram[hIdx-1]; + localHistogram[hIdx] += localHistogram[hIdx-2]; + localHistogram[hIdx] += localHistogram[hIdx-4]; + localHistogram[hIdx] += localHistogram[hIdx-8]; + } + + GROUP_LDS_BARRIER; + } + {// write back + for(int ie=0; ie>m_startBit)&0xf; + int groupOffset = localHistogramToCarry[binIdx]; + int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx]; + + dataToSortOut[ groupOffset + myIdx ] = myData[ie]; + } + } + + GROUP_LDS_BARRIER; + if( lIdx.x < NUM_BUCKET ) + { + localHistogramToCarry[lIdx.x] += myHistogram; + } + GROUP_LDS_BARRIER; + + } +} +*/ + +StructuredBuffer dataToSort1 : register( t0 ); +RWStructuredBuffer wHistogram1 : register(u0); + +#define MY_HISTOGRAM(idx) localHistogramMat[(idx)*WG_SIZE+lIdx.x] + +[numthreads(WG_SIZE, 1, 1)] +void StreamCountKernel( DEFAULT_ARGS ) +{ + u32 lIdx = GET_LOCAL_IDX; + u32 wgIdx = GET_GROUP_IDX; + + int myHistogram[NUM_BUCKET]; + + for(int i=0; i> m_startBit) & 0xf; + localKeys[1] = (localData1.key >> m_startBit) & 0xf; + localKeys[2] = (localData2.key >> m_startBit) & 0xf; + localKeys[3] = (localData3.key >> m_startBit) & 0xf; + } + + MY_HISTOGRAM( localKeys[0] )++; + MY_HISTOGRAM( localKeys[1] )++; + MY_HISTOGRAM( localKeys[2] )++; + MY_HISTOGRAM( localKeys[3] )++; + } + + GROUP_LDS_BARRIER; + + { // reduce to 1 + if( lIdx < 64 )//WG_SIZE/2 ) + { + for(int i=0; i> m_startBit) & 0xf; + localKeys[1] = (localData1.key >> m_startBit) & 0xf; + localKeys[2] = (localData2.key >> m_startBit) & 0xf; + localKeys[3] = (localData3.key >> m_startBit) & 0xf; + } + + myHistogram[ localKeys[0] ]++; + myHistogram[ localKeys[1] ]++; + myHistogram[ localKeys[2] ]++; + myHistogram[ localKeys[3] ]++; + } + + { // move to shared + for(int i=0; i 80*16 ) +[numthreads(WG_SIZE, 1, 1)] +void PrefixScanKernel( DEFAULT_ARGS ) +{ + u32 lIdx = GET_LOCAL_IDX; + u32 wgIdx = GET_GROUP_IDX; + + uint data[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; + for(int i=0; i<12; i++) + { + if( int(12*lIdx+i) < NUM_BUCKET*m_nWorkGroupsToExecute ) + data[i] = wHistogram1[12*lIdx+i]; + } + + uint4 myData = uint4(0,0,0,0); + myData.x = data[0] + data[1]; + myData.y = data[2] + data[3]; + myData.z = data[4] + data[5]; + myData.w = data[6] + data[7]; + + + uint totalSum; + uint4 scanned = localPrefixSum128V( myData, lIdx, totalSum ); + + data[11] = scanned.w + data[9] + data[10]; + data[10] = scanned.w + data[9]; + data[9] = scanned.w; + data[8] = scanned.z + data[6] + data[7]; + data[7] = scanned.z + data[6]; + data[6] = scanned.z; + data[5] = scanned.y + data[3] + data[4]; + data[4] = scanned.y + data[3]; + data[3] = scanned.y; + data[2] = scanned.x + data[0] + data[1]; + data[1] = scanned.x + data[0]; + data[0] = scanned.x; + + for(int i=0; i<12; i++) + { + wHistogram1[12*lIdx+i] = data[i]; + } +} +/* +[numthreads(WG_SIZE, 1, 1)] +void PrefixScanKernel( DEFAULT_ARGS ) +{ + u32 lIdx = GET_LOCAL_IDX; + u32 wgIdx = GET_GROUP_IDX; + + uint data[8] = {0,0,0,0,0,0,0,0}; + for(int i=0; i<8; i++) + { + if( int(8*lIdx+i) < NUM_BUCKET*m_nWorkGroupsToExecute ) + data[i] = wHistogram1[8*lIdx+i]; + } + + uint4 myData = uint4(0,0,0,0); + myData.x = data[0] + data[1]; + myData.y = data[2] + data[3]; + myData.z = data[4] + data[5]; + myData.w = data[6] + data[7]; + + + uint totalSum; + uint4 scanned = localPrefixSum128V( myData, lIdx, totalSum ); + + data[7] = scanned.w + data[6]; + data[6] = scanned.w;// + data[5]; + data[5] = scanned.z + data[4]; + data[4] = scanned.z;// + data[3]; + data[3] = scanned.y + data[2]; + data[2] = scanned.y;// + data[1]; + data[1] = scanned.x + data[0]; + data[0] = scanned.x; + + for(int i=0; i<8; i++) + { + wHistogram1[8*lIdx+i] = data[i]; + } +} +*/ + + +[numthreads(WG_SIZE, 1, 1)] +void CopyKernel( DEFAULT_ARGS ) +{ + u32 lIdx = GET_LOCAL_IDX; + u32 wgIdx = GET_GROUP_IDX; + + for(uint igroup=wgIdx.x*m_nBlocksPerGroup; igroup rHistogram : register(t0);\n" +"\n" +"RWStructuredBuffer dataToSort : register( u0 );\n" +"RWStructuredBuffer dataToSortOut : register( u1 );\n" +"\n" +"\n" +"\n" +"#define WG_SIZE 128\n" +"#define ELEMENTS_PER_WORK_ITEM 4\n" +"#define BITS_PER_PASS 4\n" +"#define NUM_BUCKET (1<> targetKey;\n" +" key.y = (data.y & mask) >> targetKey;\n" +" key.z = (data.z & mask) >> targetKey;\n" +" key.w = (data.w & mask) >> targetKey;\n" +" return key;\n" +"}\n" +"\n" +"uint packKeys(uint lower, uint upper)\n" +"{\n" +" return lower|(upper<<16);\n" +"}\n" +"\n" +"uint4 packKeys(uint4 lower, uint4 upper)\n" +"{\n" +" return uint4( lower.x|(upper.x<<16), lower.y|(upper.y<<16), lower.z|(upper.z<<16), lower.w|(upper.w<<16) );\n" +"}\n" +"\n" +"uint extractLower( uint data )\n" +"{\n" +" return data&0xffff;\n" +"}\n" +"\n" +"uint extractUpper( uint data )\n" +"{\n" +" return (data>>16)&0xffff;\n" +"}\n" +"\n" +"uint4 extractLower( uint4 data )\n" +"{\n" +" return uint4( data.x&0xffff, data.y&0xffff, data.z&0xffff, data.w&0xffff );\n" +"}\n" +"\n" +"uint4 extractUpper( uint4 data )\n" +"{\n" +" return uint4( (data.x>>16)&0xffff, (data.y>>16)&0xffff, (data.z>>16)&0xffff, (data.w>>16)&0xffff );\n" +"}\n" +"\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void SortAndScatterKernel( DEFAULT_ARGS ) \n" +"{\n" +" u32 lIdx = GET_LOCAL_IDX;\n" +" u32 wgIdx = GET_GROUP_IDX;\n" +"\n" +" if( lIdx < (NUM_BUCKET) )\n" +" {\n" +" localHistogramToCarry[lIdx] = rHistogram[lIdx*m_nWorkGroupsToExecute + wgIdx];\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" for(uint igroup=wgIdx*m_nBlocksPerGroup; igroup>m_startBit) & 0xf, (myData[1].key>>m_startBit) & 0xf, (myData[2].key>>m_startBit) & 0xf, (myData[3].key>>m_startBit) & 0xf);\n" +" for(uint targetKey=0; targetKey<(NUM_BUCKET); targetKey+=4)\n" +" {\n" +" uint4 key[4];\n" +" uint keySet[2];\n" +" { // pack 4\n" +" uint4 scannedKey[4];\n" +" key[0] = scannedKey[0] = extractKeys( b, targetKey+0 );\n" +" key[1] = scannedKey[1] = extractKeys( b, targetKey+1 );\n" +" key[2] = scannedKey[2] = extractKeys( b, targetKey+2 );\n" +" key[3] = scannedKey[3] = extractKeys( b, targetKey+3 );\n" +" {\n" +" uint s[4];\n" +" s[0] = prefixScanVectorEx( scannedKey[0] );\n" +" s[1] = prefixScanVectorEx( scannedKey[1] );\n" +" s[2] = prefixScanVectorEx( scannedKey[2] );\n" +" s[3] = prefixScanVectorEx( scannedKey[3] );\n" +" keySet[0] = packKeys( s[0], s[1] );\n" +" keySet[1] = packKeys( s[2], s[3] );\n" +" }\n" +" }\n" +"\n" +" uint dstAddressBase[4];\n" +" {\n" +"\n" +" uint totalSumPacked[2];\n" +" uint dstAddressPacked[2];\n" +"\n" +" localPrefixScan128Dual( keySet[0], keySet[1], lIdx, dstAddressPacked[0], dstAddressPacked[1], totalSumPacked[0], totalSumPacked[1] );\n" +"\n" +" dstAddressBase[0] = extractLower( dstAddressPacked[0] );\n" +" dstAddressBase[1] = extractUpper( dstAddressPacked[0] );\n" +" dstAddressBase[2] = extractLower( dstAddressPacked[1] );\n" +" dstAddressBase[3] = extractUpper( dstAddressPacked[1] );\n" +"\n" +" uint4 histogram;\n" +" histogram.x = extractLower(totalSumPacked[0]);\n" +" histogram.y = extractUpper(totalSumPacked[0]);\n" +" histogram.z = extractLower(totalSumPacked[1]);\n" +" histogram.w = extractUpper(totalSumPacked[1]);\n" +"\n" +" if( lIdx == targetKey + 0 ) myHistogram = histogram.x;\n" +" else if( lIdx == targetKey + 1 ) myHistogram = histogram.y;\n" +" else if( lIdx == targetKey + 2 ) myHistogram = histogram.z;\n" +" else if( lIdx == targetKey + 3 ) myHistogram = histogram.w;\n" +" \n" +" uint histogramSum = prefixScanVectorEx( histogram );\n" +"\n" +" if( lIdx == targetKey + 0 ) localPrefixSum[targetKey+0] = localOffset+histogram.x;\n" +" else if( lIdx == targetKey + 1 ) localPrefixSum[targetKey+1] = localOffset+histogram.y;\n" +" else if( lIdx == targetKey + 2 ) localPrefixSum[targetKey+2] = localOffset+histogram.z;\n" +" else if( lIdx == targetKey + 3 ) localPrefixSum[targetKey+3] = localOffset+histogram.w;\n" +"\n" +" localOffset += histogramSum;\n" +" }\n" +" \n" +" GROUP_LDS_BARRIER;\n" +"\n" +"\n" +" for(int ie=0; ie<4; ie++)\n" +" {\n" +" uint4 scannedKey = key[ie];\n" +" prefixScanVectorEx( scannedKey );\n" +"\n" +" uint offset = localPrefixSum[targetKey + ie] + dstAddressBase[ie];\n" +" uint4 dstAddress = uint4( offset, offset, offset, offset ) + scannedKey;\n" +"\n" +" newOffset[0] += dstAddress.x*key[ie].x;\n" +" newOffset[1] += dstAddress.y*key[ie].y;\n" +" newOffset[2] += dstAddress.z*key[ie].z;\n" +" newOffset[3] += dstAddress.w*key[ie].w;\n" +" }\n" +" }\n" +"\n" +" { // local scatter\n" +" SET_LOCAL_SORT_DATA(newOffset[0], myData[0]);\n" +" SET_LOCAL_SORT_DATA(newOffset[1], myData[1]);\n" +" SET_LOCAL_SORT_DATA(newOffset[2], myData[2]);\n" +" SET_LOCAL_SORT_DATA(newOffset[3], myData[3]);\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" { // write data\n" +" for(int i=0; i> m_startBit) & 0xf;\n" +" int groupOffset = localHistogramToCarry[binIdx];\n" +" int myIdx = dataIdx - localPrefixSum[binIdx];\n" +"\n" +" dataToSortOut[ groupOffset + myIdx ] = localData;\n" +" }\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" localHistogramToCarry[lIdx] += myHistogram;\n" +" }\n" +" GROUP_LDS_BARRIER;\n" +" }\n" +"}\n" +"\n" +"\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void SortAndScatterKernel1( DEFAULT_ARGS )\n" +"{\n" +" u32 lIdx = GET_LOCAL_IDX;\n" +" u32 wgIdx = GET_GROUP_IDX;\n" +"\n" +" if( lIdx < (NUM_BUCKET) )\n" +" {\n" +" localHistogramToCarry[lIdx] = rHistogram[lIdx*m_nWorkGroupsToExecute + wgIdx.x];\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" for(uint igroup=wgIdx.x*m_nBlocksPerGroup; igroup>ib) & 0x1, ~(myData[1].key>>ib) & 0x1, ~(myData[2].key>>ib) & 0x1, ~(myData[3].key>>ib) & 0x1);\n" +" uint total;\n" +" uint4 rankOfP = localPrefixSum128V( keys, lIdx, total );\n" +" uint4 rankOfN = uint4(startAddrBlock, startAddrBlock+1, startAddrBlock+2, startAddrBlock+3) - rankOfP + uint4( total, total, total, total );\n" +"\n" +" uint4 myAddr = (keys==uint4(1,1,1,1))? rankOfP: rankOfN;\n" +" \n" +" GROUP_LDS_BARRIER;\n" +"\n" +" SET_LOCAL_SORT_DATA( myAddr.x, myData[0] );\n" +" SET_LOCAL_SORT_DATA( myAddr.y, myData[1] );\n" +" SET_LOCAL_SORT_DATA( myAddr.z, myData[2] );\n" +" SET_LOCAL_SORT_DATA( myAddr.w, myData[3] );\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" \n" +" GET_LOCAL_SORT_DATA( startAddrBlock+0, myData[0] );\n" +" GET_LOCAL_SORT_DATA( startAddrBlock+1, myData[1] );\n" +" GET_LOCAL_SORT_DATA( startAddrBlock+2, myData[2] );\n" +" GET_LOCAL_SORT_DATA( startAddrBlock+3, myData[3] );\n" +" }\n" +"\n" +" {// create histogram -> prefix sum\n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" localHistogram[lIdx] = 0;\n" +" localHistogram[NUM_BUCKET+lIdx] = 0;\n" +" }\n" +" GROUP_LDS_BARRIER;\n" +" uint4 keys = uint4((myData[0].key>>m_startBit) & 0xf, (myData[1].key>>m_startBit) & 0xf, (myData[2].key>>m_startBit) & 0xf, (myData[3].key>>m_startBit) & 0xf);\n" +" \n" +" InterlockedAdd( localHistogram[NUM_BUCKET+keys.x], 1 );\n" +" InterlockedAdd( localHistogram[NUM_BUCKET+keys.y], 1 );\n" +" InterlockedAdd( localHistogram[NUM_BUCKET+keys.z], 1 );\n" +" InterlockedAdd( localHistogram[NUM_BUCKET+keys.w], 1 );\n" +" \n" +" GROUP_LDS_BARRIER;\n" +" \n" +" uint hIdx = NUM_BUCKET+lIdx;\n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" myHistogram = localHistogram[hIdx];\n" +" }\n" +" GROUP_LDS_BARRIER;\n" +" \n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" localHistogram[hIdx] = localHistogram[hIdx-1];\n" +"\n" +" localHistogram[hIdx] += localHistogram[hIdx-1];\n" +" localHistogram[hIdx] += localHistogram[hIdx-2];\n" +" localHistogram[hIdx] += localHistogram[hIdx-4];\n" +" localHistogram[hIdx] += localHistogram[hIdx-8];\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" }\n" +"/*\n" +" {// write back\n" +" int numLocalElements = WG_SIZE*ELEMENTS_PER_WORK_ITEM;\n" +" startAddrBlock = lIdx*4;\n" +" uint startAddress = igroup*numLocalElements + startAddrBlock;\n" +"\n" +" for(int ie=0; ie>m_startBit)&0xf;\n" +" int groupOffset = localHistogramToCarry[binIdx];\n" +" int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];\n" +" dataToSortOut[ groupOffset + myIdx ] = myData[ie];\n" +" }\n" +" }\n" +" \n" +" GROUP_LDS_BARRIER;\n" +" if( lIdx < NUM_BUCKET )\n" +" {\n" +" localHistogramToCarry[lIdx] += myHistogram;\n" +" }\n" +" GROUP_LDS_BARRIER;\n" +" \n" +" }\n" +"}\n" +"\n" +"/*\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void SortAndScatterKernel1( uint3 gIdx : SV_GroupID, uint3 lIdx : SV_GroupThreadID )\n" +"{\n" +" if( lIdx.x < (NUM_BUCKET) )\n" +" {\n" +" localHistogramToCarry[lIdx.x] = rHistogram[lIdx.x*m_nWorkGroupsToExecute + gIdx.x];\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" for(uint igroup=gIdx.x*m_nBlocksPerGroup; igroup>ib) & 0x1, ~(myData[1].key>>ib) & 0x1, ~(myData[2].key>>ib) & 0x1, ~(myData[3].key>>ib) & 0x1);\n" +" uint total;\n" +" uint4 rankOfP = localPrefixSum128V( keys, lIdx.x, total );\n" +" uint4 rankOfN = uint4(startAddrBlock, startAddrBlock+1, startAddrBlock+2, startAddrBlock+3) - rankOfP + uint4( total, total, total, total );\n" +"\n" +" uint4 myAddr = (keys==uint4(1,1,1,1))? rankOfP: rankOfN;\n" +" \n" +" GROUP_LDS_BARRIER;\n" +"\n" +" SET_LOCAL_SORT_DATA( myAddr.x, myData[0] );\n" +" SET_LOCAL_SORT_DATA( myAddr.y, myData[1] );\n" +" SET_LOCAL_SORT_DATA( myAddr.z, myData[2] );\n" +" SET_LOCAL_SORT_DATA( myAddr.w, myData[3] );\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" \n" +" GET_LOCAL_SORT_DATA( startAddrBlock+0, myData[0] );\n" +" GET_LOCAL_SORT_DATA( startAddrBlock+1, myData[1] );\n" +" GET_LOCAL_SORT_DATA( startAddrBlock+2, myData[2] );\n" +" GET_LOCAL_SORT_DATA( startAddrBlock+3, myData[3] );\n" +" }\n" +" \n" +" {// create histogram -> prefix sum\n" +" if( lIdx.x < NUM_BUCKET )\n" +" {\n" +" localHistogram[lIdx.x] = 0;\n" +" localHistogram[NUM_BUCKET+lIdx.x] = 0;\n" +" }\n" +" GROUP_LDS_BARRIER;\n" +" uint4 keys = uint4((myData[0].key>>m_startBit) & 0xf, (myData[1].key>>m_startBit) & 0xf, (myData[2].key>>m_startBit) & 0xf, (myData[3].key>>m_startBit) & 0xf);\n" +" \n" +" InterlockedAdd( localHistogram[NUM_BUCKET+keys.x], 1 );\n" +" InterlockedAdd( localHistogram[NUM_BUCKET+keys.y], 1 );\n" +" InterlockedAdd( localHistogram[NUM_BUCKET+keys.z], 1 );\n" +" InterlockedAdd( localHistogram[NUM_BUCKET+keys.w], 1 );\n" +" \n" +" GROUP_LDS_BARRIER;\n" +" \n" +" uint hIdx = NUM_BUCKET+lIdx.x;\n" +" if( lIdx.x < NUM_BUCKET )\n" +" {\n" +" myHistogram = localHistogram[hIdx];\n" +" }\n" +" GROUP_LDS_BARRIER;\n" +" \n" +"\n" +" if( lIdx.x < NUM_BUCKET )\n" +" {\n" +" localHistogram[hIdx] = localHistogram[hIdx-1];\n" +"\n" +" localHistogram[hIdx] += localHistogram[hIdx-1];\n" +" localHistogram[hIdx] += localHistogram[hIdx-2];\n" +" localHistogram[hIdx] += localHistogram[hIdx-4];\n" +" localHistogram[hIdx] += localHistogram[hIdx-8];\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" }\n" +" {// write back\n" +" for(int ie=0; ie>m_startBit)&0xf;\n" +" int groupOffset = localHistogramToCarry[binIdx];\n" +" int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];\n" +" \n" +" dataToSortOut[ groupOffset + myIdx ] = myData[ie];\n" +" }\n" +" }\n" +" \n" +" GROUP_LDS_BARRIER;\n" +" if( lIdx.x < NUM_BUCKET )\n" +" {\n" +" localHistogramToCarry[lIdx.x] += myHistogram;\n" +" }\n" +" GROUP_LDS_BARRIER;\n" +" \n" +" }\n" +"}\n" +"*/\n" +"\n" +"StructuredBuffer dataToSort1 : register( t0 );\n" +"RWStructuredBuffer wHistogram1 : register(u0);\n" +"\n" +"#define MY_HISTOGRAM(idx) localHistogramMat[(idx)*WG_SIZE+lIdx.x]\n" +"\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void StreamCountKernel( DEFAULT_ARGS ) \n" +"{\n" +" u32 lIdx = GET_LOCAL_IDX;\n" +" u32 wgIdx = GET_GROUP_IDX;\n" +"\n" +" int myHistogram[NUM_BUCKET];\n" +"\n" +" for(int i=0; i> m_startBit) & 0xf;\n" +" localKeys[1] = (localData1.key >> m_startBit) & 0xf;\n" +" localKeys[2] = (localData2.key >> m_startBit) & 0xf;\n" +" localKeys[3] = (localData3.key >> m_startBit) & 0xf;\n" +" }\n" +"\n" +" MY_HISTOGRAM( localKeys[0] )++;\n" +" MY_HISTOGRAM( localKeys[1] )++;\n" +" MY_HISTOGRAM( localKeys[2] )++;\n" +" MY_HISTOGRAM( localKeys[3] )++;\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" { // reduce to 1\n" +" if( lIdx < 64 )//WG_SIZE/2 )\n" +" {\n" +" for(int i=0; i> m_startBit) & 0xf;\n" +" localKeys[1] = (localData1.key >> m_startBit) & 0xf;\n" +" localKeys[2] = (localData2.key >> m_startBit) & 0xf;\n" +" localKeys[3] = (localData3.key >> m_startBit) & 0xf;\n" +" }\n" +"\n" +" myHistogram[ localKeys[0] ]++;\n" +" myHistogram[ localKeys[1] ]++;\n" +" myHistogram[ localKeys[2] ]++;\n" +" myHistogram[ localKeys[3] ]++;\n" +" }\n" +"\n" +" { // move to shared\n" +" for(int i=0; i 80*16 )\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void PrefixScanKernel( DEFAULT_ARGS )\n" +"{\n" +" u32 lIdx = GET_LOCAL_IDX;\n" +" u32 wgIdx = GET_GROUP_IDX;\n" +"\n" +" uint data[12] = {0,0,0,0,0,0,0,0,0,0,0,0};\n" +" for(int i=0; i<12; i++)\n" +" {\n" +" if( int(12*lIdx+i) < NUM_BUCKET*m_nWorkGroupsToExecute )\n" +" data[i] = wHistogram1[12*lIdx+i];\n" +" }\n" +"\n" +" uint4 myData = uint4(0,0,0,0);\n" +" myData.x = data[0] + data[1];\n" +" myData.y = data[2] + data[3];\n" +" myData.z = data[4] + data[5];\n" +" myData.w = data[6] + data[7];\n" +"\n" +"\n" +" uint totalSum;\n" +" uint4 scanned = localPrefixSum128V( myData, lIdx, totalSum );\n" +"\n" +" data[11] = scanned.w + data[9] + data[10];\n" +" data[10] = scanned.w + data[9];\n" +" data[9] = scanned.w;\n" +" data[8] = scanned.z + data[6] + data[7];\n" +" data[7] = scanned.z + data[6];\n" +" data[6] = scanned.z;\n" +" data[5] = scanned.y + data[3] + data[4];\n" +" data[4] = scanned.y + data[3];\n" +" data[3] = scanned.y;\n" +" data[2] = scanned.x + data[0] + data[1];\n" +" data[1] = scanned.x + data[0];\n" +" data[0] = scanned.x;\n" +"\n" +" for(int i=0; i<12; i++)\n" +" {\n" +" wHistogram1[12*lIdx+i] = data[i];\n" +" }\n" +"}\n" +"/*\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void PrefixScanKernel( DEFAULT_ARGS )\n" +"{\n" +" u32 lIdx = GET_LOCAL_IDX;\n" +" u32 wgIdx = GET_GROUP_IDX;\n" +"\n" +" uint data[8] = {0,0,0,0,0,0,0,0};\n" +" for(int i=0; i<8; i++)\n" +" {\n" +" if( int(8*lIdx+i) < NUM_BUCKET*m_nWorkGroupsToExecute )\n" +" data[i] = wHistogram1[8*lIdx+i];\n" +" }\n" +"\n" +" uint4 myData = uint4(0,0,0,0);\n" +" myData.x = data[0] + data[1];\n" +" myData.y = data[2] + data[3];\n" +" myData.z = data[4] + data[5];\n" +" myData.w = data[6] + data[7];\n" +"\n" +"\n" +" uint totalSum;\n" +" uint4 scanned = localPrefixSum128V( myData, lIdx, totalSum );\n" +"\n" +" data[7] = scanned.w + data[6];\n" +" data[6] = scanned.w;// + data[5];\n" +" data[5] = scanned.z + data[4];\n" +" data[4] = scanned.z;// + data[3];\n" +" data[3] = scanned.y + data[2];\n" +" data[2] = scanned.y;// + data[1];\n" +" data[1] = scanned.x + data[0];\n" +" data[0] = scanned.x;\n" +"\n" +" for(int i=0; i<8; i++)\n" +" {\n" +" wHistogram1[8*lIdx+i] = data[i];\n" +" }\n" +"}\n" +"*/\n" +"\n" +"\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void CopyKernel( DEFAULT_ARGS )\n" +"{\n" +" u32 lIdx = GET_LOCAL_IDX;\n" +" u32 wgIdx = GET_GROUP_IDX;\n" +"\n" +" for(uint igroup=wgIdx.x*m_nBlocksPerGroup; igroup +class RadixSort : public RadixSortBase +{ + public: + struct Data + { + HostBuffer* m_workBuffer; + }; + + enum + { + BITS_PER_PASS = 8, + NUM_TABLES = (1<m_type == TYPE_HOST ); + + Data* data = new Data; + data->m_workBuffer = new HostBuffer( deviceData, maxSize ); + return data; + } + + static + void deallocate(Data* data) + { + delete data->m_workBuffer; + delete data; + } + + static + void execute(Data* data, Buffer& inout, int n, int sortBits = 32) + { + ADLASSERT( inout.getType() == TYPE_HOST ); + + int tables[NUM_TABLES]; + int counter[NUM_TABLES]; + + SortData* src = inout.m_ptr; + SortData* dst = data->m_workBuffer->m_ptr; + + int count=0; + for(int startBit=0; startBit> startBit) & (NUM_TABLES-1); + tables[tableIdx]++; + } + + // prefix scan + int sum = 0; + for(int i=0; i> startBit) & (NUM_TABLES-1); + + dst[tables[tableIdx] + counter[tableIdx]] = src[i]; + counter[tableIdx] ++; + } + + swap2( src, dst ); + count++; + } + + { + if (count&1) + //if( src != inout.m_ptr ) + { + memcpy( dst, src, sizeof(SortData)*n ); + } + } + } +}; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortSimpleCL.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortSimpleCL.h new file mode 100644 index 0000000..8325529 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortSimpleCL.h @@ -0,0 +1,134 @@ +static const char* radixSortSimpleKernelsCL = \ + "#pragma OPENCL EXTENSION cl_amd_printf : enable\n" + "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n" + "\n" + "typedef unsigned int u32;\n" + "#define GET_GROUP_IDX get_group_id(0)\n" + "#define GET_LOCAL_IDX get_local_id(0)\n" + "#define GET_GLOBAL_IDX get_global_id(0)\n" + "#define GET_GROUP_SIZE get_local_size(0)\n" + "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n" + "#define AtomInc(x) atom_inc(&(x))\n" + "#define AtomInc1(x, out) out = atom_inc(&(x))\n" + "\n" + "\n" + "#define WG_SIZE 128\n" + "#define NUM_PER_WI 4\n" + "\n" + "\n" + "typedef struct\n" + "{\n" + " u32 m_key;\n" + " u32 m_value;\n" + "}SortData;\n" + "\n" + "\n" + "typedef struct\n" + "{\n" + " u32 m_startBit;\n" + " u32 m_numGroups;\n" + " u32 m_padding[2];\n" + "} ConstBuffer;\n" + "\n" + "\n" + "__kernel\n" + "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n" + "void LocalCountKernel(__global SortData* sortData,\n" + " __global u32* ldsHistogramOut,\n" + " ConstBuffer cb)\n" + "{\n" + " __local u32 ldsHistogram[16][256];\n" + "\n" + " int lIdx = GET_LOCAL_IDX;\n" + " int gIdx = GET_GLOBAL_IDX;\n" + "\n" + " for(int i=0; i<16; i++)\n" + " {\n" + " ldsHistogram[i][lIdx] = 0.f;\n" + " ldsHistogram[i][lIdx+128] = 0.f;\n" + " }\n" + "\n" + " GROUP_LDS_BARRIER;\n" + "\n" + " SortData datas[NUM_PER_WI];\n" + " datas[0] = sortData[gIdx*NUM_PER_WI+0];\n" + " datas[1] = sortData[gIdx*NUM_PER_WI+1];\n" + " datas[2] = sortData[gIdx*NUM_PER_WI+2];\n" + " datas[3] = sortData[gIdx*NUM_PER_WI+3];\n" + "\n" + " datas[0].m_key = (datas[0].m_key >> cb.m_startBit) & 0xff;\n" + " datas[1].m_key = (datas[1].m_key >> cb.m_startBit) & 0xff;\n" + " datas[2].m_key = (datas[2].m_key >> cb.m_startBit) & 0xff;\n" + " datas[3].m_key = (datas[3].m_key >> cb.m_startBit) & 0xff;\n" + "\n" + " int tableIdx = lIdx%16;\n" + "\n" + " AtomInc(ldsHistogram[tableIdx][datas[0].m_key]);\n" + " AtomInc(ldsHistogram[tableIdx][datas[1].m_key]);\n" + " AtomInc(ldsHistogram[tableIdx][datas[2].m_key]);\n" + " AtomInc(ldsHistogram[tableIdx][datas[3].m_key]);\n" + "\n" + " GROUP_LDS_BARRIER;\n" + "\n" + " u32 sum0, sum1;\n" + " sum0 = sum1 = 0;\n" + " for(int i=0; i<16; i++)\n" + " {\n" + " sum0 += ldsHistogram[i][lIdx];\n" + " sum1 += ldsHistogram[i][lIdx+128];\n" + " }\n" + "\n" + " ldsHistogramOut[lIdx*cb.m_numGroups+GET_GROUP_IDX] = sum0;\n" + " ldsHistogramOut[(lIdx+128)*cb.m_numGroups+GET_GROUP_IDX] = sum1;\n" + "}\n" + "\n" + "__kernel\n" + "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n" + "void ScatterKernel(__global SortData* sortData,\n" + " __global SortData* sortDataOut,\n" + " __global u32* scannedHistogram,\n" + " ConstBuffer cb)\n" + "{\n" + " __local u32 ldsCurrentLocation[256];\n" + "\n" + " int lIdx = GET_LOCAL_IDX;\n" + " int gIdx = GET_GLOBAL_IDX;\n" + "\n" + " {\n" + " ldsCurrentLocation[lIdx] = scannedHistogram[lIdx*cb.m_numGroups+GET_GROUP_IDX];\n" + " ldsCurrentLocation[lIdx+128] = scannedHistogram[(lIdx+128)*cb.m_numGroups+GET_GROUP_IDX];\n" + " }\n" + "\n" + " GROUP_LDS_BARRIER;\n" + "\n" + " SortData datas[NUM_PER_WI];\n" + " int keys[NUM_PER_WI];\n" + " datas[0] = sortData[gIdx*NUM_PER_WI+0];\n" + " datas[1] = sortData[gIdx*NUM_PER_WI+1];\n" + " datas[2] = sortData[gIdx*NUM_PER_WI+2];\n" + " datas[3] = sortData[gIdx*NUM_PER_WI+3];\n" + "\n" + " keys[0] = (datas[0].m_key >> cb.m_startBit) & 0xff;\n" + " keys[1] = (datas[1].m_key >> cb.m_startBit) & 0xff;\n" + " keys[2] = (datas[2].m_key >> cb.m_startBit) & 0xff;\n" + " keys[3] = (datas[3].m_key >> cb.m_startBit) & 0xff;\n" + "\n" + " int dst[NUM_PER_WI];\n" + " for(int i=0; i sortData : register( t0 );\n" + "RWStructuredBuffer ldsHistogramOut : register( u0 );\n" + "\n" + "groupshared u32 ldsHistogram[16][256];\n" + "\n" + "[numthreads(WG_SIZE, 1, 1)]\n" + "void LocalCountKernel( DEFAULT_ARGS )\n" + "{\n" + " int lIdx = GET_LOCAL_IDX;\n" + " int gIdx = GET_GLOBAL_IDX;\n" + "\n" + " for(int i=0; i<16; i++)\n" + " {\n" + " ldsHistogram[i][lIdx] = 0.f;\n" + " ldsHistogram[i][lIdx+128] = 0.f;\n" + " }\n" + "\n" + " GROUP_LDS_BARRIER;\n" + "\n" + " SortData datas[NUM_PER_WI];\n" + " datas[0] = sortData[gIdx*NUM_PER_WI+0];\n" + " datas[1] = sortData[gIdx*NUM_PER_WI+1];\n" + " datas[2] = sortData[gIdx*NUM_PER_WI+2];\n" + " datas[3] = sortData[gIdx*NUM_PER_WI+3];\n" + "\n" + " datas[0].m_key = (datas[0].m_key >> m_startBit) & 0xff;\n" + " datas[1].m_key = (datas[1].m_key >> m_startBit) & 0xff;\n" + " datas[2].m_key = (datas[2].m_key >> m_startBit) & 0xff;\n" + " datas[3].m_key = (datas[3].m_key >> m_startBit) & 0xff;\n" + "\n" + " int tableIdx = lIdx%16;\n" + "\n" + " AtomInc(ldsHistogram[tableIdx][datas[0].m_key]);\n" + " AtomInc(ldsHistogram[tableIdx][datas[1].m_key]);\n" + " AtomInc(ldsHistogram[tableIdx][datas[2].m_key]);\n" + " AtomInc(ldsHistogram[tableIdx][datas[3].m_key]);\n" + "\n" + " GROUP_LDS_BARRIER;\n" + "\n" + " u32 sum0, sum1;\n" + " sum0 = sum1 = 0;\n" + " for(int i=0; i<16; i++)\n" + " {\n" + " sum0 += ldsHistogram[i][lIdx];\n" + " sum1 += ldsHistogram[i][lIdx+128];\n" + " }\n" + "\n" + " ldsHistogramOut[lIdx*m_numGroups+GET_GROUP_IDX] = sum0;\n" + " ldsHistogramOut[(lIdx+128)*m_numGroups+GET_GROUP_IDX] = sum1;\n" + "}\n" + "\n" + "\n" + "RWStructuredBuffer sortDataOut : register( u0 );\n" + "RWStructuredBuffer scannedHistogram : register( u1 );\n" + "\n" + "groupshared u32 ldsCurrentLocation[256];\n" + "\n" + "[numthreads(WG_SIZE, 1, 1)]\n" + "void ScatterKernel( DEFAULT_ARGS )\n" + "{\n" + " int lIdx = GET_LOCAL_IDX;\n" + " int gIdx = GET_GLOBAL_IDX;\n" + "\n" + " {\n" + " ldsCurrentLocation[lIdx] = scannedHistogram[lIdx*m_numGroups+GET_GROUP_IDX];\n" + " ldsCurrentLocation[lIdx+128] = scannedHistogram[(lIdx+128)*m_numGroups+GET_GROUP_IDX];\n" + " }\n" + "\n" + " GROUP_LDS_BARRIER;\n" + "\n" + " SortData datas[NUM_PER_WI];\n" + " int keys[NUM_PER_WI];\n" + " datas[0] = sortData[gIdx*NUM_PER_WI+0];\n" + " datas[1] = sortData[gIdx*NUM_PER_WI+1];\n" + " datas[2] = sortData[gIdx*NUM_PER_WI+2];\n" + " datas[3] = sortData[gIdx*NUM_PER_WI+3];\n" + "\n" + " keys[0] = (datas[0].m_key >> m_startBit) & 0xff;\n" + " keys[1] = (datas[1].m_key >> m_startBit) & 0xff;\n" + " keys[2] = (datas[2].m_key >> m_startBit) & 0xff;\n" + " keys[3] = (datas[3].m_key >> m_startBit) & 0xff;\n" + "\n" + " int dst[NUM_PER_WI];\n" + " for(int i=0; i> cb.m_startBit) & 0xff; + datas[1].m_key = (datas[1].m_key >> cb.m_startBit) & 0xff; + datas[2].m_key = (datas[2].m_key >> cb.m_startBit) & 0xff; + datas[3].m_key = (datas[3].m_key >> cb.m_startBit) & 0xff; + + int tableIdx = lIdx%16; + + AtomInc(ldsHistogram[tableIdx][datas[0].m_key]); + AtomInc(ldsHistogram[tableIdx][datas[1].m_key]); + AtomInc(ldsHistogram[tableIdx][datas[2].m_key]); + AtomInc(ldsHistogram[tableIdx][datas[3].m_key]); + + GROUP_LDS_BARRIER; + + u32 sum0, sum1; + sum0 = sum1 = 0; + for(int i=0; i<16; i++) + { + sum0 += ldsHistogram[i][lIdx]; + sum1 += ldsHistogram[i][lIdx+128]; + } + + ldsHistogramOut[lIdx*cb.m_numGroups+GET_GROUP_IDX] = sum0; + ldsHistogramOut[(lIdx+128)*cb.m_numGroups+GET_GROUP_IDX] = sum1; +} + +__kernel +__attribute__((reqd_work_group_size(WG_SIZE,1,1))) +void ScatterKernel(__global SortData* sortData, + __global SortData* sortDataOut, + __global u32* scannedHistogram, + ConstBuffer cb) +{ + __local u32 ldsCurrentLocation[256]; + + int lIdx = GET_LOCAL_IDX; + int gIdx = GET_GLOBAL_IDX; + + { + ldsCurrentLocation[lIdx] = scannedHistogram[lIdx*cb.m_numGroups+GET_GROUP_IDX]; + ldsCurrentLocation[lIdx+128] = scannedHistogram[(lIdx+128)*cb.m_numGroups+GET_GROUP_IDX]; + } + + GROUP_LDS_BARRIER; + + SortData datas[NUM_PER_WI]; + int keys[NUM_PER_WI]; + datas[0] = sortData[gIdx*NUM_PER_WI+0]; + datas[1] = sortData[gIdx*NUM_PER_WI+1]; + datas[2] = sortData[gIdx*NUM_PER_WI+2]; + datas[3] = sortData[gIdx*NUM_PER_WI+3]; + + keys[0] = (datas[0].m_key >> cb.m_startBit) & 0xff; + keys[1] = (datas[1].m_key >> cb.m_startBit) & 0xff; + keys[2] = (datas[2].m_key >> cb.m_startBit) & 0xff; + keys[3] = (datas[3].m_key >> cb.m_startBit) & 0xff; + + int dst[NUM_PER_WI]; + for(int i=0; i sortData : register( t0 ); +RWStructuredBuffer ldsHistogramOut : register( u0 ); + +groupshared u32 ldsHistogram[16][256]; + +[numthreads(WG_SIZE, 1, 1)] +void LocalCountKernel( DEFAULT_ARGS ) +{ + int lIdx = GET_LOCAL_IDX; + int gIdx = GET_GLOBAL_IDX; + + for(int i=0; i<16; i++) + { + ldsHistogram[i][lIdx] = 0.f; + ldsHistogram[i][lIdx+128] = 0.f; + } + + GROUP_LDS_BARRIER; + + SortData datas[NUM_PER_WI]; + datas[0] = sortData[gIdx*NUM_PER_WI+0]; + datas[1] = sortData[gIdx*NUM_PER_WI+1]; + datas[2] = sortData[gIdx*NUM_PER_WI+2]; + datas[3] = sortData[gIdx*NUM_PER_WI+3]; + + datas[0].m_key = (datas[0].m_key >> m_startBit) & 0xff; + datas[1].m_key = (datas[1].m_key >> m_startBit) & 0xff; + datas[2].m_key = (datas[2].m_key >> m_startBit) & 0xff; + datas[3].m_key = (datas[3].m_key >> m_startBit) & 0xff; + + int tableIdx = lIdx%16; + + AtomInc(ldsHistogram[tableIdx][datas[0].m_key]); + AtomInc(ldsHistogram[tableIdx][datas[1].m_key]); + AtomInc(ldsHistogram[tableIdx][datas[2].m_key]); + AtomInc(ldsHistogram[tableIdx][datas[3].m_key]); + + GROUP_LDS_BARRIER; + + u32 sum0, sum1; + sum0 = sum1 = 0; + for(int i=0; i<16; i++) + { + sum0 += ldsHistogram[i][lIdx]; + sum1 += ldsHistogram[i][lIdx+128]; + } + + ldsHistogramOut[lIdx*m_numGroups+GET_GROUP_IDX] = sum0; + ldsHistogramOut[(lIdx+128)*m_numGroups+GET_GROUP_IDX] = sum1; +} + + +RWStructuredBuffer sortDataOut : register( u0 ); +RWStructuredBuffer scannedHistogram : register( u1 ); + +groupshared u32 ldsCurrentLocation[256]; + +[numthreads(WG_SIZE, 1, 1)] +void ScatterKernel( DEFAULT_ARGS ) +{ + int lIdx = GET_LOCAL_IDX; + int gIdx = GET_GLOBAL_IDX; + + { + ldsCurrentLocation[lIdx] = scannedHistogram[lIdx*m_numGroups+GET_GROUP_IDX]; + ldsCurrentLocation[lIdx+128] = scannedHistogram[(lIdx+128)*m_numGroups+GET_GROUP_IDX]; + } + + GROUP_LDS_BARRIER; + + SortData datas[NUM_PER_WI]; + int keys[NUM_PER_WI]; + datas[0] = sortData[gIdx*NUM_PER_WI+0]; + datas[1] = sortData[gIdx*NUM_PER_WI+1]; + datas[2] = sortData[gIdx*NUM_PER_WI+2]; + datas[3] = sortData[gIdx*NUM_PER_WI+3]; + + keys[0] = (datas[0].m_key >> m_startBit) & 0xff; + keys[1] = (datas[1].m_key >> m_startBit) & 0xff; + keys[2] = (datas[2].m_key >> m_startBit) & 0xff; + keys[3] = (datas[3].m_key >> m_startBit) & 0xff; + + int dst[NUM_PER_WI]; + for(int i=0; i> cb.m_startBit) & 0xff;\n" +" datas[1].m_key = (datas[1].m_key >> cb.m_startBit) & 0xff;\n" +" datas[2].m_key = (datas[2].m_key >> cb.m_startBit) & 0xff;\n" +" datas[3].m_key = (datas[3].m_key >> cb.m_startBit) & 0xff;\n" +"\n" +" int tableIdx = lIdx%16;\n" +" \n" +" AtomInc(ldsHistogram[tableIdx][datas[0].m_key]);\n" +" AtomInc(ldsHistogram[tableIdx][datas[1].m_key]);\n" +" AtomInc(ldsHistogram[tableIdx][datas[2].m_key]);\n" +" AtomInc(ldsHistogram[tableIdx][datas[3].m_key]);\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" \n" +" u32 sum0, sum1;\n" +" sum0 = sum1 = 0;\n" +" for(int i=0; i<16; i++)\n" +" {\n" +" sum0 += ldsHistogram[i][lIdx];\n" +" sum1 += ldsHistogram[i][lIdx+128];\n" +" }\n" +"\n" +" ldsHistogramOut[lIdx*cb.m_numGroups+GET_GROUP_IDX] = sum0;\n" +" ldsHistogramOut[(lIdx+128)*cb.m_numGroups+GET_GROUP_IDX] = sum1;\n" +"}\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n" +"void ScatterKernel(__global SortData* sortData,\n" +" __global SortData* sortDataOut,\n" +" __global u32* scannedHistogram, \n" +" ConstBuffer cb)\n" +"{\n" +" __local u32 ldsCurrentLocation[256];\n" +"\n" +" int lIdx = GET_LOCAL_IDX;\n" +" int gIdx = GET_GLOBAL_IDX;\n" +" \n" +" {\n" +" ldsCurrentLocation[lIdx] = scannedHistogram[lIdx*cb.m_numGroups+GET_GROUP_IDX];\n" +" ldsCurrentLocation[lIdx+128] = scannedHistogram[(lIdx+128)*cb.m_numGroups+GET_GROUP_IDX];\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" \n" +" SortData datas[NUM_PER_WI];\n" +" int keys[NUM_PER_WI];\n" +" datas[0] = sortData[gIdx*NUM_PER_WI+0];\n" +" datas[1] = sortData[gIdx*NUM_PER_WI+1];\n" +" datas[2] = sortData[gIdx*NUM_PER_WI+2];\n" +" datas[3] = sortData[gIdx*NUM_PER_WI+3];\n" +"\n" +" keys[0] = (datas[0].m_key >> cb.m_startBit) & 0xff;\n" +" keys[1] = (datas[1].m_key >> cb.m_startBit) & 0xff;\n" +" keys[2] = (datas[2].m_key >> cb.m_startBit) & 0xff;\n" +" keys[3] = (datas[3].m_key >> cb.m_startBit) & 0xff;\n" +"\n" +" int dst[NUM_PER_WI];\n" +" for(int i=0; i sortData : register( t0 );\n" +"RWStructuredBuffer ldsHistogramOut : register( u0 );\n" +"\n" +"groupshared u32 ldsHistogram[16][256];\n" +"\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void LocalCountKernel( DEFAULT_ARGS )\n" +"{\n" +" int lIdx = GET_LOCAL_IDX;\n" +" int gIdx = GET_GLOBAL_IDX;\n" +" \n" +" for(int i=0; i<16; i++)\n" +" {\n" +" ldsHistogram[i][lIdx] = 0.f;\n" +" ldsHistogram[i][lIdx+128] = 0.f;\n" +" }\n" +" \n" +" GROUP_LDS_BARRIER;\n" +" \n" +" SortData datas[NUM_PER_WI];\n" +" datas[0] = sortData[gIdx*NUM_PER_WI+0];\n" +" datas[1] = sortData[gIdx*NUM_PER_WI+1];\n" +" datas[2] = sortData[gIdx*NUM_PER_WI+2];\n" +" datas[3] = sortData[gIdx*NUM_PER_WI+3];\n" +"\n" +" datas[0].m_key = (datas[0].m_key >> m_startBit) & 0xff;\n" +" datas[1].m_key = (datas[1].m_key >> m_startBit) & 0xff;\n" +" datas[2].m_key = (datas[2].m_key >> m_startBit) & 0xff;\n" +" datas[3].m_key = (datas[3].m_key >> m_startBit) & 0xff;\n" +"\n" +" int tableIdx = lIdx%16;\n" +" \n" +" AtomInc(ldsHistogram[tableIdx][datas[0].m_key]);\n" +" AtomInc(ldsHistogram[tableIdx][datas[1].m_key]);\n" +" AtomInc(ldsHistogram[tableIdx][datas[2].m_key]);\n" +" AtomInc(ldsHistogram[tableIdx][datas[3].m_key]);\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" \n" +" u32 sum0, sum1;\n" +" sum0 = sum1 = 0;\n" +" for(int i=0; i<16; i++)\n" +" {\n" +" sum0 += ldsHistogram[i][lIdx];\n" +" sum1 += ldsHistogram[i][lIdx+128];\n" +" }\n" +"\n" +" ldsHistogramOut[lIdx*m_numGroups+GET_GROUP_IDX] = sum0;\n" +" ldsHistogramOut[(lIdx+128)*m_numGroups+GET_GROUP_IDX] = sum1;\n" +"}\n" +"\n" +"\n" +"RWStructuredBuffer sortDataOut : register( u0 );\n" +"RWStructuredBuffer scannedHistogram : register( u1 );\n" +"\n" +"groupshared u32 ldsCurrentLocation[256];\n" +"\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void ScatterKernel( DEFAULT_ARGS )\n" +"{\n" +" int lIdx = GET_LOCAL_IDX;\n" +" int gIdx = GET_GLOBAL_IDX;\n" +" \n" +" {\n" +" ldsCurrentLocation[lIdx] = scannedHistogram[lIdx*m_numGroups+GET_GROUP_IDX];\n" +" ldsCurrentLocation[lIdx+128] = scannedHistogram[(lIdx+128)*m_numGroups+GET_GROUP_IDX];\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +" \n" +" SortData datas[NUM_PER_WI];\n" +" int keys[NUM_PER_WI];\n" +" datas[0] = sortData[gIdx*NUM_PER_WI+0];\n" +" datas[1] = sortData[gIdx*NUM_PER_WI+1];\n" +" datas[2] = sortData[gIdx*NUM_PER_WI+2];\n" +" datas[3] = sortData[gIdx*NUM_PER_WI+3];\n" +"\n" +" keys[0] = (datas[0].m_key >> m_startBit) & 0xff;\n" +" keys[1] = (datas[1].m_key >> m_startBit) & 0xff;\n" +" keys[2] = (datas[2].m_key >> m_startBit) & 0xff;\n" +" keys[3] = (datas[3].m_key >> m_startBit) & 0xff;\n" +"\n" +" int dst[NUM_PER_WI];\n" +" for(int i=0; i +#include + +template +class RadixSortStandard : public RadixSortBase +{ + public: + typedef Launcher::BufferInfo BufferInfo; + + enum + { + WG_SIZE = 128, + NUM_PER_WI = 4, + + BITS_PER_PASS = 4, + }; + + struct Data : public RadixSort::Data + { + Kernel* m_localSortKernel; + Kernel* m_scatterKernel; + Kernel* m_copyKernel; + + Buffer* m_workBuffer0; + Buffer* m_workBuffer1; + Buffer* m_workBuffer2; + Buffer* m_workBuffer3; + Buffer* m_constBuffer[32/BITS_PER_PASS]; + }; + + + static + Data* allocate(const Device* deviceData, int maxSize, Option option = SORT_NORMAL); + + static + void deallocate(void* data); + + static + void execute(void* data, Buffer& inout, int n, int sortBits); +}; + +template +typename RadixSortStandard::Data* RadixSortStandard::allocate(const Device* deviceData, int maxSize, Option option) +{ + ADLASSERT( type == deviceData->m_type ); + + u32 maxNumGroups = (maxSize+WG_SIZE*NUM_PER_WI-1)/(WG_SIZE*NUM_PER_WI); + + const char* src[] = +#if defined(ADL_LOAD_KERNEL_FROM_STRING) + {radixSortStandardKernelsCL,radixSortStandardKernelsDX11}; +// ADLASSERT(0); +#else + {0,0}; +#endif + + Data* data = new Data; + data->m_option = option; + data->m_deviceData = deviceData; + + data->m_localSortKernel = deviceData->getKernel( PATH, KERNEL0, 0, src[type] ); + data->m_scatterKernel = deviceData->getKernel( PATH, KERNEL1, 0, src[type] ); + data->m_copyKernel = deviceData->getKernel( PATH, KERNEL2, 0, src[type] ); + + // is this correct? + data->m_scanData = PrefixScan::allocate( deviceData, maxNumGroups*(1<m_workBuffer0 = new Buffer( deviceData, maxNumGroups*(1<m_workBuffer1 = new Buffer( deviceData, maxNumGroups*(1<m_workBuffer2 = new Buffer( deviceData, maxNumGroups*(1<m_workBuffer3 = new Buffer( deviceData, maxSize ); + for(int i=0; i<32/BITS_PER_PASS; i++) + data->m_constBuffer[i] = new Buffer( deviceData, 1, BufferBase::BUFFER_CONST ); + data->m_maxSize = maxSize; + + return data; +} + +template +void RadixSortStandard::deallocate(void* rawData) +{ + Data* data = (Data*)rawData; + + delete data->m_workBuffer0; + delete data->m_workBuffer1; + delete data->m_workBuffer2; + delete data->m_workBuffer3; + for(int i=0; i<32/BITS_PER_PASS; i++) + delete data->m_constBuffer[i]; + + PrefixScan::deallocate( data->m_scanData ); + + delete data; +} + +template +void RadixSortStandard::execute(void* rawData, Buffer& inout, int n, int sortBits) +{ + Data* data = (Data*)rawData; + + ADLASSERT( n%512 == 0 ); + ADLASSERT( n <= data->m_maxSize ); + ADLASSERT( NUM_PER_WI == 4 ); + + Buffer* src = BufferUtils::map( data->m_deviceData, &inout ); + Buffer* dst = data->m_workBuffer3; + + const Device* deviceData = data->m_deviceData; + + int numGroups = (n+WG_SIZE*NUM_PER_WI-1)/(WG_SIZE*NUM_PER_WI); + + int4 constBuffer; + + int iPass = 0; + for(int startBit=0; startBitm_workBuffer0 ), BufferInfo( data->m_workBuffer1 ) }; + + Launcher launcher( deviceData, data->m_localSortKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[iPass], constBuffer ); + launcher.launch1D( WG_SIZE*numGroups, WG_SIZE ); + } + + PrefixScan::execute( data->m_scanData, *data->m_workBuffer0, *data->m_workBuffer2, numGroups*(1<m_workBuffer2, true ), BufferInfo( data->m_workBuffer1, true ), + BufferInfo( dst ) }; + + Launcher launcher( deviceData, data->m_scatterKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[iPass], constBuffer ); + launcher.launch1D( WG_SIZE*numGroups, WG_SIZE ); + } + + if(0) + { + BufferInfo bInfo[] = { BufferInfo( dst, true ), BufferInfo( src ) }; + + Launcher launcher( deviceData, data->m_copyKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.launch1D( n, WG_SIZE ); + } + swap2( src, dst ); + } + + if( src != &inout ) + { + BufferInfo bInfo[] = { BufferInfo( src, true ), BufferInfo( dst ) }; + + Launcher launcher( deviceData, data->m_copyKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.launch1D( n, WG_SIZE ); + } + + BufferUtils::unmap( src, &inout ); +} + +#undef PATH +#undef KERNEL0 +#undef KERNEL1 +#undef KERNEL2 diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandardKernels.cl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandardKernels.cl new file mode 100644 index 0000000..c79348d --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandardKernels.cl @@ -0,0 +1,345 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +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. +*/ +//Author Takahiro Harada + + +#pragma OPENCL EXTENSION cl_amd_printf : enable +#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable + +typedef unsigned int u32; +#define GET_GROUP_IDX get_group_id(0) +#define GET_LOCAL_IDX get_local_id(0) +#define GET_GLOBAL_IDX get_global_id(0) +#define GET_GROUP_SIZE get_local_size(0) +#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE) +#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE) +#define AtomInc(x) atom_inc(&(x)) +#define AtomInc1(x, out) out = atom_inc(&(x)) + +#define make_uint4 (uint4) +#define make_uint2 (uint2) + +#define SELECT_UINT4( b, a, condition ) select( b,a,condition ) + +#define WG_SIZE 128 +#define NUM_PER_WI 4 + + +typedef struct +{ + u32 m_key; + u32 m_value; +}SortData; + + +typedef struct +{ + u32 m_startBit; + u32 m_numGroups; + u32 m_padding[2]; +} ConstBuffer; + +#define BITS_PER_PASS 4 + + + +uint4 prefixScanVector( uint4 data ) +{ + data.y += data.x; + data.w += data.z; + data.z += data.y; + data.w += data.y; + return data; +} + +uint prefixScanVectorEx( uint4* data ) +{ + uint4 backup = data[0]; + data[0].y += data[0].x; + data[0].w += data[0].z; + data[0].z += data[0].y; + data[0].w += data[0].y; + uint sum = data[0].w; + *data -= backup; + return sum; +} + +uint4 localPrefixSum128V( uint4 pData, uint lIdx, uint* totalSum, __local u32 sorterSharedMemory[] ) +{ + { // Set data + sorterSharedMemory[lIdx] = 0; + sorterSharedMemory[lIdx+WG_SIZE] = prefixScanVectorEx( &pData ); + } + + GROUP_LDS_BARRIER; + + { // Prefix sum + int idx = 2*lIdx + (WG_SIZE+1); + if( lIdx < 64 ) + { + sorterSharedMemory[idx] += sorterSharedMemory[idx-1]; + GROUP_MEM_FENCE; + sorterSharedMemory[idx] += sorterSharedMemory[idx-2]; + GROUP_MEM_FENCE; + sorterSharedMemory[idx] += sorterSharedMemory[idx-4]; + GROUP_MEM_FENCE; + sorterSharedMemory[idx] += sorterSharedMemory[idx-8]; + GROUP_MEM_FENCE; + sorterSharedMemory[idx] += sorterSharedMemory[idx-16]; + GROUP_MEM_FENCE; + sorterSharedMemory[idx] += sorterSharedMemory[idx-32]; + GROUP_MEM_FENCE; + sorterSharedMemory[idx] += sorterSharedMemory[idx-64]; + GROUP_MEM_FENCE; + + sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2]; + GROUP_MEM_FENCE; + } + } + + GROUP_LDS_BARRIER; + + *totalSum = sorterSharedMemory[WG_SIZE*2-1]; + uint addValue = sorterSharedMemory[lIdx+127]; + return pData + make_uint4(addValue, addValue, addValue, addValue); +} + + +void generateHistogram(u32 lIdx, u32 wgIdx, + uint4 sortedData, + __local u32 *histogram) +{ + if( lIdx < (1<>cb.m_startBit, sortData[1].m_key>>cb.m_startBit, + sortData[2].m_key>>cb.m_startBit, sortData[3].m_key>>cb.m_startBit ); + + generateHistogram( lIdx, wgIdx, localKeys, ldsSortData ); + + GROUP_LDS_BARRIER; + + int nBins = (1<>cb.m_startBit)&cmpValue, (sortData[1].m_key>>cb.m_startBit)&cmpValue, + (sortData[2].m_key>>cb.m_startBit)&cmpValue, (sortData[3].m_key>>cb.m_startBit)&cmpValue );; + + // data is already sorted. So simply subtract local prefix sum + uint4 dstAddr; + dstAddr.x = ldsGlobalHistogram[radix.x] + (localAddr.x - ldsLocalHistogram[radix.x]); + dstAddr.y = ldsGlobalHistogram[radix.y] + (localAddr.y - ldsLocalHistogram[radix.y]); + dstAddr.z = ldsGlobalHistogram[radix.z] + (localAddr.z - ldsLocalHistogram[radix.z]); + dstAddr.w = ldsGlobalHistogram[radix.w] + (localAddr.w - ldsLocalHistogram[radix.w]); + + dst[dstAddr.x] = sortData[0]; + dst[dstAddr.y] = sortData[1]; + dst[dstAddr.z] = sortData[2]; + dst[dstAddr.w] = sortData[3]; +} + +__kernel +__attribute__((reqd_work_group_size(WG_SIZE,1,1))) +void CopyKernel(__global SortData *src, __global SortData *dst) +{ + dst[ GET_GLOBAL_IDX ] = src[ GET_GLOBAL_IDX ]; +} diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandardKernels.hlsl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandardKernels.hlsl new file mode 100644 index 0000000..55a6a1c --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandardKernels.hlsl @@ -0,0 +1,322 @@ +/* + 2011 Takahiro Harada +*/ + +typedef uint u32; + +#define GET_GROUP_IDX groupIdx.x +#define GET_LOCAL_IDX localIdx.x +#define GET_GLOBAL_IDX globalIdx.x +#define GROUP_LDS_BARRIER GroupMemoryBarrierWithGroupSync() +#define GROUP_MEM_FENCE +#define DEFAULT_ARGS uint3 globalIdx : SV_DispatchThreadID, uint3 localIdx : SV_GroupThreadID, uint3 groupIdx : SV_GroupID +#define AtomInc(x) InterlockedAdd(x, 1) +#define AtomInc1(x, out) InterlockedAdd(x, 1, out) + +#define make_uint4 uint4 +#define make_uint2 uint2 + +uint4 SELECT_UINT4(uint4 b,uint4 a,uint4 condition ){ return make_uint4( ((condition).x)?a.x:b.x, ((condition).y)?a.y:b.y, ((condition).z)?a.z:b.z, ((condition).w)?a.w:b.w ); } + +// takahiro end +#define WG_SIZE 128 +#define NUM_PER_WI 4 + +#define GET_GROUP_SIZE WG_SIZE + +typedef struct +{ + u32 m_key; + u32 m_value; +}SortData; + +cbuffer SortCB : register( b0 ) +{ + u32 m_startBit; + u32 m_numGroups; + u32 m_padding[2]; +}; + +#define BITS_PER_PASS 4 + + +uint4 prefixScanVector( uint4 data ) +{ + data.y += data.x; + data.w += data.z; + data.z += data.y; + data.w += data.y; + return data; +} + +uint prefixScanVectorEx( inout uint4 data ) +{ + uint4 backup = data; + data.y += data.x; + data.w += data.z; + data.z += data.y; + data.w += data.y; + uint sum = data.w; + data -= backup; + return sum; +} + + + +RWStructuredBuffer sortDataIn : register( u0 ); +RWStructuredBuffer ldsHistogramOut0 : register( u1 ); +RWStructuredBuffer ldsHistogramOut1 : register( u2 ); + +groupshared u32 ldsSortData[ WG_SIZE*NUM_PER_WI + 16 ]; + + +uint4 localPrefixSum128V( uint4 pData, uint lIdx, inout uint totalSum ) +{ + { // Set data + ldsSortData[lIdx] = 0; + ldsSortData[lIdx+WG_SIZE] = prefixScanVectorEx( pData ); + } + + GROUP_LDS_BARRIER; + + { // Prefix sum + int idx = 2*lIdx + (WG_SIZE+1); + if( lIdx < 64 ) + { + ldsSortData[idx] += ldsSortData[idx-1]; + GROUP_MEM_FENCE; + ldsSortData[idx] += ldsSortData[idx-2]; + GROUP_MEM_FENCE; + ldsSortData[idx] += ldsSortData[idx-4]; + GROUP_MEM_FENCE; + ldsSortData[idx] += ldsSortData[idx-8]; + GROUP_MEM_FENCE; + ldsSortData[idx] += ldsSortData[idx-16]; + GROUP_MEM_FENCE; + ldsSortData[idx] += ldsSortData[idx-32]; + GROUP_MEM_FENCE; + ldsSortData[idx] += ldsSortData[idx-64]; + GROUP_MEM_FENCE; + + ldsSortData[idx-1] += ldsSortData[idx-2]; + GROUP_MEM_FENCE; + } + } + + GROUP_LDS_BARRIER; + + totalSum = ldsSortData[WG_SIZE*2-1]; + uint addValue = ldsSortData[lIdx+127]; + return pData + make_uint4(addValue, addValue, addValue, addValue); +} + +void generateHistogram(u32 lIdx, u32 wgIdx, + uint4 sortedData) +{ + if( lIdx < (1<>m_startBit, sortData[1].m_key>>m_startBit, + sortData[2].m_key>>m_startBit, sortData[3].m_key>>m_startBit ); + + generateHistogram( lIdx, wgIdx, localKeys ); + + GROUP_LDS_BARRIER; + + int nBins = (1< src : register( t0 ); +StructuredBuffer histogramGlobalRadixMajor : register( t1 ); +StructuredBuffer histogramLocalGroupMajor : register( t2 ); + +RWStructuredBuffer dst : register( u0 ); + +groupshared u32 ldsLocalHistogram[ 2*(1<>m_startBit)&cmpValue, (sortData[1].m_key>>m_startBit)&cmpValue, + (sortData[2].m_key>>m_startBit)&cmpValue, (sortData[3].m_key>>m_startBit)&cmpValue );; + + // data is already sorted. So simply subtract local prefix sum + uint4 dstAddr; + dstAddr.x = ldsGlobalHistogram[radix.x] + (localAddr.x - ldsLocalHistogram[radix.x]); + dstAddr.y = ldsGlobalHistogram[radix.y] + (localAddr.y - ldsLocalHistogram[radix.y]); + dstAddr.z = ldsGlobalHistogram[radix.z] + (localAddr.z - ldsLocalHistogram[radix.z]); + dstAddr.w = ldsGlobalHistogram[radix.w] + (localAddr.w - ldsLocalHistogram[radix.w]); + + dst[dstAddr.x] = sortData[0]; + dst[dstAddr.y] = sortData[1]; + dst[dstAddr.z] = sortData[2]; + dst[dstAddr.w] = sortData[3]; +} + +[numthreads(WG_SIZE, 1, 1)] +void CopyKernel( DEFAULT_ARGS ) +{ + dst[ GET_GLOBAL_IDX ] = src[ GET_GLOBAL_IDX ]; +} diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandardKernelsCL.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandardKernelsCL.h new file mode 100644 index 0000000..e793c7e --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandardKernelsCL.h @@ -0,0 +1,347 @@ +static const char* radixSortStandardKernelsCL= \ +"/*\n" +"Bullet Continuous Collision Detection and Physics Library\n" +"Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org\n" +"\n" +"This software is provided 'as-is', without any express or implied warranty.\n" +"In no event will the authors be held liable for any damages arising from the use of this software.\n" +"Permission is granted to anyone to use this software for any purpose, \n" +"including commercial applications, and to alter it and redistribute it freely, \n" +"subject to the following restrictions:\n" +"\n" +"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.\n" +"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n" +"3. This notice may not be removed or altered from any source distribution.\n" +"*/\n" +"//Author Takahiro Harada\n" +"\n" +"\n" +"#pragma OPENCL EXTENSION cl_amd_printf : enable\n" +"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n" +"\n" +"typedef unsigned int u32;\n" +"#define GET_GROUP_IDX get_group_id(0)\n" +"#define GET_LOCAL_IDX get_local_id(0)\n" +"#define GET_GLOBAL_IDX get_global_id(0)\n" +"#define GET_GROUP_SIZE get_local_size(0)\n" +"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n" +"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n" +"#define AtomInc(x) atom_inc(&(x))\n" +"#define AtomInc1(x, out) out = atom_inc(&(x))\n" +"\n" +"#define make_uint4 (uint4)\n" +"#define make_uint2 (uint2)\n" +"\n" +"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n" +"\n" +"#define WG_SIZE 128\n" +"#define NUM_PER_WI 4\n" +"\n" +"\n" +"typedef struct\n" +"{\n" +" u32 m_key; \n" +" u32 m_value;\n" +"}SortData;\n" +"\n" +"\n" +"typedef struct\n" +"{\n" +" u32 m_startBit;\n" +" u32 m_numGroups;\n" +" u32 m_padding[2];\n" +"} ConstBuffer;\n" +"\n" +"#define BITS_PER_PASS 4\n" +"\n" +"\n" +"\n" +"uint4 prefixScanVector( uint4 data )\n" +"{\n" +" data.y += data.x;\n" +" data.w += data.z;\n" +" data.z += data.y;\n" +" data.w += data.y;\n" +" return data;\n" +"}\n" +"\n" +"uint prefixScanVectorEx( uint4* data )\n" +"{\n" +" uint4 backup = data[0];\n" +" data[0].y += data[0].x;\n" +" data[0].w += data[0].z;\n" +" data[0].z += data[0].y;\n" +" data[0].w += data[0].y;\n" +" uint sum = data[0].w;\n" +" *data -= backup;\n" +" return sum;\n" +"}\n" +"\n" +"uint4 localPrefixSum128V( uint4 pData, uint lIdx, uint* totalSum, __local u32 sorterSharedMemory[] )\n" +"{\n" +" { // Set data\n" +" sorterSharedMemory[lIdx] = 0;\n" +" sorterSharedMemory[lIdx+WG_SIZE] = prefixScanVectorEx( &pData );\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" { // Prefix sum\n" +" int idx = 2*lIdx + (WG_SIZE+1);\n" +" if( lIdx < 64 )\n" +" {\n" +" sorterSharedMemory[idx] += sorterSharedMemory[idx-1];\n" +" GROUP_MEM_FENCE;\n" +" sorterSharedMemory[idx] += sorterSharedMemory[idx-2]; \n" +" GROUP_MEM_FENCE;\n" +" sorterSharedMemory[idx] += sorterSharedMemory[idx-4];\n" +" GROUP_MEM_FENCE;\n" +" sorterSharedMemory[idx] += sorterSharedMemory[idx-8];\n" +" GROUP_MEM_FENCE;\n" +" sorterSharedMemory[idx] += sorterSharedMemory[idx-16];\n" +" GROUP_MEM_FENCE;\n" +" sorterSharedMemory[idx] += sorterSharedMemory[idx-32]; \n" +" GROUP_MEM_FENCE;\n" +" sorterSharedMemory[idx] += sorterSharedMemory[idx-64];\n" +" GROUP_MEM_FENCE;\n" +"\n" +" sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];\n" +" GROUP_MEM_FENCE;\n" +" }\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" *totalSum = sorterSharedMemory[WG_SIZE*2-1];\n" +" uint addValue = sorterSharedMemory[lIdx+127];\n" +" return pData + make_uint4(addValue, addValue, addValue, addValue);\n" +"}\n" +"\n" +"\n" +"void generateHistogram(u32 lIdx, u32 wgIdx, \n" +" uint4 sortedData,\n" +" __local u32 *histogram)\n" +"{\n" +" if( lIdx < (1<>cb.m_startBit, sortData[1].m_key>>cb.m_startBit, \n" +" sortData[2].m_key>>cb.m_startBit, sortData[3].m_key>>cb.m_startBit );\n" +"\n" +" generateHistogram( lIdx, wgIdx, localKeys, ldsSortData );\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" int nBins = (1<>cb.m_startBit)&cmpValue, (sortData[1].m_key>>cb.m_startBit)&cmpValue, \n" +" (sortData[2].m_key>>cb.m_startBit)&cmpValue, (sortData[3].m_key>>cb.m_startBit)&cmpValue );;\n" +"\n" +" // data is already sorted. So simply subtract local prefix sum\n" +" uint4 dstAddr;\n" +" dstAddr.x = ldsGlobalHistogram[radix.x] + (localAddr.x - ldsLocalHistogram[radix.x]);\n" +" dstAddr.y = ldsGlobalHistogram[radix.y] + (localAddr.y - ldsLocalHistogram[radix.y]);\n" +" dstAddr.z = ldsGlobalHistogram[radix.z] + (localAddr.z - ldsLocalHistogram[radix.z]);\n" +" dstAddr.w = ldsGlobalHistogram[radix.w] + (localAddr.w - ldsLocalHistogram[radix.w]);\n" +"\n" +" dst[dstAddr.x] = sortData[0];\n" +" dst[dstAddr.y] = sortData[1];\n" +" dst[dstAddr.z] = sortData[2];\n" +" dst[dstAddr.w] = sortData[3];\n" +"}\n" +"\n" +"__kernel\n" +"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n" +"void CopyKernel(__global SortData *src, __global SortData *dst)\n" +"{\n" +" dst[ GET_GLOBAL_IDX ] = src[ GET_GLOBAL_IDX ];\n" +"}\n" +; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandardKernelsDX11.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandardKernelsDX11.h new file mode 100644 index 0000000..1a919ed --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/RadixSortStandardKernelsDX11.h @@ -0,0 +1,324 @@ +static const char* radixSortStandardKernelsDX11= \ +"/*\n" +" 2011 Takahiro Harada\n" +"*/\n" +"\n" +"typedef uint u32;\n" +"\n" +"#define GET_GROUP_IDX groupIdx.x\n" +"#define GET_LOCAL_IDX localIdx.x\n" +"#define GET_GLOBAL_IDX globalIdx.x\n" +"#define GROUP_LDS_BARRIER GroupMemoryBarrierWithGroupSync()\n" +"#define GROUP_MEM_FENCE\n" +"#define DEFAULT_ARGS uint3 globalIdx : SV_DispatchThreadID, uint3 localIdx : SV_GroupThreadID, uint3 groupIdx : SV_GroupID\n" +"#define AtomInc(x) InterlockedAdd(x, 1)\n" +"#define AtomInc1(x, out) InterlockedAdd(x, 1, out)\n" +"\n" +"#define make_uint4 uint4\n" +"#define make_uint2 uint2\n" +"\n" +"uint4 SELECT_UINT4(uint4 b,uint4 a,uint4 condition ){ return make_uint4( ((condition).x)?a.x:b.x, ((condition).y)?a.y:b.y, ((condition).z)?a.z:b.z, ((condition).w)?a.w:b.w ); }\n" +"\n" +"// takahiro end\n" +"#define WG_SIZE 128\n" +"#define NUM_PER_WI 4\n" +"\n" +"#define GET_GROUP_SIZE WG_SIZE\n" +"\n" +"typedef struct\n" +"{\n" +" u32 m_key; \n" +" u32 m_value;\n" +"}SortData;\n" +"\n" +"cbuffer SortCB : register( b0 )\n" +"{\n" +" u32 m_startBit;\n" +" u32 m_numGroups;\n" +" u32 m_padding[2];\n" +"};\n" +"\n" +"#define BITS_PER_PASS 4\n" +"\n" +"\n" +"uint4 prefixScanVector( uint4 data )\n" +"{\n" +" data.y += data.x;\n" +" data.w += data.z;\n" +" data.z += data.y;\n" +" data.w += data.y;\n" +" return data;\n" +"}\n" +"\n" +"uint prefixScanVectorEx( inout uint4 data )\n" +"{\n" +" uint4 backup = data;\n" +" data.y += data.x;\n" +" data.w += data.z;\n" +" data.z += data.y;\n" +" data.w += data.y;\n" +" uint sum = data.w;\n" +" data -= backup;\n" +" return sum;\n" +"}\n" +"\n" +"\n" +"\n" +"RWStructuredBuffer sortDataIn : register( u0 );\n" +"RWStructuredBuffer ldsHistogramOut0 : register( u1 );\n" +"RWStructuredBuffer ldsHistogramOut1 : register( u2 );\n" +"\n" +"groupshared u32 ldsSortData[ WG_SIZE*NUM_PER_WI + 16 ];\n" +"\n" +"\n" +"uint4 localPrefixSum128V( uint4 pData, uint lIdx, inout uint totalSum )\n" +"{\n" +" { // Set data\n" +" ldsSortData[lIdx] = 0;\n" +" ldsSortData[lIdx+WG_SIZE] = prefixScanVectorEx( pData );\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" { // Prefix sum\n" +" int idx = 2*lIdx + (WG_SIZE+1);\n" +" if( lIdx < 64 )\n" +" {\n" +" ldsSortData[idx] += ldsSortData[idx-1];\n" +" GROUP_MEM_FENCE;\n" +" ldsSortData[idx] += ldsSortData[idx-2]; \n" +" GROUP_MEM_FENCE;\n" +" ldsSortData[idx] += ldsSortData[idx-4];\n" +" GROUP_MEM_FENCE;\n" +" ldsSortData[idx] += ldsSortData[idx-8];\n" +" GROUP_MEM_FENCE;\n" +" ldsSortData[idx] += ldsSortData[idx-16];\n" +" GROUP_MEM_FENCE;\n" +" ldsSortData[idx] += ldsSortData[idx-32]; \n" +" GROUP_MEM_FENCE;\n" +" ldsSortData[idx] += ldsSortData[idx-64];\n" +" GROUP_MEM_FENCE;\n" +"\n" +" ldsSortData[idx-1] += ldsSortData[idx-2];\n" +" GROUP_MEM_FENCE;\n" +" }\n" +" }\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" totalSum = ldsSortData[WG_SIZE*2-1];\n" +" uint addValue = ldsSortData[lIdx+127];\n" +" return pData + make_uint4(addValue, addValue, addValue, addValue);\n" +"}\n" +"\n" +"void generateHistogram(u32 lIdx, u32 wgIdx, \n" +" uint4 sortedData)\n" +"{\n" +" if( lIdx < (1<>m_startBit, sortData[1].m_key>>m_startBit, \n" +" sortData[2].m_key>>m_startBit, sortData[3].m_key>>m_startBit );\n" +"\n" +" generateHistogram( lIdx, wgIdx, localKeys );\n" +"\n" +" GROUP_LDS_BARRIER;\n" +"\n" +" int nBins = (1< src : register( t0 );\n" +"StructuredBuffer histogramGlobalRadixMajor : register( t1 );\n" +"StructuredBuffer histogramLocalGroupMajor : register( t2 );\n" +"\n" +"RWStructuredBuffer dst : register( u0 );\n" +"\n" +"groupshared u32 ldsLocalHistogram[ 2*(1<>m_startBit)&cmpValue, (sortData[1].m_key>>m_startBit)&cmpValue, \n" +" (sortData[2].m_key>>m_startBit)&cmpValue, (sortData[3].m_key>>m_startBit)&cmpValue );;\n" +"\n" +" // data is already sorted. So simply subtract local prefix sum\n" +" uint4 dstAddr;\n" +" dstAddr.x = ldsGlobalHistogram[radix.x] + (localAddr.x - ldsLocalHistogram[radix.x]);\n" +" dstAddr.y = ldsGlobalHistogram[radix.y] + (localAddr.y - ldsLocalHistogram[radix.y]);\n" +" dstAddr.z = ldsGlobalHistogram[radix.z] + (localAddr.z - ldsLocalHistogram[radix.z]);\n" +" dstAddr.w = ldsGlobalHistogram[radix.w] + (localAddr.w - ldsLocalHistogram[radix.w]);\n" +"\n" +" dst[dstAddr.x] = sortData[0];\n" +" dst[dstAddr.y] = sortData[1];\n" +" dst[dstAddr.z] = sortData[2];\n" +" dst[dstAddr.w] = sortData[3];\n" +"}\n" +"\n" +"[numthreads(WG_SIZE, 1, 1)]\n" +"void CopyKernel( DEFAULT_ARGS )\n" +"{\n" +" dst[ GET_GLOBAL_IDX ] = src[ GET_GLOBAL_IDX ];\n" +"}\n" +; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/SortData.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/SortData.h new file mode 100644 index 0000000..3d88ebd --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/SortData.h @@ -0,0 +1,31 @@ +/* + 2011 Takahiro Harada +*/ + +#pragma once + +#include + +namespace adl +{ + +struct SortData +{ + SortData(){} + SortData( u32 key, u32 value ) : m_key(key), m_value(value) {} + + union + { + u32 m_key; + struct { u16 m_key16[2]; }; + }; + u32 m_value; + + friend bool operator <(const SortData& a, const SortData& b) + { + return a.m_key < b.m_key; + } +}; + + +}; diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/radixsortadvanced.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/radixsortadvanced.inl new file mode 100644 index 0000000..210b5dd --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/radixsortadvanced.inl @@ -0,0 +1,146 @@ +/* + 2011 Takahiro Harada +*/ + +#define PATH "..\\..\\AdlPrimitives\\Sort\\RadixSortAdvancedKernels" +#define KERNEL0 "StreamCountKernel" +#define KERNEL1 "SortAndScatterKernel1" +#define KERNEL2 "PrefixScanKernel" + +template +class RadixSortAdvanced : public RadixSortBase +{ + public: + typedef Launcher::BufferInfo BufferInfo; + + enum + { + WG_SIZE = 128, + NUM_PER_WI = 4, + MAX_NUM_WORKGROUPS = 60, + }; + + struct Data : public RadixSort::Data + { + Kernel* m_localCountKernel; + Kernel* m_scatterKernel; + Kernel* m_scanKernel; + + Buffer* m_workBuffer0; + Buffer* m_workBuffer1; + Buffer* m_constBuffer[32/4]; + }; + + + static + Data* allocate(const Device* deviceData, int maxSize, Option option = SORT_NORMAL); + + static + void deallocate(void* data); + + static + void execute(void* data, Buffer& inout, int n, int sortBits); +}; + +template +typename RadixSortAdvanced::Data* RadixSortAdvanced::allocate(const Device* deviceData, int maxSize, Option option) +{ + ADLASSERT( type == deviceData->m_type ); + + const char* src[] = { 0, 0, 0 }; + + Data* data = new Data; + data->m_option = option; + data->m_deviceData = deviceData; + + data->m_localCountKernel = deviceData->getKernel( PATH, KERNEL0, 0, src[type] ); + data->m_scatterKernel = deviceData->getKernel( PATH, KERNEL1, 0, src[type] ); + data->m_scanKernel = deviceData->getKernel( PATH, KERNEL2, 0, src[type] ); + + data->m_workBuffer0 = new Buffer( deviceData, MAX_NUM_WORKGROUPS*16 ); + data->m_workBuffer1 = new Buffer( deviceData, maxSize ); + for(int i=0; i<32/4; i++) + data->m_constBuffer[i] = new Buffer( deviceData, 1, BufferBase::BUFFER_CONST ); + data->m_maxSize = maxSize; + + return data; +} + +template +void RadixSortAdvanced::deallocate(void* rawData) +{ + Data* data = (Data*)rawData; + + delete data->m_workBuffer0; + delete data->m_workBuffer1; + for(int i=0; i<32/4; i++) + delete data->m_constBuffer[i]; + + delete data; +} + +template +void RadixSortAdvanced::execute(void* rawData, Buffer& inout, int n, int sortBits) +{ + Data* data = (Data*)rawData; + + ADLASSERT( sortBits == 32 ); + + ADLASSERT( NUM_PER_WI == 4 ); + ADLASSERT( n%(WG_SIZE*NUM_PER_WI) == 0 ); + ADLASSERT( MAX_NUM_WORKGROUPS < 128*8/16 ); + + Buffer* src = &inout; + Buffer* dst = data->m_workBuffer1; + + const Device* deviceData = data->m_deviceData; + + int nBlocks = n/(NUM_PER_WI*WG_SIZE); + const int nWorkGroupsToExecute = min2((int)MAX_NUM_WORKGROUPS, nBlocks); + int nBlocksPerGroup = (nBlocks+nWorkGroupsToExecute-1)/nWorkGroupsToExecute; + ADLASSERT( nWorkGroupsToExecute <= MAX_NUM_WORKGROUPS ); + + int4 constBuffer = make_int4(0, nBlocks, nWorkGroupsToExecute, nBlocksPerGroup); + + int iPass = 0; + int startBit = 0; + for(int startBit=0; startBit<32; startBit+=4, iPass++) + { + constBuffer.x = startBit; + + { + BufferInfo bInfo[] = { BufferInfo( src, true ), BufferInfo( data->m_workBuffer0 ) }; + + Launcher launcher( deviceData, data->m_localCountKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[iPass], constBuffer ); + launcher.launch1D( WG_SIZE* nWorkGroupsToExecute, WG_SIZE ); + } + + + { + BufferInfo bInfo[] = { BufferInfo( data->m_workBuffer0 ) }; + + Launcher launcher( deviceData, data->m_scanKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[iPass], constBuffer ); + launcher.launch1D( WG_SIZE, WG_SIZE ); + } + + { + BufferInfo bInfo[] = { BufferInfo( data->m_workBuffer0, true ), BufferInfo( src ), BufferInfo( dst ) }; + + Launcher launcher( deviceData, data->m_scatterKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[iPass], constBuffer ); + launcher.launch1D( WG_SIZE*nWorkGroupsToExecute, WG_SIZE ); + } + + swap2( src, dst ); + } +} + +#undef PATH +#undef KERNEL0 +#undef KERNEL1 +#undef KERNEL2 diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/radixsortsimple.inl b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/radixsortsimple.inl new file mode 100644 index 0000000..3fcab75 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/Sort/radixsortsimple.inl @@ -0,0 +1,149 @@ +/* + 2011 Takahiro Harada +*/ + +#define PATH "..\\..\\opencl\\primitives\\AdlPrimitives\\Sort\\RadixSortSimpleKernels" +#define KERNEL0 "LocalCountKernel" +#define KERNEL1 "ScatterKernel" + +#include +#include + +template +class RadixSortSimple : public RadixSortBase +{ + public: + typedef Launcher::BufferInfo BufferInfo; + + enum + { + WG_SIZE = 128, + NUM_PER_WI = 4, + }; + + struct Data : public RadixSort::Data + { + Kernel* m_localCountKernel; + Kernel* m_scatterKernel; + + Buffer* m_workBuffer0; + Buffer* m_workBuffer1; + Buffer* m_workBuffer2; + Buffer* m_constBuffer[4]; + }; + + + static + Data* allocate(const Device* deviceData, int maxSize, Option option = SORT_NORMAL); + + static + void deallocate(void* data); + + static + void execute(void* data, Buffer& inout, int n, int sortBits); +}; + +template +typename RadixSortSimple::Data* RadixSortSimple::allocate(const Device* deviceData, int maxSize, Option option) +{ + ADLASSERT( type == deviceData->m_type ); + + const char* src[] = +#if defined(ADL_LOAD_KERNEL_FROM_STRING) + {radixSortSimpleKernelsCL, radixSortSimpleKernelsDX11}; +#else + { 0, 0 }; +#endif + u32 maxNumGroups = (maxSize+WG_SIZE*NUM_PER_WI-1)/(WG_SIZE*NUM_PER_WI); + + Data* data = new Data; + data->m_option = option; + data->m_deviceData = deviceData; + + data->m_localCountKernel = deviceData->getKernel( PATH, KERNEL0, 0, src[type] ); + data->m_scatterKernel = deviceData->getKernel( PATH, KERNEL1, 0, src[type] ); + + data->m_scanData = PrefixScan::allocate( deviceData, maxSize ); + + data->m_workBuffer0 = new Buffer( deviceData, maxNumGroups*256 ); + data->m_workBuffer1 = new Buffer( deviceData, maxNumGroups*256 ); + data->m_workBuffer2 = new Buffer( deviceData, maxSize ); + data->m_constBuffer[0] = new Buffer( deviceData, 1, BufferBase::BUFFER_CONST ); + data->m_constBuffer[1] = new Buffer( deviceData, 1, BufferBase::BUFFER_CONST ); + data->m_constBuffer[2] = new Buffer( deviceData, 1, BufferBase::BUFFER_CONST ); + data->m_constBuffer[3] = new Buffer( deviceData, 1, BufferBase::BUFFER_CONST ); + data->m_maxSize = maxSize; + + return data; +} + +template +void RadixSortSimple::deallocate(void* rawData) +{ + Data* data = (Data*)rawData; + + delete data->m_workBuffer0; + delete data->m_workBuffer1; + delete data->m_workBuffer2; + delete data->m_constBuffer[0]; + delete data->m_constBuffer[1]; + delete data->m_constBuffer[2]; + delete data->m_constBuffer[3]; + + PrefixScan::deallocate( data->m_scanData ); + + delete data; +} + +template +void RadixSortSimple::execute(void* rawData, Buffer& inout, int n, int sortBits) +{ + Data* data = (Data*)rawData; + + ADLASSERT( sortBits == 32 ); + ADLASSERT( n%512 == 0 ); + ADLASSERT( n <= data->m_maxSize ); + + Buffer* src = &inout; + Buffer* dst = data->m_workBuffer2; + + const Device* deviceData = data->m_deviceData; + + int numGroups = (n+WG_SIZE*NUM_PER_WI-1)/(WG_SIZE*NUM_PER_WI); + + int4 constBuffer; + + int iPass = 0; + for(int startBit=0; startBit<32; startBit+=8, iPass++) + { + constBuffer.x = startBit; + constBuffer.y = numGroups; + constBuffer.z = WG_SIZE; + + { + BufferInfo bInfo[] = { BufferInfo( src, true ), BufferInfo( data->m_workBuffer0 ) }; + + Launcher launcher( deviceData, data->m_localCountKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[iPass], constBuffer ); + launcher.launch1D( WG_SIZE*numGroups, WG_SIZE ); + } + + PrefixScan::execute( data->m_scanData, *data->m_workBuffer0, *data->m_workBuffer1, numGroups*256 ); + + { + BufferInfo bInfo[] = { BufferInfo( src, true ), BufferInfo( dst ), BufferInfo( data->m_workBuffer1 ) }; + + Launcher launcher( deviceData, data->m_scatterKernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( *data->m_constBuffer[iPass], constBuffer ); + launcher.launch1D( WG_SIZE*numGroups, WG_SIZE ); + } + + swap2( src, dst ); + } +} + +#undef PATH +#undef KERNEL0 +#undef KERNEL1 diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/stringify.py b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/stringify.py new file mode 100644 index 0000000..e79e281 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/stringify.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +import sys +import os +import shutil + +arg = sys.argv[1] +fh = open(arg) + +print 'static const char* '+sys.argv[2]+'= \\' +for line in fh.readlines(): + a = line.strip('\n') + print '"'+a+'\\n"' +print ';' diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/stringifykernels.bat b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/stringifykernels.bat new file mode 100644 index 0000000..3a2aa63 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlPrimitives/stringifykernels.bat @@ -0,0 +1,22 @@ +stringify.py Fill/FillKernels.cl fillKernelsCL >Fill/FillKernelsCL.h +stringify.py Fill/FillKernels.hlsl fillKernelsDX11 >Fill/FillKernelsDX11.h +stringify.py Scan/PrefixScanKernels.cl prefixScanKernelsCL >Scan/PrefixScanKernelsCL.h +stringify.py Scan/PrefixScanKernels.hlsl prefixScanKernelsDX11 >Scan/PrefixScanKernelsDX11.h +stringify.py Search/BoundSearchKernels.cl boundSearchKernelsCL >Search/BoundSearchKernelsCL.h +stringify.py Search/BoundSearchKernels.hlsl boundSearchKernelsDX11 >Search/BoundSearchKernelsDX11.h +stringify.py Sort/RadixSortSimpleKernels.cl radixSortSimpleKernelsCL >Sort/RadixSortSimpleKernelsCL.h +stringify.py Sort/RadixSortSimpleKernels.hlsl radixSortSimpleKernelsDX11 >Sort/RadixSortSimpleKernelsDX11.h +stringify.py Sort/RadixSortStandardKernels.cl radixSortStandardKernelsCL >Sort/RadixSortStandardKernelsCL.h + +stringify.py Sort/RadixSort32Kernels.cl radixSort32KernelsCL >Sort/RadixSort32KernelsCL.h +stringify.py Sort/RadixSort32Kernels.hlsl radixSort32KernelsDX11 >Sort/RadixSort32KernelsDX11.h + +stringify.py Copy/CopyKernels.cl copyKernelsCL >Copy/CopyKernelsCL.h +stringify.py Copy/CopyKernels.hlsl copyKernelsDX11 >Copy/CopyKernelsDX11.h + +stringify.py Sort/RadixSortStandardKernels.hlsl radixSortStandardKernelsDX11 >Sort/RadixSortStandardKernelsDX11.h +stringify.py Sort/RadixSortAdvancedKernels.hlsl radixSortAdvancedKernelsDX11 >Sort/RadixSortAdvancedKernelsDX11.h + + + + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/AMD/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/AMD/premake4.lua new file mode 100644 index 0000000..d47cec9 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/AMD/premake4.lua @@ -0,0 +1,31 @@ + + hasCL = findOpenCL_AMD() + hasDX11 = findDirectX11() + + if (hasCL) then + + project "OpenCL_DX11_primitives_test_AMD" + + initOpenCL_AMD() + + if (hasDX11) then + initDirectX11() + end + + language "C++" + + kind "ConsoleApp" + targetdir "../../../../bin" + includedirs {"..","../.."} + + links { + "OpenCL" + } + + files { + "../main.cpp", + "../RadixSortBenchmark.h", + "../UnitTests.h" + } + + end \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/Intel/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/Intel/premake4.lua new file mode 100644 index 0000000..157405f --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/Intel/premake4.lua @@ -0,0 +1,31 @@ + + hasCL = findOpenCL_Intel() + hasDX11 = findDirectX11() + + if (hasCL) then + + project "OpenCL_DX11_primitives_test_Intel" + + initOpenCL_Intel() + + if (hasDX11) then + initDirectX11() + end + + language "C++" + + kind "ConsoleApp" + targetdir "../../../../bin" + includedirs {"..","../.."} + + links { + "OpenCL" + } + + files { + "../main.cpp", + "../RadixSortBenchmark.h", + "../UnitTests.h" + } + + end \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/LaunchOverheadBenchmark.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/LaunchOverheadBenchmark.h new file mode 100644 index 0000000..4b1ae7d --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/LaunchOverheadBenchmark.h @@ -0,0 +1,103 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#include + + + +template +__inline +void copyTest( Device* device ) +{ + int size = 65*1024; + + Buffer buf0( device, size ); + Buffer buf1( device, size ); + + Stopwatch sw( device ); + + Copy::Data* data = Copy::allocate( device ); + + for(int i=0; i<10; i++) + Copy::execute( data, buf1, buf0, size, CopyBase::PER_WI_1 ); + DeviceUtils::waitForCompletion( device ); + + { + const int nTests = 12; + + float t[nTests]; + + for(int ii=0; ii::execute( data, buf1, buf0, size, CopyBase::PER_WI_1 ); + } + DeviceUtils::waitForCompletion( device ); + sw.stop(); + + t[ii] = sw.getMs()/(float)iter; + } + + for(int ii=0; ii::deallocate( data ); +} + +void launchOverheadBenchmark() +{ + printf("LaunchOverheadBenchmark\n"); + + + Device* ddcl; +#if defined(ADL_ENABLE_DX11) + Device* dddx; +#endif + { + DeviceUtils::Config cfg; + ddcl = DeviceUtils::allocate( TYPE_CL, cfg ); +#if defined(ADL_ENABLE_DX11) + dddx = DeviceUtils::allocate( TYPE_DX11, cfg ); +#endif + } + + { + printf("CL\n"); + copyTest( ddcl ); + } +#ifdef ADL_ENABLE_DX11 + { + printf("DX11\n"); + copyTest( dddx ); + } +#endif + + +} + + +//1, 2, 4, 8, 16, 32, 64, 128, 256, + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/NVIDIA/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/NVIDIA/premake4.lua new file mode 100644 index 0000000..e4d5cea --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/NVIDIA/premake4.lua @@ -0,0 +1,31 @@ + + hasCL = findOpenCL_NVIDIA() + hasDX11 = findDirectX11() + + if (hasCL) then + + project "OpenCL_DX11_primitives_test_NVIDIA" + + initOpenCL_NVIDIA() + + if (hasDX11) then + initDirectX11() + end + + language "C++" + + kind "ConsoleApp" + targetdir "../../../../bin" + includedirs {"..","../.."} + + links { + "OpenCL" + } + + files { + "../main.cpp", + "../RadixSortBenchmark.h", + "../UnitTests.h" + } + + end \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/RadixSortBenchmark.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/RadixSortBenchmark.h new file mode 100644 index 0000000..35404dd --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/RadixSortBenchmark.h @@ -0,0 +1,121 @@ + +template +void run( Device* device, int minSize = 512, int maxSize = 64*1024 )//, int increment = 512 ) +{ + ADLASSERT( TYPE == device->m_type ); + + Stopwatch sw( device ); + +// RadixSort::Data* data0 = RadixSort::allocate( device, maxSize, RadixSortBase::SORT_SIMPLE ); + RadixSort::Data* data0 = RadixSort::allocate( device, maxSize, RadixSortBase::SORT_STANDARD ); + RadixSort::Data* data1 = RadixSort::allocate( device, maxSize, RadixSortBase::SORT_STANDARD ); + RadixSort::Data* data2 = RadixSort::allocate( device, maxSize, RadixSortBase::SORT_ADVANCED ); + + Buffer buf0( device, maxSize ); + Buffer buf1( device, maxSize ); + Buffer buf2( device, maxSize ); + + SortData* input = new SortData[ maxSize ]; + +// for(int iter = minSize; iter<=maxSize; iter+=increment) + for(int iter = minSize; iter<=maxSize; iter*=2) + { + int size = NEXTMULTIPLEOF( iter, 512 ); + + for(int i=0; i::execute( data0, buf0, size ); + + sw.split(); + + RadixSort::execute( data1, buf1, size ); + + sw.split(); + + RadixSort::execute( data2, buf2, size ); + + sw.stop(); + + + float t[3]; + sw.getMs( t, 3 ); +// printf(" %d %3.2f %3.2f %3.2f\n", size, t[0], t[1], t[2]); + printf(" %d %3.2f %3.2f\n", size, t[1], t[2]); + } + + RadixSort::deallocate( data0 ); + RadixSort::deallocate( data1 ); + RadixSort::deallocate( data2 ); + + delete [] input; +} + +template +void run32( Device* device, int size ) +{ + //Cayman: 4194.30Keys: 373.05MKeys/s + //Cypress: 4194.30Keys: 315.13MKeys/s + ADLASSERT( TYPE == device->m_type ); + + Stopwatch sw( device ); + + RadixSort32::Data* data = RadixSort32::allocate( device, size ); + Copy::Data* copyData = Copy::allocate( device ); + + Buffer inputMaster( device, size ); + Buffer input( device, size ); + Buffer output( device, size ); + { + u32* host = new u32[size]; + for(int i=0; i::execute( copyData, (Buffer&)input, (Buffer&)inputMaster, size ); +// RadixSort32::execute( data, input, size ); + RadixSort32::execute( data, input, output, size ); + } + sw.stop(); + + { + float tInS = sw.getMs()/1000.f/(float)nIter; + float mKeysPerS = size/1000.f/1000.f/tInS; + printf("%3.2fMKeys: %3.2fMKeys/s\n", size/1000.f, mKeysPerS); + } + + RadixSort32::deallocate( data ); + Copy::deallocate( copyData ); +} + +template +void radixSortBenchmark() +{ + + Device* device; + { + DeviceUtils::Config cfg; + device = DeviceUtils::allocate( TYPE, cfg ); + } + + run32( device, 256*1024*8*2 ); +// run32( device, 256*20*6 ); + +// run( device, 512, 1024*128*4 ); + + DeviceUtils::deallocate( device ); + +} diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/UnitTests.h b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/UnitTests.h new file mode 100644 index 0000000..a1ab2e4 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/UnitTests.h @@ -0,0 +1,801 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#include +#include +#include +#include +#include +#include + +#include + +using namespace adl; + +#define NUM_TESTS 10 + +int g_nPassed = 0; +int g_nFailed = 0; +bool g_testFailed = 0; + +//#define TEST_INIT bool g_testFailed = 0; +#define TEST_INIT g_testFailed = 0; +#define TEST_ASSERT(x) if( !(x) ){g_testFailed = 1;} +//#define TEST_ASSERT(x) if( !(x) ){g_testFailed = 1;ADLASSERT(x);} +#define TEST_REPORT(testName) printf("[%s] %s\n",(g_testFailed)?"X":"O", testName); if(g_testFailed) g_nFailed++; else g_nPassed++; + +void memCpyTest( Device* deviceData ) +{ + TEST_INIT; + int maxSize = 64*1024; + Buffer buff( deviceData, maxSize ); + + u32* hostBuff = new u32[maxSize]; + + for(int iter=0; iterquery(deviceData, ".\\Kernel", "VectorAddKernel" ); + + { + int size = 1024; + Buffer buf0( deviceData, size ); + Buffer buf1( deviceData, size ); + Buffer cBuf( deviceData, 1, BufferBase::BUFFER_CONST ); + int* hostBuf0 = new int[size]; + int* hostBuf1 = new int[size]; + for(int i=0; i*)&buf0 ), Launcher::BufferInfo( (Buffer*)&buf1, true ) }; + + Launcher launcher( deviceData, kernel ); + launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(Launcher::BufferInfo) ); + launcher.setConst( (Buffer&)cBuf, constBuffer ); + launcher.launch1D( size ); + + buf0.read( hostBuf0, size ); + buf1.read( hostBuf1, size ); + DeviceUtils::waitForCompletion( deviceData ); + } + + for(int i=0; i +void scanTest( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + + ADLASSERT( type == deviceGPU->m_type ); + + int maxSize = 1024*256; + + HostBuffer buf0( deviceHost, maxSize ); + HostBuffer buf1( deviceHost, maxSize ); + Buffer buf2( deviceGPU, maxSize ); + Buffer buf3( deviceGPU, maxSize ); + + PrefixScan::Data* data0 = PrefixScan::allocate( deviceGPU, maxSize ); + PrefixScan::Data* data1 = PrefixScan::allocate( deviceHost, maxSize ); + + int dx = maxSize/NUM_TESTS; + for(int iter=0; iter::execute( data1, buf0, buf1, size, &sumHost ); + PrefixScan::execute( data0, buf2, buf3, size, &sumGPU ); + + buf3.read( buf0.m_ptr, size ); + DeviceUtils::waitForCompletion( deviceGPU ); + TEST_ASSERT( sumHost == sumGPU ); + for(int i=0; i::deallocate( data1 ); + PrefixScan::deallocate( data0 ); + + TEST_REPORT( "scanTest" ); +} + +template +bool radixSortTest( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + ADLASSERT( type == deviceGPU->m_type ); + + int maxSize = 1024*256; + + HostBuffer buf0( deviceHost, maxSize ); + HostBuffer buf1( deviceHost, maxSize ); + Buffer buf2( deviceGPU, maxSize ); + + RadixSort::Data* dataH = RadixSort::allocate( deviceHost, maxSize, RadixSortBase::SORT_SIMPLE ); + RadixSort::Data* dataC = RadixSort::allocate( deviceGPU, maxSize, SORT_TYPE ); + + int dx = maxSize/NUM_TESTS; + for(int iter=0; iter::execute( dataH, buf0, size ); + RadixSort::execute( dataC, buf2, size ); + + buf2.read( buf1.m_ptr, size ); + DeviceUtils::waitForCompletion( deviceGPU ); + for(int i=0; i::deallocate( dataH ); + RadixSort::deallocate( dataC ); + + return g_testFailed; +} + +template +void radixSortSimpleTest( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + g_testFailed = radixSortTest(deviceGPU, deviceHost); + TEST_REPORT( "radixSortSimpleTest" ); +} + +template +void radixSortStandardTest( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + g_testFailed = radixSortTest(deviceGPU, deviceHost); + TEST_REPORT( "radixSortStandardTest" ); +} + +template +void radixSortAdvancedTest( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + g_testFailed = radixSortTest(deviceGPU, deviceHost); + TEST_REPORT( "radixSortAdvancedTest" ); +} + +template +void boundSearchTest( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + + ADLASSERT( type == deviceGPU->m_type ); + + int maxSize = 1024*256; + int bucketSize = 256; + + HostBuffer buf0( deviceHost, maxSize ); + HostBuffer lowerH( deviceHost, maxSize ); + HostBuffer upperH( deviceHost, maxSize ); + + Buffer buf( deviceGPU, maxSize ); + Buffer lower( deviceGPU, maxSize ); + Buffer upper( deviceGPU, maxSize ); + + BoundSearch::Data* dataH = BoundSearch::allocate( deviceGPU ); + RadixSort::Data* dataHSort = RadixSort::allocate( deviceHost, maxSize, RadixSortBase::SORT_SIMPLE ); + + int dx = maxSize/NUM_TESTS; + for(int iter=0; iter::execute( dataHSort, buf0, size ); + buf.write( buf0.m_ptr, size ); + { + u32* host = new u32[size]; + for(int i=0; i::execute( dataH, buf, size, lower, bucketSize, BoundSearchBase::BOUND_LOWER ); + BoundSearch::execute( dataH, buf, size, upper, bucketSize, BoundSearchBase::BOUND_UPPER ); + + lower.read( lowerH.m_ptr, bucketSize ); + upper.read( upperH.m_ptr, bucketSize ); + DeviceUtils::waitForCompletion( deviceGPU ); +/* + for(u32 i=1; i<(u32)bucketSize; i++) + { + for(u32 j=lowerH[i-1]; j::deallocate( dataH ); + RadixSort::deallocate( dataHSort ); + + TEST_REPORT( "boundSearchTest" ); +} + +template +void fillIntTest( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + + ADLASSERT( type == deviceGPU->m_type ); + + int maxSize = 1024*256; + + HostBuffer buf0( deviceHost, maxSize ); + HostBuffer buf1( deviceHost, maxSize ); + Buffer buf2( deviceGPU, maxSize ); + + Fill::Data* data0 = Fill::allocate( deviceHost ); + Fill::Data* data1 = Fill::allocate( deviceGPU ); + + int dx = maxSize/NUM_TESTS; + for(int iter=0; iter::execute( data0, buf0, 12, size ); + Fill::execute( data1, buf2, 12, size ); + + buf2.read( buf1.m_ptr, size ); + DeviceUtils::waitForCompletion( deviceGPU ); + for(int i=0; i::deallocate( data0 ); + Fill::deallocate( data1 ); + + TEST_REPORT( "fillIntTest" ); +} + +template +void fillInt2Test( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + + ADLASSERT( type == deviceGPU->m_type ); + + int maxSize = 1024*256; + + HostBuffer buf0( deviceHost, maxSize ); + HostBuffer buf1( deviceHost, maxSize ); + Buffer buf2( deviceGPU, maxSize ); + + Fill::Data* data0 = Fill::allocate( deviceHost ); + Fill::Data* data1 = Fill::allocate( deviceGPU ); + + int dx = maxSize/NUM_TESTS; + for(int iter=0; iter::execute( data0, buf0, make_int2( 12, 12 ), size ); + Fill::execute( data1, buf2, make_int2( 12, 12 ), size ); + + buf2.read( buf1.m_ptr, size ); + DeviceUtils::waitForCompletion( deviceGPU ); + for(int i=0; i::deallocate( data0 ); + Fill::deallocate( data1 ); + + TEST_REPORT( "fillInt2Test" ); +} + +template +void fillInt4Test( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + + ADLASSERT( type == deviceGPU->m_type ); + + int maxSize = 1024*256; + + HostBuffer buf0( deviceHost, maxSize ); + HostBuffer buf1( deviceHost, maxSize ); + Buffer buf2( deviceGPU, maxSize ); + + Fill::Data* data0 = Fill::allocate( deviceHost ); + Fill::Data* data1 = Fill::allocate( deviceGPU ); + + int dx = maxSize/NUM_TESTS; + for(int iter=0; iter::execute( data0, buf0, make_int4( 12 ), size ); + Fill::execute( data1, buf2, make_int4( 12 ), size ); + + buf2.read( buf1.m_ptr, size ); + DeviceUtils::waitForCompletion( deviceGPU ); + for(int i=0; i::deallocate( data0 ); + Fill::deallocate( data1 ); + + TEST_REPORT( "fillInt4Test" ); +} + + +template +bool CopyF4Test( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + ADLASSERT( type == deviceGPU->m_type ); + + int maxSize = 1024*256; + + HostBuffer buf0( deviceHost, maxSize ); + HostBuffer buf1( deviceHost, maxSize ); + Buffer buf2( deviceGPU, maxSize ); + Buffer buf3( deviceGPU, maxSize ); + HostBuffer devResult( deviceHost, maxSize ); + + Copy::Data* data0 = Copy::allocate( deviceHost ); + Copy::Data* data1 = Copy::allocate( deviceGPU ); + + int dx = maxSize/NUM_TESTS; + for(int iter=0; iter::execute( data0, buf1, buf0, size, OPTION ); + Copy::execute( data1, buf3, buf2, size, OPTION ); + + buf3.read( devResult.m_ptr, size ); + DeviceUtils::waitForCompletion( deviceGPU ); + for(int i=0; i::deallocate( data0 ); + Copy::deallocate( data1 ); + + return g_testFailed; +} + +template +void Copy1F4Test( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + g_testFailed = CopyF4Test( deviceGPU, deviceHost ); + TEST_REPORT( "Copy1F4Test" ); +} + +template +void Copy2F4Test( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + g_testFailed = CopyF4Test( deviceGPU, deviceHost ); + TEST_REPORT( "Copy2F4Test" ); +} + +template +void Copy4F4Test( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + g_testFailed = CopyF4Test( deviceGPU, deviceHost ); + TEST_REPORT( "Copy4F4Test" ); +} + + +template +void CopyF1Test( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + ADLASSERT( type == deviceGPU->m_type ); + + int maxSize = 1024*256; + + HostBuffer buf0( deviceHost, maxSize ); + HostBuffer buf1( deviceHost, maxSize ); + Buffer buf2( deviceGPU, maxSize ); + Buffer buf3( deviceGPU, maxSize ); + HostBuffer devResult( deviceHost, maxSize ); + + Copy::Data* data0 = Copy::allocate( deviceHost ); + Copy::Data* data1 = Copy::allocate( deviceGPU ); + + int dx = maxSize/NUM_TESTS; + for(int iter=0; iter::execute( data0, buf1, buf0, size ); + Copy::execute( data1, buf3, buf2, size ); + + buf3.read( devResult.m_ptr, size ); + DeviceUtils::waitForCompletion( deviceGPU ); + for(int i=0; i::deallocate( data0 ); + Copy::deallocate( data1 ); + + TEST_REPORT( "CopyF1Test" ); +} + +template +void CopyF2Test( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + ADLASSERT( type == deviceGPU->m_type ); + + int maxSize = 1024*256; + + HostBuffer buf0( deviceHost, maxSize ); + HostBuffer buf1( deviceHost, maxSize ); + Buffer buf2( deviceGPU, maxSize ); + Buffer buf3( deviceGPU, maxSize ); + HostBuffer devResult( deviceHost, maxSize ); + + Copy::Data* data0 = Copy::allocate( deviceHost ); + Copy::Data* data1 = Copy::allocate( deviceGPU ); + + int dx = maxSize/NUM_TESTS; + for(int iter=0; iter::execute( data0, buf1, buf0, size ); + Copy::execute( data1, buf3, buf2, size ); + + buf3.read( devResult.m_ptr, size ); + DeviceUtils::waitForCompletion( deviceGPU ); + for(int i=0; i::deallocate( data0 ); + Copy::deallocate( data1 ); + + TEST_REPORT( "CopyF2Test" ); +} + +template +void radixSort32Test( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + ADLASSERT( type == deviceGPU->m_type ); + + int maxSize = 1024*256; + + HostBuffer buf0( deviceHost, maxSize ); + HostBuffer buf1( deviceHost, maxSize ); + Buffer buf2( deviceGPU, maxSize ); + + RadixSort32::Data* dataH = RadixSort32::allocate( deviceHost, maxSize ); + RadixSort32::Data* dataC = RadixSort32::allocate( deviceGPU, maxSize ); + + int dx = maxSize/NUM_TESTS; + for(int iter=0; iter::execute( dataH, buf0, size, 32 ); + RadixSort32::execute( dataC, buf2, size, 32 ); + + buf2.read( buf1.m_ptr, size ); + DeviceUtils::waitForCompletion( deviceGPU ); +// for(int i=0; i::deallocate( dataH ); + RadixSort32::deallocate( dataC ); + + TEST_REPORT( "RadixSort32Test" ); +} + +template +void radixSortKeyValue32Test( Device* deviceGPU, Device* deviceHost ) +{ + TEST_INIT; + ADLASSERT( type == deviceGPU->m_type ); + + int maxSize = 1024*256; + + // Host buffers + HostBuffer buf0( deviceHost, maxSize ); // Buffer for keys in host and will be sorted by host. + HostBuffer buf1( deviceHost, maxSize ); // Buffer for keys in host and will be saved by device after sorting in device. + HostBuffer buf2( deviceHost, maxSize ); // Buffer for values in host. This buffer is paired with buf0. + HostBuffer buf3( deviceHost, maxSize ); // Buffer for values in host and will be saved by device after sorting. It is paired with buf1. + + // Device buffers + Buffer buf4( deviceGPU, maxSize ); // Buffer for input keys for device. + Buffer buf5( deviceGPU, maxSize ); // Buffer for output keys from device and will be sorted by device. This key data will be saved to buf1 to be compared with a result(buf0) from host. + Buffer buf6( deviceGPU, maxSize ); // Buffer for input values in device. + Buffer buf7( deviceGPU, maxSize ); // Buffer for output values in device. + + RadixSort32::Data* dataH = RadixSort32::allocate( deviceHost, maxSize ); + RadixSort32::Data* dataC = RadixSort32::allocate( deviceGPU, maxSize ); + + int dx = maxSize/NUM_TESTS; + + for(int iter=0; iter::execute( dataH, buf0, buf2, size, 32 ); + RadixSort32::execute( dataC, buf4, buf5, buf6, buf7, size, 32 ); + buf5.read( buf1.m_ptr, size ); + buf7.read( buf3.m_ptr, size ); + + DeviceUtils::waitForCompletion( deviceGPU ); + + for(int i=0; i::deallocate( dataH ); + RadixSort32::deallocate( dataC ); + + TEST_REPORT( "RadixSortKeyValue32Test" ); +} + +#if defined(ADL_ENABLE_DX11) + #define RUN_GPU( func ) func(ddcl); func(dddx); + #define RUN_GPU_TEMPLATE( func ) func( ddcl, ddhost ); func( dddx, ddhost ); + #define RUN_CL_TEMPLATE( func ) func( ddcl, ddhost ); +#else + #define RUN_GPU( func ) func(ddcl); + #define RUN_GPU_TEMPLATE( func ) func( ddcl, ddhost ); +#endif +#define RUN_ALL( func ) RUN_GPU( func ); func(ddhost); + +void runAllTest() +{ + g_nPassed = 0; + g_nFailed = 0; + + + Device* ddcl; + Device* ddhost; +#if defined(ADL_ENABLE_DX11) + Device* dddx; +#endif + + { + DeviceUtils::Config cfg; + + // Choose AMD or NVidia +#ifdef CL_PLATFORM_AMD + cfg.m_vendor = adl::DeviceUtils::Config::VD_AMD; +#endif + +#ifdef CL_PLATFORM_INTEL + cfg.m_vendor = adl::DeviceUtils::Config::VD_INTEL; + cfg.m_type = DeviceUtils::Config::DEVICE_CPU; +#endif + + +#ifdef CL_PLATFORM_NVIDIA + cfg.m_vendor = adl::DeviceUtils::Config::VD_NV; +#endif + + + ddcl = DeviceUtils::allocate( TYPE_CL, cfg ); + ddhost = DeviceUtils::allocate( TYPE_HOST, cfg ); +// cfg.m_type = DeviceUtils::Config::DEVICE_GPU; +#if defined(ADL_ENABLE_DX11) + dddx = DeviceUtils::allocate( TYPE_DX11, cfg ); +#endif + } + + { + char name[128]; + ddcl->getDeviceName( name ); + printf("CL: %s\n", name); +#ifdef ADL_ENABLE_DX11 + dddx->getDeviceName( name ); + printf("DX11: %s\n", name); +#endif + } + + RUN_GPU_TEMPLATE( radixSort32Test ); + RUN_GPU_TEMPLATE( radixSortKeyValue32Test ); + + if (1) + { + RUN_GPU_TEMPLATE( CopyF1Test ); + RUN_GPU_TEMPLATE( CopyF2Test ); + + boundSearchTest( ddhost, ddhost ); +// fillTest( ddhost, ddhost ); +// fillTest( ddcl, ddhost ); + + + + + RUN_GPU_TEMPLATE( boundSearchTest ); + + RUN_GPU_TEMPLATE( fillIntTest ); + RUN_GPU_TEMPLATE( fillInt2Test ); + RUN_GPU_TEMPLATE( fillInt4Test ); + + RUN_ALL( stopwatchTest ); + RUN_ALL( memCpyTest ); +// RUN_GPU( kernelTest ); + RUN_GPU_TEMPLATE( scanTest ); + RUN_GPU_TEMPLATE( radixSortSimpleTest ); + + RUN_GPU_TEMPLATE( radixSortStandardTest ); + + RUN_GPU_TEMPLATE( radixSort32Test ); + +// RUN_GPU_TEMPLATE( boundSearchTest ); + RUN_GPU_TEMPLATE( Copy1F4Test ); + RUN_GPU_TEMPLATE( Copy2F4Test ); + RUN_GPU_TEMPLATE( Copy4F4Test ); + } + + DeviceUtils::deallocate( ddcl ); + DeviceUtils::deallocate( ddhost ); +#if defined(ADL_ENABLE_DX11) + DeviceUtils::deallocate( dddx ); +#endif + + printf("=========\n%d Passed\n%d Failed\n", g_nPassed, g_nFailed); + + +} \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/main.cpp b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/main.cpp new file mode 100644 index 0000000..2f9eaa1 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/main.cpp @@ -0,0 +1,118 @@ +/* +Copyright (c) 2012 Advanced Micro Devices, Inc. + +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. +*/ +//Originally written by Takahiro Harada + + +#include + +#include +#include + +#include "UnitTests.h" +#include "RadixSortBenchmark.h" +#include "LaunchOverheadBenchmark.h" + + +#undef NUM_TESTS + + +struct ConstBuffer +{ + float4 m_a; + float4 m_b; + float4 m_c; +}; + +int main() +{ + if(0) + { // radix sort test + Device* deviceHost; + Device* deviceGPU; + { + DeviceUtils::Config cfg; + + // Choose AMD or NVidia +#ifdef CL_PLATFORM_AMD + cfg.m_vendor = DeviceUtils::Config::VD_AMD; +#endif + +#ifdef CL_PLATFORM_INTEL + cfg.m_vendor = DeviceUtils::Config::VD_INTEL; +#endif + +#ifdef CL_PLATFORM_NVIDIA + cfg.m_vendor = adl::DeviceUtils::Config::VD_NV; +#endif + deviceGPU = DeviceUtils::allocate( TYPE_DX11, cfg ); + deviceHost = DeviceUtils::allocate( TYPE_HOST, cfg ); + } + + { + int maxSize = 512*20; + int size = maxSize; + + HostBuffer buf0( deviceHost, maxSize ); + HostBuffer buf1( deviceHost, maxSize ); + Buffer buf2( deviceGPU, maxSize ); + + RadixSort::Data* dataH = RadixSort::allocate( deviceHost, maxSize, RadixSortBase::SORT_STANDARD ); + RadixSort::Data* dataC = RadixSort::allocate( deviceGPU, maxSize, RadixSortBase::SORT_ADVANCED ); + + { + size = NEXTMULTIPLEOF( size, 512 ); + + for(int i=0; i::execute( dataH, buf0, size ); + RadixSort::execute( dataC, buf2, size ); + + buf2.read( buf1.m_ptr, size ); + DeviceUtils::waitForCompletion( deviceGPU ); + for(int i=0; i::deallocate( dataH ); + RadixSort::deallocate( dataC ); + } + + DeviceUtils::deallocate( deviceHost ); + DeviceUtils::deallocate( deviceGPU ); + } + + if(0) + { + launchOverheadBenchmark(); + } + + if(0) + { + radixSortBenchmark(); + } + + if(0) + { + radixSortBenchmark(); + } + + if(1) + { + runAllTest(); + } + printf("End, press \n"); + getchar(); +} + diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/premake4.lua new file mode 100644 index 0000000..2c16f4b --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/AdlTest/premake4.lua @@ -0,0 +1,4 @@ + +include "AMD" +include "NVIDIA" +include "Intel" \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/benchmark/AMD/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/primitives/benchmark/AMD/premake4.lua new file mode 100644 index 0000000..3704037 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/benchmark/AMD/premake4.lua @@ -0,0 +1,29 @@ + + hasCL = findOpenCL_AMD() + hasDX11 = findDirectX11() + + if (hasCL) then + + project "OpenCL_DX11_radixsort_benchmark_AMD" + + initOpenCL_AMD() + + if (hasDX11) then + initDirectX11() + end + + language "C++" + + kind "ConsoleApp" + targetdir "../../../../bin" + includedirs {"..","../.."} + + links { + "OpenCL" + } + + files { + "../test_large_problem_sorting.cpp" + } + + end \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/benchmark/NVIDIA/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/primitives/benchmark/NVIDIA/premake4.lua new file mode 100644 index 0000000..b959d13 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/benchmark/NVIDIA/premake4.lua @@ -0,0 +1,29 @@ + + hasCL = findOpenCL_NVIDIA() + hasDX11 = findDirectX11() + + if (hasCL) then + + project "OpenCL_DX11_radixsort_benchmark_NVIDIA" + + initOpenCL_NVIDIA() + + if (hasDX11) then + initDirectX11() + end + + language "C++" + + kind "ConsoleApp" + targetdir "../../../../bin" + includedirs {"..","../.."} + + links { + "OpenCL" + } + + files { + "../test_large_problem_sorting.cpp" + } + + end \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/benchmark/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/primitives/benchmark/premake4.lua new file mode 100644 index 0000000..e3cf352 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/benchmark/premake4.lua @@ -0,0 +1,2 @@ +include "AMD" +include "NVIDIA" diff --git a/Extras/RigidBodyGpuPipeline/opencl/primitives/benchmark/test_large_problem_sorting.cpp b/Extras/RigidBodyGpuPipeline/opencl/primitives/benchmark/test_large_problem_sorting.cpp new file mode 100644 index 0000000..b167301 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/primitives/benchmark/test_large_problem_sorting.cpp @@ -0,0 +1,705 @@ +/****************************************************************************** + * Copyright 2010 Duane Merrill + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + * + * + * AUTHORS' REQUEST: + * + * If you use|reference|benchmark this code, please cite our Technical + * Report (http://www.cs.virginia.edu/~dgm4d/papers/RadixSortTR.pdf): + * + * @TechReport{ Merrill:Sorting:2010, + * author = "Duane Merrill and Andrew Grimshaw", + * title = "Revisiting Sorting for GPGPU Stream Architectures", + * year = "2010", + * institution = "University of Virginia, Department of Computer Science", + * address = "Charlottesville, VA, USA", + * number = "CS2010-03" + * } + * + * For more information, see our Google Code project site: + * http://code.google.com/p/back40computing/ + * + * Thanks! + ******************************************************************************/ + +/****************************************************************************** + * Simple test driver program for *large-problem* radix sorting. + * + * Useful for demonstrating how to integrate radix sorting into + * your application + ******************************************************************************/ + +/****************************************************************************** + * Converted from CUDA to OpenCL/DirectCompute by Erwin Coumans + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#define BUFFERSIZE_WORKAROUND + +//#include +#include +/********************** +* +*/ + +#include "Adl/Adl.h" +#include "AdlPrimitives/Sort/RadixSort32.h" +#include "AdlPrimitives/Sort/SortData.h" + +using namespace adl; + + +/*********************** +* +*/ + +bool g_verbose; + + +/****************************************************************************** + * Routines + ******************************************************************************/ + + +/** + * Keys-only sorting. Uses the GPU to sort the specified vector of elements for the given + * number of iterations, displaying runtime information. + * + * @param[in] num_elements + * Size in elements of the vector to sort + * @param[in] h_keys + * Vector of keys to sort + * @param[in] iterations + * Number of times to invoke the GPU sorting primitive + * @param[in] cfg + * Config + */ +template +void TimedSort( + unsigned int num_elements, + K *h_keys, + unsigned int iterations, const DeviceUtils::Config& cfg) +{ + std::string sType = "No type selected"; + + if (type == TYPE_CL) + sType = "OpenCL"; + else if (type == TYPE_DX11) + sType = "DX11"; + + printf("Keys-only, %s, %d iterations, %d elements\n", sType.c_str(), iterations, num_elements); + + int max_elements = num_elements; + +#ifdef BUFFERSIZE_WORKAROUND + if (max_elements < 1024*256) + max_elements = 1024*256; +#endif + + // Allocate device storage + Device* deviceData = NULL; + + if ( type == TYPE_CL ) + deviceData = new DeviceCL(); +#ifdef ADL_ENABLE_DX11 + else if ( type == TYPE_DX11 ) + deviceData = new DeviceDX11(); +#endif //ADL_ENABLE_DX11 + + deviceData->initialize(cfg); + + RadixSort32::Data* planData = RadixSort32::allocate( deviceData, max_elements); + + { + Buffer keysInOut(deviceData,max_elements); + + // Create sorting enactor + keysInOut.write(h_keys,num_elements); + DeviceUtils::waitForCompletion( deviceData); + + RadixSort32::execute( planData,keysInOut,num_elements, 32); + DeviceUtils::waitForCompletion( deviceData); + + // Perform the timed number of sorting iterations + double elapsed = 0; + float duration = 0; + StopwatchHost watch; + watch.init(deviceData); + + watch.start(); + + for (int i = 0; i < iterations; i++) + { + + // Move a fresh copy of the problem into device storage + keysInOut.write(h_keys,num_elements); + DeviceUtils::waitForCompletion( deviceData); + + // Start GPU timing record + watch.start(); + + // Call the sorting API routine + RadixSort32::execute( planData,keysInOut,num_elements, 32); + DeviceUtils::waitForCompletion( deviceData); + + watch.stop(); + duration = watch.getMs(); + + // End GPU timing record + elapsed += (double) duration; + } + + // Display timing information + double avg_runtime = elapsed / iterations; + // double throughput = ((double) num_elements) / avg_runtime / 1000.0 / 1000.0; + // printf(", %f GPU ms, %f x10^9 elts/sec\n", avg_runtime, throughput); + double throughput = ((double) num_elements) / avg_runtime / 1000.0 ; + printf(", %f GPU ms, %f x10^6 elts/sec\n", avg_runtime, throughput); + + // Copy out data + keysInOut.read(h_keys,num_elements); + + DeviceUtils::waitForCompletion( deviceData); + + } + // Free allocated memory + RadixSort32::deallocate( planData); + delete deviceData; + // Clean up events +} + +/** + * Key-value sorting. Uses the GPU to sort the specified vector of elements for the given + * number of iterations, displaying runtime information. + * + * @param[in] num_elements + * Size in elements of the vector to sort + * @param[in] h_keys + * Vector of keys to sort + * @param[in,out] h_values + * Vector of values to sort + * @param[in] iterations + * Number of times to invoke the GPU sorting primitive + * @param[in] cfg + * Config + */ +template +void TimedSort( + unsigned int num_elements, + K *h_keys, + V *h_values, + unsigned int iterations, const DeviceUtils::Config& cfg) +{ + std::string sType = "No type selected"; + + if (type == TYPE_CL) + sType = "OpenCL"; + else if (type == TYPE_DX11) + sType = "DX11"; + + printf("Key-values, %s, %d iterations, %d elements\n", sType.c_str(), iterations, num_elements); + + int max_elements = num_elements; + +#ifdef BUFFERSIZE_WORKAROUND + if (max_elements < 1024*256) + max_elements = 1024*256; +#endif + + // Allocate device storage + Device* deviceData = NULL; + + if ( type == TYPE_CL ) + deviceData = new DeviceCL(); +#ifdef ADL_ENABLE_DX11 + else if ( type == TYPE_DX11 ) + deviceData = new DeviceDX11(); +#endif //ADL_ENABLE_DX11 + + deviceData->initialize(cfg); + RadixSort32::Data* planData = RadixSort32::allocate( deviceData, max_elements); + { + Buffer keysIn(deviceData,max_elements); + Buffer valuesIn(deviceData,max_elements); + + Buffer keysOut(deviceData,max_elements); + Buffer valuesOut(deviceData,max_elements); + + //printf("Key-values, %d iterations, %d elements", iterations, num_elements); + + // Create sorting enactor + keysIn.write(h_keys,num_elements); + DeviceUtils::waitForCompletion( deviceData); + valuesIn.write(h_values,num_elements); + DeviceUtils::waitForCompletion( deviceData); + + + // Perform a single sorting iteration to allocate memory, prime code caches, etc. + //RadixSort::execute( planData, buffer, num_elements ); + + //RadixSort32::execute( planData, keysIn,keysOut, valuesIn,valuesOut, num_elements, 32); + RadixSort32::execute( planData, keysIn,keysOut, valuesIn,valuesOut, num_elements, 32); + DeviceUtils::waitForCompletion( deviceData); + + // Perform the timed number of sorting iterations + double elapsed = 0; + float duration = 0; + StopwatchHost watch; + watch.init(deviceData); + + watch.start(); + + for (int i = 0; i < iterations; i++) + { + + // Move a fresh copy of the problem into device storage + keysIn.write(h_keys,num_elements); + valuesIn.write(h_values,num_elements); + + DeviceUtils::waitForCompletion( deviceData); + + // Start GPU timing record + watch.start(); + + // Call the sorting API routine + + RadixSort32::execute( planData, keysIn,keysOut, valuesIn,valuesOut, num_elements, 32); + + DeviceUtils::waitForCompletion( deviceData); + + watch.stop(); + duration = watch.getMs(); + + // End GPU timing record + elapsed += (double) duration; + } + + // Display timing information + double avg_runtime = elapsed / iterations; + // double throughput = ((double) num_elements) / avg_runtime / 1000.0 / 1000.0; + // printf(", %f GPU ms, %f x10^9 elts/sec\n", avg_runtime, throughput); + double throughput = ((double) num_elements) / avg_runtime / 1000.0 ; + printf(", %f GPU ms, %f x10^6 elts/sec\n", avg_runtime, throughput); + + //memset(h_keys,1,num_elements); + //memset(h_values,1,num_elements); + // Copy out data + keysOut.read(h_keys,num_elements); + valuesOut.read(h_values,num_elements); + + DeviceUtils::waitForCompletion( deviceData); + } + + // Free allocated memory + RadixSort32::deallocate( planData); + delete deviceData; + // Clean up events + +} + + + +/** + * Generates random 32-bit keys. + * + * We always take the second-order byte from rand() because the higher-order + * bits returned by rand() are commonly considered more uniformly distributed + * than the lower-order bits. + * + * We can decrease the entropy level of keys by adopting the technique + * of Thearling and Smith in which keys are computed from the bitwise AND of + * multiple random samples: + * + * entropy_reduction | Effectively-unique bits per key + * ----------------------------------------------------- + * -1 | 0 + * 0 | 32 + * 1 | 25.95 + * 2 | 17.41 + * 3 | 10.78 + * 4 | 6.42 + * ... | ... + * + */ +template +void RandomBits(K &key, int entropy_reduction = 0, int lower_key_bits = sizeof(K) * 8) +{ + const unsigned int NUM_UCHARS = (sizeof(K) + sizeof(unsigned char) - 1) / sizeof(unsigned char); + unsigned char key_bits[NUM_UCHARS]; + + do { + + for (int j = 0; j < NUM_UCHARS; j++) { + unsigned char quarterword = 0xff; + for (int i = 0; i <= entropy_reduction; i++) { + quarterword &= (rand() >> 7); + } + key_bits[j] = quarterword; + } + + if (lower_key_bits < sizeof(K) * 8) { + unsigned long long base = 0; + memcpy(&base, key_bits, sizeof(K)); + base &= (1 << lower_key_bits) - 1; + memcpy(key_bits, &base, sizeof(K)); + } + + memcpy(&key, key_bits, sizeof(K)); + + } while (key != key); // avoids NaNs when generating random floating point numbers +} + + +/****************************************************************************** + * Templated routines for printing keys/values to the console + ******************************************************************************/ + +template +void PrintValue(T val) { + printf("%d", val); +} + +template<> +void PrintValue(float val) { + printf("%f", val); +} + +template<> +void PrintValue(double val) { + printf("%f", val); +} + +template<> +void PrintValue(unsigned char val) { + printf("%u", val); +} + +template<> +void PrintValue(unsigned short val) { + printf("%u", val); +} + +template<> +void PrintValue(unsigned int val) { + printf("%u", val); +} + +template<> +void PrintValue(long val) { + printf("%ld", val); +} + +template<> +void PrintValue(unsigned long val) { + printf("%lu", val); +} + +template<> +void PrintValue(long long val) { + printf("%lld", val); +} + +template<> +void PrintValue(unsigned long long val) { + printf("%llu", val); +} + + + +/** + * Compares the equivalence of two arrays + */ +template +int CompareResults(T* computed, T* reference, SizeT len, bool verbose = true) +{ + printf("\n"); + for (SizeT i = 0; i < len; i++) { + + if (computed[i] != reference[i]) { + printf("INCORRECT: [%lu]: ", (unsigned long) i); + PrintValue(computed[i]); + printf(" != "); + PrintValue(reference[i]); + + if (verbose) { + printf("\nresult[..."); + for (size_t j = (i >= 5) ? i - 5 : 0; (j < i + 5) && (j < len); j++) { + PrintValue(computed[j]); + printf(", "); + } + printf("...]"); + printf("\nreference[..."); + for (size_t j = (i >= 5) ? i - 5 : 0; (j < i + 5) && (j < len); j++) { + PrintValue(reference[j]); + printf(", "); + } + printf("...]"); + } + + return 1; + } + } + + printf("CORRECT\n"); + return 0; +} + +/** + * Creates an example sorting problem whose keys is a vector of the specified + * number of K elements, values of V elements, and then dispatches the problem + * to the GPU for the given number of iterations, displaying runtime information. + * + * @param[in] iterations + * Number of times to invoke the GPU sorting primitive + * @param[in] num_elements + * Size in elements of the vector to sort + * @param[in] cfg + * Config + */ +template +void TestSort( + unsigned int iterations, + int num_elements, + bool keys_only, const DeviceUtils::Config& cfg) +{ + // Allocate the sorting problem on the host and fill the keys with random bytes + + K *h_keys = NULL; + K *h_reference_keys = NULL; + V *h_values = NULL; + h_keys = (K*) malloc(num_elements * sizeof(K)); + h_reference_keys = (K*) malloc(num_elements * sizeof(K)); + if (!keys_only) h_values = (V*) malloc(num_elements * sizeof(V)); + + + // Use random bits + for (unsigned int i = 0; i < num_elements; ++i) { + RandomBits(h_keys[i], 0); + //h_keys[i] = 0xffffffffu-i; + if (!keys_only) + h_values[i] = h_keys[i];//0xffffffffu-i; + + h_reference_keys[i] = h_keys[i]; + } + + // Run the timing test + if (keys_only) { + TimedSort(num_elements, h_keys, iterations, cfg); + } else { + TimedSort(num_elements, h_keys, h_values, iterations, cfg); + } + +// cudaThreadSynchronize(); + + // Display sorted key data + if (g_verbose) { + printf("\n\nKeys:\n"); + for (int i = 0; i < num_elements; i++) { + PrintValue(h_keys[i]); + printf(", "); + } + printf("\n\n"); + } + + // Verify solution + std::sort(h_reference_keys, h_reference_keys + num_elements); + CompareResults(h_keys, h_reference_keys, num_elements, true); + printf("\n"); + fflush(stdout); + + // Free our allocated host memory + if (h_keys != NULL) free(h_keys); + if (h_values != NULL) free(h_values); +} + + + +/** + * Displays the commandline usage for this tool + */ +void Usage() +{ + printf("\ntest_large_problem_sorting [--device=] [--v] [--i=] [--n=] [--keys-only]\n"); + printf("\n"); + printf("\t--v\tDisplays sorted results to the console.\n"); + printf("\n"); + printf("\t--i\tPerforms the sorting operation times\n"); + printf("\t\t\ton the device. Re-copies original input each time. Default = 1\n"); + printf("\n"); + printf("\t--n\tThe number of elements to comprise the sample problem\n"); + printf("\t\t\tDefault = 512\n"); + printf("\n"); + printf("\t--keys-only\tSpecifies that keys are not accommodated by value pairings\n"); + printf("\n"); +} + + +/****************************************************************************** + * Command-line parsing + ******************************************************************************/ +#include +#include +#include + +class CommandLineArgs +{ +protected: + + std::map pairs; + +public: + + // Constructor + CommandLineArgs(int argc, char **argv) + { + using namespace std; + + for (int i = 1; i < argc; i++) + { + string arg = argv[i]; + + if ((arg[0] != '-') || (arg[1] != '-')) { + continue; + } + + string::size_type pos; + string key, val; + if ((pos = arg.find( '=')) == string::npos) { + key = string(arg, 2, arg.length() - 2); + val = ""; + } else { + key = string(arg, 2, pos - 2); + val = string(arg, pos + 1, arg.length() - 1); + } + pairs[key] = val; + } + } + + bool CheckCmdLineFlag(const char* arg_name) + { + using namespace std; + map::iterator itr; + if ((itr = pairs.find(arg_name)) != pairs.end()) { + return true; + } + return false; + } + + template + void GetCmdLineArgument(const char *arg_name, T &val); + + int ParsedArgc() + { + return pairs.size(); + } +}; + +template +void CommandLineArgs::GetCmdLineArgument(const char *arg_name, T &val) +{ + using namespace std; + map::iterator itr; + if ((itr = pairs.find(arg_name)) != pairs.end()) { + istringstream strstream(itr->second); + strstream >> val; + } +} + +template <> +void CommandLineArgs::GetCmdLineArgument(const char* arg_name, char* &val) +{ + using namespace std; + map::iterator itr; + if ((itr = pairs.find(arg_name)) != pairs.end()) { + + string s = itr->second; + val = (char*) malloc(sizeof(char) * (s.length() + 1)); + strcpy(val, s.c_str()); + + } else { + val = NULL; + } +} + + + + + +/****************************************************************************** + * Main + ******************************************************************************/ + +int main( int argc, char** argv) +{ + + //srand(time(NULL)); + srand(0); // presently deterministic + + unsigned int num_elements = 1024*1024*12;//16*1024;//8*524288;//2048;//512;//524288; + unsigned int iterations = 10; + bool keys_only; + + // + // Check command line arguments + // + + CommandLineArgs args(argc,argv); + + if (args.CheckCmdLineFlag("help")) + { + Usage(); + return 0; + } + + args.GetCmdLineArgument("i", iterations); + args.GetCmdLineArgument("n", num_elements); + keys_only = args.CheckCmdLineFlag("keys-only"); + g_verbose = args.CheckCmdLineFlag("v"); + + DeviceUtils::Config cfg; + + // Choose AMD or NVidia +#ifdef CL_PLATFORM_AMD + cfg.m_vendor = DeviceUtils::Config::VD_AMD; +#endif + +#ifdef CL_PLATFORM_NVIDIA + cfg.m_vendor = DeviceUtils::Config::VD_NV; +#endif + + TestSort( + iterations, + num_elements, + keys_only, cfg); + +#ifdef ADL_ENABLE_DX11 + TestSort( + iterations, + num_elements, + keys_only, cfg); +#endif //ADL_ENABLE_DX11 +} + + + diff --git a/Extras/RigidBodyGpuPipeline/opencl/vector_add/AMD/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/vector_add/AMD/premake4.lua new file mode 100644 index 0000000..4b5e39b --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/vector_add/AMD/premake4.lua @@ -0,0 +1,21 @@ + + hasCL = findOpenCL_AMD() + + if (hasCL) then + + project "OpenCL_VectorAdd_AMD" + + initOpenCL_AMD() + + language "C++" + + kind "ConsoleApp" + targetdir "../../../bin" + + files { + "../main.cpp", + "../../basic_initialize/btOpenCLUtils.cpp", + "../../basic_initialize/btOpenCLUtils.h" + } + + end \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/vector_add/Intel/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/vector_add/Intel/premake4.lua new file mode 100644 index 0000000..0f1be98 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/vector_add/Intel/premake4.lua @@ -0,0 +1,23 @@ + + hasCL = findOpenCL_Intel() + + if (hasCL) then + + project "OpenCL_intialize_Intel" + + initOpenCL_Intel() + + language "C++" + + kind "ConsoleApp" + targetdir "../../../bin" + +-- includedirs {"..","../../../../include/gpu_research"} + + files { + "../main.cpp", + "../btOpenCLUtils.cpp", + "../btOpenCLUtils.h" + } + + end \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/vector_add/NVIDIA/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/vector_add/NVIDIA/premake4.lua new file mode 100644 index 0000000..e7c1d15 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/vector_add/NVIDIA/premake4.lua @@ -0,0 +1,23 @@ + + hasCL = findOpenCL_NVIDIA() + + if (hasCL) then + + project "OpenCL_intialize_NVIDIA" + + initOpenCL_NVIDIA() + + language "C++" + + kind "ConsoleApp" + targetdir "../../../bin" + +-- includedirs {"..","../../../../include/gpu_research"} + + files { + "../main.cpp", + "../btOpenCLUtils.cpp", + "../btOpenCLUtils.h" + } + + end \ No newline at end of file diff --git a/Extras/RigidBodyGpuPipeline/opencl/vector_add/VectorAddKernels.cl b/Extras/RigidBodyGpuPipeline/opencl/vector_add/VectorAddKernels.cl new file mode 100644 index 0000000..2ff1782 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/vector_add/VectorAddKernels.cl @@ -0,0 +1,16 @@ + + +__kernel void VectorAdd(__global const float8* a, __global const float8* b, __global float8* c, int numElements) +{ + // get oct-float index into global data array + int iGID = get_global_id(0); + if (iGID>=numElements) + return; + + float8 aGID = a[iGID]; + float8 bGID = b[iGID]; + + float8 result = aGID + bGID; + // write back out to GMEM + c[iGID] = result; +} diff --git a/Extras/RigidBodyGpuPipeline/opencl/vector_add/VectorAddKernels.h b/Extras/RigidBodyGpuPipeline/opencl/vector_add/VectorAddKernels.h new file mode 100644 index 0000000..fb7e2fc --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/vector_add/VectorAddKernels.h @@ -0,0 +1,18 @@ +static const char* vectorAddCL= \ +"\n" +"\n" +"__kernel void VectorAdd(__global const float8* a, __global const float8* b, __global float8* c, int numElements)\n" +"{\n" +" // get oct-float index into global data array\n" +" int iGID = get_global_id(0);\n" +" if (iGID>=numElements)\n" +" return;\n" +"\n" +" float8 aGID = a[iGID];\n" +" float8 bGID = b[iGID];\n" +"\n" +" float8 result = aGID + bGID;\n" +" // write back out to GMEM\n" +" c[iGID] = result;\n" +"}\n" +; diff --git a/Extras/RigidBodyGpuPipeline/opencl/vector_add/main.cpp b/Extras/RigidBodyGpuPipeline/opencl/vector_add/main.cpp new file mode 100644 index 0000000..54afa4e --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/vector_add/main.cpp @@ -0,0 +1,367 @@ + +///VectorAdd sample, from the NVidia JumpStart Guide +///http://developer.download.nvidia.com/OpenCL/NVIDIA_OpenCL_JumpStart_Guide.pdf + +///Instead of #include we include +///Apart from this include file, all other code should compile and work on OpenCL compliant implementation + + +//#define LOAD_FROM_FILE + +#ifdef __APPLE__ + #include +#else + #include +#endif //__APPLE__ + +#include +#include +#include +#include + +#define GRID3DOCL_CHECKERROR(a, b) if((a)!=(b)) { printf("3D GRID OCL Error : %d\n", (a)); btAssert((a) == (b)); } +size_t wgSize; + +#include "VectorAddKernels.h" + + + +char* loadProgSource(const char* cFilename, const char* cPreamble, size_t* szFinalLength) +{ + // locals + FILE* pFileStream = NULL; + size_t szSourceLength; + + // open the OpenCL source code file + pFileStream = fopen(cFilename, "rb"); + if(pFileStream == 0) + { + return NULL; + } + + size_t szPreambleLength = strlen(cPreamble); + + // get the length of the source code + fseek(pFileStream, 0, SEEK_END); + szSourceLength = ftell(pFileStream); + fseek(pFileStream, 0, SEEK_SET); + + // allocate a buffer for the source code string and read it in + char* cSourceString = (char *)malloc(szSourceLength + szPreambleLength + 1); + memcpy(cSourceString, cPreamble, szPreambleLength); + fread((cSourceString) + szPreambleLength, szSourceLength, 1, pFileStream); + + // close the file and return the total length of the combined (preamble + source) string + fclose(pFileStream); + if(szFinalLength != 0) + { + *szFinalLength = szSourceLength + szPreambleLength; + } + cSourceString[szSourceLength + szPreambleLength] = '\0'; + + return cSourceString; +} + +size_t workitem_size[3]; + +void printDevInfo(cl_device_id device) +{ + char device_string[1024]; + + clGetDeviceInfo(device, CL_DEVICE_NAME, sizeof(device_string), &device_string, NULL); + printf( " Device %s:\n", device_string); + + // CL_DEVICE_INFO + cl_device_type type; + clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(type), &type, NULL); + if( type & CL_DEVICE_TYPE_CPU ) + printf(" CL_DEVICE_TYPE:\t\t%s\n", "CL_DEVICE_TYPE_CPU"); + if( type & CL_DEVICE_TYPE_GPU ) + printf( " CL_DEVICE_TYPE:\t\t%s\n", "CL_DEVICE_TYPE_GPU"); + if( type & CL_DEVICE_TYPE_ACCELERATOR ) + printf( " CL_DEVICE_TYPE:\t\t%s\n", "CL_DEVICE_TYPE_ACCELERATOR"); + if( type & CL_DEVICE_TYPE_DEFAULT ) + printf( " CL_DEVICE_TYPE:\t\t%s\n", "CL_DEVICE_TYPE_DEFAULT"); + + // CL_DEVICE_MAX_COMPUTE_UNITS + cl_uint compute_units; + clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(compute_units), &compute_units, NULL); + printf( " CL_DEVICE_MAX_COMPUTE_UNITS:\t%d\n", compute_units); + + // CL_DEVICE_MAX_WORK_GROUP_SIZE + + clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(workitem_size), &workitem_size, NULL); + printf( " CL_DEVICE_MAX_WORK_ITEM_SIZES:\t%zu / %zu / %zu \n", workitem_size[0], workitem_size[1], workitem_size[2]); + +} + + + + +// Main function +// ********************************************************************* +int main(int argc, char **argv) +{ + void *srcA, *srcB, *dst; // Host buffers for OpenCL test + cl_context cxGPUContext; // OpenCL context + cl_command_queue cqCommandQue; // OpenCL command que + cl_device_id* cdDevices; // OpenCL device list + cl_program cpProgram; // OpenCL program + cl_kernel ckKernel; // OpenCL kernel + cl_mem cmMemObjs[3]; // OpenCL memory buffer objects: 3 for device + size_t szGlobalWorkSize[1]; // 1D var for Total # of work items + size_t szLocalWorkSize[1]; // 1D var for # of work items in the work group + size_t szParmDataBytes; // Byte size of context information + cl_int ciErr1, ciErr2; // Error code var + + + int iTestN = 100000 * 8; // Size of Vectors to process + + int actualGlobalSize = iTestN / 8; + + + // set Global and Local work size dimensions + szGlobalWorkSize[0] = iTestN >> 3; // do 8 computations per work item + szLocalWorkSize[0]= iTestN>>3; + + + // Allocate and initialize host arrays + srcA = (void *)malloc (sizeof(cl_float) * iTestN); + srcB = (void *)malloc (sizeof(cl_float) * iTestN); + dst = (void *)malloc (sizeof(cl_float) * iTestN); + + int i; + + // Initialize arrays with some values + for (i=0;i processing outside of the buffer + //make sure to check kernel + } + + size_t globalThreads[] = {num_t * workgroupSize}; + size_t localThreads[] = {workgroupSize}; + + + localWorkSize[0] = workgroupSize; + globalWorkSize[0] = num_t * workgroupSize; + localWorkSize[1] = 1; + globalWorkSize[1] = 1; + + // Copy input data from host to GPU and launch kernel + ciErr1 |= clEnqueueNDRangeKernel(cqCommandQue, ckKernel, 1, NULL, globalThreads, localThreads, 0, NULL, NULL); + + } + + if (ciErrNum != CL_SUCCESS) + { + printf("cannot clEnqueueNDRangeKernel\n"); + exit(0); + } + + clFinish(cqCommandQue); + // Read back results and check accumulated errors + ciErr1 |= clEnqueueReadBuffer(cqCommandQue, cmMemObjs[2], CL_TRUE, 0, sizeof(cl_float8) * szGlobalWorkSize[0], dst, 0, NULL, NULL); + + // Release kernel, program, and memory objects + // NOTE: Most properly this should be done at any of the exit points above, but it is omitted elsewhere for clarity. + free(cdDevices); + clReleaseKernel(ckKernel); + clReleaseProgram(cpProgram); + clReleaseCommandQueue(cqCommandQue); + clReleaseContext(cxGPUContext); + + + // print the results + int iErrorCount = 0; + for (i = 0; i < iTestN; i++) + { + if (((float*)dst)[i] != ((float*)srcA)[i]+((float*)srcB)[i]) + iErrorCount++; + } + + if (iErrorCount) + { + printf("MiniCL validation FAILED\n"); + } else + { + printf("MiniCL validation SUCCESSFULL\n"); + } + // Free host memory, close log and return success + for (i = 0; i < 3; i++) + { + clReleaseMemObject(cmMemObjs[i]); + } + + free(srcA); + free(srcB); + free (dst); + printf("Press ENTER to quit\n"); + getchar(); +} + + diff --git a/Extras/RigidBodyGpuPipeline/opencl/vector_add/premake4.lua b/Extras/RigidBodyGpuPipeline/opencl/vector_add/premake4.lua new file mode 100644 index 0000000..56a16ee --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/vector_add/premake4.lua @@ -0,0 +1,4 @@ + + include "AMD" +-- include "Intel" +-- include "NVIDIA" diff --git a/Extras/RigidBodyGpuPipeline/opencl/vector_add/stringify.py b/Extras/RigidBodyGpuPipeline/opencl/vector_add/stringify.py new file mode 100644 index 0000000..e79e281 --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/vector_add/stringify.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +import sys +import os +import shutil + +arg = sys.argv[1] +fh = open(arg) + +print 'static const char* '+sys.argv[2]+'= \\' +for line in fh.readlines(): + a = line.strip('\n') + print '"'+a+'\\n"' +print ';' diff --git a/Extras/RigidBodyGpuPipeline/opencl/vector_add/stringifyVectorAddKernel.bat b/Extras/RigidBodyGpuPipeline/opencl/vector_add/stringifyVectorAddKernel.bat new file mode 100644 index 0000000..9b3913d --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/opencl/vector_add/stringifyVectorAddKernel.bat @@ -0,0 +1,8 @@ +stringify.py VectorAddKernels.cl vectorAddCL >VectorAddKernels.h + + + + +@echo Warning: +@echo You might still need to find/replace for \\n (due to macros) and replace #include statements by their content +pause diff --git a/Extras/RigidBodyGpuPipeline/readme.txt b/Extras/RigidBodyGpuPipeline/readme.txt new file mode 100644 index 0000000..914da0e --- /dev/null +++ b/Extras/RigidBodyGpuPipeline/readme.txt @@ -0,0 +1,8 @@ +This GPU rigid body pipeline is only tested under Windows with the latest GPUs and GPU/OpenCL drivers. +AMD Radeon 5970, preferably Tahiti 7970 with Catalyst 12.x or NVIDIA 470 with latest drivers (at least 290.53) + +Click on the build/vs2010.bat file to generation Visual Studio project files. +It requires either the AMD APP SDK 2.6 or later, or NVIDIA CUDA SDK. + +Check out the videos at http://youtube.com/erwincoumans or the slides at http://github.com/erwincoumans/experiments/downloads + diff --git a/Extras/Serialize/BlenderSerialize/CMakeLists.txt b/Extras/Serialize/BlenderSerialize/CMakeLists.txt new file mode 100644 index 0000000..5b74d74 --- /dev/null +++ b/Extras/Serialize/BlenderSerialize/CMakeLists.txt @@ -0,0 +1,7 @@ +INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/src +${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletFileLoader +${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BlenderSerialize +) + +ADD_LIBRARY(BlenderSerialize dna249.cpp dna249-64bit.cpp bBlenderFile.cpp bBlenderFile.h bMain.cpp bMain.h ) diff --git a/Extras/Serialize/BlenderSerialize/bBlenderFile.cpp b/Extras/Serialize/BlenderSerialize/bBlenderFile.cpp new file mode 100644 index 0000000..7a4da96 --- /dev/null +++ b/Extras/Serialize/BlenderSerialize/bBlenderFile.cpp @@ -0,0 +1,225 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +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 "bBlenderFile.h" +#include "bMain.h" +#include "bDefines.h" +#include "bDNA.h" +#include +#include + +// 32 && 64 bit versions +extern unsigned char DNAstr[]; +extern int DNAlen; + +extern unsigned char DNAstr64[]; +extern int DNAlen64; + + +using namespace bParse; + +bBlenderFile::bBlenderFile(const char* fileName) +:bFile(fileName, "BLENDER") +{ + mMain= new bMain(this, fileName, mVersion); +} + + + +bBlenderFile::bBlenderFile(char *memoryBuffer, int len) +:bFile(memoryBuffer,len, "BLENDER"), +mMain(0) +{ + mMain= new bMain(this, "memoryBuf", mVersion); +} + + +bBlenderFile::~bBlenderFile() +{ + delete mMain; +} + + +bMain* bBlenderFile::getMain() +{ + return mMain; +} + +// ----------------------------------------------------- // +void bBlenderFile::parseData() +{ + printf ("Building datablocks\n"); + printf ("Chunk size = %d\n",CHUNK_HEADER_LEN); + printf ("File chunk size = %d\n", ChunkUtils::getOffset(mFlags)); + + const bool swap = (mFlags&FD_ENDIAN_SWAP)!=0; + + + + char *dataPtr = mFileBuffer+mDataStart; + + bChunkInd dataChunk; + dataChunk.code = 0; + + + //dataPtr += ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags); + int seek = getNextBlock(&dataChunk, dataPtr, mFlags); + //dataPtr += ChunkUtils::getOffset(mFlags); + char *dataPtrHead = 0; + + while (dataChunk.code != DNA1) + { + + + + + // one behind + if (dataChunk.code == SDNA) break; + //if (dataChunk.code == DNA1) break; + + // same as (BHEAD+DATA dependency) + dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags); + char *id = readStruct(dataPtrHead, dataChunk); + + // lookup maps + if (id) + { + m_chunkPtrPtrMap.insert(dataChunk.oldPtr, dataChunk); + mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)id); + + m_chunks.push_back(dataChunk); + // block it + bListBasePtr *listID = mMain->getListBasePtr(dataChunk.code); + if (listID) + listID->push_back((bStructHandle*)id); + } + + if (dataChunk.code == GLOB) + { + m_glob = (bStructHandle*) id; + } + + // next please! + dataPtr += seek; + + seek = getNextBlock(&dataChunk, dataPtr, mFlags); + if (seek < 0) + break; + } + +} + +void bBlenderFile::addDataBlock(char* dataBlock) +{ + mMain->addDatablock(dataBlock); +} + + + + + +// 32 && 64 bit versions +extern unsigned char DNAstr[]; +extern int DNAlen; + +//unsigned char DNAstr[]={0}; +//int DNAlen=0; + + +extern unsigned char DNAstr64[]; +extern int DNAlen64; + + +void bBlenderFile::writeDNA(FILE* fp) +{ + + bChunkInd dataChunk; + dataChunk.code = DNA1; + dataChunk.dna_nr = 0; + dataChunk.nr = 1; + + if (VOID_IS_8) + { + dataChunk.len = DNAlen64; + dataChunk.oldPtr = DNAstr64; + fwrite(&dataChunk,sizeof(bChunkInd),1,fp); + fwrite(DNAstr64, DNAlen64,1,fp); + } + else + { + dataChunk.len = DNAlen; + dataChunk.oldPtr = DNAstr; + fwrite(&dataChunk,sizeof(bChunkInd),1,fp); + fwrite(DNAstr, DNAlen,1,fp); + } +} + +void bBlenderFile::parse(bool verboseDumpAllTypes) +{ + if (VOID_IS_8) + { + parseInternal(verboseDumpAllTypes,(char*)DNAstr64,DNAlen64); + } + else + { + parseInternal(verboseDumpAllTypes,(char*)DNAstr,DNAlen); + } +} + +// experimental +int bBlenderFile::write(const char* fileName, bool fixupPointers) +{ + FILE *fp = fopen(fileName, "wb"); + if (fp) + { + char header[SIZEOFBLENDERHEADER] ; + memcpy(header, m_headerString, 7); + int endian= 1; + endian= ((char*)&endian)[0]; + + if (endian) + { + header[7] = '_'; + } else + { + header[7] = '-'; + } + if (VOID_IS_8) + { + header[8]='V'; + } else + { + header[8]='v'; + } + + header[9] = '2'; + header[10] = '4'; + header[11] = '9'; + + fwrite(header,SIZEOFBLENDERHEADER,1,fp); + + writeChunks(fp, fixupPointers); + + writeDNA(fp); + + fclose(fp); + + } else + { + printf("Error: cannot open file %s for writing\n",fileName); + return 0; + } + return 1; +} \ No newline at end of file diff --git a/Extras/Serialize/BlenderSerialize/bBlenderFile.h b/Extras/Serialize/BlenderSerialize/bBlenderFile.h new file mode 100644 index 0000000..0410750 --- /dev/null +++ b/Extras/Serialize/BlenderSerialize/bBlenderFile.h @@ -0,0 +1,63 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +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 B_BLENDER_FILE_H +#define B_BLENDER_FILE_H + + +#include "bFile.h" + +namespace bParse { + + // ----------------------------------------------------- // + class bBlenderFile : public bFile + { + + protected: + bMain* mMain; + + bStructHandle* m_glob; + + + public: + + bBlenderFile(const char* fileName); + + bBlenderFile(char *memoryBuffer, int len); + + virtual ~bBlenderFile(); + + bMain* getMain(); + + virtual void addDataBlock(char* dataBlock); + + bStructHandle* getFileGlobal() + { + return m_glob; + } + + // experimental + virtual int write(const char* fileName, bool fixupPointers = false); + + virtual void parse(bool verboseDumpAllTypes); + + virtual void parseData(); + + virtual void writeDNA(FILE* fp); + + }; +}; + +#endif //B_BLENDER_FILE_H diff --git a/Extras/Serialize/BlenderSerialize/bMain.cpp b/Extras/Serialize/BlenderSerialize/bMain.cpp new file mode 100644 index 0000000..fa672fb --- /dev/null +++ b/Extras/Serialize/BlenderSerialize/bMain.cpp @@ -0,0 +1,392 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +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 "bMain.h" +#include "bBlenderFile.h" +#include "bDefines.h" +#include "bChunk.h" +#include "bDNA.h" + +using namespace bParse; + + +// ----------------------------------------------------- // +bMain::bMain(bBlenderFile *filePtr, const char *baseName, int fileVersion) + : mFP(filePtr), + mVersion(fileVersion), + mName(baseName) +{ + mData.insert(ID_SCE,bListBasePtr()); + mData.insert(ID_LI,bListBasePtr()); + mData.insert(ID_OB,bListBasePtr()); + mData.insert(ID_ME,bListBasePtr()); + mData.insert(ID_CU,bListBasePtr()); + mData.insert(ID_MB,bListBasePtr()); + mData.insert(ID_MA,bListBasePtr()); + mData.insert(ID_TE,bListBasePtr()); + mData.insert(ID_IM,bListBasePtr()); + mData.insert(ID_WV,bListBasePtr()); + mData.insert(ID_LT,bListBasePtr()); + mData.insert(ID_LA,bListBasePtr()); + mData.insert(ID_CA,bListBasePtr()); + mData.insert(ID_IP,bListBasePtr()); + mData.insert(ID_KE,bListBasePtr()); + mData.insert(ID_WO,bListBasePtr()); + mData.insert(ID_SCR,bListBasePtr()); + mData.insert(ID_VF,bListBasePtr()); + mData.insert(ID_TXT,bListBasePtr()); + mData.insert(ID_SO,bListBasePtr()); + mData.insert(ID_GR,bListBasePtr()); + mData.insert(ID_AR,bListBasePtr()); + mData.insert(ID_AC,bListBasePtr()); + mData.insert(ID_NT,bListBasePtr()); + mData.insert(ID_BR,bListBasePtr()); + mData.insert(ID_SCRIPT, bListBasePtr()); +} + + +// ----------------------------------------------------- // +bMain::~bMain() +{ + // allocated data blocks! + + int sz = mPool.size(); + for (int i=0;ifirst) + return; + + base->first = mFP->findLibPointer(base->first); + if (!base->first) + { + base->last = 0; + return; + } + + void *prev = 0; + Link *l = (Link*)base->first; + while (l) + { + l->next = mFP->findLibPointer(l->next); + l->prev = l->next; + prev = l->next; + l = (Link*)l->next; + } +} + +// ------------------------------------------------------------// +bListBasePtr* bMain::getListBasePtr(int listBaseCode) +{ + bListBasePtr *ptr = _findCode(listBaseCode); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::_findCode(int code) +{ + + bListBasePtr* lbPtr = mData.find(code); + return lbPtr; +} + + +// ------------------------------------------------------------// +bListBasePtr *bMain::getScene() +{ + bListBasePtr *ptr = _findCode(ID_SCE); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getLibrary() +{ + bListBasePtr *ptr = _findCode(ID_LI); + if (!ptr) + return 0; + return ptr; +} +// ------------------------------------------------------------// +bListBasePtr *bMain::getObject() +{ + bListBasePtr *ptr = _findCode(ID_OB); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getMesh() +{ + bListBasePtr *ptr = _findCode(ID_ME); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getCurve() +{ + bListBasePtr *ptr = _findCode(ID_CU); + if (!ptr) + return 0; + return ptr; +} + + + +// ------------------------------------------------------------// +bListBasePtr *bMain::getMball() +{ + bListBasePtr *ptr = _findCode(ID_MB); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getMat() +{ + bListBasePtr *ptr = _findCode(ID_MA); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getTex() +{ + bListBasePtr *ptr = _findCode(ID_TE); + if (!ptr) + return 0; + return ptr; +} + + +// ------------------------------------------------------------// +bListBasePtr *bMain::getImage() +{ + bListBasePtr *ptr = _findCode(ID_IM); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getWave() +{ + bListBasePtr *ptr = _findCode(ID_WV); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getLatt() +{ + bListBasePtr *ptr = _findCode(ID_LT); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getLamp() +{ + bListBasePtr *ptr = _findCode(ID_LA); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getCamera() +{ + bListBasePtr *ptr = _findCode(ID_CA); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getIpo() +{ + bListBasePtr *ptr = _findCode(ID_IP); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getKey() +{ + bListBasePtr *ptr = _findCode(ID_KE); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getWorld() +{ + bListBasePtr *ptr = _findCode(ID_WO); + if (!ptr) + return 0; + return ptr; +} + + +// ------------------------------------------------------------// +bListBasePtr *bMain::getScreen() +{ + bListBasePtr *ptr = _findCode(ID_SCR); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getScript() +{ + bListBasePtr *ptr = _findCode(ID_SCRIPT); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getVfont() +{ + bListBasePtr *ptr = _findCode(ID_VF); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getText() +{ + bListBasePtr *ptr = _findCode(ID_TXT); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getSound() +{ + bListBasePtr *ptr = _findCode(ID_SO); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getGroup() +{ + bListBasePtr *ptr = _findCode(ID_GR); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getArmature() +{ + bListBasePtr *ptr = _findCode(ID_AR); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getAction() +{ + bListBasePtr *ptr = _findCode(ID_AC); + if (!ptr) + return 0; + return ptr; +} + + +// ------------------------------------------------------------// +bListBasePtr *bMain::getNodetree() +{ + bListBasePtr *ptr = _findCode(ID_NT); + if (!ptr) + return 0; + return ptr; +} + +// ------------------------------------------------------------// +bListBasePtr *bMain::getBrush() +{ + bListBasePtr *ptr = _findCode(ID_BR); + if (!ptr) + return 0; + return ptr; +} + + + +//eof diff --git a/Extras/Serialize/BlenderSerialize/bMain.h b/Extras/Serialize/BlenderSerialize/bMain.h new file mode 100644 index 0000000..f8e9afc --- /dev/null +++ b/Extras/Serialize/BlenderSerialize/bMain.h @@ -0,0 +1,110 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +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 __BMAIN_H__ +#define __BMAIN_H__ + +#include "bCommon.h" +#include "bChunk.h" +#include "LinearMath/btHashMap.h" + + +namespace bParse +{ + class bDNA; + + class bBlenderFile; +}; + + + +namespace bParse { + + + // ----------------------------------------------------- // + + typedef btHashMap bMainDataMap; + + + + // ----------------------------------------------------- // + class bMain + { + //private: + public: + bBlenderFile* mFP; + bListBasePtr mPool; + + int mVersion; + const char* mName; + + bMainDataMap mData; + + + + + bListBasePtr *_findCode(int code); + + public: + bMain(bBlenderFile *filePtr, const char *baseName, int fileVersion); + ~bMain(); + + int getVersion(); + const char *getName(); + + bListBasePtr *getListBasePtr(int listBaseCode); + + + bListBasePtr *getScene(); + bListBasePtr *getLibrary(); + bListBasePtr *getObject(); + bListBasePtr *getMesh(); + bListBasePtr *getCurve(); + bListBasePtr *getMball(); + bListBasePtr *getMat(); + bListBasePtr *getTex(); + bListBasePtr *getImage(); + bListBasePtr *getWave(); + bListBasePtr *getLatt(); + bListBasePtr *getLamp(); + bListBasePtr *getCamera(); + bListBasePtr *getIpo(); + bListBasePtr *getKey(); + bListBasePtr *getWorld(); + bListBasePtr *getScreen(); + bListBasePtr *getScript(); + bListBasePtr *getVfont(); + bListBasePtr *getText(); + bListBasePtr *getSound(); + bListBasePtr *getGroup(); + bListBasePtr *getArmature(); + bListBasePtr *getAction(); + bListBasePtr *getNodetree(); + bListBasePtr *getBrush(); + + + + // tracking allocated memory + void addDatablock(void *allocated); + + + // -- + + void linkList(void *listBasePtr); + }; +} + + +#endif//__BMAIN_H__ diff --git a/Extras/Serialize/BlenderSerialize/dna249-64bit.cpp b/Extras/Serialize/BlenderSerialize/dna249-64bit.cpp new file mode 100644 index 0000000..7c56c2c --- /dev/null +++ b/Extras/Serialize/BlenderSerialize/dna249-64bit.cpp @@ -0,0 +1,1411 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +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. +*/ +unsigned char DNAstr64[]= { +83,68,78,65,78,65,77,69,119,9,0,0,42,110,101,120,116,0,42,112,114,101,118,0,42,100,97,116,97,0,42,102,105, +114,115,116,0,42,108,97,115,116,0,120,0,121,0,122,0,119,0,120,109,105,110,0,120,109,97,120,0,121,109,105,110, +0,121,109,97,120,0,42,112,111,105,110,116,101,114,0,103,114,111,117,112,0,118,97,108,0,118,97,108,50,0,110,97, +109,101,91,51,50,93,0,116,121,112,101,0,115,117,98,116,121,112,101,0,102,108,97,103,0,115,97,118,101,100,0,100, +97,116,97,0,108,101,110,0,116,111,116,97,108,108,101,110,0,42,110,101,119,105,100,0,42,108,105,98,0,110,97,109, +101,91,50,52,93,0,117,115,0,105,99,111,110,95,105,100,0,42,112,114,111,112,101,114,116,105,101,115,0,105,100,0, +42,105,100,98,108,111,99,107,0,42,102,105,108,101,100,97,116,97,0,110,97,109,101,91,50,52,48,93,0,102,105,108, +101,110,97,109,101,91,50,52,48,93,0,116,111,116,0,112,97,100,0,42,112,97,114,101,110,116,0,119,91,50,93,0, +104,91,50,93,0,99,104,97,110,103,101,100,91,50,93,0,112,97,100,48,0,112,97,100,49,0,42,114,101,99,116,91, +50,93,0,42,111,98,0,98,108,111,99,107,116,121,112,101,0,97,100,114,99,111,100,101,0,110,97,109,101,91,49,50, +56,93,0,42,98,112,0,42,98,101,122,116,0,109,97,120,114,99,116,0,116,111,116,114,99,116,0,118,97,114,116,121, +112,101,0,116,111,116,118,101,114,116,0,105,112,111,0,101,120,116,114,97,112,0,114,116,0,98,105,116,109,97,115,107, +0,115,108,105,100,101,95,109,105,110,0,115,108,105,100,101,95,109,97,120,0,99,117,114,118,97,108,0,42,100,114,105, +118,101,114,0,99,117,114,118,101,0,99,117,114,0,115,104,111,119,107,101,121,0,109,117,116,101,105,112,111,0,112,111, +115,0,114,101,108,97,116,105,118,101,0,116,111,116,101,108,101,109,0,112,97,100,50,0,42,119,101,105,103,104,116,115, +0,118,103,114,111,117,112,91,51,50,93,0,115,108,105,100,101,114,109,105,110,0,115,108,105,100,101,114,109,97,120,0, +42,114,101,102,107,101,121,0,101,108,101,109,115,116,114,91,51,50,93,0,101,108,101,109,115,105,122,101,0,98,108,111, +99,107,0,42,105,112,111,0,42,102,114,111,109,0,116,111,116,107,101,121,0,115,108,117,114,112,104,0,42,42,115,99, +114,105,112,116,115,0,42,102,108,97,103,0,97,99,116,115,99,114,105,112,116,0,116,111,116,115,99,114,105,112,116,0, +42,108,105,110,101,0,42,102,111,114,109,97,116,0,98,108,101,110,0,108,105,110,101,110,111,0,115,116,97,114,116,0, +101,110,100,0,102,108,97,103,115,0,99,111,108,111,114,91,52,93,0,112,97,100,91,52,93,0,42,110,97,109,101,0, +110,108,105,110,101,115,0,108,105,110,101,115,0,42,99,117,114,108,0,42,115,101,108,108,0,99,117,114,99,0,115,101, +108,99,0,109,97,114,107,101,114,115,0,42,117,110,100,111,95,98,117,102,0,117,110,100,111,95,112,111,115,0,117,110, +100,111,95,108,101,110,0,42,99,111,109,112,105,108,101,100,0,109,116,105,109,101,0,115,105,122,101,0,115,101,101,107, +0,112,97,115,115,101,112,97,114,116,97,108,112,104,97,0,97,110,103,108,101,0,99,108,105,112,115,116,97,0,99,108, +105,112,101,110,100,0,108,101,110,115,0,111,114,116,104,111,95,115,99,97,108,101,0,100,114,97,119,115,105,122,101,0, +115,104,105,102,116,120,0,115,104,105,102,116,121,0,89,70,95,100,111,102,100,105,115,116,0,89,70,95,97,112,101,114, +116,117,114,101,0,89,70,95,98,107,104,116,121,112,101,0,89,70,95,98,107,104,98,105,97,115,0,89,70,95,98,107, +104,114,111,116,0,115,99,114,105,112,116,108,105,110,107,0,42,100,111,102,95,111,98,0,102,114,97,109,101,110,114,0, +102,114,97,109,101,115,0,111,102,102,115,101,116,0,115,102,114,97,0,102,105,101,95,105,109,97,0,99,121,99,108,0, +111,107,0,109,117,108,116,105,95,105,110,100,101,120,0,108,97,121,101,114,0,112,97,115,115,0,109,101,110,117,110,114, +0,105,98,117,102,115,0,42,103,112,117,116,101,120,116,117,114,101,0,42,97,110,105,109,0,42,114,114,0,115,111,117, +114,99,101,0,108,97,115,116,102,114,97,109,101,0,116,112,97,103,101,102,108,97,103,0,116,111,116,98,105,110,100,0, +120,114,101,112,0,121,114,101,112,0,116,119,115,116,97,0,116,119,101,110,100,0,98,105,110,100,99,111,100,101,0,42, +114,101,112,98,105,110,100,0,42,112,97,99,107,101,100,102,105,108,101,0,42,112,114,101,118,105,101,119,0,108,97,115, +116,117,112,100,97,116,101,0,108,97,115,116,117,115,101,100,0,97,110,105,109,115,112,101,101,100,0,103,101,110,95,120, +0,103,101,110,95,121,0,103,101,110,95,116,121,112,101,0,97,115,112,120,0,97,115,112,121,0,42,118,110,111,100,101, +0,116,101,120,99,111,0,109,97,112,116,111,0,109,97,112,116,111,110,101,103,0,98,108,101,110,100,116,121,112,101,0, +42,111,98,106,101,99,116,0,42,116,101,120,0,117,118,110,97,109,101,91,51,50,93,0,112,114,111,106,120,0,112,114, +111,106,121,0,112,114,111,106,122,0,109,97,112,112,105,110,103,0,111,102,115,91,51,93,0,115,105,122,101,91,51,93, +0,116,101,120,102,108,97,103,0,99,111,108,111,114,109,111,100,101,108,0,112,109,97,112,116,111,0,112,109,97,112,116, +111,110,101,103,0,110,111,114,109,97,112,115,112,97,99,101,0,119,104,105,99,104,95,111,117,116,112,117,116,0,112,97, +100,91,50,93,0,114,0,103,0,98,0,107,0,100,101,102,95,118,97,114,0,99,111,108,102,97,99,0,110,111,114,102, +97,99,0,118,97,114,102,97,99,0,100,105,115,112,102,97,99,0,119,97,114,112,102,97,99,0,110,97,109,101,91,49, +54,48,93,0,42,104,97,110,100,108,101,0,42,112,110,97,109,101,0,42,115,116,110,97,109,101,115,0,115,116,121,112, +101,115,0,118,97,114,115,0,42,118,97,114,115,116,114,0,42,114,101,115,117,108,116,0,42,99,102,114,97,0,100,97, +116,97,91,51,50,93,0,40,42,100,111,105,116,41,40,41,0,40,42,105,110,115,116,97,110,99,101,95,105,110,105,116, +41,40,41,0,40,42,99,97,108,108,98,97,99,107,41,40,41,0,118,101,114,115,105,111,110,0,97,0,105,112,111,116, +121,112,101,0,42,105,109,97,0,42,99,117,98,101,91,54,93,0,105,109,97,116,91,52,93,91,52,93,0,111,98,105, +109,97,116,91,51,93,91,51,93,0,115,116,121,112,101,0,118,105,101,119,115,99,97,108,101,0,110,111,116,108,97,121, +0,99,117,98,101,114,101,115,0,100,101,112,116,104,0,114,101,99,97,108,99,0,108,97,115,116,115,105,122,101,0,110, +111,105,115,101,115,105,122,101,0,116,117,114,98,117,108,0,98,114,105,103,104,116,0,99,111,110,116,114,97,115,116,0, +114,102,97,99,0,103,102,97,99,0,98,102,97,99,0,102,105,108,116,101,114,115,105,122,101,0,109,103,95,72,0,109, +103,95,108,97,99,117,110,97,114,105,116,121,0,109,103,95,111,99,116,97,118,101,115,0,109,103,95,111,102,102,115,101, +116,0,109,103,95,103,97,105,110,0,100,105,115,116,95,97,109,111,117,110,116,0,110,115,95,111,117,116,115,99,97,108, +101,0,118,110,95,119,49,0,118,110,95,119,50,0,118,110,95,119,51,0,118,110,95,119,52,0,118,110,95,109,101,120, +112,0,118,110,95,100,105,115,116,109,0,118,110,95,99,111,108,116,121,112,101,0,110,111,105,115,101,100,101,112,116,104, +0,110,111,105,115,101,116,121,112,101,0,110,111,105,115,101,98,97,115,105,115,0,110,111,105,115,101,98,97,115,105,115, +50,0,105,109,97,102,108,97,103,0,99,114,111,112,120,109,105,110,0,99,114,111,112,121,109,105,110,0,99,114,111,112, +120,109,97,120,0,99,114,111,112,121,109,97,120,0,120,114,101,112,101,97,116,0,121,114,101,112,101,97,116,0,101,120, +116,101,110,100,0,99,104,101,99,107,101,114,100,105,115,116,0,110,97,98,108,97,0,105,117,115,101,114,0,42,110,111, +100,101,116,114,101,101,0,42,112,108,117,103,105,110,0,42,99,111,98,97,0,42,101,110,118,0,117,115,101,95,110,111, +100,101,115,0,112,97,100,91,55,93,0,108,111,99,91,51,93,0,114,111,116,91,51,93,0,109,97,116,91,52,93,91, +52,93,0,109,105,110,91,51,93,0,109,97,120,91,51,93,0,112,97,100,51,0,109,111,100,101,0,116,111,116,101,120, +0,115,104,100,119,114,0,115,104,100,119,103,0,115,104,100,119,98,0,115,104,100,119,112,97,100,0,101,110,101,114,103, +121,0,100,105,115,116,0,115,112,111,116,115,105,122,101,0,115,112,111,116,98,108,101,110,100,0,104,97,105,110,116,0, +97,116,116,49,0,97,116,116,50,0,42,99,117,114,102,97,108,108,111,102,102,0,102,97,108,108,111,102,102,95,116,121, +112,101,0,115,104,97,100,115,112,111,116,115,105,122,101,0,98,105,97,115,0,115,111,102,116,0,98,117,102,115,105,122, +101,0,115,97,109,112,0,98,117,102,102,101,114,115,0,102,105,108,116,101,114,116,121,112,101,0,98,117,102,102,108,97, +103,0,98,117,102,116,121,112,101,0,114,97,121,95,115,97,109,112,0,114,97,121,95,115,97,109,112,121,0,114,97,121, +95,115,97,109,112,122,0,114,97,121,95,115,97,109,112,95,116,121,112,101,0,97,114,101,97,95,115,104,97,112,101,0, +97,114,101,97,95,115,105,122,101,0,97,114,101,97,95,115,105,122,101,121,0,97,114,101,97,95,115,105,122,101,122,0, +97,100,97,112,116,95,116,104,114,101,115,104,0,114,97,121,95,115,97,109,112,95,109,101,116,104,111,100,0,116,101,120, +97,99,116,0,115,104,97,100,104,97,108,111,115,116,101,112,0,115,117,110,95,101,102,102,101,99,116,95,116,121,112,101, +0,115,107,121,98,108,101,110,100,116,121,112,101,0,104,111,114,105,122,111,110,95,98,114,105,103,104,116,110,101,115,115, +0,115,112,114,101,97,100,0,115,117,110,95,98,114,105,103,104,116,110,101,115,115,0,115,117,110,95,115,105,122,101,0, +98,97,99,107,115,99,97,116,116,101,114,101,100,95,108,105,103,104,116,0,115,117,110,95,105,110,116,101,110,115,105,116, +121,0,97,116,109,95,116,117,114,98,105,100,105,116,121,0,97,116,109,95,105,110,115,99,97,116,116,101,114,105,110,103, +95,102,97,99,116,111,114,0,97,116,109,95,101,120,116,105,110,99,116,105,111,110,95,102,97,99,116,111,114,0,97,116, +109,95,100,105,115,116,97,110,99,101,95,102,97,99,116,111,114,0,115,107,121,98,108,101,110,100,102,97,99,0,115,107, +121,95,101,120,112,111,115,117,114,101,0,115,107,121,95,99,111,108,111,114,115,112,97,99,101,0,112,97,100,52,0,89, +70,95,110,117,109,112,104,111,116,111,110,115,0,89,70,95,110,117,109,115,101,97,114,99,104,0,89,70,95,112,104,100, +101,112,116,104,0,89,70,95,117,115,101,113,109,99,0,89,70,95,98,117,102,115,105,122,101,0,89,70,95,112,97,100, +0,89,70,95,99,97,117,115,116,105,99,98,108,117,114,0,89,70,95,108,116,114,97,100,105,117,115,0,89,70,95,103, +108,111,119,105,110,116,0,89,70,95,103,108,111,119,111,102,115,0,89,70,95,103,108,111,119,116,121,112,101,0,89,70, +95,112,97,100,50,0,42,109,116,101,120,91,49,56,93,0,115,112,101,99,114,0,115,112,101,99,103,0,115,112,101,99, +98,0,109,105,114,114,0,109,105,114,103,0,109,105,114,98,0,97,109,98,114,0,97,109,98,98,0,97,109,98,103,0, +97,109,98,0,101,109,105,116,0,97,110,103,0,115,112,101,99,116,114,97,0,114,97,121,95,109,105,114,114,111,114,0, +97,108,112,104,97,0,114,101,102,0,115,112,101,99,0,122,111,102,102,115,0,97,100,100,0,116,114,97,110,115,108,117, +99,101,110,99,121,0,102,114,101,115,110,101,108,95,109,105,114,0,102,114,101,115,110,101,108,95,109,105,114,95,105,0, +102,114,101,115,110,101,108,95,116,114,97,0,102,114,101,115,110,101,108,95,116,114,97,95,105,0,102,105,108,116,101,114, +0,116,120,95,108,105,109,105,116,0,116,120,95,102,97,108,108,111,102,102,0,114,97,121,95,100,101,112,116,104,0,114, +97,121,95,100,101,112,116,104,95,116,114,97,0,104,97,114,0,115,101,101,100,49,0,115,101,101,100,50,0,103,108,111, +115,115,95,109,105,114,0,103,108,111,115,115,95,116,114,97,0,115,97,109,112,95,103,108,111,115,115,95,109,105,114,0, +115,97,109,112,95,103,108,111,115,115,95,116,114,97,0,97,100,97,112,116,95,116,104,114,101,115,104,95,109,105,114,0, +97,100,97,112,116,95,116,104,114,101,115,104,95,116,114,97,0,97,110,105,115,111,95,103,108,111,115,115,95,109,105,114, +0,100,105,115,116,95,109,105,114,0,102,97,100,101,116,111,95,109,105,114,0,115,104,97,100,101,95,102,108,97,103,0, +109,111,100,101,95,108,0,102,108,97,114,101,99,0,115,116,97,114,99,0,108,105,110,101,99,0,114,105,110,103,99,0, +104,97,115,105,122,101,0,102,108,97,114,101,115,105,122,101,0,115,117,98,115,105,122,101,0,102,108,97,114,101,98,111, +111,115,116,0,115,116,114,97,110,100,95,115,116,97,0,115,116,114,97,110,100,95,101,110,100,0,115,116,114,97,110,100, +95,101,97,115,101,0,115,116,114,97,110,100,95,115,117,114,102,110,111,114,0,115,116,114,97,110,100,95,109,105,110,0, +115,116,114,97,110,100,95,119,105,100,116,104,102,97,100,101,0,115,116,114,97,110,100,95,117,118,110,97,109,101,91,51, +50,93,0,115,98,105,97,115,0,108,98,105,97,115,0,115,104,97,100,95,97,108,112,104,97,0,115,101,112,116,101,120, +0,114,103,98,115,101,108,0,112,114,95,116,121,112,101,0,112,114,95,98,97,99,107,0,112,114,95,108,97,109,112,0, +109,108,95,102,108,97,103,0,100,105,102,102,95,115,104,97,100,101,114,0,115,112,101,99,95,115,104,97,100,101,114,0, +114,111,117,103,104,110,101,115,115,0,114,101,102,114,97,99,0,112,97,114,97,109,91,52,93,0,114,109,115,0,100,97, +114,107,110,101,115,115,0,42,114,97,109,112,95,99,111,108,0,42,114,97,109,112,95,115,112,101,99,0,114,97,109,112, +105,110,95,99,111,108,0,114,97,109,112,105,110,95,115,112,101,99,0,114,97,109,112,98,108,101,110,100,95,99,111,108, +0,114,97,109,112,98,108,101,110,100,95,115,112,101,99,0,114,97,109,112,95,115,104,111,119,0,114,97,109,112,102,97, +99,95,99,111,108,0,114,97,109,112,102,97,99,95,115,112,101,99,0,42,103,114,111,117,112,0,102,114,105,99,116,105, +111,110,0,102,104,0,114,101,102,108,101,99,116,0,102,104,100,105,115,116,0,120,121,102,114,105,99,116,0,100,121,110, +97,109,111,100,101,0,115,115,115,95,114,97,100,105,117,115,91,51,93,0,115,115,115,95,99,111,108,91,51,93,0,115, +115,115,95,101,114,114,111,114,0,115,115,115,95,115,99,97,108,101,0,115,115,115,95,105,111,114,0,115,115,115,95,99, +111,108,102,97,99,0,115,115,115,95,116,101,120,102,97,99,0,115,115,115,95,102,114,111,110,116,0,115,115,115,95,98, +97,99,107,0,115,115,115,95,102,108,97,103,0,115,115,115,95,112,114,101,115,101,116,0,89,70,95,97,114,0,89,70, +95,97,103,0,89,70,95,97,98,0,89,70,95,100,115,99,97,108,101,0,89,70,95,100,112,119,114,0,89,70,95,100, +115,109,112,0,89,70,95,112,114,101,115,101,116,0,89,70,95,100,106,105,116,0,103,112,117,109,97,116,101,114,105,97, +108,0,110,97,109,101,91,50,53,54,93,0,115,99,97,108,101,0,42,98,98,0,105,49,0,106,49,0,107,49,0,105, +50,0,106,50,0,107,50,0,115,101,108,99,111,108,49,0,115,101,108,99,111,108,50,0,113,117,97,116,91,52,93,0, +101,120,112,120,0,101,120,112,121,0,101,120,112,122,0,114,97,100,0,114,97,100,50,0,115,0,42,109,97,116,0,42, +105,109,97,116,0,101,108,101,109,115,0,100,105,115,112,0,42,42,109,97,116,0,116,111,116,99,111,108,0,119,105,114, +101,115,105,122,101,0,114,101,110,100,101,114,115,105,122,101,0,116,104,114,101,115,104,0,118,101,99,91,51,93,91,51, +93,0,97,108,102,97,0,119,101,105,103,104,116,0,114,97,100,105,117,115,0,104,49,0,104,50,0,102,49,0,102,50, +0,102,51,0,104,105,100,101,0,118,101,99,91,52,93,0,109,97,116,95,110,114,0,112,110,116,115,117,0,112,110,116, +115,118,0,114,101,115,111,108,117,0,114,101,115,111,108,118,0,111,114,100,101,114,117,0,111,114,100,101,114,118,0,102, +108,97,103,117,0,102,108,97,103,118,0,42,107,110,111,116,115,117,0,42,107,110,111,116,115,118,0,116,105,108,116,95, +105,110,116,101,114,112,0,114,97,100,105,117,115,95,105,110,116,101,114,112,0,99,104,97,114,105,100,120,0,107,101,114, +110,0,104,0,110,117,114,98,0,42,98,101,118,111,98,106,0,42,116,97,112,101,114,111,98,106,0,42,116,101,120,116, +111,110,99,117,114,118,101,0,42,112,97,116,104,0,42,107,101,121,0,98,101,118,0,112,97,116,104,108,101,110,0,98, +101,118,114,101,115,111,108,0,119,105,100,116,104,0,101,120,116,49,0,101,120,116,50,0,114,101,115,111,108,117,95,114, +101,110,0,114,101,115,111,108,118,95,114,101,110,0,115,112,97,99,101,109,111,100,101,0,115,112,97,99,105,110,103,0, +108,105,110,101,100,105,115,116,0,115,104,101,97,114,0,102,115,105,122,101,0,119,111,114,100,115,112,97,99,101,0,117, +108,112,111,115,0,117,108,104,101,105,103,104,116,0,120,111,102,0,121,111,102,0,108,105,110,101,119,105,100,116,104,0, +42,115,116,114,0,102,97,109,105,108,121,91,50,52,93,0,42,118,102,111,110,116,0,42,118,102,111,110,116,98,0,42, +118,102,111,110,116,105,0,42,118,102,111,110,116,98,105,0,115,101,112,99,104,97,114,0,116,111,116,98,111,120,0,97, +99,116,98,111,120,0,42,116,98,0,115,101,108,115,116,97,114,116,0,115,101,108,101,110,100,0,42,115,116,114,105,110, +102,111,0,99,117,114,105,110,102,111,0,101,102,102,101,99,116,0,42,109,102,97,99,101,0,42,109,116,102,97,99,101, +0,42,116,102,97,99,101,0,42,109,118,101,114,116,0,42,109,101,100,103,101,0,42,100,118,101,114,116,0,42,109,99, +111,108,0,42,109,115,116,105,99,107,121,0,42,116,101,120,99,111,109,101,115,104,0,42,109,115,101,108,101,99,116,0, +118,100,97,116,97,0,101,100,97,116,97,0,102,100,97,116,97,0,116,111,116,101,100,103,101,0,116,111,116,102,97,99, +101,0,116,111,116,115,101,108,101,99,116,0,97,99,116,95,102,97,99,101,0,99,117,98,101,109,97,112,115,105,122,101, +0,115,109,111,111,116,104,114,101,115,104,0,115,117,98,100,105,118,0,115,117,98,100,105,118,114,0,115,117,98,115,117, +114,102,116,121,112,101,0,42,109,114,0,42,112,118,0,42,116,112,97,103,101,0,117,118,91,52,93,91,50,93,0,99, +111,108,91,52,93,0,116,114,97,110,115,112,0,116,105,108,101,0,117,110,119,114,97,112,0,118,49,0,118,50,0,118, +51,0,118,52,0,101,100,99,111,100,101,0,99,114,101,97,115,101,0,98,119,101,105,103,104,116,0,100,101,102,95,110, +114,0,42,100,119,0,116,111,116,119,101,105,103,104,116,0,99,111,91,51,93,0,110,111,91,51,93,0,112,97,100,91, +51,93,0,117,118,91,50,93,0,99,111,91,50,93,0,105,110,100,101,120,0,102,0,105,0,115,91,50,53,54,93,0, +118,91,52,93,0,109,105,100,0,118,91,50,93,0,42,102,97,99,101,115,0,42,99,111,108,102,97,99,101,115,0,42, +101,100,103,101,115,0,42,101,100,103,101,95,98,111,117,110,100,97,114,121,95,115,116,97,116,101,115,0,42,118,101,114, +116,95,101,100,103,101,95,109,97,112,0,42,118,101,114,116,95,102,97,99,101,95,109,97,112,0,42,109,97,112,95,109, +101,109,0,42,118,101,114,116,115,0,108,101,118,101,108,115,0,108,101,118,101,108,95,99,111,117,110,116,0,99,117,114, +114,101,110,116,0,110,101,119,108,118,108,0,101,100,103,101,108,118,108,0,112,105,110,108,118,108,0,114,101,110,100,101, +114,108,118,108,0,117,115,101,95,99,111,108,0,42,101,100,103,101,95,102,108,97,103,115,0,42,101,100,103,101,95,99, +114,101,97,115,101,115,0,42,118,101,114,116,95,109,97,112,0,42,101,100,103,101,95,109,97,112,0,42,111,108,100,95, +102,97,99,101,115,0,42,111,108,100,95,101,100,103,101,115,0,42,101,114,114,111,114,0,109,111,100,105,102,105,101,114, +0,115,117,98,100,105,118,84,121,112,101,0,114,101,110,100,101,114,76,101,118,101,108,115,0,42,101,109,67,97,99,104, +101,0,42,109,67,97,99,104,101,0,100,101,102,97,120,105,115,0,112,97,100,91,54,93,0,108,101,110,103,116,104,0, +114,97,110,100,111,109,105,122,101,0,115,101,101,100,0,42,111,98,95,97,114,109,0,42,115,116,97,114,116,95,99,97, +112,0,42,101,110,100,95,99,97,112,0,42,99,117,114,118,101,95,111,98,0,42,111,102,102,115,101,116,95,111,98,0, +111,102,102,115,101,116,91,51,93,0,115,99,97,108,101,91,51,93,0,109,101,114,103,101,95,100,105,115,116,0,102,105, +116,95,116,121,112,101,0,111,102,102,115,101,116,95,116,121,112,101,0,99,111,117,110,116,0,97,120,105,115,0,116,111, +108,101,114,97,110,99,101,0,42,109,105,114,114,111,114,95,111,98,0,115,112,108,105,116,95,97,110,103,108,101,0,118, +97,108,117,101,0,114,101,115,0,118,97,108,95,102,108,97,103,115,0,108,105,109,95,102,108,97,103,115,0,101,95,102, +108,97,103,115,0,98,101,118,101,108,95,97,110,103,108,101,0,100,101,102,103,114,112,95,110,97,109,101,91,51,50,93, +0,42,116,101,120,116,117,114,101,0,115,116,114,101,110,103,116,104,0,100,105,114,101,99,116,105,111,110,0,109,105,100, +108,101,118,101,108,0,116,101,120,109,97,112,112,105,110,103,0,42,109,97,112,95,111,98,106,101,99,116,0,117,118,108, +97,121,101,114,95,110,97,109,101,91,51,50,93,0,117,118,108,97,121,101,114,95,116,109,112,0,42,112,114,111,106,101, +99,116,111,114,115,91,49,48,93,0,42,105,109,97,103,101,0,110,117,109,95,112,114,111,106,101,99,116,111,114,115,0, +97,115,112,101,99,116,120,0,97,115,112,101,99,116,121,0,112,101,114,99,101,110,116,0,102,97,99,101,67,111,117,110, +116,0,102,97,99,0,114,101,112,101,97,116,0,42,111,98,106,101,99,116,99,101,110,116,101,114,0,115,116,97,114,116, +120,0,115,116,97,114,116,121,0,104,101,105,103,104,116,0,110,97,114,114,111,119,0,115,112,101,101,100,0,100,97,109, +112,0,102,97,108,108,111,102,102,0,116,105,109,101,111,102,102,115,0,108,105,102,101,116,105,109,101,0,100,101,102,111, +114,109,102,108,97,103,0,109,117,108,116,105,0,42,112,114,101,118,67,111,115,0,112,97,114,101,110,116,105,110,118,91, +52,93,91,52,93,0,99,101,110,116,91,51,93,0,42,105,110,100,101,120,97,114,0,116,111,116,105,110,100,101,120,0, +102,111,114,99,101,0,42,99,108,111,116,104,79,98,106,101,99,116,0,42,115,105,109,95,112,97,114,109,115,0,42,99, +111,108,108,95,112,97,114,109,115,0,42,112,111,105,110,116,95,99,97,99,104,101,0,42,120,0,42,120,110,101,119,0, +42,120,111,108,100,0,42,99,117,114,114,101,110,116,95,120,110,101,119,0,42,99,117,114,114,101,110,116,95,120,0,42, +99,117,114,114,101,110,116,95,118,0,42,109,102,97,99,101,115,0,110,117,109,118,101,114,116,115,0,110,117,109,102,97, +99,101,115,0,97,98,115,111,114,112,116,105,111,110,0,116,105,109,101,0,42,98,118,104,116,114,101,101,0,42,100,109, +0,111,112,101,114,97,116,105,111,110,0,118,101,114,116,101,120,0,116,111,116,105,110,102,108,117,101,110,99,101,0,103, +114,105,100,115,105,122,101,0,110,101,101,100,98,105,110,100,0,42,98,105,110,100,119,101,105,103,104,116,115,0,42,98, +105,110,100,99,111,115,0,116,111,116,99,97,103,101,118,101,114,116,0,42,100,121,110,103,114,105,100,0,42,100,121,110, +105,110,102,108,117,101,110,99,101,115,0,42,100,121,110,118,101,114,116,115,0,42,112,97,100,50,0,100,121,110,103,114, +105,100,115,105,122,101,0,100,121,110,99,101,108,108,109,105,110,91,51,93,0,100,121,110,99,101,108,108,119,105,100,116, +104,0,98,105,110,100,109,97,116,91,52,93,91,52,93,0,42,112,115,121,115,0,116,111,116,100,109,118,101,114,116,0, +116,111,116,100,109,101,100,103,101,0,116,111,116,100,109,102,97,99,101,0,112,115,121,115,0,114,116,91,50,93,0,42, +102,97,99,101,112,97,0,118,103,114,111,117,112,0,112,114,111,116,101,99,116,0,42,102,115,115,0,42,116,97,114,103, +101,116,0,42,97,117,120,84,97,114,103,101,116,0,118,103,114,111,117,112,95,110,97,109,101,91,51,50,93,0,107,101, +101,112,68,105,115,116,0,115,104,114,105,110,107,84,121,112,101,0,115,104,114,105,110,107,79,112,116,115,0,112,114,111, +106,65,120,105,115,0,115,117,98,115,117,114,102,76,101,118,101,108,115,0,42,111,114,105,103,105,110,0,102,97,99,116, +111,114,0,108,105,109,105,116,91,50,93,0,111,114,105,103,105,110,79,112,116,115,0,112,110,116,115,119,0,111,112,110, +116,115,117,0,111,112,110,116,115,118,0,111,112,110,116,115,119,0,116,121,112,101,117,0,116,121,112,101,118,0,116,121, +112,101,119,0,102,117,0,102,118,0,102,119,0,100,117,0,100,118,0,100,119,0,42,100,101,102,0,118,101,99,91,56, +93,91,51,93,0,112,97,114,116,121,112,101,0,112,97,114,49,0,112,97,114,50,0,112,97,114,51,0,112,97,114,115, +117,98,115,116,114,91,51,50,93,0,42,116,114,97,99,107,0,42,112,114,111,120,121,0,42,112,114,111,120,121,95,103, +114,111,117,112,0,42,112,114,111,120,121,95,102,114,111,109,0,42,97,99,116,105,111,110,0,42,112,111,115,101,108,105, +98,0,42,112,111,115,101,0,99,111,110,115,116,114,97,105,110,116,67,104,97,110,110,101,108,115,0,100,101,102,98,97, +115,101,0,109,111,100,105,102,105,101,114,115,0,100,108,111,99,91,51,93,0,111,114,105,103,91,51,93,0,100,115,105, +122,101,91,51,93,0,100,114,111,116,91,51,93,0,111,98,109,97,116,91,52,93,91,52,93,0,99,111,110,115,116,105, +110,118,91,52,93,91,52,93,0,108,97,121,0,99,111,108,98,105,116,115,0,116,114,97,110,115,102,108,97,103,0,105, +112,111,102,108,97,103,0,116,114,97,99,107,102,108,97,103,0,117,112,102,108,97,103,0,110,108,97,102,108,97,103,0, +112,114,111,116,101,99,116,102,108,97,103,0,105,112,111,119,105,110,0,115,99,97,102,108,97,103,0,115,99,97,118,105, +115,102,108,97,103,0,98,111,117,110,100,116,121,112,101,0,100,117,112,111,110,0,100,117,112,111,102,102,0,100,117,112, +115,116,97,0,100,117,112,101,110,100,0,115,102,0,99,116,105,109,101,0,109,97,115,115,0,100,97,109,112,105,110,103, +0,105,110,101,114,116,105,97,0,102,111,114,109,102,97,99,116,111,114,0,114,100,97,109,112,105,110,103,0,115,105,122, +101,102,97,99,0,109,97,114,103,105,110,0,109,97,120,95,118,101,108,0,109,105,110,95,118,101,108,0,109,95,99,111, +110,116,97,99,116,80,114,111,99,101,115,115,105,110,103,84,104,114,101,115,104,111,108,100,0,100,116,0,100,116,120,0, +97,99,116,99,111,108,0,101,109,112,116,121,95,100,114,97,119,116,121,112,101,0,112,97,100,49,91,51,93,0,101,109, +112,116,121,95,100,114,97,119,115,105,122,101,0,100,117,112,102,97,99,101,115,99,97,0,112,114,111,112,0,115,101,110, +115,111,114,115,0,99,111,110,116,114,111,108,108,101,114,115,0,97,99,116,117,97,116,111,114,115,0,98,98,115,105,122, +101,91,51,93,0,97,99,116,100,101,102,0,103,97,109,101,102,108,97,103,0,103,97,109,101,102,108,97,103,50,0,42, +98,115,111,102,116,0,115,111,102,116,102,108,97,103,0,97,110,105,115,111,116,114,111,112,105,99,70,114,105,99,116,105, +111,110,91,51,93,0,99,111,110,115,116,114,97,105,110,116,115,0,110,108,97,115,116,114,105,112,115,0,104,111,111,107, +115,0,112,97,114,116,105,99,108,101,115,121,115,116,101,109,0,42,112,100,0,42,115,111,102,116,0,42,100,117,112,95, +103,114,111,117,112,0,102,108,117,105,100,115,105,109,70,108,97,103,0,114,101,115,116,114,105,99,116,102,108,97,103,0, +115,104,97,112,101,110,114,0,115,104,97,112,101,102,108,97,103,0,114,101,99,97,108,99,111,0,98,111,100,121,95,116, +121,112,101,0,42,102,108,117,105,100,115,105,109,83,101,116,116,105,110,103,115,0,42,100,101,114,105,118,101,100,68,101, +102,111,114,109,0,42,100,101,114,105,118,101,100,70,105,110,97,108,0,108,97,115,116,68,97,116,97,77,97,115,107,0, +115,116,97,116,101,0,105,110,105,116,95,115,116,97,116,101,0,103,112,117,108,97,109,112,0,99,117,114,105,110,100,101, +120,0,97,99,116,105,118,101,0,100,101,102,108,101,99,116,0,102,111,114,99,101,102,105,101,108,100,0,112,100,101,102, +95,100,97,109,112,0,112,100,101,102,95,114,100,97,109,112,0,112,100,101,102,95,112,101,114,109,0,112,100,101,102,95, +102,114,105,99,116,0,112,100,101,102,95,114,102,114,105,99,116,0,102,95,115,116,114,101,110,103,116,104,0,102,95,112, +111,119,101,114,0,102,95,100,105,115,116,0,102,95,100,97,109,112,0,109,97,120,100,105,115,116,0,109,105,110,100,105, +115,116,0,109,97,120,114,97,100,0,109,105,110,114,97,100,0,102,95,112,111,119,101,114,95,114,0,112,100,101,102,95, +115,98,100,97,109,112,0,112,100,101,102,95,115,98,105,102,116,0,112,100,101,102,95,115,98,111,102,116,0,99,108,117, +109,112,95,102,97,99,0,99,108,117,109,112,95,112,111,119,0,107,105,110,107,95,102,114,101,113,0,107,105,110,107,95, +115,104,97,112,101,0,107,105,110,107,95,97,109,112,0,102,114,101,101,95,101,110,100,0,116,101,120,95,110,97,98,108, +97,0,116,101,120,95,109,111,100,101,0,107,105,110,107,0,107,105,110,107,95,97,120,105,115,0,114,116,50,0,42,114, +110,103,0,102,95,110,111,105,115,101,0,115,105,109,102,114,97,109,101,0,115,116,97,114,116,102,114,97,109,101,0,101, +110,100,102,114,97,109,101,0,101,100,105,116,102,114,97,109,101,0,108,105,110,83,116,105,102,102,0,97,110,103,83,116, +105,102,102,0,118,111,108,117,109,101,0,118,105,116,101,114,97,116,105,111,110,115,0,112,105,116,101,114,97,116,105,111, +110,115,0,100,105,116,101,114,97,116,105,111,110,115,0,99,105,116,101,114,97,116,105,111,110,115,0,107,83,82,72,82, +95,67,76,0,107,83,75,72,82,95,67,76,0,107,83,83,72,82,95,67,76,0,107,83,82,95,83,80,76,84,95,67, +76,0,107,83,75,95,83,80,76,84,95,67,76,0,107,83,83,95,83,80,76,84,95,67,76,0,107,86,67,70,0,107, +68,80,0,107,68,71,0,107,76,70,0,107,80,82,0,107,86,67,0,107,68,70,0,107,77,84,0,107,67,72,82,0, +107,75,72,82,0,107,83,72,82,0,107,65,72,82,0,99,111,108,108,105,115,105,111,110,102,108,97,103,115,0,110,117, +109,99,108,117,115,116,101,114,105,116,101,114,97,116,105,111,110,115,0,119,101,108,100,105,110,103,0,42,112,97,114,116, +105,99,108,101,115,0,116,111,116,112,111,105,110,116,0,116,111,116,115,112,114,105,110,103,0,42,98,112,111,105,110,116, +0,42,98,115,112,114,105,110,103,0,109,115,103,95,108,111,99,107,0,109,115,103,95,118,97,108,117,101,0,110,111,100, +101,109,97,115,115,0,110,97,109,101,100,86,71,95,77,97,115,115,91,51,50,93,0,103,114,97,118,0,109,101,100,105, +97,102,114,105,99,116,0,114,107,108,105,109,105,116,0,112,104,121,115,105,99,115,95,115,112,101,101,100,0,103,111,97, +108,115,112,114,105,110,103,0,103,111,97,108,102,114,105,99,116,0,109,105,110,103,111,97,108,0,109,97,120,103,111,97, +108,0,100,101,102,103,111,97,108,0,118,101,114,116,103,114,111,117,112,0,110,97,109,101,100,86,71,95,83,111,102,116, +103,111,97,108,91,51,50,93,0,102,117,122,122,121,110,101,115,115,0,105,110,115,112,114,105,110,103,0,105,110,102,114, +105,99,116,0,110,97,109,101,100,86,71,95,83,112,114,105,110,103,95,75,91,51,50,93,0,101,102,114,97,0,105,110, +116,101,114,118,97,108,0,108,111,99,97,108,0,115,111,108,118,101,114,102,108,97,103,115,0,42,42,107,101,121,115,0, +116,111,116,112,111,105,110,116,107,101,121,0,115,101,99,111,110,100,115,112,114,105,110,103,0,99,111,108,98,97,108,108, +0,98,97,108,108,100,97,109,112,0,98,97,108,108,115,116,105,102,102,0,115,98,99,95,109,111,100,101,0,97,101,114, +111,101,100,103,101,0,109,105,110,108,111,111,112,115,0,109,97,120,108,111,111,112,115,0,99,104,111,107,101,0,115,111, +108,118,101,114,95,73,68,0,112,108,97,115,116,105,99,0,115,112,114,105,110,103,112,114,101,108,111,97,100,0,42,115, +99,114,97,116,99,104,0,115,104,101,97,114,115,116,105,102,102,0,105,110,112,117,115,104,0,42,112,111,105,110,116,99, +97,99,104,101,0,115,104,111,119,95,97,100,118,97,110,99,101,100,111,112,116,105,111,110,115,0,114,101,115,111,108,117, +116,105,111,110,120,121,122,0,112,114,101,118,105,101,119,114,101,115,120,121,122,0,114,101,97,108,115,105,122,101,0,103, +117,105,68,105,115,112,108,97,121,77,111,100,101,0,114,101,110,100,101,114,68,105,115,112,108,97,121,77,111,100,101,0, +118,105,115,99,111,115,105,116,121,86,97,108,117,101,0,118,105,115,99,111,115,105,116,121,77,111,100,101,0,118,105,115, +99,111,115,105,116,121,69,120,112,111,110,101,110,116,0,103,114,97,118,120,0,103,114,97,118,121,0,103,114,97,118,122, +0,97,110,105,109,83,116,97,114,116,0,97,110,105,109,69,110,100,0,103,115,116,97,114,0,109,97,120,82,101,102,105, +110,101,0,105,110,105,86,101,108,120,0,105,110,105,86,101,108,121,0,105,110,105,86,101,108,122,0,42,111,114,103,77, +101,115,104,0,42,109,101,115,104,83,117,114,102,97,99,101,0,42,109,101,115,104,66,66,0,115,117,114,102,100,97,116, +97,80,97,116,104,91,50,52,48,93,0,98,98,83,116,97,114,116,91,51,93,0,98,98,83,105,122,101,91,51,93,0, +116,121,112,101,70,108,97,103,115,0,100,111,109,97,105,110,78,111,118,101,99,103,101,110,0,118,111,108,117,109,101,73, +110,105,116,84,121,112,101,0,112,97,114,116,83,108,105,112,86,97,108,117,101,0,103,101,110,101,114,97,116,101,84,114, +97,99,101,114,115,0,103,101,110,101,114,97,116,101,80,97,114,116,105,99,108,101,115,0,115,117,114,102,97,99,101,83, +109,111,111,116,104,105,110,103,0,115,117,114,102,97,99,101,83,117,98,100,105,118,115,0,112,97,114,116,105,99,108,101, +73,110,102,83,105,122,101,0,112,97,114,116,105,99,108,101,73,110,102,65,108,112,104,97,0,102,97,114,70,105,101,108, +100,83,105,122,101,0,42,109,101,115,104,83,117,114,102,78,111,114,109,97,108,115,0,99,112,115,84,105,109,101,83,116, +97,114,116,0,99,112,115,84,105,109,101,69,110,100,0,99,112,115,81,117,97,108,105,116,121,0,97,116,116,114,97,99, +116,102,111,114,99,101,83,116,114,101,110,103,116,104,0,97,116,116,114,97,99,116,102,111,114,99,101,82,97,100,105,117, +115,0,118,101,108,111,99,105,116,121,102,111,114,99,101,83,116,114,101,110,103,116,104,0,118,101,108,111,99,105,116,121, +102,111,114,99,101,82,97,100,105,117,115,0,108,97,115,116,103,111,111,100,102,114,97,109,101,0,109,105,115,116,121,112, +101,0,104,111,114,114,0,104,111,114,103,0,104,111,114,98,0,104,111,114,107,0,122,101,110,114,0,122,101,110,103,0, +122,101,110,98,0,122,101,110,107,0,97,109,98,107,0,102,97,115,116,99,111,108,0,101,120,112,111,115,117,114,101,0, +101,120,112,0,114,97,110,103,101,0,108,105,110,102,97,99,0,108,111,103,102,97,99,0,103,114,97,118,105,116,121,0, +97,99,116,105,118,105,116,121,66,111,120,82,97,100,105,117,115,0,115,107,121,116,121,112,101,0,111,99,99,108,117,115, +105,111,110,82,101,115,0,112,104,121,115,105,99,115,69,110,103,105,110,101,0,116,105,99,114,97,116,101,0,109,97,120, +108,111,103,105,99,115,116,101,112,0,112,104,121,115,117,98,115,116,101,112,0,109,97,120,112,104,121,115,116,101,112,0, +109,105,115,105,0,109,105,115,116,115,116,97,0,109,105,115,116,100,105,115,116,0,109,105,115,116,104,105,0,115,116,97, +114,114,0,115,116,97,114,103,0,115,116,97,114,98,0,115,116,97,114,107,0,115,116,97,114,115,105,122,101,0,115,116, +97,114,109,105,110,100,105,115,116,0,115,116,97,114,100,105,115,116,0,115,116,97,114,99,111,108,110,111,105,115,101,0, +100,111,102,115,116,97,0,100,111,102,101,110,100,0,100,111,102,109,105,110,0,100,111,102,109,97,120,0,97,111,100,105, +115,116,0,97,111,100,105,115,116,102,97,99,0,97,111,101,110,101,114,103,121,0,97,111,98,105,97,115,0,97,111,109, +111,100,101,0,97,111,115,97,109,112,0,97,111,109,105,120,0,97,111,99,111,108,111,114,0,97,111,95,97,100,97,112, +116,95,116,104,114,101,115,104,0,97,111,95,97,100,97,112,116,95,115,112,101,101,100,95,102,97,99,0,97,111,95,97, +112,112,114,111,120,95,101,114,114,111,114,0,97,111,95,97,112,112,114,111,120,95,99,111,114,114,101,99,116,105,111,110, +0,97,111,95,115,97,109,112,95,109,101,116,104,111,100,0,97,111,95,103,97,116,104,101,114,95,109,101,116,104,111,100, +0,97,111,95,97,112,112,114,111,120,95,112,97,115,115,101,115,0,42,97,111,115,112,104,101,114,101,0,42,97,111,116, +97,98,108,101,115,0,104,101,109,105,114,101,115,0,109,97,120,105,116,101,114,0,100,114,97,119,116,121,112,101,0,115, +117,98,115,104,111,111,116,112,0,115,117,98,115,104,111,111,116,101,0,110,111,100,101,108,105,109,0,109,97,120,115,117, +98,108,97,109,112,0,112,97,109,97,0,112,97,109,105,0,101,108,109,97,0,101,108,109,105,0,109,97,120,110,111,100, +101,0,99,111,110,118,101,114,103,101,110,99,101,0,114,97,100,102,97,99,0,103,97,109,109,97,0,115,101,108,99,111, +108,0,115,120,0,115,121,0,42,108,112,70,111,114,109,97,116,0,42,108,112,80,97,114,109,115,0,99,98,70,111,114, +109,97,116,0,99,98,80,97,114,109,115,0,102,99,99,84,121,112,101,0,102,99,99,72,97,110,100,108,101,114,0,100, +119,75,101,121,70,114,97,109,101,69,118,101,114,121,0,100,119,81,117,97,108,105,116,121,0,100,119,66,121,116,101,115, +80,101,114,83,101,99,111,110,100,0,100,119,70,108,97,103,115,0,100,119,73,110,116,101,114,108,101,97,118,101,69,118, +101,114,121,0,97,118,105,99,111,100,101,99,110,97,109,101,91,49,50,56,93,0,42,99,100,80,97,114,109,115,0,42, +112,97,100,0,99,100,83,105,122,101,0,113,116,99,111,100,101,99,110,97,109,101,91,49,50,56,93,0,99,111,100,101, +99,0,97,117,100,105,111,95,99,111,100,101,99,0,118,105,100,101,111,95,98,105,116,114,97,116,101,0,97,117,100,105, +111,95,98,105,116,114,97,116,101,0,103,111,112,95,115,105,122,101,0,114,99,95,109,105,110,95,114,97,116,101,0,114, +99,95,109,97,120,95,114,97,116,101,0,114,99,95,98,117,102,102,101,114,95,115,105,122,101,0,109,117,120,95,112,97, +99,107,101,116,95,115,105,122,101,0,109,117,120,95,114,97,116,101,0,109,105,120,114,97,116,101,0,109,97,105,110,0, +42,109,97,116,95,111,118,101,114,114,105,100,101,0,42,108,105,103,104,116,95,111,118,101,114,114,105,100,101,0,108,97, +121,95,122,109,97,115,107,0,108,97,121,102,108,97,103,0,112,97,115,115,102,108,97,103,0,112,97,115,115,95,120,111, +114,0,42,97,118,105,99,111,100,101,99,100,97,116,97,0,42,113,116,99,111,100,101,99,100,97,116,97,0,102,102,99, +111,100,101,99,100,97,116,97,0,99,102,114,97,0,112,115,102,114,97,0,112,101,102,114,97,0,105,109,97,103,101,115, +0,102,114,97,109,97,112,116,111,0,116,104,114,101,97,100,115,0,102,114,97,109,101,108,101,110,0,98,108,117,114,102, +97,99,0,101,100,103,101,82,0,101,100,103,101,71,0,101,100,103,101,66,0,102,117,108,108,115,99,114,101,101,110,0, +120,112,108,97,121,0,121,112,108,97,121,0,102,114,101,113,112,108,97,121,0,97,116,116,114,105,98,0,114,116,49,0, +115,116,101,114,101,111,109,111,100,101,0,100,105,109,101,110,115,105,111,110,115,112,114,101,115,101,116,0,109,97,120,105, +109,115,105,122,101,0,120,115,99,104,0,121,115,99,104,0,120,112,97,114,116,115,0,121,112,97,114,116,115,0,119,105, +110,112,111,115,0,112,108,97,110,101,115,0,105,109,116,121,112,101,0,115,117,98,105,109,116,121,112,101,0,113,117,97, +108,105,116,121,0,114,112,97,100,0,114,112,97,100,49,0,114,112,97,100,50,0,115,99,101,109,111,100,101,0,114,101, +110,100,101,114,101,114,0,111,99,114,101,115,0,97,108,112,104,97,109,111,100,101,0,111,115,97,0,102,114,115,95,115, +101,99,0,101,100,103,101,105,110,116,0,115,97,102,101,116,121,0,98,111,114,100,101,114,0,100,105,115,112,114,101,99, +116,0,108,97,121,101,114,115,0,97,99,116,108,97,121,0,120,97,115,112,0,121,97,115,112,0,102,114,115,95,115,101, +99,95,98,97,115,101,0,103,97,117,115,115,0,112,111,115,116,109,117,108,0,112,111,115,116,103,97,109,109,97,0,112, +111,115,116,104,117,101,0,112,111,115,116,115,97,116,0,100,105,116,104,101,114,95,105,110,116,101,110,115,105,116,121,0, +98,97,107,101,95,111,115,97,0,98,97,107,101,95,102,105,108,116,101,114,0,98,97,107,101,95,109,111,100,101,0,98, +97,107,101,95,102,108,97,103,0,98,97,107,101,95,110,111,114,109,97,108,95,115,112,97,99,101,0,98,97,107,101,95, +113,117,97,100,95,115,112,108,105,116,0,98,97,107,101,95,109,97,120,100,105,115,116,0,98,97,107,101,95,98,105,97, +115,100,105,115,116,0,98,97,107,101,95,112,97,100,0,71,73,113,117,97,108,105,116,121,0,71,73,99,97,99,104,101, +0,71,73,109,101,116,104,111,100,0,71,73,112,104,111,116,111,110,115,0,71,73,100,105,114,101,99,116,0,89,70,95, +65,65,0,89,70,101,120,112,111,114,116,120,109,108,0,89,70,95,110,111,98,117,109,112,0,89,70,95,99,108,97,109, +112,114,103,98,0,121,102,112,97,100,49,0,71,73,100,101,112,116,104,0,71,73,99,97,117,115,100,101,112,116,104,0, +71,73,112,105,120,101,108,115,112,101,114,115,97,109,112,108,101,0,71,73,112,104,111,116,111,110,99,111,117,110,116,0, +71,73,109,105,120,112,104,111,116,111,110,115,0,71,73,112,104,111,116,111,110,114,97,100,105,117,115,0,89,70,95,114, +97,121,100,101,112,116,104,0,89,70,95,65,65,112,97,115,115,101,115,0,89,70,95,65,65,115,97,109,112,108,101,115, +0,121,102,112,97,100,50,0,71,73,115,104,97,100,111,119,113,117,97,108,105,116,121,0,71,73,114,101,102,105,110,101, +109,101,110,116,0,71,73,112,111,119,101,114,0,71,73,105,110,100,105,114,112,111,119,101,114,0,89,70,95,103,97,109, +109,97,0,89,70,95,101,120,112,111,115,117,114,101,0,89,70,95,114,97,121,98,105,97,115,0,89,70,95,65,65,112, +105,120,101,108,115,105,122,101,0,89,70,95,65,65,116,104,114,101,115,104,111,108,100,0,98,97,99,107,98,117,102,91, +49,54,48,93,0,112,105,99,91,49,54,48,93,0,115,116,97,109,112,0,115,116,97,109,112,95,102,111,110,116,95,105, +100,0,115,116,97,109,112,95,117,100,97,116,97,91,49,54,48,93,0,102,103,95,115,116,97,109,112,91,52,93,0,98, +103,95,115,116,97,109,112,91,52,93,0,115,105,109,112,108,105,102,121,95,115,117,98,115,117,114,102,0,115,105,109,112, +108,105,102,121,95,115,104,97,100,111,119,115,97,109,112,108,101,115,0,115,105,109,112,108,105,102,121,95,112,97,114,116, +105,99,108,101,115,0,115,105,109,112,108,105,102,121,95,97,111,115,115,115,0,99,105,110,101,111,110,119,104,105,116,101, +0,99,105,110,101,111,110,98,108,97,99,107,0,99,105,110,101,111,110,103,97,109,109,97,0,106,112,50,95,112,114,101, +115,101,116,0,106,112,50,95,100,101,112,116,104,0,114,112,97,100,51,0,100,111,109,101,114,101,115,0,100,111,109,101, +109,111,100,101,0,100,111,109,101,97,110,103,108,101,0,100,111,109,101,116,105,108,116,0,100,111,109,101,114,101,115,98, +117,102,0,42,100,111,109,101,116,101,120,116,0,112,97,114,116,105,99,108,101,95,112,101,114,99,0,115,117,98,115,117, +114,102,95,109,97,120,0,115,104,97,100,98,117,102,115,97,109,112,108,101,95,109,97,120,0,97,111,95,101,114,114,111, +114,0,99,111,108,91,51,93,0,102,114,97,109,101,0,110,97,109,101,91,54,52,93,0,42,98,114,117,115,104,0,116, +111,111,108,0,115,101,97,109,95,98,108,101,101,100,0,110,111,114,109,97,108,95,97,110,103,108,101,0,115,116,101,112, +0,105,110,118,101,114,116,0,116,111,116,114,101,107,101,121,0,116,111,116,97,100,100,107,101,121,0,98,114,117,115,104, +116,121,112,101,0,98,114,117,115,104,91,55,93,0,101,109,105,116,116,101,114,100,105,115,116,0,100,114,97,119,95,116, +105,109,101,100,0,110,97,109,101,91,51,54,93,0,109,97,116,91,51,93,91,51,93,0,99,111,114,110,101,114,116,121, +112,101,0,101,100,105,116,98,117,116,102,108,97,103,0,106,111,105,110,116,114,105,108,105,109,105,116,0,100,101,103,114, +0,116,117,114,110,0,101,120,116,114,95,111,102,102,115,0,100,111,117,98,108,105,109,105,116,0,115,101,103,109,101,110, +116,115,0,114,105,110,103,115,0,118,101,114,116,105,99,101,115,0,117,110,119,114,97,112,112,101,114,0,117,118,99,97, +108,99,95,114,97,100,105,117,115,0,117,118,99,97,108,99,95,99,117,98,101,115,105,122,101,0,117,118,99,97,108,99, +95,109,97,114,103,105,110,0,117,118,99,97,108,99,95,109,97,112,100,105,114,0,117,118,99,97,108,99,95,109,97,112, +97,108,105,103,110,0,117,118,99,97,108,99,95,102,108,97,103,0,97,117,116,111,105,107,95,99,104,97,105,110,108,101, +110,0,105,109,97,112,97,105,110,116,0,112,97,114,116,105,99,108,101,0,115,101,108,101,99,116,95,116,104,114,101,115, +104,0,99,108,101,97,110,95,116,104,114,101,115,104,0,114,101,116,111,112,111,95,109,111,100,101,0,114,101,116,111,112, +111,95,112,97,105,110,116,95,116,111,111,108,0,108,105,110,101,95,100,105,118,0,101,108,108,105,112,115,101,95,100,105, +118,0,114,101,116,111,112,111,95,104,111,116,115,112,111,116,0,109,117,108,116,105,114,101,115,95,115,117,98,100,105,118, +95,116,121,112,101,0,115,107,103,101,110,95,114,101,115,111,108,117,116,105,111,110,0,115,107,103,101,110,95,116,104,114, +101,115,104,111,108,100,95,105,110,116,101,114,110,97,108,0,115,107,103,101,110,95,116,104,114,101,115,104,111,108,100,95, +101,120,116,101,114,110,97,108,0,115,107,103,101,110,95,108,101,110,103,116,104,95,114,97,116,105,111,0,115,107,103,101, +110,95,108,101,110,103,116,104,95,108,105,109,105,116,0,115,107,103,101,110,95,97,110,103,108,101,95,108,105,109,105,116, +0,115,107,103,101,110,95,99,111,114,114,101,108,97,116,105,111,110,95,108,105,109,105,116,0,115,107,103,101,110,95,115, +121,109,109,101,116,114,121,95,108,105,109,105,116,0,115,107,103,101,110,95,114,101,116,97,114,103,101,116,95,97,110,103, +108,101,95,119,101,105,103,104,116,0,115,107,103,101,110,95,114,101,116,97,114,103,101,116,95,108,101,110,103,116,104,95, +119,101,105,103,104,116,0,115,107,103,101,110,95,114,101,116,97,114,103,101,116,95,100,105,115,116,97,110,99,101,95,119, +101,105,103,104,116,0,115,107,103,101,110,95,111,112,116,105,111,110,115,0,115,107,103,101,110,95,112,111,115,116,112,114, +111,0,115,107,103,101,110,95,112,111,115,116,112,114,111,95,112,97,115,115,101,115,0,115,107,103,101,110,95,115,117,98, +100,105,118,105,115,105,111,110,115,91,51,93,0,115,107,103,101,110,95,109,117,108,116,105,95,108,101,118,101,108,0,42, +115,107,103,101,110,95,116,101,109,112,108,97,116,101,0,98,111,110,101,95,115,107,101,116,99,104,105,110,103,0,98,111, +110,101,95,115,107,101,116,99,104,105,110,103,95,99,111,110,118,101,114,116,0,115,107,103,101,110,95,115,117,98,100,105, +118,105,115,105,111,110,95,110,117,109,98,101,114,0,115,107,103,101,110,95,114,101,116,97,114,103,101,116,95,111,112,116, +105,111,110,115,0,115,107,103,101,110,95,114,101,116,97,114,103,101,116,95,114,111,108,108,0,115,107,103,101,110,95,115, +105,100,101,95,115,116,114,105,110,103,91,56,93,0,115,107,103,101,110,95,110,117,109,95,115,116,114,105,110,103,91,56, +93,0,101,100,103,101,95,109,111,100,101,0,112,97,100,51,91,50,93,0,100,105,114,0,118,105,101,119,0,42,115,101, +115,115,105,111,110,0,42,99,117,109,97,112,0,100,114,97,119,98,114,117,115,104,0,115,109,111,111,116,104,98,114,117, +115,104,0,112,105,110,99,104,98,114,117,115,104,0,105,110,102,108,97,116,101,98,114,117,115,104,0,103,114,97,98,98, +114,117,115,104,0,108,97,121,101,114,98,114,117,115,104,0,102,108,97,116,116,101,110,98,114,117,115,104,0,112,105,118, +111,116,91,51,93,0,98,114,117,115,104,95,116,121,112,101,0,116,101,120,110,114,0,116,101,120,114,101,112,116,0,116, +101,120,102,97,100,101,0,116,101,120,115,101,112,0,97,118,101,114,97,103,105,110,103,0,116,97,98,108,101,116,95,115, +105,122,101,0,116,97,98,108,101,116,95,115,116,114,101,110,103,116,104,0,115,121,109,109,0,114,97,107,101,0,97,120, +105,115,108,111,99,107,0,42,99,97,109,101,114,97,0,42,119,111,114,108,100,0,42,115,101,116,0,98,97,115,101,0, +42,98,97,115,97,99,116,0,99,117,114,115,111,114,91,51,93,0,116,119,99,101,110,116,91,51,93,0,116,119,109,105, +110,91,51,93,0,116,119,109,97,120,91,51,93,0,101,100,105,116,98,117,116,115,105,122,101,0,115,101,108,101,99,116, +109,111,100,101,0,112,114,111,112,111,114,116,105,111,110,97,108,0,112,114,111,112,95,109,111,100,101,0,97,117,116,111, +109,101,114,103,101,0,112,97,100,53,0,112,97,100,54,0,97,117,116,111,107,101,121,95,109,111,100,101,0,42,101,100, +0,42,114,97,100,105,111,0,102,114,97,109,105,110,103,0,42,116,111,111,108,115,101,116,116,105,110,103,115,0,97,117, +100,105,111,0,116,114,97,110,115,102,111,114,109,95,115,112,97,99,101,115,0,106,117,109,112,102,114,97,109,101,0,115, +110,97,112,95,109,111,100,101,0,115,110,97,112,95,102,108,97,103,0,115,110,97,112,95,116,97,114,103,101,116,0,42, +116,104,101,68,97,103,0,100,97,103,105,115,118,97,108,105,100,0,100,97,103,102,108,97,103,115,0,115,99,117,108,112, +116,100,97,116,97,0,102,114,97,109,101,95,115,116,101,112,0,122,111,111,109,0,98,108,101,110,100,0,120,105,109,0, +121,105,109,0,115,112,97,99,101,116,121,112,101,0,98,108,111,99,107,115,99,97,108,101,0,42,97,114,101,97,0,98, +108,111,99,107,104,97,110,100,108,101,114,91,56,93,0,118,105,101,119,109,97,116,91,52,93,91,52,93,0,118,105,101, +119,105,110,118,91,52,93,91,52,93,0,112,101,114,115,109,97,116,91,52,93,91,52,93,0,112,101,114,115,105,110,118, +91,52,93,91,52,93,0,119,105,110,109,97,116,49,91,52,93,91,52,93,0,118,105,101,119,109,97,116,49,91,52,93, +91,52,93,0,118,105,101,119,113,117,97,116,91,52,93,0,122,102,97,99,0,108,97,121,95,117,115,101,100,0,112,101, +114,115,112,0,42,111,98,95,99,101,110,116,114,101,0,42,98,103,112,105,99,0,42,108,111,99,97,108,118,100,0,42, +114,105,0,42,114,101,116,111,112,111,95,118,105,101,119,95,100,97,116,97,0,42,100,101,112,116,104,115,0,111,98,95, +99,101,110,116,114,101,95,98,111,110,101,91,51,50,93,0,108,111,99,97,108,118,105,101,119,0,108,97,121,97,99,116, +0,115,99,101,110,101,108,111,99,107,0,97,114,111,117,110,100,0,99,97,109,122,111,111,109,0,112,105,118,111,116,95, +108,97,115,116,0,103,114,105,100,0,103,114,105,100,118,105,101,119,0,112,105,120,115,105,122,101,0,110,101,97,114,0, +102,97,114,0,99,97,109,100,120,0,99,97,109,100,121,0,103,114,105,100,108,105,110,101,115,0,118,105,101,119,98,117, +116,0,103,114,105,100,102,108,97,103,0,109,111,100,101,115,101,108,101,99,116,0,116,119,116,121,112,101,0,116,119,109, +111,100,101,0,116,119,102,108,97,103,0,116,119,100,114,97,119,102,108,97,103,0,116,119,109,97,116,91,52,93,91,52, +93,0,99,108,105,112,91,52,93,91,52,93,0,42,99,108,105,112,98,98,0,97,102,116,101,114,100,114,97,119,0,122, +98,117,102,0,120,114,97,121,0,102,108,97,103,50,0,103,114,105,100,115,117,98,100,105,118,0,107,101,121,102,108,97, +103,115,0,110,100,111,102,109,111,100,101,0,110,100,111,102,102,105,108,116,101,114,0,42,112,114,111,112,101,114,116,105, +101,115,95,115,116,111,114,97,103,101,0,42,103,112,100,0,108,118,105,101,119,113,117,97,116,91,52,93,0,108,112,101, +114,115,112,0,108,118,105,101,119,0,118,101,114,116,0,104,111,114,0,109,97,115,107,0,109,105,110,91,50,93,0,109, +97,120,91,50,93,0,109,105,110,122,111,111,109,0,109,97,120,122,111,111,109,0,115,99,114,111,108,108,0,107,101,101, +112,116,111,116,0,107,101,101,112,97,115,112,101,99,116,0,107,101,101,112,122,111,111,109,0,111,108,100,119,105,110,120, +0,111,108,100,119,105,110,121,0,99,117,114,115,111,114,91,50,93,0,114,111,119,98,117,116,0,118,50,100,0,42,101, +100,105,116,105,112,111,0,105,112,111,107,101,121,0,97,99,116,110,97,109,101,91,51,50,93,0,99,111,110,115,116,110, +97,109,101,91,51,50,93,0,98,111,110,101,110,97,109,101,91,51,50,93,0,116,111,116,105,112,111,0,112,105,110,0, +98,117,116,111,102,115,0,99,104,97,110,110,101,108,0,108,111,99,107,0,109,101,100,105,97,110,91,51,93,0,99,117, +114,115,101,110,115,0,99,117,114,97,99,116,0,97,108,105,103,110,0,116,97,98,111,0,109,97,105,110,98,0,109,97, +105,110,98,111,0,42,108,111,99,107,112,111,105,110,0,116,101,120,102,114,111,109,0,115,104,111,119,103,114,111,117,112, +0,109,111,100,101,108,116,121,112,101,0,115,99,114,105,112,116,98,108,111,99,107,0,114,101,95,97,108,105,103,110,0, +111,108,100,107,101,121,112,114,101,115,115,0,116,97,98,91,55,93,0,114,101,110,100,101,114,95,115,105,122,101,0,99, +104,97,110,115,104,111,119,110,0,122,101,98,114,97,0,42,102,105,108,101,108,105,115,116,0,116,111,116,102,105,108,101, +0,116,105,116,108,101,91,50,52,93,0,100,105,114,91,50,52,48,93,0,102,105,108,101,91,56,48,93,0,111,102,115, +0,115,111,114,116,0,109,97,120,110,97,109,101,108,101,110,0,99,111,108,108,117,109,115,0,102,95,102,112,0,102,112, +95,115,116,114,91,56,93,0,42,108,105,98,102,105,108,101,100,97,116,97,0,114,101,116,118,97,108,0,109,101,110,117, +0,97,99,116,0,40,42,114,101,116,117,114,110,102,117,110,99,41,40,41,0,40,42,114,101,116,117,114,110,102,117,110, +99,95,101,118,101,110,116,41,40,41,0,40,42,114,101,116,117,114,110,102,117,110,99,95,97,114,103,115,41,40,41,0, +42,97,114,103,49,0,42,97,114,103,50,0,42,109,101,110,117,112,0,42,112,117,112,109,101,110,117,0,111,111,112,115, +0,118,105,115,105,102,108,97,103,0,116,114,101,101,0,42,116,114,101,101,115,116,111,114,101,0,115,101,97,114,99,104, +95,115,116,114,105,110,103,91,51,50,93,0,115,101,97,114,99,104,95,116,115,101,0,115,101,97,114,99,104,95,102,108, +97,103,115,0,100,111,95,0,111,117,116,108,105,110,101,118,105,115,0,115,116,111,114,101,102,108,97,103,0,100,101,112, +115,95,102,108,97,103,115,0,105,109,97,110,114,0,99,117,114,116,105,108,101,0,105,109,116,121,112,101,110,114,0,100, +116,95,117,118,0,115,116,105,99,107,121,0,100,116,95,117,118,115,116,114,101,116,99,104,0,112,97,100,91,53,93,0, +99,101,110,116,120,0,99,101,110,116,121,0,97,117,116,111,115,110,97,112,0,42,116,101,120,116,0,116,111,112,0,118, +105,101,119,108,105,110,101,115,0,102,111,110,116,95,105,100,0,108,104,101,105,103,104,116,0,108,101,102,116,0,115,104, +111,119,108,105,110,101,110,114,115,0,116,97,98,110,117,109,98,101,114,0,99,117,114,114,116,97,98,95,115,101,116,0, +115,104,111,119,115,121,110,116,97,120,0,111,118,101,114,119,114,105,116,101,0,112,105,120,95,112,101,114,95,108,105,110, +101,0,116,120,116,115,99,114,111,108,108,0,116,120,116,98,97,114,0,119,111,114,100,119,114,97,112,0,100,111,112,108, +117,103,105,110,115,0,42,112,121,95,100,114,97,119,0,42,112,121,95,101,118,101,110,116,0,42,112,121,95,98,117,116, +116,111,110,0,42,112,121,95,98,114,111,119,115,101,114,99,97,108,108,98,97,99,107,0,42,112,121,95,103,108,111,98, +97,108,100,105,99,116,0,108,97,115,116,115,112,97,99,101,0,115,99,114,105,112,116,110,97,109,101,91,50,53,54,93, +0,115,99,114,105,112,116,97,114,103,91,50,53,54,93,0,42,115,99,114,105,112,116,0,42,98,117,116,95,114,101,102, +115,0,114,101,100,114,97,119,115,0,42,105,100,0,97,115,112,101,99,116,0,42,99,117,114,102,111,110,116,0,42,101, +100,105,116,116,114,101,101,0,116,114,101,101,116,121,112,101,0,42,102,105,108,101,115,0,97,99,116,105,118,101,95,102, +105,108,101,0,110,117,109,116,105,108,101,115,120,0,110,117,109,116,105,108,101,115,121,0,115,101,108,115,116,97,116,101, +0,118,105,101,119,114,101,99,116,0,98,111,111,107,109,97,114,107,114,101,99,116,0,115,99,114,111,108,108,112,111,115, +0,115,99,114,111,108,108,104,101,105,103,104,116,0,115,99,114,111,108,108,97,114,101,97,0,97,99,116,105,118,101,95, +98,111,111,107,109,97,114,107,0,112,114,118,95,119,0,112,114,118,95,104,0,42,105,109,103,0,111,117,116,108,105,110, +101,91,52,93,0,110,101,117,116,114,97,108,91,52,93,0,97,99,116,105,111,110,91,52,93,0,115,101,116,116,105,110, +103,91,52,93,0,115,101,116,116,105,110,103,49,91,52,93,0,115,101,116,116,105,110,103,50,91,52,93,0,110,117,109, +91,52,93,0,116,101,120,116,102,105,101,108,100,91,52,93,0,116,101,120,116,102,105,101,108,100,95,104,105,91,52,93, +0,112,111,112,117,112,91,52,93,0,116,101,120,116,91,52,93,0,116,101,120,116,95,104,105,91,52,93,0,109,101,110, +117,95,98,97,99,107,91,52,93,0,109,101,110,117,95,105,116,101,109,91,52,93,0,109,101,110,117,95,104,105,108,105, +116,101,91,52,93,0,109,101,110,117,95,116,101,120,116,91,52,93,0,109,101,110,117,95,116,101,120,116,95,104,105,91, +52,93,0,98,117,116,95,100,114,97,119,116,121,112,101,0,105,99,111,110,102,105,108,101,91,56,48,93,0,98,97,99, +107,91,52,93,0,104,101,97,100,101,114,91,52,93,0,112,97,110,101,108,91,52,93,0,115,104,97,100,101,49,91,52, +93,0,115,104,97,100,101,50,91,52,93,0,104,105,108,105,116,101,91,52,93,0,103,114,105,100,91,52,93,0,119,105, +114,101,91,52,93,0,115,101,108,101,99,116,91,52,93,0,108,97,109,112,91,52,93,0,97,99,116,105,118,101,91,52, +93,0,103,114,111,117,112,91,52,93,0,103,114,111,117,112,95,97,99,116,105,118,101,91,52,93,0,116,114,97,110,115, +102,111,114,109,91,52,93,0,118,101,114,116,101,120,91,52,93,0,118,101,114,116,101,120,95,115,101,108,101,99,116,91, +52,93,0,101,100,103,101,91,52,93,0,101,100,103,101,95,115,101,108,101,99,116,91,52,93,0,101,100,103,101,95,115, +101,97,109,91,52,93,0,101,100,103,101,95,115,104,97,114,112,91,52,93,0,101,100,103,101,95,102,97,99,101,115,101, +108,91,52,93,0,102,97,99,101,91,52,93,0,102,97,99,101,95,115,101,108,101,99,116,91,52,93,0,102,97,99,101, +95,100,111,116,91,52,93,0,110,111,114,109,97,108,91,52,93,0,98,111,110,101,95,115,111,108,105,100,91,52,93,0, +98,111,110,101,95,112,111,115,101,91,52,93,0,115,116,114,105,112,91,52,93,0,115,116,114,105,112,95,115,101,108,101, +99,116,91,52,93,0,99,102,114,97,109,101,91,52,93,0,118,101,114,116,101,120,95,115,105,122,101,0,102,97,99,101, +100,111,116,95,115,105,122,101,0,98,112,97,100,91,50,93,0,115,121,110,116,97,120,108,91,52,93,0,115,121,110,116, +97,120,110,91,52,93,0,115,121,110,116,97,120,98,91,52,93,0,115,121,110,116,97,120,118,91,52,93,0,115,121,110, +116,97,120,99,91,52,93,0,109,111,118,105,101,91,52,93,0,105,109,97,103,101,91,52,93,0,115,99,101,110,101,91, +52,93,0,97,117,100,105,111,91,52,93,0,101,102,102,101,99,116,91,52,93,0,112,108,117,103,105,110,91,52,93,0, +116,114,97,110,115,105,116,105,111,110,91,52,93,0,109,101,116,97,91,52,93,0,101,100,105,116,109,101,115,104,95,97, +99,116,105,118,101,91,52,93,0,104,97,110,100,108,101,95,118,101,114,116,101,120,91,52,93,0,104,97,110,100,108,101, +95,118,101,114,116,101,120,95,115,101,108,101,99,116,91,52,93,0,104,97,110,100,108,101,95,118,101,114,116,101,120,95, +115,105,122,101,0,104,112,97,100,91,55,93,0,115,111,108,105,100,91,52,93,0,116,117,105,0,116,98,117,116,115,0, +116,118,51,100,0,116,102,105,108,101,0,116,105,112,111,0,116,105,110,102,111,0,116,115,110,100,0,116,97,99,116,0, +116,110,108,97,0,116,115,101,113,0,116,105,109,97,0,116,105,109,97,115,101,108,0,116,101,120,116,0,116,111,111,112, +115,0,116,116,105,109,101,0,116,110,111,100,101,0,116,97,114,109,91,50,48,93,0,98,112,97,100,91,52,93,0,98, +112,97,100,49,91,52,93,0,115,112,101,99,91,52,93,0,100,117,112,102,108,97,103,0,115,97,118,101,116,105,109,101, +0,116,101,109,112,100,105,114,91,49,54,48,93,0,102,111,110,116,100,105,114,91,49,54,48,93,0,114,101,110,100,101, +114,100,105,114,91,49,54,48,93,0,116,101,120,116,117,100,105,114,91,49,54,48,93,0,112,108,117,103,116,101,120,100, +105,114,91,49,54,48,93,0,112,108,117,103,115,101,113,100,105,114,91,49,54,48,93,0,112,121,116,104,111,110,100,105, +114,91,49,54,48,93,0,115,111,117,110,100,100,105,114,91,49,54,48,93,0,121,102,101,120,112,111,114,116,100,105,114, +91,49,54,48,93,0,118,101,114,115,105,111,110,115,0,118,114,109,108,102,108,97,103,0,103,97,109,101,102,108,97,103, +115,0,119,104,101,101,108,108,105,110,101,115,99,114,111,108,108,0,117,105,102,108,97,103,0,108,97,110,103,117,97,103, +101,0,117,115,101,114,112,114,101,102,0,118,105,101,119,122,111,111,109,0,99,111,110,115,111,108,101,95,98,117,102,102, +101,114,0,99,111,110,115,111,108,101,95,111,117,116,0,109,105,120,98,117,102,115,105,122,101,0,102,111,110,116,115,105, +122,101,0,101,110,99,111,100,105,110,103,0,116,114,97,110,115,111,112,116,115,0,109,101,110,117,116,104,114,101,115,104, +111,108,100,49,0,109,101,110,117,116,104,114,101,115,104,111,108,100,50,0,102,111,110,116,110,97,109,101,91,50,53,54, +93,0,116,104,101,109,101,115,0,117,110,100,111,115,116,101,112,115,0,117,110,100,111,109,101,109,111,114,121,0,103,112, +95,109,97,110,104,97,116,116,101,110,100,105,115,116,0,103,112,95,101,117,99,108,105,100,101,97,110,100,105,115,116,0, +103,112,95,101,114,97,115,101,114,0,103,112,95,115,101,116,116,105,110,103,115,0,116,98,95,108,101,102,116,109,111,117, +115,101,0,116,98,95,114,105,103,104,116,109,111,117,115,101,0,108,105,103,104,116,91,51,93,0,116,119,95,104,111,116, +115,112,111,116,0,116,119,95,102,108,97,103,0,116,119,95,104,97,110,100,108,101,115,105,122,101,0,116,119,95,115,105, +122,101,0,116,101,120,116,105,109,101,111,117,116,0,116,101,120,99,111,108,108,101,99,116,114,97,116,101,0,109,101,109, +99,97,99,104,101,108,105,109,105,116,0,112,114,101,102,101,116,99,104,102,114,97,109,101,115,0,102,114,97,109,101,115, +101,114,118,101,114,112,111,114,116,0,112,97,100,95,114,111,116,95,97,110,103,108,101,0,111,98,99,101,110,116,101,114, +95,100,105,97,0,114,118,105,115,105,122,101,0,114,118,105,98,114,105,103,104,116,0,114,101,99,101,110,116,95,102,105, +108,101,115,0,115,109,111,111,116,104,95,118,105,101,119,116,120,0,103,108,114,101,115,108,105,109,105,116,0,110,100,111, +102,95,112,97,110,0,110,100,111,102,95,114,111,116,97,116,101,0,99,117,114,115,115,105,122,101,0,112,97,100,91,56, +93,0,118,101,114,115,101,109,97,115,116,101,114,91,49,54,48,93,0,118,101,114,115,101,117,115,101,114,91,49,54,48, +93,0,103,108,97,108,112,104,97,99,108,105,112,0,97,117,116,111,107,101,121,95,102,108,97,103,0,99,111,98,97,95, +119,101,105,103,104,116,0,118,101,114,116,98,97,115,101,0,101,100,103,101,98,97,115,101,0,97,114,101,97,98,97,115, +101,0,42,115,99,101,110,101,0,101,110,100,120,0,101,110,100,121,0,115,105,122,101,120,0,115,105,122,101,121,0,115, +99,101,110,101,110,114,0,115,99,114,101,101,110,110,114,0,102,117,108,108,0,109,97,105,110,119,105,110,0,119,105,110, +97,107,116,0,104,97,110,100,108,101,114,91,56,93,0,42,110,101,119,118,0,118,101,99,0,42,118,49,0,42,118,50, +0,112,97,110,101,108,110,97,109,101,91,54,52,93,0,116,97,98,110,97,109,101,91,54,52,93,0,100,114,97,119,110, +97,109,101,91,54,52,93,0,111,102,115,120,0,111,102,115,121,0,99,111,110,116,114,111,108,0,115,110,97,112,0,111, +108,100,95,111,102,115,120,0,111,108,100,95,111,102,115,121,0,115,111,114,116,99,111,117,110,116,101,114,0,42,112,97, +110,101,108,116,97,98,0,42,118,51,0,42,118,52,0,42,102,117,108,108,0,119,105,110,109,97,116,91,52,93,91,52, +93,0,104,101,97,100,114,99,116,0,119,105,110,114,99,116,0,104,101,97,100,119,105,110,0,119,105,110,0,104,101,97, +100,101,114,116,121,112,101,0,98,117,116,115,112,97,99,101,116,121,112,101,0,119,105,110,120,0,119,105,110,121,0,104, +101,97,100,95,115,119,97,112,0,104,101,97,100,95,101,113,117,97,108,0,119,105,110,95,115,119,97,112,0,119,105,110, +95,101,113,117,97,108,0,104,101,97,100,98,117,116,108,101,110,0,104,101,97,100,98,117,116,111,102,115,0,99,117,114, +115,111,114,0,115,112,97,99,101,100,97,116,97,0,117,105,98,108,111,99,107,115,0,112,97,110,101,108,115,0,115,117, +98,118,115,116,114,91,52,93,0,115,117,98,118,101,114,115,105,111,110,0,112,97,100,115,0,109,105,110,118,101,114,115, +105,111,110,0,109,105,110,115,117,98,118,101,114,115,105,111,110,0,100,105,115,112,108,97,121,109,111,100,101,0,42,99, +117,114,115,99,114,101,101,110,0,42,99,117,114,115,99,101,110,101,0,102,105,108,101,102,108,97,103,115,0,103,108,111, +98,97,108,102,0,110,97,109,101,91,56,48,93,0,42,105,98,117,102,0,42,105,98,117,102,95,99,111,109,112,0,42, +115,101,49,0,42,115,101,50,0,42,115,101,51,0,110,114,0,98,111,116,116,111,109,0,114,105,103,104,116,0,120,111, +102,115,0,121,111,102,115,0,108,105,102,116,91,51,93,0,103,97,109,109,97,91,51,93,0,103,97,105,110,91,51,93, +0,115,97,116,117,114,97,116,105,111,110,0,42,103,117,105,0,100,105,114,91,49,54,48,93,0,100,111,110,101,0,115, +116,97,114,116,115,116,105,108,108,0,101,110,100,115,116,105,108,108,0,42,115,116,114,105,112,100,97,116,97,0,111,114, +120,0,111,114,121,0,42,99,114,111,112,0,42,116,114,97,110,115,102,111,114,109,0,42,99,111,108,111,114,95,98,97, +108,97,110,99,101,0,42,116,115,116,114,105,112,100,97,116,97,0,42,116,115,116,114,105,112,100,97,116,97,95,115,116, +97,114,116,115,116,105,108,108,0,42,116,115,116,114,105,112,100,97,116,97,95,101,110,100,115,116,105,108,108,0,42,105, +98,117,102,95,115,116,97,114,116,115,116,105,108,108,0,42,105,98,117,102,95,101,110,100,115,116,105,108,108,0,42,105, +110,115,116,97,110,99,101,95,112,114,105,118,97,116,101,95,100,97,116,97,0,42,42,99,117,114,114,101,110,116,95,112, +114,105,118,97,116,101,95,100,97,116,97,0,42,116,109,112,0,115,116,97,114,116,111,102,115,0,101,110,100,111,102,115, +0,109,97,99,104,105,110,101,0,115,116,97,114,116,100,105,115,112,0,101,110,100,100,105,115,112,0,109,117,108,0,104, +97,110,100,115,105,122,101,0,97,110,105,109,95,112,114,101,115,101,101,107,0,42,115,116,114,105,112,0,102,97,99,102, +48,0,102,97,99,102,49,0,42,115,101,113,49,0,42,115,101,113,50,0,42,115,101,113,51,0,115,101,113,98,97,115, +101,0,42,115,111,117,110,100,0,42,104,100,97,117,100,105,111,0,108,101,118,101,108,0,112,97,110,0,115,116,114,111, +98,101,0,42,101,102,102,101,99,116,100,97,116,97,0,97,110,105,109,95,115,116,97,114,116,111,102,115,0,97,110,105, +109,95,101,110,100,111,102,115,0,98,108,101,110,100,95,109,111,100,101,0,98,108,101,110,100,95,111,112,97,99,105,116, +121,0,42,111,108,100,98,97,115,101,112,0,42,112,97,114,115,101,113,0,42,115,101,113,98,97,115,101,112,0,109,101, +116,97,115,116,97,99,107,0,101,100,103,101,87,105,100,116,104,0,102,111,114,119,97,114,100,0,119,105,112,101,116,121, +112,101,0,102,77,105,110,105,0,102,67,108,97,109,112,0,102,66,111,111,115,116,0,100,68,105,115,116,0,100,81,117, +97,108,105,116,121,0,98,78,111,67,111,109,112,0,83,99,97,108,101,120,73,110,105,0,83,99,97,108,101,121,73,110, +105,0,83,99,97,108,101,120,70,105,110,0,83,99,97,108,101,121,70,105,110,0,120,73,110,105,0,120,70,105,110,0, +121,73,110,105,0,121,70,105,110,0,114,111,116,73,110,105,0,114,111,116,70,105,110,0,105,110,116,101,114,112,111,108, +97,116,105,111,110,0,42,102,114,97,109,101,77,97,112,0,103,108,111,98,97,108,83,112,101,101,100,0,108,97,115,116, +86,97,108,105,100,70,114,97,109,101,0,98,108,101,110,100,70,114,97,109,101,115,0,98,117,116,116,121,112,101,0,117, +115,101,114,106,105,116,0,115,116,97,0,116,111,116,112,97,114,116,0,110,111,114,109,102,97,99,0,111,98,102,97,99, +0,114,97,110,100,102,97,99,0,116,101,120,102,97,99,0,114,97,110,100,108,105,102,101,0,102,111,114,99,101,91,51, +93,0,118,101,99,116,115,105,122,101,0,109,97,120,108,101,110,0,100,101,102,118,101,99,91,51,93,0,109,117,108,116, +91,52,93,0,108,105,102,101,91,52,93,0,99,104,105,108,100,91,52,93,0,109,97,116,91,52,93,0,116,101,120,109, +97,112,0,99,117,114,109,117,108,116,0,115,116,97,116,105,99,115,116,101,112,0,111,109,97,116,0,116,105,109,101,116, +101,120,0,115,112,101,101,100,116,101,120,0,102,108,97,103,50,110,101,103,0,118,101,114,116,103,114,111,117,112,95,118, +0,118,103,114,111,117,112,110,97,109,101,91,51,50,93,0,118,103,114,111,117,112,110,97,109,101,95,118,91,51,50,93, +0,42,107,101,121,115,0,109,105,110,102,97,99,0,117,115,101,100,0,117,115,101,100,101,108,101,109,0,100,120,0,100, +121,0,108,105,110,107,0,111,116,121,112,101,0,111,108,100,0,42,112,111,105,110,0,42,111,108,100,112,111,105,110,0, +114,101,115,101,116,100,105,115,116,0,108,97,115,116,118,97,108,0,42,109,97,0,107,101,121,0,113,117,97,108,0,113, +117,97,108,50,0,116,97,114,103,101,116,78,97,109,101,91,51,50,93,0,116,111,103,103,108,101,78,97,109,101,91,51, +50,93,0,118,97,108,117,101,91,51,50,93,0,109,97,120,118,97,108,117,101,91,51,50,93,0,100,101,108,97,121,0, +100,117,114,97,116,105,111,110,0,109,97,116,101,114,105,97,108,78,97,109,101,91,51,50,93,0,100,97,109,112,116,105, +109,101,114,0,112,114,111,112,110,97,109,101,91,51,50,93,0,109,97,116,110,97,109,101,91,51,50,93,0,97,120,105, +115,102,108,97,103,0,42,102,114,111,109,79,98,106,101,99,116,0,115,117,98,106,101,99,116,91,51,50,93,0,98,111, +100,121,91,51,50,93,0,112,117,108,115,101,0,102,114,101,113,0,116,111,116,108,105,110,107,115,0,42,42,108,105,110, +107,115,0,116,97,112,0,106,111,121,105,110,100,101,120,0,97,120,105,115,95,115,105,110,103,108,101,0,97,120,105,115, +102,0,98,117,116,116,111,110,0,104,97,116,0,104,97,116,102,0,112,114,101,99,105,115,105,111,110,0,115,116,114,91, +49,50,56,93,0,109,111,100,117,108,101,91,54,52,93,0,42,109,121,110,101,119,0,105,110,112,117,116,115,0,116,111, +116,115,108,105,110,107,115,0,42,42,115,108,105,110,107,115,0,118,97,108,111,0,115,116,97,116,101,95,109,97,115,107, +0,42,97,99,116,0,102,114,97,109,101,80,114,111,112,91,51,50,93,0,98,108,101,110,100,105,110,0,112,114,105,111, +114,105,116,121,0,101,110,100,95,114,101,115,101,116,0,115,116,114,105,100,101,97,120,105,115,0,115,116,114,105,100,101, +108,101,110,103,116,104,0,115,110,100,110,114,0,112,97,100,49,91,50,93,0,109,97,107,101,99,111,112,121,0,99,111, +112,121,109,97,100,101,0,112,97,100,50,91,49,93,0,116,114,97,99,107,0,42,109,101,0,108,105,110,86,101,108,111, +99,105,116,121,91,51,93,0,97,110,103,86,101,108,111,99,105,116,121,91,51,93,0,108,111,99,97,108,102,108,97,103, +0,100,121,110,95,111,112,101,114,97,116,105,111,110,0,102,111,114,99,101,108,111,99,91,51,93,0,102,111,114,99,101, +114,111,116,91,51,93,0,108,105,110,101,97,114,118,101,108,111,99,105,116,121,91,51,93,0,97,110,103,117,108,97,114, +118,101,108,111,99,105,116,121,91,51,93,0,42,114,101,102,101,114,101,110,99,101,0,98,117,116,115,116,97,0,98,117, +116,101,110,100,0,109,105,110,0,109,97,120,0,118,105,115,105,102,97,99,0,114,111,116,100,97,109,112,0,109,105,110, +108,111,99,91,51,93,0,109,97,120,108,111,99,91,51,93,0,109,105,110,114,111,116,91,51,93,0,109,97,120,114,111, +116,91,51,93,0,109,97,116,112,114,111,112,91,51,50,93,0,100,105,115,116,114,105,98,117,116,105,111,110,0,105,110, +116,95,97,114,103,95,49,0,105,110,116,95,97,114,103,95,50,0,102,108,111,97,116,95,97,114,103,95,49,0,102,108, +111,97,116,95,97,114,103,95,50,0,116,111,80,114,111,112,78,97,109,101,91,51,50,93,0,42,116,111,79,98,106,101, +99,116,0,98,111,100,121,84,121,112,101,0,102,105,108,101,110,97,109,101,91,54,52,93,0,108,111,97,100,97,110,105, +110,97,109,101,91,54,52,93,0,105,110,116,95,97,114,103,0,102,108,111,97,116,95,97,114,103,0,103,111,0,97,99, +99,101,108,108,101,114,97,116,105,111,110,0,109,97,120,115,112,101,101,100,0,109,97,120,114,111,116,115,112,101,101,100, +0,109,97,120,116,105,108,116,115,112,101,101,100,0,116,105,108,116,100,97,109,112,0,115,112,101,101,100,100,97,109,112, +0,42,115,97,109,112,108,101,0,42,115,116,114,101,97,109,0,42,110,101,119,112,97,99,107,101,100,102,105,108,101,0, +42,115,110,100,95,115,111,117,110,100,0,112,97,110,110,105,110,103,0,97,116,116,101,110,117,97,116,105,111,110,0,112, +105,116,99,104,0,109,105,110,95,103,97,105,110,0,109,97,120,95,103,97,105,110,0,100,105,115,116,97,110,99,101,0, +115,116,114,101,97,109,108,101,110,0,99,104,97,110,110,101,108,115,0,104,105,103,104,112,114,105,111,0,112,97,100,91, +49,48,93,0,103,97,105,110,0,100,111,112,112,108,101,114,102,97,99,116,111,114,0,100,111,112,112,108,101,114,118,101, +108,111,99,105,116,121,0,110,117,109,115,111,117,110,100,115,98,108,101,110,100,101,114,0,110,117,109,115,111,117,110,100, +115,103,97,109,101,101,110,103,105,110,101,0,42,108,97,109,112,114,101,110,0,103,111,98,106,101,99,116,0,100,117,112, +108,105,95,111,102,115,91,51,93,0,99,104,105,108,100,98,97,115,101,0,114,111,108,108,0,104,101,97,100,91,51,93, +0,116,97,105,108,91,51,93,0,98,111,110,101,95,109,97,116,91,51,93,91,51,93,0,97,114,109,95,104,101,97,100, +91,51,93,0,97,114,109,95,116,97,105,108,91,51,93,0,97,114,109,95,109,97,116,91,52,93,91,52,93,0,120,119, +105,100,116,104,0,122,119,105,100,116,104,0,101,97,115,101,49,0,101,97,115,101,50,0,114,97,100,95,104,101,97,100, +0,114,97,100,95,116,97,105,108,0,98,111,110,101,98,97,115,101,0,99,104,97,105,110,98,97,115,101,0,112,97,116, +104,102,108,97,103,0,108,97,121,101,114,95,112,114,111,116,101,99,116,101,100,0,103,104,111,115,116,101,112,0,103,104, +111,115,116,115,105,122,101,0,103,104,111,115,116,116,121,112,101,0,112,97,116,104,115,105,122,101,0,103,104,111,115,116, +115,102,0,103,104,111,115,116,101,102,0,112,97,116,104,115,102,0,112,97,116,104,101,102,0,112,97,116,104,98,99,0, +112,97,116,104,97,99,0,99,111,110,115,116,102,108,97,103,0,105,107,102,108,97,103,0,115,101,108,101,99,116,102,108, +97,103,0,97,103,114,112,95,105,110,100,101,120,0,42,98,111,110,101,0,42,99,104,105,108,100,0,105,107,116,114,101, +101,0,42,98,95,98,111,110,101,95,109,97,116,115,0,42,100,117,97,108,95,113,117,97,116,0,42,98,95,98,111,110, +101,95,100,117,97,108,95,113,117,97,116,115,0,99,104,97,110,95,109,97,116,91,52,93,91,52,93,0,112,111,115,101, +95,109,97,116,91,52,93,91,52,93,0,112,111,115,101,95,104,101,97,100,91,51,93,0,112,111,115,101,95,116,97,105, +108,91,51,93,0,108,105,109,105,116,109,105,110,91,51,93,0,108,105,109,105,116,109,97,120,91,51,93,0,115,116,105, +102,102,110,101,115,115,91,51,93,0,105,107,115,116,114,101,116,99,104,0,42,99,117,115,116,111,109,0,99,104,97,110, +98,97,115,101,0,112,114,111,120,121,95,108,97,121,101,114,0,115,116,114,105,100,101,95,111,102,102,115,101,116,91,51, +93,0,99,121,99,108,105,99,95,111,102,102,115,101,116,91,51,93,0,97,103,114,111,117,112,115,0,97,99,116,105,118, +101,95,103,114,111,117,112,0,99,117,115,116,111,109,67,111,108,0,99,115,0,42,103,114,112,0,114,101,115,101,114,118, +101,100,49,0,103,114,111,117,112,115,0,97,99,116,105,118,101,95,109,97,114,107,101,114,0,97,99,116,110,114,0,97, +99,116,119,105,100,116,104,0,116,105,109,101,115,108,105,100,101,0,110,97,109,101,91,51,48,93,0,111,119,110,115,112, +97,99,101,0,116,97,114,115,112,97,99,101,0,101,110,102,111,114,99,101,0,104,101,97,100,116,97,105,108,0,42,116, +97,114,0,115,117,98,116,97,114,103,101,116,91,51,50,93,0,109,97,116,114,105,120,91,52,93,91,52,93,0,115,112, +97,99,101,0,42,112,114,111,112,0,116,97,114,110,117,109,0,116,97,114,103,101,116,115,0,105,116,101,114,97,116,105, +111,110,115,0,114,111,111,116,98,111,110,101,0,109,97,120,95,114,111,111,116,98,111,110,101,0,42,112,111,108,101,116, +97,114,0,112,111,108,101,115,117,98,116,97,114,103,101,116,91,51,50,93,0,112,111,108,101,97,110,103,108,101,0,111, +114,105,101,110,116,119,101,105,103,104,116,0,103,114,97,98,116,97,114,103,101,116,91,51,93,0,114,101,115,101,114,118, +101,100,50,0,109,105,110,109,97,120,102,108,97,103,0,115,116,117,99,107,0,99,97,99,104,101,91,51,93,0,108,111, +99,107,102,108,97,103,0,102,111,108,108,111,119,102,108,97,103,0,118,111,108,109,111,100,101,0,112,108,97,110,101,0, +111,114,103,108,101,110,103,116,104,0,98,117,108,103,101,0,112,105,118,88,0,112,105,118,89,0,112,105,118,90,0,97, +120,88,0,97,120,89,0,97,120,90,0,109,105,110,76,105,109,105,116,91,54,93,0,109,97,120,76,105,109,105,116,91, +54,93,0,101,120,116,114,97,70,122,0,105,110,118,109,97,116,91,52,93,91,52,93,0,102,114,111,109,0,116,111,0, +109,97,112,91,51,93,0,101,120,112,111,0,102,114,111,109,95,109,105,110,91,51,93,0,102,114,111,109,95,109,97,120, +91,51,93,0,116,111,95,109,105,110,91,51,93,0,116,111,95,109,97,120,91,51,93,0,122,109,105,110,0,122,109,97, +120,0,112,97,100,91,57,93,0,99,104,97,110,110,101,108,91,51,50,93,0,110,111,95,114,111,116,95,97,120,105,115, +0,115,116,114,105,100,101,95,97,120,105,115,0,99,117,114,109,111,100,0,97,99,116,115,116,97,114,116,0,97,99,116, +101,110,100,0,97,99,116,111,102,102,115,0,115,116,114,105,100,101,108,101,110,0,98,108,101,110,100,111,117,116,0,115, +116,114,105,100,101,99,104,97,110,110,101,108,91,51,50,93,0,111,102,102,115,95,98,111,110,101,91,51,50,93,0,104, +97,115,105,110,112,117,116,0,104,97,115,111,117,116,112,117,116,0,100,97,116,97,116,121,112,101,0,115,111,99,107,101, +116,116,121,112,101,0,42,110,101,119,95,115,111,99,107,0,110,115,0,108,105,109,105,116,0,115,116,97,99,107,95,105, +110,100,101,120,0,105,110,116,101,114,110,0,115,116,97,99,107,95,105,110,100,101,120,95,101,120,116,0,108,111,99,120, +0,108,111,99,121,0,111,119,110,95,105,110,100,101,120,0,116,111,95,105,110,100,101,120,0,42,116,111,115,111,99,107, +0,42,108,105,110,107,0,42,110,101,119,95,110,111,100,101,0,117,115,101,114,110,97,109,101,91,51,50,93,0,108,97, +115,116,121,0,111,117,116,112,117,116,115,0,42,115,116,111,114,97,103,101,0,109,105,110,105,119,105,100,116,104,0,99, +117,115,116,111,109,49,0,99,117,115,116,111,109,50,0,99,117,115,116,111,109,51,0,99,117,115,116,111,109,52,0,110, +101,101,100,95,101,120,101,99,0,101,120,101,99,0,116,111,116,114,0,98,117,116,114,0,112,114,118,114,0,42,116,121, +112,101,105,110,102,111,0,42,102,114,111,109,110,111,100,101,0,42,116,111,110,111,100,101,0,42,102,114,111,109,115,111, +99,107,0,110,111,100,101,115,0,108,105,110,107,115,0,42,115,116,97,99,107,0,42,116,104,114,101,97,100,115,116,97, +99,107,0,105,110,105,116,0,115,116,97,99,107,115,105,122,101,0,99,117,114,95,105,110,100,101,120,0,97,108,108,116, +121,112,101,115,0,42,111,119,110,116,121,112,101,0,42,115,101,108,105,110,0,42,115,101,108,111,117,116,0,40,42,116, +105,109,101,99,117,114,115,111,114,41,40,41,0,40,42,115,116,97,116,115,95,100,114,97,119,41,40,41,0,40,42,116, +101,115,116,95,98,114,101,97,107,41,40,41,0,99,121,99,108,105,99,0,109,111,118,105,101,0,115,97,109,112,108,101, +115,0,109,105,110,115,112,101,101,100,0,112,101,114,99,101,110,116,120,0,112,101,114,99,101,110,116,121,0,98,111,107, +101,104,0,99,117,114,118,101,100,0,105,109,97,103,101,95,105,110,95,119,105,100,116,104,0,105,109,97,103,101,95,105, +110,95,104,101,105,103,104,116,0,99,101,110,116,101,114,95,120,0,99,101,110,116,101,114,95,121,0,115,112,105,110,0, +105,116,101,114,0,119,114,97,112,0,115,105,103,109,97,95,99,111,108,111,114,0,115,105,103,109,97,95,115,112,97,99, +101,0,104,117,101,0,115,97,116,0,116,49,0,116,50,0,116,51,0,102,115,116,114,101,110,103,116,104,0,102,97,108, +112,104,97,0,107,101,121,91,52,93,0,120,49,0,120,50,0,121,49,0,121,50,0,99,111,108,110,97,109,101,91,51, +50,93,0,98,107,116,121,112,101,0,114,111,116,97,116,105,111,110,0,112,114,101,118,105,101,119,0,103,97,109,99,111, +0,110,111,95,122,98,117,102,0,102,115,116,111,112,0,109,97,120,98,108,117,114,0,98,116,104,114,101,115,104,0,42, +100,105,99,116,0,42,110,111,100,101,0,97,110,103,108,101,95,111,102,115,0,99,111,108,109,111,100,0,109,105,120,0, +116,104,114,101,115,104,111,108,100,0,102,97,100,101,0,109,0,99,0,106,105,116,0,112,114,111,106,0,102,105,116,0, +115,104,111,114,116,121,0,109,105,110,116,97,98,108,101,0,109,97,120,116,97,98,108,101,0,101,120,116,95,105,110,91, +50,93,0,101,120,116,95,111,117,116,91,50,93,0,42,99,117,114,118,101,0,42,116,97,98,108,101,0,42,112,114,101, +109,117,108,116,97,98,108,101,0,99,117,114,114,0,99,108,105,112,114,0,99,109,91,52,93,0,98,108,97,99,107,91, +51,93,0,119,104,105,116,101,91,51,93,0,98,119,109,117,108,91,51,93,0,115,97,109,112,108,101,91,51,93,0,111, +102,102,115,101,116,91,50,93,0,105,110,110,101,114,114,97,100,105,117,115,0,114,97,116,101,0,114,103,98,91,51,93, +0,99,108,111,110,101,0,97,99,116,105,118,101,95,114,110,100,0,97,99,116,105,118,101,95,99,108,111,110,101,0,97, +99,116,105,118,101,95,109,97,115,107,0,42,108,97,121,101,114,115,0,116,111,116,108,97,121,101,114,0,109,97,120,108, +97,121,101,114,0,116,111,116,115,105,122,101,0,42,112,111,111,108,0,101,100,105,116,102,108,97,103,0,118,101,108,91, +51,93,0,114,111,116,91,52,93,0,97,118,101,91,51,93,0,110,117,109,0,112,97,114,101,110,116,0,112,97,91,52, +93,0,119,91,52,93,0,102,117,118,91,52,93,0,102,111,102,102,115,101,116,0,114,97,110,100,91,51,93,0,42,115, +116,105,99,107,95,111,98,0,112,114,101,118,95,115,116,97,116,101,0,42,104,97,105,114,0,105,95,114,111,116,91,52, +93,0,114,95,114,111,116,91,52,93,0,114,95,97,118,101,91,51,93,0,114,95,118,101,91,51,93,0,100,105,101,116, +105,109,101,0,98,97,110,107,0,115,105,122,101,109,117,108,0,110,117,109,95,100,109,99,97,99,104,101,0,98,112,105, +0,97,108,105,118,101,0,108,111,111,112,0,100,105,115,116,114,0,112,104,121,115,116,121,112,101,0,114,111,116,109,111, +100,101,0,97,118,101,109,111,100,101,0,114,101,97,99,116,101,118,101,110,116,0,100,114,97,119,0,100,114,97,119,95, +97,115,0,100,114,97,119,95,115,105,122,101,0,99,104,105,108,100,116,121,112,101,0,100,114,97,119,95,115,116,101,112, +0,114,101,110,95,115,116,101,112,0,104,97,105,114,95,115,116,101,112,0,107,101,121,115,95,115,116,101,112,0,97,100, +97,112,116,95,97,110,103,108,101,0,97,100,97,112,116,95,112,105,120,0,114,111,116,102,114,111,109,0,105,110,116,101, +103,114,97,116,111,114,0,110,98,101,116,119,101,101,110,0,98,111,105,100,110,101,105,103,104,98,111,117,114,115,0,98, +98,95,97,108,105,103,110,0,98,98,95,117,118,95,115,112,108,105,116,0,98,98,95,97,110,105,109,0,98,98,95,115, +112,108,105,116,95,111,102,102,115,101,116,0,98,98,95,116,105,108,116,0,98,98,95,114,97,110,100,95,116,105,108,116, +0,98,98,95,111,102,102,115,101,116,91,50,93,0,115,105,109,112,108,105,102,121,95,102,108,97,103,0,115,105,109,112, +108,105,102,121,95,114,101,102,115,105,122,101,0,115,105,109,112,108,105,102,121,95,114,97,116,101,0,115,105,109,112,108, +105,102,121,95,116,114,97,110,115,105,116,105,111,110,0,115,105,109,112,108,105,102,121,95,118,105,101,119,112,111,114,116, +0,116,105,109,101,116,119,101,97,107,0,106,105,116,102,97,99,0,107,101,121,101,100,95,116,105,109,101,0,101,102,102, +95,104,97,105,114,0,103,114,105,100,95,114,101,115,0,112,97,114,116,102,97,99,0,116,97,110,102,97,99,0,116,97, +110,112,104,97,115,101,0,114,101,97,99,116,102,97,99,0,97,118,101,102,97,99,0,112,104,97,115,101,102,97,99,0, +114,97,110,100,114,111,116,102,97,99,0,114,97,110,100,112,104,97,115,101,102,97,99,0,114,97,110,100,115,105,122,101, +0,114,101,97,99,116,115,104,97,112,101,0,97,99,99,91,51,93,0,100,114,97,103,102,97,99,0,98,114,111,119,110, +102,97,99,0,100,97,109,112,102,97,99,0,97,98,115,108,101,110,103,116,104,0,114,97,110,100,108,101,110,103,116,104, +0,99,104,105,108,100,95,110,98,114,0,114,101,110,95,99,104,105,108,100,95,110,98,114,0,112,97,114,101,110,116,115, +0,99,104,105,108,100,115,105,122,101,0,99,104,105,108,100,114,97,110,100,115,105,122,101,0,99,104,105,108,100,114,97, +100,0,99,104,105,108,100,102,108,97,116,0,99,104,105,108,100,115,112,114,101,97,100,0,99,108,117,109,112,102,97,99, +0,99,108,117,109,112,112,111,119,0,114,111,117,103,104,49,0,114,111,117,103,104,49,95,115,105,122,101,0,114,111,117, +103,104,50,0,114,111,117,103,104,50,95,115,105,122,101,0,114,111,117,103,104,50,95,116,104,114,101,115,0,114,111,117, +103,104,95,101,110,100,0,114,111,117,103,104,95,101,110,100,95,115,104,97,112,101,0,98,114,97,110,99,104,95,116,104, +114,101,115,0,100,114,97,119,95,108,105,110,101,91,50,93,0,109,97,120,95,108,97,116,95,97,99,99,0,109,97,120, +95,116,97,110,95,97,99,99,0,97,118,101,114,97,103,101,95,118,101,108,0,98,97,110,107,105,110,103,0,109,97,120, +95,98,97,110,107,0,103,114,111,117,110,100,122,0,98,111,105,100,102,97,99,91,56,93,0,98,111,105,100,114,117,108, +101,91,56,93,0,42,101,102,102,95,103,114,111,117,112,0,42,100,117,112,95,111,98,0,42,98,98,95,111,98,0,42, +112,100,50,0,42,112,97,114,116,0,42,101,100,105,116,0,42,42,112,97,116,104,99,97,99,104,101,0,42,42,99,104, +105,108,100,99,97,99,104,101,0,112,97,116,104,99,97,99,104,101,98,117,102,115,0,99,104,105,108,100,99,97,99,104, +101,98,117,102,115,0,42,116,97,114,103,101,116,95,111,98,0,42,107,101,121,101,100,95,111,98,0,42,108,97,116,116, +105,99,101,0,101,102,102,101,99,116,111,114,115,0,114,101,97,99,116,101,118,101,110,116,115,0,116,111,116,99,104,105, +108,100,0,116,111,116,99,97,99,104,101,100,0,116,111,116,99,104,105,108,100,99,97,99,104,101,0,116,97,114,103,101, +116,95,112,115,121,115,0,107,101,121,101,100,95,112,115,121,115,0,116,111,116,107,101,121,101,100,0,98,97,107,101,115, +112,97,99,101,0,98,98,95,117,118,110,97,109,101,91,51,93,91,51,50,93,0,118,103,114,111,117,112,91,49,50,93, +0,118,103,95,110,101,103,0,114,116,51,0,42,114,101,110,100,101,114,100,97,116,97,0,42,99,97,99,104,101,0,67, +100,105,115,0,67,118,105,0,91,51,93,0,115,116,114,117,99,116,117,114,97,108,0,98,101,110,100,105,110,103,0,109, +97,120,95,98,101,110,100,0,109,97,120,95,115,116,114,117,99,116,0,109,97,120,95,115,104,101,97,114,0,97,118,103, +95,115,112,114,105,110,103,95,108,101,110,0,116,105,109,101,115,99,97,108,101,0,101,102,102,95,102,111,114,99,101,95, +115,99,97,108,101,0,101,102,102,95,119,105,110,100,95,115,99,97,108,101,0,115,105,109,95,116,105,109,101,95,111,108, +100,0,115,116,101,112,115,80,101,114,70,114,97,109,101,0,112,114,101,114,111,108,108,0,109,97,120,115,112,114,105,110, +103,108,101,110,0,115,111,108,118,101,114,95,116,121,112,101,0,118,103,114,111,117,112,95,98,101,110,100,0,118,103,114, +111,117,112,95,109,97,115,115,0,118,103,114,111,117,112,95,115,116,114,117,99,116,0,112,114,101,115,101,116,115,0,42, +99,111,108,108,105,115,105,111,110,95,108,105,115,116,0,101,112,115,105,108,111,110,0,115,101,108,102,95,102,114,105,99, +116,105,111,110,0,115,101,108,102,101,112,115,105,108,111,110,0,115,101,108,102,95,108,111,111,112,95,99,111,117,110,116, +0,108,111,111,112,95,99,111,117,110,116,0,112,114,101,115,115,117,114,101,0,42,112,111,105,110,116,115,0,116,111,116, +112,111,105,110,116,115,0,116,104,105,99,107,110,101,115,115,0,115,116,114,111,107,101,115,0,102,114,97,109,101,110,117, +109,0,42,97,99,116,102,114,97,109,101,0,103,115,116,101,112,0,105,110,102,111,91,49,50,56,93,0,115,98,117,102, +102,101,114,95,115,105,122,101,0,115,98,117,102,102,101,114,95,115,102,108,97,103,0,42,115,98,117,102,102,101,114,0, +0,0,0,84,89,80,69,100,1,0,0,99,104,97,114,0,117,99,104,97,114,0,115,104,111,114,116,0,117,115,104,111, +114,116,0,105,110,116,0,108,111,110,103,0,117,108,111,110,103,0,102,108,111,97,116,0,100,111,117,98,108,101,0,118, +111,105,100,0,76,105,110,107,0,76,105,110,107,68,97,116,97,0,76,105,115,116,66,97,115,101,0,118,101,99,50,115, +0,118,101,99,50,105,0,118,101,99,50,102,0,118,101,99,50,100,0,118,101,99,51,105,0,118,101,99,51,102,0,118, +101,99,51,100,0,118,101,99,52,105,0,118,101,99,52,102,0,118,101,99,52,100,0,114,99,116,105,0,114,99,116,102, +0,73,68,80,114,111,112,101,114,116,121,68,97,116,97,0,73,68,80,114,111,112,101,114,116,121,0,73,68,0,76,105, +98,114,97,114,121,0,70,105,108,101,68,97,116,97,0,80,114,101,118,105,101,119,73,109,97,103,101,0,73,112,111,68, +114,105,118,101,114,0,79,98,106,101,99,116,0,73,112,111,67,117,114,118,101,0,66,80,111,105,110,116,0,66,101,122, +84,114,105,112,108,101,0,73,112,111,0,75,101,121,66,108,111,99,107,0,75,101,121,0,83,99,114,105,112,116,76,105, +110,107,0,84,101,120,116,76,105,110,101,0,84,101,120,116,77,97,114,107,101,114,0,84,101,120,116,0,80,97,99,107, +101,100,70,105,108,101,0,67,97,109,101,114,97,0,73,109,97,103,101,85,115,101,114,0,73,109,97,103,101,0,71,80, +85,84,101,120,116,117,114,101,0,97,110,105,109,0,82,101,110,100,101,114,82,101,115,117,108,116,0,77,84,101,120,0, +84,101,120,0,80,108,117,103,105,110,84,101,120,0,67,66,68,97,116,97,0,67,111,108,111,114,66,97,110,100,0,69, +110,118,77,97,112,0,73,109,66,117,102,0,98,78,111,100,101,84,114,101,101,0,84,101,120,77,97,112,112,105,110,103, +0,76,97,109,112,0,67,117,114,118,101,77,97,112,112,105,110,103,0,87,97,118,101,0,77,97,116,101,114,105,97,108, +0,71,114,111,117,112,0,86,70,111,110,116,0,86,70,111,110,116,68,97,116,97,0,77,101,116,97,69,108,101,109,0, +66,111,117,110,100,66,111,120,0,77,101,116,97,66,97,108,108,0,78,117,114,98,0,67,104,97,114,73,110,102,111,0, +84,101,120,116,66,111,120,0,67,117,114,118,101,0,80,97,116,104,0,77,101,115,104,0,77,70,97,99,101,0,77,84, +70,97,99,101,0,84,70,97,99,101,0,77,86,101,114,116,0,77,69,100,103,101,0,77,68,101,102,111,114,109,86,101, +114,116,0,77,67,111,108,0,77,83,116,105,99,107,121,0,77,83,101,108,101,99,116,0,67,117,115,116,111,109,68,97, +116,97,0,77,117,108,116,105,114,101,115,0,80,97,114,116,105,97,108,86,105,115,105,98,105,108,105,116,121,0,77,68, +101,102,111,114,109,87,101,105,103,104,116,0,77,84,101,120,80,111,108,121,0,77,76,111,111,112,85,86,0,77,76,111, +111,112,67,111,108,0,77,70,108,111,97,116,80,114,111,112,101,114,116,121,0,77,73,110,116,80,114,111,112,101,114,116, +121,0,77,83,116,114,105,110,103,80,114,111,112,101,114,116,121,0,79,114,105,103,83,112,97,99,101,70,97,99,101,0, +77,117,108,116,105,114,101,115,67,111,108,0,77,117,108,116,105,114,101,115,67,111,108,70,97,99,101,0,77,117,108,116, +105,114,101,115,70,97,99,101,0,77,117,108,116,105,114,101,115,69,100,103,101,0,77,117,108,116,105,114,101,115,76,101, +118,101,108,0,77,117,108,116,105,114,101,115,77,97,112,78,111,100,101,0,77,111,100,105,102,105,101,114,68,97,116,97, +0,83,117,98,115,117,114,102,77,111,100,105,102,105,101,114,68,97,116,97,0,76,97,116,116,105,99,101,77,111,100,105, +102,105,101,114,68,97,116,97,0,67,117,114,118,101,77,111,100,105,102,105,101,114,68,97,116,97,0,66,117,105,108,100, +77,111,100,105,102,105,101,114,68,97,116,97,0,77,97,115,107,77,111,100,105,102,105,101,114,68,97,116,97,0,65,114, +114,97,121,77,111,100,105,102,105,101,114,68,97,116,97,0,77,105,114,114,111,114,77,111,100,105,102,105,101,114,68,97, +116,97,0,69,100,103,101,83,112,108,105,116,77,111,100,105,102,105,101,114,68,97,116,97,0,66,101,118,101,108,77,111, +100,105,102,105,101,114,68,97,116,97,0,66,77,101,115,104,77,111,100,105,102,105,101,114,68,97,116,97,0,68,105,115, +112,108,97,99,101,77,111,100,105,102,105,101,114,68,97,116,97,0,85,86,80,114,111,106,101,99,116,77,111,100,105,102, +105,101,114,68,97,116,97,0,68,101,99,105,109,97,116,101,77,111,100,105,102,105,101,114,68,97,116,97,0,83,109,111, +111,116,104,77,111,100,105,102,105,101,114,68,97,116,97,0,67,97,115,116,77,111,100,105,102,105,101,114,68,97,116,97, +0,87,97,118,101,77,111,100,105,102,105,101,114,68,97,116,97,0,65,114,109,97,116,117,114,101,77,111,100,105,102,105, +101,114,68,97,116,97,0,72,111,111,107,77,111,100,105,102,105,101,114,68,97,116,97,0,83,111,102,116,98,111,100,121, +77,111,100,105,102,105,101,114,68,97,116,97,0,67,108,111,116,104,77,111,100,105,102,105,101,114,68,97,116,97,0,67, +108,111,116,104,0,67,108,111,116,104,83,105,109,83,101,116,116,105,110,103,115,0,67,108,111,116,104,67,111,108,108,83, +101,116,116,105,110,103,115,0,80,111,105,110,116,67,97,99,104,101,0,67,111,108,108,105,115,105,111,110,77,111,100,105, +102,105,101,114,68,97,116,97,0,66,86,72,84,114,101,101,0,83,117,114,102,97,99,101,77,111,100,105,102,105,101,114, +68,97,116,97,0,68,101,114,105,118,101,100,77,101,115,104,0,66,86,72,84,114,101,101,70,114,111,109,77,101,115,104, +0,66,111,111,108,101,97,110,77,111,100,105,102,105,101,114,68,97,116,97,0,77,68,101,102,73,110,102,108,117,101,110, +99,101,0,77,68,101,102,67,101,108,108,0,77,101,115,104,68,101,102,111,114,109,77,111,100,105,102,105,101,114,68,97, +116,97,0,80,97,114,116,105,99,108,101,83,121,115,116,101,109,77,111,100,105,102,105,101,114,68,97,116,97,0,80,97, +114,116,105,99,108,101,83,121,115,116,101,109,0,80,97,114,116,105,99,108,101,73,110,115,116,97,110,99,101,77,111,100, +105,102,105,101,114,68,97,116,97,0,69,120,112,108,111,100,101,77,111,100,105,102,105,101,114,68,97,116,97,0,70,108, +117,105,100,115,105,109,77,111,100,105,102,105,101,114,68,97,116,97,0,70,108,117,105,100,115,105,109,83,101,116,116,105, +110,103,115,0,83,104,114,105,110,107,119,114,97,112,77,111,100,105,102,105,101,114,68,97,116,97,0,83,105,109,112,108, +101,68,101,102,111,114,109,77,111,100,105,102,105,101,114,68,97,116,97,0,76,97,116,116,105,99,101,0,98,68,101,102, +111,114,109,71,114,111,117,112,0,98,65,99,116,105,111,110,0,98,80,111,115,101,0,66,117,108,108,101,116,83,111,102, +116,66,111,100,121,0,80,97,114,116,68,101,102,108,101,99,116,0,83,111,102,116,66,111,100,121,0,79,98,72,111,111, +107,0,82,78,71,0,83,66,86,101,114,116,101,120,0,66,111,100,121,80,111,105,110,116,0,66,111,100,121,83,112,114, +105,110,103,0,83,66,83,99,114,97,116,99,104,0,87,111,114,108,100,0,82,97,100,105,111,0,66,97,115,101,0,65, +118,105,67,111,100,101,99,68,97,116,97,0,81,117,105,99,107,116,105,109,101,67,111,100,101,99,68,97,116,97,0,70, +70,77,112,101,103,67,111,100,101,99,68,97,116,97,0,65,117,100,105,111,68,97,116,97,0,83,99,101,110,101,82,101, +110,100,101,114,76,97,121,101,114,0,82,101,110,100,101,114,68,97,116,97,0,82,101,110,100,101,114,80,114,111,102,105, +108,101,0,71,97,109,101,70,114,97,109,105,110,103,0,84,105,109,101,77,97,114,107,101,114,0,73,109,97,103,101,80, +97,105,110,116,83,101,116,116,105,110,103,115,0,66,114,117,115,104,0,80,97,114,116,105,99,108,101,66,114,117,115,104, +68,97,116,97,0,80,97,114,116,105,99,108,101,69,100,105,116,83,101,116,116,105,110,103,115,0,84,114,97,110,115,102, +111,114,109,79,114,105,101,110,116,97,116,105,111,110,0,84,111,111,108,83,101,116,116,105,110,103,115,0,66,114,117,115, +104,68,97,116,97,0,83,99,117,108,112,116,68,97,116,97,0,83,99,117,108,112,116,83,101,115,115,105,111,110,0,83, +99,101,110,101,0,68,97,103,70,111,114,101,115,116,0,66,71,112,105,99,0,86,105,101,119,51,68,0,83,112,97,99, +101,76,105,110,107,0,83,99,114,65,114,101,97,0,82,101,110,100,101,114,73,110,102,111,0,82,101,116,111,112,111,86, +105,101,119,68,97,116,97,0,86,105,101,119,68,101,112,116,104,115,0,98,71,80,100,97,116,97,0,86,105,101,119,50, +68,0,83,112,97,99,101,73,110,102,111,0,83,112,97,99,101,73,112,111,0,83,112,97,99,101,66,117,116,115,0,83, +112,97,99,101,83,101,113,0,83,112,97,99,101,70,105,108,101,0,100,105,114,101,110,116,114,121,0,66,108,101,110,100, +72,97,110,100,108,101,0,83,112,97,99,101,79,111,112,115,0,84,114,101,101,83,116,111,114,101,0,84,114,101,101,83, +116,111,114,101,69,108,101,109,0,83,112,97,99,101,73,109,97,103,101,0,83,112,97,99,101,78,108,97,0,83,112,97, +99,101,84,101,120,116,0,83,99,114,105,112,116,0,83,112,97,99,101,83,99,114,105,112,116,0,83,112,97,99,101,84, +105,109,101,0,83,112,97,99,101,78,111,100,101,0,83,112,97,99,101,73,109,97,83,101,108,0,70,105,108,101,76,105, +115,116,0,84,104,101,109,101,85,73,0,84,104,101,109,101,83,112,97,99,101,0,84,104,101,109,101,87,105,114,101,67, +111,108,111,114,0,98,84,104,101,109,101,0,83,111,108,105,100,76,105,103,104,116,0,85,115,101,114,68,101,102,0,98, +83,99,114,101,101,110,0,83,99,114,86,101,114,116,0,83,99,114,69,100,103,101,0,80,97,110,101,108,0,70,105,108, +101,71,108,111,98,97,108,0,83,116,114,105,112,69,108,101,109,0,84,83,116,114,105,112,69,108,101,109,0,83,116,114, +105,112,67,114,111,112,0,83,116,114,105,112,84,114,97,110,115,102,111,114,109,0,83,116,114,105,112,67,111,108,111,114, +66,97,108,97,110,99,101,0,83,116,114,105,112,67,111,108,111,114,66,97,108,97,110,99,101,71,85,73,72,101,108,112, +101,114,0,83,116,114,105,112,80,114,111,120,121,0,83,116,114,105,112,0,80,108,117,103,105,110,83,101,113,0,83,101, +113,117,101,110,99,101,0,98,83,111,117,110,100,0,104,100,97,117,100,105,111,0,77,101,116,97,83,116,97,99,107,0, +69,100,105,116,105,110,103,0,87,105,112,101,86,97,114,115,0,71,108,111,119,86,97,114,115,0,84,114,97,110,115,102, +111,114,109,86,97,114,115,0,83,111,108,105,100,67,111,108,111,114,86,97,114,115,0,83,112,101,101,100,67,111,110,116, +114,111,108,86,97,114,115,0,69,102,102,101,99,116,0,66,117,105,108,100,69,102,102,0,80,97,114,116,69,102,102,0, +80,97,114,116,105,99,108,101,0,87,97,118,101,69,102,102,0,79,111,112,115,0,98,80,114,111,112,101,114,116,121,0, +98,78,101,97,114,83,101,110,115,111,114,0,98,77,111,117,115,101,83,101,110,115,111,114,0,98,84,111,117,99,104,83, +101,110,115,111,114,0,98,75,101,121,98,111,97,114,100,83,101,110,115,111,114,0,98,80,114,111,112,101,114,116,121,83, +101,110,115,111,114,0,98,65,99,116,117,97,116,111,114,83,101,110,115,111,114,0,98,68,101,108,97,121,83,101,110,115, +111,114,0,98,67,111,108,108,105,115,105,111,110,83,101,110,115,111,114,0,98,82,97,100,97,114,83,101,110,115,111,114, +0,98,82,97,110,100,111,109,83,101,110,115,111,114,0,98,82,97,121,83,101,110,115,111,114,0,98,77,101,115,115,97, +103,101,83,101,110,115,111,114,0,98,83,101,110,115,111,114,0,98,67,111,110,116,114,111,108,108,101,114,0,98,74,111, +121,115,116,105,99,107,83,101,110,115,111,114,0,98,69,120,112,114,101,115,115,105,111,110,67,111,110,116,0,98,80,121, +116,104,111,110,67,111,110,116,0,98,65,99,116,117,97,116,111,114,0,98,65,100,100,79,98,106,101,99,116,65,99,116, +117,97,116,111,114,0,98,65,99,116,105,111,110,65,99,116,117,97,116,111,114,0,98,83,111,117,110,100,65,99,116,117, +97,116,111,114,0,98,67,68,65,99,116,117,97,116,111,114,0,98,69,100,105,116,79,98,106,101,99,116,65,99,116,117, +97,116,111,114,0,98,83,99,101,110,101,65,99,116,117,97,116,111,114,0,98,80,114,111,112,101,114,116,121,65,99,116, +117,97,116,111,114,0,98,79,98,106,101,99,116,65,99,116,117,97,116,111,114,0,98,73,112,111,65,99,116,117,97,116, +111,114,0,98,67,97,109,101,114,97,65,99,116,117,97,116,111,114,0,98,67,111,110,115,116,114,97,105,110,116,65,99, +116,117,97,116,111,114,0,98,71,114,111,117,112,65,99,116,117,97,116,111,114,0,98,82,97,110,100,111,109,65,99,116, +117,97,116,111,114,0,98,77,101,115,115,97,103,101,65,99,116,117,97,116,111,114,0,98,71,97,109,101,65,99,116,117, +97,116,111,114,0,98,86,105,115,105,98,105,108,105,116,121,65,99,116,117,97,116,111,114,0,98,84,119,111,68,70,105, +108,116,101,114,65,99,116,117,97,116,111,114,0,98,80,97,114,101,110,116,65,99,116,117,97,116,111,114,0,98,83,116, +97,116,101,65,99,116,117,97,116,111,114,0,70,114,101,101,67,97,109,101,114,97,0,98,83,97,109,112,108,101,0,98, +83,111,117,110,100,76,105,115,116,101,110,101,114,0,83,112,97,99,101,83,111,117,110,100,0,71,114,111,117,112,79,98, +106,101,99,116,0,66,111,110,101,0,98,65,114,109,97,116,117,114,101,0,98,80,111,115,101,67,104,97,110,110,101,108, +0,98,65,99,116,105,111,110,71,114,111,117,112,0,98,65,99,116,105,111,110,67,104,97,110,110,101,108,0,83,112,97, +99,101,65,99,116,105,111,110,0,98,67,111,110,115,116,114,97,105,110,116,67,104,97,110,110,101,108,0,98,67,111,110, +115,116,114,97,105,110,116,0,98,67,111,110,115,116,114,97,105,110,116,84,97,114,103,101,116,0,98,80,121,116,104,111, +110,67,111,110,115,116,114,97,105,110,116,0,98,75,105,110,101,109,97,116,105,99,67,111,110,115,116,114,97,105,110,116, +0,98,84,114,97,99,107,84,111,67,111,110,115,116,114,97,105,110,116,0,98,82,111,116,97,116,101,76,105,107,101,67, +111,110,115,116,114,97,105,110,116,0,98,76,111,99,97,116,101,76,105,107,101,67,111,110,115,116,114,97,105,110,116,0, +98,77,105,110,77,97,120,67,111,110,115,116,114,97,105,110,116,0,98,83,105,122,101,76,105,107,101,67,111,110,115,116, +114,97,105,110,116,0,98,65,99,116,105,111,110,67,111,110,115,116,114,97,105,110,116,0,98,76,111,99,107,84,114,97, +99,107,67,111,110,115,116,114,97,105,110,116,0,98,70,111,108,108,111,119,80,97,116,104,67,111,110,115,116,114,97,105, +110,116,0,98,83,116,114,101,116,99,104,84,111,67,111,110,115,116,114,97,105,110,116,0,98,82,105,103,105,100,66,111, +100,121,74,111,105,110,116,67,111,110,115,116,114,97,105,110,116,0,98,67,108,97,109,112,84,111,67,111,110,115,116,114, +97,105,110,116,0,98,67,104,105,108,100,79,102,67,111,110,115,116,114,97,105,110,116,0,98,84,114,97,110,115,102,111, +114,109,67,111,110,115,116,114,97,105,110,116,0,98,76,111,99,76,105,109,105,116,67,111,110,115,116,114,97,105,110,116, +0,98,82,111,116,76,105,109,105,116,67,111,110,115,116,114,97,105,110,116,0,98,83,105,122,101,76,105,109,105,116,67, +111,110,115,116,114,97,105,110,116,0,98,68,105,115,116,76,105,109,105,116,67,111,110,115,116,114,97,105,110,116,0,98, +83,104,114,105,110,107,119,114,97,112,67,111,110,115,116,114,97,105,110,116,0,98,65,99,116,105,111,110,77,111,100,105, +102,105,101,114,0,98,65,99,116,105,111,110,83,116,114,105,112,0,98,78,111,100,101,83,116,97,99,107,0,98,78,111, +100,101,83,111,99,107,101,116,0,98,78,111,100,101,76,105,110,107,0,98,78,111,100,101,0,98,78,111,100,101,80,114, +101,118,105,101,119,0,98,78,111,100,101,84,121,112,101,0,78,111,100,101,73,109,97,103,101,65,110,105,109,0,78,111, +100,101,66,108,117,114,68,97,116,97,0,78,111,100,101,68,66,108,117,114,68,97,116,97,0,78,111,100,101,66,105,108, +97,116,101,114,97,108,66,108,117,114,68,97,116,97,0,78,111,100,101,72,117,101,83,97,116,0,78,111,100,101,73,109, +97,103,101,70,105,108,101,0,78,111,100,101,67,104,114,111,109,97,0,78,111,100,101,84,119,111,88,89,115,0,78,111, +100,101,84,119,111,70,108,111,97,116,115,0,78,111,100,101,71,101,111,109,101,116,114,121,0,78,111,100,101,86,101,114, +116,101,120,67,111,108,0,78,111,100,101,68,101,102,111,99,117,115,0,78,111,100,101,83,99,114,105,112,116,68,105,99, +116,0,78,111,100,101,71,108,97,114,101,0,78,111,100,101,84,111,110,101,109,97,112,0,78,111,100,101,76,101,110,115, +68,105,115,116,0,84,101,120,78,111,100,101,79,117,116,112,117,116,0,67,117,114,118,101,77,97,112,80,111,105,110,116, +0,67,117,114,118,101,77,97,112,0,66,114,117,115,104,67,108,111,110,101,0,67,117,115,116,111,109,68,97,116,97,76, +97,121,101,114,0,72,97,105,114,75,101,121,0,80,97,114,116,105,99,108,101,75,101,121,0,67,104,105,108,100,80,97, +114,116,105,99,108,101,0,80,97,114,116,105,99,108,101,68,97,116,97,0,80,97,114,116,105,99,108,101,83,101,116,116, +105,110,103,115,0,80,97,114,116,105,99,108,101,69,100,105,116,0,80,97,114,116,105,99,108,101,67,97,99,104,101,75, +101,121,0,76,105,110,107,78,111,100,101,0,98,71,80,68,115,112,111,105,110,116,0,98,71,80,68,115,116,114,111,107, +101,0,98,71,80,68,102,114,97,109,101,0,98,71,80,68,108,97,121,101,114,0,0,84,76,69,78,1,0,1,0,2, +0,2,0,4,0,4,0,4,0,4,0,8,0,0,0,16,0,24,0,16,0,4,0,8,0,8,0,16,0,12,0,12, +0,24,0,16,0,16,0,32,0,16,0,16,0,32,0,96,0,72,0,72,2,0,0,40,0,-112,0,48,4,112,0,36, +0,56,0,112,0,-128,0,-96,0,24,0,40,0,48,0,-80,0,24,0,-88,0,32,0,-72,1,0,0,0,0,0,0,-112, +0,64,1,120,1,24,0,8,3,-56,0,0,0,-56,0,-120,0,-16,1,56,1,80,0,-16,2,104,0,96,1,0,0,-128, +0,104,0,-72,0,80,0,8,0,16,0,-96,1,0,0,-112,1,20,0,48,0,64,0,24,0,12,0,16,0,4,0,8, +0,8,0,32,0,112,0,48,0,8,0,16,0,8,0,8,0,4,0,4,0,0,1,32,0,16,0,64,0,24,0,12, +0,96,0,0,0,64,0,88,0,104,0,112,0,80,0,112,0,-112,0,80,0,72,0,120,0,72,0,-88,0,-48,0,72, +0,104,0,120,0,-48,0,120,0,-56,0,64,0,96,0,0,0,-120,0,32,0,20,0,-112,0,0,0,80,0,0,0,0, +0,80,0,8,0,8,0,0,1,96,0,-104,1,80,0,80,0,80,0,-72,1,-128,0,120,0,-104,0,48,0,-128,0,72, +0,120,0,-120,0,16,1,-32,0,0,0,16,0,0,0,0,0,0,0,-32,1,40,0,40,0,-72,0,-104,0,56,0,16, +0,88,0,-24,3,64,0,16,0,88,0,16,0,24,1,8,0,72,0,88,0,-16,0,8,0,-8,0,0,0,64,6,0, +0,64,0,88,3,48,0,8,1,0,0,0,0,0,0,32,0,-120,0,48,0,120,1,-16,0,-40,0,-8,1,0,0,0, +0,48,1,16,0,16,0,32,1,-64,0,-112,0,120,2,56,0,-80,0,0,1,-72,2,0,0,-104,0,-48,0,16,0,64, +14,56,0,40,12,-88,0,32,0,40,0,-16,0,40,0,80,0,48,0,16,0,8,0,64,0,0,0,0,1,32,1,-56, +1,8,1,72,1,0,0,32,0,48,0,12,0,24,0,48,0,16,0,32,0,24,0,32,0,72,1,0,0,64,0,64, +0,80,0,48,0,8,0,48,0,72,0,104,0,40,0,8,0,72,0,44,0,40,0,108,0,72,0,96,0,104,0,60, +0,-128,0,80,0,80,0,16,0,96,0,32,0,20,0,88,0,24,0,80,0,112,0,84,0,32,0,96,0,64,0,56, +0,112,0,-116,0,4,0,24,0,16,0,8,0,40,0,0,0,88,0,-64,0,40,0,24,1,-104,0,-48,1,88,0,88, +0,-48,0,56,0,80,0,-128,0,80,0,112,0,56,0,48,0,48,0,72,0,48,0,72,0,48,0,24,0,56,0,104, +0,16,0,112,0,96,0,28,0,28,0,28,0,56,0,24,0,72,0,-88,0,40,0,-112,0,48,0,-8,0,0,0,0, +0,16,0,40,0,28,0,12,0,12,0,16,1,40,0,8,0,8,0,64,0,32,0,24,0,16,0,24,0,32,0,8, +0,32,0,12,0,56,0,24,0,72,0,24,0,56,0,72,0,8,1,16,2,0,0,0,0,0,0,16,0,32,0,40, +0,-64,0,83,84,82,67,57,1,0,0,10,0,2,0,10,0,0,0,10,0,1,0,11,0,3,0,11,0,0,0,11, +0,1,0,9,0,2,0,12,0,2,0,9,0,3,0,9,0,4,0,13,0,2,0,2,0,5,0,2,0,6,0,14, +0,2,0,4,0,5,0,4,0,6,0,15,0,2,0,7,0,5,0,7,0,6,0,16,0,2,0,8,0,5,0,8, +0,6,0,17,0,3,0,4,0,5,0,4,0,6,0,4,0,7,0,18,0,3,0,7,0,5,0,7,0,6,0,7, +0,7,0,19,0,3,0,8,0,5,0,8,0,6,0,8,0,7,0,20,0,4,0,4,0,5,0,4,0,6,0,4, +0,7,0,4,0,8,0,21,0,4,0,7,0,5,0,7,0,6,0,7,0,7,0,7,0,8,0,22,0,4,0,8, +0,5,0,8,0,6,0,8,0,7,0,8,0,8,0,23,0,4,0,4,0,9,0,4,0,10,0,4,0,11,0,4, +0,12,0,24,0,4,0,7,0,9,0,7,0,10,0,7,0,11,0,7,0,12,0,25,0,4,0,9,0,13,0,12, +0,14,0,4,0,15,0,4,0,16,0,26,0,10,0,26,0,0,0,26,0,1,0,0,0,17,0,0,0,18,0,0, +0,19,0,2,0,20,0,4,0,21,0,25,0,22,0,4,0,23,0,4,0,24,0,27,0,9,0,9,0,0,0,9, +0,1,0,27,0,25,0,28,0,26,0,0,0,27,0,2,0,28,0,2,0,20,0,4,0,29,0,26,0,30,0,28, +0,8,0,27,0,31,0,27,0,32,0,29,0,33,0,0,0,34,0,0,0,35,0,4,0,36,0,4,0,37,0,28, +0,38,0,30,0,6,0,4,0,39,0,4,0,40,0,2,0,41,0,2,0,42,0,2,0,43,0,4,0,44,0,31, +0,6,0,32,0,45,0,2,0,46,0,2,0,47,0,2,0,18,0,2,0,20,0,0,0,48,0,33,0,21,0,33, +0,0,0,33,0,1,0,34,0,49,0,35,0,50,0,24,0,51,0,24,0,52,0,2,0,46,0,2,0,47,0,2, +0,53,0,2,0,54,0,2,0,55,0,2,0,56,0,2,0,20,0,2,0,57,0,7,0,11,0,7,0,12,0,4, +0,58,0,7,0,59,0,7,0,60,0,7,0,61,0,31,0,62,0,36,0,7,0,27,0,31,0,12,0,63,0,24, +0,64,0,2,0,46,0,2,0,65,0,2,0,66,0,2,0,37,0,37,0,16,0,37,0,0,0,37,0,1,0,7, +0,67,0,7,0,61,0,2,0,18,0,2,0,47,0,2,0,68,0,2,0,20,0,4,0,69,0,4,0,70,0,9, +0,2,0,7,0,71,0,0,0,17,0,0,0,72,0,7,0,73,0,7,0,74,0,38,0,12,0,27,0,31,0,37, +0,75,0,0,0,76,0,4,0,77,0,7,0,61,0,12,0,78,0,36,0,79,0,27,0,80,0,2,0,18,0,2, +0,81,0,2,0,82,0,2,0,20,0,39,0,5,0,27,0,83,0,2,0,84,0,2,0,85,0,2,0,86,0,4, +0,37,0,40,0,6,0,40,0,0,0,40,0,1,0,0,0,87,0,0,0,88,0,4,0,23,0,4,0,89,0,41, +0,10,0,41,0,0,0,41,0,1,0,4,0,90,0,4,0,91,0,4,0,92,0,4,0,43,0,4,0,14,0,4, +0,93,0,0,0,94,0,0,0,95,0,42,0,15,0,27,0,31,0,0,0,96,0,4,0,93,0,4,0,97,0,12, +0,98,0,40,0,99,0,40,0,100,0,4,0,101,0,4,0,102,0,12,0,103,0,0,0,104,0,4,0,105,0,4, +0,106,0,9,0,107,0,8,0,108,0,43,0,5,0,4,0,109,0,4,0,110,0,4,0,93,0,4,0,37,0,9, +0,2,0,44,0,20,0,27,0,31,0,2,0,18,0,2,0,20,0,7,0,111,0,7,0,112,0,7,0,113,0,7, +0,114,0,7,0,115,0,7,0,116,0,7,0,117,0,7,0,118,0,7,0,119,0,7,0,120,0,7,0,121,0,2, +0,122,0,2,0,123,0,7,0,124,0,36,0,79,0,39,0,125,0,32,0,126,0,45,0,12,0,4,0,127,0,4, +0,-128,0,4,0,-127,0,4,0,-126,0,2,0,-125,0,2,0,-124,0,2,0,20,0,2,0,-123,0,2,0,-122,0,2, +0,-121,0,2,0,-120,0,2,0,-119,0,46,0,32,0,27,0,31,0,0,0,34,0,12,0,-118,0,47,0,-117,0,48, +0,-116,0,49,0,-115,0,2,0,-123,0,2,0,20,0,2,0,-114,0,2,0,18,0,2,0,37,0,2,0,43,0,4, +0,-113,0,2,0,-112,0,2,0,-111,0,2,0,-110,0,2,0,-109,0,2,0,-108,0,2,0,-107,0,4,0,-106,0,4, +0,-105,0,43,0,-104,0,30,0,-103,0,7,0,-102,0,4,0,-101,0,2,0,-100,0,2,0,-99,0,2,0,-98,0,2, +0,-97,0,7,0,-96,0,7,0,-95,0,9,0,-94,0,50,0,31,0,2,0,-93,0,2,0,-92,0,2,0,-91,0,2, +0,-90,0,32,0,-89,0,51,0,-88,0,0,0,-87,0,0,0,-86,0,0,0,-85,0,0,0,-84,0,0,0,-83,0,7, +0,-82,0,7,0,-81,0,2,0,-80,0,2,0,-79,0,2,0,-78,0,2,0,-77,0,2,0,-76,0,2,0,-75,0,2, +0,-74,0,7,0,-73,0,7,0,-72,0,7,0,-71,0,7,0,-70,0,7,0,-69,0,7,0,57,0,7,0,-68,0,7, +0,-67,0,7,0,-66,0,7,0,-65,0,7,0,-64,0,52,0,15,0,0,0,-63,0,9,0,-62,0,0,0,-61,0,0, +0,-60,0,4,0,-59,0,4,0,-58,0,9,0,-57,0,7,0,-56,0,7,0,-55,0,7,0,-54,0,4,0,-53,0,9, +0,-52,0,9,0,-51,0,4,0,-50,0,4,0,37,0,53,0,6,0,7,0,-73,0,7,0,-72,0,7,0,-71,0,7, +0,-49,0,7,0,67,0,4,0,64,0,54,0,5,0,2,0,20,0,2,0,36,0,2,0,64,0,2,0,-48,0,53, +0,-54,0,55,0,17,0,32,0,-89,0,46,0,-47,0,56,0,-46,0,7,0,-45,0,7,0,-44,0,2,0,18,0,2, +0,-43,0,7,0,113,0,7,0,114,0,7,0,-42,0,4,0,-41,0,2,0,-40,0,2,0,-39,0,4,0,-123,0,4, +0,-113,0,2,0,-38,0,2,0,-37,0,51,0,56,0,27,0,31,0,7,0,-36,0,7,0,-35,0,7,0,-34,0,7, +0,-33,0,7,0,-32,0,7,0,-31,0,7,0,-30,0,7,0,-29,0,7,0,-28,0,7,0,-27,0,7,0,-26,0,7, +0,-25,0,7,0,-24,0,7,0,-23,0,7,0,-22,0,7,0,-21,0,7,0,-20,0,7,0,-19,0,7,0,-18,0,7, +0,-17,0,2,0,-16,0,2,0,-15,0,2,0,-14,0,2,0,-13,0,2,0,-12,0,2,0,-11,0,2,0,-10,0,2, +0,20,0,2,0,18,0,2,0,-43,0,7,0,-9,0,7,0,-8,0,7,0,-7,0,7,0,-6,0,2,0,-5,0,2, +0,-4,0,2,0,-3,0,2,0,-125,0,4,0,23,0,4,0,-128,0,4,0,-127,0,4,0,-126,0,7,0,-2,0,7, +0,-1,0,7,0,-67,0,45,0,0,1,57,0,1,1,36,0,79,0,46,0,-47,0,52,0,2,1,54,0,3,1,55, +0,4,1,30,0,-103,0,0,0,5,1,0,0,6,1,58,0,8,0,7,0,7,1,7,0,8,1,7,0,-81,0,4, +0,20,0,7,0,9,1,7,0,10,1,7,0,11,1,32,0,45,0,59,0,80,0,27,0,31,0,2,0,18,0,2, +0,12,1,4,0,13,1,2,0,-79,0,2,0,14,1,7,0,-73,0,7,0,-72,0,7,0,-71,0,7,0,-70,0,7, +0,15,1,7,0,16,1,7,0,17,1,7,0,18,1,7,0,19,1,7,0,20,1,7,0,21,1,7,0,22,1,7, +0,23,1,7,0,24,1,7,0,25,1,60,0,26,1,2,0,27,1,2,0,70,0,7,0,113,0,7,0,114,0,7, +0,28,1,7,0,29,1,7,0,30,1,2,0,31,1,2,0,32,1,2,0,33,1,2,0,34,1,0,0,35,1,0, +0,36,1,2,0,37,1,2,0,38,1,2,0,39,1,2,0,40,1,2,0,41,1,7,0,42,1,7,0,43,1,7, +0,44,1,7,0,45,1,2,0,46,1,2,0,43,0,2,0,47,1,2,0,48,1,2,0,49,1,2,0,50,1,7, +0,51,1,7,0,52,1,7,0,53,1,7,0,54,1,7,0,55,1,7,0,56,1,7,0,57,1,7,0,58,1,7, +0,59,1,7,0,60,1,7,0,61,1,7,0,62,1,2,0,63,1,2,0,64,1,4,0,65,1,4,0,66,1,2, +0,67,1,2,0,68,1,2,0,69,1,2,0,70,1,7,0,71,1,7,0,72,1,7,0,73,1,7,0,74,1,2, +0,75,1,2,0,76,1,50,0,77,1,36,0,79,0,30,0,-103,0,39,0,125,0,61,0,2,0,27,0,31,0,36, +0,79,0,62,0,-127,0,27,0,31,0,2,0,-79,0,2,0,20,0,7,0,-73,0,7,0,-72,0,7,0,-71,0,7, +0,78,1,7,0,79,1,7,0,80,1,7,0,81,1,7,0,82,1,7,0,83,1,7,0,84,1,7,0,85,1,7, +0,86,1,7,0,87,1,7,0,88,1,7,0,89,1,7,0,90,1,7,0,91,1,7,0,92,1,7,0,93,1,7, +0,94,1,7,0,95,1,7,0,96,1,7,0,97,1,7,0,98,1,7,0,99,1,7,0,100,1,7,0,101,1,7, +0,102,1,7,0,103,1,7,0,104,1,2,0,105,1,2,0,106,1,2,0,107,1,0,0,108,1,0,0,109,1,7, +0,110,1,7,0,111,1,2,0,112,1,2,0,113,1,7,0,114,1,7,0,115,1,7,0,116,1,7,0,117,1,2, +0,118,1,2,0,119,1,4,0,13,1,4,0,120,1,2,0,121,1,2,0,122,1,2,0,123,1,2,0,124,1,7, +0,125,1,7,0,126,1,7,0,127,1,7,0,-128,1,7,0,-127,1,7,0,-126,1,7,0,-125,1,7,0,-124,1,7, +0,-123,1,7,0,-122,1,0,0,-121,1,7,0,-120,1,7,0,-119,1,7,0,-118,1,4,0,-117,1,0,0,-116,1,0, +0,47,1,0,0,-115,1,0,0,5,1,2,0,-114,1,2,0,-113,1,2,0,64,1,2,0,-112,1,2,0,-111,1,2, +0,-110,1,7,0,-109,1,7,0,-108,1,7,0,-107,1,7,0,-106,1,7,0,-105,1,2,0,-93,0,2,0,-92,0,54, +0,-104,1,54,0,-103,1,0,0,-102,1,0,0,-101,1,0,0,-100,1,0,0,-99,1,2,0,-98,1,2,0,12,1,7, +0,-97,1,7,0,-96,1,50,0,77,1,57,0,1,1,36,0,79,0,63,0,-95,1,30,0,-103,0,7,0,-94,1,7, +0,-93,1,7,0,-92,1,7,0,-91,1,7,0,-90,1,2,0,-89,1,2,0,70,0,7,0,-88,1,7,0,-87,1,7, +0,-86,1,7,0,-85,1,7,0,-84,1,7,0,-83,1,7,0,-82,1,7,0,-81,1,7,0,-80,1,2,0,-79,1,2, +0,-78,1,7,0,-77,1,7,0,-76,1,7,0,-75,1,7,0,-74,1,7,0,-73,1,4,0,-72,1,4,0,-71,1,4, +0,-70,1,39,0,125,0,12,0,-69,1,64,0,6,0,27,0,31,0,0,0,-68,1,7,0,-67,1,7,0,37,0,65, +0,2,0,43,0,-104,0,66,0,26,0,66,0,0,0,66,0,1,0,67,0,-66,1,4,0,-65,1,4,0,-64,1,4, +0,-63,1,4,0,-62,1,4,0,-61,1,4,0,-60,1,2,0,18,0,2,0,20,0,2,0,-59,1,2,0,-58,1,7, +0,5,0,7,0,6,0,7,0,7,0,7,0,-57,1,7,0,-56,1,7,0,-55,1,7,0,-54,1,7,0,-53,1,7, +0,-52,1,7,0,-51,1,7,0,23,0,7,0,-50,1,7,0,-49,1,68,0,15,0,27,0,31,0,67,0,-66,1,12, +0,-48,1,12,0,-47,1,36,0,79,0,62,0,-46,1,2,0,20,0,2,0,-45,1,4,0,-80,0,7,0,7,1,7, +0,-81,0,7,0,8,1,7,0,-44,1,7,0,-43,1,7,0,-42,1,35,0,10,0,7,0,-41,1,7,0,-40,1,7, +0,-39,1,7,0,-38,1,2,0,-37,1,2,0,-36,1,0,0,-35,1,0,0,-34,1,0,0,-33,1,0,0,-32,1,34, +0,7,0,7,0,-31,1,7,0,-40,1,7,0,-39,1,2,0,-35,1,2,0,-32,1,7,0,-38,1,7,0,37,0,69, +0,21,0,69,0,0,0,69,0,1,0,2,0,18,0,2,0,-30,1,2,0,-32,1,2,0,20,0,2,0,-29,1,2, +0,-28,1,2,0,-27,1,2,0,-26,1,2,0,-25,1,2,0,-24,1,2,0,-23,1,2,0,-22,1,7,0,-21,1,7, +0,-20,1,34,0,49,0,35,0,50,0,2,0,-19,1,2,0,-18,1,4,0,-17,1,70,0,5,0,2,0,-16,1,2, +0,-30,1,0,0,20,0,0,0,37,0,2,0,70,0,71,0,4,0,7,0,5,0,7,0,6,0,7,0,8,0,7, +0,-15,1,72,0,57,0,27,0,31,0,67,0,-66,1,12,0,-14,1,12,0,-47,1,32,0,-13,1,32,0,-12,1,32, +0,-11,1,36,0,79,0,73,0,-10,1,38,0,-9,1,62,0,-46,1,12,0,-8,1,7,0,7,1,7,0,-81,0,7, +0,8,1,4,0,-80,0,2,0,-7,1,2,0,-45,1,2,0,20,0,2,0,-6,1,7,0,-5,1,7,0,-4,1,7, +0,-3,1,2,0,-27,1,2,0,-26,1,2,0,-2,1,2,0,-1,1,4,0,70,0,2,0,23,0,2,0,98,0,2, +0,67,0,2,0,0,2,7,0,1,2,7,0,2,2,7,0,3,2,7,0,4,2,7,0,5,2,7,0,6,2,7, +0,7,2,7,0,8,2,7,0,9,2,7,0,10,2,0,0,11,2,0,0,12,2,64,0,13,2,64,0,14,2,64, +0,15,2,64,0,16,2,4,0,17,2,4,0,18,2,4,0,19,2,4,0,37,0,71,0,20,2,4,0,21,2,4, +0,22,2,70,0,23,2,70,0,24,2,74,0,39,0,27,0,31,0,67,0,-66,1,12,0,25,2,36,0,79,0,38, +0,-9,1,62,0,-46,1,75,0,26,2,76,0,27,2,77,0,28,2,78,0,29,2,79,0,30,2,80,0,31,2,81, +0,32,2,82,0,33,2,74,0,34,2,83,0,35,2,84,0,36,2,84,0,37,2,84,0,38,2,4,0,54,0,4, +0,39,2,4,0,40,2,4,0,41,2,4,0,42,2,4,0,-80,0,7,0,7,1,7,0,-81,0,7,0,8,1,7, +0,43,2,7,0,37,0,2,0,44,2,2,0,20,0,2,0,45,2,2,0,46,2,2,0,-45,1,2,0,47,2,85, +0,48,2,86,0,49,2,9,0,-94,0,77,0,8,0,9,0,50,2,7,0,51,2,4,0,52,2,0,0,20,0,0, +0,53,2,2,0,13,1,2,0,54,2,2,0,55,2,75,0,8,0,4,0,56,2,4,0,57,2,4,0,58,2,4, +0,59,2,0,0,37,0,0,0,-30,1,0,0,60,2,0,0,20,0,79,0,5,0,4,0,56,2,4,0,57,2,0, +0,61,2,0,0,62,2,2,0,20,0,87,0,2,0,4,0,63,2,7,0,-39,1,80,0,3,0,87,0,64,2,4, +0,65,2,4,0,20,0,78,0,6,0,7,0,66,2,2,0,67,2,0,0,20,0,0,0,-30,1,0,0,62,2,0, +0,68,2,81,0,4,0,0,0,-49,0,0,0,-73,0,0,0,-72,0,0,0,-71,0,88,0,6,0,46,0,50,2,0, +0,20,0,0,0,53,2,2,0,13,1,2,0,54,2,2,0,55,2,89,0,1,0,7,0,69,2,90,0,5,0,0, +0,-49,0,0,0,-73,0,0,0,-72,0,0,0,-71,0,4,0,37,0,82,0,1,0,7,0,70,2,83,0,2,0,4, +0,71,2,4,0,18,0,76,0,7,0,7,0,51,2,46,0,50,2,0,0,20,0,0,0,53,2,2,0,13,1,2, +0,54,2,2,0,55,2,91,0,1,0,7,0,72,2,92,0,1,0,4,0,73,2,93,0,1,0,0,0,74,2,94, +0,1,0,7,0,51,2,95,0,4,0,7,0,-49,0,7,0,-73,0,7,0,-72,0,7,0,-71,0,96,0,1,0,95, +0,52,2,97,0,5,0,4,0,75,2,4,0,76,2,0,0,20,0,0,0,-30,1,0,0,-74,0,98,0,2,0,4, +0,77,2,4,0,76,2,99,0,14,0,99,0,0,0,99,0,1,0,97,0,78,2,96,0,79,2,98,0,80,2,0, +0,81,2,12,0,82,2,12,0,83,2,100,0,84,2,4,0,54,0,4,0,40,2,4,0,39,2,4,0,37,0,78, +0,85,2,85,0,14,0,12,0,86,2,78,0,85,2,0,0,87,2,0,0,88,2,0,0,89,2,0,0,90,2,0, +0,91,2,0,0,92,2,0,0,93,2,0,0,20,0,84,0,36,2,84,0,38,2,2,0,94,2,0,0,95,2,86, +0,8,0,4,0,96,2,4,0,97,2,75,0,98,2,79,0,99,2,4,0,40,2,4,0,39,2,4,0,54,0,4, +0,37,0,101,0,6,0,101,0,0,0,101,0,1,0,4,0,18,0,4,0,13,1,0,0,17,0,0,0,100,2,102, +0,7,0,101,0,101,2,2,0,102,2,2,0,86,2,2,0,103,2,2,0,93,0,9,0,104,2,9,0,105,2,103, +0,3,0,101,0,101,2,32,0,-89,0,0,0,17,0,104,0,5,0,101,0,101,2,32,0,-89,0,0,0,17,0,2, +0,106,2,0,0,107,2,105,0,5,0,101,0,101,2,7,0,91,0,7,0,108,2,4,0,109,2,4,0,110,2,106, +0,5,0,101,0,101,2,32,0,111,2,0,0,72,0,4,0,13,1,4,0,20,0,107,0,13,0,101,0,101,2,32, +0,112,2,32,0,113,2,32,0,114,2,32,0,115,2,7,0,116,2,7,0,117,2,7,0,108,2,7,0,118,2,4, +0,119,2,4,0,120,2,4,0,93,0,4,0,121,2,108,0,5,0,101,0,101,2,2,0,122,2,2,0,20,0,7, +0,123,2,32,0,124,2,109,0,3,0,101,0,101,2,7,0,125,2,4,0,93,0,110,0,10,0,101,0,101,2,7, +0,126,2,4,0,127,2,4,0,37,0,2,0,93,0,2,0,-128,2,2,0,-127,2,2,0,-126,2,7,0,-125,2,0, +0,-124,2,111,0,3,0,101,0,101,2,7,0,37,0,4,0,18,0,112,0,11,0,101,0,101,2,51,0,-123,2,7, +0,-122,2,4,0,-121,2,0,0,-124,2,7,0,-120,2,4,0,-119,2,32,0,-118,2,0,0,-117,2,4,0,-116,2,4, +0,37,0,113,0,10,0,101,0,101,2,32,0,-115,2,46,0,-114,2,4,0,93,0,4,0,-113,2,7,0,-112,2,7, +0,-111,2,0,0,-117,2,4,0,-116,2,4,0,37,0,114,0,3,0,101,0,101,2,7,0,-110,2,4,0,-109,2,115, +0,5,0,101,0,101,2,7,0,-108,2,0,0,-124,2,2,0,20,0,2,0,-107,2,116,0,8,0,101,0,101,2,32, +0,-89,0,7,0,-108,2,7,0,-38,1,7,0,109,0,0,0,-124,2,2,0,20,0,2,0,18,0,117,0,21,0,101, +0,101,2,32,0,-106,2,0,0,-124,2,51,0,-123,2,32,0,-118,2,2,0,20,0,2,0,37,0,7,0,-105,2,7, +0,-104,2,7,0,-103,2,7,0,-5,1,7,0,-102,2,7,0,-101,2,7,0,-100,2,7,0,-99,2,4,0,-119,2,4, +0,-116,2,0,0,-117,2,7,0,-98,2,7,0,-97,2,7,0,43,0,118,0,7,0,101,0,101,2,2,0,-96,2,2, +0,-95,2,4,0,70,0,32,0,-89,0,7,0,-94,2,0,0,-124,2,119,0,9,0,101,0,101,2,32,0,-89,0,7, +0,-93,2,7,0,-92,2,7,0,-99,2,4,0,-91,2,4,0,-90,2,7,0,-89,2,0,0,17,0,120,0,1,0,101, +0,101,2,121,0,5,0,101,0,101,2,122,0,-88,2,123,0,-87,2,124,0,-86,2,125,0,-85,2,126,0,14,0,101, +0,101,2,78,0,-84,2,78,0,-83,2,78,0,-82,2,78,0,-81,2,78,0,-80,2,78,0,-79,2,75,0,-78,2,4, +0,-77,2,4,0,-76,2,2,0,-75,2,2,0,37,0,7,0,-74,2,127,0,-73,2,-128,0,3,0,101,0,101,2,-127, +0,-72,2,-126,0,-73,2,-125,0,4,0,101,0,101,2,32,0,-89,0,4,0,-71,2,4,0,37,0,-124,0,2,0,4, +0,-70,2,7,0,-39,1,-123,0,2,0,4,0,-127,0,4,0,-69,2,-122,0,20,0,101,0,101,2,32,0,-89,0,0, +0,-124,2,2,0,-68,2,2,0,-67,2,2,0,20,0,2,0,37,0,7,0,-66,2,7,0,-65,2,4,0,54,0,4, +0,-64,2,-123,0,-63,2,-124,0,-62,2,4,0,-61,2,4,0,-60,2,4,0,-59,2,4,0,-69,2,7,0,-58,2,7, +0,-57,2,7,0,-56,2,-121,0,8,0,101,0,101,2,-120,0,-55,2,-127,0,-72,2,4,0,-54,2,4,0,-53,2,4, +0,-52,2,2,0,20,0,2,0,57,0,-119,0,5,0,101,0,101,2,32,0,45,0,2,0,-51,2,2,0,20,0,2, +0,-50,2,-118,0,5,0,101,0,101,2,4,0,-49,2,2,0,20,0,2,0,-48,2,7,0,-47,2,-117,0,3,0,101, +0,101,2,-116,0,-46,2,125,0,-85,2,-115,0,10,0,101,0,101,2,32,0,-45,2,32,0,-44,2,0,0,-43,2,7, +0,-42,2,2,0,-41,2,2,0,-40,2,0,0,-39,2,0,0,-38,2,0,0,107,2,-114,0,9,0,101,0,101,2,32, +0,-37,2,0,0,-43,2,7,0,-36,2,7,0,-35,2,0,0,13,1,0,0,122,2,0,0,-34,2,0,0,37,0,-113, +0,24,0,27,0,31,0,2,0,-29,1,2,0,-28,1,2,0,-33,2,2,0,20,0,2,0,-32,2,2,0,-31,2,2, +0,-30,2,2,0,70,0,0,0,-29,2,0,0,-28,2,0,0,-27,2,0,0,18,0,4,0,37,0,7,0,-26,2,7, +0,-25,2,7,0,-24,2,7,0,-23,2,7,0,-22,2,7,0,-21,2,34,0,-20,2,36,0,79,0,38,0,-9,1,80, +0,31,2,-112,0,3,0,-112,0,0,0,-112,0,1,0,0,0,17,0,67,0,3,0,7,0,-19,2,4,0,20,0,4, +0,37,0,32,0,111,0,27,0,31,0,2,0,18,0,2,0,-18,2,4,0,-17,2,4,0,-16,2,4,0,-15,2,0, +0,-14,2,32,0,38,0,32,0,-13,2,32,0,-12,2,32,0,-11,2,32,0,-10,2,36,0,79,0,73,0,-10,1,67, +0,-66,1,-111,0,-9,2,-111,0,-8,2,-110,0,-7,2,9,0,2,0,12,0,-6,2,12,0,25,2,12,0,-47,1,12, +0,-5,2,12,0,-4,2,62,0,-46,1,7,0,7,1,7,0,-3,2,7,0,-2,2,7,0,-81,0,7,0,-1,2,7, +0,8,1,7,0,0,3,7,0,1,3,7,0,-93,2,7,0,2,3,7,0,-45,0,4,0,3,3,2,0,20,0,2, +0,4,3,2,0,5,3,2,0,6,3,2,0,7,3,2,0,8,3,2,0,9,3,2,0,10,3,2,0,11,3,2, +0,12,3,2,0,13,3,2,0,14,3,4,0,15,3,4,0,16,3,4,0,17,3,4,0,18,3,7,0,19,3,7, +0,20,3,7,0,21,3,7,0,22,3,7,0,23,3,7,0,24,3,7,0,25,3,7,0,26,3,7,0,27,3,7, +0,28,3,7,0,29,3,7,0,30,3,0,0,31,3,0,0,32,3,0,0,-45,1,0,0,33,3,0,0,34,3,0, +0,35,3,7,0,36,3,7,0,37,3,39,0,125,0,12,0,38,3,12,0,39,3,12,0,40,3,12,0,41,3,7, +0,42,3,2,0,71,2,2,0,43,3,7,0,52,2,4,0,44,3,4,0,45,3,-109,0,46,3,2,0,47,3,2, +0,-38,0,7,0,48,3,12,0,49,3,12,0,50,3,12,0,51,3,12,0,52,3,-108,0,53,3,-107,0,54,3,63, +0,55,3,2,0,56,3,2,0,57,3,2,0,58,3,2,0,59,3,7,0,44,2,2,0,60,3,2,0,61,3,-116, +0,62,3,-127,0,63,3,-127,0,64,3,4,0,65,3,4,0,66,3,4,0,67,3,4,0,70,0,9,0,-94,0,12, +0,68,3,-106,0,14,0,-106,0,0,0,-106,0,1,0,32,0,38,0,7,0,-93,2,7,0,9,1,7,0,-92,2,7, +0,-99,2,0,0,17,0,4,0,-91,2,4,0,-90,2,4,0,69,3,2,0,18,0,2,0,70,3,7,0,-89,2,-108, +0,36,0,2,0,71,3,2,0,72,3,2,0,20,0,2,0,-99,2,7,0,73,3,7,0,74,3,7,0,75,3,7, +0,76,3,7,0,77,3,7,0,78,3,7,0,79,3,7,0,80,3,7,0,81,3,7,0,82,3,7,0,83,3,7, +0,84,3,7,0,85,3,7,0,86,3,7,0,87,3,7,0,88,3,7,0,89,3,7,0,90,3,7,0,91,3,7, +0,92,3,7,0,93,3,7,0,94,3,7,0,95,3,7,0,96,3,2,0,97,3,2,0,98,3,2,0,99,3,2, +0,100,3,51,0,-88,0,-105,0,101,3,7,0,102,3,4,0,110,2,125,0,5,0,4,0,20,0,4,0,103,3,4, +0,104,3,4,0,105,3,4,0,106,3,-104,0,1,0,7,0,-31,1,-109,0,30,0,4,0,20,0,7,0,107,3,7, +0,108,3,7,0,109,3,4,0,110,3,4,0,111,3,4,0,112,3,4,0,113,3,7,0,114,3,7,0,115,3,7, +0,116,3,7,0,117,3,7,0,118,3,7,0,119,3,7,0,120,3,7,0,121,3,7,0,122,3,7,0,123,3,7, +0,124,3,7,0,125,3,7,0,126,3,7,0,127,3,7,0,-128,3,7,0,-127,3,7,0,-126,3,7,0,-125,3,4, +0,-124,3,4,0,-123,3,7,0,-122,3,7,0,27,3,-107,0,49,0,-120,0,-121,3,4,0,-120,3,4,0,-119,3,-103, +0,-118,3,-102,0,-117,3,0,0,37,0,0,0,-116,3,2,0,-115,3,7,0,-114,3,0,0,-113,3,7,0,-112,3,7, +0,-111,3,7,0,-110,3,7,0,-109,3,7,0,-108,3,7,0,-107,3,7,0,-106,3,7,0,-105,3,7,0,-104,3,2, +0,-103,3,0,0,-102,3,2,0,-101,3,7,0,-100,3,7,0,-99,3,0,0,-98,3,4,0,-126,0,4,0,-97,3,4, +0,-96,3,2,0,-95,3,2,0,-94,3,-104,0,-93,3,4,0,-92,3,4,0,81,0,7,0,-91,3,7,0,-90,3,7, +0,-89,3,7,0,-88,3,2,0,-87,3,2,0,-86,3,2,0,-85,3,2,0,-84,3,2,0,-83,3,2,0,-82,3,2, +0,-81,3,2,0,-80,3,-101,0,-79,3,7,0,-78,3,7,0,-77,3,125,0,-76,3,-116,0,48,0,2,0,18,0,2, +0,-75,3,2,0,-74,3,2,0,-73,3,7,0,-72,3,2,0,-71,3,2,0,-70,3,7,0,-69,3,2,0,-68,3,2, +0,-67,3,7,0,-66,3,7,0,-65,3,7,0,-64,3,7,0,-63,3,7,0,-62,3,7,0,-61,3,4,0,-60,3,7, +0,-59,3,7,0,-58,3,7,0,-57,3,74,0,-56,3,74,0,-55,3,74,0,-54,3,0,0,-53,3,7,0,-52,3,7, +0,-51,3,36,0,79,0,2,0,-50,3,0,0,-49,3,0,0,-48,3,7,0,-47,3,4,0,-46,3,7,0,-45,3,7, +0,-44,3,4,0,-43,3,4,0,20,0,7,0,-42,3,7,0,-41,3,7,0,-40,3,78,0,-39,3,7,0,-38,3,7, +0,-37,3,7,0,-36,3,7,0,-35,3,7,0,-34,3,7,0,-33,3,7,0,-32,3,4,0,-31,3,-100,0,71,0,27, +0,31,0,2,0,-79,0,2,0,14,1,2,0,47,1,2,0,-30,3,7,0,-29,3,7,0,-28,3,7,0,-27,3,7, +0,-26,3,7,0,-25,3,7,0,-24,3,7,0,-23,3,7,0,-22,3,7,0,84,1,7,0,86,1,7,0,85,1,7, +0,-21,3,4,0,-20,3,7,0,-19,3,7,0,-18,3,7,0,-17,3,7,0,-16,3,7,0,-15,3,7,0,-14,3,7, +0,-13,3,2,0,-12,3,2,0,13,1,2,0,-11,3,2,0,-10,3,2,0,-9,3,2,0,-8,3,2,0,-7,3,2, +0,-6,3,7,0,-5,3,7,0,-4,3,7,0,-3,3,7,0,-2,3,7,0,-1,3,7,0,0,4,7,0,1,4,7, +0,2,4,7,0,3,4,7,0,4,4,7,0,5,4,7,0,6,4,2,0,7,4,2,0,8,4,2,0,9,4,2, +0,10,4,7,0,11,4,7,0,12,4,7,0,13,4,7,0,14,4,2,0,15,4,2,0,16,4,2,0,17,4,2, +0,18,4,7,0,19,4,7,0,20,4,7,0,21,4,7,0,22,4,2,0,23,4,2,0,24,4,2,0,25,4,2, +0,43,0,7,0,26,4,7,0,27,4,36,0,79,0,50,0,77,1,30,0,-103,0,39,0,125,0,-99,0,16,0,2, +0,28,4,2,0,29,4,2,0,30,4,2,0,20,0,2,0,31,4,2,0,32,4,2,0,33,4,2,0,34,4,2, +0,35,4,2,0,36,4,2,0,37,4,2,0,38,4,4,0,39,4,7,0,40,4,7,0,41,4,7,0,42,4,-98, +0,8,0,-98,0,0,0,-98,0,1,0,4,0,3,3,4,0,43,4,4,0,20,0,2,0,44,4,2,0,45,4,32, +0,-89,0,-97,0,13,0,9,0,46,4,9,0,47,4,4,0,48,4,4,0,49,4,4,0,50,4,4,0,51,4,4, +0,52,4,4,0,53,4,4,0,54,4,4,0,55,4,4,0,56,4,4,0,37,0,0,0,57,4,-96,0,5,0,9, +0,58,4,9,0,59,4,4,0,60,4,4,0,70,0,0,0,61,4,-95,0,13,0,4,0,18,0,4,0,62,4,4, +0,63,4,4,0,64,4,4,0,65,4,4,0,66,4,4,0,93,0,4,0,67,4,4,0,68,4,4,0,69,4,4, +0,70,4,4,0,71,4,26,0,30,0,-94,0,4,0,4,0,72,4,7,0,73,4,2,0,20,0,2,0,68,2,-93, +0,11,0,-93,0,0,0,-93,0,1,0,0,0,17,0,62,0,74,4,63,0,75,4,4,0,3,3,4,0,76,4,4, +0,77,4,4,0,37,0,4,0,78,4,4,0,79,4,-92,0,-126,0,-97,0,80,4,-96,0,81,4,-95,0,82,4,4, +0,83,4,4,0,-126,0,4,0,-97,3,4,0,84,4,4,0,85,4,4,0,86,4,4,0,87,4,2,0,20,0,2, +0,88,4,7,0,20,3,7,0,89,4,7,0,90,4,7,0,91,4,7,0,92,4,7,0,93,4,2,0,94,4,2, +0,95,4,2,0,96,4,2,0,97,4,2,0,-39,0,2,0,98,4,2,0,99,4,2,0,100,3,2,0,100,4,2, +0,101,4,2,0,34,1,2,0,109,0,2,0,102,4,2,0,103,4,2,0,104,4,2,0,105,4,2,0,106,4,2, +0,107,4,2,0,108,4,2,0,109,4,2,0,110,4,2,0,35,1,2,0,111,4,2,0,112,4,2,0,113,4,2, +0,114,4,4,0,115,4,4,0,13,1,2,0,116,4,2,0,117,4,2,0,118,4,2,0,119,4,2,0,120,4,2, +0,121,4,24,0,122,4,24,0,123,4,23,0,124,4,12,0,125,4,2,0,126,4,2,0,37,0,7,0,127,4,7, +0,-128,4,7,0,-127,4,7,0,-126,4,7,0,-125,4,7,0,-124,4,7,0,-123,4,7,0,-122,4,7,0,-121,4,2, +0,-120,4,2,0,-119,4,2,0,-118,4,2,0,-117,4,2,0,-116,4,2,0,-115,4,7,0,-114,4,7,0,-113,4,7, +0,-112,4,2,0,-111,4,2,0,-110,4,2,0,-109,4,2,0,-108,4,2,0,-107,4,2,0,-106,4,2,0,-105,4,2, +0,-104,4,2,0,-103,4,2,0,-102,4,4,0,-101,4,4,0,-100,4,4,0,-99,4,4,0,-98,4,4,0,-97,4,7, +0,-96,4,4,0,-95,4,4,0,-94,4,4,0,-93,4,4,0,-92,4,7,0,-91,4,7,0,-90,4,7,0,-89,4,7, +0,-88,4,7,0,-87,4,7,0,-86,4,7,0,-85,4,7,0,-84,4,7,0,-83,4,0,0,-82,4,0,0,-81,4,4, +0,-80,4,2,0,-79,4,2,0,12,1,0,0,-78,4,7,0,-77,4,7,0,-76,4,4,0,-75,4,4,0,-74,4,7, +0,-73,4,7,0,-72,4,2,0,-71,4,2,0,-70,4,7,0,-69,4,2,0,-68,4,2,0,-67,4,4,0,-66,4,2, +0,-65,4,2,0,-64,4,2,0,-63,4,2,0,-62,4,7,0,-61,4,7,0,70,0,42,0,-60,4,-91,0,9,0,-91, +0,0,0,-91,0,1,0,0,0,17,0,2,0,-59,4,2,0,-58,4,2,0,-57,4,2,0,43,0,7,0,-56,4,7, +0,70,0,-90,0,5,0,7,0,-55,4,0,0,18,0,0,0,43,0,0,0,70,0,0,0,12,1,-89,0,5,0,-89, +0,0,0,-89,0,1,0,4,0,-54,4,0,0,-53,4,4,0,20,0,-88,0,5,0,-87,0,-52,4,2,0,20,0,2, +0,-51,4,2,0,-50,4,2,0,-49,4,-86,0,4,0,2,0,109,0,2,0,-122,2,2,0,-48,4,2,0,-47,4,-85, +0,7,0,2,0,20,0,2,0,-46,4,2,0,-45,4,2,0,-44,4,-86,0,-43,4,7,0,-42,4,4,0,-41,4,-84, +0,4,0,-84,0,0,0,-84,0,1,0,0,0,-40,4,7,0,-39,4,-83,0,56,0,2,0,-38,4,2,0,-37,4,7, +0,-36,4,7,0,-35,4,2,0,-48,4,2,0,-34,4,7,0,-33,4,7,0,-32,4,2,0,-31,4,2,0,-30,4,2, +0,-29,4,2,0,-28,4,7,0,-27,4,7,0,-26,4,7,0,-25,4,7,0,37,0,2,0,-24,4,2,0,-23,4,2, +0,-22,4,2,0,-21,4,-88,0,-20,4,-85,0,-19,4,7,0,-18,4,7,0,-17,4,0,0,-16,4,0,0,-15,4,0, +0,-14,4,0,0,-13,4,0,0,-12,4,0,0,-11,4,2,0,-10,4,7,0,-9,4,7,0,-8,4,7,0,-7,4,7, +0,-6,4,7,0,-5,4,7,0,-4,4,7,0,-3,4,7,0,-2,4,7,0,-1,4,7,0,0,5,2,0,1,5,0, +0,2,5,0,0,3,5,0,0,4,5,0,0,5,5,32,0,6,5,0,0,7,5,0,0,8,5,0,0,9,5,0, +0,10,5,0,0,11,5,0,0,12,5,0,0,13,5,0,0,14,5,0,0,15,5,-82,0,6,0,2,0,109,0,0, +0,-122,2,0,0,16,5,0,0,17,5,0,0,20,0,0,0,-74,0,-81,0,26,0,-80,0,18,5,50,0,77,1,60, +0,19,5,-82,0,20,5,-82,0,21,5,-82,0,22,5,-82,0,23,5,-82,0,24,5,-82,0,25,5,-82,0,26,5,7, +0,27,5,2,0,28,5,2,0,47,1,2,0,29,5,2,0,1,2,0,0,30,5,0,0,31,5,0,0,32,5,0, +0,33,5,0,0,93,0,0,0,34,5,0,0,35,5,0,0,36,5,0,0,37,5,0,0,38,5,0,0,-74,0,-79, +0,43,0,27,0,31,0,32,0,39,5,-100,0,40,5,-79,0,41,5,46,0,-47,0,12,0,42,5,-98,0,43,5,7, +0,44,5,7,0,45,5,7,0,46,5,7,0,47,5,4,0,3,3,7,0,48,5,2,0,49,5,2,0,50,5,2, +0,51,5,2,0,52,5,2,0,53,5,2,0,54,5,2,0,55,5,2,0,5,1,57,0,1,1,9,0,56,5,-99, +0,57,5,-90,0,58,5,-83,0,59,5,-92,0,-73,0,-94,0,60,5,39,0,125,0,12,0,103,0,12,0,61,5,2, +0,62,5,2,0,63,5,2,0,64,5,2,0,65,5,-78,0,66,5,2,0,67,5,2,0,68,5,2,0,64,1,2, +0,-38,0,-81,0,69,5,4,0,70,5,4,0,37,0,-77,0,9,0,46,0,-47,0,45,0,0,1,7,0,8,2,7, +0,9,2,7,0,109,0,7,0,71,5,7,0,72,5,2,0,73,5,2,0,74,5,-76,0,75,0,-75,0,0,0,-75, +0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,7,0,79,5,7,0,80,5,7,0,81,5,7, +0,82,5,7,0,83,5,7,0,84,5,7,0,85,5,7,0,20,1,7,0,86,5,4,0,87,5,2,0,88,5,2, +0,17,5,32,0,39,5,32,0,89,5,-77,0,90,5,-76,0,91,5,-73,0,92,5,-72,0,93,5,-71,0,94,5,0, +0,95,5,2,0,30,4,2,0,96,5,4,0,3,3,4,0,97,5,2,0,98,5,2,0,99,5,2,0,100,5,0, +0,101,5,0,0,43,0,7,0,115,0,7,0,102,5,7,0,103,5,7,0,104,5,7,0,105,5,7,0,106,5,7, +0,107,5,7,0,108,5,7,0,-82,0,7,0,44,5,2,0,109,5,2,0,110,5,2,0,111,5,2,0,112,5,2, +0,-119,0,2,0,29,5,2,0,113,5,2,0,114,5,2,0,115,5,2,0,116,5,7,0,117,5,7,0,118,5,67, +0,119,5,12,0,120,5,2,0,121,5,2,0,53,2,2,0,122,5,2,0,20,0,2,0,123,5,2,0,124,5,2, +0,125,5,0,0,126,5,0,0,127,5,9,0,-128,5,-70,0,-127,5,7,0,-126,5,2,0,-125,5,2,0,-124,5,2, +0,53,5,2,0,54,5,-69,0,19,0,24,0,36,0,24,0,64,0,23,0,-123,5,23,0,-122,5,23,0,-121,5,7, +0,-120,5,7,0,-119,5,7,0,-118,5,7,0,-117,5,2,0,-116,5,2,0,-115,5,2,0,-114,5,2,0,-113,5,2, +0,-112,5,2,0,-111,5,4,0,20,0,7,0,-110,5,2,0,99,5,0,0,107,2,-75,0,6,0,-75,0,0,0,-75, +0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,-68,0,6,0,-75,0,0,0,-75,0,1,0,4, +0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,-67,0,27,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7, +0,76,5,-74,0,77,5,2,0,78,5,4,0,-109,5,4,0,70,0,-69,0,-108,5,9,0,-107,5,12,0,-106,5,36, +0,79,0,27,0,80,0,0,0,-105,5,0,0,-104,5,0,0,-103,5,2,0,-102,5,2,0,-101,5,2,0,-100,5,2, +0,-99,5,2,0,65,0,2,0,46,0,2,0,-119,0,2,0,-98,5,4,0,20,0,7,0,-97,5,24,0,36,0,-66, +0,29,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,-73,0,92,5,2,0,78,5,2, +0,-96,5,2,0,-95,5,2,0,-94,5,2,0,-93,5,-69,0,-108,5,2,0,-92,5,2,0,-119,0,2,0,-101,5,2, +0,-91,5,9,0,-90,5,2,0,29,5,0,0,-89,5,0,0,-88,5,2,0,-87,5,2,0,-86,5,2,0,12,3,2, +0,-85,5,2,0,-84,5,0,0,37,0,0,0,20,0,0,0,47,1,0,0,-83,5,-65,0,16,0,-75,0,0,0,-75, +0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,-69,0,-108,5,7,0,8,2,7,0,9,2,2, +0,-92,5,2,0,-82,5,2,0,-81,5,2,0,-80,5,4,0,20,0,7,0,71,5,-70,0,-127,5,-64,0,33,0,-75, +0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,-63,0,-79,5,4,0,-78,5,0, +0,-77,5,0,0,-76,5,0,0,-75,5,2,0,18,0,2,0,-74,5,2,0,20,0,2,0,-73,5,2,0,-72,5,2, +0,-71,5,2,0,-70,5,2,0,43,0,4,0,70,0,0,0,-69,5,-62,0,-68,5,2,0,-67,5,2,0,-66,5,2, +0,-65,5,2,0,-48,0,9,0,-64,5,9,0,-63,5,9,0,-62,5,9,0,-61,5,9,0,-60,5,2,0,-59,5,0, +0,-58,5,-61,0,23,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,-69, +0,-108,5,12,0,-57,5,2,0,-101,5,2,0,-56,5,2,0,20,0,2,0,57,0,9,0,-90,5,12,0,-55,5,-60, +0,-54,5,0,0,-53,5,-59,0,-52,5,4,0,-51,5,4,0,-50,5,2,0,18,0,2,0,-49,5,2,0,-48,5,2, +0,-47,5,-58,0,29,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,-69, +0,-108,5,46,0,-114,2,45,0,0,1,60,0,19,5,2,0,13,1,2,0,-119,0,2,0,-46,5,2,0,-45,5,4, +0,20,0,2,0,49,5,2,0,-44,5,2,0,-98,5,2,0,-101,5,7,0,71,5,0,0,-43,5,0,0,-42,5,0, +0,-41,5,0,0,-40,5,7,0,8,2,7,0,9,2,7,0,-39,5,7,0,-38,5,-70,0,-127,5,-57,0,11,0,-75, +0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,2,0,-119,0,2,0,-98,5,2, +0,-37,5,2,0,20,0,-69,0,-108,5,-56,0,24,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74, +0,77,5,2,0,78,5,42,0,-36,5,4,0,-35,5,4,0,-34,5,2,0,93,0,2,0,-119,0,4,0,-33,5,4, +0,-32,5,4,0,-31,5,4,0,-30,5,4,0,-29,5,4,0,-28,5,4,0,-27,5,4,0,-26,5,7,0,-25,5,23, +0,-24,5,23,0,-23,5,4,0,-22,5,4,0,-21,5,-55,0,10,0,27,0,31,0,9,0,-20,5,9,0,-19,5,9, +0,-18,5,9,0,-17,5,9,0,-16,5,4,0,93,0,4,0,-15,5,0,0,-14,5,0,0,-13,5,-54,0,10,0,-75, +0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,-55,0,-12,5,2,0,93,0,2,0,-119,0,4, +0,43,0,9,0,-11,5,-53,0,8,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,-69, +0,-108,5,4,0,20,0,4,0,-10,5,-52,0,21,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74, +0,77,5,2,0,78,5,-69,0,-108,5,27,0,-9,5,27,0,80,0,2,0,20,0,2,0,-119,0,7,0,-8,5,9, +0,-7,5,7,0,8,2,7,0,9,2,57,0,1,1,57,0,-6,5,4,0,-5,5,2,0,-89,5,2,0,37,0,-70, +0,-127,5,-51,0,42,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,-69, +0,-108,5,-50,0,-4,5,0,0,-77,5,0,0,-76,5,0,0,-75,5,2,0,18,0,2,0,-66,5,2,0,20,0,2, +0,-73,5,9,0,-7,5,4,0,-3,5,4,0,-2,5,4,0,-1,5,4,0,0,6,23,0,1,6,23,0,2,6,7, +0,3,6,7,0,4,6,7,0,5,6,7,0,-8,5,2,0,-67,5,2,0,-48,0,2,0,102,1,2,0,6,6,2, +0,37,0,2,0,43,0,2,0,7,6,2,0,8,6,9,0,-64,5,9,0,-63,5,9,0,-62,5,9,0,-61,5,9, +0,-60,5,2,0,-59,5,0,0,-58,5,56,0,9,6,-49,0,20,0,0,0,10,6,0,0,11,6,0,0,12,6,0, +0,13,6,0,0,14,6,0,0,15,6,0,0,16,6,0,0,17,6,0,0,18,6,0,0,19,6,0,0,20,6,0, +0,21,6,0,0,22,6,0,0,23,6,0,0,24,6,0,0,25,6,0,0,26,6,0,0,27,6,0,0,68,2,0, +0,28,6,-48,0,54,0,0,0,29,6,0,0,20,6,0,0,21,6,0,0,30,6,0,0,31,6,0,0,32,6,0, +0,33,6,0,0,34,6,0,0,35,6,0,0,36,6,0,0,37,6,0,0,38,6,0,0,39,6,0,0,40,6,0, +0,41,6,0,0,42,6,0,0,43,6,0,0,44,6,0,0,45,6,0,0,46,6,0,0,47,6,0,0,48,6,0, +0,49,6,0,0,50,6,0,0,51,6,0,0,52,6,0,0,53,6,0,0,54,6,0,0,55,6,0,0,56,6,0, +0,57,6,0,0,58,6,0,0,95,0,0,0,59,6,0,0,60,6,0,0,61,6,0,0,62,6,0,0,63,6,0, +0,64,6,0,0,65,6,0,0,66,6,0,0,67,6,0,0,68,6,0,0,69,6,0,0,70,6,0,0,71,6,0, +0,72,6,0,0,73,6,0,0,74,6,0,0,75,6,0,0,76,6,0,0,77,6,0,0,78,6,0,0,79,6,-47, +0,5,0,0,0,80,6,0,0,37,6,0,0,39,6,2,0,20,0,2,0,37,0,-46,0,22,0,-46,0,0,0,-46, +0,1,0,0,0,17,0,-49,0,81,6,-48,0,82,6,-48,0,83,6,-48,0,84,6,-48,0,85,6,-48,0,86,6,-48, +0,87,6,-48,0,88,6,-48,0,89,6,-48,0,90,6,-48,0,91,6,-48,0,92,6,-48,0,93,6,-48,0,94,6,-48, +0,95,6,-48,0,96,6,-47,0,97,6,0,0,98,6,0,0,99,6,-45,0,5,0,4,0,20,0,4,0,37,0,7, +0,52,2,7,0,100,6,7,0,-31,1,-44,0,66,0,4,0,20,0,4,0,101,6,4,0,102,6,0,0,103,6,0, +0,104,6,0,0,105,6,0,0,106,6,0,0,107,6,0,0,108,6,0,0,109,6,0,0,110,6,0,0,111,6,2, +0,112,6,2,0,113,6,4,0,114,6,4,0,115,6,4,0,116,6,4,0,117,6,2,0,118,6,2,0,119,6,2, +0,120,6,2,0,121,6,4,0,122,6,4,0,123,6,2,0,124,6,2,0,125,6,2,0,126,6,2,0,127,6,0, +0,-128,6,12,0,-127,6,2,0,-126,6,2,0,-125,6,2,0,-124,6,2,0,-123,6,2,0,-122,6,2,0,-121,6,2, +0,-120,6,2,0,-119,6,-45,0,-118,6,2,0,-117,6,2,0,-116,6,2,0,-115,6,2,0,-114,6,4,0,-113,6,4, +0,-112,6,4,0,-111,6,4,0,-110,6,2,0,-109,6,2,0,-108,6,2,0,-107,6,2,0,-106,6,2,0,-105,6,2, +0,-104,6,2,0,-103,6,2,0,-102,6,2,0,-101,6,2,0,-100,6,2,0,-99,6,2,0,37,0,0,0,-98,6,0, +0,-97,6,0,0,-96,6,7,0,-95,6,2,0,55,5,2,0,-94,6,54,0,-93,6,-43,0,18,0,27,0,31,0,12, +0,-92,6,12,0,-91,6,12,0,-90,6,-79,0,-89,6,2,0,-105,2,2,0,-88,6,2,0,-104,2,2,0,-87,6,2, +0,-86,6,2,0,-85,6,2,0,-84,6,2,0,-83,6,2,0,-82,6,2,0,37,0,2,0,-81,6,2,0,-80,6,2, +0,-79,6,-42,0,5,0,-42,0,0,0,-42,0,1,0,-42,0,-78,6,13,0,-77,6,4,0,20,0,-41,0,7,0,-41, +0,0,0,-41,0,1,0,-42,0,-76,6,-42,0,-75,6,2,0,123,4,2,0,20,0,4,0,37,0,-40,0,17,0,-40, +0,0,0,-40,0,1,0,0,0,-74,6,0,0,-73,6,0,0,-72,6,2,0,-71,6,2,0,-70,6,2,0,-86,6,2, +0,-85,6,2,0,20,0,2,0,70,3,2,0,-69,6,2,0,-68,6,2,0,-67,6,2,0,-66,6,4,0,-65,6,-40, +0,-64,6,-74,0,30,0,-74,0,0,0,-74,0,1,0,-42,0,-76,6,-42,0,-75,6,-42,0,-63,6,-42,0,-62,6,-43, +0,-61,6,7,0,-60,6,23,0,52,0,23,0,-59,6,23,0,-58,6,2,0,-57,6,2,0,-56,6,2,0,-55,6,0, +0,75,5,0,0,-54,6,2,0,-53,6,2,0,-52,6,0,0,-51,6,0,0,-50,6,0,0,-49,6,0,0,-48,6,2, +0,-47,6,2,0,-46,6,2,0,-45,6,2,0,20,0,39,0,125,0,12,0,-44,6,12,0,-43,6,12,0,-42,6,-39, +0,11,0,0,0,-41,6,2,0,-40,6,2,0,-39,6,2,0,-38,6,2,0,-37,6,2,0,-36,6,2,0,107,4,9, +0,-35,6,9,0,-34,6,4,0,-33,6,4,0,-32,6,-38,0,1,0,0,0,-31,6,-37,0,8,0,56,0,-30,6,56, +0,-29,6,-37,0,-28,6,-37,0,-27,6,-37,0,-26,6,2,0,-123,0,2,0,20,0,4,0,-25,6,-36,0,4,0,4, +0,-35,5,4,0,-24,6,4,0,-31,5,4,0,-23,6,-35,0,2,0,4,0,-22,6,4,0,-21,6,-34,0,9,0,7, +0,-20,6,7,0,-19,6,7,0,-18,6,4,0,20,0,4,0,13,1,7,0,-19,3,7,0,-17,6,4,0,37,0,-33, +0,-16,6,-32,0,6,0,0,0,-15,6,0,0,-75,5,48,0,-116,0,2,0,109,0,2,0,111,4,4,0,37,0,-31, +0,21,0,-31,0,0,0,-31,0,1,0,4,0,57,0,4,0,23,0,4,0,28,0,4,0,-14,6,4,0,-13,6,4, +0,-12,6,-38,0,-11,6,0,0,-15,6,4,0,-10,6,4,0,-9,6,-32,0,-12,2,-36,0,-8,6,-35,0,-7,6,-34, +0,-6,6,-37,0,-5,6,-37,0,-4,6,-37,0,-3,6,56,0,-2,6,56,0,-1,6,-30,0,12,0,0,0,-68,1,9, +0,-62,0,0,0,-61,0,4,0,-58,0,4,0,-50,0,9,0,-57,0,7,0,-55,0,7,0,-54,0,9,0,0,7,9, +0,1,7,9,0,-53,0,9,0,-51,0,-29,0,43,0,-29,0,0,0,-29,0,1,0,9,0,2,7,9,0,26,0,0, +0,27,0,4,0,20,0,4,0,18,0,4,0,23,0,4,0,91,0,4,0,3,7,4,0,4,7,4,0,-13,6,4, +0,-12,6,4,0,5,7,4,0,-39,0,4,0,6,7,4,0,7,7,7,0,8,7,7,0,9,7,4,0,-126,0,4, +0,10,7,-31,0,11,7,36,0,79,0,-79,0,-89,6,48,0,-116,0,7,0,12,7,7,0,13,7,-30,0,2,1,-29, +0,14,7,-29,0,15,7,-29,0,16,7,12,0,17,7,-28,0,18,7,-27,0,19,7,7,0,20,7,7,0,21,7,4, +0,-84,6,7,0,22,7,9,0,23,7,4,0,24,7,4,0,25,7,4,0,26,7,7,0,27,7,-26,0,4,0,-26, +0,0,0,-26,0,1,0,12,0,28,7,-29,0,29,7,-25,0,6,0,12,0,30,7,12,0,17,7,12,0,31,7,2, +0,20,0,2,0,37,0,4,0,57,0,-24,0,4,0,7,0,32,7,7,0,112,0,2,0,33,7,2,0,34,7,-23, +0,6,0,7,0,35,7,7,0,36,7,7,0,37,7,7,0,38,7,4,0,39,7,4,0,40,7,-22,0,12,0,7, +0,41,7,7,0,42,7,7,0,43,7,7,0,44,7,7,0,45,7,7,0,46,7,7,0,47,7,7,0,48,7,7, +0,49,7,7,0,50,7,4,0,-110,2,4,0,51,7,-21,0,2,0,7,0,-55,4,7,0,37,0,-20,0,7,0,7, +0,52,7,7,0,53,7,4,0,93,0,4,0,108,2,4,0,54,7,4,0,55,7,4,0,37,0,-19,0,6,0,-19, +0,0,0,-19,0,1,0,2,0,18,0,2,0,20,0,2,0,56,7,2,0,57,0,-18,0,8,0,-18,0,0,0,-18, +0,1,0,2,0,18,0,2,0,20,0,2,0,56,7,2,0,57,0,7,0,23,0,7,0,-126,0,-17,0,45,0,-17, +0,0,0,-17,0,1,0,2,0,18,0,2,0,20,0,2,0,56,7,2,0,-43,0,2,0,-103,3,2,0,57,7,7, +0,58,7,7,0,92,0,7,0,-97,2,4,0,59,7,4,0,81,0,4,0,110,2,7,0,60,7,7,0,61,7,7, +0,62,7,7,0,63,7,7,0,64,7,7,0,65,7,7,0,-100,2,7,0,-1,0,7,0,66,7,7,0,67,7,7, +0,37,0,7,0,68,7,7,0,69,7,7,0,70,7,2,0,71,7,2,0,72,7,2,0,73,7,2,0,74,7,2, +0,75,7,2,0,76,7,2,0,77,7,2,0,78,7,2,0,123,5,2,0,79,7,2,0,-47,1,2,0,80,7,0, +0,81,7,0,0,82,7,7,0,-45,0,-16,0,83,7,63,0,-95,1,-15,0,16,0,-15,0,0,0,-15,0,1,0,2, +0,18,0,2,0,20,0,2,0,56,7,2,0,-43,0,7,0,-105,2,7,0,-104,2,7,0,-103,2,7,0,-5,1,7, +0,-102,2,7,0,-101,2,7,0,84,7,7,0,-100,2,7,0,-98,2,7,0,-97,2,-59,0,5,0,2,0,18,0,2, +0,-25,6,2,0,20,0,2,0,85,7,27,0,-9,5,-60,0,3,0,4,0,69,0,4,0,86,7,-59,0,2,0,-14, +0,12,0,-14,0,0,0,-14,0,1,0,2,0,18,0,2,0,20,0,2,0,31,3,2,0,-32,1,7,0,5,0,7, +0,6,0,7,0,87,7,7,0,88,7,27,0,-9,5,12,0,89,7,-13,0,11,0,-13,0,0,0,-13,0,1,0,0, +0,17,0,2,0,18,0,2,0,90,7,4,0,22,0,4,0,91,7,2,0,20,0,2,0,37,0,9,0,92,7,9, +0,93,7,-12,0,5,0,0,0,17,0,7,0,20,1,7,0,94,7,4,0,95,7,4,0,37,0,-11,0,4,0,2, +0,18,0,2,0,20,0,2,0,43,0,2,0,70,0,-10,0,4,0,0,0,17,0,62,0,96,7,7,0,20,1,7, +0,37,0,-9,0,6,0,2,0,97,7,2,0,98,7,2,0,18,0,2,0,99,7,0,0,100,7,0,0,101,7,-8, +0,5,0,4,0,18,0,4,0,37,0,0,0,17,0,0,0,102,7,0,0,103,7,-7,0,3,0,4,0,18,0,4, +0,37,0,0,0,17,0,-6,0,4,0,2,0,104,7,2,0,105,7,2,0,20,0,2,0,37,0,-5,0,6,0,0, +0,17,0,0,0,106,7,2,0,107,7,2,0,-100,2,2,0,13,1,2,0,70,0,-4,0,5,0,0,0,17,0,7, +0,112,0,7,0,-17,3,2,0,20,0,2,0,122,2,-3,0,3,0,0,0,17,0,4,0,110,2,4,0,104,7,-2, +0,7,0,0,0,17,0,7,0,-17,3,0,0,108,7,0,0,109,7,2,0,13,1,2,0,43,0,4,0,110,7,-1, +0,3,0,32,0,111,7,0,0,112,7,0,0,113,7,0,1,18,0,0,1,0,0,0,1,1,0,2,0,18,0,2, +0,90,7,2,0,20,0,2,0,114,7,2,0,115,7,2,0,116,7,2,0,43,0,2,0,70,0,0,0,17,0,9, +0,2,0,1,1,117,7,32,0,45,0,2,0,-47,4,2,0,20,7,2,0,118,7,2,0,37,0,2,1,11,0,0, +0,17,0,0,0,18,0,0,0,119,7,2,0,20,0,2,0,122,2,2,0,120,7,4,0,121,7,4,0,122,7,4, +0,123,7,4,0,124,7,4,0,125,7,3,1,1,0,0,0,126,7,4,1,4,0,42,0,-36,5,0,0,127,7,4, +0,13,1,4,0,20,0,1,1,18,0,1,1,0,0,1,1,1,0,1,1,-128,7,2,0,18,0,2,0,20,0,2, +0,-127,7,2,0,116,7,2,0,90,7,2,0,-126,7,2,0,70,0,2,0,12,1,0,0,17,0,9,0,2,0,5, +1,117,7,0,1,-125,7,2,0,15,0,2,0,-124,7,4,0,-123,7,6,1,3,0,4,0,-74,2,4,0,37,0,32, +0,45,0,7,1,12,0,-111,0,-122,7,2,0,18,0,2,0,20,0,4,0,58,7,4,0,92,0,0,0,17,0,0, +0,-121,7,2,0,-120,7,2,0,-119,7,2,0,-118,7,2,0,-117,7,7,0,-116,7,8,1,10,0,2,0,20,0,2, +0,-115,7,4,0,58,7,4,0,92,0,2,0,-114,7,-28,0,18,7,2,0,18,0,2,0,-113,7,2,0,-112,7,2, +0,-111,7,9,1,7,0,2,0,20,0,2,0,-115,7,4,0,58,7,4,0,92,0,2,0,18,0,2,0,-110,7,7, +0,109,3,10,1,11,0,4,0,-74,2,2,0,18,0,2,0,20,0,32,0,45,0,74,0,-109,7,0,0,17,0,7, +0,-108,7,7,0,-107,7,7,0,21,3,2,0,-106,7,2,0,-105,7,11,1,5,0,2,0,18,0,2,0,20,0,4, +0,37,0,-79,0,-89,6,32,0,39,5,12,1,5,0,4,0,20,0,4,0,18,0,0,0,17,0,0,0,102,7,32, +0,45,0,13,1,13,0,2,0,20,0,2,0,18,0,2,0,90,7,2,0,22,3,7,0,-104,7,7,0,-103,7,7, +0,7,1,7,0,8,1,7,0,-3,2,7,0,0,3,7,0,-102,7,7,0,-101,7,32,0,-100,7,14,1,10,0,2, +0,20,0,2,0,18,0,4,0,58,7,4,0,92,0,0,0,17,0,0,0,-121,7,2,0,43,0,2,0,64,0,2, +0,-99,7,2,0,-98,7,15,1,8,0,32,0,45,0,7,0,-103,2,7,0,-97,7,7,0,-96,7,7,0,-108,2,2, +0,20,0,2,0,122,2,7,0,-95,7,16,1,12,0,2,0,18,0,2,0,13,1,2,0,20,0,2,0,-100,2,2, +0,-74,2,2,0,-94,7,4,0,37,0,7,0,-93,7,7,0,-92,7,7,0,-91,7,7,0,-90,7,0,0,-89,7,17, +1,10,0,2,0,20,0,2,0,18,0,4,0,58,7,4,0,92,0,0,0,17,0,2,0,68,2,2,0,64,0,2, +0,-99,7,2,0,-98,7,63,0,-95,1,18,1,7,0,4,0,110,2,4,0,-88,7,4,0,-87,7,4,0,-86,7,7, +0,-85,7,7,0,-84,7,0,0,108,7,19,1,7,0,0,0,-83,7,32,0,-82,7,0,0,112,7,2,0,-81,7,2, +0,43,0,4,0,70,0,0,0,113,7,20,1,6,0,2,0,20,0,2,0,18,0,4,0,58,7,4,0,92,0,0, +0,-80,7,0,0,-79,7,21,1,1,0,4,0,20,0,22,1,6,0,0,0,95,0,2,0,18,0,2,0,20,0,4, +0,-78,7,7,0,-77,7,42,0,-36,5,23,1,4,0,0,0,-74,0,2,0,20,0,4,0,18,0,32,0,45,0,24, +1,2,0,4,0,18,0,4,0,-121,5,5,1,10,0,5,1,0,0,5,1,1,0,5,1,-128,7,2,0,18,0,2, +0,20,0,2,0,90,7,2,0,-76,7,0,0,17,0,9,0,2,0,32,0,45,0,25,1,10,0,7,0,21,3,7, +0,-75,7,7,0,-74,7,7,0,-73,7,7,0,-72,7,4,0,20,0,7,0,-94,7,7,0,-71,7,7,0,-70,7,7, +0,37,0,-28,0,20,0,27,0,31,0,0,0,-63,0,26,1,-69,7,9,0,-68,7,43,0,-104,0,43,0,-67,7,9, +0,-66,7,36,0,79,0,7,0,109,3,7,0,-65,7,7,0,-64,7,7,0,-63,7,7,0,-62,7,7,0,-61,7,7, +0,-60,7,4,0,93,0,4,0,-59,7,0,0,-58,7,0,0,-57,7,0,0,-56,7,27,1,6,0,27,0,31,0,7, +0,-55,7,7,0,-54,7,7,0,-53,7,2,0,-52,7,2,0,-51,7,28,1,14,0,-75,0,0,0,-75,0,1,0,4, +0,75,5,7,0,76,5,-74,0,77,5,-69,0,-108,5,-28,0,18,7,2,0,13,1,2,0,-115,7,2,0,8,2,2, +0,9,2,2,0,20,0,2,0,-98,5,4,0,70,0,29,1,6,0,29,1,0,0,29,1,1,0,32,0,45,0,9, +0,-50,7,4,0,-38,0,4,0,37,0,63,0,4,0,27,0,31,0,12,0,-49,7,4,0,-121,0,7,0,-48,7,30, +1,25,0,30,1,0,0,30,1,1,0,30,1,38,0,12,0,-47,7,0,0,17,0,7,0,-46,7,7,0,-45,7,7, +0,-44,7,7,0,-43,7,4,0,20,0,7,0,-42,7,7,0,-41,7,7,0,-40,7,7,0,20,1,7,0,-39,1,7, +0,-39,7,7,0,108,2,7,0,-38,7,7,0,-37,7,7,0,-36,7,7,0,-35,7,7,0,-34,7,7,0,-81,0,2, +0,-121,0,2,0,-31,4,31,1,19,0,27,0,31,0,12,0,-33,7,12,0,-32,7,4,0,20,0,4,0,30,4,2, +0,-96,2,2,0,-31,7,2,0,-121,0,2,0,-30,7,2,0,-29,7,2,0,-28,7,2,0,-27,7,2,0,-26,7,4, +0,-25,7,4,0,-24,7,4,0,-23,7,4,0,-22,7,4,0,-21,7,4,0,-20,7,32,1,34,0,32,1,0,0,32, +1,1,0,12,0,49,3,0,0,17,0,2,0,20,0,2,0,-19,7,2,0,-18,7,2,0,-17,7,2,0,10,3,2, +0,-16,7,4,0,-7,1,4,0,-23,7,4,0,-22,7,30,1,-15,7,32,1,38,0,32,1,-14,7,12,0,-13,7,9, +0,-12,7,9,0,-11,7,9,0,-10,7,7,0,7,1,7,0,-81,0,7,0,-57,1,7,0,-9,7,7,0,-8,7,7, +0,2,3,7,0,-7,7,7,0,-6,7,7,0,-5,7,7,0,-4,7,7,0,-3,7,7,0,-2,7,7,0,-10,1,32, +0,-1,7,-110,0,9,0,12,0,0,8,2,0,20,0,2,0,1,8,7,0,20,3,7,0,2,8,7,0,3,8,12, +0,4,8,4,0,5,8,4,0,37,0,33,1,7,0,33,1,0,0,33,1,1,0,12,0,-58,7,4,0,20,0,4, +0,6,8,0,0,17,0,-47,0,7,8,34,1,8,0,34,1,0,0,34,1,1,0,33,1,8,8,36,0,79,0,12, +0,-6,2,4,0,20,0,0,0,17,0,4,0,9,8,-111,0,6,0,27,0,31,0,12,0,0,8,12,0,10,8,12, +0,103,0,4,0,11,8,4,0,37,0,35,1,16,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74, +0,77,5,2,0,78,5,-69,0,-108,5,-111,0,-9,2,0,0,13,1,0,0,-37,5,2,0,20,0,2,0,12,8,2, +0,-101,5,2,0,-98,5,2,0,13,8,7,0,14,8,36,1,5,0,36,1,0,0,36,1,1,0,36,0,79,0,2, +0,20,0,0,0,15,8,37,1,12,0,37,1,0,0,37,1,1,0,9,0,2,0,2,0,18,0,2,0,20,0,0, +0,16,8,0,0,17,8,0,0,15,8,7,0,18,8,7,0,19,8,4,0,37,0,36,0,79,0,38,1,9,0,38, +1,0,0,38,1,1,0,32,0,20,8,0,0,21,8,7,0,22,8,2,0,23,8,2,0,20,0,2,0,18,0,2, +0,37,0,39,1,7,0,42,0,-36,5,26,0,24,8,4,0,20,0,4,0,25,8,12,0,26,8,32,0,20,8,0, +0,21,8,40,1,12,0,32,0,20,8,2,0,27,8,2,0,20,0,2,0,28,8,2,0,29,8,0,0,21,8,32, +0,30,8,0,0,31,8,7,0,32,8,7,0,-39,1,7,0,33,8,7,0,34,8,41,1,6,0,32,0,20,8,4, +0,9,8,4,0,35,8,4,0,93,0,4,0,37,0,0,0,21,8,42,1,4,0,32,0,20,8,4,0,20,0,4, +0,9,8,0,0,21,8,43,1,4,0,32,0,20,8,4,0,20,0,4,0,9,8,0,0,21,8,44,1,10,0,32, +0,20,8,4,0,36,8,7,0,-127,0,4,0,20,0,2,0,-42,5,2,0,37,8,2,0,43,0,2,0,70,0,7, +0,38,8,0,0,21,8,45,1,4,0,32,0,20,8,4,0,20,0,4,0,9,8,0,0,21,8,46,1,10,0,32, +0,20,8,2,0,18,0,2,0,-95,3,4,0,91,0,4,0,92,0,7,0,-97,7,7,0,-96,7,4,0,37,0,-111, +0,-122,7,0,0,21,8,47,1,4,0,32,0,20,8,4,0,7,3,4,0,39,8,0,0,21,8,48,1,5,0,32, +0,20,8,7,0,-127,0,4,0,40,8,4,0,7,3,4,0,8,3,49,1,6,0,32,0,20,8,4,0,41,8,4, +0,42,8,7,0,43,8,7,0,44,8,0,0,21,8,50,1,16,0,32,0,20,8,32,0,-14,7,4,0,18,0,7, +0,45,8,7,0,46,8,7,0,47,8,7,0,48,8,7,0,49,8,7,0,50,8,7,0,51,8,7,0,52,8,7, +0,53,8,2,0,20,0,2,0,37,0,2,0,43,0,2,0,70,0,51,1,3,0,32,0,20,8,4,0,20,0,4, +0,123,5,52,1,5,0,32,0,20,8,4,0,20,0,4,0,37,0,7,0,54,8,0,0,21,8,53,1,10,0,32, +0,20,8,0,0,21,8,2,0,55,8,2,0,56,8,0,0,57,8,0,0,58,8,7,0,59,8,7,0,60,8,7, +0,61,8,7,0,62,8,54,1,8,0,7,0,9,0,7,0,10,0,7,0,11,0,7,0,12,0,7,0,63,8,7, +0,64,8,2,0,20,0,2,0,123,5,55,1,8,0,7,0,9,0,7,0,10,0,7,0,11,0,7,0,12,0,7, +0,63,8,7,0,64,8,2,0,20,0,2,0,123,5,56,1,8,0,7,0,9,0,7,0,10,0,7,0,11,0,7, +0,12,0,7,0,63,8,7,0,64,8,2,0,20,0,2,0,123,5,57,1,7,0,32,0,20,8,0,0,21,8,7, +0,20,1,7,0,30,1,2,0,20,0,2,0,13,1,4,0,37,0,58,1,5,0,32,0,-45,2,7,0,20,1,2, +0,-41,2,0,0,-39,2,0,0,65,8,59,1,10,0,59,1,0,0,59,1,1,0,2,0,18,0,2,0,20,0,0, +0,66,8,7,0,-36,0,7,0,-35,0,2,0,-58,7,2,0,67,8,32,0,45,0,60,1,22,0,60,1,0,0,60, +1,1,0,2,0,20,0,2,0,13,1,2,0,68,8,2,0,69,8,36,0,79,0,-111,0,-122,7,32,0,-89,0,7, +0,91,0,7,0,92,0,7,0,70,8,7,0,71,8,7,0,72,8,7,0,73,8,7,0,-107,2,7,0,-67,1,7, +0,-120,7,7,0,74,8,0,0,75,8,0,0,76,8,12,0,-4,2,61,1,8,0,7,0,-31,1,7,0,-97,7,7, +0,-96,7,9,0,2,0,2,0,77,8,2,0,78,8,2,0,79,8,2,0,80,8,62,1,18,0,62,1,0,0,62, +1,1,0,62,1,81,8,0,0,17,0,61,1,82,8,2,0,18,0,2,0,20,0,2,0,83,8,2,0,84,8,2, +0,85,8,2,0,86,8,4,0,43,0,7,0,87,8,7,0,88,8,4,0,89,8,4,0,90,8,62,1,91,8,63, +1,92,8,64,1,32,0,64,1,0,0,64,1,1,0,64,1,93,8,0,0,17,0,0,0,94,8,2,0,18,0,2, +0,20,0,2,0,-14,6,2,0,20,7,2,0,95,8,2,0,-119,0,2,0,84,8,2,0,-25,6,12,0,-127,7,12, +0,96,8,27,0,-9,5,9,0,97,8,7,0,87,8,7,0,88,8,7,0,-5,1,7,0,98,8,2,0,99,8,2, +0,100,8,7,0,101,8,7,0,102,8,2,0,103,8,2,0,104,8,24,0,105,8,24,0,106,8,24,0,107,8,65, +1,-103,0,66,1,108,8,63,1,6,0,63,1,0,0,63,1,1,0,64,1,109,8,64,1,110,8,62,1,111,8,62, +1,91,8,57,0,16,0,27,0,31,0,12,0,112,8,12,0,113,8,61,1,114,8,12,0,115,8,4,0,18,0,4, +0,116,8,4,0,117,8,4,0,118,8,12,0,119,8,66,1,120,8,62,1,121,8,62,1,122,8,9,0,123,8,9, +0,124,8,4,0,125,8,67,1,6,0,4,0,-128,0,4,0,-126,0,4,0,-25,6,0,0,126,8,0,0,127,8,2, +0,37,0,68,1,16,0,2,0,-86,6,2,0,-85,6,2,0,-128,8,2,0,-74,7,2,0,-127,8,2,0,68,0,7, +0,-108,2,7,0,-126,8,7,0,-125,8,2,0,34,1,0,0,-124,8,0,0,42,4,2,0,-123,8,2,0,37,0,4, +0,-122,8,4,0,-121,8,69,1,9,0,7,0,-120,8,7,0,-119,8,7,0,-60,7,7,0,112,0,7,0,-118,8,7, +0,71,5,2,0,-117,8,0,0,-116,8,0,0,37,0,70,1,4,0,7,0,-115,8,7,0,-114,8,2,0,-117,8,2, +0,37,0,71,1,3,0,7,0,-113,8,7,0,-112,8,7,0,15,0,72,1,7,0,0,0,-68,1,2,0,109,4,2, +0,110,4,2,0,111,4,2,0,62,4,4,0,-126,0,4,0,-97,3,73,1,7,0,7,0,-111,8,7,0,-110,8,7, +0,-109,8,7,0,4,2,7,0,-108,8,7,0,-107,8,7,0,-106,8,74,1,4,0,2,0,-105,8,2,0,-104,8,2, +0,-103,8,2,0,-102,8,75,1,2,0,7,0,5,0,7,0,6,0,76,1,2,0,0,0,-87,0,0,0,-101,8,77, +1,1,0,0,0,17,0,78,1,10,0,0,0,-100,8,0,0,-99,8,0,0,-98,8,0,0,-97,8,2,0,-128,8,2, +0,-96,8,7,0,-95,8,7,0,-94,8,7,0,-93,8,7,0,-67,1,79,1,2,0,9,0,-92,8,9,0,-91,8,80, +1,11,0,0,0,111,4,0,0,18,0,0,0,-117,8,0,0,112,0,0,0,-90,8,0,0,109,0,0,0,-74,0,7, +0,-89,8,7,0,-88,8,7,0,-87,8,7,0,-86,8,81,1,8,0,7,0,97,7,7,0,-127,0,7,0,42,4,7, +0,72,2,7,0,-85,8,7,0,-49,0,7,0,-84,8,4,0,18,0,82,1,4,0,2,0,-83,8,2,0,-82,8,2, +0,-81,8,2,0,37,0,83,1,1,0,0,0,17,0,84,1,4,0,7,0,5,0,7,0,6,0,2,0,20,0,2, +0,-80,8,85,1,10,0,2,0,-120,3,2,0,20,0,7,0,-17,3,7,0,-79,8,7,0,-78,8,7,0,-77,8,7, +0,-76,8,84,1,-75,8,84,1,-74,8,84,1,-73,8,60,0,9,0,4,0,20,0,4,0,64,0,24,0,-72,8,24, +0,-71,8,85,1,-70,8,7,0,-69,8,7,0,-68,8,7,0,-67,8,7,0,-66,8,86,1,4,0,46,0,-114,2,7, +0,-65,8,7,0,92,1,7,0,37,0,-87,0,13,0,27,0,31,0,2,0,20,0,2,0,72,5,4,0,109,0,7, +0,-64,8,7,0,1,2,7,0,-63,8,7,0,-62,8,7,0,92,1,2,0,47,1,2,0,37,0,50,0,77,1,86, +1,-61,8,87,1,10,0,4,0,18,0,4,0,-127,0,4,0,20,0,4,0,70,3,4,0,-60,8,4,0,-59,8,4, +0,-58,8,0,0,95,0,0,0,17,0,9,0,2,0,84,0,6,0,87,1,-57,8,4,0,-56,8,4,0,-55,8,4, +0,-54,8,4,0,37,0,9,0,-53,8,88,1,5,0,7,0,66,2,7,0,-74,2,7,0,-39,1,2,0,-52,8,2, +0,37,0,89,1,5,0,7,0,66,2,7,0,-51,8,7,0,-50,8,7,0,-49,8,7,0,-74,2,90,1,7,0,4, +0,-48,8,4,0,-47,8,4,0,-46,8,7,0,-45,8,7,0,-44,8,7,0,-43,8,7,0,-42,8,91,1,26,0,32, +0,-41,8,89,1,66,3,89,1,-40,8,88,1,-39,8,89,1,83,7,7,0,-38,8,7,0,-37,8,7,0,-36,8,7, +0,-35,8,7,0,-44,8,7,0,-43,8,7,0,-74,2,7,0,-97,2,7,0,-34,8,7,0,-33,8,7,0,109,0,7, +0,-32,8,4,0,-48,8,4,0,-31,8,4,0,37,0,4,0,81,0,4,0,-30,8,2,0,20,0,2,0,-29,8,2, +0,-28,8,2,0,100,3,92,1,112,0,27,0,31,0,4,0,20,0,2,0,18,0,2,0,55,8,2,0,-27,8,2, +0,-26,8,2,0,-25,8,2,0,-24,8,2,0,-23,8,2,0,-22,8,2,0,-21,8,2,0,-20,8,2,0,-19,8,2, +0,-18,8,2,0,-17,8,2,0,-16,8,2,0,-15,8,2,0,-14,8,2,0,-13,8,2,0,-47,1,2,0,76,7,2, +0,51,7,2,0,-12,8,2,0,-11,8,2,0,98,3,2,0,99,3,2,0,-10,8,2,0,-9,8,2,0,-8,8,2, +0,-7,8,2,0,-6,8,2,0,-5,8,7,0,-4,8,7,0,-3,8,7,0,-2,8,2,0,-1,8,2,0,0,9,7, +0,1,9,7,0,2,9,7,0,3,9,7,0,58,7,7,0,92,0,7,0,-97,2,7,0,64,7,7,0,4,9,7, +0,5,9,7,0,6,9,7,0,7,9,7,0,57,0,4,0,59,7,4,0,57,7,4,0,8,9,7,0,60,7,7, +0,61,7,7,0,62,7,7,0,9,9,7,0,10,9,7,0,11,9,7,0,12,9,7,0,13,9,7,0,14,9,7, +0,15,9,7,0,16,9,7,0,21,3,7,0,109,0,7,0,17,9,7,0,18,9,7,0,19,9,7,0,20,9,7, +0,21,9,7,0,22,9,7,0,108,2,7,0,23,9,7,0,24,9,4,0,25,9,4,0,26,9,7,0,27,9,7, +0,28,9,7,0,29,9,7,0,30,9,7,0,31,9,7,0,32,9,7,0,33,9,7,0,34,9,7,0,94,3,7, +0,92,3,7,0,93,3,7,0,35,9,7,0,36,9,7,0,37,9,7,0,38,9,7,0,39,9,7,0,40,9,7, +0,41,9,7,0,42,9,7,0,43,9,7,0,28,3,7,0,44,9,7,0,45,9,7,0,46,9,7,0,47,9,7, +0,48,9,7,0,49,9,7,0,50,9,0,0,51,9,63,0,55,3,63,0,52,9,32,0,53,9,32,0,54,9,36, +0,79,0,-108,0,53,3,-108,0,55,9,-120,0,37,0,-120,0,0,0,-120,0,1,0,92,1,56,9,91,1,-121,3,90, +1,-14,7,93,1,57,9,94,1,58,9,94,1,59,9,12,0,60,9,12,0,61,9,-107,0,54,3,32,0,62,9,32, +0,63,9,32,0,64,9,12,0,65,9,12,0,66,9,7,0,-45,0,7,0,83,4,4,0,110,2,4,0,20,0,4, +0,59,7,4,0,67,9,4,0,68,9,4,0,69,9,4,0,57,0,2,0,-38,0,2,0,70,9,2,0,71,9,2, +0,72,9,2,0,47,3,2,0,73,9,0,0,74,9,2,0,75,9,2,0,76,9,2,0,77,9,9,0,78,9,125, +0,-76,3,123,0,34,0,95,1,79,9,7,0,-106,3,7,0,80,9,7,0,81,9,7,0,-14,3,7,0,82,9,7, +0,31,3,7,0,21,3,7,0,83,9,7,0,3,2,7,0,84,9,7,0,85,9,7,0,86,9,7,0,87,9,7, +0,88,9,7,0,89,9,7,0,-105,3,7,0,90,9,7,0,91,9,7,0,92,9,7,0,-104,3,7,0,-108,3,7, +0,-107,3,4,0,93,9,4,0,93,0,4,0,94,9,4,0,95,9,2,0,96,9,2,0,97,9,2,0,98,9,2, +0,99,9,2,0,100,9,2,0,37,0,4,0,70,0,124,0,8,0,95,1,101,9,7,0,102,9,7,0,103,9,7, +0,-94,1,7,0,104,9,4,0,93,0,2,0,105,9,2,0,106,9,96,1,4,0,7,0,5,0,7,0,6,0,7, +0,7,0,7,0,107,9,97,1,6,0,97,1,0,0,97,1,1,0,96,1,108,9,4,0,109,9,2,0,110,9,2, +0,20,0,98,1,5,0,98,1,0,0,98,1,1,0,12,0,111,9,4,0,112,9,4,0,20,0,99,1,9,0,99, +1,0,0,99,1,1,0,12,0,-128,0,98,1,113,9,4,0,20,0,2,0,110,9,2,0,114,9,7,0,94,0,0, +0,115,9,-70,0,5,0,12,0,125,4,4,0,20,0,2,0,116,9,2,0,117,9,9,0,118,9,69,78,68,66,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; +int DNAlen64= sizeof(DNAstr64); diff --git a/Extras/Serialize/BlenderSerialize/dna249.cpp b/Extras/Serialize/BlenderSerialize/dna249.cpp new file mode 100644 index 0000000..97881b4 --- /dev/null +++ b/Extras/Serialize/BlenderSerialize/dna249.cpp @@ -0,0 +1,1411 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +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. +*/ +unsigned char DNAstr[]= { +83,68,78,65,78,65,77,69,119,9,0,0,42,110,101,120,116,0,42,112,114,101,118,0,42,100,97,116,97,0,42,102,105, +114,115,116,0,42,108,97,115,116,0,120,0,121,0,122,0,119,0,120,109,105,110,0,120,109,97,120,0,121,109,105,110, +0,121,109,97,120,0,42,112,111,105,110,116,101,114,0,103,114,111,117,112,0,118,97,108,0,118,97,108,50,0,110,97, +109,101,91,51,50,93,0,116,121,112,101,0,115,117,98,116,121,112,101,0,102,108,97,103,0,115,97,118,101,100,0,100, +97,116,97,0,108,101,110,0,116,111,116,97,108,108,101,110,0,42,110,101,119,105,100,0,42,108,105,98,0,110,97,109, +101,91,50,52,93,0,117,115,0,105,99,111,110,95,105,100,0,42,112,114,111,112,101,114,116,105,101,115,0,105,100,0, +42,105,100,98,108,111,99,107,0,42,102,105,108,101,100,97,116,97,0,110,97,109,101,91,50,52,48,93,0,102,105,108, +101,110,97,109,101,91,50,52,48,93,0,116,111,116,0,112,97,100,0,42,112,97,114,101,110,116,0,119,91,50,93,0, +104,91,50,93,0,99,104,97,110,103,101,100,91,50,93,0,112,97,100,48,0,112,97,100,49,0,42,114,101,99,116,91, +50,93,0,42,111,98,0,98,108,111,99,107,116,121,112,101,0,97,100,114,99,111,100,101,0,110,97,109,101,91,49,50, +56,93,0,42,98,112,0,42,98,101,122,116,0,109,97,120,114,99,116,0,116,111,116,114,99,116,0,118,97,114,116,121, +112,101,0,116,111,116,118,101,114,116,0,105,112,111,0,101,120,116,114,97,112,0,114,116,0,98,105,116,109,97,115,107, +0,115,108,105,100,101,95,109,105,110,0,115,108,105,100,101,95,109,97,120,0,99,117,114,118,97,108,0,42,100,114,105, +118,101,114,0,99,117,114,118,101,0,99,117,114,0,115,104,111,119,107,101,121,0,109,117,116,101,105,112,111,0,112,111, +115,0,114,101,108,97,116,105,118,101,0,116,111,116,101,108,101,109,0,112,97,100,50,0,42,119,101,105,103,104,116,115, +0,118,103,114,111,117,112,91,51,50,93,0,115,108,105,100,101,114,109,105,110,0,115,108,105,100,101,114,109,97,120,0, +42,114,101,102,107,101,121,0,101,108,101,109,115,116,114,91,51,50,93,0,101,108,101,109,115,105,122,101,0,98,108,111, +99,107,0,42,105,112,111,0,42,102,114,111,109,0,116,111,116,107,101,121,0,115,108,117,114,112,104,0,42,42,115,99, +114,105,112,116,115,0,42,102,108,97,103,0,97,99,116,115,99,114,105,112,116,0,116,111,116,115,99,114,105,112,116,0, +42,108,105,110,101,0,42,102,111,114,109,97,116,0,98,108,101,110,0,108,105,110,101,110,111,0,115,116,97,114,116,0, +101,110,100,0,102,108,97,103,115,0,99,111,108,111,114,91,52,93,0,112,97,100,91,52,93,0,42,110,97,109,101,0, +110,108,105,110,101,115,0,108,105,110,101,115,0,42,99,117,114,108,0,42,115,101,108,108,0,99,117,114,99,0,115,101, +108,99,0,109,97,114,107,101,114,115,0,42,117,110,100,111,95,98,117,102,0,117,110,100,111,95,112,111,115,0,117,110, +100,111,95,108,101,110,0,42,99,111,109,112,105,108,101,100,0,109,116,105,109,101,0,115,105,122,101,0,115,101,101,107, +0,112,97,115,115,101,112,97,114,116,97,108,112,104,97,0,97,110,103,108,101,0,99,108,105,112,115,116,97,0,99,108, +105,112,101,110,100,0,108,101,110,115,0,111,114,116,104,111,95,115,99,97,108,101,0,100,114,97,119,115,105,122,101,0, +115,104,105,102,116,120,0,115,104,105,102,116,121,0,89,70,95,100,111,102,100,105,115,116,0,89,70,95,97,112,101,114, +116,117,114,101,0,89,70,95,98,107,104,116,121,112,101,0,89,70,95,98,107,104,98,105,97,115,0,89,70,95,98,107, +104,114,111,116,0,115,99,114,105,112,116,108,105,110,107,0,42,100,111,102,95,111,98,0,102,114,97,109,101,110,114,0, +102,114,97,109,101,115,0,111,102,102,115,101,116,0,115,102,114,97,0,102,105,101,95,105,109,97,0,99,121,99,108,0, +111,107,0,109,117,108,116,105,95,105,110,100,101,120,0,108,97,121,101,114,0,112,97,115,115,0,109,101,110,117,110,114, +0,105,98,117,102,115,0,42,103,112,117,116,101,120,116,117,114,101,0,42,97,110,105,109,0,42,114,114,0,115,111,117, +114,99,101,0,108,97,115,116,102,114,97,109,101,0,116,112,97,103,101,102,108,97,103,0,116,111,116,98,105,110,100,0, +120,114,101,112,0,121,114,101,112,0,116,119,115,116,97,0,116,119,101,110,100,0,98,105,110,100,99,111,100,101,0,42, +114,101,112,98,105,110,100,0,42,112,97,99,107,101,100,102,105,108,101,0,42,112,114,101,118,105,101,119,0,108,97,115, +116,117,112,100,97,116,101,0,108,97,115,116,117,115,101,100,0,97,110,105,109,115,112,101,101,100,0,103,101,110,95,120, +0,103,101,110,95,121,0,103,101,110,95,116,121,112,101,0,97,115,112,120,0,97,115,112,121,0,42,118,110,111,100,101, +0,116,101,120,99,111,0,109,97,112,116,111,0,109,97,112,116,111,110,101,103,0,98,108,101,110,100,116,121,112,101,0, +42,111,98,106,101,99,116,0,42,116,101,120,0,117,118,110,97,109,101,91,51,50,93,0,112,114,111,106,120,0,112,114, +111,106,121,0,112,114,111,106,122,0,109,97,112,112,105,110,103,0,111,102,115,91,51,93,0,115,105,122,101,91,51,93, +0,116,101,120,102,108,97,103,0,99,111,108,111,114,109,111,100,101,108,0,112,109,97,112,116,111,0,112,109,97,112,116, +111,110,101,103,0,110,111,114,109,97,112,115,112,97,99,101,0,119,104,105,99,104,95,111,117,116,112,117,116,0,112,97, +100,91,50,93,0,114,0,103,0,98,0,107,0,100,101,102,95,118,97,114,0,99,111,108,102,97,99,0,110,111,114,102, +97,99,0,118,97,114,102,97,99,0,100,105,115,112,102,97,99,0,119,97,114,112,102,97,99,0,110,97,109,101,91,49, +54,48,93,0,42,104,97,110,100,108,101,0,42,112,110,97,109,101,0,42,115,116,110,97,109,101,115,0,115,116,121,112, +101,115,0,118,97,114,115,0,42,118,97,114,115,116,114,0,42,114,101,115,117,108,116,0,42,99,102,114,97,0,100,97, +116,97,91,51,50,93,0,40,42,100,111,105,116,41,40,41,0,40,42,105,110,115,116,97,110,99,101,95,105,110,105,116, +41,40,41,0,40,42,99,97,108,108,98,97,99,107,41,40,41,0,118,101,114,115,105,111,110,0,97,0,105,112,111,116, +121,112,101,0,42,105,109,97,0,42,99,117,98,101,91,54,93,0,105,109,97,116,91,52,93,91,52,93,0,111,98,105, +109,97,116,91,51,93,91,51,93,0,115,116,121,112,101,0,118,105,101,119,115,99,97,108,101,0,110,111,116,108,97,121, +0,99,117,98,101,114,101,115,0,100,101,112,116,104,0,114,101,99,97,108,99,0,108,97,115,116,115,105,122,101,0,110, +111,105,115,101,115,105,122,101,0,116,117,114,98,117,108,0,98,114,105,103,104,116,0,99,111,110,116,114,97,115,116,0, +114,102,97,99,0,103,102,97,99,0,98,102,97,99,0,102,105,108,116,101,114,115,105,122,101,0,109,103,95,72,0,109, +103,95,108,97,99,117,110,97,114,105,116,121,0,109,103,95,111,99,116,97,118,101,115,0,109,103,95,111,102,102,115,101, +116,0,109,103,95,103,97,105,110,0,100,105,115,116,95,97,109,111,117,110,116,0,110,115,95,111,117,116,115,99,97,108, +101,0,118,110,95,119,49,0,118,110,95,119,50,0,118,110,95,119,51,0,118,110,95,119,52,0,118,110,95,109,101,120, +112,0,118,110,95,100,105,115,116,109,0,118,110,95,99,111,108,116,121,112,101,0,110,111,105,115,101,100,101,112,116,104, +0,110,111,105,115,101,116,121,112,101,0,110,111,105,115,101,98,97,115,105,115,0,110,111,105,115,101,98,97,115,105,115, +50,0,105,109,97,102,108,97,103,0,99,114,111,112,120,109,105,110,0,99,114,111,112,121,109,105,110,0,99,114,111,112, +120,109,97,120,0,99,114,111,112,121,109,97,120,0,120,114,101,112,101,97,116,0,121,114,101,112,101,97,116,0,101,120, +116,101,110,100,0,99,104,101,99,107,101,114,100,105,115,116,0,110,97,98,108,97,0,105,117,115,101,114,0,42,110,111, +100,101,116,114,101,101,0,42,112,108,117,103,105,110,0,42,99,111,98,97,0,42,101,110,118,0,117,115,101,95,110,111, +100,101,115,0,112,97,100,91,55,93,0,108,111,99,91,51,93,0,114,111,116,91,51,93,0,109,97,116,91,52,93,91, +52,93,0,109,105,110,91,51,93,0,109,97,120,91,51,93,0,112,97,100,51,0,109,111,100,101,0,116,111,116,101,120, +0,115,104,100,119,114,0,115,104,100,119,103,0,115,104,100,119,98,0,115,104,100,119,112,97,100,0,101,110,101,114,103, +121,0,100,105,115,116,0,115,112,111,116,115,105,122,101,0,115,112,111,116,98,108,101,110,100,0,104,97,105,110,116,0, +97,116,116,49,0,97,116,116,50,0,42,99,117,114,102,97,108,108,111,102,102,0,102,97,108,108,111,102,102,95,116,121, +112,101,0,115,104,97,100,115,112,111,116,115,105,122,101,0,98,105,97,115,0,115,111,102,116,0,98,117,102,115,105,122, +101,0,115,97,109,112,0,98,117,102,102,101,114,115,0,102,105,108,116,101,114,116,121,112,101,0,98,117,102,102,108,97, +103,0,98,117,102,116,121,112,101,0,114,97,121,95,115,97,109,112,0,114,97,121,95,115,97,109,112,121,0,114,97,121, +95,115,97,109,112,122,0,114,97,121,95,115,97,109,112,95,116,121,112,101,0,97,114,101,97,95,115,104,97,112,101,0, +97,114,101,97,95,115,105,122,101,0,97,114,101,97,95,115,105,122,101,121,0,97,114,101,97,95,115,105,122,101,122,0, +97,100,97,112,116,95,116,104,114,101,115,104,0,114,97,121,95,115,97,109,112,95,109,101,116,104,111,100,0,116,101,120, +97,99,116,0,115,104,97,100,104,97,108,111,115,116,101,112,0,115,117,110,95,101,102,102,101,99,116,95,116,121,112,101, +0,115,107,121,98,108,101,110,100,116,121,112,101,0,104,111,114,105,122,111,110,95,98,114,105,103,104,116,110,101,115,115, +0,115,112,114,101,97,100,0,115,117,110,95,98,114,105,103,104,116,110,101,115,115,0,115,117,110,95,115,105,122,101,0, +98,97,99,107,115,99,97,116,116,101,114,101,100,95,108,105,103,104,116,0,115,117,110,95,105,110,116,101,110,115,105,116, +121,0,97,116,109,95,116,117,114,98,105,100,105,116,121,0,97,116,109,95,105,110,115,99,97,116,116,101,114,105,110,103, +95,102,97,99,116,111,114,0,97,116,109,95,101,120,116,105,110,99,116,105,111,110,95,102,97,99,116,111,114,0,97,116, +109,95,100,105,115,116,97,110,99,101,95,102,97,99,116,111,114,0,115,107,121,98,108,101,110,100,102,97,99,0,115,107, +121,95,101,120,112,111,115,117,114,101,0,115,107,121,95,99,111,108,111,114,115,112,97,99,101,0,112,97,100,52,0,89, +70,95,110,117,109,112,104,111,116,111,110,115,0,89,70,95,110,117,109,115,101,97,114,99,104,0,89,70,95,112,104,100, +101,112,116,104,0,89,70,95,117,115,101,113,109,99,0,89,70,95,98,117,102,115,105,122,101,0,89,70,95,112,97,100, +0,89,70,95,99,97,117,115,116,105,99,98,108,117,114,0,89,70,95,108,116,114,97,100,105,117,115,0,89,70,95,103, +108,111,119,105,110,116,0,89,70,95,103,108,111,119,111,102,115,0,89,70,95,103,108,111,119,116,121,112,101,0,89,70, +95,112,97,100,50,0,42,109,116,101,120,91,49,56,93,0,115,112,101,99,114,0,115,112,101,99,103,0,115,112,101,99, +98,0,109,105,114,114,0,109,105,114,103,0,109,105,114,98,0,97,109,98,114,0,97,109,98,98,0,97,109,98,103,0, +97,109,98,0,101,109,105,116,0,97,110,103,0,115,112,101,99,116,114,97,0,114,97,121,95,109,105,114,114,111,114,0, +97,108,112,104,97,0,114,101,102,0,115,112,101,99,0,122,111,102,102,115,0,97,100,100,0,116,114,97,110,115,108,117, +99,101,110,99,121,0,102,114,101,115,110,101,108,95,109,105,114,0,102,114,101,115,110,101,108,95,109,105,114,95,105,0, +102,114,101,115,110,101,108,95,116,114,97,0,102,114,101,115,110,101,108,95,116,114,97,95,105,0,102,105,108,116,101,114, +0,116,120,95,108,105,109,105,116,0,116,120,95,102,97,108,108,111,102,102,0,114,97,121,95,100,101,112,116,104,0,114, +97,121,95,100,101,112,116,104,95,116,114,97,0,104,97,114,0,115,101,101,100,49,0,115,101,101,100,50,0,103,108,111, +115,115,95,109,105,114,0,103,108,111,115,115,95,116,114,97,0,115,97,109,112,95,103,108,111,115,115,95,109,105,114,0, +115,97,109,112,95,103,108,111,115,115,95,116,114,97,0,97,100,97,112,116,95,116,104,114,101,115,104,95,109,105,114,0, +97,100,97,112,116,95,116,104,114,101,115,104,95,116,114,97,0,97,110,105,115,111,95,103,108,111,115,115,95,109,105,114, +0,100,105,115,116,95,109,105,114,0,102,97,100,101,116,111,95,109,105,114,0,115,104,97,100,101,95,102,108,97,103,0, +109,111,100,101,95,108,0,102,108,97,114,101,99,0,115,116,97,114,99,0,108,105,110,101,99,0,114,105,110,103,99,0, +104,97,115,105,122,101,0,102,108,97,114,101,115,105,122,101,0,115,117,98,115,105,122,101,0,102,108,97,114,101,98,111, +111,115,116,0,115,116,114,97,110,100,95,115,116,97,0,115,116,114,97,110,100,95,101,110,100,0,115,116,114,97,110,100, +95,101,97,115,101,0,115,116,114,97,110,100,95,115,117,114,102,110,111,114,0,115,116,114,97,110,100,95,109,105,110,0, +115,116,114,97,110,100,95,119,105,100,116,104,102,97,100,101,0,115,116,114,97,110,100,95,117,118,110,97,109,101,91,51, +50,93,0,115,98,105,97,115,0,108,98,105,97,115,0,115,104,97,100,95,97,108,112,104,97,0,115,101,112,116,101,120, +0,114,103,98,115,101,108,0,112,114,95,116,121,112,101,0,112,114,95,98,97,99,107,0,112,114,95,108,97,109,112,0, +109,108,95,102,108,97,103,0,100,105,102,102,95,115,104,97,100,101,114,0,115,112,101,99,95,115,104,97,100,101,114,0, +114,111,117,103,104,110,101,115,115,0,114,101,102,114,97,99,0,112,97,114,97,109,91,52,93,0,114,109,115,0,100,97, +114,107,110,101,115,115,0,42,114,97,109,112,95,99,111,108,0,42,114,97,109,112,95,115,112,101,99,0,114,97,109,112, +105,110,95,99,111,108,0,114,97,109,112,105,110,95,115,112,101,99,0,114,97,109,112,98,108,101,110,100,95,99,111,108, +0,114,97,109,112,98,108,101,110,100,95,115,112,101,99,0,114,97,109,112,95,115,104,111,119,0,114,97,109,112,102,97, +99,95,99,111,108,0,114,97,109,112,102,97,99,95,115,112,101,99,0,42,103,114,111,117,112,0,102,114,105,99,116,105, +111,110,0,102,104,0,114,101,102,108,101,99,116,0,102,104,100,105,115,116,0,120,121,102,114,105,99,116,0,100,121,110, +97,109,111,100,101,0,115,115,115,95,114,97,100,105,117,115,91,51,93,0,115,115,115,95,99,111,108,91,51,93,0,115, +115,115,95,101,114,114,111,114,0,115,115,115,95,115,99,97,108,101,0,115,115,115,95,105,111,114,0,115,115,115,95,99, +111,108,102,97,99,0,115,115,115,95,116,101,120,102,97,99,0,115,115,115,95,102,114,111,110,116,0,115,115,115,95,98, +97,99,107,0,115,115,115,95,102,108,97,103,0,115,115,115,95,112,114,101,115,101,116,0,89,70,95,97,114,0,89,70, +95,97,103,0,89,70,95,97,98,0,89,70,95,100,115,99,97,108,101,0,89,70,95,100,112,119,114,0,89,70,95,100, +115,109,112,0,89,70,95,112,114,101,115,101,116,0,89,70,95,100,106,105,116,0,103,112,117,109,97,116,101,114,105,97, +108,0,110,97,109,101,91,50,53,54,93,0,115,99,97,108,101,0,42,98,98,0,105,49,0,106,49,0,107,49,0,105, +50,0,106,50,0,107,50,0,115,101,108,99,111,108,49,0,115,101,108,99,111,108,50,0,113,117,97,116,91,52,93,0, +101,120,112,120,0,101,120,112,121,0,101,120,112,122,0,114,97,100,0,114,97,100,50,0,115,0,42,109,97,116,0,42, +105,109,97,116,0,101,108,101,109,115,0,100,105,115,112,0,42,42,109,97,116,0,116,111,116,99,111,108,0,119,105,114, +101,115,105,122,101,0,114,101,110,100,101,114,115,105,122,101,0,116,104,114,101,115,104,0,118,101,99,91,51,93,91,51, +93,0,97,108,102,97,0,119,101,105,103,104,116,0,114,97,100,105,117,115,0,104,49,0,104,50,0,102,49,0,102,50, +0,102,51,0,104,105,100,101,0,118,101,99,91,52,93,0,109,97,116,95,110,114,0,112,110,116,115,117,0,112,110,116, +115,118,0,114,101,115,111,108,117,0,114,101,115,111,108,118,0,111,114,100,101,114,117,0,111,114,100,101,114,118,0,102, +108,97,103,117,0,102,108,97,103,118,0,42,107,110,111,116,115,117,0,42,107,110,111,116,115,118,0,116,105,108,116,95, +105,110,116,101,114,112,0,114,97,100,105,117,115,95,105,110,116,101,114,112,0,99,104,97,114,105,100,120,0,107,101,114, +110,0,104,0,110,117,114,98,0,42,98,101,118,111,98,106,0,42,116,97,112,101,114,111,98,106,0,42,116,101,120,116, +111,110,99,117,114,118,101,0,42,112,97,116,104,0,42,107,101,121,0,98,101,118,0,112,97,116,104,108,101,110,0,98, +101,118,114,101,115,111,108,0,119,105,100,116,104,0,101,120,116,49,0,101,120,116,50,0,114,101,115,111,108,117,95,114, +101,110,0,114,101,115,111,108,118,95,114,101,110,0,115,112,97,99,101,109,111,100,101,0,115,112,97,99,105,110,103,0, +108,105,110,101,100,105,115,116,0,115,104,101,97,114,0,102,115,105,122,101,0,119,111,114,100,115,112,97,99,101,0,117, +108,112,111,115,0,117,108,104,101,105,103,104,116,0,120,111,102,0,121,111,102,0,108,105,110,101,119,105,100,116,104,0, +42,115,116,114,0,102,97,109,105,108,121,91,50,52,93,0,42,118,102,111,110,116,0,42,118,102,111,110,116,98,0,42, +118,102,111,110,116,105,0,42,118,102,111,110,116,98,105,0,115,101,112,99,104,97,114,0,116,111,116,98,111,120,0,97, +99,116,98,111,120,0,42,116,98,0,115,101,108,115,116,97,114,116,0,115,101,108,101,110,100,0,42,115,116,114,105,110, +102,111,0,99,117,114,105,110,102,111,0,101,102,102,101,99,116,0,42,109,102,97,99,101,0,42,109,116,102,97,99,101, +0,42,116,102,97,99,101,0,42,109,118,101,114,116,0,42,109,101,100,103,101,0,42,100,118,101,114,116,0,42,109,99, +111,108,0,42,109,115,116,105,99,107,121,0,42,116,101,120,99,111,109,101,115,104,0,42,109,115,101,108,101,99,116,0, +118,100,97,116,97,0,101,100,97,116,97,0,102,100,97,116,97,0,116,111,116,101,100,103,101,0,116,111,116,102,97,99, +101,0,116,111,116,115,101,108,101,99,116,0,97,99,116,95,102,97,99,101,0,99,117,98,101,109,97,112,115,105,122,101, +0,115,109,111,111,116,104,114,101,115,104,0,115,117,98,100,105,118,0,115,117,98,100,105,118,114,0,115,117,98,115,117, +114,102,116,121,112,101,0,42,109,114,0,42,112,118,0,42,116,112,97,103,101,0,117,118,91,52,93,91,50,93,0,99, +111,108,91,52,93,0,116,114,97,110,115,112,0,116,105,108,101,0,117,110,119,114,97,112,0,118,49,0,118,50,0,118, +51,0,118,52,0,101,100,99,111,100,101,0,99,114,101,97,115,101,0,98,119,101,105,103,104,116,0,100,101,102,95,110, +114,0,42,100,119,0,116,111,116,119,101,105,103,104,116,0,99,111,91,51,93,0,110,111,91,51,93,0,112,97,100,91, +51,93,0,117,118,91,50,93,0,99,111,91,50,93,0,105,110,100,101,120,0,102,0,105,0,115,91,50,53,54,93,0, +118,91,52,93,0,109,105,100,0,118,91,50,93,0,42,102,97,99,101,115,0,42,99,111,108,102,97,99,101,115,0,42, +101,100,103,101,115,0,42,101,100,103,101,95,98,111,117,110,100,97,114,121,95,115,116,97,116,101,115,0,42,118,101,114, +116,95,101,100,103,101,95,109,97,112,0,42,118,101,114,116,95,102,97,99,101,95,109,97,112,0,42,109,97,112,95,109, +101,109,0,42,118,101,114,116,115,0,108,101,118,101,108,115,0,108,101,118,101,108,95,99,111,117,110,116,0,99,117,114, +114,101,110,116,0,110,101,119,108,118,108,0,101,100,103,101,108,118,108,0,112,105,110,108,118,108,0,114,101,110,100,101, +114,108,118,108,0,117,115,101,95,99,111,108,0,42,101,100,103,101,95,102,108,97,103,115,0,42,101,100,103,101,95,99, +114,101,97,115,101,115,0,42,118,101,114,116,95,109,97,112,0,42,101,100,103,101,95,109,97,112,0,42,111,108,100,95, +102,97,99,101,115,0,42,111,108,100,95,101,100,103,101,115,0,42,101,114,114,111,114,0,109,111,100,105,102,105,101,114, +0,115,117,98,100,105,118,84,121,112,101,0,114,101,110,100,101,114,76,101,118,101,108,115,0,42,101,109,67,97,99,104, +101,0,42,109,67,97,99,104,101,0,100,101,102,97,120,105,115,0,112,97,100,91,54,93,0,108,101,110,103,116,104,0, +114,97,110,100,111,109,105,122,101,0,115,101,101,100,0,42,111,98,95,97,114,109,0,42,115,116,97,114,116,95,99,97, +112,0,42,101,110,100,95,99,97,112,0,42,99,117,114,118,101,95,111,98,0,42,111,102,102,115,101,116,95,111,98,0, +111,102,102,115,101,116,91,51,93,0,115,99,97,108,101,91,51,93,0,109,101,114,103,101,95,100,105,115,116,0,102,105, +116,95,116,121,112,101,0,111,102,102,115,101,116,95,116,121,112,101,0,99,111,117,110,116,0,97,120,105,115,0,116,111, +108,101,114,97,110,99,101,0,42,109,105,114,114,111,114,95,111,98,0,115,112,108,105,116,95,97,110,103,108,101,0,118, +97,108,117,101,0,114,101,115,0,118,97,108,95,102,108,97,103,115,0,108,105,109,95,102,108,97,103,115,0,101,95,102, +108,97,103,115,0,98,101,118,101,108,95,97,110,103,108,101,0,100,101,102,103,114,112,95,110,97,109,101,91,51,50,93, +0,42,116,101,120,116,117,114,101,0,115,116,114,101,110,103,116,104,0,100,105,114,101,99,116,105,111,110,0,109,105,100, +108,101,118,101,108,0,116,101,120,109,97,112,112,105,110,103,0,42,109,97,112,95,111,98,106,101,99,116,0,117,118,108, +97,121,101,114,95,110,97,109,101,91,51,50,93,0,117,118,108,97,121,101,114,95,116,109,112,0,42,112,114,111,106,101, +99,116,111,114,115,91,49,48,93,0,42,105,109,97,103,101,0,110,117,109,95,112,114,111,106,101,99,116,111,114,115,0, +97,115,112,101,99,116,120,0,97,115,112,101,99,116,121,0,112,101,114,99,101,110,116,0,102,97,99,101,67,111,117,110, +116,0,102,97,99,0,114,101,112,101,97,116,0,42,111,98,106,101,99,116,99,101,110,116,101,114,0,115,116,97,114,116, +120,0,115,116,97,114,116,121,0,104,101,105,103,104,116,0,110,97,114,114,111,119,0,115,112,101,101,100,0,100,97,109, +112,0,102,97,108,108,111,102,102,0,116,105,109,101,111,102,102,115,0,108,105,102,101,116,105,109,101,0,100,101,102,111, +114,109,102,108,97,103,0,109,117,108,116,105,0,42,112,114,101,118,67,111,115,0,112,97,114,101,110,116,105,110,118,91, +52,93,91,52,93,0,99,101,110,116,91,51,93,0,42,105,110,100,101,120,97,114,0,116,111,116,105,110,100,101,120,0, +102,111,114,99,101,0,42,99,108,111,116,104,79,98,106,101,99,116,0,42,115,105,109,95,112,97,114,109,115,0,42,99, +111,108,108,95,112,97,114,109,115,0,42,112,111,105,110,116,95,99,97,99,104,101,0,42,120,0,42,120,110,101,119,0, +42,120,111,108,100,0,42,99,117,114,114,101,110,116,95,120,110,101,119,0,42,99,117,114,114,101,110,116,95,120,0,42, +99,117,114,114,101,110,116,95,118,0,42,109,102,97,99,101,115,0,110,117,109,118,101,114,116,115,0,110,117,109,102,97, +99,101,115,0,97,98,115,111,114,112,116,105,111,110,0,116,105,109,101,0,42,98,118,104,116,114,101,101,0,42,100,109, +0,111,112,101,114,97,116,105,111,110,0,118,101,114,116,101,120,0,116,111,116,105,110,102,108,117,101,110,99,101,0,103, +114,105,100,115,105,122,101,0,110,101,101,100,98,105,110,100,0,42,98,105,110,100,119,101,105,103,104,116,115,0,42,98, +105,110,100,99,111,115,0,116,111,116,99,97,103,101,118,101,114,116,0,42,100,121,110,103,114,105,100,0,42,100,121,110, +105,110,102,108,117,101,110,99,101,115,0,42,100,121,110,118,101,114,116,115,0,42,112,97,100,50,0,100,121,110,103,114, +105,100,115,105,122,101,0,100,121,110,99,101,108,108,109,105,110,91,51,93,0,100,121,110,99,101,108,108,119,105,100,116, +104,0,98,105,110,100,109,97,116,91,52,93,91,52,93,0,42,112,115,121,115,0,116,111,116,100,109,118,101,114,116,0, +116,111,116,100,109,101,100,103,101,0,116,111,116,100,109,102,97,99,101,0,112,115,121,115,0,114,116,91,50,93,0,42, +102,97,99,101,112,97,0,118,103,114,111,117,112,0,112,114,111,116,101,99,116,0,42,102,115,115,0,42,116,97,114,103, +101,116,0,42,97,117,120,84,97,114,103,101,116,0,118,103,114,111,117,112,95,110,97,109,101,91,51,50,93,0,107,101, +101,112,68,105,115,116,0,115,104,114,105,110,107,84,121,112,101,0,115,104,114,105,110,107,79,112,116,115,0,112,114,111, +106,65,120,105,115,0,115,117,98,115,117,114,102,76,101,118,101,108,115,0,42,111,114,105,103,105,110,0,102,97,99,116, +111,114,0,108,105,109,105,116,91,50,93,0,111,114,105,103,105,110,79,112,116,115,0,112,110,116,115,119,0,111,112,110, +116,115,117,0,111,112,110,116,115,118,0,111,112,110,116,115,119,0,116,121,112,101,117,0,116,121,112,101,118,0,116,121, +112,101,119,0,102,117,0,102,118,0,102,119,0,100,117,0,100,118,0,100,119,0,42,100,101,102,0,118,101,99,91,56, +93,91,51,93,0,112,97,114,116,121,112,101,0,112,97,114,49,0,112,97,114,50,0,112,97,114,51,0,112,97,114,115, +117,98,115,116,114,91,51,50,93,0,42,116,114,97,99,107,0,42,112,114,111,120,121,0,42,112,114,111,120,121,95,103, +114,111,117,112,0,42,112,114,111,120,121,95,102,114,111,109,0,42,97,99,116,105,111,110,0,42,112,111,115,101,108,105, +98,0,42,112,111,115,101,0,99,111,110,115,116,114,97,105,110,116,67,104,97,110,110,101,108,115,0,100,101,102,98,97, +115,101,0,109,111,100,105,102,105,101,114,115,0,100,108,111,99,91,51,93,0,111,114,105,103,91,51,93,0,100,115,105, +122,101,91,51,93,0,100,114,111,116,91,51,93,0,111,98,109,97,116,91,52,93,91,52,93,0,99,111,110,115,116,105, +110,118,91,52,93,91,52,93,0,108,97,121,0,99,111,108,98,105,116,115,0,116,114,97,110,115,102,108,97,103,0,105, +112,111,102,108,97,103,0,116,114,97,99,107,102,108,97,103,0,117,112,102,108,97,103,0,110,108,97,102,108,97,103,0, +112,114,111,116,101,99,116,102,108,97,103,0,105,112,111,119,105,110,0,115,99,97,102,108,97,103,0,115,99,97,118,105, +115,102,108,97,103,0,98,111,117,110,100,116,121,112,101,0,100,117,112,111,110,0,100,117,112,111,102,102,0,100,117,112, +115,116,97,0,100,117,112,101,110,100,0,115,102,0,99,116,105,109,101,0,109,97,115,115,0,100,97,109,112,105,110,103, +0,105,110,101,114,116,105,97,0,102,111,114,109,102,97,99,116,111,114,0,114,100,97,109,112,105,110,103,0,115,105,122, +101,102,97,99,0,109,97,114,103,105,110,0,109,97,120,95,118,101,108,0,109,105,110,95,118,101,108,0,109,95,99,111, +110,116,97,99,116,80,114,111,99,101,115,115,105,110,103,84,104,114,101,115,104,111,108,100,0,100,116,0,100,116,120,0, +97,99,116,99,111,108,0,101,109,112,116,121,95,100,114,97,119,116,121,112,101,0,112,97,100,49,91,51,93,0,101,109, +112,116,121,95,100,114,97,119,115,105,122,101,0,100,117,112,102,97,99,101,115,99,97,0,112,114,111,112,0,115,101,110, +115,111,114,115,0,99,111,110,116,114,111,108,108,101,114,115,0,97,99,116,117,97,116,111,114,115,0,98,98,115,105,122, +101,91,51,93,0,97,99,116,100,101,102,0,103,97,109,101,102,108,97,103,0,103,97,109,101,102,108,97,103,50,0,42, +98,115,111,102,116,0,115,111,102,116,102,108,97,103,0,97,110,105,115,111,116,114,111,112,105,99,70,114,105,99,116,105, +111,110,91,51,93,0,99,111,110,115,116,114,97,105,110,116,115,0,110,108,97,115,116,114,105,112,115,0,104,111,111,107, +115,0,112,97,114,116,105,99,108,101,115,121,115,116,101,109,0,42,112,100,0,42,115,111,102,116,0,42,100,117,112,95, +103,114,111,117,112,0,102,108,117,105,100,115,105,109,70,108,97,103,0,114,101,115,116,114,105,99,116,102,108,97,103,0, +115,104,97,112,101,110,114,0,115,104,97,112,101,102,108,97,103,0,114,101,99,97,108,99,111,0,98,111,100,121,95,116, +121,112,101,0,42,102,108,117,105,100,115,105,109,83,101,116,116,105,110,103,115,0,42,100,101,114,105,118,101,100,68,101, +102,111,114,109,0,42,100,101,114,105,118,101,100,70,105,110,97,108,0,108,97,115,116,68,97,116,97,77,97,115,107,0, +115,116,97,116,101,0,105,110,105,116,95,115,116,97,116,101,0,103,112,117,108,97,109,112,0,99,117,114,105,110,100,101, +120,0,97,99,116,105,118,101,0,100,101,102,108,101,99,116,0,102,111,114,99,101,102,105,101,108,100,0,112,100,101,102, +95,100,97,109,112,0,112,100,101,102,95,114,100,97,109,112,0,112,100,101,102,95,112,101,114,109,0,112,100,101,102,95, +102,114,105,99,116,0,112,100,101,102,95,114,102,114,105,99,116,0,102,95,115,116,114,101,110,103,116,104,0,102,95,112, +111,119,101,114,0,102,95,100,105,115,116,0,102,95,100,97,109,112,0,109,97,120,100,105,115,116,0,109,105,110,100,105, +115,116,0,109,97,120,114,97,100,0,109,105,110,114,97,100,0,102,95,112,111,119,101,114,95,114,0,112,100,101,102,95, +115,98,100,97,109,112,0,112,100,101,102,95,115,98,105,102,116,0,112,100,101,102,95,115,98,111,102,116,0,99,108,117, +109,112,95,102,97,99,0,99,108,117,109,112,95,112,111,119,0,107,105,110,107,95,102,114,101,113,0,107,105,110,107,95, +115,104,97,112,101,0,107,105,110,107,95,97,109,112,0,102,114,101,101,95,101,110,100,0,116,101,120,95,110,97,98,108, +97,0,116,101,120,95,109,111,100,101,0,107,105,110,107,0,107,105,110,107,95,97,120,105,115,0,114,116,50,0,42,114, +110,103,0,102,95,110,111,105,115,101,0,115,105,109,102,114,97,109,101,0,115,116,97,114,116,102,114,97,109,101,0,101, +110,100,102,114,97,109,101,0,101,100,105,116,102,114,97,109,101,0,108,105,110,83,116,105,102,102,0,97,110,103,83,116, +105,102,102,0,118,111,108,117,109,101,0,118,105,116,101,114,97,116,105,111,110,115,0,112,105,116,101,114,97,116,105,111, +110,115,0,100,105,116,101,114,97,116,105,111,110,115,0,99,105,116,101,114,97,116,105,111,110,115,0,107,83,82,72,82, +95,67,76,0,107,83,75,72,82,95,67,76,0,107,83,83,72,82,95,67,76,0,107,83,82,95,83,80,76,84,95,67, +76,0,107,83,75,95,83,80,76,84,95,67,76,0,107,83,83,95,83,80,76,84,95,67,76,0,107,86,67,70,0,107, +68,80,0,107,68,71,0,107,76,70,0,107,80,82,0,107,86,67,0,107,68,70,0,107,77,84,0,107,67,72,82,0, +107,75,72,82,0,107,83,72,82,0,107,65,72,82,0,99,111,108,108,105,115,105,111,110,102,108,97,103,115,0,110,117, +109,99,108,117,115,116,101,114,105,116,101,114,97,116,105,111,110,115,0,119,101,108,100,105,110,103,0,42,112,97,114,116, +105,99,108,101,115,0,116,111,116,112,111,105,110,116,0,116,111,116,115,112,114,105,110,103,0,42,98,112,111,105,110,116, +0,42,98,115,112,114,105,110,103,0,109,115,103,95,108,111,99,107,0,109,115,103,95,118,97,108,117,101,0,110,111,100, +101,109,97,115,115,0,110,97,109,101,100,86,71,95,77,97,115,115,91,51,50,93,0,103,114,97,118,0,109,101,100,105, +97,102,114,105,99,116,0,114,107,108,105,109,105,116,0,112,104,121,115,105,99,115,95,115,112,101,101,100,0,103,111,97, +108,115,112,114,105,110,103,0,103,111,97,108,102,114,105,99,116,0,109,105,110,103,111,97,108,0,109,97,120,103,111,97, +108,0,100,101,102,103,111,97,108,0,118,101,114,116,103,114,111,117,112,0,110,97,109,101,100,86,71,95,83,111,102,116, +103,111,97,108,91,51,50,93,0,102,117,122,122,121,110,101,115,115,0,105,110,115,112,114,105,110,103,0,105,110,102,114, +105,99,116,0,110,97,109,101,100,86,71,95,83,112,114,105,110,103,95,75,91,51,50,93,0,101,102,114,97,0,105,110, +116,101,114,118,97,108,0,108,111,99,97,108,0,115,111,108,118,101,114,102,108,97,103,115,0,42,42,107,101,121,115,0, +116,111,116,112,111,105,110,116,107,101,121,0,115,101,99,111,110,100,115,112,114,105,110,103,0,99,111,108,98,97,108,108, +0,98,97,108,108,100,97,109,112,0,98,97,108,108,115,116,105,102,102,0,115,98,99,95,109,111,100,101,0,97,101,114, +111,101,100,103,101,0,109,105,110,108,111,111,112,115,0,109,97,120,108,111,111,112,115,0,99,104,111,107,101,0,115,111, +108,118,101,114,95,73,68,0,112,108,97,115,116,105,99,0,115,112,114,105,110,103,112,114,101,108,111,97,100,0,42,115, +99,114,97,116,99,104,0,115,104,101,97,114,115,116,105,102,102,0,105,110,112,117,115,104,0,42,112,111,105,110,116,99, +97,99,104,101,0,115,104,111,119,95,97,100,118,97,110,99,101,100,111,112,116,105,111,110,115,0,114,101,115,111,108,117, +116,105,111,110,120,121,122,0,112,114,101,118,105,101,119,114,101,115,120,121,122,0,114,101,97,108,115,105,122,101,0,103, +117,105,68,105,115,112,108,97,121,77,111,100,101,0,114,101,110,100,101,114,68,105,115,112,108,97,121,77,111,100,101,0, +118,105,115,99,111,115,105,116,121,86,97,108,117,101,0,118,105,115,99,111,115,105,116,121,77,111,100,101,0,118,105,115, +99,111,115,105,116,121,69,120,112,111,110,101,110,116,0,103,114,97,118,120,0,103,114,97,118,121,0,103,114,97,118,122, +0,97,110,105,109,83,116,97,114,116,0,97,110,105,109,69,110,100,0,103,115,116,97,114,0,109,97,120,82,101,102,105, +110,101,0,105,110,105,86,101,108,120,0,105,110,105,86,101,108,121,0,105,110,105,86,101,108,122,0,42,111,114,103,77, +101,115,104,0,42,109,101,115,104,83,117,114,102,97,99,101,0,42,109,101,115,104,66,66,0,115,117,114,102,100,97,116, +97,80,97,116,104,91,50,52,48,93,0,98,98,83,116,97,114,116,91,51,93,0,98,98,83,105,122,101,91,51,93,0, +116,121,112,101,70,108,97,103,115,0,100,111,109,97,105,110,78,111,118,101,99,103,101,110,0,118,111,108,117,109,101,73, +110,105,116,84,121,112,101,0,112,97,114,116,83,108,105,112,86,97,108,117,101,0,103,101,110,101,114,97,116,101,84,114, +97,99,101,114,115,0,103,101,110,101,114,97,116,101,80,97,114,116,105,99,108,101,115,0,115,117,114,102,97,99,101,83, +109,111,111,116,104,105,110,103,0,115,117,114,102,97,99,101,83,117,98,100,105,118,115,0,112,97,114,116,105,99,108,101, +73,110,102,83,105,122,101,0,112,97,114,116,105,99,108,101,73,110,102,65,108,112,104,97,0,102,97,114,70,105,101,108, +100,83,105,122,101,0,42,109,101,115,104,83,117,114,102,78,111,114,109,97,108,115,0,99,112,115,84,105,109,101,83,116, +97,114,116,0,99,112,115,84,105,109,101,69,110,100,0,99,112,115,81,117,97,108,105,116,121,0,97,116,116,114,97,99, +116,102,111,114,99,101,83,116,114,101,110,103,116,104,0,97,116,116,114,97,99,116,102,111,114,99,101,82,97,100,105,117, +115,0,118,101,108,111,99,105,116,121,102,111,114,99,101,83,116,114,101,110,103,116,104,0,118,101,108,111,99,105,116,121, +102,111,114,99,101,82,97,100,105,117,115,0,108,97,115,116,103,111,111,100,102,114,97,109,101,0,109,105,115,116,121,112, +101,0,104,111,114,114,0,104,111,114,103,0,104,111,114,98,0,104,111,114,107,0,122,101,110,114,0,122,101,110,103,0, +122,101,110,98,0,122,101,110,107,0,97,109,98,107,0,102,97,115,116,99,111,108,0,101,120,112,111,115,117,114,101,0, +101,120,112,0,114,97,110,103,101,0,108,105,110,102,97,99,0,108,111,103,102,97,99,0,103,114,97,118,105,116,121,0, +97,99,116,105,118,105,116,121,66,111,120,82,97,100,105,117,115,0,115,107,121,116,121,112,101,0,111,99,99,108,117,115, +105,111,110,82,101,115,0,112,104,121,115,105,99,115,69,110,103,105,110,101,0,116,105,99,114,97,116,101,0,109,97,120, +108,111,103,105,99,115,116,101,112,0,112,104,121,115,117,98,115,116,101,112,0,109,97,120,112,104,121,115,116,101,112,0, +109,105,115,105,0,109,105,115,116,115,116,97,0,109,105,115,116,100,105,115,116,0,109,105,115,116,104,105,0,115,116,97, +114,114,0,115,116,97,114,103,0,115,116,97,114,98,0,115,116,97,114,107,0,115,116,97,114,115,105,122,101,0,115,116, +97,114,109,105,110,100,105,115,116,0,115,116,97,114,100,105,115,116,0,115,116,97,114,99,111,108,110,111,105,115,101,0, +100,111,102,115,116,97,0,100,111,102,101,110,100,0,100,111,102,109,105,110,0,100,111,102,109,97,120,0,97,111,100,105, +115,116,0,97,111,100,105,115,116,102,97,99,0,97,111,101,110,101,114,103,121,0,97,111,98,105,97,115,0,97,111,109, +111,100,101,0,97,111,115,97,109,112,0,97,111,109,105,120,0,97,111,99,111,108,111,114,0,97,111,95,97,100,97,112, +116,95,116,104,114,101,115,104,0,97,111,95,97,100,97,112,116,95,115,112,101,101,100,95,102,97,99,0,97,111,95,97, +112,112,114,111,120,95,101,114,114,111,114,0,97,111,95,97,112,112,114,111,120,95,99,111,114,114,101,99,116,105,111,110, +0,97,111,95,115,97,109,112,95,109,101,116,104,111,100,0,97,111,95,103,97,116,104,101,114,95,109,101,116,104,111,100, +0,97,111,95,97,112,112,114,111,120,95,112,97,115,115,101,115,0,42,97,111,115,112,104,101,114,101,0,42,97,111,116, +97,98,108,101,115,0,104,101,109,105,114,101,115,0,109,97,120,105,116,101,114,0,100,114,97,119,116,121,112,101,0,115, +117,98,115,104,111,111,116,112,0,115,117,98,115,104,111,111,116,101,0,110,111,100,101,108,105,109,0,109,97,120,115,117, +98,108,97,109,112,0,112,97,109,97,0,112,97,109,105,0,101,108,109,97,0,101,108,109,105,0,109,97,120,110,111,100, +101,0,99,111,110,118,101,114,103,101,110,99,101,0,114,97,100,102,97,99,0,103,97,109,109,97,0,115,101,108,99,111, +108,0,115,120,0,115,121,0,42,108,112,70,111,114,109,97,116,0,42,108,112,80,97,114,109,115,0,99,98,70,111,114, +109,97,116,0,99,98,80,97,114,109,115,0,102,99,99,84,121,112,101,0,102,99,99,72,97,110,100,108,101,114,0,100, +119,75,101,121,70,114,97,109,101,69,118,101,114,121,0,100,119,81,117,97,108,105,116,121,0,100,119,66,121,116,101,115, +80,101,114,83,101,99,111,110,100,0,100,119,70,108,97,103,115,0,100,119,73,110,116,101,114,108,101,97,118,101,69,118, +101,114,121,0,97,118,105,99,111,100,101,99,110,97,109,101,91,49,50,56,93,0,42,99,100,80,97,114,109,115,0,42, +112,97,100,0,99,100,83,105,122,101,0,113,116,99,111,100,101,99,110,97,109,101,91,49,50,56,93,0,99,111,100,101, +99,0,97,117,100,105,111,95,99,111,100,101,99,0,118,105,100,101,111,95,98,105,116,114,97,116,101,0,97,117,100,105, +111,95,98,105,116,114,97,116,101,0,103,111,112,95,115,105,122,101,0,114,99,95,109,105,110,95,114,97,116,101,0,114, +99,95,109,97,120,95,114,97,116,101,0,114,99,95,98,117,102,102,101,114,95,115,105,122,101,0,109,117,120,95,112,97, +99,107,101,116,95,115,105,122,101,0,109,117,120,95,114,97,116,101,0,109,105,120,114,97,116,101,0,109,97,105,110,0, +42,109,97,116,95,111,118,101,114,114,105,100,101,0,42,108,105,103,104,116,95,111,118,101,114,114,105,100,101,0,108,97, +121,95,122,109,97,115,107,0,108,97,121,102,108,97,103,0,112,97,115,115,102,108,97,103,0,112,97,115,115,95,120,111, +114,0,42,97,118,105,99,111,100,101,99,100,97,116,97,0,42,113,116,99,111,100,101,99,100,97,116,97,0,102,102,99, +111,100,101,99,100,97,116,97,0,99,102,114,97,0,112,115,102,114,97,0,112,101,102,114,97,0,105,109,97,103,101,115, +0,102,114,97,109,97,112,116,111,0,116,104,114,101,97,100,115,0,102,114,97,109,101,108,101,110,0,98,108,117,114,102, +97,99,0,101,100,103,101,82,0,101,100,103,101,71,0,101,100,103,101,66,0,102,117,108,108,115,99,114,101,101,110,0, +120,112,108,97,121,0,121,112,108,97,121,0,102,114,101,113,112,108,97,121,0,97,116,116,114,105,98,0,114,116,49,0, +115,116,101,114,101,111,109,111,100,101,0,100,105,109,101,110,115,105,111,110,115,112,114,101,115,101,116,0,109,97,120,105, +109,115,105,122,101,0,120,115,99,104,0,121,115,99,104,0,120,112,97,114,116,115,0,121,112,97,114,116,115,0,119,105, +110,112,111,115,0,112,108,97,110,101,115,0,105,109,116,121,112,101,0,115,117,98,105,109,116,121,112,101,0,113,117,97, +108,105,116,121,0,114,112,97,100,0,114,112,97,100,49,0,114,112,97,100,50,0,115,99,101,109,111,100,101,0,114,101, +110,100,101,114,101,114,0,111,99,114,101,115,0,97,108,112,104,97,109,111,100,101,0,111,115,97,0,102,114,115,95,115, +101,99,0,101,100,103,101,105,110,116,0,115,97,102,101,116,121,0,98,111,114,100,101,114,0,100,105,115,112,114,101,99, +116,0,108,97,121,101,114,115,0,97,99,116,108,97,121,0,120,97,115,112,0,121,97,115,112,0,102,114,115,95,115,101, +99,95,98,97,115,101,0,103,97,117,115,115,0,112,111,115,116,109,117,108,0,112,111,115,116,103,97,109,109,97,0,112, +111,115,116,104,117,101,0,112,111,115,116,115,97,116,0,100,105,116,104,101,114,95,105,110,116,101,110,115,105,116,121,0, +98,97,107,101,95,111,115,97,0,98,97,107,101,95,102,105,108,116,101,114,0,98,97,107,101,95,109,111,100,101,0,98, +97,107,101,95,102,108,97,103,0,98,97,107,101,95,110,111,114,109,97,108,95,115,112,97,99,101,0,98,97,107,101,95, +113,117,97,100,95,115,112,108,105,116,0,98,97,107,101,95,109,97,120,100,105,115,116,0,98,97,107,101,95,98,105,97, +115,100,105,115,116,0,98,97,107,101,95,112,97,100,0,71,73,113,117,97,108,105,116,121,0,71,73,99,97,99,104,101, +0,71,73,109,101,116,104,111,100,0,71,73,112,104,111,116,111,110,115,0,71,73,100,105,114,101,99,116,0,89,70,95, +65,65,0,89,70,101,120,112,111,114,116,120,109,108,0,89,70,95,110,111,98,117,109,112,0,89,70,95,99,108,97,109, +112,114,103,98,0,121,102,112,97,100,49,0,71,73,100,101,112,116,104,0,71,73,99,97,117,115,100,101,112,116,104,0, +71,73,112,105,120,101,108,115,112,101,114,115,97,109,112,108,101,0,71,73,112,104,111,116,111,110,99,111,117,110,116,0, +71,73,109,105,120,112,104,111,116,111,110,115,0,71,73,112,104,111,116,111,110,114,97,100,105,117,115,0,89,70,95,114, +97,121,100,101,112,116,104,0,89,70,95,65,65,112,97,115,115,101,115,0,89,70,95,65,65,115,97,109,112,108,101,115, +0,121,102,112,97,100,50,0,71,73,115,104,97,100,111,119,113,117,97,108,105,116,121,0,71,73,114,101,102,105,110,101, +109,101,110,116,0,71,73,112,111,119,101,114,0,71,73,105,110,100,105,114,112,111,119,101,114,0,89,70,95,103,97,109, +109,97,0,89,70,95,101,120,112,111,115,117,114,101,0,89,70,95,114,97,121,98,105,97,115,0,89,70,95,65,65,112, +105,120,101,108,115,105,122,101,0,89,70,95,65,65,116,104,114,101,115,104,111,108,100,0,98,97,99,107,98,117,102,91, +49,54,48,93,0,112,105,99,91,49,54,48,93,0,115,116,97,109,112,0,115,116,97,109,112,95,102,111,110,116,95,105, +100,0,115,116,97,109,112,95,117,100,97,116,97,91,49,54,48,93,0,102,103,95,115,116,97,109,112,91,52,93,0,98, +103,95,115,116,97,109,112,91,52,93,0,115,105,109,112,108,105,102,121,95,115,117,98,115,117,114,102,0,115,105,109,112, +108,105,102,121,95,115,104,97,100,111,119,115,97,109,112,108,101,115,0,115,105,109,112,108,105,102,121,95,112,97,114,116, +105,99,108,101,115,0,115,105,109,112,108,105,102,121,95,97,111,115,115,115,0,99,105,110,101,111,110,119,104,105,116,101, +0,99,105,110,101,111,110,98,108,97,99,107,0,99,105,110,101,111,110,103,97,109,109,97,0,106,112,50,95,112,114,101, +115,101,116,0,106,112,50,95,100,101,112,116,104,0,114,112,97,100,51,0,100,111,109,101,114,101,115,0,100,111,109,101, +109,111,100,101,0,100,111,109,101,97,110,103,108,101,0,100,111,109,101,116,105,108,116,0,100,111,109,101,114,101,115,98, +117,102,0,42,100,111,109,101,116,101,120,116,0,112,97,114,116,105,99,108,101,95,112,101,114,99,0,115,117,98,115,117, +114,102,95,109,97,120,0,115,104,97,100,98,117,102,115,97,109,112,108,101,95,109,97,120,0,97,111,95,101,114,114,111, +114,0,99,111,108,91,51,93,0,102,114,97,109,101,0,110,97,109,101,91,54,52,93,0,42,98,114,117,115,104,0,116, +111,111,108,0,115,101,97,109,95,98,108,101,101,100,0,110,111,114,109,97,108,95,97,110,103,108,101,0,115,116,101,112, +0,105,110,118,101,114,116,0,116,111,116,114,101,107,101,121,0,116,111,116,97,100,100,107,101,121,0,98,114,117,115,104, +116,121,112,101,0,98,114,117,115,104,91,55,93,0,101,109,105,116,116,101,114,100,105,115,116,0,100,114,97,119,95,116, +105,109,101,100,0,110,97,109,101,91,51,54,93,0,109,97,116,91,51,93,91,51,93,0,99,111,114,110,101,114,116,121, +112,101,0,101,100,105,116,98,117,116,102,108,97,103,0,106,111,105,110,116,114,105,108,105,109,105,116,0,100,101,103,114, +0,116,117,114,110,0,101,120,116,114,95,111,102,102,115,0,100,111,117,98,108,105,109,105,116,0,115,101,103,109,101,110, +116,115,0,114,105,110,103,115,0,118,101,114,116,105,99,101,115,0,117,110,119,114,97,112,112,101,114,0,117,118,99,97, +108,99,95,114,97,100,105,117,115,0,117,118,99,97,108,99,95,99,117,98,101,115,105,122,101,0,117,118,99,97,108,99, +95,109,97,114,103,105,110,0,117,118,99,97,108,99,95,109,97,112,100,105,114,0,117,118,99,97,108,99,95,109,97,112, +97,108,105,103,110,0,117,118,99,97,108,99,95,102,108,97,103,0,97,117,116,111,105,107,95,99,104,97,105,110,108,101, +110,0,105,109,97,112,97,105,110,116,0,112,97,114,116,105,99,108,101,0,115,101,108,101,99,116,95,116,104,114,101,115, +104,0,99,108,101,97,110,95,116,104,114,101,115,104,0,114,101,116,111,112,111,95,109,111,100,101,0,114,101,116,111,112, +111,95,112,97,105,110,116,95,116,111,111,108,0,108,105,110,101,95,100,105,118,0,101,108,108,105,112,115,101,95,100,105, +118,0,114,101,116,111,112,111,95,104,111,116,115,112,111,116,0,109,117,108,116,105,114,101,115,95,115,117,98,100,105,118, +95,116,121,112,101,0,115,107,103,101,110,95,114,101,115,111,108,117,116,105,111,110,0,115,107,103,101,110,95,116,104,114, +101,115,104,111,108,100,95,105,110,116,101,114,110,97,108,0,115,107,103,101,110,95,116,104,114,101,115,104,111,108,100,95, +101,120,116,101,114,110,97,108,0,115,107,103,101,110,95,108,101,110,103,116,104,95,114,97,116,105,111,0,115,107,103,101, +110,95,108,101,110,103,116,104,95,108,105,109,105,116,0,115,107,103,101,110,95,97,110,103,108,101,95,108,105,109,105,116, +0,115,107,103,101,110,95,99,111,114,114,101,108,97,116,105,111,110,95,108,105,109,105,116,0,115,107,103,101,110,95,115, +121,109,109,101,116,114,121,95,108,105,109,105,116,0,115,107,103,101,110,95,114,101,116,97,114,103,101,116,95,97,110,103, +108,101,95,119,101,105,103,104,116,0,115,107,103,101,110,95,114,101,116,97,114,103,101,116,95,108,101,110,103,116,104,95, +119,101,105,103,104,116,0,115,107,103,101,110,95,114,101,116,97,114,103,101,116,95,100,105,115,116,97,110,99,101,95,119, +101,105,103,104,116,0,115,107,103,101,110,95,111,112,116,105,111,110,115,0,115,107,103,101,110,95,112,111,115,116,112,114, +111,0,115,107,103,101,110,95,112,111,115,116,112,114,111,95,112,97,115,115,101,115,0,115,107,103,101,110,95,115,117,98, +100,105,118,105,115,105,111,110,115,91,51,93,0,115,107,103,101,110,95,109,117,108,116,105,95,108,101,118,101,108,0,42, +115,107,103,101,110,95,116,101,109,112,108,97,116,101,0,98,111,110,101,95,115,107,101,116,99,104,105,110,103,0,98,111, +110,101,95,115,107,101,116,99,104,105,110,103,95,99,111,110,118,101,114,116,0,115,107,103,101,110,95,115,117,98,100,105, +118,105,115,105,111,110,95,110,117,109,98,101,114,0,115,107,103,101,110,95,114,101,116,97,114,103,101,116,95,111,112,116, +105,111,110,115,0,115,107,103,101,110,95,114,101,116,97,114,103,101,116,95,114,111,108,108,0,115,107,103,101,110,95,115, +105,100,101,95,115,116,114,105,110,103,91,56,93,0,115,107,103,101,110,95,110,117,109,95,115,116,114,105,110,103,91,56, +93,0,101,100,103,101,95,109,111,100,101,0,112,97,100,51,91,50,93,0,100,105,114,0,118,105,101,119,0,42,115,101, +115,115,105,111,110,0,42,99,117,109,97,112,0,100,114,97,119,98,114,117,115,104,0,115,109,111,111,116,104,98,114,117, +115,104,0,112,105,110,99,104,98,114,117,115,104,0,105,110,102,108,97,116,101,98,114,117,115,104,0,103,114,97,98,98, +114,117,115,104,0,108,97,121,101,114,98,114,117,115,104,0,102,108,97,116,116,101,110,98,114,117,115,104,0,112,105,118, +111,116,91,51,93,0,98,114,117,115,104,95,116,121,112,101,0,116,101,120,110,114,0,116,101,120,114,101,112,116,0,116, +101,120,102,97,100,101,0,116,101,120,115,101,112,0,97,118,101,114,97,103,105,110,103,0,116,97,98,108,101,116,95,115, +105,122,101,0,116,97,98,108,101,116,95,115,116,114,101,110,103,116,104,0,115,121,109,109,0,114,97,107,101,0,97,120, +105,115,108,111,99,107,0,42,99,97,109,101,114,97,0,42,119,111,114,108,100,0,42,115,101,116,0,98,97,115,101,0, +42,98,97,115,97,99,116,0,99,117,114,115,111,114,91,51,93,0,116,119,99,101,110,116,91,51,93,0,116,119,109,105, +110,91,51,93,0,116,119,109,97,120,91,51,93,0,101,100,105,116,98,117,116,115,105,122,101,0,115,101,108,101,99,116, +109,111,100,101,0,112,114,111,112,111,114,116,105,111,110,97,108,0,112,114,111,112,95,109,111,100,101,0,97,117,116,111, +109,101,114,103,101,0,112,97,100,53,0,112,97,100,54,0,97,117,116,111,107,101,121,95,109,111,100,101,0,42,101,100, +0,42,114,97,100,105,111,0,102,114,97,109,105,110,103,0,42,116,111,111,108,115,101,116,116,105,110,103,115,0,97,117, +100,105,111,0,116,114,97,110,115,102,111,114,109,95,115,112,97,99,101,115,0,106,117,109,112,102,114,97,109,101,0,115, +110,97,112,95,109,111,100,101,0,115,110,97,112,95,102,108,97,103,0,115,110,97,112,95,116,97,114,103,101,116,0,42, +116,104,101,68,97,103,0,100,97,103,105,115,118,97,108,105,100,0,100,97,103,102,108,97,103,115,0,115,99,117,108,112, +116,100,97,116,97,0,102,114,97,109,101,95,115,116,101,112,0,122,111,111,109,0,98,108,101,110,100,0,120,105,109,0, +121,105,109,0,115,112,97,99,101,116,121,112,101,0,98,108,111,99,107,115,99,97,108,101,0,42,97,114,101,97,0,98, +108,111,99,107,104,97,110,100,108,101,114,91,56,93,0,118,105,101,119,109,97,116,91,52,93,91,52,93,0,118,105,101, +119,105,110,118,91,52,93,91,52,93,0,112,101,114,115,109,97,116,91,52,93,91,52,93,0,112,101,114,115,105,110,118, +91,52,93,91,52,93,0,119,105,110,109,97,116,49,91,52,93,91,52,93,0,118,105,101,119,109,97,116,49,91,52,93, +91,52,93,0,118,105,101,119,113,117,97,116,91,52,93,0,122,102,97,99,0,108,97,121,95,117,115,101,100,0,112,101, +114,115,112,0,42,111,98,95,99,101,110,116,114,101,0,42,98,103,112,105,99,0,42,108,111,99,97,108,118,100,0,42, +114,105,0,42,114,101,116,111,112,111,95,118,105,101,119,95,100,97,116,97,0,42,100,101,112,116,104,115,0,111,98,95, +99,101,110,116,114,101,95,98,111,110,101,91,51,50,93,0,108,111,99,97,108,118,105,101,119,0,108,97,121,97,99,116, +0,115,99,101,110,101,108,111,99,107,0,97,114,111,117,110,100,0,99,97,109,122,111,111,109,0,112,105,118,111,116,95, +108,97,115,116,0,103,114,105,100,0,103,114,105,100,118,105,101,119,0,112,105,120,115,105,122,101,0,110,101,97,114,0, +102,97,114,0,99,97,109,100,120,0,99,97,109,100,121,0,103,114,105,100,108,105,110,101,115,0,118,105,101,119,98,117, +116,0,103,114,105,100,102,108,97,103,0,109,111,100,101,115,101,108,101,99,116,0,116,119,116,121,112,101,0,116,119,109, +111,100,101,0,116,119,102,108,97,103,0,116,119,100,114,97,119,102,108,97,103,0,116,119,109,97,116,91,52,93,91,52, +93,0,99,108,105,112,91,52,93,91,52,93,0,42,99,108,105,112,98,98,0,97,102,116,101,114,100,114,97,119,0,122, +98,117,102,0,120,114,97,121,0,102,108,97,103,50,0,103,114,105,100,115,117,98,100,105,118,0,107,101,121,102,108,97, +103,115,0,110,100,111,102,109,111,100,101,0,110,100,111,102,102,105,108,116,101,114,0,42,112,114,111,112,101,114,116,105, +101,115,95,115,116,111,114,97,103,101,0,42,103,112,100,0,108,118,105,101,119,113,117,97,116,91,52,93,0,108,112,101, +114,115,112,0,108,118,105,101,119,0,118,101,114,116,0,104,111,114,0,109,97,115,107,0,109,105,110,91,50,93,0,109, +97,120,91,50,93,0,109,105,110,122,111,111,109,0,109,97,120,122,111,111,109,0,115,99,114,111,108,108,0,107,101,101, +112,116,111,116,0,107,101,101,112,97,115,112,101,99,116,0,107,101,101,112,122,111,111,109,0,111,108,100,119,105,110,120, +0,111,108,100,119,105,110,121,0,99,117,114,115,111,114,91,50,93,0,114,111,119,98,117,116,0,118,50,100,0,42,101, +100,105,116,105,112,111,0,105,112,111,107,101,121,0,97,99,116,110,97,109,101,91,51,50,93,0,99,111,110,115,116,110, +97,109,101,91,51,50,93,0,98,111,110,101,110,97,109,101,91,51,50,93,0,116,111,116,105,112,111,0,112,105,110,0, +98,117,116,111,102,115,0,99,104,97,110,110,101,108,0,108,111,99,107,0,109,101,100,105,97,110,91,51,93,0,99,117, +114,115,101,110,115,0,99,117,114,97,99,116,0,97,108,105,103,110,0,116,97,98,111,0,109,97,105,110,98,0,109,97, +105,110,98,111,0,42,108,111,99,107,112,111,105,110,0,116,101,120,102,114,111,109,0,115,104,111,119,103,114,111,117,112, +0,109,111,100,101,108,116,121,112,101,0,115,99,114,105,112,116,98,108,111,99,107,0,114,101,95,97,108,105,103,110,0, +111,108,100,107,101,121,112,114,101,115,115,0,116,97,98,91,55,93,0,114,101,110,100,101,114,95,115,105,122,101,0,99, +104,97,110,115,104,111,119,110,0,122,101,98,114,97,0,42,102,105,108,101,108,105,115,116,0,116,111,116,102,105,108,101, +0,116,105,116,108,101,91,50,52,93,0,100,105,114,91,50,52,48,93,0,102,105,108,101,91,56,48,93,0,111,102,115, +0,115,111,114,116,0,109,97,120,110,97,109,101,108,101,110,0,99,111,108,108,117,109,115,0,102,95,102,112,0,102,112, +95,115,116,114,91,56,93,0,42,108,105,98,102,105,108,101,100,97,116,97,0,114,101,116,118,97,108,0,109,101,110,117, +0,97,99,116,0,40,42,114,101,116,117,114,110,102,117,110,99,41,40,41,0,40,42,114,101,116,117,114,110,102,117,110, +99,95,101,118,101,110,116,41,40,41,0,40,42,114,101,116,117,114,110,102,117,110,99,95,97,114,103,115,41,40,41,0, +42,97,114,103,49,0,42,97,114,103,50,0,42,109,101,110,117,112,0,42,112,117,112,109,101,110,117,0,111,111,112,115, +0,118,105,115,105,102,108,97,103,0,116,114,101,101,0,42,116,114,101,101,115,116,111,114,101,0,115,101,97,114,99,104, +95,115,116,114,105,110,103,91,51,50,93,0,115,101,97,114,99,104,95,116,115,101,0,115,101,97,114,99,104,95,102,108, +97,103,115,0,100,111,95,0,111,117,116,108,105,110,101,118,105,115,0,115,116,111,114,101,102,108,97,103,0,100,101,112, +115,95,102,108,97,103,115,0,105,109,97,110,114,0,99,117,114,116,105,108,101,0,105,109,116,121,112,101,110,114,0,100, +116,95,117,118,0,115,116,105,99,107,121,0,100,116,95,117,118,115,116,114,101,116,99,104,0,112,97,100,91,53,93,0, +99,101,110,116,120,0,99,101,110,116,121,0,97,117,116,111,115,110,97,112,0,42,116,101,120,116,0,116,111,112,0,118, +105,101,119,108,105,110,101,115,0,102,111,110,116,95,105,100,0,108,104,101,105,103,104,116,0,108,101,102,116,0,115,104, +111,119,108,105,110,101,110,114,115,0,116,97,98,110,117,109,98,101,114,0,99,117,114,114,116,97,98,95,115,101,116,0, +115,104,111,119,115,121,110,116,97,120,0,111,118,101,114,119,114,105,116,101,0,112,105,120,95,112,101,114,95,108,105,110, +101,0,116,120,116,115,99,114,111,108,108,0,116,120,116,98,97,114,0,119,111,114,100,119,114,97,112,0,100,111,112,108, +117,103,105,110,115,0,42,112,121,95,100,114,97,119,0,42,112,121,95,101,118,101,110,116,0,42,112,121,95,98,117,116, +116,111,110,0,42,112,121,95,98,114,111,119,115,101,114,99,97,108,108,98,97,99,107,0,42,112,121,95,103,108,111,98, +97,108,100,105,99,116,0,108,97,115,116,115,112,97,99,101,0,115,99,114,105,112,116,110,97,109,101,91,50,53,54,93, +0,115,99,114,105,112,116,97,114,103,91,50,53,54,93,0,42,115,99,114,105,112,116,0,42,98,117,116,95,114,101,102, +115,0,114,101,100,114,97,119,115,0,42,105,100,0,97,115,112,101,99,116,0,42,99,117,114,102,111,110,116,0,42,101, +100,105,116,116,114,101,101,0,116,114,101,101,116,121,112,101,0,42,102,105,108,101,115,0,97,99,116,105,118,101,95,102, +105,108,101,0,110,117,109,116,105,108,101,115,120,0,110,117,109,116,105,108,101,115,121,0,115,101,108,115,116,97,116,101, +0,118,105,101,119,114,101,99,116,0,98,111,111,107,109,97,114,107,114,101,99,116,0,115,99,114,111,108,108,112,111,115, +0,115,99,114,111,108,108,104,101,105,103,104,116,0,115,99,114,111,108,108,97,114,101,97,0,97,99,116,105,118,101,95, +98,111,111,107,109,97,114,107,0,112,114,118,95,119,0,112,114,118,95,104,0,42,105,109,103,0,111,117,116,108,105,110, +101,91,52,93,0,110,101,117,116,114,97,108,91,52,93,0,97,99,116,105,111,110,91,52,93,0,115,101,116,116,105,110, +103,91,52,93,0,115,101,116,116,105,110,103,49,91,52,93,0,115,101,116,116,105,110,103,50,91,52,93,0,110,117,109, +91,52,93,0,116,101,120,116,102,105,101,108,100,91,52,93,0,116,101,120,116,102,105,101,108,100,95,104,105,91,52,93, +0,112,111,112,117,112,91,52,93,0,116,101,120,116,91,52,93,0,116,101,120,116,95,104,105,91,52,93,0,109,101,110, +117,95,98,97,99,107,91,52,93,0,109,101,110,117,95,105,116,101,109,91,52,93,0,109,101,110,117,95,104,105,108,105, +116,101,91,52,93,0,109,101,110,117,95,116,101,120,116,91,52,93,0,109,101,110,117,95,116,101,120,116,95,104,105,91, +52,93,0,98,117,116,95,100,114,97,119,116,121,112,101,0,105,99,111,110,102,105,108,101,91,56,48,93,0,98,97,99, +107,91,52,93,0,104,101,97,100,101,114,91,52,93,0,112,97,110,101,108,91,52,93,0,115,104,97,100,101,49,91,52, +93,0,115,104,97,100,101,50,91,52,93,0,104,105,108,105,116,101,91,52,93,0,103,114,105,100,91,52,93,0,119,105, +114,101,91,52,93,0,115,101,108,101,99,116,91,52,93,0,108,97,109,112,91,52,93,0,97,99,116,105,118,101,91,52, +93,0,103,114,111,117,112,91,52,93,0,103,114,111,117,112,95,97,99,116,105,118,101,91,52,93,0,116,114,97,110,115, +102,111,114,109,91,52,93,0,118,101,114,116,101,120,91,52,93,0,118,101,114,116,101,120,95,115,101,108,101,99,116,91, +52,93,0,101,100,103,101,91,52,93,0,101,100,103,101,95,115,101,108,101,99,116,91,52,93,0,101,100,103,101,95,115, +101,97,109,91,52,93,0,101,100,103,101,95,115,104,97,114,112,91,52,93,0,101,100,103,101,95,102,97,99,101,115,101, +108,91,52,93,0,102,97,99,101,91,52,93,0,102,97,99,101,95,115,101,108,101,99,116,91,52,93,0,102,97,99,101, +95,100,111,116,91,52,93,0,110,111,114,109,97,108,91,52,93,0,98,111,110,101,95,115,111,108,105,100,91,52,93,0, +98,111,110,101,95,112,111,115,101,91,52,93,0,115,116,114,105,112,91,52,93,0,115,116,114,105,112,95,115,101,108,101, +99,116,91,52,93,0,99,102,114,97,109,101,91,52,93,0,118,101,114,116,101,120,95,115,105,122,101,0,102,97,99,101, +100,111,116,95,115,105,122,101,0,98,112,97,100,91,50,93,0,115,121,110,116,97,120,108,91,52,93,0,115,121,110,116, +97,120,110,91,52,93,0,115,121,110,116,97,120,98,91,52,93,0,115,121,110,116,97,120,118,91,52,93,0,115,121,110, +116,97,120,99,91,52,93,0,109,111,118,105,101,91,52,93,0,105,109,97,103,101,91,52,93,0,115,99,101,110,101,91, +52,93,0,97,117,100,105,111,91,52,93,0,101,102,102,101,99,116,91,52,93,0,112,108,117,103,105,110,91,52,93,0, +116,114,97,110,115,105,116,105,111,110,91,52,93,0,109,101,116,97,91,52,93,0,101,100,105,116,109,101,115,104,95,97, +99,116,105,118,101,91,52,93,0,104,97,110,100,108,101,95,118,101,114,116,101,120,91,52,93,0,104,97,110,100,108,101, +95,118,101,114,116,101,120,95,115,101,108,101,99,116,91,52,93,0,104,97,110,100,108,101,95,118,101,114,116,101,120,95, +115,105,122,101,0,104,112,97,100,91,55,93,0,115,111,108,105,100,91,52,93,0,116,117,105,0,116,98,117,116,115,0, +116,118,51,100,0,116,102,105,108,101,0,116,105,112,111,0,116,105,110,102,111,0,116,115,110,100,0,116,97,99,116,0, +116,110,108,97,0,116,115,101,113,0,116,105,109,97,0,116,105,109,97,115,101,108,0,116,101,120,116,0,116,111,111,112, +115,0,116,116,105,109,101,0,116,110,111,100,101,0,116,97,114,109,91,50,48,93,0,98,112,97,100,91,52,93,0,98, +112,97,100,49,91,52,93,0,115,112,101,99,91,52,93,0,100,117,112,102,108,97,103,0,115,97,118,101,116,105,109,101, +0,116,101,109,112,100,105,114,91,49,54,48,93,0,102,111,110,116,100,105,114,91,49,54,48,93,0,114,101,110,100,101, +114,100,105,114,91,49,54,48,93,0,116,101,120,116,117,100,105,114,91,49,54,48,93,0,112,108,117,103,116,101,120,100, +105,114,91,49,54,48,93,0,112,108,117,103,115,101,113,100,105,114,91,49,54,48,93,0,112,121,116,104,111,110,100,105, +114,91,49,54,48,93,0,115,111,117,110,100,100,105,114,91,49,54,48,93,0,121,102,101,120,112,111,114,116,100,105,114, +91,49,54,48,93,0,118,101,114,115,105,111,110,115,0,118,114,109,108,102,108,97,103,0,103,97,109,101,102,108,97,103, +115,0,119,104,101,101,108,108,105,110,101,115,99,114,111,108,108,0,117,105,102,108,97,103,0,108,97,110,103,117,97,103, +101,0,117,115,101,114,112,114,101,102,0,118,105,101,119,122,111,111,109,0,99,111,110,115,111,108,101,95,98,117,102,102, +101,114,0,99,111,110,115,111,108,101,95,111,117,116,0,109,105,120,98,117,102,115,105,122,101,0,102,111,110,116,115,105, +122,101,0,101,110,99,111,100,105,110,103,0,116,114,97,110,115,111,112,116,115,0,109,101,110,117,116,104,114,101,115,104, +111,108,100,49,0,109,101,110,117,116,104,114,101,115,104,111,108,100,50,0,102,111,110,116,110,97,109,101,91,50,53,54, +93,0,116,104,101,109,101,115,0,117,110,100,111,115,116,101,112,115,0,117,110,100,111,109,101,109,111,114,121,0,103,112, +95,109,97,110,104,97,116,116,101,110,100,105,115,116,0,103,112,95,101,117,99,108,105,100,101,97,110,100,105,115,116,0, +103,112,95,101,114,97,115,101,114,0,103,112,95,115,101,116,116,105,110,103,115,0,116,98,95,108,101,102,116,109,111,117, +115,101,0,116,98,95,114,105,103,104,116,109,111,117,115,101,0,108,105,103,104,116,91,51,93,0,116,119,95,104,111,116, +115,112,111,116,0,116,119,95,102,108,97,103,0,116,119,95,104,97,110,100,108,101,115,105,122,101,0,116,119,95,115,105, +122,101,0,116,101,120,116,105,109,101,111,117,116,0,116,101,120,99,111,108,108,101,99,116,114,97,116,101,0,109,101,109, +99,97,99,104,101,108,105,109,105,116,0,112,114,101,102,101,116,99,104,102,114,97,109,101,115,0,102,114,97,109,101,115, +101,114,118,101,114,112,111,114,116,0,112,97,100,95,114,111,116,95,97,110,103,108,101,0,111,98,99,101,110,116,101,114, +95,100,105,97,0,114,118,105,115,105,122,101,0,114,118,105,98,114,105,103,104,116,0,114,101,99,101,110,116,95,102,105, +108,101,115,0,115,109,111,111,116,104,95,118,105,101,119,116,120,0,103,108,114,101,115,108,105,109,105,116,0,110,100,111, +102,95,112,97,110,0,110,100,111,102,95,114,111,116,97,116,101,0,99,117,114,115,115,105,122,101,0,112,97,100,91,56, +93,0,118,101,114,115,101,109,97,115,116,101,114,91,49,54,48,93,0,118,101,114,115,101,117,115,101,114,91,49,54,48, +93,0,103,108,97,108,112,104,97,99,108,105,112,0,97,117,116,111,107,101,121,95,102,108,97,103,0,99,111,98,97,95, +119,101,105,103,104,116,0,118,101,114,116,98,97,115,101,0,101,100,103,101,98,97,115,101,0,97,114,101,97,98,97,115, +101,0,42,115,99,101,110,101,0,101,110,100,120,0,101,110,100,121,0,115,105,122,101,120,0,115,105,122,101,121,0,115, +99,101,110,101,110,114,0,115,99,114,101,101,110,110,114,0,102,117,108,108,0,109,97,105,110,119,105,110,0,119,105,110, +97,107,116,0,104,97,110,100,108,101,114,91,56,93,0,42,110,101,119,118,0,118,101,99,0,42,118,49,0,42,118,50, +0,112,97,110,101,108,110,97,109,101,91,54,52,93,0,116,97,98,110,97,109,101,91,54,52,93,0,100,114,97,119,110, +97,109,101,91,54,52,93,0,111,102,115,120,0,111,102,115,121,0,99,111,110,116,114,111,108,0,115,110,97,112,0,111, +108,100,95,111,102,115,120,0,111,108,100,95,111,102,115,121,0,115,111,114,116,99,111,117,110,116,101,114,0,42,112,97, +110,101,108,116,97,98,0,42,118,51,0,42,118,52,0,42,102,117,108,108,0,119,105,110,109,97,116,91,52,93,91,52, +93,0,104,101,97,100,114,99,116,0,119,105,110,114,99,116,0,104,101,97,100,119,105,110,0,119,105,110,0,104,101,97, +100,101,114,116,121,112,101,0,98,117,116,115,112,97,99,101,116,121,112,101,0,119,105,110,120,0,119,105,110,121,0,104, +101,97,100,95,115,119,97,112,0,104,101,97,100,95,101,113,117,97,108,0,119,105,110,95,115,119,97,112,0,119,105,110, +95,101,113,117,97,108,0,104,101,97,100,98,117,116,108,101,110,0,104,101,97,100,98,117,116,111,102,115,0,99,117,114, +115,111,114,0,115,112,97,99,101,100,97,116,97,0,117,105,98,108,111,99,107,115,0,112,97,110,101,108,115,0,115,117, +98,118,115,116,114,91,52,93,0,115,117,98,118,101,114,115,105,111,110,0,112,97,100,115,0,109,105,110,118,101,114,115, +105,111,110,0,109,105,110,115,117,98,118,101,114,115,105,111,110,0,100,105,115,112,108,97,121,109,111,100,101,0,42,99, +117,114,115,99,114,101,101,110,0,42,99,117,114,115,99,101,110,101,0,102,105,108,101,102,108,97,103,115,0,103,108,111, +98,97,108,102,0,110,97,109,101,91,56,48,93,0,42,105,98,117,102,0,42,105,98,117,102,95,99,111,109,112,0,42, +115,101,49,0,42,115,101,50,0,42,115,101,51,0,110,114,0,98,111,116,116,111,109,0,114,105,103,104,116,0,120,111, +102,115,0,121,111,102,115,0,108,105,102,116,91,51,93,0,103,97,109,109,97,91,51,93,0,103,97,105,110,91,51,93, +0,115,97,116,117,114,97,116,105,111,110,0,42,103,117,105,0,100,105,114,91,49,54,48,93,0,100,111,110,101,0,115, +116,97,114,116,115,116,105,108,108,0,101,110,100,115,116,105,108,108,0,42,115,116,114,105,112,100,97,116,97,0,111,114, +120,0,111,114,121,0,42,99,114,111,112,0,42,116,114,97,110,115,102,111,114,109,0,42,99,111,108,111,114,95,98,97, +108,97,110,99,101,0,42,116,115,116,114,105,112,100,97,116,97,0,42,116,115,116,114,105,112,100,97,116,97,95,115,116, +97,114,116,115,116,105,108,108,0,42,116,115,116,114,105,112,100,97,116,97,95,101,110,100,115,116,105,108,108,0,42,105, +98,117,102,95,115,116,97,114,116,115,116,105,108,108,0,42,105,98,117,102,95,101,110,100,115,116,105,108,108,0,42,105, +110,115,116,97,110,99,101,95,112,114,105,118,97,116,101,95,100,97,116,97,0,42,42,99,117,114,114,101,110,116,95,112, +114,105,118,97,116,101,95,100,97,116,97,0,42,116,109,112,0,115,116,97,114,116,111,102,115,0,101,110,100,111,102,115, +0,109,97,99,104,105,110,101,0,115,116,97,114,116,100,105,115,112,0,101,110,100,100,105,115,112,0,109,117,108,0,104, +97,110,100,115,105,122,101,0,97,110,105,109,95,112,114,101,115,101,101,107,0,42,115,116,114,105,112,0,102,97,99,102, +48,0,102,97,99,102,49,0,42,115,101,113,49,0,42,115,101,113,50,0,42,115,101,113,51,0,115,101,113,98,97,115, +101,0,42,115,111,117,110,100,0,42,104,100,97,117,100,105,111,0,108,101,118,101,108,0,112,97,110,0,115,116,114,111, +98,101,0,42,101,102,102,101,99,116,100,97,116,97,0,97,110,105,109,95,115,116,97,114,116,111,102,115,0,97,110,105, +109,95,101,110,100,111,102,115,0,98,108,101,110,100,95,109,111,100,101,0,98,108,101,110,100,95,111,112,97,99,105,116, +121,0,42,111,108,100,98,97,115,101,112,0,42,112,97,114,115,101,113,0,42,115,101,113,98,97,115,101,112,0,109,101, +116,97,115,116,97,99,107,0,101,100,103,101,87,105,100,116,104,0,102,111,114,119,97,114,100,0,119,105,112,101,116,121, +112,101,0,102,77,105,110,105,0,102,67,108,97,109,112,0,102,66,111,111,115,116,0,100,68,105,115,116,0,100,81,117, +97,108,105,116,121,0,98,78,111,67,111,109,112,0,83,99,97,108,101,120,73,110,105,0,83,99,97,108,101,121,73,110, +105,0,83,99,97,108,101,120,70,105,110,0,83,99,97,108,101,121,70,105,110,0,120,73,110,105,0,120,70,105,110,0, +121,73,110,105,0,121,70,105,110,0,114,111,116,73,110,105,0,114,111,116,70,105,110,0,105,110,116,101,114,112,111,108, +97,116,105,111,110,0,42,102,114,97,109,101,77,97,112,0,103,108,111,98,97,108,83,112,101,101,100,0,108,97,115,116, +86,97,108,105,100,70,114,97,109,101,0,98,108,101,110,100,70,114,97,109,101,115,0,98,117,116,116,121,112,101,0,117, +115,101,114,106,105,116,0,115,116,97,0,116,111,116,112,97,114,116,0,110,111,114,109,102,97,99,0,111,98,102,97,99, +0,114,97,110,100,102,97,99,0,116,101,120,102,97,99,0,114,97,110,100,108,105,102,101,0,102,111,114,99,101,91,51, +93,0,118,101,99,116,115,105,122,101,0,109,97,120,108,101,110,0,100,101,102,118,101,99,91,51,93,0,109,117,108,116, +91,52,93,0,108,105,102,101,91,52,93,0,99,104,105,108,100,91,52,93,0,109,97,116,91,52,93,0,116,101,120,109, +97,112,0,99,117,114,109,117,108,116,0,115,116,97,116,105,99,115,116,101,112,0,111,109,97,116,0,116,105,109,101,116, +101,120,0,115,112,101,101,100,116,101,120,0,102,108,97,103,50,110,101,103,0,118,101,114,116,103,114,111,117,112,95,118, +0,118,103,114,111,117,112,110,97,109,101,91,51,50,93,0,118,103,114,111,117,112,110,97,109,101,95,118,91,51,50,93, +0,42,107,101,121,115,0,109,105,110,102,97,99,0,117,115,101,100,0,117,115,101,100,101,108,101,109,0,100,120,0,100, +121,0,108,105,110,107,0,111,116,121,112,101,0,111,108,100,0,42,112,111,105,110,0,42,111,108,100,112,111,105,110,0, +114,101,115,101,116,100,105,115,116,0,108,97,115,116,118,97,108,0,42,109,97,0,107,101,121,0,113,117,97,108,0,113, +117,97,108,50,0,116,97,114,103,101,116,78,97,109,101,91,51,50,93,0,116,111,103,103,108,101,78,97,109,101,91,51, +50,93,0,118,97,108,117,101,91,51,50,93,0,109,97,120,118,97,108,117,101,91,51,50,93,0,100,101,108,97,121,0, +100,117,114,97,116,105,111,110,0,109,97,116,101,114,105,97,108,78,97,109,101,91,51,50,93,0,100,97,109,112,116,105, +109,101,114,0,112,114,111,112,110,97,109,101,91,51,50,93,0,109,97,116,110,97,109,101,91,51,50,93,0,97,120,105, +115,102,108,97,103,0,42,102,114,111,109,79,98,106,101,99,116,0,115,117,98,106,101,99,116,91,51,50,93,0,98,111, +100,121,91,51,50,93,0,112,117,108,115,101,0,102,114,101,113,0,116,111,116,108,105,110,107,115,0,42,42,108,105,110, +107,115,0,116,97,112,0,106,111,121,105,110,100,101,120,0,97,120,105,115,95,115,105,110,103,108,101,0,97,120,105,115, +102,0,98,117,116,116,111,110,0,104,97,116,0,104,97,116,102,0,112,114,101,99,105,115,105,111,110,0,115,116,114,91, +49,50,56,93,0,109,111,100,117,108,101,91,54,52,93,0,42,109,121,110,101,119,0,105,110,112,117,116,115,0,116,111, +116,115,108,105,110,107,115,0,42,42,115,108,105,110,107,115,0,118,97,108,111,0,115,116,97,116,101,95,109,97,115,107, +0,42,97,99,116,0,102,114,97,109,101,80,114,111,112,91,51,50,93,0,98,108,101,110,100,105,110,0,112,114,105,111, +114,105,116,121,0,101,110,100,95,114,101,115,101,116,0,115,116,114,105,100,101,97,120,105,115,0,115,116,114,105,100,101, +108,101,110,103,116,104,0,115,110,100,110,114,0,112,97,100,49,91,50,93,0,109,97,107,101,99,111,112,121,0,99,111, +112,121,109,97,100,101,0,112,97,100,50,91,49,93,0,116,114,97,99,107,0,42,109,101,0,108,105,110,86,101,108,111, +99,105,116,121,91,51,93,0,97,110,103,86,101,108,111,99,105,116,121,91,51,93,0,108,111,99,97,108,102,108,97,103, +0,100,121,110,95,111,112,101,114,97,116,105,111,110,0,102,111,114,99,101,108,111,99,91,51,93,0,102,111,114,99,101, +114,111,116,91,51,93,0,108,105,110,101,97,114,118,101,108,111,99,105,116,121,91,51,93,0,97,110,103,117,108,97,114, +118,101,108,111,99,105,116,121,91,51,93,0,42,114,101,102,101,114,101,110,99,101,0,98,117,116,115,116,97,0,98,117, +116,101,110,100,0,109,105,110,0,109,97,120,0,118,105,115,105,102,97,99,0,114,111,116,100,97,109,112,0,109,105,110, +108,111,99,91,51,93,0,109,97,120,108,111,99,91,51,93,0,109,105,110,114,111,116,91,51,93,0,109,97,120,114,111, +116,91,51,93,0,109,97,116,112,114,111,112,91,51,50,93,0,100,105,115,116,114,105,98,117,116,105,111,110,0,105,110, +116,95,97,114,103,95,49,0,105,110,116,95,97,114,103,95,50,0,102,108,111,97,116,95,97,114,103,95,49,0,102,108, +111,97,116,95,97,114,103,95,50,0,116,111,80,114,111,112,78,97,109,101,91,51,50,93,0,42,116,111,79,98,106,101, +99,116,0,98,111,100,121,84,121,112,101,0,102,105,108,101,110,97,109,101,91,54,52,93,0,108,111,97,100,97,110,105, +110,97,109,101,91,54,52,93,0,105,110,116,95,97,114,103,0,102,108,111,97,116,95,97,114,103,0,103,111,0,97,99, +99,101,108,108,101,114,97,116,105,111,110,0,109,97,120,115,112,101,101,100,0,109,97,120,114,111,116,115,112,101,101,100, +0,109,97,120,116,105,108,116,115,112,101,101,100,0,116,105,108,116,100,97,109,112,0,115,112,101,101,100,100,97,109,112, +0,42,115,97,109,112,108,101,0,42,115,116,114,101,97,109,0,42,110,101,119,112,97,99,107,101,100,102,105,108,101,0, +42,115,110,100,95,115,111,117,110,100,0,112,97,110,110,105,110,103,0,97,116,116,101,110,117,97,116,105,111,110,0,112, +105,116,99,104,0,109,105,110,95,103,97,105,110,0,109,97,120,95,103,97,105,110,0,100,105,115,116,97,110,99,101,0, +115,116,114,101,97,109,108,101,110,0,99,104,97,110,110,101,108,115,0,104,105,103,104,112,114,105,111,0,112,97,100,91, +49,48,93,0,103,97,105,110,0,100,111,112,112,108,101,114,102,97,99,116,111,114,0,100,111,112,112,108,101,114,118,101, +108,111,99,105,116,121,0,110,117,109,115,111,117,110,100,115,98,108,101,110,100,101,114,0,110,117,109,115,111,117,110,100, +115,103,97,109,101,101,110,103,105,110,101,0,42,108,97,109,112,114,101,110,0,103,111,98,106,101,99,116,0,100,117,112, +108,105,95,111,102,115,91,51,93,0,99,104,105,108,100,98,97,115,101,0,114,111,108,108,0,104,101,97,100,91,51,93, +0,116,97,105,108,91,51,93,0,98,111,110,101,95,109,97,116,91,51,93,91,51,93,0,97,114,109,95,104,101,97,100, +91,51,93,0,97,114,109,95,116,97,105,108,91,51,93,0,97,114,109,95,109,97,116,91,52,93,91,52,93,0,120,119, +105,100,116,104,0,122,119,105,100,116,104,0,101,97,115,101,49,0,101,97,115,101,50,0,114,97,100,95,104,101,97,100, +0,114,97,100,95,116,97,105,108,0,98,111,110,101,98,97,115,101,0,99,104,97,105,110,98,97,115,101,0,112,97,116, +104,102,108,97,103,0,108,97,121,101,114,95,112,114,111,116,101,99,116,101,100,0,103,104,111,115,116,101,112,0,103,104, +111,115,116,115,105,122,101,0,103,104,111,115,116,116,121,112,101,0,112,97,116,104,115,105,122,101,0,103,104,111,115,116, +115,102,0,103,104,111,115,116,101,102,0,112,97,116,104,115,102,0,112,97,116,104,101,102,0,112,97,116,104,98,99,0, +112,97,116,104,97,99,0,99,111,110,115,116,102,108,97,103,0,105,107,102,108,97,103,0,115,101,108,101,99,116,102,108, +97,103,0,97,103,114,112,95,105,110,100,101,120,0,42,98,111,110,101,0,42,99,104,105,108,100,0,105,107,116,114,101, +101,0,42,98,95,98,111,110,101,95,109,97,116,115,0,42,100,117,97,108,95,113,117,97,116,0,42,98,95,98,111,110, +101,95,100,117,97,108,95,113,117,97,116,115,0,99,104,97,110,95,109,97,116,91,52,93,91,52,93,0,112,111,115,101, +95,109,97,116,91,52,93,91,52,93,0,112,111,115,101,95,104,101,97,100,91,51,93,0,112,111,115,101,95,116,97,105, +108,91,51,93,0,108,105,109,105,116,109,105,110,91,51,93,0,108,105,109,105,116,109,97,120,91,51,93,0,115,116,105, +102,102,110,101,115,115,91,51,93,0,105,107,115,116,114,101,116,99,104,0,42,99,117,115,116,111,109,0,99,104,97,110, +98,97,115,101,0,112,114,111,120,121,95,108,97,121,101,114,0,115,116,114,105,100,101,95,111,102,102,115,101,116,91,51, +93,0,99,121,99,108,105,99,95,111,102,102,115,101,116,91,51,93,0,97,103,114,111,117,112,115,0,97,99,116,105,118, +101,95,103,114,111,117,112,0,99,117,115,116,111,109,67,111,108,0,99,115,0,42,103,114,112,0,114,101,115,101,114,118, +101,100,49,0,103,114,111,117,112,115,0,97,99,116,105,118,101,95,109,97,114,107,101,114,0,97,99,116,110,114,0,97, +99,116,119,105,100,116,104,0,116,105,109,101,115,108,105,100,101,0,110,97,109,101,91,51,48,93,0,111,119,110,115,112, +97,99,101,0,116,97,114,115,112,97,99,101,0,101,110,102,111,114,99,101,0,104,101,97,100,116,97,105,108,0,42,116, +97,114,0,115,117,98,116,97,114,103,101,116,91,51,50,93,0,109,97,116,114,105,120,91,52,93,91,52,93,0,115,112, +97,99,101,0,42,112,114,111,112,0,116,97,114,110,117,109,0,116,97,114,103,101,116,115,0,105,116,101,114,97,116,105, +111,110,115,0,114,111,111,116,98,111,110,101,0,109,97,120,95,114,111,111,116,98,111,110,101,0,42,112,111,108,101,116, +97,114,0,112,111,108,101,115,117,98,116,97,114,103,101,116,91,51,50,93,0,112,111,108,101,97,110,103,108,101,0,111, +114,105,101,110,116,119,101,105,103,104,116,0,103,114,97,98,116,97,114,103,101,116,91,51,93,0,114,101,115,101,114,118, +101,100,50,0,109,105,110,109,97,120,102,108,97,103,0,115,116,117,99,107,0,99,97,99,104,101,91,51,93,0,108,111, +99,107,102,108,97,103,0,102,111,108,108,111,119,102,108,97,103,0,118,111,108,109,111,100,101,0,112,108,97,110,101,0, +111,114,103,108,101,110,103,116,104,0,98,117,108,103,101,0,112,105,118,88,0,112,105,118,89,0,112,105,118,90,0,97, +120,88,0,97,120,89,0,97,120,90,0,109,105,110,76,105,109,105,116,91,54,93,0,109,97,120,76,105,109,105,116,91, +54,93,0,101,120,116,114,97,70,122,0,105,110,118,109,97,116,91,52,93,91,52,93,0,102,114,111,109,0,116,111,0, +109,97,112,91,51,93,0,101,120,112,111,0,102,114,111,109,95,109,105,110,91,51,93,0,102,114,111,109,95,109,97,120, +91,51,93,0,116,111,95,109,105,110,91,51,93,0,116,111,95,109,97,120,91,51,93,0,122,109,105,110,0,122,109,97, +120,0,112,97,100,91,57,93,0,99,104,97,110,110,101,108,91,51,50,93,0,110,111,95,114,111,116,95,97,120,105,115, +0,115,116,114,105,100,101,95,97,120,105,115,0,99,117,114,109,111,100,0,97,99,116,115,116,97,114,116,0,97,99,116, +101,110,100,0,97,99,116,111,102,102,115,0,115,116,114,105,100,101,108,101,110,0,98,108,101,110,100,111,117,116,0,115, +116,114,105,100,101,99,104,97,110,110,101,108,91,51,50,93,0,111,102,102,115,95,98,111,110,101,91,51,50,93,0,104, +97,115,105,110,112,117,116,0,104,97,115,111,117,116,112,117,116,0,100,97,116,97,116,121,112,101,0,115,111,99,107,101, +116,116,121,112,101,0,42,110,101,119,95,115,111,99,107,0,110,115,0,108,105,109,105,116,0,115,116,97,99,107,95,105, +110,100,101,120,0,105,110,116,101,114,110,0,115,116,97,99,107,95,105,110,100,101,120,95,101,120,116,0,108,111,99,120, +0,108,111,99,121,0,111,119,110,95,105,110,100,101,120,0,116,111,95,105,110,100,101,120,0,42,116,111,115,111,99,107, +0,42,108,105,110,107,0,42,110,101,119,95,110,111,100,101,0,117,115,101,114,110,97,109,101,91,51,50,93,0,108,97, +115,116,121,0,111,117,116,112,117,116,115,0,42,115,116,111,114,97,103,101,0,109,105,110,105,119,105,100,116,104,0,99, +117,115,116,111,109,49,0,99,117,115,116,111,109,50,0,99,117,115,116,111,109,51,0,99,117,115,116,111,109,52,0,110, +101,101,100,95,101,120,101,99,0,101,120,101,99,0,116,111,116,114,0,98,117,116,114,0,112,114,118,114,0,42,116,121, +112,101,105,110,102,111,0,42,102,114,111,109,110,111,100,101,0,42,116,111,110,111,100,101,0,42,102,114,111,109,115,111, +99,107,0,110,111,100,101,115,0,108,105,110,107,115,0,42,115,116,97,99,107,0,42,116,104,114,101,97,100,115,116,97, +99,107,0,105,110,105,116,0,115,116,97,99,107,115,105,122,101,0,99,117,114,95,105,110,100,101,120,0,97,108,108,116, +121,112,101,115,0,42,111,119,110,116,121,112,101,0,42,115,101,108,105,110,0,42,115,101,108,111,117,116,0,40,42,116, +105,109,101,99,117,114,115,111,114,41,40,41,0,40,42,115,116,97,116,115,95,100,114,97,119,41,40,41,0,40,42,116, +101,115,116,95,98,114,101,97,107,41,40,41,0,99,121,99,108,105,99,0,109,111,118,105,101,0,115,97,109,112,108,101, +115,0,109,105,110,115,112,101,101,100,0,112,101,114,99,101,110,116,120,0,112,101,114,99,101,110,116,121,0,98,111,107, +101,104,0,99,117,114,118,101,100,0,105,109,97,103,101,95,105,110,95,119,105,100,116,104,0,105,109,97,103,101,95,105, +110,95,104,101,105,103,104,116,0,99,101,110,116,101,114,95,120,0,99,101,110,116,101,114,95,121,0,115,112,105,110,0, +105,116,101,114,0,119,114,97,112,0,115,105,103,109,97,95,99,111,108,111,114,0,115,105,103,109,97,95,115,112,97,99, +101,0,104,117,101,0,115,97,116,0,116,49,0,116,50,0,116,51,0,102,115,116,114,101,110,103,116,104,0,102,97,108, +112,104,97,0,107,101,121,91,52,93,0,120,49,0,120,50,0,121,49,0,121,50,0,99,111,108,110,97,109,101,91,51, +50,93,0,98,107,116,121,112,101,0,114,111,116,97,116,105,111,110,0,112,114,101,118,105,101,119,0,103,97,109,99,111, +0,110,111,95,122,98,117,102,0,102,115,116,111,112,0,109,97,120,98,108,117,114,0,98,116,104,114,101,115,104,0,42, +100,105,99,116,0,42,110,111,100,101,0,97,110,103,108,101,95,111,102,115,0,99,111,108,109,111,100,0,109,105,120,0, +116,104,114,101,115,104,111,108,100,0,102,97,100,101,0,109,0,99,0,106,105,116,0,112,114,111,106,0,102,105,116,0, +115,104,111,114,116,121,0,109,105,110,116,97,98,108,101,0,109,97,120,116,97,98,108,101,0,101,120,116,95,105,110,91, +50,93,0,101,120,116,95,111,117,116,91,50,93,0,42,99,117,114,118,101,0,42,116,97,98,108,101,0,42,112,114,101, +109,117,108,116,97,98,108,101,0,99,117,114,114,0,99,108,105,112,114,0,99,109,91,52,93,0,98,108,97,99,107,91, +51,93,0,119,104,105,116,101,91,51,93,0,98,119,109,117,108,91,51,93,0,115,97,109,112,108,101,91,51,93,0,111, +102,102,115,101,116,91,50,93,0,105,110,110,101,114,114,97,100,105,117,115,0,114,97,116,101,0,114,103,98,91,51,93, +0,99,108,111,110,101,0,97,99,116,105,118,101,95,114,110,100,0,97,99,116,105,118,101,95,99,108,111,110,101,0,97, +99,116,105,118,101,95,109,97,115,107,0,42,108,97,121,101,114,115,0,116,111,116,108,97,121,101,114,0,109,97,120,108, +97,121,101,114,0,116,111,116,115,105,122,101,0,42,112,111,111,108,0,101,100,105,116,102,108,97,103,0,118,101,108,91, +51,93,0,114,111,116,91,52,93,0,97,118,101,91,51,93,0,110,117,109,0,112,97,114,101,110,116,0,112,97,91,52, +93,0,119,91,52,93,0,102,117,118,91,52,93,0,102,111,102,102,115,101,116,0,114,97,110,100,91,51,93,0,42,115, +116,105,99,107,95,111,98,0,112,114,101,118,95,115,116,97,116,101,0,42,104,97,105,114,0,105,95,114,111,116,91,52, +93,0,114,95,114,111,116,91,52,93,0,114,95,97,118,101,91,51,93,0,114,95,118,101,91,51,93,0,100,105,101,116, +105,109,101,0,98,97,110,107,0,115,105,122,101,109,117,108,0,110,117,109,95,100,109,99,97,99,104,101,0,98,112,105, +0,97,108,105,118,101,0,108,111,111,112,0,100,105,115,116,114,0,112,104,121,115,116,121,112,101,0,114,111,116,109,111, +100,101,0,97,118,101,109,111,100,101,0,114,101,97,99,116,101,118,101,110,116,0,100,114,97,119,0,100,114,97,119,95, +97,115,0,100,114,97,119,95,115,105,122,101,0,99,104,105,108,100,116,121,112,101,0,100,114,97,119,95,115,116,101,112, +0,114,101,110,95,115,116,101,112,0,104,97,105,114,95,115,116,101,112,0,107,101,121,115,95,115,116,101,112,0,97,100, +97,112,116,95,97,110,103,108,101,0,97,100,97,112,116,95,112,105,120,0,114,111,116,102,114,111,109,0,105,110,116,101, +103,114,97,116,111,114,0,110,98,101,116,119,101,101,110,0,98,111,105,100,110,101,105,103,104,98,111,117,114,115,0,98, +98,95,97,108,105,103,110,0,98,98,95,117,118,95,115,112,108,105,116,0,98,98,95,97,110,105,109,0,98,98,95,115, +112,108,105,116,95,111,102,102,115,101,116,0,98,98,95,116,105,108,116,0,98,98,95,114,97,110,100,95,116,105,108,116, +0,98,98,95,111,102,102,115,101,116,91,50,93,0,115,105,109,112,108,105,102,121,95,102,108,97,103,0,115,105,109,112, +108,105,102,121,95,114,101,102,115,105,122,101,0,115,105,109,112,108,105,102,121,95,114,97,116,101,0,115,105,109,112,108, +105,102,121,95,116,114,97,110,115,105,116,105,111,110,0,115,105,109,112,108,105,102,121,95,118,105,101,119,112,111,114,116, +0,116,105,109,101,116,119,101,97,107,0,106,105,116,102,97,99,0,107,101,121,101,100,95,116,105,109,101,0,101,102,102, +95,104,97,105,114,0,103,114,105,100,95,114,101,115,0,112,97,114,116,102,97,99,0,116,97,110,102,97,99,0,116,97, +110,112,104,97,115,101,0,114,101,97,99,116,102,97,99,0,97,118,101,102,97,99,0,112,104,97,115,101,102,97,99,0, +114,97,110,100,114,111,116,102,97,99,0,114,97,110,100,112,104,97,115,101,102,97,99,0,114,97,110,100,115,105,122,101, +0,114,101,97,99,116,115,104,97,112,101,0,97,99,99,91,51,93,0,100,114,97,103,102,97,99,0,98,114,111,119,110, +102,97,99,0,100,97,109,112,102,97,99,0,97,98,115,108,101,110,103,116,104,0,114,97,110,100,108,101,110,103,116,104, +0,99,104,105,108,100,95,110,98,114,0,114,101,110,95,99,104,105,108,100,95,110,98,114,0,112,97,114,101,110,116,115, +0,99,104,105,108,100,115,105,122,101,0,99,104,105,108,100,114,97,110,100,115,105,122,101,0,99,104,105,108,100,114,97, +100,0,99,104,105,108,100,102,108,97,116,0,99,104,105,108,100,115,112,114,101,97,100,0,99,108,117,109,112,102,97,99, +0,99,108,117,109,112,112,111,119,0,114,111,117,103,104,49,0,114,111,117,103,104,49,95,115,105,122,101,0,114,111,117, +103,104,50,0,114,111,117,103,104,50,95,115,105,122,101,0,114,111,117,103,104,50,95,116,104,114,101,115,0,114,111,117, +103,104,95,101,110,100,0,114,111,117,103,104,95,101,110,100,95,115,104,97,112,101,0,98,114,97,110,99,104,95,116,104, +114,101,115,0,100,114,97,119,95,108,105,110,101,91,50,93,0,109,97,120,95,108,97,116,95,97,99,99,0,109,97,120, +95,116,97,110,95,97,99,99,0,97,118,101,114,97,103,101,95,118,101,108,0,98,97,110,107,105,110,103,0,109,97,120, +95,98,97,110,107,0,103,114,111,117,110,100,122,0,98,111,105,100,102,97,99,91,56,93,0,98,111,105,100,114,117,108, +101,91,56,93,0,42,101,102,102,95,103,114,111,117,112,0,42,100,117,112,95,111,98,0,42,98,98,95,111,98,0,42, +112,100,50,0,42,112,97,114,116,0,42,101,100,105,116,0,42,42,112,97,116,104,99,97,99,104,101,0,42,42,99,104, +105,108,100,99,97,99,104,101,0,112,97,116,104,99,97,99,104,101,98,117,102,115,0,99,104,105,108,100,99,97,99,104, +101,98,117,102,115,0,42,116,97,114,103,101,116,95,111,98,0,42,107,101,121,101,100,95,111,98,0,42,108,97,116,116, +105,99,101,0,101,102,102,101,99,116,111,114,115,0,114,101,97,99,116,101,118,101,110,116,115,0,116,111,116,99,104,105, +108,100,0,116,111,116,99,97,99,104,101,100,0,116,111,116,99,104,105,108,100,99,97,99,104,101,0,116,97,114,103,101, +116,95,112,115,121,115,0,107,101,121,101,100,95,112,115,121,115,0,116,111,116,107,101,121,101,100,0,98,97,107,101,115, +112,97,99,101,0,98,98,95,117,118,110,97,109,101,91,51,93,91,51,50,93,0,118,103,114,111,117,112,91,49,50,93, +0,118,103,95,110,101,103,0,114,116,51,0,42,114,101,110,100,101,114,100,97,116,97,0,42,99,97,99,104,101,0,67, +100,105,115,0,67,118,105,0,91,51,93,0,115,116,114,117,99,116,117,114,97,108,0,98,101,110,100,105,110,103,0,109, +97,120,95,98,101,110,100,0,109,97,120,95,115,116,114,117,99,116,0,109,97,120,95,115,104,101,97,114,0,97,118,103, +95,115,112,114,105,110,103,95,108,101,110,0,116,105,109,101,115,99,97,108,101,0,101,102,102,95,102,111,114,99,101,95, +115,99,97,108,101,0,101,102,102,95,119,105,110,100,95,115,99,97,108,101,0,115,105,109,95,116,105,109,101,95,111,108, +100,0,115,116,101,112,115,80,101,114,70,114,97,109,101,0,112,114,101,114,111,108,108,0,109,97,120,115,112,114,105,110, +103,108,101,110,0,115,111,108,118,101,114,95,116,121,112,101,0,118,103,114,111,117,112,95,98,101,110,100,0,118,103,114, +111,117,112,95,109,97,115,115,0,118,103,114,111,117,112,95,115,116,114,117,99,116,0,112,114,101,115,101,116,115,0,42, +99,111,108,108,105,115,105,111,110,95,108,105,115,116,0,101,112,115,105,108,111,110,0,115,101,108,102,95,102,114,105,99, +116,105,111,110,0,115,101,108,102,101,112,115,105,108,111,110,0,115,101,108,102,95,108,111,111,112,95,99,111,117,110,116, +0,108,111,111,112,95,99,111,117,110,116,0,112,114,101,115,115,117,114,101,0,42,112,111,105,110,116,115,0,116,111,116, +112,111,105,110,116,115,0,116,104,105,99,107,110,101,115,115,0,115,116,114,111,107,101,115,0,102,114,97,109,101,110,117, +109,0,42,97,99,116,102,114,97,109,101,0,103,115,116,101,112,0,105,110,102,111,91,49,50,56,93,0,115,98,117,102, +102,101,114,95,115,105,122,101,0,115,98,117,102,102,101,114,95,115,102,108,97,103,0,42,115,98,117,102,102,101,114,0, +0,0,0,84,89,80,69,100,1,0,0,99,104,97,114,0,117,99,104,97,114,0,115,104,111,114,116,0,117,115,104,111, +114,116,0,105,110,116,0,108,111,110,103,0,117,108,111,110,103,0,102,108,111,97,116,0,100,111,117,98,108,101,0,118, +111,105,100,0,76,105,110,107,0,76,105,110,107,68,97,116,97,0,76,105,115,116,66,97,115,101,0,118,101,99,50,115, +0,118,101,99,50,105,0,118,101,99,50,102,0,118,101,99,50,100,0,118,101,99,51,105,0,118,101,99,51,102,0,118, +101,99,51,100,0,118,101,99,52,105,0,118,101,99,52,102,0,118,101,99,52,100,0,114,99,116,105,0,114,99,116,102, +0,73,68,80,114,111,112,101,114,116,121,68,97,116,97,0,73,68,80,114,111,112,101,114,116,121,0,73,68,0,76,105, +98,114,97,114,121,0,70,105,108,101,68,97,116,97,0,80,114,101,118,105,101,119,73,109,97,103,101,0,73,112,111,68, +114,105,118,101,114,0,79,98,106,101,99,116,0,73,112,111,67,117,114,118,101,0,66,80,111,105,110,116,0,66,101,122, +84,114,105,112,108,101,0,73,112,111,0,75,101,121,66,108,111,99,107,0,75,101,121,0,83,99,114,105,112,116,76,105, +110,107,0,84,101,120,116,76,105,110,101,0,84,101,120,116,77,97,114,107,101,114,0,84,101,120,116,0,80,97,99,107, +101,100,70,105,108,101,0,67,97,109,101,114,97,0,73,109,97,103,101,85,115,101,114,0,73,109,97,103,101,0,71,80, +85,84,101,120,116,117,114,101,0,97,110,105,109,0,82,101,110,100,101,114,82,101,115,117,108,116,0,77,84,101,120,0, +84,101,120,0,80,108,117,103,105,110,84,101,120,0,67,66,68,97,116,97,0,67,111,108,111,114,66,97,110,100,0,69, +110,118,77,97,112,0,73,109,66,117,102,0,98,78,111,100,101,84,114,101,101,0,84,101,120,77,97,112,112,105,110,103, +0,76,97,109,112,0,67,117,114,118,101,77,97,112,112,105,110,103,0,87,97,118,101,0,77,97,116,101,114,105,97,108, +0,71,114,111,117,112,0,86,70,111,110,116,0,86,70,111,110,116,68,97,116,97,0,77,101,116,97,69,108,101,109,0, +66,111,117,110,100,66,111,120,0,77,101,116,97,66,97,108,108,0,78,117,114,98,0,67,104,97,114,73,110,102,111,0, +84,101,120,116,66,111,120,0,67,117,114,118,101,0,80,97,116,104,0,77,101,115,104,0,77,70,97,99,101,0,77,84, +70,97,99,101,0,84,70,97,99,101,0,77,86,101,114,116,0,77,69,100,103,101,0,77,68,101,102,111,114,109,86,101, +114,116,0,77,67,111,108,0,77,83,116,105,99,107,121,0,77,83,101,108,101,99,116,0,67,117,115,116,111,109,68,97, +116,97,0,77,117,108,116,105,114,101,115,0,80,97,114,116,105,97,108,86,105,115,105,98,105,108,105,116,121,0,77,68, +101,102,111,114,109,87,101,105,103,104,116,0,77,84,101,120,80,111,108,121,0,77,76,111,111,112,85,86,0,77,76,111, +111,112,67,111,108,0,77,70,108,111,97,116,80,114,111,112,101,114,116,121,0,77,73,110,116,80,114,111,112,101,114,116, +121,0,77,83,116,114,105,110,103,80,114,111,112,101,114,116,121,0,79,114,105,103,83,112,97,99,101,70,97,99,101,0, +77,117,108,116,105,114,101,115,67,111,108,0,77,117,108,116,105,114,101,115,67,111,108,70,97,99,101,0,77,117,108,116, +105,114,101,115,70,97,99,101,0,77,117,108,116,105,114,101,115,69,100,103,101,0,77,117,108,116,105,114,101,115,76,101, +118,101,108,0,77,117,108,116,105,114,101,115,77,97,112,78,111,100,101,0,77,111,100,105,102,105,101,114,68,97,116,97, +0,83,117,98,115,117,114,102,77,111,100,105,102,105,101,114,68,97,116,97,0,76,97,116,116,105,99,101,77,111,100,105, +102,105,101,114,68,97,116,97,0,67,117,114,118,101,77,111,100,105,102,105,101,114,68,97,116,97,0,66,117,105,108,100, +77,111,100,105,102,105,101,114,68,97,116,97,0,77,97,115,107,77,111,100,105,102,105,101,114,68,97,116,97,0,65,114, +114,97,121,77,111,100,105,102,105,101,114,68,97,116,97,0,77,105,114,114,111,114,77,111,100,105,102,105,101,114,68,97, +116,97,0,69,100,103,101,83,112,108,105,116,77,111,100,105,102,105,101,114,68,97,116,97,0,66,101,118,101,108,77,111, +100,105,102,105,101,114,68,97,116,97,0,66,77,101,115,104,77,111,100,105,102,105,101,114,68,97,116,97,0,68,105,115, +112,108,97,99,101,77,111,100,105,102,105,101,114,68,97,116,97,0,85,86,80,114,111,106,101,99,116,77,111,100,105,102, +105,101,114,68,97,116,97,0,68,101,99,105,109,97,116,101,77,111,100,105,102,105,101,114,68,97,116,97,0,83,109,111, +111,116,104,77,111,100,105,102,105,101,114,68,97,116,97,0,67,97,115,116,77,111,100,105,102,105,101,114,68,97,116,97, +0,87,97,118,101,77,111,100,105,102,105,101,114,68,97,116,97,0,65,114,109,97,116,117,114,101,77,111,100,105,102,105, +101,114,68,97,116,97,0,72,111,111,107,77,111,100,105,102,105,101,114,68,97,116,97,0,83,111,102,116,98,111,100,121, +77,111,100,105,102,105,101,114,68,97,116,97,0,67,108,111,116,104,77,111,100,105,102,105,101,114,68,97,116,97,0,67, +108,111,116,104,0,67,108,111,116,104,83,105,109,83,101,116,116,105,110,103,115,0,67,108,111,116,104,67,111,108,108,83, +101,116,116,105,110,103,115,0,80,111,105,110,116,67,97,99,104,101,0,67,111,108,108,105,115,105,111,110,77,111,100,105, +102,105,101,114,68,97,116,97,0,66,86,72,84,114,101,101,0,83,117,114,102,97,99,101,77,111,100,105,102,105,101,114, +68,97,116,97,0,68,101,114,105,118,101,100,77,101,115,104,0,66,86,72,84,114,101,101,70,114,111,109,77,101,115,104, +0,66,111,111,108,101,97,110,77,111,100,105,102,105,101,114,68,97,116,97,0,77,68,101,102,73,110,102,108,117,101,110, +99,101,0,77,68,101,102,67,101,108,108,0,77,101,115,104,68,101,102,111,114,109,77,111,100,105,102,105,101,114,68,97, +116,97,0,80,97,114,116,105,99,108,101,83,121,115,116,101,109,77,111,100,105,102,105,101,114,68,97,116,97,0,80,97, +114,116,105,99,108,101,83,121,115,116,101,109,0,80,97,114,116,105,99,108,101,73,110,115,116,97,110,99,101,77,111,100, +105,102,105,101,114,68,97,116,97,0,69,120,112,108,111,100,101,77,111,100,105,102,105,101,114,68,97,116,97,0,70,108, +117,105,100,115,105,109,77,111,100,105,102,105,101,114,68,97,116,97,0,70,108,117,105,100,115,105,109,83,101,116,116,105, +110,103,115,0,83,104,114,105,110,107,119,114,97,112,77,111,100,105,102,105,101,114,68,97,116,97,0,83,105,109,112,108, +101,68,101,102,111,114,109,77,111,100,105,102,105,101,114,68,97,116,97,0,76,97,116,116,105,99,101,0,98,68,101,102, +111,114,109,71,114,111,117,112,0,98,65,99,116,105,111,110,0,98,80,111,115,101,0,66,117,108,108,101,116,83,111,102, +116,66,111,100,121,0,80,97,114,116,68,101,102,108,101,99,116,0,83,111,102,116,66,111,100,121,0,79,98,72,111,111, +107,0,82,78,71,0,83,66,86,101,114,116,101,120,0,66,111,100,121,80,111,105,110,116,0,66,111,100,121,83,112,114, +105,110,103,0,83,66,83,99,114,97,116,99,104,0,87,111,114,108,100,0,82,97,100,105,111,0,66,97,115,101,0,65, +118,105,67,111,100,101,99,68,97,116,97,0,81,117,105,99,107,116,105,109,101,67,111,100,101,99,68,97,116,97,0,70, +70,77,112,101,103,67,111,100,101,99,68,97,116,97,0,65,117,100,105,111,68,97,116,97,0,83,99,101,110,101,82,101, +110,100,101,114,76,97,121,101,114,0,82,101,110,100,101,114,68,97,116,97,0,82,101,110,100,101,114,80,114,111,102,105, +108,101,0,71,97,109,101,70,114,97,109,105,110,103,0,84,105,109,101,77,97,114,107,101,114,0,73,109,97,103,101,80, +97,105,110,116,83,101,116,116,105,110,103,115,0,66,114,117,115,104,0,80,97,114,116,105,99,108,101,66,114,117,115,104, +68,97,116,97,0,80,97,114,116,105,99,108,101,69,100,105,116,83,101,116,116,105,110,103,115,0,84,114,97,110,115,102, +111,114,109,79,114,105,101,110,116,97,116,105,111,110,0,84,111,111,108,83,101,116,116,105,110,103,115,0,66,114,117,115, +104,68,97,116,97,0,83,99,117,108,112,116,68,97,116,97,0,83,99,117,108,112,116,83,101,115,115,105,111,110,0,83, +99,101,110,101,0,68,97,103,70,111,114,101,115,116,0,66,71,112,105,99,0,86,105,101,119,51,68,0,83,112,97,99, +101,76,105,110,107,0,83,99,114,65,114,101,97,0,82,101,110,100,101,114,73,110,102,111,0,82,101,116,111,112,111,86, +105,101,119,68,97,116,97,0,86,105,101,119,68,101,112,116,104,115,0,98,71,80,100,97,116,97,0,86,105,101,119,50, +68,0,83,112,97,99,101,73,110,102,111,0,83,112,97,99,101,73,112,111,0,83,112,97,99,101,66,117,116,115,0,83, +112,97,99,101,83,101,113,0,83,112,97,99,101,70,105,108,101,0,100,105,114,101,110,116,114,121,0,66,108,101,110,100, +72,97,110,100,108,101,0,83,112,97,99,101,79,111,112,115,0,84,114,101,101,83,116,111,114,101,0,84,114,101,101,83, +116,111,114,101,69,108,101,109,0,83,112,97,99,101,73,109,97,103,101,0,83,112,97,99,101,78,108,97,0,83,112,97, +99,101,84,101,120,116,0,83,99,114,105,112,116,0,83,112,97,99,101,83,99,114,105,112,116,0,83,112,97,99,101,84, +105,109,101,0,83,112,97,99,101,78,111,100,101,0,83,112,97,99,101,73,109,97,83,101,108,0,70,105,108,101,76,105, +115,116,0,84,104,101,109,101,85,73,0,84,104,101,109,101,83,112,97,99,101,0,84,104,101,109,101,87,105,114,101,67, +111,108,111,114,0,98,84,104,101,109,101,0,83,111,108,105,100,76,105,103,104,116,0,85,115,101,114,68,101,102,0,98, +83,99,114,101,101,110,0,83,99,114,86,101,114,116,0,83,99,114,69,100,103,101,0,80,97,110,101,108,0,70,105,108, +101,71,108,111,98,97,108,0,83,116,114,105,112,69,108,101,109,0,84,83,116,114,105,112,69,108,101,109,0,83,116,114, +105,112,67,114,111,112,0,83,116,114,105,112,84,114,97,110,115,102,111,114,109,0,83,116,114,105,112,67,111,108,111,114, +66,97,108,97,110,99,101,0,83,116,114,105,112,67,111,108,111,114,66,97,108,97,110,99,101,71,85,73,72,101,108,112, +101,114,0,83,116,114,105,112,80,114,111,120,121,0,83,116,114,105,112,0,80,108,117,103,105,110,83,101,113,0,83,101, +113,117,101,110,99,101,0,98,83,111,117,110,100,0,104,100,97,117,100,105,111,0,77,101,116,97,83,116,97,99,107,0, +69,100,105,116,105,110,103,0,87,105,112,101,86,97,114,115,0,71,108,111,119,86,97,114,115,0,84,114,97,110,115,102, +111,114,109,86,97,114,115,0,83,111,108,105,100,67,111,108,111,114,86,97,114,115,0,83,112,101,101,100,67,111,110,116, +114,111,108,86,97,114,115,0,69,102,102,101,99,116,0,66,117,105,108,100,69,102,102,0,80,97,114,116,69,102,102,0, +80,97,114,116,105,99,108,101,0,87,97,118,101,69,102,102,0,79,111,112,115,0,98,80,114,111,112,101,114,116,121,0, +98,78,101,97,114,83,101,110,115,111,114,0,98,77,111,117,115,101,83,101,110,115,111,114,0,98,84,111,117,99,104,83, +101,110,115,111,114,0,98,75,101,121,98,111,97,114,100,83,101,110,115,111,114,0,98,80,114,111,112,101,114,116,121,83, +101,110,115,111,114,0,98,65,99,116,117,97,116,111,114,83,101,110,115,111,114,0,98,68,101,108,97,121,83,101,110,115, +111,114,0,98,67,111,108,108,105,115,105,111,110,83,101,110,115,111,114,0,98,82,97,100,97,114,83,101,110,115,111,114, +0,98,82,97,110,100,111,109,83,101,110,115,111,114,0,98,82,97,121,83,101,110,115,111,114,0,98,77,101,115,115,97, +103,101,83,101,110,115,111,114,0,98,83,101,110,115,111,114,0,98,67,111,110,116,114,111,108,108,101,114,0,98,74,111, +121,115,116,105,99,107,83,101,110,115,111,114,0,98,69,120,112,114,101,115,115,105,111,110,67,111,110,116,0,98,80,121, +116,104,111,110,67,111,110,116,0,98,65,99,116,117,97,116,111,114,0,98,65,100,100,79,98,106,101,99,116,65,99,116, +117,97,116,111,114,0,98,65,99,116,105,111,110,65,99,116,117,97,116,111,114,0,98,83,111,117,110,100,65,99,116,117, +97,116,111,114,0,98,67,68,65,99,116,117,97,116,111,114,0,98,69,100,105,116,79,98,106,101,99,116,65,99,116,117, +97,116,111,114,0,98,83,99,101,110,101,65,99,116,117,97,116,111,114,0,98,80,114,111,112,101,114,116,121,65,99,116, +117,97,116,111,114,0,98,79,98,106,101,99,116,65,99,116,117,97,116,111,114,0,98,73,112,111,65,99,116,117,97,116, +111,114,0,98,67,97,109,101,114,97,65,99,116,117,97,116,111,114,0,98,67,111,110,115,116,114,97,105,110,116,65,99, +116,117,97,116,111,114,0,98,71,114,111,117,112,65,99,116,117,97,116,111,114,0,98,82,97,110,100,111,109,65,99,116, +117,97,116,111,114,0,98,77,101,115,115,97,103,101,65,99,116,117,97,116,111,114,0,98,71,97,109,101,65,99,116,117, +97,116,111,114,0,98,86,105,115,105,98,105,108,105,116,121,65,99,116,117,97,116,111,114,0,98,84,119,111,68,70,105, +108,116,101,114,65,99,116,117,97,116,111,114,0,98,80,97,114,101,110,116,65,99,116,117,97,116,111,114,0,98,83,116, +97,116,101,65,99,116,117,97,116,111,114,0,70,114,101,101,67,97,109,101,114,97,0,98,83,97,109,112,108,101,0,98, +83,111,117,110,100,76,105,115,116,101,110,101,114,0,83,112,97,99,101,83,111,117,110,100,0,71,114,111,117,112,79,98, +106,101,99,116,0,66,111,110,101,0,98,65,114,109,97,116,117,114,101,0,98,80,111,115,101,67,104,97,110,110,101,108, +0,98,65,99,116,105,111,110,71,114,111,117,112,0,98,65,99,116,105,111,110,67,104,97,110,110,101,108,0,83,112,97, +99,101,65,99,116,105,111,110,0,98,67,111,110,115,116,114,97,105,110,116,67,104,97,110,110,101,108,0,98,67,111,110, +115,116,114,97,105,110,116,0,98,67,111,110,115,116,114,97,105,110,116,84,97,114,103,101,116,0,98,80,121,116,104,111, +110,67,111,110,115,116,114,97,105,110,116,0,98,75,105,110,101,109,97,116,105,99,67,111,110,115,116,114,97,105,110,116, +0,98,84,114,97,99,107,84,111,67,111,110,115,116,114,97,105,110,116,0,98,82,111,116,97,116,101,76,105,107,101,67, +111,110,115,116,114,97,105,110,116,0,98,76,111,99,97,116,101,76,105,107,101,67,111,110,115,116,114,97,105,110,116,0, +98,77,105,110,77,97,120,67,111,110,115,116,114,97,105,110,116,0,98,83,105,122,101,76,105,107,101,67,111,110,115,116, +114,97,105,110,116,0,98,65,99,116,105,111,110,67,111,110,115,116,114,97,105,110,116,0,98,76,111,99,107,84,114,97, +99,107,67,111,110,115,116,114,97,105,110,116,0,98,70,111,108,108,111,119,80,97,116,104,67,111,110,115,116,114,97,105, +110,116,0,98,83,116,114,101,116,99,104,84,111,67,111,110,115,116,114,97,105,110,116,0,98,82,105,103,105,100,66,111, +100,121,74,111,105,110,116,67,111,110,115,116,114,97,105,110,116,0,98,67,108,97,109,112,84,111,67,111,110,115,116,114, +97,105,110,116,0,98,67,104,105,108,100,79,102,67,111,110,115,116,114,97,105,110,116,0,98,84,114,97,110,115,102,111, +114,109,67,111,110,115,116,114,97,105,110,116,0,98,76,111,99,76,105,109,105,116,67,111,110,115,116,114,97,105,110,116, +0,98,82,111,116,76,105,109,105,116,67,111,110,115,116,114,97,105,110,116,0,98,83,105,122,101,76,105,109,105,116,67, +111,110,115,116,114,97,105,110,116,0,98,68,105,115,116,76,105,109,105,116,67,111,110,115,116,114,97,105,110,116,0,98, +83,104,114,105,110,107,119,114,97,112,67,111,110,115,116,114,97,105,110,116,0,98,65,99,116,105,111,110,77,111,100,105, +102,105,101,114,0,98,65,99,116,105,111,110,83,116,114,105,112,0,98,78,111,100,101,83,116,97,99,107,0,98,78,111, +100,101,83,111,99,107,101,116,0,98,78,111,100,101,76,105,110,107,0,98,78,111,100,101,0,98,78,111,100,101,80,114, +101,118,105,101,119,0,98,78,111,100,101,84,121,112,101,0,78,111,100,101,73,109,97,103,101,65,110,105,109,0,78,111, +100,101,66,108,117,114,68,97,116,97,0,78,111,100,101,68,66,108,117,114,68,97,116,97,0,78,111,100,101,66,105,108, +97,116,101,114,97,108,66,108,117,114,68,97,116,97,0,78,111,100,101,72,117,101,83,97,116,0,78,111,100,101,73,109, +97,103,101,70,105,108,101,0,78,111,100,101,67,104,114,111,109,97,0,78,111,100,101,84,119,111,88,89,115,0,78,111, +100,101,84,119,111,70,108,111,97,116,115,0,78,111,100,101,71,101,111,109,101,116,114,121,0,78,111,100,101,86,101,114, +116,101,120,67,111,108,0,78,111,100,101,68,101,102,111,99,117,115,0,78,111,100,101,83,99,114,105,112,116,68,105,99, +116,0,78,111,100,101,71,108,97,114,101,0,78,111,100,101,84,111,110,101,109,97,112,0,78,111,100,101,76,101,110,115, +68,105,115,116,0,84,101,120,78,111,100,101,79,117,116,112,117,116,0,67,117,114,118,101,77,97,112,80,111,105,110,116, +0,67,117,114,118,101,77,97,112,0,66,114,117,115,104,67,108,111,110,101,0,67,117,115,116,111,109,68,97,116,97,76, +97,121,101,114,0,72,97,105,114,75,101,121,0,80,97,114,116,105,99,108,101,75,101,121,0,67,104,105,108,100,80,97, +114,116,105,99,108,101,0,80,97,114,116,105,99,108,101,68,97,116,97,0,80,97,114,116,105,99,108,101,83,101,116,116, +105,110,103,115,0,80,97,114,116,105,99,108,101,69,100,105,116,0,80,97,114,116,105,99,108,101,67,97,99,104,101,75, +101,121,0,76,105,110,107,78,111,100,101,0,98,71,80,68,115,112,111,105,110,116,0,98,71,80,68,115,116,114,111,107, +101,0,98,71,80,68,102,114,97,109,101,0,98,71,80,68,108,97,121,101,114,0,0,84,76,69,78,1,0,1,0,2, +0,2,0,4,0,4,0,4,0,4,0,8,0,0,0,8,0,12,0,8,0,4,0,8,0,8,0,16,0,12,0,12, +0,24,0,16,0,16,0,32,0,16,0,16,0,20,0,76,0,52,0,40,2,0,0,32,0,-116,0,80,3,92,0,36, +0,56,0,84,0,112,0,120,0,16,0,24,0,40,0,120,0,20,0,-124,0,32,0,-128,1,0,0,0,0,0,0,-120, +0,16,1,84,1,24,0,8,3,-88,0,0,0,124,0,-124,0,-128,1,8,1,56,0,108,2,76,0,68,1,0,0,108, +0,104,0,-120,0,56,0,8,0,16,0,56,1,0,0,24,1,20,0,44,0,60,0,24,0,12,0,12,0,4,0,8, +0,8,0,24,0,76,0,32,0,8,0,12,0,8,0,8,0,4,0,4,0,0,1,32,0,16,0,64,0,24,0,12, +0,56,0,0,0,52,0,68,0,88,0,96,0,68,0,96,0,116,0,64,0,60,0,108,0,60,0,-108,0,-104,0,60, +0,92,0,104,0,-72,0,100,0,-76,0,52,0,68,0,0,0,-124,0,28,0,20,0,100,0,0,0,60,0,0,0,0, +0,64,0,8,0,8,0,-40,0,76,0,64,1,64,0,64,0,60,0,-92,1,108,0,104,0,116,0,40,0,84,0,56, +0,120,0,-128,0,-8,0,-48,0,0,0,16,0,0,0,0,0,0,0,108,1,40,0,28,0,-80,0,-112,0,52,0,16, +0,72,0,-48,3,56,0,16,0,80,0,12,0,-72,0,8,0,72,0,80,0,-24,0,8,0,-88,0,0,0,124,5,0, +0,60,0,28,3,36,0,-52,0,0,0,0,0,0,0,20,0,-120,0,36,0,88,1,-36,0,-56,0,-56,1,0,0,0, +0,8,1,12,0,12,0,8,1,-76,0,-128,0,80,2,36,0,-92,0,-36,0,-124,2,0,0,-104,0,-48,0,16,0,56, +14,56,0,32,12,120,0,20,0,24,0,-28,0,32,0,80,0,28,0,16,0,8,0,60,0,0,0,-4,0,-16,0,-88, +1,-60,0,28,1,0,0,16,0,28,0,12,0,24,0,48,0,16,0,28,0,16,0,24,0,56,1,0,0,56,0,44, +0,64,0,48,0,8,0,44,0,72,0,104,0,40,0,8,0,72,0,44,0,40,0,108,0,68,0,76,0,80,0,60, +0,-128,0,76,0,60,0,12,0,92,0,28,0,20,0,80,0,16,0,76,0,108,0,84,0,28,0,96,0,60,0,56, +0,108,0,-116,0,4,0,20,0,12,0,8,0,40,0,0,0,68,0,-80,0,24,0,4,1,116,0,-104,1,72,0,64, +0,-64,0,44,0,64,0,116,0,60,0,104,0,52,0,44,0,44,0,68,0,44,0,64,0,44,0,20,0,52,0,96, +0,12,0,108,0,92,0,28,0,28,0,28,0,52,0,20,0,60,0,-116,0,36,0,120,0,24,0,-52,0,0,0,0, +0,16,0,40,0,28,0,12,0,12,0,16,1,40,0,8,0,8,0,64,0,32,0,24,0,8,0,24,0,32,0,8, +0,32,0,12,0,44,0,20,0,68,0,24,0,56,0,72,0,-4,0,-32,1,0,0,0,0,0,0,16,0,20,0,24, +0,-84,0,83,84,82,67,57,1,0,0,10,0,2,0,10,0,0,0,10,0,1,0,11,0,3,0,11,0,0,0,11, +0,1,0,9,0,2,0,12,0,2,0,9,0,3,0,9,0,4,0,13,0,2,0,2,0,5,0,2,0,6,0,14, +0,2,0,4,0,5,0,4,0,6,0,15,0,2,0,7,0,5,0,7,0,6,0,16,0,2,0,8,0,5,0,8, +0,6,0,17,0,3,0,4,0,5,0,4,0,6,0,4,0,7,0,18,0,3,0,7,0,5,0,7,0,6,0,7, +0,7,0,19,0,3,0,8,0,5,0,8,0,6,0,8,0,7,0,20,0,4,0,4,0,5,0,4,0,6,0,4, +0,7,0,4,0,8,0,21,0,4,0,7,0,5,0,7,0,6,0,7,0,7,0,7,0,8,0,22,0,4,0,8, +0,5,0,8,0,6,0,8,0,7,0,8,0,8,0,23,0,4,0,4,0,9,0,4,0,10,0,4,0,11,0,4, +0,12,0,24,0,4,0,7,0,9,0,7,0,10,0,7,0,11,0,7,0,12,0,25,0,4,0,9,0,13,0,12, +0,14,0,4,0,15,0,4,0,16,0,26,0,10,0,26,0,0,0,26,0,1,0,0,0,17,0,0,0,18,0,0, +0,19,0,2,0,20,0,4,0,21,0,25,0,22,0,4,0,23,0,4,0,24,0,27,0,9,0,9,0,0,0,9, +0,1,0,27,0,25,0,28,0,26,0,0,0,27,0,2,0,28,0,2,0,20,0,4,0,29,0,26,0,30,0,28, +0,8,0,27,0,31,0,27,0,32,0,29,0,33,0,0,0,34,0,0,0,35,0,4,0,36,0,4,0,37,0,28, +0,38,0,30,0,6,0,4,0,39,0,4,0,40,0,2,0,41,0,2,0,42,0,2,0,43,0,4,0,44,0,31, +0,6,0,32,0,45,0,2,0,46,0,2,0,47,0,2,0,18,0,2,0,20,0,0,0,48,0,33,0,21,0,33, +0,0,0,33,0,1,0,34,0,49,0,35,0,50,0,24,0,51,0,24,0,52,0,2,0,46,0,2,0,47,0,2, +0,53,0,2,0,54,0,2,0,55,0,2,0,56,0,2,0,20,0,2,0,57,0,7,0,11,0,7,0,12,0,4, +0,58,0,7,0,59,0,7,0,60,0,7,0,61,0,31,0,62,0,36,0,7,0,27,0,31,0,12,0,63,0,24, +0,64,0,2,0,46,0,2,0,65,0,2,0,66,0,2,0,37,0,37,0,16,0,37,0,0,0,37,0,1,0,7, +0,67,0,7,0,61,0,2,0,18,0,2,0,47,0,2,0,68,0,2,0,20,0,4,0,69,0,4,0,70,0,9, +0,2,0,7,0,71,0,0,0,17,0,0,0,72,0,7,0,73,0,7,0,74,0,38,0,12,0,27,0,31,0,37, +0,75,0,0,0,76,0,4,0,77,0,7,0,61,0,12,0,78,0,36,0,79,0,27,0,80,0,2,0,18,0,2, +0,81,0,2,0,82,0,2,0,20,0,39,0,5,0,27,0,83,0,2,0,84,0,2,0,85,0,2,0,86,0,4, +0,37,0,40,0,6,0,40,0,0,0,40,0,1,0,0,0,87,0,0,0,88,0,4,0,23,0,4,0,89,0,41, +0,10,0,41,0,0,0,41,0,1,0,4,0,90,0,4,0,91,0,4,0,92,0,4,0,43,0,4,0,14,0,4, +0,93,0,0,0,94,0,0,0,95,0,42,0,15,0,27,0,31,0,0,0,96,0,4,0,93,0,4,0,97,0,12, +0,98,0,40,0,99,0,40,0,100,0,4,0,101,0,4,0,102,0,12,0,103,0,0,0,104,0,4,0,105,0,4, +0,106,0,9,0,107,0,8,0,108,0,43,0,5,0,4,0,109,0,4,0,110,0,4,0,93,0,4,0,37,0,9, +0,2,0,44,0,20,0,27,0,31,0,2,0,18,0,2,0,20,0,7,0,111,0,7,0,112,0,7,0,113,0,7, +0,114,0,7,0,115,0,7,0,116,0,7,0,117,0,7,0,118,0,7,0,119,0,7,0,120,0,7,0,121,0,2, +0,122,0,2,0,123,0,7,0,124,0,36,0,79,0,39,0,125,0,32,0,126,0,45,0,12,0,4,0,127,0,4, +0,-128,0,4,0,-127,0,4,0,-126,0,2,0,-125,0,2,0,-124,0,2,0,20,0,2,0,-123,0,2,0,-122,0,2, +0,-121,0,2,0,-120,0,2,0,-119,0,46,0,32,0,27,0,31,0,0,0,34,0,12,0,-118,0,47,0,-117,0,48, +0,-116,0,49,0,-115,0,2,0,-123,0,2,0,20,0,2,0,-114,0,2,0,18,0,2,0,37,0,2,0,43,0,4, +0,-113,0,2,0,-112,0,2,0,-111,0,2,0,-110,0,2,0,-109,0,2,0,-108,0,2,0,-107,0,4,0,-106,0,4, +0,-105,0,43,0,-104,0,30,0,-103,0,7,0,-102,0,4,0,-101,0,2,0,-100,0,2,0,-99,0,2,0,-98,0,2, +0,-97,0,7,0,-96,0,7,0,-95,0,9,0,-94,0,50,0,31,0,2,0,-93,0,2,0,-92,0,2,0,-91,0,2, +0,-90,0,32,0,-89,0,51,0,-88,0,0,0,-87,0,0,0,-86,0,0,0,-85,0,0,0,-84,0,0,0,-83,0,7, +0,-82,0,7,0,-81,0,2,0,-80,0,2,0,-79,0,2,0,-78,0,2,0,-77,0,2,0,-76,0,2,0,-75,0,2, +0,-74,0,7,0,-73,0,7,0,-72,0,7,0,-71,0,7,0,-70,0,7,0,-69,0,7,0,57,0,7,0,-68,0,7, +0,-67,0,7,0,-66,0,7,0,-65,0,7,0,-64,0,52,0,15,0,0,0,-63,0,9,0,-62,0,0,0,-61,0,0, +0,-60,0,4,0,-59,0,4,0,-58,0,9,0,-57,0,7,0,-56,0,7,0,-55,0,7,0,-54,0,4,0,-53,0,9, +0,-52,0,9,0,-51,0,4,0,-50,0,4,0,37,0,53,0,6,0,7,0,-73,0,7,0,-72,0,7,0,-71,0,7, +0,-49,0,7,0,67,0,4,0,64,0,54,0,5,0,2,0,20,0,2,0,36,0,2,0,64,0,2,0,-48,0,53, +0,-54,0,55,0,17,0,32,0,-89,0,46,0,-47,0,56,0,-46,0,7,0,-45,0,7,0,-44,0,2,0,18,0,2, +0,-43,0,7,0,113,0,7,0,114,0,7,0,-42,0,4,0,-41,0,2,0,-40,0,2,0,-39,0,4,0,-123,0,4, +0,-113,0,2,0,-38,0,2,0,-37,0,51,0,56,0,27,0,31,0,7,0,-36,0,7,0,-35,0,7,0,-34,0,7, +0,-33,0,7,0,-32,0,7,0,-31,0,7,0,-30,0,7,0,-29,0,7,0,-28,0,7,0,-27,0,7,0,-26,0,7, +0,-25,0,7,0,-24,0,7,0,-23,0,7,0,-22,0,7,0,-21,0,7,0,-20,0,7,0,-19,0,7,0,-18,0,7, +0,-17,0,2,0,-16,0,2,0,-15,0,2,0,-14,0,2,0,-13,0,2,0,-12,0,2,0,-11,0,2,0,-10,0,2, +0,20,0,2,0,18,0,2,0,-43,0,7,0,-9,0,7,0,-8,0,7,0,-7,0,7,0,-6,0,2,0,-5,0,2, +0,-4,0,2,0,-3,0,2,0,-125,0,4,0,23,0,4,0,-128,0,4,0,-127,0,4,0,-126,0,7,0,-2,0,7, +0,-1,0,7,0,-67,0,45,0,0,1,57,0,1,1,36,0,79,0,46,0,-47,0,52,0,2,1,54,0,3,1,55, +0,4,1,30,0,-103,0,0,0,5,1,0,0,6,1,58,0,8,0,7,0,7,1,7,0,8,1,7,0,-81,0,4, +0,20,0,7,0,9,1,7,0,10,1,7,0,11,1,32,0,45,0,59,0,80,0,27,0,31,0,2,0,18,0,2, +0,12,1,4,0,13,1,2,0,-79,0,2,0,14,1,7,0,-73,0,7,0,-72,0,7,0,-71,0,7,0,-70,0,7, +0,15,1,7,0,16,1,7,0,17,1,7,0,18,1,7,0,19,1,7,0,20,1,7,0,21,1,7,0,22,1,7, +0,23,1,7,0,24,1,7,0,25,1,60,0,26,1,2,0,27,1,2,0,70,0,7,0,113,0,7,0,114,0,7, +0,28,1,7,0,29,1,7,0,30,1,2,0,31,1,2,0,32,1,2,0,33,1,2,0,34,1,0,0,35,1,0, +0,36,1,2,0,37,1,2,0,38,1,2,0,39,1,2,0,40,1,2,0,41,1,7,0,42,1,7,0,43,1,7, +0,44,1,7,0,45,1,2,0,46,1,2,0,43,0,2,0,47,1,2,0,48,1,2,0,49,1,2,0,50,1,7, +0,51,1,7,0,52,1,7,0,53,1,7,0,54,1,7,0,55,1,7,0,56,1,7,0,57,1,7,0,58,1,7, +0,59,1,7,0,60,1,7,0,61,1,7,0,62,1,2,0,63,1,2,0,64,1,4,0,65,1,4,0,66,1,2, +0,67,1,2,0,68,1,2,0,69,1,2,0,70,1,7,0,71,1,7,0,72,1,7,0,73,1,7,0,74,1,2, +0,75,1,2,0,76,1,50,0,77,1,36,0,79,0,30,0,-103,0,39,0,125,0,61,0,2,0,27,0,31,0,36, +0,79,0,62,0,-127,0,27,0,31,0,2,0,-79,0,2,0,20,0,7,0,-73,0,7,0,-72,0,7,0,-71,0,7, +0,78,1,7,0,79,1,7,0,80,1,7,0,81,1,7,0,82,1,7,0,83,1,7,0,84,1,7,0,85,1,7, +0,86,1,7,0,87,1,7,0,88,1,7,0,89,1,7,0,90,1,7,0,91,1,7,0,92,1,7,0,93,1,7, +0,94,1,7,0,95,1,7,0,96,1,7,0,97,1,7,0,98,1,7,0,99,1,7,0,100,1,7,0,101,1,7, +0,102,1,7,0,103,1,7,0,104,1,2,0,105,1,2,0,106,1,2,0,107,1,0,0,108,1,0,0,109,1,7, +0,110,1,7,0,111,1,2,0,112,1,2,0,113,1,7,0,114,1,7,0,115,1,7,0,116,1,7,0,117,1,2, +0,118,1,2,0,119,1,4,0,13,1,4,0,120,1,2,0,121,1,2,0,122,1,2,0,123,1,2,0,124,1,7, +0,125,1,7,0,126,1,7,0,127,1,7,0,-128,1,7,0,-127,1,7,0,-126,1,7,0,-125,1,7,0,-124,1,7, +0,-123,1,7,0,-122,1,0,0,-121,1,7,0,-120,1,7,0,-119,1,7,0,-118,1,4,0,-117,1,0,0,-116,1,0, +0,47,1,0,0,-115,1,0,0,5,1,2,0,-114,1,2,0,-113,1,2,0,64,1,2,0,-112,1,2,0,-111,1,2, +0,-110,1,7,0,-109,1,7,0,-108,1,7,0,-107,1,7,0,-106,1,7,0,-105,1,2,0,-93,0,2,0,-92,0,54, +0,-104,1,54,0,-103,1,0,0,-102,1,0,0,-101,1,0,0,-100,1,0,0,-99,1,2,0,-98,1,2,0,12,1,7, +0,-97,1,7,0,-96,1,50,0,77,1,57,0,1,1,36,0,79,0,63,0,-95,1,30,0,-103,0,7,0,-94,1,7, +0,-93,1,7,0,-92,1,7,0,-91,1,7,0,-90,1,2,0,-89,1,2,0,70,0,7,0,-88,1,7,0,-87,1,7, +0,-86,1,7,0,-85,1,7,0,-84,1,7,0,-83,1,7,0,-82,1,7,0,-81,1,7,0,-80,1,2,0,-79,1,2, +0,-78,1,7,0,-77,1,7,0,-76,1,7,0,-75,1,7,0,-74,1,7,0,-73,1,4,0,-72,1,4,0,-71,1,4, +0,-70,1,39,0,125,0,12,0,-69,1,64,0,6,0,27,0,31,0,0,0,-68,1,7,0,-67,1,7,0,37,0,65, +0,2,0,43,0,-104,0,66,0,26,0,66,0,0,0,66,0,1,0,67,0,-66,1,4,0,-65,1,4,0,-64,1,4, +0,-63,1,4,0,-62,1,4,0,-61,1,4,0,-60,1,2,0,18,0,2,0,20,0,2,0,-59,1,2,0,-58,1,7, +0,5,0,7,0,6,0,7,0,7,0,7,0,-57,1,7,0,-56,1,7,0,-55,1,7,0,-54,1,7,0,-53,1,7, +0,-52,1,7,0,-51,1,7,0,23,0,7,0,-50,1,7,0,-49,1,68,0,15,0,27,0,31,0,67,0,-66,1,12, +0,-48,1,12,0,-47,1,36,0,79,0,62,0,-46,1,2,0,20,0,2,0,-45,1,4,0,-80,0,7,0,7,1,7, +0,-81,0,7,0,8,1,7,0,-44,1,7,0,-43,1,7,0,-42,1,35,0,10,0,7,0,-41,1,7,0,-40,1,7, +0,-39,1,7,0,-38,1,2,0,-37,1,2,0,-36,1,0,0,-35,1,0,0,-34,1,0,0,-33,1,0,0,-32,1,34, +0,7,0,7,0,-31,1,7,0,-40,1,7,0,-39,1,2,0,-35,1,2,0,-32,1,7,0,-38,1,7,0,37,0,69, +0,21,0,69,0,0,0,69,0,1,0,2,0,18,0,2,0,-30,1,2,0,-32,1,2,0,20,0,2,0,-29,1,2, +0,-28,1,2,0,-27,1,2,0,-26,1,2,0,-25,1,2,0,-24,1,2,0,-23,1,2,0,-22,1,7,0,-21,1,7, +0,-20,1,34,0,49,0,35,0,50,0,2,0,-19,1,2,0,-18,1,4,0,-17,1,70,0,5,0,2,0,-16,1,2, +0,-30,1,0,0,20,0,0,0,37,0,2,0,70,0,71,0,4,0,7,0,5,0,7,0,6,0,7,0,8,0,7, +0,-15,1,72,0,57,0,27,0,31,0,67,0,-66,1,12,0,-14,1,12,0,-47,1,32,0,-13,1,32,0,-12,1,32, +0,-11,1,36,0,79,0,73,0,-10,1,38,0,-9,1,62,0,-46,1,12,0,-8,1,7,0,7,1,7,0,-81,0,7, +0,8,1,4,0,-80,0,2,0,-7,1,2,0,-45,1,2,0,20,0,2,0,-6,1,7,0,-5,1,7,0,-4,1,7, +0,-3,1,2,0,-27,1,2,0,-26,1,2,0,-2,1,2,0,-1,1,4,0,70,0,2,0,23,0,2,0,98,0,2, +0,67,0,2,0,0,2,7,0,1,2,7,0,2,2,7,0,3,2,7,0,4,2,7,0,5,2,7,0,6,2,7, +0,7,2,7,0,8,2,7,0,9,2,7,0,10,2,0,0,11,2,0,0,12,2,64,0,13,2,64,0,14,2,64, +0,15,2,64,0,16,2,4,0,17,2,4,0,18,2,4,0,19,2,4,0,37,0,71,0,20,2,4,0,21,2,4, +0,22,2,70,0,23,2,70,0,24,2,74,0,39,0,27,0,31,0,67,0,-66,1,12,0,25,2,36,0,79,0,38, +0,-9,1,62,0,-46,1,75,0,26,2,76,0,27,2,77,0,28,2,78,0,29,2,79,0,30,2,80,0,31,2,81, +0,32,2,82,0,33,2,74,0,34,2,83,0,35,2,84,0,36,2,84,0,37,2,84,0,38,2,4,0,54,0,4, +0,39,2,4,0,40,2,4,0,41,2,4,0,42,2,4,0,-80,0,7,0,7,1,7,0,-81,0,7,0,8,1,7, +0,43,2,7,0,37,0,2,0,44,2,2,0,20,0,2,0,45,2,2,0,46,2,2,0,-45,1,2,0,47,2,85, +0,48,2,86,0,49,2,9,0,-94,0,77,0,8,0,9,0,50,2,7,0,51,2,4,0,52,2,0,0,20,0,0, +0,53,2,2,0,13,1,2,0,54,2,2,0,55,2,75,0,8,0,4,0,56,2,4,0,57,2,4,0,58,2,4, +0,59,2,0,0,37,0,0,0,-30,1,0,0,60,2,0,0,20,0,79,0,5,0,4,0,56,2,4,0,57,2,0, +0,61,2,0,0,62,2,2,0,20,0,87,0,2,0,4,0,63,2,7,0,-39,1,80,0,3,0,87,0,64,2,4, +0,65,2,4,0,20,0,78,0,6,0,7,0,66,2,2,0,67,2,0,0,20,0,0,0,-30,1,0,0,62,2,0, +0,68,2,81,0,4,0,0,0,-49,0,0,0,-73,0,0,0,-72,0,0,0,-71,0,88,0,6,0,46,0,50,2,0, +0,20,0,0,0,53,2,2,0,13,1,2,0,54,2,2,0,55,2,89,0,1,0,7,0,69,2,90,0,5,0,0, +0,-49,0,0,0,-73,0,0,0,-72,0,0,0,-71,0,4,0,37,0,82,0,1,0,7,0,70,2,83,0,2,0,4, +0,71,2,4,0,18,0,76,0,7,0,7,0,51,2,46,0,50,2,0,0,20,0,0,0,53,2,2,0,13,1,2, +0,54,2,2,0,55,2,91,0,1,0,7,0,72,2,92,0,1,0,4,0,73,2,93,0,1,0,0,0,74,2,94, +0,1,0,7,0,51,2,95,0,4,0,7,0,-49,0,7,0,-73,0,7,0,-72,0,7,0,-71,0,96,0,1,0,95, +0,52,2,97,0,5,0,4,0,75,2,4,0,76,2,0,0,20,0,0,0,-30,1,0,0,-74,0,98,0,2,0,4, +0,77,2,4,0,76,2,99,0,14,0,99,0,0,0,99,0,1,0,97,0,78,2,96,0,79,2,98,0,80,2,0, +0,81,2,12,0,82,2,12,0,83,2,100,0,84,2,4,0,54,0,4,0,40,2,4,0,39,2,4,0,37,0,78, +0,85,2,85,0,14,0,12,0,86,2,78,0,85,2,0,0,87,2,0,0,88,2,0,0,89,2,0,0,90,2,0, +0,91,2,0,0,92,2,0,0,93,2,0,0,20,0,84,0,36,2,84,0,38,2,2,0,94,2,0,0,95,2,86, +0,8,0,4,0,96,2,4,0,97,2,75,0,98,2,79,0,99,2,4,0,40,2,4,0,39,2,4,0,54,0,4, +0,37,0,101,0,6,0,101,0,0,0,101,0,1,0,4,0,18,0,4,0,13,1,0,0,17,0,0,0,100,2,102, +0,7,0,101,0,101,2,2,0,102,2,2,0,86,2,2,0,103,2,2,0,93,0,9,0,104,2,9,0,105,2,103, +0,3,0,101,0,101,2,32,0,-89,0,0,0,17,0,104,0,5,0,101,0,101,2,32,0,-89,0,0,0,17,0,2, +0,106,2,0,0,107,2,105,0,5,0,101,0,101,2,7,0,91,0,7,0,108,2,4,0,109,2,4,0,110,2,106, +0,5,0,101,0,101,2,32,0,111,2,0,0,72,0,4,0,13,1,4,0,20,0,107,0,13,0,101,0,101,2,32, +0,112,2,32,0,113,2,32,0,114,2,32,0,115,2,7,0,116,2,7,0,117,2,7,0,108,2,7,0,118,2,4, +0,119,2,4,0,120,2,4,0,93,0,4,0,121,2,108,0,5,0,101,0,101,2,2,0,122,2,2,0,20,0,7, +0,123,2,32,0,124,2,109,0,3,0,101,0,101,2,7,0,125,2,4,0,93,0,110,0,10,0,101,0,101,2,7, +0,126,2,4,0,127,2,4,0,37,0,2,0,93,0,2,0,-128,2,2,0,-127,2,2,0,-126,2,7,0,-125,2,0, +0,-124,2,111,0,3,0,101,0,101,2,7,0,37,0,4,0,18,0,112,0,11,0,101,0,101,2,51,0,-123,2,7, +0,-122,2,4,0,-121,2,0,0,-124,2,7,0,-120,2,4,0,-119,2,32,0,-118,2,0,0,-117,2,4,0,-116,2,4, +0,37,0,113,0,10,0,101,0,101,2,32,0,-115,2,46,0,-114,2,4,0,93,0,4,0,-113,2,7,0,-112,2,7, +0,-111,2,0,0,-117,2,4,0,-116,2,4,0,37,0,114,0,3,0,101,0,101,2,7,0,-110,2,4,0,-109,2,115, +0,5,0,101,0,101,2,7,0,-108,2,0,0,-124,2,2,0,20,0,2,0,-107,2,116,0,8,0,101,0,101,2,32, +0,-89,0,7,0,-108,2,7,0,-38,1,7,0,109,0,0,0,-124,2,2,0,20,0,2,0,18,0,117,0,21,0,101, +0,101,2,32,0,-106,2,0,0,-124,2,51,0,-123,2,32,0,-118,2,2,0,20,0,2,0,37,0,7,0,-105,2,7, +0,-104,2,7,0,-103,2,7,0,-5,1,7,0,-102,2,7,0,-101,2,7,0,-100,2,7,0,-99,2,4,0,-119,2,4, +0,-116,2,0,0,-117,2,7,0,-98,2,7,0,-97,2,7,0,43,0,118,0,7,0,101,0,101,2,2,0,-96,2,2, +0,-95,2,4,0,70,0,32,0,-89,0,7,0,-94,2,0,0,-124,2,119,0,9,0,101,0,101,2,32,0,-89,0,7, +0,-93,2,7,0,-92,2,7,0,-99,2,4,0,-91,2,4,0,-90,2,7,0,-89,2,0,0,17,0,120,0,1,0,101, +0,101,2,121,0,5,0,101,0,101,2,122,0,-88,2,123,0,-87,2,124,0,-86,2,125,0,-85,2,126,0,14,0,101, +0,101,2,78,0,-84,2,78,0,-83,2,78,0,-82,2,78,0,-81,2,78,0,-80,2,78,0,-79,2,75,0,-78,2,4, +0,-77,2,4,0,-76,2,2,0,-75,2,2,0,37,0,7,0,-74,2,127,0,-73,2,-128,0,3,0,101,0,101,2,-127, +0,-72,2,-126,0,-73,2,-125,0,4,0,101,0,101,2,32,0,-89,0,4,0,-71,2,4,0,37,0,-124,0,2,0,4, +0,-70,2,7,0,-39,1,-123,0,2,0,4,0,-127,0,4,0,-69,2,-122,0,20,0,101,0,101,2,32,0,-89,0,0, +0,-124,2,2,0,-68,2,2,0,-67,2,2,0,20,0,2,0,37,0,7,0,-66,2,7,0,-65,2,4,0,54,0,4, +0,-64,2,-123,0,-63,2,-124,0,-62,2,4,0,-61,2,4,0,-60,2,4,0,-59,2,4,0,-69,2,7,0,-58,2,7, +0,-57,2,7,0,-56,2,-121,0,8,0,101,0,101,2,-120,0,-55,2,-127,0,-72,2,4,0,-54,2,4,0,-53,2,4, +0,-52,2,2,0,20,0,2,0,57,0,-119,0,5,0,101,0,101,2,32,0,45,0,2,0,-51,2,2,0,20,0,2, +0,-50,2,-118,0,5,0,101,0,101,2,4,0,-49,2,2,0,20,0,2,0,-48,2,7,0,-47,2,-117,0,3,0,101, +0,101,2,-116,0,-46,2,125,0,-85,2,-115,0,10,0,101,0,101,2,32,0,-45,2,32,0,-44,2,0,0,-43,2,7, +0,-42,2,2,0,-41,2,2,0,-40,2,0,0,-39,2,0,0,-38,2,0,0,107,2,-114,0,9,0,101,0,101,2,32, +0,-37,2,0,0,-43,2,7,0,-36,2,7,0,-35,2,0,0,13,1,0,0,122,2,0,0,-34,2,0,0,37,0,-113, +0,24,0,27,0,31,0,2,0,-29,1,2,0,-28,1,2,0,-33,2,2,0,20,0,2,0,-32,2,2,0,-31,2,2, +0,-30,2,2,0,70,0,0,0,-29,2,0,0,-28,2,0,0,-27,2,0,0,18,0,4,0,37,0,7,0,-26,2,7, +0,-25,2,7,0,-24,2,7,0,-23,2,7,0,-22,2,7,0,-21,2,34,0,-20,2,36,0,79,0,38,0,-9,1,80, +0,31,2,-112,0,3,0,-112,0,0,0,-112,0,1,0,0,0,17,0,67,0,3,0,7,0,-19,2,4,0,20,0,4, +0,37,0,32,0,111,0,27,0,31,0,2,0,18,0,2,0,-18,2,4,0,-17,2,4,0,-16,2,4,0,-15,2,0, +0,-14,2,32,0,38,0,32,0,-13,2,32,0,-12,2,32,0,-11,2,32,0,-10,2,36,0,79,0,73,0,-10,1,67, +0,-66,1,-111,0,-9,2,-111,0,-8,2,-110,0,-7,2,9,0,2,0,12,0,-6,2,12,0,25,2,12,0,-47,1,12, +0,-5,2,12,0,-4,2,62,0,-46,1,7,0,7,1,7,0,-3,2,7,0,-2,2,7,0,-81,0,7,0,-1,2,7, +0,8,1,7,0,0,3,7,0,1,3,7,0,-93,2,7,0,2,3,7,0,-45,0,4,0,3,3,2,0,20,0,2, +0,4,3,2,0,5,3,2,0,6,3,2,0,7,3,2,0,8,3,2,0,9,3,2,0,10,3,2,0,11,3,2, +0,12,3,2,0,13,3,2,0,14,3,4,0,15,3,4,0,16,3,4,0,17,3,4,0,18,3,7,0,19,3,7, +0,20,3,7,0,21,3,7,0,22,3,7,0,23,3,7,0,24,3,7,0,25,3,7,0,26,3,7,0,27,3,7, +0,28,3,7,0,29,3,7,0,30,3,0,0,31,3,0,0,32,3,0,0,-45,1,0,0,33,3,0,0,34,3,0, +0,35,3,7,0,36,3,7,0,37,3,39,0,125,0,12,0,38,3,12,0,39,3,12,0,40,3,12,0,41,3,7, +0,42,3,2,0,71,2,2,0,43,3,7,0,52,2,4,0,44,3,4,0,45,3,-109,0,46,3,2,0,47,3,2, +0,-38,0,7,0,48,3,12,0,49,3,12,0,50,3,12,0,51,3,12,0,52,3,-108,0,53,3,-107,0,54,3,63, +0,55,3,2,0,56,3,2,0,57,3,2,0,58,3,2,0,59,3,7,0,44,2,2,0,60,3,2,0,61,3,-116, +0,62,3,-127,0,63,3,-127,0,64,3,4,0,65,3,4,0,66,3,4,0,67,3,4,0,70,0,9,0,-94,0,12, +0,68,3,-106,0,14,0,-106,0,0,0,-106,0,1,0,32,0,38,0,7,0,-93,2,7,0,9,1,7,0,-92,2,7, +0,-99,2,0,0,17,0,4,0,-91,2,4,0,-90,2,4,0,69,3,2,0,18,0,2,0,70,3,7,0,-89,2,-108, +0,36,0,2,0,71,3,2,0,72,3,2,0,20,0,2,0,-99,2,7,0,73,3,7,0,74,3,7,0,75,3,7, +0,76,3,7,0,77,3,7,0,78,3,7,0,79,3,7,0,80,3,7,0,81,3,7,0,82,3,7,0,83,3,7, +0,84,3,7,0,85,3,7,0,86,3,7,0,87,3,7,0,88,3,7,0,89,3,7,0,90,3,7,0,91,3,7, +0,92,3,7,0,93,3,7,0,94,3,7,0,95,3,7,0,96,3,2,0,97,3,2,0,98,3,2,0,99,3,2, +0,100,3,51,0,-88,0,-105,0,101,3,7,0,102,3,4,0,110,2,125,0,5,0,4,0,20,0,4,0,103,3,4, +0,104,3,4,0,105,3,4,0,106,3,-104,0,1,0,7,0,-31,1,-109,0,30,0,4,0,20,0,7,0,107,3,7, +0,108,3,7,0,109,3,4,0,110,3,4,0,111,3,4,0,112,3,4,0,113,3,7,0,114,3,7,0,115,3,7, +0,116,3,7,0,117,3,7,0,118,3,7,0,119,3,7,0,120,3,7,0,121,3,7,0,122,3,7,0,123,3,7, +0,124,3,7,0,125,3,7,0,126,3,7,0,127,3,7,0,-128,3,7,0,-127,3,7,0,-126,3,7,0,-125,3,4, +0,-124,3,4,0,-123,3,7,0,-122,3,7,0,27,3,-107,0,49,0,-120,0,-121,3,4,0,-120,3,4,0,-119,3,-103, +0,-118,3,-102,0,-117,3,0,0,37,0,0,0,-116,3,2,0,-115,3,7,0,-114,3,0,0,-113,3,7,0,-112,3,7, +0,-111,3,7,0,-110,3,7,0,-109,3,7,0,-108,3,7,0,-107,3,7,0,-106,3,7,0,-105,3,7,0,-104,3,2, +0,-103,3,0,0,-102,3,2,0,-101,3,7,0,-100,3,7,0,-99,3,0,0,-98,3,4,0,-126,0,4,0,-97,3,4, +0,-96,3,2,0,-95,3,2,0,-94,3,-104,0,-93,3,4,0,-92,3,4,0,81,0,7,0,-91,3,7,0,-90,3,7, +0,-89,3,7,0,-88,3,2,0,-87,3,2,0,-86,3,2,0,-85,3,2,0,-84,3,2,0,-83,3,2,0,-82,3,2, +0,-81,3,2,0,-80,3,-101,0,-79,3,7,0,-78,3,7,0,-77,3,125,0,-76,3,-116,0,48,0,2,0,18,0,2, +0,-75,3,2,0,-74,3,2,0,-73,3,7,0,-72,3,2,0,-71,3,2,0,-70,3,7,0,-69,3,2,0,-68,3,2, +0,-67,3,7,0,-66,3,7,0,-65,3,7,0,-64,3,7,0,-63,3,7,0,-62,3,7,0,-61,3,4,0,-60,3,7, +0,-59,3,7,0,-58,3,7,0,-57,3,74,0,-56,3,74,0,-55,3,74,0,-54,3,0,0,-53,3,7,0,-52,3,7, +0,-51,3,36,0,79,0,2,0,-50,3,0,0,-49,3,0,0,-48,3,7,0,-47,3,4,0,-46,3,7,0,-45,3,7, +0,-44,3,4,0,-43,3,4,0,20,0,7,0,-42,3,7,0,-41,3,7,0,-40,3,78,0,-39,3,7,0,-38,3,7, +0,-37,3,7,0,-36,3,7,0,-35,3,7,0,-34,3,7,0,-33,3,7,0,-32,3,4,0,-31,3,-100,0,71,0,27, +0,31,0,2,0,-79,0,2,0,14,1,2,0,47,1,2,0,-30,3,7,0,-29,3,7,0,-28,3,7,0,-27,3,7, +0,-26,3,7,0,-25,3,7,0,-24,3,7,0,-23,3,7,0,-22,3,7,0,84,1,7,0,86,1,7,0,85,1,7, +0,-21,3,4,0,-20,3,7,0,-19,3,7,0,-18,3,7,0,-17,3,7,0,-16,3,7,0,-15,3,7,0,-14,3,7, +0,-13,3,2,0,-12,3,2,0,13,1,2,0,-11,3,2,0,-10,3,2,0,-9,3,2,0,-8,3,2,0,-7,3,2, +0,-6,3,7,0,-5,3,7,0,-4,3,7,0,-3,3,7,0,-2,3,7,0,-1,3,7,0,0,4,7,0,1,4,7, +0,2,4,7,0,3,4,7,0,4,4,7,0,5,4,7,0,6,4,2,0,7,4,2,0,8,4,2,0,9,4,2, +0,10,4,7,0,11,4,7,0,12,4,7,0,13,4,7,0,14,4,2,0,15,4,2,0,16,4,2,0,17,4,2, +0,18,4,7,0,19,4,7,0,20,4,7,0,21,4,7,0,22,4,2,0,23,4,2,0,24,4,2,0,25,4,2, +0,43,0,7,0,26,4,7,0,27,4,36,0,79,0,50,0,77,1,30,0,-103,0,39,0,125,0,-99,0,16,0,2, +0,28,4,2,0,29,4,2,0,30,4,2,0,20,0,2,0,31,4,2,0,32,4,2,0,33,4,2,0,34,4,2, +0,35,4,2,0,36,4,2,0,37,4,2,0,38,4,4,0,39,4,7,0,40,4,7,0,41,4,7,0,42,4,-98, +0,8,0,-98,0,0,0,-98,0,1,0,4,0,3,3,4,0,43,4,4,0,20,0,2,0,44,4,2,0,45,4,32, +0,-89,0,-97,0,13,0,9,0,46,4,9,0,47,4,4,0,48,4,4,0,49,4,4,0,50,4,4,0,51,4,4, +0,52,4,4,0,53,4,4,0,54,4,4,0,55,4,4,0,56,4,4,0,37,0,0,0,57,4,-96,0,5,0,9, +0,58,4,9,0,59,4,4,0,60,4,4,0,70,0,0,0,61,4,-95,0,13,0,4,0,18,0,4,0,62,4,4, +0,63,4,4,0,64,4,4,0,65,4,4,0,66,4,4,0,93,0,4,0,67,4,4,0,68,4,4,0,69,4,4, +0,70,4,4,0,71,4,26,0,30,0,-94,0,4,0,4,0,72,4,7,0,73,4,2,0,20,0,2,0,68,2,-93, +0,11,0,-93,0,0,0,-93,0,1,0,0,0,17,0,62,0,74,4,63,0,75,4,4,0,3,3,4,0,76,4,4, +0,77,4,4,0,37,0,4,0,78,4,4,0,79,4,-92,0,-126,0,-97,0,80,4,-96,0,81,4,-95,0,82,4,4, +0,83,4,4,0,-126,0,4,0,-97,3,4,0,84,4,4,0,85,4,4,0,86,4,4,0,87,4,2,0,20,0,2, +0,88,4,7,0,20,3,7,0,89,4,7,0,90,4,7,0,91,4,7,0,92,4,7,0,93,4,2,0,94,4,2, +0,95,4,2,0,96,4,2,0,97,4,2,0,-39,0,2,0,98,4,2,0,99,4,2,0,100,3,2,0,100,4,2, +0,101,4,2,0,34,1,2,0,109,0,2,0,102,4,2,0,103,4,2,0,104,4,2,0,105,4,2,0,106,4,2, +0,107,4,2,0,108,4,2,0,109,4,2,0,110,4,2,0,35,1,2,0,111,4,2,0,112,4,2,0,113,4,2, +0,114,4,4,0,115,4,4,0,13,1,2,0,116,4,2,0,117,4,2,0,118,4,2,0,119,4,2,0,120,4,2, +0,121,4,24,0,122,4,24,0,123,4,23,0,124,4,12,0,125,4,2,0,126,4,2,0,37,0,7,0,127,4,7, +0,-128,4,7,0,-127,4,7,0,-126,4,7,0,-125,4,7,0,-124,4,7,0,-123,4,7,0,-122,4,7,0,-121,4,2, +0,-120,4,2,0,-119,4,2,0,-118,4,2,0,-117,4,2,0,-116,4,2,0,-115,4,7,0,-114,4,7,0,-113,4,7, +0,-112,4,2,0,-111,4,2,0,-110,4,2,0,-109,4,2,0,-108,4,2,0,-107,4,2,0,-106,4,2,0,-105,4,2, +0,-104,4,2,0,-103,4,2,0,-102,4,4,0,-101,4,4,0,-100,4,4,0,-99,4,4,0,-98,4,4,0,-97,4,7, +0,-96,4,4,0,-95,4,4,0,-94,4,4,0,-93,4,4,0,-92,4,7,0,-91,4,7,0,-90,4,7,0,-89,4,7, +0,-88,4,7,0,-87,4,7,0,-86,4,7,0,-85,4,7,0,-84,4,7,0,-83,4,0,0,-82,4,0,0,-81,4,4, +0,-80,4,2,0,-79,4,2,0,12,1,0,0,-78,4,7,0,-77,4,7,0,-76,4,4,0,-75,4,4,0,-74,4,7, +0,-73,4,7,0,-72,4,2,0,-71,4,2,0,-70,4,7,0,-69,4,2,0,-68,4,2,0,-67,4,4,0,-66,4,2, +0,-65,4,2,0,-64,4,2,0,-63,4,2,0,-62,4,7,0,-61,4,7,0,70,0,42,0,-60,4,-91,0,9,0,-91, +0,0,0,-91,0,1,0,0,0,17,0,2,0,-59,4,2,0,-58,4,2,0,-57,4,2,0,43,0,7,0,-56,4,7, +0,70,0,-90,0,5,0,7,0,-55,4,0,0,18,0,0,0,43,0,0,0,70,0,0,0,12,1,-89,0,5,0,-89, +0,0,0,-89,0,1,0,4,0,-54,4,0,0,-53,4,4,0,20,0,-88,0,5,0,-87,0,-52,4,2,0,20,0,2, +0,-51,4,2,0,-50,4,2,0,-49,4,-86,0,4,0,2,0,109,0,2,0,-122,2,2,0,-48,4,2,0,-47,4,-85, +0,7,0,2,0,20,0,2,0,-46,4,2,0,-45,4,2,0,-44,4,-86,0,-43,4,7,0,-42,4,4,0,-41,4,-84, +0,4,0,-84,0,0,0,-84,0,1,0,0,0,-40,4,7,0,-39,4,-83,0,56,0,2,0,-38,4,2,0,-37,4,7, +0,-36,4,7,0,-35,4,2,0,-48,4,2,0,-34,4,7,0,-33,4,7,0,-32,4,2,0,-31,4,2,0,-30,4,2, +0,-29,4,2,0,-28,4,7,0,-27,4,7,0,-26,4,7,0,-25,4,7,0,37,0,2,0,-24,4,2,0,-23,4,2, +0,-22,4,2,0,-21,4,-88,0,-20,4,-85,0,-19,4,7,0,-18,4,7,0,-17,4,0,0,-16,4,0,0,-15,4,0, +0,-14,4,0,0,-13,4,0,0,-12,4,0,0,-11,4,2,0,-10,4,7,0,-9,4,7,0,-8,4,7,0,-7,4,7, +0,-6,4,7,0,-5,4,7,0,-4,4,7,0,-3,4,7,0,-2,4,7,0,-1,4,7,0,0,5,2,0,1,5,0, +0,2,5,0,0,3,5,0,0,4,5,0,0,5,5,32,0,6,5,0,0,7,5,0,0,8,5,0,0,9,5,0, +0,10,5,0,0,11,5,0,0,12,5,0,0,13,5,0,0,14,5,0,0,15,5,-82,0,6,0,2,0,109,0,0, +0,-122,2,0,0,16,5,0,0,17,5,0,0,20,0,0,0,-74,0,-81,0,26,0,-80,0,18,5,50,0,77,1,60, +0,19,5,-82,0,20,5,-82,0,21,5,-82,0,22,5,-82,0,23,5,-82,0,24,5,-82,0,25,5,-82,0,26,5,7, +0,27,5,2,0,28,5,2,0,47,1,2,0,29,5,2,0,1,2,0,0,30,5,0,0,31,5,0,0,32,5,0, +0,33,5,0,0,93,0,0,0,34,5,0,0,35,5,0,0,36,5,0,0,37,5,0,0,38,5,0,0,-74,0,-79, +0,43,0,27,0,31,0,32,0,39,5,-100,0,40,5,-79,0,41,5,46,0,-47,0,12,0,42,5,-98,0,43,5,7, +0,44,5,7,0,45,5,7,0,46,5,7,0,47,5,4,0,3,3,7,0,48,5,2,0,49,5,2,0,50,5,2, +0,51,5,2,0,52,5,2,0,53,5,2,0,54,5,2,0,55,5,2,0,5,1,57,0,1,1,9,0,56,5,-99, +0,57,5,-90,0,58,5,-83,0,59,5,-92,0,-73,0,-94,0,60,5,39,0,125,0,12,0,103,0,12,0,61,5,2, +0,62,5,2,0,63,5,2,0,64,5,2,0,65,5,-78,0,66,5,2,0,67,5,2,0,68,5,2,0,64,1,2, +0,-38,0,-81,0,69,5,4,0,70,5,4,0,37,0,-77,0,9,0,46,0,-47,0,45,0,0,1,7,0,8,2,7, +0,9,2,7,0,109,0,7,0,71,5,7,0,72,5,2,0,73,5,2,0,74,5,-76,0,75,0,-75,0,0,0,-75, +0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,7,0,79,5,7,0,80,5,7,0,81,5,7, +0,82,5,7,0,83,5,7,0,84,5,7,0,85,5,7,0,20,1,7,0,86,5,4,0,87,5,2,0,88,5,2, +0,17,5,32,0,39,5,32,0,89,5,-77,0,90,5,-76,0,91,5,-73,0,92,5,-72,0,93,5,-71,0,94,5,0, +0,95,5,2,0,30,4,2,0,96,5,4,0,3,3,4,0,97,5,2,0,98,5,2,0,99,5,2,0,100,5,0, +0,101,5,0,0,43,0,7,0,115,0,7,0,102,5,7,0,103,5,7,0,104,5,7,0,105,5,7,0,106,5,7, +0,107,5,7,0,108,5,7,0,-82,0,7,0,44,5,2,0,109,5,2,0,110,5,2,0,111,5,2,0,112,5,2, +0,-119,0,2,0,29,5,2,0,113,5,2,0,114,5,2,0,115,5,2,0,116,5,7,0,117,5,7,0,118,5,67, +0,119,5,12,0,120,5,2,0,121,5,2,0,53,2,2,0,122,5,2,0,20,0,2,0,123,5,2,0,124,5,2, +0,125,5,0,0,126,5,0,0,127,5,9,0,-128,5,-70,0,-127,5,7,0,-126,5,2,0,-125,5,2,0,-124,5,2, +0,53,5,2,0,54,5,-69,0,19,0,24,0,36,0,24,0,64,0,23,0,-123,5,23,0,-122,5,23,0,-121,5,7, +0,-120,5,7,0,-119,5,7,0,-118,5,7,0,-117,5,2,0,-116,5,2,0,-115,5,2,0,-114,5,2,0,-113,5,2, +0,-112,5,2,0,-111,5,4,0,20,0,7,0,-110,5,2,0,99,5,0,0,107,2,-75,0,6,0,-75,0,0,0,-75, +0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,-68,0,6,0,-75,0,0,0,-75,0,1,0,4, +0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,-67,0,27,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7, +0,76,5,-74,0,77,5,2,0,78,5,4,0,-109,5,4,0,70,0,-69,0,-108,5,9,0,-107,5,12,0,-106,5,36, +0,79,0,27,0,80,0,0,0,-105,5,0,0,-104,5,0,0,-103,5,2,0,-102,5,2,0,-101,5,2,0,-100,5,2, +0,-99,5,2,0,65,0,2,0,46,0,2,0,-119,0,2,0,-98,5,4,0,20,0,7,0,-97,5,24,0,36,0,-66, +0,29,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,-73,0,92,5,2,0,78,5,2, +0,-96,5,2,0,-95,5,2,0,-94,5,2,0,-93,5,-69,0,-108,5,2,0,-92,5,2,0,-119,0,2,0,-101,5,2, +0,-91,5,9,0,-90,5,2,0,29,5,0,0,-89,5,0,0,-88,5,2,0,-87,5,2,0,-86,5,2,0,12,3,2, +0,-85,5,2,0,-84,5,0,0,37,0,0,0,20,0,0,0,47,1,0,0,-83,5,-65,0,16,0,-75,0,0,0,-75, +0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,-69,0,-108,5,7,0,8,2,7,0,9,2,2, +0,-92,5,2,0,-82,5,2,0,-81,5,2,0,-80,5,4,0,20,0,7,0,71,5,-70,0,-127,5,-64,0,33,0,-75, +0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,-63,0,-79,5,4,0,-78,5,0, +0,-77,5,0,0,-76,5,0,0,-75,5,2,0,18,0,2,0,-74,5,2,0,20,0,2,0,-73,5,2,0,-72,5,2, +0,-71,5,2,0,-70,5,2,0,43,0,4,0,70,0,0,0,-69,5,-62,0,-68,5,2,0,-67,5,2,0,-66,5,2, +0,-65,5,2,0,-48,0,9,0,-64,5,9,0,-63,5,9,0,-62,5,9,0,-61,5,9,0,-60,5,2,0,-59,5,0, +0,-58,5,-61,0,23,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,-69, +0,-108,5,12,0,-57,5,2,0,-101,5,2,0,-56,5,2,0,20,0,2,0,57,0,9,0,-90,5,12,0,-55,5,-60, +0,-54,5,0,0,-53,5,-59,0,-52,5,4,0,-51,5,4,0,-50,5,2,0,18,0,2,0,-49,5,2,0,-48,5,2, +0,-47,5,-58,0,29,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,-69, +0,-108,5,46,0,-114,2,45,0,0,1,60,0,19,5,2,0,13,1,2,0,-119,0,2,0,-46,5,2,0,-45,5,4, +0,20,0,2,0,49,5,2,0,-44,5,2,0,-98,5,2,0,-101,5,7,0,71,5,0,0,-43,5,0,0,-42,5,0, +0,-41,5,0,0,-40,5,7,0,8,2,7,0,9,2,7,0,-39,5,7,0,-38,5,-70,0,-127,5,-57,0,11,0,-75, +0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,2,0,-119,0,2,0,-98,5,2, +0,-37,5,2,0,20,0,-69,0,-108,5,-56,0,24,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74, +0,77,5,2,0,78,5,42,0,-36,5,4,0,-35,5,4,0,-34,5,2,0,93,0,2,0,-119,0,4,0,-33,5,4, +0,-32,5,4,0,-31,5,4,0,-30,5,4,0,-29,5,4,0,-28,5,4,0,-27,5,4,0,-26,5,7,0,-25,5,23, +0,-24,5,23,0,-23,5,4,0,-22,5,4,0,-21,5,-55,0,10,0,27,0,31,0,9,0,-20,5,9,0,-19,5,9, +0,-18,5,9,0,-17,5,9,0,-16,5,4,0,93,0,4,0,-15,5,0,0,-14,5,0,0,-13,5,-54,0,10,0,-75, +0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,-55,0,-12,5,2,0,93,0,2,0,-119,0,4, +0,43,0,9,0,-11,5,-53,0,8,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,-69, +0,-108,5,4,0,20,0,4,0,-10,5,-52,0,21,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74, +0,77,5,2,0,78,5,-69,0,-108,5,27,0,-9,5,27,0,80,0,2,0,20,0,2,0,-119,0,7,0,-8,5,9, +0,-7,5,7,0,8,2,7,0,9,2,57,0,1,1,57,0,-6,5,4,0,-5,5,2,0,-89,5,2,0,37,0,-70, +0,-127,5,-51,0,42,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74,0,77,5,2,0,78,5,-69, +0,-108,5,-50,0,-4,5,0,0,-77,5,0,0,-76,5,0,0,-75,5,2,0,18,0,2,0,-66,5,2,0,20,0,2, +0,-73,5,9,0,-7,5,4,0,-3,5,4,0,-2,5,4,0,-1,5,4,0,0,6,23,0,1,6,23,0,2,6,7, +0,3,6,7,0,4,6,7,0,5,6,7,0,-8,5,2,0,-67,5,2,0,-48,0,2,0,102,1,2,0,6,6,2, +0,37,0,2,0,43,0,2,0,7,6,2,0,8,6,9,0,-64,5,9,0,-63,5,9,0,-62,5,9,0,-61,5,9, +0,-60,5,2,0,-59,5,0,0,-58,5,56,0,9,6,-49,0,20,0,0,0,10,6,0,0,11,6,0,0,12,6,0, +0,13,6,0,0,14,6,0,0,15,6,0,0,16,6,0,0,17,6,0,0,18,6,0,0,19,6,0,0,20,6,0, +0,21,6,0,0,22,6,0,0,23,6,0,0,24,6,0,0,25,6,0,0,26,6,0,0,27,6,0,0,68,2,0, +0,28,6,-48,0,54,0,0,0,29,6,0,0,20,6,0,0,21,6,0,0,30,6,0,0,31,6,0,0,32,6,0, +0,33,6,0,0,34,6,0,0,35,6,0,0,36,6,0,0,37,6,0,0,38,6,0,0,39,6,0,0,40,6,0, +0,41,6,0,0,42,6,0,0,43,6,0,0,44,6,0,0,45,6,0,0,46,6,0,0,47,6,0,0,48,6,0, +0,49,6,0,0,50,6,0,0,51,6,0,0,52,6,0,0,53,6,0,0,54,6,0,0,55,6,0,0,56,6,0, +0,57,6,0,0,58,6,0,0,95,0,0,0,59,6,0,0,60,6,0,0,61,6,0,0,62,6,0,0,63,6,0, +0,64,6,0,0,65,6,0,0,66,6,0,0,67,6,0,0,68,6,0,0,69,6,0,0,70,6,0,0,71,6,0, +0,72,6,0,0,73,6,0,0,74,6,0,0,75,6,0,0,76,6,0,0,77,6,0,0,78,6,0,0,79,6,-47, +0,5,0,0,0,80,6,0,0,37,6,0,0,39,6,2,0,20,0,2,0,37,0,-46,0,22,0,-46,0,0,0,-46, +0,1,0,0,0,17,0,-49,0,81,6,-48,0,82,6,-48,0,83,6,-48,0,84,6,-48,0,85,6,-48,0,86,6,-48, +0,87,6,-48,0,88,6,-48,0,89,6,-48,0,90,6,-48,0,91,6,-48,0,92,6,-48,0,93,6,-48,0,94,6,-48, +0,95,6,-48,0,96,6,-47,0,97,6,0,0,98,6,0,0,99,6,-45,0,5,0,4,0,20,0,4,0,37,0,7, +0,52,2,7,0,100,6,7,0,-31,1,-44,0,66,0,4,0,20,0,4,0,101,6,4,0,102,6,0,0,103,6,0, +0,104,6,0,0,105,6,0,0,106,6,0,0,107,6,0,0,108,6,0,0,109,6,0,0,110,6,0,0,111,6,2, +0,112,6,2,0,113,6,4,0,114,6,4,0,115,6,4,0,116,6,4,0,117,6,2,0,118,6,2,0,119,6,2, +0,120,6,2,0,121,6,4,0,122,6,4,0,123,6,2,0,124,6,2,0,125,6,2,0,126,6,2,0,127,6,0, +0,-128,6,12,0,-127,6,2,0,-126,6,2,0,-125,6,2,0,-124,6,2,0,-123,6,2,0,-122,6,2,0,-121,6,2, +0,-120,6,2,0,-119,6,-45,0,-118,6,2,0,-117,6,2,0,-116,6,2,0,-115,6,2,0,-114,6,4,0,-113,6,4, +0,-112,6,4,0,-111,6,4,0,-110,6,2,0,-109,6,2,0,-108,6,2,0,-107,6,2,0,-106,6,2,0,-105,6,2, +0,-104,6,2,0,-103,6,2,0,-102,6,2,0,-101,6,2,0,-100,6,2,0,-99,6,2,0,37,0,0,0,-98,6,0, +0,-97,6,0,0,-96,6,7,0,-95,6,2,0,55,5,2,0,-94,6,54,0,-93,6,-43,0,18,0,27,0,31,0,12, +0,-92,6,12,0,-91,6,12,0,-90,6,-79,0,-89,6,2,0,-105,2,2,0,-88,6,2,0,-104,2,2,0,-87,6,2, +0,-86,6,2,0,-85,6,2,0,-84,6,2,0,-83,6,2,0,-82,6,2,0,37,0,2,0,-81,6,2,0,-80,6,2, +0,-79,6,-42,0,5,0,-42,0,0,0,-42,0,1,0,-42,0,-78,6,13,0,-77,6,4,0,20,0,-41,0,7,0,-41, +0,0,0,-41,0,1,0,-42,0,-76,6,-42,0,-75,6,2,0,123,4,2,0,20,0,4,0,37,0,-40,0,17,0,-40, +0,0,0,-40,0,1,0,0,0,-74,6,0,0,-73,6,0,0,-72,6,2,0,-71,6,2,0,-70,6,2,0,-86,6,2, +0,-85,6,2,0,20,0,2,0,70,3,2,0,-69,6,2,0,-68,6,2,0,-67,6,2,0,-66,6,4,0,-65,6,-40, +0,-64,6,-74,0,30,0,-74,0,0,0,-74,0,1,0,-42,0,-76,6,-42,0,-75,6,-42,0,-63,6,-42,0,-62,6,-43, +0,-61,6,7,0,-60,6,23,0,52,0,23,0,-59,6,23,0,-58,6,2,0,-57,6,2,0,-56,6,2,0,-55,6,0, +0,75,5,0,0,-54,6,2,0,-53,6,2,0,-52,6,0,0,-51,6,0,0,-50,6,0,0,-49,6,0,0,-48,6,2, +0,-47,6,2,0,-46,6,2,0,-45,6,2,0,20,0,39,0,125,0,12,0,-44,6,12,0,-43,6,12,0,-42,6,-39, +0,11,0,0,0,-41,6,2,0,-40,6,2,0,-39,6,2,0,-38,6,2,0,-37,6,2,0,-36,6,2,0,107,4,9, +0,-35,6,9,0,-34,6,4,0,-33,6,4,0,-32,6,-38,0,1,0,0,0,-31,6,-37,0,8,0,56,0,-30,6,56, +0,-29,6,-37,0,-28,6,-37,0,-27,6,-37,0,-26,6,2,0,-123,0,2,0,20,0,4,0,-25,6,-36,0,4,0,4, +0,-35,5,4,0,-24,6,4,0,-31,5,4,0,-23,6,-35,0,2,0,4,0,-22,6,4,0,-21,6,-34,0,9,0,7, +0,-20,6,7,0,-19,6,7,0,-18,6,4,0,20,0,4,0,13,1,7,0,-19,3,7,0,-17,6,4,0,37,0,-33, +0,-16,6,-32,0,6,0,0,0,-15,6,0,0,-75,5,48,0,-116,0,2,0,109,0,2,0,111,4,4,0,37,0,-31, +0,21,0,-31,0,0,0,-31,0,1,0,4,0,57,0,4,0,23,0,4,0,28,0,4,0,-14,6,4,0,-13,6,4, +0,-12,6,-38,0,-11,6,0,0,-15,6,4,0,-10,6,4,0,-9,6,-32,0,-12,2,-36,0,-8,6,-35,0,-7,6,-34, +0,-6,6,-37,0,-5,6,-37,0,-4,6,-37,0,-3,6,56,0,-2,6,56,0,-1,6,-30,0,12,0,0,0,-68,1,9, +0,-62,0,0,0,-61,0,4,0,-58,0,4,0,-50,0,9,0,-57,0,7,0,-55,0,7,0,-54,0,9,0,0,7,9, +0,1,7,9,0,-53,0,9,0,-51,0,-29,0,43,0,-29,0,0,0,-29,0,1,0,9,0,2,7,9,0,26,0,0, +0,27,0,4,0,20,0,4,0,18,0,4,0,23,0,4,0,91,0,4,0,3,7,4,0,4,7,4,0,-13,6,4, +0,-12,6,4,0,5,7,4,0,-39,0,4,0,6,7,4,0,7,7,7,0,8,7,7,0,9,7,4,0,-126,0,4, +0,10,7,-31,0,11,7,36,0,79,0,-79,0,-89,6,48,0,-116,0,7,0,12,7,7,0,13,7,-30,0,2,1,-29, +0,14,7,-29,0,15,7,-29,0,16,7,12,0,17,7,-28,0,18,7,-27,0,19,7,7,0,20,7,7,0,21,7,4, +0,-84,6,7,0,22,7,9,0,23,7,4,0,24,7,4,0,25,7,4,0,26,7,7,0,27,7,-26,0,4,0,-26, +0,0,0,-26,0,1,0,12,0,28,7,-29,0,29,7,-25,0,6,0,12,0,30,7,12,0,17,7,12,0,31,7,2, +0,20,0,2,0,37,0,4,0,57,0,-24,0,4,0,7,0,32,7,7,0,112,0,2,0,33,7,2,0,34,7,-23, +0,6,0,7,0,35,7,7,0,36,7,7,0,37,7,7,0,38,7,4,0,39,7,4,0,40,7,-22,0,12,0,7, +0,41,7,7,0,42,7,7,0,43,7,7,0,44,7,7,0,45,7,7,0,46,7,7,0,47,7,7,0,48,7,7, +0,49,7,7,0,50,7,4,0,-110,2,4,0,51,7,-21,0,2,0,7,0,-55,4,7,0,37,0,-20,0,7,0,7, +0,52,7,7,0,53,7,4,0,93,0,4,0,108,2,4,0,54,7,4,0,55,7,4,0,37,0,-19,0,6,0,-19, +0,0,0,-19,0,1,0,2,0,18,0,2,0,20,0,2,0,56,7,2,0,57,0,-18,0,8,0,-18,0,0,0,-18, +0,1,0,2,0,18,0,2,0,20,0,2,0,56,7,2,0,57,0,7,0,23,0,7,0,-126,0,-17,0,45,0,-17, +0,0,0,-17,0,1,0,2,0,18,0,2,0,20,0,2,0,56,7,2,0,-43,0,2,0,-103,3,2,0,57,7,7, +0,58,7,7,0,92,0,7,0,-97,2,4,0,59,7,4,0,81,0,4,0,110,2,7,0,60,7,7,0,61,7,7, +0,62,7,7,0,63,7,7,0,64,7,7,0,65,7,7,0,-100,2,7,0,-1,0,7,0,66,7,7,0,67,7,7, +0,37,0,7,0,68,7,7,0,69,7,7,0,70,7,2,0,71,7,2,0,72,7,2,0,73,7,2,0,74,7,2, +0,75,7,2,0,76,7,2,0,77,7,2,0,78,7,2,0,123,5,2,0,79,7,2,0,-47,1,2,0,80,7,0, +0,81,7,0,0,82,7,7,0,-45,0,-16,0,83,7,63,0,-95,1,-15,0,16,0,-15,0,0,0,-15,0,1,0,2, +0,18,0,2,0,20,0,2,0,56,7,2,0,-43,0,7,0,-105,2,7,0,-104,2,7,0,-103,2,7,0,-5,1,7, +0,-102,2,7,0,-101,2,7,0,84,7,7,0,-100,2,7,0,-98,2,7,0,-97,2,-59,0,5,0,2,0,18,0,2, +0,-25,6,2,0,20,0,2,0,85,7,27,0,-9,5,-60,0,3,0,4,0,69,0,4,0,86,7,-59,0,2,0,-14, +0,12,0,-14,0,0,0,-14,0,1,0,2,0,18,0,2,0,20,0,2,0,31,3,2,0,-32,1,7,0,5,0,7, +0,6,0,7,0,87,7,7,0,88,7,27,0,-9,5,12,0,89,7,-13,0,11,0,-13,0,0,0,-13,0,1,0,0, +0,17,0,2,0,18,0,2,0,90,7,4,0,22,0,4,0,91,7,2,0,20,0,2,0,37,0,9,0,92,7,9, +0,93,7,-12,0,5,0,0,0,17,0,7,0,20,1,7,0,94,7,4,0,95,7,4,0,37,0,-11,0,4,0,2, +0,18,0,2,0,20,0,2,0,43,0,2,0,70,0,-10,0,4,0,0,0,17,0,62,0,96,7,7,0,20,1,7, +0,37,0,-9,0,6,0,2,0,97,7,2,0,98,7,2,0,18,0,2,0,99,7,0,0,100,7,0,0,101,7,-8, +0,5,0,4,0,18,0,4,0,37,0,0,0,17,0,0,0,102,7,0,0,103,7,-7,0,3,0,4,0,18,0,4, +0,37,0,0,0,17,0,-6,0,4,0,2,0,104,7,2,0,105,7,2,0,20,0,2,0,37,0,-5,0,6,0,0, +0,17,0,0,0,106,7,2,0,107,7,2,0,-100,2,2,0,13,1,2,0,70,0,-4,0,5,0,0,0,17,0,7, +0,112,0,7,0,-17,3,2,0,20,0,2,0,122,2,-3,0,3,0,0,0,17,0,4,0,110,2,4,0,104,7,-2, +0,7,0,0,0,17,0,7,0,-17,3,0,0,108,7,0,0,109,7,2,0,13,1,2,0,43,0,4,0,110,7,-1, +0,3,0,32,0,111,7,0,0,112,7,0,0,113,7,0,1,18,0,0,1,0,0,0,1,1,0,2,0,18,0,2, +0,90,7,2,0,20,0,2,0,114,7,2,0,115,7,2,0,116,7,2,0,43,0,2,0,70,0,0,0,17,0,9, +0,2,0,1,1,117,7,32,0,45,0,2,0,-47,4,2,0,20,7,2,0,118,7,2,0,37,0,2,1,11,0,0, +0,17,0,0,0,18,0,0,0,119,7,2,0,20,0,2,0,122,2,2,0,120,7,4,0,121,7,4,0,122,7,4, +0,123,7,4,0,124,7,4,0,125,7,3,1,1,0,0,0,126,7,4,1,4,0,42,0,-36,5,0,0,127,7,4, +0,13,1,4,0,20,0,1,1,18,0,1,1,0,0,1,1,1,0,1,1,-128,7,2,0,18,0,2,0,20,0,2, +0,-127,7,2,0,116,7,2,0,90,7,2,0,-126,7,2,0,70,0,2,0,12,1,0,0,17,0,9,0,2,0,5, +1,117,7,0,1,-125,7,2,0,15,0,2,0,-124,7,4,0,-123,7,6,1,3,0,4,0,-74,2,4,0,37,0,32, +0,45,0,7,1,12,0,-111,0,-122,7,2,0,18,0,2,0,20,0,4,0,58,7,4,0,92,0,0,0,17,0,0, +0,-121,7,2,0,-120,7,2,0,-119,7,2,0,-118,7,2,0,-117,7,7,0,-116,7,8,1,10,0,2,0,20,0,2, +0,-115,7,4,0,58,7,4,0,92,0,2,0,-114,7,-28,0,18,7,2,0,18,0,2,0,-113,7,2,0,-112,7,2, +0,-111,7,9,1,7,0,2,0,20,0,2,0,-115,7,4,0,58,7,4,0,92,0,2,0,18,0,2,0,-110,7,7, +0,109,3,10,1,11,0,4,0,-74,2,2,0,18,0,2,0,20,0,32,0,45,0,74,0,-109,7,0,0,17,0,7, +0,-108,7,7,0,-107,7,7,0,21,3,2,0,-106,7,2,0,-105,7,11,1,5,0,2,0,18,0,2,0,20,0,4, +0,37,0,-79,0,-89,6,32,0,39,5,12,1,5,0,4,0,20,0,4,0,18,0,0,0,17,0,0,0,102,7,32, +0,45,0,13,1,13,0,2,0,20,0,2,0,18,0,2,0,90,7,2,0,22,3,7,0,-104,7,7,0,-103,7,7, +0,7,1,7,0,8,1,7,0,-3,2,7,0,0,3,7,0,-102,7,7,0,-101,7,32,0,-100,7,14,1,10,0,2, +0,20,0,2,0,18,0,4,0,58,7,4,0,92,0,0,0,17,0,0,0,-121,7,2,0,43,0,2,0,64,0,2, +0,-99,7,2,0,-98,7,15,1,8,0,32,0,45,0,7,0,-103,2,7,0,-97,7,7,0,-96,7,7,0,-108,2,2, +0,20,0,2,0,122,2,7,0,-95,7,16,1,12,0,2,0,18,0,2,0,13,1,2,0,20,0,2,0,-100,2,2, +0,-74,2,2,0,-94,7,4,0,37,0,7,0,-93,7,7,0,-92,7,7,0,-91,7,7,0,-90,7,0,0,-89,7,17, +1,10,0,2,0,20,0,2,0,18,0,4,0,58,7,4,0,92,0,0,0,17,0,2,0,68,2,2,0,64,0,2, +0,-99,7,2,0,-98,7,63,0,-95,1,18,1,7,0,4,0,110,2,4,0,-88,7,4,0,-87,7,4,0,-86,7,7, +0,-85,7,7,0,-84,7,0,0,108,7,19,1,7,0,0,0,-83,7,32,0,-82,7,0,0,112,7,2,0,-81,7,2, +0,43,0,4,0,70,0,0,0,113,7,20,1,6,0,2,0,20,0,2,0,18,0,4,0,58,7,4,0,92,0,0, +0,-80,7,0,0,-79,7,21,1,1,0,4,0,20,0,22,1,6,0,0,0,95,0,2,0,18,0,2,0,20,0,4, +0,-78,7,7,0,-77,7,42,0,-36,5,23,1,4,0,0,0,-74,0,2,0,20,0,4,0,18,0,32,0,45,0,24, +1,2,0,4,0,18,0,4,0,-121,5,5,1,10,0,5,1,0,0,5,1,1,0,5,1,-128,7,2,0,18,0,2, +0,20,0,2,0,90,7,2,0,-76,7,0,0,17,0,9,0,2,0,32,0,45,0,25,1,10,0,7,0,21,3,7, +0,-75,7,7,0,-74,7,7,0,-73,7,7,0,-72,7,4,0,20,0,7,0,-94,7,7,0,-71,7,7,0,-70,7,7, +0,37,0,-28,0,20,0,27,0,31,0,0,0,-63,0,26,1,-69,7,9,0,-68,7,43,0,-104,0,43,0,-67,7,9, +0,-66,7,36,0,79,0,7,0,109,3,7,0,-65,7,7,0,-64,7,7,0,-63,7,7,0,-62,7,7,0,-61,7,7, +0,-60,7,4,0,93,0,4,0,-59,7,0,0,-58,7,0,0,-57,7,0,0,-56,7,27,1,6,0,27,0,31,0,7, +0,-55,7,7,0,-54,7,7,0,-53,7,2,0,-52,7,2,0,-51,7,28,1,14,0,-75,0,0,0,-75,0,1,0,4, +0,75,5,7,0,76,5,-74,0,77,5,-69,0,-108,5,-28,0,18,7,2,0,13,1,2,0,-115,7,2,0,8,2,2, +0,9,2,2,0,20,0,2,0,-98,5,4,0,70,0,29,1,6,0,29,1,0,0,29,1,1,0,32,0,45,0,9, +0,-50,7,4,0,-38,0,4,0,37,0,63,0,4,0,27,0,31,0,12,0,-49,7,4,0,-121,0,7,0,-48,7,30, +1,25,0,30,1,0,0,30,1,1,0,30,1,38,0,12,0,-47,7,0,0,17,0,7,0,-46,7,7,0,-45,7,7, +0,-44,7,7,0,-43,7,4,0,20,0,7,0,-42,7,7,0,-41,7,7,0,-40,7,7,0,20,1,7,0,-39,1,7, +0,-39,7,7,0,108,2,7,0,-38,7,7,0,-37,7,7,0,-36,7,7,0,-35,7,7,0,-34,7,7,0,-81,0,2, +0,-121,0,2,0,-31,4,31,1,19,0,27,0,31,0,12,0,-33,7,12,0,-32,7,4,0,20,0,4,0,30,4,2, +0,-96,2,2,0,-31,7,2,0,-121,0,2,0,-30,7,2,0,-29,7,2,0,-28,7,2,0,-27,7,2,0,-26,7,4, +0,-25,7,4,0,-24,7,4,0,-23,7,4,0,-22,7,4,0,-21,7,4,0,-20,7,32,1,34,0,32,1,0,0,32, +1,1,0,12,0,49,3,0,0,17,0,2,0,20,0,2,0,-19,7,2,0,-18,7,2,0,-17,7,2,0,10,3,2, +0,-16,7,4,0,-7,1,4,0,-23,7,4,0,-22,7,30,1,-15,7,32,1,38,0,32,1,-14,7,12,0,-13,7,9, +0,-12,7,9,0,-11,7,9,0,-10,7,7,0,7,1,7,0,-81,0,7,0,-57,1,7,0,-9,7,7,0,-8,7,7, +0,2,3,7,0,-7,7,7,0,-6,7,7,0,-5,7,7,0,-4,7,7,0,-3,7,7,0,-2,7,7,0,-10,1,32, +0,-1,7,-110,0,9,0,12,0,0,8,2,0,20,0,2,0,1,8,7,0,20,3,7,0,2,8,7,0,3,8,12, +0,4,8,4,0,5,8,4,0,37,0,33,1,7,0,33,1,0,0,33,1,1,0,12,0,-58,7,4,0,20,0,4, +0,6,8,0,0,17,0,-47,0,7,8,34,1,8,0,34,1,0,0,34,1,1,0,33,1,8,8,36,0,79,0,12, +0,-6,2,4,0,20,0,0,0,17,0,4,0,9,8,-111,0,6,0,27,0,31,0,12,0,0,8,12,0,10,8,12, +0,103,0,4,0,11,8,4,0,37,0,35,1,16,0,-75,0,0,0,-75,0,1,0,4,0,75,5,7,0,76,5,-74, +0,77,5,2,0,78,5,-69,0,-108,5,-111,0,-9,2,0,0,13,1,0,0,-37,5,2,0,20,0,2,0,12,8,2, +0,-101,5,2,0,-98,5,2,0,13,8,7,0,14,8,36,1,5,0,36,1,0,0,36,1,1,0,36,0,79,0,2, +0,20,0,0,0,15,8,37,1,12,0,37,1,0,0,37,1,1,0,9,0,2,0,2,0,18,0,2,0,20,0,0, +0,16,8,0,0,17,8,0,0,15,8,7,0,18,8,7,0,19,8,4,0,37,0,36,0,79,0,38,1,9,0,38, +1,0,0,38,1,1,0,32,0,20,8,0,0,21,8,7,0,22,8,2,0,23,8,2,0,20,0,2,0,18,0,2, +0,37,0,39,1,7,0,42,0,-36,5,26,0,24,8,4,0,20,0,4,0,25,8,12,0,26,8,32,0,20,8,0, +0,21,8,40,1,12,0,32,0,20,8,2,0,27,8,2,0,20,0,2,0,28,8,2,0,29,8,0,0,21,8,32, +0,30,8,0,0,31,8,7,0,32,8,7,0,-39,1,7,0,33,8,7,0,34,8,41,1,6,0,32,0,20,8,4, +0,9,8,4,0,35,8,4,0,93,0,4,0,37,0,0,0,21,8,42,1,4,0,32,0,20,8,4,0,20,0,4, +0,9,8,0,0,21,8,43,1,4,0,32,0,20,8,4,0,20,0,4,0,9,8,0,0,21,8,44,1,10,0,32, +0,20,8,4,0,36,8,7,0,-127,0,4,0,20,0,2,0,-42,5,2,0,37,8,2,0,43,0,2,0,70,0,7, +0,38,8,0,0,21,8,45,1,4,0,32,0,20,8,4,0,20,0,4,0,9,8,0,0,21,8,46,1,10,0,32, +0,20,8,2,0,18,0,2,0,-95,3,4,0,91,0,4,0,92,0,7,0,-97,7,7,0,-96,7,4,0,37,0,-111, +0,-122,7,0,0,21,8,47,1,4,0,32,0,20,8,4,0,7,3,4,0,39,8,0,0,21,8,48,1,5,0,32, +0,20,8,7,0,-127,0,4,0,40,8,4,0,7,3,4,0,8,3,49,1,6,0,32,0,20,8,4,0,41,8,4, +0,42,8,7,0,43,8,7,0,44,8,0,0,21,8,50,1,16,0,32,0,20,8,32,0,-14,7,4,0,18,0,7, +0,45,8,7,0,46,8,7,0,47,8,7,0,48,8,7,0,49,8,7,0,50,8,7,0,51,8,7,0,52,8,7, +0,53,8,2,0,20,0,2,0,37,0,2,0,43,0,2,0,70,0,51,1,3,0,32,0,20,8,4,0,20,0,4, +0,123,5,52,1,5,0,32,0,20,8,4,0,20,0,4,0,37,0,7,0,54,8,0,0,21,8,53,1,10,0,32, +0,20,8,0,0,21,8,2,0,55,8,2,0,56,8,0,0,57,8,0,0,58,8,7,0,59,8,7,0,60,8,7, +0,61,8,7,0,62,8,54,1,8,0,7,0,9,0,7,0,10,0,7,0,11,0,7,0,12,0,7,0,63,8,7, +0,64,8,2,0,20,0,2,0,123,5,55,1,8,0,7,0,9,0,7,0,10,0,7,0,11,0,7,0,12,0,7, +0,63,8,7,0,64,8,2,0,20,0,2,0,123,5,56,1,8,0,7,0,9,0,7,0,10,0,7,0,11,0,7, +0,12,0,7,0,63,8,7,0,64,8,2,0,20,0,2,0,123,5,57,1,7,0,32,0,20,8,0,0,21,8,7, +0,20,1,7,0,30,1,2,0,20,0,2,0,13,1,4,0,37,0,58,1,5,0,32,0,-45,2,7,0,20,1,2, +0,-41,2,0,0,-39,2,0,0,65,8,59,1,10,0,59,1,0,0,59,1,1,0,2,0,18,0,2,0,20,0,0, +0,66,8,7,0,-36,0,7,0,-35,0,2,0,-58,7,2,0,67,8,32,0,45,0,60,1,22,0,60,1,0,0,60, +1,1,0,2,0,20,0,2,0,13,1,2,0,68,8,2,0,69,8,36,0,79,0,-111,0,-122,7,32,0,-89,0,7, +0,91,0,7,0,92,0,7,0,70,8,7,0,71,8,7,0,72,8,7,0,73,8,7,0,-107,2,7,0,-67,1,7, +0,-120,7,7,0,74,8,0,0,75,8,0,0,76,8,12,0,-4,2,61,1,8,0,7,0,-31,1,7,0,-97,7,7, +0,-96,7,9,0,2,0,2,0,77,8,2,0,78,8,2,0,79,8,2,0,80,8,62,1,18,0,62,1,0,0,62, +1,1,0,62,1,81,8,0,0,17,0,61,1,82,8,2,0,18,0,2,0,20,0,2,0,83,8,2,0,84,8,2, +0,85,8,2,0,86,8,4,0,43,0,7,0,87,8,7,0,88,8,4,0,89,8,4,0,90,8,62,1,91,8,63, +1,92,8,64,1,32,0,64,1,0,0,64,1,1,0,64,1,93,8,0,0,17,0,0,0,94,8,2,0,18,0,2, +0,20,0,2,0,-14,6,2,0,20,7,2,0,95,8,2,0,-119,0,2,0,84,8,2,0,-25,6,12,0,-127,7,12, +0,96,8,27,0,-9,5,9,0,97,8,7,0,87,8,7,0,88,8,7,0,-5,1,7,0,98,8,2,0,99,8,2, +0,100,8,7,0,101,8,7,0,102,8,2,0,103,8,2,0,104,8,24,0,105,8,24,0,106,8,24,0,107,8,65, +1,-103,0,66,1,108,8,63,1,6,0,63,1,0,0,63,1,1,0,64,1,109,8,64,1,110,8,62,1,111,8,62, +1,91,8,57,0,16,0,27,0,31,0,12,0,112,8,12,0,113,8,61,1,114,8,12,0,115,8,4,0,18,0,4, +0,116,8,4,0,117,8,4,0,118,8,12,0,119,8,66,1,120,8,62,1,121,8,62,1,122,8,9,0,123,8,9, +0,124,8,4,0,125,8,67,1,6,0,4,0,-128,0,4,0,-126,0,4,0,-25,6,0,0,126,8,0,0,127,8,2, +0,37,0,68,1,16,0,2,0,-86,6,2,0,-85,6,2,0,-128,8,2,0,-74,7,2,0,-127,8,2,0,68,0,7, +0,-108,2,7,0,-126,8,7,0,-125,8,2,0,34,1,0,0,-124,8,0,0,42,4,2,0,-123,8,2,0,37,0,4, +0,-122,8,4,0,-121,8,69,1,9,0,7,0,-120,8,7,0,-119,8,7,0,-60,7,7,0,112,0,7,0,-118,8,7, +0,71,5,2,0,-117,8,0,0,-116,8,0,0,37,0,70,1,4,0,7,0,-115,8,7,0,-114,8,2,0,-117,8,2, +0,37,0,71,1,3,0,7,0,-113,8,7,0,-112,8,7,0,15,0,72,1,7,0,0,0,-68,1,2,0,109,4,2, +0,110,4,2,0,111,4,2,0,62,4,4,0,-126,0,4,0,-97,3,73,1,7,0,7,0,-111,8,7,0,-110,8,7, +0,-109,8,7,0,4,2,7,0,-108,8,7,0,-107,8,7,0,-106,8,74,1,4,0,2,0,-105,8,2,0,-104,8,2, +0,-103,8,2,0,-102,8,75,1,2,0,7,0,5,0,7,0,6,0,76,1,2,0,0,0,-87,0,0,0,-101,8,77, +1,1,0,0,0,17,0,78,1,10,0,0,0,-100,8,0,0,-99,8,0,0,-98,8,0,0,-97,8,2,0,-128,8,2, +0,-96,8,7,0,-95,8,7,0,-94,8,7,0,-93,8,7,0,-67,1,79,1,2,0,9,0,-92,8,9,0,-91,8,80, +1,11,0,0,0,111,4,0,0,18,0,0,0,-117,8,0,0,112,0,0,0,-90,8,0,0,109,0,0,0,-74,0,7, +0,-89,8,7,0,-88,8,7,0,-87,8,7,0,-86,8,81,1,8,0,7,0,97,7,7,0,-127,0,7,0,42,4,7, +0,72,2,7,0,-85,8,7,0,-49,0,7,0,-84,8,4,0,18,0,82,1,4,0,2,0,-83,8,2,0,-82,8,2, +0,-81,8,2,0,37,0,83,1,1,0,0,0,17,0,84,1,4,0,7,0,5,0,7,0,6,0,2,0,20,0,2, +0,-80,8,85,1,10,0,2,0,-120,3,2,0,20,0,7,0,-17,3,7,0,-79,8,7,0,-78,8,7,0,-77,8,7, +0,-76,8,84,1,-75,8,84,1,-74,8,84,1,-73,8,60,0,9,0,4,0,20,0,4,0,64,0,24,0,-72,8,24, +0,-71,8,85,1,-70,8,7,0,-69,8,7,0,-68,8,7,0,-67,8,7,0,-66,8,86,1,4,0,46,0,-114,2,7, +0,-65,8,7,0,92,1,7,0,37,0,-87,0,13,0,27,0,31,0,2,0,20,0,2,0,72,5,4,0,109,0,7, +0,-64,8,7,0,1,2,7,0,-63,8,7,0,-62,8,7,0,92,1,2,0,47,1,2,0,37,0,50,0,77,1,86, +1,-61,8,87,1,10,0,4,0,18,0,4,0,-127,0,4,0,20,0,4,0,70,3,4,0,-60,8,4,0,-59,8,4, +0,-58,8,0,0,95,0,0,0,17,0,9,0,2,0,84,0,6,0,87,1,-57,8,4,0,-56,8,4,0,-55,8,4, +0,-54,8,4,0,37,0,9,0,-53,8,88,1,5,0,7,0,66,2,7,0,-74,2,7,0,-39,1,2,0,-52,8,2, +0,37,0,89,1,5,0,7,0,66,2,7,0,-51,8,7,0,-50,8,7,0,-49,8,7,0,-74,2,90,1,7,0,4, +0,-48,8,4,0,-47,8,4,0,-46,8,7,0,-45,8,7,0,-44,8,7,0,-43,8,7,0,-42,8,91,1,26,0,32, +0,-41,8,89,1,66,3,89,1,-40,8,88,1,-39,8,89,1,83,7,7,0,-38,8,7,0,-37,8,7,0,-36,8,7, +0,-35,8,7,0,-44,8,7,0,-43,8,7,0,-74,2,7,0,-97,2,7,0,-34,8,7,0,-33,8,7,0,109,0,7, +0,-32,8,4,0,-48,8,4,0,-31,8,4,0,37,0,4,0,81,0,4,0,-30,8,2,0,20,0,2,0,-29,8,2, +0,-28,8,2,0,100,3,92,1,112,0,27,0,31,0,4,0,20,0,2,0,18,0,2,0,55,8,2,0,-27,8,2, +0,-26,8,2,0,-25,8,2,0,-24,8,2,0,-23,8,2,0,-22,8,2,0,-21,8,2,0,-20,8,2,0,-19,8,2, +0,-18,8,2,0,-17,8,2,0,-16,8,2,0,-15,8,2,0,-14,8,2,0,-13,8,2,0,-47,1,2,0,76,7,2, +0,51,7,2,0,-12,8,2,0,-11,8,2,0,98,3,2,0,99,3,2,0,-10,8,2,0,-9,8,2,0,-8,8,2, +0,-7,8,2,0,-6,8,2,0,-5,8,7,0,-4,8,7,0,-3,8,7,0,-2,8,2,0,-1,8,2,0,0,9,7, +0,1,9,7,0,2,9,7,0,3,9,7,0,58,7,7,0,92,0,7,0,-97,2,7,0,64,7,7,0,4,9,7, +0,5,9,7,0,6,9,7,0,7,9,7,0,57,0,4,0,59,7,4,0,57,7,4,0,8,9,7,0,60,7,7, +0,61,7,7,0,62,7,7,0,9,9,7,0,10,9,7,0,11,9,7,0,12,9,7,0,13,9,7,0,14,9,7, +0,15,9,7,0,16,9,7,0,21,3,7,0,109,0,7,0,17,9,7,0,18,9,7,0,19,9,7,0,20,9,7, +0,21,9,7,0,22,9,7,0,108,2,7,0,23,9,7,0,24,9,4,0,25,9,4,0,26,9,7,0,27,9,7, +0,28,9,7,0,29,9,7,0,30,9,7,0,31,9,7,0,32,9,7,0,33,9,7,0,34,9,7,0,94,3,7, +0,92,3,7,0,93,3,7,0,35,9,7,0,36,9,7,0,37,9,7,0,38,9,7,0,39,9,7,0,40,9,7, +0,41,9,7,0,42,9,7,0,43,9,7,0,28,3,7,0,44,9,7,0,45,9,7,0,46,9,7,0,47,9,7, +0,48,9,7,0,49,9,7,0,50,9,0,0,51,9,63,0,55,3,63,0,52,9,32,0,53,9,32,0,54,9,36, +0,79,0,-108,0,53,3,-108,0,55,9,-120,0,37,0,-120,0,0,0,-120,0,1,0,92,1,56,9,91,1,-121,3,90, +1,-14,7,93,1,57,9,94,1,58,9,94,1,59,9,12,0,60,9,12,0,61,9,-107,0,54,3,32,0,62,9,32, +0,63,9,32,0,64,9,12,0,65,9,12,0,66,9,7,0,-45,0,7,0,83,4,4,0,110,2,4,0,20,0,4, +0,59,7,4,0,67,9,4,0,68,9,4,0,69,9,4,0,57,0,2,0,-38,0,2,0,70,9,2,0,71,9,2, +0,72,9,2,0,47,3,2,0,73,9,0,0,74,9,2,0,75,9,2,0,76,9,2,0,77,9,9,0,78,9,125, +0,-76,3,123,0,34,0,95,1,79,9,7,0,-106,3,7,0,80,9,7,0,81,9,7,0,-14,3,7,0,82,9,7, +0,31,3,7,0,21,3,7,0,83,9,7,0,3,2,7,0,84,9,7,0,85,9,7,0,86,9,7,0,87,9,7, +0,88,9,7,0,89,9,7,0,-105,3,7,0,90,9,7,0,91,9,7,0,92,9,7,0,-104,3,7,0,-108,3,7, +0,-107,3,4,0,93,9,4,0,93,0,4,0,94,9,4,0,95,9,2,0,96,9,2,0,97,9,2,0,98,9,2, +0,99,9,2,0,100,9,2,0,37,0,4,0,70,0,124,0,8,0,95,1,101,9,7,0,102,9,7,0,103,9,7, +0,-94,1,7,0,104,9,4,0,93,0,2,0,105,9,2,0,106,9,96,1,4,0,7,0,5,0,7,0,6,0,7, +0,7,0,7,0,107,9,97,1,6,0,97,1,0,0,97,1,1,0,96,1,108,9,4,0,109,9,2,0,110,9,2, +0,20,0,98,1,5,0,98,1,0,0,98,1,1,0,12,0,111,9,4,0,112,9,4,0,20,0,99,1,9,0,99, +1,0,0,99,1,1,0,12,0,-128,0,98,1,113,9,4,0,20,0,2,0,110,9,2,0,114,9,7,0,94,0,0, +0,115,9,-70,0,5,0,12,0,125,4,4,0,20,0,2,0,116,9,2,0,117,9,9,0,118,9,69,78,68,66,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; +int DNAlen= sizeof(DNAstr); diff --git a/Extras/Serialize/BulletFileLoader/CMakeLists.txt b/Extras/Serialize/BulletFileLoader/CMakeLists.txt new file mode 100644 index 0000000..51e33e4 --- /dev/null +++ b/Extras/Serialize/BulletFileLoader/CMakeLists.txt @@ -0,0 +1,49 @@ +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src +) + +SET(BulletFileLoader_SRCS +bChunk.cpp +bDNA.cpp +bFile.cpp +btBulletFile.cpp +) + +SET(BulletFileLoader_HDRS +bChunk.h +bCommon.h +bDefines.h +bDNA.h +bFile.h +btBulletFile.h +) + +ADD_LIBRARY(BulletFileLoader ${BulletFileLoader_SRCS} ${BulletFileLoader_HDRS}) + +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletFileLoader LinearMath) +ENDIF (BUILD_SHARED_LIBS) + +SET_TARGET_PROPERTIES(BulletFileLoader PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletFileLoader PROPERTIES SOVERSION ${BULLET_VERSION}) + +IF (INSTALL_EXTRA_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + #FILES_MATCHING requires CMake 2.6 + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletFileLoader DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletFileLoader DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN +".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletFileLoader PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletFileLoader PROPERTIES PUBLIC_HEADER "${BulletFileLoader_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_EXTRA_LIBS) diff --git a/Extras/Serialize/BulletFileLoader/autogenerated/bullet.h b/Extras/Serialize/BulletFileLoader/autogenerated/bullet.h new file mode 100644 index 0000000..d6278f7 --- /dev/null +++ b/Extras/Serialize/BulletFileLoader/autogenerated/bullet.h @@ -0,0 +1,966 @@ +/* Copyright (C) 2011 Erwin Coumans & Charlie C +* +* 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. +*/ +// Auto generated from Bullet/Extras/HeaderGenerator/bulletGenerate.py +#ifndef __BULLET_H__ +#define __BULLET_H__ +namespace Bullet { + +// put an empty struct in the case +typedef struct bInvalidHandle { + int unused; +}bInvalidHandle; + + class PointerArray; + class btPhysicsSystem; + class ListBase; + class btVector3FloatData; + class btVector3DoubleData; + class btMatrix3x3FloatData; + class btMatrix3x3DoubleData; + class btTransformFloatData; + class btTransformDoubleData; + class btBvhSubtreeInfoData; + class btOptimizedBvhNodeFloatData; + class btOptimizedBvhNodeDoubleData; + class btQuantizedBvhNodeData; + class btQuantizedBvhFloatData; + class btQuantizedBvhDoubleData; + class btCollisionShapeData; + class btStaticPlaneShapeData; + class btConvexInternalShapeData; + class btPositionAndRadius; + class btMultiSphereShapeData; + class btIntIndexData; + class btShortIntIndexData; + class btShortIntIndexTripletData; + class btCharIndexTripletData; + class btMeshPartData; + class btStridingMeshInterfaceData; + class btTriangleMeshShapeData; + class btScaledTriangleMeshShapeData; + class btCompoundShapeChildData; + class btCompoundShapeData; + class btCylinderShapeData; + class btCapsuleShapeData; + class btTriangleInfoData; + class btTriangleInfoMapData; + class btGImpactMeshShapeData; + class btConvexHullShapeData; + class btCollisionObjectDoubleData; + class btCollisionObjectFloatData; + class btRigidBodyFloatData; + class btRigidBodyDoubleData; + class btConstraintInfo1; + class btTypedConstraintData; + class btPoint2PointConstraintFloatData; + class btPoint2PointConstraintDoubleData; + class btHingeConstraintDoubleData; + class btHingeConstraintFloatData; + class btConeTwistConstraintData; + class btGeneric6DofConstraintData; + class btGeneric6DofSpringConstraintData; + class btSliderConstraintData; + class SoftBodyMaterialData; + class SoftBodyNodeData; + class SoftBodyLinkData; + class SoftBodyFaceData; + class SoftBodyTetraData; + class SoftRigidAnchorData; + class SoftBodyConfigData; + class SoftBodyPoseData; + class SoftBodyClusterData; + class btSoftBodyJointData; + class btSoftBodyFloatData; +// -------------------------------------------------- // + class PointerArray + { + public: + int m_size; + int m_capacity; + void *m_data; + }; + + +// -------------------------------------------------- // + class btPhysicsSystem + { + public: + PointerArray m_collisionShapes; + PointerArray m_collisionObjects; + PointerArray m_constraints; + }; + + +// -------------------------------------------------- // + class ListBase + { + public: + void *first; + void *last; + }; + + +// -------------------------------------------------- // + class btVector3FloatData + { + public: + float m_floats[4]; + }; + + +// -------------------------------------------------- // + class btVector3DoubleData + { + public: + double m_floats[4]; + }; + + +// -------------------------------------------------- // + class btMatrix3x3FloatData + { + public: + btVector3FloatData m_el[3]; + }; + + +// -------------------------------------------------- // + class btMatrix3x3DoubleData + { + public: + btVector3DoubleData m_el[3]; + }; + + +// -------------------------------------------------- // + class btTransformFloatData + { + public: + btMatrix3x3FloatData m_basis; + btVector3FloatData m_origin; + }; + + +// -------------------------------------------------- // + class btTransformDoubleData + { + public: + btMatrix3x3DoubleData m_basis; + btVector3DoubleData m_origin; + }; + + +// -------------------------------------------------- // + class btBvhSubtreeInfoData + { + public: + int m_rootNodeIndex; + int m_subtreeSize; + short m_quantizedAabbMin[3]; + short m_quantizedAabbMax[3]; + }; + + +// -------------------------------------------------- // + class btOptimizedBvhNodeFloatData + { + public: + btVector3FloatData m_aabbMinOrg; + btVector3FloatData m_aabbMaxOrg; + int m_escapeIndex; + int m_subPart; + int m_triangleIndex; + char m_pad[4]; + }; + + +// -------------------------------------------------- // + class btOptimizedBvhNodeDoubleData + { + public: + btVector3DoubleData m_aabbMinOrg; + btVector3DoubleData m_aabbMaxOrg; + int m_escapeIndex; + int m_subPart; + int m_triangleIndex; + char m_pad[4]; + }; + + +// -------------------------------------------------- // + class btQuantizedBvhNodeData + { + public: + short m_quantizedAabbMin[3]; + short m_quantizedAabbMax[3]; + int m_escapeIndexOrTriangleIndex; + }; + + +// -------------------------------------------------- // + class btQuantizedBvhFloatData + { + public: + btVector3FloatData m_bvhAabbMin; + btVector3FloatData m_bvhAabbMax; + btVector3FloatData m_bvhQuantization; + int m_curNodeIndex; + int m_useQuantization; + int m_numContiguousLeafNodes; + int m_numQuantizedContiguousNodes; + btOptimizedBvhNodeFloatData *m_contiguousNodesPtr; + btQuantizedBvhNodeData *m_quantizedContiguousNodesPtr; + btBvhSubtreeInfoData *m_subTreeInfoPtr; + int m_traversalMode; + int m_numSubtreeHeaders; + }; + + +// -------------------------------------------------- // + class btQuantizedBvhDoubleData + { + public: + btVector3DoubleData m_bvhAabbMin; + btVector3DoubleData m_bvhAabbMax; + btVector3DoubleData m_bvhQuantization; + int m_curNodeIndex; + int m_useQuantization; + int m_numContiguousLeafNodes; + int m_numQuantizedContiguousNodes; + btOptimizedBvhNodeDoubleData *m_contiguousNodesPtr; + btQuantizedBvhNodeData *m_quantizedContiguousNodesPtr; + int m_traversalMode; + int m_numSubtreeHeaders; + btBvhSubtreeInfoData *m_subTreeInfoPtr; + }; + + +// -------------------------------------------------- // + class btCollisionShapeData + { + public: + char *m_name; + int m_shapeType; + char m_padding[4]; + }; + + +// -------------------------------------------------- // + class btStaticPlaneShapeData + { + public: + btCollisionShapeData m_collisionShapeData; + btVector3FloatData m_localScaling; + btVector3FloatData m_planeNormal; + float m_planeConstant; + char m_pad[4]; + }; + + +// -------------------------------------------------- // + class btConvexInternalShapeData + { + public: + btCollisionShapeData m_collisionShapeData; + btVector3FloatData m_localScaling; + btVector3FloatData m_implicitShapeDimensions; + float m_collisionMargin; + int m_padding; + }; + + +// -------------------------------------------------- // + class btPositionAndRadius + { + public: + btVector3FloatData m_pos; + float m_radius; + }; + + +// -------------------------------------------------- // + class btMultiSphereShapeData + { + public: + btConvexInternalShapeData m_convexInternalShapeData; + btPositionAndRadius *m_localPositionArrayPtr; + int m_localPositionArraySize; + char m_padding[4]; + }; + + +// -------------------------------------------------- // + class btIntIndexData + { + public: + int m_value; + }; + + +// -------------------------------------------------- // + class btShortIntIndexData + { + public: + short m_value; + char m_pad[2]; + }; + + +// -------------------------------------------------- // + class btShortIntIndexTripletData + { + public: + short m_values[3]; + char m_pad[2]; + }; + + +// -------------------------------------------------- // + class btCharIndexTripletData + { + public: + char m_values[3]; + char m_pad; + }; + + +// -------------------------------------------------- // + class btMeshPartData + { + public: + btVector3FloatData *m_vertices3f; + btVector3DoubleData *m_vertices3d; + btIntIndexData *m_indices32; + btShortIntIndexTripletData *m_3indices16; + btCharIndexTripletData *m_3indices8; + btShortIntIndexData *m_indices16; + int m_numTriangles; + int m_numVertices; + }; + + +// -------------------------------------------------- // + class btStridingMeshInterfaceData + { + public: + btMeshPartData *m_meshPartsPtr; + btVector3FloatData m_scaling; + int m_numMeshParts; + char m_padding[4]; + }; + + +// -------------------------------------------------- // + class btTriangleMeshShapeData + { + public: + btCollisionShapeData m_collisionShapeData; + btStridingMeshInterfaceData m_meshInterface; + btQuantizedBvhFloatData *m_quantizedFloatBvh; + btQuantizedBvhDoubleData *m_quantizedDoubleBvh; + btTriangleInfoMapData *m_triangleInfoMap; + float m_collisionMargin; + char m_pad3[4]; + }; + + +// -------------------------------------------------- // + class btScaledTriangleMeshShapeData + { + public: + btTriangleMeshShapeData m_trimeshShapeData; + btVector3FloatData m_localScaling; + }; + + +// -------------------------------------------------- // + class btCompoundShapeChildData + { + public: + btTransformFloatData m_transform; + btCollisionShapeData *m_childShape; + int m_childShapeType; + float m_childMargin; + }; + + +// -------------------------------------------------- // + class btCompoundShapeData + { + public: + btCollisionShapeData m_collisionShapeData; + btCompoundShapeChildData *m_childShapePtr; + int m_numChildShapes; + float m_collisionMargin; + }; + + +// -------------------------------------------------- // + class btCylinderShapeData + { + public: + btConvexInternalShapeData m_convexInternalShapeData; + int m_upAxis; + char m_padding[4]; + }; + + +// -------------------------------------------------- // + class btCapsuleShapeData + { + public: + btConvexInternalShapeData m_convexInternalShapeData; + int m_upAxis; + char m_padding[4]; + }; + + +// -------------------------------------------------- // + class btTriangleInfoData + { + public: + int m_flags; + float m_edgeV0V1Angle; + float m_edgeV1V2Angle; + float m_edgeV2V0Angle; + }; + + +// -------------------------------------------------- // + class btTriangleInfoMapData + { + public: + int *m_hashTablePtr; + int *m_nextPtr; + btTriangleInfoData *m_valueArrayPtr; + int *m_keyArrayPtr; + float m_convexEpsilon; + float m_planarEpsilon; + float m_equalVertexThreshold; + float m_edgeDistanceThreshold; + float m_zeroAreaThreshold; + int m_nextSize; + int m_hashTableSize; + int m_numValues; + int m_numKeys; + char m_padding[4]; + }; + + +// -------------------------------------------------- // + class btGImpactMeshShapeData + { + public: + btCollisionShapeData m_collisionShapeData; + btStridingMeshInterfaceData m_meshInterface; + btVector3FloatData m_localScaling; + float m_collisionMargin; + int m_gimpactSubType; + }; + + +// -------------------------------------------------- // + class btConvexHullShapeData + { + public: + btConvexInternalShapeData m_convexInternalShapeData; + btVector3FloatData *m_unscaledPointsFloatPtr; + btVector3DoubleData *m_unscaledPointsDoublePtr; + int m_numUnscaledPoints; + char m_padding3[4]; + }; + + +// -------------------------------------------------- // + class btCollisionObjectDoubleData + { + public: + void *m_broadphaseHandle; + void *m_collisionShape; + btCollisionShapeData *m_rootCollisionShape; + char *m_name; + btTransformDoubleData m_worldTransform; + btTransformDoubleData m_interpolationWorldTransform; + btVector3DoubleData m_interpolationLinearVelocity; + btVector3DoubleData m_interpolationAngularVelocity; + btVector3DoubleData m_anisotropicFriction; + double m_contactProcessingThreshold; + double m_deactivationTime; + double m_friction; + double m_restitution; + double m_hitFraction; + double m_ccdSweptSphereRadius; + double m_ccdMotionThreshold; + int m_hasAnisotropicFriction; + int m_collisionFlags; + int m_islandTag1; + int m_companionId; + int m_activationState1; + int m_internalType; + int m_checkCollideWith; + char m_padding[4]; + }; + + +// -------------------------------------------------- // + class btCollisionObjectFloatData + { + public: + void *m_broadphaseHandle; + void *m_collisionShape; + btCollisionShapeData *m_rootCollisionShape; + char *m_name; + btTransformFloatData m_worldTransform; + btTransformFloatData m_interpolationWorldTransform; + btVector3FloatData m_interpolationLinearVelocity; + btVector3FloatData m_interpolationAngularVelocity; + btVector3FloatData m_anisotropicFriction; + float m_contactProcessingThreshold; + float m_deactivationTime; + float m_friction; + float m_restitution; + float m_hitFraction; + float m_ccdSweptSphereRadius; + float m_ccdMotionThreshold; + int m_hasAnisotropicFriction; + int m_collisionFlags; + int m_islandTag1; + int m_companionId; + int m_activationState1; + int m_internalType; + int m_checkCollideWith; + }; + + +// -------------------------------------------------- // + class btRigidBodyFloatData + { + public: + btCollisionObjectFloatData m_collisionObjectData; + btMatrix3x3FloatData m_invInertiaTensorWorld; + btVector3FloatData m_linearVelocity; + btVector3FloatData m_angularVelocity; + btVector3FloatData m_angularFactor; + btVector3FloatData m_linearFactor; + btVector3FloatData m_gravity; + btVector3FloatData m_gravity_acceleration; + btVector3FloatData m_invInertiaLocal; + btVector3FloatData m_totalForce; + btVector3FloatData m_totalTorque; + float m_inverseMass; + float m_linearDamping; + float m_angularDamping; + float m_additionalDampingFactor; + float m_additionalLinearDampingThresholdSqr; + float m_additionalAngularDampingThresholdSqr; + float m_additionalAngularDampingFactor; + float m_linearSleepingThreshold; + float m_angularSleepingThreshold; + int m_additionalDamping; + }; + + +// -------------------------------------------------- // + class btRigidBodyDoubleData + { + public: + btCollisionObjectDoubleData m_collisionObjectData; + btMatrix3x3DoubleData m_invInertiaTensorWorld; + btVector3DoubleData m_linearVelocity; + btVector3DoubleData m_angularVelocity; + btVector3DoubleData m_angularFactor; + btVector3DoubleData m_linearFactor; + btVector3DoubleData m_gravity; + btVector3DoubleData m_gravity_acceleration; + btVector3DoubleData m_invInertiaLocal; + btVector3DoubleData m_totalForce; + btVector3DoubleData m_totalTorque; + double m_inverseMass; + double m_linearDamping; + double m_angularDamping; + double m_additionalDampingFactor; + double m_additionalLinearDampingThresholdSqr; + double m_additionalAngularDampingThresholdSqr; + double m_additionalAngularDampingFactor; + double m_linearSleepingThreshold; + double m_angularSleepingThreshold; + int m_additionalDamping; + char m_padding[4]; + }; + + +// -------------------------------------------------- // + class btConstraintInfo1 + { + public: + int m_numConstraintRows; + int nub; + }; + + +// -------------------------------------------------- // + class btTypedConstraintData + { + public: + bInvalidHandle *m_rbA; + bInvalidHandle *m_rbB; + char *m_name; + int m_objectType; + int m_userConstraintType; + int m_userConstraintId; + int m_needsFeedback; + float m_appliedImpulse; + float m_dbgDrawSize; + int m_disableCollisionsBetweenLinkedBodies; + char m_pad4[4]; + }; + + +// -------------------------------------------------- // + class btPoint2PointConstraintFloatData + { + public: + btTypedConstraintData m_typeConstraintData; + btVector3FloatData m_pivotInA; + btVector3FloatData m_pivotInB; + }; + + +// -------------------------------------------------- // + class btPoint2PointConstraintDoubleData + { + public: + btTypedConstraintData m_typeConstraintData; + btVector3DoubleData m_pivotInA; + btVector3DoubleData m_pivotInB; + }; + + +// -------------------------------------------------- // + class btHingeConstraintDoubleData + { + public: + btTypedConstraintData m_typeConstraintData; + btTransformDoubleData m_rbAFrame; + btTransformDoubleData m_rbBFrame; + int m_useReferenceFrameA; + int m_angularOnly; + int m_enableAngularMotor; + float m_motorTargetVelocity; + float m_maxMotorImpulse; + float m_lowerLimit; + float m_upperLimit; + float m_limitSoftness; + float m_biasFactor; + float m_relaxationFactor; + }; + + +// -------------------------------------------------- // + class btHingeConstraintFloatData + { + public: + btTypedConstraintData m_typeConstraintData; + btTransformFloatData m_rbAFrame; + btTransformFloatData m_rbBFrame; + int m_useReferenceFrameA; + int m_angularOnly; + int m_enableAngularMotor; + float m_motorTargetVelocity; + float m_maxMotorImpulse; + float m_lowerLimit; + float m_upperLimit; + float m_limitSoftness; + float m_biasFactor; + float m_relaxationFactor; + }; + + +// -------------------------------------------------- // + class btConeTwistConstraintData + { + public: + btTypedConstraintData m_typeConstraintData; + btTransformFloatData m_rbAFrame; + btTransformFloatData m_rbBFrame; + float m_swingSpan1; + float m_swingSpan2; + float m_twistSpan; + float m_limitSoftness; + float m_biasFactor; + float m_relaxationFactor; + float m_damping; + char m_pad[4]; + }; + + +// -------------------------------------------------- // + class btGeneric6DofConstraintData + { + public: + btTypedConstraintData m_typeConstraintData; + btTransformFloatData m_rbAFrame; + btTransformFloatData m_rbBFrame; + btVector3FloatData m_linearUpperLimit; + btVector3FloatData m_linearLowerLimit; + btVector3FloatData m_angularUpperLimit; + btVector3FloatData m_angularLowerLimit; + int m_useLinearReferenceFrameA; + int m_useOffsetForConstraintFrame; + }; + + +// -------------------------------------------------- // + class btGeneric6DofSpringConstraintData + { + public: + btGeneric6DofConstraintData m_6dofData; + int m_springEnabled[6]; + float m_equilibriumPoint[6]; + float m_springStiffness[6]; + float m_springDamping[6]; + }; + + +// -------------------------------------------------- // + class btSliderConstraintData + { + public: + btTypedConstraintData m_typeConstraintData; + btTransformFloatData m_rbAFrame; + btTransformFloatData m_rbBFrame; + float m_linearUpperLimit; + float m_linearLowerLimit; + float m_angularUpperLimit; + float m_angularLowerLimit; + int m_useLinearReferenceFrameA; + int m_useOffsetForConstraintFrame; + }; + + +// -------------------------------------------------- // + class SoftBodyMaterialData + { + public: + float m_linearStiffness; + float m_angularStiffness; + float m_volumeStiffness; + int m_flags; + }; + + +// -------------------------------------------------- // + class SoftBodyNodeData + { + public: + SoftBodyMaterialData *m_material; + btVector3FloatData m_position; + btVector3FloatData m_previousPosition; + btVector3FloatData m_velocity; + btVector3FloatData m_accumulatedForce; + btVector3FloatData m_normal; + float m_inverseMass; + float m_area; + int m_attach; + int m_pad; + }; + + +// -------------------------------------------------- // + class SoftBodyLinkData + { + public: + SoftBodyMaterialData *m_material; + int m_nodeIndices[2]; + float m_restLength; + int m_bbending; + }; + + +// -------------------------------------------------- // + class SoftBodyFaceData + { + public: + btVector3FloatData m_normal; + SoftBodyMaterialData *m_material; + int m_nodeIndices[3]; + float m_restArea; + }; + + +// -------------------------------------------------- // + class SoftBodyTetraData + { + public: + btVector3FloatData m_c0[4]; + SoftBodyMaterialData *m_material; + int m_nodeIndices[4]; + float m_restVolume; + float m_c1; + float m_c2; + int m_pad; + }; + + +// -------------------------------------------------- // + class SoftRigidAnchorData + { + public: + btMatrix3x3FloatData m_c0; + btVector3FloatData m_c1; + btVector3FloatData m_localFrame; + bInvalidHandle *m_rigidBody; + int m_nodeIndex; + float m_c2; + }; + + +// -------------------------------------------------- // + class SoftBodyConfigData + { + public: + int m_aeroModel; + float m_baumgarte; + float m_damping; + float m_drag; + float m_lift; + float m_pressure; + float m_volume; + float m_dynamicFriction; + float m_poseMatch; + float m_rigidContactHardness; + float m_kineticContactHardness; + float m_softContactHardness; + float m_anchorHardness; + float m_softRigidClusterHardness; + float m_softKineticClusterHardness; + float m_softSoftClusterHardness; + float m_softRigidClusterImpulseSplit; + float m_softKineticClusterImpulseSplit; + float m_softSoftClusterImpulseSplit; + float m_maxVolume; + float m_timeScale; + int m_velocityIterations; + int m_positionIterations; + int m_driftIterations; + int m_clusterIterations; + int m_collisionFlags; + }; + + +// -------------------------------------------------- // + class SoftBodyPoseData + { + public: + btMatrix3x3FloatData m_rot; + btMatrix3x3FloatData m_scale; + btMatrix3x3FloatData m_aqq; + btVector3FloatData m_com; + btVector3FloatData *m_positions; + float *m_weights; + int m_numPositions; + int m_numWeigts; + int m_bvolume; + int m_bframe; + float m_restVolume; + int m_pad; + }; + + +// -------------------------------------------------- // + class SoftBodyClusterData + { + public: + btTransformFloatData m_framexform; + btMatrix3x3FloatData m_locii; + btMatrix3x3FloatData m_invwi; + btVector3FloatData m_com; + btVector3FloatData m_vimpulses[2]; + btVector3FloatData m_dimpulses[2]; + btVector3FloatData m_lv; + btVector3FloatData m_av; + btVector3FloatData *m_framerefs; + int *m_nodeIndices; + float *m_masses; + int m_numFrameRefs; + int m_numNodes; + int m_numMasses; + float m_idmass; + float m_imass; + int m_nvimpulses; + int m_ndimpulses; + float m_ndamping; + float m_ldamping; + float m_adamping; + float m_matching; + float m_maxSelfCollisionImpulse; + float m_selfCollisionImpulseFactor; + int m_containsAnchor; + int m_collide; + int m_clusterIndex; + }; + + +// -------------------------------------------------- // + class btSoftBodyJointData + { + public: + void *m_bodyA; + void *m_bodyB; + btVector3FloatData m_refs[2]; + float m_cfm; + float m_erp; + float m_split; + int m_delete; + btVector3FloatData m_relPosition[2]; + int m_bodyAtype; + int m_bodyBtype; + int m_jointType; + int m_pad; + }; + + +// -------------------------------------------------- // + class btSoftBodyFloatData + { + public: + btCollisionObjectFloatData m_collisionObjectData; + SoftBodyPoseData *m_pose; + SoftBodyMaterialData **m_materials; + SoftBodyNodeData *m_nodes; + SoftBodyLinkData *m_links; + SoftBodyFaceData *m_faces; + SoftBodyTetraData *m_tetrahedra; + SoftRigidAnchorData *m_anchors; + SoftBodyClusterData *m_clusters; + btSoftBodyJointData *m_joints; + int m_numMaterials; + int m_numNodes; + int m_numLinks; + int m_numFaces; + int m_numTetrahedra; + int m_numAnchors; + int m_numClusters; + int m_numJoints; + SoftBodyConfigData m_config; + }; + + +} +#endif//__BULLET_H__ \ No newline at end of file diff --git a/Extras/Serialize/BulletFileLoader/bChunk.cpp b/Extras/Serialize/BulletFileLoader/bChunk.cpp new file mode 100644 index 0000000..564e550 --- /dev/null +++ b/Extras/Serialize/BulletFileLoader/bChunk.cpp @@ -0,0 +1,75 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +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 "bChunk.h" +#include "bDefines.h" +#include "bFile.h" + +#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__) +#include +#endif +#include + + +using namespace bParse; + + +// ----------------------------------------------------- // +short ChunkUtils::swapShort(short sht) +{ + SWITCH_SHORT(sht); + return sht; +} + +// ----------------------------------------------------- // +int ChunkUtils::swapInt(int inte) +{ + SWITCH_INT(inte); + return inte; +} + +// ----------------------------------------------------- // +long64 ChunkUtils::swapLong64(long64 lng) +{ + SWITCH_LONGINT(lng); + return lng; +} + +// ----------------------------------------------------- // +int ChunkUtils::getOffset(int flags) +{ + // if the file is saved in a + // different format, get the + // file's chunk size + int res = CHUNK_HEADER_LEN; + + if (VOID_IS_8) + { + if (flags &FD_BITS_VARIES) + res = sizeof(bChunkPtr4); + } + else + { + if (flags &FD_BITS_VARIES) + res = sizeof(bChunkPtr8); + } + return res; +} + + + + + +//eof diff --git a/Extras/Serialize/BulletFileLoader/bChunk.h b/Extras/Serialize/BulletFileLoader/bChunk.h new file mode 100644 index 0000000..77039bc --- /dev/null +++ b/Extras/Serialize/BulletFileLoader/bChunk.h @@ -0,0 +1,92 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +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 __BCHUNK_H__ +#define __BCHUNK_H__ + +#if defined (_WIN32) && ! defined (__MINGW32__) + #define long64 __int64 +#elif defined (__MINGW32__) + #include + #define long64 int64_t +#else + #define long64 long long +#endif + + +namespace bParse { + + + // ----------------------------------------------------- // + class bChunkPtr4 + { + public: + bChunkPtr4(){} + int code; + int len; + union + { + int m_uniqueInt; + }; + int dna_nr; + int nr; + }; + + // ----------------------------------------------------- // + class bChunkPtr8 + { + public: + bChunkPtr8(){} + int code, len; + union + { + long64 oldPrev; + int m_uniqueInts[2]; + }; + int dna_nr, nr; + }; + + // ----------------------------------------------------- // + class bChunkInd + { + public: + bChunkInd(){} + int code, len; + void *oldPtr; + int dna_nr, nr; + }; + + + // ----------------------------------------------------- // + class ChunkUtils + { + public: + + // file chunk offset + static int getOffset(int flags); + + // endian utils + static short swapShort(short sht); + static int swapInt(int inte); + static long64 swapLong64(long64 lng); + + }; + + + const int CHUNK_HEADER_LEN = ((sizeof(bChunkInd))); + const bool VOID_IS_8 = ((sizeof(void*)==8)); +} + +#endif//__BCHUNK_H__ diff --git a/Extras/Serialize/BulletFileLoader/bCommon.h b/Extras/Serialize/BulletFileLoader/bCommon.h new file mode 100644 index 0000000..b01d2b8 --- /dev/null +++ b/Extras/Serialize/BulletFileLoader/bCommon.h @@ -0,0 +1,39 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +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 __BCOMMON_H__ +#define __BCOMMON_H__ + + +#include +//#include "bLog.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btHashMap.h" + +namespace bParse { + + class bMain; + class bFileData; + class bFile; + class bDNA; + + // delete void* undefined + typedef struct bStructHandle {int unused;}bStructHandle; + typedef btAlignedObjectArray bListBasePtr; + typedef btHashMap bPtrMap; +} + + +#endif//__BCOMMON_H__ diff --git a/Extras/Serialize/BulletFileLoader/bDNA.cpp b/Extras/Serialize/BulletFileLoader/bDNA.cpp new file mode 100644 index 0000000..c72db23 --- /dev/null +++ b/Extras/Serialize/BulletFileLoader/bDNA.cpp @@ -0,0 +1,636 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +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 + +#include "bDNA.h" +#include "bChunk.h" +#include +#include +#include + +//this define will force traversal of structures, to check backward (and forward) compatibility +//#define TEST_BACKWARD_FORWARD_COMPATIBILITY + + +using namespace bParse; + + +// ----------------------------------------------------- // +bDNA::bDNA() + : mPtrLen(0) +{ + // -- +} + +// ----------------------------------------------------- // +bDNA::~bDNA() +{ + // -- +} + +// ----------------------------------------------------- // +bool bDNA::lessThan(bDNA *file) +{ + return ( m_Names.size() < file->m_Names.size()); +} + +// ----------------------------------------------------- // +char *bDNA::getName(int ind) +{ + assert(ind <= (int)m_Names.size()); + return m_Names[ind].m_name; +} + + +// ----------------------------------------------------- // +char *bDNA::getType(int ind) +{ + assert(ind<= (int)mTypes.size()); + return mTypes[ind]; +} + + +// ----------------------------------------------------- // +short *bDNA::getStruct(int ind) +{ + assert(ind <= (int)mStructs.size()); + return mStructs[ind]; +} + + +// ----------------------------------------------------- // +short bDNA::getLength(int ind) +{ + assert(ind <= (int)mTlens.size()); + return mTlens[ind]; +} + + +// ----------------------------------------------------- // +int bDNA::getReverseType(short type) +{ + + int* intPtr = mStructReverse.find(type); + if (intPtr) + return *intPtr; + + return -1; +} + +// ----------------------------------------------------- // +int bDNA::getReverseType(const char *type) +{ + + btHashString key(type); + int* valuePtr = mTypeLookup.find(key); + if (valuePtr) + return *valuePtr; + + return -1; +} + +// ----------------------------------------------------- // +int bDNA::getNumStructs() +{ + return (int)mStructs.size(); +} + +// ----------------------------------------------------- // +bool bDNA::flagNotEqual(int dna_nr) +{ + assert(dna_nr <= (int)mCMPFlags.size()); + return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU; +} + +// ----------------------------------------------------- // +bool bDNA::flagEqual(int dna_nr) +{ + assert(dna_nr <= (int)mCMPFlags.size()); + int flag = mCMPFlags[dna_nr]; + return flag == FDF_STRUCT_EQU; +} + +// ----------------------------------------------------- // +bool bDNA::flagNone(int dna_nr) +{ + assert(dna_nr <= (int)mCMPFlags.size()); + return mCMPFlags[dna_nr] == FDF_NONE; +} + +// ----------------------------------------------------- // +int bDNA::getPointerSize() +{ + return mPtrLen; +} + +// ----------------------------------------------------- // +void bDNA::initRecurseCmpFlags(int iter) +{ + // iter is FDF_STRUCT_NEQU + + short *oldStrc = mStructs[iter]; + short type = oldStrc[0]; + + for (int i=0; i<(int)mStructs.size(); i++) + { + if (i != iter && mCMPFlags[i] == FDF_STRUCT_EQU ) + { + short *curStruct = mStructs[i]; + int eleLen = curStruct[1]; + curStruct+=2; + + for (int j=0; jgetReverseType(typeName); + if (newLookup == -1) + { + mCMPFlags[i] = FDF_NONE; + continue; + } + short *curStruct = memDNA->mStructs[newLookup]; +#else + // memory for file + + if (oldLookup < memDNA->mStructs.size()) + { + short *curStruct = memDNA->mStructs[oldLookup]; +#endif + + + + // rebuild... + mCMPFlags[i] = FDF_STRUCT_NEQU; + +#ifndef TEST_BACKWARD_FORWARD_COMPATIBILITY + + if (curStruct[1] == oldStruct[1]) + { + // type len same ... + if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]]) + { + bool isSame = true; + int elementLength = oldStruct[1]; + + + curStruct+=2; + oldStruct+=2; + + + for (int j=0; jmTypes[curStruct[0]])!=0) + { + isSame=false; + break; + } + + // name the same + if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name)!=0) + { + isSame=false; + break; + } + } + // flag valid == + if (isSame) + mCMPFlags[i] = FDF_STRUCT_EQU; + } + } +#endif + } + } + + + + + + // recurse in + for ( i=0; i<(int)mStructs.size(); i++) + { + if (mCMPFlags[i] == FDF_STRUCT_NEQU) + initRecurseCmpFlags(i); + } +} + + + + +static int name_is_array(char* name, int* dim1, int* dim2) { + int len = strlen(name); + /*fprintf(stderr,"[%s]",name);*/ + /*if (len >= 1) { + if (name[len-1] != ']') + return 1; + } + return 0;*/ + char *bp; + int num; + if (dim1) { + *dim1 = 1; + } + if (dim2) { + *dim2 = 1; + } + bp = strchr(name, '['); + if (!bp) { + return 0; + } + num = 0; + while (++bp < name+len-1) { + const char c = *bp; + if (c == ']') { + break; + } + if (c <= '9' && c >= '0') { + num *= 10; + num += (c - '0'); + } else { + printf("array parse error.\n"); + return 0; + } + } + if (dim2) { + *dim2 = num; + } + + /* find second dim, if any. */ + bp = strchr(bp, '['); + if (!bp) { + return 1; /* at least we got the first dim. */ + } + num = 0; + while (++bp < name+len-1) { + const char c = *bp; + if (c == ']') { + break; + } + if (c <= '9' && c >= '0') { + num *= 10; + num += (c - '0'); + } else { + printf("array2 parse error.\n"); + return 1; + } + } + if (dim1) { + if (dim2) { + *dim1 = *dim2; + *dim2 = num; + } else { + *dim1 = num; + } + } + + return 1; +} + + +// ----------------------------------------------------- // +void bDNA::init(char *data, int len, bool swap) +{ + printf("swap = %d\n",swap); + int *intPtr=0;short *shtPtr=0; + char *cp = 0;int dataLen =0;long nr=0; + intPtr = (int*)data; + + /* + SDNA (4 bytes) (magic number) + NAME (4 bytes) + (4 bytes) amount of names (int) + + + */ + + if (strncmp(data, "SDNA", 4)==0) + { + // skip ++ NAME + intPtr++; intPtr++; + } + + + + // Parse names + if (swap) dataLen = ChunkUtils::swapInt(*intPtr); + else dataLen = *intPtr; + intPtr++; + + cp = (char*)intPtr; + int i; + for ( i=0; i amount of types (int) + + + */ + + intPtr = (int*)cp; + assert(strncmp(cp, "TYPE", 4)==0); intPtr++; + + if (swap) dataLen = ChunkUtils::swapInt(*intPtr); + else dataLen = *intPtr; + intPtr++; + + cp = (char*)intPtr; + for ( i=0; i (short) the lengths of types + + */ + + // Parse type lens + intPtr = (int*)cp; + assert(strncmp(cp, "TLEN", 4)==0); intPtr++; + + dataLen = (int)mTypes.size(); + + shtPtr = (short*)intPtr; + for ( i=0; i amount of structs (int) + + + + + + + */ + + intPtr = (int*)shtPtr; + cp = (char*)intPtr; + assert(strncmp(cp, "STRC", 4)==0); intPtr++; + + if (swap) dataLen = ChunkUtils::swapInt(*intPtr); + else dataLen = *intPtr; + intPtr++; + + + shtPtr = (short*)intPtr; + for ( i=0; itypes_count; ++i) { + /* if (!bf->types[i].is_struct)*/ + { + printf("%3d: sizeof(%s%s)=%d", + i, + bf->types[i].is_struct ? "struct " : "atomic ", + bf->types[i].name, bf->types[i].size); + if (bf->types[i].is_struct) { + int j; + printf(", %d fields: { ", bf->types[i].fieldtypes_count); + for (j=0; jtypes[i].fieldtypes_count; ++j) { + printf("%s %s", + bf->types[bf->types[i].fieldtypes[j]].name, + bf->names[bf->types[i].fieldnames[j]]); + if (j == bf->types[i].fieldtypes_count-1) { + printf(";}"); + } else { + printf("; "); + } + } + } + printf("\n\n"); + + } + } +#endif + +} + + + + +//eof + + diff --git a/Extras/Serialize/BulletFileLoader/bDNA.h b/Extras/Serialize/BulletFileLoader/bDNA.h new file mode 100644 index 0000000..691080b --- /dev/null +++ b/Extras/Serialize/BulletFileLoader/bDNA.h @@ -0,0 +1,110 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +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 __BDNA_H__ +#define __BDNA_H__ + + +#include "bCommon.h" + +namespace bParse { + + struct bNameInfo + { + char* m_name; + bool m_isPointer; + int m_dim0; + int m_dim1; + }; + + class bDNA + { + public: + bDNA(); + ~bDNA(); + + void init(char *data, int len, bool swap=false); + + int getArraySize(char* str); + int getArraySizeNew(short name) + { + const bNameInfo& nameInfo = m_Names[name]; + return nameInfo.m_dim0*nameInfo.m_dim1; + } + int getElementSize(short type, short name) + { + const bNameInfo& nameInfo = m_Names[name]; + int size = nameInfo.m_isPointer ? mPtrLen*nameInfo.m_dim0*nameInfo.m_dim1 : mTlens[type]*nameInfo.m_dim0*nameInfo.m_dim1; + return size; + } + + int getNumNames() const + { + return m_Names.size(); + } + + char *getName(int ind); + char *getType(int ind); + short *getStruct(int ind); + short getLength(int ind); + int getReverseType(short type); + int getReverseType(const char *type); + + + int getNumStructs(); + + // + bool lessThan(bDNA* other); + + void initCmpFlags(bDNA *memDNA); + bool flagNotEqual(int dna_nr); + bool flagEqual(int dna_nr); + bool flagNone(int dna_nr); + + + int getPointerSize(); + + void dumpTypeDefinitions(); + + + private: + enum FileDNAFlags + { + FDF_NONE=0, + FDF_STRUCT_NEQU, + FDF_STRUCT_EQU + }; + + void initRecurseCmpFlags(int i); + + btAlignedObjectArray mCMPFlags; + + btAlignedObjectArray m_Names; + btAlignedObjectArray mTypes; + btAlignedObjectArray mStructs; + btAlignedObjectArray mTlens; + btHashMap mStructReverse; + btHashMap mTypeLookup; + + int mPtrLen; + + + + + }; +} + + +#endif//__BDNA_H__ diff --git a/Extras/Serialize/BulletFileLoader/bDefines.h b/Extras/Serialize/BulletFileLoader/bDefines.h new file mode 100644 index 0000000..238df7d --- /dev/null +++ b/Extras/Serialize/BulletFileLoader/bDefines.h @@ -0,0 +1,140 @@ +/* Copyright (C) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com +* +* 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 __B_DEFINES_H__ +#define __B_DEFINES_H__ + + +// MISC defines, see BKE_global.h, BKE_utildefines.h +#define SIZEOFBLENDERHEADER 12 + + +// ------------------------------------------------------------ +#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) +# define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) ) +#else +# define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) ) +#endif + + +// ------------------------------------------------------------ +#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) +# define MAKE_ID2(c, d) ( (c)<<8 | (d) ) +# define MOST_SIG_BYTE 0 +# define BBIG_ENDIAN +#else +# define MAKE_ID2(c, d) ( (d)<<8 | (c) ) +# define MOST_SIG_BYTE 1 +# define BLITTLE_ENDIAN +#endif + +// ------------------------------------------------------------ +#define ID_SCE MAKE_ID2('S', 'C') +#define ID_LI MAKE_ID2('L', 'I') +#define ID_OB MAKE_ID2('O', 'B') +#define ID_ME MAKE_ID2('M', 'E') +#define ID_CU MAKE_ID2('C', 'U') +#define ID_MB MAKE_ID2('M', 'B') +#define ID_MA MAKE_ID2('M', 'A') +#define ID_TE MAKE_ID2('T', 'E') +#define ID_IM MAKE_ID2('I', 'M') +#define ID_IK MAKE_ID2('I', 'K') +#define ID_WV MAKE_ID2('W', 'V') +#define ID_LT MAKE_ID2('L', 'T') +#define ID_SE MAKE_ID2('S', 'E') +#define ID_LF MAKE_ID2('L', 'F') +#define ID_LA MAKE_ID2('L', 'A') +#define ID_CA MAKE_ID2('C', 'A') +#define ID_IP MAKE_ID2('I', 'P') +#define ID_KE MAKE_ID2('K', 'E') +#define ID_WO MAKE_ID2('W', 'O') +#define ID_SCR MAKE_ID2('S', 'R') +#define ID_VF MAKE_ID2('V', 'F') +#define ID_TXT MAKE_ID2('T', 'X') +#define ID_SO MAKE_ID2('S', 'O') +#define ID_SAMPLE MAKE_ID2('S', 'A') +#define ID_GR MAKE_ID2('G', 'R') +#define ID_ID MAKE_ID2('I', 'D') +#define ID_AR MAKE_ID2('A', 'R') +#define ID_AC MAKE_ID2('A', 'C') +#define ID_SCRIPT MAKE_ID2('P', 'Y') +#define ID_FLUIDSIM MAKE_ID2('F', 'S') +#define ID_NT MAKE_ID2('N', 'T') +#define ID_BR MAKE_ID2('B', 'R') + + +#define ID_SEQ MAKE_ID2('S', 'Q') +#define ID_CO MAKE_ID2('C', 'O') +#define ID_PO MAKE_ID2('A', 'C') +#define ID_NLA MAKE_ID2('N', 'L') + +#define ID_VS MAKE_ID2('V', 'S') +#define ID_VN MAKE_ID2('V', 'N') + + +// ------------------------------------------------------------ +#define FORM MAKE_ID('F','O','R','M') +#define DDG1 MAKE_ID('3','D','G','1') +#define DDG2 MAKE_ID('3','D','G','2') +#define DDG3 MAKE_ID('3','D','G','3') +#define DDG4 MAKE_ID('3','D','G','4') +#define GOUR MAKE_ID('G','O','U','R') +#define BLEN MAKE_ID('B','L','E','N') +#define DER_ MAKE_ID('D','E','R','_') +#define V100 MAKE_ID('V','1','0','0') +#define DATA MAKE_ID('D','A','T','A') +#define GLOB MAKE_ID('G','L','O','B') +#define IMAG MAKE_ID('I','M','A','G') +#define TEST MAKE_ID('T','E','S','T') +#define USER MAKE_ID('U','S','E','R') + + +// ------------------------------------------------------------ +#define DNA1 MAKE_ID('D','N','A','1') +#define REND MAKE_ID('R','E','N','D') +#define ENDB MAKE_ID('E','N','D','B') +#define NAME MAKE_ID('N','A','M','E') +#define SDNA MAKE_ID('S','D','N','A') +#define TYPE MAKE_ID('T','Y','P','E') +#define TLEN MAKE_ID('T','L','E','N') +#define STRC MAKE_ID('S','T','R','C') + + +// ------------------------------------------------------------ +#define SWITCH_INT(a) { \ + char s_i, *p_i; \ + p_i= (char *)&(a); \ + s_i=p_i[0]; p_i[0]=p_i[3]; p_i[3]=s_i; \ + s_i=p_i[1]; p_i[1]=p_i[2]; p_i[2]=s_i; } + +// ------------------------------------------------------------ +#define SWITCH_SHORT(a) { \ + char s_i, *p_i; \ + p_i= (char *)&(a); \ + s_i=p_i[0]; p_i[0]=p_i[1]; p_i[1]=s_i; } + +// ------------------------------------------------------------ +#define SWITCH_LONGINT(a) { \ + char s_i, *p_i; \ + p_i= (char *)&(a); \ + s_i=p_i[0]; p_i[0]=p_i[7]; p_i[7]=s_i; \ + s_i=p_i[1]; p_i[1]=p_i[6]; p_i[6]=s_i; \ + s_i=p_i[2]; p_i[2]=p_i[5]; p_i[5]=s_i; \ + s_i=p_i[3]; p_i[3]=p_i[4]; p_i[4]=s_i; } + +#endif//__B_DEFINES_H__ diff --git a/Extras/Serialize/BulletFileLoader/bFile.cpp b/Extras/Serialize/BulletFileLoader/bFile.cpp new file mode 100644 index 0000000..e3fe4dc --- /dev/null +++ b/Extras/Serialize/BulletFileLoader/bFile.cpp @@ -0,0 +1,1354 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +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 "bFile.h" +#include "bCommon.h" +#include "bChunk.h" +#include "bDNA.h" +#include +#include +#include +#include "bDefines.h" +#include "LinearMath/btSerializer.h" + +#define SIZEOFBLENDERHEADER 12 +#define MAX_ARRAY_LENGTH 512 +using namespace bParse; + + + +int numallocs = 0; + +// ----------------------------------------------------- // +bFile::bFile(const char *filename, const char headerString[7]) + : mOwnsBuffer(true), + mFileBuffer(0), + mFileLen(0), + mVersion(0), + mDataStart(0), + mFileDNA(0), + mMemoryDNA(0), + mFlags(FD_INVALID) +{ + for (int i=0;i<7;i++) + { + m_headerString[i] = headerString[i]; + } + + FILE *fp = fopen(filename, "rb"); + if (fp) + { + fseek(fp, 0L, SEEK_END); + mFileLen = ftell(fp); + fseek(fp, 0L, SEEK_SET); + + mFileBuffer = (char*)malloc(mFileLen+1); + fread(mFileBuffer, mFileLen, 1, fp); + + fclose(fp); + + // + parseHeader(); + + } +} + +// ----------------------------------------------------- // +bFile::bFile( char *memoryBuffer, int len, const char headerString[7]) +: mOwnsBuffer(false), + mFileBuffer(0), + mFileLen(0), + mVersion(0), + mDataStart(0), + mFileDNA(0), + mMemoryDNA(0), + mFlags(FD_INVALID) +{ + for (int i=0;i<7;i++) + { + m_headerString[i] = headerString[i]; + } + mFileBuffer = memoryBuffer; + mFileLen = len; + + parseHeader(); + +} + + +// ----------------------------------------------------- // +bFile::~bFile() +{ + if (mOwnsBuffer && mFileBuffer) + { + free(mFileBuffer); + mFileBuffer = 0; + } + + + delete mMemoryDNA; + delete mFileDNA; +} + + + + + +// ----------------------------------------------------- // +void bFile::parseHeader() +{ + if (!mFileLen || !mFileBuffer) + return; + + char *blenderBuf = mFileBuffer; + char header[SIZEOFBLENDERHEADER+1] ; + memcpy(header, blenderBuf, SIZEOFBLENDERHEADER); + header[SIZEOFBLENDERHEADER]='\0'; + + if (strncmp(header, m_headerString, 6)!=0) + { + memcpy(header, m_headerString, SIZEOFBLENDERHEADER); + printf ("Invalid %s file...",header); + return; + } + + if (header[6] == 'd') + { + mFlags |= FD_DOUBLE_PRECISION; + } + + char *ver = header+9; + mVersion = atoi(ver); + if (mVersion <= 241) + printf ("Warning, %d not fully tested : <= 242\n", mVersion); + + + int littleEndian= 1; + littleEndian= ((char*)&littleEndian)[0]; + + // swap ptr sizes... + if (header[7]=='-') + { + mFlags |= FD_FILE_64; + if (!VOID_IS_8) + mFlags |= FD_BITS_VARIES; + } + else if (VOID_IS_8) mFlags |= FD_BITS_VARIES; + + // swap endian... + if (header[8]=='V') + { + if (littleEndian ==1) + mFlags |= FD_ENDIAN_SWAP; + } + else + if (littleEndian==0) + mFlags |= FD_ENDIAN_SWAP; + + + printf ("%s\n",header); + printf ("\nsizeof(void*) == %d\n",int(sizeof(void*))); + const char* endStr = ((mFlags & FD_ENDIAN_SWAP)!=0) ? "yes" : "no"; + printf ("Swapping endian? %s\n",endStr); + const char* bitStr = (mFlags &FD_FILE_64)!=0 ? "64 bit" : "32bit"; + printf ("File format is %s\n",bitStr); + const char* varStr = (mFlags & FD_BITS_VARIES)!=0 ? "yes" : "no"; + printf ("Varing pointer sizes? %s\n",varStr); + + + mFlags |= FD_OK; +} + +// ----------------------------------------------------- // +bool bFile::ok() +{ + return (mFlags &FD_OK)!=0; +} + +// ----------------------------------------------------- // +void bFile::parseInternal(bool verboseDumpAllTypes, char* memDna,int memDnaLength) +{ + if ( (mFlags &FD_OK) ==0) + return; + + char *blenderData = mFileBuffer; + bChunkInd dna; + dna.oldPtr = 0; + + char *tempBuffer = blenderData; + for (int i=0; i 0) + { + if (strncmp((tempBuffer + ChunkUtils::getOffset(mFlags)), "SDNANAME", 8) ==0) + dna.oldPtr = (tempBuffer + ChunkUtils::getOffset(mFlags)); + else dna.oldPtr = 0; + } + else dna.oldPtr = 0; + } + // Some Bullet files are missing the DNA1 block + // In Blender it's DNA1 + ChunkUtils::getOffset() + SDNA + NAME + // In Bullet tests its SDNA + NAME + else if (strncmp(tempBuffer, "SDNANAME", 8) ==0) + { + dna.oldPtr = blenderData + i; + dna.len = mFileLen-i; + + // Also no REND block, so exit now. + if (mVersion==276) break; + } + + if (mDataStart && dna.oldPtr) break; + tempBuffer++; + } + if (!dna.oldPtr || !dna.len) + { + printf("Failed to find DNA1+SDNA pair\n"); + mFlags &= ~FD_OK; + return; + } + + + mFileDNA = new bDNA(); + mFileDNA->init((char*)dna.oldPtr, dna.len, (mFlags & FD_ENDIAN_SWAP)!=0); + + if (mVersion==276) + { + int i; + for (i=0;igetNumNames();i++) + { + if (strcmp(mFileDNA->getName(i),"int")==0) + { + mFlags |= FD_BROKEN_DNA; + } + } + if ((mFlags&FD_BROKEN_DNA)!=0) + { + printf("warning: fixing some broken DNA version\n"); + } + } + + + + if (verboseDumpAllTypes) + { + mFileDNA->dumpTypeDefinitions(); + } + + mMemoryDNA = new bDNA(); + int littleEndian= 1; + littleEndian= ((char*)&littleEndian)[0]; + + mMemoryDNA->init(memDna,memDnaLength,littleEndian==0); + + + + + ///@todo we need a better version check, add version/sub version info from FileGlobal into memory DNA/header files + if (mMemoryDNA->getNumNames() != mFileDNA->getNumNames()) + { + mFlags |= FD_VERSION_VARIES; + printf ("Warning, file DNA is different than built in, performance is reduced. Best to re-export file with a matching version/platform"); + } + + // as long as it kept up to date it will be ok!! + if (mMemoryDNA->lessThan(mFileDNA)) + { + printf ("Warning, file DNA is newer than built in."); + } + + mFileDNA->initCmpFlags(mMemoryDNA); + + parseData(); + + resolvePointers(verboseDumpAllTypes);//verboseDumpAllBlocks); + + updateOldPointers(); + + printf("numAllocs = %d\n",numallocs); +} + + + +// ----------------------------------------------------- // +void bFile::swap(char *head, bChunkInd& dataChunk) +{ + char *data = head; + short *strc = mFileDNA->getStruct(dataChunk.dna_nr); + int len = mFileDNA->getLength(strc[0]); + + for (int i=0; iflagEqual(dataChunk.dna_nr)) + { + // Ouch! need to rebuild the struct + short *oldStruct,*curStruct; + char *oldType, *newType; + int oldLen, curLen, reverseOld; + + + oldStruct = mFileDNA->getStruct(dataChunk.dna_nr); + oldType = mFileDNA->getType(oldStruct[0]); + oldLen = mFileDNA->getLength(oldStruct[0]); + + if ((mFlags&FD_BROKEN_DNA)!=0) + { + if ((strcmp(oldType,"btQuantizedBvhNodeData")==0)&&oldLen==20) + { + return 0; + } + if ((strcmp(oldType,"btShortIntIndexData")==0)) + { + int allocLen = 2; + char *dataAlloc = new char[(dataChunk.nr*allocLen)+1]; + memset(dataAlloc, 0, (dataChunk.nr*allocLen)+1); + short* dest = (short*) dataAlloc; + const short* src = (short*) head; + for (int i=0;igetReverseType(oldType); + + if ((reverseOld!=-1)) + { + // make sure it's here + //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!"); + + // + curStruct = mMemoryDNA->getStruct(reverseOld); + newType = mMemoryDNA->getType(curStruct[0]); + curLen = mMemoryDNA->getLength(curStruct[0]); + + + + // make sure it's the same + assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!"); + + + numallocs++; + // numBlocks * length + + int allocLen = (curLen); + char *dataAlloc = new char[(dataChunk.nr*allocLen)+1]; + memset(dataAlloc, 0, (dataChunk.nr*allocLen)); + + // track allocated + addDataBlock(dataAlloc); + + char *cur = dataAlloc; + char *old = head; + for (int block=0; blockgetStruct(dataChunk.dna_nr); + oldType = mFileDNA->getType(oldStruct[0]); + printf("%s equal structure, just memcpy\n",oldType); +#endif // + } + + + char *dataAlloc = new char[(dataChunk.len)+1]; + memset(dataAlloc, 0, dataChunk.len+1); + + + // track allocated + addDataBlock(dataAlloc); + + memcpy(dataAlloc, head, dataChunk.len); + return dataAlloc; + +} + + +// ----------------------------------------------------- // +void bFile::parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers) +{ + if (old_dna == -1) return; + if (new_dna == -1) return; + + //disable this, because we need to fixup pointers/ListBase + if (0)//mFileDNA->flagEqual(old_dna)) + { + short *strc = mFileDNA->getStruct(old_dna); + int len = mFileDNA->getLength(strc[0]); + + memcpy(strcPtr, dtPtr, len); + return; + } + + // Ok, now build the struct + char *memType, *memName, *cpc, *cpo; + short *fileStruct, *filePtrOld, *memoryStruct, *firstStruct; + int elementLength, size, revType, old_nr, new_nr, fpLen; + short firstStructType; + + + // File to memory lookup + memoryStruct = mMemoryDNA->getStruct(new_dna); + fileStruct = mFileDNA->getStruct(old_dna); + firstStruct = fileStruct; + + + filePtrOld = fileStruct; + firstStructType = mMemoryDNA->getStruct(0)[0]; + + // Get number of elements + elementLength = memoryStruct[1]; + memoryStruct+=2; + + cpc = strcPtr; cpo = 0; + for (int ele=0; elegetType(memoryStruct[0]); + memName = mMemoryDNA->getName(memoryStruct[1]); + + + size = mMemoryDNA->getElementSize(memoryStruct[0], memoryStruct[1]); + revType = mMemoryDNA->getReverseType(memoryStruct[0]); + + if (revType != -1 && memoryStruct[0]>=firstStructType && memName[0] != '*') + { + cpo = getFileElement(firstStruct, memName, memType, dtPtr, &filePtrOld); + if (cpo) + { + int arrayLen = mFileDNA->getArraySizeNew(filePtrOld[1]); + old_nr = mFileDNA->getReverseType(memType); + new_nr = revType; + fpLen = mFileDNA->getElementSize(filePtrOld[0], filePtrOld[1]); + if (arrayLen==1) + { + parseStruct(cpc, cpo, old_nr, new_nr,fixupPointers); + } else + { + char* tmpCpc = cpc; + char* tmpCpo = cpo; + + for (int i=0;i3 && type <8) + { + char c; + char *cp = data; + for (int i=0; igetPointerSize(); + int ptrMem = mMemoryDNA->getPointerSize(); + + if (!src && !dst) + return; + + + if (ptrFile == ptrMem) + { + memcpy(dst, src, ptrMem); + } + else if (ptrMem==4 && ptrFile==8) + { + btPointerUid* oldPtr = (btPointerUid*)src; + btPointerUid* newPtr = (btPointerUid*)dst; + + if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1]) + { + //Bullet stores the 32bit unique ID in both upper and lower part of 64bit pointers + //so it can be used to distinguish between .blend and .bullet + newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0]; + } else + { + //deal with pointers the Blender .blend style way, see + //readfile.c in the Blender source tree + long64 longValue = *((long64*)src); + //endian swap for 64bit pointer otherwise truncation will fail due to trailing zeros + if (mFlags & FD_ENDIAN_SWAP) + SWITCH_LONGINT(longValue); + *((int*)dst) = (int)(longValue>>3); + } + + } + else if (ptrMem==8 && ptrFile==4) + { + btPointerUid* oldPtr = (btPointerUid*)src; + btPointerUid* newPtr = (btPointerUid*)dst; + if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1]) + { + newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0]; + newPtr->m_uniqueIds[1] = 0; + } else + { + *((long64*)dst)= *((int*)src); + } + } + else + { + printf ("%d %d\n", ptrFile,ptrMem); + assert(0 && "Invalid pointer len"); + } + + +} + + +// ----------------------------------------------------- // +void bFile::getMatchingFileDNA(short* dna_addr, const char* lookupName, const char* lookupType, char *strcData, char *data, bool fixupPointers) +{ + // find the matching memory dna data + // to the file being loaded. Fill the + // memory with the file data... + + int len = dna_addr[1]; + dna_addr+=2; + + for (int i=0; igetType(dna_addr[0]); + const char* name = mFileDNA->getName(dna_addr[1]); + + + + int eleLen = mFileDNA->getElementSize(dna_addr[0], dna_addr[1]); + + if ((mFlags&FD_BROKEN_DNA)!=0) + { + if ((strcmp(type,"short")==0)&&(strcmp(name,"int")==0)) + { + eleLen = 0; + } + } + + if (strcmp(lookupName, name)==0) + { + //int arrayLenold = mFileDNA->getArraySize((char*)name.c_str()); + int arrayLen = mFileDNA->getArraySizeNew(dna_addr[1]); + //assert(arrayLenold == arrayLen); + + if (name[0] == '*') + { + // cast pointers + int ptrFile = mFileDNA->getPointerSize(); + int ptrMem = mMemoryDNA->getPointerSize(); + safeSwapPtr(strcData,data); + + if (fixupPointers) + { + if (arrayLen > 1) + { + //void **sarray = (void**)strcData; + //void **darray = (void**)data; + + char *cpc, *cpo; + cpc = (char*)strcData; + cpo = (char*)data; + + for (int a=0; agetStruct(old_nr); + int elementLength = old[1]; + old+=2; + + for (int i=0; igetType(old[0]); + char* name = mFileDNA->getName(old[1]); + int len = mFileDNA->getElementSize(old[0], old[1]); + + if (strcmp(lookupName, name)==0) + { + if (strcmp(type, lookupType)==0) + { + if (foundPos) + *foundPos = old; + return data; + } + return 0; + } + data+=len; + } + return 0; +} + + +// ----------------------------------------------------- // +void bFile::swapStruct(int dna_nr, char *data) +{ + if (dna_nr == -1) return; + + short *strc = mFileDNA->getStruct(dna_nr); + //short *firstStrc = strc; + + int elementLen= strc[1]; + strc+=2; + + short first = mFileDNA->getStruct(0)[0]; + + char *buf = data; + for (int i=0; igetType(strc[0]); + char *name = mFileDNA->getName(strc[1]); + + int size = mFileDNA->getElementSize(strc[0], strc[1]); + if (strc[0] >= first && name[0]!='*') + { + int old_nr = mFileDNA->getReverseType(type); + int arrayLen = mFileDNA->getArraySizeNew(strc[1]); + if (arrayLen==1) + { + swapStruct(old_nr,buf); + } else + { + char* tmpBuf = buf; + for (int i=0;igetArraySize(name); + int arrayLen = mFileDNA->getArraySizeNew(strc[1]); + //assert(arrayLenOld == arrayLen); + swapData(buf, strc[0], arrayLen); + } + buf+=size; + } +} + +void bFile::resolvePointersMismatch() +{ +// printf("resolvePointersStructMismatch\n"); + + int i; + + for (i=0;i< m_pointerFixupArray.size();i++) + { + char* cur = m_pointerFixupArray.at(i); + void** ptrptr = (void**) cur; + void* ptr = *ptrptr; + ptr = findLibPointer(ptr); + if (ptr) + { + //printf("Fixup pointer!\n"); + *(ptrptr) = ptr; + } else + { +// printf("pointer not found: %x\n",cur); + } + } + + + for (i=0; igetPointerSize(); + int ptrFile = mFileDNA->getPointerSize(); + + + int blockLen = block->len / ptrFile; + + void *onptr = findLibPointer(*ptrptr); + if (onptr) + { + char *newPtr = new char[blockLen * ptrMem]; + addDataBlock(newPtr); + memset(newPtr, 0, blockLen * ptrMem); + + void **onarray = (void**)onptr; + char *oldPtr = (char*)onarray; + + int p = 0; + while (blockLen-- > 0) + { + btPointerUid dp = {0}; + safeSwapPtr((char*)dp.m_uniqueIds, oldPtr); + + void **tptr = (void**)(newPtr + p * ptrMem); + *tptr = findLibPointer(dp.m_ptr); + + oldPtr += ptrFile; + ++p; + } + + *ptrptr = newPtr; + } + } + } +} + + +///this loop only works fine if the Blender DNA structure of the file matches the headerfiles +void bFile::resolvePointersChunk(const bChunkInd& dataChunk, bool verboseDumpAllBlocks) +{ + bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA; + + short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr); + short oldLen = fileDna->getLength(oldStruct[0]); + //char* structType = fileDna->getType(oldStruct[0]); + + char* cur = (char*)findLibPointer(dataChunk.oldPtr); + for (int block=0; blockgetStruct(0)[0]; + + + char* elemPtr= strcPtr; + + short int* oldStruct = fileDna->getStruct(dna_nr); + + int elementLength = oldStruct[1]; + oldStruct+=2; + + + for (int ele=0; elegetType(oldStruct[0]); + memName = fileDna->getName(oldStruct[1]); + + + + int arrayLen = fileDna->getArraySizeNew(oldStruct[1]); + if (memName[0] == '*') + { + if (arrayLen > 1) + { + void **array= (void**)elemPtr; + for (int a=0; agetReverseType(oldStruct[0]); + if (oldStruct[0]>=firstStructType) //revType != -1 && + { + if (verboseDumpAllBlocks) + { + for (int i=0;i\n",memName,memType); + } + resolvePointersStructRecursive(elemPtr,revType, verboseDumpAllBlocks,recursion+1); + if (verboseDumpAllBlocks) + { + for (int i=0;i\n",memName); + } + } else + { + //export a simple type + if (verboseDumpAllBlocks) + { + + if (arrayLen>MAX_ARRAY_LENGTH) + { + printf("too long\n"); + } else + { + //printf("%s %s\n",memType,memName); + + bool isIntegerType = (strcmp(memType,"char")==0) || (strcmp(memType,"int")==0) || (strcmp(memType,"short")==0); + + if (isIntegerType) + { + const char* newtype="int"; + int dbarray[MAX_ARRAY_LENGTH]; + int* dbPtr = 0; + char* tmp = elemPtr; + dbPtr = &dbarray[0]; + if (dbPtr) + { + int i; + getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr); + for (i=0;i",memName,memType); + else + printf("<%s type=\"%s\" count=%d>",memName,memType,arrayLen); + for (i=0;i\n",memName); + } + } else + { + const char* newtype="double"; + double dbarray[MAX_ARRAY_LENGTH]; + double* dbPtr = 0; + char* tmp = elemPtr; + dbPtr = &dbarray[0]; + if (dbPtr) + { + int i; + getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr); + for (i=0;i",memName,memType); + else + printf("<%s type=\"%s\" count=%d>",memName,memType,arrayLen); + for (i=0;i\n",memName); + } + } + } + + } + } + } + + int size = fileDna->getElementSize(oldStruct[0], oldStruct[1]); + elemPtr+=size; + + } +} + + +///Resolve pointers replaces the original pointers in structures, and linked lists by the new in-memory structures +void bFile::resolvePointers(bool verboseDumpAllBlocks) +{ + bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA; + + printf("resolvePointers start\n"); + //char *dataPtr = mFileBuffer+mDataStart; + + if (1) //mFlags & (FD_BITS_VARIES | FD_VERSION_VARIES)) + { + resolvePointersMismatch(); + } + + { + for (int i=0;iflagEqual(dataChunk.dna_nr)) + { + //dataChunk.len + short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr); + char* oldType = fileDna->getType(oldStruct[0]); + + if (verboseDumpAllBlocks) + printf("<%s>\n",oldType); + + resolvePointersChunk(dataChunk, verboseDumpAllBlocks); + + if (verboseDumpAllBlocks) + printf("\n",oldType); + } else + { + //printf("skipping mStruct\n"); + } + } + } + + printf("resolvePointers end\n"); +} + + +// ----------------------------------------------------- // +void* bFile::findLibPointer(void *ptr) +{ + + bStructHandle** ptrptr = getLibPointers().find(ptr); + if (ptrptr) + return *ptrptr; + return 0; +} + + +void bFile::updateOldPointers() +{ + int i; + + for (i=0;igetStruct(dataChunk.dna_nr); + char* typeName = dna->getType(newStruct[0]); + printf("%3d: %s ",i,typeName); + + printf("code=%s ",codestr); + + printf("ptr=%p ",dataChunk.oldPtr); + printf("len=%d ",dataChunk.len); + printf("nr=%d ",dataChunk.nr); + if (dataChunk.nr!=1) + { + printf("not 1\n"); + } + printf("\n"); + + + + + } + +#if 0 + IDFinderData ifd; + ifd.success = 0; + ifd.IDname = NULL; + ifd.just_print_it = 1; + for (i=0; im_blocks.size(); ++i) + { + BlendBlock* bb = bf->m_blocks[i]; + printf("tag='%s'\tptr=%p\ttype=%s\t[%4d]", bb->tag, bb,bf->types[bb->type_index].name,bb->m_array_entries_.size()); + block_ID_finder(bb, bf, &ifd); + printf("\n"); + } +#endif + +} + + +void bFile::writeChunks(FILE* fp, bool fixupPointers) +{ + bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA; + + for (int i=0;igetStruct(dataChunk.dna_nr); + oldType = fileDna->getType(oldStruct[0]); + oldLen = fileDna->getLength(oldStruct[0]); + ///don't try to convert Link block data, just memcpy it. Other data can be converted. + reverseOld = mMemoryDNA->getReverseType(oldType); + + + if ((reverseOld!=-1)) + { + // make sure it's here + //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!"); + // + curStruct = mMemoryDNA->getStruct(reverseOld); + newType = mMemoryDNA->getType(curStruct[0]); + // make sure it's the same + assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!"); + + + curLen = mMemoryDNA->getLength(curStruct[0]); + dataChunk.dna_nr = reverseOld; + if (strcmp("Link",oldType)!=0) + { + dataChunk.len = curLen * dataChunk.nr; + } else + { +// printf("keep length of link = %d\n",dataChunk.len); + } + + //write the structure header + fwrite(&dataChunk,sizeof(bChunkInd),1,fp); + + + + short int* curStruct1; + curStruct1 = mMemoryDNA->getStruct(dataChunk.dna_nr); + assert(curStruct1 == curStruct); + + char* cur = fixupPointers ? (char*)findLibPointer(dataChunk.oldPtr) : (char*)dataChunk.oldPtr; + + //write the actual contents of the structure(s) + fwrite(cur,dataChunk.len,1,fp); + } else + { + printf("serious error, struct mismatch: don't write\n"); + } + } + +} + +// ----------------------------------------------------- // +int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags) +{ + bool swap = false; + bool varies = false; + + if (flags &FD_ENDIAN_SWAP) swap = true; + if (flags &FD_BITS_VARIES) varies = true; + + if (VOID_IS_8) + { + if (varies) + { + bChunkPtr4 head; + memcpy(&head, dataPtr, sizeof(bChunkPtr4)); + + + bChunkPtr8 chunk; + + chunk.code = head.code; + chunk.len = head.len; + chunk.m_uniqueInts[0] = head.m_uniqueInt; + chunk.m_uniqueInts[1] = 0; + chunk.dna_nr = head.dna_nr; + chunk.nr = head.nr; + + if (swap) + { + if ((chunk.code & 0xFFFF)==0) + chunk.code >>=16; + + SWITCH_INT(chunk.len); + SWITCH_INT(chunk.dna_nr); + SWITCH_INT(chunk.nr); + } + + + memcpy(dataChunk, &chunk, sizeof(bChunkInd)); + } + else + { + bChunkPtr8 c; + memcpy(&c, dataPtr, sizeof(bChunkPtr8)); + + if (swap) + { + if ((c.code & 0xFFFF)==0) + c.code >>=16; + + SWITCH_INT(c.len); + SWITCH_INT(c.dna_nr); + SWITCH_INT(c.nr); + } + + memcpy(dataChunk, &c, sizeof(bChunkInd)); + } + } + else + { + if (varies) + { + bChunkPtr8 head; + memcpy(&head, dataPtr, sizeof(bChunkPtr8)); + + + bChunkPtr4 chunk; + chunk.code = head.code; + chunk.len = head.len; + + if (head.m_uniqueInts[0]==head.m_uniqueInts[1]) + { + chunk.m_uniqueInt = head.m_uniqueInts[0]; + } else + { + long64 oldPtr =0; + memcpy(&oldPtr, &head.m_uniqueInts[0], 8); + if (swap) + SWITCH_LONGINT(oldPtr); + chunk.m_uniqueInt = (int)(oldPtr >> 3); + } + + + chunk.dna_nr = head.dna_nr; + chunk.nr = head.nr; + + if (swap) + { + if ((chunk.code & 0xFFFF)==0) + chunk.code >>=16; + + SWITCH_INT(chunk.len); + SWITCH_INT(chunk.dna_nr); + SWITCH_INT(chunk.nr); + } + + memcpy(dataChunk, &chunk, sizeof(bChunkInd)); + } + else + { + bChunkPtr4 c; + memcpy(&c, dataPtr, sizeof(bChunkPtr4)); + + if (swap) + { + if ((c.code & 0xFFFF)==0) + c.code >>=16; + + SWITCH_INT(c.len); + SWITCH_INT(c.dna_nr); + SWITCH_INT(c.nr); + } + memcpy(dataChunk, &c, sizeof(bChunkInd)); + } + } + + if (dataChunk->len < 0) + return -1; + +#if 0 + print ("----------"); + print (dataChunk->code); + print (dataChunk->len); + print (dataChunk->old); + print (dataChunk->dna_nr); + print (dataChunk->nr); +#endif + return (dataChunk->len+ChunkUtils::getOffset(flags)); +} + + + +//eof diff --git a/Extras/Serialize/BulletFileLoader/bFile.h b/Extras/Serialize/BulletFileLoader/bFile.h new file mode 100644 index 0000000..405bbe3 --- /dev/null +++ b/Extras/Serialize/BulletFileLoader/bFile.h @@ -0,0 +1,158 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +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 __BFILE_H__ +#define __BFILE_H__ + +#include "bCommon.h" +#include "bChunk.h" +#include + +namespace bParse { + + // ----------------------------------------------------- // + enum bFileFlags + { + FD_INVALID =0, + FD_OK =1, + FD_VOID_IS_8 =2, + FD_ENDIAN_SWAP =4, + FD_FILE_64 =8, + FD_BITS_VARIES =16, + FD_VERSION_VARIES = 32, + FD_DOUBLE_PRECISION =64, + FD_BROKEN_DNA = 128 + }; + + + // ----------------------------------------------------- // + class bFile + { + protected: + + char m_headerString[7]; + + bool mOwnsBuffer; + char* mFileBuffer; + int mFileLen; + int mVersion; + + + bPtrMap mLibPointers; + + int mDataStart; + bDNA* mFileDNA; + bDNA* mMemoryDNA; + + btAlignedObjectArray m_pointerFixupArray; + btAlignedObjectArray m_pointerPtrFixupArray; + + btAlignedObjectArray m_chunks; + btHashMap m_chunkPtrPtrMap; + + // + + bPtrMap mDataPointers; + + + int mFlags; + + // //////////////////////////////////////////////////////////////////////////// + + // buffer offset util + int getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags); + void safeSwapPtr(char *dst, const char *src); + + virtual void parseHeader(); + + virtual void parseData() = 0; + + void resolvePointersMismatch(); + void resolvePointersChunk(const bChunkInd& dataChunk, bool verboseDumpAllBlocks); + + void resolvePointersStructRecursive(char *strcPtr, int old_dna, bool verboseDumpAllBlocks, int recursion); + //void swapPtr(char *dst, char *src); + + void parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers); + void getMatchingFileDNA(short* old, const char* lookupName, const char* lookupType, char *strcData, char *data, bool fixupPointers); + char* getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos); + + + void swap(char *head, class bChunkInd& ch); + + void swapData(char *data, short type, int arraySize); + void swapStruct(int dna_nr, char *data); + + + + + char* readStruct(char *head, class bChunkInd& chunk); + char *getAsString(int code); + + void parseInternal(bool verboseDumpAllTypes, char* memDna,int memDnaLength); + + public: + bFile(const char *filename, const char headerString[7]); + + //todo: make memoryBuffer const char + //bFile( const char *memoryBuffer, int len); + bFile( char *memoryBuffer, int len, const char headerString[7]); + virtual ~bFile(); + + bDNA* getFileDNA() + { + return mFileDNA; + } + + virtual void addDataBlock(char* dataBlock) = 0; + + int getFlags() const + { + return mFlags; + } + + bPtrMap& getLibPointers() + { + return mLibPointers; + } + + void* findLibPointer(void *ptr); + + bool ok(); + + virtual void parse(bool verboseDumpAllTypes) = 0; + + virtual int write(const char* fileName, bool fixupPointers=false) = 0; + + virtual void writeChunks(FILE* fp, bool fixupPointers ); + + virtual void writeDNA(FILE* fp) = 0; + + void updateOldPointers(); + void resolvePointers(bool verboseDumpAllBlocks); + + void dumpChunks(bDNA* dna); + + int getVersion() const + { + return mVersion; + } + + + }; +} + + +#endif//__BFILE_H__ diff --git a/Extras/Serialize/BulletFileLoader/btBulletFile.cpp b/Extras/Serialize/BulletFileLoader/btBulletFile.cpp new file mode 100644 index 0000000..69b3e2e --- /dev/null +++ b/Extras/Serialize/BulletFileLoader/btBulletFile.cpp @@ -0,0 +1,401 @@ +/* +bParse +Copyright (c) 2006-2010 Erwin Coumans http://gamekit.googlecode.com + +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 "btBulletFile.h" +#include "bDefines.h" +#include "bDNA.h" + +#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__) +#include +#endif +#include + + +// 32 && 64 bit versions +#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES +#ifdef _WIN64 +extern char sBulletDNAstr64[]; +extern int sBulletDNAlen64; +#else +extern char sBulletDNAstr[]; +extern int sBulletDNAlen; +#endif //_WIN64 +#else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + +extern char sBulletDNAstr64[]; +extern int sBulletDNAlen64; +extern char sBulletDNAstr[]; +extern int sBulletDNAlen; + +#endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + +using namespace bParse; + +btBulletFile::btBulletFile() +:bFile("", "BULLET ") +{ + mMemoryDNA = new bDNA(); //this memory gets released in the bFile::~bFile destructor,@todo not consistent with the rule 'who allocates it, has to deallocate it" + + m_DnaCopy = 0; + + +#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES +#ifdef _WIN64 + m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen64,16); + memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64); + mMemoryDNA->init(m_DnaCopy,sBulletDNAlen64); +#else//_WIN64 + m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen,16); + memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen); + mMemoryDNA->init(m_DnaCopy,sBulletDNAlen); +#endif//_WIN64 +#else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + if (VOID_IS_8) + { + m_DnaCopy = (char*) btAlignedAlloc(sBulletDNAlen64,16); + memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64); + mMemoryDNA->init(m_DnaCopy,sBulletDNAlen64); + } + else + { + m_DnaCopy =(char*) btAlignedAlloc(sBulletDNAlen,16); + memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen); + mMemoryDNA->init(m_DnaCopy,sBulletDNAlen); + } +#endif//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES +} + + + +btBulletFile::btBulletFile(const char* fileName) +:bFile(fileName, "BULLET ") +{ + m_DnaCopy = 0; +} + + + +btBulletFile::btBulletFile(char *memoryBuffer, int len) +:bFile(memoryBuffer,len, "BULLET ") +{ + m_DnaCopy = 0; +} + + +btBulletFile::~btBulletFile() +{ + if (m_DnaCopy) + btAlignedFree(m_DnaCopy); + + + while (m_dataBlocks.size()) + { + char* dataBlock = m_dataBlocks[m_dataBlocks.size()-1]; + delete[] dataBlock; + m_dataBlocks.pop_back(); + } + +} + + + +// ----------------------------------------------------- // +void btBulletFile::parseData() +{ + printf ("Building datablocks"); + printf ("Chunk size = %d",CHUNK_HEADER_LEN); + printf ("File chunk size = %d",ChunkUtils::getOffset(mFlags)); + + const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0; + + //const bool swap = (mFlags&FD_ENDIAN_SWAP)!=0; + + + mDataStart = 12; + + char *dataPtr = mFileBuffer+mDataStart; + + bChunkInd dataChunk; + dataChunk.code = 0; + + + //dataPtr += ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags); + int seek = getNextBlock(&dataChunk, dataPtr, mFlags); + //dataPtr += ChunkUtils::getOffset(mFlags); + char *dataPtrHead = 0; + + while (dataChunk.code != DNA1) + { + if (!brokenDNA || (dataChunk.code != BT_QUANTIZED_BVH_CODE) ) + { + + // one behind + if (dataChunk.code == SDNA) break; + //if (dataChunk.code == DNA1) break; + + // same as (BHEAD+DATA dependency) + dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags); + if (dataChunk.dna_nr>=0) + { + char *id = readStruct(dataPtrHead, dataChunk); + + // lookup maps + if (id) + { + m_chunkPtrPtrMap.insert(dataChunk.oldPtr, dataChunk); + mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)id); + + m_chunks.push_back(dataChunk); + // block it + //bListBasePtr *listID = mMain->getListBasePtr(dataChunk.code); + //if (listID) + // listID->push_back((bStructHandle*)id); + } + + if (dataChunk.code == BT_SOFTBODY_CODE) + { + m_softBodies.push_back((bStructHandle*) id); + } + + if (dataChunk.code == BT_RIGIDBODY_CODE) + { + m_rigidBodies.push_back((bStructHandle*) id); + } + + if (dataChunk.code == BT_CONSTRAINT_CODE) + { + m_constraints.push_back((bStructHandle*) id); + } + + if (dataChunk.code == BT_QUANTIZED_BVH_CODE) + { + m_bvhs.push_back((bStructHandle*) id); + } + + if (dataChunk.code == BT_TRIANLGE_INFO_MAP) + { + m_triangleInfoMaps.push_back((bStructHandle*) id); + } + + if (dataChunk.code == BT_COLLISIONOBJECT_CODE) + { + m_collisionObjects.push_back((bStructHandle*) id); + } + + if (dataChunk.code == BT_SHAPE_CODE) + { + m_collisionShapes.push_back((bStructHandle*) id); + } + + // if (dataChunk.code == GLOB) + // { + // m_glob = (bStructHandle*) id; + // } + } else + { + printf("unknown chunk\n"); + + mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)dataPtrHead); + } + } else + { + printf("skipping BT_QUANTIZED_BVH_CODE due to broken DNA\n"); + } + + // next please! + dataPtr += seek; + + seek = getNextBlock(&dataChunk, dataPtr, mFlags); + if (seek < 0) + break; + } + +} + +void btBulletFile::addDataBlock(char* dataBlock) +{ + m_dataBlocks.push_back(dataBlock); + +} + + + + +void btBulletFile::writeDNA(FILE* fp) +{ + + bChunkInd dataChunk; + dataChunk.code = DNA1; + dataChunk.dna_nr = 0; + dataChunk.nr = 1; +#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + if (VOID_IS_8) + { +#ifdef _WIN64 + dataChunk.len = sBulletDNAlen64; + dataChunk.oldPtr = sBulletDNAstr64; + fwrite(&dataChunk,sizeof(bChunkInd),1,fp); + fwrite(sBulletDNAstr64, sBulletDNAlen64,1,fp); +#else + btAssert(0); +#endif + } + else + { +#ifndef _WIN64 + dataChunk.len = sBulletDNAlen; + dataChunk.oldPtr = sBulletDNAstr; + fwrite(&dataChunk,sizeof(bChunkInd),1,fp); + fwrite(sBulletDNAstr, sBulletDNAlen,1,fp); +#else//_WIN64 + btAssert(0); +#endif//_WIN64 + } +#else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + if (VOID_IS_8) + { + dataChunk.len = sBulletDNAlen64; + dataChunk.oldPtr = sBulletDNAstr64; + fwrite(&dataChunk,sizeof(bChunkInd),1,fp); + fwrite(sBulletDNAstr64, sBulletDNAlen64,1,fp); + } + else + { + dataChunk.len = sBulletDNAlen; + dataChunk.oldPtr = sBulletDNAstr; + fwrite(&dataChunk,sizeof(bChunkInd),1,fp); + fwrite(sBulletDNAstr, sBulletDNAlen,1,fp); + } +#endif//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES +} + + +void btBulletFile::parse(bool verboseDumpAllTypes) +{ +#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + if (VOID_IS_8) + { +#ifdef _WIN64 + + if (m_DnaCopy) + delete m_DnaCopy; + m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen64,16); + memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64); + parseInternal(verboseDumpAllTypes,(char*)sBulletDNAstr64,sBulletDNAlen64); +#else + btAssert(0); +#endif + } + else + { +#ifndef _WIN64 + + if (m_DnaCopy) + delete m_DnaCopy; + m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen,16); + memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen); + parseInternal(verboseDumpAllTypes,m_DnaCopy,sBulletDNAlen); +#else + btAssert(0); +#endif + } +#else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + if (VOID_IS_8) + { + if (m_DnaCopy) + delete m_DnaCopy; + m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen64,16); + memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64); + parseInternal(verboseDumpAllTypes,m_DnaCopy,sBulletDNAlen64); + } + else + { + if (m_DnaCopy) + delete m_DnaCopy; + m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen,16); + memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen); + parseInternal(verboseDumpAllTypes,m_DnaCopy,sBulletDNAlen); + } +#endif//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES +} + +// experimental +int btBulletFile::write(const char* fileName, bool fixupPointers) +{ + FILE *fp = fopen(fileName, "wb"); + if (fp) + { + char header[SIZEOFBLENDERHEADER] ; + memcpy(header, m_headerString, 7); + int endian= 1; + endian= ((char*)&endian)[0]; + + if (endian) + { + header[7] = '_'; + } else + { + header[7] = '-'; + } + if (VOID_IS_8) + { + header[8]='V'; + } else + { + header[8]='v'; + } + + header[9] = '2'; + header[10] = '7'; + header[11] = '5'; + + fwrite(header,SIZEOFBLENDERHEADER,1,fp); + + writeChunks(fp, fixupPointers); + + writeDNA(fp); + + fclose(fp); + + } else + { + printf("Error: cannot open file %s for writing\n",fileName); + return 0; + } + return 1; +} + + + +void btBulletFile::addStruct(const char* structType,void* data, int len, void* oldPtr, int code) +{ + + bParse::bChunkInd dataChunk; + dataChunk.code = code; + dataChunk.nr = 1; + dataChunk.len = len; + dataChunk.dna_nr = mMemoryDNA->getReverseType(structType); + dataChunk.oldPtr = oldPtr; + + ///Perform structure size validation + short* structInfo= mMemoryDNA->getStruct(dataChunk.dna_nr); + int elemBytes; + elemBytes= mMemoryDNA->getLength(structInfo[0]); +// int elemBytes = mMemoryDNA->getElementSize(structInfo[0],structInfo[1]); + assert(len==elemBytes); + + mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)data); + m_chunks.push_back(dataChunk); +} \ No newline at end of file diff --git a/Extras/Serialize/BulletFileLoader/btBulletFile.h b/Extras/Serialize/BulletFileLoader/btBulletFile.h new file mode 100644 index 0000000..e82c3e9 --- /dev/null +++ b/Extras/Serialize/BulletFileLoader/btBulletFile.h @@ -0,0 +1,81 @@ +/* +bParse +Copyright (c) 2006-2010 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_BULLET_FILE_H +#define BT_BULLET_FILE_H + + +#include "bFile.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "bDefines.h" + +#include "LinearMath/btSerializer.h" + + + +namespace bParse { + + // ----------------------------------------------------- // + class btBulletFile : public bFile + { + + + protected: + + char* m_DnaCopy; + + public: + + btAlignedObjectArray m_softBodies; + + btAlignedObjectArray m_rigidBodies; + + btAlignedObjectArray m_collisionObjects; + + btAlignedObjectArray m_collisionShapes; + + btAlignedObjectArray m_constraints; + + btAlignedObjectArray m_bvhs; + + btAlignedObjectArray m_triangleInfoMaps; + + btAlignedObjectArray m_dataBlocks; + btBulletFile(); + + btBulletFile(const char* fileName); + + btBulletFile(char *memoryBuffer, int len); + + virtual ~btBulletFile(); + + virtual void addDataBlock(char* dataBlock); + + + // experimental + virtual int write(const char* fileName, bool fixupPointers=false); + + virtual void parse(bool verboseDumpAllTypes); + + virtual void parseData(); + + virtual void writeDNA(FILE* fp); + + void addStruct(const char* structType,void* data, int len, void* oldPtr, int code); + + }; +}; + +#endif //BT_BULLET_FILE_H diff --git a/Extras/Serialize/BulletFileLoader/premake4.lua b/Extras/Serialize/BulletFileLoader/premake4.lua new file mode 100644 index 0000000..b9480ed --- /dev/null +++ b/Extras/Serialize/BulletFileLoader/premake4.lua @@ -0,0 +1,12 @@ + project "BulletFileLoader" + + kind "StaticLib" + targetdir "../../lib" + includedirs { + "../../../src" + } + + files { + "**.cpp", + "**.h" + } \ No newline at end of file diff --git a/Extras/Serialize/BulletWorldImporter/CMakeLists.txt b/Extras/Serialize/BulletWorldImporter/CMakeLists.txt new file mode 100644 index 0000000..85103a9 --- /dev/null +++ b/Extras/Serialize/BulletWorldImporter/CMakeLists.txt @@ -0,0 +1,38 @@ +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletFileLoader +) + +ADD_LIBRARY( +BulletWorldImporter +btBulletWorldImporter.cpp +btBulletWorldImporter.h +) + +SET_TARGET_PROPERTIES(BulletWorldImporter PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletWorldImporter PROPERTIES SOVERSION ${BULLET_VERSION}) + +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletWorldImporter BulletDynamics BulletCollision BulletFileLoader LinearMath) +ENDIF (BUILD_SHARED_LIBS) + +IF (INSTALL_EXTRA_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + #FILES_MATCHING requires CMake 2.6 + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletWorldImporter DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletWorldImporter DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN +".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletWorldImporter PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletWorldImporter PROPERTIES PUBLIC_HEADER "btBulletWorldImporter.h") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_EXTRA_LIBS) diff --git a/Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.cpp b/Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.cpp new file mode 100644 index 0000000..7e58f3c --- /dev/null +++ b/Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.cpp @@ -0,0 +1,1558 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2010 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 "btBulletWorldImporter.h" +#include "../BulletFileLoader/btBulletFile.h" + +#include "btBulletDynamicsCommon.h" +#include "BulletCollision/Gimpact/btGImpactShape.h" + + + +//#define USE_INTERNAL_EDGE_UTILITY +#ifdef USE_INTERNAL_EDGE_UTILITY +#include "BulletCollision/CollisionDispatch/btInternalEdgeUtility.h" +#endif //USE_INTERNAL_EDGE_UTILITY + +btBulletWorldImporter::btBulletWorldImporter(btDynamicsWorld* world) +:m_dynamicsWorld(world), +m_verboseDumpAllTypes(false) +{ +} + +btBulletWorldImporter::~btBulletWorldImporter() +{ +} + +void btBulletWorldImporter::deleteAllData() +{ + int i; + for (i=0;iremoveConstraint(m_allocatedConstraints[i]); + delete m_allocatedConstraints[i]; + } + m_allocatedConstraints.clear(); + + + for (i=0;iremoveRigidBody(btRigidBody::upcast(m_allocatedRigidBodies[i])); + delete m_allocatedRigidBodies[i]; + } + + m_allocatedRigidBodies.clear(); + + + for (i=0;im_numMeshParts;a++) + { + btMeshPartData* curPart = &curData->m_meshPartsPtr[a]; + if(curPart->m_vertices3f) + delete [] curPart->m_vertices3f; + + if(curPart->m_vertices3d) + delete [] curPart->m_vertices3d; + + if(curPart->m_indices32) + delete [] curPart->m_indices32; + + if(curPart->m_3indices16) + delete [] curPart->m_3indices16; + + if(curPart->m_indices16) + delete [] curPart->m_indices16; + + if (curPart->m_3indices8) + delete [] curPart->m_3indices8; + + } + delete [] curData->m_meshPartsPtr; + delete curData; + } + m_allocatedbtStridingMeshInterfaceDatas.clear(); + + for (i=0;iaddIndexedMesh(meshPart,meshPart.m_indexType); + } + } + + return meshInterface; +} + + +btStridingMeshInterfaceData* btBulletWorldImporter::createStridingMeshInterfaceData(btStridingMeshInterfaceData* interfaceData) +{ + //create a new btStridingMeshInterfaceData that is an exact copy of shapedata and store it in the WorldImporter + btStridingMeshInterfaceData* newData = new btStridingMeshInterfaceData; + + newData->m_scaling = interfaceData->m_scaling; + newData->m_numMeshParts = interfaceData->m_numMeshParts; + newData->m_meshPartsPtr = new btMeshPartData[newData->m_numMeshParts]; + + for(int i = 0;i < newData->m_numMeshParts;i++) + { + btMeshPartData* curPart = &interfaceData->m_meshPartsPtr[i]; + btMeshPartData* curNewPart = &newData->m_meshPartsPtr[i]; + + curNewPart->m_numTriangles = curPart->m_numTriangles; + curNewPart->m_numVertices = curPart->m_numVertices; + + if(curPart->m_vertices3f) + { + curNewPart->m_vertices3f = new btVector3FloatData[curNewPart->m_numVertices]; + memcpy(curNewPart->m_vertices3f,curPart->m_vertices3f,sizeof(btVector3FloatData) * curNewPart->m_numVertices); + } + else + curNewPart->m_vertices3f = NULL; + + if(curPart->m_vertices3d) + { + curNewPart->m_vertices3d = new btVector3DoubleData[curNewPart->m_numVertices]; + memcpy(curNewPart->m_vertices3d,curPart->m_vertices3d,sizeof(btVector3DoubleData) * curNewPart->m_numVertices); + } + else + curNewPart->m_vertices3d = NULL; + + int numIndices = curNewPart->m_numTriangles * 3; + ///the m_3indices8 was not initialized in some Bullet versions, this can cause crashes at loading time + ///we catch it by only dealing with m_3indices8 if none of the other indices are initialized + bool uninitialized3indices8Workaround =false; + + if(curPart->m_indices32) + { + uninitialized3indices8Workaround=true; + curNewPart->m_indices32 = new btIntIndexData[numIndices]; + memcpy(curNewPart->m_indices32,curPart->m_indices32,sizeof(btIntIndexData) * numIndices); + } + else + curNewPart->m_indices32 = NULL; + + if(curPart->m_3indices16) + { + uninitialized3indices8Workaround=true; + curNewPart->m_3indices16 = new btShortIntIndexTripletData[curNewPart->m_numTriangles]; + memcpy(curNewPart->m_3indices16,curPart->m_3indices16,sizeof(btShortIntIndexTripletData) * curNewPart->m_numTriangles); + } + else + curNewPart->m_3indices16 = NULL; + + if(curPart->m_indices16) + { + uninitialized3indices8Workaround=true; + curNewPart->m_indices16 = new btShortIntIndexData[numIndices]; + memcpy(curNewPart->m_indices16,curPart->m_indices16,sizeof(btShortIntIndexData) * numIndices); + } + else + curNewPart->m_indices16 = NULL; + + if(!uninitialized3indices8Workaround && curPart->m_3indices8) + { + curNewPart->m_3indices8 = new btCharIndexTripletData[curNewPart->m_numTriangles]; + memcpy(curNewPart->m_3indices8,curPart->m_3indices8,sizeof(btCharIndexTripletData) * curNewPart->m_numTriangles); + } + else + curNewPart->m_3indices8 = NULL; + + } + + m_allocatedbtStridingMeshInterfaceDatas.push_back(newData); + + return(newData); +} + +#ifdef USE_INTERNAL_EDGE_UTILITY +extern ContactAddedCallback gContactAddedCallback; + +static bool btAdjustInternalEdgeContactsCallback(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1) +{ + + btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1); + //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_BACKFACE_MODE); + //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_DOUBLE_SIDED+BT_TRIANGLE_CONCAVE_DOUBLE_SIDED); + return true; +} +#endif //USE_INTERNAL_EDGE_UTILITY + +btCollisionShape* btBulletWorldImporter::convertCollisionShape( btCollisionShapeData* shapeData ) +{ + btCollisionShape* shape = 0; + + switch (shapeData->m_shapeType) + { + case STATIC_PLANE_PROXYTYPE: + { + btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*)shapeData; + btVector3 planeNormal,localScaling; + planeNormal.deSerializeFloat(planeData->m_planeNormal); + localScaling.deSerializeFloat(planeData->m_localScaling); + shape = createPlaneShape(planeNormal,planeData->m_planeConstant); + shape->setLocalScaling(localScaling); + + break; + } + case SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE: + { + btScaledTriangleMeshShapeData* scaledMesh = (btScaledTriangleMeshShapeData*) shapeData; + btCollisionShapeData* colShapeData = (btCollisionShapeData*) &scaledMesh->m_trimeshShapeData; + colShapeData->m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE; + btCollisionShape* childShape = convertCollisionShape(colShapeData); + btBvhTriangleMeshShape* meshShape = (btBvhTriangleMeshShape*)childShape; + btVector3 localScaling; + localScaling.deSerializeFloat(scaledMesh->m_localScaling); + + shape = createScaledTrangleMeshShape(meshShape, localScaling); + break; + } + case GIMPACT_SHAPE_PROXYTYPE: + { + btGImpactMeshShapeData* gimpactData = (btGImpactMeshShapeData*) shapeData; + if (gimpactData->m_gimpactSubType == CONST_GIMPACT_TRIMESH_SHAPE) + { + btStridingMeshInterfaceData* interfaceData = createStridingMeshInterfaceData(&gimpactData->m_meshInterface); + btTriangleIndexVertexArray* meshInterface = createMeshInterface(*interfaceData); + + + btGImpactMeshShape* gimpactShape = createGimpactShape(meshInterface); + btVector3 localScaling; + localScaling.deSerializeFloat(gimpactData->m_localScaling); + gimpactShape->setLocalScaling(localScaling); + gimpactShape->setMargin(btScalar(gimpactData->m_collisionMargin)); + gimpactShape->updateBound(); + shape = gimpactShape; + } else + { + printf("unsupported gimpact sub type\n"); + } + break; + } + + case CYLINDER_SHAPE_PROXYTYPE: + case CAPSULE_SHAPE_PROXYTYPE: + case BOX_SHAPE_PROXYTYPE: + case SPHERE_SHAPE_PROXYTYPE: + case MULTI_SPHERE_SHAPE_PROXYTYPE: + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + btConvexInternalShapeData* bsd = (btConvexInternalShapeData*)shapeData; + btVector3 implicitShapeDimensions; + implicitShapeDimensions.deSerializeFloat(bsd->m_implicitShapeDimensions); + btVector3 localScaling; + localScaling.deSerializeFloat(bsd->m_localScaling); + btVector3 margin(bsd->m_collisionMargin,bsd->m_collisionMargin,bsd->m_collisionMargin); + switch (shapeData->m_shapeType) + { + case BOX_SHAPE_PROXYTYPE: + { + shape = createBoxShape(implicitShapeDimensions/localScaling+margin); + break; + } + case SPHERE_SHAPE_PROXYTYPE: + { + shape = createSphereShape(implicitShapeDimensions.getX()); + break; + } + case CAPSULE_SHAPE_PROXYTYPE: + { + btCapsuleShapeData* capData = (btCapsuleShapeData*)shapeData; + switch (capData->m_upAxis) + { + case 0: + { + shape = createCapsuleShapeX(implicitShapeDimensions.getY()+bsd->m_collisionMargin*2,2*implicitShapeDimensions.getX()); + break; + } + case 1: + { + shape = createCapsuleShapeY(implicitShapeDimensions.getX()+bsd->m_collisionMargin*2,2*implicitShapeDimensions.getY()); + break; + } + case 2: + { + shape = createCapsuleShapeZ(implicitShapeDimensions.getX()+bsd->m_collisionMargin*2,2*implicitShapeDimensions.getZ()); + break; + } + default: + { + printf("error: wrong up axis for btCapsuleShape\n"); + } + bsd->m_collisionMargin = 0.f; + + }; + + break; + } + case CYLINDER_SHAPE_PROXYTYPE: + { + btCylinderShapeData* cylData = (btCylinderShapeData*) shapeData; + btVector3 halfExtents = implicitShapeDimensions+margin; + switch (cylData->m_upAxis) + { + case 0: + { + shape = createCylinderShapeX(halfExtents.getY(),halfExtents.getX()); + break; + } + case 1: + { + shape = createCylinderShapeY(halfExtents.getX(),halfExtents.getY()); + break; + } + case 2: + { + shape = createCylinderShapeZ(halfExtents.getX(),halfExtents.getZ()); + break; + } + default: + { + printf("unknown Cylinder up axis\n"); + } + + }; + + + + break; + } + case MULTI_SPHERE_SHAPE_PROXYTYPE: + { + btMultiSphereShapeData* mss = (btMultiSphereShapeData*)bsd; + int numSpheres = mss->m_localPositionArraySize; + + btAlignedObjectArray tmpPos; + btAlignedObjectArray radii; + radii.resize(numSpheres); + tmpPos.resize(numSpheres); + int i; + for ( i=0;im_localPositionArrayPtr[i].m_pos); + radii[i] = mss->m_localPositionArrayPtr[i].m_radius; + } + shape = new btMultiSphereShape(&tmpPos[0],&radii[0],numSpheres); + break; + } + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + // int sz = sizeof(btConvexHullShapeData); + // int sz2 = sizeof(btConvexInternalShapeData); + // int sz3 = sizeof(btCollisionShapeData); + btConvexHullShapeData* convexData = (btConvexHullShapeData*)bsd; + int numPoints = convexData->m_numUnscaledPoints; + + btAlignedObjectArray tmpPoints; + tmpPoints.resize(numPoints); + int i; + for ( i=0;im_unscaledPointsDoublePtr) + tmpPoints[i].deSerialize(convexData->m_unscaledPointsDoublePtr[i]); + if (convexData->m_unscaledPointsFloatPtr) + tmpPoints[i].deSerializeFloat(convexData->m_unscaledPointsFloatPtr[i]); +#else + if (convexData->m_unscaledPointsFloatPtr) + tmpPoints[i].deSerialize(convexData->m_unscaledPointsFloatPtr[i]); + if (convexData->m_unscaledPointsDoublePtr) + tmpPoints[i].deSerializeDouble(convexData->m_unscaledPointsDoublePtr[i]); +#endif //BT_USE_DOUBLE_PRECISION + } + btConvexHullShape* hullShape = createConvexHullShape(); + for (i=0;iaddPoint(tmpPoints[i]); + } + shape = hullShape; + break; + } + default: + { + printf("error: cannot create shape type (%d)\n",shapeData->m_shapeType); + } + } + + if (shape) + { + //shape->setMargin(bsd->m_collisionMargin); + btVector3 localScaling; + localScaling.deSerializeFloat(bsd->m_localScaling); + shape->setLocalScaling(localScaling); + + } + break; + } + case TRIANGLE_MESH_SHAPE_PROXYTYPE: + { + btTriangleMeshShapeData* trimesh = (btTriangleMeshShapeData*)shapeData; + btStridingMeshInterfaceData* interfaceData = createStridingMeshInterfaceData(&trimesh->m_meshInterface); + btTriangleIndexVertexArray* meshInterface = createMeshInterface(*interfaceData); + if (!meshInterface->getNumSubParts()) + { + return 0; + } + + btVector3 scaling; scaling.deSerializeFloat(trimesh->m_meshInterface.m_scaling); + meshInterface->setScaling(scaling); + + + btOptimizedBvh* bvh = 0; +#if 0 + if (trimesh->m_quantizedFloatBvh) + { + btOptimizedBvh** bvhPtr = m_bvhMap.find(trimesh->m_quantizedFloatBvh); + if (bvhPtr && *bvhPtr) + { + bvh = *bvhPtr; + } else + { + bvh = createOptimizedBvh(); + bvh->deSerializeFloat(*trimesh->m_quantizedFloatBvh); + } + } + if (trimesh->m_quantizedDoubleBvh) + { + btOptimizedBvh** bvhPtr = m_bvhMap.find(trimesh->m_quantizedDoubleBvh); + if (bvhPtr && *bvhPtr) + { + bvh = *bvhPtr; + } else + { + bvh = createOptimizedBvh(); + bvh->deSerializeDouble(*trimesh->m_quantizedDoubleBvh); + } + } +#endif + + + btBvhTriangleMeshShape* trimeshShape = createBvhTriangleMeshShape(meshInterface,bvh); + trimeshShape->setMargin(trimesh->m_collisionMargin); + shape = trimeshShape; + + if (trimesh->m_triangleInfoMap) + { + btTriangleInfoMap* map = createTriangleInfoMap(); + map->deSerialize(*trimesh->m_triangleInfoMap); + trimeshShape->setTriangleInfoMap(map); + +#ifdef USE_INTERNAL_EDGE_UTILITY + gContactAddedCallback = btAdjustInternalEdgeContactsCallback; +#endif //USE_INTERNAL_EDGE_UTILITY + + } + + //printf("trimesh->m_collisionMargin=%f\n",trimesh->m_collisionMargin); + break; + } + case COMPOUND_SHAPE_PROXYTYPE: + { + btCompoundShapeData* compoundData = (btCompoundShapeData*)shapeData; + btCompoundShape* compoundShape = createCompoundShape(); + + + btAlignedObjectArray childShapes; + for (int i=0;im_numChildShapes;i++) + { + btCollisionShape* childShape = convertCollisionShape(compoundData->m_childShapePtr[i].m_childShape); + if (childShape) + { + btTransform localTransform; + localTransform.deSerializeFloat(compoundData->m_childShapePtr[i].m_transform); + compoundShape->addChildShape(localTransform,childShape); + } else + { +#ifdef _DEBUG + printf("error: couldn't create childShape for compoundShape\n"); +#endif + } + + } + shape = compoundShape; + + break; + } + case SOFTBODY_SHAPE_PROXYTYPE: + { + return 0; + } + default: + { +#ifdef _DEBUG + printf("unsupported shape type (%d)\n",shapeData->m_shapeType); +#endif + } + } + + return shape; + +} + +char* btBulletWorldImporter::duplicateName(const char* name) +{ + if (name) + { + int l = (int)strlen(name); + char* newName = new char[l+1]; + memcpy(newName,name,l); + newName[l] = 0; + m_allocatedNames.push_back(newName); + return newName; + } + return 0; +} + +bool btBulletWorldImporter::loadFileFromMemory( bParse::btBulletFile* bulletFile2) +{ + bool ok = (bulletFile2->getFlags()& bParse::FD_OK)!=0; + + if (ok) + bulletFile2->parse(m_verboseDumpAllTypes); + else + return false; + + if (m_verboseDumpAllTypes) + { + bulletFile2->dumpChunks(bulletFile2->getFileDNA()); + } + + return convertAllObjects(bulletFile2); + +} + +bool btBulletWorldImporter::convertAllObjects( bParse::btBulletFile* bulletFile2) +{ + + m_shapeMap.clear(); + m_bodyMap.clear(); + + int i; + + for (i=0;im_bvhs.size();i++) + { + btOptimizedBvh* bvh = createOptimizedBvh(); + + if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) + { + btQuantizedBvhDoubleData* bvhData = (btQuantizedBvhDoubleData*)bulletFile2->m_bvhs[i]; + bvh->deSerializeDouble(*bvhData); + } else + { + btQuantizedBvhFloatData* bvhData = (btQuantizedBvhFloatData*)bulletFile2->m_bvhs[i]; + bvh->deSerializeFloat(*bvhData); + } + m_bvhMap.insert(bulletFile2->m_bvhs[i],bvh); + } + + + + + + for (i=0;im_collisionShapes.size();i++) + { + btCollisionShapeData* shapeData = (btCollisionShapeData*)bulletFile2->m_collisionShapes[i]; + btCollisionShape* shape = convertCollisionShape(shapeData); + if (shape) + { + // printf("shapeMap.insert(%x,%x)\n",shapeData,shape); + m_shapeMap.insert(shapeData,shape); + } + + if (shape&& shapeData->m_name) + { + char* newname = duplicateName(shapeData->m_name); + m_objectNameMap.insert(shape,newname); + m_nameShapeMap.insert(newname,shape); + } + } + + + + + + + + + for (i=0;im_rigidBodies.size();i++) + { + if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) + { + btRigidBodyDoubleData* colObjData = (btRigidBodyDoubleData*)bulletFile2->m_rigidBodies[i]; + btScalar mass = btScalar(colObjData->m_inverseMass? 1.f/colObjData->m_inverseMass : 0.f); + btVector3 localInertia; + localInertia.setZero(); + btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionObjectData.m_collisionShape); + if (shapePtr && *shapePtr) + { + btTransform startTransform; + startTransform.deSerializeDouble(colObjData->m_collisionObjectData.m_worldTransform); + // startTransform.setBasis(btMatrix3x3::getIdentity()); + btCollisionShape* shape = (btCollisionShape*)*shapePtr; + if (shape->isNonMoving()) + { + mass = 0.f; + } + + if (mass) + { + shape->calculateLocalInertia(mass,localInertia); + } + bool isDynamic = mass!=0.f; + + btRigidBody* body = createRigidBody(isDynamic,mass,startTransform,shape,colObjData->m_collisionObjectData.m_name); +#ifdef USE_INTERNAL_EDGE_UTILITY + if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape; + if (trimesh->getTriangleInfoMap()) + { + body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + } + } +#endif //USE_INTERNAL_EDGE_UTILITY + m_bodyMap.insert(colObjData,body); + } else + { + printf("error: no shape found\n"); + } + + } else + { + btRigidBodyFloatData* colObjData = (btRigidBodyFloatData*)bulletFile2->m_rigidBodies[i]; + btScalar mass = btScalar(colObjData->m_inverseMass? 1.f/colObjData->m_inverseMass : 0.f); + btVector3 localInertia; + localInertia.setZero(); + btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionObjectData.m_collisionShape); + if (shapePtr && *shapePtr) + { + btTransform startTransform; + startTransform.deSerializeFloat(colObjData->m_collisionObjectData.m_worldTransform); + // startTransform.setBasis(btMatrix3x3::getIdentity()); + btCollisionShape* shape = (btCollisionShape*)*shapePtr; + if (shape->isNonMoving()) + { + mass = 0.f; + } + if (mass) + { + shape->calculateLocalInertia(mass,localInertia); + } + bool isDynamic = mass!=0.f; + btRigidBody* body = createRigidBody(isDynamic,mass,startTransform,shape,colObjData->m_collisionObjectData.m_name); + body->setFriction(colObjData->m_collisionObjectData.m_friction); + body->setRestitution(colObjData->m_collisionObjectData.m_restitution); + + +#ifdef USE_INTERNAL_EDGE_UTILITY + if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape; + if (trimesh->getTriangleInfoMap()) + { + body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + } + } +#endif //USE_INTERNAL_EDGE_UTILITY + m_bodyMap.insert(colObjData,body); + } else + { + printf("error: no shape found\n"); + } + } + } + + for (i=0;im_collisionObjects.size();i++) + { + if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) + { + btCollisionObjectDoubleData* colObjData = (btCollisionObjectDoubleData*)bulletFile2->m_collisionObjects[i]; + btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape); + if (shapePtr && *shapePtr) + { + btTransform startTransform; + startTransform.deSerializeDouble(colObjData->m_worldTransform); + btCollisionShape* shape = (btCollisionShape*)*shapePtr; + btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name); + body->setFriction(colObjData->m_friction); + body->setRestitution(colObjData->m_restitution); + +#ifdef USE_INTERNAL_EDGE_UTILITY + if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape; + if (trimesh->getTriangleInfoMap()) + { + body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + } + } +#endif //USE_INTERNAL_EDGE_UTILITY + m_bodyMap.insert(colObjData,body); + } else + { + printf("error: no shape found\n"); + } + + } else + { + btCollisionObjectFloatData* colObjData = (btCollisionObjectFloatData*)bulletFile2->m_collisionObjects[i]; + btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape); + if (shapePtr && *shapePtr) + { + btTransform startTransform; + startTransform.deSerializeFloat(colObjData->m_worldTransform); + btCollisionShape* shape = (btCollisionShape*)*shapePtr; + btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name); + +#ifdef USE_INTERNAL_EDGE_UTILITY + if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape; + if (trimesh->getTriangleInfoMap()) + { + body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + } + } +#endif //USE_INTERNAL_EDGE_UTILITY + m_bodyMap.insert(colObjData,body); + } else + { + printf("error: no shape found\n"); + } + } + + } + + + for (i=0;im_constraints.size();i++) + { + btTypedConstraintData* constraintData = (btTypedConstraintData*)bulletFile2->m_constraints[i]; + btCollisionObject** colAptr = m_bodyMap.find(constraintData->m_rbA); + btCollisionObject** colBptr = m_bodyMap.find(constraintData->m_rbB); + + btRigidBody* rbA = 0; + btRigidBody* rbB = 0; + + if (colAptr) + { + rbA = btRigidBody::upcast(*colAptr); + if (!rbA) + rbA = &getFixedBody(); + } + if (colBptr) + { + rbB = btRigidBody::upcast(*colBptr); + if (!rbB) + rbB = &getFixedBody(); + } + if (!rbA && !rbB) + continue; + + btTypedConstraint* constraint = 0; + + switch (constraintData->m_objectType) + { + case POINT2POINT_CONSTRAINT_TYPE: + { + if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) + { + btPoint2PointConstraintDoubleData* p2pData = (btPoint2PointConstraintDoubleData*)constraintData; + if (rbA && rbB) + { + btVector3 pivotInA,pivotInB; + pivotInA.deSerializeDouble(p2pData->m_pivotInA); + pivotInB.deSerializeDouble(p2pData->m_pivotInB); + constraint = createPoint2PointConstraint(*rbA,*rbB,pivotInA,pivotInB); + } else + { + btVector3 pivotInA; + pivotInA.deSerializeDouble(p2pData->m_pivotInA); + constraint = createPoint2PointConstraint(*rbA,pivotInA); + } + } else + { + btPoint2PointConstraintFloatData* p2pData = (btPoint2PointConstraintFloatData*)constraintData; + if (rbA&& rbB) + { + btVector3 pivotInA,pivotInB; + pivotInA.deSerializeFloat(p2pData->m_pivotInA); + pivotInB.deSerializeFloat(p2pData->m_pivotInB); + constraint = createPoint2PointConstraint(*rbA,*rbB,pivotInA,pivotInB); + + } else + { + btVector3 pivotInA; + pivotInA.deSerializeFloat(p2pData->m_pivotInA); + constraint = createPoint2PointConstraint(*rbA,pivotInA); + } + + } + + break; + } + case HINGE_CONSTRAINT_TYPE: + { + btHingeConstraint* hinge = 0; + + if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) + { + btHingeConstraintDoubleData* hingeData = (btHingeConstraintDoubleData*)constraintData; + if (rbA&& rbB) + { + btTransform rbAFrame,rbBFrame; + rbAFrame.deSerializeDouble(hingeData->m_rbAFrame); + rbBFrame.deSerializeDouble(hingeData->m_rbBFrame); + hinge = createHingeConstraint(*rbA,*rbB,rbAFrame,rbBFrame,hingeData->m_useReferenceFrameA!=0); + } else + { + btTransform rbAFrame; + rbAFrame.deSerializeDouble(hingeData->m_rbAFrame); + hinge = createHingeConstraint(*rbA,rbAFrame,hingeData->m_useReferenceFrameA!=0); + } + if (hingeData->m_enableAngularMotor) + { + hinge->enableAngularMotor(true,hingeData->m_motorTargetVelocity,hingeData->m_maxMotorImpulse); + } + hinge->setAngularOnly(hingeData->m_angularOnly!=0); + hinge->setLimit(btScalar(hingeData->m_lowerLimit),btScalar(hingeData->m_upperLimit),btScalar(hingeData->m_limitSoftness),btScalar(hingeData->m_biasFactor),btScalar(hingeData->m_relaxationFactor)); + } else + { + btHingeConstraintFloatData* hingeData = (btHingeConstraintFloatData*)constraintData; + if (rbA&& rbB) + { + btTransform rbAFrame,rbBFrame; + rbAFrame.deSerializeFloat(hingeData->m_rbAFrame); + rbBFrame.deSerializeFloat(hingeData->m_rbBFrame); + hinge = createHingeConstraint(*rbA,*rbB,rbAFrame,rbBFrame,hingeData->m_useReferenceFrameA!=0); + } else + { + btTransform rbAFrame; + rbAFrame.deSerializeFloat(hingeData->m_rbAFrame); + hinge = createHingeConstraint(*rbA,rbAFrame,hingeData->m_useReferenceFrameA!=0); + } + if (hingeData->m_enableAngularMotor) + { + hinge->enableAngularMotor(true,hingeData->m_motorTargetVelocity,hingeData->m_maxMotorImpulse); + } + hinge->setAngularOnly(hingeData->m_angularOnly!=0); + hinge->setLimit(btScalar(hingeData->m_lowerLimit),btScalar(hingeData->m_upperLimit),btScalar(hingeData->m_limitSoftness),btScalar(hingeData->m_biasFactor),btScalar(hingeData->m_relaxationFactor)); + } + + constraint = hinge; + break; + + } + case CONETWIST_CONSTRAINT_TYPE: + { + btConeTwistConstraintData* coneData = (btConeTwistConstraintData*)constraintData; + btConeTwistConstraint* coneTwist = 0; + + if (rbA&& rbB) + { + btTransform rbAFrame,rbBFrame; + rbAFrame.deSerializeFloat(coneData->m_rbAFrame); + rbBFrame.deSerializeFloat(coneData->m_rbBFrame); + coneTwist = createConeTwistConstraint(*rbA,*rbB,rbAFrame,rbBFrame); + } else + { + btTransform rbAFrame; + rbAFrame.deSerializeFloat(coneData->m_rbAFrame); + coneTwist = createConeTwistConstraint(*rbA,rbAFrame); + } + coneTwist->setLimit(coneData->m_swingSpan1,coneData->m_swingSpan2,coneData->m_twistSpan,coneData->m_limitSoftness,coneData->m_biasFactor,coneData->m_relaxationFactor); + coneTwist->setDamping(coneData->m_damping); + + constraint = coneTwist; + break; + } + + case D6_SPRING_CONSTRAINT_TYPE: + { + btGeneric6DofSpringConstraintData* dofData = (btGeneric6DofSpringConstraintData*)constraintData; + btGeneric6DofSpringConstraint* dof = 0; + + if (rbA && rbB) + { + btTransform rbAFrame,rbBFrame; + rbAFrame.deSerializeFloat(dofData->m_6dofData.m_rbAFrame); + rbBFrame.deSerializeFloat(dofData->m_6dofData.m_rbBFrame); + dof = createGeneric6DofSpringConstraint(*rbA,*rbB,rbAFrame,rbBFrame,dofData->m_6dofData.m_useLinearReferenceFrameA!=0); + } else + { + printf("Error in btWorldImporter::createGeneric6DofSpringConstraint: requires rbA && rbB\n"); + } + + if (dof) + { + btVector3 angLowerLimit,angUpperLimit, linLowerLimit,linUpperlimit; + angLowerLimit.deSerializeFloat(dofData->m_6dofData.m_angularLowerLimit); + angUpperLimit.deSerializeFloat(dofData->m_6dofData.m_angularUpperLimit); + linLowerLimit.deSerializeFloat(dofData->m_6dofData.m_linearLowerLimit); + linUpperlimit.deSerializeFloat(dofData->m_6dofData.m_linearUpperLimit); + + dof->setAngularLowerLimit(angLowerLimit); + dof->setAngularUpperLimit(angUpperLimit); + dof->setLinearLowerLimit(linLowerLimit); + dof->setLinearUpperLimit(linUpperlimit); + + int i; + for (i=0;i<6;i++) + { + dof->setStiffness(i,dofData->m_springStiffness[i]); + dof->setEquilibriumPoint(i,dofData->m_equilibriumPoint[i]); + dof->enableSpring(i,dofData->m_springEnabled[i]!=0); + dof->setDamping(i,dofData->m_springDamping[i]); + } + } + + constraint = dof; + break; + } + case D6_CONSTRAINT_TYPE: + { + btGeneric6DofConstraintData* dofData = (btGeneric6DofConstraintData*)constraintData; + btGeneric6DofConstraint* dof = 0; + + if (rbA&& rbB) + { + btTransform rbAFrame,rbBFrame; + rbAFrame.deSerializeFloat(dofData->m_rbAFrame); + rbBFrame.deSerializeFloat(dofData->m_rbBFrame); + dof = createGeneric6DofConstraint(*rbA,*rbB,rbAFrame,rbBFrame,dofData->m_useLinearReferenceFrameA!=0); + } else + { + if (rbB) + { + btTransform rbBFrame; + rbBFrame.deSerializeFloat(dofData->m_rbBFrame); + dof = createGeneric6DofConstraint(*rbB,rbBFrame,dofData->m_useLinearReferenceFrameA!=0); + } else + { + printf("Error in btWorldImporter::createGeneric6DofConstraint: missing rbB\n"); + } + } + + if (dof) + { + btVector3 angLowerLimit,angUpperLimit, linLowerLimit,linUpperlimit; + angLowerLimit.deSerializeFloat(dofData->m_angularLowerLimit); + angUpperLimit.deSerializeFloat(dofData->m_angularUpperLimit); + linLowerLimit.deSerializeFloat(dofData->m_linearLowerLimit); + linUpperlimit.deSerializeFloat(dofData->m_linearUpperLimit); + + dof->setAngularLowerLimit(angLowerLimit); + dof->setAngularUpperLimit(angUpperLimit); + dof->setLinearLowerLimit(linLowerLimit); + dof->setLinearUpperLimit(linUpperlimit); + } + + constraint = dof; + break; + } + case SLIDER_CONSTRAINT_TYPE: + { + btSliderConstraintData* sliderData = (btSliderConstraintData*)constraintData; + btSliderConstraint* slider = 0; + if (rbA&& rbB) + { + btTransform rbAFrame,rbBFrame; + rbAFrame.deSerializeFloat(sliderData->m_rbAFrame); + rbBFrame.deSerializeFloat(sliderData->m_rbBFrame); + slider = createSliderConstraint(*rbA,*rbB,rbAFrame,rbBFrame,sliderData->m_useLinearReferenceFrameA!=0); + } else + { + btTransform rbBFrame; + rbBFrame.deSerializeFloat(sliderData->m_rbBFrame); + slider = createSliderConstraint(*rbB,rbBFrame,sliderData->m_useLinearReferenceFrameA!=0); + } + slider->setLowerLinLimit(sliderData->m_linearLowerLimit); + slider->setUpperLinLimit(sliderData->m_linearUpperLimit); + slider->setLowerAngLimit(sliderData->m_angularLowerLimit); + slider->setUpperAngLimit(sliderData->m_angularUpperLimit); + slider->setUseFrameOffset(sliderData->m_useOffsetForConstraintFrame!=0); + constraint = slider; + break; + } + + default: + { + printf("unknown constraint type\n"); + } + }; + + if (constraint) + { + constraint->setDbgDrawSize(constraintData->m_dbgDrawSize); + ///those fields didn't exist and set to zero for pre-280 versions, so do a check here + if (bulletFile2->getVersion()>=280) + { + constraint->setBreakingImpulseThreshold(constraintData->m_breakingImpulseThreshold); + constraint->setEnabled(constraintData->m_isEnabled!=0); + constraint->setOverrideNumSolverIterations(constraintData->m_overrideNumSolverIterations); + } + + if (constraintData->m_name) + { + char* newname = duplicateName(constraintData->m_name); + m_nameConstraintMap.insert(newname,constraint); + m_objectNameMap.insert(constraint,newname); + } + if(m_dynamicsWorld) + m_dynamicsWorld->addConstraint(constraint,constraintData->m_disableCollisionsBetweenLinkedBodies!=0); + } + + } + + return true; +} + + + +btCollisionObject* btBulletWorldImporter::createCollisionObject(const btTransform& startTransform,btCollisionShape* shape, const char* bodyName) +{ + return createRigidBody(false,0,startTransform,shape,bodyName); +} + + + +btRigidBody* btBulletWorldImporter::createRigidBody(bool isDynamic, btScalar mass, const btTransform& startTransform,btCollisionShape* shape,const char* bodyName) +{ + btVector3 localInertia; + localInertia.setZero(); + + if (mass) + shape->calculateLocalInertia(mass,localInertia); + + btRigidBody* body = new btRigidBody(mass,0,shape,localInertia); + body->setWorldTransform(startTransform); + + if (m_dynamicsWorld) + m_dynamicsWorld->addRigidBody(body); + + if (bodyName) + { + char* newname = duplicateName(bodyName); + m_objectNameMap.insert(body,newname); + m_nameBodyMap.insert(newname,body); + } + m_allocatedRigidBodies.push_back(body); + return body; + +} + +btCollisionShape* btBulletWorldImporter::createPlaneShape(const btVector3& planeNormal,btScalar planeConstant) +{ + btStaticPlaneShape* shape = new btStaticPlaneShape(planeNormal,planeConstant); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} +btCollisionShape* btBulletWorldImporter::createBoxShape(const btVector3& halfExtents) +{ + btBoxShape* shape = new btBoxShape(halfExtents); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} +btCollisionShape* btBulletWorldImporter::createSphereShape(btScalar radius) +{ + btSphereShape* shape = new btSphereShape(radius); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + + +btCollisionShape* btBulletWorldImporter::createCapsuleShapeX(btScalar radius, btScalar height) +{ + btCapsuleShapeX* shape = new btCapsuleShapeX(radius,height); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btCollisionShape* btBulletWorldImporter::createCapsuleShapeY(btScalar radius, btScalar height) +{ + btCapsuleShape* shape = new btCapsuleShape(radius,height); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btCollisionShape* btBulletWorldImporter::createCapsuleShapeZ(btScalar radius, btScalar height) +{ + btCapsuleShapeZ* shape = new btCapsuleShapeZ(radius,height); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btCollisionShape* btBulletWorldImporter::createCylinderShapeX(btScalar radius,btScalar height) +{ + btCylinderShapeX* shape = new btCylinderShapeX(btVector3(height,radius,radius)); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btCollisionShape* btBulletWorldImporter::createCylinderShapeY(btScalar radius,btScalar height) +{ + btCylinderShape* shape = new btCylinderShape(btVector3(radius,height,radius)); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btCollisionShape* btBulletWorldImporter::createCylinderShapeZ(btScalar radius,btScalar height) +{ + btCylinderShapeZ* shape = new btCylinderShapeZ(btVector3(radius,radius,height)); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btTriangleIndexVertexArray* btBulletWorldImporter::createTriangleMeshContainer() +{ + btTriangleIndexVertexArray* in = new btTriangleIndexVertexArray(); + m_allocatedTriangleIndexArrays.push_back(in); + return in; +} + +btOptimizedBvh* btBulletWorldImporter::createOptimizedBvh() +{ + btOptimizedBvh* bvh = new btOptimizedBvh(); + m_allocatedBvhs.push_back(bvh); + return bvh; +} + + +btTriangleInfoMap* btBulletWorldImporter::createTriangleInfoMap() +{ + btTriangleInfoMap* tim = new btTriangleInfoMap(); + m_allocatedTriangleInfoMaps.push_back(tim); + return tim; +} + +btBvhTriangleMeshShape* btBulletWorldImporter::createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh) +{ + if (bvh) + { + btBvhTriangleMeshShape* bvhTriMesh = new btBvhTriangleMeshShape(trimesh,bvh->isQuantized(), false); + bvhTriMesh->setOptimizedBvh(bvh); + m_allocatedCollisionShapes.push_back(bvhTriMesh); + return bvhTriMesh; + } + + btBvhTriangleMeshShape* ts = new btBvhTriangleMeshShape(trimesh,true); + m_allocatedCollisionShapes.push_back(ts); + return ts; + +} +btCollisionShape* btBulletWorldImporter::createConvexTriangleMeshShape(btStridingMeshInterface* trimesh) +{ + return 0; +} +btGImpactMeshShape* btBulletWorldImporter::createGimpactShape(btStridingMeshInterface* trimesh) +{ + btGImpactMeshShape* shape = new btGImpactMeshShape(trimesh); + m_allocatedCollisionShapes.push_back(shape); + return shape; + +} +btConvexHullShape* btBulletWorldImporter::createConvexHullShape() +{ + btConvexHullShape* shape = new btConvexHullShape(); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btCompoundShape* btBulletWorldImporter::createCompoundShape() +{ + btCompoundShape* shape = new btCompoundShape(); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + + +btScaledBvhTriangleMeshShape* btBulletWorldImporter::createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape,const btVector3& localScaling) +{ + btScaledBvhTriangleMeshShape* shape = new btScaledBvhTriangleMeshShape(meshShape,localScaling); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + + +btRigidBody& btBulletWorldImporter::getFixedBody() +{ + static btRigidBody s_fixed(0, 0,0); + s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); + return s_fixed; +} + +btPoint2PointConstraint* btBulletWorldImporter::createPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB) +{ + btPoint2PointConstraint* p2p = new btPoint2PointConstraint(rbA,rbB,pivotInA,pivotInB); + m_allocatedConstraints.push_back(p2p); + return p2p; +} + +btPoint2PointConstraint* btBulletWorldImporter::createPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA) +{ + btPoint2PointConstraint* p2p = new btPoint2PointConstraint(rbA,pivotInA); + m_allocatedConstraints.push_back(p2p); + return p2p; +} + + +btHingeConstraint* btBulletWorldImporter::createHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA) +{ + btHingeConstraint* hinge = new btHingeConstraint(rbA,rbB,rbAFrame,rbBFrame,useReferenceFrameA); + m_allocatedConstraints.push_back(hinge); + return hinge; +} + +btHingeConstraint* btBulletWorldImporter::createHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA) +{ + btHingeConstraint* hinge = new btHingeConstraint(rbA,rbAFrame,useReferenceFrameA); + m_allocatedConstraints.push_back(hinge); + return hinge; +} + +btConeTwistConstraint* btBulletWorldImporter::createConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,const btTransform& rbAFrame, const btTransform& rbBFrame) +{ + btConeTwistConstraint* cone = new btConeTwistConstraint(rbA,rbB,rbAFrame,rbBFrame); + m_allocatedConstraints.push_back(cone); + return cone; +} + +btConeTwistConstraint* btBulletWorldImporter::createConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame) +{ + btConeTwistConstraint* cone = new btConeTwistConstraint(rbA,rbAFrame); + m_allocatedConstraints.push_back(cone); + return cone; +} + + +btGeneric6DofConstraint* btBulletWorldImporter::createGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA) +{ + btGeneric6DofConstraint* dof = new btGeneric6DofConstraint(rbA,rbB,frameInA,frameInB,useLinearReferenceFrameA); + m_allocatedConstraints.push_back(dof); + return dof; +} + +btGeneric6DofConstraint* btBulletWorldImporter::createGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB) +{ + btGeneric6DofConstraint* dof = new btGeneric6DofConstraint(rbB,frameInB,useLinearReferenceFrameB); + m_allocatedConstraints.push_back(dof); + return dof; +} + +btGeneric6DofSpringConstraint* btBulletWorldImporter::createGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA) +{ + btGeneric6DofSpringConstraint* dof = new btGeneric6DofSpringConstraint(rbA,rbB,frameInA,frameInB,useLinearReferenceFrameA); + m_allocatedConstraints.push_back(dof); + return dof; +} + + +btSliderConstraint* btBulletWorldImporter::createSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA) +{ + btSliderConstraint* slider = new btSliderConstraint(rbA,rbB,frameInA,frameInB,useLinearReferenceFrameA); + m_allocatedConstraints.push_back(slider); + return slider; +} + +btSliderConstraint* btBulletWorldImporter::createSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA) +{ + btSliderConstraint* slider = new btSliderConstraint(rbB,frameInB,useLinearReferenceFrameA); + m_allocatedConstraints.push_back(slider); + return slider; +} + + + // query for data +int btBulletWorldImporter::getNumCollisionShapes() const +{ + return m_allocatedCollisionShapes.size(); +} + +btCollisionShape* btBulletWorldImporter::getCollisionShapeByIndex(int index) +{ + return m_allocatedCollisionShapes[index]; +} + +btCollisionShape* btBulletWorldImporter::getCollisionShapeByName(const char* name) +{ + btCollisionShape** shapePtr = m_nameShapeMap.find(name); + if (shapePtr&& *shapePtr) + { + return *shapePtr; + } + return 0; +} + +btRigidBody* btBulletWorldImporter::getRigidBodyByName(const char* name) +{ + btRigidBody** bodyPtr = m_nameBodyMap.find(name); + if (bodyPtr && *bodyPtr) + { + return *bodyPtr; + } + return 0; +} + +btTypedConstraint* btBulletWorldImporter::getConstraintByName(const char* name) +{ + btTypedConstraint** constraintPtr = m_nameConstraintMap.find(name); + if (constraintPtr && *constraintPtr) + { + return *constraintPtr; + } + return 0; +} + +const char* btBulletWorldImporter::getNameForPointer(const void* ptr) const +{ + const char*const * namePtr = m_objectNameMap.find(ptr); + if (namePtr && *namePtr) + return *namePtr; + return 0; +} + + +int btBulletWorldImporter::getNumRigidBodies() const +{ + return m_allocatedRigidBodies.size(); +} + +btCollisionObject* btBulletWorldImporter::getRigidBodyByIndex(int index) const +{ + return m_allocatedRigidBodies[index]; +} +int btBulletWorldImporter::getNumConstraints() const +{ + return m_allocatedConstraints.size(); +} + +btTypedConstraint* btBulletWorldImporter::getConstraintByIndex(int index) const +{ + return m_allocatedConstraints[index]; +} + +int btBulletWorldImporter::getNumBvhs() const +{ + return m_allocatedBvhs.size(); +} + btOptimizedBvh* btBulletWorldImporter::getBvhByIndex(int index) const +{ + return m_allocatedBvhs[index]; +} + +int btBulletWorldImporter::getNumTriangleInfoMaps() const +{ + return m_allocatedTriangleInfoMaps.size(); +} + +btTriangleInfoMap* btBulletWorldImporter::getTriangleInfoMapByIndex(int index) const +{ + return m_allocatedTriangleInfoMaps[index]; +} + diff --git a/Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.h b/Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.h new file mode 100644 index 0000000..05c3ccb --- /dev/null +++ b/Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.h @@ -0,0 +1,208 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2010 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 BULLET_WORLD_IMPORTER_H +#define BULLET_WORLD_IMPORTER_H + +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btHashMap.h" + + +class btBulletFile; +class btCollisionShape; +class btCollisionObject; +class btRigidBody; +class btTypedConstraint; +class btDynamicsWorld; +struct ConstraintInput; +class btRigidBodyColladaInfo; +struct btCollisionShapeData; +class btTriangleIndexVertexArray; +class btStridingMeshInterface; +struct btStridingMeshInterfaceData; +class btGImpactMeshShape; +class btOptimizedBvh; +struct btTriangleInfoMap; +class btBvhTriangleMeshShape; +class btPoint2PointConstraint; +class btHingeConstraint; +class btConeTwistConstraint; +class btGeneric6DofConstraint; +class btGeneric6DofSpringConstraint; +class btSliderConstraint; + + + +namespace bParse +{ + class btBulletFile; + +}; + + + +///The btBulletWorldImporter is a starting point to import .bullet files. +///note that not all data is converted yet. You are expected to override or modify this class. +///See Bullet/Demos/SerializeDemo for a derived class that extract btSoftBody objects too. +class btBulletWorldImporter +{ +protected: + + btDynamicsWorld* m_dynamicsWorld; + + bool m_verboseDumpAllTypes; + + btCollisionShape* convertCollisionShape( btCollisionShapeData* shapeData ); + + btAlignedObjectArray m_allocatedCollisionShapes; + btAlignedObjectArray m_allocatedRigidBodies; + btAlignedObjectArray m_allocatedConstraints; + btAlignedObjectArray m_allocatedBvhs; + btAlignedObjectArray m_allocatedTriangleInfoMaps; + btAlignedObjectArray m_allocatedTriangleIndexArrays; + btAlignedObjectArray m_allocatedbtStridingMeshInterfaceDatas; + + btAlignedObjectArray m_allocatedNames; + + btAlignedObjectArray m_indexArrays; + btAlignedObjectArray m_shortIndexArrays; + btAlignedObjectArray m_charIndexArrays; + + btAlignedObjectArray m_floatVertexArrays; + btAlignedObjectArray m_doubleVertexArrays; + + + btHashMap m_bvhMap; + btHashMap m_timMap; + + btHashMap m_nameShapeMap; + btHashMap m_nameBodyMap; + btHashMap m_nameConstraintMap; + btHashMap m_objectNameMap; + + btHashMap m_shapeMap; + btHashMap m_bodyMap; + + + //methods + + + + static btRigidBody& getFixedBody(); + + char* duplicateName(const char* name); + +public: + + btBulletWorldImporter(btDynamicsWorld* world=0); + + virtual ~btBulletWorldImporter(); + + ///delete all memory collision shapes, rigid bodies, constraints etc. allocated during the load. + ///make sure you don't use the dynamics world containing objects after you call this method + virtual void deleteAllData(); + + bool loadFile(const char* fileName); + + ///the memoryBuffer might be modified (for example if endian swaps are necessary) + bool loadFileFromMemory(char *memoryBuffer, int len); + + bool loadFileFromMemory(bParse::btBulletFile* file); + + //call make sure bulletFile2 has been parsed, either using btBulletFile::parse or btBulletWorldImporter::loadFileFromMemory + virtual bool convertAllObjects(bParse::btBulletFile* file); + + void setVerboseMode(bool verboseDumpAllTypes) + { + m_verboseDumpAllTypes = verboseDumpAllTypes; + } + + bool getVerboseMode() const + { + return m_verboseDumpAllTypes; + } + + // query for data + int getNumCollisionShapes() const; + btCollisionShape* getCollisionShapeByIndex(int index); + int getNumRigidBodies() const; + btCollisionObject* getRigidBodyByIndex(int index) const; + int getNumConstraints() const; + btTypedConstraint* getConstraintByIndex(int index) const; + int getNumBvhs() const; + btOptimizedBvh* getBvhByIndex(int index) const; + int getNumTriangleInfoMaps() const; + btTriangleInfoMap* getTriangleInfoMapByIndex(int index) const; + + // queris involving named objects + btCollisionShape* getCollisionShapeByName(const char* name); + btRigidBody* getRigidBodyByName(const char* name); + btTypedConstraint* getConstraintByName(const char* name); + const char* getNameForPointer(const void* ptr) const; + + ///those virtuals are called by load and can be overridden by the user + + //bodies + virtual btRigidBody* createRigidBody(bool isDynamic, btScalar mass, const btTransform& startTransform, btCollisionShape* shape,const char* bodyName); + virtual btCollisionObject* createCollisionObject( const btTransform& startTransform, btCollisionShape* shape,const char* bodyName); + + ///shapes + + virtual btCollisionShape* createPlaneShape(const btVector3& planeNormal,btScalar planeConstant); + virtual btCollisionShape* createBoxShape(const btVector3& halfExtents); + virtual btCollisionShape* createSphereShape(btScalar radius); + virtual btCollisionShape* createCapsuleShapeX(btScalar radius, btScalar height); + virtual btCollisionShape* createCapsuleShapeY(btScalar radius, btScalar height); + virtual btCollisionShape* createCapsuleShapeZ(btScalar radius, btScalar height); + + virtual btCollisionShape* createCylinderShapeX(btScalar radius,btScalar height); + virtual btCollisionShape* createCylinderShapeY(btScalar radius,btScalar height); + virtual btCollisionShape* createCylinderShapeZ(btScalar radius,btScalar height); + virtual class btTriangleIndexVertexArray* createTriangleMeshContainer(); + virtual btBvhTriangleMeshShape* createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh); + virtual btCollisionShape* createConvexTriangleMeshShape(btStridingMeshInterface* trimesh); + virtual btGImpactMeshShape* createGimpactShape(btStridingMeshInterface* trimesh); + virtual btStridingMeshInterfaceData* createStridingMeshInterfaceData(btStridingMeshInterfaceData* interfaceData); + + virtual class btConvexHullShape* createConvexHullShape(); + virtual class btCompoundShape* createCompoundShape(); + virtual class btScaledBvhTriangleMeshShape* createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape,const btVector3& localScalingbtBvhTriangleMeshShape); + + virtual btTriangleIndexVertexArray* createMeshInterface(btStridingMeshInterfaceData& meshData); + + ///acceleration and connectivity structures + virtual btOptimizedBvh* createOptimizedBvh(); + virtual btTriangleInfoMap* createTriangleInfoMap(); + + ///constraints + virtual btPoint2PointConstraint* createPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB); + virtual btPoint2PointConstraint* createPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA); + virtual btHingeConstraint* createHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA=false); + virtual btHingeConstraint* createHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA=false); + virtual btConeTwistConstraint* createConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,const btTransform& rbAFrame, const btTransform& rbBFrame); + virtual btConeTwistConstraint* createConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame); + virtual btGeneric6DofConstraint* createGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); + virtual btGeneric6DofConstraint* createGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB); + virtual btGeneric6DofSpringConstraint* createGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); + virtual btSliderConstraint* createSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); + virtual btSliderConstraint* createSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA); + +}; + +#endif //BULLET_WORLD_IMPORTER_H + diff --git a/Extras/Serialize/BulletWorldImporter/premake4.lua b/Extras/Serialize/BulletWorldImporter/premake4.lua new file mode 100644 index 0000000..170bc65 --- /dev/null +++ b/Extras/Serialize/BulletWorldImporter/premake4.lua @@ -0,0 +1,13 @@ + project "BulletWorldImporter" + + kind "StaticLib" + targetdir "../../lib" + includedirs { + "../BulletFileLoader", + "../../../src" + } + + files { + "**.cpp", + "**.h" + } \ No newline at end of file diff --git a/Extras/Serialize/CMakeLists.txt b/Extras/Serialize/CMakeLists.txt new file mode 100644 index 0000000..23a544c --- /dev/null +++ b/Extras/Serialize/CMakeLists.txt @@ -0,0 +1,20 @@ + +IF (BUILD_BLEND_DEMO OR INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) + SUBDIRS(BlenderSerialize ) +ENDIF() + + +IF(INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) + +# makesdna and HeaderGenerator are for advanced use only +# makesdna can re-generate the binary DNA representing the Bullet serialization structures +# Be very careful modifying any of this, otherwise the .bullet format becomes incompatible + + SUBDIRS ( BulletFileLoader BulletWorldImporter HeaderGenerator makesdna) + +ELSE(INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) + + SUBDIRS ( BulletFileLoader BulletWorldImporter ) + +ENDIF (INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) + diff --git a/Extras/Serialize/HeaderGenerator/CMakeLists.txt b/Extras/Serialize/HeaderGenerator/CMakeLists.txt new file mode 100644 index 0000000..ee975cc --- /dev/null +++ b/Extras/Serialize/HeaderGenerator/CMakeLists.txt @@ -0,0 +1,32 @@ +############################################################################### +PROJECT(GEN) +FILE(GLOB cpp_SRC "*.cpp") +FILE(GLOB h_SRC "*.h") + + +SET(includes + . + ${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletFileLoader + ${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BlenderSerialize + ${BULLET_PHYSICS_SOURCE_DIR}/src +) + + +LINK_LIBRARIES( + BulletFileLoader BlenderSerialize LinearMath +) + +INCLUDE_DIRECTORIES(${includes}) + +SET(Main_LIBS LinearMath) + +ADD_EXECUTABLE(HeaderGenerator ${cpp_SRC} ${h_SRC}) + +IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + ADD_CUSTOM_COMMAND( + TARGET HeaderGenerator + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/HeaderGenerator/createDnaString.bat ${CMAKE_CURRENT_BINARY_DIR}/createDnaString.bat + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/HeaderGenerator/bulletGenerate.py ${CMAKE_CURRENT_BINARY_DIR}/bulletGenerate.py + ) +ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) diff --git a/Extras/Serialize/HeaderGenerator/apiGen.cpp b/Extras/Serialize/HeaderGenerator/apiGen.cpp new file mode 100644 index 0000000..7b7b085 --- /dev/null +++ b/Extras/Serialize/HeaderGenerator/apiGen.cpp @@ -0,0 +1,464 @@ +/* Copyright (C) 2006 Charlie C +* +* 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 +#include "bDNA.h" +#include "bBlenderFile.h" +#include "btBulletFile.h" +#include "bCommon.h" +#include +#include +#include + +bool isBulletFile = false; + +using namespace bParse; +typedef std::string bString; + +/////////////////////////////////////////////////////////////////////////////// +typedef std::map bStringMap; +typedef std::vector bVariableList; +typedef std::vector bStringList; + + +/////////////////////////////////////////////////////////////////////////////// +static FILE *dump = 0; +static bDNA *mDNA =0; +static bStringMap mStructs; + + +/////////////////////////////////////////////////////////////////////////////// +class bVariable +{ +public: + bVariable(); + ~bVariable(); + + + bString dataType; + bString variableName; + + + bString functionName; + bString classCtor; + + bString memberVariable; + bString memberDataType; + bString functionArgs; + + + void initialize(bString dataType, bString variable, bStringMap refDataTable); + + bool isPtr; + bool isFunctionPtr; + bool isPtrToPtr; + bool isArray; + bool isCharArray; + bool isListBase; + bool isPadding; + bool isCommentedOut; + bool isGeneratedType; + bool isbString; +}; + +/////////////////////////////////////////////////////////////////////////////// +bool dataTypeStandard(bString dataType) +{ + if (dataType == "char") + return true; + if (dataType == "short") + return true; + if (dataType == "int") + return true; + if (dataType == "long") + return true; + if (dataType == "float") + return true; + if (dataType == "double") + return true; + if (dataType == "void") + return true; + if (dataType == "btScalar") + return true; + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +void writeTemplate(short *structData) +{ + bString type = mDNA->getType(structData[0]); + bString className=type; + bString prefix = isBulletFile? "bullet_" : "blender_"; + + int thisLen = structData[1]; + structData+=2; + + bString fileName = prefix+type; + + bVariableList dataTypes; + bStringMap includeFiles; + + + for (int dataVal =0; dataValgetType(structData[0]); + bString dataName = mDNA->getName(structData[1]); + { + bString newDataType = ""; + bString newDataName = ""; + + bStringMap::iterator addB = mStructs.find(dataType); + if (addB != mStructs.end()) + { + newDataType = addB->second; + newDataName = dataName; + } + + else + { + if (dataTypeStandard(dataType)) + { + newDataType = dataType; + newDataName = dataName; + } + else + { + // Unresolved + // set it to an empty struct + // if it's not a ptr generate an error + newDataType = "bInvalidHandle"; + newDataName = dataName; + + if (dataName[0] != '*') + { + } + + } + } + + if (!newDataType.empty() && !newDataName.empty()) + { + bVariable var = bVariable(); + var.initialize(newDataType, newDataName, mStructs); + dataTypes.push_back(var); + } + } + + + bStringMap::iterator include = mStructs.find(dataType); + if (include != mStructs.end()) + { + if (dataName[0] != '*') + { + if (includeFiles.find(dataType)== includeFiles.end()) + { + includeFiles[dataType]=prefix+dataType; + } + } + } + } + + + fprintf(dump, "###############################################################\n"); + fprintf(dump, "%s = bStructClass()\n", fileName.c_str()); + fprintf(dump, "%s.name = '%s'\n", fileName.c_str(), className.c_str()); + fprintf(dump, "%s.filename = '%s'\n", fileName.c_str(), fileName.c_str()); + + bVariableList::iterator vars = dataTypes.begin(); + while (vars!= dataTypes.end()) + { + fprintf(dump, "%s.dataTypes.append('%s %s')\n", fileName.c_str(), vars->dataType.c_str(), vars->variableName.c_str()); + vars++; + } + + bStringMap::iterator inc = includeFiles.begin(); + while (inc != includeFiles.end()) + { + fprintf(dump, "%s.includes.append('%s.h')\n", fileName.c_str(), inc->second.c_str()); + inc++; + } + fprintf(dump, "DataTypeList.append(%s)\n", fileName.c_str()); +} + + +/////////////////////////////////////////////////////////////////////////////// +char data[]={ +"\n" +"class bStructClass:\n" +" def __init__(self):\n" +" self.name = \"\";\n" +" self.filename = \"\";\n" +" self.includes = []\n" +" self.dataTypes = []\n" +"\n\n" +"DataTypeList = []\n" +}; + + +/////////////////////////////////////////////////////////////////////////////// +int main(int argc,char** argv) +{ + using namespace bParse; + dump = fopen("dump.py", "w"); + + if (!dump) return 0; + fprintf(dump, "%s\n", data); + + + char* filename = "../../../Demos/SerializeDemo/testFile.bullet"; + + if (argc==2) + filename = argv[1]; + + bString fileStr(filename); + bString extension(".bullet"); + + int index2 = fileStr.find(extension); + if (index2>=0) + isBulletFile=true; + + + FILE* fp = fopen (filename,"rb"); + + if (!fp) + { + printf("error: file not found %s\n",filename); + exit(0); + } + + char* memBuf = 0; + int len = 0; + + long currentpos = ftell(fp); /* save current cursor position */ + long newpos; + int bytesRead; + + fseek(fp, 0, SEEK_END); /* seek to end */ + newpos = ftell(fp); /* find position of end -- this is the length */ + fseek(fp, currentpos, SEEK_SET); /* restore previous cursor position */ + + len = newpos; + + memBuf = (char*)malloc(len); + bytesRead = fread(memBuf,len,1,fp); + + bool swap = false; + + + if (isBulletFile) + { + btBulletFile f(memBuf,len); + swap = (f.getFlags() & FD_ENDIAN_SWAP)!=0; + } else + { + bBlenderFile f(memBuf,len); + swap = (f.getFlags() & FD_ENDIAN_SWAP)!=0; + } + + + + + + char *blenderData = memBuf; + int sdnaPos=0; + int mDataStart = 12; + + char *tempBuffer = blenderData; + for (int i=0; iinitMemory(); + + mDNA->init(memBuf+sdnaPos, len-sdnaPos, swap); + + + for (int i=0; igetNumStructs(); i++) + { + short *structData = mDNA->getStruct(i); + bString type = mDNA->getType(structData[0]); + + bString className = type; + mStructs[type]=className; + } + + + for (int i=0; igetNumStructs(); i++) + { + short *structData = mDNA->getStruct(i); + writeTemplate(structData); + } + + delete mDNA; + fclose(dump); + return 0; +} +/////////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +int _getArraySize(char* str) +{ + int a, mul=1; + char stri[100], *cp=0; + int len = (int)strlen(str); + + memcpy(stri, str, len+1); + for (a=0; a + +///work-in-progress +///This ReadBulletSample is kept as simple as possible without dependencies to the Bullet SDK. +///It can be used to load .bullet data for other physics SDKs +///For a more complete example how to load and convert Bullet data using the Bullet SDK check out +///the Bullet/Demos/SerializeDemo and Bullet/Serialize/BulletWorldImporter + +using namespace Bullet; + +enum LocalBroadphaseNativeTypes +{ + // polyhedral convex shapes + BOX_SHAPE_PROXYTYPE, + TRIANGLE_SHAPE_PROXYTYPE, + TETRAHEDRAL_SHAPE_PROXYTYPE, + CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE, + CONVEX_HULL_SHAPE_PROXYTYPE, + CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE, + CUSTOM_POLYHEDRAL_SHAPE_TYPE, +//implicit convex shapes +IMPLICIT_CONVEX_SHAPES_START_HERE, + SPHERE_SHAPE_PROXYTYPE, + MULTI_SPHERE_SHAPE_PROXYTYPE, + CAPSULE_SHAPE_PROXYTYPE, + CONE_SHAPE_PROXYTYPE, + CONVEX_SHAPE_PROXYTYPE, + CYLINDER_SHAPE_PROXYTYPE, + UNIFORM_SCALING_SHAPE_PROXYTYPE, + MINKOWSKI_SUM_SHAPE_PROXYTYPE, + MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE, + BOX_2D_SHAPE_PROXYTYPE, + CONVEX_2D_SHAPE_PROXYTYPE, + CUSTOM_CONVEX_SHAPE_TYPE, +//concave shapes +CONCAVE_SHAPES_START_HERE, + //keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy! + TRIANGLE_MESH_SHAPE_PROXYTYPE, + SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE, + ///used for demo integration FAST/Swift collision library and Bullet + FAST_CONCAVE_MESH_PROXYTYPE, + //terrain + TERRAIN_SHAPE_PROXYTYPE, +///Used for GIMPACT Trimesh integration + GIMPACT_SHAPE_PROXYTYPE, +///Multimaterial mesh + MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE, + + EMPTY_SHAPE_PROXYTYPE, + STATIC_PLANE_PROXYTYPE, + CUSTOM_CONCAVE_SHAPE_TYPE, +CONCAVE_SHAPES_END_HERE, + + COMPOUND_SHAPE_PROXYTYPE, + + SOFTBODY_SHAPE_PROXYTYPE, + HFFLUID_SHAPE_PROXYTYPE, + HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE, + INVALID_SHAPE_PROXYTYPE, + + MAX_BROADPHASE_COLLISION_TYPES + +}; + +btBulletDataExtractor::btBulletDataExtractor() +{ +} + +btBulletDataExtractor::~btBulletDataExtractor() +{ +} + +void btBulletDataExtractor::convertAllObjects(bParse::btBulletFile* bulletFile2) +{ + int i; + + for (i=0;im_collisionShapes.size();i++) + { + btCollisionShapeData* shapeData = (btCollisionShapeData*)bulletFile2->m_collisionShapes[i]; + if (shapeData->m_name) + printf("converting shape %s\n", shapeData->m_name); + void* shape = convertCollisionShape(shapeData); + } + +} + + + +void* btBulletDataExtractor::convertCollisionShape( btCollisionShapeData* shapeData ) +{ + void* shape = 0; + + switch (shapeData->m_shapeType) + { + case STATIC_PLANE_PROXYTYPE: + { + btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*)shapeData; + void* shape = createPlaneShape(planeData->m_planeNormal,planeData->m_planeConstant, planeData->m_localScaling); + break; + } + + case CYLINDER_SHAPE_PROXYTYPE: + case CAPSULE_SHAPE_PROXYTYPE: + case BOX_SHAPE_PROXYTYPE: + case SPHERE_SHAPE_PROXYTYPE: + case MULTI_SPHERE_SHAPE_PROXYTYPE: + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + btConvexInternalShapeData* bsd = (btConvexInternalShapeData*)shapeData; + + switch (shapeData->m_shapeType) + { + case BOX_SHAPE_PROXYTYPE: + { + shape = createBoxShape(bsd->m_implicitShapeDimensions, bsd->m_localScaling,bsd->m_collisionMargin); + break; + } + case SPHERE_SHAPE_PROXYTYPE: + { + shape = createSphereShape(bsd->m_implicitShapeDimensions.m_floats[0],bsd->m_localScaling, bsd->m_collisionMargin); + break; + } +#if 0 + case CAPSULE_SHAPE_PROXYTYPE: + { + btCapsuleShapeData* capData = (btCapsuleShapeData*)shapeData; + switch (capData->m_upAxis) + { + case 0: + { + shape = createCapsuleShapeX(implicitShapeDimensions.getY(),2*implicitShapeDimensions.getX()); + break; + } + case 1: + { + shape = createCapsuleShapeY(implicitShapeDimensions.getX(),2*implicitShapeDimensions.getY()); + break; + } + case 2: + { + shape = createCapsuleShapeZ(implicitShapeDimensions.getX(),2*implicitShapeDimensions.getZ()); + break; + } + default: + { + printf("error: wrong up axis for btCapsuleShape\n"); + } + + }; + + break; + } + case CYLINDER_SHAPE_PROXYTYPE: + { + btCylinderShapeData* cylData = (btCylinderShapeData*) shapeData; + btVector3 halfExtents = implicitShapeDimensions+margin; + switch (cylData->m_upAxis) + { + case 0: + { + shape = createCylinderShapeX(halfExtents.getY(),halfExtents.getX()); + break; + } + case 1: + { + shape = createCylinderShapeY(halfExtents.getX(),halfExtents.getY()); + break; + } + case 2: + { + shape = createCylinderShapeZ(halfExtents.getX(),halfExtents.getZ()); + break; + } + default: + { + printf("unknown Cylinder up axis\n"); + } + + }; + + + + break; + } + case MULTI_SPHERE_SHAPE_PROXYTYPE: + { + btMultiSphereShapeData* mss = (btMultiSphereShapeData*)bsd; + int numSpheres = mss->m_localPositionArraySize; + int i; + for ( i=0;im_localPositionArrayPtr[i].m_pos); + radii[i] = mss->m_localPositionArrayPtr[i].m_radius; + } + shape = new btMultiSphereShape(&tmpPos[0],&radii[0],numSpheres); + break; + } + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + btConvexHullShapeData* convexData = (btConvexHullShapeData*)bsd; + int numPoints = convexData->m_numUnscaledPoints; + + btAlignedObjectArray tmpPoints; + tmpPoints.resize(numPoints); + int i; + for ( i=0;im_unscaledPointsFloatPtr) + tmpPoints[i].deSerialize(convexData->m_unscaledPointsFloatPtr[i]); + if (convexData->m_unscaledPointsDoublePtr) + tmpPoints[i].deSerializeDouble(convexData->m_unscaledPointsDoublePtr[i]); + } + shape = createConvexHullShape(); + + return shape; + break; + } +#endif + + default: + { + printf("error: cannot create shape type (%d)\n",shapeData->m_shapeType); + } + } + + break; + } +#if 0 + case TRIANGLE_MESH_SHAPE_PROXYTYPE: + { + btTriangleMeshShapeData* trimesh = (btTriangleMeshShapeData*)shapeData; + btTriangleIndexVertexArray* meshInterface = createMeshInterface(trimesh->m_meshInterface); + if (!meshInterface->getNumSubParts()) + { + return 0; + } + + btVector3 scaling; scaling.deSerializeFloat(trimesh->m_meshInterface.m_scaling); + meshInterface->setScaling(scaling); + + + btOptimizedBvh* bvh = 0; + + btBvhTriangleMeshShape* trimeshShape = createBvhTriangleMeshShape(meshInterface,bvh); + trimeshShape->setMargin(trimesh->m_collisionMargin); + shape = trimeshShape; + + if (trimesh->m_triangleInfoMap) + { + btTriangleInfoMap* map = createTriangleInfoMap(); + map->deSerialize(*trimesh->m_triangleInfoMap); + trimeshShape->setTriangleInfoMap(map); + +#ifdef USE_INTERNAL_EDGE_UTILITY + gContactAddedCallback = btAdjustInternalEdgeContactsCallback; +#endif //USE_INTERNAL_EDGE_UTILITY + + } + + //printf("trimesh->m_collisionMargin=%f\n",trimesh->m_collisionMargin); + break; + } + case COMPOUND_SHAPE_PROXYTYPE: + { + btCompoundShapeData* compoundData = (btCompoundShapeData*)shapeData; + btCompoundShape* compoundShape = createCompoundShape(); + + + btAlignedObjectArray childShapes; + for (int i=0;im_numChildShapes;i++) + { + btCollisionShape* childShape = convertCollisionShape(compoundData->m_childShapePtr[i].m_childShape); + if (childShape) + { + btTransform localTransform; + localTransform.deSerializeFloat(compoundData->m_childShapePtr[i].m_transform); + compoundShape->addChildShape(localTransform,childShape); + } else + { + printf("error: couldn't create childShape for compoundShape\n"); + } + + } + shape = compoundShape; + + break; + } + + case GIMPACT_SHAPE_PROXYTYPE: + { + btGImpactMeshShapeData* gimpactData = (btGImpactMeshShapeData*) shapeData; + if (gimpactData->m_gimpactSubType == CONST_GIMPACT_TRIMESH_SHAPE) + { + btTriangleIndexVertexArray* meshInterface = createMeshInterface(gimpactData->m_meshInterface); + btGImpactMeshShape* gimpactShape = createGimpactShape(meshInterface); + btVector3 localScaling; + localScaling.deSerializeFloat(gimpactData->m_localScaling); + gimpactShape->setLocalScaling(localScaling); + gimpactShape->setMargin(btScalar(gimpactData->m_collisionMargin)); + gimpactShape->updateBound(); + shape = gimpactShape; + } else + { + printf("unsupported gimpact sub type\n"); + } + break; + } + case SOFTBODY_SHAPE_PROXYTYPE: + { + return 0; + } +#endif + default: + { + printf("unsupported shape type (%d)\n",shapeData->m_shapeType); + } + } + + return shape; + +} + +void* btBulletDataExtractor::createBoxShape( const Bullet::btVector3FloatData& halfDimensions, const Bullet::btVector3FloatData& localScaling, float collisionMargin) +{ + printf("createBoxShape with halfDimensions %f,%f,%f\n",halfDimensions.m_floats[0], halfDimensions.m_floats[1],halfDimensions.m_floats[2]); + return 0; +} + +void* btBulletDataExtractor::createSphereShape( float radius, const Bullet::btVector3FloatData& localScaling, float collisionMargin) +{ + printf("createSphereShape with radius %f\n",radius); + return 0; +} + + +void* btBulletDataExtractor::createPlaneShape( const btVector3FloatData& planeNormal, float planeConstant, const Bullet::btVector3FloatData& localScaling) +{ + printf("createPlaneShape with normal %f,%f,%f and planeConstant\n",planeNormal.m_floats[0], planeNormal.m_floats[1],planeNormal.m_floats[2],planeConstant); + return 0; +} + diff --git a/Extras/Serialize/ReadBulletSample/BulletDataExtractor.h b/Extras/Serialize/ReadBulletSample/BulletDataExtractor.h new file mode 100644 index 0000000..f30b216 --- /dev/null +++ b/Extras/Serialize/ReadBulletSample/BulletDataExtractor.h @@ -0,0 +1,32 @@ +#ifndef BULLET_DATA_EXTRACTOR_H +#define BULLET_DATA_EXTRACTOR_H + + +#include "../BulletFileLoader/autogenerated/bullet.h" + +namespace bParse +{ + class btBulletFile; +}; + +class btBulletDataExtractor +{ + public: + + btBulletDataExtractor(); + + virtual ~btBulletDataExtractor(); + + virtual void convertAllObjects(bParse::btBulletFile* bulletFile); + + virtual void* convertCollisionShape( Bullet::btCollisionShapeData* shapeData ); + + virtual void* createPlaneShape( const Bullet::btVector3FloatData& planeNormal, float planeConstant, const Bullet::btVector3FloatData& localScaling); + + virtual void* createBoxShape( const Bullet::btVector3FloatData& halfDimensions, const Bullet::btVector3FloatData& localScaling, float collisionMargin); + + virtual void* createSphereShape( float radius, const Bullet::btVector3FloatData& localScaling, float collisionMargin); + +}; + +#endif //BULLET_DATA_EXTRACTOR_H \ No newline at end of file diff --git a/Extras/Serialize/ReadBulletSample/CMakeLists.txt b/Extras/Serialize/ReadBulletSample/CMakeLists.txt new file mode 100644 index 0000000..eca415d --- /dev/null +++ b/Extras/Serialize/ReadBulletSample/CMakeLists.txt @@ -0,0 +1,33 @@ + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +) + +LINK_LIBRARIES( + BulletFileLoader +) +IF (WIN32) + SET(ADDITIONAL_SRC + ${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc + ) +ENDIF() + +SET(READBULLET_SRC + main.cpp + BulletDataExtractor.cpp + BulletDataExtractor.h + ${BULLET_PHYSICS_SOURCE_DIR}/src/LinearMath/btSerializer.cpp + ${BULLET_PHYSICS_SOURCE_DIR}/src/LinearMath/btAlignedAllocator.cpp +) + +ADD_EXECUTABLE(AppReadBulletSample + ${READBULLET_SRC} + ${ADDITIONAL_SRC} +) + + +IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) + SET_TARGET_PROPERTIES(AppReadBulletSample PROPERTIES DEBUG_POSTFIX "_Debug") + SET_TARGET_PROPERTIES(AppReadBulletSample PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel") + SET_TARGET_PROPERTIES(AppReadBulletSample PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo") +ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES) \ No newline at end of file diff --git a/Extras/Serialize/ReadBulletSample/main.cpp b/Extras/Serialize/ReadBulletSample/main.cpp new file mode 100644 index 0000000..20719ed --- /dev/null +++ b/Extras/Serialize/ReadBulletSample/main.cpp @@ -0,0 +1,63 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 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 +#include "../BulletFileLoader/btBulletFile.h" +#include "BulletDataExtractor.h" + +///This ReadBulletSample is kept as simple as possible without dependencies to the Bullet SDK. +///It can be used to load .bullet data for other physics SDKs +///For a more complete example how to load and convert Bullet data using the Bullet SDK check out +///the Bullet/Demos/SerializeDemo and Bullet/Serialize/BulletWorldImporter + +int main(int argc, char** argv) +{ + const char* fileName="testFile.bullet"; + bool verboseDumpAllTypes = false; + + bParse::btBulletFile* bulletFile2 = new bParse::btBulletFile(fileName); + + bool ok = (bulletFile2->getFlags()& bParse::FD_OK)!=0; + + if (ok) + bulletFile2->parse(verboseDumpAllTypes); + else + { + printf("Error loading file %s.\n",fileName); + exit(0); + } + ok = (bulletFile2->getFlags()& bParse::FD_OK)!=0; + if (!ok) + { + printf("Error parsing file %s.\n",fileName); + exit(0); + } + + if (verboseDumpAllTypes) + { + bulletFile2->dumpChunks(bulletFile2->getFileDNA()); + } + + + btBulletDataExtractor extractor; + + extractor.convertAllObjects(bulletFile2); + + delete bulletFile2; + + return 0; +} + diff --git a/Extras/Serialize/makesdna/CMakeLists.txt b/Extras/Serialize/makesdna/CMakeLists.txt new file mode 100644 index 0000000..9f5d5c6 --- /dev/null +++ b/Extras/Serialize/makesdna/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 2.4) + +IF(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + +INCLUDE_DIRECTORIES(${BULLET_PHYSICS_SOURCE_DIR}/src ) + +#FILE(GLOB INC_FILES ../*.h) + +SET (INC_FILES + DNA_rigidbody.h + + ${BULLET_PHYSICS_SOURCE_DIR}/src/LinearMath/btVector3.h + ${BULLET_PHYSICS_SOURCE_DIR}/src/LinearMath/btMatrix3x3.h + ${BULLET_PHYSICS_SOURCE_DIR}/src/LinearMath/btTransform.h + ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletCollision/CollisionShapes/btCollisionShape.h + ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletCollision/CollisionShapes/btConvexInternalShape.h + ${BULLET_PHYSICS_SOURCE_DIR}/src/BulletCollision/CollisionDispatch/btCollisionObject.h +) + +# Build makesdna executable +SET(SRC makesdna.cpp) +ADD_EXECUTABLE(makesdna ${SRC} ${INC_FILES}) + +# Output BulletDNA.c +ADD_CUSTOM_COMMAND( + OUTPUT ${BULLET_PHYSICS_SOURCE_DIR}/src/LinearMath/btSerializer.cpp + COMMAND ${CMAKE_CFG_INTDIR}/makesdna ${BULLET_PHYSICS_SOURCE_DIR}/src/LinearMath/btSerializer.cpp ${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/CommonSerialize/ + DEPENDS makesdna +) + +# Build bf_dna library +SET(SRC ${BULLET_PHYSICS_SOURCE_DIR}/src/LinearMath/btSerializer.cpp) +ADD_LIBRARY(BulletDNA ${SRC} ${INC_FILES}) + +MESSAGE(STATUS "Configuring makesdna") diff --git a/Extras/Serialize/makesdna/DNA_rigidbody.h b/Extras/Serialize/makesdna/DNA_rigidbody.h new file mode 100644 index 0000000..010ed1b --- /dev/null +++ b/Extras/Serialize/makesdna/DNA_rigidbody.h @@ -0,0 +1,29 @@ + +#ifndef DNA_RIGIDBODY_H +#define DNA_RIGIDBODY_H + + +struct PointerArray +{ + int m_size; + int m_capacity; + void *m_data; +}; + + +struct btPhysicsSystem +{ + PointerArray m_collisionShapes; + PointerArray m_collisionObjects; + PointerArray m_constraints; +}; + +///we need this to compute the pointer sizes +struct ListBase +{ + void *first; + void *last; +}; + + +#endif diff --git a/Extras/Serialize/makesdna/makesdna.cpp b/Extras/Serialize/makesdna/makesdna.cpp new file mode 100644 index 0000000..f3b8c1a --- /dev/null +++ b/Extras/Serialize/makesdna/makesdna.cpp @@ -0,0 +1,1246 @@ +/// Current makesdna.cpp is a from Blender, but we will completely rewrite it in C++ under a ZLib license +/// The Original version is at https://svn.blender.org/svnroot/bf-blender/trunk/blender/source/blender/makesdna/intern/makesdna.c + +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + * + * Struct muncher for making SDNA + * + * Originally by Ton, some mods by Frank, and some cleaning and + * extension by Nzc. + * + * Makesdna creates a .c file with a long string of numbers that + * encode the Blender file format. It is fast, because it is basically + * a binary dump. There are some details to mind when reconstructing + * the file (endianness and byte-alignment). + * + * This little program scans all structs that need to be serialized, + * and determined the names and types of all members. It calculates + * how much memory (on disk or in ram) is needed to store that struct, + * and the offsets for reaching a particular one. + * + * There is a facility to get verbose output from sdna. Search for + * debugSDNA. This int can be set to 0 (no output) to some int. Higher + * numbers give more output. + * */ + + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_WIN32) && !defined(FREE_WINDOWS) + +/* The __intXX are built-in types of the visual complier! So we don't + * need to include anything else here. */ + +typedef signed __int8 int8_t; +typedef signed __int16 int16_t; +typedef signed __int32 int32_t; +typedef signed __int64 int64_t; + +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; + +#ifndef _INTPTR_T_DEFINED +#ifdef _WIN64 +typedef __int64 intptr_t; +#else +typedef long intptr_t; +#endif +#define _INTPTR_T_DEFINED +#endif + +#ifndef _UINTPTR_T_DEFINED +#ifdef _WIN64 +typedef unsigned __int64 uintptr_t; +#else +typedef unsigned long uintptr_t; +#endif +#define _UINTPTR_T_DEFINED +#endif + +#elif defined(__linux__) || defined(__NetBSD__) + + /* Linux-i386, Linux-Alpha, Linux-ppc */ +#include + +#elif defined (__APPLE__) + +#include + +#elif defined(FREE_WINDOWS) + +#include + +#else + + /* FreeBSD, Irix, Solaris */ +#include + +#endif /* ifdef platform for types */ + +#ifdef __cplusplus +} +#endif + + +#include +#include +#include + +//#include "DNA_sdna_types.h" +// include files for automatic dependancies +#include "DNA_rigidbody.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btTransform.h" +#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" +#include "BulletCollision/CollisionShapes/btConvexInternalShape.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/CollisionShapes/btConvexHullShape.h" +#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h" +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/CollisionShapes/btCylinderShape.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletCollision/CollisionShapes/btTriangleInfoMap.h" +#include "BulletCollision/Gimpact/btGImpactShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h" +#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h" +#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h" +#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h" +#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h" +#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h" + +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletSoftBody/btSoftBodyData.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define SDNA_MAX_FILENAME_LENGTH 255 + +/* Included the path relative from /source/blender/ here, so we can move */ +/* headers around with more freedom. */ +char *includefiles[] = { + + // if you add files here, please add them at the end + // of makesdna.c (this file) as well + "../makesdna/DNA_rigidbody.h", + "../../../src/LinearMath/btVector3.h", + "../../../src/LinearMath/btMatrix3x3.h", + "../../../src/LinearMath/btTransform.h", + "../../../src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h", + "../../../src/BulletCollision/CollisionShapes/btCollisionShape.h", + "../../../src/BulletCollision/CollisionShapes/btStaticPlaneShape.h", + "../../../src/BulletCollision/CollisionShapes/btConvexInternalShape.h", + "../../../src/BulletCollision/CollisionShapes/btMultiSphereShape.h", + "../../../src/BulletCollision/CollisionShapes/btStridingMeshInterface.h", + "../../../src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h", + "../../../src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h", + "../../../src/BulletCollision/CollisionShapes/btCompoundShape.h", + "../../../src/BulletCollision/CollisionShapes/btCylinderShape.h", + "../../../src/BulletCollision/CollisionShapes/btCapsuleShape.h", + "../../../src/BulletCollision/CollisionShapes/btTriangleInfoMap.h", + "../../../src/BulletCollision/Gimpact/btGImpactShape.h", + "../../../src/BulletCollision/CollisionShapes/btConvexHullShape.h", + "../../../src/BulletCollision/CollisionDispatch/btCollisionObject.h", + "../../../src/BulletDynamics/Dynamics/btRigidBody.h", + "../../../src/BulletDynamics/ConstraintSolver/btTypedConstraint.h", + "../../../src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h", + "../../../src/BulletDynamics/ConstraintSolver/btHingeConstraint.h", + "../../../src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h", + "../../../src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h", + "../../../src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h", + "../../../src/BulletDynamics/ConstraintSolver/btSliderConstraint.h", + "../../../src/BulletSoftBody/btSoftBodyData.h", + // empty string to indicate end of includefiles + "" +}; + +void* malloc_and_setzero(int numbytes) +{ + char* buf = (char*)malloc(numbytes); + memset(buf,0,numbytes); + return buf; +} + +int maxdata= 500000, maxnr= 50000; +int nr_names=0; +int nr_types=0; +int nr_structs=0; +char **names, *namedata; /* at adress names[a] is string a */ +char **types, *typedata; /* at adress types[a] is string a */ +short *typelens; /* at typelens[a] is de length of type a */ +short *alphalens; /* contains sizes as they are calculated on the DEC Alpha (64 bits) */ +short **structs, *structdata; /* at sp= structs[a] is the first adress of a struct definition + sp[0] is type number + sp[1] is amount of elements + sp[2] sp[3] is typenr, namenr (etc) */ +/* + * debugSDNA: + * - 0 = no output, except errors + * - 1 = detail actions + * - 2 = full trace, tell which names and types were found + * - 4 = full trace, plus all gritty details + */ +int debugSDNA = 0; +int additional_slen_offset; + +/* ************************************************************************** */ +/* Functions */ +/* ************************************************************************** */ + +/** + * Add type to struct indexed by , if it was not yet found. + */ +int add_type(char *str, int len); + +/** + * Add variable to + */ +int add_name(char *str); + +/** + * Search whether this structure type was already found, and if not, + * add it. + */ +short *add_struct(int namecode); + +/** + * Remove comments from this buffer. Assumes that the buffer refers to + * ascii-code text. + */ +int preprocess_include(char *maindata, int len); + +/** + * Scan this file for serializable types. + */ +int convert_include(char *filename); + +/** + * Determine how many bytes are needed for an array. + */ +int arraysize(char *astr, int len); + +/** + * Determine how many bytes are needed for each struct. + */ +static int calculate_structlens(int); + +/** + * Construct the DNA.c file + */ +void dna_write(FILE *file, void *pntr, int size); + +/** + * Report all structures found so far, and print their lenghts. + */ +void printStructLenghts(void); + + + +/* ************************************************************************** */ +/* Implementation */ +/* ************************************************************************** */ + +/* ************************* MAKEN DNA ********************** */ + +int add_type(char *str, int len) +{ + int nr; + char *cp; + + if(str[0]==0) return -1; + + /* search through type array */ + for(nr=0; nr=maxnr) { + printf("too many types\n"); + return nr_types-1;; + } + nr_types++; + + return nr_types-1; +} + +/** + * + * Because of the weird way of tokenizing, we have to 'cast' function + * pointers to ... (*f)(), whatever the original signature. In fact, + * we add name and type at the same time... There are two special + * cases, unfortunately. These are explicitly checked. + * + * */ +int add_name(char *str) +{ + int nr, i, j, k; + char *cp; + char buf[255]; /* stupid limit, change it :) */ + char *name; + + additional_slen_offset = 0; + + if((str[0]==0) /* || (str[1]==0) */) return -1; + + if (str[0] == '(' && str[1] == '*') { + if (debugSDNA > 3) printf("\t\t\t\t*** Function pointer found\n"); + /* functionpointer: transform the type (sometimes) */ + i = 0; + j = 0; + + while (str[i] != ')') { + buf[i] = str[i]; + i++; + } + + /* Another number we need is the extra slen offset. This extra + * offset is the overshoot after a space. If there is no + * space, no overshoot should be calculated. */ + j = i; /* j at first closing brace */ + + if (debugSDNA > 3) printf("first brace after offset %d\n", i); + + j++; /* j beyond closing brace ? */ + while ((str[j] != 0) && (str[j] != ')' )) { + if (debugSDNA > 3) printf("seen %c ( %d) \n", str[j], str[j]); + j++; + } + if (debugSDNA > 3) printf("seen %c ( %d) \n", str[j], str[j]); + if (debugSDNA > 3) printf("special after offset %d\n", j); + + if (str[j] == 0 ) { + if (debugSDNA > 3) printf("offsetting for space\n"); + /* get additional offset */ + k = 0; + while (str[j] != ')') { + j++; + k++; + } + if (debugSDNA > 3) printf("extra offset %d\n", k); + additional_slen_offset = k; + } else if (str[j] == ')' ) { + if (debugSDNA > 3) printf("offsetting for brace\n"); + ; /* don't get extra offset */ + } else { + printf("Error during tokening function pointer argument list\n"); + } + + /* + * Put )(void) at the end? Maybe )(). Should check this with + * old sdna. Actually, sometimes )(), sometimes )(void...) + * Alas.. such is the nature of braindamage :( + * + * Sorted it out: always do )(), except for headdraw and + * windraw, part of ScrArea. This is important, because some + * linkers will treat different fp's differently when called + * !!! This has to do with interference in byte-alignment and + * the way args are pushed on the stack. + * + * */ + buf[i] = 0; + if (debugSDNA > 3) printf("Name before chomping: %s\n", buf); + if ( (strncmp(buf,"(*headdraw", 10) == 0) + || (strncmp(buf,"(*windraw", 9) == 0) ) { + buf[i] = ')'; + buf[i+1] = '('; + buf[i+2] = 'v'; + buf[i+3] = 'o'; + buf[i+4] = 'i'; + buf[i+5] = 'd'; + buf[i+6] = ')'; + buf[i+7] = 0; + } else { + buf[i] = ')'; + buf[i+1] = '('; + buf[i+2] = ')'; + buf[i+3] = 0; + } + /* now precede with buf*/ + if (debugSDNA > 3) printf("\t\t\t\t\tProposing fp name %s\n", buf); + name = buf; + } else { + /* normal field: old code */ + name = str; + } + + /* search name array */ + for(nr=0; nr=maxnr) { + printf("too many names\n"); + return nr_names-1; + } + nr_names++; + + return nr_names-1; +} + +short *add_struct(int namecode) +{ + int len; + short *sp; + + if(nr_structs==0) { + structs[0]= structdata; + } + else { + sp= structs[nr_structs-1]; + len= sp[1]; + structs[nr_structs]= sp+ 2*len+2; + } + + sp= structs[nr_structs]; + sp[0]= namecode; + + if(nr_structs>=maxnr) { + printf("too many structs\n"); + return sp; + } + nr_structs++; + + return sp; +} + +int preprocess_include(char *maindata, int len) +{ + int a, newlen, comment = 0; + char *cp, *temp, *md; + + temp= (char*) malloc_and_setzero(len); + memcpy(temp, maindata, len); + + // remove all c++ comments + /* replace all enters/tabs/etc with spaces */ + cp= temp; + a= len; + comment = 0; + while(a--) { + if(cp[0]=='/' && cp[1]=='/') { + comment = 1; + } else if (*cp<32) { + comment = 0; + } + if (comment || *cp<32 || *cp>128 ) *cp= 32; + cp++; + } + + + /* data from temp copy to maindata, remove comments and double spaces */ + cp= temp; + md= maindata; + newlen= 0; + comment= 0; + a= len; + while(a--) { + + if(cp[0]=='/' && cp[1]=='*') { + comment= 1; + cp[0]=cp[1]= 32; + } + if(cp[0]=='*' && cp[1]=='/') { + comment= 0; + cp[0]=cp[1]= 32; + } + + /* do not copy when: */ + if(comment); + else if( cp[0]==' ' && cp[1]==' ' ); + else if( cp[-1]=='*' && cp[0]==' ' ); /* pointers with a space */ + else { + md[0]= cp[0]; + md++; + newlen++; + } + cp++; + } + + free(temp); + return newlen; +} + +static void *read_file_data(char *filename, int *len_r) +{ +#ifdef WIN32 + FILE *fp= fopen(filename, "rb"); +#else + FILE *fp= fopen(filename, "r"); +#endif + void *data; + + if (!fp) { + *len_r= -1; + return NULL; + } + + fseek(fp, 0L, SEEK_END); + *len_r= ftell(fp); + fseek(fp, 0L, SEEK_SET); + + data= malloc_and_setzero(*len_r); + if (!data) { + *len_r= -1; + fclose(fp); + return NULL; + } + + if (fread(data, *len_r, 1, fp)!=1) { + *len_r= -1; + free(data); + fclose(fp); + return NULL; + } + + fclose(fp); + return data; +} + + +const char* skipStructTypes[]= +{ + "btRigidBodyConstructionInfo", + "Euler", + "btConstraintInfo2", + "btConstraintSetting", + "btTriangleInfo", + "" +}; + +int skipStruct(const char* structType) +{ + int i=0; + while (strlen(skipStructTypes[i])) + { + if (strcmp(structType,skipStructTypes[i])==0) + { + return 1; + } + i++; + } + return 0; +} + +int convert_include(char *filename) +{ + /* read include file, skip structs with a '#' before it. + store all data in temporal arrays. + */ + int filelen, count, overslaan, slen, type, name, strct; + short *structpoin, *sp; + char *maindata, *mainend, *md, *md1; + + md= maindata= (char*)read_file_data(filename, &filelen); + if (filelen==-1) { + printf("Can't read file %s\n", filename); + return 1; + } + + filelen= preprocess_include(maindata, filelen); + mainend= maindata+filelen-1; + + /* we look for '{' and then back to 'struct' */ + count= 0; + overslaan= 0; + while(count 1) printf("\t|\t|-- detected struct %s\n", types[strct]); + + /* first lets make it all nice strings */ + md1= md+1; + while(*md1 != '}') { + if(md1>mainend) break; + + if(*md1==',' || *md1==' ') *md1= 0; + md1++; + } + + /* read types and names until first character that is not '}' */ + md1= md+1; + while( *md1 != '}' ) { + if(md1>mainend) break; + + /* skip when it says 'struct' or 'unsigned' or 'const' */ + if(*md1) { + if( strncmp(md1, "struct", 6)==0 ) md1+= 7; + if( strncmp(md1, "unsigned", 8)==0 ) md1+= 9; + if( strncmp(md1, "const", 5)==0 ) md1+= 6; + + /* we've got a type! */ + type= add_type(md1, 0); + + if (debugSDNA > 1) printf("\t|\t|\tfound type %s (", md1); + + md1+= strlen(md1); + + + /* read until ';' */ + while( *md1 != ';' ) { + if(md1>mainend) break; + + if(*md1) { + /* We've got a name. slen needs + * correction for function + * pointers! */ + slen= (int) strlen(md1); + if( md1[slen-1]==';' ) { + md1[slen-1]= 0; + + + name= add_name(md1); + slen += additional_slen_offset; + sp[0]= type; + sp[1]= name; + + if ((debugSDNA>1) && (names[name] != 0 )) printf("%s |", names[name]); + + structpoin[1]++; + sp+= 2; + + md1+= slen; + break; + } + + + name= add_name(md1); + slen += additional_slen_offset; + + sp[0]= type; + sp[1]= name; + if ((debugSDNA > 1) && (names[name] != 0 )) printf("%s ||", names[name]); + + structpoin[1]++; + sp+= 2; + + md1+= slen; + } + md1++; + } + + if (debugSDNA > 1) printf(")\n"); + + } + md1++; + } + } + } + } + } + count++; + md++; + } + + free(maindata); + + return 0; +} + +int arraysize(char *astr, int len) +{ + int a, mul=1; + char str[100], *cp=0; + + memcpy(str, astr, len+1); + + for(a=0; a= firststruct) { + if(sizeof(void *)==8 && (len % 8) ) { + printf("Align struct error: %s %s\n", types[structtype],cp); + dna_error = 1; + } + } + + /* 2-4 aligned/ */ + if(typelens[type]>3 && (len % 4) ) { + printf("Align 4 error in struct: %s %s (add %d padding bytes)\n", types[structtype], cp, len%4); + dna_error = 1; + } + else if(typelens[type]==2 && (len % 2) ) { + printf("Align 2 error in struct: %s %s (add %d padding bytes)\n", types[structtype], cp, len%2); + dna_error = 1; + } + + len += mul*typelens[type]; + alphalen += mul * alphalens[type]; + + } else { + len= 0; + alphalen = 0; + break; + } + } + + if (len==0) { + unknown++; + } else { + typelens[structtype]= len; + alphalens[structtype]= alphalen; + // two ways to detect if a struct contains a pointer: + // has_pointer is set or alphalen != len + if (has_pointer || alphalen != len) { + if (alphalen % 8) { + printf("alphalen = %d len = %d\n",alphalen,len); + printf("Sizeerror 8 in struct: %s (add %d bytes)\n", types[structtype], alphalen%8); + dna_error = 1; + } + } + + if(len % 4) { + printf("Sizeerror 4 in struct: %s (add %d bytes)\n", types[structtype], len%4); + dna_error = 1; + } + + } + } + } + + if(unknown==lastunknown) break; + } + + if(unknown) { + printf("ERROR: still %d structs unknown\n", unknown); + + if (debugSDNA) { + printf("*** Known structs : \n"); + + for(a=0; a= MAX_DNA_LINE_LENGTH) { + fprintf(file, "\n"); + linelength = 0; + } + } +} + +void printStructLenghts(void) +{ + int a, unknown= nr_structs, lastunknown, structtype; + short *structpoin; + printf("\n\n*** All detected structs:\n"); + + while(unknown) { + lastunknown= unknown; + unknown= 0; + + /* check all structs... */ + for(a=0; a -1) { + fflush(stdout); + printf("Running makesdna at debug level %d\n", debugSDNA); + + } + + /* the longest known struct is 50k, so we assume 100k is sufficent! */ + namedata= (char*)malloc_and_setzero(maxdata); + typedata= (char*)malloc_and_setzero(maxdata); + structdata= (short*)malloc_and_setzero(maxdata); + + /* a maximum of 5000 variables, must be sufficient? */ + names= (char**)malloc_and_setzero(sizeof(char *)*maxnr); + types= (char**)malloc_and_setzero(sizeof(char *)*maxnr); + typelens= (short*) malloc_and_setzero(sizeof(short)*maxnr); + alphalens= (short*)malloc_and_setzero(sizeof(short)*maxnr); + structs= (short**)malloc_and_setzero(sizeof(short)*maxnr); + + /* insertion of all known types */ + /* watch it: uint is not allowed! use in structs an unsigned int */ + add_type("char", 1); /* 0 */ + add_type("uchar", 1); /* 1 */ + add_type("short", 2); /* 2 */ + add_type("ushort", 2); /* 3 */ + add_type("int", 4); /* 4 */ + add_type("long", 4); /* 5 */ /* should it be 8 on 64 bits? */ + add_type("ulong", 4); /* 6 */ + add_type("float", 4); /* 7 */ + add_type("double", 8); /* 8 */ + add_type("void", 0); /* 9 */ + + // the defines above shouldn't be output in the padding file... + firststruct = nr_types; + + /* add all include files defined in the global array */ + /* Since the internal file+path name buffer has limited length, I do a */ + /* little test first... */ + /* Mind the breaking condition here! */ + if (debugSDNA) printf("\tStart of header scan:\n"); + for (i = 0; strlen(includefiles[i]); i++) { + sprintf(str, "%s%s", baseDirectory, includefiles[i]); + if (debugSDNA) printf("\t|-- Converting %s\n", str); + if (convert_include(str)) { + return (1); + } + } + if (debugSDNA) printf("\tFinished scanning %d headers.\n", i); + + if (calculate_structlens(firststruct)) { + // error + return(1); + } + + + /* FOR DEBUG */ + if (debugSDNA > 1) + { + int a,b; +/* short *elem; */ + short num_types; + + printf("nr_names %d nr_types %d nr_structs %d\n", nr_names, nr_types, nr_structs); + for(a=0; a -1) printf("Writing file ... "); + + if(nr_names==0 || nr_structs==0); + else { + strcpy(str, "SDNA"); + dna_write(file, str, 4); + + /* write names */ + strcpy(str, "NAME"); + dna_write(file, str, 4); + len= nr_names; + dna_write(file, &len, 4); + + /* calculate size of datablock with strings */ + cp= names[nr_names-1]; + cp+= strlen(names[nr_names-1]) + 1; /* +1: null-terminator */ + len= (intptr_t) (cp - (char*) names[0]); + len= (len+3) & ~3; + dna_write(file, names[0], len); + + /* write TYPES */ + strcpy(str, "TYPE"); + dna_write(file, str, 4); + len= nr_types; + dna_write(file, &len, 4); + + /* calculate datablock size */ + cp= types[nr_types-1]; + cp+= strlen(types[nr_types-1]) + 1; /* +1: null-terminator */ + len= (intptr_t) (cp - (char*) types[0]); + len= (len+3) & ~3; + + dna_write(file, types[0], len); + + /* WRITE TYPELENGTHS */ + strcpy(str, "TLEN"); + dna_write(file, str, 4); + + len= 2*nr_types; + if(nr_types & 1) len+= 2; + dna_write(file, typelens, len); + + /* WRITE STRUCTS */ + strcpy(str, "STRC"); + dna_write(file, str, 4); + len= nr_structs; + dna_write(file, &len, 4); + + /* calc datablock size */ + sp= structs[nr_structs-1]; + sp+= 2+ 2*( sp[1] ); + len= (intptr_t) ((char*) sp - (char*) structs[0]); + len= (len+3) & ~3; + + dna_write(file, structs[0], len); + + /* a simple dna padding test */ + if (0) { + FILE *fp; + int a; + + fp= fopen("padding.c", "w"); + if(fp==NULL); + else { + + // add all include files defined in the global array + for (i = 0; strlen(includefiles[i]); i++) { + fprintf(fp, "#include \"%s%s\"\n", baseDirectory, includefiles[i]); + } + + fprintf(fp, "main(){\n"); + sp = typelens; + sp += firststruct; + for(a=firststruct; a -1) printf("done.\n"); + + return(0); +} + +/* ************************* END MAKE DNA ********************** */ + +static void make_bad_file(char *file) +{ + FILE *fp= fopen(file, "w"); + fprintf(fp, "ERROR! Cannot make correct DNA.c file, STUPID!\n"); + fclose(fp); +} + +#ifndef BASE_HEADER +#define BASE_HEADER "../" +#endif + +int main(int argc, char ** argv) +{ +// printf("btCollisionObject=%d\n",sizeof(btCollisionObject)); +// printf("btCollisionObjectData=%d\n",sizeof(btCollisionObjectData)); +// printf("btTransform=%d\n",sizeof(btTransform)); +// printf("btTransformData=%d\n",sizeof(btTransformData)); +// +// btCollisionObject* bla = new btCollisionObject(); +// btCollisionObjectData* bla2 = new btCollisionObjectData(); + + //int offsetof(bla,m_hasAnisotropicFriction); +/* + btTransformData m_worldTransform; + btTransform m_interpolationWorldTransform; + btVector3 m_interpolationLinearVelocity; + btVector3 m_interpolationAngularVelocity; + btVector3 m_anisotropicFriction; + bool m_hasAnisotropicFriction; + btScalar m_contactProcessingThreshold; + btBroadphaseProxy *m_broadphaseHandle; + btCollisionShape *m_collisionShape; + btCollisionShape *m_rootCollisionShape; + int m_collisionFlags; + int m_islandTag1; + int m_companionId; + int m_activationState1; + btScalar m_deactivationTime; + btScalar m_friction; + btScalar m_restitution; + void* m_userObjectPointer; + int m_internalType; + btScalar m_hitFraction; + btScalar m_ccdSweptSphereRadius; + btScalar m_ccdMotionThreshold; + bool m_checkCollideWith; + char m_pad[7]; +*/ + + FILE *file; + int return_status = 0; + + if (argc!=2 && argc!=3) { + printf("Usage: %s outfile.c [base directory]\n", argv[0]); + return_status = 1; + } else { + file = fopen(argv[1], "w"); + if (!file) { + printf ("Unable to open file: %s\n", argv[1]); + return_status = 1; + } else { + char baseDirectory[256]; + + if (argc==3) { + strcpy(baseDirectory, argv[2]); + } else { + strcpy(baseDirectory, BASE_HEADER); + } + + if (sizeof(void*)==8) + { + fprintf (file, "unsigned char sBulletDNAstr64[]= {\n"); + } else + { + fprintf (file, "unsigned char sBulletDNAstr[]= {\n"); + } + + if (make_structDNA(baseDirectory, file)) { + // error + fclose(file); + make_bad_file(argv[1]); + return_status = 1; + } else { + fprintf(file, "};\n"); + if (sizeof(void*)==8) + { + fprintf(file, "int sBulletDNAlen64= sizeof(sBulletDNAstr64);\n"); + } else + { + fprintf(file, "int sBulletDNAlen= sizeof(sBulletDNAstr);\n"); + } + + fclose(file); + } + } + } + + + return(return_status); +} + + +/* end of list */ diff --git a/Extras/glui/CMakeLists.txt b/Extras/glui/CMakeLists.txt new file mode 100644 index 0000000..c2018a7 --- /dev/null +++ b/Extras/glui/CMakeLists.txt @@ -0,0 +1,66 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + +ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS) + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# This is the variable for Windows. I use this to define the root of my directory structure. +SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/glut) + +# You shouldn't have to modify anything below this line +######################################################## + + +# This is the shortcut to finding GLU, GLUT and OpenGL if they are properly installed on your system +# This should be the case. +INCLUDE (${CMAKE_ROOT}/Modules/FindGLU.cmake) +INCLUDE (${CMAKE_ROOT}/Modules/FindGLUT.cmake) +INCLUDE (${CMAKE_ROOT}/Modules/FindOpenGL.cmake) + + +IF (WIN32) + # This is the Windows code for which Opengl, and Glut are not properly installed + # since I can't install them I must cheat and copy libraries around + INCLUDE_DIRECTORIES(${GLUT_ROOT}) + # LINK_DIRECTORIES(${GLUT_ROOT}\\lib) + # IF (${GLUT_glut_LIBRARY} MATCHES "GLUT_glut_LIBRARY-NOTFOUND") + # LINK_LIBRARIES(${GLUT_ROOT}\\lib\\glut32 ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY}) + # TARGET_LINK_LIBRARIES(table ${GLUT_ROOT}\\lib\\glut32) +# +# ADD_CUSTOM_COMMAND(TARGET table POST_BUILD COMMAND copy ${GLUT_ROOT}\\lib\\glut32.dll ${GLUT_ROOT}\\bin\\vs2005\\Debug +# COMMAND copy ${GLUT_ROOT}\\lib\\glut32.dll ${GLUT_ROOT}\\bin\\vs2003\\Debug +# COMMAND copy ${GLUT_ROOT}\\lib\\glut32.dll ${GLUT_ROOT}\\bin\\vs6\\Debug) +# ELSE (${GLUT_glut_LIBRARY} MATCHES "GLUT_glut_LIBRARY-NOTFOUND") +# LINK_LIBRARIES(${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}) +# TARGET_LINK_LIBRARIES(table ${GLUT_glut_LIBRARY}) +# ENDIF(${GLUT_glut_LIBRARY} MATCHES "GLUT_glut_LIBRARY-NOTFOUND") +# TARGET_LINK_LIBRARIES(table ${OPENGL_gl_LIBRARY}) +# TARGET_LINK_LIBRARIES(table ${OPENGL_glu_LIBRARY}) +ELSE (WIN32) + # This is the lines for linux. This should always work if everything is installed and working fine. +# SET(CMAKE_BUILD_TYPE Debug) +# SET(CMAKE_CXX_FLAGS_DEBUG "-g") + INCLUDE_DIRECTORIES(/usr/include /usr/local/include ${GLUT_INCLUDE_DIR}) +# TARGET_LINK_LIBRARIES(table ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}) +# TARGET_LINK_LIBRARIES(checker ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}) +ENDIF (WIN32) + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/Extras/glui +) + +ADD_LIBRARY(GLUI + arcball.h glui_checkbox.cpp glui_internal.h glui_panel.cpp glui_spinner.cpp glui_treepanel.cpp +GL glui.cpp glui_column.cpp glui_internal_control.h glui_radio.cpp glui_statictext.cpp glui_window.cpp +glui_add_controls.cpp glui_commandline.cpp glui_list.cpp glui_rollout.cpp glui_string.cpp quaternion.cpp +algebra3.cpp glui_bitmap_img_data.cpp glui_control.cpp glui_listbox.cpp glui_rotation.cpp glui_textbox.cpp quaternion.h +algebra3.h glui_bitmaps.cpp glui_edittext.cpp glui_mouse_iaction.cpp glui_scrollbar.cpp glui_translation.cpp +arcball.cpp glui_button.cpp glui_filebrowser.cpp glui_node.cpp glui_separator.cpp glui_tree.cpp + +) + +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(GLUI ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}) +ENDIF (BUILD_SHARED_LIBS) diff --git a/Extras/glui/GL/glui.h b/Extras/glui/GL/glui.h new file mode 100644 index 0000000..2deb9dc --- /dev/null +++ b/Extras/glui/GL/glui.h @@ -0,0 +1,2723 @@ +/**************************************************************************** + + GLUI User Interface Toolkit (LGPL) + ---------------------------------- + + glui.h - Main (and only) external header for + GLUI User Interface Toolkit + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#ifndef GLUI_GLUI_H +#define GLUI_GLUI_H + +#ifdef WIN32 + #pragma warning(disable : 4324) // disable padding warning + #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning. + #pragma warning(disable:4996) //Turn off warnings about deprecated C routines + #pragma warning(disable:4786) // Disable the "debug name too long" warning +#endif + + +#ifdef WIN32//for glut.h +#include +#endif + +#if defined(GLUI_FREEGLUT) || defined(BT_USE_FREEGLUT) + + // FreeGLUT does not yet work perfectly with GLUI + // - use at your own risk. + #include + +#elif defined(GLUI_OPENGLUT) + + // OpenGLUT does not yet work properly with GLUI + // - use at your own risk. + + #include + +#else + +#if defined(__APPLE__) && !defined (VMDMESA) + #include + #include + #include +#else +// #include "../../freeglut/gl/glut.h" + #include + #endif + +#endif + +#include +#include +#include +#include +#include + +#define GLUI_VERSION 2.3f /********** Current version **********/ + +#if defined(_WIN32) +#if !defined(GLUI_NO_LIB_PRAGMA) +//#pragma comment(lib, "glui32.lib") // Link automatically with GLUI library +#endif +#endif + +/********** Do some basic defines *******/ + +#ifndef Byte +#define Byte unsigned char +#endif + +#ifndef _RGBC_ +class RGBc { +public: + Byte r, g, b; + + void set(Byte r,Byte g,Byte b) {this->r=r;this->g=g;this->b=b;} + + RGBc( void ) {} + RGBc( Byte r, Byte g, Byte b ) { set( r, g, b ); } +}; +#define _RGBC_ +#endif + +/********** List of GLUT callbacks ********/ + +enum GLUI_Glut_CB_Types +{ + GLUI_GLUT_RESHAPE, + GLUI_GLUT_KEYBOARD, + GLUI_GLUT_DISPLAY, + GLUI_GLUT_MOUSE, + GLUI_GLUT_MOTION, + GLUI_GLUT_SPECIAL, + GLUI_GLUT_SPECIAL_UP, + GLUI_GLUT_PASSIVE_MOTION, + GLUI_GLUT_ENTRY, + GLUI_GLUT_VISIBILITY +}; + +/********* Constants for window placement **********/ + +#define GLUI_XOFF 6 +#define GLUI_YOFF 6 +#define GLUI_ITEMSPACING 3 +#define GLUI_CHECKBOX_SIZE 13 +#define GLUI_RADIOBUTTON_SIZE 13 +#define GLUI_BUTTON_SIZE 20 +#define GLUI_STATICTEXT_SIZE 13 +#define GLUI_SEPARATOR_HEIGHT 8 +#define GLUI_DEFAULT_CONTROL_WIDTH 100 +#define GLUI_DEFAULT_CONTROL_HEIGHT 13 +#define GLUI_EDITTEXT_BOXINNERMARGINX 3 +#define GLUI_EDITTEXT_HEIGHT 20 +#define GLUI_EDITTEXT_WIDTH 130 +#define GLUI_EDITTEXT_MIN_INT_WIDTH 35 +#define GLUI_EDITTEXT_MIN_TEXT_WIDTH 50 +#define GLUI_PANEL_NAME_DROP 8 +#define GLUI_PANEL_EMBOSS_TOP 4 +/* #define GLUI_ROTATION_WIDTH 60 */ +/* #define GLUI_ROTATION_HEIGHT 78 */ +#define GLUI_ROTATION_WIDTH 50 +#define GLUI_ROTATION_HEIGHT (GLUI_ROTATION_WIDTH+18) +#define GLUI_MOUSE_INTERACTION_WIDTH 50 +#define GLUI_MOUSE_INTERACTION_HEIGHT (GLUI_MOUSE_INTERACTION_WIDTH)+18 + +/** Different panel control types **/ +#define GLUI_PANEL_NONE 0 +#define GLUI_PANEL_EMBOSSED 1 +#define GLUI_PANEL_RAISED 2 + +/** Max # of els in control's float_array **/ +#define GLUI_DEF_MAX_ARRAY 30 + +/********* The control's 'active' behavior *********/ +#define GLUI_CONTROL_ACTIVE_MOUSEDOWN 1 +#define GLUI_CONTROL_ACTIVE_PERMANENT 2 + +/********* Control alignment types **********/ +#define GLUI_ALIGN_CENTER 1 +#define GLUI_ALIGN_RIGHT 2 +#define GLUI_ALIGN_LEFT 3 + +/********** Limit types - how to limit spinner values *********/ +#define GLUI_LIMIT_NONE 0 +#define GLUI_LIMIT_CLAMP 1 +#define GLUI_LIMIT_WRAP 2 + +/********** Translation control types ********************/ +#define GLUI_TRANSLATION_XY 0 +#define GLUI_TRANSLATION_Z 1 +#define GLUI_TRANSLATION_X 2 +#define GLUI_TRANSLATION_Y 3 + +#define GLUI_TRANSLATION_LOCK_NONE 0 +#define GLUI_TRANSLATION_LOCK_X 1 +#define GLUI_TRANSLATION_LOCK_Y 2 + +/********** How was a control activated? *****************/ +#define GLUI_ACTIVATE_MOUSE 1 +#define GLUI_ACTIVATE_TAB 2 + +/********** What type of live variable does a control have? **********/ +#define GLUI_LIVE_NONE 0 +#define GLUI_LIVE_INT 1 +#define GLUI_LIVE_FLOAT 2 +#define GLUI_LIVE_TEXT 3 +#define GLUI_LIVE_STRING 6 +#define GLUI_LIVE_DOUBLE 4 +#define GLUI_LIVE_FLOAT_ARRAY 5 + +/************* Textbox and List Defaults - JVK ******************/ +#define GLUI_TEXTBOX_HEIGHT 130 +#define GLUI_TEXTBOX_WIDTH 130 +#define GLUI_LIST_HEIGHT 130 +#define GLUI_LIST_WIDTH 130 +#define GLUI_DOUBLE_CLICK 1 +#define GLUI_SINGLE_CLICK 0 +#define GLUI_TAB_WIDTH 50 /* In pixels */ +#define GLUI_TEXTBOX_BOXINNERMARGINX 3 +#define GLUI_TEXTBOX_MIN_TEXT_WIDTH 50 +#define GLUI_LIST_BOXINNERMARGINX 3 +#define GLUI_LIST_MIN_TEXT_WIDTH 50 + +/*********************** TreePanel Defaults - JVK *****************************/ +#define GLUI_TREEPANEL_DEFAULTS 0 // bar, standard bar color +#define GLUI_TREEPANEL_ALTERNATE_COLOR 1 // Alternate between 8 different bar colors +#define GLUI_TREEPANEL_ENABLE_BAR 2 // enable the bar +#define GLUI_TREEPANEL_DISABLE_BAR 4 // disable the bar +#define GLUI_TREEPANEL_DISABLE_DEEPEST_BAR 8 // disable only the deepest bar +#define GLUI_TREEPANEL_CONNECT_CHILDREN_ONLY 16 // disable only the bar of the last child of each root +#define GLUI_TREEPANEL_DISPLAY_HIERARCHY 32 // display some sort of hierachy in the tree node title +#define GLUI_TREEPANEL_HIERARCHY_NUMERICDOT 64 // display hierarchy in 1.3.2 (etc... ) format +#define GLUI_TREEPANEL_HIERARCHY_LEVEL_ONLY 128 // display hierarchy as only the level depth + +/******************* GLUI Scrollbar Defaults - JVK ***************************/ +#define GLUI_SCROLL_ARROW_WIDTH 16 +#define GLUI_SCROLL_ARROW_HEIGHT 16 +#define GLUI_SCROLL_BOX_MIN_HEIGHT 5 +#define GLUI_SCROLL_BOX_STD_HEIGHT 16 +#define GLUI_SCROLL_STATE_NONE 0 +#define GLUI_SCROLL_STATE_UP 1 +#define GLUI_SCROLL_STATE_DOWN 2 +#define GLUI_SCROLL_STATE_BOTH 3 +#define GLUI_SCROLL_STATE_SCROLL 4 +#define GLUI_SCROLL_DEFAULT_GROWTH_EXP 1.05f +#define GLUI_SCROLL_VERTICAL 0 +#define GLUI_SCROLL_HORIZONTAL 1 + + +/** Size of the character width hash table for faster lookups. + Make sure to keep this a power of two to avoid the slow divide. + This is also a speed/memory tradeoff; 128 is enough for low ASCII. +*/ +#define CHAR_WIDTH_HASH_SIZE 128 + +/********** Translation codes **********/ + +enum TranslationCodes +{ + GLUI_TRANSLATION_MOUSE_NONE = 0, + GLUI_TRANSLATION_MOUSE_UP, + GLUI_TRANSLATION_MOUSE_DOWN, + GLUI_TRANSLATION_MOUSE_LEFT, + GLUI_TRANSLATION_MOUSE_RIGHT, + GLUI_TRANSLATION_MOUSE_UP_LEFT, + GLUI_TRANSLATION_MOUSE_UP_RIGHT, + GLUI_TRANSLATION_MOUSE_DOWN_LEFT, + GLUI_TRANSLATION_MOUSE_DOWN_RIGHT +}; + +/************ A string type for us to use **********/ + +typedef std::string GLUI_String; +GLUI_String& glui_format_str(GLUI_String &str, const char* fmt, ...); + +/********* Pre-declare classes as needed *********/ + +class GLUI; +class GLUI_Control; +class GLUI_Listbox; +class GLUI_StaticText; +class GLUI_EditText; +class GLUI_Panel; +class GLUI_Spinner; +class GLUI_RadioButton; +class GLUI_RadioGroup; +class GLUI_Glut_Window; +class GLUI_TreePanel; +class GLUI_Scrollbar; +class GLUI_List; + +class Arcball; + +/*** Flags for GLUI class constructor ***/ +#define GLUI_SUBWINDOW ((long)(1<<1)) +#define GLUI_SUBWINDOW_TOP ((long)(1<<2)) +#define GLUI_SUBWINDOW_BOTTOM ((long)(1<<3)) +#define GLUI_SUBWINDOW_LEFT ((long)(1<<4)) +#define GLUI_SUBWINDOW_RIGHT ((long)(1<<5)) + +/*** Codes for different type of edittext boxes and spinners ***/ +#define GLUI_EDITTEXT_TEXT 1 +#define GLUI_EDITTEXT_INT 2 +#define GLUI_EDITTEXT_FLOAT 3 +#define GLUI_SPINNER_INT GLUI_EDITTEXT_INT +#define GLUI_SPINNER_FLOAT GLUI_EDITTEXT_FLOAT +#define GLUI_SCROLL_INT GLUI_EDITTEXT_INT +#define GLUI_SCROLL_FLOAT GLUI_EDITTEXT_FLOAT +// This is only for deprecated interface +#define GLUI_EDITTEXT_STRING 4 + +/*** Definition of callbacks ***/ +typedef void (*GLUI_Update_CB) (int id); +typedef void (*GLUI_Control_CB)(GLUI_Control *); +typedef void (*Int1_CB) (int); +typedef void (*Int2_CB) (int, int); +typedef void (*Int3_CB) (int, int, int); +typedef void (*Int4_CB) (int, int, int, int); + +/************************************************************/ +/** + Callback Adapter Class + Allows us to support different types of callbacks; + like a GLUI_Update_CB function pointer--which takes an int; + and a GLUI_Control_CB function pointer--which takes a GUI_Control object. +*/ +class GLUI_CB +{ +public: + GLUI_CB() : idCB(0),objCB(0) {} + GLUI_CB(GLUI_Update_CB cb) : idCB(cb),objCB(0) {} + GLUI_CB(GLUI_Control_CB cb) : idCB(0),objCB(cb) {} + // (Compiler generated copy constructor) + + /** This control just activated. Fire our callback.*/ + void operator()(GLUI_Control *ctrl) const; + bool operator!() const { return !idCB && !objCB; } + operator bool() const { return !(!(*this)); } +private: + GLUI_Update_CB idCB; + GLUI_Control_CB objCB; +}; + +/************************************************************/ +/* */ +/* Base class, for hierarchical relationships */ +/* */ +/************************************************************/ + +class GLUI_Control; +class GLUI_Column; +class GLUI_Panel; +class GLUI_FileBrowser; +class GLUI_Scrollbar; +class GLUI_Listbox; +class GLUI_List; +class GLUI_Rollout; +class GLUI_Tree; + + +/** + GLUI_Node is a node in a sort of tree of GLUI controls. + Each GLUI_Node has a list of siblings (in a circular list) + and a linked list of children. + + Everything onscreen is a GLUI_Node--windows, buttons, etc. + The nodes are traversed for event processing, sizing, redraws, etc. +*/ +class GLUI_Node +{ + friend class GLUI_Tree; /* JVK */ + friend class GLUI_Rollout; + friend class GLUI_Main; + +public: + GLUI_Node(); + virtual ~GLUI_Node() {} + + GLUI_Node *first_sibling(); + GLUI_Node *last_sibling(); + GLUI_Node *prev(); + GLUI_Node *next(); + + GLUI_Node *first_child() { return child_head; } + GLUI_Node *last_child() { return child_tail; } + GLUI_Node *parent() { return parent_node; } + + /** Link in a new child control */ + virtual int add_control( GLUI_Control *control ); + + void link_this_to_parent_last (GLUI_Node *parent ); + void link_this_to_parent_first(GLUI_Node *parent ); + void link_this_to_sibling_next(GLUI_Node *sibling ); + void link_this_to_sibling_prev(GLUI_Node *sibling ); + void unlink(); + + void dump( FILE *out, const char *name ); + + virtual GLUI_Panel* dynamicCastGLUI_Panel() + { + return 0; + } + + virtual GLUI_Column* dynamicCastGLUI_Column() + { + return 0; + } + virtual GLUI_EditText* dynamicCastGLUI_EditText() + { + return 0; + } + virtual GLUI_Rollout* dynamicCastGLUI_Rollout() + { + return 0; + } + + virtual GLUI_Tree* dynamicCastGLUI_Tree() + { + return 0; + } + + virtual GLUI_List* dynamicCastGLUI_List() + { + return 0; + } + + virtual GLUI_FileBrowser* dynamicCastGLUI_FileBrowser() + { + return 0; + } + + virtual GLUI_Scrollbar* dynamicCastGLUI_Scrollbar() + { + return 0; + } + + virtual GLUI_Listbox* dynamicCastGLUI_Listbox() + { + return 0; + } + + virtual GLUI_TreePanel* dynamicCastGLUI_TreePanel() + { + return 0; + } + + + +protected: + static void add_child_to_control(GLUI_Node *parent,GLUI_Control *child); + GLUI_Node *parent_node; + GLUI_Node *child_head; + GLUI_Node *child_tail; + GLUI_Node *next_sibling; + GLUI_Node *prev_sibling; +}; + + +/************************************************************/ +/* */ +/* Standard Bitmap stuff */ +/* */ +/************************************************************/ + +enum GLUI_StdBitmaps_Codes +{ + GLUI_STDBITMAP_CHECKBOX_OFF = 0, + GLUI_STDBITMAP_CHECKBOX_ON, + GLUI_STDBITMAP_RADIOBUTTON_OFF, + GLUI_STDBITMAP_RADIOBUTTON_ON, + GLUI_STDBITMAP_UP_ARROW, + GLUI_STDBITMAP_DOWN_ARROW, + GLUI_STDBITMAP_LEFT_ARROW, + GLUI_STDBITMAP_RIGHT_ARROW, + GLUI_STDBITMAP_SPINNER_UP_OFF, + GLUI_STDBITMAP_SPINNER_UP_ON, + GLUI_STDBITMAP_SPINNER_DOWN_OFF, + GLUI_STDBITMAP_SPINNER_DOWN_ON, + GLUI_STDBITMAP_CHECKBOX_OFF_DIS, /*** Disactivated control bitmaps ***/ + GLUI_STDBITMAP_CHECKBOX_ON_DIS, + GLUI_STDBITMAP_RADIOBUTTON_OFF_DIS, + GLUI_STDBITMAP_RADIOBUTTON_ON_DIS, + GLUI_STDBITMAP_SPINNER_UP_DIS, + GLUI_STDBITMAP_SPINNER_DOWN_DIS, + GLUI_STDBITMAP_LISTBOX_UP, + GLUI_STDBITMAP_LISTBOX_DOWN, + GLUI_STDBITMAP_LISTBOX_UP_DIS, + GLUI_STDBITMAP_NUM_ITEMS +}; + +/************************************************************/ +/* */ +/* Class GLUI_Bitmap */ +/* */ +/************************************************************/ + +/** + GLUI_Bitmap is a simple 2D texture map. It's used + to represent small textures like checkboxes, arrows, etc. + via the GLUI_StdBitmaps class. +*/ +class GLUI_Bitmap +{ + friend class GLUI_StdBitmaps; + +public: + GLUI_Bitmap(); + ~GLUI_Bitmap(); + + /** Create bitmap from greyscale byte image */ + void init_grey(unsigned char *array); + + /** Create bitmap from color int image */ + void init(int *array); + +private: + /** RGB pixel data */ + unsigned char *pixels; + int w, h; +}; + + +/************************************************************/ +/* */ +/* Class GLUI_StdBitmap */ +/* */ +/************************************************************/ + +/** + Keeps an array of GLUI_Bitmap objects to represent all the + images used in the UI: checkboxes, arrows, etc. +*/ +class GLUI_StdBitmaps +{ +public: + GLUI_StdBitmaps(); + ~GLUI_StdBitmaps(); + + /** Return the width (in pixels) of the n'th standard bitmap. */ + int width (int n) const; + /** Return the height (in pixels) of the n'th standard bitmap. */ + int height(int n) const; + + /** Draw the n'th standard bitmap (one of the enums + listed in GLUI_StdBitmaps_Codes) at pixel corner (x,y). + */ + void draw(int n, int x, int y) const; + +private: + GLUI_Bitmap bitmaps[GLUI_STDBITMAP_NUM_ITEMS]; +}; + +/************************************************************/ +/* */ +/* Master GLUI Class */ +/* */ +/************************************************************/ + +/** + The master manages our interaction with GLUT. + There's only one GLUI_Master_Object. +*/ +class GLUI_Master_Object +{ + + friend void glui_idle_func(); + +public: + + GLUI_Master_Object(); + ~GLUI_Master_Object(); + + GLUI_Node gluis; + GLUI_Control *active_control, *curr_left_button_glut_menu; + GLUI *active_control_glui; + int glui_id_counter; + + GLUI_Glut_Window *find_glut_window( int window_id ); + + void set_glutIdleFunc(void (*f)(void)); + + /************** + void (*glut_keyboard_CB)(unsigned char, int, int); + void (*glut_reshape_CB)(int, int); + void (*glut_special_CB)(int, int, int); + void (*glut_mouse_CB)(int,int,int,int); + + void (*glut_passive_motion_CB)(int,int); + void (*glut_visibility_CB)(int); + void (*glut_motion_CB)(int,int); + void (*glut_display_CB)(void); + void (*glut_entry_CB)(int); + **********/ + + void set_left_button_glut_menu_control( GLUI_Control *control ); + + /********** GLUT callthroughs **********/ + /* These are the glut callbacks that we do not handle */ + + void set_glutReshapeFunc (void (*f)(int width, int height)); + void set_glutKeyboardFunc(void (*f)(unsigned char key, int x, int y)); + void set_glutSpecialFunc (void (*f)(int key, int x, int y)); + void set_glutSpecialUpFunc(void (*f)(int key, int x, int y)); + + void set_glutMouseFunc (void (*f)(int, int, int, int )); + + void set_glutDisplayFunc(void (*f)(void)) {glutDisplayFunc(f);} + void set_glutTimerFunc(unsigned int millis, void (*f)(int value), int value) + { ::glutTimerFunc(millis,f,value);} + void set_glutOverlayDisplayFunc(void(*f)(void)){glutOverlayDisplayFunc(f);} + void set_glutSpaceballMotionFunc(Int3_CB f) {glutSpaceballMotionFunc(f);} + void set_glutSpaceballRotateFunc(Int3_CB f) {glutSpaceballRotateFunc(f);} + void set_glutSpaceballButtonFunc(Int2_CB f) {glutSpaceballButtonFunc(f);} + void set_glutTabletMotionFunc(Int2_CB f) {glutTabletMotionFunc(f);} + void set_glutTabletButtonFunc(Int4_CB f) {glutTabletButtonFunc(f);} + /* void set_glutWindowStatusFunc(Int1_CB f) {glutWindowStatusFunc(f);} */ + void set_glutMenuStatusFunc(Int3_CB f) {glutMenuStatusFunc(f);} + void set_glutMenuStateFunc(Int1_CB f) {glutMenuStateFunc(f);} + void set_glutButtonBoxFunc(Int2_CB f) {glutButtonBoxFunc(f);} + void set_glutDialsFunc(Int2_CB f) {glutDialsFunc(f);} + + + GLUI *create_glui( const char *name, long flags=0, int x=-1, int y=-1 ); + GLUI *create_glui_subwindow( int parent_window, long flags=0 ); + GLUI *find_glui_by_window_id( int window_id ); + void get_viewport_area( int *x, int *y, int *w, int *h ); + void auto_set_viewport(); + void close_all(); + void sync_live_all(); + + void reshape(); + + float get_version() { return GLUI_VERSION; } + + void glui_setIdleFuncIfNecessary(void); + +private: + GLUI_Node glut_windows; + void (*glut_idle_CB)(void); + + void add_cb_to_glut_window(int window,int cb_type,void *cb); +}; + +/** + This is the only GLUI_Master_Object in existence. +*/ +extern GLUI_Master_Object GLUI_Master; + +/************************************************************/ +/* */ +/* Class for managing a GLUT window */ +/* */ +/************************************************************/ + +/** + A top-level window. The GLUI_Master GLUT callback can route events + to the callbacks in this class, for arbitrary use by external users. + (see GLUI_Master_Object::set_glutKeyboardFunc). + + This entire approach seems to be superceded by the "subwindow" flavor + of GLUI. +*/ +class GLUI_Glut_Window : public GLUI_Node +{ +public: + GLUI_Glut_Window(); + + int glut_window_id; + + /*********** Pointers to GLUT callthrough functions *****/ + void (*glut_keyboard_CB)(unsigned char, int, int); + void (*glut_special_CB)(int, int, int); + void (*glut_special_up_CB)(int, int, int); + void (*glut_reshape_CB)(int, int); + void (*glut_passive_motion_CB)(int,int); + void (*glut_mouse_CB)(int,int,int,int); + void (*glut_visibility_CB)(int); + void (*glut_motion_CB)(int,int); + void (*glut_display_CB)(void); + void (*glut_entry_CB)(int); +}; + +/************************************************************/ +/* */ +/* Main Window GLUI class (not user-level) */ +/* */ +/************************************************************/ + +/** + A GLUI_Main handles GLUT events for one window, routing them to the + appropriate controls. The central user-visible "GLUI" class + inherits from this class; users should not allocate GLUT_Main objects. + + There's a separate GLUI_Main object for: + - Each top-level window with GUI stuff in it. + - Each "subwindow" of another top-level window. + + All the GLUI_Main objects are listed in GLUI_Master.gluis. + A better name for this class might be "GLUI_Environment"; + this class provides the window-level context for every control. +*/ +class GLUI_Main : public GLUI_Node +{ + /********** Friend classes *************/ + + friend class GLUI_Control; + friend class GLUI_Rotation; + friend class GLUI_Translation; + friend class GLUI; + friend class GLUI_Master_Object; + + /*********** Friend functions **********/ + + friend void glui_mouse_func(int button, int state, int x, int y); + friend void glui_keyboard_func(unsigned char key, int x, int y); + friend void glui_special_func(int key, int x, int y); + friend void glui_special_up_func(int key, int x, int y); + friend void glui_passive_motion_func(int x, int y); + friend void glui_reshape_func( int w, int h ); + friend void glui_visibility_func(int state); + friend void glui_motion_func(int x, int y); + friend void glui_entry_func(int state); + friend void glui_display_func( void ); + friend void glui_idle_func(void); + + friend void glui_parent_window_reshape_func( int w, int h ); + friend void glui_parent_window_keyboard_func( unsigned char, int, int ); + friend void glui_parent_window_special_func( int, int, int ); + friend void glui_parent_window_mouse_func( int, int, int, int ); + +protected: + /*** Variables ***/ + int main_gfx_window_id; + int mouse_button_down; + int glut_window_id; + int top_level_glut_window_id; + GLUI_Control *active_control; + GLUI_Control *mouse_over_control; + GLUI_Panel *main_panel; + enum buffer_mode_t { + buffer_front=1, ///< Draw updated controls directly to screen. + buffer_back=2 ///< Double buffering: postpone updates until next redraw. + }; + buffer_mode_t buffer_mode; ///< Current drawing mode + int curr_cursor; + int w, h; + long flags; + bool closing; + int parent_window; + int glui_id; + + /********** Misc functions *************/ + + GLUI_Control *find_control( int x, int y ); + GLUI_Control *find_next_control( GLUI_Control *control ); + GLUI_Control *find_next_control_rec( GLUI_Control *control ); + GLUI_Control *find_next_control_( GLUI_Control *control ); + GLUI_Control *find_prev_control( GLUI_Control *control ); + void create_standalone_window( const char *name, int x=-1, int y=-1 ); + void create_subwindow( int parent,int window_alignment ); + void setup_default_glut_callbacks( void ); + + void mouse(int button, int state, int x, int y); + void keyboard(unsigned char key, int x, int y); + void special(int key, int x, int y); + void special_up(int key, int x, int y); + void passive_motion(int x, int y); + void reshape( int w, int h ); + void visibility(int state); + void motion(int x, int y); + void entry(int state); + void display( void ); + void idle(void); + int needs_idle(void); + + void (*glut_mouse_CB)(int, int, int, int); + void (*glut_keyboard_CB)(unsigned char, int, int); + void (*glut_special_CB)(int, int, int); + void (*glut_reshape_CB)(int, int); + + + /*********** Controls ************/ + + virtual int add_control( GLUI_Node *parent, GLUI_Control *control ); + + + /********** Constructors and Destructors ***********/ + + GLUI_Main( void ); + +public: + GLUI_StdBitmaps std_bitmaps; + GLUI_String window_name; + RGBc bkgd_color; + float bkgd_color_f[3]; + + void *font; + int curr_modifiers; + + void adjust_glut_xy( int &x, int &y ) { (void)x; y = h-y; } + void activate_control( GLUI_Control *control, int how ); + void align_controls( GLUI_Control *control ); + void deactivate_current_control( void ); + + /** Draw a 3D-look pushed-out box around this rectangle */ + void draw_raised_box( int x, int y, int w, int h ); + /** Draw a 3D-look pushed-in box around this rectangle */ + void draw_lowered_box( int x, int y, int w, int h ); + + /** Return true if this control should redraw itself immediately (front buffer); + Or queue up a redraw and return false if it shouldn't (back buffer). + */ + bool should_redraw_now(GLUI_Control *ctl); + + int getMainWindowId() + { + return main_gfx_window_id; + } + /** Switch to the appropriate draw buffer now. Returns the old draw buffer. + This routine should probably only be called from inside the GLUI_DrawingSentinal, + in glui_internal_control.h + */ + int set_current_draw_buffer(); + /** Go back to using this draw buffer. Undoes set_current_draw_buffer. */ + void restore_draw_buffer( int buffer_state ); + + /** Pack, resize the window, and redraw all the controls. */ + void refresh(); + + /** Redraw the main graphics window */ + void post_update_main_gfx(); + + /** Recompute the sizes and positions of all controls */ + void pack_controls(); + + void close_internal(); + void check_subwindow_position(); + void set_ortho_projection(); + void set_viewport(); + int get_glut_window_id( void ) { return glut_window_id; } /* JVK */ +}; + +/************************************************************/ +/* */ +/* GLUI_Control: base class for all controls */ +/* */ +/************************************************************/ + +//get rid of the dynamic_cast/RTTI requirements, just do a virtual function + + +/** + All the GUI objects inherit from GLUI_Control: buttons, + checkboxes, labels, edit boxes, scrollbars, etc. + Most of the work of this class is in routing events, + like keystrokes, mouseclicks, redraws, and sizing events. + + Yes, this is a huge and hideous class. It needs to be + split up into simpler subobjects. None of the data members + should be directly accessed by users (they should be protected, + not public); only subclasses. +*/ +class GLUI_Control : public GLUI_Node +{ +public: + +/** Onscreen coordinates */ + int w, h; /* dimensions of control */ + int x_abs, y_abs; + int x_off, y_off_top, y_off_bot; /* INNER margins, by which child + controls are indented */ + int contain_x, contain_y; + int contain_w, contain_h; + /* if this is a container control (e.g., + radiogroup or panel) this indicated dimensions + of inner area in which controls reside */ + +/** "activation" for tabbing between controls. */ + int active_type; ///< "GLUI_CONTROL_ACTIVE_..." + bool active; ///< If true, we've got the focus + bool can_activate; ///< If false, remove from tab order. + bool spacebar_mouse_click; ///< Spacebar simulates click. + +/** Callbacks */ + long user_id; ///< Integer to pass to callback function. + GLUI_CB callback; ///< User callback function, or NULL. + +/** Variable value storage */ + float float_val; /**< Our float value */ + int int_val; /**< Our integer value */ + float float_array_val[GLUI_DEF_MAX_ARRAY]; + int float_array_size; + GLUI_String text; /**< The text inside this control */ + +/** "Live variable" updating */ + void *ptr_val; /**< A pointer to the user's live variable value */ + int live_type; + bool live_inited; + /* These variables store the last value that live variable was known to have. */ + int last_live_int; + float last_live_float; + GLUI_String last_live_text; + float last_live_float_array[GLUI_DEF_MAX_ARRAY]; + +/** Properties of our control */ + GLUI *glui; /**< Our containing event handler (NEVER NULL during event processing!) */ + bool is_container; /**< Is this a container class (e.g., panel) */ + int alignment; + bool enabled; /**< Is this control grayed out? */ + GLUI_String name; /**< The name of this control */ + void *font; /**< Our glutbitmap font */ + bool collapsible, is_open; + GLUI_Node collapsed_node; + bool hidden; /* Collapsed controls (and children) are hidden */ + int char_widths[CHAR_WIDTH_HASH_SIZE][2]; /* Character width hash table */ + +public: + /*** Get/Set values ***/ + virtual void set_name( const char *string ); + virtual void set_int_val( int new_int ) { int_val = new_int; output_live(true); } + virtual void set_float_val( float new_float ) { float_val = new_float; output_live(true); } + virtual void set_ptr_val( void *new_ptr ) { ptr_val = new_ptr; output_live(true); } + virtual void set_float_array_val( float *array_ptr ); + + virtual float get_float_val( void ) { return float_val; } + virtual int get_int_val( void ) { return int_val; } + virtual void get_float_array_val( float *array_ptr ); + virtual int get_id( void ) const { return user_id; } + virtual void set_id( int id ) { user_id=id; } + + virtual int mouse_down_handler( int local_x, int local_y ) { (void)local_x; (void)local_y; return false; } + virtual int mouse_up_handler( int local_x, int local_y, bool inside ) { (void)local_x; (void)local_y; (void)inside; return false; } + virtual int mouse_held_down_handler( int local_x, int local_y, bool inside) { (void)local_x; (void)local_y; (void)inside; return false; } + virtual int key_handler( unsigned char key, int modifiers ) { (void)key; (void)modifiers; return false; } + virtual int special_handler( int key,int modifiers ) { (void)key; (void)modifiers; return false; } + virtual int special_up_handler( int key,int modifiers ) { (void)key; (void)modifiers; return false; } + + virtual void update_size( void ) { } + virtual void idle( void ) { } + virtual int mouse_over( int state, int x, int y ) { (void)state; (void)x; (void)y; return false; } + + virtual void enable( void ); + virtual void disable( void ); + virtual void activate( int how ) { (void)how; active = true; } + virtual void deactivate( void ) { active = false; } + + /** Hide (shrink into a rollout) and unhide (expose from a rollout) */ + void hide_internal( int recurse ); + void unhide_internal( int recurse ); + + + /** Return true if it currently makes sense to draw this class. */ + int can_draw( void ) { return (glui != NULL && hidden == false); } + + /** Redraw this control. + In single-buffering mode (drawing to GL_FRONT), this is just + a call to translate_and_draw_front (after a can_draw() check). + In double-buffering mode (drawing to GL_BACK), this queues up + a redraw and returns false, since you shouldn't draw yet. + */ + void redraw(void); + + /** Redraw everybody in our window. */ + void redraw_window(void); + + virtual void align( void ); + void pack( int x, int y ); /* Recalculate positions and offsets */ + void pack_old( int x, int y ); + void draw_recursive( int x, int y ); + int set_to_glut_window( void ); + void restore_window( int orig ); + void translate_and_draw_front( void ); + void translate_to_origin( void ) + {glTranslatef((float)x_abs+.5f,(float)y_abs+.5f,0.0f);} + virtual void draw( int x, int y )=0; + void set_font( void *new_font ); + void *get_font( void ); + int string_width( const char *text ); + int string_width( const GLUI_String &str ) + { return string_width(str.c_str()); } + int char_width( char c ); + + void draw_name( int x, int y ); + void draw_box_inwards_outline( int x_min, int x_max, + int y_min, int y_max ); + void draw_box( int x_min, int x_max, int y_min, int y_max, + float r, float g, float b ); + void draw_bkgd_box( int x_min, int x_max, int y_min, int y_max ); + void draw_emboss_box( int x_min, int x_max,int y_min,int y_max); + void draw_string( const char *text ); + void draw_string( const GLUI_String &s ) + { draw_string(s.c_str()); } + void draw_char( char c ); + void draw_active_box( int x_min, int x_max, int y_min, int y_max ); + void set_to_bkgd_color( void ); + + void set_w( int new_w ); + void set_h( int new_w ); + void set_alignment( int new_align ); + void sync_live( int recurse, int draw ); /* Reads live variable */ + void init_live( void ); + void output_live( int update_main_gfx ); /** Writes live variable **/ + virtual void set_text( const char *t ) { (void)t; } + void execute_callback( void ); + void get_this_column_dims( int *col_x, int *col_y, + int *col_w, int *col_h, + int *col_x_off, int *col_y_off ); + virtual bool needs_idle( void ) const; + virtual bool wants_tabs() const { return false; } + + GLUI_Control(void) + { + x_off = GLUI_XOFF; + y_off_top = GLUI_YOFF; + y_off_bot = GLUI_YOFF; + x_abs = GLUI_XOFF; + y_abs = GLUI_YOFF; + active = false; + enabled = true; + int_val = 0; + last_live_int = 0; + float_array_size = 0; + glui_format_str(name, "Control: %p", this); + float_val = 0.0; + last_live_float = 0.0; + ptr_val = NULL; + glui = NULL; + w = GLUI_DEFAULT_CONTROL_WIDTH; + h = GLUI_DEFAULT_CONTROL_HEIGHT; + font = NULL; + active_type = GLUI_CONTROL_ACTIVE_MOUSEDOWN; + alignment = GLUI_ALIGN_LEFT; + is_container = false; + can_activate = true; /* By default, you can activate a control */ + spacebar_mouse_click = true; /* Does spacebar simulate a mouse click? */ + live_type = GLUI_LIVE_NONE; + text = ""; + last_live_text == ""; + live_inited = false; + collapsible = false; + is_open = true; + hidden = false; + memset(char_widths, -1, sizeof(char_widths)); /* JVK */ + int i; + for( i=0; iint_val = 1; set_color(red, green, blue); } } + void disable_bar() { if (column) { column->int_val = 0; } } + void set_child_number(int c) { child_number = c; } + void set_level_color(float r, float g, float b) { + lred = r; + lgreen = g; + lblue = b; + } + void set_color(float r, float g, float b) { + red = r; + green = g; + blue = b; + } + + virtual GLUI_Tree* dynamicCastGLUI_Tree() + { + return this; + } +protected: + void common_init() + { + currently_inside = false; + initially_inside = false; + can_activate = true; + is_container = true; + h = GLUI_DEFAULT_CONTROL_HEIGHT + 7; + w = GLUI_DEFAULT_CONTROL_WIDTH; + y_off_top = 21; + collapsible = true; + red = .5; + green = .5; + blue = .5; + lred = 0; + lgreen = 0; + lblue = 0; + column = NULL; + is_current = 0; + child_number = 0; + format = 0; + panel = NULL; + name = ""; + level_name = ""; + level = 0; + + }; +}; + + +/************************************************************/ +/* */ +/* TreePanel class (container) JVK */ +/* */ +/************************************************************/ + +/** + Manages, maintains, and formats a tree of GLUI_Tree objects. + These are shown in a heirarchical, collapsible display. + + FIXME: There's an infinite loop in the traversal code (OSL 2006/06) +*/ +class GLUI_TreePanel : public GLUI_Panel +{ +public: + GLUI_TreePanel(GLUI_Node *parent, const char *name, + bool open=false, int inset=0); + + int max_levels; + int next_id; + int format; + float red; + float green; + float blue; + float lred; + float lgreen; + float lblue; + int root_children; + /* These variables allow the tree panel to traverse the tree + using only two function calls. (Well, four, if you count + going in reverse */ + + GLUI_Tree *curr_branch; /* Current Branch */ + GLUI_Panel *curr_root; /* Current Root */ + +public: + void set_color(float r, float g, float b); + void set_level_color(float r, float g, float b); + void set_format(int f) { format = f; } + + /* Adds branch to curr_root */ + GLUI_Tree * ab(const char *name, GLUI_Tree *root = NULL); + /* Goes up one level, resets curr_root and curr_branch to parents*/ + void fb(GLUI_Tree *branch= NULL); + /* Deletes the curr_branch, goes up one level using fb */ + void db(GLUI_Tree *branch = NULL); + /* Finds the very last branch of curr_root, resets vars */ + void descendBranch(GLUI_Panel *root = NULL); + /* Resets curr_root and curr branch to TreePanel and lastChild */ + void resetToRoot(GLUI_Panel *new_root = NULL); + void next( void ); + void refresh( void ); + void expand_all( void ); + void collapse_all( void ); + void update_all( void ); + void initNode(GLUI_Tree *temp); + void formatNode(GLUI_Tree *temp); + virtual GLUI_TreePanel* dynamicCastGLUI_TreePanel() + { + return this; + } + +protected: + int uniqueID( void ) { next_id++; return next_id - 1; } + void common_init() + { + GLUI_Panel(); + next_id = 0; + curr_root = this; + curr_branch = NULL; + red = .5; + green = .5; + blue = .5; + root_children = 0; + } +}; + +/************************************************************/ +/* */ +/* User-Level GLUI class */ +/* */ +/************************************************************/ + +class GLUI_Rotation; +class GLUI_Translation; + +/** + The main user-visible interface object to GLUI. + +*/ +class GLUI : public GLUI_Main +{ +public: +/** DEPRECATED interface for creating new GLUI objects */ + int add_control( GLUI_Control *control ) { return main_panel->add_control(control); } + + void add_column( int draw_bar = true ); + void add_column_to_panel( GLUI_Panel *panel, int draw_bar = true ); + + void add_separator( void ); + void add_separator_to_panel( GLUI_Panel *panel ); + + GLUI_RadioGroup + *add_radiogroup( int *live_var=NULL, + int user_id=-1,GLUI_CB callback=GLUI_CB()); + + GLUI_RadioGroup + *add_radiogroup_to_panel( GLUI_Panel *panel, + int *live_var=NULL, + int user_id=-1, GLUI_CB callback=GLUI_CB() ); + GLUI_RadioButton + *add_radiobutton_to_group( GLUI_RadioGroup *group, + const char *name ); + + GLUI_Listbox *add_listbox( const char *name, int *live_var=NULL, + int id=-1, GLUI_CB callback=GLUI_CB() ); + GLUI_Listbox *add_listbox_to_panel( GLUI_Panel *panel, + const char *name, int *live_var=NULL, + int id=-1, GLUI_CB callback=GLUI_CB()); + + GLUI_Rotation *add_rotation( const char *name, float *live_var=NULL, + int id=-1, GLUI_CB callback=GLUI_CB() ); + GLUI_Rotation *add_rotation_to_panel( GLUI_Panel *panel, + const char *name, float *live_var=NULL, + int id=-1, GLUI_CB callback=GLUI_CB()); + + GLUI_Translation *add_translation( const char *name, + int trans_type, float *live_var=NULL, + int id=-1, GLUI_CB callback=GLUI_CB() ); + GLUI_Translation *add_translation_to_panel( + GLUI_Panel *panel, const char *name, + int trans_type, float *live_var=NULL, + int id=-1, GLUI_CB callback=GLUI_CB()); + + GLUI_Checkbox *add_checkbox( const char *name, + int *live_var=NULL, + int id=-1, GLUI_CB callback=GLUI_CB()); + GLUI_Checkbox *add_checkbox_to_panel( GLUI_Panel *panel, const char *name, + int *live_var=NULL, int id=-1, + GLUI_CB callback=GLUI_CB()); + + GLUI_Button *add_button( const char *name, int id=-1, + GLUI_CB callback=GLUI_CB()); + GLUI_Button *add_button_to_panel( GLUI_Panel *panel, const char *name, + int id=-1, GLUI_CB callback=GLUI_CB() ); + + GLUI_StaticText *add_statictext( const char *name ); + GLUI_StaticText *add_statictext_to_panel( GLUI_Panel *panel, const char *name ); + + GLUI_EditText *add_edittext( const char *name, + int data_type=GLUI_EDITTEXT_TEXT, + void*live_var=NULL, + int id=-1, GLUI_CB callback=GLUI_CB() ); + GLUI_EditText *add_edittext_to_panel( GLUI_Panel *panel, + const char *name, + int data_type=GLUI_EDITTEXT_TEXT, + void *live_var=NULL, int id=-1, + GLUI_CB callback=GLUI_CB() ); + GLUI_EditText *add_edittext( const char *name, GLUI_String& live_var, + int id=-1, GLUI_CB callback=GLUI_CB() ); + GLUI_EditText *add_edittext_to_panel( GLUI_Panel *panel, const char *name, + GLUI_String& live_var, int id=-1, + GLUI_CB callback=GLUI_CB() ); + + GLUI_Spinner *add_spinner( const char *name, + int data_type=GLUI_SPINNER_INT, + void *live_var=NULL, + int id=-1, GLUI_CB callback=GLUI_CB() ); + GLUI_Spinner *add_spinner_to_panel( GLUI_Panel *panel, + const char *name, + int data_type=GLUI_SPINNER_INT, + void *live_var=NULL, + int id=-1, + GLUI_CB callback=GLUI_CB() ); + + GLUI_Panel *add_panel( const char *name, int type=GLUI_PANEL_EMBOSSED ); + GLUI_Panel *add_panel_to_panel( GLUI_Panel *panel, const char *name, + int type=GLUI_PANEL_EMBOSSED ); + + + GLUI_Rollout *add_rollout( const char *name, int open=true, + int type=GLUI_PANEL_EMBOSSED); + GLUI_Rollout *add_rollout_to_panel( GLUI_Panel *panel, const char *name, + int open=true, + int type=GLUI_PANEL_EMBOSSED); + + +/** Set the window where our widgets should be displayed. */ + void set_main_gfx_window( int window_id ); + int get_glut_window_id( void ) { return glut_window_id; } + + void enable( void ) { main_panel->enable(); } + void disable( void ); + + void sync_live( void ); + + void close( void ); + + void show( void ); + void hide( void ); + + /***** GLUT callback setup functions *****/ + /* + void set_glutDisplayFunc(void (*f)(void)); + void set_glutReshapeFunc(void (*f)(int width, int height)); + void set_glutKeyboardFunc(void (*f)(unsigned char key, int x, int y)); + void set_glutSpecialFunc(void (*f)(int key, int x, int y)); + void set_glutMouseFunc(void (*f)(int button, int state, int x, int y)); + void set_glutMotionFunc(void (*f)(int x, int y)); + void set_glutPassiveMotionFunc(void (*f)(int x, int y)); + void set_glutEntryFunc(void (*f)(int state)); + void set_glutVisibilityFunc(void (*f)(int state)); + void set_glutInit( int *argcp, const char **argv ); + void set_glutInitWindowSize(int width, int height); + void set_glutInitWindowPosition(int x, int y); + void set_glutInitDisplayMode(unsigned int mode); + int set_glutCreateWindow(const char *name); + */ + + /***** Constructors and desctructors *****/ + + int init( const char *name, long flags, int x, int y, int parent_window ); +protected: + virtual int add_control( GLUI_Node *parent, GLUI_Control *control ) { + return GLUI_Main::add_control( parent, control ); + } +}; + +/************************************************************/ +/* */ +/* EditText class */ +/* */ +/************************************************************/ + +class GLUI_EditText : public GLUI_Control +{ +public: + int has_limits; + int data_type; + GLUI_String orig_text; + int insertion_pt; + int title_x_offset; + int text_x_offset; + int substring_start; /*substring that gets displayed in box*/ + int substring_end; + int sel_start, sel_end; /* current selection */ + int num_periods; + int last_insertion_pt; + float float_low, float_high; + int int_low, int_high; + GLUI_Spinner *spinner; + int debug; + int draw_text_only; + + + int mouse_down_handler( int local_x, int local_y ); + int mouse_up_handler( int local_x, int local_y, bool inside ); + int mouse_held_down_handler( int local_x, int local_y, bool inside ); + int key_handler( unsigned char key,int modifiers ); + int special_handler( int key, int modifiers ); + + void activate( int how ); + void deactivate( void ); + + void draw( int x, int y ); + + int mouse_over( int state, int x, int y ); + + int find_word_break( int start, int direction ); + int substring_width( int start, int end ); + void clear_substring( int start, int end ); + int find_insertion_pt( int x, int y ); + int update_substring_bounds( void ); + void update_and_draw_text( void ); + void draw_text( int x, int y ); + void draw_insertion_pt( void ); + void set_numeric_text( void ); + void update_x_offsets( void ); + void update_size( void ); + + void set_float_limits( float low,float high,int limit_type=GLUI_LIMIT_CLAMP); + void set_int_limits( int low, int high, int limit_type=GLUI_LIMIT_CLAMP ); + void set_float_val( float new_val ); + void set_int_val( int new_val ); + void set_text( const char *text ); + void set_text( const GLUI_String &s) { set_text(s.c_str()); } + const char *get_text() { return text.c_str(); } + + void dump( FILE *out, const char *text ); + + // Constructor, no live variable + GLUI_EditText( GLUI_Node *parent, const char *name, + int text_type=GLUI_EDITTEXT_TEXT, + int id=-1, GLUI_CB callback=GLUI_CB() ); + // Constructor, int live variable + GLUI_EditText( GLUI_Node *parent, const char *name, + int *live_var, + int id=-1, GLUI_CB callback=GLUI_CB() ); + // Constructor, float live variable + GLUI_EditText( GLUI_Node *parent, const char *name, + float *live_var, + int id=-1, GLUI_CB callback=GLUI_CB() ); + // Constructor, char* live variable + GLUI_EditText( GLUI_Node *parent, const char *name, + char *live_var, + int id=-1, GLUI_CB callback=GLUI_CB() ); + // Constructor, std::string live variable + GLUI_EditText( GLUI_Node *parent, const char *name, + std::string &live_var, + int id=-1, GLUI_CB callback=GLUI_CB() ); + + // Deprecated constructor, only called internally + GLUI_EditText( GLUI_Node *parent, const char *name, + int text_type, void *live_var, + int id, GLUI_CB callback ); + // Deprecated constructor, only called internally + GLUI_EditText( void ) { common_init(); } + + virtual GLUI_EditText* dynamicCastGLUI_EditText() + { + return this; + } + + +protected: + void common_init( void ) { + h = GLUI_EDITTEXT_HEIGHT; + w = GLUI_EDITTEXT_WIDTH; + title_x_offset = 0; + text_x_offset = 55; + insertion_pt = -1; + last_insertion_pt = -1; + name = ""; + substring_start = 0; + data_type = GLUI_EDITTEXT_TEXT; + substring_end = 2; + num_periods = 0; + has_limits = GLUI_LIMIT_NONE; + sel_start = 0; + sel_end = 0; + active_type = GLUI_CONTROL_ACTIVE_PERMANENT; + can_activate = true; + spacebar_mouse_click = false; + spinner = NULL; + debug = false; + draw_text_only = false; + } + void common_construct( GLUI_Node *parent, const char *name, + int data_type, int live_type, void *live_var, + int id, GLUI_CB callback ); +}; + +/************************************************************/ +/* */ +/* CommandLine class */ +/* */ +/************************************************************/ + +class GLUI_CommandLine : public GLUI_EditText +{ +public: + typedef GLUI_EditText Super; + + enum { HIST_SIZE = 100 }; + std::vector hist_list; + int curr_hist; + int oldest_hist; + int newest_hist; + bool commit_flag; + +public: + int key_handler( unsigned char key,int modifiers ); + int special_handler( int key,int modifiers ); + void deactivate( void ); + + virtual const char *get_history( int command_number ) const + { return hist_list[command_number - oldest_hist].c_str(); } + virtual GLUI_String& get_history_str( int command_number ) + { return hist_list[command_number - oldest_hist]; } + virtual const GLUI_String& get_history_str( int command_number ) const + { return hist_list[command_number - oldest_hist]; } + virtual void recall_history( int history_number ); + virtual void scroll_history( int direction ); + virtual void add_to_history( const char *text ); + virtual void reset_history( void ); + + void dump( FILE *out, const char *text ); + + + GLUI_CommandLine( GLUI_Node *parent, const char *name, void *live_var=NULL, + int id=-1, GLUI_CB callback=GLUI_CB() ); + GLUI_CommandLine( void ) { common_init(); } +protected: + void common_init() { + hist_list.resize(HIST_SIZE); + curr_hist = 0; + oldest_hist = 0; + newest_hist = 0; + commit_flag = false; + } +}; + +/************************************************************/ +/* */ +/* RadioGroup class (container) */ +/* */ +/************************************************************/ + +class GLUI_RadioGroup : public GLUI_Control +{ +public: + int num_buttons; + + void draw( int x, int y ); + void set_name( const char *text ); + void set_int_val( int int_val ); + void set_selected( int int_val ); + + void draw_group( int translate ); + + GLUI_RadioGroup( GLUI_Node *parent, int *live_var=NULL, + int user_id=-1,GLUI_CB callback=GLUI_CB() ); + GLUI_RadioGroup( void ) { common_init(); } + +protected: + void common_init( void ) { + x_off = 0; + y_off_top = 0; + y_off_bot = 0; + is_container = true; + w = 300; + h = 300; + num_buttons = 0; + name = ""; + can_activate = false; + live_type = GLUI_LIVE_INT; + } +}; + +/************************************************************/ +/* */ +/* RadioButton class (container) */ +/* */ +/************************************************************/ + +class GLUI_RadioButton : public GLUI_Control +{ +public: + int orig_value; + bool currently_inside; + int text_x_offset; + + int mouse_down_handler( int local_x, int local_y ); + int mouse_up_handler( int local_x, int local_y, bool inside ); + int mouse_held_down_handler( int local_x, int local_y, bool inside ); + + void draw( int x, int y ); + void update_size( void ); + + void draw_active_area( void ); + void draw_checked( void ); + void draw_unchecked( void ); + void draw_O( void ); + + GLUI_RadioButton( GLUI_RadioGroup *group, const char *name ); + GLUI_RadioGroup *group; + +protected: + void common_init() + { + glui_format_str( name, "RadioButton: %p", (void *) this ); + h = GLUI_RADIOBUTTON_SIZE; + group = NULL; + orig_value = -1; + text_x_offset = 18; + can_activate = true; + } +}; + + +/************************************************************/ +/* */ +/* Separator class (container) */ +/* */ +/************************************************************/ + +class GLUI_Separator : public GLUI_Control +{ +public: + void draw( int x, int y ); + + GLUI_Separator( GLUI_Node *parent ); + GLUI_Separator( void ) { common_init(); } + +protected: + void common_init() { + w = 100; + h = GLUI_SEPARATOR_HEIGHT; + can_activate = false; + } +}; + +#define GLUI_SPINNER_ARROW_WIDTH 12 +#define GLUI_SPINNER_ARROW_HEIGHT 8 +#define GLUI_SPINNER_ARROW_Y 2 + +#define GLUI_SPINNER_STATE_NONE 0 +#define GLUI_SPINNER_STATE_UP 1 +#define GLUI_SPINNER_STATE_DOWN 2 +#define GLUI_SPINNER_STATE_BOTH 3 + +#define GLUI_SPINNER_DEFAULT_GROWTH_EXP 1.05f + +/************************************************************/ +/* */ +/* Spinner class (container) */ +/* */ +/************************************************************/ + +class GLUI_Spinner : public GLUI_Control +{ +public: + // Constructor, no live var + GLUI_Spinner( GLUI_Node* parent, const char *name, + int data_type=GLUI_SPINNER_INT, int id=-1, GLUI_CB callback=GLUI_CB() ); + // Constructor, int live var + GLUI_Spinner( GLUI_Node* parent, const char *name, + int *live_var, int id=-1, GLUI_CB callback=GLUI_CB() ); + // Constructor, float live var + GLUI_Spinner( GLUI_Node* parent, const char *name, + float *live_var, int id=-1, GLUI_CB callback=GLUI_CB() ); + // Deprecated constructor + GLUI_Spinner( GLUI_Node* parent, const char *name, + int data_type, + void *live_var, + int id=-1, GLUI_CB callback=GLUI_CB() ); + // Deprecated constructor + GLUI_Spinner( void ) { common_init(); } + + bool currently_inside; + int state; + float growth, growth_exp; + int last_x, last_y; + int data_type; + int callback_count; + int last_int_val; + float last_float_val; + int first_callback; + float user_speed; + + GLUI_EditText *edittext; + + int mouse_down_handler( int local_x, int local_y ); + int mouse_up_handler( int local_x, int local_y, bool inside ); + int mouse_held_down_handler( int local_x, int local_y, bool inside ); + int key_handler( unsigned char key,int modifiers ); + int special_handler( int key,int modifiers ); + + void draw( int x, int y ); + void draw_pressed( void ); + void draw_unpressed( void ); + void draw_text( int sunken ); + + void update_size( void ); + + void set_float_limits( float low,float high,int limit_type=GLUI_LIMIT_CLAMP); + void set_int_limits( int low, int high,int limit_type=GLUI_LIMIT_CLAMP); + int find_arrow( int local_x, int local_y ); + void do_drag( int x, int y ); + void do_callbacks( void ); + void do_click( void ); + void idle( void ); + bool needs_idle( void ) const; + + const char *get_text( void ); + + void set_float_val( float new_val ); + void set_int_val( int new_val ); + float get_float_val( void ); + int get_int_val( void ); + void increase_growth( void ); + void reset_growth( void ); + + void set_speed( float speed ) { user_speed = speed; } + +protected: + void common_init() { + glui_format_str( name, "Spinner: %p", this ); + h = GLUI_EDITTEXT_HEIGHT; + w = GLUI_EDITTEXT_WIDTH; + x_off = 0; + y_off_top = 0; + y_off_bot = 0; + can_activate = true; + state = GLUI_SPINNER_STATE_NONE; + edittext = NULL; + growth_exp = GLUI_SPINNER_DEFAULT_GROWTH_EXP; + callback_count = 0; + first_callback = true; + user_speed = 1.0; + } + void common_construct( GLUI_Node* parent, const char *name, + int data_type, void *live_var, + int id, GLUI_CB callback ); +}; + +/************************************************************/ +/* */ +/* StaticText class */ +/* */ +/************************************************************/ + +class GLUI_StaticText : public GLUI_Control +{ +public: + void set_text( const char *text ); + void draw( int x, int y ); + void draw_text( void ); + void update_size( void ); + void erase_text( void ); + + GLUI_StaticText(GLUI_Node *parent, const char *name); + GLUI_StaticText( void ) { common_init(); } + +protected: + void common_init() { + h = GLUI_STATICTEXT_SIZE; + name = ""; + can_activate = false; + } +}; + +/************************************************************/ +/* */ +/* TextBox class - JVK */ +/* */ +/************************************************************/ + +class GLUI_TextBox : public GLUI_Control +{ +public: + /* GLUI Textbox - JVK */ + GLUI_TextBox(GLUI_Node *parent, GLUI_String &live_var, + bool scroll = false, int id=-1, GLUI_CB callback=GLUI_CB() ); + GLUI_TextBox( GLUI_Node *parent, + bool scroll = false, int id=-1, + GLUI_CB callback=GLUI_CB() ); + + GLUI_String orig_text; + int insertion_pt; + int substring_start; /*substring that gets displayed in box*/ + int substring_end; + int sel_start, sel_end; /* current selection */ + int last_insertion_pt; + int debug; + int draw_text_only; + int tab_width; + int start_line; + int num_lines; + int curr_line; + int visible_lines; + int insert_x; /* Similar to "insertion_pt", these variables keep */ + int insert_y; /* track of where the ptr is, but in pixels */ + int keygoal_x; /* where up down keys would like to put insertion pt*/ + GLUI_Scrollbar *scrollbar; + + int mouse_down_handler( int local_x, int local_y ); + int mouse_up_handler( int local_x, int local_y, bool inside ); + int mouse_held_down_handler( int local_x, int local_y, bool inside ); + int key_handler( unsigned char key,int modifiers ); + int special_handler( int key,int modifiers ); + + void activate( int how ); + void deactivate( void ); + + void enable( void ); + void disable( void ); + + void draw( int x, int y ); + + int mouse_over( int state, int x, int y ); + + int get_box_width(); + int find_word_break( int start, int direction ); + int substring_width( int start, int end, int initial_width=0 ); + void clear_substring( int start, int end ); + int find_insertion_pt( int x, int y ); + int update_substring_bounds( void ); + void update_and_draw_text( void ); + void draw_text( int x, int y ); + void draw_insertion_pt( void ); + void update_x_offsets( void ); + void update_size( void ); + + void set_text( const char *text ); + const char *get_text( void ) { return text.c_str(); } + + void dump( FILE *out, const char *text ); + void set_tab_w(int w) { tab_width = w; } + void set_start_line(int l) { start_line = l; } + static void scrollbar_callback(GLUI_Control*); + + bool wants_tabs( void ) const { return true; } + +protected: + void common_init() + { + h = GLUI_TEXTBOX_HEIGHT; + w = GLUI_TEXTBOX_WIDTH; + tab_width = GLUI_TAB_WIDTH; + num_lines = 0; + visible_lines = 0; + start_line = 0; + curr_line = 0; + insert_y = -1; + insert_x = -1; + insertion_pt = -1; + last_insertion_pt = -1; + name[0] = '\0'; + substring_start = 0; + substring_end = 2; + sel_start = 0; + sel_end = 0; + active_type = GLUI_CONTROL_ACTIVE_PERMANENT; + can_activate = true; + spacebar_mouse_click = false; + scrollbar = NULL; + debug = false; + draw_text_only = false; + } + void common_construct( + GLUI_Node *parent, GLUI_String *live_var, + bool scroll, int id, GLUI_CB callback); +}; + +/************************************************************/ +/* */ +/* List class - JVK */ +/* */ +/************************************************************/ + +class GLUI_List_Item : public GLUI_Node +{ +public: + GLUI_String text; + int id; +}; + +/************************************************************/ +/* */ +/* List class - JVK */ +/* */ +/************************************************************/ + +class GLUI_List : public GLUI_Control +{ +public: + /* GLUI List - JVK */ + GLUI_List( GLUI_Node *parent, bool scroll = false, + int id=-1, GLUI_CB callback=GLUI_CB() ); + /*, GLUI_Control *object = NULL + ,GLUI_InterObject_CB obj_cb = NULL);*/ + + GLUI_List( GLUI_Node *parent, + GLUI_String& live_var, bool scroll = false, + int id=-1, + GLUI_CB callback=GLUI_CB() + /*,GLUI_Control *object = NULL */ + /*,GLUI_InterObject_CB obj_cb = NULL*/); + + + GLUI_String orig_text; + int debug; + int draw_text_only; + int start_line; + int num_lines; + int curr_line; + int visible_lines; + GLUI_Scrollbar *scrollbar; + GLUI_List_Item items_list; + GLUI_Control *associated_object; + GLUI_CB obj_cb; + int cb_click_type; + int last_line; + int last_click_time; + + int mouse_down_handler( int local_x, int local_y ); + int mouse_up_handler( int local_x, int local_y, bool inside ); + int mouse_held_down_handler( int local_x, int local_y, bool inside ); + int key_handler( unsigned char key,int modifiers ); + int special_handler( int key,int modifiers ); + + void activate( int how ); + void deactivate( void ); + + void draw( int x, int y ); + + int mouse_over( int state, int x, int y ); + + int get_box_width(); + int find_word_break( int start, int direction ); + int substring_width( const char *t, int start, int end ); + int find_line( int x, int y ); + void update_and_draw_text( void ); + void draw_text( const char *t, int selected, int x, int y ); + void update_size( void ); + + + int add_item( int id, const char *text ); + int delete_item( const char *text ); + int delete_item( int id ); + int delete_all(); + + GLUI_List_Item *get_item_ptr( const char *text ); + GLUI_List_Item *get_item_ptr( int id ); + + void dump( FILE *out, const char *text ); + void set_start_line(int l) { start_line = l; } + static void scrollbar_callback(GLUI_Control*); + int get_current_item() { return curr_line; } + void set_click_type(int d) { + cb_click_type = d; } + void set_object_callback(GLUI_CB cb=GLUI_CB(), GLUI_Control*obj=NULL) + { obj_cb=cb; associated_object=obj; } + + virtual GLUI_List* dynamicCastGLUI_List() + { + return this; + } + +protected: + void common_init() + { + h = GLUI_LIST_HEIGHT; + w = GLUI_LIST_WIDTH; + num_lines = 0; + visible_lines = 0; + start_line = 0; + curr_line = 0; + name[0] = '\0'; + active_type = GLUI_CONTROL_ACTIVE_PERMANENT; + can_activate = true; + spacebar_mouse_click = false; + scrollbar = NULL; + debug = false; + draw_text_only = false; + cb_click_type = GLUI_SINGLE_CLICK; + last_line = -1; + last_click_time = 0; + associated_object = NULL; + }; + void common_construct( + GLUI_Node *parent, + GLUI_String* live_var, bool scroll, + int id, + GLUI_CB callback + /*,GLUI_Control *object*/ + /*,GLUI_InterObject_CB obj_cb*/); +}; + +/************************************************************/ +/* */ +/* Scrollbar class - JVK */ +/* */ +/************************************************************/ + +class GLUI_Scrollbar : public GLUI_Control +{ +public: + // Constructor, no live var + GLUI_Scrollbar( GLUI_Node *parent, + const char *name, + int horz_vert=GLUI_SCROLL_HORIZONTAL, + int data_type=GLUI_SCROLL_INT, + int id=-1, GLUI_CB callback=GLUI_CB() + /*,GLUI_Control *object = NULL*/ + /*,GLUI_InterObject_CB obj_cb = NULL*/ + ); + + // Constructor, int live var + GLUI_Scrollbar( GLUI_Node *parent, const char *name, int horz_vert, + int *live_var, + int id=-1, GLUI_CB callback=GLUI_CB() + /*,GLUI_Control *object = NULL*/ + /*,GLUI_InterObject_CB obj_cb = NULL*/ + ); + + // Constructor, float live var + GLUI_Scrollbar( GLUI_Node *parent, const char *name, int horz_vert, + float *live_var, + int id=-1, GLUI_CB callback=GLUI_CB() + /*,GLUI_Control *object = NULL*/ + /*,GLUI_InterObject_CB obj_cb = NULL*/ + ); + + bool currently_inside; + int state; + float growth, growth_exp; + int last_x, last_y; + int data_type; + int callback_count; + int last_int_val; ///< Used to prevent repeated callbacks. + float last_float_val; + int first_callback; + float user_speed; + float float_min, float_max; + int int_min, int_max; + int horizontal; + double last_update_time; ///< GLUI_Time() we last advanced scrollbar. + double velocity_limit; ///< Maximum distance to advance per second. + int box_length; + int box_start_position; + int box_end_position; + int track_length; + + + /* Rather than directly access an Editbox or Textbox for + changing variables, a pointer to some object is defined + along with a static callback in the form func(void *, int) - + the int is the new value, the void * must be cast to that + particular object type before use. + */ + void * associated_object; /* Lets the Spinner manage it's own callbacks */ + GLUI_CB object_cb; /* function pointer to object call_back */ + + int mouse_down_handler( int local_x, int local_y ); + int mouse_up_handler( int local_x, int local_y, bool inside ); + int mouse_held_down_handler( int local_x, int local_y, bool inside ); + int key_handler( unsigned char key,int modifiers ); + int special_handler( int key,int modifiers ); + + void draw( int x, int y ); + void draw_pressed( void ); + void draw_unpressed( void ); + void draw_text( int sunken ); + + void update_size( void ); + + void set_int_limits( int low, int high,int limit_type=GLUI_LIMIT_CLAMP); + void set_float_limits( float low,float high,int limit_type=GLUI_LIMIT_CLAMP); + int find_arrow( int local_x, int local_y ); + void do_drag( int x, int y ); + void do_callbacks( void ); + void draw_scroll( void ); + void do_click( void ); + void idle( void ); + bool needs_idle( void ) const; + void set_int_val( int new_val ); + void set_float_val( float new_val ); + void increase_growth( void ); + void reset_growth( void ); + + void set_speed( float speed ) { user_speed = speed; }; + void update_scroll_parameters(); + void set_object_callback(GLUI_CB cb=GLUI_CB(), GLUI_Control*obj=NULL) + { object_cb=cb; associated_object=obj; } + + virtual GLUI_Scrollbar* dynamicCastGLUI_Scrollbar() + { + return this; + } + +protected: + void common_init ( void ); + void common_construct( + GLUI_Node *parent, + const char *name, + int horz_vert, + int data_type, void* live_var, + int id, GLUI_CB callback + /*,GLUI_Control *object + ,GLUI_InterObject_CB obj_cb*/ + ); + + virtual void draw_scroll_arrow(int arrowtype, int x, int y); + virtual void draw_scroll_box(int x, int y, int w, int h); +}; + +/************************************************************/ +/* */ +/* Listbox class */ +/* */ +/************************************************************/ + +class GLUI_Listbox_Item : public GLUI_Node +{ +public: + GLUI_String text; + int id; +}; + +class GLUI_Listbox : public GLUI_Control +{ +public: + GLUI_String curr_text; + GLUI_Listbox_Item items_list; + int depressed; + + int orig_value; + bool currently_inside; + int text_x_offset, title_x_offset; + int glut_menu_id; + + int mouse_down_handler( int local_x, int local_y ); + int mouse_up_handler( int local_x, int local_y, bool inside ); + int mouse_held_down_handler( int local_x, int local_y, bool inside ); + int key_handler( unsigned char key,int modifiers ); + int special_handler( int key,int modifiers ); + + void update_size( void ); + void draw( int x, int y ); + int mouse_over( int state, int x, int y ); + + void set_int_val( int new_val ); + void dump( FILE *output ); + + int add_item( int id, const char *text ); + int delete_item( const char *text ); + int delete_item( int id ); + int sort_items( void ); + + int do_selection( int item ); + + GLUI_Listbox_Item *get_item_ptr( const char *text ); + GLUI_Listbox_Item *get_item_ptr( int id ); + + + GLUI_Listbox( GLUI_Node *parent, + const char *name, int *live_var=NULL, + int id=-1, GLUI_CB callback=GLUI_CB() ); + GLUI_Listbox( void ) { common_init(); } + + virtual GLUI_Listbox* dynamicCastGLUI_Listbox() + { + return this; + } + +protected: + /** Change w and return true if we need to be widened to fit the current item. */ + bool recalculate_item_width( void ); + void common_init() { + glui_format_str( name, "Listbox: %p", this ); + w = GLUI_EDITTEXT_WIDTH; + h = GLUI_EDITTEXT_HEIGHT; + orig_value = -1; + title_x_offset = 0; + text_x_offset = 55; + can_activate = true; + curr_text = ""; + live_type = GLUI_LIVE_INT; /* This has an integer live var */ + depressed = false; + glut_menu_id = -1; + } + + ~GLUI_Listbox(); +}; + +/************************************************************/ +/* */ +/* Mouse_Interaction class */ +/* */ +/************************************************************/ + +/** + This is the superclass of translation and rotation widgets. +*/ +class GLUI_Mouse_Interaction : public GLUI_Control +{ +public: + /*int get_main_area_size( void ) { return MIN( h-18, */ + int draw_active_area_only; + + int mouse_down_handler( int local_x, int local_y ); + int mouse_up_handler( int local_x, int local_y, bool inside ); + int mouse_held_down_handler( int local_x, int local_y, bool inside ); + int special_handler( int key, int modifiers ); + void update_size( void ); + void draw( int x, int y ); + void draw_active_area( void ); + + /*** The following methods (starting with "iaction_") need to + be overloaded ***/ + virtual int iaction_mouse_down_handler( int local_x, int local_y ) = 0; + virtual int iaction_mouse_up_handler( int local_x, int local_y, bool inside )=0; + virtual int iaction_mouse_held_down_handler( int local_x, int local_y, bool inside )=0; + virtual int iaction_special_handler( int key, int modifiers )=0; + virtual void iaction_draw_active_area_persp( void )=0; + virtual void iaction_draw_active_area_ortho( void )=0; + virtual void iaction_dump( FILE *output )=0; + virtual void iaction_init( void ) = 0; + + GLUI_Mouse_Interaction( void ) { + glui_format_str( name, "Mouse_Interaction: %p", this ); + w = GLUI_MOUSE_INTERACTION_WIDTH; + h = GLUI_MOUSE_INTERACTION_HEIGHT; + can_activate = true; + live_type = GLUI_LIVE_NONE; + alignment = GLUI_ALIGN_CENTER; + draw_active_area_only = false; + } +}; + +/************************************************************/ +/* */ +/* Rotation class */ +/* */ +/************************************************************/ + +/** + An onscreen rotation controller--allows the user to interact with + a 3D rotation via a spaceball-like interface. +*/ +class GLUI_Rotation : public GLUI_Mouse_Interaction +{ +public: + Arcball *ball; + GLUquadricObj *quadObj; + bool can_spin, spinning; + float damping; + + int iaction_mouse_down_handler( int local_x, int local_y ); + int iaction_mouse_up_handler( int local_x, int local_y, bool inside ); + int iaction_mouse_held_down_handler( int local_x, int local_y, bool inside ); + int iaction_special_handler( int key, int modifiers ); + void iaction_init( void ) { init_ball(); } + void iaction_draw_active_area_persp( void ); + void iaction_draw_active_area_ortho( void ); + void iaction_dump( FILE *output ); + + /* void update_size( void ); */ + /* void draw( int x, int y ); */ + /* int mouse_over( int state, int x, int y ); */ + + void setup_texture( void ); + void setup_lights( void ); + void draw_ball( float radius ); + + void init_ball( void ); + + void reset( void ); + + bool needs_idle( void ) const; + void idle( void ); + + void copy_float_array_to_ball( void ); + void copy_ball_to_float_array( void ); + + void set_spin( float damp_factor ); + + GLUI_Rotation( GLUI_Node *parent, const char *name, float *live_var=NULL, + int id=-1, GLUI_CB callback=GLUI_CB() ); + GLUI_Rotation(void) { common_init(); } + +protected: + void common_init(); +}; + +/************************************************************/ +/* */ +/* Translation class */ +/* */ +/************************************************************/ + +/** + An onscreen translation controller--allows the user to interact with + a 3D translation. +*/ +class GLUI_Translation : public GLUI_Mouse_Interaction +{ +public: + int trans_type; /* Is this an XY or a Z controller? */ + int down_x, down_y; + float scale_factor; + GLUquadricObj *quadObj; + int trans_mouse_code; + float orig_x, orig_y, orig_z; + int locked; + + int iaction_mouse_down_handler( int local_x, int local_y ); + int iaction_mouse_up_handler( int local_x, int local_y, bool inside ); + int iaction_mouse_held_down_handler( int local_x, int local_y, bool inside ); + int iaction_special_handler( int key, int modifiers ); + void iaction_init( void ) { } + void iaction_draw_active_area_persp( void ); + void iaction_draw_active_area_ortho( void ); + void iaction_dump( FILE *output ); + + void set_speed( float s ) { scale_factor = s; } + + void setup_texture( void ); + void setup_lights( void ); + void draw_2d_arrow( int radius, int filled, int orientation ); + void draw_2d_x_arrows( int radius ); + void draw_2d_y_arrows( int radius ); + void draw_2d_z_arrows( int radius ); + void draw_2d_xy_arrows( int radius ); + + int get_mouse_code( int x, int y ); + + /* Float array is either a single float (for single-axis controls), + or two floats for X and Y (if an XY controller) */ + + float get_z( void ) { return float_array_val[0]; } + float get_x( void ) { return float_array_val[0]; } + float get_y( void ) { + if ( trans_type == GLUI_TRANSLATION_XY ) return float_array_val[1]; + else return float_array_val[0]; + } + + void set_z( float val ); + void set_x( float val ); + void set_y( float val ); + void set_one_val( float val, int index ); + + GLUI_Translation( GLUI_Node *parent, const char *name, + int trans_type, float *live_var=NULL, + int id=-1, GLUI_CB callback=GLUI_CB() ); + GLUI_Translation( void ) { common_init(); } + +protected: + void common_init() { + locked = GLUI_TRANSLATION_LOCK_NONE; + glui_format_str( name, "Translation: %p", this ); + w = GLUI_MOUSE_INTERACTION_WIDTH; + h = GLUI_MOUSE_INTERACTION_HEIGHT; + can_activate = true; + live_type = GLUI_LIVE_FLOAT_ARRAY; + float_array_size = 0; + alignment = GLUI_ALIGN_CENTER; + trans_type = GLUI_TRANSLATION_XY; + scale_factor = 1.0; + quadObj = NULL; + trans_mouse_code = GLUI_TRANSLATION_MOUSE_NONE; + } +}; + +/********** Misc functions *********************/ +int _glutBitmapWidthString( void *font, const char *s ); +void _glutBitmapString( void *font, const char *s ); + +/********** Our own callbacks for glut *********/ +/* These are the callbacks that we pass to glut. They take + some action if necessary, then (possibly) call the user-level + glut callbacks. +*/ + +void glui_display_func( void ); +void glui_reshape_func( int w, int h ); +void glui_keyboard_func(unsigned char key, int x, int y); +void glui_special_func(int key, int x, int y); +void glui_mouse_func(int button, int state, int x, int y); +void glui_motion_func(int x, int y); +void glui_passive_motion_func(int x, int y); +void glui_entry_func(int state); +void glui_visibility_func(int state); +void glui_idle_func(void); + +void glui_parent_window_reshape_func( int w, int h ); +void glui_parent_window_keyboard_func(unsigned char key, int x, int y); +void glui_parent_window_mouse_func(int, int, int, int ); +void glui_parent_window_special_func(int key, int x, int y); + +#endif diff --git a/Extras/glui/algebra3.cpp b/Extras/glui/algebra3.cpp new file mode 100644 index 0000000..5101480 --- /dev/null +++ b/Extras/glui/algebra3.cpp @@ -0,0 +1,1609 @@ +/* + + algebra3.cpp, algebra3.h - C++ Vector and Matrix Algebra routines + + GLUI User Interface Toolkit (LGPL) + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/************************************************************************** + + There are three vector classes and two matrix classes: vec2, vec3, + vec4, mat3, and mat4. + + All the standard arithmetic operations are defined, with '*' + for dot product of two vectors and multiplication of two matrices, + and '^' for cross product of two vectors. + + Additional functions include length(), normalize(), homogenize for + vectors, and print(), set(), apply() for all classes. + + There is a function transpose() for matrices, but note that it + does not actually change the matrix, + + When multiplied with a matrix, a vector is treated as a row vector + if it precedes the matrix (v*M), and as a column vector if it + follows the matrix (M*v). + + Matrices are stored in row-major form. + + A vector of one dimension (2d, 3d, or 4d) can be cast to a vector + of a higher or lower dimension. If casting to a higher dimension, + the new component is set by default to 1.0, unless a value is + specified: + vec3 a(1.0, 2.0, 3.0 ); + vec4 b( a, 4.0 ); // now b == {1.0, 2.0, 3.0, 4.0}; + When casting to a lower dimension, the vector is homogenized in + the lower dimension. E.g., if a 4d {X,Y,Z,W} is cast to 3d, the + resulting vector is {X/W, Y/W, Z/W}. It is up to the user to + insure the fourth component is not zero before casting. + + There are also the following function for building matrices: + identity2D(), translation2D(), rotation2D(), + scaling2D(), identity3D(), translation3D(), + rotation3D(), rotation3Drad(), scaling3D(), + perspective3D() + + + --------------------------------------------------------------------- + + Author: Jean-Francois DOUEg + Revised: Paul Rademacher + Version 3.2 - Feb 1998 + Revised: Nigel Stewart (GLUI Code Cleaning) + +**************************************************************************/ + +#include "algebra3.h" +#include "glui_internal.h" +#include + +#ifdef VEC_ERROR_FATAL +#ifndef VEC_ERROR +#define VEC_ERROR(E) { printf( "VERROR %s\n", E ); exit(1); } +#endif +#else +#ifndef VEC_ERROR +#define VEC_ERROR(E) { printf( "VERROR %s\n", E ); } +#endif +#endif + +/**************************************************************** + * * + * vec2 Member functions * + * * + ****************************************************************/ + +/******************** vec2 CONSTRUCTORS ********************/ + +vec2::vec2() +{ + n[VX] = n[VY] = 0.0; +} + +vec2::vec2(float x, float y) +{ + n[VX] = x; + n[VY] = y; +} + +vec2::vec2(const vec2 &v) +{ + n[VX] = v.n[VX]; + n[VY] = v.n[VY]; +} + +vec2::vec2(const vec3 &v) // it is up to caller to avoid divide-by-zero +{ + n[VX] = v.n[VX]/v.n[VZ]; + n[VY] = v.n[VY]/v.n[VZ]; +} + +vec2::vec2(const vec3 &v, int dropAxis) +{ + switch (dropAxis) + { + case VX: n[VX] = v.n[VY]; n[VY] = v.n[VZ]; break; + case VY: n[VX] = v.n[VX]; n[VY] = v.n[VZ]; break; + default: n[VX] = v.n[VX]; n[VY] = v.n[VY]; break; + } +} + +/******************** vec2 ASSIGNMENT OPERATORS ******************/ + +vec2 & vec2::operator=(const vec2 &v) +{ + n[VX] = v.n[VX]; + n[VY] = v.n[VY]; + return *this; +} + +vec2 & vec2::operator+=(const vec2 &v) +{ + n[VX] += v.n[VX]; + n[VY] += v.n[VY]; + return *this; +} + +vec2 & vec2::operator-=(const vec2 &v) +{ + n[VX] -= v.n[VX]; + n[VY] -= v.n[VY]; + return *this; +} + +vec2 &vec2::operator*=(float d) +{ + n[VX] *= d; + n[VY] *= d; + return *this; +} + +vec2 &vec2::operator/=(float d) +{ + float d_inv = 1.0f/d; + n[VX] *= d_inv; + n[VY] *= d_inv; + return *this; +} + +float &vec2::operator[](int i) +{ + if (i < VX || i > VY) + //VEC_ERROR("vec2 [] operator: illegal access; index = " << i << '\n') + VEC_ERROR("vec2 [] operator: illegal access" ); + return n[i]; +} + +const float &vec2::operator[](int i) const +{ + if (i < VX || i > VY) + //VEC_ERROR("vec2 [] operator: illegal access; index = " << i << '\n') + VEC_ERROR("vec2 [] operator: illegal access" ); + + return n[i]; +} + +/******************** vec2 SPECIAL FUNCTIONS ********************/ + +float vec2::length() const +{ + return (float) sqrt(length2()); +} + +float vec2::length2() const +{ + return n[VX]*n[VX] + n[VY]*n[VY]; +} + +vec2 &vec2::normalize() // it is up to caller to avoid divide-by-zero +{ + *this /= length(); + return *this; +} + +vec2 &vec2::apply(V_FCT_PTR fct) +{ + n[VX] = (*fct)(n[VX]); + n[VY] = (*fct)(n[VY]); + return *this; +} + +void vec2::set( float x, float y ) +{ + n[VX] = x; n[VY] = y; +} + +/******************** vec2 FRIENDS *****************************/ + +vec2 operator-(const vec2 &a) +{ + return vec2(-a.n[VX],-a.n[VY]); +} + +vec2 operator+(const vec2 &a, const vec2& b) +{ + return vec2(a.n[VX]+b.n[VX], a.n[VY]+b.n[VY]); +} + +vec2 operator-(const vec2 &a, const vec2& b) +{ + return vec2(a.n[VX]-b.n[VX], a.n[VY]-b.n[VY]); +} + +vec2 operator*(const vec2 &a, float d) +{ + return vec2(d*a.n[VX], d*a.n[VY]); +} + +vec2 operator*(float d, const vec2 &a) +{ + return a*d; +} + +vec2 operator*(const mat3 &a, const vec2 &v) +{ + vec3 av; + + av.n[VX] = a.v[0].n[VX]*v.n[VX] + a.v[0].n[VY]*v.n[VY] + a.v[0].n[VZ]; + av.n[VY] = a.v[1].n[VX]*v.n[VX] + a.v[1].n[VY]*v.n[VY] + a.v[1].n[VZ]; + av.n[VZ] = a.v[2].n[VX]*v.n[VX] + a.v[2].n[VY]*v.n[VY] + a.v[2].n[VZ]; + + return av; +} + +vec2 operator*(const vec2 &v, const mat3 &a) +{ + return a.transpose() * v; +} + +vec3 operator*(const mat3 &a, const vec3 &v) +{ + vec3 av; + + av.n[VX] = a.v[0].n[VX]*v.n[VX] + a.v[0].n[VY]*v.n[VY] + a.v[0].n[VZ]*v.n[VZ]; + av.n[VY] = a.v[1].n[VX]*v.n[VX] + a.v[1].n[VY]*v.n[VY] + a.v[1].n[VZ]*v.n[VZ]; + av.n[VZ] = a.v[2].n[VX]*v.n[VX] + a.v[2].n[VY]*v.n[VY] + a.v[2].n[VZ]*v.n[VZ]; + + return av; +} + +vec3 operator*(const vec3 &v, const mat3 &a) +{ + return a.transpose() * v; +} + +float operator*(const vec2 &a, const vec2 &b) +{ + return a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY]; +} + +vec2 operator/(const vec2 &a, float d) +{ + float d_inv = 1.0f/d; + return vec2(a.n[VX]*d_inv, a.n[VY]*d_inv); +} + +vec3 operator^(const vec2 &a, const vec2 &b) +{ + return vec3(0.0, 0.0, a.n[VX] * b.n[VY] - b.n[VX] * a.n[VY]); +} + +int operator==(const vec2 &a, const vec2 &b) +{ + return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]); +} + +int operator!=(const vec2 &a, const vec2 &b) +{ + return !(a == b); +} + +/*ostream& operator << (ostream& s, vec2& v) +{ return s << "| " << v.n[VX] << ' ' << v.n[VY] << " |"; } +*/ + +/*istream& operator >> (istream& s, vec2& v) { + vec2 v_tmp; + char c = ' '; + + while (isspace(c)) + s >> c; + // The vectors can be formatted either as x y or | x y | + if (c == '|') { + s >> v_tmp[VX] >> v_tmp[VY]; + while (s >> c && isspace(c)) ; + if (c != '|') + ;//s.set(_bad); + } + else { + s.putback(c); + s >> v_tmp[VX] >> v_tmp[VY]; + } + if (s) + v = v_tmp; + return s; +} +*/ + +void swap(vec2 &a, vec2 &b) +{ + vec2 tmp(a); + a = b; + b = tmp; +} + +vec2 min_vec(const vec2 &a, const vec2 &b) +{ + return vec2(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY])); +} + +vec2 max_vec(const vec2 &a, const vec2 &b) +{ + return vec2(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY])); +} + +vec2 prod(const vec2 &a, const vec2 &b) +{ + return vec2(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY]); +} + +/**************************************************************** + * * + * vec3 Member functions * + * * + ****************************************************************/ + +// CONSTRUCTORS + +vec3::vec3() +{ + n[VX] = n[VY] = n[VZ] = 0.0; +} + +vec3::vec3(float x, float y, float z) +{ + n[VX] = x; + n[VY] = y; + n[VZ] = z; +} + +vec3::vec3(const vec3 &v) +{ + n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; +} + +vec3::vec3(const vec2 &v) +{ + n[VX] = v.n[VX]; + n[VY] = v.n[VY]; + n[VZ] = 1.0; +} + +vec3::vec3(const vec2 &v, float d) +{ + n[VX] = v.n[VX]; + n[VY] = v.n[VY]; + n[VZ] = d; +} + +vec3::vec3(const vec4 &v) // it is up to caller to avoid divide-by-zero +{ + n[VX] = v.n[VX] / v.n[VW]; + n[VY] = v.n[VY] / v.n[VW]; + n[VZ] = v.n[VZ] / v.n[VW]; +} + +vec3::vec3(const vec4 &v, int dropAxis) +{ + switch (dropAxis) + { + case VX: n[VX] = v.n[VY]; n[VY] = v.n[VZ]; n[VZ] = v.n[VW]; break; + case VY: n[VX] = v.n[VX]; n[VY] = v.n[VZ]; n[VZ] = v.n[VW]; break; + case VZ: n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VW]; break; + default: n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; break; + } +} + + +// ASSIGNMENT OPERATORS + +vec3 &vec3::operator=(const vec3 &v) +{ + n[VX] = v.n[VX]; + n[VY] = v.n[VY]; + n[VZ] = v.n[VZ]; + return *this; +} + +vec3 &vec3::operator+=(const vec3 &v) +{ + n[VX] += v.n[VX]; + n[VY] += v.n[VY]; + n[VZ] += v.n[VZ]; + return *this; +} + +vec3 &vec3::operator-=(const vec3& v) +{ + n[VX] -= v.n[VX]; + n[VY] -= v.n[VY]; + n[VZ] -= v.n[VZ]; + return *this; +} + +vec3 &vec3::operator*=(float d) +{ + n[VX] *= d; + n[VY] *= d; + n[VZ] *= d; + return *this; +} + +vec3 &vec3::operator/=(float d) +{ + float d_inv = 1.0f/d; + n[VX] *= d_inv; + n[VY] *= d_inv; + n[VZ] *= d_inv; + return *this; +} + +float &vec3::operator[](int i) +{ + if (i < VX || i > VZ) + //VEC_ERROR("vec3 [] operator: illegal access; index = " << i << '\n') + VEC_ERROR("vec3 [] operator: illegal access" ); + + return n[i]; +} + +const float &vec3::operator[](int i) const +{ + if (i < VX || i > VZ) + //VEC_ERROR("vec3 [] operator: illegal access; index = " << i << '\n') + VEC_ERROR("vec3 [] operator: illegal access" ); + + return n[i]; +} + +// SPECIAL FUNCTIONS + +float vec3::length() const +{ + return (float) sqrt(length2()); +} + +float vec3::length2() const +{ + return n[VX]*n[VX] + n[VY]*n[VY] + n[VZ]*n[VZ]; +} + +vec3 &vec3::normalize() // it is up to caller to avoid divide-by-zero +{ + *this /= length(); + return *this; +} + +vec3 &vec3::homogenize(void) // it is up to caller to avoid divide-by-zero +{ + n[VX] /= n[VZ]; + n[VY] /= n[VZ]; + n[VZ] = 1.0; + return *this; +} + +vec3 &vec3::apply(V_FCT_PTR fct) +{ + n[VX] = (*fct)(n[VX]); + n[VY] = (*fct)(n[VY]); + n[VZ] = (*fct)(n[VZ]); + return *this; +} + +void vec3::set(float x, float y, float z) // set vector +{ + n[VX] = x; + n[VY] = y; + n[VZ] = z; +} + +void vec3::print(FILE *file, const char *name) const // print vector to a file +{ + fprintf( file, "%s: <%f, %f, %f>\n", name, n[VX], n[VY], n[VZ] ); +} + +// FRIENDS + +vec3 operator-(const vec3 &a) +{ + return vec3(-a.n[VX],-a.n[VY],-a.n[VZ]); +} + +vec3 operator+(const vec3 &a, const vec3 &b) +{ + return vec3(a.n[VX]+ b.n[VX], a.n[VY] + b.n[VY], a.n[VZ] + b.n[VZ]); +} + +vec3 operator-(const vec3 &a, const vec3 &b) +{ + return vec3(a.n[VX]-b.n[VX], a.n[VY]-b.n[VY], a.n[VZ]-b.n[VZ]); +} + +vec3 operator*(const vec3 &a, float d) +{ + return vec3(d*a.n[VX], d*a.n[VY], d*a.n[VZ]); +} + +vec3 operator*(float d, const vec3 &a) +{ + return a*d; +} + +vec3 operator*(const mat4 &a, const vec3 &v) +{ + return a*vec4(v); +} + +vec3 operator*(const vec3 &v, mat4 &a) +{ + return a.transpose()*v; +} + +float operator*(const vec3 &a, const vec3 &b) +{ + return a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY] + a.n[VZ]*b.n[VZ]; +} + +vec3 operator/(const vec3 &a, float d) +{ + float d_inv = 1.0f/d; + return vec3(a.n[VX]*d_inv, a.n[VY]*d_inv, a.n[VZ]*d_inv); +} + +vec3 operator^(const vec3 &a, const vec3 &b) +{ + return + vec3(a.n[VY]*b.n[VZ] - a.n[VZ]*b.n[VY], + a.n[VZ]*b.n[VX] - a.n[VX]*b.n[VZ], + a.n[VX]*b.n[VY] - a.n[VY]*b.n[VX]); +} + +int operator==(const vec3 &a, const vec3 &b) +{ + return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]) && (a.n[VZ] == b.n[VZ]); +} + +int operator!=(const vec3 &a, const vec3 &b) +{ + return !(a == b); +} + +/*ostream& operator << (ostream& s, vec3& v) +{ return s << "| " << v.n[VX] << ' ' << v.n[VY] << ' ' << v.n[VZ] << " |"; } + +istream& operator >> (istream& s, vec3& v) { + vec3 v_tmp; + char c = ' '; + + while (isspace(c)) + s >> c; + // The vectors can be formatted either as x y z or | x y z | + if (c == '|') { + s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ]; + while (s >> c && isspace(c)) ; + if (c != '|') + ;//s.set(_bad); + } + else { + s.putback(c); + s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ]; + } + if (s) + v = v_tmp; + return s; +} +*/ + +void swap(vec3 &a, vec3 &b) +{ + vec3 tmp(a); + a = b; + b = tmp; +} + +vec3 min_vec(const vec3 &a, const vec3 &b) +{ + return vec3( + MIN(a.n[VX], b.n[VX]), + MIN(a.n[VY], b.n[VY]), + MIN(a.n[VZ], b.n[VZ])); +} + +vec3 max_vec(const vec3 &a, const vec3 &b) +{ + return vec3( + MAX(a.n[VX], b.n[VX]), + MAX(a.n[VY], b.n[VY]), + MAX(a.n[VZ], b.n[VZ])); +} + +vec3 prod(const vec3 &a, const vec3 &b) +{ + return vec3(a.n[VX]*b.n[VX], a.n[VY]*b.n[VY], a.n[VZ]*b.n[VZ]); +} + +/**************************************************************** + * * + * vec4 Member functions * + * * + ****************************************************************/ + +// CONSTRUCTORS + +vec4::vec4() +{ + n[VX] = n[VY] = n[VZ] = 0.0; + n[VW] = 1.0; +} + +vec4::vec4(float x, float y, float z, float w) +{ + n[VX] = x; + n[VY] = y; + n[VZ] = z; + n[VW] = w; +} + +vec4::vec4(const vec4 &v) +{ + n[VX] = v.n[VX]; + n[VY] = v.n[VY]; + n[VZ] = v.n[VZ]; + n[VW] = v.n[VW]; +} + +vec4::vec4(const vec3 &v) +{ + n[VX] = v.n[VX]; + n[VY] = v.n[VY]; + n[VZ] = v.n[VZ]; + n[VW] = 1.0; +} + +vec4::vec4(const vec3 &v, float d) +{ + n[VX] = v.n[VX]; + n[VY] = v.n[VY]; + n[VZ] = v.n[VZ]; + n[VW] = d; +} + +// ASSIGNMENT OPERATORS + +vec4 &vec4::operator=(const vec4 &v) +{ + n[VX] = v.n[VX]; + n[VY] = v.n[VY]; + n[VZ] = v.n[VZ]; + n[VW] = v.n[VW]; + return *this; +} + +vec4 &vec4::operator+=(const vec4 &v) +{ + n[VX] += v.n[VX]; + n[VY] += v.n[VY]; + n[VZ] += v.n[VZ]; + n[VW] += v.n[VW]; + return *this; +} + +vec4 &vec4::operator-=(const vec4 &v) +{ + n[VX] -= v.n[VX]; + n[VY] -= v.n[VY]; + n[VZ] -= v.n[VZ]; + n[VW] -= v.n[VW]; + return *this; +} + +vec4 &vec4::operator*=(float d) +{ + n[VX] *= d; + n[VY] *= d; + n[VZ] *= d; + n[VW] *= d; + return *this; +} + +vec4 &vec4::operator/=(float d) +{ + float d_inv = 1.0f/d; + n[VX] *= d_inv; + n[VY] *= d_inv; + n[VZ] *= d_inv; + n[VW] *= d_inv; + return *this; +} + +float &vec4::operator[](int i) +{ + if (i < VX || i > VW) + //VEC_ERROR("vec4 [] operator: illegal access; index = " << i << '\n') + VEC_ERROR("vec4 [] operator: illegal access" ); + + return n[i]; +} + +const float &vec4::operator[](int i) const +{ + if (i < VX || i > VW) + //VEC_ERROR("vec4 [] operator: illegal access; index = " << i << '\n') + VEC_ERROR("vec4 [] operator: illegal access" ); + + return n[i]; +} + +// SPECIAL FUNCTIONS + +float vec4::length() const +{ + return (float) sqrt(length2()); +} + +float vec4::length2() const +{ + return n[VX]*n[VX] + n[VY]*n[VY] + n[VZ]*n[VZ] + n[VW]*n[VW]; +} + +vec4 &vec4::normalize() // it is up to caller to avoid divide-by-zero +{ + *this /= length(); + return *this; +} + +vec4 &vec4::homogenize() // it is up to caller to avoid divide-by-zero +{ + n[VX] /= n[VW]; + n[VY] /= n[VW]; + n[VZ] /= n[VW]; + n[VW] = 1.0; + return *this; +} + +vec4 &vec4::apply(V_FCT_PTR fct) +{ + n[VX] = (*fct)(n[VX]); + n[VY] = (*fct)(n[VY]); + n[VZ] = (*fct)(n[VZ]); + n[VW] = (*fct)(n[VW]); + return *this; +} + +void vec4::print(FILE *file, const char *name) const // print vector to a file +{ + fprintf( file, "%s: <%f, %f, %f, %f>\n", name, n[VX], n[VY], n[VZ], n[VW]); +} + +void vec4::set(float x, float y, float z, float a) +{ + n[0] = x; + n[1] = y; + n[2] = z; + n[3] = a; +} + + +// FRIENDS + +vec4 operator-(const vec4 &a) +{ + return vec4(-a.n[VX],-a.n[VY],-a.n[VZ],-a.n[VW]); +} + +vec4 operator+(const vec4 &a, const vec4 &b) +{ + return vec4( + a.n[VX] + b.n[VX], + a.n[VY] + b.n[VY], + a.n[VZ] + b.n[VZ], + a.n[VW] + b.n[VW]); +} + +vec4 operator-(const vec4 &a, const vec4 &b) +{ + return vec4( + a.n[VX] - b.n[VX], + a.n[VY] - b.n[VY], + a.n[VZ] - b.n[VZ], + a.n[VW] - b.n[VW]); +} + +vec4 operator*(const vec4 &a, float d) +{ + return vec4(d*a.n[VX], d*a.n[VY], d*a.n[VZ], d*a.n[VW]); +} + +vec4 operator*(float d, const vec4 &a) +{ + return a*d; +} + +vec4 operator*(const mat4 &a, const vec4 &v) +{ + #define ROWCOL(i) \ + a.v[i].n[0]*v.n[VX] + \ + a.v[i].n[1]*v.n[VY] + \ + a.v[i].n[2]*v.n[VZ] + \ + a.v[i].n[3]*v.n[VW] + + return vec4(ROWCOL(0), ROWCOL(1), ROWCOL(2), ROWCOL(3)); + + #undef ROWCOL +} + +vec4 operator*(const vec4 &v, const mat4 &a) +{ + return a.transpose()*v; +} + +float operator*(const vec4 &a, const vec4 &b) +{ + return + a.n[VX]*b.n[VX] + + a.n[VY]*b.n[VY] + + a.n[VZ]*b.n[VZ] + + a.n[VW]*b.n[VW]; +} + +vec4 operator/(const vec4 &a, float d) +{ + float d_inv = 1.0f/d; + return vec4( + a.n[VX]*d_inv, + a.n[VY]*d_inv, + a.n[VZ]*d_inv, + a.n[VW]*d_inv); +} + +int operator==(const vec4 &a, const vec4 &b) +{ + return + (a.n[VX] == b.n[VX]) && + (a.n[VY] == b.n[VY]) && + (a.n[VZ] == b.n[VZ]) && + (a.n[VW] == b.n[VW]); +} + +int operator!=(const vec4 &a, const vec4 &b) +{ + return !(a == b); +} + +/*ostream& operator << (ostream& s, vec4& v) +{ return s << "| " << v.n[VX] << ' ' << v.n[VY] << ' ' << v.n[VZ] << ' ' + << v.n[VW] << " |"; } + +istream& operator >> (istream& s, vec4& v) { + vec4 v_tmp; + char c = ' '; + + while (isspace(c)) + s >> c; + // The vectors can be formatted either as x y z w or | x y z w | + if (c == '|') { + s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ] >> v_tmp[VW]; + while (s >> c && isspace(c)) ; + if (c != '|') + ;//s.set(_bad); + } + else { + s.putback(c); + s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ] >> v_tmp[VW]; + } + if (s) + v = v_tmp; + return s; +} +*/ + +void swap(vec4 &a, vec4 &b) +{ + vec4 tmp(a); + a = b; + b = tmp; +} + +vec4 min_vec(const vec4 &a, const vec4 &b) +{ + return vec4( + MIN(a.n[VX], b.n[VX]), + MIN(a.n[VY], b.n[VY]), + MIN(a.n[VZ], b.n[VZ]), + MIN(a.n[VW], b.n[VW])); +} + +vec4 max_vec(const vec4 &a, const vec4 &b) +{ + return vec4( + MAX(a.n[VX], b.n[VX]), + MAX(a.n[VY], b.n[VY]), + MAX(a.n[VZ], b.n[VZ]), + MAX(a.n[VW], b.n[VW])); +} + +vec4 prod(const vec4 &a, const vec4 &b) +{ + return vec4( + a.n[VX] * b.n[VX], + a.n[VY] * b.n[VY], + a.n[VZ] * b.n[VZ], + a.n[VW] * b.n[VW]); +} + +/**************************************************************** + * * + * mat3 member functions * + * * + ****************************************************************/ + +// CONSTRUCTORS + +mat3::mat3() +{ + *this = identity2D(); +} + +mat3::mat3(const vec3 &v0, const vec3 &v1, const vec3 &v2) +{ + set(v0, v1, v2); +} + +mat3::mat3(const mat3 &m) +{ + v[0] = m.v[0]; + v[1] = m.v[1]; + v[2] = m.v[2]; +} + +// ASSIGNMENT OPERATORS + +mat3 &mat3::operator=(const mat3 &m) +{ + v[0] = m.v[0]; + v[1] = m.v[1]; + v[2] = m.v[2]; + return *this; +} + +mat3 &mat3::operator+=(const mat3& m) +{ + v[0] += m.v[0]; + v[1] += m.v[1]; + v[2] += m.v[2]; + return *this; +} + +mat3 &mat3::operator-=(const mat3& m) +{ + v[0] -= m.v[0]; + v[1] -= m.v[1]; + v[2] -= m.v[2]; + return *this; +} + +mat3 &mat3::operator*=(float d) +{ + v[0] *= d; + v[1] *= d; + v[2] *= d; + return *this; +} + +mat3 &mat3::operator/=(float d) +{ + v[0] /= d; + v[1] /= d; + v[2] /= d; + return *this; +} + +vec3 &mat3::operator[](int i) +{ + if (i < VX || i > VZ) + //VEC_ERROR("mat3 [] operator: illegal access; index = " << i << '\n') + VEC_ERROR("mat3 [] operator: illegal access" ); + + return v[i]; +} + +const vec3 &mat3::operator[](int i) const +{ + if (i < VX || i > VZ) + //VEC_ERROR("mat3 [] operator: illegal access; index = " << i << '\n') + VEC_ERROR("mat3 [] operator: illegal access" ); + + return v[i]; +} + +void mat3::set(const vec3 &v0, const vec3 &v1, const vec3 &v2) +{ + v[0] = v0; + v[1] = v1; + v[2] = v2; +} + +// SPECIAL FUNCTIONS + +mat3 mat3::transpose() const +{ + return mat3( + vec3(v[0][0], v[1][0], v[2][0]), + vec3(v[0][1], v[1][1], v[2][1]), + vec3(v[0][2], v[1][2], v[2][2])); +} + +mat3 mat3::inverse() const // Gauss-Jordan elimination with partial pivoting +{ + mat3 a(*this); // As a evolves from original mat into identity + mat3 b(identity2D()); // b evolves from identity into inverse(a) + int i, j, i1; + + // Loop over cols of a from left to right, eliminating above and below diag + for (j=0; j<3; j++) // Find largest pivot in column j among rows j..2 + { + i1 = j; // Row with largest pivot candidate + for (i=j+1; i<3; i++) + if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j])) + i1 = i; + + // Swap rows i1 and j in a and b to put pivot on diagonal + swap(a.v[i1], a.v[j]); + swap(b.v[i1], b.v[j]); + + // Scale row j to have a unit diagonal + if (a.v[j].n[j]==0.) + VEC_ERROR("mat3::inverse: singular matrix; can't invert\n"); + + b.v[j] /= a.v[j].n[j]; + a.v[j] /= a.v[j].n[j]; + + // Eliminate off-diagonal elems in col j of a, doing identical ops to b + for (i=0; i<3; i++) + if (i!=j) + { + b.v[i] -= a.v[i].n[j]*b.v[j]; + a.v[i] -= a.v[i].n[j]*a.v[j]; + } + } + + return b; +} + +mat3 &mat3::apply(V_FCT_PTR fct) +{ + v[VX].apply(fct); + v[VY].apply(fct); + v[VZ].apply(fct); + return *this; +} + + +// FRIENDS + +mat3 operator-(const mat3 &a) +{ + return mat3(-a.v[0], -a.v[1], -a.v[2]); +} + +mat3 operator+(const mat3 &a, const mat3 &b) +{ + return mat3(a.v[0]+b.v[0], a.v[1]+b.v[1], a.v[2]+b.v[2]); +} + +mat3 operator-(const mat3 &a, const mat3 &b) +{ + return mat3(a.v[0]-b.v[0], a.v[1]-b.v[1], a.v[2]-b.v[2]); +} + +mat3 operator*(const mat3 &a, const mat3 &b) +{ + #define ROWCOL(i, j) \ + a.v[i].n[0]*b.v[0][j] + a.v[i].n[1]*b.v[1][j] + a.v[i].n[2]*b.v[2][j] + + return mat3( + vec3(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2)), + vec3(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2)), + vec3(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2))); + + #undef ROWCOL +} + +mat3 operator*(const mat3 &a, float d) +{ + return mat3(a.v[0]*d, a.v[1]*d, a.v[2]*d); +} + +mat3 operator*(float d, const mat3 &a) +{ + return a*d; +} + +mat3 operator/(const mat3 &a, float d) +{ + return mat3(a.v[0]/d, a.v[1]/d, a.v[2]/d); +} + +int operator==(const mat3 &a, const mat3 &b) +{ + return + (a.v[0] == b.v[0]) && + (a.v[1] == b.v[1]) && + (a.v[2] == b.v[2]); +} + +int operator!=(const mat3 &a, const mat3 &b) +{ + return !(a == b); +} + +/*ostream& operator << (ostream& s, mat3& m) +{ return s << m.v[VX] << '\n' << m.v[VY] << '\n' << m.v[VZ]; } + +istream& operator >> (istream& s, mat3& m) { + mat3 m_tmp; + + s >> m_tmp[VX] >> m_tmp[VY] >> m_tmp[VZ]; + if (s) + m = m_tmp; + return s; +} +*/ + +void swap(mat3 &a, mat3 &b) +{ + mat3 tmp(a); + a = b; + b = tmp; +} + +void mat3::print(FILE *file, const char *name) const +{ + int i, j; + + fprintf( stderr, "%s:\n", name ); + + for( i = 0; i < 3; i++ ) + { + fprintf( stderr, " " ); + for( j = 0; j < 3; j++ ) + { + fprintf( stderr, "%f ", v[i][j] ); + } + fprintf( stderr, "\n" ); + } +} + + + +/**************************************************************** + * * + * mat4 member functions * + * * + ****************************************************************/ + +// CONSTRUCTORS + +mat4::mat4() +{ + *this = identity3D(); +} + +mat4::mat4(const vec4& v0, const vec4& v1, const vec4& v2, const vec4& v3) +{ + v[0] = v0; + v[1] = v1; + v[2] = v2; + v[3] = v3; +} + +mat4::mat4(const mat4 &m) +{ + v[0] = m.v[0]; + v[1] = m.v[1]; + v[2] = m.v[2]; + v[3] = m.v[3]; +} + +mat4::mat4( + float a00, float a01, float a02, float a03, + float a10, float a11, float a12, float a13, + float a20, float a21, float a22, float a23, + float a30, float a31, float a32, float a33 ) +{ + v[0][0] = a00; v[0][1] = a01; v[0][2] = a02; v[0][3] = a03; + v[1][0] = a10; v[1][1] = a11; v[1][2] = a12; v[1][3] = a13; + v[2][0] = a20; v[2][1] = a21; v[2][2] = a22; v[2][3] = a23; + v[3][0] = a30; v[3][1] = a31; v[3][2] = a32; v[3][3] = a33; +} + +// ASSIGNMENT OPERATORS + +mat4 &mat4::operator=(const mat4 &m) +{ + v[0] = m.v[0]; + v[1] = m.v[1]; + v[2] = m.v[2]; + v[3] = m.v[3]; + return *this; +} + +mat4 &mat4::operator+=(const mat4 &m) +{ + v[0] += m.v[0]; + v[1] += m.v[1]; + v[2] += m.v[2]; + v[3] += m.v[3]; + return *this; +} + +mat4 &mat4::operator-=(const mat4 &m) +{ + v[0] -= m.v[0]; + v[1] -= m.v[1]; + v[2] -= m.v[2]; + v[3] -= m.v[3]; + return *this; +} + +mat4 &mat4::operator*=(float d) +{ + v[0] *= d; + v[1] *= d; + v[2] *= d; + v[3] *= d; + return *this; +} + +mat4 &mat4::operator/=(float d) +{ + v[0] /= d; + v[1] /= d; + v[2] /= d; + v[3] /= d; + return *this; +} + +vec4 &mat4::operator[](int i) +{ + if (i < VX || i > VW) + //VEC_ERROR("mat4 [] operator: illegal access; index = " << i << '\n') + VEC_ERROR("mat4 [] operator: illegal access" ); + return v[i]; +} + +const vec4 &mat4::operator[](int i) const +{ + if (i < VX || i > VW) + //VEC_ERROR("mat4 [] operator: illegal access; index = " << i << '\n') + VEC_ERROR("mat4 [] operator: illegal access" ); + return v[i]; +} + +// SPECIAL FUNCTIONS; + +mat4 mat4::transpose() const +{ + return mat4( + vec4(v[0][0], v[1][0], v[2][0], v[3][0]), + vec4(v[0][1], v[1][1], v[2][1], v[3][1]), + vec4(v[0][2], v[1][2], v[2][2], v[3][2]), + vec4(v[0][3], v[1][3], v[2][3], v[3][3])); +} + +mat4 mat4::inverse() const // Gauss-Jordan elimination with partial pivoting +{ + mat4 a(*this); // As a evolves from original mat into identity + mat4 b(identity3D()); // b evolves from identity into inverse(a) + int i, j, i1; + + // Loop over cols of a from left to right, eliminating above and below diag + for (j=0; j<4; j++) // Find largest pivot in column j among rows j..3 + { + i1 = j; // Row with largest pivot candidate + for (i=j+1; i<4; i++) + if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j])) + i1 = i; + + // Swap rows i1 and j in a and b to put pivot on diagonal + swap(a.v[i1], a.v[j]); + swap(b.v[i1], b.v[j]); + + // Scale row j to have a unit diagonal + if (a.v[j].n[j]==0.) + VEC_ERROR("mat4::inverse: singular matrix; can't invert\n"); + + b.v[j] /= a.v[j].n[j]; + a.v[j] /= a.v[j].n[j]; + + // Eliminate off-diagonal elems in col j of a, doing identical ops to b + for (i=0; i<4; i++) + if (i!=j) + { + b.v[i] -= a.v[i].n[j]*b.v[j]; + a.v[i] -= a.v[i].n[j]*a.v[j]; + } + } + + return b; +} + +mat4 &mat4::apply(V_FCT_PTR fct) +{ + v[VX].apply(fct); + v[VY].apply(fct); + v[VZ].apply(fct); + v[VW].apply(fct); + return *this; +} + +void mat4::print(FILE *file, const char *name) const +{ + int i, j; + + fprintf( stderr, "%s:\n", name ); + + for( i = 0; i < 4; i++ ) + { + fprintf( stderr, " " ); + for( j = 0; j < 4; j++ ) + { + fprintf( stderr, "%f ", v[i][j] ); + } + fprintf( stderr, "\n" ); + } +} + +void mat4::swap_rows(int i, int j) +{ + vec4 t; + + t = v[i]; + v[i] = v[j]; + v[j] = t; +} + +void mat4::swap_cols(int i, int j) +{ + float t; + int k; + + for (k=0; k<4; k++) + { + t = v[k][i]; + v[k][i] = v[k][j]; + v[k][j] = t; + } +} + + +// FRIENDS + +mat4 operator-(const mat4 &a) +{ + return mat4(-a.v[0],-a.v[1],-a.v[2],-a.v[3]); +} + +mat4 operator+(const mat4 &a, const mat4 &b) +{ + return mat4( + a.v[0] + b.v[0], + a.v[1] + b.v[1], + a.v[2] + b.v[2], + a.v[3] + b.v[3]); +} + +mat4 operator-(const mat4 &a, const mat4 &b) +{ + return mat4( + a.v[0] - b.v[0], + a.v[1] - b.v[1], + a.v[2] - b.v[2], + a.v[3] - b.v[3]); +} + +mat4 operator*(const mat4 &a, const mat4 &b) +{ + #define ROWCOL(i, j) \ + a.v[i].n[0]*b.v[0][j] + \ + a.v[i].n[1]*b.v[1][j] + \ + a.v[i].n[2]*b.v[2][j] + \ + a.v[i].n[3]*b.v[3][j] + + return mat4( + vec4(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2), ROWCOL(0,3)), + vec4(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2), ROWCOL(1,3)), + vec4(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2), ROWCOL(2,3)), + vec4(ROWCOL(3,0), ROWCOL(3,1), ROWCOL(3,2), ROWCOL(3,3)) + ); + + #undef ROWCOL +} + +mat4 operator*(const mat4 &a, float d) +{ + return mat4(a.v[0]*d, a.v[1]*d, a.v[2]*d, a.v[3]*d); +} + +mat4 operator*(float d, const mat4 &a) +{ + return a*d; +} + +mat4 operator/(const mat4 &a, float d) +{ + return mat4(a.v[0]/d, a.v[1]/d, a.v[2]/d, a.v[3]/d); +} + +int operator==(const mat4 &a, const mat4 &b) +{ + return + (a.v[0] == b.v[0]) && + (a.v[1] == b.v[1]) && + (a.v[2] == b.v[2]) && + (a.v[3] == b.v[3]); +} + +int operator!=(const mat4 &a, const mat4 &b) +{ + return !(a == b); +} + +/*ostream& operator << (ostream& s, mat4& m) +{ return s << m.v[VX] << '\n' << m.v[VY] << '\n' << m.v[VZ] << '\n' << m.v[VW]; } + +istream& operator >> (istream& s, mat4& m) +{ + mat4 m_tmp; + + s >> m_tmp[VX] >> m_tmp[VY] >> m_tmp[VZ] >> m_tmp[VW]; + if (s) + m = m_tmp; + return s; +} +*/ + +void swap(mat4 &a, mat4 &b) +{ + mat4 tmp(a); + a = b; + b = tmp; +} + +/**************************************************************** + * * + * 2D functions and 3D functions * + * * + ****************************************************************/ + +mat3 identity2D() +{ + return mat3( + vec3(1.0, 0.0, 0.0), + vec3(0.0, 1.0, 0.0), + vec3(0.0, 0.0, 1.0)); +} + +mat3 translation2D(const vec2 &v) +{ + return mat3( + vec3(1.0, 0.0, v[VX]), + vec3(0.0, 1.0, v[VY]), + vec3(0.0, 0.0, 1.0)); +} + +mat3 rotation2D(const vec2 &Center, float angleDeg) +{ + float angleRad = (float) (angleDeg * M_PI / 180.0); + float c = (float) cos(angleRad); + float s = (float) sin(angleRad); + + return mat3( + vec3(c, -s, Center[VX] * (1.0f-c) + Center[VY] * s), + vec3(s, c, Center[VY] * (1.0f-c) - Center[VX] * s), + vec3(0.0, 0.0, 1.0)); +} + +mat3 scaling2D(const vec2 &scaleVector) +{ + return mat3( + vec3(scaleVector[VX], 0.0, 0.0), + vec3(0.0, scaleVector[VY], 0.0), + vec3(0.0, 0.0, 1.0)); +} + +mat4 identity3D() +{ + return mat4( + vec4(1.0, 0.0, 0.0, 0.0), + vec4(0.0, 1.0, 0.0, 0.0), + vec4(0.0, 0.0, 1.0, 0.0), + vec4(0.0, 0.0, 0.0, 1.0)); +} + +mat4 translation3D(const vec3 &v) +{ + return mat4( + vec4(1.0, 0.0, 0.0, v[VX]), + vec4(0.0, 1.0, 0.0, v[VY]), + vec4(0.0, 0.0, 1.0, v[VZ]), + vec4(0.0, 0.0, 0.0, 1.0)); +} + +mat4 rotation3D(const vec3 &Axis, float angleDeg) +{ + float angleRad = (float) (angleDeg * M_PI / 180.0); + float c = (float) cos(angleRad); + float s = (float) sin(angleRad); + float t = 1.0f - c; + + vec3 axis(Axis); + axis.normalize(); + + return mat4( + vec4(t * axis[VX] * axis[VX] + c, + t * axis[VX] * axis[VY] - s * axis[VZ], + t * axis[VX] * axis[VZ] + s * axis[VY], + 0.0), + vec4(t * axis[VX] * axis[VY] + s * axis[VZ], + t * axis[VY] * axis[VY] + c, + t * axis[VY] * axis[VZ] - s * axis[VX], + 0.0), + vec4(t * axis[VX] * axis[VZ] - s * axis[VY], + t * axis[VY] * axis[VZ] + s * axis[VX], + t * axis[VZ] * axis[VZ] + c, + 0.0), + vec4(0.0, 0.0, 0.0, 1.0)); +} + +mat4 rotation3Drad(const vec3 &Axis, float angleRad) +{ + float c = (float) cos(angleRad); + float s = (float) sin(angleRad); + float t = 1.0f - c; + + vec3 axis(Axis); + axis.normalize(); + + return mat4( + vec4(t * axis[VX] * axis[VX] + c, + t * axis[VX] * axis[VY] - s * axis[VZ], + t * axis[VX] * axis[VZ] + s * axis[VY], + 0.0), + vec4(t * axis[VX] * axis[VY] + s * axis[VZ], + t * axis[VY] * axis[VY] + c, + t * axis[VY] * axis[VZ] - s * axis[VX], + 0.0), + vec4(t * axis[VX] * axis[VZ] - s * axis[VY], + t * axis[VY] * axis[VZ] + s * axis[VX], + t * axis[VZ] * axis[VZ] + c, + 0.0), + vec4(0.0, 0.0, 0.0, 1.0)); +} + +mat4 scaling3D(const vec3 &scaleVector) +{ + return mat4( + vec4(scaleVector[VX], 0.0, 0.0, 0.0), + vec4(0.0, scaleVector[VY], 0.0, 0.0), + vec4(0.0, 0.0, scaleVector[VZ], 0.0), + vec4(0.0, 0.0, 0.0, 1.0)); +} + +mat4 perspective3D(float d) +{ + return mat4( + vec4(1.0f, 0.0f, 0.0f, 0.0f), + vec4(0.0f, 1.0f, 0.0f, 0.0f), + vec4(0.0f, 0.0f, 1.0f, 0.0f), + vec4(0.0f, 0.0f, 1.0f/d, 0.0f)); +} diff --git a/Extras/glui/algebra3.h b/Extras/glui/algebra3.h new file mode 100644 index 0000000..9875b3a --- /dev/null +++ b/Extras/glui/algebra3.h @@ -0,0 +1,475 @@ +/* + + algebra3.cpp, algebra3.h - C++ Vector and Matrix Algebra routines + + GLUI User Interface Toolkit (LGPL) + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/************************************************************************** + + There are three vector classes and two matrix classes: vec2, vec3, + vec4, mat3, and mat4. + + All the standard arithmetic operations are defined, with '*' + for dot product of two vectors and multiplication of two matrices, + and '^' for cross product of two vectors. + + Additional functions include length(), normalize(), homogenize for + vectors, and print(), set(), apply() for all classes. + + There is a function transpose() for matrices, but note that it + does not actually change the matrix, + + When multiplied with a matrix, a vector is treated as a row vector + if it precedes the matrix (v*M), and as a column vector if it + follows the matrix (M*v). + + Matrices are stored in row-major form. + + A vector of one dimension (2d, 3d, or 4d) can be cast to a vector + of a higher or lower dimension. If casting to a higher dimension, + the new component is set by default to 1.0, unless a value is + specified: + vec3 a(1.0, 2.0, 3.0 ); + vec4 b( a, 4.0 ); // now b == {1.0, 2.0, 3.0, 4.0}; + When casting to a lower dimension, the vector is homogenized in + the lower dimension. E.g., if a 4d {X,Y,Z,W} is cast to 3d, the + resulting vector is {X/W, Y/W, Z/W}. It is up to the user to + insure the fourth component is not zero before casting. + + There are also the following function for building matrices: + identity2D(), translation2D(), rotation2D(), + scaling2D(), identity3D(), translation3D(), + rotation3D(), rotation3Drad(), scaling3D(), + perspective3D() + + NOTE: When compiling for Windows, include this file first, to avoid + certain name conflicts + + --------------------------------------------------------------------- + + Author: Jean-Francois DOUEg + Revised: Paul Rademacher + Version 3.2 - Feb 1998 + Revised: Nigel Stewart (GLUI Code Cleaning) + +**************************************************************************/ + +#ifndef GLUI_ALGEBRA3_H +#define GLUI_ALGEBRA3_H + +#include +#include +#include + +// this line defines a new type: pointer to a function which returns a +// float and takes as argument a float +typedef float (*V_FCT_PTR)(float); + +class vec2; +class vec3; +class vec4; +class mat3; +class mat4; + +#ifndef M_PI +#define M_PI 3.141592654 +#endif + +enum {VX, VY, VZ, VW}; // axes +enum {PA, PB, PC, PD}; // planes +enum {RED, GREEN, BLUE, ALPHA}; // colors +enum {KA, KD, KS, ES}; // phong coefficients + +/**************************************************************** + * * + * 2D Vector * + * * + ****************************************************************/ + +class vec2 +{ + friend class vec3; + +protected: + + float n[2]; + +public: + + // Constructors + + vec2(); + vec2(float x, float y); + vec2(const vec2 &v); // copy constructor + vec2(const vec3 &v); // cast v3 to v2 + vec2(const vec3 &v, int dropAxis); // cast v3 to v2 + + // Assignment operators + + vec2 &operator = (const vec2 &v); // assignment of a vec2 + vec2 &operator += (const vec2 &v); // incrementation by a vec2 + vec2 &operator -= (const vec2 &v); // decrementation by a vec2 + vec2 &operator *= (float d); // multiplication by a constant + vec2 &operator /= (float d); // division by a constant + + // special functions + + float length() const; // length of a vec2 + float length2() const; // squared length of a vec2 + vec2 &normalize(); // normalize a vec2 + vec2 &apply(V_FCT_PTR fct); // apply a func. to each component + void set(float x, float y); // set vector + + float &operator [] (int i); // indexing + const float &operator [] (int i) const; // indexing + + // friends + + friend vec2 operator - (const vec2 &v); // -v1 + friend vec2 operator + (const vec2 &a, const vec2 &b); // v1 + v2 + friend vec2 operator - (const vec2 &a, const vec2 &b); // v1 - v2 + friend vec2 operator * (const vec2 &a, float d); // v1 * 3.0 + friend vec2 operator * (float d, const vec2 &a); // 3.0 * v1 + friend vec2 operator * (const mat3 &a, const vec2 &v); // M . v + friend vec2 operator * (const vec2 &v, const mat3 &a); // v . M + friend float operator * (const vec2 &a, const vec2 &b); // dot product + friend vec2 operator / (const vec2 &a, float d); // v1 / 3.0 + friend vec3 operator ^ (const vec2 &a, const vec2 &b); // cross product + friend int operator == (const vec2 &a, const vec2 &b); // v1 == v2 ? + friend int operator != (const vec2 &a, const vec2 &b); // v1 != v2 ? + //friend ostream& operator << (ostream& s, vec2& v); // output to stream + //friend istream& operator >> (istream& s, vec2& v); // input from strm. + friend void swap(vec2 &a, vec2 &b); // swap v1 & v2 + friend vec2 min_vec(const vec2 &a, const vec2 &b); // min(v1, v2) + friend vec2 max_vec(const vec2 &a, const vec2 &b); // max(v1, v2) + friend vec2 prod (const vec2 &a, const vec2 &b); // term by term * +}; + +/**************************************************************** + * * + * 3D Vector * + * * + ****************************************************************/ + +class vec3 +{ + friend class vec2; + friend class vec4; + friend class mat3; + +protected: + + float n[3]; + +public: + + // Constructors + + vec3(); + vec3(float x, float y, float z); + vec3(const vec3 &v); // copy constructor + vec3(const vec2 &v); // cast v2 to v3 + vec3(const vec2 &v, float d); // cast v2 to v3 + vec3(const vec4 &v); // cast v4 to v3 + vec3(const vec4 &v, int dropAxis); // cast v4 to v3 + + // Assignment operators + + vec3 &operator = (const vec3 &v); // assignment of a vec3 + vec3 &operator += (const vec3 &v); // incrementation by a vec3 + vec3 &operator -= (const vec3 &v); // decrementation by a vec3 + vec3 &operator *= (float d); // multiplication by a constant + vec3 &operator /= (float d); // division by a constant + + // special functions + + float length() const; // length of a vec3 + float length2() const; // squared length of a vec3 + vec3& normalize(); // normalize a vec3 + vec3& homogenize(); // homogenize (div by Z) + vec3& apply(V_FCT_PTR fct); // apply a func. to each component + void set(float x, float y, float z); // set vector + + void print(FILE *file, const char *name) const; // print vector to a file + + + float &operator [] (int i); // indexing + const float &operator [] (int i) const; // indexing + + // friends + + friend vec3 operator - (const vec3 &v); // -v1 + friend vec3 operator + (const vec3 &a, const vec3 &b); // v1 + v2 + friend vec3 operator - (const vec3 &a, const vec3 &b); // v1 - v2 + friend vec3 operator * (const vec3 &a, float d); // v1 * 3.0 + friend vec3 operator * (float d, const vec3 &a); // 3.0 * v1 + friend vec3 operator * (const mat4 &a, const vec3 &v); // M . v + friend vec3 operator * (const vec3 &v, const mat4 &a); // v . M + friend float operator * (const vec3 &a, const vec3 &b); // dot product + friend vec3 operator / (const vec3 &a, float d); // v1 / 3.0 + friend vec3 operator ^ (const vec3 &a, const vec3 &b); // cross product + friend int operator == (const vec3 &a, const vec3 &b); // v1 == v2 ? + friend int operator != (const vec3 &a, const vec3 &b); // v1 != v2 ? + //friend ostream& operator << (ostream& s, vec3& v); // output to stream + //friend istream& operator >> (istream& s, vec3& v); // input from strm. + friend void swap(vec3 &a, vec3 &b); // swap v1 & v2 + friend vec3 min_vec(const vec3 &a, const vec3 &b); // min(v1, v2) + friend vec3 max_vec(const vec3 &a, const vec3 &b); // max(v1, v2) + friend vec3 prod(const vec3 &a, const vec3 &b); // term by term * + + // necessary friend declarations + + friend vec2 operator * (const mat3 &a, const vec2 &v); // linear transform + friend vec3 operator * (const mat3 &a, const vec3 &v); // linear transform + friend mat3 operator * (const mat3 &a, const mat3 &b); // matrix 3 product +}; + +/**************************************************************** + * * + * 4D Vector * + * * + ****************************************************************/ + +class vec4 +{ + friend class vec3; + friend class mat4; + +protected: + + float n[4]; + +public: + + // Constructors + + vec4(); + vec4(float x, float y, float z, float w); + vec4(const vec4 &v); // copy constructor + vec4(const vec3 &v); // cast vec3 to vec4 + vec4(const vec3 &v, float d); // cast vec3 to vec4 + + // Assignment operators + + vec4 &operator = (const vec4 &v); // assignment of a vec4 + vec4 &operator += (const vec4 &v); // incrementation by a vec4 + vec4 &operator -= (const vec4 &v); // decrementation by a vec4 + vec4 &operator *= (float d); // multiplication by a constant + vec4 &operator /= (float d); // division by a constant + + // special functions + + float length() const; // length of a vec4 + float length2() const; // squared length of a vec4 + vec4 &normalize(); // normalize a vec4 + vec4 &apply(V_FCT_PTR fct); // apply a func. to each component + vec4 &homogenize(); + + void print(FILE *file, const char *name) const; // print vector to a file + + void set(float x, float y, float z, float a); + + float &operator [] (int i); // indexing + const float &operator [] (int i) const; // indexing + + // friends + + friend vec4 operator - (const vec4 &v); // -v1 + friend vec4 operator + (const vec4 &a, const vec4 &b); // v1 + v2 + friend vec4 operator - (const vec4 &a, const vec4 &b); // v1 - v2 + friend vec4 operator * (const vec4 &a, float d); // v1 * 3.0 + friend vec4 operator * (float d, const vec4 &a); // 3.0 * v1 + friend vec4 operator * (const mat4 &a, const vec4 &v); // M . v + friend vec4 operator * (const vec4 &v, const mat4 &a); // v . M + friend float operator * (const vec4 &a, const vec4 &b); // dot product + friend vec4 operator / (const vec4 &a, float d); // v1 / 3.0 + friend int operator == (const vec4 &a, const vec4 &b); // v1 == v2 ? + friend int operator != (const vec4 &a, const vec4 &b); // v1 != v2 ? + //friend ostream& operator << (ostream& s, vec4& v); // output to stream + //friend istream& operator >> (istream& s, vec4& v); // input from strm. + friend void swap(vec4 &a, vec4 &b); // swap v1 & v2 + friend vec4 min_vec(const vec4 &a, const vec4 &b); // min(v1, v2) + friend vec4 max_vec(const vec4 &a, const vec4 &b); // max(v1, v2) + friend vec4 prod (const vec4 &a, const vec4 &b); // term by term * + + // necessary friend declarations + + friend vec3 operator * (const mat4 &a, const vec3 &v); // linear transform + friend mat4 operator * (const mat4 &a, const mat4 &b); // matrix 4 product +}; + +/**************************************************************** + * * + * 3x3 Matrix * + * * + ****************************************************************/ + +class mat3 +{ +protected: + + vec3 v[3]; + +public: + + // Constructors + + mat3(); + mat3(const vec3 &v0, const vec3 &v1, const vec3 &v2); + mat3(const mat3 &m); + + // Assignment operators + + mat3 &operator = (const mat3 &m); // assignment of a mat3 + mat3 &operator += (const mat3 &m); // incrementation by a mat3 + mat3 &operator -= (const mat3 &m); // decrementation by a mat3 + mat3 &operator *= (float d); // multiplication by a constant + mat3 &operator /= (float d); // division by a constant + + // special functions + + mat3 transpose() const; // transpose + mat3 inverse() const; // inverse + mat3 &apply(V_FCT_PTR fct); // apply a func. to each element + + void print(FILE *file, const char *name ) const; // print matrix to a file + + void set(const vec3 &v0, const vec3 &v1, const vec3 &v2); + + vec3 &operator [] (int i); // indexing + const vec3 &operator [] (int i) const; // indexing + + // friends + + friend mat3 operator - (const mat3 &a); // -m1 + friend mat3 operator + (const mat3 &a, const mat3 &b); // m1 + m2 + friend mat3 operator - (const mat3 &a, const mat3 &b); // m1 - m2 + friend mat3 operator * (const mat3 &a, const mat3 &b); // m1 * m2 + friend mat3 operator * (const mat3 &a, float d); // m1 * 3.0 + friend mat3 operator * (float d, const mat3 &a); // 3.0 * m1 + friend mat3 operator / (const mat3 &a, float d); // m1 / 3.0 + friend int operator == (const mat3 &a, const mat3 &b); // m1 == m2 ? + friend int operator != (const mat3 &a, const mat3 &b); // m1 != m2 ? + //friend ostream& operator << (ostream& s, mat3& m); // output to stream + //friend istream& operator >> (istream& s, mat3& m); // input from strm. + friend void swap(mat3 &a, mat3 &b); // swap m1 & m2 + + // necessary friend declarations + + friend vec3 operator * (const mat3 &a, const vec3 &v); // linear transform + friend vec2 operator * (const mat3 &a, const vec2 &v); // linear transform +}; + +/**************************************************************** + * * + * 4x4 Matrix * + * * + ****************************************************************/ + +class mat4 +{ +protected: + + vec4 v[4]; + +public: + + // Constructors + + mat4(); + mat4(const vec4 &v0, const vec4 &v1, const vec4 &v2, const vec4 &v3); + mat4(const mat4 &m); + mat4(float a00, float a01, float a02, float a03, + float a10, float a11, float a12, float a13, + float a20, float a21, float a22, float a23, + float a30, float a31, float a32, float a33 ); + + + // Assignment operators + + mat4 &operator = (const mat4 &m); // assignment of a mat4 + mat4 &operator += (const mat4 &m); // incrementation by a mat4 + mat4 &operator -= (const mat4 &m); // decrementation by a mat4 + mat4 &operator *= (float d); // multiplication by a constant + mat4 &operator /= (float d); // division by a constant + + // special functions + + mat4 transpose() const; // transpose + mat4 inverse() const; // inverse + mat4 &apply(V_FCT_PTR fct); // apply a func. to each element + + void print(FILE *file, const char *name) const; // print matrix to a file + + vec4 &operator [] (int i); // indexing + const vec4 &operator [] (int i) const; // indexing + + void swap_rows(int i, int j); // swap rows i and j + void swap_cols(int i, int j); // swap cols i and j + + // friends + + friend mat4 operator - (const mat4 &a); // -m1 + friend mat4 operator + (const mat4 &a, const mat4 &b); // m1 + m2 + friend mat4 operator - (const mat4 &a, const mat4 &b); // m1 - m2 + friend mat4 operator * (const mat4 &a, const mat4 &b); // m1 * m2 + friend mat4 operator * (const mat4 &a, float d); // m1 * 4.0 + friend mat4 operator * (float d, const mat4 &a); // 4.0 * m1 + friend mat4 operator / (const mat4 &a, float d); // m1 / 3.0 + friend int operator == (const mat4 &a, const mat4 &b); // m1 == m2 ? + friend int operator != (const mat4 &a, const mat4 &b); // m1 != m2 ? + //friend ostream& operator << (ostream& s, mat4& m); // output to stream + //friend istream& operator >> (istream& s, mat4& m); // input from strm. + friend void swap(mat4 &a, mat4 &b); // swap m1 & m2 + + // necessary friend declarations + + friend vec4 operator * (const mat4 &a, const vec4 &v); // linear transform + //friend vec4 operator * (const vec4& v, const mat4& a); // linear transform + friend vec3 operator * (const mat4 &a, const vec3 &v); // linear transform + friend vec3 operator * (const vec3 &v, const mat4 &a); // linear transform +}; + +/**************************************************************** + * * + * 2D functions and 3D functions * + * * + ****************************************************************/ + +mat3 identity2D (); // identity 2D +mat3 translation2D(const vec2 &v); // translation 2D +mat3 rotation2D (const vec2 &Center, float angleDeg); // rotation 2D +mat3 scaling2D (const vec2 &scaleVector); // scaling 2D +mat4 identity3D (); // identity 3D +mat4 translation3D(const vec3 &v); // translation 3D +mat4 rotation3D (const vec3 &Axis, float angleDeg); // rotation 3D +mat4 rotation3Drad(const vec3 &Axis, float angleRad); // rotation 3D +mat4 scaling3D (const vec3 &scaleVector); // scaling 3D +mat4 perspective3D(float d); // perspective 3D + +vec3 operator * (const vec3 &v, const mat3 &a); +vec2 operator * (const vec2 &v, const mat3 &a); +vec3 operator * (const vec3 &v, const mat4 &a); +vec4 operator * (const vec4 &v, const mat4 &a); + +#endif diff --git a/Extras/glui/arcball.cpp b/Extras/glui/arcball.cpp new file mode 100644 index 0000000..63c983e --- /dev/null +++ b/Extras/glui/arcball.cpp @@ -0,0 +1,237 @@ +/********************************************************************** + + arcball.cpp + + + -------------------------------------------------- + + GLUI User Interface Toolkit (LGPL) + Copyright (c) 1998 Paul Rademacher + Feb 1998, Paul Rademacher (rademach@cs.unc.edu) + Oct 2003, Nigel Stewart - GLUI Code Cleaning + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +**********************************************************************/ + +#include "arcball.h" + +#include + + +/**************************************** Arcball::Arcball() ****/ +/* Default (void) constructor for Arcball */ + +Arcball::Arcball() +{ + rot_ptr = &rot; + init(); +} + +/**************************************** Arcball::Arcball() ****/ +/* Takes as argument a mat4 to use instead of the internal rot */ + +Arcball::Arcball(mat4 *mtx) +{ + rot_ptr = mtx; +} + + +/**************************************** Arcball::Arcball() ****/ +/* A constructor that accepts the screen center and arcball radius*/ + +Arcball::Arcball(const vec2 &_center, float _radius) +{ + rot_ptr = &rot; + init(); + set_params(_center, _radius); +} + + +/************************************** Arcball::set_params() ****/ + +void Arcball::set_params(const vec2 &_center, float _radius) +{ + center = _center; + radius = _radius; +} + +/*************************************** Arcball::init() **********/ + +void Arcball::init() +{ + center.set( 0.0, 0.0 ); + radius = 1.0; + q_now = quat_identity(); + *rot_ptr = identity3D(); + q_increment = quat_identity(); + rot_increment = identity3D(); + is_mouse_down = false; + is_spinning = false; + damp_factor = 0.0; + zero_increment = true; +} + +/*********************************** Arcball::mouse_to_sphere() ****/ + +vec3 Arcball::mouse_to_sphere(const vec2 &p) +{ + float mag; + vec2 v2 = (p - center) / radius; + vec3 v3( v2[0], v2[1], 0.0 ); + + mag = v2*v2; + + if ( mag > 1.0 ) + v3.normalize(); + else + v3[VZ] = (float) sqrt( 1.0 - mag ); + + /* Now we add constraints - X takes precedence over Y */ + if ( constraint_x ) + { + v3 = constrain_vector( v3, vec3( 1.0, 0.0, 0.0 )); + } + else if ( constraint_y ) + { + v3 = constrain_vector( v3, vec3( 0.0, 1.0, 0.0 )); + } + + return v3; +} + + +/************************************ Arcball::constrain_vector() ****/ + +vec3 Arcball::constrain_vector(const vec3 &vector, const vec3 &axis) +{ + return (vector-(vector*axis)*axis).normalize(); +} + +/************************************ Arcball::mouse_down() **********/ + +void Arcball::mouse_down(int x, int y) +{ + down_pt.set( (float)x, (float) y ); + is_mouse_down = true; + + q_increment = quat_identity(); + rot_increment = identity3D(); + zero_increment = true; +} + + +/************************************ Arcball::mouse_up() **********/ + +void Arcball::mouse_up() +{ + q_now = q_drag * q_now; + is_mouse_down = false; +} + + +/********************************** Arcball::mouse_motion() **********/ + +void Arcball::mouse_motion(int x, int y, int shift, int ctrl, int alt) +{ + /* Set the X constraint if CONTROL key is pressed, Y if ALT key */ + set_constraints( ctrl != 0, alt != 0 ); + + vec2 new_pt( (float)x, (float) y ); + vec3 v0 = mouse_to_sphere( down_pt ); + vec3 v1 = mouse_to_sphere( new_pt ); + + vec3 cross = v0^v1; + + q_drag.set( cross, v0 * v1 ); + + // *rot_ptr = (q_drag * q_now).to_mat4(); + mat4 temp = q_drag.to_mat4(); + *rot_ptr = *rot_ptr * temp; + + down_pt = new_pt; + + /* We keep a copy of the current incremental rotation (= q_drag) */ + q_increment = q_drag; + rot_increment = q_increment.to_mat4(); + + set_constraints(false, false); + + if ( q_increment.s < .999999 ) + { + is_spinning = true; + zero_increment = false; + } + else + { + is_spinning = false; + zero_increment = true; + } +} + + +/********************************** Arcball::mouse_motion() **********/ + +void Arcball::mouse_motion(int x, int y) +{ + mouse_motion(x, y, 0, 0, 0); +} + + +/***************************** Arcball::set_constraints() **********/ + +void Arcball::set_constraints(bool _constraint_x, bool _constraint_y) +{ + constraint_x = _constraint_x; + constraint_y = _constraint_y; +} + +/***************************** Arcball::idle() *********************/ + +void Arcball::idle() +{ + if (is_mouse_down) + { + is_spinning = false; + zero_increment = true; + } + + if (damp_factor < 1.0f) + q_increment.scale_angle(1.0f - damp_factor); + + rot_increment = q_increment.to_mat4(); + + if (q_increment.s >= .999999f) + { + is_spinning = false; + zero_increment = true; + } +} + + +/************************ Arcball::set_damping() *********************/ + +void Arcball::set_damping(float d) +{ + damp_factor = d; +} + + + + + diff --git a/Extras/glui/arcball.h b/Extras/glui/arcball.h new file mode 100644 index 0000000..18edd05 --- /dev/null +++ b/Extras/glui/arcball.h @@ -0,0 +1,97 @@ +/********************************************************************** + + arcball.h + + GLUI User Interface Toolkit (LGPL) + Copyright (c) 1998 Paul Rademacher + Feb 1998, Paul Rademacher (rademach@cs.unc.edu) + Oct 2003, Nigel Stewart - GLUI Code Cleaning + + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + --------------------------------------------------------------------- + + A C++ class that implements the Arcball, as described by Ken + Shoemake in Graphics Gems IV. + This class takes as input mouse events (mouse down, mouse drag, + mouse up), and creates the appropriate quaternions and 4x4 matrices + to represent the rotation given by the mouse. + + This class is used as follows: + - initialize [either in the constructor or with set_params()], the + center position (x,y) of the arcball on the screen, and the radius + - on mouse down, call mouse_down(x,y) with the mouse position + - as the mouse is dragged, repeatedly call mouse_motion() with the + current x and y positions. One can optionally pass in the current + state of the SHIFT, ALT, and CONTROL keys (passing zero if keys + are not pressed, non-zero otherwise), which constrains + the rotation to certain axes (X for CONTROL, Y for ALT). + - when the mouse button is released, call mouse_up() + + Axis constraints can also be explicitly set with the + set_constraints() function. + + The current rotation is stored in the 4x4 float matrix 'rot'. + It is also stored in the quaternion 'q_now'. + +**********************************************************************/ + +#ifndef GLUI_ARCBALL_H +#define GLUI_ARCBALL_H + +#include "glui_internal.h" +#include "algebra3.h" +#include "quaternion.h" + +class Arcball +{ +public: + Arcball(); + Arcball(mat4 *mtx); + Arcball(const vec2 ¢er, float radius); + + void set_damping(float d); + void idle(); + void mouse_down(int x, int y); + void mouse_up(); + void mouse_motion(int x, int y, int shift, int ctrl, int alt); + void mouse_motion(int x, int y); + void set_constraints(bool constrain_x, bool constrain_y); + void set_params(const vec2 ¢er, float radius); + void reset_mouse(); + void init(); + + vec3 constrain_vector(const vec3 &vector, const vec3 &axis); + vec3 mouse_to_sphere(const vec2 &p); + + //public: + int is_mouse_down; /* true for down, false for up */ + int is_spinning; + quat q_now, q_down, q_drag, q_increment; + vec2 down_pt; + mat4 rot, rot_increment; + mat4 *rot_ptr; + + bool constraint_x, constraint_y; + vec2 center; + float radius, damp_factor; + int zero_increment; +}; + +#endif diff --git a/Extras/glui/glui.cpp b/Extras/glui/glui.cpp new file mode 100644 index 0000000..239b12f --- /dev/null +++ b/Extras/glui/glui.cpp @@ -0,0 +1,2171 @@ +/**************************************************************************** + + GLUI User Interface Toolkit (LGPL) + --------------------------- + + glui.cpp + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ +#include "glui_internal_control.h" + + +/** + Note: moving this routine here from glui_add_controls.cpp prevents the linker + from touching glui_add_controls.o in non-deprecated programs, which + descreases the linked size of small GLUI programs substantially (100K+). (OSL 2006/06) +*/ +void GLUI_Node::add_child_to_control(GLUI_Node *parent,GLUI_Control *child) +{ + GLUI_Control *parent_control; + + /*** Collapsible nodes have to be handled differently, b/c the first and + last children are swapped in and out ***/ + parent_control = ((GLUI_Control*)parent); + if ( parent_control->collapsible == true ) { + if ( NOT parent_control->is_open ) { + /** Swap in the original first and last children **/ + parent_control->child_head = parent_control->collapsed_node.child_head; + parent_control->child_tail = parent_control->collapsed_node.child_tail; + + /*** Link this control ***/ + child->link_this_to_parent_last( parent_control ); + + /** Swap the children back out ***/ + parent_control->collapsed_node.child_head = parent_control->child_head; + parent_control->collapsed_node.child_tail = parent_control->child_tail; + parent_control->child_head = NULL; + parent_control->child_tail = NULL; + } + else { + child->link_this_to_parent_last( parent_control ); + } + } + else { + child->link_this_to_parent_last( parent_control ); + } + child->glui = (GLUI*) parent_control->glui; + child->update_size(); + child->enabled = parent_control->enabled; + child->glui->refresh(); + + /** Now set the 'hidden' var based on the parent **/ + if ( parent_control->hidden OR + (parent_control->collapsible AND NOT parent_control->is_open ) ) + { + child->hidden = true; + } +} + + +/************************************ GLUI_Node::add_control() **************/ + +int GLUI_Node::add_control( GLUI_Control *child ) +{ + add_child_to_control(this,child); + return true; +} + +/************************************ GLUI_Main::add_control() **************/ + +int GLUI_Main::add_control( GLUI_Node *parent, GLUI_Control *control ) +{ + add_child_to_control(parent,control); + return true; +} + + + +/*** This object must be used to create a GLUI ***/ + +GLUI_Master_Object GLUI_Master; + +/************************************ finish_drawing() *********** + Probably a silly routine. Called after all event handling callbacks. +*/ + +static void finish_drawing(void) +{ + glFinish(); +} + +/************************************ GLUI_CB::operator()() ************/ +void GLUI_CB::operator()(GLUI_Control*ctrl) const +{ + if (idCB) idCB(ctrl->user_id); + if (objCB) objCB(ctrl); +} + + +/************************************************ GLUI::GLUI() **********/ + +int GLUI::init( const char *text, long flags, int x, int y, int parent_window ) +{ + int old_glut_window; + + this->flags = flags; + + window_name = text; + + buffer_mode = buffer_back; ///< New smooth way + //buffer_mode = buffer_front; ///< Old flickery way (a bit faster). + + /*** We copy over the current window callthroughs ***/ + /*** (I think this might actually only be needed for subwindows) ***/ + /* glut_keyboard_CB = GLUI_Master.glut_keyboard_CB; + glut_reshape_CB = GLUI_Master.glut_reshape_CB; + glut_special_CB = GLUI_Master.glut_special_CB; + glut_mouse_CB = GLUI_Master.glut_mouse_CB;*/ + + + if ( (flags & GLUI_SUBWINDOW) != GLUI_SUBWINDOW ) { /* not a subwindow, creating a new top-level window */ + old_glut_window = glutGetWindow(); + + create_standalone_window( window_name.c_str(), x, y ); + setup_default_glut_callbacks(); + + if ( old_glut_window > 0 ) + glutSetWindow( old_glut_window ); + + top_level_glut_window_id = glut_window_id; + } + else /* *is* a subwindow */ + { + old_glut_window = glutGetWindow(); + + create_subwindow( parent_window, flags ); + setup_default_glut_callbacks(); + + if ( old_glut_window > 0 ) + glutSetWindow( old_glut_window ); + + top_level_glut_window_id = parent_window; + + /* + glutReshapeFunc( glui_parent_window_reshape_func ); + glutSpecialFunc( glui_parent_window_special_func ); + glutKeyboardFunc( glui_parent_window_keyboard_func ); + glutMouseFunc( glui_parent_window_mouse_func ); + */ + + } + + return true; +} + + +/**************************** GLUI_Main::create_standalone_window() ********/ + +void GLUI_Main::create_standalone_window( const char *name, int x, int y ) +{ + glutInitWindowSize( 100, 100 ); + if ( x >= 0 OR y >= 0 ) + glutInitWindowPosition( x, y ); + glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); + glut_window_id = glutCreateWindow( name ); +} + + +/******************************** GLUI_Main::create_subwindow() **********/ + +void GLUI_Main::create_subwindow( int parent_window, int window_alignment ) +{ + glut_window_id = glutCreateSubWindow(parent_window, 0,0, 100, 100); + this->parent_window = parent_window; +} + + +/**************************** GLUI_Main::setup_default_glut_callbacks() *****/ + +void GLUI_Main::setup_default_glut_callbacks( void ) +{ + glutDisplayFunc( glui_display_func ); + glutReshapeFunc( glui_reshape_func ); + glutKeyboardFunc( glui_keyboard_func ); + glutSpecialFunc( glui_special_func ); + glutMouseFunc( glui_mouse_func ); + glutMotionFunc( glui_motion_func ); + glutPassiveMotionFunc( glui_passive_motion_func ); + glutEntryFunc( glui_entry_func ); + glutVisibilityFunc( glui_visibility_func ); + /* glutIdleFunc( glui_idle_func ); // FIXME! 100% CPU usage! */ +} + + +/********************************************** glui_display_func() ********/ + +void glui_display_func(void) +{ + GLUI *glui; + + /* printf( "display func\n" ); */ + + glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() ); + + if ( glui ) { + glui->display(); + /* + Do not do anything after the above line, b/c the GLUI + window might have just closed itself + */ + } +} + + +/********************************************** glui_reshape_func() ********/ + +void glui_reshape_func(int w,int h ) +{ + GLUI *glui; + GLUI_Glut_Window *glut_window; + int current_window; + + /*printf( "glui_reshape_func(): %d w/h: %d/%d\n", glutGetWindow(), w, h ); */ + + current_window = glutGetWindow(); + + /*** First check if this is main glut window ***/ + glut_window = GLUI_Master.find_glut_window( current_window ); + if ( glut_window ) { + if (glut_window->glut_reshape_CB) glut_window->glut_reshape_CB(w,h); + + /*** Now send reshape events to all subwindows ***/ + glui = (GLUI*) GLUI_Master.gluis.first_child(); + while(glui) { + if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND + glui->parent_window == current_window ) { + glutSetWindow( glui->get_glut_window_id()); + glui->reshape(w,h); + /* glui->check_subwindow_position(); */ + } + glui = (GLUI*) glui->next(); + } + } + else { + /*** A standalone GLUI window ***/ + + glui = GLUI_Master.find_glui_by_window_id( current_window ); + + if ( glui ) { + glui->reshape(w,h); + } + } +} + +/********************************************** glui_keyboard_func() ********/ + +void glui_keyboard_func(unsigned char key, int x, int y) +{ + GLUI *glui; + int current_window; + GLUI_Glut_Window *glut_window; + + current_window = glutGetWindow(); + glut_window = GLUI_Master.find_glut_window( current_window ); + + /*printf( "key: %d\n", current_window ); */ + + if ( glut_window ) { /** Was event in a GLUT window? **/ + if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control ) { + glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() ); + + GLUI_Master.active_control_glui->keyboard(key,x,y); + finish_drawing(); + + glutSetWindow( current_window ); + } + else { + if (glut_window->glut_keyboard_CB) + glut_window->glut_keyboard_CB( key, x, y ); + } + } + else { /*** Nope, event was in a standalone GLUI window **/ + glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() ); + + if ( glui ) { + glui->keyboard(key,x,y); + finish_drawing(); + } + } +} + + + + +void glui_special_up_func(int key, int x, int y) +{ + GLUI *glui; + int current_window; + GLUI_Glut_Window *glut_window; + + current_window = glutGetWindow(); + glut_window = GLUI_Master.find_glut_window( current_window ); + + if (glut_window) /** Was event in a GLUT window? **/ + { + if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control ) + { + glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() ); + + GLUI_Master.active_control_glui->special_up(key,x,y); + finish_drawing(); + + glutSetWindow( current_window ); + } + else + { + if (glut_window->glut_special_up_CB) + glut_window->glut_special_up_CB( key, x, y ); + } + } + else /*** Nope, event was in a standalone GLUI window **/ + { + glui = GLUI_Master.find_glui_by_window_id(glutGetWindow()); + + if ( glui ) + { + glui->special_up(key,x,y); + finish_drawing(); + } + } +} + + + +/************************************************ glui_special_func() ********/ + +void glui_special_func(int key, int x, int y) +{ + GLUI *glui; + int current_window; + GLUI_Glut_Window *glut_window; + + current_window = glutGetWindow(); + glut_window = GLUI_Master.find_glut_window( current_window ); + + if (glut_window) /** Was event in a GLUT window? **/ + { + if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control ) + { + glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() ); + + GLUI_Master.active_control_glui->special(key,x,y); + finish_drawing(); + + glutSetWindow( current_window ); + } + else + { + if (glut_window->glut_special_CB) + glut_window->glut_special_CB( key, x, y ); + } + } + else /*** Nope, event was in a standalone GLUI window **/ + { + glui = GLUI_Master.find_glui_by_window_id(glutGetWindow()); + + if ( glui ) + { + glui->special(key,x,y); + finish_drawing(); + } + } +} + +/********************************************** glui_mouse_func() ********/ + +void glui_mouse_func(int button, int state, int x, int y) +{ + GLUI *glui; + int current_window; + GLUI_Glut_Window *glut_window; + + current_window = glutGetWindow(); + glut_window = GLUI_Master.find_glut_window( current_window ); + + if ( glut_window ) { /** Was event in a GLUT window? **/ + if ( GLUI_Master.active_control_glui != NULL ) + GLUI_Master.active_control_glui->deactivate_current_control(); + + if (glut_window->glut_mouse_CB) + glut_window->glut_mouse_CB( button, state, x, y ); + finish_drawing(); + } + else { /** Nope - event was in a GLUI standalone window **/ + glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() ); + if ( glui ) { + glui->passive_motion( 0,0 ); + glui->mouse( button, state, x, y ); + finish_drawing(); + } + } +} + + +/********************************************** glui_motion_func() ********/ + +void glui_motion_func(int x, int y) +{ + GLUI *glui; + + glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() ); + + if ( glui ) { + glui->motion(x,y); + finish_drawing(); + } + +} + + +/**************************************** glui_passive_motion_func() ********/ + +void glui_passive_motion_func(int x, int y) +{ + GLUI *glui; + + glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() ); + + if ( glui ) { + glui->passive_motion(x,y); + finish_drawing(); + } +} + + +/********************************************** glui_entry_func() ********/ + +void glui_entry_func(int state) +{ + GLUI *glui; + + glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() ); + + if ( glui ) { + glui->entry(state); + } +} + + +/******************************************** glui_visibility_func() ********/ + +void glui_visibility_func(int state) +{ + GLUI *glui; + + /* printf( "IN GLUI VISIBILITY()\n" ); */ + /* fflush( stdout ); */ + + glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() ); + + if ( glui ) { + glui->visibility(state); + } +} + + +/********************************************** glui_idle_func() ********/ +/* Send idle event to each glui, then to the main window */ + +void glui_idle_func(void) +{ + GLUI *glui; + + glui = (GLUI*) GLUI_Master.gluis.first_child(); + while( glui ) { + glui->idle(); + finish_drawing(); + + glui = (GLUI*) glui->next(); + } + + if ( GLUI_Master.glut_idle_CB ) { + /*** We set the current glut window before calling the user's + idle function, even though glut explicitly says the window id is + undefined in an idle callback. ***/ + + /** Check what the current window is first ***/ + + /*** Arbitrarily set the window id to the main gfx window of the + first glui window ***/ + /* int current_window, new_window; */ + /* current_window = glutGetWindow(); */ + /* if (GLUI_Master.gluis.first_child() != NULL ) { */ + /* new_window = ((GLUI_Main*)GLUI_Master.gluis.first_child())-> */ + /* main_gfx_window_id; */ + /* if ( new_window > 0 AND new_window != old_window ) { */ + /* --- Window is changed only if its not already the current window ---*/ + /* glutSetWindow( new_window ); */ + /* } */ + /*} */ + + GLUI_Master.glut_idle_CB(); + } +} + +/*********************************** GLUI_Master_Object::GLUI_Master_Object() ******/ + +GLUI_Master_Object::GLUI_Master_Object() +: glui_id_counter(1), + glut_idle_CB(NULL) +{ +} + +GLUI_Master_Object::~GLUI_Master_Object() +{ +} + +/*********************************** GLUI_Master_Object::create_glui() ******/ + +GLUI *GLUI_Master_Object::create_glui( const char *name, long flags,int x,int y ) +{ + GLUI *new_glui = new GLUI; + new_glui->init( name, flags, x, y, -1 ); + new_glui->link_this_to_parent_last( &this->gluis ); + return new_glui; +} + + +/************************** GLUI_Master_Object::create_glui_subwindow() ******/ + +GLUI *GLUI_Master_Object::create_glui_subwindow( int parent_window, + long flags ) +{ + GLUI *new_glui = new GLUI; + GLUI_String new_name; + glui_format_str( new_name, "subwin_%p", this ); + + new_glui->init( new_name.c_str(), flags | GLUI_SUBWINDOW, 0,0, + parent_window ); + new_glui->main_panel->set_int_val( GLUI_PANEL_EMBOSSED ); + new_glui->link_this_to_parent_last( &this->gluis ); + return new_glui; +} + + +/********************** GLUI_Master_Object::find_glui_by_window_id() ********/ + +GLUI *GLUI_Master_Object::find_glui_by_window_id( int window_id ) +{ + GLUI_Node *node; + + node = gluis.first_child(); + while( node ) { + if ( ((GLUI*)node)->get_glut_window_id() == window_id ) + return (GLUI*) node; + + node = node->next(); + } + return NULL; +} + + +/******************************************** GLUI_Main::display() **********/ + +void GLUI_Main::display( void ) +{ + int win_w, win_h; + + /* SUBTLE: on freeGLUT, the correct window is always already set. + But older versions of GLUT need this call, or else subwindows + don't update properly when resizing or damage-painting. + */ + glutSetWindow( glut_window_id ); + + /* Set up OpenGL state for widget drawing */ + glDisable( GL_DEPTH_TEST ); + glCullFace( GL_BACK ); + glDisable( GL_CULL_FACE ); + glDisable( GL_LIGHTING ); + set_current_draw_buffer(); + + /**** This function is used as a special place to do 'safe' processing, + e.g., handling window close requests. + That is, we can't close the window directly in the callback, so + we set a flag, post a redisplay message (which eventually calls + this function), then close the window safely in here. ****/ + if ( closing ) { + close_internal(); + return; + } + + /* if ( TEST_AND( this->flags, GLUI_SUBWINDOW )) + check_subwindow_position(); + */ + + win_w = glutGet( GLUT_WINDOW_WIDTH ); + win_h = glutGet( GLUT_WINDOW_HEIGHT ); + + /*** Check here if the window needs resizing ***/ + if ( win_w != main_panel->w OR win_h != main_panel->h ) { + glutReshapeWindow( main_panel->w, main_panel->h ); + return; + } + + /******* Draw GLUI window ******/ + glClearColor( (float) bkgd_color.r / 255.0, + (float) bkgd_color.g / 255.0, + (float) bkgd_color.b / 255.0, + 1.0 ); + glClear( GL_COLOR_BUFFER_BIT ); /* | GL_DEPTH_BUFFER_BIT ); */ + + set_ortho_projection(); + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + + /*** Rotate image so y increases downward. + In normal OpenGL, y increases upward. ***/ + glTranslatef( (float) win_w/2.0, (float) win_h/2.0, 0.0 ); + glRotatef( 180.0, 0.0, 1.0, 0.0 ); + glRotatef( 180.0, 0.0, 0.0, 1.0 ); + glTranslatef( (float) -win_w/2.0, (float) -win_h/2.0, 0.0 ); + + // Recursively draw the main panel + // main_panel->draw_bkgd_box( 0, 0, win_w, win_h ); + main_panel->draw_recursive( 0, 0 ); + + switch (buffer_mode) { + case buffer_front: /* Make sure drawing gets to screen */ + glFlush(); + break; + case buffer_back: /* Bring back buffer to front */ + glutSwapBuffers(); + break; + } +} + + + + +/*************************************** _glutBitmapWidthString() **********/ + +int _glutBitmapWidthString( void *font, const char *s ) +{ + const char *p = s; + int width = 0; + + while( *p != '\0' ) { + width += glutBitmapWidth( font, *p ); + p++; + } + + return width; +} + +/************************************ _glutBitmapString *********************/ +/* Displays the contents of a string using GLUT's bitmap character function */ +/* Does not handle newlines */ + +void _glutBitmapString( void *font, const char *s ) +{ + const char *p = s; + + while( *p != '\0' ) { + glutBitmapCharacter( font, *p ); + p++; + } +} + + + +/****************************** GLUI_Main::reshape() **************/ + +void GLUI_Main::reshape( int reshape_w, int reshape_h ) +{ + int new_w, new_h; + + pack_controls(); + + new_w = main_panel->w;/* + 1; */ + new_h = main_panel->h;/* + 1; */ + + if ( reshape_w != new_w OR reshape_h != new_h ) { + this->w = new_w; + this->h = new_h; + + glutReshapeWindow( new_w, new_h ); + } + else { + } + + if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) { + check_subwindow_position(); + + /***** if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) { + } + else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) { + } + else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) { + } + else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) { + } + ****/ + } + + glViewport( 0, 0, new_w, new_h ); + + /* printf( "%d: %d\n", glutGetWindow(), this->flags ); */ + + glutPostRedisplay(); +} + + +/****************************** GLUI_Main::keyboard() **************/ + +void GLUI_Main::keyboard(unsigned char key, int x, int y) +{ + GLUI_Control *new_control; + + curr_modifiers = glutGetModifiers(); + + /*** If it's a tab or shift tab, we don't pass it on to the controls. + Instead, we use it to cycle through active controls ***/ + if ( key == '\t' AND !mouse_button_down AND + (!active_control || !active_control->wants_tabs())) { + if ( curr_modifiers & GLUT_ACTIVE_SHIFT ) { + new_control = find_prev_control( active_control ); + } + else { + new_control = find_next_control( active_control ); + } + + /* if ( new_control ) + printf( "new_control: %s\n", new_control->name ); + */ + + deactivate_current_control(); + activate_control( new_control, GLUI_ACTIVATE_TAB ); + } + else if ( key == ' ' AND active_control + AND active_control->spacebar_mouse_click ) { + /*** If the user presses the spacebar, and a non-edittext control + is active, we send it a mouse down event followed by a mouse up + event (simulated mouse-click) ***/ + + active_control->mouse_down_handler( 0, 0 ); + active_control->mouse_up_handler( 0, 0, true ); + } else { + /*** Pass the keystroke onto the active control, if any ***/ + if ( active_control != NULL ) + active_control->key_handler( key, curr_modifiers ); + } +} + + + +void GLUI_Main::special_up(int key, int x, int y) +{ + curr_modifiers = glutGetModifiers(); + + /*** Pass the keystroke onto the active control, if any ***/ + if ( active_control != NULL ) + active_control->special_up_handler( key, glutGetModifiers() ); +} + + +/****************************** GLUI_Main::special() **************/ + +void GLUI_Main::special(int key, int x, int y) +{ + curr_modifiers = glutGetModifiers(); + + /*** Pass the keystroke onto the active control, if any ***/ + if ( active_control != NULL ) + active_control->special_handler( key, glutGetModifiers() ); +} + + + +/****************************** GLUI_Main::mouse() **************/ + +void GLUI_Main::mouse(int button, int state, int x, int y) +{ + int callthrough; + GLUI_Control *control; + + /* printf( "MOUSE: %d %d\n", button, state ); */ + + callthrough = true; + + curr_modifiers = glutGetModifiers(); + + if ( button == GLUT_LEFT ) { + control = find_control( x, y ); + + /*if ( control ) printf( "control: %s\n", control->name.c_str() ); */ + + if ( mouse_button_down AND active_control != NULL AND + state == GLUT_UP ) + { + /** We just released the mouse, which was depressed at some control **/ + + callthrough = active_control-> + mouse_up_handler( x, y, control==active_control); + glutSetCursor( GLUT_CURSOR_LEFT_ARROW ); + + if ( active_control AND + active_control->active_type == GLUI_CONTROL_ACTIVE_MOUSEDOWN AND 0) + { + /*** This is a control that needs to be deactivated when the + mouse button is released ****/ + deactivate_current_control(); + } + } + else { + if ( control ) { + if ( NOT mouse_button_down AND state == GLUT_DOWN ) { + /*** We just pressed the mouse down at some control ***/ + + if ( active_control != control ) { + if ( active_control != NULL ) { + /** There is an active control still - deactivate it ***/ + deactivate_current_control(); + } + } + + if ( control->enabled ) { + activate_control( control, GLUI_ACTIVATE_MOUSE ); + callthrough = control->mouse_down_handler( x, y ); + } + } + } + } + + if ( state == GLUT_DOWN ) + mouse_button_down = true; + else if ( state == GLUT_UP ) + mouse_button_down = false; + } + + /** + NO CALLTHROUGH NEEDED FOR MOUSE EVENTS + if ( callthrough AND glut_mouse_CB ) + glut_mouse_CB( button, state, x, y ); + **/ + + callthrough=callthrough; /* To get rid of compiler warnings */ +} + + +/****************************** GLUI_Main::motion() **************/ + +void GLUI_Main::motion(int x, int y) +{ + int callthrough; + GLUI_Control *control; + + /* printf( "MOTION: %d %d\n", x, y ); */ + + callthrough = true; + + control = find_control(x,y); + + if ( mouse_button_down AND active_control != NULL ) { + callthrough = + active_control->mouse_held_down_handler(x,y,control==active_control); + } + + /** + NO CALLTHROUGH NEEDED FOR MOUSE EVENTS + + if ( callthrough AND glut_motion_CB ) + glut_motion_CB(x,y); + **/ + + callthrough=callthrough; /* To get rid of compiler warnings */ +} + + +/*********************** GLUI_Main::passive_motion() **************/ + +void GLUI_Main::passive_motion(int x, int y) +{ + GLUI_Control *control; + + control = find_control( x, y ); + + /* printf( "%p %p\n", control, mouse_over_control ); */ + + if ( control != mouse_over_control ) { + if ( mouse_over_control ) { + mouse_over_control->mouse_over( false, x, y ); + } + + if ( control ) { + control->mouse_over( true, x, y ); + mouse_over_control = control; + } + } + + /* + if ( curr_cursor != GLUT_CURSOR_INHERIT ) { + curr_cursor = GLUT_CURSOR_INHERIT; + glutSetCursor( GLUT_CURSOR_INHERIT ); + }*/ + +} + + +/****************************** GLUI_Main::entry() **************/ + +void GLUI_Main::entry(int state) +{ + /*if ( NOT active_control OR ( active_control AND ( active_control->type == GLUI_CONTROL_EDITTEXT + OR active_control->type == GLUI_CONTROL_SPINNER) ) )*/ + glutSetCursor( GLUT_CURSOR_LEFT_ARROW ); +} + + +/****************************** GLUI_Main::visibility() **************/ + +void GLUI_Main::visibility(int state) +{ +} + + +/****************************** GLUI_Main::idle() **************/ + +void GLUI_Main::idle(void) +{ + /*** Pass the idle event onto the active control, if any ***/ + + /* printf( "IDLE \t" ); */ + + if ( active_control != NULL ) { + /* First we check if the control actually needs the idle right now. + Otherwise, let's avoid wasting cycles and OpenGL context switching */ + + if ( active_control->needs_idle() ) { + /*** Set the current glut window to the glui window */ + /*** But don't change the window if we're already at that window ***/ + + if ( glut_window_id > 0 AND glutGetWindow() != glut_window_id ) { + glutSetWindow( glut_window_id ); + } + + active_control->idle(); + } + } +} + +int GLUI_Main::needs_idle( void ) +{ + return active_control != NULL && active_control->needs_idle(); +} + + +/******************************************* GLUI_Main::find_control() ******/ + +GLUI_Control *GLUI_Main::find_control( int x, int y ) +{ + GLUI_Control *node, *last_container; + + last_container = NULL; + + node = main_panel; + while( node != NULL ) { + if ( !node->dynamicCastGLUI_Column() AND + PT_IN_BOX( x, y, + node->x_abs, node->x_abs + node->w, + node->y_abs, node->y_abs + node->h ) + ) + { + /*** Point is inside current node ***/ + + if ( node->first_child() == NULL ) { + /*** SPECIAL CASE: for edittext boxes, we make sure click is + in box, and not on name string. This should be generalized + for all controls later... ***/ + if ( node->dynamicCastGLUI_EditText() ) { + if ( x < node->x_abs + ((GLUI_EditText*)node)->text_x_offset ) + return (GLUI_Control*) node->parent(); + } + + return node; /* point is inside this node, and node has no children, + so return this node as the selected node */ + } + else { + /*** This is a container class ***/ + last_container = node; + node = (GLUI_Control*) node->first_child(); /* Descend into child */ + } + + } + else { + node = (GLUI_Control*) node->next(); + } + } + + /** No leaf-level nodes found to accept the mouse click, so + return the last container control found which DOES accept the click **/ + + if ( last_container ) { + /* printf( "ctrl: '%s'\n", last_container->name ); */ + + return last_container; + } + else { + return NULL; + } +} + + +/************************************* GLUI_Main::pack_controls() ***********/ + +void GLUI_Main::pack_controls( void ) +{ + main_panel->pack(0,0); + + /**** Now align controls within their bounds ****/ + align_controls( main_panel ); + + /*** If this is a subwindow, expand panel to fit parent window ***/ + if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) { + int parent_h, parent_w; + int orig_window; + + orig_window = glutGetWindow(); + glutSetWindow( this->top_level_glut_window_id ); + parent_h = glutGet( GLUT_WINDOW_HEIGHT ); + parent_w = glutGet( GLUT_WINDOW_WIDTH ); + + glutSetWindow( orig_window ); + + /* printf( "%d %d\n", parent_h, parent_w ); */ + + if ( 1 ) { + if ( TEST_AND(this->flags,GLUI_SUBWINDOW_TOP )) { + main_panel->w = MAX( main_panel->w, parent_w ); + } + else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) { + main_panel->h = MAX( main_panel->h, parent_h ); + } + else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_BOTTOM )) { + main_panel->w = MAX( main_panel->w, parent_w ); + } + else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) { + main_panel->h = MAX( main_panel->h, parent_h ); + } + } + } + + this->w = main_panel->w; + this->h = main_panel->h; +} + + +/************************************ GLUI_Main::align_controls() **********/ + +void GLUI_Main::align_controls( GLUI_Control *control ) +{ + GLUI_Control *child; + + control->align(); + + child = (GLUI_Control*) control->first_child(); + + while( child != NULL ) { + align_controls( child ); + + child = (GLUI_Control*)child->next(); + } +} + + + +/*********************************** GLUI::set_main_gfx_window() ************/ + +void GLUI::set_main_gfx_window( int window_id ) +{ + main_gfx_window_id = window_id; +} + + +/********************************* GLUI_Main::post_update_main_gfx() ********/ + +void GLUI_Main::post_update_main_gfx( void ) +{ + int old_window; + + if ( main_gfx_window_id > 0 ) { + old_window = glutGetWindow(); + glutSetWindow( main_gfx_window_id ); + glutPostRedisplay(); + if( old_window > 0 ) + glutSetWindow( old_window ); + } +} + +/********************************* GLUI_Main::should_redraw_now() ********/ +/** Return true if this control should redraw itself immediately (front buffer); + Or queue up a redraw and return false if it shouldn't (back buffer). + + Called from GLUI_Control::redraw. +*/ +bool GLUI_Main::should_redraw_now(GLUI_Control *ctl) +{ + switch (buffer_mode) { + case buffer_front: return true; /* always draw in front-buffer mode */ + case buffer_back: { + int orig = ctl->set_to_glut_window(); + glutPostRedisplay(); /* redraw soon */ + ctl->restore_window(orig); + return false; /* don't draw now. */ + } + } + return false; /* never executed */ +} + +/********************************* GLUI_Main::set_current_draw_buffer() ********/ + +int GLUI_Main::set_current_draw_buffer( void ) +{ + /* Save old buffer */ + GLint state; + glGetIntegerv( GL_DRAW_BUFFER, &state ); + /* Switch to new buffer */ + switch (buffer_mode) { + case buffer_front: glDrawBuffer(GL_FRONT); break; + case buffer_back: glDrawBuffer(GL_BACK); break; /* might not be needed... */ + } + return (int)state; +} + + +/********************************* GLUI_Main::restore_draw_buffer() **********/ + +void GLUI_Main::restore_draw_buffer( int buffer_state ) +{ + glDrawBuffer( buffer_state ); +} + + +/******************************************** GLUI_Main::GLUI_Main() ********/ + +GLUI_Main::GLUI_Main( void ) +{ + mouse_button_down = false; + w = 0; + h = 0; + active_control = NULL; + mouse_over_control = NULL; + main_gfx_window_id = -1; + glut_window_id = -1; + curr_modifiers = 0; + closing = false; + parent_window = -1; + glui_id = GLUI_Master.glui_id_counter; + GLUI_Master.glui_id_counter++; + + font = GLUT_BITMAP_HELVETICA_12; + curr_cursor = GLUT_CURSOR_LEFT_ARROW; + + int r=200, g=200, b=200; + bkgd_color.set( r,g,b ); + bkgd_color_f[0] = r / 255.0; + bkgd_color_f[1] = g / 255.0; + bkgd_color_f[2] = b / 255.0; + + /*** Create the main panel ***/ + main_panel = new GLUI_Panel; + main_panel->set_int_val( GLUI_PANEL_NONE ); + main_panel->glui = (GLUI*) this; + main_panel->name = "\0"; +} + +/************************************ GLUI_Main::draw_raised_box() **********/ + +void GLUI_Main::draw_raised_box( int x, int y, int w, int h ) +{ + w = w+x; + h = h+y; + + glColor3ub( bkgd_color.r, bkgd_color.g, bkgd_color.b ); + glBegin( GL_LINE_LOOP ); + glVertex2i( x+1, y+1 ); glVertex2i( w-1, y+1 ); + glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 ); + glEnd(); + + glColor3d( 1.0, 1.0, 1.0 ); + glBegin( GL_LINE_STRIP ); + glVertex2i( x, h ); glVertex2i( x, y ); glVertex2i( w, y ); + glEnd(); + + glColor3d( 0.0, 0.0, 0.0 ); + glBegin( GL_LINE_STRIP ); + glVertex2i( w, y ); glVertex2i( w, h ); glVertex2i( x, h ); + glEnd(); + + glColor3d( .5, .5, .5 ); + glBegin( GL_LINE_STRIP ); + glVertex2i( w-1, y+1 ); glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 ); + glEnd(); +} + + +/************************************ GLUI_Main::draw_lowered_box() **********/ +/* Not quite perfect... **/ + +void GLUI_Main::draw_lowered_box( int x, int y, int w, int h ) +{ + w = w+x; + h = h+y; + + glColor3ub( bkgd_color.r, bkgd_color.g, bkgd_color.b ); + glBegin( GL_LINE_LOOP ); + glVertex2i( x+1, y+1 ); glVertex2i( w-1, y+1 ); + glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 ); + glEnd(); + + glColor3d( 0.0, 0.0, 0.0 ); + glBegin( GL_LINE_STRIP ); + glVertex2i( x, h ); glVertex2i( x, y ); glVertex2i( w, y ); + glEnd(); + + glColor3d( 1.0, 1.0, 1.0 ); + glBegin( GL_LINE_STRIP ); + glVertex2i( w, y ); glVertex2i( w, h ); glVertex2i( x, h ); + glEnd(); + + glColor3d( .5, .5, .5 ); + glBegin( GL_LINE_STRIP ); + glVertex2i( w-1, y+1 ); glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 ); + glEnd(); +} + + +/************************************* GLUI_Main::activate_control() *********/ + +void GLUI_Main::activate_control( GLUI_Control *control, int how ) +{ + /** Are we not activating a control in the same window as the + previous active control? */ + if ( GLUI_Master.active_control_glui AND + this != (GLUI_Main*) GLUI_Master.active_control_glui ) { + GLUI_Master.active_control_glui->deactivate_current_control(); + } + + /******* Now activate it *****/ + if ( control != NULL AND control->can_activate AND control->enabled ) { + active_control = control; + + control->activate(how); + + /*if ( NOT active_control->is_container OR */ + /* active_control->type == GLUI_CONTROL_ROLLOUT) { */ + active_control->redraw(); + /*} */ + } + else { + active_control = NULL; + } + + /* printf( "activate: %d\n", glutGetWindow() ); */ + GLUI_Master.active_control = active_control; + GLUI_Master.active_control_glui = (GLUI*) this; +} + + +/************************* GLUI_Main::deactivate_current_control() **********/ + +void GLUI_Main::deactivate_current_control( void ) +{ + int orig; + + if ( active_control != NULL ) { + orig = active_control->set_to_glut_window(); + + active_control->deactivate(); + + /** If this isn't a container control, then redraw it in its + deactivated state. Container controls, such as panels, look + the same activated or not **/ + + /*if ( NOT active_control->is_container OR */ + /* active_control->type == GLUI_CONTROL_ROLLOUT ) { */ + active_control->redraw(); + /*} */ + + active_control->restore_window( orig ); + + active_control = NULL; + } + + /* printf( "deactivate: %d\n", glutGetWindow() ); */ + GLUI_Master.active_control = NULL; + GLUI_Master.active_control_glui = NULL; +} + + +/****************************** GLUI_Main::find_next_control() **************/ + +GLUI_Control *GLUI_Main::find_next_control_( GLUI_Control *control ) +{ + /*** THIS IS NOT find_next_control()! This is an unused older + version (look at the underscore at the end) ***/ + + if ( control == NULL ) + return find_next_control_rec( main_panel ); + else + return find_next_control_rec( control ); +} + +/****************************** GLUI_Main::find_next_control() **************/ + +GLUI_Control *GLUI_Main::find_next_control_rec( GLUI_Control *control ) +{ + GLUI_Control *child = NULL, *rec_control, *sibling; + + /*** Recursively investigate children ***/ + child = (GLUI_Control*) control->first_child(); + if ( child ) { + /*** If we can activate the first child, then do so ***/ + if ( child->can_activate AND child->enabled ) + return child; + else /*** Recurse into first child ***/ + rec_control = find_next_control_rec( child ); + + if ( rec_control ) + return rec_control; + } + + /*** At this point, either we don't have children, or the child cannot + be activated. So let's try the next sibling ***/ + + sibling = (GLUI_Control*) control->next(); + if ( sibling ) { + if ( sibling->can_activate AND sibling->enabled ) + return sibling; + else /*** Recurse into sibling ***/ + rec_control = find_next_control_rec( sibling ); + + if ( rec_control ) + return rec_control; + } + + return NULL; +} + + +/****************************** GLUI_Main::find_next_control() **************/ + +GLUI_Control *GLUI_Main::find_next_control( GLUI_Control *control ) +{ + GLUI_Control *tmp_control = NULL; + int back_up; + + if ( control == NULL ) + control = main_panel; + + while( control != NULL ) { + /** see if this control has a child **/ + tmp_control = (GLUI_Control*) control->first_child(); + + if ( tmp_control != NULL ) { + if ( tmp_control->can_activate AND tmp_control->enabled ) + return tmp_control; + + control = tmp_control; /* Descend into child */ + continue; + } + + /*** At this point, control has no children ***/ + + /** see if this control has a next sibling **/ + tmp_control = (GLUI_Control*) control->next(); + + if ( tmp_control != NULL ) { + if ( tmp_control->can_activate AND tmp_control->enabled ) + return tmp_control; + + control = tmp_control; + continue; + } + + /** back up until we find a sibling of an ancestor **/ + back_up = true; + while ( control->parent() AND back_up ) { + control = (GLUI_Control*) control->parent(); + + if ( control->next() ) { + control = (GLUI_Control*) control->next(); + if ( control->can_activate AND control->enabled ) + return control; + else + back_up = false; + + /*** if ( control->is_container ) { + tmp_control = control; + control = NULL; + break; + } + else { + back_up = false; + } + ***/ + } + } + + /** Check if we've cycled back to the top... if so, return NULL **/ + if ( control == main_panel ) { + return NULL; + } + } + /* + if ( tmp_control != NULL AND tmp_control->can_activate AND + tmp_control->enabled ) { + return tmp_control; + }*/ + + return NULL; +} + + +/****************************** GLUI_Main::find_prev_control() **************/ + +GLUI_Control *GLUI_Main::find_prev_control( GLUI_Control *control ) +{ + GLUI_Control *tmp_control, *next_control; + + if ( control == NULL ) { /* here we find the last valid control */ + next_control = main_panel; + + do { + tmp_control = next_control; + next_control = find_next_control( tmp_control ); + } while( next_control != NULL ); + + return tmp_control; + } + else { /* here we find the actual previous control */ + next_control = main_panel; + + do { + tmp_control = next_control; + next_control = find_next_control( tmp_control ); + } while( next_control != NULL AND next_control != control ); + + if ( next_control == NULL OR tmp_control == main_panel ) + return NULL; + else + return tmp_control; + } +} + +/************************* GLUI_Master_Object::set_glutIdleFunc() ***********/ + +void GLUI_Master_Object::set_glutIdleFunc(void (*f)(void)) +{ + glut_idle_CB = f; + GLUI_Master.glui_setIdleFuncIfNecessary(); +} + + +/**************************************** GLUI::disable() ********************/ + +void GLUI::disable( void ) +{ + deactivate_current_control(); + main_panel->disable(); +} + + +/******************************************** GLUI::sync_live() **************/ + +void GLUI::sync_live( void ) +{ + main_panel->sync_live(true, true); +} + + +/********************************* GLUI_Master_Object::sync_live_all() *****/ + +void GLUI_Master_Object::sync_live_all( void ) +{ + GLUI *glui; + + glui = (GLUI*) GLUI_Master.gluis.first_child(); + while( glui ) { + + glui->sync_live(); /** sync it **/ + + glui = (GLUI*) glui->next(); + } +} + + +/************************************* GLUI_Master_Object::close() **********/ + +void GLUI_Master_Object::close_all( void ) +{ + GLUI *glui; + + glui = (GLUI*) GLUI_Master.gluis.first_child(); + while( glui ) { + + glui->close(); /** Set flag to close **/ + + glui = (GLUI*) glui->next(); + } +} + + +/************************************* GLUI_Main::close_internal() **********/ + +void GLUI_Main::close_internal( void ) +{ + glutDestroyWindow(glutGetWindow()); /** Close this window **/ + + this->unlink(); + + if ( GLUI_Master.active_control_glui == this ) { + GLUI_Master.active_control = NULL; + GLUI_Master.active_control_glui = NULL; + } + + if ( parent_window != -1 ) { + glutSetWindow( parent_window ); + int win_w = glutGet( GLUT_WINDOW_WIDTH ); + int win_h = glutGet( GLUT_WINDOW_HEIGHT ); + glutReshapeWindow(win_w+1, win_h); + glutReshapeWindow(win_w-1, win_h); + } + + delete this->main_panel; + + delete this; +} + + +/************************************************** GLUI::close() **********/ + +void GLUI::close( void ) +{ + int old_glut_window; + + closing = true; + + old_glut_window = glutGetWindow(); + glutSetWindow( get_glut_window_id() ); + glutPostRedisplay(); + + glutSetWindow( old_glut_window ); +} + + +/************************** GLUI_Main::check_subwindow_position() **********/ + +void GLUI_Main::check_subwindow_position( void ) +{ + /*** Reposition this window if subwindow ***/ + if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) { + + int parent_w, parent_h, new_x, new_y; + int old_window = glutGetWindow(); + + glutSetWindow( glut_window_id ); + + glutSetWindow( glutGet( GLUT_WINDOW_PARENT )); + parent_w = glutGet( GLUT_WINDOW_WIDTH ); + parent_h = glutGet( GLUT_WINDOW_HEIGHT ); + + glutSetWindow( glut_window_id ); + + if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) { + new_x = parent_w - this->w; + new_y = 0; + } + else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) { + new_x = 0; + new_y = 0; + } + else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_BOTTOM )) { + new_x = 0; + new_y = parent_h - this->h; + } + else { /*** GLUI_SUBWINDOW_TOP ***/ + new_x = 0; + new_y = 0; + } + + /** Now make adjustments based on presence of other subwindows **/ + GLUI *curr_glui; + curr_glui = (GLUI*) GLUI_Master.gluis.first_child(); + while( curr_glui ) { + if ( TEST_AND( curr_glui->flags, GLUI_SUBWINDOW) AND + curr_glui->parent_window == this->parent_window ) { + + if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_LEFT ) ) { + } + else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_BOTTOM ) ) { + } + else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_RIGHT ) ) { + } + else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_TOP ) AND + ( TEST_AND( this->flags,GLUI_SUBWINDOW_LEFT ) OR + TEST_AND( this->flags,GLUI_SUBWINDOW_RIGHT ) ) ) { + /** If we are a RIGHT or LEFT subwindow, and there exists some + TOP subwindow, bump our position down **/ + + new_y += curr_glui->h; + } + + /** CHeck multiple subwins at same position **/ + /** We check the glui_id's: only the glui with the higher + ID number (meaning it was created later) gets bumped over **/ + if ( curr_glui != this AND this->glui_id > curr_glui->glui_id ) { + if ( TEST_AND( this->flags,GLUI_SUBWINDOW_LEFT ) AND + TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_LEFT ) ) { + new_x += curr_glui->w; + } + else if ( TEST_AND( this->flags,GLUI_SUBWINDOW_TOP ) AND + TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_TOP ) ) { + new_y += curr_glui->h; + } + else if ( TEST_AND( this->flags,GLUI_SUBWINDOW_BOTTOM ) AND + TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_BOTTOM ) ) { + new_y -= curr_glui->h; + } + else if ( TEST_AND( this->flags,GLUI_SUBWINDOW_RIGHT ) AND + TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_RIGHT ) ) { + new_x -= curr_glui->w; + } + + } + } + + curr_glui = (GLUI*) curr_glui->next(); + } + + + + CLAMP( new_x, 0, new_x ); + CLAMP( new_y, 0, new_y ); + + glutPositionWindow( new_x, new_y ); + /* glutPostRedisplay(); */ + + glutSetWindow( old_window ); + } +} + + +/********************************* GLUI_Master_Object::reshape() **********/ +/* This gets called by the user from a GLUT reshape callback. So we look */ +/* for subwindows that belong to the current window */ + +void GLUI_Master_Object::reshape( void ) +{ + GLUI *glui; + int current_window; + + current_window = glutGetWindow(); + + glui = (GLUI*) GLUI_Master.gluis.first_child(); + while( glui ) { + if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND + glui->parent_window == current_window ) { + glutSetWindow( glui->get_glut_window_id()); + glui->check_subwindow_position(); + } + + glui = (GLUI*) glui->next(); + } + + glutSetWindow(current_window); +} + + +/**************************** GLUI_Master_Object::set_glutReshapeFunc() *****/ + +void GLUI_Master_Object::set_glutReshapeFunc(void (*f)(int width, int height)) +{ + glutReshapeFunc( glui_reshape_func ); + add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_RESHAPE, (void*) f); +} + + +/**************************** GLUI_Master_Object::set_glutKeyboardFunc() ****/ + +void GLUI_Master_Object::set_glutKeyboardFunc(void (*f)(unsigned char key, + int x, int y)) +{ + glutKeyboardFunc( glui_keyboard_func ); + add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_KEYBOARD, (void*) f); +} + + +/*********************** GLUI_Master_Object::set_glutSpecialFunc() **********/ + + + +void GLUI_Master_Object::set_glutSpecialUpFunc(void (*f)(int key, + int x, int y)) +{ + glutSpecialUpFunc( glui_special_up_func ); + add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_SPECIAL_UP, (void*) f); +} + + +void GLUI_Master_Object::set_glutSpecialFunc(void (*f)(int key, + int x, int y)) +{ + glutSpecialFunc( glui_special_func ); + add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_SPECIAL, (void*) f); +} + + +/*********************** GLUI_Master_Object::set_glutMouseFunc() **********/ + +void GLUI_Master_Object::set_glutMouseFunc(void (*f)(int button, int state, + int x, int y)) +{ + glutMouseFunc( glui_mouse_func ); + add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_MOUSE, (void*) f); +} + + +/****************************** glui_parent_window_reshape_func() **********/ +/* This is the reshape callback for a window that contains subwindows */ + +void glui_parent_window_reshape_func( int w, int h ) +{ + int current_window; + GLUI *glui; + int first = true; + + /* printf( "glui_parent_window_reshape_func: %d\n", glutGetWindow() ); */ + + current_window = glutGetWindow(); + + glui = (GLUI*) GLUI_Master.gluis.first_child(); + while( glui ) { + if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND + glui->parent_window == current_window ) { + glutSetWindow( glui->get_glut_window_id()); + glui->check_subwindow_position(); + glutSetWindow( current_window ); + + if ( first ) { + if (glui->glut_reshape_CB) glui->glut_reshape_CB( w, h ); + + first = false; + } + } + + glui = (GLUI*) glui->next(); + } +} + + +/****************************** glui_parent_window_keyboard_func() **********/ + +void glui_parent_window_keyboard_func(unsigned char key, int x, int y) +{ + /* printf( "glui_parent_window_keyboard_func: %d\n", glutGetWindow() ); */ + + int current_window; + GLUI *glui; + + current_window = glutGetWindow(); + + if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control ) { + glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() ); + + GLUI_Master.active_control_glui->keyboard(key,x,y); + + glutSetWindow( current_window ); + } + else { + glui = (GLUI*) GLUI_Master.gluis.first_child(); + while( glui ) { + if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND + glui->parent_window == current_window AND + glui->glut_keyboard_CB ) + { + glui->glut_keyboard_CB( key, x, y ); + break; + } + + glui = (GLUI*) glui->next(); + } + } +} + + +/****************************** glui_parent_window_special_func() **********/ + +void glui_parent_window_special_func(int key, int x, int y) +{ + /*printf( "glui_parent_window_special_func: %d\n", glutGetWindow() ); */ + + int current_window; + GLUI *glui; + + /** If clicking in the main area of a window w/subwindows, + deactivate any current control **/ + if ( GLUI_Master.active_control_glui != NULL ) + GLUI_Master.active_control_glui->deactivate_current_control(); + + /*** Now pass on the mouse event ***/ + + current_window = glutGetWindow(); + + glui = (GLUI*) GLUI_Master.gluis.first_child(); + while( glui ) { + if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND + glui->parent_window == current_window ) + { + glutSetWindow( glui->get_glut_window_id()); + if (glui->glut_special_CB) glui->glut_special_CB( key, x, y ); + break; + } + + glui = (GLUI*) glui->next(); + } +} + + +/****************************** glui_parent_window_mouse_func() **********/ + +void glui_parent_window_mouse_func(int button, int state, int x, int y) +{ + int current_window; + GLUI *glui; + + /** If clicking in the main area of a window w/subwindows, + deactivate any current control **/ + if ( GLUI_Master.active_control_glui != NULL ) + GLUI_Master.active_control_glui->deactivate_current_control(); + + + /*** Now pass on the mouse event ***/ + + current_window = glutGetWindow(); + + glui = (GLUI*) GLUI_Master.gluis.first_child(); + while( glui ) { + if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND + glui->parent_window == current_window AND + glui->glut_mouse_CB) + { + glutSetWindow( glui->get_glut_window_id()); + glui->glut_mouse_CB( button, state, x, y ); + break; + } + + glui = (GLUI*) glui->next(); + } +} + + +/************************** GLUI_Master_Object::find_glut_window() **********/ + +GLUI_Glut_Window *GLUI_Master_Object::find_glut_window( int window_id ) +{ + GLUI_Glut_Window *window; + + window = (GLUI_Glut_Window*) glut_windows.first_child(); + while( window ) { + if ( window->glut_window_id == window_id ) + return window; + + window = (GLUI_Glut_Window*) window->next(); + } + + /*** Window not found - return NULL ***/ + return NULL; +} + + +/******************** GLUI_Master_Object::add_cb_to_glut_window() **********/ + +void GLUI_Master_Object::add_cb_to_glut_window(int window_id, + int cb_type,void *cb) +{ + GLUI_Glut_Window *window; + + window = find_glut_window( window_id ); + if ( NOT window ) { + /*** Allocate new window structure ***/ + + window = new GLUI_Glut_Window; + window->glut_window_id = window_id; + window->link_this_to_parent_last( (GLUI_Node*) &this->glut_windows ); + } + + switch( cb_type ) { + case GLUI_GLUT_RESHAPE: + window->glut_reshape_CB = (void(*)(int,int)) cb; + break; + case GLUI_GLUT_DISPLAY: + window->glut_display_CB = (void(*)()) cb; + break; + case GLUI_GLUT_KEYBOARD: + window->glut_keyboard_CB = (void(*)(unsigned char,int,int)) cb; + break; + case GLUI_GLUT_SPECIAL: + window->glut_special_CB = (void(*)(int,int,int)) cb; + break; + case GLUI_GLUT_SPECIAL_UP: + window->glut_special_up_CB = (void(*)(int,int,int)) cb; + break; + case GLUI_GLUT_MOUSE: + window->glut_mouse_CB = (void(*)(int,int,int,int)) cb; + break; + case GLUI_GLUT_MOTION: + window->glut_motion_CB = (void(*)(int,int)) cb; + break; + case GLUI_GLUT_PASSIVE_MOTION: + window->glut_passive_motion_CB = (void(*)(int,int)) cb; + break; + case GLUI_GLUT_ENTRY: + window->glut_entry_CB = (void(*)(int)) cb; + break; + case GLUI_GLUT_VISIBILITY: + window->glut_visibility_CB= (void(*)(int)) cb; + break; + } +} + + +/************* GLUI_Master_Object::set_left_button_glut_menu_control() *****/ + +void GLUI_Master_Object::set_left_button_glut_menu_control( + GLUI_Control *control ) +{ + curr_left_button_glut_menu = control; +} + + +/******************************* GLUI_Main::set_ortho_projection() **********/ + +void GLUI_Main::set_ortho_projection( void ) +{ + int win_h, win_w; + + win_w = glutGet( GLUT_WINDOW_WIDTH ); + win_h = glutGet( GLUT_WINDOW_HEIGHT ); + + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + /* gluOrtho2D( 0.0, (float) win_w, 0.0, (float) win_h ); */ + glOrtho( 0.0, (float)win_w, 0.0, (float) win_h, -1000.0, 1000.0 ); + + glMatrixMode( GL_MODELVIEW ); + + return; /****-----------------------------------------------***/ + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + + /*** Rotate image so y increases upwards, contrary to OpenGL axes ***/ + glTranslatef( (float) win_w/2.0, (float) win_h/2.0, 0.0 ); + glRotatef( 180.0, 0.0, 1.0, 0.0 ); + glRotatef( 180.0, 0.0, 0.0, 1.0 ); + glTranslatef( (float) -win_w/2.0, (float) -win_h/2.0, 0.0 ); +} + + +/******************************* GLUI_Main::set_viewport() **********/ + +void GLUI_Main::set_viewport( void ) +{ + glViewport( 0, 0, main_panel->w, main_panel->h ); +} + + +/****************************** GLUI_Main::refresh() ****************/ + +void GLUI_Main::refresh( void ) +{ + int orig; + + /****** GLUI_Glut_Window *glut_window; + int current_window; + current_window = glutGetWindow(); + glut_window = GLUI_Master.find_glut_window( current_window ); + if ( glut_window ) { + glut_window->glut_reshape_CB(w,h); + ******/ + + orig = glutGetWindow(); + + pack_controls(); + + if ( glut_window_id > 0 ) + glutSetWindow( glut_window_id ); + + + if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) { + /*** GLUI subwindow ***/ + + check_subwindow_position(); + } + else { + /*** Standalone GLUI window ***/ + + glutReshapeWindow( this->h, this->w ); + + } + + glutPostRedisplay(); + glutSetWindow( orig); +} + + + +/***************** GLUI_Master_Object::get_main_gfx_viewport() ***********/ + +void GLUI_Master_Object::get_viewport_area( int *x, int *y, + int *w, int *h ) +{ + GLUI *curr_glui; + int curr_x, curr_y, curr_w, curr_h; + int curr_window; + + curr_window = glutGetWindow(); + curr_x = 0; + curr_y = 0; + curr_w = glutGet( GLUT_WINDOW_WIDTH ); + curr_h = glutGet( GLUT_WINDOW_HEIGHT ); + + curr_glui = (GLUI*) gluis.first_child(); + while( curr_glui ) { + if ( TEST_AND( curr_glui->flags, GLUI_SUBWINDOW) AND + curr_glui->parent_window == curr_window ) { + + /* printf( "%s -> %d %d %d\n", curr_glui->window_name.c_str(), curr_glui->flags, + curr_glui->w, curr_glui->h );*/ + + if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_LEFT ) ) { + curr_x += curr_glui->w; + curr_w -= curr_glui->w; + } + else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_BOTTOM ) ) { + curr_y += curr_glui->h; + curr_h -= curr_glui->h; + } + else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_RIGHT ) ) { + curr_w -= curr_glui->w; + } + else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_TOP ) ) { + curr_h -= curr_glui->h; + } + } + + curr_glui = (GLUI*) curr_glui->next(); + } + + curr_x = MAX( 0, curr_x ); + curr_y = MAX( 0, curr_y ); + curr_w = MAX( 0, curr_w ); + curr_h = MAX( 0, curr_h ); + + *x = curr_x; + *y = curr_y; + *w = curr_w; + *h = curr_h; +} + + +/*****************GLUI_Master_Object::auto_set_main_gfx_viewport() **********/ + +void GLUI_Master_Object::auto_set_viewport( void ) +{ + int x, y, w, h; + + get_viewport_area( &x, &y, &w, &h ); + glViewport( MAX(x,0), MAX(y,0), MAX(w,0), MAX(h,0) ); +} + + + +/***************************************** GLUI::show() **********************/ + +void GLUI::show( void ) +{ + int orig_window; + + orig_window = main_panel->set_to_glut_window(); + + glutShowWindow(); + + main_panel->restore_window(orig_window); +} + + + +/***************************************** GLUI::hide() **********************/ + +void GLUI::hide( void ) +{ + int orig_window; + + this->deactivate_current_control(); + + orig_window = main_panel->set_to_glut_window(); + + glutHideWindow(); + + main_panel->restore_window(orig_window); +} + + +/**************** GLUI_DrawingSentinal **************/ +GLUI_DrawingSentinal::GLUI_DrawingSentinal(GLUI_Control *c_) + :c(c_) +{ + orig_win = c->set_to_glut_window(); + orig_buf = c->glui->set_current_draw_buffer(); +} +GLUI_DrawingSentinal::~GLUI_DrawingSentinal() { + c->glui->restore_draw_buffer(orig_buf); + c->restore_window(orig_win); +} + + +void GLUI_Master_Object::glui_setIdleFuncIfNecessary( void ) +{ + GLUI *glui; + + glui = (GLUI*) GLUI_Master.gluis.first_child(); + int necessary; + if (this->glut_idle_CB) + necessary = true; + else { + necessary = false; + while( glui ) { + if( glui->needs_idle() ) { + necessary = true; + break; + } + glui = (GLUI*) glui->next(); + } + } + if( necessary ) + glutIdleFunc( glui_idle_func ); + else + glutIdleFunc( NULL ); +} diff --git a/Extras/glui/glui_add_controls.cpp b/Extras/glui/glui_add_controls.cpp new file mode 100644 index 0000000..20ed43d --- /dev/null +++ b/Extras/glui/glui_add_controls.cpp @@ -0,0 +1,319 @@ +/**************************************************************************** + + GLUI User Interface Toolkit (LGPL) + --------------------------- + + glui_add_controls.cpp - Routines for adding controls to a GLUI window + +Note: these routines are all deprecated. Keeping them all here +prevents the linker from dragging in all the .o files, even for controls +that aren't used. + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "GL/glui.h" +#include "glui_internal.h" + + +/*********************************** GLUI:: add_checkbox() ************/ + +GLUI_Checkbox *GLUI:: add_checkbox( const char *name, int *value_ptr, + int id, GLUI_CB callback ) +{ + return add_checkbox_to_panel( main_panel, + name, value_ptr, id, callback ); +} + + +/*********************************** GLUI:: add_checkbox_to_panel() **********/ + +GLUI_Checkbox *GLUI::add_checkbox_to_panel( GLUI_Panel *panel, + const char *name, int *value_ptr, + int id, + GLUI_CB callback ) +{ + return new GLUI_Checkbox( panel, name, value_ptr, id, callback ); +} + +/********************************************* GLUI::add_panel() *************/ + +GLUI_Panel *GLUI::add_panel( const char *name, int type ) +{ + return add_panel_to_panel( main_panel, name, type ); +} + + +/**************************************** GLUI::add_panel_to_panel() *********/ + +GLUI_Panel *GLUI::add_panel_to_panel( GLUI_Panel *parent_panel, + const char *name, int type ) +{ + return new GLUI_Panel( parent_panel, name, type ); +} + + +/***************************** GLUI::add_radiogroup() ***************/ + +GLUI_RadioGroup *GLUI::add_radiogroup( int *value_ptr, + int user_id, GLUI_CB callback) +{ + return add_radiogroup_to_panel( main_panel, value_ptr, + user_id, callback ); +} + + +/***************************** GLUI::add_radiogroup_to_panel() ***************/ + +GLUI_RadioGroup *GLUI::add_radiogroup_to_panel( + GLUI_Panel *panel, int *value_ptr, + int user_id, GLUI_CB callback + ) +{ + return new GLUI_RadioGroup( panel, value_ptr, user_id, callback ); +} + + +/***************************** GLUI::add_radiobutton_to_group() *************/ + +GLUI_RadioButton *GLUI::add_radiobutton_to_group( GLUI_RadioGroup *group, + const char *name ) +{ + return new GLUI_RadioButton( group, name ); +} + + +/********************************** GLUI::add_statictext() ************/ + +GLUI_StaticText *GLUI::add_statictext( const char *name ) +{ + return add_statictext_to_panel( main_panel, name ); +} + + +/******************************* GLUI::add_statictext_to_panel() **********/ + +GLUI_StaticText *GLUI::add_statictext_to_panel( GLUI_Panel *panel, + const char *name ) +{ + return new GLUI_StaticText( panel, name ); +} + + +/***************************************** GLUI:: add_button() ************/ + +GLUI_Button *GLUI:: add_button( const char *name, + int id, GLUI_CB callback ) +{ + return add_button_to_panel( main_panel, + name, id, callback ); +} + +/*********************************** GLUI:: add_button_to_panel() **********/ + +GLUI_Button *GLUI::add_button_to_panel( GLUI_Panel *panel, + const char *name, + int id, + GLUI_CB callback ) +{ + return new GLUI_Button( panel, name, id, callback ); +} + +/********************************** GLUI::add_separator() ************/ + +void GLUI::add_separator( void ) +{ + add_separator_to_panel( main_panel ); +} + + +/******************************* GLUI::add_separator_to_panel() **********/ + +void GLUI::add_separator_to_panel( GLUI_Panel *panel ) +{ + new GLUI_Separator( panel ); +} + + +/********************************** GLUI::add_edittext() ************/ + +GLUI_EditText *GLUI::add_edittext( const char *name, + int data_type, void *data, + int id, GLUI_CB callback) +{ + return add_edittext_to_panel( main_panel, name, data_type, data, + id, callback ); +} + + +/******************************* GLUI::add_edittext_to_panel() **********/ + +GLUI_EditText *GLUI::add_edittext_to_panel( GLUI_Panel *panel, + const char *name, + int data_type, void *data, + int id, GLUI_CB callback) +{ + return new GLUI_EditText( panel, name, data_type, data, id, callback ); +} + +/********************************** GLUI::add_edittext() ************/ + +GLUI_EditText *GLUI::add_edittext( const char *name, + GLUI_String & data, + int id, GLUI_CB callback) +{ + return add_edittext_to_panel( main_panel, name, data, id, callback ); +} + + +/******************************* GLUI::add_edittext_to_panel() **********/ + +GLUI_EditText* +GLUI::add_edittext_to_panel( GLUI_Panel *panel, const char *name, + GLUI_String& data, + int id, GLUI_CB callback) +{ + return new GLUI_EditText( panel, name, GLUI_EDITTEXT_STRING, &data, id, callback ); +} + +/********************************** GLUI::add_spinner() ************/ + +GLUI_Spinner *GLUI::add_spinner( const char *name, + int data_type, void *data, + int id, GLUI_CB callback) +{ + return add_spinner_to_panel( main_panel, name, data_type, data, + id, callback ); +} + + +/******************************* GLUI::add_spinner_to_panel() **********/ + +GLUI_Spinner *GLUI::add_spinner_to_panel( + GLUI_Panel *panel, const char *name, + int data_type, void *data, + int id, GLUI_CB callback +) +{ + return new GLUI_Spinner( panel, name, data_type, data, id, callback ); +} + + +/********************************** GLUI::add_column() ************/ + +void GLUI::add_column( int draw_bar ) +{ + add_column_to_panel( main_panel, draw_bar ); +} + + +/******************************* GLUI::add_column_to_panel() **********/ + +void GLUI::add_column_to_panel( GLUI_Panel *panel, int draw_bar ) +{ + new GLUI_Column( panel, draw_bar ); +} + + +/*********************************** GLUI:: add_listbox() ************/ + +GLUI_Listbox *GLUI:: add_listbox( const char *name, int *value_ptr, + int id, GLUI_CB callback ) +{ + return add_listbox_to_panel( main_panel, + name, value_ptr, id, callback ); +} + + +/*********************************** GLUI:: add_listbox_to_panel() **********/ + +GLUI_Listbox *GLUI::add_listbox_to_panel( GLUI_Panel *panel, + const char *name, int *value_ptr, + int id, + GLUI_CB callback ) +{ + return new GLUI_Listbox( panel, name, value_ptr, id, callback ); +} + + +/*********************************** GLUI:: add_rotation() ************/ + +GLUI_Rotation *GLUI:: add_rotation( const char *name, float *value_ptr, + int id, GLUI_CB callback ) +{ + return add_rotation_to_panel( main_panel, name, value_ptr, id, callback ); +} + + +/*********************************** GLUI:: add_rotation_to_panel() **********/ + +GLUI_Rotation *GLUI::add_rotation_to_panel( GLUI_Panel *panel, + const char *name, float *value_ptr, + int id, + GLUI_CB callback ) +{ + return new GLUI_Rotation( panel, name, value_ptr, id, callback ); +} + + +/*********************************** GLUI:: add_translation() ************/ + +GLUI_Translation *GLUI:: add_translation( const char *name, int trans_type, + float *value_ptr, int id, + GLUI_CB callback ) +{ + return add_translation_to_panel( main_panel,name,trans_type, + value_ptr, id, callback ); +} + + +/*********************************** GLUI:: add_translation_to_panel() **********/ + +GLUI_Translation *GLUI::add_translation_to_panel( + GLUI_Panel *panel, const char *name, + int trans_type, float *value_ptr, + int id, GLUI_CB callback + ) +{ + return new GLUI_Translation(panel, name, trans_type, value_ptr, id, callback); +} + + +/********************************** GLUI::add_rollout() **************/ + +GLUI_Rollout *GLUI::add_rollout( const char *name, int open, int type) +{ + return add_rollout_to_panel( main_panel, name, open, type); +} + + +/****************************** GLUI::add_rollout_to_panel() *********/ + +GLUI_Rollout *GLUI::add_rollout_to_panel(GLUI_Panel *panel, const char *name, + int open, int type) +{ + return new GLUI_Rollout( panel, name, open, type ); +} + + + diff --git a/Extras/glui/glui_bitmap_img_data.cpp b/Extras/glui/glui_bitmap_img_data.cpp new file mode 100644 index 0000000..bfcef31 --- /dev/null +++ b/Extras/glui/glui_bitmap_img_data.cpp @@ -0,0 +1,138 @@ +/** + Bitmaps for all GLUI images. + + These were converted from original PPM images + (mostly lost) with the tools/ppm2array program. + + The images here are extracted in typical OpenGL + bottom-to-top fashion. + + FIXME: don't use greyscale brightness here--this prevents + people changing the background color. Instead, use a code + indicating the underlying purpose of the pixel: + 0 = shadows; outlines; UI elements (check boxes, arrows) + 64 = disabled shadows and UI elements + 128 = shadowing, disabled + 192 = disabled white; background + 255 = highlights; checkbox/radio background + + I'm thinking the way to do this would be to have an +enum { + BG = 0, // Background shines through-- totally alpha transparent + BS, // Background of scrollbar/spin box-- opaque gray + SB, // Shadowed-black element-- strong alpha blend to black + SD, // Shadowed-dark element-- weak alpha blend to black + HL, // Highlight-light-- weak alpha blend to white + HW, // Highlight-white-- strong alpha blend to white + UB, // User-interface black-- arrows, checkboxes, radio buttons + UW, // User-interface white-- backgrounds of checkboxes and radio buttons +}; + + Orion Sky Lawlor, olawlor@acm.org, 2006/05/04 (LGPL) +*/ + +/*----------------------- checkboxes --------------------------*/ +unsigned char glui_img_checkbox_0[] = { 13, 13, /* width, height */ +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 128, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 128, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 128, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 128, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 128, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 128, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 128, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 128, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 128, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 255, +}; + + +unsigned char glui_img_checkbox_0_dis[] = { 13, 13, /* width, height */ +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 128, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 128, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 128, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 128, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 128, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 128, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 128, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 128, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 128, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 255, +}; + + +unsigned char glui_img_checkbox_1[] = { 13, 13, /* width, height */ +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 128, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 128, 0, 255, 255, 255, 0, 255, 255, 255, 255, 255, 192, 255, 128, 0, 255, 255, 0, 0, 0, 255, 255, 255, 255, 192, 255, 128, 0, 255, 0, 0, 0, 0, 0, 255, 255, 255, 192, 255, 128, 0, 255, 0, 0, 255, 0, 0, 0, 255, 255, 192, 255, 128, 0, 255, 0, 255, 255, 255, 0, 0, 0, 255, 192, 255, 128, 0, 255, 255, 255, 255, 255, 255, 0, 0, 255, 192, 255, 128, 0, 255, 255, 255, 255, 255, 255, 255, 0, 255, 192, 255, 128, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 255, +}; + + +unsigned char glui_img_checkbox_1_dis[] = { 13, 13, /* width, height */ +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 128, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 128, 64, 192, 192, 192, 64, 192, 192, 192, 192, 192, 192, 255, 128, 64, 192, 192, 64, 64, 64, 192, 192, 192, 192, 192, 255, 128, 64, 192, 64, 64, 64, 64, 64, 192, 192, 192, 192, 255, 128, 64, 192, 64, 64, 192, 64, 64, 64, 192, 192, 192, 255, 128, 64, 192, 64, 192, 192, 192, 64, 64, 64, 192, 192, 255, 128, 64, 192, 192, 192, 192, 192, 192, 64, 64, 192, 192, 255, 128, 64, 192, 192, 192, 192, 192, 192, 192, 64, 192, 192, 255, 128, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 255, +}; + + +/*------------------------------- arrows -------------------------------------*/ +unsigned char glui_img_downarrow[] = { 16, 16, /* width, height */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 0, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 0, 0, 0, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 0, 0, 0, 0, 0, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 0, 0, 0, 0, 0, 0, 0, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, +}; + + +unsigned char glui_img_leftarrow[] = { 16, 16, /* width, height */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 0, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 0, 0, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 0, 0, 0, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 0, 0, 0, 0, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 0, 0, 0, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 0, 0, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 0, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, +}; + +unsigned char glui_img_rightarrow[] = { 16, 16, /* width, height */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 0, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 0, 0, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 0, 0, 0, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 0, 0, 0, 0, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 0, 0, 0, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 0, 0, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 0, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, +}; + +unsigned char glui_img_uparrow[] = { 16, 16, /* width, height */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 0, 0, 0, 0, 0, 0, 0, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 0, 0, 0, 0, 0, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 0, 0, 0, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 0, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 0, 192, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, +}; + +/*------------------ listboxes ---------------------*/ +unsigned char glui_img_listbox_down[] = { 11, 17, /* width, height */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 0, 127, 191, 191, 191, 191, 191, 191, 191, 191, 127, 0, 127, 191, 191, 191, 191, 191, 191, 191, 191, 127, 0, 127, 191, 191, 191, 191, 191, 191, 191, 191, 127, 0, 127, 191, 191, 191, 191, 191, 191, 191, 191, 127, 0, 127, 191, 191, 191, 191, 191, 191, 191, 191, 127, 0, 127, 191, 191, 191, 191, 127, 191, 191, 191, 127, 0, 127, 191, 191, 191, 127, 127, 127, 191, 191, 127, 0, 127, 191, 191, 127, 127, 127, 127, 127, 191, 127, 0, 127, 191, 191, 191, 191, 191, 191, 191, 191, 127, 0, 127, 191, 191, 191, 191, 191, 191, 191, 191, 127, 0, 127, 191, 191, 191, 191, 191, 191, 191, 191, 127, 0, 127, 191, 191, 191, 191, 191, 191, 191, 191, 127, 0, 127, 191, 191, 191, 191, 191, 191, 191, 191, 127, 0, 127, 191, 191, 191, 191, 191, 191, 191, 191, 127, 0, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 0, +}; + + +unsigned char glui_img_listbox_up[] = { 11, 17, /* width, height */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 127, 127, 127, 127, 127, 127, 127, 127, 127, 0, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 0, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 0, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 0, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 0, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 0, 191, 255, 191, 191, 191, 0, 191, 191, 191, 127, 0, 191, 255, 191, 191, 0, 0, 0, 191, 191, 127, 0, 191, 255, 191, 0, 0, 0, 0, 0, 191, 127, 0, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 0, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 0, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 0, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 0, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 0, 191, 255, 255, 255, 255, 255, 255, 255, 255, 127, 0, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 0, +}; + +unsigned char glui_img_listbox_up_dis[] = { 11, 17, /* width, height */ +127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 191, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 127, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 127, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 127, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 127, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 127, 191, 255, 191, 191, 191, 254, 191, 191, 191, 127, 127, 191, 255, 191, 191, 127, 127, 254, 191, 191, 127, 127, 191, 255, 191, 127, 127, 127, 127, 254, 191, 127, 127, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 127, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 127, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 127, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 127, 191, 255, 191, 191, 191, 191, 191, 191, 191, 127, 127, 191, 255, 255, 255, 255, 255, 255, 255, 255, 127, 127, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 127, +}; + +/*--------------------------- radio buttons -------------------------*/ +unsigned char glui_img_radiobutton_0[] = { 14, 14, /* width, height */ +192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 255, 255, 255, 192, 192, 192, 192, 192, 192, 192, 192, 255, 255, 192, 192, 192, 192, 255, 255, 192, 192, 192, 192, 192, 128, 192, 192, 255, 255, 255, 255, 192, 192, 255, 192, 192, 192, 192, 128, 0, 255, 255, 255, 255, 255, 255, 192, 255, 192, 192, 192, 128, 0, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 192, 192, 128, 0, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 192, 192, 128, 0, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 192, 192, 128, 0, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 192, 192, 192, 128, 0, 255, 255, 255, 255, 255, 255, 192, 255, 192, 192, 192, 192, 128, 0, 0, 255, 255, 255, 255, 0, 0, 255, 192, 192, 192, 192, 192, 128, 128, 0, 0, 0, 0, 128, 128, 192, 192, 192, 192, 192, 192, 192, 192, 128, 128, 128, 128, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, +}; + + +unsigned char glui_img_radiobutton_0_dis[] = { 14, 14, /* width, height */ +192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 255, 255, 255, 192, 192, 192, 192, 192, 192, 192, 192, 255, 255, 192, 192, 192, 192, 255, 255, 192, 192, 192, 192, 192, 128, 192, 192, 192, 192, 192, 192, 192, 192, 255, 192, 192, 192, 192, 128, 64, 192, 192, 192, 192, 192, 192, 192, 255, 192, 192, 192, 128, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 192, 192, 128, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 192, 192, 128, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 192, 192, 128, 64, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 192, 192, 192, 128, 64, 192, 192, 192, 192, 192, 192, 192, 255, 192, 192, 192, 192, 128, 64, 64, 192, 192, 192, 192, 64, 64, 255, 192, 192, 192, 192, 192, 128, 128, 64, 64, 64, 64, 128, 128, 192, 192, 192, 192, 192, 192, 192, 192, 128, 128, 128, 128, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, +}; + + +unsigned char glui_img_radiobutton_1[] = { 14, 14, /* width, height */ +192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 255, 255, 255, 192, 192, 192, 192, 192, 192, 192, 192, 255, 255, 192, 192, 192, 192, 255, 255, 192, 192, 192, 192, 192, 128, 192, 192, 255, 255, 255, 255, 192, 192, 255, 192, 192, 192, 192, 128, 0, 255, 255, 255, 255, 255, 255, 192, 255, 192, 192, 192, 128, 0, 255, 255, 255, 0, 0, 255, 255, 255, 192, 255, 192, 192, 128, 0, 255, 255, 0, 0, 0, 0, 255, 255, 192, 255, 192, 192, 128, 0, 255, 255, 0, 0, 0, 0, 255, 255, 192, 255, 192, 192, 128, 0, 255, 255, 255, 0, 0, 255, 255, 255, 192, 255, 192, 192, 192, 128, 0, 255, 255, 255, 255, 255, 255, 192, 255, 192, 192, 192, 192, 128, 0, 0, 255, 255, 255, 255, 0, 0, 255, 192, 192, 192, 192, 192, 128, 128, 0, 0, 0, 0, 128, 128, 192, 192, 192, 192, 192, 192, 192, 192, 128, 128, 128, 128, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, +}; + + +unsigned char glui_img_radiobutton_1_dis[] = { 14, 14, /* width, height */ +192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 255, 255, 255, 192, 192, 192, 192, 192, 192, 192, 192, 255, 255, 192, 192, 192, 192, 255, 255, 192, 192, 192, 192, 192, 128, 192, 192, 192, 192, 192, 192, 192, 192, 255, 192, 192, 192, 192, 128, 64, 192, 192, 192, 192, 192, 192, 192, 255, 192, 192, 192, 128, 64, 192, 192, 192, 64, 64, 192, 192, 192, 192, 255, 192, 192, 128, 64, 192, 192, 64, 64, 64, 64, 192, 192, 192, 255, 192, 192, 128, 64, 192, 192, 64, 64, 64, 64, 192, 192, 192, 255, 192, 192, 128, 64, 192, 192, 192, 64, 64, 192, 192, 192, 192, 255, 192, 192, 192, 128, 64, 192, 192, 192, 192, 192, 192, 192, 255, 192, 192, 192, 192, 128, 64, 64, 192, 192, 192, 192, 64, 64, 255, 192, 192, 192, 192, 192, 128, 128, 64, 64, 64, 64, 128, 128, 192, 192, 192, 192, 192, 192, 192, 192, 128, 128, 128, 128, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, +}; + + + +/*----------------- spinners ----------------------------*/ +unsigned char glui_img_spindown_0[] = { 12, 8, /* width, height */ +255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 0, 255, 191, 191, 191, 191, 191, 191, 191, 191, 191, 127, 0, 255, 191, 191, 191, 191, 0, 127, 191, 191, 191, 127, 0, 255, 191, 191, 191, 0, 0, 0, 127, 191, 191, 127, 0, 255, 191, 191, 0, 0, 0, 0, 0, 127, 191, 127, 0, 255, 191, 191, 191, 191, 191, 191, 191, 191, 191, 127, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, +}; + + +unsigned char glui_img_spindown_1[] = { 12, 8, /* width, height */ +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 127, 191, 191, 191, 191, 191, 191, 191, 191, 191, 255, 0, 127, 191, 191, 191, 191, 191, 191, 191, 191, 191, 255, 0, 127, 191, 191, 191, 127, 0, 191, 191, 191, 191, 255, 0, 127, 191, 191, 127, 0, 0, 0, 191, 191, 191, 255, 0, 127, 191, 127, 0, 0, 0, 0, 0, 191, 191, 255, 0, 127, 191, 191, 191, 191, 191, 191, 191, 191, 191, 255, 0, 127, 127, 127, 127, 127, 127, 127, 127, 127, 191, 255, +}; + + +unsigned char glui_img_spindown_dis[] = { 12, 8, /* width, height */ +255, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 255, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 64, 255, 191, 191, 191, 191, 191, 191, 191, 191, 191, 127, 64, 255, 191, 191, 191, 191, 127, 255, 191, 191, 191, 127, 64, 255, 191, 191, 191, 127, 127, 127, 255, 191, 191, 127, 64, 255, 191, 191, 127, 127, 127, 127, 127, 255, 191, 127, 64, 255, 191, 191, 191, 191, 191, 191, 191, 191, 191, 127, 64, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 64, +}; + + +unsigned char glui_img_spinup_0[] = { 12, 8, /* width, height */ +255, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 0, 255, 191, 191, 191, 191, 191, 191, 191, 191, 191, 127, 0, 255, 191, 191, 0, 0, 0, 0, 0, 127, 191, 127, 0, 255, 191, 191, 191, 0, 0, 0, 127, 191, 191, 127, 0, 255, 191, 191, 191, 191, 0, 127, 191, 191, 191, 127, 0, 255, 191, 191, 191, 191, 191, 191, 191, 191, 191, 127, 0, 255, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +}; + + +unsigned char glui_img_spinup_1[] = { 12, 8, /* width, height */ + 0, 127, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 127, 191, 191, 191, 191, 191, 191, 191, 191, 191, 255, 0, 127, 191, 127, 0, 0, 0, 0, 0, 191, 191, 255, 0, 127, 191, 191, 127, 0, 0, 0, 191, 191, 191, 255, 0, 127, 191, 191, 191, 127, 0, 191, 191, 191, 191, 255, 0, 127, 191, 191, 191, 191, 191, 191, 191, 191, 191, 255, 0, 127, 127, 127, 127, 127, 127, 127, 127, 127, 191, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, +}; + + +unsigned char glui_img_spinup_dis[] = { 12, 8, /* width, height */ +255, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 64, 255, 191, 191, 191, 191, 191, 191, 191, 191, 191, 127, 64, 255, 191, 191, 127, 127, 127, 127, 127, 255, 191, 127, 64, 255, 191, 191, 191, 127, 127, 127, 255, 191, 191, 127, 64, 255, 191, 191, 191, 191, 127, 255, 191, 191, 191, 127, 64, 255, 191, 191, 191, 191, 191, 191, 191, 191, 191, 127, 64, 255, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 64, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +}; + diff --git a/Extras/glui/glui_bitmaps.cpp b/Extras/glui/glui_bitmaps.cpp new file mode 100644 index 0000000..35d338e --- /dev/null +++ b/Extras/glui/glui_bitmaps.cpp @@ -0,0 +1,176 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_bitmaps.cpp + +Draws the hardcoded images listed in glui_bitmap_img_data with OpenGL. + +FIXME: upload the images to a texture. This will allow them to be: + - Drawn with alpha blending + - Drawn at random sizes and angles onscreen + - Drawn much faster than with glDrawPixels + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "GL/glui.h" +#include "glui_internal.h" +#include + +/************ Image Bitmap arrays **********/ + +extern unsigned char glui_img_checkbox_0[]; +extern unsigned char glui_img_checkbox_1[]; +extern unsigned char glui_img_radiobutton_0[]; +extern unsigned char glui_img_radiobutton_1[]; +extern unsigned char glui_img_uparrow[]; +extern unsigned char glui_img_downarrow[]; +extern unsigned char glui_img_leftarrow[]; +extern unsigned char glui_img_rightarrow[]; +extern unsigned char glui_img_spinup_0[]; +extern unsigned char glui_img_spinup_1[]; +extern unsigned char glui_img_spindown_0[]; +extern unsigned char glui_img_spindown_1[]; +extern unsigned char glui_img_checkbox_0_dis[]; +extern unsigned char glui_img_checkbox_1_dis[]; +extern unsigned char glui_img_radiobutton_0_dis[]; +extern unsigned char glui_img_radiobutton_1_dis[]; +extern unsigned char glui_img_spinup_dis[]; +extern unsigned char glui_img_spindown_dis[]; +extern unsigned char glui_img_listbox_up[]; +extern unsigned char glui_img_listbox_down[]; +extern unsigned char glui_img_listbox_up_dis[]; + + +// These must be in the same order as the GLUI_STDBITMAP enums from glui.h! +unsigned char *bitmap_arrays[] = { + glui_img_checkbox_0, + glui_img_checkbox_1, + glui_img_radiobutton_0, + glui_img_radiobutton_1, + glui_img_uparrow, + glui_img_downarrow, + glui_img_leftarrow, + glui_img_rightarrow, + glui_img_spinup_0, + glui_img_spinup_1, + glui_img_spindown_0, + glui_img_spindown_1, + glui_img_checkbox_0_dis, + glui_img_checkbox_1_dis, + glui_img_radiobutton_0_dis, + glui_img_radiobutton_1_dis, + glui_img_spinup_dis, + glui_img_spindown_dis, + glui_img_listbox_up, + glui_img_listbox_down, + glui_img_listbox_up_dis, +}; + + +/************************************ GLUI_Bitmap::load_from_array() ********/ + +GLUI_Bitmap::GLUI_Bitmap() +: pixels(NULL), + w(0), + h(0) +{ +} + +GLUI_Bitmap::~GLUI_Bitmap() +{ + if (pixels) + { + free(pixels); + pixels = NULL; + } +} + +/* Create bitmap from greyscale byte array */ +void GLUI_Bitmap::init_grey(unsigned char *array) +{ + w = array[0]; h = array[1]; + pixels = (unsigned char *) malloc(w*h*3); + assert(pixels); + + for(int i = 0; i=0 && i=0 && i=0 && iadd_control( this ); +} + + +/****************************** GLUI_Button::mouse_down_handler() **********/ + +int GLUI_Button::mouse_down_handler( int local_x, int local_y ) +{ + int_val = 1; /** A button always in unpressed before here, so + now we invariably set it to 'depressed' **/ + + currently_inside = true; + redraw(); + + return false; +} + + +/****************************** GLUI_Button::mouse_up_handler() **********/ + +int GLUI_Button::mouse_up_handler( int local_x, int local_y, bool inside ) +{ + set_int_val( 0 ); /** A button always turns off after you press it **/ + + currently_inside = false; + redraw(); + + if ( inside ) { + /*** Invoke the user's callback ***/ + execute_callback(); + } + + return false; +} + + +/****************************** GLUI_Button::mouse_held_down_handler() ******/ + +int GLUI_Button::mouse_held_down_handler( int local_x, int local_y, + bool new_inside) +{ + if (new_inside != currently_inside) { + currently_inside = new_inside; + redraw(); + } + + return false; +} + + +/****************************** GLUI_Button::key_handler() **********/ + +int GLUI_Button::key_handler( unsigned char key,int modifiers ) +{ + return false; +} + +/********************************************** GLUI_Button::draw() **********/ + +void GLUI_Button::draw( int x, int y ) +{ + if (currently_inside) draw_pressed(); + else { + glui->draw_raised_box( 0, 0, w, h ); + draw_text( 0 ); + } +} + + +/************************************** GLUI_Button::draw_pressed() ******/ + +void GLUI_Button::draw_pressed( void ) +{ + glColor3f( 0.0, 0.0, 0.0 ); + + draw_text( 1 ); + + glBegin( GL_LINE_LOOP ); + glVertex2i( 0, 0 ); glVertex2i( w, 0 ); + glVertex2i( w, h ); glVertex2i( 0, h ); + glEnd(); + + glBegin( GL_LINE_LOOP ); + glVertex2i( 1, 1 ); glVertex2i( w-1, 1 ); + glVertex2i( w-1, h-1 ); glVertex2i( 1, h-1 ); + glEnd(); +} + + +/**************************************** GLUI_Button::draw_text() **********/ + +void GLUI_Button::draw_text( int sunken ) +{ + int string_width; + + glColor3ub( glui->bkgd_color.r, glui->bkgd_color.g, glui->bkgd_color.b ); + glDisable( GL_CULL_FACE ); + glBegin( GL_QUADS ); + glVertex2i( 2, 2 ); glVertex2i( w-2, 2 ); + glVertex2i( w-2, h-2 ); glVertex2i( 2, h-2 ); + glEnd(); + + glColor3ub( 0,0,0 ); + + string_width = _glutBitmapWidthString( glui->font, + this->name.c_str() ); + if ( NOT sunken ) { + draw_name( MAX((w-string_width),0)/2, 13); + } + else { + draw_name( MAX((w-string_width),0)/2 + 1, 13 + 1); + } + + if ( active ) { + glEnable( GL_LINE_STIPPLE ); + glLineStipple( 1, 0x5555 ); + + glColor3f( 0., 0., 0. ); + + glBegin( GL_LINE_LOOP ); + glVertex2i( 3, 3 ); glVertex2i( w-3, 3 ); + glVertex2i( w-3, h-3 ); glVertex2i( 3, h-3 ); + glEnd(); + + glDisable( GL_LINE_STIPPLE ); + } +} + + +/************************************** GLUI_Button::update_size() **********/ + +void GLUI_Button::update_size( void ) +{ + int text_size; + + if ( NOT glui ) + return; + + text_size = string_width( name ); + + if ( w < text_size + 16 ) + w = text_size + 16 ; +} diff --git a/Extras/glui/glui_checkbox.cpp b/Extras/glui/glui_checkbox.cpp new file mode 100644 index 0000000..ed77b36 --- /dev/null +++ b/Extras/glui/glui_checkbox.cpp @@ -0,0 +1,188 @@ + +/**************************************************************************** + + GLUI User Interface Toolkit (LGPL) + --------------------------- + + glui_checkbox - GLUI_Checkbox control class + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "glui_internal_control.h" + +/****************************** GLUI_Checkbox::GLUI_Checkbox() **********/ + +GLUI_Checkbox::GLUI_Checkbox( GLUI_Node *parent, + const char *name, int *value_ptr, + int id, + GLUI_CB cb ) +{ + common_init(); + + set_ptr_val( value_ptr ); + set_name( name ); + user_id = id; + callback = cb; + + parent->add_control( this ); + + init_live(); +} + +/****************************** GLUI_Checkbox::mouse_down_handler() **********/ + +int GLUI_Checkbox::mouse_down_handler( int local_x, int local_y ) +{ + orig_value = int_val; + int_val = !int_val; + + currently_inside = true; + redraw(); + + return false; +} + + +/****************************** GLUI_Checkbox::mouse_up_handler() **********/ + +int GLUI_Checkbox::mouse_up_handler( int local_x, int local_y, bool inside ) +{ + if ( NOT inside ) { /* undo effect on value */ + int_val = orig_value; + } + else { + set_int_val( int_val ); + + /*** Invoke the callback ***/ + execute_callback(); + } + + return false; +} + + +/****************************** GLUI_Checkbox::mouse_held_down_handler() ******/ + +int GLUI_Checkbox::mouse_held_down_handler( int local_x, int local_y, + bool inside) +{ + /********** Toggle checked and unchecked bitmap if we're entering or + leaving the checkbox area **********/ + if ( inside != currently_inside ) { + int_val = !int_val; + currently_inside = inside; + redraw(); + } + + return false; +} + + +/****************************** GLUI_Checkbox::key_handler() **********/ + +int GLUI_Checkbox::key_handler( unsigned char key,int modifiers ) +{ + return false; +} + + +/****************************** GLUI_Checkbox::draw() **********/ + +void GLUI_Checkbox::draw( int x, int y ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + + if ( int_val != 0 ) { + if ( enabled ) + glui->std_bitmaps.draw( GLUI_STDBITMAP_CHECKBOX_ON, 0, 0 ); + else + glui->std_bitmaps.draw( GLUI_STDBITMAP_CHECKBOX_ON_DIS, 0, 0 ); + } + else { + if ( enabled ) + glui->std_bitmaps.draw( GLUI_STDBITMAP_CHECKBOX_OFF, 0, 0 ); + else + glui->std_bitmaps.draw( GLUI_STDBITMAP_CHECKBOX_OFF_DIS, 0, 0 ); + } + + draw_active_area(); + + draw_name( text_x_offset, 10); +} + +/**************************** GLUI_Checkbox::draw_active_area() **************/ + +void GLUI_Checkbox::draw_active_area( void ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + int text_width, left, right; + + text_width = _glutBitmapWidthString( glui->font, name.c_str() ); + left = text_x_offset-3; + right = left + 7 + text_width; + + if ( active ) { + glEnable( GL_LINE_STIPPLE ); + glLineStipple( 1, 0x5555 ); + glColor3f( 0., 0., 0. ); + } else { + glColor3ub( glui->bkgd_color.r, glui->bkgd_color.g, glui->bkgd_color.b ); + } + + glBegin( GL_LINE_LOOP ); + glVertex2i(left,0); glVertex2i( right,0); + glVertex2i(right,h+1); glVertex2i( left,h+1); + glEnd(); + + glDisable( GL_LINE_STIPPLE ); +} + + +/************************************ GLUI_Checkbox::update_size() **********/ + +void GLUI_Checkbox::update_size( void ) +{ + int text_size; + + if ( NOT glui ) + return; + + text_size = _glutBitmapWidthString( glui->font, name.c_str() ); + + /* if ( w < text_x_offset + text_size + 6 ) */ + w = text_x_offset + text_size + 6 ; +} + + +/********************************* GLUI_Checkbox::set_int_val() **************/ + +void GLUI_Checkbox::set_int_val( int new_val ) +{ + int_val = new_val; + + /*** Update the variable we're (possibly) pointing to ***/ + output_live(true); + redraw(); +} diff --git a/Extras/glui/glui_column.cpp b/Extras/glui/glui_column.cpp new file mode 100644 index 0000000..29901bc --- /dev/null +++ b/Extras/glui/glui_column.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** + GLUI User Interface Toolkit + --------------------------- + + glui_column.cpp - GLUI_Column control class + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "glui_internal_control.h" + +/******************************** GLUI_Column::GLUI_Column() ************/ + +GLUI_Column::GLUI_Column( GLUI_Node *parent, int draw_bar ) +{ + common_init(); + int_val = draw_bar; /* Whether to draw vertical bar or not */ + + parent->add_control( this ); +} + +/**************************************** GLUI_Column::draw() ************/ + +void GLUI_Column::draw( int x, int y ) +{ + int panel_x, panel_y, panel_w, panel_h, panel_x_off, panel_y_off; + int y_diff; + + if ( int_val == 1 ) { /* Draw a vertical bar */ + GLUI_DRAWINGSENTINAL_IDIOM + if ( parent() != NULL ) { + get_this_column_dims(&panel_x, &panel_y, &panel_w, &panel_h, + &panel_x_off, &panel_y_off); + + y_diff = y_abs - panel_y; + + if ( 0 ) { + glLineWidth(1.0); + glBegin( GL_LINES ); + glColor3f( .5, .5, .5 ); + glVertex2i( -GLUI_XOFF+1, -y_diff + GLUI_SEPARATOR_HEIGHT/2 ); + glVertex2i( -GLUI_XOFF+1, -y_diff + panel_h - GLUI_SEPARATOR_HEIGHT/2); + + glColor3f( 1.0, 1.0, 1.0 ); + glVertex2i( -GLUI_XOFF+2, -y_diff + GLUI_SEPARATOR_HEIGHT/2 ); + glVertex2i( -GLUI_XOFF+2, -y_diff + panel_h - GLUI_SEPARATOR_HEIGHT/2); + glEnd(); + } + else { + glLineWidth(1.0); + glBegin( GL_LINES ); + glColor3f( .5, .5, .5 ); + glVertex2i( -2, 0 ); + glVertex2i( -2, h ); + /*glVertex2i( 0, -y_diff + GLUI_SEPARATOR_HEIGHT/2 ); */ + /*glVertex2i( 0, -y_diff + panel_h - GLUI_SEPARATOR_HEIGHT/2); */ + + glColor3f( 1.0, 1.0, 1.0 ); + glVertex2i( -1, 0 ); + glVertex2i( -1, h ); + /*glVertex2i( 1, -y_diff + GLUI_SEPARATOR_HEIGHT/2 ); */ + /*glVertex2i( 1, -y_diff + panel_h - GLUI_SEPARATOR_HEIGHT/2); */ + glEnd(); + } + } + } +} + diff --git a/Extras/glui/glui_commandline.cpp b/Extras/glui/glui_commandline.cpp new file mode 100644 index 0000000..7586598 --- /dev/null +++ b/Extras/glui/glui_commandline.cpp @@ -0,0 +1,197 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_commandline.cpp - GLUI_CommandLine control class + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher, 2005 William Baxter + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA + + This program is -not- in the public domain. + +*****************************************************************************/ + +#include "GL/glui.h" +#include "glui_internal.h" + +/****************************** GLUI_CommandLine::GLUI_CommandLine() **********/ +GLUI_CommandLine::GLUI_CommandLine( GLUI_Node *parent, const char *name, + void *data, int id, GLUI_CB cb ) +{ + common_init(); + set_name( name ); + + data_type = GLUI_EDITTEXT_TEXT; + ptr_val = data; + user_id = id; + callback = cb; + + live_type = GLUI_LIVE_TEXT; + + parent->add_control( this ); + + init_live(); +} + +/****************************** GLUI_CommandLine::key_handler() **********/ + +int GLUI_CommandLine::key_handler( unsigned char key,int modifiers ) +{ + int ret; + + if ( NOT glui ) + return false; + + if ( debug ) + dump( stdout, "-> CMD_TEXT KEY HANDLER" ); + + if ( key == 13 ) { /* RETURN */ + commit_flag = true; + } + + ret = Super::key_handler( key, modifiers ); + + if ( debug ) + dump( stdout, "<- CMD_TEXT KEY HANDLER" ); + + return ret; +} + + +/****************************** GLUI_CommandLine::deactivate() **********/ + +void GLUI_CommandLine::deactivate( void ) +{ + // if the commit_flag is set, add the current command to + // history and call deactivate as normal + + // Trick deactivate into calling callback if and only if commit_flag set. + // A bit subtle, but deactivate checks that orig_text and text + // are the same to decide whether or not to call the callback. + // Force them to be different for commit, and the same for no commit. + if (commit_flag) { + add_to_history(text.c_str()); + orig_text = ""; + Super::deactivate( ); + set_text( "" ); + commit_flag = false; + } + else { + orig_text = text; + } +} + +/**************************** GLUI_CommandLine::special_handler() **********/ + +int GLUI_CommandLine::special_handler( int key,int modifiers ) +{ + if ( NOT glui ) + return false; + + if ( debug ) + printf( "CMD_TEXT SPECIAL:%d - mod:%d subs:%d/%d ins:%d sel:%d/%d\n", + key, modifiers, substring_start, substring_end,insertion_pt, + sel_start, sel_end ); + + if ( key == GLUT_KEY_UP ) // PREVIOUS HISTORY + { + scroll_history(-1); + } + else if ( key == GLUT_KEY_DOWN ) // NEXT HISTORY + { + scroll_history(+1); + } + else { + return Super::special_handler( key, modifiers ); + } + return false; +} + + + +/**************************** GLUI_CommandLine::scroll_history() ********/ + +void GLUI_CommandLine::scroll_history( int direction ) +{ + recall_history(curr_hist + direction); +} + +/**************************** GLUI_CommandLine::recall_history() ********/ + +void GLUI_CommandLine::recall_history( int hist_num ) +{ + if (hist_num < oldest_hist OR + hist_num > newest_hist OR + hist_num == curr_hist) + return; + + // Commit the current text first before we blow it away! + if (curr_hist == newest_hist) { + get_history_str(newest_hist) = text; + } + + curr_hist = hist_num; + set_text(get_history_str(curr_hist)); + sel_end = sel_start = insertion_pt = (int)text.length(); + update_and_draw_text(); +} + +/**************************** GLUI_CommandLine::add_to_history() ********/ + +void GLUI_CommandLine::add_to_history( const char *cmd ) +{ + if (cmd[0]=='\0') return; // don't add if it's empty + + curr_hist = newest_hist; + get_history_str(newest_hist) = text; + + newest_hist = ++curr_hist; + if ( newest_hist >= HIST_SIZE ) + { + // bump oldest off the list + hist_list.erase(hist_list.begin()); + hist_list.push_back(""); + + oldest_hist++; + } +} + +/**************************** GLUI_CommandLine::reset_history() ********/ + +void GLUI_CommandLine::reset_history( void ) +{ + oldest_hist = newest_hist = curr_hist = 0; +} + + + +/*************************************** GLUI_CommandLine::dump() **************/ + +void GLUI_CommandLine::dump( FILE *out, const char *name ) +{ + fprintf( out, + "%s (commandline@%p): ins_pt:%d subs:%d/%d sel:%d/%d len:%d\n", + name, this, + insertion_pt, substring_start, substring_end, sel_start, sel_end, + (int)text.length()); +} + + diff --git a/Extras/glui/glui_control.cpp b/Extras/glui/glui_control.cpp new file mode 100644 index 0000000..576a2a9 --- /dev/null +++ b/Extras/glui/glui_control.cpp @@ -0,0 +1,1203 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_control.cpp - top-level GLUI_Control class + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "glui_internal_control.h" + +int _glui_draw_border_only = 0; + +/*************************** Drawing Utility routines *********************/ + +/* Redraw this control. */ +void GLUI_Control::redraw(void) { + if (glui==NULL || hidden) return; + if (glui->should_redraw_now(this)) + translate_and_draw_front(); +} + +/** Redraw everybody in our window. */ +void GLUI_Control::redraw_window(void) { + if (glui==NULL || hidden) return; + if ( glui->get_glut_window_id() == -1 ) return; + int orig = set_to_glut_window(); + glutPostRedisplay(); + restore_window(orig); +} + + + +/* GLUI_Control::translate_and_draw_front() ********/ + +void GLUI_Control::translate_and_draw_front() +{ + GLUI_DRAWINGSENTINAL_IDIOM + + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + translate_to_origin(); + draw(0,0); + glPopMatrix(); +} + + +/********** GLUI_Control::set_to_bkgd_color() ********/ + +void GLUI_Control::set_to_bkgd_color( void ) +{ + if ( NOT glui ) + return; + + glColor3ub( glui->bkgd_color.r, glui->bkgd_color.g, glui->bkgd_color.b ); +} + +/******** GLUI_Control::draw_box_inwards_outline() ********/ + +void GLUI_Control::draw_box_inwards_outline( int x_min, int x_max, int y_min, int y_max ) +{ + glBegin( GL_LINES ); + glColor3f( .5, .5, .5 ); + glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min ); + glVertex2i( x_min, y_min ); glVertex2i( x_min, y_max ); + + glColor3f( 1., 1., 1. ); + glVertex2i( x_min, y_max ); glVertex2i( x_max, y_max ); + glVertex2i( x_max, y_max ); glVertex2i( x_max, y_min ); + + if ( enabled ) + glColor3f( 0., 0., 0. ); + else + glColor3f( .25, .25, .25 ); + + glVertex2i( x_min+1, y_min+1 ); glVertex2i( x_max-1, y_min+1 ); + glVertex2i( x_min+1, y_min+1 ); glVertex2i( x_min+1, y_max-1 ); + + glColor3f( .75, .75, .75 ); + glVertex2i( x_min+1, y_max-1 ); glVertex2i( x_max-1, y_max-1 ); + glVertex2i( x_max-1, y_max-1 ); glVertex2i( x_max-1, y_min+1 ); + glEnd(); +} + + +/******* GLUI_Control::draw_box() **********/ + +void GLUI_Control::draw_box( int x_min, int x_max, int y_min, int y_max, float r, float g, float b) +{ + if ( r == 1.0 AND g == 1.0 AND b == 1.0 AND NOT enabled AND glui ) { + draw_bkgd_box( x_min, x_max, y_min, y_max ); + return; + } + + glColor3f( r, g, b ); + glBegin( GL_QUADS ); + glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min ); + glVertex2i( x_max, y_max ); glVertex2i( x_min, y_max ); + glEnd(); +} + + +/******* GLUI_Control::draw_bkgd_box() **********/ + +void GLUI_Control::draw_bkgd_box( int x_min, int x_max, int y_min, int y_max ) +{ + set_to_bkgd_color(); + + glBegin( GL_QUADS ); + glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min ); + glVertex2i( x_max, y_max ); glVertex2i( x_min, y_max ); + glEnd(); +} + + +/**** GLUI_Control::draw_active_area() ********/ + +void GLUI_Control::draw_active_box( int x_min, int x_max, int y_min, int y_max ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + + if ( active ) { + glEnable( GL_LINE_STIPPLE ); + glLineStipple( 1, 0x5555 ); + glColor3f( 0., 0., 0. ); + } else { + set_to_bkgd_color(); + } + + glBegin( GL_LINE_LOOP ); + glVertex2i(x_min, y_min); glVertex2i( x_max, y_min ); + glVertex2i(x_max, y_max); glVertex2i( x_min, y_max ); + glEnd(); + + glDisable( GL_LINE_STIPPLE ); +} + + +/**** GLUI_Control::draw_emboss_box() ********/ + +void GLUI_Control::draw_emboss_box(int x_min,int x_max,int y_min,int y_max) +{ + glLineWidth( 1.0 ); + glColor3f( 1.0, 1.0, 1.0 ); + + glBegin( GL_LINE_LOOP ); + glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min ); + glVertex2i( x_max, y_max ); glVertex2i( x_min, y_max ); + glEnd(); + + glBegin( GL_LINE_LOOP ); + glVertex2i( x_min+1, y_min+1 ); glVertex2i( x_max-1, y_min+1 ); + glVertex2i( x_max-1, y_max-1 ); glVertex2i( x_min+1, y_max-1 ); + glEnd(); + + glColor3f( .5, .5, .5 ); + glBegin( GL_LINE_LOOP ); + glVertex2i( x_min, y_min ); + glVertex2i( x_max-1, y_min ); + glVertex2i( x_max-1, y_max-1 ); + glVertex2i( x_min, y_max-1 ); + glEnd(); +} + + + +/******* GLUT_Control::draw_recursive() **********/ + +void GLUI_Control::draw_recursive( int x, int y ) +{ + GLUI_Control *node; + + /* printf( "%s %d\n", this->name.c_str(), this->hidden );*/ + if ( NOT can_draw() ) + return; + + /*if ( 1 ) { -- Debugging to check control width + glColor3f( 1.0, 0.0, 0.0 ); + glBegin( GL_LINES ); + glVertex2i( x_abs, y_abs );00 + glVertex2i( x_abs+w, y_abs ); + + glEnd(); + }*/ + + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + + glTranslatef( (float) this->x_abs + .5, + (float) this->y_abs + .5, + 0.0 ); + + if ( NOT _glui_draw_border_only ) { + if ( NOT strcmp( name.c_str(), "Rollout" ) ) { + } + + this->draw( this->x_off, this->y_off_top ); + } + else + { + if ( this->dynamicCastGLUI_Column() ) { + /* printf( "%s w/h: %d/%d\n", (char*) name, w, h ); */ + /*w = 2; */ + } + + /* The following draws the area of each control */ + glColor3f( 1.0, 0.0, 0.0 ); + glBegin( GL_LINE_LOOP ); + glVertex2i( 0, 0 ); glVertex2i( w, 0 ); + glVertex2i( w, h ); glVertex2i( 0, h ); + glEnd(); + } + glPopMatrix(); + + node = (GLUI_Control*) first_child(); + while( node ) { + node->draw_recursive( node->x_abs, node->y_abs ); + node = (GLUI_Control*) node->next(); + } +} + + +/****** GLUI_Control::set_to_glut_window() *********/ +/* Sets the current window to the glut window associated with this control */ + +int GLUI_Control::set_to_glut_window() +{ + int orig_window; + + if ( NOT glui) + return 1; + + orig_window = glutGetWindow(); + + glutSetWindow( glui->get_glut_window_id()); + + return orig_window; +} + + +/********** GLUI_Control::restore_window() *********/ + +void GLUI_Control::restore_window(int orig) +{ + if ( orig > 0 ) + glutSetWindow( orig ); +} + + + +/****************************** Text ***************************/ + +/*************** GLUI_Control::set_font() **********/ + +void GLUI_Control::set_font(void *new_font) +{ + font = new_font; + redraw(); +} + + +/********** GLUI_Control::draw_string() ************/ + +void GLUI_Control::draw_string( const char *text ) +{ + _glutBitmapString( get_font(), text ); +} + + +/**************** GLUI_Control::draw_char() ********/ + +void GLUI_Control::draw_char(char c) +{ + glutBitmapCharacter( get_font(), c ); +} + + +/*********** GLUI_Control::string_width() **********/ + +int GLUI_Control::string_width(const char *text) +{ + return _glutBitmapWidthString( get_font(), text ); +} + + +/************* GLUI_Control::char_width() **********/ + +int GLUI_Control::char_width(char c) +{ /* Hash table for faster character width lookups - JVK + Speeds up the textbox a little bit. + */ + int hash_index = c % CHAR_WIDTH_HASH_SIZE; + if (char_widths[hash_index][0] != c) { + char_widths[hash_index][0] = c; + char_widths[hash_index][1] = glutBitmapWidth( get_font(), c ); + } + return char_widths[hash_index][1]; +} + + +/*************** GLUI_Control::get_font() **********/ + +void *GLUI_Control::get_font( void ) +{ + /*** Does this control have its own font? ***/ + if ( this->font != NULL ) + return this->font; + + /*** Does the parent glui have a font? ***/ + if ( glui ) + return glui->font; + + /*** Return the default font ***/ + return GLUT_BITMAP_HELVETICA_12; +} + + +/************* GLUI_Control::draw_name() ***********/ +/* This draws the name of the control as either black (if enabled), or */ +/* embossed if disabled. */ + +void GLUI_Control::draw_name(int x, int y) +{ + if ( NOT can_draw() ) + return; + + if ( enabled ) + { + set_to_bkgd_color(); + glRasterPos2i(x+1, y+1); + draw_string(name); + glColor3b( 0, 0, 0 ); + glRasterPos2i(x, y); + draw_string(name); + } + else + { /* Control is disabled - emboss the string */ + glColor3f( 1.0f, 1.0f, 1.0f ); + glRasterPos2i(x+1, y+1); + draw_string(name); + glColor3f( .4f, .4f, .4f ); + glRasterPos2i(x, y); + draw_string(name); + } +} + + +/**************************** Layout and Packing *********************/ + +/****** GLUI_Control::align() **************/ + +void GLUI_Control::align() +{ + int col_x, col_y, col_w, col_h, col_x_off, col_y_off; + int orig_x_abs; + + orig_x_abs = x_abs; + + /* Fix alignment bug relating to columns */ + /*return; */ + + if ( NOT parent() ) + return; /* Clearly this shouldn't happen, though */ + + get_this_column_dims(&col_x, &col_y, &col_w, &col_h, + &col_x_off, &col_y_off); + + if ( this->dynamicCastGLUI_Column() ) { + /* if ( this->prev() != NULL ) { + ((GLUI_Control*)prev())->get_this_column_dims(&col_x, &col_y, &col_w, &col_h, + &col_x_off, &col_y_off); + + x_abs = col_x + col_w; + } + else { + x_abs = ((GLUI_Control*)parent())->x_abs; + } + */ + return; + } + + if ( alignment == GLUI_ALIGN_LEFT ) { + x_abs = col_x + col_x_off; + } + else if ( alignment == GLUI_ALIGN_RIGHT ) { + x_abs = col_x + col_w - col_x_off - this->w; + } + else if ( alignment == GLUI_ALIGN_CENTER ) { + x_abs = col_x + (col_w - this->w) / 2; + } + + if ( this->is_container ) { + /*** Shift all child columns ***/ + int delta = x_abs - orig_x_abs; + + GLUI_Control *node; + + node = (GLUI_Control*) this->first_child(); + while( node != NULL ) { + if ( node->dynamicCastGLUI_Column() ) { + node->x_abs += delta; + } + + node = (GLUI_Control*) node->next(); + } + } + +} + + +/************** GLUI_Control::pack() ************/ +/* Recalculate positions and offsets */ + +void GLUI_Control::pack_old(int x, int y) +{ + GLUI_Control *node; + int max_w, curr_y, curr_x, max_y; + int x_in = x, y_in =y; + int x_margin, y_margin_top, y_margin_bot; + int y_top_column; + int column_x; + GLUI_Column *curr_column = NULL; + this->update_size(); + x_margin = this->x_off; + y_margin_top = this->y_off_top; + y_margin_bot = this->y_off_bot; + this->x_abs = x_in; + this->y_abs = y_in; + max_w = -1; + max_y = -1; + curr_x = this->x_abs + x_margin; + curr_y = this->y_abs + y_margin_top; + /*** Record start of this set of columns ***/ + y_top_column = curr_y; + column_x = 0; + if ( this == glui->main_panel ) { + x=x; + } + /*** Iterate over children, packing them first ***/ + node = (GLUI_Control*) this->first_child(); + while( node != NULL ) { + if ( node->dynamicCastGLUI_Panel() && !node->collapsible) { + /* Pad some space above fixed size panels */ + curr_y += GLUI_ITEMSPACING; + } + else if ( node->dynamicCastGLUI_Column()) { + curr_column = (GLUI_Column*) node; + if ( 1 ) { + column_x += max_w + 2 * x_margin; + curr_x += max_w + 2 * x_margin; + } + else { + column_x += max_w + 0 * x_margin; + curr_x += max_w + 0 * x_margin; + } + /*node->pack( curr_x, curr_y ); */ + node->x_abs = curr_x; + node->y_abs = y_top_column; + node->w = 2; + node->h = curr_y - y_top_column; + curr_x += x_margin * 3 + 40; + curr_y = y_top_column; + max_w = 0; + node = (GLUI_Control*) node->next(); + continue; + } + node->pack( curr_x, curr_y ); + if ( node->dynamicCastGLUI_Panel() && !node->collapsible) + /* Pad some space below fixed size panels */ + curr_y += GLUI_ITEMSPACING; + curr_y += node->h; + if ( node->w > max_w ) { + max_w = node->w; + if ( curr_column != NULL ) + curr_column->w = max_w; + } + node = (GLUI_Control*) node->next(); + if ( node ) { + curr_y += GLUI_ITEMSPACING; + } + if ( curr_y > max_y ) + max_y = curr_y; + } + if ( this->is_container ) { + max_y += y_margin_bot; /*** Add bottom border inside box */ + if ( this->first_child() ) { + if ( this->dynamicCastGLUI_Rollout() ) { + /** We don't want the rollout to shrink in width when it's + closed **/ + this->w = MAX(this->w, column_x + max_w + 2 * x_margin ); + } + else { + this->w = column_x + max_w + 2 * x_margin; + } + this->h = (max_y - y_in); + } + else { /* An empty container, so just assign default w & h */ + this->w = GLUI_DEFAULT_CONTROL_WIDTH; + this->h = GLUI_DEFAULT_CONTROL_HEIGHT; + } + /** Expand panel if necessary (e.g., to include all the text in + a panel label) **/ + this->update_size(); + } +} + +/*** GLUI_Control::get_this_column_dims() **********/ +/* Gets the x,y,w,h,and x/y offsets of the column to which a control belongs */ + +void GLUI_Control::get_this_column_dims( int *col_x, int *col_y, + int *col_w, int *col_h, + int *col_x_off, int *col_y_off ) +{ + GLUI_Control *node, *parent_ptr; + int parent_h, parent_y_abs; + + parent_ptr = (GLUI_Control*) parent(); + + if ( parent_ptr==NULL ) + return; + + parent_h = parent_ptr->h; + parent_y_abs = parent_ptr->y_abs; + + if ( parent_ptr->dynamicCastGLUI_Panel() AND + parent_ptr->int_val == GLUI_PANEL_EMBOSSED AND + parent_ptr->name != "" ) { + parent_h -= GLUI_PANEL_EMBOSS_TOP; + parent_y_abs += GLUI_PANEL_EMBOSS_TOP; + } + + if ( 0 ) { + GLUI_Node *first, *last, *curr; + + /** Look for first control in this column **/ + first = this; + while (first->prev() AND !(first->prev())->dynamicCastGLUI_Column() ) + first = first->prev(); + + /** Look for last control in this column **/ + last = this; + while ( last->next() AND !(first->next())->dynamicCastGLUI_Column() ) + last = last->next(); + + curr = first; + int max_w = -1; + do { + if ( ((GLUI_Control*)curr)->w > max_w ) + max_w = ((GLUI_Control*)curr)->w; + + if ( curr == last ) + break; + + curr = curr->next(); + } while( curr != NULL ); + + *col_x = ((GLUI_Control*)first)->x_abs; + *col_y = ((GLUI_Control*)first)->y_abs; + *col_w = max_w; + if ( parent() ) { + *col_h = ((GLUI_Control*)parent())->h; + *col_x_off = ((GLUI_Control*)parent())->x_off; + } + else { + *col_h = 10; + *col_x_off = 0; + } + *col_y_off = 0; + + return; + } + + if ( 1 ) { /* IS THIS WRONG? */ + /*** Look for preceding column ***/ + node = (GLUI_Control*) this->prev(); + while( node ) { + if ( node->dynamicCastGLUI_Column() ) { + *col_x = node->x_abs; + *col_y = parent_y_abs; + *col_w = node->w; + *col_h = parent_h; + *col_x_off = node->x_off; + *col_y_off = 0; + + return; + } + + node = (GLUI_Control*) node->prev(); + } + + /*** Nope, Look for next column ***/ + node = (GLUI_Control*) this->next(); + while( node ) { + if ( node->dynamicCastGLUI_Column() ) { + *col_x = parent_ptr->x_abs; + *col_y = parent_y_abs; + *col_w = node->x_abs - parent_ptr->x_abs; + *col_h = parent_h; + *col_x_off = node->x_off; + *col_y_off = 0; + + return; + } + + node = (GLUI_Control*) node->next(); + } + + /*** This is single-column panel, so return panel dims ***/ + *col_x = parent_ptr->x_abs; + *col_y = parent_y_abs; + *col_w = parent_ptr->w; + *col_h = parent_h; + *col_x_off = parent_ptr->x_off; + *col_y_off = 0; + } +} + + +void GLUI_Control::pack( int x, int y ) +{ + GLUI_Control *node; + int max_w, curr_y, curr_x, max_y; + int x_in = x, y_in =y; + int x_margin, y_margin_top, y_margin_bot; + int y_top_column; + int column_x; + GLUI_Column *curr_column = NULL; + + this->update_size(); + + x_margin = this->x_off; + y_margin_top = this->y_off_top; + y_margin_bot = this->y_off_bot; + + this->x_abs = x_in; + this->y_abs = y_in; + + max_w = 0; + max_y = 0; + curr_x = this->x_abs + x_margin; + curr_y = this->y_abs + y_margin_top; + + /*** Record start of this set of columns ***/ + + y_top_column = curr_y; + column_x = curr_x; + + /*** Iterate over children, packing them first ***/ + + node = (GLUI_Control*) this->first_child(); + while( node != NULL ) { + if ( node->dynamicCastGLUI_Panel() && !node->collapsible) { + /* Pad some space above fixed-size panels */ + curr_y += GLUI_ITEMSPACING; + } + else if ( node->dynamicCastGLUI_Column() ) { + curr_column = (GLUI_Column*) node; + curr_x += max_w + 1 * x_margin; + column_x = curr_x; + + node->x_abs = curr_x; + node->y_abs = y_top_column; + node->w = 2; + node->h = curr_y - y_top_column; + + curr_x += x_margin * 1; + curr_y = y_top_column; + max_w = 0; + + node = (GLUI_Control*) node->next(); + continue; + } + + node->pack( curr_x, curr_y ); + + if ( node->dynamicCastGLUI_Panel() && !node->collapsible) + /* Pad some space below fixed-size panels */ + curr_y += GLUI_ITEMSPACING; + + curr_y += node->h; + + if ( node->w > max_w ) { + max_w = node->w; + if ( curr_column != NULL ) + curr_column->w = max_w + x_margin; + } + + if ( curr_y > max_y ) { + max_y = curr_y; + if ( curr_column != NULL ) + curr_column->h = max_y - y_top_column; + } + + node = (GLUI_Control*) node->next(); + + if ( node ) { + curr_y += GLUI_ITEMSPACING; + } + + } + + if ( this->is_container ) { + max_y += y_margin_bot; /*** Add bottom border inside box */ + + if ( this->first_child() ) { + this->w = column_x + max_w + 2 * x_margin - x_in; + this->h = (max_y - y_in); + } + else { /* An empty container, so just assign default w & h */ + if ( !this->dynamicCastGLUI_Rollout() && + !this->dynamicCastGLUI_Tree() ) { + this->w = GLUI_DEFAULT_CONTROL_WIDTH; + this->h = GLUI_DEFAULT_CONTROL_HEIGHT; + } + } + + /** Expand panel if necessary (e.g., to include all the text in + a panel label) **/ + this->update_size(); + + + /*** Now we step through the GLUI_Columns, setting the 'h' ***/ + node = (GLUI_Control*) this->first_child(); + while( node != NULL ) { + if ( node->dynamicCastGLUI_Column() ) { + node->h = this->h - y_margin_bot - y_margin_top; + } + + node = (GLUI_Control*) node->next(); + } + } +} + + + +/******************************** Live Variables **************************/ +/*********** GLUI_Control::sync_live() ************/ +/* Reads live variable and sets control to its current value */ +/* This function is recursive, and operates on control's children */ + +void GLUI_Control::sync_live(int recurse, int draw_it) +{ + GLUI_Node *node; + int sync_it=true; + int i; + float *fp; + bool changed = false; + + /*** If this is currently active control, and mouse button is down, + don't sync ***/ + if ( glui ) + { + if ( this == glui->active_control AND glui->mouse_button_down ) + sync_it = false; + + /*** Actually, just disable syncing if button is down ***/ + /*** Nope, go ahead and sync if mouse is down - this allows syncing in + callbacks ***/ + if ( 0 ) { /* THIS CODE BELOW SHOULD NOT BE EXECUTED */ + if ( glui->mouse_button_down ) { + /* printf( "Can't sync\n" ); */ + return; + } + } + } + + /*** If this control has a live variable, we check its current value + against the stored value in the control ***/ + + if ( ptr_val != NULL ) { + if ( live_type == GLUI_LIVE_NONE OR NOT sync_it ) { + } + else if ( live_type == GLUI_LIVE_INT ) { + if ( *((int*)ptr_val) != last_live_int ) { + set_int_val( *((int*)ptr_val) ); + last_live_int = *((int*)ptr_val); + changed = true; + } + } + else if ( live_type == GLUI_LIVE_FLOAT ) { + if ( *((float*)ptr_val) != last_live_float ) { + set_float_val( *((float*)ptr_val) ); + last_live_float = *((float*)ptr_val); + changed = true; + } + } + else if ( live_type == GLUI_LIVE_TEXT ) { + if ( last_live_text.compare((const char*)ptr_val) != 0 ) { + set_text( (char*) ptr_val ); + last_live_text = (const char*)ptr_val; + changed = true; + } + } + else if ( live_type == GLUI_LIVE_STRING ) { + if ( last_live_text.compare(((std::string*) ptr_val)->c_str()) != 0 ) { + set_text( ((std::string*) ptr_val)->c_str()); + last_live_text = *((std::string*) ptr_val); + changed = true; + } + } + else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) { + /*** Step through the arrays, and see if they're the same ***/ + + fp = (float*) ptr_val; + for ( i=0; ifirst_child(); + while( node ) { + ((GLUI_Control*) node)->sync_live(true, true); + node = node->next(); + } + + if ( collapsible == true AND is_open == false ) { + /** Here we have a collapsed control (e.g., a rollout that is closed **/ + /** We need to go in and sync all the collapsed controls inside **/ + + node = this->collapsed_node.first_child(); + while( node ) { + ((GLUI_Control*) node)->sync_live(true, false); + node = node->next(); + } + } + } +} + + +/********** GLUI_Control::output_live() ************/ +/* Writes current value of control to live variable. */ + +void GLUI_Control::output_live(int update_main_gfx) +{ + int i; + float *fp; + + if ( ptr_val == NULL ) + return; + + if ( NOT live_inited ) + return; + + if ( live_type == GLUI_LIVE_NONE ) { + } + else if ( live_type == GLUI_LIVE_INT ) { + *((int*)ptr_val) = int_val; + last_live_int = int_val; + } + else if ( live_type == GLUI_LIVE_FLOAT ) { + *((float*)ptr_val) = float_val; + last_live_float = float_val; + } + else if ( live_type == GLUI_LIVE_TEXT ) { + strncpy( (char*) ptr_val, text.c_str(), text.length()+1); + last_live_text = text; + } + else if ( live_type == GLUI_LIVE_STRING ) { + (*(std::string*)ptr_val)= text.c_str(); + last_live_text = text; + } + else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) { + fp = (float*) ptr_val; + + for( i=0; iglui != NULL ) { + this->glui->post_update_main_gfx(); + } +} + + +/****** GLUI_Control::execute_callback() **********/ + +void GLUI_Control::execute_callback() +{ + int old_window; + + old_window = glutGetWindow(); + + if ( glui AND glui->main_gfx_window_id != -1 ) + glutSetWindow( glui->main_gfx_window_id ); + + this->callback( this ); +// if ( this->callback ) +// this->callback( this->user_id ); + + glutSetWindow( old_window ); +} + + +/************** GLUI_Control::init_live() **********/ +/* Reads in value of a live variable. Called once, when ctrl is created */ + +void GLUI_Control::init_live() +{ + int i; + float *fp; + + if ( ptr_val == NULL ) + return; + + if ( live_type == GLUI_LIVE_NONE ) { + } + else if ( live_type == GLUI_LIVE_INT ) { + set_int_val( *((int*)ptr_val) ); + last_live_int = *((int*)ptr_val); + } + else if ( live_type == GLUI_LIVE_FLOAT ) { + set_float_val( *((float*)ptr_val) ); + last_live_float = *((float*)ptr_val); + } + else if ( live_type == GLUI_LIVE_TEXT ) { + set_text( (const char*) ptr_val ); + last_live_text = (const char*) ptr_val; + } + else if ( live_type == GLUI_LIVE_STRING ) { + set_text( ((std::string*) ptr_val)->c_str() ); + last_live_text = ((std::string*) ptr_val)->c_str(); + } + else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) { + set_float_array_val( (float*) ptr_val ); + + fp = (float*) ptr_val; + + for( i=0; ienable(); + node = (GLUI_Control*) node->next(); + } +} + + +/***** GLUI_Control::disable() ****************/ + +void GLUI_Control::disable() +{ + GLUI_Control *node; + + enabled = false; + + if ( NOT glui ) + return; + + if ( glui->active_control == this ) + glui->deactivate_current_control(); + redraw(); + + /*** Now recursively disable all buttons below it ***/ + node = (GLUI_Control*) first_child(); + while(node) { + node->disable(); + node = (GLUI_Control*) node->next(); + } +} + +/******* GLUI_Control::set_w() **************/ + +void GLUI_Control::set_w(int new_w) +{ + w = new_w; + update_size(); /* Make sure control is big enough to fit text */ + if (glui) glui->refresh(); +} + + +/**** GLUI_Control::set_h() **************/ + +void GLUI_Control::set_h(int new_h) +{ + h = new_h; + update_size(); /* Make sure control is big enough to fit text */ + if (glui) glui->refresh(); +} + + +/***** GLUI_Control::set_alignment() ******/ + +void GLUI_Control::set_alignment(int new_align) +{ + alignment = new_align; + + if ( glui ) + { + glui->align_controls(this); + redraw_window(); + } +} + + +/***** GLUI_Control::needs_idle() *********/ +/* This method gets overloaded by specific classes, e.g. Spinner. */ +/* It returns whether or not a control needs to receive an idle event or not */ +/* For example, a spinner only needs idle events when the user is holding */ +/* the mouse down in one of the arrows. Otherwise, don't waste cycles */ +/* and OpenGL context switching by calling its idle. */ + +bool GLUI_Control::needs_idle() const +{ + return false; +} + + +/********* GLUI_Control::~GLUI_Control() **********/ + +GLUI_Control::~GLUI_Control() +{ + GLUI_Control *item = (GLUI_Control*) this->first_child(); + + while (item) + { + GLUI_Control *tmp = item; + item = (GLUI_Control*) item->next(); + delete tmp; + } +} + +/********* GLUI_Control::hide_internal() ********/ +/** Sets hidden==true for this control and all its siblings. */ +/** If recurse is true, we go to children as well */ + +void GLUI_Control::hide_internal( int recurse ) +{ + GLUI_Node *node; + + node = (GLUI_Node *) this; + while( node != NULL ) { + ((GLUI_Control*)node)->hidden = true; + + if ( recurse AND node->first_child() != NULL ) + ((GLUI_Control*) node->first_child())->hide_internal(true); + + node = node->next(); + } + + node = this->collapsed_node.first_child(); + while( node != NULL ) { + ((GLUI_Control*)node)->hidden = true; + + if ( recurse AND node->first_child() != NULL ) + ((GLUI_Control*) node->first_child())->hide_internal(true); + + node = node->next(); + } +} + + +/********* GLUI_Control::unhide_internal() ********/ +/** Sets hidden==false for this control and all its siblings. */ +/** If recurse is true, we go to children as well */ + +void GLUI_Control::unhide_internal( int recurse ) +{ + GLUI_Node *node; + + node = (GLUI_Node *) this; + while( node != NULL ) { + /* printf( "unhide: %s [%d]\n", ((GLUI_Control*)node)->name.c_str(), + ((GLUI_Control*)node)->hidden );*/ + ((GLUI_Control*)node)->hidden = false; + + if ( recurse AND node->first_child() != NULL ) + ((GLUI_Control*) node->first_child())->unhide_internal(true); + + node = node->next(); + } + + node = this->collapsed_node.first_child(); + while( node != NULL ) { + ((GLUI_Control*)node)->hidden = false; + + if ( recurse AND node->first_child() != NULL ) + ((GLUI_Control*) node->first_child())->unhide_internal(true); + + node = node->next(); + } +} diff --git a/Extras/glui/glui_edittext.cpp b/Extras/glui/glui_edittext.cpp new file mode 100644 index 0000000..9066fde --- /dev/null +++ b/Extras/glui/glui_edittext.cpp @@ -0,0 +1,1198 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_edittext.cpp - GLUI_EditText control class + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "glui_internal_control.h" +#include + +/****************************** GLUI_EditText::GLUI_EditText() **********/ + +GLUI_EditText::GLUI_EditText( GLUI_Node *parent, const char *name, + int data_type, void *live_var, + int id, GLUI_CB callback ) +{ + if (data_type == GLUI_EDITTEXT_TEXT) { + live_type = GLUI_LIVE_TEXT; + } + else if (data_type == GLUI_EDITTEXT_STRING) { + data_type = GLUI_EDITTEXT_TEXT; // EDITTEXT_STRING doesn't really exist. + // Except as a signal to make a string. + // It's a backwards-compat hack. + live_type = GLUI_LIVE_STRING; + } + else if (data_type == GLUI_EDITTEXT_INT) { + live_type = GLUI_LIVE_INT; + } + else if (data_type == GLUI_EDITTEXT_FLOAT) { + live_type = GLUI_LIVE_FLOAT; + } + common_construct( parent, name, data_type, live_type, live_var, id, callback ); +} + +/****************************** GLUI_EditText::GLUI_EditText() **********/ + +GLUI_EditText::GLUI_EditText( GLUI_Node *parent, const char *name, + int text_type, int id, GLUI_CB callback ) +{ + common_construct( parent, name, text_type, GLUI_LIVE_NONE, 0, id, callback); +} + +/****************************** GLUI_EditText::GLUI_EditText() **********/ + +GLUI_EditText::GLUI_EditText( GLUI_Node *parent, const char *name, + int *live_var, + int id, GLUI_CB callback ) +{ + common_construct( parent, name, GLUI_EDITTEXT_INT, GLUI_LIVE_INT, live_var, id, callback); +} + +/****************************** GLUI_EditText::GLUI_EditText() **********/ + +GLUI_EditText::GLUI_EditText( GLUI_Node *parent, const char *name, + float *live_var, + int id, GLUI_CB callback ) +{ + common_construct( parent, name, GLUI_EDITTEXT_FLOAT, GLUI_LIVE_FLOAT, live_var, id, callback); +} + +/****************************** GLUI_EditText::GLUI_EditText() **********/ + +GLUI_EditText::GLUI_EditText( GLUI_Node *parent, const char *name, + char *live_var, + int id, GLUI_CB callback ) +{ + common_construct( parent, name, GLUI_EDITTEXT_TEXT, GLUI_LIVE_TEXT, live_var, id, callback); +} + +/****************************** GLUI_EditText::GLUI_EditText() **********/ + +GLUI_EditText::GLUI_EditText( GLUI_Node *parent, const char *name, + std::string &live_var, + int id, GLUI_CB callback ) +{ + common_construct( parent, name, GLUI_EDITTEXT_TEXT, GLUI_LIVE_STRING, &live_var, id, callback); +} + +/****************************** GLUI_EditText::common_construct() **********/ + +void GLUI_EditText::common_construct( GLUI_Node *parent, const char *name, + int data_t, int live_t, void *data, int id, + GLUI_CB cb ) +{ + common_init(); + set_name( name ); + + live_type = live_t; + data_type = data_t; + ptr_val = data; + user_id = id; + callback = cb; + + + if ( live_type == GLUI_LIVE_INT) { + if ( data == NULL ) + set_int_val(int_val); /** Set to some default, in case of no live var **/ + } + else if ( live_type == GLUI_LIVE_FLOAT ) { + num_periods = 1; + if ( data == NULL ) + set_float_val(float_val); /** Set to some default, in case of no live var **/ + } + + parent->add_control( this ); + + init_live(); +} + +/****************************** GLUI_EditText::mouse_down_handler() **********/ + +int GLUI_EditText::mouse_down_handler( int local_x, int local_y ) +{ + int tmp_insertion_pt; + + if ( debug ) dump( stdout, "-> MOUSE DOWN" ); + + tmp_insertion_pt = find_insertion_pt( local_x, local_y ); + if ( tmp_insertion_pt == -1 ) { + if ( glui ) + glui->deactivate_current_control( ); + return false; + } + + insertion_pt = tmp_insertion_pt; + + sel_start = sel_end = insertion_pt; + + if ( can_draw()) + update_and_draw_text(); + + if ( debug ) dump( stdout, "<- MOUSE UP" ); + + return true; +} + + +/******************************** GLUI_EditText::mouse_up_handler() **********/ + +int GLUI_EditText::mouse_up_handler( int local_x, int local_y, bool inside ) +{ + return false; +} + + +/***************************** GLUI_EditText::mouse_held_down_handler() ******/ + +int GLUI_EditText::mouse_held_down_handler( int local_x, int local_y, + bool new_inside) +{ + int tmp_pt; + + if ( NOT new_inside ) + return false; + + if ( debug ) dump( stdout, "-> HELD DOWN" ); + + tmp_pt = find_insertion_pt( local_x, local_y ); + + if ( tmp_pt == -1 AND sel_end != 0 ) { /* moved mouse past left edge */ + special_handler( GLUT_KEY_LEFT, GLUT_ACTIVE_SHIFT ); + } + else if ( tmp_pt == substring_end+1 AND sel_end != (int) text.length()) { + /* moved mouse past right edge */ + special_handler( GLUT_KEY_RIGHT, GLUT_ACTIVE_SHIFT ); + } + else if ( tmp_pt != -1 AND tmp_pt != sel_end ) { + sel_end = insertion_pt = tmp_pt; + + update_and_draw_text(); + } + + if ( debug ) + dump( stdout, "<- HELD DOWN" ); + + return false; +} + + +/****************************** GLUI_EditText::key_handler() **********/ + +int GLUI_EditText::key_handler( unsigned char key,int modifiers ) +{ + int i, regular_key; + /* int has_selection; */ + + if ( NOT glui ) + return false; + + if ( debug ) + dump( stdout, "-> KEY HANDLER" ); + + regular_key = false; + bool ctrl_down = (modifiers & GLUT_ACTIVE_CTRL)!=0; + /* has_selection = (sel_start != sel_end); */ + + if ( key == CTRL('m') ) { /* RETURN */ + /* glui->deactivate_current_control(); */ + deactivate(); /** Force callbacks, etc **/ + activate(GLUI_ACTIVATE_TAB); /** Reselect all text **/ + redraw(); + return true; + } + else if ( key == CTRL('[')) { /* ESCAPE */ + glui->deactivate_current_control(); + return true; + } + else if ( (key == 127 AND !ctrl_down) OR /* FORWARD DELETE */ + ( key == CTRL('d') AND modifiers == GLUT_ACTIVE_CTRL) ) + { + if ( sel_start == sel_end ) { /* no selection */ + if ( insertion_pt < (int)text.length() ) { + /*** See if we're deleting a period in a float data-type box ***/ + if ( data_type == GLUI_EDITTEXT_FLOAT AND text[insertion_pt]=='.' ) + num_periods--; + + /*** Shift over string first ***/ + text.erase(insertion_pt,1); + } + } + else { /* There is a selection */ + clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end )); + insertion_pt = MIN(sel_start,sel_end); + sel_start = sel_end = insertion_pt; + } + } + else if ( ((key == 127) AND ctrl_down) OR // Delete word forward + ((key == 'd') AND (modifiers == GLUT_ACTIVE_ALT)) ) + { + if ( sel_start == sel_end ) { /* no selection */ + sel_start = insertion_pt; + sel_end = find_word_break( insertion_pt, +1 ); + } + + clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end )); + insertion_pt = MIN(sel_start,sel_end); + sel_start = sel_end = insertion_pt; + } + else if ( key == CTRL('h') ) { /* BACKSPACE */ + if ( sel_start == sel_end ) { /* no selection */ + if ( insertion_pt > 0 ) { + /*** See if we're deleting a period in a float data-type box ***/ + if ( data_type == GLUI_EDITTEXT_FLOAT AND text[insertion_pt-1]=='.' ) + num_periods--; + + /*** Shift over string first ***/ + insertion_pt--; + text.erase(insertion_pt,1); + } + } + else { /* There is a selection */ + clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end )); + insertion_pt = MIN(sel_start,sel_end); + sel_start = sel_end = insertion_pt; + } + } + else if ( modifiers == GLUT_ACTIVE_CTRL ) /* CTRL ONLY */ + { + /* Ctrl-key bindings */ + if ( key == CTRL('a') ) { + return special_handler( GLUT_KEY_HOME, 0 ); + } + else if ( key == CTRL('e') ) { + return special_handler( GLUT_KEY_END, 0 ); + } + else if ( key == CTRL('b') ) { + return special_handler( GLUT_KEY_LEFT, 0 ); + } + else if ( key == CTRL('f') ) { + return special_handler( GLUT_KEY_RIGHT, 0 ); + } + else if ( key == CTRL('p') ) { + return special_handler( GLUT_KEY_UP, 0 ); + } + else if ( key == CTRL('n') ) { + return special_handler( GLUT_KEY_DOWN, 0 ); + } + else if ( key == CTRL('u') ) { /* ERASE LINE */ + insertion_pt = 0; + text.erase(0,text.length()); + sel_start = sel_end = 0; + } + else if ( key == CTRL('k') ) { /* KILL TO END OF LINE */ + sel_start = sel_end = insertion_pt; + text.erase(insertion_pt,GLUI_String::npos); + } + } + else if ( modifiers == GLUT_ACTIVE_ALT ) /* ALT ONLY */ + { + if ( key == 'b' ) { // Backward word + return special_handler ( GLUT_KEY_LEFT, GLUT_ACTIVE_CTRL ); + } + if ( key == 'f' ) { // Forward word + return special_handler ( GLUT_KEY_RIGHT, GLUT_ACTIVE_CTRL ); + } + } + else if ( (modifiers & GLUT_ACTIVE_CTRL) OR + (modifiers & GLUT_ACTIVE_ALT) ) + { + /** ignore other keys with modifiers */ + return true; + } + else { /* Regular key */ + regular_key = true; + + /** Check if we only accept numbers **/ + if (data_type == GLUI_EDITTEXT_FLOAT ) { + if ( (key < '0' OR key > '9') AND key != '.' AND key != '-' ) + return true; + + if ( key == '-' ) { /* User typed a '-' */ + + /* If user has first character selected, then '-' is allowed */ + if ( NOT ( MIN(sel_start,sel_end) == 0 AND + MAX(sel_start,sel_end) > 0 ) ) { + + /* User does not have 1st char selected */ + if (insertion_pt != 0 OR text[0] == '-' ) { + return true; /* Can only place negative at beginning of text, + and only one of them */ + } + } + } + + if ( key == '.' ) { + /*printf( "PERIOD: %d\n", num_periods ); */ + + if ( num_periods > 0 ) { + /** We're trying to type a period, but the text already contains + a period. Check whether the period is contained within + is current selection (thus it will be safely replaced) **/ + + int period_found = false; + if ( sel_start != sel_end ) { + for( i=MIN(sel_end,sel_start); i '9') AND key != '-' ) + return true; + + if ( key == '-' ) { /* User typed a '-' */ + + /* If user has first character selected, then '-' is allowed */ + if ( NOT ( MIN(sel_start,sel_end) == 0 AND + MAX(sel_start,sel_end) > 0 ) ) { + + /* User does not have 1st char selected */ + if (insertion_pt != 0 OR text[0] == '-' ) { + return true; /* Can only place negative at beginning of text, + and only one of them */ + } + } + } + } + + /** This is just to get rid of warnings - the flag regular_key is + set if the key was not a backspace, return, whatever. But I + believe if we're here, we know it was a regular key anyway */ + if ( regular_key ) { + } + + /**** If there's a current selection, erase it ******/ + if ( sel_start != sel_end ) { + clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end )); + insertion_pt = MIN(sel_start,sel_end); + sel_start = sel_end = insertion_pt; + } + + /******** We insert the character into the string ***/ + + text.insert(insertion_pt,1,key); + + /******** Move the insertion point and substring_end one over ******/ + insertion_pt++; + substring_end++; + + sel_start = sel_end = insertion_pt; + } + + /******** Now redraw text ***********/ + /* Hack to prevent text box from being cleared first **/ + /** int substring_change = update_substring_bounds(); + draw_text_only = + (NOT substring_change AND NOT has_selection AND regular_key ); + */ + + draw_text_only = false; /** Well, hack is not yet working **/ + update_and_draw_text(); + draw_text_only = false; + + + if ( debug ) + dump( stdout, "<- KEY HANDLER" ); + + /*** Now look to see if this string has a period ***/ + num_periods = 0; + for( i=0; i<(int)text.length(); i++ ) + if ( text[i] == '.' ) + num_periods++; + + return true; +} + + +/****************************** GLUI_EditText::activate() **********/ + +void GLUI_EditText::activate( int how ) +{ + if ( debug ) + dump( stdout, "-> ACTIVATE" ); + + active = true; + + if ( how == GLUI_ACTIVATE_MOUSE ) + return; /* Don't select everything if activated with mouse */ + + orig_text = text; + + sel_start = 0; + sel_end = (int)text.length(); + insertion_pt = 0; + + if ( debug ) + dump( stdout, "<- ACTIVATE" ); +} + + +/****************************** GLUI_EditText::deactivate() **********/ + +void GLUI_EditText::deactivate( void ) +{ + int new_int_val; + float new_float_val; + + active = false; + + if ( NOT glui ) + return; + + if ( debug ) + dump( stdout, "-> DISACTIVATE" ); + + sel_start = sel_end = insertion_pt = -1; + + /***** Retrieve the current value from the text *****/ + /***** The live variable will be updated by set_text() ****/ + if ( data_type == GLUI_EDITTEXT_FLOAT ) { + if ( text.length() == 0 ) /* zero-length string - make it "0.0" */ + text = "0.0"; + + new_float_val = atof( text.c_str() ); + + set_float_val( new_float_val ); + } + else if ( data_type == GLUI_EDITTEXT_INT ) { + if ( text.length() == 0 ) /* zero-length string - make it "0" */ + text = "0"; + + new_int_val = atoi( text.c_str() ); + + set_int_val( new_int_val ); + } + else + if ( data_type == GLUI_EDITTEXT_TEXT ) { + set_text(text); /* This will force callbacks and gfx refresh */ + } + + update_substring_bounds(); + + /******** redraw text without insertion point ***********/ + redraw(); + + /***** Now do callbacks if value changed ******/ + if ( orig_text != text ) { + this->execute_callback(); + + if ( 0 ) { + /* THE CODE BELOW IS FROM WHEN SPINNER ALSO MAINTAINED CALLBACKS */ + if ( spinner == NULL ) { /** Are we independent of a spinner? **/ + if ( callback ) { + callback( this ); + } + } + else { /* We're attached to a spinner */ + spinner->do_callbacks(); /* Let the spinner do the callback stuff */ + } + } + } + + if ( debug ) + dump( stdout, "<- DISACTIVATE" ); +} + +/****************************** GLUI_EditText::draw() **********/ + +void GLUI_EditText::draw( int x, int y ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + int name_x; + + name_x = MAX(text_x_offset - string_width(this->name) - 3,0); + draw_name( name_x , 13); + + glBegin( GL_LINES ); + glColor3f( .5, .5, .5 ); + glVertex2i( text_x_offset, 0 ); glVertex2i( w, 0 ); + glVertex2i( text_x_offset, 0 ); glVertex2i( text_x_offset, h ); + + glColor3f( 1., 1., 1. ); + glVertex2i( text_x_offset, h ); glVertex2i( w, h ); + glVertex2i( w, h ); glVertex2i( w, 0 ); + + if ( enabled ) + glColor3f( 0., 0., 0. ); + else + glColor3f( .25, .25, .25 ); + glVertex2i( text_x_offset+1, 1 ); glVertex2i( w-1, 1 ); + glVertex2i( text_x_offset+1, 1 ); glVertex2i( text_x_offset+1, h-1 ); + + glColor3f( .75, .75, .75 ); + glVertex2i( text_x_offset+1, h-1 ); glVertex2i( w-1, h-1 ); + glVertex2i( w-1, h-1 ); glVertex2i( w-1, 1 ); + glEnd(); + + /** Find where to draw the text **/ + update_substring_bounds(); + draw_text(0,0); + + draw_insertion_pt(); +} + + + +/************************** GLUI_EditText::update_substring_bounds() *********/ + +int GLUI_EditText::update_substring_bounds( void ) +{ + int box_width; + int text_len = (int)text.length(); + int old_start, old_end; + + old_start = substring_start; + old_end = substring_end; + + /*** Calculate the width of the usable area of the edit box ***/ + box_width = MAX( this->w - this->text_x_offset + - 4 /* 2 * the two-line box border */ + - 2 * GLUI_EDITTEXT_BOXINNERMARGINX, 0 ); + + CLAMP( substring_end, 0, MAX(text_len-1,0) ); + CLAMP( substring_start, 0, MAX(text_len-1,0) ); + + if ( debug ) dump( stdout, "-> UPDATE SS" ); + + if ( insertion_pt >= 0 AND + insertion_pt < substring_start ) { /* cursor moved left */ + substring_start = insertion_pt; + + while ( substring_width( substring_start, substring_end ) > box_width ) + substring_end--; + } + else if ( insertion_pt > substring_end ) { /* cursor moved right */ + substring_end = insertion_pt-1; + + while ( substring_width( substring_start, substring_end ) > box_width ) + substring_start++; + } + else { /* cursor is within old substring bounds */ + if ( last_insertion_pt > insertion_pt ) { /* cursor moved left */ + } + else { + while ( substring_width( substring_start, substring_end ) > box_width ) + substring_end--; + + while(substring_end < text_len-1 + AND substring_width( substring_start, substring_end ) <= box_width) + substring_end++; + } + } + + while ( substring_width( substring_start, substring_end ) > box_width ) + substring_end--; + + last_insertion_pt = insertion_pt; + + /*** No selection if not enabled ***/ + if ( NOT enabled ) { + sel_start = sel_end = 0; + } + + if ( debug ) dump( stdout, "<- UPDATE SS" ); + + if ( substring_start == old_start AND substring_end == old_end ) + return false; /*** bounds did not change ***/ + else + return true; /*** bounds did change ***/ +} + + +/********************************* GLUI_EditText::update_x_offsets() *********/ + +void GLUI_EditText::update_x_offsets( void ) +{ +} + + +/********************************* GLUI_EditText::draw_text() ****************/ + +void GLUI_EditText::draw_text( int x, int y ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + int text_x, i, sel_lo, sel_hi; + + if ( debug ) dump( stdout, "-> DRAW_TEXT" ); + + if ( NOT draw_text_only ) { + if ( enabled ) + glColor3f( 1., 1., 1. ); + else + set_to_bkgd_color(); + glDisable( GL_CULL_FACE ); + glBegin( GL_QUADS ); + glVertex2i( text_x_offset+2, 2 ); glVertex2i( w-2, 2 ); + glVertex2i( w-2, h-2 ); glVertex2i( text_x_offset+2, h-2 ); + glEnd(); + } + + /** Find where to draw the text **/ + + text_x = text_x_offset + 2 + GLUI_EDITTEXT_BOXINNERMARGINX; + + /*printf( "text_x: %d substr_width: %d start/end: %d/%d\n", + text_x, substring_width( substring_start, substring_end ), + substring_start, substring_end ); + */ + /** Find lower and upper selection bounds **/ + sel_lo = MIN(sel_start, sel_end ); + sel_hi = MAX(sel_start, sel_end ); + + int sel_x_start, sel_x_end, delta; + + /** Draw selection area dark **/ + if ( sel_start != sel_end ) { + sel_x_start = text_x; + sel_x_end = text_x; + for( i=substring_start; i<=substring_end; i++ ) { + delta = char_width( text[i] ); + + if ( i < sel_lo ) { + sel_x_start += delta; + sel_x_end += delta; + } + else if ( i < sel_hi ) { + sel_x_end += delta; + } + } + + glColor3f( 0.0f, 0.0f, .6f ); + glBegin( GL_QUADS ); + glVertex2i( sel_x_start, 2 ); glVertex2i( sel_x_end, 2 ); + glVertex2i( sel_x_end, h-2 ); glVertex2i( sel_x_start, h-2 ); + glEnd(); + } + + + if ( sel_start == sel_end ) { /* No current selection */ + if ( enabled ) + glColor3b( 0, 0, 0 ); + else + glColor3b( 32, 32, 32 ); + + glRasterPos2i( text_x, 13); + for( i=substring_start; i<=substring_end; i++ ) { + glutBitmapCharacter( get_font(), this->text[i] ); + } + } + else { /* There is a selection */ + int x = text_x; + for( i=substring_start; i<=substring_end; i++ ) { + if ( IN_BOUNDS( i, sel_lo, sel_hi-1)) { /* This character is selected */ + glColor3f( 1., 1., 1. ); + glRasterPos2i( x, 13); + glutBitmapCharacter( get_font(), this->text[i] ); + } + else { + glColor3f( 0., 0., 0. ); + glRasterPos2i( x, 13); + glutBitmapCharacter( get_font(), this->text[i] ); + } + + x += char_width( text[i] ); + } + } + + if ( debug ) dump( stdout, "<- DRAW_TEXT" ); +} + + +/******************************** GLUI_EditText::find_insertion_pt() *********/ +/* This function returns the character numer *before which* the insertion */ +/* point goes */ + +int GLUI_EditText::find_insertion_pt( int x, int y ) +{ + int curr_x, i; + + /*** See if we clicked outside box ***/ + if ( x < this->x_abs + text_x_offset ) + return -1; + + /* We move from right to left, looking to see if the mouse was clicked + to the right of the ith character */ + + curr_x = this->x_abs + text_x_offset + + substring_width( substring_start, substring_end ) + + 2 /* The edittext box has a 2-pixel margin */ + + GLUI_EDITTEXT_BOXINNERMARGINX; /** plus this many pixels blank space + between the text and the box **/ + + /*** See if we clicked in an empty box ***/ + if ( (int) text.length() == 0 ) + return 0; + + /** find mouse click in text **/ + for( i=substring_end; i>=substring_start; i-- ) { + curr_x -= char_width( text[i] ); + + if ( x > curr_x ) { + /* printf( "-> %d\n", i ); */ + + return i+1; + } + } + + return 0; + + /* Well, the mouse wasn't after any of the characters...see if it's + before the beginning of the substring */ + if ( 0 ) { + if ( x > (x_abs + text_x_offset + 2 ) ) + return substring_start; + + return -1; /* Nothing found */ + } +} + + +/******************************** GLUI_EditText::draw_insertion_pt() *********/ + +void GLUI_EditText::draw_insertion_pt( void ) +{ + int curr_x, i; + + if ( NOT can_draw() ) + return; + + /*** Don't draw insertion pt if control is disabled ***/ + if ( NOT enabled ) + return; + + if ( debug ) dump( stdout, "-> DRAW_INS_PT" ); + + if ( sel_start != sel_end OR insertion_pt < 0 ) { + return; /* Don't draw insertion point if there is a current selection */ + } + + /* printf( "insertion pt: %d\n", insertion_pt ); */ + + curr_x = this->x_abs + text_x_offset + + substring_width( substring_start, substring_end ) + + 2 /* The edittext box has a 2-pixel margin */ + + GLUI_EDITTEXT_BOXINNERMARGINX; /** plus this many pixels blank space + between the text and the box **/ + + for( i=substring_end; i>=insertion_pt; i-- ) { + curr_x -= char_width( text[i] ); + } + + glColor3f( 0.0, 0.0, 0.0 ); + glBegin( GL_LINE_LOOP ); + /*** + glVertex2i( curr_x, y_abs + 4 ); + glVertex2i( curr_x, y_abs + 4 ); + glVertex2i( curr_x, y_abs + h - 3 ); + glVertex2i( curr_x, y_abs + h - 3 ); + ***/ + curr_x -= x_abs; + glVertex2i( curr_x, 0 + 4 ); + glVertex2i( curr_x, 0 + 4 ); + glVertex2i( curr_x, 0 + h - 3 ); + glVertex2i( curr_x, 0 + h - 3 ); + glEnd(); + + if ( debug ) dump( stdout, "-> DRAW_INS_PT" ); +} + + + +/******************************** GLUI_EditText::substring_width() *********/ + +int GLUI_EditText::substring_width( int start, int end ) +{ + int i, width; + + width = 0; + + for( i=start; i<=end; i++ ) + width += char_width( text[i] ); + + return width; +} + + +/***************************** GLUI_EditText::update_and_draw_text() ********/ + +void GLUI_EditText::update_and_draw_text( void ) +{ + if ( NOT can_draw() ) + return; + + update_substring_bounds(); + /* printf( "ss: %d/%d\n", substring_start, substring_end ); */ + + redraw(); +} + + +/********************************* GLUI_EditText::special_handler() **********/ + +int GLUI_EditText::special_handler( int key,int modifiers ) +{ + if ( NOT glui ) + return false; + + if ( debug ) + printf( "SPECIAL:%d - mod:%d subs:%d/%d ins:%d sel:%d/%d\n", + key, modifiers, substring_start, substring_end,insertion_pt, + sel_start, sel_end ); + + if ( key == GLUT_KEY_LEFT ) { + if ( (modifiers & GLUT_ACTIVE_CTRL) != 0 ) { + insertion_pt = find_word_break( insertion_pt, -1 ); + } + else { + insertion_pt--; + } + } + else if ( key == GLUT_KEY_RIGHT ) { + if ( (modifiers & GLUT_ACTIVE_CTRL) != 0 ) { + insertion_pt = find_word_break( insertion_pt, +1 ); + } + else { + insertion_pt++; + } + } + else if ( key == GLUT_KEY_HOME ) { + insertion_pt = 0; + } + else if ( key == GLUT_KEY_END ) { + insertion_pt = (int) text.length(); + } + + /*** Update selection if shift key is down ***/ + if ( (modifiers & GLUT_ACTIVE_SHIFT ) != 0 ) + sel_end = insertion_pt; + else + sel_start = sel_end = insertion_pt; + + + CLAMP( insertion_pt, 0, (int) text.length()); /* Make sure insertion_pt + is in bounds */ + CLAMP( sel_start, 0, (int) text.length()); /* Make sure insertion_pt + is in bounds */ + CLAMP( sel_end, 0, (int) text.length()); /* Make sure insertion_pt + is in bounds */ + + /******** Now redraw text ***********/ + if ( can_draw()) + update_and_draw_text(); + + return true; +} + + +/****************************** GLUI_EditText::find_word_break() **********/ +/* It looks either left or right (depending on value of 'direction' */ +/* for the beginning of the next 'word', where word are characters */ +/* separated by one of the following tokens: " :-.," */ +/* If there is no next word in the specified direction, this returns */ +/* the beginning of 'text', or the very end. */ + +int GLUI_EditText::find_word_break( int start, int direction ) +{ + int i, j; + const char *breaks = " :-.,"; + int num_break_chars = (int)strlen(breaks), text_len = (int)text.length(); + int new_pt; + + /** If we're moving left, we have to start two back, in case we're either + already at the beginning of a word, or on a separating token. + Otherwise, this function would just return the word we're already at **/ + if ( direction == -1 ) { + start -= 2; + } + + /***** Iterate over text in the specified direction *****/ + for ( i=start; i >= 0 AND i < text_len; i += direction ) { + + /** For each character in text, iterate over list of separating tokens **/ + for( j=0; j 0 ) /* Return the end of string */ + return text_len; + else /* Return the beginning of the text */ + return 0; +} + + +/********************************** GLUI_EditText::clear_substring() ********/ + +void GLUI_EditText::clear_substring( int start, int end ) +{ + int i; + + /* + printf( "clearing: %d-%d '", start,end); + for(i=start;ifloat_val = this->float_val; + spinner->int_val = this->int_val; + } + + /*** Now update the live variable ***/ + output_live(true); +} + + +/******************************* GLUI_EditText::set_float_val() ************/ + +void GLUI_EditText::set_float_val( float new_val ) +{ + if ( has_limits == GLUI_LIMIT_CLAMP ) { + /*** Clamp the new value to the existing limits ***/ + + CLAMP( new_val, float_low, float_high ); + } + else if ( has_limits == GLUI_LIMIT_WRAP ) { + /*** Clamp the value cyclically to the limits - that is, if the + value exceeds the max, set it the the minimum, and conversely ***/ + + if ( new_val < float_low ) + new_val = float_high; + if ( new_val > float_high ) + new_val = float_low; + } + + float_val = new_val; + int_val = (int) new_val; /* Mirror the value as an int, too */ + + set_numeric_text(); +} + + +/********************************** GLUI_EditText::set_int_val() ************/ + +void GLUI_EditText::set_int_val( int new_val ) +{ + if ( has_limits == GLUI_LIMIT_CLAMP ) { + /*** Clamp the new value to the existing limits ***/ + + CLAMP( new_val, int_low, int_high ); + } + else if ( has_limits == GLUI_LIMIT_WRAP ) { + /*** Clamp the value cyclically to the limits - that is, if the + value exceeds the max, set it the the minimum, and conversely ***/ + + if ( new_val < int_low ) + new_val = int_high; + if ( new_val > int_high ) + new_val = int_low; + } + + int_val = new_val; + float_val = (float) new_val; /* We mirror the value as a float, too */ + + set_numeric_text(); +} + + +/********************************* GLUI_EditText::set_float_limits() *********/ + +void GLUI_EditText::set_float_limits( float low, float high, int limit_type ) +{ + has_limits = limit_type; + float_low = low; + float_high = high; + + if ( NOT IN_BOUNDS( float_val, float_low, float_high )) + set_float_val( float_low ); + + int_low = (int) float_low; + int_high = (int) float_high; +} + + +/*********************************** GLUI_EditText::set_int_limits() *********/ + +void GLUI_EditText::set_int_limits( int low, int high, int limit_type ) +{ + has_limits = limit_type; + int_low = low; + int_high = high; + + if ( NOT IN_BOUNDS( int_val, int_low, int_high )) + set_int_val( int_low ); + + float_low = (float) int_low; + float_high = (float) int_high; +} + + +/************************************ GLUI_EditText::set_numeric_text() ******/ + +void GLUI_EditText::set_numeric_text( void ) +{ + char buf_num[200]; + int i, text_len; + + if ( data_type == GLUI_EDITTEXT_FLOAT ) { + sprintf( buf_num, "%#g", float_val ); + + num_periods = 0; + text_len = (int) strlen(buf_num); + for ( i=0; i 0 ) { + text_len = (int) strlen(buf_num); + for ( i=text_len-1; i>0; i-- ) { + if ( buf_num[i] == '0' AND buf_num[i-1] != '.' ) + buf_num[i] = '\0'; + else + break; + } + } + set_text( buf_num ); + } + else { + sprintf( buf_num, "%d", int_val ); + set_text( buf_num ); + } + +} + + +/*************************************** GLUI_EditText::dump() **************/ + +void GLUI_EditText::dump( FILE *out, const char *name ) +{ + fprintf( out, + "%s (edittext@%p): ins_pt:%d subs:%d/%d sel:%d/%d len:%d\n", + name, this, + insertion_pt, + substring_start, + substring_end, + sel_start, + sel_end, + (int) text.length()); +} + + +/**************************************** GLUI_EditText::mouse_over() ********/ + +int GLUI_EditText::mouse_over( int state, int x, int y ) +{ + if ( state ) { + /* curr_cursor = GLUT_CURSOR_TEXT; */ + glutSetCursor( GLUT_CURSOR_TEXT ); + } + else { + /* printf( "OUT\n" ); */ + glutSetCursor( GLUT_CURSOR_LEFT_ARROW ); + } + + return true; +} diff --git a/Extras/glui/glui_filebrowser.cpp b/Extras/glui/glui_filebrowser.cpp new file mode 100644 index 0000000..81361cb --- /dev/null +++ b/Extras/glui/glui_filebrowser.cpp @@ -0,0 +1,165 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_filebrowser.cpp - GLUI_FileBrowser control class + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + This program is freely distributable without licensing fees and is + provided without guarantee or warrantee expressed or implied. This + program is -not- in the public domain. + +*****************************************************************************/ + +#include "GL/glui.h" +#include "glui_internal.h" +#include + +#ifdef __GNUC__ +#include +#include +#endif + +#ifdef _WIN32 +#include +#endif + +#include + +GLUI_FileBrowser::GLUI_FileBrowser( GLUI_Node *parent, + const char *name, + int type, + int id, + GLUI_CB cb) +{ + common_init(); + + set_name( name ); + user_id = id; + int_val = type; + callback = cb; + + parent->add_control( this ); + list = new GLUI_List(this, true, 1); + list->set_object_callback( GLUI_FileBrowser::dir_list_callback, this ); + list->set_click_type(GLUI_DOUBLE_CLICK); + this->fbreaddir(this->current_dir.c_str()); +} + +/****************************** GLUI_FileBrowser::draw() **********/ + +void GLUI_FileBrowser::dir_list_callback(GLUI_Control *glui_object) { + GLUI_List *list = glui_object->dynamicCastGLUI_List(); + if (!list) + return; + GLUI_FileBrowser* me = list->associated_object->dynamicCastGLUI_FileBrowser(); + if (!me) + return; + int this_item; + const char *selected; + this_item = list->get_current_item(); + if (this_item > 0) { /* file or directory selected */ + selected = list->get_item_ptr( this_item )->text.c_str(); + if (selected[0] == '/' || selected[0] == '\\') { + if (me->allow_change_dir) { +#ifdef __GNUC__ + chdir(selected+1); +#endif +#ifdef _WIN32 + SetCurrentDirectory(selected+1); +#endif + me->fbreaddir("."); + } + } else { + me->file = selected; + me->execute_callback(); + } + } +} + + + +void GLUI_FileBrowser::fbreaddir(const char *d) { + GLUI_String item; + int i = 0; + + if (!d) + return; + +#ifdef _WIN32 + + WIN32_FIND_DATA FN; + HANDLE hFind; + //char search_arg[MAX_PATH], new_file_path[MAX_PATH]; + //sprintf(search_arg, "%s\\*.*", path_name); + + hFind = FindFirstFile("*.*", &FN); + if (list) { + list->delete_all(); + if (hFind != INVALID_HANDLE_VALUE) { + do { + int len = int(strlen(FN.cFileName)); + if (FN.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + item = '\\'; + item += FN.cFileName; + } else { + item = FN.cFileName; + } + list->add_item(i,item.c_str()); + i++; + } while (FindNextFile(hFind, &FN) != 0); + + if (GetLastError() == ERROR_NO_MORE_FILES) + FindClose(&FN); + else + perror("fbreaddir"); + } + } + +#elif defined(__GNUC__) + + DIR *dir; + struct dirent *dirp; + struct stat dr; + + if (list) { + list->delete_all(); + if ((dir = opendir(d)) == NULL) + perror("fbreaddir:"); + else { + while ((dirp = readdir(dir)) != NULL) /* open directory */ + { + if (!lstat(dirp->d_name,&dr) && S_ISDIR(dr.st_mode)) /* dir is directory */ + item = dirp->d_name + GLUI_String("/"); + else + item = dirp->d_name; + + list->add_item(i,item.c_str()); + i++; + } + closedir(dir); + } + } +#endif +} + +void ProcessFiles(const char *path_name) +{ + +} + + +void GLUI_FileBrowser::set_w(int w) +{ + if (list) list->set_w(w); +} + +void GLUI_FileBrowser::set_h(int h) +{ + if (list) list->set_h(h); +} diff --git a/Extras/glui/glui_internal.h b/Extras/glui/glui_internal.h new file mode 100644 index 0000000..147b65c --- /dev/null +++ b/Extras/glui/glui_internal.h @@ -0,0 +1,107 @@ +#ifndef GLUI_INTERNAL_H +#define GLUI_INTERNAL_H + +#include +#include + + + +#ifndef AND +#define AND && +#define OR || +#define NOT ! +#endif + +#ifndef MAX +#define MAX(a,b) ((a)>(b) ? (a) : (b)) +#define MIN(a,b) ((a)<(b) ? (a) : (b)) +#endif + +#ifndef ABS +#define ABS(a) ((a)>=0 ? (a) : (-(a))) +#endif + +/******************** bit comparisons and operations ***************/ +#ifndef TEST_BIT +#define TEST_BIT( x, b ) (((x) & (1<<(b))) != 0 ) +#define SET_BIT( x, b ) ((x) |= (1 << (b))) +#define CLEAR_BIT( x, b ) ((x) &= ~(1 << (b))) +#define TOGGLE_BIT( x, b ) ((TEST_BIT(x,b)) ?(CLEAR_BIT(x,b)):(SET_BIT(x,b))) +#endif + +#ifndef TEST_AND +#define TEST_AND( a, b ) ((a&b)==b) +#endif + + +#ifndef M_PI +#define M_PI 3.141592654 +#endif + +/*********** flush the stdout and stderr output streams *************/ +#ifndef flushout +#define flushout fflush(stdout) +#define flusherr fflush(stderr) +#endif + +/********** Debugging functions *************************************/ +#ifndef error_return +#define error_return( c ); {fprintf(stderr,c);return;} +#endif + +/************************* floating-point random ********************/ +#ifndef randf +#define randf() ((float) rand() / (float)RAND_MAX ) +#endif + +#ifndef SIGN +#define SIGN(x) ((x)>=0 ? 1 : -1) +#endif + +/****************** conversion between degrees and radians **********/ +#ifndef DEG2RAD +#define DEG2RAD(x) ((x)/180.0*M_PI) +#define RAD2DEG(x) ((x)/M_PI*180.0) +#endif + +/***************** clamp a value to some fixed interval *************/ +#ifndef CLAMP +#define CLAMP(x,lo,hi) {if ((x) < (lo)) {(x)=(lo);} else if((x) > (hi)) {(x)=(hi);}} +#endif + +/************ check if a value lies within a closed interval *********/ +#ifndef IN_BOUNDS +#define IN_BOUNDS( x, lo, hi ) ( (x) >= (lo) AND (x) <= (hi) ) +#endif + +/************ check if a 2D point lies within a 2D box ***************/ +#ifndef PT_IN_BOX +#define PT_IN_BOX( x, y, lo_x, hi_x, lo_y, hi_y ) \ +( IN_BOUNDS(x,lo_x,hi_x) AND IN_BOUNDS(y,lo_y,hi_y) ) +#endif + +/****** check if value lies on proper side of another value *****/ +/*** if side is positive => proper side is positive, else negative **/ +#ifndef CHECK_PROPER_SIDE +#define CHECK_PROPER_SIDE(x,val,side) ((side) > 0 ? (x) > (val) : (x) < (val)) +#endif + + +/***** Small value when we want to do a comparison to 'close to zero' *****/ +#ifndef FUDGE +#define FUDGE .00001 +#endif + + +/******************* swap two values, using a temp variable *********/ +#ifndef SWAP2 +#define SWAP2(a,b,t) {t=a;a=b;b=t;} +#endif + +#define VEC3_TO_ARRAY(v,a) a[0]=v[0], a[1]=v[1], a[2]=v[2] + +/**** Return the ASCII control code given the non-control ASCII character */ +#define CTRL(c) ( (c>=('a'-1)) ? (c-'a'+1) : (c-'A'+1) ) + + +#endif /* GLUI_INTERNAL_H */ diff --git a/Extras/glui/glui_internal_control.h b/Extras/glui/glui_internal_control.h new file mode 100644 index 0000000..7e363aa --- /dev/null +++ b/Extras/glui/glui_internal_control.h @@ -0,0 +1,45 @@ +/* + Header file for use by GLUI controls. + Everything you need is right here. + + +*/ +#ifndef __GLUI_INTERNAL_CONTROL_H +#define __GLUI_INTERNAL_CONTROL_H + +/* This is the main GLUI external header */ +#include "GL/glui.h" + +/* Here's some utility routines */ +#include "glui_internal.h" + + +/** + A GLUI_Control-drawing sentinal object. + On creation, saves the current draw buffer and window. + On destruction, restores draw buffer and window. + This is way nicer than calling save/restore manually. +*/ +class GLUI_DrawingSentinal { + int orig_buf, orig_win; + GLUI_Control *c; +public: + /** The constructor sets up the drawing system */ + GLUI_DrawingSentinal(GLUI_Control *c_); + /** The destructor cleans up drawing back how it was */ + ~GLUI_DrawingSentinal(); + + // Do-nothing routine to avoid compiler warning about unused variable + inline void avoid_warning(void) {} +}; +/** Just drop a GLUI_DRAWINGSENTINAL_IDIOM at the start of your draw methods, +and they'll return if we can't be drawn, and +automatically save and restore all needed state. +*/ +#define GLUI_DRAWINGSENTINAL_IDIOM if (NOT can_draw()) return; GLUI_DrawingSentinal drawSentinal(this); drawSentinal.avoid_warning(); + + +/** Return the time, in seconds. */ +inline double GLUI_Time(void) {return 0.001*glutGet(GLUT_ELAPSED_TIME);} + +#endif diff --git a/Extras/glui/glui_list.cpp b/Extras/glui/glui_list.cpp new file mode 100644 index 0000000..f0ffd47 --- /dev/null +++ b/Extras/glui/glui_list.cpp @@ -0,0 +1,542 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_list.cpp - GLUI_List control class + + + -------------------------------------------------- + + Copyright (c) 2004 John Kew + + This program is freely distributable without licensing fees and is + provided without guarantee or warrantee expressed or implied. This + program is -not- in the public domain. + +*****************************************************************************/ + + + +#include "glui_internal_control.h" +#include +#include + +/****************************** GLUI_List::GLUI_List() **********/ + +GLUI_List::GLUI_List( GLUI_Node *parent, bool scroll, + int id, GLUI_CB callback + /*,GLUI_Control *object + GLUI_InterObject_CB obj_cb*/) +{ + common_construct(parent, NULL, scroll, id, callback/*, object, obj_cb*/); +} + +/****************************** GLUI_List::GLUI_List() **********/ + +GLUI_List::GLUI_List( GLUI_Node *parent, + GLUI_String& live_var, bool scroll, + int id, + GLUI_CB callback + /* ,GLUI_Control *object + ,GLUI_InterObject_CB obj_cb*/ ) +{ + common_construct(parent, &live_var, scroll, id, callback/*, object, obj_cb*/); +} + +/****************************** GLUI_List::common_construct() **********/ + +void GLUI_List::common_construct( + GLUI_Node *parent, + GLUI_String* data, bool scroll, + int id, + GLUI_CB callback + /*,GLUI_Control *object + , GLUI_InterObject_CB obj_cb*/) +{ + common_init(); + GLUI_Node *list_panel = parent; + + if (scroll) { + GLUI_Panel *p = new GLUI_Panel(parent,"",GLUI_PANEL_NONE); + p->x_off = 1; + list_panel = p; + } + this->ptr_val = data; + if (data) { + this->live_type = GLUI_LIVE_STRING; + } + this->user_id = id; + this->callback = callback; + this->name = "list"; + list_panel->add_control( this ); + if (scroll) + { + new GLUI_Column(list_panel, false); + scrollbar = + new GLUI_Scrollbar(list_panel, + "scrollbar", + GLUI_SCROLL_VERTICAL, + GLUI_SCROLL_INT); + scrollbar->set_object_callback(GLUI_List::scrollbar_callback, this); + scrollbar->set_alignment(GLUI_ALIGN_LEFT); + // scrollbar->can_activate = false; //kills ability to mouse drag too + } + init_live(); +} + +/****************************** GLUI_List::mouse_down_handler() **********/ +int GLUI_List::mouse_down_handler( int local_x, int local_y ) +{ + int tmp_line; + unsigned long int ms; + timeb time; + ftime(&time); + ms = time.millitm + (time.time)*1000; + + tmp_line = find_line( local_x-x_abs, local_y-y_abs-5 ); + if ( tmp_line == -1 ) { + if ( glui ) + glui->deactivate_current_control( ); + return false; + } + + if (tmp_line < num_lines) { + curr_line = tmp_line; + if (scrollbar) + scrollbar->set_int_val(curr_line); + this->execute_callback(); + if (associated_object != NULL) + if (cb_click_type == GLUI_SINGLE_CLICK) { + if (obj_cb) { + // obj_cb(associated_object, user_id); + obj_cb(this); + } + } else { + if (last_line == curr_line && (ms - last_click_time) < 300) { + //obj_cb(associated_object, user_id); + obj_cb(this); + } else { + last_click_time = ms; + last_line = curr_line; + } + } + if ( can_draw()) + update_and_draw_text(); + } + + return true; +} + + + + +/******************************** GLUI_List::mouse_up_handler() **********/ + +int GLUI_List::mouse_up_handler( int local_x, int local_y, bool inside ) +{ + return false; +} + + +/***************************** GLUI_List::mouse_held_down_handler() ******/ + +int GLUI_List::mouse_held_down_handler( int local_x, int local_y, + bool new_inside) +{ + return false; +} + + +/****************************** GLUI_List::key_handler() **********/ + +int GLUI_List::key_handler( unsigned char key,int modifiers ) +{ + + + draw_text_only = false; /** Well, hack is not yet working **/ + update_and_draw_text(); + draw_text_only = false; + + return true; +} + + +/****************************** GLUI_List::activate() **********/ + +void GLUI_List::activate( int how ) +{ +// if ( debug ) +// dump( stdout, "-> ACTIVATE" ); + active = true; + + if ( how == GLUI_ACTIVATE_MOUSE ) + return; /* Don't select everything if activated with mouse */ + +} + + +/****************************** GLUI_List::deactivate() **********/ + +void GLUI_List::deactivate( void ) +{ + active = false; + redraw(); +} + +/****************************** GLUI_List::draw() **********/ + +void GLUI_List::draw( int x, int y ) +{ + int line = 0; + int box_width; + GLUI_List_Item *item; + + GLUI_DRAWINGSENTINAL_IDIOM + + /* Bevelled Border */ + glBegin( GL_LINES ); + glColor3f( .5, .5, .5 ); + glVertex2i( 0, 0 ); glVertex2i( w, 0 ); + glVertex2i( 0, 0 ); glVertex2i( 0, h ); + + glColor3f( 1., 1., 1. ); + glVertex2i( 0, h ); glVertex2i( w, h ); + glVertex2i( w, h ); glVertex2i( w, 0 ); + + if ( enabled ) + glColor3f( 0., 0., 0. ); + else + glColor3f( .25, .25, .25 ); + glVertex2i( 1, 1 ); glVertex2i( w-1, 1 ); + glVertex2i( 1, 1 ); glVertex2i( 1, h-1 ); + + glColor3f( .75, .75, .75 ); + glVertex2i( 1, h-1 ); glVertex2i( w-1, h-1 ); + glVertex2i( w-1, h-1 ); glVertex2i( w-1, 1 ); + glEnd(); + + /* Draw Background if enabled*/ + if (enabled) { + glColor3f( 1., 1., 1. ); + glDisable( GL_CULL_FACE ); + glBegin( GL_QUADS ); + glVertex2i( 2, 2 ); glVertex2i( w-2, 2 ); + glVertex2i( w-2, h-2 ); glVertex2i(2, h-2 ); + glEnd(); + } else { + glColor3f( .8, .8, .8 ); + glDisable( GL_CULL_FACE ); + glBegin( GL_QUADS ); + glVertex2i( 2, 2 ); glVertex2i( w-2, 2 ); + glVertex2i( w-2, h-2 ); glVertex2i(2, h-2 ); + glEnd(); + } + + /* Figure out how wide the box is */ + box_width = get_box_width(); + + /* Figure out which lines are visible*/ + + visible_lines = (int)(h-20)/15; + + item = (GLUI_List_Item *) items_list.first_child(); + + line = 0; + while (item) { + if (line < start_line) { + line++; + item = (GLUI_List_Item *) item->next(); + continue; + } + if (line >= start_line && line <= (start_line+visible_lines)) { + if (curr_line == line) + draw_text(item->text.c_str(),1,0,(line - start_line)*15); + else + draw_text(item->text.c_str(),0,0,(line - start_line)*15); + } + line++; + item = (GLUI_List_Item *) item->next(); + } + + if (scrollbar) { + scrollbar->set_int_limits(MAX(0,num_lines-visible_lines), 0); + glPushMatrix(); + glTranslatef(scrollbar->x_abs-x_abs, scrollbar->y_abs-y_abs,0.0); + scrollbar->draw_scroll(); + glPopMatrix(); + } +} + +/********************************* GLUI_List::draw_text() ****************/ + +void GLUI_List::draw_text(const char *t, int selected, int x, int y ) +{ + int text_x, i, x_pos; + int box_width; + + GLUI_DRAWINGSENTINAL_IDIOM + + /** Find where to draw the text **/ + + text_x = 2 + GLUI_LIST_BOXINNERMARGINX; + + /** Draw selection area dark **/ + if ( enabled && selected ) { + glColor3f( 0.0f, 0.0f, .6f ); + glBegin( GL_QUADS ); + glVertex2i(text_x, y+5 ); glVertex2i( w-text_x, y+5 ); + glVertex2i(w-text_x, y+19 ); glVertex2i(text_x, y+19 ); + glEnd(); + } + box_width = get_box_width(); + + if ( !selected || !enabled ) { /* No current selection */ + x_pos = text_x; /* or control disabled */ + if ( enabled ) + glColor3b( 0, 0, 0 ); + else + glColor3b( 32, 32, 32 ); + + glRasterPos2i( text_x, y+15); + i = 0; + while( t[i] != '\0' && substring_width(t,0,i) < box_width) { + glutBitmapCharacter( get_font(), t[i] ); + x_pos += char_width( t[i] ); + i++; + } + } + else { /* There is a selection */ + i = 0; + x_pos = text_x; + glColor3f( 1., 1., 1. ); + glRasterPos2i( text_x, y+15); + while( t[i] != '\0' && substring_width(t,0,i) < box_width) { + glutBitmapCharacter( get_font(), t[i] ); + x_pos += char_width( t[i] ); + i++; + } + } +} + + +int GLUI_List::find_line(int x, int y) { + return start_line + ((int)(y/15)); +} + +int GLUI_List::get_box_width() { + return MAX( this->w + - 6 /* 2 * the two-line box border */ + - 2 * GLUI_LIST_BOXINNERMARGINX, 0 ); + +} + +/******************************** GLUI_List::substring_width() *********/ +int GLUI_List::substring_width( const char *t, int start, int end ) +{ + int i, width; + + width = 0; + + for( i=start; i<=end; i++ ) + width += char_width( t[i] ); + + return width; +} + + +/***************************** GLUI_List::update_and_draw_text() ********/ + +void GLUI_List::update_and_draw_text( void ) +{ + if ( NOT can_draw() ) + return; + + //update_substring_bounds(); + /* printf( "ss: %d/%d\n", substring_start, substring_end ); */ + + redraw(); +} + + +/********************************* GLUI_List::special_handler() **********/ + +int GLUI_List::special_handler( int key,int modifiers ) +{ + if ( NOT glui ) + return false; + + if ( key == GLUT_KEY_DOWN ) { + if (curr_line < num_lines) { + curr_line++; + if (curr_line > start_line+visible_lines) + start_line++; + } + } else if ( key == GLUT_KEY_UP ) { + if (curr_line > 0) { + curr_line--; + if (curr_line < start_line) + start_line--; + } + } + + if (scrollbar) + scrollbar->set_int_val(curr_line); + redraw(); + return true; +} + + +/************************************ GLUI_List::update_size() **********/ + +void GLUI_List::update_size( void ) +{ + if ( NOT glui ) + return; + + if ( w < GLUI_LIST_MIN_TEXT_WIDTH ) + w = GLUI_LIST_MIN_TEXT_WIDTH; +} + +/**************************************** GLUI_Listbox::add_item() **********/ + +int GLUI_List::add_item( int id, const char *new_text ) +{ + GLUI_List_Item *new_node = new GLUI_List_Item; + GLUI_List_Item *head; + + new_node->text = new_text; + new_node->id = id; + + head = (GLUI_List_Item*) items_list.first_child(); + new_node->link_this_to_parent_last( &items_list ); + + if ( head == NULL ) { + /*** This is first item added ***/ + + int_val = id+1; /** Different than id **/ + // do_selection( id ); + last_live_int = id; + + if( glui ) + glui->post_update_main_gfx(); + } + num_lines++; + if (scrollbar) + scrollbar->set_int_limits(MAX(num_lines-visible_lines,0), 0); + + return true; +} + +/************************************** GLUI_Listbox::delete_() **********/ + +int GLUI_List::delete_all() +{ + GLUI_List_Item *item; + + item = (GLUI_List_Item *) items_list.first_child(); + while( item ) { + item->unlink(); + delete item; + item = (GLUI_List_Item *) items_list.first_child(); + } + + num_lines = 0; + curr_line = 0; + + return true; +} + + +/************************************** GLUI_Listbox::delete_item() **********/ + +int GLUI_List::delete_item( const char *text ) +{ + GLUI_List_Item *node = get_item_ptr( text ); + + if ( node ) { + node->unlink(); + delete node; + num_lines--; + return true; + } + else { + return false; + } +} + + +/************************************** GLUI_Listbox::delete_item() **********/ + +int GLUI_List::delete_item( int id ) +{ + GLUI_List_Item *node = get_item_ptr( id ); + + if ( node ) { + node->unlink(); + delete node; + num_lines--; + return true; + } + else { + return false; + } +} + + +/************************************ GLUI_Listbox::get_item_ptr() **********/ + +GLUI_List_Item *GLUI_List::get_item_ptr( const char *text ) +{ + GLUI_List_Item *item; + + item = (GLUI_List_Item *) items_list.first_child(); + while( item ) { + if ( item->text == text ) + return item; + + item = (GLUI_List_Item *) item->next(); + } + + return NULL; +} + + +/************************************ GLUI_Listbox::get_item_ptr() **********/ + +GLUI_List_Item *GLUI_List::get_item_ptr( int id ) +{ + GLUI_List_Item *item; + + item = (GLUI_List_Item *) items_list.first_child(); + while( item ) { + if ( item->id == id ) + return item; + + item = (GLUI_List_Item *) item->next(); + } + + return NULL; +} + +/**************************************** GLUI_List::mouse_over() ********/ + +int GLUI_List::mouse_over( int state, int x, int y ) +{ + glutSetCursor( GLUT_CURSOR_LEFT_ARROW ); + + return true; +} + +void GLUI_List::scrollbar_callback(GLUI_Control *my_scrollbar) { + GLUI_Scrollbar *sb = my_scrollbar->dynamicCastGLUI_Scrollbar(); + if (!sb) return; + GLUI_List* me = (GLUI_List*) sb->associated_object; + if (me->scrollbar == NULL) + return; + int new_start_line = sb->get_int_val(); // TODO!! + me->start_line = new_start_line; + + if ( me->can_draw() ) + me->update_and_draw_text(); +} diff --git a/Extras/glui/glui_listbox.cpp b/Extras/glui/glui_listbox.cpp new file mode 100644 index 0000000..1bf1276 --- /dev/null +++ b/Extras/glui/glui_listbox.cpp @@ -0,0 +1,448 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_listbox - GLUI_ListBox control class + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "glui_internal_control.h" + +/****************************** GLUI_Listbox::GLUI_Listbox() **********/ +GLUI_Listbox::GLUI_Listbox( GLUI_Node *parent, + const char *name, int *value_ptr, + int id, + GLUI_CB cb) +{ + common_init(); + set_ptr_val( value_ptr ); + user_id = id; + set_name( name ); + callback = cb; + + parent->add_control( this ); + + init_live(); +} + + +/****************************** GLUI_Listbox::mouse_down_handler() **********/ + +int GLUI_Listbox::mouse_down_handler( int local_x, int local_y ) +{ + return false; +} + + +/****************************** GLUI_Listbox::mouse_up_handler() **********/ + +int GLUI_Listbox::mouse_up_handler( int local_x, int local_y, bool inside ) +{ + + return false; +} + + +/****************************** GLUI_Listbox::mouse_held_down_handler() ******/ + +int GLUI_Listbox::mouse_held_down_handler( int local_x, int local_y, + bool inside) +{ + + return false; +} + + +/****************************** GLUI_Listbox::key_handler() **********/ + +int GLUI_Listbox::key_handler( unsigned char key,int modifiers ) +{ + return false; +} + + +/****************************** GLUI_Listbox::draw() **********/ + +void GLUI_Listbox::draw( int x, int y ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + int name_x; + + /* draw_active_area(); */ + + name_x = MAX(text_x_offset - string_width(this->name) - 3,0); + draw_name( name_x , 13); + draw_box_inwards_outline( text_x_offset, w, + 0, h ); + + if ( NOT active ) { + draw_box( text_x_offset+3, w-2, 2, h-2, 1.0, 1.0, 1.0 ); + if ( NOT enabled ) + glColor3b( 32, 32, 32 ); + else + glColor3f( 0.0, 0.0, 0.0 ); + glRasterPos2i( text_x_offset+5, 13 ); + draw_string( curr_text ); + } + else { + draw_box( text_x_offset+3, w-2, 2, h-2, .0, .0, .6 ); + glColor3f( 1.0, 1.0, 1.0 ); + glRasterPos2i( text_x_offset+5, 13 ); + draw_string( curr_text ); + } + + + if ( enabled ) { + glui->std_bitmaps. + draw(GLUI_STDBITMAP_LISTBOX_UP, + w-glui->std_bitmaps.width(GLUI_STDBITMAP_LISTBOX_UP)-1, + 2 ); + } + else { + glui->std_bitmaps. + draw(GLUI_STDBITMAP_LISTBOX_UP_DIS, + w-glui->std_bitmaps.width(GLUI_STDBITMAP_LISTBOX_UP)-1, + 2 ); + } +} + + +/************************************ GLUI_Listbox::update_si() **********/ +void GLUI_Listbox::update_size( void ) +{ + recalculate_item_width(); +} + +/********************************* GLUI_Listbox::set_int_val() **************/ + +void GLUI_Listbox::set_int_val( int new_val ) +{ + /* int_val = new_val; */ + + do_selection( new_val ); + + /*** Update the variable we're (possibly) pointing to, and update the main gfx ***/ + output_live(true); +} + +/**************************************** GLUI_Listbox::add_item() **********/ + +int GLUI_Listbox::add_item( int id, const char *new_text ) +{ + GLUI_Listbox_Item *new_node = new GLUI_Listbox_Item; + GLUI_Listbox_Item *head; + + new_node->text = new_text; + new_node->id = id; + + head = (GLUI_Listbox_Item*) items_list.first_child(); + new_node->link_this_to_parent_last( &items_list ); + + if ( head == NULL ) { + /*** This is first item added ***/ + + int_val = id+1; /** Different than id **/ + do_selection( id ); + last_live_int = id; + + if( glui ) + glui->post_update_main_gfx(); + } + if (recalculate_item_width()) glui->refresh(); + + return true; +} + + +/************************************** GLUI_Listbox::delete_item() **********/ + +int GLUI_Listbox::delete_item( const char *text ) +{ + GLUI_Listbox_Item *node = get_item_ptr(text); + + if (node) + { + node->unlink(); + delete node; + return true; + } + if (recalculate_item_width()) glui->refresh(); + + return false; +} + + +/************************************** GLUI_Listbox::delete_item() **********/ + +int GLUI_Listbox::delete_item(int id) +{ + GLUI_Listbox_Item *node = get_item_ptr(id); + + if (node) + { + node->unlink(); + delete node; + return true; + } + if (recalculate_item_width()) glui->refresh(); + + return false; +} + + +/************************************** GLUI_Listbox::sort_items() **********/ + +int GLUI_Listbox::sort_items( void ) +{ + return false; +} + + +/********************************************* GLUI_Listbox::dump() **********/ + +void GLUI_Listbox::dump( FILE *output ) +{ + GLUI_Listbox_Item *item; + + /* printf( "%p\n", (char*) name ); */ + + fprintf( output, "Listbox: %s\n", name.c_str() ); + + item = (GLUI_Listbox_Item *) items_list.first_child(); + while( item ) { + fprintf( output, " %3d : %s\n", item->id, item->text.c_str() ); + + item = (GLUI_Listbox_Item *) item->next(); + } +} + + +/************************************ GLUI_Listbox::get_item_ptr() **********/ + +GLUI_Listbox_Item *GLUI_Listbox::get_item_ptr( const char *text ) +{ + GLUI_Listbox_Item *item; + + item = (GLUI_Listbox_Item *) items_list.first_child(); + while( item ) { + if ( item->text == text ) + return item; + + item = (GLUI_Listbox_Item *) item->next(); + } + + return NULL; +} + + +/************************************ GLUI_Listbox::get_item_ptr() **********/ + +GLUI_Listbox_Item *GLUI_Listbox::get_item_ptr( int id ) +{ + GLUI_Listbox_Item *item; + + item = (GLUI_Listbox_Item *) items_list.first_child(); + while( item ) { + if ( item->id == id ) + return item; + + item = (GLUI_Listbox_Item *) item->next(); + } + + return NULL; +} + + +/************************************ GLUI_Listbox::mouse_over() **********/ + +static void listbox_callback( int i ) +{ + int old_val; + + if ( NOT GLUI_Master.curr_left_button_glut_menu OR + !GLUI_Master.curr_left_button_glut_menu->dynamicCastGLUI_Listbox() ) + return; + + old_val = ((GLUI_Listbox*)GLUI_Master.curr_left_button_glut_menu)->int_val; + ((GLUI_Listbox*)GLUI_Master.curr_left_button_glut_menu)->set_int_val(i); + + /**** If value changed, execute callback ****/ + if ( old_val != + ((GLUI_Listbox*)GLUI_Master.curr_left_button_glut_menu)->int_val ) { + ((GLUI_Listbox*)GLUI_Master.curr_left_button_glut_menu)->execute_callback(); + } +} + + +/*************************************** GLUI_Listbox::mouse_over() **********/ + +int GLUI_Listbox::mouse_over( int state, int x, int y ) +{ + GLUI_Listbox_Item *item; + + /* printf( "x/y: %d/%d\n", x, y ); */ + + if ( state AND enabled AND x > x_abs + text_x_offset) { + /**** Build a GLUT menu for this listbox ***/ + + /* printf( "%d %d\n", x, y ); */ + + glut_menu_id = glutCreateMenu(listbox_callback); + + item = (GLUI_Listbox_Item *) items_list.first_child(); + while( item ) { + glutAddMenuEntry( item->text.c_str(), item->id ); + item = (GLUI_Listbox_Item *) item->next(); + } + + glutAttachMenu( GLUT_LEFT_BUTTON); + + GLUI_Master.set_left_button_glut_menu_control( this ); + } + else if ( glut_menu_id != -1 ) { + /* printf( "OUT\n" ); */ + glutDetachMenu( GLUT_LEFT_BUTTON ); + glutDestroyMenu( glut_menu_id ); + glut_menu_id = -1; + } + + return true; +} + + +/************************************ GLUI_Listbox::do_selection() **********/ + +int GLUI_Listbox::do_selection( int item_num ) +{ + GLUI_Listbox_Item *item, *sel_item; + + /*** Is this item already selected? ***/ + if ( item_num == int_val ) + return false; + + sel_item = NULL; + item = (GLUI_Listbox_Item *) items_list.first_child(); + while( item ) { + if ( item->id == item_num ) { + sel_item = item; + break; + } + + item = (GLUI_Listbox_Item *) item->next(); + } + + if ( NOT sel_item ) + return false; + + /* printf( "-> %s\n", (char*) sel_item->text ); */ + + int_val = item_num; + curr_text = sel_item->text; + redraw(); + + return true; +} + + +/*********************************** GLUI_Listbox::~GLUI_Listbox() **********/ + +GLUI_Listbox::~GLUI_Listbox() +{ + GLUI_Listbox_Item *item = (GLUI_Listbox_Item *) items_list.first_child(); + + while (item) + { + GLUI_Listbox_Item *tmp = item; + item = (GLUI_Listbox_Item *) item->next(); + delete tmp; + } +} + +/****************************** GLUI_Listbox::special_handler() **********/ + +int GLUI_Listbox::special_handler( int key,int modifiers ) +{ + GLUI_Listbox_Item *node, *new_node; + + node = get_item_ptr( int_val ); + new_node = NULL; + + if ( key == GLUT_KEY_DOWN ) { + new_node = (GLUI_Listbox_Item*) node->next(); + } + else if ( key == GLUT_KEY_UP ) { + new_node = (GLUI_Listbox_Item*) node->prev(); + } + else if ( key == GLUT_KEY_HOME ) { + new_node = (GLUI_Listbox_Item*) items_list.first_child(); + } + else if ( key == GLUT_KEY_END ) { + new_node = (GLUI_Listbox_Item*) items_list.last_child(); + } + + if ( new_node != NULL AND new_node != node ) { + node = new_node; + set_int_val( node->id ); + execute_callback(); + return true; + } + else { + return false; + } +} + + +/************************* GLUI_Listbox::recalculate_item_width( void ) ***********/ +/** Change w and return true if we need to be widened to fit the current items. */ +bool GLUI_Listbox::recalculate_item_width( void ) +{ + int item_text_size; + + if ( NOT glui ) + return false; + + /* Find the title size */ + text_x_offset = string_width( name ); + + /* Find the longest item string ***/ + item_text_size = 0; + + GLUI_Listbox_Item *item = (GLUI_Listbox_Item *) items_list.first_child(); + while( item ) { + item_text_size = MAX(item_text_size,string_width(item->text)); + item = (GLUI_Listbox_Item *) item->next(); + } + + /* Sum up our layout: name, item, and drop-down marker */ + int new_wid=text_x_offset+MAX(GLUI_EDITTEXT_MIN_TEXT_WIDTH,item_text_size)+20; + if ( w != new_wid) { + w = new_wid; + return true; /* we gotta be shortened or widened */ + } + else { + return false; /* our current width is OK */ + } +} diff --git a/Extras/glui/glui_mouse_iaction.cpp b/Extras/glui/glui_mouse_iaction.cpp new file mode 100644 index 0000000..0acd69f --- /dev/null +++ b/Extras/glui/glui_mouse_iaction.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_mouse_iaction - GLUI Mouse Interaction control class + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "glui_internal_control.h" + +/********************** GLUI_Mouse_Interaction::mouse_down_handler() ******/ + +int GLUI_Mouse_Interaction::mouse_down_handler( int local_x, int local_y ) +{ + /* int win_h = glutGet( GLUT_WINDOW_HEIGHT ); */ + + /* iaction_mouse_down_handler( local_x, local_y ); */ + iaction_mouse_down_handler( local_x-x_abs, local_y-y_abs ); + /*local_x-x_abs, ((glui->h-local_y)-y_abs) ); */ + redraw(); + + return false; +} + + +/**************************** GLUI_Mouse_Interaction::mouse_up_handler() */ + +int GLUI_Mouse_Interaction::mouse_up_handler( int local_x, int local_y, bool inside ) +{ + iaction_mouse_up_handler( local_x-x_abs, local_y-y_abs, inside ); + return false; +} + + +/****************************** GLUI_Mouse_Interaction::mouse_held_down_handler() ******/ + +int GLUI_Mouse_Interaction::mouse_held_down_handler( int local_x, int local_y, + bool inside) +{ + iaction_mouse_held_down_handler( local_x-x_abs, local_y-y_abs , inside ); + + redraw(); + + /** Tell the main graphics window to update iteself **/ + if( glui ) + glui->post_update_main_gfx(); + + execute_callback(); + + return false; +} + + + +/****************************** GLUI_Mouse_Interaction::draw() **********/ + +void GLUI_Mouse_Interaction::draw( int x, int y ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + int text_width = string_width( this->name ); + int x_left = this->w/2 - text_width/2; + + if ( NOT draw_active_area_only ) { + draw_name( x_left, h-4 ); + draw_active_box( x_left-4, x_left+string_width( name )+4, + h, h-14 ); + } + + draw_active_area(); +} + + +/************************************ GLUI_Mouse_Interaction::update_size() **********/ + +void GLUI_Mouse_Interaction::update_size( void ) +{ + if ( NOT glui ) + return; + + int text_width = string_width( this->name ); + + if ( w < text_width+6 ) + w = text_width+6; + + if ( h - 18 > w ) + w = h - 18; + + iaction_init(); +} + + +/****************************** GLUI_Mouse_Interaction::special_handler() **********/ + +int GLUI_Mouse_Interaction::special_handler( int key,int modifiers ) +{ + int center_x, center_y; + int drag_x, drag_y; + + center_x = w/2; + center_y = (h-18)/2; + drag_x = 0; + drag_y = 0; + + if ( key == GLUT_KEY_LEFT ) + drag_x = -6; + else if ( key == GLUT_KEY_RIGHT ) + drag_x = 6; + else if ( key == GLUT_KEY_UP ) + drag_y = -6; + else if ( key == GLUT_KEY_DOWN ) + drag_y = 6; + + if ( drag_x != 0 OR drag_y != 0 ) { + mouse_down_handler( center_x, center_y ); + mouse_held_down_handler( center_x + drag_x, center_y + drag_y,true ); + mouse_up_handler( center_x + drag_x, center_y + drag_y, true ); + } + + return false; +} + + +/****************************** GLUI_Mouse_Interaction::draw_active_area() **********/ + +void GLUI_Mouse_Interaction::draw_active_area( void ) +{ + int win_h = glutGet( GLUT_WINDOW_HEIGHT ), win_w = glutGet(GLUT_WINDOW_WIDTH); + + int text_height = 18; /* what a kludge */ + + int viewport_size = h-text_height; /*MIN(w,h); */ + + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadIdentity(); + glTranslatef( (float) win_w/2.0, (float) win_h/2.0, 0.0 ); + glRotatef( 180.0, 0.0, 1.0, 0.0 ); + glRotatef( 180.0, 0.0, 0.0, 1.0 ); + glTranslatef( (float) -win_w/2.0, (float) -win_h/2.0, 0.0 ); + + glTranslatef( (float) this->x_abs + .5, (float) this->y_abs + .5, 0.0 ); + + glTranslatef( (float)this->w/2.0, (float)viewport_size/2.0 + 2.0 , 0.0 ); + + /*** Draw the interaction control's orthographic elements ***/ + iaction_draw_active_area_ortho(); + + /*** Setup and draw the interaction control's perspective elements ***/ + + /*** Set the viewport to just the square of the drawing area ***/ + /* glViewport( this->x_abs , glui->main_panel->h - this->y_abs - this->h,*/ + /*glViewport( this->x_abs+1+(this->w/2-viewport_size/2), + this->h-this->y_abs-viewport_size-1, + viewport_size, viewport_size );*/ + + viewport_size -= 4; + int offset = 0; + if ( ((this->w-viewport_size) % 2) == 1 ) + offset = 1; + + glViewport( this->x_abs + (this->w-viewport_size)/2 + offset, + win_h - this->y_abs - this->h + text_height, + viewport_size, viewport_size ); + + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + double xy=1.00,zc=50.0; /* X-Y size, and Z origin */ + glFrustum( -1.0*xy, 1.0*xy, -xy, xy, zc*0.7, zc*1.3 ); + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadIdentity(); + glTranslatef( 0.0, 0.0, -zc ); + glScalef(xy,xy,1.0); // xy); + + /* glutSolidTeapot( 1.0 ); */ + iaction_draw_active_area_persp(); + + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); + + glui->set_viewport(); + glui->set_ortho_projection(); + + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); +} + diff --git a/Extras/glui/glui_node.cpp b/Extras/glui/glui_node.cpp new file mode 100644 index 0000000..a943332 --- /dev/null +++ b/Extras/glui/glui_node.cpp @@ -0,0 +1,212 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_node.cpp - linked-list tree structure + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "GL/glui.h" +#include "glui_internal.h" + +/********************************************* GLUI_Node::GLUI_Node() *******/ + +GLUI_Node::GLUI_Node() +: + parent_node(NULL), + child_head(NULL), + child_tail(NULL), + next_sibling(NULL), + prev_sibling(NULL) +{ +} + +/********************************************* GLUI_Node::first() *******/ +/* Returns first sibling in 'this' node's sibling list */ + +GLUI_Node *GLUI_Node::first_sibling( void ) +{ + if ( parent_node == NULL ) + return this; /* root node has no siblings */ + else + return parent_node->child_head; +} + + +/******************************************** GLUI_Node::next() ********/ +/* Returns next sibling in 'this' node's sibling list */ + +GLUI_Node *GLUI_Node::next( void ) +{ + return next_sibling; +} + + +/******************************************** GLUI_Node::prev() ********/ +/* Returns prev sibling in 'this' node's sibling list */ + +GLUI_Node *GLUI_Node::prev( void ) +{ + return prev_sibling; +} + + +/********************************************* GLUI_Node::last() *******/ +/* Returns last sibling in 'this' node's sibling list */ + +GLUI_Node *GLUI_Node::last_sibling( void ) +{ + if ( parent_node == NULL ) + return this; /* root node has no siblings */ + else + return parent_node->child_tail; +} + + +/*************************** GLUI_Node::link_this_to_parent_last() *******/ +/* Links as last child of parent */ + +void GLUI_Node::link_this_to_parent_last( GLUI_Node *new_parent ) +{ + if ( new_parent->child_tail == NULL ) { /* parent has no children */ + new_parent->child_head = this; + new_parent->child_tail = this; + this->parent_node = new_parent; + } + else { /* parent has children */ + new_parent->child_tail->next_sibling = this; + this->prev_sibling = new_parent->child_tail; + new_parent->child_tail = this; + this->parent_node = new_parent; + } +} + + +/*************************** GLUI_Node::link_this_to_parent_first() *******/ +/* Links as first child of parent */ + +void GLUI_Node::link_this_to_parent_first( GLUI_Node *new_parent ) +{ + if ( new_parent->child_head == NULL ) { /* parent has no children */ + new_parent->child_head = this; + new_parent->child_tail = this; + this->parent_node = new_parent; + } + else { /* parent has children */ + new_parent->child_head->prev_sibling = this; + this->next_sibling = new_parent->child_head; + new_parent->child_head = this; + this->parent_node = new_parent; + } +} + +/**************************** GLUI_Node::link_this_to_sibling_next() *****/ + +void GLUI_Node::link_this_to_sibling_next( GLUI_Node *sibling ) +{ + if ( sibling->next_sibling == NULL ) { /* node has no next sibling */ + sibling->next_sibling = this; + this->prev_sibling = sibling; + + /* This was the parent's last child, so update that as well */ + if ( sibling->parent_node != NULL ) { + sibling->parent_node->child_tail = this; + } + } + else { /* node already has a next sibling */ + sibling->next_sibling->prev_sibling = this; + this->next_sibling = sibling->next_sibling; + sibling->next_sibling = this; + this->prev_sibling = sibling; + } + + this->parent_node = sibling->parent_node; +} + + +/**************************** GLUI_Node::link_this_to_sibling_prev() *****/ + +void GLUI_Node::link_this_to_sibling_prev( GLUI_Node *sibling ) +{ + if ( sibling->prev_sibling == NULL ) { /* node has no prev sibling */ + sibling->prev_sibling = this; + this->next_sibling = sibling; + + /* This was the parent's first child, so update that as well */ + if ( sibling->parent_node != NULL ) { + sibling->parent_node->child_head = this; + } + } + else { /* node already has a prev sibling */ + sibling->prev_sibling->next_sibling = this; + this->prev_sibling = sibling->prev_sibling; + sibling->prev_sibling = this; + this->next_sibling = sibling; + } + + this->parent_node = sibling->parent_node; +} + +/**************************************** GLUI_Node::unlink() **************/ + +void GLUI_Node::unlink( void ) +{ + /* Unlink from prev sibling */ + if ( this->prev_sibling != NULL ) { + this->prev_sibling->next_sibling = this->next_sibling; + } + else { /* No prev sibling: this was parent's first child */ + this->parent_node->child_head = this->next_sibling; + } + + /* Unlink from next sibling */ + if ( this->next_sibling != NULL ) { + this->next_sibling->prev_sibling = this->prev_sibling; + } + else { /* No next sibling: this was parent's last child */ + this->parent_node->child_tail = this->prev_sibling; + } + + this->parent_node = NULL; + this->next_sibling = NULL; + this->prev_sibling = NULL; + this->child_head = NULL; + this->child_tail = NULL; +} + +/**************************************** GLUI_Node::dump() **************/ + +void GLUI_Node::dump( FILE *out, const char *name ) +{ + fprintf( out, "GLUI_node: %s\n", name ); + fprintf( out, " parent: %p child_head: %p child_tail: %p\n", + (void *) parent_node, + (void *) child_head, + (void *) child_tail ); + fprintf( out, " next: %p prev: %p\n", + (void *) next_sibling, + (void *) prev_sibling ); +} diff --git a/Extras/glui/glui_panel.cpp b/Extras/glui/glui_panel.cpp new file mode 100644 index 0000000..3aa61ae --- /dev/null +++ b/Extras/glui/glui_panel.cpp @@ -0,0 +1,186 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_panel.cpp - GLUI_Panel control class + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "glui_internal_control.h" + +GLUI_Panel::GLUI_Panel( GLUI_Node *parent, const char *name, int type ) +{ + common_init(); + set_name( name ); + user_id = -1; + int_val = type; + + parent->add_control( this ); +} + +/****************************** GLUI_Panel::draw() **********/ + +void GLUI_Panel::draw( int x, int y ) +{ + int top; + GLUI_DRAWINGSENTINAL_IDIOM + + if ( int_val == GLUI_PANEL_RAISED ) { + top = 0; + glLineWidth( 1.0 ); + glColor3f( 1.0, 1.0, 1.0 ); + glBegin( GL_LINE_LOOP ); + glVertex2i( 0, top ); glVertex2i( w, top ); + glVertex2i( 0, top ); glVertex2i( 0, h ); + glEnd(); + + glColor3f( .5, .5, .5 ); + glBegin( GL_LINE_LOOP ); + glVertex2i( w, top ); + glVertex2i( w, h ); + glVertex2i( 0, h ); + glVertex2i( w, h ); + glEnd(); + + /** ORIGINAL RAISED PANEL METHOD - A LITTLE TOO HIGH ** + glLineWidth(1.0); + glBegin( GL_LINES ); + glColor3f( 1.0, 1.0, 1.0 ); + glVertex2i( 1, 1 ); glVertex2i( w-2, 1 ); + glVertex2i( 1, 1 ); glVertex2i( 1, h-2 ); + + glColor3f( .5, .5, .5 ); + glVertex2i( w-1, 1 ); glVertex2i( w-1, h-1 ); + glVertex2i( 1, h-1 ); glVertex2i( w-1, h-1 ); + + glColor3f( 0.0, 0.0, 0.0 ); + glVertex2i( 0, h ); glVertex2i( w, h ); + glVertex2i( w, 0 ); glVertex2i( w, h ); + glEnd(); + + -- Touch up the lines a bit (needed in some opengl implementations + glBegin( GL_POINTS ); + glColor3f( .5, .5, .5 ); + glVertex2i( w-1, h-1 ); + glColor3f( 0.0, 0.0, 0.0 ); + glVertex2i( w, h ); + glEnd(); + **/ + } + else if ( int_val == GLUI_PANEL_EMBOSSED ) { + if ( parent_node == NULL || name == "" ) { + top = 0; + } + else { + top = GLUI_PANEL_EMBOSS_TOP; + } + + glLineWidth( 1.0 ); + glColor3f( 1.0, 1.0, 1.0 ); + glBegin( GL_LINE_LOOP ); + glVertex2i( 0, top ); glVertex2i( w, top ); + glVertex2i( w, h ); glVertex2i( 0, h ); + + glVertex2i( 1, top+1 ); glVertex2i( w-1, top+1 ); + glVertex2i( w-1, h-1 ); glVertex2i( 1, h-1 ); + glEnd(); + + glColor3f( .5, .5, .5 ); + glBegin( GL_LINE_LOOP ); + glVertex2i( 0, top ); + glVertex2i( w-1, top ); + glVertex2i( w-1, h-1 ); + glVertex2i( 0, h-1 ); + glEnd(); + + /**** Only display text in embossed panel ****/ + if ( parent_node != NULL && name != "" ) { /* Only draw non-null strings */ + int left = 7, height=GLUI_PANEL_NAME_DROP+1; + int str_width; + + str_width = string_width(name); + + if ( glui ) + glColor3ub(glui->bkgd_color.r,glui->bkgd_color.g,glui->bkgd_color.b); + glDisable( GL_CULL_FACE ); + glBegin( GL_QUADS ); + glVertex2i( left-3, 0 ); glVertex2i( left+str_width+3, 0 ); + glVertex2i( left+str_width+3, height ); glVertex2i( left-3, height ); + glEnd(); + + draw_name( left, GLUI_PANEL_NAME_DROP ); + } + } + + glLineWidth( 1.0 ); +} + +/****************************** GLUI_Panel::set_name() **********/ + +void GLUI_Panel::set_name( const char *new_name ) +{ + name = new_name ? new_name : ""; + + update_size(); + + if ( glui ) + glui->refresh(); +} + + +/****************************** GLUI_Panel::set_type() **********/ + +void GLUI_Panel::set_type( int new_type ) +{ + if ( new_type != int_val ) { + int_val = new_type; + update_size(); + redraw(); + } +} + + +/************************************** GLUI_Panel::update_size() **********/ + +void GLUI_Panel::update_size( void ) +{ + int text_size; + + if ( NOT glui ) + return; + + text_size = string_width(name); + + if ( w < text_size + 16 ) + w = text_size + 16 ; + + if ( name != "" AND int_val == GLUI_PANEL_EMBOSSED ) { + this->y_off_top = GLUI_YOFF + 8; + } + else { + this->y_off_top = GLUI_YOFF; + } +} diff --git a/Extras/glui/glui_radio.cpp b/Extras/glui/glui_radio.cpp new file mode 100644 index 0000000..aef1668 --- /dev/null +++ b/Extras/glui/glui_radio.cpp @@ -0,0 +1,362 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_radio.cpp - GLUI_RadioGroup and GLUI_RadioButton control classes + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "glui_internal_control.h" +#include + +/****************************** GLUI_RadioGroup::GLUI_RadioGroup() **********/ + +GLUI_RadioGroup::GLUI_RadioGroup(GLUI_Node *parent, + int *value_ptr, + int id, GLUI_CB cb) +{ + common_init(); + GLUI_String buf; + + set_ptr_val( value_ptr ); + if ( value_ptr ) { + int_val = *value_ptr; /** Can't call set_int_val(), b/c that + function will try to call the + callback, etc */ + /** Actually, maybe not **/ + last_live_int = *value_ptr; + } + + user_id = id; + glui_format_str( buf, "RadioGroup: %p", this ); + set_name( buf.c_str() ); + callback = cb; + + parent->add_control( this ); + + init_live(); +} + + +/****************************** GLUI_RadioGroup::draw() **********/ + +void GLUI_RadioGroup::draw( int x, int y ) +{ + if ( NOT can_draw() ) + return; + + draw_group(false); +} + + +/********************* GLUI_RadioGroup::draw_group(int translate) **********/ + +void GLUI_RadioGroup::draw_group( int translate ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + GLUI_RadioButton *button; + this->int_val = int_val; + + glMatrixMode(GL_MODELVIEW ); + + button = (GLUI_RadioButton*) first_child(); + while( button != NULL ) { + glPushMatrix(); + if (translate) { + button->translate_to_origin(); + } + else { + glTranslatef(button->x_abs-x_abs, + button->y_abs-y_abs,0.0); + } + + if ( button->int_val ) + button->draw_checked(); + else + button->draw_unchecked(); + + glPopMatrix(); + + button = (GLUI_RadioButton*) button->next(); + } +} + + +/****************************** GLUI_RadioGroup::set_name() **********/ + +void GLUI_RadioGroup::set_name( const char *text ) +{ + name = text; + + if ( glui ) + glui->refresh(); +} + + +/********************************* GLUI_RadioGroup::set_selected() **********/ + +void GLUI_RadioGroup::set_selected( int int_val ) +{ + GLUI_RadioButton *button; + + this->int_val = int_val; + + button = (GLUI_RadioButton*) first_child(); + while( button != NULL ) { + if ( int_val == -1 ) { /*** All buttons in group are deselected ***/ + button->set_int_val(0); + } + else if ( int_val == button->user_id ) { /*** This is selected button ***/ + button->set_int_val(1); + } + else { /*** This is NOT selected button ***/ + button->set_int_val(0); + + } + button = (GLUI_RadioButton*) button->next(); + } + redraw(); +} + + +/************************ GLUI_RadioButton::GLUI_RadioButton() **********/ + +GLUI_RadioButton::GLUI_RadioButton( GLUI_RadioGroup *grp, const char *name ) +{ + common_init(); + + set_int_val( 0 ); + + /** A radio button's user id is always its ordinal number (zero-indexed) + within the group */ + user_id = grp->num_buttons; + set_name( name ); + group = grp; + + group->num_buttons++; /* Increments radiogroup's button count */ + group->add_control( this ); + + /*** Now update button states ***/ + group->set_int_val( group->int_val ); /* This tells the group to + reset itself to its + current value, thereby + updating all its buttons */ +} + + +/************************ GLUI_RadioButton::mouse_down_handler() **********/ + +int GLUI_RadioButton::mouse_down_handler( int local_x, int local_y ) +{ + if ( NOT group ) + return false; + + orig_value = group->int_val; + + currently_inside = true; + + group->set_selected( this->user_id ); + redraw(); + + return false; +} + +/********************** GLUI_RadioButton::mouse_held_down_handler() ******/ + +int GLUI_RadioButton::mouse_held_down_handler( int local_x, int local_y, + bool inside) +{ + if (inside != currently_inside) { + if (inside) group->set_selected( this->user_id ); + else group->set_selected( orig_value ); + currently_inside = inside; + redraw(); + } + + return false; +} + + +/*************************** GLUI_RadioButton::mouse_up_handler() **********/ + +int GLUI_RadioButton::mouse_up_handler( int local_x, int local_y, + bool inside ) +{ + if ( NOT group ) + return false; + + if ( NOT inside ) { + group->set_selected( orig_value ); + redraw(); + } + else { + /** Now we update the radio button group. We tell the group + handler to set the currently-selected item to this button, which + is reference by its user_id/ordinal number within group **/ + + group->set_selected( this->user_id ); + redraw(); + + /*** Now update the linked variable, and call the callback, + but ONLY if the value of the radio group actually changed ***/ + if ( group->int_val != orig_value ) { + group->output_live(true); /** Output live and update gfx ***/ + + group->execute_callback(); + } + } + + return false; +} + +/****************************** GLUI_RadioButton::draw() **********/ + +void GLUI_RadioButton::draw( int x, int y ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + + if ( NOT group OR NOT can_draw() ) + return; + + /*** See if we're the currently-selected button. If so, draw ***/ + if ( group->int_val == this->user_id ) { + if ( enabled ) + glui->std_bitmaps.draw( GLUI_STDBITMAP_RADIOBUTTON_ON, 0, 0 ); + else + glui->std_bitmaps.draw( GLUI_STDBITMAP_RADIOBUTTON_ON_DIS, 0, 0 ); + } + else { + if ( enabled ) + glui->std_bitmaps.draw( GLUI_STDBITMAP_RADIOBUTTON_OFF, 0, 0 ); + else + glui->std_bitmaps.draw( GLUI_STDBITMAP_RADIOBUTTON_OFF_DIS, 0, 0 ); + } + + draw_active_area(); + + draw_name( text_x_offset, 10 ); +} + + +/************************************ GLUI_RadioButton::draw_checked() ******/ + +void GLUI_RadioButton::draw_checked( void ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + if ( enabled ) + glui->std_bitmaps.draw( GLUI_STDBITMAP_RADIOBUTTON_ON, 0, 0 ); + else + glui->std_bitmaps.draw( GLUI_STDBITMAP_RADIOBUTTON_ON_DIS, 0, 0 ); + draw_active_area(); +} + + +/*********************************** GLUI_RadioButton::draw_unchecked() ******/ + +void GLUI_RadioButton::draw_unchecked( void ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + + if ( enabled ) + glui->std_bitmaps.draw( GLUI_STDBITMAP_RADIOBUTTON_OFF, 0, 0 ); + else + glui->std_bitmaps.draw( GLUI_STDBITMAP_RADIOBUTTON_OFF_DIS, 0, 0 ); + draw_active_area(); +} + + +/**************************************** GLUI_RadioButton::draw_O() ********/ + +void GLUI_RadioButton::draw_O( void ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + int i, j; + + glBegin( GL_POINTS ); + for(i=3; i<=GLUI_RADIOBUTTON_SIZE-3; i++ ) + for(j=3; j<=GLUI_RADIOBUTTON_SIZE-3; j++ ) + glVertex2i(i,j); + glEnd(); +} + + +/******************************** GLUI_RadioButton::update_size() **********/ + +void GLUI_RadioButton::update_size( void ) +{ + int text_size; + + if ( NOT glui ) + return; + + text_size = _glutBitmapWidthString( glui->font, name.c_str() ); + + /* if ( w < text_x_offset + text_size + 6 ) */ + w = text_x_offset + text_size + 6 ; +} + + +/************************* GLUI_RadioButton::draw_active_area() **************/ + +void GLUI_RadioButton::draw_active_area( void ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + int text_width, left, right; + + text_width = _glutBitmapWidthString( glui->font, name.c_str() ); + left = text_x_offset-3; + right = left + 7 + text_width; + + if ( active ) { + glEnable( GL_LINE_STIPPLE ); + glLineStipple( 1, 0x5555 ); + glColor3f( 0., 0., 0. ); + } else { + glColor3ub( glui->bkgd_color.r, glui->bkgd_color.g, glui->bkgd_color.b ); + } + + glBegin( GL_LINE_LOOP ); + glVertex2i(left,0); glVertex2i( right,0); + glVertex2i(right,h+1); glVertex2i( left,h+1); + glEnd(); + + glDisable( GL_LINE_STIPPLE ); +} + + +/********************************* GLUI_RadioGroup::set_int_val() **********/ + +void GLUI_RadioGroup::set_int_val( int new_val ) +{ + if ( new_val == int_val ) + return; + + set_selected( new_val ); + redraw(); + + output_live(true); + +} diff --git a/Extras/glui/glui_rollout.cpp b/Extras/glui/glui_rollout.cpp new file mode 100644 index 0000000..d29e006 --- /dev/null +++ b/Extras/glui/glui_rollout.cpp @@ -0,0 +1,275 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_panel.cpp - GLUI_Panel control class + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "glui_internal_control.h" + +enum {rollout_height_pixels=GLUI_DEFAULT_CONTROL_HEIGHT + 7}; + +/****************************** GLUI_Rollout::GLUI_Rollout() **********/ + +GLUI_Rollout::GLUI_Rollout( GLUI_Node *parent, const char *name, + int open, int type ) +{ + common_init(); + set_name( name ); + user_id = -1; + int_val = type; + + if ( NOT open ) { + is_open = false; + h = rollout_height_pixels; + } + + parent->add_control( this ); +} + +/****************************** GLUI_Rollout::open() **********/ + +void GLUI_Rollout::open( void ) +{ + if ( NOT glui ) + return; + + if ( is_open ) + return; + is_open = true; + + GLUI_DRAWINGSENTINAL_IDIOM + + /* Copy hidden children into our private list "collapsed_node" */ + child_head = collapsed_node.child_head; + child_tail = collapsed_node.child_tail; + collapsed_node.child_head = NULL; + collapsed_node.child_tail = NULL; + + if ( child_head != NULL ) { + ((GLUI_Control*) child_head)->unhide_internal( true ); + } + + glui->refresh(); +} + + +/****************************** GLUI_Rollout::close() **********/ + +void GLUI_Rollout::close( void ) +{ + if ( NOT glui ) + return; + + if ( NOT is_open ) + return; + is_open = false; + + GLUI_DRAWINGSENTINAL_IDIOM + + if ( child_head != NULL ) { + ((GLUI_Control*) child_head)->hide_internal( true ); + } + + /* Move all children into a private list of hidden children */ + collapsed_node.child_head = first_child(); + collapsed_node.child_tail = last_child(); + child_head = NULL; + child_tail = NULL; + + this->h = rollout_height_pixels; + + glui->refresh(); +} + + +/**************************** GLUI_Rollout::mouse_down_handler() **********/ + + +int GLUI_Rollout::mouse_down_handler( int local_x, int local_y ) +{ + if ( local_y - y_abs > rollout_height_pixels ) { + initially_inside = currently_inside = false; + return false; + } + + currently_inside = true; + initially_inside = true; + redraw(); + + return false; +} + + +/**************************** GLUI_Rollout::mouse_held_down_handler() ****/ + +int GLUI_Rollout::mouse_held_down_handler( + int local_x, int local_y, + bool new_inside ) +{ + if ( NOT initially_inside ) + return false; + + if ( local_y - y_abs> rollout_height_pixels ) + new_inside = false; + + if (new_inside != currently_inside) { + currently_inside = new_inside; + redraw(); + } + + return false; +} + + +/**************************** GLUI_Rollout::mouse_down_handler() **********/ + +int GLUI_Rollout::mouse_up_handler( int local_x, int local_y, bool inside ) +{ + if ( currently_inside ) { + if ( is_open ) + close(); + else + open(); + } + + currently_inside = false; + initially_inside = false; + redraw(); + + return false; +} + + +/********************************* GLUI_Rollout::draw() ***********/ + +void GLUI_Rollout::draw( int x, int y ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + + int left, right, top, bottom; + + left = 5; + right = w-left; + top = 3; + bottom = 3+16; + + if ( is_open ) + draw_emboss_box( 0, w, top+3, h ); + else + draw_emboss_box( 0, w, top+3, h-7 ); + + glui->draw_raised_box( left, top, w-left*2, 16 ); + + if ( glui ) + glColor3ub(glui->bkgd_color.r,glui->bkgd_color.g,glui->bkgd_color.b); + glDisable( GL_CULL_FACE ); + glBegin( GL_QUADS ); + glVertex2i( left+1, top+1 ); glVertex2i( right-1, top+1 ); + glVertex2i( right-1, bottom-1 ); glVertex2i( left+1, bottom-1 ); + glEnd(); + + draw_name( left+8, top+11 ); + + if ( active ) + /*draw_active_box( left+4, left+string_width( name.c_str() )+12, */ + draw_active_box( left+4, right-17, + top+2, bottom-2 ); + + + /** Draw '+' or '-' **/ + + glBegin( GL_LINES ); + if ( is_open ) { + if ( enabled ) glColor3f( 0.0, 0.0, 0.0 ); + else glColor3f( 0.5, 0.5, 0.5 ); + glVertex2i(right-14,(top+bottom)/2); glVertex2i(right-5,(top+bottom)/2); + + glColor3f( 1.0, 1.0, 1.0 ); + glVertex2i(right-14,1+(top+bottom)/2);glVertex2i(right-5,1+(top+bottom)/2); + } + else + { + glColor3f( 1.0, 1.0, 1.0 ); + glVertex2i(right-9,top+3); glVertex2i(right-9,bottom-4); + glVertex2i(right-14,(top+bottom)/2); glVertex2i(right-5,(top+bottom)/2); + + if ( enabled ) glColor3f( 0.0, 0.0, 0.0 ); + else glColor3f( 0.5, 0.5, 0.5 ); + glVertex2i(right-14,-1+(top+bottom)/2); + glVertex2i(right-5,-1+(top+bottom)/2); + glVertex2i(right-10,top+3); + glVertex2i(right-10,bottom-4); + } + glEnd(); + + glLineWidth( 1.0 ); + + if (currently_inside) {draw_pressed(); /* heavy black outline when pressed */ } +} + + +/***************************** GLUI_Rollout::update_size() **********/ + +void GLUI_Rollout::update_size( void ) +{ + int text_size; + + if ( NOT glui ) + return; + + text_size = string_width(name); + + if ( w < text_size + 36 ) + w = text_size + 36; +} + + +/**************************** GLUI_Rollout::draw_pressed() ***********/ + +void GLUI_Rollout::draw_pressed( void ) +{ + int left, right, top, bottom; + + left = 5; + right = w-left; + top = 3; + bottom = 3+16; + + + glColor3f( 0.0, 0.0, 0.0 ); + + glBegin( GL_LINE_LOOP ); + glVertex2i( left, top ); glVertex2i( right, top ); + glVertex2i( right, bottom ); glVertex2i( left,bottom ); + glEnd(); + + glBegin( GL_LINE_LOOP ); + glVertex2i( left+1, top+1 ); glVertex2i( right-1, top+1 ); + glVertex2i( right-1, bottom-1 ); glVertex2i( left+1,bottom-1 ); + glEnd(); +} diff --git a/Extras/glui/glui_rotation.cpp b/Extras/glui/glui_rotation.cpp new file mode 100644 index 0000000..b02d743 --- /dev/null +++ b/Extras/glui/glui_rotation.cpp @@ -0,0 +1,473 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_rotation - GLUI_Rotation control class + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "GL/glui.h" +#include "arcball.h" +#include "algebra3.h" + +/*************************** GLUI_Rotation::iaction_mouse_down_handler() ***/ + +int GLUI_Rotation::iaction_mouse_down_handler( int local_x, int local_y ) +{ + copy_float_array_to_ball(); + + init_ball(); + + local_y = (int) floor(2.0 * ball->center[1] - local_y); + + ball->mouse_down( local_x, local_y ); + + /* printf( "%d %d - %f %f\n", local_x, local_y, ball->center[0], ball->center[1] ); */ + + copy_ball_to_float_array(); + + spinning = false; + + return false; +} + + +/*********************** GLUI_Rotation::iaction_mouse_up_handler() **********/ + +int GLUI_Rotation::iaction_mouse_up_handler( int local_x, int local_y, + bool inside ) +{ + copy_float_array_to_ball(); + + ball->mouse_up(); + + return false; +} + + +/******************* GLUI_Rotation::iaction_mouse_held_down_handler() ******/ + +int GLUI_Rotation::iaction_mouse_held_down_handler( int local_x, int local_y, + bool inside) +{ + if ( NOT glui ) + return 0; + + copy_float_array_to_ball(); + + local_y = (int) floor(2.0 * ball->center[1] - local_y); + + /* printf( "%d %d\n", local_x, local_y ); */ + + ball->mouse_motion( local_x, local_y, 0, + (glui->curr_modifiers & GLUT_ACTIVE_ALT) != 0, + (glui->curr_modifiers & GLUT_ACTIVE_CTRL) != 0 ); + + copy_ball_to_float_array(); + + if ( can_spin ) + spinning = true; + + return false; +} + + +/******************** GLUI_Rotation::iaction_draw_active_area_persp() **************/ + +void GLUI_Rotation::iaction_draw_active_area_persp( void ) +{ + /********** arcball *******/ + copy_float_array_to_ball(); + + setup_texture(); + setup_lights(); + + glEnable(GL_CULL_FACE ); + + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + + mat4 tmp_rot = *ball->rot_ptr; + glMultMatrixf( (float*) &tmp_rot[0][0] ); + + /*** Draw the checkered box ***/ + /*glDisable( GL_TEXTURE_2D ); */ + draw_ball(1.35); // 1.96 ); + + glPopMatrix(); + + glBindTexture(GL_TEXTURE_2D,0); /* unhook our checkerboard texture */ + glDisable( GL_TEXTURE_2D ); + glDisable( GL_LIGHTING ); + glDisable( GL_CULL_FACE ); +} + + +/******************** GLUI_Rotation::iaction_draw_active_area_ortho() **********/ + +void GLUI_Rotation::iaction_draw_active_area_ortho( void ) +{ + float radius; + radius = (float)(h-22)/2.0; /*MIN((float)w/2.0, (float)h/2.0); */ + + /********* Draw emboss circles around arcball control *********/ + int k; + glLineWidth( 1.0 ); + glBegin( GL_LINE_LOOP); + for( k=0; k<60; k++ ) { + float phi = 2*M_PI*(float)k/60.0; + vec2 p( cos(phi) * (2.0 + radius), sin(phi) * (2.0 + radius)); + if ( p[1] < -p[0] ) glColor3ub( 128,128,128 ); + else glColor3ub( 255,255,255 ); + glVertex2fv((float*)&p[0]); + } + glEnd(); + + glBegin( GL_LINE_LOOP); + for( k=0; k<60; k++ ) { + float phi = 2*M_PI*(float)k/60.0; + vec2 p( cos(phi) * (1.0 + radius), sin(phi) * (1.0 + radius)); + if ( enabled ) { + if ( p[1] < -p[0] ) glColor3ub( 0,0,0); + else glColor3ub( 192,192,192); + } + else + { + if ( p[1] < -p[0] ) glColor3ub( 180,180,180); + else glColor3ub( 192,192,192); + } + glVertex2fv((float*)&p[0]); + } + glEnd(); +} + + +/******************************** GLUI_Rotation::iaction_dump() **********/ + +void GLUI_Rotation::iaction_dump( FILE *output ) +{ +} + + +/******************** GLUI_Rotation::iaction_special_handler() **********/ + +int GLUI_Rotation::iaction_special_handler( int key,int modifiers ) +{ + + return false; +} + +/********************************** GLUI_Rotation::init_ball() **********/ + +void GLUI_Rotation::init_ball( void ) +{ + /*printf( "%f %f %f", float( MIN(w/2,h/2)), (float) w/2, (float) h/2 ); */ + + ball->set_params( vec2( (float)(w/2), (float)((h-18)/2)), + (float) 2.0*(h-18) ); + /*ball->set_damping( .05 ); */ + /*float( MIN(w/2,h/2))*2.0 ); */ + /* ball->reset_mouse(); */ +} + + +/****************************** GLUI_Rotation::setup_texture() *********/ + +void GLUI_Rotation::setup_texture( void ) +{ + static GLuint tex=0u; + GLenum t=GL_TEXTURE_2D; + glEnable(t); + glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + glColor3f( 1.0, 1.0, 1.0 ); + if (tex!=0u) { + /* (OSL 2006/06) Just use glBindTexture to avoid having to re-upload the whole checkerboard every frame. */ + glBindTexture(t,tex); + return; + } /* Else need to make a new checkerboard texture */ + glGenTextures(1,&tex); + glBindTexture(t,tex); + glEnable(t); + + unsigned int i, j; + int dark, light; /*** Dark and light colors for ball checkerboard ***/ + +/* Note: you can change the number of checkers across there sphere in draw_ball */ +#define CHECKBOARD_SIZE 64 /* pixels across whole texture */ +#define CHECKBOARD_REPEAT 32u /* pixels across one black/white sector */ + unsigned char texture_image[CHECKBOARD_SIZE] [CHECKBOARD_SIZE] [3]; + unsigned char c; + for( i=0; iinit(); /** reset quaternion, etc. **/ + ball->set_params( vec2( (float)(w/2), (float)((h-18)/2)), + (float) 2.0*(h-18) ); + + set_spin( this->damping ); + + copy_ball_to_float_array(); + + translate_and_draw_front(); + + output_live(true); /*** Output live and draw main grx window ***/ +} + + +/****************************** GLUI_Rotation::needs_idle() *********/ + +bool GLUI_Rotation::needs_idle( void ) const +{ + return can_spin; +} + + +/****************************** GLUI_Rotation::idle() ***************/ + +void GLUI_Rotation::idle( void ) +{ + spinning = ball->is_spinning?true:false; + + if ( can_spin AND spinning ) { + copy_float_array_to_ball(); + ball->idle(); + + *ball->rot_ptr = *ball->rot_ptr * ball->rot_increment; + + mat4 tmp_rot; + tmp_rot = *ball->rot_ptr; + + copy_ball_to_float_array(); + + draw_active_area_only = true; + translate_and_draw_front(); + draw_active_area_only = false; + + output_live(true); /** output live and update gfx **/ + } + else { + } +} + + +/********************** GLUI_Rotation::copy_float_array_to_ball() *********/ + +void GLUI_Rotation::copy_float_array_to_ball( void ) +{ + int i; + float *fp_src, *fp_dst; + + fp_src = &float_array_val[0]; + fp_dst = &((*ball->rot_ptr)[0][0]); + + for( i=0; i<16; i++ ) { + *fp_dst = *fp_src; + + fp_src++; + fp_dst++; + } +} + + +/********************** GLUI_Rotation::copy_ball_to_float_array() *********/ + +void GLUI_Rotation::copy_ball_to_float_array( void ) +{ + mat4 tmp_rot; + tmp_rot = *ball->rot_ptr; + + set_float_array_val( (float*) &tmp_rot[0][0] ); +} + + +/************************ GLUI_Rotation::set_spin() **********************/ + +void GLUI_Rotation::set_spin( float damp_factor ) +{ + if ( damp_factor == 0.0 ) + can_spin = false; + else + can_spin = true; + + ball->set_damping( 1.0 - damp_factor ); + + this->damping = damp_factor; +} + + +/************** GLUI_Rotation::GLUI_Rotation() ********************/ + +GLUI_Rotation::GLUI_Rotation( GLUI_Node *parent, + const char *name, float *value_ptr, + int id, + GLUI_CB cb ) +{ + common_init(); + set_ptr_val( value_ptr ); + user_id = id; + set_name( name ); + callback = cb; + parent->add_control( this ); + init_live(); + + /*** Init the live 4x4 matrix. This is different than the standard + live variable behavior, since the original value of the 4x4 matrix + is ignored and reset to Identity ***/ +/* +NO! WVB + if ( value_ptr != NULL ) { + int i, j, index; + for( i=0; i<4; i++ ) { + for( j=0; j<4; j++ ) { + index = i*4+j; + if ( i==j ) + value_ptr[index] = 1.0; + else + value_ptr[index] = 0.0; + } + } + } +*/ + /*init_ball(); */ + + +} + + +/************** GLUI_Rotation::common_init() ********************/ + +void GLUI_Rotation::common_init( void ) +{ + glui_format_str( name, "Rotation: %p", this ); +// type = GLUI_CONTROL_ROTATION; + w = GLUI_ROTATION_WIDTH; + h = GLUI_ROTATION_HEIGHT; + can_activate = true; + live_type = GLUI_LIVE_FLOAT_ARRAY; + float_array_size = 16; + quadObj = NULL; + alignment = GLUI_ALIGN_CENTER; + can_spin = false; + spinning = false; + damping = 0.0; + ball = new Arcball; + + reset(); +} diff --git a/Extras/glui/glui_scrollbar.cpp b/Extras/glui/glui_scrollbar.cpp new file mode 100644 index 0000000..f0fb137 --- /dev/null +++ b/Extras/glui/glui_scrollbar.cpp @@ -0,0 +1,832 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_scrollbar.cpp - GLUI_Scrollbar class + + -------------------------------------------------- + + Copyright (c) 2004 John Kew, 1998 Paul Rademacher + + This program is freely distributable without licensing fees and is + provided without guarantee or warrantee expressed or implied. This + program is -not- in the public domain. + +*****************************************************************************/ + +#include "glui_internal_control.h" +#include +#include + +/*static int __debug=0; */ + +#define GLUI_SCROLL_GROWTH_STEPS 800 +#define GLUI_SCROLL_MIN_GROWTH_STEPS 100 +#define GLUI_SCROLL_CALLBACK_INTERVAL 1 /* Execute the user's callback every this many clicks */ + +enum { + GLUI_SCROLL_ARROW_UP, + GLUI_SCROLL_ARROW_DOWN, + GLUI_SCROLL_ARROW_LEFT, + GLUI_SCROLL_ARROW_RIGHT +}; + + +/****************************** GLUI_Scrollbar::GLUI_Scrollbar() **********/ +// Constructor, no live var +GLUI_Scrollbar::GLUI_Scrollbar( GLUI_Node *parent, + const char *name, + int horz_vert, + int data_type, + int id, GLUI_CB callback + /*,GLUI_Control *object + ,GLUI_InterObject_CB obj_cb*/ + ) +{ + common_construct(parent, name, horz_vert, data_type, NULL, id, callback/*, object, obj_cb*/); +} + +/****************************** GLUI_Scrollbar::GLUI_Scrollbar() **********/ +// Constructor, int live var +GLUI_Scrollbar::GLUI_Scrollbar( GLUI_Node *parent, const char *name, + int horz_vert, + int *live_var, + int id, GLUI_CB callback + /*,GLUI_Control *object + ,GLUI_InterObject_CB obj_cb*/ + ) +{ + common_construct(parent, name, horz_vert, GLUI_SCROLL_INT, live_var, id, callback/*, object, obj_cb*/); +} + +/****************************** GLUI_Scrollbar::GLUI_Scrollbar() **********/ +// Constructor, float live var +GLUI_Scrollbar::GLUI_Scrollbar( GLUI_Node *parent, const char *name, + int horz_vert, + float *live_var, + int id, GLUI_CB callback + /*,GLUI_Control *object + ,GLUI_InterObject_CB obj_cb*/ + ) +{ + common_construct(parent, name, horz_vert, GLUI_SCROLL_FLOAT, live_var, id, callback/*, object, obj_cb*/); +} + +/****************************** GLUI_Scrollbar::common_init() **********/ +void GLUI_Scrollbar::common_init(void) +{ + horizontal = true; + h = GLUI_SCROLL_ARROW_HEIGHT; + w = GLUI_TEXTBOX_WIDTH; + alignment = GLUI_ALIGN_CENTER; + x_off = 0; + y_off_top = 0; + y_off_bot = 0; + can_activate = true; + state = GLUI_SCROLL_STATE_NONE; + growth_exp = GLUI_SCROLL_DEFAULT_GROWTH_EXP; + callback_count = 0; + first_callback = true; + user_speed = 1.0; + float_min = 0.0; + float_max = 0.0; + int_min = 0; + int_max = 0; + associated_object = NULL; + last_update_time=0; + velocity_limit=50.0; /* Change value by at most 50 per second */ + box_length = 0; + box_start_position = 0; + box_end_position = 0; + track_length = 0; +} + +/****************************** GLUI_Scrollbar::common_construct() **********/ +void GLUI_Scrollbar::common_construct( + GLUI_Node *parent, + const char *name, + int horz_vert, + int data_type, + void *data, + int id, GLUI_CB callback + /*,GLUI_Control *object, + GLUI_InterObject_CB obj_cb*/ + ) +{ + common_init(); + + // make sure limits are wide enough to hold live value + if (data_type==GLUI_SCROLL_FLOAT) { + float lo = 0.0f, hi=1.0f; + if (data) { + float d = *(float*)(data); + lo = MIN(lo, d); + hi = MAX(hi, d); + } + this->set_float_limits(lo,hi); + this->set_float_val(lo); + this->live_type = GLUI_LIVE_FLOAT; + } else { + int lo = 0, hi=100; + if (data) { + int d = *(int*)(data); + lo = MIN(lo, d); + hi = MAX(hi, d); + } + this->set_int_limits(lo,hi); + this->set_int_val(0); + this->live_type = GLUI_LIVE_INT; + } + this->data_type = data_type; + this->set_ptr_val( data ); + this->set_name(name); + this->user_id = id; + this->callback = callback; + //this->associated_object = object; + //this->object_cb = obj_cb; + this->horizontal=(horz_vert==GLUI_SCROLL_HORIZONTAL); + if (this->horizontal) { + this->h = GLUI_SCROLL_ARROW_HEIGHT; + this->w = GLUI_TEXTBOX_WIDTH; + } else { + this->h = GLUI_TEXTBOX_HEIGHT; + this->w = GLUI_SCROLL_ARROW_WIDTH; + } + parent->add_control( this ); + this->init_live(); +} + +/****************************** GLUI_Scrollbar::mouse_down_handler() **********/ + +int GLUI_Scrollbar::mouse_down_handler( int local_x, int local_y ) +{ + last_update_time=GLUI_Time()-1.0; + this->state = find_arrow( local_x, local_y ); + GLUI_Master.glui_setIdleFuncIfNecessary(); + + /* printf( "spinner: mouse down : %d/%d arrow:%d\n", local_x, local_y, + find_arrow( local_x, local_y )); + */ + + if ( state != GLUI_SCROLL_STATE_UP AND state != GLUI_SCROLL_STATE_DOWN) + return true; + + reset_growth(); + + /*** ints and floats behave a bit differently. When you click on + an int spinner, you expect the value to immediately go up by 1, whereas + for a float it'll go up only by a fractional amount. Therefore, we + go ahead and increment by one for int spinners ***/ +#if 1 + if ( data_type == GLUI_SCROLL_INT ) { + // Allow for possibility of reversed limits + int lo = MIN(int_min,int_max); + int hi = MAX(int_min,int_max); + int increase = int_min < int_max ? 1 : -1; + int new_val = int_val; + if ( state == GLUI_SCROLL_STATE_UP ) { + new_val += increase; + } else if ( state == GLUI_SCROLL_STATE_DOWN ) { + new_val -= increase; + } + if (new_val >= lo && new_val <= hi && new_val!=int_val) { + set_int_val(new_val); + do_callbacks(); + } + } +#endif + do_click(); + redraw(); + + return false; +} + + +/******************************** GLUI_Scrollbar::mouse_up_handler() **********/ + +int GLUI_Scrollbar::mouse_up_handler( int local_x, int local_y, bool inside ) +{ + state = GLUI_SCROLL_STATE_NONE; + GLUI_Master.glui_setIdleFuncIfNecessary(); + + /* printf("spinner: mouse up : %d/%d inside: %d\n",local_x,local_y,inside); */ + + /*glutSetCursor( GLUT_CURSOR_INHERIT ); */ + glutSetCursor( GLUT_CURSOR_LEFT_ARROW ); + + redraw(); + + /* do_callbacks(); --- stub */ + /* if ( callback ) */ + /* callback( this->user_id ); */ + + return false; +} + + +/***************************** GLUI_Scrollbar::mouse_held_down_handler() ******/ + +int GLUI_Scrollbar::mouse_held_down_handler( int local_x, int local_y, + bool new_inside) +{ + int new_state; + if ( state == GLUI_SCROLL_STATE_NONE ) + return false; + + /* printf("spinner: mouse held: %d/%d inside: %d\n",local_x,local_y, + new_inside); + */ + + if ( state == GLUI_SCROLL_STATE_SCROLL) { /* dragging? */ + do_drag( local_x-x_abs, local_y-y_abs ); + } + else { /* not dragging */ + new_state = find_arrow( local_x, local_y ); + + if ( new_state == state ) { + /** Still in same arrow **/ + do_click(); + } + } + redraw(); + + return false; +} + + +/****************************** GLUI_Scrollbar::key_handler() **********/ + +int GLUI_Scrollbar::key_handler( unsigned char key,int modifiers ) +{ + return true; +} + + +/****************************** GLUI_Scrollbar::draw() **********/ + +void GLUI_Scrollbar::draw( int x, int y ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + + if ( horizontal ) { + draw_scroll_arrow(GLUI_SCROLL_ARROW_LEFT, 0, 0); + draw_scroll_arrow(GLUI_SCROLL_ARROW_RIGHT, w-GLUI_SCROLL_ARROW_WIDTH, 0); + } else { + draw_scroll_arrow(GLUI_SCROLL_ARROW_UP, 0, 0); + draw_scroll_arrow(GLUI_SCROLL_ARROW_DOWN, 0, h-GLUI_SCROLL_ARROW_HEIGHT); + } + draw_scroll(); +} + + +/****************************** GLUI_Scrollbar::draw_scroll_arrow() **********/ + +void GLUI_Scrollbar::draw_scroll_arrow(int arrowtype, int x, int y) +{ + float offset=0; + float L=3.5f,HC=7.f,R=10.5f; + float T=4.5f,VC=8.f,B=11.5; + const float verts[][6]={ + { L,10.5f, R, 10.5f, HC, 6.5f }, // up arrow + { L,6.5f, R, 6.5f, HC,10.5f }, // down arrow + { R-2,T, R-2, B, L+1, VC }, // left arrow + { L+2,T, L+2, B, R-1, VC } // right arrow + }; + + const float *tri = NULL; + + switch (arrowtype) + { + case GLUI_SCROLL_ARROW_UP: + tri = verts[0]; + if (state & GLUI_SCROLL_STATE_UP) offset = 1; + break; + + case GLUI_SCROLL_ARROW_DOWN: + tri = verts[1]; + if (state & GLUI_SCROLL_STATE_DOWN) offset = 1; + break; + + case GLUI_SCROLL_ARROW_LEFT: + tri = verts[2]; + if (state & GLUI_SCROLL_STATE_DOWN) offset = 1; + break; + + case GLUI_SCROLL_ARROW_RIGHT: + tri = verts[3]; + if (state & GLUI_SCROLL_STATE_UP) offset = 1; + break; + + default: + return; /* tri is NULL */ + } + + glColor3ubv(&glui->bkgd_color.r); + glRecti(x,y,x+GLUI_SCROLL_ARROW_WIDTH,y+GLUI_SCROLL_ARROW_HEIGHT); + if (!offset) { + glui->draw_raised_box(x,y+1,GLUI_SCROLL_ARROW_WIDTH-1,GLUI_SCROLL_ARROW_HEIGHT-1); + } else { + glColor3ub(128,128,128); + glBegin(GL_LINE_LOOP); + int x2=x+GLUI_SCROLL_ARROW_WIDTH, y2=y+GLUI_SCROLL_ARROW_HEIGHT; + glVertex2i(x ,y); + glVertex2i(x2,y); + glVertex2i(x2,y2); + glVertex2i(x ,y2); + glEnd(); + } + + GLubyte black[]={0,0,0}; + GLubyte white[]={255,255,255}; + GLubyte gray[]={128,128,128}; + GLubyte *color=black; + if (!enabled) { + offset = 1; + color = white; + } + glTranslatef(x+offset,y+offset,0); + glColor3ubv(color); + glBegin(GL_TRIANGLES); + glVertex2fv(tri); glVertex2fv(tri+2), glVertex2fv(tri+4); + glEnd(); + glTranslatef(-(x+offset),-(y+offset),0); + + if (!enabled) { // once more! + glTranslatef(x,y,0); + glColor3ubv(gray); + glBegin(GL_TRIANGLES); + glVertex2fv(tri); glVertex2fv(tri+2), glVertex2fv(tri+4); + glEnd(); + glTranslatef(-x,-y,0); + } +} + + +void GLUI_Scrollbar::draw_scroll() { + update_scroll_parameters(); + + // Draw track using a checkerboard background + const unsigned char scroll_bg[] = { + 0xD4, 0xD0, 0xC8, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xD4, 0xD0, 0xC8 + }; + glColor3f( 1.0, 1.0, 1.0 ); + glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); + glEnable( GL_TEXTURE_2D); + glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, + scroll_bg); + + float y0 = horizontal? 0 : GLUI_SCROLL_ARROW_HEIGHT; + float y1 = horizontal? h : h-GLUI_SCROLL_ARROW_HEIGHT; + float x0 = horizontal? GLUI_SCROLL_ARROW_WIDTH : 0; + float x1 = horizontal? w-GLUI_SCROLL_ARROW_WIDTH : w; + x0-=0.5; y0+=0.5; + x1-=0.5; y1+=0.5; + float dy = y1-y0; + float dx = x1-x0; + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2f(x0,y0); + glTexCoord2f(dx*0.5f,0); glVertex2f(x1,y0); + glTexCoord2f(dx*0.5f,dy*0.5f); glVertex2f(x1,y1); + glTexCoord2f(0, dy*0.5f); glVertex2f(x0,y1); + glEnd(); + glDisable(GL_TEXTURE_2D); + + // Draw scroll box + int box = box_start_position; + if (horizontal) { + box += GLUI_SCROLL_ARROW_WIDTH; + draw_scroll_box(box,1,box_length,h); + } else { + box += GLUI_SCROLL_ARROW_HEIGHT+1; + draw_scroll_box(0,box,w,box_length); + } +} + +/****************************** GLUI_Scrollbar::draw_scroll_box() **********/ + +void GLUI_Scrollbar::draw_scroll_box(int x, int y, int w, int h) +{ + if (!enabled) return; + glColor3ubv(&glui->bkgd_color.r); + glRecti(x,y,x+w,y+h); + glui->draw_raised_box(x,y, w-1, h-1); + + if (active) { + glEnable( GL_LINE_STIPPLE ); + glLineStipple( 1, 0x5555 ); + glColor3f( 0., 0., 0. ); + glBegin(GL_LINE_LOOP); + int x1 = x+2, y1 = y+2, x2 = x+w-4, y2 = y+h-4; + glVertex2i(x1,y1); + glVertex2i(x2,y1); + glVertex2i(x2,y2); + glVertex2i(x1,y2); + glEnd(); + glDisable( GL_LINE_STIPPLE ); + } +} + + + +/**************************** update_scroll_parameters ***********/ + +void GLUI_Scrollbar::update_scroll_parameters() { + track_length = horizontal? + this->w-GLUI_SCROLL_ARROW_WIDTH*2 : + this->h-GLUI_SCROLL_ARROW_HEIGHT*2; + if (data_type==GLUI_SCROLL_INT) + { + if (int_max==int_min) + box_length=track_length; + else { + const int MIN_TAB = GLUI_SCROLL_BOX_STD_HEIGHT; + //box_length = int(track_length/float(visible_range)); + //if (box_length < MIN_TAB) + box_length = MIN_TAB; + } + float pixels_per_unit = (track_length-box_length)/float(int_max-int_min); + if (horizontal) + box_start_position = int((int_val-int_min)*pixels_per_unit); + else + box_start_position = int((int_max-int_val)*pixels_per_unit); + box_end_position = box_start_position+box_length; + } + else if (data_type==GLUI_SCROLL_FLOAT) + { + if (float_max==float_min) + box_length=track_length; + else { + box_length = GLUI_SCROLL_BOX_STD_HEIGHT; + } + float pixels_per_unit = (track_length-box_length)/float(float_max-float_min); + if (horizontal) + box_start_position = int((float_val-float_min)*pixels_per_unit); + else + box_start_position = int((float_max-float_val)*pixels_per_unit); + box_end_position = box_start_position+box_length; + } +} + + +/********************************* GLUI_Scrollbar::special_handler() **********/ + +int GLUI_Scrollbar::special_handler( int key,int modifiers ) +{ + if ( !horizontal && key == GLUT_KEY_UP ) { + mouse_down_handler( x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1, + y_abs + 1 ); + mouse_up_handler( x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1, + y_abs + 1, true ); + } + else if ( !horizontal && key == GLUT_KEY_DOWN ) { + mouse_down_handler(x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1, + y_abs+1+GLUI_SCROLL_ARROW_HEIGHT); + mouse_up_handler( x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1, + y_abs+1 +GLUI_SCROLL_ARROW_HEIGHT, + true ); + } + if ( horizontal && key == GLUT_KEY_LEFT ) { + mouse_down_handler( x_abs + 1,y_abs + 1 ); + mouse_up_handler( x_abs + 1, y_abs + 1, true ); + } + else if ( horizontal && key == GLUT_KEY_RIGHT ) { + mouse_down_handler(x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1, + y_abs+1); + mouse_up_handler( x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1, + y_abs+1, + true ); + } + else if ( key == GLUT_KEY_HOME ) { /** Set value to limit top - + or increment by 10 **/ + } + else if ( key == GLUT_KEY_END ) { + } + + return true; +} + + +/************************************ GLUI_Scrollbar::update_size() **********/ + +void GLUI_Scrollbar::update_size( void ) +{ + if (horizontal) { + h = GLUI_SCROLL_ARROW_HEIGHT; + if (associated_object) { + this->w = ((GLUI_Control *)associated_object)->w; + } + } + else { + w = GLUI_SCROLL_ARROW_WIDTH; + if (associated_object) { + this->h = ((GLUI_Control *)associated_object)->h; + } + } +} + + +/************************************ GLUI_Scrollbar::find_arrow() ************/ + +int GLUI_Scrollbar::find_arrow( int local_x, int local_y ) +{ + + local_x = local_x-x_abs; + local_y = local_y-y_abs; + + if (horizontal) + { + if ( local_y >= h-GLUI_SCROLL_ARROW_HEIGHT-3 && local_y <= h) + { + update_scroll_parameters(); + if ( local_x >= 0 AND local_x <= (GLUI_SCROLL_ARROW_WIDTH+box_start_position) ) + { + return GLUI_SCROLL_STATE_DOWN; + } + if ( local_x >= (GLUI_SCROLL_ARROW_WIDTH+box_end_position) + AND local_x <= (w+GLUI_SCROLL_ARROW_WIDTH) ) + { + return GLUI_SCROLL_STATE_UP; + } + return GLUI_SCROLL_STATE_SCROLL; + } + } + else + { + if ( local_x >= w-GLUI_SCROLL_ARROW_WIDTH-3 && local_x <= w) + { + update_scroll_parameters(); + if ( local_y >= 0 AND local_y <= (GLUI_SCROLL_ARROW_HEIGHT+box_start_position) ) + { + return GLUI_SCROLL_STATE_UP; + } + if ( local_y >= (GLUI_SCROLL_ARROW_HEIGHT+box_end_position) + AND local_y <= (h+GLUI_SCROLL_ARROW_HEIGHT) ) + { + return GLUI_SCROLL_STATE_DOWN; + } + return GLUI_SCROLL_STATE_SCROLL; + } + } + + return GLUI_SCROLL_STATE_NONE; +} + +/***************************************** GLUI_Scrollbar::do_click() **********/ + +void GLUI_Scrollbar::do_click( void ) +{ + int direction = 0; + + if ( state == GLUI_SCROLL_STATE_UP ) + direction = +1; + else if ( state == GLUI_SCROLL_STATE_DOWN ) + direction = -1; + + if (data_type==GLUI_SCROLL_INT&&int_min>int_max) direction*=-1; + if (data_type==GLUI_SCROLL_FLOAT&&float_min>float_max) direction*=-1; + + increase_growth(); + + float modifier_factor = 1.0; + float incr = growth * modifier_factor * user_speed ; + + double frame_time=GLUI_Time()-last_update_time; + double frame_limit=velocity_limit*frame_time; + if (incr>frame_limit) incr=frame_limit; /* don't scroll faster than limit */ + last_update_time=GLUI_Time(); + + float new_val = float_val; + + new_val += direction * incr; + if (1 || data_type==GLUI_SCROLL_FLOAT) set_float_val(new_val); + if (0 && data_type==GLUI_SCROLL_INT) set_int_val((int)new_val); + //printf("do_click: incr %f val=%f float_val=%f\n",incr,new_val,float_val); + + /*** Now update live variable and do callback. We don't want + to do the callback on each iteration of this function, just on every + i^th iteration, where i is given by GLUI_SCROLL_CALLBACK_INTERVAL ****/ + callback_count++; + if ( (callback_count % GLUI_SCROLL_CALLBACK_INTERVAL ) == 0 ) + do_callbacks(); + +} + + +/***************************************** GLUI_Scrollbar::do_drag() **********/ + +void GLUI_Scrollbar::do_drag( int x, int y ) +{ + int direction = 0; + float incr, modifier_factor; + /* int delta_x; */ + int new_int_val = int_val; + float new_float_val = float_val; + + int free_len = track_length-box_length; + if (free_len == 0) return; + + modifier_factor = 1.0; + if ( state == GLUI_SCROLL_STATE_SCROLL) { + update_scroll_parameters(); + + int hbox = box_length/2; + if (horizontal) { + int track_v = x-GLUI_SCROLL_ARROW_WIDTH; + new_int_val = int_min + (track_v-hbox)*(int_max-int_min)/free_len; + new_float_val = float_min + (track_v-hbox)*(float_max-float_min)/float(free_len); + } else { + int track_v = y-GLUI_SCROLL_ARROW_HEIGHT; + new_int_val = int_max - (track_v-hbox)*(int_max-int_min)/free_len; + new_float_val = float_max - (track_v-hbox)*(float_max-float_min)/float(free_len); + } + } + else { + if ( state == GLUI_SCROLL_STATE_UP ) + direction = +1; + else if ( state == GLUI_SCROLL_STATE_DOWN ) + direction = -1; + incr = growth * direction * modifier_factor * user_speed; + new_int_val += direction; + new_float_val += direction * (float_max-float_min)/free_len; + } + last_y = y; + last_x = x; + + /*** Now update live variable and do callback. We don't want + to do the callback on each iteration of this function, just on every + i^th iteration, where i is given by GLUI_SCROLL_CALLBACK_INTERVAL ****/ + if(data_type==GLUI_SCROLL_INT) + set_int_val(new_int_val); + else if (data_type==GLUI_SCROLL_FLOAT) + set_float_val(new_float_val); + + callback_count++; + if ( (callback_count % GLUI_SCROLL_CALLBACK_INTERVAL ) == 0 ) + do_callbacks(); +} + + +/***************************************** GLUI_Scrollbar::needs_idle() ******/ + +bool GLUI_Scrollbar::needs_idle( void ) const +{ + if (state == GLUI_SCROLL_STATE_UP OR state == GLUI_SCROLL_STATE_DOWN ) { + return true; + } + else { + return false; + } +} + +/***************************************** GLUI_Scrollbar::idle() **********/ + +void GLUI_Scrollbar::idle( void ) +{ + if ( NOT needs_idle() ) + return; + else + do_click(); +} + + +/************************************ GLUI_Scrollbar::do_callbacks() **********/ + +void GLUI_Scrollbar::do_callbacks( void ) +{ + + /* *******************************************/ + + if ( NOT first_callback ) { + if ( data_type == GLUI_SCROLL_INT AND int_val == last_int_val ) { + return; + } + if ( data_type == GLUI_SPINNER_FLOAT AND float_val == last_float_val ) { + return; + } + } + + if (associated_object == NULL) { + this->execute_callback(); + } + else { // Use internal Callbacks + if (object_cb) { + //object_cb(associated_object, int_val); + object_cb(this); + } + } + last_int_val = int_val; + last_float_val = float_val; + first_callback = false; +} + + +/********************************** GLUI_Scrollbar::set_float_val() ************/ + +void GLUI_Scrollbar::set_float_val( float new_val ) +{ + // Allow for the possibility that the limits are reversed + float hi = MAX(float_min,float_max); + float lo = MIN(float_min,float_max); + if (new_val > hi) + new_val = hi; + if (new_val < lo) + new_val = lo; + last_float_val = float_val; + float_val = new_val; + int_val = (int)new_val; + + redraw(); + + /*** Now update the live variable ***/ + output_live(true); +} + + +/********************************** GLUI_Scrollbar::set_int_val() ************/ + +void GLUI_Scrollbar::set_int_val( int new_val ) +{ + // Allow for the possibility that the limits are reversed + int hi = MAX(int_min,int_max); + int lo = MIN(int_min,int_max); + if (new_val > hi) + new_val = hi; + if (new_val < lo) + new_val = lo; + last_int_val = int_val; + float_val = int_val = new_val; + + redraw(); + + /*** Now update the live variable ***/ + output_live(true); +} + +/*********************************** GLUI_Scrollbar::set_float_limits() *********/ + +void GLUI_Scrollbar::set_float_limits( float low, float high, int limit_type ) +{ + if (limit_type != GLUI_LIMIT_CLAMP) { + // error! + } + float_min = low; + float_max = high; + // Allow for possiblitly of reversed limits + float lo = MIN(low,high); + float hi = MAX(low,high); + if (float_valhi) set_float_val(hi); +} + + +/*********************************** GLUI_Scrollbar::set_int_limits() *********/ + +void GLUI_Scrollbar::set_int_limits( int low, int high, int limit_type ) +{ + if (limit_type != GLUI_LIMIT_CLAMP) { + // error! + } + int_min = low; + int_max = high; + // Allow for possiblitly of reversed limits + int lo = MIN(low,high); + int hi = MAX(low,high); + if (int_valhi) set_int_val(hi); + float_min = low; + float_max = high; +} + + +/*********************************** GLUI_Scrollbar::reset_growth() *************/ + +void GLUI_Scrollbar::reset_growth( void ) +{ + growth = fabs(float_max - float_min) / float(GLUI_SCROLL_GROWTH_STEPS); + if (data_type == GLUI_SCROLL_INT && growth<1) growth=1; +} + + +/******************************* GLUI_Scrollbar::increase_growth() *************/ + +void GLUI_Scrollbar::increase_growth( void ) +{ + float range=0; + if (data_type==GLUI_SCROLL_FLOAT) + range = fabs(float_max-float_min); + else + range = fabs(float(int_max-int_min)); + if ( growth < (range / float(GLUI_SCROLL_MIN_GROWTH_STEPS)) ) + growth *= growth_exp; + return; +} + + + diff --git a/Extras/glui/glui_separator.cpp b/Extras/glui/glui_separator.cpp new file mode 100644 index 0000000..87907d8 --- /dev/null +++ b/Extras/glui/glui_separator.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_separator.cpp - GLUI_Separator control class + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "glui_internal_control.h" + +/****************************** GLUI_Separator::GLUI_Separator() **********/ + +GLUI_Separator::GLUI_Separator( GLUI_Node *parent ) +{ + common_init(); + parent->add_control( this ); +} + +/****************************** GLUI_Separator::draw() **********/ + +void GLUI_Separator::draw( int x, int y ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + + int width, indent; + int cont_x, cont_y, cont_w, cont_h, cont_x_off, cont_y_off; + + if ( parent() != NULL ) { + get_this_column_dims(&cont_x, &cont_y, &cont_w, &cont_h, + &cont_x_off, &cont_y_off); + + width = cont_w - cont_x_off*2; + } + else { + width = this->w; + } + + indent = (int) floor(width * .05); + + glLineWidth( 1.0 ); + glBegin( GL_LINES ); + glColor3f( .5, .5, .5 ); + glVertex2i( indent, GLUI_SEPARATOR_HEIGHT/2-1 ); + glVertex2i( width-indent, GLUI_SEPARATOR_HEIGHT/2-1 ); + + glColor3f( 1., 1., 1. ); + glVertex2i( indent, GLUI_SEPARATOR_HEIGHT/2 ); + glVertex2i( width-indent, GLUI_SEPARATOR_HEIGHT/2 ); + glEnd(); +} + + diff --git a/Extras/glui/glui_spinner.cpp b/Extras/glui/glui_spinner.cpp new file mode 100644 index 0000000..9867739 --- /dev/null +++ b/Extras/glui/glui_spinner.cpp @@ -0,0 +1,630 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_spinner.cpp - GLUI_Spinner class + + + notes: + spinner does not explicitly keep track of the current value - this is all + handled by the underlying edittext control + -> thus, spinner->sync_live() has no meaning, nor spinner->output_live + -> BUT, edittext will alter this spinner's float_val and int_val, + so that spinner->get/set will work + + +FIXME: there's a heck of a lot of duplication between this and glui_scrollbar.cpp. + (OSL, 2006/06) + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "glui_internal_control.h" +#include +#include + +/*static int __debug=0; */ + +#define GLUI_SPINNER_GROWTH_STEPS 800 +#define GLUI_SPINNER_MIN_GROWTH_STEPS 100 +#define GLUI_SPINNER_CALLBACK_INTERVAL 1 + + + + +/****************************** GLUI_Spinner::GLUI_Spinner() ****************/ + +GLUI_Spinner::GLUI_Spinner( GLUI_Node* parent, const char *name, + int data_type, int id, GLUI_CB callback ) +{ + common_construct(parent, name, data_type, NULL, id, callback); +} + +/****************************** GLUI_Spinner::GLUI_Spinner() ****************/ + +GLUI_Spinner::GLUI_Spinner( GLUI_Node* parent, const char *name, + int *live_var, int id, GLUI_CB callback ) +{ + common_construct(parent, name, GLUI_SPINNER_INT, live_var, id, callback); +} + +/****************************** GLUI_Spinner::GLUI_Spinner() ****************/ + +GLUI_Spinner::GLUI_Spinner( GLUI_Node* parent, const char *name, + float *live_var, int id, GLUI_CB callback ) +{ + common_construct(parent, name, GLUI_SPINNER_FLOAT, live_var, id, callback); +} + +/****************************** GLUI_Spinner::GLUI_Spinner() ****************/ + +GLUI_Spinner::GLUI_Spinner( GLUI_Node *parent, const char *name, + int data_t, void *live_var, + int id, GLUI_CB callback ) +{ + common_construct(parent, name, data_t, live_var, id, callback); +} + +/****************************** GLUI_Spinner::common_construct() ************/ + +void GLUI_Spinner::common_construct( GLUI_Node* parent, const char *name, + int data_t, void *data, + int id, GLUI_CB cb ) +{ + common_init(); + + if ( NOT strcmp( name, "Spinner Test" )) + id=id; + + int text_type; + if ( data_t == GLUI_SPINNER_INT ) { + text_type = GLUI_EDITTEXT_INT; + } + else if ( data_t == GLUI_SPINNER_FLOAT ) { + text_type = GLUI_EDITTEXT_FLOAT; + } + else { + assert(0); /* Did not pass in a valid data type */ + } + + user_id = id; + data_type = data_t; + callback = cb; + set_name( name ); + //glui = parent->get_glui(); + + parent->add_control( this ); + + GLUI_EditText *txt = + new GLUI_EditText( this, name, text_type, data, id, cb); + + edittext = txt; /* Link the edittext to the spinner */ + /* control->ptr_val = data; */ + + edittext->spinner = this; /* Link the spinner to the edittext */ + +} + +/****************************** GLUI_Spinner::mouse_down_handler() **********/ + +int GLUI_Spinner::mouse_down_handler( int local_x, int local_y ) +{ + this->state = find_arrow( local_x, local_y ); + GLUI_Master.glui_setIdleFuncIfNecessary(); + + /* printf( "spinner: mouse down : %d/%d arrow:%d\n", local_x, local_y, + find_arrow( local_x, local_y )); + */ + + if ( state != GLUI_SPINNER_STATE_UP AND state != GLUI_SPINNER_STATE_DOWN ) + return true; + + reset_growth(); + redraw(); + + /*** ints and floats behave a bit differently. When you click on + an int spinner, you expect the value to immediately go up by 1, whereas + for a float it'll go up only by a fractional amount. Therefore, we + go ahead and increment by one for int spinners ***/ + if ( data_type == GLUI_SPINNER_INT ) { + if ( state == GLUI_SPINNER_STATE_UP ) + edittext->set_float_val( edittext->float_val + 1.0 ); + else if ( state == GLUI_SPINNER_STATE_DOWN ) + edittext->set_float_val( edittext->float_val - .9 ); + } + + do_click(); + + return false; +} + + +/******************************** GLUI_Spinner::mouse_up_handler() **********/ + +int GLUI_Spinner::mouse_up_handler( int local_x, int local_y, bool inside ) +{ + state = GLUI_SPINNER_STATE_NONE; + GLUI_Master.glui_setIdleFuncIfNecessary(); + + /* printf("spinner: mouse up : %d/%d inside: %d\n",local_x,local_y,inside); */ + + /*glutSetCursor( GLUT_CURSOR_INHERIT ); */ + glutSetCursor( GLUT_CURSOR_LEFT_ARROW ); + redraw(); + + /* do_callbacks(); --- stub */ + /* if ( callback ) */ + /* callback( this->user_id ); */ + + return false; +} + + +/***************************** GLUI_Spinner::mouse_held_down_handler() ******/ + +int GLUI_Spinner::mouse_held_down_handler( int local_x, int local_y, + bool new_inside) +{ + int new_state; + + if ( state == GLUI_SPINNER_STATE_NONE ) + return false; + + /* printf("spinner: mouse held: %d/%d inside: %d\n",local_x,local_y, + new_inside); + */ + + if ( state == GLUI_SPINNER_STATE_BOTH ) { /* dragging? */ + do_drag( local_x, local_y ); + } + else { /* not dragging */ + new_state = find_arrow( local_x, local_y ); + + if ( new_state == state ) { + /** Still in same arrow **/ + do_click(); + } + else { + if ( new_inside OR 1) { + /** The state changed, but we're still inside - that + means we moved off the arrow: begin dragging **/ + state = GLUI_SPINNER_STATE_BOTH; + } + else { + /*** Here check y of mouse position to determine whether to + drag ***/ + + /* ... */ + } + } + + /*** We switched to up/down dragging ***/ + if ( state == GLUI_SPINNER_STATE_BOTH ) { + glutSetCursor( GLUT_CURSOR_UP_DOWN ); + last_x = local_x; + last_y = local_y; + + /** If the spinner has limits, we reset the growth value, since + reset_growth() will compute a new growth value for dragging + vs. clicking. If the spinner has no limits, then we just let the + growth remain at whatever the user has incremented it up to **/ + if ( edittext->has_limits != GLUI_LIMIT_NONE ) + reset_growth(); + } + + redraw(); + } + + return false; +} + + +/****************************** GLUI_Spinner::key_handler() **********/ + +int GLUI_Spinner::key_handler( unsigned char key,int modifiers ) +{ + + + return true; +} + + +/****************************** GLUI_Spinner::draw() **********/ + +void GLUI_Spinner::draw( int x, int y ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + + if ( enabled ) { + /*** Draw the up arrow either pressed or unrpessed ***/ + if ( state == GLUI_SPINNER_STATE_UP OR state == GLUI_SPINNER_STATE_BOTH ) + glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_UP_ON, + w-GLUI_SPINNER_ARROW_WIDTH-1, + GLUI_SPINNER_ARROW_Y); + else + glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_UP_OFF, + w-GLUI_SPINNER_ARROW_WIDTH-1, + GLUI_SPINNER_ARROW_Y); + + /*** Draw the down arrow either pressed or unrpessed ***/ + if (state == GLUI_SPINNER_STATE_DOWN OR state == GLUI_SPINNER_STATE_BOTH) + glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_DOWN_ON, + w-GLUI_SPINNER_ARROW_WIDTH-1, + GLUI_SPINNER_ARROW_HEIGHT+GLUI_SPINNER_ARROW_Y); + else + glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_DOWN_OFF, + w-GLUI_SPINNER_ARROW_WIDTH-1, + GLUI_SPINNER_ARROW_HEIGHT+GLUI_SPINNER_ARROW_Y); + } + else { /**** The spinner is disabled ****/ + glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_UP_DIS, + w-GLUI_SPINNER_ARROW_WIDTH-1, + GLUI_SPINNER_ARROW_Y); + glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_DOWN_DIS, + w-GLUI_SPINNER_ARROW_WIDTH-1, + GLUI_SPINNER_ARROW_HEIGHT+GLUI_SPINNER_ARROW_Y); + } + + if ( active ) { + glColor3ub( 0, 0, 0 ); + glEnable( GL_LINE_STIPPLE ); + glLineStipple( 1, 0x5555 ); + } + else { + glColor3ub( glui->bkgd_color.r,glui->bkgd_color.g,glui->bkgd_color.b ); + } + + glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); + glDisable( GL_CULL_FACE ); + glBegin( GL_QUADS ); + glVertex2i( w-GLUI_SPINNER_ARROW_WIDTH-2, 0 ); + glVertex2i( w, 0 ); + glVertex2i( w, h ); + glVertex2i( w-GLUI_SPINNER_ARROW_WIDTH-2, h ); + glEnd(); + glDisable( GL_LINE_STIPPLE ); + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); +} + + +/********************************* GLUI_Spinner::special_handler() **********/ + +int GLUI_Spinner::special_handler( int key,int modifiers ) +{ + if ( key == GLUT_KEY_UP ) { /** Simulate a click in the up arrow **/ + mouse_down_handler( x_abs + w - GLUI_SPINNER_ARROW_WIDTH + 1, + y_abs + GLUI_SPINNER_ARROW_Y+1 ); + mouse_up_handler( x_abs + w - GLUI_SPINNER_ARROW_WIDTH + 1, + y_abs + GLUI_SPINNER_ARROW_Y+1, true ); + } + else if ( key == GLUT_KEY_DOWN ) { /** Simulate a click in the up arrow **/ + mouse_down_handler(x_abs + w - GLUI_SPINNER_ARROW_WIDTH + 1, + y_abs+GLUI_SPINNER_ARROW_Y+1+GLUI_SPINNER_ARROW_HEIGHT); + mouse_up_handler( x_abs + w - GLUI_SPINNER_ARROW_WIDTH + 1, + y_abs+GLUI_SPINNER_ARROW_Y+1 +GLUI_SPINNER_ARROW_HEIGHT, + true ); + } + else if ( key == GLUT_KEY_HOME ) { /** Set value to limit top - + or increment by 10 **/ + } + else if ( key == GLUT_KEY_END ) { + } + + return true; +} + + +/******************************* GLUI_Spinner::set_float_val() ************/ + +void GLUI_Spinner::set_float_val( float new_val ) +{ + if ( NOT edittext ) + return; + + edittext->set_float_val( new_val ); +} + + +/********************************** GLUI_Spinner::set_int_val() ************/ + +void GLUI_Spinner::set_int_val( int new_val ) +{ + if ( NOT edittext ) + return; + + edittext->set_int_val( new_val ); +} + + +/************************************ GLUI_Spinner::update_size() **********/ + +void GLUI_Spinner::update_size( void ) +{ + if (!edittext) return; + /*edittext->w = this->w - GLUI_SPINNER_ARROW_WIDTH-3; */ + this->w = edittext->w + GLUI_SPINNER_ARROW_WIDTH + 3; +} + + +/************************************ GLUI_Spinner::find_arrow() ************/ + +int GLUI_Spinner::find_arrow( int local_x, int local_y ) +{ + local_x -= x_abs; + local_y -= y_abs; + + if ( local_x >= (w - GLUI_SPINNER_ARROW_WIDTH) AND + local_x <= w ) { + + if ( local_y >= GLUI_SPINNER_ARROW_Y AND + local_y <= (GLUI_SPINNER_ARROW_Y+GLUI_SPINNER_ARROW_HEIGHT) ) + return GLUI_SPINNER_STATE_UP; + + if ( local_y >= GLUI_SPINNER_ARROW_Y+GLUI_SPINNER_ARROW_HEIGHT AND + local_y <= (GLUI_SPINNER_ARROW_Y+GLUI_SPINNER_ARROW_HEIGHT*2) ) + return GLUI_SPINNER_STATE_DOWN; + + } + + return GLUI_SPINNER_STATE_NONE; +} + + +/***************************************** GLUI_Spinner::do_click() **********/ + +void GLUI_Spinner::do_click( void ) +{ + int direction = 0; + float incr; + float modifier_factor; + + if ( state == GLUI_SPINNER_STATE_UP ) + direction = +1; + else if ( state == GLUI_SPINNER_STATE_DOWN ) + direction = -1; + + increase_growth(); + + modifier_factor = 1.0; + if ( glui ) { + if ( glui->curr_modifiers & GLUT_ACTIVE_SHIFT ) + modifier_factor = 100.0f; + else if ( glui->curr_modifiers & GLUT_ACTIVE_CTRL ) + modifier_factor = .01f; + } + + if ( this->data_type == GLUI_SPINNER_FLOAT OR 1) { + incr = growth * direction * modifier_factor * user_speed; + edittext->set_float_val( edittext->float_val + incr ); + /** Remember, edittext mirrors the float and int values ***/ + } + + /*** Now update live variable and do callback. We don't want + to do the callback on each iteration of this function, just on every + i^th iteration, where i is given by GLUI_SPINNER_CALLBACK_INTERVAL ****/ + callback_count++; + if ( (callback_count % GLUI_SPINNER_CALLBACK_INTERVAL ) == 0 ) + do_callbacks(); +} + + +/***************************************** GLUI_Spinner::do_drag() **********/ + +void GLUI_Spinner::do_drag( int x, int y ) +{ + int delta_y; + float incr, modifier_factor; + /* int delta_x; */ + + modifier_factor = 1.0f; + if ( glui ) { + if ( glui->curr_modifiers & GLUT_ACTIVE_SHIFT ) + modifier_factor = 100.0f; + else if ( glui->curr_modifiers & GLUT_ACTIVE_CTRL ) + modifier_factor = .01f; + } + + /* delta_x = x - last_x; */ + delta_y = -(y - last_y); + + if ( this->data_type == GLUI_SPINNER_FLOAT OR 1 ) { + incr = growth * delta_y * modifier_factor * user_speed; + edittext->set_float_val( edittext->float_val + incr ); + /** Remember, edittext mirrors the float and int values ***/ + } + + last_x = x; + last_y = y; + + /*** Now update live variable and do callback. We don't want + to do the callback on each iteration of this function, just on every + i^th iteration, where i is given by GLUI_SPINNER_CALLBACK_INTERVAL ****/ + + callback_count++; + if ( (callback_count % GLUI_SPINNER_CALLBACK_INTERVAL ) == 0 ) + do_callbacks(); +} + + +/***************************************** GLUI_Spinner::needs_idle() ******/ + +bool GLUI_Spinner::needs_idle( void ) const +{ + if (state == GLUI_SPINNER_STATE_UP OR state == GLUI_SPINNER_STATE_DOWN ) { + return true; + } + else { + return false; + } +} + +/***************************************** GLUI_Spinner::idle() **********/ + +void GLUI_Spinner::idle( void ) +{ + if ( NOT needs_idle() ) + return; + else + do_click(); +} + + +/************************************ GLUI_Spinner::do_callbacks() **********/ + +void GLUI_Spinner::do_callbacks( void ) +{ + /*** This is not necessary, b/c edittext automatically updates us ***/ + if ( NOT edittext ) + return; + this->float_val = edittext->float_val; + this->int_val = edittext->int_val; + /* *******************************************/ + + if ( NOT first_callback ) { + if ( data_type == GLUI_SPINNER_INT AND int_val == last_int_val ) { + return; + } + + if ( data_type == GLUI_SPINNER_FLOAT AND float_val == last_float_val ) { + return; + } + } + + this->execute_callback(); + + last_int_val = int_val; + last_float_val = float_val; + first_callback = false; +} + + +/********************************* GLUI_Spinner::set_float_limits() *********/ + +void GLUI_Spinner::set_float_limits( float low, float high, int limit_type ) +{ + if ( NOT edittext ) + return; + + edittext->set_float_limits( low, high, limit_type ); +} + + +/*********************************** GLUI_Spinner::set_int_limits() *********/ + +void GLUI_Spinner::set_int_limits( int low, int high, int limit_type ) +{ + if ( NOT edittext ) + return; + + edittext->set_int_limits( low, high, limit_type ); +} + + +/*********************************** GLUI_Spinner:reset_growth() *************/ + +void GLUI_Spinner::reset_growth( void ) +{ + float lo, hi; + + if ( edittext->has_limits == GLUI_LIMIT_NONE ) { + if ( data_type == GLUI_SPINNER_FLOAT ) + growth = sqrt(ABS(edittext->float_val)) * .05f; + else if ( data_type == GLUI_SPINNER_INT ) + growth = .4f; + } + else { + if ( data_type == GLUI_SPINNER_FLOAT ) { + lo = edittext->float_low; + hi = edittext->float_high; + growth = (hi-lo) / GLUI_SPINNER_GROWTH_STEPS; + } + else if ( data_type == GLUI_SPINNER_INT ) { + lo = (float) edittext->int_low; + hi = (float) edittext->int_high; + + growth = (hi-lo) / GLUI_SPINNER_GROWTH_STEPS; + } + } + + if ( growth == 0.0f ) + growth = .001f; +} + + +/******************************* GLUI_Spinner:increase_growth() *************/ + +void GLUI_Spinner::increase_growth( void ) +{ + float hi = 0.0,lo = 0.0; + + if ( data_type == GLUI_SPINNER_FLOAT ) { + lo = edittext->float_low; + hi = edittext->float_high; + } + else if ( data_type == GLUI_SPINNER_INT ) { + lo = (float) edittext->int_low; + hi = (float) edittext->int_high; + } + + if ( growth < (hi-lo) / GLUI_SPINNER_MIN_GROWTH_STEPS ) + growth *= growth_exp; + + /* printf( "growth: %f\n", growth ); */ +} + + +/*************************************** GLUI_Spinner:get_text() *************/ + +const char *GLUI_Spinner::get_text( void ) +{ + if (edittext) + return edittext->text.c_str(); + else + return ""; +} + + +/********************************** GLUI_Spinner:get_float_val() *************/ + +float GLUI_Spinner::get_float_val( void ) +{ + if (edittext) + return edittext->float_val; + else + return 0.0f; +} + + +/********************************** GLUI_Spinner:get_int_val() *************/ + +int GLUI_Spinner::get_int_val( void ) +{ + if (edittext) + return edittext->int_val; + else + return 0; +} + + diff --git a/Extras/glui/glui_statictext.cpp b/Extras/glui/glui_statictext.cpp new file mode 100644 index 0000000..21ffa13 --- /dev/null +++ b/Extras/glui/glui_statictext.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_statictext.cpp - GLUI_StaticText Control + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "glui_internal_control.h" + +/****************************** GLUI_StaticText::GLUI_StaticText() **********/ +GLUI_StaticText::GLUI_StaticText( GLUI_Node *parent, const char *name ) +{ + common_init(); + set_name( name ); + parent->add_control( this ); +} + +/****************************** GLUI_StaticText::draw() **********/ + +void GLUI_StaticText::draw( int x, int y ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + + draw_text(); +} + + +/****************************** GLUI_StaticText::set_text() **********/ + +void GLUI_StaticText::set_text( const char *text ) +{ + set_name( text ); + redraw(); +} + + +/************************************ GLUI_StaticText::update_size() **********/ + +void GLUI_StaticText::update_size( void ) +{ + int text_size; + + if ( NOT glui ) + return; + + text_size = string_width( name ); + + if ( w < text_size ) + w = text_size; +} + + +/****************************** GLUI_StaticText::draw_text() **********/ + +void GLUI_StaticText::draw_text( void ) +{ + if ( NOT can_draw() ) + return; + + erase_text(); + draw_name( 0, 9 ); +} + + +/****************************** GLUI_StaticText::erase_text() **********/ + +void GLUI_StaticText::erase_text( void ) +{ + if ( NOT can_draw() ) + return; + + set_to_bkgd_color(); + glDisable( GL_CULL_FACE ); + glBegin( GL_TRIANGLES ); + glVertex2i( 0,0 ); glVertex2i( w, 0 ); glVertex2i( w, h ); + glVertex2i( 0, 0 ); glVertex2i( w, h ); glVertex2i( 0, h ); + glEnd(); +} + + + diff --git a/Extras/glui/glui_string.cpp b/Extras/glui/glui_string.cpp new file mode 100644 index 0000000..b2fe2eb --- /dev/null +++ b/Extras/glui/glui_string.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui.cpp + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher (this file, Bill Baxter 2005) + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA + + This program is -not- in the public domain. + +*****************************************************************************/ + +#include "GL/glui.h" +#include + +#if defined (_MSC_VER) && (_MSC_VER < 1500) +#define vsnprintf _vsnprintf +#endif + +GLUI_String& glui_format_str(GLUI_String& str, const char* fmt, ...) +{ + const size_t ISIZE = 128; + char stackbuf[ISIZE]; + size_t bufsz = ISIZE; + char *buf = stackbuf; + str = ""; + va_list arg; + while (1) { + va_start(arg, fmt); + int ret = vsnprintf(buf,299,fmt,arg); + va_end(arg); + if (ret>=0) { + break; + } + // else make a bigger buf, try again + bufsz <<= 1; + if (buf==stackbuf) buf = (char*)malloc(sizeof(char)*bufsz); + else buf = (char*)realloc(buf, sizeof(char)*bufsz); + } + if (buf!=stackbuf) free(buf); + str=buf; + return str; +} diff --git a/Extras/glui/glui_textbox.cpp b/Extras/glui/glui_textbox.cpp new file mode 100644 index 0000000..342e009 --- /dev/null +++ b/Extras/glui/glui_textbox.cpp @@ -0,0 +1,1108 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_textbox.cpp - GLUI_TextBox control class + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher, 2004 John Kew + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "glui_internal_control.h" +#include + + +static const int LINE_HEIGHT = 15; + +/****************************** GLUI_TextBox::GLUI_TextBox() **********/ + +GLUI_TextBox::GLUI_TextBox(GLUI_Node *parent, GLUI_String &live_var, + bool scroll, int id, GLUI_CB callback ) +{ + common_construct(parent, &live_var, scroll, id, callback); +} + +/****************************** GLUI_TextBox::GLUI_TextBox() **********/ + +GLUI_TextBox::GLUI_TextBox( GLUI_Node *parent, bool scroll, int id, + GLUI_CB callback ) +{ + common_construct(parent, NULL, scroll, id, callback); +} + +/****************************** GLUI_TextBox::common_construct() **********/ +void GLUI_TextBox::common_construct( + GLUI_Node *parent, GLUI_String *data, + bool scroll, int id, GLUI_CB callback) +{ + common_init(); + + GLUI_Node *tb_panel = parent; + + if (scroll) { + GLUI_Panel *p = new GLUI_Panel(parent,"",GLUI_PANEL_NONE); + p->x_off = 1; + tb_panel = p; + } + this->ptr_val = data; + if (data) { + this->live_type = GLUI_LIVE_STRING; + } else { + this->live_type = GLUI_LIVE_NONE; + } + this->user_id = id; + this->callback = callback; + this->name = "textbox"; + tb_panel->add_control( this ); + if (scroll) { + new GLUI_Column(tb_panel, false); + scrollbar = + new GLUI_Scrollbar(tb_panel, + "scrollbar", + GLUI_SCROLL_VERTICAL, + GLUI_SCROLL_INT); + scrollbar->set_object_callback(GLUI_TextBox::scrollbar_callback, this); + scrollbar->set_alignment(GLUI_ALIGN_LEFT); + // scrollbar->can_activate = false; //kills ability to mouse drag too + } + init_live(); +} + +/****************************** GLUI_TextBox::mouse_down_handler() **********/ + +int GLUI_TextBox::mouse_down_handler( int local_x, int local_y ) +{ + int tmp_insertion_pt; + + if ( debug ) dump( stdout, "-> MOUSE DOWN" ); + + tmp_insertion_pt = find_insertion_pt( local_x, local_y ); + if ( tmp_insertion_pt == -1 ) { + if ( glui ) + glui->deactivate_current_control( ); + return false; + } + + insertion_pt = tmp_insertion_pt; + + sel_start = sel_end = insertion_pt; + + keygoal_x = insert_x; + + if ( can_draw()) + update_and_draw_text(); + + if ( debug ) dump( stdout, "<- MOUSE UP" ); + + return true; +} + + +/******************************** GLUI_TextBox::mouse_up_handler() **********/ + +int GLUI_TextBox::mouse_up_handler( int local_x, int local_y, bool inside ) +{ + return false; +} + + +/***************************** GLUI_TextBox::mouse_held_down_handler() ******/ + +int GLUI_TextBox::mouse_held_down_handler( int local_x, int local_y, + bool new_inside) +{ + int tmp_pt; + + if ( NOT new_inside ) return false; + + if ( debug ) dump( stdout, "-> HELD DOWN" ); + + tmp_pt = find_insertion_pt( local_x, local_y ); + keygoal_x = insert_x; + + if ( tmp_pt == -1 AND sel_end != 0 ) { /* moved mouse past left edge */ + special_handler( GLUT_KEY_LEFT, GLUT_ACTIVE_SHIFT ); + } + else if ( tmp_pt == substring_end+1 AND sel_end != (int) text.length()) { + /* moved mouse past right edge */ + special_handler( GLUT_KEY_RIGHT, GLUT_ACTIVE_SHIFT ); + } + else if ( tmp_pt != -1 AND tmp_pt != sel_end ) { + sel_end = insertion_pt = tmp_pt; + + update_and_draw_text(); + } + + if ( debug ) + dump( stdout, "<- HELD DOWN" ); + + return false; +} + + +/****************************** GLUI_TextBox::key_handler() **********/ +int GLUI_TextBox::key_handler( unsigned char key,int modifiers ) +{ + int regular_key; + /* int has_selection; */ + + if ( NOT glui ) + return false; + + if ( debug ) + dump( stdout, "-> KEY HANDLER" ); + + regular_key = false; + bool ctrl_down = (modifiers & GLUT_ACTIVE_CTRL)!=0; + /* has_selection = (sel_start != sel_end); */ + + if ( key == CTRL('[')) { /* ESCAPE */ + glui->deactivate_current_control(); + return true; + } + else if ( (key == 127 AND !ctrl_down) OR /* FORWARD DELETE */ + ( key == CTRL('d') AND modifiers == GLUT_ACTIVE_CTRL) ) + { + if ( sel_start == sel_end ) { /* no selection */ + if ( insertion_pt < (int)text.length() ) { + text.erase(insertion_pt,1); + } + } + else { /* There is a selection */ + clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end )); + insertion_pt = MIN(sel_start,sel_end); + sel_start = sel_end = insertion_pt; + } + } + else if ( ((key == 127) AND ctrl_down) OR // Delete word forward + ((key == 'd') AND (modifiers == GLUT_ACTIVE_ALT)) ) + { + if ( sel_start == sel_end ) { /* no selection */ + sel_start = insertion_pt; + sel_end = find_word_break( insertion_pt, +1 ); + } + + clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end )); + insertion_pt = MIN(sel_start,sel_end); + sel_start = sel_end = insertion_pt; + } + else if ( key == CTRL('h') ) { /* BACKSPACE */ + if ( sel_start == sel_end ) { /* no selection */ + if ( insertion_pt > 0 ) { + insertion_pt--; + text.erase(insertion_pt,1); + } + } + else { /* There is a selection */ + clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end )); + insertion_pt = MIN(sel_start,sel_end); + sel_start = sel_end = insertion_pt; + } + } + else if ( modifiers == GLUT_ACTIVE_CTRL ) /* CTRL ONLY */ + { + /* Ctrl-key bindings */ + if ( key == CTRL('a') ) { + return special_handler( GLUT_KEY_HOME, 0 ); + } + else if ( key == CTRL('e') ) { + return special_handler( GLUT_KEY_END, 0 ); + } + else if ( key == CTRL('b') ) { + return special_handler( GLUT_KEY_LEFT, 0 ); + } + else if ( key == CTRL('f') ) { + return special_handler( GLUT_KEY_RIGHT, 0 ); + } + else if ( key == CTRL('p') ) { + return special_handler( GLUT_KEY_UP, 0 ); + } + else if ( key == CTRL('n') ) { + return special_handler( GLUT_KEY_DOWN, 0 ); + } + else if ( key == CTRL('u') ) { /* ERASE LINE */ + insertion_pt = 0; + text.erase(0,text.length()); + sel_start = sel_end = 0; + } + else if ( key == CTRL('k') ) { /* KILL TO END OF LINE */ + sel_start = sel_end = insertion_pt; + text.erase(insertion_pt,GLUI_String::npos); + } + } + else if ( modifiers == GLUT_ACTIVE_ALT ) /* ALT ONLY */ + { + if ( key == 'b' ) { // Backward word + return special_handler ( GLUT_KEY_LEFT, GLUT_ACTIVE_CTRL ); + } + if ( key == 'f' ) { // Forward word + return special_handler ( GLUT_KEY_RIGHT, GLUT_ACTIVE_CTRL ); + } + } + else if ( (modifiers & GLUT_ACTIVE_CTRL) OR + (modifiers & GLUT_ACTIVE_ALT) ) + { + /** ignore other keys with modifiers */ + return true; + } + else { /* Regular key */ + if ( key == 13 ) /* RETURNS are written as newlines*/ + key = '\n'; + + regular_key = true; + + /** This is just to get rid of warnings - the flag regular_key is + set if the key was not a backspace, return, whatever. But I + believe if we're here, we know it was a regular key anyway */ + if ( regular_key ) { + } + + /**** If there's a current selection, erase it ******/ + if ( sel_start != sel_end ) { + clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end )); + insertion_pt = MIN(sel_start,sel_end); + sel_start = sel_end = insertion_pt; + } + + /******** We insert the character into the string ***/ + + text.insert(insertion_pt,1,key); + + /******** Move the insertion point and substring_end one over ******/ + insertion_pt++; + substring_end++; + + sel_start = sel_end = insertion_pt; + } + + /******** Now redraw text ***********/ + /* Hack to prevent text box from being cleared first **/ + /** int substring_change = update_substring_bounds(); + draw_text_only = + (NOT substring_change AND NOT has_selection AND regular_key ); + */ + + draw_text_only = false; /** Well, hack is not yet working **/ + update_and_draw_text(); + draw_text_only = false; + + + if ( debug ) + dump( stdout, "<- KEY HANDLER" ); + + return true; +} + +/****************************** GLUI_TextBox::enable() **********/ + +void GLUI_TextBox::enable( void ) +{ + GLUI_Control::enable(); + scrollbar->enable(); +} + +/****************************** GLUI_TextBox::disable() **********/ + +void GLUI_TextBox::disable( void ) +{ + GLUI_Control::disable(); + scrollbar->disable(); +} + +/****************************** GLUI_TextBox::activate() **********/ + +void GLUI_TextBox::activate( int how ) +{ + if ( debug ) + dump( stdout, "-> ACTIVATE" ); + active = true; + + if ( how == GLUI_ACTIVATE_MOUSE ) + return; /* Don't select everything if activated with mouse */ + + orig_text = text; + + sel_start = 0; + sel_end = int(text.length()); + insertion_pt = 0; + if ( debug ) + dump( stdout, "<- ACTIVATE" ); +} + + +/****************************** GLUI_TextBox::deactivate() **********/ + +void GLUI_TextBox::deactivate( void ) +{ + active = false; + + if ( NOT glui ) + return; + + if ( debug ) + dump( stdout, "-> DISACTIVATE" ); + + sel_start = sel_end = insertion_pt = -1; + + /***** Retrieve the current value from the text *****/ + /***** The live variable will be updated by set_text() ****/ + set_text(text.c_str()); /* This will force callbacks and gfx refresh */ + + update_substring_bounds(); + + /******** redraw text without insertion point ***********/ + redraw(); + + /***** Now do callbacks if value changed ******/ + if ( orig_text != text ) { + this->execute_callback(); + + + } + + + if ( debug ) + dump( stdout, "<- DISACTIVATE" ); +} + +/****************************** GLUI_TextBox::draw() **********/ + +void GLUI_TextBox::draw( int x, int y ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + int line = 0; + int text_length; + int box_width; + int i; + + /* Bevelled Border */ + glBegin( GL_LINES ); + glColor3f( .5, .5, .5 ); + glVertex2i( 0, 0 ); glVertex2i( w, 0 ); + glVertex2i( 0, 0 ); glVertex2i( 0, h ); + + glColor3f( 1., 1., 1. ); + glVertex2i( 0, h ); glVertex2i( w, h ); + glVertex2i( w, h ); glVertex2i( w, 0 ); + + if ( enabled ) + glColor3f( 0., 0., 0. ); + else + glColor3f( .25, .25, .25 ); + glVertex2i( 1, 1 ); glVertex2i( w-1, 1 ); + glVertex2i( 1, 1 ); glVertex2i( 1, h-1 ); + + glColor3f( .75, .75, .75 ); + glVertex2i( 1, h-1 ); glVertex2i( w-1, h-1 ); + glVertex2i( w-1, h-1 ); glVertex2i( w-1, 1 ); + glEnd(); + + /* Draw Background if enabled*/ + if (enabled) { + glColor3f( 1., 1., 1. ); + glDisable( GL_CULL_FACE ); + glBegin( GL_QUADS ); + glVertex2i( 2, 2 ); glVertex2i( w-2, 2 ); + glVertex2i( w-2, h-2 ); glVertex2i(2, h-2 ); + glEnd(); + } else { + glColor3f( .8, .8, .8 ); + glDisable( GL_CULL_FACE ); + glBegin( GL_QUADS ); + glVertex2i( 2, 2 ); glVertex2i( w-2, 2 ); + glVertex2i( w-2, h-2 ); glVertex2i(2, h-2 ); + glEnd(); + } + + /* Begin Drawing Lines of Text */ + substring_start = 0; + substring_end = 0; + text_length = int(text.length())-1; + + /* Figure out how wide the box is */ + box_width = get_box_width(); + + /* Get the first line substring */ + while (substring_width(substring_start, substring_end+1 ) < box_width && + substring_end < text_length && text[substring_end+1] != '\n') + substring_end++; + + /* Figure out which lines are visible*/ + + visible_lines = (int)(h-20)/LINE_HEIGHT; + if (start_line < (curr_line-visible_lines)) { + for (i = 0; ((curr_line-i)*LINE_HEIGHT+20) > h; i++); + start_line = i; + } else if ( start_line > curr_line) { + start_line = curr_line; + } + line = 0; + do { + if (line && substring_end < text_length) { + substring_start = substring_end+1; + while (substring_width(substring_start, substring_end+1 ) < box_width && + substring_end < text_length && text[substring_end+1] != '\n') + substring_end++; + } + if (text[substring_end+1] == '\n') { /* Skip newline */ + substring_end++; + } + if (line < start_line || (line > curr_line && curr_line > (start_line + visible_lines))) { + line++; + continue; + } + if ((line - start_line) <= visible_lines) + draw_text(0,(line - start_line)*LINE_HEIGHT); /* tabs and other nasties are handled by substring_width */ + line++; + } while (substring_end < text_length); + + num_lines = line; + + draw_insertion_pt(); + if (scrollbar) { + scrollbar->set_int_limits(MAX(0,num_lines/*-1*/-visible_lines),0); + glPushMatrix(); + glTranslatef(scrollbar->x_abs-x_abs, scrollbar->y_abs-y_abs,0.0); + scrollbar->draw_scroll(); + glPopMatrix(); + } +} + + + +/************************** GLUI_TextBox::update_substring_bounds() *********/ + +int GLUI_TextBox::update_substring_bounds( void ) +{ + int box_width; + int text_len = int(text.length()); + int old_start, old_end; + + old_start = substring_start; + old_end = substring_end; + + /*** Calculate the width of the usable area of the edit box ***/ + box_width = get_box_width(); + + CLAMP( substring_end, 0, MAX(text_len-1,0) ); + CLAMP( substring_start, 0, MAX(text_len-1,0) ); + + if ( debug ) dump( stdout, "-> UPDATE SS" ); + + if ( insertion_pt >= 0 AND + insertion_pt < substring_start ) { /* cursor moved left */ + substring_start = insertion_pt; + + while ( substring_width( substring_start, substring_end ) > box_width ) + substring_end--; + } + else if ( insertion_pt > substring_end ) { /* cursor moved right */ + substring_end = insertion_pt-1; + + while ( substring_width( substring_start, substring_end ) > box_width ) + substring_start++; + } + else { /* cursor is within old substring bounds */ + if ( last_insertion_pt > insertion_pt ) { /* cursor moved left */ + } + else { + while ( substring_width( substring_start, substring_end ) > box_width ) + substring_end--; + + while(substring_width( substring_start, substring_end+1 ) <= box_width + AND substring_end < text_len-1 ) + substring_end++; + } + } + + while ( substring_width( substring_start, substring_end ) > box_width ) + substring_end--; + + last_insertion_pt = insertion_pt; + + /*** No selection if not enabled ***/ + if ( NOT enabled ) { + sel_start = sel_end = 0; + } + + if ( debug ) dump( stdout, "<- UPDATE SS" ); + + if ( substring_start == old_start AND substring_end == old_end ) + return false; /*** bounds did not change ***/ + else + return true; /*** bounds did change ***/ + +} + + +/********************************* GLUI_TextBox::update_x_offsets() *********/ + +void GLUI_TextBox::update_x_offsets( void ) +{ +} + + +/********************************* GLUI_TextBox::draw_text() ****************/ + +void GLUI_TextBox::draw_text( int x, int y ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + int text_x, i, sel_lo, sel_hi, x_pos; + + if ( debug ) dump( stdout, "-> DRAW_TEXT" ); + + /** Find where to draw the text **/ + + text_x = 2 + GLUI_TEXTBOX_BOXINNERMARGINX; + + /** Find lower and upper selection bounds **/ + sel_lo = MIN(sel_start, sel_end ); + sel_hi = MAX(sel_start, sel_end ); + + int sel_x_start, sel_x_end, delta; + + /** Draw selection area dark **/ + if ( sel_start != sel_end ) { + sel_x_start = text_x; + sel_x_end = text_x; + delta = 0; + for( i=substring_start; sel_x_end < (w - text_x) && i<=substring_end; i++ ) { + delta = 0; + if (text[i] == '\t') // Character is a tab, go to next tab stop + while (((delta + sel_x_end) < (w - text_x)) && + (delta == 0 || delta % tab_width)) + delta++; + else + delta = char_width( text[i] ); + + if ( i < sel_lo ) { + sel_x_start += delta; + sel_x_end += delta; + } + else if ( i < sel_hi ) { + sel_x_end += delta; + } + } + + glColor3f( 0.0f, 0.0f, .6f ); + glRecti(sel_x_start, y+5, sel_x_end, y+20); + } + + + if ( sel_start == sel_end ) { // No current selection + x_pos = text_x; + if ( enabled ) + glColor3b( 0, 0, 0 ); + else + glColor3b( 32, 32, 32 ); + + glRasterPos2i( text_x, y+LINE_HEIGHT); + for( i=substring_start; i<=substring_end; i++ ) { + if (this->text[i] == '\t') { // Character is a tab, go to next tab stop + x_pos = ((x_pos-text_x)/tab_width)*tab_width+tab_width+text_x; + glRasterPos2i( x_pos, y+LINE_HEIGHT); // Reposition pen after tab + } else { + glutBitmapCharacter( get_font(), this->text[i] ); + x_pos += char_width( this->text[i] ); + } + } + } + else { // There is a selection + x_pos = text_x; + for( i=substring_start; i<=substring_end; i++ ) { + if ( IN_BOUNDS( i, sel_lo, sel_hi-1)) { // This character is selected + glColor3f( 1., 1., 1. ); + glRasterPos2i( x_pos, y+LINE_HEIGHT); + if (this->text[i] == '\t') { // Character is a tab, go to next tab stop + x_pos = ((x_pos-text_x)/tab_width)*tab_width+tab_width+text_x; + } + else + glutBitmapCharacter( get_font(), this->text[i] ); + } + else { + glColor3f( 0., 0., 0. ); + glRasterPos2i( x_pos, y+LINE_HEIGHT); + if (this->text[i] == '\t') { // Character is a tab, go to next tab stop + x_pos = ((x_pos-text_x)/tab_width)*tab_width+tab_width+text_x; + glRasterPos2i( x_pos, y+LINE_HEIGHT); // Reposition pen after tab + } else + glutBitmapCharacter( get_font(), this->text[i] ); + } + + x_pos += char_width( text[i] ); + } + } + + if ( debug ) dump( stdout, "<- DRAW_TEXT" ); +} + + +/******************************** GLUI_TextBox::find_insertion_pt() *********/ +/* This function returns the character number *before which* the insertion */ +/* point goes */ + +int GLUI_TextBox::find_insertion_pt( int x, int y ) +{ + /*** See if we clicked outside box ***/ + if ( x < this->x_abs || y < this->y_abs) + return -1; + + /*** See if we clicked in an empty box ***/ + if ( text.empty() ) + return 0; + + /* update insert variables */ + insert_x = x; + insert_y = y; + + int text_length = int(text.length())-1; + int box_width = get_box_width(); + + int sol = 0; + int eol = 0; + int line = 0; + + int y_off = y - (y_abs + 2 + GLUI_TEXTBOX_BOXINNERMARGINX); + int x_off = x - (x_abs + 2 + GLUI_TEXTBOX_BOXINNERMARGINX); + + /* Find the line clicked, + The possibility of long lines getting wrapped complicates this. */ + while ((line-start_line+1)*LINE_HEIGHT < y_off && eol < text_length) + { + while (eol < text_length && text[eol] != '\n' && + substring_width(sol, eol+1) <= box_width) + { + eol++; + } + if (text[eol]=='\n' && eol=x_off) { + // did we go far enough? (see if click was >1/2 width of last char) + int decision_pt = prev_w+(total_w-prev_w)/2; + if (x_off>decision_pt) eol++; + } + return eol; + +#if 0 + while (eol < text_length && text[eol] != '\n' && + substring_width(sol, eol+1) < box_width ) + { + eol++; + } + + + /* We move from right to left, looking to see if the mouse was clicked + to the right of the ith character */ +#if 0 + int curr_x = this->x_abs + + substring_width( sol, eol ) + + 2 /* The edittext box has a 2-pixel margin */ + + GLUI_TEXTBOX_BOXINNERMARGINX; /** plus this many pixels blank space + between the text and the box **/ +#endif + + /** find mouse click in text **/ + + if (x_off > substring_width(sol, eol)) + return eol; + + for(i = sol; i <= eol+1; i++) { + if (x_off <= substring_width(sol, i)) + return i+1; + } + return 0; +#endif +} + + +int GLUI_TextBox::get_box_width() +{ + return MAX( this->w + - 4 /* 2 * the two-line box border */ + - 2 * GLUI_TEXTBOX_BOXINNERMARGINX, 0 ); + +} + +/******************************** GLUI_TextBox::draw_insertion_pt() *********/ + +void GLUI_TextBox::draw_insertion_pt( void ) +{ + int curr_x, box_width, text_length, eol, sol, line; + + if ( NOT can_draw() ) + return; + + /*** Don't draw insertion pt if control is disabled ***/ + if ( NOT enabled ) + return; + + if ( sel_start != sel_end OR insertion_pt < 0 ) { + return; /* Don't draw insertion point if there is a current selection */ + } + + if ( debug ) dump( stdout, "-> DRAW_INS_PT" ); + + /* printf( "insertion pt: %d\n", insertion_pt ); */ + + box_width = get_box_width(); + + // This function is unable to distinguish whether an insertion + // point on a line break should be drawn on the line before or the line after. + // This depends on the sequence of operations used to get there, and this + // function just doesn't have that information. If curr_line were kept up + // to date elsewhere that could be used here to disambiguate, but arrow keys + // and such do not update it. + + sol = 0; + eol = 0; + text_length = int(text.length())-1; + + //while (eol < text_length && text[eol] != '\n' + // && substring_width(sol, eol + 1) < box_width ) + // eol++; + line = 0; + while (eol < insertion_pt && eol <= text_length) + { + if (text[eol] == '\n' || substring_width(sol, eol + 1) >= box_width) + { + eol++; + if (text[eol]=='\n'||eol!=insertion_pt + ||(eol==insertion_pt && eol>0 && text[eol-1]=='\n')) { + sol = eol; + line++; + } + } + else { + eol++; + } + } + + //glColor3f(1,0,0); + //glRecti(0, curr_line*LINE_HEIGHT, 3, (curr_line+1)*LINE_HEIGHT); + + curr_line = line; + + if (scrollbar) + scrollbar->set_int_val(start_line); + if (curr_line < start_line || curr_line > (start_line + visible_lines)) /* Insertion pt out of draw area */ + return; + + curr_x = this->x_abs + + 2 /* The edittext box has a 2-pixel margin */ + + GLUI_TEXTBOX_BOXINNERMARGINX; /** plus this many pixels blank space + between the text and the box **/ + + curr_x += substring_width(sol,insertion_pt-1); + if (insertion_pt == text.length() && text[text.length()-1] == '\n' + || curr_x-this->x_abs > (w - 2 - GLUI_TEXTBOX_BOXINNERMARGINX)) { // Insert on the next line + curr_x = this->x_abs + GLUI_TEXTBOX_BOXINNERMARGINX; + line++; + } + /* update insertion coordinates */ + insert_x = curr_x+5; /* I hate magic numbers too, these offset the imagined insertion point */ + insert_y = (curr_line-start_line+2)*LINE_HEIGHT; + + + glColor3f( 0.0, 0.0, 0.0 ); + glBegin( GL_LINE_LOOP ); + + curr_x -= x_abs; + glVertex2i( curr_x+1, (curr_line-start_line)*LINE_HEIGHT + 4 ); + glVertex2i( curr_x, (curr_line-start_line)*LINE_HEIGHT + 4 ); + glVertex2i( curr_x+1, (curr_line-start_line)*LINE_HEIGHT + 16 ); + glVertex2i( curr_x, (curr_line-start_line)*LINE_HEIGHT + 16 ); + glEnd(); + + + if ( debug ) dump( stdout, "-> DRAW_INS_PT" ); +} + + + + +/******************************** GLUI_TextBox::substring_width() *********/ +int GLUI_TextBox::substring_width( int start, int end, int initial_width ) +{ + // This function only works properly if start is really the start of a line. + // Otherwise tabs will be messed up. + int i, width = initial_width; + + for( i=start; i<=end; i++ ) + if (text[i] == '\t') { // Character is a tab, jump to next tab stop + width += tab_width-(width%tab_width); + //while (width == 0 || width % tab_width) + // width++; + } + else + width += char_width( text[i] ); + + return width; +} + + +/***************************** GLUI_TextBox::update_and_draw_text() ********/ + +void GLUI_TextBox::update_and_draw_text( void ) +{ + //update_substring_bounds(); + /* printf( "ss: %d/%d\n", substring_start, substring_end ); */ + + redraw(); +} + + +/********************************* GLUI_TextBox::special_handler() **********/ + +int GLUI_TextBox::special_handler( int key,int modifiers ) +{ + int tmp_insertion_pt; + if ( NOT glui ) + return false; + + if ( debug ) + printf( "SPECIAL:%d - mod:%d subs:%d/%d ins:%d sel:%d/%d\n", + key, modifiers, substring_start, substring_end,insertion_pt, + sel_start, sel_end ); + + if ( key == GLUT_KEY_DOWN ) { + if (insert_x == -1 || insert_y == -1) + return false; + tmp_insertion_pt = find_insertion_pt( keygoal_x, insert_y+LINE_HEIGHT); + if (tmp_insertion_pt < 0) + return false; + insertion_pt = tmp_insertion_pt; + sel_end = insertion_pt; + if (!(modifiers & GLUT_ACTIVE_SHIFT)) { + sel_start = sel_end; + } + if ( can_draw()) + update_and_draw_text(); + } else if ( key == GLUT_KEY_UP ) { + if (insert_x == -1 || insert_y == -1) + return false; + tmp_insertion_pt = find_insertion_pt( keygoal_x, insert_y-LINE_HEIGHT); + if (tmp_insertion_pt < 0) + return false; + insertion_pt = tmp_insertion_pt; + sel_end = insertion_pt; + if (!(modifiers & GLUT_ACTIVE_SHIFT)) { + sel_start = sel_end; + } + if ( can_draw()) + update_and_draw_text(); + } else if ( key == GLUT_KEY_LEFT ) { + if ( (modifiers & GLUT_ACTIVE_CTRL) != 0 ) { + insertion_pt = find_word_break( insertion_pt, -1 ); + } + else { + insertion_pt--; + } + // update keygoal_x! + } + else if ( key == GLUT_KEY_RIGHT ) { + if ( (modifiers & GLUT_ACTIVE_CTRL) != 0 ) { + insertion_pt = find_word_break( insertion_pt, +1 ); + } + else { + insertion_pt++; + } + // update keygoal_x! + } + else if ( key == GLUT_KEY_HOME ) { + insertion_pt = 0; + // update keygoal_x! + } + else if ( key == GLUT_KEY_END ) { + insertion_pt = int(text.length()); + // update keygoal_x! + } + + /*** Update selection if shift key is down ***/ + if ( (modifiers & GLUT_ACTIVE_SHIFT ) != 0 ) + sel_end = insertion_pt; + else + sel_start = sel_end = insertion_pt; + + + CLAMP( insertion_pt, 0, (int)text.length()); /* Make sure insertion_pt + is in bounds */ + CLAMP( sel_start, 0, (int)text.length()); /* Make sure insertion_pt + is in bounds */ + CLAMP( sel_end, 0, (int)text.length()); /* Make sure insertion_pt + is in bounds */ + + /******** Now redraw text ***********/ + if ( can_draw()) + update_and_draw_text(); + + return true; +} + + +/****************************** GLUI_TextBox::find_word_break() **********/ +/* It looks either left or right (depending on value of 'direction' */ +/* for the beginning of the next 'word', where word are characters */ +/* separated by one of the following tokens: " :-.," */ +/* If there is no next word in the specified direction, this returns */ +/* the beginning of 'text', or the very end. */ + +int GLUI_TextBox::find_word_break( int start, int direction ) +{ + int i, j; + char breaks[] = " \n\t:-.,"; + int num_break_chars = (int)strlen(breaks), text_len = int(text.length()); + int new_pt; + + /** If we're moving left, we have to start two back, in case we're either + already at the beginning of a word, or on a separating token. + Otherwise, this function would just return the word we're already at **/ + if ( direction == -1 ) { + start -= 2; + } + + /***** Iterate over text in the specified direction *****/ + for ( i=start; i >= 0 AND i < text_len; i += direction ) { + + /** For each character in text, iterate over list of separating tokens **/ + for( j=0; j 0 ) /* Return the end of string */ + return text_len; + else /* Return the beginning of the text */ + return 0; +} + + +/********************************** GLUI_TextBox::clear_substring() ********/ + +void GLUI_TextBox::clear_substring( int start, int end ) +{ + text.erase(start,end-start); +} + + + +/************************************ GLUI_TextBox::update_size() **********/ + +void GLUI_TextBox::update_size( void ) +{ + if ( NOT glui ) + return; + + if ( w < GLUI_TEXTBOX_MIN_TEXT_WIDTH ) + w = GLUI_TEXTBOX_MIN_TEXT_WIDTH; +} + + +/****************************** GLUI_TextBox::set_text() **********/ + +void GLUI_TextBox::set_text( const char *new_text ) +{ + text = new_text; + + substring_start = 0; + substring_end = int(text.length()) - 1; + insertion_pt = -1; + sel_start = 0; + sel_end = 0; + visible_lines = 0; + start_line = 0; + curr_line = 0; + num_lines = 0; + + if ( can_draw() ) + update_and_draw_text(); + + /*** Now update the live variable ***/ + output_live(true); +} + + +/*************************************** GLUI_TextBox::dump() **************/ + +void GLUI_TextBox::dump( FILE *out, const char *name ) +{ + fprintf( out, + "%s (edittext@%p): line:%d ins_pt:%d subs:%d/%d sel:%d/%d len:%zu\n", + name, this, curr_line, + insertion_pt, substring_start, substring_end, sel_start, sel_end, + text.length()); +} + + +/**************************************** GLUI_TextBox::mouse_over() ********/ + +int GLUI_TextBox::mouse_over( int state, int x, int y ) +{ + if ( state && enabled) { + /* curr_cursor = GLUT_CURSOR_TEXT; */ + glutSetCursor( GLUT_CURSOR_TEXT ); + } + else { + /* printf( "OUT\n" ); */ + glutSetCursor( GLUT_CURSOR_LEFT_ARROW ); + } + + return true; +} + +void GLUI_TextBox::scrollbar_callback(GLUI_Control *my_scrollbar) { + GLUI_Scrollbar *sb = my_scrollbar->dynamicCastGLUI_Scrollbar(); + if (!sb) return; + GLUI_TextBox* me = (GLUI_TextBox*) sb->associated_object; + if (me->scrollbar == NULL) + return; + int new_start_line = sb->get_int_val(); // ?? + me->start_line = new_start_line; + if (new_start_line < (me->curr_line - me->visible_lines)) + me->curr_line = new_start_line + me->visible_lines; + if (new_start_line > me->curr_line) + me->curr_line = new_start_line; + if ( me->can_draw() ) + me->update_and_draw_text(); +} diff --git a/Extras/glui/glui_translation.cpp b/Extras/glui/glui_translation.cpp new file mode 100644 index 0000000..43e82d8 --- /dev/null +++ b/Extras/glui/glui_translation.cpp @@ -0,0 +1,559 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_translation - GLUI_Translation control class + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#include "GL/glui.h" +#include "glui_internal.h" +#include "algebra3.h" + +/********************** GLUI_Translation::GLUI_Translation() ***/ + +GLUI_Translation::GLUI_Translation( + GLUI_Node *parent, const char *name, + int trans_t, float *value_ptr, + int id, GLUI_CB cb ) +{ + common_init(); + + set_ptr_val( value_ptr ); + user_id = id; + set_name( name ); + callback = cb; + parent->add_control( this ); + //init_live(); + + trans_type = trans_t; + + if ( trans_type == GLUI_TRANSLATION_XY ) { + float_array_size = 2; + } + else if ( trans_type == GLUI_TRANSLATION_X ) { + float_array_size = 1; + } + else if ( trans_type == GLUI_TRANSLATION_Y ) { + float_array_size = 1; + } + else if ( trans_type == GLUI_TRANSLATION_Z ) { + float_array_size = 1; + } + init_live(); +} + +/********************** GLUI_Translation::iaction_mouse_down_handler() ***/ +/* These are really in local coords (5/10/99) */ + +int GLUI_Translation::iaction_mouse_down_handler( int local_x, + int local_y ) +{ + int center_x, center_y; + + down_x = local_x; + down_y = local_y; + + if ( trans_type == GLUI_TRANSLATION_XY ) { + orig_x = float_array_val[0]; + orig_y = float_array_val[1]; + + /** Check if the Alt key is down, which means lock to an axis **/ + + center_x = w/2; + center_y = (h-18)/2; + + if ( glui->curr_modifiers & GLUT_ACTIVE_ALT ) { + if ( ABS(local_y-center_y) > ABS(local_x-center_x) ) { + locked = GLUI_TRANSLATION_LOCK_Y; + glutSetCursor( GLUT_CURSOR_UP_DOWN ); + } + else { + locked = GLUI_TRANSLATION_LOCK_X; + glutSetCursor( GLUT_CURSOR_LEFT_RIGHT ); + } + } + else { + locked = GLUI_TRANSLATION_LOCK_NONE; + glutSetCursor( GLUT_CURSOR_SPRAY ); + } + } + else if ( trans_type == GLUI_TRANSLATION_X ) { + glutSetCursor( GLUT_CURSOR_LEFT_RIGHT ); + orig_x = float_array_val[0]; + } + else if ( trans_type == GLUI_TRANSLATION_Y ) { + glutSetCursor( GLUT_CURSOR_UP_DOWN ); + orig_y = float_array_val[0]; + } + else if ( trans_type == GLUI_TRANSLATION_Z ) { + glutSetCursor( GLUT_CURSOR_UP_DOWN ); + orig_z = float_array_val[0]; + } + + trans_mouse_code = 1; + redraw(); + + return false; +} + + +/*********************** GLUI_Translation::iaction_mouse_up_handler() **********/ + +int GLUI_Translation::iaction_mouse_up_handler( int local_x, int local_y, + bool inside ) +{ + trans_mouse_code = GLUI_TRANSLATION_MOUSE_NONE; + locked = GLUI_TRANSLATION_LOCK_NONE; + + redraw(); + + return false; +} + + +/******************* GLUI_Translation::iaction_mouse_held_down_handler() ******/ + +int GLUI_Translation::iaction_mouse_held_down_handler( int local_x, int local_y, + bool inside) +{ + float x_off, y_off; + float off_array[2]; + + x_off = scale_factor * (float)(local_x - down_x); + y_off = -scale_factor * (float)(local_y - down_y); + + if ( glui->curr_modifiers & GLUT_ACTIVE_SHIFT ) { + x_off *= 100.0f; + y_off *= 100.0f; + } + else if ( glui->curr_modifiers & GLUT_ACTIVE_CTRL ) { + x_off *= .01f; + y_off *= .01f; + } + + + if ( trans_type == GLUI_TRANSLATION_XY ) { + + if ( locked == GLUI_TRANSLATION_LOCK_X ) + y_off = 0.0; + else if ( locked == GLUI_TRANSLATION_LOCK_Y ) + x_off = 0.0; + + off_array[0] = x_off + orig_x; + off_array[1] = y_off + orig_y; + } + else if ( trans_type == GLUI_TRANSLATION_X ) { + off_array[0] = x_off + orig_x; + } + else if ( trans_type == GLUI_TRANSLATION_Y ) { + off_array[0] = y_off + orig_y; + } + else if ( trans_type == GLUI_TRANSLATION_Z ) { + off_array[0] = y_off + orig_z; + } + + set_float_array_val( (float*) &off_array[0] ); + + return false; +} + + +/******************** GLUI_Translation::iaction_draw_active_area_persp() **************/ + +void GLUI_Translation::iaction_draw_active_area_persp( void ) +{ +} + + +/******************** GLUI_Translation::iaction_draw_active_area_ortho() **********/ + +void GLUI_Translation::iaction_draw_active_area_ortho( void ) +{ + /********* Draw emboss circles around arcball control *********/ + float radius; + radius = (float)(h-22)/2.0; /* MIN((float)w/2.0, (float)h/2.0); */ + glLineWidth( 1.0 ); + + draw_emboss_box( (int) -radius-2, (int)radius+2, + (int)-radius-2, (int)radius+2 ); + + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glTranslatef( .5, .5, .5 ); + /* glScalef( radius-1.0, radius-1.0, radius-1.0 ); */ + if ( trans_type == GLUI_TRANSLATION_Z ) + draw_2d_z_arrows((int)radius-1); + else if ( trans_type == GLUI_TRANSLATION_XY ) + draw_2d_xy_arrows((int)radius-1); + else if ( trans_type == GLUI_TRANSLATION_X ) + draw_2d_x_arrows((int)radius-1); + else if ( trans_type == GLUI_TRANSLATION_Y ) + draw_2d_y_arrows((int)radius-1); + + glPopMatrix(); +} + + +/******************************** GLUI_Translation::iaction_dump() **********/ + +void GLUI_Translation::iaction_dump( FILE *output ) +{ +} + + +/******************** GLUI_Translation::iaction_special_handler() **********/ + +int GLUI_Translation::iaction_special_handler( int key,int modifiers ) +{ + + return false; +} + + + +/*************************** GLUI_Translation::draw_2d_z_arrows() **************/ + +void GLUI_Translation::draw_2d_z_arrows( int radius ) +{ + if ( trans_mouse_code != GLUI_TRANSLATION_MOUSE_NONE ) { + draw_2d_arrow(radius, true, 2); + draw_2d_arrow(radius, true, 0); + } + else { + draw_2d_arrow(radius, false, 2); + draw_2d_arrow(radius, false, 0); + } +} + + +/*************************** GLUI_Translation::draw_2d_x_arrows() **************/ + +void GLUI_Translation::draw_2d_x_arrows( int radius ) +{ + if ( trans_mouse_code != GLUI_TRANSLATION_MOUSE_NONE ) { + draw_2d_arrow(radius, true, 1); + draw_2d_arrow(radius, true, 3); + } + else { + draw_2d_arrow(radius, false, 1); + draw_2d_arrow(radius, false, 3); + } +} + + +/*************************** GLUI_Translation::draw_2d_y_arrows() **************/ + +void GLUI_Translation::draw_2d_y_arrows( int radius ) +{ + if ( trans_mouse_code != GLUI_TRANSLATION_MOUSE_NONE ) { + draw_2d_arrow(radius, true, 0); + draw_2d_arrow(radius, true, 2); + } + else { + draw_2d_arrow(radius, false, 0); + draw_2d_arrow(radius, false, 2); + } +} + + +/************************** GLUI_Translation::draw_2d_xy_arrows() **************/ + +void GLUI_Translation::draw_2d_xy_arrows( int radius) +{ + if ( trans_mouse_code != GLUI_TRANSLATION_MOUSE_NONE ) { + if ( locked == GLUI_TRANSLATION_LOCK_X ) { + draw_2d_arrow(radius, false, 0); + draw_2d_arrow(radius, false, 2); + draw_2d_arrow(radius, true, 1); + draw_2d_arrow(radius, true, 3); + } + else if ( locked == GLUI_TRANSLATION_LOCK_Y ) { + draw_2d_arrow(radius, false, 1); + draw_2d_arrow(radius, false, 3); + draw_2d_arrow(radius, true, 0); + draw_2d_arrow(radius, true, 2); + } + else { + draw_2d_arrow(radius, true, 0); + draw_2d_arrow(radius, true, 1); + draw_2d_arrow(radius, true, 2); + draw_2d_arrow(radius, true, 3); + } + } + else { + draw_2d_arrow(radius, false, 0); + draw_2d_arrow(radius, false, 1); + draw_2d_arrow(radius, false, 2); + draw_2d_arrow(radius, false, 3); + } + + return; +} + + +/*************************** GLUI_Translation::draw_2d_arrow() **************/ +/* ori: 0=up, 1=left, 2=down, 3=right */ +/* */ +/* */ +/* 0, y2 */ +/* / \ */ +/* / \ */ +/* / \ */ +/* / \ */ +/* / \ */ +/* / \ */ +/* / \ */ +/* / \ */ +/* -x2,y1 -x1b,y1 x1b,y1 x2,y1 */ +/* | | */ +/* | | */ +/* | | */ +/* | | */ +/* | | */ +/* -x1a,y0 x1a,y0 */ +/* */ + + +void GLUI_Translation::draw_2d_arrow( int radius, int filled, int orientation ) +{ + float x1 = .2, x2 = .4, y1 = .54, y2 = .94, y0; + float x1a, x1b; +/* + vec3 col1( 0.0, 0.0, 0.0 ), col2( .45, .45, .45 ), + col3( .7, .7, .7 ), col4( 1.0, 1.0, 1.0 ); + vec3 c1, c2, c3, c4, c5, c6; +*/ + vec3 white(1.0,1.0,1.0), black(0.0,0.0,0.0), gray(.45,.45,.45), + bkgd(.7,.7,.7); + int c_off=0; /* color index offset */ + + if ( glui ) + bkgd.set(glui->bkgd_color_f[0], + glui->bkgd_color_f[1], + glui->bkgd_color_f[2]); + + /* bkgd[0] = 255.0; bkgd[1] = 0; */ + + /** The following 8 colors define the shading of an octagon, in + clockwise order, starting from the upstroke on the left **/ + /** This is for an outside and inside octagons **/ + vec3 colors_out[]={white, white, white, gray, black, black, black, gray}; + vec3 colors_in[] ={bkgd,white,bkgd,gray,gray,gray,gray,gray}; + +#define SET_COL_OUT(i) glColor3fv((float*) &colors_out[(i)%8][0]); +#define SET_COL_IN(i) glColor3fv((float*) &colors_in[(i)%8][0]); + + x1 = (float)radius * .2; + x2 = x1 * 2; + y1 = (float)radius * .54; + y2 = y1 + x2; + x1a = x1; + x1b = x1; + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + +#define DRAW_SEG( xa,ya,xb,yb ) glVertex2f(xa,ya); glVertex2f(xb,yb); + + glScalef( -1.0, 1.0, 1.0 ); + + if ( orientation == 2 ) { + c_off = 4; + } + else if ( orientation == 0 ) { + c_off = 0; + glRotatef( 180.0, 0.0, 0.0, 1.0 ); + } + else if ( orientation == 1 ) { + c_off = 2; + glRotatef( 90.0, 0.0, 0.0, 1.0 ); + } + else if ( orientation == 3 ) { + c_off = 6; + glRotatef( -90.0, 0.0, 0.0, 1.0 ); + } + + if ( trans_type == GLUI_TRANSLATION_Z ) + y0 = 0.0; + else if ( trans_type == GLUI_TRANSLATION_XY ) + y0 = x1; + else + y0 = 0.0; + + + if ( trans_type == GLUI_TRANSLATION_Z ) { + if ( orientation == 0 ) { + y1 += 2.0; + y2 += 0.0; + + x1b -= 2.0; + x2 -= 2.0; + x1a += 2.0; + } + else if ( orientation == 2 ) { + y1 -= 6.0; + x1a += 2.0; + x1b += 4.0; + x2 += 6.0; + } + } + + /*** Fill in inside of arrow ***/ + if ( NOT filled ) { /*** Means button is up - control is not clicked ***/ + /*glColor3f( .8, .8, .8 ); */ + set_to_bkgd_color(); + glColor3f( bkgd[0]+.07, bkgd[1]+.07, bkgd[2]+.07 ); + } + else { /*** Button is down on control ***/ + glColor3f( .6, .6, .6 ); + c_off += 4; /* Indents the shadows - goes from a raised look to embossed */ + } + + /*** Check if control is enabled or not ***/ + if ( NOT enabled ) { + set_to_bkgd_color(); + /*c_off += 4; -- Indents the shadows - goes from a raised look to embossed */ + colors_out[0] = colors_out[1] = colors_out[2] = colors_out[7] = gray; + colors_out[3] = colors_out[4] = colors_out[5] = colors_out[6] = white; + colors_in[0] = colors_in[1] = colors_in[2] = colors_in[7] = white; + colors_in[3] = colors_in[4] = colors_in[5] = colors_in[6] = gray; + + } + + glBegin( GL_POLYGON ); + glVertex2f( 0.0, 0.0 ); glVertex2f( -x1a, 0.0 ); + glVertex2f( -x1a, 0.0 ); glVertex2f( -x1b, y1 ); + glVertex2f( x1b, y1); glVertex2f( x1a, 0.0 ); + glVertex2f( x1a, 0.0 ); glVertex2f( 0.0, 0.0 ); + glEnd(); + glBegin( GL_TRIANGLES ); + glVertex2f( -x2, y1 ); glVertex2f( 0.0, y2 ); glVertex2f( x2, y1 ); + glEnd(); + + glLineWidth( 1.0 ); + /*** Draw arrow outline ***/ + glBegin( GL_LINES ); + + SET_COL_IN(1+c_off); DRAW_SEG( 0.0, y2-1.0, -x2, y1-1.0 ); + SET_COL_IN(6+c_off); DRAW_SEG( -x2+2.0, y1+1.0, -x1b+1.0, y1+1.0 ); + SET_COL_IN(0+c_off); DRAW_SEG( -x1b+1.0, y1+1.0, -x1a+1.0, y0 ); + SET_COL_IN(3+c_off); DRAW_SEG( 0.0, y2-1.0, x2, y1-1.0 ); + SET_COL_IN(6+c_off); DRAW_SEG( x2-1.0, y1+1.0, x1b-1.0, y1+1.0 ); + SET_COL_IN(4+c_off); DRAW_SEG( x1b-1.0, y1+1.0, x1a-1.0, y0 ); + + SET_COL_OUT(0+c_off); DRAW_SEG( -x1a, y0, -x1b, y1 ); + SET_COL_OUT(6+c_off); DRAW_SEG( -x1b, y1, -x2, y1 ); + SET_COL_OUT(1+c_off); DRAW_SEG( -x2, y1, 0.0, y2 ); + SET_COL_OUT(3+c_off); DRAW_SEG( 0.0, y2, x2, y1 ); + SET_COL_OUT(6+c_off); DRAW_SEG( x2, y1, x1b, y1 ); + SET_COL_OUT(4+c_off); DRAW_SEG( x1b, y1, x1a, y0 ); + + glEnd(); + +#undef DRAW_SEG + + glPopMatrix(); +} + + +/*************************** GLUI_Translation::get_mouse_code() *************/ + +int GLUI_Translation::get_mouse_code( int x, int y ) +{ + if ( x == 0 AND y < 0 ) + return GLUI_TRANSLATION_MOUSE_DOWN; + else if ( x == 0 AND y > 0 ) + return GLUI_TRANSLATION_MOUSE_UP; + else if ( x > 0 AND y == 0 ) + return GLUI_TRANSLATION_MOUSE_LEFT; + else if ( x < 0 AND y == 0 ) + return GLUI_TRANSLATION_MOUSE_RIGHT; + else if ( x < 0 AND y < 0 ) + return GLUI_TRANSLATION_MOUSE_DOWN_LEFT; + else if ( x < 0 AND y > 0 ) + return GLUI_TRANSLATION_MOUSE_DOWN_RIGHT; + else if ( x > 0 AND y < 0 ) + return GLUI_TRANSLATION_MOUSE_UP_LEFT; + else if ( x > 0 AND y > 0 ) + return GLUI_TRANSLATION_MOUSE_UP_RIGHT; + + + return GLUI_TRANSLATION_MOUSE_NONE; +} + + +/*********************************** GLUI_Translation::set_x() ******/ + +void GLUI_Translation::set_x( float val ) +{ + set_one_val( val, 0 ); +} + + +/*********************************** GLUI_Translation::set_y() ******/ + +void GLUI_Translation::set_y( float val ) +{ + if ( trans_type == GLUI_TRANSLATION_XY ) + set_one_val( val, 1 ); + else + set_one_val( val, 0 ); +} + + +/*********************************** GLUI_Translation::set_z() ******/ + +void GLUI_Translation::set_z( float val ) +{ + set_one_val( val, 0 ); +} + + +/******************************* GLUI_Translation::set_one_val() ****/ + +void GLUI_Translation::set_one_val( float val, int index ) +{ + float *fp; + + float_array_val[index] = val; /* set value in array */ + + /*** The code below is like output_live, except it only operates on + a single member of the float array (given by 'index') instead of + outputting the entire array ****/ + + if ( ptr_val == NULL OR NOT live_inited ) + return; + + fp = (float*) ptr_val; + fp[index] = float_array_val[index]; + last_live_float_array[index] = float_array_val[index]; + + /** Update the main gfx window? **/ + if ( this->glui != NULL ) { + this->glui->post_update_main_gfx(); + } +} diff --git a/Extras/glui/glui_tree.cpp b/Extras/glui/glui_tree.cpp new file mode 100644 index 0000000..f253fa4 --- /dev/null +++ b/Extras/glui/glui_tree.cpp @@ -0,0 +1,278 @@ +/**************************************************************************** + + GLUI User Interface Toolkit + --------------------------- + + glui_panel.cpp - GLUI_Panel control class + + + -------------------------------------------------- + + Copyright (c) 1998 Paul Rademacher + + This program is freely distributable without licensing fees and is + provided without guarantee or warrantee expressed or implied. This + program is -not- in the public domain. + +*****************************************************************************/ + +#include "glui_internal_control.h" + + +/****************************** GLUI_Tree::GLUI_Tree() **********/ +GLUI_Tree::GLUI_Tree(GLUI_Node *parent, const char *name, + int open, int inset) +{ + common_init(); + GLUI_StaticText *inset_label; + GLUI_Column *col; + + this->set_name( name ); + this->user_id = -1; + + if ( NOT open ) { + this->is_open = false; + this->h = GLUI_DEFAULT_CONTROL_HEIGHT + 7; + } + + parent->add_control( this ); + inset_label = new GLUI_StaticText(this,""); + inset_label->set_w(inset); + col = new GLUI_Column(this,true); + this->set_column(col); + this->set_alignment(GLUI_ALIGN_LEFT); +} + + +/****************************** GLUI_Tree::open() **********/ + +void GLUI_Tree::open( void ) +{ + if ( is_open ) + return; + is_open = true; + + GLUI_DRAWINGSENTINAL_IDIOM + + child_head = collapsed_node.child_head; + child_tail = collapsed_node.child_tail; + + collapsed_node.child_head = NULL; + collapsed_node.child_tail = NULL; + + if ( child_head != NULL ) { + ((GLUI_Control*) child_head)->unhide_internal( true ); + } + + glui->refresh(); +} + + +/****************************** GLUI_Tree::close() **********/ + +void GLUI_Tree::close( void ) +{ + if ( NOT glui ) + return; + + if ( NOT is_open ) + return; + is_open = false; + + GLUI_DRAWINGSENTINAL_IDIOM + + if ( child_head != NULL ) { + ((GLUI_Control*) child_head)->hide_internal( true ); + } + + collapsed_node.child_head = first_child(); + collapsed_node.child_tail = last_child(); + + child_head = NULL; + child_tail = NULL; + + this->h = GLUI_DEFAULT_CONTROL_HEIGHT + 7; + + glui->refresh(); +} + + +/**************************** GLUI_Tree::mouse_down_handler() **********/ + + +int GLUI_Tree::mouse_down_handler( int local_x, int local_y ) +{ + if ( local_y - y_abs > 18 ) { + initially_inside = currently_inside = false; + return false; + } + + currently_inside = true; + initially_inside = true; + redraw(); + + return false; +} + +/**************************** GLUI_Tree::mouse_held_down_handler() ****/ + +int GLUI_Tree::mouse_held_down_handler( + int local_x, int local_y, + bool new_inside ) +{ + if ( NOT initially_inside ) + return false; + + if ( local_y - y_abs> 18 ) + new_inside = false; + + if (currently_inside != new_inside) + redraw(); + + return false; +} + + +/**************************** GLUI_Tree::mouse_down_handler() **********/ + +int GLUI_Tree::mouse_up_handler( int local_x, int local_y, bool inside ) +{ + if ( currently_inside ) { + if ( is_open ) + close(); + else + open(); + } + + currently_inside = false; + initially_inside = false; + redraw(); + + return false; +} + + +/********************************* GLUI_Tree::draw() ***********/ + +void GLUI_Tree::draw( int x, int y ) +{ + GLUI_DRAWINGSENTINAL_IDIOM + int left, right, top, bottom, delta_x; + + left = 5; + right = w-left; + top = 3; + bottom = 3+16; + delta_x = 0; + + glui->draw_raised_box( left, top, 16, 16 ); + + if ( glui ) + glColor3ub(glui->bkgd_color.r,glui->bkgd_color.g,glui->bkgd_color.b); + glDisable( GL_CULL_FACE ); + glBegin( GL_QUADS ); + glVertex2i( left+17, top+1 ); glVertex2i( right-1, top+1 ); + glVertex2i( right-1, bottom-1 ); glVertex2i( left+17, bottom-1 ); + glEnd(); + + if (format & GLUI_TREEPANEL_DISPLAY_HIERARCHY) { + delta_x = string_width( level_name ) + char_width(' '); + glColor3f( lred, lgreen, lblue); /* The hierarchy is drawn in bold */ + glRasterPos2i(left + 25, top + 11); + draw_string(level_name); + glRasterPos2i(left + 24, top + 11); + draw_string(level_name); + } + + draw_name( delta_x+left+24, top+11 ); + + if ( active ) + draw_active_box( left+22, delta_x+left+string_width( name )+32, + top, bottom-2 ); + + + /** Draw '+' or '-' **/ + + glBegin( GL_LINES ); + if ( is_open ) { + if ( enabled ) + if (is_current) + glColor3f( 0, 0, 1 ); + else + glColor3f( 0.0, 0.0, 0.0 ); + else + glColor3f( 0.5, 0.5, 0.5 ); + glVertex2i(left+4,(top+bottom)/2); glVertex2i(left+13,(top+bottom)/2); + + glColor3f( 1.0, 1.0, 1.0 ); + glVertex2i(left+4,1+(top+bottom)/2);glVertex2i(left+13,1+(top+bottom)/2); + } + else + { + glColor3f( 1.0, 1.0, 1.0 ); + glVertex2i(left+9,top+3); glVertex2i(left+9,bottom-4); + glVertex2i(left+4,(top+bottom)/2); glVertex2i(left+13,(top+bottom)/2); + + if ( enabled ) + if (is_current) + glColor3f( 0, 0, 1 ); + else + glColor3f( 0.0, 0.0, 0.0 ); + else + glColor3f( 0.5, 0.5, 0.5 ); + glVertex2i(left+4,-1+(top+bottom)/2); + glVertex2i(left+13,-1+(top+bottom)/2); + glVertex2i(left+8,top+3); + glVertex2i(left+8,bottom-4); + } + glEnd(); + + glLineWidth( 1.0 ); + + if (currently_inside) draw_pressed(); +} + + +/***************************** GLUI_Tree::update_size() **********/ + +void GLUI_Tree::update_size( void ) +{ + int text_size = 0, delta_x = 0; + + if ( NOT glui ) + return; + + text_size = string_width(name); + + if (format & GLUI_TREEPANEL_DISPLAY_HIERARCHY) { + delta_x = string_width( level_name ); + } + + if ( w < text_size + 36 + delta_x) + w = text_size + 36 + delta_x; +} + + +/**************************** GLUI_Tree::draw_pressed() ***********/ + +void GLUI_Tree::draw_pressed( void ) +{ + int left, right, top, bottom; + + left = 5; + right = w-left; + top = 3; + bottom = 3+16; + + glColor3f( 0.0, 0.0, 0.0 ); + + glBegin( GL_LINE_LOOP ); + glVertex2i( left, top ); glVertex2i( right, top ); + glVertex2i( right, bottom ); glVertex2i( left,bottom ); + glEnd(); + + glBegin( GL_LINE_LOOP ); + glVertex2i( left+1, top+1 ); glVertex2i( right-1, top+1 ); + glVertex2i( right-1, bottom-1 ); glVertex2i( left+1,bottom-1 ); + glEnd(); +} diff --git a/Extras/glui/glui_treepanel.cpp b/Extras/glui/glui_treepanel.cpp new file mode 100644 index 0000000..27c659c --- /dev/null +++ b/Extras/glui/glui_treepanel.cpp @@ -0,0 +1,388 @@ +#include "GL/glui.h" + + +/****************************** GLUI_TreePanel::GLUI_TreePanel() *********/ + +GLUI_TreePanel::GLUI_TreePanel(GLUI_Node *parent, const char *name, + bool open, int inset) +{ + common_init(); + + set_name( name ); + user_id = -1; + + if ( !open ) { + is_open = false; + h = GLUI_DEFAULT_CONTROL_HEIGHT + 7; + } + + parent->add_control( this ); +} + +/****************************** GLUI_TreePanel::set_color() *********/ + +void GLUI_TreePanel::set_color(float r, float g, float b) +{ + red = r; + green = g; + blue = b; + redraw(); +} + +/************************ GLUI_TreePanel::set_level_color() *********/ + +void GLUI_TreePanel::set_level_color(float r, float g, float b) +{ + lred = r; + lgreen = g; + lblue = b; + redraw(); +} + +/****************************** GLUI_TreePanel::ab() *********/ + +/* Adds branch to curr_root */ +GLUI_Tree *GLUI_TreePanel::ab(const char *name, GLUI_Tree *root) +{ + GLUI_Tree *temp; + + + if (root != NULL) { + resetToRoot(root); + } + + temp = new GLUI_Tree(curr_root, name); + initNode(temp); + formatNode(temp); + + curr_root = temp; + curr_branch = NULL; /* Currently at leaf */ + + if (temp->dynamicCastGLUI_Tree()) + ((GLUI_Tree *)temp)->set_current(true); + //refresh(); + // glui->deactivate_current_control(); + //glui->activate_control( temp, GLUI_ACTIVATE_TAB ); + return temp; + +} + +/****************************** GLUI_TreePanel::fb() *********/ + +/* Goes up one level, resets curr_root and curr_branch to parents*/ +void GLUI_TreePanel::fb(GLUI_Tree *branch) +{ + if (((GLUI_Panel *)branch) == ((GLUI_Panel *)this)) + return; + + if (((GLUI_Panel *)curr_branch) == ((GLUI_Panel *)this)) { + resetToRoot(); + return; + } + if (((GLUI_Panel *)curr_root) == ((GLUI_Panel *)this)) { + resetToRoot(); + return; + } + + if (branch != NULL) { + + if ( branch->dynamicCastGLUI_Tree() ) + ((GLUI_Tree *)branch)->set_current(false); + + curr_branch = (GLUI_Tree *)branch->next(); + curr_root = (GLUI_Panel *)branch->parent(); + + if (curr_branch == NULL && (curr_root->collapsed_node).first_child() != NULL) + curr_branch = (GLUI_Tree *)(curr_root->collapsed_node).first_child(); + + + if ( curr_root->dynamicCastGLUI_Tree() ) + ((GLUI_Tree *)curr_root)->set_current(true); + + } else { + if (curr_root != NULL) { /* up one parent */ + + if (curr_root->dynamicCastGLUI_Tree()) + ((GLUI_Tree *)curr_root)->set_current(false); + + curr_branch = (GLUI_Tree *) curr_root->next(); + curr_root = (GLUI_Panel *) curr_root->parent(); + + if (curr_branch == NULL && (curr_root->collapsed_node).first_child() != NULL) + curr_branch = (GLUI_Tree *)(curr_root->collapsed_node).first_child(); + + if (curr_root->dynamicCastGLUI_Tree()) + ((GLUI_Tree *)curr_root)->set_current(true); + + } + + } + //refresh(); +} + + +/****************************** GLUI_TreePanel::refresh() *********/ + +void GLUI_TreePanel::refresh() +{ + glui->deactivate_current_control(); + glui->activate_control( curr_root, GLUI_ACTIVATE_TAB ); + + redraw(); +} + +/****************************** GLUI_TreePanel::initNode() *********/ + +void GLUI_TreePanel::initNode(GLUI_Tree *temp) +{ + if (temp == NULL) + return; + int level = temp->get_level(); + int child_number = 1; + + GLUI_Tree *ptree = temp->parent()->dynamicCastGLUI_Tree(); + if (ptree) { + level = ptree->get_level() + 1; + GLUI_Tree *prevTree = temp->prev()->dynamicCastGLUI_Tree(); + if (prevTree) { + child_number = prevTree->get_child_number() + 1; + } + } else if (temp->dynamicCastGLUI_Tree() && + temp->parent()->dynamicCastGLUI_TreePanel()) { + child_number = ++root_children; + } + temp->set_id(uniqueID()); // -1 if unset + temp->set_level(level); + temp->set_child_number(child_number); +} + +/****************************** GLUI_TreePanel::formatNode() *********/ + +void GLUI_TreePanel::formatNode(GLUI_Tree *temp) +{ + if (temp == NULL) + return; + int level = temp->get_level(); + int child_number = temp->get_child_number(); + GLUI_String level_name=""; + GLUI_String full_name=""; + + temp->level_name == ""; + + if (format & GLUI_TREEPANEL_DISPLAY_HIERARCHY) { + if (format & GLUI_TREEPANEL_HIERARCHY_LEVEL_ONLY) { + glui_format_str(level_name, "%d", level); + } + if (format & GLUI_TREEPANEL_HIERARCHY_NUMERICDOT) { + if ( temp->parent()->dynamicCastGLUI_Tree() ) + glui_format_str(level_name, "%s.%d", + ((GLUI_Tree *)(temp->parent()))->level_name.c_str(), + child_number); + else + glui_format_str(level_name, "%d", child_number); + } + } + + temp->set_level_color(lred, lgreen, lblue); + temp->set_format(format); + temp->level_name = level_name; + + if (format & GLUI_TREEPANEL_ALTERNATE_COLOR) { + switch (level%8) { + case (7): temp->set_color(.5,.5,.5); break; + case (6): temp->set_color(.3,.5,.5); break; + case (5): temp->set_color(.5,.3,.5); break; + case (4): temp->set_color(.3,.3,.5); break; + case (3): temp->set_color(.5,.5,.3); break; + case (2): temp->set_color(.3,.5,.3); break; + case (1): temp->set_color(.5,.3,.3); break; + default: temp->set_color(.3,.3,.3); + } + } else { + temp->set_color(red,green,blue); + } + + if (format & GLUI_TREEPANEL_DISABLE_BAR) { + temp->disable_bar(); + } else { + if (format & GLUI_TREEPANEL_DISABLE_DEEPEST_BAR) { + temp->disable_bar(); + if ( curr_root->dynamicCastGLUI_Tree() ) + ((GLUI_Tree *)curr_root)->enable_bar(); + } else + if (format & GLUI_TREEPANEL_CONNECT_CHILDREN_ONLY) { + temp->disable_bar(); + if (temp->prev() && temp->prev()->dynamicCastGLUI_Tree() ) + { + ((GLUI_Tree *)temp->prev())->enable_bar(); + } + } + } +} + +/****************************** GLUI_TreePanel::update_all() *********/ + +void GLUI_TreePanel::update_all() +{ + printf("GLUI_TreePanel::update_all() doesn't work yet. - JVK\n"); + return; + GLUI_Panel *saved_root = curr_root; + GLUI_Tree *saved_branch = curr_branch; + root_children = 0; + resetToRoot(this); + if (curr_branch && curr_branch->dynamicCastGLUI_Tree()) + formatNode((GLUI_Tree *)curr_branch); + next(); + while (curr_root && curr_branch != this->first_child()) { + if (curr_branch && curr_branch->dynamicCastGLUI_Tree()) { + formatNode((GLUI_Tree *)curr_branch); + } + next(); + } + curr_root = saved_root; + curr_branch = saved_branch; +} + +/****************************** GLUI_TreePanel::expand_all() *********/ + +void GLUI_TreePanel::expand_all() +{ + GLUI_Panel *saved_root = curr_root; + GLUI_Tree *saved_branch = curr_branch; + + resetToRoot(this); + if (curr_root->dynamicCastGLUI_Tree()) + ((GLUI_Tree*)curr_root)->open(); + next(); + while (curr_root != NULL && curr_branch != this->first_child()) { + if (curr_root->dynamicCastGLUI_Tree()) + ((GLUI_Tree*)curr_root)->open(); + next(); + } + + curr_root = saved_root; + curr_branch = saved_branch; +} + +/****************************** GLUI_TreePanel::collapse_all() *********/ + +void GLUI_TreePanel::collapse_all() +{ + GLUI_Panel *saved_root = curr_root; + GLUI_Tree *saved_branch = curr_branch; + + resetToRoot(this); + next(); + while (curr_root != NULL && curr_branch != this->first_child()) { + if (curr_root->dynamicCastGLUI_Tree() && + curr_branch == NULL) { /* we want to close everything leaf-first */ + ((GLUI_Tree*)curr_root)->close(); + /* Rather than simply next(), we need to manually move the + curr_root because this node has been moved to the + collapsed_node list */ + curr_branch = (GLUI_Tree *)curr_root->next(); + curr_root = (GLUI_Panel *)curr_root->parent(); + } else + next(); + } + + curr_root = saved_root; + curr_branch = saved_branch; + +} + +/****************************** GLUI_TreePanel::db() *********/ + +/* Deletes the curr_root */ +void GLUI_TreePanel::db(GLUI_Tree *root) +{ + GLUI_Tree *temp_branch; + GLUI_Panel *temp_root; + + if (((GLUI_Control *)root) == ((GLUI_Control *)this)) + return; + + if (root != NULL) { + curr_root = (GLUI_Tree *)root; + curr_branch = NULL; + } + + if (curr_root == NULL || ((GLUI_Panel *)curr_root) == ((GLUI_Panel *)this)) { + resetToRoot(); + return; + } + + + temp_branch = (GLUI_Tree *)curr_root->next(); /* Next branch, if any */ + temp_root = (GLUI_Panel *)curr_root->parent(); /* new root */ + curr_root->unlink(); + delete curr_root; + curr_branch = (GLUI_Tree *) temp_branch; + curr_root = (GLUI_Panel *) temp_root; + if (curr_root->dynamicCastGLUI_Tree()) + ((GLUI_Tree *)curr_root)->open(); + + if ((format & GLUI_TREEPANEL_DISABLE_DEEPEST_BAR) == GLUI_TREEPANEL_DISABLE_DEEPEST_BAR) { + if (curr_root->dynamicCastGLUI_Tree() && ((GLUI_Tree *)curr_root->next()) == NULL) + ((GLUI_Tree *)curr_root)->disable_bar(); + } + //refresh(); +} + +/****************************** GLUI_TreePanel::descendBranch() *********/ + +/* Finds the very last branch of curr_root, resets vars */ +void GLUI_TreePanel::descendBranch(GLUI_Panel *root) { + if (root) + resetToRoot(root); + else + resetToRoot(curr_root); + if (curr_branch != NULL && curr_branch != ((GLUI_Panel *)this)) { + if (curr_root->dynamicCastGLUI_Tree()) + ((GLUI_Tree *)curr_root)->set_current(false); + descendBranch(curr_branch); + } +} + +/****************************** GLUI_TreePanel::next() *********/ + +void GLUI_TreePanel::next() +{ + if (curr_root == NULL) + resetToRoot(this); + + if (curr_branch == NULL && (curr_root->collapsed_node).first_child() != NULL) + curr_branch = (GLUI_Tree *)(curr_root->collapsed_node).first_child(); + + + if (curr_branch != NULL && curr_branch != ((GLUI_Panel *)this)) { /* Descend into branch */ + if (curr_root->dynamicCastGLUI_Tree()) + ((GLUI_Tree *)curr_root)->set_current(false); + resetToRoot(curr_branch); + } else if (curr_branch == NULL) { + fb(NULL); /* Backup and move on */ + } +} + +/****************************** GLUI_TreePanel::resetToRoot() *********/ + +/* Resets curr_root and curr branch to TreePanel and lastChild */ +void GLUI_TreePanel::resetToRoot(GLUI_Panel *new_root) +{ + GLUI_Panel *root = this; + if (new_root != NULL) + root = new_root; + curr_root = root; + if (curr_root->dynamicCastGLUI_Tree()) + ((GLUI_Tree *)curr_root)->set_current(true); + curr_branch = (GLUI_Tree *)root->first_child(); + + /* since Trees are collapsable, we need to check the collapsed nodes + in case the curr_root is collapsed */ + if (curr_branch == NULL && (root->collapsed_node).first_child() != NULL) { + curr_branch = (GLUI_Tree *)(root->collapsed_node).first_child(); + } + while (curr_branch && curr_branch->dynamicCastGLUI_Tree()) { + curr_branch=(GLUI_Tree *)curr_branch->next(); + } +} diff --git a/Extras/glui/glui_window.cpp b/Extras/glui/glui_window.cpp new file mode 100644 index 0000000..02c2d0d --- /dev/null +++ b/Extras/glui/glui_window.cpp @@ -0,0 +1,44 @@ +/* + + glui_window.cpp - GLUI_Button control class + + GLUI User Interface Toolkit (LGPL) + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "GL/glui.h" +#include "glui_internal.h" + +GLUI_Glut_Window::GLUI_Glut_Window() +: GLUI_Node(), + + glut_window_id(0), + glut_keyboard_CB(NULL), + glut_special_CB(NULL), + glut_reshape_CB(NULL), + glut_passive_motion_CB(NULL), + glut_mouse_CB(NULL), + glut_visibility_CB(NULL), + glut_motion_CB(NULL), + glut_display_CB(NULL), + glut_entry_CB(NULL) +{ +} diff --git a/Extras/glui/quaternion.cpp b/Extras/glui/quaternion.cpp new file mode 100644 index 0000000..d73523e --- /dev/null +++ b/Extras/glui/quaternion.cpp @@ -0,0 +1,243 @@ +/*********************************************************************** + + quaternion.cpp - A quaternion class + + ------------------------------------------------------------------- + + GLUI User Interface Toolkit (LGPL) + Copyright (c) 1998 Paul Rademacher + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +************************************************************************ + + Feb 1998, Paul Rademacher (rademach@cs.unc.edu) + Oct 2003, Nigel Stewart - GLUI Code Cleaning + +************************************************************************/ +#include "glui_internal_control.h" +#include "quaternion.h" +#include +#include "glui_internal.h" + +/******************************************* constructors **************/ + +quat::quat() +{ + *this = quat_identity(); +} + +quat::quat(const float x, const float y, const float z, const float w) +{ + v.set( x, y, z ); + s = w; +} + +quat::quat(const vec3 &_v, const float _s) +{ + set( _v, _s ); +} + +quat::quat(const float _s, const vec3 &_v) +{ + set( _v, _s ); +} + +quat::quat(const float *d) +{ + v[0] = d[0]; + v[1] = d[1]; + v[2] = d[2]; + s = d[3]; +} + +quat::quat(const double *d) +{ + v[0] = (float) d[0]; + v[1] = (float) d[1]; + v[2] = (float) d[2]; + s = (float) d[3]; +} + +quat::quat(const quat &q) +{ + v = q.v; + s = q.s; +} + +void quat::set(const vec3 &_v, const float _s) +{ + v = _v; + s = _s; +} + +quat &quat::operator=(const quat &q) +{ + v = q.v; + s = q.s; + return *this; +} + +/******** quat friends ************/ + +quat operator + (const quat &a, const quat &b) +{ + return quat( a.s+b.s, a.v+b.v ); +} + +quat operator - (const quat &a, const quat &b) +{ + return quat( a.s-b.s, a.v-b.v ); +} + +quat operator - (const quat &a ) +{ + return quat( -a.s, -a.v ); +} + +quat operator * ( const quat &a, const quat &b) +{ + return quat( a.s*b.s - a.v*b.v, a.s*b.v + b.s*a.v + a.v^b.v ); +} + +quat operator * ( const quat &a, const float t) +{ + return quat( a.v * t, a.s * t ); +} + +quat operator * ( const float t, const quat &a ) +{ + return quat( a.v * t, a.s * t ); +} + +mat4 quat::to_mat4() const +{ + float xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz; + + float t = 2.0f / (v*v + s*s); + + xs = v[VX]*t; ys = v[VY]*t; zs = v[VZ]*t; + wx = s*xs; wy = s*ys; wz = s*zs; + xx = v[VX]*xs; xy = v[VX]*ys; xz = v[VX]*zs; + yy = v[VY]*ys; yz = v[VY]*zs; zz = v[VZ]*zs; + + mat4 matrix( + 1.0f-(yy+zz), xy+wz, xz-wy, 0.0f, + xy-wz, 1.0f-(xx+zz), yz+wx, 0.0f, + xz+wy, yz-wx, 1.0f-(xx+yy), 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f ); + + return matrix; +} + +/************************************************* quat_identity() *****/ +/* Returns quaternion identity element */ + +quat quat_identity() +{ + return quat( vec3( 0.0, 0.0, 0.0 ), 1.0 ); +} + +/************************************************ quat_slerp() ********/ +/* Quaternion spherical interpolation */ + +quat quat_slerp(const quat &from, const quat &to, float t) +{ + quat to1; + float omega, cosom, sinom, scale0, scale1; + + /* calculate cosine */ + cosom = from.v * to.v + from.s + to.s; + + /* Adjust signs (if necessary) */ + if ( cosom < 0.0 ) + { + cosom = -cosom; + to1 = -to; + } + else + { + to1 = to; + } + + /* Calculate coefficients */ + if ((1.0 - cosom) > FUDGE ) + { + /* standard case (slerp) */ + omega = (float) acos( cosom ); + sinom = (float) sin( omega ); + scale0 = (float) sin((1.0 - t) * omega) / sinom; + scale1 = (float) sin(t * omega) / sinom; + } + else + { + /* 'from' and 'to' are very close - just do linear interpolation */ + scale0 = 1.0f - t; + scale1 = t; + } + + return scale0 * from + scale1 * to1; +} + +/********************************************** set_angle() ************/ +/* set rot angle (degrees) */ + +void quat::set_angle(float f) +{ + vec3 axis = get_axis(); + + s = (float) cos( DEG2RAD( f ) / 2.0 ); + + v = axis * (float) sin(DEG2RAD(f) / 2.0); +} + +/********************************************** scale_angle() ************/ +/* scale rot angle (degrees) */ + +void quat::scale_angle(float f) +{ + set_angle( f * get_angle() ); +} + +/********************************************** get_angle() ************/ +/* get rot angle (degrees). Assumes s is between -1 and 1 */ + +float quat::get_angle() const +{ + return (float) RAD2DEG( 2.0 * acos( s ) ); +} + +/********************************************* get_axis() **************/ + +vec3 quat::get_axis() const +{ + float scale = (float) sin( acos( s ) ); + + if ( scale < FUDGE AND scale > -FUDGE ) + return vec3( 0.0, 0.0, 0.0 ); + else + return v / scale; +} + +/******************************************* quat::print() ************/ + +void quat::print(FILE *dest, const char *name) const +{ + fprintf( dest, "%s: v:<%3.2f %3.2f %3.2f> s:%3.2f\n", + name, v[0], v[1], v[2], s ); +} diff --git a/Extras/glui/quaternion.h b/Extras/glui/quaternion.h new file mode 100644 index 0000000..f58a744 --- /dev/null +++ b/Extras/glui/quaternion.h @@ -0,0 +1,114 @@ +/**************************************************************************** + + quaternion.h - A quaternion class + + GLUI User Interface Toolkit (LGPL) + Copyright (c) 1998 Paul Rademacher + + --------------------------------------------------------------------- + + WWW: http://sourceforge.net/projects/glui/ + Forums: http://sourceforge.net/forum/?group_id=92496 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +#ifndef GLUI_QUATERNION_H +#define GLUI_QUATERNION_H + +#include "algebra3.h" +#include + +/* this line defines a new type: pointer to a function which returns a */ +/* float and takes as argument a float */ +typedef float (*V_FCT_PTR)(float); + +/**************************************************************** + * Quaternion * + ****************************************************************/ + +class quat +{ + /*protected: */ +public: + + vec3 v; /* vector component */ + float s; /* scalar component */ + + /*public: */ + + /* Constructors */ + + quat(); + quat(float x, float y, float z, float w); + quat(const vec3 &v, float s); + quat(float s, const vec3 &v); + quat(const float *d); /* copy from four-element float array */ + quat(const double *f); /* copy from four-element double array */ + quat(const quat &q); /* copy from other quat */ + + /* Assignment operators */ + + quat &operator = (const quat &v); /* assignment of a quat */ + quat &operator += (const quat &v); /* incrementation by a quat */ + quat &operator -= (const quat &v); /* decrementation by a quat */ + quat &operator *= (float d); /* multiplication by a constant */ + quat &operator /= (float d); /* division by a constant */ + + /* special functions */ + + float length() const; /* length of a quat */ + float length2() const; /* squared length of a quat */ + quat &normalize(); /* normalize a quat */ + quat &apply(V_FCT_PTR fct); /* apply a func. to each component */ + vec3 xform(const vec3 &v ); /* q*v*q-1 */ + mat4 to_mat4() const; + void set_angle(float f); /* set rot angle (degrees) */ + void scale_angle(float f); /* scale rot angle (degrees) */ + float get_angle() const; /* set rot angle (degrees) */ + vec3 get_axis() const; /* get axis */ + + void print( FILE *file, const char *name ) const; /* print to a file */ + + float &operator [] (int i); /* indexing */ + const float &operator [] (int i) const; /* indexing */ + + void set(float x, float y, float z); /* set quat */ + void set(const vec3 &v, float s); /* set quat */ + + /* friends */ + + friend quat operator - (const quat &v); /* -q1 */ + friend quat operator + (const quat &a, const quat &b); /* q1 + q2 */ + friend quat operator - (const quat &a, const quat &b); /* q1 - q2 */ + friend quat operator * (const quat &a, float d); /* q1 * 3.0 */ + friend quat operator * (float d, const quat &a); /* 3.0 * q1 */ + friend quat operator * (const quat &a, const quat &b); /* q1 * q2 */ + friend quat operator / (const quat &a, float d); /* q1 / 3.0 */ + friend int operator == (const quat &a, const quat &b); /* q1 == q2 ? */ + friend int operator != (const quat &a, const quat &b); /* q1 != q2 ? */ + friend void swap(quat &a, quat &b); /* swap q1 &q2 */ + /*friend quat min(const quat &a, const quat &b); -- min(q1, q2) */ + /*friend quat max(const quat &a, const quat &b); -- max(q1, q2) */ + friend quat prod(const quat &a, const quat &b); /* term by term mult*/ +}; + +/* Utility functions */ + +quat quat_identity(); /* Returns quaternion identity element */ +quat quat_slerp(const quat &from, const quat &to, float t); + +#endif diff --git a/Extras/glui/readme.txt b/Extras/glui/readme.txt new file mode 100644 index 0000000..4cda867 --- /dev/null +++ b/Extras/glui/readme.txt @@ -0,0 +1,228 @@ +Welcome to the GLUI User Interface Library, v2.3! +March 22, 2005 +------------------------------------------------- + +This distribution contains the latest community-maintained fork of the +GLUI Library. It is based on the GLUI v2.1 beta version from Paul +Rademacher (http://www.cs.unc.edu/~rademach/glui/) plus the +compatibility changes made by Nigel Stewart in his "GLUI v2.2" +(http://www.nigels.com/glt/glui) In accordance with the LGPL under +which the library is released (according to Paul's web page at least), +these changes are available to everyone in the community. + +WARNING: This version (2.3) introduces some incompatible changes with +previous versions!! + +CHANGES: + +---------------------------------- +- GLUI_String is now a std::string + This is the main source of most incopatibilities, but I felt it was + a necessary change, because the previous usage of a fixed-sized + buffer was just too unsafe. I myself was bitten a few times passing + a char* buffer of insufficient size into GLUI as a live variable. + It is still possible to use a char buffer, but it is not recommended. + + If you used GLUI_String before as a live var type, the easiest way + to get your code compiling again is to change those to "char + buf[300]". The better way, though, is to update your code to treat + it as a std::string. + + For instance, if you used to pass mystr to functions that take + 'const char*', now use mystr.c_str() method, instead. + If you used strcpy(mystr, b) to set the value, now just do mystr=b. + If you used sprintf(mystr,...) to set the value, now do + glui_format_string(mystr,...). + If you used to clear the string with mystr[0]='\0', now just clear + it with mystr="". + +---------------------------------- +- Enhanced GLUI_EditText + Control keys can be used for navigation and control. The bindings + are bash-like: Ctrl-B for previous char, Ctrl-F for forward char, etc. + bindings. Also control keys that aren't bound to commands are + simply ignored, whereas before they would be inserted as invisible + characters. + +---------------------------------- +- Added GLUI_CommandLine class + This is a GLUI_EditText with a history mechanism. + +---------------------------------- +- New, more object oriented construction API. + Now instead of calling + + glui->add_button_to_panel( panel, "my button", myid, mycallback ); + + you should just call the button constructor: + + new GLUI_Button( panel, "my button", myid, mycallback ); + + And similarly to add it to a GLUI instead of a panel, rather than: + + glui->add_button( glui, "my button", myid, mycallback ); + + just call the constructor with the GLUI as the first argument: + + new GLUI_Button( glui, "my button", myid, mycallback ); + + The old scheme is now deprecated, but still works. The benefit of + this new scheme is that now the GLUI class doesn't have to know + about all the different types of GLUI_Controls that exist. + Previously GLUI had to both know about all the controls, and know + how to initialize them. Now the responsibility for initialization + belongs to the GLUI_Control subclasses themselves, where it + belongs. Additionally it means that you can create your own + GLUI_Control subclasses which will be on equal footing with the + built-in controls, whereas before any user-created controls would + always be "second-class citizens" since they would have to be + constructed differently from the built-ins. + + +---------------------------------- +- Removed need for type-declaring arguments when argment type suffices. + This effects GLUI_Spinner and GLUI_EditText (and GLUI_CommandLine?). + + For example, instead of calling + + new GLUI_Spinner( glui, "myspin", GLUI_SPINNER_INT, &live_int_var ); + + you can just omit the GLUI_SPINNER_INT part, because the type of the + live_int_var tells the compiler which type you want. + + new GLUI_Spinner( glui, "myspin", &live_int_var ); + + If you're not using a live, var, you can still use the + GLUI_SPINNER_INT type argument. See glui.h for all the new + constructor signatures. Note this only works with the new + construction API, not with the old "add_blah_to_panel" style of + API. + +---------------------------------- +- GLUI_Rotation uses your matrix live-variable now. + GLUI used to ignore the matrix in your live variable. This version + doesn't ignore it, so you'll need to set it to the identity matrix + yourself if that's what you want it to start as. There could + probably be some improvements to this API, though. + +---------------------------------- +- Improvements to 'const' usage. + Most char*'s in GLUI functions used to be non-const even when the + functions did not modify the string. I changed everywhere + appropriate to use const char* instead. + +---------------------------------- +- Updated license info in the headers + Paul's web page says that GLUI is LGPL, but that wasn't declared in + the code itself. I've modified all the headers with the standard + LGPL notice. + +---------------------------------- +- Updated examples for the API changes + +---------------------------------- +- Created project files for Visual Studio .NET (MSVC7.1) + + +That's about it. Enjoy! + + +If you find yourself with too much time on your hands, the things I +think would be most useful for future improvements to GLUI would be: + +1. The GLUI_TextBox and GLUI_Tree definitely need some work, still. +2. Clipboard integration under Windows/X-Win. I have some code that + works on Win32 that I once integrated with GLUI, but I lost that + version somewhere. I still have the Win32 clipboard code, though + if anyone wants to work on integrating it. I have some X-Win + clipboard code, too, but I never got it working quite right. +3. Remove the dependency on GLUT, making the connection with window + system APIs into a more plug-in/adapter modular design. + So e.g. if you want to use GLUT, you'd link with the GLUI lib and a + GLUI_GLUT lib, and call one extra GLUI_glut_init() function or + something. + + +Definitly consider submitting a patch if you've made some nice improvements +to GLUI. Hopefully being an LGPL sourceforge project will attract some new +interest to the GLUI project. + +Bill Baxter +baxter +at +cs unc edu + +================================================= +JOHN KEW'S ADDITIONS (March 2005) +================================================= + +Thanks to John Kew of Natural Solutions Inc., +there are some new widgets. These are demonstrated in example6.cpp. + +The new widgets are: + +* GLUI_Scrollbar - A scrollbar slider widget +* GLUI_TextBox - A multi-line text widget +* GLUI_List - A static choice list +* GLUI_FileBrowser - A simple filebrowser based on GLUI_List +* GLUI_Tree - Hierarchical tree widget +* GLUI_TreePanel - Manager for the tree widget + +And one other change: + +* GLUI_Rollout has optional embossed border + +================================================= +PAUL'S ORIGINAL GLUI 2.0/2.1 README +================================================= + +Welcome to the GLUI User Interface Library, v2.0 beta! +------------------------------------------------- + +This distribution contains the full GLUI sources, as well as 5 example +programs. You'll find the full manual under "glui_manual.pdf". The +GLUI web page is at + + http://www.cs.unc.edu/~rademach/glui + + + ---------- Windows ---------- + +The directory 'msvc' contains a Visual C++ workspace entitled +'glui.dsw'. To recompile the library and examples, open this +workspace and run the menu command "Build:Batch Build:Build". The 3 +executables will be in the 'bin' directory, and the library in the +'lib' directory. + +To create a new Windows executable using GLUI, create a "Win32 Console +Application" in VC++, add the GLUI library (in 'msvc/lib/glui32.lib'), +and add the OpenGL libs: + + glui32.lib glut32.lib glu32.lib opengl32.lib (Microsoft OpenGL) + +Include the file "glui.h" in any file that uses the GLUI library. + + + ---------- Unix ---------- + +An SGI/HP makefile is found in the file 'makefile' (certain lines may need +to be commented/uncommented). + +To include GLUI in your own apps, add the glui library to your +makefile (before the glut library 'libglut.a'), and include "glui.h" +in your sources. + + + +---------------------------------------------------------------------- + +Please let me know what you think, what you'd like to change or add, +and especially what bugs you encounter. Also, please send me your +e-mail so I can add you to a mailing list for updates. + +Good luck, and thanks for trying this out! + +Paul Rademacher +rademach +at +cs unc edu \ No newline at end of file diff --git a/Extras/iff/CMakeLists.txt b/Extras/iff/CMakeLists.txt new file mode 100644 index 0000000..17d798c --- /dev/null +++ b/Extras/iff/CMakeLists.txt @@ -0,0 +1,11 @@ +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/Extras/iff +) + +ADD_LIBRARY(Iff +iff.h +iffr.cpp +iffw.cpp +) + +#SUBDIRS( BulletIffConverter ) diff --git a/Extras/iff/IFF.txt b/Extras/iff/IFF.txt new file mode 100644 index 0000000..9d4ae8b --- /dev/null +++ b/Extras/iff/IFF.txt @@ -0,0 +1,1423 @@ + +"EA IFF 85" Standard for Interchange Format Files + +Document Date: January 14, 1985 +From: Jerry Morrison, Electronic Arts +Status of Standard: Released and in use + +1. Introduction + +Standards are Good for Software Developers + +As home computer hardware evolves to better and better media machines, +the demand increases for higher quality, more detailed data. Data +development gets more expensive, requires more expertise and better +tools, and has to be shared across projects. Think about several ports +of a product on one CD-ROM with 500M Bytes of common data! + +Development tools need standard interchange file formats. Imagine +scanning in images of "player" shapes, moving them to a paint program +for editing, then incorporating them into a game. Or writing a theme +song with a Macintosh score editor and incorporating it into an Amiga +game. The data must at times be transformed, clipped, filled out, +and moved across machine kinds. Media projects will depend on data +transfer from graphic, music, sound effect, animation, and script +tools. + +Standards are Good for Software Users + +Customers should be able to move their own data between independently +developed software products. And they should be able to buy data libraries +usable across many such products. The types of data objects to exchange +are open-ended and include plain and formatted text, raster and structured +graphics, fonts, music, sound effects, musical instrument descriptions, +and animation. + +The problem with expedient file formats typically memory dumps is +that they're too provincial. By designing data for one particular +use (e.g. a screen snapshot), they preclude future expansion (would +you like a full page picture? a multi-page document?). In neglecting +the possibility that other programs might read their data, they fail +to save contextual information (how many bit planes? what resolution?). +Ignoring that other programs might create such files, they're intolerant +of extra data (texture palette for a picture editor), missing data +(no color map), or minor variations (smaller image). In practice, +a filed representation should rarely mirror an in-memory representation. +The former should be designed for longevity; the latter to optimize +the manipulations of a particular program. The same filed data will +be read into different memory formats by different programs. + +The IFF philosophy: "A little behind-the-scenes conversion when programs +read and write files is far better than NxM explicit conversion utilities +for highly specialized formats." + +So we need some standardization for data interchange among development +tools and products. The more developers that adopt a standard, the +better for all of us and our customers. + +Here is "EA IFF 1985" + +Here is our offering: Electronic Arts' IFF standard for Interchange +File Format. The full name is "EA IFF 1985". Alternatives and justifications +are included for certain choices. Public domain subroutine packages +and utility programs are available to make it easy to write and use +IFF-compatible programs. + +Part 1 introduces the standard. Part 2 presents its requirements and +background. Parts 3, 4, and 5 define the primitive data types, FORMs, +and LISTs, respectively, and how to define new high level types. Part +6 specifies the top level file structure. Appendix A is included for +quick reference and Appendix B names the committee responsible for +this standard. + +References + +American National Standard Additional Control Codes for Use with ASCII, +ANSI standard 3.64-1979 for an 8-bit character set. See also ISO standard +2022 and ISO/DIS standard 6429.2. + +Amiga[tm] is a trademark of Commodore-Amiga, Inc. + +C, A Reference Manual, Samuel P. Harbison and Guy L. Steele Jr., Tartan +Laboratories. Prentice-Hall, Englewood Cliffs, NJ, 1984. + +Compiler Construction, An Advanced Course, edited by F. L. Bauer and +J. Eickel (Springer-Verlag, 1976). This book is one of many sources +for information on recursive descent parsing. + +DIF Technical Specification (c)1981 by Software Arts, Inc. DIF[tm] is +the format for spreadsheet data interchange developed by Software +Arts, Inc. +DIF[tm] is a trademark of Software Arts, Inc. + +Electronic Arts[tm] is a trademark of Electronic Arts. + +"FTXT" IFF Formatted Text, from Electronic Arts. IFF supplement document +for a text format. + +Inside Macintosh (c) 1982, 1983, 1984, 1985 Apple Computer, Inc., a +programmer's reference manual. +Apple(R) is a trademark of Apple Computer, Inc. +Macintosh[tm] is a trademark licensed to Apple Computer, Inc. + +"ILBM" IFF Interleaved Bitmap, from Electronic Arts. IFF supplement +document for a raster image format. + +M68000 16/32-Bit Microprocessor Programmer's Reference Manual(c) 1984, +1982, 1980, 1979 by Motorola, Inc. + +PostScript Language Manual (c) 1984 Adobe Systems Incorporated. +PostScript[tm] is a trademark of Adobe Systems, Inc. +Times and Helvetica(R) are trademarks of Allied Corporation. + +InterScript: A Proposal for a Standard for the Interchange of Editable +Documents (c)1984 Xerox Corporation. +Introduction to InterScript (c) 1985 Xerox Corporation. + + + +2. Background for Designers + +Part 2 is about the background, requirements, and goals for the standard. +It's geared for people who want to design new types of IFF objects. +People just interested in using the standard may wish to skip this +part. + +What Do We Need? + +A standard should be long on prescription and short on overhead. It +should give lots of rules for designing programs and data files for +synergy. But neither the programs nor the files should cost too much +more than the expedient variety. While we're looking to a future with +CD-ROMs and perpendicular recording, the standard must work well on +floppy disks. + +For program portability, simplicity, and efficiency, formats should +be designed with more than one implementation style in mind. (In practice, +pure stream I/O is adequate although random access makes it easier +to write files.) It ought to be possible to read one of many objects +in a file without scanning all the preceding data. Some programs need +to read and play out their data in real time, so we need good compromises +between generality and efficiency. + +As much as we need standards, they can't hold up product schedules. +So we also need a kind of decentralized extensibility where any software +developer can define and refine new object types without some "standards +authority" in the loop. Developers must be able to extend existing +formats in a forward- and backward-compatible way. A central repository +for design information and example programs can help us take full +advantage of the standard. + +For convenience, data formats should heed the restrictions of various +processors and environments. E.g. word-alignment greatly helps 68000 +access at insignificant cost to 8088 programs. + +Other goals include the ability to share common elements over a list +of objects and the ability to construct composite objects containing +other data objects with structural information like directories. + +And finally, "Simple things should be simple and complex things should +be possible." Alan Kay. + +Think Ahead + +Let's think ahead and build programs that read and write files for +each other and for programs yet to be designed. Build data formats +to last for future computers so long as the overhead is acceptable. +This extends the usefulness and life of today's programs and data. + +To maximize interconnectivity, the standard file structure and the +specific object formats must all be general and extensible. Think +ahead when designing an object. It should serve many purposes and +allow many programs to store and read back all the information they +need; even squeeze in custom data. Then a programmer can store the +available data and is encouraged to include fixed contextual details. +Recipient programs can read the needed parts, skip unrecognized stuff, +default missing data, and use the stored context to help transform +the data as needed. + +Scope + +IFF addresses these needs by defining a standard file structure, some +initial data object types, ways to define new types, and rules for +accessing these files. We can accomplish a great deal by writing programs +according to this standard, but don't expect direct compatibility +with existing software. We'll need conversion programs to bridge the +gap from the old world. + +IFF is geared for computers that readily process information in 8-bit +bytes. It assumes a "physical layer" of data storage and transmission +that reliably maintains "files" as strings of 8-bit bytes. The standard +treats a "file" as a container of data bytes and is independent of +how to find a file and whether it has a byte count. + +This standard does not by itself implement a clipboard for cutting +and pasting data between programs. A clipboard needs software to mediate +access, to maintain a "contents version number" so programs can detect +updates, and to manage the data in "virtual memory". + +Data Abstraction + +The basic problem is how to represent information in a way that's +program-independent, compiler- independent, machine-independent, and +device-independent. + +The computer science approach is "data abstraction", also known as +"objects", "actors", and "abstract data types". A data abstraction +has a "concrete representation" (its storage format), an "abstract +representation" (its capabilities and uses), and access procedures +that isolate all the calling software from the concrete representation. +Only the access procedures touch the data storage. Hiding mutable +details behind an interface is called "information hiding". What data +abstraction does is abstract from details of implementing the object, +namely the selected storage representation and algorithms for manipulating +it. + +The power of this approach is modularity. By adjusting the access +procedures we can extend and restructure the data without impacting +the interface or its callers. Conversely, we can extend and restructure +the interface and callers without making existing data obsolete. It's +great for interchange! + +But we seem to need the opposite: fixed file formats for all programs +to access. Actually, we could file data abstractions ("filed objects") +by storing the data and access procedures together. We'd have to encode +the access procedures in a standard machine-independent programming +language la PostScript. Even still, the interface can't evolve freely +since we can't update all copies of the access procedures. So we'll +have to design our abstract representations for limited evolution +and occasional revolution (conversion). + +In any case, today's microcomputers can't practically store data abstractions. +They can do the next best thing: store arbitrary types of data in +"data chunks", each with a type identifier and a length count. The +type identifier is a reference by name to the access procedures (any +local implementation). The length count enables storage-level object +operations like "copy" and "skip to next" independent of object type. + +Chunk writing is straightforward. Chunk reading requires a trivial +parser to scan each chunk and dispatch to the proper access/conversion +procedure. Reading chunks nested inside other chunks requires recursion, +but no lookahead or backup. + +That's the main idea of IFF. There are, of course, a few other detailsI + +Previous Work + +Where our needs are similar, we borrow from existing standards. + +Our basic need to move data between independently developed programs +is similar to that addressed by the Apple Macintosh desk scrap or +"clipboard" [Inside Macintosh chapter "Scrap Manager"]. The Scrap +Manager works closely with the Resource Manager, a handy filer and +swapper for data objects (text strings, dialog window templates, pictures, +fontsI) including types yet to be designed [Inside Macintosh chapter +"Resource Manager"]. The Resource Manager is a kin to Smalltalk's +object swapper. + +We will probably write a Macintosh desk accessory that converts IFF +files to and from the Macintosh clipboard for quick and easy interchange +with programs like MacPaint and Resource Mover. + +Macintosh uses a simple and elegant scheme of 4-character "identifiers" +to identify resource types, clipboard format types, file types, and +file creator programs. Alternatives are unique ID numbers assigned +by a central authority or by hierarchical authorities, unique ID numbers +generated by algorithm, other fixed length character strings, and +variable length strings. Character string identifiers double as readable +signposts in data files and programs. The choice of 4 characters is +a good tradeoff between storage space, fetch/compare/store time, and +name space size. We'll honor Apple's designers by adopting this scheme. + +"PICT" is a good example of a standard structured graphics format +(including raster images) and its many uses [Inside Macintosh chapter +"QuickDraw"]. Macintosh provides QuickDraw routines in ROM to create, +manipulate, and display PICTs. Any application can create a PICT by +simply asking QuickDraw to record a sequence of drawing commands. +Since it's just as easy to ask QuickDraw to render a PICT to a screen +or a printer, it's very effective to pass them between programs, say +from an illustrator to a word processor. An important feature is the +ability to store "comments" in a PICT which QuickDraw will ignore. +Actually, it passes them to your optional custom "comment handler". + +PostScript, Adobe's print file standard, is a more general way to +represent any print image (which is a specification for putting marks +on paper) [PostScript Language Manual]. In fact, PostScript is a full-fledged +programming language. To interpret a PostScript program is to render +a document on a raster output device. The language is defined in layers: +a lexical layer of identifiers, constants, and operators; a layer +of reverse polish semantics including scope rules and a way to define +new subroutines; and a printing-specific layer of built-in identifiers +and operators for rendering graphic images. It is clearly a powerful +(Turing equivalent) image definition language. PICT and a subset of +PostScript are candidates for structured graphics standards. + +A PostScript document can be printed on any raster output device (including +a display) but cannot generally be edited. That's because the original +flexibility and constraints have been discarded. Besides, a PostScript +program may use arbitrary computation to supply parameters like placement +and size to each operator. A QuickDraw PICT, in comparison, is a more +restricted format of graphic primitives parameterized by constants. +So a PICT can be edited at the level of the primitives, e.g. move +or thicken a line. It cannot be edited at the higher level of, say, +the bar chart data which generated the picture. + +PostScript has another limitation: Not all kinds of data amount to +marks on paper. A musical instrument description is one example. PostScript +is just not geared for such uses. + +"DIF" is another example of data being stored in a general format +usable by future programs [DIF Technical Specification]. DIF is a +format for spreadsheet data interchange. DIF and PostScript are both +expressed in plain ASCII text files. This is very handy for printing, +debugging, experimenting, and transmitting across modems. It can have +substantial cost in compaction and read/write work, depending on use. +We won't store IFF files this way but we could define an ASCII alternate +representation with a converter program. + +InterScript is Xerox' standard for interchange of editable documents +[Introduction to InterScript]. It approaches a harder problem: How +to represent editable word processor documents that may contain formatted +text, pictures, cross-references like figure numbers, and even highly +specialized objects like mathematical equations? InterScript aims +to define one standard representation for each kind of information. +Each InterScript-compatible editor is supposed to preserve the objects +it doesn't understand and even maintain nested cross-references. So +a simple word processor would let you edit the text of a fancy document +without discarding the equations or disrupting the equation numbers. + +Our task is similarly to store high level information and preserve +as much content as practical while moving it between programs. But +we need to span a larger universe of data types and cannot expect +to centrally define them all. Fortunately, we don't need to make programs +preserve information that they don't understand. And for better or +worse, we don't have to tackle general-purpose cross-references yet. + + + +3. Primitive Data Types + +Atomic components such as integers and characters that are interpretable +directly by the CPU are specified in one format for all processors. +We chose a format that's most convenient for the Motorola MC68000 +processor [M68000 16/32-Bit Microprocessor Programmer's Reference +Manual]. + +N.B.: Part 3 dictates the format for "primitive" data types where and +only where used in the overall file structure and standard kinds of +chunks (Cf. Chunks). The number of such occurrences will be small +enough that the costs of conversion, storage, and management of processor- +specific files would far exceed the costs of conversion during I/O by "foreign" +programs. A particular data chunk may be specified with a different +format for its internal primitive types or with processor- or environment- +speci fic variants if necessary to optimize local usage. Since that hurts +data interchange, it's not recommended. (Cf. Designing New Data Sections, +in Part 4.) + +Alignment + +All data objects larger than a byte are aligned on even byte addresses +relative to the start of the file. This may require padding. Pad bytes +are to be written as zeros, but don't count on that when reading. + +This means that every odd-length "chunk" (see below) must be padded +so that the next one will fall on an even boundary. Also, designers +of structures to be stored in chunks should include pad fields where +needed to align every field larger than a byte. Zeros should be stored +in all the pad bytes. + +Justification: Even-alignment causes a little extra work for files +that are used only on certain processors but allows 68000 programs +to construct and scan the data in memory and do block I/O. You just +add an occasional pad field to data structures that you're going to +block read/write or else stream read/write an extra byte. And the +same source code works on all processors. Unspecified alignment, on +the other hand, would force 68000 programs to (dis)assemble word and +long-word data one byte at a time. Pretty cumbersome in a high level +language. And if you don't conditionally compile that out for other +processors, you won't gain anything. + +Numbers + +Numeric types supported are two's complement binary integers in the +format used by the MC68000 processor high byte first, high word first the +reverse of 8088 and 6502 format. They could potentially include signed +and unsigned 8, 16, and 32 bit integers but the standard only uses +the following: + +UBYTE 8 bits unsigned +WORD 16 bits signed +UWORD 16 bits unsigned +LONG 32 bits signed + +The actual type definitions depend on the CPU and the compiler. In +this document, we'll express data type definitions in the C programming +language. [See C, A Reference Manual.] In 68000 Lattice C: + +typedef unsigned char UBYTE; /* 8 bits unsigned */ +typedef short WORD; /* 16 bits signed */ +typedef unsigned short UWORD; /* 16 bits unsigned */ +typedef long LONG; /* 32 bits signed */ + +Characters + +The following character set is assumed wherever characters are used, +e.g. in text strings, IDs, and TEXT chunks (see below). + +Characters are encoded in 8-bit ASCII. Characters in the range NUL +(hex 0) through DEL (hex 7F) are well defined by the 7-bit ASCII standard. +IFF uses the graphic group RJS (SP, hex 20) through R~S (hex 7E). + +Most of the control character group hex 01 through hex 1F have no +standard meaning in IFF. The control character LF (hex 0A) is defined +as a "newline" character. It denotes an intentional line break, that +is, a paragraph or line terminator. (There is no way to store an automatic +line break. That is strictly a function of the margins in the environment +the text is placed.) The control character ESC (hex 1B) is a reserved +escape character under the rules of ANSI standard 3.64-1979 American +National Standard Additional Control Codes for Use with ASCII, ISO +standard 2022, and ISO/DIS standard 6429.2. + +Characters in the range hex 7F through hex FF are not globally defined +in IFF. They are best left reserved for future standardization. But +note that the FORM type FTXT (formatted text) defines the meaning +of these characters within FTXT forms. In particular, character values +hex 7F through hex 9F are control codes while characters hex A0 through +hex FF are extended graphic characters like , as per the ISO and +ANSI standards cited above. [See the supplementary document "FTXT" +IFF Formatted Text.] + +Dates + +A "creation date" is defined as the date and time a stream of data +bytes was created. (Some systems call this a "last modified date".) +Editing some data changes its creation date. Moving the data between +volumes or machines does not. + +The IFF standard date format will be one of those used in MS-DOS, +Macintosh, or Amiga DOS (probably a 32-bit unsigned number of seconds +since a reference point). Issue: Investigate these three. + +Type IDs + +A "type ID", "property name", "FORM type", or any other IFF identifier +is a 32-bit value: the concatenation of four ASCII characters in the +range R S (SP, hex 20) through R~S (hex 7E). Spaces (hex 20) should +not precede printing characters; trailing spaces are ok. Control characters +are forbidden. + +typedef CHAR ID[4]; + +IDs are compared using a simple 32-bit case-dependent equality test. + +Data section type IDs (aka FORM types) are restriced IDs. (Cf. Data +Sections.) Since they may be stored in filename extensions (Cf. Single +Purpose Files) lower case letters and punctuation marks are forbidden. +Trailing spaces are ok. + +Carefully choose those four characters when you pick a new ID. Make +them mnemonic so programmers can look at an interchange format file +and figure out what kind of data it contains. The name space makes +it possible for developers scattered around the globe to generate +ID values with minimal collisions so long as they choose specific +names like "MUS4" instead of general ones like "TYPE" and "FILE". +EA will "register" new FORM type IDs and format descriptions as they're +devised, but collisions will be improbable so there will be no pressure +on this "clearinghouse" process. Appendix A has a list of currently +defined IDs. + +Sometimes it's necessary to make data format changes that aren't backward +compatible. Since IDs are used to denote data formats in IFF, new +IDs are chosen to denote revised formats. Since programs won't read +chunks whose IDs they don't recognize (see Chunks, below), the new +IDs keep old programs from stumbling over new data. The conventional +way to chose a "revision" ID is to increment the last character if +it's a digit or else change the last character to a digit. E.g. first +and second revisions of the ID "XY" would be "XY1" and "XY2". Revisions +of "CMAP" would be "CMA1" and "CMA2". + +Chunks + +Chunks are the building blocks in the IFF structure. The form expressed +as a C typedef is: + +typedef struct { + ID ckID; + LONG ckSize; /* sizeof(ckData) */ + UBYTE ckData[/* ckSize */]; + } Chunk; + +We can diagram an example chunk a "CMAP" chunk containing 12 data +bytes like this: + ---------------- + ckID: | 'CMAP' | + ckSize: | 12 | + ckData: | 0, 0, 0, 32 | -------- + | 0, 0, 64, 0 | 12 bytes + | 0, 0, 64, 0 | --------- + ---------------- + +The fixed header part means "Here's a type ckID chunk with ckSize +bytes of data." + +The ckID identifies the format and purpose of the chunk. As a rule, +a program must recognize ckID to interpret ckData. It should skip +over all unrecognized chunks. The ckID also serves as a format version +number as long as we pick new IDs to identify new formats of ckData +(see above). + +The following ckIDs are universally reserved to identify chunks with +particular IFF meanings: "LIST", "FORM", "PROP", "CAT ", and " +". The special ID " " (4 spaces) is a ckID for "filler" chunks, +that is, chunks that fill space but have no meaningful contents. The +IDs "LIS1" through "LIS9", "FOR1" through "FOR9", and "CAT1" through +"CAT9" are reserved for future "version number" variations. All IFF-compatible +software must account for these 23 chunk IDs. Appendix A has a list +of predefined IDs. + +The ckSize is a logical block size how many data bytes are in ckData. +If ckData is an odd number of bytes long, a 0 pad byte follows which +is not included in ckSize. (Cf. Alignment.) A chunk's total physical +size is ckSize rounded up to an even number plus the size of the header. +So the smallest chunk is 8 bytes long with ckSize = 0. For the sake +of following chunks, programs must respect every chunk's ckSize as +a virtual end-of-file for reading its ckData even if that data is +malformed, e.g. if nested contents are truncated. + +We can describe the syntax of a chunk as a regular expression with +"#" representing the ckSize, i.e. the length of the following {braced} +bytes. The "[0]" represents a sometimes needed pad byte. (The regular +expressions in this document are collected in Appendix A along with +an explanation of notation.) + +Chunk ::= ID #{ UBYTE* } [0] + +One chunk output technique is to stream write a chunk header, stream +write the chunk contents, then random access back to the header to +fill in the size. Another technique is to make a preliminary pass +over the data to compute the size, then write it out all at once. + +Strings, String Chunks, and String Properties + +In a string of ASCII text, LF denotes a forced line break (paragraph +or line terminator). Other control characters are not used. (Cf. Characters.) + +The ckID for a chunk that contains a string of plain, unformatted +text is "TEXT". As a practical matter, a text string should probably +not be longer than 32767 bytes. The standard allows up to 231 - 1 +bytes. + +When used as a data property (see below), a text string chunk may +be 0 to 255 characters long. Such a string is readily converted to +a C string or a Pascal STRING[255]. The ckID of a property must be +the property name, not "TEXT". + +When used as a part of a chunk or data property, restricted C string +format is normally used. That means 0 to 255 characters followed by +a NUL byte (ASCII value 0). + +Data Properties + +Data properties specify attributes for following (non-property) chunks. +A data property essentially says "identifier = value", for example +"XY = (10, 200)", telling something about following chunks. Properties +may only appear inside data sections ("FORM" chunks, cf. Data Sections) +and property sections ("PROP" chunks, cf. Group PROP). + +The form of a data property is a special case of Chunk. The ckID is +a property name as well as a property type. The ckSize should be small +since data properties are intended to be accumulated in RAM when reading +a file. (256 bytes is a reasonable upper bound.) Syntactically: + +Property ::= Chunk + +When designing a data object, use properties to describe context information +like the size of an image, even if they don't vary in your program. +Other programs will need this information. + +Think of property settings as assignments to variables in a programming +language. Multiple assignments are redundant and local assignments +temporarily override global assignments. The order of assignments +doesn't matter as long as they precede the affected chunks. (Cf. LISTs, +CATs, and Shared Properties.) + +Each object type (FORM type) is a local name space for property IDs. +Think of a "CMAP" property in a "FORM ILBM" as the qualified ID "ILBM.CMAP". +Property IDs specified when an object type is designed (and therefore +known to all clients) are called "standard" while specialized ones +added later are "nonstandard". + +Links + +Issue: A standard mechanism for "links" or "cross references" is very +desirable for things like combining images and sounds into animations. +Perhaps we'll define "link" chunks within FORMs that refer to other +FORMs or to specific chunks within the same and other FORMs. This +needs further work. EA IFF 1985 has no standard link mechanism. + +For now, it may suffice to read a list of, say, musical instruments, +and then just refer to them within a musical score by index number. + +File References + +Issue: We may need a standard form for references to other files. +A "file ref" could name a directory and a file in the same type of +operating system as the ref's originator. Following the reference +would expect the file to be on some mounted volume. In a network environment, +a file ref could name a server, too. + +Issue: How can we express operating-system independent file refs? + +Issue: What about a means to reference a portion of another file? +Would this be a "file ref" plus a reference to a "link" within the +target file? + + + +4. Data Sections + +The first thing we need of a file is to check: Does it contain IFF +data and, if so, does it contain the kind of data we're looking for? +So we come to the notion of a "data section". + +A "data section" or IFF "FORM" is one self-contained "data object" +that might be stored in a file by itself. It is one high level data +object such as a picture or a sound effect. The IFF structure "FORM" +makes it self- identifying. It could be a composite object like a +musical score with nested musical instrument descriptions. + +Group FORM + +A data section is a chunk with ckID "FORM" and this arrangement: + +FORM ::= "FORM" #{ FormType (LocalChunk | FORM | LIST | CAT)* +} +FormType ::= ID +LocalChunk ::= Property | Chunk + +The ID "FORM" is a syntactic keyword like "struct" in C. Think of +a "struct ILBM" containing a field "CMAP". If you see "FORM" you'll +know to expect a FORM type ID (the structure name, "ILBM" in this +example) and a particular contents arrangement or "syntax" (local +chunks, FORMs, LISTs, and CATs). (LISTs and CATs are discussed in +part 5, below.) A "FORM ILBM", in particular, might contain a local +chunk "CMAP", an "ILBM.CMAP" (to use a qualified name). + +So the chunk ID "FORM" indicates a data section. It implies that the +chunk contains an ID and some number of nested chunks. In reading +a FORM, like any other chunk, programs must respect its ckSize as +a virtual end-of-file for reading its contents, even if they're truncated. + +The FormType (or FORM type) is a restricted ID that may not contain +lower case letters or punctuation characters. (Cf. Type IDs. Cf. Single +Purpose Files.) + +The type-specific information in a FORM is composed of its "local +chunks": data properties and other chunks. Each FORM type is a local +name space for local chunk IDs. So "CMAP" local chunks in other FORM +types may be unrelated to "ILBM.CMAP". More than that, each FORM type +defines semantic scope. If you know what a FORM ILBM is, you'll know +what an ILBM.CMAP is. + +Local chunks defined when the FORM type is designed (and therefore +known to all clients of this type) are called "standard" while specialized +ones added later are "nonstandard". + +Among the local chunks, property chunks give settings for various +details like text font while the other chunks supply the essential +information. This distinction is not clear cut. A property setting +cancelled by a later setting of the same property has effect only +on data chunks in between. E.g. in the sequence: + +prop1 = x (propN = value)* prop1 = y + +where the propNs are not prop1, the setting prop1 = x has no effect. + +The following universal chunk IDs are reserved inside any FORM: "LIST", +"FORM", "PROP", "CAT ", "JJJJ", "LIS1" through "LIS9", "FOR1" through +"FOR9", and "CAT1" through "CAT9". (Cf. Chunks. Cf. Group LIST. Cf. +Group PROP.) For clarity, these universal chunk names may not be FORM +type IDs, either. + +Part 5, below, talks about grouping FORMs into LISTs and CATs. They +let you group a bunch of FORMs but don't impose any particular meaning +or constraints on the grouping. Read on. + +Composite FORMs + +A FORM chunk inside a FORM is a full-fledged data section. This means +you can build a composite object like a multi-frame animation sequence +from available picture FORMs and sound effect FORMs. You can insert +additional chunks with information like frame rate and frame count. + +Using composite FORMs, you leverage on existing programs that create +and edit the component FORMs. Those editors may even look into your +composite object to copy out its type of component, although it'll +be the rare program that's fancy enough to do that. Such editors are +not allowed to replace their component objects within your composite +object. That's because the IFF standard lets you specify consistency +requirements for the composite FORM such as maintaining a count or +a directory of the components. Only programs that are written to uphold +the rules of your FORM type should create or modify such FORMs. + +Therefore, in designing a program that creates composite objects, +you are strongly requested to provide a facility for your users to +import and export the nested FORMs. Import and export could move the +data through a clipboard or a file. + +Here are several existing FORM types and rules for defining new ones. + +FTXT + +An FTXT data section contains text with character formatting information +like fonts and faces. It has no paragraph or document formatting information +like margins and page headers. FORM FTXT is well matched to the text +representation in Amiga's Intuition environment. See the supplemental +document "FTXT" IFF Formatted Text. + +ILBM + +"ILBM" is an InterLeaved BitMap image with color map; a machine-independent +format for raster images. FORM ILBM is the standard image file format +for the Commodore-Amiga computer and is useful in other environments, +too. See the supplemental document "ILBM" IFF Interleaved Bitmap. + +PICS + +The data chunk inside a "PICS" data section has ID "PICT" and holds +a QuickDraw picture. Issue: Allow more than one PICT in a PICS? See +Inside Macintosh chapter "QuickDraw" for details on PICTs and how +to create and display them on the Macintosh computer. + +The only standard property for PICS is "XY", an optional property +that indicates the position of the PICT relative to "the big picture". +The contents of an XY is a QuickDraw Point. + +Note: PICT may be limited to Macintosh use, in which case there'll +be another format for structured graphics in other environments. + +Other Macintosh Resource Types + +Some other Macintosh resource types could be adopted for use within +IFF files; perhaps MWRT, ICN, ICN#, and STR#. + +Issue: Consider the candidates and reserve some more IDs. + +Designing New Data Sections + +Supplemental documents will define additional object types. A supplement +needs to specify the object's purpose, its FORM type ID, the IDs and +formats of standard local chunks, and rules for generating and interpreting +the data. It's a good idea to supply typedefs and an example source +program that accesses the new object. See "ILBM" IFF Interleaved Bitmap +for a good example. + +Anyone can pick a new FORM type ID but should reserve it with Electronic +Arts at their earliest convenience. [Issue: EA contact person? Hand +this off to another organization?] While decentralized format definitions +and extensions are possible in IFF, our preference is to get design +consensus by committee, implement a program to read and write it, +perhaps tune the format, and then publish the format with example +code. Some organization should remain in charge of answering questions +and coordinating extensions to the format. + +If it becomes necessary to revise the design of some data section, +its FORM type ID will serve as a version number (Cf. Type IDs). E.g. +a revised "VDEO" data section could be called "VDE1". But try to get +by with compatible revisions within the existing FORM type. + +In a new FORM type, the rules for primitive data types and word-alignment +(Cf. Primitive Data Types) may be overriden for the contents of its +local chunks but not for the chunk structure itself if your documentation +spells out the deviations. If machine-specific type variants are needed, +e.g. to store vast numbers of integers in reverse bit order, then +outline the conversion algorithm and indicate the variant inside each +file, perhaps via different FORM types. Needless to say, variations +should be minimized. + +In designing a FORM type, encapsulate all the data that other programs +will need to interpret your files. E.g. a raster graphics image should +specify the image size even if your program always uses 320 x 200 +pixels x 3 bitplanes. Receiving programs are then empowered to append +or clip the image rectangle, to add or drop bitplanes, etc. This enables +a lot more compatibility. + +Separate the central data (like musical notes) from more specialized +information (like note beams) so simpler programs can extract the +central parts during read-in. Leave room for expansion so other programs +can squeeze in new kinds of information (like lyrics). And remember +to keep the property chunks manageably short let's say 2 256 bytes. + +When designing a data object, try to strike a good tradeoff between +a super-general format and a highly-specialized one. Fit the details +to at least one particular need, for example a raster image might +as well store pixels in the current machine's scan order. But add +the kind of generality that makes it usable with foreseeable hardware +and software. E.g. use a whole byte for each red, green, and blue +color value even if this year's computer has only 4-bit video DACs. +Think ahead and help other programs so long as the overhead is acceptable. +E.g. run compress a raster by scan line rather than as a unit so future +programs can swap images by scan line to and from secondary storage. + +Try to design a general purpose "least common multiple" format that +encompasses the needs of many programs without getting too complicated. +Let's coalesce our uses around a few such formats widely separated +in the vast design space. Two factors make this flexibility and simplicity +practical. First, file storage space is getting very plentiful, so +compaction is not a priority. Second, nearly any locally-performed +data conversion work during file reading and writing will be cheap +compared to the I/O time. + +It must be ok to copy a LIST or FORM or CAT intact, e.g. to incorporate +it into a composite FORM. So any kind of internal references within +a FORM must be relative references. They could be relative to the +start of the containing FORM, relative from the referencing chunk, +or a sequence number into a collection. + +With composite FORMs, you leverage on existing programs that create +and edit the components. If you write a program that creates composite +objects, please provide a facility for your users to import and export +the nested FORMs. The import and export functions may move data through +a separate file or a clipboard. + +Finally, don't forget to specify all implied rules in detail. + + + +5. LISTs, CATs, and Shared Properties + +Data often needs to be grouped together like a list of icons. Sometimes +a trick like arranging little images into a big raster works, but +generally they'll need to be structured as a first class group. The +objects "LIST" and "CAT" are IFF-universal mechanisms for this purpose. + +Property settings sometimes need to be shared over a list of similar +objects. E.g. a list of icons may share one color map. LIST provides +a means called "PROP" to do this. One purpose of a LIST is to define +the scope of a PROP. A "CAT", on the other hand, is simply a concatenation +of objects. + +Simpler programs may skip LISTs and PROPs altogether and just handle +FORMs and CATs. All "fully-conforming" IFF programs also know about +"CAT ", "LIST", and "PROP". Any program that reads a FORM inside a +LIST must process shared PROPs to correctly interpret that FORM. + +Group CAT + +A CAT is just an untyped group of data objects. + +Structurally, a CAT is a chunk with chunk ID "CAT " containing a "contents +type" ID followed by the nested objects. The ckSize of each contained +chunk is essentially a relative pointer to the next one. + +CAT ::= "CAT " #{ ContentsType (FORM | LIST | CAT)* } +ContentsType ::= ID -- a hint or an "abstract data type" ID + +In reading a CAT, like any other chunk, programs must respect it's +ckSize as a virtual end-of-file for reading the nested objects even +if they're malformed or truncated. + +The "contents type" following the CAT's ckSize indicates what kind +of FORMs are inside. So a CAT of ILBMs would store "ILBM" there. It's +just a hint. It may be used to store an "abstract data type". A CAT +could just have blank contents ID ("JJJJ") if it contains more than +one kind of FORM. + +CAT defines only the format of the group. The group's meaning is open +to interpretation. This is like a list in LISP: the structure of cells +is predefined but the meaning of the contents as, say, an association +list depends on use. If you need a group with an enforced meaning +(an "abstract data type" or Smalltalk "subclass"), some consistency +constraints, or additional data chunks, use a composite FORM instead +(Cf. Composite FORMs). + +Since a CAT just means a concatenation of objects, CATs are rarely +nested. Programs should really merge CATs rather than nest them. + +Group LIST + +A LIST defines a group very much like CAT but it also gives a scope +for PROPs (see below). And unlike CATs, LISTs should not be merged +without understanding their contents. + +Structurally, a LIST is a chunk with ckID "LIST" containing a "contents +type" ID, optional shared properties, and the nested contents (FORMs, +LISTs, and CATs), in that order. The ckSize of each contained chunk +is a relative pointer to the next one. A LIST is not an arbitrary +linked list the cells are simply concatenated. + +LIST ::= "LIST" #{ ContentsType PROP* (FORM | LIST | CAT)* } +ContentsType ::= ID + +Group PROP + +PROP chunks may appear in LISTs (not in FORMs or CATs). They supply +shared properties for the FORMs in that LIST. This ability to elevate +some property settings to shared status for a list of forms is useful +for both indirection and compaction. E.g. a list of images with the +same size and colors can share one "size" property and one "color +map" property. Individual FORMs can override the shared settings. + +The contents of a PROP is like a FORM with no data chunks: + +PROP ::= "PROP" #{ FormType Property* } + +It means, "Here are the shared properties for FORM type <." + +A LIST may have at most one PROP of a FORM type, and all the PROPs +must appear before any of the FORMs or nested LISTs and CATs. You +can have subsequences of FORMs sharing properties by making each subsequence +a LIST. + +Scoping: Think of property settings as variable bindings in nested +blocks of a programming language. Where in C you could write: + +TEXT_FONT text_font = Courier; /* program's global default */ + +File(); { + TEXT_FONT text_font = TimesRoman; /* shared setting */ + + { + TEXT_FONT text_font = Helvetica; /* local setting */ + Print("Hello "); /* uses font Helvetica */ + } + + { + Print("there."); /* uses font TimesRoman */ + } + } + +An IFF file could contain: + +LIST { + PROP TEXT { + FONT {TimesRoman} /* shared setting */ + } + + FORM TEXT { + FONT {Helvetica} /* local setting */ + CHRS {Hello } /* uses font Helvetica */ + } + + FORM TEXT { + CHRS {there.} /* uses font TimesRoman */ + } + } + +The shared property assignments selectively override the reader's +global defaults, but only for FORMs within the group. A FORM's own +property assignments selectively override the global and group-supplied +values. So when reading an IFF file, keep property settings on a stack. +They're designed to be small enough to hold in main memory. + +Shared properties are semantically equivalent to copying those properties +into each of the nested FORMs right after their FORM type IDs. + +Properties for LIST + +Optional "properties for LIST" store the origin of the list's contents +in a PROP chunk for the fake FORM type "LIST". They are the properties +originating program "OPGM", processor family "OCPU", computer type +"OCMP", computer serial number or network address "OSN ", and user +name "UNAM". In our imperfect world, these could be called upon to +distinguish between unintended variations of a data format or to work +around bugs in particular originating/receiving program pairs. Issue: +Specify the format of these properties. + +A creation date could also be stored in a property but let's ask that +file creating, editing, and transporting programs maintain the correct +date in the local file system. Programs that move files between machine +types are expected to copy across the creation dates. + + + +6. Standard File Structure + +File Structure Overview + +An IFF file is just a single chunk of type FORM, LIST, or CAT. Therefore +an IFF file can be recognized by its first 4 bytes: "FORM", "LIST", +or "CAT ". Any file contents after the chunk's end are to be ignored. + +Since an IFF file can be a group of objects, programs that read/write +single objects can communicate to an extent with programs that read/write +groups. You're encouraged to write programs that handle all the objects +in a LIST or CAT. A graphics editor, for example, could process a +list of pictures as a multiple page document, one page at a time. + +Programs should enforce IFF's syntactic rules when reading and writing +files. This ensures robust data transfer. The public domain IFF reader/writer +subroutine package does this for you. A utility program "IFFCheck" +is available that scans an IFF file and checks it for conformance +to IFF's syntactic rules. IFFCheck also prints an outline of the chunks +in the file, showing the ckID and ckSize of each. This is quite handy +when building IFF programs. Example programs are also available to +show details of reading and writing IFF files. + +A merge program "IFFJoin" will be available that logically appends +IFF files into a single CAT group. It "unwraps" each input file that +is a CAT so that the combined file isn't nested CATs. + +If we need to revise the IFF standard, the three anchoring IDs will +be used as "version numbers". That's why IDs "FOR1" through "FOR9", +"LIS1" through "LIS9", and "CAT1" through "CAT9" are reserved. + +IFF formats are designed for reasonable performance with floppy disks. +We achieve considerable simplicity in the formats and programs by +relying on the host file system rather than defining universal grouping +structures like directories for LIST contents. On huge storage systems, +IFF files could be leaf nodes in a file structure like a B-tree. Let's +hope the host file system implements that for us! + +Thre are two kinds of IFF files: single purpose files and scrap files. +They differ in the interpretation of multiple data objects and in +the file's external type. + +Single Purpose Files + +A single purpose IFF file is for normal "document" and "archive" storage. +This is in contrast with "scrap files" (see below) and temporary backing +storage (non-interchange files). + +The external file type (or filename extension, depending on the host +file system) indicates the file's contents. It's generally the FORM +type of the data contained, hence the restrictions on FORM type IDs. + +Programmers and users may pick an "intended use" type as the filename +extension to make it easy to filter for the relevant files in a filename +requestor. This is actually a "subclass" or "subtype" that conveniently +separates files of the same FORM type that have different uses. Programs +cannot demand conformity to its expected subtypes without overly restricting +data interchange since they cannot know about the subtypes to be used +by future programs that users will want to exchange data with. + +Issue: How to generate 3-letter MS-DOS extensions from 4-letter FORM +type IDs? + +Most single purpose files will be a single FORM (perhaps a composite +FORM like a musical score containing nested FORMs like musical instrument +descriptions). If it's a LIST or a CAT, programs should skip over +unrecognized objects to read the recognized ones or the first recognized +one. Then a program that can read a single purpose file can read something +out of a "scrap file", too. + +Scrap Files + +A "scrap file" is for maximum interconnectivity in getting data between +programs; the core of a clipboard function. Scrap files may have type +"IFF " or filename extension ".IFF". + +A scrap file is typically a CAT containing alternate representations +of the same basic information. Include as many alternatives as you +can readily generate. This redundancy improves interconnectivity in +situations where we can't make all programs read and write super-general +formats. [Inside Macintosh chapter "Scrap Manager".] E.g. a graphically- +annotated musical score might be supplemented by a stripped down 4-voice +melody and by a text (the lyrics). + +The originating program should write the alternate representations +in order of "preference": most preferred (most comprehensive) type +to least preferred (least comprehensive) type. A receiving program +should either use the first appearing type that it understands or +search for its own "preferred" type. + +A scrap file should have at most one alternative of any type. (A LIST +of same type objects is ok as one of the alternatives.) But don't +count on this when reading; ignore extra sections of a type. Then +a program that reads scrap files can read something out of single +purpose files. + +Rules for Reader Programs + +Here are some notes on building programs that read IFF files. If you +use the standard IFF reader module "IFFR.C", many of these rules and +details will be automatically handled. (See "Support Software" in +Appendix A.) We recommend that you start from the example program +"ShowILBM.C". You should also read up on recursive descent parsers. +[See, for example, Compiler Construction, An Advanced Course.] + +% The standard is very flexible so many programs can exchange +data. This implies a program has to scan the file and react to what's +actually there in whatever order it appears. An IFF reader program +is a parser. + +% For interchange to really work, programs must be willing to +do some conversion during read-in. If the data isn't exactly what +you expect, say, the raster is smaller than those created by your +program, then adjust it. Similarly, your program could crop a large +picture, add or drop bitplanes, and create/discard a mask plane. The +program should give up gracefully on data that it can't convert. + +% If it doesn't start with "FORM", "LIST", or "CAT ", it's not +an IFF-85 file. + +% For any chunk you encounter, you must recognize its type ID +to understand its contents. + +% For any FORM chunk you encounter, you must recognize its FORM +type ID to understand the contained "local chunks". Even if you don't +recognize the FORM type, you can still scan it for nested FORMs, LISTs, +and CATs of interest. + +% Don't forget to skip the pad byte after every odd-length chunk. + +% Chunk types LIST, FORM, PROP, and CAT are generic groups. They +always contain a subtype ID followed by chunks. + +% Readers ought to handle a CAT of FORMs in a file. You may treat +the FORMs like document pages to sequence through or just use the +first FORM. + +% Simpler IFF readers completely skip LISTs. "Fully IFF-conforming" +readers are those that handle LISTs, even if just to read the first +FORM from a file. If you do look into a LIST, you must process shared +properties (in PROP chunks) properly. The idea is to get the correct +data or none at all. + +% The nicest readers are willing to look into unrecognized FORMs +for nested FORM types that they do recognize. For example, a musical +score may contain nested instrument descriptions and an animation +file may contain still pictures. + +Note to programmers: Processing PROP chunks is not simple! You'll +need some background in interpreters with stack frames. If this is +foreign to you, build programs that read/write only one FORM per file. +For the more intrepid programmers, the next paragraph summarizes how +to process LISTs and PROPs. See the general IFF reader module "IFFR.C" +and the example program "ShowILBM.C" for details. + +Allocate a stack frame for every LIST and FORM you encounter and initialize +it by copying the stack frame of the parent LIST or FORM. At the top +level, you'll need a stack frame initialized to your program's global +defaults. While reading each LIST or FORM, store all encountered properties +into the current stack frame. In the example ShowILBM, each stack +frame has a place for a bitmap header property ILBM.BMHD and a color +map property ILBM.CMAP. When you finally get to the ILBM's BODY chunk, +use the property settings accumulated in the current stack frame. + +An alternate implementation would just remember PROPs encountered, +forgetting each on reaching the end of its scope (the end of the containing +LIST). When a FORM XXXX is encountered, scan the chunks in all remembered +PROPs XXXX, in order, as if they appeared before the chunks actually +in the FORM XXXX. This gets trickier if you read FORMs inside of FORMs. + +Rules for Writer Programs + +Here are some notes on building programs that write IFF files, which +is much easier than reading them. If you use the standard IFF writer +module "IFFW.C" (see "Support Software" in Appendix A), many of these +rules and details will automatically be enforced. See the example +program "Raw2ILBM.C". + +% An IFF file is a single FORM, LIST, or CAT chunk. + +% Any IFF-85 file must start with the 4 characters "FORM", "LIST", +or "CAT ", followed by a LONG ckSize. There should be no data after +the chunk end. + +% Chunk types LIST, FORM, PROP, and CAT are generic. They always +contain a subtype ID followed by chunks. These three IDs are universally +reserved, as are "LIS1" through "LIS9", "FOR1" through "FOR9", "CAT1" +through "CAT9", and " ". + +% Don't forget to write a 0 pad byte after each odd-length chunk. + +% Four techniques for writing an IFF group: (1) build the data +in a file mapped into virtual memory, (2) build the data in memory +blocks and use block I/O, (3) stream write the data piecemeal and +(don't forget!) random access back to set the group length count, +and (4) make a preliminary pass to compute the length count then stream +write the data. + +% Do not try to edit a file that you don't know how to create. +Programs may look into a file and copy out nested FORMs of types that +they recognize, but don't edit and replace the nested FORMs and don't +add or remove them. That could make the containing structure inconsistent. +You may write a new file containing items you copied (or copied and +modified) from another IFF file, but don't copy structural parts you +don't understand. + +% You must adhere to the syntax descriptions in Appendex A. E.g. +PROPs may only appear inside LISTs. + + + + +Appendix A. Reference + +Type Definitions + +The following C typedefs describe standard IFF structures. Declarations +to use in practice will vary with the CPU and compiler. For example, +68000 Lattice C produces efficient comparison code if we define ID +as a "LONG". A macro "MakeID" builds these IDs at compile time. + +/* Standard IFF types, expressed in 68000 Lattice C. */ + +typedef unsigned char UBYTE; /* 8 bits unsigned */ +typedef short WORD; /* 16 bits signed */ +typedef unsigned short UWORD; /* 16 bits unsigned */ +typedef long LONG; /* 32 bits signed */ + +typedef char ID[4]; /* 4 chars in ' ' through '~' */ + +typedef struct { + ID ckID; + LONG ckSize; /* sizeof(ckData) */ + UBYTE ckData[/* ckSize */]; + } Chunk; + +/* ID typedef and builder for 68000 Lattice C. */ +typedef LONG ID; /* 4 chars in ' ' through '~' */ +#define MakeID(a,b,c,d) ( (a)<<<<24 | (b)<<<<16 | (c)<<<<8 | (d) ) + +/* Globally reserved IDs. */ +#define ID_FORM MakeID('F','O','R','M') +#define ID_LIST MakeID('L','I','S','T') +#define ID_PROP MakeID('P','R','O','P') +#define ID_CAT MakeID('C','A','T',' ') +#define ID_FILLER MakeID(' ',' ',' ',' ') + +Syntax Definitions + +Here's a collection of the syntax definitions in this document. + +Chunk ::= ID #{ UBYTE* } [0] + +Property ::= Chunk + +FORM ::= "FORM" #{ FormType (LocalChunk | FORM | LIST | CAT)* +} +FormType ::= ID +LocalChunk ::= Property | Chunk + +CAT ::= "CAT " #{ ContentsType (FORM | LIST | CAT)* } +ContentsType ::= ID -- a hint or an "abstract data type" ID + +LIST ::= "LIST" #{ ContentsType PROP* (FORM | LIST | CAT)* } +PROP ::= "PROP" #{ FormType Property* } + +In this extended regular expression notation, the token "#" represents +a ckSize LONG count of the following {braced} data bytes. Literal +items are shown in "quotes", [square bracketed items] are optional, +and "*" means 0 or more instances. A sometimes-needed pad byte is +shown as "[0]". + +Defined Chunk IDs + +This is a table of currently defined chunk IDs. We may also borrow +some Macintosh IDs and data formats. + +Group chunk IDs + FORM, LIST, PROP, CAT. +Future revision group chunk IDs + FOR1 I FOR9, LIS1 I LIS9, CAT1 I CAT9. +FORM type IDs + (The above group chunk IDs may not be used for FORM type IDs.) + (Lower case letters and punctuation marks are forbidden in FORM +type IDs.) + 8SVX 8-bit sampled sound voice, ANBM animated bitmap, FNTR raster +font, FNTV vector font, FTXT formatted text, GSCR general-use musical +score, ILBM interleaved raster bitmap image, PDEF Deluxe Print page +definition, PICS Macintosh picture, PLBM (obsolete), USCR Uhuru Sound +Software musical score, UVOX Uhuru Sound Software Macintosh voice, +SMUS simple musical score, VDEO Deluxe Video Construction Set video. +Data chunk IDs + "JJJJ", TEXT, PICT. +PROP LIST property IDs + OPGM, OCPU, OCMP, OSN, UNAM. + + + +Support Software + +These public domain C source programs are available for use in building +IFF-compatible programs: + +IFF.H, IFFR.C, IFFW.C + + IFF reader and writer package. + These modules handle many of the details of reliably + reading and writing IFF files. + +IFFCheck.C This handy utility program scans an IFF file, checks + that the contents are well formed, and prints an outline + of the chunks. + +PACKER.H, Packer.C, UnPacker.C + + Run encoder and decoder used for ILBM files. + +ILBM.H, ILBMR.C, ILBMW.C + + Reader and writer support routines for raster image + FORM ILBM. ILBMR calls IFFR and UnPacker. ILBMW calls + IFFW and Packer. + +ShowILBM.C + Example caller of IFFR and ILBMR modules. This + Commodore-Amiga program reads and displays a FORM ILBM. +Raw2ILBM.C + Example ILBM writer program. As a demonstration, it + reads a raw raster image file and writes the image + as a FORM ILBM file. +ILBM2Raw.C + Example ILBM reader program. Reads a FORM ILBM file + and writes it into a raw raster image. + +REMALLOC.H, Remalloc.c + + Memory allocation routines used in these examples. + +INTUALL.H generic "include almost everything" include-file + with the sequence of includes correctly specified. + +READPICT.H, ReadPict.c + + given an ILBM file, read it into a bitmap and + a color map + +PUTPICT.H, PutPict.c + + given a bitmap and a color map, save it as + an ILBM file. + +GIO.H, Gio.c generic I/O speedup package. Attempts to speed + disk I/O by buffering writes and reads. + +giocall.c sample call to gio. + +ilbmdump.c reads in ILBM file, prints out ascii representation + for including in C files. + +bmprintc.c prints out a C-language representation of data for + a bitmap. + + + +Example Diagrams + +Here's a box diagram for an example IFF file, a raster image FORM +ILBM. This FORM contains a bitmap header property chunk BMHD, a color +map property chunk CMAP, and a raster data chunk BODY. This particular +raster is 320 x 200 pixels x 3 bit planes uncompressed. The "0" after +the CMAP chunk represents a zero pad byte; included since the CMAP +chunk has an odd length. The text to the right of the diagram shows +the outline that would be printed by the IFFCheck utility program +for this particular file. + + +-----------------------------------+ + |'FORM' 24070 | FORM 24070 IBLM + +-----------------------------------+ + |'ILBM' | + +-----------------------------------+ + | +-------------------------------+ | + | | 'BMHD' 20 | | .BMHD 20 + | | 320, 200, 0, 0, 3, 0, 0, ... | | + | + ------------------------------+ | + | | 'CMAP' 21 | | .CMAP 21 + | | 0, 0, 0; 32, 0, 0; 64,0,0; .. | | + | +-------------------------------+ | + | 0 | + +-----------------------------------+ + |'BODY' 24000 | .BODY 24000 + |0, 0, 0, ... | + +-----------------------------------+ + +This second diagram shows a LIST of two FORMs ILBM sharing a common +BMHD property and a common CMAP property. Again, the text on the right +is an outline a la IFFCheck. + + + +-----------------------------------------+ + |'LIST' 48114 | LIST 48114 AAAA + +-----------------------------------------+ + |'AAAA' | .PROP 62 ILBM + | +-----------------------------------+ | + | |'PROP' 62 | | + | +-----------------------------------+ | + | |'ILBM' | | + | +-----------------------------------+ | + | | +-------------------------------+ | | + | | | 'BMHD' 20 | | | ..BMHD 20 + | | | 320, 200, 0, 0, 3, 0, 0, ... | | | + | | | ------------------------------+ | | + | | | 'CMAP' 21 | | | ..CMAP 21 + | | | 0, 0, 0; 32, 0, 0; 64,0,0; .. | | | + | | +-------------------------------+ | | + | | 0 | | + | +-----------------------------------+ | + | +-----------------------------------+ | + | |'FORM' 24012 | | .FORM 24012 ILBM + | +-----------------------------------+ | + | |'ILBM' | | + | +-----------------------------------+ | + | | +-----------------------------+ | | + | | |'BODY' 24000 | | | ..BODY 24000 + | | |0, 0, 0, ... | | | + | | +-----------------------------+ | | + | +-----------------------------------+ | + | +-----------------------------------+ | + | |'FORM' 24012 | | .FORM 24012 ILBM + | +-----------------------------------+ | + | |'ILBM' | | + | +-----------------------------------+ | + | | +-----------------------------+ | | + | | |'BODY' 24000 | | | ..BODY 24000 + | | |0, 0, 0, ... | | | + | | +-----------------------------+ | | + | +-----------------------------------+ | + +-----------------------------------------+ + + + +Appendix B. Standards Committee + +The following people contributed to the design of this IFF standard: + +Bob "Kodiak" Burns, Commodore-Amiga +R. J. Mical, Commodore-Amiga +Jerry Morrison, Electronic Arts +Greg Riker, Electronic Arts +Steve Shaw, Electronic Arts +Barry Walsh, Commodore-Amiga diff --git a/Extras/iff/iff.h b/Extras/iff/iff.h new file mode 100644 index 0000000..bc467f3 --- /dev/null +++ b/Extras/iff/iff.h @@ -0,0 +1,460 @@ +#ifndef IFF_H +#define IFF_H +/*----------------------------------------------------------------------*/ +/* IFF.H defs for IFF-85 Interchange Format Files. 10/8/85 */ +/* */ +/* By Jerry Morrison and Steve Shaw, Electronic Arts. */ +/* This software is in the public domain. */ +/* Original version was for the Commodore-Amiga computer. */ +/* This version is compatible with PC, OSX, PS3, Wii, iPhone. 10/26/2008*/ +/*----------------------------------------------------------------------*/ + + + +#define NL 0L /** A ver of NULL So Manx will like it **/ +#include //printf debugging +typedef unsigned char UBYTE; +typedef FILE* BPTR; +typedef unsigned short int UWORD; +typedef short int WORD; +typedef char BYTE; +#define LOCAL +#define TRUE 1 +#define FALSE 0 +typedef int BOOL; +#define OFFSET_END SEEK_END +#define OFFSET_CURRENT SEEK_CUR +#define OFFSET_BEGINNING SEEK_SET + +#define Seek fseek +#define Write fwrite +#define Read(file,buffer,nbytes) fread(buffer,1,nbytes,file) +#define GWriteFlush(file) (0) +//#define GWrite(file, buffer, nBytes) fwrite(buffer,1,nBytes,file) +#define GSeek(file, position, mode) Seek(file, position, mode) + + + + + + +typedef int IFFP; /* Status code result from an IFF procedure */ +/* int, because must be type compatable with ID for GetChunkHdr.*/ +/* Note that the error codes below are not legal IDs.*/ +#define IFF_OKAY 0L /* Keep going...*/ +#define END_MARK -1L /* As if there was a chunk at end of group.*/ +#define IFF_DONE -2L /* clientProc returns this when it has READ enough. +* It means return thru all levels. File is Okay.*/ +#define DOS_ERROR -3L +#define NOT_IFF -4L /* not an IFF file.*/ +#define NO_FILE -5L /* Tried to open file, DOS didn't find it.*/ +#define CLIENT_ERROR -6L /* Client made invalid request, for instance, asking +* for more bytes than existed in chunk.*/ +#define BAD_FORM -7L /* A client read proc complains about FORM semantics; +* e.g. valid IFF, but missing a required chunk.*/ +#define SHORT_CHUNK -8L /* Client asked to IFFReadBytes more bytes than left +* in the chunk. Could be client bug or bad form.*/ +#define BAD_IFF -9L /* mal-formed IFF file. [TBD] Expand this into a +* range of error codes.*/ +#define LAST_ERROR (short)BAD_IFF + +/* This MACRO is used to RETURN immediately when a termination condition is +* found. This is a pretty weird macro. It requires the caller to declare a +* local "IFFP iffp" and assign it. This wouldn't work as a subroutine since +* it returns for it's caller. */ +#define CheckIFFP() { if (iffp != IFF_OKAY) return(iffp); } + + +/* ---------- ID -------------------------------------------------------*/ + +typedef int ID; /* An ID is four printable ASCII chars but + * stored as a int for efficient copy & compare.*/ + +/* Four-character IDentifier builder.*/ +#define MakeID(a,b,c,d) (((long)(a)) | ((long)(b))<<8L | (c)<<16L | (d)<<24L) +//#define MakeID(a,b,c,d) (((long)(a))<<24L | ((long)(b))<<16L | (c)<<8 | (d)) + +/* Standard group IDs. A chunk with one of these IDs contains a +SubTypeID followed by zero or more chunks.*/ +#define FORM MakeID('F','O','R','M') +#define PROP MakeID('P','R','O','P') +#define LIST MakeID('L','I','S','T') +#define CAT MakeID('C','A','T',' ') +#define FILLER MakeID(' ',' ',' ',' ') +/* The IDs "FOR1".."FOR9", "LIS1".."LIS9", & "CAT1".."CAT9" are reserved +* for future standardization.*/ + +/* Pseudo-ID used internally by chunk reader and writer.*/ +#define NULL_CHUNK 0L /* No current chunk.*/ + + +/* ---------- Chunk ----------------------------------------------------*/ + +/* All chunks start with a type ID and a count of the data bytes that +follow--the chunk's "logical size" or "data size". If that number is odd, +a 0 pad byte is written, too. */ +typedef struct { + ID ckID; + int ckSize; +} ChunkHeader; + +typedef struct { + ID ckID; + int ckSize; + UBYTE ckData[ 1 /*REALLY: ckSize*/ ]; +} Chunk; + +/* Pass ckSize = szNotYetKnown to the writer to mean "compute the size".*/ +#define szNotYetKnown 0x80000001L + +/* Need to know whether a value is odd so can word-align.*/ +#define IS_ODD(a) ((a) & 1) + +/* This macro rounds up to an even number. */ +#define WordAlign(size) ((size+1)&~1) + +/* ALL CHUNKS MUST BE PADDED TO EVEN NUMBER OF BYTES. +* ChunkPSize computes the total "physical size" of a padded chunk from +* its "data size" or "logical size". */ +#define ChunkPSize(dataSize) (WordAlign(dataSize) + (long)sizeof(ChunkHeader)) + +/* The Grouping chunks (LIST, FORM, PROP, & CAT) contain concatenations of +* chunks after a subtype ID that identifies the content chunks. +* "FORM type XXXX", "LIST of FORM type XXXX", "PROPerties associated +* with FORM type XXXX", or "conCATenation of XXXX".*/ +typedef struct { + ID ckID; + int ckSize; /* this ckSize includes "grpSubID".*/ + ID grpSubID; +} GroupHeader; + +typedef struct { + ID ckID; + int ckSize; + ID grpSubID; + UBYTE grpData[ 1 /*REALLY: ckSize-sizeof(grpSubID)*/ ]; +} GroupChunk; + + +/* ---------- IFF Reader -----------------------------------------------*/ + +/******** Routines to support a stream-oriented IFF file reader ******* +* +* These routines handle lots of details like error checking and skipping +* over padding. They're also careful not to read past any containing context. +* +* These routines ASSUME they're the only ones reading from the file. +* Client should check IFFP error codes. Don't press on after an error! +* These routines try to have no side effects in the error case, except +* partial I/O is sometimes unavoidable. +* +* All of these routines may return DOS_ERROR. In that case, ask DOS for the +* specific error code. +* +* The overall scheme for the low level chunk reader is to open a "group read +* context" with OpenRIFF or OpenRGroup, read the chunks with GetChunkHdr +* (and its kin) and IFFReadBytes, and close the context with CloseRGroup. +* +* The overall scheme for reading an IFF file is to use ReadIFF, ReadIList, +* and ReadICat to scan the file. See those procedures, ClientProc (below), +* and the skeleton IFF reader. */ + +/* Client passes ptrs to procedures of this type to ReadIFF which call them +* back to handle LISTs, FORMs, CATs, and PROPs. +* +* Use the GroupContext ptr when calling reader routines like GetChunkHdr. +* Look inside the GroupContext ptr for your ClientFrame ptr. You'll +* want to type cast it into a ptr to your containing struct to get your +* private contextual data (stacked property settings). See below. */ +typedef IFFP ClientProc( struct _GroupContext * ); + +/* Client's context for reading an IFF file or a group. +* Client should actually make this the first component of a larger struct +* (it's personal stack "frame") that has a field to store each "interesting" +* property encountered. +* Either initialize each such field to a global default or keep a boolean +* indicating if you've read a property chunk into that field. +* Your getList and getForm procs should allocate a new "frame" and copy the +* parent frame's contents. The getProp procedure should store into the frame +* allocated by getList for the containing LIST. */ +typedef struct _ClientFrame { + ClientProc *getList, *getProp, *getForm, *getCat; + /* client's own data follows; place to stack property settings */ +} ClientFrame; + +/* Our context for reading a group chunk. */ +typedef struct _GroupContext { + struct _GroupContext *parent; /* Containing group; NULL => whole file. */ + ClientFrame *clientFrame; /* Reader data & client's context state. */ + BPTR file; /* Byte-stream file handle. */ + int position; /* The context's logical file position. */ + int bound; /* File-absolute context bound + * or szNotYetKnown (writer only). */ + ChunkHeader ckHdr; /* Current chunk header. ckHdr.ckSize = szNotYetKnown + * means we need to go back and set the size (writer onl + y). + * See also Pseudo-IDs, above. */ + ID subtype; /* Group's subtype ID when reading. */ + int bytesSoFar; /* # bytes read/written of current chunk's data. */ +} GroupContext; + +/* Computes the number of bytes not yet read from the current chunk, given +* a group read context gc. */ +#define ChunkMoreBytes(gc) ((gc)->ckHdr.ckSize - (gc)->bytesSoFar) + + +/***** Low Level IFF Chunk Reader *****/ + +/* Given an open file, open a read context spanning the whole file. +* This is normally only called by ReadIFF. +* This sets new->clientFrame = clientFrame. +* ASSUME context allocated by caller but not initialized. +* ASSUME caller doesn't deallocate the context before calling CloseRGroup. +* NOT_IFF ERROR if the file is too short for even a chunk header.*/ +extern IFFP OpenRIFF(BPTR file, GroupContext *, ClientFrame * ); + +/* Open the remainder of the current chunk as a group read context. +* This will be called just after the group's subtype ID has been read +* (automatically by GetChunkHdr for LIST, FORM, PROP, and CAT) so the +* remainder is a sequence of chunks. +* This sets new->clientFrame = parent->clientFrame. The caller should repoint +* it at a new clientFrame if opening a LIST context so it'll have a "stack +* frame" to store PROPs for the LIST. (It's usually convenient to also +* allocate a new Frame when you encounter FORM of the right type.) +* +* ASSUME new context allocated by caller but not initialized. +* ASSUME caller doesn't deallocate the context or access the parent context +* before calling CloseRGroup. +* BAD_IFF ERROR if context end is odd or extends past parent. */ +extern IFFP OpenRGroup(GroupContext *, GroupContext * ); +/* parent, new */ + +/* Close a group read context, updating its parent context. +* After calling this, the old context may be deallocated and the parent +* context can be accessed again. It's okay to call this particular procedure +* after an error has occurred reading the group. +* This always returns IFF_OKAY. */ +extern IFFP CloseRGroup( GroupContext * ); +/* old */ + +/* Skip any remaining bytes of the previous chunk and any padding, then +* read the next chunk header into context.ckHdr. +* If the ckID is LIST, FORM, CAT, or PROP, this automatically reads the +* subtype ID into context->subtype. +* Caller should dispatch on ckID (and subtype) to an appropriate handler. +* +* RETURNS context.ckHdr.ckID (the ID of the new chunk header); END_MARK +* if there are no more chunks in this context; or NOT_IFF if the top level +* file chunk isn't a FORM, LIST, or CAT; or BAD_IFF if malformed chunk, e.g. +* ckSize is negative or too big for containing context, ckID isn't positive, +* or we hit end-of-file. +* +* See also GetFChunkHdr, GetF1ChunkHdr, and GetPChunkHdr, below.*/ +extern ID GetChunkHdr(/* GroupContext * */); +/* context.ckHdr.ckID context */ + +/* Read nBytes number of data bytes of current chunk. (Use OpenGroup, etc. +* instead to read the contents of a group chunk.) You can call this several +* times to read the data piecemeal. +* CLIENT_ERROR if nBytes < 0. SHORT_CHUNK if nBytes > ChunkMoreBytes(context) +* which could be due to a client bug or a chunk that's shorter than it +* ought to be (bad form). (on either CLIENT_ERROR or SHORT_CHUNK, +* IFFReadBytes won't read any bytes.) */ +extern IFFP IFFReadBytes( GroupContext *, BYTE *, int ); +/* context, buffer, nBytes */ + + +/***** IFF File Reader *****/ + +/* This is a noop ClientProc that you can use for a getList, getForm, getProp, +* or getCat procedure that just skips the group. A simple reader might just +* implement getForm, store &ReadICat in the getCat field of clientFrame, and +* use &SkipGroup for the getList and getProp procs.*/ +extern IFFP SkipGroup( GroupContext* ); + +/* IFF file reader. +* Given an open file, allocate a group context and use it to read the FORM, +* LIST, or CAT and it's contents. The idea is to parse the file's contents, +* and for each FORM, LIST, CAT, or PROP encountered, call the getForm, +* getList, getCat, or getProp procedure in clientFrame, passing the +* GroupContext ptr. +* This is achieved with the aid of ReadIList (which your getList should +* call) and ReadICat (which your getCat should call, if you don't just use +* &ReadICat for your getCat). If you want to handle FORMs, LISTs, and CATs +* nested within FORMs, the getForm procedure must dispatch to getForm, +* getList, and getCat (it can use GetF1ChunkHdr to make this easy). +* +* Normal return is IFF_OKAY (if whole file scanned) or IFF_DONE (if a client +* proc said "done" first). +* See the skeletal getList, getForm, getCat, and getProp procedures. */ +extern IFFP ReadIFF( BPTR, ClientFrame * ); +/* file, clientFrame */ + +/* IFF LIST reader. +* Your "getList" procedure should allocate a ClientFrame, copy the parent's +* ClientFrame, and then call this procedure to do all the work. +* +* Normal return is IFF_OKAY (if whole LIST scanned) or IFF_DONE (if a client +* proc said "done" first). +* BAD_IFF ERROR if a PROP appears after a non-PROP. */ +extern IFFP ReadIList(GroupContext* parent, ClientFrame * clientFrame ); + +/* IFF CAT reader. +* Most clients can simply use this to read their CATs. If you must do extra +* setup work, put a ptr to your getCat procedure in the clientFrame, and +* have that procedure call ReadICat to do the detail work. +* +* Normal return is IFF_OKAY (if whole CAT scanned) or IFF_DONE (if a client +* proc said "done" first). +* BAD_IFF ERROR if a PROP appears in the CAT. */ +extern IFFP ReadICat( GroupContext * ); +/* parent */ + +/* Call GetFChunkHdr instead of GetChunkHdr to read each chunk inside a FORM. +* It just calls GetChunkHdr and returns BAD_IFF if it gets a PROP chunk. */ +extern ID GetFChunkHdr( GroupContext * ); +/* context.ckHdr.ckID context */ + +/* GetF1ChunkHdr is like GetFChunkHdr, but it automatically dispatches to the +* getForm, getList, and getCat procedure (and returns the result) if it +* encounters a FORM, LIST, or CAT. */ +extern ID GetF1ChunkHdr( GroupContext * ); +/* context.ckHdr.ckID context */ + +/* Call GetPChunkHdr instead of GetChunkHdr to read each chunk inside a PROP. +* It just calls GetChunkHdr and returns BAD_IFF if it gets a group chunk. */ +extern ID GetPChunkHdr( GroupContext * ); +/* context.ckHdr.ckID context */ + +/** endianSwap32/endianSwap16 convert integers from big endian to little endian on little-endian platforms. +* They have no effect on big-endian platforms +**/ +extern int endianSwap32(int value); +extern short int endianSwap16(short int value); + + + +/* ---------- IFF Writer -----------------------------------------------*/ + +/******* Routines to support a stream-oriented IFF file writer ******* +* +* These routines will random access back to set a chunk size value when the +* caller doesn't know it ahead of time. They'll also do things automatically +* like padding and error checking. +* +* These routines ASSUME they're the only ones writing to the file. +* Client should check IFFP error codes. Don't press on after an error! +* These routines try to have no side effects in the error case, except that +* partial I/O is sometimes unavoidable. +* +* All of these routines may return DOS_ERROR. In that case, ask DOS for the +* specific error code. +* +* The overall scheme is to open an output GroupContext via OpenWIFF or +* OpenWGroup, call either PutCk or {PutCkHdr {IFFWriteBytes}* PutCkEnd} for +* each chunk, then use CloseWGroup to close the GroupContext. +* +* To write a group (LIST, FORM, PROP, or CAT), call StartWGroup, write out +* its chunks, then call EndWGroup. StartWGroup automatically writes the +* group header and opens a nested context for writing the contents. +* EndWGroup closes the nested context and completes the group chunk. */ + + +/* Given a file open for output, open a write context. +* The "limit" arg imposes a fence or upper limit on the logical file +* position for writing data in this context. Pass in szNotYetKnown to be +* bounded only by disk capacity. +* ASSUME new context structure allocated by caller but not initialized. +* ASSUME caller doesn't deallocate the context before calling CloseWGroup. +* The caller is only allowed to write out one FORM, LIST, or CAT in this top +* level context (see StartWGroup and PutCkHdr). +* CLIENT_ERROR if limit is odd.*/ +extern IFFP OpenWIFF( BPTR, GroupContext *, int ); +/* file, new, limit {file position} */ + +/* Start writing a group (presumably LIST, FORM, PROP, or CAT), opening a +* nested context. The groupSize includes all nested chunks + the subtype ID. +* +* The subtype of a LIST or CAT is a hint at the contents' FORM type(s). Pass +* in FILLER if it's a mixture of different kinds. +* +* This writes the chunk header via PutCkHdr, writes the subtype ID via +* IFFWriteBytes, and calls OpenWGroup. The caller may then write the nested +* chunks and finish by calling EndWGroup. +* The OpenWGroup call sets new->clientFrame = parent->clientFrame. +* +* ASSUME new context structure allocated by caller but not initialized. +* ASSUME caller doesn't deallocate the context or access the parent context +* before calling CloseWGroup. +* ERROR conditions: See PutCkHdr, IFFWriteBytes, OpenWGroup. */ +extern IFFP StartWGroup( GroupContext *, int, int, int, GroupContext * ); +/* End a group started by StartWGroup. +* This just calls CloseWGroup and PutCkEnd. +* ERROR conditions: See CloseWGroup and PutCkEnd. */ +extern IFFP EndWGroup( GroupContext * ); +/* old */ + +/* Open the remainder of the current chunk as a group write context. +* This is normally only called by StartWGroup. +* +* Any fixed limit to this group chunk or a containing context will impose +* a limit on the new context. +* This will be called just after the group's subtype ID has been written +* so the remaining contents will be a sequence of chunks. +* This sets new->clientFrame = parent->clientFrame. +* ASSUME new context structure allocated by caller but not initialized. +* ASSUME caller doesn't deallocate the context or access the parent context +* before calling CloseWGroup. +* CLIENT_ERROR if context end is odd or PutCkHdr wasn't called first. */ +extern IFFP OpenWGroup( GroupContext *, GroupContext *); + + +/* Close a write context and update its parent context. +* This is normally only called by EndWGroup. +* +* If this is a top level context (created by OpenWIFF) we'll set the file's +* EOF (end of file) but won't close the file. +* After calling this, the old context may be deallocated and the parent +* context can be accessed again. +* +* Amiga DOS Note: There's no call to set the EOF. We just position to the +* desired end and return. Caller must Close file at that position. +* CLIENT_ERROR if PutCkEnd wasn't called first. */ +extern IFFP CloseWGroup( GroupContext * ); +/* old */ + +/* Write a whole chunk to a GroupContext. This writes a chunk header, ckSize +* data bytes, and (if needed) a pad byte. It also updates the GroupContext. +* CLIENT_ERROR if ckSize == szNotYetKnown. See also PutCkHdr errors. */ +extern IFFP PutCk( GroupContext *, ID, int, BYTE * ); +/* context, ckID, ckSize, *data */ + +/* Write just a chunk header. Follow this will any number of calls to +* IFFWriteBytes and finish with PutCkEnd. +* If you don't yet know how big the chunk is, pass in ckSize = szNotYetKnown, +* then PutCkEnd will set the ckSize for you later. +* Otherwise, IFFWriteBytes and PutCkEnd will ensure that the specified +* number of bytes get written. +* CLIENT_ERROR if the chunk would overflow the GroupContext's bound, if +* PutCkHdr was previously called without a matching PutCkEnd, if ckSize < 0 +* (except szNotYetKnown), if you're trying to write something other +* than one FORM, LIST, or CAT in a top level (file level) context, or +* if ckID <= 0 (these illegal ID values are used for error codes). */ +extern IFFP PutCkHdr( GroupContext* context, int ckID, int ckSize); + +/* Write nBytes number of data bytes for the current chunk and update +* GroupContext. +* CLIENT_ERROR if this would overflow the GroupContext's limit or the +* current chunk's ckSize, or if PutCkHdr wasn't called first, or if +* nBytes < 0. */ +extern IFFP IFFWriteBytes(GroupContext *context0, BYTE *data, int nBytes); + +/* Complete the current chunk, write a pad byte if needed, and update +* GroupContext. +* If current chunk's ckSize = szNotYetKnown, this goes back and sets the +* ckSize in the file. +* CLIENT_ERROR if PutCkHdr wasn't called first, or if client hasn't +* written 'ckSize' number of bytes with IFFWriteBytes. */ +extern IFFP PutCkEnd( GroupContext* context ); + +#endif diff --git a/Extras/iff/iffCheck/iffcheck.cpp b/Extras/iff/iffCheck/iffcheck.cpp new file mode 100644 index 0000000..a3cdfee --- /dev/null +++ b/Extras/iff/iffCheck/iffcheck.cpp @@ -0,0 +1,233 @@ +/*---------------------------------------------------------------------* +* IFFCheck.C Print out the structure of an IFF-85 file, 11/19/85 +* checking for structural errors. +* +* DO NOT USE THIS AS A SKELETAL PROGRAM FOR AN IFF READER! +* See ShowILBM.C for a skeletal example. +* +* Original version was for the Commodore-Amiga computer. +/* This version is compatible with PC, OSX, PS3, Wii, iPhone. 10/26/2008 +*----------------------------------------------------------------------*/ + +#include "iff.h" +#include "stdlib.h" //for exit + +/* ---------- IFFCheck -------------------------------------------------*/ +/* [TBD] More extensive checking could be done on the IDs encountered in the +* file. Check that the reserved IDs "FOR1".."FOR9", "LIS1".."LIS9", and +* "CAT1".."CAT9" aren't used. Check that reserved IDs aren't used as Form +* types. Check that all IDs are made of 4 printable characters (trailing +* spaces ok). */ + +typedef struct { + ClientFrame clientFrame; + int levels; /* # groups currently nested within.*/ +} Frame; + +char MsgOkay[] = { "----- (IFF_OKAY) A good IFF file." }; +char MsgEndMark[] = {"----- (END_MARK) How did you get this message??" }; +char MsgDone[] = { "----- (IFF_DONE) How did you get this message??" }; +char MsgDos[] = { "----- (DOS_ERROR) The DOS gave back an error." }; +char MsgNot[] = { "----- (NOT_IFF) not an IFF file." }; +char MsgNoFile[] = { "----- (NO_FILE) no such file found." }; +char MsgClientError[] = {"----- (CLIENT_ERROR) IFF Checker bug."}; +char MsgForm[] = { "----- (BAD_FORM) How did you get this message??" }; +char MsgShort[] = { "----- (SHORT_CHUNK) How did you get this message??" }; +char MsgBad[] = { "----- (BAD_IFF) a mangled IFF file." }; + +/* MUST GET THESE IN RIGHT ORDER!!*/ +char *IFFPMessages[-LAST_ERROR+1] = { + /*IFF_OKAY*/ MsgOkay, + /*END_MARK*/ MsgEndMark, + /*IFF_DONE*/ MsgDone, + /*DOS_ERROR*/ MsgDos, + /*NOT_IFF*/ MsgNot, + /*NO_FILE*/ MsgNoFile, + /*CLIENT_ERROR*/ MsgClientError, + /*BAD_FORM*/ MsgForm, + /*SHORT_CHUNK*/ MsgShort, + /*BAD_IFF*/ MsgBad +}; + +/* FORWARD REFERENCES */ +extern IFFP GetList(GroupContext*); +extern IFFP GetForm(GroupContext*); +extern IFFP GetProp(GroupContext*); +extern IFFP GetCat (GroupContext*); + +void IFFCheck(char *name) +{ + IFFP iffp; + BPTR file = fopen(name,"rb");//Open(name, MODE_OLDFILE); + Frame frame; + + frame.levels = 0; + frame.clientFrame.getList = GetList; + frame.clientFrame.getForm = GetForm; + frame.clientFrame.getProp = GetProp; + frame.clientFrame.getCat = GetCat ; + + printf("----- Checking file '%s' -----\n", name); + if (file == 0) + iffp = NO_FILE; + else + iffp = ReadIFF(file, (ClientFrame *)&frame); + + fclose(file); + printf("%s\n", IFFPMessages[-iffp]); +} + +int main(int argc, char **argv) +{ + if (argc != 1+1) { + printf("Usage: 'iffcheck filename'\n"); + exit(0); + } + IFFCheck(argv[1]); + return 0; +} + +/* ---------- Put... ---------------------------------------------------*/ + +void PutLevels(int count) +{ + for ( ; count > 0; --count) { + printf("."); + } +} + +void PutID(int id) +{ + long int i = 1; + const char *p = (const char *) &i; + if (p[0] == 1) // Lowest address contains the least significant byte + { + //little endian machine + printf("%c%c%c%c ", (char)(id&0x7f) , (char)(id>>8)&0x7f, + (char)(id>>16)&0x7f, (char)(id>>24)&0x7f); + } else + { + //big endian machine + printf("%c%c%c%c ", (char)(id>>24)&0x7f, (char)(id>>16)&0x7f, + (char)(id>>8)&0x7f, (char)(id&0x7f)); + } + /* printf("id = %lx", id); */ +} + +void PutN(long n) +{ + printf(" %ld ", n); +} + +/* Put something like "...BMHD 14" or "...LIST 14 PLBM". */ +void PutHdr(GroupContext *context) +{ + PutLevels( ((Frame *)context->clientFrame)->levels ); + PutID(context->ckHdr.ckID); + PutN(context->ckHdr.ckSize); + + if (context->subtype != NULL_CHUNK) + PutID(context->subtype); + + printf("\n"); +} + +/* ---------- AtLeaf ---------------------------------------------------*/ + +/* At Leaf chunk. That is, a chunk which does NOT contain other chunks. +* Print "int size".*/ +IFFP AtLeaf(GroupContext *context) +{ + + PutHdr(context); + /* A typical reader would read the chunk's contents, using the "Frame" + * for local data, esp. shared property settings (PROP).*/ + /* IFFReadBytes(context, ...buffer, context->ckHdr->ckSize); */ + return(IFF_OKAY); +} + +/* ---------- GetList --------------------------------------------------*/ +/* Handle a LIST chunk. Print "LIST size subTypeID". +* Then dive into it.*/ +IFFP GetList(GroupContext *parent) +{ + Frame newFrame; + + newFrame = *(Frame *)parent->clientFrame; /* copy parent's frame*/ + newFrame.levels++; + + PutHdr(parent); + + return( ReadIList(parent, (ClientFrame *)&newFrame) ); +} + +/* ---------- GetForm --------------------------------------------------*/ +/* Handle a FORM chunk. Print "FORM size subTypeID". +* Then dive into it.*/ +IFFP GetForm(GroupContext *parent) +{ + /*CompilerBug register*/ IFFP iffp; + GroupContext newptr; + Frame newFrame; + + newFrame = *(Frame *)parent->clientFrame; /* copy parent's frame*/ + newFrame.levels++; + + PutHdr(parent); + + iffp = OpenRGroup(parent, &newptr); + CheckIFFP(); + newptr.clientFrame = (ClientFrame *)&newFrame; + + /* FORM reader for Checker. */ + /* LIST, FORM, PROP, CAT already handled by GetF1ChunkHdr. */ + do {if ( (iffp = GetF1ChunkHdr(&newptr)) > 0 ) + iffp = AtLeaf(&newptr); + } while (iffp >= IFF_OKAY); + + CloseRGroup(&newptr); + return(iffp == END_MARK ? IFF_OKAY : iffp); +} + +/* ---------- GetProp --------------------------------------------------*/ +/* Handle a PROP chunk. Print "PROP size subTypeID". +* Then dive into it.*/ +IFFP GetProp(GroupContext *listContext) +{ + /*CompilerBug register*/ IFFP iffp; + GroupContext newptr; + + PutHdr(listContext); + + iffp = OpenRGroup(listContext, &newptr); + CheckIFFP(); + + /* PROP reader for Checker. */ + ((Frame *)listContext->clientFrame)->levels++; + + do {if ( (iffp = GetPChunkHdr(&newptr)) > 0 ) + iffp = AtLeaf(&newptr); + } while (iffp >= IFF_OKAY); + + ((Frame *)listContext->clientFrame)->levels--; + + CloseRGroup(&newptr); + return(iffp == END_MARK ? IFF_OKAY : iffp); +} + +/* ---------- GetCat ---------------------------------------------------*/ +/* Handle a CAT chunk. Print "CAT size subTypeID". +* Then dive into it.*/ +IFFP GetCat(GroupContext *parent) +{ + IFFP iffp; + + ((Frame *)parent->clientFrame)->levels++; + + PutHdr(parent); + + iffp = ReadICat(parent); + + ((Frame *)parent->clientFrame)->levels--; + return(iffp); +} diff --git a/Extras/iff/iffCreateTest/main.cpp b/Extras/iff/iffCreateTest/main.cpp new file mode 100644 index 0000000..6bf301a --- /dev/null +++ b/Extras/iff/iffCreateTest/main.cpp @@ -0,0 +1,236 @@ +/* +Test read and write IFF-85, Interchange Format File +Copyright (c) 2008 Erwin Coumans http://bulletphysics.com + +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. +*/ + +/* +* IFF Support routines for writing IFF-85 files. 12/02/85 +* (IFF is Interchange Format File.) +* By Jerry Morrison and Steve Shaw, Electronic Arts. +* This software is in the public domain. +* +*/ + +#include + +#include "iff.h" + +IFFP MyReadICat(GroupContext *parent) +{ + printf("Found and skipped a CAT\n"); + return 0; +} + +IFFP MySkipGroup( GroupContext * ) +{ + printf("Found and skipped a LIST\n"); + return 0; +} + +typedef UBYTE Masking; /* Choice of masking technique.*/ +typedef UBYTE Compression; /* Choice of compression algorithm applied to + + /* A BitMapHeader is stored in a BMHD chunk. */ +typedef struct { + + UWORD w, h; /* raster width & height in pixels */ + + WORD x, y; /* position for this image */ + UBYTE nPlanes; /* # source bitplanes */ + Masking masking; /* masking technique */ + Compression compression; /* compression algoithm */ + UBYTE pad1; /* UNUSED. For consistency, put 0 here.*/ + UWORD transparentColor; /* transparent "color number" */ + UBYTE xAspect, yAspect; /* aspect ratio, a rational number x/y */ + WORD pageWidth, pageHeight; /* source "page" size in pixels */ + +} BitMapHeader; + + +#define bufSz 512 +BYTE bodyBuffer[bufSz]; + +static void btSwap(char* a, char* b) +{ + char tmp = *a; + *a = *b; + *b = tmp; +}; + +#define ID_ILBM MakeID('I','L','B','M') +#define ID_BMHD MakeID('B','M','H','D') +#define ID_CMAP MakeID('C','M','A','P') +#define ID_BODY MakeID('B','O','D','Y') + +#define ID_DYNAWORLD MakeID('B','T','D','W') +#define ID_RIGIDBODY MakeID('B','T','R','B') +#define ID_SID MakeID('S','I','D',' ') +#define ID_MASS MakeID('M','A','S','S') +#define ID_SHAPE MakeID('S','H','A','P') + + +#define ID_COLOBJ MakeID('C','O','B','J') +#define ID_CUBE MakeID('C','U','B','E') +#define ID_DIMENSIONS MakeID('D','I','M','E') + + +IFFP MyProcessGroup(GroupContext *parent) +{ + /*compilerBug register*/ IFFP iffp; + GroupContext rigidbodyContext; + + BitMapHeader bmHeader; + bool foundBMHD = false; + + + if (parent->subtype != ID_ILBM) + return(IFF_OKAY); /* just continue scaning the file */ + + iffp = OpenRGroup(parent, &rigidbodyContext); + CheckIFFP(); + + do { + iffp = GetFChunkHdr(&rigidbodyContext); + if (iffp == ID_BMHD) { + printf("found ID_BMHD\n"); + foundBMHD = true; + + iffp = IFFReadBytes(&rigidbodyContext, (BYTE *)&bmHeader, (long)sizeof(BitMapHeader)); + //do endian swap + bmHeader.w = endianSwap16(bmHeader.w); + bmHeader.h = endianSwap16(bmHeader.h); + bmHeader.pageWidth = endianSwap16(bmHeader.pageWidth); + bmHeader.pageHeight = endianSwap16(bmHeader.pageHeight); + } + + else if (iffp == ID_CMAP) { + printf("found ID_CMAP\n"); + + // ilbmFrame.nColorRegs = maxColorReg; /* we have room for this many */ + // iffp = GetCMAP( + // &rigidbodyContext, (WORD *)&ilbmFrame.colorMap, &ilbmFrame.nColorRegs); + } + + else if (iffp == ID_BODY) + { + printf("found ID_BODY\n"); + if (!foundBMHD) + return BAD_FORM; + // if (!ilbmFrame.foundBMHD) return(BAD_FORM); /* No BMHD chunk! */ + + int moreBytes = ChunkMoreBytes(&rigidbodyContext); + while (moreBytes>0) + { + int curRead = moreBytes > bufSz? bufSz : moreBytes; + //read + iffp = IFFReadBytes(&rigidbodyContext, bodyBuffer, curRead); + moreBytes -= curRead; + + } + printf("remaining=%d\n",moreBytes); + if (iffp == IFF_OKAY) + iffp = IFF_DONE; /* Eureka */ + + + + // nPlanes = MIN(ilbmFrame.bmHdr.nPlanes, EXDepth); + } + + else if (iffp == END_MARK) + iffp = BAD_FORM; + + } while (iffp >= IFF_OKAY); /* loop if valid ID of ignored chunk or a + * subroutine returned IFF_OKAY (no errors).*/ + + if (iffp != IFF_DONE) return(iffp); + + /* If we get this far, there were no errors. */ + CloseRGroup(&rigidbodyContext); + return(iffp); +} + + + +#define CkErr(expression) {if (ifferr == IFF_OKAY) ifferr = (expression);} + + +int main(int argc, char* argv[]) +{ + FILE* file = 0; + + { + //Create and write an IFF file from scratch + file = fopen("test.iff","wb"); + + GroupContext fileContext; + GroupContext catContext; + + IFFP ifferr=0; + + ifferr = OpenWIFF(file, &fileContext, szNotYetKnown) ; + //ifferr = StartWGroup(&fileContext, CAT, szNotYetKnown, ID_DYNAWORLD, &catContext); + ifferr = StartWGroup(&fileContext, LIST, szNotYetKnown, ID_DYNAWORLD, &catContext); + + { + GroupContext rigidbodyPropContext; + ifferr = StartWGroup(&catContext, PROP, szNotYetKnown, ID_MASS, &rigidbodyPropContext); + float mass = 0.1f; + PutCk(&rigidbodyPropContext, ID_MASS, 4,(char*)&mass); + ifferr = EndWGroup(&rigidbodyPropContext) ; + + for (int i=0;i<3;i++) + { + GroupContext rigidbodyContext; + ifferr = StartWGroup(&catContext, FORM, szNotYetKnown, ID_RIGIDBODY, &rigidbodyContext); + char sidbuffer[]="rb1"; + + float dimensions[3] = {2,2,2}; + PutCk(&rigidbodyContext, ID_SID, 3,sidbuffer); + { + GroupContext shapeContext; + ifferr = StartWGroup(&rigidbodyContext, FORM, szNotYetKnown, ID_SHAPE, &shapeContext); + PutCk(&shapeContext, ID_CUBE, 4,(char*)&mass); + PutCk(&shapeContext, ID_DIMENSIONS, sizeof(dimensions),(char*)&dimensions); + ifferr = EndWGroup(&shapeContext) ; + } + ifferr = EndWGroup(&rigidbodyContext) ; + } + + } + ifferr = EndWGroup(&catContext) ; + ifferr = CloseWGroup(&fileContext); + + fclose(file); + } + + { + //show a very simple way to skim through an ILBM or general IFF file + //for more verbose feedback, use iffcheck.c + IFFP result; + //file = fopen("pe_3000_fall.iff","rb"); + file = fopen("test.iff","rb"); + + ClientFrame clientFrame; + + clientFrame.getList = MySkipGroup; + clientFrame.getProp = MySkipGroup; + clientFrame.getForm = MyProcessGroup; + clientFrame.getCat = MyReadICat ; + + result = ReadIFF(file,&clientFrame); + fclose(file); + } + + + return 0; +} diff --git a/Extras/iff/iffr.cpp b/Extras/iff/iffr.cpp new file mode 100644 index 0000000..82377e7 --- /dev/null +++ b/Extras/iff/iffr.cpp @@ -0,0 +1,370 @@ +/*----------------------------------------------------------------------* +* IFFR.C Support routines for reading IFF-85 files. 11/15/85 +* (IFF is Interchange Format File.) +* +* By Jerry Morrison and Steve Shaw, Electronic Arts. +* This software is in the public domain. +* +* Original version was for the Commodore-Amiga computer. +* This version is compatible with PC, OSX, PS3, Wii, iPhone. 10/26/2008 +*----------------------------------------------------------------------*/ + +#include "iff.h" +/* #include "DF1:iff/gio.h" */ +/* #define OFFSET_BEGINNING OFFSET_BEGINING */ + +/** Manx expects INTs as 16 bits, This wont matter on LAttice ***/ + + + +/* ---------- Read -----------------------------------------------------*/ + +extern int PutID(); /** Added as a diagnostic aid, will remove later ***/ + +/* ---------- OpenRIFF --------------------------------------------------*/ +IFFP OpenRIFF(BPTR file0, GroupContext *new0,ClientFrame *clientFrame) +{ + register BPTR file = file0; + register GroupContext *newtmp = new0; + IFFP iffp = IFF_OKAY; + + newtmp->parent = NL; /* "whole file" has no parent.*/ + newtmp->clientFrame = clientFrame; + newtmp->file = file; + newtmp->position = 0; + newtmp->ckHdr.ckID = newtmp->subtype = NULL_CHUNK; + newtmp->ckHdr.ckSize = newtmp->bytesSoFar = 0; + + /* Set newtmp->bound. AmigaDOS specific code.*/ + if (file <= 0) return(NO_FILE); + Seek(file, 0L, OFFSET_END); /* Seek to end of file.*/ + newtmp->bound = ftell(file);//Seek(file, 0L, OFFSET_CURRENT); /* Pos'n == #bytes in file.*/ + if (newtmp->bound < 0) return(DOS_ERROR); /* DOS being absurd.*/ + Seek(file, 0L, OFFSET_BEGINNING); /* Go to file start.*/ + /* Would just do this if Amiga DOS maintained fh_End: */ + /* newtmp->bound = (FileHandle *)BADDR(file)->fh_End; */ + + if ( newtmp->bound < (long)sizeof(ChunkHeader) ) + iffp = NOT_IFF; + return(iffp); +} + +/* ---------- OpenRGroup -----------------------------------------------*/ +IFFP OpenRGroup(GroupContext* parent0,GroupContext* new0) +{ + register GroupContext *parent = parent0; + register GroupContext *newtmp = new0; + IFFP iffp = IFF_OKAY; + + newtmp->parent = parent; + newtmp->clientFrame = parent->clientFrame; + newtmp->file = parent->file; + newtmp->position = parent->position; + newtmp->bound = parent->position + ChunkMoreBytes(parent); + newtmp->ckHdr.ckID = newtmp->subtype = NULL_CHUNK; + newtmp->ckHdr.ckSize = newtmp->bytesSoFar = 0; + + if ( newtmp->bound > parent->bound || IS_ODD(newtmp->bound) ) + iffp = BAD_IFF; + return(iffp); +} + +/* ---------- CloseRGroup -----------------------------------------------*/ +IFFP CloseRGroup(GroupContext *context) +{ + register int position; + + if (context->parent == NL) { + } /* Context for whole file.*/ + else { + position = context->position; + context->parent->bytesSoFar += position - context->parent->position; + context->parent->position = position; + } + return(IFF_OKAY); +} + +/* ---------- SkipFwd --------------------------------------------------*/ +/* Skip over bytes in a context. Won't go backwards.*/ +/* Updates context->position but not context->bytesSoFar.*/ +/* This implementation is AmigaDOS specific.*/ +IFFP SkipFwd(GroupContext *context,int bytes) +{ + IFFP iffp = IFF_OKAY; + + if (bytes > 0) { + if (-1 == Seek(context->file, bytes, OFFSET_CURRENT)) + iffp = BAD_IFF; /* Ran out of bytes before chunk complete.*/ + else + context->position += bytes; + } + return(iffp); +} + +short int endianSwap16(short int val) +{ + long int i = 1; + const char *p = (const char *) &i; + if (p[0] == 1) // Lowest address contains the least significant byte + { + return (((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)); + } + return val; +} + + + +int endianSwap32(int val) +{ + long int i = 1; + const char *p = (const char *) &i; + if (p[0] == 1) // Lowest address contains the least significant byte + { + return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); + } + return val; +} + + + + + +/* ---------- GetChunkHdr ----------------------------------------------*/ +int GetChunkHdr(GroupContext *context0) +{ + register GroupContext *context = context0; + register IFFP iffp; + int remaining; + + /* Skip remainder of previous chunk & padding. */ + iffp = SkipFwd(context, + ChunkMoreBytes(context) + IS_ODD(context->ckHdr.ckSize)); + CheckIFFP(); + + /* Set up to read the newtmp header. */ + context->ckHdr.ckID = BAD_IFF; /* Until we know it's okay, mark it BAD.*/ + context->subtype = NULL_CHUNK; + context->bytesSoFar = 0; + + /* Generate a psuedo-chunk if at end-of-context. */ + remaining = context->bound - context->position; + if (remaining == 0 ) { + context->ckHdr.ckSize = 0; + context->ckHdr.ckID = END_MARK; + } + /* BAD_IFF if not enough bytes in the context for a ChunkHeader.*/ + else if ((long)sizeof(ChunkHeader) > remaining) { + context->ckHdr.ckSize = remaining; + } + + /* Read the chunk header (finally). */ + else { + switch (Read(context->file, + &context->ckHdr, (long)sizeof(ChunkHeader))) + { + case -1: return(context->ckHdr.ckID = DOS_ERROR); + case 0: return(context->ckHdr.ckID = BAD_IFF); + } + //swap endian-ness of ckSize on little endian machines + context->ckHdr.ckSize = endianSwap32(context->ckHdr.ckSize); + + + + + /*** $$$ *** + PutID(context->ckHdr.ckID); + printf("\n"); + printf("id = %lx\n", context->ckHdr.ckID); + **/ + + /* Check: Top level chunk must be LIST or FORM or CAT. */ + if (context->parent == NL) { + if (context->ckHdr.ckID != FORM && + context->ckHdr.ckID != LIST && + context->ckHdr.ckID != CAT ) + return(context->ckHdr.ckID = NOT_IFF); + } + + /* Update the context. */ + context->position += (long)sizeof(ChunkHeader); + remaining -= (long)sizeof(ChunkHeader); + + /* Non-positive int values are illegal and used for error codes.*/ + /* We could check for other illegal IDs...*/ + if (context->ckHdr.ckID <= 0 ) + context->ckHdr.ckID = BAD_IFF; + + /* Check: ckSize negative or larger than # bytes left in context? */ + else if (context->ckHdr.ckSize < 0 || + context->ckHdr.ckSize > remaining) { + context->ckHdr.ckSize = remaining; + context->ckHdr.ckID = BAD_IFF; + } + + /* Automatically read the LIST, FORM, PROP, or CAT subtype int */ + else { + if (context->ckHdr.ckID == LIST || + context->ckHdr.ckID == FORM || + context->ckHdr.ckID == PROP || + context->ckHdr.ckID == CAT) { + iffp = IFFReadBytes(context, (BYTE *)&context->subtype, + (long)sizeof(int)); + if (iffp != IFF_OKAY ) + context->ckHdr.ckID = iffp; + } + } + } + return(context->ckHdr.ckID); +} + +/* ---------- IFFReadBytes ---------------------------------------------*/ +IFFP IFFReadBytes(GroupContext *context,BYTE *buffer, int nBytes) +{ + register IFFP iffp = IFF_OKAY; + + if (nBytes < 0) + iffp = CLIENT_ERROR; + + else if (nBytes > ChunkMoreBytes(context)) + iffp = SHORT_CHUNK; + + else if (nBytes > 0 ) + switch ( Read(context->file, buffer, nBytes) ) { + case -1: {iffp = DOS_ERROR; break; } + case 0: {iffp = BAD_IFF; break; } + default: { + context->position += nBytes; + context->bytesSoFar += nBytes; + } + } + return(iffp); +} + +/* ---------- SkipGroup ------------------------------------------------*/ +IFFP SkipGroup( GroupContext* context) +{ + return 0; +} /* Nothing to do, thanks to GetChunkHdr */ + +/* ---------- ReadIFF --------------------------------------------------*/ +IFFP ReadIFF(BPTR file,ClientFrame *clientFrame) +{ + /*CompilerBug register*/ IFFP iffp; + GroupContext context; + + iffp = OpenRIFF(file, &context,clientFrame); + context.clientFrame = clientFrame; + + if (iffp == IFF_OKAY) { + iffp = GetChunkHdr(&context); + + if (iffp == FORM) + iffp = (*clientFrame->getForm)(&context); + + else if (iffp == LIST) + iffp = (*clientFrame->getList)(&context); + + else if (iffp == CAT) + iffp = (*clientFrame->getCat)(&context); + } + CloseRGroup(&context); + + if (iffp > 0 ) /* Make sure we don't return an int.*/ + iffp = NOT_IFF; /* GetChunkHdr should've caught this.*/ + return(iffp); +} + +/* ---------- ReadIList ------------------------------------------------*/ +IFFP ReadIList(GroupContext *parent,ClientFrame *clientFrame) +{ + GroupContext listContext; + IFFP iffp; + BOOL propOk = TRUE; + + iffp = OpenRGroup(parent, &listContext); + CheckIFFP(); + + /* One special case test lets us handle CATs as well as LISTs.*/ + if (parent->ckHdr.ckID == CAT) + propOk = FALSE; + else + listContext.clientFrame = clientFrame; + + do { + iffp = GetChunkHdr(&listContext); + if (iffp == PROP) { + if (propOk) + iffp = (*clientFrame->getProp)(&listContext); + else + iffp = BAD_IFF; + } + else if (iffp == FORM) + iffp = (*clientFrame->getForm)(&listContext); + + else if (iffp == LIST) + iffp = (*clientFrame->getList)(&listContext); + + else if (iffp == CAT) + iffp = (*clientFrame->getList)(&listContext); + + if (listContext.ckHdr.ckID != PROP) + propOk = FALSE; /* No PROPs allowed after this point.*/ + } while (iffp == IFF_OKAY); + + CloseRGroup(&listContext); + + if (iffp > 0 ) /* Only chunk types above are allowed in a LIST/CAT.*/ + iffp = BAD_IFF; + return(iffp == END_MARK ? IFF_OKAY : iffp); +} + +/* ---------- ReadICat -------------------------------------------------*/ +/* By special arrangement with the ReadIList implement'n, this is trivial.*/ +IFFP ReadICat(GroupContext *parent) +{ + return( ReadIList(parent, parent->clientFrame));//NL) ); +} + +/* ---------- GetFChunkHdr ---------------------------------------------*/ +int GetFChunkHdr(GroupContext *context) +{ + register int id; + + id = GetChunkHdr(context); + if (id == PROP) + context->ckHdr.ckID = id = BAD_IFF; + return(id); +} + +/* ---------- GetF1ChunkHdr ---------------------------------------------*/ +int GetF1ChunkHdr(GroupContext *context) +{ + register int id; + register ClientFrame *clientFrame = context->clientFrame; + + id = GetChunkHdr(context); + if (id == PROP) + id = BAD_IFF; + + else if (id == FORM) + id = (*clientFrame->getForm)(context); + + else if (id == LIST) + id = (*clientFrame->getForm)(context); + + else if (id == CAT) + id = (*clientFrame->getCat)(context); + + return(context->ckHdr.ckID = id); +} + +/* ---------- GetPChunkHdr ---------------------------------------------*/ +int GetPChunkHdr(GroupContext *context) +{ + register int id; + + id = GetChunkHdr(context); + if (id == LIST || id == FORM || id == PROP || id == CAT ) + id = context->ckHdr.ckID = BAD_IFF; + return(id); +} diff --git a/Extras/iff/iffw.cpp b/Extras/iff/iffw.cpp new file mode 100644 index 0000000..0e66f8a --- /dev/null +++ b/Extras/iff/iffw.cpp @@ -0,0 +1,243 @@ +/*----------------------------------------------------------------------* +* IFFW.C Support routines for writing IFF-85 files. 12/02/85 +* (IFF is Interchange Format File.) +* +* By Jerry Morrison and Steve Shaw, Electronic Arts. +* This software is in the public domain. +* +* Original version was for the Commodore-Amiga computer. +* This version is compatible with PC, OSX, PS3, Wii, iPhone. 10/26/2008 +*----------------------------------------------------------------------*/ +#include "iff.h" + + + + +/* ---------- IFF Writer -----------------------------------------------*/ + +/* A macro to test if a chunk size is definite, i.e. not szNotYetKnown.*/ +#define Known(size) ( (size) != szNotYetKnown ) + +/* Yet another weird macro to make the source code simpler...*/ +#define IfIffp(expr) {if (iffp == IFF_OKAY) iffp = (expr);} + +/* ---------- OpenWIFF -------------------------------------------------*/ + +IFFP OpenWIFF(BPTR file, GroupContext *new0, int limit) +{ + register GroupContext *newtmp = new0; + register IFFP iffp = IFF_OKAY; + + newtmp->parent = NULL; + newtmp->clientFrame = NULL; + newtmp->file = file; + newtmp->position = 0; + newtmp->bound = limit; + newtmp->ckHdr.ckID = NULL_CHUNK; /* indicates no current chunk */ + newtmp->ckHdr.ckSize = newtmp->bytesSoFar = 0; + + if (0 > Seek(file, 0, OFFSET_BEGINNING)) /* Go to start of the file.*/ + iffp = DOS_ERROR; + else if ( Known(limit) && IS_ODD(limit) ) + iffp = CLIENT_ERROR; + return(iffp); +} + +/* ---------- StartWGroup ----------------------------------------------*/ +IFFP StartWGroup( GroupContext* parent, int groupType,int groupSize,int subtype, GroupContext * newtmp) +{ + register IFFP iffp; + + iffp = PutCkHdr(parent, groupType, groupSize); + IfIffp( IFFWriteBytes(parent, (char *)&subtype, sizeof(int)) ); + IfIffp( OpenWGroup(parent, newtmp) ); + return(iffp); +} + +/* ---------- OpenWGroup -----------------------------------------------*/ +IFFP OpenWGroup(GroupContext *parent0,GroupContext* new0) +{ + register GroupContext *parent = parent0; + register GroupContext *newtmp = new0; + register int ckEnd; + register IFFP iffp = IFF_OKAY; + + newtmp->parent = parent; + newtmp->clientFrame = parent->clientFrame; + newtmp->file = parent->file; + newtmp->position = parent->position; + newtmp->bound = parent->bound; + newtmp->ckHdr.ckID = NULL_CHUNK; + newtmp->ckHdr.ckSize = newtmp->bytesSoFar = 0; + + if ( Known(parent->ckHdr.ckSize) ) { + ckEnd = newtmp->position + ChunkMoreBytes(parent); + if ( newtmp->bound == szNotYetKnown || newtmp->bound > ckEnd ) + newtmp->bound = ckEnd; + }; + + if ( parent->ckHdr.ckID == NULL_CHUNK || /* not currently writing a chunk*/ + IS_ODD(newtmp->position) || + (Known(newtmp->bound) && IS_ODD(newtmp->bound)) ) + iffp = CLIENT_ERROR; + return(iffp); +} + +/* ---------- CloseWGroup ----------------------------------------------*/ +IFFP CloseWGroup(GroupContext *old0) +{ + register GroupContext *old = old0; + + if ( old->ckHdr.ckID != NULL_CHUNK ) /* didn't close the last chunk */ + return(CLIENT_ERROR); + + if ( old->parent == NULL ) { /* top level file context */ + GWriteFlush(old->file); + } + else { + old->parent->bytesSoFar += old->position - old->parent->position; + old->parent->position = old->position; + }; + return(IFF_OKAY); +} + +/* ---------- EndWGroup ------------------------------------------------*/ +IFFP EndWGroup(GroupContext *old) +{ + register GroupContext *parent = old->parent; + register IFFP iffp; + + + iffp = CloseWGroup(old); + IfIffp( PutCkEnd(parent) ); + return(iffp); +} + +/* ---------- PutCk ----------------------------------------------------*/ +IFFP PutCk(GroupContext *context, int ckID,int ckSize,char *data) +{ + register IFFP iffp = IFF_OKAY; + + if ( ckSize == szNotYetKnown ) + iffp = CLIENT_ERROR; + IfIffp( PutCkHdr(context, ckID, ckSize) ); + IfIffp( IFFWriteBytes(context, data, ckSize) ); + IfIffp( PutCkEnd(context) ); + return(iffp); +} + +/* ---------- PutCkHdr -------------------------------------------------*/ +IFFP PutCkHdr(GroupContext *context0, int ckID, int ckSize) +{ + register GroupContext *context = context0; + int minPSize = sizeof(ChunkHeader); /* physical chunk >= minPSize bytes*/ + + /* CLIENT_ERROR if we're already inside a chunk or asked to write + * other than one FORM, LIST, or CAT at the top level of a file */ + /* Also, non-positive int values are illegal and used for error codes.*/ + /* (We could check for other illegal IDs...)*/ + if ( context->ckHdr.ckID != NULL_CHUNK || ckID <= 0 ) + return(CLIENT_ERROR); + else if (context->parent == NULL) { + switch (ckID) { + case FORM: case LIST: case CAT: break; + default: return(CLIENT_ERROR); + } + if (context->position != 0) + return(CLIENT_ERROR); + } + + if ( Known(ckSize) ) { + if ( ckSize < 0 ) + return(CLIENT_ERROR); + minPSize += ckSize; + }; + if ( Known(context->bound) && + context->position + minPSize > context->bound ) + return(CLIENT_ERROR); + + context->ckHdr.ckID = ckID; + context->ckHdr.ckSize = ckSize; + context->bytesSoFar = 0; + { + context->ckHdr.ckSize = endianSwap32(context->ckHdr.ckSize); + if (0 > fwrite(&context->ckHdr, 1,sizeof(ChunkHeader),context->file)) + return(DOS_ERROR); + context->ckHdr.ckSize = endianSwap32(context->ckHdr.ckSize); + } + context->position += sizeof(ChunkHeader); + return(IFF_OKAY); +} + +/* ---------- IFFWriteBytes ---------------------------------------------*/ +IFFP IFFWriteBytes(GroupContext *context0, char *data, int nBytes) +{ + register GroupContext *context = context0; + + if ( context->ckHdr.ckID == NULL_CHUNK || /* not in a chunk */ + nBytes < 0 || /* negative nBytes */ + (Known(context->bound) && /* overflow context */ + context->position + nBytes > context->bound) || + (Known(context->ckHdr.ckSize) && /* overflow chunk */ + context->bytesSoFar + nBytes > context->ckHdr.ckSize) ) + { + return(CLIENT_ERROR); + } + + if (0 > fwrite(data, 1,nBytes,context->file)) + return(DOS_ERROR); + + context->bytesSoFar += nBytes; + context->position += nBytes; + return(IFF_OKAY); +} + +/* ---------- PutCkEnd -------------------------------------------------*/ +IFFP PutCkEnd(GroupContext *context0) +{ + register GroupContext *context = context0; + WORD zero = 0; /* padding source */ + + if ( context->ckHdr.ckID == NULL_CHUNK ) /* not in a chunk */ + return(CLIENT_ERROR); + + if ( context->ckHdr.ckSize == szNotYetKnown ) { + /* go back and set the chunk size to bytesSoFar */ + int offset = context->bytesSoFar+sizeof(int); + if ( 0 > GSeek(context->file, + -(offset), + OFFSET_CURRENT)) + { + return(DOS_ERROR); + } else + { + context->bytesSoFar = endianSwap32(context->bytesSoFar); + if (0 > fwrite(&context->bytesSoFar, 1,sizeof(int),context->file)) + return (DOS_ERROR); + context->bytesSoFar = endianSwap32(context->bytesSoFar); + if (0 > GSeek(context->file, context->bytesSoFar, OFFSET_CURRENT) ) + return (DOS_ERROR); + } + + + } + else { /* make sure the client wrote as many bytes as planned */ + if ( context->ckHdr.ckSize != context->bytesSoFar ) + return(CLIENT_ERROR); + }; + + /* Write a pad byte if needed to bring us up to an even boundary. + * Since the context end must be even, and since we haven't + * overwritten the context, if we're on an odd position there must + * be room for a pad byte. */ + if ( IS_ODD(context->bytesSoFar) ) { + if ( 0 > fwrite(&zero, 1,1,context->file) ) + return(DOS_ERROR); + context->position += 1; + }; + + context->ckHdr.ckID = NULL_CHUNK; + context->ckHdr.ckSize = context->bytesSoFar = 0; + return(IFF_OKAY); +} + diff --git a/Extras/khx2dae/Bullet_dae_screenshot.jpg b/Extras/khx2dae/Bullet_dae_screenshot.jpg new file mode 100644 index 0000000000000000000000000000000000000000..37987fb7635efb54074ebb0ebc55fe5f91b89bea GIT binary patch literal 18301 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 + + + + Bullet Physics SDK 269 Snapshot(BulletColladaConverter) http://bulletphysics.com + + 2008-02-12T15:28:54.891550 + 2008-02-12T15:28:54.891550 + Y_UP + + + + + + + 0 0 0 + 0 0 0 + + + + + 0 0 0 + 0 0 0 + + + + + 0 0 0 + 0 0 0 + + + + + 0 0 0 + 0 0 0 + + + + + 0 0 0 + 0 0 0 + + + + + 0 0 0 + 0 0 0 + + + + + 0 0 0 + 0 0 0 + + + + + + + 0 -10 0 + + + + + + + 3.05176e-007 1.5 0 + 1 0 0 0 + + + + + + + + 0 0 0 + 1 0 0 0 + + + + + + + + 0 6.11808 0 + 1 0 0 0 + + + + + + + + 0 7.86898 0 + 1 0 0 0 + + + + + + + + 0.52094 9.75749 0.301791 + 1 0 0 0 + + + + + + + + 0 3.05235 -0.561565 + 1 0 0 0 + + + + + + + + 0 3.05235 1.07583 + 1 0 0 0 + + + + + + + + + + + + + 1.05801 1 1.45623 1.05801 -1 1.45623 0.556231 1 1.7119 0.556231 1 1.7119 1.05801 -1 1.45623 0.556231 -1 1.7119 0.556231 1 1.7119 0.556231 -1 1.7119 1.78647e-008 1 1.8 1.78647e-008 1 1.8 0.556231 -1 1.7119 1.78647e-008 -1 1.8 1.78647e-008 1 1.8 1.78647e-008 -1 1.8 -0.556231 1 1.7119 -0.556231 1 1.7119 1.78647e-008 -1 1.8 -0.556231 -1 1.7119 -0.556231 1 1.7119 -0.556231 -1 1.7119 -1.05801 1 1.45623 -1.05801 1 1.45623 -0.556231 -1 1.7119 -1.05801 -1 1.45623 -1.05801 1 1.45623 -1.05801 -1 1.45623 -1.45623 1 1.05801 -1.45623 1 1.05801 -1.05801 -1 1.45623 -1.45623 -1 1.05801 -1.45623 1 1.05801 -1.45623 -1 1.05801 -1.7119 1 0.556231 -1.7119 1 0.556231 -1.45623 -1 1.05801 -1.7119 -1 0.556231 -1.7119 1 0.556231 -1.7119 -1 0.556231 -1.8 1 -3.05784e-008 -1.8 1 -3.05784e-008 -1.7119 -1 0.556231 -1.8 -1 -3.05784e-008 -1.8 1 -3.05784e-008 -1.8 -1 -3.05784e-008 -1.7119 1 -0.556231 -1.7119 1 -0.556231 -1.8 -1 -3.05784e-008 -1.7119 -1 -0.556231 -1.7119 1 -0.556231 -1.7119 -1 -0.556231 -1.45623 1 -1.05801 -1.45623 1 -1.05801 -1.7119 -1 -0.556231 -1.45623 -1 -1.05801 -1.45623 1 -1.05801 -1.45623 -1 -1.05801 -1.05801 1 -1.45623 -1.05801 1 -1.45623 -1.45623 -1 -1.05801 -1.05801 -1 -1.45623 -1.05801 1 -1.45623 -1.05801 -1 -1.45623 -0.556231 1 -1.7119 -0.556231 1 -1.7119 -1.05801 -1 -1.45623 -0.556231 -1 -1.7119 -0.556231 1 -1.7119 -0.556231 -1 -1.7119 1.27137e-008 1 -1.8 1.27137e-008 1 -1.8 -0.556231 -1 -1.7119 1.27137e-008 -1 -1.8 1.27137e-008 1 -1.8 1.27137e-008 -1 -1.8 0.556231 1 -1.7119 0.556231 1 -1.7119 1.27137e-008 -1 -1.8 0.556231 -1 -1.7119 0.556231 1 -1.7119 0.556231 -1 -1.7119 1.05801 1 -1.45623 1.05801 1 -1.45623 0.556231 -1 -1.7119 1.05801 -1 -1.45623 1.05801 1 -1.45623 1.05801 -1 -1.45623 1.45623 1 -1.05801 1.45623 1 -1.05801 1.05801 -1 -1.45623 1.45623 -1 -1.05801 1.45623 1 -1.05801 1.45623 -1 -1.05801 1.7119 1 -0.556231 1.7119 1 -0.556231 1.45623 -1 -1.05801 1.7119 -1 -0.556231 1.8 -1 0 1.8 1 0 1.7119 -1 -0.556231 1.7119 -1 -0.556231 1.8 1 0 1.7119 1 -0.556231 1.8 1 0 1.8 -1 0 1.7119 1 0.556231 1.7119 1 0.556231 1.8 -1 0 1.7119 -1 0.556231 1.7119 1 0.556231 1.7119 -1 0.556231 1.45623 1 1.05801 1.45623 1 1.05801 1.7119 -1 0.556231 1.45623 -1 1.05801 1.45623 1 1.05801 1.45623 -1 1.05801 1.05801 1 1.45623 1.05801 1 1.45623 1.45623 -1 1.05801 1.05801 -1 1.45623 1.7119 1 -0.556231 1.8 1 0 1.90211 1 -0.618034 1.90211 1 -0.618034 1.8 1 0 2 1 0 1.8 1 0 1.7119 1 0.556231 2 1 0 2 1 0 1.7119 1 0.556231 1.90211 1 0.618034 1.7119 1 0.556231 1.45623 1 1.05801 1.90211 1 0.618034 1.90211 1 0.618034 1.45623 1 1.05801 1.61803 1 1.17557 1.45623 1 1.05801 1.05801 1 1.45623 1.61803 1 1.17557 1.61803 1 1.17557 1.05801 1 1.45623 1.17557 1 1.61803 1.05801 1 1.45623 0.556231 1 1.7119 1.17557 1 1.61803 1.17557 1 1.61803 0.556231 1 1.7119 0.618034 1 1.90211 0.556231 1 1.7119 1.78647e-008 1 1.8 0.618034 1 1.90211 0.618034 1 1.90211 1.78647e-008 1 1.8 1.98497e-008 1 2 1.78647e-008 1 1.8 -0.556231 1 1.7119 1.98497e-008 1 2 1.98497e-008 1 2 -0.556231 1 1.7119 -0.618034 1 1.90211 -0.556231 1 1.7119 -1.05801 1 1.45623 -0.618034 1 1.90211 -0.618034 1 1.90211 -1.05801 1 1.45623 -1.17557 1 1.61803 -1.05801 1 1.45623 -1.45623 1 1.05801 -1.17557 1 1.61803 -1.17557 1 1.61803 -1.45623 1 1.05801 -1.61803 1 1.17557 -1.45623 1 1.05801 -1.7119 1 0.556231 -1.61803 1 1.17557 -1.61803 1 1.17557 -1.7119 1 0.556231 -1.90211 1 0.618034 -1.7119 1 0.556231 -1.8 1 -3.05784e-008 -1.90211 1 0.618034 -1.90211 1 0.618034 -1.8 1 -3.05784e-008 -2 1 -3.3976e-008 -1.8 1 -3.05784e-008 -1.7119 1 -0.556231 -2 1 -3.3976e-008 -2 1 -3.3976e-008 -1.7119 1 -0.556231 -1.90211 1 -0.618034 -1.7119 1 -0.556231 -1.45623 1 -1.05801 -1.90211 1 -0.618034 -1.90211 1 -0.618034 -1.45623 1 -1.05801 -1.61803 1 -1.17557 -1.45623 1 -1.05801 -1.05801 1 -1.45623 -1.61803 1 -1.17557 -1.61803 1 -1.17557 -1.05801 1 -1.45623 -1.17557 1 -1.61803 -1.05801 1 -1.45623 -0.556231 1 -1.7119 -1.17557 1 -1.61803 -1.17557 1 -1.61803 -0.556231 1 -1.7119 -0.618034 1 -1.90211 -0.556231 1 -1.7119 1.27137e-008 1 -1.8 -0.618034 1 -1.90211 -0.618034 1 -1.90211 1.27137e-008 1 -1.8 1.41263e-008 1 -2 1.27137e-008 1 -1.8 0.556231 1 -1.7119 1.41263e-008 1 -2 1.41263e-008 1 -2 0.556231 1 -1.7119 0.618034 1 -1.90211 0.556231 1 -1.7119 1.05801 1 -1.45623 0.618034 1 -1.90211 0.618034 1 -1.90211 1.05801 1 -1.45623 1.17557 1 -1.61803 1.05801 1 -1.45623 1.45623 1 -1.05801 1.17557 1 -1.61803 1.17557 1 -1.61803 1.45623 1 -1.05801 1.61803 1 -1.17557 1.45623 1 -1.05801 1.7119 1 -0.556231 1.61803 1 -1.17557 1.61803 1 -1.17557 1.7119 1 -0.556231 1.90211 1 -0.618034 1.8 -1 0 1.7119 -1 -0.556231 2 -1 0 2 -1 0 1.7119 -1 -0.556231 1.90211 -1 -0.618034 1.7119 -1 0.556231 1.8 -1 0 1.90211 -1 0.618034 1.90211 -1 0.618034 1.8 -1 0 2 -1 0 1.45623 -1 1.05801 1.7119 -1 0.556231 1.61803 -1 1.17557 1.61803 -1 1.17557 1.7119 -1 0.556231 1.90211 -1 0.618034 1.05801 -1 1.45623 1.45623 -1 1.05801 1.17557 -1 1.61803 1.17557 -1 1.61803 1.45623 -1 1.05801 1.61803 -1 1.17557 0.556231 -1 1.7119 1.05801 -1 1.45623 0.618034 -1 1.90211 0.618034 -1 1.90211 1.05801 -1 1.45623 1.17557 -1 1.61803 1.78647e-008 -1 1.8 0.556231 -1 1.7119 1.98497e-008 -1 2 1.98497e-008 -1 2 0.556231 -1 1.7119 0.618034 -1 1.90211 -0.556231 -1 1.7119 1.78647e-008 -1 1.8 -0.618034 -1 1.90211 -0.618034 -1 1.90211 1.78647e-008 -1 1.8 1.98497e-008 -1 2 -1.05801 -1 1.45623 -0.556231 -1 1.7119 -1.17557 -1 1.61803 -1.17557 -1 1.61803 -0.556231 -1 1.7119 -0.618034 -1 1.90211 -1.45623 -1 1.05801 -1.05801 -1 1.45623 -1.61803 -1 1.17557 -1.61803 -1 1.17557 -1.05801 -1 1.45623 -1.17557 -1 1.61803 -1.7119 -1 0.556231 -1.45623 -1 1.05801 -1.90211 -1 0.618034 -1.90211 -1 0.618034 -1.45623 -1 1.05801 -1.61803 -1 1.17557 -1.8 -1 -3.05784e-008 -1.7119 -1 0.556231 -2 -1 -3.3976e-008 -2 -1 -3.3976e-008 -1.7119 -1 0.556231 -1.90211 -1 0.618034 -1.7119 -1 -0.556231 -1.8 -1 -3.05784e-008 -1.90211 -1 -0.618034 -1.90211 -1 -0.618034 -1.8 -1 -3.05784e-008 -2 -1 -3.3976e-008 -1.45623 -1 -1.05801 -1.7119 -1 -0.556231 -1.61803 -1 -1.17557 -1.61803 -1 -1.17557 -1.7119 -1 -0.556231 -1.90211 -1 -0.618034 -1.05801 -1 -1.45623 -1.45623 -1 -1.05801 -1.17557 -1 -1.61803 -1.17557 -1 -1.61803 -1.45623 -1 -1.05801 -1.61803 -1 -1.17557 -0.556231 -1 -1.7119 -1.05801 -1 -1.45623 -0.618034 -1 -1.90211 -0.618034 -1 -1.90211 -1.05801 -1 -1.45623 -1.17557 -1 -1.61803 1.27137e-008 -1 -1.8 -0.556231 -1 -1.7119 1.41263e-008 -1 -2 1.41263e-008 -1 -2 -0.556231 -1 -1.7119 -0.618034 -1 -1.90211 0.556231 -1 -1.7119 1.27137e-008 -1 -1.8 0.618034 -1 -1.90211 0.618034 -1 -1.90211 1.27137e-008 -1 -1.8 1.41263e-008 -1 -2 1.05801 -1 -1.45623 0.556231 -1 -1.7119 1.17557 -1 -1.61803 1.17557 -1 -1.61803 0.556231 -1 -1.7119 0.618034 -1 -1.90211 1.45623 -1 -1.05801 1.05801 -1 -1.45623 1.61803 -1 -1.17557 1.61803 -1 -1.17557 1.05801 -1 -1.45623 1.17557 -1 -1.61803 1.7119 -1 -0.556231 1.45623 -1 -1.05801 1.90211 -1 -0.618034 1.90211 -1 -0.618034 1.45623 -1 -1.05801 1.61803 -1 -1.17557 2 -1 0 1.90211 -1 -0.618034 2 1 0 2 1 0 1.90211 -1 -0.618034 1.90211 1 -0.618034 1.90211 -1 0.618034 2 -1 0 1.90211 1 0.618034 1.90211 1 0.618034 2 -1 0 2 1 0 1.61803 -1 1.17557 1.90211 -1 0.618034 1.61803 1 1.17557 1.61803 1 1.17557 1.90211 -1 0.618034 1.90211 1 0.618034 1.17557 -1 1.61803 1.61803 -1 1.17557 1.17557 1 1.61803 1.17557 1 1.61803 1.61803 -1 1.17557 1.61803 1 1.17557 0.618034 -1 1.90211 1.17557 -1 1.61803 0.618034 1 1.90211 0.618034 1 1.90211 1.17557 -1 1.61803 1.17557 1 1.61803 1.98497e-008 -1 2 0.618034 -1 1.90211 1.98497e-008 1 2 1.98497e-008 1 2 0.618034 -1 1.90211 0.618034 1 1.90211 -0.618034 -1 1.90211 1.98497e-008 -1 2 -0.618034 1 1.90211 -0.618034 1 1.90211 1.98497e-008 -1 2 1.98497e-008 1 2 -1.17557 -1 1.61803 -0.618034 -1 1.90211 -1.17557 1 1.61803 -1.17557 1 1.61803 -0.618034 -1 1.90211 -0.618034 1 1.90211 -1.61803 -1 1.17557 -1.17557 -1 1.61803 -1.61803 1 1.17557 -1.61803 1 1.17557 -1.17557 -1 1.61803 -1.17557 1 1.61803 -1.90211 -1 0.618034 -1.61803 -1 1.17557 -1.90211 1 0.618034 -1.90211 1 0.618034 -1.61803 -1 1.17557 -1.61803 1 1.17557 -2 -1 -3.3976e-008 -1.90211 -1 0.618034 -2 1 -3.3976e-008 -2 1 -3.3976e-008 -1.90211 -1 0.618034 -1.90211 1 0.618034 -1.90211 -1 -0.618034 -2 -1 -3.3976e-008 -1.90211 1 -0.618034 -1.90211 1 -0.618034 -2 -1 -3.3976e-008 -2 1 -3.3976e-008 -1.61803 -1 -1.17557 -1.90211 -1 -0.618034 -1.61803 1 -1.17557 -1.61803 1 -1.17557 -1.90211 -1 -0.618034 -1.90211 1 -0.618034 -1.17557 -1 -1.61803 -1.61803 -1 -1.17557 -1.17557 1 -1.61803 -1.17557 1 -1.61803 -1.61803 -1 -1.17557 -1.61803 1 -1.17557 -0.618034 -1 -1.90211 -1.17557 -1 -1.61803 -0.618034 1 -1.90211 -0.618034 1 -1.90211 -1.17557 -1 -1.61803 -1.17557 1 -1.61803 1.41263e-008 -1 -2 -0.618034 -1 -1.90211 1.41263e-008 1 -2 1.41263e-008 1 -2 -0.618034 -1 -1.90211 -0.618034 1 -1.90211 0.618034 -1 -1.90211 1.41263e-008 -1 -2 0.618034 1 -1.90211 0.618034 1 -1.90211 1.41263e-008 -1 -2 1.41263e-008 1 -2 1.17557 -1 -1.61803 0.618034 -1 -1.90211 1.17557 1 -1.61803 1.17557 1 -1.61803 0.618034 -1 -1.90211 0.618034 1 -1.90211 1.61803 -1 -1.17557 1.17557 -1 -1.61803 1.61803 1 -1.17557 1.61803 1 -1.17557 1.17557 -1 -1.61803 1.17557 1 -1.61803 1.90211 -1 -0.618034 1.61803 -1 -1.17557 1.90211 1 -0.618034 1.90211 1 -0.618034 1.61803 -1 -1.17557 1.61803 1 -1.17557 + + + + + + + + + + + + + +

    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479

    + + + + + + + 5 0.5 -5 5 -0.5 -5 -5 -0.5 -5 5 0.5 5 5 -0.5 5 -5 -0.5 5 -5 0.5 -5 -5 0.5 5 + + + + + + + + + + + + + +

    0 1 2 1 0 3 4 2 1 4 1 3 5 2 4 5 4 3 6 2 5 6 3 0 6 0 2 7 5 3 7 3 6 7 6 5

    +
    +
    +
    + + + + + + + 0.5 0.5 -0.5 0.5 -0.5 -0.5 -0.5 -0.5 -0.5 0.5 0.5 0.5 0.5 -0.5 0.5 -0.5 0.5 -0.5 -0.5 -0.5 0.5 -0.5 0.5 0.5 + + + + + + + + + + + + + +

    0 1 2 1 0 3 4 2 1 4 1 3 5 3 0 5 0 2 6 5 2 6 2 4 6 4 3 7 3 5 7 5 6 7 6 3

    +
    +
    +
    + + + + + + + 0.293893 0.404508 0 0.344095 0.249998 0.262868 0.475529 0.154506 0 0.131434 0.404506 -0.262869 0 0.5 0 -0.293893 -0.404508 0 -0.475529 -0.154506 0 -0.344095 -0.249998 -0.262868 0 -0.5 0 -0.131434 -0.404506 0.262869 -0.293893 0.404508 0 -0.361804 0.262862 0.223609 -0.131434 0.404506 0.262869 0.293893 -0.404508 0 0.131434 -0.404506 -0.262869 0.361804 -0.262862 -0.223609 -0.475529 0.154506 0 -0.344095 0.249998 -0.262868 -0.425324 0 0.262868 0.475529 -0.154506 0 0.344095 -0.249998 0.262868 0.425324 0 -0.262868 -0.262865 0 -0.425326 0 0 -0.5 -0.081228 -0.249998 -0.425327 -0.081228 0.249998 -0.425327 0.262865 0 0.425326 0.081228 0.249998 0.425327 0 0 0.5 0.081228 -0.249998 0.425327 -0.212662 -0.154506 0.425327 0.212662 0.154506 -0.425327 -0.138194 -0.425325 -0.22361 0.138194 -0.425325 0.22361 0.138194 0.425325 0.22361 -0.138194 0.425325 -0.22361 -0.361804 -0.262862 0.223609 0.361804 0.262862 -0.223609 -0.447213 0 -0.223608 0.447213 0 0.223608 -0.212662 0.154506 0.425327 0.212662 -0.154506 -0.425327 + + + + + + + + + + + + + +

    0 1 2 0 3 4 5 6 7 5 8 9 10 11 12 10 12 4 13 8 14 13 14 15 16 11 10 16 10 17 16 6 18 16 18 11 19 20 13 19 13 15 19 15 21 19 21 2 22 23 24 22 24 7 22 17 25 22 25 23 26 1 27 26 27 28 26 28 29 26 29 20 30 9 29 30 29 28 31 23 25 31 25 3 32 7 24 32 24 14 32 8 5 32 5 7 32 14 8 33 20 29 33 29 9 33 8 13 33 13 20 33 9 8 34 12 27 34 27 1 34 1 0 34 0 4 34 4 12 35 3 25 35 25 17 35 17 10 35 10 4 35 4 3 36 9 30 36 30 18 36 6 5 36 5 9 36 18 6 37 21 31 37 31 3 37 3 0 37 0 2 37 2 21 38 17 22 38 22 7 38 6 16 38 16 17 38 7 6 39 1 26 39 26 20 39 20 19 39 19 2 39 2 1 40 18 30 40 30 28 40 28 27 40 27 12 40 12 11 40 11 18 41 23 31 41 31 21 41 14 24 41 24 23 41 15 14 41 21 15

    +
    +
    +
    + + + + + + + 0.511305 -0.5 0.172397 0.432036 -0.52 0.314922 0.523511 -0.532361 0 0.304948 -0.534026 0.422397 0.314922 -0.5 0.438535 -0.432036 -0.52 -0.314922 -0.314922 -0.5 -0.438535 -0.304948 -0.534026 -0.422397 0.161007 -0.52 0.509555 4.96242e-009 -0.5 0.54 -0.165023 -0.53236 0.496558 -0.161007 -0.52 -0.509555 3.53158e-009 -0.5 -0.54 0.165023 -0.53236 -0.496558 -0.5 -0.54 -8.494e-009 0.0275276 0.52 0.0210294 0.538042 -0.487639 0 -0.0275276 0.52 -0.0210294 -0.511305 -0.5 -0.172397 -0.0289443 0.521029 0.0178888 -0.438534 -0.5 0.314922 -0.171521 -0.48764 0.509555 0.0289443 0.521029 -0.0178888 0.438535 -0.5 -0.314922 0.171521 -0.48764 -0.509555 0.433453 -0.521029 -0.311782 -0.433453 -0.521029 0.311781 -0.538042 -0.512361 -8.494e-009 0.00649824 0.52 0.0340262 -0.00649824 0.52 -0.0340262 -0.538042 -0.487639 -8.494e-009 0.538042 -0.512361 0 0.171521 -0.51236 -0.509555 -0.171521 -0.51236 0.509555 -0.523512 -0.532361 -8.494e-009 -0.0235114 0.532361 0 0.0235114 0.532361 0 -0.0105148 0.53236 0.0210295 0 0.54 0 0.0105148 0.53236 -0.0210295 -0.0110555 0.534026 -0.0178888 0.0110555 0.534026 0.0178888 + + + + + + + + + + + + + +

    0 1 2 3 2 1 3 1 4 5 6 7 8 9 10 8 10 3 8 3 4 11 12 13 11 13 7 11 7 6 14 5 7 14 2 3 14 3 10 14 13 2 14 7 13 15 1 0 15 0 16 15 4 1 17 5 18 17 6 5 19 20 21 22 16 23 22 23 24 25 2 13 26 14 10 26 20 27 28 21 9 28 9 8 28 8 4 28 4 15 29 24 12 29 12 11 29 11 6 29 6 17 30 27 20 30 20 19 30 18 27 30 17 18 31 23 16 31 25 23 31 2 25 31 16 0 31 0 2 32 25 13 32 24 23 32 23 25 32 12 24 32 13 12 33 26 10 33 21 20 33 20 26 33 9 21 33 10 9 34 14 26 34 26 27 34 18 5 34 5 14 34 27 18 35 17 30 35 30 19 36 15 16 36 16 22 37 38 35 37 35 19 37 19 21 37 21 28 39 38 36 39 36 22 39 22 24 39 24 29 40 38 39 40 39 29 40 17 35 40 35 38 40 29 17 41 38 37 41 37 28 41 15 36 41 36 38 41 28 15

    +
    +
    +
    + + + + + + + -1 -0.165 -0.5 1.01051 -0.15736 -0.52103 1.01106 -0.159026 0.517889 1.03804 0.137361 -0.5 1.03578 -0.125 0.517889 1.03804 -0.137361 -0.5 1.02753 0.145 0.521029 -1.01051 -0.15736 0.52103 -1.03403 -0.125 0.521029 -1.03804 0.137361 -0.5 -1.03804 -0.137361 -0.5 -1.02894 0.146029 0.517889 1.0065 -0.145 0.534026 -1.01701 -0.13736 0.534026 -1.0065 0.145 -0.534026 -1.01106 0.159026 -0.517889 1.01051 0.15736 -0.52103 1.01701 0.13736 -0.534026 -1 -0.125 -0.54 1.01106 0.159026 0.517889 1.0065 0.145 0.534026 -1.01051 0.15736 0.52103 1.03403 -0.125 -0.521029 -1.01701 0.13736 0.534026 1.01701 -0.13736 -0.534026 -1.0065 -0.145 -0.534026 -1.02894 -0.146029 0.517889 1.02351 -0.157361 -0.5 1.02351 0.157361 -0.5 -1.02351 -0.157361 -0.5 -1.02753 -0.145 -0.521029 -1.02753 0.145 -0.521029 1.02103 -0.125 0.534026 -1.02103 -0.125 -0.534026 -1.02351 0.157361 -0.5 -1 0.165 -0.5 1.02894 0.146029 -0.517889 -1.01106 -0.159026 -0.517889 -1.03578 -0.125 -0.517889 1.02894 -0.146029 -0.517889 -1 -0.125 0.54 1.02753 -0.145 0.521029 + + + + + + + + + + + + + +

    0 1 2 3 4 5 6 4 3 7 0 2 8 9 10 8 11 9 12 13 7 12 7 2 14 15 16 14 16 17 14 17 18 19 20 6 19 21 20 22 3 5 23 11 8 23 8 13 23 21 11 23 20 21 24 17 22 24 18 17 25 18 24 25 24 1 26 7 13 26 13 8 26 8 10 27 2 1 28 6 3 28 19 6 29 0 7 29 7 26 29 10 30 29 26 10 31 15 14 32 4 6 32 6 20 33 14 18 33 31 14 33 18 25 33 25 30 34 15 31 34 31 9 34 9 11 34 11 21 35 15 34 35 34 21 35 19 28 35 28 16 35 16 15 35 21 19 36 16 28 36 28 3 36 3 22 36 22 17 36 17 16 37 0 29 37 29 30 37 30 25 37 1 0 37 25 1 38 31 33 38 33 30 38 9 31 38 10 9 38 30 10 39 5 27 39 27 1 39 1 24 39 24 22 39 22 5 40 12 32 40 32 20 40 20 23 40 23 13 40 13 12 41 4 32 41 32 12 41 2 27 41 27 5 41 12 2 41 5 4

    +
    +
    +
    + + + + + + + -1 -0.165 -1.01527 1.01051 -0.15736 -1.0363 1.01106 -0.159026 0.00262109 1.03804 0.137361 -1.01527 1.03578 -0.125 0.00262092 1.03804 -0.137361 -1.01527 1.02753 0.145 0.00576172 -1.01051 -0.15736 0.00576179 -1.03403 -0.125 0.00576172 -1.03804 0.137361 -1.01527 -1.03804 -0.137361 -1.01527 -1.02894 0.146029 0.00262104 1.0065 -0.145 0.0187585 -1.01701 -0.13736 0.0187585 -1.0065 0.145 -1.04929 -1.01106 0.159026 -1.03316 1.01051 0.15736 -1.0363 1.01701 0.13736 -1.04929 -1 -0.125 -1.05527 1.01106 0.159026 0.00262106 1.0065 0.145 0.0187585 -1.01051 0.15736 0.00576179 1.03403 -0.125 -1.0363 -1.01701 0.13736 0.0187585 1.01701 -0.13736 -1.04929 -1.0065 -0.145 -1.04929 -1.02894 -0.146029 0.00262104 1.02351 -0.157361 -1.01527 1.02351 0.157361 -1.01527 -1.02351 -0.157361 -1.01527 -1.02753 -0.145 -1.0363 -1.02753 0.145 -1.0363 1.02103 -0.125 0.0187584 -1.02103 -0.125 -1.04929 -1.02351 0.157361 -1.01527 -1 0.165 -1.01527 1.02894 0.146029 -1.03316 -1.01106 -0.159026 -1.03316 1.02894 -0.146029 -1.03316 -1.03578 -0.125 -1.03316 -1 -0.125 0.0247323 1.02753 -0.145 0.00576172 + + + + + + + + + + + + + +

    0 1 2 3 4 5 6 4 3 7 0 2 8 9 10 8 11 9 12 13 7 12 7 2 14 15 16 14 16 17 14 17 18 19 20 6 19 21 20 22 3 5 23 11 8 23 8 13 23 21 11 23 20 21 24 17 22 24 18 17 25 18 24 25 24 1 26 7 13 26 13 8 26 8 10 27 2 1 28 6 3 28 19 6 29 0 7 29 7 26 29 10 30 29 26 10 31 15 14 32 4 6 32 6 20 33 14 18 33 31 14 33 18 25 33 25 30 34 15 31 34 31 9 34 9 11 34 11 21 35 15 34 35 34 21 35 19 28 35 28 16 35 16 15 35 21 19 36 16 28 36 28 3 36 3 22 36 22 17 36 17 16 37 0 29 37 29 30 37 30 25 37 1 0 37 25 1 38 5 27 38 27 1 38 1 24 38 24 22 38 22 5 39 31 33 39 33 30 39 9 31 39 10 9 39 30 10 40 12 32 40 32 20 40 20 23 40 23 13 40 13 12 41 4 32 41 32 12 41 2 27 41 27 5 41 12 2 41 5 4

    +
    +
    +
    + + + + + + + + 0.5 + 0 + 0.5 + + + + + 0.5 + 0 + 0.5 + + + + + 0.5 + 0 + 0.5 + + + + + 0.5 + 0 + 0.5 + + + + + 0.5 + 0 + 0.5 + + + + + 0.5 + 0 + 0.5 + + + + + 0.5 + 0 + 0.5 + + + + + + + + false + 0 + 0 0 0 + + + + + + + + + false + 0 + 0 0 0 + + + + 5 0.5 5 + + + + + + + true + 5 + 0.833333 0.833333 0.833333 + + + + 0.5 0.5 0.5 + + + + + + + true + 5 + 0.5 0.5 0.5 + + + + 0.5 + + + + + + + true + 5 + 1.452 1.452 1.452 + + + + + + + + + true + 5 + 0.861375 2.96867 2.37804 + + + + + + + + + true + 5 + 0.861375 2.96867 2.37804 + + + + + + + + + 0 0 -0.552105 + -4.21468e-008 0.707107 0.707107 180 + + + true + false + + + 1 0 0 + -1 0 0 + + + 0 0 0 + 0 0 0 + + + + + + + 0 0 0 + -1 5.96046e-008 5.96046e-008 90 + + + true + false + + + 1 0 0 + -1 0 0 + + + 0 0 0 + 0 0 0 + + + + + + + + + + + diff --git a/Extras/khx2dae/Havok_hkx_screenshot.jpg b/Extras/khx2dae/Havok_hkx_screenshot.jpg new file mode 100644 index 0000000000000000000000000000000000000000..97967f121937a500d126b02a9c89884c8b5cb538 GIT binary patch literal 16013 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
      ?0$KA#y_&AQkO_B6q$*ewb}%x@4iXq@GBiLzNd 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 literal 0 HcmV?d00001 diff --git a/Extras/vectormathlibrary/include/vectormath/SSE/cpp/boolInVec.h b/Extras/vectormathlibrary/include/vectormath/SSE/cpp/boolInVec.h new file mode 100644 index 0000000..a11f72a --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/SSE/cpp/boolInVec.h @@ -0,0 +1,247 @@ +/* + Copyright (C) 2006, 2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _BOOLINVEC_H +#define _BOOLINVEC_H + +#include + +namespace Vectormath { + +class floatInVec; + +//-------------------------------------------------------------------------------------------------- +// boolInVec class +// + +class boolInVec +{ + private: + __m128 mData; + + inline boolInVec(__m128 vec); + public: + inline boolInVec() {} + + // matches standard type conversions + // + inline boolInVec(const floatInVec &vec); + + // explicit cast from bool + // + explicit inline boolInVec(bool scalar); + +#ifdef _VECTORMATH_NO_SCALAR_CAST + // explicit cast to bool + // + inline bool getAsBool() const; +#else + // implicit cast to bool + // + inline operator bool() const; +#endif + + // get vector data + // bool value is splatted across all word slots of vector as 0 (false) or -1 (true) + // + inline __m128 get128() const; + + // operators + // + inline const boolInVec operator ! () const; + inline boolInVec& operator = (const boolInVec &vec); + inline boolInVec& operator &= (const boolInVec &vec); + inline boolInVec& operator ^= (const boolInVec &vec); + inline boolInVec& operator |= (const boolInVec &vec); + + // friend functions + // + friend inline const boolInVec operator == (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec operator != (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec operator < (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator <= (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator > (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator >= (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator == (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator != (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator & (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec operator ^ (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec operator | (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec select(const boolInVec &vec0, const boolInVec &vec1, const boolInVec &select_vec1); +}; + +//-------------------------------------------------------------------------------------------------- +// boolInVec functions +// + +// operators +// +inline const boolInVec operator == (const boolInVec &vec0, const boolInVec &vec1); +inline const boolInVec operator != (const boolInVec &vec0, const boolInVec &vec1); +inline const boolInVec operator & (const boolInVec &vec0, const boolInVec &vec1); +inline const boolInVec operator ^ (const boolInVec &vec0, const boolInVec &vec1); +inline const boolInVec operator | (const boolInVec &vec0, const boolInVec &vec1); + +// select between vec0 and vec1 using boolInVec. +// false selects vec0, true selects vec1 +// +inline const boolInVec select(const boolInVec &vec0, const boolInVec &vec1, const boolInVec &select_vec1); + +} // namespace Vectormath + +//-------------------------------------------------------------------------------------------------- +// boolInVec implementation +// + +#include "floatInVec.h" + +namespace Vectormath { + +inline +boolInVec::boolInVec(__m128 vec) +{ + mData = vec; +} + +inline +boolInVec::boolInVec(const floatInVec &vec) +{ + *this = (vec != floatInVec(0.0f)); +} + +inline +boolInVec::boolInVec(bool scalar) +{ + unsigned int mask = -(int)scalar; + mData = _mm_set1_ps(*(float *)&mask); // TODO: Union +} + +#ifdef _VECTORMATH_NO_SCALAR_CAST +inline +bool +boolInVec::getAsBool() const +#else +inline +boolInVec::operator bool() const +#endif +{ + return *(bool *)&mData; +} + +inline +__m128 +boolInVec::get128() const +{ + return mData; +} + +inline +const boolInVec +boolInVec::operator ! () const +{ + return boolInVec(_mm_andnot_ps(mData, _mm_cmpneq_ps(_mm_setzero_ps(),_mm_setzero_ps()))); +} + +inline +boolInVec& +boolInVec::operator = (const boolInVec &vec) +{ + mData = vec.mData; + return *this; +} + +inline +boolInVec& +boolInVec::operator &= (const boolInVec &vec) +{ + *this = *this & vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator ^= (const boolInVec &vec) +{ + *this = *this ^ vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator |= (const boolInVec &vec) +{ + *this = *this | vec; + return *this; +} + +inline +const boolInVec +operator == (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_cmpeq_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator != (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_cmpneq_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator & (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_and_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator | (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_or_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator ^ (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_xor_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +select(const boolInVec &vec0, const boolInVec &vec1, const boolInVec &select_vec1) +{ + return boolInVec(vec_sel(vec0.get128(), vec1.get128(), select_vec1.get128())); +} + +} // namespace Vectormath + +#endif // boolInVec_h diff --git a/Extras/vectormathlibrary/include/vectormath/SSE/cpp/floatInVec.h b/Extras/vectormathlibrary/include/vectormath/SSE/cpp/floatInVec.h new file mode 100644 index 0000000..4c96824 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/SSE/cpp/floatInVec.h @@ -0,0 +1,340 @@ +/* + Copyright (C) 2006, 2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _FLOATINVEC_H +#define _FLOATINVEC_H + +#include +#include + +namespace Vectormath { + +class boolInVec; + +//-------------------------------------------------------------------------------------------------- +// floatInVec class +// + +class floatInVec +{ + private: + __m128 mData; + + public: + inline floatInVec(__m128 vec); + + inline floatInVec() {} + + // matches standard type conversions + // + inline floatInVec(const boolInVec &vec); + + // construct from a slot of __m128 + // + inline floatInVec(__m128 vec, int slot); + + // explicit cast from float + // + explicit inline floatInVec(float scalar); + +#ifdef _VECTORMATH_NO_SCALAR_CAST + // explicit cast to float + // + inline float getAsFloat() const; +#else + // implicit cast to float + // + inline operator float() const; +#endif + + // get vector data + // float value is splatted across all word slots of vector + // + inline __m128 get128() const; + + // operators + // + inline const floatInVec operator ++ (int); + inline const floatInVec operator -- (int); + inline floatInVec& operator ++ (); + inline floatInVec& operator -- (); + inline const floatInVec operator - () const; + inline floatInVec& operator = (const floatInVec &vec); + inline floatInVec& operator *= (const floatInVec &vec); + inline floatInVec& operator /= (const floatInVec &vec); + inline floatInVec& operator += (const floatInVec &vec); + inline floatInVec& operator -= (const floatInVec &vec); + + // friend functions + // + friend inline const floatInVec operator * (const floatInVec &vec0, const floatInVec &vec1); + friend inline const floatInVec operator / (const floatInVec &vec0, const floatInVec &vec1); + friend inline const floatInVec operator + (const floatInVec &vec0, const floatInVec &vec1); + friend inline const floatInVec operator - (const floatInVec &vec0, const floatInVec &vec1); + friend inline const floatInVec select(const floatInVec &vec0, const floatInVec &vec1, boolInVec select_vec1); +}; + +//-------------------------------------------------------------------------------------------------- +// floatInVec functions +// + +// operators +// +inline const floatInVec operator * (const floatInVec &vec0, const floatInVec &vec1); +inline const floatInVec operator / (const floatInVec &vec0, const floatInVec &vec1); +inline const floatInVec operator + (const floatInVec &vec0, const floatInVec &vec1); +inline const floatInVec operator - (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator < (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator <= (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator > (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator >= (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator == (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator != (const floatInVec &vec0, const floatInVec &vec1); + +// select between vec0 and vec1 using boolInVec. +// false selects vec0, true selects vec1 +// +inline const floatInVec select(const floatInVec &vec0, const floatInVec &vec1, const boolInVec &select_vec1); + +} // namespace Vectormath + +//-------------------------------------------------------------------------------------------------- +// floatInVec implementation +// + +#include "boolInVec.h" + +namespace Vectormath { + +inline +floatInVec::floatInVec(__m128 vec) +{ + mData = vec; +} + +inline +floatInVec::floatInVec(const boolInVec &vec) +{ + mData = vec_sel(_mm_setzero_ps(), _mm_set1_ps(1.0f), vec.get128()); +} + +inline +floatInVec::floatInVec(__m128 vec, int slot) +{ + SSEFloat v; + v.m128 = vec; + mData = _mm_set1_ps(v.f[slot]); +} + +inline +floatInVec::floatInVec(float scalar) +{ + mData = _mm_set1_ps(scalar); +} + +#ifdef _VECTORMATH_NO_SCALAR_CAST +inline +float +floatInVec::getAsFloat() const +#else +inline +floatInVec::operator float() const +#endif +{ + return *((float *)&mData); +} + +inline +__m128 +floatInVec::get128() const +{ + return mData; +} + +inline +const floatInVec +floatInVec::operator ++ (int) +{ + __m128 olddata = mData; + operator ++(); + return floatInVec(olddata); +} + +inline +const floatInVec +floatInVec::operator -- (int) +{ + __m128 olddata = mData; + operator --(); + return floatInVec(olddata); +} + +inline +floatInVec& +floatInVec::operator ++ () +{ + *this += floatInVec(_mm_set1_ps(1.0f)); + return *this; +} + +inline +floatInVec& +floatInVec::operator -- () +{ + *this -= floatInVec(_mm_set1_ps(1.0f)); + return *this; +} + +inline +const floatInVec +floatInVec::operator - () const +{ + return floatInVec(_mm_sub_ps(_mm_setzero_ps(), mData)); +} + +inline +floatInVec& +floatInVec::operator = (const floatInVec &vec) +{ + mData = vec.mData; + return *this; +} + +inline +floatInVec& +floatInVec::operator *= (const floatInVec &vec) +{ + *this = *this * vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator /= (const floatInVec &vec) +{ + *this = *this / vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator += (const floatInVec &vec) +{ + *this = *this + vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator -= (const floatInVec &vec) +{ + *this = *this - vec; + return *this; +} + +inline +const floatInVec +operator * (const floatInVec &vec0, const floatInVec &vec1) +{ + return floatInVec(_mm_mul_ps(vec0.get128(), vec1.get128())); +} + +inline +const floatInVec +operator / (const floatInVec &num, const floatInVec &den) +{ + return floatInVec(_mm_div_ps(num.get128(), den.get128())); +} + +inline +const floatInVec +operator + (const floatInVec &vec0, const floatInVec &vec1) +{ + return floatInVec(_mm_add_ps(vec0.get128(), vec1.get128())); +} + +inline +const floatInVec +operator - (const floatInVec &vec0, const floatInVec &vec1) +{ + return floatInVec(_mm_sub_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator < (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpgt_ps(vec1.get128(), vec0.get128())); +} + +inline +const boolInVec +operator <= (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpge_ps(vec1.get128(), vec0.get128())); +} + +inline +const boolInVec +operator > (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpgt_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator >= (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpge_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator == (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpeq_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator != (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpneq_ps(vec0.get128(), vec1.get128())); +} + +inline +const floatInVec +select(const floatInVec &vec0, const floatInVec &vec1, const boolInVec &select_vec1) +{ + return floatInVec(vec_sel(vec0.get128(), vec1.get128(), select_vec1.get128())); +} + +} // namespace Vectormath + +#endif // floatInVec_h diff --git a/Extras/vectormathlibrary/include/vectormath/SSE/cpp/mat_aos.h b/Extras/vectormathlibrary/include/vectormath/SSE/cpp/mat_aos.h new file mode 100644 index 0000000..5b2b714 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/SSE/cpp/mat_aos.h @@ -0,0 +1,2190 @@ +/* + Copyright (C) 2006, 2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _VECTORMATH_MAT_AOS_CPP_H +#define _VECTORMATH_MAT_AOS_CPP_H + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// Constants +// for shuffles, words are labeled [x,y,z,w] [a,b,c,d] + +#define _VECTORMATH_PERM_ZBWX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XCYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_C, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XYAB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_ZWCD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W, _VECTORMATH_PERM_C, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_XZBX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_CXXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_YAXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XAZC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_YXWZ ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W, _VECTORMATH_PERM_Z }) +#define _VECTORMATH_PERM_YBWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_XYCX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_YCXY ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y }) +#define _VECTORMATH_PERM_CXYC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_ZAYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_BZXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_B, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XZYA ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A }) +#define _VECTORMATH_PERM_ZXXB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_YXXC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_BBYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_B, _VECTORMATH_PERM_B, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PI_OVER_2 1.570796327f + +//----------------------------------------------------------------------------- +// Definitions + +__forceinline Matrix3::Matrix3( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; +} + +__forceinline Matrix3::Matrix3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +__forceinline Matrix3::Matrix3( const floatInVec &scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +__forceinline Matrix3::Matrix3( const Quat &unitQuat ) +{ + __m128 xyzw_2, wwww, yzxw, zxyw, yzxw_2, zxyw_2; + __m128 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + __declspec(align(16)) unsigned int sx[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int sz[4] = {0, 0, 0xffffffff, 0}; + __m128 select_x = _mm_load_ps((float *)sx); + __m128 select_z = _mm_load_ps((float *)sz); + + xyzw_2 = _mm_add_ps( unitQuat.get128(), unitQuat.get128() ); + wwww = _mm_shuffle_ps( unitQuat.get128(), unitQuat.get128(), _MM_SHUFFLE(3,3,3,3) ); + yzxw = _mm_shuffle_ps( unitQuat.get128(), unitQuat.get128(), _MM_SHUFFLE(3,0,2,1) ); + zxyw = _mm_shuffle_ps( unitQuat.get128(), unitQuat.get128(), _MM_SHUFFLE(3,1,0,2) ); + yzxw_2 = _mm_shuffle_ps( xyzw_2, xyzw_2, _MM_SHUFFLE(3,0,2,1) ); + zxyw_2 = _mm_shuffle_ps( xyzw_2, xyzw_2, _MM_SHUFFLE(3,1,0,2) ); + + tmp0 = _mm_mul_ps( yzxw_2, wwww ); // tmp0 = 2yw, 2zw, 2xw, 2w2 + tmp1 = _mm_sub_ps( _mm_set1_ps(1.0f), _mm_mul_ps(yzxw, yzxw_2) ); // tmp1 = 1 - 2y2, 1 - 2z2, 1 - 2x2, 1 - 2w2 + tmp2 = _mm_mul_ps( yzxw, xyzw_2 ); // tmp2 = 2xy, 2yz, 2xz, 2w2 + tmp0 = _mm_add_ps( _mm_mul_ps(zxyw, xyzw_2), tmp0 ); // tmp0 = 2yw + 2zx, 2zw + 2xy, 2xw + 2yz, 2w2 + 2w2 + tmp1 = _mm_sub_ps( tmp1, _mm_mul_ps(zxyw, zxyw_2) ); // tmp1 = 1 - 2y2 - 2z2, 1 - 2z2 - 2x2, 1 - 2x2 - 2y2, 1 - 2w2 - 2w2 + tmp2 = _mm_sub_ps( tmp2, _mm_mul_ps(zxyw_2, wwww) ); // tmp2 = 2xy - 2zw, 2yz - 2xw, 2xz - 2yw, 2w2 -2w2 + + tmp3 = vec_sel( tmp0, tmp1, select_x ); + tmp4 = vec_sel( tmp1, tmp2, select_x ); + tmp5 = vec_sel( tmp2, tmp0, select_x ); + mCol0 = Vector3( vec_sel( tmp3, tmp2, select_z ) ); + mCol1 = Vector3( vec_sel( tmp4, tmp0, select_z ) ); + mCol2 = Vector3( vec_sel( tmp5, tmp1, select_z ) ); +} + +__forceinline Matrix3::Matrix3( const Vector3 &_col0, const Vector3 &_col1, const Vector3 &_col2 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; +} + +__forceinline Matrix3 & Matrix3::setCol0( const Vector3 &_col0 ) +{ + mCol0 = _col0; + return *this; +} + +__forceinline Matrix3 & Matrix3::setCol1( const Vector3 &_col1 ) +{ + mCol1 = _col1; + return *this; +} + +__forceinline Matrix3 & Matrix3::setCol2( const Vector3 &_col2 ) +{ + mCol2 = _col2; + return *this; +} + +__forceinline Matrix3 & Matrix3::setCol( int col, const Vector3 &vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +__forceinline Matrix3 & Matrix3::setRow( int row, const Vector3 &vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + return *this; +} + +__forceinline Matrix3 & Matrix3::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +__forceinline Matrix3 & Matrix3::setElem( int col, int row, const floatInVec &val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +__forceinline const floatInVec Matrix3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +__forceinline const Vector3 Matrix3::getCol0( ) const +{ + return mCol0; +} + +__forceinline const Vector3 Matrix3::getCol1( ) const +{ + return mCol1; +} + +__forceinline const Vector3 Matrix3::getCol2( ) const +{ + return mCol2; +} + +__forceinline const Vector3 Matrix3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +__forceinline const Vector3 Matrix3::getRow( int row ) const +{ + return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); +} + +__forceinline Vector3 & Matrix3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +__forceinline const Vector3 Matrix3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +__forceinline Matrix3 & Matrix3::operator =( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + return *this; +} + +__forceinline const Matrix3 transpose( const Matrix3 & mat ) +{ + __m128 tmp0, tmp1, res0, res1, res2; + tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp1 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); + res0 = vec_mergeh( tmp0, mat.getCol1().get128() ); + //res1 = vec_perm( tmp0, mat.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + res1 = _mm_shuffle_ps( tmp0, tmp0, _MM_SHUFFLE(0,3,2,2)); + res1 = vec_sel(res1, mat.getCol1().get128(), select_y); + //res2 = vec_perm( tmp1, mat.getCol1().get128(), _VECTORMATH_PERM_XCYX ); + res2 = _mm_shuffle_ps( tmp1, tmp1, _MM_SHUFFLE(0,1,1,0)); + res2 = vec_sel(res2, vec_splat(mat.getCol1().get128(), 2), select_y); + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +__forceinline const Matrix3 inverse( const Matrix3 & mat ) +{ + __m128 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet, inv0, inv1, inv2; + tmp2 = _vmathVfCross( mat.getCol0().get128(), mat.getCol1().get128() ); + tmp0 = _vmathVfCross( mat.getCol1().get128(), mat.getCol2().get128() ); + tmp1 = _vmathVfCross( mat.getCol2().get128(), mat.getCol0().get128() ); + dot = _vmathVfDot3( tmp2, mat.getCol2().get128() ); + dot = vec_splat( dot, 0 ); + invdet = recipf4( dot ); + tmp3 = vec_mergeh( tmp0, tmp2 ); + tmp4 = vec_mergel( tmp0, tmp2 ); + inv0 = vec_mergeh( tmp3, tmp1 ); + //inv1 = vec_perm( tmp3, tmp1, _VECTORMATH_PERM_ZBWX ); + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + inv1 = _mm_shuffle_ps( tmp3, tmp3, _MM_SHUFFLE(0,3,2,2)); + inv1 = vec_sel(inv1, tmp1, select_y); + //inv2 = vec_perm( tmp4, tmp1, _VECTORMATH_PERM_XCYX ); + inv2 = _mm_shuffle_ps( tmp4, tmp4, _MM_SHUFFLE(0,1,1,0)); + inv2 = vec_sel(inv2, vec_splat(tmp1, 2), select_y); + inv0 = vec_mul( inv0, invdet ); + inv1 = vec_mul( inv1, invdet ); + inv2 = vec_mul( inv2, invdet ); + return Matrix3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ) + ); +} + +__forceinline const floatInVec determinant( const Matrix3 & mat ) +{ + return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); +} + +__forceinline const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ) + ); +} + +__forceinline const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ) + ); +} + +__forceinline Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) +{ + *this = *this + mat; + return *this; +} + +__forceinline Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) +{ + *this = *this - mat; + return *this; +} + +__forceinline const Matrix3 Matrix3::operator -( ) const +{ + return Matrix3( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ) + ); +} + +__forceinline const Matrix3 absPerElem( const Matrix3 & mat ) +{ + return Matrix3( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ) + ); +} + +__forceinline const Matrix3 Matrix3::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +__forceinline const Matrix3 Matrix3::operator *( const floatInVec &scalar ) const +{ + return Matrix3( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ) + ); +} + +__forceinline Matrix3 & Matrix3::operator *=( float scalar ) +{ + return *this *= floatInVec(scalar); +} + +__forceinline Matrix3 & Matrix3::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +__forceinline const Matrix3 operator *( float scalar, const Matrix3 & mat ) +{ + return floatInVec(scalar) * mat; +} + +__forceinline const Matrix3 operator *( const floatInVec &scalar, const Matrix3 & mat ) +{ + return mat * scalar; +} + +__forceinline const Vector3 Matrix3::operator *( const Vector3 &vec ) const +{ + __m128 res; + __m128 xxxx, yyyy, zzzz; + xxxx = vec_splat( vec.get128(), 0 ); + yyyy = vec_splat( vec.get128(), 1 ); + zzzz = vec_splat( vec.get128(), 2 ); + res = vec_mul( mCol0.get128(), xxxx ); + res = vec_madd( mCol1.get128(), yyyy, res ); + res = vec_madd( mCol2.get128(), zzzz, res ); + return Vector3( res ); +} + +__forceinline const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const +{ + return Matrix3( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ) + ); +} + +__forceinline Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) +{ + *this = *this * mat; + return *this; +} + +__forceinline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) +{ + return Matrix3( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ) + ); +} + +__forceinline const Matrix3 Matrix3::identity( ) +{ + return Matrix3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ) + ); +} + +__forceinline const Matrix3 Matrix3::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +__forceinline const Matrix3 Matrix3::rotationX( const floatInVec &radians ) +{ + __m128 s, c, res1, res2; + __m128 zero; + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + __declspec(align(16)) unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + return Matrix3( + Vector3::xAxis( ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +__forceinline const Matrix3 Matrix3::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +__forceinline const Matrix3 Matrix3::rotationY( const floatInVec &radians ) +{ + __m128 s, c, res0, res2; + __m128 zero; + __declspec(align(16)) unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + return Matrix3( + Vector3( res0 ), + Vector3::yAxis( ), + Vector3( res2 ) + ); +} + +__forceinline const Matrix3 Matrix3::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +__forceinline const Matrix3 Matrix3::rotationZ( const floatInVec &radians ) +{ + __m128 s, c, res0, res1; + __m128 zero; + __declspec(align(16)) unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3::zAxis( ) + ); +} + +__forceinline const Matrix3 Matrix3::rotationZYX( const Vector3 &radiansXYZ ) +{ + __m128 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + angles = Vector4( radiansXYZ, 0.0f ).get128(); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + __declspec(align(16)) unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; + Z1 = vec_and( Z1, _mm_load_ps( (float *)select_xyz ) ); + Y0 = _mm_shuffle_ps( c, negS, _MM_SHUFFLE(0,1,1,1) ); + Y1 = _mm_shuffle_ps( s, c, _MM_SHUFFLE(0,1,1,1) ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_mul( Z0, Y1 ); + return Matrix3( + Vector3( vec_mul( Z0, Y0 ) ), + Vector3( vec_madd( Z1, X1, vec_mul( tmp, X0 ) ) ), + Vector3( vec_nmsub( Z1, X0, vec_mul( tmp, X1 ) ) ) + ); +} + +__forceinline const Matrix3 Matrix3::rotation( float radians, const Vector3 &unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +__forceinline const Matrix3 Matrix3::rotation( const floatInVec &radians, const Vector3 &unitVec ) +{ + __m128 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2; + axis = unitVec.get128(); + sincosf4( radians.get128(), &s, &c ); + xxxx = vec_splat( axis, 0 ); + yyyy = vec_splat( axis, 1 ); + zzzz = vec_splat( axis, 2 ); + oneMinusC = vec_sub( _mm_set1_ps(1.0f), c ); + axisS = vec_mul( axis, s ); + negAxisS = negatef4( axisS ); + __declspec(align(16)) unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + __declspec(align(16)) unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + //tmp0 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_XZBX ); + tmp0 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,2,0) ); + tmp0 = vec_sel(tmp0, vec_splat(negAxisS, 1), select_z); + //tmp1 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_CXXX ); + tmp1 = vec_sel( vec_splat(axisS, 0), vec_splat(negAxisS, 2), select_x ); + //tmp2 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_YAXX ); + tmp2 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,0,1) ); + tmp2 = vec_sel(tmp2, vec_splat(negAxisS, 0), select_y); + tmp0 = vec_sel( tmp0, c, select_x ); + tmp1 = vec_sel( tmp1, c, select_y ); + tmp2 = vec_sel( tmp2, c, select_z ); + return Matrix3( + Vector3( vec_madd( vec_mul( axis, xxxx ), oneMinusC, tmp0 ) ), + Vector3( vec_madd( vec_mul( axis, yyyy ), oneMinusC, tmp1 ) ), + Vector3( vec_madd( vec_mul( axis, zzzz ), oneMinusC, tmp2 ) ) + ); +} + +__forceinline const Matrix3 Matrix3::rotation( const Quat &unitQuat ) +{ + return Matrix3( unitQuat ); +} + +__forceinline const Matrix3 Matrix3::scale( const Vector3 &scaleVec ) +{ + __m128 zero = _mm_setzero_ps(); + __declspec(align(16)) unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + __declspec(align(16)) unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + return Matrix3( + Vector3( vec_sel( zero, scaleVec.get128(), select_x ) ), + Vector3( vec_sel( zero, scaleVec.get128(), select_y ) ), + Vector3( vec_sel( zero, scaleVec.get128(), select_z ) ) + ); +} + +__forceinline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 &scaleVec ) +{ + return Matrix3( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ) + ); +} + +__forceinline const Matrix3 prependScale( const Vector3 &scaleVec, const Matrix3 & mat ) +{ + return Matrix3( + mulPerElem( mat.getCol0(), scaleVec ), + mulPerElem( mat.getCol1(), scaleVec ), + mulPerElem( mat.getCol2(), scaleVec ) + ); +} + +__forceinline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +__forceinline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, const boolInVec &select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +__forceinline void print( const Matrix3 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); +} + +__forceinline void print( const Matrix3 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +__forceinline Matrix4::Matrix4( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; +} + +__forceinline Matrix4::Matrix4( float scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +__forceinline Matrix4::Matrix4( const floatInVec &scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +__forceinline Matrix4::Matrix4( const Transform3 & mat ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( mat.getCol3(), 1.0f ); +} + +__forceinline Matrix4::Matrix4( const Vector4 &_col0, const Vector4 &_col1, const Vector4 &_col2, const Vector4 &_col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +__forceinline Matrix4::Matrix4( const Matrix3 & mat, const Vector3 &translateVec ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +__forceinline Matrix4::Matrix4( const Quat &unitQuat, const Vector3 &translateVec ) +{ + Matrix3 mat; + mat = Matrix3( unitQuat ); + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +__forceinline Matrix4 & Matrix4::setCol0( const Vector4 &_col0 ) +{ + mCol0 = _col0; + return *this; +} + +__forceinline Matrix4 & Matrix4::setCol1( const Vector4 &_col1 ) +{ + mCol1 = _col1; + return *this; +} + +__forceinline Matrix4 & Matrix4::setCol2( const Vector4 &_col2 ) +{ + mCol2 = _col2; + return *this; +} + +__forceinline Matrix4 & Matrix4::setCol3( const Vector4 &_col3 ) +{ + mCol3 = _col3; + return *this; +} + +__forceinline Matrix4 & Matrix4::setCol( int col, const Vector4 &vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +__forceinline Matrix4 & Matrix4::setRow( int row, const Vector4 &vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +__forceinline Matrix4 & Matrix4::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +__forceinline Matrix4 & Matrix4::setElem( int col, int row, const floatInVec &val ) +{ + Vector4 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +__forceinline const floatInVec Matrix4::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +__forceinline const Vector4 Matrix4::getCol0( ) const +{ + return mCol0; +} + +__forceinline const Vector4 Matrix4::getCol1( ) const +{ + return mCol1; +} + +__forceinline const Vector4 Matrix4::getCol2( ) const +{ + return mCol2; +} + +__forceinline const Vector4 Matrix4::getCol3( ) const +{ + return mCol3; +} + +__forceinline const Vector4 Matrix4::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +__forceinline const Vector4 Matrix4::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +__forceinline Vector4 & Matrix4::operator []( int col ) +{ + return *(&mCol0 + col); +} + +__forceinline const Vector4 Matrix4::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +__forceinline Matrix4 & Matrix4::operator =( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; + return *this; +} + +__forceinline const Matrix4 transpose( const Matrix4 & mat ) +{ + __m128 tmp0, tmp1, tmp2, tmp3, res0, res1, res2, res3; + tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp1 = vec_mergeh( mat.getCol1().get128(), mat.getCol3().get128() ); + tmp2 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp3 = vec_mergel( mat.getCol1().get128(), mat.getCol3().get128() ); + res0 = vec_mergeh( tmp0, tmp1 ); + res1 = vec_mergel( tmp0, tmp1 ); + res2 = vec_mergeh( tmp2, tmp3 ); + res3 = vec_mergel( tmp2, tmp3 ); + return Matrix4( + Vector4( res0 ), + Vector4( res1 ), + Vector4( res2 ), + Vector4( res3 ) + ); +} + +// TODO: Tidy +static __declspec(align(16)) const unsigned int _vmathPNPN[4] = {0x00000000, 0x80000000, 0x00000000, 0x80000000}; +static __declspec(align(16)) const unsigned int _vmathNPNP[4] = {0x80000000, 0x00000000, 0x80000000, 0x00000000}; +static __declspec(align(16)) const float _vmathZERONE[4] = {1.0f, 0.0f, 0.0f, 1.0f}; + +__forceinline const Matrix4 inverse( const Matrix4 & mat ) +{ + __m128 Va,Vb,Vc; + __m128 r1,r2,r3,tt,tt2; + __m128 sum,Det,RDet; + __m128 trns0,trns1,trns2,trns3; + + __m128 _L1 = mat.getCol0().get128(); + __m128 _L2 = mat.getCol1().get128(); + __m128 _L3 = mat.getCol2().get128(); + __m128 _L4 = mat.getCol3().get128(); + // Calculating the minterms for the first line. + + // _mm_ror_ps is just a macro using _mm_shuffle_ps(). + tt = _L4; tt2 = _mm_ror_ps(_L3,1); + Vc = _mm_mul_ps(tt2,_mm_ror_ps(tt,0)); // V3'·V4 + Va = _mm_mul_ps(tt2,_mm_ror_ps(tt,2)); // V3'·V4" + Vb = _mm_mul_ps(tt2,_mm_ror_ps(tt,3)); // V3'·V4^ + + r1 = _mm_sub_ps(_mm_ror_ps(Va,1),_mm_ror_ps(Vc,2)); // V3"·V4^ - V3^·V4" + r2 = _mm_sub_ps(_mm_ror_ps(Vb,2),_mm_ror_ps(Vb,0)); // V3^·V4' - V3'·V4^ + r3 = _mm_sub_ps(_mm_ror_ps(Va,0),_mm_ror_ps(Vc,1)); // V3'·V4" - V3"·V4' + + tt = _L2; + Va = _mm_ror_ps(tt,1); sum = _mm_mul_ps(Va,r1); + Vb = _mm_ror_ps(tt,2); sum = _mm_add_ps(sum,_mm_mul_ps(Vb,r2)); + Vc = _mm_ror_ps(tt,3); sum = _mm_add_ps(sum,_mm_mul_ps(Vc,r3)); + + // Calculating the determinant. + Det = _mm_mul_ps(sum,_L1); + Det = _mm_add_ps(Det,_mm_movehl_ps(Det,Det)); + + const __m128 Sign_PNPN = _mm_load_ps((float *)_vmathPNPN); + const __m128 Sign_NPNP = _mm_load_ps((float *)_vmathNPNP); + + __m128 mtL1 = _mm_xor_ps(sum,Sign_PNPN); + + // Calculating the minterms of the second line (using previous results). + tt = _mm_ror_ps(_L1,1); sum = _mm_mul_ps(tt,r1); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); + __m128 mtL2 = _mm_xor_ps(sum,Sign_NPNP); + + // Testing the determinant. + Det = _mm_sub_ss(Det,_mm_shuffle_ps(Det,Det,1)); + + // Calculating the minterms of the third line. + tt = _mm_ror_ps(_L1,1); + Va = _mm_mul_ps(tt,Vb); // V1'·V2" + Vb = _mm_mul_ps(tt,Vc); // V1'·V2^ + Vc = _mm_mul_ps(tt,_L2); // V1'·V2 + + r1 = _mm_sub_ps(_mm_ror_ps(Va,1),_mm_ror_ps(Vc,2)); // V1"·V2^ - V1^·V2" + r2 = _mm_sub_ps(_mm_ror_ps(Vb,2),_mm_ror_ps(Vb,0)); // V1^·V2' - V1'·V2^ + r3 = _mm_sub_ps(_mm_ror_ps(Va,0),_mm_ror_ps(Vc,1)); // V1'·V2" - V1"·V2' + + tt = _mm_ror_ps(_L4,1); sum = _mm_mul_ps(tt,r1); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); + __m128 mtL3 = _mm_xor_ps(sum,Sign_PNPN); + + // Dividing is FASTER than rcp_nr! (Because rcp_nr causes many register-memory RWs). + RDet = _mm_div_ss(_mm_load_ss((float *)&_vmathZERONE), Det); // TODO: just 1.0f? + RDet = _mm_shuffle_ps(RDet,RDet,0x00); + + // Devide the first 12 minterms with the determinant. + mtL1 = _mm_mul_ps(mtL1, RDet); + mtL2 = _mm_mul_ps(mtL2, RDet); + mtL3 = _mm_mul_ps(mtL3, RDet); + + // Calculate the minterms of the forth line and devide by the determinant. + tt = _mm_ror_ps(_L3,1); sum = _mm_mul_ps(tt,r1); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); + __m128 mtL4 = _mm_xor_ps(sum,Sign_NPNP); + mtL4 = _mm_mul_ps(mtL4, RDet); + + // Now we just have to transpose the minterms matrix. + trns0 = _mm_unpacklo_ps(mtL1,mtL2); + trns1 = _mm_unpacklo_ps(mtL3,mtL4); + trns2 = _mm_unpackhi_ps(mtL1,mtL2); + trns3 = _mm_unpackhi_ps(mtL3,mtL4); + _L1 = _mm_movelh_ps(trns0,trns1); + _L2 = _mm_movehl_ps(trns1,trns0); + _L3 = _mm_movelh_ps(trns2,trns3); + _L4 = _mm_movehl_ps(trns3,trns2); + + return Matrix4( + Vector4( _L1 ), + Vector4( _L2 ), + Vector4( _L3 ), + Vector4( _L4 ) + ); +} + +__forceinline const Matrix4 affineInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( inverse( affineMat ) ); +} + +__forceinline const Matrix4 orthoInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( orthoInverse( affineMat ) ); +} + +__forceinline const floatInVec determinant( const Matrix4 & mat ) +{ + __m128 Va,Vb,Vc; + __m128 r1,r2,r3,tt,tt2; + __m128 sum,Det; + + __m128 _L1 = mat.getCol0().get128(); + __m128 _L2 = mat.getCol1().get128(); + __m128 _L3 = mat.getCol2().get128(); + __m128 _L4 = mat.getCol3().get128(); + // Calculating the minterms for the first line. + + // _mm_ror_ps is just a macro using _mm_shuffle_ps(). + tt = _L4; tt2 = _mm_ror_ps(_L3,1); + Vc = _mm_mul_ps(tt2,_mm_ror_ps(tt,0)); // V3'·V4 + Va = _mm_mul_ps(tt2,_mm_ror_ps(tt,2)); // V3'·V4" + Vb = _mm_mul_ps(tt2,_mm_ror_ps(tt,3)); // V3'·V4^ + + r1 = _mm_sub_ps(_mm_ror_ps(Va,1),_mm_ror_ps(Vc,2)); // V3"·V4^ - V3^·V4" + r2 = _mm_sub_ps(_mm_ror_ps(Vb,2),_mm_ror_ps(Vb,0)); // V3^·V4' - V3'·V4^ + r3 = _mm_sub_ps(_mm_ror_ps(Va,0),_mm_ror_ps(Vc,1)); // V3'·V4" - V3"·V4' + + tt = _L2; + Va = _mm_ror_ps(tt,1); sum = _mm_mul_ps(Va,r1); + Vb = _mm_ror_ps(tt,2); sum = _mm_add_ps(sum,_mm_mul_ps(Vb,r2)); + Vc = _mm_ror_ps(tt,3); sum = _mm_add_ps(sum,_mm_mul_ps(Vc,r3)); + + // Calculating the determinant. + Det = _mm_mul_ps(sum,_L1); + Det = _mm_add_ps(Det,_mm_movehl_ps(Det,Det)); + + // Calculating the minterms of the second line (using previous results). + tt = _mm_ror_ps(_L1,1); sum = _mm_mul_ps(tt,r1); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); + + // Testing the determinant. + Det = _mm_sub_ss(Det,_mm_shuffle_ps(Det,Det,1)); + return floatInVec(Det, 0); +} + +__forceinline const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ), + ( mCol3 + mat.mCol3 ) + ); +} + +__forceinline const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ), + ( mCol3 - mat.mCol3 ) + ); +} + +__forceinline Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) +{ + *this = *this + mat; + return *this; +} + +__forceinline Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) +{ + *this = *this - mat; + return *this; +} + +__forceinline const Matrix4 Matrix4::operator -( ) const +{ + return Matrix4( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ), + ( -mCol3 ) + ); +} + +__forceinline const Matrix4 absPerElem( const Matrix4 & mat ) +{ + return Matrix4( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ), + absPerElem( mat.getCol3() ) + ); +} + +__forceinline const Matrix4 Matrix4::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +__forceinline const Matrix4 Matrix4::operator *( const floatInVec &scalar ) const +{ + return Matrix4( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ), + ( mCol3 * scalar ) + ); +} + +__forceinline Matrix4 & Matrix4::operator *=( float scalar ) +{ + return *this *= floatInVec(scalar); +} + +__forceinline Matrix4 & Matrix4::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +__forceinline const Matrix4 operator *( float scalar, const Matrix4 & mat ) +{ + return floatInVec(scalar) * mat; +} + +__forceinline const Matrix4 operator *( const floatInVec &scalar, const Matrix4 & mat ) +{ + return mat * scalar; +} + +__forceinline const Vector4 Matrix4::operator *( const Vector4 &vec ) const +{ + return Vector4( + _mm_add_ps( + _mm_add_ps(_mm_mul_ps(mCol0.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(0,0,0,0))), _mm_mul_ps(mCol1.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(1,1,1,1)))), + _mm_add_ps(_mm_mul_ps(mCol2.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(2,2,2,2))), _mm_mul_ps(mCol3.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(3,3,3,3))))) + ); +} + +__forceinline const Vector4 Matrix4::operator *( const Vector3 &vec ) const +{ + return Vector4( + _mm_add_ps( + _mm_add_ps(_mm_mul_ps(mCol0.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(0,0,0,0))), _mm_mul_ps(mCol1.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(1,1,1,1)))), + _mm_mul_ps(mCol2.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(2,2,2,2)))) + ); +} + +__forceinline const Vector4 Matrix4::operator *( const Point3 &pnt ) const +{ + return Vector4( + _mm_add_ps( + _mm_add_ps(_mm_mul_ps(mCol0.get128(), _mm_shuffle_ps(pnt.get128(), pnt.get128(), _MM_SHUFFLE(0,0,0,0))), _mm_mul_ps(mCol1.get128(), _mm_shuffle_ps(pnt.get128(), pnt.get128(), _MM_SHUFFLE(1,1,1,1)))), + _mm_add_ps(_mm_mul_ps(mCol2.get128(), _mm_shuffle_ps(pnt.get128(), pnt.get128(), _MM_SHUFFLE(2,2,2,2))), mCol3.get128())) + ); +} + +__forceinline const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const +{ + return Matrix4( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ), + ( *this * mat.mCol3 ) + ); +} + +__forceinline Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) +{ + *this = *this * mat; + return *this; +} + +__forceinline const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const +{ + return Matrix4( + ( *this * tfrm.getCol0() ), + ( *this * tfrm.getCol1() ), + ( *this * tfrm.getCol2() ), + ( *this * Point3( tfrm.getCol3() ) ) + ); +} + +__forceinline Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +__forceinline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) +{ + return Matrix4( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ), + mulPerElem( mat0.getCol3(), mat1.getCol3() ) + ); +} + +__forceinline const Matrix4 Matrix4::identity( ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +__forceinline Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) +{ + mCol0.setXYZ( mat3.getCol0() ); + mCol1.setXYZ( mat3.getCol1() ); + mCol2.setXYZ( mat3.getCol2() ); + return *this; +} + +__forceinline const Matrix3 Matrix4::getUpper3x3( ) const +{ + return Matrix3( + mCol0.getXYZ( ), + mCol1.getXYZ( ), + mCol2.getXYZ( ) + ); +} + +__forceinline Matrix4 & Matrix4::setTranslation( const Vector3 &translateVec ) +{ + mCol3.setXYZ( translateVec ); + return *this; +} + +__forceinline const Vector3 Matrix4::getTranslation( ) const +{ + return mCol3.getXYZ( ); +} + +__forceinline const Matrix4 Matrix4::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +__forceinline const Matrix4 Matrix4::rotationX( const floatInVec &radians ) +{ + __m128 s, c, res1, res2; + __m128 zero; + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + __declspec(align(16)) unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + return Matrix4( + Vector4::xAxis( ), + Vector4( res1 ), + Vector4( res2 ), + Vector4::wAxis( ) + ); +} + +__forceinline const Matrix4 Matrix4::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +__forceinline const Matrix4 Matrix4::rotationY( const floatInVec &radians ) +{ + __m128 s, c, res0, res2; + __m128 zero; + __declspec(align(16)) unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + return Matrix4( + Vector4( res0 ), + Vector4::yAxis( ), + Vector4( res2 ), + Vector4::wAxis( ) + ); +} + +__forceinline const Matrix4 Matrix4::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +__forceinline const Matrix4 Matrix4::rotationZ( const floatInVec &radians ) +{ + __m128 s, c, res0, res1; + __m128 zero; + __declspec(align(16)) unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + return Matrix4( + Vector4( res0 ), + Vector4( res1 ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +__forceinline const Matrix4 Matrix4::rotationZYX( const Vector3 &radiansXYZ ) +{ + __m128 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + angles = Vector4( radiansXYZ, 0.0f ).get128(); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + __declspec(align(16)) unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; + Z1 = vec_and( Z1, _mm_load_ps( (float *)select_xyz ) ); + Y0 = _mm_shuffle_ps( c, negS, _MM_SHUFFLE(0,1,1,1) ); + Y1 = _mm_shuffle_ps( s, c, _MM_SHUFFLE(0,1,1,1) ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_mul( Z0, Y1 ); + return Matrix4( + Vector4( vec_mul( Z0, Y0 ) ), + Vector4( vec_madd( Z1, X1, vec_mul( tmp, X0 ) ) ), + Vector4( vec_nmsub( Z1, X0, vec_mul( tmp, X1 ) ) ), + Vector4::wAxis( ) + ); +} + +__forceinline const Matrix4 Matrix4::rotation( float radians, const Vector3 &unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +__forceinline const Matrix4 Matrix4::rotation( const floatInVec &radians, const Vector3 &unitVec ) +{ + __m128 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2; + axis = unitVec.get128(); + sincosf4( radians.get128(), &s, &c ); + xxxx = vec_splat( axis, 0 ); + yyyy = vec_splat( axis, 1 ); + zzzz = vec_splat( axis, 2 ); + oneMinusC = vec_sub( _mm_set1_ps(1.0f), c ); + axisS = vec_mul( axis, s ); + negAxisS = negatef4( axisS ); + __declspec(align(16)) unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + __declspec(align(16)) unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + //tmp0 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_XZBX ); + tmp0 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,2,0) ); + tmp0 = vec_sel(tmp0, vec_splat(negAxisS, 1), select_z); + //tmp1 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_CXXX ); + tmp1 = vec_sel( vec_splat(axisS, 0), vec_splat(negAxisS, 2), select_x ); + //tmp2 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_YAXX ); + tmp2 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,0,1) ); + tmp2 = vec_sel(tmp2, vec_splat(negAxisS, 0), select_y); + tmp0 = vec_sel( tmp0, c, select_x ); + tmp1 = vec_sel( tmp1, c, select_y ); + tmp2 = vec_sel( tmp2, c, select_z ); + __declspec(align(16)) unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; + axis = vec_and( axis, _mm_load_ps( (float *)select_xyz ) ); + tmp0 = vec_and( tmp0, _mm_load_ps( (float *)select_xyz ) ); + tmp1 = vec_and( tmp1, _mm_load_ps( (float *)select_xyz ) ); + tmp2 = vec_and( tmp2, _mm_load_ps( (float *)select_xyz ) ); + return Matrix4( + Vector4( vec_madd( vec_mul( axis, xxxx ), oneMinusC, tmp0 ) ), + Vector4( vec_madd( vec_mul( axis, yyyy ), oneMinusC, tmp1 ) ), + Vector4( vec_madd( vec_mul( axis, zzzz ), oneMinusC, tmp2 ) ), + Vector4::wAxis( ) + ); +} + +__forceinline const Matrix4 Matrix4::rotation( const Quat &unitQuat ) +{ + return Matrix4( Transform3::rotation( unitQuat ) ); +} + +__forceinline const Matrix4 Matrix4::scale( const Vector3 &scaleVec ) +{ + __m128 zero = _mm_setzero_ps(); + __declspec(align(16)) unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + __declspec(align(16)) unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + return Matrix4( + Vector4( vec_sel( zero, scaleVec.get128(), select_x ) ), + Vector4( vec_sel( zero, scaleVec.get128(), select_y ) ), + Vector4( vec_sel( zero, scaleVec.get128(), select_z ) ), + Vector4::wAxis( ) + ); +} + +__forceinline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 &scaleVec ) +{ + return Matrix4( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ), + mat.getCol3() + ); +} + +__forceinline const Matrix4 prependScale( const Vector3 &scaleVec, const Matrix4 & mat ) +{ + Vector4 scale4; + scale4 = Vector4( scaleVec, 1.0f ); + return Matrix4( + mulPerElem( mat.getCol0(), scale4 ), + mulPerElem( mat.getCol1(), scale4 ), + mulPerElem( mat.getCol2(), scale4 ), + mulPerElem( mat.getCol3(), scale4 ) + ); +} + +__forceinline const Matrix4 Matrix4::translation( const Vector3 &translateVec ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4( translateVec, 1.0f ) + ); +} + +__forceinline const Matrix4 Matrix4::lookAt( const Point3 &eyePos, const Point3 &lookAtPos, const Vector3 &upVec ) +{ + Matrix4 m4EyeFrame; + Vector3 v3X, v3Y, v3Z; + v3Y = normalize( upVec ); + v3Z = normalize( ( eyePos - lookAtPos ) ); + v3X = normalize( cross( v3Y, v3Z ) ); + v3Y = cross( v3Z, v3X ); + m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); + return orthoInverse( m4EyeFrame ); +} + +__forceinline const Matrix4 Matrix4::perspective( float fovyRadians, float aspect, float zNear, float zFar ) +{ + float f, rangeInv; + __m128 zero, col0, col1, col2, col3; + union { __m128 v; float s[4]; } tmp; + f = tanf( _VECTORMATH_PI_OVER_2 - fovyRadians * 0.5f ); + rangeInv = 1.0f / ( zNear - zFar ); + zero = _mm_setzero_ps(); + tmp.v = zero; + tmp.s[0] = f / aspect; + col0 = tmp.v; + tmp.v = zero; + tmp.s[1] = f; + col1 = tmp.v; + tmp.v = zero; + tmp.s[2] = ( zNear + zFar ) * rangeInv; + tmp.s[3] = -1.0f; + col2 = tmp.v; + tmp.v = zero; + tmp.s[2] = zNear * zFar * rangeInv * 2.0f; + col3 = tmp.v; + return Matrix4( + Vector4( col0 ), + Vector4( col1 ), + Vector4( col2 ), + Vector4( col3 ) + ); +} + +__forceinline const Matrix4 Matrix4::frustum( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + __m128 lbf, rtn; + __m128 diff, sum, inv_diff; + __m128 diagonal, column, near2; + __m128 zero = _mm_setzero_ps(); + union { __m128 v; float s[4]; } l, f, r, n, b, t; // TODO: Union? + l.s[0] = left; + f.s[0] = zFar; + r.s[0] = right; + n.s[0] = zNear; + b.s[0] = bottom; + t.s[0] = top; + lbf = vec_mergeh( l.v, f.v ); + rtn = vec_mergeh( r.v, n.v ); + lbf = vec_mergeh( lbf, b.v ); + rtn = vec_mergeh( rtn, t.v ); + diff = vec_sub( rtn, lbf ); + sum = vec_add( rtn, lbf ); + inv_diff = recipf4( diff ); + near2 = vec_splat( n.v, 0 ); + near2 = vec_add( near2, near2 ); + diagonal = vec_mul( near2, inv_diff ); + column = vec_mul( sum, inv_diff ); + __declspec(align(16)) unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + __declspec(align(16)) unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + __declspec(align(16)) unsigned int select_w[4] = {0, 0, 0, 0xffffffff}; + return Matrix4( + Vector4( vec_sel( zero, diagonal, select_x ) ), + Vector4( vec_sel( zero, diagonal, select_y ) ), + Vector4( vec_sel( column, _mm_set1_ps(-1.0f), select_w ) ), + Vector4( vec_sel( zero, vec_mul( diagonal, vec_splat( f.v, 0 ) ), select_z ) ) + ); +} + +__forceinline const Matrix4 Matrix4::orthographic( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + __m128 lbf, rtn; + __m128 diff, sum, inv_diff, neg_inv_diff; + __m128 diagonal, column; + __m128 zero = _mm_setzero_ps(); + union { __m128 v; float s[4]; } l, f, r, n, b, t; + l.s[0] = left; + f.s[0] = zFar; + r.s[0] = right; + n.s[0] = zNear; + b.s[0] = bottom; + t.s[0] = top; + lbf = vec_mergeh( l.v, f.v ); + rtn = vec_mergeh( r.v, n.v ); + lbf = vec_mergeh( lbf, b.v ); + rtn = vec_mergeh( rtn, t.v ); + diff = vec_sub( rtn, lbf ); + sum = vec_add( rtn, lbf ); + inv_diff = recipf4( diff ); + neg_inv_diff = negatef4( inv_diff ); + diagonal = vec_add( inv_diff, inv_diff ); + __declspec(align(16)) unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + __declspec(align(16)) unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + __declspec(align(16)) unsigned int select_w[4] = {0, 0, 0, 0xffffffff}; + column = vec_mul( sum, vec_sel( neg_inv_diff, inv_diff, select_z ) ); // TODO: no madds with zero + return Matrix4( + Vector4( vec_sel( zero, diagonal, select_x ) ), + Vector4( vec_sel( zero, diagonal, select_y ) ), + Vector4( vec_sel( zero, diagonal, select_z ) ), + Vector4( vec_sel( column, _mm_set1_ps(1.0f), select_w ) ) + ); +} + +__forceinline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +__forceinline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, const boolInVec &select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +__forceinline void print( const Matrix4 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); + print( mat.getRow( 3 ) ); +} + +__forceinline void print( const Matrix4 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +__forceinline Transform3::Transform3( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; +} + +__forceinline Transform3::Transform3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +__forceinline Transform3::Transform3( const floatInVec &scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +__forceinline Transform3::Transform3( const Vector3 &_col0, const Vector3 &_col1, const Vector3 &_col2, const Vector3 &_col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +__forceinline Transform3::Transform3( const Matrix3 & tfrm, const Vector3 &translateVec ) +{ + this->setUpper3x3( tfrm ); + this->setTranslation( translateVec ); +} + +__forceinline Transform3::Transform3( const Quat &unitQuat, const Vector3 &translateVec ) +{ + this->setUpper3x3( Matrix3( unitQuat ) ); + this->setTranslation( translateVec ); +} + +__forceinline Transform3 & Transform3::setCol0( const Vector3 &_col0 ) +{ + mCol0 = _col0; + return *this; +} + +__forceinline Transform3 & Transform3::setCol1( const Vector3 &_col1 ) +{ + mCol1 = _col1; + return *this; +} + +__forceinline Transform3 & Transform3::setCol2( const Vector3 &_col2 ) +{ + mCol2 = _col2; + return *this; +} + +__forceinline Transform3 & Transform3::setCol3( const Vector3 &_col3 ) +{ + mCol3 = _col3; + return *this; +} + +__forceinline Transform3 & Transform3::setCol( int col, const Vector3 &vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +__forceinline Transform3 & Transform3::setRow( int row, const Vector4 &vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +__forceinline Transform3 & Transform3::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +__forceinline Transform3 & Transform3::setElem( int col, int row, const floatInVec &val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +__forceinline const floatInVec Transform3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +__forceinline const Vector3 Transform3::getCol0( ) const +{ + return mCol0; +} + +__forceinline const Vector3 Transform3::getCol1( ) const +{ + return mCol1; +} + +__forceinline const Vector3 Transform3::getCol2( ) const +{ + return mCol2; +} + +__forceinline const Vector3 Transform3::getCol3( ) const +{ + return mCol3; +} + +__forceinline const Vector3 Transform3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +__forceinline const Vector4 Transform3::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +__forceinline Vector3 & Transform3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +__forceinline const Vector3 Transform3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +__forceinline Transform3 & Transform3::operator =( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; + return *this; +} + +__forceinline const Transform3 inverse( const Transform3 & tfrm ) +{ + __m128 inv0, inv1, inv2, inv3; + __m128 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet; + __m128 xxxx, yyyy, zzzz; + tmp2 = _vmathVfCross( tfrm.getCol0().get128(), tfrm.getCol1().get128() ); + tmp0 = _vmathVfCross( tfrm.getCol1().get128(), tfrm.getCol2().get128() ); + tmp1 = _vmathVfCross( tfrm.getCol2().get128(), tfrm.getCol0().get128() ); + inv3 = negatef4( tfrm.getCol3().get128() ); + dot = _vmathVfDot3( tmp2, tfrm.getCol2().get128() ); + dot = vec_splat( dot, 0 ); + invdet = recipf4( dot ); + tmp3 = vec_mergeh( tmp0, tmp2 ); + tmp4 = vec_mergel( tmp0, tmp2 ); + inv0 = vec_mergeh( tmp3, tmp1 ); + xxxx = vec_splat( inv3, 0 ); + //inv1 = vec_perm( tmp3, tmp1, _VECTORMATH_PERM_ZBWX ); + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + inv1 = _mm_shuffle_ps( tmp3, tmp3, _MM_SHUFFLE(0,3,2,2)); + inv1 = vec_sel(inv1, tmp1, select_y); + //inv2 = vec_perm( tmp4, tmp1, _VECTORMATH_PERM_XCYX ); + inv2 = _mm_shuffle_ps( tmp4, tmp4, _MM_SHUFFLE(0,1,1,0)); + inv2 = vec_sel(inv2, vec_splat(tmp1, 2), select_y); + yyyy = vec_splat( inv3, 1 ); + zzzz = vec_splat( inv3, 2 ); + inv3 = vec_mul( inv0, xxxx ); + inv3 = vec_madd( inv1, yyyy, inv3 ); + inv3 = vec_madd( inv2, zzzz, inv3 ); + inv0 = vec_mul( inv0, invdet ); + inv1 = vec_mul( inv1, invdet ); + inv2 = vec_mul( inv2, invdet ); + inv3 = vec_mul( inv3, invdet ); + return Transform3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ), + Vector3( inv3 ) + ); +} + +__forceinline const Transform3 orthoInverse( const Transform3 & tfrm ) +{ + __m128 inv0, inv1, inv2, inv3; + __m128 tmp0, tmp1; + __m128 xxxx, yyyy, zzzz; + tmp0 = vec_mergeh( tfrm.getCol0().get128(), tfrm.getCol2().get128() ); + tmp1 = vec_mergel( tfrm.getCol0().get128(), tfrm.getCol2().get128() ); + inv3 = negatef4( tfrm.getCol3().get128() ); + inv0 = vec_mergeh( tmp0, tfrm.getCol1().get128() ); + xxxx = vec_splat( inv3, 0 ); + //inv1 = vec_perm( tmp0, tfrm.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + inv1 = _mm_shuffle_ps( tmp0, tmp0, _MM_SHUFFLE(0,3,2,2)); + inv1 = vec_sel(inv1, tfrm.getCol1().get128(), select_y); + //inv2 = vec_perm( tmp1, tfrm.getCol1().get128(), _VECTORMATH_PERM_XCYX ); + inv2 = _mm_shuffle_ps( tmp1, tmp1, _MM_SHUFFLE(0,1,1,0)); + inv2 = vec_sel(inv2, vec_splat(tfrm.getCol1().get128(), 2), select_y); + yyyy = vec_splat( inv3, 1 ); + zzzz = vec_splat( inv3, 2 ); + inv3 = vec_mul( inv0, xxxx ); + inv3 = vec_madd( inv1, yyyy, inv3 ); + inv3 = vec_madd( inv2, zzzz, inv3 ); + return Transform3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ), + Vector3( inv3 ) + ); +} + +__forceinline const Transform3 absPerElem( const Transform3 & tfrm ) +{ + return Transform3( + absPerElem( tfrm.getCol0() ), + absPerElem( tfrm.getCol1() ), + absPerElem( tfrm.getCol2() ), + absPerElem( tfrm.getCol3() ) + ); +} + +__forceinline const Vector3 Transform3::operator *( const Vector3 &vec ) const +{ + __m128 res; + __m128 xxxx, yyyy, zzzz; + xxxx = vec_splat( vec.get128(), 0 ); + yyyy = vec_splat( vec.get128(), 1 ); + zzzz = vec_splat( vec.get128(), 2 ); + res = vec_mul( mCol0.get128(), xxxx ); + res = vec_madd( mCol1.get128(), yyyy, res ); + res = vec_madd( mCol2.get128(), zzzz, res ); + return Vector3( res ); +} + +__forceinline const Point3 Transform3::operator *( const Point3 &pnt ) const +{ + __m128 tmp0, tmp1, res; + __m128 xxxx, yyyy, zzzz; + xxxx = vec_splat( pnt.get128(), 0 ); + yyyy = vec_splat( pnt.get128(), 1 ); + zzzz = vec_splat( pnt.get128(), 2 ); + tmp0 = vec_mul( mCol0.get128(), xxxx ); + tmp1 = vec_mul( mCol1.get128(), yyyy ); + tmp0 = vec_madd( mCol2.get128(), zzzz, tmp0 ); + tmp1 = vec_add( mCol3.get128(), tmp1 ); + res = vec_add( tmp0, tmp1 ); + return Point3( res ); +} + +__forceinline const Transform3 Transform3::operator *( const Transform3 & tfrm ) const +{ + return Transform3( + ( *this * tfrm.mCol0 ), + ( *this * tfrm.mCol1 ), + ( *this * tfrm.mCol2 ), + Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) + ); +} + +__forceinline Transform3 & Transform3::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +__forceinline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) +{ + return Transform3( + mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), + mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), + mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), + mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) + ); +} + +__forceinline const Transform3 Transform3::identity( ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +__forceinline Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) +{ + mCol0 = tfrm.getCol0(); + mCol1 = tfrm.getCol1(); + mCol2 = tfrm.getCol2(); + return *this; +} + +__forceinline const Matrix3 Transform3::getUpper3x3( ) const +{ + return Matrix3( mCol0, mCol1, mCol2 ); +} + +__forceinline Transform3 & Transform3::setTranslation( const Vector3 &translateVec ) +{ + mCol3 = translateVec; + return *this; +} + +__forceinline const Vector3 Transform3::getTranslation( ) const +{ + return mCol3; +} + +__forceinline const Transform3 Transform3::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +__forceinline const Transform3 Transform3::rotationX( const floatInVec &radians ) +{ + __m128 s, c, res1, res2; + __m128 zero; + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + __declspec(align(16)) unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + return Transform3( + Vector3::xAxis( ), + Vector3( res1 ), + Vector3( res2 ), + Vector3( _mm_setzero_ps() ) + ); +} + +__forceinline const Transform3 Transform3::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +__forceinline const Transform3 Transform3::rotationY( const floatInVec &radians ) +{ + __m128 s, c, res0, res2; + __m128 zero; + __declspec(align(16)) unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + return Transform3( + Vector3( res0 ), + Vector3::yAxis( ), + Vector3( res2 ), + Vector3( 0.0f ) + ); +} + +__forceinline const Transform3 Transform3::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +__forceinline const Transform3 Transform3::rotationZ( const floatInVec &radians ) +{ + __m128 s, c, res0, res1; + __declspec(align(16)) unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + __m128 zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + return Transform3( + Vector3( res0 ), + Vector3( res1 ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +__forceinline const Transform3 Transform3::rotationZYX( const Vector3 &radiansXYZ ) +{ + __m128 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + angles = Vector4( radiansXYZ, 0.0f ).get128(); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + __declspec(align(16)) unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; + Z1 = vec_and( Z1, _mm_load_ps( (float *)select_xyz ) ); + Y0 = _mm_shuffle_ps( c, negS, _MM_SHUFFLE(0,1,1,1) ); + Y1 = _mm_shuffle_ps( s, c, _MM_SHUFFLE(0,1,1,1) ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_mul( Z0, Y1 ); + return Transform3( + Vector3( vec_mul( Z0, Y0 ) ), + Vector3( vec_madd( Z1, X1, vec_mul( tmp, X0 ) ) ), + Vector3( vec_nmsub( Z1, X0, vec_mul( tmp, X1 ) ) ), + Vector3( 0.0f ) + ); +} + +__forceinline const Transform3 Transform3::rotation( float radians, const Vector3 &unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +__forceinline const Transform3 Transform3::rotation( const floatInVec &radians, const Vector3 &unitVec ) +{ + return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( 0.0f ) ); +} + +__forceinline const Transform3 Transform3::rotation( const Quat &unitQuat ) +{ + return Transform3( Matrix3( unitQuat ), Vector3( 0.0f ) ); +} + +__forceinline const Transform3 Transform3::scale( const Vector3 &scaleVec ) +{ + __m128 zero = _mm_setzero_ps(); + __declspec(align(16)) unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + __declspec(align(16)) unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + return Transform3( + Vector3( vec_sel( zero, scaleVec.get128(), select_x ) ), + Vector3( vec_sel( zero, scaleVec.get128(), select_y ) ), + Vector3( vec_sel( zero, scaleVec.get128(), select_z ) ), + Vector3( 0.0f ) + ); +} + +__forceinline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 &scaleVec ) +{ + return Transform3( + ( tfrm.getCol0() * scaleVec.getX( ) ), + ( tfrm.getCol1() * scaleVec.getY( ) ), + ( tfrm.getCol2() * scaleVec.getZ( ) ), + tfrm.getCol3() + ); +} + +__forceinline const Transform3 prependScale( const Vector3 &scaleVec, const Transform3 & tfrm ) +{ + return Transform3( + mulPerElem( tfrm.getCol0(), scaleVec ), + mulPerElem( tfrm.getCol1(), scaleVec ), + mulPerElem( tfrm.getCol2(), scaleVec ), + mulPerElem( tfrm.getCol3(), scaleVec ) + ); +} + +__forceinline const Transform3 Transform3::translation( const Vector3 &translateVec ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + translateVec + ); +} + +__forceinline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +__forceinline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, const boolInVec &select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +__forceinline void print( const Transform3 & tfrm ) +{ + print( tfrm.getRow( 0 ) ); + print( tfrm.getRow( 1 ) ); + print( tfrm.getRow( 2 ) ); +} + +__forceinline void print( const Transform3 & tfrm, const char * name ) +{ + printf("%s:\n", name); + print( tfrm ); +} + +#endif + +__forceinline Quat::Quat( const Matrix3 & tfrm ) +{ + __m128 res; + __m128 col0, col1, col2; + __m128 xx_yy, xx_yy_zz_xx, yy_zz_xx_yy, zz_xx_yy_zz, diagSum, diagDiff; + __m128 zy_xz_yx, yz_zx_xy, sum, diff; + __m128 radicand, invSqrt, scale; + __m128 res0, res1, res2, res3; + __m128 xx, yy, zz; + __declspec(align(16)) unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + __declspec(align(16)) unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + __declspec(align(16)) unsigned int select_w[4] = {0, 0, 0, 0xffffffff}; + + col0 = tfrm.getCol0().get128(); + col1 = tfrm.getCol1().get128(); + col2 = tfrm.getCol2().get128(); + + /* four cases: */ + /* trace > 0 */ + /* else */ + /* xx largest diagonal element */ + /* yy largest diagonal element */ + /* zz largest diagonal element */ + + /* compute quaternion for each case */ + + xx_yy = vec_sel( col0, col1, select_y ); + //xx_yy_zz_xx = vec_perm( xx_yy, col2, _VECTORMATH_PERM_XYCX ); + //yy_zz_xx_yy = vec_perm( xx_yy, col2, _VECTORMATH_PERM_YCXY ); + //zz_xx_yy_zz = vec_perm( xx_yy, col2, _VECTORMATH_PERM_CXYC ); + xx_yy_zz_xx = _mm_shuffle_ps( xx_yy, xx_yy, _MM_SHUFFLE(0,0,1,0) ); + xx_yy_zz_xx = vec_sel( xx_yy_zz_xx, col2, select_z ); // TODO: Ck + yy_zz_xx_yy = _mm_shuffle_ps( xx_yy_zz_xx, xx_yy_zz_xx, _MM_SHUFFLE(1,0,2,1) ); + zz_xx_yy_zz = _mm_shuffle_ps( xx_yy_zz_xx, xx_yy_zz_xx, _MM_SHUFFLE(2,1,0,2) ); + + diagSum = vec_add( vec_add( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); + diagDiff = vec_sub( vec_sub( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); + radicand = vec_add( vec_sel( diagDiff, diagSum, select_w ), _mm_set1_ps(1.0f) ); + // invSqrt = rsqrtf4( radicand ); + invSqrt = newtonrapson_rsqrt4( radicand ); + + + + zy_xz_yx = vec_sel( col0, col1, select_z ); // zy_xz_yx = 00 01 12 03 + //zy_xz_yx = vec_perm( zy_xz_yx, col2, _VECTORMATH_PERM_ZAYX ); + zy_xz_yx = _mm_shuffle_ps( zy_xz_yx, zy_xz_yx, _MM_SHUFFLE(0,1,2,2) ); // zy_xz_yx = 12 12 01 00 + zy_xz_yx = vec_sel( zy_xz_yx, vec_splat(col2, 0), select_y ); // zy_xz_yx = 12 20 01 00 + yz_zx_xy = vec_sel( col0, col1, select_x ); // yz_zx_xy = 10 01 02 03 + //yz_zx_xy = vec_perm( yz_zx_xy, col2, _VECTORMATH_PERM_BZXX ); + yz_zx_xy = _mm_shuffle_ps( yz_zx_xy, yz_zx_xy, _MM_SHUFFLE(0,0,2,0) ); // yz_zx_xy = 10 02 10 10 + yz_zx_xy = vec_sel( yz_zx_xy, vec_splat(col2, 1), select_x ); // yz_zx_xy = 21 02 10 10 + + sum = vec_add( zy_xz_yx, yz_zx_xy ); + diff = vec_sub( zy_xz_yx, yz_zx_xy ); + + scale = vec_mul( invSqrt, _mm_set1_ps(0.5f) ); + + //res0 = vec_perm( sum, diff, _VECTORMATH_PERM_XZYA ); + res0 = _mm_shuffle_ps( sum, sum, _MM_SHUFFLE(0,1,2,0) ); + res0 = vec_sel( res0, vec_splat(diff, 0), select_w ); // TODO: Ck + //res1 = vec_perm( sum, diff, _VECTORMATH_PERM_ZXXB ); + res1 = _mm_shuffle_ps( sum, sum, _MM_SHUFFLE(0,0,0,2) ); + res1 = vec_sel( res1, vec_splat(diff, 1), select_w ); // TODO: Ck + //res2 = vec_perm( sum, diff, _VECTORMATH_PERM_YXXC ); + res2 = _mm_shuffle_ps( sum, sum, _MM_SHUFFLE(0,0,0,1) ); + res2 = vec_sel( res2, vec_splat(diff, 2), select_w ); // TODO: Ck + res3 = diff; + res0 = vec_sel( res0, radicand, select_x ); + res1 = vec_sel( res1, radicand, select_y ); + res2 = vec_sel( res2, radicand, select_z ); + res3 = vec_sel( res3, radicand, select_w ); + res0 = vec_mul( res0, vec_splat( scale, 0 ) ); + res1 = vec_mul( res1, vec_splat( scale, 1 ) ); + res2 = vec_mul( res2, vec_splat( scale, 2 ) ); + res3 = vec_mul( res3, vec_splat( scale, 3 ) ); + + /* determine case and select answer */ + + xx = vec_splat( col0, 0 ); + yy = vec_splat( col1, 1 ); + zz = vec_splat( col2, 2 ); + res = vec_sel( res0, res1, vec_cmpgt( yy, xx ) ); + res = vec_sel( res, res2, vec_and( vec_cmpgt( zz, xx ), vec_cmpgt( zz, yy ) ) ); + res = vec_sel( res, res3, vec_cmpgt( vec_splat( diagSum, 0 ), _mm_setzero_ps() ) ); + mVec128 = res; +} + +__forceinline const Matrix3 outer( const Vector3 &tfrm0, const Vector3 &tfrm1 ) +{ + return Matrix3( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ) + ); +} + +__forceinline const Matrix4 outer( const Vector4 &tfrm0, const Vector4 &tfrm1 ) +{ + return Matrix4( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ), + ( tfrm0 * tfrm1.getW( ) ) + ); +} + +__forceinline const Vector3 rowMul( const Vector3 &vec, const Matrix3 & mat ) +{ + __m128 tmp0, tmp1, mcol0, mcol1, mcol2, res; + __m128 xxxx, yyyy, zzzz; + tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp1 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); + xxxx = vec_splat( vec.get128(), 0 ); + mcol0 = vec_mergeh( tmp0, mat.getCol1().get128() ); + //mcol1 = vec_perm( tmp0, mat.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + mcol1 = _mm_shuffle_ps( tmp0, tmp0, _MM_SHUFFLE(0,3,2,2)); + mcol1 = vec_sel(mcol1, mat.getCol1().get128(), select_y); + //mcol2 = vec_perm( tmp1, mat.getCol1().get128(), _VECTORMATH_PERM_XCYX ); + mcol2 = _mm_shuffle_ps( tmp1, tmp1, _MM_SHUFFLE(0,1,1,0)); + mcol2 = vec_sel(mcol2, vec_splat(mat.getCol1().get128(), 2), select_y); + yyyy = vec_splat( vec.get128(), 1 ); + res = vec_mul( mcol0, xxxx ); + zzzz = vec_splat( vec.get128(), 2 ); + res = vec_madd( mcol1, yyyy, res ); + res = vec_madd( mcol2, zzzz, res ); + return Vector3( res ); +} + +__forceinline const Matrix3 crossMatrix( const Vector3 &vec ) +{ + __m128 neg, res0, res1, res2; + neg = negatef4( vec.get128() ); + __declspec(align(16)) unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + __declspec(align(16)) unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + //res0 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_XZBX ); + res0 = _mm_shuffle_ps( vec.get128(), vec.get128(), _MM_SHUFFLE(0,2,2,0) ); + res0 = vec_sel(res0, vec_splat(neg, 1), select_z); + //res1 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_CXXX ); + res1 = vec_sel(vec_splat(vec.get128(), 0), vec_splat(neg, 2), select_x); + //res2 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_YAXX ); + res2 = _mm_shuffle_ps( vec.get128(), vec.get128(), _MM_SHUFFLE(0,0,1,1) ); + res2 = vec_sel(res2, vec_splat(neg, 0), select_y); + __declspec(align(16)) unsigned int filter_x[4] = {0, 0xffffffff, 0xffffffff, 0xffffffff}; + __declspec(align(16)) unsigned int filter_y[4] = {0xffffffff, 0, 0xffffffff, 0xffffffff}; + __declspec(align(16)) unsigned int filter_z[4] = {0xffffffff, 0xffffffff, 0, 0xffffffff}; + res0 = vec_and( res0, _mm_load_ps((float *)filter_x ) ); + res1 = vec_and( res1, _mm_load_ps((float *)filter_y ) ); + res2 = vec_and( res2, _mm_load_ps((float *)filter_z ) ); // TODO: Use selects? + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +__forceinline const Matrix3 crossMatrixMul( const Vector3 &vec, const Matrix3 & mat ) +{ + return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); +} + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/SSE/cpp/quat_aos.h b/Extras/vectormathlibrary/include/vectormath/SSE/cpp/quat_aos.h new file mode 100644 index 0000000..081cb3a --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/SSE/cpp/quat_aos.h @@ -0,0 +1,568 @@ +/* + Copyright (C) 2006, 2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _VECTORMATH_QUAT_AOS_CPP_H +#define _VECTORMATH_QUAT_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +__forceinline void Quat::set128(vec_float4 vec) +{ + mVec128 = vec; +} + +__forceinline Quat::Quat( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z, const floatInVec &_w ) +{ + mVec128 = _mm_unpacklo_ps( + _mm_unpacklo_ps( _x.get128(), _z.get128() ), + _mm_unpacklo_ps( _y.get128(), _w.get128() ) ); +} + +__forceinline Quat::Quat( const Vector3 &xyz, float _w ) +{ + mVec128 = xyz.get128(); + _vmathVfSetElement(mVec128, _w, 3); +} + + + +__forceinline Quat::Quat(const Quat& quat) +{ + mVec128 = quat.get128(); +} + +__forceinline Quat::Quat( float _x, float _y, float _z, float _w ) +{ + mVec128 = _mm_setr_ps(_x, _y, _z, _w); +} + + + + + +__forceinline Quat::Quat( const Vector3 &xyz, const floatInVec &_w ) +{ + mVec128 = xyz.get128(); + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); +} + +__forceinline Quat::Quat( const Vector4 &vec ) +{ + mVec128 = vec.get128(); +} + +__forceinline Quat::Quat( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +__forceinline Quat::Quat( const floatInVec &scalar ) +{ + mVec128 = scalar.get128(); +} + +__forceinline Quat::Quat( __m128 vf4 ) +{ + mVec128 = vf4; +} + +__forceinline const Quat Quat::identity( ) +{ + return Quat( _VECTORMATH_UNIT_0001 ); +} + +__forceinline const Quat lerp( float t, const Quat &quat0, const Quat &quat1 ) +{ + return lerp( floatInVec(t), quat0, quat1 ); +} + +__forceinline const Quat lerp( const floatInVec &t, const Quat &quat0, const Quat &quat1 ) +{ + return ( quat0 + ( ( quat1 - quat0 ) * t ) ); +} + +__forceinline const Quat slerp( float t, const Quat &unitQuat0, const Quat &unitQuat1 ) +{ + return slerp( floatInVec(t), unitQuat0, unitQuat1 ); +} + +__forceinline const Quat slerp( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1 ) +{ + Quat start; + vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + __m128 selectMask; + cosAngle = _vmathVfDot4( unitQuat0.get128(), unitQuat1.get128() ); + selectMask = (__m128)vec_cmpgt( _mm_setzero_ps(), cosAngle ); + cosAngle = vec_sel( cosAngle, negatef4( cosAngle ), selectMask ); + start = Quat( vec_sel( unitQuat0.get128(), negatef4( unitQuat0.get128() ), selectMask ) ); + selectMask = (__m128)vec_cmpgt( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = t.get128(); + oneMinusT = vec_sub( _mm_set1_ps(1.0f), tttt ); + angles = vec_mergeh( _mm_set1_ps(1.0f), tttt ); + angles = vec_mergeh( angles, oneMinusT ); + angles = vec_madd( angles, angle, _mm_setzero_ps() ); + sines = sinf4( angles ); + scales = _mm_div_ps( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + return Quat( vec_madd( start.get128(), scale0, vec_mul( unitQuat1.get128(), scale1 ) ) ); +} + +__forceinline const Quat squad( float t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ) +{ + return squad( floatInVec(t), unitQuat0, unitQuat1, unitQuat2, unitQuat3 ); +} + +__forceinline const Quat squad( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ) +{ + return slerp( ( ( floatInVec(2.0f) * t ) * ( floatInVec(1.0f) - t ) ), slerp( t, unitQuat0, unitQuat3 ), slerp( t, unitQuat1, unitQuat2 ) ); +} + +__forceinline __m128 Quat::get128( ) const +{ + return mVec128; +} + +__forceinline Quat & Quat::operator =( const Quat &quat ) +{ + mVec128 = quat.mVec128; + return *this; +} + +__forceinline Quat & Quat::setXYZ( const Vector3 &vec ) +{ + __declspec(align(16)) unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + mVec128 = vec_sel( vec.get128(), mVec128, sw ); + return *this; +} + +__forceinline const Vector3 Quat::getXYZ( ) const +{ + return Vector3( mVec128 ); +} + +__forceinline Quat & Quat::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +__forceinline Quat & Quat::setX( const floatInVec &_x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +__forceinline const floatInVec Quat::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +__forceinline Quat & Quat::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +__forceinline Quat & Quat::setY( const floatInVec &_y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +__forceinline const floatInVec Quat::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +__forceinline Quat & Quat::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +__forceinline Quat & Quat::setZ( const floatInVec &_z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +__forceinline const floatInVec Quat::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +__forceinline Quat & Quat::setW( float _w ) +{ + _vmathVfSetElement(mVec128, _w, 3); + return *this; +} + +__forceinline Quat & Quat::setW( const floatInVec &_w ) +{ + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); + return *this; +} + +__forceinline const floatInVec Quat::getW( ) const +{ + return floatInVec( mVec128, 3 ); +} + +__forceinline Quat & Quat::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +__forceinline Quat & Quat::setElem( int idx, const floatInVec &value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +__forceinline const floatInVec Quat::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +__forceinline VecIdx Quat::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +__forceinline const floatInVec Quat::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +__forceinline const Quat Quat::operator +( const Quat &quat ) const +{ + return Quat( _mm_add_ps( mVec128, quat.mVec128 ) ); +} + + +__forceinline const Quat Quat::operator -( const Quat &quat ) const +{ + return Quat( _mm_sub_ps( mVec128, quat.mVec128 ) ); +} + +__forceinline const Quat Quat::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +__forceinline const Quat Quat::operator *( const floatInVec &scalar ) const +{ + return Quat( _mm_mul_ps( mVec128, scalar.get128() ) ); +} + +__forceinline Quat & Quat::operator +=( const Quat &quat ) +{ + *this = *this + quat; + return *this; +} + +__forceinline Quat & Quat::operator -=( const Quat &quat ) +{ + *this = *this - quat; + return *this; +} + +__forceinline Quat & Quat::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +__forceinline Quat & Quat::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +__forceinline const Quat Quat::operator /( float scalar ) const +{ + return *this / floatInVec(scalar); +} + +__forceinline const Quat Quat::operator /( const floatInVec &scalar ) const +{ + return Quat( _mm_div_ps( mVec128, scalar.get128() ) ); +} + +__forceinline Quat & Quat::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +__forceinline Quat & Quat::operator /=( const floatInVec &scalar ) +{ + *this = *this / scalar; + return *this; +} + +__forceinline const Quat Quat::operator -( ) const +{ + return Quat(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) ); +} + +__forceinline const Quat operator *( float scalar, const Quat &quat ) +{ + return floatInVec(scalar) * quat; +} + +__forceinline const Quat operator *( const floatInVec &scalar, const Quat &quat ) +{ + return quat * scalar; +} + +__forceinline const floatInVec dot( const Quat &quat0, const Quat &quat1 ) +{ + return floatInVec( _vmathVfDot4( quat0.get128(), quat1.get128() ), 0 ); +} + +__forceinline const floatInVec norm( const Quat &quat ) +{ + return floatInVec( _vmathVfDot4( quat.get128(), quat.get128() ), 0 ); +} + +__forceinline const floatInVec length( const Quat &quat ) +{ + return floatInVec( _mm_sqrt_ps(_vmathVfDot4( quat.get128(), quat.get128() )), 0 ); +} + +__forceinline const Quat normalize( const Quat &quat ) +{ + vec_float4 dot =_vmathVfDot4( quat.get128(), quat.get128()); + return Quat( _mm_mul_ps( quat.get128(), newtonrapson_rsqrt4( dot ) ) ); +} + + +__forceinline const Quat Quat::rotation( const Vector3 &unitVec0, const Vector3 &unitVec1 ) +{ + Vector3 crossVec; + __m128 cosAngle, cosAngleX2Plus2, recipCosHalfAngleX2, cosHalfAngleX2, res; + cosAngle = _vmathVfDot3( unitVec0.get128(), unitVec1.get128() ); + cosAngleX2Plus2 = vec_madd( cosAngle, _mm_set1_ps(2.0f), _mm_set1_ps(2.0f) ); + recipCosHalfAngleX2 = _mm_rsqrt_ps( cosAngleX2Plus2 ); + cosHalfAngleX2 = vec_mul( recipCosHalfAngleX2, cosAngleX2Plus2 ); + crossVec = cross( unitVec0, unitVec1 ); + res = vec_mul( crossVec.get128(), recipCosHalfAngleX2 ); + __declspec(align(16)) unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( res, vec_mul( cosHalfAngleX2, _mm_set1_ps(0.5f) ), sw ); + return Quat( res ); +} + +__forceinline const Quat Quat::rotation( float radians, const Vector3 &unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +__forceinline const Quat Quat::rotation( const floatInVec &radians, const Vector3 &unitVec ) +{ + __m128 s, c, angle, res; + angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); + sincosf4( angle, &s, &c ); + __declspec(align(16)) unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( vec_mul( unitVec.get128(), s ), c, sw ); + return Quat( res ); +} + +__forceinline const Quat Quat::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +__forceinline const Quat Quat::rotationX( const floatInVec &radians ) +{ + __m128 s, c, angle, res; + angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); + sincosf4( angle, &s, &c ); + __declspec(align(16)) unsigned int xsw[4] = {0xffffffff, 0, 0, 0}; + __declspec(align(16)) unsigned int wsw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( _mm_setzero_ps(), s, xsw ); + res = vec_sel( res, c, wsw ); + return Quat( res ); +} + +__forceinline const Quat Quat::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +__forceinline const Quat Quat::rotationY( const floatInVec &radians ) +{ + __m128 s, c, angle, res; + angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); + sincosf4( angle, &s, &c ); + __declspec(align(16)) unsigned int ysw[4] = {0, 0xffffffff, 0, 0}; + __declspec(align(16)) unsigned int wsw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( _mm_setzero_ps(), s, ysw ); + res = vec_sel( res, c, wsw ); + return Quat( res ); +} + +__forceinline const Quat Quat::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +__forceinline const Quat Quat::rotationZ( const floatInVec &radians ) +{ + __m128 s, c, angle, res; + angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); + sincosf4( angle, &s, &c ); + __declspec(align(16)) unsigned int zsw[4] = {0, 0, 0xffffffff, 0}; + __declspec(align(16)) unsigned int wsw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( _mm_setzero_ps(), s, zsw ); + res = vec_sel( res, c, wsw ); + return Quat( res ); +} + +__forceinline const Quat Quat::operator *( const Quat &quat ) const +{ + __m128 ldata, rdata, qv, tmp0, tmp1, tmp2, tmp3; + __m128 product, l_wxyz, r_wxyz, xy, qw; + ldata = mVec128; + rdata = quat.mVec128; + tmp0 = _mm_shuffle_ps( ldata, ldata, _MM_SHUFFLE(3,0,2,1) ); + tmp1 = _mm_shuffle_ps( rdata, rdata, _MM_SHUFFLE(3,1,0,2) ); + tmp2 = _mm_shuffle_ps( ldata, ldata, _MM_SHUFFLE(3,1,0,2) ); + tmp3 = _mm_shuffle_ps( rdata, rdata, _MM_SHUFFLE(3,0,2,1) ); + qv = vec_mul( vec_splat( ldata, 3 ), rdata ); + qv = vec_madd( vec_splat( rdata, 3 ), ldata, qv ); + qv = vec_madd( tmp0, tmp1, qv ); + qv = vec_nmsub( tmp2, tmp3, qv ); + product = vec_mul( ldata, rdata ); + l_wxyz = vec_sld( ldata, ldata, 12 ); + r_wxyz = vec_sld( rdata, rdata, 12 ); + qw = vec_nmsub( l_wxyz, r_wxyz, product ); + xy = vec_madd( l_wxyz, r_wxyz, product ); + qw = vec_sub( qw, vec_sld( xy, xy, 8 ) ); + __declspec(align(16)) unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + return Quat( vec_sel( qv, qw, sw ) ); +} + +__forceinline Quat & Quat::operator *=( const Quat &quat ) +{ + *this = *this * quat; + return *this; +} + +__forceinline const Vector3 rotate( const Quat &quat, const Vector3 &vec ) +{ __m128 qdata, vdata, product, tmp0, tmp1, tmp2, tmp3, wwww, qv, qw, res; + qdata = quat.get128(); + vdata = vec.get128(); + tmp0 = _mm_shuffle_ps( qdata, qdata, _MM_SHUFFLE(3,0,2,1) ); + tmp1 = _mm_shuffle_ps( vdata, vdata, _MM_SHUFFLE(3,1,0,2) ); + tmp2 = _mm_shuffle_ps( qdata, qdata, _MM_SHUFFLE(3,1,0,2) ); + tmp3 = _mm_shuffle_ps( vdata, vdata, _MM_SHUFFLE(3,0,2,1) ); + wwww = vec_splat( qdata, 3 ); + qv = vec_mul( wwww, vdata ); + qv = vec_madd( tmp0, tmp1, qv ); + qv = vec_nmsub( tmp2, tmp3, qv ); + product = vec_mul( qdata, vdata ); + qw = vec_madd( vec_sld( qdata, qdata, 4 ), vec_sld( vdata, vdata, 4 ), product ); + qw = vec_add( vec_sld( product, product, 8 ), qw ); + tmp1 = _mm_shuffle_ps( qv, qv, _MM_SHUFFLE(3,1,0,2) ); + tmp3 = _mm_shuffle_ps( qv, qv, _MM_SHUFFLE(3,0,2,1) ); + res = vec_mul( vec_splat( qw, 0 ), qdata ); + res = vec_madd( wwww, qv, res ); + res = vec_madd( tmp0, tmp1, res ); + res = vec_nmsub( tmp2, tmp3, res ); + return Vector3( res ); +} + +__forceinline const Quat conj( const Quat &quat ) +{ + __declspec(align(16)) unsigned int sw[4] = {0x80000000,0x80000000,0x80000000,0}; + return Quat( vec_xor( quat.get128(), _mm_load_ps((float *)sw) ) ); +} + +__forceinline const Quat select( const Quat &quat0, const Quat &quat1, bool select1 ) +{ + return select( quat0, quat1, boolInVec(select1) ); +} + +//__forceinline const Quat select( const Quat &quat0, const Quat &quat1, const boolInVec &select1 ) +//{ +// return Quat( vec_sel( quat0.get128(), quat1.get128(), select1.get128() ) ); +//} + +__forceinline void loadXYZW(Quat& quat, const float* fptr) +{ +#ifdef USE_SSE2_LDDQU + quat = Quat( SSEFloat(_mm_lddqu_si128((const __m128i*)((float*)(fptr)))).m128 ); +#else + SSEFloat fl; + fl.f[0] = fptr[0]; + fl.f[1] = fptr[1]; + fl.f[2] = fptr[2]; + fl.f[3] = fptr[3]; + quat = Quat( fl.m128); +#endif + + +} + +#ifdef _VECTORMATH_DEBUG + +__forceinline void print( const Quat &quat ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = quat.get128(); + printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +__forceinline void print( const Quat &quat, const char * name ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = quat.get128(); + printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/SSE/cpp/readme_e.txt b/Extras/vectormathlibrary/include/vectormath/SSE/cpp/readme_e.txt new file mode 100644 index 0000000..6f30b25 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/SSE/cpp/readme_e.txt @@ -0,0 +1 @@ +This folder contains an SSE implementation of the c++ aos component of the vectormath library as used by PSSG. \ No newline at end of file diff --git a/Extras/vectormathlibrary/include/vectormath/SSE/cpp/vec_aos.h b/Extras/vectormathlibrary/include/vectormath/SSE/cpp/vec_aos.h new file mode 100644 index 0000000..98f5607 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/SSE/cpp/vec_aos.h @@ -0,0 +1,1431 @@ +/* + Copyright (C) 2006, 2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_AOS_CPP_H +#define _VECTORMATH_VEC_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Constants +// for permutes words are labeled [x,y,z,w] [a,b,c,d] + +#define _VECTORMATH_PERM_X 0x00010203 +#define _VECTORMATH_PERM_Y 0x04050607 +#define _VECTORMATH_PERM_Z 0x08090a0b +#define _VECTORMATH_PERM_W 0x0c0d0e0f +#define _VECTORMATH_PERM_A 0x10111213 +#define _VECTORMATH_PERM_B 0x14151617 +#define _VECTORMATH_PERM_C 0x18191a1b +#define _VECTORMATH_PERM_D 0x1c1d1e1f +#define _VECTORMATH_PERM_XYZA (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A } +#define _VECTORMATH_PERM_ZXYW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_YZXW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_YZAB (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B } +#define _VECTORMATH_PERM_ZABC (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B, _VECTORMATH_PERM_C } +#define _VECTORMATH_PERM_XYAW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_XAZW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W } +#define _VECTORMATH_MASK_0xF000 (vec_uint4){ 0xffffffff, 0, 0, 0 } +#define _VECTORMATH_MASK_0x0F00 (vec_uint4){ 0, 0xffffffff, 0, 0 } +#define _VECTORMATH_MASK_0x00F0 (vec_uint4){ 0, 0, 0xffffffff, 0 } +#define _VECTORMATH_MASK_0x000F (vec_uint4){ 0, 0, 0, 0xffffffff } +#define _VECTORMATH_UNIT_1000 _mm_setr_ps(1.0f,0.0f,0.0f,0.0f) // (__m128){ 1.0f, 0.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0100 _mm_setr_ps(0.0f,1.0f,0.0f,0.0f) // (__m128){ 0.0f, 1.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0010 _mm_setr_ps(0.0f,0.0f,1.0f,0.0f) // (__m128){ 0.0f, 0.0f, 1.0f, 0.0f } +#define _VECTORMATH_UNIT_0001 _mm_setr_ps(0.0f,0.0f,0.0f,1.0f) // (__m128){ 0.0f, 0.0f, 0.0f, 1.0f } +#define _VECTORMATH_SLERP_TOL 0.999f +//_VECTORMATH_SLERP_TOLF + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#define _vmath_shufps(a, b, immx, immy, immz, immw) _mm_shuffle_ps(a, b, _MM_SHUFFLE(immw, immz, immy, immx)) +static __forceinline __m128 _vmathVfDot3( __m128 vec0, __m128 vec1 ) +{ + __m128 result = _mm_mul_ps( vec0, vec1); + return _mm_add_ps( vec_splat( result, 0 ), _mm_add_ps( vec_splat( result, 1 ), vec_splat( result, 2 ) ) ); +} + +static __forceinline __m128 _vmathVfDot4( __m128 vec0, __m128 vec1 ) +{ + __m128 result = _mm_mul_ps(vec0, vec1); + return _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(0,0,0,0)), + _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(1,1,1,1)), + _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(2,2,2,2)), _mm_shuffle_ps(result, result, _MM_SHUFFLE(3,3,3,3))))); +} + +static __forceinline __m128 _vmathVfCross( __m128 vec0, __m128 vec1 ) +{ + __m128 tmp0, tmp1, tmp2, tmp3, result; + tmp0 = _mm_shuffle_ps( vec0, vec0, _MM_SHUFFLE(3,0,2,1) ); + tmp1 = _mm_shuffle_ps( vec1, vec1, _MM_SHUFFLE(3,1,0,2) ); + tmp2 = _mm_shuffle_ps( vec0, vec0, _MM_SHUFFLE(3,1,0,2) ); + tmp3 = _mm_shuffle_ps( vec1, vec1, _MM_SHUFFLE(3,0,2,1) ); + result = vec_mul( tmp0, tmp1 ); + result = vec_nmsub( tmp2, tmp3, result ); + return result; +} +/* +static __forceinline vec_uint4 _vmathVfToHalfFloatsUnpacked(__m128 v) +{ +#if 0 + vec_int4 bexp; + vec_uint4 mant, sign, hfloat; + vec_uint4 notZero, isInf; + const vec_uint4 hfloatInf = (vec_uint4)(0x00007c00u); + const vec_uint4 mergeMant = (vec_uint4)(0x000003ffu); + const vec_uint4 mergeSign = (vec_uint4)(0x00008000u); + + sign = vec_sr((vec_uint4)v, (vec_uint4)16); + mant = vec_sr((vec_uint4)v, (vec_uint4)13); + bexp = vec_and(vec_sr((vec_int4)v, (vec_uint4)23), (vec_int4)0xff); + + notZero = (vec_uint4)vec_cmpgt(bexp, (vec_int4)112); + isInf = (vec_uint4)vec_cmpgt(bexp, (vec_int4)142); + + bexp = _mm_add_ps(bexp, (vec_int4)-112); + bexp = vec_sl(bexp, (vec_uint4)10); + + hfloat = vec_sel((vec_uint4)bexp, mant, mergeMant); + hfloat = vec_sel((vec_uint4)(0), hfloat, notZero); + hfloat = vec_sel(hfloat, hfloatInf, isInf); + hfloat = vec_sel(hfloat, sign, mergeSign); + + return hfloat; +#else + assert(0); + return _mm_setzero_ps(); +#endif +} + +static __forceinline vec_ushort8 _vmath2VfToHalfFloats(__m128 u, __m128 v) +{ +#if 0 + vec_uint4 hfloat_u, hfloat_v; + const vec_uchar16 pack = (vec_uchar16){2,3,6,7,10,11,14,15,18,19,22,23,26,27,30,31}; + hfloat_u = _vmathVfToHalfFloatsUnpacked(u); + hfloat_v = _vmathVfToHalfFloatsUnpacked(v); + return (vec_ushort8)vec_perm(hfloat_u, hfloat_v, pack); +#else + assert(0); + return _mm_setzero_si128(); +#endif +} +*/ + +static __forceinline __m128 _vmathVfInsert(__m128 dst, __m128 src, int slot) +{ + SSEFloat s; + s.m128 = src; + SSEFloat d; + d.m128 = dst; + d.f[slot] = s.f[slot]; + return d.m128; +} + +#define _vmathVfSetElement(vec, scalar, slot) ((float *)&(vec))[slot] = scalar + +static __forceinline __m128 _vmathVfSplatScalar(float scalar) +{ + return _mm_set1_ps(scalar); +} + +#endif + +namespace Vectormath { +namespace Aos { + + +#ifdef _VECTORMATH_NO_SCALAR_CAST +__forceinline VecIdx::operator floatInVec() const +{ + return floatInVec(ref, i); +} + +__forceinline float VecIdx::getAsFloat() const +#else +__forceinline VecIdx::operator float() const +#endif +{ + return ((float *)&ref)[i]; +} + +__forceinline float VecIdx::operator =( float scalar ) +{ + _vmathVfSetElement(ref, scalar, i); + return scalar; +} + +__forceinline floatInVec VecIdx::operator =( const floatInVec &scalar ) +{ + ref = _vmathVfInsert(ref, scalar.get128(), i); + return scalar; +} + +__forceinline floatInVec VecIdx::operator =( const VecIdx& scalar ) +{ + return *this = floatInVec(scalar.ref, scalar.i); +} + +__forceinline floatInVec VecIdx::operator *=( float scalar ) +{ + return *this *= floatInVec(scalar); +} + +__forceinline floatInVec VecIdx::operator *=( const floatInVec &scalar ) +{ + return *this = floatInVec(ref, i) * scalar; +} + +__forceinline floatInVec VecIdx::operator /=( float scalar ) +{ + return *this /= floatInVec(scalar); +} + +inline floatInVec VecIdx::operator /=( const floatInVec &scalar ) +{ + return *this = floatInVec(ref, i) / scalar; +} + +__forceinline floatInVec VecIdx::operator +=( float scalar ) +{ + return *this += floatInVec(scalar); +} + +__forceinline floatInVec VecIdx::operator +=( const floatInVec &scalar ) +{ + return *this = floatInVec(ref, i) + scalar; +} + +__forceinline floatInVec VecIdx::operator -=( float scalar ) +{ + return *this -= floatInVec(scalar); +} + +__forceinline floatInVec VecIdx::operator -=( const floatInVec &scalar ) +{ + return *this = floatInVec(ref, i) - scalar; +} + +__forceinline Vector3::Vector3(const Vector3& vec) +{ + set128(vec.get128()); +} + +__forceinline void Vector3::set128(vec_float4 vec) +{ + mVec128 = vec; +} + + +__forceinline Vector3::Vector3( float _x, float _y, float _z ) +{ + mVec128 = _mm_setr_ps(_x, _y, _z, 0.0f); +} + +__forceinline Vector3::Vector3( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z ) +{ + __m128 xz = _mm_unpacklo_ps( _x.get128(), _z.get128() ); + mVec128 = _mm_unpacklo_ps( xz, _y.get128() ); +} + +__forceinline Vector3::Vector3( const Point3 &pnt ) +{ + mVec128 = pnt.get128(); +} + +__forceinline Vector3::Vector3( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +__forceinline Vector3::Vector3( const floatInVec &scalar ) +{ + mVec128 = scalar.get128(); +} + +__forceinline Vector3::Vector3( __m128 vf4 ) +{ + mVec128 = vf4; +} + +__forceinline const Vector3 Vector3::xAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_1000 ); +} + +__forceinline const Vector3 Vector3::yAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_0100 ); +} + +__forceinline const Vector3 Vector3::zAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_0010 ); +} + +__forceinline const Vector3 lerp( float t, const Vector3 &vec0, const Vector3 &vec1 ) +{ + return lerp( floatInVec(t), vec0, vec1 ); +} + +__forceinline const Vector3 lerp( const floatInVec &t, const Vector3 &vec0, const Vector3 &vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +__forceinline const Vector3 slerp( float t, const Vector3 &unitVec0, const Vector3 &unitVec1 ) +{ + return slerp( floatInVec(t), unitVec0, unitVec1 ); +} + +__forceinline const Vector3 slerp( const floatInVec &t, const Vector3 &unitVec0, const Vector3 &unitVec1 ) +{ + __m128 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + cosAngle = _vmathVfDot3( unitVec0.get128(), unitVec1.get128() ); + __m128 selectMask = _mm_cmpgt_ps( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = t.get128(); + oneMinusT = _mm_sub_ps( _mm_set1_ps(1.0f), tttt ); + angles = _mm_unpacklo_ps( _mm_set1_ps(1.0f), tttt ); // angles = 1, t, 1, t + angles = _mm_unpacklo_ps( angles, oneMinusT ); // angles = 1, 1-t, t, 1-t + angles = _mm_mul_ps( angles, angle ); + sines = sinf4( angles ); + scales = _mm_div_ps( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + return Vector3( vec_madd( unitVec0.get128(), scale0, _mm_mul_ps( unitVec1.get128(), scale1 ) ) ); +} + +__forceinline __m128 Vector3::get128( ) const +{ + return mVec128; +} + +__forceinline void loadXYZ(Vector3& vec, const float* fptr) +{ +#ifdef USE_SSE2_LDDQU + vec = Vector3( SSEFloat(_mm_lddqu_si128((const __m128i*)((float*)(fptr)))).m128 ); +#else + SSEFloat fl; + fl.f[0] = fptr[0]; + fl.f[1] = fptr[1]; + fl.f[2] = fptr[2]; + fl.f[3] = fptr[3]; + vec = Vector3( fl.m128); +#endif //USE_SSE2_LDDQU + +} + +__forceinline void storeXYZ( const Vector3 &vec, __m128 * quad ) +{ + __m128 dstVec = *quad; + __declspec(align(16)) unsigned int sw[4] = {0, 0, 0, 0xffffffff}; // TODO: Centralize + dstVec = vec_sel(vec.get128(), dstVec, sw); + *quad = dstVec; +} + +__forceinline void storeXYZ(const Vector3& vec, float* fptr) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); +} + + +__forceinline void loadXYZArray( Vector3 & vec0, Vector3 & vec1, Vector3 & vec2, Vector3 & vec3, const __m128 * threeQuads ) +{ + const float *quads = (float *)threeQuads; + vec0 = Vector3( _mm_load_ps(quads) ); + vec1 = Vector3( _mm_loadu_ps(quads + 3) ); + vec2 = Vector3( _mm_loadu_ps(quads + 6) ); + vec3 = Vector3( _mm_loadu_ps(quads + 9) ); +} + +__forceinline void storeXYZArray( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, __m128 * threeQuads ) +{ + __m128 xxxx = _mm_shuffle_ps( vec1.get128(), vec1.get128(), _MM_SHUFFLE(0, 0, 0, 0) ); + __m128 zzzz = _mm_shuffle_ps( vec2.get128(), vec2.get128(), _MM_SHUFFLE(2, 2, 2, 2) ); + __declspec(align(16)) unsigned int xsw[4] = {0, 0, 0, 0xffffffff}; + __declspec(align(16)) unsigned int zsw[4] = {0xffffffff, 0, 0, 0}; + threeQuads[0] = vec_sel( vec0.get128(), xxxx, xsw ); + threeQuads[1] = _mm_shuffle_ps( vec1.get128(), vec2.get128(), _MM_SHUFFLE(1, 0, 2, 1) ); + threeQuads[2] = vec_sel( _mm_shuffle_ps( vec3.get128(), vec3.get128(), _MM_SHUFFLE(2, 1, 0, 3) ), zzzz, zsw ); +} +/* +__forceinline void storeHalfFloats( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, const Vector3 &vec4, const Vector3 &vec5, const Vector3 &vec6, const Vector3 &vec7, vec_ushort8 * threeQuads ) +{ + assert(0); +#if 0 + __m128 xyz0[3]; + __m128 xyz1[3]; + storeXYZArray( vec0, vec1, vec2, vec3, xyz0 ); + storeXYZArray( vec4, vec5, vec6, vec7, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +#endif +} +*/ +__forceinline Vector3 & Vector3::operator =( const Vector3 &vec ) +{ + mVec128 = vec.mVec128; + return *this; +} + +__forceinline Vector3 & Vector3::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +__forceinline Vector3 & Vector3::setX( const floatInVec &_x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +__forceinline const floatInVec Vector3::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +__forceinline Vector3 & Vector3::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +__forceinline Vector3 & Vector3::setY( const floatInVec &_y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +__forceinline const floatInVec Vector3::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +__forceinline Vector3 & Vector3::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +__forceinline Vector3 & Vector3::setZ( const floatInVec &_z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +__forceinline const floatInVec Vector3::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +__forceinline Vector3 & Vector3::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +__forceinline Vector3 & Vector3::setElem( int idx, const floatInVec &value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +__forceinline const floatInVec Vector3::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +__forceinline VecIdx Vector3::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +__forceinline const floatInVec Vector3::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +__forceinline const Vector3 Vector3::operator +( const Vector3 &vec ) const +{ + return Vector3( _mm_add_ps( mVec128, vec.mVec128 ) ); +} + +__forceinline const Vector3 Vector3::operator -( const Vector3 &vec ) const +{ + return Vector3( _mm_sub_ps( mVec128, vec.mVec128 ) ); +} + +__forceinline const Point3 Vector3::operator +( const Point3 &pnt ) const +{ + return Point3( _mm_add_ps( mVec128, pnt.get128() ) ); +} + +__forceinline const Vector3 Vector3::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +__forceinline const Vector3 Vector3::operator *( const floatInVec &scalar ) const +{ + return Vector3( _mm_mul_ps( mVec128, scalar.get128() ) ); +} + +__forceinline Vector3 & Vector3::operator +=( const Vector3 &vec ) +{ + *this = *this + vec; + return *this; +} + +__forceinline Vector3 & Vector3::operator -=( const Vector3 &vec ) +{ + *this = *this - vec; + return *this; +} + +__forceinline Vector3 & Vector3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +__forceinline Vector3 & Vector3::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +__forceinline const Vector3 Vector3::operator /( float scalar ) const +{ + return *this / floatInVec(scalar); +} + +__forceinline const Vector3 Vector3::operator /( const floatInVec &scalar ) const +{ + return Vector3( _mm_div_ps( mVec128, scalar.get128() ) ); +} + +__forceinline Vector3 & Vector3::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +__forceinline Vector3 & Vector3::operator /=( const floatInVec &scalar ) +{ + *this = *this / scalar; + return *this; +} + +__forceinline const Vector3 Vector3::operator -( ) const +{ + //return Vector3(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) ); + + __declspec(align(16)) static const int array[] = {0x80000000, 0x80000000, 0x80000000, 0x80000000}; + __m128 NEG_MASK = SSEFloat(*(const vec_float4*)array).vf; + return Vector3(_mm_xor_ps(get128(),NEG_MASK)); +} + +__forceinline const Vector3 operator *( float scalar, const Vector3 &vec ) +{ + return floatInVec(scalar) * vec; +} + +__forceinline const Vector3 operator *( const floatInVec &scalar, const Vector3 &vec ) +{ + return vec * scalar; +} + +__forceinline const Vector3 mulPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _mm_mul_ps( vec0.get128(), vec1.get128() ) ); +} + +__forceinline const Vector3 divPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _mm_div_ps( vec0.get128(), vec1.get128() ) ); +} + +__forceinline const Vector3 recipPerElem( const Vector3 &vec ) +{ + return Vector3( _mm_rcp_ps( vec.get128() ) ); +} + +__forceinline const Vector3 absPerElem( const Vector3 &vec ) +{ + return Vector3( fabsf4( vec.get128() ) ); +} + +__forceinline const Vector3 copySignPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + __m128 vmask = toM128(0x7fffffff); + return Vector3( _mm_or_ps( + _mm_and_ps ( vmask, vec0.get128() ), // Value + _mm_andnot_ps( vmask, vec1.get128() ) ) ); // Signs +} + +__forceinline const Vector3 maxPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _mm_max_ps( vec0.get128(), vec1.get128() ) ); +} + +__forceinline const floatInVec maxElem( const Vector3 &vec ) +{ + return floatInVec( _mm_max_ps( _mm_max_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) ); +} + +__forceinline const Vector3 minPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _mm_min_ps( vec0.get128(), vec1.get128() ) ); +} + +__forceinline const floatInVec minElem( const Vector3 &vec ) +{ + return floatInVec( _mm_min_ps( _mm_min_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) ); +} + +__forceinline const floatInVec sum( const Vector3 &vec ) +{ + return floatInVec( _mm_add_ps( _mm_add_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) ); +} + +__forceinline const floatInVec dot( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return floatInVec( _vmathVfDot3( vec0.get128(), vec1.get128() ), 0 ); +} + +__forceinline const floatInVec lengthSqr( const Vector3 &vec ) +{ + return floatInVec( _vmathVfDot3( vec.get128(), vec.get128() ), 0 ); +} + +__forceinline const floatInVec length( const Vector3 &vec ) +{ + return floatInVec( _mm_sqrt_ps(_vmathVfDot3( vec.get128(), vec.get128() )), 0 ); +} + + +__forceinline const Vector3 normalizeApprox( const Vector3 &vec ) +{ + return Vector3( _mm_mul_ps( vec.get128(), _mm_rsqrt_ps( _vmathVfDot3( vec.get128(), vec.get128() ) ) ) ); +} + +__forceinline const Vector3 normalize( const Vector3 &vec ) +{ + return Vector3( _mm_mul_ps( vec.get128(), newtonrapson_rsqrt4( _vmathVfDot3( vec.get128(), vec.get128() ) ) ) ); +} + +__forceinline const Vector3 cross( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _vmathVfCross( vec0.get128(), vec1.get128() ) ); +} + +__forceinline const Vector3 select( const Vector3 &vec0, const Vector3 &vec1, bool select1 ) +{ + return select( vec0, vec1, boolInVec(select1) ); +} + + +__forceinline const Vector4 select(const Vector4& vec0, const Vector4& vec1, const boolInVec& select1) +{ + return Vector4(vec_sel(vec0.get128(), vec1.get128(), select1.get128())); +} + +#ifdef _VECTORMATH_DEBUG + +__forceinline void print( const Vector3 &vec ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +__forceinline void print( const Vector3 &vec, const char * name ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +#endif + +__forceinline Vector4::Vector4( float _x, float _y, float _z, float _w ) +{ + mVec128 = _mm_setr_ps(_x, _y, _z, _w); + } + +__forceinline Vector4::Vector4( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z, const floatInVec &_w ) +{ + mVec128 = _mm_unpacklo_ps( + _mm_unpacklo_ps( _x.get128(), _z.get128() ), + _mm_unpacklo_ps( _y.get128(), _w.get128() ) ); +} + +__forceinline Vector4::Vector4( const Vector3 &xyz, float _w ) +{ + mVec128 = xyz.get128(); + _vmathVfSetElement(mVec128, _w, 3); +} + +__forceinline Vector4::Vector4( const Vector3 &xyz, const floatInVec &_w ) +{ + mVec128 = xyz.get128(); + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); +} + +__forceinline Vector4::Vector4( const Vector3 &vec ) +{ + mVec128 = vec.get128(); + mVec128 = _vmathVfInsert(mVec128, _mm_setzero_ps(), 3); +} + +__forceinline Vector4::Vector4( const Point3 &pnt ) +{ + mVec128 = pnt.get128(); + mVec128 = _vmathVfInsert(mVec128, _mm_set1_ps(1.0f), 3); +} + +__forceinline Vector4::Vector4( const Quat &quat ) +{ + mVec128 = quat.get128(); +} + +__forceinline Vector4::Vector4( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +__forceinline Vector4::Vector4( const floatInVec &scalar ) +{ + mVec128 = scalar.get128(); +} + +__forceinline Vector4::Vector4( __m128 vf4 ) +{ + mVec128 = vf4; +} + +__forceinline const Vector4 Vector4::xAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_1000 ); +} + +__forceinline const Vector4 Vector4::yAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0100 ); +} + +__forceinline const Vector4 Vector4::zAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0010 ); +} + +__forceinline const Vector4 Vector4::wAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0001 ); +} + +__forceinline const Vector4 lerp( float t, const Vector4 &vec0, const Vector4 &vec1 ) +{ + return lerp( floatInVec(t), vec0, vec1 ); +} + +__forceinline const Vector4 lerp( const floatInVec &t, const Vector4 &vec0, const Vector4 &vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +__forceinline const Vector4 slerp( float t, const Vector4 &unitVec0, const Vector4 &unitVec1 ) +{ + return slerp( floatInVec(t), unitVec0, unitVec1 ); +} + +__forceinline const Vector4 slerp( const floatInVec &t, const Vector4 &unitVec0, const Vector4 &unitVec1 ) +{ + __m128 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + cosAngle = _vmathVfDot4( unitVec0.get128(), unitVec1.get128() ); + __m128 selectMask = _mm_cmpgt_ps( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = t.get128(); + oneMinusT = _mm_sub_ps( _mm_set1_ps(1.0f), tttt ); + angles = _mm_unpacklo_ps( _mm_set1_ps(1.0f), tttt ); // angles = 1, t, 1, t + angles = _mm_unpacklo_ps( angles, oneMinusT ); // angles = 1, 1-t, t, 1-t + angles = _mm_mul_ps( angles, angle ); + sines = sinf4( angles ); + scales = _mm_div_ps( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + return Vector4( vec_madd( unitVec0.get128(), scale0, _mm_mul_ps( unitVec1.get128(), scale1 ) ) ); +} + +__forceinline __m128 Vector4::get128( ) const +{ + return mVec128; +} +/* +__forceinline void storeHalfFloats( const Vector4 &vec0, const Vector4 &vec1, const Vector4 &vec2, const Vector4 &vec3, vec_ushort8 * twoQuads ) +{ + twoQuads[0] = _vmath2VfToHalfFloats(vec0.get128(), vec1.get128()); + twoQuads[1] = _vmath2VfToHalfFloats(vec2.get128(), vec3.get128()); +} +*/ +__forceinline Vector4 & Vector4::operator =( const Vector4 &vec ) +{ + mVec128 = vec.mVec128; + return *this; +} + +__forceinline Vector4 & Vector4::setXYZ( const Vector3 &vec ) +{ + __declspec(align(16)) unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + mVec128 = vec_sel( vec.get128(), mVec128, sw ); + return *this; +} + +__forceinline const Vector3 Vector4::getXYZ( ) const +{ + return Vector3( mVec128 ); +} + +__forceinline Vector4 & Vector4::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +__forceinline Vector4 & Vector4::setX( const floatInVec &_x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +__forceinline const floatInVec Vector4::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +__forceinline Vector4 & Vector4::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +__forceinline Vector4 & Vector4::setY( const floatInVec &_y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +__forceinline const floatInVec Vector4::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +__forceinline Vector4 & Vector4::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +__forceinline Vector4 & Vector4::setZ( const floatInVec &_z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +__forceinline const floatInVec Vector4::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +__forceinline Vector4 & Vector4::setW( float _w ) +{ + _vmathVfSetElement(mVec128, _w, 3); + return *this; +} + +__forceinline Vector4 & Vector4::setW( const floatInVec &_w ) +{ + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); + return *this; +} + +__forceinline const floatInVec Vector4::getW( ) const +{ + return floatInVec( mVec128, 3 ); +} + +__forceinline Vector4 & Vector4::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +__forceinline Vector4 & Vector4::setElem( int idx, const floatInVec &value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +__forceinline const floatInVec Vector4::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +__forceinline VecIdx Vector4::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +__forceinline const floatInVec Vector4::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +__forceinline const Vector4 Vector4::operator +( const Vector4 &vec ) const +{ + return Vector4( _mm_add_ps( mVec128, vec.mVec128 ) ); +} + +__forceinline const Vector4 Vector4::operator -( const Vector4 &vec ) const +{ + return Vector4( _mm_sub_ps( mVec128, vec.mVec128 ) ); +} + +__forceinline const Vector4 Vector4::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +__forceinline const Vector4 Vector4::operator *( const floatInVec &scalar ) const +{ + return Vector4( _mm_mul_ps( mVec128, scalar.get128() ) ); +} + +__forceinline Vector4 & Vector4::operator +=( const Vector4 &vec ) +{ + *this = *this + vec; + return *this; +} + +__forceinline Vector4 & Vector4::operator -=( const Vector4 &vec ) +{ + *this = *this - vec; + return *this; +} + +__forceinline Vector4 & Vector4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +__forceinline Vector4 & Vector4::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +__forceinline const Vector4 Vector4::operator /( float scalar ) const +{ + return *this / floatInVec(scalar); +} + +__forceinline const Vector4 Vector4::operator /( const floatInVec &scalar ) const +{ + return Vector4( _mm_div_ps( mVec128, scalar.get128() ) ); +} + +__forceinline Vector4 & Vector4::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +__forceinline Vector4 & Vector4::operator /=( const floatInVec &scalar ) +{ + *this = *this / scalar; + return *this; +} + +__forceinline const Vector4 Vector4::operator -( ) const +{ + return Vector4(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) ); +} + +__forceinline const Vector4 operator *( float scalar, const Vector4 &vec ) +{ + return floatInVec(scalar) * vec; +} + +__forceinline const Vector4 operator *( const floatInVec &scalar, const Vector4 &vec ) +{ + return vec * scalar; +} + +__forceinline const Vector4 mulPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return Vector4( _mm_mul_ps( vec0.get128(), vec1.get128() ) ); +} + +__forceinline const Vector4 divPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return Vector4( _mm_div_ps( vec0.get128(), vec1.get128() ) ); +} + +__forceinline const Vector4 recipPerElem( const Vector4 &vec ) +{ + return Vector4( _mm_rcp_ps( vec.get128() ) ); +} + +__forceinline const Vector4 absPerElem( const Vector4 &vec ) +{ + return Vector4( fabsf4( vec.get128() ) ); +} + +__forceinline const Vector4 copySignPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + __m128 vmask = toM128(0x7fffffff); + return Vector4( _mm_or_ps( + _mm_and_ps ( vmask, vec0.get128() ), // Value + _mm_andnot_ps( vmask, vec1.get128() ) ) ); // Signs +} + +__forceinline const Vector4 maxPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return Vector4( _mm_max_ps( vec0.get128(), vec1.get128() ) ); +} + +__forceinline const floatInVec maxElem( const Vector4 &vec ) +{ + return floatInVec( _mm_max_ps( + _mm_max_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), + _mm_max_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) ); +} + +__forceinline const Vector4 minPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return Vector4( _mm_min_ps( vec0.get128(), vec1.get128() ) ); +} + +__forceinline const floatInVec minElem( const Vector4 &vec ) +{ + return floatInVec( _mm_min_ps( + _mm_min_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), + _mm_min_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) ); +} + +__forceinline const floatInVec sum( const Vector4 &vec ) +{ + return floatInVec( _mm_add_ps( + _mm_add_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), + _mm_add_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) ); +} + +__forceinline const floatInVec dot( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return floatInVec( _vmathVfDot4( vec0.get128(), vec1.get128() ), 0 ); +} + +__forceinline const floatInVec lengthSqr( const Vector4 &vec ) +{ + return floatInVec( _vmathVfDot4( vec.get128(), vec.get128() ), 0 ); +} + +__forceinline const floatInVec length( const Vector4 &vec ) +{ + return floatInVec( _mm_sqrt_ps(_vmathVfDot4( vec.get128(), vec.get128() )), 0 ); +} + +__forceinline const Vector4 normalizeApprox( const Vector4 &vec ) +{ + return Vector4( _mm_mul_ps( vec.get128(), _mm_rsqrt_ps( _vmathVfDot4( vec.get128(), vec.get128() ) ) ) ); +} + +__forceinline const Vector4 normalize( const Vector4 &vec ) +{ + return Vector4( _mm_mul_ps( vec.get128(), newtonrapson_rsqrt4( _vmathVfDot4( vec.get128(), vec.get128() ) ) ) ); +} + +__forceinline const Vector4 select( const Vector4 &vec0, const Vector4 &vec1, bool select1 ) +{ + return select( vec0, vec1, boolInVec(select1) ); +} + + +#ifdef _VECTORMATH_DEBUG + +__forceinline void print( const Vector4 &vec ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +__forceinline void print( const Vector4 &vec, const char * name ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +#endif + +__forceinline Point3::Point3( float _x, float _y, float _z ) +{ + mVec128 = _mm_setr_ps(_x, _y, _z, 0.0f); +} + +__forceinline Point3::Point3( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z ) +{ + mVec128 = _mm_unpacklo_ps( _mm_unpacklo_ps( _x.get128(), _z.get128() ), _y.get128() ); +} + +__forceinline Point3::Point3( const Vector3 &vec ) +{ + mVec128 = vec.get128(); +} + +__forceinline Point3::Point3( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +__forceinline Point3::Point3( const floatInVec &scalar ) +{ + mVec128 = scalar.get128(); +} + +__forceinline Point3::Point3( __m128 vf4 ) +{ + mVec128 = vf4; +} + +__forceinline const Point3 lerp( float t, const Point3 &pnt0, const Point3 &pnt1 ) +{ + return lerp( floatInVec(t), pnt0, pnt1 ); +} + +__forceinline const Point3 lerp( const floatInVec &t, const Point3 &pnt0, const Point3 &pnt1 ) +{ + return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); +} + +__forceinline __m128 Point3::get128( ) const +{ + return mVec128; +} + +__forceinline void storeXYZ( const Point3 &pnt, __m128 * quad ) +{ + __m128 dstVec = *quad; + __declspec(align(16)) unsigned int sw[4] = {0, 0, 0, 0xffffffff}; // TODO: Centralize + dstVec = vec_sel(pnt.get128(), dstVec, sw); + *quad = dstVec; +} + +__forceinline void loadXYZArray( Point3 & pnt0, Point3 & pnt1, Point3 & pnt2, Point3 & pnt3, const __m128 * threeQuads ) +{ + const float *quads = (float *)threeQuads; + pnt0 = Point3( _mm_load_ps(quads) ); + pnt1 = Point3( _mm_loadu_ps(quads + 3) ); + pnt2 = Point3( _mm_loadu_ps(quads + 6) ); + pnt3 = Point3( _mm_loadu_ps(quads + 9) ); +} + +__forceinline void storeXYZArray( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, __m128 * threeQuads ) +{ + __m128 xxxx = _mm_shuffle_ps( pnt1.get128(), pnt1.get128(), _MM_SHUFFLE(0, 0, 0, 0) ); + __m128 zzzz = _mm_shuffle_ps( pnt2.get128(), pnt2.get128(), _MM_SHUFFLE(2, 2, 2, 2) ); + __declspec(align(16)) unsigned int xsw[4] = {0, 0, 0, 0xffffffff}; + __declspec(align(16)) unsigned int zsw[4] = {0xffffffff, 0, 0, 0}; + threeQuads[0] = vec_sel( pnt0.get128(), xxxx, xsw ); + threeQuads[1] = _mm_shuffle_ps( pnt1.get128(), pnt2.get128(), _MM_SHUFFLE(1, 0, 2, 1) ); + threeQuads[2] = vec_sel( _mm_shuffle_ps( pnt3.get128(), pnt3.get128(), _MM_SHUFFLE(2, 1, 0, 3) ), zzzz, zsw ); +} +/* +__forceinline void storeHalfFloats( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, const Point3 &pnt4, const Point3 &pnt5, const Point3 &pnt6, const Point3 &pnt7, vec_ushort8 * threeQuads ) +{ +#if 0 + __m128 xyz0[3]; + __m128 xyz1[3]; + storeXYZArray( pnt0, pnt1, pnt2, pnt3, xyz0 ); + storeXYZArray( pnt4, pnt5, pnt6, pnt7, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +#else + assert(0); +#endif +} +*/ +__forceinline Point3 & Point3::operator =( const Point3 &pnt ) +{ + mVec128 = pnt.mVec128; + return *this; +} + +__forceinline Point3 & Point3::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +__forceinline Point3 & Point3::setX( const floatInVec &_x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +__forceinline const floatInVec Point3::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +__forceinline Point3 & Point3::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +__forceinline Point3 & Point3::setY( const floatInVec &_y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +__forceinline const floatInVec Point3::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +__forceinline Point3 & Point3::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +__forceinline Point3 & Point3::setZ( const floatInVec &_z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +__forceinline const floatInVec Point3::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +__forceinline Point3 & Point3::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +__forceinline Point3 & Point3::setElem( int idx, const floatInVec &value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +__forceinline const floatInVec Point3::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +__forceinline VecIdx Point3::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +__forceinline const floatInVec Point3::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +__forceinline const Vector3 Point3::operator -( const Point3 &pnt ) const +{ + return Vector3( _mm_sub_ps( mVec128, pnt.mVec128 ) ); +} + +__forceinline const Point3 Point3::operator +( const Vector3 &vec ) const +{ + return Point3( _mm_add_ps( mVec128, vec.get128() ) ); +} + +__forceinline const Point3 Point3::operator -( const Vector3 &vec ) const +{ + return Point3( _mm_sub_ps( mVec128, vec.get128() ) ); +} + +__forceinline Point3 & Point3::operator +=( const Vector3 &vec ) +{ + *this = *this + vec; + return *this; +} + +__forceinline Point3 & Point3::operator -=( const Vector3 &vec ) +{ + *this = *this - vec; + return *this; +} + +__forceinline const Point3 mulPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return Point3( _mm_mul_ps( pnt0.get128(), pnt1.get128() ) ); +} + +__forceinline const Point3 divPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return Point3( _mm_div_ps( pnt0.get128(), pnt1.get128() ) ); +} + +__forceinline const Point3 recipPerElem( const Point3 &pnt ) +{ + return Point3( _mm_rcp_ps( pnt.get128() ) ); +} + +__forceinline const Point3 absPerElem( const Point3 &pnt ) +{ + return Point3( fabsf4( pnt.get128() ) ); +} + +__forceinline const Point3 copySignPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + __m128 vmask = toM128(0x7fffffff); + return Point3( _mm_or_ps( + _mm_and_ps ( vmask, pnt0.get128() ), // Value + _mm_andnot_ps( vmask, pnt1.get128() ) ) ); // Signs +} + +__forceinline const Point3 maxPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return Point3( _mm_max_ps( pnt0.get128(), pnt1.get128() ) ); +} + +__forceinline const floatInVec maxElem( const Point3 &pnt ) +{ + return floatInVec( _mm_max_ps( _mm_max_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) ); +} + +__forceinline const Point3 minPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return Point3( _mm_min_ps( pnt0.get128(), pnt1.get128() ) ); +} + +__forceinline const floatInVec minElem( const Point3 &pnt ) +{ + return floatInVec( _mm_min_ps( _mm_min_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) ); +} + +__forceinline const floatInVec sum( const Point3 &pnt ) +{ + return floatInVec( _mm_add_ps( _mm_add_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) ); +} + +__forceinline const Point3 scale( const Point3 &pnt, float scaleVal ) +{ + return scale( pnt, floatInVec( scaleVal ) ); +} + +__forceinline const Point3 scale( const Point3 &pnt, const floatInVec &scaleVal ) +{ + return mulPerElem( pnt, Point3( scaleVal ) ); +} + +__forceinline const Point3 scale( const Point3 &pnt, const Vector3 &scaleVec ) +{ + return mulPerElem( pnt, Point3( scaleVec ) ); +} + +__forceinline const floatInVec projection( const Point3 &pnt, const Vector3 &unitVec ) +{ + return floatInVec( _vmathVfDot3( pnt.get128(), unitVec.get128() ), 0 ); +} + +__forceinline const floatInVec distSqrFromOrigin( const Point3 &pnt ) +{ + return lengthSqr( Vector3( pnt ) ); +} + +__forceinline const floatInVec distFromOrigin( const Point3 &pnt ) +{ + return length( Vector3( pnt ) ); +} + +__forceinline const floatInVec distSqr( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return lengthSqr( ( pnt1 - pnt0 ) ); +} + +__forceinline const floatInVec dist( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return length( ( pnt1 - pnt0 ) ); +} + +__forceinline const Point3 select( const Point3 &pnt0, const Point3 &pnt1, bool select1 ) +{ + return select( pnt0, pnt1, boolInVec(select1) ); +} + +__forceinline const Point3 select( const Point3 &pnt0, const Point3 &pnt1, const boolInVec &select1 ) +{ + return Point3( vec_sel( pnt0.get128(), pnt1.get128(), select1.get128() ) ); +} + + + +#ifdef _VECTORMATH_DEBUG + +__forceinline void print( const Point3 &pnt ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = pnt.get128(); + printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +__forceinline void print( const Point3 &pnt, const char * name ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = pnt.get128(); + printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/SSE/cpp/vecidx_aos.h b/Extras/vectormathlibrary/include/vectormath/SSE/cpp/vecidx_aos.h new file mode 100644 index 0000000..703790f --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/SSE/cpp/vecidx_aos.h @@ -0,0 +1,80 @@ +/* + Copyright (C) 2006, 2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VECIDX_AOS_H +#define _VECTORMATH_VECIDX_AOS_H + + +#include "floatInVec.h" + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// VecIdx +// Used in setting elements of Vector3, Vector4, Point3, or Quat with the +// subscripting operator. +// + +__declspec(align(16)) class VecIdx +{ +private: + __m128 &ref; + int i; +public: + inline VecIdx( __m128& vec, int idx ): ref(vec) { i = idx; } + + // implicitly casts to float unless _VECTORMATH_NO_SCALAR_CAST defined + // in which case, implicitly casts to floatInVec, and one must call + // getAsFloat to convert to float. + // +#ifdef _VECTORMATH_NO_SCALAR_CAST + inline operator floatInVec() const; + inline float getAsFloat() const; +#else + inline operator float() const; +#endif + + inline float operator =( float scalar ); + inline floatInVec operator =( const floatInVec &scalar ); + inline floatInVec operator =( const VecIdx& scalar ); + inline floatInVec operator *=( float scalar ); + inline floatInVec operator *=( const floatInVec &scalar ); + inline floatInVec operator /=( float scalar ); + inline floatInVec operator /=( const floatInVec &scalar ); + inline floatInVec operator +=( float scalar ); + inline floatInVec operator +=( const floatInVec &scalar ); + inline floatInVec operator -=( float scalar ); + inline floatInVec operator -=( const floatInVec &scalar ); +}; + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/SSE/cpp/vectormath_aos.h b/Extras/vectormathlibrary/include/vectormath/SSE/cpp/vectormath_aos.h new file mode 100644 index 0000000..131c754 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/SSE/cpp/vectormath_aos.h @@ -0,0 +1,2527 @@ +/* + Copyright (C) 2006, 2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _VECTORMATH_AOS_CPP_SSE_H +#define _VECTORMATH_AOS_CPP_SSE_H + +#include +#include +#include +#include + +#define USE_SSE2_LDDQU +#ifdef USE_SSE2_LDDQU +#include //used for _mm_lddqu_si128 +#endif //USE_SSE2_LDDQU + +// TODO: Tidy +typedef __m128 vec_float4; +typedef __m128 vec_uint4; +typedef __m128 vec_int4; +typedef __m128i vec_uchar16; +typedef __m128i vec_ushort8; + +#define vec_splat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e)) + +#define _mm_ror_ps(vec,i) \ + (((i)%4) ? (_mm_shuffle_ps(vec,vec, _MM_SHUFFLE((unsigned char)(i+3)%4,(unsigned char)(i+2)%4,(unsigned char)(i+1)%4,(unsigned char)(i+0)%4))) : (vec)) +#define _mm_rol_ps(vec,i) \ + (((i)%4) ? (_mm_shuffle_ps(vec,vec, _MM_SHUFFLE((unsigned char)(7-i)%4,(unsigned char)(6-i)%4,(unsigned char)(5-i)%4,(unsigned char)(4-i)%4))) : (vec)) + +#define vec_sld(vec,vec2,x) _mm_ror_ps(vec, ((x)/4)) + +#define _mm_abs_ps(vec) _mm_andnot_ps(_MASKSIGN_,vec) +#define _mm_neg_ps(vec) _mm_xor_ps(_MASKSIGN_,vec) + +#define vec_madd(a, b, c) _mm_add_ps(c, _mm_mul_ps(a, b) ) + +union SSEFloat +{ + __m128i vi; + __m128 m128; + __m128 vf; + unsigned int ui[4]; + unsigned short s[8]; + float f[4]; + SSEFloat(__m128 v) : m128(v) {} + SSEFloat(__m128i v) : vi(v) {} + SSEFloat() {}//uninitialized +}; + +static __forceinline __m128 vec_sel(__m128 a, __m128 b, __m128 mask) +{ + return _mm_or_ps(_mm_and_ps(mask, b), _mm_andnot_ps(mask, a)); +} +static __forceinline __m128 vec_sel(__m128 a, __m128 b, const unsigned int *_mask) +{ + return vec_sel(a, b, _mm_load_ps((float *)_mask)); +} +static __forceinline __m128 vec_sel(__m128 a, __m128 b, unsigned int _mask) +{ + return vec_sel(a, b, _mm_set1_ps(*(float *)&_mask)); +} + +static __forceinline __m128 toM128(unsigned int x) +{ + return _mm_set1_ps( *(float *)&x ); +} + +static __forceinline __m128 fabsf4(__m128 x) +{ + return _mm_and_ps( x, toM128( 0x7fffffff ) ); +} +/* +union SSE64 +{ + __m128 m128; + struct + { + __m64 m01; + __m64 m23; + } m64; +}; + +static __forceinline __m128 vec_cts(__m128 x, int a) +{ + assert(a == 0); // Only 2^0 supported + (void)a; + SSE64 sse64; + sse64.m64.m01 = _mm_cvttps_pi32(x); + sse64.m64.m23 = _mm_cvttps_pi32(_mm_ror_ps(x,2)); + _mm_empty(); + return sse64.m128; +} + +static __forceinline __m128 vec_ctf(__m128 x, int a) +{ + assert(a == 0); // Only 2^0 supported + (void)a; + SSE64 sse64; + sse64.m128 = x; + __m128 result =_mm_movelh_ps( + _mm_cvt_pi2ps(_mm_setzero_ps(), sse64.m64.m01), + _mm_cvt_pi2ps(_mm_setzero_ps(), sse64.m64.m23)); + _mm_empty(); + return result; +} +*/ +static __forceinline __m128 vec_cts(__m128 x, int a) +{ + assert(a == 0); // Only 2^0 supported + (void)a; + __m128i result = _mm_cvtps_epi32(x); + return (__m128 &)result; +} + +static __forceinline __m128 vec_ctf(__m128 x, int a) +{ + assert(a == 0); // Only 2^0 supported + (void)a; + return _mm_cvtepi32_ps((__m128i &)x); +} + +#define vec_nmsub(a,b,c) _mm_sub_ps( c, _mm_mul_ps( a, b ) ) +#define vec_sub(a,b) _mm_sub_ps( a, b ) +#define vec_add(a,b) _mm_add_ps( a, b ) +#define vec_mul(a,b) _mm_mul_ps( a, b ) +#define vec_xor(a,b) _mm_xor_ps( a, b ) +#define vec_and(a,b) _mm_and_ps( a, b ) +#define vec_cmpeq(a,b) _mm_cmpeq_ps( a, b ) +#define vec_cmpgt(a,b) _mm_cmpgt_ps( a, b ) + +#define vec_mergeh(a,b) _mm_unpacklo_ps( a, b ) +#define vec_mergel(a,b) _mm_unpackhi_ps( a, b ) + +#define vec_andc(a,b) _mm_andnot_ps( b, a ) + +#define sqrtf4(x) _mm_sqrt_ps( x ) +#define rsqrtf4(x) _mm_rsqrt_ps( x ) +#define recipf4(x) _mm_rcp_ps( x ) +#define negatef4(x) _mm_sub_ps( _mm_setzero_ps(), x ) + +static __forceinline __m128 newtonrapson_rsqrt4( const __m128 v ) +{ +#define _half4 _mm_setr_ps(.5f,.5f,.5f,.5f) +#define _three _mm_setr_ps(3.f,3.f,3.f,3.f) +const __m128 approx = _mm_rsqrt_ps( v ); +const __m128 muls = _mm_mul_ps(_mm_mul_ps(v, approx), approx); +return _mm_mul_ps(_mm_mul_ps(_half4, approx), _mm_sub_ps(_three, muls) ); +} + +static __forceinline __m128 acosf4(__m128 x) +{ + __m128 xabs = fabsf4(x); + __m128 select = _mm_cmplt_ps( x, _mm_setzero_ps() ); + __m128 t1 = sqrtf4(vec_sub(_mm_set1_ps(1.0f), xabs)); + + /* Instruction counts can be reduced if the polynomial was + * computed entirely from nested (dependent) fma's. However, + * to reduce the number of pipeline stalls, the polygon is evaluated + * in two halves (hi amd lo). + */ + __m128 xabs2 = _mm_mul_ps(xabs, xabs); + __m128 xabs4 = _mm_mul_ps(xabs2, xabs2); + __m128 hi = vec_madd(vec_madd(vec_madd(_mm_set1_ps(-0.0012624911f), + xabs, _mm_set1_ps(0.0066700901f)), + xabs, _mm_set1_ps(-0.0170881256f)), + xabs, _mm_set1_ps( 0.0308918810f)); + __m128 lo = vec_madd(vec_madd(vec_madd(_mm_set1_ps(-0.0501743046f), + xabs, _mm_set1_ps(0.0889789874f)), + xabs, _mm_set1_ps(-0.2145988016f)), + xabs, _mm_set1_ps( 1.5707963050f)); + + __m128 result = vec_madd(hi, xabs4, lo); + + // Adjust the result if x is negactive. + return vec_sel( + vec_mul(t1, result), // Positive + vec_nmsub(t1, result, _mm_set1_ps(3.1415926535898f)), // Negative + select); +} + +static __forceinline __m128 sinf4(vec_float4 x) +{ + +// +// Common constants used to evaluate sinf4/cosf4/tanf4 +// +#define _SINCOS_CC0 -0.0013602249f +#define _SINCOS_CC1 0.0416566950f +#define _SINCOS_CC2 -0.4999990225f +#define _SINCOS_SC0 -0.0001950727f +#define _SINCOS_SC1 0.0083320758f +#define _SINCOS_SC2 -0.1666665247f + +#define _SINCOS_KC1 1.57079625129f +#define _SINCOS_KC2 7.54978995489e-8f + + vec_float4 xl,xl2,xl3,res; + + // Range reduction using : xl = angle * TwoOverPi; + // + xl = vec_mul(x, _mm_set1_ps(0.63661977236f)); + + // Find the quadrant the angle falls in + // using: q = (int) (ceil(abs(xl))*sign(xl)) + // + vec_int4 q = vec_cts(xl,0); + + // Compute an offset based on the quadrant that the angle falls in + // + vec_int4 offset = _mm_and_ps(q,toM128(0x3)); + + // Remainder in range [-pi/4..pi/4] + // + vec_float4 qf = vec_ctf(q,0); + xl = vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC2),vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC1),x)); + + // Compute x^2 and x^3 + // + xl2 = vec_mul(xl,xl); + xl3 = vec_mul(xl2,xl); + + // Compute both the sin and cos of the angles + // using a polynomial expression: + // cx = 1.0f + xl2 * ((C0 * xl2 + C1) * xl2 + C2), and + // sx = xl + xl3 * ((S0 * xl2 + S1) * xl2 + S2) + // + + vec_float4 cx = + vec_madd( + vec_madd( + vec_madd(_mm_set1_ps(_SINCOS_CC0),xl2,_mm_set1_ps(_SINCOS_CC1)),xl2,_mm_set1_ps(_SINCOS_CC2)),xl2,_mm_set1_ps(1.0f)); + vec_float4 sx = + vec_madd( + vec_madd( + vec_madd(_mm_set1_ps(_SINCOS_SC0),xl2,_mm_set1_ps(_SINCOS_SC1)),xl2,_mm_set1_ps(_SINCOS_SC2)),xl3,xl); + + // Use the cosine when the offset is odd and the sin + // when the offset is even + // + res = vec_sel(cx,sx,vec_cmpeq(vec_and(offset, + toM128(0x1)), + _mm_setzero_ps())); + + // Flip the sign of the result when (offset mod 4) = 1 or 2 + // + return vec_sel( + vec_xor(toM128(0x80000000U), res), // Negative + res, // Positive + vec_cmpeq(vec_and(offset,toM128(0x2)),_mm_setzero_ps())); +} + +static __forceinline void sincosf4(vec_float4 x, vec_float4* s, vec_float4* c) +{ + vec_float4 xl,xl2,xl3; + vec_int4 offsetSin, offsetCos; + + // Range reduction using : xl = angle * TwoOverPi; + // + xl = vec_mul(x, _mm_set1_ps(0.63661977236f)); + + // Find the quadrant the angle falls in + // using: q = (int) (ceil(abs(xl))*sign(xl)) + // + //vec_int4 q = vec_cts(vec_add(xl,vec_sel(_mm_set1_ps(0.5f),xl,(0x80000000))),0); + vec_int4 q = vec_cts(xl,0); + + // Compute the offset based on the quadrant that the angle falls in. + // Add 1 to the offset for the cosine. + // + offsetSin = vec_and(q,toM128((int)0x3)); + __m128i temp = _mm_add_epi32(_mm_set1_epi32(1),(__m128i &)offsetSin); + offsetCos = (__m128 &)temp; + + // Remainder in range [-pi/4..pi/4] + // + vec_float4 qf = vec_ctf(q,0); + xl = vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC2),vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC1),x)); + + // Compute x^2 and x^3 + // + xl2 = vec_mul(xl,xl); + xl3 = vec_mul(xl2,xl); + + // Compute both the sin and cos of the angles + // using a polynomial expression: + // cx = 1.0f + xl2 * ((C0 * xl2 + C1) * xl2 + C2), and + // sx = xl + xl3 * ((S0 * xl2 + S1) * xl2 + S2) + // + vec_float4 cx = + vec_madd( + vec_madd( + vec_madd(_mm_set1_ps(_SINCOS_CC0),xl2,_mm_set1_ps(_SINCOS_CC1)),xl2,_mm_set1_ps(_SINCOS_CC2)),xl2,_mm_set1_ps(1.0f)); + vec_float4 sx = + vec_madd( + vec_madd( + vec_madd(_mm_set1_ps(_SINCOS_SC0),xl2,_mm_set1_ps(_SINCOS_SC1)),xl2,_mm_set1_ps(_SINCOS_SC2)),xl3,xl); + + // Use the cosine when the offset is odd and the sin + // when the offset is even + // + vec_uint4 sinMask = (vec_uint4)vec_cmpeq(vec_and(offsetSin,toM128(0x1)),_mm_setzero_ps()); + vec_uint4 cosMask = (vec_uint4)vec_cmpeq(vec_and(offsetCos,toM128(0x1)),_mm_setzero_ps()); + *s = vec_sel(cx,sx,sinMask); + *c = vec_sel(cx,sx,cosMask); + + // Flip the sign of the result when (offset mod 4) = 1 or 2 + // + sinMask = vec_cmpeq(vec_and(offsetSin,toM128(0x2)),_mm_setzero_ps()); + cosMask = vec_cmpeq(vec_and(offsetCos,toM128(0x2)),_mm_setzero_ps()); + + *s = vec_sel((vec_float4)vec_xor(toM128(0x80000000),(vec_uint4)*s),*s,sinMask); + *c = vec_sel((vec_float4)vec_xor(toM128(0x80000000),(vec_uint4)*c),*c,cosMask); +} + +#include "vecidx_aos.h" +#include "floatInVec.h" +#include "boolInVec.h" + +#ifdef _VECTORMATH_DEBUG +#include +#endif +namespace Vectormath { + +namespace Aos { + +//----------------------------------------------------------------------------- +// Forward Declarations +// + +class Vector3; +class Vector4; +class Point3; +class Quat; +class Matrix3; +class Matrix4; +class Transform3; + +// A 3-D vector in array-of-structures format +// +class Vector3 +{ + __m128 mVec128; + + __forceinline void set128(vec_float4 vec); + + __forceinline vec_float4& get128Ref(); + +public: + // Default constructor; does no initialization + // + __forceinline Vector3( ) { }; + + // Default copy constructor + // + __forceinline Vector3(const Vector3& vec); + + // Construct a 3-D vector from x, y, and z elements + // + __forceinline Vector3( float x, float y, float z ); + + // Construct a 3-D vector from x, y, and z elements (scalar data contained in vector data type) + // + __forceinline Vector3( const floatInVec &x, const floatInVec &y, const floatInVec &z ); + + // Copy elements from a 3-D point into a 3-D vector + // + explicit __forceinline Vector3( const Point3 &pnt ); + + // Set all elements of a 3-D vector to the same scalar value + // + explicit __forceinline Vector3( float scalar ); + + // Set all elements of a 3-D vector to the same scalar value (scalar data contained in vector data type) + // + explicit __forceinline Vector3( const floatInVec &scalar ); + + // Set vector float data in a 3-D vector + // + explicit __forceinline Vector3( __m128 vf4 ); + + // Get vector float data from a 3-D vector + // + __forceinline __m128 get128( ) const; + + // Assign one 3-D vector to another + // + __forceinline Vector3 & operator =( const Vector3 &vec ); + + // Set the x element of a 3-D vector + // + __forceinline Vector3 & setX( float x ); + + // Set the y element of a 3-D vector + // + __forceinline Vector3 & setY( float y ); + + // Set the z element of a 3-D vector + // + __forceinline Vector3 & setZ( float z ); + + // Set the x element of a 3-D vector (scalar data contained in vector data type) + // + __forceinline Vector3 & setX( const floatInVec &x ); + + // Set the y element of a 3-D vector (scalar data contained in vector data type) + // + __forceinline Vector3 & setY( const floatInVec &y ); + + // Set the z element of a 3-D vector (scalar data contained in vector data type) + // + __forceinline Vector3 & setZ( const floatInVec &z ); + + // Get the x element of a 3-D vector + // + __forceinline const floatInVec getX( ) const; + + // Get the y element of a 3-D vector + // + __forceinline const floatInVec getY( ) const; + + // Get the z element of a 3-D vector + // + __forceinline const floatInVec getZ( ) const; + + // Set an x, y, or z element of a 3-D vector by index + // + __forceinline Vector3 & setElem( int idx, float value ); + + // Set an x, y, or z element of a 3-D vector by index (scalar data contained in vector data type) + // + __forceinline Vector3 & setElem( int idx, const floatInVec &value ); + + // Get an x, y, or z element of a 3-D vector by index + // + __forceinline const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + __forceinline VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + __forceinline const floatInVec operator []( int idx ) const; + + // Add two 3-D vectors + // + __forceinline const Vector3 operator +( const Vector3 &vec ) const; + + // Subtract a 3-D vector from another 3-D vector + // + __forceinline const Vector3 operator -( const Vector3 &vec ) const; + + // Add a 3-D vector to a 3-D point + // + __forceinline const Point3 operator +( const Point3 &pnt ) const; + + // Multiply a 3-D vector by a scalar + // + __forceinline const Vector3 operator *( float scalar ) const; + + // Divide a 3-D vector by a scalar + // + __forceinline const Vector3 operator /( float scalar ) const; + + // Multiply a 3-D vector by a scalar (scalar data contained in vector data type) + // + __forceinline const Vector3 operator *( const floatInVec &scalar ) const; + + // Divide a 3-D vector by a scalar (scalar data contained in vector data type) + // + __forceinline const Vector3 operator /( const floatInVec &scalar ) const; + + // Perform compound assignment and addition with a 3-D vector + // + __forceinline Vector3 & operator +=( const Vector3 &vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + __forceinline Vector3 & operator -=( const Vector3 &vec ); + + // Perform compound assignment and multiplication by a scalar + // + __forceinline Vector3 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + __forceinline Vector3 & operator /=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + __forceinline Vector3 & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and division by a scalar (scalar data contained in vector data type) + // + __forceinline Vector3 & operator /=( const floatInVec &scalar ); + + // Negate all elements of a 3-D vector + // + __forceinline const Vector3 operator -( ) const; + + // Construct x axis + // + static __forceinline const Vector3 xAxis( ); + + // Construct y axis + // + static __forceinline const Vector3 yAxis( ); + + // Construct z axis + // + static __forceinline const Vector3 zAxis( ); + +}; + +// Multiply a 3-D vector by a scalar +// +__forceinline const Vector3 operator *( float scalar, const Vector3 &vec ); + +// Multiply a 3-D vector by a scalar (scalar data contained in vector data type) +// +__forceinline const Vector3 operator *( const floatInVec &scalar, const Vector3 &vec ); + +// Multiply two 3-D vectors per element +// +__forceinline const Vector3 mulPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Divide two 3-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +__forceinline const Vector3 divPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Compute the reciprocal of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +__forceinline const Vector3 recipPerElem( const Vector3 &vec ); + +// Compute the absolute value of a 3-D vector per element +// +__forceinline const Vector3 absPerElem( const Vector3 &vec ); + +// Copy sign from one 3-D vector to another, per element +// +__forceinline const Vector3 copySignPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Maximum of two 3-D vectors per element +// +__forceinline const Vector3 maxPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Minimum of two 3-D vectors per element +// +__forceinline const Vector3 minPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Maximum element of a 3-D vector +// +__forceinline const floatInVec maxElem( const Vector3 &vec ); + +// Minimum element of a 3-D vector +// +__forceinline const floatInVec minElem( const Vector3 &vec ); + +// Compute the sum of all elements of a 3-D vector +// +__forceinline const floatInVec sum( const Vector3 &vec ); + +// Compute the dot product of two 3-D vectors +// +__forceinline const floatInVec dot( const Vector3 &vec0, const Vector3 &vec1 ); + +// Compute the square of the length of a 3-D vector +// +__forceinline const floatInVec lengthSqr( const Vector3 &vec ); + +// Compute the length of a 3-D vector +// +__forceinline const floatInVec length( const Vector3 &vec ); + +// Normalize a 3-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +__forceinline const Vector3 normalize( const Vector3 &vec ); + +// Compute cross product of two 3-D vectors +// +__forceinline const Vector3 cross( const Vector3 &vec0, const Vector3 &vec1 ); + +// Outer product of two 3-D vectors +// +__forceinline const Matrix3 outer( const Vector3 &vec0, const Vector3 &vec1 ); + +// Pre-multiply a row vector by a 3x3 matrix +// NOTE: +// Slower than column post-multiply. +// +__forceinline const Vector3 rowMul( const Vector3 &vec, const Matrix3 & mat ); + +// Cross-product matrix of a 3-D vector +// +__forceinline const Matrix3 crossMatrix( const Vector3 &vec ); + +// Create cross-product matrix and multiply +// NOTE: +// Faster than separately creating a cross-product matrix and multiplying. +// +__forceinline const Matrix3 crossMatrixMul( const Vector3 &vec, const Matrix3 & mat ); + +// Linear interpolation between two 3-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +__forceinline const Vector3 lerp( float t, const Vector3 &vec0, const Vector3 &vec1 ); + +// Linear interpolation between two 3-D vectors (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +__forceinline const Vector3 lerp( const floatInVec &t, const Vector3 &vec0, const Vector3 &vec1 ); + +// Spherical linear interpolation between two 3-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +__forceinline const Vector3 slerp( float t, const Vector3 &unitVec0, const Vector3 &unitVec1 ); + +// Spherical linear interpolation between two 3-D vectors (scalar data contained in vector data type) +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +__forceinline const Vector3 slerp( const floatInVec &t, const Vector3 &unitVec0, const Vector3 &unitVec1 ); + +// Conditionally select between two 3-D vectors +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +__forceinline const Vector3 select( const Vector3 &vec0, const Vector3 &vec1, bool select1 ); + +// Conditionally select between two 3-D vectors (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +__forceinline const Vector3 select( const Vector3 &vec0, const Vector3 &vec1, const boolInVec &select1 ); + +// Store x, y, and z elements of 3-D vector in first three words of a quadword, preserving fourth word +// +__forceinline void storeXYZ( const Vector3 &vec, __m128 * quad ); + +// Load four three-float 3-D vectors, stored in three quadwords +// +__forceinline void loadXYZArray( Vector3 & vec0, Vector3 & vec1, Vector3 & vec2, Vector3 & vec3, const __m128 * threeQuads ); + +// Store four 3-D vectors in three quadwords +// +__forceinline void storeXYZArray( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, __m128 * threeQuads ); + +// Store eight 3-D vectors as half-floats +// +__forceinline void storeHalfFloats( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, const Vector3 &vec4, const Vector3 &vec5, const Vector3 &vec6, const Vector3 &vec7, vec_ushort8 * threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +__forceinline void print( const Vector3 &vec ); + +// Print a 3-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +__forceinline void print( const Vector3 &vec, const char * name ); + +#endif + +// A 4-D vector in array-of-structures format +// +class Vector4 +{ + __m128 mVec128; + +public: + // Default constructor; does no initialization + // + __forceinline Vector4( ) { }; + + // Construct a 4-D vector from x, y, z, and w elements + // + __forceinline Vector4( float x, float y, float z, float w ); + + // Construct a 4-D vector from x, y, z, and w elements (scalar data contained in vector data type) + // + __forceinline Vector4( const floatInVec &x, const floatInVec &y, const floatInVec &z, const floatInVec &w ); + + // Construct a 4-D vector from a 3-D vector and a scalar + // + __forceinline Vector4( const Vector3 &xyz, float w ); + + // Construct a 4-D vector from a 3-D vector and a scalar (scalar data contained in vector data type) + // + __forceinline Vector4( const Vector3 &xyz, const floatInVec &w ); + + // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + // + explicit __forceinline Vector4( const Vector3 &vec ); + + // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + // + explicit __forceinline Vector4( const Point3 &pnt ); + + // Copy elements from a quaternion into a 4-D vector + // + explicit __forceinline Vector4( const Quat &quat ); + + // Set all elements of a 4-D vector to the same scalar value + // + explicit __forceinline Vector4( float scalar ); + + // Set all elements of a 4-D vector to the same scalar value (scalar data contained in vector data type) + // + explicit __forceinline Vector4( const floatInVec &scalar ); + + // Set vector float data in a 4-D vector + // + explicit __forceinline Vector4( __m128 vf4 ); + + // Get vector float data from a 4-D vector + // + __forceinline __m128 get128( ) const; + + // Assign one 4-D vector to another + // + __forceinline Vector4 & operator =( const Vector4 &vec ); + + // Set the x, y, and z elements of a 4-D vector + // NOTE: + // This function does not change the w element. + // + __forceinline Vector4 & setXYZ( const Vector3 &vec ); + + // Get the x, y, and z elements of a 4-D vector + // + __forceinline const Vector3 getXYZ( ) const; + + // Set the x element of a 4-D vector + // + __forceinline Vector4 & setX( float x ); + + // Set the y element of a 4-D vector + // + __forceinline Vector4 & setY( float y ); + + // Set the z element of a 4-D vector + // + __forceinline Vector4 & setZ( float z ); + + // Set the w element of a 4-D vector + // + __forceinline Vector4 & setW( float w ); + + // Set the x element of a 4-D vector (scalar data contained in vector data type) + // + __forceinline Vector4 & setX( const floatInVec &x ); + + // Set the y element of a 4-D vector (scalar data contained in vector data type) + // + __forceinline Vector4 & setY( const floatInVec &y ); + + // Set the z element of a 4-D vector (scalar data contained in vector data type) + // + __forceinline Vector4 & setZ( const floatInVec &z ); + + // Set the w element of a 4-D vector (scalar data contained in vector data type) + // + __forceinline Vector4 & setW( const floatInVec &w ); + + // Get the x element of a 4-D vector + // + __forceinline const floatInVec getX( ) const; + + // Get the y element of a 4-D vector + // + __forceinline const floatInVec getY( ) const; + + // Get the z element of a 4-D vector + // + __forceinline const floatInVec getZ( ) const; + + // Get the w element of a 4-D vector + // + __forceinline const floatInVec getW( ) const; + + // Set an x, y, z, or w element of a 4-D vector by index + // + __forceinline Vector4 & setElem( int idx, float value ); + + // Set an x, y, z, or w element of a 4-D vector by index (scalar data contained in vector data type) + // + __forceinline Vector4 & setElem( int idx, const floatInVec &value ); + + // Get an x, y, z, or w element of a 4-D vector by index + // + __forceinline const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + __forceinline VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + __forceinline const floatInVec operator []( int idx ) const; + + // Add two 4-D vectors + // + __forceinline const Vector4 operator +( const Vector4 &vec ) const; + + // Subtract a 4-D vector from another 4-D vector + // + __forceinline const Vector4 operator -( const Vector4 &vec ) const; + + // Multiply a 4-D vector by a scalar + // + __forceinline const Vector4 operator *( float scalar ) const; + + // Divide a 4-D vector by a scalar + // + __forceinline const Vector4 operator /( float scalar ) const; + + // Multiply a 4-D vector by a scalar (scalar data contained in vector data type) + // + __forceinline const Vector4 operator *( const floatInVec &scalar ) const; + + // Divide a 4-D vector by a scalar (scalar data contained in vector data type) + // + __forceinline const Vector4 operator /( const floatInVec &scalar ) const; + + // Perform compound assignment and addition with a 4-D vector + // + __forceinline Vector4 & operator +=( const Vector4 &vec ); + + // Perform compound assignment and subtraction by a 4-D vector + // + __forceinline Vector4 & operator -=( const Vector4 &vec ); + + // Perform compound assignment and multiplication by a scalar + // + __forceinline Vector4 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + __forceinline Vector4 & operator /=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + __forceinline Vector4 & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and division by a scalar (scalar data contained in vector data type) + // + __forceinline Vector4 & operator /=( const floatInVec &scalar ); + + // Negate all elements of a 4-D vector + // + __forceinline const Vector4 operator -( ) const; + + // Construct x axis + // + static __forceinline const Vector4 xAxis( ); + + // Construct y axis + // + static __forceinline const Vector4 yAxis( ); + + // Construct z axis + // + static __forceinline const Vector4 zAxis( ); + + // Construct w axis + // + static __forceinline const Vector4 wAxis( ); + +}; + +// Multiply a 4-D vector by a scalar +// +__forceinline const Vector4 operator *( float scalar, const Vector4 &vec ); + +// Multiply a 4-D vector by a scalar (scalar data contained in vector data type) +// +__forceinline const Vector4 operator *( const floatInVec &scalar, const Vector4 &vec ); + +// Multiply two 4-D vectors per element +// +__forceinline const Vector4 mulPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Divide two 4-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +__forceinline const Vector4 divPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Compute the reciprocal of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +__forceinline const Vector4 recipPerElem( const Vector4 &vec ); + +// Compute the absolute value of a 4-D vector per element +// +__forceinline const Vector4 absPerElem( const Vector4 &vec ); + +// Copy sign from one 4-D vector to another, per element +// +__forceinline const Vector4 copySignPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Maximum of two 4-D vectors per element +// +__forceinline const Vector4 maxPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Minimum of two 4-D vectors per element +// +__forceinline const Vector4 minPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Maximum element of a 4-D vector +// +__forceinline const floatInVec maxElem( const Vector4 &vec ); + +// Minimum element of a 4-D vector +// +__forceinline const floatInVec minElem( const Vector4 &vec ); + +// Compute the sum of all elements of a 4-D vector +// +__forceinline const floatInVec sum( const Vector4 &vec ); + +// Compute the dot product of two 4-D vectors +// +__forceinline const floatInVec dot( const Vector4 &vec0, const Vector4 &vec1 ); + +// Compute the square of the length of a 4-D vector +// +__forceinline const floatInVec lengthSqr( const Vector4 &vec ); + +// Compute the length of a 4-D vector +// +__forceinline const floatInVec length( const Vector4 &vec ); + +// Normalize a 4-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +__forceinline const Vector4 normalize( const Vector4 &vec ); + +// Outer product of two 4-D vectors +// +__forceinline const Matrix4 outer( const Vector4 &vec0, const Vector4 &vec1 ); + +// Linear interpolation between two 4-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +__forceinline const Vector4 lerp( float t, const Vector4 &vec0, const Vector4 &vec1 ); + +// Linear interpolation between two 4-D vectors (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +__forceinline const Vector4 lerp( const floatInVec &t, const Vector4 &vec0, const Vector4 &vec1 ); + +// Spherical linear interpolation between two 4-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +__forceinline const Vector4 slerp( float t, const Vector4 &unitVec0, const Vector4 &unitVec1 ); + +// Spherical linear interpolation between two 4-D vectors (scalar data contained in vector data type) +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +__forceinline const Vector4 slerp( const floatInVec &t, const Vector4 &unitVec0, const Vector4 &unitVec1 ); + +// Conditionally select between two 4-D vectors +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +__forceinline const Vector4 select( const Vector4 &vec0, const Vector4 &vec1, bool select1 ); + +// Conditionally select between two 4-D vectors (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +__forceinline const Vector4 select( const Vector4 &vec0, const Vector4 &vec1, const boolInVec &select1 ); + +// Store four 4-D vectors as half-floats +// +__forceinline void storeHalfFloats( const Vector4 &vec0, const Vector4 &vec1, const Vector4 &vec2, const Vector4 &vec3, vec_ushort8 * twoQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +__forceinline void print( const Vector4 &vec ); + +// Print a 4-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +__forceinline void print( const Vector4 &vec, const char * name ); + +#endif + +// A 3-D point in array-of-structures format +// +class Point3 +{ + __m128 mVec128; + +public: + // Default constructor; does no initialization + // + __forceinline Point3( ) { }; + + // Construct a 3-D point from x, y, and z elements + // + __forceinline Point3( float x, float y, float z ); + + // Construct a 3-D point from x, y, and z elements (scalar data contained in vector data type) + // + __forceinline Point3( const floatInVec &x, const floatInVec &y, const floatInVec &z ); + + // Copy elements from a 3-D vector into a 3-D point + // + explicit __forceinline Point3( const Vector3 &vec ); + + // Set all elements of a 3-D point to the same scalar value + // + explicit __forceinline Point3( float scalar ); + + // Set all elements of a 3-D point to the same scalar value (scalar data contained in vector data type) + // + explicit __forceinline Point3( const floatInVec &scalar ); + + // Set vector float data in a 3-D point + // + explicit __forceinline Point3( __m128 vf4 ); + + // Get vector float data from a 3-D point + // + __forceinline __m128 get128( ) const; + + // Assign one 3-D point to another + // + __forceinline Point3 & operator =( const Point3 &pnt ); + + // Set the x element of a 3-D point + // + __forceinline Point3 & setX( float x ); + + // Set the y element of a 3-D point + // + __forceinline Point3 & setY( float y ); + + // Set the z element of a 3-D point + // + __forceinline Point3 & setZ( float z ); + + // Set the x element of a 3-D point (scalar data contained in vector data type) + // + __forceinline Point3 & setX( const floatInVec &x ); + + // Set the y element of a 3-D point (scalar data contained in vector data type) + // + __forceinline Point3 & setY( const floatInVec &y ); + + // Set the z element of a 3-D point (scalar data contained in vector data type) + // + __forceinline Point3 & setZ( const floatInVec &z ); + + // Get the x element of a 3-D point + // + __forceinline const floatInVec getX( ) const; + + // Get the y element of a 3-D point + // + __forceinline const floatInVec getY( ) const; + + // Get the z element of a 3-D point + // + __forceinline const floatInVec getZ( ) const; + + // Set an x, y, or z element of a 3-D point by index + // + __forceinline Point3 & setElem( int idx, float value ); + + // Set an x, y, or z element of a 3-D point by index (scalar data contained in vector data type) + // + __forceinline Point3 & setElem( int idx, const floatInVec &value ); + + // Get an x, y, or z element of a 3-D point by index + // + __forceinline const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + __forceinline VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + __forceinline const floatInVec operator []( int idx ) const; + + // Subtract a 3-D point from another 3-D point + // + __forceinline const Vector3 operator -( const Point3 &pnt ) const; + + // Add a 3-D point to a 3-D vector + // + __forceinline const Point3 operator +( const Vector3 &vec ) const; + + // Subtract a 3-D vector from a 3-D point + // + __forceinline const Point3 operator -( const Vector3 &vec ) const; + + // Perform compound assignment and addition with a 3-D vector + // + __forceinline Point3 & operator +=( const Vector3 &vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + __forceinline Point3 & operator -=( const Vector3 &vec ); + +}; + +// Multiply two 3-D points per element +// +__forceinline const Point3 mulPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Divide two 3-D points per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +__forceinline const Point3 divPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Compute the reciprocal of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +__forceinline const Point3 recipPerElem( const Point3 &pnt ); + +// Compute the absolute value of a 3-D point per element +// +__forceinline const Point3 absPerElem( const Point3 &pnt ); + +// Copy sign from one 3-D point to another, per element +// +__forceinline const Point3 copySignPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Maximum of two 3-D points per element +// +__forceinline const Point3 maxPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Minimum of two 3-D points per element +// +__forceinline const Point3 minPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Maximum element of a 3-D point +// +__forceinline const floatInVec maxElem( const Point3 &pnt ); + +// Minimum element of a 3-D point +// +__forceinline const floatInVec minElem( const Point3 &pnt ); + +// Compute the sum of all elements of a 3-D point +// +__forceinline const floatInVec sum( const Point3 &pnt ); + +// Apply uniform scale to a 3-D point +// +__forceinline const Point3 scale( const Point3 &pnt, float scaleVal ); + +// Apply uniform scale to a 3-D point (scalar data contained in vector data type) +// +__forceinline const Point3 scale( const Point3 &pnt, const floatInVec &scaleVal ); + +// Apply non-uniform scale to a 3-D point +// +__forceinline const Point3 scale( const Point3 &pnt, const Vector3 &scaleVec ); + +// Scalar projection of a 3-D point on a unit-length 3-D vector +// +__forceinline const floatInVec projection( const Point3 &pnt, const Vector3 &unitVec ); + +// Compute the square of the distance of a 3-D point from the coordinate-system origin +// +__forceinline const floatInVec distSqrFromOrigin( const Point3 &pnt ); + +// Compute the distance of a 3-D point from the coordinate-system origin +// +__forceinline const floatInVec distFromOrigin( const Point3 &pnt ); + +// Compute the square of the distance between two 3-D points +// +__forceinline const floatInVec distSqr( const Point3 &pnt0, const Point3 &pnt1 ); + +// Compute the distance between two 3-D points +// +__forceinline const floatInVec dist( const Point3 &pnt0, const Point3 &pnt1 ); + +// Linear interpolation between two 3-D points +// NOTE: +// Does not clamp t between 0 and 1. +// +__forceinline const Point3 lerp( float t, const Point3 &pnt0, const Point3 &pnt1 ); + +// Linear interpolation between two 3-D points (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +__forceinline const Point3 lerp( const floatInVec &t, const Point3 &pnt0, const Point3 &pnt1 ); + +// Conditionally select between two 3-D points +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +__forceinline const Point3 select( const Point3 &pnt0, const Point3 &pnt1, bool select1 ); + +// Conditionally select between two 3-D points (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +__forceinline const Point3 select( const Point3 &pnt0, const Point3 &pnt1, const boolInVec &select1 ); + +// Store x, y, and z elements of 3-D point in first three words of a quadword, preserving fourth word +// +__forceinline void storeXYZ( const Point3 &pnt, __m128 * quad ); + +// Load four three-float 3-D points, stored in three quadwords +// +__forceinline void loadXYZArray( Point3 & pnt0, Point3 & pnt1, Point3 & pnt2, Point3 & pnt3, const __m128 * threeQuads ); + +// Store four 3-D points in three quadwords +// +__forceinline void storeXYZArray( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, __m128 * threeQuads ); + +// Store eight 3-D points as half-floats +// +__forceinline void storeHalfFloats( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, const Point3 &pnt4, const Point3 &pnt5, const Point3 &pnt6, const Point3 &pnt7, vec_ushort8 * threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D point +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +__forceinline void print( const Point3 &pnt ); + +// Print a 3-D point and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +__forceinline void print( const Point3 &pnt, const char * name ); + +#endif + +// A quaternion in array-of-structures format +// +class Quat +{ + __m128 mVec128; + +public: + // Default constructor; does no initialization + // + __forceinline Quat( ) { }; + + __forceinline Quat::Quat(const Quat& quat); + + // Construct a quaternion from x, y, z, and w elements + // + __forceinline Quat( float x, float y, float z, float w ); + + // Construct a quaternion from x, y, z, and w elements (scalar data contained in vector data type) + // + __forceinline Quat( const floatInVec &x, const floatInVec &y, const floatInVec &z, const floatInVec &w ); + + // Construct a quaternion from a 3-D vector and a scalar + // + __forceinline Quat( const Vector3 &xyz, float w ); + + // Construct a quaternion from a 3-D vector and a scalar (scalar data contained in vector data type) + // + __forceinline Quat( const Vector3 &xyz, const floatInVec &w ); + + // Copy elements from a 4-D vector into a quaternion + // + explicit __forceinline Quat( const Vector4 &vec ); + + // Convert a rotation matrix to a unit-length quaternion + // + explicit __forceinline Quat( const Matrix3 & rotMat ); + + // Set all elements of a quaternion to the same scalar value + // + explicit __forceinline Quat( float scalar ); + + // Set all elements of a quaternion to the same scalar value (scalar data contained in vector data type) + // + explicit __forceinline Quat( const floatInVec &scalar ); + + // Set vector float data in a quaternion + // + explicit __forceinline Quat( __m128 vf4 ); + + // Get vector float data from a quaternion + // + __forceinline __m128 get128( ) const; + + // Set a quaterion from vector float data + // + __forceinline void set128(vec_float4 vec); + + // Assign one quaternion to another + // + __forceinline Quat & operator =( const Quat &quat ); + + // Set the x, y, and z elements of a quaternion + // NOTE: + // This function does not change the w element. + // + __forceinline Quat & setXYZ( const Vector3 &vec ); + + // Get the x, y, and z elements of a quaternion + // + __forceinline const Vector3 getXYZ( ) const; + + // Set the x element of a quaternion + // + __forceinline Quat & setX( float x ); + + // Set the y element of a quaternion + // + __forceinline Quat & setY( float y ); + + // Set the z element of a quaternion + // + __forceinline Quat & setZ( float z ); + + // Set the w element of a quaternion + // + __forceinline Quat & setW( float w ); + + // Set the x element of a quaternion (scalar data contained in vector data type) + // + __forceinline Quat & setX( const floatInVec &x ); + + // Set the y element of a quaternion (scalar data contained in vector data type) + // + __forceinline Quat & setY( const floatInVec &y ); + + // Set the z element of a quaternion (scalar data contained in vector data type) + // + __forceinline Quat & setZ( const floatInVec &z ); + + // Set the w element of a quaternion (scalar data contained in vector data type) + // + __forceinline Quat & setW( const floatInVec &w ); + + // Get the x element of a quaternion + // + __forceinline const floatInVec getX( ) const; + + // Get the y element of a quaternion + // + __forceinline const floatInVec getY( ) const; + + // Get the z element of a quaternion + // + __forceinline const floatInVec getZ( ) const; + + // Get the w element of a quaternion + // + __forceinline const floatInVec getW( ) const; + + // Set an x, y, z, or w element of a quaternion by index + // + __forceinline Quat & setElem( int idx, float value ); + + // Set an x, y, z, or w element of a quaternion by index (scalar data contained in vector data type) + // + __forceinline Quat & setElem( int idx, const floatInVec &value ); + + // Get an x, y, z, or w element of a quaternion by index + // + __forceinline const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + __forceinline VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + __forceinline const floatInVec operator []( int idx ) const; + + // Add two quaternions + // + __forceinline const Quat operator +( const Quat &quat ) const; + + // Subtract a quaternion from another quaternion + // + __forceinline const Quat operator -( const Quat &quat ) const; + + // Multiply two quaternions + // + __forceinline const Quat operator *( const Quat &quat ) const; + + // Multiply a quaternion by a scalar + // + __forceinline const Quat operator *( float scalar ) const; + + // Divide a quaternion by a scalar + // + __forceinline const Quat operator /( float scalar ) const; + + // Multiply a quaternion by a scalar (scalar data contained in vector data type) + // + __forceinline const Quat operator *( const floatInVec &scalar ) const; + + // Divide a quaternion by a scalar (scalar data contained in vector data type) + // + __forceinline const Quat operator /( const floatInVec &scalar ) const; + + // Perform compound assignment and addition with a quaternion + // + __forceinline Quat & operator +=( const Quat &quat ); + + // Perform compound assignment and subtraction by a quaternion + // + __forceinline Quat & operator -=( const Quat &quat ); + + // Perform compound assignment and multiplication by a quaternion + // + __forceinline Quat & operator *=( const Quat &quat ); + + // Perform compound assignment and multiplication by a scalar + // + __forceinline Quat & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + __forceinline Quat & operator /=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + __forceinline Quat & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and division by a scalar (scalar data contained in vector data type) + // + __forceinline Quat & operator /=( const floatInVec &scalar ); + + // Negate all elements of a quaternion + // + __forceinline const Quat operator -( ) const; + + // Construct an identity quaternion + // + static __forceinline const Quat identity( ); + + // Construct a quaternion to rotate between two unit-length 3-D vectors + // NOTE: + // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + // + static __forceinline const Quat rotation( const Vector3 &unitVec0, const Vector3 &unitVec1 ); + + // Construct a quaternion to rotate around a unit-length 3-D vector + // + static __forceinline const Quat rotation( float radians, const Vector3 &unitVec ); + + // Construct a quaternion to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static __forceinline const Quat rotation( const floatInVec &radians, const Vector3 &unitVec ); + + // Construct a quaternion to rotate around the x axis + // + static __forceinline const Quat rotationX( float radians ); + + // Construct a quaternion to rotate around the y axis + // + static __forceinline const Quat rotationY( float radians ); + + // Construct a quaternion to rotate around the z axis + // + static __forceinline const Quat rotationZ( float radians ); + + // Construct a quaternion to rotate around the x axis (scalar data contained in vector data type) + // + static __forceinline const Quat rotationX( const floatInVec &radians ); + + // Construct a quaternion to rotate around the y axis (scalar data contained in vector data type) + // + static __forceinline const Quat rotationY( const floatInVec &radians ); + + // Construct a quaternion to rotate around the z axis (scalar data contained in vector data type) + // + static __forceinline const Quat rotationZ( const floatInVec &radians ); + +}; + +// Multiply a quaternion by a scalar +// +__forceinline const Quat operator *( float scalar, const Quat &quat ); + +// Multiply a quaternion by a scalar (scalar data contained in vector data type) +// +__forceinline const Quat operator *( const floatInVec &scalar, const Quat &quat ); + +// Compute the conjugate of a quaternion +// +__forceinline const Quat conj( const Quat &quat ); + +// Use a unit-length quaternion to rotate a 3-D vector +// +__forceinline const Vector3 rotate( const Quat &unitQuat, const Vector3 &vec ); + +// Compute the dot product of two quaternions +// +__forceinline const floatInVec dot( const Quat &quat0, const Quat &quat1 ); + +// Compute the norm of a quaternion +// +__forceinline const floatInVec norm( const Quat &quat ); + +// Compute the length of a quaternion +// +__forceinline const floatInVec length( const Quat &quat ); + +// Normalize a quaternion +// NOTE: +// The result is unpredictable when all elements of quat are at or near zero. +// +__forceinline const Quat normalize( const Quat &quat ); + +// Linear interpolation between two quaternions +// NOTE: +// Does not clamp t between 0 and 1. +// +__forceinline const Quat lerp( float t, const Quat &quat0, const Quat &quat1 ); + +// Linear interpolation between two quaternions (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +__forceinline const Quat lerp( const floatInVec &t, const Quat &quat0, const Quat &quat1 ); + +// Spherical linear interpolation between two quaternions +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +__forceinline const Quat slerp( float t, const Quat &unitQuat0, const Quat &unitQuat1 ); + +// Spherical linear interpolation between two quaternions (scalar data contained in vector data type) +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +__forceinline const Quat slerp( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1 ); + +// Spherical quadrangle interpolation +// +__forceinline const Quat squad( float t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ); + +// Spherical quadrangle interpolation (scalar data contained in vector data type) +// +__forceinline const Quat squad( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ); + +// Conditionally select between two quaternions +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +__forceinline const Quat select( const Quat &quat0, const Quat &quat1, bool select1 ); + +// Conditionally select between two quaternions (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +__forceinline const Quat select( const Quat &quat0, const Quat &quat1, const boolInVec &select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a quaternion +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +__forceinline void print( const Quat &quat ); + +// Print a quaternion and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +__forceinline void print( const Quat &quat, const char * name ); + +#endif + +// A 3x3 matrix in array-of-structures format +// +class Matrix3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + +public: + // Default constructor; does no initialization + // + __forceinline Matrix3( ) { }; + + // Copy a 3x3 matrix + // + __forceinline Matrix3( const Matrix3 & mat ); + + // Construct a 3x3 matrix containing the specified columns + // + __forceinline Matrix3( const Vector3 &col0, const Vector3 &col1, const Vector3 &col2 ); + + // Construct a 3x3 rotation matrix from a unit-length quaternion + // + explicit __forceinline Matrix3( const Quat &unitQuat ); + + // Set all elements of a 3x3 matrix to the same scalar value + // + explicit __forceinline Matrix3( float scalar ); + + // Set all elements of a 3x3 matrix to the same scalar value (scalar data contained in vector data type) + // + explicit __forceinline Matrix3( const floatInVec &scalar ); + + // Assign one 3x3 matrix to another + // + __forceinline Matrix3 & operator =( const Matrix3 & mat ); + + // Set column 0 of a 3x3 matrix + // + __forceinline Matrix3 & setCol0( const Vector3 &col0 ); + + // Set column 1 of a 3x3 matrix + // + __forceinline Matrix3 & setCol1( const Vector3 &col1 ); + + // Set column 2 of a 3x3 matrix + // + __forceinline Matrix3 & setCol2( const Vector3 &col2 ); + + // Get column 0 of a 3x3 matrix + // + __forceinline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x3 matrix + // + __forceinline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x3 matrix + // + __forceinline const Vector3 getCol2( ) const; + + // Set the column of a 3x3 matrix referred to by the specified index + // + __forceinline Matrix3 & setCol( int col, const Vector3 &vec ); + + // Set the row of a 3x3 matrix referred to by the specified index + // + __forceinline Matrix3 & setRow( int row, const Vector3 &vec ); + + // Get the column of a 3x3 matrix referred to by the specified index + // + __forceinline const Vector3 getCol( int col ) const; + + // Get the row of a 3x3 matrix referred to by the specified index + // + __forceinline const Vector3 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + __forceinline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + __forceinline const Vector3 operator []( int col ) const; + + // Set the element of a 3x3 matrix referred to by column and row indices + // + __forceinline Matrix3 & setElem( int col, int row, float val ); + + // Set the element of a 3x3 matrix referred to by column and row indices (scalar data contained in vector data type) + // + __forceinline Matrix3 & setElem( int col, int row, const floatInVec &val ); + + // Get the element of a 3x3 matrix referred to by column and row indices + // + __forceinline const floatInVec getElem( int col, int row ) const; + + // Add two 3x3 matrices + // + __forceinline const Matrix3 operator +( const Matrix3 & mat ) const; + + // Subtract a 3x3 matrix from another 3x3 matrix + // + __forceinline const Matrix3 operator -( const Matrix3 & mat ) const; + + // Negate all elements of a 3x3 matrix + // + __forceinline const Matrix3 operator -( ) const; + + // Multiply a 3x3 matrix by a scalar + // + __forceinline const Matrix3 operator *( float scalar ) const; + + // Multiply a 3x3 matrix by a scalar (scalar data contained in vector data type) + // + __forceinline const Matrix3 operator *( const floatInVec &scalar ) const; + + // Multiply a 3x3 matrix by a 3-D vector + // + __forceinline const Vector3 operator *( const Vector3 &vec ) const; + + // Multiply two 3x3 matrices + // + __forceinline const Matrix3 operator *( const Matrix3 & mat ) const; + + // Perform compound assignment and addition with a 3x3 matrix + // + __forceinline Matrix3 & operator +=( const Matrix3 & mat ); + + // Perform compound assignment and subtraction by a 3x3 matrix + // + __forceinline Matrix3 & operator -=( const Matrix3 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + __forceinline Matrix3 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + __forceinline Matrix3 & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and multiplication by a 3x3 matrix + // + __forceinline Matrix3 & operator *=( const Matrix3 & mat ); + + // Construct an identity 3x3 matrix + // + static __forceinline const Matrix3 identity( ); + + // Construct a 3x3 matrix to rotate around the x axis + // + static __forceinline const Matrix3 rotationX( float radians ); + + // Construct a 3x3 matrix to rotate around the y axis + // + static __forceinline const Matrix3 rotationY( float radians ); + + // Construct a 3x3 matrix to rotate around the z axis + // + static __forceinline const Matrix3 rotationZ( float radians ); + + // Construct a 3x3 matrix to rotate around the x axis (scalar data contained in vector data type) + // + static __forceinline const Matrix3 rotationX( const floatInVec &radians ); + + // Construct a 3x3 matrix to rotate around the y axis (scalar data contained in vector data type) + // + static __forceinline const Matrix3 rotationY( const floatInVec &radians ); + + // Construct a 3x3 matrix to rotate around the z axis (scalar data contained in vector data type) + // + static __forceinline const Matrix3 rotationZ( const floatInVec &radians ); + + // Construct a 3x3 matrix to rotate around the x, y, and z axes + // + static __forceinline const Matrix3 rotationZYX( const Vector3 &radiansXYZ ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector + // + static __forceinline const Matrix3 rotation( float radians, const Vector3 &unitVec ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static __forceinline const Matrix3 rotation( const floatInVec &radians, const Vector3 &unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static __forceinline const Matrix3 rotation( const Quat &unitQuat ); + + // Construct a 3x3 matrix to perform scaling + // + static __forceinline const Matrix3 scale( const Vector3 &scaleVec ); + +}; +// Multiply a 3x3 matrix by a scalar +// +__forceinline const Matrix3 operator *( float scalar, const Matrix3 & mat ); + +// Multiply a 3x3 matrix by a scalar (scalar data contained in vector data type) +// +__forceinline const Matrix3 operator *( const floatInVec &scalar, const Matrix3 & mat ); + +// Append (post-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +__forceinline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 &scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +__forceinline const Matrix3 prependScale( const Vector3 &scaleVec, const Matrix3 & mat ); + +// Multiply two 3x3 matrices per element +// +__forceinline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); + +// Compute the absolute value of a 3x3 matrix per element +// +__forceinline const Matrix3 absPerElem( const Matrix3 & mat ); + +// Transpose of a 3x3 matrix +// +__forceinline const Matrix3 transpose( const Matrix3 & mat ); + +// Compute the inverse of a 3x3 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +__forceinline const Matrix3 inverse( const Matrix3 & mat ); + +// Determinant of a 3x3 matrix +// +__forceinline const floatInVec determinant( const Matrix3 & mat ); + +// Conditionally select between two 3x3 matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +__forceinline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ); + +// Conditionally select between two 3x3 matrices (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +__forceinline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, const boolInVec &select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x3 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +__forceinline void print( const Matrix3 & mat ); + +// Print a 3x3 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +__forceinline void print( const Matrix3 & mat, const char * name ); + +#endif + +// A 4x4 matrix in array-of-structures format +// +class Matrix4 +{ + Vector4 mCol0; + Vector4 mCol1; + Vector4 mCol2; + Vector4 mCol3; + +public: + // Default constructor; does no initialization + // + __forceinline Matrix4( ) { }; + + // Copy a 4x4 matrix + // + __forceinline Matrix4( const Matrix4 & mat ); + + // Construct a 4x4 matrix containing the specified columns + // + __forceinline Matrix4( const Vector4 &col0, const Vector4 &col1, const Vector4 &col2, const Vector4 &col3 ); + + // Construct a 4x4 matrix from a 3x4 transformation matrix + // + explicit __forceinline Matrix4( const Transform3 & mat ); + + // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + // + __forceinline Matrix4( const Matrix3 & mat, const Vector3 &translateVec ); + + // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + // + __forceinline Matrix4( const Quat &unitQuat, const Vector3 &translateVec ); + + // Set all elements of a 4x4 matrix to the same scalar value + // + explicit __forceinline Matrix4( float scalar ); + + // Set all elements of a 4x4 matrix to the same scalar value (scalar data contained in vector data type) + // + explicit __forceinline Matrix4( const floatInVec &scalar ); + + // Assign one 4x4 matrix to another + // + __forceinline Matrix4 & operator =( const Matrix4 & mat ); + + // Set the upper-left 3x3 submatrix + // NOTE: + // This function does not change the bottom row elements. + // + __forceinline Matrix4 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 4x4 matrix + // + __forceinline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // NOTE: + // This function does not change the bottom row elements. + // + __forceinline Matrix4 & setTranslation( const Vector3 &translateVec ); + + // Get the translation component of a 4x4 matrix + // + __forceinline const Vector3 getTranslation( ) const; + + // Set column 0 of a 4x4 matrix + // + __forceinline Matrix4 & setCol0( const Vector4 &col0 ); + + // Set column 1 of a 4x4 matrix + // + __forceinline Matrix4 & setCol1( const Vector4 &col1 ); + + // Set column 2 of a 4x4 matrix + // + __forceinline Matrix4 & setCol2( const Vector4 &col2 ); + + // Set column 3 of a 4x4 matrix + // + __forceinline Matrix4 & setCol3( const Vector4 &col3 ); + + // Get column 0 of a 4x4 matrix + // + __forceinline const Vector4 getCol0( ) const; + + // Get column 1 of a 4x4 matrix + // + __forceinline const Vector4 getCol1( ) const; + + // Get column 2 of a 4x4 matrix + // + __forceinline const Vector4 getCol2( ) const; + + // Get column 3 of a 4x4 matrix + // + __forceinline const Vector4 getCol3( ) const; + + // Set the column of a 4x4 matrix referred to by the specified index + // + __forceinline Matrix4 & setCol( int col, const Vector4 &vec ); + + // Set the row of a 4x4 matrix referred to by the specified index + // + __forceinline Matrix4 & setRow( int row, const Vector4 &vec ); + + // Get the column of a 4x4 matrix referred to by the specified index + // + __forceinline const Vector4 getCol( int col ) const; + + // Get the row of a 4x4 matrix referred to by the specified index + // + __forceinline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + __forceinline Vector4 & operator []( int col ); + + // Subscripting operator to get a column + // + __forceinline const Vector4 operator []( int col ) const; + + // Set the element of a 4x4 matrix referred to by column and row indices + // + __forceinline Matrix4 & setElem( int col, int row, float val ); + + // Set the element of a 4x4 matrix referred to by column and row indices (scalar data contained in vector data type) + // + __forceinline Matrix4 & setElem( int col, int row, const floatInVec &val ); + + // Get the element of a 4x4 matrix referred to by column and row indices + // + __forceinline const floatInVec getElem( int col, int row ) const; + + // Add two 4x4 matrices + // + __forceinline const Matrix4 operator +( const Matrix4 & mat ) const; + + // Subtract a 4x4 matrix from another 4x4 matrix + // + __forceinline const Matrix4 operator -( const Matrix4 & mat ) const; + + // Negate all elements of a 4x4 matrix + // + __forceinline const Matrix4 operator -( ) const; + + // Multiply a 4x4 matrix by a scalar + // + __forceinline const Matrix4 operator *( float scalar ) const; + + // Multiply a 4x4 matrix by a scalar (scalar data contained in vector data type) + // + __forceinline const Matrix4 operator *( const floatInVec &scalar ) const; + + // Multiply a 4x4 matrix by a 4-D vector + // + __forceinline const Vector4 operator *( const Vector4 &vec ) const; + + // Multiply a 4x4 matrix by a 3-D vector + // + __forceinline const Vector4 operator *( const Vector3 &vec ) const; + + // Multiply a 4x4 matrix by a 3-D point + // + __forceinline const Vector4 operator *( const Point3 &pnt ) const; + + // Multiply two 4x4 matrices + // + __forceinline const Matrix4 operator *( const Matrix4 & mat ) const; + + // Multiply a 4x4 matrix by a 3x4 transformation matrix + // + __forceinline const Matrix4 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and addition with a 4x4 matrix + // + __forceinline Matrix4 & operator +=( const Matrix4 & mat ); + + // Perform compound assignment and subtraction by a 4x4 matrix + // + __forceinline Matrix4 & operator -=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + __forceinline Matrix4 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + __forceinline Matrix4 & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and multiplication by a 4x4 matrix + // + __forceinline Matrix4 & operator *=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + __forceinline Matrix4 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 4x4 matrix + // + static __forceinline const Matrix4 identity( ); + + // Construct a 4x4 matrix to rotate around the x axis + // + static __forceinline const Matrix4 rotationX( float radians ); + + // Construct a 4x4 matrix to rotate around the y axis + // + static __forceinline const Matrix4 rotationY( float radians ); + + // Construct a 4x4 matrix to rotate around the z axis + // + static __forceinline const Matrix4 rotationZ( float radians ); + + // Construct a 4x4 matrix to rotate around the x axis (scalar data contained in vector data type) + // + static __forceinline const Matrix4 rotationX( const floatInVec &radians ); + + // Construct a 4x4 matrix to rotate around the y axis (scalar data contained in vector data type) + // + static __forceinline const Matrix4 rotationY( const floatInVec &radians ); + + // Construct a 4x4 matrix to rotate around the z axis (scalar data contained in vector data type) + // + static __forceinline const Matrix4 rotationZ( const floatInVec &radians ); + + // Construct a 4x4 matrix to rotate around the x, y, and z axes + // + static __forceinline const Matrix4 rotationZYX( const Vector3 &radiansXYZ ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector + // + static __forceinline const Matrix4 rotation( float radians, const Vector3 &unitVec ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static __forceinline const Matrix4 rotation( const floatInVec &radians, const Vector3 &unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static __forceinline const Matrix4 rotation( const Quat &unitQuat ); + + // Construct a 4x4 matrix to perform scaling + // + static __forceinline const Matrix4 scale( const Vector3 &scaleVec ); + + // Construct a 4x4 matrix to perform translation + // + static __forceinline const Matrix4 translation( const Vector3 &translateVec ); + + // Construct viewing matrix based on eye, position looked at, and up direction + // + static __forceinline const Matrix4 lookAt( const Point3 &eyePos, const Point3 &lookAtPos, const Vector3 &upVec ); + + // Construct a perspective projection matrix + // + static __forceinline const Matrix4 perspective( float fovyRadians, float aspect, float zNear, float zFar ); + + // Construct a perspective projection matrix based on frustum + // + static __forceinline const Matrix4 frustum( float left, float right, float bottom, float top, float zNear, float zFar ); + + // Construct an orthographic projection matrix + // + static __forceinline const Matrix4 orthographic( float left, float right, float bottom, float top, float zNear, float zFar ); + +}; +// Multiply a 4x4 matrix by a scalar +// +__forceinline const Matrix4 operator *( float scalar, const Matrix4 & mat ); + +// Multiply a 4x4 matrix by a scalar (scalar data contained in vector data type) +// +__forceinline const Matrix4 operator *( const floatInVec &scalar, const Matrix4 & mat ); + +// Append (post-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +__forceinline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 &scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +__forceinline const Matrix4 prependScale( const Vector3 &scaleVec, const Matrix4 & mat ); + +// Multiply two 4x4 matrices per element +// +__forceinline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); + +// Compute the absolute value of a 4x4 matrix per element +// +__forceinline const Matrix4 absPerElem( const Matrix4 & mat ); + +// Transpose of a 4x4 matrix +// +__forceinline const Matrix4 transpose( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +__forceinline const Matrix4 inverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. +// +__forceinline const Matrix4 affineInverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. +// +__forceinline const Matrix4 orthoInverse( const Matrix4 & mat ); + +// Determinant of a 4x4 matrix +// +__forceinline const floatInVec determinant( const Matrix4 & mat ); + +// Conditionally select between two 4x4 matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +__forceinline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ); + +// Conditionally select between two 4x4 matrices (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +__forceinline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, const boolInVec &select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4x4 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +__forceinline void print( const Matrix4 & mat ); + +// Print a 4x4 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +__forceinline void print( const Matrix4 & mat, const char * name ); + +#endif + +// A 3x4 transformation matrix in array-of-structures format +// +class Transform3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + Vector3 mCol3; + +public: + // Default constructor; does no initialization + // + __forceinline Transform3( ) { }; + + // Copy a 3x4 transformation matrix + // + __forceinline Transform3( const Transform3 & tfrm ); + + // Construct a 3x4 transformation matrix containing the specified columns + // + __forceinline Transform3( const Vector3 &col0, const Vector3 &col1, const Vector3 &col2, const Vector3 &col3 ); + + // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + // + __forceinline Transform3( const Matrix3 & tfrm, const Vector3 &translateVec ); + + // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + // + __forceinline Transform3( const Quat &unitQuat, const Vector3 &translateVec ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value + // + explicit __forceinline Transform3( float scalar ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value (scalar data contained in vector data type) + // + explicit __forceinline Transform3( const floatInVec &scalar ); + + // Assign one 3x4 transformation matrix to another + // + __forceinline Transform3 & operator =( const Transform3 & tfrm ); + + // Set the upper-left 3x3 submatrix + // + __forceinline Transform3 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + // + __forceinline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // + __forceinline Transform3 & setTranslation( const Vector3 &translateVec ); + + // Get the translation component of a 3x4 transformation matrix + // + __forceinline const Vector3 getTranslation( ) const; + + // Set column 0 of a 3x4 transformation matrix + // + __forceinline Transform3 & setCol0( const Vector3 &col0 ); + + // Set column 1 of a 3x4 transformation matrix + // + __forceinline Transform3 & setCol1( const Vector3 &col1 ); + + // Set column 2 of a 3x4 transformation matrix + // + __forceinline Transform3 & setCol2( const Vector3 &col2 ); + + // Set column 3 of a 3x4 transformation matrix + // + __forceinline Transform3 & setCol3( const Vector3 &col3 ); + + // Get column 0 of a 3x4 transformation matrix + // + __forceinline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x4 transformation matrix + // + __forceinline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x4 transformation matrix + // + __forceinline const Vector3 getCol2( ) const; + + // Get column 3 of a 3x4 transformation matrix + // + __forceinline const Vector3 getCol3( ) const; + + // Set the column of a 3x4 transformation matrix referred to by the specified index + // + __forceinline Transform3 & setCol( int col, const Vector3 &vec ); + + // Set the row of a 3x4 transformation matrix referred to by the specified index + // + __forceinline Transform3 & setRow( int row, const Vector4 &vec ); + + // Get the column of a 3x4 transformation matrix referred to by the specified index + // + __forceinline const Vector3 getCol( int col ) const; + + // Get the row of a 3x4 transformation matrix referred to by the specified index + // + __forceinline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + __forceinline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + __forceinline const Vector3 operator []( int col ) const; + + // Set the element of a 3x4 transformation matrix referred to by column and row indices + // + __forceinline Transform3 & setElem( int col, int row, float val ); + + // Set the element of a 3x4 transformation matrix referred to by column and row indices (scalar data contained in vector data type) + // + __forceinline Transform3 & setElem( int col, int row, const floatInVec &val ); + + // Get the element of a 3x4 transformation matrix referred to by column and row indices + // + __forceinline const floatInVec getElem( int col, int row ) const; + + // Multiply a 3x4 transformation matrix by a 3-D vector + // + __forceinline const Vector3 operator *( const Vector3 &vec ) const; + + // Multiply a 3x4 transformation matrix by a 3-D point + // + __forceinline const Point3 operator *( const Point3 &pnt ) const; + + // Multiply two 3x4 transformation matrices + // + __forceinline const Transform3 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + __forceinline Transform3 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 3x4 transformation matrix + // + static __forceinline const Transform3 identity( ); + + // Construct a 3x4 transformation matrix to rotate around the x axis + // + static __forceinline const Transform3 rotationX( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis + // + static __forceinline const Transform3 rotationY( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis + // + static __forceinline const Transform3 rotationZ( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the x axis (scalar data contained in vector data type) + // + static __forceinline const Transform3 rotationX( const floatInVec &radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis (scalar data contained in vector data type) + // + static __forceinline const Transform3 rotationY( const floatInVec &radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis (scalar data contained in vector data type) + // + static __forceinline const Transform3 rotationZ( const floatInVec &radians ); + + // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + // + static __forceinline const Transform3 rotationZYX( const Vector3 &radiansXYZ ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + // + static __forceinline const Transform3 rotation( float radians, const Vector3 &unitVec ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static __forceinline const Transform3 rotation( const floatInVec &radians, const Vector3 &unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static __forceinline const Transform3 rotation( const Quat &unitQuat ); + + // Construct a 3x4 transformation matrix to perform scaling + // + static __forceinline const Transform3 scale( const Vector3 &scaleVec ); + + // Construct a 3x4 transformation matrix to perform translation + // + static __forceinline const Transform3 translation( const Vector3 &translateVec ); + +}; +// Append (post-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +__forceinline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 &scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +__forceinline const Transform3 prependScale( const Vector3 &scaleVec, const Transform3 & tfrm ); + +// Multiply two 3x4 transformation matrices per element +// +__forceinline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); + +// Compute the absolute value of a 3x4 transformation matrix per element +// +__forceinline const Transform3 absPerElem( const Transform3 & tfrm ); + +// Inverse of a 3x4 transformation matrix +// NOTE: +// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. +// +__forceinline const Transform3 inverse( const Transform3 & tfrm ); + +// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. +// +__forceinline const Transform3 orthoInverse( const Transform3 & tfrm ); + +// Conditionally select between two 3x4 transformation matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +__forceinline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ); + +// Conditionally select between two 3x4 transformation matrices (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +__forceinline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, const boolInVec &select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x4 transformation matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +__forceinline void print( const Transform3 & tfrm ); + +// Print a 3x4 transformation matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +__forceinline void print( const Transform3 & tfrm, const char * name ); + +#endif + +} // namespace Aos +} // namespace Vectormath + +#include "vec_aos.h" +#include "quat_aos.h" +#include "mat_aos.h" + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/c/vectormath_aos.h b/Extras/vectormathlibrary/include/vectormath/c/vectormath_aos.h new file mode 100644 index 0000000..329f07a --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/c/vectormath_aos.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_AOS_C_H +#define _VECTORMATH_AOS_C_H + +#if defined(__SPU__) +# include "../spu/c/vectormath_aos.h" +#elif defined(__ALTIVEC__) +# include "../ppu/c/vectormath_aos.h" +#else +# include "../scalar/c/vectormath_aos.h" +#endif + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/c/vectormath_aos_v.h b/Extras/vectormathlibrary/include/vectormath/c/vectormath_aos_v.h new file mode 100644 index 0000000..83368fa --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/c/vectormath_aos_v.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_AOS_C_V_H +#define _VECTORMATH_AOS_C_V_H + +#if defined(__SPU__) +# include "../spu/c/vectormath_aos_v.h" +#elif defined(__ALTIVEC__) +# include "../ppu/c/vectormath_aos_v.h" +#else +# include "../scalar/c/vectormath_aos_v.h" +#endif + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/c/vectormath_soa.h b/Extras/vectormathlibrary/include/vectormath/c/vectormath_soa.h new file mode 100644 index 0000000..42d0792 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/c/vectormath_soa.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_SOA_C_H +#define _VECTORMATH_SOA_C_H + +#if defined(__SPU__) +# include "../spu/c/vectormath_soa.h" +#elif defined(__ALTIVEC__) +# include "../ppu/c/vectormath_soa.h" +#else +# error "Not implemented." +#endif + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/c/vectormath_soa_v.h b/Extras/vectormathlibrary/include/vectormath/c/vectormath_soa_v.h new file mode 100644 index 0000000..ade2eee --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/c/vectormath_soa_v.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_SOA_C_V_H +#define _VECTORMATH_SOA_C_V_H + +#if defined(__SPU__) +# include "../spu/c/vectormath_soa_v.h" +#elif defined(__ALTIVEC__) +# include "../ppu/c/vectormath_soa_v.h" +#else +# error "Not implemented." +#endif + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/cpp/vectormath_aos.h b/Extras/vectormathlibrary/include/vectormath/cpp/vectormath_aos.h new file mode 100644 index 0000000..1d5088f --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/cpp/vectormath_aos.h @@ -0,0 +1,43 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_AOS_CPP_H +#define _VECTORMATH_AOS_CPP_H + +#if defined(__SPU__) +# include "../spu/cpp/vectormath_aos.h" +#elif defined(__ALTIVEC__) +# include "../ppu/cpp/vectormath_aos.h" +#elif defined(__SSE__) +# include "../SSE/cpp/vectormath_aos.h" +#else +# include "../scalar/cpp/vectormath_aos.h" +#endif + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/cpp/vectormath_soa.h b/Extras/vectormathlibrary/include/vectormath/cpp/vectormath_soa.h new file mode 100644 index 0000000..287915f --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/cpp/vectormath_soa.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_SOA_CPP_H +#define _VECTORMATH_SOA_CPP_H + +#if defined(__SPU__) +# include "../spu/cpp/vectormath_soa.h" +#elif defined(__ALTIVEC__) +# include "../ppu/cpp/vectormath_soa.h" +#else +# error "Not implemented." +#endif + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/mat_aos.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/mat_aos.h new file mode 100644 index 0000000..13f4821 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/mat_aos.h @@ -0,0 +1,1833 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_AOS_C_H +#define _VECTORMATH_MAT_AOS_C_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + * for shuffles, words are labeled [x,y,z,w] [a,b,c,d] + */ +#define _VECTORMATH_PERM_ZBWX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XCYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_C, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XYAB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_ZWCD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W, _VECTORMATH_PERM_C, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_XZBX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_CXXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_YAXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XAZC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_YXWZ ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W, _VECTORMATH_PERM_Z }) +#define _VECTORMATH_PERM_YBWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_XYCX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_YCXY ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y }) +#define _VECTORMATH_PERM_CXYC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_ZAYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_BZXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_B, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XZYA ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A }) +#define _VECTORMATH_PERM_ZXXB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_YXXC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_BBYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_B, _VECTORMATH_PERM_B, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PI_OVER_2 1.570796327f + +/*----------------------------------------------------------------------------- + * Definitions + */ +static inline void vmathM3Copy( VmathMatrix3 *result, const VmathMatrix3 *mat ) +{ + vmathV3Copy( &result->col0, &mat->col0 ); + vmathV3Copy( &result->col1, &mat->col1 ); + vmathV3Copy( &result->col2, &mat->col2 ); +} + +static inline void vmathM3MakeFromScalar( VmathMatrix3 *result, float scalar ) +{ + vmathV3MakeFromScalar( &result->col0, scalar ); + vmathV3MakeFromScalar( &result->col1, scalar ); + vmathV3MakeFromScalar( &result->col2, scalar ); +} + +static inline void vmathM3MakeFromQ( VmathMatrix3 *result, const VmathQuat *unitQuat ) +{ + vec_float4 xyzw_2, wwww, yzxw, zxyw, yzxw_2, zxyw_2; + vec_float4 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + vec_uint4 select_x = _VECTORMATH_MASK_0xF000; + vec_uint4 select_z = _VECTORMATH_MASK_0x00F0; + xyzw_2 = vec_add( unitQuat->vec128, unitQuat->vec128 ); + wwww = vec_splat( unitQuat->vec128, 3 ); + yzxw = vec_perm( unitQuat->vec128, unitQuat->vec128, _VECTORMATH_PERM_YZXW ); + zxyw = vec_perm( unitQuat->vec128, unitQuat->vec128, _VECTORMATH_PERM_ZXYW ); + yzxw_2 = vec_perm( xyzw_2, xyzw_2, _VECTORMATH_PERM_YZXW ); + zxyw_2 = vec_perm( xyzw_2, xyzw_2, _VECTORMATH_PERM_ZXYW ); + tmp0 = vec_madd( yzxw_2, wwww, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + tmp1 = vec_nmsub( yzxw, yzxw_2, ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); + tmp2 = vec_madd( yzxw, xyzw_2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + tmp0 = vec_madd( zxyw, xyzw_2, tmp0 ); + tmp1 = vec_nmsub( zxyw, zxyw_2, tmp1 ); + tmp2 = vec_nmsub( zxyw_2, wwww, tmp2 ); + tmp3 = vec_sel( tmp0, tmp1, select_x ); + tmp4 = vec_sel( tmp1, tmp2, select_x ); + tmp5 = vec_sel( tmp2, tmp0, select_x ); + result->col0.vec128 = vec_sel( tmp3, tmp2, select_z ); + result->col1.vec128 = vec_sel( tmp4, tmp0, select_z ); + result->col2.vec128 = vec_sel( tmp5, tmp1, select_z ); +} + +static inline void vmathM3MakeFromCols( VmathMatrix3 *result, const VmathVector3 *_col0, const VmathVector3 *_col1, const VmathVector3 *_col2 ) +{ + vmathV3Copy( &result->col0, _col0 ); + vmathV3Copy( &result->col1, _col1 ); + vmathV3Copy( &result->col2, _col2 ); +} + +static inline void vmathM3SetCol0( VmathMatrix3 *result, const VmathVector3 *_col0 ) +{ + vmathV3Copy( &result->col0, _col0 ); +} + +static inline void vmathM3SetCol1( VmathMatrix3 *result, const VmathVector3 *_col1 ) +{ + vmathV3Copy( &result->col1, _col1 ); +} + +static inline void vmathM3SetCol2( VmathMatrix3 *result, const VmathVector3 *_col2 ) +{ + vmathV3Copy( &result->col2, _col2 ); +} + +static inline void vmathM3SetCol( VmathMatrix3 *result, int col, const VmathVector3 *vec ) +{ + vmathV3Copy( (&result->col0 + col), vec ); +} + +static inline void vmathM3SetRow( VmathMatrix3 *result, int row, const VmathVector3 *vec ) +{ + vmathV3SetElem( &result->col0, row, vmathV3GetElem( vec, 0 ) ); + vmathV3SetElem( &result->col1, row, vmathV3GetElem( vec, 1 ) ); + vmathV3SetElem( &result->col2, row, vmathV3GetElem( vec, 2 ) ); +} + +static inline void vmathM3SetElem( VmathMatrix3 *result, int col, int row, float val ) +{ + VmathVector3 tmpV3_0; + vmathM3GetCol( &tmpV3_0, result, col ); + vmathV3SetElem( &tmpV3_0, row, val ); + vmathM3SetCol( result, col, &tmpV3_0 ); +} + +static inline float vmathM3GetElem( const VmathMatrix3 *mat, int col, int row ) +{ + VmathVector3 tmpV3_0; + vmathM3GetCol( &tmpV3_0, mat, col ); + return vmathV3GetElem( &tmpV3_0, row ); +} + +static inline void vmathM3GetCol0( VmathVector3 *result, const VmathMatrix3 *mat ) +{ + vmathV3Copy( result, &mat->col0 ); +} + +static inline void vmathM3GetCol1( VmathVector3 *result, const VmathMatrix3 *mat ) +{ + vmathV3Copy( result, &mat->col1 ); +} + +static inline void vmathM3GetCol2( VmathVector3 *result, const VmathMatrix3 *mat ) +{ + vmathV3Copy( result, &mat->col2 ); +} + +static inline void vmathM3GetCol( VmathVector3 *result, const VmathMatrix3 *mat, int col ) +{ + vmathV3Copy( result, (&mat->col0 + col) ); +} + +static inline void vmathM3GetRow( VmathVector3 *result, const VmathMatrix3 *mat, int row ) +{ + vmathV3MakeFromElems( result, vmathV3GetElem( &mat->col0, row ), vmathV3GetElem( &mat->col1, row ), vmathV3GetElem( &mat->col2, row ) ); +} + +static inline void vmathM3Transpose( VmathMatrix3 *result, const VmathMatrix3 *mat ) +{ + vec_float4 tmp0, tmp1, res0, res1, res2; + tmp0 = vec_mergeh( mat->col0.vec128, mat->col2.vec128 ); + tmp1 = vec_mergel( mat->col0.vec128, mat->col2.vec128 ); + res0 = vec_mergeh( tmp0, mat->col1.vec128 ); + res1 = vec_perm( tmp0, mat->col1.vec128, _VECTORMATH_PERM_ZBWX ); + res2 = vec_perm( tmp1, mat->col1.vec128, _VECTORMATH_PERM_XCYX ); + result->col0.vec128 = res0; + result->col1.vec128 = res1; + result->col2.vec128 = res2; +} + +static inline void vmathM3Inverse( VmathMatrix3 *result, const VmathMatrix3 *mat ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet, inv0, inv1, inv2; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + tmp2 = _vmathVfCross( mat->col0.vec128, mat->col1.vec128 ); + tmp0 = _vmathVfCross( mat->col1.vec128, mat->col2.vec128 ); + tmp1 = _vmathVfCross( mat->col2.vec128, mat->col0.vec128 ); + dot = _vmathVfDot3( tmp2, mat->col2.vec128 ); + dot = vec_splat( dot, 0 ); + invdet = recipf4( dot ); + tmp3 = vec_mergeh( tmp0, tmp2 ); + tmp4 = vec_mergel( tmp0, tmp2 ); + inv0 = vec_mergeh( tmp3, tmp1 ); + inv1 = vec_perm( tmp3, tmp1, _VECTORMATH_PERM_ZBWX ); + inv2 = vec_perm( tmp4, tmp1, _VECTORMATH_PERM_XCYX ); + inv0 = vec_madd( inv0, invdet, zero ); + inv1 = vec_madd( inv1, invdet, zero ); + inv2 = vec_madd( inv2, invdet, zero ); + result->col0.vec128 = inv0; + result->col1.vec128 = inv1; + result->col2.vec128 = inv2; +} + +static inline float vmathM3Determinant( const VmathMatrix3 *mat ) +{ + VmathVector3 tmpV3_0; + vmathV3Cross( &tmpV3_0, &mat->col0, &mat->col1 ); + return vmathV3Dot( &mat->col2, &tmpV3_0 ); +} + +static inline void vmathM3Add( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ) +{ + vmathV3Add( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV3Add( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV3Add( &result->col2, &mat0->col2, &mat1->col2 ); +} + +static inline void vmathM3Sub( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ) +{ + vmathV3Sub( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV3Sub( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV3Sub( &result->col2, &mat0->col2, &mat1->col2 ); +} + +static inline void vmathM3Neg( VmathMatrix3 *result, const VmathMatrix3 *mat ) +{ + vmathV3Neg( &result->col0, &mat->col0 ); + vmathV3Neg( &result->col1, &mat->col1 ); + vmathV3Neg( &result->col2, &mat->col2 ); +} + +static inline void vmathM3AbsPerElem( VmathMatrix3 *result, const VmathMatrix3 *mat ) +{ + vmathV3AbsPerElem( &result->col0, &mat->col0 ); + vmathV3AbsPerElem( &result->col1, &mat->col1 ); + vmathV3AbsPerElem( &result->col2, &mat->col2 ); +} + +static inline void vmathM3ScalarMul( VmathMatrix3 *result, const VmathMatrix3 *mat, float scalar ) +{ + vmathV3ScalarMul( &result->col0, &mat->col0, scalar ); + vmathV3ScalarMul( &result->col1, &mat->col1, scalar ); + vmathV3ScalarMul( &result->col2, &mat->col2, scalar ); +} + +static inline void vmathM3MulV3( VmathVector3 *result, const VmathMatrix3 *mat, const VmathVector3 *vec ) +{ + vec_float4 res; + vec_float4 xxxx, yyyy, zzzz; + xxxx = vec_splat( vec->vec128, 0 ); + yyyy = vec_splat( vec->vec128, 1 ); + zzzz = vec_splat( vec->vec128, 2 ); + res = vec_madd( mat->col0.vec128, xxxx, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + res = vec_madd( mat->col1.vec128, yyyy, res ); + res = vec_madd( mat->col2.vec128, zzzz, res ); + result->vec128 = res; +} + +static inline void vmathM3Mul( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ) +{ + VmathMatrix3 tmpResult; + vmathM3MulV3( &tmpResult.col0, mat0, &mat1->col0 ); + vmathM3MulV3( &tmpResult.col1, mat0, &mat1->col1 ); + vmathM3MulV3( &tmpResult.col2, mat0, &mat1->col2 ); + vmathM3Copy( result, &tmpResult ); +} + +static inline void vmathM3MulPerElem( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ) +{ + vmathV3MulPerElem( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV3MulPerElem( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV3MulPerElem( &result->col2, &mat0->col2, &mat1->col2 ); +} + +static inline void vmathM3MakeIdentity( VmathMatrix3 *result ) +{ + vmathV3MakeXAxis( &result->col0 ); + vmathV3MakeYAxis( &result->col1 ); + vmathV3MakeZAxis( &result->col2 ); +} + +static inline void vmathM3MakeRotationX( VmathMatrix3 *result, float radians ) +{ + vec_float4 s, c, res1, res2; + vec_uint4 select_y, select_z; + vec_float4 zero; + select_y = _VECTORMATH_MASK_0x0F00; + select_z = _VECTORMATH_MASK_0x00F0; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( _vmathVfSplatScalar(radians), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + vmathV3MakeXAxis( &result->col0 ); + result->col1.vec128 = res1; + result->col2.vec128 = res2; +} + +static inline void vmathM3MakeRotationY( VmathMatrix3 *result, float radians ) +{ + vec_float4 s, c, res0, res2; + vec_uint4 select_x, select_z; + vec_float4 zero; + select_x = _VECTORMATH_MASK_0xF000; + select_z = _VECTORMATH_MASK_0x00F0; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( _vmathVfSplatScalar(radians), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + result->col0.vec128 = res0; + vmathV3MakeYAxis( &result->col1 ); + result->col2.vec128 = res2; +} + +static inline void vmathM3MakeRotationZ( VmathMatrix3 *result, float radians ) +{ + vec_float4 s, c, res0, res1; + vec_uint4 select_x, select_y; + vec_float4 zero; + select_x = _VECTORMATH_MASK_0xF000; + select_y = _VECTORMATH_MASK_0x0F00; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( _vmathVfSplatScalar(radians), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + result->col0.vec128 = res0; + result->col1.vec128 = res1; + vmathV3MakeZAxis( &result->col2 ); +} + +static inline void vmathM3MakeRotationZYX( VmathMatrix3 *result, const VmathVector3 *radiansXYZ ) +{ + VmathVector4 tmpV4_0; + vec_float4 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + vmathV4MakeFromV3Scalar( &tmpV4_0, radiansXYZ, 0.0f ); + angles = tmpV4_0.vec128; + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + Z1 = vec_andc( Z1, (vec_float4)_VECTORMATH_MASK_0x000F ); + Y0 = vec_perm( negS, c, _VECTORMATH_PERM_BBYX ); + Y1 = vec_perm( c, s, _VECTORMATH_PERM_BBYX ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_madd( Z0, Y1, zero ); + result->col0.vec128 = vec_madd( Z0, Y0, zero ); + result->col1.vec128 = vec_madd( Z1, X1, vec_madd( tmp, X0, zero ) ); + result->col2.vec128 = vec_nmsub( Z1, X0, vec_madd( tmp, X1, zero ) ); +} + +static inline void vmathM3MakeRotationAxis( VmathMatrix3 *result, float radians, const VmathVector3 *unitVec ) +{ + vec_float4 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + axis = unitVec->vec128; + sincosf4( (vec_float4){radians,radians,radians,radians}, &s, &c ); + xxxx = vec_splat( axis, 0 ); + yyyy = vec_splat( axis, 1 ); + zzzz = vec_splat( axis, 2 ); + oneMinusC = vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), c ); + axisS = vec_madd( axis, s, zero ); + negAxisS = negatef4( axisS ); + tmp0 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_XZBX ); + tmp1 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_CXXX ); + tmp2 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_YAXX ); + tmp0 = vec_sel( tmp0, c, _VECTORMATH_MASK_0xF000 ); + tmp1 = vec_sel( tmp1, c, _VECTORMATH_MASK_0x0F00 ); + tmp2 = vec_sel( tmp2, c, _VECTORMATH_MASK_0x00F0 ); + result->col0.vec128 = vec_madd( vec_madd( axis, xxxx, zero ), oneMinusC, tmp0 ); + result->col1.vec128 = vec_madd( vec_madd( axis, yyyy, zero ), oneMinusC, tmp1 ); + result->col2.vec128 = vec_madd( vec_madd( axis, zzzz, zero ), oneMinusC, tmp2 ); +} + +static inline void vmathM3MakeRotationQ( VmathMatrix3 *result, const VmathQuat *unitQuat ) +{ + vmathM3MakeFromQ( result, unitQuat ); +} + +static inline void vmathM3MakeScale( VmathMatrix3 *result, const VmathVector3 *scaleVec ) +{ + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + result->col0.vec128 = vec_sel( zero, scaleVec->vec128, _VECTORMATH_MASK_0xF000 ); + result->col1.vec128 = vec_sel( zero, scaleVec->vec128, _VECTORMATH_MASK_0x0F00 ); + result->col2.vec128 = vec_sel( zero, scaleVec->vec128, _VECTORMATH_MASK_0x00F0 ); +} + +static inline void vmathM3AppendScale( VmathMatrix3 *result, const VmathMatrix3 *mat, const VmathVector3 *scaleVec ) +{ + vmathV3ScalarMul( &result->col0, &mat->col0, vmathV3GetX( scaleVec ) ); + vmathV3ScalarMul( &result->col1, &mat->col1, vmathV3GetY( scaleVec ) ); + vmathV3ScalarMul( &result->col2, &mat->col2, vmathV3GetZ( scaleVec ) ); +} + +static inline void vmathM3PrependScale( VmathMatrix3 *result, const VmathVector3 *scaleVec, const VmathMatrix3 *mat ) +{ + vmathV3MulPerElem( &result->col0, &mat->col0, scaleVec ); + vmathV3MulPerElem( &result->col1, &mat->col1, scaleVec ); + vmathV3MulPerElem( &result->col2, &mat->col2, scaleVec ); +} + +static inline void vmathM3Select( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1, unsigned int select1 ) +{ + vmathV3Select( &result->col0, &mat0->col0, &mat1->col0, select1 ); + vmathV3Select( &result->col1, &mat0->col1, &mat1->col1, select1 ); + vmathV3Select( &result->col2, &mat0->col2, &mat1->col2, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathM3Print( const VmathMatrix3 *mat ) +{ + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2; + vmathM3GetRow( &tmpV3_0, mat, 0 ); + vmathV3Print( &tmpV3_0 ); + vmathM3GetRow( &tmpV3_1, mat, 1 ); + vmathV3Print( &tmpV3_1 ); + vmathM3GetRow( &tmpV3_2, mat, 2 ); + vmathV3Print( &tmpV3_2 ); +} + +static inline void vmathM3Prints( const VmathMatrix3 *mat, const char *name ) +{ + printf("%s:\n", name); + vmathM3Print( mat ); +} + +#endif + +static inline void vmathM4Copy( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Copy( &result->col0, &mat->col0 ); + vmathV4Copy( &result->col1, &mat->col1 ); + vmathV4Copy( &result->col2, &mat->col2 ); + vmathV4Copy( &result->col3, &mat->col3 ); +} + +static inline void vmathM4MakeFromScalar( VmathMatrix4 *result, float scalar ) +{ + vmathV4MakeFromScalar( &result->col0, scalar ); + vmathV4MakeFromScalar( &result->col1, scalar ); + vmathV4MakeFromScalar( &result->col2, scalar ); + vmathV4MakeFromScalar( &result->col3, scalar ); +} + +static inline void vmathM4MakeFromT3( VmathMatrix4 *result, const VmathTransform3 *mat ) +{ + vmathV4MakeFromV3Scalar( &result->col0, &mat->col0, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col1, &mat->col1, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col2, &mat->col2, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col3, &mat->col3, 1.0f ); +} + +static inline void vmathM4MakeFromCols( VmathMatrix4 *result, const VmathVector4 *_col0, const VmathVector4 *_col1, const VmathVector4 *_col2, const VmathVector4 *_col3 ) +{ + vmathV4Copy( &result->col0, _col0 ); + vmathV4Copy( &result->col1, _col1 ); + vmathV4Copy( &result->col2, _col2 ); + vmathV4Copy( &result->col3, _col3 ); +} + +static inline void vmathM4MakeFromM3V3( VmathMatrix4 *result, const VmathMatrix3 *mat, const VmathVector3 *translateVec ) +{ + vmathV4MakeFromV3Scalar( &result->col0, &mat->col0, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col1, &mat->col1, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col2, &mat->col2, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col3, translateVec, 1.0f ); +} + +static inline void vmathM4MakeFromQV3( VmathMatrix4 *result, const VmathQuat *unitQuat, const VmathVector3 *translateVec ) +{ + VmathMatrix3 mat; + vmathM3MakeFromQ( &mat, unitQuat ); + vmathV4MakeFromV3Scalar( &result->col0, &mat.col0, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col1, &mat.col1, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col2, &mat.col2, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col3, translateVec, 1.0f ); +} + +static inline void vmathM4SetCol0( VmathMatrix4 *result, const VmathVector4 *_col0 ) +{ + vmathV4Copy( &result->col0, _col0 ); +} + +static inline void vmathM4SetCol1( VmathMatrix4 *result, const VmathVector4 *_col1 ) +{ + vmathV4Copy( &result->col1, _col1 ); +} + +static inline void vmathM4SetCol2( VmathMatrix4 *result, const VmathVector4 *_col2 ) +{ + vmathV4Copy( &result->col2, _col2 ); +} + +static inline void vmathM4SetCol3( VmathMatrix4 *result, const VmathVector4 *_col3 ) +{ + vmathV4Copy( &result->col3, _col3 ); +} + +static inline void vmathM4SetCol( VmathMatrix4 *result, int col, const VmathVector4 *vec ) +{ + vmathV4Copy( (&result->col0 + col), vec ); +} + +static inline void vmathM4SetRow( VmathMatrix4 *result, int row, const VmathVector4 *vec ) +{ + vmathV4SetElem( &result->col0, row, vmathV4GetElem( vec, 0 ) ); + vmathV4SetElem( &result->col1, row, vmathV4GetElem( vec, 1 ) ); + vmathV4SetElem( &result->col2, row, vmathV4GetElem( vec, 2 ) ); + vmathV4SetElem( &result->col3, row, vmathV4GetElem( vec, 3 ) ); +} + +static inline void vmathM4SetElem( VmathMatrix4 *result, int col, int row, float val ) +{ + VmathVector4 tmpV3_0; + vmathM4GetCol( &tmpV3_0, result, col ); + vmathV4SetElem( &tmpV3_0, row, val ); + vmathM4SetCol( result, col, &tmpV3_0 ); +} + +static inline float vmathM4GetElem( const VmathMatrix4 *mat, int col, int row ) +{ + VmathVector4 tmpV4_0; + vmathM4GetCol( &tmpV4_0, mat, col ); + return vmathV4GetElem( &tmpV4_0, row ); +} + +static inline void vmathM4GetCol0( VmathVector4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Copy( result, &mat->col0 ); +} + +static inline void vmathM4GetCol1( VmathVector4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Copy( result, &mat->col1 ); +} + +static inline void vmathM4GetCol2( VmathVector4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Copy( result, &mat->col2 ); +} + +static inline void vmathM4GetCol3( VmathVector4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Copy( result, &mat->col3 ); +} + +static inline void vmathM4GetCol( VmathVector4 *result, const VmathMatrix4 *mat, int col ) +{ + vmathV4Copy( result, (&mat->col0 + col) ); +} + +static inline void vmathM4GetRow( VmathVector4 *result, const VmathMatrix4 *mat, int row ) +{ + vmathV4MakeFromElems( result, vmathV4GetElem( &mat->col0, row ), vmathV4GetElem( &mat->col1, row ), vmathV4GetElem( &mat->col2, row ), vmathV4GetElem( &mat->col3, row ) ); +} + +static inline void vmathM4Transpose( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3, res0, res1, res2, res3; + tmp0 = vec_mergeh( mat->col0.vec128, mat->col2.vec128 ); + tmp1 = vec_mergeh( mat->col1.vec128, mat->col3.vec128 ); + tmp2 = vec_mergel( mat->col0.vec128, mat->col2.vec128 ); + tmp3 = vec_mergel( mat->col1.vec128, mat->col3.vec128 ); + res0 = vec_mergeh( tmp0, tmp1 ); + res1 = vec_mergel( tmp0, tmp1 ); + res2 = vec_mergeh( tmp2, tmp3 ); + res3 = vec_mergel( tmp2, tmp3 ); + result->col0.vec128 = res0; + result->col1.vec128 = res1; + result->col2.vec128 = res2; + result->col3.vec128 = res3; +} + +static inline void vmathM4Inverse( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + vector float in0, in1, in2, in3; + vector float tmp0, tmp1, tmp2, tmp3; + vector float cof0, cof1, cof2, cof3; + vector float t0, t1, t2, t3; + vector float t01, t02, t03, t12, t23; + vector float t1r, t2r; + vector float t01r, t02r, t03r, t12r, t23r; + vector float t1r3, t1r3r; + vector float det, det0, det1, det2, det3, invdet; + vector float vzero = (vector float){0.0}; + in0 = mat->col0.vec128; + in1 = mat->col1.vec128; + in2 = mat->col2.vec128; + in3 = mat->col3.vec128; + /* Perform transform of the input matrix of the form: + * A B C D + * E F G H + * I J K L + * M N O P + * + * The pseudo transpose of the input matrix is trans: + * A E I M + * J N B F + * C G K O + * L P D H + */ + tmp0 = vec_perm(in0, in1, _VECTORMATH_PERM_XAZC); /* A E C G */ + tmp1 = vec_perm(in2, in3, _VECTORMATH_PERM_XAZC); /* I M K O */ + tmp2 = vec_perm(in0, in1, _VECTORMATH_PERM_YBWD); /* B F D H */ + tmp3 = vec_perm(in2, in3, _VECTORMATH_PERM_YBWD); /* J N L P */ + t0 = vec_perm(tmp0, tmp1, _VECTORMATH_PERM_XYAB); /* A E I M */ + t1 = vec_perm(tmp3, tmp2, _VECTORMATH_PERM_XYAB); /* J N B F */ + t2 = vec_perm(tmp0, tmp1, _VECTORMATH_PERM_ZWCD); /* C G K O */ + t3 = vec_perm(tmp3, tmp2, _VECTORMATH_PERM_ZWCD); /* L P D H */ + /* Generate a cofactor matrix. The computed cofactors reside in + * cof0, cof1, cof2, cof3. + */ + t23 = vec_madd(t2, t3, vzero); /* CL GP KD OH */ + t23 = vec_perm(t23, t23, _VECTORMATH_PERM_YXWZ); /* GP CL OH KD */ + cof0 = vec_nmsub(t1, t23, vzero); /* -(JGP NCL FOH BKD) */ + cof1 = vec_nmsub(t0, t23, vzero); /* -(AGP ECL IOH MKD) */ + t23r = vec_sld(t23, t23, 8); /* OH KD GP CL */ + cof0 = vec_madd(t1, t23r, cof0); /* JOH NKD BGP FCL + cof0 */ + cof1 = vec_madd(t0, t23r, cof1); /* AOH EKD IGP MCL + cof1 */ + cof1 = vec_sld(cof1, cof1, 8); /* IGP MCL AOH EKD - IOH MKD AGP ECL */ + t12 = vec_madd(t1, t2, vzero); /* JC NG BK FO */ + t12 = vec_perm(t12, t12, _VECTORMATH_PERM_YXWZ); /* NG JC FO BK */ + cof0 = vec_madd(t3, t12, cof0); /* LNG PJC DFO HBK + cof0 */ + cof3 = vec_madd(t0, t12, vzero); /* ANG EJC IFO MBK */ + t12r = vec_sld(t12, t12, 8); /* FO BK NG JC */ + cof0 = vec_nmsub(t3, t12r, cof0); /* cof0 - LFO PBK DNG HJC */ + cof3 = vec_nmsub(t0, t12r, cof3); /* cof3 - AFO EBK ING MJC */ + cof3 = vec_sld(cof3, cof3, 8); /* ING MJC AFO EBK - IFO MBK ANG EJC */ + t1r = vec_sld(t1, t1, 8); /* B F J N */ + t2r = vec_sld(t2, t2, 8); /* K O C G */ + t1r3 = vec_madd(t1r, t3, vzero); /* BL FP JD NH */ + t1r3 = vec_perm(t1r3, t1r3, _VECTORMATH_PERM_YXWZ); /* FP BL NH JD */ + cof0 = vec_madd(t2r, t1r3, cof0); /* KFP OBL CNH GJD + cof0 */ + cof2 = vec_madd(t0, t1r3, vzero); /* AFP EBL INH MJD */ + t1r3r = vec_sld(t1r3, t1r3, 8); /* NH JD FP BL */ + cof0 = vec_nmsub(t2r, t1r3r, cof0); /* cof0 - KNH OJD CFP GBL */ + cof2 = vec_nmsub(t0, t1r3r, cof2); /* cof2 - ANH EJD IFP MBL */ + cof2 = vec_sld(cof2, cof2, 8); /* IFP MBL ANH EJD - INH MJD AFP EBL */ + t01 = vec_madd(t0, t1, vzero); /* AJ EN IB MF */ + t01 = vec_perm(t01, t01, _VECTORMATH_PERM_YXWZ); /* EN AJ MF IB */ + cof2 = vec_nmsub(t3, t01, cof2); /* cof2 - LEN PAJ DMF HIB */ + cof3 = vec_madd(t2r, t01, cof3); /* KEN OAJ CMF GIB + cof3 */ + t01r = vec_sld(t01, t01, 8); /* MF IB EN AJ */ + cof2 = vec_madd(t3, t01r, cof2); /* LMF PIB DEN HAJ + cof2 */ + cof3 = vec_nmsub(t2r, t01r, cof3); /* cof3 - KMF OIB CEN GAJ */ + t03 = vec_madd(t0, t3, vzero); /* AL EP ID MH */ + t03 = vec_perm(t03, t03, _VECTORMATH_PERM_YXWZ); /* EP AL MH ID */ + cof1 = vec_nmsub(t2r, t03, cof1); /* cof1 - KEP OAL CMH GID */ + cof2 = vec_madd(t1, t03, cof2); /* JEP NAL BMH FID + cof2 */ + t03r = vec_sld(t03, t03, 8); /* MH ID EP AL */ + cof1 = vec_madd(t2r, t03r, cof1); /* KMH OID CEP GAL + cof1 */ + cof2 = vec_nmsub(t1, t03r, cof2); /* cof2 - JMH NID BEP FAL */ + t02 = vec_madd(t0, t2r, vzero); /* AK EO IC MG */ + t02 = vec_perm(t02, t02, _VECTORMATH_PERM_YXWZ); /* E0 AK MG IC */ + cof1 = vec_madd(t3, t02, cof1); /* LEO PAK DMG HIC + cof1 */ + cof3 = vec_nmsub(t1, t02, cof3); /* cof3 - JEO NAK BMG FIC */ + t02r = vec_sld(t02, t02, 8); /* MG IC EO AK */ + cof1 = vec_nmsub(t3, t02r, cof1); /* cof1 - LMG PIC DEO HAK */ + cof3 = vec_madd(t1, t02r, cof3); /* JMG NIC BEO FAK + cof3 */ + /* Compute the determinant of the matrix + * + * det = sum_across(t0 * cof0); + * + * We perform a sum across the entire vector so that + * we don't have to splat the result when multiplying the + * cofactors by the inverse of the determinant. + */ + det = vec_madd(t0, cof0, vzero); + det0 = vec_splat(det, 0); + det1 = vec_splat(det, 1); + det2 = vec_splat(det, 2); + det3 = vec_splat(det, 3); + det = vec_add(det0, det1); + det2 = vec_add(det2, det3); + det = vec_add(det, det2); + /* Compute the reciprocal of the determinant. + */ + invdet = recipf4(det); + /* Multiply the cofactors by the reciprocal of the determinant. + */ + result->col0.vec128 = vec_madd(cof0, invdet, vzero); + result->col1.vec128 = vec_madd(cof1, invdet, vzero); + result->col2.vec128 = vec_madd(cof2, invdet, vzero); + result->col3.vec128 = vec_madd(cof3, invdet, vzero); +} + +static inline void vmathM4AffineInverse( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + VmathTransform3 affineMat, tmpT3_0; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + vmathV4GetXYZ( &tmpV3_0, &mat->col0 ); + vmathT3SetCol0( &affineMat, &tmpV3_0 ); + vmathV4GetXYZ( &tmpV3_1, &mat->col1 ); + vmathT3SetCol1( &affineMat, &tmpV3_1 ); + vmathV4GetXYZ( &tmpV3_2, &mat->col2 ); + vmathT3SetCol2( &affineMat, &tmpV3_2 ); + vmathV4GetXYZ( &tmpV3_3, &mat->col3 ); + vmathT3SetCol3( &affineMat, &tmpV3_3 ); + vmathT3Inverse( &tmpT3_0, &affineMat ); + vmathM4MakeFromT3( result, &tmpT3_0 ); +} + +static inline void vmathM4OrthoInverse( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + VmathTransform3 affineMat, tmpT3_0; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + vmathV4GetXYZ( &tmpV3_0, &mat->col0 ); + vmathT3SetCol0( &affineMat, &tmpV3_0 ); + vmathV4GetXYZ( &tmpV3_1, &mat->col1 ); + vmathT3SetCol1( &affineMat, &tmpV3_1 ); + vmathV4GetXYZ( &tmpV3_2, &mat->col2 ); + vmathT3SetCol2( &affineMat, &tmpV3_2 ); + vmathV4GetXYZ( &tmpV3_3, &mat->col3 ); + vmathT3SetCol3( &affineMat, &tmpV3_3 ); + vmathT3OrthoInverse( &tmpT3_0, &affineMat ); + vmathM4MakeFromT3( result, &tmpT3_0 ); +} + +static inline float vmathM4Determinant( const VmathMatrix4 *mat ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + vector float in0, in1, in2, in3; + vector float tmp0, tmp1, tmp2, tmp3; + vector float cof0; + vector float t0, t1, t2, t3; + vector float t12, t23; + vector float t1r, t2r; + vector float t12r, t23r; + vector float t1r3, t1r3r; + vector float vzero = (vector float){0.0}; + union { vec_float4 v; float s[4]; } tmp; + in0 = mat->col0.vec128; + in1 = mat->col1.vec128; + in2 = mat->col2.vec128; + in3 = mat->col3.vec128; + /* Perform transform of the input matrix of the form: + * A B C D + * E F G H + * I J K L + * M N O P + * + * The pseudo transpose of the input matrix is trans: + * A E I M + * J N B F + * C G K O + * L P D H + */ + tmp0 = vec_perm(in0, in1, _VECTORMATH_PERM_XAZC); /* A E C G */ + tmp1 = vec_perm(in2, in3, _VECTORMATH_PERM_XAZC); /* I M K O */ + tmp2 = vec_perm(in0, in1, _VECTORMATH_PERM_YBWD); /* B F D H */ + tmp3 = vec_perm(in2, in3, _VECTORMATH_PERM_YBWD); /* J N L P */ + t0 = vec_perm(tmp0, tmp1, _VECTORMATH_PERM_XYAB); /* A E I M */ + t1 = vec_perm(tmp3, tmp2, _VECTORMATH_PERM_XYAB); /* J N B F */ + t2 = vec_perm(tmp0, tmp1, _VECTORMATH_PERM_ZWCD); /* C G K O */ + t3 = vec_perm(tmp3, tmp2, _VECTORMATH_PERM_ZWCD); /* L P D H */ + /* Generate a cofactor matrix. The computed cofactors reside in + * cof0, cof1, cof2, cof3. + */ + t23 = vec_madd(t2, t3, vzero); /* CL GP KD OH */ + t23 = vec_perm(t23, t23, _VECTORMATH_PERM_YXWZ); /* GP CL OH KD */ + cof0 = vec_nmsub(t1, t23, vzero); /* -(JGP NCL FOH BKD) */ + t23r = vec_sld(t23, t23, 8); /* OH KD GP CL */ + cof0 = vec_madd(t1, t23r, cof0); /* JOH NKD BGP FCL + cof0 */ + t12 = vec_madd(t1, t2, vzero); /* JC NG BK FO */ + t12 = vec_perm(t12, t12, _VECTORMATH_PERM_YXWZ); /* NG JC FO BK */ + cof0 = vec_madd(t3, t12, cof0); /* LNG PJC DFO HBK + cof0 */ + t12r = vec_sld(t12, t12, 8); /* FO BK NG JC */ + cof0 = vec_nmsub(t3, t12r, cof0); /* cof0 - LFO PBK DNG HJC */ + t1r = vec_sld(t1, t1, 8); /* B F J N */ + t2r = vec_sld(t2, t2, 8); /* K O C G */ + t1r3 = vec_madd(t1r, t3, vzero); /* BL FP JD NH */ + t1r3 = vec_perm(t1r3, t1r3, _VECTORMATH_PERM_YXWZ); /* FP BL NH JD */ + cof0 = vec_madd(t2r, t1r3, cof0); /* KFP OBL CNH GJD + cof0 */ + t1r3r = vec_sld(t1r3, t1r3, 8); /* NH JD FP BL */ + cof0 = vec_nmsub(t2r, t1r3r, cof0); /* cof0 - KNH OJD CFP GBL */ + tmp.v = _vmathVfDot4(t0,cof0); + return tmp.s[0]; +} + +static inline void vmathM4Add( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ) +{ + vmathV4Add( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV4Add( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV4Add( &result->col2, &mat0->col2, &mat1->col2 ); + vmathV4Add( &result->col3, &mat0->col3, &mat1->col3 ); +} + +static inline void vmathM4Sub( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ) +{ + vmathV4Sub( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV4Sub( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV4Sub( &result->col2, &mat0->col2, &mat1->col2 ); + vmathV4Sub( &result->col3, &mat0->col3, &mat1->col3 ); +} + +static inline void vmathM4Neg( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Neg( &result->col0, &mat->col0 ); + vmathV4Neg( &result->col1, &mat->col1 ); + vmathV4Neg( &result->col2, &mat->col2 ); + vmathV4Neg( &result->col3, &mat->col3 ); +} + +static inline void vmathM4AbsPerElem( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + vmathV4AbsPerElem( &result->col0, &mat->col0 ); + vmathV4AbsPerElem( &result->col1, &mat->col1 ); + vmathV4AbsPerElem( &result->col2, &mat->col2 ); + vmathV4AbsPerElem( &result->col3, &mat->col3 ); +} + +static inline void vmathM4ScalarMul( VmathMatrix4 *result, const VmathMatrix4 *mat, float scalar ) +{ + vmathV4ScalarMul( &result->col0, &mat->col0, scalar ); + vmathV4ScalarMul( &result->col1, &mat->col1, scalar ); + vmathV4ScalarMul( &result->col2, &mat->col2, scalar ); + vmathV4ScalarMul( &result->col3, &mat->col3, scalar ); +} + +static inline void vmathM4MulV4( VmathVector4 *result, const VmathMatrix4 *mat, const VmathVector4 *vec ) +{ + vec_float4 tmp0, tmp1, res; + vec_float4 xxxx, yyyy, zzzz, wwww; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + xxxx = vec_splat( vec->vec128, 0 ); + yyyy = vec_splat( vec->vec128, 1 ); + zzzz = vec_splat( vec->vec128, 2 ); + wwww = vec_splat( vec->vec128, 3 ); + tmp0 = vec_madd( mat->col0.vec128, xxxx, zero ); + tmp1 = vec_madd( mat->col1.vec128, yyyy, zero ); + tmp0 = vec_madd( mat->col2.vec128, zzzz, tmp0 ); + tmp1 = vec_madd( mat->col3.vec128, wwww, tmp1 ); + res = vec_add( tmp0, tmp1 ); + result->vec128 = res; +} + +static inline void vmathM4MulV3( VmathVector4 *result, const VmathMatrix4 *mat, const VmathVector3 *vec ) +{ + vec_float4 res; + vec_float4 xxxx, yyyy, zzzz; + xxxx = vec_splat( vec->vec128, 0 ); + yyyy = vec_splat( vec->vec128, 1 ); + zzzz = vec_splat( vec->vec128, 2 ); + res = vec_madd( mat->col0.vec128, xxxx, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + res = vec_madd( mat->col1.vec128, yyyy, res ); + res = vec_madd( mat->col2.vec128, zzzz, res ); + result->vec128 = res; +} + +static inline void vmathM4MulP3( VmathVector4 *result, const VmathMatrix4 *mat, const VmathPoint3 *pnt ) +{ + vec_float4 tmp0, tmp1, res; + vec_float4 xxxx, yyyy, zzzz; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + xxxx = vec_splat( pnt->vec128, 0 ); + yyyy = vec_splat( pnt->vec128, 1 ); + zzzz = vec_splat( pnt->vec128, 2 ); + tmp0 = vec_madd( mat->col0.vec128, xxxx, zero ); + tmp1 = vec_madd( mat->col1.vec128, yyyy, zero ); + tmp0 = vec_madd( mat->col2.vec128, zzzz, tmp0 ); + tmp1 = vec_add( mat->col3.vec128, tmp1 ); + res = vec_add( tmp0, tmp1 ); + result->vec128 = res; +} + +static inline void vmathM4Mul( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ) +{ + VmathMatrix4 tmpResult; + vmathM4MulV4( &tmpResult.col0, mat0, &mat1->col0 ); + vmathM4MulV4( &tmpResult.col1, mat0, &mat1->col1 ); + vmathM4MulV4( &tmpResult.col2, mat0, &mat1->col2 ); + vmathM4MulV4( &tmpResult.col3, mat0, &mat1->col3 ); + vmathM4Copy( result, &tmpResult ); +} + +static inline void vmathM4MulT3( VmathMatrix4 *result, const VmathMatrix4 *mat, const VmathTransform3 *tfrm1 ) +{ + VmathMatrix4 tmpResult; + VmathPoint3 tmpP3_0; + vmathM4MulV3( &tmpResult.col0, mat, &tfrm1->col0 ); + vmathM4MulV3( &tmpResult.col1, mat, &tfrm1->col1 ); + vmathM4MulV3( &tmpResult.col2, mat, &tfrm1->col2 ); + vmathP3MakeFromV3( &tmpP3_0, &tfrm1->col3 ); + vmathM4MulP3( &tmpResult.col3, mat, &tmpP3_0 ); + vmathM4Copy( result, &tmpResult ); +} + +static inline void vmathM4MulPerElem( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ) +{ + vmathV4MulPerElem( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV4MulPerElem( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV4MulPerElem( &result->col2, &mat0->col2, &mat1->col2 ); + vmathV4MulPerElem( &result->col3, &mat0->col3, &mat1->col3 ); +} + +static inline void vmathM4MakeIdentity( VmathMatrix4 *result ) +{ + vmathV4MakeXAxis( &result->col0 ); + vmathV4MakeYAxis( &result->col1 ); + vmathV4MakeZAxis( &result->col2 ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4SetUpper3x3( VmathMatrix4 *result, const VmathMatrix3 *mat3 ) +{ + vmathV4SetXYZ( &result->col0, &mat3->col0 ); + vmathV4SetXYZ( &result->col1, &mat3->col1 ); + vmathV4SetXYZ( &result->col2, &mat3->col2 ); +} + +static inline void vmathM4GetUpper3x3( VmathMatrix3 *result, const VmathMatrix4 *mat ) +{ + vmathV4GetXYZ( &result->col0, &mat->col0 ); + vmathV4GetXYZ( &result->col1, &mat->col1 ); + vmathV4GetXYZ( &result->col2, &mat->col2 ); +} + +static inline void vmathM4SetTranslation( VmathMatrix4 *result, const VmathVector3 *translateVec ) +{ + vmathV4SetXYZ( &result->col3, translateVec ); +} + +static inline void vmathM4GetTranslation( VmathVector3 *result, const VmathMatrix4 *mat ) +{ + vmathV4GetXYZ( result, &mat->col3 ); +} + +static inline void vmathM4MakeRotationX( VmathMatrix4 *result, float radians ) +{ + vec_float4 s, c, res1, res2; + vec_uint4 select_y, select_z; + vec_float4 zero; + select_y = _VECTORMATH_MASK_0x0F00; + select_z = _VECTORMATH_MASK_0x00F0; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( _vmathVfSplatScalar(radians), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + vmathV4MakeXAxis( &result->col0 ); + result->col1.vec128 = res1; + result->col2.vec128 = res2; + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4MakeRotationY( VmathMatrix4 *result, float radians ) +{ + vec_float4 s, c, res0, res2; + vec_uint4 select_x, select_z; + vec_float4 zero; + select_x = _VECTORMATH_MASK_0xF000; + select_z = _VECTORMATH_MASK_0x00F0; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( _vmathVfSplatScalar(radians), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + result->col0.vec128 = res0; + vmathV4MakeYAxis( &result->col1 ); + result->col2.vec128 = res2; + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4MakeRotationZ( VmathMatrix4 *result, float radians ) +{ + vec_float4 s, c, res0, res1; + vec_uint4 select_x, select_y; + vec_float4 zero; + select_x = _VECTORMATH_MASK_0xF000; + select_y = _VECTORMATH_MASK_0x0F00; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( _vmathVfSplatScalar(radians), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + result->col0.vec128 = res0; + result->col1.vec128 = res1; + vmathV4MakeZAxis( &result->col2 ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4MakeRotationZYX( VmathMatrix4 *result, const VmathVector3 *radiansXYZ ) +{ + VmathVector4 tmpV4_0; + vec_float4 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + vmathV4MakeFromV3Scalar( &tmpV4_0, radiansXYZ, 0.0f ); + angles = tmpV4_0.vec128; + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + Z1 = vec_andc( Z1, (vec_float4)_VECTORMATH_MASK_0x000F ); + Y0 = vec_perm( negS, c, _VECTORMATH_PERM_BBYX ); + Y1 = vec_perm( c, s, _VECTORMATH_PERM_BBYX ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_madd( Z0, Y1, zero ); + result->col0.vec128 = vec_madd( Z0, Y0, zero ); + result->col1.vec128 = vec_madd( Z1, X1, vec_madd( tmp, X0, zero ) ); + result->col2.vec128 = vec_nmsub( Z1, X0, vec_madd( tmp, X1, zero ) ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4MakeRotationAxis( VmathMatrix4 *result, float radians, const VmathVector3 *unitVec ) +{ + vec_float4 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2, zeroW; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + axis = unitVec->vec128; + sincosf4( (vec_float4){radians,radians,radians,radians}, &s, &c ); + xxxx = vec_splat( axis, 0 ); + yyyy = vec_splat( axis, 1 ); + zzzz = vec_splat( axis, 2 ); + oneMinusC = vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), c ); + axisS = vec_madd( axis, s, zero ); + negAxisS = negatef4( axisS ); + tmp0 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_XZBX ); + tmp1 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_CXXX ); + tmp2 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_YAXX ); + tmp0 = vec_sel( tmp0, c, _VECTORMATH_MASK_0xF000 ); + tmp1 = vec_sel( tmp1, c, _VECTORMATH_MASK_0x0F00 ); + tmp2 = vec_sel( tmp2, c, _VECTORMATH_MASK_0x00F0 ); + zeroW = (vec_float4)_VECTORMATH_MASK_0x000F; + axis = vec_andc( axis, zeroW ); + tmp0 = vec_andc( tmp0, zeroW ); + tmp1 = vec_andc( tmp1, zeroW ); + tmp2 = vec_andc( tmp2, zeroW ); + result->col0.vec128 = vec_madd( vec_madd( axis, xxxx, zero ), oneMinusC, tmp0 ); + result->col1.vec128 = vec_madd( vec_madd( axis, yyyy, zero ), oneMinusC, tmp1 ); + result->col2.vec128 = vec_madd( vec_madd( axis, zzzz, zero ), oneMinusC, tmp2 ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4MakeRotationQ( VmathMatrix4 *result, const VmathQuat *unitQuat ) +{ + VmathTransform3 tmpT3_0; + vmathT3MakeRotationQ( &tmpT3_0, unitQuat ); + vmathM4MakeFromT3( result, &tmpT3_0 ); +} + +static inline void vmathM4MakeScale( VmathMatrix4 *result, const VmathVector3 *scaleVec ) +{ + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + result->col0.vec128 = vec_sel( zero, scaleVec->vec128, _VECTORMATH_MASK_0xF000 ); + result->col1.vec128 = vec_sel( zero, scaleVec->vec128, _VECTORMATH_MASK_0x0F00 ); + result->col2.vec128 = vec_sel( zero, scaleVec->vec128, _VECTORMATH_MASK_0x00F0 ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4AppendScale( VmathMatrix4 *result, const VmathMatrix4 *mat, const VmathVector3 *scaleVec ) +{ + vmathV4ScalarMul( &result->col0, &mat->col0, vmathV3GetX( scaleVec ) ); + vmathV4ScalarMul( &result->col1, &mat->col1, vmathV3GetY( scaleVec ) ); + vmathV4ScalarMul( &result->col2, &mat->col2, vmathV3GetZ( scaleVec ) ); + vmathV4Copy( &result->col3, &mat->col3 ); +} + +static inline void vmathM4PrependScale( VmathMatrix4 *result, const VmathVector3 *scaleVec, const VmathMatrix4 *mat ) +{ + VmathVector4 scale4; + vmathV4MakeFromV3Scalar( &scale4, scaleVec, 1.0f ); + vmathV4MulPerElem( &result->col0, &mat->col0, &scale4 ); + vmathV4MulPerElem( &result->col1, &mat->col1, &scale4 ); + vmathV4MulPerElem( &result->col2, &mat->col2, &scale4 ); + vmathV4MulPerElem( &result->col3, &mat->col3, &scale4 ); +} + +static inline void vmathM4MakeTranslation( VmathMatrix4 *result, const VmathVector3 *translateVec ) +{ + vmathV4MakeXAxis( &result->col0 ); + vmathV4MakeYAxis( &result->col1 ); + vmathV4MakeZAxis( &result->col2 ); + vmathV4MakeFromV3Scalar( &result->col3, translateVec, 1.0f ); +} + +static inline void vmathM4MakeLookAt( VmathMatrix4 *result, const VmathPoint3 *eyePos, const VmathPoint3 *lookAtPos, const VmathVector3 *upVec ) +{ + VmathMatrix4 m4EyeFrame; + VmathVector3 v3X, v3Y, v3Z, tmpV3_0, tmpV3_1; + VmathVector4 tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3; + vmathV3Normalize( &v3Y, upVec ); + vmathP3Sub( &tmpV3_0, eyePos, lookAtPos ); + vmathV3Normalize( &v3Z, &tmpV3_0 ); + vmathV3Cross( &tmpV3_1, &v3Y, &v3Z ); + vmathV3Normalize( &v3X, &tmpV3_1 ); + vmathV3Cross( &v3Y, &v3Z, &v3X ); + vmathV4MakeFromV3( &tmpV4_0, &v3X ); + vmathV4MakeFromV3( &tmpV4_1, &v3Y ); + vmathV4MakeFromV3( &tmpV4_2, &v3Z ); + vmathV4MakeFromP3( &tmpV4_3, eyePos ); + vmathM4MakeFromCols( &m4EyeFrame, &tmpV4_0, &tmpV4_1, &tmpV4_2, &tmpV4_3 ); + vmathM4OrthoInverse( result, &m4EyeFrame ); +} + +static inline void vmathM4MakePerspective( VmathMatrix4 *result, float fovyRadians, float aspect, float zNear, float zFar ) +{ + float f, rangeInv; + vec_float4 zero, col0, col1, col2, col3; + union { vec_float4 v; float s[4]; } tmp; + f = tanf( _VECTORMATH_PI_OVER_2 - fovyRadians * 0.5f ); + rangeInv = 1.0f / ( zNear - zFar ); + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + tmp.v = zero; + tmp.s[0] = f / aspect; + col0 = tmp.v; + tmp.v = zero; + tmp.s[1] = f; + col1 = tmp.v; + tmp.v = zero; + tmp.s[2] = ( zNear + zFar ) * rangeInv; + tmp.s[3] = -1.0f; + col2 = tmp.v; + tmp.v = zero; + tmp.s[2] = zNear * zFar * rangeInv * 2.0f; + col3 = tmp.v; + result->col0.vec128 = col0; + result->col1.vec128 = col1; + result->col2.vec128 = col2; + result->col3.vec128 = col3; +} + +static inline void vmathM4MakeFrustum( VmathMatrix4 *result, float left, float right, float bottom, float top, float zNear, float zFar ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + vec_float4 lbf, rtn; + vec_float4 diff, sum, inv_diff; + vec_float4 diagonal, column, near2; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + union { vec_float4 v; float s[4]; } l, f, r, n, b, t; + l.s[0] = left; + f.s[0] = zFar; + r.s[0] = right; + n.s[0] = zNear; + b.s[0] = bottom; + t.s[0] = top; + lbf = vec_mergeh( l.v, f.v ); + rtn = vec_mergeh( r.v, n.v ); + lbf = vec_mergeh( lbf, b.v ); + rtn = vec_mergeh( rtn, t.v ); + diff = vec_sub( rtn, lbf ); + sum = vec_add( rtn, lbf ); + inv_diff = recipf4( diff ); + near2 = vec_splat( n.v, 0 ); + near2 = vec_add( near2, near2 ); + diagonal = vec_madd( near2, inv_diff, zero ); + column = vec_madd( sum, inv_diff, zero ); + result->col0.vec128 = vec_sel( zero, diagonal, _VECTORMATH_MASK_0xF000 ); + result->col1.vec128 = vec_sel( zero, diagonal, _VECTORMATH_MASK_0x0F00 ); + result->col2.vec128 = vec_sel( column, ((vec_float4){-1.0f,-1.0f,-1.0f,-1.0f}), _VECTORMATH_MASK_0x000F ); + result->col3.vec128 = vec_sel( zero, vec_madd( diagonal, vec_splat( f.v, 0 ), zero ), _VECTORMATH_MASK_0x00F0 ); +} + +static inline void vmathM4MakeOrthographic( VmathMatrix4 *result, float left, float right, float bottom, float top, float zNear, float zFar ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + vec_float4 lbf, rtn; + vec_float4 diff, sum, inv_diff, neg_inv_diff; + vec_float4 diagonal, column; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + union { vec_float4 v; float s[4]; } l, f, r, n, b, t; + l.s[0] = left; + f.s[0] = zFar; + r.s[0] = right; + n.s[0] = zNear; + b.s[0] = bottom; + t.s[0] = top; + lbf = vec_mergeh( l.v, f.v ); + rtn = vec_mergeh( r.v, n.v ); + lbf = vec_mergeh( lbf, b.v ); + rtn = vec_mergeh( rtn, t.v ); + diff = vec_sub( rtn, lbf ); + sum = vec_add( rtn, lbf ); + inv_diff = recipf4( diff ); + neg_inv_diff = negatef4( inv_diff ); + diagonal = vec_add( inv_diff, inv_diff ); + column = vec_madd( sum, vec_sel( neg_inv_diff, inv_diff, _VECTORMATH_MASK_0x00F0 ), zero ); + result->col0.vec128 = vec_sel( zero, diagonal, _VECTORMATH_MASK_0xF000 ); + result->col1.vec128 = vec_sel( zero, diagonal, _VECTORMATH_MASK_0x0F00 ); + result->col2.vec128 = vec_sel( zero, diagonal, _VECTORMATH_MASK_0x00F0 ); + result->col3.vec128 = vec_sel( column, ((vec_float4){1.0f,1.0f,1.0f,1.0f}), _VECTORMATH_MASK_0x000F ); +} + +static inline void vmathM4Select( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1, unsigned int select1 ) +{ + vmathV4Select( &result->col0, &mat0->col0, &mat1->col0, select1 ); + vmathV4Select( &result->col1, &mat0->col1, &mat1->col1, select1 ); + vmathV4Select( &result->col2, &mat0->col2, &mat1->col2, select1 ); + vmathV4Select( &result->col3, &mat0->col3, &mat1->col3, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathM4Print( const VmathMatrix4 *mat ) +{ + VmathVector4 tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3; + vmathM4GetRow( &tmpV4_0, mat, 0 ); + vmathV4Print( &tmpV4_0 ); + vmathM4GetRow( &tmpV4_1, mat, 1 ); + vmathV4Print( &tmpV4_1 ); + vmathM4GetRow( &tmpV4_2, mat, 2 ); + vmathV4Print( &tmpV4_2 ); + vmathM4GetRow( &tmpV4_3, mat, 3 ); + vmathV4Print( &tmpV4_3 ); +} + +static inline void vmathM4Prints( const VmathMatrix4 *mat, const char *name ) +{ + printf("%s:\n", name); + vmathM4Print( mat ); +} + +#endif + +static inline void vmathT3Copy( VmathTransform3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( &result->col0, &tfrm->col0 ); + vmathV3Copy( &result->col1, &tfrm->col1 ); + vmathV3Copy( &result->col2, &tfrm->col2 ); + vmathV3Copy( &result->col3, &tfrm->col3 ); +} + +static inline void vmathT3MakeFromScalar( VmathTransform3 *result, float scalar ) +{ + vmathV3MakeFromScalar( &result->col0, scalar ); + vmathV3MakeFromScalar( &result->col1, scalar ); + vmathV3MakeFromScalar( &result->col2, scalar ); + vmathV3MakeFromScalar( &result->col3, scalar ); +} + +static inline void vmathT3MakeFromCols( VmathTransform3 *result, const VmathVector3 *_col0, const VmathVector3 *_col1, const VmathVector3 *_col2, const VmathVector3 *_col3 ) +{ + vmathV3Copy( &result->col0, _col0 ); + vmathV3Copy( &result->col1, _col1 ); + vmathV3Copy( &result->col2, _col2 ); + vmathV3Copy( &result->col3, _col3 ); +} + +static inline void vmathT3MakeFromM3V3( VmathTransform3 *result, const VmathMatrix3 *tfrm, const VmathVector3 *translateVec ) +{ + vmathT3SetUpper3x3( result, tfrm ); + vmathT3SetTranslation( result, translateVec ); +} + +static inline void vmathT3MakeFromQV3( VmathTransform3 *result, const VmathQuat *unitQuat, const VmathVector3 *translateVec ) +{ + VmathMatrix3 tmpM3_0; + vmathM3MakeFromQ( &tmpM3_0, unitQuat ); + vmathT3SetUpper3x3( result, &tmpM3_0 ); + vmathT3SetTranslation( result, translateVec ); +} + +static inline void vmathT3SetCol0( VmathTransform3 *result, const VmathVector3 *_col0 ) +{ + vmathV3Copy( &result->col0, _col0 ); +} + +static inline void vmathT3SetCol1( VmathTransform3 *result, const VmathVector3 *_col1 ) +{ + vmathV3Copy( &result->col1, _col1 ); +} + +static inline void vmathT3SetCol2( VmathTransform3 *result, const VmathVector3 *_col2 ) +{ + vmathV3Copy( &result->col2, _col2 ); +} + +static inline void vmathT3SetCol3( VmathTransform3 *result, const VmathVector3 *_col3 ) +{ + vmathV3Copy( &result->col3, _col3 ); +} + +static inline void vmathT3SetCol( VmathTransform3 *result, int col, const VmathVector3 *vec ) +{ + vmathV3Copy( (&result->col0 + col), vec ); +} + +static inline void vmathT3SetRow( VmathTransform3 *result, int row, const VmathVector4 *vec ) +{ + vmathV3SetElem( &result->col0, row, vmathV4GetElem( vec, 0 ) ); + vmathV3SetElem( &result->col1, row, vmathV4GetElem( vec, 1 ) ); + vmathV3SetElem( &result->col2, row, vmathV4GetElem( vec, 2 ) ); + vmathV3SetElem( &result->col3, row, vmathV4GetElem( vec, 3 ) ); +} + +static inline void vmathT3SetElem( VmathTransform3 *result, int col, int row, float val ) +{ + VmathVector3 tmpV3_0; + vmathT3GetCol( &tmpV3_0, result, col ); + vmathV3SetElem( &tmpV3_0, row, val ); + vmathT3SetCol( result, col, &tmpV3_0 ); +} + +static inline float vmathT3GetElem( const VmathTransform3 *tfrm, int col, int row ) +{ + VmathVector3 tmpV3_0; + vmathT3GetCol( &tmpV3_0, tfrm, col ); + return vmathV3GetElem( &tmpV3_0, row ); +} + +static inline void vmathT3GetCol0( VmathVector3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( result, &tfrm->col0 ); +} + +static inline void vmathT3GetCol1( VmathVector3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( result, &tfrm->col1 ); +} + +static inline void vmathT3GetCol2( VmathVector3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( result, &tfrm->col2 ); +} + +static inline void vmathT3GetCol3( VmathVector3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( result, &tfrm->col3 ); +} + +static inline void vmathT3GetCol( VmathVector3 *result, const VmathTransform3 *tfrm, int col ) +{ + vmathV3Copy( result, (&tfrm->col0 + col) ); +} + +static inline void vmathT3GetRow( VmathVector4 *result, const VmathTransform3 *tfrm, int row ) +{ + vmathV4MakeFromElems( result, vmathV3GetElem( &tfrm->col0, row ), vmathV3GetElem( &tfrm->col1, row ), vmathV3GetElem( &tfrm->col2, row ), vmathV3GetElem( &tfrm->col3, row ) ); +} + +static inline void vmathT3Inverse( VmathTransform3 *result, const VmathTransform3 *tfrm ) +{ + vec_float4 inv0, inv1, inv2, inv3; + vec_float4 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet; + vec_float4 xxxx, yyyy, zzzz; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + tmp2 = _vmathVfCross( tfrm->col0.vec128, tfrm->col1.vec128 ); + tmp0 = _vmathVfCross( tfrm->col1.vec128, tfrm->col2.vec128 ); + tmp1 = _vmathVfCross( tfrm->col2.vec128, tfrm->col0.vec128 ); + inv3 = negatef4( tfrm->col3.vec128 ); + dot = _vmathVfDot3( tmp2, tfrm->col2.vec128 ); + dot = vec_splat( dot, 0 ); + invdet = recipf4( dot ); + tmp3 = vec_mergeh( tmp0, tmp2 ); + tmp4 = vec_mergel( tmp0, tmp2 ); + inv0 = vec_mergeh( tmp3, tmp1 ); + xxxx = vec_splat( inv3, 0 ); + inv1 = vec_perm( tmp3, tmp1, _VECTORMATH_PERM_ZBWX ); + inv2 = vec_perm( tmp4, tmp1, _VECTORMATH_PERM_XCYX ); + yyyy = vec_splat( inv3, 1 ); + zzzz = vec_splat( inv3, 2 ); + inv3 = vec_madd( inv0, xxxx, zero ); + inv3 = vec_madd( inv1, yyyy, inv3 ); + inv3 = vec_madd( inv2, zzzz, inv3 ); + inv0 = vec_madd( inv0, invdet, zero ); + inv1 = vec_madd( inv1, invdet, zero ); + inv2 = vec_madd( inv2, invdet, zero ); + inv3 = vec_madd( inv3, invdet, zero ); + result->col0.vec128 = inv0; + result->col1.vec128 = inv1; + result->col2.vec128 = inv2; + result->col3.vec128 = inv3; +} + +static inline void vmathT3OrthoInverse( VmathTransform3 *result, const VmathTransform3 *tfrm ) +{ + vec_float4 inv0, inv1, inv2, inv3; + vec_float4 tmp0, tmp1; + vec_float4 xxxx, yyyy, zzzz; + tmp0 = vec_mergeh( tfrm->col0.vec128, tfrm->col2.vec128 ); + tmp1 = vec_mergel( tfrm->col0.vec128, tfrm->col2.vec128 ); + inv3 = negatef4( tfrm->col3.vec128 ); + inv0 = vec_mergeh( tmp0, tfrm->col1.vec128 ); + xxxx = vec_splat( inv3, 0 ); + inv1 = vec_perm( tmp0, tfrm->col1.vec128, _VECTORMATH_PERM_ZBWX ); + inv2 = vec_perm( tmp1, tfrm->col1.vec128, _VECTORMATH_PERM_XCYX ); + yyyy = vec_splat( inv3, 1 ); + zzzz = vec_splat( inv3, 2 ); + inv3 = vec_madd( inv0, xxxx, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + inv3 = vec_madd( inv1, yyyy, inv3 ); + inv3 = vec_madd( inv2, zzzz, inv3 ); + result->col0.vec128 = inv0; + result->col1.vec128 = inv1; + result->col2.vec128 = inv2; + result->col3.vec128 = inv3; +} + +static inline void vmathT3AbsPerElem( VmathTransform3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3AbsPerElem( &result->col0, &tfrm->col0 ); + vmathV3AbsPerElem( &result->col1, &tfrm->col1 ); + vmathV3AbsPerElem( &result->col2, &tfrm->col2 ); + vmathV3AbsPerElem( &result->col3, &tfrm->col3 ); +} + +static inline void vmathT3MulV3( VmathVector3 *result, const VmathTransform3 *tfrm, const VmathVector3 *vec ) +{ + vec_float4 res; + vec_float4 xxxx, yyyy, zzzz; + xxxx = vec_splat( vec->vec128, 0 ); + yyyy = vec_splat( vec->vec128, 1 ); + zzzz = vec_splat( vec->vec128, 2 ); + res = vec_madd( tfrm->col0.vec128, xxxx, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + res = vec_madd( tfrm->col1.vec128, yyyy, res ); + res = vec_madd( tfrm->col2.vec128, zzzz, res ); + result->vec128 = res; +} + +static inline void vmathT3MulP3( VmathPoint3 *result, const VmathTransform3 *tfrm, const VmathPoint3 *pnt ) +{ + vec_float4 tmp0, tmp1, res; + vec_float4 xxxx, yyyy, zzzz; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + xxxx = vec_splat( pnt->vec128, 0 ); + yyyy = vec_splat( pnt->vec128, 1 ); + zzzz = vec_splat( pnt->vec128, 2 ); + tmp0 = vec_madd( tfrm->col0.vec128, xxxx, zero ); + tmp1 = vec_madd( tfrm->col1.vec128, yyyy, zero ); + tmp0 = vec_madd( tfrm->col2.vec128, zzzz, tmp0 ); + tmp1 = vec_add( tfrm->col3.vec128, tmp1 ); + res = vec_add( tmp0, tmp1 ); + result->vec128 = res; +} + +static inline void vmathT3Mul( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1 ) +{ + VmathTransform3 tmpResult; + VmathPoint3 tmpP3_0, tmpP3_1; + vmathT3MulV3( &tmpResult.col0, tfrm0, &tfrm1->col0 ); + vmathT3MulV3( &tmpResult.col1, tfrm0, &tfrm1->col1 ); + vmathT3MulV3( &tmpResult.col2, tfrm0, &tfrm1->col2 ); + vmathP3MakeFromV3( &tmpP3_0, &tfrm1->col3 ); + vmathT3MulP3( &tmpP3_1, tfrm0, &tmpP3_0 ); + vmathV3MakeFromP3( &tmpResult.col3, &tmpP3_1 ); + vmathT3Copy( result, &tmpResult ); +} + +static inline void vmathT3MulPerElem( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1 ) +{ + vmathV3MulPerElem( &result->col0, &tfrm0->col0, &tfrm1->col0 ); + vmathV3MulPerElem( &result->col1, &tfrm0->col1, &tfrm1->col1 ); + vmathV3MulPerElem( &result->col2, &tfrm0->col2, &tfrm1->col2 ); + vmathV3MulPerElem( &result->col3, &tfrm0->col3, &tfrm1->col3 ); +} + +static inline void vmathT3MakeIdentity( VmathTransform3 *result ) +{ + vmathV3MakeXAxis( &result->col0 ); + vmathV3MakeYAxis( &result->col1 ); + vmathV3MakeZAxis( &result->col2 ); + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3SetUpper3x3( VmathTransform3 *result, const VmathMatrix3 *tfrm ) +{ + vmathV3Copy( &result->col0, &tfrm->col0 ); + vmathV3Copy( &result->col1, &tfrm->col1 ); + vmathV3Copy( &result->col2, &tfrm->col2 ); +} + +static inline void vmathT3GetUpper3x3( VmathMatrix3 *result, const VmathTransform3 *tfrm ) +{ + vmathM3MakeFromCols( result, &tfrm->col0, &tfrm->col1, &tfrm->col2 ); +} + +static inline void vmathT3SetTranslation( VmathTransform3 *result, const VmathVector3 *translateVec ) +{ + vmathV3Copy( &result->col3, translateVec ); +} + +static inline void vmathT3GetTranslation( VmathVector3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( result, &tfrm->col3 ); +} + +static inline void vmathT3MakeRotationX( VmathTransform3 *result, float radians ) +{ + vec_float4 s, c, res1, res2; + vec_uint4 select_y, select_z; + vec_float4 zero; + select_y = _VECTORMATH_MASK_0x0F00; + select_z = _VECTORMATH_MASK_0x00F0; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( _vmathVfSplatScalar(radians), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + vmathV3MakeXAxis( &result->col0 ); + result->col1.vec128 = res1; + result->col2.vec128 = res2; + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3MakeRotationY( VmathTransform3 *result, float radians ) +{ + vec_float4 s, c, res0, res2; + vec_uint4 select_x, select_z; + vec_float4 zero; + select_x = _VECTORMATH_MASK_0xF000; + select_z = _VECTORMATH_MASK_0x00F0; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( _vmathVfSplatScalar(radians), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + result->col0.vec128 = res0; + vmathV3MakeYAxis( &result->col1 ); + result->col2.vec128 = res2; + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3MakeRotationZ( VmathTransform3 *result, float radians ) +{ + vec_float4 s, c, res0, res1; + vec_uint4 select_x, select_y; + vec_float4 zero; + select_x = _VECTORMATH_MASK_0xF000; + select_y = _VECTORMATH_MASK_0x0F00; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( _vmathVfSplatScalar(radians), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + result->col0.vec128 = res0; + result->col1.vec128 = res1; + vmathV3MakeZAxis( &result->col2 ); + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3MakeRotationZYX( VmathTransform3 *result, const VmathVector3 *radiansXYZ ) +{ + VmathVector4 tmpV4_0; + vec_float4 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + vmathV4MakeFromV3Scalar( &tmpV4_0, radiansXYZ, 0.0f ); + angles = tmpV4_0.vec128; + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + Z1 = vec_andc( Z1, (vec_float4)_VECTORMATH_MASK_0x000F ); + Y0 = vec_perm( negS, c, _VECTORMATH_PERM_BBYX ); + Y1 = vec_perm( c, s, _VECTORMATH_PERM_BBYX ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_madd( Z0, Y1, zero ); + result->col0.vec128 = vec_madd( Z0, Y0, zero ); + result->col1.vec128 = vec_madd( Z1, X1, vec_madd( tmp, X0, zero ) ); + result->col2.vec128 = vec_nmsub( Z1, X0, vec_madd( tmp, X1, zero ) ); + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3MakeRotationAxis( VmathTransform3 *result, float radians, const VmathVector3 *unitVec ) +{ + VmathMatrix3 tmpM3_0; + VmathVector3 tmpV3_0; + vmathM3MakeRotationAxis( &tmpM3_0, radians, unitVec ); + vmathV3MakeFromScalar( &tmpV3_0, 0.0f ); + vmathT3MakeFromM3V3( result, &tmpM3_0, &tmpV3_0 ); +} + +static inline void vmathT3MakeRotationQ( VmathTransform3 *result, const VmathQuat *unitQuat ) +{ + VmathMatrix3 tmpM3_0; + VmathVector3 tmpV3_0; + vmathM3MakeFromQ( &tmpM3_0, unitQuat ); + vmathV3MakeFromScalar( &tmpV3_0, 0.0f ); + vmathT3MakeFromM3V3( result, &tmpM3_0, &tmpV3_0 ); +} + +static inline void vmathT3MakeScale( VmathTransform3 *result, const VmathVector3 *scaleVec ) +{ + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + result->col0.vec128 = vec_sel( zero, scaleVec->vec128, _VECTORMATH_MASK_0xF000 ); + result->col1.vec128 = vec_sel( zero, scaleVec->vec128, _VECTORMATH_MASK_0x0F00 ); + result->col2.vec128 = vec_sel( zero, scaleVec->vec128, _VECTORMATH_MASK_0x00F0 ); + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3AppendScale( VmathTransform3 *result, const VmathTransform3 *tfrm, const VmathVector3 *scaleVec ) +{ + vmathV3ScalarMul( &result->col0, &tfrm->col0, vmathV3GetX( scaleVec ) ); + vmathV3ScalarMul( &result->col1, &tfrm->col1, vmathV3GetY( scaleVec ) ); + vmathV3ScalarMul( &result->col2, &tfrm->col2, vmathV3GetZ( scaleVec ) ); + vmathV3Copy( &result->col3, &tfrm->col3 ); +} + +static inline void vmathT3PrependScale( VmathTransform3 *result, const VmathVector3 *scaleVec, const VmathTransform3 *tfrm ) +{ + vmathV3MulPerElem( &result->col0, &tfrm->col0, scaleVec ); + vmathV3MulPerElem( &result->col1, &tfrm->col1, scaleVec ); + vmathV3MulPerElem( &result->col2, &tfrm->col2, scaleVec ); + vmathV3MulPerElem( &result->col3, &tfrm->col3, scaleVec ); +} + +static inline void vmathT3MakeTranslation( VmathTransform3 *result, const VmathVector3 *translateVec ) +{ + vmathV3MakeXAxis( &result->col0 ); + vmathV3MakeYAxis( &result->col1 ); + vmathV3MakeZAxis( &result->col2 ); + vmathV3Copy( &result->col3, translateVec ); +} + +static inline void vmathT3Select( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1, unsigned int select1 ) +{ + vmathV3Select( &result->col0, &tfrm0->col0, &tfrm1->col0, select1 ); + vmathV3Select( &result->col1, &tfrm0->col1, &tfrm1->col1, select1 ); + vmathV3Select( &result->col2, &tfrm0->col2, &tfrm1->col2, select1 ); + vmathV3Select( &result->col3, &tfrm0->col3, &tfrm1->col3, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathT3Print( const VmathTransform3 *tfrm ) +{ + VmathVector4 tmpV4_0, tmpV4_1, tmpV4_2; + vmathT3GetRow( &tmpV4_0, tfrm, 0 ); + vmathV4Print( &tmpV4_0 ); + vmathT3GetRow( &tmpV4_1, tfrm, 1 ); + vmathV4Print( &tmpV4_1 ); + vmathT3GetRow( &tmpV4_2, tfrm, 2 ); + vmathV4Print( &tmpV4_2 ); +} + +static inline void vmathT3Prints( const VmathTransform3 *tfrm, const char *name ) +{ + printf("%s:\n", name); + vmathT3Print( tfrm ); +} + +#endif + +static inline void vmathQMakeFromM3( VmathQuat *result, const VmathMatrix3 *tfrm ) +{ + vec_float4 res; + vec_float4 col0, col1, col2; + vec_float4 xx_yy, xx_yy_zz_xx, yy_zz_xx_yy, zz_xx_yy_zz, diagSum, diagDiff; + vec_float4 zy_xz_yx, yz_zx_xy, sum, diff; + vec_float4 radicand, invSqrt, scale; + vec_float4 res0, res1, res2, res3; + vec_float4 xx, yy, zz; + vec_uint4 select_x = _VECTORMATH_MASK_0xF000; + vec_uint4 select_y = _VECTORMATH_MASK_0x0F00; + vec_uint4 select_z = _VECTORMATH_MASK_0x00F0; + vec_uint4 select_w = _VECTORMATH_MASK_0x000F; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + + col0 = tfrm->col0.vec128; + col1 = tfrm->col1.vec128; + col2 = tfrm->col2.vec128; + + /* four cases: */ + /* trace > 0 */ + /* else */ + /* xx largest diagonal element */ + /* yy largest diagonal element */ + /* zz largest diagonal element */ + + /* compute quaternion for each case */ + + xx_yy = vec_sel( col0, col1, select_y ); + xx_yy_zz_xx = vec_perm( xx_yy, col2, _VECTORMATH_PERM_XYCX ); + yy_zz_xx_yy = vec_perm( xx_yy, col2, _VECTORMATH_PERM_YCXY ); + zz_xx_yy_zz = vec_perm( xx_yy, col2, _VECTORMATH_PERM_CXYC ); + + diagSum = vec_add( vec_add( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); + diagDiff = vec_sub( vec_sub( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); + radicand = vec_add( vec_sel( diagDiff, diagSum, select_w ), ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); + invSqrt = rsqrtf4( radicand ); + + zy_xz_yx = vec_sel( col0, col1, select_z ); + zy_xz_yx = vec_perm( zy_xz_yx, col2, _VECTORMATH_PERM_ZAYX ); + yz_zx_xy = vec_sel( col0, col1, select_x ); + yz_zx_xy = vec_perm( yz_zx_xy, col2, _VECTORMATH_PERM_BZXX ); + + sum = vec_add( zy_xz_yx, yz_zx_xy ); + diff = vec_sub( zy_xz_yx, yz_zx_xy ); + + scale = vec_madd( invSqrt, ((vec_float4){0.5f,0.5f,0.5f,0.5f}), zero ); + res0 = vec_perm( sum, diff, _VECTORMATH_PERM_XZYA ); + res1 = vec_perm( sum, diff, _VECTORMATH_PERM_ZXXB ); + res2 = vec_perm( sum, diff, _VECTORMATH_PERM_YXXC ); + res3 = diff; + res0 = vec_sel( res0, radicand, select_x ); + res1 = vec_sel( res1, radicand, select_y ); + res2 = vec_sel( res2, radicand, select_z ); + res3 = vec_sel( res3, radicand, select_w ); + res0 = vec_madd( res0, vec_splat( scale, 0 ), zero ); + res1 = vec_madd( res1, vec_splat( scale, 1 ), zero ); + res2 = vec_madd( res2, vec_splat( scale, 2 ), zero ); + res3 = vec_madd( res3, vec_splat( scale, 3 ), zero ); + + /* determine case and select answer */ + + xx = vec_splat( col0, 0 ); + yy = vec_splat( col1, 1 ); + zz = vec_splat( col2, 2 ); + res = vec_sel( res0, res1, vec_cmpgt( yy, xx ) ); + res = vec_sel( res, res2, vec_and( vec_cmpgt( zz, xx ), vec_cmpgt( zz, yy ) ) ); + res = vec_sel( res, res3, vec_cmpgt( vec_splat( diagSum, 0 ), zero ) ); + result->vec128 = res; +} + +static inline void vmathV3Outer( VmathMatrix3 *result, const VmathVector3 *tfrm0, const VmathVector3 *tfrm1 ) +{ + vmathV3ScalarMul( &result->col0, tfrm0, vmathV3GetX( tfrm1 ) ); + vmathV3ScalarMul( &result->col1, tfrm0, vmathV3GetY( tfrm1 ) ); + vmathV3ScalarMul( &result->col2, tfrm0, vmathV3GetZ( tfrm1 ) ); +} + +static inline void vmathV4Outer( VmathMatrix4 *result, const VmathVector4 *tfrm0, const VmathVector4 *tfrm1 ) +{ + vmathV4ScalarMul( &result->col0, tfrm0, vmathV4GetX( tfrm1 ) ); + vmathV4ScalarMul( &result->col1, tfrm0, vmathV4GetY( tfrm1 ) ); + vmathV4ScalarMul( &result->col2, tfrm0, vmathV4GetZ( tfrm1 ) ); + vmathV4ScalarMul( &result->col3, tfrm0, vmathV4GetW( tfrm1 ) ); +} + +static inline void vmathV3RowMul( VmathVector3 *result, const VmathVector3 *vec, const VmathMatrix3 *mat ) +{ + vec_float4 tmp0, tmp1, mcol0, mcol1, mcol2, res; + vec_float4 xxxx, yyyy, zzzz; + tmp0 = vec_mergeh( mat->col0.vec128, mat->col2.vec128 ); + tmp1 = vec_mergel( mat->col0.vec128, mat->col2.vec128 ); + xxxx = vec_splat( vec->vec128, 0 ); + mcol0 = vec_mergeh( tmp0, mat->col1.vec128 ); + mcol1 = vec_perm( tmp0, mat->col1.vec128, _VECTORMATH_PERM_ZBWX ); + mcol2 = vec_perm( tmp1, mat->col1.vec128, _VECTORMATH_PERM_XCYX ); + yyyy = vec_splat( vec->vec128, 1 ); + res = vec_madd( mcol0, xxxx, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + zzzz = vec_splat( vec->vec128, 2 ); + res = vec_madd( mcol1, yyyy, res ); + res = vec_madd( mcol2, zzzz, res ); + result->vec128 = res; +} + +static inline void vmathV3CrossMatrix( VmathMatrix3 *result, const VmathVector3 *vec ) +{ + vec_float4 neg, res0, res1, res2; + neg = negatef4( vec->vec128 ); + res0 = vec_perm( vec->vec128, neg, _VECTORMATH_PERM_XZBX ); + res1 = vec_perm( vec->vec128, neg, _VECTORMATH_PERM_CXXX ); + res2 = vec_perm( vec->vec128, neg, _VECTORMATH_PERM_YAXX ); + res0 = vec_andc( res0, (vec_float4)_VECTORMATH_MASK_0xF000 ); + res1 = vec_andc( res1, (vec_float4)_VECTORMATH_MASK_0x0F00 ); + res2 = vec_andc( res2, (vec_float4)_VECTORMATH_MASK_0x00F0 ); + result->col0.vec128 = res0; + result->col1.vec128 = res1; + result->col2.vec128 = res2; +} + +static inline void vmathV3CrossMatrixMul( VmathMatrix3 *result, const VmathVector3 *vec, const VmathMatrix3 *mat ) +{ + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2; + vmathV3Cross( &tmpV3_0, vec, &mat->col0 ); + vmathV3Cross( &tmpV3_1, vec, &mat->col1 ); + vmathV3Cross( &tmpV3_2, vec, &mat->col2 ); + vmathM3MakeFromCols( result, &tmpV3_0, &tmpV3_1, &tmpV3_2 ); +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/mat_aos_v.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/mat_aos_v.h new file mode 100644 index 0000000..47c683a --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/mat_aos_v.h @@ -0,0 +1,1026 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_AOS_V_C_H +#define _VECTORMATH_MAT_AOS_V_C_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + * for shuffles, words are labeled [x,y,z,w] [a,b,c,d] + */ +#define _VECTORMATH_PERM_ZBWX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XCYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_C, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XYAB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_ZWCD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W, _VECTORMATH_PERM_C, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_XZBX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_CXXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_YAXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XAZC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_YXWZ ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W, _VECTORMATH_PERM_Z }) +#define _VECTORMATH_PERM_YBWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_XYCX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_YCXY ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y }) +#define _VECTORMATH_PERM_CXYC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_ZAYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_BZXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_B, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XZYA ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A }) +#define _VECTORMATH_PERM_ZXXB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_YXXC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_BBYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_B, _VECTORMATH_PERM_B, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PI_OVER_2 1.570796327f + +/*----------------------------------------------------------------------------- + * Definitions + */ +static inline VmathMatrix3 vmathM3MakeFromScalar_V( float scalar ) +{ + VmathMatrix3 result; + vmathM3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathMatrix3 vmathM3MakeFromQ_V( VmathQuat unitQuat ) +{ + VmathMatrix3 result; + vmathM3MakeFromQ(&result, &unitQuat); + return result; +} + +static inline VmathMatrix3 vmathM3MakeFromCols_V( VmathVector3 _col0, VmathVector3 _col1, VmathVector3 _col2 ) +{ + VmathMatrix3 result; + vmathM3MakeFromCols(&result, &_col0, &_col1, &_col2); + return result; +} + +static inline void vmathM3SetCol0_V( VmathMatrix3 *result, VmathVector3 _col0 ) +{ + vmathM3SetCol0(result, &_col0); +} + +static inline void vmathM3SetCol1_V( VmathMatrix3 *result, VmathVector3 _col1 ) +{ + vmathM3SetCol1(result, &_col1); +} + +static inline void vmathM3SetCol2_V( VmathMatrix3 *result, VmathVector3 _col2 ) +{ + vmathM3SetCol2(result, &_col2); +} + +static inline void vmathM3SetCol_V( VmathMatrix3 *result, int col, VmathVector3 vec ) +{ + vmathM3SetCol(result, col, &vec); +} + +static inline void vmathM3SetRow_V( VmathMatrix3 *result, int row, VmathVector3 vec ) +{ + vmathM3SetRow(result, row, &vec); +} + +static inline void vmathM3SetElem_V( VmathMatrix3 *result, int col, int row, float val ) +{ + vmathM3SetElem(result, col, row, val); +} + +static inline float vmathM3GetElem_V( VmathMatrix3 mat, int col, int row ) +{ + return vmathM3GetElem(&mat, col, row); +} + +static inline VmathVector3 vmathM3GetCol0_V( VmathMatrix3 mat ) +{ + VmathVector3 result; + vmathM3GetCol0(&result, &mat); + return result; +} + +static inline VmathVector3 vmathM3GetCol1_V( VmathMatrix3 mat ) +{ + VmathVector3 result; + vmathM3GetCol1(&result, &mat); + return result; +} + +static inline VmathVector3 vmathM3GetCol2_V( VmathMatrix3 mat ) +{ + VmathVector3 result; + vmathM3GetCol2(&result, &mat); + return result; +} + +static inline VmathVector3 vmathM3GetCol_V( VmathMatrix3 mat, int col ) +{ + VmathVector3 result; + vmathM3GetCol(&result, &mat, col); + return result; +} + +static inline VmathVector3 vmathM3GetRow_V( VmathMatrix3 mat, int row ) +{ + VmathVector3 result; + vmathM3GetRow(&result, &mat, row); + return result; +} + +static inline VmathMatrix3 vmathM3Transpose_V( VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathM3Transpose(&result, &mat); + return result; +} + +static inline VmathMatrix3 vmathM3Inverse_V( VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathM3Inverse(&result, &mat); + return result; +} + +static inline float vmathM3Determinant_V( VmathMatrix3 mat ) +{ + return vmathM3Determinant(&mat); +} + +static inline VmathMatrix3 vmathM3Add_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ) +{ + VmathMatrix3 result; + vmathM3Add(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix3 vmathM3Sub_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ) +{ + VmathMatrix3 result; + vmathM3Sub(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix3 vmathM3Neg_V( VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathM3Neg(&result, &mat); + return result; +} + +static inline VmathMatrix3 vmathM3AbsPerElem_V( VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathM3AbsPerElem(&result, &mat); + return result; +} + +static inline VmathMatrix3 vmathM3ScalarMul_V( VmathMatrix3 mat, float scalar ) +{ + VmathMatrix3 result; + vmathM3ScalarMul(&result, &mat, scalar); + return result; +} + +static inline VmathVector3 vmathM3MulV3_V( VmathMatrix3 mat, VmathVector3 vec ) +{ + VmathVector3 result; + vmathM3MulV3(&result, &mat, &vec); + return result; +} + +static inline VmathMatrix3 vmathM3Mul_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ) +{ + VmathMatrix3 result; + vmathM3Mul(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix3 vmathM3MulPerElem_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ) +{ + VmathMatrix3 result; + vmathM3MulPerElem(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix3 vmathM3MakeIdentity_V( ) +{ + VmathMatrix3 result; + vmathM3MakeIdentity(&result); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationX_V( float radians ) +{ + VmathMatrix3 result; + vmathM3MakeRotationX(&result, radians); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationY_V( float radians ) +{ + VmathMatrix3 result; + vmathM3MakeRotationY(&result, radians); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationZ_V( float radians ) +{ + VmathMatrix3 result; + vmathM3MakeRotationZ(&result, radians); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationZYX_V( VmathVector3 radiansXYZ ) +{ + VmathMatrix3 result; + vmathM3MakeRotationZYX(&result, &radiansXYZ); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationAxis_V( float radians, VmathVector3 unitVec ) +{ + VmathMatrix3 result; + vmathM3MakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationQ_V( VmathQuat unitQuat ) +{ + VmathMatrix3 result; + vmathM3MakeRotationQ(&result, &unitQuat); + return result; +} + +static inline VmathMatrix3 vmathM3MakeScale_V( VmathVector3 scaleVec ) +{ + VmathMatrix3 result; + vmathM3MakeScale(&result, &scaleVec); + return result; +} + +static inline VmathMatrix3 vmathM3AppendScale_V( VmathMatrix3 mat, VmathVector3 scaleVec ) +{ + VmathMatrix3 result; + vmathM3AppendScale(&result, &mat, &scaleVec); + return result; +} + +static inline VmathMatrix3 vmathM3PrependScale_V( VmathVector3 scaleVec, VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathM3PrependScale(&result, &scaleVec, &mat); + return result; +} + +static inline VmathMatrix3 vmathM3Select_V( VmathMatrix3 mat0, VmathMatrix3 mat1, unsigned int select1 ) +{ + VmathMatrix3 result; + vmathM3Select(&result, &mat0, &mat1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathM3Print_V( VmathMatrix3 mat ) +{ + vmathM3Print(&mat); +} + +static inline void vmathM3Prints_V( VmathMatrix3 mat, const char *name ) +{ + vmathM3Prints(&mat, name); +} + +#endif + +static inline VmathMatrix4 vmathM4MakeFromScalar_V( float scalar ) +{ + VmathMatrix4 result; + vmathM4MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathMatrix4 vmathM4MakeFromT3_V( VmathTransform3 mat ) +{ + VmathMatrix4 result; + vmathM4MakeFromT3(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4MakeFromCols_V( VmathVector4 _col0, VmathVector4 _col1, VmathVector4 _col2, VmathVector4 _col3 ) +{ + VmathMatrix4 result; + vmathM4MakeFromCols(&result, &_col0, &_col1, &_col2, &_col3); + return result; +} + +static inline VmathMatrix4 vmathM4MakeFromM3V3_V( VmathMatrix3 mat, VmathVector3 translateVec ) +{ + VmathMatrix4 result; + vmathM4MakeFromM3V3(&result, &mat, &translateVec); + return result; +} + +static inline VmathMatrix4 vmathM4MakeFromQV3_V( VmathQuat unitQuat, VmathVector3 translateVec ) +{ + VmathMatrix4 result; + vmathM4MakeFromQV3(&result, &unitQuat, &translateVec); + return result; +} + +static inline void vmathM4SetCol0_V( VmathMatrix4 *result, VmathVector4 _col0 ) +{ + vmathM4SetCol0(result, &_col0); +} + +static inline void vmathM4SetCol1_V( VmathMatrix4 *result, VmathVector4 _col1 ) +{ + vmathM4SetCol1(result, &_col1); +} + +static inline void vmathM4SetCol2_V( VmathMatrix4 *result, VmathVector4 _col2 ) +{ + vmathM4SetCol2(result, &_col2); +} + +static inline void vmathM4SetCol3_V( VmathMatrix4 *result, VmathVector4 _col3 ) +{ + vmathM4SetCol3(result, &_col3); +} + +static inline void vmathM4SetCol_V( VmathMatrix4 *result, int col, VmathVector4 vec ) +{ + vmathM4SetCol(result, col, &vec); +} + +static inline void vmathM4SetRow_V( VmathMatrix4 *result, int row, VmathVector4 vec ) +{ + vmathM4SetRow(result, row, &vec); +} + +static inline void vmathM4SetElem_V( VmathMatrix4 *result, int col, int row, float val ) +{ + vmathM4SetElem(result, col, row, val); +} + +static inline float vmathM4GetElem_V( VmathMatrix4 mat, int col, int row ) +{ + return vmathM4GetElem(&mat, col, row); +} + +static inline VmathVector4 vmathM4GetCol0_V( VmathMatrix4 mat ) +{ + VmathVector4 result; + vmathM4GetCol0(&result, &mat); + return result; +} + +static inline VmathVector4 vmathM4GetCol1_V( VmathMatrix4 mat ) +{ + VmathVector4 result; + vmathM4GetCol1(&result, &mat); + return result; +} + +static inline VmathVector4 vmathM4GetCol2_V( VmathMatrix4 mat ) +{ + VmathVector4 result; + vmathM4GetCol2(&result, &mat); + return result; +} + +static inline VmathVector4 vmathM4GetCol3_V( VmathMatrix4 mat ) +{ + VmathVector4 result; + vmathM4GetCol3(&result, &mat); + return result; +} + +static inline VmathVector4 vmathM4GetCol_V( VmathMatrix4 mat, int col ) +{ + VmathVector4 result; + vmathM4GetCol(&result, &mat, col); + return result; +} + +static inline VmathVector4 vmathM4GetRow_V( VmathMatrix4 mat, int row ) +{ + VmathVector4 result; + vmathM4GetRow(&result, &mat, row); + return result; +} + +static inline VmathMatrix4 vmathM4Transpose_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4Transpose(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4Inverse_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4Inverse(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4AffineInverse_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4AffineInverse(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4OrthoInverse_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4OrthoInverse(&result, &mat); + return result; +} + +static inline float vmathM4Determinant_V( VmathMatrix4 mat ) +{ + return vmathM4Determinant(&mat); +} + +static inline VmathMatrix4 vmathM4Add_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ) +{ + VmathMatrix4 result; + vmathM4Add(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix4 vmathM4Sub_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ) +{ + VmathMatrix4 result; + vmathM4Sub(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix4 vmathM4Neg_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4Neg(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4AbsPerElem_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4AbsPerElem(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4ScalarMul_V( VmathMatrix4 mat, float scalar ) +{ + VmathMatrix4 result; + vmathM4ScalarMul(&result, &mat, scalar); + return result; +} + +static inline VmathVector4 vmathM4MulV4_V( VmathMatrix4 mat, VmathVector4 vec ) +{ + VmathVector4 result; + vmathM4MulV4(&result, &mat, &vec); + return result; +} + +static inline VmathVector4 vmathM4MulV3_V( VmathMatrix4 mat, VmathVector3 vec ) +{ + VmathVector4 result; + vmathM4MulV3(&result, &mat, &vec); + return result; +} + +static inline VmathVector4 vmathM4MulP3_V( VmathMatrix4 mat, VmathPoint3 pnt ) +{ + VmathVector4 result; + vmathM4MulP3(&result, &mat, &pnt); + return result; +} + +static inline VmathMatrix4 vmathM4Mul_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ) +{ + VmathMatrix4 result; + vmathM4Mul(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix4 vmathM4MulT3_V( VmathMatrix4 mat, VmathTransform3 tfrm1 ) +{ + VmathMatrix4 result; + vmathM4MulT3(&result, &mat, &tfrm1); + return result; +} + +static inline VmathMatrix4 vmathM4MulPerElem_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ) +{ + VmathMatrix4 result; + vmathM4MulPerElem(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix4 vmathM4MakeIdentity_V( ) +{ + VmathMatrix4 result; + vmathM4MakeIdentity(&result); + return result; +} + +static inline void vmathM4SetUpper3x3_V( VmathMatrix4 *result, VmathMatrix3 mat3 ) +{ + vmathM4SetUpper3x3(result, &mat3); +} + +static inline VmathMatrix3 vmathM4GetUpper3x3_V( VmathMatrix4 mat ) +{ + VmathMatrix3 result; + vmathM4GetUpper3x3(&result, &mat); + return result; +} + +static inline void vmathM4SetTranslation_V( VmathMatrix4 *result, VmathVector3 translateVec ) +{ + vmathM4SetTranslation(result, &translateVec); +} + +static inline VmathVector3 vmathM4GetTranslation_V( VmathMatrix4 mat ) +{ + VmathVector3 result; + vmathM4GetTranslation(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationX_V( float radians ) +{ + VmathMatrix4 result; + vmathM4MakeRotationX(&result, radians); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationY_V( float radians ) +{ + VmathMatrix4 result; + vmathM4MakeRotationY(&result, radians); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationZ_V( float radians ) +{ + VmathMatrix4 result; + vmathM4MakeRotationZ(&result, radians); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationZYX_V( VmathVector3 radiansXYZ ) +{ + VmathMatrix4 result; + vmathM4MakeRotationZYX(&result, &radiansXYZ); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationAxis_V( float radians, VmathVector3 unitVec ) +{ + VmathMatrix4 result; + vmathM4MakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationQ_V( VmathQuat unitQuat ) +{ + VmathMatrix4 result; + vmathM4MakeRotationQ(&result, &unitQuat); + return result; +} + +static inline VmathMatrix4 vmathM4MakeScale_V( VmathVector3 scaleVec ) +{ + VmathMatrix4 result; + vmathM4MakeScale(&result, &scaleVec); + return result; +} + +static inline VmathMatrix4 vmathM4AppendScale_V( VmathMatrix4 mat, VmathVector3 scaleVec ) +{ + VmathMatrix4 result; + vmathM4AppendScale(&result, &mat, &scaleVec); + return result; +} + +static inline VmathMatrix4 vmathM4PrependScale_V( VmathVector3 scaleVec, VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4PrependScale(&result, &scaleVec, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4MakeTranslation_V( VmathVector3 translateVec ) +{ + VmathMatrix4 result; + vmathM4MakeTranslation(&result, &translateVec); + return result; +} + +static inline VmathMatrix4 vmathM4MakeLookAt_V( VmathPoint3 eyePos, VmathPoint3 lookAtPos, VmathVector3 upVec ) +{ + VmathMatrix4 result; + vmathM4MakeLookAt(&result, &eyePos, &lookAtPos, &upVec); + return result; +} + +static inline VmathMatrix4 vmathM4MakePerspective_V( float fovyRadians, float aspect, float zNear, float zFar ) +{ + VmathMatrix4 result; + vmathM4MakePerspective(&result, fovyRadians, aspect, zNear, zFar); + return result; +} + +static inline VmathMatrix4 vmathM4MakeFrustum_V( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + VmathMatrix4 result; + vmathM4MakeFrustum(&result, left, right, bottom, top, zNear, zFar); + return result; +} + +static inline VmathMatrix4 vmathM4MakeOrthographic_V( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + VmathMatrix4 result; + vmathM4MakeOrthographic(&result, left, right, bottom, top, zNear, zFar); + return result; +} + +static inline VmathMatrix4 vmathM4Select_V( VmathMatrix4 mat0, VmathMatrix4 mat1, unsigned int select1 ) +{ + VmathMatrix4 result; + vmathM4Select(&result, &mat0, &mat1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathM4Print_V( VmathMatrix4 mat ) +{ + vmathM4Print(&mat); +} + +static inline void vmathM4Prints_V( VmathMatrix4 mat, const char *name ) +{ + vmathM4Prints(&mat, name); +} + +#endif + +static inline VmathTransform3 vmathT3MakeFromScalar_V( float scalar ) +{ + VmathTransform3 result; + vmathT3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathTransform3 vmathT3MakeFromCols_V( VmathVector3 _col0, VmathVector3 _col1, VmathVector3 _col2, VmathVector3 _col3 ) +{ + VmathTransform3 result; + vmathT3MakeFromCols(&result, &_col0, &_col1, &_col2, &_col3); + return result; +} + +static inline VmathTransform3 vmathT3MakeFromM3V3_V( VmathMatrix3 tfrm, VmathVector3 translateVec ) +{ + VmathTransform3 result; + vmathT3MakeFromM3V3(&result, &tfrm, &translateVec); + return result; +} + +static inline VmathTransform3 vmathT3MakeFromQV3_V( VmathQuat unitQuat, VmathVector3 translateVec ) +{ + VmathTransform3 result; + vmathT3MakeFromQV3(&result, &unitQuat, &translateVec); + return result; +} + +static inline void vmathT3SetCol0_V( VmathTransform3 *result, VmathVector3 _col0 ) +{ + vmathT3SetCol0(result, &_col0); +} + +static inline void vmathT3SetCol1_V( VmathTransform3 *result, VmathVector3 _col1 ) +{ + vmathT3SetCol1(result, &_col1); +} + +static inline void vmathT3SetCol2_V( VmathTransform3 *result, VmathVector3 _col2 ) +{ + vmathT3SetCol2(result, &_col2); +} + +static inline void vmathT3SetCol3_V( VmathTransform3 *result, VmathVector3 _col3 ) +{ + vmathT3SetCol3(result, &_col3); +} + +static inline void vmathT3SetCol_V( VmathTransform3 *result, int col, VmathVector3 vec ) +{ + vmathT3SetCol(result, col, &vec); +} + +static inline void vmathT3SetRow_V( VmathTransform3 *result, int row, VmathVector4 vec ) +{ + vmathT3SetRow(result, row, &vec); +} + +static inline void vmathT3SetElem_V( VmathTransform3 *result, int col, int row, float val ) +{ + vmathT3SetElem(result, col, row, val); +} + +static inline float vmathT3GetElem_V( VmathTransform3 tfrm, int col, int row ) +{ + return vmathT3GetElem(&tfrm, col, row); +} + +static inline VmathVector3 vmathT3GetCol0_V( VmathTransform3 tfrm ) +{ + VmathVector3 result; + vmathT3GetCol0(&result, &tfrm); + return result; +} + +static inline VmathVector3 vmathT3GetCol1_V( VmathTransform3 tfrm ) +{ + VmathVector3 result; + vmathT3GetCol1(&result, &tfrm); + return result; +} + +static inline VmathVector3 vmathT3GetCol2_V( VmathTransform3 tfrm ) +{ + VmathVector3 result; + vmathT3GetCol2(&result, &tfrm); + return result; +} + +static inline VmathVector3 vmathT3GetCol3_V( VmathTransform3 tfrm ) +{ + VmathVector3 result; + vmathT3GetCol3(&result, &tfrm); + return result; +} + +static inline VmathVector3 vmathT3GetCol_V( VmathTransform3 tfrm, int col ) +{ + VmathVector3 result; + vmathT3GetCol(&result, &tfrm, col); + return result; +} + +static inline VmathVector4 vmathT3GetRow_V( VmathTransform3 tfrm, int row ) +{ + VmathVector4 result; + vmathT3GetRow(&result, &tfrm, row); + return result; +} + +static inline VmathTransform3 vmathT3Inverse_V( VmathTransform3 tfrm ) +{ + VmathTransform3 result; + vmathT3Inverse(&result, &tfrm); + return result; +} + +static inline VmathTransform3 vmathT3OrthoInverse_V( VmathTransform3 tfrm ) +{ + VmathTransform3 result; + vmathT3OrthoInverse(&result, &tfrm); + return result; +} + +static inline VmathTransform3 vmathT3AbsPerElem_V( VmathTransform3 tfrm ) +{ + VmathTransform3 result; + vmathT3AbsPerElem(&result, &tfrm); + return result; +} + +static inline VmathVector3 vmathT3MulV3_V( VmathTransform3 tfrm, VmathVector3 vec ) +{ + VmathVector3 result; + vmathT3MulV3(&result, &tfrm, &vec); + return result; +} + +static inline VmathPoint3 vmathT3MulP3_V( VmathTransform3 tfrm, VmathPoint3 pnt ) +{ + VmathPoint3 result; + vmathT3MulP3(&result, &tfrm, &pnt); + return result; +} + +static inline VmathTransform3 vmathT3Mul_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1 ) +{ + VmathTransform3 result; + vmathT3Mul(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathTransform3 vmathT3MulPerElem_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1 ) +{ + VmathTransform3 result; + vmathT3MulPerElem(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathTransform3 vmathT3MakeIdentity_V( ) +{ + VmathTransform3 result; + vmathT3MakeIdentity(&result); + return result; +} + +static inline void vmathT3SetUpper3x3_V( VmathTransform3 *result, VmathMatrix3 tfrm ) +{ + vmathT3SetUpper3x3(result, &tfrm); +} + +static inline VmathMatrix3 vmathT3GetUpper3x3_V( VmathTransform3 tfrm ) +{ + VmathMatrix3 result; + vmathT3GetUpper3x3(&result, &tfrm); + return result; +} + +static inline void vmathT3SetTranslation_V( VmathTransform3 *result, VmathVector3 translateVec ) +{ + vmathT3SetTranslation(result, &translateVec); +} + +static inline VmathVector3 vmathT3GetTranslation_V( VmathTransform3 tfrm ) +{ + VmathVector3 result; + vmathT3GetTranslation(&result, &tfrm); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationX_V( float radians ) +{ + VmathTransform3 result; + vmathT3MakeRotationX(&result, radians); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationY_V( float radians ) +{ + VmathTransform3 result; + vmathT3MakeRotationY(&result, radians); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationZ_V( float radians ) +{ + VmathTransform3 result; + vmathT3MakeRotationZ(&result, radians); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationZYX_V( VmathVector3 radiansXYZ ) +{ + VmathTransform3 result; + vmathT3MakeRotationZYX(&result, &radiansXYZ); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationAxis_V( float radians, VmathVector3 unitVec ) +{ + VmathTransform3 result; + vmathT3MakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationQ_V( VmathQuat unitQuat ) +{ + VmathTransform3 result; + vmathT3MakeRotationQ(&result, &unitQuat); + return result; +} + +static inline VmathTransform3 vmathT3MakeScale_V( VmathVector3 scaleVec ) +{ + VmathTransform3 result; + vmathT3MakeScale(&result, &scaleVec); + return result; +} + +static inline VmathTransform3 vmathT3AppendScale_V( VmathTransform3 tfrm, VmathVector3 scaleVec ) +{ + VmathTransform3 result; + vmathT3AppendScale(&result, &tfrm, &scaleVec); + return result; +} + +static inline VmathTransform3 vmathT3PrependScale_V( VmathVector3 scaleVec, VmathTransform3 tfrm ) +{ + VmathTransform3 result; + vmathT3PrependScale(&result, &scaleVec, &tfrm); + return result; +} + +static inline VmathTransform3 vmathT3MakeTranslation_V( VmathVector3 translateVec ) +{ + VmathTransform3 result; + vmathT3MakeTranslation(&result, &translateVec); + return result; +} + +static inline VmathTransform3 vmathT3Select_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1, unsigned int select1 ) +{ + VmathTransform3 result; + vmathT3Select(&result, &tfrm0, &tfrm1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathT3Print_V( VmathTransform3 tfrm ) +{ + vmathT3Print(&tfrm); +} + +static inline void vmathT3Prints_V( VmathTransform3 tfrm, const char *name ) +{ + vmathT3Prints(&tfrm, name); +} + +#endif + +static inline VmathQuat vmathQMakeFromM3_V( VmathMatrix3 tfrm ) +{ + VmathQuat result; + vmathQMakeFromM3(&result, &tfrm); + return result; +} + +static inline VmathMatrix3 vmathV3Outer_V( VmathVector3 tfrm0, VmathVector3 tfrm1 ) +{ + VmathMatrix3 result; + vmathV3Outer(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathMatrix4 vmathV4Outer_V( VmathVector4 tfrm0, VmathVector4 tfrm1 ) +{ + VmathMatrix4 result; + vmathV4Outer(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathVector3 vmathV3RowMul_V( VmathVector3 vec, VmathMatrix3 mat ) +{ + VmathVector3 result; + vmathV3RowMul(&result, &vec, &mat); + return result; +} + +static inline VmathMatrix3 vmathV3CrossMatrix_V( VmathVector3 vec ) +{ + VmathMatrix3 result; + vmathV3CrossMatrix(&result, &vec); + return result; +} + +static inline VmathMatrix3 vmathV3CrossMatrixMul_V( VmathVector3 vec, VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathV3CrossMatrixMul(&result, &vec, &mat); + return result; +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/mat_soa.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/mat_soa.h new file mode 100644 index 0000000..3b673c4 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/mat_soa.h @@ -0,0 +1,1493 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_SOA_C_H +#define _VECTORMATH_MAT_SOA_C_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + */ +#define _VECTORMATH_PI_OVER_2 1.570796327f + +/*----------------------------------------------------------------------------- + * Definitions + */ +static inline void vmathSoaM3Copy( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ) +{ + vmathSoaV3Copy( &result->col0, &mat->col0 ); + vmathSoaV3Copy( &result->col1, &mat->col1 ); + vmathSoaV3Copy( &result->col2, &mat->col2 ); +} + +static inline void vmathSoaM3MakeFromScalar( VmathSoaMatrix3 *result, vec_float4 scalar ) +{ + vmathSoaV3MakeFromScalar( &result->col0, scalar ); + vmathSoaV3MakeFromScalar( &result->col1, scalar ); + vmathSoaV3MakeFromScalar( &result->col2, scalar ); +} + +static inline void vmathSoaM3MakeFromQ( VmathSoaMatrix3 *result, const VmathSoaQuat *unitQuat ) +{ + vec_float4 qx, qy, qz, qw, qx2, qy2, qz2, qxqx2, qyqy2, qzqz2, qxqy2, qyqz2, qzqw2, qxqz2, qyqw2, qxqw2; + qx = unitQuat->x; + qy = unitQuat->y; + qz = unitQuat->z; + qw = unitQuat->w; + qx2 = vec_add( qx, qx ); + qy2 = vec_add( qy, qy ); + qz2 = vec_add( qz, qz ); + qxqx2 = vec_madd( qx, qx2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qxqy2 = vec_madd( qx, qy2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qxqz2 = vec_madd( qx, qz2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qxqw2 = vec_madd( qw, qx2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qyqy2 = vec_madd( qy, qy2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qyqz2 = vec_madd( qy, qz2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qyqw2 = vec_madd( qw, qy2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qzqz2 = vec_madd( qz, qz2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qzqw2 = vec_madd( qw, qz2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV3MakeFromElems( &result->col0, vec_sub( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), qyqy2 ), qzqz2 ), vec_add( qxqy2, qzqw2 ), vec_sub( qxqz2, qyqw2 ) ); + vmathSoaV3MakeFromElems( &result->col1, vec_sub( qxqy2, qzqw2 ), vec_sub( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), qxqx2 ), qzqz2 ), vec_add( qyqz2, qxqw2 ) ); + vmathSoaV3MakeFromElems( &result->col2, vec_add( qxqz2, qyqw2 ), vec_sub( qyqz2, qxqw2 ), vec_sub( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), qxqx2 ), qyqy2 ) ); +} + +static inline void vmathSoaM3MakeFromCols( VmathSoaMatrix3 *result, const VmathSoaVector3 *_col0, const VmathSoaVector3 *_col1, const VmathSoaVector3 *_col2 ) +{ + vmathSoaV3Copy( &result->col0, _col0 ); + vmathSoaV3Copy( &result->col1, _col1 ); + vmathSoaV3Copy( &result->col2, _col2 ); +} + +static inline void vmathSoaM3MakeFromAos( VmathSoaMatrix3 *result, const VmathMatrix3 *mat ) +{ + vmathSoaV3MakeFromAos( &result->col0, &mat->col0 ); + vmathSoaV3MakeFromAos( &result->col1, &mat->col1 ); + vmathSoaV3MakeFromAos( &result->col2, &mat->col2 ); +} + +static inline void vmathSoaM3MakeFrom4Aos( VmathSoaMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1, const VmathMatrix3 *mat2, const VmathMatrix3 *mat3 ) +{ + vmathSoaV3MakeFrom4Aos( &result->col0, &mat0->col0, &mat1->col0, &mat2->col0, &mat3->col0 ); + vmathSoaV3MakeFrom4Aos( &result->col1, &mat0->col1, &mat1->col1, &mat2->col1, &mat3->col1 ); + vmathSoaV3MakeFrom4Aos( &result->col2, &mat0->col2, &mat1->col2, &mat2->col2, &mat3->col2 ); +} + +static inline void vmathSoaM3Get4Aos( const VmathSoaMatrix3 *mat, VmathMatrix3 *result0, VmathMatrix3 *result1, VmathMatrix3 *result2, VmathMatrix3 *result3 ) +{ + vmathSoaV3Get4Aos( &mat->col0, &result0->col0, &result1->col0, &result2->col0, &result3->col0 ); + vmathSoaV3Get4Aos( &mat->col1, &result0->col1, &result1->col1, &result2->col1, &result3->col1 ); + vmathSoaV3Get4Aos( &mat->col2, &result0->col2, &result1->col2, &result2->col2, &result3->col2 ); +} + +static inline void vmathSoaM3SetCol0( VmathSoaMatrix3 *result, const VmathSoaVector3 *_col0 ) +{ + vmathSoaV3Copy( &result->col0, _col0 ); +} + +static inline void vmathSoaM3SetCol1( VmathSoaMatrix3 *result, const VmathSoaVector3 *_col1 ) +{ + vmathSoaV3Copy( &result->col1, _col1 ); +} + +static inline void vmathSoaM3SetCol2( VmathSoaMatrix3 *result, const VmathSoaVector3 *_col2 ) +{ + vmathSoaV3Copy( &result->col2, _col2 ); +} + +static inline void vmathSoaM3SetCol( VmathSoaMatrix3 *result, int col, const VmathSoaVector3 *vec ) +{ + vmathSoaV3Copy( (&result->col0 + col), vec ); +} + +static inline void vmathSoaM3SetRow( VmathSoaMatrix3 *result, int row, const VmathSoaVector3 *vec ) +{ + vmathSoaV3SetElem( &result->col0, row, vmathSoaV3GetElem( vec, 0 ) ); + vmathSoaV3SetElem( &result->col1, row, vmathSoaV3GetElem( vec, 1 ) ); + vmathSoaV3SetElem( &result->col2, row, vmathSoaV3GetElem( vec, 2 ) ); +} + +static inline void vmathSoaM3SetElem( VmathSoaMatrix3 *result, int col, int row, vec_float4 val ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaM3GetCol( &tmpV3_0, result, col ); + vmathSoaV3SetElem( &tmpV3_0, row, val ); + vmathSoaM3SetCol( result, col, &tmpV3_0 ); +} + +static inline vec_float4 vmathSoaM3GetElem( const VmathSoaMatrix3 *mat, int col, int row ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaM3GetCol( &tmpV3_0, mat, col ); + return vmathSoaV3GetElem( &tmpV3_0, row ); +} + +static inline void vmathSoaM3GetCol0( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat ) +{ + vmathSoaV3Copy( result, &mat->col0 ); +} + +static inline void vmathSoaM3GetCol1( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat ) +{ + vmathSoaV3Copy( result, &mat->col1 ); +} + +static inline void vmathSoaM3GetCol2( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat ) +{ + vmathSoaV3Copy( result, &mat->col2 ); +} + +static inline void vmathSoaM3GetCol( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat, int col ) +{ + vmathSoaV3Copy( result, (&mat->col0 + col) ); +} + +static inline void vmathSoaM3GetRow( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat, int row ) +{ + vmathSoaV3MakeFromElems( result, vmathSoaV3GetElem( &mat->col0, row ), vmathSoaV3GetElem( &mat->col1, row ), vmathSoaV3GetElem( &mat->col2, row ) ); +} + +static inline void vmathSoaM3Transpose( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ) +{ + VmathSoaMatrix3 tmpResult; + vmathSoaV3MakeFromElems( &tmpResult.col0, mat->col0.x, mat->col1.x, mat->col2.x ); + vmathSoaV3MakeFromElems( &tmpResult.col1, mat->col0.y, mat->col1.y, mat->col2.y ); + vmathSoaV3MakeFromElems( &tmpResult.col2, mat->col0.z, mat->col1.z, mat->col2.z ); + vmathSoaM3Copy( result, &tmpResult ); +} + +static inline void vmathSoaM3Inverse( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ) +{ + VmathSoaVector3 tmp0, tmp1, tmp2; + vec_float4 detinv; + vmathSoaV3Cross( &tmp0, &mat->col1, &mat->col2 ); + vmathSoaV3Cross( &tmp1, &mat->col2, &mat->col0 ); + vmathSoaV3Cross( &tmp2, &mat->col0, &mat->col1 ); + detinv = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vmathSoaV3Dot( &mat->col2, &tmp2 ) ); + vmathSoaV3MakeFromElems( &result->col0, vec_madd( tmp0.x, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp1.x, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp2.x, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV3MakeFromElems( &result->col1, vec_madd( tmp0.y, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp1.y, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp2.y, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV3MakeFromElems( &result->col2, vec_madd( tmp0.z, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp1.z, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp2.z, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +static inline vec_float4 vmathSoaM3Determinant( const VmathSoaMatrix3 *mat ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaV3Cross( &tmpV3_0, &mat->col0, &mat->col1 ); + return vmathSoaV3Dot( &mat->col2, &tmpV3_0 ); +} + +static inline void vmathSoaM3Add( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 ) +{ + vmathSoaV3Add( &result->col0, &mat0->col0, &mat1->col0 ); + vmathSoaV3Add( &result->col1, &mat0->col1, &mat1->col1 ); + vmathSoaV3Add( &result->col2, &mat0->col2, &mat1->col2 ); +} + +static inline void vmathSoaM3Sub( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 ) +{ + vmathSoaV3Sub( &result->col0, &mat0->col0, &mat1->col0 ); + vmathSoaV3Sub( &result->col1, &mat0->col1, &mat1->col1 ); + vmathSoaV3Sub( &result->col2, &mat0->col2, &mat1->col2 ); +} + +static inline void vmathSoaM3Neg( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ) +{ + vmathSoaV3Neg( &result->col0, &mat->col0 ); + vmathSoaV3Neg( &result->col1, &mat->col1 ); + vmathSoaV3Neg( &result->col2, &mat->col2 ); +} + +static inline void vmathSoaM3AbsPerElem( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ) +{ + vmathSoaV3AbsPerElem( &result->col0, &mat->col0 ); + vmathSoaV3AbsPerElem( &result->col1, &mat->col1 ); + vmathSoaV3AbsPerElem( &result->col2, &mat->col2 ); +} + +static inline void vmathSoaM3ScalarMul( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat, vec_float4 scalar ) +{ + vmathSoaV3ScalarMul( &result->col0, &mat->col0, scalar ); + vmathSoaV3ScalarMul( &result->col1, &mat->col1, scalar ); + vmathSoaV3ScalarMul( &result->col2, &mat->col2, scalar ); +} + +static inline void vmathSoaM3MulV3( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat, const VmathSoaVector3 *vec ) +{ + vec_float4 tmpX, tmpY, tmpZ; + tmpX = vec_add( vec_add( vec_madd( mat->col0.x, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mat->col1.x, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col2.x, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpY = vec_add( vec_add( vec_madd( mat->col0.y, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mat->col1.y, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col2.y, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpZ = vec_add( vec_add( vec_madd( mat->col0.z, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mat->col1.z, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col2.z, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV3MakeFromElems( result, tmpX, tmpY, tmpZ ); +} + +static inline void vmathSoaM3Mul( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 ) +{ + VmathSoaMatrix3 tmpResult; + vmathSoaM3MulV3( &tmpResult.col0, mat0, &mat1->col0 ); + vmathSoaM3MulV3( &tmpResult.col1, mat0, &mat1->col1 ); + vmathSoaM3MulV3( &tmpResult.col2, mat0, &mat1->col2 ); + vmathSoaM3Copy( result, &tmpResult ); +} + +static inline void vmathSoaM3MulPerElem( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 ) +{ + vmathSoaV3MulPerElem( &result->col0, &mat0->col0, &mat1->col0 ); + vmathSoaV3MulPerElem( &result->col1, &mat0->col1, &mat1->col1 ); + vmathSoaV3MulPerElem( &result->col2, &mat0->col2, &mat1->col2 ); +} + +static inline void vmathSoaM3MakeIdentity( VmathSoaMatrix3 *result ) +{ + vmathSoaV3MakeXAxis( &result->col0 ); + vmathSoaV3MakeYAxis( &result->col1 ); + vmathSoaV3MakeZAxis( &result->col2 ); +} + +static inline void vmathSoaM3MakeRotationX( VmathSoaMatrix3 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV3MakeXAxis( &result->col0 ); + vmathSoaV3MakeFromElems( &result->col1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), c, s ); + vmathSoaV3MakeFromElems( &result->col2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), negatef4( s ), c ); +} + +static inline void vmathSoaM3MakeRotationY( VmathSoaMatrix3 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV3MakeFromElems( &result->col0, c, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), negatef4( s ) ); + vmathSoaV3MakeYAxis( &result->col1 ); + vmathSoaV3MakeFromElems( &result->col2, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), c ); +} + +static inline void vmathSoaM3MakeRotationZ( VmathSoaMatrix3 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV3MakeFromElems( &result->col0, c, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV3MakeFromElems( &result->col1, negatef4( s ), c, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV3MakeZAxis( &result->col2 ); +} + +static inline void vmathSoaM3MakeRotationZYX( VmathSoaMatrix3 *result, const VmathSoaVector3 *radiansXYZ ) +{ + vec_float4 sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sincosf4( radiansXYZ->x, &sX, &cX ); + sincosf4( radiansXYZ->y, &sY, &cY ); + sincosf4( radiansXYZ->z, &sZ, &cZ ); + tmp0 = vec_madd( cZ, sY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + tmp1 = vec_madd( sZ, sY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV3MakeFromElems( &result->col0, vec_madd( cZ, cY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, cY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), negatef4( sY ) ); + vmathSoaV3MakeFromElems( &result->col1, vec_sub( vec_madd( tmp0, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_add( vec_madd( tmp1, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( cZ, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( cY, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV3MakeFromElems( &result->col2, vec_add( vec_madd( tmp0, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_sub( vec_madd( tmp1, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( cZ, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( cY, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +static inline void vmathSoaM3MakeRotationAxis( VmathSoaMatrix3 *result, vec_float4 radians, const VmathSoaVector3 *unitVec ) +{ + vec_float4 x, y, z, s, c, oneMinusC, xy, yz, zx; + sincosf4( radians, &s, &c ); + x = unitVec->x; + y = unitVec->y; + z = unitVec->z; + xy = vec_madd( x, y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + yz = vec_madd( y, z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + zx = vec_madd( z, x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + oneMinusC = vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), c ); + vmathSoaV3MakeFromElems( &result->col0, vec_add( vec_madd( vec_madd( x, x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), c ), vec_add( vec_madd( xy, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( z, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_sub( vec_madd( zx, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( y, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); + vmathSoaV3MakeFromElems( &result->col1, vec_sub( vec_madd( xy, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( z, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_add( vec_madd( vec_madd( y, y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), c ), vec_add( vec_madd( yz, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( x, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); + vmathSoaV3MakeFromElems( &result->col2, vec_add( vec_madd( zx, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( y, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_sub( vec_madd( yz, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( x, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_add( vec_madd( vec_madd( z, z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), c ) ); +} + +static inline void vmathSoaM3MakeRotationQ( VmathSoaMatrix3 *result, const VmathSoaQuat *unitQuat ) +{ + vmathSoaM3MakeFromQ( result, unitQuat ); +} + +static inline void vmathSoaM3MakeScale( VmathSoaMatrix3 *result, const VmathSoaVector3 *scaleVec ) +{ + vmathSoaV3MakeFromElems( &result->col0, scaleVec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV3MakeFromElems( &result->col1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), scaleVec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV3MakeFromElems( &result->col2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), scaleVec->z ); +} + +static inline void vmathSoaM3AppendScale( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat, const VmathSoaVector3 *scaleVec ) +{ + vmathSoaV3ScalarMul( &result->col0, &mat->col0, vmathSoaV3GetX( scaleVec ) ); + vmathSoaV3ScalarMul( &result->col1, &mat->col1, vmathSoaV3GetY( scaleVec ) ); + vmathSoaV3ScalarMul( &result->col2, &mat->col2, vmathSoaV3GetZ( scaleVec ) ); +} + +static inline void vmathSoaM3PrependScale( VmathSoaMatrix3 *result, const VmathSoaVector3 *scaleVec, const VmathSoaMatrix3 *mat ) +{ + vmathSoaV3MulPerElem( &result->col0, &mat->col0, scaleVec ); + vmathSoaV3MulPerElem( &result->col1, &mat->col1, scaleVec ); + vmathSoaV3MulPerElem( &result->col2, &mat->col2, scaleVec ); +} + +static inline void vmathSoaM3Select( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1, vec_uint4 select1 ) +{ + vmathSoaV3Select( &result->col0, &mat0->col0, &mat1->col0, select1 ); + vmathSoaV3Select( &result->col1, &mat0->col1, &mat1->col1, select1 ); + vmathSoaV3Select( &result->col2, &mat0->col2, &mat1->col2, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaM3Print( const VmathSoaMatrix3 *mat ) +{ + VmathMatrix3 mat0, mat1, mat2, mat3; + vmathSoaM3Get4Aos( mat, &mat0, &mat1, &mat2, &mat3 ); + printf("slot 0:\n"); + vmathM3Print( &mat0 ); + printf("slot 1:\n"); + vmathM3Print( &mat1 ); + printf("slot 2:\n"); + vmathM3Print( &mat2 ); + printf("slot 3:\n"); + vmathM3Print( &mat3 ); +} + +static inline void vmathSoaM3Prints( const VmathSoaMatrix3 *mat, const char *name ) +{ + printf("%s:\n", name); + vmathSoaM3Print( mat ); +} + +#endif + +static inline void vmathSoaM4Copy( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4Copy( &result->col0, &mat->col0 ); + vmathSoaV4Copy( &result->col1, &mat->col1 ); + vmathSoaV4Copy( &result->col2, &mat->col2 ); + vmathSoaV4Copy( &result->col3, &mat->col3 ); +} + +static inline void vmathSoaM4MakeFromScalar( VmathSoaMatrix4 *result, vec_float4 scalar ) +{ + vmathSoaV4MakeFromScalar( &result->col0, scalar ); + vmathSoaV4MakeFromScalar( &result->col1, scalar ); + vmathSoaV4MakeFromScalar( &result->col2, scalar ); + vmathSoaV4MakeFromScalar( &result->col3, scalar ); +} + +static inline void vmathSoaM4MakeFromT3( VmathSoaMatrix4 *result, const VmathSoaTransform3 *mat ) +{ + vmathSoaV4MakeFromV3Scalar( &result->col0, &mat->col0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromV3Scalar( &result->col1, &mat->col1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromV3Scalar( &result->col2, &mat->col2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromV3Scalar( &result->col3, &mat->col3, ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); +} + +static inline void vmathSoaM4MakeFromCols( VmathSoaMatrix4 *result, const VmathSoaVector4 *_col0, const VmathSoaVector4 *_col1, const VmathSoaVector4 *_col2, const VmathSoaVector4 *_col3 ) +{ + vmathSoaV4Copy( &result->col0, _col0 ); + vmathSoaV4Copy( &result->col1, _col1 ); + vmathSoaV4Copy( &result->col2, _col2 ); + vmathSoaV4Copy( &result->col3, _col3 ); +} + +static inline void vmathSoaM4MakeFromM3V3( VmathSoaMatrix4 *result, const VmathSoaMatrix3 *mat, const VmathSoaVector3 *translateVec ) +{ + vmathSoaV4MakeFromV3Scalar( &result->col0, &mat->col0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromV3Scalar( &result->col1, &mat->col1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromV3Scalar( &result->col2, &mat->col2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromV3Scalar( &result->col3, translateVec, ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); +} + +static inline void vmathSoaM4MakeFromQV3( VmathSoaMatrix4 *result, const VmathSoaQuat *unitQuat, const VmathSoaVector3 *translateVec ) +{ + VmathSoaMatrix3 mat; + vmathSoaM3MakeFromQ( &mat, unitQuat ); + vmathSoaV4MakeFromV3Scalar( &result->col0, &mat.col0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromV3Scalar( &result->col1, &mat.col1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromV3Scalar( &result->col2, &mat.col2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromV3Scalar( &result->col3, translateVec, ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); +} + +static inline void vmathSoaM4MakeFromAos( VmathSoaMatrix4 *result, const VmathMatrix4 *mat ) +{ + vmathSoaV4MakeFromAos( &result->col0, &mat->col0 ); + vmathSoaV4MakeFromAos( &result->col1, &mat->col1 ); + vmathSoaV4MakeFromAos( &result->col2, &mat->col2 ); + vmathSoaV4MakeFromAos( &result->col3, &mat->col3 ); +} + +static inline void vmathSoaM4MakeFrom4Aos( VmathSoaMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1, const VmathMatrix4 *mat2, const VmathMatrix4 *mat3 ) +{ + vmathSoaV4MakeFrom4Aos( &result->col0, &mat0->col0, &mat1->col0, &mat2->col0, &mat3->col0 ); + vmathSoaV4MakeFrom4Aos( &result->col1, &mat0->col1, &mat1->col1, &mat2->col1, &mat3->col1 ); + vmathSoaV4MakeFrom4Aos( &result->col2, &mat0->col2, &mat1->col2, &mat2->col2, &mat3->col2 ); + vmathSoaV4MakeFrom4Aos( &result->col3, &mat0->col3, &mat1->col3, &mat2->col3, &mat3->col3 ); +} + +static inline void vmathSoaM4Get4Aos( const VmathSoaMatrix4 *mat, VmathMatrix4 *result0, VmathMatrix4 *result1, VmathMatrix4 *result2, VmathMatrix4 *result3 ) +{ + vmathSoaV4Get4Aos( &mat->col0, &result0->col0, &result1->col0, &result2->col0, &result3->col0 ); + vmathSoaV4Get4Aos( &mat->col1, &result0->col1, &result1->col1, &result2->col1, &result3->col1 ); + vmathSoaV4Get4Aos( &mat->col2, &result0->col2, &result1->col2, &result2->col2, &result3->col2 ); + vmathSoaV4Get4Aos( &mat->col3, &result0->col3, &result1->col3, &result2->col3, &result3->col3 ); +} + +static inline void vmathSoaM4SetCol0( VmathSoaMatrix4 *result, const VmathSoaVector4 *_col0 ) +{ + vmathSoaV4Copy( &result->col0, _col0 ); +} + +static inline void vmathSoaM4SetCol1( VmathSoaMatrix4 *result, const VmathSoaVector4 *_col1 ) +{ + vmathSoaV4Copy( &result->col1, _col1 ); +} + +static inline void vmathSoaM4SetCol2( VmathSoaMatrix4 *result, const VmathSoaVector4 *_col2 ) +{ + vmathSoaV4Copy( &result->col2, _col2 ); +} + +static inline void vmathSoaM4SetCol3( VmathSoaMatrix4 *result, const VmathSoaVector4 *_col3 ) +{ + vmathSoaV4Copy( &result->col3, _col3 ); +} + +static inline void vmathSoaM4SetCol( VmathSoaMatrix4 *result, int col, const VmathSoaVector4 *vec ) +{ + vmathSoaV4Copy( (&result->col0 + col), vec ); +} + +static inline void vmathSoaM4SetRow( VmathSoaMatrix4 *result, int row, const VmathSoaVector4 *vec ) +{ + vmathSoaV4SetElem( &result->col0, row, vmathSoaV4GetElem( vec, 0 ) ); + vmathSoaV4SetElem( &result->col1, row, vmathSoaV4GetElem( vec, 1 ) ); + vmathSoaV4SetElem( &result->col2, row, vmathSoaV4GetElem( vec, 2 ) ); + vmathSoaV4SetElem( &result->col3, row, vmathSoaV4GetElem( vec, 3 ) ); +} + +static inline void vmathSoaM4SetElem( VmathSoaMatrix4 *result, int col, int row, vec_float4 val ) +{ + VmathSoaVector4 tmpV3_0; + vmathSoaM4GetCol( &tmpV3_0, result, col ); + vmathSoaV4SetElem( &tmpV3_0, row, val ); + vmathSoaM4SetCol( result, col, &tmpV3_0 ); +} + +static inline vec_float4 vmathSoaM4GetElem( const VmathSoaMatrix4 *mat, int col, int row ) +{ + VmathSoaVector4 tmpV4_0; + vmathSoaM4GetCol( &tmpV4_0, mat, col ); + return vmathSoaV4GetElem( &tmpV4_0, row ); +} + +static inline void vmathSoaM4GetCol0( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4Copy( result, &mat->col0 ); +} + +static inline void vmathSoaM4GetCol1( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4Copy( result, &mat->col1 ); +} + +static inline void vmathSoaM4GetCol2( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4Copy( result, &mat->col2 ); +} + +static inline void vmathSoaM4GetCol3( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4Copy( result, &mat->col3 ); +} + +static inline void vmathSoaM4GetCol( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, int col ) +{ + vmathSoaV4Copy( result, (&mat->col0 + col) ); +} + +static inline void vmathSoaM4GetRow( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, int row ) +{ + vmathSoaV4MakeFromElems( result, vmathSoaV4GetElem( &mat->col0, row ), vmathSoaV4GetElem( &mat->col1, row ), vmathSoaV4GetElem( &mat->col2, row ), vmathSoaV4GetElem( &mat->col3, row ) ); +} + +static inline void vmathSoaM4Transpose( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ) +{ + VmathSoaMatrix4 tmpResult; + vmathSoaV4MakeFromElems( &tmpResult.col0, mat->col0.x, mat->col1.x, mat->col2.x, mat->col3.x ); + vmathSoaV4MakeFromElems( &tmpResult.col1, mat->col0.y, mat->col1.y, mat->col2.y, mat->col3.y ); + vmathSoaV4MakeFromElems( &tmpResult.col2, mat->col0.z, mat->col1.z, mat->col2.z, mat->col3.z ); + vmathSoaV4MakeFromElems( &tmpResult.col3, mat->col0.w, mat->col1.w, mat->col2.w, mat->col3.w ); + vmathSoaM4Copy( result, &tmpResult ); +} + +static inline void vmathSoaM4Inverse( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ) +{ + VmathSoaVector4 res0, res1, res2, res3; + vec_float4 mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, detInv; + mA = mat->col0.x; + mB = mat->col0.y; + mC = mat->col0.z; + mD = mat->col0.w; + mE = mat->col1.x; + mF = mat->col1.y; + mG = mat->col1.z; + mH = mat->col1.w; + mI = mat->col2.x; + mJ = mat->col2.y; + mK = mat->col2.z; + mL = mat->col2.w; + mM = mat->col3.x; + mN = mat->col3.y; + mO = mat->col3.z; + mP = mat->col3.w; + tmp0 = vec_sub( vec_madd( mK, mD, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mC, mL, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp1 = vec_sub( vec_madd( mO, mH, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mG, mP, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp2 = vec_sub( vec_madd( mB, mK, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mJ, mC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp3 = vec_sub( vec_madd( mF, mO, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mN, mG, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp4 = vec_sub( vec_madd( mJ, mD, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mB, mL, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp5 = vec_sub( vec_madd( mN, mH, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mF, mP, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV4SetX( &res0, vec_sub( vec_sub( vec_madd( mJ, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mL, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mK, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); + vmathSoaV4SetY( &res0, vec_sub( vec_sub( vec_madd( mN, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mP, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mO, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); + vmathSoaV4SetZ( &res0, vec_sub( vec_add( vec_madd( mD, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mC, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mB, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); + vmathSoaV4SetW( &res0, vec_sub( vec_add( vec_madd( mH, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mG, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mF, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); + detInv = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec_add( vec_add( vec_add( vec_madd( mA, res0.x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mE, res0.y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mI, res0.z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mM, res0.w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); + vmathSoaV4SetX( &res1, vec_madd( mI, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV4SetY( &res1, vec_madd( mM, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV4SetZ( &res1, vec_madd( mA, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV4SetW( &res1, vec_madd( mE, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV4SetX( &res3, vec_madd( mI, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV4SetY( &res3, vec_madd( mM, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV4SetZ( &res3, vec_madd( mA, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV4SetW( &res3, vec_madd( mE, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV4SetX( &res2, vec_madd( mI, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV4SetY( &res2, vec_madd( mM, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV4SetZ( &res2, vec_madd( mA, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV4SetW( &res2, vec_madd( mE, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp0 = vec_sub( vec_madd( mI, mB, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mA, mJ, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp1 = vec_sub( vec_madd( mM, mF, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mE, mN, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp2 = vec_sub( vec_madd( mI, mD, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mA, mL, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp3 = vec_sub( vec_madd( mM, mH, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mE, mP, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp4 = vec_sub( vec_madd( mI, mC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mA, mK, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp5 = vec_sub( vec_madd( mM, mG, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mE, mO, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV4SetX( &res2, vec_add( vec_sub( vec_madd( mL, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mJ, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res2.x ) ); + vmathSoaV4SetY( &res2, vec_add( vec_sub( vec_madd( mP, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mN, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res2.y ) ); + vmathSoaV4SetZ( &res2, vec_sub( vec_sub( vec_madd( mB, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mD, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res2.z ) ); + vmathSoaV4SetW( &res2, vec_sub( vec_sub( vec_madd( mF, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mH, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res2.w ) ); + vmathSoaV4SetX( &res3, vec_add( vec_sub( vec_madd( mJ, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mK, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res3.x ) ); + vmathSoaV4SetY( &res3, vec_add( vec_sub( vec_madd( mN, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mO, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res3.y ) ); + vmathSoaV4SetZ( &res3, vec_sub( vec_sub( vec_madd( mC, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mB, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res3.z ) ); + vmathSoaV4SetW( &res3, vec_sub( vec_sub( vec_madd( mG, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mF, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res3.w ) ); + vmathSoaV4SetX( &res1, vec_sub( vec_sub( vec_madd( mK, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mL, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res1.x ) ); + vmathSoaV4SetY( &res1, vec_sub( vec_sub( vec_madd( mO, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mP, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res1.y ) ); + vmathSoaV4SetZ( &res1, vec_add( vec_sub( vec_madd( mD, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mC, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res1.z ) ); + vmathSoaV4SetW( &res1, vec_add( vec_sub( vec_madd( mH, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mG, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res1.w ) ); + vmathSoaV4ScalarMul( &result->col0, &res0, detInv ); + vmathSoaV4ScalarMul( &result->col1, &res1, detInv ); + vmathSoaV4ScalarMul( &result->col2, &res2, detInv ); + vmathSoaV4ScalarMul( &result->col3, &res3, detInv ); +} + +static inline void vmathSoaM4AffineInverse( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ) +{ + VmathSoaTransform3 affineMat, tmpT3_0; + VmathSoaVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + vmathSoaV4GetXYZ( &tmpV3_0, &mat->col0 ); + vmathSoaT3SetCol0( &affineMat, &tmpV3_0 ); + vmathSoaV4GetXYZ( &tmpV3_1, &mat->col1 ); + vmathSoaT3SetCol1( &affineMat, &tmpV3_1 ); + vmathSoaV4GetXYZ( &tmpV3_2, &mat->col2 ); + vmathSoaT3SetCol2( &affineMat, &tmpV3_2 ); + vmathSoaV4GetXYZ( &tmpV3_3, &mat->col3 ); + vmathSoaT3SetCol3( &affineMat, &tmpV3_3 ); + vmathSoaT3Inverse( &tmpT3_0, &affineMat ); + vmathSoaM4MakeFromT3( result, &tmpT3_0 ); +} + +static inline void vmathSoaM4OrthoInverse( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ) +{ + VmathSoaTransform3 affineMat, tmpT3_0; + VmathSoaVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + vmathSoaV4GetXYZ( &tmpV3_0, &mat->col0 ); + vmathSoaT3SetCol0( &affineMat, &tmpV3_0 ); + vmathSoaV4GetXYZ( &tmpV3_1, &mat->col1 ); + vmathSoaT3SetCol1( &affineMat, &tmpV3_1 ); + vmathSoaV4GetXYZ( &tmpV3_2, &mat->col2 ); + vmathSoaT3SetCol2( &affineMat, &tmpV3_2 ); + vmathSoaV4GetXYZ( &tmpV3_3, &mat->col3 ); + vmathSoaT3SetCol3( &affineMat, &tmpV3_3 ); + vmathSoaT3OrthoInverse( &tmpT3_0, &affineMat ); + vmathSoaM4MakeFromT3( result, &tmpT3_0 ); +} + +static inline vec_float4 vmathSoaM4Determinant( const VmathSoaMatrix4 *mat ) +{ + vec_float4 dx, dy, dz, dw, mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + mA = mat->col0.x; + mB = mat->col0.y; + mC = mat->col0.z; + mD = mat->col0.w; + mE = mat->col1.x; + mF = mat->col1.y; + mG = mat->col1.z; + mH = mat->col1.w; + mI = mat->col2.x; + mJ = mat->col2.y; + mK = mat->col2.z; + mL = mat->col2.w; + mM = mat->col3.x; + mN = mat->col3.y; + mO = mat->col3.z; + mP = mat->col3.w; + tmp0 = vec_sub( vec_madd( mK, mD, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mC, mL, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp1 = vec_sub( vec_madd( mO, mH, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mG, mP, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp2 = vec_sub( vec_madd( mB, mK, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mJ, mC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp3 = vec_sub( vec_madd( mF, mO, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mN, mG, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp4 = vec_sub( vec_madd( mJ, mD, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mB, mL, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp5 = vec_sub( vec_madd( mN, mH, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mF, mP, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + dx = vec_sub( vec_sub( vec_madd( mJ, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mL, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mK, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + dy = vec_sub( vec_sub( vec_madd( mN, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mP, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mO, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + dz = vec_sub( vec_add( vec_madd( mD, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mC, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mB, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + dw = vec_sub( vec_add( vec_madd( mH, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mG, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mF, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return vec_add( vec_add( vec_add( vec_madd( mA, dx, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mE, dy, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mI, dz, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mM, dw, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +static inline void vmathSoaM4Add( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 ) +{ + vmathSoaV4Add( &result->col0, &mat0->col0, &mat1->col0 ); + vmathSoaV4Add( &result->col1, &mat0->col1, &mat1->col1 ); + vmathSoaV4Add( &result->col2, &mat0->col2, &mat1->col2 ); + vmathSoaV4Add( &result->col3, &mat0->col3, &mat1->col3 ); +} + +static inline void vmathSoaM4Sub( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 ) +{ + vmathSoaV4Sub( &result->col0, &mat0->col0, &mat1->col0 ); + vmathSoaV4Sub( &result->col1, &mat0->col1, &mat1->col1 ); + vmathSoaV4Sub( &result->col2, &mat0->col2, &mat1->col2 ); + vmathSoaV4Sub( &result->col3, &mat0->col3, &mat1->col3 ); +} + +static inline void vmathSoaM4Neg( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4Neg( &result->col0, &mat->col0 ); + vmathSoaV4Neg( &result->col1, &mat->col1 ); + vmathSoaV4Neg( &result->col2, &mat->col2 ); + vmathSoaV4Neg( &result->col3, &mat->col3 ); +} + +static inline void vmathSoaM4AbsPerElem( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4AbsPerElem( &result->col0, &mat->col0 ); + vmathSoaV4AbsPerElem( &result->col1, &mat->col1 ); + vmathSoaV4AbsPerElem( &result->col2, &mat->col2 ); + vmathSoaV4AbsPerElem( &result->col3, &mat->col3 ); +} + +static inline void vmathSoaM4ScalarMul( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat, vec_float4 scalar ) +{ + vmathSoaV4ScalarMul( &result->col0, &mat->col0, scalar ); + vmathSoaV4ScalarMul( &result->col1, &mat->col1, scalar ); + vmathSoaV4ScalarMul( &result->col2, &mat->col2, scalar ); + vmathSoaV4ScalarMul( &result->col3, &mat->col3, scalar ); +} + +static inline void vmathSoaM4MulV4( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, const VmathSoaVector4 *vec ) +{ + vec_float4 tmpX, tmpY, tmpZ, tmpW; + tmpX = vec_add( vec_add( vec_add( vec_madd( mat->col0.x, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mat->col1.x, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col2.x, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col3.x, vec->w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpY = vec_add( vec_add( vec_add( vec_madd( mat->col0.y, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mat->col1.y, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col2.y, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col3.y, vec->w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpZ = vec_add( vec_add( vec_add( vec_madd( mat->col0.z, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mat->col1.z, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col2.z, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col3.z, vec->w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpW = vec_add( vec_add( vec_add( vec_madd( mat->col0.w, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mat->col1.w, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col2.w, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col3.w, vec->w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV4MakeFromElems( result, tmpX, tmpY, tmpZ, tmpW ); +} + +static inline void vmathSoaM4MulV3( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, const VmathSoaVector3 *vec ) +{ + result->x = vec_add( vec_add( vec_madd( mat->col0.x, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mat->col1.x, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col2.x, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result->y = vec_add( vec_add( vec_madd( mat->col0.y, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mat->col1.y, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col2.y, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result->z = vec_add( vec_add( vec_madd( mat->col0.z, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mat->col1.z, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col2.z, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result->w = vec_add( vec_add( vec_madd( mat->col0.w, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mat->col1.w, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col2.w, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +static inline void vmathSoaM4MulP3( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, const VmathSoaPoint3 *pnt ) +{ + result->x = vec_add( vec_add( vec_add( vec_madd( mat->col0.x, pnt->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mat->col1.x, pnt->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col2.x, pnt->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), mat->col3.x ); + result->y = vec_add( vec_add( vec_add( vec_madd( mat->col0.y, pnt->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mat->col1.y, pnt->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col2.y, pnt->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), mat->col3.y ); + result->z = vec_add( vec_add( vec_add( vec_madd( mat->col0.z, pnt->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mat->col1.z, pnt->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col2.z, pnt->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), mat->col3.z ); + result->w = vec_add( vec_add( vec_add( vec_madd( mat->col0.w, pnt->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mat->col1.w, pnt->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mat->col2.w, pnt->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), mat->col3.w ); +} + +static inline void vmathSoaM4Mul( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 ) +{ + VmathSoaMatrix4 tmpResult; + vmathSoaM4MulV4( &tmpResult.col0, mat0, &mat1->col0 ); + vmathSoaM4MulV4( &tmpResult.col1, mat0, &mat1->col1 ); + vmathSoaM4MulV4( &tmpResult.col2, mat0, &mat1->col2 ); + vmathSoaM4MulV4( &tmpResult.col3, mat0, &mat1->col3 ); + vmathSoaM4Copy( result, &tmpResult ); +} + +static inline void vmathSoaM4MulT3( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat, const VmathSoaTransform3 *tfrm1 ) +{ + VmathSoaMatrix4 tmpResult; + VmathSoaPoint3 tmpP3_0; + vmathSoaM4MulV3( &tmpResult.col0, mat, &tfrm1->col0 ); + vmathSoaM4MulV3( &tmpResult.col1, mat, &tfrm1->col1 ); + vmathSoaM4MulV3( &tmpResult.col2, mat, &tfrm1->col2 ); + vmathSoaP3MakeFromV3( &tmpP3_0, &tfrm1->col3 ); + vmathSoaM4MulP3( &tmpResult.col3, mat, &tmpP3_0 ); + vmathSoaM4Copy( result, &tmpResult ); +} + +static inline void vmathSoaM4MulPerElem( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 ) +{ + vmathSoaV4MulPerElem( &result->col0, &mat0->col0, &mat1->col0 ); + vmathSoaV4MulPerElem( &result->col1, &mat0->col1, &mat1->col1 ); + vmathSoaV4MulPerElem( &result->col2, &mat0->col2, &mat1->col2 ); + vmathSoaV4MulPerElem( &result->col3, &mat0->col3, &mat1->col3 ); +} + +static inline void vmathSoaM4MakeIdentity( VmathSoaMatrix4 *result ) +{ + vmathSoaV4MakeXAxis( &result->col0 ); + vmathSoaV4MakeYAxis( &result->col1 ); + vmathSoaV4MakeZAxis( &result->col2 ); + vmathSoaV4MakeWAxis( &result->col3 ); +} + +static inline void vmathSoaM4SetUpper3x3( VmathSoaMatrix4 *result, const VmathSoaMatrix3 *mat3 ) +{ + vmathSoaV4SetXYZ( &result->col0, &mat3->col0 ); + vmathSoaV4SetXYZ( &result->col1, &mat3->col1 ); + vmathSoaV4SetXYZ( &result->col2, &mat3->col2 ); +} + +static inline void vmathSoaM4GetUpper3x3( VmathSoaMatrix3 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4GetXYZ( &result->col0, &mat->col0 ); + vmathSoaV4GetXYZ( &result->col1, &mat->col1 ); + vmathSoaV4GetXYZ( &result->col2, &mat->col2 ); +} + +static inline void vmathSoaM4SetTranslation( VmathSoaMatrix4 *result, const VmathSoaVector3 *translateVec ) +{ + vmathSoaV4SetXYZ( &result->col3, translateVec ); +} + +static inline void vmathSoaM4GetTranslation( VmathSoaVector3 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4GetXYZ( result, &mat->col3 ); +} + +static inline void vmathSoaM4MakeRotationX( VmathSoaMatrix4 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV4MakeXAxis( &result->col0 ); + vmathSoaV4MakeFromElems( &result->col1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), c, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromElems( &result->col2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), negatef4( s ), c, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeWAxis( &result->col3 ); +} + +static inline void vmathSoaM4MakeRotationY( VmathSoaMatrix4 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV4MakeFromElems( &result->col0, c, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), negatef4( s ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeYAxis( &result->col1 ); + vmathSoaV4MakeFromElems( &result->col2, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), c, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeWAxis( &result->col3 ); +} + +static inline void vmathSoaM4MakeRotationZ( VmathSoaMatrix4 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV4MakeFromElems( &result->col0, c, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromElems( &result->col1, negatef4( s ), c, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeZAxis( &result->col2 ); + vmathSoaV4MakeWAxis( &result->col3 ); +} + +static inline void vmathSoaM4MakeRotationZYX( VmathSoaMatrix4 *result, const VmathSoaVector3 *radiansXYZ ) +{ + vec_float4 sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sincosf4( radiansXYZ->x, &sX, &cX ); + sincosf4( radiansXYZ->y, &sY, &cY ); + sincosf4( radiansXYZ->z, &sZ, &cZ ); + tmp0 = vec_madd( cZ, sY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + tmp1 = vec_madd( sZ, sY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromElems( &result->col0, vec_madd( cZ, cY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, cY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), negatef4( sY ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromElems( &result->col1, vec_sub( vec_madd( tmp0, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_add( vec_madd( tmp1, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( cZ, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( cY, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromElems( &result->col2, vec_add( vec_madd( tmp0, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_sub( vec_madd( tmp1, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( cZ, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( cY, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeWAxis( &result->col3 ); +} + +static inline void vmathSoaM4MakeRotationAxis( VmathSoaMatrix4 *result, vec_float4 radians, const VmathSoaVector3 *unitVec ) +{ + vec_float4 x, y, z, s, c, oneMinusC, xy, yz, zx; + sincosf4( radians, &s, &c ); + x = unitVec->x; + y = unitVec->y; + z = unitVec->z; + xy = vec_madd( x, y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + yz = vec_madd( y, z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + zx = vec_madd( z, x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + oneMinusC = vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), c ); + vmathSoaV4MakeFromElems( &result->col0, vec_add( vec_madd( vec_madd( x, x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), c ), vec_add( vec_madd( xy, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( z, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_sub( vec_madd( zx, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( y, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromElems( &result->col1, vec_sub( vec_madd( xy, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( z, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_add( vec_madd( vec_madd( y, y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), c ), vec_add( vec_madd( yz, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( x, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromElems( &result->col2, vec_add( vec_madd( zx, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( y, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_sub( vec_madd( yz, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( x, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_add( vec_madd( vec_madd( z, z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), c ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeWAxis( &result->col3 ); +} + +static inline void vmathSoaM4MakeRotationQ( VmathSoaMatrix4 *result, const VmathSoaQuat *unitQuat ) +{ + VmathSoaTransform3 tmpT3_0; + vmathSoaT3MakeRotationQ( &tmpT3_0, unitQuat ); + vmathSoaM4MakeFromT3( result, &tmpT3_0 ); +} + +static inline void vmathSoaM4MakeScale( VmathSoaMatrix4 *result, const VmathSoaVector3 *scaleVec ) +{ + vmathSoaV4MakeFromElems( &result->col0, scaleVec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromElems( &result->col1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), scaleVec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromElems( &result->col2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), scaleVec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeWAxis( &result->col3 ); +} + +static inline void vmathSoaM4AppendScale( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat, const VmathSoaVector3 *scaleVec ) +{ + vmathSoaV4ScalarMul( &result->col0, &mat->col0, vmathSoaV3GetX( scaleVec ) ); + vmathSoaV4ScalarMul( &result->col1, &mat->col1, vmathSoaV3GetY( scaleVec ) ); + vmathSoaV4ScalarMul( &result->col2, &mat->col2, vmathSoaV3GetZ( scaleVec ) ); + vmathSoaV4Copy( &result->col3, &mat->col3 ); +} + +static inline void vmathSoaM4PrependScale( VmathSoaMatrix4 *result, const VmathSoaVector3 *scaleVec, const VmathSoaMatrix4 *mat ) +{ + VmathSoaVector4 scale4; + vmathSoaV4MakeFromV3Scalar( &scale4, scaleVec, ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); + vmathSoaV4MulPerElem( &result->col0, &mat->col0, &scale4 ); + vmathSoaV4MulPerElem( &result->col1, &mat->col1, &scale4 ); + vmathSoaV4MulPerElem( &result->col2, &mat->col2, &scale4 ); + vmathSoaV4MulPerElem( &result->col3, &mat->col3, &scale4 ); +} + +static inline void vmathSoaM4MakeTranslation( VmathSoaMatrix4 *result, const VmathSoaVector3 *translateVec ) +{ + vmathSoaV4MakeXAxis( &result->col0 ); + vmathSoaV4MakeYAxis( &result->col1 ); + vmathSoaV4MakeZAxis( &result->col2 ); + vmathSoaV4MakeFromV3Scalar( &result->col3, translateVec, ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); +} + +static inline void vmathSoaM4MakeLookAt( VmathSoaMatrix4 *result, const VmathSoaPoint3 *eyePos, const VmathSoaPoint3 *lookAtPos, const VmathSoaVector3 *upVec ) +{ + VmathSoaMatrix4 m4EyeFrame; + VmathSoaVector3 v3X, v3Y, v3Z, tmpV3_0, tmpV3_1; + VmathSoaVector4 tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3; + vmathSoaV3Normalize( &v3Y, upVec ); + vmathSoaP3Sub( &tmpV3_0, eyePos, lookAtPos ); + vmathSoaV3Normalize( &v3Z, &tmpV3_0 ); + vmathSoaV3Cross( &tmpV3_1, &v3Y, &v3Z ); + vmathSoaV3Normalize( &v3X, &tmpV3_1 ); + vmathSoaV3Cross( &v3Y, &v3Z, &v3X ); + vmathSoaV4MakeFromV3( &tmpV4_0, &v3X ); + vmathSoaV4MakeFromV3( &tmpV4_1, &v3Y ); + vmathSoaV4MakeFromV3( &tmpV4_2, &v3Z ); + vmathSoaV4MakeFromP3( &tmpV4_3, eyePos ); + vmathSoaM4MakeFromCols( &m4EyeFrame, &tmpV4_0, &tmpV4_1, &tmpV4_2, &tmpV4_3 ); + vmathSoaM4OrthoInverse( result, &m4EyeFrame ); +} + +static inline void vmathSoaM4MakePerspective( VmathSoaMatrix4 *result, vec_float4 fovyRadians, vec_float4 aspect, vec_float4 zNear, vec_float4 zFar ) +{ + vec_float4 f, rangeInv; + f = tanf4( vec_sub( ((vec_float4){_VECTORMATH_PI_OVER_2,_VECTORMATH_PI_OVER_2,_VECTORMATH_PI_OVER_2,_VECTORMATH_PI_OVER_2}), vec_madd( ((vec_float4){0.5f,0.5f,0.5f,0.5f}), fovyRadians, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); + rangeInv = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec_sub( zNear, zFar ) ); + vmathSoaV4MakeFromElems( &result->col0, divf4( f, aspect ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromElems( &result->col1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), f, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromElems( &result->col2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), vec_madd( vec_add( zNear, zFar ), rangeInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){-1.0f,-1.0f,-1.0f,-1.0f}) ); + vmathSoaV4MakeFromElems( &result->col3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), vec_madd( vec_madd( vec_madd( zNear, zFar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), rangeInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){2.0f,2.0f,2.0f,2.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaM4MakeFrustum( VmathSoaMatrix4 *result, vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ) +{ + vec_float4 sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf, n2; + sum_rl = vec_add( right, left ); + sum_tb = vec_add( top, bottom ); + sum_nf = vec_add( zNear, zFar ); + inv_rl = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec_sub( right, left ) ); + inv_tb = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec_sub( top, bottom ) ); + inv_nf = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec_sub( zNear, zFar ) ); + n2 = vec_add( zNear, zNear ); + vmathSoaV4MakeFromElems( &result->col0, vec_madd( n2, inv_rl, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromElems( &result->col1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), vec_madd( n2, inv_tb, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromElems( &result->col2, vec_madd( sum_rl, inv_rl, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sum_tb, inv_tb, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sum_nf, inv_nf, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){-1.0f,-1.0f,-1.0f,-1.0f}) ); + vmathSoaV4MakeFromElems( &result->col3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), vec_madd( vec_madd( n2, inv_nf, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), zFar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaM4MakeOrthographic( VmathSoaMatrix4 *result, vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ) +{ + vec_float4 sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf; + sum_rl = vec_add( right, left ); + sum_tb = vec_add( top, bottom ); + sum_nf = vec_add( zNear, zFar ); + inv_rl = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec_sub( right, left ) ); + inv_tb = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec_sub( top, bottom ) ); + inv_nf = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec_sub( zNear, zFar ) ); + vmathSoaV4MakeFromElems( &result->col0, vec_add( inv_rl, inv_rl ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromElems( &result->col1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), vec_add( inv_tb, inv_tb ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromElems( &result->col2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), vec_add( inv_nf, inv_nf ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV4MakeFromElems( &result->col3, vec_madd( negatef4( sum_rl ), inv_rl, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( negatef4( sum_tb ), inv_tb, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sum_nf, inv_nf, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); +} + +static inline void vmathSoaM4Select( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1, vec_uint4 select1 ) +{ + vmathSoaV4Select( &result->col0, &mat0->col0, &mat1->col0, select1 ); + vmathSoaV4Select( &result->col1, &mat0->col1, &mat1->col1, select1 ); + vmathSoaV4Select( &result->col2, &mat0->col2, &mat1->col2, select1 ); + vmathSoaV4Select( &result->col3, &mat0->col3, &mat1->col3, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaM4Print( const VmathSoaMatrix4 *mat ) +{ + VmathMatrix4 mat0, mat1, mat2, mat3; + vmathSoaM4Get4Aos( mat, &mat0, &mat1, &mat2, &mat3 ); + printf("slot 0:\n"); + vmathM4Print( &mat0 ); + printf("slot 1:\n"); + vmathM4Print( &mat1 ); + printf("slot 2:\n"); + vmathM4Print( &mat2 ); + printf("slot 3:\n"); + vmathM4Print( &mat3 ); +} + +static inline void vmathSoaM4Prints( const VmathSoaMatrix4 *mat, const char *name ) +{ + printf("%s:\n", name); + vmathSoaM4Print( mat ); +} + +#endif + +static inline void vmathSoaT3Copy( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaV3Copy( &result->col0, &tfrm->col0 ); + vmathSoaV3Copy( &result->col1, &tfrm->col1 ); + vmathSoaV3Copy( &result->col2, &tfrm->col2 ); + vmathSoaV3Copy( &result->col3, &tfrm->col3 ); +} + +static inline void vmathSoaT3MakeFromScalar( VmathSoaTransform3 *result, vec_float4 scalar ) +{ + vmathSoaV3MakeFromScalar( &result->col0, scalar ); + vmathSoaV3MakeFromScalar( &result->col1, scalar ); + vmathSoaV3MakeFromScalar( &result->col2, scalar ); + vmathSoaV3MakeFromScalar( &result->col3, scalar ); +} + +static inline void vmathSoaT3MakeFromCols( VmathSoaTransform3 *result, const VmathSoaVector3 *_col0, const VmathSoaVector3 *_col1, const VmathSoaVector3 *_col2, const VmathSoaVector3 *_col3 ) +{ + vmathSoaV3Copy( &result->col0, _col0 ); + vmathSoaV3Copy( &result->col1, _col1 ); + vmathSoaV3Copy( &result->col2, _col2 ); + vmathSoaV3Copy( &result->col3, _col3 ); +} + +static inline void vmathSoaT3MakeFromM3V3( VmathSoaTransform3 *result, const VmathSoaMatrix3 *tfrm, const VmathSoaVector3 *translateVec ) +{ + vmathSoaT3SetUpper3x3( result, tfrm ); + vmathSoaT3SetTranslation( result, translateVec ); +} + +static inline void vmathSoaT3MakeFromQV3( VmathSoaTransform3 *result, const VmathSoaQuat *unitQuat, const VmathSoaVector3 *translateVec ) +{ + VmathSoaMatrix3 tmpM3_0; + vmathSoaM3MakeFromQ( &tmpM3_0, unitQuat ); + vmathSoaT3SetUpper3x3( result, &tmpM3_0 ); + vmathSoaT3SetTranslation( result, translateVec ); +} + +static inline void vmathSoaT3MakeFromAos( VmathSoaTransform3 *result, const VmathTransform3 *tfrm ) +{ + vmathSoaV3MakeFromAos( &result->col0, &tfrm->col0 ); + vmathSoaV3MakeFromAos( &result->col1, &tfrm->col1 ); + vmathSoaV3MakeFromAos( &result->col2, &tfrm->col2 ); + vmathSoaV3MakeFromAos( &result->col3, &tfrm->col3 ); +} + +static inline void vmathSoaT3MakeFrom4Aos( VmathSoaTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1, const VmathTransform3 *tfrm2, const VmathTransform3 *tfrm3 ) +{ + vmathSoaV3MakeFrom4Aos( &result->col0, &tfrm0->col0, &tfrm1->col0, &tfrm2->col0, &tfrm3->col0 ); + vmathSoaV3MakeFrom4Aos( &result->col1, &tfrm0->col1, &tfrm1->col1, &tfrm2->col1, &tfrm3->col1 ); + vmathSoaV3MakeFrom4Aos( &result->col2, &tfrm0->col2, &tfrm1->col2, &tfrm2->col2, &tfrm3->col2 ); + vmathSoaV3MakeFrom4Aos( &result->col3, &tfrm0->col3, &tfrm1->col3, &tfrm2->col3, &tfrm3->col3 ); +} + +static inline void vmathSoaT3Get4Aos( const VmathSoaTransform3 *tfrm, VmathTransform3 *result0, VmathTransform3 *result1, VmathTransform3 *result2, VmathTransform3 *result3 ) +{ + vmathSoaV3Get4Aos( &tfrm->col0, &result0->col0, &result1->col0, &result2->col0, &result3->col0 ); + vmathSoaV3Get4Aos( &tfrm->col1, &result0->col1, &result1->col1, &result2->col1, &result3->col1 ); + vmathSoaV3Get4Aos( &tfrm->col2, &result0->col2, &result1->col2, &result2->col2, &result3->col2 ); + vmathSoaV3Get4Aos( &tfrm->col3, &result0->col3, &result1->col3, &result2->col3, &result3->col3 ); +} + +static inline void vmathSoaT3SetCol0( VmathSoaTransform3 *result, const VmathSoaVector3 *_col0 ) +{ + vmathSoaV3Copy( &result->col0, _col0 ); +} + +static inline void vmathSoaT3SetCol1( VmathSoaTransform3 *result, const VmathSoaVector3 *_col1 ) +{ + vmathSoaV3Copy( &result->col1, _col1 ); +} + +static inline void vmathSoaT3SetCol2( VmathSoaTransform3 *result, const VmathSoaVector3 *_col2 ) +{ + vmathSoaV3Copy( &result->col2, _col2 ); +} + +static inline void vmathSoaT3SetCol3( VmathSoaTransform3 *result, const VmathSoaVector3 *_col3 ) +{ + vmathSoaV3Copy( &result->col3, _col3 ); +} + +static inline void vmathSoaT3SetCol( VmathSoaTransform3 *result, int col, const VmathSoaVector3 *vec ) +{ + vmathSoaV3Copy( (&result->col0 + col), vec ); +} + +static inline void vmathSoaT3SetRow( VmathSoaTransform3 *result, int row, const VmathSoaVector4 *vec ) +{ + vmathSoaV3SetElem( &result->col0, row, vmathSoaV4GetElem( vec, 0 ) ); + vmathSoaV3SetElem( &result->col1, row, vmathSoaV4GetElem( vec, 1 ) ); + vmathSoaV3SetElem( &result->col2, row, vmathSoaV4GetElem( vec, 2 ) ); + vmathSoaV3SetElem( &result->col3, row, vmathSoaV4GetElem( vec, 3 ) ); +} + +static inline void vmathSoaT3SetElem( VmathSoaTransform3 *result, int col, int row, vec_float4 val ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaT3GetCol( &tmpV3_0, result, col ); + vmathSoaV3SetElem( &tmpV3_0, row, val ); + vmathSoaT3SetCol( result, col, &tmpV3_0 ); +} + +static inline vec_float4 vmathSoaT3GetElem( const VmathSoaTransform3 *tfrm, int col, int row ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaT3GetCol( &tmpV3_0, tfrm, col ); + return vmathSoaV3GetElem( &tmpV3_0, row ); +} + +static inline void vmathSoaT3GetCol0( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaV3Copy( result, &tfrm->col0 ); +} + +static inline void vmathSoaT3GetCol1( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaV3Copy( result, &tfrm->col1 ); +} + +static inline void vmathSoaT3GetCol2( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaV3Copy( result, &tfrm->col2 ); +} + +static inline void vmathSoaT3GetCol3( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaV3Copy( result, &tfrm->col3 ); +} + +static inline void vmathSoaT3GetCol( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm, int col ) +{ + vmathSoaV3Copy( result, (&tfrm->col0 + col) ); +} + +static inline void vmathSoaT3GetRow( VmathSoaVector4 *result, const VmathSoaTransform3 *tfrm, int row ) +{ + vmathSoaV4MakeFromElems( result, vmathSoaV3GetElem( &tfrm->col0, row ), vmathSoaV3GetElem( &tfrm->col1, row ), vmathSoaV3GetElem( &tfrm->col2, row ), vmathSoaV3GetElem( &tfrm->col3, row ) ); +} + +static inline void vmathSoaT3Inverse( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm ) +{ + VmathSoaVector3 tmp0, tmp1, tmp2, inv0, inv1, inv2, tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5; + vec_float4 detinv; + vmathSoaV3Cross( &tmp0, &tfrm->col1, &tfrm->col2 ); + vmathSoaV3Cross( &tmp1, &tfrm->col2, &tfrm->col0 ); + vmathSoaV3Cross( &tmp2, &tfrm->col0, &tfrm->col1 ); + detinv = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vmathSoaV3Dot( &tfrm->col2, &tmp2 ) ); + vmathSoaV3MakeFromElems( &inv0, vec_madd( tmp0.x, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp1.x, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp2.x, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV3MakeFromElems( &inv1, vec_madd( tmp0.y, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp1.y, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp2.y, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV3MakeFromElems( &inv2, vec_madd( tmp0.z, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp1.z, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp2.z, detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV3Copy( &result->col0, &inv0 ); + vmathSoaV3Copy( &result->col1, &inv1 ); + vmathSoaV3Copy( &result->col2, &inv2 ); + vmathSoaV3ScalarMul( &tmpV3_0, &inv0, tfrm->col3.x ); + vmathSoaV3ScalarMul( &tmpV3_1, &inv1, tfrm->col3.y ); + vmathSoaV3ScalarMul( &tmpV3_2, &inv2, tfrm->col3.z ); + vmathSoaV3Add( &tmpV3_3, &tmpV3_1, &tmpV3_2 ); + vmathSoaV3Add( &tmpV3_4, &tmpV3_0, &tmpV3_3 ); + vmathSoaV3Neg( &tmpV3_5, &tmpV3_4 ); + vmathSoaV3Copy( &result->col3, &tmpV3_5 ); +} + +static inline void vmathSoaT3OrthoInverse( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm ) +{ + VmathSoaVector3 inv0, inv1, inv2, tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5; + vmathSoaV3MakeFromElems( &inv0, tfrm->col0.x, tfrm->col1.x, tfrm->col2.x ); + vmathSoaV3MakeFromElems( &inv1, tfrm->col0.y, tfrm->col1.y, tfrm->col2.y ); + vmathSoaV3MakeFromElems( &inv2, tfrm->col0.z, tfrm->col1.z, tfrm->col2.z ); + vmathSoaV3Copy( &result->col0, &inv0 ); + vmathSoaV3Copy( &result->col1, &inv1 ); + vmathSoaV3Copy( &result->col2, &inv2 ); + vmathSoaV3ScalarMul( &tmpV3_0, &inv0, tfrm->col3.x ); + vmathSoaV3ScalarMul( &tmpV3_1, &inv1, tfrm->col3.y ); + vmathSoaV3ScalarMul( &tmpV3_2, &inv2, tfrm->col3.z ); + vmathSoaV3Add( &tmpV3_3, &tmpV3_1, &tmpV3_2 ); + vmathSoaV3Add( &tmpV3_4, &tmpV3_0, &tmpV3_3 ); + vmathSoaV3Neg( &tmpV3_5, &tmpV3_4 ); + vmathSoaV3Copy( &result->col3, &tmpV3_5 ); +} + +static inline void vmathSoaT3AbsPerElem( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaV3AbsPerElem( &result->col0, &tfrm->col0 ); + vmathSoaV3AbsPerElem( &result->col1, &tfrm->col1 ); + vmathSoaV3AbsPerElem( &result->col2, &tfrm->col2 ); + vmathSoaV3AbsPerElem( &result->col3, &tfrm->col3 ); +} + +static inline void vmathSoaT3MulV3( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm, const VmathSoaVector3 *vec ) +{ + vec_float4 tmpX, tmpY, tmpZ; + tmpX = vec_add( vec_add( vec_madd( tfrm->col0.x, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tfrm->col1.x, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tfrm->col2.x, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpY = vec_add( vec_add( vec_madd( tfrm->col0.y, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tfrm->col1.y, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tfrm->col2.y, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpZ = vec_add( vec_add( vec_madd( tfrm->col0.z, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tfrm->col1.z, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tfrm->col2.z, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV3MakeFromElems( result, tmpX, tmpY, tmpZ ); +} + +static inline void vmathSoaT3MulP3( VmathSoaPoint3 *result, const VmathSoaTransform3 *tfrm, const VmathSoaPoint3 *pnt ) +{ + vec_float4 tmpX, tmpY, tmpZ; + tmpX = vec_add( vec_add( vec_add( vec_madd( tfrm->col0.x, pnt->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tfrm->col1.x, pnt->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tfrm->col2.x, pnt->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), tfrm->col3.x ); + tmpY = vec_add( vec_add( vec_add( vec_madd( tfrm->col0.y, pnt->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tfrm->col1.y, pnt->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tfrm->col2.y, pnt->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), tfrm->col3.y ); + tmpZ = vec_add( vec_add( vec_add( vec_madd( tfrm->col0.z, pnt->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tfrm->col1.z, pnt->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tfrm->col2.z, pnt->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), tfrm->col3.z ); + vmathSoaP3MakeFromElems( result, tmpX, tmpY, tmpZ ); +} + +static inline void vmathSoaT3Mul( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm0, const VmathSoaTransform3 *tfrm1 ) +{ + VmathSoaTransform3 tmpResult; + VmathSoaPoint3 tmpP3_0, tmpP3_1; + vmathSoaT3MulV3( &tmpResult.col0, tfrm0, &tfrm1->col0 ); + vmathSoaT3MulV3( &tmpResult.col1, tfrm0, &tfrm1->col1 ); + vmathSoaT3MulV3( &tmpResult.col2, tfrm0, &tfrm1->col2 ); + vmathSoaP3MakeFromV3( &tmpP3_0, &tfrm1->col3 ); + vmathSoaT3MulP3( &tmpP3_1, tfrm0, &tmpP3_0 ); + vmathSoaV3MakeFromP3( &tmpResult.col3, &tmpP3_1 ); + vmathSoaT3Copy( result, &tmpResult ); +} + +static inline void vmathSoaT3MulPerElem( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm0, const VmathSoaTransform3 *tfrm1 ) +{ + vmathSoaV3MulPerElem( &result->col0, &tfrm0->col0, &tfrm1->col0 ); + vmathSoaV3MulPerElem( &result->col1, &tfrm0->col1, &tfrm1->col1 ); + vmathSoaV3MulPerElem( &result->col2, &tfrm0->col2, &tfrm1->col2 ); + vmathSoaV3MulPerElem( &result->col3, &tfrm0->col3, &tfrm1->col3 ); +} + +static inline void vmathSoaT3MakeIdentity( VmathSoaTransform3 *result ) +{ + vmathSoaV3MakeXAxis( &result->col0 ); + vmathSoaV3MakeYAxis( &result->col1 ); + vmathSoaV3MakeZAxis( &result->col2 ); + vmathSoaV3MakeFromScalar( &result->col3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaT3SetUpper3x3( VmathSoaTransform3 *result, const VmathSoaMatrix3 *tfrm ) +{ + vmathSoaV3Copy( &result->col0, &tfrm->col0 ); + vmathSoaV3Copy( &result->col1, &tfrm->col1 ); + vmathSoaV3Copy( &result->col2, &tfrm->col2 ); +} + +static inline void vmathSoaT3GetUpper3x3( VmathSoaMatrix3 *result, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaM3MakeFromCols( result, &tfrm->col0, &tfrm->col1, &tfrm->col2 ); +} + +static inline void vmathSoaT3SetTranslation( VmathSoaTransform3 *result, const VmathSoaVector3 *translateVec ) +{ + vmathSoaV3Copy( &result->col3, translateVec ); +} + +static inline void vmathSoaT3GetTranslation( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaV3Copy( result, &tfrm->col3 ); +} + +static inline void vmathSoaT3MakeRotationX( VmathSoaTransform3 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV3MakeXAxis( &result->col0 ); + vmathSoaV3MakeFromElems( &result->col1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), c, s ); + vmathSoaV3MakeFromElems( &result->col2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), negatef4( s ), c ); + vmathSoaV3MakeFromScalar( &result->col3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaT3MakeRotationY( VmathSoaTransform3 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV3MakeFromElems( &result->col0, c, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), negatef4( s ) ); + vmathSoaV3MakeYAxis( &result->col1 ); + vmathSoaV3MakeFromElems( &result->col2, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), c ); + vmathSoaV3MakeFromScalar( &result->col3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaT3MakeRotationZ( VmathSoaTransform3 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV3MakeFromElems( &result->col0, c, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV3MakeFromElems( &result->col1, negatef4( s ), c, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV3MakeZAxis( &result->col2 ); + vmathSoaV3MakeFromScalar( &result->col3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaT3MakeRotationZYX( VmathSoaTransform3 *result, const VmathSoaVector3 *radiansXYZ ) +{ + vec_float4 sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sincosf4( radiansXYZ->x, &sX, &cX ); + sincosf4( radiansXYZ->y, &sY, &cY ); + sincosf4( radiansXYZ->z, &sZ, &cZ ); + tmp0 = vec_madd( cZ, sY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + tmp1 = vec_madd( sZ, sY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV3MakeFromElems( &result->col0, vec_madd( cZ, cY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, cY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), negatef4( sY ) ); + vmathSoaV3MakeFromElems( &result->col1, vec_sub( vec_madd( tmp0, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_add( vec_madd( tmp1, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( cZ, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( cY, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV3MakeFromElems( &result->col2, vec_add( vec_madd( tmp0, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_sub( vec_madd( tmp1, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( cZ, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( cY, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV3MakeFromScalar( &result->col3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaT3MakeRotationAxis( VmathSoaTransform3 *result, vec_float4 radians, const VmathSoaVector3 *unitVec ) +{ + VmathSoaMatrix3 tmpM3_0; + VmathSoaVector3 tmpV3_0; + vmathSoaM3MakeRotationAxis( &tmpM3_0, radians, unitVec ); + vmathSoaV3MakeFromScalar( &tmpV3_0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaT3MakeFromM3V3( result, &tmpM3_0, &tmpV3_0 ); +} + +static inline void vmathSoaT3MakeRotationQ( VmathSoaTransform3 *result, const VmathSoaQuat *unitQuat ) +{ + VmathSoaMatrix3 tmpM3_0; + VmathSoaVector3 tmpV3_0; + vmathSoaM3MakeFromQ( &tmpM3_0, unitQuat ); + vmathSoaV3MakeFromScalar( &tmpV3_0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaT3MakeFromM3V3( result, &tmpM3_0, &tmpV3_0 ); +} + +static inline void vmathSoaT3MakeScale( VmathSoaTransform3 *result, const VmathSoaVector3 *scaleVec ) +{ + vmathSoaV3MakeFromElems( &result->col0, scaleVec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV3MakeFromElems( &result->col1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), scaleVec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathSoaV3MakeFromElems( &result->col2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), scaleVec->z ); + vmathSoaV3MakeFromScalar( &result->col3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaT3AppendScale( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm, const VmathSoaVector3 *scaleVec ) +{ + vmathSoaV3ScalarMul( &result->col0, &tfrm->col0, vmathSoaV3GetX( scaleVec ) ); + vmathSoaV3ScalarMul( &result->col1, &tfrm->col1, vmathSoaV3GetY( scaleVec ) ); + vmathSoaV3ScalarMul( &result->col2, &tfrm->col2, vmathSoaV3GetZ( scaleVec ) ); + vmathSoaV3Copy( &result->col3, &tfrm->col3 ); +} + +static inline void vmathSoaT3PrependScale( VmathSoaTransform3 *result, const VmathSoaVector3 *scaleVec, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaV3MulPerElem( &result->col0, &tfrm->col0, scaleVec ); + vmathSoaV3MulPerElem( &result->col1, &tfrm->col1, scaleVec ); + vmathSoaV3MulPerElem( &result->col2, &tfrm->col2, scaleVec ); + vmathSoaV3MulPerElem( &result->col3, &tfrm->col3, scaleVec ); +} + +static inline void vmathSoaT3MakeTranslation( VmathSoaTransform3 *result, const VmathSoaVector3 *translateVec ) +{ + vmathSoaV3MakeXAxis( &result->col0 ); + vmathSoaV3MakeYAxis( &result->col1 ); + vmathSoaV3MakeZAxis( &result->col2 ); + vmathSoaV3Copy( &result->col3, translateVec ); +} + +static inline void vmathSoaT3Select( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm0, const VmathSoaTransform3 *tfrm1, vec_uint4 select1 ) +{ + vmathSoaV3Select( &result->col0, &tfrm0->col0, &tfrm1->col0, select1 ); + vmathSoaV3Select( &result->col1, &tfrm0->col1, &tfrm1->col1, select1 ); + vmathSoaV3Select( &result->col2, &tfrm0->col2, &tfrm1->col2, select1 ); + vmathSoaV3Select( &result->col3, &tfrm0->col3, &tfrm1->col3, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaT3Print( const VmathSoaTransform3 *tfrm ) +{ + VmathTransform3 mat0, mat1, mat2, mat3; + vmathSoaT3Get4Aos( tfrm, &mat0, &mat1, &mat2, &mat3 ); + printf("slot 0:\n"); + vmathT3Print( &mat0 ); + printf("slot 1:\n"); + vmathT3Print( &mat1 ); + printf("slot 2:\n"); + vmathT3Print( &mat2 ); + printf("slot 3:\n"); + vmathT3Print( &mat3 ); +} + +static inline void vmathSoaT3Prints( const VmathSoaTransform3 *tfrm, const char *name ) +{ + printf("%s:\n", name); + vmathSoaT3Print( tfrm ); +} + +#endif + +static inline void vmathSoaQMakeFromM3( VmathSoaQuat *result, const VmathSoaMatrix3 *tfrm ) +{ + vec_float4 trace, radicand, scale, xx, yx, zx, xy, yy, zy, xz, yz, zz, tmpx, tmpy, tmpz, tmpw, qx, qy, qz, qw; + vec_uint4 negTrace, ZgtX, ZgtY, YgtX; + vec_uint4 largestXorY, largestYorZ, largestZorX; + + xx = tfrm->col0.x; + yx = tfrm->col0.y; + zx = tfrm->col0.z; + xy = tfrm->col1.x; + yy = tfrm->col1.y; + zy = tfrm->col1.z; + xz = tfrm->col2.x; + yz = tfrm->col2.y; + zz = tfrm->col2.z; + + trace = vec_add( vec_add( xx, yy ), zz ); + + negTrace = (vec_uint4)vec_cmpgt( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), trace ); + ZgtX = (vec_uint4)vec_cmpgt( zz, xx ); + ZgtY = (vec_uint4)vec_cmpgt( zz, yy ); + YgtX = (vec_uint4)vec_cmpgt( yy, xx ); + largestXorY = vec_andc( negTrace, vec_and( ZgtX, ZgtY ) ); + largestYorZ = vec_and( negTrace, vec_or( YgtX, ZgtX ) ); + largestZorX = vec_andc( negTrace, vec_andc( YgtX, ZgtY ) ); + + zz = vec_sel( zz, negatef4(zz), largestXorY ); + xy = vec_sel( xy, negatef4(xy), largestXorY ); + xx = vec_sel( xx, negatef4(xx), largestYorZ ); + yz = vec_sel( yz, negatef4(yz), largestYorZ ); + yy = vec_sel( yy, negatef4(yy), largestZorX ); + zx = vec_sel( zx, negatef4(zx), largestZorX ); + + radicand = vec_add( vec_add( vec_add( xx, yy ), zz ), ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); + scale = vec_madd( ((vec_float4){0.5f,0.5f,0.5f,0.5f}), divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( radicand ) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + + tmpx = vec_madd( vec_sub( zy, yz ), scale, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + tmpy = vec_madd( vec_sub( xz, zx ), scale, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + tmpz = vec_madd( vec_sub( yx, xy ), scale, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + tmpw = vec_madd( radicand, scale, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qx = tmpx; + qy = tmpy; + qz = tmpz; + qw = tmpw; + + qx = vec_sel( qx, tmpw, largestXorY ); + qy = vec_sel( qy, tmpz, largestXorY ); + qz = vec_sel( qz, tmpy, largestXorY ); + qw = vec_sel( qw, tmpx, largestXorY ); + tmpx = qx; + tmpz = qz; + qx = vec_sel( qx, qy, largestYorZ ); + qy = vec_sel( qy, tmpx, largestYorZ ); + qz = vec_sel( qz, qw, largestYorZ ); + qw = vec_sel( qw, tmpz, largestYorZ ); + + result->x = qx; + result->y = qy; + result->z = qz; + result->w = qw; +} + +static inline void vmathSoaV3Outer( VmathSoaMatrix3 *result, const VmathSoaVector3 *tfrm0, const VmathSoaVector3 *tfrm1 ) +{ + vmathSoaV3ScalarMul( &result->col0, tfrm0, vmathSoaV3GetX( tfrm1 ) ); + vmathSoaV3ScalarMul( &result->col1, tfrm0, vmathSoaV3GetY( tfrm1 ) ); + vmathSoaV3ScalarMul( &result->col2, tfrm0, vmathSoaV3GetZ( tfrm1 ) ); +} + +static inline void vmathSoaV4Outer( VmathSoaMatrix4 *result, const VmathSoaVector4 *tfrm0, const VmathSoaVector4 *tfrm1 ) +{ + vmathSoaV4ScalarMul( &result->col0, tfrm0, vmathSoaV4GetX( tfrm1 ) ); + vmathSoaV4ScalarMul( &result->col1, tfrm0, vmathSoaV4GetY( tfrm1 ) ); + vmathSoaV4ScalarMul( &result->col2, tfrm0, vmathSoaV4GetZ( tfrm1 ) ); + vmathSoaV4ScalarMul( &result->col3, tfrm0, vmathSoaV4GetW( tfrm1 ) ); +} + +static inline void vmathSoaV3RowMul( VmathSoaVector3 *result, const VmathSoaVector3 *vec, const VmathSoaMatrix3 *mat ) +{ + vec_float4 tmpX, tmpY, tmpZ; + tmpX = vec_add( vec_add( vec_madd( vec->x, mat->col0.x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( vec->y, mat->col0.y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( vec->z, mat->col0.z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpY = vec_add( vec_add( vec_madd( vec->x, mat->col1.x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( vec->y, mat->col1.y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( vec->z, mat->col1.z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpZ = vec_add( vec_add( vec_madd( vec->x, mat->col2.x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( vec->y, mat->col2.y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( vec->z, mat->col2.z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV3MakeFromElems( result, tmpX, tmpY, tmpZ ); +} + +static inline void vmathSoaV3CrossMatrix( VmathSoaMatrix3 *result, const VmathSoaVector3 *vec ) +{ + vmathSoaV3MakeFromElems( &result->col0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), vec->z, negatef4( vec->y ) ); + vmathSoaV3MakeFromElems( &result->col1, negatef4( vec->z ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), vec->x ); + vmathSoaV3MakeFromElems( &result->col2, vec->y, negatef4( vec->x ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaV3CrossMatrixMul( VmathSoaMatrix3 *result, const VmathSoaVector3 *vec, const VmathSoaMatrix3 *mat ) +{ + VmathSoaVector3 tmpV3_0, tmpV3_1, tmpV3_2; + vmathSoaV3Cross( &tmpV3_0, vec, &mat->col0 ); + vmathSoaV3Cross( &tmpV3_1, vec, &mat->col1 ); + vmathSoaV3Cross( &tmpV3_2, vec, &mat->col2 ); + vmathSoaM3MakeFromCols( result, &tmpV3_0, &tmpV3_1, &tmpV3_2 ); +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/mat_soa_v.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/mat_soa_v.h new file mode 100644 index 0000000..c8401e3 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/mat_soa_v.h @@ -0,0 +1,1063 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_SOA_V_C_H +#define _VECTORMATH_MAT_SOA_V_C_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + */ +#define _VECTORMATH_PI_OVER_2 1.570796327f + +/*----------------------------------------------------------------------------- + * Definitions + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeFromScalar_V( vec_float4 scalar ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeFromQ_V( VmathSoaQuat unitQuat ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeFromQ(&result, &unitQuat); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeFromCols_V( VmathSoaVector3 _col0, VmathSoaVector3 _col1, VmathSoaVector3 _col2 ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeFromCols(&result, &_col0, &_col1, &_col2); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeFromAos_V( VmathMatrix3 mat ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeFromAos(&result, &mat); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeFrom4Aos_V( VmathMatrix3 mat0, VmathMatrix3 mat1, VmathMatrix3 mat2, VmathMatrix3 mat3 ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeFrom4Aos(&result, &mat0, &mat1, &mat2, &mat3); + return result; +} + +static inline void vmathSoaM3Get4Aos_V( VmathSoaMatrix3 mat, VmathMatrix3 *result0, VmathMatrix3 *result1, VmathMatrix3 *result2, VmathMatrix3 *result3 ) +{ + vmathSoaM3Get4Aos(&mat, result0, result1, result2, result3); +} + +static inline void vmathSoaM3SetCol0_V( VmathSoaMatrix3 *result, VmathSoaVector3 _col0 ) +{ + vmathSoaM3SetCol0(result, &_col0); +} + +static inline void vmathSoaM3SetCol1_V( VmathSoaMatrix3 *result, VmathSoaVector3 _col1 ) +{ + vmathSoaM3SetCol1(result, &_col1); +} + +static inline void vmathSoaM3SetCol2_V( VmathSoaMatrix3 *result, VmathSoaVector3 _col2 ) +{ + vmathSoaM3SetCol2(result, &_col2); +} + +static inline void vmathSoaM3SetCol_V( VmathSoaMatrix3 *result, int col, VmathSoaVector3 vec ) +{ + vmathSoaM3SetCol(result, col, &vec); +} + +static inline void vmathSoaM3SetRow_V( VmathSoaMatrix3 *result, int row, VmathSoaVector3 vec ) +{ + vmathSoaM3SetRow(result, row, &vec); +} + +static inline void vmathSoaM3SetElem_V( VmathSoaMatrix3 *result, int col, int row, vec_float4 val ) +{ + vmathSoaM3SetElem(result, col, row, val); +} + +static inline vec_float4 vmathSoaM3GetElem_V( VmathSoaMatrix3 mat, int col, int row ) +{ + return vmathSoaM3GetElem(&mat, col, row); +} + +static inline VmathSoaVector3 vmathSoaM3GetCol0_V( VmathSoaMatrix3 mat ) +{ + VmathSoaVector3 result; + vmathSoaM3GetCol0(&result, &mat); + return result; +} + +static inline VmathSoaVector3 vmathSoaM3GetCol1_V( VmathSoaMatrix3 mat ) +{ + VmathSoaVector3 result; + vmathSoaM3GetCol1(&result, &mat); + return result; +} + +static inline VmathSoaVector3 vmathSoaM3GetCol2_V( VmathSoaMatrix3 mat ) +{ + VmathSoaVector3 result; + vmathSoaM3GetCol2(&result, &mat); + return result; +} + +static inline VmathSoaVector3 vmathSoaM3GetCol_V( VmathSoaMatrix3 mat, int col ) +{ + VmathSoaVector3 result; + vmathSoaM3GetCol(&result, &mat, col); + return result; +} + +static inline VmathSoaVector3 vmathSoaM3GetRow_V( VmathSoaMatrix3 mat, int row ) +{ + VmathSoaVector3 result; + vmathSoaM3GetRow(&result, &mat, row); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3Transpose_V( VmathSoaMatrix3 mat ) +{ + VmathSoaMatrix3 result; + vmathSoaM3Transpose(&result, &mat); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3Inverse_V( VmathSoaMatrix3 mat ) +{ + VmathSoaMatrix3 result; + vmathSoaM3Inverse(&result, &mat); + return result; +} + +static inline vec_float4 vmathSoaM3Determinant_V( VmathSoaMatrix3 mat ) +{ + return vmathSoaM3Determinant(&mat); +} + +static inline VmathSoaMatrix3 vmathSoaM3Add_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1 ) +{ + VmathSoaMatrix3 result; + vmathSoaM3Add(&result, &mat0, &mat1); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3Sub_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1 ) +{ + VmathSoaMatrix3 result; + vmathSoaM3Sub(&result, &mat0, &mat1); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3Neg_V( VmathSoaMatrix3 mat ) +{ + VmathSoaMatrix3 result; + vmathSoaM3Neg(&result, &mat); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3AbsPerElem_V( VmathSoaMatrix3 mat ) +{ + VmathSoaMatrix3 result; + vmathSoaM3AbsPerElem(&result, &mat); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3ScalarMul_V( VmathSoaMatrix3 mat, vec_float4 scalar ) +{ + VmathSoaMatrix3 result; + vmathSoaM3ScalarMul(&result, &mat, scalar); + return result; +} + +static inline VmathSoaVector3 vmathSoaM3MulV3_V( VmathSoaMatrix3 mat, VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaM3MulV3(&result, &mat, &vec); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3Mul_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1 ) +{ + VmathSoaMatrix3 result; + vmathSoaM3Mul(&result, &mat0, &mat1); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MulPerElem_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1 ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MulPerElem(&result, &mat0, &mat1); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeIdentity_V( ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeIdentity(&result); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationX_V( vec_float4 radians ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeRotationX(&result, radians); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationY_V( vec_float4 radians ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeRotationY(&result, radians); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationZ_V( vec_float4 radians ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeRotationZ(&result, radians); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationZYX_V( VmathSoaVector3 radiansXYZ ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeRotationZYX(&result, &radiansXYZ); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationAxis_V( vec_float4 radians, VmathSoaVector3 unitVec ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationQ_V( VmathSoaQuat unitQuat ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeRotationQ(&result, &unitQuat); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeScale_V( VmathSoaVector3 scaleVec ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeScale(&result, &scaleVec); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3AppendScale_V( VmathSoaMatrix3 mat, VmathSoaVector3 scaleVec ) +{ + VmathSoaMatrix3 result; + vmathSoaM3AppendScale(&result, &mat, &scaleVec); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3PrependScale_V( VmathSoaVector3 scaleVec, VmathSoaMatrix3 mat ) +{ + VmathSoaMatrix3 result; + vmathSoaM3PrependScale(&result, &scaleVec, &mat); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3Select_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1, vec_uint4 select1 ) +{ + VmathSoaMatrix3 result; + vmathSoaM3Select(&result, &mat0, &mat1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaM3Print_V( VmathSoaMatrix3 mat ) +{ + vmathSoaM3Print(&mat); +} + +static inline void vmathSoaM3Prints_V( VmathSoaMatrix3 mat, const char *name ) +{ + vmathSoaM3Prints(&mat, name); +} + +#endif + +static inline VmathSoaMatrix4 vmathSoaM4MakeFromScalar_V( vec_float4 scalar ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeFromT3_V( VmathSoaTransform3 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeFromT3(&result, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeFromCols_V( VmathSoaVector4 _col0, VmathSoaVector4 _col1, VmathSoaVector4 _col2, VmathSoaVector4 _col3 ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeFromCols(&result, &_col0, &_col1, &_col2, &_col3); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeFromM3V3_V( VmathSoaMatrix3 mat, VmathSoaVector3 translateVec ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeFromM3V3(&result, &mat, &translateVec); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeFromQV3_V( VmathSoaQuat unitQuat, VmathSoaVector3 translateVec ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeFromQV3(&result, &unitQuat, &translateVec); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeFromAos_V( VmathMatrix4 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeFromAos(&result, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeFrom4Aos_V( VmathMatrix4 mat0, VmathMatrix4 mat1, VmathMatrix4 mat2, VmathMatrix4 mat3 ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeFrom4Aos(&result, &mat0, &mat1, &mat2, &mat3); + return result; +} + +static inline void vmathSoaM4Get4Aos_V( VmathSoaMatrix4 mat, VmathMatrix4 *result0, VmathMatrix4 *result1, VmathMatrix4 *result2, VmathMatrix4 *result3 ) +{ + vmathSoaM4Get4Aos(&mat, result0, result1, result2, result3); +} + +static inline void vmathSoaM4SetCol0_V( VmathSoaMatrix4 *result, VmathSoaVector4 _col0 ) +{ + vmathSoaM4SetCol0(result, &_col0); +} + +static inline void vmathSoaM4SetCol1_V( VmathSoaMatrix4 *result, VmathSoaVector4 _col1 ) +{ + vmathSoaM4SetCol1(result, &_col1); +} + +static inline void vmathSoaM4SetCol2_V( VmathSoaMatrix4 *result, VmathSoaVector4 _col2 ) +{ + vmathSoaM4SetCol2(result, &_col2); +} + +static inline void vmathSoaM4SetCol3_V( VmathSoaMatrix4 *result, VmathSoaVector4 _col3 ) +{ + vmathSoaM4SetCol3(result, &_col3); +} + +static inline void vmathSoaM4SetCol_V( VmathSoaMatrix4 *result, int col, VmathSoaVector4 vec ) +{ + vmathSoaM4SetCol(result, col, &vec); +} + +static inline void vmathSoaM4SetRow_V( VmathSoaMatrix4 *result, int row, VmathSoaVector4 vec ) +{ + vmathSoaM4SetRow(result, row, &vec); +} + +static inline void vmathSoaM4SetElem_V( VmathSoaMatrix4 *result, int col, int row, vec_float4 val ) +{ + vmathSoaM4SetElem(result, col, row, val); +} + +static inline vec_float4 vmathSoaM4GetElem_V( VmathSoaMatrix4 mat, int col, int row ) +{ + return vmathSoaM4GetElem(&mat, col, row); +} + +static inline VmathSoaVector4 vmathSoaM4GetCol0_V( VmathSoaMatrix4 mat ) +{ + VmathSoaVector4 result; + vmathSoaM4GetCol0(&result, &mat); + return result; +} + +static inline VmathSoaVector4 vmathSoaM4GetCol1_V( VmathSoaMatrix4 mat ) +{ + VmathSoaVector4 result; + vmathSoaM4GetCol1(&result, &mat); + return result; +} + +static inline VmathSoaVector4 vmathSoaM4GetCol2_V( VmathSoaMatrix4 mat ) +{ + VmathSoaVector4 result; + vmathSoaM4GetCol2(&result, &mat); + return result; +} + +static inline VmathSoaVector4 vmathSoaM4GetCol3_V( VmathSoaMatrix4 mat ) +{ + VmathSoaVector4 result; + vmathSoaM4GetCol3(&result, &mat); + return result; +} + +static inline VmathSoaVector4 vmathSoaM4GetCol_V( VmathSoaMatrix4 mat, int col ) +{ + VmathSoaVector4 result; + vmathSoaM4GetCol(&result, &mat, col); + return result; +} + +static inline VmathSoaVector4 vmathSoaM4GetRow_V( VmathSoaMatrix4 mat, int row ) +{ + VmathSoaVector4 result; + vmathSoaM4GetRow(&result, &mat, row); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4Transpose_V( VmathSoaMatrix4 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4Transpose(&result, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4Inverse_V( VmathSoaMatrix4 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4Inverse(&result, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4AffineInverse_V( VmathSoaMatrix4 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4AffineInverse(&result, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4OrthoInverse_V( VmathSoaMatrix4 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4OrthoInverse(&result, &mat); + return result; +} + +static inline vec_float4 vmathSoaM4Determinant_V( VmathSoaMatrix4 mat ) +{ + return vmathSoaM4Determinant(&mat); +} + +static inline VmathSoaMatrix4 vmathSoaM4Add_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1 ) +{ + VmathSoaMatrix4 result; + vmathSoaM4Add(&result, &mat0, &mat1); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4Sub_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1 ) +{ + VmathSoaMatrix4 result; + vmathSoaM4Sub(&result, &mat0, &mat1); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4Neg_V( VmathSoaMatrix4 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4Neg(&result, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4AbsPerElem_V( VmathSoaMatrix4 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4AbsPerElem(&result, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4ScalarMul_V( VmathSoaMatrix4 mat, vec_float4 scalar ) +{ + VmathSoaMatrix4 result; + vmathSoaM4ScalarMul(&result, &mat, scalar); + return result; +} + +static inline VmathSoaVector4 vmathSoaM4MulV4_V( VmathSoaMatrix4 mat, VmathSoaVector4 vec ) +{ + VmathSoaVector4 result; + vmathSoaM4MulV4(&result, &mat, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaM4MulV3_V( VmathSoaMatrix4 mat, VmathSoaVector3 vec ) +{ + VmathSoaVector4 result; + vmathSoaM4MulV3(&result, &mat, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaM4MulP3_V( VmathSoaMatrix4 mat, VmathSoaPoint3 pnt ) +{ + VmathSoaVector4 result; + vmathSoaM4MulP3(&result, &mat, &pnt); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4Mul_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1 ) +{ + VmathSoaMatrix4 result; + vmathSoaM4Mul(&result, &mat0, &mat1); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MulT3_V( VmathSoaMatrix4 mat, VmathSoaTransform3 tfrm1 ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MulT3(&result, &mat, &tfrm1); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MulPerElem_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1 ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MulPerElem(&result, &mat0, &mat1); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeIdentity_V( ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeIdentity(&result); + return result; +} + +static inline void vmathSoaM4SetUpper3x3_V( VmathSoaMatrix4 *result, VmathSoaMatrix3 mat3 ) +{ + vmathSoaM4SetUpper3x3(result, &mat3); +} + +static inline VmathSoaMatrix3 vmathSoaM4GetUpper3x3_V( VmathSoaMatrix4 mat ) +{ + VmathSoaMatrix3 result; + vmathSoaM4GetUpper3x3(&result, &mat); + return result; +} + +static inline void vmathSoaM4SetTranslation_V( VmathSoaMatrix4 *result, VmathSoaVector3 translateVec ) +{ + vmathSoaM4SetTranslation(result, &translateVec); +} + +static inline VmathSoaVector3 vmathSoaM4GetTranslation_V( VmathSoaMatrix4 mat ) +{ + VmathSoaVector3 result; + vmathSoaM4GetTranslation(&result, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationX_V( vec_float4 radians ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeRotationX(&result, radians); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationY_V( vec_float4 radians ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeRotationY(&result, radians); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationZ_V( vec_float4 radians ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeRotationZ(&result, radians); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationZYX_V( VmathSoaVector3 radiansXYZ ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeRotationZYX(&result, &radiansXYZ); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationAxis_V( vec_float4 radians, VmathSoaVector3 unitVec ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationQ_V( VmathSoaQuat unitQuat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeRotationQ(&result, &unitQuat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeScale_V( VmathSoaVector3 scaleVec ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeScale(&result, &scaleVec); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4AppendScale_V( VmathSoaMatrix4 mat, VmathSoaVector3 scaleVec ) +{ + VmathSoaMatrix4 result; + vmathSoaM4AppendScale(&result, &mat, &scaleVec); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4PrependScale_V( VmathSoaVector3 scaleVec, VmathSoaMatrix4 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4PrependScale(&result, &scaleVec, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeTranslation_V( VmathSoaVector3 translateVec ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeTranslation(&result, &translateVec); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeLookAt_V( VmathSoaPoint3 eyePos, VmathSoaPoint3 lookAtPos, VmathSoaVector3 upVec ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeLookAt(&result, &eyePos, &lookAtPos, &upVec); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakePerspective_V( vec_float4 fovyRadians, vec_float4 aspect, vec_float4 zNear, vec_float4 zFar ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakePerspective(&result, fovyRadians, aspect, zNear, zFar); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeFrustum_V( vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeFrustum(&result, left, right, bottom, top, zNear, zFar); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeOrthographic_V( vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeOrthographic(&result, left, right, bottom, top, zNear, zFar); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4Select_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1, vec_uint4 select1 ) +{ + VmathSoaMatrix4 result; + vmathSoaM4Select(&result, &mat0, &mat1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaM4Print_V( VmathSoaMatrix4 mat ) +{ + vmathSoaM4Print(&mat); +} + +static inline void vmathSoaM4Prints_V( VmathSoaMatrix4 mat, const char *name ) +{ + vmathSoaM4Prints(&mat, name); +} + +#endif + +static inline VmathSoaTransform3 vmathSoaT3MakeFromScalar_V( vec_float4 scalar ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeFromCols_V( VmathSoaVector3 _col0, VmathSoaVector3 _col1, VmathSoaVector3 _col2, VmathSoaVector3 _col3 ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeFromCols(&result, &_col0, &_col1, &_col2, &_col3); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeFromM3V3_V( VmathSoaMatrix3 tfrm, VmathSoaVector3 translateVec ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeFromM3V3(&result, &tfrm, &translateVec); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeFromQV3_V( VmathSoaQuat unitQuat, VmathSoaVector3 translateVec ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeFromQV3(&result, &unitQuat, &translateVec); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeFromAos_V( VmathTransform3 tfrm ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeFromAos(&result, &tfrm); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeFrom4Aos_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1, VmathTransform3 tfrm2, VmathTransform3 tfrm3 ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeFrom4Aos(&result, &tfrm0, &tfrm1, &tfrm2, &tfrm3); + return result; +} + +static inline void vmathSoaT3Get4Aos_V( VmathSoaTransform3 tfrm, VmathTransform3 *result0, VmathTransform3 *result1, VmathTransform3 *result2, VmathTransform3 *result3 ) +{ + vmathSoaT3Get4Aos(&tfrm, result0, result1, result2, result3); +} + +static inline void vmathSoaT3SetCol0_V( VmathSoaTransform3 *result, VmathSoaVector3 _col0 ) +{ + vmathSoaT3SetCol0(result, &_col0); +} + +static inline void vmathSoaT3SetCol1_V( VmathSoaTransform3 *result, VmathSoaVector3 _col1 ) +{ + vmathSoaT3SetCol1(result, &_col1); +} + +static inline void vmathSoaT3SetCol2_V( VmathSoaTransform3 *result, VmathSoaVector3 _col2 ) +{ + vmathSoaT3SetCol2(result, &_col2); +} + +static inline void vmathSoaT3SetCol3_V( VmathSoaTransform3 *result, VmathSoaVector3 _col3 ) +{ + vmathSoaT3SetCol3(result, &_col3); +} + +static inline void vmathSoaT3SetCol_V( VmathSoaTransform3 *result, int col, VmathSoaVector3 vec ) +{ + vmathSoaT3SetCol(result, col, &vec); +} + +static inline void vmathSoaT3SetRow_V( VmathSoaTransform3 *result, int row, VmathSoaVector4 vec ) +{ + vmathSoaT3SetRow(result, row, &vec); +} + +static inline void vmathSoaT3SetElem_V( VmathSoaTransform3 *result, int col, int row, vec_float4 val ) +{ + vmathSoaT3SetElem(result, col, row, val); +} + +static inline vec_float4 vmathSoaT3GetElem_V( VmathSoaTransform3 tfrm, int col, int row ) +{ + return vmathSoaT3GetElem(&tfrm, col, row); +} + +static inline VmathSoaVector3 vmathSoaT3GetCol0_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaVector3 result; + vmathSoaT3GetCol0(&result, &tfrm); + return result; +} + +static inline VmathSoaVector3 vmathSoaT3GetCol1_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaVector3 result; + vmathSoaT3GetCol1(&result, &tfrm); + return result; +} + +static inline VmathSoaVector3 vmathSoaT3GetCol2_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaVector3 result; + vmathSoaT3GetCol2(&result, &tfrm); + return result; +} + +static inline VmathSoaVector3 vmathSoaT3GetCol3_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaVector3 result; + vmathSoaT3GetCol3(&result, &tfrm); + return result; +} + +static inline VmathSoaVector3 vmathSoaT3GetCol_V( VmathSoaTransform3 tfrm, int col ) +{ + VmathSoaVector3 result; + vmathSoaT3GetCol(&result, &tfrm, col); + return result; +} + +static inline VmathSoaVector4 vmathSoaT3GetRow_V( VmathSoaTransform3 tfrm, int row ) +{ + VmathSoaVector4 result; + vmathSoaT3GetRow(&result, &tfrm, row); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3Inverse_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaTransform3 result; + vmathSoaT3Inverse(&result, &tfrm); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3OrthoInverse_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaTransform3 result; + vmathSoaT3OrthoInverse(&result, &tfrm); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3AbsPerElem_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaTransform3 result; + vmathSoaT3AbsPerElem(&result, &tfrm); + return result; +} + +static inline VmathSoaVector3 vmathSoaT3MulV3_V( VmathSoaTransform3 tfrm, VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaT3MulV3(&result, &tfrm, &vec); + return result; +} + +static inline VmathSoaPoint3 vmathSoaT3MulP3_V( VmathSoaTransform3 tfrm, VmathSoaPoint3 pnt ) +{ + VmathSoaPoint3 result; + vmathSoaT3MulP3(&result, &tfrm, &pnt); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3Mul_V( VmathSoaTransform3 tfrm0, VmathSoaTransform3 tfrm1 ) +{ + VmathSoaTransform3 result; + vmathSoaT3Mul(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MulPerElem_V( VmathSoaTransform3 tfrm0, VmathSoaTransform3 tfrm1 ) +{ + VmathSoaTransform3 result; + vmathSoaT3MulPerElem(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeIdentity_V( ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeIdentity(&result); + return result; +} + +static inline void vmathSoaT3SetUpper3x3_V( VmathSoaTransform3 *result, VmathSoaMatrix3 tfrm ) +{ + vmathSoaT3SetUpper3x3(result, &tfrm); +} + +static inline VmathSoaMatrix3 vmathSoaT3GetUpper3x3_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaMatrix3 result; + vmathSoaT3GetUpper3x3(&result, &tfrm); + return result; +} + +static inline void vmathSoaT3SetTranslation_V( VmathSoaTransform3 *result, VmathSoaVector3 translateVec ) +{ + vmathSoaT3SetTranslation(result, &translateVec); +} + +static inline VmathSoaVector3 vmathSoaT3GetTranslation_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaVector3 result; + vmathSoaT3GetTranslation(&result, &tfrm); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeRotationX_V( vec_float4 radians ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeRotationX(&result, radians); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeRotationY_V( vec_float4 radians ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeRotationY(&result, radians); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeRotationZ_V( vec_float4 radians ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeRotationZ(&result, radians); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeRotationZYX_V( VmathSoaVector3 radiansXYZ ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeRotationZYX(&result, &radiansXYZ); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeRotationAxis_V( vec_float4 radians, VmathSoaVector3 unitVec ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeRotationQ_V( VmathSoaQuat unitQuat ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeRotationQ(&result, &unitQuat); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeScale_V( VmathSoaVector3 scaleVec ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeScale(&result, &scaleVec); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3AppendScale_V( VmathSoaTransform3 tfrm, VmathSoaVector3 scaleVec ) +{ + VmathSoaTransform3 result; + vmathSoaT3AppendScale(&result, &tfrm, &scaleVec); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3PrependScale_V( VmathSoaVector3 scaleVec, VmathSoaTransform3 tfrm ) +{ + VmathSoaTransform3 result; + vmathSoaT3PrependScale(&result, &scaleVec, &tfrm); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeTranslation_V( VmathSoaVector3 translateVec ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeTranslation(&result, &translateVec); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3Select_V( VmathSoaTransform3 tfrm0, VmathSoaTransform3 tfrm1, vec_uint4 select1 ) +{ + VmathSoaTransform3 result; + vmathSoaT3Select(&result, &tfrm0, &tfrm1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaT3Print_V( VmathSoaTransform3 tfrm ) +{ + vmathSoaT3Print(&tfrm); +} + +static inline void vmathSoaT3Prints_V( VmathSoaTransform3 tfrm, const char *name ) +{ + vmathSoaT3Prints(&tfrm, name); +} + +#endif + +static inline VmathSoaQuat vmathSoaQMakeFromM3_V( VmathSoaMatrix3 tfrm ) +{ + VmathSoaQuat result; + vmathSoaQMakeFromM3(&result, &tfrm); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaV3Outer_V( VmathSoaVector3 tfrm0, VmathSoaVector3 tfrm1 ) +{ + VmathSoaMatrix3 result; + vmathSoaV3Outer(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaV4Outer_V( VmathSoaVector4 tfrm0, VmathSoaVector4 tfrm1 ) +{ + VmathSoaMatrix4 result; + vmathSoaV4Outer(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3RowMul_V( VmathSoaVector3 vec, VmathSoaMatrix3 mat ) +{ + VmathSoaVector3 result; + vmathSoaV3RowMul(&result, &vec, &mat); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaV3CrossMatrix_V( VmathSoaVector3 vec ) +{ + VmathSoaMatrix3 result; + vmathSoaV3CrossMatrix(&result, &vec); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaV3CrossMatrixMul_V( VmathSoaVector3 vec, VmathSoaMatrix3 mat ) +{ + VmathSoaMatrix3 result; + vmathSoaV3CrossMatrixMul(&result, &vec, &mat); + return result; +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/quat_aos.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/quat_aos.h new file mode 100644 index 0000000..2915f4f --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/quat_aos.h @@ -0,0 +1,379 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_AOS_C_H +#define _VECTORMATH_QUAT_AOS_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline void vmathQCopy( VmathQuat *result, const VmathQuat *quat ) +{ + result->vec128 = quat->vec128; +} + +static inline void vmathQMakeFromElems( VmathQuat *result, float _x, float _y, float _z, float _w ) +{ + if (__builtin_constant_p(_x) & __builtin_constant_p(_y) & + __builtin_constant_p(_z) & __builtin_constant_p(_w)) { + result->vec128 = (vec_float4){_x, _y, _z, _w}; + } else { + float *pf = (float *)&result->vec128; + pf[0] = _x; + pf[1] = _y; + pf[2] = _z; + pf[3] = _w; + } +} + +static inline void vmathQMakeFromV3Scalar( VmathQuat *result, const VmathVector3 *xyz, float _w ) +{ + result->vec128 = xyz->vec128; + _vmathVfSetElement(result->vec128, _w, 3); +} + +static inline void vmathQMakeFromV4( VmathQuat *result, const VmathVector4 *vec ) +{ + result->vec128 = vec->vec128; +} + +static inline void vmathQMakeFromScalar( VmathQuat *result, float scalar ) +{ + result->vec128 = _vmathVfSplatScalar(scalar); +} + +static inline void vmathQMakeFrom128( VmathQuat *result, vec_float4 vf4 ) +{ + result->vec128 = vf4; +} + +static inline void vmathQMakeIdentity( VmathQuat *result ) +{ + result->vec128 = _VECTORMATH_UNIT_0001; +} + +static inline void vmathQLerp( VmathQuat *result, float t, const VmathQuat *quat0, const VmathQuat *quat1 ) +{ + VmathQuat tmpQ_0, tmpQ_1; + vmathQSub( &tmpQ_0, quat1, quat0 ); + vmathQScalarMul( &tmpQ_1, &tmpQ_0, t ); + vmathQAdd( result, quat0, &tmpQ_1 ); +} + +static inline void vmathQSlerp( VmathQuat *result, float t, const VmathQuat *unitQuat0, const VmathQuat *unitQuat1 ) +{ + VmathQuat start; + vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + vec_uint4 selectMask; + cosAngle = _vmathVfDot4( unitQuat0->vec128, unitQuat1->vec128 ); + cosAngle = vec_splat( cosAngle, 0 ); + selectMask = (vec_uint4)vec_cmpgt( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), cosAngle ); + cosAngle = vec_sel( cosAngle, negatef4( cosAngle ), selectMask ); + start.vec128 = vec_sel( unitQuat0->vec128, negatef4( unitQuat0->vec128 ), selectMask ); + selectMask = (vec_uint4)vec_cmpgt( ((vec_float4){_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL}), cosAngle ); + angle = acosf4( cosAngle ); + tttt = _vmathVfSplatScalar(t); + oneMinusT = vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), tttt ); + angles = vec_mergeh( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), tttt ); + angles = vec_mergeh( angles, oneMinusT ); + angles = vec_madd( angles, angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sines = sinf4( angles ); + scales = divf4( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + result->vec128 = vec_madd( start.vec128, scale0, vec_madd( unitQuat1->vec128, scale1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +static inline void vmathQSquad( VmathQuat *result, float t, const VmathQuat *unitQuat0, const VmathQuat *unitQuat1, const VmathQuat *unitQuat2, const VmathQuat *unitQuat3 ) +{ + VmathQuat tmp0, tmp1; + vmathQSlerp( &tmp0, t, unitQuat0, unitQuat3 ); + vmathQSlerp( &tmp1, t, unitQuat1, unitQuat2 ); + vmathQSlerp( result, ( ( 2.0f * t ) * ( 1.0f - t ) ), &tmp0, &tmp1 ); +} + +static inline vec_float4 vmathQGet128( const VmathQuat *quat ) +{ + return quat->vec128; +} + +static inline void vmathQSetXYZ( VmathQuat *result, const VmathVector3 *vec ) +{ + result->vec128 = vec_sel( vec->vec128, result->vec128, _VECTORMATH_MASK_0x000F ); +} + +static inline void vmathQGetXYZ( VmathVector3 *result, const VmathQuat *quat ) +{ + result->vec128 = quat->vec128; +} + +static inline void vmathQSetX( VmathQuat *result, float _x ) +{ + _vmathVfSetElement(result->vec128, _x, 0); +} + +static inline float vmathQGetX( const VmathQuat *quat ) +{ + return _vmathVfGetElement(quat->vec128, 0); +} + +static inline void vmathQSetY( VmathQuat *result, float _y ) +{ + _vmathVfSetElement(result->vec128, _y, 1); +} + +static inline float vmathQGetY( const VmathQuat *quat ) +{ + return _vmathVfGetElement(quat->vec128, 1); +} + +static inline void vmathQSetZ( VmathQuat *result, float _z ) +{ + _vmathVfSetElement(result->vec128, _z, 2); +} + +static inline float vmathQGetZ( const VmathQuat *quat ) +{ + return _vmathVfGetElement(quat->vec128, 2); +} + +static inline void vmathQSetW( VmathQuat *result, float _w ) +{ + _vmathVfSetElement(result->vec128, _w, 3); +} + +static inline float vmathQGetW( const VmathQuat *quat ) +{ + return _vmathVfGetElement(quat->vec128, 3); +} + +static inline void vmathQSetElem( VmathQuat *result, int idx, float value ) +{ + _vmathVfSetElement(result->vec128, value, idx); +} + +static inline float vmathQGetElem( const VmathQuat *quat, int idx ) +{ + return _vmathVfGetElement(quat->vec128, idx); +} + +static inline void vmathQAdd( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ) +{ + result->vec128 = vec_add( quat0->vec128, quat1->vec128 ); +} + +static inline void vmathQSub( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ) +{ + result->vec128 = vec_sub( quat0->vec128, quat1->vec128 ); +} + +static inline void vmathQScalarMul( VmathQuat *result, const VmathQuat *quat, float scalar ) +{ + result->vec128 = vec_madd( quat->vec128, _vmathVfSplatScalar(scalar), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathQScalarDiv( VmathQuat *result, const VmathQuat *quat, float scalar ) +{ + result->vec128 = divf4( quat->vec128, _vmathVfSplatScalar(scalar) ); +} + +static inline void vmathQNeg( VmathQuat *result, const VmathQuat *quat ) +{ + result->vec128 = negatef4( quat->vec128 ); +} + +static inline float vmathQDot( const VmathQuat *quat0, const VmathQuat *quat1 ) +{ + vec_float4 result = _vmathVfDot4( quat0->vec128, quat1->vec128 ); + return _vmathVfGetElement(result, 0); +} + +static inline float vmathQNorm( const VmathQuat *quat ) +{ + vec_float4 result = _vmathVfDot4( quat->vec128, quat->vec128 ); + return _vmathVfGetElement(result, 0); +} + +static inline float vmathQLength( const VmathQuat *quat ) +{ + return sqrtf( vmathQNorm( quat ) ); +} + +static inline void vmathQNormalize( VmathQuat *result, const VmathQuat *quat ) +{ + vec_float4 dot = _vmathVfDot4( quat->vec128, quat->vec128 ); + result->vec128 = vec_madd( quat->vec128, rsqrtf4( dot ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathQMakeRotationArc( VmathQuat *result, const VmathVector3 *unitVec0, const VmathVector3 *unitVec1 ) +{ + VmathVector3 crossVec, tmpV3_0; + vec_float4 cosAngle, cosAngleX2Plus2, recipCosHalfAngleX2, cosHalfAngleX2, res; + cosAngle = _vmathVfDot3( unitVec0->vec128, unitVec1->vec128 ); + cosAngle = vec_splat( cosAngle, 0 ); + cosAngleX2Plus2 = vec_madd( cosAngle, ((vec_float4){2.0f,2.0f,2.0f,2.0f}), ((vec_float4){2.0f,2.0f,2.0f,2.0f}) ); + recipCosHalfAngleX2 = rsqrtf4( cosAngleX2Plus2 ); + cosHalfAngleX2 = vec_madd( recipCosHalfAngleX2, cosAngleX2Plus2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + vmathV3Cross( &tmpV3_0, unitVec0, unitVec1 ); + crossVec = tmpV3_0; + res = vec_madd( crossVec.vec128, recipCosHalfAngleX2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + res = vec_sel( res, vec_madd( cosHalfAngleX2, ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), _VECTORMATH_MASK_0x000F ); + result->vec128 = res; +} + +static inline void vmathQMakeRotationAxis( VmathQuat *result, float radians, const VmathVector3 *unitVec ) +{ + vec_float4 s, c, angle, res; + angle = vec_madd( _vmathVfSplatScalar(radians), ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sincosf4( angle, &s, &c ); + res = vec_sel( vec_madd( unitVec->vec128, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), c, _VECTORMATH_MASK_0x000F ); + result->vec128 = res; +} + +static inline void vmathQMakeRotationX( VmathQuat *result, float radians ) +{ + vec_float4 s, c, angle, res; + angle = vec_madd( _vmathVfSplatScalar(radians), ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sincosf4( angle, &s, &c ); + res = vec_sel( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), s, _VECTORMATH_MASK_0xF000 ); + res = vec_sel( res, c, _VECTORMATH_MASK_0x000F ); + result->vec128 = res; +} + +static inline void vmathQMakeRotationY( VmathQuat *result, float radians ) +{ + vec_float4 s, c, angle, res; + angle = vec_madd( _vmathVfSplatScalar(radians), ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sincosf4( angle, &s, &c ); + res = vec_sel( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), s, _VECTORMATH_MASK_0x0F00 ); + res = vec_sel( res, c, _VECTORMATH_MASK_0x000F ); + result->vec128 = res; +} + +static inline void vmathQMakeRotationZ( VmathQuat *result, float radians ) +{ + vec_float4 s, c, angle, res; + angle = vec_madd( _vmathVfSplatScalar(radians), ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sincosf4( angle, &s, &c ); + res = vec_sel( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), s, _VECTORMATH_MASK_0x00F0 ); + res = vec_sel( res, c, _VECTORMATH_MASK_0x000F ); + result->vec128 = res; +} + +static inline void vmathQMul( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ) +{ + vec_float4 ldata, rdata, qv, tmp0, tmp1, tmp2, tmp3; + vec_float4 product, l_wxyz, r_wxyz, xy, qw; + ldata = quat0->vec128; + rdata = quat1->vec128; + tmp0 = vec_perm( ldata, ldata, _VECTORMATH_PERM_YZXW ); + tmp1 = vec_perm( rdata, rdata, _VECTORMATH_PERM_ZXYW ); + tmp2 = vec_perm( ldata, ldata, _VECTORMATH_PERM_ZXYW ); + tmp3 = vec_perm( rdata, rdata, _VECTORMATH_PERM_YZXW ); + qv = vec_madd( vec_splat( ldata, 3 ), rdata, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qv = vec_madd( vec_splat( rdata, 3 ), ldata, qv ); + qv = vec_madd( tmp0, tmp1, qv ); + qv = vec_nmsub( tmp2, tmp3, qv ); + product = vec_madd( ldata, rdata, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + l_wxyz = vec_sld( ldata, ldata, 12 ); + r_wxyz = vec_sld( rdata, rdata, 12 ); + qw = vec_nmsub( l_wxyz, r_wxyz, product ); + xy = vec_madd( l_wxyz, r_wxyz, product ); + qw = vec_sub( qw, vec_sld( xy, xy, 8 ) ); + result->vec128 = vec_sel( qv, qw, _VECTORMATH_MASK_0x000F ); +} + +static inline void vmathQRotate( VmathVector3 *result, const VmathQuat *quat, const VmathVector3 *vec ) +{ + vec_float4 qdata, vdata, product, tmp0, tmp1, tmp2, tmp3, wwww, qv, qw, res; + qdata = quat->vec128; + vdata = vec->vec128; + tmp0 = vec_perm( qdata, qdata, _VECTORMATH_PERM_YZXW ); + tmp1 = vec_perm( vdata, vdata, _VECTORMATH_PERM_ZXYW ); + tmp2 = vec_perm( qdata, qdata, _VECTORMATH_PERM_ZXYW ); + tmp3 = vec_perm( vdata, vdata, _VECTORMATH_PERM_YZXW ); + wwww = vec_splat( qdata, 3 ); + qv = vec_madd( wwww, vdata, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qv = vec_madd( tmp0, tmp1, qv ); + qv = vec_nmsub( tmp2, tmp3, qv ); + product = vec_madd( qdata, vdata, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qw = vec_madd( vec_sld( qdata, qdata, 4 ), vec_sld( vdata, vdata, 4 ), product ); + qw = vec_add( vec_sld( product, product, 8 ), qw ); + tmp1 = vec_perm( qv, qv, _VECTORMATH_PERM_ZXYW ); + tmp3 = vec_perm( qv, qv, _VECTORMATH_PERM_YZXW ); + res = vec_madd( vec_splat( qw, 0 ), qdata, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + res = vec_madd( wwww, qv, res ); + res = vec_madd( tmp0, tmp1, res ); + res = vec_nmsub( tmp2, tmp3, res ); + result->vec128 = res; +} + +static inline void vmathQConj( VmathQuat *result, const VmathQuat *quat ) +{ + result->vec128 = vec_xor( quat->vec128, ((vec_float4)(vec_int4){0x80000000,0x80000000,0x80000000,0}) ); +} + +static inline void vmathQSelect( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1, unsigned int select1 ) +{ + unsigned int tmp; + tmp = (unsigned int)-(select1 > 0); + result->vec128 = vec_sel( quat0->vec128, quat1->vec128, _vmathVuiSplatScalar(tmp) ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathQPrint( const VmathQuat *quat ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = quat->vec128; + printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +static inline void vmathQPrints( const VmathQuat *quat, const char *name ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = quat->vec128; + printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/quat_aos_v.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/quat_aos_v.h new file mode 100644 index 0000000..04cf6cc --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/quat_aos_v.h @@ -0,0 +1,312 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_AOS_V_C_H +#define _VECTORMATH_QUAT_AOS_V_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline VmathQuat vmathQMakeFromElems_V( float _x, float _y, float _z, float _w ) +{ + VmathQuat result; + vmathQMakeFromElems(&result, _x, _y, _z, _w); + return result; +} + +static inline VmathQuat vmathQMakeFromV3Scalar_V( VmathVector3 xyz, float _w ) +{ + VmathQuat result; + vmathQMakeFromV3Scalar(&result, &xyz, _w); + return result; +} + +static inline VmathQuat vmathQMakeFromV4_V( VmathVector4 vec ) +{ + VmathQuat result; + vmathQMakeFromV4(&result, &vec); + return result; +} + +static inline VmathQuat vmathQMakeFromScalar_V( float scalar ) +{ + VmathQuat result; + vmathQMakeFromScalar(&result, scalar); + return result; +} + +static inline VmathQuat vmathQMakeFrom128_V( vec_float4 vf4 ) +{ + VmathQuat result; + vmathQMakeFrom128(&result, vf4); + return result; +} + +static inline VmathQuat vmathQMakeIdentity_V( ) +{ + VmathQuat result; + vmathQMakeIdentity(&result); + return result; +} + +static inline VmathQuat vmathQLerp_V( float t, VmathQuat quat0, VmathQuat quat1 ) +{ + VmathQuat result; + vmathQLerp(&result, t, &quat0, &quat1); + return result; +} + +static inline VmathQuat vmathQSlerp_V( float t, VmathQuat unitQuat0, VmathQuat unitQuat1 ) +{ + VmathQuat result; + vmathQSlerp(&result, t, &unitQuat0, &unitQuat1); + return result; +} + +static inline VmathQuat vmathQSquad_V( float t, VmathQuat unitQuat0, VmathQuat unitQuat1, VmathQuat unitQuat2, VmathQuat unitQuat3 ) +{ + VmathQuat result; + vmathQSquad(&result, t, &unitQuat0, &unitQuat1, &unitQuat2, &unitQuat3); + return result; +} + +static inline vec_float4 vmathQGet128_V( VmathQuat quat ) +{ + return vmathQGet128(&quat); +} + +static inline void vmathQSetXYZ_V( VmathQuat *result, VmathVector3 vec ) +{ + vmathQSetXYZ(result, &vec); +} + +static inline VmathVector3 vmathQGetXYZ_V( VmathQuat quat ) +{ + VmathVector3 result; + vmathQGetXYZ(&result, &quat); + return result; +} + +static inline void vmathQSetX_V( VmathQuat *result, float _x ) +{ + vmathQSetX(result, _x); +} + +static inline float vmathQGetX_V( VmathQuat quat ) +{ + return vmathQGetX(&quat); +} + +static inline void vmathQSetY_V( VmathQuat *result, float _y ) +{ + vmathQSetY(result, _y); +} + +static inline float vmathQGetY_V( VmathQuat quat ) +{ + return vmathQGetY(&quat); +} + +static inline void vmathQSetZ_V( VmathQuat *result, float _z ) +{ + vmathQSetZ(result, _z); +} + +static inline float vmathQGetZ_V( VmathQuat quat ) +{ + return vmathQGetZ(&quat); +} + +static inline void vmathQSetW_V( VmathQuat *result, float _w ) +{ + vmathQSetW(result, _w); +} + +static inline float vmathQGetW_V( VmathQuat quat ) +{ + return vmathQGetW(&quat); +} + +static inline void vmathQSetElem_V( VmathQuat *result, int idx, float value ) +{ + vmathQSetElem(result, idx, value); +} + +static inline float vmathQGetElem_V( VmathQuat quat, int idx ) +{ + return vmathQGetElem(&quat, idx); +} + +static inline VmathQuat vmathQAdd_V( VmathQuat quat0, VmathQuat quat1 ) +{ + VmathQuat result; + vmathQAdd(&result, &quat0, &quat1); + return result; +} + +static inline VmathQuat vmathQSub_V( VmathQuat quat0, VmathQuat quat1 ) +{ + VmathQuat result; + vmathQSub(&result, &quat0, &quat1); + return result; +} + +static inline VmathQuat vmathQScalarMul_V( VmathQuat quat, float scalar ) +{ + VmathQuat result; + vmathQScalarMul(&result, &quat, scalar); + return result; +} + +static inline VmathQuat vmathQScalarDiv_V( VmathQuat quat, float scalar ) +{ + VmathQuat result; + vmathQScalarDiv(&result, &quat, scalar); + return result; +} + +static inline VmathQuat vmathQNeg_V( VmathQuat quat ) +{ + VmathQuat result; + vmathQNeg(&result, &quat); + return result; +} + +static inline float vmathQDot_V( VmathQuat quat0, VmathQuat quat1 ) +{ + return vmathQDot(&quat0, &quat1); +} + +static inline float vmathQNorm_V( VmathQuat quat ) +{ + return vmathQNorm(&quat); +} + +static inline float vmathQLength_V( VmathQuat quat ) +{ + return vmathQLength(&quat); +} + +static inline VmathQuat vmathQNormalize_V( VmathQuat quat ) +{ + VmathQuat result; + vmathQNormalize(&result, &quat); + return result; +} + +static inline VmathQuat vmathQMakeRotationArc_V( VmathVector3 unitVec0, VmathVector3 unitVec1 ) +{ + VmathQuat result; + vmathQMakeRotationArc(&result, &unitVec0, &unitVec1); + return result; +} + +static inline VmathQuat vmathQMakeRotationAxis_V( float radians, VmathVector3 unitVec ) +{ + VmathQuat result; + vmathQMakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathQuat vmathQMakeRotationX_V( float radians ) +{ + VmathQuat result; + vmathQMakeRotationX(&result, radians); + return result; +} + +static inline VmathQuat vmathQMakeRotationY_V( float radians ) +{ + VmathQuat result; + vmathQMakeRotationY(&result, radians); + return result; +} + +static inline VmathQuat vmathQMakeRotationZ_V( float radians ) +{ + VmathQuat result; + vmathQMakeRotationZ(&result, radians); + return result; +} + +static inline VmathQuat vmathQMul_V( VmathQuat quat0, VmathQuat quat1 ) +{ + VmathQuat result; + vmathQMul(&result, &quat0, &quat1); + return result; +} + +static inline VmathVector3 vmathQRotate_V( VmathQuat quat, VmathVector3 vec ) +{ + VmathVector3 result; + vmathQRotate(&result, &quat, &vec); + return result; +} + +static inline VmathQuat vmathQConj_V( VmathQuat quat ) +{ + VmathQuat result; + vmathQConj(&result, &quat); + return result; +} + +static inline VmathQuat vmathQSelect_V( VmathQuat quat0, VmathQuat quat1, unsigned int select1 ) +{ + VmathQuat result; + vmathQSelect(&result, &quat0, &quat1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathQPrint_V( VmathQuat quat ) +{ + vmathQPrint(&quat); +} + +static inline void vmathQPrints_V( VmathQuat quat, const char *name ) +{ + vmathQPrints(&quat, name); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/quat_soa.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/quat_soa.h new file mode 100644 index 0000000..334c17b --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/quat_soa.h @@ -0,0 +1,415 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_SOA_C_H +#define _VECTORMATH_QUAT_SOA_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline void vmathSoaQCopy( VmathSoaQuat *result, const VmathSoaQuat *quat ) +{ + result->x = quat->x; + result->y = quat->y; + result->z = quat->z; + result->w = quat->w; +} + +static inline void vmathSoaQMakeFromElems( VmathSoaQuat *result, vec_float4 _x, vec_float4 _y, vec_float4 _z, vec_float4 _w ) +{ + result->x = _x; + result->y = _y; + result->z = _z; + result->w = _w; +} + +static inline void vmathSoaQMakeFromV3Scalar( VmathSoaQuat *result, const VmathSoaVector3 *xyz, vec_float4 _w ) +{ + vmathSoaQSetXYZ( result, xyz ); + vmathSoaQSetW( result, _w ); +} + +static inline void vmathSoaQMakeFromV4( VmathSoaQuat *result, const VmathSoaVector4 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; + result->w = vec->w; +} + +static inline void vmathSoaQMakeFromScalar( VmathSoaQuat *result, vec_float4 scalar ) +{ + result->x = scalar; + result->y = scalar; + result->z = scalar; + result->w = scalar; +} + +static inline void vmathSoaQMakeFromAos( VmathSoaQuat *result, const VmathQuat *quat ) +{ + vec_float4 vec128 = quat->vec128; + result->x = vec_splat( vec128, 0 ); + result->y = vec_splat( vec128, 1 ); + result->z = vec_splat( vec128, 2 ); + result->w = vec_splat( vec128, 3 ); +} + +static inline void vmathSoaQMakeFrom4Aos( VmathSoaQuat *result, const VmathQuat *quat0, const VmathQuat *quat1, const VmathQuat *quat2, const VmathQuat *quat3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = vec_mergeh( quat0->vec128, quat2->vec128 ); + tmp1 = vec_mergeh( quat1->vec128, quat3->vec128 ); + tmp2 = vec_mergel( quat0->vec128, quat2->vec128 ); + tmp3 = vec_mergel( quat1->vec128, quat3->vec128 ); + result->x = vec_mergeh( tmp0, tmp1 ); + result->y = vec_mergel( tmp0, tmp1 ); + result->z = vec_mergeh( tmp2, tmp3 ); + result->w = vec_mergel( tmp2, tmp3 ); +} + +static inline void vmathSoaQMakeIdentity( VmathSoaQuat *result ) +{ + vmathSoaQMakeFromElems( result, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); +} + +static inline void vmathSoaQLerp( VmathSoaQuat *result, vec_float4 t, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ) +{ + VmathSoaQuat tmpQ_0, tmpQ_1; + vmathSoaQSub( &tmpQ_0, quat1, quat0 ); + vmathSoaQScalarMul( &tmpQ_1, &tmpQ_0, t ); + vmathSoaQAdd( result, quat0, &tmpQ_1 ); +} + +static inline void vmathSoaQSlerp( VmathSoaQuat *result, vec_float4 t, const VmathSoaQuat *unitQuat0, const VmathSoaQuat *unitQuat1 ) +{ + VmathSoaQuat start, tmpQ_0, tmpQ_1; + vec_float4 recipSinAngle, scale0, scale1, cosAngle, angle; + vec_uint4 selectMask; + cosAngle = vmathSoaQDot( unitQuat0, unitQuat1 ); + selectMask = (vec_uint4)vec_cmpgt( (vec_float4){0.0f,0.0f,0.0f,0.0f}, cosAngle ); + cosAngle = vec_sel( cosAngle, negatef4( cosAngle ), selectMask ); + vmathSoaQSetX( &start, vec_sel( unitQuat0->x, negatef4( unitQuat0->x ), selectMask ) ); + vmathSoaQSetY( &start, vec_sel( unitQuat0->y, negatef4( unitQuat0->y ), selectMask ) ); + vmathSoaQSetZ( &start, vec_sel( unitQuat0->z, negatef4( unitQuat0->z ), selectMask ) ); + vmathSoaQSetW( &start, vec_sel( unitQuat0->w, negatef4( unitQuat0->w ), selectMask ) ); + selectMask = (vec_uint4)vec_cmpgt( (vec_float4){_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL}, cosAngle ); + angle = acosf4( cosAngle ); + recipSinAngle = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sinf4( angle ) ); + scale0 = vec_sel( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), t ), vec_madd( sinf4( vec_madd( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), t ), angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), recipSinAngle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), selectMask ); + scale1 = vec_sel( t, vec_madd( sinf4( vec_madd( t, angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), recipSinAngle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), selectMask ); + vmathSoaQScalarMul( &tmpQ_0, &start, scale0 ); + vmathSoaQScalarMul( &tmpQ_1, unitQuat1, scale1 ); + vmathSoaQAdd( result, &tmpQ_0, &tmpQ_1 ); +} + +static inline void vmathSoaQSquad( VmathSoaQuat *result, vec_float4 t, const VmathSoaQuat *unitQuat0, const VmathSoaQuat *unitQuat1, const VmathSoaQuat *unitQuat2, const VmathSoaQuat *unitQuat3 ) +{ + VmathSoaQuat tmp0, tmp1; + vmathSoaQSlerp( &tmp0, t, unitQuat0, unitQuat3 ); + vmathSoaQSlerp( &tmp1, t, unitQuat1, unitQuat2 ); + vmathSoaQSlerp( result, vec_madd( vec_madd( ((vec_float4){2.0f,2.0f,2.0f,2.0f}), t, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), t ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), &tmp0, &tmp1 ); +} + +static inline void vmathSoaQGet4Aos( const VmathSoaQuat *quat, VmathQuat *result0, VmathQuat *result1, VmathQuat *result2, VmathQuat *result3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = vec_mergeh( quat->x, quat->z ); + tmp1 = vec_mergeh( quat->y, quat->w ); + tmp2 = vec_mergel( quat->x, quat->z ); + tmp3 = vec_mergel( quat->y, quat->w ); + vmathQMakeFrom128( result0, vec_mergeh( tmp0, tmp1 ) ); + vmathQMakeFrom128( result1, vec_mergel( tmp0, tmp1 ) ); + vmathQMakeFrom128( result2, vec_mergeh( tmp2, tmp3 ) ); + vmathQMakeFrom128( result3, vec_mergel( tmp2, tmp3 ) ); +} + +static inline void vmathSoaQSetXYZ( VmathSoaQuat *result, const VmathSoaVector3 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; +} + +static inline void vmathSoaQGetXYZ( VmathSoaVector3 *result, const VmathSoaQuat *quat ) +{ + vmathSoaV3MakeFromElems( result, quat->x, quat->y, quat->z ); +} + +static inline void vmathSoaQSetX( VmathSoaQuat *result, vec_float4 _x ) +{ + result->x = _x; +} + +static inline vec_float4 vmathSoaQGetX( const VmathSoaQuat *quat ) +{ + return quat->x; +} + +static inline void vmathSoaQSetY( VmathSoaQuat *result, vec_float4 _y ) +{ + result->y = _y; +} + +static inline vec_float4 vmathSoaQGetY( const VmathSoaQuat *quat ) +{ + return quat->y; +} + +static inline void vmathSoaQSetZ( VmathSoaQuat *result, vec_float4 _z ) +{ + result->z = _z; +} + +static inline vec_float4 vmathSoaQGetZ( const VmathSoaQuat *quat ) +{ + return quat->z; +} + +static inline void vmathSoaQSetW( VmathSoaQuat *result, vec_float4 _w ) +{ + result->w = _w; +} + +static inline vec_float4 vmathSoaQGetW( const VmathSoaQuat *quat ) +{ + return quat->w; +} + +static inline void vmathSoaQSetElem( VmathSoaQuat *result, int idx, vec_float4 value ) +{ + *(&result->x + idx) = value; +} + +static inline vec_float4 vmathSoaQGetElem( const VmathSoaQuat *quat, int idx ) +{ + return *(&quat->x + idx); +} + +static inline void vmathSoaQAdd( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ) +{ + result->x = vec_add( quat0->x, quat1->x ); + result->y = vec_add( quat0->y, quat1->y ); + result->z = vec_add( quat0->z, quat1->z ); + result->w = vec_add( quat0->w, quat1->w ); +} + +static inline void vmathSoaQSub( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ) +{ + result->x = vec_sub( quat0->x, quat1->x ); + result->y = vec_sub( quat0->y, quat1->y ); + result->z = vec_sub( quat0->z, quat1->z ); + result->w = vec_sub( quat0->w, quat1->w ); +} + +static inline void vmathSoaQScalarMul( VmathSoaQuat *result, const VmathSoaQuat *quat, vec_float4 scalar ) +{ + result->x = vec_madd( quat->x, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->y = vec_madd( quat->y, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->z = vec_madd( quat->z, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->w = vec_madd( quat->w, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaQScalarDiv( VmathSoaQuat *result, const VmathSoaQuat *quat, vec_float4 scalar ) +{ + result->x = divf4( quat->x, scalar ); + result->y = divf4( quat->y, scalar ); + result->z = divf4( quat->z, scalar ); + result->w = divf4( quat->w, scalar ); +} + +static inline void vmathSoaQNeg( VmathSoaQuat *result, const VmathSoaQuat *quat ) +{ + result->x = negatef4( quat->x ); + result->y = negatef4( quat->y ); + result->z = negatef4( quat->z ); + result->w = negatef4( quat->w ); +} + +static inline vec_float4 vmathSoaQDot( const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ) +{ + vec_float4 result; + result = vec_madd( quat0->x, quat1->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result = vec_add( result, vec_madd( quat0->y, quat1->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( quat0->z, quat1->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( quat0->w, quat1->w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return result; +} + +static inline vec_float4 vmathSoaQNorm( const VmathSoaQuat *quat ) +{ + vec_float4 result; + result = vec_madd( quat->x, quat->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result = vec_add( result, vec_madd( quat->y, quat->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( quat->z, quat->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( quat->w, quat->w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return result; +} + +static inline vec_float4 vmathSoaQLength( const VmathSoaQuat *quat ) +{ + return sqrtf4( vmathSoaQNorm( quat ) ); +} + +static inline void vmathSoaQNormalize( VmathSoaQuat *result, const VmathSoaQuat *quat ) +{ + vec_float4 lenSqr, lenInv; + lenSqr = vmathSoaQNorm( quat ); + lenInv = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( lenSqr ) ); + result->x = vec_madd( quat->x, lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->y = vec_madd( quat->y, lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->z = vec_madd( quat->z, lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->w = vec_madd( quat->w, lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaQMakeRotationArc( VmathSoaQuat *result, const VmathSoaVector3 *unitVec0, const VmathSoaVector3 *unitVec1 ) +{ + VmathSoaVector3 tmpV3_0, tmpV3_1; + vec_float4 cosHalfAngleX2, recipCosHalfAngleX2; + cosHalfAngleX2 = sqrtf4( vec_madd( ((vec_float4){2.0f,2.0f,2.0f,2.0f}), vec_add( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vmathSoaV3Dot( unitVec0, unitVec1 ) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + recipCosHalfAngleX2 = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), cosHalfAngleX2 ); + vmathSoaV3Cross( &tmpV3_0, unitVec0, unitVec1 ); + vmathSoaV3ScalarMul( &tmpV3_1, &tmpV3_0, recipCosHalfAngleX2 ); + vmathSoaQMakeFromV3Scalar( result, &tmpV3_1, vec_madd( cosHalfAngleX2, ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +static inline void vmathSoaQMakeRotationAxis( VmathSoaQuat *result, vec_float4 radians, const VmathSoaVector3 *unitVec ) +{ + VmathSoaVector3 tmpV3_0; + vec_float4 s, c, angle; + angle = vec_madd( radians, ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sincosf4( angle, &s, &c ); + vmathSoaV3ScalarMul( &tmpV3_0, unitVec, s ); + vmathSoaQMakeFromV3Scalar( result, &tmpV3_0, c ); +} + +static inline void vmathSoaQMakeRotationX( VmathSoaQuat *result, vec_float4 radians ) +{ + vec_float4 s, c, angle; + angle = vec_madd( radians, ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sincosf4( angle, &s, &c ); + vmathSoaQMakeFromElems( result, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), c ); +} + +static inline void vmathSoaQMakeRotationY( VmathSoaQuat *result, vec_float4 radians ) +{ + vec_float4 s, c, angle; + angle = vec_madd( radians, ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sincosf4( angle, &s, &c ); + vmathSoaQMakeFromElems( result, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), c ); +} + +static inline void vmathSoaQMakeRotationZ( VmathSoaQuat *result, vec_float4 radians ) +{ + vec_float4 s, c, angle; + angle = vec_madd( radians, ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sincosf4( angle, &s, &c ); + vmathSoaQMakeFromElems( result, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), s, c ); +} + +static inline void vmathSoaQMul( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ) +{ + vec_float4 tmpX, tmpY, tmpZ, tmpW; + tmpX = vec_sub( vec_add( vec_add( vec_madd( quat0->w, quat1->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( quat0->x, quat1->w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( quat0->y, quat1->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( quat0->z, quat1->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpY = vec_sub( vec_add( vec_add( vec_madd( quat0->w, quat1->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( quat0->y, quat1->w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( quat0->z, quat1->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( quat0->x, quat1->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpZ = vec_sub( vec_add( vec_add( vec_madd( quat0->w, quat1->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( quat0->z, quat1->w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( quat0->x, quat1->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( quat0->y, quat1->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpW = vec_sub( vec_sub( vec_sub( vec_madd( quat0->w, quat1->w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( quat0->x, quat1->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( quat0->y, quat1->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( quat0->z, quat1->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaQMakeFromElems( result, tmpX, tmpY, tmpZ, tmpW ); +} + +static inline void vmathSoaQRotate( VmathSoaVector3 *result, const VmathSoaQuat *quat, const VmathSoaVector3 *vec ) +{ + vec_float4 tmpX, tmpY, tmpZ, tmpW; + tmpX = vec_sub( vec_add( vec_madd( quat->w, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( quat->y, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( quat->z, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpY = vec_sub( vec_add( vec_madd( quat->w, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( quat->z, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( quat->x, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpZ = vec_sub( vec_add( vec_madd( quat->w, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( quat->x, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( quat->y, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpW = vec_add( vec_add( vec_madd( quat->x, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( quat->y, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( quat->z, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result->x = vec_add( vec_sub( vec_add( vec_madd( tmpW, quat->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmpX, quat->w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tmpY, quat->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tmpZ, quat->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result->y = vec_add( vec_sub( vec_add( vec_madd( tmpW, quat->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmpY, quat->w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tmpZ, quat->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tmpX, quat->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result->z = vec_add( vec_sub( vec_add( vec_madd( tmpW, quat->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmpZ, quat->w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tmpX, quat->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tmpY, quat->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +static inline void vmathSoaQConj( VmathSoaQuat *result, const VmathSoaQuat *quat ) +{ + vmathSoaQMakeFromElems( result, negatef4( quat->x ), negatef4( quat->y ), negatef4( quat->z ), quat->w ); +} + +static inline void vmathSoaQSelect( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1, vec_uint4 select1 ) +{ + result->x = vec_sel( quat0->x, quat1->x, select1 ); + result->y = vec_sel( quat0->y, quat1->y, select1 ); + result->z = vec_sel( quat0->z, quat1->z, select1 ); + result->w = vec_sel( quat0->w, quat1->w, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaQPrint( const VmathSoaQuat *quat ) +{ + VmathQuat vec0, vec1, vec2, vec3; + vmathSoaQGet4Aos( quat, &vec0, &vec1, &vec2, &vec3 ); + printf("slot 0:\n"); + vmathQPrint( &vec0 ); + printf("slot 1:\n"); + vmathQPrint( &vec1 ); + printf("slot 2:\n"); + vmathQPrint( &vec2 ); + printf("slot 3:\n"); + vmathQPrint( &vec3 ); +} + +static inline void vmathSoaQPrints( const VmathSoaQuat *quat, const char *name ) +{ + VmathQuat vec0, vec1, vec2, vec3; + printf( "%s:\n", name ); + vmathSoaQGet4Aos( quat, &vec0, &vec1, &vec2, &vec3 ); + printf("slot 0:\n"); + vmathQPrint( &vec0 ); + printf("slot 1:\n"); + vmathQPrint( &vec1 ); + printf("slot 2:\n"); + vmathQPrint( &vec2 ); + printf("slot 3:\n"); + vmathQPrint( &vec3 ); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/quat_soa_v.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/quat_soa_v.h new file mode 100644 index 0000000..601d9da --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/quat_soa_v.h @@ -0,0 +1,319 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_SOA_V_C_H +#define _VECTORMATH_QUAT_SOA_V_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline VmathSoaQuat vmathSoaQMakeFromElems_V( vec_float4 _x, vec_float4 _y, vec_float4 _z, vec_float4 _w ) +{ + VmathSoaQuat result; + vmathSoaQMakeFromElems(&result, _x, _y, _z, _w); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeFromV3Scalar_V( VmathSoaVector3 xyz, vec_float4 _w ) +{ + VmathSoaQuat result; + vmathSoaQMakeFromV3Scalar(&result, &xyz, _w); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeFromV4_V( VmathSoaVector4 vec ) +{ + VmathSoaQuat result; + vmathSoaQMakeFromV4(&result, &vec); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeFromScalar_V( vec_float4 scalar ) +{ + VmathSoaQuat result; + vmathSoaQMakeFromScalar(&result, scalar); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeFromAos_V( VmathQuat quat ) +{ + VmathSoaQuat result; + vmathSoaQMakeFromAos(&result, &quat); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeFrom4Aos_V( VmathQuat quat0, VmathQuat quat1, VmathQuat quat2, VmathQuat quat3 ) +{ + VmathSoaQuat result; + vmathSoaQMakeFrom4Aos(&result, &quat0, &quat1, &quat2, &quat3); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeIdentity_V( ) +{ + VmathSoaQuat result; + vmathSoaQMakeIdentity(&result); + return result; +} + +static inline VmathSoaQuat vmathSoaQLerp_V( vec_float4 t, VmathSoaQuat quat0, VmathSoaQuat quat1 ) +{ + VmathSoaQuat result; + vmathSoaQLerp(&result, t, &quat0, &quat1); + return result; +} + +static inline VmathSoaQuat vmathSoaQSlerp_V( vec_float4 t, VmathSoaQuat unitQuat0, VmathSoaQuat unitQuat1 ) +{ + VmathSoaQuat result; + vmathSoaQSlerp(&result, t, &unitQuat0, &unitQuat1); + return result; +} + +static inline VmathSoaQuat vmathSoaQSquad_V( vec_float4 t, VmathSoaQuat unitQuat0, VmathSoaQuat unitQuat1, VmathSoaQuat unitQuat2, VmathSoaQuat unitQuat3 ) +{ + VmathSoaQuat result; + vmathSoaQSquad(&result, t, &unitQuat0, &unitQuat1, &unitQuat2, &unitQuat3); + return result; +} + +static inline void vmathSoaQGet4Aos_V( VmathSoaQuat quat, VmathQuat *result0, VmathQuat *result1, VmathQuat *result2, VmathQuat *result3 ) +{ + vmathSoaQGet4Aos(&quat, result0, result1, result2, result3); +} + +static inline void vmathSoaQSetXYZ_V( VmathSoaQuat *result, VmathSoaVector3 vec ) +{ + vmathSoaQSetXYZ(result, &vec); +} + +static inline VmathSoaVector3 vmathSoaQGetXYZ_V( VmathSoaQuat quat ) +{ + VmathSoaVector3 result; + vmathSoaQGetXYZ(&result, &quat); + return result; +} + +static inline void vmathSoaQSetX_V( VmathSoaQuat *result, vec_float4 _x ) +{ + vmathSoaQSetX(result, _x); +} + +static inline vec_float4 vmathSoaQGetX_V( VmathSoaQuat quat ) +{ + return vmathSoaQGetX(&quat); +} + +static inline void vmathSoaQSetY_V( VmathSoaQuat *result, vec_float4 _y ) +{ + vmathSoaQSetY(result, _y); +} + +static inline vec_float4 vmathSoaQGetY_V( VmathSoaQuat quat ) +{ + return vmathSoaQGetY(&quat); +} + +static inline void vmathSoaQSetZ_V( VmathSoaQuat *result, vec_float4 _z ) +{ + vmathSoaQSetZ(result, _z); +} + +static inline vec_float4 vmathSoaQGetZ_V( VmathSoaQuat quat ) +{ + return vmathSoaQGetZ(&quat); +} + +static inline void vmathSoaQSetW_V( VmathSoaQuat *result, vec_float4 _w ) +{ + vmathSoaQSetW(result, _w); +} + +static inline vec_float4 vmathSoaQGetW_V( VmathSoaQuat quat ) +{ + return vmathSoaQGetW(&quat); +} + +static inline void vmathSoaQSetElem_V( VmathSoaQuat *result, int idx, vec_float4 value ) +{ + vmathSoaQSetElem(result, idx, value); +} + +static inline vec_float4 vmathSoaQGetElem_V( VmathSoaQuat quat, int idx ) +{ + return vmathSoaQGetElem(&quat, idx); +} + +static inline VmathSoaQuat vmathSoaQAdd_V( VmathSoaQuat quat0, VmathSoaQuat quat1 ) +{ + VmathSoaQuat result; + vmathSoaQAdd(&result, &quat0, &quat1); + return result; +} + +static inline VmathSoaQuat vmathSoaQSub_V( VmathSoaQuat quat0, VmathSoaQuat quat1 ) +{ + VmathSoaQuat result; + vmathSoaQSub(&result, &quat0, &quat1); + return result; +} + +static inline VmathSoaQuat vmathSoaQScalarMul_V( VmathSoaQuat quat, vec_float4 scalar ) +{ + VmathSoaQuat result; + vmathSoaQScalarMul(&result, &quat, scalar); + return result; +} + +static inline VmathSoaQuat vmathSoaQScalarDiv_V( VmathSoaQuat quat, vec_float4 scalar ) +{ + VmathSoaQuat result; + vmathSoaQScalarDiv(&result, &quat, scalar); + return result; +} + +static inline VmathSoaQuat vmathSoaQNeg_V( VmathSoaQuat quat ) +{ + VmathSoaQuat result; + vmathSoaQNeg(&result, &quat); + return result; +} + +static inline vec_float4 vmathSoaQDot_V( VmathSoaQuat quat0, VmathSoaQuat quat1 ) +{ + return vmathSoaQDot(&quat0, &quat1); +} + +static inline vec_float4 vmathSoaQNorm_V( VmathSoaQuat quat ) +{ + return vmathSoaQNorm(&quat); +} + +static inline vec_float4 vmathSoaQLength_V( VmathSoaQuat quat ) +{ + return vmathSoaQLength(&quat); +} + +static inline VmathSoaQuat vmathSoaQNormalize_V( VmathSoaQuat quat ) +{ + VmathSoaQuat result; + vmathSoaQNormalize(&result, &quat); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeRotationArc_V( VmathSoaVector3 unitVec0, VmathSoaVector3 unitVec1 ) +{ + VmathSoaQuat result; + vmathSoaQMakeRotationArc(&result, &unitVec0, &unitVec1); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeRotationAxis_V( vec_float4 radians, VmathSoaVector3 unitVec ) +{ + VmathSoaQuat result; + vmathSoaQMakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeRotationX_V( vec_float4 radians ) +{ + VmathSoaQuat result; + vmathSoaQMakeRotationX(&result, radians); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeRotationY_V( vec_float4 radians ) +{ + VmathSoaQuat result; + vmathSoaQMakeRotationY(&result, radians); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeRotationZ_V( vec_float4 radians ) +{ + VmathSoaQuat result; + vmathSoaQMakeRotationZ(&result, radians); + return result; +} + +static inline VmathSoaQuat vmathSoaQMul_V( VmathSoaQuat quat0, VmathSoaQuat quat1 ) +{ + VmathSoaQuat result; + vmathSoaQMul(&result, &quat0, &quat1); + return result; +} + +static inline VmathSoaVector3 vmathSoaQRotate_V( VmathSoaQuat quat, VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaQRotate(&result, &quat, &vec); + return result; +} + +static inline VmathSoaQuat vmathSoaQConj_V( VmathSoaQuat quat ) +{ + VmathSoaQuat result; + vmathSoaQConj(&result, &quat); + return result; +} + +static inline VmathSoaQuat vmathSoaQSelect_V( VmathSoaQuat quat0, VmathSoaQuat quat1, vec_uint4 select1 ) +{ + VmathSoaQuat result; + vmathSoaQSelect(&result, &quat0, &quat1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaQPrint_V( VmathSoaQuat quat ) +{ + vmathSoaQPrint(&quat); +} + +static inline void vmathSoaQPrints_V( VmathSoaQuat quat, const char *name ) +{ + vmathSoaQPrints(&quat, name); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/vec_aos.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/vec_aos.h new file mode 100644 index 0000000..58427a2 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/vec_aos.h @@ -0,0 +1,1125 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_AOS_C_H +#define _VECTORMATH_VEC_AOS_C_H +#include +#include +#include +#include "vec_types.h" +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + * for permutes words are labeled [x,y,z,w] [a,b,c,d] + */ +#define _VECTORMATH_PERM_X 0x00010203 +#define _VECTORMATH_PERM_Y 0x04050607 +#define _VECTORMATH_PERM_Z 0x08090a0b +#define _VECTORMATH_PERM_W 0x0c0d0e0f +#define _VECTORMATH_PERM_A 0x10111213 +#define _VECTORMATH_PERM_B 0x14151617 +#define _VECTORMATH_PERM_C 0x18191a1b +#define _VECTORMATH_PERM_D 0x1c1d1e1f +#define _VECTORMATH_PERM_XYZA (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A } +#define _VECTORMATH_PERM_ZXYW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_YZXW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_YZAB (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B } +#define _VECTORMATH_PERM_ZABC (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B, _VECTORMATH_PERM_C } +#define _VECTORMATH_PERM_XYAW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_XAZW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W } +#define _VECTORMATH_MASK_0xF000 (vec_uint4){ 0xffffffff, 0, 0, 0 } +#define _VECTORMATH_MASK_0x0F00 (vec_uint4){ 0, 0xffffffff, 0, 0 } +#define _VECTORMATH_MASK_0x00F0 (vec_uint4){ 0, 0, 0xffffffff, 0 } +#define _VECTORMATH_MASK_0x000F (vec_uint4){ 0, 0, 0, 0xffffffff } +#define _VECTORMATH_UNIT_1000 (vec_float4){ 1.0f, 0.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0100 (vec_float4){ 0.0f, 1.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0010 (vec_float4){ 0.0f, 0.0f, 1.0f, 0.0f } +#define _VECTORMATH_UNIT_0001 (vec_float4){ 0.0f, 0.0f, 0.0f, 1.0f } +#define _VECTORMATH_SLERP_TOL 0.999f + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +static inline vec_float4 _vmathVfDot3( vec_float4 vec0, vec_float4 vec1 ) +{ + vec_float4 result; + result = vec_madd( vec0, vec1, (vec_float4){0.0f,0.0f,0.0f,0.0f} ); + result = vec_madd( vec_sld( vec0, vec0, 4 ), vec_sld( vec1, vec1, 4 ), result ); + return vec_madd( vec_sld( vec0, vec0, 8 ), vec_sld( vec1, vec1, 8 ), result ); +} + +static inline vec_float4 _vmathVfDot4( vec_float4 vec0, vec_float4 vec1 ) +{ + vec_float4 result; + result = vec_madd( vec0, vec1, (vec_float4){0.0f,0.0f,0.0f,0.0f} ); + result = vec_madd( vec_sld( vec0, vec0, 4 ), vec_sld( vec1, vec1, 4 ), result ); + return vec_add( vec_sld( result, result, 8 ), result ); +} + +static inline vec_float4 _vmathVfCross( vec_float4 vec0, vec_float4 vec1 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3, result; + tmp0 = vec_perm( vec0, vec0, _VECTORMATH_PERM_YZXW ); + tmp1 = vec_perm( vec1, vec1, _VECTORMATH_PERM_ZXYW ); + tmp2 = vec_perm( vec0, vec0, _VECTORMATH_PERM_ZXYW ); + tmp3 = vec_perm( vec1, vec1, _VECTORMATH_PERM_YZXW ); + result = vec_madd( tmp0, tmp1, (vec_float4){0.0f,0.0f,0.0f,0.0f} ); + result = vec_nmsub( tmp2, tmp3, result ); + return result; +} + +static inline vec_uint4 _vmathVfToHalfFloatsUnpacked(vec_float4 v) +{ + vec_int4 bexp; + vec_uint4 mant, sign, hfloat; + vec_uint4 notZero, isInf; + const vec_uint4 hfloatInf = (vec_uint4){0x00007c00u,0x00007c00u,0x00007c00u,0x00007c00u}; + const vec_uint4 mergeMant = (vec_uint4){0x000003ffu,0x000003ffu,0x000003ffu,0x000003ffu}; + const vec_uint4 mergeSign = (vec_uint4){0x00008000u,0x00008000u,0x00008000u,0x00008000u}; + + sign = vec_sr((vec_uint4)v, (vec_uint4){16,16,16,16}); + mant = vec_sr((vec_uint4)v, (vec_uint4){13,13,13,13}); + bexp = vec_and(vec_sr((vec_int4)v, (vec_uint4){23,23,23,23}), (vec_int4){0xff,0xff,0xff,0xff}); + + notZero = (vec_uint4)vec_cmpgt(bexp, (vec_int4){112,112,112,112}); + isInf = (vec_uint4)vec_cmpgt(bexp, (vec_int4){142,142,142,142}); + + bexp = vec_add(bexp, (vec_int4){-112,-112,-112,-112}); + bexp = vec_sl(bexp, (vec_uint4){10,10,10,10}); + + hfloat = vec_sel((vec_uint4)bexp, mant, mergeMant); + hfloat = vec_sel((vec_uint4){0,0,0,0}, hfloat, notZero); + hfloat = vec_sel(hfloat, hfloatInf, isInf); + hfloat = vec_sel(hfloat, sign, mergeSign); + + return hfloat; +} + +static inline vec_ushort8 _vmath2VfToHalfFloats(vec_float4 u, vec_float4 v) +{ + vec_uint4 hfloat_u, hfloat_v; + const vec_uchar16 pack = (vec_uchar16){2,3,6,7,10,11,14,15,18,19,22,23,26,27,30,31}; + hfloat_u = _vmathVfToHalfFloatsUnpacked(u); + hfloat_v = _vmathVfToHalfFloatsUnpacked(v); + return (vec_ushort8)vec_perm(hfloat_u, hfloat_v, pack); +} + +#ifndef __GNUC__ +#define __builtin_constant_p(x) 0 +#endif + +static inline vec_float4 _vmathVfInsert(vec_float4 dst, vec_float4 src, int slot) +{ +#ifdef __GNUC__ + if (__builtin_constant_p(slot)) { + dst = vec_sld(dst, dst, slot<<2); + dst = vec_sld(dst, src, 4); + if (slot != 3) dst = vec_sld(dst, dst, (3-slot)<<2); + return dst; + } else +#endif + { + vec_uchar16 shiftpattern = vec_lvsr( 0, (float *)(size_t)(slot<<2) ); + vec_uint4 selectmask = (vec_uint4)vec_perm( (vec_uint4){0,0,0,0}, _VECTORMATH_MASK_0xF000, shiftpattern ); + return vec_sel( dst, src, selectmask ); + } +} + +#define _vmathVfGetElement(vec, slot) ((float *)&(vec))[slot] +#ifdef _VECTORMATH_SET_CONSTS_IN_MEM +#define _vmathVfSetElement(vec, scalar, slot) ((float *)&(vec))[slot] = scalar +#else +#define _vmathVfSetElement(vec, scalar, slot) \ +{ \ + if (__builtin_constant_p(scalar)) { \ + (vec) = _vmathVfInsert(vec, (vec_float4){scalar, scalar, scalar, scalar}, slot); \ + } else { \ + ((float *)&(vec))[slot] = scalar; \ + } \ +} +#endif + +static inline vec_float4 _vmathVfSplatScalar(float scalar) +{ + vec_float4 result; + if (__builtin_constant_p(scalar)) { + result = (vec_float4){scalar, scalar, scalar, scalar}; + } else { + result = vec_ld(0, &scalar); + result = vec_splat(vec_perm(result, result, vec_lvsl(0, &scalar)), 0); + } + return result; +} + +static inline vec_uint4 _vmathVuiSplatScalar(unsigned int scalar) +{ + vec_uint4 result; + if (__builtin_constant_p(scalar)) { + result = (vec_uint4){scalar, scalar, scalar, scalar}; + } else { + result = vec_ld(0, &scalar); + result = vec_splat(vec_perm(result, result, vec_lvsl(0, &scalar)), 0); + } + return result; +} + +#endif + +static inline void vmathV3Copy( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->vec128 = vec->vec128; +} + +static inline void vmathV3MakeFromElems( VmathVector3 *result, float _x, float _y, float _z ) +{ + if (__builtin_constant_p(_x) & __builtin_constant_p(_y) & __builtin_constant_p(_z)) { + result->vec128 = (vec_float4){_x, _y, _z, 0.0f}; + } else { + float *pf = (float *)&result->vec128; + pf[0] = _x; + pf[1] = _y; + pf[2] = _z; + } +} + +static inline void vmathV3MakeFromP3( VmathVector3 *result, const VmathPoint3 *pnt ) +{ + result->vec128 = pnt->vec128; +} + +static inline void vmathV3MakeFromScalar( VmathVector3 *result, float scalar ) +{ + result->vec128 = _vmathVfSplatScalar(scalar); +} + +static inline void vmathV3MakeFrom128( VmathVector3 *result, vec_float4 vf4 ) +{ + result->vec128 = vf4; +} + +static inline void vmathV3MakeXAxis( VmathVector3 *result ) +{ + result->vec128 = _VECTORMATH_UNIT_1000; +} + +static inline void vmathV3MakeYAxis( VmathVector3 *result ) +{ + result->vec128 = _VECTORMATH_UNIT_0100; +} + +static inline void vmathV3MakeZAxis( VmathVector3 *result ) +{ + result->vec128 = _VECTORMATH_UNIT_0010; +} + +static inline void vmathV3Lerp( VmathVector3 *result, float t, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + VmathVector3 tmpV3_0, tmpV3_1; + vmathV3Sub( &tmpV3_0, vec1, vec0 ); + vmathV3ScalarMul( &tmpV3_1, &tmpV3_0, t ); + vmathV3Add( result, vec0, &tmpV3_1 ); +} + +static inline void vmathV3Slerp( VmathVector3 *result, float t, const VmathVector3 *unitVec0, const VmathVector3 *unitVec1 ) +{ + vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + vec_uint4 selectMask; + cosAngle = _vmathVfDot3( unitVec0->vec128, unitVec1->vec128 ); + cosAngle = vec_splat( cosAngle, 0 ); + selectMask = (vec_uint4)vec_cmpgt( ((vec_float4){_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL}), cosAngle ); + angle = acosf4( cosAngle ); + tttt = _vmathVfSplatScalar(t); + oneMinusT = vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), tttt ); + angles = vec_mergeh( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), tttt ); + angles = vec_mergeh( angles, oneMinusT ); + angles = vec_madd( angles, angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sines = sinf4( angles ); + scales = divf4( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + result->vec128 = vec_madd( unitVec0->vec128, scale0, vec_madd( unitVec1->vec128, scale1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +static inline vec_float4 vmathV3Get128( const VmathVector3 *vec ) +{ + return vec->vec128; +} + +static inline void vmathV3StoreXYZ( const VmathVector3 *vec, vec_float4 *quad ) +{ + vec_float4 dstVec = *quad; + vec_uint4 mask = _VECTORMATH_MASK_0x000F; + dstVec = vec_sel(vec->vec128, dstVec, mask); + *quad = dstVec; +} + +static inline void vmathV3LoadXYZArray( VmathVector3 *vec0, VmathVector3 *vec1, VmathVector3 *vec2, VmathVector3 *vec3, const vec_float4 *threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz, xyz1, xyz2, xyz3; + xyzx = threeQuads[0]; + yzxy = threeQuads[1]; + zxyz = threeQuads[2]; + xyz1 = vec_sld( xyzx, yzxy, 12 ); + xyz2 = vec_sld( yzxy, zxyz, 8 ); + xyz3 = vec_sld( zxyz, zxyz, 4 ); + vec0->vec128 = xyzx; + vec1->vec128 = xyz1; + vec2->vec128 = xyz2; + vec3->vec128 = xyz3; +} + +static inline void vmathV3StoreXYZArray( const VmathVector3 *vec0, const VmathVector3 *vec1, const VmathVector3 *vec2, const VmathVector3 *vec3, vec_float4 *threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz; + xyzx = vec_perm( vec0->vec128, vec1->vec128, _VECTORMATH_PERM_XYZA ); + yzxy = vec_perm( vec1->vec128, vec2->vec128, _VECTORMATH_PERM_YZAB ); + zxyz = vec_perm( vec2->vec128, vec3->vec128, _VECTORMATH_PERM_ZABC ); + threeQuads[0] = xyzx; + threeQuads[1] = yzxy; + threeQuads[2] = zxyz; +} + +static inline void vmathV3StoreHalfFloats( const VmathVector3 *vec0, const VmathVector3 *vec1, const VmathVector3 *vec2, const VmathVector3 *vec3, const VmathVector3 *vec4, const VmathVector3 *vec5, const VmathVector3 *vec6, const VmathVector3 *vec7, vec_ushort8 *threeQuads ) +{ + vec_float4 xyz0[3]; + vec_float4 xyz1[3]; + vmathV3StoreXYZArray( vec0, vec1, vec2, vec3, xyz0 ); + vmathV3StoreXYZArray( vec4, vec5, vec6, vec7, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +} + +static inline void vmathV3SetX( VmathVector3 *result, float _x ) +{ + _vmathVfSetElement(result->vec128, _x, 0); +} + +static inline float vmathV3GetX( const VmathVector3 *vec ) +{ + return _vmathVfGetElement(vec->vec128, 0); +} + +static inline void vmathV3SetY( VmathVector3 *result, float _y ) +{ + _vmathVfSetElement(result->vec128, _y, 1); +} + +static inline float vmathV3GetY( const VmathVector3 *vec ) +{ + return _vmathVfGetElement(vec->vec128, 1); +} + +static inline void vmathV3SetZ( VmathVector3 *result, float _z ) +{ + _vmathVfSetElement(result->vec128, _z, 2); +} + +static inline float vmathV3GetZ( const VmathVector3 *vec ) +{ + return _vmathVfGetElement(vec->vec128, 2); +} + +static inline void vmathV3SetElem( VmathVector3 *result, int idx, float value ) +{ + _vmathVfSetElement(result->vec128, value, idx); +} + +static inline float vmathV3GetElem( const VmathVector3 *vec, int idx ) +{ + return _vmathVfGetElement(vec->vec128, idx); +} + +static inline void vmathV3Add( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->vec128 = vec_add( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV3Sub( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->vec128 = vec_sub( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV3AddP3( VmathPoint3 *result, const VmathVector3 *vec, const VmathPoint3 *pnt1 ) +{ + result->vec128 = vec_add( vec->vec128, pnt1->vec128 ); +} + +static inline void vmathV3ScalarMul( VmathVector3 *result, const VmathVector3 *vec, float scalar ) +{ + result->vec128 = vec_madd( vec->vec128, _vmathVfSplatScalar(scalar), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathV3ScalarDiv( VmathVector3 *result, const VmathVector3 *vec, float scalar ) +{ + result->vec128 = divf4( vec->vec128, _vmathVfSplatScalar(scalar) ); +} + +static inline void vmathV3Neg( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->vec128 = negatef4( vec->vec128 ); +} + +static inline void vmathV3MulPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->vec128 = vec_madd( vec0->vec128, vec1->vec128, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathV3DivPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->vec128 = divf4( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV3RecipPerElem( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->vec128 = recipf4( vec->vec128 ); +} + +static inline void vmathV3SqrtPerElem( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->vec128 = sqrtf4( vec->vec128 ); +} + +static inline void vmathV3RsqrtPerElem( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->vec128 = rsqrtf4( vec->vec128 ); +} + +static inline void vmathV3AbsPerElem( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->vec128 = fabsf4( vec->vec128 ); +} + +static inline void vmathV3CopySignPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->vec128 = copysignf4( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV3MaxPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->vec128 = fmaxf4( vec0->vec128, vec1->vec128 ); +} + +static inline float vmathV3MaxElem( const VmathVector3 *vec ) +{ + vec_float4 result; + result = fmaxf4( vec_splat( vec->vec128, 1 ), vec->vec128 ); + result = fmaxf4( vec_splat( vec->vec128, 2 ), result ); + return _vmathVfGetElement(result, 0); +} + +static inline void vmathV3MinPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->vec128 = fminf4( vec0->vec128, vec1->vec128 ); +} + +static inline float vmathV3MinElem( const VmathVector3 *vec ) +{ + vec_float4 result; + result = fminf4( vec_splat( vec->vec128, 1 ), vec->vec128 ); + result = fminf4( vec_splat( vec->vec128, 2 ), result ); + return _vmathVfGetElement(result, 0); +} + +static inline float vmathV3Sum( const VmathVector3 *vec ) +{ + vec_float4 result; + result = vec_add( vec_splat( vec->vec128, 1 ), vec->vec128 ); + result = vec_add( vec_splat( vec->vec128, 2 ), result ); + return _vmathVfGetElement(result, 0); +} + +static inline float vmathV3Dot( const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + vec_float4 result = _vmathVfDot3( vec0->vec128, vec1->vec128 ); + return _vmathVfGetElement(result, 0); +} + +static inline float vmathV3LengthSqr( const VmathVector3 *vec ) +{ + vec_float4 result = _vmathVfDot3( vec->vec128, vec->vec128 ); + return _vmathVfGetElement(result, 0); +} + +static inline float vmathV3Length( const VmathVector3 *vec ) +{ + return sqrtf( vmathV3LengthSqr( vec ) ); +} + +static inline void vmathV3Normalize( VmathVector3 *result, const VmathVector3 *vec ) +{ + vec_float4 dot = _vmathVfDot3( vec->vec128, vec->vec128 ); + dot = vec_splat( dot, 0 ); + result->vec128 = vec_madd( vec->vec128, rsqrtf4( dot ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathV3Cross( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->vec128 = _vmathVfCross( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV3Select( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1, unsigned int select1 ) +{ + unsigned int tmp; + tmp = (unsigned int)-(select1 > 0); + result->vec128 = vec_sel( vec0->vec128, vec1->vec128, _vmathVuiSplatScalar(tmp) ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathV3Print( const VmathVector3 *vec ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = vec->vec128; + printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +static inline void vmathV3Prints( const VmathVector3 *vec, const char *name ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = vec->vec128; + printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +#endif + +static inline void vmathV4Copy( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->vec128 = vec->vec128; +} + +static inline void vmathV4MakeFromElems( VmathVector4 *result, float _x, float _y, float _z, float _w ) +{ + if (__builtin_constant_p(_x) & __builtin_constant_p(_y) & + __builtin_constant_p(_z) & __builtin_constant_p(_w)) { + result->vec128 = (vec_float4){_x, _y, _z, _w}; + } else { + float *pf = (float *)&result->vec128; + pf[0] = _x; + pf[1] = _y; + pf[2] = _z; + pf[3] = _w; + } +} + +static inline void vmathV4MakeFromV3Scalar( VmathVector4 *result, const VmathVector3 *xyz, float _w ) +{ + result->vec128 = xyz->vec128; + _vmathVfSetElement(result->vec128, _w, 3); +} + +static inline void vmathV4MakeFromV3( VmathVector4 *result, const VmathVector3 *vec ) +{ + result->vec128 = vec->vec128; + result->vec128 = _vmathVfInsert(result->vec128, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), 3); +} + +static inline void vmathV4MakeFromP3( VmathVector4 *result, const VmathPoint3 *pnt ) +{ + result->vec128 = pnt->vec128; + result->vec128 = _vmathVfInsert(result->vec128, ((vec_float4){1.0f,1.0f,1.0f,1.0f}), 3); +} + +static inline void vmathV4MakeFromQ( VmathVector4 *result, const VmathQuat *quat ) +{ + result->vec128 = quat->vec128; +} + +static inline void vmathV4MakeFromScalar( VmathVector4 *result, float scalar ) +{ + result->vec128 = _vmathVfSplatScalar(scalar); +} + +static inline void vmathV4MakeFrom128( VmathVector4 *result, vec_float4 vf4 ) +{ + result->vec128 = vf4; +} + +static inline void vmathV4MakeXAxis( VmathVector4 *result ) +{ + result->vec128 = _VECTORMATH_UNIT_1000; +} + +static inline void vmathV4MakeYAxis( VmathVector4 *result ) +{ + result->vec128 = _VECTORMATH_UNIT_0100; +} + +static inline void vmathV4MakeZAxis( VmathVector4 *result ) +{ + result->vec128 = _VECTORMATH_UNIT_0010; +} + +static inline void vmathV4MakeWAxis( VmathVector4 *result ) +{ + result->vec128 = _VECTORMATH_UNIT_0001; +} + +static inline void vmathV4Lerp( VmathVector4 *result, float t, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + VmathVector4 tmpV4_0, tmpV4_1; + vmathV4Sub( &tmpV4_0, vec1, vec0 ); + vmathV4ScalarMul( &tmpV4_1, &tmpV4_0, t ); + vmathV4Add( result, vec0, &tmpV4_1 ); +} + +static inline void vmathV4Slerp( VmathVector4 *result, float t, const VmathVector4 *unitVec0, const VmathVector4 *unitVec1 ) +{ + vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + vec_uint4 selectMask; + cosAngle = _vmathVfDot4( unitVec0->vec128, unitVec1->vec128 ); + cosAngle = vec_splat( cosAngle, 0 ); + selectMask = (vec_uint4)vec_cmpgt( ((vec_float4){_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL}), cosAngle ); + angle = acosf4( cosAngle ); + tttt = _vmathVfSplatScalar(t); + oneMinusT = vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), tttt ); + angles = vec_mergeh( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), tttt ); + angles = vec_mergeh( angles, oneMinusT ); + angles = vec_madd( angles, angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sines = sinf4( angles ); + scales = divf4( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + result->vec128 = vec_madd( unitVec0->vec128, scale0, vec_madd( unitVec1->vec128, scale1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +static inline vec_float4 vmathV4Get128( const VmathVector4 *vec ) +{ + return vec->vec128; +} + +static inline void vmathV4StoreHalfFloats( const VmathVector4 *vec0, const VmathVector4 *vec1, const VmathVector4 *vec2, const VmathVector4 *vec3, vec_ushort8 *twoQuads ) +{ + twoQuads[0] = _vmath2VfToHalfFloats(vec0->vec128, vec1->vec128); + twoQuads[1] = _vmath2VfToHalfFloats(vec2->vec128, vec3->vec128); +} + +static inline void vmathV4SetXYZ( VmathVector4 *result, const VmathVector3 *vec ) +{ + result->vec128 = vec_sel( vec->vec128, result->vec128, _VECTORMATH_MASK_0x000F ); +} + +static inline void vmathV4GetXYZ( VmathVector3 *result, const VmathVector4 *vec ) +{ + result->vec128 = vec->vec128; +} + +static inline void vmathV4SetX( VmathVector4 *result, float _x ) +{ + _vmathVfSetElement(result->vec128, _x, 0); +} + +static inline float vmathV4GetX( const VmathVector4 *vec ) +{ + return _vmathVfGetElement(vec->vec128, 0); +} + +static inline void vmathV4SetY( VmathVector4 *result, float _y ) +{ + _vmathVfSetElement(result->vec128, _y, 1); +} + +static inline float vmathV4GetY( const VmathVector4 *vec ) +{ + return _vmathVfGetElement(vec->vec128, 1); +} + +static inline void vmathV4SetZ( VmathVector4 *result, float _z ) +{ + _vmathVfSetElement(result->vec128, _z, 2); +} + +static inline float vmathV4GetZ( const VmathVector4 *vec ) +{ + return _vmathVfGetElement(vec->vec128, 2); +} + +static inline void vmathV4SetW( VmathVector4 *result, float _w ) +{ + _vmathVfSetElement(result->vec128, _w, 3); +} + +static inline float vmathV4GetW( const VmathVector4 *vec ) +{ + return _vmathVfGetElement(vec->vec128, 3); +} + +static inline void vmathV4SetElem( VmathVector4 *result, int idx, float value ) +{ + _vmathVfSetElement(result->vec128, value, idx); +} + +static inline float vmathV4GetElem( const VmathVector4 *vec, int idx ) +{ + return _vmathVfGetElement(vec->vec128, idx); +} + +static inline void vmathV4Add( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->vec128 = vec_add( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV4Sub( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->vec128 = vec_sub( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV4ScalarMul( VmathVector4 *result, const VmathVector4 *vec, float scalar ) +{ + result->vec128 = vec_madd( vec->vec128, _vmathVfSplatScalar(scalar), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathV4ScalarDiv( VmathVector4 *result, const VmathVector4 *vec, float scalar ) +{ + result->vec128 = divf4( vec->vec128, _vmathVfSplatScalar(scalar) ); +} + +static inline void vmathV4Neg( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->vec128 = negatef4( vec->vec128 ); +} + +static inline void vmathV4MulPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->vec128 = vec_madd( vec0->vec128, vec1->vec128, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathV4DivPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->vec128 = divf4( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV4RecipPerElem( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->vec128 = recipf4( vec->vec128 ); +} + +static inline void vmathV4SqrtPerElem( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->vec128 = sqrtf4( vec->vec128 ); +} + +static inline void vmathV4RsqrtPerElem( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->vec128 = rsqrtf4( vec->vec128 ); +} + +static inline void vmathV4AbsPerElem( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->vec128 = fabsf4( vec->vec128 ); +} + +static inline void vmathV4CopySignPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->vec128 = copysignf4( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV4MaxPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->vec128 = fmaxf4( vec0->vec128, vec1->vec128 ); +} + +static inline float vmathV4MaxElem( const VmathVector4 *vec ) +{ + vec_float4 result; + result = fmaxf4( vec_splat( vec->vec128, 1 ), vec->vec128 ); + result = fmaxf4( vec_splat( vec->vec128, 2 ), result ); + result = fmaxf4( vec_splat( vec->vec128, 3 ), result ); + return _vmathVfGetElement(result, 0); +} + +static inline void vmathV4MinPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->vec128 = fminf4( vec0->vec128, vec1->vec128 ); +} + +static inline float vmathV4MinElem( const VmathVector4 *vec ) +{ + vec_float4 result; + result = fminf4( vec_splat( vec->vec128, 1 ), vec->vec128 ); + result = fminf4( vec_splat( vec->vec128, 2 ), result ); + result = fminf4( vec_splat( vec->vec128, 3 ), result ); + return _vmathVfGetElement(result, 0); +} + +static inline float vmathV4Sum( const VmathVector4 *vec ) +{ + vec_float4 result; + result = vec_add( vec_splat( vec->vec128, 1 ), vec->vec128 ); + result = vec_add( vec_splat( vec->vec128, 2 ), result ); + result = vec_add( vec_splat( vec->vec128, 3 ), result ); + return _vmathVfGetElement(result, 0); +} + +static inline float vmathV4Dot( const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + vec_float4 result = _vmathVfDot4( vec0->vec128, vec1->vec128 ); + return _vmathVfGetElement(result, 0); +} + +static inline float vmathV4LengthSqr( const VmathVector4 *vec ) +{ + vec_float4 result = _vmathVfDot4( vec->vec128, vec->vec128 ); + return _vmathVfGetElement(result, 0); +} + +static inline float vmathV4Length( const VmathVector4 *vec ) +{ + return sqrtf( vmathV4LengthSqr( vec ) ); +} + +static inline void vmathV4Normalize( VmathVector4 *result, const VmathVector4 *vec ) +{ + vec_float4 dot = _vmathVfDot4( vec->vec128, vec->vec128 ); + result->vec128 = vec_madd( vec->vec128, rsqrtf4( dot ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathV4Select( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1, unsigned int select1 ) +{ + unsigned int tmp; + tmp = (unsigned int)-(select1 > 0); + result->vec128 = vec_sel( vec0->vec128, vec1->vec128, _vmathVuiSplatScalar(tmp) ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathV4Print( const VmathVector4 *vec ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = vec->vec128; + printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +static inline void vmathV4Prints( const VmathVector4 *vec, const char *name ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = vec->vec128; + printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +#endif + +static inline void vmathP3Copy( VmathPoint3 *result, const VmathPoint3 *pnt ) +{ + result->vec128 = pnt->vec128; +} + +static inline void vmathP3MakeFromElems( VmathPoint3 *result, float _x, float _y, float _z ) +{ + if (__builtin_constant_p(_x) & __builtin_constant_p(_y) & __builtin_constant_p(_z)) { + result->vec128 = (vec_float4){_x, _y, _z, 0.0f}; + } else { + float *pf = (float *)&result->vec128; + pf[0] = _x; + pf[1] = _y; + pf[2] = _z; + } +} + +static inline void vmathP3MakeFromV3( VmathPoint3 *result, const VmathVector3 *vec ) +{ + result->vec128 = vec->vec128; +} + +static inline void vmathP3MakeFromScalar( VmathPoint3 *result, float scalar ) +{ + result->vec128 = _vmathVfSplatScalar(scalar); +} + +static inline void vmathP3MakeFrom128( VmathPoint3 *result, vec_float4 vf4 ) +{ + result->vec128 = vf4; +} + +static inline void vmathP3Lerp( VmathPoint3 *result, float t, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + VmathVector3 tmpV3_0, tmpV3_1; + vmathP3Sub( &tmpV3_0, pnt1, pnt0 ); + vmathV3ScalarMul( &tmpV3_1, &tmpV3_0, t ); + vmathP3AddV3( result, pnt0, &tmpV3_1 ); +} + +static inline vec_float4 vmathP3Get128( const VmathPoint3 *pnt ) +{ + return pnt->vec128; +} + +static inline void vmathP3StoreXYZ( const VmathPoint3 *pnt, vec_float4 *quad ) +{ + vec_float4 dstVec = *quad; + vec_uint4 mask = _VECTORMATH_MASK_0x000F; + dstVec = vec_sel(pnt->vec128, dstVec, mask); + *quad = dstVec; +} + +static inline void vmathP3LoadXYZArray( VmathPoint3 *pnt0, VmathPoint3 *pnt1, VmathPoint3 *pnt2, VmathPoint3 *pnt3, const vec_float4 *threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz, xyz1, xyz2, xyz3; + xyzx = threeQuads[0]; + yzxy = threeQuads[1]; + zxyz = threeQuads[2]; + xyz1 = vec_sld( xyzx, yzxy, 12 ); + xyz2 = vec_sld( yzxy, zxyz, 8 ); + xyz3 = vec_sld( zxyz, zxyz, 4 ); + pnt0->vec128 = xyzx; + pnt1->vec128 = xyz1; + pnt2->vec128 = xyz2; + pnt3->vec128 = xyz3; +} + +static inline void vmathP3StoreXYZArray( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, const VmathPoint3 *pnt2, const VmathPoint3 *pnt3, vec_float4 *threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz; + xyzx = vec_perm( pnt0->vec128, pnt1->vec128, _VECTORMATH_PERM_XYZA ); + yzxy = vec_perm( pnt1->vec128, pnt2->vec128, _VECTORMATH_PERM_YZAB ); + zxyz = vec_perm( pnt2->vec128, pnt3->vec128, _VECTORMATH_PERM_ZABC ); + threeQuads[0] = xyzx; + threeQuads[1] = yzxy; + threeQuads[2] = zxyz; +} + +static inline void vmathP3StoreHalfFloats( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, const VmathPoint3 *pnt2, const VmathPoint3 *pnt3, const VmathPoint3 *pnt4, const VmathPoint3 *pnt5, const VmathPoint3 *pnt6, const VmathPoint3 *pnt7, vec_ushort8 *threeQuads ) +{ + vec_float4 xyz0[3]; + vec_float4 xyz1[3]; + vmathP3StoreXYZArray( pnt0, pnt1, pnt2, pnt3, xyz0 ); + vmathP3StoreXYZArray( pnt4, pnt5, pnt6, pnt7, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +} + +static inline void vmathP3SetX( VmathPoint3 *result, float _x ) +{ + _vmathVfSetElement(result->vec128, _x, 0); +} + +static inline float vmathP3GetX( const VmathPoint3 *pnt ) +{ + return _vmathVfGetElement(pnt->vec128, 0); +} + +static inline void vmathP3SetY( VmathPoint3 *result, float _y ) +{ + _vmathVfSetElement(result->vec128, _y, 1); +} + +static inline float vmathP3GetY( const VmathPoint3 *pnt ) +{ + return _vmathVfGetElement(pnt->vec128, 1); +} + +static inline void vmathP3SetZ( VmathPoint3 *result, float _z ) +{ + _vmathVfSetElement(result->vec128, _z, 2); +} + +static inline float vmathP3GetZ( const VmathPoint3 *pnt ) +{ + return _vmathVfGetElement(pnt->vec128, 2); +} + +static inline void vmathP3SetElem( VmathPoint3 *result, int idx, float value ) +{ + _vmathVfSetElement(result->vec128, value, idx); +} + +static inline float vmathP3GetElem( const VmathPoint3 *pnt, int idx ) +{ + return _vmathVfGetElement(pnt->vec128, idx); +} + +static inline void vmathP3Sub( VmathVector3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->vec128 = vec_sub( pnt0->vec128, pnt1->vec128 ); +} + +static inline void vmathP3AddV3( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *vec1 ) +{ + result->vec128 = vec_add( pnt->vec128, vec1->vec128 ); +} + +static inline void vmathP3SubV3( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *vec1 ) +{ + result->vec128 = vec_sub( pnt->vec128, vec1->vec128 ); +} + +static inline void vmathP3MulPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->vec128 = vec_madd( pnt0->vec128, pnt1->vec128, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathP3DivPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->vec128 = divf4( pnt0->vec128, pnt1->vec128 ); +} + +static inline void vmathP3RecipPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ) +{ + result->vec128 = recipf4( pnt->vec128 ); +} + +static inline void vmathP3SqrtPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ) +{ + result->vec128 = sqrtf4( pnt->vec128 ); +} + +static inline void vmathP3RsqrtPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ) +{ + result->vec128 = rsqrtf4( pnt->vec128 ); +} + +static inline void vmathP3AbsPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ) +{ + result->vec128 = fabsf4( pnt->vec128 ); +} + +static inline void vmathP3CopySignPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->vec128 = copysignf4( pnt0->vec128, pnt1->vec128 ); +} + +static inline void vmathP3MaxPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->vec128 = fmaxf4( pnt0->vec128, pnt1->vec128 ); +} + +static inline float vmathP3MaxElem( const VmathPoint3 *pnt ) +{ + vec_float4 result; + result = fmaxf4( vec_splat( pnt->vec128, 1 ), pnt->vec128 ); + result = fmaxf4( vec_splat( pnt->vec128, 2 ), result ); + return _vmathVfGetElement(result, 0); +} + +static inline void vmathP3MinPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->vec128 = fminf4( pnt0->vec128, pnt1->vec128 ); +} + +static inline float vmathP3MinElem( const VmathPoint3 *pnt ) +{ + vec_float4 result; + result = fminf4( vec_splat( pnt->vec128, 1 ), pnt->vec128 ); + result = fminf4( vec_splat( pnt->vec128, 2 ), result ); + return _vmathVfGetElement(result, 0); +} + +static inline float vmathP3Sum( const VmathPoint3 *pnt ) +{ + vec_float4 result; + result = vec_add( vec_splat( pnt->vec128, 1 ), pnt->vec128 ); + result = vec_add( vec_splat( pnt->vec128, 2 ), result ); + return _vmathVfGetElement(result, 0); +} + +static inline void vmathP3Scale( VmathPoint3 *result, const VmathPoint3 *pnt, float scaleVal ) +{ + VmathPoint3 tmpP3_0; + vmathP3MakeFromScalar( &tmpP3_0, scaleVal ); + vmathP3MulPerElem( result, pnt, &tmpP3_0 ); +} + +static inline void vmathP3NonUniformScale( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *scaleVec ) +{ + VmathPoint3 tmpP3_0; + vmathP3MakeFromV3( &tmpP3_0, scaleVec ); + vmathP3MulPerElem( result, pnt, &tmpP3_0 ); +} + +static inline float vmathP3Projection( const VmathPoint3 *pnt, const VmathVector3 *unitVec ) +{ + vec_float4 result = _vmathVfDot3( pnt->vec128, unitVec->vec128 ); + return _vmathVfGetElement(result, 0); +} + +static inline float vmathP3DistSqrFromOrigin( const VmathPoint3 *pnt ) +{ + VmathVector3 tmpV3_0; + vmathV3MakeFromP3( &tmpV3_0, pnt ); + return vmathV3LengthSqr( &tmpV3_0 ); +} + +static inline float vmathP3DistFromOrigin( const VmathPoint3 *pnt ) +{ + VmathVector3 tmpV3_0; + vmathV3MakeFromP3( &tmpV3_0, pnt ); + return vmathV3Length( &tmpV3_0 ); +} + +static inline float vmathP3DistSqr( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + VmathVector3 tmpV3_0; + vmathP3Sub( &tmpV3_0, pnt1, pnt0 ); + return vmathV3LengthSqr( &tmpV3_0 ); +} + +static inline float vmathP3Dist( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + VmathVector3 tmpV3_0; + vmathP3Sub( &tmpV3_0, pnt1, pnt0 ); + return vmathV3Length( &tmpV3_0 ); +} + +static inline void vmathP3Select( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, unsigned int select1 ) +{ + unsigned int tmp; + tmp = (unsigned int)-(select1 > 0); + result->vec128 = vec_sel( pnt0->vec128, pnt1->vec128, _vmathVuiSplatScalar(tmp) ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathP3Print( const VmathPoint3 *pnt ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = pnt->vec128; + printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +static inline void vmathP3Prints( const VmathPoint3 *pnt, const char *name ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = pnt->vec128; + printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/vec_aos_v.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/vec_aos_v.h new file mode 100644 index 0000000..6dcc79c --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/vec_aos_v.h @@ -0,0 +1,953 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_AOS_V_C_H +#define _VECTORMATH_VEC_AOS_V_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + * for permutes words are labeled [x,y,z,w] [a,b,c,d] + */ +#define _VECTORMATH_PERM_X 0x00010203 +#define _VECTORMATH_PERM_Y 0x04050607 +#define _VECTORMATH_PERM_Z 0x08090a0b +#define _VECTORMATH_PERM_W 0x0c0d0e0f +#define _VECTORMATH_PERM_A 0x10111213 +#define _VECTORMATH_PERM_B 0x14151617 +#define _VECTORMATH_PERM_C 0x18191a1b +#define _VECTORMATH_PERM_D 0x1c1d1e1f +#define _VECTORMATH_PERM_XYZA (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A } +#define _VECTORMATH_PERM_ZXYW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_YZXW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_YZAB (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B } +#define _VECTORMATH_PERM_ZABC (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B, _VECTORMATH_PERM_C } +#define _VECTORMATH_PERM_XYAW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_XAZW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W } +#define _VECTORMATH_MASK_0xF000 (vec_uint4){ 0xffffffff, 0, 0, 0 } +#define _VECTORMATH_MASK_0x0F00 (vec_uint4){ 0, 0xffffffff, 0, 0 } +#define _VECTORMATH_MASK_0x00F0 (vec_uint4){ 0, 0, 0xffffffff, 0 } +#define _VECTORMATH_MASK_0x000F (vec_uint4){ 0, 0, 0, 0xffffffff } +#define _VECTORMATH_UNIT_1000 (vec_float4){ 1.0f, 0.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0100 (vec_float4){ 0.0f, 1.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0010 (vec_float4){ 0.0f, 0.0f, 1.0f, 0.0f } +#define _VECTORMATH_UNIT_0001 (vec_float4){ 0.0f, 0.0f, 0.0f, 1.0f } +#define _VECTORMATH_SLERP_TOL 0.999f + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline VmathVector3 vmathV3MakeFromElems_V( float _x, float _y, float _z ) +{ + VmathVector3 result; + vmathV3MakeFromElems(&result, _x, _y, _z); + return result; +} + +static inline VmathVector3 vmathV3MakeFromP3_V( VmathPoint3 pnt ) +{ + VmathVector3 result; + vmathV3MakeFromP3(&result, &pnt); + return result; +} + +static inline VmathVector3 vmathV3MakeFromScalar_V( float scalar ) +{ + VmathVector3 result; + vmathV3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathVector3 vmathV3MakeFrom128_V( vec_float4 vf4 ) +{ + VmathVector3 result; + vmathV3MakeFrom128(&result, vf4); + return result; +} + +static inline VmathVector3 vmathV3MakeXAxis_V( ) +{ + VmathVector3 result; + vmathV3MakeXAxis(&result); + return result; +} + +static inline VmathVector3 vmathV3MakeYAxis_V( ) +{ + VmathVector3 result; + vmathV3MakeYAxis(&result); + return result; +} + +static inline VmathVector3 vmathV3MakeZAxis_V( ) +{ + VmathVector3 result; + vmathV3MakeZAxis(&result); + return result; +} + +static inline VmathVector3 vmathV3Lerp_V( float t, VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3Lerp(&result, t, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3Slerp_V( float t, VmathVector3 unitVec0, VmathVector3 unitVec1 ) +{ + VmathVector3 result; + vmathV3Slerp(&result, t, &unitVec0, &unitVec1); + return result; +} + +static inline vec_float4 vmathV3Get128_V( VmathVector3 vec ) +{ + return vmathV3Get128(&vec); +} + +static inline void vmathV3StoreXYZ_V( VmathVector3 vec, vec_float4 *quad ) +{ + vmathV3StoreXYZ(&vec, quad); +} + +static inline void vmathV3LoadXYZArray_V( VmathVector3 *vec0, VmathVector3 *vec1, VmathVector3 *vec2, VmathVector3 *vec3, const vec_float4 *threeQuads ) +{ + vmathV3LoadXYZArray(vec0, vec1, vec2, vec3, threeQuads); +} + +static inline void vmathV3StoreXYZArray_V( VmathVector3 vec0, VmathVector3 vec1, VmathVector3 vec2, VmathVector3 vec3, vec_float4 *threeQuads ) +{ + vmathV3StoreXYZArray(&vec0, &vec1, &vec2, &vec3, threeQuads); +} + +static inline void vmathV3StoreHalfFloats_V( VmathVector3 vec0, VmathVector3 vec1, VmathVector3 vec2, VmathVector3 vec3, VmathVector3 vec4, VmathVector3 vec5, VmathVector3 vec6, VmathVector3 vec7, vec_ushort8 *threeQuads ) +{ + vmathV3StoreHalfFloats(&vec0, &vec1, &vec2, &vec3, &vec4, &vec5, &vec6, &vec7, threeQuads); +} + +static inline void vmathV3SetX_V( VmathVector3 *result, float _x ) +{ + vmathV3SetX(result, _x); +} + +static inline float vmathV3GetX_V( VmathVector3 vec ) +{ + return vmathV3GetX(&vec); +} + +static inline void vmathV3SetY_V( VmathVector3 *result, float _y ) +{ + vmathV3SetY(result, _y); +} + +static inline float vmathV3GetY_V( VmathVector3 vec ) +{ + return vmathV3GetY(&vec); +} + +static inline void vmathV3SetZ_V( VmathVector3 *result, float _z ) +{ + vmathV3SetZ(result, _z); +} + +static inline float vmathV3GetZ_V( VmathVector3 vec ) +{ + return vmathV3GetZ(&vec); +} + +static inline void vmathV3SetElem_V( VmathVector3 *result, int idx, float value ) +{ + vmathV3SetElem(result, idx, value); +} + +static inline float vmathV3GetElem_V( VmathVector3 vec, int idx ) +{ + return vmathV3GetElem(&vec, idx); +} + +static inline VmathVector3 vmathV3Add_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3Add(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3Sub_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3Sub(&result, &vec0, &vec1); + return result; +} + +static inline VmathPoint3 vmathV3AddP3_V( VmathVector3 vec, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathV3AddP3(&result, &vec, &pnt1); + return result; +} + +static inline VmathVector3 vmathV3ScalarMul_V( VmathVector3 vec, float scalar ) +{ + VmathVector3 result; + vmathV3ScalarMul(&result, &vec, scalar); + return result; +} + +static inline VmathVector3 vmathV3ScalarDiv_V( VmathVector3 vec, float scalar ) +{ + VmathVector3 result; + vmathV3ScalarDiv(&result, &vec, scalar); + return result; +} + +static inline VmathVector3 vmathV3Neg_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3Neg(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3MulPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3MulPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3DivPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3DivPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3RecipPerElem_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3RecipPerElem(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3SqrtPerElem_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3SqrtPerElem(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3RsqrtPerElem_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3RsqrtPerElem(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3AbsPerElem_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3AbsPerElem(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3CopySignPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3CopySignPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3MaxPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3MaxPerElem(&result, &vec0, &vec1); + return result; +} + +static inline float vmathV3MaxElem_V( VmathVector3 vec ) +{ + return vmathV3MaxElem(&vec); +} + +static inline VmathVector3 vmathV3MinPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3MinPerElem(&result, &vec0, &vec1); + return result; +} + +static inline float vmathV3MinElem_V( VmathVector3 vec ) +{ + return vmathV3MinElem(&vec); +} + +static inline float vmathV3Sum_V( VmathVector3 vec ) +{ + return vmathV3Sum(&vec); +} + +static inline float vmathV3Dot_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + return vmathV3Dot(&vec0, &vec1); +} + +static inline float vmathV3LengthSqr_V( VmathVector3 vec ) +{ + return vmathV3LengthSqr(&vec); +} + +static inline float vmathV3Length_V( VmathVector3 vec ) +{ + return vmathV3Length(&vec); +} + +static inline VmathVector3 vmathV3Normalize_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3Normalize(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3Cross_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3Cross(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3Select_V( VmathVector3 vec0, VmathVector3 vec1, unsigned int select1 ) +{ + VmathVector3 result; + vmathV3Select(&result, &vec0, &vec1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathV3Print_V( VmathVector3 vec ) +{ + vmathV3Print(&vec); +} + +static inline void vmathV3Prints_V( VmathVector3 vec, const char *name ) +{ + vmathV3Prints(&vec, name); +} + +#endif + +static inline VmathVector4 vmathV4MakeFromElems_V( float _x, float _y, float _z, float _w ) +{ + VmathVector4 result; + vmathV4MakeFromElems(&result, _x, _y, _z, _w); + return result; +} + +static inline VmathVector4 vmathV4MakeFromV3Scalar_V( VmathVector3 xyz, float _w ) +{ + VmathVector4 result; + vmathV4MakeFromV3Scalar(&result, &xyz, _w); + return result; +} + +static inline VmathVector4 vmathV4MakeFromV3_V( VmathVector3 vec ) +{ + VmathVector4 result; + vmathV4MakeFromV3(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4MakeFromP3_V( VmathPoint3 pnt ) +{ + VmathVector4 result; + vmathV4MakeFromP3(&result, &pnt); + return result; +} + +static inline VmathVector4 vmathV4MakeFromQ_V( VmathQuat quat ) +{ + VmathVector4 result; + vmathV4MakeFromQ(&result, &quat); + return result; +} + +static inline VmathVector4 vmathV4MakeFromScalar_V( float scalar ) +{ + VmathVector4 result; + vmathV4MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathVector4 vmathV4MakeFrom128_V( vec_float4 vf4 ) +{ + VmathVector4 result; + vmathV4MakeFrom128(&result, vf4); + return result; +} + +static inline VmathVector4 vmathV4MakeXAxis_V( ) +{ + VmathVector4 result; + vmathV4MakeXAxis(&result); + return result; +} + +static inline VmathVector4 vmathV4MakeYAxis_V( ) +{ + VmathVector4 result; + vmathV4MakeYAxis(&result); + return result; +} + +static inline VmathVector4 vmathV4MakeZAxis_V( ) +{ + VmathVector4 result; + vmathV4MakeZAxis(&result); + return result; +} + +static inline VmathVector4 vmathV4MakeWAxis_V( ) +{ + VmathVector4 result; + vmathV4MakeWAxis(&result); + return result; +} + +static inline VmathVector4 vmathV4Lerp_V( float t, VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4Lerp(&result, t, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4Slerp_V( float t, VmathVector4 unitVec0, VmathVector4 unitVec1 ) +{ + VmathVector4 result; + vmathV4Slerp(&result, t, &unitVec0, &unitVec1); + return result; +} + +static inline vec_float4 vmathV4Get128_V( VmathVector4 vec ) +{ + return vmathV4Get128(&vec); +} + +static inline void vmathV4StoreHalfFloats_V( VmathVector4 vec0, VmathVector4 vec1, VmathVector4 vec2, VmathVector4 vec3, vec_ushort8 *twoQuads ) +{ + vmathV4StoreHalfFloats(&vec0, &vec1, &vec2, &vec3, twoQuads); +} + +static inline void vmathV4SetXYZ_V( VmathVector4 *result, VmathVector3 vec ) +{ + vmathV4SetXYZ(result, &vec); +} + +static inline VmathVector3 vmathV4GetXYZ_V( VmathVector4 vec ) +{ + VmathVector3 result; + vmathV4GetXYZ(&result, &vec); + return result; +} + +static inline void vmathV4SetX_V( VmathVector4 *result, float _x ) +{ + vmathV4SetX(result, _x); +} + +static inline float vmathV4GetX_V( VmathVector4 vec ) +{ + return vmathV4GetX(&vec); +} + +static inline void vmathV4SetY_V( VmathVector4 *result, float _y ) +{ + vmathV4SetY(result, _y); +} + +static inline float vmathV4GetY_V( VmathVector4 vec ) +{ + return vmathV4GetY(&vec); +} + +static inline void vmathV4SetZ_V( VmathVector4 *result, float _z ) +{ + vmathV4SetZ(result, _z); +} + +static inline float vmathV4GetZ_V( VmathVector4 vec ) +{ + return vmathV4GetZ(&vec); +} + +static inline void vmathV4SetW_V( VmathVector4 *result, float _w ) +{ + vmathV4SetW(result, _w); +} + +static inline float vmathV4GetW_V( VmathVector4 vec ) +{ + return vmathV4GetW(&vec); +} + +static inline void vmathV4SetElem_V( VmathVector4 *result, int idx, float value ) +{ + vmathV4SetElem(result, idx, value); +} + +static inline float vmathV4GetElem_V( VmathVector4 vec, int idx ) +{ + return vmathV4GetElem(&vec, idx); +} + +static inline VmathVector4 vmathV4Add_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4Add(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4Sub_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4Sub(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4ScalarMul_V( VmathVector4 vec, float scalar ) +{ + VmathVector4 result; + vmathV4ScalarMul(&result, &vec, scalar); + return result; +} + +static inline VmathVector4 vmathV4ScalarDiv_V( VmathVector4 vec, float scalar ) +{ + VmathVector4 result; + vmathV4ScalarDiv(&result, &vec, scalar); + return result; +} + +static inline VmathVector4 vmathV4Neg_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4Neg(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4MulPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4MulPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4DivPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4DivPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4RecipPerElem_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4RecipPerElem(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4SqrtPerElem_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4SqrtPerElem(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4RsqrtPerElem_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4RsqrtPerElem(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4AbsPerElem_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4AbsPerElem(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4CopySignPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4CopySignPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4MaxPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4MaxPerElem(&result, &vec0, &vec1); + return result; +} + +static inline float vmathV4MaxElem_V( VmathVector4 vec ) +{ + return vmathV4MaxElem(&vec); +} + +static inline VmathVector4 vmathV4MinPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4MinPerElem(&result, &vec0, &vec1); + return result; +} + +static inline float vmathV4MinElem_V( VmathVector4 vec ) +{ + return vmathV4MinElem(&vec); +} + +static inline float vmathV4Sum_V( VmathVector4 vec ) +{ + return vmathV4Sum(&vec); +} + +static inline float vmathV4Dot_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + return vmathV4Dot(&vec0, &vec1); +} + +static inline float vmathV4LengthSqr_V( VmathVector4 vec ) +{ + return vmathV4LengthSqr(&vec); +} + +static inline float vmathV4Length_V( VmathVector4 vec ) +{ + return vmathV4Length(&vec); +} + +static inline VmathVector4 vmathV4Normalize_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4Normalize(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4Select_V( VmathVector4 vec0, VmathVector4 vec1, unsigned int select1 ) +{ + VmathVector4 result; + vmathV4Select(&result, &vec0, &vec1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathV4Print_V( VmathVector4 vec ) +{ + vmathV4Print(&vec); +} + +static inline void vmathV4Prints_V( VmathVector4 vec, const char *name ) +{ + vmathV4Prints(&vec, name); +} + +#endif + +static inline VmathPoint3 vmathP3MakeFromElems_V( float _x, float _y, float _z ) +{ + VmathPoint3 result; + vmathP3MakeFromElems(&result, _x, _y, _z); + return result; +} + +static inline VmathPoint3 vmathP3MakeFromV3_V( VmathVector3 vec ) +{ + VmathPoint3 result; + vmathP3MakeFromV3(&result, &vec); + return result; +} + +static inline VmathPoint3 vmathP3MakeFromScalar_V( float scalar ) +{ + VmathPoint3 result; + vmathP3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathPoint3 vmathP3MakeFrom128_V( vec_float4 vf4 ) +{ + VmathPoint3 result; + vmathP3MakeFrom128(&result, vf4); + return result; +} + +static inline VmathPoint3 vmathP3Lerp_V( float t, VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3Lerp(&result, t, &pnt0, &pnt1); + return result; +} + +static inline vec_float4 vmathP3Get128_V( VmathPoint3 pnt ) +{ + return vmathP3Get128(&pnt); +} + +static inline void vmathP3StoreXYZ_V( VmathPoint3 pnt, vec_float4 *quad ) +{ + vmathP3StoreXYZ(&pnt, quad); +} + +static inline void vmathP3LoadXYZArray_V( VmathPoint3 *pnt0, VmathPoint3 *pnt1, VmathPoint3 *pnt2, VmathPoint3 *pnt3, const vec_float4 *threeQuads ) +{ + vmathP3LoadXYZArray(pnt0, pnt1, pnt2, pnt3, threeQuads); +} + +static inline void vmathP3StoreXYZArray_V( VmathPoint3 pnt0, VmathPoint3 pnt1, VmathPoint3 pnt2, VmathPoint3 pnt3, vec_float4 *threeQuads ) +{ + vmathP3StoreXYZArray(&pnt0, &pnt1, &pnt2, &pnt3, threeQuads); +} + +static inline void vmathP3StoreHalfFloats_V( VmathPoint3 pnt0, VmathPoint3 pnt1, VmathPoint3 pnt2, VmathPoint3 pnt3, VmathPoint3 pnt4, VmathPoint3 pnt5, VmathPoint3 pnt6, VmathPoint3 pnt7, vec_ushort8 *threeQuads ) +{ + vmathP3StoreHalfFloats(&pnt0, &pnt1, &pnt2, &pnt3, &pnt4, &pnt5, &pnt6, &pnt7, threeQuads); +} + +static inline void vmathP3SetX_V( VmathPoint3 *result, float _x ) +{ + vmathP3SetX(result, _x); +} + +static inline float vmathP3GetX_V( VmathPoint3 pnt ) +{ + return vmathP3GetX(&pnt); +} + +static inline void vmathP3SetY_V( VmathPoint3 *result, float _y ) +{ + vmathP3SetY(result, _y); +} + +static inline float vmathP3GetY_V( VmathPoint3 pnt ) +{ + return vmathP3GetY(&pnt); +} + +static inline void vmathP3SetZ_V( VmathPoint3 *result, float _z ) +{ + vmathP3SetZ(result, _z); +} + +static inline float vmathP3GetZ_V( VmathPoint3 pnt ) +{ + return vmathP3GetZ(&pnt); +} + +static inline void vmathP3SetElem_V( VmathPoint3 *result, int idx, float value ) +{ + vmathP3SetElem(result, idx, value); +} + +static inline float vmathP3GetElem_V( VmathPoint3 pnt, int idx ) +{ + return vmathP3GetElem(&pnt, idx); +} + +static inline VmathVector3 vmathP3Sub_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathVector3 result; + vmathP3Sub(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathPoint3 vmathP3AddV3_V( VmathPoint3 pnt, VmathVector3 vec1 ) +{ + VmathPoint3 result; + vmathP3AddV3(&result, &pnt, &vec1); + return result; +} + +static inline VmathPoint3 vmathP3SubV3_V( VmathPoint3 pnt, VmathVector3 vec1 ) +{ + VmathPoint3 result; + vmathP3SubV3(&result, &pnt, &vec1); + return result; +} + +static inline VmathPoint3 vmathP3MulPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3MulPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathPoint3 vmathP3DivPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3DivPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathPoint3 vmathP3RecipPerElem_V( VmathPoint3 pnt ) +{ + VmathPoint3 result; + vmathP3RecipPerElem(&result, &pnt); + return result; +} + +static inline VmathPoint3 vmathP3SqrtPerElem_V( VmathPoint3 pnt ) +{ + VmathPoint3 result; + vmathP3SqrtPerElem(&result, &pnt); + return result; +} + +static inline VmathPoint3 vmathP3RsqrtPerElem_V( VmathPoint3 pnt ) +{ + VmathPoint3 result; + vmathP3RsqrtPerElem(&result, &pnt); + return result; +} + +static inline VmathPoint3 vmathP3AbsPerElem_V( VmathPoint3 pnt ) +{ + VmathPoint3 result; + vmathP3AbsPerElem(&result, &pnt); + return result; +} + +static inline VmathPoint3 vmathP3CopySignPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3CopySignPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathPoint3 vmathP3MaxPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3MaxPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline float vmathP3MaxElem_V( VmathPoint3 pnt ) +{ + return vmathP3MaxElem(&pnt); +} + +static inline VmathPoint3 vmathP3MinPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3MinPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline float vmathP3MinElem_V( VmathPoint3 pnt ) +{ + return vmathP3MinElem(&pnt); +} + +static inline float vmathP3Sum_V( VmathPoint3 pnt ) +{ + return vmathP3Sum(&pnt); +} + +static inline VmathPoint3 vmathP3Scale_V( VmathPoint3 pnt, float scaleVal ) +{ + VmathPoint3 result; + vmathP3Scale(&result, &pnt, scaleVal); + return result; +} + +static inline VmathPoint3 vmathP3NonUniformScale_V( VmathPoint3 pnt, VmathVector3 scaleVec ) +{ + VmathPoint3 result; + vmathP3NonUniformScale(&result, &pnt, &scaleVec); + return result; +} + +static inline float vmathP3Projection_V( VmathPoint3 pnt, VmathVector3 unitVec ) +{ + return vmathP3Projection(&pnt, &unitVec); +} + +static inline float vmathP3DistSqrFromOrigin_V( VmathPoint3 pnt ) +{ + return vmathP3DistSqrFromOrigin(&pnt); +} + +static inline float vmathP3DistFromOrigin_V( VmathPoint3 pnt ) +{ + return vmathP3DistFromOrigin(&pnt); +} + +static inline float vmathP3DistSqr_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + return vmathP3DistSqr(&pnt0, &pnt1); +} + +static inline float vmathP3Dist_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + return vmathP3Dist(&pnt0, &pnt1); +} + +static inline VmathPoint3 vmathP3Select_V( VmathPoint3 pnt0, VmathPoint3 pnt1, unsigned int select1 ) +{ + VmathPoint3 result; + vmathP3Select(&result, &pnt0, &pnt1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathP3Print_V( VmathPoint3 pnt ) +{ + vmathP3Print(&pnt); +} + +static inline void vmathP3Prints_V( VmathPoint3 pnt, const char *name ) +{ + vmathP3Prints(&pnt, name); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/vec_soa.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/vec_soa.h new file mode 100644 index 0000000..1cda257 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/vec_soa.h @@ -0,0 +1,1223 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_SOA_C_H +#define _VECTORMATH_VEC_SOA_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + * for permutes, words are labeled [x,y,z,w] [a,b,c,d] + */ +#define _VECTORMATH_PERM_X 0x00010203 +#define _VECTORMATH_PERM_Y 0x04050607 +#define _VECTORMATH_PERM_Z 0x08090a0b +#define _VECTORMATH_PERM_W 0x0c0d0e0f +#define _VECTORMATH_PERM_A 0x10111213 +#define _VECTORMATH_PERM_B 0x14151617 +#define _VECTORMATH_PERM_C 0x18191a1b +#define _VECTORMATH_PERM_D 0x1c1d1e1f +#define _VECTORMATH_PERM_ZBWX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XCYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_C, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_ZDWX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_D, _VECTORMATH_PERM_W, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_ZCXA ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_A }) +#define _VECTORMATH_PERM_XBZD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_B, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_WDYB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_W, _VECTORMATH_PERM_D, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_ZBXD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_X, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_WCYA ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_W, _VECTORMATH_PERM_C, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A }) +#define _VECTORMATH_PERM_XDZB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_D, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B }) +#define _VECTORMATH_SLERP_TOL 0.999f + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline void vmathSoaV3Copy( VmathSoaVector3 *result, const VmathSoaVector3 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; +} + +static inline void vmathSoaV3MakeFromElems( VmathSoaVector3 *result, vec_float4 _x, vec_float4 _y, vec_float4 _z ) +{ + result->x = _x; + result->y = _y; + result->z = _z; +} + +static inline void vmathSoaV3MakeFromP3( VmathSoaVector3 *result, const VmathSoaPoint3 *pnt ) +{ + result->x = pnt->x; + result->y = pnt->y; + result->z = pnt->z; +} + +static inline void vmathSoaV3MakeFromScalar( VmathSoaVector3 *result, vec_float4 scalar ) +{ + result->x = scalar; + result->y = scalar; + result->z = scalar; +} + +static inline void vmathSoaV3MakeFromAos( VmathSoaVector3 *result, const VmathVector3 *vec ) +{ + vec_float4 vec128 = vec->vec128; + result->x = vec_splat( vec128, 0 ); + result->y = vec_splat( vec128, 1 ); + result->z = vec_splat( vec128, 2 ); +} + +static inline void vmathSoaV3MakeFrom4Aos( VmathSoaVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1, const VmathVector3 *vec2, const VmathVector3 *vec3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = vec_mergeh( vec0->vec128, vec2->vec128 ); + tmp1 = vec_mergeh( vec1->vec128, vec3->vec128 ); + tmp2 = vec_mergel( vec0->vec128, vec2->vec128 ); + tmp3 = vec_mergel( vec1->vec128, vec3->vec128 ); + result->x = vec_mergeh( tmp0, tmp1 ); + result->y = vec_mergel( tmp0, tmp1 ); + result->z = vec_mergeh( tmp2, tmp3 ); +} + +static inline void vmathSoaV3MakeXAxis( VmathSoaVector3 *result ) +{ + vmathSoaV3MakeFromElems( result, ((vec_float4){1.0f,1.0f,1.0f,1.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaV3MakeYAxis( VmathSoaVector3 *result ) +{ + vmathSoaV3MakeFromElems( result, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){1.0f,1.0f,1.0f,1.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaV3MakeZAxis( VmathSoaVector3 *result ) +{ + vmathSoaV3MakeFromElems( result, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); +} + +static inline void vmathSoaV3Lerp( VmathSoaVector3 *result, vec_float4 t, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + VmathSoaVector3 tmpV3_0, tmpV3_1; + vmathSoaV3Sub( &tmpV3_0, vec1, vec0 ); + vmathSoaV3ScalarMul( &tmpV3_1, &tmpV3_0, t ); + vmathSoaV3Add( result, vec0, &tmpV3_1 ); +} + +static inline void vmathSoaV3Slerp( VmathSoaVector3 *result, vec_float4 t, const VmathSoaVector3 *unitVec0, const VmathSoaVector3 *unitVec1 ) +{ + VmathSoaVector3 tmpV3_0, tmpV3_1; + vec_float4 recipSinAngle, scale0, scale1, cosAngle, angle; + vec_uint4 selectMask; + cosAngle = vmathSoaV3Dot( unitVec0, unitVec1 ); + selectMask = (vec_uint4)vec_cmpgt( (vec_float4){_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL}, cosAngle ); + angle = acosf4( cosAngle ); + recipSinAngle = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sinf4( angle ) ); + scale0 = vec_sel( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), t ), vec_madd( sinf4( vec_madd( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), t ), angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), recipSinAngle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), selectMask ); + scale1 = vec_sel( t, vec_madd( sinf4( vec_madd( t, angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), recipSinAngle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), selectMask ); + vmathSoaV3ScalarMul( &tmpV3_0, unitVec0, scale0 ); + vmathSoaV3ScalarMul( &tmpV3_1, unitVec1, scale1 ); + vmathSoaV3Add( result, &tmpV3_0, &tmpV3_1 ); +} + +static inline void vmathSoaV3Get4Aos( const VmathSoaVector3 *vec, VmathVector3 *result0, VmathVector3 *result1, VmathVector3 *result2, VmathVector3 *result3 ) +{ + vec_float4 tmp0, tmp1; + tmp0 = vec_mergeh( vec->x, vec->z ); + tmp1 = vec_mergel( vec->x, vec->z ); + vmathV3MakeFrom128( result0, vec_mergeh( tmp0, vec->y ) ); + vmathV3MakeFrom128( result1, vec_perm( tmp0, vec->y, _VECTORMATH_PERM_ZBWX ) ); + vmathV3MakeFrom128( result2, vec_perm( tmp1, vec->y, _VECTORMATH_PERM_XCYX ) ); + vmathV3MakeFrom128( result3, vec_perm( tmp1, vec->y, _VECTORMATH_PERM_ZDWX ) ); +} + +static inline void vmathSoaV3LoadXYZArray( VmathSoaVector3 *vec, const vec_float4 *threeQuads ) +{ + vec_float4 xyxy, yzyz, zxzx, xyzx, yzxy, zxyz; + xyzx = threeQuads[0]; + yzxy = threeQuads[1]; + zxyz = threeQuads[2]; + xyxy = vec_sld( yzxy, xyzx, 8 ); + zxzx = vec_sld( xyzx, zxyz, 8 ); + yzyz = vec_sld( zxyz, yzxy, 8 ); + vmathSoaV3SetX( vec, vec_perm( xyxy, zxzx, _VECTORMATH_PERM_ZBXD ) ); + vmathSoaV3SetY( vec, vec_perm( xyxy, yzyz, _VECTORMATH_PERM_WCYA ) ); + vmathSoaV3SetZ( vec, vec_perm( zxzx, yzyz, _VECTORMATH_PERM_XDZB ) ); +} + +static inline void vmathSoaV3StoreXYZArray( const VmathSoaVector3 *vec, vec_float4 *threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz, xyxy, zxzx, yzyz; + xyxy = vec_perm( vec->x, vec->y, _VECTORMATH_PERM_ZCXA ); + zxzx = vec_perm( vec->z, vec->x, _VECTORMATH_PERM_XBZD ); + yzyz = vec_perm( vec->y, vec->z, _VECTORMATH_PERM_WDYB ); + xyzx = vec_sld( xyxy, zxzx, 8 ); + yzxy = vec_sld( yzyz, xyxy, 8 ); + zxyz = vec_sld( zxzx, yzyz, 8 ); + threeQuads[0] = xyzx; + threeQuads[1] = yzxy; + threeQuads[2] = zxyz; +} + +static inline void vmathSoaV3StoreHalfFloats( const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1, vec_ushort8 *threeQuads ) +{ + vec_float4 xyz0[3]; + vec_float4 xyz1[3]; + vmathSoaV3StoreXYZArray( vec0, xyz0 ); + vmathSoaV3StoreXYZArray( vec1, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +} + +static inline void vmathSoaV3SetX( VmathSoaVector3 *result, vec_float4 _x ) +{ + result->x = _x; +} + +static inline vec_float4 vmathSoaV3GetX( const VmathSoaVector3 *vec ) +{ + return vec->x; +} + +static inline void vmathSoaV3SetY( VmathSoaVector3 *result, vec_float4 _y ) +{ + result->y = _y; +} + +static inline vec_float4 vmathSoaV3GetY( const VmathSoaVector3 *vec ) +{ + return vec->y; +} + +static inline void vmathSoaV3SetZ( VmathSoaVector3 *result, vec_float4 _z ) +{ + result->z = _z; +} + +static inline vec_float4 vmathSoaV3GetZ( const VmathSoaVector3 *vec ) +{ + return vec->z; +} + +static inline void vmathSoaV3SetElem( VmathSoaVector3 *result, int idx, vec_float4 value ) +{ + *(&result->x + idx) = value; +} + +static inline vec_float4 vmathSoaV3GetElem( const VmathSoaVector3 *vec, int idx ) +{ + return *(&vec->x + idx); +} + +static inline void vmathSoaV3Add( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + result->x = vec_add( vec0->x, vec1->x ); + result->y = vec_add( vec0->y, vec1->y ); + result->z = vec_add( vec0->z, vec1->z ); +} + +static inline void vmathSoaV3Sub( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + result->x = vec_sub( vec0->x, vec1->x ); + result->y = vec_sub( vec0->y, vec1->y ); + result->z = vec_sub( vec0->z, vec1->z ); +} + +static inline void vmathSoaV3AddP3( VmathSoaPoint3 *result, const VmathSoaVector3 *vec, const VmathSoaPoint3 *pnt1 ) +{ + result->x = vec_add( vec->x, pnt1->x ); + result->y = vec_add( vec->y, pnt1->y ); + result->z = vec_add( vec->z, pnt1->z ); +} + +static inline void vmathSoaV3ScalarMul( VmathSoaVector3 *result, const VmathSoaVector3 *vec, vec_float4 scalar ) +{ + result->x = vec_madd( vec->x, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->y = vec_madd( vec->y, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->z = vec_madd( vec->z, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaV3ScalarDiv( VmathSoaVector3 *result, const VmathSoaVector3 *vec, vec_float4 scalar ) +{ + result->x = divf4( vec->x, scalar ); + result->y = divf4( vec->y, scalar ); + result->z = divf4( vec->z, scalar ); +} + +static inline void vmathSoaV3Neg( VmathSoaVector3 *result, const VmathSoaVector3 *vec ) +{ + result->x = negatef4( vec->x ); + result->y = negatef4( vec->y ); + result->z = negatef4( vec->z ); +} + +static inline void vmathSoaV3MulPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + result->x = vec_madd( vec0->x, vec1->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->y = vec_madd( vec0->y, vec1->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->z = vec_madd( vec0->z, vec1->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaV3DivPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + result->x = divf4( vec0->x, vec1->x ); + result->y = divf4( vec0->y, vec1->y ); + result->z = divf4( vec0->z, vec1->z ); +} + +static inline void vmathSoaV3RecipPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec ) +{ + result->x = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec->x ); + result->y = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec->y ); + result->z = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec->z ); +} + +static inline void vmathSoaV3SqrtPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec ) +{ + result->x = sqrtf4( vec->x ); + result->y = sqrtf4( vec->y ); + result->z = sqrtf4( vec->z ); +} + +static inline void vmathSoaV3RsqrtPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec ) +{ + result->x = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( vec->x ) ); + result->y = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( vec->y ) ); + result->z = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( vec->z ) ); +} + +static inline void vmathSoaV3AbsPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec ) +{ + result->x = fabsf4( vec->x ); + result->y = fabsf4( vec->y ); + result->z = fabsf4( vec->z ); +} + +static inline void vmathSoaV3CopySignPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + result->x = copysignf4( vec0->x, vec1->x ); + result->y = copysignf4( vec0->y, vec1->y ); + result->z = copysignf4( vec0->z, vec1->z ); +} + +static inline void vmathSoaV3MaxPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + result->x = fmaxf4( vec0->x, vec1->x ); + result->y = fmaxf4( vec0->y, vec1->y ); + result->z = fmaxf4( vec0->z, vec1->z ); +} + +static inline vec_float4 vmathSoaV3MaxElem( const VmathSoaVector3 *vec ) +{ + vec_float4 result; + result = fmaxf4( vec->x, vec->y ); + result = fmaxf4( vec->z, result ); + return result; +} + +static inline void vmathSoaV3MinPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + result->x = fminf4( vec0->x, vec1->x ); + result->y = fminf4( vec0->y, vec1->y ); + result->z = fminf4( vec0->z, vec1->z ); +} + +static inline vec_float4 vmathSoaV3MinElem( const VmathSoaVector3 *vec ) +{ + vec_float4 result; + result = fminf4( vec->x, vec->y ); + result = fminf4( vec->z, result ); + return result; +} + +static inline vec_float4 vmathSoaV3Sum( const VmathSoaVector3 *vec ) +{ + vec_float4 result; + result = vec_add( vec->x, vec->y ); + result = vec_add( result, vec->z ); + return result; +} + +static inline vec_float4 vmathSoaV3Dot( const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + vec_float4 result; + result = vec_madd( vec0->x, vec1->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result = vec_add( result, vec_madd( vec0->y, vec1->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( vec0->z, vec1->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return result; +} + +static inline vec_float4 vmathSoaV3LengthSqr( const VmathSoaVector3 *vec ) +{ + vec_float4 result; + result = vec_madd( vec->x, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result = vec_add( result, vec_madd( vec->y, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( vec->z, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return result; +} + +static inline vec_float4 vmathSoaV3Length( const VmathSoaVector3 *vec ) +{ + return sqrtf4( vmathSoaV3LengthSqr( vec ) ); +} + +static inline void vmathSoaV3Normalize( VmathSoaVector3 *result, const VmathSoaVector3 *vec ) +{ + vec_float4 lenSqr, lenInv; + lenSqr = vmathSoaV3LengthSqr( vec ); + lenInv = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( lenSqr ) ); + result->x = vec_madd( vec->x, lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->y = vec_madd( vec->y, lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->z = vec_madd( vec->z, lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaV3Cross( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + vec_float4 tmpX, tmpY, tmpZ; + tmpX = vec_sub( vec_madd( vec0->y, vec1->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( vec0->z, vec1->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpY = vec_sub( vec_madd( vec0->z, vec1->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( vec0->x, vec1->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpZ = vec_sub( vec_madd( vec0->x, vec1->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( vec0->y, vec1->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + vmathSoaV3MakeFromElems( result, tmpX, tmpY, tmpZ ); +} + +static inline void vmathSoaV3Select( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1, vec_uint4 select1 ) +{ + result->x = vec_sel( vec0->x, vec1->x, select1 ); + result->y = vec_sel( vec0->y, vec1->y, select1 ); + result->z = vec_sel( vec0->z, vec1->z, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaV3Print( const VmathSoaVector3 *vec ) +{ + VmathVector3 vec0, vec1, vec2, vec3; + vmathSoaV3Get4Aos( vec, &vec0, &vec1, &vec2, &vec3 ); + printf("slot 0:\n"); + vmathV3Print( &vec0 ); + printf("slot 1:\n"); + vmathV3Print( &vec1 ); + printf("slot 2:\n"); + vmathV3Print( &vec2 ); + printf("slot 3:\n"); + vmathV3Print( &vec3 ); +} + +static inline void vmathSoaV3Prints( const VmathSoaVector3 *vec, const char *name ) +{ + VmathVector3 vec0, vec1, vec2, vec3; + printf( "%s:\n", name ); + vmathSoaV3Get4Aos( vec, &vec0, &vec1, &vec2, &vec3 ); + printf("slot 0:\n"); + vmathV3Print( &vec0 ); + printf("slot 1:\n"); + vmathV3Print( &vec1 ); + printf("slot 2:\n"); + vmathV3Print( &vec2 ); + printf("slot 3:\n"); + vmathV3Print( &vec3 ); +} + +#endif + +static inline void vmathSoaV4Copy( VmathSoaVector4 *result, const VmathSoaVector4 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; + result->w = vec->w; +} + +static inline void vmathSoaV4MakeFromElems( VmathSoaVector4 *result, vec_float4 _x, vec_float4 _y, vec_float4 _z, vec_float4 _w ) +{ + result->x = _x; + result->y = _y; + result->z = _z; + result->w = _w; +} + +static inline void vmathSoaV4MakeFromV3Scalar( VmathSoaVector4 *result, const VmathSoaVector3 *xyz, vec_float4 _w ) +{ + vmathSoaV4SetXYZ( result, xyz ); + vmathSoaV4SetW( result, _w ); +} + +static inline void vmathSoaV4MakeFromV3( VmathSoaVector4 *result, const VmathSoaVector3 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; + result->w = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); +} + +static inline void vmathSoaV4MakeFromP3( VmathSoaVector4 *result, const VmathSoaPoint3 *pnt ) +{ + result->x = pnt->x; + result->y = pnt->y; + result->z = pnt->z; + result->w = ((vec_float4){1.0f,1.0f,1.0f,1.0f}); +} + +static inline void vmathSoaV4MakeFromQ( VmathSoaVector4 *result, const VmathSoaQuat *quat ) +{ + result->x = quat->x; + result->y = quat->y; + result->z = quat->z; + result->w = quat->w; +} + +static inline void vmathSoaV4MakeFromScalar( VmathSoaVector4 *result, vec_float4 scalar ) +{ + result->x = scalar; + result->y = scalar; + result->z = scalar; + result->w = scalar; +} + +static inline void vmathSoaV4MakeFromAos( VmathSoaVector4 *result, const VmathVector4 *vec ) +{ + vec_float4 vec128 = vec->vec128; + result->x = vec_splat( vec128, 0 ); + result->y = vec_splat( vec128, 1 ); + result->z = vec_splat( vec128, 2 ); + result->w = vec_splat( vec128, 3 ); +} + +static inline void vmathSoaV4MakeFrom4Aos( VmathSoaVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1, const VmathVector4 *vec2, const VmathVector4 *vec3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = vec_mergeh( vec0->vec128, vec2->vec128 ); + tmp1 = vec_mergeh( vec1->vec128, vec3->vec128 ); + tmp2 = vec_mergel( vec0->vec128, vec2->vec128 ); + tmp3 = vec_mergel( vec1->vec128, vec3->vec128 ); + result->x = vec_mergeh( tmp0, tmp1 ); + result->y = vec_mergel( tmp0, tmp1 ); + result->z = vec_mergeh( tmp2, tmp3 ); + result->w = vec_mergel( tmp2, tmp3 ); +} + +static inline void vmathSoaV4MakeXAxis( VmathSoaVector4 *result ) +{ + vmathSoaV4MakeFromElems( result, ((vec_float4){1.0f,1.0f,1.0f,1.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaV4MakeYAxis( VmathSoaVector4 *result ) +{ + vmathSoaV4MakeFromElems( result, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){1.0f,1.0f,1.0f,1.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaV4MakeZAxis( VmathSoaVector4 *result ) +{ + vmathSoaV4MakeFromElems( result, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){1.0f,1.0f,1.0f,1.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaV4MakeWAxis( VmathSoaVector4 *result ) +{ + vmathSoaV4MakeFromElems( result, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); +} + +static inline void vmathSoaV4Lerp( VmathSoaVector4 *result, vec_float4 t, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + VmathSoaVector4 tmpV4_0, tmpV4_1; + vmathSoaV4Sub( &tmpV4_0, vec1, vec0 ); + vmathSoaV4ScalarMul( &tmpV4_1, &tmpV4_0, t ); + vmathSoaV4Add( result, vec0, &tmpV4_1 ); +} + +static inline void vmathSoaV4Slerp( VmathSoaVector4 *result, vec_float4 t, const VmathSoaVector4 *unitVec0, const VmathSoaVector4 *unitVec1 ) +{ + VmathSoaVector4 tmpV4_0, tmpV4_1; + vec_float4 recipSinAngle, scale0, scale1, cosAngle, angle; + vec_uint4 selectMask; + cosAngle = vmathSoaV4Dot( unitVec0, unitVec1 ); + selectMask = (vec_uint4)vec_cmpgt( (vec_float4){_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL}, cosAngle ); + angle = acosf4( cosAngle ); + recipSinAngle = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sinf4( angle ) ); + scale0 = vec_sel( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), t ), vec_madd( sinf4( vec_madd( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), t ), angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), recipSinAngle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), selectMask ); + scale1 = vec_sel( t, vec_madd( sinf4( vec_madd( t, angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), recipSinAngle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), selectMask ); + vmathSoaV4ScalarMul( &tmpV4_0, unitVec0, scale0 ); + vmathSoaV4ScalarMul( &tmpV4_1, unitVec1, scale1 ); + vmathSoaV4Add( result, &tmpV4_0, &tmpV4_1 ); +} + +static inline void vmathSoaV4Get4Aos( const VmathSoaVector4 *vec, VmathVector4 *result0, VmathVector4 *result1, VmathVector4 *result2, VmathVector4 *result3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = vec_mergeh( vec->x, vec->z ); + tmp1 = vec_mergeh( vec->y, vec->w ); + tmp2 = vec_mergel( vec->x, vec->z ); + tmp3 = vec_mergel( vec->y, vec->w ); + vmathV4MakeFrom128( result0, vec_mergeh( tmp0, tmp1 ) ); + vmathV4MakeFrom128( result1, vec_mergel( tmp0, tmp1 ) ); + vmathV4MakeFrom128( result2, vec_mergeh( tmp2, tmp3 ) ); + vmathV4MakeFrom128( result3, vec_mergel( tmp2, tmp3 ) ); +} + +static inline void vmathSoaV4StoreHalfFloats( const VmathSoaVector4 *vec, vec_ushort8 *twoQuads ) +{ + VmathVector4 v0, v1, v2, v3; + vmathSoaV4Get4Aos( vec, &v0, &v1, &v2, &v3 ); + twoQuads[0] = _vmath2VfToHalfFloats(v0.vec128, v1.vec128); + twoQuads[1] = _vmath2VfToHalfFloats(v2.vec128, v3.vec128); +} + +static inline void vmathSoaV4SetXYZ( VmathSoaVector4 *result, const VmathSoaVector3 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; +} + +static inline void vmathSoaV4GetXYZ( VmathSoaVector3 *result, const VmathSoaVector4 *vec ) +{ + vmathSoaV3MakeFromElems( result, vec->x, vec->y, vec->z ); +} + +static inline void vmathSoaV4SetX( VmathSoaVector4 *result, vec_float4 _x ) +{ + result->x = _x; +} + +static inline vec_float4 vmathSoaV4GetX( const VmathSoaVector4 *vec ) +{ + return vec->x; +} + +static inline void vmathSoaV4SetY( VmathSoaVector4 *result, vec_float4 _y ) +{ + result->y = _y; +} + +static inline vec_float4 vmathSoaV4GetY( const VmathSoaVector4 *vec ) +{ + return vec->y; +} + +static inline void vmathSoaV4SetZ( VmathSoaVector4 *result, vec_float4 _z ) +{ + result->z = _z; +} + +static inline vec_float4 vmathSoaV4GetZ( const VmathSoaVector4 *vec ) +{ + return vec->z; +} + +static inline void vmathSoaV4SetW( VmathSoaVector4 *result, vec_float4 _w ) +{ + result->w = _w; +} + +static inline vec_float4 vmathSoaV4GetW( const VmathSoaVector4 *vec ) +{ + return vec->w; +} + +static inline void vmathSoaV4SetElem( VmathSoaVector4 *result, int idx, vec_float4 value ) +{ + *(&result->x + idx) = value; +} + +static inline vec_float4 vmathSoaV4GetElem( const VmathSoaVector4 *vec, int idx ) +{ + return *(&vec->x + idx); +} + +static inline void vmathSoaV4Add( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + result->x = vec_add( vec0->x, vec1->x ); + result->y = vec_add( vec0->y, vec1->y ); + result->z = vec_add( vec0->z, vec1->z ); + result->w = vec_add( vec0->w, vec1->w ); +} + +static inline void vmathSoaV4Sub( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + result->x = vec_sub( vec0->x, vec1->x ); + result->y = vec_sub( vec0->y, vec1->y ); + result->z = vec_sub( vec0->z, vec1->z ); + result->w = vec_sub( vec0->w, vec1->w ); +} + +static inline void vmathSoaV4ScalarMul( VmathSoaVector4 *result, const VmathSoaVector4 *vec, vec_float4 scalar ) +{ + result->x = vec_madd( vec->x, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->y = vec_madd( vec->y, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->z = vec_madd( vec->z, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->w = vec_madd( vec->w, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaV4ScalarDiv( VmathSoaVector4 *result, const VmathSoaVector4 *vec, vec_float4 scalar ) +{ + result->x = divf4( vec->x, scalar ); + result->y = divf4( vec->y, scalar ); + result->z = divf4( vec->z, scalar ); + result->w = divf4( vec->w, scalar ); +} + +static inline void vmathSoaV4Neg( VmathSoaVector4 *result, const VmathSoaVector4 *vec ) +{ + result->x = negatef4( vec->x ); + result->y = negatef4( vec->y ); + result->z = negatef4( vec->z ); + result->w = negatef4( vec->w ); +} + +static inline void vmathSoaV4MulPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + result->x = vec_madd( vec0->x, vec1->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->y = vec_madd( vec0->y, vec1->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->z = vec_madd( vec0->z, vec1->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->w = vec_madd( vec0->w, vec1->w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaV4DivPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + result->x = divf4( vec0->x, vec1->x ); + result->y = divf4( vec0->y, vec1->y ); + result->z = divf4( vec0->z, vec1->z ); + result->w = divf4( vec0->w, vec1->w ); +} + +static inline void vmathSoaV4RecipPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec ) +{ + result->x = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec->x ); + result->y = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec->y ); + result->z = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec->z ); + result->w = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec->w ); +} + +static inline void vmathSoaV4SqrtPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec ) +{ + result->x = sqrtf4( vec->x ); + result->y = sqrtf4( vec->y ); + result->z = sqrtf4( vec->z ); + result->w = sqrtf4( vec->w ); +} + +static inline void vmathSoaV4RsqrtPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec ) +{ + result->x = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( vec->x ) ); + result->y = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( vec->y ) ); + result->z = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( vec->z ) ); + result->w = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( vec->w ) ); +} + +static inline void vmathSoaV4AbsPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec ) +{ + result->x = fabsf4( vec->x ); + result->y = fabsf4( vec->y ); + result->z = fabsf4( vec->z ); + result->w = fabsf4( vec->w ); +} + +static inline void vmathSoaV4CopySignPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + result->x = copysignf4( vec0->x, vec1->x ); + result->y = copysignf4( vec0->y, vec1->y ); + result->z = copysignf4( vec0->z, vec1->z ); + result->w = copysignf4( vec0->w, vec1->w ); +} + +static inline void vmathSoaV4MaxPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + result->x = fmaxf4( vec0->x, vec1->x ); + result->y = fmaxf4( vec0->y, vec1->y ); + result->z = fmaxf4( vec0->z, vec1->z ); + result->w = fmaxf4( vec0->w, vec1->w ); +} + +static inline vec_float4 vmathSoaV4MaxElem( const VmathSoaVector4 *vec ) +{ + vec_float4 result; + result = fmaxf4( vec->x, vec->y ); + result = fmaxf4( vec->z, result ); + result = fmaxf4( vec->w, result ); + return result; +} + +static inline void vmathSoaV4MinPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + result->x = fminf4( vec0->x, vec1->x ); + result->y = fminf4( vec0->y, vec1->y ); + result->z = fminf4( vec0->z, vec1->z ); + result->w = fminf4( vec0->w, vec1->w ); +} + +static inline vec_float4 vmathSoaV4MinElem( const VmathSoaVector4 *vec ) +{ + vec_float4 result; + result = fminf4( vec->x, vec->y ); + result = fminf4( vec->z, result ); + result = fminf4( vec->w, result ); + return result; +} + +static inline vec_float4 vmathSoaV4Sum( const VmathSoaVector4 *vec ) +{ + vec_float4 result; + result = vec_add( vec->x, vec->y ); + result = vec_add( result, vec->z ); + result = vec_add( result, vec->w ); + return result; +} + +static inline vec_float4 vmathSoaV4Dot( const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + vec_float4 result; + result = vec_madd( vec0->x, vec1->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result = vec_add( result, vec_madd( vec0->y, vec1->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( vec0->z, vec1->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( vec0->w, vec1->w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return result; +} + +static inline vec_float4 vmathSoaV4LengthSqr( const VmathSoaVector4 *vec ) +{ + vec_float4 result; + result = vec_madd( vec->x, vec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result = vec_add( result, vec_madd( vec->y, vec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( vec->z, vec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( vec->w, vec->w, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return result; +} + +static inline vec_float4 vmathSoaV4Length( const VmathSoaVector4 *vec ) +{ + return sqrtf4( vmathSoaV4LengthSqr( vec ) ); +} + +static inline void vmathSoaV4Normalize( VmathSoaVector4 *result, const VmathSoaVector4 *vec ) +{ + vec_float4 lenSqr, lenInv; + lenSqr = vmathSoaV4LengthSqr( vec ); + lenInv = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( lenSqr ) ); + result->x = vec_madd( vec->x, lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->y = vec_madd( vec->y, lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->z = vec_madd( vec->z, lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->w = vec_madd( vec->w, lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaV4Select( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1, vec_uint4 select1 ) +{ + result->x = vec_sel( vec0->x, vec1->x, select1 ); + result->y = vec_sel( vec0->y, vec1->y, select1 ); + result->z = vec_sel( vec0->z, vec1->z, select1 ); + result->w = vec_sel( vec0->w, vec1->w, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaV4Print( const VmathSoaVector4 *vec ) +{ + VmathVector4 vec0, vec1, vec2, vec3; + vmathSoaV4Get4Aos( vec, &vec0, &vec1, &vec2, &vec3 ); + printf("slot 0:\n"); + vmathV4Print( &vec0 ); + printf("slot 1:\n"); + vmathV4Print( &vec1 ); + printf("slot 2:\n"); + vmathV4Print( &vec2 ); + printf("slot 3:\n"); + vmathV4Print( &vec3 ); +} + +static inline void vmathSoaV4Prints( const VmathSoaVector4 *vec, const char *name ) +{ + VmathVector4 vec0, vec1, vec2, vec3; + printf( "%s:\n", name ); + vmathSoaV4Get4Aos( vec, &vec0, &vec1, &vec2, &vec3 ); + printf("slot 0:\n"); + vmathV4Print( &vec0 ); + printf("slot 1:\n"); + vmathV4Print( &vec1 ); + printf("slot 2:\n"); + vmathV4Print( &vec2 ); + printf("slot 3:\n"); + vmathV4Print( &vec3 ); +} + +#endif + +static inline void vmathSoaP3Copy( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ) +{ + result->x = pnt->x; + result->y = pnt->y; + result->z = pnt->z; +} + +static inline void vmathSoaP3MakeFromElems( VmathSoaPoint3 *result, vec_float4 _x, vec_float4 _y, vec_float4 _z ) +{ + result->x = _x; + result->y = _y; + result->z = _z; +} + +static inline void vmathSoaP3MakeFromV3( VmathSoaPoint3 *result, const VmathSoaVector3 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; +} + +static inline void vmathSoaP3MakeFromScalar( VmathSoaPoint3 *result, vec_float4 scalar ) +{ + result->x = scalar; + result->y = scalar; + result->z = scalar; +} + +static inline void vmathSoaP3MakeFromAos( VmathSoaPoint3 *result, const VmathPoint3 *pnt ) +{ + vec_float4 vec128 = pnt->vec128; + result->x = vec_splat( vec128, 0 ); + result->y = vec_splat( vec128, 1 ); + result->z = vec_splat( vec128, 2 ); +} + +static inline void vmathSoaP3MakeFrom4Aos( VmathSoaPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, const VmathPoint3 *pnt2, const VmathPoint3 *pnt3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = vec_mergeh( pnt0->vec128, pnt2->vec128 ); + tmp1 = vec_mergeh( pnt1->vec128, pnt3->vec128 ); + tmp2 = vec_mergel( pnt0->vec128, pnt2->vec128 ); + tmp3 = vec_mergel( pnt1->vec128, pnt3->vec128 ); + result->x = vec_mergeh( tmp0, tmp1 ); + result->y = vec_mergel( tmp0, tmp1 ); + result->z = vec_mergeh( tmp2, tmp3 ); +} + +static inline void vmathSoaP3Lerp( VmathSoaPoint3 *result, vec_float4 t, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + VmathSoaVector3 tmpV3_0, tmpV3_1; + vmathSoaP3Sub( &tmpV3_0, pnt1, pnt0 ); + vmathSoaV3ScalarMul( &tmpV3_1, &tmpV3_0, t ); + vmathSoaP3AddV3( result, pnt0, &tmpV3_1 ); +} + +static inline void vmathSoaP3Get4Aos( const VmathSoaPoint3 *pnt, VmathPoint3 *result0, VmathPoint3 *result1, VmathPoint3 *result2, VmathPoint3 *result3 ) +{ + vec_float4 tmp0, tmp1; + tmp0 = vec_mergeh( pnt->x, pnt->z ); + tmp1 = vec_mergel( pnt->x, pnt->z ); + vmathP3MakeFrom128( result0, vec_mergeh( tmp0, pnt->y ) ); + vmathP3MakeFrom128( result1, vec_perm( tmp0, pnt->y, _VECTORMATH_PERM_ZBWX ) ); + vmathP3MakeFrom128( result2, vec_perm( tmp1, pnt->y, _VECTORMATH_PERM_XCYX ) ); + vmathP3MakeFrom128( result3, vec_perm( tmp1, pnt->y, _VECTORMATH_PERM_ZDWX ) ); +} + +static inline void vmathSoaP3LoadXYZArray( VmathSoaPoint3 *vec, const vec_float4 *threeQuads ) +{ + vec_float4 xyxy, yzyz, zxzx, xyzx, yzxy, zxyz; + xyzx = threeQuads[0]; + yzxy = threeQuads[1]; + zxyz = threeQuads[2]; + xyxy = vec_sld( yzxy, xyzx, 8 ); + zxzx = vec_sld( xyzx, zxyz, 8 ); + yzyz = vec_sld( zxyz, yzxy, 8 ); + vmathSoaP3SetX( vec, vec_perm( xyxy, zxzx, _VECTORMATH_PERM_ZBXD ) ); + vmathSoaP3SetY( vec, vec_perm( xyxy, yzyz, _VECTORMATH_PERM_WCYA ) ); + vmathSoaP3SetZ( vec, vec_perm( zxzx, yzyz, _VECTORMATH_PERM_XDZB ) ); +} + +static inline void vmathSoaP3StoreXYZArray( const VmathSoaPoint3 *vec, vec_float4 *threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz, xyxy, zxzx, yzyz; + xyxy = vec_perm( vec->x, vec->y, _VECTORMATH_PERM_ZCXA ); + zxzx = vec_perm( vec->z, vec->x, _VECTORMATH_PERM_XBZD ); + yzyz = vec_perm( vec->y, vec->z, _VECTORMATH_PERM_WDYB ); + xyzx = vec_sld( xyxy, zxzx, 8 ); + yzxy = vec_sld( yzyz, xyxy, 8 ); + zxyz = vec_sld( zxzx, yzyz, 8 ); + threeQuads[0] = xyzx; + threeQuads[1] = yzxy; + threeQuads[2] = zxyz; +} + +static inline void vmathSoaP3StoreHalfFloats( const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1, vec_ushort8 *threeQuads ) +{ + vec_float4 xyz0[3]; + vec_float4 xyz1[3]; + vmathSoaP3StoreXYZArray( pnt0, xyz0 ); + vmathSoaP3StoreXYZArray( pnt1, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +} + +static inline void vmathSoaP3SetX( VmathSoaPoint3 *result, vec_float4 _x ) +{ + result->x = _x; +} + +static inline vec_float4 vmathSoaP3GetX( const VmathSoaPoint3 *pnt ) +{ + return pnt->x; +} + +static inline void vmathSoaP3SetY( VmathSoaPoint3 *result, vec_float4 _y ) +{ + result->y = _y; +} + +static inline vec_float4 vmathSoaP3GetY( const VmathSoaPoint3 *pnt ) +{ + return pnt->y; +} + +static inline void vmathSoaP3SetZ( VmathSoaPoint3 *result, vec_float4 _z ) +{ + result->z = _z; +} + +static inline vec_float4 vmathSoaP3GetZ( const VmathSoaPoint3 *pnt ) +{ + return pnt->z; +} + +static inline void vmathSoaP3SetElem( VmathSoaPoint3 *result, int idx, vec_float4 value ) +{ + *(&result->x + idx) = value; +} + +static inline vec_float4 vmathSoaP3GetElem( const VmathSoaPoint3 *pnt, int idx ) +{ + return *(&pnt->x + idx); +} + +static inline void vmathSoaP3Sub( VmathSoaVector3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + result->x = vec_sub( pnt0->x, pnt1->x ); + result->y = vec_sub( pnt0->y, pnt1->y ); + result->z = vec_sub( pnt0->z, pnt1->z ); +} + +static inline void vmathSoaP3AddV3( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, const VmathSoaVector3 *vec1 ) +{ + result->x = vec_add( pnt->x, vec1->x ); + result->y = vec_add( pnt->y, vec1->y ); + result->z = vec_add( pnt->z, vec1->z ); +} + +static inline void vmathSoaP3SubV3( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, const VmathSoaVector3 *vec1 ) +{ + result->x = vec_sub( pnt->x, vec1->x ); + result->y = vec_sub( pnt->y, vec1->y ); + result->z = vec_sub( pnt->z, vec1->z ); +} + +static inline void vmathSoaP3MulPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + result->x = vec_madd( pnt0->x, pnt1->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->y = vec_madd( pnt0->y, pnt1->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result->z = vec_madd( pnt0->z, pnt1->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +static inline void vmathSoaP3DivPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + result->x = divf4( pnt0->x, pnt1->x ); + result->y = divf4( pnt0->y, pnt1->y ); + result->z = divf4( pnt0->z, pnt1->z ); +} + +static inline void vmathSoaP3RecipPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ) +{ + result->x = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), pnt->x ); + result->y = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), pnt->y ); + result->z = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), pnt->z ); +} + +static inline void vmathSoaP3SqrtPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ) +{ + result->x = sqrtf4( pnt->x ); + result->y = sqrtf4( pnt->y ); + result->z = sqrtf4( pnt->z ); +} + +static inline void vmathSoaP3RsqrtPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ) +{ + result->x = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( pnt->x ) ); + result->y = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( pnt->y ) ); + result->z = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( pnt->z ) ); +} + +static inline void vmathSoaP3AbsPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ) +{ + result->x = fabsf4( pnt->x ); + result->y = fabsf4( pnt->y ); + result->z = fabsf4( pnt->z ); +} + +static inline void vmathSoaP3CopySignPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + result->x = copysignf4( pnt0->x, pnt1->x ); + result->y = copysignf4( pnt0->y, pnt1->y ); + result->z = copysignf4( pnt0->z, pnt1->z ); +} + +static inline void vmathSoaP3MaxPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + result->x = fmaxf4( pnt0->x, pnt1->x ); + result->y = fmaxf4( pnt0->y, pnt1->y ); + result->z = fmaxf4( pnt0->z, pnt1->z ); +} + +static inline vec_float4 vmathSoaP3MaxElem( const VmathSoaPoint3 *pnt ) +{ + vec_float4 result; + result = fmaxf4( pnt->x, pnt->y ); + result = fmaxf4( pnt->z, result ); + return result; +} + +static inline void vmathSoaP3MinPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + result->x = fminf4( pnt0->x, pnt1->x ); + result->y = fminf4( pnt0->y, pnt1->y ); + result->z = fminf4( pnt0->z, pnt1->z ); +} + +static inline vec_float4 vmathSoaP3MinElem( const VmathSoaPoint3 *pnt ) +{ + vec_float4 result; + result = fminf4( pnt->x, pnt->y ); + result = fminf4( pnt->z, result ); + return result; +} + +static inline vec_float4 vmathSoaP3Sum( const VmathSoaPoint3 *pnt ) +{ + vec_float4 result; + result = vec_add( pnt->x, pnt->y ); + result = vec_add( result, pnt->z ); + return result; +} + +static inline void vmathSoaP3Scale( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, vec_float4 scaleVal ) +{ + VmathSoaPoint3 tmpP3_0; + vmathSoaP3MakeFromScalar( &tmpP3_0, scaleVal ); + vmathSoaP3MulPerElem( result, pnt, &tmpP3_0 ); +} + +static inline void vmathSoaP3NonUniformScale( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, const VmathSoaVector3 *scaleVec ) +{ + VmathSoaPoint3 tmpP3_0; + vmathSoaP3MakeFromV3( &tmpP3_0, scaleVec ); + vmathSoaP3MulPerElem( result, pnt, &tmpP3_0 ); +} + +static inline vec_float4 vmathSoaP3Projection( const VmathSoaPoint3 *pnt, const VmathSoaVector3 *unitVec ) +{ + vec_float4 result; + result = vec_madd( pnt->x, unitVec->x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result = vec_add( result, vec_madd( pnt->y, unitVec->y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( pnt->z, unitVec->z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return result; +} + +static inline vec_float4 vmathSoaP3DistSqrFromOrigin( const VmathSoaPoint3 *pnt ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaV3MakeFromP3( &tmpV3_0, pnt ); + return vmathSoaV3LengthSqr( &tmpV3_0 ); +} + +static inline vec_float4 vmathSoaP3DistFromOrigin( const VmathSoaPoint3 *pnt ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaV3MakeFromP3( &tmpV3_0, pnt ); + return vmathSoaV3Length( &tmpV3_0 ); +} + +static inline vec_float4 vmathSoaP3DistSqr( const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaP3Sub( &tmpV3_0, pnt1, pnt0 ); + return vmathSoaV3LengthSqr( &tmpV3_0 ); +} + +static inline vec_float4 vmathSoaP3Dist( const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaP3Sub( &tmpV3_0, pnt1, pnt0 ); + return vmathSoaV3Length( &tmpV3_0 ); +} + +static inline void vmathSoaP3Select( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1, vec_uint4 select1 ) +{ + result->x = vec_sel( pnt0->x, pnt1->x, select1 ); + result->y = vec_sel( pnt0->y, pnt1->y, select1 ); + result->z = vec_sel( pnt0->z, pnt1->z, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaP3Print( const VmathSoaPoint3 *pnt ) +{ + VmathPoint3 vec0, vec1, vec2, vec3; + vmathSoaP3Get4Aos( pnt, &vec0, &vec1, &vec2, &vec3 ); + printf("slot 0:\n"); + vmathP3Print( &vec0 ); + printf("slot 1:\n"); + vmathP3Print( &vec1 ); + printf("slot 2:\n"); + vmathP3Print( &vec2 ); + printf("slot 3:\n"); + vmathP3Print( &vec3 ); +} + +static inline void vmathSoaP3Prints( const VmathSoaPoint3 *pnt, const char *name ) +{ + VmathPoint3 vec0, vec1, vec2, vec3; + printf( "%s:\n", name ); + vmathSoaP3Get4Aos( pnt, &vec0, &vec1, &vec2, &vec3 ); + printf("slot 0:\n"); + vmathP3Print( &vec0 ); + printf("slot 1:\n"); + vmathP3Print( &vec1 ); + printf("slot 2:\n"); + vmathP3Print( &vec2 ); + printf("slot 3:\n"); + vmathP3Print( &vec3 ); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/vec_soa_v.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/vec_soa_v.h new file mode 100644 index 0000000..75d7bb6 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/vec_soa_v.h @@ -0,0 +1,958 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_SOA_V_C_H +#define _VECTORMATH_VEC_SOA_V_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + * for permutes, words are labeled [x,y,z,w] [a,b,c,d] + */ +#define _VECTORMATH_PERM_X 0x00010203 +#define _VECTORMATH_PERM_Y 0x04050607 +#define _VECTORMATH_PERM_Z 0x08090a0b +#define _VECTORMATH_PERM_W 0x0c0d0e0f +#define _VECTORMATH_PERM_A 0x10111213 +#define _VECTORMATH_PERM_B 0x14151617 +#define _VECTORMATH_PERM_C 0x18191a1b +#define _VECTORMATH_PERM_D 0x1c1d1e1f +#define _VECTORMATH_PERM_ZBWX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XCYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_C, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_ZDWX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_D, _VECTORMATH_PERM_W, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_ZCXA ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_A }) +#define _VECTORMATH_PERM_XBZD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_B, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_WDYB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_W, _VECTORMATH_PERM_D, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_ZBXD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_X, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_WCYA ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_W, _VECTORMATH_PERM_C, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A }) +#define _VECTORMATH_PERM_XDZB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_D, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B }) +#define _VECTORMATH_SLERP_TOL 0.999f + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline VmathSoaVector3 vmathSoaV3MakeFromElems_V( vec_float4 _x, vec_float4 _y, vec_float4 _z ) +{ + VmathSoaVector3 result; + vmathSoaV3MakeFromElems(&result, _x, _y, _z); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MakeFromP3_V( VmathSoaPoint3 pnt ) +{ + VmathSoaVector3 result; + vmathSoaV3MakeFromP3(&result, &pnt); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MakeFromScalar_V( vec_float4 scalar ) +{ + VmathSoaVector3 result; + vmathSoaV3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MakeFromAos_V( VmathVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaV3MakeFromAos(&result, &vec); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MakeFrom4Aos_V( VmathVector3 vec0, VmathVector3 vec1, VmathVector3 vec2, VmathVector3 vec3 ) +{ + VmathSoaVector3 result; + vmathSoaV3MakeFrom4Aos(&result, &vec0, &vec1, &vec2, &vec3); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MakeXAxis_V( ) +{ + VmathSoaVector3 result; + vmathSoaV3MakeXAxis(&result); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MakeYAxis_V( ) +{ + VmathSoaVector3 result; + vmathSoaV3MakeYAxis(&result); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MakeZAxis_V( ) +{ + VmathSoaVector3 result; + vmathSoaV3MakeZAxis(&result); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3Lerp_V( vec_float4 t, VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3Lerp(&result, t, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3Slerp_V( vec_float4 t, VmathSoaVector3 unitVec0, VmathSoaVector3 unitVec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3Slerp(&result, t, &unitVec0, &unitVec1); + return result; +} + +static inline void vmathSoaV3Get4Aos_V( VmathSoaVector3 vec, VmathVector3 *result0, VmathVector3 *result1, VmathVector3 *result2, VmathVector3 *result3 ) +{ + vmathSoaV3Get4Aos(&vec, result0, result1, result2, result3); +} + +static inline void vmathSoaV3LoadXYZArray_V( VmathSoaVector3 *vec, const vec_float4 *threeQuads ) +{ + vmathSoaV3LoadXYZArray(vec, threeQuads); +} + +static inline void vmathSoaV3StoreXYZArray_V( VmathSoaVector3 vec, vec_float4 *threeQuads ) +{ + vmathSoaV3StoreXYZArray(&vec, threeQuads); +} + +static inline void vmathSoaV3StoreHalfFloats_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1, vec_ushort8 *threeQuads ) +{ + vmathSoaV3StoreHalfFloats(&vec0, &vec1, threeQuads); +} + +static inline void vmathSoaV3SetX_V( VmathSoaVector3 *result, vec_float4 _x ) +{ + vmathSoaV3SetX(result, _x); +} + +static inline vec_float4 vmathSoaV3GetX_V( VmathSoaVector3 vec ) +{ + return vmathSoaV3GetX(&vec); +} + +static inline void vmathSoaV3SetY_V( VmathSoaVector3 *result, vec_float4 _y ) +{ + vmathSoaV3SetY(result, _y); +} + +static inline vec_float4 vmathSoaV3GetY_V( VmathSoaVector3 vec ) +{ + return vmathSoaV3GetY(&vec); +} + +static inline void vmathSoaV3SetZ_V( VmathSoaVector3 *result, vec_float4 _z ) +{ + vmathSoaV3SetZ(result, _z); +} + +static inline vec_float4 vmathSoaV3GetZ_V( VmathSoaVector3 vec ) +{ + return vmathSoaV3GetZ(&vec); +} + +static inline void vmathSoaV3SetElem_V( VmathSoaVector3 *result, int idx, vec_float4 value ) +{ + vmathSoaV3SetElem(result, idx, value); +} + +static inline vec_float4 vmathSoaV3GetElem_V( VmathSoaVector3 vec, int idx ) +{ + return vmathSoaV3GetElem(&vec, idx); +} + +static inline VmathSoaVector3 vmathSoaV3Add_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3Add(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3Sub_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3Sub(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaPoint3 vmathSoaV3AddP3_V( VmathSoaVector3 vec, VmathSoaPoint3 pnt1 ) +{ + VmathSoaPoint3 result; + vmathSoaV3AddP3(&result, &vec, &pnt1); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3ScalarMul_V( VmathSoaVector3 vec, vec_float4 scalar ) +{ + VmathSoaVector3 result; + vmathSoaV3ScalarMul(&result, &vec, scalar); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3ScalarDiv_V( VmathSoaVector3 vec, vec_float4 scalar ) +{ + VmathSoaVector3 result; + vmathSoaV3ScalarDiv(&result, &vec, scalar); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3Neg_V( VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaV3Neg(&result, &vec); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MulPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3MulPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3DivPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3DivPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3RecipPerElem_V( VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaV3RecipPerElem(&result, &vec); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3SqrtPerElem_V( VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaV3SqrtPerElem(&result, &vec); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3RsqrtPerElem_V( VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaV3RsqrtPerElem(&result, &vec); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3AbsPerElem_V( VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaV3AbsPerElem(&result, &vec); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3CopySignPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3CopySignPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MaxPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3MaxPerElem(&result, &vec0, &vec1); + return result; +} + +static inline vec_float4 vmathSoaV3MaxElem_V( VmathSoaVector3 vec ) +{ + return vmathSoaV3MaxElem(&vec); +} + +static inline VmathSoaVector3 vmathSoaV3MinPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3MinPerElem(&result, &vec0, &vec1); + return result; +} + +static inline vec_float4 vmathSoaV3MinElem_V( VmathSoaVector3 vec ) +{ + return vmathSoaV3MinElem(&vec); +} + +static inline vec_float4 vmathSoaV3Sum_V( VmathSoaVector3 vec ) +{ + return vmathSoaV3Sum(&vec); +} + +static inline vec_float4 vmathSoaV3Dot_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + return vmathSoaV3Dot(&vec0, &vec1); +} + +static inline vec_float4 vmathSoaV3LengthSqr_V( VmathSoaVector3 vec ) +{ + return vmathSoaV3LengthSqr(&vec); +} + +static inline vec_float4 vmathSoaV3Length_V( VmathSoaVector3 vec ) +{ + return vmathSoaV3Length(&vec); +} + +static inline VmathSoaVector3 vmathSoaV3Normalize_V( VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaV3Normalize(&result, &vec); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3Cross_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3Cross(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3Select_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1, vec_uint4 select1 ) +{ + VmathSoaVector3 result; + vmathSoaV3Select(&result, &vec0, &vec1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaV3Print_V( VmathSoaVector3 vec ) +{ + vmathSoaV3Print(&vec); +} + +static inline void vmathSoaV3Prints_V( VmathSoaVector3 vec, const char *name ) +{ + vmathSoaV3Prints(&vec, name); +} + +#endif + +static inline VmathSoaVector4 vmathSoaV4MakeFromElems_V( vec_float4 _x, vec_float4 _y, vec_float4 _z, vec_float4 _w ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeFromElems(&result, _x, _y, _z, _w); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeFromV3Scalar_V( VmathSoaVector3 xyz, vec_float4 _w ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeFromV3Scalar(&result, &xyz, _w); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeFromV3_V( VmathSoaVector3 vec ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeFromV3(&result, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeFromP3_V( VmathSoaPoint3 pnt ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeFromP3(&result, &pnt); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeFromQ_V( VmathSoaQuat quat ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeFromQ(&result, &quat); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeFromScalar_V( vec_float4 scalar ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeFromAos_V( VmathVector4 vec ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeFromAos(&result, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeFrom4Aos_V( VmathVector4 vec0, VmathVector4 vec1, VmathVector4 vec2, VmathVector4 vec3 ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeFrom4Aos(&result, &vec0, &vec1, &vec2, &vec3); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeXAxis_V( ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeXAxis(&result); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeYAxis_V( ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeYAxis(&result); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeZAxis_V( ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeZAxis(&result); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeWAxis_V( ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeWAxis(&result); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4Lerp_V( vec_float4 t, VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4Lerp(&result, t, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4Slerp_V( vec_float4 t, VmathSoaVector4 unitVec0, VmathSoaVector4 unitVec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4Slerp(&result, t, &unitVec0, &unitVec1); + return result; +} + +static inline void vmathSoaV4Get4Aos_V( VmathSoaVector4 vec, VmathVector4 *result0, VmathVector4 *result1, VmathVector4 *result2, VmathVector4 *result3 ) +{ + vmathSoaV4Get4Aos(&vec, result0, result1, result2, result3); +} + +static inline void vmathSoaV4StoreHalfFloats_V( VmathSoaVector4 vec, vec_ushort8 *twoQuads ) +{ + vmathSoaV4StoreHalfFloats(&vec, twoQuads); +} + +static inline void vmathSoaV4SetXYZ_V( VmathSoaVector4 *result, VmathSoaVector3 vec ) +{ + vmathSoaV4SetXYZ(result, &vec); +} + +static inline VmathSoaVector3 vmathSoaV4GetXYZ_V( VmathSoaVector4 vec ) +{ + VmathSoaVector3 result; + vmathSoaV4GetXYZ(&result, &vec); + return result; +} + +static inline void vmathSoaV4SetX_V( VmathSoaVector4 *result, vec_float4 _x ) +{ + vmathSoaV4SetX(result, _x); +} + +static inline vec_float4 vmathSoaV4GetX_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4GetX(&vec); +} + +static inline void vmathSoaV4SetY_V( VmathSoaVector4 *result, vec_float4 _y ) +{ + vmathSoaV4SetY(result, _y); +} + +static inline vec_float4 vmathSoaV4GetY_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4GetY(&vec); +} + +static inline void vmathSoaV4SetZ_V( VmathSoaVector4 *result, vec_float4 _z ) +{ + vmathSoaV4SetZ(result, _z); +} + +static inline vec_float4 vmathSoaV4GetZ_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4GetZ(&vec); +} + +static inline void vmathSoaV4SetW_V( VmathSoaVector4 *result, vec_float4 _w ) +{ + vmathSoaV4SetW(result, _w); +} + +static inline vec_float4 vmathSoaV4GetW_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4GetW(&vec); +} + +static inline void vmathSoaV4SetElem_V( VmathSoaVector4 *result, int idx, vec_float4 value ) +{ + vmathSoaV4SetElem(result, idx, value); +} + +static inline vec_float4 vmathSoaV4GetElem_V( VmathSoaVector4 vec, int idx ) +{ + return vmathSoaV4GetElem(&vec, idx); +} + +static inline VmathSoaVector4 vmathSoaV4Add_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4Add(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4Sub_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4Sub(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4ScalarMul_V( VmathSoaVector4 vec, vec_float4 scalar ) +{ + VmathSoaVector4 result; + vmathSoaV4ScalarMul(&result, &vec, scalar); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4ScalarDiv_V( VmathSoaVector4 vec, vec_float4 scalar ) +{ + VmathSoaVector4 result; + vmathSoaV4ScalarDiv(&result, &vec, scalar); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4Neg_V( VmathSoaVector4 vec ) +{ + VmathSoaVector4 result; + vmathSoaV4Neg(&result, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MulPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4MulPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4DivPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4DivPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4RecipPerElem_V( VmathSoaVector4 vec ) +{ + VmathSoaVector4 result; + vmathSoaV4RecipPerElem(&result, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4SqrtPerElem_V( VmathSoaVector4 vec ) +{ + VmathSoaVector4 result; + vmathSoaV4SqrtPerElem(&result, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4RsqrtPerElem_V( VmathSoaVector4 vec ) +{ + VmathSoaVector4 result; + vmathSoaV4RsqrtPerElem(&result, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4AbsPerElem_V( VmathSoaVector4 vec ) +{ + VmathSoaVector4 result; + vmathSoaV4AbsPerElem(&result, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4CopySignPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4CopySignPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MaxPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4MaxPerElem(&result, &vec0, &vec1); + return result; +} + +static inline vec_float4 vmathSoaV4MaxElem_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4MaxElem(&vec); +} + +static inline VmathSoaVector4 vmathSoaV4MinPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4MinPerElem(&result, &vec0, &vec1); + return result; +} + +static inline vec_float4 vmathSoaV4MinElem_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4MinElem(&vec); +} + +static inline vec_float4 vmathSoaV4Sum_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4Sum(&vec); +} + +static inline vec_float4 vmathSoaV4Dot_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + return vmathSoaV4Dot(&vec0, &vec1); +} + +static inline vec_float4 vmathSoaV4LengthSqr_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4LengthSqr(&vec); +} + +static inline vec_float4 vmathSoaV4Length_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4Length(&vec); +} + +static inline VmathSoaVector4 vmathSoaV4Normalize_V( VmathSoaVector4 vec ) +{ + VmathSoaVector4 result; + vmathSoaV4Normalize(&result, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4Select_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1, vec_uint4 select1 ) +{ + VmathSoaVector4 result; + vmathSoaV4Select(&result, &vec0, &vec1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaV4Print_V( VmathSoaVector4 vec ) +{ + vmathSoaV4Print(&vec); +} + +static inline void vmathSoaV4Prints_V( VmathSoaVector4 vec, const char *name ) +{ + vmathSoaV4Prints(&vec, name); +} + +#endif + +static inline VmathSoaPoint3 vmathSoaP3MakeFromElems_V( vec_float4 _x, vec_float4 _y, vec_float4 _z ) +{ + VmathSoaPoint3 result; + vmathSoaP3MakeFromElems(&result, _x, _y, _z); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3MakeFromV3_V( VmathSoaVector3 vec ) +{ + VmathSoaPoint3 result; + vmathSoaP3MakeFromV3(&result, &vec); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3MakeFromScalar_V( vec_float4 scalar ) +{ + VmathSoaPoint3 result; + vmathSoaP3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3MakeFromAos_V( VmathPoint3 pnt ) +{ + VmathSoaPoint3 result; + vmathSoaP3MakeFromAos(&result, &pnt); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3MakeFrom4Aos_V( VmathPoint3 pnt0, VmathPoint3 pnt1, VmathPoint3 pnt2, VmathPoint3 pnt3 ) +{ + VmathSoaPoint3 result; + vmathSoaP3MakeFrom4Aos(&result, &pnt0, &pnt1, &pnt2, &pnt3); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3Lerp_V( vec_float4 t, VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3Lerp(&result, t, &pnt0, &pnt1); + return result; +} + +static inline void vmathSoaP3Get4Aos_V( VmathSoaPoint3 pnt, VmathPoint3 *result0, VmathPoint3 *result1, VmathPoint3 *result2, VmathPoint3 *result3 ) +{ + vmathSoaP3Get4Aos(&pnt, result0, result1, result2, result3); +} + +static inline void vmathSoaP3LoadXYZArray_V( VmathSoaPoint3 *vec, const vec_float4 *threeQuads ) +{ + vmathSoaP3LoadXYZArray(vec, threeQuads); +} + +static inline void vmathSoaP3StoreXYZArray_V( VmathSoaPoint3 vec, vec_float4 *threeQuads ) +{ + vmathSoaP3StoreXYZArray(&vec, threeQuads); +} + +static inline void vmathSoaP3StoreHalfFloats_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1, vec_ushort8 *threeQuads ) +{ + vmathSoaP3StoreHalfFloats(&pnt0, &pnt1, threeQuads); +} + +static inline void vmathSoaP3SetX_V( VmathSoaPoint3 *result, vec_float4 _x ) +{ + vmathSoaP3SetX(result, _x); +} + +static inline vec_float4 vmathSoaP3GetX_V( VmathSoaPoint3 pnt ) +{ + return vmathSoaP3GetX(&pnt); +} + +static inline void vmathSoaP3SetY_V( VmathSoaPoint3 *result, vec_float4 _y ) +{ + vmathSoaP3SetY(result, _y); +} + +static inline vec_float4 vmathSoaP3GetY_V( VmathSoaPoint3 pnt ) +{ + return vmathSoaP3GetY(&pnt); +} + +static inline void vmathSoaP3SetZ_V( VmathSoaPoint3 *result, vec_float4 _z ) +{ + vmathSoaP3SetZ(result, _z); +} + +static inline vec_float4 vmathSoaP3GetZ_V( VmathSoaPoint3 pnt ) +{ + return vmathSoaP3GetZ(&pnt); +} + +static inline void vmathSoaP3SetElem_V( VmathSoaPoint3 *result, int idx, vec_float4 value ) +{ + vmathSoaP3SetElem(result, idx, value); +} + +static inline vec_float4 vmathSoaP3GetElem_V( VmathSoaPoint3 pnt, int idx ) +{ + return vmathSoaP3GetElem(&pnt, idx); +} + +static inline VmathSoaVector3 vmathSoaP3Sub_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + VmathSoaVector3 result; + vmathSoaP3Sub(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3AddV3_V( VmathSoaPoint3 pnt, VmathSoaVector3 vec1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3AddV3(&result, &pnt, &vec1); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3SubV3_V( VmathSoaPoint3 pnt, VmathSoaVector3 vec1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3SubV3(&result, &pnt, &vec1); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3MulPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3MulPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3DivPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3DivPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3RecipPerElem_V( VmathSoaPoint3 pnt ) +{ + VmathSoaPoint3 result; + vmathSoaP3RecipPerElem(&result, &pnt); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3SqrtPerElem_V( VmathSoaPoint3 pnt ) +{ + VmathSoaPoint3 result; + vmathSoaP3SqrtPerElem(&result, &pnt); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3RsqrtPerElem_V( VmathSoaPoint3 pnt ) +{ + VmathSoaPoint3 result; + vmathSoaP3RsqrtPerElem(&result, &pnt); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3AbsPerElem_V( VmathSoaPoint3 pnt ) +{ + VmathSoaPoint3 result; + vmathSoaP3AbsPerElem(&result, &pnt); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3CopySignPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3CopySignPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3MaxPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3MaxPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline vec_float4 vmathSoaP3MaxElem_V( VmathSoaPoint3 pnt ) +{ + return vmathSoaP3MaxElem(&pnt); +} + +static inline VmathSoaPoint3 vmathSoaP3MinPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3MinPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline vec_float4 vmathSoaP3MinElem_V( VmathSoaPoint3 pnt ) +{ + return vmathSoaP3MinElem(&pnt); +} + +static inline vec_float4 vmathSoaP3Sum_V( VmathSoaPoint3 pnt ) +{ + return vmathSoaP3Sum(&pnt); +} + +static inline VmathSoaPoint3 vmathSoaP3Scale_V( VmathSoaPoint3 pnt, vec_float4 scaleVal ) +{ + VmathSoaPoint3 result; + vmathSoaP3Scale(&result, &pnt, scaleVal); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3NonUniformScale_V( VmathSoaPoint3 pnt, VmathSoaVector3 scaleVec ) +{ + VmathSoaPoint3 result; + vmathSoaP3NonUniformScale(&result, &pnt, &scaleVec); + return result; +} + +static inline vec_float4 vmathSoaP3Projection_V( VmathSoaPoint3 pnt, VmathSoaVector3 unitVec ) +{ + return vmathSoaP3Projection(&pnt, &unitVec); +} + +static inline vec_float4 vmathSoaP3DistSqrFromOrigin_V( VmathSoaPoint3 pnt ) +{ + return vmathSoaP3DistSqrFromOrigin(&pnt); +} + +static inline vec_float4 vmathSoaP3DistFromOrigin_V( VmathSoaPoint3 pnt ) +{ + return vmathSoaP3DistFromOrigin(&pnt); +} + +static inline vec_float4 vmathSoaP3DistSqr_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + return vmathSoaP3DistSqr(&pnt0, &pnt1); +} + +static inline vec_float4 vmathSoaP3Dist_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + return vmathSoaP3Dist(&pnt0, &pnt1); +} + +static inline VmathSoaPoint3 vmathSoaP3Select_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1, vec_uint4 select1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3Select(&result, &pnt0, &pnt1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaP3Print_V( VmathSoaPoint3 pnt ) +{ + vmathSoaP3Print(&pnt); +} + +static inline void vmathSoaP3Prints_V( VmathSoaPoint3 pnt, const char *name ) +{ + vmathSoaP3Prints(&pnt, name); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/vec_types.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/vec_types.h new file mode 100644 index 0000000..022ce4d --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/vec_types.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +/* Single token vector data types for the PowerPC SIMD/Vector Multi-media + eXtension */ + +#ifndef _VEC_TYPES_H_ +#define _VEC_TYPES_H_ 1 + +#define qword vector unsigned char + +#define vec_uchar16 vector unsigned char +#define vec_char16 vector signed char +#define vec_bchar16 vector bool char + +#define vec_ushort8 vector unsigned short +#define vec_short8 vector signed short +#define vec_bshort8 vector bool short + +#define vec_pixel8 vector pixel + +#define vec_uint4 vector unsigned int +#define vec_int4 vector signed int +#define vec_bint4 vector bool int + +#define vec_float4 vector float + +#define vec_ullong2 vector bool char +#define vec_llong2 vector bool short + +#define vec_double2 vector bool int + +#endif /* _VEC_TYPES_H_ */ diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/vectormath_aos.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/vectormath_aos.h new file mode 100644 index 0000000..6a6ccd2 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/vectormath_aos.h @@ -0,0 +1,1960 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_AOS_C_PPU_H +#define _VECTORMATH_AOS_C_PPU_H + +#include +#include +#include +#include "vec_types.h" + +#ifdef _VECTORMATH_DEBUG +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef _VECTORMATH_AOS_C_TYPES_H +#define _VECTORMATH_AOS_C_TYPES_H + +/* A 3-D vector in array-of-structures format + */ +typedef struct _VmathVector3 +{ + vec_float4 vec128; +} VmathVector3; + +/* A 4-D vector in array-of-structures format + */ +typedef struct _VmathVector4 +{ + vec_float4 vec128; +} VmathVector4; + +/* A 3-D point in array-of-structures format + */ +typedef struct _VmathPoint3 +{ + vec_float4 vec128; +} VmathPoint3; + +/* A quaternion in array-of-structures format + */ +typedef struct _VmathQuat +{ + vec_float4 vec128; +} VmathQuat; + +/* A 3x3 matrix in array-of-structures format + */ +typedef struct _VmathMatrix3 +{ + VmathVector3 col0; + VmathVector3 col1; + VmathVector3 col2; +} VmathMatrix3; + +/* A 4x4 matrix in array-of-structures format + */ +typedef struct _VmathMatrix4 +{ + VmathVector4 col0; + VmathVector4 col1; + VmathVector4 col2; + VmathVector4 col3; +} VmathMatrix4; + +/* A 3x4 transformation matrix in array-of-structures format + */ +typedef struct _VmathTransform3 +{ + VmathVector3 col0; + VmathVector3 col1; + VmathVector3 col2; + VmathVector3 col3; +} VmathTransform3; + +#endif + +/* + * Copy a 3-D vector + */ +static inline void vmathV3Copy( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Construct a 3-D vector from x, y, and z elements + */ +static inline void vmathV3MakeFromElems( VmathVector3 *result, float x, float y, float z ); + +/* + * Copy elements from a 3-D point into a 3-D vector + */ +static inline void vmathV3MakeFromP3( VmathVector3 *result, const VmathPoint3 *pnt ); + +/* + * Set all elements of a 3-D vector to the same scalar value + */ +static inline void vmathV3MakeFromScalar( VmathVector3 *result, float scalar ); + +/* + * Set vector float data in a 3-D vector + */ +static inline void vmathV3MakeFrom128( VmathVector3 *result, vec_float4 vf4 ); + +/* + * Get vector float data from a 3-D vector + */ +static inline vec_float4 vmathV3Get128( const VmathVector3 *vec ); + +/* + * Set the x element of a 3-D vector + */ +static inline void vmathV3SetX( VmathVector3 *result, float x ); + +/* + * Set the y element of a 3-D vector + */ +static inline void vmathV3SetY( VmathVector3 *result, float y ); + +/* + * Set the z element of a 3-D vector + */ +static inline void vmathV3SetZ( VmathVector3 *result, float z ); + +/* + * Get the x element of a 3-D vector + */ +static inline float vmathV3GetX( const VmathVector3 *vec ); + +/* + * Get the y element of a 3-D vector + */ +static inline float vmathV3GetY( const VmathVector3 *vec ); + +/* + * Get the z element of a 3-D vector + */ +static inline float vmathV3GetZ( const VmathVector3 *vec ); + +/* + * Set an x, y, or z element of a 3-D vector by index + */ +static inline void vmathV3SetElem( VmathVector3 *result, int idx, float value ); + +/* + * Get an x, y, or z element of a 3-D vector by index + */ +static inline float vmathV3GetElem( const VmathVector3 *vec, int idx ); + +/* + * Add two 3-D vectors + */ +static inline void vmathV3Add( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Subtract a 3-D vector from another 3-D vector + */ +static inline void vmathV3Sub( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Add a 3-D vector to a 3-D point + */ +static inline void vmathV3AddP3( VmathPoint3 *result, const VmathVector3 *vec, const VmathPoint3 *pnt ); + +/* + * Multiply a 3-D vector by a scalar + */ +static inline void vmathV3ScalarMul( VmathVector3 *result, const VmathVector3 *vec, float scalar ); + +/* + * Divide a 3-D vector by a scalar + */ +static inline void vmathV3ScalarDiv( VmathVector3 *result, const VmathVector3 *vec, float scalar ); + +/* + * Negate all elements of a 3-D vector + */ +static inline void vmathV3Neg( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Construct x axis + */ +static inline void vmathV3MakeXAxis( VmathVector3 *result ); + +/* + * Construct y axis + */ +static inline void vmathV3MakeYAxis( VmathVector3 *result ); + +/* + * Construct z axis + */ +static inline void vmathV3MakeZAxis( VmathVector3 *result ); + +/* + * Multiply two 3-D vectors per element + */ +static inline void vmathV3MulPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Divide two 3-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline void vmathV3DivPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Compute the reciprocal of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline void vmathV3RecipPerElem( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Compute the square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline void vmathV3SqrtPerElem( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Compute the reciprocal square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline void vmathV3RsqrtPerElem( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Compute the absolute value of a 3-D vector per element + */ +static inline void vmathV3AbsPerElem( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Copy sign from one 3-D vector to another, per element + */ +static inline void vmathV3CopySignPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Maximum of two 3-D vectors per element + */ +static inline void vmathV3MaxPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Minimum of two 3-D vectors per element + */ +static inline void vmathV3MinPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Maximum element of a 3-D vector + */ +static inline float vmathV3MaxElem( const VmathVector3 *vec ); + +/* + * Minimum element of a 3-D vector + */ +static inline float vmathV3MinElem( const VmathVector3 *vec ); + +/* + * Compute the sum of all elements of a 3-D vector + */ +static inline float vmathV3Sum( const VmathVector3 *vec ); + +/* + * Compute the dot product of two 3-D vectors + */ +static inline float vmathV3Dot( const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Compute the square of the length of a 3-D vector + */ +static inline float vmathV3LengthSqr( const VmathVector3 *vec ); + +/* + * Compute the length of a 3-D vector + */ +static inline float vmathV3Length( const VmathVector3 *vec ); + +/* + * Normalize a 3-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline void vmathV3Normalize( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Compute cross product of two 3-D vectors + */ +static inline void vmathV3Cross( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Outer product of two 3-D vectors + */ +static inline void vmathV3Outer( VmathMatrix3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Pre-multiply a row vector by a 3x3 matrix + * NOTE: + * Slower than column post-multiply. + */ +static inline void vmathV3RowMul( VmathVector3 *result, const VmathVector3 *vec, const VmathMatrix3 *mat ); + +/* + * Cross-product matrix of a 3-D vector + */ +static inline void vmathV3CrossMatrix( VmathMatrix3 *result, const VmathVector3 *vec ); + +/* + * Create cross-product matrix and multiply + * NOTE: + * Faster than separately creating a cross-product matrix and multiplying. + */ +static inline void vmathV3CrossMatrixMul( VmathMatrix3 *result, const VmathVector3 *vec, const VmathMatrix3 *mat ); + +/* + * Linear interpolation between two 3-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathV3Lerp( VmathVector3 *result, float t, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Spherical linear interpolation between two 3-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline void vmathV3Slerp( VmathVector3 *result, float t, const VmathVector3 *unitVec0, const VmathVector3 *unitVec1 ); + +/* + * Conditionally select between two 3-D vectors + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + * However, the transfer of select1 to a VMX register may use more processing time than a branch. + */ +static inline void vmathV3Select( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1, unsigned int select1 ); + +/* + * Store x, y, and z elements of a 3-D vector in the first three words of a quadword. + * The value of the fourth word (the word with the highest address) remains unchanged + */ +static inline void vmathV3StoreXYZ( const VmathVector3 *vec, vec_float4 *quad ); + +/* + * Load four three-float 3-D vectors, stored in three quadwords + */ +static inline void vmathV3LoadXYZArray( VmathVector3 *vec0, VmathVector3 *vec1, VmathVector3 *vec2, VmathVector3 *vec3, const vec_float4 *threeQuads ); + +/* + * Store four 3-D vectors in three quadwords + */ +static inline void vmathV3StoreXYZArray( const VmathVector3 *vec0, const VmathVector3 *vec1, const VmathVector3 *vec2, const VmathVector3 *vec3, vec_float4 *threeQuads ); + +/* + * Store eight 3-D vectors as half-floats + */ +static inline void vmathV3StoreHalfFloats( const VmathVector3 *vec0, const VmathVector3 *vec1, const VmathVector3 *vec2, const VmathVector3 *vec3, const VmathVector3 *vec4, const VmathVector3 *vec5, const VmathVector3 *vec6, const VmathVector3 *vec7, vec_ushort8 *threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV3Print( const VmathVector3 *vec ); + +/* + * Print a 3-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV3Prints( const VmathVector3 *vec, const char *name ); + +#endif + +/* + * Copy a 4-D vector + */ +static inline void vmathV4Copy( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Construct a 4-D vector from x, y, z, and w elements + */ +static inline void vmathV4MakeFromElems( VmathVector4 *result, float x, float y, float z, float w ); + +/* + * Construct a 4-D vector from a 3-D vector and a scalar + */ +static inline void vmathV4MakeFromV3Scalar( VmathVector4 *result, const VmathVector3 *xyz, float w ); + +/* + * Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + */ +static inline void vmathV4MakeFromV3( VmathVector4 *result, const VmathVector3 *vec ); + +/* + * Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + */ +static inline void vmathV4MakeFromP3( VmathVector4 *result, const VmathPoint3 *pnt ); + +/* + * Copy elements from a quaternion into a 4-D vector + */ +static inline void vmathV4MakeFromQ( VmathVector4 *result, const VmathQuat *quat ); + +/* + * Set all elements of a 4-D vector to the same scalar value + */ +static inline void vmathV4MakeFromScalar( VmathVector4 *result, float scalar ); + +/* + * Set vector float data in a 4-D vector + */ +static inline void vmathV4MakeFrom128( VmathVector4 *result, vec_float4 vf4 ); + +/* + * Get vector float data from a 4-D vector + */ +static inline vec_float4 vmathV4Get128( const VmathVector4 *vec ); + +/* + * Set the x, y, and z elements of a 4-D vector + * NOTE: + * This function does not change the w element. + */ +static inline void vmathV4SetXYZ( VmathVector4 *result, const VmathVector3 *vec ); + +/* + * Get the x, y, and z elements of a 4-D vector + */ +static inline void vmathV4GetXYZ( VmathVector3 *result, const VmathVector4 *vec ); + +/* + * Set the x element of a 4-D vector + */ +static inline void vmathV4SetX( VmathVector4 *result, float x ); + +/* + * Set the y element of a 4-D vector + */ +static inline void vmathV4SetY( VmathVector4 *result, float y ); + +/* + * Set the z element of a 4-D vector + */ +static inline void vmathV4SetZ( VmathVector4 *result, float z ); + +/* + * Set the w element of a 4-D vector + */ +static inline void vmathV4SetW( VmathVector4 *result, float w ); + +/* + * Get the x element of a 4-D vector + */ +static inline float vmathV4GetX( const VmathVector4 *vec ); + +/* + * Get the y element of a 4-D vector + */ +static inline float vmathV4GetY( const VmathVector4 *vec ); + +/* + * Get the z element of a 4-D vector + */ +static inline float vmathV4GetZ( const VmathVector4 *vec ); + +/* + * Get the w element of a 4-D vector + */ +static inline float vmathV4GetW( const VmathVector4 *vec ); + +/* + * Set an x, y, z, or w element of a 4-D vector by index + */ +static inline void vmathV4SetElem( VmathVector4 *result, int idx, float value ); + +/* + * Get an x, y, z, or w element of a 4-D vector by index + */ +static inline float vmathV4GetElem( const VmathVector4 *vec, int idx ); + +/* + * Add two 4-D vectors + */ +static inline void vmathV4Add( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Subtract a 4-D vector from another 4-D vector + */ +static inline void vmathV4Sub( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Multiply a 4-D vector by a scalar + */ +static inline void vmathV4ScalarMul( VmathVector4 *result, const VmathVector4 *vec, float scalar ); + +/* + * Divide a 4-D vector by a scalar + */ +static inline void vmathV4ScalarDiv( VmathVector4 *result, const VmathVector4 *vec, float scalar ); + +/* + * Negate all elements of a 4-D vector + */ +static inline void vmathV4Neg( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Construct x axis + */ +static inline void vmathV4MakeXAxis( VmathVector4 *result ); + +/* + * Construct y axis + */ +static inline void vmathV4MakeYAxis( VmathVector4 *result ); + +/* + * Construct z axis + */ +static inline void vmathV4MakeZAxis( VmathVector4 *result ); + +/* + * Construct w axis + */ +static inline void vmathV4MakeWAxis( VmathVector4 *result ); + +/* + * Multiply two 4-D vectors per element + */ +static inline void vmathV4MulPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Divide two 4-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline void vmathV4DivPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Compute the reciprocal of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline void vmathV4RecipPerElem( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Compute the square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline void vmathV4SqrtPerElem( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Compute the reciprocal square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline void vmathV4RsqrtPerElem( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Compute the absolute value of a 4-D vector per element + */ +static inline void vmathV4AbsPerElem( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Copy sign from one 4-D vector to another, per element + */ +static inline void vmathV4CopySignPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Maximum of two 4-D vectors per element + */ +static inline void vmathV4MaxPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Minimum of two 4-D vectors per element + */ +static inline void vmathV4MinPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Maximum element of a 4-D vector + */ +static inline float vmathV4MaxElem( const VmathVector4 *vec ); + +/* + * Minimum element of a 4-D vector + */ +static inline float vmathV4MinElem( const VmathVector4 *vec ); + +/* + * Compute the sum of all elements of a 4-D vector + */ +static inline float vmathV4Sum( const VmathVector4 *vec ); + +/* + * Compute the dot product of two 4-D vectors + */ +static inline float vmathV4Dot( const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Compute the square of the length of a 4-D vector + */ +static inline float vmathV4LengthSqr( const VmathVector4 *vec ); + +/* + * Compute the length of a 4-D vector + */ +static inline float vmathV4Length( const VmathVector4 *vec ); + +/* + * Normalize a 4-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline void vmathV4Normalize( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Outer product of two 4-D vectors + */ +static inline void vmathV4Outer( VmathMatrix4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Linear interpolation between two 4-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathV4Lerp( VmathVector4 *result, float t, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Spherical linear interpolation between two 4-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline void vmathV4Slerp( VmathVector4 *result, float t, const VmathVector4 *unitVec0, const VmathVector4 *unitVec1 ); + +/* + * Conditionally select between two 4-D vectors + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + * However, the transfer of select1 to a VMX register may use more processing time than a branch. + */ +static inline void vmathV4Select( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1, unsigned int select1 ); + +/* + * Store four 4-D vectors as half-floats + */ +static inline void vmathV4StoreHalfFloats( const VmathVector4 *vec0, const VmathVector4 *vec1, const VmathVector4 *vec2, const VmathVector4 *vec3, vec_ushort8 *twoQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV4Print( const VmathVector4 *vec ); + +/* + * Print a 4-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV4Prints( const VmathVector4 *vec, const char *name ); + +#endif + +/* + * Copy a 3-D point + */ +static inline void vmathP3Copy( VmathPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Construct a 3-D point from x, y, and z elements + */ +static inline void vmathP3MakeFromElems( VmathPoint3 *result, float x, float y, float z ); + +/* + * Copy elements from a 3-D vector into a 3-D point + */ +static inline void vmathP3MakeFromV3( VmathPoint3 *result, const VmathVector3 *vec ); + +/* + * Set all elements of a 3-D point to the same scalar value + */ +static inline void vmathP3MakeFromScalar( VmathPoint3 *result, float scalar ); + +/* + * Set vector float data in a 3-D point + */ +static inline void vmathP3MakeFrom128( VmathPoint3 *result, vec_float4 vf4 ); + +/* + * Get vector float data from a 3-D point + */ +static inline vec_float4 vmathP3Get128( const VmathPoint3 *pnt ); + +/* + * Set the x element of a 3-D point + */ +static inline void vmathP3SetX( VmathPoint3 *result, float x ); + +/* + * Set the y element of a 3-D point + */ +static inline void vmathP3SetY( VmathPoint3 *result, float y ); + +/* + * Set the z element of a 3-D point + */ +static inline void vmathP3SetZ( VmathPoint3 *result, float z ); + +/* + * Get the x element of a 3-D point + */ +static inline float vmathP3GetX( const VmathPoint3 *pnt ); + +/* + * Get the y element of a 3-D point + */ +static inline float vmathP3GetY( const VmathPoint3 *pnt ); + +/* + * Get the z element of a 3-D point + */ +static inline float vmathP3GetZ( const VmathPoint3 *pnt ); + +/* + * Set an x, y, or z element of a 3-D point by index + */ +static inline void vmathP3SetElem( VmathPoint3 *result, int idx, float value ); + +/* + * Get an x, y, or z element of a 3-D point by index + */ +static inline float vmathP3GetElem( const VmathPoint3 *pnt, int idx ); + +/* + * Subtract a 3-D point from another 3-D point + */ +static inline void vmathP3Sub( VmathVector3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Add a 3-D point to a 3-D vector + */ +static inline void vmathP3AddV3( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *vec ); + +/* + * Subtract a 3-D vector from a 3-D point + */ +static inline void vmathP3SubV3( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *vec ); + +/* + * Multiply two 3-D points per element + */ +static inline void vmathP3MulPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Divide two 3-D points per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline void vmathP3DivPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Compute the reciprocal of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline void vmathP3RecipPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Compute the square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline void vmathP3SqrtPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Compute the reciprocal square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline void vmathP3RsqrtPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Compute the absolute value of a 3-D point per element + */ +static inline void vmathP3AbsPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Copy sign from one 3-D point to another, per element + */ +static inline void vmathP3CopySignPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Maximum of two 3-D points per element + */ +static inline void vmathP3MaxPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Minimum of two 3-D points per element + */ +static inline void vmathP3MinPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Maximum element of a 3-D point + */ +static inline float vmathP3MaxElem( const VmathPoint3 *pnt ); + +/* + * Minimum element of a 3-D point + */ +static inline float vmathP3MinElem( const VmathPoint3 *pnt ); + +/* + * Compute the sum of all elements of a 3-D point + */ +static inline float vmathP3Sum( const VmathPoint3 *pnt ); + +/* + * Apply uniform scale to a 3-D point + */ +static inline void vmathP3Scale( VmathPoint3 *result, const VmathPoint3 *pnt, float scaleVal ); + +/* + * Apply non-uniform scale to a 3-D point + */ +static inline void vmathP3NonUniformScale( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *scaleVec ); + +/* + * Scalar projection of a 3-D point on a unit-length 3-D vector + */ +static inline float vmathP3Projection( const VmathPoint3 *pnt, const VmathVector3 *unitVec ); + +/* + * Compute the square of the distance of a 3-D point from the coordinate-system origin + */ +static inline float vmathP3DistSqrFromOrigin( const VmathPoint3 *pnt ); + +/* + * Compute the distance of a 3-D point from the coordinate-system origin + */ +static inline float vmathP3DistFromOrigin( const VmathPoint3 *pnt ); + +/* + * Compute the square of the distance between two 3-D points + */ +static inline float vmathP3DistSqr( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Compute the distance between two 3-D points + */ +static inline float vmathP3Dist( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Linear interpolation between two 3-D points + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathP3Lerp( VmathPoint3 *result, float t, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Conditionally select between two 3-D points + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + * However, the transfer of select1 to a VMX register may use more processing time than a branch. + */ +static inline void vmathP3Select( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, unsigned int select1 ); + +/* + * Store x, y, and z elements of a 3-D point in the first three words of a quadword. + * The value of the fourth word (the word with the highest address) remains unchanged + */ +static inline void vmathP3StoreXYZ( const VmathPoint3 *pnt, vec_float4 *quad ); + +/* + * Load four three-float 3-D points, stored in three quadwords + */ +static inline void vmathP3LoadXYZArray( VmathPoint3 *pnt0, VmathPoint3 *pnt1, VmathPoint3 *pnt2, VmathPoint3 *pnt3, const vec_float4 *threeQuads ); + +/* + * Store four 3-D points in three quadwords + */ +static inline void vmathP3StoreXYZArray( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, const VmathPoint3 *pnt2, const VmathPoint3 *pnt3, vec_float4 *threeQuads ); + +/* + * Store eight 3-D points as half-floats + */ +static inline void vmathP3StoreHalfFloats( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, const VmathPoint3 *pnt2, const VmathPoint3 *pnt3, const VmathPoint3 *pnt4, const VmathPoint3 *pnt5, const VmathPoint3 *pnt6, const VmathPoint3 *pnt7, vec_ushort8 *threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D point + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathP3Print( const VmathPoint3 *pnt ); + +/* + * Print a 3-D point and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathP3Prints( const VmathPoint3 *pnt, const char *name ); + +#endif + +/* + * Copy a quaternion + */ +static inline void vmathQCopy( VmathQuat *result, const VmathQuat *quat ); + +/* + * Construct a quaternion from x, y, z, and w elements + */ +static inline void vmathQMakeFromElems( VmathQuat *result, float x, float y, float z, float w ); + +/* + * Construct a quaternion from a 3-D vector and a scalar + */ +static inline void vmathQMakeFromV3Scalar( VmathQuat *result, const VmathVector3 *xyz, float w ); + +/* + * Copy elements from a 4-D vector into a quaternion + */ +static inline void vmathQMakeFromV4( VmathQuat *result, const VmathVector4 *vec ); + +/* + * Convert a rotation matrix to a unit-length quaternion + */ +static inline void vmathQMakeFromM3( VmathQuat *result, const VmathMatrix3 *rotMat ); + +/* + * Set all elements of a quaternion to the same scalar value + */ +static inline void vmathQMakeFromScalar( VmathQuat *result, float scalar ); + +/* + * Set vector float data in a quaternion + */ +static inline void vmathQMakeFrom128( VmathQuat *result, vec_float4 vf4 ); + +/* + * Get vector float data from a quaternion + */ +static inline vec_float4 vmathQGet128( const VmathQuat *quat ); + +/* + * Set the x, y, and z elements of a quaternion + * NOTE: + * This function does not change the w element. + */ +static inline void vmathQSetXYZ( VmathQuat *result, const VmathVector3 *vec ); + +/* + * Get the x, y, and z elements of a quaternion + */ +static inline void vmathQGetXYZ( VmathVector3 *result, const VmathQuat *quat ); + +/* + * Set the x element of a quaternion + */ +static inline void vmathQSetX( VmathQuat *result, float x ); + +/* + * Set the y element of a quaternion + */ +static inline void vmathQSetY( VmathQuat *result, float y ); + +/* + * Set the z element of a quaternion + */ +static inline void vmathQSetZ( VmathQuat *result, float z ); + +/* + * Set the w element of a quaternion + */ +static inline void vmathQSetW( VmathQuat *result, float w ); + +/* + * Get the x element of a quaternion + */ +static inline float vmathQGetX( const VmathQuat *quat ); + +/* + * Get the y element of a quaternion + */ +static inline float vmathQGetY( const VmathQuat *quat ); + +/* + * Get the z element of a quaternion + */ +static inline float vmathQGetZ( const VmathQuat *quat ); + +/* + * Get the w element of a quaternion + */ +static inline float vmathQGetW( const VmathQuat *quat ); + +/* + * Set an x, y, z, or w element of a quaternion by index + */ +static inline void vmathQSetElem( VmathQuat *result, int idx, float value ); + +/* + * Get an x, y, z, or w element of a quaternion by index + */ +static inline float vmathQGetElem( const VmathQuat *quat, int idx ); + +/* + * Add two quaternions + */ +static inline void vmathQAdd( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ); + +/* + * Subtract a quaternion from another quaternion + */ +static inline void vmathQSub( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ); + +/* + * Multiply two quaternions + */ +static inline void vmathQMul( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ); + +/* + * Multiply a quaternion by a scalar + */ +static inline void vmathQScalarMul( VmathQuat *result, const VmathQuat *quat, float scalar ); + +/* + * Divide a quaternion by a scalar + */ +static inline void vmathQScalarDiv( VmathQuat *result, const VmathQuat *quat, float scalar ); + +/* + * Negate all elements of a quaternion + */ +static inline void vmathQNeg( VmathQuat *result, const VmathQuat *quat ); + +/* + * Construct an identity quaternion + */ +static inline void vmathQMakeIdentity( VmathQuat *result ); + +/* + * Construct a quaternion to rotate between two unit-length 3-D vectors + * NOTE: + * The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + */ +static inline void vmathQMakeRotationArc( VmathQuat *result, const VmathVector3 *unitVec0, const VmathVector3 *unitVec1 ); + +/* + * Construct a quaternion to rotate around a unit-length 3-D vector + */ +static inline void vmathQMakeRotationAxis( VmathQuat *result, float radians, const VmathVector3 *unitVec ); + +/* + * Construct a quaternion to rotate around the x axis + */ +static inline void vmathQMakeRotationX( VmathQuat *result, float radians ); + +/* + * Construct a quaternion to rotate around the y axis + */ +static inline void vmathQMakeRotationY( VmathQuat *result, float radians ); + +/* + * Construct a quaternion to rotate around the z axis + */ +static inline void vmathQMakeRotationZ( VmathQuat *result, float radians ); + +/* + * Compute the conjugate of a quaternion + */ +static inline void vmathQConj( VmathQuat *result, const VmathQuat *quat ); + +/* + * Use a unit-length quaternion to rotate a 3-D vector + */ +static inline void vmathQRotate( VmathVector3 *result, const VmathQuat *unitQuat, const VmathVector3 *vec ); + +/* + * Compute the dot product of two quaternions + */ +static inline float vmathQDot( const VmathQuat *quat0, const VmathQuat *quat1 ); + +/* + * Compute the norm of a quaternion + */ +static inline float vmathQNorm( const VmathQuat *quat ); + +/* + * Compute the length of a quaternion + */ +static inline float vmathQLength( const VmathQuat *quat ); + +/* + * Normalize a quaternion + * NOTE: + * The result is unpredictable when all elements of quat are at or near zero. + */ +static inline void vmathQNormalize( VmathQuat *result, const VmathQuat *quat ); + +/* + * Linear interpolation between two quaternions + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathQLerp( VmathQuat *result, float t, const VmathQuat *quat0, const VmathQuat *quat1 ); + +/* + * Spherical linear interpolation between two quaternions + * NOTE: + * Interpolates along the shortest path between orientations. + * Does not clamp t between 0 and 1. + */ +static inline void vmathQSlerp( VmathQuat *result, float t, const VmathQuat *unitQuat0, const VmathQuat *unitQuat1 ); + +/* + * Spherical quadrangle interpolation + */ +static inline void vmathQSquad( VmathQuat *result, float t, const VmathQuat *unitQuat0, const VmathQuat *unitQuat1, const VmathQuat *unitQuat2, const VmathQuat *unitQuat3 ); + +/* + * Conditionally select between two quaternions + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + * However, the transfer of select1 to a VMX register may use more processing time than a branch. + */ +static inline void vmathQSelect( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a quaternion + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathQPrint( const VmathQuat *quat ); + +/* + * Print a quaternion and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathQPrints( const VmathQuat *quat, const char *name ); + +#endif + +/* + * Copy a 3x3 matrix + */ +static inline void vmathM3Copy( VmathMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Construct a 3x3 matrix containing the specified columns + */ +static inline void vmathM3MakeFromCols( VmathMatrix3 *result, const VmathVector3 *col0, const VmathVector3 *col1, const VmathVector3 *col2 ); + +/* + * Construct a 3x3 rotation matrix from a unit-length quaternion + */ +static inline void vmathM3MakeFromQ( VmathMatrix3 *result, const VmathQuat *unitQuat ); + +/* + * Set all elements of a 3x3 matrix to the same scalar value + */ +static inline void vmathM3MakeFromScalar( VmathMatrix3 *result, float scalar ); + +/* + * Set column 0 of a 3x3 matrix + */ +static inline void vmathM3SetCol0( VmathMatrix3 *result, const VmathVector3 *col0 ); + +/* + * Set column 1 of a 3x3 matrix + */ +static inline void vmathM3SetCol1( VmathMatrix3 *result, const VmathVector3 *col1 ); + +/* + * Set column 2 of a 3x3 matrix + */ +static inline void vmathM3SetCol2( VmathMatrix3 *result, const VmathVector3 *col2 ); + +/* + * Get column 0 of a 3x3 matrix + */ +static inline void vmathM3GetCol0( VmathVector3 *result, const VmathMatrix3 *mat ); + +/* + * Get column 1 of a 3x3 matrix + */ +static inline void vmathM3GetCol1( VmathVector3 *result, const VmathMatrix3 *mat ); + +/* + * Get column 2 of a 3x3 matrix + */ +static inline void vmathM3GetCol2( VmathVector3 *result, const VmathMatrix3 *mat ); + +/* + * Set the column of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3SetCol( VmathMatrix3 *result, int col, const VmathVector3 *vec ); + +/* + * Set the row of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3SetRow( VmathMatrix3 *result, int row, const VmathVector3 *vec ); + +/* + * Get the column of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3GetCol( VmathVector3 *result, const VmathMatrix3 *mat, int col ); + +/* + * Get the row of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3GetRow( VmathVector3 *result, const VmathMatrix3 *mat, int row ); + +/* + * Set the element of a 3x3 matrix referred to by column and row indices + */ +static inline void vmathM3SetElem( VmathMatrix3 *result, int col, int row, float val ); + +/* + * Get the element of a 3x3 matrix referred to by column and row indices + */ +static inline float vmathM3GetElem( const VmathMatrix3 *mat, int col, int row ); + +/* + * Add two 3x3 matrices + */ +static inline void vmathM3Add( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ); + +/* + * Subtract a 3x3 matrix from another 3x3 matrix + */ +static inline void vmathM3Sub( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ); + +/* + * Negate all elements of a 3x3 matrix + */ +static inline void vmathM3Neg( VmathMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Multiply a 3x3 matrix by a scalar + */ +static inline void vmathM3ScalarMul( VmathMatrix3 *result, const VmathMatrix3 *mat, float scalar ); + +/* + * Multiply a 3x3 matrix by a 3-D vector + */ +static inline void vmathM3MulV3( VmathVector3 *result, const VmathMatrix3 *mat, const VmathVector3 *vec ); + +/* + * Multiply two 3x3 matrices + */ +static inline void vmathM3Mul( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ); + +/* + * Construct an identity 3x3 matrix + */ +static inline void vmathM3MakeIdentity( VmathMatrix3 *result ); + +/* + * Construct a 3x3 matrix to rotate around the x axis + */ +static inline void vmathM3MakeRotationX( VmathMatrix3 *result, float radians ); + +/* + * Construct a 3x3 matrix to rotate around the y axis + */ +static inline void vmathM3MakeRotationY( VmathMatrix3 *result, float radians ); + +/* + * Construct a 3x3 matrix to rotate around the z axis + */ +static inline void vmathM3MakeRotationZ( VmathMatrix3 *result, float radians ); + +/* + * Construct a 3x3 matrix to rotate around the x, y, and z axes + */ +static inline void vmathM3MakeRotationZYX( VmathMatrix3 *result, const VmathVector3 *radiansXYZ ); + +/* + * Construct a 3x3 matrix to rotate around a unit-length 3-D vector + */ +static inline void vmathM3MakeRotationAxis( VmathMatrix3 *result, float radians, const VmathVector3 *unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline void vmathM3MakeRotationQ( VmathMatrix3 *result, const VmathQuat *unitQuat ); + +/* + * Construct a 3x3 matrix to perform scaling + */ +static inline void vmathM3MakeScale( VmathMatrix3 *result, const VmathVector3 *scaleVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathM3AppendScale( VmathMatrix3 *result, const VmathMatrix3 *mat, const VmathVector3 *scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathM3PrependScale( VmathMatrix3 *result, const VmathVector3 *scaleVec, const VmathMatrix3 *mat ); + +/* + * Multiply two 3x3 matrices per element + */ +static inline void vmathM3MulPerElem( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ); + +/* + * Compute the absolute value of a 3x3 matrix per element + */ +static inline void vmathM3AbsPerElem( VmathMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Transpose of a 3x3 matrix + */ +static inline void vmathM3Transpose( VmathMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Compute the inverse of a 3x3 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline void vmathM3Inverse( VmathMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Determinant of a 3x3 matrix + */ +static inline float vmathM3Determinant( const VmathMatrix3 *mat ); + +/* + * Conditionally select between two 3x3 matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + * However, the transfer of select1 to a VMX register may use more processing time than a branch. + */ +static inline void vmathM3Select( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x3 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM3Print( const VmathMatrix3 *mat ); + +/* + * Print a 3x3 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM3Prints( const VmathMatrix3 *mat, const char *name ); + +#endif + +/* + * Copy a 4x4 matrix + */ +static inline void vmathM4Copy( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Construct a 4x4 matrix containing the specified columns + */ +static inline void vmathM4MakeFromCols( VmathMatrix4 *result, const VmathVector4 *col0, const VmathVector4 *col1, const VmathVector4 *col2, const VmathVector4 *col3 ); + +/* + * Construct a 4x4 matrix from a 3x4 transformation matrix + */ +static inline void vmathM4MakeFromT3( VmathMatrix4 *result, const VmathTransform3 *mat ); + +/* + * Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + */ +static inline void vmathM4MakeFromM3V3( VmathMatrix4 *result, const VmathMatrix3 *mat, const VmathVector3 *translateVec ); + +/* + * Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + */ +static inline void vmathM4MakeFromQV3( VmathMatrix4 *result, const VmathQuat *unitQuat, const VmathVector3 *translateVec ); + +/* + * Set all elements of a 4x4 matrix to the same scalar value + */ +static inline void vmathM4MakeFromScalar( VmathMatrix4 *result, float scalar ); + +/* + * Set the upper-left 3x3 submatrix + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathM4SetUpper3x3( VmathMatrix4 *result, const VmathMatrix3 *mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 4x4 matrix + */ +static inline void vmathM4GetUpper3x3( VmathMatrix3 *result, const VmathMatrix4 *mat ); + +/* + * Set translation component + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathM4SetTranslation( VmathMatrix4 *result, const VmathVector3 *translateVec ); + +/* + * Get the translation component of a 4x4 matrix + */ +static inline void vmathM4GetTranslation( VmathVector3 *result, const VmathMatrix4 *mat ); + +/* + * Set column 0 of a 4x4 matrix + */ +static inline void vmathM4SetCol0( VmathMatrix4 *result, const VmathVector4 *col0 ); + +/* + * Set column 1 of a 4x4 matrix + */ +static inline void vmathM4SetCol1( VmathMatrix4 *result, const VmathVector4 *col1 ); + +/* + * Set column 2 of a 4x4 matrix + */ +static inline void vmathM4SetCol2( VmathMatrix4 *result, const VmathVector4 *col2 ); + +/* + * Set column 3 of a 4x4 matrix + */ +static inline void vmathM4SetCol3( VmathMatrix4 *result, const VmathVector4 *col3 ); + +/* + * Get column 0 of a 4x4 matrix + */ +static inline void vmathM4GetCol0( VmathVector4 *result, const VmathMatrix4 *mat ); + +/* + * Get column 1 of a 4x4 matrix + */ +static inline void vmathM4GetCol1( VmathVector4 *result, const VmathMatrix4 *mat ); + +/* + * Get column 2 of a 4x4 matrix + */ +static inline void vmathM4GetCol2( VmathVector4 *result, const VmathMatrix4 *mat ); + +/* + * Get column 3 of a 4x4 matrix + */ +static inline void vmathM4GetCol3( VmathVector4 *result, const VmathMatrix4 *mat ); + +/* + * Set the column of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4SetCol( VmathMatrix4 *result, int col, const VmathVector4 *vec ); + +/* + * Set the row of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4SetRow( VmathMatrix4 *result, int row, const VmathVector4 *vec ); + +/* + * Get the column of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4GetCol( VmathVector4 *result, const VmathMatrix4 *mat, int col ); + +/* + * Get the row of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4GetRow( VmathVector4 *result, const VmathMatrix4 *mat, int row ); + +/* + * Set the element of a 4x4 matrix referred to by column and row indices + */ +static inline void vmathM4SetElem( VmathMatrix4 *result, int col, int row, float val ); + +/* + * Get the element of a 4x4 matrix referred to by column and row indices + */ +static inline float vmathM4GetElem( const VmathMatrix4 *mat, int col, int row ); + +/* + * Add two 4x4 matrices + */ +static inline void vmathM4Add( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ); + +/* + * Subtract a 4x4 matrix from another 4x4 matrix + */ +static inline void vmathM4Sub( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ); + +/* + * Negate all elements of a 4x4 matrix + */ +static inline void vmathM4Neg( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Multiply a 4x4 matrix by a scalar + */ +static inline void vmathM4ScalarMul( VmathMatrix4 *result, const VmathMatrix4 *mat, float scalar ); + +/* + * Multiply a 4x4 matrix by a 4-D vector + */ +static inline void vmathM4MulV4( VmathVector4 *result, const VmathMatrix4 *mat, const VmathVector4 *vec ); + +/* + * Multiply a 4x4 matrix by a 3-D vector + */ +static inline void vmathM4MulV3( VmathVector4 *result, const VmathMatrix4 *mat, const VmathVector3 *vec ); + +/* + * Multiply a 4x4 matrix by a 3-D point + */ +static inline void vmathM4MulP3( VmathVector4 *result, const VmathMatrix4 *mat, const VmathPoint3 *pnt ); + +/* + * Multiply two 4x4 matrices + */ +static inline void vmathM4Mul( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ); + +/* + * Multiply a 4x4 matrix by a 3x4 transformation matrix + */ +static inline void vmathM4MulT3( VmathMatrix4 *result, const VmathMatrix4 *mat, const VmathTransform3 *tfrm ); + +/* + * Construct an identity 4x4 matrix + */ +static inline void vmathM4MakeIdentity( VmathMatrix4 *result ); + +/* + * Construct a 4x4 matrix to rotate around the x axis + */ +static inline void vmathM4MakeRotationX( VmathMatrix4 *result, float radians ); + +/* + * Construct a 4x4 matrix to rotate around the y axis + */ +static inline void vmathM4MakeRotationY( VmathMatrix4 *result, float radians ); + +/* + * Construct a 4x4 matrix to rotate around the z axis + */ +static inline void vmathM4MakeRotationZ( VmathMatrix4 *result, float radians ); + +/* + * Construct a 4x4 matrix to rotate around the x, y, and z axes + */ +static inline void vmathM4MakeRotationZYX( VmathMatrix4 *result, const VmathVector3 *radiansXYZ ); + +/* + * Construct a 4x4 matrix to rotate around a unit-length 3-D vector + */ +static inline void vmathM4MakeRotationAxis( VmathMatrix4 *result, float radians, const VmathVector3 *unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline void vmathM4MakeRotationQ( VmathMatrix4 *result, const VmathQuat *unitQuat ); + +/* + * Construct a 4x4 matrix to perform scaling + */ +static inline void vmathM4MakeScale( VmathMatrix4 *result, const VmathVector3 *scaleVec ); + +/* + * Construct a 4x4 matrix to perform translation + */ +static inline void vmathM4MakeTranslation( VmathMatrix4 *result, const VmathVector3 *translateVec ); + +/* + * Construct viewing matrix based on eye position, position looked at, and up direction + */ +static inline void vmathM4MakeLookAt( VmathMatrix4 *result, const VmathPoint3 *eyePos, const VmathPoint3 *lookAtPos, const VmathVector3 *upVec ); + +/* + * Construct a perspective projection matrix + */ +static inline void vmathM4MakePerspective( VmathMatrix4 *result, float fovyRadians, float aspect, float zNear, float zFar ); + +/* + * Construct a perspective projection matrix based on frustum + */ +static inline void vmathM4MakeFrustum( VmathMatrix4 *result, float left, float right, float bottom, float top, float zNear, float zFar ); + +/* + * Construct an orthographic projection matrix + */ +static inline void vmathM4MakeOrthographic( VmathMatrix4 *result, float left, float right, float bottom, float top, float zNear, float zFar ); + +/* + * Append (post-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathM4AppendScale( VmathMatrix4 *result, const VmathMatrix4 *mat, const VmathVector3 *scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathM4PrependScale( VmathMatrix4 *result, const VmathVector3 *scaleVec, const VmathMatrix4 *mat ); + +/* + * Multiply two 4x4 matrices per element + */ +static inline void vmathM4MulPerElem( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ); + +/* + * Compute the absolute value of a 4x4 matrix per element + */ +static inline void vmathM4AbsPerElem( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Transpose of a 4x4 matrix + */ +static inline void vmathM4Transpose( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Compute the inverse of a 4x4 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline void vmathM4Inverse( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline void vmathM4AffineInverse( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. + */ +static inline void vmathM4OrthoInverse( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Determinant of a 4x4 matrix + */ +static inline float vmathM4Determinant( const VmathMatrix4 *mat ); + +/* + * Conditionally select between two 4x4 matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + * However, the transfer of select1 to a VMX register may use more processing time than a branch. + */ +static inline void vmathM4Select( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4x4 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM4Print( const VmathMatrix4 *mat ); + +/* + * Print a 4x4 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM4Prints( const VmathMatrix4 *mat, const char *name ); + +#endif + +/* + * Copy a 3x4 transformation matrix + */ +static inline void vmathT3Copy( VmathTransform3 *result, const VmathTransform3 *tfrm ); + +/* + * Construct a 3x4 transformation matrix containing the specified columns + */ +static inline void vmathT3MakeFromCols( VmathTransform3 *result, const VmathVector3 *col0, const VmathVector3 *col1, const VmathVector3 *col2, const VmathVector3 *col3 ); + +/* + * Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + */ +static inline void vmathT3MakeFromM3V3( VmathTransform3 *result, const VmathMatrix3 *tfrm, const VmathVector3 *translateVec ); + +/* + * Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + */ +static inline void vmathT3MakeFromQV3( VmathTransform3 *result, const VmathQuat *unitQuat, const VmathVector3 *translateVec ); + +/* + * Set all elements of a 3x4 transformation matrix to the same scalar value + */ +static inline void vmathT3MakeFromScalar( VmathTransform3 *result, float scalar ); + +/* + * Set the upper-left 3x3 submatrix + */ +static inline void vmathT3SetUpper3x3( VmathTransform3 *result, const VmathMatrix3 *mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + */ +static inline void vmathT3GetUpper3x3( VmathMatrix3 *result, const VmathTransform3 *tfrm ); + +/* + * Set translation component + */ +static inline void vmathT3SetTranslation( VmathTransform3 *result, const VmathVector3 *translateVec ); + +/* + * Get the translation component of a 3x4 transformation matrix + */ +static inline void vmathT3GetTranslation( VmathVector3 *result, const VmathTransform3 *tfrm ); + +/* + * Set column 0 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol0( VmathTransform3 *result, const VmathVector3 *col0 ); + +/* + * Set column 1 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol1( VmathTransform3 *result, const VmathVector3 *col1 ); + +/* + * Set column 2 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol2( VmathTransform3 *result, const VmathVector3 *col2 ); + +/* + * Set column 3 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol3( VmathTransform3 *result, const VmathVector3 *col3 ); + +/* + * Get column 0 of a 3x4 transformation matrix + */ +static inline void vmathT3GetCol0( VmathVector3 *result, const VmathTransform3 *tfrm ); + +/* + * Get column 1 of a 3x4 transformation matrix + */ +static inline void vmathT3GetCol1( VmathVector3 *result, const VmathTransform3 *tfrm ); + +/* + * Get column 2 of a 3x4 transformation matrix + */ +static inline void vmathT3GetCol2( VmathVector3 *result, const VmathTransform3 *tfrm ); + +/* + * Get column 3 of a 3x4 transformation matrix + */ +static inline void vmathT3GetCol3( VmathVector3 *result, const VmathTransform3 *tfrm ); + +/* + * Set the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3SetCol( VmathTransform3 *result, int col, const VmathVector3 *vec ); + +/* + * Set the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3SetRow( VmathTransform3 *result, int row, const VmathVector4 *vec ); + +/* + * Get the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3GetCol( VmathVector3 *result, const VmathTransform3 *tfrm, int col ); + +/* + * Get the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3GetRow( VmathVector4 *result, const VmathTransform3 *tfrm, int row ); + +/* + * Set the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline void vmathT3SetElem( VmathTransform3 *result, int col, int row, float val ); + +/* + * Get the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline float vmathT3GetElem( const VmathTransform3 *tfrm, int col, int row ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D vector + */ +static inline void vmathT3MulV3( VmathVector3 *result, const VmathTransform3 *tfrm, const VmathVector3 *vec ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D point + */ +static inline void vmathT3MulP3( VmathPoint3 *result, const VmathTransform3 *tfrm, const VmathPoint3 *pnt ); + +/* + * Multiply two 3x4 transformation matrices + */ +static inline void vmathT3Mul( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1 ); + +/* + * Construct an identity 3x4 transformation matrix + */ +static inline void vmathT3MakeIdentity( VmathTransform3 *result ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x axis + */ +static inline void vmathT3MakeRotationX( VmathTransform3 *result, float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the y axis + */ +static inline void vmathT3MakeRotationY( VmathTransform3 *result, float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the z axis + */ +static inline void vmathT3MakeRotationZ( VmathTransform3 *result, float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + */ +static inline void vmathT3MakeRotationZYX( VmathTransform3 *result, const VmathVector3 *radiansXYZ ); + +/* + * Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + */ +static inline void vmathT3MakeRotationAxis( VmathTransform3 *result, float radians, const VmathVector3 *unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline void vmathT3MakeRotationQ( VmathTransform3 *result, const VmathQuat *unitQuat ); + +/* + * Construct a 3x4 transformation matrix to perform scaling + */ +static inline void vmathT3MakeScale( VmathTransform3 *result, const VmathVector3 *scaleVec ); + +/* + * Construct a 3x4 transformation matrix to perform translation + */ +static inline void vmathT3MakeTranslation( VmathTransform3 *result, const VmathVector3 *translateVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathT3AppendScale( VmathTransform3 *result, const VmathTransform3 *tfrm, const VmathVector3 *scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathT3PrependScale( VmathTransform3 *result, const VmathVector3 *scaleVec, const VmathTransform3 *tfrm ); + +/* + * Multiply two 3x4 transformation matrices per element + */ +static inline void vmathT3MulPerElem( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1 ); + +/* + * Compute the absolute value of a 3x4 transformation matrix per element + */ +static inline void vmathT3AbsPerElem( VmathTransform3 *result, const VmathTransform3 *tfrm ); + +/* + * Inverse of a 3x4 transformation matrix + * NOTE: + * Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. + */ +static inline void vmathT3Inverse( VmathTransform3 *result, const VmathTransform3 *tfrm ); + +/* + * Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. + */ +static inline void vmathT3OrthoInverse( VmathTransform3 *result, const VmathTransform3 *tfrm ); + +/* + * Conditionally select between two 3x4 transformation matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + * However, the transfer of select1 to a VMX register may use more processing time than a branch. + */ +static inline void vmathT3Select( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x4 transformation matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathT3Print( const VmathTransform3 *tfrm ); + +/* + * Print a 3x4 transformation matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathT3Prints( const VmathTransform3 *tfrm, const char *name ); + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#include "vec_aos.h" +#include "quat_aos.h" +#include "mat_aos.h" + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/vectormath_aos_v.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/vectormath_aos_v.h new file mode 100644 index 0000000..a859917 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/vectormath_aos_v.h @@ -0,0 +1,1925 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_AOS_C_V_PPU_H +#define _VECTORMATH_AOS_C_V_PPU_H + +#include +#include +#include "vec_types.h" + +#ifdef _VECTORMATH_DEBUG +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef _VECTORMATH_AOS_C_TYPES_H +#define _VECTORMATH_AOS_C_TYPES_H + +/* A 3-D vector in array-of-structures format + */ +typedef struct _VmathVector3 +{ + vec_float4 vec128; +} VmathVector3; + +/* A 4-D vector in array-of-structures format + */ +typedef struct _VmathVector4 +{ + vec_float4 vec128; +} VmathVector4; + +/* A 3-D point in array-of-structures format + */ +typedef struct _VmathPoint3 +{ + vec_float4 vec128; +} VmathPoint3; + +/* A quaternion in array-of-structures format + */ +typedef struct _VmathQuat +{ + vec_float4 vec128; +} VmathQuat; + +/* A 3x3 matrix in array-of-structures format + */ +typedef struct _VmathMatrix3 +{ + VmathVector3 col0; + VmathVector3 col1; + VmathVector3 col2; +} VmathMatrix3; + +/* A 4x4 matrix in array-of-structures format + */ +typedef struct _VmathMatrix4 +{ + VmathVector4 col0; + VmathVector4 col1; + VmathVector4 col2; + VmathVector4 col3; +} VmathMatrix4; + +/* A 3x4 transformation matrix in array-of-structures format + */ +typedef struct _VmathTransform3 +{ + VmathVector3 col0; + VmathVector3 col1; + VmathVector3 col2; + VmathVector3 col3; +} VmathTransform3; + +#endif + +/* + * Construct a 3-D vector from x, y, and z elements + */ +static inline VmathVector3 vmathV3MakeFromElems_V( float x, float y, float z ); + +/* + * Copy elements from a 3-D point into a 3-D vector + */ +static inline VmathVector3 vmathV3MakeFromP3_V( VmathPoint3 pnt ); + +/* + * Set all elements of a 3-D vector to the same scalar value + */ +static inline VmathVector3 vmathV3MakeFromScalar_V( float scalar ); + +/* + * Set vector float data in a 3-D vector + */ +static inline VmathVector3 vmathV3MakeFrom128_V( vec_float4 vf4 ); + +/* + * Get vector float data from a 3-D vector + */ +static inline vec_float4 vmathV3Get128_V( VmathVector3 vec ); + +/* + * Set the x element of a 3-D vector + */ +static inline void vmathV3SetX_V( VmathVector3 *result, float x ); + +/* + * Set the y element of a 3-D vector + */ +static inline void vmathV3SetY_V( VmathVector3 *result, float y ); + +/* + * Set the z element of a 3-D vector + */ +static inline void vmathV3SetZ_V( VmathVector3 *result, float z ); + +/* + * Get the x element of a 3-D vector + */ +static inline float vmathV3GetX_V( VmathVector3 vec ); + +/* + * Get the y element of a 3-D vector + */ +static inline float vmathV3GetY_V( VmathVector3 vec ); + +/* + * Get the z element of a 3-D vector + */ +static inline float vmathV3GetZ_V( VmathVector3 vec ); + +/* + * Set an x, y, or z element of a 3-D vector by index + */ +static inline void vmathV3SetElem_V( VmathVector3 *result, int idx, float value ); + +/* + * Get an x, y, or z element of a 3-D vector by index + */ +static inline float vmathV3GetElem_V( VmathVector3 vec, int idx ); + +/* + * Add two 3-D vectors + */ +static inline VmathVector3 vmathV3Add_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Subtract a 3-D vector from another 3-D vector + */ +static inline VmathVector3 vmathV3Sub_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Add a 3-D vector to a 3-D point + */ +static inline VmathPoint3 vmathV3AddP3_V( VmathVector3 vec, VmathPoint3 pnt ); + +/* + * Multiply a 3-D vector by a scalar + */ +static inline VmathVector3 vmathV3ScalarMul_V( VmathVector3 vec, float scalar ); + +/* + * Divide a 3-D vector by a scalar + */ +static inline VmathVector3 vmathV3ScalarDiv_V( VmathVector3 vec, float scalar ); + +/* + * Negate all elements of a 3-D vector + */ +static inline VmathVector3 vmathV3Neg_V( VmathVector3 vec ); + +/* + * Construct x axis + */ +static inline VmathVector3 vmathV3MakeXAxis_V( ); + +/* + * Construct y axis + */ +static inline VmathVector3 vmathV3MakeYAxis_V( ); + +/* + * Construct z axis + */ +static inline VmathVector3 vmathV3MakeZAxis_V( ); + +/* + * Multiply two 3-D vectors per element + */ +static inline VmathVector3 vmathV3MulPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Divide two 3-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline VmathVector3 vmathV3DivPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Compute the reciprocal of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline VmathVector3 vmathV3RecipPerElem_V( VmathVector3 vec ); + +/* + * Compute the square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline VmathVector3 vmathV3SqrtPerElem_V( VmathVector3 vec ); + +/* + * Compute the reciprocal square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline VmathVector3 vmathV3RsqrtPerElem_V( VmathVector3 vec ); + +/* + * Compute the absolute value of a 3-D vector per element + */ +static inline VmathVector3 vmathV3AbsPerElem_V( VmathVector3 vec ); + +/* + * Copy sign from one 3-D vector to another, per element + */ +static inline VmathVector3 vmathV3CopySignPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Maximum of two 3-D vectors per element + */ +static inline VmathVector3 vmathV3MaxPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Minimum of two 3-D vectors per element + */ +static inline VmathVector3 vmathV3MinPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Maximum element of a 3-D vector + */ +static inline float vmathV3MaxElem_V( VmathVector3 vec ); + +/* + * Minimum element of a 3-D vector + */ +static inline float vmathV3MinElem_V( VmathVector3 vec ); + +/* + * Compute the sum of all elements of a 3-D vector + */ +static inline float vmathV3Sum_V( VmathVector3 vec ); + +/* + * Compute the dot product of two 3-D vectors + */ +static inline float vmathV3Dot_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Compute the square of the length of a 3-D vector + */ +static inline float vmathV3LengthSqr_V( VmathVector3 vec ); + +/* + * Compute the length of a 3-D vector + */ +static inline float vmathV3Length_V( VmathVector3 vec ); + +/* + * Normalize a 3-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline VmathVector3 vmathV3Normalize_V( VmathVector3 vec ); + +/* + * Compute cross product of two 3-D vectors + */ +static inline VmathVector3 vmathV3Cross_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Outer product of two 3-D vectors + */ +static inline VmathMatrix3 vmathV3Outer_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Pre-multiply a row vector by a 3x3 matrix + * NOTE: + * Slower than column post-multiply. + */ +static inline VmathVector3 vmathV3RowMul_V( VmathVector3 vec, VmathMatrix3 mat ); + +/* + * Cross-product matrix of a 3-D vector + */ +static inline VmathMatrix3 vmathV3CrossMatrix_V( VmathVector3 vec ); + +/* + * Create cross-product matrix and multiply + * NOTE: + * Faster than separately creating a cross-product matrix and multiplying. + */ +static inline VmathMatrix3 vmathV3CrossMatrixMul_V( VmathVector3 vec, VmathMatrix3 mat ); + +/* + * Linear interpolation between two 3-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathVector3 vmathV3Lerp_V( float t, VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Spherical linear interpolation between two 3-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline VmathVector3 vmathV3Slerp_V( float t, VmathVector3 unitVec0, VmathVector3 unitVec1 ); + +/* + * Conditionally select between two 3-D vectors + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + * However, the transfer of select1 to a VMX register may use more processing time than a branch. + */ +static inline VmathVector3 vmathV3Select_V( VmathVector3 vec0, VmathVector3 vec1, unsigned int select1 ); + +/* + * Store x, y, and z elements of a 3-D vector in the first three words of a quadword. + * The value of the fourth word (the word with the highest address) remains unchanged + */ +static inline void vmathV3StoreXYZ_V( VmathVector3 vec, vec_float4 *quad ); + +/* + * Load four three-float 3-D vectors, stored in three quadwords + */ +static inline void vmathV3LoadXYZArray_V( VmathVector3 *vec0, VmathVector3 *vec1, VmathVector3 *vec2, VmathVector3 *vec3, const vec_float4 *threeQuads ); + +/* + * Store four 3-D vectors in three quadwords + */ +static inline void vmathV3StoreXYZArray_V( VmathVector3 vec0, VmathVector3 vec1, VmathVector3 vec2, VmathVector3 vec3, vec_float4 *threeQuads ); + +/* + * Store eight 3-D vectors as half-floats + */ +static inline void vmathV3StoreHalfFloats_V( VmathVector3 vec0, VmathVector3 vec1, VmathVector3 vec2, VmathVector3 vec3, VmathVector3 vec4, VmathVector3 vec5, VmathVector3 vec6, VmathVector3 vec7, vec_ushort8 *threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV3Print_V( VmathVector3 vec ); + +/* + * Print a 3-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV3Prints_V( VmathVector3 vec, const char *name ); + +#endif + +/* + * Construct a 4-D vector from x, y, z, and w elements + */ +static inline VmathVector4 vmathV4MakeFromElems_V( float x, float y, float z, float w ); + +/* + * Construct a 4-D vector from a 3-D vector and a scalar + */ +static inline VmathVector4 vmathV4MakeFromV3Scalar_V( VmathVector3 xyz, float w ); + +/* + * Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + */ +static inline VmathVector4 vmathV4MakeFromV3_V( VmathVector3 vec ); + +/* + * Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + */ +static inline VmathVector4 vmathV4MakeFromP3_V( VmathPoint3 pnt ); + +/* + * Copy elements from a quaternion into a 4-D vector + */ +static inline VmathVector4 vmathV4MakeFromQ_V( VmathQuat quat ); + +/* + * Set all elements of a 4-D vector to the same scalar value + */ +static inline VmathVector4 vmathV4MakeFromScalar_V( float scalar ); + +/* + * Set vector float data in a 4-D vector + */ +static inline VmathVector4 vmathV4MakeFrom128_V( vec_float4 vf4 ); + +/* + * Get vector float data from a 4-D vector + */ +static inline vec_float4 vmathV4Get128_V( VmathVector4 vec ); + +/* + * Set the x, y, and z elements of a 4-D vector + * NOTE: + * This function does not change the w element. + */ +static inline void vmathV4SetXYZ_V( VmathVector4 *result, VmathVector3 vec ); + +/* + * Get the x, y, and z elements of a 4-D vector + */ +static inline VmathVector3 vmathV4GetXYZ_V( VmathVector4 vec ); + +/* + * Set the x element of a 4-D vector + */ +static inline void vmathV4SetX_V( VmathVector4 *result, float x ); + +/* + * Set the y element of a 4-D vector + */ +static inline void vmathV4SetY_V( VmathVector4 *result, float y ); + +/* + * Set the z element of a 4-D vector + */ +static inline void vmathV4SetZ_V( VmathVector4 *result, float z ); + +/* + * Set the w element of a 4-D vector + */ +static inline void vmathV4SetW_V( VmathVector4 *result, float w ); + +/* + * Get the x element of a 4-D vector + */ +static inline float vmathV4GetX_V( VmathVector4 vec ); + +/* + * Get the y element of a 4-D vector + */ +static inline float vmathV4GetY_V( VmathVector4 vec ); + +/* + * Get the z element of a 4-D vector + */ +static inline float vmathV4GetZ_V( VmathVector4 vec ); + +/* + * Get the w element of a 4-D vector + */ +static inline float vmathV4GetW_V( VmathVector4 vec ); + +/* + * Set an x, y, z, or w element of a 4-D vector by index + */ +static inline void vmathV4SetElem_V( VmathVector4 *result, int idx, float value ); + +/* + * Get an x, y, z, or w element of a 4-D vector by index + */ +static inline float vmathV4GetElem_V( VmathVector4 vec, int idx ); + +/* + * Add two 4-D vectors + */ +static inline VmathVector4 vmathV4Add_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Subtract a 4-D vector from another 4-D vector + */ +static inline VmathVector4 vmathV4Sub_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Multiply a 4-D vector by a scalar + */ +static inline VmathVector4 vmathV4ScalarMul_V( VmathVector4 vec, float scalar ); + +/* + * Divide a 4-D vector by a scalar + */ +static inline VmathVector4 vmathV4ScalarDiv_V( VmathVector4 vec, float scalar ); + +/* + * Negate all elements of a 4-D vector + */ +static inline VmathVector4 vmathV4Neg_V( VmathVector4 vec ); + +/* + * Construct x axis + */ +static inline VmathVector4 vmathV4MakeXAxis_V( ); + +/* + * Construct y axis + */ +static inline VmathVector4 vmathV4MakeYAxis_V( ); + +/* + * Construct z axis + */ +static inline VmathVector4 vmathV4MakeZAxis_V( ); + +/* + * Construct w axis + */ +static inline VmathVector4 vmathV4MakeWAxis_V( ); + +/* + * Multiply two 4-D vectors per element + */ +static inline VmathVector4 vmathV4MulPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Divide two 4-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline VmathVector4 vmathV4DivPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Compute the reciprocal of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline VmathVector4 vmathV4RecipPerElem_V( VmathVector4 vec ); + +/* + * Compute the square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline VmathVector4 vmathV4SqrtPerElem_V( VmathVector4 vec ); + +/* + * Compute the reciprocal square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline VmathVector4 vmathV4RsqrtPerElem_V( VmathVector4 vec ); + +/* + * Compute the absolute value of a 4-D vector per element + */ +static inline VmathVector4 vmathV4AbsPerElem_V( VmathVector4 vec ); + +/* + * Copy sign from one 4-D vector to another, per element + */ +static inline VmathVector4 vmathV4CopySignPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Maximum of two 4-D vectors per element + */ +static inline VmathVector4 vmathV4MaxPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Minimum of two 4-D vectors per element + */ +static inline VmathVector4 vmathV4MinPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Maximum element of a 4-D vector + */ +static inline float vmathV4MaxElem_V( VmathVector4 vec ); + +/* + * Minimum element of a 4-D vector + */ +static inline float vmathV4MinElem_V( VmathVector4 vec ); + +/* + * Compute the sum of all elements of a 4-D vector + */ +static inline float vmathV4Sum_V( VmathVector4 vec ); + +/* + * Compute the dot product of two 4-D vectors + */ +static inline float vmathV4Dot_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Compute the square of the length of a 4-D vector + */ +static inline float vmathV4LengthSqr_V( VmathVector4 vec ); + +/* + * Compute the length of a 4-D vector + */ +static inline float vmathV4Length_V( VmathVector4 vec ); + +/* + * Normalize a 4-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline VmathVector4 vmathV4Normalize_V( VmathVector4 vec ); + +/* + * Outer product of two 4-D vectors + */ +static inline VmathMatrix4 vmathV4Outer_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Linear interpolation between two 4-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathVector4 vmathV4Lerp_V( float t, VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Spherical linear interpolation between two 4-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline VmathVector4 vmathV4Slerp_V( float t, VmathVector4 unitVec0, VmathVector4 unitVec1 ); + +/* + * Conditionally select between two 4-D vectors + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + * However, the transfer of select1 to a VMX register may use more processing time than a branch. + */ +static inline VmathVector4 vmathV4Select_V( VmathVector4 vec0, VmathVector4 vec1, unsigned int select1 ); + +/* + * Store four 4-D vectors as half-floats + */ +static inline void vmathV4StoreHalfFloats_V( VmathVector4 vec0, VmathVector4 vec1, VmathVector4 vec2, VmathVector4 vec3, vec_ushort8 *twoQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV4Print_V( VmathVector4 vec ); + +/* + * Print a 4-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV4Prints_V( VmathVector4 vec, const char *name ); + +#endif + +/* + * Construct a 3-D point from x, y, and z elements + */ +static inline VmathPoint3 vmathP3MakeFromElems_V( float x, float y, float z ); + +/* + * Copy elements from a 3-D vector into a 3-D point + */ +static inline VmathPoint3 vmathP3MakeFromV3_V( VmathVector3 vec ); + +/* + * Set all elements of a 3-D point to the same scalar value + */ +static inline VmathPoint3 vmathP3MakeFromScalar_V( float scalar ); + +/* + * Set vector float data in a 3-D point + */ +static inline VmathPoint3 vmathP3MakeFrom128_V( vec_float4 vf4 ); + +/* + * Get vector float data from a 3-D point + */ +static inline vec_float4 vmathP3Get128_V( VmathPoint3 pnt ); + +/* + * Set the x element of a 3-D point + */ +static inline void vmathP3SetX_V( VmathPoint3 *result, float x ); + +/* + * Set the y element of a 3-D point + */ +static inline void vmathP3SetY_V( VmathPoint3 *result, float y ); + +/* + * Set the z element of a 3-D point + */ +static inline void vmathP3SetZ_V( VmathPoint3 *result, float z ); + +/* + * Get the x element of a 3-D point + */ +static inline float vmathP3GetX_V( VmathPoint3 pnt ); + +/* + * Get the y element of a 3-D point + */ +static inline float vmathP3GetY_V( VmathPoint3 pnt ); + +/* + * Get the z element of a 3-D point + */ +static inline float vmathP3GetZ_V( VmathPoint3 pnt ); + +/* + * Set an x, y, or z element of a 3-D point by index + */ +static inline void vmathP3SetElem_V( VmathPoint3 *result, int idx, float value ); + +/* + * Get an x, y, or z element of a 3-D point by index + */ +static inline float vmathP3GetElem_V( VmathPoint3 pnt, int idx ); + +/* + * Subtract a 3-D point from another 3-D point + */ +static inline VmathVector3 vmathP3Sub_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Add a 3-D point to a 3-D vector + */ +static inline VmathPoint3 vmathP3AddV3_V( VmathPoint3 pnt, VmathVector3 vec ); + +/* + * Subtract a 3-D vector from a 3-D point + */ +static inline VmathPoint3 vmathP3SubV3_V( VmathPoint3 pnt, VmathVector3 vec ); + +/* + * Multiply two 3-D points per element + */ +static inline VmathPoint3 vmathP3MulPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Divide two 3-D points per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline VmathPoint3 vmathP3DivPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Compute the reciprocal of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline VmathPoint3 vmathP3RecipPerElem_V( VmathPoint3 pnt ); + +/* + * Compute the square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline VmathPoint3 vmathP3SqrtPerElem_V( VmathPoint3 pnt ); + +/* + * Compute the reciprocal square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline VmathPoint3 vmathP3RsqrtPerElem_V( VmathPoint3 pnt ); + +/* + * Compute the absolute value of a 3-D point per element + */ +static inline VmathPoint3 vmathP3AbsPerElem_V( VmathPoint3 pnt ); + +/* + * Copy sign from one 3-D point to another, per element + */ +static inline VmathPoint3 vmathP3CopySignPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Maximum of two 3-D points per element + */ +static inline VmathPoint3 vmathP3MaxPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Minimum of two 3-D points per element + */ +static inline VmathPoint3 vmathP3MinPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Maximum element of a 3-D point + */ +static inline float vmathP3MaxElem_V( VmathPoint3 pnt ); + +/* + * Minimum element of a 3-D point + */ +static inline float vmathP3MinElem_V( VmathPoint3 pnt ); + +/* + * Compute the sum of all elements of a 3-D point + */ +static inline float vmathP3Sum_V( VmathPoint3 pnt ); + +/* + * Apply uniform scale to a 3-D point + */ +static inline VmathPoint3 vmathP3Scale_V( VmathPoint3 pnt, float scaleVal ); + +/* + * Apply non-uniform scale to a 3-D point + */ +static inline VmathPoint3 vmathP3NonUniformScale_V( VmathPoint3 pnt, VmathVector3 scaleVec ); + +/* + * Scalar projection of a 3-D point on a unit-length 3-D vector + */ +static inline float vmathP3Projection_V( VmathPoint3 pnt, VmathVector3 unitVec ); + +/* + * Compute the square of the distance of a 3-D point from the coordinate-system origin + */ +static inline float vmathP3DistSqrFromOrigin_V( VmathPoint3 pnt ); + +/* + * Compute the distance of a 3-D point from the coordinate-system origin + */ +static inline float vmathP3DistFromOrigin_V( VmathPoint3 pnt ); + +/* + * Compute the square of the distance between two 3-D points + */ +static inline float vmathP3DistSqr_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Compute the distance between two 3-D points + */ +static inline float vmathP3Dist_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Linear interpolation between two 3-D points + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathPoint3 vmathP3Lerp_V( float t, VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Conditionally select between two 3-D points + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + * However, the transfer of select1 to a VMX register may use more processing time than a branch. + */ +static inline VmathPoint3 vmathP3Select_V( VmathPoint3 pnt0, VmathPoint3 pnt1, unsigned int select1 ); + +/* + * Store x, y, and z elements of a 3-D point in the first three words of a quadword. + * The value of the fourth word (the word with the highest address) remains unchanged + */ +static inline void vmathP3StoreXYZ_V( VmathPoint3 pnt, vec_float4 *quad ); + +/* + * Load four three-float 3-D points, stored in three quadwords + */ +static inline void vmathP3LoadXYZArray_V( VmathPoint3 *pnt0, VmathPoint3 *pnt1, VmathPoint3 *pnt2, VmathPoint3 *pnt3, const vec_float4 *threeQuads ); + +/* + * Store four 3-D points in three quadwords + */ +static inline void vmathP3StoreXYZArray_V( VmathPoint3 pnt0, VmathPoint3 pnt1, VmathPoint3 pnt2, VmathPoint3 pnt3, vec_float4 *threeQuads ); + +/* + * Store eight 3-D points as half-floats + */ +static inline void vmathP3StoreHalfFloats_V( VmathPoint3 pnt0, VmathPoint3 pnt1, VmathPoint3 pnt2, VmathPoint3 pnt3, VmathPoint3 pnt4, VmathPoint3 pnt5, VmathPoint3 pnt6, VmathPoint3 pnt7, vec_ushort8 *threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D point + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathP3Print_V( VmathPoint3 pnt ); + +/* + * Print a 3-D point and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathP3Prints_V( VmathPoint3 pnt, const char *name ); + +#endif + +/* + * Construct a quaternion from x, y, z, and w elements + */ +static inline VmathQuat vmathQMakeFromElems_V( float x, float y, float z, float w ); + +/* + * Construct a quaternion from a 3-D vector and a scalar + */ +static inline VmathQuat vmathQMakeFromV3Scalar_V( VmathVector3 xyz, float w ); + +/* + * Copy elements from a 4-D vector into a quaternion + */ +static inline VmathQuat vmathQMakeFromV4_V( VmathVector4 vec ); + +/* + * Convert a rotation matrix to a unit-length quaternion + */ +static inline VmathQuat vmathQMakeFromM3_V( VmathMatrix3 rotMat ); + +/* + * Set all elements of a quaternion to the same scalar value + */ +static inline VmathQuat vmathQMakeFromScalar_V( float scalar ); + +/* + * Set vector float data in a quaternion + */ +static inline VmathQuat vmathQMakeFrom128_V( vec_float4 vf4 ); + +/* + * Get vector float data from a quaternion + */ +static inline vec_float4 vmathQGet128_V( VmathQuat quat ); + +/* + * Set the x, y, and z elements of a quaternion + * NOTE: + * This function does not change the w element. + */ +static inline void vmathQSetXYZ_V( VmathQuat *result, VmathVector3 vec ); + +/* + * Get the x, y, and z elements of a quaternion + */ +static inline VmathVector3 vmathQGetXYZ_V( VmathQuat quat ); + +/* + * Set the x element of a quaternion + */ +static inline void vmathQSetX_V( VmathQuat *result, float x ); + +/* + * Set the y element of a quaternion + */ +static inline void vmathQSetY_V( VmathQuat *result, float y ); + +/* + * Set the z element of a quaternion + */ +static inline void vmathQSetZ_V( VmathQuat *result, float z ); + +/* + * Set the w element of a quaternion + */ +static inline void vmathQSetW_V( VmathQuat *result, float w ); + +/* + * Get the x element of a quaternion + */ +static inline float vmathQGetX_V( VmathQuat quat ); + +/* + * Get the y element of a quaternion + */ +static inline float vmathQGetY_V( VmathQuat quat ); + +/* + * Get the z element of a quaternion + */ +static inline float vmathQGetZ_V( VmathQuat quat ); + +/* + * Get the w element of a quaternion + */ +static inline float vmathQGetW_V( VmathQuat quat ); + +/* + * Set an x, y, z, or w element of a quaternion by index + */ +static inline void vmathQSetElem_V( VmathQuat *result, int idx, float value ); + +/* + * Get an x, y, z, or w element of a quaternion by index + */ +static inline float vmathQGetElem_V( VmathQuat quat, int idx ); + +/* + * Add two quaternions + */ +static inline VmathQuat vmathQAdd_V( VmathQuat quat0, VmathQuat quat1 ); + +/* + * Subtract a quaternion from another quaternion + */ +static inline VmathQuat vmathQSub_V( VmathQuat quat0, VmathQuat quat1 ); + +/* + * Multiply two quaternions + */ +static inline VmathQuat vmathQMul_V( VmathQuat quat0, VmathQuat quat1 ); + +/* + * Multiply a quaternion by a scalar + */ +static inline VmathQuat vmathQScalarMul_V( VmathQuat quat, float scalar ); + +/* + * Divide a quaternion by a scalar + */ +static inline VmathQuat vmathQScalarDiv_V( VmathQuat quat, float scalar ); + +/* + * Negate all elements of a quaternion + */ +static inline VmathQuat vmathQNeg_V( VmathQuat quat ); + +/* + * Construct an identity quaternion + */ +static inline VmathQuat vmathQMakeIdentity_V( ); + +/* + * Construct a quaternion to rotate between two unit-length 3-D vectors + * NOTE: + * The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + */ +static inline VmathQuat vmathQMakeRotationArc_V( VmathVector3 unitVec0, VmathVector3 unitVec1 ); + +/* + * Construct a quaternion to rotate around a unit-length 3-D vector + */ +static inline VmathQuat vmathQMakeRotationAxis_V( float radians, VmathVector3 unitVec ); + +/* + * Construct a quaternion to rotate around the x axis + */ +static inline VmathQuat vmathQMakeRotationX_V( float radians ); + +/* + * Construct a quaternion to rotate around the y axis + */ +static inline VmathQuat vmathQMakeRotationY_V( float radians ); + +/* + * Construct a quaternion to rotate around the z axis + */ +static inline VmathQuat vmathQMakeRotationZ_V( float radians ); + +/* + * Compute the conjugate of a quaternion + */ +static inline VmathQuat vmathQConj_V( VmathQuat quat ); + +/* + * Use a unit-length quaternion to rotate a 3-D vector + */ +static inline VmathVector3 vmathQRotate_V( VmathQuat unitQuat, VmathVector3 vec ); + +/* + * Compute the dot product of two quaternions + */ +static inline float vmathQDot_V( VmathQuat quat0, VmathQuat quat1 ); + +/* + * Compute the norm of a quaternion + */ +static inline float vmathQNorm_V( VmathQuat quat ); + +/* + * Compute the length of a quaternion + */ +static inline float vmathQLength_V( VmathQuat quat ); + +/* + * Normalize a quaternion + * NOTE: + * The result is unpredictable when all elements of quat are at or near zero. + */ +static inline VmathQuat vmathQNormalize_V( VmathQuat quat ); + +/* + * Linear interpolation between two quaternions + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathQuat vmathQLerp_V( float t, VmathQuat quat0, VmathQuat quat1 ); + +/* + * Spherical linear interpolation between two quaternions + * NOTE: + * Interpolates along the shortest path between orientations. + * Does not clamp t between 0 and 1. + */ +static inline VmathQuat vmathQSlerp_V( float t, VmathQuat unitQuat0, VmathQuat unitQuat1 ); + +/* + * Spherical quadrangle interpolation + */ +static inline VmathQuat vmathQSquad_V( float t, VmathQuat unitQuat0, VmathQuat unitQuat1, VmathQuat unitQuat2, VmathQuat unitQuat3 ); + +/* + * Conditionally select between two quaternions + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + * However, the transfer of select1 to a VMX register may use more processing time than a branch. + */ +static inline VmathQuat vmathQSelect_V( VmathQuat quat0, VmathQuat quat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a quaternion + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathQPrint_V( VmathQuat quat ); + +/* + * Print a quaternion and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathQPrints_V( VmathQuat quat, const char *name ); + +#endif + +/* + * Construct a 3x3 matrix containing the specified columns + */ +static inline VmathMatrix3 vmathM3MakeFromCols_V( VmathVector3 col0, VmathVector3 col1, VmathVector3 col2 ); + +/* + * Construct a 3x3 rotation matrix from a unit-length quaternion + */ +static inline VmathMatrix3 vmathM3MakeFromQ_V( VmathQuat unitQuat ); + +/* + * Set all elements of a 3x3 matrix to the same scalar value + */ +static inline VmathMatrix3 vmathM3MakeFromScalar_V( float scalar ); + +/* + * Set column 0 of a 3x3 matrix + */ +static inline void vmathM3SetCol0_V( VmathMatrix3 *result, VmathVector3 col0 ); + +/* + * Set column 1 of a 3x3 matrix + */ +static inline void vmathM3SetCol1_V( VmathMatrix3 *result, VmathVector3 col1 ); + +/* + * Set column 2 of a 3x3 matrix + */ +static inline void vmathM3SetCol2_V( VmathMatrix3 *result, VmathVector3 col2 ); + +/* + * Get column 0 of a 3x3 matrix + */ +static inline VmathVector3 vmathM3GetCol0_V( VmathMatrix3 mat ); + +/* + * Get column 1 of a 3x3 matrix + */ +static inline VmathVector3 vmathM3GetCol1_V( VmathMatrix3 mat ); + +/* + * Get column 2 of a 3x3 matrix + */ +static inline VmathVector3 vmathM3GetCol2_V( VmathMatrix3 mat ); + +/* + * Set the column of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3SetCol_V( VmathMatrix3 *result, int col, VmathVector3 vec ); + +/* + * Set the row of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3SetRow_V( VmathMatrix3 *result, int row, VmathVector3 vec ); + +/* + * Get the column of a 3x3 matrix referred to by the specified index + */ +static inline VmathVector3 vmathM3GetCol_V( VmathMatrix3 mat, int col ); + +/* + * Get the row of a 3x3 matrix referred to by the specified index + */ +static inline VmathVector3 vmathM3GetRow_V( VmathMatrix3 mat, int row ); + +/* + * Set the element of a 3x3 matrix referred to by column and row indices + */ +static inline void vmathM3SetElem_V( VmathMatrix3 *result, int col, int row, float val ); + +/* + * Get the element of a 3x3 matrix referred to by column and row indices + */ +static inline float vmathM3GetElem_V( VmathMatrix3 mat, int col, int row ); + +/* + * Add two 3x3 matrices + */ +static inline VmathMatrix3 vmathM3Add_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ); + +/* + * Subtract a 3x3 matrix from another 3x3 matrix + */ +static inline VmathMatrix3 vmathM3Sub_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ); + +/* + * Negate all elements of a 3x3 matrix + */ +static inline VmathMatrix3 vmathM3Neg_V( VmathMatrix3 mat ); + +/* + * Multiply a 3x3 matrix by a scalar + */ +static inline VmathMatrix3 vmathM3ScalarMul_V( VmathMatrix3 mat, float scalar ); + +/* + * Multiply a 3x3 matrix by a 3-D vector + */ +static inline VmathVector3 vmathM3MulV3_V( VmathMatrix3 mat, VmathVector3 vec ); + +/* + * Multiply two 3x3 matrices + */ +static inline VmathMatrix3 vmathM3Mul_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ); + +/* + * Construct an identity 3x3 matrix + */ +static inline VmathMatrix3 vmathM3MakeIdentity_V( ); + +/* + * Construct a 3x3 matrix to rotate around the x axis + */ +static inline VmathMatrix3 vmathM3MakeRotationX_V( float radians ); + +/* + * Construct a 3x3 matrix to rotate around the y axis + */ +static inline VmathMatrix3 vmathM3MakeRotationY_V( float radians ); + +/* + * Construct a 3x3 matrix to rotate around the z axis + */ +static inline VmathMatrix3 vmathM3MakeRotationZ_V( float radians ); + +/* + * Construct a 3x3 matrix to rotate around the x, y, and z axes + */ +static inline VmathMatrix3 vmathM3MakeRotationZYX_V( VmathVector3 radiansXYZ ); + +/* + * Construct a 3x3 matrix to rotate around a unit-length 3-D vector + */ +static inline VmathMatrix3 vmathM3MakeRotationAxis_V( float radians, VmathVector3 unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline VmathMatrix3 vmathM3MakeRotationQ_V( VmathQuat unitQuat ); + +/* + * Construct a 3x3 matrix to perform scaling + */ +static inline VmathMatrix3 vmathM3MakeScale_V( VmathVector3 scaleVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathMatrix3 vmathM3AppendScale_V( VmathMatrix3 mat, VmathVector3 scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathMatrix3 vmathM3PrependScale_V( VmathVector3 scaleVec, VmathMatrix3 mat ); + +/* + * Multiply two 3x3 matrices per element + */ +static inline VmathMatrix3 vmathM3MulPerElem_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ); + +/* + * Compute the absolute value of a 3x3 matrix per element + */ +static inline VmathMatrix3 vmathM3AbsPerElem_V( VmathMatrix3 mat ); + +/* + * Transpose of a 3x3 matrix + */ +static inline VmathMatrix3 vmathM3Transpose_V( VmathMatrix3 mat ); + +/* + * Compute the inverse of a 3x3 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline VmathMatrix3 vmathM3Inverse_V( VmathMatrix3 mat ); + +/* + * Determinant of a 3x3 matrix + */ +static inline float vmathM3Determinant_V( VmathMatrix3 mat ); + +/* + * Conditionally select between two 3x3 matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + * However, the transfer of select1 to a VMX register may use more processing time than a branch. + */ +static inline VmathMatrix3 vmathM3Select_V( VmathMatrix3 mat0, VmathMatrix3 mat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x3 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM3Print_V( VmathMatrix3 mat ); + +/* + * Print a 3x3 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM3Prints_V( VmathMatrix3 mat, const char *name ); + +#endif + +/* + * Construct a 4x4 matrix containing the specified columns + */ +static inline VmathMatrix4 vmathM4MakeFromCols_V( VmathVector4 col0, VmathVector4 col1, VmathVector4 col2, VmathVector4 col3 ); + +/* + * Construct a 4x4 matrix from a 3x4 transformation matrix + */ +static inline VmathMatrix4 vmathM4MakeFromT3_V( VmathTransform3 mat ); + +/* + * Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + */ +static inline VmathMatrix4 vmathM4MakeFromM3V3_V( VmathMatrix3 mat, VmathVector3 translateVec ); + +/* + * Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + */ +static inline VmathMatrix4 vmathM4MakeFromQV3_V( VmathQuat unitQuat, VmathVector3 translateVec ); + +/* + * Set all elements of a 4x4 matrix to the same scalar value + */ +static inline VmathMatrix4 vmathM4MakeFromScalar_V( float scalar ); + +/* + * Set the upper-left 3x3 submatrix + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathM4SetUpper3x3_V( VmathMatrix4 *result, VmathMatrix3 mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 4x4 matrix + */ +static inline VmathMatrix3 vmathM4GetUpper3x3_V( VmathMatrix4 mat ); + +/* + * Set translation component + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathM4SetTranslation_V( VmathMatrix4 *result, VmathVector3 translateVec ); + +/* + * Get the translation component of a 4x4 matrix + */ +static inline VmathVector3 vmathM4GetTranslation_V( VmathMatrix4 mat ); + +/* + * Set column 0 of a 4x4 matrix + */ +static inline void vmathM4SetCol0_V( VmathMatrix4 *result, VmathVector4 col0 ); + +/* + * Set column 1 of a 4x4 matrix + */ +static inline void vmathM4SetCol1_V( VmathMatrix4 *result, VmathVector4 col1 ); + +/* + * Set column 2 of a 4x4 matrix + */ +static inline void vmathM4SetCol2_V( VmathMatrix4 *result, VmathVector4 col2 ); + +/* + * Set column 3 of a 4x4 matrix + */ +static inline void vmathM4SetCol3_V( VmathMatrix4 *result, VmathVector4 col3 ); + +/* + * Get column 0 of a 4x4 matrix + */ +static inline VmathVector4 vmathM4GetCol0_V( VmathMatrix4 mat ); + +/* + * Get column 1 of a 4x4 matrix + */ +static inline VmathVector4 vmathM4GetCol1_V( VmathMatrix4 mat ); + +/* + * Get column 2 of a 4x4 matrix + */ +static inline VmathVector4 vmathM4GetCol2_V( VmathMatrix4 mat ); + +/* + * Get column 3 of a 4x4 matrix + */ +static inline VmathVector4 vmathM4GetCol3_V( VmathMatrix4 mat ); + +/* + * Set the column of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4SetCol_V( VmathMatrix4 *result, int col, VmathVector4 vec ); + +/* + * Set the row of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4SetRow_V( VmathMatrix4 *result, int row, VmathVector4 vec ); + +/* + * Get the column of a 4x4 matrix referred to by the specified index + */ +static inline VmathVector4 vmathM4GetCol_V( VmathMatrix4 mat, int col ); + +/* + * Get the row of a 4x4 matrix referred to by the specified index + */ +static inline VmathVector4 vmathM4GetRow_V( VmathMatrix4 mat, int row ); + +/* + * Set the element of a 4x4 matrix referred to by column and row indices + */ +static inline void vmathM4SetElem_V( VmathMatrix4 *result, int col, int row, float val ); + +/* + * Get the element of a 4x4 matrix referred to by column and row indices + */ +static inline float vmathM4GetElem_V( VmathMatrix4 mat, int col, int row ); + +/* + * Add two 4x4 matrices + */ +static inline VmathMatrix4 vmathM4Add_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ); + +/* + * Subtract a 4x4 matrix from another 4x4 matrix + */ +static inline VmathMatrix4 vmathM4Sub_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ); + +/* + * Negate all elements of a 4x4 matrix + */ +static inline VmathMatrix4 vmathM4Neg_V( VmathMatrix4 mat ); + +/* + * Multiply a 4x4 matrix by a scalar + */ +static inline VmathMatrix4 vmathM4ScalarMul_V( VmathMatrix4 mat, float scalar ); + +/* + * Multiply a 4x4 matrix by a 4-D vector + */ +static inline VmathVector4 vmathM4MulV4_V( VmathMatrix4 mat, VmathVector4 vec ); + +/* + * Multiply a 4x4 matrix by a 3-D vector + */ +static inline VmathVector4 vmathM4MulV3_V( VmathMatrix4 mat, VmathVector3 vec ); + +/* + * Multiply a 4x4 matrix by a 3-D point + */ +static inline VmathVector4 vmathM4MulP3_V( VmathMatrix4 mat, VmathPoint3 pnt ); + +/* + * Multiply two 4x4 matrices + */ +static inline VmathMatrix4 vmathM4Mul_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ); + +/* + * Multiply a 4x4 matrix by a 3x4 transformation matrix + */ +static inline VmathMatrix4 vmathM4MulT3_V( VmathMatrix4 mat, VmathTransform3 tfrm ); + +/* + * Construct an identity 4x4 matrix + */ +static inline VmathMatrix4 vmathM4MakeIdentity_V( ); + +/* + * Construct a 4x4 matrix to rotate around the x axis + */ +static inline VmathMatrix4 vmathM4MakeRotationX_V( float radians ); + +/* + * Construct a 4x4 matrix to rotate around the y axis + */ +static inline VmathMatrix4 vmathM4MakeRotationY_V( float radians ); + +/* + * Construct a 4x4 matrix to rotate around the z axis + */ +static inline VmathMatrix4 vmathM4MakeRotationZ_V( float radians ); + +/* + * Construct a 4x4 matrix to rotate around the x, y, and z axes + */ +static inline VmathMatrix4 vmathM4MakeRotationZYX_V( VmathVector3 radiansXYZ ); + +/* + * Construct a 4x4 matrix to rotate around a unit-length 3-D vector + */ +static inline VmathMatrix4 vmathM4MakeRotationAxis_V( float radians, VmathVector3 unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline VmathMatrix4 vmathM4MakeRotationQ_V( VmathQuat unitQuat ); + +/* + * Construct a 4x4 matrix to perform scaling + */ +static inline VmathMatrix4 vmathM4MakeScale_V( VmathVector3 scaleVec ); + +/* + * Construct a 4x4 matrix to perform translation + */ +static inline VmathMatrix4 vmathM4MakeTranslation_V( VmathVector3 translateVec ); + +/* + * Construct viewing matrix based on eye position, position looked at, and up direction + */ +static inline VmathMatrix4 vmathM4MakeLookAt_V( VmathPoint3 eyePos, VmathPoint3 lookAtPos, VmathVector3 upVec ); + +/* + * Construct a perspective projection matrix + */ +static inline VmathMatrix4 vmathM4MakePerspective_V( float fovyRadians, float aspect, float zNear, float zFar ); + +/* + * Construct a perspective projection matrix based on frustum + */ +static inline VmathMatrix4 vmathM4MakeFrustum_V( float left, float right, float bottom, float top, float zNear, float zFar ); + +/* + * Construct an orthographic projection matrix + */ +static inline VmathMatrix4 vmathM4MakeOrthographic_V( float left, float right, float bottom, float top, float zNear, float zFar ); + +/* + * Append (post-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathMatrix4 vmathM4AppendScale_V( VmathMatrix4 mat, VmathVector3 scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathMatrix4 vmathM4PrependScale_V( VmathVector3 scaleVec, VmathMatrix4 mat ); + +/* + * Multiply two 4x4 matrices per element + */ +static inline VmathMatrix4 vmathM4MulPerElem_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ); + +/* + * Compute the absolute value of a 4x4 matrix per element + */ +static inline VmathMatrix4 vmathM4AbsPerElem_V( VmathMatrix4 mat ); + +/* + * Transpose of a 4x4 matrix + */ +static inline VmathMatrix4 vmathM4Transpose_V( VmathMatrix4 mat ); + +/* + * Compute the inverse of a 4x4 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline VmathMatrix4 vmathM4Inverse_V( VmathMatrix4 mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline VmathMatrix4 vmathM4AffineInverse_V( VmathMatrix4 mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. + */ +static inline VmathMatrix4 vmathM4OrthoInverse_V( VmathMatrix4 mat ); + +/* + * Determinant of a 4x4 matrix + */ +static inline float vmathM4Determinant_V( VmathMatrix4 mat ); + +/* + * Conditionally select between two 4x4 matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + * However, the transfer of select1 to a VMX register may use more processing time than a branch. + */ +static inline VmathMatrix4 vmathM4Select_V( VmathMatrix4 mat0, VmathMatrix4 mat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4x4 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM4Print_V( VmathMatrix4 mat ); + +/* + * Print a 4x4 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM4Prints_V( VmathMatrix4 mat, const char *name ); + +#endif + +/* + * Construct a 3x4 transformation matrix containing the specified columns + */ +static inline VmathTransform3 vmathT3MakeFromCols_V( VmathVector3 col0, VmathVector3 col1, VmathVector3 col2, VmathVector3 col3 ); + +/* + * Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + */ +static inline VmathTransform3 vmathT3MakeFromM3V3_V( VmathMatrix3 tfrm, VmathVector3 translateVec ); + +/* + * Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + */ +static inline VmathTransform3 vmathT3MakeFromQV3_V( VmathQuat unitQuat, VmathVector3 translateVec ); + +/* + * Set all elements of a 3x4 transformation matrix to the same scalar value + */ +static inline VmathTransform3 vmathT3MakeFromScalar_V( float scalar ); + +/* + * Set the upper-left 3x3 submatrix + */ +static inline void vmathT3SetUpper3x3_V( VmathTransform3 *result, VmathMatrix3 mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + */ +static inline VmathMatrix3 vmathT3GetUpper3x3_V( VmathTransform3 tfrm ); + +/* + * Set translation component + */ +static inline void vmathT3SetTranslation_V( VmathTransform3 *result, VmathVector3 translateVec ); + +/* + * Get the translation component of a 3x4 transformation matrix + */ +static inline VmathVector3 vmathT3GetTranslation_V( VmathTransform3 tfrm ); + +/* + * Set column 0 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol0_V( VmathTransform3 *result, VmathVector3 col0 ); + +/* + * Set column 1 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol1_V( VmathTransform3 *result, VmathVector3 col1 ); + +/* + * Set column 2 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol2_V( VmathTransform3 *result, VmathVector3 col2 ); + +/* + * Set column 3 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol3_V( VmathTransform3 *result, VmathVector3 col3 ); + +/* + * Get column 0 of a 3x4 transformation matrix + */ +static inline VmathVector3 vmathT3GetCol0_V( VmathTransform3 tfrm ); + +/* + * Get column 1 of a 3x4 transformation matrix + */ +static inline VmathVector3 vmathT3GetCol1_V( VmathTransform3 tfrm ); + +/* + * Get column 2 of a 3x4 transformation matrix + */ +static inline VmathVector3 vmathT3GetCol2_V( VmathTransform3 tfrm ); + +/* + * Get column 3 of a 3x4 transformation matrix + */ +static inline VmathVector3 vmathT3GetCol3_V( VmathTransform3 tfrm ); + +/* + * Set the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3SetCol_V( VmathTransform3 *result, int col, VmathVector3 vec ); + +/* + * Set the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3SetRow_V( VmathTransform3 *result, int row, VmathVector4 vec ); + +/* + * Get the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline VmathVector3 vmathT3GetCol_V( VmathTransform3 tfrm, int col ); + +/* + * Get the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline VmathVector4 vmathT3GetRow_V( VmathTransform3 tfrm, int row ); + +/* + * Set the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline void vmathT3SetElem_V( VmathTransform3 *result, int col, int row, float val ); + +/* + * Get the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline float vmathT3GetElem_V( VmathTransform3 tfrm, int col, int row ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D vector + */ +static inline VmathVector3 vmathT3MulV3_V( VmathTransform3 tfrm, VmathVector3 vec ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D point + */ +static inline VmathPoint3 vmathT3MulP3_V( VmathTransform3 tfrm, VmathPoint3 pnt ); + +/* + * Multiply two 3x4 transformation matrices + */ +static inline VmathTransform3 vmathT3Mul_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1 ); + +/* + * Construct an identity 3x4 transformation matrix + */ +static inline VmathTransform3 vmathT3MakeIdentity_V( ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x axis + */ +static inline VmathTransform3 vmathT3MakeRotationX_V( float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the y axis + */ +static inline VmathTransform3 vmathT3MakeRotationY_V( float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the z axis + */ +static inline VmathTransform3 vmathT3MakeRotationZ_V( float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + */ +static inline VmathTransform3 vmathT3MakeRotationZYX_V( VmathVector3 radiansXYZ ); + +/* + * Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + */ +static inline VmathTransform3 vmathT3MakeRotationAxis_V( float radians, VmathVector3 unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline VmathTransform3 vmathT3MakeRotationQ_V( VmathQuat unitQuat ); + +/* + * Construct a 3x4 transformation matrix to perform scaling + */ +static inline VmathTransform3 vmathT3MakeScale_V( VmathVector3 scaleVec ); + +/* + * Construct a 3x4 transformation matrix to perform translation + */ +static inline VmathTransform3 vmathT3MakeTranslation_V( VmathVector3 translateVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathTransform3 vmathT3AppendScale_V( VmathTransform3 tfrm, VmathVector3 scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathTransform3 vmathT3PrependScale_V( VmathVector3 scaleVec, VmathTransform3 tfrm ); + +/* + * Multiply two 3x4 transformation matrices per element + */ +static inline VmathTransform3 vmathT3MulPerElem_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1 ); + +/* + * Compute the absolute value of a 3x4 transformation matrix per element + */ +static inline VmathTransform3 vmathT3AbsPerElem_V( VmathTransform3 tfrm ); + +/* + * Inverse of a 3x4 transformation matrix + * NOTE: + * Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. + */ +static inline VmathTransform3 vmathT3Inverse_V( VmathTransform3 tfrm ); + +/* + * Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. + */ +static inline VmathTransform3 vmathT3OrthoInverse_V( VmathTransform3 tfrm ); + +/* + * Conditionally select between two 3x4 transformation matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + * However, the transfer of select1 to a VMX register may use more processing time than a branch. + */ +static inline VmathTransform3 vmathT3Select_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x4 transformation matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathT3Print_V( VmathTransform3 tfrm ); + +/* + * Print a 3x4 transformation matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathT3Prints_V( VmathTransform3 tfrm, const char *name ); + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#include "vectormath_aos.h" +#include "vec_aos_v.h" +#include "quat_aos_v.h" +#include "mat_aos_v.h" + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/vectormath_soa.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/vectormath_soa.h new file mode 100644 index 0000000..0188dcb --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/vectormath_soa.h @@ -0,0 +1,2013 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_SOA_C_PPU_H +#define _VECTORMATH_SOA_C_PPU_H + +#include +#include +#include "vectormath_aos.h" + +#ifdef _VECTORMATH_DEBUG +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef _VECTORMATH_SOA_C_TYPES_H +#define _VECTORMATH_SOA_C_TYPES_H + +/* A set of four 3-D vectors in structure-of-arrays format + */ +typedef struct _VmathSoaVector3 +{ + vec_float4 x; + vec_float4 y; + vec_float4 z; +} VmathSoaVector3; + +/* A set of four 4-D vectors in structure-of-arrays format + */ +typedef struct _VmathSoaVector4 +{ + vec_float4 x; + vec_float4 y; + vec_float4 z; + vec_float4 w; +} VmathSoaVector4; + +/* A set of four 3-D points in structure-of-arrays format + */ +typedef struct _VmathSoaPoint3 +{ + vec_float4 x; + vec_float4 y; + vec_float4 z; +} VmathSoaPoint3; + +/* A set of four quaternions in structure-of-arrays format + */ +typedef struct _VmathSoaQuat +{ + vec_float4 x; + vec_float4 y; + vec_float4 z; + vec_float4 w; +} VmathSoaQuat; + +/* A set of four 3x3 matrices in structure-of-arrays format + */ +typedef struct _VmathSoaMatrix3 +{ + VmathSoaVector3 col0; + VmathSoaVector3 col1; + VmathSoaVector3 col2; +} VmathSoaMatrix3; + +/* A set of four 4x4 matrices in structure-of-arrays format + */ +typedef struct _VmathSoaMatrix4 +{ + VmathSoaVector4 col0; + VmathSoaVector4 col1; + VmathSoaVector4 col2; + VmathSoaVector4 col3; +} VmathSoaMatrix4; + +/* A set of four 3x4 transformation matrices in structure-of-arrays format + */ +typedef struct _VmathSoaTransform3 +{ + VmathSoaVector3 col0; + VmathSoaVector3 col1; + VmathSoaVector3 col2; + VmathSoaVector3 col3; +} VmathSoaTransform3; + +#endif + +/* + * Copy a 3-D vector + */ +static inline void vmathSoaV3Copy( VmathSoaVector3 *result, const VmathSoaVector3 *vec ); + +/* + * Construct a 3-D vector from x, y, and z elements + */ +static inline void vmathSoaV3MakeFromElems( VmathSoaVector3 *result, vec_float4 x, vec_float4 y, vec_float4 z ); + +/* + * Copy elements from a 3-D point into a 3-D vector + */ +static inline void vmathSoaV3MakeFromP3( VmathSoaVector3 *result, const VmathSoaPoint3 *pnt ); + +/* + * Set all elements of a 3-D vector to the same scalar value + */ +static inline void vmathSoaV3MakeFromScalar( VmathSoaVector3 *result, vec_float4 scalar ); + +/* + * Replicate an AoS 3-D vector + */ +static inline void vmathSoaV3MakeFromAos( VmathSoaVector3 *result, const VmathVector3 *vec ); + +/* + * Insert four AoS 3-D vectors + */ +static inline void vmathSoaV3MakeFrom4Aos( VmathSoaVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1, const VmathVector3 *vec2, const VmathVector3 *vec3 ); + +/* + * Extract four AoS 3-D vectors + */ +static inline void vmathSoaV3Get4Aos( const VmathSoaVector3 *vec, VmathVector3 *result0, VmathVector3 *result1, VmathVector3 *result2, VmathVector3 *result3 ); + +/* + * Set the x element of a 3-D vector + */ +static inline void vmathSoaV3SetX( VmathSoaVector3 *result, vec_float4 x ); + +/* + * Set the y element of a 3-D vector + */ +static inline void vmathSoaV3SetY( VmathSoaVector3 *result, vec_float4 y ); + +/* + * Set the z element of a 3-D vector + */ +static inline void vmathSoaV3SetZ( VmathSoaVector3 *result, vec_float4 z ); + +/* + * Get the x element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3GetX( const VmathSoaVector3 *vec ); + +/* + * Get the y element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3GetY( const VmathSoaVector3 *vec ); + +/* + * Get the z element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3GetZ( const VmathSoaVector3 *vec ); + +/* + * Set an x, y, or z element of a 3-D vector by index + */ +static inline void vmathSoaV3SetElem( VmathSoaVector3 *result, int idx, vec_float4 value ); + +/* + * Get an x, y, or z element of a 3-D vector by index + */ +static inline vec_float4 vmathSoaV3GetElem( const VmathSoaVector3 *vec, int idx ); + +/* + * Add two 3-D vectors + */ +static inline void vmathSoaV3Add( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Subtract a 3-D vector from another 3-D vector + */ +static inline void vmathSoaV3Sub( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Add a 3-D vector to a 3-D point + */ +static inline void vmathSoaV3AddP3( VmathSoaPoint3 *result, const VmathSoaVector3 *vec, const VmathSoaPoint3 *pnt ); + +/* + * Multiply a 3-D vector by a scalar + */ +static inline void vmathSoaV3ScalarMul( VmathSoaVector3 *result, const VmathSoaVector3 *vec, vec_float4 scalar ); + +/* + * Divide a 3-D vector by a scalar + */ +static inline void vmathSoaV3ScalarDiv( VmathSoaVector3 *result, const VmathSoaVector3 *vec, vec_float4 scalar ); + +/* + * Negate all elements of a 3-D vector + */ +static inline void vmathSoaV3Neg( VmathSoaVector3 *result, const VmathSoaVector3 *vec ); + +/* + * Construct x axis + */ +static inline void vmathSoaV3MakeXAxis( VmathSoaVector3 *result ); + +/* + * Construct y axis + */ +static inline void vmathSoaV3MakeYAxis( VmathSoaVector3 *result ); + +/* + * Construct z axis + */ +static inline void vmathSoaV3MakeZAxis( VmathSoaVector3 *result ); + +/* + * Multiply two 3-D vectors per element + */ +static inline void vmathSoaV3MulPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Divide two 3-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline void vmathSoaV3DivPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Compute the reciprocal of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline void vmathSoaV3RecipPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec ); + +/* + * Compute the square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline void vmathSoaV3SqrtPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec ); + +/* + * Compute the reciprocal square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline void vmathSoaV3RsqrtPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec ); + +/* + * Compute the absolute value of a 3-D vector per element + */ +static inline void vmathSoaV3AbsPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec ); + +/* + * Copy sign from one 3-D vector to another, per element + */ +static inline void vmathSoaV3CopySignPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Maximum of two 3-D vectors per element + */ +static inline void vmathSoaV3MaxPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Minimum of two 3-D vectors per element + */ +static inline void vmathSoaV3MinPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Maximum element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3MaxElem( const VmathSoaVector3 *vec ); + +/* + * Minimum element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3MinElem( const VmathSoaVector3 *vec ); + +/* + * Compute the sum of all elements of a 3-D vector + */ +static inline vec_float4 vmathSoaV3Sum( const VmathSoaVector3 *vec ); + +/* + * Compute the dot product of two 3-D vectors + */ +static inline vec_float4 vmathSoaV3Dot( const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Compute the square of the length of a 3-D vector + */ +static inline vec_float4 vmathSoaV3LengthSqr( const VmathSoaVector3 *vec ); + +/* + * Compute the length of a 3-D vector + */ +static inline vec_float4 vmathSoaV3Length( const VmathSoaVector3 *vec ); + +/* + * Normalize a 3-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline void vmathSoaV3Normalize( VmathSoaVector3 *result, const VmathSoaVector3 *vec ); + +/* + * Compute cross product of two 3-D vectors + */ +static inline void vmathSoaV3Cross( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Outer product of two 3-D vectors + */ +static inline void vmathSoaV3Outer( VmathSoaMatrix3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Pre-multiply a row vector by a 3x3 matrix + */ +static inline void vmathSoaV3RowMul( VmathSoaVector3 *result, const VmathSoaVector3 *vec, const VmathSoaMatrix3 *mat ); + +/* + * Cross-product matrix of a 3-D vector + */ +static inline void vmathSoaV3CrossMatrix( VmathSoaMatrix3 *result, const VmathSoaVector3 *vec ); + +/* + * Create cross-product matrix and multiply + * NOTE: + * Faster than separately creating a cross-product matrix and multiplying. + */ +static inline void vmathSoaV3CrossMatrixMul( VmathSoaMatrix3 *result, const VmathSoaVector3 *vec, const VmathSoaMatrix3 *mat ); + +/* + * Linear interpolation between two 3-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathSoaV3Lerp( VmathSoaVector3 *result, vec_float4 t, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Spherical linear interpolation between two 3-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline void vmathSoaV3Slerp( VmathSoaVector3 *result, vec_float4 t, const VmathSoaVector3 *unitVec0, const VmathSoaVector3 *unitVec1 ); + +/* + * Conditionally select between two 3-D vectors + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathSoaV3Select( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1, vec_uint4 select1 ); + +/* + * Load four three-float 3-D vectors, stored in three quadwords + */ +static inline void vmathSoaV3LoadXYZArray( VmathSoaVector3 *vec, const vec_float4 *threeQuads ); + +/* + * Store four slots of an SoA 3-D vector in three quadwords + */ +static inline void vmathSoaV3StoreXYZArray( const VmathSoaVector3 *vec, vec_float4 *threeQuads ); + +/* + * Store eight slots of two SoA 3-D vectors as half-floats + */ +static inline void vmathSoaV3StoreHalfFloats( const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1, vec_ushort8 *threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaV3Print( const VmathSoaVector3 *vec ); + +/* + * Print a 3-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaV3Prints( const VmathSoaVector3 *vec, const char *name ); + +#endif + +/* + * Copy a 4-D vector + */ +static inline void vmathSoaV4Copy( VmathSoaVector4 *result, const VmathSoaVector4 *vec ); + +/* + * Construct a 4-D vector from x, y, z, and w elements + */ +static inline void vmathSoaV4MakeFromElems( VmathSoaVector4 *result, vec_float4 x, vec_float4 y, vec_float4 z, vec_float4 w ); + +/* + * Construct a 4-D vector from a 3-D vector and a scalar + */ +static inline void vmathSoaV4MakeFromV3Scalar( VmathSoaVector4 *result, const VmathSoaVector3 *xyz, vec_float4 w ); + +/* + * Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + */ +static inline void vmathSoaV4MakeFromV3( VmathSoaVector4 *result, const VmathSoaVector3 *vec ); + +/* + * Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + */ +static inline void vmathSoaV4MakeFromP3( VmathSoaVector4 *result, const VmathSoaPoint3 *pnt ); + +/* + * Copy elements from a quaternion into a 4-D vector + */ +static inline void vmathSoaV4MakeFromQ( VmathSoaVector4 *result, const VmathSoaQuat *quat ); + +/* + * Set all elements of a 4-D vector to the same scalar value + */ +static inline void vmathSoaV4MakeFromScalar( VmathSoaVector4 *result, vec_float4 scalar ); + +/* + * Replicate an AoS 4-D vector + */ +static inline void vmathSoaV4MakeFromAos( VmathSoaVector4 *result, const VmathVector4 *vec ); + +/* + * Insert four AoS 4-D vectors + */ +static inline void vmathSoaV4MakeFrom4Aos( VmathSoaVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1, const VmathVector4 *vec2, const VmathVector4 *vec3 ); + +/* + * Extract four AoS 4-D vectors + */ +static inline void vmathSoaV4Get4Aos( const VmathSoaVector4 *vec, VmathVector4 *result0, VmathVector4 *result1, VmathVector4 *result2, VmathVector4 *result3 ); + +/* + * Set the x, y, and z elements of a 4-D vector + * NOTE: + * This function does not change the w element. + */ +static inline void vmathSoaV4SetXYZ( VmathSoaVector4 *result, const VmathSoaVector3 *vec ); + +/* + * Get the x, y, and z elements of a 4-D vector + */ +static inline void vmathSoaV4GetXYZ( VmathSoaVector3 *result, const VmathSoaVector4 *vec ); + +/* + * Set the x element of a 4-D vector + */ +static inline void vmathSoaV4SetX( VmathSoaVector4 *result, vec_float4 x ); + +/* + * Set the y element of a 4-D vector + */ +static inline void vmathSoaV4SetY( VmathSoaVector4 *result, vec_float4 y ); + +/* + * Set the z element of a 4-D vector + */ +static inline void vmathSoaV4SetZ( VmathSoaVector4 *result, vec_float4 z ); + +/* + * Set the w element of a 4-D vector + */ +static inline void vmathSoaV4SetW( VmathSoaVector4 *result, vec_float4 w ); + +/* + * Get the x element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4GetX( const VmathSoaVector4 *vec ); + +/* + * Get the y element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4GetY( const VmathSoaVector4 *vec ); + +/* + * Get the z element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4GetZ( const VmathSoaVector4 *vec ); + +/* + * Get the w element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4GetW( const VmathSoaVector4 *vec ); + +/* + * Set an x, y, z, or w element of a 4-D vector by index + */ +static inline void vmathSoaV4SetElem( VmathSoaVector4 *result, int idx, vec_float4 value ); + +/* + * Get an x, y, z, or w element of a 4-D vector by index + */ +static inline vec_float4 vmathSoaV4GetElem( const VmathSoaVector4 *vec, int idx ); + +/* + * Add two 4-D vectors + */ +static inline void vmathSoaV4Add( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Subtract a 4-D vector from another 4-D vector + */ +static inline void vmathSoaV4Sub( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Multiply a 4-D vector by a scalar + */ +static inline void vmathSoaV4ScalarMul( VmathSoaVector4 *result, const VmathSoaVector4 *vec, vec_float4 scalar ); + +/* + * Divide a 4-D vector by a scalar + */ +static inline void vmathSoaV4ScalarDiv( VmathSoaVector4 *result, const VmathSoaVector4 *vec, vec_float4 scalar ); + +/* + * Negate all elements of a 4-D vector + */ +static inline void vmathSoaV4Neg( VmathSoaVector4 *result, const VmathSoaVector4 *vec ); + +/* + * Construct x axis + */ +static inline void vmathSoaV4MakeXAxis( VmathSoaVector4 *result ); + +/* + * Construct y axis + */ +static inline void vmathSoaV4MakeYAxis( VmathSoaVector4 *result ); + +/* + * Construct z axis + */ +static inline void vmathSoaV4MakeZAxis( VmathSoaVector4 *result ); + +/* + * Construct w axis + */ +static inline void vmathSoaV4MakeWAxis( VmathSoaVector4 *result ); + +/* + * Multiply two 4-D vectors per element + */ +static inline void vmathSoaV4MulPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Divide two 4-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline void vmathSoaV4DivPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Compute the reciprocal of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline void vmathSoaV4RecipPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec ); + +/* + * Compute the square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline void vmathSoaV4SqrtPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec ); + +/* + * Compute the reciprocal square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline void vmathSoaV4RsqrtPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec ); + +/* + * Compute the absolute value of a 4-D vector per element + */ +static inline void vmathSoaV4AbsPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec ); + +/* + * Copy sign from one 4-D vector to another, per element + */ +static inline void vmathSoaV4CopySignPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Maximum of two 4-D vectors per element + */ +static inline void vmathSoaV4MaxPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Minimum of two 4-D vectors per element + */ +static inline void vmathSoaV4MinPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Maximum element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4MaxElem( const VmathSoaVector4 *vec ); + +/* + * Minimum element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4MinElem( const VmathSoaVector4 *vec ); + +/* + * Compute the sum of all elements of a 4-D vector + */ +static inline vec_float4 vmathSoaV4Sum( const VmathSoaVector4 *vec ); + +/* + * Compute the dot product of two 4-D vectors + */ +static inline vec_float4 vmathSoaV4Dot( const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Compute the square of the length of a 4-D vector + */ +static inline vec_float4 vmathSoaV4LengthSqr( const VmathSoaVector4 *vec ); + +/* + * Compute the length of a 4-D vector + */ +static inline vec_float4 vmathSoaV4Length( const VmathSoaVector4 *vec ); + +/* + * Normalize a 4-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline void vmathSoaV4Normalize( VmathSoaVector4 *result, const VmathSoaVector4 *vec ); + +/* + * Outer product of two 4-D vectors + */ +static inline void vmathSoaV4Outer( VmathSoaMatrix4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Linear interpolation between two 4-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathSoaV4Lerp( VmathSoaVector4 *result, vec_float4 t, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Spherical linear interpolation between two 4-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline void vmathSoaV4Slerp( VmathSoaVector4 *result, vec_float4 t, const VmathSoaVector4 *unitVec0, const VmathSoaVector4 *unitVec1 ); + +/* + * Conditionally select between two 4-D vectors + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathSoaV4Select( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1, vec_uint4 select1 ); + +/* + * Store four slots of an SoA 4-D vector as half-floats + */ +static inline void vmathSoaV4StoreHalfFloats( const VmathSoaVector4 *vec, vec_ushort8 *twoQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaV4Print( const VmathSoaVector4 *vec ); + +/* + * Print a 4-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaV4Prints( const VmathSoaVector4 *vec, const char *name ); + +#endif + +/* + * Copy a 3-D point + */ +static inline void vmathSoaP3Copy( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ); + +/* + * Construct a 3-D point from x, y, and z elements + */ +static inline void vmathSoaP3MakeFromElems( VmathSoaPoint3 *result, vec_float4 x, vec_float4 y, vec_float4 z ); + +/* + * Copy elements from a 3-D vector into a 3-D point + */ +static inline void vmathSoaP3MakeFromV3( VmathSoaPoint3 *result, const VmathSoaVector3 *vec ); + +/* + * Set all elements of a 3-D point to the same scalar value + */ +static inline void vmathSoaP3MakeFromScalar( VmathSoaPoint3 *result, vec_float4 scalar ); + +/* + * Replicate an AoS 3-D point + */ +static inline void vmathSoaP3MakeFromAos( VmathSoaPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Insert four AoS 3-D points + */ +static inline void vmathSoaP3MakeFrom4Aos( VmathSoaPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, const VmathPoint3 *pnt2, const VmathPoint3 *pnt3 ); + +/* + * Extract four AoS 3-D points + */ +static inline void vmathSoaP3Get4Aos( const VmathSoaPoint3 *pnt, VmathPoint3 *result0, VmathPoint3 *result1, VmathPoint3 *result2, VmathPoint3 *result3 ); + +/* + * Set the x element of a 3-D point + */ +static inline void vmathSoaP3SetX( VmathSoaPoint3 *result, vec_float4 x ); + +/* + * Set the y element of a 3-D point + */ +static inline void vmathSoaP3SetY( VmathSoaPoint3 *result, vec_float4 y ); + +/* + * Set the z element of a 3-D point + */ +static inline void vmathSoaP3SetZ( VmathSoaPoint3 *result, vec_float4 z ); + +/* + * Get the x element of a 3-D point + */ +static inline vec_float4 vmathSoaP3GetX( const VmathSoaPoint3 *pnt ); + +/* + * Get the y element of a 3-D point + */ +static inline vec_float4 vmathSoaP3GetY( const VmathSoaPoint3 *pnt ); + +/* + * Get the z element of a 3-D point + */ +static inline vec_float4 vmathSoaP3GetZ( const VmathSoaPoint3 *pnt ); + +/* + * Set an x, y, or z element of a 3-D point by index + */ +static inline void vmathSoaP3SetElem( VmathSoaPoint3 *result, int idx, vec_float4 value ); + +/* + * Get an x, y, or z element of a 3-D point by index + */ +static inline vec_float4 vmathSoaP3GetElem( const VmathSoaPoint3 *pnt, int idx ); + +/* + * Subtract a 3-D point from another 3-D point + */ +static inline void vmathSoaP3Sub( VmathSoaVector3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Add a 3-D point to a 3-D vector + */ +static inline void vmathSoaP3AddV3( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, const VmathSoaVector3 *vec ); + +/* + * Subtract a 3-D vector from a 3-D point + */ +static inline void vmathSoaP3SubV3( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, const VmathSoaVector3 *vec ); + +/* + * Multiply two 3-D points per element + */ +static inline void vmathSoaP3MulPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Divide two 3-D points per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline void vmathSoaP3DivPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Compute the reciprocal of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline void vmathSoaP3RecipPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ); + +/* + * Compute the square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline void vmathSoaP3SqrtPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ); + +/* + * Compute the reciprocal square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline void vmathSoaP3RsqrtPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ); + +/* + * Compute the absolute value of a 3-D point per element + */ +static inline void vmathSoaP3AbsPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ); + +/* + * Copy sign from one 3-D point to another, per element + */ +static inline void vmathSoaP3CopySignPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Maximum of two 3-D points per element + */ +static inline void vmathSoaP3MaxPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Minimum of two 3-D points per element + */ +static inline void vmathSoaP3MinPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Maximum element of a 3-D point + */ +static inline vec_float4 vmathSoaP3MaxElem( const VmathSoaPoint3 *pnt ); + +/* + * Minimum element of a 3-D point + */ +static inline vec_float4 vmathSoaP3MinElem( const VmathSoaPoint3 *pnt ); + +/* + * Compute the sum of all elements of a 3-D point + */ +static inline vec_float4 vmathSoaP3Sum( const VmathSoaPoint3 *pnt ); + +/* + * Apply uniform scale to a 3-D point + */ +static inline void vmathSoaP3Scale( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, vec_float4 scaleVal ); + +/* + * Apply non-uniform scale to a 3-D point + */ +static inline void vmathSoaP3NonUniformScale( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, const VmathSoaVector3 *scaleVec ); + +/* + * Scalar projection of a 3-D point on a unit-length 3-D vector + */ +static inline vec_float4 vmathSoaP3Projection( const VmathSoaPoint3 *pnt, const VmathSoaVector3 *unitVec ); + +/* + * Compute the square of the distance of a 3-D point from the coordinate-system origin + */ +static inline vec_float4 vmathSoaP3DistSqrFromOrigin( const VmathSoaPoint3 *pnt ); + +/* + * Compute the distance of a 3-D point from the coordinate-system origin + */ +static inline vec_float4 vmathSoaP3DistFromOrigin( const VmathSoaPoint3 *pnt ); + +/* + * Compute the square of the distance between two 3-D points + */ +static inline vec_float4 vmathSoaP3DistSqr( const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Compute the distance between two 3-D points + */ +static inline vec_float4 vmathSoaP3Dist( const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Linear interpolation between two 3-D points + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathSoaP3Lerp( VmathSoaPoint3 *result, vec_float4 t, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Conditionally select between two 3-D points + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathSoaP3Select( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1, vec_uint4 select1 ); + +/* + * Load four three-float 3-D points, stored in three quadwords + */ +static inline void vmathSoaP3LoadXYZArray( VmathSoaPoint3 *pnt, const vec_float4 *threeQuads ); + +/* + * Store four slots of an SoA 3-D point in three quadwords + */ +static inline void vmathSoaP3StoreXYZArray( const VmathSoaPoint3 *pnt, vec_float4 *threeQuads ); + +/* + * Store eight slots of two SoA 3-D points as half-floats + */ +static inline void vmathSoaP3StoreHalfFloats( const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1, vec_ushort8 *threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D point + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaP3Print( const VmathSoaPoint3 *pnt ); + +/* + * Print a 3-D point and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaP3Prints( const VmathSoaPoint3 *pnt, const char *name ); + +#endif + +/* + * Copy a quaternion + */ +static inline void vmathSoaQCopy( VmathSoaQuat *result, const VmathSoaQuat *quat ); + +/* + * Construct a quaternion from x, y, z, and w elements + */ +static inline void vmathSoaQMakeFromElems( VmathSoaQuat *result, vec_float4 x, vec_float4 y, vec_float4 z, vec_float4 w ); + +/* + * Construct a quaternion from a 3-D vector and a scalar + */ +static inline void vmathSoaQMakeFromV3Scalar( VmathSoaQuat *result, const VmathSoaVector3 *xyz, vec_float4 w ); + +/* + * Copy elements from a 4-D vector into a quaternion + */ +static inline void vmathSoaQMakeFromV4( VmathSoaQuat *result, const VmathSoaVector4 *vec ); + +/* + * Convert a rotation matrix to a unit-length quaternion + */ +static inline void vmathSoaQMakeFromM3( VmathSoaQuat *result, const VmathSoaMatrix3 *rotMat ); + +/* + * Set all elements of a quaternion to the same scalar value + */ +static inline void vmathSoaQMakeFromScalar( VmathSoaQuat *result, vec_float4 scalar ); + +/* + * Replicate an AoS quaternion + */ +static inline void vmathSoaQMakeFromAos( VmathSoaQuat *result, const VmathQuat *quat ); + +/* + * Insert four AoS quaternions + */ +static inline void vmathSoaQMakeFrom4Aos( VmathSoaQuat *result, const VmathQuat *quat0, const VmathQuat *quat1, const VmathQuat *quat2, const VmathQuat *quat3 ); + +/* + * Extract four AoS quaternions + */ +static inline void vmathSoaQGet4Aos( const VmathSoaQuat *quat, VmathQuat *result0, VmathQuat *result1, VmathQuat *result2, VmathQuat *result3 ); + +/* + * Set the x, y, and z elements of a quaternion + * NOTE: + * This function does not change the w element. + */ +static inline void vmathSoaQSetXYZ( VmathSoaQuat *result, const VmathSoaVector3 *vec ); + +/* + * Get the x, y, and z elements of a quaternion + */ +static inline void vmathSoaQGetXYZ( VmathSoaVector3 *result, const VmathSoaQuat *quat ); + +/* + * Set the x element of a quaternion + */ +static inline void vmathSoaQSetX( VmathSoaQuat *result, vec_float4 x ); + +/* + * Set the y element of a quaternion + */ +static inline void vmathSoaQSetY( VmathSoaQuat *result, vec_float4 y ); + +/* + * Set the z element of a quaternion + */ +static inline void vmathSoaQSetZ( VmathSoaQuat *result, vec_float4 z ); + +/* + * Set the w element of a quaternion + */ +static inline void vmathSoaQSetW( VmathSoaQuat *result, vec_float4 w ); + +/* + * Get the x element of a quaternion + */ +static inline vec_float4 vmathSoaQGetX( const VmathSoaQuat *quat ); + +/* + * Get the y element of a quaternion + */ +static inline vec_float4 vmathSoaQGetY( const VmathSoaQuat *quat ); + +/* + * Get the z element of a quaternion + */ +static inline vec_float4 vmathSoaQGetZ( const VmathSoaQuat *quat ); + +/* + * Get the w element of a quaternion + */ +static inline vec_float4 vmathSoaQGetW( const VmathSoaQuat *quat ); + +/* + * Set an x, y, z, or w element of a quaternion by index + */ +static inline void vmathSoaQSetElem( VmathSoaQuat *result, int idx, vec_float4 value ); + +/* + * Get an x, y, z, or w element of a quaternion by index + */ +static inline vec_float4 vmathSoaQGetElem( const VmathSoaQuat *quat, int idx ); + +/* + * Add two quaternions + */ +static inline void vmathSoaQAdd( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ); + +/* + * Subtract a quaternion from another quaternion + */ +static inline void vmathSoaQSub( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ); + +/* + * Multiply two quaternions + */ +static inline void vmathSoaQMul( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ); + +/* + * Multiply a quaternion by a scalar + */ +static inline void vmathSoaQScalarMul( VmathSoaQuat *result, const VmathSoaQuat *quat, vec_float4 scalar ); + +/* + * Divide a quaternion by a scalar + */ +static inline void vmathSoaQScalarDiv( VmathSoaQuat *result, const VmathSoaQuat *quat, vec_float4 scalar ); + +/* + * Negate all elements of a quaternion + */ +static inline void vmathSoaQNeg( VmathSoaQuat *result, const VmathSoaQuat *quat ); + +/* + * Construct an identity quaternion + */ +static inline void vmathSoaQMakeIdentity( VmathSoaQuat *result ); + +/* + * Construct a quaternion to rotate between two unit-length 3-D vectors + * NOTE: + * The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + */ +static inline void vmathSoaQMakeRotationArc( VmathSoaQuat *result, const VmathSoaVector3 *unitVec0, const VmathSoaVector3 *unitVec1 ); + +/* + * Construct a quaternion to rotate around a unit-length 3-D vector + */ +static inline void vmathSoaQMakeRotationAxis( VmathSoaQuat *result, vec_float4 radians, const VmathSoaVector3 *unitVec ); + +/* + * Construct a quaternion to rotate around the x axis + */ +static inline void vmathSoaQMakeRotationX( VmathSoaQuat *result, vec_float4 radians ); + +/* + * Construct a quaternion to rotate around the y axis + */ +static inline void vmathSoaQMakeRotationY( VmathSoaQuat *result, vec_float4 radians ); + +/* + * Construct a quaternion to rotate around the z axis + */ +static inline void vmathSoaQMakeRotationZ( VmathSoaQuat *result, vec_float4 radians ); + +/* + * Compute the conjugate of a quaternion + */ +static inline void vmathSoaQConj( VmathSoaQuat *result, const VmathSoaQuat *quat ); + +/* + * Use a unit-length quaternion to rotate a 3-D vector + */ +static inline void vmathSoaQRotate( VmathSoaVector3 *result, const VmathSoaQuat *unitQuat, const VmathSoaVector3 *vec ); + +/* + * Compute the dot product of two quaternions + */ +static inline vec_float4 vmathSoaQDot( const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ); + +/* + * Compute the norm of a quaternion + */ +static inline vec_float4 vmathSoaQNorm( const VmathSoaQuat *quat ); + +/* + * Compute the length of a quaternion + */ +static inline vec_float4 vmathSoaQLength( const VmathSoaQuat *quat ); + +/* + * Normalize a quaternion + * NOTE: + * The result is unpredictable when all elements of quat are at or near zero. + */ +static inline void vmathSoaQNormalize( VmathSoaQuat *result, const VmathSoaQuat *quat ); + +/* + * Linear interpolation between two quaternions + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathSoaQLerp( VmathSoaQuat *result, vec_float4 t, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ); + +/* + * Spherical linear interpolation between two quaternions + * NOTE: + * Interpolates along the shortest path between orientations. + * Does not clamp t between 0 and 1. + */ +static inline void vmathSoaQSlerp( VmathSoaQuat *result, vec_float4 t, const VmathSoaQuat *unitQuat0, const VmathSoaQuat *unitQuat1 ); + +/* + * Spherical quadrangle interpolation + */ +static inline void vmathSoaQSquad( VmathSoaQuat *result, vec_float4 t, const VmathSoaQuat *unitQuat0, const VmathSoaQuat *unitQuat1, const VmathSoaQuat *unitQuat2, const VmathSoaQuat *unitQuat3 ); + +/* + * Conditionally select between two quaternions + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathSoaQSelect( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a quaternion + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaQPrint( const VmathSoaQuat *quat ); + +/* + * Print a quaternion and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaQPrints( const VmathSoaQuat *quat, const char *name ); + +#endif + +/* + * Copy a 3x3 matrix + */ +static inline void vmathSoaM3Copy( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ); + +/* + * Construct a 3x3 matrix containing the specified columns + */ +static inline void vmathSoaM3MakeFromCols( VmathSoaMatrix3 *result, const VmathSoaVector3 *col0, const VmathSoaVector3 *col1, const VmathSoaVector3 *col2 ); + +/* + * Construct a 3x3 rotation matrix from a unit-length quaternion + */ +static inline void vmathSoaM3MakeFromQ( VmathSoaMatrix3 *result, const VmathSoaQuat *unitQuat ); + +/* + * Set all elements of a 3x3 matrix to the same scalar value + */ +static inline void vmathSoaM3MakeFromScalar( VmathSoaMatrix3 *result, vec_float4 scalar ); + +/* + * Replicate an AoS 3x3 matrix + */ +static inline void vmathSoaM3MakeFromAos( VmathSoaMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Insert four AoS 3x3 matrices + */ +static inline void vmathSoaM3MakeFrom4Aos( VmathSoaMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1, const VmathMatrix3 *mat2, const VmathMatrix3 *mat3 ); + +/* + * Extract four AoS 3x3 matrices + */ +static inline void vmathSoaM3Get4Aos( const VmathSoaMatrix3 *mat, VmathMatrix3 *result0, VmathMatrix3 *result1, VmathMatrix3 *result2, VmathMatrix3 *result3 ); + +/* + * Set column 0 of a 3x3 matrix + */ +static inline void vmathSoaM3SetCol0( VmathSoaMatrix3 *result, const VmathSoaVector3 *col0 ); + +/* + * Set column 1 of a 3x3 matrix + */ +static inline void vmathSoaM3SetCol1( VmathSoaMatrix3 *result, const VmathSoaVector3 *col1 ); + +/* + * Set column 2 of a 3x3 matrix + */ +static inline void vmathSoaM3SetCol2( VmathSoaMatrix3 *result, const VmathSoaVector3 *col2 ); + +/* + * Get column 0 of a 3x3 matrix + */ +static inline void vmathSoaM3GetCol0( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat ); + +/* + * Get column 1 of a 3x3 matrix + */ +static inline void vmathSoaM3GetCol1( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat ); + +/* + * Get column 2 of a 3x3 matrix + */ +static inline void vmathSoaM3GetCol2( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat ); + +/* + * Set the column of a 3x3 matrix referred to by the specified index + */ +static inline void vmathSoaM3SetCol( VmathSoaMatrix3 *result, int col, const VmathSoaVector3 *vec ); + +/* + * Set the row of a 3x3 matrix referred to by the specified index + */ +static inline void vmathSoaM3SetRow( VmathSoaMatrix3 *result, int row, const VmathSoaVector3 *vec ); + +/* + * Get the column of a 3x3 matrix referred to by the specified index + */ +static inline void vmathSoaM3GetCol( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat, int col ); + +/* + * Get the row of a 3x3 matrix referred to by the specified index + */ +static inline void vmathSoaM3GetRow( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat, int row ); + +/* + * Set the element of a 3x3 matrix referred to by column and row indices + */ +static inline void vmathSoaM3SetElem( VmathSoaMatrix3 *result, int col, int row, vec_float4 val ); + +/* + * Get the element of a 3x3 matrix referred to by column and row indices + */ +static inline vec_float4 vmathSoaM3GetElem( const VmathSoaMatrix3 *mat, int col, int row ); + +/* + * Add two 3x3 matrices + */ +static inline void vmathSoaM3Add( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 ); + +/* + * Subtract a 3x3 matrix from another 3x3 matrix + */ +static inline void vmathSoaM3Sub( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 ); + +/* + * Negate all elements of a 3x3 matrix + */ +static inline void vmathSoaM3Neg( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ); + +/* + * Multiply a 3x3 matrix by a scalar + */ +static inline void vmathSoaM3ScalarMul( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat, vec_float4 scalar ); + +/* + * Multiply a 3x3 matrix by a 3-D vector + */ +static inline void vmathSoaM3MulV3( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat, const VmathSoaVector3 *vec ); + +/* + * Multiply two 3x3 matrices + */ +static inline void vmathSoaM3Mul( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 ); + +/* + * Construct an identity 3x3 matrix + */ +static inline void vmathSoaM3MakeIdentity( VmathSoaMatrix3 *result ); + +/* + * Construct a 3x3 matrix to rotate around the x axis + */ +static inline void vmathSoaM3MakeRotationX( VmathSoaMatrix3 *result, vec_float4 radians ); + +/* + * Construct a 3x3 matrix to rotate around the y axis + */ +static inline void vmathSoaM3MakeRotationY( VmathSoaMatrix3 *result, vec_float4 radians ); + +/* + * Construct a 3x3 matrix to rotate around the z axis + */ +static inline void vmathSoaM3MakeRotationZ( VmathSoaMatrix3 *result, vec_float4 radians ); + +/* + * Construct a 3x3 matrix to rotate around the x, y, and z axes + */ +static inline void vmathSoaM3MakeRotationZYX( VmathSoaMatrix3 *result, const VmathSoaVector3 *radiansXYZ ); + +/* + * Construct a 3x3 matrix to rotate around a unit-length 3-D vector + */ +static inline void vmathSoaM3MakeRotationAxis( VmathSoaMatrix3 *result, vec_float4 radians, const VmathSoaVector3 *unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline void vmathSoaM3MakeRotationQ( VmathSoaMatrix3 *result, const VmathSoaQuat *unitQuat ); + +/* + * Construct a 3x3 matrix to perform scaling + */ +static inline void vmathSoaM3MakeScale( VmathSoaMatrix3 *result, const VmathSoaVector3 *scaleVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathSoaM3AppendScale( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat, const VmathSoaVector3 *scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathSoaM3PrependScale( VmathSoaMatrix3 *result, const VmathSoaVector3 *scaleVec, const VmathSoaMatrix3 *mat ); + +/* + * Multiply two 3x3 matrices per element + */ +static inline void vmathSoaM3MulPerElem( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 ); + +/* + * Compute the absolute value of a 3x3 matrix per element + */ +static inline void vmathSoaM3AbsPerElem( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ); + +/* + * Transpose of a 3x3 matrix + */ +static inline void vmathSoaM3Transpose( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ); + +/* + * Compute the inverse of a 3x3 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline void vmathSoaM3Inverse( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ); + +/* + * Determinant of a 3x3 matrix + */ +static inline vec_float4 vmathSoaM3Determinant( const VmathSoaMatrix3 *mat ); + +/* + * Conditionally select between two 3x3 matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathSoaM3Select( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x3 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaM3Print( const VmathSoaMatrix3 *mat ); + +/* + * Print a 3x3 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaM3Prints( const VmathSoaMatrix3 *mat, const char *name ); + +#endif + +/* + * Copy a 4x4 matrix + */ +static inline void vmathSoaM4Copy( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Construct a 4x4 matrix containing the specified columns + */ +static inline void vmathSoaM4MakeFromCols( VmathSoaMatrix4 *result, const VmathSoaVector4 *col0, const VmathSoaVector4 *col1, const VmathSoaVector4 *col2, const VmathSoaVector4 *col3 ); + +/* + * Construct a 4x4 matrix from a 3x4 transformation matrix + */ +static inline void vmathSoaM4MakeFromT3( VmathSoaMatrix4 *result, const VmathSoaTransform3 *mat ); + +/* + * Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + */ +static inline void vmathSoaM4MakeFromM3V3( VmathSoaMatrix4 *result, const VmathSoaMatrix3 *mat, const VmathSoaVector3 *translateVec ); + +/* + * Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + */ +static inline void vmathSoaM4MakeFromQV3( VmathSoaMatrix4 *result, const VmathSoaQuat *unitQuat, const VmathSoaVector3 *translateVec ); + +/* + * Set all elements of a 4x4 matrix to the same scalar value + */ +static inline void vmathSoaM4MakeFromScalar( VmathSoaMatrix4 *result, vec_float4 scalar ); + +/* + * Replicate an AoS 4x4 matrix + */ +static inline void vmathSoaM4MakeFromAos( VmathSoaMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Insert four AoS 4x4 matrices + */ +static inline void vmathSoaM4MakeFrom4Aos( VmathSoaMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1, const VmathMatrix4 *mat2, const VmathMatrix4 *mat3 ); + +/* + * Extract four AoS 4x4 matrices + */ +static inline void vmathSoaM4Get4Aos( const VmathSoaMatrix4 *mat, VmathMatrix4 *result0, VmathMatrix4 *result1, VmathMatrix4 *result2, VmathMatrix4 *result3 ); + +/* + * Set the upper-left 3x3 submatrix + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathSoaM4SetUpper3x3( VmathSoaMatrix4 *result, const VmathSoaMatrix3 *mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 4x4 matrix + */ +static inline void vmathSoaM4GetUpper3x3( VmathSoaMatrix3 *result, const VmathSoaMatrix4 *mat ); + +/* + * Set translation component + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathSoaM4SetTranslation( VmathSoaMatrix4 *result, const VmathSoaVector3 *translateVec ); + +/* + * Get the translation component of a 4x4 matrix + */ +static inline void vmathSoaM4GetTranslation( VmathSoaVector3 *result, const VmathSoaMatrix4 *mat ); + +/* + * Set column 0 of a 4x4 matrix + */ +static inline void vmathSoaM4SetCol0( VmathSoaMatrix4 *result, const VmathSoaVector4 *col0 ); + +/* + * Set column 1 of a 4x4 matrix + */ +static inline void vmathSoaM4SetCol1( VmathSoaMatrix4 *result, const VmathSoaVector4 *col1 ); + +/* + * Set column 2 of a 4x4 matrix + */ +static inline void vmathSoaM4SetCol2( VmathSoaMatrix4 *result, const VmathSoaVector4 *col2 ); + +/* + * Set column 3 of a 4x4 matrix + */ +static inline void vmathSoaM4SetCol3( VmathSoaMatrix4 *result, const VmathSoaVector4 *col3 ); + +/* + * Get column 0 of a 4x4 matrix + */ +static inline void vmathSoaM4GetCol0( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Get column 1 of a 4x4 matrix + */ +static inline void vmathSoaM4GetCol1( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Get column 2 of a 4x4 matrix + */ +static inline void vmathSoaM4GetCol2( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Get column 3 of a 4x4 matrix + */ +static inline void vmathSoaM4GetCol3( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Set the column of a 4x4 matrix referred to by the specified index + */ +static inline void vmathSoaM4SetCol( VmathSoaMatrix4 *result, int col, const VmathSoaVector4 *vec ); + +/* + * Set the row of a 4x4 matrix referred to by the specified index + */ +static inline void vmathSoaM4SetRow( VmathSoaMatrix4 *result, int row, const VmathSoaVector4 *vec ); + +/* + * Get the column of a 4x4 matrix referred to by the specified index + */ +static inline void vmathSoaM4GetCol( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, int col ); + +/* + * Get the row of a 4x4 matrix referred to by the specified index + */ +static inline void vmathSoaM4GetRow( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, int row ); + +/* + * Set the element of a 4x4 matrix referred to by column and row indices + */ +static inline void vmathSoaM4SetElem( VmathSoaMatrix4 *result, int col, int row, vec_float4 val ); + +/* + * Get the element of a 4x4 matrix referred to by column and row indices + */ +static inline vec_float4 vmathSoaM4GetElem( const VmathSoaMatrix4 *mat, int col, int row ); + +/* + * Add two 4x4 matrices + */ +static inline void vmathSoaM4Add( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 ); + +/* + * Subtract a 4x4 matrix from another 4x4 matrix + */ +static inline void vmathSoaM4Sub( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 ); + +/* + * Negate all elements of a 4x4 matrix + */ +static inline void vmathSoaM4Neg( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Multiply a 4x4 matrix by a scalar + */ +static inline void vmathSoaM4ScalarMul( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat, vec_float4 scalar ); + +/* + * Multiply a 4x4 matrix by a 4-D vector + */ +static inline void vmathSoaM4MulV4( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, const VmathSoaVector4 *vec ); + +/* + * Multiply a 4x4 matrix by a 3-D vector + */ +static inline void vmathSoaM4MulV3( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, const VmathSoaVector3 *vec ); + +/* + * Multiply a 4x4 matrix by a 3-D point + */ +static inline void vmathSoaM4MulP3( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, const VmathSoaPoint3 *pnt ); + +/* + * Multiply two 4x4 matrices + */ +static inline void vmathSoaM4Mul( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 ); + +/* + * Multiply a 4x4 matrix by a 3x4 transformation matrix + */ +static inline void vmathSoaM4MulT3( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat, const VmathSoaTransform3 *tfrm ); + +/* + * Construct an identity 4x4 matrix + */ +static inline void vmathSoaM4MakeIdentity( VmathSoaMatrix4 *result ); + +/* + * Construct a 4x4 matrix to rotate around the x axis + */ +static inline void vmathSoaM4MakeRotationX( VmathSoaMatrix4 *result, vec_float4 radians ); + +/* + * Construct a 4x4 matrix to rotate around the y axis + */ +static inline void vmathSoaM4MakeRotationY( VmathSoaMatrix4 *result, vec_float4 radians ); + +/* + * Construct a 4x4 matrix to rotate around the z axis + */ +static inline void vmathSoaM4MakeRotationZ( VmathSoaMatrix4 *result, vec_float4 radians ); + +/* + * Construct a 4x4 matrix to rotate around the x, y, and z axes + */ +static inline void vmathSoaM4MakeRotationZYX( VmathSoaMatrix4 *result, const VmathSoaVector3 *radiansXYZ ); + +/* + * Construct a 4x4 matrix to rotate around a unit-length 3-D vector + */ +static inline void vmathSoaM4MakeRotationAxis( VmathSoaMatrix4 *result, vec_float4 radians, const VmathSoaVector3 *unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline void vmathSoaM4MakeRotationQ( VmathSoaMatrix4 *result, const VmathSoaQuat *unitQuat ); + +/* + * Construct a 4x4 matrix to perform scaling + */ +static inline void vmathSoaM4MakeScale( VmathSoaMatrix4 *result, const VmathSoaVector3 *scaleVec ); + +/* + * Construct a 4x4 matrix to perform translation + */ +static inline void vmathSoaM4MakeTranslation( VmathSoaMatrix4 *result, const VmathSoaVector3 *translateVec ); + +/* + * Construct viewing matrix based on eye position, position looked at, and up direction + */ +static inline void vmathSoaM4MakeLookAt( VmathSoaMatrix4 *result, const VmathSoaPoint3 *eyePos, const VmathSoaPoint3 *lookAtPos, const VmathSoaVector3 *upVec ); + +/* + * Construct a perspective projection matrix + */ +static inline void vmathSoaM4MakePerspective( VmathSoaMatrix4 *result, vec_float4 fovyRadians, vec_float4 aspect, vec_float4 zNear, vec_float4 zFar ); + +/* + * Construct a perspective projection matrix based on frustum + */ +static inline void vmathSoaM4MakeFrustum( VmathSoaMatrix4 *result, vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ); + +/* + * Construct an orthographic projection matrix + */ +static inline void vmathSoaM4MakeOrthographic( VmathSoaMatrix4 *result, vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ); + +/* + * Append (post-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathSoaM4AppendScale( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat, const VmathSoaVector3 *scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathSoaM4PrependScale( VmathSoaMatrix4 *result, const VmathSoaVector3 *scaleVec, const VmathSoaMatrix4 *mat ); + +/* + * Multiply two 4x4 matrices per element + */ +static inline void vmathSoaM4MulPerElem( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 ); + +/* + * Compute the absolute value of a 4x4 matrix per element + */ +static inline void vmathSoaM4AbsPerElem( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Transpose of a 4x4 matrix + */ +static inline void vmathSoaM4Transpose( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Compute the inverse of a 4x4 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline void vmathSoaM4Inverse( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline void vmathSoaM4AffineInverse( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. + */ +static inline void vmathSoaM4OrthoInverse( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Determinant of a 4x4 matrix + */ +static inline vec_float4 vmathSoaM4Determinant( const VmathSoaMatrix4 *mat ); + +/* + * Conditionally select between two 4x4 matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathSoaM4Select( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4x4 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaM4Print( const VmathSoaMatrix4 *mat ); + +/* + * Print a 4x4 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaM4Prints( const VmathSoaMatrix4 *mat, const char *name ); + +#endif + +/* + * Copy a 3x4 transformation matrix + */ +static inline void vmathSoaT3Copy( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Construct a 3x4 transformation matrix containing the specified columns + */ +static inline void vmathSoaT3MakeFromCols( VmathSoaTransform3 *result, const VmathSoaVector3 *col0, const VmathSoaVector3 *col1, const VmathSoaVector3 *col2, const VmathSoaVector3 *col3 ); + +/* + * Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + */ +static inline void vmathSoaT3MakeFromM3V3( VmathSoaTransform3 *result, const VmathSoaMatrix3 *tfrm, const VmathSoaVector3 *translateVec ); + +/* + * Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + */ +static inline void vmathSoaT3MakeFromQV3( VmathSoaTransform3 *result, const VmathSoaQuat *unitQuat, const VmathSoaVector3 *translateVec ); + +/* + * Set all elements of a 3x4 transformation matrix to the same scalar value + */ +static inline void vmathSoaT3MakeFromScalar( VmathSoaTransform3 *result, vec_float4 scalar ); + +/* + * Replicate an AoS 3x4 transformation matrix + */ +static inline void vmathSoaT3MakeFromAos( VmathSoaTransform3 *result, const VmathTransform3 *tfrm ); + +/* + * Insert four AoS 3x4 transformation matrices + */ +static inline void vmathSoaT3MakeFrom4Aos( VmathSoaTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1, const VmathTransform3 *tfrm2, const VmathTransform3 *tfrm3 ); + +/* + * Extract four AoS 3x4 transformation matrices + */ +static inline void vmathSoaT3Get4Aos( const VmathSoaTransform3 *tfrm, VmathTransform3 *result0, VmathTransform3 *result1, VmathTransform3 *result2, VmathTransform3 *result3 ); + +/* + * Set the upper-left 3x3 submatrix + */ +static inline void vmathSoaT3SetUpper3x3( VmathSoaTransform3 *result, const VmathSoaMatrix3 *mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + */ +static inline void vmathSoaT3GetUpper3x3( VmathSoaMatrix3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Set translation component + */ +static inline void vmathSoaT3SetTranslation( VmathSoaTransform3 *result, const VmathSoaVector3 *translateVec ); + +/* + * Get the translation component of a 3x4 transformation matrix + */ +static inline void vmathSoaT3GetTranslation( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Set column 0 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3SetCol0( VmathSoaTransform3 *result, const VmathSoaVector3 *col0 ); + +/* + * Set column 1 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3SetCol1( VmathSoaTransform3 *result, const VmathSoaVector3 *col1 ); + +/* + * Set column 2 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3SetCol2( VmathSoaTransform3 *result, const VmathSoaVector3 *col2 ); + +/* + * Set column 3 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3SetCol3( VmathSoaTransform3 *result, const VmathSoaVector3 *col3 ); + +/* + * Get column 0 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3GetCol0( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Get column 1 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3GetCol1( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Get column 2 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3GetCol2( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Get column 3 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3GetCol3( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Set the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathSoaT3SetCol( VmathSoaTransform3 *result, int col, const VmathSoaVector3 *vec ); + +/* + * Set the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathSoaT3SetRow( VmathSoaTransform3 *result, int row, const VmathSoaVector4 *vec ); + +/* + * Get the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathSoaT3GetCol( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm, int col ); + +/* + * Get the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathSoaT3GetRow( VmathSoaVector4 *result, const VmathSoaTransform3 *tfrm, int row ); + +/* + * Set the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline void vmathSoaT3SetElem( VmathSoaTransform3 *result, int col, int row, vec_float4 val ); + +/* + * Get the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline vec_float4 vmathSoaT3GetElem( const VmathSoaTransform3 *tfrm, int col, int row ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D vector + */ +static inline void vmathSoaT3MulV3( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm, const VmathSoaVector3 *vec ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D point + */ +static inline void vmathSoaT3MulP3( VmathSoaPoint3 *result, const VmathSoaTransform3 *tfrm, const VmathSoaPoint3 *pnt ); + +/* + * Multiply two 3x4 transformation matrices + */ +static inline void vmathSoaT3Mul( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm0, const VmathSoaTransform3 *tfrm1 ); + +/* + * Construct an identity 3x4 transformation matrix + */ +static inline void vmathSoaT3MakeIdentity( VmathSoaTransform3 *result ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x axis + */ +static inline void vmathSoaT3MakeRotationX( VmathSoaTransform3 *result, vec_float4 radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the y axis + */ +static inline void vmathSoaT3MakeRotationY( VmathSoaTransform3 *result, vec_float4 radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the z axis + */ +static inline void vmathSoaT3MakeRotationZ( VmathSoaTransform3 *result, vec_float4 radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + */ +static inline void vmathSoaT3MakeRotationZYX( VmathSoaTransform3 *result, const VmathSoaVector3 *radiansXYZ ); + +/* + * Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + */ +static inline void vmathSoaT3MakeRotationAxis( VmathSoaTransform3 *result, vec_float4 radians, const VmathSoaVector3 *unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline void vmathSoaT3MakeRotationQ( VmathSoaTransform3 *result, const VmathSoaQuat *unitQuat ); + +/* + * Construct a 3x4 transformation matrix to perform scaling + */ +static inline void vmathSoaT3MakeScale( VmathSoaTransform3 *result, const VmathSoaVector3 *scaleVec ); + +/* + * Construct a 3x4 transformation matrix to perform translation + */ +static inline void vmathSoaT3MakeTranslation( VmathSoaTransform3 *result, const VmathSoaVector3 *translateVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathSoaT3AppendScale( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm, const VmathSoaVector3 *scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathSoaT3PrependScale( VmathSoaTransform3 *result, const VmathSoaVector3 *scaleVec, const VmathSoaTransform3 *tfrm ); + +/* + * Multiply two 3x4 transformation matrices per element + */ +static inline void vmathSoaT3MulPerElem( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm0, const VmathSoaTransform3 *tfrm1 ); + +/* + * Compute the absolute value of a 3x4 transformation matrix per element + */ +static inline void vmathSoaT3AbsPerElem( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Inverse of a 3x4 transformation matrix + * NOTE: + * Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. + */ +static inline void vmathSoaT3Inverse( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. + */ +static inline void vmathSoaT3OrthoInverse( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Conditionally select between two 3x4 transformation matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathSoaT3Select( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm0, const VmathSoaTransform3 *tfrm1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x4 transformation matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaT3Print( const VmathSoaTransform3 *tfrm ); + +/* + * Print a 3x4 transformation matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaT3Prints( const VmathSoaTransform3 *tfrm, const char *name ); + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#include "vec_soa.h" +#include "quat_soa.h" +#include "mat_soa.h" + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/c/vectormath_soa_v.h b/Extras/vectormathlibrary/include/vectormath/ppu/c/vectormath_soa_v.h new file mode 100644 index 0000000..7a93c17 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/c/vectormath_soa_v.h @@ -0,0 +1,1979 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_SOA_C_V_PPU_H +#define _VECTORMATH_SOA_C_V_PPU_H + +#include +#include +#include "vectormath_aos_v.h" + +#ifdef _VECTORMATH_DEBUG +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef _VECTORMATH_SOA_C_TYPES_H +#define _VECTORMATH_SOA_C_TYPES_H + +/* A set of four 3-D vectors in structure-of-arrays format + */ +typedef struct _VmathSoaVector3 +{ + vec_float4 x; + vec_float4 y; + vec_float4 z; +} VmathSoaVector3; + +/* A set of four 4-D vectors in structure-of-arrays format + */ +typedef struct _VmathSoaVector4 +{ + vec_float4 x; + vec_float4 y; + vec_float4 z; + vec_float4 w; +} VmathSoaVector4; + +/* A set of four 3-D points in structure-of-arrays format + */ +typedef struct _VmathSoaPoint3 +{ + vec_float4 x; + vec_float4 y; + vec_float4 z; +} VmathSoaPoint3; + +/* A set of four quaternions in structure-of-arrays format + */ +typedef struct _VmathSoaQuat +{ + vec_float4 x; + vec_float4 y; + vec_float4 z; + vec_float4 w; +} VmathSoaQuat; + +/* A set of four 3x3 matrices in structure-of-arrays format + */ +typedef struct _VmathSoaMatrix3 +{ + VmathSoaVector3 col0; + VmathSoaVector3 col1; + VmathSoaVector3 col2; +} VmathSoaMatrix3; + +/* A set of four 4x4 matrices in structure-of-arrays format + */ +typedef struct _VmathSoaMatrix4 +{ + VmathSoaVector4 col0; + VmathSoaVector4 col1; + VmathSoaVector4 col2; + VmathSoaVector4 col3; +} VmathSoaMatrix4; + +/* A set of four 3x4 transformation matrices in structure-of-arrays format + */ +typedef struct _VmathSoaTransform3 +{ + VmathSoaVector3 col0; + VmathSoaVector3 col1; + VmathSoaVector3 col2; + VmathSoaVector3 col3; +} VmathSoaTransform3; + +#endif + +/* + * Construct a 3-D vector from x, y, and z elements + */ +static inline VmathSoaVector3 vmathSoaV3MakeFromElems_V( vec_float4 x, vec_float4 y, vec_float4 z ); + +/* + * Copy elements from a 3-D point into a 3-D vector + */ +static inline VmathSoaVector3 vmathSoaV3MakeFromP3_V( VmathSoaPoint3 pnt ); + +/* + * Set all elements of a 3-D vector to the same scalar value + */ +static inline VmathSoaVector3 vmathSoaV3MakeFromScalar_V( vec_float4 scalar ); + +/* + * Replicate an AoS 3-D vector + */ +static inline VmathSoaVector3 vmathSoaV3MakeFromAos_V( VmathVector3 vec ); + +/* + * Insert four AoS 3-D vectors + */ +static inline VmathSoaVector3 vmathSoaV3MakeFrom4Aos_V( VmathVector3 vec0, VmathVector3 vec1, VmathVector3 vec2, VmathVector3 vec3 ); + +/* + * Extract four AoS 3-D vectors + */ +static inline void vmathSoaV3Get4Aos_V( VmathSoaVector3 vec, VmathVector3 *result0, VmathVector3 *result1, VmathVector3 *result2, VmathVector3 *result3 ); + +/* + * Set the x element of a 3-D vector + */ +static inline void vmathSoaV3SetX_V( VmathSoaVector3 *result, vec_float4 x ); + +/* + * Set the y element of a 3-D vector + */ +static inline void vmathSoaV3SetY_V( VmathSoaVector3 *result, vec_float4 y ); + +/* + * Set the z element of a 3-D vector + */ +static inline void vmathSoaV3SetZ_V( VmathSoaVector3 *result, vec_float4 z ); + +/* + * Get the x element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3GetX_V( VmathSoaVector3 vec ); + +/* + * Get the y element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3GetY_V( VmathSoaVector3 vec ); + +/* + * Get the z element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3GetZ_V( VmathSoaVector3 vec ); + +/* + * Set an x, y, or z element of a 3-D vector by index + */ +static inline void vmathSoaV3SetElem_V( VmathSoaVector3 *result, int idx, vec_float4 value ); + +/* + * Get an x, y, or z element of a 3-D vector by index + */ +static inline vec_float4 vmathSoaV3GetElem_V( VmathSoaVector3 vec, int idx ); + +/* + * Add two 3-D vectors + */ +static inline VmathSoaVector3 vmathSoaV3Add_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Subtract a 3-D vector from another 3-D vector + */ +static inline VmathSoaVector3 vmathSoaV3Sub_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Add a 3-D vector to a 3-D point + */ +static inline VmathSoaPoint3 vmathSoaV3AddP3_V( VmathSoaVector3 vec, VmathSoaPoint3 pnt ); + +/* + * Multiply a 3-D vector by a scalar + */ +static inline VmathSoaVector3 vmathSoaV3ScalarMul_V( VmathSoaVector3 vec, vec_float4 scalar ); + +/* + * Divide a 3-D vector by a scalar + */ +static inline VmathSoaVector3 vmathSoaV3ScalarDiv_V( VmathSoaVector3 vec, vec_float4 scalar ); + +/* + * Negate all elements of a 3-D vector + */ +static inline VmathSoaVector3 vmathSoaV3Neg_V( VmathSoaVector3 vec ); + +/* + * Construct x axis + */ +static inline VmathSoaVector3 vmathSoaV3MakeXAxis_V( ); + +/* + * Construct y axis + */ +static inline VmathSoaVector3 vmathSoaV3MakeYAxis_V( ); + +/* + * Construct z axis + */ +static inline VmathSoaVector3 vmathSoaV3MakeZAxis_V( ); + +/* + * Multiply two 3-D vectors per element + */ +static inline VmathSoaVector3 vmathSoaV3MulPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Divide two 3-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline VmathSoaVector3 vmathSoaV3DivPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Compute the reciprocal of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline VmathSoaVector3 vmathSoaV3RecipPerElem_V( VmathSoaVector3 vec ); + +/* + * Compute the square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline VmathSoaVector3 vmathSoaV3SqrtPerElem_V( VmathSoaVector3 vec ); + +/* + * Compute the reciprocal square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline VmathSoaVector3 vmathSoaV3RsqrtPerElem_V( VmathSoaVector3 vec ); + +/* + * Compute the absolute value of a 3-D vector per element + */ +static inline VmathSoaVector3 vmathSoaV3AbsPerElem_V( VmathSoaVector3 vec ); + +/* + * Copy sign from one 3-D vector to another, per element + */ +static inline VmathSoaVector3 vmathSoaV3CopySignPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Maximum of two 3-D vectors per element + */ +static inline VmathSoaVector3 vmathSoaV3MaxPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Minimum of two 3-D vectors per element + */ +static inline VmathSoaVector3 vmathSoaV3MinPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Maximum element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3MaxElem_V( VmathSoaVector3 vec ); + +/* + * Minimum element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3MinElem_V( VmathSoaVector3 vec ); + +/* + * Compute the sum of all elements of a 3-D vector + */ +static inline vec_float4 vmathSoaV3Sum_V( VmathSoaVector3 vec ); + +/* + * Compute the dot product of two 3-D vectors + */ +static inline vec_float4 vmathSoaV3Dot_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Compute the square of the length of a 3-D vector + */ +static inline vec_float4 vmathSoaV3LengthSqr_V( VmathSoaVector3 vec ); + +/* + * Compute the length of a 3-D vector + */ +static inline vec_float4 vmathSoaV3Length_V( VmathSoaVector3 vec ); + +/* + * Normalize a 3-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline VmathSoaVector3 vmathSoaV3Normalize_V( VmathSoaVector3 vec ); + +/* + * Compute cross product of two 3-D vectors + */ +static inline VmathSoaVector3 vmathSoaV3Cross_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Outer product of two 3-D vectors + */ +static inline VmathSoaMatrix3 vmathSoaV3Outer_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Pre-multiply a row vector by a 3x3 matrix + */ +static inline VmathSoaVector3 vmathSoaV3RowMul_V( VmathSoaVector3 vec, VmathSoaMatrix3 mat ); + +/* + * Cross-product matrix of a 3-D vector + */ +static inline VmathSoaMatrix3 vmathSoaV3CrossMatrix_V( VmathSoaVector3 vec ); + +/* + * Create cross-product matrix and multiply + * NOTE: + * Faster than separately creating a cross-product matrix and multiplying. + */ +static inline VmathSoaMatrix3 vmathSoaV3CrossMatrixMul_V( VmathSoaVector3 vec, VmathSoaMatrix3 mat ); + +/* + * Linear interpolation between two 3-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathSoaVector3 vmathSoaV3Lerp_V( vec_float4 t, VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Spherical linear interpolation between two 3-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline VmathSoaVector3 vmathSoaV3Slerp_V( vec_float4 t, VmathSoaVector3 unitVec0, VmathSoaVector3 unitVec1 ); + +/* + * Conditionally select between two 3-D vectors + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathSoaVector3 vmathSoaV3Select_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1, vec_uint4 select1 ); + +/* + * Load four three-float 3-D vectors, stored in three quadwords + */ +static inline void vmathSoaV3LoadXYZArray_V( VmathSoaVector3 *vec, const vec_float4 *threeQuads ); + +/* + * Store four slots of an SoA 3-D vector in three quadwords + */ +static inline void vmathSoaV3StoreXYZArray_V( VmathSoaVector3 vec, vec_float4 *threeQuads ); + +/* + * Store eight slots of two SoA 3-D vectors as half-floats + */ +static inline void vmathSoaV3StoreHalfFloats_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1, vec_ushort8 *threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaV3Print_V( VmathSoaVector3 vec ); + +/* + * Print a 3-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaV3Prints_V( VmathSoaVector3 vec, const char *name ); + +#endif + +/* + * Construct a 4-D vector from x, y, z, and w elements + */ +static inline VmathSoaVector4 vmathSoaV4MakeFromElems_V( vec_float4 x, vec_float4 y, vec_float4 z, vec_float4 w ); + +/* + * Construct a 4-D vector from a 3-D vector and a scalar + */ +static inline VmathSoaVector4 vmathSoaV4MakeFromV3Scalar_V( VmathSoaVector3 xyz, vec_float4 w ); + +/* + * Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + */ +static inline VmathSoaVector4 vmathSoaV4MakeFromV3_V( VmathSoaVector3 vec ); + +/* + * Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + */ +static inline VmathSoaVector4 vmathSoaV4MakeFromP3_V( VmathSoaPoint3 pnt ); + +/* + * Copy elements from a quaternion into a 4-D vector + */ +static inline VmathSoaVector4 vmathSoaV4MakeFromQ_V( VmathSoaQuat quat ); + +/* + * Set all elements of a 4-D vector to the same scalar value + */ +static inline VmathSoaVector4 vmathSoaV4MakeFromScalar_V( vec_float4 scalar ); + +/* + * Replicate an AoS 4-D vector + */ +static inline VmathSoaVector4 vmathSoaV4MakeFromAos_V( VmathVector4 vec ); + +/* + * Insert four AoS 4-D vectors + */ +static inline VmathSoaVector4 vmathSoaV4MakeFrom4Aos_V( VmathVector4 vec0, VmathVector4 vec1, VmathVector4 vec2, VmathVector4 vec3 ); + +/* + * Extract four AoS 4-D vectors + */ +static inline void vmathSoaV4Get4Aos_V( VmathSoaVector4 vec, VmathVector4 *result0, VmathVector4 *result1, VmathVector4 *result2, VmathVector4 *result3 ); + +/* + * Set the x, y, and z elements of a 4-D vector + * NOTE: + * This function does not change the w element. + */ +static inline void vmathSoaV4SetXYZ_V( VmathSoaVector4 *result, VmathSoaVector3 vec ); + +/* + * Get the x, y, and z elements of a 4-D vector + */ +static inline VmathSoaVector3 vmathSoaV4GetXYZ_V( VmathSoaVector4 vec ); + +/* + * Set the x element of a 4-D vector + */ +static inline void vmathSoaV4SetX_V( VmathSoaVector4 *result, vec_float4 x ); + +/* + * Set the y element of a 4-D vector + */ +static inline void vmathSoaV4SetY_V( VmathSoaVector4 *result, vec_float4 y ); + +/* + * Set the z element of a 4-D vector + */ +static inline void vmathSoaV4SetZ_V( VmathSoaVector4 *result, vec_float4 z ); + +/* + * Set the w element of a 4-D vector + */ +static inline void vmathSoaV4SetW_V( VmathSoaVector4 *result, vec_float4 w ); + +/* + * Get the x element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4GetX_V( VmathSoaVector4 vec ); + +/* + * Get the y element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4GetY_V( VmathSoaVector4 vec ); + +/* + * Get the z element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4GetZ_V( VmathSoaVector4 vec ); + +/* + * Get the w element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4GetW_V( VmathSoaVector4 vec ); + +/* + * Set an x, y, z, or w element of a 4-D vector by index + */ +static inline void vmathSoaV4SetElem_V( VmathSoaVector4 *result, int idx, vec_float4 value ); + +/* + * Get an x, y, z, or w element of a 4-D vector by index + */ +static inline vec_float4 vmathSoaV4GetElem_V( VmathSoaVector4 vec, int idx ); + +/* + * Add two 4-D vectors + */ +static inline VmathSoaVector4 vmathSoaV4Add_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Subtract a 4-D vector from another 4-D vector + */ +static inline VmathSoaVector4 vmathSoaV4Sub_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Multiply a 4-D vector by a scalar + */ +static inline VmathSoaVector4 vmathSoaV4ScalarMul_V( VmathSoaVector4 vec, vec_float4 scalar ); + +/* + * Divide a 4-D vector by a scalar + */ +static inline VmathSoaVector4 vmathSoaV4ScalarDiv_V( VmathSoaVector4 vec, vec_float4 scalar ); + +/* + * Negate all elements of a 4-D vector + */ +static inline VmathSoaVector4 vmathSoaV4Neg_V( VmathSoaVector4 vec ); + +/* + * Construct x axis + */ +static inline VmathSoaVector4 vmathSoaV4MakeXAxis_V( ); + +/* + * Construct y axis + */ +static inline VmathSoaVector4 vmathSoaV4MakeYAxis_V( ); + +/* + * Construct z axis + */ +static inline VmathSoaVector4 vmathSoaV4MakeZAxis_V( ); + +/* + * Construct w axis + */ +static inline VmathSoaVector4 vmathSoaV4MakeWAxis_V( ); + +/* + * Multiply two 4-D vectors per element + */ +static inline VmathSoaVector4 vmathSoaV4MulPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Divide two 4-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline VmathSoaVector4 vmathSoaV4DivPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Compute the reciprocal of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline VmathSoaVector4 vmathSoaV4RecipPerElem_V( VmathSoaVector4 vec ); + +/* + * Compute the square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline VmathSoaVector4 vmathSoaV4SqrtPerElem_V( VmathSoaVector4 vec ); + +/* + * Compute the reciprocal square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline VmathSoaVector4 vmathSoaV4RsqrtPerElem_V( VmathSoaVector4 vec ); + +/* + * Compute the absolute value of a 4-D vector per element + */ +static inline VmathSoaVector4 vmathSoaV4AbsPerElem_V( VmathSoaVector4 vec ); + +/* + * Copy sign from one 4-D vector to another, per element + */ +static inline VmathSoaVector4 vmathSoaV4CopySignPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Maximum of two 4-D vectors per element + */ +static inline VmathSoaVector4 vmathSoaV4MaxPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Minimum of two 4-D vectors per element + */ +static inline VmathSoaVector4 vmathSoaV4MinPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Maximum element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4MaxElem_V( VmathSoaVector4 vec ); + +/* + * Minimum element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4MinElem_V( VmathSoaVector4 vec ); + +/* + * Compute the sum of all elements of a 4-D vector + */ +static inline vec_float4 vmathSoaV4Sum_V( VmathSoaVector4 vec ); + +/* + * Compute the dot product of two 4-D vectors + */ +static inline vec_float4 vmathSoaV4Dot_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Compute the square of the length of a 4-D vector + */ +static inline vec_float4 vmathSoaV4LengthSqr_V( VmathSoaVector4 vec ); + +/* + * Compute the length of a 4-D vector + */ +static inline vec_float4 vmathSoaV4Length_V( VmathSoaVector4 vec ); + +/* + * Normalize a 4-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline VmathSoaVector4 vmathSoaV4Normalize_V( VmathSoaVector4 vec ); + +/* + * Outer product of two 4-D vectors + */ +static inline VmathSoaMatrix4 vmathSoaV4Outer_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Linear interpolation between two 4-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathSoaVector4 vmathSoaV4Lerp_V( vec_float4 t, VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Spherical linear interpolation between two 4-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline VmathSoaVector4 vmathSoaV4Slerp_V( vec_float4 t, VmathSoaVector4 unitVec0, VmathSoaVector4 unitVec1 ); + +/* + * Conditionally select between two 4-D vectors + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathSoaVector4 vmathSoaV4Select_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1, vec_uint4 select1 ); + +/* + * Store four slots of an SoA 4-D vector as half-floats + */ +static inline void vmathSoaV4StoreHalfFloats_V( VmathSoaVector4 vec, vec_ushort8 *twoQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaV4Print_V( VmathSoaVector4 vec ); + +/* + * Print a 4-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaV4Prints_V( VmathSoaVector4 vec, const char *name ); + +#endif + +/* + * Construct a 3-D point from x, y, and z elements + */ +static inline VmathSoaPoint3 vmathSoaP3MakeFromElems_V( vec_float4 x, vec_float4 y, vec_float4 z ); + +/* + * Copy elements from a 3-D vector into a 3-D point + */ +static inline VmathSoaPoint3 vmathSoaP3MakeFromV3_V( VmathSoaVector3 vec ); + +/* + * Set all elements of a 3-D point to the same scalar value + */ +static inline VmathSoaPoint3 vmathSoaP3MakeFromScalar_V( vec_float4 scalar ); + +/* + * Replicate an AoS 3-D point + */ +static inline VmathSoaPoint3 vmathSoaP3MakeFromAos_V( VmathPoint3 pnt ); + +/* + * Insert four AoS 3-D points + */ +static inline VmathSoaPoint3 vmathSoaP3MakeFrom4Aos_V( VmathPoint3 pnt0, VmathPoint3 pnt1, VmathPoint3 pnt2, VmathPoint3 pnt3 ); + +/* + * Extract four AoS 3-D points + */ +static inline void vmathSoaP3Get4Aos_V( VmathSoaPoint3 pnt, VmathPoint3 *result0, VmathPoint3 *result1, VmathPoint3 *result2, VmathPoint3 *result3 ); + +/* + * Set the x element of a 3-D point + */ +static inline void vmathSoaP3SetX_V( VmathSoaPoint3 *result, vec_float4 x ); + +/* + * Set the y element of a 3-D point + */ +static inline void vmathSoaP3SetY_V( VmathSoaPoint3 *result, vec_float4 y ); + +/* + * Set the z element of a 3-D point + */ +static inline void vmathSoaP3SetZ_V( VmathSoaPoint3 *result, vec_float4 z ); + +/* + * Get the x element of a 3-D point + */ +static inline vec_float4 vmathSoaP3GetX_V( VmathSoaPoint3 pnt ); + +/* + * Get the y element of a 3-D point + */ +static inline vec_float4 vmathSoaP3GetY_V( VmathSoaPoint3 pnt ); + +/* + * Get the z element of a 3-D point + */ +static inline vec_float4 vmathSoaP3GetZ_V( VmathSoaPoint3 pnt ); + +/* + * Set an x, y, or z element of a 3-D point by index + */ +static inline void vmathSoaP3SetElem_V( VmathSoaPoint3 *result, int idx, vec_float4 value ); + +/* + * Get an x, y, or z element of a 3-D point by index + */ +static inline vec_float4 vmathSoaP3GetElem_V( VmathSoaPoint3 pnt, int idx ); + +/* + * Subtract a 3-D point from another 3-D point + */ +static inline VmathSoaVector3 vmathSoaP3Sub_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Add a 3-D point to a 3-D vector + */ +static inline VmathSoaPoint3 vmathSoaP3AddV3_V( VmathSoaPoint3 pnt, VmathSoaVector3 vec ); + +/* + * Subtract a 3-D vector from a 3-D point + */ +static inline VmathSoaPoint3 vmathSoaP3SubV3_V( VmathSoaPoint3 pnt, VmathSoaVector3 vec ); + +/* + * Multiply two 3-D points per element + */ +static inline VmathSoaPoint3 vmathSoaP3MulPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Divide two 3-D points per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline VmathSoaPoint3 vmathSoaP3DivPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Compute the reciprocal of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline VmathSoaPoint3 vmathSoaP3RecipPerElem_V( VmathSoaPoint3 pnt ); + +/* + * Compute the square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline VmathSoaPoint3 vmathSoaP3SqrtPerElem_V( VmathSoaPoint3 pnt ); + +/* + * Compute the reciprocal square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline VmathSoaPoint3 vmathSoaP3RsqrtPerElem_V( VmathSoaPoint3 pnt ); + +/* + * Compute the absolute value of a 3-D point per element + */ +static inline VmathSoaPoint3 vmathSoaP3AbsPerElem_V( VmathSoaPoint3 pnt ); + +/* + * Copy sign from one 3-D point to another, per element + */ +static inline VmathSoaPoint3 vmathSoaP3CopySignPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Maximum of two 3-D points per element + */ +static inline VmathSoaPoint3 vmathSoaP3MaxPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Minimum of two 3-D points per element + */ +static inline VmathSoaPoint3 vmathSoaP3MinPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Maximum element of a 3-D point + */ +static inline vec_float4 vmathSoaP3MaxElem_V( VmathSoaPoint3 pnt ); + +/* + * Minimum element of a 3-D point + */ +static inline vec_float4 vmathSoaP3MinElem_V( VmathSoaPoint3 pnt ); + +/* + * Compute the sum of all elements of a 3-D point + */ +static inline vec_float4 vmathSoaP3Sum_V( VmathSoaPoint3 pnt ); + +/* + * Apply uniform scale to a 3-D point + */ +static inline VmathSoaPoint3 vmathSoaP3Scale_V( VmathSoaPoint3 pnt, vec_float4 scaleVal ); + +/* + * Apply non-uniform scale to a 3-D point + */ +static inline VmathSoaPoint3 vmathSoaP3NonUniformScale_V( VmathSoaPoint3 pnt, VmathSoaVector3 scaleVec ); + +/* + * Scalar projection of a 3-D point on a unit-length 3-D vector + */ +static inline vec_float4 vmathSoaP3Projection_V( VmathSoaPoint3 pnt, VmathSoaVector3 unitVec ); + +/* + * Compute the square of the distance of a 3-D point from the coordinate-system origin + */ +static inline vec_float4 vmathSoaP3DistSqrFromOrigin_V( VmathSoaPoint3 pnt ); + +/* + * Compute the distance of a 3-D point from the coordinate-system origin + */ +static inline vec_float4 vmathSoaP3DistFromOrigin_V( VmathSoaPoint3 pnt ); + +/* + * Compute the square of the distance between two 3-D points + */ +static inline vec_float4 vmathSoaP3DistSqr_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Compute the distance between two 3-D points + */ +static inline vec_float4 vmathSoaP3Dist_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Linear interpolation between two 3-D points + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathSoaPoint3 vmathSoaP3Lerp_V( vec_float4 t, VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Conditionally select between two 3-D points + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathSoaPoint3 vmathSoaP3Select_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1, vec_uint4 select1 ); + +/* + * Load four three-float 3-D points, stored in three quadwords + */ +static inline void vmathSoaP3LoadXYZArray_V( VmathSoaPoint3 *pnt, const vec_float4 *threeQuads ); + +/* + * Store four slots of an SoA 3-D point in three quadwords + */ +static inline void vmathSoaP3StoreXYZArray_V( VmathSoaPoint3 pnt, vec_float4 *threeQuads ); + +/* + * Store eight slots of two SoA 3-D points as half-floats + */ +static inline void vmathSoaP3StoreHalfFloats_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1, vec_ushort8 *threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D point + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaP3Print_V( VmathSoaPoint3 pnt ); + +/* + * Print a 3-D point and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaP3Prints_V( VmathSoaPoint3 pnt, const char *name ); + +#endif + +/* + * Construct a quaternion from x, y, z, and w elements + */ +static inline VmathSoaQuat vmathSoaQMakeFromElems_V( vec_float4 x, vec_float4 y, vec_float4 z, vec_float4 w ); + +/* + * Construct a quaternion from a 3-D vector and a scalar + */ +static inline VmathSoaQuat vmathSoaQMakeFromV3Scalar_V( VmathSoaVector3 xyz, vec_float4 w ); + +/* + * Copy elements from a 4-D vector into a quaternion + */ +static inline VmathSoaQuat vmathSoaQMakeFromV4_V( VmathSoaVector4 vec ); + +/* + * Convert a rotation matrix to a unit-length quaternion + */ +static inline VmathSoaQuat vmathSoaQMakeFromM3_V( VmathSoaMatrix3 rotMat ); + +/* + * Set all elements of a quaternion to the same scalar value + */ +static inline VmathSoaQuat vmathSoaQMakeFromScalar_V( vec_float4 scalar ); + +/* + * Replicate an AoS quaternion + */ +static inline VmathSoaQuat vmathSoaQMakeFromAos_V( VmathQuat quat ); + +/* + * Insert four AoS quaternions + */ +static inline VmathSoaQuat vmathSoaQMakeFrom4Aos_V( VmathQuat quat0, VmathQuat quat1, VmathQuat quat2, VmathQuat quat3 ); + +/* + * Extract four AoS quaternions + */ +static inline void vmathSoaQGet4Aos_V( VmathSoaQuat quat, VmathQuat *result0, VmathQuat *result1, VmathQuat *result2, VmathQuat *result3 ); + +/* + * Set the x, y, and z elements of a quaternion + * NOTE: + * This function does not change the w element. + */ +static inline void vmathSoaQSetXYZ_V( VmathSoaQuat *result, VmathSoaVector3 vec ); + +/* + * Get the x, y, and z elements of a quaternion + */ +static inline VmathSoaVector3 vmathSoaQGetXYZ_V( VmathSoaQuat quat ); + +/* + * Set the x element of a quaternion + */ +static inline void vmathSoaQSetX_V( VmathSoaQuat *result, vec_float4 x ); + +/* + * Set the y element of a quaternion + */ +static inline void vmathSoaQSetY_V( VmathSoaQuat *result, vec_float4 y ); + +/* + * Set the z element of a quaternion + */ +static inline void vmathSoaQSetZ_V( VmathSoaQuat *result, vec_float4 z ); + +/* + * Set the w element of a quaternion + */ +static inline void vmathSoaQSetW_V( VmathSoaQuat *result, vec_float4 w ); + +/* + * Get the x element of a quaternion + */ +static inline vec_float4 vmathSoaQGetX_V( VmathSoaQuat quat ); + +/* + * Get the y element of a quaternion + */ +static inline vec_float4 vmathSoaQGetY_V( VmathSoaQuat quat ); + +/* + * Get the z element of a quaternion + */ +static inline vec_float4 vmathSoaQGetZ_V( VmathSoaQuat quat ); + +/* + * Get the w element of a quaternion + */ +static inline vec_float4 vmathSoaQGetW_V( VmathSoaQuat quat ); + +/* + * Set an x, y, z, or w element of a quaternion by index + */ +static inline void vmathSoaQSetElem_V( VmathSoaQuat *result, int idx, vec_float4 value ); + +/* + * Get an x, y, z, or w element of a quaternion by index + */ +static inline vec_float4 vmathSoaQGetElem_V( VmathSoaQuat quat, int idx ); + +/* + * Add two quaternions + */ +static inline VmathSoaQuat vmathSoaQAdd_V( VmathSoaQuat quat0, VmathSoaQuat quat1 ); + +/* + * Subtract a quaternion from another quaternion + */ +static inline VmathSoaQuat vmathSoaQSub_V( VmathSoaQuat quat0, VmathSoaQuat quat1 ); + +/* + * Multiply two quaternions + */ +static inline VmathSoaQuat vmathSoaQMul_V( VmathSoaQuat quat0, VmathSoaQuat quat1 ); + +/* + * Multiply a quaternion by a scalar + */ +static inline VmathSoaQuat vmathSoaQScalarMul_V( VmathSoaQuat quat, vec_float4 scalar ); + +/* + * Divide a quaternion by a scalar + */ +static inline VmathSoaQuat vmathSoaQScalarDiv_V( VmathSoaQuat quat, vec_float4 scalar ); + +/* + * Negate all elements of a quaternion + */ +static inline VmathSoaQuat vmathSoaQNeg_V( VmathSoaQuat quat ); + +/* + * Construct an identity quaternion + */ +static inline VmathSoaQuat vmathSoaQMakeIdentity_V( ); + +/* + * Construct a quaternion to rotate between two unit-length 3-D vectors + * NOTE: + * The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + */ +static inline VmathSoaQuat vmathSoaQMakeRotationArc_V( VmathSoaVector3 unitVec0, VmathSoaVector3 unitVec1 ); + +/* + * Construct a quaternion to rotate around a unit-length 3-D vector + */ +static inline VmathSoaQuat vmathSoaQMakeRotationAxis_V( vec_float4 radians, VmathSoaVector3 unitVec ); + +/* + * Construct a quaternion to rotate around the x axis + */ +static inline VmathSoaQuat vmathSoaQMakeRotationX_V( vec_float4 radians ); + +/* + * Construct a quaternion to rotate around the y axis + */ +static inline VmathSoaQuat vmathSoaQMakeRotationY_V( vec_float4 radians ); + +/* + * Construct a quaternion to rotate around the z axis + */ +static inline VmathSoaQuat vmathSoaQMakeRotationZ_V( vec_float4 radians ); + +/* + * Compute the conjugate of a quaternion + */ +static inline VmathSoaQuat vmathSoaQConj_V( VmathSoaQuat quat ); + +/* + * Use a unit-length quaternion to rotate a 3-D vector + */ +static inline VmathSoaVector3 vmathSoaQRotate_V( VmathSoaQuat unitQuat, VmathSoaVector3 vec ); + +/* + * Compute the dot product of two quaternions + */ +static inline vec_float4 vmathSoaQDot_V( VmathSoaQuat quat0, VmathSoaQuat quat1 ); + +/* + * Compute the norm of a quaternion + */ +static inline vec_float4 vmathSoaQNorm_V( VmathSoaQuat quat ); + +/* + * Compute the length of a quaternion + */ +static inline vec_float4 vmathSoaQLength_V( VmathSoaQuat quat ); + +/* + * Normalize a quaternion + * NOTE: + * The result is unpredictable when all elements of quat are at or near zero. + */ +static inline VmathSoaQuat vmathSoaQNormalize_V( VmathSoaQuat quat ); + +/* + * Linear interpolation between two quaternions + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathSoaQuat vmathSoaQLerp_V( vec_float4 t, VmathSoaQuat quat0, VmathSoaQuat quat1 ); + +/* + * Spherical linear interpolation between two quaternions + * NOTE: + * Interpolates along the shortest path between orientations. + * Does not clamp t between 0 and 1. + */ +static inline VmathSoaQuat vmathSoaQSlerp_V( vec_float4 t, VmathSoaQuat unitQuat0, VmathSoaQuat unitQuat1 ); + +/* + * Spherical quadrangle interpolation + */ +static inline VmathSoaQuat vmathSoaQSquad_V( vec_float4 t, VmathSoaQuat unitQuat0, VmathSoaQuat unitQuat1, VmathSoaQuat unitQuat2, VmathSoaQuat unitQuat3 ); + +/* + * Conditionally select between two quaternions + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathSoaQuat vmathSoaQSelect_V( VmathSoaQuat quat0, VmathSoaQuat quat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a quaternion + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaQPrint_V( VmathSoaQuat quat ); + +/* + * Print a quaternion and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaQPrints_V( VmathSoaQuat quat, const char *name ); + +#endif + +/* + * Construct a 3x3 matrix containing the specified columns + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeFromCols_V( VmathSoaVector3 col0, VmathSoaVector3 col1, VmathSoaVector3 col2 ); + +/* + * Construct a 3x3 rotation matrix from a unit-length quaternion + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeFromQ_V( VmathSoaQuat unitQuat ); + +/* + * Set all elements of a 3x3 matrix to the same scalar value + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeFromScalar_V( vec_float4 scalar ); + +/* + * Replicate an AoS 3x3 matrix + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeFromAos_V( VmathMatrix3 mat ); + +/* + * Insert four AoS 3x3 matrices + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeFrom4Aos_V( VmathMatrix3 mat0, VmathMatrix3 mat1, VmathMatrix3 mat2, VmathMatrix3 mat3 ); + +/* + * Extract four AoS 3x3 matrices + */ +static inline void vmathSoaM3Get4Aos_V( VmathSoaMatrix3 mat, VmathMatrix3 *result0, VmathMatrix3 *result1, VmathMatrix3 *result2, VmathMatrix3 *result3 ); + +/* + * Set column 0 of a 3x3 matrix + */ +static inline void vmathSoaM3SetCol0_V( VmathSoaMatrix3 *result, VmathSoaVector3 col0 ); + +/* + * Set column 1 of a 3x3 matrix + */ +static inline void vmathSoaM3SetCol1_V( VmathSoaMatrix3 *result, VmathSoaVector3 col1 ); + +/* + * Set column 2 of a 3x3 matrix + */ +static inline void vmathSoaM3SetCol2_V( VmathSoaMatrix3 *result, VmathSoaVector3 col2 ); + +/* + * Get column 0 of a 3x3 matrix + */ +static inline VmathSoaVector3 vmathSoaM3GetCol0_V( VmathSoaMatrix3 mat ); + +/* + * Get column 1 of a 3x3 matrix + */ +static inline VmathSoaVector3 vmathSoaM3GetCol1_V( VmathSoaMatrix3 mat ); + +/* + * Get column 2 of a 3x3 matrix + */ +static inline VmathSoaVector3 vmathSoaM3GetCol2_V( VmathSoaMatrix3 mat ); + +/* + * Set the column of a 3x3 matrix referred to by the specified index + */ +static inline void vmathSoaM3SetCol_V( VmathSoaMatrix3 *result, int col, VmathSoaVector3 vec ); + +/* + * Set the row of a 3x3 matrix referred to by the specified index + */ +static inline void vmathSoaM3SetRow_V( VmathSoaMatrix3 *result, int row, VmathSoaVector3 vec ); + +/* + * Get the column of a 3x3 matrix referred to by the specified index + */ +static inline VmathSoaVector3 vmathSoaM3GetCol_V( VmathSoaMatrix3 mat, int col ); + +/* + * Get the row of a 3x3 matrix referred to by the specified index + */ +static inline VmathSoaVector3 vmathSoaM3GetRow_V( VmathSoaMatrix3 mat, int row ); + +/* + * Set the element of a 3x3 matrix referred to by column and row indices + */ +static inline void vmathSoaM3SetElem_V( VmathSoaMatrix3 *result, int col, int row, vec_float4 val ); + +/* + * Get the element of a 3x3 matrix referred to by column and row indices + */ +static inline vec_float4 vmathSoaM3GetElem_V( VmathSoaMatrix3 mat, int col, int row ); + +/* + * Add two 3x3 matrices + */ +static inline VmathSoaMatrix3 vmathSoaM3Add_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1 ); + +/* + * Subtract a 3x3 matrix from another 3x3 matrix + */ +static inline VmathSoaMatrix3 vmathSoaM3Sub_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1 ); + +/* + * Negate all elements of a 3x3 matrix + */ +static inline VmathSoaMatrix3 vmathSoaM3Neg_V( VmathSoaMatrix3 mat ); + +/* + * Multiply a 3x3 matrix by a scalar + */ +static inline VmathSoaMatrix3 vmathSoaM3ScalarMul_V( VmathSoaMatrix3 mat, vec_float4 scalar ); + +/* + * Multiply a 3x3 matrix by a 3-D vector + */ +static inline VmathSoaVector3 vmathSoaM3MulV3_V( VmathSoaMatrix3 mat, VmathSoaVector3 vec ); + +/* + * Multiply two 3x3 matrices + */ +static inline VmathSoaMatrix3 vmathSoaM3Mul_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1 ); + +/* + * Construct an identity 3x3 matrix + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeIdentity_V( ); + +/* + * Construct a 3x3 matrix to rotate around the x axis + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationX_V( vec_float4 radians ); + +/* + * Construct a 3x3 matrix to rotate around the y axis + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationY_V( vec_float4 radians ); + +/* + * Construct a 3x3 matrix to rotate around the z axis + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationZ_V( vec_float4 radians ); + +/* + * Construct a 3x3 matrix to rotate around the x, y, and z axes + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationZYX_V( VmathSoaVector3 radiansXYZ ); + +/* + * Construct a 3x3 matrix to rotate around a unit-length 3-D vector + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationAxis_V( vec_float4 radians, VmathSoaVector3 unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationQ_V( VmathSoaQuat unitQuat ); + +/* + * Construct a 3x3 matrix to perform scaling + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeScale_V( VmathSoaVector3 scaleVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathSoaMatrix3 vmathSoaM3AppendScale_V( VmathSoaMatrix3 mat, VmathSoaVector3 scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathSoaMatrix3 vmathSoaM3PrependScale_V( VmathSoaVector3 scaleVec, VmathSoaMatrix3 mat ); + +/* + * Multiply two 3x3 matrices per element + */ +static inline VmathSoaMatrix3 vmathSoaM3MulPerElem_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1 ); + +/* + * Compute the absolute value of a 3x3 matrix per element + */ +static inline VmathSoaMatrix3 vmathSoaM3AbsPerElem_V( VmathSoaMatrix3 mat ); + +/* + * Transpose of a 3x3 matrix + */ +static inline VmathSoaMatrix3 vmathSoaM3Transpose_V( VmathSoaMatrix3 mat ); + +/* + * Compute the inverse of a 3x3 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline VmathSoaMatrix3 vmathSoaM3Inverse_V( VmathSoaMatrix3 mat ); + +/* + * Determinant of a 3x3 matrix + */ +static inline vec_float4 vmathSoaM3Determinant_V( VmathSoaMatrix3 mat ); + +/* + * Conditionally select between two 3x3 matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathSoaMatrix3 vmathSoaM3Select_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x3 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaM3Print_V( VmathSoaMatrix3 mat ); + +/* + * Print a 3x3 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaM3Prints_V( VmathSoaMatrix3 mat, const char *name ); + +#endif + +/* + * Construct a 4x4 matrix containing the specified columns + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeFromCols_V( VmathSoaVector4 col0, VmathSoaVector4 col1, VmathSoaVector4 col2, VmathSoaVector4 col3 ); + +/* + * Construct a 4x4 matrix from a 3x4 transformation matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeFromT3_V( VmathSoaTransform3 mat ); + +/* + * Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeFromM3V3_V( VmathSoaMatrix3 mat, VmathSoaVector3 translateVec ); + +/* + * Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeFromQV3_V( VmathSoaQuat unitQuat, VmathSoaVector3 translateVec ); + +/* + * Set all elements of a 4x4 matrix to the same scalar value + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeFromScalar_V( vec_float4 scalar ); + +/* + * Replicate an AoS 4x4 matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeFromAos_V( VmathMatrix4 mat ); + +/* + * Insert four AoS 4x4 matrices + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeFrom4Aos_V( VmathMatrix4 mat0, VmathMatrix4 mat1, VmathMatrix4 mat2, VmathMatrix4 mat3 ); + +/* + * Extract four AoS 4x4 matrices + */ +static inline void vmathSoaM4Get4Aos_V( VmathSoaMatrix4 mat, VmathMatrix4 *result0, VmathMatrix4 *result1, VmathMatrix4 *result2, VmathMatrix4 *result3 ); + +/* + * Set the upper-left 3x3 submatrix + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathSoaM4SetUpper3x3_V( VmathSoaMatrix4 *result, VmathSoaMatrix3 mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 4x4 matrix + */ +static inline VmathSoaMatrix3 vmathSoaM4GetUpper3x3_V( VmathSoaMatrix4 mat ); + +/* + * Set translation component + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathSoaM4SetTranslation_V( VmathSoaMatrix4 *result, VmathSoaVector3 translateVec ); + +/* + * Get the translation component of a 4x4 matrix + */ +static inline VmathSoaVector3 vmathSoaM4GetTranslation_V( VmathSoaMatrix4 mat ); + +/* + * Set column 0 of a 4x4 matrix + */ +static inline void vmathSoaM4SetCol0_V( VmathSoaMatrix4 *result, VmathSoaVector4 col0 ); + +/* + * Set column 1 of a 4x4 matrix + */ +static inline void vmathSoaM4SetCol1_V( VmathSoaMatrix4 *result, VmathSoaVector4 col1 ); + +/* + * Set column 2 of a 4x4 matrix + */ +static inline void vmathSoaM4SetCol2_V( VmathSoaMatrix4 *result, VmathSoaVector4 col2 ); + +/* + * Set column 3 of a 4x4 matrix + */ +static inline void vmathSoaM4SetCol3_V( VmathSoaMatrix4 *result, VmathSoaVector4 col3 ); + +/* + * Get column 0 of a 4x4 matrix + */ +static inline VmathSoaVector4 vmathSoaM4GetCol0_V( VmathSoaMatrix4 mat ); + +/* + * Get column 1 of a 4x4 matrix + */ +static inline VmathSoaVector4 vmathSoaM4GetCol1_V( VmathSoaMatrix4 mat ); + +/* + * Get column 2 of a 4x4 matrix + */ +static inline VmathSoaVector4 vmathSoaM4GetCol2_V( VmathSoaMatrix4 mat ); + +/* + * Get column 3 of a 4x4 matrix + */ +static inline VmathSoaVector4 vmathSoaM4GetCol3_V( VmathSoaMatrix4 mat ); + +/* + * Set the column of a 4x4 matrix referred to by the specified index + */ +static inline void vmathSoaM4SetCol_V( VmathSoaMatrix4 *result, int col, VmathSoaVector4 vec ); + +/* + * Set the row of a 4x4 matrix referred to by the specified index + */ +static inline void vmathSoaM4SetRow_V( VmathSoaMatrix4 *result, int row, VmathSoaVector4 vec ); + +/* + * Get the column of a 4x4 matrix referred to by the specified index + */ +static inline VmathSoaVector4 vmathSoaM4GetCol_V( VmathSoaMatrix4 mat, int col ); + +/* + * Get the row of a 4x4 matrix referred to by the specified index + */ +static inline VmathSoaVector4 vmathSoaM4GetRow_V( VmathSoaMatrix4 mat, int row ); + +/* + * Set the element of a 4x4 matrix referred to by column and row indices + */ +static inline void vmathSoaM4SetElem_V( VmathSoaMatrix4 *result, int col, int row, vec_float4 val ); + +/* + * Get the element of a 4x4 matrix referred to by column and row indices + */ +static inline vec_float4 vmathSoaM4GetElem_V( VmathSoaMatrix4 mat, int col, int row ); + +/* + * Add two 4x4 matrices + */ +static inline VmathSoaMatrix4 vmathSoaM4Add_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1 ); + +/* + * Subtract a 4x4 matrix from another 4x4 matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4Sub_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1 ); + +/* + * Negate all elements of a 4x4 matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4Neg_V( VmathSoaMatrix4 mat ); + +/* + * Multiply a 4x4 matrix by a scalar + */ +static inline VmathSoaMatrix4 vmathSoaM4ScalarMul_V( VmathSoaMatrix4 mat, vec_float4 scalar ); + +/* + * Multiply a 4x4 matrix by a 4-D vector + */ +static inline VmathSoaVector4 vmathSoaM4MulV4_V( VmathSoaMatrix4 mat, VmathSoaVector4 vec ); + +/* + * Multiply a 4x4 matrix by a 3-D vector + */ +static inline VmathSoaVector4 vmathSoaM4MulV3_V( VmathSoaMatrix4 mat, VmathSoaVector3 vec ); + +/* + * Multiply a 4x4 matrix by a 3-D point + */ +static inline VmathSoaVector4 vmathSoaM4MulP3_V( VmathSoaMatrix4 mat, VmathSoaPoint3 pnt ); + +/* + * Multiply two 4x4 matrices + */ +static inline VmathSoaMatrix4 vmathSoaM4Mul_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1 ); + +/* + * Multiply a 4x4 matrix by a 3x4 transformation matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4MulT3_V( VmathSoaMatrix4 mat, VmathSoaTransform3 tfrm ); + +/* + * Construct an identity 4x4 matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeIdentity_V( ); + +/* + * Construct a 4x4 matrix to rotate around the x axis + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationX_V( vec_float4 radians ); + +/* + * Construct a 4x4 matrix to rotate around the y axis + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationY_V( vec_float4 radians ); + +/* + * Construct a 4x4 matrix to rotate around the z axis + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationZ_V( vec_float4 radians ); + +/* + * Construct a 4x4 matrix to rotate around the x, y, and z axes + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationZYX_V( VmathSoaVector3 radiansXYZ ); + +/* + * Construct a 4x4 matrix to rotate around a unit-length 3-D vector + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationAxis_V( vec_float4 radians, VmathSoaVector3 unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationQ_V( VmathSoaQuat unitQuat ); + +/* + * Construct a 4x4 matrix to perform scaling + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeScale_V( VmathSoaVector3 scaleVec ); + +/* + * Construct a 4x4 matrix to perform translation + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeTranslation_V( VmathSoaVector3 translateVec ); + +/* + * Construct viewing matrix based on eye position, position looked at, and up direction + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeLookAt_V( VmathSoaPoint3 eyePos, VmathSoaPoint3 lookAtPos, VmathSoaVector3 upVec ); + +/* + * Construct a perspective projection matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4MakePerspective_V( vec_float4 fovyRadians, vec_float4 aspect, vec_float4 zNear, vec_float4 zFar ); + +/* + * Construct a perspective projection matrix based on frustum + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeFrustum_V( vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ); + +/* + * Construct an orthographic projection matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeOrthographic_V( vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ); + +/* + * Append (post-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathSoaMatrix4 vmathSoaM4AppendScale_V( VmathSoaMatrix4 mat, VmathSoaVector3 scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathSoaMatrix4 vmathSoaM4PrependScale_V( VmathSoaVector3 scaleVec, VmathSoaMatrix4 mat ); + +/* + * Multiply two 4x4 matrices per element + */ +static inline VmathSoaMatrix4 vmathSoaM4MulPerElem_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1 ); + +/* + * Compute the absolute value of a 4x4 matrix per element + */ +static inline VmathSoaMatrix4 vmathSoaM4AbsPerElem_V( VmathSoaMatrix4 mat ); + +/* + * Transpose of a 4x4 matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4Transpose_V( VmathSoaMatrix4 mat ); + +/* + * Compute the inverse of a 4x4 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline VmathSoaMatrix4 vmathSoaM4Inverse_V( VmathSoaMatrix4 mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline VmathSoaMatrix4 vmathSoaM4AffineInverse_V( VmathSoaMatrix4 mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. + */ +static inline VmathSoaMatrix4 vmathSoaM4OrthoInverse_V( VmathSoaMatrix4 mat ); + +/* + * Determinant of a 4x4 matrix + */ +static inline vec_float4 vmathSoaM4Determinant_V( VmathSoaMatrix4 mat ); + +/* + * Conditionally select between two 4x4 matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathSoaMatrix4 vmathSoaM4Select_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4x4 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaM4Print_V( VmathSoaMatrix4 mat ); + +/* + * Print a 4x4 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaM4Prints_V( VmathSoaMatrix4 mat, const char *name ); + +#endif + +/* + * Construct a 3x4 transformation matrix containing the specified columns + */ +static inline VmathSoaTransform3 vmathSoaT3MakeFromCols_V( VmathSoaVector3 col0, VmathSoaVector3 col1, VmathSoaVector3 col2, VmathSoaVector3 col3 ); + +/* + * Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + */ +static inline VmathSoaTransform3 vmathSoaT3MakeFromM3V3_V( VmathSoaMatrix3 tfrm, VmathSoaVector3 translateVec ); + +/* + * Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + */ +static inline VmathSoaTransform3 vmathSoaT3MakeFromQV3_V( VmathSoaQuat unitQuat, VmathSoaVector3 translateVec ); + +/* + * Set all elements of a 3x4 transformation matrix to the same scalar value + */ +static inline VmathSoaTransform3 vmathSoaT3MakeFromScalar_V( vec_float4 scalar ); + +/* + * Replicate an AoS 3x4 transformation matrix + */ +static inline VmathSoaTransform3 vmathSoaT3MakeFromAos_V( VmathTransform3 tfrm ); + +/* + * Insert four AoS 3x4 transformation matrices + */ +static inline VmathSoaTransform3 vmathSoaT3MakeFrom4Aos_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1, VmathTransform3 tfrm2, VmathTransform3 tfrm3 ); + +/* + * Extract four AoS 3x4 transformation matrices + */ +static inline void vmathSoaT3Get4Aos_V( VmathSoaTransform3 tfrm, VmathTransform3 *result0, VmathTransform3 *result1, VmathTransform3 *result2, VmathTransform3 *result3 ); + +/* + * Set the upper-left 3x3 submatrix + */ +static inline void vmathSoaT3SetUpper3x3_V( VmathSoaTransform3 *result, VmathSoaMatrix3 mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + */ +static inline VmathSoaMatrix3 vmathSoaT3GetUpper3x3_V( VmathSoaTransform3 tfrm ); + +/* + * Set translation component + */ +static inline void vmathSoaT3SetTranslation_V( VmathSoaTransform3 *result, VmathSoaVector3 translateVec ); + +/* + * Get the translation component of a 3x4 transformation matrix + */ +static inline VmathSoaVector3 vmathSoaT3GetTranslation_V( VmathSoaTransform3 tfrm ); + +/* + * Set column 0 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3SetCol0_V( VmathSoaTransform3 *result, VmathSoaVector3 col0 ); + +/* + * Set column 1 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3SetCol1_V( VmathSoaTransform3 *result, VmathSoaVector3 col1 ); + +/* + * Set column 2 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3SetCol2_V( VmathSoaTransform3 *result, VmathSoaVector3 col2 ); + +/* + * Set column 3 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3SetCol3_V( VmathSoaTransform3 *result, VmathSoaVector3 col3 ); + +/* + * Get column 0 of a 3x4 transformation matrix + */ +static inline VmathSoaVector3 vmathSoaT3GetCol0_V( VmathSoaTransform3 tfrm ); + +/* + * Get column 1 of a 3x4 transformation matrix + */ +static inline VmathSoaVector3 vmathSoaT3GetCol1_V( VmathSoaTransform3 tfrm ); + +/* + * Get column 2 of a 3x4 transformation matrix + */ +static inline VmathSoaVector3 vmathSoaT3GetCol2_V( VmathSoaTransform3 tfrm ); + +/* + * Get column 3 of a 3x4 transformation matrix + */ +static inline VmathSoaVector3 vmathSoaT3GetCol3_V( VmathSoaTransform3 tfrm ); + +/* + * Set the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathSoaT3SetCol_V( VmathSoaTransform3 *result, int col, VmathSoaVector3 vec ); + +/* + * Set the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathSoaT3SetRow_V( VmathSoaTransform3 *result, int row, VmathSoaVector4 vec ); + +/* + * Get the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline VmathSoaVector3 vmathSoaT3GetCol_V( VmathSoaTransform3 tfrm, int col ); + +/* + * Get the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline VmathSoaVector4 vmathSoaT3GetRow_V( VmathSoaTransform3 tfrm, int row ); + +/* + * Set the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline void vmathSoaT3SetElem_V( VmathSoaTransform3 *result, int col, int row, vec_float4 val ); + +/* + * Get the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline vec_float4 vmathSoaT3GetElem_V( VmathSoaTransform3 tfrm, int col, int row ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D vector + */ +static inline VmathSoaVector3 vmathSoaT3MulV3_V( VmathSoaTransform3 tfrm, VmathSoaVector3 vec ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D point + */ +static inline VmathSoaPoint3 vmathSoaT3MulP3_V( VmathSoaTransform3 tfrm, VmathSoaPoint3 pnt ); + +/* + * Multiply two 3x4 transformation matrices + */ +static inline VmathSoaTransform3 vmathSoaT3Mul_V( VmathSoaTransform3 tfrm0, VmathSoaTransform3 tfrm1 ); + +/* + * Construct an identity 3x4 transformation matrix + */ +static inline VmathSoaTransform3 vmathSoaT3MakeIdentity_V( ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x axis + */ +static inline VmathSoaTransform3 vmathSoaT3MakeRotationX_V( vec_float4 radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the y axis + */ +static inline VmathSoaTransform3 vmathSoaT3MakeRotationY_V( vec_float4 radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the z axis + */ +static inline VmathSoaTransform3 vmathSoaT3MakeRotationZ_V( vec_float4 radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + */ +static inline VmathSoaTransform3 vmathSoaT3MakeRotationZYX_V( VmathSoaVector3 radiansXYZ ); + +/* + * Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + */ +static inline VmathSoaTransform3 vmathSoaT3MakeRotationAxis_V( vec_float4 radians, VmathSoaVector3 unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline VmathSoaTransform3 vmathSoaT3MakeRotationQ_V( VmathSoaQuat unitQuat ); + +/* + * Construct a 3x4 transformation matrix to perform scaling + */ +static inline VmathSoaTransform3 vmathSoaT3MakeScale_V( VmathSoaVector3 scaleVec ); + +/* + * Construct a 3x4 transformation matrix to perform translation + */ +static inline VmathSoaTransform3 vmathSoaT3MakeTranslation_V( VmathSoaVector3 translateVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathSoaTransform3 vmathSoaT3AppendScale_V( VmathSoaTransform3 tfrm, VmathSoaVector3 scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathSoaTransform3 vmathSoaT3PrependScale_V( VmathSoaVector3 scaleVec, VmathSoaTransform3 tfrm ); + +/* + * Multiply two 3x4 transformation matrices per element + */ +static inline VmathSoaTransform3 vmathSoaT3MulPerElem_V( VmathSoaTransform3 tfrm0, VmathSoaTransform3 tfrm1 ); + +/* + * Compute the absolute value of a 3x4 transformation matrix per element + */ +static inline VmathSoaTransform3 vmathSoaT3AbsPerElem_V( VmathSoaTransform3 tfrm ); + +/* + * Inverse of a 3x4 transformation matrix + * NOTE: + * Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. + */ +static inline VmathSoaTransform3 vmathSoaT3Inverse_V( VmathSoaTransform3 tfrm ); + +/* + * Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. + */ +static inline VmathSoaTransform3 vmathSoaT3OrthoInverse_V( VmathSoaTransform3 tfrm ); + +/* + * Conditionally select between two 3x4 transformation matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathSoaTransform3 vmathSoaT3Select_V( VmathSoaTransform3 tfrm0, VmathSoaTransform3 tfrm1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x4 transformation matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaT3Print_V( VmathSoaTransform3 tfrm ); + +/* + * Print a 3x4 transformation matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaT3Prints_V( VmathSoaTransform3 tfrm, const char *name ); + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#include "vectormath_soa.h" +#include "vec_soa_v.h" +#include "quat_soa_v.h" +#include "mat_soa_v.h" + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/cpp/boolInVec.h b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/boolInVec.h new file mode 100644 index 0000000..351a6f6 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/boolInVec.h @@ -0,0 +1,261 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _BOOLINVEC_H +#define _BOOLINVEC_H + +#include +#include +#include "../c/vec_types.h" +#undef bool + +namespace Vectormath { + +class floatInVec; + +//-------------------------------------------------------------------------------------------------- +// boolInVec class +// + +class boolInVec +{ + private: + vec_uint4 mData; + + inline boolInVec(vec_uint4 vec); + public: + inline boolInVec() {} + + // matches standard type conversions + // + inline boolInVec(floatInVec vec); + + // explicit cast from bool + // + explicit inline boolInVec(bool scalar); + +#ifdef _VECTORMATH_NO_SCALAR_CAST + // explicit cast to bool + // + inline bool getAsBool() const; +#else + // implicit cast to bool + // + inline operator bool() const; +#endif + + // get vector data + // bool value is splatted across all word slots of vector as 0 (false) or -1 (true) + // + inline vec_uint4 get128() const; + + // operators + // + inline const boolInVec operator ! () const; + inline boolInVec& operator = (boolInVec vec); + inline boolInVec& operator &= (boolInVec vec); + inline boolInVec& operator ^= (boolInVec vec); + inline boolInVec& operator |= (boolInVec vec); + + // friend functions + // + friend inline const boolInVec operator == (boolInVec vec0, boolInVec vec1); + friend inline const boolInVec operator != (boolInVec vec0, boolInVec vec1); + friend inline const boolInVec operator < (floatInVec vec0, floatInVec vec1); + friend inline const boolInVec operator <= (floatInVec vec0, floatInVec vec1); + friend inline const boolInVec operator > (floatInVec vec0, floatInVec vec1); + friend inline const boolInVec operator >= (floatInVec vec0, floatInVec vec1); + friend inline const boolInVec operator == (floatInVec vec0, floatInVec vec1); + friend inline const boolInVec operator != (floatInVec vec0, floatInVec vec1); + friend inline const boolInVec operator & (boolInVec vec0, boolInVec vec1); + friend inline const boolInVec operator ^ (boolInVec vec0, boolInVec vec1); + friend inline const boolInVec operator | (boolInVec vec0, boolInVec vec1); + friend inline const boolInVec select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1); +}; + +//-------------------------------------------------------------------------------------------------- +// boolInVec functions +// + +// operators +// +inline const boolInVec operator == (boolInVec vec0, boolInVec vec1); +inline const boolInVec operator != (boolInVec vec0, boolInVec vec1); +inline const boolInVec operator & (boolInVec vec0, boolInVec vec1); +inline const boolInVec operator ^ (boolInVec vec0, boolInVec vec1); +inline const boolInVec operator | (boolInVec vec0, boolInVec vec1); + +// select between vec0 and vec1 using boolInVec. +// false selects vec0, true selects vec1 +// +inline const boolInVec select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1); + +} // namespace Vectormath + +//-------------------------------------------------------------------------------------------------- +// boolInVec implementation +// + +#include "floatInVec.h" + +namespace Vectormath { + +inline +boolInVec::boolInVec(vec_uint4 vec) +{ + mData = vec; +} + +inline +boolInVec::boolInVec(floatInVec vec) +{ + *this = (vec != floatInVec(0.0f)); +} + +inline +boolInVec::boolInVec(bool scalar) +{ +#ifdef __GNUC__ + if (__builtin_constant_p(scalar)) + { + const unsigned int mask = -(int)scalar; + mData = (vec_uint4){mask, mask, mask, mask}; + } + else +#endif + { + unsigned int mask = -(int)scalar; + vec_uint4 vec = vec_ld(0, &mask); + mData = vec_splat(vec_perm(vec, vec, vec_lvsl(0, &mask)), 0); + } +} + +#ifdef _VECTORMATH_NO_SCALAR_CAST +inline +bool +boolInVec::getAsBool() const +#else +inline +boolInVec::operator bool() const +#endif +{ + return vec_all_gt(mData, ((vec_uint4){0,0,0,0})); +} + +inline +vec_uint4 +boolInVec::get128() const +{ + return mData; +} + +inline +const boolInVec +boolInVec::operator ! () const +{ + return boolInVec(vec_nor(mData, mData)); +} + +inline +boolInVec& +boolInVec::operator = (boolInVec vec) +{ + mData = vec.mData; + return *this; +} + +inline +boolInVec& +boolInVec::operator &= (boolInVec vec) +{ + *this = *this & vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator ^= (boolInVec vec) +{ + *this = *this ^ vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator |= (boolInVec vec) +{ + *this = *this | vec; + return *this; +} + +inline +const boolInVec +operator == (boolInVec vec0, boolInVec vec1) +{ + return boolInVec((vec_uint4)vec_cmpeq(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator != (boolInVec vec0, boolInVec vec1) +{ + return !(vec0 == vec1); +} + +inline +const boolInVec +operator & (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec_and(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator | (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec_or(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator ^ (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec_xor(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1) +{ + return boolInVec(vec_sel(vec0.get128(), vec1.get128(), select_vec1.get128())); +} + +} // namespace Vectormath + +#endif // boolInVec_h diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/cpp/floatInVec.h b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/floatInVec.h new file mode 100644 index 0000000..9579719 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/floatInVec.h @@ -0,0 +1,361 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _FLOATINVEC_H +#define _FLOATINVEC_H + +#include +#include +#include +#include +#include "../c/vec_types.h" +#undef bool + +namespace Vectormath { + +class boolInVec; + +//-------------------------------------------------------------------------------------------------- +// floatInVec class +// + +class floatInVec +{ + private: + vec_float4 mData; + + inline floatInVec(vec_float4 vec); + public: + inline floatInVec() {} + + // matches standard type conversions + // + inline floatInVec(boolInVec vec); + + // construct from a slot of vec_float4 + // + inline floatInVec(vec_float4 vec, int slot); + + // explicit cast from float + // + explicit inline floatInVec(float scalar); + +#ifdef _VECTORMATH_NO_SCALAR_CAST + // explicit cast to float + // + inline float getAsFloat() const; +#else + // implicit cast to float + // + inline operator float() const; +#endif + + // get vector data + // float value is splatted across all word slots of vector + // + inline vec_float4 get128() const; + + // operators + // + inline const floatInVec operator ++ (int); + inline const floatInVec operator -- (int); + inline floatInVec& operator ++ (); + inline floatInVec& operator -- (); + inline const floatInVec operator - () const; + inline floatInVec& operator = (floatInVec vec); + inline floatInVec& operator *= (floatInVec vec); + inline floatInVec& operator /= (floatInVec vec); + inline floatInVec& operator += (floatInVec vec); + inline floatInVec& operator -= (floatInVec vec); + + // friend functions + // + friend inline const floatInVec operator * (floatInVec vec0, floatInVec vec1); + friend inline const floatInVec operator / (floatInVec vec0, floatInVec vec1); + friend inline const floatInVec operator + (floatInVec vec0, floatInVec vec1); + friend inline const floatInVec operator - (floatInVec vec0, floatInVec vec1); + friend inline const floatInVec select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1); +}; + +//-------------------------------------------------------------------------------------------------- +// floatInVec functions +// + +// operators +// +inline const floatInVec operator * (floatInVec vec0, floatInVec vec1); +inline const floatInVec operator / (floatInVec vec0, floatInVec vec1); +inline const floatInVec operator + (floatInVec vec0, floatInVec vec1); +inline const floatInVec operator - (floatInVec vec0, floatInVec vec1); +inline const boolInVec operator < (floatInVec vec0, floatInVec vec1); +inline const boolInVec operator <= (floatInVec vec0, floatInVec vec1); +inline const boolInVec operator > (floatInVec vec0, floatInVec vec1); +inline const boolInVec operator >= (floatInVec vec0, floatInVec vec1); +inline const boolInVec operator == (floatInVec vec0, floatInVec vec1); +inline const boolInVec operator != (floatInVec vec0, floatInVec vec1); + +// select between vec0 and vec1 using boolInVec. +// false selects vec0, true selects vec1 +// +inline const floatInVec select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1); + +} // namespace Vectormath + +//-------------------------------------------------------------------------------------------------- +// floatInVec implementation +// + +#include "boolInVec.h" + +namespace Vectormath { + +inline +floatInVec::floatInVec(vec_float4 vec) +{ + mData = vec; +} + +inline +floatInVec::floatInVec(boolInVec vec) +{ + mData = vec_ctf(vec_sub((vec_uint4){0,0,0,0}, vec.get128()), 0); +} + +inline +floatInVec::floatInVec(vec_float4 vec, int slot) +{ +#ifdef __GNUC__ + if (__builtin_constant_p(slot)) + { + mData = vec_splat(vec, slot); + } + else +#endif + { + const vec_uchar16 shiftpattern = vec_lvsl(0, (float *)(size_t)(slot << 2)); + mData = vec_splat(vec_perm(vec, vec, shiftpattern), 0); + } +} + +inline +floatInVec::floatInVec(float scalar) +{ +#ifdef __GNUC__ + if (__builtin_constant_p(scalar)) + { + mData = (vec_float4){scalar, scalar, scalar, scalar}; + } + else +#endif + { + vec_float4 vec = vec_ld(0, &scalar); + mData = vec_splat(vec_perm(vec, vec, vec_lvsl(0, &scalar)), 0); + } +} + +#ifdef _VECTORMATH_NO_SCALAR_CAST +inline +float +floatInVec::getAsFloat() const +#else +inline +floatInVec::operator float() const +#endif +{ + return *((float *)&mData); +} + +inline +vec_float4 +floatInVec::get128() const +{ + return mData; +} + +inline +const floatInVec +floatInVec::operator ++ (int) +{ + vec_float4 olddata = mData; + operator ++(); + return floatInVec(olddata); +} + +inline +const floatInVec +floatInVec::operator -- (int) +{ + vec_float4 olddata = mData; + operator --(); + return floatInVec(olddata); +} + +inline +floatInVec& +floatInVec::operator ++ () +{ + *this += floatInVec((vec_float4){1.0f,1.0f,1.0f,1.0f}); + return *this; +} + +inline +floatInVec& +floatInVec::operator -- () +{ + *this -= floatInVec((vec_float4){1.0f,1.0f,1.0f,1.0f}); + return *this; +} + +inline +const floatInVec +floatInVec::operator - () const +{ + return floatInVec((vec_float4)vec_xor((vec_uint4)mData, (vec_uint4){0x80000000,0x80000000,0x80000000,0x80000000})); +} + +inline +floatInVec& +floatInVec::operator = (floatInVec vec) +{ + mData = vec.mData; + return *this; +} + +inline +floatInVec& +floatInVec::operator *= (floatInVec vec) +{ + *this = *this * vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator /= (floatInVec vec) +{ + *this = *this / vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator += (floatInVec vec) +{ + *this = *this + vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator -= (floatInVec vec) +{ + *this = *this - vec; + return *this; +} + +inline +const floatInVec +operator * (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec_madd(vec0.get128(), vec1.get128(), (vec_float4){0,0,0,0})); +} + +inline +const floatInVec +operator / (floatInVec num, floatInVec den) +{ + return floatInVec(divf4(num.get128(), den.get128())); +} + +inline +const floatInVec +operator + (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec_add(vec0.get128(), vec1.get128())); +} + +inline +const floatInVec +operator - (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec_sub(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator < (floatInVec vec0, floatInVec vec1) +{ + return boolInVec((vec_uint4)vec_cmpgt(vec1.get128(), vec0.get128())); +} + +inline +const boolInVec +operator <= (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 > vec1); +} + +inline +const boolInVec +operator > (floatInVec vec0, floatInVec vec1) +{ + return boolInVec((vec_uint4)vec_cmpgt(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator >= (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 < vec1); +} + +inline +const boolInVec +operator == (floatInVec vec0, floatInVec vec1) +{ + return boolInVec((vec_uint4)vec_cmpeq(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator != (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 == vec1); +} + +inline +const floatInVec +select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1) +{ + return floatInVec(vec_sel(vec0.get128(), vec1.get128(), select_vec1.get128())); +} + +} // namespace Vectormath + +#endif // floatInVec_h diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/cpp/mat_aos.h b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/mat_aos.h new file mode 100644 index 0000000..77a1847 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/mat_aos.h @@ -0,0 +1,2188 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_AOS_CPP_H +#define _VECTORMATH_MAT_AOS_CPP_H + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// Constants +// for shuffles, words are labeled [x,y,z,w] [a,b,c,d] + +#define _VECTORMATH_PERM_ZBWX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XCYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_C, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XYAB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_ZWCD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W, _VECTORMATH_PERM_C, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_XZBX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_CXXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_YAXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XAZC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_YXWZ ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W, _VECTORMATH_PERM_Z }) +#define _VECTORMATH_PERM_YBWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_XYCX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_YCXY ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y }) +#define _VECTORMATH_PERM_CXYC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_ZAYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_BZXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_B, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XZYA ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A }) +#define _VECTORMATH_PERM_ZXXB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_YXXC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_BBYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_B, _VECTORMATH_PERM_B, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PI_OVER_2 1.570796327f + +//----------------------------------------------------------------------------- +// Definitions + +inline Matrix3::Matrix3( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; +} + +inline Matrix3::Matrix3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +inline Matrix3::Matrix3( floatInVec scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +inline Matrix3::Matrix3( Quat unitQuat ) +{ + vec_float4 xyzw_2, wwww, yzxw, zxyw, yzxw_2, zxyw_2; + vec_float4 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + vec_uint4 select_x = _VECTORMATH_MASK_0xF000; + vec_uint4 select_z = _VECTORMATH_MASK_0x00F0; + xyzw_2 = vec_add( unitQuat.get128(), unitQuat.get128() ); + wwww = vec_splat( unitQuat.get128(), 3 ); + yzxw = vec_perm( unitQuat.get128(), unitQuat.get128(), _VECTORMATH_PERM_YZXW ); + zxyw = vec_perm( unitQuat.get128(), unitQuat.get128(), _VECTORMATH_PERM_ZXYW ); + yzxw_2 = vec_perm( xyzw_2, xyzw_2, _VECTORMATH_PERM_YZXW ); + zxyw_2 = vec_perm( xyzw_2, xyzw_2, _VECTORMATH_PERM_ZXYW ); + tmp0 = vec_madd( yzxw_2, wwww, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + tmp1 = vec_nmsub( yzxw, yzxw_2, ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); + tmp2 = vec_madd( yzxw, xyzw_2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + tmp0 = vec_madd( zxyw, xyzw_2, tmp0 ); + tmp1 = vec_nmsub( zxyw, zxyw_2, tmp1 ); + tmp2 = vec_nmsub( zxyw_2, wwww, tmp2 ); + tmp3 = vec_sel( tmp0, tmp1, select_x ); + tmp4 = vec_sel( tmp1, tmp2, select_x ); + tmp5 = vec_sel( tmp2, tmp0, select_x ); + mCol0 = Vector3( vec_sel( tmp3, tmp2, select_z ) ); + mCol1 = Vector3( vec_sel( tmp4, tmp0, select_z ) ); + mCol2 = Vector3( vec_sel( tmp5, tmp1, select_z ) ); +} + +inline Matrix3::Matrix3( Vector3 _col0, Vector3 _col1, Vector3 _col2 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; +} + +inline Matrix3 & Matrix3::setCol0( Vector3 _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix3 & Matrix3::setCol1( Vector3 _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix3 & Matrix3::setCol2( Vector3 _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix3 & Matrix3::setCol( int col, Vector3 vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix3 & Matrix3::setRow( int row, Vector3 vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + return *this; +} + +inline Matrix3 & Matrix3::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +inline Matrix3 & Matrix3::setElem( int col, int row, floatInVec val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline const floatInVec Matrix3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Matrix3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Matrix3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Matrix3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Matrix3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::getRow( int row ) const +{ + return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); +} + +inline Vector3 & Matrix3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix3 & Matrix3::operator =( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + return *this; +} + +inline const Matrix3 transpose( const Matrix3 & mat ) +{ + vec_float4 tmp0, tmp1, res0, res1, res2; + tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp1 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); + res0 = vec_mergeh( tmp0, mat.getCol1().get128() ); + res1 = vec_perm( tmp0, mat.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); + res2 = vec_perm( tmp1, mat.getCol1().get128(), _VECTORMATH_PERM_XCYX ); + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +inline const Matrix3 inverse( const Matrix3 & mat ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet, inv0, inv1, inv2; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + tmp2 = _vmathVfCross( mat.getCol0().get128(), mat.getCol1().get128() ); + tmp0 = _vmathVfCross( mat.getCol1().get128(), mat.getCol2().get128() ); + tmp1 = _vmathVfCross( mat.getCol2().get128(), mat.getCol0().get128() ); + dot = _vmathVfDot3( tmp2, mat.getCol2().get128() ); + dot = vec_splat( dot, 0 ); + invdet = recipf4( dot ); + tmp3 = vec_mergeh( tmp0, tmp2 ); + tmp4 = vec_mergel( tmp0, tmp2 ); + inv0 = vec_mergeh( tmp3, tmp1 ); + inv1 = vec_perm( tmp3, tmp1, _VECTORMATH_PERM_ZBWX ); + inv2 = vec_perm( tmp4, tmp1, _VECTORMATH_PERM_XCYX ); + inv0 = vec_madd( inv0, invdet, zero ); + inv1 = vec_madd( inv1, invdet, zero ); + inv2 = vec_madd( inv2, invdet, zero ); + return Matrix3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ) + ); +} + +inline const floatInVec determinant( const Matrix3 & mat ) +{ + return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); +} + +inline const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ) + ); +} + +inline const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix3 Matrix3::operator -( ) const +{ + return Matrix3( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ) + ); +} + +inline const Matrix3 absPerElem( const Matrix3 & mat ) +{ + return Matrix3( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +inline const Matrix3 Matrix3::operator *( floatInVec scalar ) const +{ + return Matrix3( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ) + ); +} + +inline Matrix3 & Matrix3::operator *=( float scalar ) +{ + return *this *= floatInVec(scalar); +} + +inline Matrix3 & Matrix3::operator *=( floatInVec scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix3 operator *( float scalar, const Matrix3 & mat ) +{ + return floatInVec(scalar) * mat; +} + +inline const Matrix3 operator *( floatInVec scalar, const Matrix3 & mat ) +{ + return mat * scalar; +} + +inline const Vector3 Matrix3::operator *( Vector3 vec ) const +{ + vec_float4 res; + vec_float4 xxxx, yyyy, zzzz; + xxxx = vec_splat( vec.get128(), 0 ); + yyyy = vec_splat( vec.get128(), 1 ); + zzzz = vec_splat( vec.get128(), 2 ); + res = vec_madd( mCol0.get128(), xxxx, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + res = vec_madd( mCol1.get128(), yyyy, res ); + res = vec_madd( mCol2.get128(), zzzz, res ); + return Vector3( res ); +} + +inline const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const +{ + return Matrix3( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) +{ + return Matrix3( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::identity( ) +{ + return Matrix3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +inline const Matrix3 Matrix3::rotationX( floatInVec radians ) +{ + vec_float4 s, c, res1, res2; + vec_uint4 select_y, select_z; + vec_float4 zero; + select_y = _VECTORMATH_MASK_0x0F00; + select_z = _VECTORMATH_MASK_0x00F0; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( radians.get128(), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + return Matrix3( + Vector3::xAxis( ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +inline const Matrix3 Matrix3::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +inline const Matrix3 Matrix3::rotationY( floatInVec radians ) +{ + vec_float4 s, c, res0, res2; + vec_uint4 select_x, select_z; + vec_float4 zero; + select_x = _VECTORMATH_MASK_0xF000; + select_z = _VECTORMATH_MASK_0x00F0; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + return Matrix3( + Vector3( res0 ), + Vector3::yAxis( ), + Vector3( res2 ) + ); +} + +inline const Matrix3 Matrix3::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +inline const Matrix3 Matrix3::rotationZ( floatInVec radians ) +{ + vec_float4 s, c, res0, res1; + vec_uint4 select_x, select_y; + vec_float4 zero; + select_x = _VECTORMATH_MASK_0xF000; + select_y = _VECTORMATH_MASK_0x0F00; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationZYX( Vector3 radiansXYZ ) +{ + vec_float4 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + angles = Vector4( radiansXYZ, 0.0f ).get128(); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + Z1 = vec_andc( Z1, (vec_float4)_VECTORMATH_MASK_0x000F ); + Y0 = vec_perm( negS, c, _VECTORMATH_PERM_BBYX ); + Y1 = vec_perm( c, s, _VECTORMATH_PERM_BBYX ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_madd( Z0, Y1, zero ); + return Matrix3( + Vector3( vec_madd( Z0, Y0, zero ) ), + Vector3( vec_madd( Z1, X1, vec_madd( tmp, X0, zero ) ) ), + Vector3( vec_nmsub( Z1, X0, vec_madd( tmp, X1, zero ) ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( float radians, Vector3 unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +inline const Matrix3 Matrix3::rotation( floatInVec radians, Vector3 unitVec ) +{ + vec_float4 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + axis = unitVec.get128(); + sincosf4( radians.get128(), &s, &c ); + xxxx = vec_splat( axis, 0 ); + yyyy = vec_splat( axis, 1 ); + zzzz = vec_splat( axis, 2 ); + oneMinusC = vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), c ); + axisS = vec_madd( axis, s, zero ); + negAxisS = negatef4( axisS ); + tmp0 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_XZBX ); + tmp1 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_CXXX ); + tmp2 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_YAXX ); + tmp0 = vec_sel( tmp0, c, _VECTORMATH_MASK_0xF000 ); + tmp1 = vec_sel( tmp1, c, _VECTORMATH_MASK_0x0F00 ); + tmp2 = vec_sel( tmp2, c, _VECTORMATH_MASK_0x00F0 ); + return Matrix3( + Vector3( vec_madd( vec_madd( axis, xxxx, zero ), oneMinusC, tmp0 ) ), + Vector3( vec_madd( vec_madd( axis, yyyy, zero ), oneMinusC, tmp1 ) ), + Vector3( vec_madd( vec_madd( axis, zzzz, zero ), oneMinusC, tmp2 ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( Quat unitQuat ) +{ + return Matrix3( unitQuat ); +} + +inline const Matrix3 Matrix3::scale( Vector3 scaleVec ) +{ + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + return Matrix3( + Vector3( vec_sel( zero, scaleVec.get128(), _VECTORMATH_MASK_0xF000 ) ), + Vector3( vec_sel( zero, scaleVec.get128(), _VECTORMATH_MASK_0x0F00 ) ), + Vector3( vec_sel( zero, scaleVec.get128(), _VECTORMATH_MASK_0x00F0 ) ) + ); +} + +inline const Matrix3 appendScale( const Matrix3 & mat, Vector3 scaleVec ) +{ + return Matrix3( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ) + ); +} + +inline const Matrix3 prependScale( Vector3 scaleVec, const Matrix3 & mat ) +{ + return Matrix3( + mulPerElem( mat.getCol0(), scaleVec ), + mulPerElem( mat.getCol1(), scaleVec ), + mulPerElem( mat.getCol2(), scaleVec ) + ); +} + +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, boolInVec select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix3 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); +} + +inline void print( const Matrix3 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Matrix4::Matrix4( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; +} + +inline Matrix4::Matrix4( float scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +inline Matrix4::Matrix4( floatInVec scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +inline Matrix4::Matrix4( const Transform3 & mat ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( mat.getCol3(), 1.0f ); +} + +inline Matrix4::Matrix4( Vector4 _col0, Vector4 _col1, Vector4 _col2, Vector4 _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Matrix4::Matrix4( const Matrix3 & mat, Vector3 translateVec ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +inline Matrix4::Matrix4( Quat unitQuat, Vector3 translateVec ) +{ + Matrix3 mat; + mat = Matrix3( unitQuat ); + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +inline Matrix4 & Matrix4::setCol0( Vector4 _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix4 & Matrix4::setCol1( Vector4 _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix4 & Matrix4::setCol2( Vector4 _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix4 & Matrix4::setCol3( Vector4 _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Matrix4 & Matrix4::setCol( int col, Vector4 vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix4 & Matrix4::setRow( int row, Vector4 vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Matrix4 & Matrix4::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +inline Matrix4 & Matrix4::setElem( int col, int row, floatInVec val ) +{ + Vector4 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline const floatInVec Matrix4::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector4 Matrix4::getCol0( ) const +{ + return mCol0; +} + +inline const Vector4 Matrix4::getCol1( ) const +{ + return mCol1; +} + +inline const Vector4 Matrix4::getCol2( ) const +{ + return mCol2; +} + +inline const Vector4 Matrix4::getCol3( ) const +{ + return mCol3; +} + +inline const Vector4 Matrix4::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector4 & Matrix4::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix4 & Matrix4::operator =( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; + return *this; +} + +inline const Matrix4 transpose( const Matrix4 & mat ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3, res0, res1, res2, res3; + tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp1 = vec_mergeh( mat.getCol1().get128(), mat.getCol3().get128() ); + tmp2 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp3 = vec_mergel( mat.getCol1().get128(), mat.getCol3().get128() ); + res0 = vec_mergeh( tmp0, tmp1 ); + res1 = vec_mergel( tmp0, tmp1 ); + res2 = vec_mergeh( tmp2, tmp3 ); + res3 = vec_mergel( tmp2, tmp3 ); + return Matrix4( + Vector4( res0 ), + Vector4( res1 ), + Vector4( res2 ), + Vector4( res3 ) + ); +} + +inline const Matrix4 inverse( const Matrix4 & mat ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + vector float in0, in1, in2, in3; + vector float tmp0, tmp1, tmp2, tmp3; + vector float cof0, cof1, cof2, cof3; + vector float t0, t1, t2, t3; + vector float t01, t02, t03, t12, t23; + vector float t1r, t2r; + vector float t01r, t02r, t03r, t12r, t23r; + vector float t1r3, t1r3r; + vector float det, det0, det1, det2, det3, invdet; + vector float vzero = (vector float){0.0}; + in0 = mat.getCol0().get128(); + in1 = mat.getCol1().get128(); + in2 = mat.getCol2().get128(); + in3 = mat.getCol3().get128(); + /* Perform transform of the input matrix of the form: + * A B C D + * E F G H + * I J K L + * M N O P + * + * The pseudo transpose of the input matrix is trans: + * A E I M + * J N B F + * C G K O + * L P D H + */ + tmp0 = vec_perm(in0, in1, _VECTORMATH_PERM_XAZC); /* A E C G */ + tmp1 = vec_perm(in2, in3, _VECTORMATH_PERM_XAZC); /* I M K O */ + tmp2 = vec_perm(in0, in1, _VECTORMATH_PERM_YBWD); /* B F D H */ + tmp3 = vec_perm(in2, in3, _VECTORMATH_PERM_YBWD); /* J N L P */ + t0 = vec_perm(tmp0, tmp1, _VECTORMATH_PERM_XYAB); /* A E I M */ + t1 = vec_perm(tmp3, tmp2, _VECTORMATH_PERM_XYAB); /* J N B F */ + t2 = vec_perm(tmp0, tmp1, _VECTORMATH_PERM_ZWCD); /* C G K O */ + t3 = vec_perm(tmp3, tmp2, _VECTORMATH_PERM_ZWCD); /* L P D H */ + /* Generate a cofactor matrix. The computed cofactors reside in + * cof0, cof1, cof2, cof3. + */ + t23 = vec_madd(t2, t3, vzero); /* CL GP KD OH */ + t23 = vec_perm(t23, t23, _VECTORMATH_PERM_YXWZ); /* GP CL OH KD */ + cof0 = vec_nmsub(t1, t23, vzero); /* -(JGP NCL FOH BKD) */ + cof1 = vec_nmsub(t0, t23, vzero); /* -(AGP ECL IOH MKD) */ + t23r = vec_sld(t23, t23, 8); /* OH KD GP CL */ + cof0 = vec_madd(t1, t23r, cof0); /* JOH NKD BGP FCL + cof0 */ + cof1 = vec_madd(t0, t23r, cof1); /* AOH EKD IGP MCL + cof1 */ + cof1 = vec_sld(cof1, cof1, 8); /* IGP MCL AOH EKD - IOH MKD AGP ECL */ + t12 = vec_madd(t1, t2, vzero); /* JC NG BK FO */ + t12 = vec_perm(t12, t12, _VECTORMATH_PERM_YXWZ); /* NG JC FO BK */ + cof0 = vec_madd(t3, t12, cof0); /* LNG PJC DFO HBK + cof0 */ + cof3 = vec_madd(t0, t12, vzero); /* ANG EJC IFO MBK */ + t12r = vec_sld(t12, t12, 8); /* FO BK NG JC */ + cof0 = vec_nmsub(t3, t12r, cof0); /* cof0 - LFO PBK DNG HJC */ + cof3 = vec_nmsub(t0, t12r, cof3); /* cof3 - AFO EBK ING MJC */ + cof3 = vec_sld(cof3, cof3, 8); /* ING MJC AFO EBK - IFO MBK ANG EJC */ + t1r = vec_sld(t1, t1, 8); /* B F J N */ + t2r = vec_sld(t2, t2, 8); /* K O C G */ + t1r3 = vec_madd(t1r, t3, vzero); /* BL FP JD NH */ + t1r3 = vec_perm(t1r3, t1r3, _VECTORMATH_PERM_YXWZ); /* FP BL NH JD */ + cof0 = vec_madd(t2r, t1r3, cof0); /* KFP OBL CNH GJD + cof0 */ + cof2 = vec_madd(t0, t1r3, vzero); /* AFP EBL INH MJD */ + t1r3r = vec_sld(t1r3, t1r3, 8); /* NH JD FP BL */ + cof0 = vec_nmsub(t2r, t1r3r, cof0); /* cof0 - KNH OJD CFP GBL */ + cof2 = vec_nmsub(t0, t1r3r, cof2); /* cof2 - ANH EJD IFP MBL */ + cof2 = vec_sld(cof2, cof2, 8); /* IFP MBL ANH EJD - INH MJD AFP EBL */ + t01 = vec_madd(t0, t1, vzero); /* AJ EN IB MF */ + t01 = vec_perm(t01, t01, _VECTORMATH_PERM_YXWZ); /* EN AJ MF IB */ + cof2 = vec_nmsub(t3, t01, cof2); /* cof2 - LEN PAJ DMF HIB */ + cof3 = vec_madd(t2r, t01, cof3); /* KEN OAJ CMF GIB + cof3 */ + t01r = vec_sld(t01, t01, 8); /* MF IB EN AJ */ + cof2 = vec_madd(t3, t01r, cof2); /* LMF PIB DEN HAJ + cof2 */ + cof3 = vec_nmsub(t2r, t01r, cof3); /* cof3 - KMF OIB CEN GAJ */ + t03 = vec_madd(t0, t3, vzero); /* AL EP ID MH */ + t03 = vec_perm(t03, t03, _VECTORMATH_PERM_YXWZ); /* EP AL MH ID */ + cof1 = vec_nmsub(t2r, t03, cof1); /* cof1 - KEP OAL CMH GID */ + cof2 = vec_madd(t1, t03, cof2); /* JEP NAL BMH FID + cof2 */ + t03r = vec_sld(t03, t03, 8); /* MH ID EP AL */ + cof1 = vec_madd(t2r, t03r, cof1); /* KMH OID CEP GAL + cof1 */ + cof2 = vec_nmsub(t1, t03r, cof2); /* cof2 - JMH NID BEP FAL */ + t02 = vec_madd(t0, t2r, vzero); /* AK EO IC MG */ + t02 = vec_perm(t02, t02, _VECTORMATH_PERM_YXWZ); /* E0 AK MG IC */ + cof1 = vec_madd(t3, t02, cof1); /* LEO PAK DMG HIC + cof1 */ + cof3 = vec_nmsub(t1, t02, cof3); /* cof3 - JEO NAK BMG FIC */ + t02r = vec_sld(t02, t02, 8); /* MG IC EO AK */ + cof1 = vec_nmsub(t3, t02r, cof1); /* cof1 - LMG PIC DEO HAK */ + cof3 = vec_madd(t1, t02r, cof3); /* JMG NIC BEO FAK + cof3 */ + /* Compute the determinant of the matrix + * + * det = sum_across(t0 * cof0); + * + * We perform a sum across the entire vector so that + * we don't have to splat the result when multiplying the + * cofactors by the inverse of the determinant. + */ + det = vec_madd(t0, cof0, vzero); + det0 = vec_splat(det, 0); + det1 = vec_splat(det, 1); + det2 = vec_splat(det, 2); + det3 = vec_splat(det, 3); + det = vec_add(det0, det1); + det2 = vec_add(det2, det3); + det = vec_add(det, det2); + /* Compute the reciprocal of the determinant. + */ + invdet = recipf4(det); + /* Multiply the cofactors by the reciprocal of the determinant. + */ + return Matrix4( + Vector4( vec_madd(cof0, invdet, vzero) ), + Vector4( vec_madd(cof1, invdet, vzero) ), + Vector4( vec_madd(cof2, invdet, vzero) ), + Vector4( vec_madd(cof3, invdet, vzero) ) + ); +} + +inline const Matrix4 affineInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( inverse( affineMat ) ); +} + +inline const Matrix4 orthoInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( orthoInverse( affineMat ) ); +} + +inline const floatInVec determinant( const Matrix4 & mat ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + vector float in0, in1, in2, in3; + vector float tmp0, tmp1, tmp2, tmp3; + vector float cof0; + vector float t0, t1, t2, t3; + vector float t12, t23; + vector float t1r, t2r; + vector float t12r, t23r; + vector float t1r3, t1r3r; + vector float vzero = (vector float){0.0}; + in0 = mat.getCol0().get128(); + in1 = mat.getCol1().get128(); + in2 = mat.getCol2().get128(); + in3 = mat.getCol3().get128(); + /* Perform transform of the input matrix of the form: + * A B C D + * E F G H + * I J K L + * M N O P + * + * The pseudo transpose of the input matrix is trans: + * A E I M + * J N B F + * C G K O + * L P D H + */ + tmp0 = vec_perm(in0, in1, _VECTORMATH_PERM_XAZC); /* A E C G */ + tmp1 = vec_perm(in2, in3, _VECTORMATH_PERM_XAZC); /* I M K O */ + tmp2 = vec_perm(in0, in1, _VECTORMATH_PERM_YBWD); /* B F D H */ + tmp3 = vec_perm(in2, in3, _VECTORMATH_PERM_YBWD); /* J N L P */ + t0 = vec_perm(tmp0, tmp1, _VECTORMATH_PERM_XYAB); /* A E I M */ + t1 = vec_perm(tmp3, tmp2, _VECTORMATH_PERM_XYAB); /* J N B F */ + t2 = vec_perm(tmp0, tmp1, _VECTORMATH_PERM_ZWCD); /* C G K O */ + t3 = vec_perm(tmp3, tmp2, _VECTORMATH_PERM_ZWCD); /* L P D H */ + /* Generate a cofactor matrix. The computed cofactors reside in + * cof0, cof1, cof2, cof3. + */ + t23 = vec_madd(t2, t3, vzero); /* CL GP KD OH */ + t23 = vec_perm(t23, t23, _VECTORMATH_PERM_YXWZ); /* GP CL OH KD */ + cof0 = vec_nmsub(t1, t23, vzero); /* -(JGP NCL FOH BKD) */ + t23r = vec_sld(t23, t23, 8); /* OH KD GP CL */ + cof0 = vec_madd(t1, t23r, cof0); /* JOH NKD BGP FCL + cof0 */ + t12 = vec_madd(t1, t2, vzero); /* JC NG BK FO */ + t12 = vec_perm(t12, t12, _VECTORMATH_PERM_YXWZ); /* NG JC FO BK */ + cof0 = vec_madd(t3, t12, cof0); /* LNG PJC DFO HBK + cof0 */ + t12r = vec_sld(t12, t12, 8); /* FO BK NG JC */ + cof0 = vec_nmsub(t3, t12r, cof0); /* cof0 - LFO PBK DNG HJC */ + t1r = vec_sld(t1, t1, 8); /* B F J N */ + t2r = vec_sld(t2, t2, 8); /* K O C G */ + t1r3 = vec_madd(t1r, t3, vzero); /* BL FP JD NH */ + t1r3 = vec_perm(t1r3, t1r3, _VECTORMATH_PERM_YXWZ); /* FP BL NH JD */ + cof0 = vec_madd(t2r, t1r3, cof0); /* KFP OBL CNH GJD + cof0 */ + t1r3r = vec_sld(t1r3, t1r3, 8); /* NH JD FP BL */ + cof0 = vec_nmsub(t2r, t1r3r, cof0); /* cof0 - KNH OJD CFP GBL */ + return floatInVec( _vmathVfDot4(t0,cof0), 0 ); +} + +inline const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ), + ( mCol3 + mat.mCol3 ) + ); +} + +inline const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ), + ( mCol3 - mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix4 Matrix4::operator -( ) const +{ + return Matrix4( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ), + ( -mCol3 ) + ); +} + +inline const Matrix4 absPerElem( const Matrix4 & mat ) +{ + return Matrix4( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ), + absPerElem( mat.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +inline const Matrix4 Matrix4::operator *( floatInVec scalar ) const +{ + return Matrix4( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ), + ( mCol3 * scalar ) + ); +} + +inline Matrix4 & Matrix4::operator *=( float scalar ) +{ + return *this *= floatInVec(scalar); +} + +inline Matrix4 & Matrix4::operator *=( floatInVec scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix4 operator *( float scalar, const Matrix4 & mat ) +{ + return floatInVec(scalar) * mat; +} + +inline const Matrix4 operator *( floatInVec scalar, const Matrix4 & mat ) +{ + return mat * scalar; +} + +inline const Vector4 Matrix4::operator *( Vector4 vec ) const +{ + vec_float4 tmp0, tmp1, res; + vec_float4 xxxx, yyyy, zzzz, wwww; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + xxxx = vec_splat( vec.get128(), 0 ); + yyyy = vec_splat( vec.get128(), 1 ); + zzzz = vec_splat( vec.get128(), 2 ); + wwww = vec_splat( vec.get128(), 3 ); + tmp0 = vec_madd( mCol0.get128(), xxxx, zero ); + tmp1 = vec_madd( mCol1.get128(), yyyy, zero ); + tmp0 = vec_madd( mCol2.get128(), zzzz, tmp0 ); + tmp1 = vec_madd( mCol3.get128(), wwww, tmp1 ); + res = vec_add( tmp0, tmp1 ); + return Vector4( res ); +} + +inline const Vector4 Matrix4::operator *( Vector3 vec ) const +{ + vec_float4 res; + vec_float4 xxxx, yyyy, zzzz; + xxxx = vec_splat( vec.get128(), 0 ); + yyyy = vec_splat( vec.get128(), 1 ); + zzzz = vec_splat( vec.get128(), 2 ); + res = vec_madd( mCol0.get128(), xxxx, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + res = vec_madd( mCol1.get128(), yyyy, res ); + res = vec_madd( mCol2.get128(), zzzz, res ); + return Vector4( res ); +} + +inline const Vector4 Matrix4::operator *( Point3 pnt ) const +{ + vec_float4 tmp0, tmp1, res; + vec_float4 xxxx, yyyy, zzzz; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + xxxx = vec_splat( pnt.get128(), 0 ); + yyyy = vec_splat( pnt.get128(), 1 ); + zzzz = vec_splat( pnt.get128(), 2 ); + tmp0 = vec_madd( mCol0.get128(), xxxx, zero ); + tmp1 = vec_madd( mCol1.get128(), yyyy, zero ); + tmp0 = vec_madd( mCol2.get128(), zzzz, tmp0 ); + tmp1 = vec_add( mCol3.get128(), tmp1 ); + res = vec_add( tmp0, tmp1 ); + return Vector4( res ); +} + +inline const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const +{ + return Matrix4( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ), + ( *this * mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const +{ + return Matrix4( + ( *this * tfrm.getCol0() ), + ( *this * tfrm.getCol1() ), + ( *this * tfrm.getCol2() ), + ( *this * Point3( tfrm.getCol3() ) ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) +{ + return Matrix4( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ), + mulPerElem( mat0.getCol3(), mat1.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::identity( ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) +{ + mCol0.setXYZ( mat3.getCol0() ); + mCol1.setXYZ( mat3.getCol1() ); + mCol2.setXYZ( mat3.getCol2() ); + return *this; +} + +inline const Matrix3 Matrix4::getUpper3x3( ) const +{ + return Matrix3( + mCol0.getXYZ( ), + mCol1.getXYZ( ), + mCol2.getXYZ( ) + ); +} + +inline Matrix4 & Matrix4::setTranslation( Vector3 translateVec ) +{ + mCol3.setXYZ( translateVec ); + return *this; +} + +inline const Vector3 Matrix4::getTranslation( ) const +{ + return mCol3.getXYZ( ); +} + +inline const Matrix4 Matrix4::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +inline const Matrix4 Matrix4::rotationX( floatInVec radians ) +{ + vec_float4 s, c, res1, res2; + vec_uint4 select_y, select_z; + vec_float4 zero; + select_y = _VECTORMATH_MASK_0x0F00; + select_z = _VECTORMATH_MASK_0x00F0; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( radians.get128(), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + return Matrix4( + Vector4::xAxis( ), + Vector4( res1 ), + Vector4( res2 ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +inline const Matrix4 Matrix4::rotationY( floatInVec radians ) +{ + vec_float4 s, c, res0, res2; + vec_uint4 select_x, select_z; + vec_float4 zero; + select_x = _VECTORMATH_MASK_0xF000; + select_z = _VECTORMATH_MASK_0x00F0; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + return Matrix4( + Vector4( res0 ), + Vector4::yAxis( ), + Vector4( res2 ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +inline const Matrix4 Matrix4::rotationZ( floatInVec radians ) +{ + vec_float4 s, c, res0, res1; + vec_uint4 select_x, select_y; + vec_float4 zero; + select_x = _VECTORMATH_MASK_0xF000; + select_y = _VECTORMATH_MASK_0x0F00; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + return Matrix4( + Vector4( res0 ), + Vector4( res1 ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZYX( Vector3 radiansXYZ ) +{ + vec_float4 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + angles = Vector4( radiansXYZ, 0.0f ).get128(); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + Z1 = vec_andc( Z1, (vec_float4)_VECTORMATH_MASK_0x000F ); + Y0 = vec_perm( negS, c, _VECTORMATH_PERM_BBYX ); + Y1 = vec_perm( c, s, _VECTORMATH_PERM_BBYX ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_madd( Z0, Y1, zero ); + return Matrix4( + Vector4( vec_madd( Z0, Y0, zero ) ), + Vector4( vec_madd( Z1, X1, vec_madd( tmp, X0, zero ) ) ), + Vector4( vec_nmsub( Z1, X0, vec_madd( tmp, X1, zero ) ) ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( float radians, Vector3 unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +inline const Matrix4 Matrix4::rotation( floatInVec radians, Vector3 unitVec ) +{ + vec_float4 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2, zeroW; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + axis = unitVec.get128(); + sincosf4( radians.get128(), &s, &c ); + xxxx = vec_splat( axis, 0 ); + yyyy = vec_splat( axis, 1 ); + zzzz = vec_splat( axis, 2 ); + oneMinusC = vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), c ); + axisS = vec_madd( axis, s, zero ); + negAxisS = negatef4( axisS ); + tmp0 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_XZBX ); + tmp1 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_CXXX ); + tmp2 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_YAXX ); + tmp0 = vec_sel( tmp0, c, _VECTORMATH_MASK_0xF000 ); + tmp1 = vec_sel( tmp1, c, _VECTORMATH_MASK_0x0F00 ); + tmp2 = vec_sel( tmp2, c, _VECTORMATH_MASK_0x00F0 ); + zeroW = (vec_float4)_VECTORMATH_MASK_0x000F; + axis = vec_andc( axis, zeroW ); + tmp0 = vec_andc( tmp0, zeroW ); + tmp1 = vec_andc( tmp1, zeroW ); + tmp2 = vec_andc( tmp2, zeroW ); + return Matrix4( + Vector4( vec_madd( vec_madd( axis, xxxx, zero ), oneMinusC, tmp0 ) ), + Vector4( vec_madd( vec_madd( axis, yyyy, zero ), oneMinusC, tmp1 ) ), + Vector4( vec_madd( vec_madd( axis, zzzz, zero ), oneMinusC, tmp2 ) ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( Quat unitQuat ) +{ + return Matrix4( Transform3::rotation( unitQuat ) ); +} + +inline const Matrix4 Matrix4::scale( Vector3 scaleVec ) +{ + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + return Matrix4( + Vector4( vec_sel( zero, scaleVec.get128(), _VECTORMATH_MASK_0xF000 ) ), + Vector4( vec_sel( zero, scaleVec.get128(), _VECTORMATH_MASK_0x0F00 ) ), + Vector4( vec_sel( zero, scaleVec.get128(), _VECTORMATH_MASK_0x00F0 ) ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 appendScale( const Matrix4 & mat, Vector3 scaleVec ) +{ + return Matrix4( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ), + mat.getCol3() + ); +} + +inline const Matrix4 prependScale( Vector3 scaleVec, const Matrix4 & mat ) +{ + Vector4 scale4; + scale4 = Vector4( scaleVec, 1.0f ); + return Matrix4( + mulPerElem( mat.getCol0(), scale4 ), + mulPerElem( mat.getCol1(), scale4 ), + mulPerElem( mat.getCol2(), scale4 ), + mulPerElem( mat.getCol3(), scale4 ) + ); +} + +inline const Matrix4 Matrix4::translation( Vector3 translateVec ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4( translateVec, 1.0f ) + ); +} + +inline const Matrix4 Matrix4::lookAt( Point3 eyePos, Point3 lookAtPos, Vector3 upVec ) +{ + Matrix4 m4EyeFrame; + Vector3 v3X, v3Y, v3Z; + v3Y = normalize( upVec ); + v3Z = normalize( ( eyePos - lookAtPos ) ); + v3X = normalize( cross( v3Y, v3Z ) ); + v3Y = cross( v3Z, v3X ); + m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); + return orthoInverse( m4EyeFrame ); +} + +inline const Matrix4 Matrix4::perspective( float fovyRadians, float aspect, float zNear, float zFar ) +{ + float f, rangeInv; + vec_float4 zero, col0, col1, col2, col3; + union { vec_float4 v; float s[4]; } tmp; + f = tanf( _VECTORMATH_PI_OVER_2 - fovyRadians * 0.5f ); + rangeInv = 1.0f / ( zNear - zFar ); + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + tmp.v = zero; + tmp.s[0] = f / aspect; + col0 = tmp.v; + tmp.v = zero; + tmp.s[1] = f; + col1 = tmp.v; + tmp.v = zero; + tmp.s[2] = ( zNear + zFar ) * rangeInv; + tmp.s[3] = -1.0f; + col2 = tmp.v; + tmp.v = zero; + tmp.s[2] = zNear * zFar * rangeInv * 2.0f; + col3 = tmp.v; + return Matrix4( + Vector4( col0 ), + Vector4( col1 ), + Vector4( col2 ), + Vector4( col3 ) + ); +} + +inline const Matrix4 Matrix4::frustum( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + vec_float4 lbf, rtn; + vec_float4 diff, sum, inv_diff; + vec_float4 diagonal, column, near2; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + union { vec_float4 v; float s[4]; } l, f, r, n, b, t; + l.s[0] = left; + f.s[0] = zFar; + r.s[0] = right; + n.s[0] = zNear; + b.s[0] = bottom; + t.s[0] = top; + lbf = vec_mergeh( l.v, f.v ); + rtn = vec_mergeh( r.v, n.v ); + lbf = vec_mergeh( lbf, b.v ); + rtn = vec_mergeh( rtn, t.v ); + diff = vec_sub( rtn, lbf ); + sum = vec_add( rtn, lbf ); + inv_diff = recipf4( diff ); + near2 = vec_splat( n.v, 0 ); + near2 = vec_add( near2, near2 ); + diagonal = vec_madd( near2, inv_diff, zero ); + column = vec_madd( sum, inv_diff, zero ); + return Matrix4( + Vector4( vec_sel( zero, diagonal, _VECTORMATH_MASK_0xF000 ) ), + Vector4( vec_sel( zero, diagonal, _VECTORMATH_MASK_0x0F00 ) ), + Vector4( vec_sel( column, ((vec_float4){-1.0f,-1.0f,-1.0f,-1.0f}), _VECTORMATH_MASK_0x000F ) ), + Vector4( vec_sel( zero, vec_madd( diagonal, vec_splat( f.v, 0 ), zero ), _VECTORMATH_MASK_0x00F0 ) ) + ); +} + +inline const Matrix4 Matrix4::orthographic( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + vec_float4 lbf, rtn; + vec_float4 diff, sum, inv_diff, neg_inv_diff; + vec_float4 diagonal, column; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + union { vec_float4 v; float s[4]; } l, f, r, n, b, t; + l.s[0] = left; + f.s[0] = zFar; + r.s[0] = right; + n.s[0] = zNear; + b.s[0] = bottom; + t.s[0] = top; + lbf = vec_mergeh( l.v, f.v ); + rtn = vec_mergeh( r.v, n.v ); + lbf = vec_mergeh( lbf, b.v ); + rtn = vec_mergeh( rtn, t.v ); + diff = vec_sub( rtn, lbf ); + sum = vec_add( rtn, lbf ); + inv_diff = recipf4( diff ); + neg_inv_diff = negatef4( inv_diff ); + diagonal = vec_add( inv_diff, inv_diff ); + column = vec_madd( sum, vec_sel( neg_inv_diff, inv_diff, _VECTORMATH_MASK_0x00F0 ), zero ); + return Matrix4( + Vector4( vec_sel( zero, diagonal, _VECTORMATH_MASK_0xF000 ) ), + Vector4( vec_sel( zero, diagonal, _VECTORMATH_MASK_0x0F00 ) ), + Vector4( vec_sel( zero, diagonal, _VECTORMATH_MASK_0x00F0 ) ), + Vector4( vec_sel( column, ((vec_float4){1.0f,1.0f,1.0f,1.0f}), _VECTORMATH_MASK_0x000F ) ) + ); +} + +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, boolInVec select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix4 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); + print( mat.getRow( 3 ) ); +} + +inline void print( const Matrix4 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Transform3::Transform3( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; +} + +inline Transform3::Transform3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +inline Transform3::Transform3( floatInVec scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +inline Transform3::Transform3( Vector3 _col0, Vector3 _col1, Vector3 _col2, Vector3 _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Transform3::Transform3( const Matrix3 & tfrm, Vector3 translateVec ) +{ + this->setUpper3x3( tfrm ); + this->setTranslation( translateVec ); +} + +inline Transform3::Transform3( Quat unitQuat, Vector3 translateVec ) +{ + this->setUpper3x3( Matrix3( unitQuat ) ); + this->setTranslation( translateVec ); +} + +inline Transform3 & Transform3::setCol0( Vector3 _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Transform3 & Transform3::setCol1( Vector3 _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Transform3 & Transform3::setCol2( Vector3 _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Transform3 & Transform3::setCol3( Vector3 _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Transform3 & Transform3::setCol( int col, Vector3 vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Transform3 & Transform3::setRow( int row, Vector4 vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Transform3 & Transform3::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +inline Transform3 & Transform3::setElem( int col, int row, floatInVec val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline const floatInVec Transform3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Transform3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Transform3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Transform3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Transform3::getCol3( ) const +{ + return mCol3; +} + +inline const Vector3 Transform3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Transform3::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector3 & Transform3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Transform3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Transform3 & Transform3::operator =( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; + return *this; +} + +inline const Transform3 inverse( const Transform3 & tfrm ) +{ + vec_float4 inv0, inv1, inv2, inv3; + vec_float4 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet; + vec_float4 xxxx, yyyy, zzzz; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + tmp2 = _vmathVfCross( tfrm.getCol0().get128(), tfrm.getCol1().get128() ); + tmp0 = _vmathVfCross( tfrm.getCol1().get128(), tfrm.getCol2().get128() ); + tmp1 = _vmathVfCross( tfrm.getCol2().get128(), tfrm.getCol0().get128() ); + inv3 = negatef4( tfrm.getCol3().get128() ); + dot = _vmathVfDot3( tmp2, tfrm.getCol2().get128() ); + dot = vec_splat( dot, 0 ); + invdet = recipf4( dot ); + tmp3 = vec_mergeh( tmp0, tmp2 ); + tmp4 = vec_mergel( tmp0, tmp2 ); + inv0 = vec_mergeh( tmp3, tmp1 ); + xxxx = vec_splat( inv3, 0 ); + inv1 = vec_perm( tmp3, tmp1, _VECTORMATH_PERM_ZBWX ); + inv2 = vec_perm( tmp4, tmp1, _VECTORMATH_PERM_XCYX ); + yyyy = vec_splat( inv3, 1 ); + zzzz = vec_splat( inv3, 2 ); + inv3 = vec_madd( inv0, xxxx, zero ); + inv3 = vec_madd( inv1, yyyy, inv3 ); + inv3 = vec_madd( inv2, zzzz, inv3 ); + inv0 = vec_madd( inv0, invdet, zero ); + inv1 = vec_madd( inv1, invdet, zero ); + inv2 = vec_madd( inv2, invdet, zero ); + inv3 = vec_madd( inv3, invdet, zero ); + return Transform3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ), + Vector3( inv3 ) + ); +} + +inline const Transform3 orthoInverse( const Transform3 & tfrm ) +{ + vec_float4 inv0, inv1, inv2, inv3; + vec_float4 tmp0, tmp1; + vec_float4 xxxx, yyyy, zzzz; + tmp0 = vec_mergeh( tfrm.getCol0().get128(), tfrm.getCol2().get128() ); + tmp1 = vec_mergel( tfrm.getCol0().get128(), tfrm.getCol2().get128() ); + inv3 = negatef4( tfrm.getCol3().get128() ); + inv0 = vec_mergeh( tmp0, tfrm.getCol1().get128() ); + xxxx = vec_splat( inv3, 0 ); + inv1 = vec_perm( tmp0, tfrm.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); + inv2 = vec_perm( tmp1, tfrm.getCol1().get128(), _VECTORMATH_PERM_XCYX ); + yyyy = vec_splat( inv3, 1 ); + zzzz = vec_splat( inv3, 2 ); + inv3 = vec_madd( inv0, xxxx, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + inv3 = vec_madd( inv1, yyyy, inv3 ); + inv3 = vec_madd( inv2, zzzz, inv3 ); + return Transform3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ), + Vector3( inv3 ) + ); +} + +inline const Transform3 absPerElem( const Transform3 & tfrm ) +{ + return Transform3( + absPerElem( tfrm.getCol0() ), + absPerElem( tfrm.getCol1() ), + absPerElem( tfrm.getCol2() ), + absPerElem( tfrm.getCol3() ) + ); +} + +inline const Vector3 Transform3::operator *( Vector3 vec ) const +{ + vec_float4 res; + vec_float4 xxxx, yyyy, zzzz; + xxxx = vec_splat( vec.get128(), 0 ); + yyyy = vec_splat( vec.get128(), 1 ); + zzzz = vec_splat( vec.get128(), 2 ); + res = vec_madd( mCol0.get128(), xxxx, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + res = vec_madd( mCol1.get128(), yyyy, res ); + res = vec_madd( mCol2.get128(), zzzz, res ); + return Vector3( res ); +} + +inline const Point3 Transform3::operator *( Point3 pnt ) const +{ + vec_float4 tmp0, tmp1, res; + vec_float4 xxxx, yyyy, zzzz; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + xxxx = vec_splat( pnt.get128(), 0 ); + yyyy = vec_splat( pnt.get128(), 1 ); + zzzz = vec_splat( pnt.get128(), 2 ); + tmp0 = vec_madd( mCol0.get128(), xxxx, zero ); + tmp1 = vec_madd( mCol1.get128(), yyyy, zero ); + tmp0 = vec_madd( mCol2.get128(), zzzz, tmp0 ); + tmp1 = vec_add( mCol3.get128(), tmp1 ); + res = vec_add( tmp0, tmp1 ); + return Point3( res ); +} + +inline const Transform3 Transform3::operator *( const Transform3 & tfrm ) const +{ + return Transform3( + ( *this * tfrm.mCol0 ), + ( *this * tfrm.mCol1 ), + ( *this * tfrm.mCol2 ), + Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) + ); +} + +inline Transform3 & Transform3::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) +{ + return Transform3( + mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), + mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), + mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), + mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) + ); +} + +inline const Transform3 Transform3::identity( ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +inline Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) +{ + mCol0 = tfrm.getCol0(); + mCol1 = tfrm.getCol1(); + mCol2 = tfrm.getCol2(); + return *this; +} + +inline const Matrix3 Transform3::getUpper3x3( ) const +{ + return Matrix3( mCol0, mCol1, mCol2 ); +} + +inline Transform3 & Transform3::setTranslation( Vector3 translateVec ) +{ + mCol3 = translateVec; + return *this; +} + +inline const Vector3 Transform3::getTranslation( ) const +{ + return mCol3; +} + +inline const Transform3 Transform3::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +inline const Transform3 Transform3::rotationX( floatInVec radians ) +{ + vec_float4 s, c, res1, res2; + vec_uint4 select_y, select_z; + vec_float4 zero; + select_y = _VECTORMATH_MASK_0x0F00; + select_z = _VECTORMATH_MASK_0x00F0; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( radians.get128(), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + return Transform3( + Vector3::xAxis( ), + Vector3( res1 ), + Vector3( res2 ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +inline const Transform3 Transform3::rotationY( floatInVec radians ) +{ + vec_float4 s, c, res0, res2; + vec_uint4 select_x, select_z; + vec_float4 zero; + select_x = _VECTORMATH_MASK_0xF000; + select_z = _VECTORMATH_MASK_0x00F0; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + return Transform3( + Vector3( res0 ), + Vector3::yAxis( ), + Vector3( res2 ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +inline const Transform3 Transform3::rotationZ( floatInVec radians ) +{ + vec_float4 s, c, res0, res1; + vec_uint4 select_x, select_y; + vec_float4 zero; + select_x = _VECTORMATH_MASK_0xF000; + select_y = _VECTORMATH_MASK_0x0F00; + zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + return Transform3( + Vector3( res0 ), + Vector3( res1 ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationZYX( Vector3 radiansXYZ ) +{ + vec_float4 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + angles = Vector4( radiansXYZ, 0.0f ).get128(); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + Z1 = vec_andc( Z1, (vec_float4)_VECTORMATH_MASK_0x000F ); + Y0 = vec_perm( negS, c, _VECTORMATH_PERM_BBYX ); + Y1 = vec_perm( c, s, _VECTORMATH_PERM_BBYX ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_madd( Z0, Y1, zero ); + return Transform3( + Vector3( vec_madd( Z0, Y0, zero ) ), + Vector3( vec_madd( Z1, X1, vec_madd( tmp, X0, zero ) ) ), + Vector3( vec_nmsub( Z1, X0, vec_madd( tmp, X1, zero ) ) ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotation( float radians, Vector3 unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +inline const Transform3 Transform3::rotation( floatInVec radians, Vector3 unitVec ) +{ + return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( 0.0f ) ); +} + +inline const Transform3 Transform3::rotation( Quat unitQuat ) +{ + return Transform3( Matrix3( unitQuat ), Vector3( 0.0f ) ); +} + +inline const Transform3 Transform3::scale( Vector3 scaleVec ) +{ + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + return Transform3( + Vector3( vec_sel( zero, scaleVec.get128(), _VECTORMATH_MASK_0xF000 ) ), + Vector3( vec_sel( zero, scaleVec.get128(), _VECTORMATH_MASK_0x0F00 ) ), + Vector3( vec_sel( zero, scaleVec.get128(), _VECTORMATH_MASK_0x00F0 ) ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 appendScale( const Transform3 & tfrm, Vector3 scaleVec ) +{ + return Transform3( + ( tfrm.getCol0() * scaleVec.getX( ) ), + ( tfrm.getCol1() * scaleVec.getY( ) ), + ( tfrm.getCol2() * scaleVec.getZ( ) ), + tfrm.getCol3() + ); +} + +inline const Transform3 prependScale( Vector3 scaleVec, const Transform3 & tfrm ) +{ + return Transform3( + mulPerElem( tfrm.getCol0(), scaleVec ), + mulPerElem( tfrm.getCol1(), scaleVec ), + mulPerElem( tfrm.getCol2(), scaleVec ), + mulPerElem( tfrm.getCol3(), scaleVec ) + ); +} + +inline const Transform3 Transform3::translation( Vector3 translateVec ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + translateVec + ); +} + +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, boolInVec select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Transform3 & tfrm ) +{ + print( tfrm.getRow( 0 ) ); + print( tfrm.getRow( 1 ) ); + print( tfrm.getRow( 2 ) ); +} + +inline void print( const Transform3 & tfrm, const char * name ) +{ + printf("%s:\n", name); + print( tfrm ); +} + +#endif + +inline Quat::Quat( const Matrix3 & tfrm ) +{ + vec_float4 res; + vec_float4 col0, col1, col2; + vec_float4 xx_yy, xx_yy_zz_xx, yy_zz_xx_yy, zz_xx_yy_zz, diagSum, diagDiff; + vec_float4 zy_xz_yx, yz_zx_xy, sum, diff; + vec_float4 radicand, invSqrt, scale; + vec_float4 res0, res1, res2, res3; + vec_float4 xx, yy, zz; + vec_uint4 select_x = _VECTORMATH_MASK_0xF000; + vec_uint4 select_y = _VECTORMATH_MASK_0x0F00; + vec_uint4 select_z = _VECTORMATH_MASK_0x00F0; + vec_uint4 select_w = _VECTORMATH_MASK_0x000F; + vec_float4 zero = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); + + col0 = tfrm.getCol0().get128(); + col1 = tfrm.getCol1().get128(); + col2 = tfrm.getCol2().get128(); + + /* four cases: */ + /* trace > 0 */ + /* else */ + /* xx largest diagonal element */ + /* yy largest diagonal element */ + /* zz largest diagonal element */ + + /* compute quaternion for each case */ + + xx_yy = vec_sel( col0, col1, select_y ); + xx_yy_zz_xx = vec_perm( xx_yy, col2, _VECTORMATH_PERM_XYCX ); + yy_zz_xx_yy = vec_perm( xx_yy, col2, _VECTORMATH_PERM_YCXY ); + zz_xx_yy_zz = vec_perm( xx_yy, col2, _VECTORMATH_PERM_CXYC ); + + diagSum = vec_add( vec_add( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); + diagDiff = vec_sub( vec_sub( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); + radicand = vec_add( vec_sel( diagDiff, diagSum, select_w ), ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); + invSqrt = rsqrtf4( radicand ); + + zy_xz_yx = vec_sel( col0, col1, select_z ); + zy_xz_yx = vec_perm( zy_xz_yx, col2, _VECTORMATH_PERM_ZAYX ); + yz_zx_xy = vec_sel( col0, col1, select_x ); + yz_zx_xy = vec_perm( yz_zx_xy, col2, _VECTORMATH_PERM_BZXX ); + + sum = vec_add( zy_xz_yx, yz_zx_xy ); + diff = vec_sub( zy_xz_yx, yz_zx_xy ); + + scale = vec_madd( invSqrt, ((vec_float4){0.5f,0.5f,0.5f,0.5f}), zero ); + res0 = vec_perm( sum, diff, _VECTORMATH_PERM_XZYA ); + res1 = vec_perm( sum, diff, _VECTORMATH_PERM_ZXXB ); + res2 = vec_perm( sum, diff, _VECTORMATH_PERM_YXXC ); + res3 = diff; + res0 = vec_sel( res0, radicand, select_x ); + res1 = vec_sel( res1, radicand, select_y ); + res2 = vec_sel( res2, radicand, select_z ); + res3 = vec_sel( res3, radicand, select_w ); + res0 = vec_madd( res0, vec_splat( scale, 0 ), zero ); + res1 = vec_madd( res1, vec_splat( scale, 1 ), zero ); + res2 = vec_madd( res2, vec_splat( scale, 2 ), zero ); + res3 = vec_madd( res3, vec_splat( scale, 3 ), zero ); + + /* determine case and select answer */ + + xx = vec_splat( col0, 0 ); + yy = vec_splat( col1, 1 ); + zz = vec_splat( col2, 2 ); + res = vec_sel( res0, res1, vec_cmpgt( yy, xx ) ); + res = vec_sel( res, res2, vec_and( vec_cmpgt( zz, xx ), vec_cmpgt( zz, yy ) ) ); + res = vec_sel( res, res3, vec_cmpgt( vec_splat( diagSum, 0 ), zero ) ); + mVec128 = res; +} + +inline const Matrix3 outer( Vector3 tfrm0, Vector3 tfrm1 ) +{ + return Matrix3( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ) + ); +} + +inline const Matrix4 outer( Vector4 tfrm0, Vector4 tfrm1 ) +{ + return Matrix4( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ), + ( tfrm0 * tfrm1.getW( ) ) + ); +} + +inline const Vector3 rowMul( Vector3 vec, const Matrix3 & mat ) +{ + vec_float4 tmp0, tmp1, mcol0, mcol1, mcol2, res; + vec_float4 xxxx, yyyy, zzzz; + tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp1 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); + xxxx = vec_splat( vec.get128(), 0 ); + mcol0 = vec_mergeh( tmp0, mat.getCol1().get128() ); + mcol1 = vec_perm( tmp0, mat.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); + mcol2 = vec_perm( tmp1, mat.getCol1().get128(), _VECTORMATH_PERM_XCYX ); + yyyy = vec_splat( vec.get128(), 1 ); + res = vec_madd( mcol0, xxxx, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + zzzz = vec_splat( vec.get128(), 2 ); + res = vec_madd( mcol1, yyyy, res ); + res = vec_madd( mcol2, zzzz, res ); + return Vector3( res ); +} + +inline const Matrix3 crossMatrix( Vector3 vec ) +{ + vec_float4 neg, res0, res1, res2; + neg = negatef4( vec.get128() ); + res0 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_XZBX ); + res1 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_CXXX ); + res2 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_YAXX ); + res0 = vec_andc( res0, (vec_float4)_VECTORMATH_MASK_0xF000 ); + res1 = vec_andc( res1, (vec_float4)_VECTORMATH_MASK_0x0F00 ); + res2 = vec_andc( res2, (vec_float4)_VECTORMATH_MASK_0x00F0 ); + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +inline const Matrix3 crossMatrixMul( Vector3 vec, const Matrix3 & mat ) +{ + return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); +} + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/cpp/mat_soa.h b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/mat_soa.h new file mode 100644 index 0000000..7868cfd --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/mat_soa.h @@ -0,0 +1,1744 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_SOA_CPP_H +#define _VECTORMATH_MAT_SOA_CPP_H + +namespace Vectormath { +namespace Soa { + +//----------------------------------------------------------------------------- +// Constants + +#define _VECTORMATH_PI_OVER_2 1.570796327f + +//----------------------------------------------------------------------------- +// Definitions + +inline Matrix3::Matrix3( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; +} + +inline Matrix3::Matrix3( vec_float4 scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +inline Matrix3::Matrix3( const Quat & unitQuat ) +{ + vec_float4 qx, qy, qz, qw, qx2, qy2, qz2, qxqx2, qyqy2, qzqz2, qxqy2, qyqz2, qzqw2, qxqz2, qyqw2, qxqw2; + qx = unitQuat.getX(); + qy = unitQuat.getY(); + qz = unitQuat.getZ(); + qw = unitQuat.getW(); + qx2 = vec_add( qx, qx ); + qy2 = vec_add( qy, qy ); + qz2 = vec_add( qz, qz ); + qxqx2 = vec_madd( qx, qx2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qxqy2 = vec_madd( qx, qy2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qxqz2 = vec_madd( qx, qz2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qxqw2 = vec_madd( qw, qx2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qyqy2 = vec_madd( qy, qy2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qyqz2 = vec_madd( qy, qz2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qyqw2 = vec_madd( qw, qy2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qzqz2 = vec_madd( qz, qz2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qzqw2 = vec_madd( qw, qz2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + mCol0 = Vector3( vec_sub( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), qyqy2 ), qzqz2 ), vec_add( qxqy2, qzqw2 ), vec_sub( qxqz2, qyqw2 ) ); + mCol1 = Vector3( vec_sub( qxqy2, qzqw2 ), vec_sub( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), qxqx2 ), qzqz2 ), vec_add( qyqz2, qxqw2 ) ); + mCol2 = Vector3( vec_add( qxqz2, qyqw2 ), vec_sub( qyqz2, qxqw2 ), vec_sub( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), qxqx2 ), qyqy2 ) ); +} + +inline Matrix3::Matrix3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; +} + +inline Matrix3::Matrix3( const Aos::Matrix3 & mat ) +{ + mCol0 = Vector3( mat.getCol0() ); + mCol1 = Vector3( mat.getCol1() ); + mCol2 = Vector3( mat.getCol2() ); +} + +inline Matrix3::Matrix3( const Aos::Matrix3 & mat0, const Aos::Matrix3 & mat1, const Aos::Matrix3 & mat2, const Aos::Matrix3 & mat3 ) +{ + mCol0 = Vector3( mat0.getCol0(), mat1.getCol0(), mat2.getCol0(), mat3.getCol0() ); + mCol1 = Vector3( mat0.getCol1(), mat1.getCol1(), mat2.getCol1(), mat3.getCol1() ); + mCol2 = Vector3( mat0.getCol2(), mat1.getCol2(), mat2.getCol2(), mat3.getCol2() ); +} + +inline void Matrix3::get4Aos( Aos::Matrix3 & result0, Aos::Matrix3 & result1, Aos::Matrix3 & result2, Aos::Matrix3 & result3 ) const +{ + Aos::Vector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + mCol0.get4Aos( tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3 ); + result0.setCol0( tmpV3_0 ); + result1.setCol0( tmpV3_1 ); + result2.setCol0( tmpV3_2 ); + result3.setCol0( tmpV3_3 ); + mCol1.get4Aos( tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3 ); + result0.setCol1( tmpV3_0 ); + result1.setCol1( tmpV3_1 ); + result2.setCol1( tmpV3_2 ); + result3.setCol1( tmpV3_3 ); + mCol2.get4Aos( tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3 ); + result0.setCol2( tmpV3_0 ); + result1.setCol2( tmpV3_1 ); + result2.setCol2( tmpV3_2 ); + result3.setCol2( tmpV3_3 ); +} + +inline Matrix3 & Matrix3::setCol0( const Vector3 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix3 & Matrix3::setCol1( const Vector3 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix3 & Matrix3::setCol2( const Vector3 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix3 & Matrix3::setCol( int col, const Vector3 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix3 & Matrix3::setRow( int row, const Vector3 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + return *this; +} + +inline Matrix3 & Matrix3::setElem( int col, int row, vec_float4 val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline vec_float4 Matrix3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Matrix3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Matrix3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Matrix3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Matrix3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::getRow( int row ) const +{ + return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); +} + +inline Vector3 & Matrix3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix3 & Matrix3::operator =( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + return *this; +} + +inline const Matrix3 transpose( const Matrix3 & mat ) +{ + return Matrix3( + Vector3( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX() ), + Vector3( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY() ), + Vector3( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ() ) + ); +} + +inline const Matrix3 inverse( const Matrix3 & mat ) +{ + Vector3 tmp0, tmp1, tmp2; + vec_float4 detinv; + tmp0 = cross( mat.getCol1(), mat.getCol2() ); + tmp1 = cross( mat.getCol2(), mat.getCol0() ); + tmp2 = cross( mat.getCol0(), mat.getCol1() ); + detinv = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), dot( mat.getCol2(), tmp2 ) ); + return Matrix3( + Vector3( vec_madd( tmp0.getX(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp1.getX(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp2.getX(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + Vector3( vec_madd( tmp0.getY(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp1.getY(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp2.getY(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + Vector3( vec_madd( tmp0.getZ(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp1.getZ(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp2.getZ(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) + ); +} + +inline vec_float4 determinant( const Matrix3 & mat ) +{ + return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); +} + +inline const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ) + ); +} + +inline const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix3 Matrix3::operator -( ) const +{ + return Matrix3( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ) + ); +} + +inline const Matrix3 absPerElem( const Matrix3 & mat ) +{ + return Matrix3( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::operator *( vec_float4 scalar ) const +{ + return Matrix3( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ) + ); +} + +inline Matrix3 & Matrix3::operator *=( vec_float4 scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix3 operator *( vec_float4 scalar, const Matrix3 & mat ) +{ + return mat * scalar; +} + +inline const Vector3 Matrix3::operator *( const Vector3 & vec ) const +{ + return Vector3( + vec_add( vec_add( vec_madd( mCol0.getX(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getX(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getX(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_add( vec_add( vec_madd( mCol0.getY(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getY(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getY(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_add( vec_add( vec_madd( mCol0.getZ(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getZ(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getZ(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) + ); +} + +inline const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const +{ + return Matrix3( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) +{ + return Matrix3( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::identity( ) +{ + return Matrix3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationX( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Matrix3( + Vector3::xAxis( ), + Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), c, s ), + Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), negatef4( s ), c ) + ); +} + +inline const Matrix3 Matrix3::rotationY( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Matrix3( + Vector3( c, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), negatef4( s ) ), + Vector3::yAxis( ), + Vector3( s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), c ) + ); +} + +inline const Matrix3 Matrix3::rotationZ( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Matrix3( + Vector3( c, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector3( negatef4( s ), c, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationZYX( const Vector3 & radiansXYZ ) +{ + vec_float4 sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sincosf4( radiansXYZ.getX(), &sX, &cX ); + sincosf4( radiansXYZ.getY(), &sY, &cY ); + sincosf4( radiansXYZ.getZ(), &sZ, &cZ ); + tmp0 = vec_madd( cZ, sY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + tmp1 = vec_madd( sZ, sY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + return Matrix3( + Vector3( vec_madd( cZ, cY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, cY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), negatef4( sY ) ), + Vector3( vec_sub( vec_madd( tmp0, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_add( vec_madd( tmp1, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( cZ, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( cY, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + Vector3( vec_add( vec_madd( tmp0, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_sub( vec_madd( tmp1, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( cZ, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( cY, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( vec_float4 radians, const Vector3 & unitVec ) +{ + vec_float4 x, y, z, s, c, oneMinusC, xy, yz, zx; + sincosf4( radians, &s, &c ); + x = unitVec.getX(); + y = unitVec.getY(); + z = unitVec.getZ(); + xy = vec_madd( x, y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + yz = vec_madd( y, z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + zx = vec_madd( z, x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + oneMinusC = vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), c ); + return Matrix3( + Vector3( vec_add( vec_madd( vec_madd( x, x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), c ), vec_add( vec_madd( xy, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( z, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_sub( vec_madd( zx, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( y, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ), + Vector3( vec_sub( vec_madd( xy, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( z, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_add( vec_madd( vec_madd( y, y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), c ), vec_add( vec_madd( yz, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( x, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ), + Vector3( vec_add( vec_madd( zx, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( y, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_sub( vec_madd( yz, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( x, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_add( vec_madd( vec_madd( z, z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), c ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( const Quat & unitQuat ) +{ + return Matrix3( unitQuat ); +} + +inline const Matrix3 Matrix3::scale( const Vector3 & scaleVec ) +{ + return Matrix3( + Vector3( scaleVec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), scaleVec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), scaleVec.getZ() ) + ); +} + +inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ) +{ + return Matrix3( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ) + ); +} + +inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ) +{ + return Matrix3( + mulPerElem( mat.getCol0(), scaleVec ), + mulPerElem( mat.getCol1(), scaleVec ), + mulPerElem( mat.getCol2(), scaleVec ) + ); +} + +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, vec_uint4 select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix3 & mat ) +{ + Aos::Matrix3 mat0, mat1, mat2, mat3; + mat.get4Aos( mat0, mat1, mat2, mat3 ); + printf("slot 0:\n"); + print( mat0 ); + printf("slot 1:\n"); + print( mat1 ); + printf("slot 2:\n"); + print( mat2 ); + printf("slot 3:\n"); + print( mat3 ); +} + +inline void print( const Matrix3 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Matrix4::Matrix4( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; +} + +inline Matrix4::Matrix4( vec_float4 scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +inline Matrix4::Matrix4( const Transform3 & mat ) +{ + mCol0 = Vector4( mat.getCol0(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + mCol1 = Vector4( mat.getCol1(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + mCol2 = Vector4( mat.getCol2(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + mCol3 = Vector4( mat.getCol3(), ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); +} + +inline Matrix4::Matrix4( const Vector4 & _col0, const Vector4 & _col1, const Vector4 & _col2, const Vector4 & _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Matrix4::Matrix4( const Matrix3 & mat, const Vector3 & translateVec ) +{ + mCol0 = Vector4( mat.getCol0(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + mCol1 = Vector4( mat.getCol1(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + mCol2 = Vector4( mat.getCol2(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + mCol3 = Vector4( translateVec, ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); +} + +inline Matrix4::Matrix4( const Quat & unitQuat, const Vector3 & translateVec ) +{ + Matrix3 mat; + mat = Matrix3( unitQuat ); + mCol0 = Vector4( mat.getCol0(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + mCol1 = Vector4( mat.getCol1(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + mCol2 = Vector4( mat.getCol2(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + mCol3 = Vector4( translateVec, ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); +} + +inline Matrix4::Matrix4( const Aos::Matrix4 & mat ) +{ + mCol0 = Vector4( mat.getCol0() ); + mCol1 = Vector4( mat.getCol1() ); + mCol2 = Vector4( mat.getCol2() ); + mCol3 = Vector4( mat.getCol3() ); +} + +inline Matrix4::Matrix4( const Aos::Matrix4 & mat0, const Aos::Matrix4 & mat1, const Aos::Matrix4 & mat2, const Aos::Matrix4 & mat3 ) +{ + mCol0 = Vector4( mat0.getCol0(), mat1.getCol0(), mat2.getCol0(), mat3.getCol0() ); + mCol1 = Vector4( mat0.getCol1(), mat1.getCol1(), mat2.getCol1(), mat3.getCol1() ); + mCol2 = Vector4( mat0.getCol2(), mat1.getCol2(), mat2.getCol2(), mat3.getCol2() ); + mCol3 = Vector4( mat0.getCol3(), mat1.getCol3(), mat2.getCol3(), mat3.getCol3() ); +} + +inline void Matrix4::get4Aos( Aos::Matrix4 & result0, Aos::Matrix4 & result1, Aos::Matrix4 & result2, Aos::Matrix4 & result3 ) const +{ + Aos::Vector4 tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3; + mCol0.get4Aos( tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3 ); + result0.setCol0( tmpV4_0 ); + result1.setCol0( tmpV4_1 ); + result2.setCol0( tmpV4_2 ); + result3.setCol0( tmpV4_3 ); + mCol1.get4Aos( tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3 ); + result0.setCol1( tmpV4_0 ); + result1.setCol1( tmpV4_1 ); + result2.setCol1( tmpV4_2 ); + result3.setCol1( tmpV4_3 ); + mCol2.get4Aos( tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3 ); + result0.setCol2( tmpV4_0 ); + result1.setCol2( tmpV4_1 ); + result2.setCol2( tmpV4_2 ); + result3.setCol2( tmpV4_3 ); + mCol3.get4Aos( tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3 ); + result0.setCol3( tmpV4_0 ); + result1.setCol3( tmpV4_1 ); + result2.setCol3( tmpV4_2 ); + result3.setCol3( tmpV4_3 ); +} + +inline Matrix4 & Matrix4::setCol0( const Vector4 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix4 & Matrix4::setCol1( const Vector4 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix4 & Matrix4::setCol2( const Vector4 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix4 & Matrix4::setCol3( const Vector4 & _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Matrix4 & Matrix4::setCol( int col, const Vector4 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix4 & Matrix4::setRow( int row, const Vector4 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Matrix4 & Matrix4::setElem( int col, int row, vec_float4 val ) +{ + Vector4 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline vec_float4 Matrix4::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector4 Matrix4::getCol0( ) const +{ + return mCol0; +} + +inline const Vector4 Matrix4::getCol1( ) const +{ + return mCol1; +} + +inline const Vector4 Matrix4::getCol2( ) const +{ + return mCol2; +} + +inline const Vector4 Matrix4::getCol3( ) const +{ + return mCol3; +} + +inline const Vector4 Matrix4::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector4 & Matrix4::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix4 & Matrix4::operator =( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; + return *this; +} + +inline const Matrix4 transpose( const Matrix4 & mat ) +{ + return Matrix4( + Vector4( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX(), mat.getCol3().getX() ), + Vector4( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY(), mat.getCol3().getY() ), + Vector4( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ(), mat.getCol3().getZ() ), + Vector4( mat.getCol0().getW(), mat.getCol1().getW(), mat.getCol2().getW(), mat.getCol3().getW() ) + ); +} + +inline const Matrix4 inverse( const Matrix4 & mat ) +{ + Vector4 res0, res1, res2, res3; + vec_float4 mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, detInv; + mA = mat.getCol0().getX(); + mB = mat.getCol0().getY(); + mC = mat.getCol0().getZ(); + mD = mat.getCol0().getW(); + mE = mat.getCol1().getX(); + mF = mat.getCol1().getY(); + mG = mat.getCol1().getZ(); + mH = mat.getCol1().getW(); + mI = mat.getCol2().getX(); + mJ = mat.getCol2().getY(); + mK = mat.getCol2().getZ(); + mL = mat.getCol2().getW(); + mM = mat.getCol3().getX(); + mN = mat.getCol3().getY(); + mO = mat.getCol3().getZ(); + mP = mat.getCol3().getW(); + tmp0 = vec_sub( vec_madd( mK, mD, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mC, mL, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp1 = vec_sub( vec_madd( mO, mH, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mG, mP, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp2 = vec_sub( vec_madd( mB, mK, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mJ, mC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp3 = vec_sub( vec_madd( mF, mO, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mN, mG, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp4 = vec_sub( vec_madd( mJ, mD, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mB, mL, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp5 = vec_sub( vec_madd( mN, mH, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mF, mP, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + res0.setX( vec_sub( vec_sub( vec_madd( mJ, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mL, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mK, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); + res0.setY( vec_sub( vec_sub( vec_madd( mN, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mP, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mO, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); + res0.setZ( vec_sub( vec_add( vec_madd( mD, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mC, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mB, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); + res0.setW( vec_sub( vec_add( vec_madd( mH, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mG, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mF, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); + detInv = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec_add( vec_add( vec_add( vec_madd( mA, res0.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mE, res0.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mI, res0.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mM, res0.getW(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); + res1.setX( vec_madd( mI, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + res1.setY( vec_madd( mM, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + res1.setZ( vec_madd( mA, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + res1.setW( vec_madd( mE, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + res3.setX( vec_madd( mI, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + res3.setY( vec_madd( mM, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + res3.setZ( vec_madd( mA, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + res3.setW( vec_madd( mE, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + res2.setX( vec_madd( mI, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + res2.setY( vec_madd( mM, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + res2.setZ( vec_madd( mA, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + res2.setW( vec_madd( mE, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp0 = vec_sub( vec_madd( mI, mB, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mA, mJ, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp1 = vec_sub( vec_madd( mM, mF, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mE, mN, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp2 = vec_sub( vec_madd( mI, mD, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mA, mL, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp3 = vec_sub( vec_madd( mM, mH, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mE, mP, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp4 = vec_sub( vec_madd( mI, mC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mA, mK, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp5 = vec_sub( vec_madd( mM, mG, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mE, mO, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + res2.setX( vec_add( vec_sub( vec_madd( mL, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mJ, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res2.getX() ) ); + res2.setY( vec_add( vec_sub( vec_madd( mP, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mN, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res2.getY() ) ); + res2.setZ( vec_sub( vec_sub( vec_madd( mB, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mD, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res2.getZ() ) ); + res2.setW( vec_sub( vec_sub( vec_madd( mF, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mH, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res2.getW() ) ); + res3.setX( vec_add( vec_sub( vec_madd( mJ, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mK, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res3.getX() ) ); + res3.setY( vec_add( vec_sub( vec_madd( mN, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mO, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res3.getY() ) ); + res3.setZ( vec_sub( vec_sub( vec_madd( mC, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mB, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res3.getZ() ) ); + res3.setW( vec_sub( vec_sub( vec_madd( mG, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mF, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res3.getW() ) ); + res1.setX( vec_sub( vec_sub( vec_madd( mK, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mL, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res1.getX() ) ); + res1.setY( vec_sub( vec_sub( vec_madd( mO, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mP, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res1.getY() ) ); + res1.setZ( vec_add( vec_sub( vec_madd( mD, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mC, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res1.getZ() ) ); + res1.setW( vec_add( vec_sub( vec_madd( mH, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mG, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), res1.getW() ) ); + return Matrix4( + ( res0 * detInv ), + ( res1 * detInv ), + ( res2 * detInv ), + ( res3 * detInv ) + ); +} + +inline const Matrix4 affineInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( inverse( affineMat ) ); +} + +inline const Matrix4 orthoInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( orthoInverse( affineMat ) ); +} + +inline vec_float4 determinant( const Matrix4 & mat ) +{ + vec_float4 dx, dy, dz, dw, mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + mA = mat.getCol0().getX(); + mB = mat.getCol0().getY(); + mC = mat.getCol0().getZ(); + mD = mat.getCol0().getW(); + mE = mat.getCol1().getX(); + mF = mat.getCol1().getY(); + mG = mat.getCol1().getZ(); + mH = mat.getCol1().getW(); + mI = mat.getCol2().getX(); + mJ = mat.getCol2().getY(); + mK = mat.getCol2().getZ(); + mL = mat.getCol2().getW(); + mM = mat.getCol3().getX(); + mN = mat.getCol3().getY(); + mO = mat.getCol3().getZ(); + mP = mat.getCol3().getW(); + tmp0 = vec_sub( vec_madd( mK, mD, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mC, mL, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp1 = vec_sub( vec_madd( mO, mH, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mG, mP, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp2 = vec_sub( vec_madd( mB, mK, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mJ, mC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp3 = vec_sub( vec_madd( mF, mO, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mN, mG, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp4 = vec_sub( vec_madd( mJ, mD, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mB, mL, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmp5 = vec_sub( vec_madd( mN, mH, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mF, mP, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + dx = vec_sub( vec_sub( vec_madd( mJ, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mL, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mK, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + dy = vec_sub( vec_sub( vec_madd( mN, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mP, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mO, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + dz = vec_sub( vec_add( vec_madd( mD, tmp3, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mC, tmp5, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mB, tmp1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + dw = vec_sub( vec_add( vec_madd( mH, tmp2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mG, tmp4, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mF, tmp0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return vec_add( vec_add( vec_add( vec_madd( mA, dx, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mE, dy, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mI, dz, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mM, dw, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +inline const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ), + ( mCol3 + mat.mCol3 ) + ); +} + +inline const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ), + ( mCol3 - mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix4 Matrix4::operator -( ) const +{ + return Matrix4( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ), + ( -mCol3 ) + ); +} + +inline const Matrix4 absPerElem( const Matrix4 & mat ) +{ + return Matrix4( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ), + absPerElem( mat.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::operator *( vec_float4 scalar ) const +{ + return Matrix4( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ), + ( mCol3 * scalar ) + ); +} + +inline Matrix4 & Matrix4::operator *=( vec_float4 scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix4 operator *( vec_float4 scalar, const Matrix4 & mat ) +{ + return mat * scalar; +} + +inline const Vector4 Matrix4::operator *( const Vector4 & vec ) const +{ + return Vector4( + vec_add( vec_add( vec_add( vec_madd( mCol0.getX(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getX(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getX(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol3.getX(), vec.getW(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_add( vec_add( vec_add( vec_madd( mCol0.getY(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getY(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getY(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol3.getY(), vec.getW(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_add( vec_add( vec_add( vec_madd( mCol0.getZ(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getZ(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getZ(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol3.getZ(), vec.getW(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_add( vec_add( vec_add( vec_madd( mCol0.getW(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getW(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getW(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol3.getW(), vec.getW(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) + ); +} + +inline const Vector4 Matrix4::operator *( const Vector3 & vec ) const +{ + return Vector4( + vec_add( vec_add( vec_madd( mCol0.getX(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getX(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getX(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_add( vec_add( vec_madd( mCol0.getY(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getY(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getY(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_add( vec_add( vec_madd( mCol0.getZ(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getZ(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getZ(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_add( vec_add( vec_madd( mCol0.getW(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getW(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getW(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) + ); +} + +inline const Vector4 Matrix4::operator *( const Point3 & pnt ) const +{ + return Vector4( + vec_add( vec_add( vec_add( vec_madd( mCol0.getX(), pnt.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getX(), pnt.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getX(), pnt.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), mCol3.getX() ), + vec_add( vec_add( vec_add( vec_madd( mCol0.getY(), pnt.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getY(), pnt.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getY(), pnt.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), mCol3.getY() ), + vec_add( vec_add( vec_add( vec_madd( mCol0.getZ(), pnt.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getZ(), pnt.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getZ(), pnt.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), mCol3.getZ() ), + vec_add( vec_add( vec_add( vec_madd( mCol0.getW(), pnt.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getW(), pnt.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getW(), pnt.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), mCol3.getW() ) + ); +} + +inline const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const +{ + return Matrix4( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ), + ( *this * mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const +{ + return Matrix4( + ( *this * tfrm.getCol0() ), + ( *this * tfrm.getCol1() ), + ( *this * tfrm.getCol2() ), + ( *this * Point3( tfrm.getCol3() ) ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) +{ + return Matrix4( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ), + mulPerElem( mat0.getCol3(), mat1.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::identity( ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) +{ + mCol0.setXYZ( mat3.getCol0() ); + mCol1.setXYZ( mat3.getCol1() ); + mCol2.setXYZ( mat3.getCol2() ); + return *this; +} + +inline const Matrix3 Matrix4::getUpper3x3( ) const +{ + return Matrix3( + mCol0.getXYZ( ), + mCol1.getXYZ( ), + mCol2.getXYZ( ) + ); +} + +inline Matrix4 & Matrix4::setTranslation( const Vector3 & translateVec ) +{ + mCol3.setXYZ( translateVec ); + return *this; +} + +inline const Vector3 Matrix4::getTranslation( ) const +{ + return mCol3.getXYZ( ); +} + +inline const Matrix4 Matrix4::rotationX( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Matrix4( + Vector4::xAxis( ), + Vector4( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), c, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), negatef4( s ), c, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationY( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Matrix4( + Vector4( c, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), negatef4( s ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4::yAxis( ), + Vector4( s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), c, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZ( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Matrix4( + Vector4( c, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4( negatef4( s ), c, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZYX( const Vector3 & radiansXYZ ) +{ + vec_float4 sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sincosf4( radiansXYZ.getX(), &sX, &cX ); + sincosf4( radiansXYZ.getY(), &sY, &cY ); + sincosf4( radiansXYZ.getZ(), &sZ, &cZ ); + tmp0 = vec_madd( cZ, sY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + tmp1 = vec_madd( sZ, sY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + return Matrix4( + Vector4( vec_madd( cZ, cY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, cY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), negatef4( sY ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4( vec_sub( vec_madd( tmp0, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_add( vec_madd( tmp1, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( cZ, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( cY, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4( vec_add( vec_madd( tmp0, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_sub( vec_madd( tmp1, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( cZ, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( cY, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( vec_float4 radians, const Vector3 & unitVec ) +{ + vec_float4 x, y, z, s, c, oneMinusC, xy, yz, zx; + sincosf4( radians, &s, &c ); + x = unitVec.getX(); + y = unitVec.getY(); + z = unitVec.getZ(); + xy = vec_madd( x, y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + yz = vec_madd( y, z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + zx = vec_madd( z, x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + oneMinusC = vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), c ); + return Matrix4( + Vector4( vec_add( vec_madd( vec_madd( x, x, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), c ), vec_add( vec_madd( xy, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( z, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_sub( vec_madd( zx, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( y, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4( vec_sub( vec_madd( xy, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( z, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_add( vec_madd( vec_madd( y, y, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), c ), vec_add( vec_madd( yz, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( x, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4( vec_add( vec_madd( zx, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( y, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_sub( vec_madd( yz, oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( x, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_add( vec_madd( vec_madd( z, z, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), oneMinusC, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), c ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( const Quat & unitQuat ) +{ + return Matrix4( Transform3::rotation( unitQuat ) ); +} + +inline const Matrix4 Matrix4::scale( const Vector3 & scaleVec ) +{ + return Matrix4( + Vector4( scaleVec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), scaleVec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), scaleVec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ) +{ + return Matrix4( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ), + mat.getCol3() + ); +} + +inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ) +{ + Vector4 scale4; + scale4 = Vector4( scaleVec, ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); + return Matrix4( + mulPerElem( mat.getCol0(), scale4 ), + mulPerElem( mat.getCol1(), scale4 ), + mulPerElem( mat.getCol2(), scale4 ), + mulPerElem( mat.getCol3(), scale4 ) + ); +} + +inline const Matrix4 Matrix4::translation( const Vector3 & translateVec ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4( translateVec, ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ) + ); +} + +inline const Matrix4 Matrix4::lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ) +{ + Matrix4 m4EyeFrame; + Vector3 v3X, v3Y, v3Z; + v3Y = normalize( upVec ); + v3Z = normalize( ( eyePos - lookAtPos ) ); + v3X = normalize( cross( v3Y, v3Z ) ); + v3Y = cross( v3Z, v3X ); + m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); + return orthoInverse( m4EyeFrame ); +} + +inline const Matrix4 Matrix4::perspective( vec_float4 fovyRadians, vec_float4 aspect, vec_float4 zNear, vec_float4 zFar ) +{ + vec_float4 f, rangeInv; + f = tanf4( vec_sub( ((vec_float4){_VECTORMATH_PI_OVER_2,_VECTORMATH_PI_OVER_2,_VECTORMATH_PI_OVER_2,_VECTORMATH_PI_OVER_2}), vec_madd( ((vec_float4){0.5f,0.5f,0.5f,0.5f}), fovyRadians, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); + rangeInv = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec_sub( zNear, zFar ) ); + return Matrix4( + Vector4( divf4( f, aspect ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), f, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), vec_madd( vec_add( zNear, zFar ), rangeInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){-1.0f,-1.0f,-1.0f,-1.0f}) ), + Vector4( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), vec_madd( vec_madd( vec_madd( zNear, zFar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), rangeInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){2.0f,2.0f,2.0f,2.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline const Matrix4 Matrix4::frustum( vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ) +{ + vec_float4 sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf, n2; + sum_rl = vec_add( right, left ); + sum_tb = vec_add( top, bottom ); + sum_nf = vec_add( zNear, zFar ); + inv_rl = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec_sub( right, left ) ); + inv_tb = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec_sub( top, bottom ) ); + inv_nf = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec_sub( zNear, zFar ) ); + n2 = vec_add( zNear, zNear ); + return Matrix4( + Vector4( vec_madd( n2, inv_rl, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), vec_madd( n2, inv_tb, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4( vec_madd( sum_rl, inv_rl, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sum_tb, inv_tb, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sum_nf, inv_nf, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){-1.0f,-1.0f,-1.0f,-1.0f}) ), + Vector4( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), vec_madd( vec_madd( n2, inv_nf, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), zFar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline const Matrix4 Matrix4::orthographic( vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ) +{ + vec_float4 sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf; + sum_rl = vec_add( right, left ); + sum_tb = vec_add( top, bottom ); + sum_nf = vec_add( zNear, zFar ); + inv_rl = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec_sub( right, left ) ); + inv_tb = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec_sub( top, bottom ) ); + inv_nf = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec_sub( zNear, zFar ) ); + return Matrix4( + Vector4( vec_add( inv_rl, inv_rl ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), vec_add( inv_tb, inv_tb ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), vec_add( inv_nf, inv_nf ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector4( vec_madd( negatef4( sum_rl ), inv_rl, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( negatef4( sum_tb ), inv_tb, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sum_nf, inv_nf, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ) + ); +} + +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, vec_uint4 select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix4 & mat ) +{ + Aos::Matrix4 mat0, mat1, mat2, mat3; + mat.get4Aos( mat0, mat1, mat2, mat3 ); + printf("slot 0:\n"); + print( mat0 ); + printf("slot 1:\n"); + print( mat1 ); + printf("slot 2:\n"); + print( mat2 ); + printf("slot 3:\n"); + print( mat3 ); +} + +inline void print( const Matrix4 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Transform3::Transform3( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; +} + +inline Transform3::Transform3( vec_float4 scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +inline Transform3::Transform3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2, const Vector3 & _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Transform3::Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ) +{ + this->setUpper3x3( tfrm ); + this->setTranslation( translateVec ); +} + +inline Transform3::Transform3( const Quat & unitQuat, const Vector3 & translateVec ) +{ + this->setUpper3x3( Matrix3( unitQuat ) ); + this->setTranslation( translateVec ); +} + +inline Transform3::Transform3( const Aos::Transform3 & tfrm ) +{ + mCol0 = Vector3( tfrm.getCol0() ); + mCol1 = Vector3( tfrm.getCol1() ); + mCol2 = Vector3( tfrm.getCol2() ); + mCol3 = Vector3( tfrm.getCol3() ); +} + +inline Transform3::Transform3( const Aos::Transform3 & tfrm0, const Aos::Transform3 & tfrm1, const Aos::Transform3 & tfrm2, const Aos::Transform3 & tfrm3 ) +{ + mCol0 = Vector3( tfrm0.getCol0(), tfrm1.getCol0(), tfrm2.getCol0(), tfrm3.getCol0() ); + mCol1 = Vector3( tfrm0.getCol1(), tfrm1.getCol1(), tfrm2.getCol1(), tfrm3.getCol1() ); + mCol2 = Vector3( tfrm0.getCol2(), tfrm1.getCol2(), tfrm2.getCol2(), tfrm3.getCol2() ); + mCol3 = Vector3( tfrm0.getCol3(), tfrm1.getCol3(), tfrm2.getCol3(), tfrm3.getCol3() ); +} + +inline void Transform3::get4Aos( Aos::Transform3 & result0, Aos::Transform3 & result1, Aos::Transform3 & result2, Aos::Transform3 & result3 ) const +{ + Aos::Vector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + mCol0.get4Aos( tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3 ); + result0.setCol0( tmpV3_0 ); + result1.setCol0( tmpV3_1 ); + result2.setCol0( tmpV3_2 ); + result3.setCol0( tmpV3_3 ); + mCol1.get4Aos( tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3 ); + result0.setCol1( tmpV3_0 ); + result1.setCol1( tmpV3_1 ); + result2.setCol1( tmpV3_2 ); + result3.setCol1( tmpV3_3 ); + mCol2.get4Aos( tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3 ); + result0.setCol2( tmpV3_0 ); + result1.setCol2( tmpV3_1 ); + result2.setCol2( tmpV3_2 ); + result3.setCol2( tmpV3_3 ); + mCol3.get4Aos( tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3 ); + result0.setCol3( tmpV3_0 ); + result1.setCol3( tmpV3_1 ); + result2.setCol3( tmpV3_2 ); + result3.setCol3( tmpV3_3 ); +} + +inline Transform3 & Transform3::setCol0( const Vector3 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Transform3 & Transform3::setCol1( const Vector3 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Transform3 & Transform3::setCol2( const Vector3 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Transform3 & Transform3::setCol3( const Vector3 & _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Transform3 & Transform3::setCol( int col, const Vector3 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Transform3 & Transform3::setRow( int row, const Vector4 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Transform3 & Transform3::setElem( int col, int row, vec_float4 val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline vec_float4 Transform3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Transform3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Transform3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Transform3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Transform3::getCol3( ) const +{ + return mCol3; +} + +inline const Vector3 Transform3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Transform3::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector3 & Transform3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Transform3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Transform3 & Transform3::operator =( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; + return *this; +} + +inline const Transform3 inverse( const Transform3 & tfrm ) +{ + Vector3 tmp0, tmp1, tmp2, inv0, inv1, inv2; + vec_float4 detinv; + tmp0 = cross( tfrm.getCol1(), tfrm.getCol2() ); + tmp1 = cross( tfrm.getCol2(), tfrm.getCol0() ); + tmp2 = cross( tfrm.getCol0(), tfrm.getCol1() ); + detinv = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), dot( tfrm.getCol2(), tmp2 ) ); + inv0 = Vector3( vec_madd( tmp0.getX(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp1.getX(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp2.getX(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + inv1 = Vector3( vec_madd( tmp0.getY(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp1.getY(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp2.getY(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + inv2 = Vector3( vec_madd( tmp0.getZ(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp1.getZ(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmp2.getZ(), detinv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return Transform3( + inv0, + inv1, + inv2, + Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) + ); +} + +inline const Transform3 orthoInverse( const Transform3 & tfrm ) +{ + Vector3 inv0, inv1, inv2; + inv0 = Vector3( tfrm.getCol0().getX(), tfrm.getCol1().getX(), tfrm.getCol2().getX() ); + inv1 = Vector3( tfrm.getCol0().getY(), tfrm.getCol1().getY(), tfrm.getCol2().getY() ); + inv2 = Vector3( tfrm.getCol0().getZ(), tfrm.getCol1().getZ(), tfrm.getCol2().getZ() ); + return Transform3( + inv0, + inv1, + inv2, + Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) + ); +} + +inline const Transform3 absPerElem( const Transform3 & tfrm ) +{ + return Transform3( + absPerElem( tfrm.getCol0() ), + absPerElem( tfrm.getCol1() ), + absPerElem( tfrm.getCol2() ), + absPerElem( tfrm.getCol3() ) + ); +} + +inline const Vector3 Transform3::operator *( const Vector3 & vec ) const +{ + return Vector3( + vec_add( vec_add( vec_madd( mCol0.getX(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getX(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getX(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_add( vec_add( vec_madd( mCol0.getY(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getY(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getY(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_add( vec_add( vec_madd( mCol0.getZ(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getZ(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getZ(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) + ); +} + +inline const Point3 Transform3::operator *( const Point3 & pnt ) const +{ + return Point3( + vec_add( vec_add( vec_add( vec_madd( mCol0.getX(), pnt.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getX(), pnt.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getX(), pnt.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), mCol3.getX() ), + vec_add( vec_add( vec_add( vec_madd( mCol0.getY(), pnt.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getY(), pnt.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getY(), pnt.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), mCol3.getY() ), + vec_add( vec_add( vec_add( vec_madd( mCol0.getZ(), pnt.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mCol1.getZ(), pnt.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mCol2.getZ(), pnt.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), mCol3.getZ() ) + ); +} + +inline const Transform3 Transform3::operator *( const Transform3 & tfrm ) const +{ + return Transform3( + ( *this * tfrm.mCol0 ), + ( *this * tfrm.mCol1 ), + ( *this * tfrm.mCol2 ), + Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) + ); +} + +inline Transform3 & Transform3::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) +{ + return Transform3( + mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), + mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), + mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), + mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) + ); +} + +inline const Transform3 Transform3::identity( ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) +{ + mCol0 = tfrm.getCol0(); + mCol1 = tfrm.getCol1(); + mCol2 = tfrm.getCol2(); + return *this; +} + +inline const Matrix3 Transform3::getUpper3x3( ) const +{ + return Matrix3( mCol0, mCol1, mCol2 ); +} + +inline Transform3 & Transform3::setTranslation( const Vector3 & translateVec ) +{ + mCol3 = translateVec; + return *this; +} + +inline const Vector3 Transform3::getTranslation( ) const +{ + return mCol3; +} + +inline const Transform3 Transform3::rotationX( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Transform3( + Vector3::xAxis( ), + Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), c, s ), + Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), negatef4( s ), c ), + Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline const Transform3 Transform3::rotationY( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Transform3( + Vector3( c, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), negatef4( s ) ), + Vector3::yAxis( ), + Vector3( s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), c ), + Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline const Transform3 Transform3::rotationZ( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Transform3( + Vector3( c, s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector3( negatef4( s ), c, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector3::zAxis( ), + Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline const Transform3 Transform3::rotationZYX( const Vector3 & radiansXYZ ) +{ + vec_float4 sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sincosf4( radiansXYZ.getX(), &sX, &cX ); + sincosf4( radiansXYZ.getY(), &sY, &cY ); + sincosf4( radiansXYZ.getZ(), &sZ, &cZ ); + tmp0 = vec_madd( cZ, sY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + tmp1 = vec_madd( sZ, sY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + return Transform3( + Vector3( vec_madd( cZ, cY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, cY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), negatef4( sY ) ), + Vector3( vec_sub( vec_madd( tmp0, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_add( vec_madd( tmp1, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( cZ, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( cY, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + Vector3( vec_add( vec_madd( tmp0, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( sZ, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_sub( vec_madd( tmp1, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( cZ, sX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( cY, cX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline const Transform3 Transform3::rotation( vec_float4 radians, const Vector3 & unitVec ) +{ + return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +inline const Transform3 Transform3::rotation( const Quat & unitQuat ) +{ + return Transform3( Matrix3( unitQuat ), Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +inline const Transform3 Transform3::scale( const Vector3 & scaleVec ) +{ + return Transform3( + Vector3( scaleVec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), scaleVec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), scaleVec.getZ() ), + Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ) +{ + return Transform3( + ( tfrm.getCol0() * scaleVec.getX( ) ), + ( tfrm.getCol1() * scaleVec.getY( ) ), + ( tfrm.getCol2() * scaleVec.getZ( ) ), + tfrm.getCol3() + ); +} + +inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ) +{ + return Transform3( + mulPerElem( tfrm.getCol0(), scaleVec ), + mulPerElem( tfrm.getCol1(), scaleVec ), + mulPerElem( tfrm.getCol2(), scaleVec ), + mulPerElem( tfrm.getCol3(), scaleVec ) + ); +} + +inline const Transform3 Transform3::translation( const Vector3 & translateVec ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + translateVec + ); +} + +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, vec_uint4 select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Transform3 & tfrm ) +{ + Aos::Transform3 mat0, mat1, mat2, mat3; + tfrm.get4Aos( mat0, mat1, mat2, mat3 ); + printf("slot 0:\n"); + print( mat0 ); + printf("slot 1:\n"); + print( mat1 ); + printf("slot 2:\n"); + print( mat2 ); + printf("slot 3:\n"); + print( mat3 ); +} + +inline void print( const Transform3 & tfrm, const char * name ) +{ + printf("%s:\n", name); + print( tfrm ); +} + +#endif + +inline Quat::Quat( const Matrix3 & tfrm ) +{ + vec_float4 trace, radicand, scale, xx, yx, zx, xy, yy, zy, xz, yz, zz, tmpx, tmpy, tmpz, tmpw, qx, qy, qz, qw; + vec_uint4 negTrace, ZgtX, ZgtY, YgtX; + vec_uint4 largestXorY, largestYorZ, largestZorX; + + xx = tfrm.getCol0().getX(); + yx = tfrm.getCol0().getY(); + zx = tfrm.getCol0().getZ(); + xy = tfrm.getCol1().getX(); + yy = tfrm.getCol1().getY(); + zy = tfrm.getCol1().getZ(); + xz = tfrm.getCol2().getX(); + yz = tfrm.getCol2().getY(); + zz = tfrm.getCol2().getZ(); + + trace = vec_add( vec_add( xx, yy ), zz ); + + negTrace = (vec_uint4)vec_cmpgt( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), trace ); + ZgtX = (vec_uint4)vec_cmpgt( zz, xx ); + ZgtY = (vec_uint4)vec_cmpgt( zz, yy ); + YgtX = (vec_uint4)vec_cmpgt( yy, xx ); + largestXorY = vec_andc( negTrace, vec_and( ZgtX, ZgtY ) ); + largestYorZ = vec_and( negTrace, vec_or( YgtX, ZgtX ) ); + largestZorX = vec_andc( negTrace, vec_andc( YgtX, ZgtY ) ); + + zz = vec_sel( zz, negatef4(zz), largestXorY ); + xy = vec_sel( xy, negatef4(xy), largestXorY ); + xx = vec_sel( xx, negatef4(xx), largestYorZ ); + yz = vec_sel( yz, negatef4(yz), largestYorZ ); + yy = vec_sel( yy, negatef4(yy), largestZorX ); + zx = vec_sel( zx, negatef4(zx), largestZorX ); + + radicand = vec_add( vec_add( vec_add( xx, yy ), zz ), ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); + scale = vec_madd( ((vec_float4){0.5f,0.5f,0.5f,0.5f}), divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( radicand ) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + + tmpx = vec_madd( vec_sub( zy, yz ), scale, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + tmpy = vec_madd( vec_sub( xz, zx ), scale, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + tmpz = vec_madd( vec_sub( yx, xy ), scale, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + tmpw = vec_madd( radicand, scale, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qx = tmpx; + qy = tmpy; + qz = tmpz; + qw = tmpw; + + qx = vec_sel( qx, tmpw, largestXorY ); + qy = vec_sel( qy, tmpz, largestXorY ); + qz = vec_sel( qz, tmpy, largestXorY ); + qw = vec_sel( qw, tmpx, largestXorY ); + tmpx = qx; + tmpz = qz; + qx = vec_sel( qx, qy, largestYorZ ); + qy = vec_sel( qy, tmpx, largestYorZ ); + qz = vec_sel( qz, qw, largestYorZ ); + qw = vec_sel( qw, tmpz, largestYorZ ); + + mX = qx; + mY = qy; + mZ = qz; + mW = qw; +} + +inline const Matrix3 outer( const Vector3 & tfrm0, const Vector3 & tfrm1 ) +{ + return Matrix3( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ) + ); +} + +inline const Matrix4 outer( const Vector4 & tfrm0, const Vector4 & tfrm1 ) +{ + return Matrix4( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ), + ( tfrm0 * tfrm1.getW( ) ) + ); +} + +inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ) +{ + return Vector3( + vec_add( vec_add( vec_madd( vec.getX(), mat.getCol0().getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( vec.getY(), mat.getCol0().getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( vec.getZ(), mat.getCol0().getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_add( vec_add( vec_madd( vec.getX(), mat.getCol1().getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( vec.getY(), mat.getCol1().getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( vec.getZ(), mat.getCol1().getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_add( vec_add( vec_madd( vec.getX(), mat.getCol2().getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( vec.getY(), mat.getCol2().getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( vec.getZ(), mat.getCol2().getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) + ); +} + +inline const Matrix3 crossMatrix( const Vector3 & vec ) +{ + return Matrix3( + Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), vec.getZ(), negatef4( vec.getY() ) ), + Vector3( negatef4( vec.getZ() ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), vec.getX() ), + Vector3( vec.getY(), negatef4( vec.getX() ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ) +{ + return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); +} + +} // namespace Soa +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/cpp/quat_aos.h b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/quat_aos.h new file mode 100644 index 0000000..196a48d --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/quat_aos.h @@ -0,0 +1,536 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_AOS_CPP_H +#define _VECTORMATH_QUAT_AOS_CPP_H +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +inline Quat::Quat( float _x, float _y, float _z, float _w ) +{ + if (__builtin_constant_p(_x) & __builtin_constant_p(_y) & + __builtin_constant_p(_z) & __builtin_constant_p(_w)) { + mVec128 = (vec_float4){_x, _y, _z, _w}; + } else { + float *pf = (float *)&mVec128; + pf[0] = _x; + pf[1] = _y; + pf[2] = _z; + pf[3] = _w; + } +} + +inline Quat::Quat( floatInVec _x, floatInVec _y, floatInVec _z, floatInVec _w ) +{ + vec_float4 xz = vec_mergeh( _x.get128(), _z.get128() ); + vec_float4 yw = vec_mergeh( _y.get128(), _w.get128() ); + mVec128 = vec_mergeh( xz, yw ); +} + +inline Quat::Quat( Vector3 xyz, float _w ) +{ + mVec128 = xyz.get128(); + _vmathVfSetElement(mVec128, _w, 3); +} + +inline Quat::Quat( Vector3 xyz, floatInVec _w ) +{ + mVec128 = xyz.get128(); + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); +} + +inline Quat::Quat( Vector4 vec ) +{ + mVec128 = vec.get128(); +} + +inline Quat::Quat( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +inline Quat::Quat( floatInVec scalar ) +{ + mVec128 = scalar.get128(); +} + +inline Quat::Quat( vec_float4 vf4 ) +{ + mVec128 = vf4; +} + +inline const Quat Quat::identity( ) +{ + return Quat( _VECTORMATH_UNIT_0001 ); +} + +inline const Quat lerp( float t, Quat quat0, Quat quat1 ) +{ + return lerp( floatInVec(t), quat0, quat1 ); +} + +inline const Quat lerp( floatInVec t, Quat quat0, Quat quat1 ) +{ + return ( quat0 + ( ( quat1 - quat0 ) * t ) ); +} + +inline const Quat slerp( float t, Quat unitQuat0, Quat unitQuat1 ) +{ + return slerp( floatInVec(t), unitQuat0, unitQuat1 ); +} + +inline const Quat slerp( floatInVec t, Quat unitQuat0, Quat unitQuat1 ) +{ + Quat start; + vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + vec_uint4 selectMask; + cosAngle = _vmathVfDot4( unitQuat0.get128(), unitQuat1.get128() ); + cosAngle = vec_splat( cosAngle, 0 ); + selectMask = (vec_uint4)vec_cmpgt( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), cosAngle ); + cosAngle = vec_sel( cosAngle, negatef4( cosAngle ), selectMask ); + start = Quat( vec_sel( unitQuat0.get128(), negatef4( unitQuat0.get128() ), selectMask ) ); + selectMask = (vec_uint4)vec_cmpgt( ((vec_float4){_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL}), cosAngle ); + angle = acosf4( cosAngle ); + tttt = t.get128(); + oneMinusT = vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), tttt ); + angles = vec_mergeh( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), tttt ); + angles = vec_mergeh( angles, oneMinusT ); + angles = vec_madd( angles, angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sines = sinf4( angles ); + scales = divf4( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + return Quat( vec_madd( start.get128(), scale0, vec_madd( unitQuat1.get128(), scale1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); +} + +inline const Quat squad( float t, Quat unitQuat0, Quat unitQuat1, Quat unitQuat2, Quat unitQuat3 ) +{ + return squad( floatInVec(t), unitQuat0, unitQuat1, unitQuat2, unitQuat3 ); +} + +inline const Quat squad( floatInVec t, Quat unitQuat0, Quat unitQuat1, Quat unitQuat2, Quat unitQuat3 ) +{ + Quat tmp0, tmp1; + tmp0 = slerp( t, unitQuat0, unitQuat3 ); + tmp1 = slerp( t, unitQuat1, unitQuat2 ); + return slerp( ( ( floatInVec(2.0f) * t ) * ( floatInVec(1.0f) - t ) ), tmp0, tmp1 ); +} + +inline vec_float4 Quat::get128( ) const +{ + return mVec128; +} + +inline Quat & Quat::operator =( Quat quat ) +{ + mVec128 = quat.mVec128; + return *this; +} + +inline Quat & Quat::setXYZ( Vector3 vec ) +{ + mVec128 = vec_sel( vec.get128(), mVec128, _VECTORMATH_MASK_0x000F ); + return *this; +} + +inline const Vector3 Quat::getXYZ( ) const +{ + return Vector3( mVec128 ); +} + +inline Quat & Quat::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +inline Quat & Quat::setX( floatInVec _x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +inline const floatInVec Quat::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +inline Quat & Quat::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +inline Quat & Quat::setY( floatInVec _y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +inline const floatInVec Quat::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +inline Quat & Quat::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +inline Quat & Quat::setZ( floatInVec _z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +inline const floatInVec Quat::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +inline Quat & Quat::setW( float _w ) +{ + _vmathVfSetElement(mVec128, _w, 3); + return *this; +} + +inline Quat & Quat::setW( floatInVec _w ) +{ + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); + return *this; +} + +inline const floatInVec Quat::getW( ) const +{ + return floatInVec( mVec128, 3 ); +} + +inline Quat & Quat::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +inline Quat & Quat::setElem( int idx, floatInVec value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +inline const floatInVec Quat::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +inline VecIdx Quat::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +inline const floatInVec Quat::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +inline const Quat Quat::operator +( Quat quat ) const +{ + return Quat( vec_add( mVec128, quat.mVec128 ) ); +} + +inline const Quat Quat::operator -( Quat quat ) const +{ + return Quat( vec_sub( mVec128, quat.mVec128 ) ); +} + +inline const Quat Quat::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +inline const Quat Quat::operator *( floatInVec scalar ) const +{ + return Quat( vec_madd( mVec128, scalar.get128(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +inline Quat & Quat::operator +=( Quat quat ) +{ + *this = *this + quat; + return *this; +} + +inline Quat & Quat::operator -=( Quat quat ) +{ + *this = *this - quat; + return *this; +} + +inline Quat & Quat::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline Quat & Quat::operator *=( floatInVec scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Quat Quat::operator /( float scalar ) const +{ + return *this / floatInVec(scalar); +} + +inline const Quat Quat::operator /( floatInVec scalar ) const +{ + return Quat( divf4( mVec128, scalar.get128() ) ); +} + +inline Quat & Quat::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline Quat & Quat::operator /=( floatInVec scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Quat Quat::operator -( ) const +{ + return Quat( negatef4( mVec128 ) ); +} + +inline const Quat operator *( float scalar, Quat quat ) +{ + return floatInVec(scalar) * quat; +} + +inline const Quat operator *( floatInVec scalar, Quat quat ) +{ + return quat * scalar; +} + +inline const floatInVec dot( Quat quat0, Quat quat1 ) +{ + return floatInVec( _vmathVfDot4( quat0.get128(), quat1.get128() ), 0 ); +} + +inline const floatInVec norm( Quat quat ) +{ + return floatInVec( _vmathVfDot4( quat.get128(), quat.get128() ), 0 ); +} + +inline const floatInVec length( Quat quat ) +{ + return floatInVec( sqrtf4(_vmathVfDot4( quat.get128(), quat.get128() )), 0 ); +} + +inline const Quat normalize( Quat quat ) +{ + vec_float4 dot = _vmathVfDot4( quat.get128(), quat.get128() ); + return Quat( vec_madd( quat.get128(), rsqrtf4( dot ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +inline const Quat Quat::rotation( Vector3 unitVec0, Vector3 unitVec1 ) +{ + Vector3 crossVec; + vec_float4 cosAngle, cosAngleX2Plus2, recipCosHalfAngleX2, cosHalfAngleX2, res; + cosAngle = _vmathVfDot3( unitVec0.get128(), unitVec1.get128() ); + cosAngle = vec_splat( cosAngle, 0 ); + cosAngleX2Plus2 = vec_madd( cosAngle, ((vec_float4){2.0f,2.0f,2.0f,2.0f}), ((vec_float4){2.0f,2.0f,2.0f,2.0f}) ); + recipCosHalfAngleX2 = rsqrtf4( cosAngleX2Plus2 ); + cosHalfAngleX2 = vec_madd( recipCosHalfAngleX2, cosAngleX2Plus2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + crossVec = cross( unitVec0, unitVec1 ); + res = vec_madd( crossVec.get128(), recipCosHalfAngleX2, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + res = vec_sel( res, vec_madd( cosHalfAngleX2, ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), _VECTORMATH_MASK_0x000F ); + return Quat( res ); +} + +inline const Quat Quat::rotation( float radians, Vector3 unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +inline const Quat Quat::rotation( floatInVec radians, Vector3 unitVec ) +{ + vec_float4 s, c, angle, res; + angle = vec_madd( radians.get128(), ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sincosf4( angle, &s, &c ); + res = vec_sel( vec_madd( unitVec.get128(), s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), c, _VECTORMATH_MASK_0x000F ); + return Quat( res ); +} + +inline const Quat Quat::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +inline const Quat Quat::rotationX( floatInVec radians ) +{ + vec_float4 s, c, angle, res; + angle = vec_madd( radians.get128(), ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sincosf4( angle, &s, &c ); + res = vec_sel( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), s, _VECTORMATH_MASK_0xF000 ); + res = vec_sel( res, c, _VECTORMATH_MASK_0x000F ); + return Quat( res ); +} + +inline const Quat Quat::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +inline const Quat Quat::rotationY( floatInVec radians ) +{ + vec_float4 s, c, angle, res; + angle = vec_madd( radians.get128(), ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sincosf4( angle, &s, &c ); + res = vec_sel( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), s, _VECTORMATH_MASK_0x0F00 ); + res = vec_sel( res, c, _VECTORMATH_MASK_0x000F ); + return Quat( res ); +} + +inline const Quat Quat::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +inline const Quat Quat::rotationZ( floatInVec radians ) +{ + vec_float4 s, c, angle, res; + angle = vec_madd( radians.get128(), ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sincosf4( angle, &s, &c ); + res = vec_sel( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), s, _VECTORMATH_MASK_0x00F0 ); + res = vec_sel( res, c, _VECTORMATH_MASK_0x000F ); + return Quat( res ); +} + +inline const Quat Quat::operator *( Quat quat ) const +{ + vec_float4 ldata, rdata, qv, tmp0, tmp1, tmp2, tmp3; + vec_float4 product, l_wxyz, r_wxyz, xy, qw; + ldata = mVec128; + rdata = quat.mVec128; + tmp0 = vec_perm( ldata, ldata, _VECTORMATH_PERM_YZXW ); + tmp1 = vec_perm( rdata, rdata, _VECTORMATH_PERM_ZXYW ); + tmp2 = vec_perm( ldata, ldata, _VECTORMATH_PERM_ZXYW ); + tmp3 = vec_perm( rdata, rdata, _VECTORMATH_PERM_YZXW ); + qv = vec_madd( vec_splat( ldata, 3 ), rdata, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qv = vec_madd( vec_splat( rdata, 3 ), ldata, qv ); + qv = vec_madd( tmp0, tmp1, qv ); + qv = vec_nmsub( tmp2, tmp3, qv ); + product = vec_madd( ldata, rdata, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + l_wxyz = vec_sld( ldata, ldata, 12 ); + r_wxyz = vec_sld( rdata, rdata, 12 ); + qw = vec_nmsub( l_wxyz, r_wxyz, product ); + xy = vec_madd( l_wxyz, r_wxyz, product ); + qw = vec_sub( qw, vec_sld( xy, xy, 8 ) ); + return Quat( vec_sel( qv, qw, _VECTORMATH_MASK_0x000F ) ); +} + +inline Quat & Quat::operator *=( Quat quat ) +{ + *this = *this * quat; + return *this; +} + +inline const Vector3 rotate( Quat quat, Vector3 vec ) +{ + vec_float4 qdata, vdata, product, tmp0, tmp1, tmp2, tmp3, wwww, qv, qw, res; + qdata = quat.get128(); + vdata = vec.get128(); + tmp0 = vec_perm( qdata, qdata, _VECTORMATH_PERM_YZXW ); + tmp1 = vec_perm( vdata, vdata, _VECTORMATH_PERM_ZXYW ); + tmp2 = vec_perm( qdata, qdata, _VECTORMATH_PERM_ZXYW ); + tmp3 = vec_perm( vdata, vdata, _VECTORMATH_PERM_YZXW ); + wwww = vec_splat( qdata, 3 ); + qv = vec_madd( wwww, vdata, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qv = vec_madd( tmp0, tmp1, qv ); + qv = vec_nmsub( tmp2, tmp3, qv ); + product = vec_madd( qdata, vdata, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + qw = vec_madd( vec_sld( qdata, qdata, 4 ), vec_sld( vdata, vdata, 4 ), product ); + qw = vec_add( vec_sld( product, product, 8 ), qw ); + tmp1 = vec_perm( qv, qv, _VECTORMATH_PERM_ZXYW ); + tmp3 = vec_perm( qv, qv, _VECTORMATH_PERM_YZXW ); + res = vec_madd( vec_splat( qw, 0 ), qdata, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + res = vec_madd( wwww, qv, res ); + res = vec_madd( tmp0, tmp1, res ); + res = vec_nmsub( tmp2, tmp3, res ); + return Vector3( res ); +} + +inline const Quat conj( Quat quat ) +{ + return Quat( vec_xor( quat.get128(), ((vec_float4)(vec_int4){0x80000000,0x80000000,0x80000000,0}) ) ); +} + +inline const Quat select( Quat quat0, Quat quat1, bool select1 ) +{ + return select( quat0, quat1, boolInVec(select1) ); +} + +inline const Quat select( Quat quat0, Quat quat1, boolInVec select1 ) +{ + return Quat( vec_sel( quat0.get128(), quat1.get128(), select1.get128() ) ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( Quat quat ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = quat.get128(); + printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +inline void print( Quat quat, const char * name ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = quat.get128(); + printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/cpp/quat_soa.h b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/quat_soa.h new file mode 100644 index 0000000..fb83e81 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/quat_soa.h @@ -0,0 +1,479 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_SOA_CPP_H +#define _VECTORMATH_QUAT_SOA_CPP_H +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Soa { + +inline Quat::Quat( const Quat & quat ) +{ + mX = quat.mX; + mY = quat.mY; + mZ = quat.mZ; + mW = quat.mW; +} + +inline Quat::Quat( vec_float4 _x, vec_float4 _y, vec_float4 _z, vec_float4 _w ) +{ + mX = _x; + mY = _y; + mZ = _z; + mW = _w; +} + +inline Quat::Quat( const Vector3 & xyz, vec_float4 _w ) +{ + this->setXYZ( xyz ); + this->setW( _w ); +} + +inline Quat::Quat( const Vector4 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + mW = vec.getW(); +} + +inline Quat::Quat( vec_float4 scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; + mW = scalar; +} + +inline Quat::Quat( Aos::Quat quat ) +{ + vec_float4 vec128 = quat.get128(); + mX = vec_splat( vec128, 0 ); + mY = vec_splat( vec128, 1 ); + mZ = vec_splat( vec128, 2 ); + mW = vec_splat( vec128, 3 ); +} + +inline Quat::Quat( Aos::Quat quat0, Aos::Quat quat1, Aos::Quat quat2, Aos::Quat quat3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = vec_mergeh( quat0.get128(), quat2.get128() ); + tmp1 = vec_mergeh( quat1.get128(), quat3.get128() ); + tmp2 = vec_mergel( quat0.get128(), quat2.get128() ); + tmp3 = vec_mergel( quat1.get128(), quat3.get128() ); + mX = vec_mergeh( tmp0, tmp1 ); + mY = vec_mergel( tmp0, tmp1 ); + mZ = vec_mergeh( tmp2, tmp3 ); + mW = vec_mergel( tmp2, tmp3 ); +} + +inline const Quat Quat::identity( ) +{ + return Quat( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); +} + +inline const Quat lerp( vec_float4 t, const Quat & quat0, const Quat & quat1 ) +{ + return ( quat0 + ( ( quat1 - quat0 ) * t ) ); +} + +inline const Quat slerp( vec_float4 t, const Quat & unitQuat0, const Quat & unitQuat1 ) +{ + Quat start; + vec_float4 recipSinAngle, scale0, scale1, cosAngle, angle; + vec_uint4 selectMask; + cosAngle = dot( unitQuat0, unitQuat1 ); + selectMask = (vec_uint4)vec_cmpgt( (vec_float4){0.0f,0.0f,0.0f,0.0f}, cosAngle ); + cosAngle = vec_sel( cosAngle, negatef4( cosAngle ), selectMask ); + start.setX( vec_sel( unitQuat0.getX(), negatef4( unitQuat0.getX() ), selectMask ) ); + start.setY( vec_sel( unitQuat0.getY(), negatef4( unitQuat0.getY() ), selectMask ) ); + start.setZ( vec_sel( unitQuat0.getZ(), negatef4( unitQuat0.getZ() ), selectMask ) ); + start.setW( vec_sel( unitQuat0.getW(), negatef4( unitQuat0.getW() ), selectMask ) ); + selectMask = (vec_uint4)vec_cmpgt( (vec_float4){_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL}, cosAngle ); + angle = acosf4( cosAngle ); + recipSinAngle = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sinf4( angle ) ); + scale0 = vec_sel( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), t ), vec_madd( sinf4( vec_madd( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), t ), angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), recipSinAngle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), selectMask ); + scale1 = vec_sel( t, vec_madd( sinf4( vec_madd( t, angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), recipSinAngle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), selectMask ); + return ( ( start * scale0 ) + ( unitQuat1 * scale1 ) ); +} + +inline const Quat squad( vec_float4 t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ) +{ + Quat tmp0, tmp1; + tmp0 = slerp( t, unitQuat0, unitQuat3 ); + tmp1 = slerp( t, unitQuat1, unitQuat2 ); + return slerp( vec_madd( vec_madd( ((vec_float4){2.0f,2.0f,2.0f,2.0f}), t, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), t ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), tmp0, tmp1 ); +} + +inline void Quat::get4Aos( Aos::Quat & result0, Aos::Quat & result1, Aos::Quat & result2, Aos::Quat & result3 ) const +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = vec_mergeh( mX, mZ ); + tmp1 = vec_mergeh( mY, mW ); + tmp2 = vec_mergel( mX, mZ ); + tmp3 = vec_mergel( mY, mW ); + result0 = Aos::Quat( vec_mergeh( tmp0, tmp1 ) ); + result1 = Aos::Quat( vec_mergel( tmp0, tmp1 ) ); + result2 = Aos::Quat( vec_mergeh( tmp2, tmp3 ) ); + result3 = Aos::Quat( vec_mergel( tmp2, tmp3 ) ); +} + +inline Quat & Quat::operator =( const Quat & quat ) +{ + mX = quat.mX; + mY = quat.mY; + mZ = quat.mZ; + mW = quat.mW; + return *this; +} + +inline Quat & Quat::setXYZ( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + return *this; +} + +inline const Vector3 Quat::getXYZ( ) const +{ + return Vector3( mX, mY, mZ ); +} + +inline Quat & Quat::setX( vec_float4 _x ) +{ + mX = _x; + return *this; +} + +inline vec_float4 Quat::getX( ) const +{ + return mX; +} + +inline Quat & Quat::setY( vec_float4 _y ) +{ + mY = _y; + return *this; +} + +inline vec_float4 Quat::getY( ) const +{ + return mY; +} + +inline Quat & Quat::setZ( vec_float4 _z ) +{ + mZ = _z; + return *this; +} + +inline vec_float4 Quat::getZ( ) const +{ + return mZ; +} + +inline Quat & Quat::setW( vec_float4 _w ) +{ + mW = _w; + return *this; +} + +inline vec_float4 Quat::getW( ) const +{ + return mW; +} + +inline Quat & Quat::setElem( int idx, vec_float4 value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline vec_float4 Quat::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline Quat::vec_float4_t & Quat::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline vec_float4 Quat::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Quat Quat::operator +( const Quat & quat ) const +{ + return Quat( + vec_add( mX, quat.mX ), + vec_add( mY, quat.mY ), + vec_add( mZ, quat.mZ ), + vec_add( mW, quat.mW ) + ); +} + +inline const Quat Quat::operator -( const Quat & quat ) const +{ + return Quat( + vec_sub( mX, quat.mX ), + vec_sub( mY, quat.mY ), + vec_sub( mZ, quat.mZ ), + vec_sub( mW, quat.mW ) + ); +} + +inline const Quat Quat::operator *( vec_float4 scalar ) const +{ + return Quat( + vec_madd( mX, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( mY, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( mZ, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( mW, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline Quat & Quat::operator +=( const Quat & quat ) +{ + *this = *this + quat; + return *this; +} + +inline Quat & Quat::operator -=( const Quat & quat ) +{ + *this = *this - quat; + return *this; +} + +inline Quat & Quat::operator *=( vec_float4 scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Quat Quat::operator /( vec_float4 scalar ) const +{ + return Quat( + divf4( mX, scalar ), + divf4( mY, scalar ), + divf4( mZ, scalar ), + divf4( mW, scalar ) + ); +} + +inline Quat & Quat::operator /=( vec_float4 scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Quat Quat::operator -( ) const +{ + return Quat( + negatef4( mX ), + negatef4( mY ), + negatef4( mZ ), + negatef4( mW ) + ); +} + +inline const Quat operator *( vec_float4 scalar, const Quat & quat ) +{ + return quat * scalar; +} + +inline vec_float4 dot( const Quat & quat0, const Quat & quat1 ) +{ + vec_float4 result; + result = vec_madd( quat0.getX(), quat1.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result = vec_add( result, vec_madd( quat0.getY(), quat1.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( quat0.getZ(), quat1.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( quat0.getW(), quat1.getW(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return result; +} + +inline vec_float4 norm( const Quat & quat ) +{ + vec_float4 result; + result = vec_madd( quat.getX(), quat.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result = vec_add( result, vec_madd( quat.getY(), quat.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( quat.getZ(), quat.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( quat.getW(), quat.getW(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return result; +} + +inline vec_float4 length( const Quat & quat ) +{ + return sqrtf4( norm( quat ) ); +} + +inline const Quat normalize( const Quat & quat ) +{ + vec_float4 lenSqr, lenInv; + lenSqr = norm( quat ); + lenInv = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( lenSqr ) ); + return Quat( + vec_madd( quat.getX(), lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( quat.getY(), lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( quat.getZ(), lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( quat.getW(), lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline const Quat Quat::rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ) +{ + vec_float4 cosHalfAngleX2, recipCosHalfAngleX2; + cosHalfAngleX2 = sqrtf4( vec_madd( ((vec_float4){2.0f,2.0f,2.0f,2.0f}), vec_add( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), dot( unitVec0, unitVec1 ) ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + recipCosHalfAngleX2 = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), cosHalfAngleX2 ); + return Quat( ( cross( unitVec0, unitVec1 ) * recipCosHalfAngleX2 ), vec_madd( cosHalfAngleX2, ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +inline const Quat Quat::rotation( vec_float4 radians, const Vector3 & unitVec ) +{ + vec_float4 s, c, angle; + angle = vec_madd( radians, ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sincosf4( angle, &s, &c ); + return Quat( ( unitVec * s ), c ); +} + +inline const Quat Quat::rotationX( vec_float4 radians ) +{ + vec_float4 s, c, angle; + angle = vec_madd( radians, ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sincosf4( angle, &s, &c ); + return Quat( s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), c ); +} + +inline const Quat Quat::rotationY( vec_float4 radians ) +{ + vec_float4 s, c, angle; + angle = vec_madd( radians, ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sincosf4( angle, &s, &c ); + return Quat( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), s, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), c ); +} + +inline const Quat Quat::rotationZ( vec_float4 radians ) +{ + vec_float4 s, c, angle; + angle = vec_madd( radians, ((vec_float4){0.5f,0.5f,0.5f,0.5f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sincosf4( angle, &s, &c ); + return Quat( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), s, c ); +} + +inline const Quat Quat::operator *( const Quat & quat ) const +{ + return Quat( + vec_sub( vec_add( vec_add( vec_madd( mW, quat.mX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mX, quat.mW, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mY, quat.mZ, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mZ, quat.mY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_sub( vec_add( vec_add( vec_madd( mW, quat.mY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mY, quat.mW, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mZ, quat.mX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mX, quat.mZ, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_sub( vec_add( vec_add( vec_madd( mW, quat.mZ, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mZ, quat.mW, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mX, quat.mY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mY, quat.mX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_sub( vec_sub( vec_sub( vec_madd( mW, quat.mW, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( mX, quat.mX, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mY, quat.mY, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( mZ, quat.mZ, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) + ); +} + +inline Quat & Quat::operator *=( const Quat & quat ) +{ + *this = *this * quat; + return *this; +} + +inline const Vector3 rotate( const Quat & quat, const Vector3 & vec ) +{ + vec_float4 tmpX, tmpY, tmpZ, tmpW; + tmpX = vec_sub( vec_add( vec_madd( quat.getW(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( quat.getY(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( quat.getZ(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpY = vec_sub( vec_add( vec_madd( quat.getW(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( quat.getZ(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( quat.getX(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpZ = vec_sub( vec_add( vec_madd( quat.getW(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( quat.getX(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( quat.getY(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + tmpW = vec_add( vec_add( vec_madd( quat.getX(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( quat.getY(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( quat.getZ(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return Vector3( + vec_add( vec_sub( vec_add( vec_madd( tmpW, quat.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmpX, quat.getW(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tmpY, quat.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tmpZ, quat.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_add( vec_sub( vec_add( vec_madd( tmpW, quat.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmpY, quat.getW(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tmpZ, quat.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tmpX, quat.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_add( vec_sub( vec_add( vec_madd( tmpW, quat.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( tmpZ, quat.getW(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tmpX, quat.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), vec_madd( tmpY, quat.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) + ); +} + +inline const Quat conj( const Quat & quat ) +{ + return Quat( negatef4( quat.getX() ), negatef4( quat.getY() ), negatef4( quat.getZ() ), quat.getW() ); +} + +inline const Quat select( const Quat & quat0, const Quat & quat1, vec_uint4 select1 ) +{ + return Quat( + vec_sel( quat0.getX(), quat1.getX(), select1 ), + vec_sel( quat0.getY(), quat1.getY(), select1 ), + vec_sel( quat0.getZ(), quat1.getZ(), select1 ), + vec_sel( quat0.getW(), quat1.getW(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Quat & quat ) +{ + Aos::Quat vec0, vec1, vec2, vec3; + quat.get4Aos( vec0, vec1, vec2, vec3 ); + printf("slot 0:\n"); + print( vec0 ); + printf("slot 1:\n"); + print( vec1 ); + printf("slot 2:\n"); + print( vec2 ); + printf("slot 3:\n"); + print( vec3 ); +} + +inline void print( const Quat & quat, const char * name ) +{ + Aos::Quat vec0, vec1, vec2, vec3; + printf( "%s:\n", name ); + quat.get4Aos( vec0, vec1, vec2, vec3 ); + printf("slot 0:\n"); + print( vec0 ); + printf("slot 1:\n"); + print( vec1 ); + printf("slot 2:\n"); + print( vec2 ); + printf("slot 3:\n"); + print( vec3 ); +} + +#endif + +} // namespace Soa +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/cpp/vec_aos.h b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/vec_aos.h new file mode 100644 index 0000000..dc1f984 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/vec_aos.h @@ -0,0 +1,1492 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_AOS_CPP_H +#define _VECTORMATH_VEC_AOS_CPP_H +//----------------------------------------------------------------------------- +// Constants +// for permutes words are labeled [x,y,z,w] [a,b,c,d] + +#define _VECTORMATH_PERM_X 0x00010203 +#define _VECTORMATH_PERM_Y 0x04050607 +#define _VECTORMATH_PERM_Z 0x08090a0b +#define _VECTORMATH_PERM_W 0x0c0d0e0f +#define _VECTORMATH_PERM_A 0x10111213 +#define _VECTORMATH_PERM_B 0x14151617 +#define _VECTORMATH_PERM_C 0x18191a1b +#define _VECTORMATH_PERM_D 0x1c1d1e1f +#define _VECTORMATH_PERM_XYZA (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A } +#define _VECTORMATH_PERM_ZXYW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_YZXW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_YZAB (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B } +#define _VECTORMATH_PERM_ZABC (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B, _VECTORMATH_PERM_C } +#define _VECTORMATH_PERM_XYAW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_XAZW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W } +#define _VECTORMATH_MASK_0xF000 (vec_uint4){ 0xffffffff, 0, 0, 0 } +#define _VECTORMATH_MASK_0x0F00 (vec_uint4){ 0, 0xffffffff, 0, 0 } +#define _VECTORMATH_MASK_0x00F0 (vec_uint4){ 0, 0, 0xffffffff, 0 } +#define _VECTORMATH_MASK_0x000F (vec_uint4){ 0, 0, 0, 0xffffffff } +#define _VECTORMATH_UNIT_1000 (vec_float4){ 1.0f, 0.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0100 (vec_float4){ 0.0f, 1.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0010 (vec_float4){ 0.0f, 0.0f, 1.0f, 0.0f } +#define _VECTORMATH_UNIT_0001 (vec_float4){ 0.0f, 0.0f, 0.0f, 1.0f } +#define _VECTORMATH_SLERP_TOL 0.999f + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +static inline vec_float4 _vmathVfDot3( vec_float4 vec0, vec_float4 vec1 ) +{ + vec_float4 result; + result = vec_madd( vec0, vec1, (vec_float4){0.0f,0.0f,0.0f,0.0f} ); + result = vec_madd( vec_sld( vec0, vec0, 4 ), vec_sld( vec1, vec1, 4 ), result ); + return vec_madd( vec_sld( vec0, vec0, 8 ), vec_sld( vec1, vec1, 8 ), result ); +} + +static inline vec_float4 _vmathVfDot4( vec_float4 vec0, vec_float4 vec1 ) +{ + vec_float4 result; + result = vec_madd( vec0, vec1, (vec_float4){0.0f,0.0f,0.0f,0.0f} ); + result = vec_madd( vec_sld( vec0, vec0, 4 ), vec_sld( vec1, vec1, 4 ), result ); + return vec_add( vec_sld( result, result, 8 ), result ); +} + +static inline vec_float4 _vmathVfCross( vec_float4 vec0, vec_float4 vec1 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3, result; + tmp0 = vec_perm( vec0, vec0, _VECTORMATH_PERM_YZXW ); + tmp1 = vec_perm( vec1, vec1, _VECTORMATH_PERM_ZXYW ); + tmp2 = vec_perm( vec0, vec0, _VECTORMATH_PERM_ZXYW ); + tmp3 = vec_perm( vec1, vec1, _VECTORMATH_PERM_YZXW ); + result = vec_madd( tmp0, tmp1, (vec_float4){0.0f,0.0f,0.0f,0.0f} ); + result = vec_nmsub( tmp2, tmp3, result ); + return result; +} + +static inline vec_uint4 _vmathVfToHalfFloatsUnpacked(vec_float4 v) +{ + vec_int4 bexp; + vec_uint4 mant, sign, hfloat; + vec_uint4 notZero, isInf; + const vec_uint4 hfloatInf = (vec_uint4){0x00007c00u,0x00007c00u,0x00007c00u,0x00007c00u}; + const vec_uint4 mergeMant = (vec_uint4){0x000003ffu,0x000003ffu,0x000003ffu,0x000003ffu}; + const vec_uint4 mergeSign = (vec_uint4){0x00008000u,0x00008000u,0x00008000u,0x00008000u}; + + sign = vec_sr((vec_uint4)v, (vec_uint4){16,16,16,16}); + mant = vec_sr((vec_uint4)v, (vec_uint4){13,13,13,13}); + bexp = vec_and(vec_sr((vec_int4)v, (vec_uint4){23,23,23,23}), (vec_int4){0xff,0xff,0xff,0xff}); + + notZero = (vec_uint4)vec_cmpgt(bexp, (vec_int4){112,112,112,112}); + isInf = (vec_uint4)vec_cmpgt(bexp, (vec_int4){142,142,142,142}); + + bexp = vec_add(bexp, (vec_int4){-112,-112,-112,-112}); + bexp = vec_sl(bexp, (vec_uint4){10,10,10,10}); + + hfloat = vec_sel((vec_uint4)bexp, mant, mergeMant); + hfloat = vec_sel((vec_uint4){0,0,0,0}, hfloat, notZero); + hfloat = vec_sel(hfloat, hfloatInf, isInf); + hfloat = vec_sel(hfloat, sign, mergeSign); + + return hfloat; +} + +static inline vec_ushort8 _vmath2VfToHalfFloats(vec_float4 u, vec_float4 v) +{ + vec_uint4 hfloat_u, hfloat_v; + const vec_uchar16 pack = (vec_uchar16){2,3,6,7,10,11,14,15,18,19,22,23,26,27,30,31}; + hfloat_u = _vmathVfToHalfFloatsUnpacked(u); + hfloat_v = _vmathVfToHalfFloatsUnpacked(v); + return (vec_ushort8)vec_perm(hfloat_u, hfloat_v, pack); +} + +#ifndef __GNUC__ +#define __builtin_constant_p(x) 0 +#endif + +static inline vec_float4 _vmathVfInsert(vec_float4 dst, vec_float4 src, int slot) +{ +#ifdef __GNUC__ + if (__builtin_constant_p(slot)) { + dst = vec_sld(dst, dst, slot<<2); + dst = vec_sld(dst, src, 4); + if (slot != 3) dst = vec_sld(dst, dst, (3-slot)<<2); + return dst; + } else +#endif + { + vec_uchar16 shiftpattern = vec_lvsr( 0, (float *)(size_t)(slot<<2) ); + vec_uint4 selectmask = (vec_uint4)vec_perm( (vec_uint4){0,0,0,0}, _VECTORMATH_MASK_0xF000, shiftpattern ); + return vec_sel( dst, src, selectmask ); + } +} + +#define _vmathVfGetElement(vec, slot) ((float *)&(vec))[slot] +#ifdef _VECTORMATH_SET_CONSTS_IN_MEM +#define _vmathVfSetElement(vec, scalar, slot) ((float *)&(vec))[slot] = scalar +#else +#define _vmathVfSetElement(vec, scalar, slot) \ +{ \ + if (__builtin_constant_p(scalar)) { \ + (vec) = _vmathVfInsert(vec, (vec_float4){scalar, scalar, scalar, scalar}, slot); \ + } else { \ + ((float *)&(vec))[slot] = scalar; \ + } \ +} +#endif + +static inline vec_float4 _vmathVfSplatScalar(float scalar) +{ + vec_float4 result; + if (__builtin_constant_p(scalar)) { + result = (vec_float4){scalar, scalar, scalar, scalar}; + } else { + result = vec_ld(0, &scalar); + result = vec_splat(vec_perm(result, result, vec_lvsl(0, &scalar)), 0); + } + return result; +} + +static inline vec_uint4 _vmathVuiSplatScalar(unsigned int scalar) +{ + vec_uint4 result; + if (__builtin_constant_p(scalar)) { + result = (vec_uint4){scalar, scalar, scalar, scalar}; + } else { + result = vec_ld(0, &scalar); + result = vec_splat(vec_perm(result, result, vec_lvsl(0, &scalar)), 0); + } + return result; +} + +#endif + +namespace Vectormath { +namespace Aos { + +#ifdef _VECTORMATH_NO_SCALAR_CAST +inline VecIdx::operator floatInVec() const +{ + return floatInVec(ref, i); +} + +inline float VecIdx::getAsFloat() const +#else +inline VecIdx::operator float() const +#endif +{ + return _vmathVfGetElement(ref, i); +} + +inline float VecIdx::operator =( float scalar ) +{ + _vmathVfSetElement(ref, scalar, i); + return scalar; +} + +inline floatInVec VecIdx::operator =( floatInVec scalar ) +{ + ref = _vmathVfInsert(ref, scalar.get128(), i); + return scalar; +} + +inline floatInVec VecIdx::operator =( const VecIdx& scalar ) +{ + return *this = floatInVec(scalar.ref, scalar.i); +} + +inline floatInVec VecIdx::operator *=( float scalar ) +{ + return *this *= floatInVec(scalar); +} + +inline floatInVec VecIdx::operator *=( floatInVec scalar ) +{ + return *this = floatInVec(ref, i) * scalar; +} + +inline floatInVec VecIdx::operator /=( float scalar ) +{ + return *this /= floatInVec(scalar); +} + +inline floatInVec VecIdx::operator /=( floatInVec scalar ) +{ + return *this = floatInVec(ref, i) / scalar; +} + +inline floatInVec VecIdx::operator +=( float scalar ) +{ + return *this += floatInVec(scalar); +} + +inline floatInVec VecIdx::operator +=( floatInVec scalar ) +{ + return *this = floatInVec(ref, i) + scalar; +} + +inline floatInVec VecIdx::operator -=( float scalar ) +{ + return *this -= floatInVec(scalar); +} + +inline floatInVec VecIdx::operator -=( floatInVec scalar ) +{ + return *this = floatInVec(ref, i) - scalar; +} + +inline Vector3::Vector3( float _x, float _y, float _z ) +{ + if (__builtin_constant_p(_x) & __builtin_constant_p(_y) & __builtin_constant_p(_z)) { + mVec128 = (vec_float4){_x, _y, _z, 0.0f}; + } else { + float *pf = (float *)&mVec128; + pf[0] = _x; + pf[1] = _y; + pf[2] = _z; + } +} + +inline Vector3::Vector3( floatInVec _x, floatInVec _y, floatInVec _z ) +{ + vec_float4 xz = vec_mergeh( _x.get128(), _z.get128() ); + mVec128 = vec_mergeh( xz, _y.get128() ); +} + +inline Vector3::Vector3( Point3 pnt ) +{ + mVec128 = pnt.get128(); +} + +inline Vector3::Vector3( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +inline Vector3::Vector3( floatInVec scalar ) +{ + mVec128 = scalar.get128(); +} + +inline Vector3::Vector3( vec_float4 vf4 ) +{ + mVec128 = vf4; +} + +inline const Vector3 Vector3::xAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_1000 ); +} + +inline const Vector3 Vector3::yAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_0100 ); +} + +inline const Vector3 Vector3::zAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_0010 ); +} + +inline const Vector3 lerp( float t, Vector3 vec0, Vector3 vec1 ) +{ + return lerp( floatInVec(t), vec0, vec1 ); +} + +inline const Vector3 lerp( floatInVec t, Vector3 vec0, Vector3 vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector3 slerp( float t, Vector3 unitVec0, Vector3 unitVec1 ) +{ + return slerp( floatInVec(t), unitVec0, unitVec1 ); +} + +inline const Vector3 slerp( floatInVec t, Vector3 unitVec0, Vector3 unitVec1 ) +{ + vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + vec_uint4 selectMask; + cosAngle = _vmathVfDot3( unitVec0.get128(), unitVec1.get128() ); + cosAngle = vec_splat( cosAngle, 0 ); + selectMask = (vec_uint4)vec_cmpgt( ((vec_float4){_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL}), cosAngle ); + angle = acosf4( cosAngle ); + tttt = t.get128(); + oneMinusT = vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), tttt ); + angles = vec_mergeh( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), tttt ); + angles = vec_mergeh( angles, oneMinusT ); + angles = vec_madd( angles, angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sines = sinf4( angles ); + scales = divf4( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + return Vector3( vec_madd( unitVec0.get128(), scale0, vec_madd( unitVec1.get128(), scale1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); +} + +inline vec_float4 Vector3::get128( ) const +{ + return mVec128; +} + +inline void storeXYZ( Vector3 vec, vec_float4 * quad ) +{ + vec_float4 dstVec = *quad; + vec_uint4 mask = _VECTORMATH_MASK_0x000F; + dstVec = vec_sel(vec.get128(), dstVec, mask); + *quad = dstVec; +} + +inline void loadXYZArray( Vector3 & vec0, Vector3 & vec1, Vector3 & vec2, Vector3 & vec3, const vec_float4 * threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz, xyz1, xyz2, xyz3; + xyzx = threeQuads[0]; + yzxy = threeQuads[1]; + zxyz = threeQuads[2]; + xyz1 = vec_sld( xyzx, yzxy, 12 ); + xyz2 = vec_sld( yzxy, zxyz, 8 ); + xyz3 = vec_sld( zxyz, zxyz, 4 ); + vec0 = Vector3( xyzx ); + vec1 = Vector3( xyz1 ); + vec2 = Vector3( xyz2 ); + vec3 = Vector3( xyz3 ); +} + +inline void storeXYZArray( Vector3 vec0, Vector3 vec1, Vector3 vec2, Vector3 vec3, vec_float4 * threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz; + xyzx = vec_perm( vec0.get128(), vec1.get128(), _VECTORMATH_PERM_XYZA ); + yzxy = vec_perm( vec1.get128(), vec2.get128(), _VECTORMATH_PERM_YZAB ); + zxyz = vec_perm( vec2.get128(), vec3.get128(), _VECTORMATH_PERM_ZABC ); + threeQuads[0] = xyzx; + threeQuads[1] = yzxy; + threeQuads[2] = zxyz; +} + +inline void storeHalfFloats( Vector3 vec0, Vector3 vec1, Vector3 vec2, Vector3 vec3, Vector3 vec4, Vector3 vec5, Vector3 vec6, Vector3 vec7, vec_ushort8 * threeQuads ) +{ + vec_float4 xyz0[3]; + vec_float4 xyz1[3]; + storeXYZArray( vec0, vec1, vec2, vec3, xyz0 ); + storeXYZArray( vec4, vec5, vec6, vec7, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +} + +inline Vector3 & Vector3::operator =( Vector3 vec ) +{ + mVec128 = vec.mVec128; + return *this; +} + +inline Vector3 & Vector3::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +inline Vector3 & Vector3::setX( floatInVec _x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +inline const floatInVec Vector3::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +inline Vector3 & Vector3::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +inline Vector3 & Vector3::setY( floatInVec _y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +inline const floatInVec Vector3::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +inline Vector3 & Vector3::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +inline Vector3 & Vector3::setZ( floatInVec _z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +inline const floatInVec Vector3::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +inline Vector3 & Vector3::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +inline Vector3 & Vector3::setElem( int idx, floatInVec value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +inline const floatInVec Vector3::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +inline VecIdx Vector3::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +inline const floatInVec Vector3::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +inline const Vector3 Vector3::operator +( Vector3 vec ) const +{ + return Vector3( vec_add( mVec128, vec.mVec128 ) ); +} + +inline const Vector3 Vector3::operator -( Vector3 vec ) const +{ + return Vector3( vec_sub( mVec128, vec.mVec128 ) ); +} + +inline const Point3 Vector3::operator +( Point3 pnt ) const +{ + return Point3( vec_add( mVec128, pnt.get128() ) ); +} + +inline const Vector3 Vector3::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +inline const Vector3 Vector3::operator *( floatInVec scalar ) const +{ + return Vector3( vec_madd( mVec128, scalar.get128(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +inline Vector3 & Vector3::operator +=( Vector3 vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector3 & Vector3::operator -=( Vector3 vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector3 & Vector3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline Vector3 & Vector3::operator *=( floatInVec scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector3 Vector3::operator /( float scalar ) const +{ + return *this / floatInVec(scalar); +} + +inline const Vector3 Vector3::operator /( floatInVec scalar ) const +{ + return Vector3( divf4( mVec128, scalar.get128() ) ); +} + +inline Vector3 & Vector3::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline Vector3 & Vector3::operator /=( floatInVec scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector3 Vector3::operator -( ) const +{ + return Vector3( negatef4( mVec128 ) ); +} + +inline const Vector3 operator *( float scalar, Vector3 vec ) +{ + return floatInVec(scalar) * vec; +} + +inline const Vector3 operator *( floatInVec scalar, Vector3 vec ) +{ + return vec * scalar; +} + +inline const Vector3 mulPerElem( Vector3 vec0, Vector3 vec1 ) +{ + return Vector3( vec_madd( vec0.get128(), vec1.get128(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +inline const Vector3 divPerElem( Vector3 vec0, Vector3 vec1 ) +{ + return Vector3( divf4( vec0.get128(), vec1.get128() ) ); +} + +inline const Vector3 recipPerElem( Vector3 vec ) +{ + return Vector3( recipf4( vec.get128() ) ); +} + +inline const Vector3 sqrtPerElem( Vector3 vec ) +{ + return Vector3( sqrtf4( vec.get128() ) ); +} + +inline const Vector3 rsqrtPerElem( Vector3 vec ) +{ + return Vector3( rsqrtf4( vec.get128() ) ); +} + +inline const Vector3 absPerElem( Vector3 vec ) +{ + return Vector3( fabsf4( vec.get128() ) ); +} + +inline const Vector3 copySignPerElem( Vector3 vec0, Vector3 vec1 ) +{ + return Vector3( copysignf4( vec0.get128(), vec1.get128() ) ); +} + +inline const Vector3 maxPerElem( Vector3 vec0, Vector3 vec1 ) +{ + return Vector3( fmaxf4( vec0.get128(), vec1.get128() ) ); +} + +inline const floatInVec maxElem( Vector3 vec ) +{ + vec_float4 result; + result = fmaxf4( vec_splat( vec.get128(), 1 ), vec.get128() ); + result = fmaxf4( vec_splat( vec.get128(), 2 ), result ); + return floatInVec( result, 0 ); +} + +inline const Vector3 minPerElem( Vector3 vec0, Vector3 vec1 ) +{ + return Vector3( fminf4( vec0.get128(), vec1.get128() ) ); +} + +inline const floatInVec minElem( Vector3 vec ) +{ + vec_float4 result; + result = fminf4( vec_splat( vec.get128(), 1 ), vec.get128() ); + result = fminf4( vec_splat( vec.get128(), 2 ), result ); + return floatInVec( result, 0 ); +} + +inline const floatInVec sum( Vector3 vec ) +{ + vec_float4 result; + result = vec_add( vec_splat( vec.get128(), 1 ), vec.get128() ); + result = vec_add( vec_splat( vec.get128(), 2 ), result ); + return floatInVec( result, 0 ); +} + +inline const floatInVec dot( Vector3 vec0, Vector3 vec1 ) +{ + return floatInVec( _vmathVfDot3( vec0.get128(), vec1.get128() ), 0 ); +} + +inline const floatInVec lengthSqr( Vector3 vec ) +{ + return floatInVec( _vmathVfDot3( vec.get128(), vec.get128() ), 0 ); +} + +inline const floatInVec length( Vector3 vec ) +{ + return floatInVec( sqrtf4(_vmathVfDot3( vec.get128(), vec.get128() )), 0 ); +} + +inline const Vector3 normalize( Vector3 vec ) +{ + vec_float4 dot = _vmathVfDot3( vec.get128(), vec.get128() ); + dot = vec_splat( dot, 0 ); + return Vector3( vec_madd( vec.get128(), rsqrtf4( dot ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +inline const Vector3 cross( Vector3 vec0, Vector3 vec1 ) +{ + return Vector3( _vmathVfCross( vec0.get128(), vec1.get128() ) ); +} + +inline const Vector3 select( Vector3 vec0, Vector3 vec1, bool select1 ) +{ + return select( vec0, vec1, boolInVec(select1) ); +} + +inline const Vector3 select( Vector3 vec0, Vector3 vec1, boolInVec select1 ) +{ + return Vector3( vec_sel( vec0.get128(), vec1.get128(), select1.get128() ) ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( Vector3 vec ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +inline void print( Vector3 vec, const char * name ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +#endif + +inline Vector4::Vector4( float _x, float _y, float _z, float _w ) +{ + if (__builtin_constant_p(_x) & __builtin_constant_p(_y) & + __builtin_constant_p(_z) & __builtin_constant_p(_w)) { + mVec128 = (vec_float4){_x, _y, _z, _w}; + } else { + float *pf = (float *)&mVec128; + pf[0] = _x; + pf[1] = _y; + pf[2] = _z; + pf[3] = _w; + } +} + +inline Vector4::Vector4( floatInVec _x, floatInVec _y, floatInVec _z, floatInVec _w ) +{ + vec_float4 xz = vec_mergeh( _x.get128(), _z.get128() ); + vec_float4 yw = vec_mergeh( _y.get128(), _w.get128() ); + mVec128 = vec_mergeh( xz, yw ); +} + +inline Vector4::Vector4( Vector3 xyz, float _w ) +{ + mVec128 = xyz.get128(); + _vmathVfSetElement(mVec128, _w, 3); +} + +inline Vector4::Vector4( Vector3 xyz, floatInVec _w ) +{ + mVec128 = xyz.get128(); + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); +} + +inline Vector4::Vector4( Vector3 vec ) +{ + mVec128 = vec.get128(); + mVec128 = _vmathVfInsert(mVec128, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), 3); +} + +inline Vector4::Vector4( Point3 pnt ) +{ + mVec128 = pnt.get128(); + mVec128 = _vmathVfInsert(mVec128, ((vec_float4){1.0f,1.0f,1.0f,1.0f}), 3); +} + +inline Vector4::Vector4( Quat quat ) +{ + mVec128 = quat.get128(); +} + +inline Vector4::Vector4( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +inline Vector4::Vector4( floatInVec scalar ) +{ + mVec128 = scalar.get128(); +} + +inline Vector4::Vector4( vec_float4 vf4 ) +{ + mVec128 = vf4; +} + +inline const Vector4 Vector4::xAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_1000 ); +} + +inline const Vector4 Vector4::yAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0100 ); +} + +inline const Vector4 Vector4::zAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0010 ); +} + +inline const Vector4 Vector4::wAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0001 ); +} + +inline const Vector4 lerp( float t, Vector4 vec0, Vector4 vec1 ) +{ + return lerp( floatInVec(t), vec0, vec1 ); +} + +inline const Vector4 lerp( floatInVec t, Vector4 vec0, Vector4 vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector4 slerp( float t, Vector4 unitVec0, Vector4 unitVec1 ) +{ + return slerp( floatInVec(t), unitVec0, unitVec1 ); +} + +inline const Vector4 slerp( floatInVec t, Vector4 unitVec0, Vector4 unitVec1 ) +{ + vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + vec_uint4 selectMask; + cosAngle = _vmathVfDot4( unitVec0.get128(), unitVec1.get128() ); + cosAngle = vec_splat( cosAngle, 0 ); + selectMask = (vec_uint4)vec_cmpgt( ((vec_float4){_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL}), cosAngle ); + angle = acosf4( cosAngle ); + tttt = t.get128(); + oneMinusT = vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), tttt ); + angles = vec_mergeh( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), tttt ); + angles = vec_mergeh( angles, oneMinusT ); + angles = vec_madd( angles, angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + sines = sinf4( angles ); + scales = divf4( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + return Vector4( vec_madd( unitVec0.get128(), scale0, vec_madd( unitVec1.get128(), scale1, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) ); +} + +inline vec_float4 Vector4::get128( ) const +{ + return mVec128; +} + +inline void storeHalfFloats( Vector4 vec0, Vector4 vec1, Vector4 vec2, Vector4 vec3, vec_ushort8 * twoQuads ) +{ + twoQuads[0] = _vmath2VfToHalfFloats(vec0.get128(), vec1.get128()); + twoQuads[1] = _vmath2VfToHalfFloats(vec2.get128(), vec3.get128()); +} + +inline Vector4 & Vector4::operator =( Vector4 vec ) +{ + mVec128 = vec.mVec128; + return *this; +} + +inline Vector4 & Vector4::setXYZ( Vector3 vec ) +{ + mVec128 = vec_sel( vec.get128(), mVec128, _VECTORMATH_MASK_0x000F ); + return *this; +} + +inline const Vector3 Vector4::getXYZ( ) const +{ + return Vector3( mVec128 ); +} + +inline Vector4 & Vector4::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +inline Vector4 & Vector4::setX( floatInVec _x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +inline const floatInVec Vector4::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +inline Vector4 & Vector4::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +inline Vector4 & Vector4::setY( floatInVec _y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +inline const floatInVec Vector4::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +inline Vector4 & Vector4::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +inline Vector4 & Vector4::setZ( floatInVec _z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +inline const floatInVec Vector4::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +inline Vector4 & Vector4::setW( float _w ) +{ + _vmathVfSetElement(mVec128, _w, 3); + return *this; +} + +inline Vector4 & Vector4::setW( floatInVec _w ) +{ + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); + return *this; +} + +inline const floatInVec Vector4::getW( ) const +{ + return floatInVec( mVec128, 3 ); +} + +inline Vector4 & Vector4::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +inline Vector4 & Vector4::setElem( int idx, floatInVec value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +inline const floatInVec Vector4::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +inline VecIdx Vector4::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +inline const floatInVec Vector4::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +inline const Vector4 Vector4::operator +( Vector4 vec ) const +{ + return Vector4( vec_add( mVec128, vec.mVec128 ) ); +} + +inline const Vector4 Vector4::operator -( Vector4 vec ) const +{ + return Vector4( vec_sub( mVec128, vec.mVec128 ) ); +} + +inline const Vector4 Vector4::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +inline const Vector4 Vector4::operator *( floatInVec scalar ) const +{ + return Vector4( vec_madd( mVec128, scalar.get128(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +inline Vector4 & Vector4::operator +=( Vector4 vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector4 & Vector4::operator -=( Vector4 vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector4 & Vector4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline Vector4 & Vector4::operator *=( floatInVec scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector4 Vector4::operator /( float scalar ) const +{ + return *this / floatInVec(scalar); +} + +inline const Vector4 Vector4::operator /( floatInVec scalar ) const +{ + return Vector4( divf4( mVec128, scalar.get128() ) ); +} + +inline Vector4 & Vector4::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline Vector4 & Vector4::operator /=( floatInVec scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector4 Vector4::operator -( ) const +{ + return Vector4( negatef4( mVec128 ) ); +} + +inline const Vector4 operator *( float scalar, Vector4 vec ) +{ + return floatInVec(scalar) * vec; +} + +inline const Vector4 operator *( floatInVec scalar, Vector4 vec ) +{ + return vec * scalar; +} + +inline const Vector4 mulPerElem( Vector4 vec0, Vector4 vec1 ) +{ + return Vector4( vec_madd( vec0.get128(), vec1.get128(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +inline const Vector4 divPerElem( Vector4 vec0, Vector4 vec1 ) +{ + return Vector4( divf4( vec0.get128(), vec1.get128() ) ); +} + +inline const Vector4 recipPerElem( Vector4 vec ) +{ + return Vector4( recipf4( vec.get128() ) ); +} + +inline const Vector4 sqrtPerElem( Vector4 vec ) +{ + return Vector4( sqrtf4( vec.get128() ) ); +} + +inline const Vector4 rsqrtPerElem( Vector4 vec ) +{ + return Vector4( rsqrtf4( vec.get128() ) ); +} + +inline const Vector4 absPerElem( Vector4 vec ) +{ + return Vector4( fabsf4( vec.get128() ) ); +} + +inline const Vector4 copySignPerElem( Vector4 vec0, Vector4 vec1 ) +{ + return Vector4( copysignf4( vec0.get128(), vec1.get128() ) ); +} + +inline const Vector4 maxPerElem( Vector4 vec0, Vector4 vec1 ) +{ + return Vector4( fmaxf4( vec0.get128(), vec1.get128() ) ); +} + +inline const floatInVec maxElem( Vector4 vec ) +{ + vec_float4 result; + result = fmaxf4( vec_splat( vec.get128(), 1 ), vec.get128() ); + result = fmaxf4( vec_splat( vec.get128(), 2 ), result ); + result = fmaxf4( vec_splat( vec.get128(), 3 ), result ); + return floatInVec( result, 0 ); +} + +inline const Vector4 minPerElem( Vector4 vec0, Vector4 vec1 ) +{ + return Vector4( fminf4( vec0.get128(), vec1.get128() ) ); +} + +inline const floatInVec minElem( Vector4 vec ) +{ + vec_float4 result; + result = fminf4( vec_splat( vec.get128(), 1 ), vec.get128() ); + result = fminf4( vec_splat( vec.get128(), 2 ), result ); + result = fminf4( vec_splat( vec.get128(), 3 ), result ); + return floatInVec( result, 0 ); +} + +inline const floatInVec sum( Vector4 vec ) +{ + vec_float4 result; + result = vec_add( vec_splat( vec.get128(), 1 ), vec.get128() ); + result = vec_add( vec_splat( vec.get128(), 2 ), result ); + result = vec_add( vec_splat( vec.get128(), 3 ), result ); + return floatInVec( result, 0 ); +} + +inline const floatInVec dot( Vector4 vec0, Vector4 vec1 ) +{ + return floatInVec( _vmathVfDot4( vec0.get128(), vec1.get128() ), 0 ); +} + +inline const floatInVec lengthSqr( Vector4 vec ) +{ + return floatInVec( _vmathVfDot4( vec.get128(), vec.get128() ), 0 ); +} + +inline const floatInVec length( Vector4 vec ) +{ + return floatInVec( sqrtf4(_vmathVfDot4( vec.get128(), vec.get128() )), 0 ); +} + +inline const Vector4 normalize( Vector4 vec ) +{ + vec_float4 dot = _vmathVfDot4( vec.get128(), vec.get128() ); + return Vector4( vec_madd( vec.get128(), rsqrtf4( dot ), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +inline const Vector4 select( Vector4 vec0, Vector4 vec1, bool select1 ) +{ + return select( vec0, vec1, boolInVec(select1) ); +} + +inline const Vector4 select( Vector4 vec0, Vector4 vec1, boolInVec select1 ) +{ + return Vector4( vec_sel( vec0.get128(), vec1.get128(), select1.get128() ) ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( Vector4 vec ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +inline void print( Vector4 vec, const char * name ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +#endif + +inline Point3::Point3( float _x, float _y, float _z ) +{ + if (__builtin_constant_p(_x) & __builtin_constant_p(_y) & __builtin_constant_p(_z)) { + mVec128 = (vec_float4){_x, _y, _z, 0.0f}; + } else { + float *pf = (float *)&mVec128; + pf[0] = _x; + pf[1] = _y; + pf[2] = _z; + } +} + +inline Point3::Point3( floatInVec _x, floatInVec _y, floatInVec _z ) +{ + vec_float4 xz = vec_mergeh( _x.get128(), _z.get128() ); + mVec128 = vec_mergeh( xz, _y.get128() ); +} + +inline Point3::Point3( Vector3 vec ) +{ + mVec128 = vec.get128(); +} + +inline Point3::Point3( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +inline Point3::Point3( floatInVec scalar ) +{ + mVec128 = scalar.get128(); +} + +inline Point3::Point3( vec_float4 vf4 ) +{ + mVec128 = vf4; +} + +inline const Point3 lerp( float t, Point3 pnt0, Point3 pnt1 ) +{ + return lerp( floatInVec(t), pnt0, pnt1 ); +} + +inline const Point3 lerp( floatInVec t, Point3 pnt0, Point3 pnt1 ) +{ + return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); +} + +inline vec_float4 Point3::get128( ) const +{ + return mVec128; +} + +inline void storeXYZ( Point3 pnt, vec_float4 * quad ) +{ + vec_float4 dstVec = *quad; + vec_uint4 mask = _VECTORMATH_MASK_0x000F; + dstVec = vec_sel(pnt.get128(), dstVec, mask); + *quad = dstVec; +} + +inline void loadXYZArray( Point3 & pnt0, Point3 & pnt1, Point3 & pnt2, Point3 & pnt3, const vec_float4 * threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz, xyz1, xyz2, xyz3; + xyzx = threeQuads[0]; + yzxy = threeQuads[1]; + zxyz = threeQuads[2]; + xyz1 = vec_sld( xyzx, yzxy, 12 ); + xyz2 = vec_sld( yzxy, zxyz, 8 ); + xyz3 = vec_sld( zxyz, zxyz, 4 ); + pnt0 = Point3( xyzx ); + pnt1 = Point3( xyz1 ); + pnt2 = Point3( xyz2 ); + pnt3 = Point3( xyz3 ); +} + +inline void storeXYZArray( Point3 pnt0, Point3 pnt1, Point3 pnt2, Point3 pnt3, vec_float4 * threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz; + xyzx = vec_perm( pnt0.get128(), pnt1.get128(), _VECTORMATH_PERM_XYZA ); + yzxy = vec_perm( pnt1.get128(), pnt2.get128(), _VECTORMATH_PERM_YZAB ); + zxyz = vec_perm( pnt2.get128(), pnt3.get128(), _VECTORMATH_PERM_ZABC ); + threeQuads[0] = xyzx; + threeQuads[1] = yzxy; + threeQuads[2] = zxyz; +} + +inline void storeHalfFloats( Point3 pnt0, Point3 pnt1, Point3 pnt2, Point3 pnt3, Point3 pnt4, Point3 pnt5, Point3 pnt6, Point3 pnt7, vec_ushort8 * threeQuads ) +{ + vec_float4 xyz0[3]; + vec_float4 xyz1[3]; + storeXYZArray( pnt0, pnt1, pnt2, pnt3, xyz0 ); + storeXYZArray( pnt4, pnt5, pnt6, pnt7, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +} + +inline Point3 & Point3::operator =( Point3 pnt ) +{ + mVec128 = pnt.mVec128; + return *this; +} + +inline Point3 & Point3::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +inline Point3 & Point3::setX( floatInVec _x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +inline const floatInVec Point3::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +inline Point3 & Point3::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +inline Point3 & Point3::setY( floatInVec _y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +inline const floatInVec Point3::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +inline Point3 & Point3::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +inline Point3 & Point3::setZ( floatInVec _z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +inline const floatInVec Point3::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +inline Point3 & Point3::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +inline Point3 & Point3::setElem( int idx, floatInVec value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +inline const floatInVec Point3::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +inline VecIdx Point3::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +inline const floatInVec Point3::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +inline const Vector3 Point3::operator -( Point3 pnt ) const +{ + return Vector3( vec_sub( mVec128, pnt.mVec128 ) ); +} + +inline const Point3 Point3::operator +( Vector3 vec ) const +{ + return Point3( vec_add( mVec128, vec.get128() ) ); +} + +inline const Point3 Point3::operator -( Vector3 vec ) const +{ + return Point3( vec_sub( mVec128, vec.get128() ) ); +} + +inline Point3 & Point3::operator +=( Vector3 vec ) +{ + *this = *this + vec; + return *this; +} + +inline Point3 & Point3::operator -=( Vector3 vec ) +{ + *this = *this - vec; + return *this; +} + +inline const Point3 mulPerElem( Point3 pnt0, Point3 pnt1 ) +{ + return Point3( vec_madd( pnt0.get128(), pnt1.get128(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); +} + +inline const Point3 divPerElem( Point3 pnt0, Point3 pnt1 ) +{ + return Point3( divf4( pnt0.get128(), pnt1.get128() ) ); +} + +inline const Point3 recipPerElem( Point3 pnt ) +{ + return Point3( recipf4( pnt.get128() ) ); +} + +inline const Point3 sqrtPerElem( Point3 pnt ) +{ + return Point3( sqrtf4( pnt.get128() ) ); +} + +inline const Point3 rsqrtPerElem( Point3 pnt ) +{ + return Point3( rsqrtf4( pnt.get128() ) ); +} + +inline const Point3 absPerElem( Point3 pnt ) +{ + return Point3( fabsf4( pnt.get128() ) ); +} + +inline const Point3 copySignPerElem( Point3 pnt0, Point3 pnt1 ) +{ + return Point3( copysignf4( pnt0.get128(), pnt1.get128() ) ); +} + +inline const Point3 maxPerElem( Point3 pnt0, Point3 pnt1 ) +{ + return Point3( fmaxf4( pnt0.get128(), pnt1.get128() ) ); +} + +inline const floatInVec maxElem( Point3 pnt ) +{ + vec_float4 result; + result = fmaxf4( vec_splat( pnt.get128(), 1 ), pnt.get128() ); + result = fmaxf4( vec_splat( pnt.get128(), 2 ), result ); + return floatInVec( result, 0 ); +} + +inline const Point3 minPerElem( Point3 pnt0, Point3 pnt1 ) +{ + return Point3( fminf4( pnt0.get128(), pnt1.get128() ) ); +} + +inline const floatInVec minElem( Point3 pnt ) +{ + vec_float4 result; + result = fminf4( vec_splat( pnt.get128(), 1 ), pnt.get128() ); + result = fminf4( vec_splat( pnt.get128(), 2 ), result ); + return floatInVec( result, 0 ); +} + +inline const floatInVec sum( Point3 pnt ) +{ + vec_float4 result; + result = vec_add( vec_splat( pnt.get128(), 1 ), pnt.get128() ); + result = vec_add( vec_splat( pnt.get128(), 2 ), result ); + return floatInVec( result, 0 ); +} + +inline const Point3 scale( Point3 pnt, float scaleVal ) +{ + return scale( pnt, floatInVec( scaleVal ) ); +} + +inline const Point3 scale( Point3 pnt, floatInVec scaleVal ) +{ + return mulPerElem( pnt, Point3( scaleVal ) ); +} + +inline const Point3 scale( Point3 pnt, Vector3 scaleVec ) +{ + return mulPerElem( pnt, Point3( scaleVec ) ); +} + +inline const floatInVec projection( Point3 pnt, Vector3 unitVec ) +{ + return floatInVec( _vmathVfDot3( pnt.get128(), unitVec.get128() ), 0 ); +} + +inline const floatInVec distSqrFromOrigin( Point3 pnt ) +{ + return lengthSqr( Vector3( pnt ) ); +} + +inline const floatInVec distFromOrigin( Point3 pnt ) +{ + return length( Vector3( pnt ) ); +} + +inline const floatInVec distSqr( Point3 pnt0, Point3 pnt1 ) +{ + return lengthSqr( ( pnt1 - pnt0 ) ); +} + +inline const floatInVec dist( Point3 pnt0, Point3 pnt1 ) +{ + return length( ( pnt1 - pnt0 ) ); +} + +inline const Point3 select( Point3 pnt0, Point3 pnt1, bool select1 ) +{ + return select( pnt0, pnt1, boolInVec(select1) ); +} + +inline const Point3 select( Point3 pnt0, Point3 pnt1, boolInVec select1 ) +{ + return Point3( vec_sel( pnt0.get128(), pnt1.get128(), select1.get128() ) ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( Point3 pnt ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = pnt.get128(); + printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +inline void print( Point3 pnt, const char * name ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = pnt.get128(); + printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/cpp/vec_soa.h b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/vec_soa.h new file mode 100644 index 0000000..89fdfcf --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/vec_soa.h @@ -0,0 +1,1425 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_SOA_CPP_H +#define _VECTORMATH_VEC_SOA_CPP_H +//----------------------------------------------------------------------------- +// Constants +// for permutes, words are labeled [x,y,z,w] [a,b,c,d] + +#define _VECTORMATH_PERM_X 0x00010203 +#define _VECTORMATH_PERM_Y 0x04050607 +#define _VECTORMATH_PERM_Z 0x08090a0b +#define _VECTORMATH_PERM_W 0x0c0d0e0f +#define _VECTORMATH_PERM_A 0x10111213 +#define _VECTORMATH_PERM_B 0x14151617 +#define _VECTORMATH_PERM_C 0x18191a1b +#define _VECTORMATH_PERM_D 0x1c1d1e1f +#define _VECTORMATH_PERM_ZBWX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XCYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_C, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_ZDWX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_D, _VECTORMATH_PERM_W, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_ZCXA ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_A }) +#define _VECTORMATH_PERM_XBZD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_B, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_WDYB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_W, _VECTORMATH_PERM_D, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_ZBXD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_X, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_WCYA ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_W, _VECTORMATH_PERM_C, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A }) +#define _VECTORMATH_PERM_XDZB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_D, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B }) +#define _VECTORMATH_SLERP_TOL 0.999f + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Soa { + +inline Vector3::Vector3( const Vector3 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; +} + +inline Vector3::Vector3( vec_float4 _x, vec_float4 _y, vec_float4 _z ) +{ + mX = _x; + mY = _y; + mZ = _z; +} + +inline Vector3::Vector3( const Point3 & pnt ) +{ + mX = pnt.getX(); + mY = pnt.getY(); + mZ = pnt.getZ(); +} + +inline Vector3::Vector3( vec_float4 scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; +} + +inline Vector3::Vector3( Aos::Vector3 vec ) +{ + vec_float4 vec128 = vec.get128(); + mX = vec_splat( vec128, 0 ); + mY = vec_splat( vec128, 1 ); + mZ = vec_splat( vec128, 2 ); +} + +inline Vector3::Vector3( Aos::Vector3 vec0, Aos::Vector3 vec1, Aos::Vector3 vec2, Aos::Vector3 vec3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = vec_mergeh( vec0.get128(), vec2.get128() ); + tmp1 = vec_mergeh( vec1.get128(), vec3.get128() ); + tmp2 = vec_mergel( vec0.get128(), vec2.get128() ); + tmp3 = vec_mergel( vec1.get128(), vec3.get128() ); + mX = vec_mergeh( tmp0, tmp1 ); + mY = vec_mergel( tmp0, tmp1 ); + mZ = vec_mergeh( tmp2, tmp3 ); +} + +inline const Vector3 Vector3::xAxis( ) +{ + return Vector3( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +inline const Vector3 Vector3::yAxis( ) +{ + return Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){1.0f,1.0f,1.0f,1.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +inline const Vector3 Vector3::zAxis( ) +{ + return Vector3( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); +} + +inline const Vector3 lerp( vec_float4 t, const Vector3 & vec0, const Vector3 & vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector3 slerp( vec_float4 t, const Vector3 & unitVec0, const Vector3 & unitVec1 ) +{ + vec_float4 recipSinAngle, scale0, scale1, cosAngle, angle; + vec_uint4 selectMask; + cosAngle = dot( unitVec0, unitVec1 ); + selectMask = (vec_uint4)vec_cmpgt( (vec_float4){_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL}, cosAngle ); + angle = acosf4( cosAngle ); + recipSinAngle = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sinf4( angle ) ); + scale0 = vec_sel( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), t ), vec_madd( sinf4( vec_madd( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), t ), angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), recipSinAngle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), selectMask ); + scale1 = vec_sel( t, vec_madd( sinf4( vec_madd( t, angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), recipSinAngle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), selectMask ); + return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); +} + +inline void Vector3::get4Aos( Aos::Vector3 & result0, Aos::Vector3 & result1, Aos::Vector3 & result2, Aos::Vector3 & result3 ) const +{ + vec_float4 tmp0, tmp1; + tmp0 = vec_mergeh( mX, mZ ); + tmp1 = vec_mergel( mX, mZ ); + result0 = Aos::Vector3( vec_mergeh( tmp0, mY ) ); + result1 = Aos::Vector3( vec_perm( tmp0, mY, _VECTORMATH_PERM_ZBWX ) ); + result2 = Aos::Vector3( vec_perm( tmp1, mY, _VECTORMATH_PERM_XCYX ) ); + result3 = Aos::Vector3( vec_perm( tmp1, mY, _VECTORMATH_PERM_ZDWX ) ); +} + +inline void loadXYZArray( Vector3 & vec, const vec_float4 * threeQuads ) +{ + vec_float4 xyxy, yzyz, zxzx, xyzx, yzxy, zxyz; + xyzx = threeQuads[0]; + yzxy = threeQuads[1]; + zxyz = threeQuads[2]; + xyxy = vec_sld( yzxy, xyzx, 8 ); + zxzx = vec_sld( xyzx, zxyz, 8 ); + yzyz = vec_sld( zxyz, yzxy, 8 ); + vec.setX( vec_perm( xyxy, zxzx, _VECTORMATH_PERM_ZBXD ) ); + vec.setY( vec_perm( xyxy, yzyz, _VECTORMATH_PERM_WCYA ) ); + vec.setZ( vec_perm( zxzx, yzyz, _VECTORMATH_PERM_XDZB ) ); +} + +inline void storeXYZArray( const Vector3 & vec, vec_float4 * threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz, xyxy, zxzx, yzyz; + xyxy = vec_perm( vec.getX(), vec.getY(), _VECTORMATH_PERM_ZCXA ); + zxzx = vec_perm( vec.getZ(), vec.getX(), _VECTORMATH_PERM_XBZD ); + yzyz = vec_perm( vec.getY(), vec.getZ(), _VECTORMATH_PERM_WDYB ); + xyzx = vec_sld( xyxy, zxzx, 8 ); + yzxy = vec_sld( yzyz, xyxy, 8 ); + zxyz = vec_sld( zxzx, yzyz, 8 ); + threeQuads[0] = xyzx; + threeQuads[1] = yzxy; + threeQuads[2] = zxyz; +} + +inline void storeHalfFloats( const Vector3 & vec0, const Vector3 & vec1, vec_ushort8 * threeQuads ) +{ + vec_float4 xyz0[3]; + vec_float4 xyz1[3]; + storeXYZArray( vec0, xyz0 ); + storeXYZArray( vec1, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +} + +inline Vector3 & Vector3::operator =( const Vector3 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + return *this; +} + +inline Vector3 & Vector3::setX( vec_float4 _x ) +{ + mX = _x; + return *this; +} + +inline vec_float4 Vector3::getX( ) const +{ + return mX; +} + +inline Vector3 & Vector3::setY( vec_float4 _y ) +{ + mY = _y; + return *this; +} + +inline vec_float4 Vector3::getY( ) const +{ + return mY; +} + +inline Vector3 & Vector3::setZ( vec_float4 _z ) +{ + mZ = _z; + return *this; +} + +inline vec_float4 Vector3::getZ( ) const +{ + return mZ; +} + +inline Vector3 & Vector3::setElem( int idx, vec_float4 value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline vec_float4 Vector3::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline Vector3::vec_float4_t & Vector3::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline vec_float4 Vector3::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector3 Vector3::operator +( const Vector3 & vec ) const +{ + return Vector3( + vec_add( mX, vec.mX ), + vec_add( mY, vec.mY ), + vec_add( mZ, vec.mZ ) + ); +} + +inline const Vector3 Vector3::operator -( const Vector3 & vec ) const +{ + return Vector3( + vec_sub( mX, vec.mX ), + vec_sub( mY, vec.mY ), + vec_sub( mZ, vec.mZ ) + ); +} + +inline const Point3 Vector3::operator +( const Point3 & pnt ) const +{ + return Point3( + vec_add( mX, pnt.getX() ), + vec_add( mY, pnt.getY() ), + vec_add( mZ, pnt.getZ() ) + ); +} + +inline const Vector3 Vector3::operator *( vec_float4 scalar ) const +{ + return Vector3( + vec_madd( mX, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( mY, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( mZ, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline Vector3 & Vector3::operator +=( const Vector3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector3 & Vector3::operator -=( const Vector3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector3 & Vector3::operator *=( vec_float4 scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector3 Vector3::operator /( vec_float4 scalar ) const +{ + return Vector3( + divf4( mX, scalar ), + divf4( mY, scalar ), + divf4( mZ, scalar ) + ); +} + +inline Vector3 & Vector3::operator /=( vec_float4 scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector3 Vector3::operator -( ) const +{ + return Vector3( + negatef4( mX ), + negatef4( mY ), + negatef4( mZ ) + ); +} + +inline const Vector3 operator *( vec_float4 scalar, const Vector3 & vec ) +{ + return vec * scalar; +} + +inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + vec_madd( vec0.getX(), vec1.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( vec0.getY(), vec1.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( vec0.getZ(), vec1.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + divf4( vec0.getX(), vec1.getX() ), + divf4( vec0.getY(), vec1.getY() ), + divf4( vec0.getZ(), vec1.getZ() ) + ); +} + +inline const Vector3 recipPerElem( const Vector3 & vec ) +{ + return Vector3( + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec.getX() ), + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec.getY() ), + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec.getZ() ) + ); +} + +inline const Vector3 sqrtPerElem( const Vector3 & vec ) +{ + return Vector3( + sqrtf4( vec.getX() ), + sqrtf4( vec.getY() ), + sqrtf4( vec.getZ() ) + ); +} + +inline const Vector3 rsqrtPerElem( const Vector3 & vec ) +{ + return Vector3( + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( vec.getX() ) ), + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( vec.getY() ) ), + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( vec.getZ() ) ) + ); +} + +inline const Vector3 absPerElem( const Vector3 & vec ) +{ + return Vector3( + fabsf4( vec.getX() ), + fabsf4( vec.getY() ), + fabsf4( vec.getZ() ) + ); +} + +inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + copysignf4( vec0.getX(), vec1.getX() ), + copysignf4( vec0.getY(), vec1.getY() ), + copysignf4( vec0.getZ(), vec1.getZ() ) + ); +} + +inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + fmaxf4( vec0.getX(), vec1.getX() ), + fmaxf4( vec0.getY(), vec1.getY() ), + fmaxf4( vec0.getZ(), vec1.getZ() ) + ); +} + +inline vec_float4 maxElem( const Vector3 & vec ) +{ + vec_float4 result; + result = fmaxf4( vec.getX(), vec.getY() ); + result = fmaxf4( vec.getZ(), result ); + return result; +} + +inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + fminf4( vec0.getX(), vec1.getX() ), + fminf4( vec0.getY(), vec1.getY() ), + fminf4( vec0.getZ(), vec1.getZ() ) + ); +} + +inline vec_float4 minElem( const Vector3 & vec ) +{ + vec_float4 result; + result = fminf4( vec.getX(), vec.getY() ); + result = fminf4( vec.getZ(), result ); + return result; +} + +inline vec_float4 sum( const Vector3 & vec ) +{ + vec_float4 result; + result = vec_add( vec.getX(), vec.getY() ); + result = vec_add( result, vec.getZ() ); + return result; +} + +inline vec_float4 dot( const Vector3 & vec0, const Vector3 & vec1 ) +{ + vec_float4 result; + result = vec_madd( vec0.getX(), vec1.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result = vec_add( result, vec_madd( vec0.getY(), vec1.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( vec0.getZ(), vec1.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return result; +} + +inline vec_float4 lengthSqr( const Vector3 & vec ) +{ + vec_float4 result; + result = vec_madd( vec.getX(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result = vec_add( result, vec_madd( vec.getY(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( vec.getZ(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return result; +} + +inline vec_float4 length( const Vector3 & vec ) +{ + return sqrtf4( lengthSqr( vec ) ); +} + +inline const Vector3 normalize( const Vector3 & vec ) +{ + vec_float4 lenSqr, lenInv; + lenSqr = lengthSqr( vec ); + lenInv = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( lenSqr ) ); + return Vector3( + vec_madd( vec.getX(), lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( vec.getY(), lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( vec.getZ(), lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + vec_sub( vec_madd( vec0.getY(), vec1.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( vec0.getZ(), vec1.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_sub( vec_madd( vec0.getZ(), vec1.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( vec0.getX(), vec1.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), + vec_sub( vec_madd( vec0.getX(), vec1.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), vec_madd( vec0.getY(), vec1.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ) + ); +} + +inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, vec_uint4 select1 ) +{ + return Vector3( + vec_sel( vec0.getX(), vec1.getX(), select1 ), + vec_sel( vec0.getY(), vec1.getY(), select1 ), + vec_sel( vec0.getZ(), vec1.getZ(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Vector3 & vec ) +{ + Aos::Vector3 vec0, vec1, vec2, vec3; + vec.get4Aos( vec0, vec1, vec2, vec3 ); + printf("slot 0:\n"); + print( vec0 ); + printf("slot 1:\n"); + print( vec1 ); + printf("slot 2:\n"); + print( vec2 ); + printf("slot 3:\n"); + print( vec3 ); +} + +inline void print( const Vector3 & vec, const char * name ) +{ + Aos::Vector3 vec0, vec1, vec2, vec3; + printf( "%s:\n", name ); + vec.get4Aos( vec0, vec1, vec2, vec3 ); + printf("slot 0:\n"); + print( vec0 ); + printf("slot 1:\n"); + print( vec1 ); + printf("slot 2:\n"); + print( vec2 ); + printf("slot 3:\n"); + print( vec3 ); +} + +#endif + +inline Vector4::Vector4( const Vector4 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + mW = vec.mW; +} + +inline Vector4::Vector4( vec_float4 _x, vec_float4 _y, vec_float4 _z, vec_float4 _w ) +{ + mX = _x; + mY = _y; + mZ = _z; + mW = _w; +} + +inline Vector4::Vector4( const Vector3 & xyz, vec_float4 _w ) +{ + this->setXYZ( xyz ); + this->setW( _w ); +} + +inline Vector4::Vector4( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + mW = ((vec_float4){0.0f,0.0f,0.0f,0.0f}); +} + +inline Vector4::Vector4( const Point3 & pnt ) +{ + mX = pnt.getX(); + mY = pnt.getY(); + mZ = pnt.getZ(); + mW = ((vec_float4){1.0f,1.0f,1.0f,1.0f}); +} + +inline Vector4::Vector4( const Quat & quat ) +{ + mX = quat.getX(); + mY = quat.getY(); + mZ = quat.getZ(); + mW = quat.getW(); +} + +inline Vector4::Vector4( vec_float4 scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; + mW = scalar; +} + +inline Vector4::Vector4( Aos::Vector4 vec ) +{ + vec_float4 vec128 = vec.get128(); + mX = vec_splat( vec128, 0 ); + mY = vec_splat( vec128, 1 ); + mZ = vec_splat( vec128, 2 ); + mW = vec_splat( vec128, 3 ); +} + +inline Vector4::Vector4( Aos::Vector4 vec0, Aos::Vector4 vec1, Aos::Vector4 vec2, Aos::Vector4 vec3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = vec_mergeh( vec0.get128(), vec2.get128() ); + tmp1 = vec_mergeh( vec1.get128(), vec3.get128() ); + tmp2 = vec_mergel( vec0.get128(), vec2.get128() ); + tmp3 = vec_mergel( vec1.get128(), vec3.get128() ); + mX = vec_mergeh( tmp0, tmp1 ); + mY = vec_mergel( tmp0, tmp1 ); + mZ = vec_mergeh( tmp2, tmp3 ); + mW = vec_mergel( tmp2, tmp3 ); +} + +inline const Vector4 Vector4::xAxis( ) +{ + return Vector4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +inline const Vector4 Vector4::yAxis( ) +{ + return Vector4( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){1.0f,1.0f,1.0f,1.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +inline const Vector4 Vector4::zAxis( ) +{ + return Vector4( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){1.0f,1.0f,1.0f,1.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); +} + +inline const Vector4 Vector4::wAxis( ) +{ + return Vector4( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); +} + +inline const Vector4 lerp( vec_float4 t, const Vector4 & vec0, const Vector4 & vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector4 slerp( vec_float4 t, const Vector4 & unitVec0, const Vector4 & unitVec1 ) +{ + vec_float4 recipSinAngle, scale0, scale1, cosAngle, angle; + vec_uint4 selectMask; + cosAngle = dot( unitVec0, unitVec1 ); + selectMask = (vec_uint4)vec_cmpgt( (vec_float4){_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL,_VECTORMATH_SLERP_TOL}, cosAngle ); + angle = acosf4( cosAngle ); + recipSinAngle = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sinf4( angle ) ); + scale0 = vec_sel( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), t ), vec_madd( sinf4( vec_madd( vec_sub( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), t ), angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), recipSinAngle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), selectMask ); + scale1 = vec_sel( t, vec_madd( sinf4( vec_madd( t, angle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ), recipSinAngle, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), selectMask ); + return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); +} + +inline void Vector4::get4Aos( Aos::Vector4 & result0, Aos::Vector4 & result1, Aos::Vector4 & result2, Aos::Vector4 & result3 ) const +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = vec_mergeh( mX, mZ ); + tmp1 = vec_mergeh( mY, mW ); + tmp2 = vec_mergel( mX, mZ ); + tmp3 = vec_mergel( mY, mW ); + result0 = Aos::Vector4( vec_mergeh( tmp0, tmp1 ) ); + result1 = Aos::Vector4( vec_mergel( tmp0, tmp1 ) ); + result2 = Aos::Vector4( vec_mergeh( tmp2, tmp3 ) ); + result3 = Aos::Vector4( vec_mergel( tmp2, tmp3 ) ); +} + +inline void storeHalfFloats( const Vector4 & vec, vec_ushort8 * twoQuads ) +{ + Aos::Vector4 v0, v1, v2, v3; + vec.get4Aos( v0, v1, v2, v3 ); + twoQuads[0] = _vmath2VfToHalfFloats(v0.get128(), v1.get128()); + twoQuads[1] = _vmath2VfToHalfFloats(v2.get128(), v3.get128()); +} + +inline Vector4 & Vector4::operator =( const Vector4 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + mW = vec.mW; + return *this; +} + +inline Vector4 & Vector4::setXYZ( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + return *this; +} + +inline const Vector3 Vector4::getXYZ( ) const +{ + return Vector3( mX, mY, mZ ); +} + +inline Vector4 & Vector4::setX( vec_float4 _x ) +{ + mX = _x; + return *this; +} + +inline vec_float4 Vector4::getX( ) const +{ + return mX; +} + +inline Vector4 & Vector4::setY( vec_float4 _y ) +{ + mY = _y; + return *this; +} + +inline vec_float4 Vector4::getY( ) const +{ + return mY; +} + +inline Vector4 & Vector4::setZ( vec_float4 _z ) +{ + mZ = _z; + return *this; +} + +inline vec_float4 Vector4::getZ( ) const +{ + return mZ; +} + +inline Vector4 & Vector4::setW( vec_float4 _w ) +{ + mW = _w; + return *this; +} + +inline vec_float4 Vector4::getW( ) const +{ + return mW; +} + +inline Vector4 & Vector4::setElem( int idx, vec_float4 value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline vec_float4 Vector4::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline Vector4::vec_float4_t & Vector4::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline vec_float4 Vector4::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector4 Vector4::operator +( const Vector4 & vec ) const +{ + return Vector4( + vec_add( mX, vec.mX ), + vec_add( mY, vec.mY ), + vec_add( mZ, vec.mZ ), + vec_add( mW, vec.mW ) + ); +} + +inline const Vector4 Vector4::operator -( const Vector4 & vec ) const +{ + return Vector4( + vec_sub( mX, vec.mX ), + vec_sub( mY, vec.mY ), + vec_sub( mZ, vec.mZ ), + vec_sub( mW, vec.mW ) + ); +} + +inline const Vector4 Vector4::operator *( vec_float4 scalar ) const +{ + return Vector4( + vec_madd( mX, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( mY, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( mZ, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( mW, scalar, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline Vector4 & Vector4::operator +=( const Vector4 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector4 & Vector4::operator -=( const Vector4 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector4 & Vector4::operator *=( vec_float4 scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector4 Vector4::operator /( vec_float4 scalar ) const +{ + return Vector4( + divf4( mX, scalar ), + divf4( mY, scalar ), + divf4( mZ, scalar ), + divf4( mW, scalar ) + ); +} + +inline Vector4 & Vector4::operator /=( vec_float4 scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector4 Vector4::operator -( ) const +{ + return Vector4( + negatef4( mX ), + negatef4( mY ), + negatef4( mZ ), + negatef4( mW ) + ); +} + +inline const Vector4 operator *( vec_float4 scalar, const Vector4 & vec ) +{ + return vec * scalar; +} + +inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + vec_madd( vec0.getX(), vec1.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( vec0.getY(), vec1.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( vec0.getZ(), vec1.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( vec0.getW(), vec1.getW(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + divf4( vec0.getX(), vec1.getX() ), + divf4( vec0.getY(), vec1.getY() ), + divf4( vec0.getZ(), vec1.getZ() ), + divf4( vec0.getW(), vec1.getW() ) + ); +} + +inline const Vector4 recipPerElem( const Vector4 & vec ) +{ + return Vector4( + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec.getX() ), + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec.getY() ), + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec.getZ() ), + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), vec.getW() ) + ); +} + +inline const Vector4 sqrtPerElem( const Vector4 & vec ) +{ + return Vector4( + sqrtf4( vec.getX() ), + sqrtf4( vec.getY() ), + sqrtf4( vec.getZ() ), + sqrtf4( vec.getW() ) + ); +} + +inline const Vector4 rsqrtPerElem( const Vector4 & vec ) +{ + return Vector4( + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( vec.getX() ) ), + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( vec.getY() ) ), + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( vec.getZ() ) ), + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( vec.getW() ) ) + ); +} + +inline const Vector4 absPerElem( const Vector4 & vec ) +{ + return Vector4( + fabsf4( vec.getX() ), + fabsf4( vec.getY() ), + fabsf4( vec.getZ() ), + fabsf4( vec.getW() ) + ); +} + +inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + copysignf4( vec0.getX(), vec1.getX() ), + copysignf4( vec0.getY(), vec1.getY() ), + copysignf4( vec0.getZ(), vec1.getZ() ), + copysignf4( vec0.getW(), vec1.getW() ) + ); +} + +inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + fmaxf4( vec0.getX(), vec1.getX() ), + fmaxf4( vec0.getY(), vec1.getY() ), + fmaxf4( vec0.getZ(), vec1.getZ() ), + fmaxf4( vec0.getW(), vec1.getW() ) + ); +} + +inline vec_float4 maxElem( const Vector4 & vec ) +{ + vec_float4 result; + result = fmaxf4( vec.getX(), vec.getY() ); + result = fmaxf4( vec.getZ(), result ); + result = fmaxf4( vec.getW(), result ); + return result; +} + +inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + fminf4( vec0.getX(), vec1.getX() ), + fminf4( vec0.getY(), vec1.getY() ), + fminf4( vec0.getZ(), vec1.getZ() ), + fminf4( vec0.getW(), vec1.getW() ) + ); +} + +inline vec_float4 minElem( const Vector4 & vec ) +{ + vec_float4 result; + result = fminf4( vec.getX(), vec.getY() ); + result = fminf4( vec.getZ(), result ); + result = fminf4( vec.getW(), result ); + return result; +} + +inline vec_float4 sum( const Vector4 & vec ) +{ + vec_float4 result; + result = vec_add( vec.getX(), vec.getY() ); + result = vec_add( result, vec.getZ() ); + result = vec_add( result, vec.getW() ); + return result; +} + +inline vec_float4 dot( const Vector4 & vec0, const Vector4 & vec1 ) +{ + vec_float4 result; + result = vec_madd( vec0.getX(), vec1.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result = vec_add( result, vec_madd( vec0.getY(), vec1.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( vec0.getZ(), vec1.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( vec0.getW(), vec1.getW(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return result; +} + +inline vec_float4 lengthSqr( const Vector4 & vec ) +{ + vec_float4 result; + result = vec_madd( vec.getX(), vec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result = vec_add( result, vec_madd( vec.getY(), vec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( vec.getZ(), vec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( vec.getW(), vec.getW(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return result; +} + +inline vec_float4 length( const Vector4 & vec ) +{ + return sqrtf4( lengthSqr( vec ) ); +} + +inline const Vector4 normalize( const Vector4 & vec ) +{ + vec_float4 lenSqr, lenInv; + lenSqr = lengthSqr( vec ); + lenInv = divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( lenSqr ) ); + return Vector4( + vec_madd( vec.getX(), lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( vec.getY(), lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( vec.getZ(), lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( vec.getW(), lenInv, ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, vec_uint4 select1 ) +{ + return Vector4( + vec_sel( vec0.getX(), vec1.getX(), select1 ), + vec_sel( vec0.getY(), vec1.getY(), select1 ), + vec_sel( vec0.getZ(), vec1.getZ(), select1 ), + vec_sel( vec0.getW(), vec1.getW(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Vector4 & vec ) +{ + Aos::Vector4 vec0, vec1, vec2, vec3; + vec.get4Aos( vec0, vec1, vec2, vec3 ); + printf("slot 0:\n"); + print( vec0 ); + printf("slot 1:\n"); + print( vec1 ); + printf("slot 2:\n"); + print( vec2 ); + printf("slot 3:\n"); + print( vec3 ); +} + +inline void print( const Vector4 & vec, const char * name ) +{ + Aos::Vector4 vec0, vec1, vec2, vec3; + printf( "%s:\n", name ); + vec.get4Aos( vec0, vec1, vec2, vec3 ); + printf("slot 0:\n"); + print( vec0 ); + printf("slot 1:\n"); + print( vec1 ); + printf("slot 2:\n"); + print( vec2 ); + printf("slot 3:\n"); + print( vec3 ); +} + +#endif + +inline Point3::Point3( const Point3 & pnt ) +{ + mX = pnt.mX; + mY = pnt.mY; + mZ = pnt.mZ; +} + +inline Point3::Point3( vec_float4 _x, vec_float4 _y, vec_float4 _z ) +{ + mX = _x; + mY = _y; + mZ = _z; +} + +inline Point3::Point3( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); +} + +inline Point3::Point3( vec_float4 scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; +} + +inline Point3::Point3( Aos::Point3 pnt ) +{ + vec_float4 vec128 = pnt.get128(); + mX = vec_splat( vec128, 0 ); + mY = vec_splat( vec128, 1 ); + mZ = vec_splat( vec128, 2 ); +} + +inline Point3::Point3( Aos::Point3 pnt0, Aos::Point3 pnt1, Aos::Point3 pnt2, Aos::Point3 pnt3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = vec_mergeh( pnt0.get128(), pnt2.get128() ); + tmp1 = vec_mergeh( pnt1.get128(), pnt3.get128() ); + tmp2 = vec_mergel( pnt0.get128(), pnt2.get128() ); + tmp3 = vec_mergel( pnt1.get128(), pnt3.get128() ); + mX = vec_mergeh( tmp0, tmp1 ); + mY = vec_mergel( tmp0, tmp1 ); + mZ = vec_mergeh( tmp2, tmp3 ); +} + +inline const Point3 lerp( vec_float4 t, const Point3 & pnt0, const Point3 & pnt1 ) +{ + return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); +} + +inline void Point3::get4Aos( Aos::Point3 & result0, Aos::Point3 & result1, Aos::Point3 & result2, Aos::Point3 & result3 ) const +{ + vec_float4 tmp0, tmp1; + tmp0 = vec_mergeh( mX, mZ ); + tmp1 = vec_mergel( mX, mZ ); + result0 = Aos::Point3( vec_mergeh( tmp0, mY ) ); + result1 = Aos::Point3( vec_perm( tmp0, mY, _VECTORMATH_PERM_ZBWX ) ); + result2 = Aos::Point3( vec_perm( tmp1, mY, _VECTORMATH_PERM_XCYX ) ); + result3 = Aos::Point3( vec_perm( tmp1, mY, _VECTORMATH_PERM_ZDWX ) ); +} + +inline void loadXYZArray( Point3 & vec, const vec_float4 * threeQuads ) +{ + vec_float4 xyxy, yzyz, zxzx, xyzx, yzxy, zxyz; + xyzx = threeQuads[0]; + yzxy = threeQuads[1]; + zxyz = threeQuads[2]; + xyxy = vec_sld( yzxy, xyzx, 8 ); + zxzx = vec_sld( xyzx, zxyz, 8 ); + yzyz = vec_sld( zxyz, yzxy, 8 ); + vec.setX( vec_perm( xyxy, zxzx, _VECTORMATH_PERM_ZBXD ) ); + vec.setY( vec_perm( xyxy, yzyz, _VECTORMATH_PERM_WCYA ) ); + vec.setZ( vec_perm( zxzx, yzyz, _VECTORMATH_PERM_XDZB ) ); +} + +inline void storeXYZArray( const Point3 & vec, vec_float4 * threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz, xyxy, zxzx, yzyz; + xyxy = vec_perm( vec.getX(), vec.getY(), _VECTORMATH_PERM_ZCXA ); + zxzx = vec_perm( vec.getZ(), vec.getX(), _VECTORMATH_PERM_XBZD ); + yzyz = vec_perm( vec.getY(), vec.getZ(), _VECTORMATH_PERM_WDYB ); + xyzx = vec_sld( xyxy, zxzx, 8 ); + yzxy = vec_sld( yzyz, xyxy, 8 ); + zxyz = vec_sld( zxzx, yzyz, 8 ); + threeQuads[0] = xyzx; + threeQuads[1] = yzxy; + threeQuads[2] = zxyz; +} + +inline void storeHalfFloats( const Point3 & pnt0, const Point3 & pnt1, vec_ushort8 * threeQuads ) +{ + vec_float4 xyz0[3]; + vec_float4 xyz1[3]; + storeXYZArray( pnt0, xyz0 ); + storeXYZArray( pnt1, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +} + +inline Point3 & Point3::operator =( const Point3 & pnt ) +{ + mX = pnt.mX; + mY = pnt.mY; + mZ = pnt.mZ; + return *this; +} + +inline Point3 & Point3::setX( vec_float4 _x ) +{ + mX = _x; + return *this; +} + +inline vec_float4 Point3::getX( ) const +{ + return mX; +} + +inline Point3 & Point3::setY( vec_float4 _y ) +{ + mY = _y; + return *this; +} + +inline vec_float4 Point3::getY( ) const +{ + return mY; +} + +inline Point3 & Point3::setZ( vec_float4 _z ) +{ + mZ = _z; + return *this; +} + +inline vec_float4 Point3::getZ( ) const +{ + return mZ; +} + +inline Point3 & Point3::setElem( int idx, vec_float4 value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline vec_float4 Point3::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline Point3::vec_float4_t & Point3::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline vec_float4 Point3::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector3 Point3::operator -( const Point3 & pnt ) const +{ + return Vector3( + vec_sub( mX, pnt.mX ), + vec_sub( mY, pnt.mY ), + vec_sub( mZ, pnt.mZ ) + ); +} + +inline const Point3 Point3::operator +( const Vector3 & vec ) const +{ + return Point3( + vec_add( mX, vec.getX() ), + vec_add( mY, vec.getY() ), + vec_add( mZ, vec.getZ() ) + ); +} + +inline const Point3 Point3::operator -( const Vector3 & vec ) const +{ + return Point3( + vec_sub( mX, vec.getX() ), + vec_sub( mY, vec.getY() ), + vec_sub( mZ, vec.getZ() ) + ); +} + +inline Point3 & Point3::operator +=( const Vector3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Point3 & Point3::operator -=( const Vector3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + vec_madd( pnt0.getX(), pnt1.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( pnt0.getY(), pnt1.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ), + vec_madd( pnt0.getZ(), pnt1.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) + ); +} + +inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + divf4( pnt0.getX(), pnt1.getX() ), + divf4( pnt0.getY(), pnt1.getY() ), + divf4( pnt0.getZ(), pnt1.getZ() ) + ); +} + +inline const Point3 recipPerElem( const Point3 & pnt ) +{ + return Point3( + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), pnt.getX() ), + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), pnt.getY() ), + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), pnt.getZ() ) + ); +} + +inline const Point3 sqrtPerElem( const Point3 & pnt ) +{ + return Point3( + sqrtf4( pnt.getX() ), + sqrtf4( pnt.getY() ), + sqrtf4( pnt.getZ() ) + ); +} + +inline const Point3 rsqrtPerElem( const Point3 & pnt ) +{ + return Point3( + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( pnt.getX() ) ), + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( pnt.getY() ) ), + divf4( ((vec_float4){1.0f,1.0f,1.0f,1.0f}), sqrtf4( pnt.getZ() ) ) + ); +} + +inline const Point3 absPerElem( const Point3 & pnt ) +{ + return Point3( + fabsf4( pnt.getX() ), + fabsf4( pnt.getY() ), + fabsf4( pnt.getZ() ) + ); +} + +inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + copysignf4( pnt0.getX(), pnt1.getX() ), + copysignf4( pnt0.getY(), pnt1.getY() ), + copysignf4( pnt0.getZ(), pnt1.getZ() ) + ); +} + +inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + fmaxf4( pnt0.getX(), pnt1.getX() ), + fmaxf4( pnt0.getY(), pnt1.getY() ), + fmaxf4( pnt0.getZ(), pnt1.getZ() ) + ); +} + +inline vec_float4 maxElem( const Point3 & pnt ) +{ + vec_float4 result; + result = fmaxf4( pnt.getX(), pnt.getY() ); + result = fmaxf4( pnt.getZ(), result ); + return result; +} + +inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + fminf4( pnt0.getX(), pnt1.getX() ), + fminf4( pnt0.getY(), pnt1.getY() ), + fminf4( pnt0.getZ(), pnt1.getZ() ) + ); +} + +inline vec_float4 minElem( const Point3 & pnt ) +{ + vec_float4 result; + result = fminf4( pnt.getX(), pnt.getY() ); + result = fminf4( pnt.getZ(), result ); + return result; +} + +inline vec_float4 sum( const Point3 & pnt ) +{ + vec_float4 result; + result = vec_add( pnt.getX(), pnt.getY() ); + result = vec_add( result, pnt.getZ() ); + return result; +} + +inline const Point3 scale( const Point3 & pnt, vec_float4 scaleVal ) +{ + return mulPerElem( pnt, Point3( scaleVal ) ); +} + +inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ) +{ + return mulPerElem( pnt, Point3( scaleVec ) ); +} + +inline vec_float4 projection( const Point3 & pnt, const Vector3 & unitVec ) +{ + vec_float4 result; + result = vec_madd( pnt.getX(), unitVec.getX(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ); + result = vec_add( result, vec_madd( pnt.getY(), unitVec.getY(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + result = vec_add( result, vec_madd( pnt.getZ(), unitVec.getZ(), ((vec_float4){0.0f,0.0f,0.0f,0.0f}) ) ); + return result; +} + +inline vec_float4 distSqrFromOrigin( const Point3 & pnt ) +{ + return lengthSqr( Vector3( pnt ) ); +} + +inline vec_float4 distFromOrigin( const Point3 & pnt ) +{ + return length( Vector3( pnt ) ); +} + +inline vec_float4 distSqr( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return lengthSqr( ( pnt1 - pnt0 ) ); +} + +inline vec_float4 dist( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return length( ( pnt1 - pnt0 ) ); +} + +inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, vec_uint4 select1 ) +{ + return Point3( + vec_sel( pnt0.getX(), pnt1.getX(), select1 ), + vec_sel( pnt0.getY(), pnt1.getY(), select1 ), + vec_sel( pnt0.getZ(), pnt1.getZ(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Point3 & pnt ) +{ + Aos::Point3 vec0, vec1, vec2, vec3; + pnt.get4Aos( vec0, vec1, vec2, vec3 ); + printf("slot 0:\n"); + print( vec0 ); + printf("slot 1:\n"); + print( vec1 ); + printf("slot 2:\n"); + print( vec2 ); + printf("slot 3:\n"); + print( vec3 ); +} + +inline void print( const Point3 & pnt, const char * name ) +{ + Aos::Point3 vec0, vec1, vec2, vec3; + printf( "%s:\n", name ); + pnt.get4Aos( vec0, vec1, vec2, vec3 ); + printf("slot 0:\n"); + print( vec0 ); + printf("slot 1:\n"); + print( vec1 ); + printf("slot 2:\n"); + print( vec2 ); + printf("slot 3:\n"); + print( vec3 ); +} + +#endif + +} // namespace Soa +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/cpp/vecidx_aos.h b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/vecidx_aos.h new file mode 100644 index 0000000..df33575 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/vecidx_aos.h @@ -0,0 +1,80 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VECIDX_AOS_H +#define _VECTORMATH_VECIDX_AOS_H + +#include "floatInVec.h" + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// VecIdx +// Used in setting elements of Vector3, Vector4, Point3, or Quat with the +// subscripting operator. +// + +class VecIdx +{ +private: + typedef vec_float4 vec_float4_t; + vec_float4_t &ref __attribute__ ((aligned(16))); + int i __attribute__ ((aligned(16))); +public: + inline VecIdx( vec_float4_t& vec, int idx ): ref(vec) { i = idx; } + + // implicitly casts to float unless _VECTORMATH_NO_SCALAR_CAST defined + // in which case, implicitly casts to floatInVec, and one must call + // getAsFloat to convert to float. + // +#ifdef _VECTORMATH_NO_SCALAR_CAST + inline operator floatInVec() const; + inline float getAsFloat() const; +#else + inline operator float() const; +#endif + + inline float operator =( float scalar ); + inline floatInVec operator =( floatInVec scalar ); + inline floatInVec operator =( const VecIdx& scalar ); + inline floatInVec operator *=( float scalar ); + inline floatInVec operator *=( floatInVec scalar ); + inline floatInVec operator /=( float scalar ); + inline floatInVec operator /=( floatInVec scalar ); + inline floatInVec operator +=( float scalar ); + inline floatInVec operator +=( floatInVec scalar ); + inline floatInVec operator -=( float scalar ); + inline floatInVec operator -=( floatInVec scalar ); +}; + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/cpp/vectormath_aos.h b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/vectormath_aos.h new file mode 100644 index 0000000..0a7fa17 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/vectormath_aos.h @@ -0,0 +1,2244 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_AOS_CPP_PPU_H +#define _VECTORMATH_AOS_CPP_PPU_H + +#include +#include +#include "vecidx_aos.h" +#include "floatInVec.h" +#include "boolInVec.h" + +#ifdef _VECTORMATH_DEBUG +#include +#endif + +namespace Vectormath { + +namespace Aos { + +//----------------------------------------------------------------------------- +// Forward Declarations +// + +class Vector3; +class Vector4; +class Point3; +class Quat; +class Matrix3; +class Matrix4; +class Transform3; + +// A 3-D vector in array-of-structures format +// +class Vector3 +{ + vec_float4 mVec128; + +public: + // Default constructor; does no initialization + // + inline Vector3( ) { }; + + // Construct a 3-D vector from x, y, and z elements + // + inline Vector3( float x, float y, float z ); + + // Construct a 3-D vector from x, y, and z elements (scalar data contained in vector data type) + // + inline Vector3( floatInVec x, floatInVec y, floatInVec z ); + + // Copy elements from a 3-D point into a 3-D vector + // + explicit inline Vector3( Point3 pnt ); + + // Set all elements of a 3-D vector to the same scalar value + // + explicit inline Vector3( float scalar ); + + // Set all elements of a 3-D vector to the same scalar value (scalar data contained in vector data type) + // + explicit inline Vector3( floatInVec scalar ); + + // Set vector float data in a 3-D vector + // + explicit inline Vector3( vec_float4 vf4 ); + + // Get vector float data from a 3-D vector + // + inline vec_float4 get128( ) const; + + // Assign one 3-D vector to another + // + inline Vector3 & operator =( Vector3 vec ); + + // Set the x element of a 3-D vector + // + inline Vector3 & setX( float x ); + + // Set the y element of a 3-D vector + // + inline Vector3 & setY( float y ); + + // Set the z element of a 3-D vector + // + inline Vector3 & setZ( float z ); + + // Set the x element of a 3-D vector (scalar data contained in vector data type) + // + inline Vector3 & setX( floatInVec x ); + + // Set the y element of a 3-D vector (scalar data contained in vector data type) + // + inline Vector3 & setY( floatInVec y ); + + // Set the z element of a 3-D vector (scalar data contained in vector data type) + // + inline Vector3 & setZ( floatInVec z ); + + // Get the x element of a 3-D vector + // + inline const floatInVec getX( ) const; + + // Get the y element of a 3-D vector + // + inline const floatInVec getY( ) const; + + // Get the z element of a 3-D vector + // + inline const floatInVec getZ( ) const; + + // Set an x, y, or z element of a 3-D vector by index + // + inline Vector3 & setElem( int idx, float value ); + + // Set an x, y, or z element of a 3-D vector by index (scalar data contained in vector data type) + // + inline Vector3 & setElem( int idx, floatInVec value ); + + // Get an x, y, or z element of a 3-D vector by index + // + inline const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + inline const floatInVec operator []( int idx ) const; + + // Add two 3-D vectors + // + inline const Vector3 operator +( Vector3 vec ) const; + + // Subtract a 3-D vector from another 3-D vector + // + inline const Vector3 operator -( Vector3 vec ) const; + + // Add a 3-D vector to a 3-D point + // + inline const Point3 operator +( Point3 pnt ) const; + + // Multiply a 3-D vector by a scalar + // + inline const Vector3 operator *( float scalar ) const; + + // Divide a 3-D vector by a scalar + // + inline const Vector3 operator /( float scalar ) const; + + // Multiply a 3-D vector by a scalar (scalar data contained in vector data type) + // + inline const Vector3 operator *( floatInVec scalar ) const; + + // Divide a 3-D vector by a scalar (scalar data contained in vector data type) + // + inline const Vector3 operator /( floatInVec scalar ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Vector3 & operator +=( Vector3 vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Vector3 & operator -=( Vector3 vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector3 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector3 & operator /=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + inline Vector3 & operator *=( floatInVec scalar ); + + // Perform compound assignment and division by a scalar (scalar data contained in vector data type) + // + inline Vector3 & operator /=( floatInVec scalar ); + + // Negate all elements of a 3-D vector + // + inline const Vector3 operator -( ) const; + + // Construct x axis + // + static inline const Vector3 xAxis( ); + + // Construct y axis + // + static inline const Vector3 yAxis( ); + + // Construct z axis + // + static inline const Vector3 zAxis( ); + +}; + +// Multiply a 3-D vector by a scalar +// +inline const Vector3 operator *( float scalar, Vector3 vec ); + +// Multiply a 3-D vector by a scalar (scalar data contained in vector data type) +// +inline const Vector3 operator *( floatInVec scalar, Vector3 vec ); + +// Multiply two 3-D vectors per element +// +inline const Vector3 mulPerElem( Vector3 vec0, Vector3 vec1 ); + +// Divide two 3-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector3 divPerElem( Vector3 vec0, Vector3 vec1 ); + +// Compute the reciprocal of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector3 recipPerElem( Vector3 vec ); + +// Compute the square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector3 sqrtPerElem( Vector3 vec ); + +// Compute the reciprocal square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector3 rsqrtPerElem( Vector3 vec ); + +// Compute the absolute value of a 3-D vector per element +// +inline const Vector3 absPerElem( Vector3 vec ); + +// Copy sign from one 3-D vector to another, per element +// +inline const Vector3 copySignPerElem( Vector3 vec0, Vector3 vec1 ); + +// Maximum of two 3-D vectors per element +// +inline const Vector3 maxPerElem( Vector3 vec0, Vector3 vec1 ); + +// Minimum of two 3-D vectors per element +// +inline const Vector3 minPerElem( Vector3 vec0, Vector3 vec1 ); + +// Maximum element of a 3-D vector +// +inline const floatInVec maxElem( Vector3 vec ); + +// Minimum element of a 3-D vector +// +inline const floatInVec minElem( Vector3 vec ); + +// Compute the sum of all elements of a 3-D vector +// +inline const floatInVec sum( Vector3 vec ); + +// Compute the dot product of two 3-D vectors +// +inline const floatInVec dot( Vector3 vec0, Vector3 vec1 ); + +// Compute the square of the length of a 3-D vector +// +inline const floatInVec lengthSqr( Vector3 vec ); + +// Compute the length of a 3-D vector +// +inline const floatInVec length( Vector3 vec ); + +// Normalize a 3-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector3 normalize( Vector3 vec ); + +// Compute cross product of two 3-D vectors +// +inline const Vector3 cross( Vector3 vec0, Vector3 vec1 ); + +// Outer product of two 3-D vectors +// +inline const Matrix3 outer( Vector3 vec0, Vector3 vec1 ); + +// Pre-multiply a row vector by a 3x3 matrix +// NOTE: +// Slower than column post-multiply. +// +inline const Vector3 rowMul( Vector3 vec, const Matrix3 & mat ); + +// Cross-product matrix of a 3-D vector +// +inline const Matrix3 crossMatrix( Vector3 vec ); + +// Create cross-product matrix and multiply +// NOTE: +// Faster than separately creating a cross-product matrix and multiplying. +// +inline const Matrix3 crossMatrixMul( Vector3 vec, const Matrix3 & mat ); + +// Linear interpolation between two 3-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector3 lerp( float t, Vector3 vec0, Vector3 vec1 ); + +// Linear interpolation between two 3-D vectors (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector3 lerp( floatInVec t, Vector3 vec0, Vector3 vec1 ); + +// Spherical linear interpolation between two 3-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector3 slerp( float t, Vector3 unitVec0, Vector3 unitVec1 ); + +// Spherical linear interpolation between two 3-D vectors (scalar data contained in vector data type) +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector3 slerp( floatInVec t, Vector3 unitVec0, Vector3 unitVec1 ); + +// Conditionally select between two 3-D vectors +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +inline const Vector3 select( Vector3 vec0, Vector3 vec1, bool select1 ); + +// Conditionally select between two 3-D vectors (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Vector3 select( Vector3 vec0, Vector3 vec1, boolInVec select1 ); + +// Store x, y, and z elements of a 3-D vector in the first three words of a quadword. +// The value of the fourth word (the word with the highest address) remains unchanged +// +inline void storeXYZ( Vector3 vec, vec_float4 * quad ); + +// Load four three-float 3-D vectors, stored in three quadwords +// +inline void loadXYZArray( Vector3 & vec0, Vector3 & vec1, Vector3 & vec2, Vector3 & vec3, const vec_float4 * threeQuads ); + +// Store four 3-D vectors in three quadwords +// +inline void storeXYZArray( Vector3 vec0, Vector3 vec1, Vector3 vec2, Vector3 vec3, vec_float4 * threeQuads ); + +// Store eight 3-D vectors as half-floats +// +inline void storeHalfFloats( Vector3 vec0, Vector3 vec1, Vector3 vec2, Vector3 vec3, Vector3 vec4, Vector3 vec5, Vector3 vec6, Vector3 vec7, vec_ushort8 * threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( Vector3 vec ); + +// Print a 3-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( Vector3 vec, const char * name ); + +#endif + +// A 4-D vector in array-of-structures format +// +class Vector4 +{ + vec_float4 mVec128; + +public: + // Default constructor; does no initialization + // + inline Vector4( ) { }; + + // Construct a 4-D vector from x, y, z, and w elements + // + inline Vector4( float x, float y, float z, float w ); + + // Construct a 4-D vector from x, y, z, and w elements (scalar data contained in vector data type) + // + inline Vector4( floatInVec x, floatInVec y, floatInVec z, floatInVec w ); + + // Construct a 4-D vector from a 3-D vector and a scalar + // + inline Vector4( Vector3 xyz, float w ); + + // Construct a 4-D vector from a 3-D vector and a scalar (scalar data contained in vector data type) + // + inline Vector4( Vector3 xyz, floatInVec w ); + + // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + // + explicit inline Vector4( Vector3 vec ); + + // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + // + explicit inline Vector4( Point3 pnt ); + + // Copy elements from a quaternion into a 4-D vector + // + explicit inline Vector4( Quat quat ); + + // Set all elements of a 4-D vector to the same scalar value + // + explicit inline Vector4( float scalar ); + + // Set all elements of a 4-D vector to the same scalar value (scalar data contained in vector data type) + // + explicit inline Vector4( floatInVec scalar ); + + // Set vector float data in a 4-D vector + // + explicit inline Vector4( vec_float4 vf4 ); + + // Get vector float data from a 4-D vector + // + inline vec_float4 get128( ) const; + + // Assign one 4-D vector to another + // + inline Vector4 & operator =( Vector4 vec ); + + // Set the x, y, and z elements of a 4-D vector + // NOTE: + // This function does not change the w element. + // + inline Vector4 & setXYZ( Vector3 vec ); + + // Get the x, y, and z elements of a 4-D vector + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a 4-D vector + // + inline Vector4 & setX( float x ); + + // Set the y element of a 4-D vector + // + inline Vector4 & setY( float y ); + + // Set the z element of a 4-D vector + // + inline Vector4 & setZ( float z ); + + // Set the w element of a 4-D vector + // + inline Vector4 & setW( float w ); + + // Set the x element of a 4-D vector (scalar data contained in vector data type) + // + inline Vector4 & setX( floatInVec x ); + + // Set the y element of a 4-D vector (scalar data contained in vector data type) + // + inline Vector4 & setY( floatInVec y ); + + // Set the z element of a 4-D vector (scalar data contained in vector data type) + // + inline Vector4 & setZ( floatInVec z ); + + // Set the w element of a 4-D vector (scalar data contained in vector data type) + // + inline Vector4 & setW( floatInVec w ); + + // Get the x element of a 4-D vector + // + inline const floatInVec getX( ) const; + + // Get the y element of a 4-D vector + // + inline const floatInVec getY( ) const; + + // Get the z element of a 4-D vector + // + inline const floatInVec getZ( ) const; + + // Get the w element of a 4-D vector + // + inline const floatInVec getW( ) const; + + // Set an x, y, z, or w element of a 4-D vector by index + // + inline Vector4 & setElem( int idx, float value ); + + // Set an x, y, z, or w element of a 4-D vector by index (scalar data contained in vector data type) + // + inline Vector4 & setElem( int idx, floatInVec value ); + + // Get an x, y, z, or w element of a 4-D vector by index + // + inline const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + inline const floatInVec operator []( int idx ) const; + + // Add two 4-D vectors + // + inline const Vector4 operator +( Vector4 vec ) const; + + // Subtract a 4-D vector from another 4-D vector + // + inline const Vector4 operator -( Vector4 vec ) const; + + // Multiply a 4-D vector by a scalar + // + inline const Vector4 operator *( float scalar ) const; + + // Divide a 4-D vector by a scalar + // + inline const Vector4 operator /( float scalar ) const; + + // Multiply a 4-D vector by a scalar (scalar data contained in vector data type) + // + inline const Vector4 operator *( floatInVec scalar ) const; + + // Divide a 4-D vector by a scalar (scalar data contained in vector data type) + // + inline const Vector4 operator /( floatInVec scalar ) const; + + // Perform compound assignment and addition with a 4-D vector + // + inline Vector4 & operator +=( Vector4 vec ); + + // Perform compound assignment and subtraction by a 4-D vector + // + inline Vector4 & operator -=( Vector4 vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector4 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector4 & operator /=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + inline Vector4 & operator *=( floatInVec scalar ); + + // Perform compound assignment and division by a scalar (scalar data contained in vector data type) + // + inline Vector4 & operator /=( floatInVec scalar ); + + // Negate all elements of a 4-D vector + // + inline const Vector4 operator -( ) const; + + // Construct x axis + // + static inline const Vector4 xAxis( ); + + // Construct y axis + // + static inline const Vector4 yAxis( ); + + // Construct z axis + // + static inline const Vector4 zAxis( ); + + // Construct w axis + // + static inline const Vector4 wAxis( ); + +}; + +// Multiply a 4-D vector by a scalar +// +inline const Vector4 operator *( float scalar, Vector4 vec ); + +// Multiply a 4-D vector by a scalar (scalar data contained in vector data type) +// +inline const Vector4 operator *( floatInVec scalar, Vector4 vec ); + +// Multiply two 4-D vectors per element +// +inline const Vector4 mulPerElem( Vector4 vec0, Vector4 vec1 ); + +// Divide two 4-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector4 divPerElem( Vector4 vec0, Vector4 vec1 ); + +// Compute the reciprocal of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector4 recipPerElem( Vector4 vec ); + +// Compute the square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector4 sqrtPerElem( Vector4 vec ); + +// Compute the reciprocal square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector4 rsqrtPerElem( Vector4 vec ); + +// Compute the absolute value of a 4-D vector per element +// +inline const Vector4 absPerElem( Vector4 vec ); + +// Copy sign from one 4-D vector to another, per element +// +inline const Vector4 copySignPerElem( Vector4 vec0, Vector4 vec1 ); + +// Maximum of two 4-D vectors per element +// +inline const Vector4 maxPerElem( Vector4 vec0, Vector4 vec1 ); + +// Minimum of two 4-D vectors per element +// +inline const Vector4 minPerElem( Vector4 vec0, Vector4 vec1 ); + +// Maximum element of a 4-D vector +// +inline const floatInVec maxElem( Vector4 vec ); + +// Minimum element of a 4-D vector +// +inline const floatInVec minElem( Vector4 vec ); + +// Compute the sum of all elements of a 4-D vector +// +inline const floatInVec sum( Vector4 vec ); + +// Compute the dot product of two 4-D vectors +// +inline const floatInVec dot( Vector4 vec0, Vector4 vec1 ); + +// Compute the square of the length of a 4-D vector +// +inline const floatInVec lengthSqr( Vector4 vec ); + +// Compute the length of a 4-D vector +// +inline const floatInVec length( Vector4 vec ); + +// Normalize a 4-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector4 normalize( Vector4 vec ); + +// Outer product of two 4-D vectors +// +inline const Matrix4 outer( Vector4 vec0, Vector4 vec1 ); + +// Linear interpolation between two 4-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector4 lerp( float t, Vector4 vec0, Vector4 vec1 ); + +// Linear interpolation between two 4-D vectors (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector4 lerp( floatInVec t, Vector4 vec0, Vector4 vec1 ); + +// Spherical linear interpolation between two 4-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector4 slerp( float t, Vector4 unitVec0, Vector4 unitVec1 ); + +// Spherical linear interpolation between two 4-D vectors (scalar data contained in vector data type) +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector4 slerp( floatInVec t, Vector4 unitVec0, Vector4 unitVec1 ); + +// Conditionally select between two 4-D vectors +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +inline const Vector4 select( Vector4 vec0, Vector4 vec1, bool select1 ); + +// Conditionally select between two 4-D vectors (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Vector4 select( Vector4 vec0, Vector4 vec1, boolInVec select1 ); + +// Store four 4-D vectors as half-floats +// +inline void storeHalfFloats( Vector4 vec0, Vector4 vec1, Vector4 vec2, Vector4 vec3, vec_ushort8 * twoQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( Vector4 vec ); + +// Print a 4-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( Vector4 vec, const char * name ); + +#endif + +// A 3-D point in array-of-structures format +// +class Point3 +{ + vec_float4 mVec128; + +public: + // Default constructor; does no initialization + // + inline Point3( ) { }; + + // Construct a 3-D point from x, y, and z elements + // + inline Point3( float x, float y, float z ); + + // Construct a 3-D point from x, y, and z elements (scalar data contained in vector data type) + // + inline Point3( floatInVec x, floatInVec y, floatInVec z ); + + // Copy elements from a 3-D vector into a 3-D point + // + explicit inline Point3( Vector3 vec ); + + // Set all elements of a 3-D point to the same scalar value + // + explicit inline Point3( float scalar ); + + // Set all elements of a 3-D point to the same scalar value (scalar data contained in vector data type) + // + explicit inline Point3( floatInVec scalar ); + + // Set vector float data in a 3-D point + // + explicit inline Point3( vec_float4 vf4 ); + + // Get vector float data from a 3-D point + // + inline vec_float4 get128( ) const; + + // Assign one 3-D point to another + // + inline Point3 & operator =( Point3 pnt ); + + // Set the x element of a 3-D point + // + inline Point3 & setX( float x ); + + // Set the y element of a 3-D point + // + inline Point3 & setY( float y ); + + // Set the z element of a 3-D point + // + inline Point3 & setZ( float z ); + + // Set the x element of a 3-D point (scalar data contained in vector data type) + // + inline Point3 & setX( floatInVec x ); + + // Set the y element of a 3-D point (scalar data contained in vector data type) + // + inline Point3 & setY( floatInVec y ); + + // Set the z element of a 3-D point (scalar data contained in vector data type) + // + inline Point3 & setZ( floatInVec z ); + + // Get the x element of a 3-D point + // + inline const floatInVec getX( ) const; + + // Get the y element of a 3-D point + // + inline const floatInVec getY( ) const; + + // Get the z element of a 3-D point + // + inline const floatInVec getZ( ) const; + + // Set an x, y, or z element of a 3-D point by index + // + inline Point3 & setElem( int idx, float value ); + + // Set an x, y, or z element of a 3-D point by index (scalar data contained in vector data type) + // + inline Point3 & setElem( int idx, floatInVec value ); + + // Get an x, y, or z element of a 3-D point by index + // + inline const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + inline const floatInVec operator []( int idx ) const; + + // Subtract a 3-D point from another 3-D point + // + inline const Vector3 operator -( Point3 pnt ) const; + + // Add a 3-D point to a 3-D vector + // + inline const Point3 operator +( Vector3 vec ) const; + + // Subtract a 3-D vector from a 3-D point + // + inline const Point3 operator -( Vector3 vec ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Point3 & operator +=( Vector3 vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Point3 & operator -=( Vector3 vec ); + +}; + +// Multiply two 3-D points per element +// +inline const Point3 mulPerElem( Point3 pnt0, Point3 pnt1 ); + +// Divide two 3-D points per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Point3 divPerElem( Point3 pnt0, Point3 pnt1 ); + +// Compute the reciprocal of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Point3 recipPerElem( Point3 pnt ); + +// Compute the square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Point3 sqrtPerElem( Point3 pnt ); + +// Compute the reciprocal square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Point3 rsqrtPerElem( Point3 pnt ); + +// Compute the absolute value of a 3-D point per element +// +inline const Point3 absPerElem( Point3 pnt ); + +// Copy sign from one 3-D point to another, per element +// +inline const Point3 copySignPerElem( Point3 pnt0, Point3 pnt1 ); + +// Maximum of two 3-D points per element +// +inline const Point3 maxPerElem( Point3 pnt0, Point3 pnt1 ); + +// Minimum of two 3-D points per element +// +inline const Point3 minPerElem( Point3 pnt0, Point3 pnt1 ); + +// Maximum element of a 3-D point +// +inline const floatInVec maxElem( Point3 pnt ); + +// Minimum element of a 3-D point +// +inline const floatInVec minElem( Point3 pnt ); + +// Compute the sum of all elements of a 3-D point +// +inline const floatInVec sum( Point3 pnt ); + +// Apply uniform scale to a 3-D point +// +inline const Point3 scale( Point3 pnt, float scaleVal ); + +// Apply uniform scale to a 3-D point (scalar data contained in vector data type) +// +inline const Point3 scale( Point3 pnt, floatInVec scaleVal ); + +// Apply non-uniform scale to a 3-D point +// +inline const Point3 scale( Point3 pnt, Vector3 scaleVec ); + +// Scalar projection of a 3-D point on a unit-length 3-D vector +// +inline const floatInVec projection( Point3 pnt, Vector3 unitVec ); + +// Compute the square of the distance of a 3-D point from the coordinate-system origin +// +inline const floatInVec distSqrFromOrigin( Point3 pnt ); + +// Compute the distance of a 3-D point from the coordinate-system origin +// +inline const floatInVec distFromOrigin( Point3 pnt ); + +// Compute the square of the distance between two 3-D points +// +inline const floatInVec distSqr( Point3 pnt0, Point3 pnt1 ); + +// Compute the distance between two 3-D points +// +inline const floatInVec dist( Point3 pnt0, Point3 pnt1 ); + +// Linear interpolation between two 3-D points +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Point3 lerp( float t, Point3 pnt0, Point3 pnt1 ); + +// Linear interpolation between two 3-D points (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Point3 lerp( floatInVec t, Point3 pnt0, Point3 pnt1 ); + +// Conditionally select between two 3-D points +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +inline const Point3 select( Point3 pnt0, Point3 pnt1, bool select1 ); + +// Conditionally select between two 3-D points (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Point3 select( Point3 pnt0, Point3 pnt1, boolInVec select1 ); + +// Store x, y, and z elements of a 3-D point in the first three words of a quadword. +// The value of the fourth word (the word with the highest address) remains unchanged +// +inline void storeXYZ( Point3 pnt, vec_float4 * quad ); + +// Load four three-float 3-D points, stored in three quadwords +// +inline void loadXYZArray( Point3 & pnt0, Point3 & pnt1, Point3 & pnt2, Point3 & pnt3, const vec_float4 * threeQuads ); + +// Store four 3-D points in three quadwords +// +inline void storeXYZArray( Point3 pnt0, Point3 pnt1, Point3 pnt2, Point3 pnt3, vec_float4 * threeQuads ); + +// Store eight 3-D points as half-floats +// +inline void storeHalfFloats( Point3 pnt0, Point3 pnt1, Point3 pnt2, Point3 pnt3, Point3 pnt4, Point3 pnt5, Point3 pnt6, Point3 pnt7, vec_ushort8 * threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D point +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( Point3 pnt ); + +// Print a 3-D point and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( Point3 pnt, const char * name ); + +#endif + +// A quaternion in array-of-structures format +// +class Quat +{ + vec_float4 mVec128; + +public: + // Default constructor; does no initialization + // + inline Quat( ) { }; + + // Construct a quaternion from x, y, z, and w elements + // + inline Quat( float x, float y, float z, float w ); + + // Construct a quaternion from x, y, z, and w elements (scalar data contained in vector data type) + // + inline Quat( floatInVec x, floatInVec y, floatInVec z, floatInVec w ); + + // Construct a quaternion from a 3-D vector and a scalar + // + inline Quat( Vector3 xyz, float w ); + + // Construct a quaternion from a 3-D vector and a scalar (scalar data contained in vector data type) + // + inline Quat( Vector3 xyz, floatInVec w ); + + // Copy elements from a 4-D vector into a quaternion + // + explicit inline Quat( Vector4 vec ); + + // Convert a rotation matrix to a unit-length quaternion + // + explicit inline Quat( const Matrix3 & rotMat ); + + // Set all elements of a quaternion to the same scalar value + // + explicit inline Quat( float scalar ); + + // Set all elements of a quaternion to the same scalar value (scalar data contained in vector data type) + // + explicit inline Quat( floatInVec scalar ); + + // Set vector float data in a quaternion + // + explicit inline Quat( vec_float4 vf4 ); + + // Get vector float data from a quaternion + // + inline vec_float4 get128( ) const; + + // Assign one quaternion to another + // + inline Quat & operator =( Quat quat ); + + // Set the x, y, and z elements of a quaternion + // NOTE: + // This function does not change the w element. + // + inline Quat & setXYZ( Vector3 vec ); + + // Get the x, y, and z elements of a quaternion + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a quaternion + // + inline Quat & setX( float x ); + + // Set the y element of a quaternion + // + inline Quat & setY( float y ); + + // Set the z element of a quaternion + // + inline Quat & setZ( float z ); + + // Set the w element of a quaternion + // + inline Quat & setW( float w ); + + // Set the x element of a quaternion (scalar data contained in vector data type) + // + inline Quat & setX( floatInVec x ); + + // Set the y element of a quaternion (scalar data contained in vector data type) + // + inline Quat & setY( floatInVec y ); + + // Set the z element of a quaternion (scalar data contained in vector data type) + // + inline Quat & setZ( floatInVec z ); + + // Set the w element of a quaternion (scalar data contained in vector data type) + // + inline Quat & setW( floatInVec w ); + + // Get the x element of a quaternion + // + inline const floatInVec getX( ) const; + + // Get the y element of a quaternion + // + inline const floatInVec getY( ) const; + + // Get the z element of a quaternion + // + inline const floatInVec getZ( ) const; + + // Get the w element of a quaternion + // + inline const floatInVec getW( ) const; + + // Set an x, y, z, or w element of a quaternion by index + // + inline Quat & setElem( int idx, float value ); + + // Set an x, y, z, or w element of a quaternion by index (scalar data contained in vector data type) + // + inline Quat & setElem( int idx, floatInVec value ); + + // Get an x, y, z, or w element of a quaternion by index + // + inline const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + inline const floatInVec operator []( int idx ) const; + + // Add two quaternions + // + inline const Quat operator +( Quat quat ) const; + + // Subtract a quaternion from another quaternion + // + inline const Quat operator -( Quat quat ) const; + + // Multiply two quaternions + // + inline const Quat operator *( Quat quat ) const; + + // Multiply a quaternion by a scalar + // + inline const Quat operator *( float scalar ) const; + + // Divide a quaternion by a scalar + // + inline const Quat operator /( float scalar ) const; + + // Multiply a quaternion by a scalar (scalar data contained in vector data type) + // + inline const Quat operator *( floatInVec scalar ) const; + + // Divide a quaternion by a scalar (scalar data contained in vector data type) + // + inline const Quat operator /( floatInVec scalar ) const; + + // Perform compound assignment and addition with a quaternion + // + inline Quat & operator +=( Quat quat ); + + // Perform compound assignment and subtraction by a quaternion + // + inline Quat & operator -=( Quat quat ); + + // Perform compound assignment and multiplication by a quaternion + // + inline Quat & operator *=( Quat quat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Quat & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Quat & operator /=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + inline Quat & operator *=( floatInVec scalar ); + + // Perform compound assignment and division by a scalar (scalar data contained in vector data type) + // + inline Quat & operator /=( floatInVec scalar ); + + // Negate all elements of a quaternion + // + inline const Quat operator -( ) const; + + // Construct an identity quaternion + // + static inline const Quat identity( ); + + // Construct a quaternion to rotate between two unit-length 3-D vectors + // NOTE: + // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + // + static inline const Quat rotation( Vector3 unitVec0, Vector3 unitVec1 ); + + // Construct a quaternion to rotate around a unit-length 3-D vector + // + static inline const Quat rotation( float radians, Vector3 unitVec ); + + // Construct a quaternion to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static inline const Quat rotation( floatInVec radians, Vector3 unitVec ); + + // Construct a quaternion to rotate around the x axis + // + static inline const Quat rotationX( float radians ); + + // Construct a quaternion to rotate around the y axis + // + static inline const Quat rotationY( float radians ); + + // Construct a quaternion to rotate around the z axis + // + static inline const Quat rotationZ( float radians ); + + // Construct a quaternion to rotate around the x axis (scalar data contained in vector data type) + // + static inline const Quat rotationX( floatInVec radians ); + + // Construct a quaternion to rotate around the y axis (scalar data contained in vector data type) + // + static inline const Quat rotationY( floatInVec radians ); + + // Construct a quaternion to rotate around the z axis (scalar data contained in vector data type) + // + static inline const Quat rotationZ( floatInVec radians ); + +}; + +// Multiply a quaternion by a scalar +// +inline const Quat operator *( float scalar, Quat quat ); + +// Multiply a quaternion by a scalar (scalar data contained in vector data type) +// +inline const Quat operator *( floatInVec scalar, Quat quat ); + +// Compute the conjugate of a quaternion +// +inline const Quat conj( Quat quat ); + +// Use a unit-length quaternion to rotate a 3-D vector +// +inline const Vector3 rotate( Quat unitQuat, Vector3 vec ); + +// Compute the dot product of two quaternions +// +inline const floatInVec dot( Quat quat0, Quat quat1 ); + +// Compute the norm of a quaternion +// +inline const floatInVec norm( Quat quat ); + +// Compute the length of a quaternion +// +inline const floatInVec length( Quat quat ); + +// Normalize a quaternion +// NOTE: +// The result is unpredictable when all elements of quat are at or near zero. +// +inline const Quat normalize( Quat quat ); + +// Linear interpolation between two quaternions +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Quat lerp( float t, Quat quat0, Quat quat1 ); + +// Linear interpolation between two quaternions (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Quat lerp( floatInVec t, Quat quat0, Quat quat1 ); + +// Spherical linear interpolation between two quaternions +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +inline const Quat slerp( float t, Quat unitQuat0, Quat unitQuat1 ); + +// Spherical linear interpolation between two quaternions (scalar data contained in vector data type) +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +inline const Quat slerp( floatInVec t, Quat unitQuat0, Quat unitQuat1 ); + +// Spherical quadrangle interpolation +// +inline const Quat squad( float t, Quat unitQuat0, Quat unitQuat1, Quat unitQuat2, Quat unitQuat3 ); + +// Spherical quadrangle interpolation (scalar data contained in vector data type) +// +inline const Quat squad( floatInVec t, Quat unitQuat0, Quat unitQuat1, Quat unitQuat2, Quat unitQuat3 ); + +// Conditionally select between two quaternions +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +inline const Quat select( Quat quat0, Quat quat1, bool select1 ); + +// Conditionally select between two quaternions (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Quat select( Quat quat0, Quat quat1, boolInVec select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a quaternion +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( Quat quat ); + +// Print a quaternion and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( Quat quat, const char * name ); + +#endif + +// A 3x3 matrix in array-of-structures format +// +class Matrix3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + +public: + // Default constructor; does no initialization + // + inline Matrix3( ) { }; + + // Copy a 3x3 matrix + // + inline Matrix3( const Matrix3 & mat ); + + // Construct a 3x3 matrix containing the specified columns + // + inline Matrix3( Vector3 col0, Vector3 col1, Vector3 col2 ); + + // Construct a 3x3 rotation matrix from a unit-length quaternion + // + explicit inline Matrix3( Quat unitQuat ); + + // Set all elements of a 3x3 matrix to the same scalar value + // + explicit inline Matrix3( float scalar ); + + // Set all elements of a 3x3 matrix to the same scalar value (scalar data contained in vector data type) + // + explicit inline Matrix3( floatInVec scalar ); + + // Assign one 3x3 matrix to another + // + inline Matrix3 & operator =( const Matrix3 & mat ); + + // Set column 0 of a 3x3 matrix + // + inline Matrix3 & setCol0( Vector3 col0 ); + + // Set column 1 of a 3x3 matrix + // + inline Matrix3 & setCol1( Vector3 col1 ); + + // Set column 2 of a 3x3 matrix + // + inline Matrix3 & setCol2( Vector3 col2 ); + + // Get column 0 of a 3x3 matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x3 matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x3 matrix + // + inline const Vector3 getCol2( ) const; + + // Set the column of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setCol( int col, Vector3 vec ); + + // Set the row of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setRow( int row, Vector3 vec ); + + // Get the column of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x3 matrix referred to by column and row indices + // + inline Matrix3 & setElem( int col, int row, float val ); + + // Set the element of a 3x3 matrix referred to by column and row indices (scalar data contained in vector data type) + // + inline Matrix3 & setElem( int col, int row, floatInVec val ); + + // Get the element of a 3x3 matrix referred to by column and row indices + // + inline const floatInVec getElem( int col, int row ) const; + + // Add two 3x3 matrices + // + inline const Matrix3 operator +( const Matrix3 & mat ) const; + + // Subtract a 3x3 matrix from another 3x3 matrix + // + inline const Matrix3 operator -( const Matrix3 & mat ) const; + + // Negate all elements of a 3x3 matrix + // + inline const Matrix3 operator -( ) const; + + // Multiply a 3x3 matrix by a scalar + // + inline const Matrix3 operator *( float scalar ) const; + + // Multiply a 3x3 matrix by a scalar (scalar data contained in vector data type) + // + inline const Matrix3 operator *( floatInVec scalar ) const; + + // Multiply a 3x3 matrix by a 3-D vector + // + inline const Vector3 operator *( Vector3 vec ) const; + + // Multiply two 3x3 matrices + // + inline const Matrix3 operator *( const Matrix3 & mat ) const; + + // Perform compound assignment and addition with a 3x3 matrix + // + inline Matrix3 & operator +=( const Matrix3 & mat ); + + // Perform compound assignment and subtraction by a 3x3 matrix + // + inline Matrix3 & operator -=( const Matrix3 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix3 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + inline Matrix3 & operator *=( floatInVec scalar ); + + // Perform compound assignment and multiplication by a 3x3 matrix + // + inline Matrix3 & operator *=( const Matrix3 & mat ); + + // Construct an identity 3x3 matrix + // + static inline const Matrix3 identity( ); + + // Construct a 3x3 matrix to rotate around the x axis + // + static inline const Matrix3 rotationX( float radians ); + + // Construct a 3x3 matrix to rotate around the y axis + // + static inline const Matrix3 rotationY( float radians ); + + // Construct a 3x3 matrix to rotate around the z axis + // + static inline const Matrix3 rotationZ( float radians ); + + // Construct a 3x3 matrix to rotate around the x axis (scalar data contained in vector data type) + // + static inline const Matrix3 rotationX( floatInVec radians ); + + // Construct a 3x3 matrix to rotate around the y axis (scalar data contained in vector data type) + // + static inline const Matrix3 rotationY( floatInVec radians ); + + // Construct a 3x3 matrix to rotate around the z axis (scalar data contained in vector data type) + // + static inline const Matrix3 rotationZ( floatInVec radians ); + + // Construct a 3x3 matrix to rotate around the x, y, and z axes + // + static inline const Matrix3 rotationZYX( Vector3 radiansXYZ ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix3 rotation( float radians, Vector3 unitVec ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static inline const Matrix3 rotation( floatInVec radians, Vector3 unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix3 rotation( Quat unitQuat ); + + // Construct a 3x3 matrix to perform scaling + // + static inline const Matrix3 scale( Vector3 scaleVec ); + +}; +// Multiply a 3x3 matrix by a scalar +// +inline const Matrix3 operator *( float scalar, const Matrix3 & mat ); + +// Multiply a 3x3 matrix by a scalar (scalar data contained in vector data type) +// +inline const Matrix3 operator *( floatInVec scalar, const Matrix3 & mat ); + +// Append (post-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 appendScale( const Matrix3 & mat, Vector3 scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 prependScale( Vector3 scaleVec, const Matrix3 & mat ); + +// Multiply two 3x3 matrices per element +// +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); + +// Compute the absolute value of a 3x3 matrix per element +// +inline const Matrix3 absPerElem( const Matrix3 & mat ); + +// Transpose of a 3x3 matrix +// +inline const Matrix3 transpose( const Matrix3 & mat ); + +// Compute the inverse of a 3x3 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix3 inverse( const Matrix3 & mat ); + +// Determinant of a 3x3 matrix +// +inline const floatInVec determinant( const Matrix3 & mat ); + +// Conditionally select between two 3x3 matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ); + +// Conditionally select between two 3x3 matrices (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, boolInVec select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x3 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat ); + +// Print a 3x3 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat, const char * name ); + +#endif + +// A 4x4 matrix in array-of-structures format +// +class Matrix4 +{ + Vector4 mCol0; + Vector4 mCol1; + Vector4 mCol2; + Vector4 mCol3; + +public: + // Default constructor; does no initialization + // + inline Matrix4( ) { }; + + // Copy a 4x4 matrix + // + inline Matrix4( const Matrix4 & mat ); + + // Construct a 4x4 matrix containing the specified columns + // + inline Matrix4( Vector4 col0, Vector4 col1, Vector4 col2, Vector4 col3 ); + + // Construct a 4x4 matrix from a 3x4 transformation matrix + // + explicit inline Matrix4( const Transform3 & mat ); + + // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + // + inline Matrix4( const Matrix3 & mat, Vector3 translateVec ); + + // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + // + inline Matrix4( Quat unitQuat, Vector3 translateVec ); + + // Set all elements of a 4x4 matrix to the same scalar value + // + explicit inline Matrix4( float scalar ); + + // Set all elements of a 4x4 matrix to the same scalar value (scalar data contained in vector data type) + // + explicit inline Matrix4( floatInVec scalar ); + + // Assign one 4x4 matrix to another + // + inline Matrix4 & operator =( const Matrix4 & mat ); + + // Set the upper-left 3x3 submatrix + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 4x4 matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setTranslation( Vector3 translateVec ); + + // Get the translation component of a 4x4 matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 4x4 matrix + // + inline Matrix4 & setCol0( Vector4 col0 ); + + // Set column 1 of a 4x4 matrix + // + inline Matrix4 & setCol1( Vector4 col1 ); + + // Set column 2 of a 4x4 matrix + // + inline Matrix4 & setCol2( Vector4 col2 ); + + // Set column 3 of a 4x4 matrix + // + inline Matrix4 & setCol3( Vector4 col3 ); + + // Get column 0 of a 4x4 matrix + // + inline const Vector4 getCol0( ) const; + + // Get column 1 of a 4x4 matrix + // + inline const Vector4 getCol1( ) const; + + // Get column 2 of a 4x4 matrix + // + inline const Vector4 getCol2( ) const; + + // Get column 3 of a 4x4 matrix + // + inline const Vector4 getCol3( ) const; + + // Set the column of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setCol( int col, Vector4 vec ); + + // Set the row of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setRow( int row, Vector4 vec ); + + // Get the column of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getCol( int col ) const; + + // Get the row of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector4 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector4 operator []( int col ) const; + + // Set the element of a 4x4 matrix referred to by column and row indices + // + inline Matrix4 & setElem( int col, int row, float val ); + + // Set the element of a 4x4 matrix referred to by column and row indices (scalar data contained in vector data type) + // + inline Matrix4 & setElem( int col, int row, floatInVec val ); + + // Get the element of a 4x4 matrix referred to by column and row indices + // + inline const floatInVec getElem( int col, int row ) const; + + // Add two 4x4 matrices + // + inline const Matrix4 operator +( const Matrix4 & mat ) const; + + // Subtract a 4x4 matrix from another 4x4 matrix + // + inline const Matrix4 operator -( const Matrix4 & mat ) const; + + // Negate all elements of a 4x4 matrix + // + inline const Matrix4 operator -( ) const; + + // Multiply a 4x4 matrix by a scalar + // + inline const Matrix4 operator *( float scalar ) const; + + // Multiply a 4x4 matrix by a scalar (scalar data contained in vector data type) + // + inline const Matrix4 operator *( floatInVec scalar ) const; + + // Multiply a 4x4 matrix by a 4-D vector + // + inline const Vector4 operator *( Vector4 vec ) const; + + // Multiply a 4x4 matrix by a 3-D vector + // + inline const Vector4 operator *( Vector3 vec ) const; + + // Multiply a 4x4 matrix by a 3-D point + // + inline const Vector4 operator *( Point3 pnt ) const; + + // Multiply two 4x4 matrices + // + inline const Matrix4 operator *( const Matrix4 & mat ) const; + + // Multiply a 4x4 matrix by a 3x4 transformation matrix + // + inline const Matrix4 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and addition with a 4x4 matrix + // + inline Matrix4 & operator +=( const Matrix4 & mat ); + + // Perform compound assignment and subtraction by a 4x4 matrix + // + inline Matrix4 & operator -=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix4 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + inline Matrix4 & operator *=( floatInVec scalar ); + + // Perform compound assignment and multiplication by a 4x4 matrix + // + inline Matrix4 & operator *=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Matrix4 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 4x4 matrix + // + static inline const Matrix4 identity( ); + + // Construct a 4x4 matrix to rotate around the x axis + // + static inline const Matrix4 rotationX( float radians ); + + // Construct a 4x4 matrix to rotate around the y axis + // + static inline const Matrix4 rotationY( float radians ); + + // Construct a 4x4 matrix to rotate around the z axis + // + static inline const Matrix4 rotationZ( float radians ); + + // Construct a 4x4 matrix to rotate around the x axis (scalar data contained in vector data type) + // + static inline const Matrix4 rotationX( floatInVec radians ); + + // Construct a 4x4 matrix to rotate around the y axis (scalar data contained in vector data type) + // + static inline const Matrix4 rotationY( floatInVec radians ); + + // Construct a 4x4 matrix to rotate around the z axis (scalar data contained in vector data type) + // + static inline const Matrix4 rotationZ( floatInVec radians ); + + // Construct a 4x4 matrix to rotate around the x, y, and z axes + // + static inline const Matrix4 rotationZYX( Vector3 radiansXYZ ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix4 rotation( float radians, Vector3 unitVec ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static inline const Matrix4 rotation( floatInVec radians, Vector3 unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix4 rotation( Quat unitQuat ); + + // Construct a 4x4 matrix to perform scaling + // + static inline const Matrix4 scale( Vector3 scaleVec ); + + // Construct a 4x4 matrix to perform translation + // + static inline const Matrix4 translation( Vector3 translateVec ); + + // Construct viewing matrix based on eye position, position looked at, and up direction + // + static inline const Matrix4 lookAt( Point3 eyePos, Point3 lookAtPos, Vector3 upVec ); + + // Construct a perspective projection matrix + // + static inline const Matrix4 perspective( float fovyRadians, float aspect, float zNear, float zFar ); + + // Construct a perspective projection matrix based on frustum + // + static inline const Matrix4 frustum( float left, float right, float bottom, float top, float zNear, float zFar ); + + // Construct an orthographic projection matrix + // + static inline const Matrix4 orthographic( float left, float right, float bottom, float top, float zNear, float zFar ); + +}; +// Multiply a 4x4 matrix by a scalar +// +inline const Matrix4 operator *( float scalar, const Matrix4 & mat ); + +// Multiply a 4x4 matrix by a scalar (scalar data contained in vector data type) +// +inline const Matrix4 operator *( floatInVec scalar, const Matrix4 & mat ); + +// Append (post-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 appendScale( const Matrix4 & mat, Vector3 scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 prependScale( Vector3 scaleVec, const Matrix4 & mat ); + +// Multiply two 4x4 matrices per element +// +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); + +// Compute the absolute value of a 4x4 matrix per element +// +inline const Matrix4 absPerElem( const Matrix4 & mat ); + +// Transpose of a 4x4 matrix +// +inline const Matrix4 transpose( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 inverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 affineInverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. +// +inline const Matrix4 orthoInverse( const Matrix4 & mat ); + +// Determinant of a 4x4 matrix +// +inline const floatInVec determinant( const Matrix4 & mat ); + +// Conditionally select between two 4x4 matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ); + +// Conditionally select between two 4x4 matrices (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, boolInVec select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4x4 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat ); + +// Print a 4x4 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat, const char * name ); + +#endif + +// A 3x4 transformation matrix in array-of-structures format +// +class Transform3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + Vector3 mCol3; + +public: + // Default constructor; does no initialization + // + inline Transform3( ) { }; + + // Copy a 3x4 transformation matrix + // + inline Transform3( const Transform3 & tfrm ); + + // Construct a 3x4 transformation matrix containing the specified columns + // + inline Transform3( Vector3 col0, Vector3 col1, Vector3 col2, Vector3 col3 ); + + // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + // + inline Transform3( const Matrix3 & tfrm, Vector3 translateVec ); + + // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + // + inline Transform3( Quat unitQuat, Vector3 translateVec ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value + // + explicit inline Transform3( float scalar ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value (scalar data contained in vector data type) + // + explicit inline Transform3( floatInVec scalar ); + + // Assign one 3x4 transformation matrix to another + // + inline Transform3 & operator =( const Transform3 & tfrm ); + + // Set the upper-left 3x3 submatrix + // + inline Transform3 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // + inline Transform3 & setTranslation( Vector3 translateVec ); + + // Get the translation component of a 3x4 transformation matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 3x4 transformation matrix + // + inline Transform3 & setCol0( Vector3 col0 ); + + // Set column 1 of a 3x4 transformation matrix + // + inline Transform3 & setCol1( Vector3 col1 ); + + // Set column 2 of a 3x4 transformation matrix + // + inline Transform3 & setCol2( Vector3 col2 ); + + // Set column 3 of a 3x4 transformation matrix + // + inline Transform3 & setCol3( Vector3 col3 ); + + // Get column 0 of a 3x4 transformation matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x4 transformation matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x4 transformation matrix + // + inline const Vector3 getCol2( ) const; + + // Get column 3 of a 3x4 transformation matrix + // + inline const Vector3 getCol3( ) const; + + // Set the column of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setCol( int col, Vector3 vec ); + + // Set the row of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setRow( int row, Vector4 vec ); + + // Get the column of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x4 transformation matrix referred to by column and row indices + // + inline Transform3 & setElem( int col, int row, float val ); + + // Set the element of a 3x4 transformation matrix referred to by column and row indices (scalar data contained in vector data type) + // + inline Transform3 & setElem( int col, int row, floatInVec val ); + + // Get the element of a 3x4 transformation matrix referred to by column and row indices + // + inline const floatInVec getElem( int col, int row ) const; + + // Multiply a 3x4 transformation matrix by a 3-D vector + // + inline const Vector3 operator *( Vector3 vec ) const; + + // Multiply a 3x4 transformation matrix by a 3-D point + // + inline const Point3 operator *( Point3 pnt ) const; + + // Multiply two 3x4 transformation matrices + // + inline const Transform3 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Transform3 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 3x4 transformation matrix + // + static inline const Transform3 identity( ); + + // Construct a 3x4 transformation matrix to rotate around the x axis + // + static inline const Transform3 rotationX( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis + // + static inline const Transform3 rotationY( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis + // + static inline const Transform3 rotationZ( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the x axis (scalar data contained in vector data type) + // + static inline const Transform3 rotationX( floatInVec radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis (scalar data contained in vector data type) + // + static inline const Transform3 rotationY( floatInVec radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis (scalar data contained in vector data type) + // + static inline const Transform3 rotationZ( floatInVec radians ); + + // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + // + static inline const Transform3 rotationZYX( Vector3 radiansXYZ ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + // + static inline const Transform3 rotation( float radians, Vector3 unitVec ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static inline const Transform3 rotation( floatInVec radians, Vector3 unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Transform3 rotation( Quat unitQuat ); + + // Construct a 3x4 transformation matrix to perform scaling + // + static inline const Transform3 scale( Vector3 scaleVec ); + + // Construct a 3x4 transformation matrix to perform translation + // + static inline const Transform3 translation( Vector3 translateVec ); + +}; +// Append (post-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 appendScale( const Transform3 & tfrm, Vector3 scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 prependScale( Vector3 scaleVec, const Transform3 & tfrm ); + +// Multiply two 3x4 transformation matrices per element +// +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); + +// Compute the absolute value of a 3x4 transformation matrix per element +// +inline const Transform3 absPerElem( const Transform3 & tfrm ); + +// Inverse of a 3x4 transformation matrix +// NOTE: +// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. +// +inline const Transform3 inverse( const Transform3 & tfrm ); + +// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. +// +inline const Transform3 orthoInverse( const Transform3 & tfrm ); + +// Conditionally select between two 3x4 transformation matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ); + +// Conditionally select between two 3x4 transformation matrices (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, boolInVec select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x4 transformation matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm ); + +// Print a 3x4 transformation matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm, const char * name ); + +#endif + +} // namespace Aos +} // namespace Vectormath + +#include "vec_aos.h" +#include "quat_aos.h" +#include "mat_aos.h" + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/ppu/cpp/vectormath_soa.h b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/vectormath_soa.h new file mode 100644 index 0000000..65932d8 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/ppu/cpp/vectormath_soa.h @@ -0,0 +1,1919 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_SOA_CPP_PPU_H +#define _VECTORMATH_SOA_CPP_PPU_H + +#include +#include +#include "vectormath_aos.h" + +#ifdef _VECTORMATH_DEBUG +#include +#endif + +namespace Vectormath { + +namespace Soa { + +//----------------------------------------------------------------------------- +// Forward Declarations +// + +class Vector3; +class Vector4; +class Point3; +class Quat; +class Matrix3; +class Matrix4; +class Transform3; + +// A set of four 3-D vectors in structure-of-arrays format +// +class Vector3 +{ + typedef vec_float4 vec_float4_t; + vec_float4 mX; + vec_float4 mY; + vec_float4 mZ; + +public: + // Default constructor; does no initialization + // + inline Vector3( ) { }; + + // Copy a 3-D vector + // + inline Vector3( const Vector3 & vec ); + + // Construct a 3-D vector from x, y, and z elements + // + inline Vector3( vec_float4 x, vec_float4 y, vec_float4 z ); + + // Copy elements from a 3-D point into a 3-D vector + // + explicit inline Vector3( const Point3 & pnt ); + + // Set all elements of a 3-D vector to the same scalar value + // + explicit inline Vector3( vec_float4 scalar ); + + // Replicate an AoS 3-D vector + // + inline Vector3( Aos::Vector3 vec ); + + // Insert four AoS 3-D vectors + // + inline Vector3( Aos::Vector3 vec0, Aos::Vector3 vec1, Aos::Vector3 vec2, Aos::Vector3 vec3 ); + + // Extract four AoS 3-D vectors + // + inline void get4Aos( Aos::Vector3 & result0, Aos::Vector3 & result1, Aos::Vector3 & result2, Aos::Vector3 & result3 ) const; + + // Assign one 3-D vector to another + // + inline Vector3 & operator =( const Vector3 & vec ); + + // Set the x element of a 3-D vector + // + inline Vector3 & setX( vec_float4 x ); + + // Set the y element of a 3-D vector + // + inline Vector3 & setY( vec_float4 y ); + + // Set the z element of a 3-D vector + // + inline Vector3 & setZ( vec_float4 z ); + + // Get the x element of a 3-D vector + // + inline vec_float4 getX( ) const; + + // Get the y element of a 3-D vector + // + inline vec_float4 getY( ) const; + + // Get the z element of a 3-D vector + // + inline vec_float4 getZ( ) const; + + // Set an x, y, or z element of a 3-D vector by index + // + inline Vector3 & setElem( int idx, vec_float4 value ); + + // Get an x, y, or z element of a 3-D vector by index + // + inline vec_float4 getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline vec_float4_t & operator []( int idx ); + + // Subscripting operator to get an element + // + inline vec_float4 operator []( int idx ) const; + + // Add two 3-D vectors + // + inline const Vector3 operator +( const Vector3 & vec ) const; + + // Subtract a 3-D vector from another 3-D vector + // + inline const Vector3 operator -( const Vector3 & vec ) const; + + // Add a 3-D vector to a 3-D point + // + inline const Point3 operator +( const Point3 & pnt ) const; + + // Multiply a 3-D vector by a scalar + // + inline const Vector3 operator *( vec_float4 scalar ) const; + + // Divide a 3-D vector by a scalar + // + inline const Vector3 operator /( vec_float4 scalar ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Vector3 & operator +=( const Vector3 & vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Vector3 & operator -=( const Vector3 & vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector3 & operator *=( vec_float4 scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector3 & operator /=( vec_float4 scalar ); + + // Negate all elements of a 3-D vector + // + inline const Vector3 operator -( ) const; + + // Construct x axis + // + static inline const Vector3 xAxis( ); + + // Construct y axis + // + static inline const Vector3 yAxis( ); + + // Construct z axis + // + static inline const Vector3 zAxis( ); + +}; + +// Multiply a 3-D vector by a scalar +// +inline const Vector3 operator *( vec_float4 scalar, const Vector3 & vec ); + +// Multiply two 3-D vectors per element +// +inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Divide two 3-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Compute the reciprocal of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector3 recipPerElem( const Vector3 & vec ); + +// Compute the square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector3 sqrtPerElem( const Vector3 & vec ); + +// Compute the reciprocal square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector3 rsqrtPerElem( const Vector3 & vec ); + +// Compute the absolute value of a 3-D vector per element +// +inline const Vector3 absPerElem( const Vector3 & vec ); + +// Copy sign from one 3-D vector to another, per element +// +inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Maximum of two 3-D vectors per element +// +inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Minimum of two 3-D vectors per element +// +inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Maximum element of a 3-D vector +// +inline vec_float4 maxElem( const Vector3 & vec ); + +// Minimum element of a 3-D vector +// +inline vec_float4 minElem( const Vector3 & vec ); + +// Compute the sum of all elements of a 3-D vector +// +inline vec_float4 sum( const Vector3 & vec ); + +// Compute the dot product of two 3-D vectors +// +inline vec_float4 dot( const Vector3 & vec0, const Vector3 & vec1 ); + +// Compute the square of the length of a 3-D vector +// +inline vec_float4 lengthSqr( const Vector3 & vec ); + +// Compute the length of a 3-D vector +// +inline vec_float4 length( const Vector3 & vec ); + +// Normalize a 3-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector3 normalize( const Vector3 & vec ); + +// Compute cross product of two 3-D vectors +// +inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ); + +// Outer product of two 3-D vectors +// +inline const Matrix3 outer( const Vector3 & vec0, const Vector3 & vec1 ); + +// Pre-multiply a row vector by a 3x3 matrix +// +inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ); + +// Cross-product matrix of a 3-D vector +// +inline const Matrix3 crossMatrix( const Vector3 & vec ); + +// Create cross-product matrix and multiply +// NOTE: +// Faster than separately creating a cross-product matrix and multiplying. +// +inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ); + +// Linear interpolation between two 3-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector3 lerp( vec_float4 t, const Vector3 & vec0, const Vector3 & vec1 ); + +// Spherical linear interpolation between two 3-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector3 slerp( vec_float4 t, const Vector3 & unitVec0, const Vector3 & unitVec1 ); + +// Conditionally select between two 3-D vectors +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, vec_uint4 select1 ); + +// Load four three-float 3-D vectors, stored in three quadwords +// +inline void loadXYZArray( Vector3 & vec, const vec_float4 * threeQuads ); + +// Store four slots of an SoA 3-D vector in three quadwords +// +inline void storeXYZArray( const Vector3 & vec, vec_float4 * threeQuads ); + +// Store eight slots of two SoA 3-D vectors as half-floats +// +inline void storeHalfFloats( const Vector3 & vec0, const Vector3 & vec1, vec_ushort8 * threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector3 & vec ); + +// Print a 3-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector3 & vec, const char * name ); + +#endif + +// A set of four 4-D vectors in structure-of-arrays format +// +class Vector4 +{ + typedef vec_float4 vec_float4_t; + vec_float4 mX; + vec_float4 mY; + vec_float4 mZ; + vec_float4 mW; + +public: + // Default constructor; does no initialization + // + inline Vector4( ) { }; + + // Copy a 4-D vector + // + inline Vector4( const Vector4 & vec ); + + // Construct a 4-D vector from x, y, z, and w elements + // + inline Vector4( vec_float4 x, vec_float4 y, vec_float4 z, vec_float4 w ); + + // Construct a 4-D vector from a 3-D vector and a scalar + // + inline Vector4( const Vector3 & xyz, vec_float4 w ); + + // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + // + explicit inline Vector4( const Vector3 & vec ); + + // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + // + explicit inline Vector4( const Point3 & pnt ); + + // Copy elements from a quaternion into a 4-D vector + // + explicit inline Vector4( const Quat & quat ); + + // Set all elements of a 4-D vector to the same scalar value + // + explicit inline Vector4( vec_float4 scalar ); + + // Replicate an AoS 4-D vector + // + inline Vector4( Aos::Vector4 vec ); + + // Insert four AoS 4-D vectors + // + inline Vector4( Aos::Vector4 vec0, Aos::Vector4 vec1, Aos::Vector4 vec2, Aos::Vector4 vec3 ); + + // Extract four AoS 4-D vectors + // + inline void get4Aos( Aos::Vector4 & result0, Aos::Vector4 & result1, Aos::Vector4 & result2, Aos::Vector4 & result3 ) const; + + // Assign one 4-D vector to another + // + inline Vector4 & operator =( const Vector4 & vec ); + + // Set the x, y, and z elements of a 4-D vector + // NOTE: + // This function does not change the w element. + // + inline Vector4 & setXYZ( const Vector3 & vec ); + + // Get the x, y, and z elements of a 4-D vector + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a 4-D vector + // + inline Vector4 & setX( vec_float4 x ); + + // Set the y element of a 4-D vector + // + inline Vector4 & setY( vec_float4 y ); + + // Set the z element of a 4-D vector + // + inline Vector4 & setZ( vec_float4 z ); + + // Set the w element of a 4-D vector + // + inline Vector4 & setW( vec_float4 w ); + + // Get the x element of a 4-D vector + // + inline vec_float4 getX( ) const; + + // Get the y element of a 4-D vector + // + inline vec_float4 getY( ) const; + + // Get the z element of a 4-D vector + // + inline vec_float4 getZ( ) const; + + // Get the w element of a 4-D vector + // + inline vec_float4 getW( ) const; + + // Set an x, y, z, or w element of a 4-D vector by index + // + inline Vector4 & setElem( int idx, vec_float4 value ); + + // Get an x, y, z, or w element of a 4-D vector by index + // + inline vec_float4 getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline vec_float4_t & operator []( int idx ); + + // Subscripting operator to get an element + // + inline vec_float4 operator []( int idx ) const; + + // Add two 4-D vectors + // + inline const Vector4 operator +( const Vector4 & vec ) const; + + // Subtract a 4-D vector from another 4-D vector + // + inline const Vector4 operator -( const Vector4 & vec ) const; + + // Multiply a 4-D vector by a scalar + // + inline const Vector4 operator *( vec_float4 scalar ) const; + + // Divide a 4-D vector by a scalar + // + inline const Vector4 operator /( vec_float4 scalar ) const; + + // Perform compound assignment and addition with a 4-D vector + // + inline Vector4 & operator +=( const Vector4 & vec ); + + // Perform compound assignment and subtraction by a 4-D vector + // + inline Vector4 & operator -=( const Vector4 & vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector4 & operator *=( vec_float4 scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector4 & operator /=( vec_float4 scalar ); + + // Negate all elements of a 4-D vector + // + inline const Vector4 operator -( ) const; + + // Construct x axis + // + static inline const Vector4 xAxis( ); + + // Construct y axis + // + static inline const Vector4 yAxis( ); + + // Construct z axis + // + static inline const Vector4 zAxis( ); + + // Construct w axis + // + static inline const Vector4 wAxis( ); + +}; + +// Multiply a 4-D vector by a scalar +// +inline const Vector4 operator *( vec_float4 scalar, const Vector4 & vec ); + +// Multiply two 4-D vectors per element +// +inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Divide two 4-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Compute the reciprocal of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector4 recipPerElem( const Vector4 & vec ); + +// Compute the square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector4 sqrtPerElem( const Vector4 & vec ); + +// Compute the reciprocal square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector4 rsqrtPerElem( const Vector4 & vec ); + +// Compute the absolute value of a 4-D vector per element +// +inline const Vector4 absPerElem( const Vector4 & vec ); + +// Copy sign from one 4-D vector to another, per element +// +inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Maximum of two 4-D vectors per element +// +inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Minimum of two 4-D vectors per element +// +inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Maximum element of a 4-D vector +// +inline vec_float4 maxElem( const Vector4 & vec ); + +// Minimum element of a 4-D vector +// +inline vec_float4 minElem( const Vector4 & vec ); + +// Compute the sum of all elements of a 4-D vector +// +inline vec_float4 sum( const Vector4 & vec ); + +// Compute the dot product of two 4-D vectors +// +inline vec_float4 dot( const Vector4 & vec0, const Vector4 & vec1 ); + +// Compute the square of the length of a 4-D vector +// +inline vec_float4 lengthSqr( const Vector4 & vec ); + +// Compute the length of a 4-D vector +// +inline vec_float4 length( const Vector4 & vec ); + +// Normalize a 4-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector4 normalize( const Vector4 & vec ); + +// Outer product of two 4-D vectors +// +inline const Matrix4 outer( const Vector4 & vec0, const Vector4 & vec1 ); + +// Linear interpolation between two 4-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector4 lerp( vec_float4 t, const Vector4 & vec0, const Vector4 & vec1 ); + +// Spherical linear interpolation between two 4-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector4 slerp( vec_float4 t, const Vector4 & unitVec0, const Vector4 & unitVec1 ); + +// Conditionally select between two 4-D vectors +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, vec_uint4 select1 ); + +// Store four slots of an SoA 4-D vector as half-floats +// +inline void storeHalfFloats( const Vector4 & vec, vec_ushort8 * twoQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector4 & vec ); + +// Print a 4-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector4 & vec, const char * name ); + +#endif + +// A set of four 3-D points in structure-of-arrays format +// +class Point3 +{ + typedef vec_float4 vec_float4_t; + vec_float4 mX; + vec_float4 mY; + vec_float4 mZ; + +public: + // Default constructor; does no initialization + // + inline Point3( ) { }; + + // Copy a 3-D point + // + inline Point3( const Point3 & pnt ); + + // Construct a 3-D point from x, y, and z elements + // + inline Point3( vec_float4 x, vec_float4 y, vec_float4 z ); + + // Copy elements from a 3-D vector into a 3-D point + // + explicit inline Point3( const Vector3 & vec ); + + // Set all elements of a 3-D point to the same scalar value + // + explicit inline Point3( vec_float4 scalar ); + + // Replicate an AoS 3-D point + // + inline Point3( Aos::Point3 pnt ); + + // Insert four AoS 3-D points + // + inline Point3( Aos::Point3 pnt0, Aos::Point3 pnt1, Aos::Point3 pnt2, Aos::Point3 pnt3 ); + + // Extract four AoS 3-D points + // + inline void get4Aos( Aos::Point3 & result0, Aos::Point3 & result1, Aos::Point3 & result2, Aos::Point3 & result3 ) const; + + // Assign one 3-D point to another + // + inline Point3 & operator =( const Point3 & pnt ); + + // Set the x element of a 3-D point + // + inline Point3 & setX( vec_float4 x ); + + // Set the y element of a 3-D point + // + inline Point3 & setY( vec_float4 y ); + + // Set the z element of a 3-D point + // + inline Point3 & setZ( vec_float4 z ); + + // Get the x element of a 3-D point + // + inline vec_float4 getX( ) const; + + // Get the y element of a 3-D point + // + inline vec_float4 getY( ) const; + + // Get the z element of a 3-D point + // + inline vec_float4 getZ( ) const; + + // Set an x, y, or z element of a 3-D point by index + // + inline Point3 & setElem( int idx, vec_float4 value ); + + // Get an x, y, or z element of a 3-D point by index + // + inline vec_float4 getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline vec_float4_t & operator []( int idx ); + + // Subscripting operator to get an element + // + inline vec_float4 operator []( int idx ) const; + + // Subtract a 3-D point from another 3-D point + // + inline const Vector3 operator -( const Point3 & pnt ) const; + + // Add a 3-D point to a 3-D vector + // + inline const Point3 operator +( const Vector3 & vec ) const; + + // Subtract a 3-D vector from a 3-D point + // + inline const Point3 operator -( const Vector3 & vec ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Point3 & operator +=( const Vector3 & vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Point3 & operator -=( const Vector3 & vec ); + +}; + +// Multiply two 3-D points per element +// +inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Divide two 3-D points per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Compute the reciprocal of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Point3 recipPerElem( const Point3 & pnt ); + +// Compute the square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Point3 sqrtPerElem( const Point3 & pnt ); + +// Compute the reciprocal square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Point3 rsqrtPerElem( const Point3 & pnt ); + +// Compute the absolute value of a 3-D point per element +// +inline const Point3 absPerElem( const Point3 & pnt ); + +// Copy sign from one 3-D point to another, per element +// +inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Maximum of two 3-D points per element +// +inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Minimum of two 3-D points per element +// +inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Maximum element of a 3-D point +// +inline vec_float4 maxElem( const Point3 & pnt ); + +// Minimum element of a 3-D point +// +inline vec_float4 minElem( const Point3 & pnt ); + +// Compute the sum of all elements of a 3-D point +// +inline vec_float4 sum( const Point3 & pnt ); + +// Apply uniform scale to a 3-D point +// +inline const Point3 scale( const Point3 & pnt, vec_float4 scaleVal ); + +// Apply non-uniform scale to a 3-D point +// +inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ); + +// Scalar projection of a 3-D point on a unit-length 3-D vector +// +inline vec_float4 projection( const Point3 & pnt, const Vector3 & unitVec ); + +// Compute the square of the distance of a 3-D point from the coordinate-system origin +// +inline vec_float4 distSqrFromOrigin( const Point3 & pnt ); + +// Compute the distance of a 3-D point from the coordinate-system origin +// +inline vec_float4 distFromOrigin( const Point3 & pnt ); + +// Compute the square of the distance between two 3-D points +// +inline vec_float4 distSqr( const Point3 & pnt0, const Point3 & pnt1 ); + +// Compute the distance between two 3-D points +// +inline vec_float4 dist( const Point3 & pnt0, const Point3 & pnt1 ); + +// Linear interpolation between two 3-D points +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Point3 lerp( vec_float4 t, const Point3 & pnt0, const Point3 & pnt1 ); + +// Conditionally select between two 3-D points +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, vec_uint4 select1 ); + +// Load four three-float 3-D points, stored in three quadwords +// +inline void loadXYZArray( Point3 & pnt, const vec_float4 * threeQuads ); + +// Store four slots of an SoA 3-D point in three quadwords +// +inline void storeXYZArray( const Point3 & pnt, vec_float4 * threeQuads ); + +// Store eight slots of two SoA 3-D points as half-floats +// +inline void storeHalfFloats( const Point3 & pnt0, const Point3 & pnt1, vec_ushort8 * threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D point +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Point3 & pnt ); + +// Print a 3-D point and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Point3 & pnt, const char * name ); + +#endif + +// A set of four quaternions in structure-of-arrays format +// +class Quat +{ + typedef vec_float4 vec_float4_t; + vec_float4 mX; + vec_float4 mY; + vec_float4 mZ; + vec_float4 mW; + +public: + // Default constructor; does no initialization + // + inline Quat( ) { }; + + // Copy a quaternion + // + inline Quat( const Quat & quat ); + + // Construct a quaternion from x, y, z, and w elements + // + inline Quat( vec_float4 x, vec_float4 y, vec_float4 z, vec_float4 w ); + + // Construct a quaternion from a 3-D vector and a scalar + // + inline Quat( const Vector3 & xyz, vec_float4 w ); + + // Copy elements from a 4-D vector into a quaternion + // + explicit inline Quat( const Vector4 & vec ); + + // Convert a rotation matrix to a unit-length quaternion + // + explicit inline Quat( const Matrix3 & rotMat ); + + // Set all elements of a quaternion to the same scalar value + // + explicit inline Quat( vec_float4 scalar ); + + // Replicate an AoS quaternion + // + inline Quat( Aos::Quat quat ); + + // Insert four AoS quaternions + // + inline Quat( Aos::Quat quat0, Aos::Quat quat1, Aos::Quat quat2, Aos::Quat quat3 ); + + // Extract four AoS quaternions + // + inline void get4Aos( Aos::Quat & result0, Aos::Quat & result1, Aos::Quat & result2, Aos::Quat & result3 ) const; + + // Assign one quaternion to another + // + inline Quat & operator =( const Quat & quat ); + + // Set the x, y, and z elements of a quaternion + // NOTE: + // This function does not change the w element. + // + inline Quat & setXYZ( const Vector3 & vec ); + + // Get the x, y, and z elements of a quaternion + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a quaternion + // + inline Quat & setX( vec_float4 x ); + + // Set the y element of a quaternion + // + inline Quat & setY( vec_float4 y ); + + // Set the z element of a quaternion + // + inline Quat & setZ( vec_float4 z ); + + // Set the w element of a quaternion + // + inline Quat & setW( vec_float4 w ); + + // Get the x element of a quaternion + // + inline vec_float4 getX( ) const; + + // Get the y element of a quaternion + // + inline vec_float4 getY( ) const; + + // Get the z element of a quaternion + // + inline vec_float4 getZ( ) const; + + // Get the w element of a quaternion + // + inline vec_float4 getW( ) const; + + // Set an x, y, z, or w element of a quaternion by index + // + inline Quat & setElem( int idx, vec_float4 value ); + + // Get an x, y, z, or w element of a quaternion by index + // + inline vec_float4 getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline vec_float4_t & operator []( int idx ); + + // Subscripting operator to get an element + // + inline vec_float4 operator []( int idx ) const; + + // Add two quaternions + // + inline const Quat operator +( const Quat & quat ) const; + + // Subtract a quaternion from another quaternion + // + inline const Quat operator -( const Quat & quat ) const; + + // Multiply two quaternions + // + inline const Quat operator *( const Quat & quat ) const; + + // Multiply a quaternion by a scalar + // + inline const Quat operator *( vec_float4 scalar ) const; + + // Divide a quaternion by a scalar + // + inline const Quat operator /( vec_float4 scalar ) const; + + // Perform compound assignment and addition with a quaternion + // + inline Quat & operator +=( const Quat & quat ); + + // Perform compound assignment and subtraction by a quaternion + // + inline Quat & operator -=( const Quat & quat ); + + // Perform compound assignment and multiplication by a quaternion + // + inline Quat & operator *=( const Quat & quat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Quat & operator *=( vec_float4 scalar ); + + // Perform compound assignment and division by a scalar + // + inline Quat & operator /=( vec_float4 scalar ); + + // Negate all elements of a quaternion + // + inline const Quat operator -( ) const; + + // Construct an identity quaternion + // + static inline const Quat identity( ); + + // Construct a quaternion to rotate between two unit-length 3-D vectors + // NOTE: + // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + // + static inline const Quat rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ); + + // Construct a quaternion to rotate around a unit-length 3-D vector + // + static inline const Quat rotation( vec_float4 radians, const Vector3 & unitVec ); + + // Construct a quaternion to rotate around the x axis + // + static inline const Quat rotationX( vec_float4 radians ); + + // Construct a quaternion to rotate around the y axis + // + static inline const Quat rotationY( vec_float4 radians ); + + // Construct a quaternion to rotate around the z axis + // + static inline const Quat rotationZ( vec_float4 radians ); + +}; + +// Multiply a quaternion by a scalar +// +inline const Quat operator *( vec_float4 scalar, const Quat & quat ); + +// Compute the conjugate of a quaternion +// +inline const Quat conj( const Quat & quat ); + +// Use a unit-length quaternion to rotate a 3-D vector +// +inline const Vector3 rotate( const Quat & unitQuat, const Vector3 & vec ); + +// Compute the dot product of two quaternions +// +inline vec_float4 dot( const Quat & quat0, const Quat & quat1 ); + +// Compute the norm of a quaternion +// +inline vec_float4 norm( const Quat & quat ); + +// Compute the length of a quaternion +// +inline vec_float4 length( const Quat & quat ); + +// Normalize a quaternion +// NOTE: +// The result is unpredictable when all elements of quat are at or near zero. +// +inline const Quat normalize( const Quat & quat ); + +// Linear interpolation between two quaternions +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Quat lerp( vec_float4 t, const Quat & quat0, const Quat & quat1 ); + +// Spherical linear interpolation between two quaternions +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +inline const Quat slerp( vec_float4 t, const Quat & unitQuat0, const Quat & unitQuat1 ); + +// Spherical quadrangle interpolation +// +inline const Quat squad( vec_float4 t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ); + +// Conditionally select between two quaternions +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Quat select( const Quat & quat0, const Quat & quat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a quaternion +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Quat & quat ); + +// Print a quaternion and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Quat & quat, const char * name ); + +#endif + +// A set of four 3x3 matrices in structure-of-arrays format +// +class Matrix3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + +public: + // Default constructor; does no initialization + // + inline Matrix3( ) { }; + + // Copy a 3x3 matrix + // + inline Matrix3( const Matrix3 & mat ); + + // Construct a 3x3 matrix containing the specified columns + // + inline Matrix3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2 ); + + // Construct a 3x3 rotation matrix from a unit-length quaternion + // + explicit inline Matrix3( const Quat & unitQuat ); + + // Set all elements of a 3x3 matrix to the same scalar value + // + explicit inline Matrix3( vec_float4 scalar ); + + // Replicate an AoS 3x3 matrix + // + inline Matrix3( const Aos::Matrix3 & mat ); + + // Insert four AoS 3x3 matrices + // + inline Matrix3( const Aos::Matrix3 & mat0, const Aos::Matrix3 & mat1, const Aos::Matrix3 & mat2, const Aos::Matrix3 & mat3 ); + + // Extract four AoS 3x3 matrices + // + inline void get4Aos( Aos::Matrix3 & result0, Aos::Matrix3 & result1, Aos::Matrix3 & result2, Aos::Matrix3 & result3 ) const; + + // Assign one 3x3 matrix to another + // + inline Matrix3 & operator =( const Matrix3 & mat ); + + // Set column 0 of a 3x3 matrix + // + inline Matrix3 & setCol0( const Vector3 & col0 ); + + // Set column 1 of a 3x3 matrix + // + inline Matrix3 & setCol1( const Vector3 & col1 ); + + // Set column 2 of a 3x3 matrix + // + inline Matrix3 & setCol2( const Vector3 & col2 ); + + // Get column 0 of a 3x3 matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x3 matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x3 matrix + // + inline const Vector3 getCol2( ) const; + + // Set the column of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setCol( int col, const Vector3 & vec ); + + // Set the row of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setRow( int row, const Vector3 & vec ); + + // Get the column of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x3 matrix referred to by column and row indices + // + inline Matrix3 & setElem( int col, int row, vec_float4 val ); + + // Get the element of a 3x3 matrix referred to by column and row indices + // + inline vec_float4 getElem( int col, int row ) const; + + // Add two 3x3 matrices + // + inline const Matrix3 operator +( const Matrix3 & mat ) const; + + // Subtract a 3x3 matrix from another 3x3 matrix + // + inline const Matrix3 operator -( const Matrix3 & mat ) const; + + // Negate all elements of a 3x3 matrix + // + inline const Matrix3 operator -( ) const; + + // Multiply a 3x3 matrix by a scalar + // + inline const Matrix3 operator *( vec_float4 scalar ) const; + + // Multiply a 3x3 matrix by a 3-D vector + // + inline const Vector3 operator *( const Vector3 & vec ) const; + + // Multiply two 3x3 matrices + // + inline const Matrix3 operator *( const Matrix3 & mat ) const; + + // Perform compound assignment and addition with a 3x3 matrix + // + inline Matrix3 & operator +=( const Matrix3 & mat ); + + // Perform compound assignment and subtraction by a 3x3 matrix + // + inline Matrix3 & operator -=( const Matrix3 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix3 & operator *=( vec_float4 scalar ); + + // Perform compound assignment and multiplication by a 3x3 matrix + // + inline Matrix3 & operator *=( const Matrix3 & mat ); + + // Construct an identity 3x3 matrix + // + static inline const Matrix3 identity( ); + + // Construct a 3x3 matrix to rotate around the x axis + // + static inline const Matrix3 rotationX( vec_float4 radians ); + + // Construct a 3x3 matrix to rotate around the y axis + // + static inline const Matrix3 rotationY( vec_float4 radians ); + + // Construct a 3x3 matrix to rotate around the z axis + // + static inline const Matrix3 rotationZ( vec_float4 radians ); + + // Construct a 3x3 matrix to rotate around the x, y, and z axes + // + static inline const Matrix3 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix3 rotation( vec_float4 radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix3 rotation( const Quat & unitQuat ); + + // Construct a 3x3 matrix to perform scaling + // + static inline const Matrix3 scale( const Vector3 & scaleVec ); + +}; +// Multiply a 3x3 matrix by a scalar +// +inline const Matrix3 operator *( vec_float4 scalar, const Matrix3 & mat ); + +// Append (post-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ); + +// Multiply two 3x3 matrices per element +// +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); + +// Compute the absolute value of a 3x3 matrix per element +// +inline const Matrix3 absPerElem( const Matrix3 & mat ); + +// Transpose of a 3x3 matrix +// +inline const Matrix3 transpose( const Matrix3 & mat ); + +// Compute the inverse of a 3x3 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix3 inverse( const Matrix3 & mat ); + +// Determinant of a 3x3 matrix +// +inline vec_float4 determinant( const Matrix3 & mat ); + +// Conditionally select between two 3x3 matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x3 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat ); + +// Print a 3x3 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat, const char * name ); + +#endif + +// A set of four 4x4 matrices in structure-of-arrays format +// +class Matrix4 +{ + Vector4 mCol0; + Vector4 mCol1; + Vector4 mCol2; + Vector4 mCol3; + +public: + // Default constructor; does no initialization + // + inline Matrix4( ) { }; + + // Copy a 4x4 matrix + // + inline Matrix4( const Matrix4 & mat ); + + // Construct a 4x4 matrix containing the specified columns + // + inline Matrix4( const Vector4 & col0, const Vector4 & col1, const Vector4 & col2, const Vector4 & col3 ); + + // Construct a 4x4 matrix from a 3x4 transformation matrix + // + explicit inline Matrix4( const Transform3 & mat ); + + // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + // + inline Matrix4( const Matrix3 & mat, const Vector3 & translateVec ); + + // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + // + inline Matrix4( const Quat & unitQuat, const Vector3 & translateVec ); + + // Set all elements of a 4x4 matrix to the same scalar value + // + explicit inline Matrix4( vec_float4 scalar ); + + // Replicate an AoS 4x4 matrix + // + inline Matrix4( const Aos::Matrix4 & mat ); + + // Insert four AoS 4x4 matrices + // + inline Matrix4( const Aos::Matrix4 & mat0, const Aos::Matrix4 & mat1, const Aos::Matrix4 & mat2, const Aos::Matrix4 & mat3 ); + + // Extract four AoS 4x4 matrices + // + inline void get4Aos( Aos::Matrix4 & result0, Aos::Matrix4 & result1, Aos::Matrix4 & result2, Aos::Matrix4 & result3 ) const; + + // Assign one 4x4 matrix to another + // + inline Matrix4 & operator =( const Matrix4 & mat ); + + // Set the upper-left 3x3 submatrix + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 4x4 matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setTranslation( const Vector3 & translateVec ); + + // Get the translation component of a 4x4 matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 4x4 matrix + // + inline Matrix4 & setCol0( const Vector4 & col0 ); + + // Set column 1 of a 4x4 matrix + // + inline Matrix4 & setCol1( const Vector4 & col1 ); + + // Set column 2 of a 4x4 matrix + // + inline Matrix4 & setCol2( const Vector4 & col2 ); + + // Set column 3 of a 4x4 matrix + // + inline Matrix4 & setCol3( const Vector4 & col3 ); + + // Get column 0 of a 4x4 matrix + // + inline const Vector4 getCol0( ) const; + + // Get column 1 of a 4x4 matrix + // + inline const Vector4 getCol1( ) const; + + // Get column 2 of a 4x4 matrix + // + inline const Vector4 getCol2( ) const; + + // Get column 3 of a 4x4 matrix + // + inline const Vector4 getCol3( ) const; + + // Set the column of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setCol( int col, const Vector4 & vec ); + + // Set the row of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setRow( int row, const Vector4 & vec ); + + // Get the column of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getCol( int col ) const; + + // Get the row of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector4 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector4 operator []( int col ) const; + + // Set the element of a 4x4 matrix referred to by column and row indices + // + inline Matrix4 & setElem( int col, int row, vec_float4 val ); + + // Get the element of a 4x4 matrix referred to by column and row indices + // + inline vec_float4 getElem( int col, int row ) const; + + // Add two 4x4 matrices + // + inline const Matrix4 operator +( const Matrix4 & mat ) const; + + // Subtract a 4x4 matrix from another 4x4 matrix + // + inline const Matrix4 operator -( const Matrix4 & mat ) const; + + // Negate all elements of a 4x4 matrix + // + inline const Matrix4 operator -( ) const; + + // Multiply a 4x4 matrix by a scalar + // + inline const Matrix4 operator *( vec_float4 scalar ) const; + + // Multiply a 4x4 matrix by a 4-D vector + // + inline const Vector4 operator *( const Vector4 & vec ) const; + + // Multiply a 4x4 matrix by a 3-D vector + // + inline const Vector4 operator *( const Vector3 & vec ) const; + + // Multiply a 4x4 matrix by a 3-D point + // + inline const Vector4 operator *( const Point3 & pnt ) const; + + // Multiply two 4x4 matrices + // + inline const Matrix4 operator *( const Matrix4 & mat ) const; + + // Multiply a 4x4 matrix by a 3x4 transformation matrix + // + inline const Matrix4 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and addition with a 4x4 matrix + // + inline Matrix4 & operator +=( const Matrix4 & mat ); + + // Perform compound assignment and subtraction by a 4x4 matrix + // + inline Matrix4 & operator -=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix4 & operator *=( vec_float4 scalar ); + + // Perform compound assignment and multiplication by a 4x4 matrix + // + inline Matrix4 & operator *=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Matrix4 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 4x4 matrix + // + static inline const Matrix4 identity( ); + + // Construct a 4x4 matrix to rotate around the x axis + // + static inline const Matrix4 rotationX( vec_float4 radians ); + + // Construct a 4x4 matrix to rotate around the y axis + // + static inline const Matrix4 rotationY( vec_float4 radians ); + + // Construct a 4x4 matrix to rotate around the z axis + // + static inline const Matrix4 rotationZ( vec_float4 radians ); + + // Construct a 4x4 matrix to rotate around the x, y, and z axes + // + static inline const Matrix4 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix4 rotation( vec_float4 radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix4 rotation( const Quat & unitQuat ); + + // Construct a 4x4 matrix to perform scaling + // + static inline const Matrix4 scale( const Vector3 & scaleVec ); + + // Construct a 4x4 matrix to perform translation + // + static inline const Matrix4 translation( const Vector3 & translateVec ); + + // Construct viewing matrix based on eye position, position looked at, and up direction + // + static inline const Matrix4 lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ); + + // Construct a perspective projection matrix + // + static inline const Matrix4 perspective( vec_float4 fovyRadians, vec_float4 aspect, vec_float4 zNear, vec_float4 zFar ); + + // Construct a perspective projection matrix based on frustum + // + static inline const Matrix4 frustum( vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ); + + // Construct an orthographic projection matrix + // + static inline const Matrix4 orthographic( vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ); + +}; +// Multiply a 4x4 matrix by a scalar +// +inline const Matrix4 operator *( vec_float4 scalar, const Matrix4 & mat ); + +// Append (post-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ); + +// Multiply two 4x4 matrices per element +// +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); + +// Compute the absolute value of a 4x4 matrix per element +// +inline const Matrix4 absPerElem( const Matrix4 & mat ); + +// Transpose of a 4x4 matrix +// +inline const Matrix4 transpose( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 inverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 affineInverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. +// +inline const Matrix4 orthoInverse( const Matrix4 & mat ); + +// Determinant of a 4x4 matrix +// +inline vec_float4 determinant( const Matrix4 & mat ); + +// Conditionally select between two 4x4 matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4x4 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat ); + +// Print a 4x4 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat, const char * name ); + +#endif + +// A set of four 3x4 transformation matrices in structure-of-arrays format +// +class Transform3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + Vector3 mCol3; + +public: + // Default constructor; does no initialization + // + inline Transform3( ) { }; + + // Copy a 3x4 transformation matrix + // + inline Transform3( const Transform3 & tfrm ); + + // Construct a 3x4 transformation matrix containing the specified columns + // + inline Transform3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2, const Vector3 & col3 ); + + // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + // + inline Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ); + + // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + // + inline Transform3( const Quat & unitQuat, const Vector3 & translateVec ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value + // + explicit inline Transform3( vec_float4 scalar ); + + // Replicate an AoS 3x4 transformation matrix + // + inline Transform3( const Aos::Transform3 & tfrm ); + + // Insert four AoS 3x4 transformation matrices + // + inline Transform3( const Aos::Transform3 & tfrm0, const Aos::Transform3 & tfrm1, const Aos::Transform3 & tfrm2, const Aos::Transform3 & tfrm3 ); + + // Extract four AoS 3x4 transformation matrices + // + inline void get4Aos( Aos::Transform3 & result0, Aos::Transform3 & result1, Aos::Transform3 & result2, Aos::Transform3 & result3 ) const; + + // Assign one 3x4 transformation matrix to another + // + inline Transform3 & operator =( const Transform3 & tfrm ); + + // Set the upper-left 3x3 submatrix + // + inline Transform3 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // + inline Transform3 & setTranslation( const Vector3 & translateVec ); + + // Get the translation component of a 3x4 transformation matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 3x4 transformation matrix + // + inline Transform3 & setCol0( const Vector3 & col0 ); + + // Set column 1 of a 3x4 transformation matrix + // + inline Transform3 & setCol1( const Vector3 & col1 ); + + // Set column 2 of a 3x4 transformation matrix + // + inline Transform3 & setCol2( const Vector3 & col2 ); + + // Set column 3 of a 3x4 transformation matrix + // + inline Transform3 & setCol3( const Vector3 & col3 ); + + // Get column 0 of a 3x4 transformation matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x4 transformation matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x4 transformation matrix + // + inline const Vector3 getCol2( ) const; + + // Get column 3 of a 3x4 transformation matrix + // + inline const Vector3 getCol3( ) const; + + // Set the column of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setCol( int col, const Vector3 & vec ); + + // Set the row of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setRow( int row, const Vector4 & vec ); + + // Get the column of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x4 transformation matrix referred to by column and row indices + // + inline Transform3 & setElem( int col, int row, vec_float4 val ); + + // Get the element of a 3x4 transformation matrix referred to by column and row indices + // + inline vec_float4 getElem( int col, int row ) const; + + // Multiply a 3x4 transformation matrix by a 3-D vector + // + inline const Vector3 operator *( const Vector3 & vec ) const; + + // Multiply a 3x4 transformation matrix by a 3-D point + // + inline const Point3 operator *( const Point3 & pnt ) const; + + // Multiply two 3x4 transformation matrices + // + inline const Transform3 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Transform3 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 3x4 transformation matrix + // + static inline const Transform3 identity( ); + + // Construct a 3x4 transformation matrix to rotate around the x axis + // + static inline const Transform3 rotationX( vec_float4 radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis + // + static inline const Transform3 rotationY( vec_float4 radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis + // + static inline const Transform3 rotationZ( vec_float4 radians ); + + // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + // + static inline const Transform3 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + // + static inline const Transform3 rotation( vec_float4 radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Transform3 rotation( const Quat & unitQuat ); + + // Construct a 3x4 transformation matrix to perform scaling + // + static inline const Transform3 scale( const Vector3 & scaleVec ); + + // Construct a 3x4 transformation matrix to perform translation + // + static inline const Transform3 translation( const Vector3 & translateVec ); + +}; +// Append (post-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ); + +// Multiply two 3x4 transformation matrices per element +// +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); + +// Compute the absolute value of a 3x4 transformation matrix per element +// +inline const Transform3 absPerElem( const Transform3 & tfrm ); + +// Inverse of a 3x4 transformation matrix +// NOTE: +// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. +// +inline const Transform3 inverse( const Transform3 & tfrm ); + +// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. +// +inline const Transform3 orthoInverse( const Transform3 & tfrm ); + +// Conditionally select between two 3x4 transformation matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x4 transformation matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm ); + +// Print a 3x4 transformation matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm, const char * name ); + +#endif + +} // namespace Soa +} // namespace Vectormath + +#include "vec_soa.h" +#include "quat_soa.h" +#include "mat_soa.h" + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/scalar/c/mat_aos.h b/Extras/vectormathlibrary/include/vectormath/scalar/c/mat_aos.h new file mode 100644 index 0000000..4e0d6ee --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/scalar/c/mat_aos.h @@ -0,0 +1,1452 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_AOS_C_H +#define _VECTORMATH_MAT_AOS_C_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + */ +#define _VECTORMATH_PI_OVER_2 1.570796327f + +/*----------------------------------------------------------------------------- + * Definitions + */ +static inline void vmathM3Copy( VmathMatrix3 *result, const VmathMatrix3 *mat ) +{ + vmathV3Copy( &result->col0, &mat->col0 ); + vmathV3Copy( &result->col1, &mat->col1 ); + vmathV3Copy( &result->col2, &mat->col2 ); +} + +static inline void vmathM3MakeFromScalar( VmathMatrix3 *result, float scalar ) +{ + vmathV3MakeFromScalar( &result->col0, scalar ); + vmathV3MakeFromScalar( &result->col1, scalar ); + vmathV3MakeFromScalar( &result->col2, scalar ); +} + +static inline void vmathM3MakeFromQ( VmathMatrix3 *result, const VmathQuat *unitQuat ) +{ + float qx, qy, qz, qw, qx2, qy2, qz2, qxqx2, qyqy2, qzqz2, qxqy2, qyqz2, qzqw2, qxqz2, qyqw2, qxqw2; + qx = unitQuat->x; + qy = unitQuat->y; + qz = unitQuat->z; + qw = unitQuat->w; + qx2 = ( qx + qx ); + qy2 = ( qy + qy ); + qz2 = ( qz + qz ); + qxqx2 = ( qx * qx2 ); + qxqy2 = ( qx * qy2 ); + qxqz2 = ( qx * qz2 ); + qxqw2 = ( qw * qx2 ); + qyqy2 = ( qy * qy2 ); + qyqz2 = ( qy * qz2 ); + qyqw2 = ( qw * qy2 ); + qzqz2 = ( qz * qz2 ); + qzqw2 = ( qw * qz2 ); + vmathV3MakeFromElems( &result->col0, ( ( 1.0f - qyqy2 ) - qzqz2 ), ( qxqy2 + qzqw2 ), ( qxqz2 - qyqw2 ) ); + vmathV3MakeFromElems( &result->col1, ( qxqy2 - qzqw2 ), ( ( 1.0f - qxqx2 ) - qzqz2 ), ( qyqz2 + qxqw2 ) ); + vmathV3MakeFromElems( &result->col2, ( qxqz2 + qyqw2 ), ( qyqz2 - qxqw2 ), ( ( 1.0f - qxqx2 ) - qyqy2 ) ); +} + +static inline void vmathM3MakeFromCols( VmathMatrix3 *result, const VmathVector3 *_col0, const VmathVector3 *_col1, const VmathVector3 *_col2 ) +{ + vmathV3Copy( &result->col0, _col0 ); + vmathV3Copy( &result->col1, _col1 ); + vmathV3Copy( &result->col2, _col2 ); +} + +static inline void vmathM3SetCol0( VmathMatrix3 *result, const VmathVector3 *_col0 ) +{ + vmathV3Copy( &result->col0, _col0 ); +} + +static inline void vmathM3SetCol1( VmathMatrix3 *result, const VmathVector3 *_col1 ) +{ + vmathV3Copy( &result->col1, _col1 ); +} + +static inline void vmathM3SetCol2( VmathMatrix3 *result, const VmathVector3 *_col2 ) +{ + vmathV3Copy( &result->col2, _col2 ); +} + +static inline void vmathM3SetCol( VmathMatrix3 *result, int col, const VmathVector3 *vec ) +{ + vmathV3Copy( (&result->col0 + col), vec ); +} + +static inline void vmathM3SetRow( VmathMatrix3 *result, int row, const VmathVector3 *vec ) +{ + vmathV3SetElem( &result->col0, row, vmathV3GetElem( vec, 0 ) ); + vmathV3SetElem( &result->col1, row, vmathV3GetElem( vec, 1 ) ); + vmathV3SetElem( &result->col2, row, vmathV3GetElem( vec, 2 ) ); +} + +static inline void vmathM3SetElem( VmathMatrix3 *result, int col, int row, float val ) +{ + VmathVector3 tmpV3_0; + vmathM3GetCol( &tmpV3_0, result, col ); + vmathV3SetElem( &tmpV3_0, row, val ); + vmathM3SetCol( result, col, &tmpV3_0 ); +} + +static inline float vmathM3GetElem( const VmathMatrix3 *mat, int col, int row ) +{ + VmathVector3 tmpV3_0; + vmathM3GetCol( &tmpV3_0, mat, col ); + return vmathV3GetElem( &tmpV3_0, row ); +} + +static inline void vmathM3GetCol0( VmathVector3 *result, const VmathMatrix3 *mat ) +{ + vmathV3Copy( result, &mat->col0 ); +} + +static inline void vmathM3GetCol1( VmathVector3 *result, const VmathMatrix3 *mat ) +{ + vmathV3Copy( result, &mat->col1 ); +} + +static inline void vmathM3GetCol2( VmathVector3 *result, const VmathMatrix3 *mat ) +{ + vmathV3Copy( result, &mat->col2 ); +} + +static inline void vmathM3GetCol( VmathVector3 *result, const VmathMatrix3 *mat, int col ) +{ + vmathV3Copy( result, (&mat->col0 + col) ); +} + +static inline void vmathM3GetRow( VmathVector3 *result, const VmathMatrix3 *mat, int row ) +{ + vmathV3MakeFromElems( result, vmathV3GetElem( &mat->col0, row ), vmathV3GetElem( &mat->col1, row ), vmathV3GetElem( &mat->col2, row ) ); +} + +static inline void vmathM3Transpose( VmathMatrix3 *result, const VmathMatrix3 *mat ) +{ + VmathMatrix3 tmpResult; + vmathV3MakeFromElems( &tmpResult.col0, mat->col0.x, mat->col1.x, mat->col2.x ); + vmathV3MakeFromElems( &tmpResult.col1, mat->col0.y, mat->col1.y, mat->col2.y ); + vmathV3MakeFromElems( &tmpResult.col2, mat->col0.z, mat->col1.z, mat->col2.z ); + vmathM3Copy( result, &tmpResult ); +} + +static inline void vmathM3Inverse( VmathMatrix3 *result, const VmathMatrix3 *mat ) +{ + VmathVector3 tmp0, tmp1, tmp2; + float detinv; + vmathV3Cross( &tmp0, &mat->col1, &mat->col2 ); + vmathV3Cross( &tmp1, &mat->col2, &mat->col0 ); + vmathV3Cross( &tmp2, &mat->col0, &mat->col1 ); + detinv = ( 1.0f / vmathV3Dot( &mat->col2, &tmp2 ) ); + vmathV3MakeFromElems( &result->col0, ( tmp0.x * detinv ), ( tmp1.x * detinv ), ( tmp2.x * detinv ) ); + vmathV3MakeFromElems( &result->col1, ( tmp0.y * detinv ), ( tmp1.y * detinv ), ( tmp2.y * detinv ) ); + vmathV3MakeFromElems( &result->col2, ( tmp0.z * detinv ), ( tmp1.z * detinv ), ( tmp2.z * detinv ) ); +} + +static inline float vmathM3Determinant( const VmathMatrix3 *mat ) +{ + VmathVector3 tmpV3_0; + vmathV3Cross( &tmpV3_0, &mat->col0, &mat->col1 ); + return vmathV3Dot( &mat->col2, &tmpV3_0 ); +} + +static inline void vmathM3Add( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ) +{ + vmathV3Add( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV3Add( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV3Add( &result->col2, &mat0->col2, &mat1->col2 ); +} + +static inline void vmathM3Sub( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ) +{ + vmathV3Sub( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV3Sub( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV3Sub( &result->col2, &mat0->col2, &mat1->col2 ); +} + +static inline void vmathM3Neg( VmathMatrix3 *result, const VmathMatrix3 *mat ) +{ + vmathV3Neg( &result->col0, &mat->col0 ); + vmathV3Neg( &result->col1, &mat->col1 ); + vmathV3Neg( &result->col2, &mat->col2 ); +} + +static inline void vmathM3AbsPerElem( VmathMatrix3 *result, const VmathMatrix3 *mat ) +{ + vmathV3AbsPerElem( &result->col0, &mat->col0 ); + vmathV3AbsPerElem( &result->col1, &mat->col1 ); + vmathV3AbsPerElem( &result->col2, &mat->col2 ); +} + +static inline void vmathM3ScalarMul( VmathMatrix3 *result, const VmathMatrix3 *mat, float scalar ) +{ + vmathV3ScalarMul( &result->col0, &mat->col0, scalar ); + vmathV3ScalarMul( &result->col1, &mat->col1, scalar ); + vmathV3ScalarMul( &result->col2, &mat->col2, scalar ); +} + +static inline void vmathM3MulV3( VmathVector3 *result, const VmathMatrix3 *mat, const VmathVector3 *vec ) +{ + float tmpX, tmpY, tmpZ; + tmpX = ( ( ( mat->col0.x * vec->x ) + ( mat->col1.x * vec->y ) ) + ( mat->col2.x * vec->z ) ); + tmpY = ( ( ( mat->col0.y * vec->x ) + ( mat->col1.y * vec->y ) ) + ( mat->col2.y * vec->z ) ); + tmpZ = ( ( ( mat->col0.z * vec->x ) + ( mat->col1.z * vec->y ) ) + ( mat->col2.z * vec->z ) ); + vmathV3MakeFromElems( result, tmpX, tmpY, tmpZ ); +} + +static inline void vmathM3Mul( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ) +{ + VmathMatrix3 tmpResult; + vmathM3MulV3( &tmpResult.col0, mat0, &mat1->col0 ); + vmathM3MulV3( &tmpResult.col1, mat0, &mat1->col1 ); + vmathM3MulV3( &tmpResult.col2, mat0, &mat1->col2 ); + vmathM3Copy( result, &tmpResult ); +} + +static inline void vmathM3MulPerElem( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ) +{ + vmathV3MulPerElem( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV3MulPerElem( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV3MulPerElem( &result->col2, &mat0->col2, &mat1->col2 ); +} + +static inline void vmathM3MakeIdentity( VmathMatrix3 *result ) +{ + vmathV3MakeXAxis( &result->col0 ); + vmathV3MakeYAxis( &result->col1 ); + vmathV3MakeZAxis( &result->col2 ); +} + +static inline void vmathM3MakeRotationX( VmathMatrix3 *result, float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + vmathV3MakeXAxis( &result->col0 ); + vmathV3MakeFromElems( &result->col1, 0.0f, c, s ); + vmathV3MakeFromElems( &result->col2, 0.0f, -s, c ); +} + +static inline void vmathM3MakeRotationY( VmathMatrix3 *result, float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + vmathV3MakeFromElems( &result->col0, c, 0.0f, -s ); + vmathV3MakeYAxis( &result->col1 ); + vmathV3MakeFromElems( &result->col2, s, 0.0f, c ); +} + +static inline void vmathM3MakeRotationZ( VmathMatrix3 *result, float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + vmathV3MakeFromElems( &result->col0, c, s, 0.0f ); + vmathV3MakeFromElems( &result->col1, -s, c, 0.0f ); + vmathV3MakeZAxis( &result->col2 ); +} + +static inline void vmathM3MakeRotationZYX( VmathMatrix3 *result, const VmathVector3 *radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ->x ); + cX = cosf( radiansXYZ->x ); + sY = sinf( radiansXYZ->y ); + cY = cosf( radiansXYZ->y ); + sZ = sinf( radiansXYZ->z ); + cZ = cosf( radiansXYZ->z ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + vmathV3MakeFromElems( &result->col0, ( cZ * cY ), ( sZ * cY ), -sY ); + vmathV3MakeFromElems( &result->col1, ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ); + vmathV3MakeFromElems( &result->col2, ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ); +} + +static inline void vmathM3MakeRotationAxis( VmathMatrix3 *result, float radians, const VmathVector3 *unitVec ) +{ + float x, y, z, s, c, oneMinusC, xy, yz, zx; + s = sinf( radians ); + c = cosf( radians ); + x = unitVec->x; + y = unitVec->y; + z = unitVec->z; + xy = ( x * y ); + yz = ( y * z ); + zx = ( z * x ); + oneMinusC = ( 1.0f - c ); + vmathV3MakeFromElems( &result->col0, ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ) ); + vmathV3MakeFromElems( &result->col1, ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ) ); + vmathV3MakeFromElems( &result->col2, ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ) ); +} + +static inline void vmathM3MakeRotationQ( VmathMatrix3 *result, const VmathQuat *unitQuat ) +{ + vmathM3MakeFromQ( result, unitQuat ); +} + +static inline void vmathM3MakeScale( VmathMatrix3 *result, const VmathVector3 *scaleVec ) +{ + vmathV3MakeFromElems( &result->col0, scaleVec->x, 0.0f, 0.0f ); + vmathV3MakeFromElems( &result->col1, 0.0f, scaleVec->y, 0.0f ); + vmathV3MakeFromElems( &result->col2, 0.0f, 0.0f, scaleVec->z ); +} + +static inline void vmathM3AppendScale( VmathMatrix3 *result, const VmathMatrix3 *mat, const VmathVector3 *scaleVec ) +{ + vmathV3ScalarMul( &result->col0, &mat->col0, vmathV3GetX( scaleVec ) ); + vmathV3ScalarMul( &result->col1, &mat->col1, vmathV3GetY( scaleVec ) ); + vmathV3ScalarMul( &result->col2, &mat->col2, vmathV3GetZ( scaleVec ) ); +} + +static inline void vmathM3PrependScale( VmathMatrix3 *result, const VmathVector3 *scaleVec, const VmathMatrix3 *mat ) +{ + vmathV3MulPerElem( &result->col0, &mat->col0, scaleVec ); + vmathV3MulPerElem( &result->col1, &mat->col1, scaleVec ); + vmathV3MulPerElem( &result->col2, &mat->col2, scaleVec ); +} + +static inline void vmathM3Select( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1, unsigned int select1 ) +{ + vmathV3Select( &result->col0, &mat0->col0, &mat1->col0, select1 ); + vmathV3Select( &result->col1, &mat0->col1, &mat1->col1, select1 ); + vmathV3Select( &result->col2, &mat0->col2, &mat1->col2, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathM3Print( const VmathMatrix3 *mat ) +{ + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2; + vmathM3GetRow( &tmpV3_0, mat, 0 ); + vmathV3Print( &tmpV3_0 ); + vmathM3GetRow( &tmpV3_1, mat, 1 ); + vmathV3Print( &tmpV3_1 ); + vmathM3GetRow( &tmpV3_2, mat, 2 ); + vmathV3Print( &tmpV3_2 ); +} + +static inline void vmathM3Prints( const VmathMatrix3 *mat, const char *name ) +{ + printf("%s:\n", name); + vmathM3Print( mat ); +} + +#endif + +static inline void vmathM4Copy( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Copy( &result->col0, &mat->col0 ); + vmathV4Copy( &result->col1, &mat->col1 ); + vmathV4Copy( &result->col2, &mat->col2 ); + vmathV4Copy( &result->col3, &mat->col3 ); +} + +static inline void vmathM4MakeFromScalar( VmathMatrix4 *result, float scalar ) +{ + vmathV4MakeFromScalar( &result->col0, scalar ); + vmathV4MakeFromScalar( &result->col1, scalar ); + vmathV4MakeFromScalar( &result->col2, scalar ); + vmathV4MakeFromScalar( &result->col3, scalar ); +} + +static inline void vmathM4MakeFromT3( VmathMatrix4 *result, const VmathTransform3 *mat ) +{ + vmathV4MakeFromV3Scalar( &result->col0, &mat->col0, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col1, &mat->col1, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col2, &mat->col2, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col3, &mat->col3, 1.0f ); +} + +static inline void vmathM4MakeFromCols( VmathMatrix4 *result, const VmathVector4 *_col0, const VmathVector4 *_col1, const VmathVector4 *_col2, const VmathVector4 *_col3 ) +{ + vmathV4Copy( &result->col0, _col0 ); + vmathV4Copy( &result->col1, _col1 ); + vmathV4Copy( &result->col2, _col2 ); + vmathV4Copy( &result->col3, _col3 ); +} + +static inline void vmathM4MakeFromM3V3( VmathMatrix4 *result, const VmathMatrix3 *mat, const VmathVector3 *translateVec ) +{ + vmathV4MakeFromV3Scalar( &result->col0, &mat->col0, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col1, &mat->col1, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col2, &mat->col2, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col3, translateVec, 1.0f ); +} + +static inline void vmathM4MakeFromQV3( VmathMatrix4 *result, const VmathQuat *unitQuat, const VmathVector3 *translateVec ) +{ + VmathMatrix3 mat; + vmathM3MakeFromQ( &mat, unitQuat ); + vmathV4MakeFromV3Scalar( &result->col0, &mat.col0, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col1, &mat.col1, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col2, &mat.col2, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col3, translateVec, 1.0f ); +} + +static inline void vmathM4SetCol0( VmathMatrix4 *result, const VmathVector4 *_col0 ) +{ + vmathV4Copy( &result->col0, _col0 ); +} + +static inline void vmathM4SetCol1( VmathMatrix4 *result, const VmathVector4 *_col1 ) +{ + vmathV4Copy( &result->col1, _col1 ); +} + +static inline void vmathM4SetCol2( VmathMatrix4 *result, const VmathVector4 *_col2 ) +{ + vmathV4Copy( &result->col2, _col2 ); +} + +static inline void vmathM4SetCol3( VmathMatrix4 *result, const VmathVector4 *_col3 ) +{ + vmathV4Copy( &result->col3, _col3 ); +} + +static inline void vmathM4SetCol( VmathMatrix4 *result, int col, const VmathVector4 *vec ) +{ + vmathV4Copy( (&result->col0 + col), vec ); +} + +static inline void vmathM4SetRow( VmathMatrix4 *result, int row, const VmathVector4 *vec ) +{ + vmathV4SetElem( &result->col0, row, vmathV4GetElem( vec, 0 ) ); + vmathV4SetElem( &result->col1, row, vmathV4GetElem( vec, 1 ) ); + vmathV4SetElem( &result->col2, row, vmathV4GetElem( vec, 2 ) ); + vmathV4SetElem( &result->col3, row, vmathV4GetElem( vec, 3 ) ); +} + +static inline void vmathM4SetElem( VmathMatrix4 *result, int col, int row, float val ) +{ + VmathVector4 tmpV3_0; + vmathM4GetCol( &tmpV3_0, result, col ); + vmathV4SetElem( &tmpV3_0, row, val ); + vmathM4SetCol( result, col, &tmpV3_0 ); +} + +static inline float vmathM4GetElem( const VmathMatrix4 *mat, int col, int row ) +{ + VmathVector4 tmpV4_0; + vmathM4GetCol( &tmpV4_0, mat, col ); + return vmathV4GetElem( &tmpV4_0, row ); +} + +static inline void vmathM4GetCol0( VmathVector4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Copy( result, &mat->col0 ); +} + +static inline void vmathM4GetCol1( VmathVector4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Copy( result, &mat->col1 ); +} + +static inline void vmathM4GetCol2( VmathVector4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Copy( result, &mat->col2 ); +} + +static inline void vmathM4GetCol3( VmathVector4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Copy( result, &mat->col3 ); +} + +static inline void vmathM4GetCol( VmathVector4 *result, const VmathMatrix4 *mat, int col ) +{ + vmathV4Copy( result, (&mat->col0 + col) ); +} + +static inline void vmathM4GetRow( VmathVector4 *result, const VmathMatrix4 *mat, int row ) +{ + vmathV4MakeFromElems( result, vmathV4GetElem( &mat->col0, row ), vmathV4GetElem( &mat->col1, row ), vmathV4GetElem( &mat->col2, row ), vmathV4GetElem( &mat->col3, row ) ); +} + +static inline void vmathM4Transpose( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + VmathMatrix4 tmpResult; + vmathV4MakeFromElems( &tmpResult.col0, mat->col0.x, mat->col1.x, mat->col2.x, mat->col3.x ); + vmathV4MakeFromElems( &tmpResult.col1, mat->col0.y, mat->col1.y, mat->col2.y, mat->col3.y ); + vmathV4MakeFromElems( &tmpResult.col2, mat->col0.z, mat->col1.z, mat->col2.z, mat->col3.z ); + vmathV4MakeFromElems( &tmpResult.col3, mat->col0.w, mat->col1.w, mat->col2.w, mat->col3.w ); + vmathM4Copy( result, &tmpResult ); +} + +static inline void vmathM4Inverse( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + VmathVector4 res0, res1, res2, res3; + float mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, detInv; + mA = mat->col0.x; + mB = mat->col0.y; + mC = mat->col0.z; + mD = mat->col0.w; + mE = mat->col1.x; + mF = mat->col1.y; + mG = mat->col1.z; + mH = mat->col1.w; + mI = mat->col2.x; + mJ = mat->col2.y; + mK = mat->col2.z; + mL = mat->col2.w; + mM = mat->col3.x; + mN = mat->col3.y; + mO = mat->col3.z; + mP = mat->col3.w; + tmp0 = ( ( mK * mD ) - ( mC * mL ) ); + tmp1 = ( ( mO * mH ) - ( mG * mP ) ); + tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); + tmp3 = ( ( mF * mO ) - ( mN * mG ) ); + tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); + tmp5 = ( ( mN * mH ) - ( mF * mP ) ); + vmathV4SetX( &res0, ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ) ); + vmathV4SetY( &res0, ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ) ); + vmathV4SetZ( &res0, ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ) ); + vmathV4SetW( &res0, ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ) ); + detInv = ( 1.0f / ( ( ( ( mA * res0.x ) + ( mE * res0.y ) ) + ( mI * res0.z ) ) + ( mM * res0.w ) ) ); + vmathV4SetX( &res1, ( mI * tmp1 ) ); + vmathV4SetY( &res1, ( mM * tmp0 ) ); + vmathV4SetZ( &res1, ( mA * tmp1 ) ); + vmathV4SetW( &res1, ( mE * tmp0 ) ); + vmathV4SetX( &res3, ( mI * tmp3 ) ); + vmathV4SetY( &res3, ( mM * tmp2 ) ); + vmathV4SetZ( &res3, ( mA * tmp3 ) ); + vmathV4SetW( &res3, ( mE * tmp2 ) ); + vmathV4SetX( &res2, ( mI * tmp5 ) ); + vmathV4SetY( &res2, ( mM * tmp4 ) ); + vmathV4SetZ( &res2, ( mA * tmp5 ) ); + vmathV4SetW( &res2, ( mE * tmp4 ) ); + tmp0 = ( ( mI * mB ) - ( mA * mJ ) ); + tmp1 = ( ( mM * mF ) - ( mE * mN ) ); + tmp2 = ( ( mI * mD ) - ( mA * mL ) ); + tmp3 = ( ( mM * mH ) - ( mE * mP ) ); + tmp4 = ( ( mI * mC ) - ( mA * mK ) ); + tmp5 = ( ( mM * mG ) - ( mE * mO ) ); + vmathV4SetX( &res2, ( ( ( mL * tmp1 ) - ( mJ * tmp3 ) ) + res2.x ) ); + vmathV4SetY( &res2, ( ( ( mP * tmp0 ) - ( mN * tmp2 ) ) + res2.y ) ); + vmathV4SetZ( &res2, ( ( ( mB * tmp3 ) - ( mD * tmp1 ) ) - res2.z ) ); + vmathV4SetW( &res2, ( ( ( mF * tmp2 ) - ( mH * tmp0 ) ) - res2.w ) ); + vmathV4SetX( &res3, ( ( ( mJ * tmp5 ) - ( mK * tmp1 ) ) + res3.x ) ); + vmathV4SetY( &res3, ( ( ( mN * tmp4 ) - ( mO * tmp0 ) ) + res3.y ) ); + vmathV4SetZ( &res3, ( ( ( mC * tmp1 ) - ( mB * tmp5 ) ) - res3.z ) ); + vmathV4SetW( &res3, ( ( ( mG * tmp0 ) - ( mF * tmp4 ) ) - res3.w ) ); + vmathV4SetX( &res1, ( ( ( mK * tmp3 ) - ( mL * tmp5 ) ) - res1.x ) ); + vmathV4SetY( &res1, ( ( ( mO * tmp2 ) - ( mP * tmp4 ) ) - res1.y ) ); + vmathV4SetZ( &res1, ( ( ( mD * tmp5 ) - ( mC * tmp3 ) ) + res1.z ) ); + vmathV4SetW( &res1, ( ( ( mH * tmp4 ) - ( mG * tmp2 ) ) + res1.w ) ); + vmathV4ScalarMul( &result->col0, &res0, detInv ); + vmathV4ScalarMul( &result->col1, &res1, detInv ); + vmathV4ScalarMul( &result->col2, &res2, detInv ); + vmathV4ScalarMul( &result->col3, &res3, detInv ); +} + +static inline void vmathM4AffineInverse( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + VmathTransform3 affineMat, tmpT3_0; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + vmathV4GetXYZ( &tmpV3_0, &mat->col0 ); + vmathT3SetCol0( &affineMat, &tmpV3_0 ); + vmathV4GetXYZ( &tmpV3_1, &mat->col1 ); + vmathT3SetCol1( &affineMat, &tmpV3_1 ); + vmathV4GetXYZ( &tmpV3_2, &mat->col2 ); + vmathT3SetCol2( &affineMat, &tmpV3_2 ); + vmathV4GetXYZ( &tmpV3_3, &mat->col3 ); + vmathT3SetCol3( &affineMat, &tmpV3_3 ); + vmathT3Inverse( &tmpT3_0, &affineMat ); + vmathM4MakeFromT3( result, &tmpT3_0 ); +} + +static inline void vmathM4OrthoInverse( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + VmathTransform3 affineMat, tmpT3_0; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + vmathV4GetXYZ( &tmpV3_0, &mat->col0 ); + vmathT3SetCol0( &affineMat, &tmpV3_0 ); + vmathV4GetXYZ( &tmpV3_1, &mat->col1 ); + vmathT3SetCol1( &affineMat, &tmpV3_1 ); + vmathV4GetXYZ( &tmpV3_2, &mat->col2 ); + vmathT3SetCol2( &affineMat, &tmpV3_2 ); + vmathV4GetXYZ( &tmpV3_3, &mat->col3 ); + vmathT3SetCol3( &affineMat, &tmpV3_3 ); + vmathT3OrthoInverse( &tmpT3_0, &affineMat ); + vmathM4MakeFromT3( result, &tmpT3_0 ); +} + +static inline float vmathM4Determinant( const VmathMatrix4 *mat ) +{ + float dx, dy, dz, dw, mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + mA = mat->col0.x; + mB = mat->col0.y; + mC = mat->col0.z; + mD = mat->col0.w; + mE = mat->col1.x; + mF = mat->col1.y; + mG = mat->col1.z; + mH = mat->col1.w; + mI = mat->col2.x; + mJ = mat->col2.y; + mK = mat->col2.z; + mL = mat->col2.w; + mM = mat->col3.x; + mN = mat->col3.y; + mO = mat->col3.z; + mP = mat->col3.w; + tmp0 = ( ( mK * mD ) - ( mC * mL ) ); + tmp1 = ( ( mO * mH ) - ( mG * mP ) ); + tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); + tmp3 = ( ( mF * mO ) - ( mN * mG ) ); + tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); + tmp5 = ( ( mN * mH ) - ( mF * mP ) ); + dx = ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ); + dy = ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ); + dz = ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ); + dw = ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ); + return ( ( ( ( mA * dx ) + ( mE * dy ) ) + ( mI * dz ) ) + ( mM * dw ) ); +} + +static inline void vmathM4Add( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ) +{ + vmathV4Add( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV4Add( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV4Add( &result->col2, &mat0->col2, &mat1->col2 ); + vmathV4Add( &result->col3, &mat0->col3, &mat1->col3 ); +} + +static inline void vmathM4Sub( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ) +{ + vmathV4Sub( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV4Sub( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV4Sub( &result->col2, &mat0->col2, &mat1->col2 ); + vmathV4Sub( &result->col3, &mat0->col3, &mat1->col3 ); +} + +static inline void vmathM4Neg( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Neg( &result->col0, &mat->col0 ); + vmathV4Neg( &result->col1, &mat->col1 ); + vmathV4Neg( &result->col2, &mat->col2 ); + vmathV4Neg( &result->col3, &mat->col3 ); +} + +static inline void vmathM4AbsPerElem( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + vmathV4AbsPerElem( &result->col0, &mat->col0 ); + vmathV4AbsPerElem( &result->col1, &mat->col1 ); + vmathV4AbsPerElem( &result->col2, &mat->col2 ); + vmathV4AbsPerElem( &result->col3, &mat->col3 ); +} + +static inline void vmathM4ScalarMul( VmathMatrix4 *result, const VmathMatrix4 *mat, float scalar ) +{ + vmathV4ScalarMul( &result->col0, &mat->col0, scalar ); + vmathV4ScalarMul( &result->col1, &mat->col1, scalar ); + vmathV4ScalarMul( &result->col2, &mat->col2, scalar ); + vmathV4ScalarMul( &result->col3, &mat->col3, scalar ); +} + +static inline void vmathM4MulV4( VmathVector4 *result, const VmathMatrix4 *mat, const VmathVector4 *vec ) +{ + float tmpX, tmpY, tmpZ, tmpW; + tmpX = ( ( ( ( mat->col0.x * vec->x ) + ( mat->col1.x * vec->y ) ) + ( mat->col2.x * vec->z ) ) + ( mat->col3.x * vec->w ) ); + tmpY = ( ( ( ( mat->col0.y * vec->x ) + ( mat->col1.y * vec->y ) ) + ( mat->col2.y * vec->z ) ) + ( mat->col3.y * vec->w ) ); + tmpZ = ( ( ( ( mat->col0.z * vec->x ) + ( mat->col1.z * vec->y ) ) + ( mat->col2.z * vec->z ) ) + ( mat->col3.z * vec->w ) ); + tmpW = ( ( ( ( mat->col0.w * vec->x ) + ( mat->col1.w * vec->y ) ) + ( mat->col2.w * vec->z ) ) + ( mat->col3.w * vec->w ) ); + vmathV4MakeFromElems( result, tmpX, tmpY, tmpZ, tmpW ); +} + +static inline void vmathM4MulV3( VmathVector4 *result, const VmathMatrix4 *mat, const VmathVector3 *vec ) +{ + result->x = ( ( ( mat->col0.x * vec->x ) + ( mat->col1.x * vec->y ) ) + ( mat->col2.x * vec->z ) ); + result->y = ( ( ( mat->col0.y * vec->x ) + ( mat->col1.y * vec->y ) ) + ( mat->col2.y * vec->z ) ); + result->z = ( ( ( mat->col0.z * vec->x ) + ( mat->col1.z * vec->y ) ) + ( mat->col2.z * vec->z ) ); + result->w = ( ( ( mat->col0.w * vec->x ) + ( mat->col1.w * vec->y ) ) + ( mat->col2.w * vec->z ) ); +} + +static inline void vmathM4MulP3( VmathVector4 *result, const VmathMatrix4 *mat, const VmathPoint3 *pnt ) +{ + result->x = ( ( ( ( mat->col0.x * pnt->x ) + ( mat->col1.x * pnt->y ) ) + ( mat->col2.x * pnt->z ) ) + mat->col3.x ); + result->y = ( ( ( ( mat->col0.y * pnt->x ) + ( mat->col1.y * pnt->y ) ) + ( mat->col2.y * pnt->z ) ) + mat->col3.y ); + result->z = ( ( ( ( mat->col0.z * pnt->x ) + ( mat->col1.z * pnt->y ) ) + ( mat->col2.z * pnt->z ) ) + mat->col3.z ); + result->w = ( ( ( ( mat->col0.w * pnt->x ) + ( mat->col1.w * pnt->y ) ) + ( mat->col2.w * pnt->z ) ) + mat->col3.w ); +} + +static inline void vmathM4Mul( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ) +{ + VmathMatrix4 tmpResult; + vmathM4MulV4( &tmpResult.col0, mat0, &mat1->col0 ); + vmathM4MulV4( &tmpResult.col1, mat0, &mat1->col1 ); + vmathM4MulV4( &tmpResult.col2, mat0, &mat1->col2 ); + vmathM4MulV4( &tmpResult.col3, mat0, &mat1->col3 ); + vmathM4Copy( result, &tmpResult ); +} + +static inline void vmathM4MulT3( VmathMatrix4 *result, const VmathMatrix4 *mat, const VmathTransform3 *tfrm1 ) +{ + VmathMatrix4 tmpResult; + VmathPoint3 tmpP3_0; + vmathM4MulV3( &tmpResult.col0, mat, &tfrm1->col0 ); + vmathM4MulV3( &tmpResult.col1, mat, &tfrm1->col1 ); + vmathM4MulV3( &tmpResult.col2, mat, &tfrm1->col2 ); + vmathP3MakeFromV3( &tmpP3_0, &tfrm1->col3 ); + vmathM4MulP3( &tmpResult.col3, mat, &tmpP3_0 ); + vmathM4Copy( result, &tmpResult ); +} + +static inline void vmathM4MulPerElem( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ) +{ + vmathV4MulPerElem( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV4MulPerElem( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV4MulPerElem( &result->col2, &mat0->col2, &mat1->col2 ); + vmathV4MulPerElem( &result->col3, &mat0->col3, &mat1->col3 ); +} + +static inline void vmathM4MakeIdentity( VmathMatrix4 *result ) +{ + vmathV4MakeXAxis( &result->col0 ); + vmathV4MakeYAxis( &result->col1 ); + vmathV4MakeZAxis( &result->col2 ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4SetUpper3x3( VmathMatrix4 *result, const VmathMatrix3 *mat3 ) +{ + vmathV4SetXYZ( &result->col0, &mat3->col0 ); + vmathV4SetXYZ( &result->col1, &mat3->col1 ); + vmathV4SetXYZ( &result->col2, &mat3->col2 ); +} + +static inline void vmathM4GetUpper3x3( VmathMatrix3 *result, const VmathMatrix4 *mat ) +{ + vmathV4GetXYZ( &result->col0, &mat->col0 ); + vmathV4GetXYZ( &result->col1, &mat->col1 ); + vmathV4GetXYZ( &result->col2, &mat->col2 ); +} + +static inline void vmathM4SetTranslation( VmathMatrix4 *result, const VmathVector3 *translateVec ) +{ + vmathV4SetXYZ( &result->col3, translateVec ); +} + +static inline void vmathM4GetTranslation( VmathVector3 *result, const VmathMatrix4 *mat ) +{ + vmathV4GetXYZ( result, &mat->col3 ); +} + +static inline void vmathM4MakeRotationX( VmathMatrix4 *result, float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + vmathV4MakeXAxis( &result->col0 ); + vmathV4MakeFromElems( &result->col1, 0.0f, c, s, 0.0f ); + vmathV4MakeFromElems( &result->col2, 0.0f, -s, c, 0.0f ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4MakeRotationY( VmathMatrix4 *result, float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + vmathV4MakeFromElems( &result->col0, c, 0.0f, -s, 0.0f ); + vmathV4MakeYAxis( &result->col1 ); + vmathV4MakeFromElems( &result->col2, s, 0.0f, c, 0.0f ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4MakeRotationZ( VmathMatrix4 *result, float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + vmathV4MakeFromElems( &result->col0, c, s, 0.0f, 0.0f ); + vmathV4MakeFromElems( &result->col1, -s, c, 0.0f, 0.0f ); + vmathV4MakeZAxis( &result->col2 ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4MakeRotationZYX( VmathMatrix4 *result, const VmathVector3 *radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ->x ); + cX = cosf( radiansXYZ->x ); + sY = sinf( radiansXYZ->y ); + cY = cosf( radiansXYZ->y ); + sZ = sinf( radiansXYZ->z ); + cZ = cosf( radiansXYZ->z ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + vmathV4MakeFromElems( &result->col0, ( cZ * cY ), ( sZ * cY ), -sY, 0.0f ); + vmathV4MakeFromElems( &result->col1, ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ), 0.0f ); + vmathV4MakeFromElems( &result->col2, ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ), 0.0f ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4MakeRotationAxis( VmathMatrix4 *result, float radians, const VmathVector3 *unitVec ) +{ + float x, y, z, s, c, oneMinusC, xy, yz, zx; + s = sinf( radians ); + c = cosf( radians ); + x = unitVec->x; + y = unitVec->y; + z = unitVec->z; + xy = ( x * y ); + yz = ( y * z ); + zx = ( z * x ); + oneMinusC = ( 1.0f - c ); + vmathV4MakeFromElems( &result->col0, ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ), 0.0f ); + vmathV4MakeFromElems( &result->col1, ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ), 0.0f ); + vmathV4MakeFromElems( &result->col2, ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ), 0.0f ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4MakeRotationQ( VmathMatrix4 *result, const VmathQuat *unitQuat ) +{ + VmathTransform3 tmpT3_0; + vmathT3MakeRotationQ( &tmpT3_0, unitQuat ); + vmathM4MakeFromT3( result, &tmpT3_0 ); +} + +static inline void vmathM4MakeScale( VmathMatrix4 *result, const VmathVector3 *scaleVec ) +{ + vmathV4MakeFromElems( &result->col0, scaleVec->x, 0.0f, 0.0f, 0.0f ); + vmathV4MakeFromElems( &result->col1, 0.0f, scaleVec->y, 0.0f, 0.0f ); + vmathV4MakeFromElems( &result->col2, 0.0f, 0.0f, scaleVec->z, 0.0f ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4AppendScale( VmathMatrix4 *result, const VmathMatrix4 *mat, const VmathVector3 *scaleVec ) +{ + vmathV4ScalarMul( &result->col0, &mat->col0, vmathV3GetX( scaleVec ) ); + vmathV4ScalarMul( &result->col1, &mat->col1, vmathV3GetY( scaleVec ) ); + vmathV4ScalarMul( &result->col2, &mat->col2, vmathV3GetZ( scaleVec ) ); + vmathV4Copy( &result->col3, &mat->col3 ); +} + +static inline void vmathM4PrependScale( VmathMatrix4 *result, const VmathVector3 *scaleVec, const VmathMatrix4 *mat ) +{ + VmathVector4 scale4; + vmathV4MakeFromV3Scalar( &scale4, scaleVec, 1.0f ); + vmathV4MulPerElem( &result->col0, &mat->col0, &scale4 ); + vmathV4MulPerElem( &result->col1, &mat->col1, &scale4 ); + vmathV4MulPerElem( &result->col2, &mat->col2, &scale4 ); + vmathV4MulPerElem( &result->col3, &mat->col3, &scale4 ); +} + +static inline void vmathM4MakeTranslation( VmathMatrix4 *result, const VmathVector3 *translateVec ) +{ + vmathV4MakeXAxis( &result->col0 ); + vmathV4MakeYAxis( &result->col1 ); + vmathV4MakeZAxis( &result->col2 ); + vmathV4MakeFromV3Scalar( &result->col3, translateVec, 1.0f ); +} + +static inline void vmathM4MakeLookAt( VmathMatrix4 *result, const VmathPoint3 *eyePos, const VmathPoint3 *lookAtPos, const VmathVector3 *upVec ) +{ + VmathMatrix4 m4EyeFrame; + VmathVector3 v3X, v3Y, v3Z, tmpV3_0, tmpV3_1; + VmathVector4 tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3; + vmathV3Normalize( &v3Y, upVec ); + vmathP3Sub( &tmpV3_0, eyePos, lookAtPos ); + vmathV3Normalize( &v3Z, &tmpV3_0 ); + vmathV3Cross( &tmpV3_1, &v3Y, &v3Z ); + vmathV3Normalize( &v3X, &tmpV3_1 ); + vmathV3Cross( &v3Y, &v3Z, &v3X ); + vmathV4MakeFromV3( &tmpV4_0, &v3X ); + vmathV4MakeFromV3( &tmpV4_1, &v3Y ); + vmathV4MakeFromV3( &tmpV4_2, &v3Z ); + vmathV4MakeFromP3( &tmpV4_3, eyePos ); + vmathM4MakeFromCols( &m4EyeFrame, &tmpV4_0, &tmpV4_1, &tmpV4_2, &tmpV4_3 ); + vmathM4OrthoInverse( result, &m4EyeFrame ); +} + +static inline void vmathM4MakePerspective( VmathMatrix4 *result, float fovyRadians, float aspect, float zNear, float zFar ) +{ + float f, rangeInv; + f = tanf( ( (float)( _VECTORMATH_PI_OVER_2 ) - ( 0.5f * fovyRadians ) ) ); + rangeInv = ( 1.0f / ( zNear - zFar ) ); + vmathV4MakeFromElems( &result->col0, ( f / aspect ), 0.0f, 0.0f, 0.0f ); + vmathV4MakeFromElems( &result->col1, 0.0f, f, 0.0f, 0.0f ); + vmathV4MakeFromElems( &result->col2, 0.0f, 0.0f, ( ( zNear + zFar ) * rangeInv ), -1.0f ); + vmathV4MakeFromElems( &result->col3, 0.0f, 0.0f, ( ( ( zNear * zFar ) * rangeInv ) * 2.0f ), 0.0f ); +} + +static inline void vmathM4MakeFrustum( VmathMatrix4 *result, float left, float right, float bottom, float top, float zNear, float zFar ) +{ + float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf, n2; + sum_rl = ( right + left ); + sum_tb = ( top + bottom ); + sum_nf = ( zNear + zFar ); + inv_rl = ( 1.0f / ( right - left ) ); + inv_tb = ( 1.0f / ( top - bottom ) ); + inv_nf = ( 1.0f / ( zNear - zFar ) ); + n2 = ( zNear + zNear ); + vmathV4MakeFromElems( &result->col0, ( n2 * inv_rl ), 0.0f, 0.0f, 0.0f ); + vmathV4MakeFromElems( &result->col1, 0.0f, ( n2 * inv_tb ), 0.0f, 0.0f ); + vmathV4MakeFromElems( &result->col2, ( sum_rl * inv_rl ), ( sum_tb * inv_tb ), ( sum_nf * inv_nf ), -1.0f ); + vmathV4MakeFromElems( &result->col3, 0.0f, 0.0f, ( ( n2 * inv_nf ) * zFar ), 0.0f ); +} + +static inline void vmathM4MakeOrthographic( VmathMatrix4 *result, float left, float right, float bottom, float top, float zNear, float zFar ) +{ + float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf; + sum_rl = ( right + left ); + sum_tb = ( top + bottom ); + sum_nf = ( zNear + zFar ); + inv_rl = ( 1.0f / ( right - left ) ); + inv_tb = ( 1.0f / ( top - bottom ) ); + inv_nf = ( 1.0f / ( zNear - zFar ) ); + vmathV4MakeFromElems( &result->col0, ( inv_rl + inv_rl ), 0.0f, 0.0f, 0.0f ); + vmathV4MakeFromElems( &result->col1, 0.0f, ( inv_tb + inv_tb ), 0.0f, 0.0f ); + vmathV4MakeFromElems( &result->col2, 0.0f, 0.0f, ( inv_nf + inv_nf ), 0.0f ); + vmathV4MakeFromElems( &result->col3, ( -sum_rl * inv_rl ), ( -sum_tb * inv_tb ), ( sum_nf * inv_nf ), 1.0f ); +} + +static inline void vmathM4Select( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1, unsigned int select1 ) +{ + vmathV4Select( &result->col0, &mat0->col0, &mat1->col0, select1 ); + vmathV4Select( &result->col1, &mat0->col1, &mat1->col1, select1 ); + vmathV4Select( &result->col2, &mat0->col2, &mat1->col2, select1 ); + vmathV4Select( &result->col3, &mat0->col3, &mat1->col3, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathM4Print( const VmathMatrix4 *mat ) +{ + VmathVector4 tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3; + vmathM4GetRow( &tmpV4_0, mat, 0 ); + vmathV4Print( &tmpV4_0 ); + vmathM4GetRow( &tmpV4_1, mat, 1 ); + vmathV4Print( &tmpV4_1 ); + vmathM4GetRow( &tmpV4_2, mat, 2 ); + vmathV4Print( &tmpV4_2 ); + vmathM4GetRow( &tmpV4_3, mat, 3 ); + vmathV4Print( &tmpV4_3 ); +} + +static inline void vmathM4Prints( const VmathMatrix4 *mat, const char *name ) +{ + printf("%s:\n", name); + vmathM4Print( mat ); +} + +#endif + +static inline void vmathT3Copy( VmathTransform3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( &result->col0, &tfrm->col0 ); + vmathV3Copy( &result->col1, &tfrm->col1 ); + vmathV3Copy( &result->col2, &tfrm->col2 ); + vmathV3Copy( &result->col3, &tfrm->col3 ); +} + +static inline void vmathT3MakeFromScalar( VmathTransform3 *result, float scalar ) +{ + vmathV3MakeFromScalar( &result->col0, scalar ); + vmathV3MakeFromScalar( &result->col1, scalar ); + vmathV3MakeFromScalar( &result->col2, scalar ); + vmathV3MakeFromScalar( &result->col3, scalar ); +} + +static inline void vmathT3MakeFromCols( VmathTransform3 *result, const VmathVector3 *_col0, const VmathVector3 *_col1, const VmathVector3 *_col2, const VmathVector3 *_col3 ) +{ + vmathV3Copy( &result->col0, _col0 ); + vmathV3Copy( &result->col1, _col1 ); + vmathV3Copy( &result->col2, _col2 ); + vmathV3Copy( &result->col3, _col3 ); +} + +static inline void vmathT3MakeFromM3V3( VmathTransform3 *result, const VmathMatrix3 *tfrm, const VmathVector3 *translateVec ) +{ + vmathT3SetUpper3x3( result, tfrm ); + vmathT3SetTranslation( result, translateVec ); +} + +static inline void vmathT3MakeFromQV3( VmathTransform3 *result, const VmathQuat *unitQuat, const VmathVector3 *translateVec ) +{ + VmathMatrix3 tmpM3_0; + vmathM3MakeFromQ( &tmpM3_0, unitQuat ); + vmathT3SetUpper3x3( result, &tmpM3_0 ); + vmathT3SetTranslation( result, translateVec ); +} + +static inline void vmathT3SetCol0( VmathTransform3 *result, const VmathVector3 *_col0 ) +{ + vmathV3Copy( &result->col0, _col0 ); +} + +static inline void vmathT3SetCol1( VmathTransform3 *result, const VmathVector3 *_col1 ) +{ + vmathV3Copy( &result->col1, _col1 ); +} + +static inline void vmathT3SetCol2( VmathTransform3 *result, const VmathVector3 *_col2 ) +{ + vmathV3Copy( &result->col2, _col2 ); +} + +static inline void vmathT3SetCol3( VmathTransform3 *result, const VmathVector3 *_col3 ) +{ + vmathV3Copy( &result->col3, _col3 ); +} + +static inline void vmathT3SetCol( VmathTransform3 *result, int col, const VmathVector3 *vec ) +{ + vmathV3Copy( (&result->col0 + col), vec ); +} + +static inline void vmathT3SetRow( VmathTransform3 *result, int row, const VmathVector4 *vec ) +{ + vmathV3SetElem( &result->col0, row, vmathV4GetElem( vec, 0 ) ); + vmathV3SetElem( &result->col1, row, vmathV4GetElem( vec, 1 ) ); + vmathV3SetElem( &result->col2, row, vmathV4GetElem( vec, 2 ) ); + vmathV3SetElem( &result->col3, row, vmathV4GetElem( vec, 3 ) ); +} + +static inline void vmathT3SetElem( VmathTransform3 *result, int col, int row, float val ) +{ + VmathVector3 tmpV3_0; + vmathT3GetCol( &tmpV3_0, result, col ); + vmathV3SetElem( &tmpV3_0, row, val ); + vmathT3SetCol( result, col, &tmpV3_0 ); +} + +static inline float vmathT3GetElem( const VmathTransform3 *tfrm, int col, int row ) +{ + VmathVector3 tmpV3_0; + vmathT3GetCol( &tmpV3_0, tfrm, col ); + return vmathV3GetElem( &tmpV3_0, row ); +} + +static inline void vmathT3GetCol0( VmathVector3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( result, &tfrm->col0 ); +} + +static inline void vmathT3GetCol1( VmathVector3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( result, &tfrm->col1 ); +} + +static inline void vmathT3GetCol2( VmathVector3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( result, &tfrm->col2 ); +} + +static inline void vmathT3GetCol3( VmathVector3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( result, &tfrm->col3 ); +} + +static inline void vmathT3GetCol( VmathVector3 *result, const VmathTransform3 *tfrm, int col ) +{ + vmathV3Copy( result, (&tfrm->col0 + col) ); +} + +static inline void vmathT3GetRow( VmathVector4 *result, const VmathTransform3 *tfrm, int row ) +{ + vmathV4MakeFromElems( result, vmathV3GetElem( &tfrm->col0, row ), vmathV3GetElem( &tfrm->col1, row ), vmathV3GetElem( &tfrm->col2, row ), vmathV3GetElem( &tfrm->col3, row ) ); +} + +static inline void vmathT3Inverse( VmathTransform3 *result, const VmathTransform3 *tfrm ) +{ + VmathVector3 tmp0, tmp1, tmp2, inv0, inv1, inv2, tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5; + float detinv; + vmathV3Cross( &tmp0, &tfrm->col1, &tfrm->col2 ); + vmathV3Cross( &tmp1, &tfrm->col2, &tfrm->col0 ); + vmathV3Cross( &tmp2, &tfrm->col0, &tfrm->col1 ); + detinv = ( 1.0f / vmathV3Dot( &tfrm->col2, &tmp2 ) ); + vmathV3MakeFromElems( &inv0, ( tmp0.x * detinv ), ( tmp1.x * detinv ), ( tmp2.x * detinv ) ); + vmathV3MakeFromElems( &inv1, ( tmp0.y * detinv ), ( tmp1.y * detinv ), ( tmp2.y * detinv ) ); + vmathV3MakeFromElems( &inv2, ( tmp0.z * detinv ), ( tmp1.z * detinv ), ( tmp2.z * detinv ) ); + vmathV3Copy( &result->col0, &inv0 ); + vmathV3Copy( &result->col1, &inv1 ); + vmathV3Copy( &result->col2, &inv2 ); + vmathV3ScalarMul( &tmpV3_0, &inv0, tfrm->col3.x ); + vmathV3ScalarMul( &tmpV3_1, &inv1, tfrm->col3.y ); + vmathV3ScalarMul( &tmpV3_2, &inv2, tfrm->col3.z ); + vmathV3Add( &tmpV3_3, &tmpV3_1, &tmpV3_2 ); + vmathV3Add( &tmpV3_4, &tmpV3_0, &tmpV3_3 ); + vmathV3Neg( &tmpV3_5, &tmpV3_4 ); + vmathV3Copy( &result->col3, &tmpV3_5 ); +} + +static inline void vmathT3OrthoInverse( VmathTransform3 *result, const VmathTransform3 *tfrm ) +{ + VmathVector3 inv0, inv1, inv2, tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5; + vmathV3MakeFromElems( &inv0, tfrm->col0.x, tfrm->col1.x, tfrm->col2.x ); + vmathV3MakeFromElems( &inv1, tfrm->col0.y, tfrm->col1.y, tfrm->col2.y ); + vmathV3MakeFromElems( &inv2, tfrm->col0.z, tfrm->col1.z, tfrm->col2.z ); + vmathV3Copy( &result->col0, &inv0 ); + vmathV3Copy( &result->col1, &inv1 ); + vmathV3Copy( &result->col2, &inv2 ); + vmathV3ScalarMul( &tmpV3_0, &inv0, tfrm->col3.x ); + vmathV3ScalarMul( &tmpV3_1, &inv1, tfrm->col3.y ); + vmathV3ScalarMul( &tmpV3_2, &inv2, tfrm->col3.z ); + vmathV3Add( &tmpV3_3, &tmpV3_1, &tmpV3_2 ); + vmathV3Add( &tmpV3_4, &tmpV3_0, &tmpV3_3 ); + vmathV3Neg( &tmpV3_5, &tmpV3_4 ); + vmathV3Copy( &result->col3, &tmpV3_5 ); +} + +static inline void vmathT3AbsPerElem( VmathTransform3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3AbsPerElem( &result->col0, &tfrm->col0 ); + vmathV3AbsPerElem( &result->col1, &tfrm->col1 ); + vmathV3AbsPerElem( &result->col2, &tfrm->col2 ); + vmathV3AbsPerElem( &result->col3, &tfrm->col3 ); +} + +static inline void vmathT3MulV3( VmathVector3 *result, const VmathTransform3 *tfrm, const VmathVector3 *vec ) +{ + float tmpX, tmpY, tmpZ; + tmpX = ( ( ( tfrm->col0.x * vec->x ) + ( tfrm->col1.x * vec->y ) ) + ( tfrm->col2.x * vec->z ) ); + tmpY = ( ( ( tfrm->col0.y * vec->x ) + ( tfrm->col1.y * vec->y ) ) + ( tfrm->col2.y * vec->z ) ); + tmpZ = ( ( ( tfrm->col0.z * vec->x ) + ( tfrm->col1.z * vec->y ) ) + ( tfrm->col2.z * vec->z ) ); + vmathV3MakeFromElems( result, tmpX, tmpY, tmpZ ); +} + +static inline void vmathT3MulP3( VmathPoint3 *result, const VmathTransform3 *tfrm, const VmathPoint3 *pnt ) +{ + float tmpX, tmpY, tmpZ; + tmpX = ( ( ( ( tfrm->col0.x * pnt->x ) + ( tfrm->col1.x * pnt->y ) ) + ( tfrm->col2.x * pnt->z ) ) + tfrm->col3.x ); + tmpY = ( ( ( ( tfrm->col0.y * pnt->x ) + ( tfrm->col1.y * pnt->y ) ) + ( tfrm->col2.y * pnt->z ) ) + tfrm->col3.y ); + tmpZ = ( ( ( ( tfrm->col0.z * pnt->x ) + ( tfrm->col1.z * pnt->y ) ) + ( tfrm->col2.z * pnt->z ) ) + tfrm->col3.z ); + vmathP3MakeFromElems( result, tmpX, tmpY, tmpZ ); +} + +static inline void vmathT3Mul( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1 ) +{ + VmathTransform3 tmpResult; + VmathPoint3 tmpP3_0, tmpP3_1; + vmathT3MulV3( &tmpResult.col0, tfrm0, &tfrm1->col0 ); + vmathT3MulV3( &tmpResult.col1, tfrm0, &tfrm1->col1 ); + vmathT3MulV3( &tmpResult.col2, tfrm0, &tfrm1->col2 ); + vmathP3MakeFromV3( &tmpP3_0, &tfrm1->col3 ); + vmathT3MulP3( &tmpP3_1, tfrm0, &tmpP3_0 ); + vmathV3MakeFromP3( &tmpResult.col3, &tmpP3_1 ); + vmathT3Copy( result, &tmpResult ); +} + +static inline void vmathT3MulPerElem( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1 ) +{ + vmathV3MulPerElem( &result->col0, &tfrm0->col0, &tfrm1->col0 ); + vmathV3MulPerElem( &result->col1, &tfrm0->col1, &tfrm1->col1 ); + vmathV3MulPerElem( &result->col2, &tfrm0->col2, &tfrm1->col2 ); + vmathV3MulPerElem( &result->col3, &tfrm0->col3, &tfrm1->col3 ); +} + +static inline void vmathT3MakeIdentity( VmathTransform3 *result ) +{ + vmathV3MakeXAxis( &result->col0 ); + vmathV3MakeYAxis( &result->col1 ); + vmathV3MakeZAxis( &result->col2 ); + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3SetUpper3x3( VmathTransform3 *result, const VmathMatrix3 *tfrm ) +{ + vmathV3Copy( &result->col0, &tfrm->col0 ); + vmathV3Copy( &result->col1, &tfrm->col1 ); + vmathV3Copy( &result->col2, &tfrm->col2 ); +} + +static inline void vmathT3GetUpper3x3( VmathMatrix3 *result, const VmathTransform3 *tfrm ) +{ + vmathM3MakeFromCols( result, &tfrm->col0, &tfrm->col1, &tfrm->col2 ); +} + +static inline void vmathT3SetTranslation( VmathTransform3 *result, const VmathVector3 *translateVec ) +{ + vmathV3Copy( &result->col3, translateVec ); +} + +static inline void vmathT3GetTranslation( VmathVector3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( result, &tfrm->col3 ); +} + +static inline void vmathT3MakeRotationX( VmathTransform3 *result, float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + vmathV3MakeXAxis( &result->col0 ); + vmathV3MakeFromElems( &result->col1, 0.0f, c, s ); + vmathV3MakeFromElems( &result->col2, 0.0f, -s, c ); + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3MakeRotationY( VmathTransform3 *result, float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + vmathV3MakeFromElems( &result->col0, c, 0.0f, -s ); + vmathV3MakeYAxis( &result->col1 ); + vmathV3MakeFromElems( &result->col2, s, 0.0f, c ); + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3MakeRotationZ( VmathTransform3 *result, float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + vmathV3MakeFromElems( &result->col0, c, s, 0.0f ); + vmathV3MakeFromElems( &result->col1, -s, c, 0.0f ); + vmathV3MakeZAxis( &result->col2 ); + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3MakeRotationZYX( VmathTransform3 *result, const VmathVector3 *radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ->x ); + cX = cosf( radiansXYZ->x ); + sY = sinf( radiansXYZ->y ); + cY = cosf( radiansXYZ->y ); + sZ = sinf( radiansXYZ->z ); + cZ = cosf( radiansXYZ->z ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + vmathV3MakeFromElems( &result->col0, ( cZ * cY ), ( sZ * cY ), -sY ); + vmathV3MakeFromElems( &result->col1, ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ); + vmathV3MakeFromElems( &result->col2, ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ); + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3MakeRotationAxis( VmathTransform3 *result, float radians, const VmathVector3 *unitVec ) +{ + VmathMatrix3 tmpM3_0; + VmathVector3 tmpV3_0; + vmathM3MakeRotationAxis( &tmpM3_0, radians, unitVec ); + vmathV3MakeFromScalar( &tmpV3_0, 0.0f ); + vmathT3MakeFromM3V3( result, &tmpM3_0, &tmpV3_0 ); +} + +static inline void vmathT3MakeRotationQ( VmathTransform3 *result, const VmathQuat *unitQuat ) +{ + VmathMatrix3 tmpM3_0; + VmathVector3 tmpV3_0; + vmathM3MakeFromQ( &tmpM3_0, unitQuat ); + vmathV3MakeFromScalar( &tmpV3_0, 0.0f ); + vmathT3MakeFromM3V3( result, &tmpM3_0, &tmpV3_0 ); +} + +static inline void vmathT3MakeScale( VmathTransform3 *result, const VmathVector3 *scaleVec ) +{ + vmathV3MakeFromElems( &result->col0, scaleVec->x, 0.0f, 0.0f ); + vmathV3MakeFromElems( &result->col1, 0.0f, scaleVec->y, 0.0f ); + vmathV3MakeFromElems( &result->col2, 0.0f, 0.0f, scaleVec->z ); + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3AppendScale( VmathTransform3 *result, const VmathTransform3 *tfrm, const VmathVector3 *scaleVec ) +{ + vmathV3ScalarMul( &result->col0, &tfrm->col0, vmathV3GetX( scaleVec ) ); + vmathV3ScalarMul( &result->col1, &tfrm->col1, vmathV3GetY( scaleVec ) ); + vmathV3ScalarMul( &result->col2, &tfrm->col2, vmathV3GetZ( scaleVec ) ); + vmathV3Copy( &result->col3, &tfrm->col3 ); +} + +static inline void vmathT3PrependScale( VmathTransform3 *result, const VmathVector3 *scaleVec, const VmathTransform3 *tfrm ) +{ + vmathV3MulPerElem( &result->col0, &tfrm->col0, scaleVec ); + vmathV3MulPerElem( &result->col1, &tfrm->col1, scaleVec ); + vmathV3MulPerElem( &result->col2, &tfrm->col2, scaleVec ); + vmathV3MulPerElem( &result->col3, &tfrm->col3, scaleVec ); +} + +static inline void vmathT3MakeTranslation( VmathTransform3 *result, const VmathVector3 *translateVec ) +{ + vmathV3MakeXAxis( &result->col0 ); + vmathV3MakeYAxis( &result->col1 ); + vmathV3MakeZAxis( &result->col2 ); + vmathV3Copy( &result->col3, translateVec ); +} + +static inline void vmathT3Select( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1, unsigned int select1 ) +{ + vmathV3Select( &result->col0, &tfrm0->col0, &tfrm1->col0, select1 ); + vmathV3Select( &result->col1, &tfrm0->col1, &tfrm1->col1, select1 ); + vmathV3Select( &result->col2, &tfrm0->col2, &tfrm1->col2, select1 ); + vmathV3Select( &result->col3, &tfrm0->col3, &tfrm1->col3, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathT3Print( const VmathTransform3 *tfrm ) +{ + VmathVector4 tmpV4_0, tmpV4_1, tmpV4_2; + vmathT3GetRow( &tmpV4_0, tfrm, 0 ); + vmathV4Print( &tmpV4_0 ); + vmathT3GetRow( &tmpV4_1, tfrm, 1 ); + vmathV4Print( &tmpV4_1 ); + vmathT3GetRow( &tmpV4_2, tfrm, 2 ); + vmathV4Print( &tmpV4_2 ); +} + +static inline void vmathT3Prints( const VmathTransform3 *tfrm, const char *name ) +{ + printf("%s:\n", name); + vmathT3Print( tfrm ); +} + +#endif + +static inline void vmathQMakeFromM3( VmathQuat *result, const VmathMatrix3 *tfrm ) +{ + float trace, radicand, scale, xx, yx, zx, xy, yy, zy, xz, yz, zz, tmpx, tmpy, tmpz, tmpw, qx, qy, qz, qw; + int negTrace, ZgtX, ZgtY, YgtX; + int largestXorY, largestYorZ, largestZorX; + + xx = tfrm->col0.x; + yx = tfrm->col0.y; + zx = tfrm->col0.z; + xy = tfrm->col1.x; + yy = tfrm->col1.y; + zy = tfrm->col1.z; + xz = tfrm->col2.x; + yz = tfrm->col2.y; + zz = tfrm->col2.z; + + trace = ( ( xx + yy ) + zz ); + + negTrace = ( trace < 0.0f ); + ZgtX = zz > xx; + ZgtY = zz > yy; + YgtX = yy > xx; + largestXorY = ( !ZgtX || !ZgtY ) && negTrace; + largestYorZ = ( YgtX || ZgtX ) && negTrace; + largestZorX = ( ZgtY || !YgtX ) && negTrace; + + if ( largestXorY ) + { + zz = -zz; + xy = -xy; + } + if ( largestYorZ ) + { + xx = -xx; + yz = -yz; + } + if ( largestZorX ) + { + yy = -yy; + zx = -zx; + } + + radicand = ( ( ( xx + yy ) + zz ) + 1.0f ); + scale = ( 0.5f * ( 1.0f / sqrtf( radicand ) ) ); + + tmpx = ( ( zy - yz ) * scale ); + tmpy = ( ( xz - zx ) * scale ); + tmpz = ( ( yx - xy ) * scale ); + tmpw = ( radicand * scale ); + qx = tmpx; + qy = tmpy; + qz = tmpz; + qw = tmpw; + + if ( largestXorY ) + { + qx = tmpw; + qy = tmpz; + qz = tmpy; + qw = tmpx; + } + if ( largestYorZ ) + { + tmpx = qx; + tmpz = qz; + qx = qy; + qy = tmpx; + qz = qw; + qw = tmpz; + } + + result->x = qx; + result->y = qy; + result->z = qz; + result->w = qw; +} + +static inline void vmathV3Outer( VmathMatrix3 *result, const VmathVector3 *tfrm0, const VmathVector3 *tfrm1 ) +{ + vmathV3ScalarMul( &result->col0, tfrm0, vmathV3GetX( tfrm1 ) ); + vmathV3ScalarMul( &result->col1, tfrm0, vmathV3GetY( tfrm1 ) ); + vmathV3ScalarMul( &result->col2, tfrm0, vmathV3GetZ( tfrm1 ) ); +} + +static inline void vmathV4Outer( VmathMatrix4 *result, const VmathVector4 *tfrm0, const VmathVector4 *tfrm1 ) +{ + vmathV4ScalarMul( &result->col0, tfrm0, vmathV4GetX( tfrm1 ) ); + vmathV4ScalarMul( &result->col1, tfrm0, vmathV4GetY( tfrm1 ) ); + vmathV4ScalarMul( &result->col2, tfrm0, vmathV4GetZ( tfrm1 ) ); + vmathV4ScalarMul( &result->col3, tfrm0, vmathV4GetW( tfrm1 ) ); +} + +static inline void vmathV3RowMul( VmathVector3 *result, const VmathVector3 *vec, const VmathMatrix3 *mat ) +{ + float tmpX, tmpY, tmpZ; + tmpX = ( ( ( vec->x * mat->col0.x ) + ( vec->y * mat->col0.y ) ) + ( vec->z * mat->col0.z ) ); + tmpY = ( ( ( vec->x * mat->col1.x ) + ( vec->y * mat->col1.y ) ) + ( vec->z * mat->col1.z ) ); + tmpZ = ( ( ( vec->x * mat->col2.x ) + ( vec->y * mat->col2.y ) ) + ( vec->z * mat->col2.z ) ); + vmathV3MakeFromElems( result, tmpX, tmpY, tmpZ ); +} + +static inline void vmathV3CrossMatrix( VmathMatrix3 *result, const VmathVector3 *vec ) +{ + vmathV3MakeFromElems( &result->col0, 0.0f, vec->z, -vec->y ); + vmathV3MakeFromElems( &result->col1, -vec->z, 0.0f, vec->x ); + vmathV3MakeFromElems( &result->col2, vec->y, -vec->x, 0.0f ); +} + +static inline void vmathV3CrossMatrixMul( VmathMatrix3 *result, const VmathVector3 *vec, const VmathMatrix3 *mat ) +{ + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2; + vmathV3Cross( &tmpV3_0, vec, &mat->col0 ); + vmathV3Cross( &tmpV3_1, vec, &mat->col1 ); + vmathV3Cross( &tmpV3_2, vec, &mat->col2 ); + vmathM3MakeFromCols( result, &tmpV3_0, &tmpV3_1, &tmpV3_2 ); +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/scalar/c/mat_aos_v.h b/Extras/vectormathlibrary/include/vectormath/scalar/c/mat_aos_v.h new file mode 100644 index 0000000..270ffcb --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/scalar/c/mat_aos_v.h @@ -0,0 +1,1006 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_AOS_V_C_H +#define _VECTORMATH_MAT_AOS_V_C_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + */ +#define _VECTORMATH_PI_OVER_2 1.570796327f + +/*----------------------------------------------------------------------------- + * Definitions + */ +static inline VmathMatrix3 vmathM3MakeFromScalar_V( float scalar ) +{ + VmathMatrix3 result; + vmathM3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathMatrix3 vmathM3MakeFromQ_V( VmathQuat unitQuat ) +{ + VmathMatrix3 result; + vmathM3MakeFromQ(&result, &unitQuat); + return result; +} + +static inline VmathMatrix3 vmathM3MakeFromCols_V( VmathVector3 _col0, VmathVector3 _col1, VmathVector3 _col2 ) +{ + VmathMatrix3 result; + vmathM3MakeFromCols(&result, &_col0, &_col1, &_col2); + return result; +} + +static inline void vmathM3SetCol0_V( VmathMatrix3 *result, VmathVector3 _col0 ) +{ + vmathM3SetCol0(result, &_col0); +} + +static inline void vmathM3SetCol1_V( VmathMatrix3 *result, VmathVector3 _col1 ) +{ + vmathM3SetCol1(result, &_col1); +} + +static inline void vmathM3SetCol2_V( VmathMatrix3 *result, VmathVector3 _col2 ) +{ + vmathM3SetCol2(result, &_col2); +} + +static inline void vmathM3SetCol_V( VmathMatrix3 *result, int col, VmathVector3 vec ) +{ + vmathM3SetCol(result, col, &vec); +} + +static inline void vmathM3SetRow_V( VmathMatrix3 *result, int row, VmathVector3 vec ) +{ + vmathM3SetRow(result, row, &vec); +} + +static inline void vmathM3SetElem_V( VmathMatrix3 *result, int col, int row, float val ) +{ + vmathM3SetElem(result, col, row, val); +} + +static inline float vmathM3GetElem_V( VmathMatrix3 mat, int col, int row ) +{ + return vmathM3GetElem(&mat, col, row); +} + +static inline VmathVector3 vmathM3GetCol0_V( VmathMatrix3 mat ) +{ + VmathVector3 result; + vmathM3GetCol0(&result, &mat); + return result; +} + +static inline VmathVector3 vmathM3GetCol1_V( VmathMatrix3 mat ) +{ + VmathVector3 result; + vmathM3GetCol1(&result, &mat); + return result; +} + +static inline VmathVector3 vmathM3GetCol2_V( VmathMatrix3 mat ) +{ + VmathVector3 result; + vmathM3GetCol2(&result, &mat); + return result; +} + +static inline VmathVector3 vmathM3GetCol_V( VmathMatrix3 mat, int col ) +{ + VmathVector3 result; + vmathM3GetCol(&result, &mat, col); + return result; +} + +static inline VmathVector3 vmathM3GetRow_V( VmathMatrix3 mat, int row ) +{ + VmathVector3 result; + vmathM3GetRow(&result, &mat, row); + return result; +} + +static inline VmathMatrix3 vmathM3Transpose_V( VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathM3Transpose(&result, &mat); + return result; +} + +static inline VmathMatrix3 vmathM3Inverse_V( VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathM3Inverse(&result, &mat); + return result; +} + +static inline float vmathM3Determinant_V( VmathMatrix3 mat ) +{ + return vmathM3Determinant(&mat); +} + +static inline VmathMatrix3 vmathM3Add_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ) +{ + VmathMatrix3 result; + vmathM3Add(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix3 vmathM3Sub_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ) +{ + VmathMatrix3 result; + vmathM3Sub(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix3 vmathM3Neg_V( VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathM3Neg(&result, &mat); + return result; +} + +static inline VmathMatrix3 vmathM3AbsPerElem_V( VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathM3AbsPerElem(&result, &mat); + return result; +} + +static inline VmathMatrix3 vmathM3ScalarMul_V( VmathMatrix3 mat, float scalar ) +{ + VmathMatrix3 result; + vmathM3ScalarMul(&result, &mat, scalar); + return result; +} + +static inline VmathVector3 vmathM3MulV3_V( VmathMatrix3 mat, VmathVector3 vec ) +{ + VmathVector3 result; + vmathM3MulV3(&result, &mat, &vec); + return result; +} + +static inline VmathMatrix3 vmathM3Mul_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ) +{ + VmathMatrix3 result; + vmathM3Mul(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix3 vmathM3MulPerElem_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ) +{ + VmathMatrix3 result; + vmathM3MulPerElem(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix3 vmathM3MakeIdentity_V( ) +{ + VmathMatrix3 result; + vmathM3MakeIdentity(&result); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationX_V( float radians ) +{ + VmathMatrix3 result; + vmathM3MakeRotationX(&result, radians); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationY_V( float radians ) +{ + VmathMatrix3 result; + vmathM3MakeRotationY(&result, radians); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationZ_V( float radians ) +{ + VmathMatrix3 result; + vmathM3MakeRotationZ(&result, radians); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationZYX_V( VmathVector3 radiansXYZ ) +{ + VmathMatrix3 result; + vmathM3MakeRotationZYX(&result, &radiansXYZ); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationAxis_V( float radians, VmathVector3 unitVec ) +{ + VmathMatrix3 result; + vmathM3MakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationQ_V( VmathQuat unitQuat ) +{ + VmathMatrix3 result; + vmathM3MakeRotationQ(&result, &unitQuat); + return result; +} + +static inline VmathMatrix3 vmathM3MakeScale_V( VmathVector3 scaleVec ) +{ + VmathMatrix3 result; + vmathM3MakeScale(&result, &scaleVec); + return result; +} + +static inline VmathMatrix3 vmathM3AppendScale_V( VmathMatrix3 mat, VmathVector3 scaleVec ) +{ + VmathMatrix3 result; + vmathM3AppendScale(&result, &mat, &scaleVec); + return result; +} + +static inline VmathMatrix3 vmathM3PrependScale_V( VmathVector3 scaleVec, VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathM3PrependScale(&result, &scaleVec, &mat); + return result; +} + +static inline VmathMatrix3 vmathM3Select_V( VmathMatrix3 mat0, VmathMatrix3 mat1, unsigned int select1 ) +{ + VmathMatrix3 result; + vmathM3Select(&result, &mat0, &mat1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathM3Print_V( VmathMatrix3 mat ) +{ + vmathM3Print(&mat); +} + +static inline void vmathM3Prints_V( VmathMatrix3 mat, const char *name ) +{ + vmathM3Prints(&mat, name); +} + +#endif + +static inline VmathMatrix4 vmathM4MakeFromScalar_V( float scalar ) +{ + VmathMatrix4 result; + vmathM4MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathMatrix4 vmathM4MakeFromT3_V( VmathTransform3 mat ) +{ + VmathMatrix4 result; + vmathM4MakeFromT3(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4MakeFromCols_V( VmathVector4 _col0, VmathVector4 _col1, VmathVector4 _col2, VmathVector4 _col3 ) +{ + VmathMatrix4 result; + vmathM4MakeFromCols(&result, &_col0, &_col1, &_col2, &_col3); + return result; +} + +static inline VmathMatrix4 vmathM4MakeFromM3V3_V( VmathMatrix3 mat, VmathVector3 translateVec ) +{ + VmathMatrix4 result; + vmathM4MakeFromM3V3(&result, &mat, &translateVec); + return result; +} + +static inline VmathMatrix4 vmathM4MakeFromQV3_V( VmathQuat unitQuat, VmathVector3 translateVec ) +{ + VmathMatrix4 result; + vmathM4MakeFromQV3(&result, &unitQuat, &translateVec); + return result; +} + +static inline void vmathM4SetCol0_V( VmathMatrix4 *result, VmathVector4 _col0 ) +{ + vmathM4SetCol0(result, &_col0); +} + +static inline void vmathM4SetCol1_V( VmathMatrix4 *result, VmathVector4 _col1 ) +{ + vmathM4SetCol1(result, &_col1); +} + +static inline void vmathM4SetCol2_V( VmathMatrix4 *result, VmathVector4 _col2 ) +{ + vmathM4SetCol2(result, &_col2); +} + +static inline void vmathM4SetCol3_V( VmathMatrix4 *result, VmathVector4 _col3 ) +{ + vmathM4SetCol3(result, &_col3); +} + +static inline void vmathM4SetCol_V( VmathMatrix4 *result, int col, VmathVector4 vec ) +{ + vmathM4SetCol(result, col, &vec); +} + +static inline void vmathM4SetRow_V( VmathMatrix4 *result, int row, VmathVector4 vec ) +{ + vmathM4SetRow(result, row, &vec); +} + +static inline void vmathM4SetElem_V( VmathMatrix4 *result, int col, int row, float val ) +{ + vmathM4SetElem(result, col, row, val); +} + +static inline float vmathM4GetElem_V( VmathMatrix4 mat, int col, int row ) +{ + return vmathM4GetElem(&mat, col, row); +} + +static inline VmathVector4 vmathM4GetCol0_V( VmathMatrix4 mat ) +{ + VmathVector4 result; + vmathM4GetCol0(&result, &mat); + return result; +} + +static inline VmathVector4 vmathM4GetCol1_V( VmathMatrix4 mat ) +{ + VmathVector4 result; + vmathM4GetCol1(&result, &mat); + return result; +} + +static inline VmathVector4 vmathM4GetCol2_V( VmathMatrix4 mat ) +{ + VmathVector4 result; + vmathM4GetCol2(&result, &mat); + return result; +} + +static inline VmathVector4 vmathM4GetCol3_V( VmathMatrix4 mat ) +{ + VmathVector4 result; + vmathM4GetCol3(&result, &mat); + return result; +} + +static inline VmathVector4 vmathM4GetCol_V( VmathMatrix4 mat, int col ) +{ + VmathVector4 result; + vmathM4GetCol(&result, &mat, col); + return result; +} + +static inline VmathVector4 vmathM4GetRow_V( VmathMatrix4 mat, int row ) +{ + VmathVector4 result; + vmathM4GetRow(&result, &mat, row); + return result; +} + +static inline VmathMatrix4 vmathM4Transpose_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4Transpose(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4Inverse_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4Inverse(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4AffineInverse_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4AffineInverse(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4OrthoInverse_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4OrthoInverse(&result, &mat); + return result; +} + +static inline float vmathM4Determinant_V( VmathMatrix4 mat ) +{ + return vmathM4Determinant(&mat); +} + +static inline VmathMatrix4 vmathM4Add_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ) +{ + VmathMatrix4 result; + vmathM4Add(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix4 vmathM4Sub_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ) +{ + VmathMatrix4 result; + vmathM4Sub(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix4 vmathM4Neg_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4Neg(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4AbsPerElem_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4AbsPerElem(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4ScalarMul_V( VmathMatrix4 mat, float scalar ) +{ + VmathMatrix4 result; + vmathM4ScalarMul(&result, &mat, scalar); + return result; +} + +static inline VmathVector4 vmathM4MulV4_V( VmathMatrix4 mat, VmathVector4 vec ) +{ + VmathVector4 result; + vmathM4MulV4(&result, &mat, &vec); + return result; +} + +static inline VmathVector4 vmathM4MulV3_V( VmathMatrix4 mat, VmathVector3 vec ) +{ + VmathVector4 result; + vmathM4MulV3(&result, &mat, &vec); + return result; +} + +static inline VmathVector4 vmathM4MulP3_V( VmathMatrix4 mat, VmathPoint3 pnt ) +{ + VmathVector4 result; + vmathM4MulP3(&result, &mat, &pnt); + return result; +} + +static inline VmathMatrix4 vmathM4Mul_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ) +{ + VmathMatrix4 result; + vmathM4Mul(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix4 vmathM4MulT3_V( VmathMatrix4 mat, VmathTransform3 tfrm1 ) +{ + VmathMatrix4 result; + vmathM4MulT3(&result, &mat, &tfrm1); + return result; +} + +static inline VmathMatrix4 vmathM4MulPerElem_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ) +{ + VmathMatrix4 result; + vmathM4MulPerElem(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix4 vmathM4MakeIdentity_V( ) +{ + VmathMatrix4 result; + vmathM4MakeIdentity(&result); + return result; +} + +static inline void vmathM4SetUpper3x3_V( VmathMatrix4 *result, VmathMatrix3 mat3 ) +{ + vmathM4SetUpper3x3(result, &mat3); +} + +static inline VmathMatrix3 vmathM4GetUpper3x3_V( VmathMatrix4 mat ) +{ + VmathMatrix3 result; + vmathM4GetUpper3x3(&result, &mat); + return result; +} + +static inline void vmathM4SetTranslation_V( VmathMatrix4 *result, VmathVector3 translateVec ) +{ + vmathM4SetTranslation(result, &translateVec); +} + +static inline VmathVector3 vmathM4GetTranslation_V( VmathMatrix4 mat ) +{ + VmathVector3 result; + vmathM4GetTranslation(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationX_V( float radians ) +{ + VmathMatrix4 result; + vmathM4MakeRotationX(&result, radians); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationY_V( float radians ) +{ + VmathMatrix4 result; + vmathM4MakeRotationY(&result, radians); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationZ_V( float radians ) +{ + VmathMatrix4 result; + vmathM4MakeRotationZ(&result, radians); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationZYX_V( VmathVector3 radiansXYZ ) +{ + VmathMatrix4 result; + vmathM4MakeRotationZYX(&result, &radiansXYZ); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationAxis_V( float radians, VmathVector3 unitVec ) +{ + VmathMatrix4 result; + vmathM4MakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationQ_V( VmathQuat unitQuat ) +{ + VmathMatrix4 result; + vmathM4MakeRotationQ(&result, &unitQuat); + return result; +} + +static inline VmathMatrix4 vmathM4MakeScale_V( VmathVector3 scaleVec ) +{ + VmathMatrix4 result; + vmathM4MakeScale(&result, &scaleVec); + return result; +} + +static inline VmathMatrix4 vmathM4AppendScale_V( VmathMatrix4 mat, VmathVector3 scaleVec ) +{ + VmathMatrix4 result; + vmathM4AppendScale(&result, &mat, &scaleVec); + return result; +} + +static inline VmathMatrix4 vmathM4PrependScale_V( VmathVector3 scaleVec, VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4PrependScale(&result, &scaleVec, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4MakeTranslation_V( VmathVector3 translateVec ) +{ + VmathMatrix4 result; + vmathM4MakeTranslation(&result, &translateVec); + return result; +} + +static inline VmathMatrix4 vmathM4MakeLookAt_V( VmathPoint3 eyePos, VmathPoint3 lookAtPos, VmathVector3 upVec ) +{ + VmathMatrix4 result; + vmathM4MakeLookAt(&result, &eyePos, &lookAtPos, &upVec); + return result; +} + +static inline VmathMatrix4 vmathM4MakePerspective_V( float fovyRadians, float aspect, float zNear, float zFar ) +{ + VmathMatrix4 result; + vmathM4MakePerspective(&result, fovyRadians, aspect, zNear, zFar); + return result; +} + +static inline VmathMatrix4 vmathM4MakeFrustum_V( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + VmathMatrix4 result; + vmathM4MakeFrustum(&result, left, right, bottom, top, zNear, zFar); + return result; +} + +static inline VmathMatrix4 vmathM4MakeOrthographic_V( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + VmathMatrix4 result; + vmathM4MakeOrthographic(&result, left, right, bottom, top, zNear, zFar); + return result; +} + +static inline VmathMatrix4 vmathM4Select_V( VmathMatrix4 mat0, VmathMatrix4 mat1, unsigned int select1 ) +{ + VmathMatrix4 result; + vmathM4Select(&result, &mat0, &mat1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathM4Print_V( VmathMatrix4 mat ) +{ + vmathM4Print(&mat); +} + +static inline void vmathM4Prints_V( VmathMatrix4 mat, const char *name ) +{ + vmathM4Prints(&mat, name); +} + +#endif + +static inline VmathTransform3 vmathT3MakeFromScalar_V( float scalar ) +{ + VmathTransform3 result; + vmathT3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathTransform3 vmathT3MakeFromCols_V( VmathVector3 _col0, VmathVector3 _col1, VmathVector3 _col2, VmathVector3 _col3 ) +{ + VmathTransform3 result; + vmathT3MakeFromCols(&result, &_col0, &_col1, &_col2, &_col3); + return result; +} + +static inline VmathTransform3 vmathT3MakeFromM3V3_V( VmathMatrix3 tfrm, VmathVector3 translateVec ) +{ + VmathTransform3 result; + vmathT3MakeFromM3V3(&result, &tfrm, &translateVec); + return result; +} + +static inline VmathTransform3 vmathT3MakeFromQV3_V( VmathQuat unitQuat, VmathVector3 translateVec ) +{ + VmathTransform3 result; + vmathT3MakeFromQV3(&result, &unitQuat, &translateVec); + return result; +} + +static inline void vmathT3SetCol0_V( VmathTransform3 *result, VmathVector3 _col0 ) +{ + vmathT3SetCol0(result, &_col0); +} + +static inline void vmathT3SetCol1_V( VmathTransform3 *result, VmathVector3 _col1 ) +{ + vmathT3SetCol1(result, &_col1); +} + +static inline void vmathT3SetCol2_V( VmathTransform3 *result, VmathVector3 _col2 ) +{ + vmathT3SetCol2(result, &_col2); +} + +static inline void vmathT3SetCol3_V( VmathTransform3 *result, VmathVector3 _col3 ) +{ + vmathT3SetCol3(result, &_col3); +} + +static inline void vmathT3SetCol_V( VmathTransform3 *result, int col, VmathVector3 vec ) +{ + vmathT3SetCol(result, col, &vec); +} + +static inline void vmathT3SetRow_V( VmathTransform3 *result, int row, VmathVector4 vec ) +{ + vmathT3SetRow(result, row, &vec); +} + +static inline void vmathT3SetElem_V( VmathTransform3 *result, int col, int row, float val ) +{ + vmathT3SetElem(result, col, row, val); +} + +static inline float vmathT3GetElem_V( VmathTransform3 tfrm, int col, int row ) +{ + return vmathT3GetElem(&tfrm, col, row); +} + +static inline VmathVector3 vmathT3GetCol0_V( VmathTransform3 tfrm ) +{ + VmathVector3 result; + vmathT3GetCol0(&result, &tfrm); + return result; +} + +static inline VmathVector3 vmathT3GetCol1_V( VmathTransform3 tfrm ) +{ + VmathVector3 result; + vmathT3GetCol1(&result, &tfrm); + return result; +} + +static inline VmathVector3 vmathT3GetCol2_V( VmathTransform3 tfrm ) +{ + VmathVector3 result; + vmathT3GetCol2(&result, &tfrm); + return result; +} + +static inline VmathVector3 vmathT3GetCol3_V( VmathTransform3 tfrm ) +{ + VmathVector3 result; + vmathT3GetCol3(&result, &tfrm); + return result; +} + +static inline VmathVector3 vmathT3GetCol_V( VmathTransform3 tfrm, int col ) +{ + VmathVector3 result; + vmathT3GetCol(&result, &tfrm, col); + return result; +} + +static inline VmathVector4 vmathT3GetRow_V( VmathTransform3 tfrm, int row ) +{ + VmathVector4 result; + vmathT3GetRow(&result, &tfrm, row); + return result; +} + +static inline VmathTransform3 vmathT3Inverse_V( VmathTransform3 tfrm ) +{ + VmathTransform3 result; + vmathT3Inverse(&result, &tfrm); + return result; +} + +static inline VmathTransform3 vmathT3OrthoInverse_V( VmathTransform3 tfrm ) +{ + VmathTransform3 result; + vmathT3OrthoInverse(&result, &tfrm); + return result; +} + +static inline VmathTransform3 vmathT3AbsPerElem_V( VmathTransform3 tfrm ) +{ + VmathTransform3 result; + vmathT3AbsPerElem(&result, &tfrm); + return result; +} + +static inline VmathVector3 vmathT3MulV3_V( VmathTransform3 tfrm, VmathVector3 vec ) +{ + VmathVector3 result; + vmathT3MulV3(&result, &tfrm, &vec); + return result; +} + +static inline VmathPoint3 vmathT3MulP3_V( VmathTransform3 tfrm, VmathPoint3 pnt ) +{ + VmathPoint3 result; + vmathT3MulP3(&result, &tfrm, &pnt); + return result; +} + +static inline VmathTransform3 vmathT3Mul_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1 ) +{ + VmathTransform3 result; + vmathT3Mul(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathTransform3 vmathT3MulPerElem_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1 ) +{ + VmathTransform3 result; + vmathT3MulPerElem(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathTransform3 vmathT3MakeIdentity_V( ) +{ + VmathTransform3 result; + vmathT3MakeIdentity(&result); + return result; +} + +static inline void vmathT3SetUpper3x3_V( VmathTransform3 *result, VmathMatrix3 tfrm ) +{ + vmathT3SetUpper3x3(result, &tfrm); +} + +static inline VmathMatrix3 vmathT3GetUpper3x3_V( VmathTransform3 tfrm ) +{ + VmathMatrix3 result; + vmathT3GetUpper3x3(&result, &tfrm); + return result; +} + +static inline void vmathT3SetTranslation_V( VmathTransform3 *result, VmathVector3 translateVec ) +{ + vmathT3SetTranslation(result, &translateVec); +} + +static inline VmathVector3 vmathT3GetTranslation_V( VmathTransform3 tfrm ) +{ + VmathVector3 result; + vmathT3GetTranslation(&result, &tfrm); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationX_V( float radians ) +{ + VmathTransform3 result; + vmathT3MakeRotationX(&result, radians); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationY_V( float radians ) +{ + VmathTransform3 result; + vmathT3MakeRotationY(&result, radians); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationZ_V( float radians ) +{ + VmathTransform3 result; + vmathT3MakeRotationZ(&result, radians); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationZYX_V( VmathVector3 radiansXYZ ) +{ + VmathTransform3 result; + vmathT3MakeRotationZYX(&result, &radiansXYZ); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationAxis_V( float radians, VmathVector3 unitVec ) +{ + VmathTransform3 result; + vmathT3MakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationQ_V( VmathQuat unitQuat ) +{ + VmathTransform3 result; + vmathT3MakeRotationQ(&result, &unitQuat); + return result; +} + +static inline VmathTransform3 vmathT3MakeScale_V( VmathVector3 scaleVec ) +{ + VmathTransform3 result; + vmathT3MakeScale(&result, &scaleVec); + return result; +} + +static inline VmathTransform3 vmathT3AppendScale_V( VmathTransform3 tfrm, VmathVector3 scaleVec ) +{ + VmathTransform3 result; + vmathT3AppendScale(&result, &tfrm, &scaleVec); + return result; +} + +static inline VmathTransform3 vmathT3PrependScale_V( VmathVector3 scaleVec, VmathTransform3 tfrm ) +{ + VmathTransform3 result; + vmathT3PrependScale(&result, &scaleVec, &tfrm); + return result; +} + +static inline VmathTransform3 vmathT3MakeTranslation_V( VmathVector3 translateVec ) +{ + VmathTransform3 result; + vmathT3MakeTranslation(&result, &translateVec); + return result; +} + +static inline VmathTransform3 vmathT3Select_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1, unsigned int select1 ) +{ + VmathTransform3 result; + vmathT3Select(&result, &tfrm0, &tfrm1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathT3Print_V( VmathTransform3 tfrm ) +{ + vmathT3Print(&tfrm); +} + +static inline void vmathT3Prints_V( VmathTransform3 tfrm, const char *name ) +{ + vmathT3Prints(&tfrm, name); +} + +#endif + +static inline VmathQuat vmathQMakeFromM3_V( VmathMatrix3 tfrm ) +{ + VmathQuat result; + vmathQMakeFromM3(&result, &tfrm); + return result; +} + +static inline VmathMatrix3 vmathV3Outer_V( VmathVector3 tfrm0, VmathVector3 tfrm1 ) +{ + VmathMatrix3 result; + vmathV3Outer(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathMatrix4 vmathV4Outer_V( VmathVector4 tfrm0, VmathVector4 tfrm1 ) +{ + VmathMatrix4 result; + vmathV4Outer(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathVector3 vmathV3RowMul_V( VmathVector3 vec, VmathMatrix3 mat ) +{ + VmathVector3 result; + vmathV3RowMul(&result, &vec, &mat); + return result; +} + +static inline VmathMatrix3 vmathV3CrossMatrix_V( VmathVector3 vec ) +{ + VmathMatrix3 result; + vmathV3CrossMatrix(&result, &vec); + return result; +} + +static inline VmathMatrix3 vmathV3CrossMatrixMul_V( VmathVector3 vec, VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathV3CrossMatrixMul(&result, &vec, &mat); + return result; +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/scalar/c/quat_aos.h b/Extras/vectormathlibrary/include/vectormath/scalar/c/quat_aos.h new file mode 100644 index 0000000..c886ab6 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/scalar/c/quat_aos.h @@ -0,0 +1,368 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_AOS_C_H +#define _VECTORMATH_QUAT_AOS_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline void vmathQCopy( VmathQuat *result, const VmathQuat *quat ) +{ + result->x = quat->x; + result->y = quat->y; + result->z = quat->z; + result->w = quat->w; +} + +static inline void vmathQMakeFromElems( VmathQuat *result, float _x, float _y, float _z, float _w ) +{ + result->x = _x; + result->y = _y; + result->z = _z; + result->w = _w; +} + +static inline void vmathQMakeFromV3Scalar( VmathQuat *result, const VmathVector3 *xyz, float _w ) +{ + vmathQSetXYZ( result, xyz ); + vmathQSetW( result, _w ); +} + +static inline void vmathQMakeFromV4( VmathQuat *result, const VmathVector4 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; + result->w = vec->w; +} + +static inline void vmathQMakeFromScalar( VmathQuat *result, float scalar ) +{ + result->x = scalar; + result->y = scalar; + result->z = scalar; + result->w = scalar; +} + +static inline void vmathQMakeIdentity( VmathQuat *result ) +{ + vmathQMakeFromElems( result, 0.0f, 0.0f, 0.0f, 1.0f ); +} + +static inline void vmathQLerp( VmathQuat *result, float t, const VmathQuat *quat0, const VmathQuat *quat1 ) +{ + VmathQuat tmpQ_0, tmpQ_1; + vmathQSub( &tmpQ_0, quat1, quat0 ); + vmathQScalarMul( &tmpQ_1, &tmpQ_0, t ); + vmathQAdd( result, quat0, &tmpQ_1 ); +} + +static inline void vmathQSlerp( VmathQuat *result, float t, const VmathQuat *unitQuat0, const VmathQuat *unitQuat1 ) +{ + VmathQuat start, tmpQ_0, tmpQ_1; + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = vmathQDot( unitQuat0, unitQuat1 ); + if ( cosAngle < 0.0f ) { + cosAngle = -cosAngle; + vmathQNeg( &start, unitQuat0 ); + } else { + vmathQCopy( &start, unitQuat0 ); + } + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + vmathQScalarMul( &tmpQ_0, &start, scale0 ); + vmathQScalarMul( &tmpQ_1, unitQuat1, scale1 ); + vmathQAdd( result, &tmpQ_0, &tmpQ_1 ); +} + +static inline void vmathQSquad( VmathQuat *result, float t, const VmathQuat *unitQuat0, const VmathQuat *unitQuat1, const VmathQuat *unitQuat2, const VmathQuat *unitQuat3 ) +{ + VmathQuat tmp0, tmp1; + vmathQSlerp( &tmp0, t, unitQuat0, unitQuat3 ); + vmathQSlerp( &tmp1, t, unitQuat1, unitQuat2 ); + vmathQSlerp( result, ( ( 2.0f * t ) * ( 1.0f - t ) ), &tmp0, &tmp1 ); +} + +static inline void vmathQSetXYZ( VmathQuat *result, const VmathVector3 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; +} + +static inline void vmathQGetXYZ( VmathVector3 *result, const VmathQuat *quat ) +{ + vmathV3MakeFromElems( result, quat->x, quat->y, quat->z ); +} + +static inline void vmathQSetX( VmathQuat *result, float _x ) +{ + result->x = _x; +} + +static inline float vmathQGetX( const VmathQuat *quat ) +{ + return quat->x; +} + +static inline void vmathQSetY( VmathQuat *result, float _y ) +{ + result->y = _y; +} + +static inline float vmathQGetY( const VmathQuat *quat ) +{ + return quat->y; +} + +static inline void vmathQSetZ( VmathQuat *result, float _z ) +{ + result->z = _z; +} + +static inline float vmathQGetZ( const VmathQuat *quat ) +{ + return quat->z; +} + +static inline void vmathQSetW( VmathQuat *result, float _w ) +{ + result->w = _w; +} + +static inline float vmathQGetW( const VmathQuat *quat ) +{ + return quat->w; +} + +static inline void vmathQSetElem( VmathQuat *result, int idx, float value ) +{ + *(&result->x + idx) = value; +} + +static inline float vmathQGetElem( const VmathQuat *quat, int idx ) +{ + return *(&quat->x + idx); +} + +static inline void vmathQAdd( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ) +{ + result->x = ( quat0->x + quat1->x ); + result->y = ( quat0->y + quat1->y ); + result->z = ( quat0->z + quat1->z ); + result->w = ( quat0->w + quat1->w ); +} + +static inline void vmathQSub( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ) +{ + result->x = ( quat0->x - quat1->x ); + result->y = ( quat0->y - quat1->y ); + result->z = ( quat0->z - quat1->z ); + result->w = ( quat0->w - quat1->w ); +} + +static inline void vmathQScalarMul( VmathQuat *result, const VmathQuat *quat, float scalar ) +{ + result->x = ( quat->x * scalar ); + result->y = ( quat->y * scalar ); + result->z = ( quat->z * scalar ); + result->w = ( quat->w * scalar ); +} + +static inline void vmathQScalarDiv( VmathQuat *result, const VmathQuat *quat, float scalar ) +{ + result->x = ( quat->x / scalar ); + result->y = ( quat->y / scalar ); + result->z = ( quat->z / scalar ); + result->w = ( quat->w / scalar ); +} + +static inline void vmathQNeg( VmathQuat *result, const VmathQuat *quat ) +{ + result->x = -quat->x; + result->y = -quat->y; + result->z = -quat->z; + result->w = -quat->w; +} + +static inline float vmathQDot( const VmathQuat *quat0, const VmathQuat *quat1 ) +{ + float result; + result = ( quat0->x * quat1->x ); + result = ( result + ( quat0->y * quat1->y ) ); + result = ( result + ( quat0->z * quat1->z ) ); + result = ( result + ( quat0->w * quat1->w ) ); + return result; +} + +static inline float vmathQNorm( const VmathQuat *quat ) +{ + float result; + result = ( quat->x * quat->x ); + result = ( result + ( quat->y * quat->y ) ); + result = ( result + ( quat->z * quat->z ) ); + result = ( result + ( quat->w * quat->w ) ); + return result; +} + +static inline float vmathQLength( const VmathQuat *quat ) +{ + return sqrtf( vmathQNorm( quat ) ); +} + +static inline void vmathQNormalize( VmathQuat *result, const VmathQuat *quat ) +{ + float lenSqr, lenInv; + lenSqr = vmathQNorm( quat ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + result->x = ( quat->x * lenInv ); + result->y = ( quat->y * lenInv ); + result->z = ( quat->z * lenInv ); + result->w = ( quat->w * lenInv ); +} + +static inline void vmathQMakeRotationArc( VmathQuat *result, const VmathVector3 *unitVec0, const VmathVector3 *unitVec1 ) +{ + VmathVector3 tmpV3_0, tmpV3_1; + float cosHalfAngleX2, recipCosHalfAngleX2; + cosHalfAngleX2 = sqrtf( ( 2.0f * ( 1.0f + vmathV3Dot( unitVec0, unitVec1 ) ) ) ); + recipCosHalfAngleX2 = ( 1.0f / cosHalfAngleX2 ); + vmathV3Cross( &tmpV3_0, unitVec0, unitVec1 ); + vmathV3ScalarMul( &tmpV3_1, &tmpV3_0, recipCosHalfAngleX2 ); + vmathQMakeFromV3Scalar( result, &tmpV3_1, ( cosHalfAngleX2 * 0.5f ) ); +} + +static inline void vmathQMakeRotationAxis( VmathQuat *result, float radians, const VmathVector3 *unitVec ) +{ + VmathVector3 tmpV3_0; + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + vmathV3ScalarMul( &tmpV3_0, unitVec, s ); + vmathQMakeFromV3Scalar( result, &tmpV3_0, c ); +} + +static inline void vmathQMakeRotationX( VmathQuat *result, float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + vmathQMakeFromElems( result, s, 0.0f, 0.0f, c ); +} + +static inline void vmathQMakeRotationY( VmathQuat *result, float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + vmathQMakeFromElems( result, 0.0f, s, 0.0f, c ); +} + +static inline void vmathQMakeRotationZ( VmathQuat *result, float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + vmathQMakeFromElems( result, 0.0f, 0.0f, s, c ); +} + +static inline void vmathQMul( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ) +{ + float tmpX, tmpY, tmpZ, tmpW; + tmpX = ( ( ( ( quat0->w * quat1->x ) + ( quat0->x * quat1->w ) ) + ( quat0->y * quat1->z ) ) - ( quat0->z * quat1->y ) ); + tmpY = ( ( ( ( quat0->w * quat1->y ) + ( quat0->y * quat1->w ) ) + ( quat0->z * quat1->x ) ) - ( quat0->x * quat1->z ) ); + tmpZ = ( ( ( ( quat0->w * quat1->z ) + ( quat0->z * quat1->w ) ) + ( quat0->x * quat1->y ) ) - ( quat0->y * quat1->x ) ); + tmpW = ( ( ( ( quat0->w * quat1->w ) - ( quat0->x * quat1->x ) ) - ( quat0->y * quat1->y ) ) - ( quat0->z * quat1->z ) ); + vmathQMakeFromElems( result, tmpX, tmpY, tmpZ, tmpW ); +} + +static inline void vmathQRotate( VmathVector3 *result, const VmathQuat *quat, const VmathVector3 *vec ) +{ + float tmpX, tmpY, tmpZ, tmpW; + tmpX = ( ( ( quat->w * vec->x ) + ( quat->y * vec->z ) ) - ( quat->z * vec->y ) ); + tmpY = ( ( ( quat->w * vec->y ) + ( quat->z * vec->x ) ) - ( quat->x * vec->z ) ); + tmpZ = ( ( ( quat->w * vec->z ) + ( quat->x * vec->y ) ) - ( quat->y * vec->x ) ); + tmpW = ( ( ( quat->x * vec->x ) + ( quat->y * vec->y ) ) + ( quat->z * vec->z ) ); + result->x = ( ( ( ( tmpW * quat->x ) + ( tmpX * quat->w ) ) - ( tmpY * quat->z ) ) + ( tmpZ * quat->y ) ); + result->y = ( ( ( ( tmpW * quat->y ) + ( tmpY * quat->w ) ) - ( tmpZ * quat->x ) ) + ( tmpX * quat->z ) ); + result->z = ( ( ( ( tmpW * quat->z ) + ( tmpZ * quat->w ) ) - ( tmpX * quat->y ) ) + ( tmpY * quat->x ) ); +} + +static inline void vmathQConj( VmathQuat *result, const VmathQuat *quat ) +{ + vmathQMakeFromElems( result, -quat->x, -quat->y, -quat->z, quat->w ); +} + +static inline void vmathQSelect( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1, unsigned int select1 ) +{ + result->x = ( select1 )? quat1->x : quat0->x; + result->y = ( select1 )? quat1->y : quat0->y; + result->z = ( select1 )? quat1->z : quat0->z; + result->w = ( select1 )? quat1->w : quat0->w; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathQPrint( const VmathQuat *quat ) +{ + printf( "( %f %f %f %f )\n", quat->x, quat->y, quat->z, quat->w ); +} + +static inline void vmathQPrints( const VmathQuat *quat, const char *name ) +{ + printf( "%s: ( %f %f %f %f )\n", name, quat->x, quat->y, quat->z, quat->w ); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/scalar/c/quat_aos_v.h b/Extras/vectormathlibrary/include/vectormath/scalar/c/quat_aos_v.h new file mode 100644 index 0000000..b5a9e24 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/scalar/c/quat_aos_v.h @@ -0,0 +1,300 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_AOS_V_C_H +#define _VECTORMATH_QUAT_AOS_V_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline VmathQuat vmathQMakeFromElems_V( float _x, float _y, float _z, float _w ) +{ + VmathQuat result; + vmathQMakeFromElems(&result, _x, _y, _z, _w); + return result; +} + +static inline VmathQuat vmathQMakeFromV3Scalar_V( VmathVector3 xyz, float _w ) +{ + VmathQuat result; + vmathQMakeFromV3Scalar(&result, &xyz, _w); + return result; +} + +static inline VmathQuat vmathQMakeFromV4_V( VmathVector4 vec ) +{ + VmathQuat result; + vmathQMakeFromV4(&result, &vec); + return result; +} + +static inline VmathQuat vmathQMakeFromScalar_V( float scalar ) +{ + VmathQuat result; + vmathQMakeFromScalar(&result, scalar); + return result; +} + +static inline VmathQuat vmathQMakeIdentity_V( ) +{ + VmathQuat result; + vmathQMakeIdentity(&result); + return result; +} + +static inline VmathQuat vmathQLerp_V( float t, VmathQuat quat0, VmathQuat quat1 ) +{ + VmathQuat result; + vmathQLerp(&result, t, &quat0, &quat1); + return result; +} + +static inline VmathQuat vmathQSlerp_V( float t, VmathQuat unitQuat0, VmathQuat unitQuat1 ) +{ + VmathQuat result; + vmathQSlerp(&result, t, &unitQuat0, &unitQuat1); + return result; +} + +static inline VmathQuat vmathQSquad_V( float t, VmathQuat unitQuat0, VmathQuat unitQuat1, VmathQuat unitQuat2, VmathQuat unitQuat3 ) +{ + VmathQuat result; + vmathQSquad(&result, t, &unitQuat0, &unitQuat1, &unitQuat2, &unitQuat3); + return result; +} + +static inline void vmathQSetXYZ_V( VmathQuat *result, VmathVector3 vec ) +{ + vmathQSetXYZ(result, &vec); +} + +static inline VmathVector3 vmathQGetXYZ_V( VmathQuat quat ) +{ + VmathVector3 result; + vmathQGetXYZ(&result, &quat); + return result; +} + +static inline void vmathQSetX_V( VmathQuat *result, float _x ) +{ + vmathQSetX(result, _x); +} + +static inline float vmathQGetX_V( VmathQuat quat ) +{ + return vmathQGetX(&quat); +} + +static inline void vmathQSetY_V( VmathQuat *result, float _y ) +{ + vmathQSetY(result, _y); +} + +static inline float vmathQGetY_V( VmathQuat quat ) +{ + return vmathQGetY(&quat); +} + +static inline void vmathQSetZ_V( VmathQuat *result, float _z ) +{ + vmathQSetZ(result, _z); +} + +static inline float vmathQGetZ_V( VmathQuat quat ) +{ + return vmathQGetZ(&quat); +} + +static inline void vmathQSetW_V( VmathQuat *result, float _w ) +{ + vmathQSetW(result, _w); +} + +static inline float vmathQGetW_V( VmathQuat quat ) +{ + return vmathQGetW(&quat); +} + +static inline void vmathQSetElem_V( VmathQuat *result, int idx, float value ) +{ + vmathQSetElem(result, idx, value); +} + +static inline float vmathQGetElem_V( VmathQuat quat, int idx ) +{ + return vmathQGetElem(&quat, idx); +} + +static inline VmathQuat vmathQAdd_V( VmathQuat quat0, VmathQuat quat1 ) +{ + VmathQuat result; + vmathQAdd(&result, &quat0, &quat1); + return result; +} + +static inline VmathQuat vmathQSub_V( VmathQuat quat0, VmathQuat quat1 ) +{ + VmathQuat result; + vmathQSub(&result, &quat0, &quat1); + return result; +} + +static inline VmathQuat vmathQScalarMul_V( VmathQuat quat, float scalar ) +{ + VmathQuat result; + vmathQScalarMul(&result, &quat, scalar); + return result; +} + +static inline VmathQuat vmathQScalarDiv_V( VmathQuat quat, float scalar ) +{ + VmathQuat result; + vmathQScalarDiv(&result, &quat, scalar); + return result; +} + +static inline VmathQuat vmathQNeg_V( VmathQuat quat ) +{ + VmathQuat result; + vmathQNeg(&result, &quat); + return result; +} + +static inline float vmathQDot_V( VmathQuat quat0, VmathQuat quat1 ) +{ + return vmathQDot(&quat0, &quat1); +} + +static inline float vmathQNorm_V( VmathQuat quat ) +{ + return vmathQNorm(&quat); +} + +static inline float vmathQLength_V( VmathQuat quat ) +{ + return vmathQLength(&quat); +} + +static inline VmathQuat vmathQNormalize_V( VmathQuat quat ) +{ + VmathQuat result; + vmathQNormalize(&result, &quat); + return result; +} + +static inline VmathQuat vmathQMakeRotationArc_V( VmathVector3 unitVec0, VmathVector3 unitVec1 ) +{ + VmathQuat result; + vmathQMakeRotationArc(&result, &unitVec0, &unitVec1); + return result; +} + +static inline VmathQuat vmathQMakeRotationAxis_V( float radians, VmathVector3 unitVec ) +{ + VmathQuat result; + vmathQMakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathQuat vmathQMakeRotationX_V( float radians ) +{ + VmathQuat result; + vmathQMakeRotationX(&result, radians); + return result; +} + +static inline VmathQuat vmathQMakeRotationY_V( float radians ) +{ + VmathQuat result; + vmathQMakeRotationY(&result, radians); + return result; +} + +static inline VmathQuat vmathQMakeRotationZ_V( float radians ) +{ + VmathQuat result; + vmathQMakeRotationZ(&result, radians); + return result; +} + +static inline VmathQuat vmathQMul_V( VmathQuat quat0, VmathQuat quat1 ) +{ + VmathQuat result; + vmathQMul(&result, &quat0, &quat1); + return result; +} + +static inline VmathVector3 vmathQRotate_V( VmathQuat quat, VmathVector3 vec ) +{ + VmathVector3 result; + vmathQRotate(&result, &quat, &vec); + return result; +} + +static inline VmathQuat vmathQConj_V( VmathQuat quat ) +{ + VmathQuat result; + vmathQConj(&result, &quat); + return result; +} + +static inline VmathQuat vmathQSelect_V( VmathQuat quat0, VmathQuat quat1, unsigned int select1 ) +{ + VmathQuat result; + vmathQSelect(&result, &quat0, &quat1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathQPrint_V( VmathQuat quat ) +{ + vmathQPrint(&quat); +} + +static inline void vmathQPrints_V( VmathQuat quat, const char *name ) +{ + vmathQPrints(&quat, name); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/scalar/c/vec_aos.h b/Extras/vectormathlibrary/include/vectormath/scalar/c/vec_aos.h new file mode 100644 index 0000000..f0b0f43 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/scalar/c/vec_aos.h @@ -0,0 +1,971 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_AOS_C_H +#define _VECTORMATH_VEC_AOS_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + */ +#define _VECTORMATH_SLERP_TOL 0.999f + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline void vmathV3Copy( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; +} + +static inline void vmathV3MakeFromElems( VmathVector3 *result, float _x, float _y, float _z ) +{ + result->x = _x; + result->y = _y; + result->z = _z; +} + +static inline void vmathV3MakeFromP3( VmathVector3 *result, const VmathPoint3 *pnt ) +{ + result->x = pnt->x; + result->y = pnt->y; + result->z = pnt->z; +} + +static inline void vmathV3MakeFromScalar( VmathVector3 *result, float scalar ) +{ + result->x = scalar; + result->y = scalar; + result->z = scalar; +} + +static inline void vmathV3MakeXAxis( VmathVector3 *result ) +{ + vmathV3MakeFromElems( result, 1.0f, 0.0f, 0.0f ); +} + +static inline void vmathV3MakeYAxis( VmathVector3 *result ) +{ + vmathV3MakeFromElems( result, 0.0f, 1.0f, 0.0f ); +} + +static inline void vmathV3MakeZAxis( VmathVector3 *result ) +{ + vmathV3MakeFromElems( result, 0.0f, 0.0f, 1.0f ); +} + +static inline void vmathV3Lerp( VmathVector3 *result, float t, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + VmathVector3 tmpV3_0, tmpV3_1; + vmathV3Sub( &tmpV3_0, vec1, vec0 ); + vmathV3ScalarMul( &tmpV3_1, &tmpV3_0, t ); + vmathV3Add( result, vec0, &tmpV3_1 ); +} + +static inline void vmathV3Slerp( VmathVector3 *result, float t, const VmathVector3 *unitVec0, const VmathVector3 *unitVec1 ) +{ + VmathVector3 tmpV3_0, tmpV3_1; + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = vmathV3Dot( unitVec0, unitVec1 ); + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + vmathV3ScalarMul( &tmpV3_0, unitVec0, scale0 ); + vmathV3ScalarMul( &tmpV3_1, unitVec1, scale1 ); + vmathV3Add( result, &tmpV3_0, &tmpV3_1 ); +} + +static inline void vmathV3SetX( VmathVector3 *result, float _x ) +{ + result->x = _x; +} + +static inline float vmathV3GetX( const VmathVector3 *vec ) +{ + return vec->x; +} + +static inline void vmathV3SetY( VmathVector3 *result, float _y ) +{ + result->y = _y; +} + +static inline float vmathV3GetY( const VmathVector3 *vec ) +{ + return vec->y; +} + +static inline void vmathV3SetZ( VmathVector3 *result, float _z ) +{ + result->z = _z; +} + +static inline float vmathV3GetZ( const VmathVector3 *vec ) +{ + return vec->z; +} + +static inline void vmathV3SetElem( VmathVector3 *result, int idx, float value ) +{ + *(&result->x + idx) = value; +} + +static inline float vmathV3GetElem( const VmathVector3 *vec, int idx ) +{ + return *(&vec->x + idx); +} + +static inline void vmathV3Add( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->x = ( vec0->x + vec1->x ); + result->y = ( vec0->y + vec1->y ); + result->z = ( vec0->z + vec1->z ); +} + +static inline void vmathV3Sub( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->x = ( vec0->x - vec1->x ); + result->y = ( vec0->y - vec1->y ); + result->z = ( vec0->z - vec1->z ); +} + +static inline void vmathV3AddP3( VmathPoint3 *result, const VmathVector3 *vec, const VmathPoint3 *pnt1 ) +{ + result->x = ( vec->x + pnt1->x ); + result->y = ( vec->y + pnt1->y ); + result->z = ( vec->z + pnt1->z ); +} + +static inline void vmathV3ScalarMul( VmathVector3 *result, const VmathVector3 *vec, float scalar ) +{ + result->x = ( vec->x * scalar ); + result->y = ( vec->y * scalar ); + result->z = ( vec->z * scalar ); +} + +static inline void vmathV3ScalarDiv( VmathVector3 *result, const VmathVector3 *vec, float scalar ) +{ + result->x = ( vec->x / scalar ); + result->y = ( vec->y / scalar ); + result->z = ( vec->z / scalar ); +} + +static inline void vmathV3Neg( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->x = -vec->x; + result->y = -vec->y; + result->z = -vec->z; +} + +static inline void vmathV3MulPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->x = ( vec0->x * vec1->x ); + result->y = ( vec0->y * vec1->y ); + result->z = ( vec0->z * vec1->z ); +} + +static inline void vmathV3DivPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->x = ( vec0->x / vec1->x ); + result->y = ( vec0->y / vec1->y ); + result->z = ( vec0->z / vec1->z ); +} + +static inline void vmathV3RecipPerElem( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->x = ( 1.0f / vec->x ); + result->y = ( 1.0f / vec->y ); + result->z = ( 1.0f / vec->z ); +} + +static inline void vmathV3SqrtPerElem( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->x = sqrtf( vec->x ); + result->y = sqrtf( vec->y ); + result->z = sqrtf( vec->z ); +} + +static inline void vmathV3RsqrtPerElem( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->x = ( 1.0f / sqrtf( vec->x ) ); + result->y = ( 1.0f / sqrtf( vec->y ) ); + result->z = ( 1.0f / sqrtf( vec->z ) ); +} + +static inline void vmathV3AbsPerElem( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->x = fabsf( vec->x ); + result->y = fabsf( vec->y ); + result->z = fabsf( vec->z ); +} + +static inline void vmathV3CopySignPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->x = ( vec1->x < 0.0f )? -fabsf( vec0->x ) : fabsf( vec0->x ); + result->y = ( vec1->y < 0.0f )? -fabsf( vec0->y ) : fabsf( vec0->y ); + result->z = ( vec1->z < 0.0f )? -fabsf( vec0->z ) : fabsf( vec0->z ); +} + +static inline void vmathV3MaxPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->x = (vec0->x > vec1->x)? vec0->x : vec1->x; + result->y = (vec0->y > vec1->y)? vec0->y : vec1->y; + result->z = (vec0->z > vec1->z)? vec0->z : vec1->z; +} + +static inline float vmathV3MaxElem( const VmathVector3 *vec ) +{ + float result; + result = (vec->x > vec->y)? vec->x : vec->y; + result = (vec->z > result)? vec->z : result; + return result; +} + +static inline void vmathV3MinPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->x = (vec0->x < vec1->x)? vec0->x : vec1->x; + result->y = (vec0->y < vec1->y)? vec0->y : vec1->y; + result->z = (vec0->z < vec1->z)? vec0->z : vec1->z; +} + +static inline float vmathV3MinElem( const VmathVector3 *vec ) +{ + float result; + result = (vec->x < vec->y)? vec->x : vec->y; + result = (vec->z < result)? vec->z : result; + return result; +} + +static inline float vmathV3Sum( const VmathVector3 *vec ) +{ + float result; + result = ( vec->x + vec->y ); + result = ( result + vec->z ); + return result; +} + +static inline float vmathV3Dot( const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + float result; + result = ( vec0->x * vec1->x ); + result = ( result + ( vec0->y * vec1->y ) ); + result = ( result + ( vec0->z * vec1->z ) ); + return result; +} + +static inline float vmathV3LengthSqr( const VmathVector3 *vec ) +{ + float result; + result = ( vec->x * vec->x ); + result = ( result + ( vec->y * vec->y ) ); + result = ( result + ( vec->z * vec->z ) ); + return result; +} + +static inline float vmathV3Length( const VmathVector3 *vec ) +{ + return sqrtf( vmathV3LengthSqr( vec ) ); +} + +static inline void vmathV3Normalize( VmathVector3 *result, const VmathVector3 *vec ) +{ + float lenSqr, lenInv; + lenSqr = vmathV3LengthSqr( vec ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + result->x = ( vec->x * lenInv ); + result->y = ( vec->y * lenInv ); + result->z = ( vec->z * lenInv ); +} + +static inline void vmathV3Cross( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + float tmpX, tmpY, tmpZ; + tmpX = ( ( vec0->y * vec1->z ) - ( vec0->z * vec1->y ) ); + tmpY = ( ( vec0->z * vec1->x ) - ( vec0->x * vec1->z ) ); + tmpZ = ( ( vec0->x * vec1->y ) - ( vec0->y * vec1->x ) ); + vmathV3MakeFromElems( result, tmpX, tmpY, tmpZ ); +} + +static inline void vmathV3Select( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1, unsigned int select1 ) +{ + result->x = ( select1 )? vec1->x : vec0->x; + result->y = ( select1 )? vec1->y : vec0->y; + result->z = ( select1 )? vec1->z : vec0->z; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathV3Print( const VmathVector3 *vec ) +{ + printf( "( %f %f %f )\n", vec->x, vec->y, vec->z ); +} + +static inline void vmathV3Prints( const VmathVector3 *vec, const char *name ) +{ + printf( "%s: ( %f %f %f )\n", name, vec->x, vec->y, vec->z ); +} + +#endif + +static inline void vmathV4Copy( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; + result->w = vec->w; +} + +static inline void vmathV4MakeFromElems( VmathVector4 *result, float _x, float _y, float _z, float _w ) +{ + result->x = _x; + result->y = _y; + result->z = _z; + result->w = _w; +} + +static inline void vmathV4MakeFromV3Scalar( VmathVector4 *result, const VmathVector3 *xyz, float _w ) +{ + vmathV4SetXYZ( result, xyz ); + vmathV4SetW( result, _w ); +} + +static inline void vmathV4MakeFromV3( VmathVector4 *result, const VmathVector3 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; + result->w = 0.0f; +} + +static inline void vmathV4MakeFromP3( VmathVector4 *result, const VmathPoint3 *pnt ) +{ + result->x = pnt->x; + result->y = pnt->y; + result->z = pnt->z; + result->w = 1.0f; +} + +static inline void vmathV4MakeFromQ( VmathVector4 *result, const VmathQuat *quat ) +{ + result->x = quat->x; + result->y = quat->y; + result->z = quat->z; + result->w = quat->w; +} + +static inline void vmathV4MakeFromScalar( VmathVector4 *result, float scalar ) +{ + result->x = scalar; + result->y = scalar; + result->z = scalar; + result->w = scalar; +} + +static inline void vmathV4MakeXAxis( VmathVector4 *result ) +{ + vmathV4MakeFromElems( result, 1.0f, 0.0f, 0.0f, 0.0f ); +} + +static inline void vmathV4MakeYAxis( VmathVector4 *result ) +{ + vmathV4MakeFromElems( result, 0.0f, 1.0f, 0.0f, 0.0f ); +} + +static inline void vmathV4MakeZAxis( VmathVector4 *result ) +{ + vmathV4MakeFromElems( result, 0.0f, 0.0f, 1.0f, 0.0f ); +} + +static inline void vmathV4MakeWAxis( VmathVector4 *result ) +{ + vmathV4MakeFromElems( result, 0.0f, 0.0f, 0.0f, 1.0f ); +} + +static inline void vmathV4Lerp( VmathVector4 *result, float t, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + VmathVector4 tmpV4_0, tmpV4_1; + vmathV4Sub( &tmpV4_0, vec1, vec0 ); + vmathV4ScalarMul( &tmpV4_1, &tmpV4_0, t ); + vmathV4Add( result, vec0, &tmpV4_1 ); +} + +static inline void vmathV4Slerp( VmathVector4 *result, float t, const VmathVector4 *unitVec0, const VmathVector4 *unitVec1 ) +{ + VmathVector4 tmpV4_0, tmpV4_1; + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = vmathV4Dot( unitVec0, unitVec1 ); + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + vmathV4ScalarMul( &tmpV4_0, unitVec0, scale0 ); + vmathV4ScalarMul( &tmpV4_1, unitVec1, scale1 ); + vmathV4Add( result, &tmpV4_0, &tmpV4_1 ); +} + +static inline void vmathV4SetXYZ( VmathVector4 *result, const VmathVector3 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; +} + +static inline void vmathV4GetXYZ( VmathVector3 *result, const VmathVector4 *vec ) +{ + vmathV3MakeFromElems( result, vec->x, vec->y, vec->z ); +} + +static inline void vmathV4SetX( VmathVector4 *result, float _x ) +{ + result->x = _x; +} + +static inline float vmathV4GetX( const VmathVector4 *vec ) +{ + return vec->x; +} + +static inline void vmathV4SetY( VmathVector4 *result, float _y ) +{ + result->y = _y; +} + +static inline float vmathV4GetY( const VmathVector4 *vec ) +{ + return vec->y; +} + +static inline void vmathV4SetZ( VmathVector4 *result, float _z ) +{ + result->z = _z; +} + +static inline float vmathV4GetZ( const VmathVector4 *vec ) +{ + return vec->z; +} + +static inline void vmathV4SetW( VmathVector4 *result, float _w ) +{ + result->w = _w; +} + +static inline float vmathV4GetW( const VmathVector4 *vec ) +{ + return vec->w; +} + +static inline void vmathV4SetElem( VmathVector4 *result, int idx, float value ) +{ + *(&result->x + idx) = value; +} + +static inline float vmathV4GetElem( const VmathVector4 *vec, int idx ) +{ + return *(&vec->x + idx); +} + +static inline void vmathV4Add( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->x = ( vec0->x + vec1->x ); + result->y = ( vec0->y + vec1->y ); + result->z = ( vec0->z + vec1->z ); + result->w = ( vec0->w + vec1->w ); +} + +static inline void vmathV4Sub( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->x = ( vec0->x - vec1->x ); + result->y = ( vec0->y - vec1->y ); + result->z = ( vec0->z - vec1->z ); + result->w = ( vec0->w - vec1->w ); +} + +static inline void vmathV4ScalarMul( VmathVector4 *result, const VmathVector4 *vec, float scalar ) +{ + result->x = ( vec->x * scalar ); + result->y = ( vec->y * scalar ); + result->z = ( vec->z * scalar ); + result->w = ( vec->w * scalar ); +} + +static inline void vmathV4ScalarDiv( VmathVector4 *result, const VmathVector4 *vec, float scalar ) +{ + result->x = ( vec->x / scalar ); + result->y = ( vec->y / scalar ); + result->z = ( vec->z / scalar ); + result->w = ( vec->w / scalar ); +} + +static inline void vmathV4Neg( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->x = -vec->x; + result->y = -vec->y; + result->z = -vec->z; + result->w = -vec->w; +} + +static inline void vmathV4MulPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->x = ( vec0->x * vec1->x ); + result->y = ( vec0->y * vec1->y ); + result->z = ( vec0->z * vec1->z ); + result->w = ( vec0->w * vec1->w ); +} + +static inline void vmathV4DivPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->x = ( vec0->x / vec1->x ); + result->y = ( vec0->y / vec1->y ); + result->z = ( vec0->z / vec1->z ); + result->w = ( vec0->w / vec1->w ); +} + +static inline void vmathV4RecipPerElem( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->x = ( 1.0f / vec->x ); + result->y = ( 1.0f / vec->y ); + result->z = ( 1.0f / vec->z ); + result->w = ( 1.0f / vec->w ); +} + +static inline void vmathV4SqrtPerElem( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->x = sqrtf( vec->x ); + result->y = sqrtf( vec->y ); + result->z = sqrtf( vec->z ); + result->w = sqrtf( vec->w ); +} + +static inline void vmathV4RsqrtPerElem( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->x = ( 1.0f / sqrtf( vec->x ) ); + result->y = ( 1.0f / sqrtf( vec->y ) ); + result->z = ( 1.0f / sqrtf( vec->z ) ); + result->w = ( 1.0f / sqrtf( vec->w ) ); +} + +static inline void vmathV4AbsPerElem( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->x = fabsf( vec->x ); + result->y = fabsf( vec->y ); + result->z = fabsf( vec->z ); + result->w = fabsf( vec->w ); +} + +static inline void vmathV4CopySignPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->x = ( vec1->x < 0.0f )? -fabsf( vec0->x ) : fabsf( vec0->x ); + result->y = ( vec1->y < 0.0f )? -fabsf( vec0->y ) : fabsf( vec0->y ); + result->z = ( vec1->z < 0.0f )? -fabsf( vec0->z ) : fabsf( vec0->z ); + result->w = ( vec1->w < 0.0f )? -fabsf( vec0->w ) : fabsf( vec0->w ); +} + +static inline void vmathV4MaxPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->x = (vec0->x > vec1->x)? vec0->x : vec1->x; + result->y = (vec0->y > vec1->y)? vec0->y : vec1->y; + result->z = (vec0->z > vec1->z)? vec0->z : vec1->z; + result->w = (vec0->w > vec1->w)? vec0->w : vec1->w; +} + +static inline float vmathV4MaxElem( const VmathVector4 *vec ) +{ + float result; + result = (vec->x > vec->y)? vec->x : vec->y; + result = (vec->z > result)? vec->z : result; + result = (vec->w > result)? vec->w : result; + return result; +} + +static inline void vmathV4MinPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->x = (vec0->x < vec1->x)? vec0->x : vec1->x; + result->y = (vec0->y < vec1->y)? vec0->y : vec1->y; + result->z = (vec0->z < vec1->z)? vec0->z : vec1->z; + result->w = (vec0->w < vec1->w)? vec0->w : vec1->w; +} + +static inline float vmathV4MinElem( const VmathVector4 *vec ) +{ + float result; + result = (vec->x < vec->y)? vec->x : vec->y; + result = (vec->z < result)? vec->z : result; + result = (vec->w < result)? vec->w : result; + return result; +} + +static inline float vmathV4Sum( const VmathVector4 *vec ) +{ + float result; + result = ( vec->x + vec->y ); + result = ( result + vec->z ); + result = ( result + vec->w ); + return result; +} + +static inline float vmathV4Dot( const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + float result; + result = ( vec0->x * vec1->x ); + result = ( result + ( vec0->y * vec1->y ) ); + result = ( result + ( vec0->z * vec1->z ) ); + result = ( result + ( vec0->w * vec1->w ) ); + return result; +} + +static inline float vmathV4LengthSqr( const VmathVector4 *vec ) +{ + float result; + result = ( vec->x * vec->x ); + result = ( result + ( vec->y * vec->y ) ); + result = ( result + ( vec->z * vec->z ) ); + result = ( result + ( vec->w * vec->w ) ); + return result; +} + +static inline float vmathV4Length( const VmathVector4 *vec ) +{ + return sqrtf( vmathV4LengthSqr( vec ) ); +} + +static inline void vmathV4Normalize( VmathVector4 *result, const VmathVector4 *vec ) +{ + float lenSqr, lenInv; + lenSqr = vmathV4LengthSqr( vec ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + result->x = ( vec->x * lenInv ); + result->y = ( vec->y * lenInv ); + result->z = ( vec->z * lenInv ); + result->w = ( vec->w * lenInv ); +} + +static inline void vmathV4Select( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1, unsigned int select1 ) +{ + result->x = ( select1 )? vec1->x : vec0->x; + result->y = ( select1 )? vec1->y : vec0->y; + result->z = ( select1 )? vec1->z : vec0->z; + result->w = ( select1 )? vec1->w : vec0->w; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathV4Print( const VmathVector4 *vec ) +{ + printf( "( %f %f %f %f )\n", vec->x, vec->y, vec->z, vec->w ); +} + +static inline void vmathV4Prints( const VmathVector4 *vec, const char *name ) +{ + printf( "%s: ( %f %f %f %f )\n", name, vec->x, vec->y, vec->z, vec->w ); +} + +#endif + +static inline void vmathP3Copy( VmathPoint3 *result, const VmathPoint3 *pnt ) +{ + result->x = pnt->x; + result->y = pnt->y; + result->z = pnt->z; +} + +static inline void vmathP3MakeFromElems( VmathPoint3 *result, float _x, float _y, float _z ) +{ + result->x = _x; + result->y = _y; + result->z = _z; +} + +static inline void vmathP3MakeFromV3( VmathPoint3 *result, const VmathVector3 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; +} + +static inline void vmathP3MakeFromScalar( VmathPoint3 *result, float scalar ) +{ + result->x = scalar; + result->y = scalar; + result->z = scalar; +} + +static inline void vmathP3Lerp( VmathPoint3 *result, float t, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + VmathVector3 tmpV3_0, tmpV3_1; + vmathP3Sub( &tmpV3_0, pnt1, pnt0 ); + vmathV3ScalarMul( &tmpV3_1, &tmpV3_0, t ); + vmathP3AddV3( result, pnt0, &tmpV3_1 ); +} + +static inline void vmathP3SetX( VmathPoint3 *result, float _x ) +{ + result->x = _x; +} + +static inline float vmathP3GetX( const VmathPoint3 *pnt ) +{ + return pnt->x; +} + +static inline void vmathP3SetY( VmathPoint3 *result, float _y ) +{ + result->y = _y; +} + +static inline float vmathP3GetY( const VmathPoint3 *pnt ) +{ + return pnt->y; +} + +static inline void vmathP3SetZ( VmathPoint3 *result, float _z ) +{ + result->z = _z; +} + +static inline float vmathP3GetZ( const VmathPoint3 *pnt ) +{ + return pnt->z; +} + +static inline void vmathP3SetElem( VmathPoint3 *result, int idx, float value ) +{ + *(&result->x + idx) = value; +} + +static inline float vmathP3GetElem( const VmathPoint3 *pnt, int idx ) +{ + return *(&pnt->x + idx); +} + +static inline void vmathP3Sub( VmathVector3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->x = ( pnt0->x - pnt1->x ); + result->y = ( pnt0->y - pnt1->y ); + result->z = ( pnt0->z - pnt1->z ); +} + +static inline void vmathP3AddV3( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *vec1 ) +{ + result->x = ( pnt->x + vec1->x ); + result->y = ( pnt->y + vec1->y ); + result->z = ( pnt->z + vec1->z ); +} + +static inline void vmathP3SubV3( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *vec1 ) +{ + result->x = ( pnt->x - vec1->x ); + result->y = ( pnt->y - vec1->y ); + result->z = ( pnt->z - vec1->z ); +} + +static inline void vmathP3MulPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->x = ( pnt0->x * pnt1->x ); + result->y = ( pnt0->y * pnt1->y ); + result->z = ( pnt0->z * pnt1->z ); +} + +static inline void vmathP3DivPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->x = ( pnt0->x / pnt1->x ); + result->y = ( pnt0->y / pnt1->y ); + result->z = ( pnt0->z / pnt1->z ); +} + +static inline void vmathP3RecipPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ) +{ + result->x = ( 1.0f / pnt->x ); + result->y = ( 1.0f / pnt->y ); + result->z = ( 1.0f / pnt->z ); +} + +static inline void vmathP3SqrtPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ) +{ + result->x = sqrtf( pnt->x ); + result->y = sqrtf( pnt->y ); + result->z = sqrtf( pnt->z ); +} + +static inline void vmathP3RsqrtPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ) +{ + result->x = ( 1.0f / sqrtf( pnt->x ) ); + result->y = ( 1.0f / sqrtf( pnt->y ) ); + result->z = ( 1.0f / sqrtf( pnt->z ) ); +} + +static inline void vmathP3AbsPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ) +{ + result->x = fabsf( pnt->x ); + result->y = fabsf( pnt->y ); + result->z = fabsf( pnt->z ); +} + +static inline void vmathP3CopySignPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->x = ( pnt1->x < 0.0f )? -fabsf( pnt0->x ) : fabsf( pnt0->x ); + result->y = ( pnt1->y < 0.0f )? -fabsf( pnt0->y ) : fabsf( pnt0->y ); + result->z = ( pnt1->z < 0.0f )? -fabsf( pnt0->z ) : fabsf( pnt0->z ); +} + +static inline void vmathP3MaxPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->x = (pnt0->x > pnt1->x)? pnt0->x : pnt1->x; + result->y = (pnt0->y > pnt1->y)? pnt0->y : pnt1->y; + result->z = (pnt0->z > pnt1->z)? pnt0->z : pnt1->z; +} + +static inline float vmathP3MaxElem( const VmathPoint3 *pnt ) +{ + float result; + result = (pnt->x > pnt->y)? pnt->x : pnt->y; + result = (pnt->z > result)? pnt->z : result; + return result; +} + +static inline void vmathP3MinPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->x = (pnt0->x < pnt1->x)? pnt0->x : pnt1->x; + result->y = (pnt0->y < pnt1->y)? pnt0->y : pnt1->y; + result->z = (pnt0->z < pnt1->z)? pnt0->z : pnt1->z; +} + +static inline float vmathP3MinElem( const VmathPoint3 *pnt ) +{ + float result; + result = (pnt->x < pnt->y)? pnt->x : pnt->y; + result = (pnt->z < result)? pnt->z : result; + return result; +} + +static inline float vmathP3Sum( const VmathPoint3 *pnt ) +{ + float result; + result = ( pnt->x + pnt->y ); + result = ( result + pnt->z ); + return result; +} + +static inline void vmathP3Scale( VmathPoint3 *result, const VmathPoint3 *pnt, float scaleVal ) +{ + VmathPoint3 tmpP3_0; + vmathP3MakeFromScalar( &tmpP3_0, scaleVal ); + vmathP3MulPerElem( result, pnt, &tmpP3_0 ); +} + +static inline void vmathP3NonUniformScale( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *scaleVec ) +{ + VmathPoint3 tmpP3_0; + vmathP3MakeFromV3( &tmpP3_0, scaleVec ); + vmathP3MulPerElem( result, pnt, &tmpP3_0 ); +} + +static inline float vmathP3Projection( const VmathPoint3 *pnt, const VmathVector3 *unitVec ) +{ + float result; + result = ( pnt->x * unitVec->x ); + result = ( result + ( pnt->y * unitVec->y ) ); + result = ( result + ( pnt->z * unitVec->z ) ); + return result; +} + +static inline float vmathP3DistSqrFromOrigin( const VmathPoint3 *pnt ) +{ + VmathVector3 tmpV3_0; + vmathV3MakeFromP3( &tmpV3_0, pnt ); + return vmathV3LengthSqr( &tmpV3_0 ); +} + +static inline float vmathP3DistFromOrigin( const VmathPoint3 *pnt ) +{ + VmathVector3 tmpV3_0; + vmathV3MakeFromP3( &tmpV3_0, pnt ); + return vmathV3Length( &tmpV3_0 ); +} + +static inline float vmathP3DistSqr( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + VmathVector3 tmpV3_0; + vmathP3Sub( &tmpV3_0, pnt1, pnt0 ); + return vmathV3LengthSqr( &tmpV3_0 ); +} + +static inline float vmathP3Dist( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + VmathVector3 tmpV3_0; + vmathP3Sub( &tmpV3_0, pnt1, pnt0 ); + return vmathV3Length( &tmpV3_0 ); +} + +static inline void vmathP3Select( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, unsigned int select1 ) +{ + result->x = ( select1 )? pnt1->x : pnt0->x; + result->y = ( select1 )? pnt1->y : pnt0->y; + result->z = ( select1 )? pnt1->z : pnt0->z; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathP3Print( const VmathPoint3 *pnt ) +{ + printf( "( %f %f %f )\n", pnt->x, pnt->y, pnt->z ); +} + +static inline void vmathP3Prints( const VmathPoint3 *pnt, const char *name ) +{ + printf( "%s: ( %f %f %f )\n", name, pnt->x, pnt->y, pnt->z ); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/scalar/c/vec_aos_v.h b/Extras/vectormathlibrary/include/vectormath/scalar/c/vec_aos_v.h new file mode 100644 index 0000000..75c4937 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/scalar/c/vec_aos_v.h @@ -0,0 +1,848 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_AOS_V_C_H +#define _VECTORMATH_VEC_AOS_V_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + */ +#define _VECTORMATH_SLERP_TOL 0.999f + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline VmathVector3 vmathV3MakeFromElems_V( float _x, float _y, float _z ) +{ + VmathVector3 result; + vmathV3MakeFromElems(&result, _x, _y, _z); + return result; +} + +static inline VmathVector3 vmathV3MakeFromP3_V( VmathPoint3 pnt ) +{ + VmathVector3 result; + vmathV3MakeFromP3(&result, &pnt); + return result; +} + +static inline VmathVector3 vmathV3MakeFromScalar_V( float scalar ) +{ + VmathVector3 result; + vmathV3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathVector3 vmathV3MakeXAxis_V( ) +{ + VmathVector3 result; + vmathV3MakeXAxis(&result); + return result; +} + +static inline VmathVector3 vmathV3MakeYAxis_V( ) +{ + VmathVector3 result; + vmathV3MakeYAxis(&result); + return result; +} + +static inline VmathVector3 vmathV3MakeZAxis_V( ) +{ + VmathVector3 result; + vmathV3MakeZAxis(&result); + return result; +} + +static inline VmathVector3 vmathV3Lerp_V( float t, VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3Lerp(&result, t, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3Slerp_V( float t, VmathVector3 unitVec0, VmathVector3 unitVec1 ) +{ + VmathVector3 result; + vmathV3Slerp(&result, t, &unitVec0, &unitVec1); + return result; +} + +static inline void vmathV3SetX_V( VmathVector3 *result, float _x ) +{ + vmathV3SetX(result, _x); +} + +static inline float vmathV3GetX_V( VmathVector3 vec ) +{ + return vmathV3GetX(&vec); +} + +static inline void vmathV3SetY_V( VmathVector3 *result, float _y ) +{ + vmathV3SetY(result, _y); +} + +static inline float vmathV3GetY_V( VmathVector3 vec ) +{ + return vmathV3GetY(&vec); +} + +static inline void vmathV3SetZ_V( VmathVector3 *result, float _z ) +{ + vmathV3SetZ(result, _z); +} + +static inline float vmathV3GetZ_V( VmathVector3 vec ) +{ + return vmathV3GetZ(&vec); +} + +static inline void vmathV3SetElem_V( VmathVector3 *result, int idx, float value ) +{ + vmathV3SetElem(result, idx, value); +} + +static inline float vmathV3GetElem_V( VmathVector3 vec, int idx ) +{ + return vmathV3GetElem(&vec, idx); +} + +static inline VmathVector3 vmathV3Add_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3Add(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3Sub_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3Sub(&result, &vec0, &vec1); + return result; +} + +static inline VmathPoint3 vmathV3AddP3_V( VmathVector3 vec, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathV3AddP3(&result, &vec, &pnt1); + return result; +} + +static inline VmathVector3 vmathV3ScalarMul_V( VmathVector3 vec, float scalar ) +{ + VmathVector3 result; + vmathV3ScalarMul(&result, &vec, scalar); + return result; +} + +static inline VmathVector3 vmathV3ScalarDiv_V( VmathVector3 vec, float scalar ) +{ + VmathVector3 result; + vmathV3ScalarDiv(&result, &vec, scalar); + return result; +} + +static inline VmathVector3 vmathV3Neg_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3Neg(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3MulPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3MulPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3DivPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3DivPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3RecipPerElem_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3RecipPerElem(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3SqrtPerElem_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3SqrtPerElem(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3RsqrtPerElem_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3RsqrtPerElem(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3AbsPerElem_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3AbsPerElem(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3CopySignPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3CopySignPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3MaxPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3MaxPerElem(&result, &vec0, &vec1); + return result; +} + +static inline float vmathV3MaxElem_V( VmathVector3 vec ) +{ + return vmathV3MaxElem(&vec); +} + +static inline VmathVector3 vmathV3MinPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3MinPerElem(&result, &vec0, &vec1); + return result; +} + +static inline float vmathV3MinElem_V( VmathVector3 vec ) +{ + return vmathV3MinElem(&vec); +} + +static inline float vmathV3Sum_V( VmathVector3 vec ) +{ + return vmathV3Sum(&vec); +} + +static inline float vmathV3Dot_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + return vmathV3Dot(&vec0, &vec1); +} + +static inline float vmathV3LengthSqr_V( VmathVector3 vec ) +{ + return vmathV3LengthSqr(&vec); +} + +static inline float vmathV3Length_V( VmathVector3 vec ) +{ + return vmathV3Length(&vec); +} + +static inline VmathVector3 vmathV3Normalize_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3Normalize(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3Cross_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3Cross(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3Select_V( VmathVector3 vec0, VmathVector3 vec1, unsigned int select1 ) +{ + VmathVector3 result; + vmathV3Select(&result, &vec0, &vec1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathV3Print_V( VmathVector3 vec ) +{ + vmathV3Print(&vec); +} + +static inline void vmathV3Prints_V( VmathVector3 vec, const char *name ) +{ + vmathV3Prints(&vec, name); +} + +#endif + +static inline VmathVector4 vmathV4MakeFromElems_V( float _x, float _y, float _z, float _w ) +{ + VmathVector4 result; + vmathV4MakeFromElems(&result, _x, _y, _z, _w); + return result; +} + +static inline VmathVector4 vmathV4MakeFromV3Scalar_V( VmathVector3 xyz, float _w ) +{ + VmathVector4 result; + vmathV4MakeFromV3Scalar(&result, &xyz, _w); + return result; +} + +static inline VmathVector4 vmathV4MakeFromV3_V( VmathVector3 vec ) +{ + VmathVector4 result; + vmathV4MakeFromV3(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4MakeFromP3_V( VmathPoint3 pnt ) +{ + VmathVector4 result; + vmathV4MakeFromP3(&result, &pnt); + return result; +} + +static inline VmathVector4 vmathV4MakeFromQ_V( VmathQuat quat ) +{ + VmathVector4 result; + vmathV4MakeFromQ(&result, &quat); + return result; +} + +static inline VmathVector4 vmathV4MakeFromScalar_V( float scalar ) +{ + VmathVector4 result; + vmathV4MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathVector4 vmathV4MakeXAxis_V( ) +{ + VmathVector4 result; + vmathV4MakeXAxis(&result); + return result; +} + +static inline VmathVector4 vmathV4MakeYAxis_V( ) +{ + VmathVector4 result; + vmathV4MakeYAxis(&result); + return result; +} + +static inline VmathVector4 vmathV4MakeZAxis_V( ) +{ + VmathVector4 result; + vmathV4MakeZAxis(&result); + return result; +} + +static inline VmathVector4 vmathV4MakeWAxis_V( ) +{ + VmathVector4 result; + vmathV4MakeWAxis(&result); + return result; +} + +static inline VmathVector4 vmathV4Lerp_V( float t, VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4Lerp(&result, t, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4Slerp_V( float t, VmathVector4 unitVec0, VmathVector4 unitVec1 ) +{ + VmathVector4 result; + vmathV4Slerp(&result, t, &unitVec0, &unitVec1); + return result; +} + +static inline void vmathV4SetXYZ_V( VmathVector4 *result, VmathVector3 vec ) +{ + vmathV4SetXYZ(result, &vec); +} + +static inline VmathVector3 vmathV4GetXYZ_V( VmathVector4 vec ) +{ + VmathVector3 result; + vmathV4GetXYZ(&result, &vec); + return result; +} + +static inline void vmathV4SetX_V( VmathVector4 *result, float _x ) +{ + vmathV4SetX(result, _x); +} + +static inline float vmathV4GetX_V( VmathVector4 vec ) +{ + return vmathV4GetX(&vec); +} + +static inline void vmathV4SetY_V( VmathVector4 *result, float _y ) +{ + vmathV4SetY(result, _y); +} + +static inline float vmathV4GetY_V( VmathVector4 vec ) +{ + return vmathV4GetY(&vec); +} + +static inline void vmathV4SetZ_V( VmathVector4 *result, float _z ) +{ + vmathV4SetZ(result, _z); +} + +static inline float vmathV4GetZ_V( VmathVector4 vec ) +{ + return vmathV4GetZ(&vec); +} + +static inline void vmathV4SetW_V( VmathVector4 *result, float _w ) +{ + vmathV4SetW(result, _w); +} + +static inline float vmathV4GetW_V( VmathVector4 vec ) +{ + return vmathV4GetW(&vec); +} + +static inline void vmathV4SetElem_V( VmathVector4 *result, int idx, float value ) +{ + vmathV4SetElem(result, idx, value); +} + +static inline float vmathV4GetElem_V( VmathVector4 vec, int idx ) +{ + return vmathV4GetElem(&vec, idx); +} + +static inline VmathVector4 vmathV4Add_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4Add(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4Sub_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4Sub(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4ScalarMul_V( VmathVector4 vec, float scalar ) +{ + VmathVector4 result; + vmathV4ScalarMul(&result, &vec, scalar); + return result; +} + +static inline VmathVector4 vmathV4ScalarDiv_V( VmathVector4 vec, float scalar ) +{ + VmathVector4 result; + vmathV4ScalarDiv(&result, &vec, scalar); + return result; +} + +static inline VmathVector4 vmathV4Neg_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4Neg(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4MulPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4MulPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4DivPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4DivPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4RecipPerElem_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4RecipPerElem(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4SqrtPerElem_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4SqrtPerElem(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4RsqrtPerElem_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4RsqrtPerElem(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4AbsPerElem_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4AbsPerElem(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4CopySignPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4CopySignPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4MaxPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4MaxPerElem(&result, &vec0, &vec1); + return result; +} + +static inline float vmathV4MaxElem_V( VmathVector4 vec ) +{ + return vmathV4MaxElem(&vec); +} + +static inline VmathVector4 vmathV4MinPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4MinPerElem(&result, &vec0, &vec1); + return result; +} + +static inline float vmathV4MinElem_V( VmathVector4 vec ) +{ + return vmathV4MinElem(&vec); +} + +static inline float vmathV4Sum_V( VmathVector4 vec ) +{ + return vmathV4Sum(&vec); +} + +static inline float vmathV4Dot_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + return vmathV4Dot(&vec0, &vec1); +} + +static inline float vmathV4LengthSqr_V( VmathVector4 vec ) +{ + return vmathV4LengthSqr(&vec); +} + +static inline float vmathV4Length_V( VmathVector4 vec ) +{ + return vmathV4Length(&vec); +} + +static inline VmathVector4 vmathV4Normalize_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4Normalize(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4Select_V( VmathVector4 vec0, VmathVector4 vec1, unsigned int select1 ) +{ + VmathVector4 result; + vmathV4Select(&result, &vec0, &vec1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathV4Print_V( VmathVector4 vec ) +{ + vmathV4Print(&vec); +} + +static inline void vmathV4Prints_V( VmathVector4 vec, const char *name ) +{ + vmathV4Prints(&vec, name); +} + +#endif + +static inline VmathPoint3 vmathP3MakeFromElems_V( float _x, float _y, float _z ) +{ + VmathPoint3 result; + vmathP3MakeFromElems(&result, _x, _y, _z); + return result; +} + +static inline VmathPoint3 vmathP3MakeFromV3_V( VmathVector3 vec ) +{ + VmathPoint3 result; + vmathP3MakeFromV3(&result, &vec); + return result; +} + +static inline VmathPoint3 vmathP3MakeFromScalar_V( float scalar ) +{ + VmathPoint3 result; + vmathP3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathPoint3 vmathP3Lerp_V( float t, VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3Lerp(&result, t, &pnt0, &pnt1); + return result; +} + +static inline void vmathP3SetX_V( VmathPoint3 *result, float _x ) +{ + vmathP3SetX(result, _x); +} + +static inline float vmathP3GetX_V( VmathPoint3 pnt ) +{ + return vmathP3GetX(&pnt); +} + +static inline void vmathP3SetY_V( VmathPoint3 *result, float _y ) +{ + vmathP3SetY(result, _y); +} + +static inline float vmathP3GetY_V( VmathPoint3 pnt ) +{ + return vmathP3GetY(&pnt); +} + +static inline void vmathP3SetZ_V( VmathPoint3 *result, float _z ) +{ + vmathP3SetZ(result, _z); +} + +static inline float vmathP3GetZ_V( VmathPoint3 pnt ) +{ + return vmathP3GetZ(&pnt); +} + +static inline void vmathP3SetElem_V( VmathPoint3 *result, int idx, float value ) +{ + vmathP3SetElem(result, idx, value); +} + +static inline float vmathP3GetElem_V( VmathPoint3 pnt, int idx ) +{ + return vmathP3GetElem(&pnt, idx); +} + +static inline VmathVector3 vmathP3Sub_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathVector3 result; + vmathP3Sub(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathPoint3 vmathP3AddV3_V( VmathPoint3 pnt, VmathVector3 vec1 ) +{ + VmathPoint3 result; + vmathP3AddV3(&result, &pnt, &vec1); + return result; +} + +static inline VmathPoint3 vmathP3SubV3_V( VmathPoint3 pnt, VmathVector3 vec1 ) +{ + VmathPoint3 result; + vmathP3SubV3(&result, &pnt, &vec1); + return result; +} + +static inline VmathPoint3 vmathP3MulPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3MulPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathPoint3 vmathP3DivPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3DivPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathPoint3 vmathP3RecipPerElem_V( VmathPoint3 pnt ) +{ + VmathPoint3 result; + vmathP3RecipPerElem(&result, &pnt); + return result; +} + +static inline VmathPoint3 vmathP3SqrtPerElem_V( VmathPoint3 pnt ) +{ + VmathPoint3 result; + vmathP3SqrtPerElem(&result, &pnt); + return result; +} + +static inline VmathPoint3 vmathP3RsqrtPerElem_V( VmathPoint3 pnt ) +{ + VmathPoint3 result; + vmathP3RsqrtPerElem(&result, &pnt); + return result; +} + +static inline VmathPoint3 vmathP3AbsPerElem_V( VmathPoint3 pnt ) +{ + VmathPoint3 result; + vmathP3AbsPerElem(&result, &pnt); + return result; +} + +static inline VmathPoint3 vmathP3CopySignPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3CopySignPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathPoint3 vmathP3MaxPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3MaxPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline float vmathP3MaxElem_V( VmathPoint3 pnt ) +{ + return vmathP3MaxElem(&pnt); +} + +static inline VmathPoint3 vmathP3MinPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3MinPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline float vmathP3MinElem_V( VmathPoint3 pnt ) +{ + return vmathP3MinElem(&pnt); +} + +static inline float vmathP3Sum_V( VmathPoint3 pnt ) +{ + return vmathP3Sum(&pnt); +} + +static inline VmathPoint3 vmathP3Scale_V( VmathPoint3 pnt, float scaleVal ) +{ + VmathPoint3 result; + vmathP3Scale(&result, &pnt, scaleVal); + return result; +} + +static inline VmathPoint3 vmathP3NonUniformScale_V( VmathPoint3 pnt, VmathVector3 scaleVec ) +{ + VmathPoint3 result; + vmathP3NonUniformScale(&result, &pnt, &scaleVec); + return result; +} + +static inline float vmathP3Projection_V( VmathPoint3 pnt, VmathVector3 unitVec ) +{ + return vmathP3Projection(&pnt, &unitVec); +} + +static inline float vmathP3DistSqrFromOrigin_V( VmathPoint3 pnt ) +{ + return vmathP3DistSqrFromOrigin(&pnt); +} + +static inline float vmathP3DistFromOrigin_V( VmathPoint3 pnt ) +{ + return vmathP3DistFromOrigin(&pnt); +} + +static inline float vmathP3DistSqr_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + return vmathP3DistSqr(&pnt0, &pnt1); +} + +static inline float vmathP3Dist_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + return vmathP3Dist(&pnt0, &pnt1); +} + +static inline VmathPoint3 vmathP3Select_V( VmathPoint3 pnt0, VmathPoint3 pnt1, unsigned int select1 ) +{ + VmathPoint3 result; + vmathP3Select(&result, &pnt0, &pnt1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathP3Print_V( VmathPoint3 pnt ) +{ + vmathP3Print(&pnt); +} + +static inline void vmathP3Prints_V( VmathPoint3 pnt, const char *name ) +{ + vmathP3Prints(&pnt, name); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/scalar/c/vectormath_aos.h b/Extras/vectormathlibrary/include/vectormath/scalar/c/vectormath_aos.h new file mode 100644 index 0000000..26bee0b --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/scalar/c/vectormath_aos.h @@ -0,0 +1,1879 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_AOS_C_SCALAR_H +#define _VECTORMATH_AOS_C_SCALAR_H + +#include + +#ifdef _VECTORMATH_DEBUG +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef _VECTORMATH_AOS_C_TYPES_H +#define _VECTORMATH_AOS_C_TYPES_H + +/* A 3-D vector in array-of-structures format + */ +typedef struct _VmathVector3 +{ + float x; + float y; + float z; +#ifndef __GNUC__ + float d; +#endif +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +VmathVector3; + +/* A 4-D vector in array-of-structures format + */ +typedef struct _VmathVector4 +{ + float x; + float y; + float z; + float w; +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +VmathVector4; + +/* A 3-D point in array-of-structures format + */ +typedef struct _VmathPoint3 +{ + float x; + float y; + float z; +#ifndef __GNUC__ + float d; +#endif +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +VmathPoint3; + +/* A quaternion in array-of-structures format + */ +typedef struct _VmathQuat +{ + float x; + float y; + float z; + float w; +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +VmathQuat; + +/* A 3x3 matrix in array-of-structures format + */ +typedef struct _VmathMatrix3 +{ + VmathVector3 col0; + VmathVector3 col1; + VmathVector3 col2; +} VmathMatrix3; + +/* A 4x4 matrix in array-of-structures format + */ +typedef struct _VmathMatrix4 +{ + VmathVector4 col0; + VmathVector4 col1; + VmathVector4 col2; + VmathVector4 col3; +} VmathMatrix4; + +/* A 3x4 transformation matrix in array-of-structures format + */ +typedef struct _VmathTransform3 +{ + VmathVector3 col0; + VmathVector3 col1; + VmathVector3 col2; + VmathVector3 col3; +} VmathTransform3; + +#endif + +/* + * Copy a 3-D vector + */ +static inline void vmathV3Copy( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Construct a 3-D vector from x, y, and z elements + */ +static inline void vmathV3MakeFromElems( VmathVector3 *result, float x, float y, float z ); + +/* + * Copy elements from a 3-D point into a 3-D vector + */ +static inline void vmathV3MakeFromP3( VmathVector3 *result, const VmathPoint3 *pnt ); + +/* + * Set all elements of a 3-D vector to the same scalar value + */ +static inline void vmathV3MakeFromScalar( VmathVector3 *result, float scalar ); + +/* + * Set the x element of a 3-D vector + */ +static inline void vmathV3SetX( VmathVector3 *result, float x ); + +/* + * Set the y element of a 3-D vector + */ +static inline void vmathV3SetY( VmathVector3 *result, float y ); + +/* + * Set the z element of a 3-D vector + */ +static inline void vmathV3SetZ( VmathVector3 *result, float z ); + +/* + * Get the x element of a 3-D vector + */ +static inline float vmathV3GetX( const VmathVector3 *vec ); + +/* + * Get the y element of a 3-D vector + */ +static inline float vmathV3GetY( const VmathVector3 *vec ); + +/* + * Get the z element of a 3-D vector + */ +static inline float vmathV3GetZ( const VmathVector3 *vec ); + +/* + * Set an x, y, or z element of a 3-D vector by index + */ +static inline void vmathV3SetElem( VmathVector3 *result, int idx, float value ); + +/* + * Get an x, y, or z element of a 3-D vector by index + */ +static inline float vmathV3GetElem( const VmathVector3 *vec, int idx ); + +/* + * Add two 3-D vectors + */ +static inline void vmathV3Add( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Subtract a 3-D vector from another 3-D vector + */ +static inline void vmathV3Sub( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Add a 3-D vector to a 3-D point + */ +static inline void vmathV3AddP3( VmathPoint3 *result, const VmathVector3 *vec, const VmathPoint3 *pnt ); + +/* + * Multiply a 3-D vector by a scalar + */ +static inline void vmathV3ScalarMul( VmathVector3 *result, const VmathVector3 *vec, float scalar ); + +/* + * Divide a 3-D vector by a scalar + */ +static inline void vmathV3ScalarDiv( VmathVector3 *result, const VmathVector3 *vec, float scalar ); + +/* + * Negate all elements of a 3-D vector + */ +static inline void vmathV3Neg( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Construct x axis + */ +static inline void vmathV3MakeXAxis( VmathVector3 *result ); + +/* + * Construct y axis + */ +static inline void vmathV3MakeYAxis( VmathVector3 *result ); + +/* + * Construct z axis + */ +static inline void vmathV3MakeZAxis( VmathVector3 *result ); + +/* + * Multiply two 3-D vectors per element + */ +static inline void vmathV3MulPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Divide two 3-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline void vmathV3DivPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Compute the reciprocal of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline void vmathV3RecipPerElem( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Compute the square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline void vmathV3SqrtPerElem( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Compute the reciprocal square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline void vmathV3RsqrtPerElem( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Compute the absolute value of a 3-D vector per element + */ +static inline void vmathV3AbsPerElem( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Copy sign from one 3-D vector to another, per element + */ +static inline void vmathV3CopySignPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Maximum of two 3-D vectors per element + */ +static inline void vmathV3MaxPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Minimum of two 3-D vectors per element + */ +static inline void vmathV3MinPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Maximum element of a 3-D vector + */ +static inline float vmathV3MaxElem( const VmathVector3 *vec ); + +/* + * Minimum element of a 3-D vector + */ +static inline float vmathV3MinElem( const VmathVector3 *vec ); + +/* + * Compute the sum of all elements of a 3-D vector + */ +static inline float vmathV3Sum( const VmathVector3 *vec ); + +/* + * Compute the dot product of two 3-D vectors + */ +static inline float vmathV3Dot( const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Compute the square of the length of a 3-D vector + */ +static inline float vmathV3LengthSqr( const VmathVector3 *vec ); + +/* + * Compute the length of a 3-D vector + */ +static inline float vmathV3Length( const VmathVector3 *vec ); + +/* + * Normalize a 3-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline void vmathV3Normalize( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Compute cross product of two 3-D vectors + */ +static inline void vmathV3Cross( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Outer product of two 3-D vectors + */ +static inline void vmathV3Outer( VmathMatrix3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Pre-multiply a row vector by a 3x3 matrix + */ +static inline void vmathV3RowMul( VmathVector3 *result, const VmathVector3 *vec, const VmathMatrix3 *mat ); + +/* + * Cross-product matrix of a 3-D vector + */ +static inline void vmathV3CrossMatrix( VmathMatrix3 *result, const VmathVector3 *vec ); + +/* + * Create cross-product matrix and multiply + * NOTE: + * Faster than separately creating a cross-product matrix and multiplying. + */ +static inline void vmathV3CrossMatrixMul( VmathMatrix3 *result, const VmathVector3 *vec, const VmathMatrix3 *mat ); + +/* + * Linear interpolation between two 3-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathV3Lerp( VmathVector3 *result, float t, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Spherical linear interpolation between two 3-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline void vmathV3Slerp( VmathVector3 *result, float t, const VmathVector3 *unitVec0, const VmathVector3 *unitVec1 ); + +/* + * Conditionally select between two 3-D vectors + */ +static inline void vmathV3Select( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV3Print( const VmathVector3 *vec ); + +/* + * Print a 3-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV3Prints( const VmathVector3 *vec, const char *name ); + +#endif + +/* + * Copy a 4-D vector + */ +static inline void vmathV4Copy( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Construct a 4-D vector from x, y, z, and w elements + */ +static inline void vmathV4MakeFromElems( VmathVector4 *result, float x, float y, float z, float w ); + +/* + * Construct a 4-D vector from a 3-D vector and a scalar + */ +static inline void vmathV4MakeFromV3Scalar( VmathVector4 *result, const VmathVector3 *xyz, float w ); + +/* + * Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + */ +static inline void vmathV4MakeFromV3( VmathVector4 *result, const VmathVector3 *vec ); + +/* + * Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + */ +static inline void vmathV4MakeFromP3( VmathVector4 *result, const VmathPoint3 *pnt ); + +/* + * Copy elements from a quaternion into a 4-D vector + */ +static inline void vmathV4MakeFromQ( VmathVector4 *result, const VmathQuat *quat ); + +/* + * Set all elements of a 4-D vector to the same scalar value + */ +static inline void vmathV4MakeFromScalar( VmathVector4 *result, float scalar ); + +/* + * Set the x, y, and z elements of a 4-D vector + * NOTE: + * This function does not change the w element. + */ +static inline void vmathV4SetXYZ( VmathVector4 *result, const VmathVector3 *vec ); + +/* + * Get the x, y, and z elements of a 4-D vector + */ +static inline void vmathV4GetXYZ( VmathVector3 *result, const VmathVector4 *vec ); + +/* + * Set the x element of a 4-D vector + */ +static inline void vmathV4SetX( VmathVector4 *result, float x ); + +/* + * Set the y element of a 4-D vector + */ +static inline void vmathV4SetY( VmathVector4 *result, float y ); + +/* + * Set the z element of a 4-D vector + */ +static inline void vmathV4SetZ( VmathVector4 *result, float z ); + +/* + * Set the w element of a 4-D vector + */ +static inline void vmathV4SetW( VmathVector4 *result, float w ); + +/* + * Get the x element of a 4-D vector + */ +static inline float vmathV4GetX( const VmathVector4 *vec ); + +/* + * Get the y element of a 4-D vector + */ +static inline float vmathV4GetY( const VmathVector4 *vec ); + +/* + * Get the z element of a 4-D vector + */ +static inline float vmathV4GetZ( const VmathVector4 *vec ); + +/* + * Get the w element of a 4-D vector + */ +static inline float vmathV4GetW( const VmathVector4 *vec ); + +/* + * Set an x, y, z, or w element of a 4-D vector by index + */ +static inline void vmathV4SetElem( VmathVector4 *result, int idx, float value ); + +/* + * Get an x, y, z, or w element of a 4-D vector by index + */ +static inline float vmathV4GetElem( const VmathVector4 *vec, int idx ); + +/* + * Add two 4-D vectors + */ +static inline void vmathV4Add( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Subtract a 4-D vector from another 4-D vector + */ +static inline void vmathV4Sub( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Multiply a 4-D vector by a scalar + */ +static inline void vmathV4ScalarMul( VmathVector4 *result, const VmathVector4 *vec, float scalar ); + +/* + * Divide a 4-D vector by a scalar + */ +static inline void vmathV4ScalarDiv( VmathVector4 *result, const VmathVector4 *vec, float scalar ); + +/* + * Negate all elements of a 4-D vector + */ +static inline void vmathV4Neg( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Construct x axis + */ +static inline void vmathV4MakeXAxis( VmathVector4 *result ); + +/* + * Construct y axis + */ +static inline void vmathV4MakeYAxis( VmathVector4 *result ); + +/* + * Construct z axis + */ +static inline void vmathV4MakeZAxis( VmathVector4 *result ); + +/* + * Construct w axis + */ +static inline void vmathV4MakeWAxis( VmathVector4 *result ); + +/* + * Multiply two 4-D vectors per element + */ +static inline void vmathV4MulPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Divide two 4-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline void vmathV4DivPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Compute the reciprocal of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline void vmathV4RecipPerElem( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Compute the square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline void vmathV4SqrtPerElem( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Compute the reciprocal square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline void vmathV4RsqrtPerElem( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Compute the absolute value of a 4-D vector per element + */ +static inline void vmathV4AbsPerElem( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Copy sign from one 4-D vector to another, per element + */ +static inline void vmathV4CopySignPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Maximum of two 4-D vectors per element + */ +static inline void vmathV4MaxPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Minimum of two 4-D vectors per element + */ +static inline void vmathV4MinPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Maximum element of a 4-D vector + */ +static inline float vmathV4MaxElem( const VmathVector4 *vec ); + +/* + * Minimum element of a 4-D vector + */ +static inline float vmathV4MinElem( const VmathVector4 *vec ); + +/* + * Compute the sum of all elements of a 4-D vector + */ +static inline float vmathV4Sum( const VmathVector4 *vec ); + +/* + * Compute the dot product of two 4-D vectors + */ +static inline float vmathV4Dot( const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Compute the square of the length of a 4-D vector + */ +static inline float vmathV4LengthSqr( const VmathVector4 *vec ); + +/* + * Compute the length of a 4-D vector + */ +static inline float vmathV4Length( const VmathVector4 *vec ); + +/* + * Normalize a 4-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline void vmathV4Normalize( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Outer product of two 4-D vectors + */ +static inline void vmathV4Outer( VmathMatrix4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Linear interpolation between two 4-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathV4Lerp( VmathVector4 *result, float t, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Spherical linear interpolation between two 4-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline void vmathV4Slerp( VmathVector4 *result, float t, const VmathVector4 *unitVec0, const VmathVector4 *unitVec1 ); + +/* + * Conditionally select between two 4-D vectors + */ +static inline void vmathV4Select( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV4Print( const VmathVector4 *vec ); + +/* + * Print a 4-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV4Prints( const VmathVector4 *vec, const char *name ); + +#endif + +/* + * Copy a 3-D point + */ +static inline void vmathP3Copy( VmathPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Construct a 3-D point from x, y, and z elements + */ +static inline void vmathP3MakeFromElems( VmathPoint3 *result, float x, float y, float z ); + +/* + * Copy elements from a 3-D vector into a 3-D point + */ +static inline void vmathP3MakeFromV3( VmathPoint3 *result, const VmathVector3 *vec ); + +/* + * Set all elements of a 3-D point to the same scalar value + */ +static inline void vmathP3MakeFromScalar( VmathPoint3 *result, float scalar ); + +/* + * Set the x element of a 3-D point + */ +static inline void vmathP3SetX( VmathPoint3 *result, float x ); + +/* + * Set the y element of a 3-D point + */ +static inline void vmathP3SetY( VmathPoint3 *result, float y ); + +/* + * Set the z element of a 3-D point + */ +static inline void vmathP3SetZ( VmathPoint3 *result, float z ); + +/* + * Get the x element of a 3-D point + */ +static inline float vmathP3GetX( const VmathPoint3 *pnt ); + +/* + * Get the y element of a 3-D point + */ +static inline float vmathP3GetY( const VmathPoint3 *pnt ); + +/* + * Get the z element of a 3-D point + */ +static inline float vmathP3GetZ( const VmathPoint3 *pnt ); + +/* + * Set an x, y, or z element of a 3-D point by index + */ +static inline void vmathP3SetElem( VmathPoint3 *result, int idx, float value ); + +/* + * Get an x, y, or z element of a 3-D point by index + */ +static inline float vmathP3GetElem( const VmathPoint3 *pnt, int idx ); + +/* + * Subtract a 3-D point from another 3-D point + */ +static inline void vmathP3Sub( VmathVector3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Add a 3-D point to a 3-D vector + */ +static inline void vmathP3AddV3( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *vec ); + +/* + * Subtract a 3-D vector from a 3-D point + */ +static inline void vmathP3SubV3( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *vec ); + +/* + * Multiply two 3-D points per element + */ +static inline void vmathP3MulPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Divide two 3-D points per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline void vmathP3DivPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Compute the reciprocal of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline void vmathP3RecipPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Compute the square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline void vmathP3SqrtPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Compute the reciprocal square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline void vmathP3RsqrtPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Compute the absolute value of a 3-D point per element + */ +static inline void vmathP3AbsPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Copy sign from one 3-D point to another, per element + */ +static inline void vmathP3CopySignPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Maximum of two 3-D points per element + */ +static inline void vmathP3MaxPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Minimum of two 3-D points per element + */ +static inline void vmathP3MinPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Maximum element of a 3-D point + */ +static inline float vmathP3MaxElem( const VmathPoint3 *pnt ); + +/* + * Minimum element of a 3-D point + */ +static inline float vmathP3MinElem( const VmathPoint3 *pnt ); + +/* + * Compute the sum of all elements of a 3-D point + */ +static inline float vmathP3Sum( const VmathPoint3 *pnt ); + +/* + * Apply uniform scale to a 3-D point + */ +static inline void vmathP3Scale( VmathPoint3 *result, const VmathPoint3 *pnt, float scaleVal ); + +/* + * Apply non-uniform scale to a 3-D point + */ +static inline void vmathP3NonUniformScale( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *scaleVec ); + +/* + * Scalar projection of a 3-D point on a unit-length 3-D vector + */ +static inline float vmathP3Projection( const VmathPoint3 *pnt, const VmathVector3 *unitVec ); + +/* + * Compute the square of the distance of a 3-D point from the coordinate-system origin + */ +static inline float vmathP3DistSqrFromOrigin( const VmathPoint3 *pnt ); + +/* + * Compute the distance of a 3-D point from the coordinate-system origin + */ +static inline float vmathP3DistFromOrigin( const VmathPoint3 *pnt ); + +/* + * Compute the square of the distance between two 3-D points + */ +static inline float vmathP3DistSqr( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Compute the distance between two 3-D points + */ +static inline float vmathP3Dist( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Linear interpolation between two 3-D points + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathP3Lerp( VmathPoint3 *result, float t, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Conditionally select between two 3-D points + */ +static inline void vmathP3Select( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D point + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathP3Print( const VmathPoint3 *pnt ); + +/* + * Print a 3-D point and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathP3Prints( const VmathPoint3 *pnt, const char *name ); + +#endif + +/* + * Copy a quaternion + */ +static inline void vmathQCopy( VmathQuat *result, const VmathQuat *quat ); + +/* + * Construct a quaternion from x, y, z, and w elements + */ +static inline void vmathQMakeFromElems( VmathQuat *result, float x, float y, float z, float w ); + +/* + * Construct a quaternion from a 3-D vector and a scalar + */ +static inline void vmathQMakeFromV3Scalar( VmathQuat *result, const VmathVector3 *xyz, float w ); + +/* + * Copy elements from a 4-D vector into a quaternion + */ +static inline void vmathQMakeFromV4( VmathQuat *result, const VmathVector4 *vec ); + +/* + * Convert a rotation matrix to a unit-length quaternion + */ +static inline void vmathQMakeFromM3( VmathQuat *result, const VmathMatrix3 *rotMat ); + +/* + * Set all elements of a quaternion to the same scalar value + */ +static inline void vmathQMakeFromScalar( VmathQuat *result, float scalar ); + +/* + * Set the x, y, and z elements of a quaternion + * NOTE: + * This function does not change the w element. + */ +static inline void vmathQSetXYZ( VmathQuat *result, const VmathVector3 *vec ); + +/* + * Get the x, y, and z elements of a quaternion + */ +static inline void vmathQGetXYZ( VmathVector3 *result, const VmathQuat *quat ); + +/* + * Set the x element of a quaternion + */ +static inline void vmathQSetX( VmathQuat *result, float x ); + +/* + * Set the y element of a quaternion + */ +static inline void vmathQSetY( VmathQuat *result, float y ); + +/* + * Set the z element of a quaternion + */ +static inline void vmathQSetZ( VmathQuat *result, float z ); + +/* + * Set the w element of a quaternion + */ +static inline void vmathQSetW( VmathQuat *result, float w ); + +/* + * Get the x element of a quaternion + */ +static inline float vmathQGetX( const VmathQuat *quat ); + +/* + * Get the y element of a quaternion + */ +static inline float vmathQGetY( const VmathQuat *quat ); + +/* + * Get the z element of a quaternion + */ +static inline float vmathQGetZ( const VmathQuat *quat ); + +/* + * Get the w element of a quaternion + */ +static inline float vmathQGetW( const VmathQuat *quat ); + +/* + * Set an x, y, z, or w element of a quaternion by index + */ +static inline void vmathQSetElem( VmathQuat *result, int idx, float value ); + +/* + * Get an x, y, z, or w element of a quaternion by index + */ +static inline float vmathQGetElem( const VmathQuat *quat, int idx ); + +/* + * Add two quaternions + */ +static inline void vmathQAdd( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ); + +/* + * Subtract a quaternion from another quaternion + */ +static inline void vmathQSub( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ); + +/* + * Multiply two quaternions + */ +static inline void vmathQMul( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ); + +/* + * Multiply a quaternion by a scalar + */ +static inline void vmathQScalarMul( VmathQuat *result, const VmathQuat *quat, float scalar ); + +/* + * Divide a quaternion by a scalar + */ +static inline void vmathQScalarDiv( VmathQuat *result, const VmathQuat *quat, float scalar ); + +/* + * Negate all elements of a quaternion + */ +static inline void vmathQNeg( VmathQuat *result, const VmathQuat *quat ); + +/* + * Construct an identity quaternion + */ +static inline void vmathQMakeIdentity( VmathQuat *result ); + +/* + * Construct a quaternion to rotate between two unit-length 3-D vectors + * NOTE: + * The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + */ +static inline void vmathQMakeRotationArc( VmathQuat *result, const VmathVector3 *unitVec0, const VmathVector3 *unitVec1 ); + +/* + * Construct a quaternion to rotate around a unit-length 3-D vector + */ +static inline void vmathQMakeRotationAxis( VmathQuat *result, float radians, const VmathVector3 *unitVec ); + +/* + * Construct a quaternion to rotate around the x axis + */ +static inline void vmathQMakeRotationX( VmathQuat *result, float radians ); + +/* + * Construct a quaternion to rotate around the y axis + */ +static inline void vmathQMakeRotationY( VmathQuat *result, float radians ); + +/* + * Construct a quaternion to rotate around the z axis + */ +static inline void vmathQMakeRotationZ( VmathQuat *result, float radians ); + +/* + * Compute the conjugate of a quaternion + */ +static inline void vmathQConj( VmathQuat *result, const VmathQuat *quat ); + +/* + * Use a unit-length quaternion to rotate a 3-D vector + */ +static inline void vmathQRotate( VmathVector3 *result, const VmathQuat *unitQuat, const VmathVector3 *vec ); + +/* + * Compute the dot product of two quaternions + */ +static inline float vmathQDot( const VmathQuat *quat0, const VmathQuat *quat1 ); + +/* + * Compute the norm of a quaternion + */ +static inline float vmathQNorm( const VmathQuat *quat ); + +/* + * Compute the length of a quaternion + */ +static inline float vmathQLength( const VmathQuat *quat ); + +/* + * Normalize a quaternion + * NOTE: + * The result is unpredictable when all elements of quat are at or near zero. + */ +static inline void vmathQNormalize( VmathQuat *result, const VmathQuat *quat ); + +/* + * Linear interpolation between two quaternions + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathQLerp( VmathQuat *result, float t, const VmathQuat *quat0, const VmathQuat *quat1 ); + +/* + * Spherical linear interpolation between two quaternions + * NOTE: + * Interpolates along the shortest path between orientations. + * Does not clamp t between 0 and 1. + */ +static inline void vmathQSlerp( VmathQuat *result, float t, const VmathQuat *unitQuat0, const VmathQuat *unitQuat1 ); + +/* + * Spherical quadrangle interpolation + */ +static inline void vmathQSquad( VmathQuat *result, float t, const VmathQuat *unitQuat0, const VmathQuat *unitQuat1, const VmathQuat *unitQuat2, const VmathQuat *unitQuat3 ); + +/* + * Conditionally select between two quaternions + */ +static inline void vmathQSelect( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a quaternion + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathQPrint( const VmathQuat *quat ); + +/* + * Print a quaternion and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathQPrints( const VmathQuat *quat, const char *name ); + +#endif + +/* + * Copy a 3x3 matrix + */ +static inline void vmathM3Copy( VmathMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Construct a 3x3 matrix containing the specified columns + */ +static inline void vmathM3MakeFromCols( VmathMatrix3 *result, const VmathVector3 *col0, const VmathVector3 *col1, const VmathVector3 *col2 ); + +/* + * Construct a 3x3 rotation matrix from a unit-length quaternion + */ +static inline void vmathM3MakeFromQ( VmathMatrix3 *result, const VmathQuat *unitQuat ); + +/* + * Set all elements of a 3x3 matrix to the same scalar value + */ +static inline void vmathM3MakeFromScalar( VmathMatrix3 *result, float scalar ); + +/* + * Set column 0 of a 3x3 matrix + */ +static inline void vmathM3SetCol0( VmathMatrix3 *result, const VmathVector3 *col0 ); + +/* + * Set column 1 of a 3x3 matrix + */ +static inline void vmathM3SetCol1( VmathMatrix3 *result, const VmathVector3 *col1 ); + +/* + * Set column 2 of a 3x3 matrix + */ +static inline void vmathM3SetCol2( VmathMatrix3 *result, const VmathVector3 *col2 ); + +/* + * Get column 0 of a 3x3 matrix + */ +static inline void vmathM3GetCol0( VmathVector3 *result, const VmathMatrix3 *mat ); + +/* + * Get column 1 of a 3x3 matrix + */ +static inline void vmathM3GetCol1( VmathVector3 *result, const VmathMatrix3 *mat ); + +/* + * Get column 2 of a 3x3 matrix + */ +static inline void vmathM3GetCol2( VmathVector3 *result, const VmathMatrix3 *mat ); + +/* + * Set the column of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3SetCol( VmathMatrix3 *result, int col, const VmathVector3 *vec ); + +/* + * Set the row of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3SetRow( VmathMatrix3 *result, int row, const VmathVector3 *vec ); + +/* + * Get the column of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3GetCol( VmathVector3 *result, const VmathMatrix3 *mat, int col ); + +/* + * Get the row of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3GetRow( VmathVector3 *result, const VmathMatrix3 *mat, int row ); + +/* + * Set the element of a 3x3 matrix referred to by column and row indices + */ +static inline void vmathM3SetElem( VmathMatrix3 *result, int col, int row, float val ); + +/* + * Get the element of a 3x3 matrix referred to by column and row indices + */ +static inline float vmathM3GetElem( const VmathMatrix3 *mat, int col, int row ); + +/* + * Add two 3x3 matrices + */ +static inline void vmathM3Add( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ); + +/* + * Subtract a 3x3 matrix from another 3x3 matrix + */ +static inline void vmathM3Sub( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ); + +/* + * Negate all elements of a 3x3 matrix + */ +static inline void vmathM3Neg( VmathMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Multiply a 3x3 matrix by a scalar + */ +static inline void vmathM3ScalarMul( VmathMatrix3 *result, const VmathMatrix3 *mat, float scalar ); + +/* + * Multiply a 3x3 matrix by a 3-D vector + */ +static inline void vmathM3MulV3( VmathVector3 *result, const VmathMatrix3 *mat, const VmathVector3 *vec ); + +/* + * Multiply two 3x3 matrices + */ +static inline void vmathM3Mul( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ); + +/* + * Construct an identity 3x3 matrix + */ +static inline void vmathM3MakeIdentity( VmathMatrix3 *result ); + +/* + * Construct a 3x3 matrix to rotate around the x axis + */ +static inline void vmathM3MakeRotationX( VmathMatrix3 *result, float radians ); + +/* + * Construct a 3x3 matrix to rotate around the y axis + */ +static inline void vmathM3MakeRotationY( VmathMatrix3 *result, float radians ); + +/* + * Construct a 3x3 matrix to rotate around the z axis + */ +static inline void vmathM3MakeRotationZ( VmathMatrix3 *result, float radians ); + +/* + * Construct a 3x3 matrix to rotate around the x, y, and z axes + */ +static inline void vmathM3MakeRotationZYX( VmathMatrix3 *result, const VmathVector3 *radiansXYZ ); + +/* + * Construct a 3x3 matrix to rotate around a unit-length 3-D vector + */ +static inline void vmathM3MakeRotationAxis( VmathMatrix3 *result, float radians, const VmathVector3 *unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline void vmathM3MakeRotationQ( VmathMatrix3 *result, const VmathQuat *unitQuat ); + +/* + * Construct a 3x3 matrix to perform scaling + */ +static inline void vmathM3MakeScale( VmathMatrix3 *result, const VmathVector3 *scaleVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathM3AppendScale( VmathMatrix3 *result, const VmathMatrix3 *mat, const VmathVector3 *scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathM3PrependScale( VmathMatrix3 *result, const VmathVector3 *scaleVec, const VmathMatrix3 *mat ); + +/* + * Multiply two 3x3 matrices per element + */ +static inline void vmathM3MulPerElem( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ); + +/* + * Compute the absolute value of a 3x3 matrix per element + */ +static inline void vmathM3AbsPerElem( VmathMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Transpose of a 3x3 matrix + */ +static inline void vmathM3Transpose( VmathMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Compute the inverse of a 3x3 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline void vmathM3Inverse( VmathMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Determinant of a 3x3 matrix + */ +static inline float vmathM3Determinant( const VmathMatrix3 *mat ); + +/* + * Conditionally select between two 3x3 matrices + */ +static inline void vmathM3Select( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x3 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM3Print( const VmathMatrix3 *mat ); + +/* + * Print a 3x3 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM3Prints( const VmathMatrix3 *mat, const char *name ); + +#endif + +/* + * Copy a 4x4 matrix + */ +static inline void vmathM4Copy( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Construct a 4x4 matrix containing the specified columns + */ +static inline void vmathM4MakeFromCols( VmathMatrix4 *result, const VmathVector4 *col0, const VmathVector4 *col1, const VmathVector4 *col2, const VmathVector4 *col3 ); + +/* + * Construct a 4x4 matrix from a 3x4 transformation matrix + */ +static inline void vmathM4MakeFromT3( VmathMatrix4 *result, const VmathTransform3 *mat ); + +/* + * Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + */ +static inline void vmathM4MakeFromM3V3( VmathMatrix4 *result, const VmathMatrix3 *mat, const VmathVector3 *translateVec ); + +/* + * Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + */ +static inline void vmathM4MakeFromQV3( VmathMatrix4 *result, const VmathQuat *unitQuat, const VmathVector3 *translateVec ); + +/* + * Set all elements of a 4x4 matrix to the same scalar value + */ +static inline void vmathM4MakeFromScalar( VmathMatrix4 *result, float scalar ); + +/* + * Set the upper-left 3x3 submatrix + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathM4SetUpper3x3( VmathMatrix4 *result, const VmathMatrix3 *mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 4x4 matrix + */ +static inline void vmathM4GetUpper3x3( VmathMatrix3 *result, const VmathMatrix4 *mat ); + +/* + * Set translation component + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathM4SetTranslation( VmathMatrix4 *result, const VmathVector3 *translateVec ); + +/* + * Get the translation component of a 4x4 matrix + */ +static inline void vmathM4GetTranslation( VmathVector3 *result, const VmathMatrix4 *mat ); + +/* + * Set column 0 of a 4x4 matrix + */ +static inline void vmathM4SetCol0( VmathMatrix4 *result, const VmathVector4 *col0 ); + +/* + * Set column 1 of a 4x4 matrix + */ +static inline void vmathM4SetCol1( VmathMatrix4 *result, const VmathVector4 *col1 ); + +/* + * Set column 2 of a 4x4 matrix + */ +static inline void vmathM4SetCol2( VmathMatrix4 *result, const VmathVector4 *col2 ); + +/* + * Set column 3 of a 4x4 matrix + */ +static inline void vmathM4SetCol3( VmathMatrix4 *result, const VmathVector4 *col3 ); + +/* + * Get column 0 of a 4x4 matrix + */ +static inline void vmathM4GetCol0( VmathVector4 *result, const VmathMatrix4 *mat ); + +/* + * Get column 1 of a 4x4 matrix + */ +static inline void vmathM4GetCol1( VmathVector4 *result, const VmathMatrix4 *mat ); + +/* + * Get column 2 of a 4x4 matrix + */ +static inline void vmathM4GetCol2( VmathVector4 *result, const VmathMatrix4 *mat ); + +/* + * Get column 3 of a 4x4 matrix + */ +static inline void vmathM4GetCol3( VmathVector4 *result, const VmathMatrix4 *mat ); + +/* + * Set the column of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4SetCol( VmathMatrix4 *result, int col, const VmathVector4 *vec ); + +/* + * Set the row of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4SetRow( VmathMatrix4 *result, int row, const VmathVector4 *vec ); + +/* + * Get the column of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4GetCol( VmathVector4 *result, const VmathMatrix4 *mat, int col ); + +/* + * Get the row of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4GetRow( VmathVector4 *result, const VmathMatrix4 *mat, int row ); + +/* + * Set the element of a 4x4 matrix referred to by column and row indices + */ +static inline void vmathM4SetElem( VmathMatrix4 *result, int col, int row, float val ); + +/* + * Get the element of a 4x4 matrix referred to by column and row indices + */ +static inline float vmathM4GetElem( const VmathMatrix4 *mat, int col, int row ); + +/* + * Add two 4x4 matrices + */ +static inline void vmathM4Add( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ); + +/* + * Subtract a 4x4 matrix from another 4x4 matrix + */ +static inline void vmathM4Sub( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ); + +/* + * Negate all elements of a 4x4 matrix + */ +static inline void vmathM4Neg( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Multiply a 4x4 matrix by a scalar + */ +static inline void vmathM4ScalarMul( VmathMatrix4 *result, const VmathMatrix4 *mat, float scalar ); + +/* + * Multiply a 4x4 matrix by a 4-D vector + */ +static inline void vmathM4MulV4( VmathVector4 *result, const VmathMatrix4 *mat, const VmathVector4 *vec ); + +/* + * Multiply a 4x4 matrix by a 3-D vector + */ +static inline void vmathM4MulV3( VmathVector4 *result, const VmathMatrix4 *mat, const VmathVector3 *vec ); + +/* + * Multiply a 4x4 matrix by a 3-D point + */ +static inline void vmathM4MulP3( VmathVector4 *result, const VmathMatrix4 *mat, const VmathPoint3 *pnt ); + +/* + * Multiply two 4x4 matrices + */ +static inline void vmathM4Mul( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ); + +/* + * Multiply a 4x4 matrix by a 3x4 transformation matrix + */ +static inline void vmathM4MulT3( VmathMatrix4 *result, const VmathMatrix4 *mat, const VmathTransform3 *tfrm ); + +/* + * Construct an identity 4x4 matrix + */ +static inline void vmathM4MakeIdentity( VmathMatrix4 *result ); + +/* + * Construct a 4x4 matrix to rotate around the x axis + */ +static inline void vmathM4MakeRotationX( VmathMatrix4 *result, float radians ); + +/* + * Construct a 4x4 matrix to rotate around the y axis + */ +static inline void vmathM4MakeRotationY( VmathMatrix4 *result, float radians ); + +/* + * Construct a 4x4 matrix to rotate around the z axis + */ +static inline void vmathM4MakeRotationZ( VmathMatrix4 *result, float radians ); + +/* + * Construct a 4x4 matrix to rotate around the x, y, and z axes + */ +static inline void vmathM4MakeRotationZYX( VmathMatrix4 *result, const VmathVector3 *radiansXYZ ); + +/* + * Construct a 4x4 matrix to rotate around a unit-length 3-D vector + */ +static inline void vmathM4MakeRotationAxis( VmathMatrix4 *result, float radians, const VmathVector3 *unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline void vmathM4MakeRotationQ( VmathMatrix4 *result, const VmathQuat *unitQuat ); + +/* + * Construct a 4x4 matrix to perform scaling + */ +static inline void vmathM4MakeScale( VmathMatrix4 *result, const VmathVector3 *scaleVec ); + +/* + * Construct a 4x4 matrix to perform translation + */ +static inline void vmathM4MakeTranslation( VmathMatrix4 *result, const VmathVector3 *translateVec ); + +/* + * Construct viewing matrix based on eye position, position looked at, and up direction + */ +static inline void vmathM4MakeLookAt( VmathMatrix4 *result, const VmathPoint3 *eyePos, const VmathPoint3 *lookAtPos, const VmathVector3 *upVec ); + +/* + * Construct a perspective projection matrix + */ +static inline void vmathM4MakePerspective( VmathMatrix4 *result, float fovyRadians, float aspect, float zNear, float zFar ); + +/* + * Construct a perspective projection matrix based on frustum + */ +static inline void vmathM4MakeFrustum( VmathMatrix4 *result, float left, float right, float bottom, float top, float zNear, float zFar ); + +/* + * Construct an orthographic projection matrix + */ +static inline void vmathM4MakeOrthographic( VmathMatrix4 *result, float left, float right, float bottom, float top, float zNear, float zFar ); + +/* + * Append (post-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathM4AppendScale( VmathMatrix4 *result, const VmathMatrix4 *mat, const VmathVector3 *scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathM4PrependScale( VmathMatrix4 *result, const VmathVector3 *scaleVec, const VmathMatrix4 *mat ); + +/* + * Multiply two 4x4 matrices per element + */ +static inline void vmathM4MulPerElem( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ); + +/* + * Compute the absolute value of a 4x4 matrix per element + */ +static inline void vmathM4AbsPerElem( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Transpose of a 4x4 matrix + */ +static inline void vmathM4Transpose( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Compute the inverse of a 4x4 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline void vmathM4Inverse( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline void vmathM4AffineInverse( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. + */ +static inline void vmathM4OrthoInverse( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Determinant of a 4x4 matrix + */ +static inline float vmathM4Determinant( const VmathMatrix4 *mat ); + +/* + * Conditionally select between two 4x4 matrices + */ +static inline void vmathM4Select( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4x4 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM4Print( const VmathMatrix4 *mat ); + +/* + * Print a 4x4 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM4Prints( const VmathMatrix4 *mat, const char *name ); + +#endif + +/* + * Copy a 3x4 transformation matrix + */ +static inline void vmathT3Copy( VmathTransform3 *result, const VmathTransform3 *tfrm ); + +/* + * Construct a 3x4 transformation matrix containing the specified columns + */ +static inline void vmathT3MakeFromCols( VmathTransform3 *result, const VmathVector3 *col0, const VmathVector3 *col1, const VmathVector3 *col2, const VmathVector3 *col3 ); + +/* + * Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + */ +static inline void vmathT3MakeFromM3V3( VmathTransform3 *result, const VmathMatrix3 *tfrm, const VmathVector3 *translateVec ); + +/* + * Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + */ +static inline void vmathT3MakeFromQV3( VmathTransform3 *result, const VmathQuat *unitQuat, const VmathVector3 *translateVec ); + +/* + * Set all elements of a 3x4 transformation matrix to the same scalar value + */ +static inline void vmathT3MakeFromScalar( VmathTransform3 *result, float scalar ); + +/* + * Set the upper-left 3x3 submatrix + */ +static inline void vmathT3SetUpper3x3( VmathTransform3 *result, const VmathMatrix3 *mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + */ +static inline void vmathT3GetUpper3x3( VmathMatrix3 *result, const VmathTransform3 *tfrm ); + +/* + * Set translation component + */ +static inline void vmathT3SetTranslation( VmathTransform3 *result, const VmathVector3 *translateVec ); + +/* + * Get the translation component of a 3x4 transformation matrix + */ +static inline void vmathT3GetTranslation( VmathVector3 *result, const VmathTransform3 *tfrm ); + +/* + * Set column 0 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol0( VmathTransform3 *result, const VmathVector3 *col0 ); + +/* + * Set column 1 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol1( VmathTransform3 *result, const VmathVector3 *col1 ); + +/* + * Set column 2 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol2( VmathTransform3 *result, const VmathVector3 *col2 ); + +/* + * Set column 3 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol3( VmathTransform3 *result, const VmathVector3 *col3 ); + +/* + * Get column 0 of a 3x4 transformation matrix + */ +static inline void vmathT3GetCol0( VmathVector3 *result, const VmathTransform3 *tfrm ); + +/* + * Get column 1 of a 3x4 transformation matrix + */ +static inline void vmathT3GetCol1( VmathVector3 *result, const VmathTransform3 *tfrm ); + +/* + * Get column 2 of a 3x4 transformation matrix + */ +static inline void vmathT3GetCol2( VmathVector3 *result, const VmathTransform3 *tfrm ); + +/* + * Get column 3 of a 3x4 transformation matrix + */ +static inline void vmathT3GetCol3( VmathVector3 *result, const VmathTransform3 *tfrm ); + +/* + * Set the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3SetCol( VmathTransform3 *result, int col, const VmathVector3 *vec ); + +/* + * Set the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3SetRow( VmathTransform3 *result, int row, const VmathVector4 *vec ); + +/* + * Get the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3GetCol( VmathVector3 *result, const VmathTransform3 *tfrm, int col ); + +/* + * Get the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3GetRow( VmathVector4 *result, const VmathTransform3 *tfrm, int row ); + +/* + * Set the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline void vmathT3SetElem( VmathTransform3 *result, int col, int row, float val ); + +/* + * Get the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline float vmathT3GetElem( const VmathTransform3 *tfrm, int col, int row ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D vector + */ +static inline void vmathT3MulV3( VmathVector3 *result, const VmathTransform3 *tfrm, const VmathVector3 *vec ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D point + */ +static inline void vmathT3MulP3( VmathPoint3 *result, const VmathTransform3 *tfrm, const VmathPoint3 *pnt ); + +/* + * Multiply two 3x4 transformation matrices + */ +static inline void vmathT3Mul( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1 ); + +/* + * Construct an identity 3x4 transformation matrix + */ +static inline void vmathT3MakeIdentity( VmathTransform3 *result ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x axis + */ +static inline void vmathT3MakeRotationX( VmathTransform3 *result, float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the y axis + */ +static inline void vmathT3MakeRotationY( VmathTransform3 *result, float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the z axis + */ +static inline void vmathT3MakeRotationZ( VmathTransform3 *result, float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + */ +static inline void vmathT3MakeRotationZYX( VmathTransform3 *result, const VmathVector3 *radiansXYZ ); + +/* + * Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + */ +static inline void vmathT3MakeRotationAxis( VmathTransform3 *result, float radians, const VmathVector3 *unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline void vmathT3MakeRotationQ( VmathTransform3 *result, const VmathQuat *unitQuat ); + +/* + * Construct a 3x4 transformation matrix to perform scaling + */ +static inline void vmathT3MakeScale( VmathTransform3 *result, const VmathVector3 *scaleVec ); + +/* + * Construct a 3x4 transformation matrix to perform translation + */ +static inline void vmathT3MakeTranslation( VmathTransform3 *result, const VmathVector3 *translateVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathT3AppendScale( VmathTransform3 *result, const VmathTransform3 *tfrm, const VmathVector3 *scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathT3PrependScale( VmathTransform3 *result, const VmathVector3 *scaleVec, const VmathTransform3 *tfrm ); + +/* + * Multiply two 3x4 transformation matrices per element + */ +static inline void vmathT3MulPerElem( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1 ); + +/* + * Compute the absolute value of a 3x4 transformation matrix per element + */ +static inline void vmathT3AbsPerElem( VmathTransform3 *result, const VmathTransform3 *tfrm ); + +/* + * Inverse of a 3x4 transformation matrix + * NOTE: + * Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. + */ +static inline void vmathT3Inverse( VmathTransform3 *result, const VmathTransform3 *tfrm ); + +/* + * Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. + */ +static inline void vmathT3OrthoInverse( VmathTransform3 *result, const VmathTransform3 *tfrm ); + +/* + * Conditionally select between two 3x4 transformation matrices + */ +static inline void vmathT3Select( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x4 transformation matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathT3Print( const VmathTransform3 *tfrm ); + +/* + * Print a 3x4 transformation matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathT3Prints( const VmathTransform3 *tfrm, const char *name ); + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#include "vec_aos.h" +#include "quat_aos.h" +#include "mat_aos.h" + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/scalar/c/vectormath_aos_v.h b/Extras/vectormathlibrary/include/vectormath/scalar/c/vectormath_aos_v.h new file mode 100644 index 0000000..f766bb1 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/scalar/c/vectormath_aos_v.h @@ -0,0 +1,1845 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_AOS_C_V_SCALAR_H +#define _VECTORMATH_AOS_C_V_SCALAR_H + +#include + +#ifdef _VECTORMATH_DEBUG +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef _VECTORMATH_AOS_C_TYPES_H +#define _VECTORMATH_AOS_C_TYPES_H + +/* A 3-D vector in array-of-structures format + */ +typedef struct _VmathVector3 +{ + float x; + float y; + float z; +#ifndef __GNUC__ + float d; +#endif +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +VmathVector3; + +/* A 4-D vector in array-of-structures format + */ +typedef struct _VmathVector4 +{ + float x; + float y; + float z; + float w; +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +VmathVector4; + +/* A 3-D point in array-of-structures format + */ +typedef struct _VmathPoint3 +{ + float x; + float y; + float z; +#ifndef __GNUC__ + float d; +#endif +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +VmathPoint3; + +/* A quaternion in array-of-structures format + */ +typedef struct _VmathQuat +{ + float x; + float y; + float z; + float w; +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +VmathQuat; + +/* A 3x3 matrix in array-of-structures format + */ +typedef struct _VmathMatrix3 +{ + VmathVector3 col0; + VmathVector3 col1; + VmathVector3 col2; +} VmathMatrix3; + +/* A 4x4 matrix in array-of-structures format + */ +typedef struct _VmathMatrix4 +{ + VmathVector4 col0; + VmathVector4 col1; + VmathVector4 col2; + VmathVector4 col3; +} VmathMatrix4; + +/* A 3x4 transformation matrix in array-of-structures format + */ +typedef struct _VmathTransform3 +{ + VmathVector3 col0; + VmathVector3 col1; + VmathVector3 col2; + VmathVector3 col3; +} VmathTransform3; + +#endif + +/* + * Construct a 3-D vector from x, y, and z elements + */ +static inline VmathVector3 vmathV3MakeFromElems_V( float x, float y, float z ); + +/* + * Copy elements from a 3-D point into a 3-D vector + */ +static inline VmathVector3 vmathV3MakeFromP3_V( VmathPoint3 pnt ); + +/* + * Set all elements of a 3-D vector to the same scalar value + */ +static inline VmathVector3 vmathV3MakeFromScalar_V( float scalar ); + +/* + * Set the x element of a 3-D vector + */ +static inline void vmathV3SetX_V( VmathVector3 *result, float x ); + +/* + * Set the y element of a 3-D vector + */ +static inline void vmathV3SetY_V( VmathVector3 *result, float y ); + +/* + * Set the z element of a 3-D vector + */ +static inline void vmathV3SetZ_V( VmathVector3 *result, float z ); + +/* + * Get the x element of a 3-D vector + */ +static inline float vmathV3GetX_V( VmathVector3 vec ); + +/* + * Get the y element of a 3-D vector + */ +static inline float vmathV3GetY_V( VmathVector3 vec ); + +/* + * Get the z element of a 3-D vector + */ +static inline float vmathV3GetZ_V( VmathVector3 vec ); + +/* + * Set an x, y, or z element of a 3-D vector by index + */ +static inline void vmathV3SetElem_V( VmathVector3 *result, int idx, float value ); + +/* + * Get an x, y, or z element of a 3-D vector by index + */ +static inline float vmathV3GetElem_V( VmathVector3 vec, int idx ); + +/* + * Add two 3-D vectors + */ +static inline VmathVector3 vmathV3Add_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Subtract a 3-D vector from another 3-D vector + */ +static inline VmathVector3 vmathV3Sub_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Add a 3-D vector to a 3-D point + */ +static inline VmathPoint3 vmathV3AddP3_V( VmathVector3 vec, VmathPoint3 pnt ); + +/* + * Multiply a 3-D vector by a scalar + */ +static inline VmathVector3 vmathV3ScalarMul_V( VmathVector3 vec, float scalar ); + +/* + * Divide a 3-D vector by a scalar + */ +static inline VmathVector3 vmathV3ScalarDiv_V( VmathVector3 vec, float scalar ); + +/* + * Negate all elements of a 3-D vector + */ +static inline VmathVector3 vmathV3Neg_V( VmathVector3 vec ); + +/* + * Construct x axis + */ +static inline VmathVector3 vmathV3MakeXAxis_V( ); + +/* + * Construct y axis + */ +static inline VmathVector3 vmathV3MakeYAxis_V( ); + +/* + * Construct z axis + */ +static inline VmathVector3 vmathV3MakeZAxis_V( ); + +/* + * Multiply two 3-D vectors per element + */ +static inline VmathVector3 vmathV3MulPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Divide two 3-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline VmathVector3 vmathV3DivPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Compute the reciprocal of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline VmathVector3 vmathV3RecipPerElem_V( VmathVector3 vec ); + +/* + * Compute the square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline VmathVector3 vmathV3SqrtPerElem_V( VmathVector3 vec ); + +/* + * Compute the reciprocal square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline VmathVector3 vmathV3RsqrtPerElem_V( VmathVector3 vec ); + +/* + * Compute the absolute value of a 3-D vector per element + */ +static inline VmathVector3 vmathV3AbsPerElem_V( VmathVector3 vec ); + +/* + * Copy sign from one 3-D vector to another, per element + */ +static inline VmathVector3 vmathV3CopySignPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Maximum of two 3-D vectors per element + */ +static inline VmathVector3 vmathV3MaxPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Minimum of two 3-D vectors per element + */ +static inline VmathVector3 vmathV3MinPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Maximum element of a 3-D vector + */ +static inline float vmathV3MaxElem_V( VmathVector3 vec ); + +/* + * Minimum element of a 3-D vector + */ +static inline float vmathV3MinElem_V( VmathVector3 vec ); + +/* + * Compute the sum of all elements of a 3-D vector + */ +static inline float vmathV3Sum_V( VmathVector3 vec ); + +/* + * Compute the dot product of two 3-D vectors + */ +static inline float vmathV3Dot_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Compute the square of the length of a 3-D vector + */ +static inline float vmathV3LengthSqr_V( VmathVector3 vec ); + +/* + * Compute the length of a 3-D vector + */ +static inline float vmathV3Length_V( VmathVector3 vec ); + +/* + * Normalize a 3-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline VmathVector3 vmathV3Normalize_V( VmathVector3 vec ); + +/* + * Compute cross product of two 3-D vectors + */ +static inline VmathVector3 vmathV3Cross_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Outer product of two 3-D vectors + */ +static inline VmathMatrix3 vmathV3Outer_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Pre-multiply a row vector by a 3x3 matrix + */ +static inline VmathVector3 vmathV3RowMul_V( VmathVector3 vec, VmathMatrix3 mat ); + +/* + * Cross-product matrix of a 3-D vector + */ +static inline VmathMatrix3 vmathV3CrossMatrix_V( VmathVector3 vec ); + +/* + * Create cross-product matrix and multiply + * NOTE: + * Faster than separately creating a cross-product matrix and multiplying. + */ +static inline VmathMatrix3 vmathV3CrossMatrixMul_V( VmathVector3 vec, VmathMatrix3 mat ); + +/* + * Linear interpolation between two 3-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathVector3 vmathV3Lerp_V( float t, VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Spherical linear interpolation between two 3-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline VmathVector3 vmathV3Slerp_V( float t, VmathVector3 unitVec0, VmathVector3 unitVec1 ); + +/* + * Conditionally select between two 3-D vectors + */ +static inline VmathVector3 vmathV3Select_V( VmathVector3 vec0, VmathVector3 vec1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV3Print_V( VmathVector3 vec ); + +/* + * Print a 3-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV3Prints_V( VmathVector3 vec, const char *name ); + +#endif + +/* + * Construct a 4-D vector from x, y, z, and w elements + */ +static inline VmathVector4 vmathV4MakeFromElems_V( float x, float y, float z, float w ); + +/* + * Construct a 4-D vector from a 3-D vector and a scalar + */ +static inline VmathVector4 vmathV4MakeFromV3Scalar_V( VmathVector3 xyz, float w ); + +/* + * Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + */ +static inline VmathVector4 vmathV4MakeFromV3_V( VmathVector3 vec ); + +/* + * Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + */ +static inline VmathVector4 vmathV4MakeFromP3_V( VmathPoint3 pnt ); + +/* + * Copy elements from a quaternion into a 4-D vector + */ +static inline VmathVector4 vmathV4MakeFromQ_V( VmathQuat quat ); + +/* + * Set all elements of a 4-D vector to the same scalar value + */ +static inline VmathVector4 vmathV4MakeFromScalar_V( float scalar ); + +/* + * Set the x, y, and z elements of a 4-D vector + * NOTE: + * This function does not change the w element. + */ +static inline void vmathV4SetXYZ_V( VmathVector4 *result, VmathVector3 vec ); + +/* + * Get the x, y, and z elements of a 4-D vector + */ +static inline VmathVector3 vmathV4GetXYZ_V( VmathVector4 vec ); + +/* + * Set the x element of a 4-D vector + */ +static inline void vmathV4SetX_V( VmathVector4 *result, float x ); + +/* + * Set the y element of a 4-D vector + */ +static inline void vmathV4SetY_V( VmathVector4 *result, float y ); + +/* + * Set the z element of a 4-D vector + */ +static inline void vmathV4SetZ_V( VmathVector4 *result, float z ); + +/* + * Set the w element of a 4-D vector + */ +static inline void vmathV4SetW_V( VmathVector4 *result, float w ); + +/* + * Get the x element of a 4-D vector + */ +static inline float vmathV4GetX_V( VmathVector4 vec ); + +/* + * Get the y element of a 4-D vector + */ +static inline float vmathV4GetY_V( VmathVector4 vec ); + +/* + * Get the z element of a 4-D vector + */ +static inline float vmathV4GetZ_V( VmathVector4 vec ); + +/* + * Get the w element of a 4-D vector + */ +static inline float vmathV4GetW_V( VmathVector4 vec ); + +/* + * Set an x, y, z, or w element of a 4-D vector by index + */ +static inline void vmathV4SetElem_V( VmathVector4 *result, int idx, float value ); + +/* + * Get an x, y, z, or w element of a 4-D vector by index + */ +static inline float vmathV4GetElem_V( VmathVector4 vec, int idx ); + +/* + * Add two 4-D vectors + */ +static inline VmathVector4 vmathV4Add_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Subtract a 4-D vector from another 4-D vector + */ +static inline VmathVector4 vmathV4Sub_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Multiply a 4-D vector by a scalar + */ +static inline VmathVector4 vmathV4ScalarMul_V( VmathVector4 vec, float scalar ); + +/* + * Divide a 4-D vector by a scalar + */ +static inline VmathVector4 vmathV4ScalarDiv_V( VmathVector4 vec, float scalar ); + +/* + * Negate all elements of a 4-D vector + */ +static inline VmathVector4 vmathV4Neg_V( VmathVector4 vec ); + +/* + * Construct x axis + */ +static inline VmathVector4 vmathV4MakeXAxis_V( ); + +/* + * Construct y axis + */ +static inline VmathVector4 vmathV4MakeYAxis_V( ); + +/* + * Construct z axis + */ +static inline VmathVector4 vmathV4MakeZAxis_V( ); + +/* + * Construct w axis + */ +static inline VmathVector4 vmathV4MakeWAxis_V( ); + +/* + * Multiply two 4-D vectors per element + */ +static inline VmathVector4 vmathV4MulPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Divide two 4-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline VmathVector4 vmathV4DivPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Compute the reciprocal of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline VmathVector4 vmathV4RecipPerElem_V( VmathVector4 vec ); + +/* + * Compute the square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline VmathVector4 vmathV4SqrtPerElem_V( VmathVector4 vec ); + +/* + * Compute the reciprocal square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline VmathVector4 vmathV4RsqrtPerElem_V( VmathVector4 vec ); + +/* + * Compute the absolute value of a 4-D vector per element + */ +static inline VmathVector4 vmathV4AbsPerElem_V( VmathVector4 vec ); + +/* + * Copy sign from one 4-D vector to another, per element + */ +static inline VmathVector4 vmathV4CopySignPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Maximum of two 4-D vectors per element + */ +static inline VmathVector4 vmathV4MaxPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Minimum of two 4-D vectors per element + */ +static inline VmathVector4 vmathV4MinPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Maximum element of a 4-D vector + */ +static inline float vmathV4MaxElem_V( VmathVector4 vec ); + +/* + * Minimum element of a 4-D vector + */ +static inline float vmathV4MinElem_V( VmathVector4 vec ); + +/* + * Compute the sum of all elements of a 4-D vector + */ +static inline float vmathV4Sum_V( VmathVector4 vec ); + +/* + * Compute the dot product of two 4-D vectors + */ +static inline float vmathV4Dot_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Compute the square of the length of a 4-D vector + */ +static inline float vmathV4LengthSqr_V( VmathVector4 vec ); + +/* + * Compute the length of a 4-D vector + */ +static inline float vmathV4Length_V( VmathVector4 vec ); + +/* + * Normalize a 4-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline VmathVector4 vmathV4Normalize_V( VmathVector4 vec ); + +/* + * Outer product of two 4-D vectors + */ +static inline VmathMatrix4 vmathV4Outer_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Linear interpolation between two 4-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathVector4 vmathV4Lerp_V( float t, VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Spherical linear interpolation between two 4-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline VmathVector4 vmathV4Slerp_V( float t, VmathVector4 unitVec0, VmathVector4 unitVec1 ); + +/* + * Conditionally select between two 4-D vectors + */ +static inline VmathVector4 vmathV4Select_V( VmathVector4 vec0, VmathVector4 vec1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV4Print_V( VmathVector4 vec ); + +/* + * Print a 4-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV4Prints_V( VmathVector4 vec, const char *name ); + +#endif + +/* + * Construct a 3-D point from x, y, and z elements + */ +static inline VmathPoint3 vmathP3MakeFromElems_V( float x, float y, float z ); + +/* + * Copy elements from a 3-D vector into a 3-D point + */ +static inline VmathPoint3 vmathP3MakeFromV3_V( VmathVector3 vec ); + +/* + * Set all elements of a 3-D point to the same scalar value + */ +static inline VmathPoint3 vmathP3MakeFromScalar_V( float scalar ); + +/* + * Set the x element of a 3-D point + */ +static inline void vmathP3SetX_V( VmathPoint3 *result, float x ); + +/* + * Set the y element of a 3-D point + */ +static inline void vmathP3SetY_V( VmathPoint3 *result, float y ); + +/* + * Set the z element of a 3-D point + */ +static inline void vmathP3SetZ_V( VmathPoint3 *result, float z ); + +/* + * Get the x element of a 3-D point + */ +static inline float vmathP3GetX_V( VmathPoint3 pnt ); + +/* + * Get the y element of a 3-D point + */ +static inline float vmathP3GetY_V( VmathPoint3 pnt ); + +/* + * Get the z element of a 3-D point + */ +static inline float vmathP3GetZ_V( VmathPoint3 pnt ); + +/* + * Set an x, y, or z element of a 3-D point by index + */ +static inline void vmathP3SetElem_V( VmathPoint3 *result, int idx, float value ); + +/* + * Get an x, y, or z element of a 3-D point by index + */ +static inline float vmathP3GetElem_V( VmathPoint3 pnt, int idx ); + +/* + * Subtract a 3-D point from another 3-D point + */ +static inline VmathVector3 vmathP3Sub_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Add a 3-D point to a 3-D vector + */ +static inline VmathPoint3 vmathP3AddV3_V( VmathPoint3 pnt, VmathVector3 vec ); + +/* + * Subtract a 3-D vector from a 3-D point + */ +static inline VmathPoint3 vmathP3SubV3_V( VmathPoint3 pnt, VmathVector3 vec ); + +/* + * Multiply two 3-D points per element + */ +static inline VmathPoint3 vmathP3MulPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Divide two 3-D points per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline VmathPoint3 vmathP3DivPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Compute the reciprocal of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline VmathPoint3 vmathP3RecipPerElem_V( VmathPoint3 pnt ); + +/* + * Compute the square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline VmathPoint3 vmathP3SqrtPerElem_V( VmathPoint3 pnt ); + +/* + * Compute the reciprocal square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline VmathPoint3 vmathP3RsqrtPerElem_V( VmathPoint3 pnt ); + +/* + * Compute the absolute value of a 3-D point per element + */ +static inline VmathPoint3 vmathP3AbsPerElem_V( VmathPoint3 pnt ); + +/* + * Copy sign from one 3-D point to another, per element + */ +static inline VmathPoint3 vmathP3CopySignPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Maximum of two 3-D points per element + */ +static inline VmathPoint3 vmathP3MaxPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Minimum of two 3-D points per element + */ +static inline VmathPoint3 vmathP3MinPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Maximum element of a 3-D point + */ +static inline float vmathP3MaxElem_V( VmathPoint3 pnt ); + +/* + * Minimum element of a 3-D point + */ +static inline float vmathP3MinElem_V( VmathPoint3 pnt ); + +/* + * Compute the sum of all elements of a 3-D point + */ +static inline float vmathP3Sum_V( VmathPoint3 pnt ); + +/* + * Apply uniform scale to a 3-D point + */ +static inline VmathPoint3 vmathP3Scale_V( VmathPoint3 pnt, float scaleVal ); + +/* + * Apply non-uniform scale to a 3-D point + */ +static inline VmathPoint3 vmathP3NonUniformScale_V( VmathPoint3 pnt, VmathVector3 scaleVec ); + +/* + * Scalar projection of a 3-D point on a unit-length 3-D vector + */ +static inline float vmathP3Projection_V( VmathPoint3 pnt, VmathVector3 unitVec ); + +/* + * Compute the square of the distance of a 3-D point from the coordinate-system origin + */ +static inline float vmathP3DistSqrFromOrigin_V( VmathPoint3 pnt ); + +/* + * Compute the distance of a 3-D point from the coordinate-system origin + */ +static inline float vmathP3DistFromOrigin_V( VmathPoint3 pnt ); + +/* + * Compute the square of the distance between two 3-D points + */ +static inline float vmathP3DistSqr_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Compute the distance between two 3-D points + */ +static inline float vmathP3Dist_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Linear interpolation between two 3-D points + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathPoint3 vmathP3Lerp_V( float t, VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Conditionally select between two 3-D points + */ +static inline VmathPoint3 vmathP3Select_V( VmathPoint3 pnt0, VmathPoint3 pnt1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D point + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathP3Print_V( VmathPoint3 pnt ); + +/* + * Print a 3-D point and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathP3Prints_V( VmathPoint3 pnt, const char *name ); + +#endif + +/* + * Construct a quaternion from x, y, z, and w elements + */ +static inline VmathQuat vmathQMakeFromElems_V( float x, float y, float z, float w ); + +/* + * Construct a quaternion from a 3-D vector and a scalar + */ +static inline VmathQuat vmathQMakeFromV3Scalar_V( VmathVector3 xyz, float w ); + +/* + * Copy elements from a 4-D vector into a quaternion + */ +static inline VmathQuat vmathQMakeFromV4_V( VmathVector4 vec ); + +/* + * Convert a rotation matrix to a unit-length quaternion + */ +static inline VmathQuat vmathQMakeFromM3_V( VmathMatrix3 rotMat ); + +/* + * Set all elements of a quaternion to the same scalar value + */ +static inline VmathQuat vmathQMakeFromScalar_V( float scalar ); + +/* + * Set the x, y, and z elements of a quaternion + * NOTE: + * This function does not change the w element. + */ +static inline void vmathQSetXYZ_V( VmathQuat *result, VmathVector3 vec ); + +/* + * Get the x, y, and z elements of a quaternion + */ +static inline VmathVector3 vmathQGetXYZ_V( VmathQuat quat ); + +/* + * Set the x element of a quaternion + */ +static inline void vmathQSetX_V( VmathQuat *result, float x ); + +/* + * Set the y element of a quaternion + */ +static inline void vmathQSetY_V( VmathQuat *result, float y ); + +/* + * Set the z element of a quaternion + */ +static inline void vmathQSetZ_V( VmathQuat *result, float z ); + +/* + * Set the w element of a quaternion + */ +static inline void vmathQSetW_V( VmathQuat *result, float w ); + +/* + * Get the x element of a quaternion + */ +static inline float vmathQGetX_V( VmathQuat quat ); + +/* + * Get the y element of a quaternion + */ +static inline float vmathQGetY_V( VmathQuat quat ); + +/* + * Get the z element of a quaternion + */ +static inline float vmathQGetZ_V( VmathQuat quat ); + +/* + * Get the w element of a quaternion + */ +static inline float vmathQGetW_V( VmathQuat quat ); + +/* + * Set an x, y, z, or w element of a quaternion by index + */ +static inline void vmathQSetElem_V( VmathQuat *result, int idx, float value ); + +/* + * Get an x, y, z, or w element of a quaternion by index + */ +static inline float vmathQGetElem_V( VmathQuat quat, int idx ); + +/* + * Add two quaternions + */ +static inline VmathQuat vmathQAdd_V( VmathQuat quat0, VmathQuat quat1 ); + +/* + * Subtract a quaternion from another quaternion + */ +static inline VmathQuat vmathQSub_V( VmathQuat quat0, VmathQuat quat1 ); + +/* + * Multiply two quaternions + */ +static inline VmathQuat vmathQMul_V( VmathQuat quat0, VmathQuat quat1 ); + +/* + * Multiply a quaternion by a scalar + */ +static inline VmathQuat vmathQScalarMul_V( VmathQuat quat, float scalar ); + +/* + * Divide a quaternion by a scalar + */ +static inline VmathQuat vmathQScalarDiv_V( VmathQuat quat, float scalar ); + +/* + * Negate all elements of a quaternion + */ +static inline VmathQuat vmathQNeg_V( VmathQuat quat ); + +/* + * Construct an identity quaternion + */ +static inline VmathQuat vmathQMakeIdentity_V( ); + +/* + * Construct a quaternion to rotate between two unit-length 3-D vectors + * NOTE: + * The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + */ +static inline VmathQuat vmathQMakeRotationArc_V( VmathVector3 unitVec0, VmathVector3 unitVec1 ); + +/* + * Construct a quaternion to rotate around a unit-length 3-D vector + */ +static inline VmathQuat vmathQMakeRotationAxis_V( float radians, VmathVector3 unitVec ); + +/* + * Construct a quaternion to rotate around the x axis + */ +static inline VmathQuat vmathQMakeRotationX_V( float radians ); + +/* + * Construct a quaternion to rotate around the y axis + */ +static inline VmathQuat vmathQMakeRotationY_V( float radians ); + +/* + * Construct a quaternion to rotate around the z axis + */ +static inline VmathQuat vmathQMakeRotationZ_V( float radians ); + +/* + * Compute the conjugate of a quaternion + */ +static inline VmathQuat vmathQConj_V( VmathQuat quat ); + +/* + * Use a unit-length quaternion to rotate a 3-D vector + */ +static inline VmathVector3 vmathQRotate_V( VmathQuat unitQuat, VmathVector3 vec ); + +/* + * Compute the dot product of two quaternions + */ +static inline float vmathQDot_V( VmathQuat quat0, VmathQuat quat1 ); + +/* + * Compute the norm of a quaternion + */ +static inline float vmathQNorm_V( VmathQuat quat ); + +/* + * Compute the length of a quaternion + */ +static inline float vmathQLength_V( VmathQuat quat ); + +/* + * Normalize a quaternion + * NOTE: + * The result is unpredictable when all elements of quat are at or near zero. + */ +static inline VmathQuat vmathQNormalize_V( VmathQuat quat ); + +/* + * Linear interpolation between two quaternions + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathQuat vmathQLerp_V( float t, VmathQuat quat0, VmathQuat quat1 ); + +/* + * Spherical linear interpolation between two quaternions + * NOTE: + * Interpolates along the shortest path between orientations. + * Does not clamp t between 0 and 1. + */ +static inline VmathQuat vmathQSlerp_V( float t, VmathQuat unitQuat0, VmathQuat unitQuat1 ); + +/* + * Spherical quadrangle interpolation + */ +static inline VmathQuat vmathQSquad_V( float t, VmathQuat unitQuat0, VmathQuat unitQuat1, VmathQuat unitQuat2, VmathQuat unitQuat3 ); + +/* + * Conditionally select between two quaternions + */ +static inline VmathQuat vmathQSelect_V( VmathQuat quat0, VmathQuat quat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a quaternion + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathQPrint_V( VmathQuat quat ); + +/* + * Print a quaternion and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathQPrints_V( VmathQuat quat, const char *name ); + +#endif + +/* + * Construct a 3x3 matrix containing the specified columns + */ +static inline VmathMatrix3 vmathM3MakeFromCols_V( VmathVector3 col0, VmathVector3 col1, VmathVector3 col2 ); + +/* + * Construct a 3x3 rotation matrix from a unit-length quaternion + */ +static inline VmathMatrix3 vmathM3MakeFromQ_V( VmathQuat unitQuat ); + +/* + * Set all elements of a 3x3 matrix to the same scalar value + */ +static inline VmathMatrix3 vmathM3MakeFromScalar_V( float scalar ); + +/* + * Set column 0 of a 3x3 matrix + */ +static inline void vmathM3SetCol0_V( VmathMatrix3 *result, VmathVector3 col0 ); + +/* + * Set column 1 of a 3x3 matrix + */ +static inline void vmathM3SetCol1_V( VmathMatrix3 *result, VmathVector3 col1 ); + +/* + * Set column 2 of a 3x3 matrix + */ +static inline void vmathM3SetCol2_V( VmathMatrix3 *result, VmathVector3 col2 ); + +/* + * Get column 0 of a 3x3 matrix + */ +static inline VmathVector3 vmathM3GetCol0_V( VmathMatrix3 mat ); + +/* + * Get column 1 of a 3x3 matrix + */ +static inline VmathVector3 vmathM3GetCol1_V( VmathMatrix3 mat ); + +/* + * Get column 2 of a 3x3 matrix + */ +static inline VmathVector3 vmathM3GetCol2_V( VmathMatrix3 mat ); + +/* + * Set the column of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3SetCol_V( VmathMatrix3 *result, int col, VmathVector3 vec ); + +/* + * Set the row of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3SetRow_V( VmathMatrix3 *result, int row, VmathVector3 vec ); + +/* + * Get the column of a 3x3 matrix referred to by the specified index + */ +static inline VmathVector3 vmathM3GetCol_V( VmathMatrix3 mat, int col ); + +/* + * Get the row of a 3x3 matrix referred to by the specified index + */ +static inline VmathVector3 vmathM3GetRow_V( VmathMatrix3 mat, int row ); + +/* + * Set the element of a 3x3 matrix referred to by column and row indices + */ +static inline void vmathM3SetElem_V( VmathMatrix3 *result, int col, int row, float val ); + +/* + * Get the element of a 3x3 matrix referred to by column and row indices + */ +static inline float vmathM3GetElem_V( VmathMatrix3 mat, int col, int row ); + +/* + * Add two 3x3 matrices + */ +static inline VmathMatrix3 vmathM3Add_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ); + +/* + * Subtract a 3x3 matrix from another 3x3 matrix + */ +static inline VmathMatrix3 vmathM3Sub_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ); + +/* + * Negate all elements of a 3x3 matrix + */ +static inline VmathMatrix3 vmathM3Neg_V( VmathMatrix3 mat ); + +/* + * Multiply a 3x3 matrix by a scalar + */ +static inline VmathMatrix3 vmathM3ScalarMul_V( VmathMatrix3 mat, float scalar ); + +/* + * Multiply a 3x3 matrix by a 3-D vector + */ +static inline VmathVector3 vmathM3MulV3_V( VmathMatrix3 mat, VmathVector3 vec ); + +/* + * Multiply two 3x3 matrices + */ +static inline VmathMatrix3 vmathM3Mul_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ); + +/* + * Construct an identity 3x3 matrix + */ +static inline VmathMatrix3 vmathM3MakeIdentity_V( ); + +/* + * Construct a 3x3 matrix to rotate around the x axis + */ +static inline VmathMatrix3 vmathM3MakeRotationX_V( float radians ); + +/* + * Construct a 3x3 matrix to rotate around the y axis + */ +static inline VmathMatrix3 vmathM3MakeRotationY_V( float radians ); + +/* + * Construct a 3x3 matrix to rotate around the z axis + */ +static inline VmathMatrix3 vmathM3MakeRotationZ_V( float radians ); + +/* + * Construct a 3x3 matrix to rotate around the x, y, and z axes + */ +static inline VmathMatrix3 vmathM3MakeRotationZYX_V( VmathVector3 radiansXYZ ); + +/* + * Construct a 3x3 matrix to rotate around a unit-length 3-D vector + */ +static inline VmathMatrix3 vmathM3MakeRotationAxis_V( float radians, VmathVector3 unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline VmathMatrix3 vmathM3MakeRotationQ_V( VmathQuat unitQuat ); + +/* + * Construct a 3x3 matrix to perform scaling + */ +static inline VmathMatrix3 vmathM3MakeScale_V( VmathVector3 scaleVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathMatrix3 vmathM3AppendScale_V( VmathMatrix3 mat, VmathVector3 scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathMatrix3 vmathM3PrependScale_V( VmathVector3 scaleVec, VmathMatrix3 mat ); + +/* + * Multiply two 3x3 matrices per element + */ +static inline VmathMatrix3 vmathM3MulPerElem_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ); + +/* + * Compute the absolute value of a 3x3 matrix per element + */ +static inline VmathMatrix3 vmathM3AbsPerElem_V( VmathMatrix3 mat ); + +/* + * Transpose of a 3x3 matrix + */ +static inline VmathMatrix3 vmathM3Transpose_V( VmathMatrix3 mat ); + +/* + * Compute the inverse of a 3x3 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline VmathMatrix3 vmathM3Inverse_V( VmathMatrix3 mat ); + +/* + * Determinant of a 3x3 matrix + */ +static inline float vmathM3Determinant_V( VmathMatrix3 mat ); + +/* + * Conditionally select between two 3x3 matrices + */ +static inline VmathMatrix3 vmathM3Select_V( VmathMatrix3 mat0, VmathMatrix3 mat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x3 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM3Print_V( VmathMatrix3 mat ); + +/* + * Print a 3x3 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM3Prints_V( VmathMatrix3 mat, const char *name ); + +#endif + +/* + * Construct a 4x4 matrix containing the specified columns + */ +static inline VmathMatrix4 vmathM4MakeFromCols_V( VmathVector4 col0, VmathVector4 col1, VmathVector4 col2, VmathVector4 col3 ); + +/* + * Construct a 4x4 matrix from a 3x4 transformation matrix + */ +static inline VmathMatrix4 vmathM4MakeFromT3_V( VmathTransform3 mat ); + +/* + * Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + */ +static inline VmathMatrix4 vmathM4MakeFromM3V3_V( VmathMatrix3 mat, VmathVector3 translateVec ); + +/* + * Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + */ +static inline VmathMatrix4 vmathM4MakeFromQV3_V( VmathQuat unitQuat, VmathVector3 translateVec ); + +/* + * Set all elements of a 4x4 matrix to the same scalar value + */ +static inline VmathMatrix4 vmathM4MakeFromScalar_V( float scalar ); + +/* + * Set the upper-left 3x3 submatrix + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathM4SetUpper3x3_V( VmathMatrix4 *result, VmathMatrix3 mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 4x4 matrix + */ +static inline VmathMatrix3 vmathM4GetUpper3x3_V( VmathMatrix4 mat ); + +/* + * Set translation component + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathM4SetTranslation_V( VmathMatrix4 *result, VmathVector3 translateVec ); + +/* + * Get the translation component of a 4x4 matrix + */ +static inline VmathVector3 vmathM4GetTranslation_V( VmathMatrix4 mat ); + +/* + * Set column 0 of a 4x4 matrix + */ +static inline void vmathM4SetCol0_V( VmathMatrix4 *result, VmathVector4 col0 ); + +/* + * Set column 1 of a 4x4 matrix + */ +static inline void vmathM4SetCol1_V( VmathMatrix4 *result, VmathVector4 col1 ); + +/* + * Set column 2 of a 4x4 matrix + */ +static inline void vmathM4SetCol2_V( VmathMatrix4 *result, VmathVector4 col2 ); + +/* + * Set column 3 of a 4x4 matrix + */ +static inline void vmathM4SetCol3_V( VmathMatrix4 *result, VmathVector4 col3 ); + +/* + * Get column 0 of a 4x4 matrix + */ +static inline VmathVector4 vmathM4GetCol0_V( VmathMatrix4 mat ); + +/* + * Get column 1 of a 4x4 matrix + */ +static inline VmathVector4 vmathM4GetCol1_V( VmathMatrix4 mat ); + +/* + * Get column 2 of a 4x4 matrix + */ +static inline VmathVector4 vmathM4GetCol2_V( VmathMatrix4 mat ); + +/* + * Get column 3 of a 4x4 matrix + */ +static inline VmathVector4 vmathM4GetCol3_V( VmathMatrix4 mat ); + +/* + * Set the column of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4SetCol_V( VmathMatrix4 *result, int col, VmathVector4 vec ); + +/* + * Set the row of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4SetRow_V( VmathMatrix4 *result, int row, VmathVector4 vec ); + +/* + * Get the column of a 4x4 matrix referred to by the specified index + */ +static inline VmathVector4 vmathM4GetCol_V( VmathMatrix4 mat, int col ); + +/* + * Get the row of a 4x4 matrix referred to by the specified index + */ +static inline VmathVector4 vmathM4GetRow_V( VmathMatrix4 mat, int row ); + +/* + * Set the element of a 4x4 matrix referred to by column and row indices + */ +static inline void vmathM4SetElem_V( VmathMatrix4 *result, int col, int row, float val ); + +/* + * Get the element of a 4x4 matrix referred to by column and row indices + */ +static inline float vmathM4GetElem_V( VmathMatrix4 mat, int col, int row ); + +/* + * Add two 4x4 matrices + */ +static inline VmathMatrix4 vmathM4Add_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ); + +/* + * Subtract a 4x4 matrix from another 4x4 matrix + */ +static inline VmathMatrix4 vmathM4Sub_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ); + +/* + * Negate all elements of a 4x4 matrix + */ +static inline VmathMatrix4 vmathM4Neg_V( VmathMatrix4 mat ); + +/* + * Multiply a 4x4 matrix by a scalar + */ +static inline VmathMatrix4 vmathM4ScalarMul_V( VmathMatrix4 mat, float scalar ); + +/* + * Multiply a 4x4 matrix by a 4-D vector + */ +static inline VmathVector4 vmathM4MulV4_V( VmathMatrix4 mat, VmathVector4 vec ); + +/* + * Multiply a 4x4 matrix by a 3-D vector + */ +static inline VmathVector4 vmathM4MulV3_V( VmathMatrix4 mat, VmathVector3 vec ); + +/* + * Multiply a 4x4 matrix by a 3-D point + */ +static inline VmathVector4 vmathM4MulP3_V( VmathMatrix4 mat, VmathPoint3 pnt ); + +/* + * Multiply two 4x4 matrices + */ +static inline VmathMatrix4 vmathM4Mul_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ); + +/* + * Multiply a 4x4 matrix by a 3x4 transformation matrix + */ +static inline VmathMatrix4 vmathM4MulT3_V( VmathMatrix4 mat, VmathTransform3 tfrm ); + +/* + * Construct an identity 4x4 matrix + */ +static inline VmathMatrix4 vmathM4MakeIdentity_V( ); + +/* + * Construct a 4x4 matrix to rotate around the x axis + */ +static inline VmathMatrix4 vmathM4MakeRotationX_V( float radians ); + +/* + * Construct a 4x4 matrix to rotate around the y axis + */ +static inline VmathMatrix4 vmathM4MakeRotationY_V( float radians ); + +/* + * Construct a 4x4 matrix to rotate around the z axis + */ +static inline VmathMatrix4 vmathM4MakeRotationZ_V( float radians ); + +/* + * Construct a 4x4 matrix to rotate around the x, y, and z axes + */ +static inline VmathMatrix4 vmathM4MakeRotationZYX_V( VmathVector3 radiansXYZ ); + +/* + * Construct a 4x4 matrix to rotate around a unit-length 3-D vector + */ +static inline VmathMatrix4 vmathM4MakeRotationAxis_V( float radians, VmathVector3 unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline VmathMatrix4 vmathM4MakeRotationQ_V( VmathQuat unitQuat ); + +/* + * Construct a 4x4 matrix to perform scaling + */ +static inline VmathMatrix4 vmathM4MakeScale_V( VmathVector3 scaleVec ); + +/* + * Construct a 4x4 matrix to perform translation + */ +static inline VmathMatrix4 vmathM4MakeTranslation_V( VmathVector3 translateVec ); + +/* + * Construct viewing matrix based on eye position, position looked at, and up direction + */ +static inline VmathMatrix4 vmathM4MakeLookAt_V( VmathPoint3 eyePos, VmathPoint3 lookAtPos, VmathVector3 upVec ); + +/* + * Construct a perspective projection matrix + */ +static inline VmathMatrix4 vmathM4MakePerspective_V( float fovyRadians, float aspect, float zNear, float zFar ); + +/* + * Construct a perspective projection matrix based on frustum + */ +static inline VmathMatrix4 vmathM4MakeFrustum_V( float left, float right, float bottom, float top, float zNear, float zFar ); + +/* + * Construct an orthographic projection matrix + */ +static inline VmathMatrix4 vmathM4MakeOrthographic_V( float left, float right, float bottom, float top, float zNear, float zFar ); + +/* + * Append (post-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathMatrix4 vmathM4AppendScale_V( VmathMatrix4 mat, VmathVector3 scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathMatrix4 vmathM4PrependScale_V( VmathVector3 scaleVec, VmathMatrix4 mat ); + +/* + * Multiply two 4x4 matrices per element + */ +static inline VmathMatrix4 vmathM4MulPerElem_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ); + +/* + * Compute the absolute value of a 4x4 matrix per element + */ +static inline VmathMatrix4 vmathM4AbsPerElem_V( VmathMatrix4 mat ); + +/* + * Transpose of a 4x4 matrix + */ +static inline VmathMatrix4 vmathM4Transpose_V( VmathMatrix4 mat ); + +/* + * Compute the inverse of a 4x4 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline VmathMatrix4 vmathM4Inverse_V( VmathMatrix4 mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline VmathMatrix4 vmathM4AffineInverse_V( VmathMatrix4 mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. + */ +static inline VmathMatrix4 vmathM4OrthoInverse_V( VmathMatrix4 mat ); + +/* + * Determinant of a 4x4 matrix + */ +static inline float vmathM4Determinant_V( VmathMatrix4 mat ); + +/* + * Conditionally select between two 4x4 matrices + */ +static inline VmathMatrix4 vmathM4Select_V( VmathMatrix4 mat0, VmathMatrix4 mat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4x4 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM4Print_V( VmathMatrix4 mat ); + +/* + * Print a 4x4 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM4Prints_V( VmathMatrix4 mat, const char *name ); + +#endif + +/* + * Construct a 3x4 transformation matrix containing the specified columns + */ +static inline VmathTransform3 vmathT3MakeFromCols_V( VmathVector3 col0, VmathVector3 col1, VmathVector3 col2, VmathVector3 col3 ); + +/* + * Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + */ +static inline VmathTransform3 vmathT3MakeFromM3V3_V( VmathMatrix3 tfrm, VmathVector3 translateVec ); + +/* + * Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + */ +static inline VmathTransform3 vmathT3MakeFromQV3_V( VmathQuat unitQuat, VmathVector3 translateVec ); + +/* + * Set all elements of a 3x4 transformation matrix to the same scalar value + */ +static inline VmathTransform3 vmathT3MakeFromScalar_V( float scalar ); + +/* + * Set the upper-left 3x3 submatrix + */ +static inline void vmathT3SetUpper3x3_V( VmathTransform3 *result, VmathMatrix3 mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + */ +static inline VmathMatrix3 vmathT3GetUpper3x3_V( VmathTransform3 tfrm ); + +/* + * Set translation component + */ +static inline void vmathT3SetTranslation_V( VmathTransform3 *result, VmathVector3 translateVec ); + +/* + * Get the translation component of a 3x4 transformation matrix + */ +static inline VmathVector3 vmathT3GetTranslation_V( VmathTransform3 tfrm ); + +/* + * Set column 0 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol0_V( VmathTransform3 *result, VmathVector3 col0 ); + +/* + * Set column 1 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol1_V( VmathTransform3 *result, VmathVector3 col1 ); + +/* + * Set column 2 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol2_V( VmathTransform3 *result, VmathVector3 col2 ); + +/* + * Set column 3 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol3_V( VmathTransform3 *result, VmathVector3 col3 ); + +/* + * Get column 0 of a 3x4 transformation matrix + */ +static inline VmathVector3 vmathT3GetCol0_V( VmathTransform3 tfrm ); + +/* + * Get column 1 of a 3x4 transformation matrix + */ +static inline VmathVector3 vmathT3GetCol1_V( VmathTransform3 tfrm ); + +/* + * Get column 2 of a 3x4 transformation matrix + */ +static inline VmathVector3 vmathT3GetCol2_V( VmathTransform3 tfrm ); + +/* + * Get column 3 of a 3x4 transformation matrix + */ +static inline VmathVector3 vmathT3GetCol3_V( VmathTransform3 tfrm ); + +/* + * Set the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3SetCol_V( VmathTransform3 *result, int col, VmathVector3 vec ); + +/* + * Set the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3SetRow_V( VmathTransform3 *result, int row, VmathVector4 vec ); + +/* + * Get the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline VmathVector3 vmathT3GetCol_V( VmathTransform3 tfrm, int col ); + +/* + * Get the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline VmathVector4 vmathT3GetRow_V( VmathTransform3 tfrm, int row ); + +/* + * Set the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline void vmathT3SetElem_V( VmathTransform3 *result, int col, int row, float val ); + +/* + * Get the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline float vmathT3GetElem_V( VmathTransform3 tfrm, int col, int row ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D vector + */ +static inline VmathVector3 vmathT3MulV3_V( VmathTransform3 tfrm, VmathVector3 vec ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D point + */ +static inline VmathPoint3 vmathT3MulP3_V( VmathTransform3 tfrm, VmathPoint3 pnt ); + +/* + * Multiply two 3x4 transformation matrices + */ +static inline VmathTransform3 vmathT3Mul_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1 ); + +/* + * Construct an identity 3x4 transformation matrix + */ +static inline VmathTransform3 vmathT3MakeIdentity_V( ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x axis + */ +static inline VmathTransform3 vmathT3MakeRotationX_V( float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the y axis + */ +static inline VmathTransform3 vmathT3MakeRotationY_V( float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the z axis + */ +static inline VmathTransform3 vmathT3MakeRotationZ_V( float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + */ +static inline VmathTransform3 vmathT3MakeRotationZYX_V( VmathVector3 radiansXYZ ); + +/* + * Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + */ +static inline VmathTransform3 vmathT3MakeRotationAxis_V( float radians, VmathVector3 unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline VmathTransform3 vmathT3MakeRotationQ_V( VmathQuat unitQuat ); + +/* + * Construct a 3x4 transformation matrix to perform scaling + */ +static inline VmathTransform3 vmathT3MakeScale_V( VmathVector3 scaleVec ); + +/* + * Construct a 3x4 transformation matrix to perform translation + */ +static inline VmathTransform3 vmathT3MakeTranslation_V( VmathVector3 translateVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathTransform3 vmathT3AppendScale_V( VmathTransform3 tfrm, VmathVector3 scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathTransform3 vmathT3PrependScale_V( VmathVector3 scaleVec, VmathTransform3 tfrm ); + +/* + * Multiply two 3x4 transformation matrices per element + */ +static inline VmathTransform3 vmathT3MulPerElem_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1 ); + +/* + * Compute the absolute value of a 3x4 transformation matrix per element + */ +static inline VmathTransform3 vmathT3AbsPerElem_V( VmathTransform3 tfrm ); + +/* + * Inverse of a 3x4 transformation matrix + * NOTE: + * Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. + */ +static inline VmathTransform3 vmathT3Inverse_V( VmathTransform3 tfrm ); + +/* + * Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. + */ +static inline VmathTransform3 vmathT3OrthoInverse_V( VmathTransform3 tfrm ); + +/* + * Conditionally select between two 3x4 transformation matrices + */ +static inline VmathTransform3 vmathT3Select_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x4 transformation matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathT3Print_V( VmathTransform3 tfrm ); + +/* + * Print a 3x4 transformation matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathT3Prints_V( VmathTransform3 tfrm, const char *name ); + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#include "vectormath_aos.h" +#include "vec_aos_v.h" +#include "quat_aos_v.h" +#include "mat_aos_v.h" + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/scalar/cpp/boolInVec.h b/Extras/vectormathlibrary/include/vectormath/scalar/cpp/boolInVec.h new file mode 100644 index 0000000..7ea380f --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/scalar/cpp/boolInVec.h @@ -0,0 +1,238 @@ +/* + Copyright (C) 2006-2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _BOOLINVEC_SCALAR_H +#define _BOOLINVEC_SCALAR_H + +#include +namespace Vectormath { + +class floatInVec; + +//-------------------------------------------------------------------------------------------------- +// boolInVec class +// + +class boolInVec +{ +private: + unsigned int mData; + +public: + // Default constructor; does no initialization + // + inline boolInVec( ) { }; + + // Construct from a value converted from float + // + inline boolInVec(floatInVec vec); + + // Explicit cast from bool + // + explicit inline boolInVec(bool scalar); + + // Explicit cast to bool + // + inline bool getAsBool() const; + +#ifndef _VECTORMATH_NO_SCALAR_CAST + // Implicit cast to bool + // + inline operator bool() const; +#endif + + // Boolean negation operator + // + inline const boolInVec operator ! () const; + + // Assignment operator + // + inline boolInVec& operator = (boolInVec vec); + + // Boolean and assignment operator + // + inline boolInVec& operator &= (boolInVec vec); + + // Boolean exclusive or assignment operator + // + inline boolInVec& operator ^= (boolInVec vec); + + // Boolean or assignment operator + // + inline boolInVec& operator |= (boolInVec vec); + +}; + +// Equal operator +// +inline const boolInVec operator == (boolInVec vec0, boolInVec vec1); + +// Not equal operator +// +inline const boolInVec operator != (boolInVec vec0, boolInVec vec1); + +// And operator +// +inline const boolInVec operator & (boolInVec vec0, boolInVec vec1); + +// Exclusive or operator +// +inline const boolInVec operator ^ (boolInVec vec0, boolInVec vec1); + +// Or operator +// +inline const boolInVec operator | (boolInVec vec0, boolInVec vec1); + +// Conditionally select between two values +// +inline const boolInVec select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1); + + +} // namespace Vectormath + + +//-------------------------------------------------------------------------------------------------- +// boolInVec implementation +// + +#include "floatInVec.h" + +namespace Vectormath { + +inline +boolInVec::boolInVec(floatInVec vec) +{ + *this = (vec != floatInVec(0.0f)); +} + +inline +boolInVec::boolInVec(bool scalar) +{ + mData = -(int)scalar; +} + +inline +bool +boolInVec::getAsBool() const +{ + return (mData > 0); +} + +#ifndef _VECTORMATH_NO_SCALAR_CAST +inline +boolInVec::operator bool() const +{ + return getAsBool(); +} +#endif + +inline +const boolInVec +boolInVec::operator ! () const +{ + return boolInVec(!mData); +} + +inline +boolInVec& +boolInVec::operator = (boolInVec vec) +{ + mData = vec.mData; + return *this; +} + +inline +boolInVec& +boolInVec::operator &= (boolInVec vec) +{ + *this = *this & vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator ^= (boolInVec vec) +{ + *this = *this ^ vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator |= (boolInVec vec) +{ + *this = *this | vec; + return *this; +} + +inline +const boolInVec +operator == (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() == vec1.getAsBool()); +} + +inline +const boolInVec +operator != (boolInVec vec0, boolInVec vec1) +{ + return !(vec0 == vec1); +} + +inline +const boolInVec +operator & (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() & vec1.getAsBool()); +} + +inline +const boolInVec +operator | (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() | vec1.getAsBool()); +} + +inline +const boolInVec +operator ^ (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() ^ vec1.getAsBool()); +} + +inline +const boolInVec +select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1) +{ + return (select_vec1.getAsBool() == 0) ? vec0 : vec1; +} + +} // namespace Vectormath + +#endif // boolInVec_h diff --git a/Extras/vectormathlibrary/include/vectormath/scalar/cpp/floatInVec.h b/Extras/vectormathlibrary/include/vectormath/scalar/cpp/floatInVec.h new file mode 100644 index 0000000..1aa2ee1 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/scalar/cpp/floatInVec.h @@ -0,0 +1,357 @@ +/* + Copyright (C) 2006-2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _FLOATINVEC__SCALAR_H +#define _FLOATINVEC__SCALAR_H + +#include +namespace Vectormath { + +class boolInVec; + +//-------------------------------------------------------------------------------------------------- +// floatInVec class +// + +// A class representing a scalar float value contained in a vector register +// This class does not support fastmath +class floatInVec +{ +private: + float mData; + +public: + // Default constructor; does no initialization + // + inline floatInVec( ) { }; + + // Construct from a value converted from bool + // + inline floatInVec(boolInVec vec); + + // Explicit cast from float + // + explicit inline floatInVec(float scalar); + + // Explicit cast to float + // + inline float getAsFloat() const; + +#ifndef _VECTORMATH_NO_SCALAR_CAST + // Implicit cast to float + // + inline operator float() const; +#endif + + // Post increment (add 1.0f) + // + inline const floatInVec operator ++ (int); + + // Post decrement (subtract 1.0f) + // + inline const floatInVec operator -- (int); + + // Pre increment (add 1.0f) + // + inline floatInVec& operator ++ (); + + // Pre decrement (subtract 1.0f) + // + inline floatInVec& operator -- (); + + // Negation operator + // + inline const floatInVec operator - () const; + + // Assignment operator + // + inline floatInVec& operator = (floatInVec vec); + + // Multiplication assignment operator + // + inline floatInVec& operator *= (floatInVec vec); + + // Division assignment operator + // + inline floatInVec& operator /= (floatInVec vec); + + // Addition assignment operator + // + inline floatInVec& operator += (floatInVec vec); + + // Subtraction assignment operator + // + inline floatInVec& operator -= (floatInVec vec); + +}; + +// Multiplication operator +// +inline const floatInVec operator * (floatInVec vec0, floatInVec vec1); + +// Division operator +// +inline const floatInVec operator / (floatInVec vec0, floatInVec vec1); + +// Addition operator +// +inline const floatInVec operator + (floatInVec vec0, floatInVec vec1); + +// Subtraction operator +// +inline const floatInVec operator - (floatInVec vec0, floatInVec vec1); + +// Less than operator +// +inline const boolInVec operator < (floatInVec vec0, floatInVec vec1); + +// Less than or equal operator +// +inline const boolInVec operator <= (floatInVec vec0, floatInVec vec1); + +// Greater than operator +// +inline const boolInVec operator > (floatInVec vec0, floatInVec vec1); + +// Greater than or equal operator +// +inline const boolInVec operator >= (floatInVec vec0, floatInVec vec1); + +// Equal operator +// +inline const boolInVec operator == (floatInVec vec0, floatInVec vec1); + +// Not equal operator +// +inline const boolInVec operator != (floatInVec vec0, floatInVec vec1); + +// Conditionally select between two values +// +inline const floatInVec select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1); + + +} // namespace Vectormath + + +//-------------------------------------------------------------------------------------------------- +// floatInVec implementation +// + +#include "boolInVec.h" + +namespace Vectormath { + +inline +floatInVec::floatInVec(boolInVec vec) +{ + mData = float(vec.getAsBool()); +} + +inline +floatInVec::floatInVec(float scalar) +{ + mData = scalar; +} + +inline +float +floatInVec::getAsFloat() const +{ + return mData; +} + +#ifndef _VECTORMATH_NO_SCALAR_CAST +inline +floatInVec::operator float() const +{ + return getAsFloat(); +} +#endif + +inline +const floatInVec +floatInVec::operator ++ (int) +{ + float olddata = mData; + operator ++(); + return floatInVec(olddata); +} + +inline +const floatInVec +floatInVec::operator -- (int) +{ + float olddata = mData; + operator --(); + return floatInVec(olddata); +} + +inline +floatInVec& +floatInVec::operator ++ () +{ + *this += floatInVec(1.0f); + return *this; +} + +inline +floatInVec& +floatInVec::operator -- () +{ + *this -= floatInVec(1.0f); + return *this; +} + +inline +const floatInVec +floatInVec::operator - () const +{ + return floatInVec(-mData); +} + +inline +floatInVec& +floatInVec::operator = (floatInVec vec) +{ + mData = vec.mData; + return *this; +} + +inline +floatInVec& +floatInVec::operator *= (floatInVec vec) +{ + *this = *this * vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator /= (floatInVec vec) +{ + *this = *this / vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator += (floatInVec vec) +{ + *this = *this + vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator -= (floatInVec vec) +{ + *this = *this - vec; + return *this; +} + +inline +const floatInVec +operator * (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() * vec1.getAsFloat()); +} + +inline +const floatInVec +operator / (floatInVec num, floatInVec den) +{ + return floatInVec(num.getAsFloat() / den.getAsFloat()); +} + +inline +const floatInVec +operator + (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() + vec1.getAsFloat()); +} + +inline +const floatInVec +operator - (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() - vec1.getAsFloat()); +} + +inline +const boolInVec +operator < (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() < vec1.getAsFloat()); +} + +inline +const boolInVec +operator <= (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 > vec1); +} + +inline +const boolInVec +operator > (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() > vec1.getAsFloat()); +} + +inline +const boolInVec +operator >= (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 < vec1); +} + +inline +const boolInVec +operator == (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() == vec1.getAsFloat()); +} + +inline +const boolInVec +operator != (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 == vec1); +} + +inline +const floatInVec +select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1) +{ + return (select_vec1.getAsBool() == 0) ? vec0 : vec1; +} + +} // namespace Vectormath + +#endif // floatInVec_h diff --git a/Extras/vectormathlibrary/include/vectormath/scalar/cpp/mat_aos.h b/Extras/vectormathlibrary/include/vectormath/scalar/cpp/mat_aos.h new file mode 100644 index 0000000..1ea2c77 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/scalar/cpp/mat_aos.h @@ -0,0 +1,1643 @@ +/* + Copyright (C) 2006-2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_AOS_CPP__SCALAR_H +#define _VECTORMATH_MAT_AOS_CPP__SCALAR_H + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// Constants + +#define _VECTORMATH_PI_OVER_2 1.570796327f + +//----------------------------------------------------------------------------- +// Definitions + +inline Matrix3::Matrix3( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; +} + +inline Matrix3::Matrix3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +inline Matrix3::Matrix3( const Quat & unitQuat ) +{ + float qx, qy, qz, qw, qx2, qy2, qz2, qxqx2, qyqy2, qzqz2, qxqy2, qyqz2, qzqw2, qxqz2, qyqw2, qxqw2; + qx = unitQuat.getX(); + qy = unitQuat.getY(); + qz = unitQuat.getZ(); + qw = unitQuat.getW(); + qx2 = ( qx + qx ); + qy2 = ( qy + qy ); + qz2 = ( qz + qz ); + qxqx2 = ( qx * qx2 ); + qxqy2 = ( qx * qy2 ); + qxqz2 = ( qx * qz2 ); + qxqw2 = ( qw * qx2 ); + qyqy2 = ( qy * qy2 ); + qyqz2 = ( qy * qz2 ); + qyqw2 = ( qw * qy2 ); + qzqz2 = ( qz * qz2 ); + qzqw2 = ( qw * qz2 ); + mCol0 = Vector3( ( ( 1.0f - qyqy2 ) - qzqz2 ), ( qxqy2 + qzqw2 ), ( qxqz2 - qyqw2 ) ); + mCol1 = Vector3( ( qxqy2 - qzqw2 ), ( ( 1.0f - qxqx2 ) - qzqz2 ), ( qyqz2 + qxqw2 ) ); + mCol2 = Vector3( ( qxqz2 + qyqw2 ), ( qyqz2 - qxqw2 ), ( ( 1.0f - qxqx2 ) - qyqy2 ) ); +} + +inline Matrix3::Matrix3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; +} + +inline Matrix3 & Matrix3::setCol0( const Vector3 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix3 & Matrix3::setCol1( const Vector3 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix3 & Matrix3::setCol2( const Vector3 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix3 & Matrix3::setCol( int col, const Vector3 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix3 & Matrix3::setRow( int row, const Vector3 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + return *this; +} + +inline Matrix3 & Matrix3::setElem( int col, int row, float val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Matrix3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Matrix3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Matrix3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Matrix3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Matrix3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::getRow( int row ) const +{ + return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); +} + +inline Vector3 & Matrix3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix3 & Matrix3::operator =( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + return *this; +} + +inline const Matrix3 transpose( const Matrix3 & mat ) +{ + return Matrix3( + Vector3( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX() ), + Vector3( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY() ), + Vector3( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ() ) + ); +} + +inline const Matrix3 inverse( const Matrix3 & mat ) +{ + Vector3 tmp0, tmp1, tmp2; + float detinv; + tmp0 = cross( mat.getCol1(), mat.getCol2() ); + tmp1 = cross( mat.getCol2(), mat.getCol0() ); + tmp2 = cross( mat.getCol0(), mat.getCol1() ); + detinv = ( 1.0f / dot( mat.getCol2(), tmp2 ) ); + return Matrix3( + Vector3( ( tmp0.getX() * detinv ), ( tmp1.getX() * detinv ), ( tmp2.getX() * detinv ) ), + Vector3( ( tmp0.getY() * detinv ), ( tmp1.getY() * detinv ), ( tmp2.getY() * detinv ) ), + Vector3( ( tmp0.getZ() * detinv ), ( tmp1.getZ() * detinv ), ( tmp2.getZ() * detinv ) ) + ); +} + +inline float determinant( const Matrix3 & mat ) +{ + return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); +} + +inline const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ) + ); +} + +inline const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix3 Matrix3::operator -( ) const +{ + return Matrix3( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ) + ); +} + +inline const Matrix3 absPerElem( const Matrix3 & mat ) +{ + return Matrix3( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::operator *( float scalar ) const +{ + return Matrix3( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ) + ); +} + +inline Matrix3 & Matrix3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix3 operator *( float scalar, const Matrix3 & mat ) +{ + return mat * scalar; +} + +inline const Vector3 Matrix3::operator *( const Vector3 & vec ) const +{ + return Vector3( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ); +} + +inline const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const +{ + return Matrix3( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) +{ + return Matrix3( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::identity( ) +{ + return Matrix3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3::xAxis( ), + Vector3( 0.0f, c, s ), + Vector3( 0.0f, -s, c ) + ); +} + +inline const Matrix3 Matrix3::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3( c, 0.0f, -s ), + Vector3::yAxis( ), + Vector3( s, 0.0f, c ) + ); +} + +inline const Matrix3 Matrix3::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3( c, s, 0.0f ), + Vector3( -s, c, 0.0f ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Matrix3( + Vector3( ( cZ * cY ), ( sZ * cY ), -sY ), + Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ), + Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( float radians, const Vector3 & unitVec ) +{ + float x, y, z, s, c, oneMinusC, xy, yz, zx; + s = sinf( radians ); + c = cosf( radians ); + x = unitVec.getX(); + y = unitVec.getY(); + z = unitVec.getZ(); + xy = ( x * y ); + yz = ( y * z ); + zx = ( z * x ); + oneMinusC = ( 1.0f - c ); + return Matrix3( + Vector3( ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ) ), + Vector3( ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ) ), + Vector3( ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( const Quat & unitQuat ) +{ + return Matrix3( unitQuat ); +} + +inline const Matrix3 Matrix3::scale( const Vector3 & scaleVec ) +{ + return Matrix3( + Vector3( scaleVec.getX(), 0.0f, 0.0f ), + Vector3( 0.0f, scaleVec.getY(), 0.0f ), + Vector3( 0.0f, 0.0f, scaleVec.getZ() ) + ); +} + +inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ) +{ + return Matrix3( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ) + ); +} + +inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ) +{ + return Matrix3( + mulPerElem( mat.getCol0(), scaleVec ), + mulPerElem( mat.getCol1(), scaleVec ), + mulPerElem( mat.getCol2(), scaleVec ) + ); +} + +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix3 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); +} + +inline void print( const Matrix3 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Matrix4::Matrix4( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; +} + +inline Matrix4::Matrix4( float scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +inline Matrix4::Matrix4( const Transform3 & mat ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( mat.getCol3(), 1.0f ); +} + +inline Matrix4::Matrix4( const Vector4 & _col0, const Vector4 & _col1, const Vector4 & _col2, const Vector4 & _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Matrix4::Matrix4( const Matrix3 & mat, const Vector3 & translateVec ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +inline Matrix4::Matrix4( const Quat & unitQuat, const Vector3 & translateVec ) +{ + Matrix3 mat; + mat = Matrix3( unitQuat ); + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +inline Matrix4 & Matrix4::setCol0( const Vector4 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix4 & Matrix4::setCol1( const Vector4 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix4 & Matrix4::setCol2( const Vector4 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix4 & Matrix4::setCol3( const Vector4 & _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Matrix4 & Matrix4::setCol( int col, const Vector4 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix4 & Matrix4::setRow( int row, const Vector4 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Matrix4 & Matrix4::setElem( int col, int row, float val ) +{ + Vector4 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Matrix4::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector4 Matrix4::getCol0( ) const +{ + return mCol0; +} + +inline const Vector4 Matrix4::getCol1( ) const +{ + return mCol1; +} + +inline const Vector4 Matrix4::getCol2( ) const +{ + return mCol2; +} + +inline const Vector4 Matrix4::getCol3( ) const +{ + return mCol3; +} + +inline const Vector4 Matrix4::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector4 & Matrix4::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix4 & Matrix4::operator =( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; + return *this; +} + +inline const Matrix4 transpose( const Matrix4 & mat ) +{ + return Matrix4( + Vector4( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX(), mat.getCol3().getX() ), + Vector4( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY(), mat.getCol3().getY() ), + Vector4( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ(), mat.getCol3().getZ() ), + Vector4( mat.getCol0().getW(), mat.getCol1().getW(), mat.getCol2().getW(), mat.getCol3().getW() ) + ); +} + +inline const Matrix4 inverse( const Matrix4 & mat ) +{ + Vector4 res0, res1, res2, res3; + float mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, detInv; + mA = mat.getCol0().getX(); + mB = mat.getCol0().getY(); + mC = mat.getCol0().getZ(); + mD = mat.getCol0().getW(); + mE = mat.getCol1().getX(); + mF = mat.getCol1().getY(); + mG = mat.getCol1().getZ(); + mH = mat.getCol1().getW(); + mI = mat.getCol2().getX(); + mJ = mat.getCol2().getY(); + mK = mat.getCol2().getZ(); + mL = mat.getCol2().getW(); + mM = mat.getCol3().getX(); + mN = mat.getCol3().getY(); + mO = mat.getCol3().getZ(); + mP = mat.getCol3().getW(); + tmp0 = ( ( mK * mD ) - ( mC * mL ) ); + tmp1 = ( ( mO * mH ) - ( mG * mP ) ); + tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); + tmp3 = ( ( mF * mO ) - ( mN * mG ) ); + tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); + tmp5 = ( ( mN * mH ) - ( mF * mP ) ); + res0.setX( ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ) ); + res0.setY( ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ) ); + res0.setZ( ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ) ); + res0.setW( ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ) ); + detInv = ( 1.0f / ( ( ( ( mA * res0.getX() ) + ( mE * res0.getY() ) ) + ( mI * res0.getZ() ) ) + ( mM * res0.getW() ) ) ); + res1.setX( ( mI * tmp1 ) ); + res1.setY( ( mM * tmp0 ) ); + res1.setZ( ( mA * tmp1 ) ); + res1.setW( ( mE * tmp0 ) ); + res3.setX( ( mI * tmp3 ) ); + res3.setY( ( mM * tmp2 ) ); + res3.setZ( ( mA * tmp3 ) ); + res3.setW( ( mE * tmp2 ) ); + res2.setX( ( mI * tmp5 ) ); + res2.setY( ( mM * tmp4 ) ); + res2.setZ( ( mA * tmp5 ) ); + res2.setW( ( mE * tmp4 ) ); + tmp0 = ( ( mI * mB ) - ( mA * mJ ) ); + tmp1 = ( ( mM * mF ) - ( mE * mN ) ); + tmp2 = ( ( mI * mD ) - ( mA * mL ) ); + tmp3 = ( ( mM * mH ) - ( mE * mP ) ); + tmp4 = ( ( mI * mC ) - ( mA * mK ) ); + tmp5 = ( ( mM * mG ) - ( mE * mO ) ); + res2.setX( ( ( ( mL * tmp1 ) - ( mJ * tmp3 ) ) + res2.getX() ) ); + res2.setY( ( ( ( mP * tmp0 ) - ( mN * tmp2 ) ) + res2.getY() ) ); + res2.setZ( ( ( ( mB * tmp3 ) - ( mD * tmp1 ) ) - res2.getZ() ) ); + res2.setW( ( ( ( mF * tmp2 ) - ( mH * tmp0 ) ) - res2.getW() ) ); + res3.setX( ( ( ( mJ * tmp5 ) - ( mK * tmp1 ) ) + res3.getX() ) ); + res3.setY( ( ( ( mN * tmp4 ) - ( mO * tmp0 ) ) + res3.getY() ) ); + res3.setZ( ( ( ( mC * tmp1 ) - ( mB * tmp5 ) ) - res3.getZ() ) ); + res3.setW( ( ( ( mG * tmp0 ) - ( mF * tmp4 ) ) - res3.getW() ) ); + res1.setX( ( ( ( mK * tmp3 ) - ( mL * tmp5 ) ) - res1.getX() ) ); + res1.setY( ( ( ( mO * tmp2 ) - ( mP * tmp4 ) ) - res1.getY() ) ); + res1.setZ( ( ( ( mD * tmp5 ) - ( mC * tmp3 ) ) + res1.getZ() ) ); + res1.setW( ( ( ( mH * tmp4 ) - ( mG * tmp2 ) ) + res1.getW() ) ); + return Matrix4( + ( res0 * detInv ), + ( res1 * detInv ), + ( res2 * detInv ), + ( res3 * detInv ) + ); +} + +inline const Matrix4 affineInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( inverse( affineMat ) ); +} + +inline const Matrix4 orthoInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( orthoInverse( affineMat ) ); +} + +inline float determinant( const Matrix4 & mat ) +{ + float dx, dy, dz, dw, mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + mA = mat.getCol0().getX(); + mB = mat.getCol0().getY(); + mC = mat.getCol0().getZ(); + mD = mat.getCol0().getW(); + mE = mat.getCol1().getX(); + mF = mat.getCol1().getY(); + mG = mat.getCol1().getZ(); + mH = mat.getCol1().getW(); + mI = mat.getCol2().getX(); + mJ = mat.getCol2().getY(); + mK = mat.getCol2().getZ(); + mL = mat.getCol2().getW(); + mM = mat.getCol3().getX(); + mN = mat.getCol3().getY(); + mO = mat.getCol3().getZ(); + mP = mat.getCol3().getW(); + tmp0 = ( ( mK * mD ) - ( mC * mL ) ); + tmp1 = ( ( mO * mH ) - ( mG * mP ) ); + tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); + tmp3 = ( ( mF * mO ) - ( mN * mG ) ); + tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); + tmp5 = ( ( mN * mH ) - ( mF * mP ) ); + dx = ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ); + dy = ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ); + dz = ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ); + dw = ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ); + return ( ( ( ( mA * dx ) + ( mE * dy ) ) + ( mI * dz ) ) + ( mM * dw ) ); +} + +inline const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ), + ( mCol3 + mat.mCol3 ) + ); +} + +inline const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ), + ( mCol3 - mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix4 Matrix4::operator -( ) const +{ + return Matrix4( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ), + ( -mCol3 ) + ); +} + +inline const Matrix4 absPerElem( const Matrix4 & mat ) +{ + return Matrix4( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ), + absPerElem( mat.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::operator *( float scalar ) const +{ + return Matrix4( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ), + ( mCol3 * scalar ) + ); +} + +inline Matrix4 & Matrix4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix4 operator *( float scalar, const Matrix4 & mat ) +{ + return mat * scalar; +} + +inline const Vector4 Matrix4::operator *( const Vector4 & vec ) const +{ + return Vector4( + ( ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ) + ( mCol3.getX() * vec.getW() ) ), + ( ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ) + ( mCol3.getY() * vec.getW() ) ), + ( ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ( mCol3.getZ() * vec.getW() ) ), + ( ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) + ( mCol3.getW() * vec.getW() ) ) + ); +} + +inline const Vector4 Matrix4::operator *( const Vector3 & vec ) const +{ + return Vector4( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ), + ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) + ); +} + +inline const Vector4 Matrix4::operator *( const Point3 & pnt ) const +{ + return Vector4( + ( ( ( ( mCol0.getX() * pnt.getX() ) + ( mCol1.getX() * pnt.getY() ) ) + ( mCol2.getX() * pnt.getZ() ) ) + mCol3.getX() ), + ( ( ( ( mCol0.getY() * pnt.getX() ) + ( mCol1.getY() * pnt.getY() ) ) + ( mCol2.getY() * pnt.getZ() ) ) + mCol3.getY() ), + ( ( ( ( mCol0.getZ() * pnt.getX() ) + ( mCol1.getZ() * pnt.getY() ) ) + ( mCol2.getZ() * pnt.getZ() ) ) + mCol3.getZ() ), + ( ( ( ( mCol0.getW() * pnt.getX() ) + ( mCol1.getW() * pnt.getY() ) ) + ( mCol2.getW() * pnt.getZ() ) ) + mCol3.getW() ) + ); +} + +inline const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const +{ + return Matrix4( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ), + ( *this * mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const +{ + return Matrix4( + ( *this * tfrm.getCol0() ), + ( *this * tfrm.getCol1() ), + ( *this * tfrm.getCol2() ), + ( *this * Point3( tfrm.getCol3() ) ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) +{ + return Matrix4( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ), + mulPerElem( mat0.getCol3(), mat1.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::identity( ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) +{ + mCol0.setXYZ( mat3.getCol0() ); + mCol1.setXYZ( mat3.getCol1() ); + mCol2.setXYZ( mat3.getCol2() ); + return *this; +} + +inline const Matrix3 Matrix4::getUpper3x3( ) const +{ + return Matrix3( + mCol0.getXYZ( ), + mCol1.getXYZ( ), + mCol2.getXYZ( ) + ); +} + +inline Matrix4 & Matrix4::setTranslation( const Vector3 & translateVec ) +{ + mCol3.setXYZ( translateVec ); + return *this; +} + +inline const Vector3 Matrix4::getTranslation( ) const +{ + return mCol3.getXYZ( ); +} + +inline const Matrix4 Matrix4::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4::xAxis( ), + Vector4( 0.0f, c, s, 0.0f ), + Vector4( 0.0f, -s, c, 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4( c, 0.0f, -s, 0.0f ), + Vector4::yAxis( ), + Vector4( s, 0.0f, c, 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4( c, s, 0.0f, 0.0f ), + Vector4( -s, c, 0.0f, 0.0f ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Matrix4( + Vector4( ( cZ * cY ), ( sZ * cY ), -sY, 0.0f ), + Vector4( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ), 0.0f ), + Vector4( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( float radians, const Vector3 & unitVec ) +{ + float x, y, z, s, c, oneMinusC, xy, yz, zx; + s = sinf( radians ); + c = cosf( radians ); + x = unitVec.getX(); + y = unitVec.getY(); + z = unitVec.getZ(); + xy = ( x * y ); + yz = ( y * z ); + zx = ( z * x ); + oneMinusC = ( 1.0f - c ); + return Matrix4( + Vector4( ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ), 0.0f ), + Vector4( ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ), 0.0f ), + Vector4( ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( const Quat & unitQuat ) +{ + return Matrix4( Transform3::rotation( unitQuat ) ); +} + +inline const Matrix4 Matrix4::scale( const Vector3 & scaleVec ) +{ + return Matrix4( + Vector4( scaleVec.getX(), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, scaleVec.getY(), 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, scaleVec.getZ(), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ) +{ + return Matrix4( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ), + mat.getCol3() + ); +} + +inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ) +{ + Vector4 scale4; + scale4 = Vector4( scaleVec, 1.0f ); + return Matrix4( + mulPerElem( mat.getCol0(), scale4 ), + mulPerElem( mat.getCol1(), scale4 ), + mulPerElem( mat.getCol2(), scale4 ), + mulPerElem( mat.getCol3(), scale4 ) + ); +} + +inline const Matrix4 Matrix4::translation( const Vector3 & translateVec ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4( translateVec, 1.0f ) + ); +} + +inline const Matrix4 Matrix4::lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ) +{ + Matrix4 m4EyeFrame; + Vector3 v3X, v3Y, v3Z; + v3Y = normalize( upVec ); + v3Z = normalize( ( eyePos - lookAtPos ) ); + v3X = normalize( cross( v3Y, v3Z ) ); + v3Y = cross( v3Z, v3X ); + m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); + return orthoInverse( m4EyeFrame ); +} + +inline const Matrix4 Matrix4::perspective( float fovyRadians, float aspect, float zNear, float zFar ) +{ + float f, rangeInv; + f = tanf( ( (float)( _VECTORMATH_PI_OVER_2 ) - ( 0.5f * fovyRadians ) ) ); + rangeInv = ( 1.0f / ( zNear - zFar ) ); + return Matrix4( + Vector4( ( f / aspect ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, f, 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, ( ( zNear + zFar ) * rangeInv ), -1.0f ), + Vector4( 0.0f, 0.0f, ( ( ( zNear * zFar ) * rangeInv ) * 2.0f ), 0.0f ) + ); +} + +inline const Matrix4 Matrix4::frustum( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf, n2; + sum_rl = ( right + left ); + sum_tb = ( top + bottom ); + sum_nf = ( zNear + zFar ); + inv_rl = ( 1.0f / ( right - left ) ); + inv_tb = ( 1.0f / ( top - bottom ) ); + inv_nf = ( 1.0f / ( zNear - zFar ) ); + n2 = ( zNear + zNear ); + return Matrix4( + Vector4( ( n2 * inv_rl ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, ( n2 * inv_tb ), 0.0f, 0.0f ), + Vector4( ( sum_rl * inv_rl ), ( sum_tb * inv_tb ), ( sum_nf * inv_nf ), -1.0f ), + Vector4( 0.0f, 0.0f, ( ( n2 * inv_nf ) * zFar ), 0.0f ) + ); +} + +inline const Matrix4 Matrix4::orthographic( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf; + sum_rl = ( right + left ); + sum_tb = ( top + bottom ); + sum_nf = ( zNear + zFar ); + inv_rl = ( 1.0f / ( right - left ) ); + inv_tb = ( 1.0f / ( top - bottom ) ); + inv_nf = ( 1.0f / ( zNear - zFar ) ); + return Matrix4( + Vector4( ( inv_rl + inv_rl ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, ( inv_tb + inv_tb ), 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, ( inv_nf + inv_nf ), 0.0f ), + Vector4( ( -sum_rl * inv_rl ), ( -sum_tb * inv_tb ), ( sum_nf * inv_nf ), 1.0f ) + ); +} + +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix4 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); + print( mat.getRow( 3 ) ); +} + +inline void print( const Matrix4 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Transform3::Transform3( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; +} + +inline Transform3::Transform3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +inline Transform3::Transform3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2, const Vector3 & _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Transform3::Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ) +{ + this->setUpper3x3( tfrm ); + this->setTranslation( translateVec ); +} + +inline Transform3::Transform3( const Quat & unitQuat, const Vector3 & translateVec ) +{ + this->setUpper3x3( Matrix3( unitQuat ) ); + this->setTranslation( translateVec ); +} + +inline Transform3 & Transform3::setCol0( const Vector3 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Transform3 & Transform3::setCol1( const Vector3 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Transform3 & Transform3::setCol2( const Vector3 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Transform3 & Transform3::setCol3( const Vector3 & _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Transform3 & Transform3::setCol( int col, const Vector3 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Transform3 & Transform3::setRow( int row, const Vector4 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Transform3 & Transform3::setElem( int col, int row, float val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Transform3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Transform3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Transform3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Transform3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Transform3::getCol3( ) const +{ + return mCol3; +} + +inline const Vector3 Transform3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Transform3::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector3 & Transform3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Transform3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Transform3 & Transform3::operator =( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; + return *this; +} + +inline const Transform3 inverse( const Transform3 & tfrm ) +{ + Vector3 tmp0, tmp1, tmp2, inv0, inv1, inv2; + float detinv; + tmp0 = cross( tfrm.getCol1(), tfrm.getCol2() ); + tmp1 = cross( tfrm.getCol2(), tfrm.getCol0() ); + tmp2 = cross( tfrm.getCol0(), tfrm.getCol1() ); + detinv = ( 1.0f / dot( tfrm.getCol2(), tmp2 ) ); + inv0 = Vector3( ( tmp0.getX() * detinv ), ( tmp1.getX() * detinv ), ( tmp2.getX() * detinv ) ); + inv1 = Vector3( ( tmp0.getY() * detinv ), ( tmp1.getY() * detinv ), ( tmp2.getY() * detinv ) ); + inv2 = Vector3( ( tmp0.getZ() * detinv ), ( tmp1.getZ() * detinv ), ( tmp2.getZ() * detinv ) ); + return Transform3( + inv0, + inv1, + inv2, + Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) + ); +} + +inline const Transform3 orthoInverse( const Transform3 & tfrm ) +{ + Vector3 inv0, inv1, inv2; + inv0 = Vector3( tfrm.getCol0().getX(), tfrm.getCol1().getX(), tfrm.getCol2().getX() ); + inv1 = Vector3( tfrm.getCol0().getY(), tfrm.getCol1().getY(), tfrm.getCol2().getY() ); + inv2 = Vector3( tfrm.getCol0().getZ(), tfrm.getCol1().getZ(), tfrm.getCol2().getZ() ); + return Transform3( + inv0, + inv1, + inv2, + Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) + ); +} + +inline const Transform3 absPerElem( const Transform3 & tfrm ) +{ + return Transform3( + absPerElem( tfrm.getCol0() ), + absPerElem( tfrm.getCol1() ), + absPerElem( tfrm.getCol2() ), + absPerElem( tfrm.getCol3() ) + ); +} + +inline const Vector3 Transform3::operator *( const Vector3 & vec ) const +{ + return Vector3( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ); +} + +inline const Point3 Transform3::operator *( const Point3 & pnt ) const +{ + return Point3( + ( ( ( ( mCol0.getX() * pnt.getX() ) + ( mCol1.getX() * pnt.getY() ) ) + ( mCol2.getX() * pnt.getZ() ) ) + mCol3.getX() ), + ( ( ( ( mCol0.getY() * pnt.getX() ) + ( mCol1.getY() * pnt.getY() ) ) + ( mCol2.getY() * pnt.getZ() ) ) + mCol3.getY() ), + ( ( ( ( mCol0.getZ() * pnt.getX() ) + ( mCol1.getZ() * pnt.getY() ) ) + ( mCol2.getZ() * pnt.getZ() ) ) + mCol3.getZ() ) + ); +} + +inline const Transform3 Transform3::operator *( const Transform3 & tfrm ) const +{ + return Transform3( + ( *this * tfrm.mCol0 ), + ( *this * tfrm.mCol1 ), + ( *this * tfrm.mCol2 ), + Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) + ); +} + +inline Transform3 & Transform3::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) +{ + return Transform3( + mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), + mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), + mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), + mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) + ); +} + +inline const Transform3 Transform3::identity( ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +inline Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) +{ + mCol0 = tfrm.getCol0(); + mCol1 = tfrm.getCol1(); + mCol2 = tfrm.getCol2(); + return *this; +} + +inline const Matrix3 Transform3::getUpper3x3( ) const +{ + return Matrix3( mCol0, mCol1, mCol2 ); +} + +inline Transform3 & Transform3::setTranslation( const Vector3 & translateVec ) +{ + mCol3 = translateVec; + return *this; +} + +inline const Vector3 Transform3::getTranslation( ) const +{ + return mCol3; +} + +inline const Transform3 Transform3::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3::xAxis( ), + Vector3( 0.0f, c, s ), + Vector3( 0.0f, -s, c ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3( c, 0.0f, -s ), + Vector3::yAxis( ), + Vector3( s, 0.0f, c ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3( c, s, 0.0f ), + Vector3( -s, c, 0.0f ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Transform3( + Vector3( ( cZ * cY ), ( sZ * cY ), -sY ), + Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ), + Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotation( float radians, const Vector3 & unitVec ) +{ + return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( 0.0f ) ); +} + +inline const Transform3 Transform3::rotation( const Quat & unitQuat ) +{ + return Transform3( Matrix3( unitQuat ), Vector3( 0.0f ) ); +} + +inline const Transform3 Transform3::scale( const Vector3 & scaleVec ) +{ + return Transform3( + Vector3( scaleVec.getX(), 0.0f, 0.0f ), + Vector3( 0.0f, scaleVec.getY(), 0.0f ), + Vector3( 0.0f, 0.0f, scaleVec.getZ() ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ) +{ + return Transform3( + ( tfrm.getCol0() * scaleVec.getX( ) ), + ( tfrm.getCol1() * scaleVec.getY( ) ), + ( tfrm.getCol2() * scaleVec.getZ( ) ), + tfrm.getCol3() + ); +} + +inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ) +{ + return Transform3( + mulPerElem( tfrm.getCol0(), scaleVec ), + mulPerElem( tfrm.getCol1(), scaleVec ), + mulPerElem( tfrm.getCol2(), scaleVec ), + mulPerElem( tfrm.getCol3(), scaleVec ) + ); +} + +inline const Transform3 Transform3::translation( const Vector3 & translateVec ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + translateVec + ); +} + +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Transform3 & tfrm ) +{ + print( tfrm.getRow( 0 ) ); + print( tfrm.getRow( 1 ) ); + print( tfrm.getRow( 2 ) ); +} + +inline void print( const Transform3 & tfrm, const char * name ) +{ + printf("%s:\n", name); + print( tfrm ); +} + +#endif + +inline Quat::Quat( const Matrix3 & tfrm ) +{ + float trace, radicand, scale, xx, yx, zx, xy, yy, zy, xz, yz, zz, tmpx, tmpy, tmpz, tmpw, qx, qy, qz, qw; + int negTrace, ZgtX, ZgtY, YgtX; + int largestXorY, largestYorZ, largestZorX; + + xx = tfrm.getCol0().getX(); + yx = tfrm.getCol0().getY(); + zx = tfrm.getCol0().getZ(); + xy = tfrm.getCol1().getX(); + yy = tfrm.getCol1().getY(); + zy = tfrm.getCol1().getZ(); + xz = tfrm.getCol2().getX(); + yz = tfrm.getCol2().getY(); + zz = tfrm.getCol2().getZ(); + + trace = ( ( xx + yy ) + zz ); + + negTrace = ( trace < 0.0f ); + ZgtX = zz > xx; + ZgtY = zz > yy; + YgtX = yy > xx; + largestXorY = ( !ZgtX || !ZgtY ) && negTrace; + largestYorZ = ( YgtX || ZgtX ) && negTrace; + largestZorX = ( ZgtY || !YgtX ) && negTrace; + + if ( largestXorY ) + { + zz = -zz; + xy = -xy; + } + if ( largestYorZ ) + { + xx = -xx; + yz = -yz; + } + if ( largestZorX ) + { + yy = -yy; + zx = -zx; + } + + radicand = ( ( ( xx + yy ) + zz ) + 1.0f ); + scale = ( 0.5f * ( 1.0f / sqrtf( radicand ) ) ); + + tmpx = ( ( zy - yz ) * scale ); + tmpy = ( ( xz - zx ) * scale ); + tmpz = ( ( yx - xy ) * scale ); + tmpw = ( radicand * scale ); + qx = tmpx; + qy = tmpy; + qz = tmpz; + qw = tmpw; + + if ( largestXorY ) + { + qx = tmpw; + qy = tmpz; + qz = tmpy; + qw = tmpx; + } + if ( largestYorZ ) + { + tmpx = qx; + tmpz = qz; + qx = qy; + qy = tmpx; + qz = qw; + qw = tmpz; + } + + mX = qx; + mY = qy; + mZ = qz; + mW = qw; +} + +inline const Matrix3 outer( const Vector3 & tfrm0, const Vector3 & tfrm1 ) +{ + return Matrix3( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ) + ); +} + +inline const Matrix4 outer( const Vector4 & tfrm0, const Vector4 & tfrm1 ) +{ + return Matrix4( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ), + ( tfrm0 * tfrm1.getW( ) ) + ); +} + +inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ) +{ + return Vector3( + ( ( ( vec.getX() * mat.getCol0().getX() ) + ( vec.getY() * mat.getCol0().getY() ) ) + ( vec.getZ() * mat.getCol0().getZ() ) ), + ( ( ( vec.getX() * mat.getCol1().getX() ) + ( vec.getY() * mat.getCol1().getY() ) ) + ( vec.getZ() * mat.getCol1().getZ() ) ), + ( ( ( vec.getX() * mat.getCol2().getX() ) + ( vec.getY() * mat.getCol2().getY() ) ) + ( vec.getZ() * mat.getCol2().getZ() ) ) + ); +} + +inline const Matrix3 crossMatrix( const Vector3 & vec ) +{ + return Matrix3( + Vector3( 0.0f, vec.getZ(), -vec.getY() ), + Vector3( -vec.getZ(), 0.0f, vec.getX() ), + Vector3( vec.getY(), -vec.getX(), 0.0f ) + ); +} + +inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ) +{ + return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); +} + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/scalar/cpp/quat_aos.h b/Extras/vectormathlibrary/include/vectormath/scalar/cpp/quat_aos.h new file mode 100644 index 0000000..205c724 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/scalar/cpp/quat_aos.h @@ -0,0 +1,446 @@ +/* + Copyright (C) 2006-2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_AOS_CPP_H +#define _VECTORMATH_QUAT_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +inline Quat::Quat( const Quat & quat ) +{ + mX = quat.mX; + mY = quat.mY; + mZ = quat.mZ; + mW = quat.mW; +} + +inline Quat::Quat( float _x, float _y, float _z, float _w ) +{ + mX = _x; + mY = _y; + mZ = _z; + mW = _w; +} + +inline Quat::Quat( const Vector3 & xyz, float _w ) +{ + this->setXYZ( xyz ); + this->setW( _w ); +} + +inline Quat::Quat( const Vector4 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + mW = vec.getW(); +} + +inline Quat::Quat( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; + mW = scalar; +} + +inline const Quat Quat::identity( ) +{ + return Quat( 0.0f, 0.0f, 0.0f, 1.0f ); +} + +inline const Quat lerp( float t, const Quat & quat0, const Quat & quat1 ) +{ + return ( quat0 + ( ( quat1 - quat0 ) * t ) ); +} + +inline const Quat slerp( float t, const Quat & unitQuat0, const Quat & unitQuat1 ) +{ + Quat start; + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitQuat0, unitQuat1 ); + if ( cosAngle < 0.0f ) { + cosAngle = -cosAngle; + start = ( -unitQuat0 ); + } else { + start = unitQuat0; + } + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( start * scale0 ) + ( unitQuat1 * scale1 ) ); +} + +inline const Quat squad( float t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ) +{ + Quat tmp0, tmp1; + tmp0 = slerp( t, unitQuat0, unitQuat3 ); + tmp1 = slerp( t, unitQuat1, unitQuat2 ); + return slerp( ( ( 2.0f * t ) * ( 1.0f - t ) ), tmp0, tmp1 ); +} + +inline void loadXYZW( Quat & quat, const float * fptr ) +{ + quat = Quat( fptr[0], fptr[1], fptr[2], fptr[3] ); +} + +inline void storeXYZW( const Quat & quat, float * fptr ) +{ + fptr[0] = quat.getX(); + fptr[1] = quat.getY(); + fptr[2] = quat.getZ(); + fptr[3] = quat.getW(); +} + +inline Quat & Quat::operator =( const Quat & quat ) +{ + mX = quat.mX; + mY = quat.mY; + mZ = quat.mZ; + mW = quat.mW; + return *this; +} + +inline Quat & Quat::setXYZ( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + return *this; +} + +inline const Vector3 Quat::getXYZ( ) const +{ + return Vector3( mX, mY, mZ ); +} + +inline Quat & Quat::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Quat::getX( ) const +{ + return mX; +} + +inline Quat & Quat::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Quat::getY( ) const +{ + return mY; +} + +inline Quat & Quat::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Quat::getZ( ) const +{ + return mZ; +} + +inline Quat & Quat::setW( float _w ) +{ + mW = _w; + return *this; +} + +inline float Quat::getW( ) const +{ + return mW; +} + +inline Quat & Quat::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Quat::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Quat::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Quat::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Quat Quat::operator +( const Quat & quat ) const +{ + return Quat( + ( mX + quat.mX ), + ( mY + quat.mY ), + ( mZ + quat.mZ ), + ( mW + quat.mW ) + ); +} + +inline const Quat Quat::operator -( const Quat & quat ) const +{ + return Quat( + ( mX - quat.mX ), + ( mY - quat.mY ), + ( mZ - quat.mZ ), + ( mW - quat.mW ) + ); +} + +inline const Quat Quat::operator *( float scalar ) const +{ + return Quat( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ), + ( mW * scalar ) + ); +} + +inline Quat & Quat::operator +=( const Quat & quat ) +{ + *this = *this + quat; + return *this; +} + +inline Quat & Quat::operator -=( const Quat & quat ) +{ + *this = *this - quat; + return *this; +} + +inline Quat & Quat::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Quat Quat::operator /( float scalar ) const +{ + return Quat( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ), + ( mW / scalar ) + ); +} + +inline Quat & Quat::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Quat Quat::operator -( ) const +{ + return Quat( + -mX, + -mY, + -mZ, + -mW + ); +} + +inline const Quat operator *( float scalar, const Quat & quat ) +{ + return quat * scalar; +} + +inline float dot( const Quat & quat0, const Quat & quat1 ) +{ + float result; + result = ( quat0.getX() * quat1.getX() ); + result = ( result + ( quat0.getY() * quat1.getY() ) ); + result = ( result + ( quat0.getZ() * quat1.getZ() ) ); + result = ( result + ( quat0.getW() * quat1.getW() ) ); + return result; +} + +inline float norm( const Quat & quat ) +{ + float result; + result = ( quat.getX() * quat.getX() ); + result = ( result + ( quat.getY() * quat.getY() ) ); + result = ( result + ( quat.getZ() * quat.getZ() ) ); + result = ( result + ( quat.getW() * quat.getW() ) ); + return result; +} + +inline float length( const Quat & quat ) +{ + return ::sqrtf( norm( quat ) ); +} + +inline const Quat normalize( const Quat & quat ) +{ + float lenSqr, lenInv; + lenSqr = norm( quat ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Quat( + ( quat.getX() * lenInv ), + ( quat.getY() * lenInv ), + ( quat.getZ() * lenInv ), + ( quat.getW() * lenInv ) + ); +} + +inline const Quat Quat::rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ) +{ + float cosHalfAngleX2, recipCosHalfAngleX2; + cosHalfAngleX2 = sqrtf( ( 2.0f * ( 1.0f + dot( unitVec0, unitVec1 ) ) ) ); + recipCosHalfAngleX2 = ( 1.0f / cosHalfAngleX2 ); + return Quat( ( cross( unitVec0, unitVec1 ) * recipCosHalfAngleX2 ), ( cosHalfAngleX2 * 0.5f ) ); +} + +inline const Quat Quat::rotation( float radians, const Vector3 & unitVec ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( ( unitVec * s ), c ); +} + +inline const Quat Quat::rotationX( float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( s, 0.0f, 0.0f, c ); +} + +inline const Quat Quat::rotationY( float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( 0.0f, s, 0.0f, c ); +} + +inline const Quat Quat::rotationZ( float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( 0.0f, 0.0f, s, c ); +} + +inline const Quat Quat::operator *( const Quat & quat ) const +{ + return Quat( + ( ( ( ( mW * quat.mX ) + ( mX * quat.mW ) ) + ( mY * quat.mZ ) ) - ( mZ * quat.mY ) ), + ( ( ( ( mW * quat.mY ) + ( mY * quat.mW ) ) + ( mZ * quat.mX ) ) - ( mX * quat.mZ ) ), + ( ( ( ( mW * quat.mZ ) + ( mZ * quat.mW ) ) + ( mX * quat.mY ) ) - ( mY * quat.mX ) ), + ( ( ( ( mW * quat.mW ) - ( mX * quat.mX ) ) - ( mY * quat.mY ) ) - ( mZ * quat.mZ ) ) + ); +} + +inline Quat & Quat::operator *=( const Quat & quat ) +{ + *this = *this * quat; + return *this; +} + +inline const Vector3 rotate( const Quat & quat, const Vector3 & vec ) +{ + float tmpX, tmpY, tmpZ, tmpW; + tmpX = ( ( ( quat.getW() * vec.getX() ) + ( quat.getY() * vec.getZ() ) ) - ( quat.getZ() * vec.getY() ) ); + tmpY = ( ( ( quat.getW() * vec.getY() ) + ( quat.getZ() * vec.getX() ) ) - ( quat.getX() * vec.getZ() ) ); + tmpZ = ( ( ( quat.getW() * vec.getZ() ) + ( quat.getX() * vec.getY() ) ) - ( quat.getY() * vec.getX() ) ); + tmpW = ( ( ( quat.getX() * vec.getX() ) + ( quat.getY() * vec.getY() ) ) + ( quat.getZ() * vec.getZ() ) ); + return Vector3( + ( ( ( ( tmpW * quat.getX() ) + ( tmpX * quat.getW() ) ) - ( tmpY * quat.getZ() ) ) + ( tmpZ * quat.getY() ) ), + ( ( ( ( tmpW * quat.getY() ) + ( tmpY * quat.getW() ) ) - ( tmpZ * quat.getX() ) ) + ( tmpX * quat.getZ() ) ), + ( ( ( ( tmpW * quat.getZ() ) + ( tmpZ * quat.getW() ) ) - ( tmpX * quat.getY() ) ) + ( tmpY * quat.getX() ) ) + ); +} + +inline const Quat conj( const Quat & quat ) +{ + return Quat( -quat.getX(), -quat.getY(), -quat.getZ(), quat.getW() ); +} + +inline const Quat select( const Quat & quat0, const Quat & quat1, bool select1 ) +{ + return Quat( + ( select1 )? quat1.getX() : quat0.getX(), + ( select1 )? quat1.getY() : quat0.getY(), + ( select1 )? quat1.getZ() : quat0.getZ(), + ( select1 )? quat1.getW() : quat0.getW() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Quat & quat ) +{ + printf( "( %f %f %f %f )\n", quat.getX(), quat.getY(), quat.getZ(), quat.getW() ); +} + +inline void print( const Quat & quat, const char * name ) +{ + printf( "%s: ( %f %f %f %f )\n", name, quat.getX(), quat.getY(), quat.getZ(), quat.getW() ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/scalar/cpp/vec_aos.h b/Extras/vectormathlibrary/include/vectormath/scalar/cpp/vec_aos.h new file mode 100644 index 0000000..9f1af36 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/scalar/cpp/vec_aos.h @@ -0,0 +1,1439 @@ +/* + Copyright (C) 2006-2010 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_AOS_CPP_H +#define _VECTORMATH_VEC_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Constants + +#define _VECTORMATH_SLERP_TOL 0.999f + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +inline Vector3::Vector3( const Vector3 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; +} + +inline Vector3::Vector3( float _x, float _y, float _z ) +{ + mX = _x; + mY = _y; + mZ = _z; +} + +inline Vector3::Vector3( const Point3 & pnt ) +{ + mX = pnt.getX(); + mY = pnt.getY(); + mZ = pnt.getZ(); +} + +inline Vector3::Vector3( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; +} + +inline const Vector3 Vector3::xAxis( ) +{ + return Vector3( 1.0f, 0.0f, 0.0f ); +} + +inline const Vector3 Vector3::yAxis( ) +{ + return Vector3( 0.0f, 1.0f, 0.0f ); +} + +inline const Vector3 Vector3::zAxis( ) +{ + return Vector3( 0.0f, 0.0f, 1.0f ); +} + +inline const Vector3 lerp( float t, const Vector3 & vec0, const Vector3 & vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector3 slerp( float t, const Vector3 & unitVec0, const Vector3 & unitVec1 ) +{ + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitVec0, unitVec1 ); + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); +} + +inline void loadXYZ( Vector3 & vec, const float * fptr ) +{ + vec = Vector3( fptr[0], fptr[1], fptr[2] ); +} + +inline void storeXYZ( const Vector3 & vec, float * fptr ) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); +} + +inline void loadHalfFloats( Vector3 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Vector3 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Vector3 & Vector3::operator =( const Vector3 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + return *this; +} + +inline Vector3 & Vector3::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Vector3::getX( ) const +{ + return mX; +} + +inline Vector3 & Vector3::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Vector3::getY( ) const +{ + return mY; +} + +inline Vector3 & Vector3::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Vector3::getZ( ) const +{ + return mZ; +} + +inline Vector3 & Vector3::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Vector3::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Vector3::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Vector3::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector3 Vector3::operator +( const Vector3 & vec ) const +{ + return Vector3( + ( mX + vec.mX ), + ( mY + vec.mY ), + ( mZ + vec.mZ ) + ); +} + +inline const Vector3 Vector3::operator -( const Vector3 & vec ) const +{ + return Vector3( + ( mX - vec.mX ), + ( mY - vec.mY ), + ( mZ - vec.mZ ) + ); +} + +inline const Point3 Vector3::operator +( const Point3 & pnt ) const +{ + return Point3( + ( mX + pnt.getX() ), + ( mY + pnt.getY() ), + ( mZ + pnt.getZ() ) + ); +} + +inline const Vector3 Vector3::operator *( float scalar ) const +{ + return Vector3( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ) + ); +} + +inline Vector3 & Vector3::operator +=( const Vector3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector3 & Vector3::operator -=( const Vector3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector3 & Vector3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector3 Vector3::operator /( float scalar ) const +{ + return Vector3( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ) + ); +} + +inline Vector3 & Vector3::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector3 Vector3::operator -( ) const +{ + return Vector3( + -mX, + -mY, + -mZ + ); +} + +inline const Vector3 operator *( float scalar, const Vector3 & vec ) +{ + return vec * scalar; +} + +inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec0.getX() * vec1.getX() ), + ( vec0.getY() * vec1.getY() ), + ( vec0.getZ() * vec1.getZ() ) + ); +} + +inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec0.getX() / vec1.getX() ), + ( vec0.getY() / vec1.getY() ), + ( vec0.getZ() / vec1.getZ() ) + ); +} + +inline const Vector3 recipPerElem( const Vector3 & vec ) +{ + return Vector3( + ( 1.0f / vec.getX() ), + ( 1.0f / vec.getY() ), + ( 1.0f / vec.getZ() ) + ); +} + +inline const Vector3 sqrtPerElem( const Vector3 & vec ) +{ + return Vector3( + sqrtf( vec.getX() ), + sqrtf( vec.getY() ), + sqrtf( vec.getZ() ) + ); +} + +inline const Vector3 rsqrtPerElem( const Vector3 & vec ) +{ + return Vector3( + ( 1.0f / sqrtf( vec.getX() ) ), + ( 1.0f / sqrtf( vec.getY() ) ), + ( 1.0f / sqrtf( vec.getZ() ) ) + ); +} + +inline const Vector3 absPerElem( const Vector3 & vec ) +{ + return Vector3( + fabsf( vec.getX() ), + fabsf( vec.getY() ), + fabsf( vec.getZ() ) + ); +} + +inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec1.getX() < 0.0f )? -fabsf( vec0.getX() ) : fabsf( vec0.getX() ), + ( vec1.getY() < 0.0f )? -fabsf( vec0.getY() ) : fabsf( vec0.getY() ), + ( vec1.getZ() < 0.0f )? -fabsf( vec0.getZ() ) : fabsf( vec0.getZ() ) + ); +} + +inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ() + ); +} + +inline float maxElem( const Vector3 & vec ) +{ + float result; + result = (vec.getX() > vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() > result)? vec.getZ() : result; + return result; +} + +inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ() + ); +} + +inline float minElem( const Vector3 & vec ) +{ + float result; + result = (vec.getX() < vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() < result)? vec.getZ() : result; + return result; +} + +inline float sum( const Vector3 & vec ) +{ + float result; + result = ( vec.getX() + vec.getY() ); + result = ( result + vec.getZ() ); + return result; +} + +inline float dot( const Vector3 & vec0, const Vector3 & vec1 ) +{ + float result; + result = ( vec0.getX() * vec1.getX() ); + result = ( result + ( vec0.getY() * vec1.getY() ) ); + result = ( result + ( vec0.getZ() * vec1.getZ() ) ); + return result; +} + +inline float lengthSqr( const Vector3 & vec ) +{ + float result; + result = ( vec.getX() * vec.getX() ); + result = ( result + ( vec.getY() * vec.getY() ) ); + result = ( result + ( vec.getZ() * vec.getZ() ) ); + return result; +} + +inline float length( const Vector3 & vec ) +{ + return ::sqrtf( lengthSqr( vec ) ); +} + +inline const Vector3 normalize( const Vector3 & vec ) +{ + float lenSqr, lenInv; + lenSqr = lengthSqr( vec ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Vector3( + ( vec.getX() * lenInv ), + ( vec.getY() * lenInv ), + ( vec.getZ() * lenInv ) + ); +} + +inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( ( vec0.getY() * vec1.getZ() ) - ( vec0.getZ() * vec1.getY() ) ), + ( ( vec0.getZ() * vec1.getX() ) - ( vec0.getX() * vec1.getZ() ) ), + ( ( vec0.getX() * vec1.getY() ) - ( vec0.getY() * vec1.getX() ) ) + ); +} + +inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, bool select1 ) +{ + return Vector3( + ( select1 )? vec1.getX() : vec0.getX(), + ( select1 )? vec1.getY() : vec0.getY(), + ( select1 )? vec1.getZ() : vec0.getZ() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Vector3 & vec ) +{ + printf( "( %f %f %f )\n", vec.getX(), vec.getY(), vec.getZ() ); +} + +inline void print( const Vector3 & vec, const char * name ) +{ + printf( "%s: ( %f %f %f )\n", name, vec.getX(), vec.getY(), vec.getZ() ); +} + +#endif + +inline Vector4::Vector4( const Vector4 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + mW = vec.mW; +} + +inline Vector4::Vector4( float _x, float _y, float _z, float _w ) +{ + mX = _x; + mY = _y; + mZ = _z; + mW = _w; +} + +inline Vector4::Vector4( const Vector3 & xyz, float _w ) +{ + this->setXYZ( xyz ); + this->setW( _w ); +} + +inline Vector4::Vector4( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + mW = 0.0f; +} + +inline Vector4::Vector4( const Point3 & pnt ) +{ + mX = pnt.getX(); + mY = pnt.getY(); + mZ = pnt.getZ(); + mW = 1.0f; +} + +inline Vector4::Vector4( const Quat & quat ) +{ + mX = quat.getX(); + mY = quat.getY(); + mZ = quat.getZ(); + mW = quat.getW(); +} + +inline Vector4::Vector4( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; + mW = scalar; +} + +inline const Vector4 Vector4::xAxis( ) +{ + return Vector4( 1.0f, 0.0f, 0.0f, 0.0f ); +} + +inline const Vector4 Vector4::yAxis( ) +{ + return Vector4( 0.0f, 1.0f, 0.0f, 0.0f ); +} + +inline const Vector4 Vector4::zAxis( ) +{ + return Vector4( 0.0f, 0.0f, 1.0f, 0.0f ); +} + +inline const Vector4 Vector4::wAxis( ) +{ + return Vector4( 0.0f, 0.0f, 0.0f, 1.0f ); +} + +inline const Vector4 lerp( float t, const Vector4 & vec0, const Vector4 & vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector4 slerp( float t, const Vector4 & unitVec0, const Vector4 & unitVec1 ) +{ + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitVec0, unitVec1 ); + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); +} + +inline void loadXYZW( Vector4 & vec, const float * fptr ) +{ + vec = Vector4( fptr[0], fptr[1], fptr[2], fptr[3] ); +} + +inline void storeXYZW( const Vector4 & vec, float * fptr ) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); + fptr[3] = vec.getW(); +} + +inline void loadHalfFloats( Vector4 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 4; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Vector4 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 4; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Vector4 & Vector4::operator =( const Vector4 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + mW = vec.mW; + return *this; +} + +inline Vector4 & Vector4::setXYZ( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + return *this; +} + +inline const Vector3 Vector4::getXYZ( ) const +{ + return Vector3( mX, mY, mZ ); +} + +inline Vector4 & Vector4::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Vector4::getX( ) const +{ + return mX; +} + +inline Vector4 & Vector4::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Vector4::getY( ) const +{ + return mY; +} + +inline Vector4 & Vector4::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Vector4::getZ( ) const +{ + return mZ; +} + +inline Vector4 & Vector4::setW( float _w ) +{ + mW = _w; + return *this; +} + +inline float Vector4::getW( ) const +{ + return mW; +} + +inline Vector4 & Vector4::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Vector4::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Vector4::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Vector4::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector4 Vector4::operator +( const Vector4 & vec ) const +{ + return Vector4( + ( mX + vec.mX ), + ( mY + vec.mY ), + ( mZ + vec.mZ ), + ( mW + vec.mW ) + ); +} + +inline const Vector4 Vector4::operator -( const Vector4 & vec ) const +{ + return Vector4( + ( mX - vec.mX ), + ( mY - vec.mY ), + ( mZ - vec.mZ ), + ( mW - vec.mW ) + ); +} + +inline const Vector4 Vector4::operator *( float scalar ) const +{ + return Vector4( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ), + ( mW * scalar ) + ); +} + +inline Vector4 & Vector4::operator +=( const Vector4 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector4 & Vector4::operator -=( const Vector4 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector4 & Vector4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector4 Vector4::operator /( float scalar ) const +{ + return Vector4( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ), + ( mW / scalar ) + ); +} + +inline Vector4 & Vector4::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector4 Vector4::operator -( ) const +{ + return Vector4( + -mX, + -mY, + -mZ, + -mW + ); +} + +inline const Vector4 operator *( float scalar, const Vector4 & vec ) +{ + return vec * scalar; +} + +inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec0.getX() * vec1.getX() ), + ( vec0.getY() * vec1.getY() ), + ( vec0.getZ() * vec1.getZ() ), + ( vec0.getW() * vec1.getW() ) + ); +} + +inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec0.getX() / vec1.getX() ), + ( vec0.getY() / vec1.getY() ), + ( vec0.getZ() / vec1.getZ() ), + ( vec0.getW() / vec1.getW() ) + ); +} + +inline const Vector4 recipPerElem( const Vector4 & vec ) +{ + return Vector4( + ( 1.0f / vec.getX() ), + ( 1.0f / vec.getY() ), + ( 1.0f / vec.getZ() ), + ( 1.0f / vec.getW() ) + ); +} + +inline const Vector4 sqrtPerElem( const Vector4 & vec ) +{ + return Vector4( + sqrtf( vec.getX() ), + sqrtf( vec.getY() ), + sqrtf( vec.getZ() ), + sqrtf( vec.getW() ) + ); +} + +inline const Vector4 rsqrtPerElem( const Vector4 & vec ) +{ + return Vector4( + ( 1.0f / sqrtf( vec.getX() ) ), + ( 1.0f / sqrtf( vec.getY() ) ), + ( 1.0f / sqrtf( vec.getZ() ) ), + ( 1.0f / sqrtf( vec.getW() ) ) + ); +} + +inline const Vector4 absPerElem( const Vector4 & vec ) +{ + return Vector4( + fabsf( vec.getX() ), + fabsf( vec.getY() ), + fabsf( vec.getZ() ), + fabsf( vec.getW() ) + ); +} + +inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec1.getX() < 0.0f )? -fabsf( vec0.getX() ) : fabsf( vec0.getX() ), + ( vec1.getY() < 0.0f )? -fabsf( vec0.getY() ) : fabsf( vec0.getY() ), + ( vec1.getZ() < 0.0f )? -fabsf( vec0.getZ() ) : fabsf( vec0.getZ() ), + ( vec1.getW() < 0.0f )? -fabsf( vec0.getW() ) : fabsf( vec0.getW() ) + ); +} + +inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ(), + (vec0.getW() > vec1.getW())? vec0.getW() : vec1.getW() + ); +} + +inline float maxElem( const Vector4 & vec ) +{ + float result; + result = (vec.getX() > vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() > result)? vec.getZ() : result; + result = (vec.getW() > result)? vec.getW() : result; + return result; +} + +inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ(), + (vec0.getW() < vec1.getW())? vec0.getW() : vec1.getW() + ); +} + +inline float minElem( const Vector4 & vec ) +{ + float result; + result = (vec.getX() < vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() < result)? vec.getZ() : result; + result = (vec.getW() < result)? vec.getW() : result; + return result; +} + +inline float sum( const Vector4 & vec ) +{ + float result; + result = ( vec.getX() + vec.getY() ); + result = ( result + vec.getZ() ); + result = ( result + vec.getW() ); + return result; +} + +inline float dot( const Vector4 & vec0, const Vector4 & vec1 ) +{ + float result; + result = ( vec0.getX() * vec1.getX() ); + result = ( result + ( vec0.getY() * vec1.getY() ) ); + result = ( result + ( vec0.getZ() * vec1.getZ() ) ); + result = ( result + ( vec0.getW() * vec1.getW() ) ); + return result; +} + +inline float lengthSqr( const Vector4 & vec ) +{ + float result; + result = ( vec.getX() * vec.getX() ); + result = ( result + ( vec.getY() * vec.getY() ) ); + result = ( result + ( vec.getZ() * vec.getZ() ) ); + result = ( result + ( vec.getW() * vec.getW() ) ); + return result; +} + +inline float length( const Vector4 & vec ) +{ + return ::sqrtf( lengthSqr( vec ) ); +} + +inline const Vector4 normalize( const Vector4 & vec ) +{ + float lenSqr, lenInv; + lenSqr = lengthSqr( vec ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Vector4( + ( vec.getX() * lenInv ), + ( vec.getY() * lenInv ), + ( vec.getZ() * lenInv ), + ( vec.getW() * lenInv ) + ); +} + +inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, bool select1 ) +{ + return Vector4( + ( select1 )? vec1.getX() : vec0.getX(), + ( select1 )? vec1.getY() : vec0.getY(), + ( select1 )? vec1.getZ() : vec0.getZ(), + ( select1 )? vec1.getW() : vec0.getW() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Vector4 & vec ) +{ + printf( "( %f %f %f %f )\n", vec.getX(), vec.getY(), vec.getZ(), vec.getW() ); +} + +inline void print( const Vector4 & vec, const char * name ) +{ + printf( "%s: ( %f %f %f %f )\n", name, vec.getX(), vec.getY(), vec.getZ(), vec.getW() ); +} + +#endif + +inline Point3::Point3( const Point3 & pnt ) +{ + mX = pnt.mX; + mY = pnt.mY; + mZ = pnt.mZ; +} + +inline Point3::Point3( float _x, float _y, float _z ) +{ + mX = _x; + mY = _y; + mZ = _z; +} + +inline Point3::Point3( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); +} + +inline Point3::Point3( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; +} + +inline const Point3 lerp( float t, const Point3 & pnt0, const Point3 & pnt1 ) +{ + return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); +} + +inline void loadXYZ( Point3 & pnt, const float * fptr ) +{ + pnt = Point3( fptr[0], fptr[1], fptr[2] ); +} + +inline void storeXYZ( const Point3 & pnt, float * fptr ) +{ + fptr[0] = pnt.getX(); + fptr[1] = pnt.getY(); + fptr[2] = pnt.getZ(); +} + +inline void loadHalfFloats( Point3 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Point3 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Point3 & Point3::operator =( const Point3 & pnt ) +{ + mX = pnt.mX; + mY = pnt.mY; + mZ = pnt.mZ; + return *this; +} + +inline Point3 & Point3::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Point3::getX( ) const +{ + return mX; +} + +inline Point3 & Point3::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Point3::getY( ) const +{ + return mY; +} + +inline Point3 & Point3::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Point3::getZ( ) const +{ + return mZ; +} + +inline Point3 & Point3::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Point3::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Point3::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Point3::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector3 Point3::operator -( const Point3 & pnt ) const +{ + return Vector3( + ( mX - pnt.mX ), + ( mY - pnt.mY ), + ( mZ - pnt.mZ ) + ); +} + +inline const Point3 Point3::operator +( const Vector3 & vec ) const +{ + return Point3( + ( mX + vec.getX() ), + ( mY + vec.getY() ), + ( mZ + vec.getZ() ) + ); +} + +inline const Point3 Point3::operator -( const Vector3 & vec ) const +{ + return Point3( + ( mX - vec.getX() ), + ( mY - vec.getY() ), + ( mZ - vec.getZ() ) + ); +} + +inline Point3 & Point3::operator +=( const Vector3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Point3 & Point3::operator -=( const Vector3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt0.getX() * pnt1.getX() ), + ( pnt0.getY() * pnt1.getY() ), + ( pnt0.getZ() * pnt1.getZ() ) + ); +} + +inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt0.getX() / pnt1.getX() ), + ( pnt0.getY() / pnt1.getY() ), + ( pnt0.getZ() / pnt1.getZ() ) + ); +} + +inline const Point3 recipPerElem( const Point3 & pnt ) +{ + return Point3( + ( 1.0f / pnt.getX() ), + ( 1.0f / pnt.getY() ), + ( 1.0f / pnt.getZ() ) + ); +} + +inline const Point3 sqrtPerElem( const Point3 & pnt ) +{ + return Point3( + sqrtf( pnt.getX() ), + sqrtf( pnt.getY() ), + sqrtf( pnt.getZ() ) + ); +} + +inline const Point3 rsqrtPerElem( const Point3 & pnt ) +{ + return Point3( + ( 1.0f / sqrtf( pnt.getX() ) ), + ( 1.0f / sqrtf( pnt.getY() ) ), + ( 1.0f / sqrtf( pnt.getZ() ) ) + ); +} + +inline const Point3 absPerElem( const Point3 & pnt ) +{ + return Point3( + fabsf( pnt.getX() ), + fabsf( pnt.getY() ), + fabsf( pnt.getZ() ) + ); +} + +inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt1.getX() < 0.0f )? -fabsf( pnt0.getX() ) : fabsf( pnt0.getX() ), + ( pnt1.getY() < 0.0f )? -fabsf( pnt0.getY() ) : fabsf( pnt0.getY() ), + ( pnt1.getZ() < 0.0f )? -fabsf( pnt0.getZ() ) : fabsf( pnt0.getZ() ) + ); +} + +inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + (pnt0.getX() > pnt1.getX())? pnt0.getX() : pnt1.getX(), + (pnt0.getY() > pnt1.getY())? pnt0.getY() : pnt1.getY(), + (pnt0.getZ() > pnt1.getZ())? pnt0.getZ() : pnt1.getZ() + ); +} + +inline float maxElem( const Point3 & pnt ) +{ + float result; + result = (pnt.getX() > pnt.getY())? pnt.getX() : pnt.getY(); + result = (pnt.getZ() > result)? pnt.getZ() : result; + return result; +} + +inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + (pnt0.getX() < pnt1.getX())? pnt0.getX() : pnt1.getX(), + (pnt0.getY() < pnt1.getY())? pnt0.getY() : pnt1.getY(), + (pnt0.getZ() < pnt1.getZ())? pnt0.getZ() : pnt1.getZ() + ); +} + +inline float minElem( const Point3 & pnt ) +{ + float result; + result = (pnt.getX() < pnt.getY())? pnt.getX() : pnt.getY(); + result = (pnt.getZ() < result)? pnt.getZ() : result; + return result; +} + +inline float sum( const Point3 & pnt ) +{ + float result; + result = ( pnt.getX() + pnt.getY() ); + result = ( result + pnt.getZ() ); + return result; +} + +inline const Point3 scale( const Point3 & pnt, float scaleVal ) +{ + return mulPerElem( pnt, Point3( scaleVal ) ); +} + +inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ) +{ + return mulPerElem( pnt, Point3( scaleVec ) ); +} + +inline float projection( const Point3 & pnt, const Vector3 & unitVec ) +{ + float result; + result = ( pnt.getX() * unitVec.getX() ); + result = ( result + ( pnt.getY() * unitVec.getY() ) ); + result = ( result + ( pnt.getZ() * unitVec.getZ() ) ); + return result; +} + +inline float distSqrFromOrigin( const Point3 & pnt ) +{ + return lengthSqr( Vector3( pnt ) ); +} + +inline float distFromOrigin( const Point3 & pnt ) +{ + return length( Vector3( pnt ) ); +} + +inline float distSqr( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return lengthSqr( ( pnt1 - pnt0 ) ); +} + +inline float dist( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return length( ( pnt1 - pnt0 ) ); +} + +inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, bool select1 ) +{ + return Point3( + ( select1 )? pnt1.getX() : pnt0.getX(), + ( select1 )? pnt1.getY() : pnt0.getY(), + ( select1 )? pnt1.getZ() : pnt0.getZ() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Point3 & pnt ) +{ + printf( "( %f %f %f )\n", pnt.getX(), pnt.getY(), pnt.getZ() ); +} + +inline void print( const Point3 & pnt, const char * name ) +{ + printf( "%s: ( %f %f %f )\n", name, pnt.getX(), pnt.getY(), pnt.getZ() ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/scalar/cpp/vectormath_aos.h b/Extras/vectormathlibrary/include/vectormath/scalar/cpp/vectormath_aos.h new file mode 100644 index 0000000..e1c04be --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/scalar/cpp/vectormath_aos.h @@ -0,0 +1,1885 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_AOS_CPP_SCALAR_H +#define _VECTORMATH_AOS_CPP_SCALAR_H + +#include + +#ifdef _VECTORMATH_DEBUG +#include +#endif + +namespace Vectormath { + +namespace Aos { + +//----------------------------------------------------------------------------- +// Forward Declarations +// + +class Vector3; +class Vector4; +class Point3; +class Quat; +class Matrix3; +class Matrix4; +class Transform3; + +// A 3-D vector in array-of-structures format +// +class Vector3 +{ + float mX; + float mY; + float mZ; +#ifndef __GNUC__ + float d; +#endif + +public: + // Default constructor; does no initialization + // + inline Vector3( ) { }; + + // Copy a 3-D vector + // + inline Vector3( const Vector3 & vec ); + + // Construct a 3-D vector from x, y, and z elements + // + inline Vector3( float x, float y, float z ); + + // Copy elements from a 3-D point into a 3-D vector + // + explicit inline Vector3( const Point3 & pnt ); + + // Set all elements of a 3-D vector to the same scalar value + // + explicit inline Vector3( float scalar ); + + // Assign one 3-D vector to another + // + inline Vector3 & operator =( const Vector3 & vec ); + + // Set the x element of a 3-D vector + // + inline Vector3 & setX( float x ); + + // Set the y element of a 3-D vector + // + inline Vector3 & setY( float y ); + + // Set the z element of a 3-D vector + // + inline Vector3 & setZ( float z ); + + // Get the x element of a 3-D vector + // + inline float getX( ) const; + + // Get the y element of a 3-D vector + // + inline float getY( ) const; + + // Get the z element of a 3-D vector + // + inline float getZ( ) const; + + // Set an x, y, or z element of a 3-D vector by index + // + inline Vector3 & setElem( int idx, float value ); + + // Get an x, y, or z element of a 3-D vector by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two 3-D vectors + // + inline const Vector3 operator +( const Vector3 & vec ) const; + + // Subtract a 3-D vector from another 3-D vector + // + inline const Vector3 operator -( const Vector3 & vec ) const; + + // Add a 3-D vector to a 3-D point + // + inline const Point3 operator +( const Point3 & pnt ) const; + + // Multiply a 3-D vector by a scalar + // + inline const Vector3 operator *( float scalar ) const; + + // Divide a 3-D vector by a scalar + // + inline const Vector3 operator /( float scalar ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Vector3 & operator +=( const Vector3 & vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Vector3 & operator -=( const Vector3 & vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector3 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector3 & operator /=( float scalar ); + + // Negate all elements of a 3-D vector + // + inline const Vector3 operator -( ) const; + + // Construct x axis + // + static inline const Vector3 xAxis( ); + + // Construct y axis + // + static inline const Vector3 yAxis( ); + + // Construct z axis + // + static inline const Vector3 zAxis( ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a 3-D vector by a scalar +// +inline const Vector3 operator *( float scalar, const Vector3 & vec ); + +// Multiply two 3-D vectors per element +// +inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Divide two 3-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Compute the reciprocal of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector3 recipPerElem( const Vector3 & vec ); + +// Compute the square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector3 sqrtPerElem( const Vector3 & vec ); + +// Compute the reciprocal square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector3 rsqrtPerElem( const Vector3 & vec ); + +// Compute the absolute value of a 3-D vector per element +// +inline const Vector3 absPerElem( const Vector3 & vec ); + +// Copy sign from one 3-D vector to another, per element +// +inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Maximum of two 3-D vectors per element +// +inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Minimum of two 3-D vectors per element +// +inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Maximum element of a 3-D vector +// +inline float maxElem( const Vector3 & vec ); + +// Minimum element of a 3-D vector +// +inline float minElem( const Vector3 & vec ); + +// Compute the sum of all elements of a 3-D vector +// +inline float sum( const Vector3 & vec ); + +// Compute the dot product of two 3-D vectors +// +inline float dot( const Vector3 & vec0, const Vector3 & vec1 ); + +// Compute the square of the length of a 3-D vector +// +inline float lengthSqr( const Vector3 & vec ); + +// Compute the length of a 3-D vector +// +inline float length( const Vector3 & vec ); + +// Normalize a 3-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector3 normalize( const Vector3 & vec ); + +// Compute cross product of two 3-D vectors +// +inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ); + +// Outer product of two 3-D vectors +// +inline const Matrix3 outer( const Vector3 & vec0, const Vector3 & vec1 ); + +// Pre-multiply a row vector by a 3x3 matrix +// +inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ); + +// Cross-product matrix of a 3-D vector +// +inline const Matrix3 crossMatrix( const Vector3 & vec ); + +// Create cross-product matrix and multiply +// NOTE: +// Faster than separately creating a cross-product matrix and multiplying. +// +inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ); + +// Linear interpolation between two 3-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector3 lerp( float t, const Vector3 & vec0, const Vector3 & vec1 ); + +// Spherical linear interpolation between two 3-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector3 slerp( float t, const Vector3 & unitVec0, const Vector3 & unitVec1 ); + +// Conditionally select between two 3-D vectors +// +inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, bool select1 ); + +// Load x, y, and z elements from the first three words of a float array. +// +// +inline void loadXYZ( Vector3 & vec, const float * fptr ); + +// Store x, y, and z elements of a 3-D vector in the first three words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZ( const Vector3 & vec, float * fptr ); + +// Load three-half-floats as a 3-D vector +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Vector3 & vec, const unsigned short * hfptr ); + +// Store a 3-D vector as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Vector3 & vec, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector3 & vec ); + +// Print a 3-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector3 & vec, const char * name ); + +#endif + +// A 4-D vector in array-of-structures format +// +class Vector4 +{ + float mX; + float mY; + float mZ; + float mW; + +public: + // Default constructor; does no initialization + // + inline Vector4( ) { }; + + // Copy a 4-D vector + // + inline Vector4( const Vector4 & vec ); + + // Construct a 4-D vector from x, y, z, and w elements + // + inline Vector4( float x, float y, float z, float w ); + + // Construct a 4-D vector from a 3-D vector and a scalar + // + inline Vector4( const Vector3 & xyz, float w ); + + // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + // + explicit inline Vector4( const Vector3 & vec ); + + // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + // + explicit inline Vector4( const Point3 & pnt ); + + // Copy elements from a quaternion into a 4-D vector + // + explicit inline Vector4( const Quat & quat ); + + // Set all elements of a 4-D vector to the same scalar value + // + explicit inline Vector4( float scalar ); + + // Assign one 4-D vector to another + // + inline Vector4 & operator =( const Vector4 & vec ); + + // Set the x, y, and z elements of a 4-D vector + // NOTE: + // This function does not change the w element. + // + inline Vector4 & setXYZ( const Vector3 & vec ); + + // Get the x, y, and z elements of a 4-D vector + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a 4-D vector + // + inline Vector4 & setX( float x ); + + // Set the y element of a 4-D vector + // + inline Vector4 & setY( float y ); + + // Set the z element of a 4-D vector + // + inline Vector4 & setZ( float z ); + + // Set the w element of a 4-D vector + // + inline Vector4 & setW( float w ); + + // Get the x element of a 4-D vector + // + inline float getX( ) const; + + // Get the y element of a 4-D vector + // + inline float getY( ) const; + + // Get the z element of a 4-D vector + // + inline float getZ( ) const; + + // Get the w element of a 4-D vector + // + inline float getW( ) const; + + // Set an x, y, z, or w element of a 4-D vector by index + // + inline Vector4 & setElem( int idx, float value ); + + // Get an x, y, z, or w element of a 4-D vector by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two 4-D vectors + // + inline const Vector4 operator +( const Vector4 & vec ) const; + + // Subtract a 4-D vector from another 4-D vector + // + inline const Vector4 operator -( const Vector4 & vec ) const; + + // Multiply a 4-D vector by a scalar + // + inline const Vector4 operator *( float scalar ) const; + + // Divide a 4-D vector by a scalar + // + inline const Vector4 operator /( float scalar ) const; + + // Perform compound assignment and addition with a 4-D vector + // + inline Vector4 & operator +=( const Vector4 & vec ); + + // Perform compound assignment and subtraction by a 4-D vector + // + inline Vector4 & operator -=( const Vector4 & vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector4 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector4 & operator /=( float scalar ); + + // Negate all elements of a 4-D vector + // + inline const Vector4 operator -( ) const; + + // Construct x axis + // + static inline const Vector4 xAxis( ); + + // Construct y axis + // + static inline const Vector4 yAxis( ); + + // Construct z axis + // + static inline const Vector4 zAxis( ); + + // Construct w axis + // + static inline const Vector4 wAxis( ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a 4-D vector by a scalar +// +inline const Vector4 operator *( float scalar, const Vector4 & vec ); + +// Multiply two 4-D vectors per element +// +inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Divide two 4-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Compute the reciprocal of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector4 recipPerElem( const Vector4 & vec ); + +// Compute the square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector4 sqrtPerElem( const Vector4 & vec ); + +// Compute the reciprocal square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector4 rsqrtPerElem( const Vector4 & vec ); + +// Compute the absolute value of a 4-D vector per element +// +inline const Vector4 absPerElem( const Vector4 & vec ); + +// Copy sign from one 4-D vector to another, per element +// +inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Maximum of two 4-D vectors per element +// +inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Minimum of two 4-D vectors per element +// +inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Maximum element of a 4-D vector +// +inline float maxElem( const Vector4 & vec ); + +// Minimum element of a 4-D vector +// +inline float minElem( const Vector4 & vec ); + +// Compute the sum of all elements of a 4-D vector +// +inline float sum( const Vector4 & vec ); + +// Compute the dot product of two 4-D vectors +// +inline float dot( const Vector4 & vec0, const Vector4 & vec1 ); + +// Compute the square of the length of a 4-D vector +// +inline float lengthSqr( const Vector4 & vec ); + +// Compute the length of a 4-D vector +// +inline float length( const Vector4 & vec ); + +// Normalize a 4-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector4 normalize( const Vector4 & vec ); + +// Outer product of two 4-D vectors +// +inline const Matrix4 outer( const Vector4 & vec0, const Vector4 & vec1 ); + +// Linear interpolation between two 4-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector4 lerp( float t, const Vector4 & vec0, const Vector4 & vec1 ); + +// Spherical linear interpolation between two 4-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector4 slerp( float t, const Vector4 & unitVec0, const Vector4 & unitVec1 ); + +// Conditionally select between two 4-D vectors +// +inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, bool select1 ); + +// Load x, y, z, and w elements from the first four words of a float array. +// +// +inline void loadXYZW( Vector4 & vec, const float * fptr ); + +// Store x, y, z, and w elements of a 4-D vector in the first four words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZW( const Vector4 & vec, float * fptr ); + +// Load four-half-floats as a 4-D vector +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Vector4 & vec, const unsigned short * hfptr ); + +// Store a 4-D vector as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Vector4 & vec, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector4 & vec ); + +// Print a 4-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector4 & vec, const char * name ); + +#endif + +// A 3-D point in array-of-structures format +// +class Point3 +{ + float mX; + float mY; + float mZ; +#ifndef __GNUC__ + float d; +#endif + +public: + // Default constructor; does no initialization + // + inline Point3( ) { }; + + // Copy a 3-D point + // + inline Point3( const Point3 & pnt ); + + // Construct a 3-D point from x, y, and z elements + // + inline Point3( float x, float y, float z ); + + // Copy elements from a 3-D vector into a 3-D point + // + explicit inline Point3( const Vector3 & vec ); + + // Set all elements of a 3-D point to the same scalar value + // + explicit inline Point3( float scalar ); + + // Assign one 3-D point to another + // + inline Point3 & operator =( const Point3 & pnt ); + + // Set the x element of a 3-D point + // + inline Point3 & setX( float x ); + + // Set the y element of a 3-D point + // + inline Point3 & setY( float y ); + + // Set the z element of a 3-D point + // + inline Point3 & setZ( float z ); + + // Get the x element of a 3-D point + // + inline float getX( ) const; + + // Get the y element of a 3-D point + // + inline float getY( ) const; + + // Get the z element of a 3-D point + // + inline float getZ( ) const; + + // Set an x, y, or z element of a 3-D point by index + // + inline Point3 & setElem( int idx, float value ); + + // Get an x, y, or z element of a 3-D point by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Subtract a 3-D point from another 3-D point + // + inline const Vector3 operator -( const Point3 & pnt ) const; + + // Add a 3-D point to a 3-D vector + // + inline const Point3 operator +( const Vector3 & vec ) const; + + // Subtract a 3-D vector from a 3-D point + // + inline const Point3 operator -( const Vector3 & vec ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Point3 & operator +=( const Vector3 & vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Point3 & operator -=( const Vector3 & vec ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply two 3-D points per element +// +inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Divide two 3-D points per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Compute the reciprocal of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Point3 recipPerElem( const Point3 & pnt ); + +// Compute the square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Point3 sqrtPerElem( const Point3 & pnt ); + +// Compute the reciprocal square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Point3 rsqrtPerElem( const Point3 & pnt ); + +// Compute the absolute value of a 3-D point per element +// +inline const Point3 absPerElem( const Point3 & pnt ); + +// Copy sign from one 3-D point to another, per element +// +inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Maximum of two 3-D points per element +// +inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Minimum of two 3-D points per element +// +inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Maximum element of a 3-D point +// +inline float maxElem( const Point3 & pnt ); + +// Minimum element of a 3-D point +// +inline float minElem( const Point3 & pnt ); + +// Compute the sum of all elements of a 3-D point +// +inline float sum( const Point3 & pnt ); + +// Apply uniform scale to a 3-D point +// +inline const Point3 scale( const Point3 & pnt, float scaleVal ); + +// Apply non-uniform scale to a 3-D point +// +inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ); + +// Scalar projection of a 3-D point on a unit-length 3-D vector +// +inline float projection( const Point3 & pnt, const Vector3 & unitVec ); + +// Compute the square of the distance of a 3-D point from the coordinate-system origin +// +inline float distSqrFromOrigin( const Point3 & pnt ); + +// Compute the distance of a 3-D point from the coordinate-system origin +// +inline float distFromOrigin( const Point3 & pnt ); + +// Compute the square of the distance between two 3-D points +// +inline float distSqr( const Point3 & pnt0, const Point3 & pnt1 ); + +// Compute the distance between two 3-D points +// +inline float dist( const Point3 & pnt0, const Point3 & pnt1 ); + +// Linear interpolation between two 3-D points +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Point3 lerp( float t, const Point3 & pnt0, const Point3 & pnt1 ); + +// Conditionally select between two 3-D points +// +inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, bool select1 ); + +// Load x, y, and z elements from the first three words of a float array. +// +// +inline void loadXYZ( Point3 & pnt, const float * fptr ); + +// Store x, y, and z elements of a 3-D point in the first three words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZ( const Point3 & pnt, float * fptr ); + +// Load three-half-floats as a 3-D point +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Point3 & pnt, const unsigned short * hfptr ); + +// Store a 3-D point as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Point3 & pnt, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D point +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Point3 & pnt ); + +// Print a 3-D point and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Point3 & pnt, const char * name ); + +#endif + +// A quaternion in array-of-structures format +// +class Quat +{ + float mX; + float mY; + float mZ; + float mW; + +public: + // Default constructor; does no initialization + // + inline Quat( ) { }; + + // Copy a quaternion + // + inline Quat( const Quat & quat ); + + // Construct a quaternion from x, y, z, and w elements + // + inline Quat( float x, float y, float z, float w ); + + // Construct a quaternion from a 3-D vector and a scalar + // + inline Quat( const Vector3 & xyz, float w ); + + // Copy elements from a 4-D vector into a quaternion + // + explicit inline Quat( const Vector4 & vec ); + + // Convert a rotation matrix to a unit-length quaternion + // + explicit inline Quat( const Matrix3 & rotMat ); + + // Set all elements of a quaternion to the same scalar value + // + explicit inline Quat( float scalar ); + + // Assign one quaternion to another + // + inline Quat & operator =( const Quat & quat ); + + // Set the x, y, and z elements of a quaternion + // NOTE: + // This function does not change the w element. + // + inline Quat & setXYZ( const Vector3 & vec ); + + // Get the x, y, and z elements of a quaternion + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a quaternion + // + inline Quat & setX( float x ); + + // Set the y element of a quaternion + // + inline Quat & setY( float y ); + + // Set the z element of a quaternion + // + inline Quat & setZ( float z ); + + // Set the w element of a quaternion + // + inline Quat & setW( float w ); + + // Get the x element of a quaternion + // + inline float getX( ) const; + + // Get the y element of a quaternion + // + inline float getY( ) const; + + // Get the z element of a quaternion + // + inline float getZ( ) const; + + // Get the w element of a quaternion + // + inline float getW( ) const; + + // Set an x, y, z, or w element of a quaternion by index + // + inline Quat & setElem( int idx, float value ); + + // Get an x, y, z, or w element of a quaternion by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two quaternions + // + inline const Quat operator +( const Quat & quat ) const; + + // Subtract a quaternion from another quaternion + // + inline const Quat operator -( const Quat & quat ) const; + + // Multiply two quaternions + // + inline const Quat operator *( const Quat & quat ) const; + + // Multiply a quaternion by a scalar + // + inline const Quat operator *( float scalar ) const; + + // Divide a quaternion by a scalar + // + inline const Quat operator /( float scalar ) const; + + // Perform compound assignment and addition with a quaternion + // + inline Quat & operator +=( const Quat & quat ); + + // Perform compound assignment and subtraction by a quaternion + // + inline Quat & operator -=( const Quat & quat ); + + // Perform compound assignment and multiplication by a quaternion + // + inline Quat & operator *=( const Quat & quat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Quat & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Quat & operator /=( float scalar ); + + // Negate all elements of a quaternion + // + inline const Quat operator -( ) const; + + // Construct an identity quaternion + // + static inline const Quat identity( ); + + // Construct a quaternion to rotate between two unit-length 3-D vectors + // NOTE: + // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + // + static inline const Quat rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ); + + // Construct a quaternion to rotate around a unit-length 3-D vector + // + static inline const Quat rotation( float radians, const Vector3 & unitVec ); + + // Construct a quaternion to rotate around the x axis + // + static inline const Quat rotationX( float radians ); + + // Construct a quaternion to rotate around the y axis + // + static inline const Quat rotationY( float radians ); + + // Construct a quaternion to rotate around the z axis + // + static inline const Quat rotationZ( float radians ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a quaternion by a scalar +// +inline const Quat operator *( float scalar, const Quat & quat ); + +// Compute the conjugate of a quaternion +// +inline const Quat conj( const Quat & quat ); + +// Use a unit-length quaternion to rotate a 3-D vector +// +inline const Vector3 rotate( const Quat & unitQuat, const Vector3 & vec ); + +// Compute the dot product of two quaternions +// +inline float dot( const Quat & quat0, const Quat & quat1 ); + +// Compute the norm of a quaternion +// +inline float norm( const Quat & quat ); + +// Compute the length of a quaternion +// +inline float length( const Quat & quat ); + +// Normalize a quaternion +// NOTE: +// The result is unpredictable when all elements of quat are at or near zero. +// +inline const Quat normalize( const Quat & quat ); + +// Linear interpolation between two quaternions +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Quat lerp( float t, const Quat & quat0, const Quat & quat1 ); + +// Spherical linear interpolation between two quaternions +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +inline const Quat slerp( float t, const Quat & unitQuat0, const Quat & unitQuat1 ); + +// Spherical quadrangle interpolation +// +inline const Quat squad( float t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ); + +// Conditionally select between two quaternions +// +inline const Quat select( const Quat & quat0, const Quat & quat1, bool select1 ); + +// Load x, y, z, and w elements from the first four words of a float array. +// +// +inline void loadXYZW( Quat & quat, const float * fptr ); + +// Store x, y, z, and w elements of a quaternion in the first four words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZW( const Quat & quat, float * fptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a quaternion +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Quat & quat ); + +// Print a quaternion and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Quat & quat, const char * name ); + +#endif + +// A 3x3 matrix in array-of-structures format +// +class Matrix3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + +public: + // Default constructor; does no initialization + // + inline Matrix3( ) { }; + + // Copy a 3x3 matrix + // + inline Matrix3( const Matrix3 & mat ); + + // Construct a 3x3 matrix containing the specified columns + // + inline Matrix3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2 ); + + // Construct a 3x3 rotation matrix from a unit-length quaternion + // + explicit inline Matrix3( const Quat & unitQuat ); + + // Set all elements of a 3x3 matrix to the same scalar value + // + explicit inline Matrix3( float scalar ); + + // Assign one 3x3 matrix to another + // + inline Matrix3 & operator =( const Matrix3 & mat ); + + // Set column 0 of a 3x3 matrix + // + inline Matrix3 & setCol0( const Vector3 & col0 ); + + // Set column 1 of a 3x3 matrix + // + inline Matrix3 & setCol1( const Vector3 & col1 ); + + // Set column 2 of a 3x3 matrix + // + inline Matrix3 & setCol2( const Vector3 & col2 ); + + // Get column 0 of a 3x3 matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x3 matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x3 matrix + // + inline const Vector3 getCol2( ) const; + + // Set the column of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setCol( int col, const Vector3 & vec ); + + // Set the row of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setRow( int row, const Vector3 & vec ); + + // Get the column of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x3 matrix referred to by column and row indices + // + inline Matrix3 & setElem( int col, int row, float val ); + + // Get the element of a 3x3 matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Add two 3x3 matrices + // + inline const Matrix3 operator +( const Matrix3 & mat ) const; + + // Subtract a 3x3 matrix from another 3x3 matrix + // + inline const Matrix3 operator -( const Matrix3 & mat ) const; + + // Negate all elements of a 3x3 matrix + // + inline const Matrix3 operator -( ) const; + + // Multiply a 3x3 matrix by a scalar + // + inline const Matrix3 operator *( float scalar ) const; + + // Multiply a 3x3 matrix by a 3-D vector + // + inline const Vector3 operator *( const Vector3 & vec ) const; + + // Multiply two 3x3 matrices + // + inline const Matrix3 operator *( const Matrix3 & mat ) const; + + // Perform compound assignment and addition with a 3x3 matrix + // + inline Matrix3 & operator +=( const Matrix3 & mat ); + + // Perform compound assignment and subtraction by a 3x3 matrix + // + inline Matrix3 & operator -=( const Matrix3 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix3 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a 3x3 matrix + // + inline Matrix3 & operator *=( const Matrix3 & mat ); + + // Construct an identity 3x3 matrix + // + static inline const Matrix3 identity( ); + + // Construct a 3x3 matrix to rotate around the x axis + // + static inline const Matrix3 rotationX( float radians ); + + // Construct a 3x3 matrix to rotate around the y axis + // + static inline const Matrix3 rotationY( float radians ); + + // Construct a 3x3 matrix to rotate around the z axis + // + static inline const Matrix3 rotationZ( float radians ); + + // Construct a 3x3 matrix to rotate around the x, y, and z axes + // + static inline const Matrix3 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix3 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix3 rotation( const Quat & unitQuat ); + + // Construct a 3x3 matrix to perform scaling + // + static inline const Matrix3 scale( const Vector3 & scaleVec ); + +}; +// Multiply a 3x3 matrix by a scalar +// +inline const Matrix3 operator *( float scalar, const Matrix3 & mat ); + +// Append (post-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ); + +// Multiply two 3x3 matrices per element +// +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); + +// Compute the absolute value of a 3x3 matrix per element +// +inline const Matrix3 absPerElem( const Matrix3 & mat ); + +// Transpose of a 3x3 matrix +// +inline const Matrix3 transpose( const Matrix3 & mat ); + +// Compute the inverse of a 3x3 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix3 inverse( const Matrix3 & mat ); + +// Determinant of a 3x3 matrix +// +inline float determinant( const Matrix3 & mat ); + +// Conditionally select between two 3x3 matrices +// +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x3 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat ); + +// Print a 3x3 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat, const char * name ); + +#endif + +// A 4x4 matrix in array-of-structures format +// +class Matrix4 +{ + Vector4 mCol0; + Vector4 mCol1; + Vector4 mCol2; + Vector4 mCol3; + +public: + // Default constructor; does no initialization + // + inline Matrix4( ) { }; + + // Copy a 4x4 matrix + // + inline Matrix4( const Matrix4 & mat ); + + // Construct a 4x4 matrix containing the specified columns + // + inline Matrix4( const Vector4 & col0, const Vector4 & col1, const Vector4 & col2, const Vector4 & col3 ); + + // Construct a 4x4 matrix from a 3x4 transformation matrix + // + explicit inline Matrix4( const Transform3 & mat ); + + // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + // + inline Matrix4( const Matrix3 & mat, const Vector3 & translateVec ); + + // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + // + inline Matrix4( const Quat & unitQuat, const Vector3 & translateVec ); + + // Set all elements of a 4x4 matrix to the same scalar value + // + explicit inline Matrix4( float scalar ); + + // Assign one 4x4 matrix to another + // + inline Matrix4 & operator =( const Matrix4 & mat ); + + // Set the upper-left 3x3 submatrix + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 4x4 matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setTranslation( const Vector3 & translateVec ); + + // Get the translation component of a 4x4 matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 4x4 matrix + // + inline Matrix4 & setCol0( const Vector4 & col0 ); + + // Set column 1 of a 4x4 matrix + // + inline Matrix4 & setCol1( const Vector4 & col1 ); + + // Set column 2 of a 4x4 matrix + // + inline Matrix4 & setCol2( const Vector4 & col2 ); + + // Set column 3 of a 4x4 matrix + // + inline Matrix4 & setCol3( const Vector4 & col3 ); + + // Get column 0 of a 4x4 matrix + // + inline const Vector4 getCol0( ) const; + + // Get column 1 of a 4x4 matrix + // + inline const Vector4 getCol1( ) const; + + // Get column 2 of a 4x4 matrix + // + inline const Vector4 getCol2( ) const; + + // Get column 3 of a 4x4 matrix + // + inline const Vector4 getCol3( ) const; + + // Set the column of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setCol( int col, const Vector4 & vec ); + + // Set the row of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setRow( int row, const Vector4 & vec ); + + // Get the column of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getCol( int col ) const; + + // Get the row of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector4 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector4 operator []( int col ) const; + + // Set the element of a 4x4 matrix referred to by column and row indices + // + inline Matrix4 & setElem( int col, int row, float val ); + + // Get the element of a 4x4 matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Add two 4x4 matrices + // + inline const Matrix4 operator +( const Matrix4 & mat ) const; + + // Subtract a 4x4 matrix from another 4x4 matrix + // + inline const Matrix4 operator -( const Matrix4 & mat ) const; + + // Negate all elements of a 4x4 matrix + // + inline const Matrix4 operator -( ) const; + + // Multiply a 4x4 matrix by a scalar + // + inline const Matrix4 operator *( float scalar ) const; + + // Multiply a 4x4 matrix by a 4-D vector + // + inline const Vector4 operator *( const Vector4 & vec ) const; + + // Multiply a 4x4 matrix by a 3-D vector + // + inline const Vector4 operator *( const Vector3 & vec ) const; + + // Multiply a 4x4 matrix by a 3-D point + // + inline const Vector4 operator *( const Point3 & pnt ) const; + + // Multiply two 4x4 matrices + // + inline const Matrix4 operator *( const Matrix4 & mat ) const; + + // Multiply a 4x4 matrix by a 3x4 transformation matrix + // + inline const Matrix4 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and addition with a 4x4 matrix + // + inline Matrix4 & operator +=( const Matrix4 & mat ); + + // Perform compound assignment and subtraction by a 4x4 matrix + // + inline Matrix4 & operator -=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix4 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a 4x4 matrix + // + inline Matrix4 & operator *=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Matrix4 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 4x4 matrix + // + static inline const Matrix4 identity( ); + + // Construct a 4x4 matrix to rotate around the x axis + // + static inline const Matrix4 rotationX( float radians ); + + // Construct a 4x4 matrix to rotate around the y axis + // + static inline const Matrix4 rotationY( float radians ); + + // Construct a 4x4 matrix to rotate around the z axis + // + static inline const Matrix4 rotationZ( float radians ); + + // Construct a 4x4 matrix to rotate around the x, y, and z axes + // + static inline const Matrix4 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix4 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix4 rotation( const Quat & unitQuat ); + + // Construct a 4x4 matrix to perform scaling + // + static inline const Matrix4 scale( const Vector3 & scaleVec ); + + // Construct a 4x4 matrix to perform translation + // + static inline const Matrix4 translation( const Vector3 & translateVec ); + + // Construct viewing matrix based on eye position, position looked at, and up direction + // + static inline const Matrix4 lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ); + + // Construct a perspective projection matrix + // + static inline const Matrix4 perspective( float fovyRadians, float aspect, float zNear, float zFar ); + + // Construct a perspective projection matrix based on frustum + // + static inline const Matrix4 frustum( float left, float right, float bottom, float top, float zNear, float zFar ); + + // Construct an orthographic projection matrix + // + static inline const Matrix4 orthographic( float left, float right, float bottom, float top, float zNear, float zFar ); + +}; +// Multiply a 4x4 matrix by a scalar +// +inline const Matrix4 operator *( float scalar, const Matrix4 & mat ); + +// Append (post-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ); + +// Multiply two 4x4 matrices per element +// +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); + +// Compute the absolute value of a 4x4 matrix per element +// +inline const Matrix4 absPerElem( const Matrix4 & mat ); + +// Transpose of a 4x4 matrix +// +inline const Matrix4 transpose( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 inverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 affineInverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. +// +inline const Matrix4 orthoInverse( const Matrix4 & mat ); + +// Determinant of a 4x4 matrix +// +inline float determinant( const Matrix4 & mat ); + +// Conditionally select between two 4x4 matrices +// +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4x4 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat ); + +// Print a 4x4 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat, const char * name ); + +#endif + +// A 3x4 transformation matrix in array-of-structures format +// +class Transform3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + Vector3 mCol3; + +public: + // Default constructor; does no initialization + // + inline Transform3( ) { }; + + // Copy a 3x4 transformation matrix + // + inline Transform3( const Transform3 & tfrm ); + + // Construct a 3x4 transformation matrix containing the specified columns + // + inline Transform3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2, const Vector3 & col3 ); + + // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + // + inline Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ); + + // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + // + inline Transform3( const Quat & unitQuat, const Vector3 & translateVec ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value + // + explicit inline Transform3( float scalar ); + + // Assign one 3x4 transformation matrix to another + // + inline Transform3 & operator =( const Transform3 & tfrm ); + + // Set the upper-left 3x3 submatrix + // + inline Transform3 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // + inline Transform3 & setTranslation( const Vector3 & translateVec ); + + // Get the translation component of a 3x4 transformation matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 3x4 transformation matrix + // + inline Transform3 & setCol0( const Vector3 & col0 ); + + // Set column 1 of a 3x4 transformation matrix + // + inline Transform3 & setCol1( const Vector3 & col1 ); + + // Set column 2 of a 3x4 transformation matrix + // + inline Transform3 & setCol2( const Vector3 & col2 ); + + // Set column 3 of a 3x4 transformation matrix + // + inline Transform3 & setCol3( const Vector3 & col3 ); + + // Get column 0 of a 3x4 transformation matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x4 transformation matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x4 transformation matrix + // + inline const Vector3 getCol2( ) const; + + // Get column 3 of a 3x4 transformation matrix + // + inline const Vector3 getCol3( ) const; + + // Set the column of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setCol( int col, const Vector3 & vec ); + + // Set the row of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setRow( int row, const Vector4 & vec ); + + // Get the column of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x4 transformation matrix referred to by column and row indices + // + inline Transform3 & setElem( int col, int row, float val ); + + // Get the element of a 3x4 transformation matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Multiply a 3x4 transformation matrix by a 3-D vector + // + inline const Vector3 operator *( const Vector3 & vec ) const; + + // Multiply a 3x4 transformation matrix by a 3-D point + // + inline const Point3 operator *( const Point3 & pnt ) const; + + // Multiply two 3x4 transformation matrices + // + inline const Transform3 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Transform3 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 3x4 transformation matrix + // + static inline const Transform3 identity( ); + + // Construct a 3x4 transformation matrix to rotate around the x axis + // + static inline const Transform3 rotationX( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis + // + static inline const Transform3 rotationY( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis + // + static inline const Transform3 rotationZ( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + // + static inline const Transform3 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + // + static inline const Transform3 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Transform3 rotation( const Quat & unitQuat ); + + // Construct a 3x4 transformation matrix to perform scaling + // + static inline const Transform3 scale( const Vector3 & scaleVec ); + + // Construct a 3x4 transformation matrix to perform translation + // + static inline const Transform3 translation( const Vector3 & translateVec ); + +}; +// Append (post-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ); + +// Multiply two 3x4 transformation matrices per element +// +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); + +// Compute the absolute value of a 3x4 transformation matrix per element +// +inline const Transform3 absPerElem( const Transform3 & tfrm ); + +// Inverse of a 3x4 transformation matrix +// NOTE: +// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. +// +inline const Transform3 inverse( const Transform3 & tfrm ); + +// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. +// +inline const Transform3 orthoInverse( const Transform3 & tfrm ); + +// Conditionally select between two 3x4 transformation matrices +// +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x4 transformation matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm ); + +// Print a 3x4 transformation matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm, const char * name ); + +#endif + +} // namespace Aos +} // namespace Vectormath + +#include "vec_aos.h" +#include "quat_aos.h" +#include "mat_aos.h" + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/c/mat_aos.h b/Extras/vectormathlibrary/include/vectormath/spu/c/mat_aos.h new file mode 100644 index 0000000..d6b4cb0 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/c/mat_aos.h @@ -0,0 +1,1833 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_AOS_C_H +#define _VECTORMATH_MAT_AOS_C_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + * for shuffles, words are labeled [x,y,z,w] [a,b,c,d] + */ +#define _VECTORMATH_SHUF_XAYB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_ZCWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_ZBW0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_XCY0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_XYAB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_ZWCD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_0ZB0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_C0X0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_YA00 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_XAZC ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_C }) +#define _VECTORMATH_SHUF_YXWZ ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_Z }) +#define _VECTORMATH_SHUF_YBWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_XYCX ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_X }) +#define _VECTORMATH_SHUF_YCXY ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y }) +#define _VECTORMATH_SHUF_CXYC ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_C }) +#define _VECTORMATH_SHUF_ZAY0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_BZX0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_0ZYA ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_A }) +#define _VECTORMATH_SHUF_Z0XB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_YX0C ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_C }) +#define _VECTORMATH_SHUF_CZD0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_D, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_BBY0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_PI_OVER_2 1.570796327f + +/*----------------------------------------------------------------------------- + * Definitions + */ +static inline void vmathM3Copy( VmathMatrix3 *result, const VmathMatrix3 *mat ) +{ + vmathV3Copy( &result->col0, &mat->col0 ); + vmathV3Copy( &result->col1, &mat->col1 ); + vmathV3Copy( &result->col2, &mat->col2 ); +} + +static inline void vmathM3MakeFromScalar( VmathMatrix3 *result, float scalar ) +{ + vmathV3MakeFromScalar( &result->col0, scalar ); + vmathV3MakeFromScalar( &result->col1, scalar ); + vmathV3MakeFromScalar( &result->col2, scalar ); +} + +static inline void vmathM3MakeFromQ( VmathMatrix3 *result, const VmathQuat *unitQuat ) +{ + vec_float4 xyzw_2, wwww, yzxw, zxyw, yzxw_2, zxyw_2; + vec_float4 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + vec_uchar16 shuffle_wwww = (vec_uchar16)spu_splats((int)0x0c0d0e0f); + vec_uint4 select_x = (vec_uint4)spu_maskb(0xf000); + vec_uint4 select_z = (vec_uint4)spu_maskb(0x00f0); + xyzw_2 = spu_add( unitQuat->vec128, unitQuat->vec128 ); + wwww = spu_shuffle( unitQuat->vec128, unitQuat->vec128, shuffle_wwww ); + yzxw = spu_shuffle( unitQuat->vec128, unitQuat->vec128, _VECTORMATH_SHUF_YZXW ); + zxyw = spu_shuffle( unitQuat->vec128, unitQuat->vec128, _VECTORMATH_SHUF_ZXYW ); + yzxw_2 = spu_shuffle( xyzw_2, xyzw_2, _VECTORMATH_SHUF_YZXW ); + zxyw_2 = spu_shuffle( xyzw_2, xyzw_2, _VECTORMATH_SHUF_ZXYW ); + tmp0 = spu_mul( yzxw_2, wwww ); + tmp1 = spu_nmsub( yzxw, yzxw_2, spu_splats(1.0f) ); + tmp2 = spu_mul( yzxw, xyzw_2 ); + tmp0 = spu_madd( zxyw, xyzw_2, tmp0 ); + tmp1 = spu_nmsub( zxyw, zxyw_2, tmp1 ); + tmp2 = spu_nmsub( zxyw_2, wwww, tmp2 ); + tmp3 = spu_sel( tmp0, tmp1, select_x ); + tmp4 = spu_sel( tmp1, tmp2, select_x ); + tmp5 = spu_sel( tmp2, tmp0, select_x ); + result->col0.vec128 = spu_sel( tmp3, tmp2, select_z ); + result->col1.vec128 = spu_sel( tmp4, tmp0, select_z ); + result->col2.vec128 = spu_sel( tmp5, tmp1, select_z ); +} + +static inline void vmathM3MakeFromCols( VmathMatrix3 *result, const VmathVector3 *_col0, const VmathVector3 *_col1, const VmathVector3 *_col2 ) +{ + vmathV3Copy( &result->col0, _col0 ); + vmathV3Copy( &result->col1, _col1 ); + vmathV3Copy( &result->col2, _col2 ); +} + +static inline void vmathM3SetCol0( VmathMatrix3 *result, const VmathVector3 *_col0 ) +{ + vmathV3Copy( &result->col0, _col0 ); +} + +static inline void vmathM3SetCol1( VmathMatrix3 *result, const VmathVector3 *_col1 ) +{ + vmathV3Copy( &result->col1, _col1 ); +} + +static inline void vmathM3SetCol2( VmathMatrix3 *result, const VmathVector3 *_col2 ) +{ + vmathV3Copy( &result->col2, _col2 ); +} + +static inline void vmathM3SetCol( VmathMatrix3 *result, int col, const VmathVector3 *vec ) +{ + vmathV3Copy( (&result->col0 + col), vec ); +} + +static inline void vmathM3SetRow( VmathMatrix3 *result, int row, const VmathVector3 *vec ) +{ + vmathV3SetElem( &result->col0, row, vmathV3GetElem( vec, 0 ) ); + vmathV3SetElem( &result->col1, row, vmathV3GetElem( vec, 1 ) ); + vmathV3SetElem( &result->col2, row, vmathV3GetElem( vec, 2 ) ); +} + +static inline void vmathM3SetElem( VmathMatrix3 *result, int col, int row, float val ) +{ + VmathVector3 tmpV3_0; + vmathM3GetCol( &tmpV3_0, result, col ); + vmathV3SetElem( &tmpV3_0, row, val ); + vmathM3SetCol( result, col, &tmpV3_0 ); +} + +static inline float vmathM3GetElem( const VmathMatrix3 *mat, int col, int row ) +{ + VmathVector3 tmpV3_0; + vmathM3GetCol( &tmpV3_0, mat, col ); + return vmathV3GetElem( &tmpV3_0, row ); +} + +static inline void vmathM3GetCol0( VmathVector3 *result, const VmathMatrix3 *mat ) +{ + vmathV3Copy( result, &mat->col0 ); +} + +static inline void vmathM3GetCol1( VmathVector3 *result, const VmathMatrix3 *mat ) +{ + vmathV3Copy( result, &mat->col1 ); +} + +static inline void vmathM3GetCol2( VmathVector3 *result, const VmathMatrix3 *mat ) +{ + vmathV3Copy( result, &mat->col2 ); +} + +static inline void vmathM3GetCol( VmathVector3 *result, const VmathMatrix3 *mat, int col ) +{ + vmathV3Copy( result, (&mat->col0 + col) ); +} + +static inline void vmathM3GetRow( VmathVector3 *result, const VmathMatrix3 *mat, int row ) +{ + vmathV3MakeFromElems( result, vmathV3GetElem( &mat->col0, row ), vmathV3GetElem( &mat->col1, row ), vmathV3GetElem( &mat->col2, row ) ); +} + +static inline void vmathM3Transpose( VmathMatrix3 *result, const VmathMatrix3 *mat ) +{ + vec_float4 tmp0, tmp1, res0, res1, res2; + tmp0 = spu_shuffle( mat->col0.vec128, mat->col2.vec128, _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( mat->col0.vec128, mat->col2.vec128, _VECTORMATH_SHUF_ZCWD ); + res0 = spu_shuffle( tmp0, mat->col1.vec128, _VECTORMATH_SHUF_XAYB ); + res1 = spu_shuffle( tmp0, mat->col1.vec128, _VECTORMATH_SHUF_ZBW0 ); + res2 = spu_shuffle( tmp1, mat->col1.vec128, _VECTORMATH_SHUF_XCY0 ); + result->col0.vec128 = res0; + result->col1.vec128 = res1; + result->col2.vec128 = res2; +} + +static inline void vmathM3Inverse( VmathMatrix3 *result, const VmathMatrix3 *mat ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet, inv0, inv1, inv2; + tmp2 = _vmathVfCross( mat->col0.vec128, mat->col1.vec128 ); + tmp0 = _vmathVfCross( mat->col1.vec128, mat->col2.vec128 ); + tmp1 = _vmathVfCross( mat->col2.vec128, mat->col0.vec128 ); + dot = _vmathVfDot3( tmp2, mat->col2.vec128 ); + dot = spu_shuffle( dot, dot, (vec_uchar16)spu_splats(0x00010203) ); + invdet = recipf4( dot ); + tmp3 = spu_shuffle( tmp0, tmp2, _VECTORMATH_SHUF_XAYB ); + tmp4 = spu_shuffle( tmp0, tmp2, _VECTORMATH_SHUF_ZCWD ); + inv0 = spu_shuffle( tmp3, tmp1, _VECTORMATH_SHUF_XAYB ); + inv1 = spu_shuffle( tmp3, tmp1, _VECTORMATH_SHUF_ZBW0 ); + inv2 = spu_shuffle( tmp4, tmp1, _VECTORMATH_SHUF_XCY0 ); + inv0 = spu_mul( inv0, invdet ); + inv1 = spu_mul( inv1, invdet ); + inv2 = spu_mul( inv2, invdet ); + result->col0.vec128 = inv0; + result->col1.vec128 = inv1; + result->col2.vec128 = inv2; +} + +static inline float vmathM3Determinant( const VmathMatrix3 *mat ) +{ + VmathVector3 tmpV3_0; + vmathV3Cross( &tmpV3_0, &mat->col0, &mat->col1 ); + return vmathV3Dot( &mat->col2, &tmpV3_0 ); +} + +static inline void vmathM3Add( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ) +{ + vmathV3Add( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV3Add( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV3Add( &result->col2, &mat0->col2, &mat1->col2 ); +} + +static inline void vmathM3Sub( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ) +{ + vmathV3Sub( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV3Sub( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV3Sub( &result->col2, &mat0->col2, &mat1->col2 ); +} + +static inline void vmathM3Neg( VmathMatrix3 *result, const VmathMatrix3 *mat ) +{ + vmathV3Neg( &result->col0, &mat->col0 ); + vmathV3Neg( &result->col1, &mat->col1 ); + vmathV3Neg( &result->col2, &mat->col2 ); +} + +static inline void vmathM3AbsPerElem( VmathMatrix3 *result, const VmathMatrix3 *mat ) +{ + vmathV3AbsPerElem( &result->col0, &mat->col0 ); + vmathV3AbsPerElem( &result->col1, &mat->col1 ); + vmathV3AbsPerElem( &result->col2, &mat->col2 ); +} + +static inline void vmathM3ScalarMul( VmathMatrix3 *result, const VmathMatrix3 *mat, float scalar ) +{ + vmathV3ScalarMul( &result->col0, &mat->col0, scalar ); + vmathV3ScalarMul( &result->col1, &mat->col1, scalar ); + vmathV3ScalarMul( &result->col2, &mat->col2, scalar ); +} + +static inline void vmathM3MulV3( VmathVector3 *result, const VmathMatrix3 *mat, const VmathVector3 *vec ) +{ + vec_float4 res; + vec_float4 xxxx, yyyy, zzzz; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + xxxx = spu_shuffle( vec->vec128, vec->vec128, shuffle_xxxx ); + yyyy = spu_shuffle( vec->vec128, vec->vec128, shuffle_yyyy ); + zzzz = spu_shuffle( vec->vec128, vec->vec128, shuffle_zzzz ); + res = spu_mul( mat->col0.vec128, xxxx ); + res = spu_madd( mat->col1.vec128, yyyy, res ); + res = spu_madd( mat->col2.vec128, zzzz, res ); + result->vec128 = res; +} + +static inline void vmathM3Mul( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ) +{ + VmathMatrix3 tmpResult; + vmathM3MulV3( &tmpResult.col0, mat0, &mat1->col0 ); + vmathM3MulV3( &tmpResult.col1, mat0, &mat1->col1 ); + vmathM3MulV3( &tmpResult.col2, mat0, &mat1->col2 ); + vmathM3Copy( result, &tmpResult ); +} + +static inline void vmathM3MulPerElem( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ) +{ + vmathV3MulPerElem( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV3MulPerElem( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV3MulPerElem( &result->col2, &mat0->col2, &mat1->col2 ); +} + +static inline void vmathM3MakeIdentity( VmathMatrix3 *result ) +{ + vmathV3MakeXAxis( &result->col0 ); + vmathV3MakeYAxis( &result->col1 ); + vmathV3MakeZAxis( &result->col2 ); +} + +static inline void vmathM3MakeRotationX( VmathMatrix3 *result, float radians ) +{ + vec_float4 s, c, res1, res2; + vec_uint4 select_y, select_z; + vec_float4 zero; + select_y = (vec_uint4)spu_maskb(0x0f00); + select_z = (vec_uint4)spu_maskb(0x00f0); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res1 = spu_sel( zero, c, select_y ); + res1 = spu_sel( res1, s, select_z ); + res2 = spu_sel( zero, negatef4(s), select_y ); + res2 = spu_sel( res2, c, select_z ); + vmathV3MakeXAxis( &result->col0 ); + result->col1.vec128 = res1; + result->col2.vec128 = res2; +} + +static inline void vmathM3MakeRotationY( VmathMatrix3 *result, float radians ) +{ + vec_float4 s, c, res0, res2; + vec_uint4 select_x, select_z; + vec_float4 zero; + select_x = (vec_uint4)spu_maskb(0xf000); + select_z = (vec_uint4)spu_maskb(0x00f0); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res0 = spu_sel( zero, c, select_x ); + res0 = spu_sel( res0, negatef4(s), select_z ); + res2 = spu_sel( zero, s, select_x ); + res2 = spu_sel( res2, c, select_z ); + result->col0.vec128 = res0; + vmathV3MakeYAxis( &result->col1 ); + result->col2.vec128 = res2; +} + +static inline void vmathM3MakeRotationZ( VmathMatrix3 *result, float radians ) +{ + vec_float4 s, c, res0, res1; + vec_uint4 select_x, select_y; + vec_float4 zero; + select_x = (vec_uint4)spu_maskb(0xf000); + select_y = (vec_uint4)spu_maskb(0x0f00); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res0 = spu_sel( zero, c, select_x ); + res0 = spu_sel( res0, s, select_y ); + res1 = spu_sel( zero, negatef4(s), select_x ); + res1 = spu_sel( res1, c, select_y ); + result->col0.vec128 = res0; + result->col1.vec128 = res1; + vmathV3MakeZAxis( &result->col2 ); +} + +static inline void vmathM3MakeRotationZYX( VmathMatrix3 *result, const VmathVector3 *radiansXYZ ) +{ + vec_float4 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + angles = radiansXYZ->vec128; + angles = spu_insert( 0.0f, angles, 3 ); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = spu_shuffle( s, c, _VECTORMATH_SHUF_CZD0 ); + Z1 = spu_shuffle( c, negS, _VECTORMATH_SHUF_CZD0 ); + Y0 = spu_shuffle( negS, c, _VECTORMATH_SHUF_BBY0 ); + Y1 = spu_shuffle( c, s, _VECTORMATH_SHUF_BBY0 ); + X0 = spu_shuffle( s, s, shuffle_xxxx ); + X1 = spu_shuffle( c, c, shuffle_xxxx ); + tmp = spu_mul( Z0, Y1 ); + result->col0.vec128 = spu_mul( Z0, Y0 ); + result->col1.vec128 = spu_madd( Z1, X1, spu_mul( tmp, X0 ) ); + result->col2.vec128 = spu_nmsub( Z1, X0, spu_mul( tmp, X1 ) ); +} + +static inline void vmathM3MakeRotationAxis( VmathMatrix3 *result, float radians, const VmathVector3 *unitVec ) +{ + vec_float4 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + axis = unitVec->vec128; + sincosf4( spu_splats( radians ), &s, &c ); + xxxx = spu_shuffle( axis, axis, shuffle_xxxx ); + yyyy = spu_shuffle( axis, axis, shuffle_yyyy ); + zzzz = spu_shuffle( axis, axis, shuffle_zzzz ); + oneMinusC = spu_sub( spu_splats(1.0f), c ); + axisS = spu_mul( axis, s ); + negAxisS = negatef4( axisS ); + tmp0 = spu_shuffle( axisS, negAxisS, _VECTORMATH_SHUF_0ZB0 ); + tmp1 = spu_shuffle( axisS, negAxisS, _VECTORMATH_SHUF_C0X0 ); + tmp2 = spu_shuffle( axisS, negAxisS, _VECTORMATH_SHUF_YA00 ); + tmp0 = spu_sel( tmp0, c, (vec_uint4)spu_maskb(0xf000) ); + tmp1 = spu_sel( tmp1, c, (vec_uint4)spu_maskb(0x0f00) ); + tmp2 = spu_sel( tmp2, c, (vec_uint4)spu_maskb(0x00f0) ); + result->col0.vec128 = spu_madd( spu_mul( axis, xxxx ), oneMinusC, tmp0 ); + result->col1.vec128 = spu_madd( spu_mul( axis, yyyy ), oneMinusC, tmp1 ); + result->col2.vec128 = spu_madd( spu_mul( axis, zzzz ), oneMinusC, tmp2 ); +} + +static inline void vmathM3MakeRotationQ( VmathMatrix3 *result, const VmathQuat *unitQuat ) +{ + vmathM3MakeFromQ( result, unitQuat ); +} + +static inline void vmathM3MakeScale( VmathMatrix3 *result, const VmathVector3 *scaleVec ) +{ + vec_float4 zero = spu_splats(0.0f); + result->col0.vec128 = spu_sel( zero, scaleVec->vec128, (vec_uint4)spu_maskb(0xf000) ); + result->col1.vec128 = spu_sel( zero, scaleVec->vec128, (vec_uint4)spu_maskb(0x0f00) ); + result->col2.vec128 = spu_sel( zero, scaleVec->vec128, (vec_uint4)spu_maskb(0x00f0) ); +} + +static inline void vmathM3AppendScale( VmathMatrix3 *result, const VmathMatrix3 *mat, const VmathVector3 *scaleVec ) +{ + vmathV3ScalarMul( &result->col0, &mat->col0, vmathV3GetX( scaleVec ) ); + vmathV3ScalarMul( &result->col1, &mat->col1, vmathV3GetY( scaleVec ) ); + vmathV3ScalarMul( &result->col2, &mat->col2, vmathV3GetZ( scaleVec ) ); +} + +static inline void vmathM3PrependScale( VmathMatrix3 *result, const VmathVector3 *scaleVec, const VmathMatrix3 *mat ) +{ + vmathV3MulPerElem( &result->col0, &mat->col0, scaleVec ); + vmathV3MulPerElem( &result->col1, &mat->col1, scaleVec ); + vmathV3MulPerElem( &result->col2, &mat->col2, scaleVec ); +} + +static inline void vmathM3Select( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1, unsigned int select1 ) +{ + vmathV3Select( &result->col0, &mat0->col0, &mat1->col0, select1 ); + vmathV3Select( &result->col1, &mat0->col1, &mat1->col1, select1 ); + vmathV3Select( &result->col2, &mat0->col2, &mat1->col2, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathM3Print( const VmathMatrix3 *mat ) +{ + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2; + vmathM3GetRow( &tmpV3_0, mat, 0 ); + vmathV3Print( &tmpV3_0 ); + vmathM3GetRow( &tmpV3_1, mat, 1 ); + vmathV3Print( &tmpV3_1 ); + vmathM3GetRow( &tmpV3_2, mat, 2 ); + vmathV3Print( &tmpV3_2 ); +} + +static inline void vmathM3Prints( const VmathMatrix3 *mat, const char *name ) +{ + printf("%s:\n", name); + vmathM3Print( mat ); +} + +#endif + +static inline void vmathM4Copy( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Copy( &result->col0, &mat->col0 ); + vmathV4Copy( &result->col1, &mat->col1 ); + vmathV4Copy( &result->col2, &mat->col2 ); + vmathV4Copy( &result->col3, &mat->col3 ); +} + +static inline void vmathM4MakeFromScalar( VmathMatrix4 *result, float scalar ) +{ + vmathV4MakeFromScalar( &result->col0, scalar ); + vmathV4MakeFromScalar( &result->col1, scalar ); + vmathV4MakeFromScalar( &result->col2, scalar ); + vmathV4MakeFromScalar( &result->col3, scalar ); +} + +static inline void vmathM4MakeFromT3( VmathMatrix4 *result, const VmathTransform3 *mat ) +{ + vmathV4MakeFromV3Scalar( &result->col0, &mat->col0, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col1, &mat->col1, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col2, &mat->col2, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col3, &mat->col3, 1.0f ); +} + +static inline void vmathM4MakeFromCols( VmathMatrix4 *result, const VmathVector4 *_col0, const VmathVector4 *_col1, const VmathVector4 *_col2, const VmathVector4 *_col3 ) +{ + vmathV4Copy( &result->col0, _col0 ); + vmathV4Copy( &result->col1, _col1 ); + vmathV4Copy( &result->col2, _col2 ); + vmathV4Copy( &result->col3, _col3 ); +} + +static inline void vmathM4MakeFromM3V3( VmathMatrix4 *result, const VmathMatrix3 *mat, const VmathVector3 *translateVec ) +{ + vmathV4MakeFromV3Scalar( &result->col0, &mat->col0, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col1, &mat->col1, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col2, &mat->col2, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col3, translateVec, 1.0f ); +} + +static inline void vmathM4MakeFromQV3( VmathMatrix4 *result, const VmathQuat *unitQuat, const VmathVector3 *translateVec ) +{ + VmathMatrix3 mat; + vmathM3MakeFromQ( &mat, unitQuat ); + vmathV4MakeFromV3Scalar( &result->col0, &mat.col0, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col1, &mat.col1, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col2, &mat.col2, 0.0f ); + vmathV4MakeFromV3Scalar( &result->col3, translateVec, 1.0f ); +} + +static inline void vmathM4SetCol0( VmathMatrix4 *result, const VmathVector4 *_col0 ) +{ + vmathV4Copy( &result->col0, _col0 ); +} + +static inline void vmathM4SetCol1( VmathMatrix4 *result, const VmathVector4 *_col1 ) +{ + vmathV4Copy( &result->col1, _col1 ); +} + +static inline void vmathM4SetCol2( VmathMatrix4 *result, const VmathVector4 *_col2 ) +{ + vmathV4Copy( &result->col2, _col2 ); +} + +static inline void vmathM4SetCol3( VmathMatrix4 *result, const VmathVector4 *_col3 ) +{ + vmathV4Copy( &result->col3, _col3 ); +} + +static inline void vmathM4SetCol( VmathMatrix4 *result, int col, const VmathVector4 *vec ) +{ + vmathV4Copy( (&result->col0 + col), vec ); +} + +static inline void vmathM4SetRow( VmathMatrix4 *result, int row, const VmathVector4 *vec ) +{ + vmathV4SetElem( &result->col0, row, vmathV4GetElem( vec, 0 ) ); + vmathV4SetElem( &result->col1, row, vmathV4GetElem( vec, 1 ) ); + vmathV4SetElem( &result->col2, row, vmathV4GetElem( vec, 2 ) ); + vmathV4SetElem( &result->col3, row, vmathV4GetElem( vec, 3 ) ); +} + +static inline void vmathM4SetElem( VmathMatrix4 *result, int col, int row, float val ) +{ + VmathVector4 tmpV3_0; + vmathM4GetCol( &tmpV3_0, result, col ); + vmathV4SetElem( &tmpV3_0, row, val ); + vmathM4SetCol( result, col, &tmpV3_0 ); +} + +static inline float vmathM4GetElem( const VmathMatrix4 *mat, int col, int row ) +{ + VmathVector4 tmpV4_0; + vmathM4GetCol( &tmpV4_0, mat, col ); + return vmathV4GetElem( &tmpV4_0, row ); +} + +static inline void vmathM4GetCol0( VmathVector4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Copy( result, &mat->col0 ); +} + +static inline void vmathM4GetCol1( VmathVector4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Copy( result, &mat->col1 ); +} + +static inline void vmathM4GetCol2( VmathVector4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Copy( result, &mat->col2 ); +} + +static inline void vmathM4GetCol3( VmathVector4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Copy( result, &mat->col3 ); +} + +static inline void vmathM4GetCol( VmathVector4 *result, const VmathMatrix4 *mat, int col ) +{ + vmathV4Copy( result, (&mat->col0 + col) ); +} + +static inline void vmathM4GetRow( VmathVector4 *result, const VmathMatrix4 *mat, int row ) +{ + vmathV4MakeFromElems( result, vmathV4GetElem( &mat->col0, row ), vmathV4GetElem( &mat->col1, row ), vmathV4GetElem( &mat->col2, row ), vmathV4GetElem( &mat->col3, row ) ); +} + +static inline void vmathM4Transpose( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3, res0, res1, res2, res3; + tmp0 = spu_shuffle( mat->col0.vec128, mat->col2.vec128, _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( mat->col1.vec128, mat->col3.vec128, _VECTORMATH_SHUF_XAYB ); + tmp2 = spu_shuffle( mat->col0.vec128, mat->col2.vec128, _VECTORMATH_SHUF_ZCWD ); + tmp3 = spu_shuffle( mat->col1.vec128, mat->col3.vec128, _VECTORMATH_SHUF_ZCWD ); + res0 = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_XAYB ); + res1 = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_ZCWD ); + res2 = spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_XAYB ); + res3 = spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_ZCWD ); + result->col0.vec128 = res0; + result->col1.vec128 = res1; + result->col2.vec128 = res2; + result->col3.vec128 = res3; +} + +static inline void vmathM4Inverse( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + vec_float4 in0, in1, in2, in3; + vec_float4 tmp0, tmp1, tmp2, tmp3; + vec_float4 cof0, cof1, cof2, cof3; + vec_float4 t0, t1, t2, t3; + vec_float4 t01, t02, t03, t12, t23; + vec_float4 t1r, t2r; + vec_float4 t01r, t02r, t03r, t12r, t23r; + vec_float4 t1r3, t1r3r; + vec_float4 det, det1, det2, det3, invdet; + in0 = mat->col0.vec128; + in1 = mat->col1.vec128; + in2 = mat->col2.vec128; + in3 = mat->col3.vec128; + /* Perform transform of the input matrix of the form: + * A B C D + * E F G H + * I J K L + * M N O P + * + * The pseudo transpose of the input matrix is trans: + * A E I M + * J N B F + * C G K O + * L P D H + */ + tmp0 = spu_shuffle(in0, in1, _VECTORMATH_SHUF_XAZC); /* A E C G */ + tmp1 = spu_shuffle(in2, in3, _VECTORMATH_SHUF_XAZC); /* I M K O */ + tmp2 = spu_shuffle(in0, in1, _VECTORMATH_SHUF_YBWD); /* B F D H */ + tmp3 = spu_shuffle(in2, in3, _VECTORMATH_SHUF_YBWD); /* J N L P */ + t0 = spu_shuffle(tmp0, tmp1, _VECTORMATH_SHUF_XYAB); /* A E I M */ + t1 = spu_shuffle(tmp3, tmp2, _VECTORMATH_SHUF_XYAB); /* J N B F */ + t2 = spu_shuffle(tmp0, tmp1, _VECTORMATH_SHUF_ZWCD); /* C G K O */ + t3 = spu_shuffle(tmp3, tmp2, _VECTORMATH_SHUF_ZWCD); /* L P D H */ + /* Generate a cofactor matrix. The computed cofactors reside in + * cof0, cof1, cof2, cof3. + */ + t23 = spu_mul(t2, t3); /* CL GP KD OH */ + t23 = spu_shuffle(t23, t23, _VECTORMATH_SHUF_YXWZ); /* GP CL OH KD */ + cof0 = spu_mul(t1, t23); /* JGP NCL BOH FKD */ + cof1 = spu_mul(t0, t23); /* AGP ECL IOH MKD */ + t23r = spu_rlqwbyte(t23, 8); /* OH KD GP CL */ + cof0 = spu_msub(t1, t23r, cof0); /* JOH NKD BGP FCL - cof0 */ + cof1 = spu_msub(t0, t23r, cof1); /* AOH EKD IGP MCL - cof1 */ + cof1 = spu_rlqwbyte(cof1, 8); /* IGP MCL AOH EKD - IOH MKD AGP ECL */ + + t12 = spu_mul(t1, t2); /* JC NG BK FO */ + t12 = spu_shuffle(t12, t12, _VECTORMATH_SHUF_YXWZ); /* NG JC FO BK */ + cof0 = spu_madd(t3, t12, cof0); /* LNG PJC DFO HBK + cof0 */ + cof3 = spu_mul(t0, t12); /* ANG EJC IFO MBK */ + t12r = spu_rlqwbyte(t12, 8); /* FO BK NG JC */ + cof0 = spu_nmsub(t3, t12r, cof0); /* cof0 - LFO PBK DNG HJC */ + cof3 = spu_msub(t0, t12r, cof3); /* AFO EBK ING MJC - cof3 */ + cof3 = spu_rlqwbyte(cof3, 8); /* ING MJC AFO EBK - IFO MBK ANG EJC */ + t1r = spu_rlqwbyte(t1, 8); /* B F J N */ + t2r = spu_rlqwbyte(t2, 8); /* K O C G */ + t1r3 = spu_mul(t1r, t3); /* BL FP JD NH */ + t1r3 = spu_shuffle(t1r3, t1r3, _VECTORMATH_SHUF_YXWZ); /* FP BL NH JD */ + cof0 = spu_madd(t2r, t1r3, cof0); /* KFP OBL CNH GJD + cof0 */ + cof2 = spu_mul(t0, t1r3); /* AFP EBL INH MJD */ + t1r3r = spu_rlqwbyte(t1r3, 8); /* NH JD FP BL */ + cof0 = spu_nmsub(t2r, t1r3r, cof0); /* cof0 - KNH OJD CFP GBL */ + cof2 = spu_msub(t0, t1r3r, cof2); /* ANH EJD IFP MBL - cof2 */ + cof2 = spu_rlqwbyte(cof2, 8); /* IFP MBL ANH EJD - INH MJD AFP EBL */ + t01 = spu_mul(t0, t1); /* AJ EN IB MF */ + t01 = spu_shuffle(t01, t01, _VECTORMATH_SHUF_YXWZ); /* EN AJ MF IB */ + cof2 = spu_madd(t3, t01, cof2); /* LEN PAJ DMF HIB + cof2 */ + cof3 = spu_msub(t2r, t01, cof3); /* KEN OAJ CMF GIB - cof3 */ + t01r = spu_rlqwbyte(t01, 8); /* MF IB EN AJ */ + cof2 = spu_msub(t3, t01r, cof2); /* LMF PIB DEN HAJ - cof2 */ + cof3 = spu_nmsub(t2r, t01r, cof3); /* cof3 - KMF OIB CEN GAJ */ + t03 = spu_mul(t0, t3); /* AL EP ID MH */ + t03 = spu_shuffle(t03, t03, _VECTORMATH_SHUF_YXWZ); /* EP AL MH ID */ + cof1 = spu_nmsub(t2r, t03, cof1); /* cof1 - KEP OAL CMH GID */ + cof2 = spu_madd(t1, t03, cof2); /* JEP NAL BMH FID + cof2 */ + t03r = spu_rlqwbyte(t03, 8); /* MH ID EP AL */ + cof1 = spu_madd(t2r, t03r, cof1); /* KMH OID CEP GAL + cof1 */ + cof2 = spu_nmsub(t1, t03r, cof2); /* cof2 - JMH NID BEP FAL */ + t02 = spu_mul(t0, t2r); /* AK EO IC MG */ + t02 = spu_shuffle(t02, t02, _VECTORMATH_SHUF_YXWZ); /* E0 AK MG IC */ + cof1 = spu_madd(t3, t02, cof1); /* LEO PAK DMG HIC + cof1 */ + cof3 = spu_nmsub(t1, t02, cof3); /* cof3 - JEO NAK BMG FIC */ + t02r = spu_rlqwbyte(t02, 8); /* MG IC EO AK */ + cof1 = spu_nmsub(t3, t02r, cof1); /* cof1 - LMG PIC DEO HAK */ + cof3 = spu_madd(t1, t02r, cof3); /* JMG NIC BEO FAK + cof3 */ + /* Compute the determinant of the matrix + * + * det = sum_across(t0 * cof0); + * + * We perform a sum across the entire vector so that + * we don't have to splat the result when multiplying the + * cofactors by the inverse of the determinant. + */ + det = spu_mul(t0, cof0); + det1 = spu_rlqwbyte(det, 4); + det2 = spu_rlqwbyte(det, 8); + det3 = spu_rlqwbyte(det, 12); + det = spu_add(det, det1); + det2 = spu_add(det2, det3); + det = spu_add(det, det2); + /* Compute the reciprocal of the determinant. + */ + invdet = recipf4(det); + /* Multiply the cofactors by the reciprocal of the determinant. + */ + result->col0.vec128 = spu_mul(cof0, invdet); + result->col1.vec128 = spu_mul(cof1, invdet); + result->col2.vec128 = spu_mul(cof2, invdet); + result->col3.vec128 = spu_mul(cof3, invdet); +} + +static inline void vmathM4AffineInverse( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + VmathTransform3 affineMat, tmpT3_0; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + vmathV4GetXYZ( &tmpV3_0, &mat->col0 ); + vmathT3SetCol0( &affineMat, &tmpV3_0 ); + vmathV4GetXYZ( &tmpV3_1, &mat->col1 ); + vmathT3SetCol1( &affineMat, &tmpV3_1 ); + vmathV4GetXYZ( &tmpV3_2, &mat->col2 ); + vmathT3SetCol2( &affineMat, &tmpV3_2 ); + vmathV4GetXYZ( &tmpV3_3, &mat->col3 ); + vmathT3SetCol3( &affineMat, &tmpV3_3 ); + vmathT3Inverse( &tmpT3_0, &affineMat ); + vmathM4MakeFromT3( result, &tmpT3_0 ); +} + +static inline void vmathM4OrthoInverse( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + VmathTransform3 affineMat, tmpT3_0; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + vmathV4GetXYZ( &tmpV3_0, &mat->col0 ); + vmathT3SetCol0( &affineMat, &tmpV3_0 ); + vmathV4GetXYZ( &tmpV3_1, &mat->col1 ); + vmathT3SetCol1( &affineMat, &tmpV3_1 ); + vmathV4GetXYZ( &tmpV3_2, &mat->col2 ); + vmathT3SetCol2( &affineMat, &tmpV3_2 ); + vmathV4GetXYZ( &tmpV3_3, &mat->col3 ); + vmathT3SetCol3( &affineMat, &tmpV3_3 ); + vmathT3OrthoInverse( &tmpT3_0, &affineMat ); + vmathM4MakeFromT3( result, &tmpT3_0 ); +} + +static inline float vmathM4Determinant( const VmathMatrix4 *mat ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + vec_float4 in0, in1, in2, in3; + vec_float4 tmp0, tmp1, tmp2, tmp3; + vec_float4 cof0; + vec_float4 t0, t1, t2, t3; + vec_float4 t12, t23; + vec_float4 t1r, t2r; + vec_float4 t12r, t23r; + vec_float4 t1r3, t1r3r; + in0 = mat->col0.vec128; + in1 = mat->col1.vec128; + in2 = mat->col2.vec128; + in3 = mat->col3.vec128; + /* Perform transform of the input matrix of the form: + * A B C D + * E F G H + * I J K L + * M N O P + * + * The pseudo transpose of the input matrix is trans: + * A E I M + * J N B F + * C G K O + * L P D H + */ + tmp0 = spu_shuffle(in0, in1, _VECTORMATH_SHUF_XAZC); /* A E C G */ + tmp1 = spu_shuffle(in2, in3, _VECTORMATH_SHUF_XAZC); /* I M K O */ + tmp2 = spu_shuffle(in0, in1, _VECTORMATH_SHUF_YBWD); /* B F D H */ + tmp3 = spu_shuffle(in2, in3, _VECTORMATH_SHUF_YBWD); /* J N L P */ + t0 = spu_shuffle(tmp0, tmp1, _VECTORMATH_SHUF_XYAB); /* A E I M */ + t1 = spu_shuffle(tmp3, tmp2, _VECTORMATH_SHUF_XYAB); /* J N B F */ + t2 = spu_shuffle(tmp0, tmp1, _VECTORMATH_SHUF_ZWCD); /* C G K O */ + t3 = spu_shuffle(tmp3, tmp2, _VECTORMATH_SHUF_ZWCD); /* L P D H */ + /* Generate a cofactor matrix. The computed cofactors reside in + * cof0, cof1, cof2, cof3. + */ + t23 = spu_mul(t2, t3); /* CL GP KD OH */ + t23 = spu_shuffle(t23, t23, _VECTORMATH_SHUF_YXWZ); /* GP CL OH KD */ + cof0 = spu_mul(t1, t23); /* JGP NCL BOH FKD */ + t23r = spu_rlqwbyte(t23, 8); /* OH KD GP CL */ + cof0 = spu_msub(t1, t23r, cof0); /* JOH NKD BGP FCL - cof0 */ + + t12 = spu_mul(t1, t2); /* JC NG BK FO */ + t12 = spu_shuffle(t12, t12, _VECTORMATH_SHUF_YXWZ); /* NG JC FO BK */ + cof0 = spu_madd(t3, t12, cof0); /* LNG PJC DFO HBK + cof0 */ + t12r = spu_rlqwbyte(t12, 8); /* FO BK NG JC */ + cof0 = spu_nmsub(t3, t12r, cof0); /* cof0 - LFO PBK DNG HJC */ + t1r = spu_rlqwbyte(t1, 8); /* B F J N */ + t2r = spu_rlqwbyte(t2, 8); /* K O C G */ + t1r3 = spu_mul(t1r, t3); /* BL FP JD NH */ + t1r3 = spu_shuffle(t1r3, t1r3, _VECTORMATH_SHUF_YXWZ); /* FP BL NH JD */ + cof0 = spu_madd(t2r, t1r3, cof0); /* KFP OBL CNH GJD + cof0 */ + t1r3r = spu_rlqwbyte(t1r3, 8); /* NH JD FP BL */ + cof0 = spu_nmsub(t2r, t1r3r, cof0); /* cof0 - KNH OJD CFP GBL */ + return spu_extract( _vmathVfDot4(t0,cof0), 0 ); +} + +static inline void vmathM4Add( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ) +{ + vmathV4Add( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV4Add( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV4Add( &result->col2, &mat0->col2, &mat1->col2 ); + vmathV4Add( &result->col3, &mat0->col3, &mat1->col3 ); +} + +static inline void vmathM4Sub( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ) +{ + vmathV4Sub( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV4Sub( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV4Sub( &result->col2, &mat0->col2, &mat1->col2 ); + vmathV4Sub( &result->col3, &mat0->col3, &mat1->col3 ); +} + +static inline void vmathM4Neg( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + vmathV4Neg( &result->col0, &mat->col0 ); + vmathV4Neg( &result->col1, &mat->col1 ); + vmathV4Neg( &result->col2, &mat->col2 ); + vmathV4Neg( &result->col3, &mat->col3 ); +} + +static inline void vmathM4AbsPerElem( VmathMatrix4 *result, const VmathMatrix4 *mat ) +{ + vmathV4AbsPerElem( &result->col0, &mat->col0 ); + vmathV4AbsPerElem( &result->col1, &mat->col1 ); + vmathV4AbsPerElem( &result->col2, &mat->col2 ); + vmathV4AbsPerElem( &result->col3, &mat->col3 ); +} + +static inline void vmathM4ScalarMul( VmathMatrix4 *result, const VmathMatrix4 *mat, float scalar ) +{ + vmathV4ScalarMul( &result->col0, &mat->col0, scalar ); + vmathV4ScalarMul( &result->col1, &mat->col1, scalar ); + vmathV4ScalarMul( &result->col2, &mat->col2, scalar ); + vmathV4ScalarMul( &result->col3, &mat->col3, scalar ); +} + +static inline void vmathM4MulV4( VmathVector4 *result, const VmathMatrix4 *mat, const VmathVector4 *vec ) +{ + vec_float4 tmp0, tmp1, res; + vec_float4 xxxx, yyyy, zzzz, wwww; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + vec_uchar16 shuffle_wwww = (vec_uchar16)spu_splats((int)0x0c0d0e0f); + xxxx = spu_shuffle( vec->vec128, vec->vec128, shuffle_xxxx ); + yyyy = spu_shuffle( vec->vec128, vec->vec128, shuffle_yyyy ); + zzzz = spu_shuffle( vec->vec128, vec->vec128, shuffle_zzzz ); + wwww = spu_shuffle( vec->vec128, vec->vec128, shuffle_wwww ); + tmp0 = spu_mul( mat->col0.vec128, xxxx ); + tmp1 = spu_mul( mat->col1.vec128, yyyy ); + tmp0 = spu_madd( mat->col2.vec128, zzzz, tmp0 ); + tmp1 = spu_madd( mat->col3.vec128, wwww, tmp1 ); + res = spu_add( tmp0, tmp1 ); + result->vec128 = res; +} + +static inline void vmathM4MulV3( VmathVector4 *result, const VmathMatrix4 *mat, const VmathVector3 *vec ) +{ + vec_float4 res; + vec_float4 xxxx, yyyy, zzzz; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + xxxx = spu_shuffle( vec->vec128, vec->vec128, shuffle_xxxx ); + yyyy = spu_shuffle( vec->vec128, vec->vec128, shuffle_yyyy ); + zzzz = spu_shuffle( vec->vec128, vec->vec128, shuffle_zzzz ); + res = spu_mul( mat->col0.vec128, xxxx ); + res = spu_madd( mat->col1.vec128, yyyy, res ); + res = spu_madd( mat->col2.vec128, zzzz, res ); + result->vec128 = res; +} + +static inline void vmathM4MulP3( VmathVector4 *result, const VmathMatrix4 *mat, const VmathPoint3 *pnt ) +{ + vec_float4 tmp0, tmp1, res; + vec_float4 xxxx, yyyy, zzzz; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + xxxx = spu_shuffle( pnt->vec128, pnt->vec128, shuffle_xxxx ); + yyyy = spu_shuffle( pnt->vec128, pnt->vec128, shuffle_yyyy ); + zzzz = spu_shuffle( pnt->vec128, pnt->vec128, shuffle_zzzz ); + tmp0 = spu_mul( mat->col0.vec128, xxxx ); + tmp1 = spu_mul( mat->col1.vec128, yyyy ); + tmp0 = spu_madd( mat->col2.vec128, zzzz, tmp0 ); + tmp1 = spu_add( mat->col3.vec128, tmp1 ); + res = spu_add( tmp0, tmp1 ); + result->vec128 = res; +} + +static inline void vmathM4Mul( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ) +{ + VmathMatrix4 tmpResult; + vmathM4MulV4( &tmpResult.col0, mat0, &mat1->col0 ); + vmathM4MulV4( &tmpResult.col1, mat0, &mat1->col1 ); + vmathM4MulV4( &tmpResult.col2, mat0, &mat1->col2 ); + vmathM4MulV4( &tmpResult.col3, mat0, &mat1->col3 ); + vmathM4Copy( result, &tmpResult ); +} + +static inline void vmathM4MulT3( VmathMatrix4 *result, const VmathMatrix4 *mat, const VmathTransform3 *tfrm1 ) +{ + VmathMatrix4 tmpResult; + VmathPoint3 tmpP3_0; + vmathM4MulV3( &tmpResult.col0, mat, &tfrm1->col0 ); + vmathM4MulV3( &tmpResult.col1, mat, &tfrm1->col1 ); + vmathM4MulV3( &tmpResult.col2, mat, &tfrm1->col2 ); + vmathP3MakeFromV3( &tmpP3_0, &tfrm1->col3 ); + vmathM4MulP3( &tmpResult.col3, mat, &tmpP3_0 ); + vmathM4Copy( result, &tmpResult ); +} + +static inline void vmathM4MulPerElem( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ) +{ + vmathV4MulPerElem( &result->col0, &mat0->col0, &mat1->col0 ); + vmathV4MulPerElem( &result->col1, &mat0->col1, &mat1->col1 ); + vmathV4MulPerElem( &result->col2, &mat0->col2, &mat1->col2 ); + vmathV4MulPerElem( &result->col3, &mat0->col3, &mat1->col3 ); +} + +static inline void vmathM4MakeIdentity( VmathMatrix4 *result ) +{ + vmathV4MakeXAxis( &result->col0 ); + vmathV4MakeYAxis( &result->col1 ); + vmathV4MakeZAxis( &result->col2 ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4SetUpper3x3( VmathMatrix4 *result, const VmathMatrix3 *mat3 ) +{ + vmathV4SetXYZ( &result->col0, &mat3->col0 ); + vmathV4SetXYZ( &result->col1, &mat3->col1 ); + vmathV4SetXYZ( &result->col2, &mat3->col2 ); +} + +static inline void vmathM4GetUpper3x3( VmathMatrix3 *result, const VmathMatrix4 *mat ) +{ + vmathV4GetXYZ( &result->col0, &mat->col0 ); + vmathV4GetXYZ( &result->col1, &mat->col1 ); + vmathV4GetXYZ( &result->col2, &mat->col2 ); +} + +static inline void vmathM4SetTranslation( VmathMatrix4 *result, const VmathVector3 *translateVec ) +{ + vmathV4SetXYZ( &result->col3, translateVec ); +} + +static inline void vmathM4GetTranslation( VmathVector3 *result, const VmathMatrix4 *mat ) +{ + vmathV4GetXYZ( result, &mat->col3 ); +} + +static inline void vmathM4MakeRotationX( VmathMatrix4 *result, float radians ) +{ + vec_float4 s, c, res1, res2; + vec_uint4 select_y, select_z; + vec_float4 zero; + select_y = (vec_uint4)spu_maskb(0x0f00); + select_z = (vec_uint4)spu_maskb(0x00f0); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res1 = spu_sel( zero, c, select_y ); + res1 = spu_sel( res1, s, select_z ); + res2 = spu_sel( zero, negatef4(s), select_y ); + res2 = spu_sel( res2, c, select_z ); + vmathV4MakeXAxis( &result->col0 ); + result->col1.vec128 = res1; + result->col2.vec128 = res2; + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4MakeRotationY( VmathMatrix4 *result, float radians ) +{ + vec_float4 s, c, res0, res2; + vec_uint4 select_x, select_z; + vec_float4 zero; + select_x = (vec_uint4)spu_maskb(0xf000); + select_z = (vec_uint4)spu_maskb(0x00f0); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res0 = spu_sel( zero, c, select_x ); + res0 = spu_sel( res0, negatef4(s), select_z ); + res2 = spu_sel( zero, s, select_x ); + res2 = spu_sel( res2, c, select_z ); + result->col0.vec128 = res0; + vmathV4MakeYAxis( &result->col1 ); + result->col2.vec128 = res2; + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4MakeRotationZ( VmathMatrix4 *result, float radians ) +{ + vec_float4 s, c, res0, res1; + vec_uint4 select_x, select_y; + vec_float4 zero; + select_x = (vec_uint4)spu_maskb(0xf000); + select_y = (vec_uint4)spu_maskb(0x0f00); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res0 = spu_sel( zero, c, select_x ); + res0 = spu_sel( res0, s, select_y ); + res1 = spu_sel( zero, negatef4(s), select_x ); + res1 = spu_sel( res1, c, select_y ); + result->col0.vec128 = res0; + result->col1.vec128 = res1; + vmathV4MakeZAxis( &result->col2 ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4MakeRotationZYX( VmathMatrix4 *result, const VmathVector3 *radiansXYZ ) +{ + vec_float4 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + angles = radiansXYZ->vec128; + angles = spu_insert( 0.0f, angles, 3 ); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = spu_shuffle( s, c, _VECTORMATH_SHUF_CZD0 ); + Z1 = spu_shuffle( c, negS, _VECTORMATH_SHUF_CZD0 ); + Y0 = spu_shuffle( negS, c, _VECTORMATH_SHUF_BBY0 ); + Y1 = spu_shuffle( c, s, _VECTORMATH_SHUF_BBY0 ); + X0 = spu_shuffle( s, s, shuffle_xxxx ); + X1 = spu_shuffle( c, c, shuffle_xxxx ); + tmp = spu_mul( Z0, Y1 ); + result->col0.vec128 = spu_mul( Z0, Y0 ); + result->col1.vec128 = spu_madd( Z1, X1, spu_mul( tmp, X0 ) ); + result->col2.vec128 = spu_nmsub( Z1, X0, spu_mul( tmp, X1 ) ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4MakeRotationAxis( VmathMatrix4 *result, float radians, const VmathVector3 *unitVec ) +{ + vec_float4 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2, zeroW; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + axis = unitVec->vec128; + sincosf4( spu_splats( radians ), &s, &c ); + xxxx = spu_shuffle( axis, axis, shuffle_xxxx ); + yyyy = spu_shuffle( axis, axis, shuffle_yyyy ); + zzzz = spu_shuffle( axis, axis, shuffle_zzzz ); + oneMinusC = spu_sub( spu_splats(1.0f), c ); + axisS = spu_mul( axis, s ); + negAxisS = negatef4( axisS ); + tmp0 = spu_shuffle( axisS, negAxisS, _VECTORMATH_SHUF_0ZB0 ); + tmp1 = spu_shuffle( axisS, negAxisS, _VECTORMATH_SHUF_C0X0 ); + tmp2 = spu_shuffle( axisS, negAxisS, _VECTORMATH_SHUF_YA00 ); + tmp0 = spu_sel( tmp0, c, (vec_uint4)spu_maskb(0xf000) ); + tmp1 = spu_sel( tmp1, c, (vec_uint4)spu_maskb(0x0f00) ); + tmp2 = spu_sel( tmp2, c, (vec_uint4)spu_maskb(0x00f0) ); + zeroW = (vec_float4)spu_maskb(0x000f); + axis = spu_andc( axis, zeroW ); + result->col0.vec128 = spu_madd( spu_mul( axis, xxxx ), oneMinusC, tmp0 ); + result->col1.vec128 = spu_madd( spu_mul( axis, yyyy ), oneMinusC, tmp1 ); + result->col2.vec128 = spu_madd( spu_mul( axis, zzzz ), oneMinusC, tmp2 ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4MakeRotationQ( VmathMatrix4 *result, const VmathQuat *unitQuat ) +{ + VmathTransform3 tmpT3_0; + vmathT3MakeRotationQ( &tmpT3_0, unitQuat ); + vmathM4MakeFromT3( result, &tmpT3_0 ); +} + +static inline void vmathM4MakeScale( VmathMatrix4 *result, const VmathVector3 *scaleVec ) +{ + vec_float4 zero = spu_splats(0.0f); + result->col0.vec128 = spu_sel( zero, scaleVec->vec128, (vec_uint4)spu_maskb(0xf000) ); + result->col1.vec128 = spu_sel( zero, scaleVec->vec128, (vec_uint4)spu_maskb(0x0f00) ); + result->col2.vec128 = spu_sel( zero, scaleVec->vec128, (vec_uint4)spu_maskb(0x00f0) ); + vmathV4MakeWAxis( &result->col3 ); +} + +static inline void vmathM4AppendScale( VmathMatrix4 *result, const VmathMatrix4 *mat, const VmathVector3 *scaleVec ) +{ + vmathV4ScalarMul( &result->col0, &mat->col0, vmathV3GetX( scaleVec ) ); + vmathV4ScalarMul( &result->col1, &mat->col1, vmathV3GetY( scaleVec ) ); + vmathV4ScalarMul( &result->col2, &mat->col2, vmathV3GetZ( scaleVec ) ); + vmathV4Copy( &result->col3, &mat->col3 ); +} + +static inline void vmathM4PrependScale( VmathMatrix4 *result, const VmathVector3 *scaleVec, const VmathMatrix4 *mat ) +{ + VmathVector4 scale4; + vmathV4MakeFromV3Scalar( &scale4, scaleVec, 1.0f ); + vmathV4MulPerElem( &result->col0, &mat->col0, &scale4 ); + vmathV4MulPerElem( &result->col1, &mat->col1, &scale4 ); + vmathV4MulPerElem( &result->col2, &mat->col2, &scale4 ); + vmathV4MulPerElem( &result->col3, &mat->col3, &scale4 ); +} + +static inline void vmathM4MakeTranslation( VmathMatrix4 *result, const VmathVector3 *translateVec ) +{ + vmathV4MakeXAxis( &result->col0 ); + vmathV4MakeYAxis( &result->col1 ); + vmathV4MakeZAxis( &result->col2 ); + vmathV4MakeFromV3Scalar( &result->col3, translateVec, 1.0f ); +} + +static inline void vmathM4MakeLookAt( VmathMatrix4 *result, const VmathPoint3 *eyePos, const VmathPoint3 *lookAtPos, const VmathVector3 *upVec ) +{ + VmathMatrix4 m4EyeFrame; + VmathVector3 v3X, v3Y, v3Z, tmpV3_0, tmpV3_1; + VmathVector4 tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3; + vmathV3Normalize( &v3Y, upVec ); + vmathP3Sub( &tmpV3_0, eyePos, lookAtPos ); + vmathV3Normalize( &v3Z, &tmpV3_0 ); + vmathV3Cross( &tmpV3_1, &v3Y, &v3Z ); + vmathV3Normalize( &v3X, &tmpV3_1 ); + vmathV3Cross( &v3Y, &v3Z, &v3X ); + vmathV4MakeFromV3( &tmpV4_0, &v3X ); + vmathV4MakeFromV3( &tmpV4_1, &v3Y ); + vmathV4MakeFromV3( &tmpV4_2, &v3Z ); + vmathV4MakeFromP3( &tmpV4_3, eyePos ); + vmathM4MakeFromCols( &m4EyeFrame, &tmpV4_0, &tmpV4_1, &tmpV4_2, &tmpV4_3 ); + vmathM4OrthoInverse( result, &m4EyeFrame ); +} + +static inline void vmathM4MakePerspective( VmathMatrix4 *result, float fovyRadians, float aspect, float zNear, float zFar ) +{ + float f, rangeInv; + vec_float4 zero, col0, col1, col2, col3; + f = tanf( _VECTORMATH_PI_OVER_2 - fovyRadians * 0.5f ); + rangeInv = 1.0f / ( zNear - zFar ); + zero = spu_splats(0.0f); + col0 = zero; + col1 = zero; + col2 = zero; + col3 = zero; + col0 = spu_insert( f / aspect, col0, 0 ); + col1 = spu_insert( f, col1, 1 ); + col2 = spu_insert( ( zNear + zFar ) * rangeInv, col2, 2 ); + col2 = spu_insert( -1.0f, col2, 3 ); + col3 = spu_insert( zNear * zFar * rangeInv * 2.0f, col3, 2 ); + result->col0.vec128 = col0; + result->col1.vec128 = col1; + result->col2.vec128 = col2; + result->col3.vec128 = col3; +} + +static inline void vmathM4MakeFrustum( VmathMatrix4 *result, float left, float right, float bottom, float top, float zNear, float zFar ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + vec_float4 lbf, rtn; + vec_float4 diff, sum, inv_diff; + vec_float4 diagonal, column, near2; + vec_float4 zero = spu_splats(0.0f); + lbf = spu_shuffle( spu_promote(left,0), spu_promote(zFar,0), _VECTORMATH_SHUF_XAYB ); + rtn = spu_shuffle( spu_promote(right,0), spu_promote(zNear,0), _VECTORMATH_SHUF_XAYB ); + lbf = spu_shuffle( lbf, spu_promote(bottom,0), _VECTORMATH_SHUF_XAYB ); + rtn = spu_shuffle( rtn, spu_promote(top,0), _VECTORMATH_SHUF_XAYB ); + diff = spu_sub( rtn, lbf ); + sum = spu_add( rtn, lbf ); + inv_diff = recipf4( diff ); + near2 = spu_splats( zNear ); + near2 = spu_add( near2, near2 ); + diagonal = spu_mul( near2, inv_diff ); + column = spu_mul( sum, inv_diff ); + result->col0.vec128 = spu_sel( zero, diagonal, (vec_uint4)spu_maskb(0xf000) ); + result->col1.vec128 = spu_sel( zero, diagonal, (vec_uint4)spu_maskb(0x0f00) ); + result->col2.vec128 = spu_sel( column, spu_splats(-1.0f), (vec_uint4)spu_maskb(0x000f) ); + result->col3.vec128 = spu_sel( zero, spu_mul( diagonal, spu_splats(zFar) ), (vec_uint4)spu_maskb(0x00f0) ); +} + +static inline void vmathM4MakeOrthographic( VmathMatrix4 *result, float left, float right, float bottom, float top, float zNear, float zFar ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + vec_float4 lbf, rtn; + vec_float4 diff, sum, inv_diff, neg_inv_diff; + vec_float4 diagonal, column; + vec_float4 zero = spu_splats(0.0f); + lbf = spu_shuffle( spu_promote(left,0), spu_promote(zFar,0), _VECTORMATH_SHUF_XAYB ); + rtn = spu_shuffle( spu_promote(right,0), spu_promote(zNear,0), _VECTORMATH_SHUF_XAYB ); + lbf = spu_shuffle( lbf, spu_promote(bottom,0), _VECTORMATH_SHUF_XAYB ); + rtn = spu_shuffle( rtn, spu_promote(top,0), _VECTORMATH_SHUF_XAYB ); + diff = spu_sub( rtn, lbf ); + sum = spu_add( rtn, lbf ); + inv_diff = recipf4( diff ); + neg_inv_diff = negatef4( inv_diff ); + diagonal = spu_add( inv_diff, inv_diff ); + column = spu_mul( sum, spu_sel( neg_inv_diff, inv_diff, (vec_uint4)spu_maskb(0x00f0) ) ); + result->col0.vec128 = spu_sel( zero, diagonal, (vec_uint4)spu_maskb(0xf000) ); + result->col1.vec128 = spu_sel( zero, diagonal, (vec_uint4)spu_maskb(0x0f00) ); + result->col2.vec128 = spu_sel( zero, diagonal, (vec_uint4)spu_maskb(0x00f0) ); + result->col3.vec128 = spu_sel( column, spu_splats(1.0f), (vec_uint4)spu_maskb(0x000f) ); +} + +static inline void vmathM4Select( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1, unsigned int select1 ) +{ + vmathV4Select( &result->col0, &mat0->col0, &mat1->col0, select1 ); + vmathV4Select( &result->col1, &mat0->col1, &mat1->col1, select1 ); + vmathV4Select( &result->col2, &mat0->col2, &mat1->col2, select1 ); + vmathV4Select( &result->col3, &mat0->col3, &mat1->col3, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathM4Print( const VmathMatrix4 *mat ) +{ + VmathVector4 tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3; + vmathM4GetRow( &tmpV4_0, mat, 0 ); + vmathV4Print( &tmpV4_0 ); + vmathM4GetRow( &tmpV4_1, mat, 1 ); + vmathV4Print( &tmpV4_1 ); + vmathM4GetRow( &tmpV4_2, mat, 2 ); + vmathV4Print( &tmpV4_2 ); + vmathM4GetRow( &tmpV4_3, mat, 3 ); + vmathV4Print( &tmpV4_3 ); +} + +static inline void vmathM4Prints( const VmathMatrix4 *mat, const char *name ) +{ + printf("%s:\n", name); + vmathM4Print( mat ); +} + +#endif + +static inline void vmathT3Copy( VmathTransform3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( &result->col0, &tfrm->col0 ); + vmathV3Copy( &result->col1, &tfrm->col1 ); + vmathV3Copy( &result->col2, &tfrm->col2 ); + vmathV3Copy( &result->col3, &tfrm->col3 ); +} + +static inline void vmathT3MakeFromScalar( VmathTransform3 *result, float scalar ) +{ + vmathV3MakeFromScalar( &result->col0, scalar ); + vmathV3MakeFromScalar( &result->col1, scalar ); + vmathV3MakeFromScalar( &result->col2, scalar ); + vmathV3MakeFromScalar( &result->col3, scalar ); +} + +static inline void vmathT3MakeFromCols( VmathTransform3 *result, const VmathVector3 *_col0, const VmathVector3 *_col1, const VmathVector3 *_col2, const VmathVector3 *_col3 ) +{ + vmathV3Copy( &result->col0, _col0 ); + vmathV3Copy( &result->col1, _col1 ); + vmathV3Copy( &result->col2, _col2 ); + vmathV3Copy( &result->col3, _col3 ); +} + +static inline void vmathT3MakeFromM3V3( VmathTransform3 *result, const VmathMatrix3 *tfrm, const VmathVector3 *translateVec ) +{ + vmathT3SetUpper3x3( result, tfrm ); + vmathT3SetTranslation( result, translateVec ); +} + +static inline void vmathT3MakeFromQV3( VmathTransform3 *result, const VmathQuat *unitQuat, const VmathVector3 *translateVec ) +{ + VmathMatrix3 tmpM3_0; + vmathM3MakeFromQ( &tmpM3_0, unitQuat ); + vmathT3SetUpper3x3( result, &tmpM3_0 ); + vmathT3SetTranslation( result, translateVec ); +} + +static inline void vmathT3SetCol0( VmathTransform3 *result, const VmathVector3 *_col0 ) +{ + vmathV3Copy( &result->col0, _col0 ); +} + +static inline void vmathT3SetCol1( VmathTransform3 *result, const VmathVector3 *_col1 ) +{ + vmathV3Copy( &result->col1, _col1 ); +} + +static inline void vmathT3SetCol2( VmathTransform3 *result, const VmathVector3 *_col2 ) +{ + vmathV3Copy( &result->col2, _col2 ); +} + +static inline void vmathT3SetCol3( VmathTransform3 *result, const VmathVector3 *_col3 ) +{ + vmathV3Copy( &result->col3, _col3 ); +} + +static inline void vmathT3SetCol( VmathTransform3 *result, int col, const VmathVector3 *vec ) +{ + vmathV3Copy( (&result->col0 + col), vec ); +} + +static inline void vmathT3SetRow( VmathTransform3 *result, int row, const VmathVector4 *vec ) +{ + vmathV3SetElem( &result->col0, row, vmathV4GetElem( vec, 0 ) ); + vmathV3SetElem( &result->col1, row, vmathV4GetElem( vec, 1 ) ); + vmathV3SetElem( &result->col2, row, vmathV4GetElem( vec, 2 ) ); + vmathV3SetElem( &result->col3, row, vmathV4GetElem( vec, 3 ) ); +} + +static inline void vmathT3SetElem( VmathTransform3 *result, int col, int row, float val ) +{ + VmathVector3 tmpV3_0; + vmathT3GetCol( &tmpV3_0, result, col ); + vmathV3SetElem( &tmpV3_0, row, val ); + vmathT3SetCol( result, col, &tmpV3_0 ); +} + +static inline float vmathT3GetElem( const VmathTransform3 *tfrm, int col, int row ) +{ + VmathVector3 tmpV3_0; + vmathT3GetCol( &tmpV3_0, tfrm, col ); + return vmathV3GetElem( &tmpV3_0, row ); +} + +static inline void vmathT3GetCol0( VmathVector3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( result, &tfrm->col0 ); +} + +static inline void vmathT3GetCol1( VmathVector3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( result, &tfrm->col1 ); +} + +static inline void vmathT3GetCol2( VmathVector3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( result, &tfrm->col2 ); +} + +static inline void vmathT3GetCol3( VmathVector3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( result, &tfrm->col3 ); +} + +static inline void vmathT3GetCol( VmathVector3 *result, const VmathTransform3 *tfrm, int col ) +{ + vmathV3Copy( result, (&tfrm->col0 + col) ); +} + +static inline void vmathT3GetRow( VmathVector4 *result, const VmathTransform3 *tfrm, int row ) +{ + vmathV4MakeFromElems( result, vmathV3GetElem( &tfrm->col0, row ), vmathV3GetElem( &tfrm->col1, row ), vmathV3GetElem( &tfrm->col2, row ), vmathV3GetElem( &tfrm->col3, row ) ); +} + +static inline void vmathT3Inverse( VmathTransform3 *result, const VmathTransform3 *tfrm ) +{ + vec_float4 inv0, inv1, inv2, inv3; + vec_float4 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet; + vec_float4 xxxx, yyyy, zzzz; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + tmp2 = _vmathVfCross( tfrm->col0.vec128, tfrm->col1.vec128 ); + tmp0 = _vmathVfCross( tfrm->col1.vec128, tfrm->col2.vec128 ); + tmp1 = _vmathVfCross( tfrm->col2.vec128, tfrm->col0.vec128 ); + inv3 = negatef4( tfrm->col3.vec128 ); + dot = _vmathVfDot3( tmp2, tfrm->col2.vec128 ); + dot = spu_shuffle( dot, dot, shuffle_xxxx ); + invdet = recipf4( dot ); + tmp3 = spu_shuffle( tmp0, tmp2, _VECTORMATH_SHUF_XAYB ); + tmp4 = spu_shuffle( tmp0, tmp2, _VECTORMATH_SHUF_ZCWD ); + inv0 = spu_shuffle( tmp3, tmp1, _VECTORMATH_SHUF_XAYB ); + xxxx = spu_shuffle( inv3, inv3, shuffle_xxxx ); + inv1 = spu_shuffle( tmp3, tmp1, _VECTORMATH_SHUF_ZBW0 ); + inv2 = spu_shuffle( tmp4, tmp1, _VECTORMATH_SHUF_XCY0 ); + yyyy = spu_shuffle( inv3, inv3, shuffle_yyyy ); + zzzz = spu_shuffle( inv3, inv3, shuffle_zzzz ); + inv3 = spu_mul( inv0, xxxx ); + inv3 = spu_madd( inv1, yyyy, inv3 ); + inv3 = spu_madd( inv2, zzzz, inv3 ); + inv0 = spu_mul( inv0, invdet ); + inv1 = spu_mul( inv1, invdet ); + inv2 = spu_mul( inv2, invdet ); + inv3 = spu_mul( inv3, invdet ); + result->col0.vec128 = inv0; + result->col1.vec128 = inv1; + result->col2.vec128 = inv2; + result->col3.vec128 = inv3; +} + +static inline void vmathT3OrthoInverse( VmathTransform3 *result, const VmathTransform3 *tfrm ) +{ + vec_float4 inv0, inv1, inv2, inv3; + vec_float4 tmp0, tmp1; + vec_float4 xxxx, yyyy, zzzz; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + tmp0 = spu_shuffle( tfrm->col0.vec128, tfrm->col2.vec128, _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( tfrm->col0.vec128, tfrm->col2.vec128, _VECTORMATH_SHUF_ZCWD ); + inv3 = negatef4( tfrm->col3.vec128 ); + inv0 = spu_shuffle( tmp0, tfrm->col1.vec128, _VECTORMATH_SHUF_XAYB ); + xxxx = spu_shuffle( inv3, inv3, shuffle_xxxx ); + inv1 = spu_shuffle( tmp0, tfrm->col1.vec128, _VECTORMATH_SHUF_ZBW0 ); + inv2 = spu_shuffle( tmp1, tfrm->col1.vec128, _VECTORMATH_SHUF_XCY0 ); + yyyy = spu_shuffle( inv3, inv3, shuffle_yyyy ); + zzzz = spu_shuffle( inv3, inv3, shuffle_zzzz ); + inv3 = spu_mul( inv0, xxxx ); + inv3 = spu_madd( inv1, yyyy, inv3 ); + inv3 = spu_madd( inv2, zzzz, inv3 ); + result->col0.vec128 = inv0; + result->col1.vec128 = inv1; + result->col2.vec128 = inv2; + result->col3.vec128 = inv3; +} + +static inline void vmathT3AbsPerElem( VmathTransform3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3AbsPerElem( &result->col0, &tfrm->col0 ); + vmathV3AbsPerElem( &result->col1, &tfrm->col1 ); + vmathV3AbsPerElem( &result->col2, &tfrm->col2 ); + vmathV3AbsPerElem( &result->col3, &tfrm->col3 ); +} + +static inline void vmathT3MulV3( VmathVector3 *result, const VmathTransform3 *tfrm, const VmathVector3 *vec ) +{ + vec_float4 res; + vec_float4 xxxx, yyyy, zzzz; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + xxxx = spu_shuffle( vec->vec128, vec->vec128, shuffle_xxxx ); + yyyy = spu_shuffle( vec->vec128, vec->vec128, shuffle_yyyy ); + zzzz = spu_shuffle( vec->vec128, vec->vec128, shuffle_zzzz ); + res = spu_mul( tfrm->col0.vec128, xxxx ); + res = spu_madd( tfrm->col1.vec128, yyyy, res ); + res = spu_madd( tfrm->col2.vec128, zzzz, res ); + result->vec128 = res; +} + +static inline void vmathT3MulP3( VmathPoint3 *result, const VmathTransform3 *tfrm, const VmathPoint3 *pnt ) +{ + vec_float4 tmp0, tmp1, res; + vec_float4 xxxx, yyyy, zzzz; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + xxxx = spu_shuffle( pnt->vec128, pnt->vec128, shuffle_xxxx ); + yyyy = spu_shuffle( pnt->vec128, pnt->vec128, shuffle_yyyy ); + zzzz = spu_shuffle( pnt->vec128, pnt->vec128, shuffle_zzzz ); + tmp0 = spu_mul( tfrm->col0.vec128, xxxx ); + tmp1 = spu_mul( tfrm->col1.vec128, yyyy ); + tmp0 = spu_madd( tfrm->col2.vec128, zzzz, tmp0 ); + tmp1 = spu_add( tfrm->col3.vec128, tmp1 ); + res = spu_add( tmp0, tmp1 ); + result->vec128 = res; +} + +static inline void vmathT3Mul( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1 ) +{ + VmathTransform3 tmpResult; + VmathPoint3 tmpP3_0, tmpP3_1; + vmathT3MulV3( &tmpResult.col0, tfrm0, &tfrm1->col0 ); + vmathT3MulV3( &tmpResult.col1, tfrm0, &tfrm1->col1 ); + vmathT3MulV3( &tmpResult.col2, tfrm0, &tfrm1->col2 ); + vmathP3MakeFromV3( &tmpP3_0, &tfrm1->col3 ); + vmathT3MulP3( &tmpP3_1, tfrm0, &tmpP3_0 ); + vmathV3MakeFromP3( &tmpResult.col3, &tmpP3_1 ); + vmathT3Copy( result, &tmpResult ); +} + +static inline void vmathT3MulPerElem( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1 ) +{ + vmathV3MulPerElem( &result->col0, &tfrm0->col0, &tfrm1->col0 ); + vmathV3MulPerElem( &result->col1, &tfrm0->col1, &tfrm1->col1 ); + vmathV3MulPerElem( &result->col2, &tfrm0->col2, &tfrm1->col2 ); + vmathV3MulPerElem( &result->col3, &tfrm0->col3, &tfrm1->col3 ); +} + +static inline void vmathT3MakeIdentity( VmathTransform3 *result ) +{ + vmathV3MakeXAxis( &result->col0 ); + vmathV3MakeYAxis( &result->col1 ); + vmathV3MakeZAxis( &result->col2 ); + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3SetUpper3x3( VmathTransform3 *result, const VmathMatrix3 *tfrm ) +{ + vmathV3Copy( &result->col0, &tfrm->col0 ); + vmathV3Copy( &result->col1, &tfrm->col1 ); + vmathV3Copy( &result->col2, &tfrm->col2 ); +} + +static inline void vmathT3GetUpper3x3( VmathMatrix3 *result, const VmathTransform3 *tfrm ) +{ + vmathM3MakeFromCols( result, &tfrm->col0, &tfrm->col1, &tfrm->col2 ); +} + +static inline void vmathT3SetTranslation( VmathTransform3 *result, const VmathVector3 *translateVec ) +{ + vmathV3Copy( &result->col3, translateVec ); +} + +static inline void vmathT3GetTranslation( VmathVector3 *result, const VmathTransform3 *tfrm ) +{ + vmathV3Copy( result, &tfrm->col3 ); +} + +static inline void vmathT3MakeRotationX( VmathTransform3 *result, float radians ) +{ + vec_float4 s, c, res1, res2; + vec_uint4 select_y, select_z; + vec_float4 zero; + select_y = (vec_uint4)spu_maskb(0x0f00); + select_z = (vec_uint4)spu_maskb(0x00f0); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res1 = spu_sel( zero, c, select_y ); + res1 = spu_sel( res1, s, select_z ); + res2 = spu_sel( zero, negatef4(s), select_y ); + res2 = spu_sel( res2, c, select_z ); + vmathV3MakeXAxis( &result->col0 ); + result->col1.vec128 = res1; + result->col2.vec128 = res2; + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3MakeRotationY( VmathTransform3 *result, float radians ) +{ + vec_float4 s, c, res0, res2; + vec_uint4 select_x, select_z; + vec_float4 zero; + select_x = (vec_uint4)spu_maskb(0xf000); + select_z = (vec_uint4)spu_maskb(0x00f0); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res0 = spu_sel( zero, c, select_x ); + res0 = spu_sel( res0, negatef4(s), select_z ); + res2 = spu_sel( zero, s, select_x ); + res2 = spu_sel( res2, c, select_z ); + result->col0.vec128 = res0; + vmathV3MakeYAxis( &result->col1 ); + result->col2.vec128 = res2; + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3MakeRotationZ( VmathTransform3 *result, float radians ) +{ + vec_float4 s, c, res0, res1; + vec_uint4 select_x, select_y; + vec_float4 zero; + select_x = (vec_uint4)spu_maskb(0xf000); + select_y = (vec_uint4)spu_maskb(0x0f00); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res0 = spu_sel( zero, c, select_x ); + res0 = spu_sel( res0, s, select_y ); + res1 = spu_sel( zero, negatef4(s), select_x ); + res1 = spu_sel( res1, c, select_y ); + result->col0.vec128 = res0; + result->col1.vec128 = res1; + vmathV3MakeZAxis( &result->col2 ); + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3MakeRotationZYX( VmathTransform3 *result, const VmathVector3 *radiansXYZ ) +{ + vec_float4 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + angles = radiansXYZ->vec128; + angles = spu_insert( 0.0f, angles, 3 ); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = spu_shuffle( s, c, _VECTORMATH_SHUF_CZD0 ); + Z1 = spu_shuffle( c, negS, _VECTORMATH_SHUF_CZD0 ); + Y0 = spu_shuffle( negS, c, _VECTORMATH_SHUF_BBY0 ); + Y1 = spu_shuffle( c, s, _VECTORMATH_SHUF_BBY0 ); + X0 = spu_shuffle( s, s, shuffle_xxxx ); + X1 = spu_shuffle( c, c, shuffle_xxxx ); + tmp = spu_mul( Z0, Y1 ); + result->col0.vec128 = spu_mul( Z0, Y0 ); + result->col1.vec128 = spu_madd( Z1, X1, spu_mul( tmp, X0 ) ); + result->col2.vec128 = spu_nmsub( Z1, X0, spu_mul( tmp, X1 ) ); + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3MakeRotationAxis( VmathTransform3 *result, float radians, const VmathVector3 *unitVec ) +{ + VmathMatrix3 tmpM3_0; + VmathVector3 tmpV3_0; + vmathM3MakeRotationAxis( &tmpM3_0, radians, unitVec ); + vmathV3MakeFromScalar( &tmpV3_0, 0.0f ); + vmathT3MakeFromM3V3( result, &tmpM3_0, &tmpV3_0 ); +} + +static inline void vmathT3MakeRotationQ( VmathTransform3 *result, const VmathQuat *unitQuat ) +{ + VmathMatrix3 tmpM3_0; + VmathVector3 tmpV3_0; + vmathM3MakeFromQ( &tmpM3_0, unitQuat ); + vmathV3MakeFromScalar( &tmpV3_0, 0.0f ); + vmathT3MakeFromM3V3( result, &tmpM3_0, &tmpV3_0 ); +} + +static inline void vmathT3MakeScale( VmathTransform3 *result, const VmathVector3 *scaleVec ) +{ + vec_float4 zero = spu_splats(0.0f); + result->col0.vec128 = spu_sel( zero, scaleVec->vec128, (vec_uint4)spu_maskb(0xf000) ); + result->col1.vec128 = spu_sel( zero, scaleVec->vec128, (vec_uint4)spu_maskb(0x0f00) ); + result->col2.vec128 = spu_sel( zero, scaleVec->vec128, (vec_uint4)spu_maskb(0x00f0) ); + vmathV3MakeFromScalar( &result->col3, 0.0f ); +} + +static inline void vmathT3AppendScale( VmathTransform3 *result, const VmathTransform3 *tfrm, const VmathVector3 *scaleVec ) +{ + vmathV3ScalarMul( &result->col0, &tfrm->col0, vmathV3GetX( scaleVec ) ); + vmathV3ScalarMul( &result->col1, &tfrm->col1, vmathV3GetY( scaleVec ) ); + vmathV3ScalarMul( &result->col2, &tfrm->col2, vmathV3GetZ( scaleVec ) ); + vmathV3Copy( &result->col3, &tfrm->col3 ); +} + +static inline void vmathT3PrependScale( VmathTransform3 *result, const VmathVector3 *scaleVec, const VmathTransform3 *tfrm ) +{ + vmathV3MulPerElem( &result->col0, &tfrm->col0, scaleVec ); + vmathV3MulPerElem( &result->col1, &tfrm->col1, scaleVec ); + vmathV3MulPerElem( &result->col2, &tfrm->col2, scaleVec ); + vmathV3MulPerElem( &result->col3, &tfrm->col3, scaleVec ); +} + +static inline void vmathT3MakeTranslation( VmathTransform3 *result, const VmathVector3 *translateVec ) +{ + vmathV3MakeXAxis( &result->col0 ); + vmathV3MakeYAxis( &result->col1 ); + vmathV3MakeZAxis( &result->col2 ); + vmathV3Copy( &result->col3, translateVec ); +} + +static inline void vmathT3Select( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1, unsigned int select1 ) +{ + vmathV3Select( &result->col0, &tfrm0->col0, &tfrm1->col0, select1 ); + vmathV3Select( &result->col1, &tfrm0->col1, &tfrm1->col1, select1 ); + vmathV3Select( &result->col2, &tfrm0->col2, &tfrm1->col2, select1 ); + vmathV3Select( &result->col3, &tfrm0->col3, &tfrm1->col3, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathT3Print( const VmathTransform3 *tfrm ) +{ + VmathVector4 tmpV4_0, tmpV4_1, tmpV4_2; + vmathT3GetRow( &tmpV4_0, tfrm, 0 ); + vmathV4Print( &tmpV4_0 ); + vmathT3GetRow( &tmpV4_1, tfrm, 1 ); + vmathV4Print( &tmpV4_1 ); + vmathT3GetRow( &tmpV4_2, tfrm, 2 ); + vmathV4Print( &tmpV4_2 ); +} + +static inline void vmathT3Prints( const VmathTransform3 *tfrm, const char *name ) +{ + printf("%s:\n", name); + vmathT3Print( tfrm ); +} + +#endif + +static inline void vmathQMakeFromM3( VmathQuat *result, const VmathMatrix3 *tfrm ) +{ + vec_float4 res; + vec_float4 col0, col1, col2; + vec_float4 xx_yy, xx_yy_zz_xx, yy_zz_xx_yy, zz_xx_yy_zz, diagSum, diagDiff; + vec_float4 zy_xz_yx, yz_zx_xy, sum, diff; + vec_float4 radicand, invSqrt, scale; + vec_float4 res0, res1, res2, res3; + vec_float4 xx, yy, zz; + vec_uint4 select_x = (vec_uint4)spu_maskb( 0xf000 ); + vec_uint4 select_y = (vec_uint4)spu_maskb( 0x0f00 ); + vec_uint4 select_z = (vec_uint4)spu_maskb( 0x00f0 ); + vec_uint4 select_w = (vec_uint4)spu_maskb( 0x000f ); + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((unsigned int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((unsigned int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((unsigned int)0x08090a0b); + vec_uchar16 shuffle_wwww = (vec_uchar16)spu_splats((unsigned int)0x0c0d0e0f); + + col0 = tfrm->col0.vec128; + col1 = tfrm->col1.vec128; + col2 = tfrm->col2.vec128; + + /* four cases: */ + /* trace > 0 */ + /* else */ + /* xx largest diagonal element */ + /* yy largest diagonal element */ + /* zz largest diagonal element */ + + /* compute quaternion for each case */ + + xx_yy = spu_sel( col0, col1, select_y ); + xx_yy_zz_xx = spu_shuffle( xx_yy, col2, _VECTORMATH_SHUF_XYCX ); + yy_zz_xx_yy = spu_shuffle( xx_yy, col2, _VECTORMATH_SHUF_YCXY ); + zz_xx_yy_zz = spu_shuffle( xx_yy, col2, _VECTORMATH_SHUF_CXYC ); + + diagSum = spu_add( spu_add( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); + diagDiff = spu_sub( spu_sub( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); + radicand = spu_add( spu_sel( diagDiff, diagSum, select_w ), spu_splats(1.0f) ); + invSqrt = rsqrtf4( radicand ); + + zy_xz_yx = spu_sel( col0, col1, select_z ); + zy_xz_yx = spu_shuffle( zy_xz_yx, col2, _VECTORMATH_SHUF_ZAY0 ); + yz_zx_xy = spu_sel( col0, col1, select_x ); + yz_zx_xy = spu_shuffle( yz_zx_xy, col2, _VECTORMATH_SHUF_BZX0 ); + + sum = spu_add( zy_xz_yx, yz_zx_xy ); + diff = spu_sub( zy_xz_yx, yz_zx_xy ); + + scale = spu_mul( invSqrt, spu_splats(0.5f) ); + res0 = spu_shuffle( sum, diff, _VECTORMATH_SHUF_0ZYA ); + res1 = spu_shuffle( sum, diff, _VECTORMATH_SHUF_Z0XB ); + res2 = spu_shuffle( sum, diff, _VECTORMATH_SHUF_YX0C ); + res3 = diff; + res0 = spu_sel( res0, radicand, select_x ); + res1 = spu_sel( res1, radicand, select_y ); + res2 = spu_sel( res2, radicand, select_z ); + res3 = spu_sel( res3, radicand, select_w ); + res0 = spu_mul( res0, spu_shuffle( scale, scale, shuffle_xxxx ) ); + res1 = spu_mul( res1, spu_shuffle( scale, scale, shuffle_yyyy ) ); + res2 = spu_mul( res2, spu_shuffle( scale, scale, shuffle_zzzz ) ); + res3 = spu_mul( res3, spu_shuffle( scale, scale, shuffle_wwww ) ); + + /* determine case and select answer */ + + xx = spu_shuffle( col0, col0, shuffle_xxxx ); + yy = spu_shuffle( col1, col1, shuffle_yyyy ); + zz = spu_shuffle( col2, col2, shuffle_zzzz ); + res = spu_sel( res0, res1, spu_cmpgt( yy, xx ) ); + res = spu_sel( res, res2, spu_and( spu_cmpgt( zz, xx ), spu_cmpgt( zz, yy ) ) ); + res = spu_sel( res, res3, spu_cmpgt( spu_shuffle( diagSum, diagSum, shuffle_xxxx ), spu_splats(0.0f) ) ); + result->vec128 = res; +} + +static inline void vmathV3Outer( VmathMatrix3 *result, const VmathVector3 *tfrm0, const VmathVector3 *tfrm1 ) +{ + vmathV3ScalarMul( &result->col0, tfrm0, vmathV3GetX( tfrm1 ) ); + vmathV3ScalarMul( &result->col1, tfrm0, vmathV3GetY( tfrm1 ) ); + vmathV3ScalarMul( &result->col2, tfrm0, vmathV3GetZ( tfrm1 ) ); +} + +static inline void vmathV4Outer( VmathMatrix4 *result, const VmathVector4 *tfrm0, const VmathVector4 *tfrm1 ) +{ + vmathV4ScalarMul( &result->col0, tfrm0, vmathV4GetX( tfrm1 ) ); + vmathV4ScalarMul( &result->col1, tfrm0, vmathV4GetY( tfrm1 ) ); + vmathV4ScalarMul( &result->col2, tfrm0, vmathV4GetZ( tfrm1 ) ); + vmathV4ScalarMul( &result->col3, tfrm0, vmathV4GetW( tfrm1 ) ); +} + +static inline void vmathV3RowMul( VmathVector3 *result, const VmathVector3 *vec, const VmathMatrix3 *mat ) +{ + vec_float4 tmp0, tmp1, mcol0, mcol1, mcol2, res; + vec_float4 xxxx, yyyy, zzzz; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + tmp0 = spu_shuffle( mat->col0.vec128, mat->col2.vec128, _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( mat->col0.vec128, mat->col2.vec128, _VECTORMATH_SHUF_ZCWD ); + xxxx = spu_shuffle( vec->vec128, vec->vec128, shuffle_xxxx ); + mcol0 = spu_shuffle( tmp0, mat->col1.vec128, _VECTORMATH_SHUF_XAYB ); + mcol1 = spu_shuffle( tmp0, mat->col1.vec128, _VECTORMATH_SHUF_ZBW0 ); + mcol2 = spu_shuffle( tmp1, mat->col1.vec128, _VECTORMATH_SHUF_XCY0 ); + yyyy = spu_shuffle( vec->vec128, vec->vec128, shuffle_yyyy ); + res = spu_mul( mcol0, xxxx ); + zzzz = spu_shuffle( vec->vec128, vec->vec128, shuffle_zzzz ); + res = spu_madd( mcol1, yyyy, res ); + res = spu_madd( mcol2, zzzz, res ); + result->vec128 = res; +} + +static inline void vmathV3CrossMatrix( VmathMatrix3 *result, const VmathVector3 *vec ) +{ + vec_float4 neg, res0, res1, res2; + neg = negatef4( vec->vec128 ); + res0 = spu_shuffle( vec->vec128, neg, _VECTORMATH_SHUF_0ZB0 ); + res1 = spu_shuffle( vec->vec128, neg, _VECTORMATH_SHUF_C0X0 ); + res2 = spu_shuffle( vec->vec128, neg, _VECTORMATH_SHUF_YA00 ); + result->col0.vec128 = res0; + result->col1.vec128 = res1; + result->col2.vec128 = res2; +} + +static inline void vmathV3CrossMatrixMul( VmathMatrix3 *result, const VmathVector3 *vec, const VmathMatrix3 *mat ) +{ + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2; + vmathV3Cross( &tmpV3_0, vec, &mat->col0 ); + vmathV3Cross( &tmpV3_1, vec, &mat->col1 ); + vmathV3Cross( &tmpV3_2, vec, &mat->col2 ); + vmathM3MakeFromCols( result, &tmpV3_0, &tmpV3_1, &tmpV3_2 ); +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/c/mat_aos_v.h b/Extras/vectormathlibrary/include/vectormath/spu/c/mat_aos_v.h new file mode 100644 index 0000000..986612e --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/c/mat_aos_v.h @@ -0,0 +1,1029 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_AOS_V_C_H +#define _VECTORMATH_MAT_AOS_V_C_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + * for shuffles, words are labeled [x,y,z,w] [a,b,c,d] + */ +#define _VECTORMATH_SHUF_XAYB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_ZCWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_ZBW0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_XCY0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_XYAB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_ZWCD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_0ZB0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_C0X0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_YA00 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_XAZC ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_C }) +#define _VECTORMATH_SHUF_YXWZ ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_Z }) +#define _VECTORMATH_SHUF_YBWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_XYCX ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_X }) +#define _VECTORMATH_SHUF_YCXY ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y }) +#define _VECTORMATH_SHUF_CXYC ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_C }) +#define _VECTORMATH_SHUF_ZAY0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_BZX0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_0ZYA ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_A }) +#define _VECTORMATH_SHUF_Z0XB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_YX0C ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_C }) +#define _VECTORMATH_SHUF_CZD0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_D, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_BBY0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_PI_OVER_2 1.570796327f + +/*----------------------------------------------------------------------------- + * Definitions + */ +static inline VmathMatrix3 vmathM3MakeFromScalar_V( float scalar ) +{ + VmathMatrix3 result; + vmathM3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathMatrix3 vmathM3MakeFromQ_V( VmathQuat unitQuat ) +{ + VmathMatrix3 result; + vmathM3MakeFromQ(&result, &unitQuat); + return result; +} + +static inline VmathMatrix3 vmathM3MakeFromCols_V( VmathVector3 _col0, VmathVector3 _col1, VmathVector3 _col2 ) +{ + VmathMatrix3 result; + vmathM3MakeFromCols(&result, &_col0, &_col1, &_col2); + return result; +} + +static inline void vmathM3SetCol0_V( VmathMatrix3 *result, VmathVector3 _col0 ) +{ + vmathM3SetCol0(result, &_col0); +} + +static inline void vmathM3SetCol1_V( VmathMatrix3 *result, VmathVector3 _col1 ) +{ + vmathM3SetCol1(result, &_col1); +} + +static inline void vmathM3SetCol2_V( VmathMatrix3 *result, VmathVector3 _col2 ) +{ + vmathM3SetCol2(result, &_col2); +} + +static inline void vmathM3SetCol_V( VmathMatrix3 *result, int col, VmathVector3 vec ) +{ + vmathM3SetCol(result, col, &vec); +} + +static inline void vmathM3SetRow_V( VmathMatrix3 *result, int row, VmathVector3 vec ) +{ + vmathM3SetRow(result, row, &vec); +} + +static inline void vmathM3SetElem_V( VmathMatrix3 *result, int col, int row, float val ) +{ + vmathM3SetElem(result, col, row, val); +} + +static inline float vmathM3GetElem_V( VmathMatrix3 mat, int col, int row ) +{ + return vmathM3GetElem(&mat, col, row); +} + +static inline VmathVector3 vmathM3GetCol0_V( VmathMatrix3 mat ) +{ + VmathVector3 result; + vmathM3GetCol0(&result, &mat); + return result; +} + +static inline VmathVector3 vmathM3GetCol1_V( VmathMatrix3 mat ) +{ + VmathVector3 result; + vmathM3GetCol1(&result, &mat); + return result; +} + +static inline VmathVector3 vmathM3GetCol2_V( VmathMatrix3 mat ) +{ + VmathVector3 result; + vmathM3GetCol2(&result, &mat); + return result; +} + +static inline VmathVector3 vmathM3GetCol_V( VmathMatrix3 mat, int col ) +{ + VmathVector3 result; + vmathM3GetCol(&result, &mat, col); + return result; +} + +static inline VmathVector3 vmathM3GetRow_V( VmathMatrix3 mat, int row ) +{ + VmathVector3 result; + vmathM3GetRow(&result, &mat, row); + return result; +} + +static inline VmathMatrix3 vmathM3Transpose_V( VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathM3Transpose(&result, &mat); + return result; +} + +static inline VmathMatrix3 vmathM3Inverse_V( VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathM3Inverse(&result, &mat); + return result; +} + +static inline float vmathM3Determinant_V( VmathMatrix3 mat ) +{ + return vmathM3Determinant(&mat); +} + +static inline VmathMatrix3 vmathM3Add_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ) +{ + VmathMatrix3 result; + vmathM3Add(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix3 vmathM3Sub_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ) +{ + VmathMatrix3 result; + vmathM3Sub(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix3 vmathM3Neg_V( VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathM3Neg(&result, &mat); + return result; +} + +static inline VmathMatrix3 vmathM3AbsPerElem_V( VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathM3AbsPerElem(&result, &mat); + return result; +} + +static inline VmathMatrix3 vmathM3ScalarMul_V( VmathMatrix3 mat, float scalar ) +{ + VmathMatrix3 result; + vmathM3ScalarMul(&result, &mat, scalar); + return result; +} + +static inline VmathVector3 vmathM3MulV3_V( VmathMatrix3 mat, VmathVector3 vec ) +{ + VmathVector3 result; + vmathM3MulV3(&result, &mat, &vec); + return result; +} + +static inline VmathMatrix3 vmathM3Mul_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ) +{ + VmathMatrix3 result; + vmathM3Mul(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix3 vmathM3MulPerElem_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ) +{ + VmathMatrix3 result; + vmathM3MulPerElem(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix3 vmathM3MakeIdentity_V( ) +{ + VmathMatrix3 result; + vmathM3MakeIdentity(&result); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationX_V( float radians ) +{ + VmathMatrix3 result; + vmathM3MakeRotationX(&result, radians); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationY_V( float radians ) +{ + VmathMatrix3 result; + vmathM3MakeRotationY(&result, radians); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationZ_V( float radians ) +{ + VmathMatrix3 result; + vmathM3MakeRotationZ(&result, radians); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationZYX_V( VmathVector3 radiansXYZ ) +{ + VmathMatrix3 result; + vmathM3MakeRotationZYX(&result, &radiansXYZ); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationAxis_V( float radians, VmathVector3 unitVec ) +{ + VmathMatrix3 result; + vmathM3MakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathMatrix3 vmathM3MakeRotationQ_V( VmathQuat unitQuat ) +{ + VmathMatrix3 result; + vmathM3MakeRotationQ(&result, &unitQuat); + return result; +} + +static inline VmathMatrix3 vmathM3MakeScale_V( VmathVector3 scaleVec ) +{ + VmathMatrix3 result; + vmathM3MakeScale(&result, &scaleVec); + return result; +} + +static inline VmathMatrix3 vmathM3AppendScale_V( VmathMatrix3 mat, VmathVector3 scaleVec ) +{ + VmathMatrix3 result; + vmathM3AppendScale(&result, &mat, &scaleVec); + return result; +} + +static inline VmathMatrix3 vmathM3PrependScale_V( VmathVector3 scaleVec, VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathM3PrependScale(&result, &scaleVec, &mat); + return result; +} + +static inline VmathMatrix3 vmathM3Select_V( VmathMatrix3 mat0, VmathMatrix3 mat1, unsigned int select1 ) +{ + VmathMatrix3 result; + vmathM3Select(&result, &mat0, &mat1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathM3Print_V( VmathMatrix3 mat ) +{ + vmathM3Print(&mat); +} + +static inline void vmathM3Prints_V( VmathMatrix3 mat, const char *name ) +{ + vmathM3Prints(&mat, name); +} + +#endif + +static inline VmathMatrix4 vmathM4MakeFromScalar_V( float scalar ) +{ + VmathMatrix4 result; + vmathM4MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathMatrix4 vmathM4MakeFromT3_V( VmathTransform3 mat ) +{ + VmathMatrix4 result; + vmathM4MakeFromT3(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4MakeFromCols_V( VmathVector4 _col0, VmathVector4 _col1, VmathVector4 _col2, VmathVector4 _col3 ) +{ + VmathMatrix4 result; + vmathM4MakeFromCols(&result, &_col0, &_col1, &_col2, &_col3); + return result; +} + +static inline VmathMatrix4 vmathM4MakeFromM3V3_V( VmathMatrix3 mat, VmathVector3 translateVec ) +{ + VmathMatrix4 result; + vmathM4MakeFromM3V3(&result, &mat, &translateVec); + return result; +} + +static inline VmathMatrix4 vmathM4MakeFromQV3_V( VmathQuat unitQuat, VmathVector3 translateVec ) +{ + VmathMatrix4 result; + vmathM4MakeFromQV3(&result, &unitQuat, &translateVec); + return result; +} + +static inline void vmathM4SetCol0_V( VmathMatrix4 *result, VmathVector4 _col0 ) +{ + vmathM4SetCol0(result, &_col0); +} + +static inline void vmathM4SetCol1_V( VmathMatrix4 *result, VmathVector4 _col1 ) +{ + vmathM4SetCol1(result, &_col1); +} + +static inline void vmathM4SetCol2_V( VmathMatrix4 *result, VmathVector4 _col2 ) +{ + vmathM4SetCol2(result, &_col2); +} + +static inline void vmathM4SetCol3_V( VmathMatrix4 *result, VmathVector4 _col3 ) +{ + vmathM4SetCol3(result, &_col3); +} + +static inline void vmathM4SetCol_V( VmathMatrix4 *result, int col, VmathVector4 vec ) +{ + vmathM4SetCol(result, col, &vec); +} + +static inline void vmathM4SetRow_V( VmathMatrix4 *result, int row, VmathVector4 vec ) +{ + vmathM4SetRow(result, row, &vec); +} + +static inline void vmathM4SetElem_V( VmathMatrix4 *result, int col, int row, float val ) +{ + vmathM4SetElem(result, col, row, val); +} + +static inline float vmathM4GetElem_V( VmathMatrix4 mat, int col, int row ) +{ + return vmathM4GetElem(&mat, col, row); +} + +static inline VmathVector4 vmathM4GetCol0_V( VmathMatrix4 mat ) +{ + VmathVector4 result; + vmathM4GetCol0(&result, &mat); + return result; +} + +static inline VmathVector4 vmathM4GetCol1_V( VmathMatrix4 mat ) +{ + VmathVector4 result; + vmathM4GetCol1(&result, &mat); + return result; +} + +static inline VmathVector4 vmathM4GetCol2_V( VmathMatrix4 mat ) +{ + VmathVector4 result; + vmathM4GetCol2(&result, &mat); + return result; +} + +static inline VmathVector4 vmathM4GetCol3_V( VmathMatrix4 mat ) +{ + VmathVector4 result; + vmathM4GetCol3(&result, &mat); + return result; +} + +static inline VmathVector4 vmathM4GetCol_V( VmathMatrix4 mat, int col ) +{ + VmathVector4 result; + vmathM4GetCol(&result, &mat, col); + return result; +} + +static inline VmathVector4 vmathM4GetRow_V( VmathMatrix4 mat, int row ) +{ + VmathVector4 result; + vmathM4GetRow(&result, &mat, row); + return result; +} + +static inline VmathMatrix4 vmathM4Transpose_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4Transpose(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4Inverse_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4Inverse(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4AffineInverse_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4AffineInverse(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4OrthoInverse_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4OrthoInverse(&result, &mat); + return result; +} + +static inline float vmathM4Determinant_V( VmathMatrix4 mat ) +{ + return vmathM4Determinant(&mat); +} + +static inline VmathMatrix4 vmathM4Add_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ) +{ + VmathMatrix4 result; + vmathM4Add(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix4 vmathM4Sub_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ) +{ + VmathMatrix4 result; + vmathM4Sub(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix4 vmathM4Neg_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4Neg(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4AbsPerElem_V( VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4AbsPerElem(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4ScalarMul_V( VmathMatrix4 mat, float scalar ) +{ + VmathMatrix4 result; + vmathM4ScalarMul(&result, &mat, scalar); + return result; +} + +static inline VmathVector4 vmathM4MulV4_V( VmathMatrix4 mat, VmathVector4 vec ) +{ + VmathVector4 result; + vmathM4MulV4(&result, &mat, &vec); + return result; +} + +static inline VmathVector4 vmathM4MulV3_V( VmathMatrix4 mat, VmathVector3 vec ) +{ + VmathVector4 result; + vmathM4MulV3(&result, &mat, &vec); + return result; +} + +static inline VmathVector4 vmathM4MulP3_V( VmathMatrix4 mat, VmathPoint3 pnt ) +{ + VmathVector4 result; + vmathM4MulP3(&result, &mat, &pnt); + return result; +} + +static inline VmathMatrix4 vmathM4Mul_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ) +{ + VmathMatrix4 result; + vmathM4Mul(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix4 vmathM4MulT3_V( VmathMatrix4 mat, VmathTransform3 tfrm1 ) +{ + VmathMatrix4 result; + vmathM4MulT3(&result, &mat, &tfrm1); + return result; +} + +static inline VmathMatrix4 vmathM4MulPerElem_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ) +{ + VmathMatrix4 result; + vmathM4MulPerElem(&result, &mat0, &mat1); + return result; +} + +static inline VmathMatrix4 vmathM4MakeIdentity_V( ) +{ + VmathMatrix4 result; + vmathM4MakeIdentity(&result); + return result; +} + +static inline void vmathM4SetUpper3x3_V( VmathMatrix4 *result, VmathMatrix3 mat3 ) +{ + vmathM4SetUpper3x3(result, &mat3); +} + +static inline VmathMatrix3 vmathM4GetUpper3x3_V( VmathMatrix4 mat ) +{ + VmathMatrix3 result; + vmathM4GetUpper3x3(&result, &mat); + return result; +} + +static inline void vmathM4SetTranslation_V( VmathMatrix4 *result, VmathVector3 translateVec ) +{ + vmathM4SetTranslation(result, &translateVec); +} + +static inline VmathVector3 vmathM4GetTranslation_V( VmathMatrix4 mat ) +{ + VmathVector3 result; + vmathM4GetTranslation(&result, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationX_V( float radians ) +{ + VmathMatrix4 result; + vmathM4MakeRotationX(&result, radians); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationY_V( float radians ) +{ + VmathMatrix4 result; + vmathM4MakeRotationY(&result, radians); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationZ_V( float radians ) +{ + VmathMatrix4 result; + vmathM4MakeRotationZ(&result, radians); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationZYX_V( VmathVector3 radiansXYZ ) +{ + VmathMatrix4 result; + vmathM4MakeRotationZYX(&result, &radiansXYZ); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationAxis_V( float radians, VmathVector3 unitVec ) +{ + VmathMatrix4 result; + vmathM4MakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathMatrix4 vmathM4MakeRotationQ_V( VmathQuat unitQuat ) +{ + VmathMatrix4 result; + vmathM4MakeRotationQ(&result, &unitQuat); + return result; +} + +static inline VmathMatrix4 vmathM4MakeScale_V( VmathVector3 scaleVec ) +{ + VmathMatrix4 result; + vmathM4MakeScale(&result, &scaleVec); + return result; +} + +static inline VmathMatrix4 vmathM4AppendScale_V( VmathMatrix4 mat, VmathVector3 scaleVec ) +{ + VmathMatrix4 result; + vmathM4AppendScale(&result, &mat, &scaleVec); + return result; +} + +static inline VmathMatrix4 vmathM4PrependScale_V( VmathVector3 scaleVec, VmathMatrix4 mat ) +{ + VmathMatrix4 result; + vmathM4PrependScale(&result, &scaleVec, &mat); + return result; +} + +static inline VmathMatrix4 vmathM4MakeTranslation_V( VmathVector3 translateVec ) +{ + VmathMatrix4 result; + vmathM4MakeTranslation(&result, &translateVec); + return result; +} + +static inline VmathMatrix4 vmathM4MakeLookAt_V( VmathPoint3 eyePos, VmathPoint3 lookAtPos, VmathVector3 upVec ) +{ + VmathMatrix4 result; + vmathM4MakeLookAt(&result, &eyePos, &lookAtPos, &upVec); + return result; +} + +static inline VmathMatrix4 vmathM4MakePerspective_V( float fovyRadians, float aspect, float zNear, float zFar ) +{ + VmathMatrix4 result; + vmathM4MakePerspective(&result, fovyRadians, aspect, zNear, zFar); + return result; +} + +static inline VmathMatrix4 vmathM4MakeFrustum_V( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + VmathMatrix4 result; + vmathM4MakeFrustum(&result, left, right, bottom, top, zNear, zFar); + return result; +} + +static inline VmathMatrix4 vmathM4MakeOrthographic_V( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + VmathMatrix4 result; + vmathM4MakeOrthographic(&result, left, right, bottom, top, zNear, zFar); + return result; +} + +static inline VmathMatrix4 vmathM4Select_V( VmathMatrix4 mat0, VmathMatrix4 mat1, unsigned int select1 ) +{ + VmathMatrix4 result; + vmathM4Select(&result, &mat0, &mat1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathM4Print_V( VmathMatrix4 mat ) +{ + vmathM4Print(&mat); +} + +static inline void vmathM4Prints_V( VmathMatrix4 mat, const char *name ) +{ + vmathM4Prints(&mat, name); +} + +#endif + +static inline VmathTransform3 vmathT3MakeFromScalar_V( float scalar ) +{ + VmathTransform3 result; + vmathT3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathTransform3 vmathT3MakeFromCols_V( VmathVector3 _col0, VmathVector3 _col1, VmathVector3 _col2, VmathVector3 _col3 ) +{ + VmathTransform3 result; + vmathT3MakeFromCols(&result, &_col0, &_col1, &_col2, &_col3); + return result; +} + +static inline VmathTransform3 vmathT3MakeFromM3V3_V( VmathMatrix3 tfrm, VmathVector3 translateVec ) +{ + VmathTransform3 result; + vmathT3MakeFromM3V3(&result, &tfrm, &translateVec); + return result; +} + +static inline VmathTransform3 vmathT3MakeFromQV3_V( VmathQuat unitQuat, VmathVector3 translateVec ) +{ + VmathTransform3 result; + vmathT3MakeFromQV3(&result, &unitQuat, &translateVec); + return result; +} + +static inline void vmathT3SetCol0_V( VmathTransform3 *result, VmathVector3 _col0 ) +{ + vmathT3SetCol0(result, &_col0); +} + +static inline void vmathT3SetCol1_V( VmathTransform3 *result, VmathVector3 _col1 ) +{ + vmathT3SetCol1(result, &_col1); +} + +static inline void vmathT3SetCol2_V( VmathTransform3 *result, VmathVector3 _col2 ) +{ + vmathT3SetCol2(result, &_col2); +} + +static inline void vmathT3SetCol3_V( VmathTransform3 *result, VmathVector3 _col3 ) +{ + vmathT3SetCol3(result, &_col3); +} + +static inline void vmathT3SetCol_V( VmathTransform3 *result, int col, VmathVector3 vec ) +{ + vmathT3SetCol(result, col, &vec); +} + +static inline void vmathT3SetRow_V( VmathTransform3 *result, int row, VmathVector4 vec ) +{ + vmathT3SetRow(result, row, &vec); +} + +static inline void vmathT3SetElem_V( VmathTransform3 *result, int col, int row, float val ) +{ + vmathT3SetElem(result, col, row, val); +} + +static inline float vmathT3GetElem_V( VmathTransform3 tfrm, int col, int row ) +{ + return vmathT3GetElem(&tfrm, col, row); +} + +static inline VmathVector3 vmathT3GetCol0_V( VmathTransform3 tfrm ) +{ + VmathVector3 result; + vmathT3GetCol0(&result, &tfrm); + return result; +} + +static inline VmathVector3 vmathT3GetCol1_V( VmathTransform3 tfrm ) +{ + VmathVector3 result; + vmathT3GetCol1(&result, &tfrm); + return result; +} + +static inline VmathVector3 vmathT3GetCol2_V( VmathTransform3 tfrm ) +{ + VmathVector3 result; + vmathT3GetCol2(&result, &tfrm); + return result; +} + +static inline VmathVector3 vmathT3GetCol3_V( VmathTransform3 tfrm ) +{ + VmathVector3 result; + vmathT3GetCol3(&result, &tfrm); + return result; +} + +static inline VmathVector3 vmathT3GetCol_V( VmathTransform3 tfrm, int col ) +{ + VmathVector3 result; + vmathT3GetCol(&result, &tfrm, col); + return result; +} + +static inline VmathVector4 vmathT3GetRow_V( VmathTransform3 tfrm, int row ) +{ + VmathVector4 result; + vmathT3GetRow(&result, &tfrm, row); + return result; +} + +static inline VmathTransform3 vmathT3Inverse_V( VmathTransform3 tfrm ) +{ + VmathTransform3 result; + vmathT3Inverse(&result, &tfrm); + return result; +} + +static inline VmathTransform3 vmathT3OrthoInverse_V( VmathTransform3 tfrm ) +{ + VmathTransform3 result; + vmathT3OrthoInverse(&result, &tfrm); + return result; +} + +static inline VmathTransform3 vmathT3AbsPerElem_V( VmathTransform3 tfrm ) +{ + VmathTransform3 result; + vmathT3AbsPerElem(&result, &tfrm); + return result; +} + +static inline VmathVector3 vmathT3MulV3_V( VmathTransform3 tfrm, VmathVector3 vec ) +{ + VmathVector3 result; + vmathT3MulV3(&result, &tfrm, &vec); + return result; +} + +static inline VmathPoint3 vmathT3MulP3_V( VmathTransform3 tfrm, VmathPoint3 pnt ) +{ + VmathPoint3 result; + vmathT3MulP3(&result, &tfrm, &pnt); + return result; +} + +static inline VmathTransform3 vmathT3Mul_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1 ) +{ + VmathTransform3 result; + vmathT3Mul(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathTransform3 vmathT3MulPerElem_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1 ) +{ + VmathTransform3 result; + vmathT3MulPerElem(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathTransform3 vmathT3MakeIdentity_V( ) +{ + VmathTransform3 result; + vmathT3MakeIdentity(&result); + return result; +} + +static inline void vmathT3SetUpper3x3_V( VmathTransform3 *result, VmathMatrix3 tfrm ) +{ + vmathT3SetUpper3x3(result, &tfrm); +} + +static inline VmathMatrix3 vmathT3GetUpper3x3_V( VmathTransform3 tfrm ) +{ + VmathMatrix3 result; + vmathT3GetUpper3x3(&result, &tfrm); + return result; +} + +static inline void vmathT3SetTranslation_V( VmathTransform3 *result, VmathVector3 translateVec ) +{ + vmathT3SetTranslation(result, &translateVec); +} + +static inline VmathVector3 vmathT3GetTranslation_V( VmathTransform3 tfrm ) +{ + VmathVector3 result; + vmathT3GetTranslation(&result, &tfrm); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationX_V( float radians ) +{ + VmathTransform3 result; + vmathT3MakeRotationX(&result, radians); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationY_V( float radians ) +{ + VmathTransform3 result; + vmathT3MakeRotationY(&result, radians); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationZ_V( float radians ) +{ + VmathTransform3 result; + vmathT3MakeRotationZ(&result, radians); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationZYX_V( VmathVector3 radiansXYZ ) +{ + VmathTransform3 result; + vmathT3MakeRotationZYX(&result, &radiansXYZ); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationAxis_V( float radians, VmathVector3 unitVec ) +{ + VmathTransform3 result; + vmathT3MakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathTransform3 vmathT3MakeRotationQ_V( VmathQuat unitQuat ) +{ + VmathTransform3 result; + vmathT3MakeRotationQ(&result, &unitQuat); + return result; +} + +static inline VmathTransform3 vmathT3MakeScale_V( VmathVector3 scaleVec ) +{ + VmathTransform3 result; + vmathT3MakeScale(&result, &scaleVec); + return result; +} + +static inline VmathTransform3 vmathT3AppendScale_V( VmathTransform3 tfrm, VmathVector3 scaleVec ) +{ + VmathTransform3 result; + vmathT3AppendScale(&result, &tfrm, &scaleVec); + return result; +} + +static inline VmathTransform3 vmathT3PrependScale_V( VmathVector3 scaleVec, VmathTransform3 tfrm ) +{ + VmathTransform3 result; + vmathT3PrependScale(&result, &scaleVec, &tfrm); + return result; +} + +static inline VmathTransform3 vmathT3MakeTranslation_V( VmathVector3 translateVec ) +{ + VmathTransform3 result; + vmathT3MakeTranslation(&result, &translateVec); + return result; +} + +static inline VmathTransform3 vmathT3Select_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1, unsigned int select1 ) +{ + VmathTransform3 result; + vmathT3Select(&result, &tfrm0, &tfrm1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathT3Print_V( VmathTransform3 tfrm ) +{ + vmathT3Print(&tfrm); +} + +static inline void vmathT3Prints_V( VmathTransform3 tfrm, const char *name ) +{ + vmathT3Prints(&tfrm, name); +} + +#endif + +static inline VmathQuat vmathQMakeFromM3_V( VmathMatrix3 tfrm ) +{ + VmathQuat result; + vmathQMakeFromM3(&result, &tfrm); + return result; +} + +static inline VmathMatrix3 vmathV3Outer_V( VmathVector3 tfrm0, VmathVector3 tfrm1 ) +{ + VmathMatrix3 result; + vmathV3Outer(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathMatrix4 vmathV4Outer_V( VmathVector4 tfrm0, VmathVector4 tfrm1 ) +{ + VmathMatrix4 result; + vmathV4Outer(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathVector3 vmathV3RowMul_V( VmathVector3 vec, VmathMatrix3 mat ) +{ + VmathVector3 result; + vmathV3RowMul(&result, &vec, &mat); + return result; +} + +static inline VmathMatrix3 vmathV3CrossMatrix_V( VmathVector3 vec ) +{ + VmathMatrix3 result; + vmathV3CrossMatrix(&result, &vec); + return result; +} + +static inline VmathMatrix3 vmathV3CrossMatrixMul_V( VmathVector3 vec, VmathMatrix3 mat ) +{ + VmathMatrix3 result; + vmathV3CrossMatrixMul(&result, &vec, &mat); + return result; +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/c/mat_soa.h b/Extras/vectormathlibrary/include/vectormath/spu/c/mat_soa.h new file mode 100644 index 0000000..c2c3734 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/c/mat_soa.h @@ -0,0 +1,1493 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_SOA_C_H +#define _VECTORMATH_MAT_SOA_C_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + */ +#define _VECTORMATH_PI_OVER_2 1.570796327f + +/*----------------------------------------------------------------------------- + * Definitions + */ +static inline void vmathSoaM3Copy( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ) +{ + vmathSoaV3Copy( &result->col0, &mat->col0 ); + vmathSoaV3Copy( &result->col1, &mat->col1 ); + vmathSoaV3Copy( &result->col2, &mat->col2 ); +} + +static inline void vmathSoaM3MakeFromScalar( VmathSoaMatrix3 *result, vec_float4 scalar ) +{ + vmathSoaV3MakeFromScalar( &result->col0, scalar ); + vmathSoaV3MakeFromScalar( &result->col1, scalar ); + vmathSoaV3MakeFromScalar( &result->col2, scalar ); +} + +static inline void vmathSoaM3MakeFromQ( VmathSoaMatrix3 *result, const VmathSoaQuat *unitQuat ) +{ + vec_float4 qx, qy, qz, qw, qx2, qy2, qz2, qxqx2, qyqy2, qzqz2, qxqy2, qyqz2, qzqw2, qxqz2, qyqw2, qxqw2; + qx = unitQuat->x; + qy = unitQuat->y; + qz = unitQuat->z; + qw = unitQuat->w; + qx2 = spu_add( qx, qx ); + qy2 = spu_add( qy, qy ); + qz2 = spu_add( qz, qz ); + qxqx2 = spu_mul( qx, qx2 ); + qxqy2 = spu_mul( qx, qy2 ); + qxqz2 = spu_mul( qx, qz2 ); + qxqw2 = spu_mul( qw, qx2 ); + qyqy2 = spu_mul( qy, qy2 ); + qyqz2 = spu_mul( qy, qz2 ); + qyqw2 = spu_mul( qw, qy2 ); + qzqz2 = spu_mul( qz, qz2 ); + qzqw2 = spu_mul( qw, qz2 ); + vmathSoaV3MakeFromElems( &result->col0, spu_sub( spu_sub( spu_splats(1.0f), qyqy2 ), qzqz2 ), spu_add( qxqy2, qzqw2 ), spu_sub( qxqz2, qyqw2 ) ); + vmathSoaV3MakeFromElems( &result->col1, spu_sub( qxqy2, qzqw2 ), spu_sub( spu_sub( spu_splats(1.0f), qxqx2 ), qzqz2 ), spu_add( qyqz2, qxqw2 ) ); + vmathSoaV3MakeFromElems( &result->col2, spu_add( qxqz2, qyqw2 ), spu_sub( qyqz2, qxqw2 ), spu_sub( spu_sub( spu_splats(1.0f), qxqx2 ), qyqy2 ) ); +} + +static inline void vmathSoaM3MakeFromCols( VmathSoaMatrix3 *result, const VmathSoaVector3 *_col0, const VmathSoaVector3 *_col1, const VmathSoaVector3 *_col2 ) +{ + vmathSoaV3Copy( &result->col0, _col0 ); + vmathSoaV3Copy( &result->col1, _col1 ); + vmathSoaV3Copy( &result->col2, _col2 ); +} + +static inline void vmathSoaM3MakeFromAos( VmathSoaMatrix3 *result, const VmathMatrix3 *mat ) +{ + vmathSoaV3MakeFromAos( &result->col0, &mat->col0 ); + vmathSoaV3MakeFromAos( &result->col1, &mat->col1 ); + vmathSoaV3MakeFromAos( &result->col2, &mat->col2 ); +} + +static inline void vmathSoaM3MakeFrom4Aos( VmathSoaMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1, const VmathMatrix3 *mat2, const VmathMatrix3 *mat3 ) +{ + vmathSoaV3MakeFrom4Aos( &result->col0, &mat0->col0, &mat1->col0, &mat2->col0, &mat3->col0 ); + vmathSoaV3MakeFrom4Aos( &result->col1, &mat0->col1, &mat1->col1, &mat2->col1, &mat3->col1 ); + vmathSoaV3MakeFrom4Aos( &result->col2, &mat0->col2, &mat1->col2, &mat2->col2, &mat3->col2 ); +} + +static inline void vmathSoaM3Get4Aos( const VmathSoaMatrix3 *mat, VmathMatrix3 *result0, VmathMatrix3 *result1, VmathMatrix3 *result2, VmathMatrix3 *result3 ) +{ + vmathSoaV3Get4Aos( &mat->col0, &result0->col0, &result1->col0, &result2->col0, &result3->col0 ); + vmathSoaV3Get4Aos( &mat->col1, &result0->col1, &result1->col1, &result2->col1, &result3->col1 ); + vmathSoaV3Get4Aos( &mat->col2, &result0->col2, &result1->col2, &result2->col2, &result3->col2 ); +} + +static inline void vmathSoaM3SetCol0( VmathSoaMatrix3 *result, const VmathSoaVector3 *_col0 ) +{ + vmathSoaV3Copy( &result->col0, _col0 ); +} + +static inline void vmathSoaM3SetCol1( VmathSoaMatrix3 *result, const VmathSoaVector3 *_col1 ) +{ + vmathSoaV3Copy( &result->col1, _col1 ); +} + +static inline void vmathSoaM3SetCol2( VmathSoaMatrix3 *result, const VmathSoaVector3 *_col2 ) +{ + vmathSoaV3Copy( &result->col2, _col2 ); +} + +static inline void vmathSoaM3SetCol( VmathSoaMatrix3 *result, int col, const VmathSoaVector3 *vec ) +{ + vmathSoaV3Copy( (&result->col0 + col), vec ); +} + +static inline void vmathSoaM3SetRow( VmathSoaMatrix3 *result, int row, const VmathSoaVector3 *vec ) +{ + vmathSoaV3SetElem( &result->col0, row, vmathSoaV3GetElem( vec, 0 ) ); + vmathSoaV3SetElem( &result->col1, row, vmathSoaV3GetElem( vec, 1 ) ); + vmathSoaV3SetElem( &result->col2, row, vmathSoaV3GetElem( vec, 2 ) ); +} + +static inline void vmathSoaM3SetElem( VmathSoaMatrix3 *result, int col, int row, vec_float4 val ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaM3GetCol( &tmpV3_0, result, col ); + vmathSoaV3SetElem( &tmpV3_0, row, val ); + vmathSoaM3SetCol( result, col, &tmpV3_0 ); +} + +static inline vec_float4 vmathSoaM3GetElem( const VmathSoaMatrix3 *mat, int col, int row ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaM3GetCol( &tmpV3_0, mat, col ); + return vmathSoaV3GetElem( &tmpV3_0, row ); +} + +static inline void vmathSoaM3GetCol0( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat ) +{ + vmathSoaV3Copy( result, &mat->col0 ); +} + +static inline void vmathSoaM3GetCol1( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat ) +{ + vmathSoaV3Copy( result, &mat->col1 ); +} + +static inline void vmathSoaM3GetCol2( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat ) +{ + vmathSoaV3Copy( result, &mat->col2 ); +} + +static inline void vmathSoaM3GetCol( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat, int col ) +{ + vmathSoaV3Copy( result, (&mat->col0 + col) ); +} + +static inline void vmathSoaM3GetRow( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat, int row ) +{ + vmathSoaV3MakeFromElems( result, vmathSoaV3GetElem( &mat->col0, row ), vmathSoaV3GetElem( &mat->col1, row ), vmathSoaV3GetElem( &mat->col2, row ) ); +} + +static inline void vmathSoaM3Transpose( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ) +{ + VmathSoaMatrix3 tmpResult; + vmathSoaV3MakeFromElems( &tmpResult.col0, mat->col0.x, mat->col1.x, mat->col2.x ); + vmathSoaV3MakeFromElems( &tmpResult.col1, mat->col0.y, mat->col1.y, mat->col2.y ); + vmathSoaV3MakeFromElems( &tmpResult.col2, mat->col0.z, mat->col1.z, mat->col2.z ); + vmathSoaM3Copy( result, &tmpResult ); +} + +static inline void vmathSoaM3Inverse( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ) +{ + VmathSoaVector3 tmp0, tmp1, tmp2; + vec_float4 detinv; + vmathSoaV3Cross( &tmp0, &mat->col1, &mat->col2 ); + vmathSoaV3Cross( &tmp1, &mat->col2, &mat->col0 ); + vmathSoaV3Cross( &tmp2, &mat->col0, &mat->col1 ); + detinv = recipf4( vmathSoaV3Dot( &mat->col2, &tmp2 ) ); + vmathSoaV3MakeFromElems( &result->col0, spu_mul( tmp0.x, detinv ), spu_mul( tmp1.x, detinv ), spu_mul( tmp2.x, detinv ) ); + vmathSoaV3MakeFromElems( &result->col1, spu_mul( tmp0.y, detinv ), spu_mul( tmp1.y, detinv ), spu_mul( tmp2.y, detinv ) ); + vmathSoaV3MakeFromElems( &result->col2, spu_mul( tmp0.z, detinv ), spu_mul( tmp1.z, detinv ), spu_mul( tmp2.z, detinv ) ); +} + +static inline vec_float4 vmathSoaM3Determinant( const VmathSoaMatrix3 *mat ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaV3Cross( &tmpV3_0, &mat->col0, &mat->col1 ); + return vmathSoaV3Dot( &mat->col2, &tmpV3_0 ); +} + +static inline void vmathSoaM3Add( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 ) +{ + vmathSoaV3Add( &result->col0, &mat0->col0, &mat1->col0 ); + vmathSoaV3Add( &result->col1, &mat0->col1, &mat1->col1 ); + vmathSoaV3Add( &result->col2, &mat0->col2, &mat1->col2 ); +} + +static inline void vmathSoaM3Sub( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 ) +{ + vmathSoaV3Sub( &result->col0, &mat0->col0, &mat1->col0 ); + vmathSoaV3Sub( &result->col1, &mat0->col1, &mat1->col1 ); + vmathSoaV3Sub( &result->col2, &mat0->col2, &mat1->col2 ); +} + +static inline void vmathSoaM3Neg( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ) +{ + vmathSoaV3Neg( &result->col0, &mat->col0 ); + vmathSoaV3Neg( &result->col1, &mat->col1 ); + vmathSoaV3Neg( &result->col2, &mat->col2 ); +} + +static inline void vmathSoaM3AbsPerElem( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ) +{ + vmathSoaV3AbsPerElem( &result->col0, &mat->col0 ); + vmathSoaV3AbsPerElem( &result->col1, &mat->col1 ); + vmathSoaV3AbsPerElem( &result->col2, &mat->col2 ); +} + +static inline void vmathSoaM3ScalarMul( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat, vec_float4 scalar ) +{ + vmathSoaV3ScalarMul( &result->col0, &mat->col0, scalar ); + vmathSoaV3ScalarMul( &result->col1, &mat->col1, scalar ); + vmathSoaV3ScalarMul( &result->col2, &mat->col2, scalar ); +} + +static inline void vmathSoaM3MulV3( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat, const VmathSoaVector3 *vec ) +{ + vec_float4 tmpX, tmpY, tmpZ; + tmpX = spu_add( spu_add( spu_mul( mat->col0.x, vec->x ), spu_mul( mat->col1.x, vec->y ) ), spu_mul( mat->col2.x, vec->z ) ); + tmpY = spu_add( spu_add( spu_mul( mat->col0.y, vec->x ), spu_mul( mat->col1.y, vec->y ) ), spu_mul( mat->col2.y, vec->z ) ); + tmpZ = spu_add( spu_add( spu_mul( mat->col0.z, vec->x ), spu_mul( mat->col1.z, vec->y ) ), spu_mul( mat->col2.z, vec->z ) ); + vmathSoaV3MakeFromElems( result, tmpX, tmpY, tmpZ ); +} + +static inline void vmathSoaM3Mul( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 ) +{ + VmathSoaMatrix3 tmpResult; + vmathSoaM3MulV3( &tmpResult.col0, mat0, &mat1->col0 ); + vmathSoaM3MulV3( &tmpResult.col1, mat0, &mat1->col1 ); + vmathSoaM3MulV3( &tmpResult.col2, mat0, &mat1->col2 ); + vmathSoaM3Copy( result, &tmpResult ); +} + +static inline void vmathSoaM3MulPerElem( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 ) +{ + vmathSoaV3MulPerElem( &result->col0, &mat0->col0, &mat1->col0 ); + vmathSoaV3MulPerElem( &result->col1, &mat0->col1, &mat1->col1 ); + vmathSoaV3MulPerElem( &result->col2, &mat0->col2, &mat1->col2 ); +} + +static inline void vmathSoaM3MakeIdentity( VmathSoaMatrix3 *result ) +{ + vmathSoaV3MakeXAxis( &result->col0 ); + vmathSoaV3MakeYAxis( &result->col1 ); + vmathSoaV3MakeZAxis( &result->col2 ); +} + +static inline void vmathSoaM3MakeRotationX( VmathSoaMatrix3 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV3MakeXAxis( &result->col0 ); + vmathSoaV3MakeFromElems( &result->col1, spu_splats(0.0f), c, s ); + vmathSoaV3MakeFromElems( &result->col2, spu_splats(0.0f), negatef4( s ), c ); +} + +static inline void vmathSoaM3MakeRotationY( VmathSoaMatrix3 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV3MakeFromElems( &result->col0, c, spu_splats(0.0f), negatef4( s ) ); + vmathSoaV3MakeYAxis( &result->col1 ); + vmathSoaV3MakeFromElems( &result->col2, s, spu_splats(0.0f), c ); +} + +static inline void vmathSoaM3MakeRotationZ( VmathSoaMatrix3 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV3MakeFromElems( &result->col0, c, s, spu_splats(0.0f) ); + vmathSoaV3MakeFromElems( &result->col1, negatef4( s ), c, spu_splats(0.0f) ); + vmathSoaV3MakeZAxis( &result->col2 ); +} + +static inline void vmathSoaM3MakeRotationZYX( VmathSoaMatrix3 *result, const VmathSoaVector3 *radiansXYZ ) +{ + vec_float4 sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sincosf4( radiansXYZ->x, &sX, &cX ); + sincosf4( radiansXYZ->y, &sY, &cY ); + sincosf4( radiansXYZ->z, &sZ, &cZ ); + tmp0 = spu_mul( cZ, sY ); + tmp1 = spu_mul( sZ, sY ); + vmathSoaV3MakeFromElems( &result->col0, spu_mul( cZ, cY ), spu_mul( sZ, cY ), negatef4( sY ) ); + vmathSoaV3MakeFromElems( &result->col1, spu_sub( spu_mul( tmp0, sX ), spu_mul( sZ, cX ) ), spu_add( spu_mul( tmp1, sX ), spu_mul( cZ, cX ) ), spu_mul( cY, sX ) ); + vmathSoaV3MakeFromElems( &result->col2, spu_add( spu_mul( tmp0, cX ), spu_mul( sZ, sX ) ), spu_sub( spu_mul( tmp1, cX ), spu_mul( cZ, sX ) ), spu_mul( cY, cX ) ); +} + +static inline void vmathSoaM3MakeRotationAxis( VmathSoaMatrix3 *result, vec_float4 radians, const VmathSoaVector3 *unitVec ) +{ + vec_float4 x, y, z, s, c, oneMinusC, xy, yz, zx; + sincosf4( radians, &s, &c ); + x = unitVec->x; + y = unitVec->y; + z = unitVec->z; + xy = spu_mul( x, y ); + yz = spu_mul( y, z ); + zx = spu_mul( z, x ); + oneMinusC = spu_sub( spu_splats(1.0f), c ); + vmathSoaV3MakeFromElems( &result->col0, spu_add( spu_mul( spu_mul( x, x ), oneMinusC ), c ), spu_add( spu_mul( xy, oneMinusC ), spu_mul( z, s ) ), spu_sub( spu_mul( zx, oneMinusC ), spu_mul( y, s ) ) ); + vmathSoaV3MakeFromElems( &result->col1, spu_sub( spu_mul( xy, oneMinusC ), spu_mul( z, s ) ), spu_add( spu_mul( spu_mul( y, y ), oneMinusC ), c ), spu_add( spu_mul( yz, oneMinusC ), spu_mul( x, s ) ) ); + vmathSoaV3MakeFromElems( &result->col2, spu_add( spu_mul( zx, oneMinusC ), spu_mul( y, s ) ), spu_sub( spu_mul( yz, oneMinusC ), spu_mul( x, s ) ), spu_add( spu_mul( spu_mul( z, z ), oneMinusC ), c ) ); +} + +static inline void vmathSoaM3MakeRotationQ( VmathSoaMatrix3 *result, const VmathSoaQuat *unitQuat ) +{ + vmathSoaM3MakeFromQ( result, unitQuat ); +} + +static inline void vmathSoaM3MakeScale( VmathSoaMatrix3 *result, const VmathSoaVector3 *scaleVec ) +{ + vmathSoaV3MakeFromElems( &result->col0, scaleVec->x, spu_splats(0.0f), spu_splats(0.0f) ); + vmathSoaV3MakeFromElems( &result->col1, spu_splats(0.0f), scaleVec->y, spu_splats(0.0f) ); + vmathSoaV3MakeFromElems( &result->col2, spu_splats(0.0f), spu_splats(0.0f), scaleVec->z ); +} + +static inline void vmathSoaM3AppendScale( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat, const VmathSoaVector3 *scaleVec ) +{ + vmathSoaV3ScalarMul( &result->col0, &mat->col0, vmathSoaV3GetX( scaleVec ) ); + vmathSoaV3ScalarMul( &result->col1, &mat->col1, vmathSoaV3GetY( scaleVec ) ); + vmathSoaV3ScalarMul( &result->col2, &mat->col2, vmathSoaV3GetZ( scaleVec ) ); +} + +static inline void vmathSoaM3PrependScale( VmathSoaMatrix3 *result, const VmathSoaVector3 *scaleVec, const VmathSoaMatrix3 *mat ) +{ + vmathSoaV3MulPerElem( &result->col0, &mat->col0, scaleVec ); + vmathSoaV3MulPerElem( &result->col1, &mat->col1, scaleVec ); + vmathSoaV3MulPerElem( &result->col2, &mat->col2, scaleVec ); +} + +static inline void vmathSoaM3Select( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1, vec_uint4 select1 ) +{ + vmathSoaV3Select( &result->col0, &mat0->col0, &mat1->col0, select1 ); + vmathSoaV3Select( &result->col1, &mat0->col1, &mat1->col1, select1 ); + vmathSoaV3Select( &result->col2, &mat0->col2, &mat1->col2, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaM3Print( const VmathSoaMatrix3 *mat ) +{ + VmathMatrix3 mat0, mat1, mat2, mat3; + vmathSoaM3Get4Aos( mat, &mat0, &mat1, &mat2, &mat3 ); + printf("slot 0:\n"); + vmathM3Print( &mat0 ); + printf("slot 1:\n"); + vmathM3Print( &mat1 ); + printf("slot 2:\n"); + vmathM3Print( &mat2 ); + printf("slot 3:\n"); + vmathM3Print( &mat3 ); +} + +static inline void vmathSoaM3Prints( const VmathSoaMatrix3 *mat, const char *name ) +{ + printf("%s:\n", name); + vmathSoaM3Print( mat ); +} + +#endif + +static inline void vmathSoaM4Copy( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4Copy( &result->col0, &mat->col0 ); + vmathSoaV4Copy( &result->col1, &mat->col1 ); + vmathSoaV4Copy( &result->col2, &mat->col2 ); + vmathSoaV4Copy( &result->col3, &mat->col3 ); +} + +static inline void vmathSoaM4MakeFromScalar( VmathSoaMatrix4 *result, vec_float4 scalar ) +{ + vmathSoaV4MakeFromScalar( &result->col0, scalar ); + vmathSoaV4MakeFromScalar( &result->col1, scalar ); + vmathSoaV4MakeFromScalar( &result->col2, scalar ); + vmathSoaV4MakeFromScalar( &result->col3, scalar ); +} + +static inline void vmathSoaM4MakeFromT3( VmathSoaMatrix4 *result, const VmathSoaTransform3 *mat ) +{ + vmathSoaV4MakeFromV3Scalar( &result->col0, &mat->col0, spu_splats(0.0f) ); + vmathSoaV4MakeFromV3Scalar( &result->col1, &mat->col1, spu_splats(0.0f) ); + vmathSoaV4MakeFromV3Scalar( &result->col2, &mat->col2, spu_splats(0.0f) ); + vmathSoaV4MakeFromV3Scalar( &result->col3, &mat->col3, spu_splats(1.0f) ); +} + +static inline void vmathSoaM4MakeFromCols( VmathSoaMatrix4 *result, const VmathSoaVector4 *_col0, const VmathSoaVector4 *_col1, const VmathSoaVector4 *_col2, const VmathSoaVector4 *_col3 ) +{ + vmathSoaV4Copy( &result->col0, _col0 ); + vmathSoaV4Copy( &result->col1, _col1 ); + vmathSoaV4Copy( &result->col2, _col2 ); + vmathSoaV4Copy( &result->col3, _col3 ); +} + +static inline void vmathSoaM4MakeFromM3V3( VmathSoaMatrix4 *result, const VmathSoaMatrix3 *mat, const VmathSoaVector3 *translateVec ) +{ + vmathSoaV4MakeFromV3Scalar( &result->col0, &mat->col0, spu_splats(0.0f) ); + vmathSoaV4MakeFromV3Scalar( &result->col1, &mat->col1, spu_splats(0.0f) ); + vmathSoaV4MakeFromV3Scalar( &result->col2, &mat->col2, spu_splats(0.0f) ); + vmathSoaV4MakeFromV3Scalar( &result->col3, translateVec, spu_splats(1.0f) ); +} + +static inline void vmathSoaM4MakeFromQV3( VmathSoaMatrix4 *result, const VmathSoaQuat *unitQuat, const VmathSoaVector3 *translateVec ) +{ + VmathSoaMatrix3 mat; + vmathSoaM3MakeFromQ( &mat, unitQuat ); + vmathSoaV4MakeFromV3Scalar( &result->col0, &mat.col0, spu_splats(0.0f) ); + vmathSoaV4MakeFromV3Scalar( &result->col1, &mat.col1, spu_splats(0.0f) ); + vmathSoaV4MakeFromV3Scalar( &result->col2, &mat.col2, spu_splats(0.0f) ); + vmathSoaV4MakeFromV3Scalar( &result->col3, translateVec, spu_splats(1.0f) ); +} + +static inline void vmathSoaM4MakeFromAos( VmathSoaMatrix4 *result, const VmathMatrix4 *mat ) +{ + vmathSoaV4MakeFromAos( &result->col0, &mat->col0 ); + vmathSoaV4MakeFromAos( &result->col1, &mat->col1 ); + vmathSoaV4MakeFromAos( &result->col2, &mat->col2 ); + vmathSoaV4MakeFromAos( &result->col3, &mat->col3 ); +} + +static inline void vmathSoaM4MakeFrom4Aos( VmathSoaMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1, const VmathMatrix4 *mat2, const VmathMatrix4 *mat3 ) +{ + vmathSoaV4MakeFrom4Aos( &result->col0, &mat0->col0, &mat1->col0, &mat2->col0, &mat3->col0 ); + vmathSoaV4MakeFrom4Aos( &result->col1, &mat0->col1, &mat1->col1, &mat2->col1, &mat3->col1 ); + vmathSoaV4MakeFrom4Aos( &result->col2, &mat0->col2, &mat1->col2, &mat2->col2, &mat3->col2 ); + vmathSoaV4MakeFrom4Aos( &result->col3, &mat0->col3, &mat1->col3, &mat2->col3, &mat3->col3 ); +} + +static inline void vmathSoaM4Get4Aos( const VmathSoaMatrix4 *mat, VmathMatrix4 *result0, VmathMatrix4 *result1, VmathMatrix4 *result2, VmathMatrix4 *result3 ) +{ + vmathSoaV4Get4Aos( &mat->col0, &result0->col0, &result1->col0, &result2->col0, &result3->col0 ); + vmathSoaV4Get4Aos( &mat->col1, &result0->col1, &result1->col1, &result2->col1, &result3->col1 ); + vmathSoaV4Get4Aos( &mat->col2, &result0->col2, &result1->col2, &result2->col2, &result3->col2 ); + vmathSoaV4Get4Aos( &mat->col3, &result0->col3, &result1->col3, &result2->col3, &result3->col3 ); +} + +static inline void vmathSoaM4SetCol0( VmathSoaMatrix4 *result, const VmathSoaVector4 *_col0 ) +{ + vmathSoaV4Copy( &result->col0, _col0 ); +} + +static inline void vmathSoaM4SetCol1( VmathSoaMatrix4 *result, const VmathSoaVector4 *_col1 ) +{ + vmathSoaV4Copy( &result->col1, _col1 ); +} + +static inline void vmathSoaM4SetCol2( VmathSoaMatrix4 *result, const VmathSoaVector4 *_col2 ) +{ + vmathSoaV4Copy( &result->col2, _col2 ); +} + +static inline void vmathSoaM4SetCol3( VmathSoaMatrix4 *result, const VmathSoaVector4 *_col3 ) +{ + vmathSoaV4Copy( &result->col3, _col3 ); +} + +static inline void vmathSoaM4SetCol( VmathSoaMatrix4 *result, int col, const VmathSoaVector4 *vec ) +{ + vmathSoaV4Copy( (&result->col0 + col), vec ); +} + +static inline void vmathSoaM4SetRow( VmathSoaMatrix4 *result, int row, const VmathSoaVector4 *vec ) +{ + vmathSoaV4SetElem( &result->col0, row, vmathSoaV4GetElem( vec, 0 ) ); + vmathSoaV4SetElem( &result->col1, row, vmathSoaV4GetElem( vec, 1 ) ); + vmathSoaV4SetElem( &result->col2, row, vmathSoaV4GetElem( vec, 2 ) ); + vmathSoaV4SetElem( &result->col3, row, vmathSoaV4GetElem( vec, 3 ) ); +} + +static inline void vmathSoaM4SetElem( VmathSoaMatrix4 *result, int col, int row, vec_float4 val ) +{ + VmathSoaVector4 tmpV3_0; + vmathSoaM4GetCol( &tmpV3_0, result, col ); + vmathSoaV4SetElem( &tmpV3_0, row, val ); + vmathSoaM4SetCol( result, col, &tmpV3_0 ); +} + +static inline vec_float4 vmathSoaM4GetElem( const VmathSoaMatrix4 *mat, int col, int row ) +{ + VmathSoaVector4 tmpV4_0; + vmathSoaM4GetCol( &tmpV4_0, mat, col ); + return vmathSoaV4GetElem( &tmpV4_0, row ); +} + +static inline void vmathSoaM4GetCol0( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4Copy( result, &mat->col0 ); +} + +static inline void vmathSoaM4GetCol1( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4Copy( result, &mat->col1 ); +} + +static inline void vmathSoaM4GetCol2( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4Copy( result, &mat->col2 ); +} + +static inline void vmathSoaM4GetCol3( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4Copy( result, &mat->col3 ); +} + +static inline void vmathSoaM4GetCol( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, int col ) +{ + vmathSoaV4Copy( result, (&mat->col0 + col) ); +} + +static inline void vmathSoaM4GetRow( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, int row ) +{ + vmathSoaV4MakeFromElems( result, vmathSoaV4GetElem( &mat->col0, row ), vmathSoaV4GetElem( &mat->col1, row ), vmathSoaV4GetElem( &mat->col2, row ), vmathSoaV4GetElem( &mat->col3, row ) ); +} + +static inline void vmathSoaM4Transpose( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ) +{ + VmathSoaMatrix4 tmpResult; + vmathSoaV4MakeFromElems( &tmpResult.col0, mat->col0.x, mat->col1.x, mat->col2.x, mat->col3.x ); + vmathSoaV4MakeFromElems( &tmpResult.col1, mat->col0.y, mat->col1.y, mat->col2.y, mat->col3.y ); + vmathSoaV4MakeFromElems( &tmpResult.col2, mat->col0.z, mat->col1.z, mat->col2.z, mat->col3.z ); + vmathSoaV4MakeFromElems( &tmpResult.col3, mat->col0.w, mat->col1.w, mat->col2.w, mat->col3.w ); + vmathSoaM4Copy( result, &tmpResult ); +} + +static inline void vmathSoaM4Inverse( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ) +{ + VmathSoaVector4 res0, res1, res2, res3; + vec_float4 mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, detInv; + mA = mat->col0.x; + mB = mat->col0.y; + mC = mat->col0.z; + mD = mat->col0.w; + mE = mat->col1.x; + mF = mat->col1.y; + mG = mat->col1.z; + mH = mat->col1.w; + mI = mat->col2.x; + mJ = mat->col2.y; + mK = mat->col2.z; + mL = mat->col2.w; + mM = mat->col3.x; + mN = mat->col3.y; + mO = mat->col3.z; + mP = mat->col3.w; + tmp0 = spu_sub( spu_mul( mK, mD ), spu_mul( mC, mL ) ); + tmp1 = spu_sub( spu_mul( mO, mH ), spu_mul( mG, mP ) ); + tmp2 = spu_sub( spu_mul( mB, mK ), spu_mul( mJ, mC ) ); + tmp3 = spu_sub( spu_mul( mF, mO ), spu_mul( mN, mG ) ); + tmp4 = spu_sub( spu_mul( mJ, mD ), spu_mul( mB, mL ) ); + tmp5 = spu_sub( spu_mul( mN, mH ), spu_mul( mF, mP ) ); + vmathSoaV4SetX( &res0, spu_sub( spu_sub( spu_mul( mJ, tmp1 ), spu_mul( mL, tmp3 ) ), spu_mul( mK, tmp5 ) ) ); + vmathSoaV4SetY( &res0, spu_sub( spu_sub( spu_mul( mN, tmp0 ), spu_mul( mP, tmp2 ) ), spu_mul( mO, tmp4 ) ) ); + vmathSoaV4SetZ( &res0, spu_sub( spu_add( spu_mul( mD, tmp3 ), spu_mul( mC, tmp5 ) ), spu_mul( mB, tmp1 ) ) ); + vmathSoaV4SetW( &res0, spu_sub( spu_add( spu_mul( mH, tmp2 ), spu_mul( mG, tmp4 ) ), spu_mul( mF, tmp0 ) ) ); + detInv = recipf4( spu_add( spu_add( spu_add( spu_mul( mA, res0.x ), spu_mul( mE, res0.y ) ), spu_mul( mI, res0.z ) ), spu_mul( mM, res0.w ) ) ); + vmathSoaV4SetX( &res1, spu_mul( mI, tmp1 ) ); + vmathSoaV4SetY( &res1, spu_mul( mM, tmp0 ) ); + vmathSoaV4SetZ( &res1, spu_mul( mA, tmp1 ) ); + vmathSoaV4SetW( &res1, spu_mul( mE, tmp0 ) ); + vmathSoaV4SetX( &res3, spu_mul( mI, tmp3 ) ); + vmathSoaV4SetY( &res3, spu_mul( mM, tmp2 ) ); + vmathSoaV4SetZ( &res3, spu_mul( mA, tmp3 ) ); + vmathSoaV4SetW( &res3, spu_mul( mE, tmp2 ) ); + vmathSoaV4SetX( &res2, spu_mul( mI, tmp5 ) ); + vmathSoaV4SetY( &res2, spu_mul( mM, tmp4 ) ); + vmathSoaV4SetZ( &res2, spu_mul( mA, tmp5 ) ); + vmathSoaV4SetW( &res2, spu_mul( mE, tmp4 ) ); + tmp0 = spu_sub( spu_mul( mI, mB ), spu_mul( mA, mJ ) ); + tmp1 = spu_sub( spu_mul( mM, mF ), spu_mul( mE, mN ) ); + tmp2 = spu_sub( spu_mul( mI, mD ), spu_mul( mA, mL ) ); + tmp3 = spu_sub( spu_mul( mM, mH ), spu_mul( mE, mP ) ); + tmp4 = spu_sub( spu_mul( mI, mC ), spu_mul( mA, mK ) ); + tmp5 = spu_sub( spu_mul( mM, mG ), spu_mul( mE, mO ) ); + vmathSoaV4SetX( &res2, spu_add( spu_sub( spu_mul( mL, tmp1 ), spu_mul( mJ, tmp3 ) ), res2.x ) ); + vmathSoaV4SetY( &res2, spu_add( spu_sub( spu_mul( mP, tmp0 ), spu_mul( mN, tmp2 ) ), res2.y ) ); + vmathSoaV4SetZ( &res2, spu_sub( spu_sub( spu_mul( mB, tmp3 ), spu_mul( mD, tmp1 ) ), res2.z ) ); + vmathSoaV4SetW( &res2, spu_sub( spu_sub( spu_mul( mF, tmp2 ), spu_mul( mH, tmp0 ) ), res2.w ) ); + vmathSoaV4SetX( &res3, spu_add( spu_sub( spu_mul( mJ, tmp5 ), spu_mul( mK, tmp1 ) ), res3.x ) ); + vmathSoaV4SetY( &res3, spu_add( spu_sub( spu_mul( mN, tmp4 ), spu_mul( mO, tmp0 ) ), res3.y ) ); + vmathSoaV4SetZ( &res3, spu_sub( spu_sub( spu_mul( mC, tmp1 ), spu_mul( mB, tmp5 ) ), res3.z ) ); + vmathSoaV4SetW( &res3, spu_sub( spu_sub( spu_mul( mG, tmp0 ), spu_mul( mF, tmp4 ) ), res3.w ) ); + vmathSoaV4SetX( &res1, spu_sub( spu_sub( spu_mul( mK, tmp3 ), spu_mul( mL, tmp5 ) ), res1.x ) ); + vmathSoaV4SetY( &res1, spu_sub( spu_sub( spu_mul( mO, tmp2 ), spu_mul( mP, tmp4 ) ), res1.y ) ); + vmathSoaV4SetZ( &res1, spu_add( spu_sub( spu_mul( mD, tmp5 ), spu_mul( mC, tmp3 ) ), res1.z ) ); + vmathSoaV4SetW( &res1, spu_add( spu_sub( spu_mul( mH, tmp4 ), spu_mul( mG, tmp2 ) ), res1.w ) ); + vmathSoaV4ScalarMul( &result->col0, &res0, detInv ); + vmathSoaV4ScalarMul( &result->col1, &res1, detInv ); + vmathSoaV4ScalarMul( &result->col2, &res2, detInv ); + vmathSoaV4ScalarMul( &result->col3, &res3, detInv ); +} + +static inline void vmathSoaM4AffineInverse( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ) +{ + VmathSoaTransform3 affineMat, tmpT3_0; + VmathSoaVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + vmathSoaV4GetXYZ( &tmpV3_0, &mat->col0 ); + vmathSoaT3SetCol0( &affineMat, &tmpV3_0 ); + vmathSoaV4GetXYZ( &tmpV3_1, &mat->col1 ); + vmathSoaT3SetCol1( &affineMat, &tmpV3_1 ); + vmathSoaV4GetXYZ( &tmpV3_2, &mat->col2 ); + vmathSoaT3SetCol2( &affineMat, &tmpV3_2 ); + vmathSoaV4GetXYZ( &tmpV3_3, &mat->col3 ); + vmathSoaT3SetCol3( &affineMat, &tmpV3_3 ); + vmathSoaT3Inverse( &tmpT3_0, &affineMat ); + vmathSoaM4MakeFromT3( result, &tmpT3_0 ); +} + +static inline void vmathSoaM4OrthoInverse( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ) +{ + VmathSoaTransform3 affineMat, tmpT3_0; + VmathSoaVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + vmathSoaV4GetXYZ( &tmpV3_0, &mat->col0 ); + vmathSoaT3SetCol0( &affineMat, &tmpV3_0 ); + vmathSoaV4GetXYZ( &tmpV3_1, &mat->col1 ); + vmathSoaT3SetCol1( &affineMat, &tmpV3_1 ); + vmathSoaV4GetXYZ( &tmpV3_2, &mat->col2 ); + vmathSoaT3SetCol2( &affineMat, &tmpV3_2 ); + vmathSoaV4GetXYZ( &tmpV3_3, &mat->col3 ); + vmathSoaT3SetCol3( &affineMat, &tmpV3_3 ); + vmathSoaT3OrthoInverse( &tmpT3_0, &affineMat ); + vmathSoaM4MakeFromT3( result, &tmpT3_0 ); +} + +static inline vec_float4 vmathSoaM4Determinant( const VmathSoaMatrix4 *mat ) +{ + vec_float4 dx, dy, dz, dw, mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + mA = mat->col0.x; + mB = mat->col0.y; + mC = mat->col0.z; + mD = mat->col0.w; + mE = mat->col1.x; + mF = mat->col1.y; + mG = mat->col1.z; + mH = mat->col1.w; + mI = mat->col2.x; + mJ = mat->col2.y; + mK = mat->col2.z; + mL = mat->col2.w; + mM = mat->col3.x; + mN = mat->col3.y; + mO = mat->col3.z; + mP = mat->col3.w; + tmp0 = spu_sub( spu_mul( mK, mD ), spu_mul( mC, mL ) ); + tmp1 = spu_sub( spu_mul( mO, mH ), spu_mul( mG, mP ) ); + tmp2 = spu_sub( spu_mul( mB, mK ), spu_mul( mJ, mC ) ); + tmp3 = spu_sub( spu_mul( mF, mO ), spu_mul( mN, mG ) ); + tmp4 = spu_sub( spu_mul( mJ, mD ), spu_mul( mB, mL ) ); + tmp5 = spu_sub( spu_mul( mN, mH ), spu_mul( mF, mP ) ); + dx = spu_sub( spu_sub( spu_mul( mJ, tmp1 ), spu_mul( mL, tmp3 ) ), spu_mul( mK, tmp5 ) ); + dy = spu_sub( spu_sub( spu_mul( mN, tmp0 ), spu_mul( mP, tmp2 ) ), spu_mul( mO, tmp4 ) ); + dz = spu_sub( spu_add( spu_mul( mD, tmp3 ), spu_mul( mC, tmp5 ) ), spu_mul( mB, tmp1 ) ); + dw = spu_sub( spu_add( spu_mul( mH, tmp2 ), spu_mul( mG, tmp4 ) ), spu_mul( mF, tmp0 ) ); + return spu_add( spu_add( spu_add( spu_mul( mA, dx ), spu_mul( mE, dy ) ), spu_mul( mI, dz ) ), spu_mul( mM, dw ) ); +} + +static inline void vmathSoaM4Add( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 ) +{ + vmathSoaV4Add( &result->col0, &mat0->col0, &mat1->col0 ); + vmathSoaV4Add( &result->col1, &mat0->col1, &mat1->col1 ); + vmathSoaV4Add( &result->col2, &mat0->col2, &mat1->col2 ); + vmathSoaV4Add( &result->col3, &mat0->col3, &mat1->col3 ); +} + +static inline void vmathSoaM4Sub( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 ) +{ + vmathSoaV4Sub( &result->col0, &mat0->col0, &mat1->col0 ); + vmathSoaV4Sub( &result->col1, &mat0->col1, &mat1->col1 ); + vmathSoaV4Sub( &result->col2, &mat0->col2, &mat1->col2 ); + vmathSoaV4Sub( &result->col3, &mat0->col3, &mat1->col3 ); +} + +static inline void vmathSoaM4Neg( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4Neg( &result->col0, &mat->col0 ); + vmathSoaV4Neg( &result->col1, &mat->col1 ); + vmathSoaV4Neg( &result->col2, &mat->col2 ); + vmathSoaV4Neg( &result->col3, &mat->col3 ); +} + +static inline void vmathSoaM4AbsPerElem( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4AbsPerElem( &result->col0, &mat->col0 ); + vmathSoaV4AbsPerElem( &result->col1, &mat->col1 ); + vmathSoaV4AbsPerElem( &result->col2, &mat->col2 ); + vmathSoaV4AbsPerElem( &result->col3, &mat->col3 ); +} + +static inline void vmathSoaM4ScalarMul( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat, vec_float4 scalar ) +{ + vmathSoaV4ScalarMul( &result->col0, &mat->col0, scalar ); + vmathSoaV4ScalarMul( &result->col1, &mat->col1, scalar ); + vmathSoaV4ScalarMul( &result->col2, &mat->col2, scalar ); + vmathSoaV4ScalarMul( &result->col3, &mat->col3, scalar ); +} + +static inline void vmathSoaM4MulV4( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, const VmathSoaVector4 *vec ) +{ + vec_float4 tmpX, tmpY, tmpZ, tmpW; + tmpX = spu_add( spu_add( spu_add( spu_mul( mat->col0.x, vec->x ), spu_mul( mat->col1.x, vec->y ) ), spu_mul( mat->col2.x, vec->z ) ), spu_mul( mat->col3.x, vec->w ) ); + tmpY = spu_add( spu_add( spu_add( spu_mul( mat->col0.y, vec->x ), spu_mul( mat->col1.y, vec->y ) ), spu_mul( mat->col2.y, vec->z ) ), spu_mul( mat->col3.y, vec->w ) ); + tmpZ = spu_add( spu_add( spu_add( spu_mul( mat->col0.z, vec->x ), spu_mul( mat->col1.z, vec->y ) ), spu_mul( mat->col2.z, vec->z ) ), spu_mul( mat->col3.z, vec->w ) ); + tmpW = spu_add( spu_add( spu_add( spu_mul( mat->col0.w, vec->x ), spu_mul( mat->col1.w, vec->y ) ), spu_mul( mat->col2.w, vec->z ) ), spu_mul( mat->col3.w, vec->w ) ); + vmathSoaV4MakeFromElems( result, tmpX, tmpY, tmpZ, tmpW ); +} + +static inline void vmathSoaM4MulV3( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, const VmathSoaVector3 *vec ) +{ + result->x = spu_add( spu_add( spu_mul( mat->col0.x, vec->x ), spu_mul( mat->col1.x, vec->y ) ), spu_mul( mat->col2.x, vec->z ) ); + result->y = spu_add( spu_add( spu_mul( mat->col0.y, vec->x ), spu_mul( mat->col1.y, vec->y ) ), spu_mul( mat->col2.y, vec->z ) ); + result->z = spu_add( spu_add( spu_mul( mat->col0.z, vec->x ), spu_mul( mat->col1.z, vec->y ) ), spu_mul( mat->col2.z, vec->z ) ); + result->w = spu_add( spu_add( spu_mul( mat->col0.w, vec->x ), spu_mul( mat->col1.w, vec->y ) ), spu_mul( mat->col2.w, vec->z ) ); +} + +static inline void vmathSoaM4MulP3( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, const VmathSoaPoint3 *pnt ) +{ + result->x = spu_add( spu_add( spu_add( spu_mul( mat->col0.x, pnt->x ), spu_mul( mat->col1.x, pnt->y ) ), spu_mul( mat->col2.x, pnt->z ) ), mat->col3.x ); + result->y = spu_add( spu_add( spu_add( spu_mul( mat->col0.y, pnt->x ), spu_mul( mat->col1.y, pnt->y ) ), spu_mul( mat->col2.y, pnt->z ) ), mat->col3.y ); + result->z = spu_add( spu_add( spu_add( spu_mul( mat->col0.z, pnt->x ), spu_mul( mat->col1.z, pnt->y ) ), spu_mul( mat->col2.z, pnt->z ) ), mat->col3.z ); + result->w = spu_add( spu_add( spu_add( spu_mul( mat->col0.w, pnt->x ), spu_mul( mat->col1.w, pnt->y ) ), spu_mul( mat->col2.w, pnt->z ) ), mat->col3.w ); +} + +static inline void vmathSoaM4Mul( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 ) +{ + VmathSoaMatrix4 tmpResult; + vmathSoaM4MulV4( &tmpResult.col0, mat0, &mat1->col0 ); + vmathSoaM4MulV4( &tmpResult.col1, mat0, &mat1->col1 ); + vmathSoaM4MulV4( &tmpResult.col2, mat0, &mat1->col2 ); + vmathSoaM4MulV4( &tmpResult.col3, mat0, &mat1->col3 ); + vmathSoaM4Copy( result, &tmpResult ); +} + +static inline void vmathSoaM4MulT3( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat, const VmathSoaTransform3 *tfrm1 ) +{ + VmathSoaMatrix4 tmpResult; + VmathSoaPoint3 tmpP3_0; + vmathSoaM4MulV3( &tmpResult.col0, mat, &tfrm1->col0 ); + vmathSoaM4MulV3( &tmpResult.col1, mat, &tfrm1->col1 ); + vmathSoaM4MulV3( &tmpResult.col2, mat, &tfrm1->col2 ); + vmathSoaP3MakeFromV3( &tmpP3_0, &tfrm1->col3 ); + vmathSoaM4MulP3( &tmpResult.col3, mat, &tmpP3_0 ); + vmathSoaM4Copy( result, &tmpResult ); +} + +static inline void vmathSoaM4MulPerElem( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 ) +{ + vmathSoaV4MulPerElem( &result->col0, &mat0->col0, &mat1->col0 ); + vmathSoaV4MulPerElem( &result->col1, &mat0->col1, &mat1->col1 ); + vmathSoaV4MulPerElem( &result->col2, &mat0->col2, &mat1->col2 ); + vmathSoaV4MulPerElem( &result->col3, &mat0->col3, &mat1->col3 ); +} + +static inline void vmathSoaM4MakeIdentity( VmathSoaMatrix4 *result ) +{ + vmathSoaV4MakeXAxis( &result->col0 ); + vmathSoaV4MakeYAxis( &result->col1 ); + vmathSoaV4MakeZAxis( &result->col2 ); + vmathSoaV4MakeWAxis( &result->col3 ); +} + +static inline void vmathSoaM4SetUpper3x3( VmathSoaMatrix4 *result, const VmathSoaMatrix3 *mat3 ) +{ + vmathSoaV4SetXYZ( &result->col0, &mat3->col0 ); + vmathSoaV4SetXYZ( &result->col1, &mat3->col1 ); + vmathSoaV4SetXYZ( &result->col2, &mat3->col2 ); +} + +static inline void vmathSoaM4GetUpper3x3( VmathSoaMatrix3 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4GetXYZ( &result->col0, &mat->col0 ); + vmathSoaV4GetXYZ( &result->col1, &mat->col1 ); + vmathSoaV4GetXYZ( &result->col2, &mat->col2 ); +} + +static inline void vmathSoaM4SetTranslation( VmathSoaMatrix4 *result, const VmathSoaVector3 *translateVec ) +{ + vmathSoaV4SetXYZ( &result->col3, translateVec ); +} + +static inline void vmathSoaM4GetTranslation( VmathSoaVector3 *result, const VmathSoaMatrix4 *mat ) +{ + vmathSoaV4GetXYZ( result, &mat->col3 ); +} + +static inline void vmathSoaM4MakeRotationX( VmathSoaMatrix4 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV4MakeXAxis( &result->col0 ); + vmathSoaV4MakeFromElems( &result->col1, spu_splats(0.0f), c, s, spu_splats(0.0f) ); + vmathSoaV4MakeFromElems( &result->col2, spu_splats(0.0f), negatef4( s ), c, spu_splats(0.0f) ); + vmathSoaV4MakeWAxis( &result->col3 ); +} + +static inline void vmathSoaM4MakeRotationY( VmathSoaMatrix4 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV4MakeFromElems( &result->col0, c, spu_splats(0.0f), negatef4( s ), spu_splats(0.0f) ); + vmathSoaV4MakeYAxis( &result->col1 ); + vmathSoaV4MakeFromElems( &result->col2, s, spu_splats(0.0f), c, spu_splats(0.0f) ); + vmathSoaV4MakeWAxis( &result->col3 ); +} + +static inline void vmathSoaM4MakeRotationZ( VmathSoaMatrix4 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV4MakeFromElems( &result->col0, c, s, spu_splats(0.0f), spu_splats(0.0f) ); + vmathSoaV4MakeFromElems( &result->col1, negatef4( s ), c, spu_splats(0.0f), spu_splats(0.0f) ); + vmathSoaV4MakeZAxis( &result->col2 ); + vmathSoaV4MakeWAxis( &result->col3 ); +} + +static inline void vmathSoaM4MakeRotationZYX( VmathSoaMatrix4 *result, const VmathSoaVector3 *radiansXYZ ) +{ + vec_float4 sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sincosf4( radiansXYZ->x, &sX, &cX ); + sincosf4( radiansXYZ->y, &sY, &cY ); + sincosf4( radiansXYZ->z, &sZ, &cZ ); + tmp0 = spu_mul( cZ, sY ); + tmp1 = spu_mul( sZ, sY ); + vmathSoaV4MakeFromElems( &result->col0, spu_mul( cZ, cY ), spu_mul( sZ, cY ), negatef4( sY ), spu_splats(0.0f) ); + vmathSoaV4MakeFromElems( &result->col1, spu_sub( spu_mul( tmp0, sX ), spu_mul( sZ, cX ) ), spu_add( spu_mul( tmp1, sX ), spu_mul( cZ, cX ) ), spu_mul( cY, sX ), spu_splats(0.0f) ); + vmathSoaV4MakeFromElems( &result->col2, spu_add( spu_mul( tmp0, cX ), spu_mul( sZ, sX ) ), spu_sub( spu_mul( tmp1, cX ), spu_mul( cZ, sX ) ), spu_mul( cY, cX ), spu_splats(0.0f) ); + vmathSoaV4MakeWAxis( &result->col3 ); +} + +static inline void vmathSoaM4MakeRotationAxis( VmathSoaMatrix4 *result, vec_float4 radians, const VmathSoaVector3 *unitVec ) +{ + vec_float4 x, y, z, s, c, oneMinusC, xy, yz, zx; + sincosf4( radians, &s, &c ); + x = unitVec->x; + y = unitVec->y; + z = unitVec->z; + xy = spu_mul( x, y ); + yz = spu_mul( y, z ); + zx = spu_mul( z, x ); + oneMinusC = spu_sub( spu_splats(1.0f), c ); + vmathSoaV4MakeFromElems( &result->col0, spu_add( spu_mul( spu_mul( x, x ), oneMinusC ), c ), spu_add( spu_mul( xy, oneMinusC ), spu_mul( z, s ) ), spu_sub( spu_mul( zx, oneMinusC ), spu_mul( y, s ) ), spu_splats(0.0f) ); + vmathSoaV4MakeFromElems( &result->col1, spu_sub( spu_mul( xy, oneMinusC ), spu_mul( z, s ) ), spu_add( spu_mul( spu_mul( y, y ), oneMinusC ), c ), spu_add( spu_mul( yz, oneMinusC ), spu_mul( x, s ) ), spu_splats(0.0f) ); + vmathSoaV4MakeFromElems( &result->col2, spu_add( spu_mul( zx, oneMinusC ), spu_mul( y, s ) ), spu_sub( spu_mul( yz, oneMinusC ), spu_mul( x, s ) ), spu_add( spu_mul( spu_mul( z, z ), oneMinusC ), c ), spu_splats(0.0f) ); + vmathSoaV4MakeWAxis( &result->col3 ); +} + +static inline void vmathSoaM4MakeRotationQ( VmathSoaMatrix4 *result, const VmathSoaQuat *unitQuat ) +{ + VmathSoaTransform3 tmpT3_0; + vmathSoaT3MakeRotationQ( &tmpT3_0, unitQuat ); + vmathSoaM4MakeFromT3( result, &tmpT3_0 ); +} + +static inline void vmathSoaM4MakeScale( VmathSoaMatrix4 *result, const VmathSoaVector3 *scaleVec ) +{ + vmathSoaV4MakeFromElems( &result->col0, scaleVec->x, spu_splats(0.0f), spu_splats(0.0f), spu_splats(0.0f) ); + vmathSoaV4MakeFromElems( &result->col1, spu_splats(0.0f), scaleVec->y, spu_splats(0.0f), spu_splats(0.0f) ); + vmathSoaV4MakeFromElems( &result->col2, spu_splats(0.0f), spu_splats(0.0f), scaleVec->z, spu_splats(0.0f) ); + vmathSoaV4MakeWAxis( &result->col3 ); +} + +static inline void vmathSoaM4AppendScale( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat, const VmathSoaVector3 *scaleVec ) +{ + vmathSoaV4ScalarMul( &result->col0, &mat->col0, vmathSoaV3GetX( scaleVec ) ); + vmathSoaV4ScalarMul( &result->col1, &mat->col1, vmathSoaV3GetY( scaleVec ) ); + vmathSoaV4ScalarMul( &result->col2, &mat->col2, vmathSoaV3GetZ( scaleVec ) ); + vmathSoaV4Copy( &result->col3, &mat->col3 ); +} + +static inline void vmathSoaM4PrependScale( VmathSoaMatrix4 *result, const VmathSoaVector3 *scaleVec, const VmathSoaMatrix4 *mat ) +{ + VmathSoaVector4 scale4; + vmathSoaV4MakeFromV3Scalar( &scale4, scaleVec, spu_splats(1.0f) ); + vmathSoaV4MulPerElem( &result->col0, &mat->col0, &scale4 ); + vmathSoaV4MulPerElem( &result->col1, &mat->col1, &scale4 ); + vmathSoaV4MulPerElem( &result->col2, &mat->col2, &scale4 ); + vmathSoaV4MulPerElem( &result->col3, &mat->col3, &scale4 ); +} + +static inline void vmathSoaM4MakeTranslation( VmathSoaMatrix4 *result, const VmathSoaVector3 *translateVec ) +{ + vmathSoaV4MakeXAxis( &result->col0 ); + vmathSoaV4MakeYAxis( &result->col1 ); + vmathSoaV4MakeZAxis( &result->col2 ); + vmathSoaV4MakeFromV3Scalar( &result->col3, translateVec, spu_splats(1.0f) ); +} + +static inline void vmathSoaM4MakeLookAt( VmathSoaMatrix4 *result, const VmathSoaPoint3 *eyePos, const VmathSoaPoint3 *lookAtPos, const VmathSoaVector3 *upVec ) +{ + VmathSoaMatrix4 m4EyeFrame; + VmathSoaVector3 v3X, v3Y, v3Z, tmpV3_0, tmpV3_1; + VmathSoaVector4 tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3; + vmathSoaV3Normalize( &v3Y, upVec ); + vmathSoaP3Sub( &tmpV3_0, eyePos, lookAtPos ); + vmathSoaV3Normalize( &v3Z, &tmpV3_0 ); + vmathSoaV3Cross( &tmpV3_1, &v3Y, &v3Z ); + vmathSoaV3Normalize( &v3X, &tmpV3_1 ); + vmathSoaV3Cross( &v3Y, &v3Z, &v3X ); + vmathSoaV4MakeFromV3( &tmpV4_0, &v3X ); + vmathSoaV4MakeFromV3( &tmpV4_1, &v3Y ); + vmathSoaV4MakeFromV3( &tmpV4_2, &v3Z ); + vmathSoaV4MakeFromP3( &tmpV4_3, eyePos ); + vmathSoaM4MakeFromCols( &m4EyeFrame, &tmpV4_0, &tmpV4_1, &tmpV4_2, &tmpV4_3 ); + vmathSoaM4OrthoInverse( result, &m4EyeFrame ); +} + +static inline void vmathSoaM4MakePerspective( VmathSoaMatrix4 *result, vec_float4 fovyRadians, vec_float4 aspect, vec_float4 zNear, vec_float4 zFar ) +{ + vec_float4 f, rangeInv; + f = tanf4( spu_sub( spu_splats( _VECTORMATH_PI_OVER_2 ), spu_mul( spu_splats(0.5f), fovyRadians ) ) ); + rangeInv = recipf4( spu_sub( zNear, zFar ) ); + vmathSoaV4MakeFromElems( &result->col0, divf4( f, aspect ), spu_splats(0.0f), spu_splats(0.0f), spu_splats(0.0f) ); + vmathSoaV4MakeFromElems( &result->col1, spu_splats(0.0f), f, spu_splats(0.0f), spu_splats(0.0f) ); + vmathSoaV4MakeFromElems( &result->col2, spu_splats(0.0f), spu_splats(0.0f), spu_mul( spu_add( zNear, zFar ), rangeInv ), spu_splats(-1.0f) ); + vmathSoaV4MakeFromElems( &result->col3, spu_splats(0.0f), spu_splats(0.0f), spu_mul( spu_mul( spu_mul( zNear, zFar ), rangeInv ), spu_splats(2.0f) ), spu_splats(0.0f) ); +} + +static inline void vmathSoaM4MakeFrustum( VmathSoaMatrix4 *result, vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ) +{ + vec_float4 sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf, n2; + sum_rl = spu_add( right, left ); + sum_tb = spu_add( top, bottom ); + sum_nf = spu_add( zNear, zFar ); + inv_rl = recipf4( spu_sub( right, left ) ); + inv_tb = recipf4( spu_sub( top, bottom ) ); + inv_nf = recipf4( spu_sub( zNear, zFar ) ); + n2 = spu_add( zNear, zNear ); + vmathSoaV4MakeFromElems( &result->col0, spu_mul( n2, inv_rl ), spu_splats(0.0f), spu_splats(0.0f), spu_splats(0.0f) ); + vmathSoaV4MakeFromElems( &result->col1, spu_splats(0.0f), spu_mul( n2, inv_tb ), spu_splats(0.0f), spu_splats(0.0f) ); + vmathSoaV4MakeFromElems( &result->col2, spu_mul( sum_rl, inv_rl ), spu_mul( sum_tb, inv_tb ), spu_mul( sum_nf, inv_nf ), spu_splats(-1.0f) ); + vmathSoaV4MakeFromElems( &result->col3, spu_splats(0.0f), spu_splats(0.0f), spu_mul( spu_mul( n2, inv_nf ), zFar ), spu_splats(0.0f) ); +} + +static inline void vmathSoaM4MakeOrthographic( VmathSoaMatrix4 *result, vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ) +{ + vec_float4 sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf; + sum_rl = spu_add( right, left ); + sum_tb = spu_add( top, bottom ); + sum_nf = spu_add( zNear, zFar ); + inv_rl = recipf4( spu_sub( right, left ) ); + inv_tb = recipf4( spu_sub( top, bottom ) ); + inv_nf = recipf4( spu_sub( zNear, zFar ) ); + vmathSoaV4MakeFromElems( &result->col0, spu_add( inv_rl, inv_rl ), spu_splats(0.0f), spu_splats(0.0f), spu_splats(0.0f) ); + vmathSoaV4MakeFromElems( &result->col1, spu_splats(0.0f), spu_add( inv_tb, inv_tb ), spu_splats(0.0f), spu_splats(0.0f) ); + vmathSoaV4MakeFromElems( &result->col2, spu_splats(0.0f), spu_splats(0.0f), spu_add( inv_nf, inv_nf ), spu_splats(0.0f) ); + vmathSoaV4MakeFromElems( &result->col3, spu_mul( negatef4( sum_rl ), inv_rl ), spu_mul( negatef4( sum_tb ), inv_tb ), spu_mul( sum_nf, inv_nf ), spu_splats(1.0f) ); +} + +static inline void vmathSoaM4Select( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1, vec_uint4 select1 ) +{ + vmathSoaV4Select( &result->col0, &mat0->col0, &mat1->col0, select1 ); + vmathSoaV4Select( &result->col1, &mat0->col1, &mat1->col1, select1 ); + vmathSoaV4Select( &result->col2, &mat0->col2, &mat1->col2, select1 ); + vmathSoaV4Select( &result->col3, &mat0->col3, &mat1->col3, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaM4Print( const VmathSoaMatrix4 *mat ) +{ + VmathMatrix4 mat0, mat1, mat2, mat3; + vmathSoaM4Get4Aos( mat, &mat0, &mat1, &mat2, &mat3 ); + printf("slot 0:\n"); + vmathM4Print( &mat0 ); + printf("slot 1:\n"); + vmathM4Print( &mat1 ); + printf("slot 2:\n"); + vmathM4Print( &mat2 ); + printf("slot 3:\n"); + vmathM4Print( &mat3 ); +} + +static inline void vmathSoaM4Prints( const VmathSoaMatrix4 *mat, const char *name ) +{ + printf("%s:\n", name); + vmathSoaM4Print( mat ); +} + +#endif + +static inline void vmathSoaT3Copy( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaV3Copy( &result->col0, &tfrm->col0 ); + vmathSoaV3Copy( &result->col1, &tfrm->col1 ); + vmathSoaV3Copy( &result->col2, &tfrm->col2 ); + vmathSoaV3Copy( &result->col3, &tfrm->col3 ); +} + +static inline void vmathSoaT3MakeFromScalar( VmathSoaTransform3 *result, vec_float4 scalar ) +{ + vmathSoaV3MakeFromScalar( &result->col0, scalar ); + vmathSoaV3MakeFromScalar( &result->col1, scalar ); + vmathSoaV3MakeFromScalar( &result->col2, scalar ); + vmathSoaV3MakeFromScalar( &result->col3, scalar ); +} + +static inline void vmathSoaT3MakeFromCols( VmathSoaTransform3 *result, const VmathSoaVector3 *_col0, const VmathSoaVector3 *_col1, const VmathSoaVector3 *_col2, const VmathSoaVector3 *_col3 ) +{ + vmathSoaV3Copy( &result->col0, _col0 ); + vmathSoaV3Copy( &result->col1, _col1 ); + vmathSoaV3Copy( &result->col2, _col2 ); + vmathSoaV3Copy( &result->col3, _col3 ); +} + +static inline void vmathSoaT3MakeFromM3V3( VmathSoaTransform3 *result, const VmathSoaMatrix3 *tfrm, const VmathSoaVector3 *translateVec ) +{ + vmathSoaT3SetUpper3x3( result, tfrm ); + vmathSoaT3SetTranslation( result, translateVec ); +} + +static inline void vmathSoaT3MakeFromQV3( VmathSoaTransform3 *result, const VmathSoaQuat *unitQuat, const VmathSoaVector3 *translateVec ) +{ + VmathSoaMatrix3 tmpM3_0; + vmathSoaM3MakeFromQ( &tmpM3_0, unitQuat ); + vmathSoaT3SetUpper3x3( result, &tmpM3_0 ); + vmathSoaT3SetTranslation( result, translateVec ); +} + +static inline void vmathSoaT3MakeFromAos( VmathSoaTransform3 *result, const VmathTransform3 *tfrm ) +{ + vmathSoaV3MakeFromAos( &result->col0, &tfrm->col0 ); + vmathSoaV3MakeFromAos( &result->col1, &tfrm->col1 ); + vmathSoaV3MakeFromAos( &result->col2, &tfrm->col2 ); + vmathSoaV3MakeFromAos( &result->col3, &tfrm->col3 ); +} + +static inline void vmathSoaT3MakeFrom4Aos( VmathSoaTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1, const VmathTransform3 *tfrm2, const VmathTransform3 *tfrm3 ) +{ + vmathSoaV3MakeFrom4Aos( &result->col0, &tfrm0->col0, &tfrm1->col0, &tfrm2->col0, &tfrm3->col0 ); + vmathSoaV3MakeFrom4Aos( &result->col1, &tfrm0->col1, &tfrm1->col1, &tfrm2->col1, &tfrm3->col1 ); + vmathSoaV3MakeFrom4Aos( &result->col2, &tfrm0->col2, &tfrm1->col2, &tfrm2->col2, &tfrm3->col2 ); + vmathSoaV3MakeFrom4Aos( &result->col3, &tfrm0->col3, &tfrm1->col3, &tfrm2->col3, &tfrm3->col3 ); +} + +static inline void vmathSoaT3Get4Aos( const VmathSoaTransform3 *tfrm, VmathTransform3 *result0, VmathTransform3 *result1, VmathTransform3 *result2, VmathTransform3 *result3 ) +{ + vmathSoaV3Get4Aos( &tfrm->col0, &result0->col0, &result1->col0, &result2->col0, &result3->col0 ); + vmathSoaV3Get4Aos( &tfrm->col1, &result0->col1, &result1->col1, &result2->col1, &result3->col1 ); + vmathSoaV3Get4Aos( &tfrm->col2, &result0->col2, &result1->col2, &result2->col2, &result3->col2 ); + vmathSoaV3Get4Aos( &tfrm->col3, &result0->col3, &result1->col3, &result2->col3, &result3->col3 ); +} + +static inline void vmathSoaT3SetCol0( VmathSoaTransform3 *result, const VmathSoaVector3 *_col0 ) +{ + vmathSoaV3Copy( &result->col0, _col0 ); +} + +static inline void vmathSoaT3SetCol1( VmathSoaTransform3 *result, const VmathSoaVector3 *_col1 ) +{ + vmathSoaV3Copy( &result->col1, _col1 ); +} + +static inline void vmathSoaT3SetCol2( VmathSoaTransform3 *result, const VmathSoaVector3 *_col2 ) +{ + vmathSoaV3Copy( &result->col2, _col2 ); +} + +static inline void vmathSoaT3SetCol3( VmathSoaTransform3 *result, const VmathSoaVector3 *_col3 ) +{ + vmathSoaV3Copy( &result->col3, _col3 ); +} + +static inline void vmathSoaT3SetCol( VmathSoaTransform3 *result, int col, const VmathSoaVector3 *vec ) +{ + vmathSoaV3Copy( (&result->col0 + col), vec ); +} + +static inline void vmathSoaT3SetRow( VmathSoaTransform3 *result, int row, const VmathSoaVector4 *vec ) +{ + vmathSoaV3SetElem( &result->col0, row, vmathSoaV4GetElem( vec, 0 ) ); + vmathSoaV3SetElem( &result->col1, row, vmathSoaV4GetElem( vec, 1 ) ); + vmathSoaV3SetElem( &result->col2, row, vmathSoaV4GetElem( vec, 2 ) ); + vmathSoaV3SetElem( &result->col3, row, vmathSoaV4GetElem( vec, 3 ) ); +} + +static inline void vmathSoaT3SetElem( VmathSoaTransform3 *result, int col, int row, vec_float4 val ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaT3GetCol( &tmpV3_0, result, col ); + vmathSoaV3SetElem( &tmpV3_0, row, val ); + vmathSoaT3SetCol( result, col, &tmpV3_0 ); +} + +static inline vec_float4 vmathSoaT3GetElem( const VmathSoaTransform3 *tfrm, int col, int row ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaT3GetCol( &tmpV3_0, tfrm, col ); + return vmathSoaV3GetElem( &tmpV3_0, row ); +} + +static inline void vmathSoaT3GetCol0( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaV3Copy( result, &tfrm->col0 ); +} + +static inline void vmathSoaT3GetCol1( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaV3Copy( result, &tfrm->col1 ); +} + +static inline void vmathSoaT3GetCol2( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaV3Copy( result, &tfrm->col2 ); +} + +static inline void vmathSoaT3GetCol3( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaV3Copy( result, &tfrm->col3 ); +} + +static inline void vmathSoaT3GetCol( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm, int col ) +{ + vmathSoaV3Copy( result, (&tfrm->col0 + col) ); +} + +static inline void vmathSoaT3GetRow( VmathSoaVector4 *result, const VmathSoaTransform3 *tfrm, int row ) +{ + vmathSoaV4MakeFromElems( result, vmathSoaV3GetElem( &tfrm->col0, row ), vmathSoaV3GetElem( &tfrm->col1, row ), vmathSoaV3GetElem( &tfrm->col2, row ), vmathSoaV3GetElem( &tfrm->col3, row ) ); +} + +static inline void vmathSoaT3Inverse( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm ) +{ + VmathSoaVector3 tmp0, tmp1, tmp2, inv0, inv1, inv2, tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5; + vec_float4 detinv; + vmathSoaV3Cross( &tmp0, &tfrm->col1, &tfrm->col2 ); + vmathSoaV3Cross( &tmp1, &tfrm->col2, &tfrm->col0 ); + vmathSoaV3Cross( &tmp2, &tfrm->col0, &tfrm->col1 ); + detinv = recipf4( vmathSoaV3Dot( &tfrm->col2, &tmp2 ) ); + vmathSoaV3MakeFromElems( &inv0, spu_mul( tmp0.x, detinv ), spu_mul( tmp1.x, detinv ), spu_mul( tmp2.x, detinv ) ); + vmathSoaV3MakeFromElems( &inv1, spu_mul( tmp0.y, detinv ), spu_mul( tmp1.y, detinv ), spu_mul( tmp2.y, detinv ) ); + vmathSoaV3MakeFromElems( &inv2, spu_mul( tmp0.z, detinv ), spu_mul( tmp1.z, detinv ), spu_mul( tmp2.z, detinv ) ); + vmathSoaV3Copy( &result->col0, &inv0 ); + vmathSoaV3Copy( &result->col1, &inv1 ); + vmathSoaV3Copy( &result->col2, &inv2 ); + vmathSoaV3ScalarMul( &tmpV3_0, &inv0, tfrm->col3.x ); + vmathSoaV3ScalarMul( &tmpV3_1, &inv1, tfrm->col3.y ); + vmathSoaV3ScalarMul( &tmpV3_2, &inv2, tfrm->col3.z ); + vmathSoaV3Add( &tmpV3_3, &tmpV3_1, &tmpV3_2 ); + vmathSoaV3Add( &tmpV3_4, &tmpV3_0, &tmpV3_3 ); + vmathSoaV3Neg( &tmpV3_5, &tmpV3_4 ); + vmathSoaV3Copy( &result->col3, &tmpV3_5 ); +} + +static inline void vmathSoaT3OrthoInverse( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm ) +{ + VmathSoaVector3 inv0, inv1, inv2, tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5; + vmathSoaV3MakeFromElems( &inv0, tfrm->col0.x, tfrm->col1.x, tfrm->col2.x ); + vmathSoaV3MakeFromElems( &inv1, tfrm->col0.y, tfrm->col1.y, tfrm->col2.y ); + vmathSoaV3MakeFromElems( &inv2, tfrm->col0.z, tfrm->col1.z, tfrm->col2.z ); + vmathSoaV3Copy( &result->col0, &inv0 ); + vmathSoaV3Copy( &result->col1, &inv1 ); + vmathSoaV3Copy( &result->col2, &inv2 ); + vmathSoaV3ScalarMul( &tmpV3_0, &inv0, tfrm->col3.x ); + vmathSoaV3ScalarMul( &tmpV3_1, &inv1, tfrm->col3.y ); + vmathSoaV3ScalarMul( &tmpV3_2, &inv2, tfrm->col3.z ); + vmathSoaV3Add( &tmpV3_3, &tmpV3_1, &tmpV3_2 ); + vmathSoaV3Add( &tmpV3_4, &tmpV3_0, &tmpV3_3 ); + vmathSoaV3Neg( &tmpV3_5, &tmpV3_4 ); + vmathSoaV3Copy( &result->col3, &tmpV3_5 ); +} + +static inline void vmathSoaT3AbsPerElem( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaV3AbsPerElem( &result->col0, &tfrm->col0 ); + vmathSoaV3AbsPerElem( &result->col1, &tfrm->col1 ); + vmathSoaV3AbsPerElem( &result->col2, &tfrm->col2 ); + vmathSoaV3AbsPerElem( &result->col3, &tfrm->col3 ); +} + +static inline void vmathSoaT3MulV3( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm, const VmathSoaVector3 *vec ) +{ + vec_float4 tmpX, tmpY, tmpZ; + tmpX = spu_add( spu_add( spu_mul( tfrm->col0.x, vec->x ), spu_mul( tfrm->col1.x, vec->y ) ), spu_mul( tfrm->col2.x, vec->z ) ); + tmpY = spu_add( spu_add( spu_mul( tfrm->col0.y, vec->x ), spu_mul( tfrm->col1.y, vec->y ) ), spu_mul( tfrm->col2.y, vec->z ) ); + tmpZ = spu_add( spu_add( spu_mul( tfrm->col0.z, vec->x ), spu_mul( tfrm->col1.z, vec->y ) ), spu_mul( tfrm->col2.z, vec->z ) ); + vmathSoaV3MakeFromElems( result, tmpX, tmpY, tmpZ ); +} + +static inline void vmathSoaT3MulP3( VmathSoaPoint3 *result, const VmathSoaTransform3 *tfrm, const VmathSoaPoint3 *pnt ) +{ + vec_float4 tmpX, tmpY, tmpZ; + tmpX = spu_add( spu_add( spu_add( spu_mul( tfrm->col0.x, pnt->x ), spu_mul( tfrm->col1.x, pnt->y ) ), spu_mul( tfrm->col2.x, pnt->z ) ), tfrm->col3.x ); + tmpY = spu_add( spu_add( spu_add( spu_mul( tfrm->col0.y, pnt->x ), spu_mul( tfrm->col1.y, pnt->y ) ), spu_mul( tfrm->col2.y, pnt->z ) ), tfrm->col3.y ); + tmpZ = spu_add( spu_add( spu_add( spu_mul( tfrm->col0.z, pnt->x ), spu_mul( tfrm->col1.z, pnt->y ) ), spu_mul( tfrm->col2.z, pnt->z ) ), tfrm->col3.z ); + vmathSoaP3MakeFromElems( result, tmpX, tmpY, tmpZ ); +} + +static inline void vmathSoaT3Mul( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm0, const VmathSoaTransform3 *tfrm1 ) +{ + VmathSoaTransform3 tmpResult; + VmathSoaPoint3 tmpP3_0, tmpP3_1; + vmathSoaT3MulV3( &tmpResult.col0, tfrm0, &tfrm1->col0 ); + vmathSoaT3MulV3( &tmpResult.col1, tfrm0, &tfrm1->col1 ); + vmathSoaT3MulV3( &tmpResult.col2, tfrm0, &tfrm1->col2 ); + vmathSoaP3MakeFromV3( &tmpP3_0, &tfrm1->col3 ); + vmathSoaT3MulP3( &tmpP3_1, tfrm0, &tmpP3_0 ); + vmathSoaV3MakeFromP3( &tmpResult.col3, &tmpP3_1 ); + vmathSoaT3Copy( result, &tmpResult ); +} + +static inline void vmathSoaT3MulPerElem( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm0, const VmathSoaTransform3 *tfrm1 ) +{ + vmathSoaV3MulPerElem( &result->col0, &tfrm0->col0, &tfrm1->col0 ); + vmathSoaV3MulPerElem( &result->col1, &tfrm0->col1, &tfrm1->col1 ); + vmathSoaV3MulPerElem( &result->col2, &tfrm0->col2, &tfrm1->col2 ); + vmathSoaV3MulPerElem( &result->col3, &tfrm0->col3, &tfrm1->col3 ); +} + +static inline void vmathSoaT3MakeIdentity( VmathSoaTransform3 *result ) +{ + vmathSoaV3MakeXAxis( &result->col0 ); + vmathSoaV3MakeYAxis( &result->col1 ); + vmathSoaV3MakeZAxis( &result->col2 ); + vmathSoaV3MakeFromScalar( &result->col3, spu_splats(0.0f) ); +} + +static inline void vmathSoaT3SetUpper3x3( VmathSoaTransform3 *result, const VmathSoaMatrix3 *tfrm ) +{ + vmathSoaV3Copy( &result->col0, &tfrm->col0 ); + vmathSoaV3Copy( &result->col1, &tfrm->col1 ); + vmathSoaV3Copy( &result->col2, &tfrm->col2 ); +} + +static inline void vmathSoaT3GetUpper3x3( VmathSoaMatrix3 *result, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaM3MakeFromCols( result, &tfrm->col0, &tfrm->col1, &tfrm->col2 ); +} + +static inline void vmathSoaT3SetTranslation( VmathSoaTransform3 *result, const VmathSoaVector3 *translateVec ) +{ + vmathSoaV3Copy( &result->col3, translateVec ); +} + +static inline void vmathSoaT3GetTranslation( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaV3Copy( result, &tfrm->col3 ); +} + +static inline void vmathSoaT3MakeRotationX( VmathSoaTransform3 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV3MakeXAxis( &result->col0 ); + vmathSoaV3MakeFromElems( &result->col1, spu_splats(0.0f), c, s ); + vmathSoaV3MakeFromElems( &result->col2, spu_splats(0.0f), negatef4( s ), c ); + vmathSoaV3MakeFromScalar( &result->col3, spu_splats(0.0f) ); +} + +static inline void vmathSoaT3MakeRotationY( VmathSoaTransform3 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV3MakeFromElems( &result->col0, c, spu_splats(0.0f), negatef4( s ) ); + vmathSoaV3MakeYAxis( &result->col1 ); + vmathSoaV3MakeFromElems( &result->col2, s, spu_splats(0.0f), c ); + vmathSoaV3MakeFromScalar( &result->col3, spu_splats(0.0f) ); +} + +static inline void vmathSoaT3MakeRotationZ( VmathSoaTransform3 *result, vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + vmathSoaV3MakeFromElems( &result->col0, c, s, spu_splats(0.0f) ); + vmathSoaV3MakeFromElems( &result->col1, negatef4( s ), c, spu_splats(0.0f) ); + vmathSoaV3MakeZAxis( &result->col2 ); + vmathSoaV3MakeFromScalar( &result->col3, spu_splats(0.0f) ); +} + +static inline void vmathSoaT3MakeRotationZYX( VmathSoaTransform3 *result, const VmathSoaVector3 *radiansXYZ ) +{ + vec_float4 sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sincosf4( radiansXYZ->x, &sX, &cX ); + sincosf4( radiansXYZ->y, &sY, &cY ); + sincosf4( radiansXYZ->z, &sZ, &cZ ); + tmp0 = spu_mul( cZ, sY ); + tmp1 = spu_mul( sZ, sY ); + vmathSoaV3MakeFromElems( &result->col0, spu_mul( cZ, cY ), spu_mul( sZ, cY ), negatef4( sY ) ); + vmathSoaV3MakeFromElems( &result->col1, spu_sub( spu_mul( tmp0, sX ), spu_mul( sZ, cX ) ), spu_add( spu_mul( tmp1, sX ), spu_mul( cZ, cX ) ), spu_mul( cY, sX ) ); + vmathSoaV3MakeFromElems( &result->col2, spu_add( spu_mul( tmp0, cX ), spu_mul( sZ, sX ) ), spu_sub( spu_mul( tmp1, cX ), spu_mul( cZ, sX ) ), spu_mul( cY, cX ) ); + vmathSoaV3MakeFromScalar( &result->col3, spu_splats(0.0f) ); +} + +static inline void vmathSoaT3MakeRotationAxis( VmathSoaTransform3 *result, vec_float4 radians, const VmathSoaVector3 *unitVec ) +{ + VmathSoaMatrix3 tmpM3_0; + VmathSoaVector3 tmpV3_0; + vmathSoaM3MakeRotationAxis( &tmpM3_0, radians, unitVec ); + vmathSoaV3MakeFromScalar( &tmpV3_0, spu_splats(0.0f) ); + vmathSoaT3MakeFromM3V3( result, &tmpM3_0, &tmpV3_0 ); +} + +static inline void vmathSoaT3MakeRotationQ( VmathSoaTransform3 *result, const VmathSoaQuat *unitQuat ) +{ + VmathSoaMatrix3 tmpM3_0; + VmathSoaVector3 tmpV3_0; + vmathSoaM3MakeFromQ( &tmpM3_0, unitQuat ); + vmathSoaV3MakeFromScalar( &tmpV3_0, spu_splats(0.0f) ); + vmathSoaT3MakeFromM3V3( result, &tmpM3_0, &tmpV3_0 ); +} + +static inline void vmathSoaT3MakeScale( VmathSoaTransform3 *result, const VmathSoaVector3 *scaleVec ) +{ + vmathSoaV3MakeFromElems( &result->col0, scaleVec->x, spu_splats(0.0f), spu_splats(0.0f) ); + vmathSoaV3MakeFromElems( &result->col1, spu_splats(0.0f), scaleVec->y, spu_splats(0.0f) ); + vmathSoaV3MakeFromElems( &result->col2, spu_splats(0.0f), spu_splats(0.0f), scaleVec->z ); + vmathSoaV3MakeFromScalar( &result->col3, spu_splats(0.0f) ); +} + +static inline void vmathSoaT3AppendScale( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm, const VmathSoaVector3 *scaleVec ) +{ + vmathSoaV3ScalarMul( &result->col0, &tfrm->col0, vmathSoaV3GetX( scaleVec ) ); + vmathSoaV3ScalarMul( &result->col1, &tfrm->col1, vmathSoaV3GetY( scaleVec ) ); + vmathSoaV3ScalarMul( &result->col2, &tfrm->col2, vmathSoaV3GetZ( scaleVec ) ); + vmathSoaV3Copy( &result->col3, &tfrm->col3 ); +} + +static inline void vmathSoaT3PrependScale( VmathSoaTransform3 *result, const VmathSoaVector3 *scaleVec, const VmathSoaTransform3 *tfrm ) +{ + vmathSoaV3MulPerElem( &result->col0, &tfrm->col0, scaleVec ); + vmathSoaV3MulPerElem( &result->col1, &tfrm->col1, scaleVec ); + vmathSoaV3MulPerElem( &result->col2, &tfrm->col2, scaleVec ); + vmathSoaV3MulPerElem( &result->col3, &tfrm->col3, scaleVec ); +} + +static inline void vmathSoaT3MakeTranslation( VmathSoaTransform3 *result, const VmathSoaVector3 *translateVec ) +{ + vmathSoaV3MakeXAxis( &result->col0 ); + vmathSoaV3MakeYAxis( &result->col1 ); + vmathSoaV3MakeZAxis( &result->col2 ); + vmathSoaV3Copy( &result->col3, translateVec ); +} + +static inline void vmathSoaT3Select( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm0, const VmathSoaTransform3 *tfrm1, vec_uint4 select1 ) +{ + vmathSoaV3Select( &result->col0, &tfrm0->col0, &tfrm1->col0, select1 ); + vmathSoaV3Select( &result->col1, &tfrm0->col1, &tfrm1->col1, select1 ); + vmathSoaV3Select( &result->col2, &tfrm0->col2, &tfrm1->col2, select1 ); + vmathSoaV3Select( &result->col3, &tfrm0->col3, &tfrm1->col3, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaT3Print( const VmathSoaTransform3 *tfrm ) +{ + VmathTransform3 mat0, mat1, mat2, mat3; + vmathSoaT3Get4Aos( tfrm, &mat0, &mat1, &mat2, &mat3 ); + printf("slot 0:\n"); + vmathT3Print( &mat0 ); + printf("slot 1:\n"); + vmathT3Print( &mat1 ); + printf("slot 2:\n"); + vmathT3Print( &mat2 ); + printf("slot 3:\n"); + vmathT3Print( &mat3 ); +} + +static inline void vmathSoaT3Prints( const VmathSoaTransform3 *tfrm, const char *name ) +{ + printf("%s:\n", name); + vmathSoaT3Print( tfrm ); +} + +#endif + +static inline void vmathSoaQMakeFromM3( VmathSoaQuat *result, const VmathSoaMatrix3 *tfrm ) +{ + vec_float4 trace, radicand, scale, xx, yx, zx, xy, yy, zy, xz, yz, zz, tmpx, tmpy, tmpz, tmpw, qx, qy, qz, qw; + vec_uint4 negTrace, ZgtX, ZgtY, YgtX; + vec_uint4 largestXorY, largestYorZ, largestZorX; + + xx = tfrm->col0.x; + yx = tfrm->col0.y; + zx = tfrm->col0.z; + xy = tfrm->col1.x; + yy = tfrm->col1.y; + zy = tfrm->col1.z; + xz = tfrm->col2.x; + yz = tfrm->col2.y; + zz = tfrm->col2.z; + + trace = spu_add( spu_add( xx, yy ), zz ); + + negTrace = spu_cmpgt( spu_splats(0.0f), trace ); + ZgtX = spu_cmpgt( zz, xx ); + ZgtY = spu_cmpgt( zz, yy ); + YgtX = spu_cmpgt( yy, xx ); + largestXorY = spu_and( negTrace, spu_nand( ZgtX, ZgtY ) ); + largestYorZ = spu_and( negTrace, spu_or( YgtX, ZgtX ) ); + largestZorX = spu_and( negTrace, spu_orc( ZgtY, YgtX ) ); + + zz = spu_sel( zz, negatef4(zz), largestXorY ); + xy = spu_sel( xy, negatef4(xy), largestXorY ); + xx = spu_sel( xx, negatef4(xx), largestYorZ ); + yz = spu_sel( yz, negatef4(yz), largestYorZ ); + yy = spu_sel( yy, negatef4(yy), largestZorX ); + zx = spu_sel( zx, negatef4(zx), largestZorX ); + + radicand = spu_add( spu_add( spu_add( xx, yy ), zz ), spu_splats(1.0f) ); + scale = spu_mul( spu_splats(0.5f), rsqrtf4( radicand ) ); + + tmpx = spu_mul( spu_sub( zy, yz ), scale ); + tmpy = spu_mul( spu_sub( xz, zx ), scale ); + tmpz = spu_mul( spu_sub( yx, xy ), scale ); + tmpw = spu_mul( radicand, scale ); + qx = tmpx; + qy = tmpy; + qz = tmpz; + qw = tmpw; + + qx = spu_sel( qx, tmpw, largestXorY ); + qy = spu_sel( qy, tmpz, largestXorY ); + qz = spu_sel( qz, tmpy, largestXorY ); + qw = spu_sel( qw, tmpx, largestXorY ); + tmpx = qx; + tmpz = qz; + qx = spu_sel( qx, qy, largestYorZ ); + qy = spu_sel( qy, tmpx, largestYorZ ); + qz = spu_sel( qz, qw, largestYorZ ); + qw = spu_sel( qw, tmpz, largestYorZ ); + + result->x = qx; + result->y = qy; + result->z = qz; + result->w = qw; +} + +static inline void vmathSoaV3Outer( VmathSoaMatrix3 *result, const VmathSoaVector3 *tfrm0, const VmathSoaVector3 *tfrm1 ) +{ + vmathSoaV3ScalarMul( &result->col0, tfrm0, vmathSoaV3GetX( tfrm1 ) ); + vmathSoaV3ScalarMul( &result->col1, tfrm0, vmathSoaV3GetY( tfrm1 ) ); + vmathSoaV3ScalarMul( &result->col2, tfrm0, vmathSoaV3GetZ( tfrm1 ) ); +} + +static inline void vmathSoaV4Outer( VmathSoaMatrix4 *result, const VmathSoaVector4 *tfrm0, const VmathSoaVector4 *tfrm1 ) +{ + vmathSoaV4ScalarMul( &result->col0, tfrm0, vmathSoaV4GetX( tfrm1 ) ); + vmathSoaV4ScalarMul( &result->col1, tfrm0, vmathSoaV4GetY( tfrm1 ) ); + vmathSoaV4ScalarMul( &result->col2, tfrm0, vmathSoaV4GetZ( tfrm1 ) ); + vmathSoaV4ScalarMul( &result->col3, tfrm0, vmathSoaV4GetW( tfrm1 ) ); +} + +static inline void vmathSoaV3RowMul( VmathSoaVector3 *result, const VmathSoaVector3 *vec, const VmathSoaMatrix3 *mat ) +{ + vec_float4 tmpX, tmpY, tmpZ; + tmpX = spu_add( spu_add( spu_mul( vec->x, mat->col0.x ), spu_mul( vec->y, mat->col0.y ) ), spu_mul( vec->z, mat->col0.z ) ); + tmpY = spu_add( spu_add( spu_mul( vec->x, mat->col1.x ), spu_mul( vec->y, mat->col1.y ) ), spu_mul( vec->z, mat->col1.z ) ); + tmpZ = spu_add( spu_add( spu_mul( vec->x, mat->col2.x ), spu_mul( vec->y, mat->col2.y ) ), spu_mul( vec->z, mat->col2.z ) ); + vmathSoaV3MakeFromElems( result, tmpX, tmpY, tmpZ ); +} + +static inline void vmathSoaV3CrossMatrix( VmathSoaMatrix3 *result, const VmathSoaVector3 *vec ) +{ + vmathSoaV3MakeFromElems( &result->col0, spu_splats(0.0f), vec->z, negatef4( vec->y ) ); + vmathSoaV3MakeFromElems( &result->col1, negatef4( vec->z ), spu_splats(0.0f), vec->x ); + vmathSoaV3MakeFromElems( &result->col2, vec->y, negatef4( vec->x ), spu_splats(0.0f) ); +} + +static inline void vmathSoaV3CrossMatrixMul( VmathSoaMatrix3 *result, const VmathSoaVector3 *vec, const VmathSoaMatrix3 *mat ) +{ + VmathSoaVector3 tmpV3_0, tmpV3_1, tmpV3_2; + vmathSoaV3Cross( &tmpV3_0, vec, &mat->col0 ); + vmathSoaV3Cross( &tmpV3_1, vec, &mat->col1 ); + vmathSoaV3Cross( &tmpV3_2, vec, &mat->col2 ); + vmathSoaM3MakeFromCols( result, &tmpV3_0, &tmpV3_1, &tmpV3_2 ); +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/c/mat_soa_v.h b/Extras/vectormathlibrary/include/vectormath/spu/c/mat_soa_v.h new file mode 100644 index 0000000..c8401e3 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/c/mat_soa_v.h @@ -0,0 +1,1063 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_SOA_V_C_H +#define _VECTORMATH_MAT_SOA_V_C_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + */ +#define _VECTORMATH_PI_OVER_2 1.570796327f + +/*----------------------------------------------------------------------------- + * Definitions + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeFromScalar_V( vec_float4 scalar ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeFromQ_V( VmathSoaQuat unitQuat ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeFromQ(&result, &unitQuat); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeFromCols_V( VmathSoaVector3 _col0, VmathSoaVector3 _col1, VmathSoaVector3 _col2 ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeFromCols(&result, &_col0, &_col1, &_col2); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeFromAos_V( VmathMatrix3 mat ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeFromAos(&result, &mat); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeFrom4Aos_V( VmathMatrix3 mat0, VmathMatrix3 mat1, VmathMatrix3 mat2, VmathMatrix3 mat3 ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeFrom4Aos(&result, &mat0, &mat1, &mat2, &mat3); + return result; +} + +static inline void vmathSoaM3Get4Aos_V( VmathSoaMatrix3 mat, VmathMatrix3 *result0, VmathMatrix3 *result1, VmathMatrix3 *result2, VmathMatrix3 *result3 ) +{ + vmathSoaM3Get4Aos(&mat, result0, result1, result2, result3); +} + +static inline void vmathSoaM3SetCol0_V( VmathSoaMatrix3 *result, VmathSoaVector3 _col0 ) +{ + vmathSoaM3SetCol0(result, &_col0); +} + +static inline void vmathSoaM3SetCol1_V( VmathSoaMatrix3 *result, VmathSoaVector3 _col1 ) +{ + vmathSoaM3SetCol1(result, &_col1); +} + +static inline void vmathSoaM3SetCol2_V( VmathSoaMatrix3 *result, VmathSoaVector3 _col2 ) +{ + vmathSoaM3SetCol2(result, &_col2); +} + +static inline void vmathSoaM3SetCol_V( VmathSoaMatrix3 *result, int col, VmathSoaVector3 vec ) +{ + vmathSoaM3SetCol(result, col, &vec); +} + +static inline void vmathSoaM3SetRow_V( VmathSoaMatrix3 *result, int row, VmathSoaVector3 vec ) +{ + vmathSoaM3SetRow(result, row, &vec); +} + +static inline void vmathSoaM3SetElem_V( VmathSoaMatrix3 *result, int col, int row, vec_float4 val ) +{ + vmathSoaM3SetElem(result, col, row, val); +} + +static inline vec_float4 vmathSoaM3GetElem_V( VmathSoaMatrix3 mat, int col, int row ) +{ + return vmathSoaM3GetElem(&mat, col, row); +} + +static inline VmathSoaVector3 vmathSoaM3GetCol0_V( VmathSoaMatrix3 mat ) +{ + VmathSoaVector3 result; + vmathSoaM3GetCol0(&result, &mat); + return result; +} + +static inline VmathSoaVector3 vmathSoaM3GetCol1_V( VmathSoaMatrix3 mat ) +{ + VmathSoaVector3 result; + vmathSoaM3GetCol1(&result, &mat); + return result; +} + +static inline VmathSoaVector3 vmathSoaM3GetCol2_V( VmathSoaMatrix3 mat ) +{ + VmathSoaVector3 result; + vmathSoaM3GetCol2(&result, &mat); + return result; +} + +static inline VmathSoaVector3 vmathSoaM3GetCol_V( VmathSoaMatrix3 mat, int col ) +{ + VmathSoaVector3 result; + vmathSoaM3GetCol(&result, &mat, col); + return result; +} + +static inline VmathSoaVector3 vmathSoaM3GetRow_V( VmathSoaMatrix3 mat, int row ) +{ + VmathSoaVector3 result; + vmathSoaM3GetRow(&result, &mat, row); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3Transpose_V( VmathSoaMatrix3 mat ) +{ + VmathSoaMatrix3 result; + vmathSoaM3Transpose(&result, &mat); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3Inverse_V( VmathSoaMatrix3 mat ) +{ + VmathSoaMatrix3 result; + vmathSoaM3Inverse(&result, &mat); + return result; +} + +static inline vec_float4 vmathSoaM3Determinant_V( VmathSoaMatrix3 mat ) +{ + return vmathSoaM3Determinant(&mat); +} + +static inline VmathSoaMatrix3 vmathSoaM3Add_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1 ) +{ + VmathSoaMatrix3 result; + vmathSoaM3Add(&result, &mat0, &mat1); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3Sub_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1 ) +{ + VmathSoaMatrix3 result; + vmathSoaM3Sub(&result, &mat0, &mat1); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3Neg_V( VmathSoaMatrix3 mat ) +{ + VmathSoaMatrix3 result; + vmathSoaM3Neg(&result, &mat); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3AbsPerElem_V( VmathSoaMatrix3 mat ) +{ + VmathSoaMatrix3 result; + vmathSoaM3AbsPerElem(&result, &mat); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3ScalarMul_V( VmathSoaMatrix3 mat, vec_float4 scalar ) +{ + VmathSoaMatrix3 result; + vmathSoaM3ScalarMul(&result, &mat, scalar); + return result; +} + +static inline VmathSoaVector3 vmathSoaM3MulV3_V( VmathSoaMatrix3 mat, VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaM3MulV3(&result, &mat, &vec); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3Mul_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1 ) +{ + VmathSoaMatrix3 result; + vmathSoaM3Mul(&result, &mat0, &mat1); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MulPerElem_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1 ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MulPerElem(&result, &mat0, &mat1); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeIdentity_V( ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeIdentity(&result); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationX_V( vec_float4 radians ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeRotationX(&result, radians); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationY_V( vec_float4 radians ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeRotationY(&result, radians); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationZ_V( vec_float4 radians ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeRotationZ(&result, radians); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationZYX_V( VmathSoaVector3 radiansXYZ ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeRotationZYX(&result, &radiansXYZ); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationAxis_V( vec_float4 radians, VmathSoaVector3 unitVec ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationQ_V( VmathSoaQuat unitQuat ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeRotationQ(&result, &unitQuat); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3MakeScale_V( VmathSoaVector3 scaleVec ) +{ + VmathSoaMatrix3 result; + vmathSoaM3MakeScale(&result, &scaleVec); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3AppendScale_V( VmathSoaMatrix3 mat, VmathSoaVector3 scaleVec ) +{ + VmathSoaMatrix3 result; + vmathSoaM3AppendScale(&result, &mat, &scaleVec); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3PrependScale_V( VmathSoaVector3 scaleVec, VmathSoaMatrix3 mat ) +{ + VmathSoaMatrix3 result; + vmathSoaM3PrependScale(&result, &scaleVec, &mat); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaM3Select_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1, vec_uint4 select1 ) +{ + VmathSoaMatrix3 result; + vmathSoaM3Select(&result, &mat0, &mat1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaM3Print_V( VmathSoaMatrix3 mat ) +{ + vmathSoaM3Print(&mat); +} + +static inline void vmathSoaM3Prints_V( VmathSoaMatrix3 mat, const char *name ) +{ + vmathSoaM3Prints(&mat, name); +} + +#endif + +static inline VmathSoaMatrix4 vmathSoaM4MakeFromScalar_V( vec_float4 scalar ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeFromT3_V( VmathSoaTransform3 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeFromT3(&result, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeFromCols_V( VmathSoaVector4 _col0, VmathSoaVector4 _col1, VmathSoaVector4 _col2, VmathSoaVector4 _col3 ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeFromCols(&result, &_col0, &_col1, &_col2, &_col3); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeFromM3V3_V( VmathSoaMatrix3 mat, VmathSoaVector3 translateVec ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeFromM3V3(&result, &mat, &translateVec); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeFromQV3_V( VmathSoaQuat unitQuat, VmathSoaVector3 translateVec ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeFromQV3(&result, &unitQuat, &translateVec); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeFromAos_V( VmathMatrix4 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeFromAos(&result, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeFrom4Aos_V( VmathMatrix4 mat0, VmathMatrix4 mat1, VmathMatrix4 mat2, VmathMatrix4 mat3 ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeFrom4Aos(&result, &mat0, &mat1, &mat2, &mat3); + return result; +} + +static inline void vmathSoaM4Get4Aos_V( VmathSoaMatrix4 mat, VmathMatrix4 *result0, VmathMatrix4 *result1, VmathMatrix4 *result2, VmathMatrix4 *result3 ) +{ + vmathSoaM4Get4Aos(&mat, result0, result1, result2, result3); +} + +static inline void vmathSoaM4SetCol0_V( VmathSoaMatrix4 *result, VmathSoaVector4 _col0 ) +{ + vmathSoaM4SetCol0(result, &_col0); +} + +static inline void vmathSoaM4SetCol1_V( VmathSoaMatrix4 *result, VmathSoaVector4 _col1 ) +{ + vmathSoaM4SetCol1(result, &_col1); +} + +static inline void vmathSoaM4SetCol2_V( VmathSoaMatrix4 *result, VmathSoaVector4 _col2 ) +{ + vmathSoaM4SetCol2(result, &_col2); +} + +static inline void vmathSoaM4SetCol3_V( VmathSoaMatrix4 *result, VmathSoaVector4 _col3 ) +{ + vmathSoaM4SetCol3(result, &_col3); +} + +static inline void vmathSoaM4SetCol_V( VmathSoaMatrix4 *result, int col, VmathSoaVector4 vec ) +{ + vmathSoaM4SetCol(result, col, &vec); +} + +static inline void vmathSoaM4SetRow_V( VmathSoaMatrix4 *result, int row, VmathSoaVector4 vec ) +{ + vmathSoaM4SetRow(result, row, &vec); +} + +static inline void vmathSoaM4SetElem_V( VmathSoaMatrix4 *result, int col, int row, vec_float4 val ) +{ + vmathSoaM4SetElem(result, col, row, val); +} + +static inline vec_float4 vmathSoaM4GetElem_V( VmathSoaMatrix4 mat, int col, int row ) +{ + return vmathSoaM4GetElem(&mat, col, row); +} + +static inline VmathSoaVector4 vmathSoaM4GetCol0_V( VmathSoaMatrix4 mat ) +{ + VmathSoaVector4 result; + vmathSoaM4GetCol0(&result, &mat); + return result; +} + +static inline VmathSoaVector4 vmathSoaM4GetCol1_V( VmathSoaMatrix4 mat ) +{ + VmathSoaVector4 result; + vmathSoaM4GetCol1(&result, &mat); + return result; +} + +static inline VmathSoaVector4 vmathSoaM4GetCol2_V( VmathSoaMatrix4 mat ) +{ + VmathSoaVector4 result; + vmathSoaM4GetCol2(&result, &mat); + return result; +} + +static inline VmathSoaVector4 vmathSoaM4GetCol3_V( VmathSoaMatrix4 mat ) +{ + VmathSoaVector4 result; + vmathSoaM4GetCol3(&result, &mat); + return result; +} + +static inline VmathSoaVector4 vmathSoaM4GetCol_V( VmathSoaMatrix4 mat, int col ) +{ + VmathSoaVector4 result; + vmathSoaM4GetCol(&result, &mat, col); + return result; +} + +static inline VmathSoaVector4 vmathSoaM4GetRow_V( VmathSoaMatrix4 mat, int row ) +{ + VmathSoaVector4 result; + vmathSoaM4GetRow(&result, &mat, row); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4Transpose_V( VmathSoaMatrix4 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4Transpose(&result, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4Inverse_V( VmathSoaMatrix4 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4Inverse(&result, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4AffineInverse_V( VmathSoaMatrix4 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4AffineInverse(&result, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4OrthoInverse_V( VmathSoaMatrix4 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4OrthoInverse(&result, &mat); + return result; +} + +static inline vec_float4 vmathSoaM4Determinant_V( VmathSoaMatrix4 mat ) +{ + return vmathSoaM4Determinant(&mat); +} + +static inline VmathSoaMatrix4 vmathSoaM4Add_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1 ) +{ + VmathSoaMatrix4 result; + vmathSoaM4Add(&result, &mat0, &mat1); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4Sub_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1 ) +{ + VmathSoaMatrix4 result; + vmathSoaM4Sub(&result, &mat0, &mat1); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4Neg_V( VmathSoaMatrix4 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4Neg(&result, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4AbsPerElem_V( VmathSoaMatrix4 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4AbsPerElem(&result, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4ScalarMul_V( VmathSoaMatrix4 mat, vec_float4 scalar ) +{ + VmathSoaMatrix4 result; + vmathSoaM4ScalarMul(&result, &mat, scalar); + return result; +} + +static inline VmathSoaVector4 vmathSoaM4MulV4_V( VmathSoaMatrix4 mat, VmathSoaVector4 vec ) +{ + VmathSoaVector4 result; + vmathSoaM4MulV4(&result, &mat, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaM4MulV3_V( VmathSoaMatrix4 mat, VmathSoaVector3 vec ) +{ + VmathSoaVector4 result; + vmathSoaM4MulV3(&result, &mat, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaM4MulP3_V( VmathSoaMatrix4 mat, VmathSoaPoint3 pnt ) +{ + VmathSoaVector4 result; + vmathSoaM4MulP3(&result, &mat, &pnt); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4Mul_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1 ) +{ + VmathSoaMatrix4 result; + vmathSoaM4Mul(&result, &mat0, &mat1); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MulT3_V( VmathSoaMatrix4 mat, VmathSoaTransform3 tfrm1 ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MulT3(&result, &mat, &tfrm1); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MulPerElem_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1 ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MulPerElem(&result, &mat0, &mat1); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeIdentity_V( ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeIdentity(&result); + return result; +} + +static inline void vmathSoaM4SetUpper3x3_V( VmathSoaMatrix4 *result, VmathSoaMatrix3 mat3 ) +{ + vmathSoaM4SetUpper3x3(result, &mat3); +} + +static inline VmathSoaMatrix3 vmathSoaM4GetUpper3x3_V( VmathSoaMatrix4 mat ) +{ + VmathSoaMatrix3 result; + vmathSoaM4GetUpper3x3(&result, &mat); + return result; +} + +static inline void vmathSoaM4SetTranslation_V( VmathSoaMatrix4 *result, VmathSoaVector3 translateVec ) +{ + vmathSoaM4SetTranslation(result, &translateVec); +} + +static inline VmathSoaVector3 vmathSoaM4GetTranslation_V( VmathSoaMatrix4 mat ) +{ + VmathSoaVector3 result; + vmathSoaM4GetTranslation(&result, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationX_V( vec_float4 radians ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeRotationX(&result, radians); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationY_V( vec_float4 radians ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeRotationY(&result, radians); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationZ_V( vec_float4 radians ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeRotationZ(&result, radians); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationZYX_V( VmathSoaVector3 radiansXYZ ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeRotationZYX(&result, &radiansXYZ); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationAxis_V( vec_float4 radians, VmathSoaVector3 unitVec ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationQ_V( VmathSoaQuat unitQuat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeRotationQ(&result, &unitQuat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeScale_V( VmathSoaVector3 scaleVec ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeScale(&result, &scaleVec); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4AppendScale_V( VmathSoaMatrix4 mat, VmathSoaVector3 scaleVec ) +{ + VmathSoaMatrix4 result; + vmathSoaM4AppendScale(&result, &mat, &scaleVec); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4PrependScale_V( VmathSoaVector3 scaleVec, VmathSoaMatrix4 mat ) +{ + VmathSoaMatrix4 result; + vmathSoaM4PrependScale(&result, &scaleVec, &mat); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeTranslation_V( VmathSoaVector3 translateVec ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeTranslation(&result, &translateVec); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeLookAt_V( VmathSoaPoint3 eyePos, VmathSoaPoint3 lookAtPos, VmathSoaVector3 upVec ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeLookAt(&result, &eyePos, &lookAtPos, &upVec); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakePerspective_V( vec_float4 fovyRadians, vec_float4 aspect, vec_float4 zNear, vec_float4 zFar ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakePerspective(&result, fovyRadians, aspect, zNear, zFar); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeFrustum_V( vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeFrustum(&result, left, right, bottom, top, zNear, zFar); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4MakeOrthographic_V( vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ) +{ + VmathSoaMatrix4 result; + vmathSoaM4MakeOrthographic(&result, left, right, bottom, top, zNear, zFar); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaM4Select_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1, vec_uint4 select1 ) +{ + VmathSoaMatrix4 result; + vmathSoaM4Select(&result, &mat0, &mat1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaM4Print_V( VmathSoaMatrix4 mat ) +{ + vmathSoaM4Print(&mat); +} + +static inline void vmathSoaM4Prints_V( VmathSoaMatrix4 mat, const char *name ) +{ + vmathSoaM4Prints(&mat, name); +} + +#endif + +static inline VmathSoaTransform3 vmathSoaT3MakeFromScalar_V( vec_float4 scalar ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeFromCols_V( VmathSoaVector3 _col0, VmathSoaVector3 _col1, VmathSoaVector3 _col2, VmathSoaVector3 _col3 ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeFromCols(&result, &_col0, &_col1, &_col2, &_col3); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeFromM3V3_V( VmathSoaMatrix3 tfrm, VmathSoaVector3 translateVec ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeFromM3V3(&result, &tfrm, &translateVec); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeFromQV3_V( VmathSoaQuat unitQuat, VmathSoaVector3 translateVec ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeFromQV3(&result, &unitQuat, &translateVec); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeFromAos_V( VmathTransform3 tfrm ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeFromAos(&result, &tfrm); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeFrom4Aos_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1, VmathTransform3 tfrm2, VmathTransform3 tfrm3 ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeFrom4Aos(&result, &tfrm0, &tfrm1, &tfrm2, &tfrm3); + return result; +} + +static inline void vmathSoaT3Get4Aos_V( VmathSoaTransform3 tfrm, VmathTransform3 *result0, VmathTransform3 *result1, VmathTransform3 *result2, VmathTransform3 *result3 ) +{ + vmathSoaT3Get4Aos(&tfrm, result0, result1, result2, result3); +} + +static inline void vmathSoaT3SetCol0_V( VmathSoaTransform3 *result, VmathSoaVector3 _col0 ) +{ + vmathSoaT3SetCol0(result, &_col0); +} + +static inline void vmathSoaT3SetCol1_V( VmathSoaTransform3 *result, VmathSoaVector3 _col1 ) +{ + vmathSoaT3SetCol1(result, &_col1); +} + +static inline void vmathSoaT3SetCol2_V( VmathSoaTransform3 *result, VmathSoaVector3 _col2 ) +{ + vmathSoaT3SetCol2(result, &_col2); +} + +static inline void vmathSoaT3SetCol3_V( VmathSoaTransform3 *result, VmathSoaVector3 _col3 ) +{ + vmathSoaT3SetCol3(result, &_col3); +} + +static inline void vmathSoaT3SetCol_V( VmathSoaTransform3 *result, int col, VmathSoaVector3 vec ) +{ + vmathSoaT3SetCol(result, col, &vec); +} + +static inline void vmathSoaT3SetRow_V( VmathSoaTransform3 *result, int row, VmathSoaVector4 vec ) +{ + vmathSoaT3SetRow(result, row, &vec); +} + +static inline void vmathSoaT3SetElem_V( VmathSoaTransform3 *result, int col, int row, vec_float4 val ) +{ + vmathSoaT3SetElem(result, col, row, val); +} + +static inline vec_float4 vmathSoaT3GetElem_V( VmathSoaTransform3 tfrm, int col, int row ) +{ + return vmathSoaT3GetElem(&tfrm, col, row); +} + +static inline VmathSoaVector3 vmathSoaT3GetCol0_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaVector3 result; + vmathSoaT3GetCol0(&result, &tfrm); + return result; +} + +static inline VmathSoaVector3 vmathSoaT3GetCol1_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaVector3 result; + vmathSoaT3GetCol1(&result, &tfrm); + return result; +} + +static inline VmathSoaVector3 vmathSoaT3GetCol2_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaVector3 result; + vmathSoaT3GetCol2(&result, &tfrm); + return result; +} + +static inline VmathSoaVector3 vmathSoaT3GetCol3_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaVector3 result; + vmathSoaT3GetCol3(&result, &tfrm); + return result; +} + +static inline VmathSoaVector3 vmathSoaT3GetCol_V( VmathSoaTransform3 tfrm, int col ) +{ + VmathSoaVector3 result; + vmathSoaT3GetCol(&result, &tfrm, col); + return result; +} + +static inline VmathSoaVector4 vmathSoaT3GetRow_V( VmathSoaTransform3 tfrm, int row ) +{ + VmathSoaVector4 result; + vmathSoaT3GetRow(&result, &tfrm, row); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3Inverse_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaTransform3 result; + vmathSoaT3Inverse(&result, &tfrm); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3OrthoInverse_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaTransform3 result; + vmathSoaT3OrthoInverse(&result, &tfrm); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3AbsPerElem_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaTransform3 result; + vmathSoaT3AbsPerElem(&result, &tfrm); + return result; +} + +static inline VmathSoaVector3 vmathSoaT3MulV3_V( VmathSoaTransform3 tfrm, VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaT3MulV3(&result, &tfrm, &vec); + return result; +} + +static inline VmathSoaPoint3 vmathSoaT3MulP3_V( VmathSoaTransform3 tfrm, VmathSoaPoint3 pnt ) +{ + VmathSoaPoint3 result; + vmathSoaT3MulP3(&result, &tfrm, &pnt); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3Mul_V( VmathSoaTransform3 tfrm0, VmathSoaTransform3 tfrm1 ) +{ + VmathSoaTransform3 result; + vmathSoaT3Mul(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MulPerElem_V( VmathSoaTransform3 tfrm0, VmathSoaTransform3 tfrm1 ) +{ + VmathSoaTransform3 result; + vmathSoaT3MulPerElem(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeIdentity_V( ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeIdentity(&result); + return result; +} + +static inline void vmathSoaT3SetUpper3x3_V( VmathSoaTransform3 *result, VmathSoaMatrix3 tfrm ) +{ + vmathSoaT3SetUpper3x3(result, &tfrm); +} + +static inline VmathSoaMatrix3 vmathSoaT3GetUpper3x3_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaMatrix3 result; + vmathSoaT3GetUpper3x3(&result, &tfrm); + return result; +} + +static inline void vmathSoaT3SetTranslation_V( VmathSoaTransform3 *result, VmathSoaVector3 translateVec ) +{ + vmathSoaT3SetTranslation(result, &translateVec); +} + +static inline VmathSoaVector3 vmathSoaT3GetTranslation_V( VmathSoaTransform3 tfrm ) +{ + VmathSoaVector3 result; + vmathSoaT3GetTranslation(&result, &tfrm); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeRotationX_V( vec_float4 radians ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeRotationX(&result, radians); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeRotationY_V( vec_float4 radians ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeRotationY(&result, radians); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeRotationZ_V( vec_float4 radians ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeRotationZ(&result, radians); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeRotationZYX_V( VmathSoaVector3 radiansXYZ ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeRotationZYX(&result, &radiansXYZ); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeRotationAxis_V( vec_float4 radians, VmathSoaVector3 unitVec ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeRotationQ_V( VmathSoaQuat unitQuat ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeRotationQ(&result, &unitQuat); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeScale_V( VmathSoaVector3 scaleVec ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeScale(&result, &scaleVec); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3AppendScale_V( VmathSoaTransform3 tfrm, VmathSoaVector3 scaleVec ) +{ + VmathSoaTransform3 result; + vmathSoaT3AppendScale(&result, &tfrm, &scaleVec); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3PrependScale_V( VmathSoaVector3 scaleVec, VmathSoaTransform3 tfrm ) +{ + VmathSoaTransform3 result; + vmathSoaT3PrependScale(&result, &scaleVec, &tfrm); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3MakeTranslation_V( VmathSoaVector3 translateVec ) +{ + VmathSoaTransform3 result; + vmathSoaT3MakeTranslation(&result, &translateVec); + return result; +} + +static inline VmathSoaTransform3 vmathSoaT3Select_V( VmathSoaTransform3 tfrm0, VmathSoaTransform3 tfrm1, vec_uint4 select1 ) +{ + VmathSoaTransform3 result; + vmathSoaT3Select(&result, &tfrm0, &tfrm1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaT3Print_V( VmathSoaTransform3 tfrm ) +{ + vmathSoaT3Print(&tfrm); +} + +static inline void vmathSoaT3Prints_V( VmathSoaTransform3 tfrm, const char *name ) +{ + vmathSoaT3Prints(&tfrm, name); +} + +#endif + +static inline VmathSoaQuat vmathSoaQMakeFromM3_V( VmathSoaMatrix3 tfrm ) +{ + VmathSoaQuat result; + vmathSoaQMakeFromM3(&result, &tfrm); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaV3Outer_V( VmathSoaVector3 tfrm0, VmathSoaVector3 tfrm1 ) +{ + VmathSoaMatrix3 result; + vmathSoaV3Outer(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathSoaMatrix4 vmathSoaV4Outer_V( VmathSoaVector4 tfrm0, VmathSoaVector4 tfrm1 ) +{ + VmathSoaMatrix4 result; + vmathSoaV4Outer(&result, &tfrm0, &tfrm1); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3RowMul_V( VmathSoaVector3 vec, VmathSoaMatrix3 mat ) +{ + VmathSoaVector3 result; + vmathSoaV3RowMul(&result, &vec, &mat); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaV3CrossMatrix_V( VmathSoaVector3 vec ) +{ + VmathSoaMatrix3 result; + vmathSoaV3CrossMatrix(&result, &vec); + return result; +} + +static inline VmathSoaMatrix3 vmathSoaV3CrossMatrixMul_V( VmathSoaVector3 vec, VmathSoaMatrix3 mat ) +{ + VmathSoaMatrix3 result; + vmathSoaV3CrossMatrixMul(&result, &vec, &mat); + return result; +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/c/quat_aos.h b/Extras/vectormathlibrary/include/vectormath/spu/c/quat_aos.h new file mode 100644 index 0000000..0f25d65 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/c/quat_aos.h @@ -0,0 +1,371 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_AOS_C_H +#define _VECTORMATH_QUAT_AOS_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline void vmathQCopy( VmathQuat *result, const VmathQuat *quat ) +{ + result->vec128 = quat->vec128; +} + +static inline void vmathQMakeFromElems( VmathQuat *result, float _x, float _y, float _z, float _w ) +{ + result->vec128 = (vec_float4){ _x, _y, _z, _w }; +} + +static inline void vmathQMakeFromV3Scalar( VmathQuat *result, const VmathVector3 *xyz, float _w ) +{ + result->vec128 = spu_shuffle( xyz->vec128, spu_promote( _w, 0 ), _VECTORMATH_SHUF_XYZA ); +} + +static inline void vmathQMakeFromV4( VmathQuat *result, const VmathVector4 *vec ) +{ + result->vec128 = vec->vec128; +} + +static inline void vmathQMakeFromScalar( VmathQuat *result, float scalar ) +{ + result->vec128 = spu_splats( scalar ); +} + +static inline void vmathQMakeFrom128( VmathQuat *result, vec_float4 vf4 ) +{ + result->vec128 = vf4; +} + +static inline void vmathQMakeIdentity( VmathQuat *result ) +{ + result->vec128 = _VECTORMATH_UNIT_0001; +} + +static inline void vmathQLerp( VmathQuat *result, float t, const VmathQuat *quat0, const VmathQuat *quat1 ) +{ + VmathQuat tmpQ_0, tmpQ_1; + vmathQSub( &tmpQ_0, quat1, quat0 ); + vmathQScalarMul( &tmpQ_1, &tmpQ_0, t ); + vmathQAdd( result, quat0, &tmpQ_1 ); +} + +static inline void vmathQSlerp( VmathQuat *result, float t, const VmathQuat *unitQuat0, const VmathQuat *unitQuat1 ) +{ + VmathQuat start; + vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + vec_uint4 selectMask; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + cosAngle = _vmathVfDot4( unitQuat0->vec128, unitQuat1->vec128 ); + cosAngle = spu_shuffle( cosAngle, cosAngle, shuffle_xxxx ); + selectMask = (vec_uint4)spu_cmpgt( spu_splats(0.0f), cosAngle ); + cosAngle = spu_sel( cosAngle, negatef4( cosAngle ), selectMask ); + start.vec128 = spu_sel( unitQuat0->vec128, negatef4( unitQuat0->vec128 ), selectMask ); + selectMask = (vec_uint4)spu_cmpgt( spu_splats(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = spu_splats(t); + oneMinusT = spu_sub( spu_splats(1.0f), tttt ); + angles = spu_sel( spu_splats(1.0f), oneMinusT, (vec_uint4)spu_maskb(0x0f00) ); + angles = spu_sel( angles, tttt, (vec_uint4)spu_maskb(0x00f0) ); + angles = spu_mul( angles, angle ); + sines = sinf4( angles ); + scales = divf4( sines, spu_shuffle( sines, sines, shuffle_xxxx ) ); + scale0 = spu_sel( oneMinusT, spu_shuffle( scales, scales, shuffle_yyyy ), selectMask ); + scale1 = spu_sel( tttt, spu_shuffle( scales, scales, shuffle_zzzz ), selectMask ); + result->vec128 = spu_madd( start.vec128, scale0, spu_mul( unitQuat1->vec128, scale1 ) ); +} + +static inline void vmathQSquad( VmathQuat *result, float t, const VmathQuat *unitQuat0, const VmathQuat *unitQuat1, const VmathQuat *unitQuat2, const VmathQuat *unitQuat3 ) +{ + VmathQuat tmp0, tmp1; + vmathQSlerp( &tmp0, t, unitQuat0, unitQuat3 ); + vmathQSlerp( &tmp1, t, unitQuat1, unitQuat2 ); + vmathQSlerp( result, ( ( 2.0f * t ) * ( 1.0f - t ) ), &tmp0, &tmp1 ); +} + +static inline vec_float4 vmathQGet128( const VmathQuat *quat ) +{ + return quat->vec128; +} + +static inline void vmathQSetXYZ( VmathQuat *result, const VmathVector3 *vec ) +{ + result->vec128 = spu_sel( vec->vec128, result->vec128, (vec_uint4)spu_maskb(0x000f) ); +} + +static inline void vmathQGetXYZ( VmathVector3 *result, const VmathQuat *quat ) +{ + result->vec128 = quat->vec128; +} + +static inline void vmathQSetX( VmathQuat *result, float _x ) +{ + result->vec128 = spu_insert( _x, result->vec128, 0 ); +} + +static inline float vmathQGetX( const VmathQuat *quat ) +{ + return spu_extract( quat->vec128, 0 ); +} + +static inline void vmathQSetY( VmathQuat *result, float _y ) +{ + result->vec128 = spu_insert( _y, result->vec128, 1 ); +} + +static inline float vmathQGetY( const VmathQuat *quat ) +{ + return spu_extract( quat->vec128, 1 ); +} + +static inline void vmathQSetZ( VmathQuat *result, float _z ) +{ + result->vec128 = spu_insert( _z, result->vec128, 2 ); +} + +static inline float vmathQGetZ( const VmathQuat *quat ) +{ + return spu_extract( quat->vec128, 2 ); +} + +static inline void vmathQSetW( VmathQuat *result, float _w ) +{ + result->vec128 = spu_insert( _w, result->vec128, 3 ); +} + +static inline float vmathQGetW( const VmathQuat *quat ) +{ + return spu_extract( quat->vec128, 3 ); +} + +static inline void vmathQSetElem( VmathQuat *result, int idx, float value ) +{ + result->vec128 = spu_insert( value, result->vec128, idx ); +} + +static inline float vmathQGetElem( const VmathQuat *quat, int idx ) +{ + return spu_extract( quat->vec128, idx ); +} + +static inline void vmathQAdd( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ) +{ + result->vec128 = spu_add( quat0->vec128, quat1->vec128 ); +} + +static inline void vmathQSub( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ) +{ + result->vec128 = spu_sub( quat0->vec128, quat1->vec128 ); +} + +static inline void vmathQScalarMul( VmathQuat *result, const VmathQuat *quat, float scalar ) +{ + result->vec128 = spu_mul( quat->vec128, spu_splats(scalar) ); +} + +static inline void vmathQScalarDiv( VmathQuat *result, const VmathQuat *quat, float scalar ) +{ + result->vec128 = divf4( quat->vec128, spu_splats(scalar) ); +} + +static inline void vmathQNeg( VmathQuat *result, const VmathQuat *quat ) +{ + result->vec128 = negatef4( quat->vec128 ); +} + +static inline float vmathQDot( const VmathQuat *quat0, const VmathQuat *quat1 ) +{ + return spu_extract( _vmathVfDot4( quat0->vec128, quat1->vec128 ), 0 ); +} + +static inline float vmathQNorm( const VmathQuat *quat ) +{ + return spu_extract( _vmathVfDot4( quat->vec128, quat->vec128 ), 0 ); +} + +static inline float vmathQLength( const VmathQuat *quat ) +{ + return sqrtf( vmathQNorm( quat ) ); +} + +static inline void vmathQNormalize( VmathQuat *result, const VmathQuat *quat ) +{ + vec_float4 dot = _vmathVfDot4( quat->vec128, quat->vec128 ); + result->vec128 = spu_mul( quat->vec128, rsqrtf4( dot ) ); +} + +static inline void vmathQMakeRotationArc( VmathQuat *result, const VmathVector3 *unitVec0, const VmathVector3 *unitVec1 ) +{ + VmathVector3 crossVec, tmpV3_0; + vec_float4 cosAngle, cosAngleX2Plus2, recipCosHalfAngleX2, cosHalfAngleX2, res; + cosAngle = _vmathVfDot3( unitVec0->vec128, unitVec1->vec128 ); + cosAngle = spu_shuffle( cosAngle, cosAngle, (vec_uchar16)spu_splats(0x00010203) ); + cosAngleX2Plus2 = spu_madd( cosAngle, spu_splats(2.0f), spu_splats(2.0f) ); + recipCosHalfAngleX2 = rsqrtf4( cosAngleX2Plus2 ); + cosHalfAngleX2 = spu_mul( recipCosHalfAngleX2, cosAngleX2Plus2 ); + vmathV3Cross( &tmpV3_0, unitVec0, unitVec1 ); + crossVec = tmpV3_0; + res = spu_mul( crossVec.vec128, recipCosHalfAngleX2 ); + res = spu_sel( res, spu_mul( cosHalfAngleX2, spu_splats(0.5f) ), (vec_uint4)spu_maskb(0x000f) ); + result->vec128 = res; +} + +static inline void vmathQMakeRotationAxis( VmathQuat *result, float radians, const VmathVector3 *unitVec ) +{ + vec_float4 s, c, angle, res; + angle = spu_mul( spu_splats(radians), spu_splats(0.5f) ); + sincosf4( angle, &s, &c ); + res = spu_sel( spu_mul( unitVec->vec128, s ), c, (vec_uint4)spu_maskb(0x000f) ); + result->vec128 = res; +} + +static inline void vmathQMakeRotationX( VmathQuat *result, float radians ) +{ + vec_float4 s, c, angle, res; + angle = spu_mul( spu_splats(radians), spu_splats(0.5f) ); + sincosf4( angle, &s, &c ); + res = spu_sel( spu_splats(0.0f), s, (vec_uint4)spu_maskb(0xf000) ); + res = spu_sel( res, c, (vec_uint4)spu_maskb(0x000f) ); + result->vec128 = res; +} + +static inline void vmathQMakeRotationY( VmathQuat *result, float radians ) +{ + vec_float4 s, c, angle, res; + angle = spu_mul( spu_splats(radians), spu_splats(0.5f) ); + sincosf4( angle, &s, &c ); + res = spu_sel( spu_splats(0.0f), s, (vec_uint4)spu_maskb(0x0f00) ); + res = spu_sel( res, c, (vec_uint4)spu_maskb(0x000f) ); + result->vec128 = res; +} + +static inline void vmathQMakeRotationZ( VmathQuat *result, float radians ) +{ + vec_float4 s, c, angle, res; + angle = spu_mul( spu_splats(radians), spu_splats(0.5f) ); + sincosf4( angle, &s, &c ); + res = spu_sel( spu_splats(0.0f), s, (vec_uint4)spu_maskb(0x00f0) ); + res = spu_sel( res, c, (vec_uint4)spu_maskb(0x000f) ); + result->vec128 = res; +} + +static inline void vmathQMul( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ) +{ + vec_float4 ldata, rdata, qv, tmp0, tmp1, tmp2, tmp3; + vec_float4 product, l_wxyz, r_wxyz, xy, qw; + ldata = quat0->vec128; + rdata = quat1->vec128; + vec_uchar16 shuffle_wwww = (vec_uchar16)spu_splats((int)0x0c0d0e0f); + tmp0 = spu_shuffle( ldata, ldata, _VECTORMATH_SHUF_YZXW ); + tmp1 = spu_shuffle( rdata, rdata, _VECTORMATH_SHUF_ZXYW ); + tmp2 = spu_shuffle( ldata, ldata, _VECTORMATH_SHUF_ZXYW ); + tmp3 = spu_shuffle( rdata, rdata, _VECTORMATH_SHUF_YZXW ); + qv = spu_mul( spu_shuffle( ldata, ldata, shuffle_wwww ), rdata ); + qv = spu_madd( spu_shuffle( rdata, rdata, shuffle_wwww ), ldata, qv ); + qv = spu_madd( tmp0, tmp1, qv ); + qv = spu_nmsub( tmp2, tmp3, qv ); + product = spu_mul( ldata, rdata ); + l_wxyz = spu_rlqwbyte( ldata, 12 ); + r_wxyz = spu_rlqwbyte( rdata, 12 ); + qw = spu_nmsub( l_wxyz, r_wxyz, product ); + xy = spu_madd( l_wxyz, r_wxyz, product ); + qw = spu_sub( qw, spu_rlqwbyte( xy, 8 ) ); + result->vec128 = spu_sel( qv, qw, (vec_uint4)spu_maskb( 0x000f ) ); +} + +static inline void vmathQRotate( VmathVector3 *result, const VmathQuat *quat, const VmathVector3 *vec ) +{ + vec_float4 qdata, vdata, product, tmp0, tmp1, tmp2, tmp3, wwww, qv, qw, res; + qdata = quat->vec128; + vdata = vec->vec128; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_wwww = (vec_uchar16)spu_splats((int)0x0c0d0e0f); + tmp0 = spu_shuffle( qdata, qdata, _VECTORMATH_SHUF_YZXW ); + tmp1 = spu_shuffle( vdata, vdata, _VECTORMATH_SHUF_ZXYW ); + tmp2 = spu_shuffle( qdata, qdata, _VECTORMATH_SHUF_ZXYW ); + tmp3 = spu_shuffle( vdata, vdata, _VECTORMATH_SHUF_YZXW ); + wwww = spu_shuffle( qdata, qdata, shuffle_wwww ); + qv = spu_mul( wwww, vdata ); + qv = spu_madd( tmp0, tmp1, qv ); + qv = spu_nmsub( tmp2, tmp3, qv ); + product = spu_mul( qdata, vdata ); + qw = spu_madd( spu_rlqwbyte( qdata, 4 ), spu_rlqwbyte( vdata, 4 ), product ); + qw = spu_add( spu_rlqwbyte( product, 8 ), qw ); + tmp1 = spu_shuffle( qv, qv, _VECTORMATH_SHUF_ZXYW ); + tmp3 = spu_shuffle( qv, qv, _VECTORMATH_SHUF_YZXW ); + res = spu_mul( spu_shuffle( qw, qw, shuffle_xxxx ), qdata ); + res = spu_madd( wwww, qv, res ); + res = spu_madd( tmp0, tmp1, res ); + res = spu_nmsub( tmp2, tmp3, res ); + result->vec128 = res; +} + +static inline void vmathQConj( VmathQuat *result, const VmathQuat *quat ) +{ + result->vec128 = spu_xor( quat->vec128, ((vec_float4)(vec_int4){0x80000000,0x80000000,0x80000000,0}) ); +} + +static inline void vmathQSelect( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1, unsigned int select1 ) +{ + result->vec128 = spu_sel( quat0->vec128, quat1->vec128, spu_splats( (unsigned int)-(select1 > 0) ) ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathQPrint( const VmathQuat *quat ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = quat->vec128; + printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +static inline void vmathQPrints( const VmathQuat *quat, const char *name ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = quat->vec128; + printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/c/quat_aos_v.h b/Extras/vectormathlibrary/include/vectormath/spu/c/quat_aos_v.h new file mode 100644 index 0000000..04cf6cc --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/c/quat_aos_v.h @@ -0,0 +1,312 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_AOS_V_C_H +#define _VECTORMATH_QUAT_AOS_V_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline VmathQuat vmathQMakeFromElems_V( float _x, float _y, float _z, float _w ) +{ + VmathQuat result; + vmathQMakeFromElems(&result, _x, _y, _z, _w); + return result; +} + +static inline VmathQuat vmathQMakeFromV3Scalar_V( VmathVector3 xyz, float _w ) +{ + VmathQuat result; + vmathQMakeFromV3Scalar(&result, &xyz, _w); + return result; +} + +static inline VmathQuat vmathQMakeFromV4_V( VmathVector4 vec ) +{ + VmathQuat result; + vmathQMakeFromV4(&result, &vec); + return result; +} + +static inline VmathQuat vmathQMakeFromScalar_V( float scalar ) +{ + VmathQuat result; + vmathQMakeFromScalar(&result, scalar); + return result; +} + +static inline VmathQuat vmathQMakeFrom128_V( vec_float4 vf4 ) +{ + VmathQuat result; + vmathQMakeFrom128(&result, vf4); + return result; +} + +static inline VmathQuat vmathQMakeIdentity_V( ) +{ + VmathQuat result; + vmathQMakeIdentity(&result); + return result; +} + +static inline VmathQuat vmathQLerp_V( float t, VmathQuat quat0, VmathQuat quat1 ) +{ + VmathQuat result; + vmathQLerp(&result, t, &quat0, &quat1); + return result; +} + +static inline VmathQuat vmathQSlerp_V( float t, VmathQuat unitQuat0, VmathQuat unitQuat1 ) +{ + VmathQuat result; + vmathQSlerp(&result, t, &unitQuat0, &unitQuat1); + return result; +} + +static inline VmathQuat vmathQSquad_V( float t, VmathQuat unitQuat0, VmathQuat unitQuat1, VmathQuat unitQuat2, VmathQuat unitQuat3 ) +{ + VmathQuat result; + vmathQSquad(&result, t, &unitQuat0, &unitQuat1, &unitQuat2, &unitQuat3); + return result; +} + +static inline vec_float4 vmathQGet128_V( VmathQuat quat ) +{ + return vmathQGet128(&quat); +} + +static inline void vmathQSetXYZ_V( VmathQuat *result, VmathVector3 vec ) +{ + vmathQSetXYZ(result, &vec); +} + +static inline VmathVector3 vmathQGetXYZ_V( VmathQuat quat ) +{ + VmathVector3 result; + vmathQGetXYZ(&result, &quat); + return result; +} + +static inline void vmathQSetX_V( VmathQuat *result, float _x ) +{ + vmathQSetX(result, _x); +} + +static inline float vmathQGetX_V( VmathQuat quat ) +{ + return vmathQGetX(&quat); +} + +static inline void vmathQSetY_V( VmathQuat *result, float _y ) +{ + vmathQSetY(result, _y); +} + +static inline float vmathQGetY_V( VmathQuat quat ) +{ + return vmathQGetY(&quat); +} + +static inline void vmathQSetZ_V( VmathQuat *result, float _z ) +{ + vmathQSetZ(result, _z); +} + +static inline float vmathQGetZ_V( VmathQuat quat ) +{ + return vmathQGetZ(&quat); +} + +static inline void vmathQSetW_V( VmathQuat *result, float _w ) +{ + vmathQSetW(result, _w); +} + +static inline float vmathQGetW_V( VmathQuat quat ) +{ + return vmathQGetW(&quat); +} + +static inline void vmathQSetElem_V( VmathQuat *result, int idx, float value ) +{ + vmathQSetElem(result, idx, value); +} + +static inline float vmathQGetElem_V( VmathQuat quat, int idx ) +{ + return vmathQGetElem(&quat, idx); +} + +static inline VmathQuat vmathQAdd_V( VmathQuat quat0, VmathQuat quat1 ) +{ + VmathQuat result; + vmathQAdd(&result, &quat0, &quat1); + return result; +} + +static inline VmathQuat vmathQSub_V( VmathQuat quat0, VmathQuat quat1 ) +{ + VmathQuat result; + vmathQSub(&result, &quat0, &quat1); + return result; +} + +static inline VmathQuat vmathQScalarMul_V( VmathQuat quat, float scalar ) +{ + VmathQuat result; + vmathQScalarMul(&result, &quat, scalar); + return result; +} + +static inline VmathQuat vmathQScalarDiv_V( VmathQuat quat, float scalar ) +{ + VmathQuat result; + vmathQScalarDiv(&result, &quat, scalar); + return result; +} + +static inline VmathQuat vmathQNeg_V( VmathQuat quat ) +{ + VmathQuat result; + vmathQNeg(&result, &quat); + return result; +} + +static inline float vmathQDot_V( VmathQuat quat0, VmathQuat quat1 ) +{ + return vmathQDot(&quat0, &quat1); +} + +static inline float vmathQNorm_V( VmathQuat quat ) +{ + return vmathQNorm(&quat); +} + +static inline float vmathQLength_V( VmathQuat quat ) +{ + return vmathQLength(&quat); +} + +static inline VmathQuat vmathQNormalize_V( VmathQuat quat ) +{ + VmathQuat result; + vmathQNormalize(&result, &quat); + return result; +} + +static inline VmathQuat vmathQMakeRotationArc_V( VmathVector3 unitVec0, VmathVector3 unitVec1 ) +{ + VmathQuat result; + vmathQMakeRotationArc(&result, &unitVec0, &unitVec1); + return result; +} + +static inline VmathQuat vmathQMakeRotationAxis_V( float radians, VmathVector3 unitVec ) +{ + VmathQuat result; + vmathQMakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathQuat vmathQMakeRotationX_V( float radians ) +{ + VmathQuat result; + vmathQMakeRotationX(&result, radians); + return result; +} + +static inline VmathQuat vmathQMakeRotationY_V( float radians ) +{ + VmathQuat result; + vmathQMakeRotationY(&result, radians); + return result; +} + +static inline VmathQuat vmathQMakeRotationZ_V( float radians ) +{ + VmathQuat result; + vmathQMakeRotationZ(&result, radians); + return result; +} + +static inline VmathQuat vmathQMul_V( VmathQuat quat0, VmathQuat quat1 ) +{ + VmathQuat result; + vmathQMul(&result, &quat0, &quat1); + return result; +} + +static inline VmathVector3 vmathQRotate_V( VmathQuat quat, VmathVector3 vec ) +{ + VmathVector3 result; + vmathQRotate(&result, &quat, &vec); + return result; +} + +static inline VmathQuat vmathQConj_V( VmathQuat quat ) +{ + VmathQuat result; + vmathQConj(&result, &quat); + return result; +} + +static inline VmathQuat vmathQSelect_V( VmathQuat quat0, VmathQuat quat1, unsigned int select1 ) +{ + VmathQuat result; + vmathQSelect(&result, &quat0, &quat1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathQPrint_V( VmathQuat quat ) +{ + vmathQPrint(&quat); +} + +static inline void vmathQPrints_V( VmathQuat quat, const char *name ) +{ + vmathQPrints(&quat, name); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/c/quat_soa.h b/Extras/vectormathlibrary/include/vectormath/spu/c/quat_soa.h new file mode 100644 index 0000000..cd79e9d --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/c/quat_soa.h @@ -0,0 +1,419 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_SOA_C_H +#define _VECTORMATH_QUAT_SOA_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline void vmathSoaQCopy( VmathSoaQuat *result, const VmathSoaQuat *quat ) +{ + result->x = quat->x; + result->y = quat->y; + result->z = quat->z; + result->w = quat->w; +} + +static inline void vmathSoaQMakeFromElems( VmathSoaQuat *result, vec_float4 _x, vec_float4 _y, vec_float4 _z, vec_float4 _w ) +{ + result->x = _x; + result->y = _y; + result->z = _z; + result->w = _w; +} + +static inline void vmathSoaQMakeFromV3Scalar( VmathSoaQuat *result, const VmathSoaVector3 *xyz, vec_float4 _w ) +{ + vmathSoaQSetXYZ( result, xyz ); + vmathSoaQSetW( result, _w ); +} + +static inline void vmathSoaQMakeFromV4( VmathSoaQuat *result, const VmathSoaVector4 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; + result->w = vec->w; +} + +static inline void vmathSoaQMakeFromScalar( VmathSoaQuat *result, vec_float4 scalar ) +{ + result->x = scalar; + result->y = scalar; + result->z = scalar; + result->w = scalar; +} + +static inline void vmathSoaQMakeFromAos( VmathSoaQuat *result, const VmathQuat *quat ) +{ + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + vec_uchar16 shuffle_wwww = (vec_uchar16)spu_splats((int)0x0c0d0e0f); + vec_float4 vec128 = quat->vec128; + result->x = spu_shuffle( vec128, vec128, shuffle_xxxx ); + result->y = spu_shuffle( vec128, vec128, shuffle_yyyy ); + result->z = spu_shuffle( vec128, vec128, shuffle_zzzz ); + result->w = spu_shuffle( vec128, vec128, shuffle_wwww ); +} + +static inline void vmathSoaQMakeFrom4Aos( VmathSoaQuat *result, const VmathQuat *quat0, const VmathQuat *quat1, const VmathQuat *quat2, const VmathQuat *quat3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = spu_shuffle( quat0->vec128, quat2->vec128, _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( quat1->vec128, quat3->vec128, _VECTORMATH_SHUF_XAYB ); + tmp2 = spu_shuffle( quat0->vec128, quat2->vec128, _VECTORMATH_SHUF_ZCWD ); + tmp3 = spu_shuffle( quat1->vec128, quat3->vec128, _VECTORMATH_SHUF_ZCWD ); + result->x = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_XAYB ); + result->y = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_ZCWD ); + result->z = spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_XAYB ); + result->w = spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_ZCWD ); +} + +static inline void vmathSoaQMakeIdentity( VmathSoaQuat *result ) +{ + vmathSoaQMakeFromElems( result, spu_splats(0.0f), spu_splats(0.0f), spu_splats(0.0f), spu_splats(1.0f) ); +} + +static inline void vmathSoaQLerp( VmathSoaQuat *result, vec_float4 t, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ) +{ + VmathSoaQuat tmpQ_0, tmpQ_1; + vmathSoaQSub( &tmpQ_0, quat1, quat0 ); + vmathSoaQScalarMul( &tmpQ_1, &tmpQ_0, t ); + vmathSoaQAdd( result, quat0, &tmpQ_1 ); +} + +static inline void vmathSoaQSlerp( VmathSoaQuat *result, vec_float4 t, const VmathSoaQuat *unitQuat0, const VmathSoaQuat *unitQuat1 ) +{ + VmathSoaQuat start, tmpQ_0, tmpQ_1; + vec_float4 recipSinAngle, scale0, scale1, cosAngle, angle; + vec_uint4 selectMask; + cosAngle = vmathSoaQDot( unitQuat0, unitQuat1 ); + selectMask = (vec_uint4)spu_cmpgt( spu_splats(0.0f), cosAngle ); + cosAngle = spu_sel( cosAngle, negatef4( cosAngle ), selectMask ); + vmathSoaQSetX( &start, spu_sel( unitQuat0->x, negatef4( unitQuat0->x ), selectMask ) ); + vmathSoaQSetY( &start, spu_sel( unitQuat0->y, negatef4( unitQuat0->y ), selectMask ) ); + vmathSoaQSetZ( &start, spu_sel( unitQuat0->z, negatef4( unitQuat0->z ), selectMask ) ); + vmathSoaQSetW( &start, spu_sel( unitQuat0->w, negatef4( unitQuat0->w ), selectMask ) ); + selectMask = (vec_uint4)spu_cmpgt( spu_splats(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + recipSinAngle = recipf4( sinf4( angle ) ); + scale0 = spu_sel( spu_sub( spu_splats(1.0f), t ), spu_mul( sinf4( spu_mul( spu_sub( spu_splats(1.0f), t ), angle ) ), recipSinAngle ), selectMask ); + scale1 = spu_sel( t, spu_mul( sinf4( spu_mul( t, angle ) ), recipSinAngle ), selectMask ); + vmathSoaQScalarMul( &tmpQ_0, &start, scale0 ); + vmathSoaQScalarMul( &tmpQ_1, unitQuat1, scale1 ); + vmathSoaQAdd( result, &tmpQ_0, &tmpQ_1 ); +} + +static inline void vmathSoaQSquad( VmathSoaQuat *result, vec_float4 t, const VmathSoaQuat *unitQuat0, const VmathSoaQuat *unitQuat1, const VmathSoaQuat *unitQuat2, const VmathSoaQuat *unitQuat3 ) +{ + VmathSoaQuat tmp0, tmp1; + vmathSoaQSlerp( &tmp0, t, unitQuat0, unitQuat3 ); + vmathSoaQSlerp( &tmp1, t, unitQuat1, unitQuat2 ); + vmathSoaQSlerp( result, spu_mul( spu_mul( spu_splats(2.0f), t ), spu_sub( spu_splats(1.0f), t ) ), &tmp0, &tmp1 ); +} + +static inline void vmathSoaQGet4Aos( const VmathSoaQuat *quat, VmathQuat *result0, VmathQuat *result1, VmathQuat *result2, VmathQuat *result3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = spu_shuffle( quat->x, quat->z, _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( quat->y, quat->w, _VECTORMATH_SHUF_XAYB ); + tmp2 = spu_shuffle( quat->x, quat->z, _VECTORMATH_SHUF_ZCWD ); + tmp3 = spu_shuffle( quat->y, quat->w, _VECTORMATH_SHUF_ZCWD ); + vmathQMakeFrom128( result0, spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_XAYB ) ); + vmathQMakeFrom128( result1, spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_ZCWD ) ); + vmathQMakeFrom128( result2, spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_XAYB ) ); + vmathQMakeFrom128( result3, spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_ZCWD ) ); +} + +static inline void vmathSoaQSetXYZ( VmathSoaQuat *result, const VmathSoaVector3 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; +} + +static inline void vmathSoaQGetXYZ( VmathSoaVector3 *result, const VmathSoaQuat *quat ) +{ + vmathSoaV3MakeFromElems( result, quat->x, quat->y, quat->z ); +} + +static inline void vmathSoaQSetX( VmathSoaQuat *result, vec_float4 _x ) +{ + result->x = _x; +} + +static inline vec_float4 vmathSoaQGetX( const VmathSoaQuat *quat ) +{ + return quat->x; +} + +static inline void vmathSoaQSetY( VmathSoaQuat *result, vec_float4 _y ) +{ + result->y = _y; +} + +static inline vec_float4 vmathSoaQGetY( const VmathSoaQuat *quat ) +{ + return quat->y; +} + +static inline void vmathSoaQSetZ( VmathSoaQuat *result, vec_float4 _z ) +{ + result->z = _z; +} + +static inline vec_float4 vmathSoaQGetZ( const VmathSoaQuat *quat ) +{ + return quat->z; +} + +static inline void vmathSoaQSetW( VmathSoaQuat *result, vec_float4 _w ) +{ + result->w = _w; +} + +static inline vec_float4 vmathSoaQGetW( const VmathSoaQuat *quat ) +{ + return quat->w; +} + +static inline void vmathSoaQSetElem( VmathSoaQuat *result, int idx, vec_float4 value ) +{ + *(&result->x + idx) = value; +} + +static inline vec_float4 vmathSoaQGetElem( const VmathSoaQuat *quat, int idx ) +{ + return *(&quat->x + idx); +} + +static inline void vmathSoaQAdd( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ) +{ + result->x = spu_add( quat0->x, quat1->x ); + result->y = spu_add( quat0->y, quat1->y ); + result->z = spu_add( quat0->z, quat1->z ); + result->w = spu_add( quat0->w, quat1->w ); +} + +static inline void vmathSoaQSub( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ) +{ + result->x = spu_sub( quat0->x, quat1->x ); + result->y = spu_sub( quat0->y, quat1->y ); + result->z = spu_sub( quat0->z, quat1->z ); + result->w = spu_sub( quat0->w, quat1->w ); +} + +static inline void vmathSoaQScalarMul( VmathSoaQuat *result, const VmathSoaQuat *quat, vec_float4 scalar ) +{ + result->x = spu_mul( quat->x, scalar ); + result->y = spu_mul( quat->y, scalar ); + result->z = spu_mul( quat->z, scalar ); + result->w = spu_mul( quat->w, scalar ); +} + +static inline void vmathSoaQScalarDiv( VmathSoaQuat *result, const VmathSoaQuat *quat, vec_float4 scalar ) +{ + result->x = divf4( quat->x, scalar ); + result->y = divf4( quat->y, scalar ); + result->z = divf4( quat->z, scalar ); + result->w = divf4( quat->w, scalar ); +} + +static inline void vmathSoaQNeg( VmathSoaQuat *result, const VmathSoaQuat *quat ) +{ + result->x = negatef4( quat->x ); + result->y = negatef4( quat->y ); + result->z = negatef4( quat->z ); + result->w = negatef4( quat->w ); +} + +static inline vec_float4 vmathSoaQDot( const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ) +{ + vec_float4 result; + result = spu_mul( quat0->x, quat1->x ); + result = spu_add( result, spu_mul( quat0->y, quat1->y ) ); + result = spu_add( result, spu_mul( quat0->z, quat1->z ) ); + result = spu_add( result, spu_mul( quat0->w, quat1->w ) ); + return result; +} + +static inline vec_float4 vmathSoaQNorm( const VmathSoaQuat *quat ) +{ + vec_float4 result; + result = spu_mul( quat->x, quat->x ); + result = spu_add( result, spu_mul( quat->y, quat->y ) ); + result = spu_add( result, spu_mul( quat->z, quat->z ) ); + result = spu_add( result, spu_mul( quat->w, quat->w ) ); + return result; +} + +static inline vec_float4 vmathSoaQLength( const VmathSoaQuat *quat ) +{ + return sqrtf4( vmathSoaQNorm( quat ) ); +} + +static inline void vmathSoaQNormalize( VmathSoaQuat *result, const VmathSoaQuat *quat ) +{ + vec_float4 lenSqr, lenInv; + lenSqr = vmathSoaQNorm( quat ); + lenInv = rsqrtf4( lenSqr ); + result->x = spu_mul( quat->x, lenInv ); + result->y = spu_mul( quat->y, lenInv ); + result->z = spu_mul( quat->z, lenInv ); + result->w = spu_mul( quat->w, lenInv ); +} + +static inline void vmathSoaQMakeRotationArc( VmathSoaQuat *result, const VmathSoaVector3 *unitVec0, const VmathSoaVector3 *unitVec1 ) +{ + VmathSoaVector3 tmpV3_0, tmpV3_1; + vec_float4 cosHalfAngleX2, recipCosHalfAngleX2; + cosHalfAngleX2 = sqrtf4( spu_mul( spu_splats(2.0f), spu_add( spu_splats(1.0f), vmathSoaV3Dot( unitVec0, unitVec1 ) ) ) ); + recipCosHalfAngleX2 = recipf4( cosHalfAngleX2 ); + vmathSoaV3Cross( &tmpV3_0, unitVec0, unitVec1 ); + vmathSoaV3ScalarMul( &tmpV3_1, &tmpV3_0, recipCosHalfAngleX2 ); + vmathSoaQMakeFromV3Scalar( result, &tmpV3_1, spu_mul( cosHalfAngleX2, spu_splats(0.5f) ) ); +} + +static inline void vmathSoaQMakeRotationAxis( VmathSoaQuat *result, vec_float4 radians, const VmathSoaVector3 *unitVec ) +{ + VmathSoaVector3 tmpV3_0; + vec_float4 s, c, angle; + angle = spu_mul( radians, spu_splats(0.5f) ); + sincosf4( angle, &s, &c ); + vmathSoaV3ScalarMul( &tmpV3_0, unitVec, s ); + vmathSoaQMakeFromV3Scalar( result, &tmpV3_0, c ); +} + +static inline void vmathSoaQMakeRotationX( VmathSoaQuat *result, vec_float4 radians ) +{ + vec_float4 s, c, angle; + angle = spu_mul( radians, spu_splats(0.5f) ); + sincosf4( angle, &s, &c ); + vmathSoaQMakeFromElems( result, s, spu_splats(0.0f), spu_splats(0.0f), c ); +} + +static inline void vmathSoaQMakeRotationY( VmathSoaQuat *result, vec_float4 radians ) +{ + vec_float4 s, c, angle; + angle = spu_mul( radians, spu_splats(0.5f) ); + sincosf4( angle, &s, &c ); + vmathSoaQMakeFromElems( result, spu_splats(0.0f), s, spu_splats(0.0f), c ); +} + +static inline void vmathSoaQMakeRotationZ( VmathSoaQuat *result, vec_float4 radians ) +{ + vec_float4 s, c, angle; + angle = spu_mul( radians, spu_splats(0.5f) ); + sincosf4( angle, &s, &c ); + vmathSoaQMakeFromElems( result, spu_splats(0.0f), spu_splats(0.0f), s, c ); +} + +static inline void vmathSoaQMul( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ) +{ + vec_float4 tmpX, tmpY, tmpZ, tmpW; + tmpX = spu_sub( spu_add( spu_add( spu_mul( quat0->w, quat1->x ), spu_mul( quat0->x, quat1->w ) ), spu_mul( quat0->y, quat1->z ) ), spu_mul( quat0->z, quat1->y ) ); + tmpY = spu_sub( spu_add( spu_add( spu_mul( quat0->w, quat1->y ), spu_mul( quat0->y, quat1->w ) ), spu_mul( quat0->z, quat1->x ) ), spu_mul( quat0->x, quat1->z ) ); + tmpZ = spu_sub( spu_add( spu_add( spu_mul( quat0->w, quat1->z ), spu_mul( quat0->z, quat1->w ) ), spu_mul( quat0->x, quat1->y ) ), spu_mul( quat0->y, quat1->x ) ); + tmpW = spu_sub( spu_sub( spu_sub( spu_mul( quat0->w, quat1->w ), spu_mul( quat0->x, quat1->x ) ), spu_mul( quat0->y, quat1->y ) ), spu_mul( quat0->z, quat1->z ) ); + vmathSoaQMakeFromElems( result, tmpX, tmpY, tmpZ, tmpW ); +} + +static inline void vmathSoaQRotate( VmathSoaVector3 *result, const VmathSoaQuat *quat, const VmathSoaVector3 *vec ) +{ + vec_float4 tmpX, tmpY, tmpZ, tmpW; + tmpX = spu_sub( spu_add( spu_mul( quat->w, vec->x ), spu_mul( quat->y, vec->z ) ), spu_mul( quat->z, vec->y ) ); + tmpY = spu_sub( spu_add( spu_mul( quat->w, vec->y ), spu_mul( quat->z, vec->x ) ), spu_mul( quat->x, vec->z ) ); + tmpZ = spu_sub( spu_add( spu_mul( quat->w, vec->z ), spu_mul( quat->x, vec->y ) ), spu_mul( quat->y, vec->x ) ); + tmpW = spu_add( spu_add( spu_mul( quat->x, vec->x ), spu_mul( quat->y, vec->y ) ), spu_mul( quat->z, vec->z ) ); + result->x = spu_add( spu_sub( spu_add( spu_mul( tmpW, quat->x ), spu_mul( tmpX, quat->w ) ), spu_mul( tmpY, quat->z ) ), spu_mul( tmpZ, quat->y ) ); + result->y = spu_add( spu_sub( spu_add( spu_mul( tmpW, quat->y ), spu_mul( tmpY, quat->w ) ), spu_mul( tmpZ, quat->x ) ), spu_mul( tmpX, quat->z ) ); + result->z = spu_add( spu_sub( spu_add( spu_mul( tmpW, quat->z ), spu_mul( tmpZ, quat->w ) ), spu_mul( tmpX, quat->y ) ), spu_mul( tmpY, quat->x ) ); +} + +static inline void vmathSoaQConj( VmathSoaQuat *result, const VmathSoaQuat *quat ) +{ + vmathSoaQMakeFromElems( result, negatef4( quat->x ), negatef4( quat->y ), negatef4( quat->z ), quat->w ); +} + +static inline void vmathSoaQSelect( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1, vec_uint4 select1 ) +{ + result->x = spu_sel( quat0->x, quat1->x, select1 ); + result->y = spu_sel( quat0->y, quat1->y, select1 ); + result->z = spu_sel( quat0->z, quat1->z, select1 ); + result->w = spu_sel( quat0->w, quat1->w, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaQPrint( const VmathSoaQuat *quat ) +{ + VmathQuat vec0, vec1, vec2, vec3; + vmathSoaQGet4Aos( quat, &vec0, &vec1, &vec2, &vec3 ); + printf("slot 0:\n"); + vmathQPrint( &vec0 ); + printf("slot 1:\n"); + vmathQPrint( &vec1 ); + printf("slot 2:\n"); + vmathQPrint( &vec2 ); + printf("slot 3:\n"); + vmathQPrint( &vec3 ); +} + +static inline void vmathSoaQPrints( const VmathSoaQuat *quat, const char *name ) +{ + VmathQuat vec0, vec1, vec2, vec3; + printf( "%s:\n", name ); + vmathSoaQGet4Aos( quat, &vec0, &vec1, &vec2, &vec3 ); + printf("slot 0:\n"); + vmathQPrint( &vec0 ); + printf("slot 1:\n"); + vmathQPrint( &vec1 ); + printf("slot 2:\n"); + vmathQPrint( &vec2 ); + printf("slot 3:\n"); + vmathQPrint( &vec3 ); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/c/quat_soa_v.h b/Extras/vectormathlibrary/include/vectormath/spu/c/quat_soa_v.h new file mode 100644 index 0000000..601d9da --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/c/quat_soa_v.h @@ -0,0 +1,319 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_SOA_V_C_H +#define _VECTORMATH_QUAT_SOA_V_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline VmathSoaQuat vmathSoaQMakeFromElems_V( vec_float4 _x, vec_float4 _y, vec_float4 _z, vec_float4 _w ) +{ + VmathSoaQuat result; + vmathSoaQMakeFromElems(&result, _x, _y, _z, _w); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeFromV3Scalar_V( VmathSoaVector3 xyz, vec_float4 _w ) +{ + VmathSoaQuat result; + vmathSoaQMakeFromV3Scalar(&result, &xyz, _w); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeFromV4_V( VmathSoaVector4 vec ) +{ + VmathSoaQuat result; + vmathSoaQMakeFromV4(&result, &vec); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeFromScalar_V( vec_float4 scalar ) +{ + VmathSoaQuat result; + vmathSoaQMakeFromScalar(&result, scalar); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeFromAos_V( VmathQuat quat ) +{ + VmathSoaQuat result; + vmathSoaQMakeFromAos(&result, &quat); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeFrom4Aos_V( VmathQuat quat0, VmathQuat quat1, VmathQuat quat2, VmathQuat quat3 ) +{ + VmathSoaQuat result; + vmathSoaQMakeFrom4Aos(&result, &quat0, &quat1, &quat2, &quat3); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeIdentity_V( ) +{ + VmathSoaQuat result; + vmathSoaQMakeIdentity(&result); + return result; +} + +static inline VmathSoaQuat vmathSoaQLerp_V( vec_float4 t, VmathSoaQuat quat0, VmathSoaQuat quat1 ) +{ + VmathSoaQuat result; + vmathSoaQLerp(&result, t, &quat0, &quat1); + return result; +} + +static inline VmathSoaQuat vmathSoaQSlerp_V( vec_float4 t, VmathSoaQuat unitQuat0, VmathSoaQuat unitQuat1 ) +{ + VmathSoaQuat result; + vmathSoaQSlerp(&result, t, &unitQuat0, &unitQuat1); + return result; +} + +static inline VmathSoaQuat vmathSoaQSquad_V( vec_float4 t, VmathSoaQuat unitQuat0, VmathSoaQuat unitQuat1, VmathSoaQuat unitQuat2, VmathSoaQuat unitQuat3 ) +{ + VmathSoaQuat result; + vmathSoaQSquad(&result, t, &unitQuat0, &unitQuat1, &unitQuat2, &unitQuat3); + return result; +} + +static inline void vmathSoaQGet4Aos_V( VmathSoaQuat quat, VmathQuat *result0, VmathQuat *result1, VmathQuat *result2, VmathQuat *result3 ) +{ + vmathSoaQGet4Aos(&quat, result0, result1, result2, result3); +} + +static inline void vmathSoaQSetXYZ_V( VmathSoaQuat *result, VmathSoaVector3 vec ) +{ + vmathSoaQSetXYZ(result, &vec); +} + +static inline VmathSoaVector3 vmathSoaQGetXYZ_V( VmathSoaQuat quat ) +{ + VmathSoaVector3 result; + vmathSoaQGetXYZ(&result, &quat); + return result; +} + +static inline void vmathSoaQSetX_V( VmathSoaQuat *result, vec_float4 _x ) +{ + vmathSoaQSetX(result, _x); +} + +static inline vec_float4 vmathSoaQGetX_V( VmathSoaQuat quat ) +{ + return vmathSoaQGetX(&quat); +} + +static inline void vmathSoaQSetY_V( VmathSoaQuat *result, vec_float4 _y ) +{ + vmathSoaQSetY(result, _y); +} + +static inline vec_float4 vmathSoaQGetY_V( VmathSoaQuat quat ) +{ + return vmathSoaQGetY(&quat); +} + +static inline void vmathSoaQSetZ_V( VmathSoaQuat *result, vec_float4 _z ) +{ + vmathSoaQSetZ(result, _z); +} + +static inline vec_float4 vmathSoaQGetZ_V( VmathSoaQuat quat ) +{ + return vmathSoaQGetZ(&quat); +} + +static inline void vmathSoaQSetW_V( VmathSoaQuat *result, vec_float4 _w ) +{ + vmathSoaQSetW(result, _w); +} + +static inline vec_float4 vmathSoaQGetW_V( VmathSoaQuat quat ) +{ + return vmathSoaQGetW(&quat); +} + +static inline void vmathSoaQSetElem_V( VmathSoaQuat *result, int idx, vec_float4 value ) +{ + vmathSoaQSetElem(result, idx, value); +} + +static inline vec_float4 vmathSoaQGetElem_V( VmathSoaQuat quat, int idx ) +{ + return vmathSoaQGetElem(&quat, idx); +} + +static inline VmathSoaQuat vmathSoaQAdd_V( VmathSoaQuat quat0, VmathSoaQuat quat1 ) +{ + VmathSoaQuat result; + vmathSoaQAdd(&result, &quat0, &quat1); + return result; +} + +static inline VmathSoaQuat vmathSoaQSub_V( VmathSoaQuat quat0, VmathSoaQuat quat1 ) +{ + VmathSoaQuat result; + vmathSoaQSub(&result, &quat0, &quat1); + return result; +} + +static inline VmathSoaQuat vmathSoaQScalarMul_V( VmathSoaQuat quat, vec_float4 scalar ) +{ + VmathSoaQuat result; + vmathSoaQScalarMul(&result, &quat, scalar); + return result; +} + +static inline VmathSoaQuat vmathSoaQScalarDiv_V( VmathSoaQuat quat, vec_float4 scalar ) +{ + VmathSoaQuat result; + vmathSoaQScalarDiv(&result, &quat, scalar); + return result; +} + +static inline VmathSoaQuat vmathSoaQNeg_V( VmathSoaQuat quat ) +{ + VmathSoaQuat result; + vmathSoaQNeg(&result, &quat); + return result; +} + +static inline vec_float4 vmathSoaQDot_V( VmathSoaQuat quat0, VmathSoaQuat quat1 ) +{ + return vmathSoaQDot(&quat0, &quat1); +} + +static inline vec_float4 vmathSoaQNorm_V( VmathSoaQuat quat ) +{ + return vmathSoaQNorm(&quat); +} + +static inline vec_float4 vmathSoaQLength_V( VmathSoaQuat quat ) +{ + return vmathSoaQLength(&quat); +} + +static inline VmathSoaQuat vmathSoaQNormalize_V( VmathSoaQuat quat ) +{ + VmathSoaQuat result; + vmathSoaQNormalize(&result, &quat); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeRotationArc_V( VmathSoaVector3 unitVec0, VmathSoaVector3 unitVec1 ) +{ + VmathSoaQuat result; + vmathSoaQMakeRotationArc(&result, &unitVec0, &unitVec1); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeRotationAxis_V( vec_float4 radians, VmathSoaVector3 unitVec ) +{ + VmathSoaQuat result; + vmathSoaQMakeRotationAxis(&result, radians, &unitVec); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeRotationX_V( vec_float4 radians ) +{ + VmathSoaQuat result; + vmathSoaQMakeRotationX(&result, radians); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeRotationY_V( vec_float4 radians ) +{ + VmathSoaQuat result; + vmathSoaQMakeRotationY(&result, radians); + return result; +} + +static inline VmathSoaQuat vmathSoaQMakeRotationZ_V( vec_float4 radians ) +{ + VmathSoaQuat result; + vmathSoaQMakeRotationZ(&result, radians); + return result; +} + +static inline VmathSoaQuat vmathSoaQMul_V( VmathSoaQuat quat0, VmathSoaQuat quat1 ) +{ + VmathSoaQuat result; + vmathSoaQMul(&result, &quat0, &quat1); + return result; +} + +static inline VmathSoaVector3 vmathSoaQRotate_V( VmathSoaQuat quat, VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaQRotate(&result, &quat, &vec); + return result; +} + +static inline VmathSoaQuat vmathSoaQConj_V( VmathSoaQuat quat ) +{ + VmathSoaQuat result; + vmathSoaQConj(&result, &quat); + return result; +} + +static inline VmathSoaQuat vmathSoaQSelect_V( VmathSoaQuat quat0, VmathSoaQuat quat1, vec_uint4 select1 ) +{ + VmathSoaQuat result; + vmathSoaQSelect(&result, &quat0, &quat1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaQPrint_V( VmathSoaQuat quat ) +{ + vmathSoaQPrint(&quat); +} + +static inline void vmathSoaQPrints_V( VmathSoaQuat quat, const char *name ) +{ + vmathSoaQPrints(&quat, name); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/c/vec_aos.h b/Extras/vectormathlibrary/include/vectormath/spu/c/vec_aos.h new file mode 100644 index 0000000..715f27d --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/c/vec_aos.h @@ -0,0 +1,1029 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_AOS_C_H +#define _VECTORMATH_VEC_AOS_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + * for shuffles, words are labeled [x,y,z,w] [a,b,c,d] + */ +#define _VECTORMATH_SHUF_X 0x00010203 +#define _VECTORMATH_SHUF_Y 0x04050607 +#define _VECTORMATH_SHUF_Z 0x08090a0b +#define _VECTORMATH_SHUF_W 0x0c0d0e0f +#define _VECTORMATH_SHUF_A 0x10111213 +#define _VECTORMATH_SHUF_B 0x14151617 +#define _VECTORMATH_SHUF_C 0x18191a1b +#define _VECTORMATH_SHUF_D 0x1c1d1e1f +#define _VECTORMATH_SHUF_0 0x80808080 +#define _VECTORMATH_SHUF_XYZA (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_A } +#define _VECTORMATH_SHUF_ZXYW (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_W } +#define _VECTORMATH_SHUF_YZXW (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_W } +#define _VECTORMATH_SHUF_WABC (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_C } +#define _VECTORMATH_SHUF_ZWAB (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_B } +#define _VECTORMATH_SHUF_XYZA (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_A } +#define _VECTORMATH_SHUF_YZAB (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_B } +#define _VECTORMATH_SHUF_ZABC (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_C } +#define _VECTORMATH_UNIT_1000 (vec_float4){ 1.0f, 0.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0100 (vec_float4){ 0.0f, 1.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0010 (vec_float4){ 0.0f, 0.0f, 1.0f, 0.0f } +#define _VECTORMATH_UNIT_0001 (vec_float4){ 0.0f, 0.0f, 0.0f, 1.0f } +#define _VECTORMATH_SLERP_TOL 0.999f + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +static inline vec_float4 _vmathVfDot3( vec_float4 vec0, vec_float4 vec1 ) +{ + vec_float4 result; + result = spu_mul( vec0, vec1 ); + result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result ); + return spu_madd( spu_rlqwbyte( vec0, 8 ), spu_rlqwbyte( vec1, 8 ), result ); +} + +static inline vec_float4 _vmathVfDot4( vec_float4 vec0, vec_float4 vec1 ) +{ + vec_float4 result; + result = spu_mul( vec0, vec1 ); + result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result ); + return spu_add( spu_rlqwbyte( result, 8 ), result ); +} + +static inline vec_float4 _vmathVfCross( vec_float4 vec0, vec_float4 vec1 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3, result; + tmp0 = spu_shuffle( vec0, vec0, _VECTORMATH_SHUF_YZXW ); + tmp1 = spu_shuffle( vec1, vec1, _VECTORMATH_SHUF_ZXYW ); + tmp2 = spu_shuffle( vec0, vec0, _VECTORMATH_SHUF_ZXYW ); + tmp3 = spu_shuffle( vec1, vec1, _VECTORMATH_SHUF_YZXW ); + result = spu_mul( tmp0, tmp1 ); + result = spu_nmsub( tmp2, tmp3, result ); + return result; +} + +static inline vec_uint4 _vmathVfToHalfFloatsUnpacked(vec_float4 v) +{ + vec_int4 bexp; + vec_uint4 mant, sign, hfloat; + vec_uint4 notZero, isInf; + const vec_uint4 hfloatInf = spu_splats(0x00007c00u); + const vec_uint4 mergeMant = spu_splats(0x000003ffu); + const vec_uint4 mergeSign = spu_splats(0x00008000u); + + sign = spu_rlmask((vec_uint4)v, -16); + mant = spu_rlmask((vec_uint4)v, -13); + bexp = spu_and(spu_rlmask((vec_int4)v, -23), 0xff); + + notZero = spu_cmpgt(bexp, 112); + isInf = spu_cmpgt(bexp, 142); + + bexp = spu_add(bexp, -112); + bexp = spu_sl(bexp, 10); + + hfloat = spu_sel((vec_uint4)bexp, mant, mergeMant); + hfloat = spu_sel(spu_splats(0u), hfloat, notZero); + hfloat = spu_sel(hfloat, hfloatInf, isInf); + hfloat = spu_sel(hfloat, sign, mergeSign); + + return hfloat; +} + +static inline vec_ushort8 _vmath2VfToHalfFloats(vec_float4 u, vec_float4 v) +{ + vec_uint4 hfloat_u, hfloat_v; + const vec_uchar16 pack = (vec_uchar16){2,3,6,7,10,11,14,15,18,19,22,23,26,27,30,31}; + hfloat_u = _vmathVfToHalfFloatsUnpacked(u); + hfloat_v = _vmathVfToHalfFloatsUnpacked(v); + return (vec_ushort8)spu_shuffle(hfloat_u, hfloat_v, pack); +} + +#endif + +static inline void vmathV3Copy( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->vec128 = vec->vec128; +} + +static inline void vmathV3MakeFromElems( VmathVector3 *result, float _x, float _y, float _z ) +{ + result->vec128 = (vec_float4){ _x, _y, _z, 0.0f }; +} + +static inline void vmathV3MakeFromP3( VmathVector3 *result, const VmathPoint3 *pnt ) +{ + result->vec128 = pnt->vec128; +} + +static inline void vmathV3MakeFromScalar( VmathVector3 *result, float scalar ) +{ + result->vec128 = spu_splats( scalar ); +} + +static inline void vmathV3MakeFrom128( VmathVector3 *result, vec_float4 vf4 ) +{ + result->vec128 = vf4; +} + +static inline void vmathV3MakeXAxis( VmathVector3 *result ) +{ + result->vec128 = _VECTORMATH_UNIT_1000; +} + +static inline void vmathV3MakeYAxis( VmathVector3 *result ) +{ + result->vec128 = _VECTORMATH_UNIT_0100; +} + +static inline void vmathV3MakeZAxis( VmathVector3 *result ) +{ + result->vec128 = _VECTORMATH_UNIT_0010; +} + +static inline void vmathV3Lerp( VmathVector3 *result, float t, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + VmathVector3 tmpV3_0, tmpV3_1; + vmathV3Sub( &tmpV3_0, vec1, vec0 ); + vmathV3ScalarMul( &tmpV3_1, &tmpV3_0, t ); + vmathV3Add( result, vec0, &tmpV3_1 ); +} + +static inline void vmathV3Slerp( VmathVector3 *result, float t, const VmathVector3 *unitVec0, const VmathVector3 *unitVec1 ) +{ + vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + vec_uint4 selectMask; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + cosAngle = _vmathVfDot3( unitVec0->vec128, unitVec1->vec128 ); + cosAngle = spu_shuffle( cosAngle, cosAngle, shuffle_xxxx ); + selectMask = (vec_uint4)spu_cmpgt( spu_splats(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = spu_splats(t); + oneMinusT = spu_sub( spu_splats(1.0f), tttt ); + angles = spu_sel( spu_splats(1.0f), oneMinusT, (vec_uint4)spu_maskb(0x0f00) ); + angles = spu_sel( angles, tttt, (vec_uint4)spu_maskb(0x00f0) ); + angles = spu_mul( angles, angle ); + sines = sinf4( angles ); + scales = divf4( sines, spu_shuffle( sines, sines, shuffle_xxxx ) ); + scale0 = spu_sel( oneMinusT, spu_shuffle( scales, scales, shuffle_yyyy ), selectMask ); + scale1 = spu_sel( tttt, spu_shuffle( scales, scales, shuffle_zzzz ), selectMask ); + result->vec128 = spu_madd( unitVec0->vec128, scale0, spu_mul( unitVec1->vec128, scale1 ) ); +} + +static inline vec_float4 vmathV3Get128( const VmathVector3 *vec ) +{ + return vec->vec128; +} + +static inline void vmathV3StoreXYZ( const VmathVector3 *vec, vec_float4 *quad ) +{ + vec_float4 dstVec = *quad; + vec_uint4 mask = (vec_uint4)spu_maskb(0x000f); + dstVec = spu_sel(vec->vec128, dstVec, mask); + *quad = dstVec; +} + +static inline void vmathV3LoadXYZArray( VmathVector3 *vec0, VmathVector3 *vec1, VmathVector3 *vec2, VmathVector3 *vec3, const vec_float4 *threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz, xyz1, xyz2, xyz3; + xyzx = threeQuads[0]; + yzxy = threeQuads[1]; + zxyz = threeQuads[2]; + xyz1 = spu_shuffle( xyzx, yzxy, _VECTORMATH_SHUF_WABC ); + xyz2 = spu_shuffle( yzxy, zxyz, _VECTORMATH_SHUF_ZWAB ); + xyz3 = spu_rlqwbyte( zxyz, 4 ); + vec0->vec128 = xyzx; + vec1->vec128 = xyz1; + vec2->vec128 = xyz2; + vec3->vec128 = xyz3; +} + +static inline void vmathV3StoreXYZArray( const VmathVector3 *vec0, const VmathVector3 *vec1, const VmathVector3 *vec2, const VmathVector3 *vec3, vec_float4 *threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz; + xyzx = spu_shuffle( vec0->vec128, vec1->vec128, _VECTORMATH_SHUF_XYZA ); + yzxy = spu_shuffle( vec1->vec128, vec2->vec128, _VECTORMATH_SHUF_YZAB ); + zxyz = spu_shuffle( vec2->vec128, vec3->vec128, _VECTORMATH_SHUF_ZABC ); + threeQuads[0] = xyzx; + threeQuads[1] = yzxy; + threeQuads[2] = zxyz; +} + +static inline void vmathV3StoreHalfFloats( const VmathVector3 *vec0, const VmathVector3 *vec1, const VmathVector3 *vec2, const VmathVector3 *vec3, const VmathVector3 *vec4, const VmathVector3 *vec5, const VmathVector3 *vec6, const VmathVector3 *vec7, vec_ushort8 *threeQuads ) +{ + vec_float4 xyz0[3]; + vec_float4 xyz1[3]; + vmathV3StoreXYZArray( vec0, vec1, vec2, vec3, xyz0 ); + vmathV3StoreXYZArray( vec4, vec5, vec6, vec7, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +} + +static inline void vmathV3SetX( VmathVector3 *result, float _x ) +{ + result->vec128 = spu_insert( _x, result->vec128, 0 ); +} + +static inline float vmathV3GetX( const VmathVector3 *vec ) +{ + return spu_extract( vec->vec128, 0 ); +} + +static inline void vmathV3SetY( VmathVector3 *result, float _y ) +{ + result->vec128 = spu_insert( _y, result->vec128, 1 ); +} + +static inline float vmathV3GetY( const VmathVector3 *vec ) +{ + return spu_extract( vec->vec128, 1 ); +} + +static inline void vmathV3SetZ( VmathVector3 *result, float _z ) +{ + result->vec128 = spu_insert( _z, result->vec128, 2 ); +} + +static inline float vmathV3GetZ( const VmathVector3 *vec ) +{ + return spu_extract( vec->vec128, 2 ); +} + +static inline void vmathV3SetElem( VmathVector3 *result, int idx, float value ) +{ + result->vec128 = spu_insert( value, result->vec128, idx ); +} + +static inline float vmathV3GetElem( const VmathVector3 *vec, int idx ) +{ + return spu_extract( vec->vec128, idx ); +} + +static inline void vmathV3Add( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->vec128 = spu_add( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV3Sub( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->vec128 = spu_sub( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV3AddP3( VmathPoint3 *result, const VmathVector3 *vec, const VmathPoint3 *pnt1 ) +{ + result->vec128 = spu_add( vec->vec128, pnt1->vec128 ); +} + +static inline void vmathV3ScalarMul( VmathVector3 *result, const VmathVector3 *vec, float scalar ) +{ + result->vec128 = spu_mul( vec->vec128, spu_splats(scalar) ); +} + +static inline void vmathV3ScalarDiv( VmathVector3 *result, const VmathVector3 *vec, float scalar ) +{ + result->vec128 = divf4( vec->vec128, spu_splats(scalar) ); +} + +static inline void vmathV3Neg( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->vec128 = negatef4( vec->vec128 ); +} + +static inline void vmathV3MulPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->vec128 = spu_mul( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV3DivPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->vec128 = divf4( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV3RecipPerElem( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->vec128 = recipf4( vec->vec128 ); +} + +static inline void vmathV3SqrtPerElem( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->vec128 = sqrtf4( vec->vec128 ); +} + +static inline void vmathV3RsqrtPerElem( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->vec128 = rsqrtf4( vec->vec128 ); +} + +static inline void vmathV3AbsPerElem( VmathVector3 *result, const VmathVector3 *vec ) +{ + result->vec128 = fabsf4( vec->vec128 ); +} + +static inline void vmathV3CopySignPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->vec128 = copysignf4( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV3MaxPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->vec128 = fmaxf4( vec0->vec128, vec1->vec128 ); +} + +static inline float vmathV3MaxElem( const VmathVector3 *vec ) +{ + vec_float4 result; + result = fmaxf4( spu_promote( spu_extract( vec->vec128, 1 ), 0 ), vec->vec128 ); + result = fmaxf4( spu_promote( spu_extract( vec->vec128, 2 ), 0 ), result ); + return spu_extract( result, 0 ); +} + +static inline void vmathV3MinPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->vec128 = fminf4( vec0->vec128, vec1->vec128 ); +} + +static inline float vmathV3MinElem( const VmathVector3 *vec ) +{ + vec_float4 result; + result = fminf4( spu_promote( spu_extract( vec->vec128, 1 ), 0 ), vec->vec128 ); + result = fminf4( spu_promote( spu_extract( vec->vec128, 2 ), 0 ), result ); + return spu_extract( result, 0 ); +} + +static inline float vmathV3Sum( const VmathVector3 *vec ) +{ + return + spu_extract( vec->vec128, 0 ) + + spu_extract( vec->vec128, 1 ) + + spu_extract( vec->vec128, 2 ); +} + +static inline float vmathV3Dot( const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + return spu_extract( _vmathVfDot3( vec0->vec128, vec1->vec128 ), 0 ); +} + +static inline float vmathV3LengthSqr( const VmathVector3 *vec ) +{ + return spu_extract( _vmathVfDot3( vec->vec128, vec->vec128 ), 0 ); +} + +static inline float vmathV3Length( const VmathVector3 *vec ) +{ + return sqrtf( vmathV3LengthSqr( vec ) ); +} + +static inline void vmathV3Normalize( VmathVector3 *result, const VmathVector3 *vec ) +{ + vec_float4 dot = _vmathVfDot3( vec->vec128, vec->vec128 ); + dot = spu_shuffle( dot, dot, (vec_uchar16)spu_splats(0x00010203) ); + result->vec128 = spu_mul( vec->vec128, rsqrtf4( dot ) ); +} + +static inline void vmathV3Cross( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ) +{ + result->vec128 = _vmathVfCross( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV3Select( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1, unsigned int select1 ) +{ + result->vec128 = spu_sel( vec0->vec128, vec1->vec128, spu_splats( (unsigned int)-(select1 > 0) ) ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathV3Print( const VmathVector3 *vec ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = vec->vec128; + printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +static inline void vmathV3Prints( const VmathVector3 *vec, const char *name ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = vec->vec128; + printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +#endif + +static inline void vmathV4Copy( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->vec128 = vec->vec128; +} + +static inline void vmathV4MakeFromElems( VmathVector4 *result, float _x, float _y, float _z, float _w ) +{ + result->vec128 = (vec_float4){ _x, _y, _z, _w }; +} + +static inline void vmathV4MakeFromV3Scalar( VmathVector4 *result, const VmathVector3 *xyz, float _w ) +{ + result->vec128 = spu_shuffle( xyz->vec128, spu_promote( _w, 0 ), _VECTORMATH_SHUF_XYZA ); +} + +static inline void vmathV4MakeFromV3( VmathVector4 *result, const VmathVector3 *vec ) +{ + result->vec128 = spu_sel( vec->vec128, spu_splats(0.0f), (vec_uint4)spu_maskb(0x000f) ); +} + +static inline void vmathV4MakeFromP3( VmathVector4 *result, const VmathPoint3 *pnt ) +{ + result->vec128 = spu_sel( pnt->vec128, spu_splats(1.0f), (vec_uint4)spu_maskb(0x000f) ); +} + +static inline void vmathV4MakeFromQ( VmathVector4 *result, const VmathQuat *quat ) +{ + result->vec128 = quat->vec128; +} + +static inline void vmathV4MakeFromScalar( VmathVector4 *result, float scalar ) +{ + result->vec128 = spu_splats( scalar ); +} + +static inline void vmathV4MakeFrom128( VmathVector4 *result, vec_float4 vf4 ) +{ + result->vec128 = vf4; +} + +static inline void vmathV4MakeXAxis( VmathVector4 *result ) +{ + result->vec128 = _VECTORMATH_UNIT_1000; +} + +static inline void vmathV4MakeYAxis( VmathVector4 *result ) +{ + result->vec128 = _VECTORMATH_UNIT_0100; +} + +static inline void vmathV4MakeZAxis( VmathVector4 *result ) +{ + result->vec128 = _VECTORMATH_UNIT_0010; +} + +static inline void vmathV4MakeWAxis( VmathVector4 *result ) +{ + result->vec128 = _VECTORMATH_UNIT_0001; +} + +static inline void vmathV4Lerp( VmathVector4 *result, float t, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + VmathVector4 tmpV4_0, tmpV4_1; + vmathV4Sub( &tmpV4_0, vec1, vec0 ); + vmathV4ScalarMul( &tmpV4_1, &tmpV4_0, t ); + vmathV4Add( result, vec0, &tmpV4_1 ); +} + +static inline void vmathV4Slerp( VmathVector4 *result, float t, const VmathVector4 *unitVec0, const VmathVector4 *unitVec1 ) +{ + vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + vec_uint4 selectMask; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + cosAngle = _vmathVfDot4( unitVec0->vec128, unitVec1->vec128 ); + cosAngle = spu_shuffle( cosAngle, cosAngle, shuffle_xxxx ); + selectMask = (vec_uint4)spu_cmpgt( spu_splats(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = spu_splats(t); + oneMinusT = spu_sub( spu_splats(1.0f), tttt ); + angles = spu_sel( spu_splats(1.0f), oneMinusT, (vec_uint4)spu_maskb(0x0f00) ); + angles = spu_sel( angles, tttt, (vec_uint4)spu_maskb(0x00f0) ); + angles = spu_mul( angles, angle ); + sines = sinf4( angles ); + scales = divf4( sines, spu_shuffle( sines, sines, shuffle_xxxx ) ); + scale0 = spu_sel( oneMinusT, spu_shuffle( scales, scales, shuffle_yyyy ), selectMask ); + scale1 = spu_sel( tttt, spu_shuffle( scales, scales, shuffle_zzzz ), selectMask ); + result->vec128 = spu_madd( unitVec0->vec128, scale0, spu_mul( unitVec1->vec128, scale1 ) ); +} + +static inline vec_float4 vmathV4Get128( const VmathVector4 *vec ) +{ + return vec->vec128; +} + +static inline void vmathV4StoreHalfFloats( const VmathVector4 *vec0, const VmathVector4 *vec1, const VmathVector4 *vec2, const VmathVector4 *vec3, vec_ushort8 *twoQuads ) +{ + twoQuads[0] = _vmath2VfToHalfFloats(vec0->vec128, vec1->vec128); + twoQuads[1] = _vmath2VfToHalfFloats(vec2->vec128, vec3->vec128); +} + +static inline void vmathV4SetXYZ( VmathVector4 *result, const VmathVector3 *vec ) +{ + result->vec128 = spu_sel( vec->vec128, result->vec128, (vec_uint4)spu_maskb(0x000f) ); +} + +static inline void vmathV4GetXYZ( VmathVector3 *result, const VmathVector4 *vec ) +{ + result->vec128 = vec->vec128; +} + +static inline void vmathV4SetX( VmathVector4 *result, float _x ) +{ + result->vec128 = spu_insert( _x, result->vec128, 0 ); +} + +static inline float vmathV4GetX( const VmathVector4 *vec ) +{ + return spu_extract( vec->vec128, 0 ); +} + +static inline void vmathV4SetY( VmathVector4 *result, float _y ) +{ + result->vec128 = spu_insert( _y, result->vec128, 1 ); +} + +static inline float vmathV4GetY( const VmathVector4 *vec ) +{ + return spu_extract( vec->vec128, 1 ); +} + +static inline void vmathV4SetZ( VmathVector4 *result, float _z ) +{ + result->vec128 = spu_insert( _z, result->vec128, 2 ); +} + +static inline float vmathV4GetZ( const VmathVector4 *vec ) +{ + return spu_extract( vec->vec128, 2 ); +} + +static inline void vmathV4SetW( VmathVector4 *result, float _w ) +{ + result->vec128 = spu_insert( _w, result->vec128, 3 ); +} + +static inline float vmathV4GetW( const VmathVector4 *vec ) +{ + return spu_extract( vec->vec128, 3 ); +} + +static inline void vmathV4SetElem( VmathVector4 *result, int idx, float value ) +{ + result->vec128 = spu_insert( value, result->vec128, idx ); +} + +static inline float vmathV4GetElem( const VmathVector4 *vec, int idx ) +{ + return spu_extract( vec->vec128, idx ); +} + +static inline void vmathV4Add( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->vec128 = spu_add( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV4Sub( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->vec128 = spu_sub( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV4ScalarMul( VmathVector4 *result, const VmathVector4 *vec, float scalar ) +{ + result->vec128 = spu_mul( vec->vec128, spu_splats(scalar) ); +} + +static inline void vmathV4ScalarDiv( VmathVector4 *result, const VmathVector4 *vec, float scalar ) +{ + result->vec128 = divf4( vec->vec128, spu_splats(scalar) ); +} + +static inline void vmathV4Neg( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->vec128 = negatef4( vec->vec128 ); +} + +static inline void vmathV4MulPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->vec128 = spu_mul( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV4DivPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->vec128 = divf4( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV4RecipPerElem( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->vec128 = recipf4( vec->vec128 ); +} + +static inline void vmathV4SqrtPerElem( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->vec128 = sqrtf4( vec->vec128 ); +} + +static inline void vmathV4RsqrtPerElem( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->vec128 = rsqrtf4( vec->vec128 ); +} + +static inline void vmathV4AbsPerElem( VmathVector4 *result, const VmathVector4 *vec ) +{ + result->vec128 = fabsf4( vec->vec128 ); +} + +static inline void vmathV4CopySignPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->vec128 = copysignf4( vec0->vec128, vec1->vec128 ); +} + +static inline void vmathV4MaxPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->vec128 = fmaxf4( vec0->vec128, vec1->vec128 ); +} + +static inline float vmathV4MaxElem( const VmathVector4 *vec ) +{ + vec_float4 result; + result = fmaxf4( spu_promote( spu_extract( vec->vec128, 1 ), 0 ), vec->vec128 ); + result = fmaxf4( spu_promote( spu_extract( vec->vec128, 2 ), 0 ), result ); + result = fmaxf4( spu_promote( spu_extract( vec->vec128, 3 ), 0 ), result ); + return spu_extract( result, 0 ); +} + +static inline void vmathV4MinPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + result->vec128 = fminf4( vec0->vec128, vec1->vec128 ); +} + +static inline float vmathV4MinElem( const VmathVector4 *vec ) +{ + vec_float4 result; + result = fminf4( spu_promote( spu_extract( vec->vec128, 1 ), 0 ), vec->vec128 ); + result = fminf4( spu_promote( spu_extract( vec->vec128, 2 ), 0 ), result ); + result = fminf4( spu_promote( spu_extract( vec->vec128, 3 ), 0 ), result ); + return spu_extract( result, 0 ); +} + +static inline float vmathV4Sum( const VmathVector4 *vec ) +{ + return + spu_extract( vec->vec128, 0 ) + + spu_extract( vec->vec128, 1 ) + + spu_extract( vec->vec128, 2 ) + + spu_extract( vec->vec128, 3 ); +} + +static inline float vmathV4Dot( const VmathVector4 *vec0, const VmathVector4 *vec1 ) +{ + return spu_extract( _vmathVfDot4( vec0->vec128, vec1->vec128 ), 0 ); +} + +static inline float vmathV4LengthSqr( const VmathVector4 *vec ) +{ + return spu_extract( _vmathVfDot4( vec->vec128, vec->vec128 ), 0 ); +} + +static inline float vmathV4Length( const VmathVector4 *vec ) +{ + return sqrtf( vmathV4LengthSqr( vec ) ); +} + +static inline void vmathV4Normalize( VmathVector4 *result, const VmathVector4 *vec ) +{ + vec_float4 dot = _vmathVfDot4( vec->vec128, vec->vec128 ); + result->vec128 = spu_mul( vec->vec128, rsqrtf4( dot ) ); +} + +static inline void vmathV4Select( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1, unsigned int select1 ) +{ + result->vec128 = spu_sel( vec0->vec128, vec1->vec128, spu_splats( (unsigned int)-(select1 > 0) ) ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathV4Print( const VmathVector4 *vec ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = vec->vec128; + printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +static inline void vmathV4Prints( const VmathVector4 *vec, const char *name ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = vec->vec128; + printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +#endif + +static inline void vmathP3Copy( VmathPoint3 *result, const VmathPoint3 *pnt ) +{ + result->vec128 = pnt->vec128; +} + +static inline void vmathP3MakeFromElems( VmathPoint3 *result, float _x, float _y, float _z ) +{ + result->vec128 = (vec_float4){ _x, _y, _z, 0.0f }; +} + +static inline void vmathP3MakeFromV3( VmathPoint3 *result, const VmathVector3 *vec ) +{ + result->vec128 = vec->vec128; +} + +static inline void vmathP3MakeFromScalar( VmathPoint3 *result, float scalar ) +{ + result->vec128 = spu_splats( scalar ); +} + +static inline void vmathP3MakeFrom128( VmathPoint3 *result, vec_float4 vf4 ) +{ + result->vec128 = vf4; +} + +static inline void vmathP3Lerp( VmathPoint3 *result, float t, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + VmathVector3 tmpV3_0, tmpV3_1; + vmathP3Sub( &tmpV3_0, pnt1, pnt0 ); + vmathV3ScalarMul( &tmpV3_1, &tmpV3_0, t ); + vmathP3AddV3( result, pnt0, &tmpV3_1 ); +} + +static inline vec_float4 vmathP3Get128( const VmathPoint3 *pnt ) +{ + return pnt->vec128; +} + +static inline void vmathP3StoreXYZ( const VmathPoint3 *pnt, vec_float4 *quad ) +{ + vec_float4 dstVec = *quad; + vec_uint4 mask = (vec_uint4)spu_maskb(0x000f); + dstVec = spu_sel(pnt->vec128, dstVec, mask); + *quad = dstVec; +} + +static inline void vmathP3LoadXYZArray( VmathPoint3 *pnt0, VmathPoint3 *pnt1, VmathPoint3 *pnt2, VmathPoint3 *pnt3, const vec_float4 *threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz, xyz1, xyz2, xyz3; + xyzx = threeQuads[0]; + yzxy = threeQuads[1]; + zxyz = threeQuads[2]; + xyz1 = spu_shuffle( xyzx, yzxy, _VECTORMATH_SHUF_WABC ); + xyz2 = spu_shuffle( yzxy, zxyz, _VECTORMATH_SHUF_ZWAB ); + xyz3 = spu_rlqwbyte( zxyz, 4 ); + pnt0->vec128 = xyzx; + pnt1->vec128 = xyz1; + pnt2->vec128 = xyz2; + pnt3->vec128 = xyz3; +} + +static inline void vmathP3StoreXYZArray( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, const VmathPoint3 *pnt2, const VmathPoint3 *pnt3, vec_float4 *threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz; + xyzx = spu_shuffle( pnt0->vec128, pnt1->vec128, _VECTORMATH_SHUF_XYZA ); + yzxy = spu_shuffle( pnt1->vec128, pnt2->vec128, _VECTORMATH_SHUF_YZAB ); + zxyz = spu_shuffle( pnt2->vec128, pnt3->vec128, _VECTORMATH_SHUF_ZABC ); + threeQuads[0] = xyzx; + threeQuads[1] = yzxy; + threeQuads[2] = zxyz; +} + +static inline void vmathP3StoreHalfFloats( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, const VmathPoint3 *pnt2, const VmathPoint3 *pnt3, const VmathPoint3 *pnt4, const VmathPoint3 *pnt5, const VmathPoint3 *pnt6, const VmathPoint3 *pnt7, vec_ushort8 *threeQuads ) +{ + vec_float4 xyz0[3]; + vec_float4 xyz1[3]; + vmathP3StoreXYZArray( pnt0, pnt1, pnt2, pnt3, xyz0 ); + vmathP3StoreXYZArray( pnt4, pnt5, pnt6, pnt7, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +} + +static inline void vmathP3SetX( VmathPoint3 *result, float _x ) +{ + result->vec128 = spu_insert( _x, result->vec128, 0 ); +} + +static inline float vmathP3GetX( const VmathPoint3 *pnt ) +{ + return spu_extract( pnt->vec128, 0 ); +} + +static inline void vmathP3SetY( VmathPoint3 *result, float _y ) +{ + result->vec128 = spu_insert( _y, result->vec128, 1 ); +} + +static inline float vmathP3GetY( const VmathPoint3 *pnt ) +{ + return spu_extract( pnt->vec128, 1 ); +} + +static inline void vmathP3SetZ( VmathPoint3 *result, float _z ) +{ + result->vec128 = spu_insert( _z, result->vec128, 2 ); +} + +static inline float vmathP3GetZ( const VmathPoint3 *pnt ) +{ + return spu_extract( pnt->vec128, 2 ); +} + +static inline void vmathP3SetElem( VmathPoint3 *result, int idx, float value ) +{ + result->vec128 = spu_insert( value, result->vec128, idx ); +} + +static inline float vmathP3GetElem( const VmathPoint3 *pnt, int idx ) +{ + return spu_extract( pnt->vec128, idx ); +} + +static inline void vmathP3Sub( VmathVector3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->vec128 = spu_sub( pnt0->vec128, pnt1->vec128 ); +} + +static inline void vmathP3AddV3( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *vec1 ) +{ + result->vec128 = spu_add( pnt->vec128, vec1->vec128 ); +} + +static inline void vmathP3SubV3( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *vec1 ) +{ + result->vec128 = spu_sub( pnt->vec128, vec1->vec128 ); +} + +static inline void vmathP3MulPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->vec128 = spu_mul( pnt0->vec128, pnt1->vec128 ); +} + +static inline void vmathP3DivPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->vec128 = divf4( pnt0->vec128, pnt1->vec128 ); +} + +static inline void vmathP3RecipPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ) +{ + result->vec128 = recipf4( pnt->vec128 ); +} + +static inline void vmathP3SqrtPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ) +{ + result->vec128 = sqrtf4( pnt->vec128 ); +} + +static inline void vmathP3RsqrtPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ) +{ + result->vec128 = rsqrtf4( pnt->vec128 ); +} + +static inline void vmathP3AbsPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ) +{ + result->vec128 = fabsf4( pnt->vec128 ); +} + +static inline void vmathP3CopySignPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->vec128 = copysignf4( pnt0->vec128, pnt1->vec128 ); +} + +static inline void vmathP3MaxPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->vec128 = fmaxf4( pnt0->vec128, pnt1->vec128 ); +} + +static inline float vmathP3MaxElem( const VmathPoint3 *pnt ) +{ + vec_float4 result; + result = fmaxf4( spu_promote( spu_extract( pnt->vec128, 1 ), 0 ), pnt->vec128 ); + result = fmaxf4( spu_promote( spu_extract( pnt->vec128, 2 ), 0 ), result ); + return spu_extract( result, 0 ); +} + +static inline void vmathP3MinPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + result->vec128 = fminf4( pnt0->vec128, pnt1->vec128 ); +} + +static inline float vmathP3MinElem( const VmathPoint3 *pnt ) +{ + vec_float4 result; + result = fminf4( spu_promote( spu_extract( pnt->vec128, 1 ), 0 ), pnt->vec128 ); + result = fminf4( spu_promote( spu_extract( pnt->vec128, 2 ), 0 ), result ); + return spu_extract( result, 0 ); +} + +static inline float vmathP3Sum( const VmathPoint3 *pnt ) +{ + return + spu_extract( pnt->vec128, 0 ) + + spu_extract( pnt->vec128, 1 ) + + spu_extract( pnt->vec128, 2 ); +} + +static inline void vmathP3Scale( VmathPoint3 *result, const VmathPoint3 *pnt, float scaleVal ) +{ + VmathPoint3 tmpP3_0; + vmathP3MakeFromScalar( &tmpP3_0, scaleVal ); + vmathP3MulPerElem( result, pnt, &tmpP3_0 ); +} + +static inline void vmathP3NonUniformScale( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *scaleVec ) +{ + VmathPoint3 tmpP3_0; + vmathP3MakeFromV3( &tmpP3_0, scaleVec ); + vmathP3MulPerElem( result, pnt, &tmpP3_0 ); +} + +static inline float vmathP3Projection( const VmathPoint3 *pnt, const VmathVector3 *unitVec ) +{ + return spu_extract( _vmathVfDot3( pnt->vec128, unitVec->vec128 ), 0 ); +} + +static inline float vmathP3DistSqrFromOrigin( const VmathPoint3 *pnt ) +{ + VmathVector3 tmpV3_0; + vmathV3MakeFromP3( &tmpV3_0, pnt ); + return vmathV3LengthSqr( &tmpV3_0 ); +} + +static inline float vmathP3DistFromOrigin( const VmathPoint3 *pnt ) +{ + VmathVector3 tmpV3_0; + vmathV3MakeFromP3( &tmpV3_0, pnt ); + return vmathV3Length( &tmpV3_0 ); +} + +static inline float vmathP3DistSqr( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + VmathVector3 tmpV3_0; + vmathP3Sub( &tmpV3_0, pnt1, pnt0 ); + return vmathV3LengthSqr( &tmpV3_0 ); +} + +static inline float vmathP3Dist( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ) +{ + VmathVector3 tmpV3_0; + vmathP3Sub( &tmpV3_0, pnt1, pnt0 ); + return vmathV3Length( &tmpV3_0 ); +} + +static inline void vmathP3Select( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, unsigned int select1 ) +{ + result->vec128 = spu_sel( pnt0->vec128, pnt1->vec128, spu_splats( (unsigned int)-(select1 > 0) ) ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathP3Print( const VmathPoint3 *pnt ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = pnt->vec128; + printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +static inline void vmathP3Prints( const VmathPoint3 *pnt, const char *name ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = pnt->vec128; + printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/c/vec_aos_v.h b/Extras/vectormathlibrary/include/vectormath/spu/c/vec_aos_v.h new file mode 100644 index 0000000..7cf0fa9 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/c/vec_aos_v.h @@ -0,0 +1,951 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_AOS_V_C_H +#define _VECTORMATH_VEC_AOS_V_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + * for shuffles, words are labeled [x,y,z,w] [a,b,c,d] + */ +#define _VECTORMATH_SHUF_X 0x00010203 +#define _VECTORMATH_SHUF_Y 0x04050607 +#define _VECTORMATH_SHUF_Z 0x08090a0b +#define _VECTORMATH_SHUF_W 0x0c0d0e0f +#define _VECTORMATH_SHUF_A 0x10111213 +#define _VECTORMATH_SHUF_B 0x14151617 +#define _VECTORMATH_SHUF_C 0x18191a1b +#define _VECTORMATH_SHUF_D 0x1c1d1e1f +#define _VECTORMATH_SHUF_0 0x80808080 +#define _VECTORMATH_SHUF_XYZA (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_A } +#define _VECTORMATH_SHUF_ZXYW (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_W } +#define _VECTORMATH_SHUF_YZXW (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_W } +#define _VECTORMATH_SHUF_WABC (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_C } +#define _VECTORMATH_SHUF_ZWAB (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_B } +#define _VECTORMATH_SHUF_XYZA (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_A } +#define _VECTORMATH_SHUF_YZAB (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_B } +#define _VECTORMATH_SHUF_ZABC (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_C } +#define _VECTORMATH_UNIT_1000 (vec_float4){ 1.0f, 0.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0100 (vec_float4){ 0.0f, 1.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0010 (vec_float4){ 0.0f, 0.0f, 1.0f, 0.0f } +#define _VECTORMATH_UNIT_0001 (vec_float4){ 0.0f, 0.0f, 0.0f, 1.0f } +#define _VECTORMATH_SLERP_TOL 0.999f + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline VmathVector3 vmathV3MakeFromElems_V( float _x, float _y, float _z ) +{ + VmathVector3 result; + vmathV3MakeFromElems(&result, _x, _y, _z); + return result; +} + +static inline VmathVector3 vmathV3MakeFromP3_V( VmathPoint3 pnt ) +{ + VmathVector3 result; + vmathV3MakeFromP3(&result, &pnt); + return result; +} + +static inline VmathVector3 vmathV3MakeFromScalar_V( float scalar ) +{ + VmathVector3 result; + vmathV3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathVector3 vmathV3MakeFrom128_V( vec_float4 vf4 ) +{ + VmathVector3 result; + vmathV3MakeFrom128(&result, vf4); + return result; +} + +static inline VmathVector3 vmathV3MakeXAxis_V( ) +{ + VmathVector3 result; + vmathV3MakeXAxis(&result); + return result; +} + +static inline VmathVector3 vmathV3MakeYAxis_V( ) +{ + VmathVector3 result; + vmathV3MakeYAxis(&result); + return result; +} + +static inline VmathVector3 vmathV3MakeZAxis_V( ) +{ + VmathVector3 result; + vmathV3MakeZAxis(&result); + return result; +} + +static inline VmathVector3 vmathV3Lerp_V( float t, VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3Lerp(&result, t, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3Slerp_V( float t, VmathVector3 unitVec0, VmathVector3 unitVec1 ) +{ + VmathVector3 result; + vmathV3Slerp(&result, t, &unitVec0, &unitVec1); + return result; +} + +static inline vec_float4 vmathV3Get128_V( VmathVector3 vec ) +{ + return vmathV3Get128(&vec); +} + +static inline void vmathV3StoreXYZ_V( VmathVector3 vec, vec_float4 *quad ) +{ + vmathV3StoreXYZ(&vec, quad); +} + +static inline void vmathV3LoadXYZArray_V( VmathVector3 *vec0, VmathVector3 *vec1, VmathVector3 *vec2, VmathVector3 *vec3, const vec_float4 *threeQuads ) +{ + vmathV3LoadXYZArray(vec0, vec1, vec2, vec3, threeQuads); +} + +static inline void vmathV3StoreXYZArray_V( VmathVector3 vec0, VmathVector3 vec1, VmathVector3 vec2, VmathVector3 vec3, vec_float4 *threeQuads ) +{ + vmathV3StoreXYZArray(&vec0, &vec1, &vec2, &vec3, threeQuads); +} + +static inline void vmathV3StoreHalfFloats_V( VmathVector3 vec0, VmathVector3 vec1, VmathVector3 vec2, VmathVector3 vec3, VmathVector3 vec4, VmathVector3 vec5, VmathVector3 vec6, VmathVector3 vec7, vec_ushort8 *threeQuads ) +{ + vmathV3StoreHalfFloats(&vec0, &vec1, &vec2, &vec3, &vec4, &vec5, &vec6, &vec7, threeQuads); +} + +static inline void vmathV3SetX_V( VmathVector3 *result, float _x ) +{ + vmathV3SetX(result, _x); +} + +static inline float vmathV3GetX_V( VmathVector3 vec ) +{ + return vmathV3GetX(&vec); +} + +static inline void vmathV3SetY_V( VmathVector3 *result, float _y ) +{ + vmathV3SetY(result, _y); +} + +static inline float vmathV3GetY_V( VmathVector3 vec ) +{ + return vmathV3GetY(&vec); +} + +static inline void vmathV3SetZ_V( VmathVector3 *result, float _z ) +{ + vmathV3SetZ(result, _z); +} + +static inline float vmathV3GetZ_V( VmathVector3 vec ) +{ + return vmathV3GetZ(&vec); +} + +static inline void vmathV3SetElem_V( VmathVector3 *result, int idx, float value ) +{ + vmathV3SetElem(result, idx, value); +} + +static inline float vmathV3GetElem_V( VmathVector3 vec, int idx ) +{ + return vmathV3GetElem(&vec, idx); +} + +static inline VmathVector3 vmathV3Add_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3Add(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3Sub_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3Sub(&result, &vec0, &vec1); + return result; +} + +static inline VmathPoint3 vmathV3AddP3_V( VmathVector3 vec, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathV3AddP3(&result, &vec, &pnt1); + return result; +} + +static inline VmathVector3 vmathV3ScalarMul_V( VmathVector3 vec, float scalar ) +{ + VmathVector3 result; + vmathV3ScalarMul(&result, &vec, scalar); + return result; +} + +static inline VmathVector3 vmathV3ScalarDiv_V( VmathVector3 vec, float scalar ) +{ + VmathVector3 result; + vmathV3ScalarDiv(&result, &vec, scalar); + return result; +} + +static inline VmathVector3 vmathV3Neg_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3Neg(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3MulPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3MulPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3DivPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3DivPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3RecipPerElem_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3RecipPerElem(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3SqrtPerElem_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3SqrtPerElem(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3RsqrtPerElem_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3RsqrtPerElem(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3AbsPerElem_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3AbsPerElem(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3CopySignPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3CopySignPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3MaxPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3MaxPerElem(&result, &vec0, &vec1); + return result; +} + +static inline float vmathV3MaxElem_V( VmathVector3 vec ) +{ + return vmathV3MaxElem(&vec); +} + +static inline VmathVector3 vmathV3MinPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3MinPerElem(&result, &vec0, &vec1); + return result; +} + +static inline float vmathV3MinElem_V( VmathVector3 vec ) +{ + return vmathV3MinElem(&vec); +} + +static inline float vmathV3Sum_V( VmathVector3 vec ) +{ + return vmathV3Sum(&vec); +} + +static inline float vmathV3Dot_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + return vmathV3Dot(&vec0, &vec1); +} + +static inline float vmathV3LengthSqr_V( VmathVector3 vec ) +{ + return vmathV3LengthSqr(&vec); +} + +static inline float vmathV3Length_V( VmathVector3 vec ) +{ + return vmathV3Length(&vec); +} + +static inline VmathVector3 vmathV3Normalize_V( VmathVector3 vec ) +{ + VmathVector3 result; + vmathV3Normalize(&result, &vec); + return result; +} + +static inline VmathVector3 vmathV3Cross_V( VmathVector3 vec0, VmathVector3 vec1 ) +{ + VmathVector3 result; + vmathV3Cross(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector3 vmathV3Select_V( VmathVector3 vec0, VmathVector3 vec1, unsigned int select1 ) +{ + VmathVector3 result; + vmathV3Select(&result, &vec0, &vec1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathV3Print_V( VmathVector3 vec ) +{ + vmathV3Print(&vec); +} + +static inline void vmathV3Prints_V( VmathVector3 vec, const char *name ) +{ + vmathV3Prints(&vec, name); +} + +#endif + +static inline VmathVector4 vmathV4MakeFromElems_V( float _x, float _y, float _z, float _w ) +{ + VmathVector4 result; + vmathV4MakeFromElems(&result, _x, _y, _z, _w); + return result; +} + +static inline VmathVector4 vmathV4MakeFromV3Scalar_V( VmathVector3 xyz, float _w ) +{ + VmathVector4 result; + vmathV4MakeFromV3Scalar(&result, &xyz, _w); + return result; +} + +static inline VmathVector4 vmathV4MakeFromV3_V( VmathVector3 vec ) +{ + VmathVector4 result; + vmathV4MakeFromV3(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4MakeFromP3_V( VmathPoint3 pnt ) +{ + VmathVector4 result; + vmathV4MakeFromP3(&result, &pnt); + return result; +} + +static inline VmathVector4 vmathV4MakeFromQ_V( VmathQuat quat ) +{ + VmathVector4 result; + vmathV4MakeFromQ(&result, &quat); + return result; +} + +static inline VmathVector4 vmathV4MakeFromScalar_V( float scalar ) +{ + VmathVector4 result; + vmathV4MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathVector4 vmathV4MakeFrom128_V( vec_float4 vf4 ) +{ + VmathVector4 result; + vmathV4MakeFrom128(&result, vf4); + return result; +} + +static inline VmathVector4 vmathV4MakeXAxis_V( ) +{ + VmathVector4 result; + vmathV4MakeXAxis(&result); + return result; +} + +static inline VmathVector4 vmathV4MakeYAxis_V( ) +{ + VmathVector4 result; + vmathV4MakeYAxis(&result); + return result; +} + +static inline VmathVector4 vmathV4MakeZAxis_V( ) +{ + VmathVector4 result; + vmathV4MakeZAxis(&result); + return result; +} + +static inline VmathVector4 vmathV4MakeWAxis_V( ) +{ + VmathVector4 result; + vmathV4MakeWAxis(&result); + return result; +} + +static inline VmathVector4 vmathV4Lerp_V( float t, VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4Lerp(&result, t, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4Slerp_V( float t, VmathVector4 unitVec0, VmathVector4 unitVec1 ) +{ + VmathVector4 result; + vmathV4Slerp(&result, t, &unitVec0, &unitVec1); + return result; +} + +static inline vec_float4 vmathV4Get128_V( VmathVector4 vec ) +{ + return vmathV4Get128(&vec); +} + +static inline void vmathV4StoreHalfFloats_V( VmathVector4 vec0, VmathVector4 vec1, VmathVector4 vec2, VmathVector4 vec3, vec_ushort8 *twoQuads ) +{ + vmathV4StoreHalfFloats(&vec0, &vec1, &vec2, &vec3, twoQuads); +} + +static inline void vmathV4SetXYZ_V( VmathVector4 *result, VmathVector3 vec ) +{ + vmathV4SetXYZ(result, &vec); +} + +static inline VmathVector3 vmathV4GetXYZ_V( VmathVector4 vec ) +{ + VmathVector3 result; + vmathV4GetXYZ(&result, &vec); + return result; +} + +static inline void vmathV4SetX_V( VmathVector4 *result, float _x ) +{ + vmathV4SetX(result, _x); +} + +static inline float vmathV4GetX_V( VmathVector4 vec ) +{ + return vmathV4GetX(&vec); +} + +static inline void vmathV4SetY_V( VmathVector4 *result, float _y ) +{ + vmathV4SetY(result, _y); +} + +static inline float vmathV4GetY_V( VmathVector4 vec ) +{ + return vmathV4GetY(&vec); +} + +static inline void vmathV4SetZ_V( VmathVector4 *result, float _z ) +{ + vmathV4SetZ(result, _z); +} + +static inline float vmathV4GetZ_V( VmathVector4 vec ) +{ + return vmathV4GetZ(&vec); +} + +static inline void vmathV4SetW_V( VmathVector4 *result, float _w ) +{ + vmathV4SetW(result, _w); +} + +static inline float vmathV4GetW_V( VmathVector4 vec ) +{ + return vmathV4GetW(&vec); +} + +static inline void vmathV4SetElem_V( VmathVector4 *result, int idx, float value ) +{ + vmathV4SetElem(result, idx, value); +} + +static inline float vmathV4GetElem_V( VmathVector4 vec, int idx ) +{ + return vmathV4GetElem(&vec, idx); +} + +static inline VmathVector4 vmathV4Add_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4Add(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4Sub_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4Sub(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4ScalarMul_V( VmathVector4 vec, float scalar ) +{ + VmathVector4 result; + vmathV4ScalarMul(&result, &vec, scalar); + return result; +} + +static inline VmathVector4 vmathV4ScalarDiv_V( VmathVector4 vec, float scalar ) +{ + VmathVector4 result; + vmathV4ScalarDiv(&result, &vec, scalar); + return result; +} + +static inline VmathVector4 vmathV4Neg_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4Neg(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4MulPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4MulPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4DivPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4DivPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4RecipPerElem_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4RecipPerElem(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4SqrtPerElem_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4SqrtPerElem(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4RsqrtPerElem_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4RsqrtPerElem(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4AbsPerElem_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4AbsPerElem(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4CopySignPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4CopySignPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathVector4 vmathV4MaxPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4MaxPerElem(&result, &vec0, &vec1); + return result; +} + +static inline float vmathV4MaxElem_V( VmathVector4 vec ) +{ + return vmathV4MaxElem(&vec); +} + +static inline VmathVector4 vmathV4MinPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + VmathVector4 result; + vmathV4MinPerElem(&result, &vec0, &vec1); + return result; +} + +static inline float vmathV4MinElem_V( VmathVector4 vec ) +{ + return vmathV4MinElem(&vec); +} + +static inline float vmathV4Sum_V( VmathVector4 vec ) +{ + return vmathV4Sum(&vec); +} + +static inline float vmathV4Dot_V( VmathVector4 vec0, VmathVector4 vec1 ) +{ + return vmathV4Dot(&vec0, &vec1); +} + +static inline float vmathV4LengthSqr_V( VmathVector4 vec ) +{ + return vmathV4LengthSqr(&vec); +} + +static inline float vmathV4Length_V( VmathVector4 vec ) +{ + return vmathV4Length(&vec); +} + +static inline VmathVector4 vmathV4Normalize_V( VmathVector4 vec ) +{ + VmathVector4 result; + vmathV4Normalize(&result, &vec); + return result; +} + +static inline VmathVector4 vmathV4Select_V( VmathVector4 vec0, VmathVector4 vec1, unsigned int select1 ) +{ + VmathVector4 result; + vmathV4Select(&result, &vec0, &vec1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathV4Print_V( VmathVector4 vec ) +{ + vmathV4Print(&vec); +} + +static inline void vmathV4Prints_V( VmathVector4 vec, const char *name ) +{ + vmathV4Prints(&vec, name); +} + +#endif + +static inline VmathPoint3 vmathP3MakeFromElems_V( float _x, float _y, float _z ) +{ + VmathPoint3 result; + vmathP3MakeFromElems(&result, _x, _y, _z); + return result; +} + +static inline VmathPoint3 vmathP3MakeFromV3_V( VmathVector3 vec ) +{ + VmathPoint3 result; + vmathP3MakeFromV3(&result, &vec); + return result; +} + +static inline VmathPoint3 vmathP3MakeFromScalar_V( float scalar ) +{ + VmathPoint3 result; + vmathP3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathPoint3 vmathP3MakeFrom128_V( vec_float4 vf4 ) +{ + VmathPoint3 result; + vmathP3MakeFrom128(&result, vf4); + return result; +} + +static inline VmathPoint3 vmathP3Lerp_V( float t, VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3Lerp(&result, t, &pnt0, &pnt1); + return result; +} + +static inline vec_float4 vmathP3Get128_V( VmathPoint3 pnt ) +{ + return vmathP3Get128(&pnt); +} + +static inline void vmathP3StoreXYZ_V( VmathPoint3 pnt, vec_float4 *quad ) +{ + vmathP3StoreXYZ(&pnt, quad); +} + +static inline void vmathP3LoadXYZArray_V( VmathPoint3 *pnt0, VmathPoint3 *pnt1, VmathPoint3 *pnt2, VmathPoint3 *pnt3, const vec_float4 *threeQuads ) +{ + vmathP3LoadXYZArray(pnt0, pnt1, pnt2, pnt3, threeQuads); +} + +static inline void vmathP3StoreXYZArray_V( VmathPoint3 pnt0, VmathPoint3 pnt1, VmathPoint3 pnt2, VmathPoint3 pnt3, vec_float4 *threeQuads ) +{ + vmathP3StoreXYZArray(&pnt0, &pnt1, &pnt2, &pnt3, threeQuads); +} + +static inline void vmathP3StoreHalfFloats_V( VmathPoint3 pnt0, VmathPoint3 pnt1, VmathPoint3 pnt2, VmathPoint3 pnt3, VmathPoint3 pnt4, VmathPoint3 pnt5, VmathPoint3 pnt6, VmathPoint3 pnt7, vec_ushort8 *threeQuads ) +{ + vmathP3StoreHalfFloats(&pnt0, &pnt1, &pnt2, &pnt3, &pnt4, &pnt5, &pnt6, &pnt7, threeQuads); +} + +static inline void vmathP3SetX_V( VmathPoint3 *result, float _x ) +{ + vmathP3SetX(result, _x); +} + +static inline float vmathP3GetX_V( VmathPoint3 pnt ) +{ + return vmathP3GetX(&pnt); +} + +static inline void vmathP3SetY_V( VmathPoint3 *result, float _y ) +{ + vmathP3SetY(result, _y); +} + +static inline float vmathP3GetY_V( VmathPoint3 pnt ) +{ + return vmathP3GetY(&pnt); +} + +static inline void vmathP3SetZ_V( VmathPoint3 *result, float _z ) +{ + vmathP3SetZ(result, _z); +} + +static inline float vmathP3GetZ_V( VmathPoint3 pnt ) +{ + return vmathP3GetZ(&pnt); +} + +static inline void vmathP3SetElem_V( VmathPoint3 *result, int idx, float value ) +{ + vmathP3SetElem(result, idx, value); +} + +static inline float vmathP3GetElem_V( VmathPoint3 pnt, int idx ) +{ + return vmathP3GetElem(&pnt, idx); +} + +static inline VmathVector3 vmathP3Sub_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathVector3 result; + vmathP3Sub(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathPoint3 vmathP3AddV3_V( VmathPoint3 pnt, VmathVector3 vec1 ) +{ + VmathPoint3 result; + vmathP3AddV3(&result, &pnt, &vec1); + return result; +} + +static inline VmathPoint3 vmathP3SubV3_V( VmathPoint3 pnt, VmathVector3 vec1 ) +{ + VmathPoint3 result; + vmathP3SubV3(&result, &pnt, &vec1); + return result; +} + +static inline VmathPoint3 vmathP3MulPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3MulPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathPoint3 vmathP3DivPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3DivPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathPoint3 vmathP3RecipPerElem_V( VmathPoint3 pnt ) +{ + VmathPoint3 result; + vmathP3RecipPerElem(&result, &pnt); + return result; +} + +static inline VmathPoint3 vmathP3SqrtPerElem_V( VmathPoint3 pnt ) +{ + VmathPoint3 result; + vmathP3SqrtPerElem(&result, &pnt); + return result; +} + +static inline VmathPoint3 vmathP3RsqrtPerElem_V( VmathPoint3 pnt ) +{ + VmathPoint3 result; + vmathP3RsqrtPerElem(&result, &pnt); + return result; +} + +static inline VmathPoint3 vmathP3AbsPerElem_V( VmathPoint3 pnt ) +{ + VmathPoint3 result; + vmathP3AbsPerElem(&result, &pnt); + return result; +} + +static inline VmathPoint3 vmathP3CopySignPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3CopySignPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathPoint3 vmathP3MaxPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3MaxPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline float vmathP3MaxElem_V( VmathPoint3 pnt ) +{ + return vmathP3MaxElem(&pnt); +} + +static inline VmathPoint3 vmathP3MinPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + VmathPoint3 result; + vmathP3MinPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline float vmathP3MinElem_V( VmathPoint3 pnt ) +{ + return vmathP3MinElem(&pnt); +} + +static inline float vmathP3Sum_V( VmathPoint3 pnt ) +{ + return vmathP3Sum(&pnt); +} + +static inline VmathPoint3 vmathP3Scale_V( VmathPoint3 pnt, float scaleVal ) +{ + VmathPoint3 result; + vmathP3Scale(&result, &pnt, scaleVal); + return result; +} + +static inline VmathPoint3 vmathP3NonUniformScale_V( VmathPoint3 pnt, VmathVector3 scaleVec ) +{ + VmathPoint3 result; + vmathP3NonUniformScale(&result, &pnt, &scaleVec); + return result; +} + +static inline float vmathP3Projection_V( VmathPoint3 pnt, VmathVector3 unitVec ) +{ + return vmathP3Projection(&pnt, &unitVec); +} + +static inline float vmathP3DistSqrFromOrigin_V( VmathPoint3 pnt ) +{ + return vmathP3DistSqrFromOrigin(&pnt); +} + +static inline float vmathP3DistFromOrigin_V( VmathPoint3 pnt ) +{ + return vmathP3DistFromOrigin(&pnt); +} + +static inline float vmathP3DistSqr_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + return vmathP3DistSqr(&pnt0, &pnt1); +} + +static inline float vmathP3Dist_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ) +{ + return vmathP3Dist(&pnt0, &pnt1); +} + +static inline VmathPoint3 vmathP3Select_V( VmathPoint3 pnt0, VmathPoint3 pnt1, unsigned int select1 ) +{ + VmathPoint3 result; + vmathP3Select(&result, &pnt0, &pnt1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathP3Print_V( VmathPoint3 pnt ) +{ + vmathP3Print(&pnt); +} + +static inline void vmathP3Prints_V( VmathPoint3 pnt, const char *name ) +{ + vmathP3Prints(&pnt, name); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/c/vec_soa.h b/Extras/vectormathlibrary/include/vectormath/spu/c/vec_soa.h new file mode 100644 index 0000000..608b385 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/c/vec_soa.h @@ -0,0 +1,1237 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_SOA_C_H +#define _VECTORMATH_VEC_SOA_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + * for shuffles, words are labeled [x,y,z,w] [a,b,c,d] + */ +#define _VECTORMATH_SHUF_X 0x00010203 +#define _VECTORMATH_SHUF_Y 0x04050607 +#define _VECTORMATH_SHUF_Z 0x08090a0b +#define _VECTORMATH_SHUF_W 0x0c0d0e0f +#define _VECTORMATH_SHUF_A 0x10111213 +#define _VECTORMATH_SHUF_B 0x14151617 +#define _VECTORMATH_SHUF_C 0x18191a1b +#define _VECTORMATH_SHUF_D 0x1c1d1e1f +#define _VECTORMATH_SHUF_0 0x80808080 +#define _VECTORMATH_SHUF_XAYB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_ZCWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_ZBW0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_XCY0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_ZDW0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_D, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_XAZC ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_C }) +#define _VECTORMATH_SHUF_ZDXB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_D, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_YBWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_XDZB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_D, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_YAWC ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_C }) +#define _VECTORMATH_SHUF_ZBXD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_XYCD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SLERP_TOL 0.999f + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline void vmathSoaV3Copy( VmathSoaVector3 *result, const VmathSoaVector3 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; +} + +static inline void vmathSoaV3MakeFromElems( VmathSoaVector3 *result, vec_float4 _x, vec_float4 _y, vec_float4 _z ) +{ + result->x = _x; + result->y = _y; + result->z = _z; +} + +static inline void vmathSoaV3MakeFromP3( VmathSoaVector3 *result, const VmathSoaPoint3 *pnt ) +{ + result->x = pnt->x; + result->y = pnt->y; + result->z = pnt->z; +} + +static inline void vmathSoaV3MakeFromScalar( VmathSoaVector3 *result, vec_float4 scalar ) +{ + result->x = scalar; + result->y = scalar; + result->z = scalar; +} + +static inline void vmathSoaV3MakeFromAos( VmathSoaVector3 *result, const VmathVector3 *vec ) +{ + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + vec_float4 vec128 = vec->vec128; + result->x = spu_shuffle( vec128, vec128, shuffle_xxxx ); + result->y = spu_shuffle( vec128, vec128, shuffle_yyyy ); + result->z = spu_shuffle( vec128, vec128, shuffle_zzzz ); +} + +static inline void vmathSoaV3MakeFrom4Aos( VmathSoaVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1, const VmathVector3 *vec2, const VmathVector3 *vec3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = spu_shuffle( vec0->vec128, vec2->vec128, _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( vec1->vec128, vec3->vec128, _VECTORMATH_SHUF_XAYB ); + tmp2 = spu_shuffle( vec0->vec128, vec2->vec128, _VECTORMATH_SHUF_ZCWD ); + tmp3 = spu_shuffle( vec1->vec128, vec3->vec128, _VECTORMATH_SHUF_ZCWD ); + result->x = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_XAYB ); + result->y = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_ZCWD ); + result->z = spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_XAYB ); +} + +static inline void vmathSoaV3MakeXAxis( VmathSoaVector3 *result ) +{ + vmathSoaV3MakeFromElems( result, spu_splats(1.0f), spu_splats(0.0f), spu_splats(0.0f) ); +} + +static inline void vmathSoaV3MakeYAxis( VmathSoaVector3 *result ) +{ + vmathSoaV3MakeFromElems( result, spu_splats(0.0f), spu_splats(1.0f), spu_splats(0.0f) ); +} + +static inline void vmathSoaV3MakeZAxis( VmathSoaVector3 *result ) +{ + vmathSoaV3MakeFromElems( result, spu_splats(0.0f), spu_splats(0.0f), spu_splats(1.0f) ); +} + +static inline void vmathSoaV3Lerp( VmathSoaVector3 *result, vec_float4 t, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + VmathSoaVector3 tmpV3_0, tmpV3_1; + vmathSoaV3Sub( &tmpV3_0, vec1, vec0 ); + vmathSoaV3ScalarMul( &tmpV3_1, &tmpV3_0, t ); + vmathSoaV3Add( result, vec0, &tmpV3_1 ); +} + +static inline void vmathSoaV3Slerp( VmathSoaVector3 *result, vec_float4 t, const VmathSoaVector3 *unitVec0, const VmathSoaVector3 *unitVec1 ) +{ + VmathSoaVector3 tmpV3_0, tmpV3_1; + vec_float4 recipSinAngle, scale0, scale1, cosAngle, angle; + vec_uint4 selectMask; + cosAngle = vmathSoaV3Dot( unitVec0, unitVec1 ); + selectMask = (vec_uint4)spu_cmpgt( spu_splats(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + recipSinAngle = recipf4( sinf4( angle ) ); + scale0 = spu_sel( spu_sub( spu_splats(1.0f), t ), spu_mul( sinf4( spu_mul( spu_sub( spu_splats(1.0f), t ), angle ) ), recipSinAngle ), selectMask ); + scale1 = spu_sel( t, spu_mul( sinf4( spu_mul( t, angle ) ), recipSinAngle ), selectMask ); + vmathSoaV3ScalarMul( &tmpV3_0, unitVec0, scale0 ); + vmathSoaV3ScalarMul( &tmpV3_1, unitVec1, scale1 ); + vmathSoaV3Add( result, &tmpV3_0, &tmpV3_1 ); +} + +static inline void vmathSoaV3Get4Aos( const VmathSoaVector3 *vec, VmathVector3 *result0, VmathVector3 *result1, VmathVector3 *result2, VmathVector3 *result3 ) +{ + vec_float4 tmp0, tmp1; + tmp0 = spu_shuffle( vec->x, vec->z, _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( vec->x, vec->z, _VECTORMATH_SHUF_ZCWD ); + vmathV3MakeFrom128( result0, spu_shuffle( tmp0, vec->y, _VECTORMATH_SHUF_XAYB ) ); + vmathV3MakeFrom128( result1, spu_shuffle( tmp0, vec->y, _VECTORMATH_SHUF_ZBW0 ) ); + vmathV3MakeFrom128( result2, spu_shuffle( tmp1, vec->y, _VECTORMATH_SHUF_XCY0 ) ); + vmathV3MakeFrom128( result3, spu_shuffle( tmp1, vec->y, _VECTORMATH_SHUF_ZDW0 ) ); +} + +static inline void vmathSoaV3LoadXYZArray( VmathSoaVector3 *vec, const vec_float4 *threeQuads ) +{ + vec_float4 xyxy, yzyz, zxzx, xyzx, yzxy, zxyz; + xyzx = threeQuads[0]; + yzxy = threeQuads[1]; + zxyz = threeQuads[2]; + xyxy = spu_shuffle( xyzx, yzxy, _VECTORMATH_SHUF_XYCD ); + zxzx = spu_shuffle( zxyz, xyzx, _VECTORMATH_SHUF_XYCD ); + yzyz = spu_shuffle( yzxy, zxyz, _VECTORMATH_SHUF_XYCD ); + vmathSoaV3SetX( vec, spu_shuffle( xyxy, zxzx, _VECTORMATH_SHUF_XDZB ) ); + vmathSoaV3SetY( vec, spu_shuffle( xyxy, yzyz, _VECTORMATH_SHUF_YAWC ) ); + vmathSoaV3SetZ( vec, spu_shuffle( zxzx, yzyz, _VECTORMATH_SHUF_ZBXD ) ); +} + +static inline void vmathSoaV3StoreXYZArray( const VmathSoaVector3 *vec, vec_float4 *threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz, xyxy, zxzx, yzyz; + xyxy = spu_shuffle( vec->x, vec->y, _VECTORMATH_SHUF_XAZC ); + zxzx = spu_shuffle( vec->z, vec->x, _VECTORMATH_SHUF_ZDXB ); + yzyz = spu_shuffle( vec->y, vec->z, _VECTORMATH_SHUF_YBWD ); + xyzx = spu_shuffle( xyxy, zxzx, _VECTORMATH_SHUF_XYCD ); + yzxy = spu_shuffle( yzyz, xyxy, _VECTORMATH_SHUF_XYCD ); + zxyz = spu_shuffle( zxzx, yzyz, _VECTORMATH_SHUF_XYCD ); + threeQuads[0] = xyzx; + threeQuads[1] = yzxy; + threeQuads[2] = zxyz; +} + +static inline void vmathSoaV3StoreHalfFloats( const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1, vec_ushort8 *threeQuads ) +{ + vec_float4 xyz0[3]; + vec_float4 xyz1[3]; + vmathSoaV3StoreXYZArray( vec0, xyz0 ); + vmathSoaV3StoreXYZArray( vec1, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +} + +static inline void vmathSoaV3SetX( VmathSoaVector3 *result, vec_float4 _x ) +{ + result->x = _x; +} + +static inline vec_float4 vmathSoaV3GetX( const VmathSoaVector3 *vec ) +{ + return vec->x; +} + +static inline void vmathSoaV3SetY( VmathSoaVector3 *result, vec_float4 _y ) +{ + result->y = _y; +} + +static inline vec_float4 vmathSoaV3GetY( const VmathSoaVector3 *vec ) +{ + return vec->y; +} + +static inline void vmathSoaV3SetZ( VmathSoaVector3 *result, vec_float4 _z ) +{ + result->z = _z; +} + +static inline vec_float4 vmathSoaV3GetZ( const VmathSoaVector3 *vec ) +{ + return vec->z; +} + +static inline void vmathSoaV3SetElem( VmathSoaVector3 *result, int idx, vec_float4 value ) +{ + *(&result->x + idx) = value; +} + +static inline vec_float4 vmathSoaV3GetElem( const VmathSoaVector3 *vec, int idx ) +{ + return *(&vec->x + idx); +} + +static inline void vmathSoaV3Add( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + result->x = spu_add( vec0->x, vec1->x ); + result->y = spu_add( vec0->y, vec1->y ); + result->z = spu_add( vec0->z, vec1->z ); +} + +static inline void vmathSoaV3Sub( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + result->x = spu_sub( vec0->x, vec1->x ); + result->y = spu_sub( vec0->y, vec1->y ); + result->z = spu_sub( vec0->z, vec1->z ); +} + +static inline void vmathSoaV3AddP3( VmathSoaPoint3 *result, const VmathSoaVector3 *vec, const VmathSoaPoint3 *pnt1 ) +{ + result->x = spu_add( vec->x, pnt1->x ); + result->y = spu_add( vec->y, pnt1->y ); + result->z = spu_add( vec->z, pnt1->z ); +} + +static inline void vmathSoaV3ScalarMul( VmathSoaVector3 *result, const VmathSoaVector3 *vec, vec_float4 scalar ) +{ + result->x = spu_mul( vec->x, scalar ); + result->y = spu_mul( vec->y, scalar ); + result->z = spu_mul( vec->z, scalar ); +} + +static inline void vmathSoaV3ScalarDiv( VmathSoaVector3 *result, const VmathSoaVector3 *vec, vec_float4 scalar ) +{ + result->x = divf4( vec->x, scalar ); + result->y = divf4( vec->y, scalar ); + result->z = divf4( vec->z, scalar ); +} + +static inline void vmathSoaV3Neg( VmathSoaVector3 *result, const VmathSoaVector3 *vec ) +{ + result->x = negatef4( vec->x ); + result->y = negatef4( vec->y ); + result->z = negatef4( vec->z ); +} + +static inline void vmathSoaV3MulPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + result->x = spu_mul( vec0->x, vec1->x ); + result->y = spu_mul( vec0->y, vec1->y ); + result->z = spu_mul( vec0->z, vec1->z ); +} + +static inline void vmathSoaV3DivPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + result->x = divf4( vec0->x, vec1->x ); + result->y = divf4( vec0->y, vec1->y ); + result->z = divf4( vec0->z, vec1->z ); +} + +static inline void vmathSoaV3RecipPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec ) +{ + result->x = recipf4( vec->x ); + result->y = recipf4( vec->y ); + result->z = recipf4( vec->z ); +} + +static inline void vmathSoaV3SqrtPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec ) +{ + result->x = sqrtf4( vec->x ); + result->y = sqrtf4( vec->y ); + result->z = sqrtf4( vec->z ); +} + +static inline void vmathSoaV3RsqrtPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec ) +{ + result->x = rsqrtf4( vec->x ); + result->y = rsqrtf4( vec->y ); + result->z = rsqrtf4( vec->z ); +} + +static inline void vmathSoaV3AbsPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec ) +{ + result->x = fabsf4( vec->x ); + result->y = fabsf4( vec->y ); + result->z = fabsf4( vec->z ); +} + +static inline void vmathSoaV3CopySignPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + result->x = copysignf4( vec0->x, vec1->x ); + result->y = copysignf4( vec0->y, vec1->y ); + result->z = copysignf4( vec0->z, vec1->z ); +} + +static inline void vmathSoaV3MaxPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + result->x = fmaxf4( vec0->x, vec1->x ); + result->y = fmaxf4( vec0->y, vec1->y ); + result->z = fmaxf4( vec0->z, vec1->z ); +} + +static inline vec_float4 vmathSoaV3MaxElem( const VmathSoaVector3 *vec ) +{ + vec_float4 result; + result = fmaxf4( vec->x, vec->y ); + result = fmaxf4( vec->z, result ); + return result; +} + +static inline void vmathSoaV3MinPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + result->x = fminf4( vec0->x, vec1->x ); + result->y = fminf4( vec0->y, vec1->y ); + result->z = fminf4( vec0->z, vec1->z ); +} + +static inline vec_float4 vmathSoaV3MinElem( const VmathSoaVector3 *vec ) +{ + vec_float4 result; + result = fminf4( vec->x, vec->y ); + result = fminf4( vec->z, result ); + return result; +} + +static inline vec_float4 vmathSoaV3Sum( const VmathSoaVector3 *vec ) +{ + vec_float4 result; + result = spu_add( vec->x, vec->y ); + result = spu_add( result, vec->z ); + return result; +} + +static inline vec_float4 vmathSoaV3Dot( const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + vec_float4 result; + result = spu_mul( vec0->x, vec1->x ); + result = spu_add( result, spu_mul( vec0->y, vec1->y ) ); + result = spu_add( result, spu_mul( vec0->z, vec1->z ) ); + return result; +} + +static inline vec_float4 vmathSoaV3LengthSqr( const VmathSoaVector3 *vec ) +{ + vec_float4 result; + result = spu_mul( vec->x, vec->x ); + result = spu_add( result, spu_mul( vec->y, vec->y ) ); + result = spu_add( result, spu_mul( vec->z, vec->z ) ); + return result; +} + +static inline vec_float4 vmathSoaV3Length( const VmathSoaVector3 *vec ) +{ + return sqrtf4( vmathSoaV3LengthSqr( vec ) ); +} + +static inline void vmathSoaV3Normalize( VmathSoaVector3 *result, const VmathSoaVector3 *vec ) +{ + vec_float4 lenSqr, lenInv; + lenSqr = vmathSoaV3LengthSqr( vec ); + lenInv = rsqrtf4( lenSqr ); + result->x = spu_mul( vec->x, lenInv ); + result->y = spu_mul( vec->y, lenInv ); + result->z = spu_mul( vec->z, lenInv ); +} + +static inline void vmathSoaV3Cross( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ) +{ + vec_float4 tmpX, tmpY, tmpZ; + tmpX = spu_sub( spu_mul( vec0->y, vec1->z ), spu_mul( vec0->z, vec1->y ) ); + tmpY = spu_sub( spu_mul( vec0->z, vec1->x ), spu_mul( vec0->x, vec1->z ) ); + tmpZ = spu_sub( spu_mul( vec0->x, vec1->y ), spu_mul( vec0->y, vec1->x ) ); + vmathSoaV3MakeFromElems( result, tmpX, tmpY, tmpZ ); +} + +static inline void vmathSoaV3Select( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1, vec_uint4 select1 ) +{ + result->x = spu_sel( vec0->x, vec1->x, select1 ); + result->y = spu_sel( vec0->y, vec1->y, select1 ); + result->z = spu_sel( vec0->z, vec1->z, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaV3Print( const VmathSoaVector3 *vec ) +{ + VmathVector3 vec0, vec1, vec2, vec3; + vmathSoaV3Get4Aos( vec, &vec0, &vec1, &vec2, &vec3 ); + printf("slot 0:\n"); + vmathV3Print( &vec0 ); + printf("slot 1:\n"); + vmathV3Print( &vec1 ); + printf("slot 2:\n"); + vmathV3Print( &vec2 ); + printf("slot 3:\n"); + vmathV3Print( &vec3 ); +} + +static inline void vmathSoaV3Prints( const VmathSoaVector3 *vec, const char *name ) +{ + VmathVector3 vec0, vec1, vec2, vec3; + printf( "%s:\n", name ); + vmathSoaV3Get4Aos( vec, &vec0, &vec1, &vec2, &vec3 ); + printf("slot 0:\n"); + vmathV3Print( &vec0 ); + printf("slot 1:\n"); + vmathV3Print( &vec1 ); + printf("slot 2:\n"); + vmathV3Print( &vec2 ); + printf("slot 3:\n"); + vmathV3Print( &vec3 ); +} + +#endif + +static inline void vmathSoaV4Copy( VmathSoaVector4 *result, const VmathSoaVector4 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; + result->w = vec->w; +} + +static inline void vmathSoaV4MakeFromElems( VmathSoaVector4 *result, vec_float4 _x, vec_float4 _y, vec_float4 _z, vec_float4 _w ) +{ + result->x = _x; + result->y = _y; + result->z = _z; + result->w = _w; +} + +static inline void vmathSoaV4MakeFromV3Scalar( VmathSoaVector4 *result, const VmathSoaVector3 *xyz, vec_float4 _w ) +{ + vmathSoaV4SetXYZ( result, xyz ); + vmathSoaV4SetW( result, _w ); +} + +static inline void vmathSoaV4MakeFromV3( VmathSoaVector4 *result, const VmathSoaVector3 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; + result->w = spu_splats(0.0f); +} + +static inline void vmathSoaV4MakeFromP3( VmathSoaVector4 *result, const VmathSoaPoint3 *pnt ) +{ + result->x = pnt->x; + result->y = pnt->y; + result->z = pnt->z; + result->w = spu_splats(1.0f); +} + +static inline void vmathSoaV4MakeFromQ( VmathSoaVector4 *result, const VmathSoaQuat *quat ) +{ + result->x = quat->x; + result->y = quat->y; + result->z = quat->z; + result->w = quat->w; +} + +static inline void vmathSoaV4MakeFromScalar( VmathSoaVector4 *result, vec_float4 scalar ) +{ + result->x = scalar; + result->y = scalar; + result->z = scalar; + result->w = scalar; +} + +static inline void vmathSoaV4MakeFromAos( VmathSoaVector4 *result, const VmathVector4 *vec ) +{ + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + vec_uchar16 shuffle_wwww = (vec_uchar16)spu_splats((int)0x0c0d0e0f); + vec_float4 vec128 = vec->vec128; + result->x = spu_shuffle( vec128, vec128, shuffle_xxxx ); + result->y = spu_shuffle( vec128, vec128, shuffle_yyyy ); + result->z = spu_shuffle( vec128, vec128, shuffle_zzzz ); + result->w = spu_shuffle( vec128, vec128, shuffle_wwww ); +} + +static inline void vmathSoaV4MakeFrom4Aos( VmathSoaVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1, const VmathVector4 *vec2, const VmathVector4 *vec3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = spu_shuffle( vec0->vec128, vec2->vec128, _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( vec1->vec128, vec3->vec128, _VECTORMATH_SHUF_XAYB ); + tmp2 = spu_shuffle( vec0->vec128, vec2->vec128, _VECTORMATH_SHUF_ZCWD ); + tmp3 = spu_shuffle( vec1->vec128, vec3->vec128, _VECTORMATH_SHUF_ZCWD ); + result->x = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_XAYB ); + result->y = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_ZCWD ); + result->z = spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_XAYB ); + result->w = spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_ZCWD ); +} + +static inline void vmathSoaV4MakeXAxis( VmathSoaVector4 *result ) +{ + vmathSoaV4MakeFromElems( result, spu_splats(1.0f), spu_splats(0.0f), spu_splats(0.0f), spu_splats(0.0f) ); +} + +static inline void vmathSoaV4MakeYAxis( VmathSoaVector4 *result ) +{ + vmathSoaV4MakeFromElems( result, spu_splats(0.0f), spu_splats(1.0f), spu_splats(0.0f), spu_splats(0.0f) ); +} + +static inline void vmathSoaV4MakeZAxis( VmathSoaVector4 *result ) +{ + vmathSoaV4MakeFromElems( result, spu_splats(0.0f), spu_splats(0.0f), spu_splats(1.0f), spu_splats(0.0f) ); +} + +static inline void vmathSoaV4MakeWAxis( VmathSoaVector4 *result ) +{ + vmathSoaV4MakeFromElems( result, spu_splats(0.0f), spu_splats(0.0f), spu_splats(0.0f), spu_splats(1.0f) ); +} + +static inline void vmathSoaV4Lerp( VmathSoaVector4 *result, vec_float4 t, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + VmathSoaVector4 tmpV4_0, tmpV4_1; + vmathSoaV4Sub( &tmpV4_0, vec1, vec0 ); + vmathSoaV4ScalarMul( &tmpV4_1, &tmpV4_0, t ); + vmathSoaV4Add( result, vec0, &tmpV4_1 ); +} + +static inline void vmathSoaV4Slerp( VmathSoaVector4 *result, vec_float4 t, const VmathSoaVector4 *unitVec0, const VmathSoaVector4 *unitVec1 ) +{ + VmathSoaVector4 tmpV4_0, tmpV4_1; + vec_float4 recipSinAngle, scale0, scale1, cosAngle, angle; + vec_uint4 selectMask; + cosAngle = vmathSoaV4Dot( unitVec0, unitVec1 ); + selectMask = (vec_uint4)spu_cmpgt( spu_splats(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + recipSinAngle = recipf4( sinf4( angle ) ); + scale0 = spu_sel( spu_sub( spu_splats(1.0f), t ), spu_mul( sinf4( spu_mul( spu_sub( spu_splats(1.0f), t ), angle ) ), recipSinAngle ), selectMask ); + scale1 = spu_sel( t, spu_mul( sinf4( spu_mul( t, angle ) ), recipSinAngle ), selectMask ); + vmathSoaV4ScalarMul( &tmpV4_0, unitVec0, scale0 ); + vmathSoaV4ScalarMul( &tmpV4_1, unitVec1, scale1 ); + vmathSoaV4Add( result, &tmpV4_0, &tmpV4_1 ); +} + +static inline void vmathSoaV4Get4Aos( const VmathSoaVector4 *vec, VmathVector4 *result0, VmathVector4 *result1, VmathVector4 *result2, VmathVector4 *result3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = spu_shuffle( vec->x, vec->z, _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( vec->y, vec->w, _VECTORMATH_SHUF_XAYB ); + tmp2 = spu_shuffle( vec->x, vec->z, _VECTORMATH_SHUF_ZCWD ); + tmp3 = spu_shuffle( vec->y, vec->w, _VECTORMATH_SHUF_ZCWD ); + vmathV4MakeFrom128( result0, spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_XAYB ) ); + vmathV4MakeFrom128( result1, spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_ZCWD ) ); + vmathV4MakeFrom128( result2, spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_XAYB ) ); + vmathV4MakeFrom128( result3, spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_ZCWD ) ); +} + +static inline void vmathSoaV4StoreHalfFloats( const VmathSoaVector4 *vec, vec_ushort8 *twoQuads ) +{ + VmathVector4 v0, v1, v2, v3; + vmathSoaV4Get4Aos( vec, &v0, &v1, &v2, &v3 ); + twoQuads[0] = _vmath2VfToHalfFloats(v0.vec128, v1.vec128); + twoQuads[1] = _vmath2VfToHalfFloats(v2.vec128, v3.vec128); +} + +static inline void vmathSoaV4SetXYZ( VmathSoaVector4 *result, const VmathSoaVector3 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; +} + +static inline void vmathSoaV4GetXYZ( VmathSoaVector3 *result, const VmathSoaVector4 *vec ) +{ + vmathSoaV3MakeFromElems( result, vec->x, vec->y, vec->z ); +} + +static inline void vmathSoaV4SetX( VmathSoaVector4 *result, vec_float4 _x ) +{ + result->x = _x; +} + +static inline vec_float4 vmathSoaV4GetX( const VmathSoaVector4 *vec ) +{ + return vec->x; +} + +static inline void vmathSoaV4SetY( VmathSoaVector4 *result, vec_float4 _y ) +{ + result->y = _y; +} + +static inline vec_float4 vmathSoaV4GetY( const VmathSoaVector4 *vec ) +{ + return vec->y; +} + +static inline void vmathSoaV4SetZ( VmathSoaVector4 *result, vec_float4 _z ) +{ + result->z = _z; +} + +static inline vec_float4 vmathSoaV4GetZ( const VmathSoaVector4 *vec ) +{ + return vec->z; +} + +static inline void vmathSoaV4SetW( VmathSoaVector4 *result, vec_float4 _w ) +{ + result->w = _w; +} + +static inline vec_float4 vmathSoaV4GetW( const VmathSoaVector4 *vec ) +{ + return vec->w; +} + +static inline void vmathSoaV4SetElem( VmathSoaVector4 *result, int idx, vec_float4 value ) +{ + *(&result->x + idx) = value; +} + +static inline vec_float4 vmathSoaV4GetElem( const VmathSoaVector4 *vec, int idx ) +{ + return *(&vec->x + idx); +} + +static inline void vmathSoaV4Add( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + result->x = spu_add( vec0->x, vec1->x ); + result->y = spu_add( vec0->y, vec1->y ); + result->z = spu_add( vec0->z, vec1->z ); + result->w = spu_add( vec0->w, vec1->w ); +} + +static inline void vmathSoaV4Sub( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + result->x = spu_sub( vec0->x, vec1->x ); + result->y = spu_sub( vec0->y, vec1->y ); + result->z = spu_sub( vec0->z, vec1->z ); + result->w = spu_sub( vec0->w, vec1->w ); +} + +static inline void vmathSoaV4ScalarMul( VmathSoaVector4 *result, const VmathSoaVector4 *vec, vec_float4 scalar ) +{ + result->x = spu_mul( vec->x, scalar ); + result->y = spu_mul( vec->y, scalar ); + result->z = spu_mul( vec->z, scalar ); + result->w = spu_mul( vec->w, scalar ); +} + +static inline void vmathSoaV4ScalarDiv( VmathSoaVector4 *result, const VmathSoaVector4 *vec, vec_float4 scalar ) +{ + result->x = divf4( vec->x, scalar ); + result->y = divf4( vec->y, scalar ); + result->z = divf4( vec->z, scalar ); + result->w = divf4( vec->w, scalar ); +} + +static inline void vmathSoaV4Neg( VmathSoaVector4 *result, const VmathSoaVector4 *vec ) +{ + result->x = negatef4( vec->x ); + result->y = negatef4( vec->y ); + result->z = negatef4( vec->z ); + result->w = negatef4( vec->w ); +} + +static inline void vmathSoaV4MulPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + result->x = spu_mul( vec0->x, vec1->x ); + result->y = spu_mul( vec0->y, vec1->y ); + result->z = spu_mul( vec0->z, vec1->z ); + result->w = spu_mul( vec0->w, vec1->w ); +} + +static inline void vmathSoaV4DivPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + result->x = divf4( vec0->x, vec1->x ); + result->y = divf4( vec0->y, vec1->y ); + result->z = divf4( vec0->z, vec1->z ); + result->w = divf4( vec0->w, vec1->w ); +} + +static inline void vmathSoaV4RecipPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec ) +{ + result->x = recipf4( vec->x ); + result->y = recipf4( vec->y ); + result->z = recipf4( vec->z ); + result->w = recipf4( vec->w ); +} + +static inline void vmathSoaV4SqrtPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec ) +{ + result->x = sqrtf4( vec->x ); + result->y = sqrtf4( vec->y ); + result->z = sqrtf4( vec->z ); + result->w = sqrtf4( vec->w ); +} + +static inline void vmathSoaV4RsqrtPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec ) +{ + result->x = rsqrtf4( vec->x ); + result->y = rsqrtf4( vec->y ); + result->z = rsqrtf4( vec->z ); + result->w = rsqrtf4( vec->w ); +} + +static inline void vmathSoaV4AbsPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec ) +{ + result->x = fabsf4( vec->x ); + result->y = fabsf4( vec->y ); + result->z = fabsf4( vec->z ); + result->w = fabsf4( vec->w ); +} + +static inline void vmathSoaV4CopySignPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + result->x = copysignf4( vec0->x, vec1->x ); + result->y = copysignf4( vec0->y, vec1->y ); + result->z = copysignf4( vec0->z, vec1->z ); + result->w = copysignf4( vec0->w, vec1->w ); +} + +static inline void vmathSoaV4MaxPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + result->x = fmaxf4( vec0->x, vec1->x ); + result->y = fmaxf4( vec0->y, vec1->y ); + result->z = fmaxf4( vec0->z, vec1->z ); + result->w = fmaxf4( vec0->w, vec1->w ); +} + +static inline vec_float4 vmathSoaV4MaxElem( const VmathSoaVector4 *vec ) +{ + vec_float4 result; + result = fmaxf4( vec->x, vec->y ); + result = fmaxf4( vec->z, result ); + result = fmaxf4( vec->w, result ); + return result; +} + +static inline void vmathSoaV4MinPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + result->x = fminf4( vec0->x, vec1->x ); + result->y = fminf4( vec0->y, vec1->y ); + result->z = fminf4( vec0->z, vec1->z ); + result->w = fminf4( vec0->w, vec1->w ); +} + +static inline vec_float4 vmathSoaV4MinElem( const VmathSoaVector4 *vec ) +{ + vec_float4 result; + result = fminf4( vec->x, vec->y ); + result = fminf4( vec->z, result ); + result = fminf4( vec->w, result ); + return result; +} + +static inline vec_float4 vmathSoaV4Sum( const VmathSoaVector4 *vec ) +{ + vec_float4 result; + result = spu_add( vec->x, vec->y ); + result = spu_add( result, vec->z ); + result = spu_add( result, vec->w ); + return result; +} + +static inline vec_float4 vmathSoaV4Dot( const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ) +{ + vec_float4 result; + result = spu_mul( vec0->x, vec1->x ); + result = spu_add( result, spu_mul( vec0->y, vec1->y ) ); + result = spu_add( result, spu_mul( vec0->z, vec1->z ) ); + result = spu_add( result, spu_mul( vec0->w, vec1->w ) ); + return result; +} + +static inline vec_float4 vmathSoaV4LengthSqr( const VmathSoaVector4 *vec ) +{ + vec_float4 result; + result = spu_mul( vec->x, vec->x ); + result = spu_add( result, spu_mul( vec->y, vec->y ) ); + result = spu_add( result, spu_mul( vec->z, vec->z ) ); + result = spu_add( result, spu_mul( vec->w, vec->w ) ); + return result; +} + +static inline vec_float4 vmathSoaV4Length( const VmathSoaVector4 *vec ) +{ + return sqrtf4( vmathSoaV4LengthSqr( vec ) ); +} + +static inline void vmathSoaV4Normalize( VmathSoaVector4 *result, const VmathSoaVector4 *vec ) +{ + vec_float4 lenSqr, lenInv; + lenSqr = vmathSoaV4LengthSqr( vec ); + lenInv = rsqrtf4( lenSqr ); + result->x = spu_mul( vec->x, lenInv ); + result->y = spu_mul( vec->y, lenInv ); + result->z = spu_mul( vec->z, lenInv ); + result->w = spu_mul( vec->w, lenInv ); +} + +static inline void vmathSoaV4Select( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1, vec_uint4 select1 ) +{ + result->x = spu_sel( vec0->x, vec1->x, select1 ); + result->y = spu_sel( vec0->y, vec1->y, select1 ); + result->z = spu_sel( vec0->z, vec1->z, select1 ); + result->w = spu_sel( vec0->w, vec1->w, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaV4Print( const VmathSoaVector4 *vec ) +{ + VmathVector4 vec0, vec1, vec2, vec3; + vmathSoaV4Get4Aos( vec, &vec0, &vec1, &vec2, &vec3 ); + printf("slot 0:\n"); + vmathV4Print( &vec0 ); + printf("slot 1:\n"); + vmathV4Print( &vec1 ); + printf("slot 2:\n"); + vmathV4Print( &vec2 ); + printf("slot 3:\n"); + vmathV4Print( &vec3 ); +} + +static inline void vmathSoaV4Prints( const VmathSoaVector4 *vec, const char *name ) +{ + VmathVector4 vec0, vec1, vec2, vec3; + printf( "%s:\n", name ); + vmathSoaV4Get4Aos( vec, &vec0, &vec1, &vec2, &vec3 ); + printf("slot 0:\n"); + vmathV4Print( &vec0 ); + printf("slot 1:\n"); + vmathV4Print( &vec1 ); + printf("slot 2:\n"); + vmathV4Print( &vec2 ); + printf("slot 3:\n"); + vmathV4Print( &vec3 ); +} + +#endif + +static inline void vmathSoaP3Copy( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ) +{ + result->x = pnt->x; + result->y = pnt->y; + result->z = pnt->z; +} + +static inline void vmathSoaP3MakeFromElems( VmathSoaPoint3 *result, vec_float4 _x, vec_float4 _y, vec_float4 _z ) +{ + result->x = _x; + result->y = _y; + result->z = _z; +} + +static inline void vmathSoaP3MakeFromV3( VmathSoaPoint3 *result, const VmathSoaVector3 *vec ) +{ + result->x = vec->x; + result->y = vec->y; + result->z = vec->z; +} + +static inline void vmathSoaP3MakeFromScalar( VmathSoaPoint3 *result, vec_float4 scalar ) +{ + result->x = scalar; + result->y = scalar; + result->z = scalar; +} + +static inline void vmathSoaP3MakeFromAos( VmathSoaPoint3 *result, const VmathPoint3 *pnt ) +{ + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + vec_float4 vec128 = pnt->vec128; + result->x = spu_shuffle( vec128, vec128, shuffle_xxxx ); + result->y = spu_shuffle( vec128, vec128, shuffle_yyyy ); + result->z = spu_shuffle( vec128, vec128, shuffle_zzzz ); +} + +static inline void vmathSoaP3MakeFrom4Aos( VmathSoaPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, const VmathPoint3 *pnt2, const VmathPoint3 *pnt3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = spu_shuffle( pnt0->vec128, pnt2->vec128, _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( pnt1->vec128, pnt3->vec128, _VECTORMATH_SHUF_XAYB ); + tmp2 = spu_shuffle( pnt0->vec128, pnt2->vec128, _VECTORMATH_SHUF_ZCWD ); + tmp3 = spu_shuffle( pnt1->vec128, pnt3->vec128, _VECTORMATH_SHUF_ZCWD ); + result->x = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_XAYB ); + result->y = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_ZCWD ); + result->z = spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_XAYB ); +} + +static inline void vmathSoaP3Lerp( VmathSoaPoint3 *result, vec_float4 t, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + VmathSoaVector3 tmpV3_0, tmpV3_1; + vmathSoaP3Sub( &tmpV3_0, pnt1, pnt0 ); + vmathSoaV3ScalarMul( &tmpV3_1, &tmpV3_0, t ); + vmathSoaP3AddV3( result, pnt0, &tmpV3_1 ); +} + +static inline void vmathSoaP3Get4Aos( const VmathSoaPoint3 *pnt, VmathPoint3 *result0, VmathPoint3 *result1, VmathPoint3 *result2, VmathPoint3 *result3 ) +{ + vec_float4 tmp0, tmp1; + tmp0 = spu_shuffle( pnt->x, pnt->z, _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( pnt->x, pnt->z, _VECTORMATH_SHUF_ZCWD ); + vmathP3MakeFrom128( result0, spu_shuffle( tmp0, pnt->y, _VECTORMATH_SHUF_XAYB ) ); + vmathP3MakeFrom128( result1, spu_shuffle( tmp0, pnt->y, _VECTORMATH_SHUF_ZBW0 ) ); + vmathP3MakeFrom128( result2, spu_shuffle( tmp1, pnt->y, _VECTORMATH_SHUF_XCY0 ) ); + vmathP3MakeFrom128( result3, spu_shuffle( tmp1, pnt->y, _VECTORMATH_SHUF_ZDW0 ) ); +} + +static inline void vmathSoaP3LoadXYZArray( VmathSoaPoint3 *vec, const vec_float4 *threeQuads ) +{ + vec_float4 xyxy, yzyz, zxzx, xyzx, yzxy, zxyz; + xyzx = threeQuads[0]; + yzxy = threeQuads[1]; + zxyz = threeQuads[2]; + xyxy = spu_shuffle( xyzx, yzxy, _VECTORMATH_SHUF_XYCD ); + zxzx = spu_shuffle( zxyz, xyzx, _VECTORMATH_SHUF_XYCD ); + yzyz = spu_shuffle( yzxy, zxyz, _VECTORMATH_SHUF_XYCD ); + vmathSoaP3SetX( vec, spu_shuffle( xyxy, zxzx, _VECTORMATH_SHUF_XDZB ) ); + vmathSoaP3SetY( vec, spu_shuffle( xyxy, yzyz, _VECTORMATH_SHUF_YAWC ) ); + vmathSoaP3SetZ( vec, spu_shuffle( zxzx, yzyz, _VECTORMATH_SHUF_ZBXD ) ); +} + +static inline void vmathSoaP3StoreXYZArray( const VmathSoaPoint3 *vec, vec_float4 *threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz, xyxy, zxzx, yzyz; + xyxy = spu_shuffle( vec->x, vec->y, _VECTORMATH_SHUF_XAZC ); + zxzx = spu_shuffle( vec->z, vec->x, _VECTORMATH_SHUF_ZDXB ); + yzyz = spu_shuffle( vec->y, vec->z, _VECTORMATH_SHUF_YBWD ); + xyzx = spu_shuffle( xyxy, zxzx, _VECTORMATH_SHUF_XYCD ); + yzxy = spu_shuffle( yzyz, xyxy, _VECTORMATH_SHUF_XYCD ); + zxyz = spu_shuffle( zxzx, yzyz, _VECTORMATH_SHUF_XYCD ); + threeQuads[0] = xyzx; + threeQuads[1] = yzxy; + threeQuads[2] = zxyz; +} + +static inline void vmathSoaP3StoreHalfFloats( const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1, vec_ushort8 *threeQuads ) +{ + vec_float4 xyz0[3]; + vec_float4 xyz1[3]; + vmathSoaP3StoreXYZArray( pnt0, xyz0 ); + vmathSoaP3StoreXYZArray( pnt1, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +} + +static inline void vmathSoaP3SetX( VmathSoaPoint3 *result, vec_float4 _x ) +{ + result->x = _x; +} + +static inline vec_float4 vmathSoaP3GetX( const VmathSoaPoint3 *pnt ) +{ + return pnt->x; +} + +static inline void vmathSoaP3SetY( VmathSoaPoint3 *result, vec_float4 _y ) +{ + result->y = _y; +} + +static inline vec_float4 vmathSoaP3GetY( const VmathSoaPoint3 *pnt ) +{ + return pnt->y; +} + +static inline void vmathSoaP3SetZ( VmathSoaPoint3 *result, vec_float4 _z ) +{ + result->z = _z; +} + +static inline vec_float4 vmathSoaP3GetZ( const VmathSoaPoint3 *pnt ) +{ + return pnt->z; +} + +static inline void vmathSoaP3SetElem( VmathSoaPoint3 *result, int idx, vec_float4 value ) +{ + *(&result->x + idx) = value; +} + +static inline vec_float4 vmathSoaP3GetElem( const VmathSoaPoint3 *pnt, int idx ) +{ + return *(&pnt->x + idx); +} + +static inline void vmathSoaP3Sub( VmathSoaVector3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + result->x = spu_sub( pnt0->x, pnt1->x ); + result->y = spu_sub( pnt0->y, pnt1->y ); + result->z = spu_sub( pnt0->z, pnt1->z ); +} + +static inline void vmathSoaP3AddV3( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, const VmathSoaVector3 *vec1 ) +{ + result->x = spu_add( pnt->x, vec1->x ); + result->y = spu_add( pnt->y, vec1->y ); + result->z = spu_add( pnt->z, vec1->z ); +} + +static inline void vmathSoaP3SubV3( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, const VmathSoaVector3 *vec1 ) +{ + result->x = spu_sub( pnt->x, vec1->x ); + result->y = spu_sub( pnt->y, vec1->y ); + result->z = spu_sub( pnt->z, vec1->z ); +} + +static inline void vmathSoaP3MulPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + result->x = spu_mul( pnt0->x, pnt1->x ); + result->y = spu_mul( pnt0->y, pnt1->y ); + result->z = spu_mul( pnt0->z, pnt1->z ); +} + +static inline void vmathSoaP3DivPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + result->x = divf4( pnt0->x, pnt1->x ); + result->y = divf4( pnt0->y, pnt1->y ); + result->z = divf4( pnt0->z, pnt1->z ); +} + +static inline void vmathSoaP3RecipPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ) +{ + result->x = recipf4( pnt->x ); + result->y = recipf4( pnt->y ); + result->z = recipf4( pnt->z ); +} + +static inline void vmathSoaP3SqrtPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ) +{ + result->x = sqrtf4( pnt->x ); + result->y = sqrtf4( pnt->y ); + result->z = sqrtf4( pnt->z ); +} + +static inline void vmathSoaP3RsqrtPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ) +{ + result->x = rsqrtf4( pnt->x ); + result->y = rsqrtf4( pnt->y ); + result->z = rsqrtf4( pnt->z ); +} + +static inline void vmathSoaP3AbsPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ) +{ + result->x = fabsf4( pnt->x ); + result->y = fabsf4( pnt->y ); + result->z = fabsf4( pnt->z ); +} + +static inline void vmathSoaP3CopySignPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + result->x = copysignf4( pnt0->x, pnt1->x ); + result->y = copysignf4( pnt0->y, pnt1->y ); + result->z = copysignf4( pnt0->z, pnt1->z ); +} + +static inline void vmathSoaP3MaxPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + result->x = fmaxf4( pnt0->x, pnt1->x ); + result->y = fmaxf4( pnt0->y, pnt1->y ); + result->z = fmaxf4( pnt0->z, pnt1->z ); +} + +static inline vec_float4 vmathSoaP3MaxElem( const VmathSoaPoint3 *pnt ) +{ + vec_float4 result; + result = fmaxf4( pnt->x, pnt->y ); + result = fmaxf4( pnt->z, result ); + return result; +} + +static inline void vmathSoaP3MinPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + result->x = fminf4( pnt0->x, pnt1->x ); + result->y = fminf4( pnt0->y, pnt1->y ); + result->z = fminf4( pnt0->z, pnt1->z ); +} + +static inline vec_float4 vmathSoaP3MinElem( const VmathSoaPoint3 *pnt ) +{ + vec_float4 result; + result = fminf4( pnt->x, pnt->y ); + result = fminf4( pnt->z, result ); + return result; +} + +static inline vec_float4 vmathSoaP3Sum( const VmathSoaPoint3 *pnt ) +{ + vec_float4 result; + result = spu_add( pnt->x, pnt->y ); + result = spu_add( result, pnt->z ); + return result; +} + +static inline void vmathSoaP3Scale( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, vec_float4 scaleVal ) +{ + VmathSoaPoint3 tmpP3_0; + vmathSoaP3MakeFromScalar( &tmpP3_0, scaleVal ); + vmathSoaP3MulPerElem( result, pnt, &tmpP3_0 ); +} + +static inline void vmathSoaP3NonUniformScale( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, const VmathSoaVector3 *scaleVec ) +{ + VmathSoaPoint3 tmpP3_0; + vmathSoaP3MakeFromV3( &tmpP3_0, scaleVec ); + vmathSoaP3MulPerElem( result, pnt, &tmpP3_0 ); +} + +static inline vec_float4 vmathSoaP3Projection( const VmathSoaPoint3 *pnt, const VmathSoaVector3 *unitVec ) +{ + vec_float4 result; + result = spu_mul( pnt->x, unitVec->x ); + result = spu_add( result, spu_mul( pnt->y, unitVec->y ) ); + result = spu_add( result, spu_mul( pnt->z, unitVec->z ) ); + return result; +} + +static inline vec_float4 vmathSoaP3DistSqrFromOrigin( const VmathSoaPoint3 *pnt ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaV3MakeFromP3( &tmpV3_0, pnt ); + return vmathSoaV3LengthSqr( &tmpV3_0 ); +} + +static inline vec_float4 vmathSoaP3DistFromOrigin( const VmathSoaPoint3 *pnt ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaV3MakeFromP3( &tmpV3_0, pnt ); + return vmathSoaV3Length( &tmpV3_0 ); +} + +static inline vec_float4 vmathSoaP3DistSqr( const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaP3Sub( &tmpV3_0, pnt1, pnt0 ); + return vmathSoaV3LengthSqr( &tmpV3_0 ); +} + +static inline vec_float4 vmathSoaP3Dist( const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ) +{ + VmathSoaVector3 tmpV3_0; + vmathSoaP3Sub( &tmpV3_0, pnt1, pnt0 ); + return vmathSoaV3Length( &tmpV3_0 ); +} + +static inline void vmathSoaP3Select( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1, vec_uint4 select1 ) +{ + result->x = spu_sel( pnt0->x, pnt1->x, select1 ); + result->y = spu_sel( pnt0->y, pnt1->y, select1 ); + result->z = spu_sel( pnt0->z, pnt1->z, select1 ); +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaP3Print( const VmathSoaPoint3 *pnt ) +{ + VmathPoint3 vec0, vec1, vec2, vec3; + vmathSoaP3Get4Aos( pnt, &vec0, &vec1, &vec2, &vec3 ); + printf("slot 0:\n"); + vmathP3Print( &vec0 ); + printf("slot 1:\n"); + vmathP3Print( &vec1 ); + printf("slot 2:\n"); + vmathP3Print( &vec2 ); + printf("slot 3:\n"); + vmathP3Print( &vec3 ); +} + +static inline void vmathSoaP3Prints( const VmathSoaPoint3 *pnt, const char *name ) +{ + VmathPoint3 vec0, vec1, vec2, vec3; + printf( "%s:\n", name ); + vmathSoaP3Get4Aos( pnt, &vec0, &vec1, &vec2, &vec3 ); + printf("slot 0:\n"); + vmathP3Print( &vec0 ); + printf("slot 1:\n"); + vmathP3Print( &vec1 ); + printf("slot 2:\n"); + vmathP3Print( &vec2 ); + printf("slot 3:\n"); + vmathP3Print( &vec3 ); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/c/vec_soa_v.h b/Extras/vectormathlibrary/include/vectormath/spu/c/vec_soa_v.h new file mode 100644 index 0000000..560356a --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/c/vec_soa_v.h @@ -0,0 +1,962 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_SOA_V_C_H +#define _VECTORMATH_VEC_SOA_V_C_H +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------------- + * Constants + * for shuffles, words are labeled [x,y,z,w] [a,b,c,d] + */ +#define _VECTORMATH_SHUF_X 0x00010203 +#define _VECTORMATH_SHUF_Y 0x04050607 +#define _VECTORMATH_SHUF_Z 0x08090a0b +#define _VECTORMATH_SHUF_W 0x0c0d0e0f +#define _VECTORMATH_SHUF_A 0x10111213 +#define _VECTORMATH_SHUF_B 0x14151617 +#define _VECTORMATH_SHUF_C 0x18191a1b +#define _VECTORMATH_SHUF_D 0x1c1d1e1f +#define _VECTORMATH_SHUF_0 0x80808080 +#define _VECTORMATH_SHUF_XAYB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_ZCWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_ZBW0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_XCY0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_ZDW0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_D, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_XAZC ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_C }) +#define _VECTORMATH_SHUF_ZDXB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_D, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_YBWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_XDZB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_D, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_YAWC ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_C }) +#define _VECTORMATH_SHUF_ZBXD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_XYCD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SLERP_TOL 0.999f + +/*----------------------------------------------------------------------------- + * Definitions + */ +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +static inline VmathSoaVector3 vmathSoaV3MakeFromElems_V( vec_float4 _x, vec_float4 _y, vec_float4 _z ) +{ + VmathSoaVector3 result; + vmathSoaV3MakeFromElems(&result, _x, _y, _z); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MakeFromP3_V( VmathSoaPoint3 pnt ) +{ + VmathSoaVector3 result; + vmathSoaV3MakeFromP3(&result, &pnt); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MakeFromScalar_V( vec_float4 scalar ) +{ + VmathSoaVector3 result; + vmathSoaV3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MakeFromAos_V( VmathVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaV3MakeFromAos(&result, &vec); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MakeFrom4Aos_V( VmathVector3 vec0, VmathVector3 vec1, VmathVector3 vec2, VmathVector3 vec3 ) +{ + VmathSoaVector3 result; + vmathSoaV3MakeFrom4Aos(&result, &vec0, &vec1, &vec2, &vec3); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MakeXAxis_V( ) +{ + VmathSoaVector3 result; + vmathSoaV3MakeXAxis(&result); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MakeYAxis_V( ) +{ + VmathSoaVector3 result; + vmathSoaV3MakeYAxis(&result); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MakeZAxis_V( ) +{ + VmathSoaVector3 result; + vmathSoaV3MakeZAxis(&result); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3Lerp_V( vec_float4 t, VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3Lerp(&result, t, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3Slerp_V( vec_float4 t, VmathSoaVector3 unitVec0, VmathSoaVector3 unitVec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3Slerp(&result, t, &unitVec0, &unitVec1); + return result; +} + +static inline void vmathSoaV3Get4Aos_V( VmathSoaVector3 vec, VmathVector3 *result0, VmathVector3 *result1, VmathVector3 *result2, VmathVector3 *result3 ) +{ + vmathSoaV3Get4Aos(&vec, result0, result1, result2, result3); +} + +static inline void vmathSoaV3LoadXYZArray_V( VmathSoaVector3 *vec, const vec_float4 *threeQuads ) +{ + vmathSoaV3LoadXYZArray(vec, threeQuads); +} + +static inline void vmathSoaV3StoreXYZArray_V( VmathSoaVector3 vec, vec_float4 *threeQuads ) +{ + vmathSoaV3StoreXYZArray(&vec, threeQuads); +} + +static inline void vmathSoaV3StoreHalfFloats_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1, vec_ushort8 *threeQuads ) +{ + vmathSoaV3StoreHalfFloats(&vec0, &vec1, threeQuads); +} + +static inline void vmathSoaV3SetX_V( VmathSoaVector3 *result, vec_float4 _x ) +{ + vmathSoaV3SetX(result, _x); +} + +static inline vec_float4 vmathSoaV3GetX_V( VmathSoaVector3 vec ) +{ + return vmathSoaV3GetX(&vec); +} + +static inline void vmathSoaV3SetY_V( VmathSoaVector3 *result, vec_float4 _y ) +{ + vmathSoaV3SetY(result, _y); +} + +static inline vec_float4 vmathSoaV3GetY_V( VmathSoaVector3 vec ) +{ + return vmathSoaV3GetY(&vec); +} + +static inline void vmathSoaV3SetZ_V( VmathSoaVector3 *result, vec_float4 _z ) +{ + vmathSoaV3SetZ(result, _z); +} + +static inline vec_float4 vmathSoaV3GetZ_V( VmathSoaVector3 vec ) +{ + return vmathSoaV3GetZ(&vec); +} + +static inline void vmathSoaV3SetElem_V( VmathSoaVector3 *result, int idx, vec_float4 value ) +{ + vmathSoaV3SetElem(result, idx, value); +} + +static inline vec_float4 vmathSoaV3GetElem_V( VmathSoaVector3 vec, int idx ) +{ + return vmathSoaV3GetElem(&vec, idx); +} + +static inline VmathSoaVector3 vmathSoaV3Add_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3Add(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3Sub_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3Sub(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaPoint3 vmathSoaV3AddP3_V( VmathSoaVector3 vec, VmathSoaPoint3 pnt1 ) +{ + VmathSoaPoint3 result; + vmathSoaV3AddP3(&result, &vec, &pnt1); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3ScalarMul_V( VmathSoaVector3 vec, vec_float4 scalar ) +{ + VmathSoaVector3 result; + vmathSoaV3ScalarMul(&result, &vec, scalar); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3ScalarDiv_V( VmathSoaVector3 vec, vec_float4 scalar ) +{ + VmathSoaVector3 result; + vmathSoaV3ScalarDiv(&result, &vec, scalar); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3Neg_V( VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaV3Neg(&result, &vec); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MulPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3MulPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3DivPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3DivPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3RecipPerElem_V( VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaV3RecipPerElem(&result, &vec); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3SqrtPerElem_V( VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaV3SqrtPerElem(&result, &vec); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3RsqrtPerElem_V( VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaV3RsqrtPerElem(&result, &vec); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3AbsPerElem_V( VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaV3AbsPerElem(&result, &vec); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3CopySignPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3CopySignPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3MaxPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3MaxPerElem(&result, &vec0, &vec1); + return result; +} + +static inline vec_float4 vmathSoaV3MaxElem_V( VmathSoaVector3 vec ) +{ + return vmathSoaV3MaxElem(&vec); +} + +static inline VmathSoaVector3 vmathSoaV3MinPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3MinPerElem(&result, &vec0, &vec1); + return result; +} + +static inline vec_float4 vmathSoaV3MinElem_V( VmathSoaVector3 vec ) +{ + return vmathSoaV3MinElem(&vec); +} + +static inline vec_float4 vmathSoaV3Sum_V( VmathSoaVector3 vec ) +{ + return vmathSoaV3Sum(&vec); +} + +static inline vec_float4 vmathSoaV3Dot_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + return vmathSoaV3Dot(&vec0, &vec1); +} + +static inline vec_float4 vmathSoaV3LengthSqr_V( VmathSoaVector3 vec ) +{ + return vmathSoaV3LengthSqr(&vec); +} + +static inline vec_float4 vmathSoaV3Length_V( VmathSoaVector3 vec ) +{ + return vmathSoaV3Length(&vec); +} + +static inline VmathSoaVector3 vmathSoaV3Normalize_V( VmathSoaVector3 vec ) +{ + VmathSoaVector3 result; + vmathSoaV3Normalize(&result, &vec); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3Cross_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ) +{ + VmathSoaVector3 result; + vmathSoaV3Cross(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector3 vmathSoaV3Select_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1, vec_uint4 select1 ) +{ + VmathSoaVector3 result; + vmathSoaV3Select(&result, &vec0, &vec1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaV3Print_V( VmathSoaVector3 vec ) +{ + vmathSoaV3Print(&vec); +} + +static inline void vmathSoaV3Prints_V( VmathSoaVector3 vec, const char *name ) +{ + vmathSoaV3Prints(&vec, name); +} + +#endif + +static inline VmathSoaVector4 vmathSoaV4MakeFromElems_V( vec_float4 _x, vec_float4 _y, vec_float4 _z, vec_float4 _w ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeFromElems(&result, _x, _y, _z, _w); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeFromV3Scalar_V( VmathSoaVector3 xyz, vec_float4 _w ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeFromV3Scalar(&result, &xyz, _w); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeFromV3_V( VmathSoaVector3 vec ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeFromV3(&result, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeFromP3_V( VmathSoaPoint3 pnt ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeFromP3(&result, &pnt); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeFromQ_V( VmathSoaQuat quat ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeFromQ(&result, &quat); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeFromScalar_V( vec_float4 scalar ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeFromAos_V( VmathVector4 vec ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeFromAos(&result, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeFrom4Aos_V( VmathVector4 vec0, VmathVector4 vec1, VmathVector4 vec2, VmathVector4 vec3 ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeFrom4Aos(&result, &vec0, &vec1, &vec2, &vec3); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeXAxis_V( ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeXAxis(&result); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeYAxis_V( ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeYAxis(&result); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeZAxis_V( ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeZAxis(&result); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MakeWAxis_V( ) +{ + VmathSoaVector4 result; + vmathSoaV4MakeWAxis(&result); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4Lerp_V( vec_float4 t, VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4Lerp(&result, t, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4Slerp_V( vec_float4 t, VmathSoaVector4 unitVec0, VmathSoaVector4 unitVec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4Slerp(&result, t, &unitVec0, &unitVec1); + return result; +} + +static inline void vmathSoaV4Get4Aos_V( VmathSoaVector4 vec, VmathVector4 *result0, VmathVector4 *result1, VmathVector4 *result2, VmathVector4 *result3 ) +{ + vmathSoaV4Get4Aos(&vec, result0, result1, result2, result3); +} + +static inline void vmathSoaV4StoreHalfFloats_V( VmathSoaVector4 vec, vec_ushort8 *twoQuads ) +{ + vmathSoaV4StoreHalfFloats(&vec, twoQuads); +} + +static inline void vmathSoaV4SetXYZ_V( VmathSoaVector4 *result, VmathSoaVector3 vec ) +{ + vmathSoaV4SetXYZ(result, &vec); +} + +static inline VmathSoaVector3 vmathSoaV4GetXYZ_V( VmathSoaVector4 vec ) +{ + VmathSoaVector3 result; + vmathSoaV4GetXYZ(&result, &vec); + return result; +} + +static inline void vmathSoaV4SetX_V( VmathSoaVector4 *result, vec_float4 _x ) +{ + vmathSoaV4SetX(result, _x); +} + +static inline vec_float4 vmathSoaV4GetX_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4GetX(&vec); +} + +static inline void vmathSoaV4SetY_V( VmathSoaVector4 *result, vec_float4 _y ) +{ + vmathSoaV4SetY(result, _y); +} + +static inline vec_float4 vmathSoaV4GetY_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4GetY(&vec); +} + +static inline void vmathSoaV4SetZ_V( VmathSoaVector4 *result, vec_float4 _z ) +{ + vmathSoaV4SetZ(result, _z); +} + +static inline vec_float4 vmathSoaV4GetZ_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4GetZ(&vec); +} + +static inline void vmathSoaV4SetW_V( VmathSoaVector4 *result, vec_float4 _w ) +{ + vmathSoaV4SetW(result, _w); +} + +static inline vec_float4 vmathSoaV4GetW_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4GetW(&vec); +} + +static inline void vmathSoaV4SetElem_V( VmathSoaVector4 *result, int idx, vec_float4 value ) +{ + vmathSoaV4SetElem(result, idx, value); +} + +static inline vec_float4 vmathSoaV4GetElem_V( VmathSoaVector4 vec, int idx ) +{ + return vmathSoaV4GetElem(&vec, idx); +} + +static inline VmathSoaVector4 vmathSoaV4Add_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4Add(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4Sub_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4Sub(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4ScalarMul_V( VmathSoaVector4 vec, vec_float4 scalar ) +{ + VmathSoaVector4 result; + vmathSoaV4ScalarMul(&result, &vec, scalar); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4ScalarDiv_V( VmathSoaVector4 vec, vec_float4 scalar ) +{ + VmathSoaVector4 result; + vmathSoaV4ScalarDiv(&result, &vec, scalar); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4Neg_V( VmathSoaVector4 vec ) +{ + VmathSoaVector4 result; + vmathSoaV4Neg(&result, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MulPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4MulPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4DivPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4DivPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4RecipPerElem_V( VmathSoaVector4 vec ) +{ + VmathSoaVector4 result; + vmathSoaV4RecipPerElem(&result, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4SqrtPerElem_V( VmathSoaVector4 vec ) +{ + VmathSoaVector4 result; + vmathSoaV4SqrtPerElem(&result, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4RsqrtPerElem_V( VmathSoaVector4 vec ) +{ + VmathSoaVector4 result; + vmathSoaV4RsqrtPerElem(&result, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4AbsPerElem_V( VmathSoaVector4 vec ) +{ + VmathSoaVector4 result; + vmathSoaV4AbsPerElem(&result, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4CopySignPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4CopySignPerElem(&result, &vec0, &vec1); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4MaxPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4MaxPerElem(&result, &vec0, &vec1); + return result; +} + +static inline vec_float4 vmathSoaV4MaxElem_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4MaxElem(&vec); +} + +static inline VmathSoaVector4 vmathSoaV4MinPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + VmathSoaVector4 result; + vmathSoaV4MinPerElem(&result, &vec0, &vec1); + return result; +} + +static inline vec_float4 vmathSoaV4MinElem_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4MinElem(&vec); +} + +static inline vec_float4 vmathSoaV4Sum_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4Sum(&vec); +} + +static inline vec_float4 vmathSoaV4Dot_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ) +{ + return vmathSoaV4Dot(&vec0, &vec1); +} + +static inline vec_float4 vmathSoaV4LengthSqr_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4LengthSqr(&vec); +} + +static inline vec_float4 vmathSoaV4Length_V( VmathSoaVector4 vec ) +{ + return vmathSoaV4Length(&vec); +} + +static inline VmathSoaVector4 vmathSoaV4Normalize_V( VmathSoaVector4 vec ) +{ + VmathSoaVector4 result; + vmathSoaV4Normalize(&result, &vec); + return result; +} + +static inline VmathSoaVector4 vmathSoaV4Select_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1, vec_uint4 select1 ) +{ + VmathSoaVector4 result; + vmathSoaV4Select(&result, &vec0, &vec1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaV4Print_V( VmathSoaVector4 vec ) +{ + vmathSoaV4Print(&vec); +} + +static inline void vmathSoaV4Prints_V( VmathSoaVector4 vec, const char *name ) +{ + vmathSoaV4Prints(&vec, name); +} + +#endif + +static inline VmathSoaPoint3 vmathSoaP3MakeFromElems_V( vec_float4 _x, vec_float4 _y, vec_float4 _z ) +{ + VmathSoaPoint3 result; + vmathSoaP3MakeFromElems(&result, _x, _y, _z); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3MakeFromV3_V( VmathSoaVector3 vec ) +{ + VmathSoaPoint3 result; + vmathSoaP3MakeFromV3(&result, &vec); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3MakeFromScalar_V( vec_float4 scalar ) +{ + VmathSoaPoint3 result; + vmathSoaP3MakeFromScalar(&result, scalar); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3MakeFromAos_V( VmathPoint3 pnt ) +{ + VmathSoaPoint3 result; + vmathSoaP3MakeFromAos(&result, &pnt); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3MakeFrom4Aos_V( VmathPoint3 pnt0, VmathPoint3 pnt1, VmathPoint3 pnt2, VmathPoint3 pnt3 ) +{ + VmathSoaPoint3 result; + vmathSoaP3MakeFrom4Aos(&result, &pnt0, &pnt1, &pnt2, &pnt3); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3Lerp_V( vec_float4 t, VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3Lerp(&result, t, &pnt0, &pnt1); + return result; +} + +static inline void vmathSoaP3Get4Aos_V( VmathSoaPoint3 pnt, VmathPoint3 *result0, VmathPoint3 *result1, VmathPoint3 *result2, VmathPoint3 *result3 ) +{ + vmathSoaP3Get4Aos(&pnt, result0, result1, result2, result3); +} + +static inline void vmathSoaP3LoadXYZArray_V( VmathSoaPoint3 *vec, const vec_float4 *threeQuads ) +{ + vmathSoaP3LoadXYZArray(vec, threeQuads); +} + +static inline void vmathSoaP3StoreXYZArray_V( VmathSoaPoint3 vec, vec_float4 *threeQuads ) +{ + vmathSoaP3StoreXYZArray(&vec, threeQuads); +} + +static inline void vmathSoaP3StoreHalfFloats_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1, vec_ushort8 *threeQuads ) +{ + vmathSoaP3StoreHalfFloats(&pnt0, &pnt1, threeQuads); +} + +static inline void vmathSoaP3SetX_V( VmathSoaPoint3 *result, vec_float4 _x ) +{ + vmathSoaP3SetX(result, _x); +} + +static inline vec_float4 vmathSoaP3GetX_V( VmathSoaPoint3 pnt ) +{ + return vmathSoaP3GetX(&pnt); +} + +static inline void vmathSoaP3SetY_V( VmathSoaPoint3 *result, vec_float4 _y ) +{ + vmathSoaP3SetY(result, _y); +} + +static inline vec_float4 vmathSoaP3GetY_V( VmathSoaPoint3 pnt ) +{ + return vmathSoaP3GetY(&pnt); +} + +static inline void vmathSoaP3SetZ_V( VmathSoaPoint3 *result, vec_float4 _z ) +{ + vmathSoaP3SetZ(result, _z); +} + +static inline vec_float4 vmathSoaP3GetZ_V( VmathSoaPoint3 pnt ) +{ + return vmathSoaP3GetZ(&pnt); +} + +static inline void vmathSoaP3SetElem_V( VmathSoaPoint3 *result, int idx, vec_float4 value ) +{ + vmathSoaP3SetElem(result, idx, value); +} + +static inline vec_float4 vmathSoaP3GetElem_V( VmathSoaPoint3 pnt, int idx ) +{ + return vmathSoaP3GetElem(&pnt, idx); +} + +static inline VmathSoaVector3 vmathSoaP3Sub_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + VmathSoaVector3 result; + vmathSoaP3Sub(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3AddV3_V( VmathSoaPoint3 pnt, VmathSoaVector3 vec1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3AddV3(&result, &pnt, &vec1); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3SubV3_V( VmathSoaPoint3 pnt, VmathSoaVector3 vec1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3SubV3(&result, &pnt, &vec1); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3MulPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3MulPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3DivPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3DivPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3RecipPerElem_V( VmathSoaPoint3 pnt ) +{ + VmathSoaPoint3 result; + vmathSoaP3RecipPerElem(&result, &pnt); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3SqrtPerElem_V( VmathSoaPoint3 pnt ) +{ + VmathSoaPoint3 result; + vmathSoaP3SqrtPerElem(&result, &pnt); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3RsqrtPerElem_V( VmathSoaPoint3 pnt ) +{ + VmathSoaPoint3 result; + vmathSoaP3RsqrtPerElem(&result, &pnt); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3AbsPerElem_V( VmathSoaPoint3 pnt ) +{ + VmathSoaPoint3 result; + vmathSoaP3AbsPerElem(&result, &pnt); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3CopySignPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3CopySignPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3MaxPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3MaxPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline vec_float4 vmathSoaP3MaxElem_V( VmathSoaPoint3 pnt ) +{ + return vmathSoaP3MaxElem(&pnt); +} + +static inline VmathSoaPoint3 vmathSoaP3MinPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3MinPerElem(&result, &pnt0, &pnt1); + return result; +} + +static inline vec_float4 vmathSoaP3MinElem_V( VmathSoaPoint3 pnt ) +{ + return vmathSoaP3MinElem(&pnt); +} + +static inline vec_float4 vmathSoaP3Sum_V( VmathSoaPoint3 pnt ) +{ + return vmathSoaP3Sum(&pnt); +} + +static inline VmathSoaPoint3 vmathSoaP3Scale_V( VmathSoaPoint3 pnt, vec_float4 scaleVal ) +{ + VmathSoaPoint3 result; + vmathSoaP3Scale(&result, &pnt, scaleVal); + return result; +} + +static inline VmathSoaPoint3 vmathSoaP3NonUniformScale_V( VmathSoaPoint3 pnt, VmathSoaVector3 scaleVec ) +{ + VmathSoaPoint3 result; + vmathSoaP3NonUniformScale(&result, &pnt, &scaleVec); + return result; +} + +static inline vec_float4 vmathSoaP3Projection_V( VmathSoaPoint3 pnt, VmathSoaVector3 unitVec ) +{ + return vmathSoaP3Projection(&pnt, &unitVec); +} + +static inline vec_float4 vmathSoaP3DistSqrFromOrigin_V( VmathSoaPoint3 pnt ) +{ + return vmathSoaP3DistSqrFromOrigin(&pnt); +} + +static inline vec_float4 vmathSoaP3DistFromOrigin_V( VmathSoaPoint3 pnt ) +{ + return vmathSoaP3DistFromOrigin(&pnt); +} + +static inline vec_float4 vmathSoaP3DistSqr_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + return vmathSoaP3DistSqr(&pnt0, &pnt1); +} + +static inline vec_float4 vmathSoaP3Dist_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ) +{ + return vmathSoaP3Dist(&pnt0, &pnt1); +} + +static inline VmathSoaPoint3 vmathSoaP3Select_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1, vec_uint4 select1 ) +{ + VmathSoaPoint3 result; + vmathSoaP3Select(&result, &pnt0, &pnt1, select1); + return result; +} + +#ifdef _VECTORMATH_DEBUG + +static inline void vmathSoaP3Print_V( VmathSoaPoint3 pnt ) +{ + vmathSoaP3Print(&pnt); +} + +static inline void vmathSoaP3Prints_V( VmathSoaPoint3 pnt, const char *name ) +{ + vmathSoaP3Prints(&pnt, name); +} + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/c/vectormath_aos.h b/Extras/vectormathlibrary/include/vectormath/spu/c/vectormath_aos.h new file mode 100644 index 0000000..3bd4e0f --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/c/vectormath_aos.h @@ -0,0 +1,1951 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_AOS_C_SPU_H +#define _VECTORMATH_AOS_C_SPU_H + +#include +#include +#include + +#ifdef _VECTORMATH_DEBUG +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef _VECTORMATH_AOS_C_TYPES_H +#define _VECTORMATH_AOS_C_TYPES_H + +/* A 3-D vector in array-of-structures format + */ +typedef struct _VmathVector3 +{ + vec_float4 vec128; +} VmathVector3; + +/* A 4-D vector in array-of-structures format + */ +typedef struct _VmathVector4 +{ + vec_float4 vec128; +} VmathVector4; + +/* A 3-D point in array-of-structures format + */ +typedef struct _VmathPoint3 +{ + vec_float4 vec128; +} VmathPoint3; + +/* A quaternion in array-of-structures format + */ +typedef struct _VmathQuat +{ + vec_float4 vec128; +} VmathQuat; + +/* A 3x3 matrix in array-of-structures format + */ +typedef struct _VmathMatrix3 +{ + VmathVector3 col0; + VmathVector3 col1; + VmathVector3 col2; +} VmathMatrix3; + +/* A 4x4 matrix in array-of-structures format + */ +typedef struct _VmathMatrix4 +{ + VmathVector4 col0; + VmathVector4 col1; + VmathVector4 col2; + VmathVector4 col3; +} VmathMatrix4; + +/* A 3x4 transformation matrix in array-of-structures format + */ +typedef struct _VmathTransform3 +{ + VmathVector3 col0; + VmathVector3 col1; + VmathVector3 col2; + VmathVector3 col3; +} VmathTransform3; + +#endif + +/* + * Copy a 3-D vector + */ +static inline void vmathV3Copy( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Construct a 3-D vector from x, y, and z elements + */ +static inline void vmathV3MakeFromElems( VmathVector3 *result, float x, float y, float z ); + +/* + * Copy elements from a 3-D point into a 3-D vector + */ +static inline void vmathV3MakeFromP3( VmathVector3 *result, const VmathPoint3 *pnt ); + +/* + * Set all elements of a 3-D vector to the same scalar value + */ +static inline void vmathV3MakeFromScalar( VmathVector3 *result, float scalar ); + +/* + * Set vector float data in a 3-D vector + */ +static inline void vmathV3MakeFrom128( VmathVector3 *result, vec_float4 vf4 ); + +/* + * Get vector float data from a 3-D vector + */ +static inline vec_float4 vmathV3Get128( const VmathVector3 *vec ); + +/* + * Set the x element of a 3-D vector + */ +static inline void vmathV3SetX( VmathVector3 *result, float x ); + +/* + * Set the y element of a 3-D vector + */ +static inline void vmathV3SetY( VmathVector3 *result, float y ); + +/* + * Set the z element of a 3-D vector + */ +static inline void vmathV3SetZ( VmathVector3 *result, float z ); + +/* + * Get the x element of a 3-D vector + */ +static inline float vmathV3GetX( const VmathVector3 *vec ); + +/* + * Get the y element of a 3-D vector + */ +static inline float vmathV3GetY( const VmathVector3 *vec ); + +/* + * Get the z element of a 3-D vector + */ +static inline float vmathV3GetZ( const VmathVector3 *vec ); + +/* + * Set an x, y, or z element of a 3-D vector by index + */ +static inline void vmathV3SetElem( VmathVector3 *result, int idx, float value ); + +/* + * Get an x, y, or z element of a 3-D vector by index + */ +static inline float vmathV3GetElem( const VmathVector3 *vec, int idx ); + +/* + * Add two 3-D vectors + */ +static inline void vmathV3Add( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Subtract a 3-D vector from another 3-D vector + */ +static inline void vmathV3Sub( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Add a 3-D vector to a 3-D point + */ +static inline void vmathV3AddP3( VmathPoint3 *result, const VmathVector3 *vec, const VmathPoint3 *pnt ); + +/* + * Multiply a 3-D vector by a scalar + */ +static inline void vmathV3ScalarMul( VmathVector3 *result, const VmathVector3 *vec, float scalar ); + +/* + * Divide a 3-D vector by a scalar + */ +static inline void vmathV3ScalarDiv( VmathVector3 *result, const VmathVector3 *vec, float scalar ); + +/* + * Negate all elements of a 3-D vector + */ +static inline void vmathV3Neg( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Construct x axis + */ +static inline void vmathV3MakeXAxis( VmathVector3 *result ); + +/* + * Construct y axis + */ +static inline void vmathV3MakeYAxis( VmathVector3 *result ); + +/* + * Construct z axis + */ +static inline void vmathV3MakeZAxis( VmathVector3 *result ); + +/* + * Multiply two 3-D vectors per element + */ +static inline void vmathV3MulPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Divide two 3-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline void vmathV3DivPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Compute the reciprocal of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline void vmathV3RecipPerElem( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Compute the square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline void vmathV3SqrtPerElem( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Compute the reciprocal square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline void vmathV3RsqrtPerElem( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Compute the absolute value of a 3-D vector per element + */ +static inline void vmathV3AbsPerElem( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Copy sign from one 3-D vector to another, per element + */ +static inline void vmathV3CopySignPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Maximum of two 3-D vectors per element + */ +static inline void vmathV3MaxPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Minimum of two 3-D vectors per element + */ +static inline void vmathV3MinPerElem( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Maximum element of a 3-D vector + */ +static inline float vmathV3MaxElem( const VmathVector3 *vec ); + +/* + * Minimum element of a 3-D vector + */ +static inline float vmathV3MinElem( const VmathVector3 *vec ); + +/* + * Compute the sum of all elements of a 3-D vector + */ +static inline float vmathV3Sum( const VmathVector3 *vec ); + +/* + * Compute the dot product of two 3-D vectors + */ +static inline float vmathV3Dot( const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Compute the square of the length of a 3-D vector + */ +static inline float vmathV3LengthSqr( const VmathVector3 *vec ); + +/* + * Compute the length of a 3-D vector + */ +static inline float vmathV3Length( const VmathVector3 *vec ); + +/* + * Normalize a 3-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline void vmathV3Normalize( VmathVector3 *result, const VmathVector3 *vec ); + +/* + * Compute cross product of two 3-D vectors + */ +static inline void vmathV3Cross( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Outer product of two 3-D vectors + */ +static inline void vmathV3Outer( VmathMatrix3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Pre-multiply a row vector by a 3x3 matrix + * NOTE: + * Slower than column post-multiply. + */ +static inline void vmathV3RowMul( VmathVector3 *result, const VmathVector3 *vec, const VmathMatrix3 *mat ); + +/* + * Cross-product matrix of a 3-D vector + */ +static inline void vmathV3CrossMatrix( VmathMatrix3 *result, const VmathVector3 *vec ); + +/* + * Create cross-product matrix and multiply + * NOTE: + * Faster than separately creating a cross-product matrix and multiplying. + */ +static inline void vmathV3CrossMatrixMul( VmathMatrix3 *result, const VmathVector3 *vec, const VmathMatrix3 *mat ); + +/* + * Linear interpolation between two 3-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathV3Lerp( VmathVector3 *result, float t, const VmathVector3 *vec0, const VmathVector3 *vec1 ); + +/* + * Spherical linear interpolation between two 3-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline void vmathV3Slerp( VmathVector3 *result, float t, const VmathVector3 *unitVec0, const VmathVector3 *unitVec1 ); + +/* + * Conditionally select between two 3-D vectors + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathV3Select( VmathVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1, unsigned int select1 ); + +/* + * Store x, y, and z elements of a 3-D vector in the first three words of a quadword. + * The value of the fourth word (the word with the highest address) remains unchanged + */ +static inline void vmathV3StoreXYZ( const VmathVector3 *vec, vec_float4 *quad ); + +/* + * Load four three-float 3-D vectors, stored in three quadwords + */ +static inline void vmathV3LoadXYZArray( VmathVector3 *vec0, VmathVector3 *vec1, VmathVector3 *vec2, VmathVector3 *vec3, const vec_float4 *threeQuads ); + +/* + * Store four 3-D vectors in three quadwords + */ +static inline void vmathV3StoreXYZArray( const VmathVector3 *vec0, const VmathVector3 *vec1, const VmathVector3 *vec2, const VmathVector3 *vec3, vec_float4 *threeQuads ); + +/* + * Store eight 3-D vectors as half-floats + */ +static inline void vmathV3StoreHalfFloats( const VmathVector3 *vec0, const VmathVector3 *vec1, const VmathVector3 *vec2, const VmathVector3 *vec3, const VmathVector3 *vec4, const VmathVector3 *vec5, const VmathVector3 *vec6, const VmathVector3 *vec7, vec_ushort8 *threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV3Print( const VmathVector3 *vec ); + +/* + * Print a 3-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV3Prints( const VmathVector3 *vec, const char *name ); + +#endif + +/* + * Copy a 4-D vector + */ +static inline void vmathV4Copy( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Construct a 4-D vector from x, y, z, and w elements + */ +static inline void vmathV4MakeFromElems( VmathVector4 *result, float x, float y, float z, float w ); + +/* + * Construct a 4-D vector from a 3-D vector and a scalar + */ +static inline void vmathV4MakeFromV3Scalar( VmathVector4 *result, const VmathVector3 *xyz, float w ); + +/* + * Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + */ +static inline void vmathV4MakeFromV3( VmathVector4 *result, const VmathVector3 *vec ); + +/* + * Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + */ +static inline void vmathV4MakeFromP3( VmathVector4 *result, const VmathPoint3 *pnt ); + +/* + * Copy elements from a quaternion into a 4-D vector + */ +static inline void vmathV4MakeFromQ( VmathVector4 *result, const VmathQuat *quat ); + +/* + * Set all elements of a 4-D vector to the same scalar value + */ +static inline void vmathV4MakeFromScalar( VmathVector4 *result, float scalar ); + +/* + * Set vector float data in a 4-D vector + */ +static inline void vmathV4MakeFrom128( VmathVector4 *result, vec_float4 vf4 ); + +/* + * Get vector float data from a 4-D vector + */ +static inline vec_float4 vmathV4Get128( const VmathVector4 *vec ); + +/* + * Set the x, y, and z elements of a 4-D vector + * NOTE: + * This function does not change the w element. + */ +static inline void vmathV4SetXYZ( VmathVector4 *result, const VmathVector3 *vec ); + +/* + * Get the x, y, and z elements of a 4-D vector + */ +static inline void vmathV4GetXYZ( VmathVector3 *result, const VmathVector4 *vec ); + +/* + * Set the x element of a 4-D vector + */ +static inline void vmathV4SetX( VmathVector4 *result, float x ); + +/* + * Set the y element of a 4-D vector + */ +static inline void vmathV4SetY( VmathVector4 *result, float y ); + +/* + * Set the z element of a 4-D vector + */ +static inline void vmathV4SetZ( VmathVector4 *result, float z ); + +/* + * Set the w element of a 4-D vector + */ +static inline void vmathV4SetW( VmathVector4 *result, float w ); + +/* + * Get the x element of a 4-D vector + */ +static inline float vmathV4GetX( const VmathVector4 *vec ); + +/* + * Get the y element of a 4-D vector + */ +static inline float vmathV4GetY( const VmathVector4 *vec ); + +/* + * Get the z element of a 4-D vector + */ +static inline float vmathV4GetZ( const VmathVector4 *vec ); + +/* + * Get the w element of a 4-D vector + */ +static inline float vmathV4GetW( const VmathVector4 *vec ); + +/* + * Set an x, y, z, or w element of a 4-D vector by index + */ +static inline void vmathV4SetElem( VmathVector4 *result, int idx, float value ); + +/* + * Get an x, y, z, or w element of a 4-D vector by index + */ +static inline float vmathV4GetElem( const VmathVector4 *vec, int idx ); + +/* + * Add two 4-D vectors + */ +static inline void vmathV4Add( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Subtract a 4-D vector from another 4-D vector + */ +static inline void vmathV4Sub( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Multiply a 4-D vector by a scalar + */ +static inline void vmathV4ScalarMul( VmathVector4 *result, const VmathVector4 *vec, float scalar ); + +/* + * Divide a 4-D vector by a scalar + */ +static inline void vmathV4ScalarDiv( VmathVector4 *result, const VmathVector4 *vec, float scalar ); + +/* + * Negate all elements of a 4-D vector + */ +static inline void vmathV4Neg( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Construct x axis + */ +static inline void vmathV4MakeXAxis( VmathVector4 *result ); + +/* + * Construct y axis + */ +static inline void vmathV4MakeYAxis( VmathVector4 *result ); + +/* + * Construct z axis + */ +static inline void vmathV4MakeZAxis( VmathVector4 *result ); + +/* + * Construct w axis + */ +static inline void vmathV4MakeWAxis( VmathVector4 *result ); + +/* + * Multiply two 4-D vectors per element + */ +static inline void vmathV4MulPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Divide two 4-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline void vmathV4DivPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Compute the reciprocal of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline void vmathV4RecipPerElem( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Compute the square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline void vmathV4SqrtPerElem( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Compute the reciprocal square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline void vmathV4RsqrtPerElem( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Compute the absolute value of a 4-D vector per element + */ +static inline void vmathV4AbsPerElem( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Copy sign from one 4-D vector to another, per element + */ +static inline void vmathV4CopySignPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Maximum of two 4-D vectors per element + */ +static inline void vmathV4MaxPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Minimum of two 4-D vectors per element + */ +static inline void vmathV4MinPerElem( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Maximum element of a 4-D vector + */ +static inline float vmathV4MaxElem( const VmathVector4 *vec ); + +/* + * Minimum element of a 4-D vector + */ +static inline float vmathV4MinElem( const VmathVector4 *vec ); + +/* + * Compute the sum of all elements of a 4-D vector + */ +static inline float vmathV4Sum( const VmathVector4 *vec ); + +/* + * Compute the dot product of two 4-D vectors + */ +static inline float vmathV4Dot( const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Compute the square of the length of a 4-D vector + */ +static inline float vmathV4LengthSqr( const VmathVector4 *vec ); + +/* + * Compute the length of a 4-D vector + */ +static inline float vmathV4Length( const VmathVector4 *vec ); + +/* + * Normalize a 4-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline void vmathV4Normalize( VmathVector4 *result, const VmathVector4 *vec ); + +/* + * Outer product of two 4-D vectors + */ +static inline void vmathV4Outer( VmathMatrix4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Linear interpolation between two 4-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathV4Lerp( VmathVector4 *result, float t, const VmathVector4 *vec0, const VmathVector4 *vec1 ); + +/* + * Spherical linear interpolation between two 4-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline void vmathV4Slerp( VmathVector4 *result, float t, const VmathVector4 *unitVec0, const VmathVector4 *unitVec1 ); + +/* + * Conditionally select between two 4-D vectors + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathV4Select( VmathVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1, unsigned int select1 ); + +/* + * Store four 4-D vectors as half-floats + */ +static inline void vmathV4StoreHalfFloats( const VmathVector4 *vec0, const VmathVector4 *vec1, const VmathVector4 *vec2, const VmathVector4 *vec3, vec_ushort8 *twoQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV4Print( const VmathVector4 *vec ); + +/* + * Print a 4-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV4Prints( const VmathVector4 *vec, const char *name ); + +#endif + +/* + * Copy a 3-D point + */ +static inline void vmathP3Copy( VmathPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Construct a 3-D point from x, y, and z elements + */ +static inline void vmathP3MakeFromElems( VmathPoint3 *result, float x, float y, float z ); + +/* + * Copy elements from a 3-D vector into a 3-D point + */ +static inline void vmathP3MakeFromV3( VmathPoint3 *result, const VmathVector3 *vec ); + +/* + * Set all elements of a 3-D point to the same scalar value + */ +static inline void vmathP3MakeFromScalar( VmathPoint3 *result, float scalar ); + +/* + * Set vector float data in a 3-D point + */ +static inline void vmathP3MakeFrom128( VmathPoint3 *result, vec_float4 vf4 ); + +/* + * Get vector float data from a 3-D point + */ +static inline vec_float4 vmathP3Get128( const VmathPoint3 *pnt ); + +/* + * Set the x element of a 3-D point + */ +static inline void vmathP3SetX( VmathPoint3 *result, float x ); + +/* + * Set the y element of a 3-D point + */ +static inline void vmathP3SetY( VmathPoint3 *result, float y ); + +/* + * Set the z element of a 3-D point + */ +static inline void vmathP3SetZ( VmathPoint3 *result, float z ); + +/* + * Get the x element of a 3-D point + */ +static inline float vmathP3GetX( const VmathPoint3 *pnt ); + +/* + * Get the y element of a 3-D point + */ +static inline float vmathP3GetY( const VmathPoint3 *pnt ); + +/* + * Get the z element of a 3-D point + */ +static inline float vmathP3GetZ( const VmathPoint3 *pnt ); + +/* + * Set an x, y, or z element of a 3-D point by index + */ +static inline void vmathP3SetElem( VmathPoint3 *result, int idx, float value ); + +/* + * Get an x, y, or z element of a 3-D point by index + */ +static inline float vmathP3GetElem( const VmathPoint3 *pnt, int idx ); + +/* + * Subtract a 3-D point from another 3-D point + */ +static inline void vmathP3Sub( VmathVector3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Add a 3-D point to a 3-D vector + */ +static inline void vmathP3AddV3( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *vec ); + +/* + * Subtract a 3-D vector from a 3-D point + */ +static inline void vmathP3SubV3( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *vec ); + +/* + * Multiply two 3-D points per element + */ +static inline void vmathP3MulPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Divide two 3-D points per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline void vmathP3DivPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Compute the reciprocal of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline void vmathP3RecipPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Compute the square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline void vmathP3SqrtPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Compute the reciprocal square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline void vmathP3RsqrtPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Compute the absolute value of a 3-D point per element + */ +static inline void vmathP3AbsPerElem( VmathPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Copy sign from one 3-D point to another, per element + */ +static inline void vmathP3CopySignPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Maximum of two 3-D points per element + */ +static inline void vmathP3MaxPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Minimum of two 3-D points per element + */ +static inline void vmathP3MinPerElem( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Maximum element of a 3-D point + */ +static inline float vmathP3MaxElem( const VmathPoint3 *pnt ); + +/* + * Minimum element of a 3-D point + */ +static inline float vmathP3MinElem( const VmathPoint3 *pnt ); + +/* + * Compute the sum of all elements of a 3-D point + */ +static inline float vmathP3Sum( const VmathPoint3 *pnt ); + +/* + * Apply uniform scale to a 3-D point + */ +static inline void vmathP3Scale( VmathPoint3 *result, const VmathPoint3 *pnt, float scaleVal ); + +/* + * Apply non-uniform scale to a 3-D point + */ +static inline void vmathP3NonUniformScale( VmathPoint3 *result, const VmathPoint3 *pnt, const VmathVector3 *scaleVec ); + +/* + * Scalar projection of a 3-D point on a unit-length 3-D vector + */ +static inline float vmathP3Projection( const VmathPoint3 *pnt, const VmathVector3 *unitVec ); + +/* + * Compute the square of the distance of a 3-D point from the coordinate-system origin + */ +static inline float vmathP3DistSqrFromOrigin( const VmathPoint3 *pnt ); + +/* + * Compute the distance of a 3-D point from the coordinate-system origin + */ +static inline float vmathP3DistFromOrigin( const VmathPoint3 *pnt ); + +/* + * Compute the square of the distance between two 3-D points + */ +static inline float vmathP3DistSqr( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Compute the distance between two 3-D points + */ +static inline float vmathP3Dist( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Linear interpolation between two 3-D points + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathP3Lerp( VmathPoint3 *result, float t, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1 ); + +/* + * Conditionally select between two 3-D points + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathP3Select( VmathPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, unsigned int select1 ); + +/* + * Store x, y, and z elements of a 3-D point in the first three words of a quadword. + * The value of the fourth word (the word with the highest address) remains unchanged + */ +static inline void vmathP3StoreXYZ( const VmathPoint3 *pnt, vec_float4 *quad ); + +/* + * Load four three-float 3-D points, stored in three quadwords + */ +static inline void vmathP3LoadXYZArray( VmathPoint3 *pnt0, VmathPoint3 *pnt1, VmathPoint3 *pnt2, VmathPoint3 *pnt3, const vec_float4 *threeQuads ); + +/* + * Store four 3-D points in three quadwords + */ +static inline void vmathP3StoreXYZArray( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, const VmathPoint3 *pnt2, const VmathPoint3 *pnt3, vec_float4 *threeQuads ); + +/* + * Store eight 3-D points as half-floats + */ +static inline void vmathP3StoreHalfFloats( const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, const VmathPoint3 *pnt2, const VmathPoint3 *pnt3, const VmathPoint3 *pnt4, const VmathPoint3 *pnt5, const VmathPoint3 *pnt6, const VmathPoint3 *pnt7, vec_ushort8 *threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D point + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathP3Print( const VmathPoint3 *pnt ); + +/* + * Print a 3-D point and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathP3Prints( const VmathPoint3 *pnt, const char *name ); + +#endif + +/* + * Copy a quaternion + */ +static inline void vmathQCopy( VmathQuat *result, const VmathQuat *quat ); + +/* + * Construct a quaternion from x, y, z, and w elements + */ +static inline void vmathQMakeFromElems( VmathQuat *result, float x, float y, float z, float w ); + +/* + * Construct a quaternion from a 3-D vector and a scalar + */ +static inline void vmathQMakeFromV3Scalar( VmathQuat *result, const VmathVector3 *xyz, float w ); + +/* + * Copy elements from a 4-D vector into a quaternion + */ +static inline void vmathQMakeFromV4( VmathQuat *result, const VmathVector4 *vec ); + +/* + * Convert a rotation matrix to a unit-length quaternion + */ +static inline void vmathQMakeFromM3( VmathQuat *result, const VmathMatrix3 *rotMat ); + +/* + * Set all elements of a quaternion to the same scalar value + */ +static inline void vmathQMakeFromScalar( VmathQuat *result, float scalar ); + +/* + * Set vector float data in a quaternion + */ +static inline void vmathQMakeFrom128( VmathQuat *result, vec_float4 vf4 ); + +/* + * Get vector float data from a quaternion + */ +static inline vec_float4 vmathQGet128( const VmathQuat *quat ); + +/* + * Set the x, y, and z elements of a quaternion + * NOTE: + * This function does not change the w element. + */ +static inline void vmathQSetXYZ( VmathQuat *result, const VmathVector3 *vec ); + +/* + * Get the x, y, and z elements of a quaternion + */ +static inline void vmathQGetXYZ( VmathVector3 *result, const VmathQuat *quat ); + +/* + * Set the x element of a quaternion + */ +static inline void vmathQSetX( VmathQuat *result, float x ); + +/* + * Set the y element of a quaternion + */ +static inline void vmathQSetY( VmathQuat *result, float y ); + +/* + * Set the z element of a quaternion + */ +static inline void vmathQSetZ( VmathQuat *result, float z ); + +/* + * Set the w element of a quaternion + */ +static inline void vmathQSetW( VmathQuat *result, float w ); + +/* + * Get the x element of a quaternion + */ +static inline float vmathQGetX( const VmathQuat *quat ); + +/* + * Get the y element of a quaternion + */ +static inline float vmathQGetY( const VmathQuat *quat ); + +/* + * Get the z element of a quaternion + */ +static inline float vmathQGetZ( const VmathQuat *quat ); + +/* + * Get the w element of a quaternion + */ +static inline float vmathQGetW( const VmathQuat *quat ); + +/* + * Set an x, y, z, or w element of a quaternion by index + */ +static inline void vmathQSetElem( VmathQuat *result, int idx, float value ); + +/* + * Get an x, y, z, or w element of a quaternion by index + */ +static inline float vmathQGetElem( const VmathQuat *quat, int idx ); + +/* + * Add two quaternions + */ +static inline void vmathQAdd( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ); + +/* + * Subtract a quaternion from another quaternion + */ +static inline void vmathQSub( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ); + +/* + * Multiply two quaternions + */ +static inline void vmathQMul( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1 ); + +/* + * Multiply a quaternion by a scalar + */ +static inline void vmathQScalarMul( VmathQuat *result, const VmathQuat *quat, float scalar ); + +/* + * Divide a quaternion by a scalar + */ +static inline void vmathQScalarDiv( VmathQuat *result, const VmathQuat *quat, float scalar ); + +/* + * Negate all elements of a quaternion + */ +static inline void vmathQNeg( VmathQuat *result, const VmathQuat *quat ); + +/* + * Construct an identity quaternion + */ +static inline void vmathQMakeIdentity( VmathQuat *result ); + +/* + * Construct a quaternion to rotate between two unit-length 3-D vectors + * NOTE: + * The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + */ +static inline void vmathQMakeRotationArc( VmathQuat *result, const VmathVector3 *unitVec0, const VmathVector3 *unitVec1 ); + +/* + * Construct a quaternion to rotate around a unit-length 3-D vector + */ +static inline void vmathQMakeRotationAxis( VmathQuat *result, float radians, const VmathVector3 *unitVec ); + +/* + * Construct a quaternion to rotate around the x axis + */ +static inline void vmathQMakeRotationX( VmathQuat *result, float radians ); + +/* + * Construct a quaternion to rotate around the y axis + */ +static inline void vmathQMakeRotationY( VmathQuat *result, float radians ); + +/* + * Construct a quaternion to rotate around the z axis + */ +static inline void vmathQMakeRotationZ( VmathQuat *result, float radians ); + +/* + * Compute the conjugate of a quaternion + */ +static inline void vmathQConj( VmathQuat *result, const VmathQuat *quat ); + +/* + * Use a unit-length quaternion to rotate a 3-D vector + */ +static inline void vmathQRotate( VmathVector3 *result, const VmathQuat *unitQuat, const VmathVector3 *vec ); + +/* + * Compute the dot product of two quaternions + */ +static inline float vmathQDot( const VmathQuat *quat0, const VmathQuat *quat1 ); + +/* + * Compute the norm of a quaternion + */ +static inline float vmathQNorm( const VmathQuat *quat ); + +/* + * Compute the length of a quaternion + */ +static inline float vmathQLength( const VmathQuat *quat ); + +/* + * Normalize a quaternion + * NOTE: + * The result is unpredictable when all elements of quat are at or near zero. + */ +static inline void vmathQNormalize( VmathQuat *result, const VmathQuat *quat ); + +/* + * Linear interpolation between two quaternions + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathQLerp( VmathQuat *result, float t, const VmathQuat *quat0, const VmathQuat *quat1 ); + +/* + * Spherical linear interpolation between two quaternions + * NOTE: + * Interpolates along the shortest path between orientations. + * Does not clamp t between 0 and 1. + */ +static inline void vmathQSlerp( VmathQuat *result, float t, const VmathQuat *unitQuat0, const VmathQuat *unitQuat1 ); + +/* + * Spherical quadrangle interpolation + */ +static inline void vmathQSquad( VmathQuat *result, float t, const VmathQuat *unitQuat0, const VmathQuat *unitQuat1, const VmathQuat *unitQuat2, const VmathQuat *unitQuat3 ); + +/* + * Conditionally select between two quaternions + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathQSelect( VmathQuat *result, const VmathQuat *quat0, const VmathQuat *quat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a quaternion + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathQPrint( const VmathQuat *quat ); + +/* + * Print a quaternion and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathQPrints( const VmathQuat *quat, const char *name ); + +#endif + +/* + * Copy a 3x3 matrix + */ +static inline void vmathM3Copy( VmathMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Construct a 3x3 matrix containing the specified columns + */ +static inline void vmathM3MakeFromCols( VmathMatrix3 *result, const VmathVector3 *col0, const VmathVector3 *col1, const VmathVector3 *col2 ); + +/* + * Construct a 3x3 rotation matrix from a unit-length quaternion + */ +static inline void vmathM3MakeFromQ( VmathMatrix3 *result, const VmathQuat *unitQuat ); + +/* + * Set all elements of a 3x3 matrix to the same scalar value + */ +static inline void vmathM3MakeFromScalar( VmathMatrix3 *result, float scalar ); + +/* + * Set column 0 of a 3x3 matrix + */ +static inline void vmathM3SetCol0( VmathMatrix3 *result, const VmathVector3 *col0 ); + +/* + * Set column 1 of a 3x3 matrix + */ +static inline void vmathM3SetCol1( VmathMatrix3 *result, const VmathVector3 *col1 ); + +/* + * Set column 2 of a 3x3 matrix + */ +static inline void vmathM3SetCol2( VmathMatrix3 *result, const VmathVector3 *col2 ); + +/* + * Get column 0 of a 3x3 matrix + */ +static inline void vmathM3GetCol0( VmathVector3 *result, const VmathMatrix3 *mat ); + +/* + * Get column 1 of a 3x3 matrix + */ +static inline void vmathM3GetCol1( VmathVector3 *result, const VmathMatrix3 *mat ); + +/* + * Get column 2 of a 3x3 matrix + */ +static inline void vmathM3GetCol2( VmathVector3 *result, const VmathMatrix3 *mat ); + +/* + * Set the column of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3SetCol( VmathMatrix3 *result, int col, const VmathVector3 *vec ); + +/* + * Set the row of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3SetRow( VmathMatrix3 *result, int row, const VmathVector3 *vec ); + +/* + * Get the column of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3GetCol( VmathVector3 *result, const VmathMatrix3 *mat, int col ); + +/* + * Get the row of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3GetRow( VmathVector3 *result, const VmathMatrix3 *mat, int row ); + +/* + * Set the element of a 3x3 matrix referred to by column and row indices + */ +static inline void vmathM3SetElem( VmathMatrix3 *result, int col, int row, float val ); + +/* + * Get the element of a 3x3 matrix referred to by column and row indices + */ +static inline float vmathM3GetElem( const VmathMatrix3 *mat, int col, int row ); + +/* + * Add two 3x3 matrices + */ +static inline void vmathM3Add( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ); + +/* + * Subtract a 3x3 matrix from another 3x3 matrix + */ +static inline void vmathM3Sub( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ); + +/* + * Negate all elements of a 3x3 matrix + */ +static inline void vmathM3Neg( VmathMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Multiply a 3x3 matrix by a scalar + */ +static inline void vmathM3ScalarMul( VmathMatrix3 *result, const VmathMatrix3 *mat, float scalar ); + +/* + * Multiply a 3x3 matrix by a 3-D vector + */ +static inline void vmathM3MulV3( VmathVector3 *result, const VmathMatrix3 *mat, const VmathVector3 *vec ); + +/* + * Multiply two 3x3 matrices + */ +static inline void vmathM3Mul( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ); + +/* + * Construct an identity 3x3 matrix + */ +static inline void vmathM3MakeIdentity( VmathMatrix3 *result ); + +/* + * Construct a 3x3 matrix to rotate around the x axis + */ +static inline void vmathM3MakeRotationX( VmathMatrix3 *result, float radians ); + +/* + * Construct a 3x3 matrix to rotate around the y axis + */ +static inline void vmathM3MakeRotationY( VmathMatrix3 *result, float radians ); + +/* + * Construct a 3x3 matrix to rotate around the z axis + */ +static inline void vmathM3MakeRotationZ( VmathMatrix3 *result, float radians ); + +/* + * Construct a 3x3 matrix to rotate around the x, y, and z axes + */ +static inline void vmathM3MakeRotationZYX( VmathMatrix3 *result, const VmathVector3 *radiansXYZ ); + +/* + * Construct a 3x3 matrix to rotate around a unit-length 3-D vector + */ +static inline void vmathM3MakeRotationAxis( VmathMatrix3 *result, float radians, const VmathVector3 *unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline void vmathM3MakeRotationQ( VmathMatrix3 *result, const VmathQuat *unitQuat ); + +/* + * Construct a 3x3 matrix to perform scaling + */ +static inline void vmathM3MakeScale( VmathMatrix3 *result, const VmathVector3 *scaleVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathM3AppendScale( VmathMatrix3 *result, const VmathMatrix3 *mat, const VmathVector3 *scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathM3PrependScale( VmathMatrix3 *result, const VmathVector3 *scaleVec, const VmathMatrix3 *mat ); + +/* + * Multiply two 3x3 matrices per element + */ +static inline void vmathM3MulPerElem( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1 ); + +/* + * Compute the absolute value of a 3x3 matrix per element + */ +static inline void vmathM3AbsPerElem( VmathMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Transpose of a 3x3 matrix + */ +static inline void vmathM3Transpose( VmathMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Compute the inverse of a 3x3 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline void vmathM3Inverse( VmathMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Determinant of a 3x3 matrix + */ +static inline float vmathM3Determinant( const VmathMatrix3 *mat ); + +/* + * Conditionally select between two 3x3 matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathM3Select( VmathMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x3 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM3Print( const VmathMatrix3 *mat ); + +/* + * Print a 3x3 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM3Prints( const VmathMatrix3 *mat, const char *name ); + +#endif + +/* + * Copy a 4x4 matrix + */ +static inline void vmathM4Copy( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Construct a 4x4 matrix containing the specified columns + */ +static inline void vmathM4MakeFromCols( VmathMatrix4 *result, const VmathVector4 *col0, const VmathVector4 *col1, const VmathVector4 *col2, const VmathVector4 *col3 ); + +/* + * Construct a 4x4 matrix from a 3x4 transformation matrix + */ +static inline void vmathM4MakeFromT3( VmathMatrix4 *result, const VmathTransform3 *mat ); + +/* + * Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + */ +static inline void vmathM4MakeFromM3V3( VmathMatrix4 *result, const VmathMatrix3 *mat, const VmathVector3 *translateVec ); + +/* + * Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + */ +static inline void vmathM4MakeFromQV3( VmathMatrix4 *result, const VmathQuat *unitQuat, const VmathVector3 *translateVec ); + +/* + * Set all elements of a 4x4 matrix to the same scalar value + */ +static inline void vmathM4MakeFromScalar( VmathMatrix4 *result, float scalar ); + +/* + * Set the upper-left 3x3 submatrix + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathM4SetUpper3x3( VmathMatrix4 *result, const VmathMatrix3 *mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 4x4 matrix + */ +static inline void vmathM4GetUpper3x3( VmathMatrix3 *result, const VmathMatrix4 *mat ); + +/* + * Set translation component + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathM4SetTranslation( VmathMatrix4 *result, const VmathVector3 *translateVec ); + +/* + * Get the translation component of a 4x4 matrix + */ +static inline void vmathM4GetTranslation( VmathVector3 *result, const VmathMatrix4 *mat ); + +/* + * Set column 0 of a 4x4 matrix + */ +static inline void vmathM4SetCol0( VmathMatrix4 *result, const VmathVector4 *col0 ); + +/* + * Set column 1 of a 4x4 matrix + */ +static inline void vmathM4SetCol1( VmathMatrix4 *result, const VmathVector4 *col1 ); + +/* + * Set column 2 of a 4x4 matrix + */ +static inline void vmathM4SetCol2( VmathMatrix4 *result, const VmathVector4 *col2 ); + +/* + * Set column 3 of a 4x4 matrix + */ +static inline void vmathM4SetCol3( VmathMatrix4 *result, const VmathVector4 *col3 ); + +/* + * Get column 0 of a 4x4 matrix + */ +static inline void vmathM4GetCol0( VmathVector4 *result, const VmathMatrix4 *mat ); + +/* + * Get column 1 of a 4x4 matrix + */ +static inline void vmathM4GetCol1( VmathVector4 *result, const VmathMatrix4 *mat ); + +/* + * Get column 2 of a 4x4 matrix + */ +static inline void vmathM4GetCol2( VmathVector4 *result, const VmathMatrix4 *mat ); + +/* + * Get column 3 of a 4x4 matrix + */ +static inline void vmathM4GetCol3( VmathVector4 *result, const VmathMatrix4 *mat ); + +/* + * Set the column of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4SetCol( VmathMatrix4 *result, int col, const VmathVector4 *vec ); + +/* + * Set the row of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4SetRow( VmathMatrix4 *result, int row, const VmathVector4 *vec ); + +/* + * Get the column of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4GetCol( VmathVector4 *result, const VmathMatrix4 *mat, int col ); + +/* + * Get the row of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4GetRow( VmathVector4 *result, const VmathMatrix4 *mat, int row ); + +/* + * Set the element of a 4x4 matrix referred to by column and row indices + */ +static inline void vmathM4SetElem( VmathMatrix4 *result, int col, int row, float val ); + +/* + * Get the element of a 4x4 matrix referred to by column and row indices + */ +static inline float vmathM4GetElem( const VmathMatrix4 *mat, int col, int row ); + +/* + * Add two 4x4 matrices + */ +static inline void vmathM4Add( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ); + +/* + * Subtract a 4x4 matrix from another 4x4 matrix + */ +static inline void vmathM4Sub( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ); + +/* + * Negate all elements of a 4x4 matrix + */ +static inline void vmathM4Neg( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Multiply a 4x4 matrix by a scalar + */ +static inline void vmathM4ScalarMul( VmathMatrix4 *result, const VmathMatrix4 *mat, float scalar ); + +/* + * Multiply a 4x4 matrix by a 4-D vector + */ +static inline void vmathM4MulV4( VmathVector4 *result, const VmathMatrix4 *mat, const VmathVector4 *vec ); + +/* + * Multiply a 4x4 matrix by a 3-D vector + */ +static inline void vmathM4MulV3( VmathVector4 *result, const VmathMatrix4 *mat, const VmathVector3 *vec ); + +/* + * Multiply a 4x4 matrix by a 3-D point + */ +static inline void vmathM4MulP3( VmathVector4 *result, const VmathMatrix4 *mat, const VmathPoint3 *pnt ); + +/* + * Multiply two 4x4 matrices + */ +static inline void vmathM4Mul( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ); + +/* + * Multiply a 4x4 matrix by a 3x4 transformation matrix + */ +static inline void vmathM4MulT3( VmathMatrix4 *result, const VmathMatrix4 *mat, const VmathTransform3 *tfrm ); + +/* + * Construct an identity 4x4 matrix + */ +static inline void vmathM4MakeIdentity( VmathMatrix4 *result ); + +/* + * Construct a 4x4 matrix to rotate around the x axis + */ +static inline void vmathM4MakeRotationX( VmathMatrix4 *result, float radians ); + +/* + * Construct a 4x4 matrix to rotate around the y axis + */ +static inline void vmathM4MakeRotationY( VmathMatrix4 *result, float radians ); + +/* + * Construct a 4x4 matrix to rotate around the z axis + */ +static inline void vmathM4MakeRotationZ( VmathMatrix4 *result, float radians ); + +/* + * Construct a 4x4 matrix to rotate around the x, y, and z axes + */ +static inline void vmathM4MakeRotationZYX( VmathMatrix4 *result, const VmathVector3 *radiansXYZ ); + +/* + * Construct a 4x4 matrix to rotate around a unit-length 3-D vector + */ +static inline void vmathM4MakeRotationAxis( VmathMatrix4 *result, float radians, const VmathVector3 *unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline void vmathM4MakeRotationQ( VmathMatrix4 *result, const VmathQuat *unitQuat ); + +/* + * Construct a 4x4 matrix to perform scaling + */ +static inline void vmathM4MakeScale( VmathMatrix4 *result, const VmathVector3 *scaleVec ); + +/* + * Construct a 4x4 matrix to perform translation + */ +static inline void vmathM4MakeTranslation( VmathMatrix4 *result, const VmathVector3 *translateVec ); + +/* + * Construct viewing matrix based on eye position, position looked at, and up direction + */ +static inline void vmathM4MakeLookAt( VmathMatrix4 *result, const VmathPoint3 *eyePos, const VmathPoint3 *lookAtPos, const VmathVector3 *upVec ); + +/* + * Construct a perspective projection matrix + */ +static inline void vmathM4MakePerspective( VmathMatrix4 *result, float fovyRadians, float aspect, float zNear, float zFar ); + +/* + * Construct a perspective projection matrix based on frustum + */ +static inline void vmathM4MakeFrustum( VmathMatrix4 *result, float left, float right, float bottom, float top, float zNear, float zFar ); + +/* + * Construct an orthographic projection matrix + */ +static inline void vmathM4MakeOrthographic( VmathMatrix4 *result, float left, float right, float bottom, float top, float zNear, float zFar ); + +/* + * Append (post-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathM4AppendScale( VmathMatrix4 *result, const VmathMatrix4 *mat, const VmathVector3 *scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathM4PrependScale( VmathMatrix4 *result, const VmathVector3 *scaleVec, const VmathMatrix4 *mat ); + +/* + * Multiply two 4x4 matrices per element + */ +static inline void vmathM4MulPerElem( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1 ); + +/* + * Compute the absolute value of a 4x4 matrix per element + */ +static inline void vmathM4AbsPerElem( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Transpose of a 4x4 matrix + */ +static inline void vmathM4Transpose( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Compute the inverse of a 4x4 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline void vmathM4Inverse( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline void vmathM4AffineInverse( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. + */ +static inline void vmathM4OrthoInverse( VmathMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Determinant of a 4x4 matrix + */ +static inline float vmathM4Determinant( const VmathMatrix4 *mat ); + +/* + * Conditionally select between two 4x4 matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathM4Select( VmathMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4x4 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM4Print( const VmathMatrix4 *mat ); + +/* + * Print a 4x4 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM4Prints( const VmathMatrix4 *mat, const char *name ); + +#endif + +/* + * Copy a 3x4 transformation matrix + */ +static inline void vmathT3Copy( VmathTransform3 *result, const VmathTransform3 *tfrm ); + +/* + * Construct a 3x4 transformation matrix containing the specified columns + */ +static inline void vmathT3MakeFromCols( VmathTransform3 *result, const VmathVector3 *col0, const VmathVector3 *col1, const VmathVector3 *col2, const VmathVector3 *col3 ); + +/* + * Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + */ +static inline void vmathT3MakeFromM3V3( VmathTransform3 *result, const VmathMatrix3 *tfrm, const VmathVector3 *translateVec ); + +/* + * Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + */ +static inline void vmathT3MakeFromQV3( VmathTransform3 *result, const VmathQuat *unitQuat, const VmathVector3 *translateVec ); + +/* + * Set all elements of a 3x4 transformation matrix to the same scalar value + */ +static inline void vmathT3MakeFromScalar( VmathTransform3 *result, float scalar ); + +/* + * Set the upper-left 3x3 submatrix + */ +static inline void vmathT3SetUpper3x3( VmathTransform3 *result, const VmathMatrix3 *mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + */ +static inline void vmathT3GetUpper3x3( VmathMatrix3 *result, const VmathTransform3 *tfrm ); + +/* + * Set translation component + */ +static inline void vmathT3SetTranslation( VmathTransform3 *result, const VmathVector3 *translateVec ); + +/* + * Get the translation component of a 3x4 transformation matrix + */ +static inline void vmathT3GetTranslation( VmathVector3 *result, const VmathTransform3 *tfrm ); + +/* + * Set column 0 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol0( VmathTransform3 *result, const VmathVector3 *col0 ); + +/* + * Set column 1 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol1( VmathTransform3 *result, const VmathVector3 *col1 ); + +/* + * Set column 2 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol2( VmathTransform3 *result, const VmathVector3 *col2 ); + +/* + * Set column 3 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol3( VmathTransform3 *result, const VmathVector3 *col3 ); + +/* + * Get column 0 of a 3x4 transformation matrix + */ +static inline void vmathT3GetCol0( VmathVector3 *result, const VmathTransform3 *tfrm ); + +/* + * Get column 1 of a 3x4 transformation matrix + */ +static inline void vmathT3GetCol1( VmathVector3 *result, const VmathTransform3 *tfrm ); + +/* + * Get column 2 of a 3x4 transformation matrix + */ +static inline void vmathT3GetCol2( VmathVector3 *result, const VmathTransform3 *tfrm ); + +/* + * Get column 3 of a 3x4 transformation matrix + */ +static inline void vmathT3GetCol3( VmathVector3 *result, const VmathTransform3 *tfrm ); + +/* + * Set the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3SetCol( VmathTransform3 *result, int col, const VmathVector3 *vec ); + +/* + * Set the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3SetRow( VmathTransform3 *result, int row, const VmathVector4 *vec ); + +/* + * Get the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3GetCol( VmathVector3 *result, const VmathTransform3 *tfrm, int col ); + +/* + * Get the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3GetRow( VmathVector4 *result, const VmathTransform3 *tfrm, int row ); + +/* + * Set the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline void vmathT3SetElem( VmathTransform3 *result, int col, int row, float val ); + +/* + * Get the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline float vmathT3GetElem( const VmathTransform3 *tfrm, int col, int row ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D vector + */ +static inline void vmathT3MulV3( VmathVector3 *result, const VmathTransform3 *tfrm, const VmathVector3 *vec ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D point + */ +static inline void vmathT3MulP3( VmathPoint3 *result, const VmathTransform3 *tfrm, const VmathPoint3 *pnt ); + +/* + * Multiply two 3x4 transformation matrices + */ +static inline void vmathT3Mul( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1 ); + +/* + * Construct an identity 3x4 transformation matrix + */ +static inline void vmathT3MakeIdentity( VmathTransform3 *result ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x axis + */ +static inline void vmathT3MakeRotationX( VmathTransform3 *result, float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the y axis + */ +static inline void vmathT3MakeRotationY( VmathTransform3 *result, float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the z axis + */ +static inline void vmathT3MakeRotationZ( VmathTransform3 *result, float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + */ +static inline void vmathT3MakeRotationZYX( VmathTransform3 *result, const VmathVector3 *radiansXYZ ); + +/* + * Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + */ +static inline void vmathT3MakeRotationAxis( VmathTransform3 *result, float radians, const VmathVector3 *unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline void vmathT3MakeRotationQ( VmathTransform3 *result, const VmathQuat *unitQuat ); + +/* + * Construct a 3x4 transformation matrix to perform scaling + */ +static inline void vmathT3MakeScale( VmathTransform3 *result, const VmathVector3 *scaleVec ); + +/* + * Construct a 3x4 transformation matrix to perform translation + */ +static inline void vmathT3MakeTranslation( VmathTransform3 *result, const VmathVector3 *translateVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathT3AppendScale( VmathTransform3 *result, const VmathTransform3 *tfrm, const VmathVector3 *scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathT3PrependScale( VmathTransform3 *result, const VmathVector3 *scaleVec, const VmathTransform3 *tfrm ); + +/* + * Multiply two 3x4 transformation matrices per element + */ +static inline void vmathT3MulPerElem( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1 ); + +/* + * Compute the absolute value of a 3x4 transformation matrix per element + */ +static inline void vmathT3AbsPerElem( VmathTransform3 *result, const VmathTransform3 *tfrm ); + +/* + * Inverse of a 3x4 transformation matrix + * NOTE: + * Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. + */ +static inline void vmathT3Inverse( VmathTransform3 *result, const VmathTransform3 *tfrm ); + +/* + * Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. + */ +static inline void vmathT3OrthoInverse( VmathTransform3 *result, const VmathTransform3 *tfrm ); + +/* + * Conditionally select between two 3x4 transformation matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathT3Select( VmathTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x4 transformation matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathT3Print( const VmathTransform3 *tfrm ); + +/* + * Print a 3x4 transformation matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathT3Prints( const VmathTransform3 *tfrm, const char *name ); + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#include "vec_aos.h" +#include "quat_aos.h" +#include "mat_aos.h" + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/c/vectormath_aos_v.h b/Extras/vectormathlibrary/include/vectormath/spu/c/vectormath_aos_v.h new file mode 100644 index 0000000..cca0872 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/c/vectormath_aos_v.h @@ -0,0 +1,1916 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_AOS_C_V_SPU_H +#define _VECTORMATH_AOS_C_V_SPU_H + +#include +#include + +#ifdef _VECTORMATH_DEBUG +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef _VECTORMATH_AOS_C_TYPES_H +#define _VECTORMATH_AOS_C_TYPES_H + +/* A 3-D vector in array-of-structures format + */ +typedef struct _VmathVector3 +{ + vec_float4 vec128; +} VmathVector3; + +/* A 4-D vector in array-of-structures format + */ +typedef struct _VmathVector4 +{ + vec_float4 vec128; +} VmathVector4; + +/* A 3-D point in array-of-structures format + */ +typedef struct _VmathPoint3 +{ + vec_float4 vec128; +} VmathPoint3; + +/* A quaternion in array-of-structures format + */ +typedef struct _VmathQuat +{ + vec_float4 vec128; +} VmathQuat; + +/* A 3x3 matrix in array-of-structures format + */ +typedef struct _VmathMatrix3 +{ + VmathVector3 col0; + VmathVector3 col1; + VmathVector3 col2; +} VmathMatrix3; + +/* A 4x4 matrix in array-of-structures format + */ +typedef struct _VmathMatrix4 +{ + VmathVector4 col0; + VmathVector4 col1; + VmathVector4 col2; + VmathVector4 col3; +} VmathMatrix4; + +/* A 3x4 transformation matrix in array-of-structures format + */ +typedef struct _VmathTransform3 +{ + VmathVector3 col0; + VmathVector3 col1; + VmathVector3 col2; + VmathVector3 col3; +} VmathTransform3; + +#endif + +/* + * Construct a 3-D vector from x, y, and z elements + */ +static inline VmathVector3 vmathV3MakeFromElems_V( float x, float y, float z ); + +/* + * Copy elements from a 3-D point into a 3-D vector + */ +static inline VmathVector3 vmathV3MakeFromP3_V( VmathPoint3 pnt ); + +/* + * Set all elements of a 3-D vector to the same scalar value + */ +static inline VmathVector3 vmathV3MakeFromScalar_V( float scalar ); + +/* + * Set vector float data in a 3-D vector + */ +static inline VmathVector3 vmathV3MakeFrom128_V( vec_float4 vf4 ); + +/* + * Get vector float data from a 3-D vector + */ +static inline vec_float4 vmathV3Get128_V( VmathVector3 vec ); + +/* + * Set the x element of a 3-D vector + */ +static inline void vmathV3SetX_V( VmathVector3 *result, float x ); + +/* + * Set the y element of a 3-D vector + */ +static inline void vmathV3SetY_V( VmathVector3 *result, float y ); + +/* + * Set the z element of a 3-D vector + */ +static inline void vmathV3SetZ_V( VmathVector3 *result, float z ); + +/* + * Get the x element of a 3-D vector + */ +static inline float vmathV3GetX_V( VmathVector3 vec ); + +/* + * Get the y element of a 3-D vector + */ +static inline float vmathV3GetY_V( VmathVector3 vec ); + +/* + * Get the z element of a 3-D vector + */ +static inline float vmathV3GetZ_V( VmathVector3 vec ); + +/* + * Set an x, y, or z element of a 3-D vector by index + */ +static inline void vmathV3SetElem_V( VmathVector3 *result, int idx, float value ); + +/* + * Get an x, y, or z element of a 3-D vector by index + */ +static inline float vmathV3GetElem_V( VmathVector3 vec, int idx ); + +/* + * Add two 3-D vectors + */ +static inline VmathVector3 vmathV3Add_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Subtract a 3-D vector from another 3-D vector + */ +static inline VmathVector3 vmathV3Sub_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Add a 3-D vector to a 3-D point + */ +static inline VmathPoint3 vmathV3AddP3_V( VmathVector3 vec, VmathPoint3 pnt ); + +/* + * Multiply a 3-D vector by a scalar + */ +static inline VmathVector3 vmathV3ScalarMul_V( VmathVector3 vec, float scalar ); + +/* + * Divide a 3-D vector by a scalar + */ +static inline VmathVector3 vmathV3ScalarDiv_V( VmathVector3 vec, float scalar ); + +/* + * Negate all elements of a 3-D vector + */ +static inline VmathVector3 vmathV3Neg_V( VmathVector3 vec ); + +/* + * Construct x axis + */ +static inline VmathVector3 vmathV3MakeXAxis_V( ); + +/* + * Construct y axis + */ +static inline VmathVector3 vmathV3MakeYAxis_V( ); + +/* + * Construct z axis + */ +static inline VmathVector3 vmathV3MakeZAxis_V( ); + +/* + * Multiply two 3-D vectors per element + */ +static inline VmathVector3 vmathV3MulPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Divide two 3-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline VmathVector3 vmathV3DivPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Compute the reciprocal of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline VmathVector3 vmathV3RecipPerElem_V( VmathVector3 vec ); + +/* + * Compute the square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline VmathVector3 vmathV3SqrtPerElem_V( VmathVector3 vec ); + +/* + * Compute the reciprocal square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline VmathVector3 vmathV3RsqrtPerElem_V( VmathVector3 vec ); + +/* + * Compute the absolute value of a 3-D vector per element + */ +static inline VmathVector3 vmathV3AbsPerElem_V( VmathVector3 vec ); + +/* + * Copy sign from one 3-D vector to another, per element + */ +static inline VmathVector3 vmathV3CopySignPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Maximum of two 3-D vectors per element + */ +static inline VmathVector3 vmathV3MaxPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Minimum of two 3-D vectors per element + */ +static inline VmathVector3 vmathV3MinPerElem_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Maximum element of a 3-D vector + */ +static inline float vmathV3MaxElem_V( VmathVector3 vec ); + +/* + * Minimum element of a 3-D vector + */ +static inline float vmathV3MinElem_V( VmathVector3 vec ); + +/* + * Compute the sum of all elements of a 3-D vector + */ +static inline float vmathV3Sum_V( VmathVector3 vec ); + +/* + * Compute the dot product of two 3-D vectors + */ +static inline float vmathV3Dot_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Compute the square of the length of a 3-D vector + */ +static inline float vmathV3LengthSqr_V( VmathVector3 vec ); + +/* + * Compute the length of a 3-D vector + */ +static inline float vmathV3Length_V( VmathVector3 vec ); + +/* + * Normalize a 3-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline VmathVector3 vmathV3Normalize_V( VmathVector3 vec ); + +/* + * Compute cross product of two 3-D vectors + */ +static inline VmathVector3 vmathV3Cross_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Outer product of two 3-D vectors + */ +static inline VmathMatrix3 vmathV3Outer_V( VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Pre-multiply a row vector by a 3x3 matrix + * NOTE: + * Slower than column post-multiply. + */ +static inline VmathVector3 vmathV3RowMul_V( VmathVector3 vec, VmathMatrix3 mat ); + +/* + * Cross-product matrix of a 3-D vector + */ +static inline VmathMatrix3 vmathV3CrossMatrix_V( VmathVector3 vec ); + +/* + * Create cross-product matrix and multiply + * NOTE: + * Faster than separately creating a cross-product matrix and multiplying. + */ +static inline VmathMatrix3 vmathV3CrossMatrixMul_V( VmathVector3 vec, VmathMatrix3 mat ); + +/* + * Linear interpolation between two 3-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathVector3 vmathV3Lerp_V( float t, VmathVector3 vec0, VmathVector3 vec1 ); + +/* + * Spherical linear interpolation between two 3-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline VmathVector3 vmathV3Slerp_V( float t, VmathVector3 unitVec0, VmathVector3 unitVec1 ); + +/* + * Conditionally select between two 3-D vectors + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathVector3 vmathV3Select_V( VmathVector3 vec0, VmathVector3 vec1, unsigned int select1 ); + +/* + * Store x, y, and z elements of a 3-D vector in the first three words of a quadword. + * The value of the fourth word (the word with the highest address) remains unchanged + */ +static inline void vmathV3StoreXYZ_V( VmathVector3 vec, vec_float4 *quad ); + +/* + * Load four three-float 3-D vectors, stored in three quadwords + */ +static inline void vmathV3LoadXYZArray_V( VmathVector3 *vec0, VmathVector3 *vec1, VmathVector3 *vec2, VmathVector3 *vec3, const vec_float4 *threeQuads ); + +/* + * Store four 3-D vectors in three quadwords + */ +static inline void vmathV3StoreXYZArray_V( VmathVector3 vec0, VmathVector3 vec1, VmathVector3 vec2, VmathVector3 vec3, vec_float4 *threeQuads ); + +/* + * Store eight 3-D vectors as half-floats + */ +static inline void vmathV3StoreHalfFloats_V( VmathVector3 vec0, VmathVector3 vec1, VmathVector3 vec2, VmathVector3 vec3, VmathVector3 vec4, VmathVector3 vec5, VmathVector3 vec6, VmathVector3 vec7, vec_ushort8 *threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV3Print_V( VmathVector3 vec ); + +/* + * Print a 3-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV3Prints_V( VmathVector3 vec, const char *name ); + +#endif + +/* + * Construct a 4-D vector from x, y, z, and w elements + */ +static inline VmathVector4 vmathV4MakeFromElems_V( float x, float y, float z, float w ); + +/* + * Construct a 4-D vector from a 3-D vector and a scalar + */ +static inline VmathVector4 vmathV4MakeFromV3Scalar_V( VmathVector3 xyz, float w ); + +/* + * Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + */ +static inline VmathVector4 vmathV4MakeFromV3_V( VmathVector3 vec ); + +/* + * Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + */ +static inline VmathVector4 vmathV4MakeFromP3_V( VmathPoint3 pnt ); + +/* + * Copy elements from a quaternion into a 4-D vector + */ +static inline VmathVector4 vmathV4MakeFromQ_V( VmathQuat quat ); + +/* + * Set all elements of a 4-D vector to the same scalar value + */ +static inline VmathVector4 vmathV4MakeFromScalar_V( float scalar ); + +/* + * Set vector float data in a 4-D vector + */ +static inline VmathVector4 vmathV4MakeFrom128_V( vec_float4 vf4 ); + +/* + * Get vector float data from a 4-D vector + */ +static inline vec_float4 vmathV4Get128_V( VmathVector4 vec ); + +/* + * Set the x, y, and z elements of a 4-D vector + * NOTE: + * This function does not change the w element. + */ +static inline void vmathV4SetXYZ_V( VmathVector4 *result, VmathVector3 vec ); + +/* + * Get the x, y, and z elements of a 4-D vector + */ +static inline VmathVector3 vmathV4GetXYZ_V( VmathVector4 vec ); + +/* + * Set the x element of a 4-D vector + */ +static inline void vmathV4SetX_V( VmathVector4 *result, float x ); + +/* + * Set the y element of a 4-D vector + */ +static inline void vmathV4SetY_V( VmathVector4 *result, float y ); + +/* + * Set the z element of a 4-D vector + */ +static inline void vmathV4SetZ_V( VmathVector4 *result, float z ); + +/* + * Set the w element of a 4-D vector + */ +static inline void vmathV4SetW_V( VmathVector4 *result, float w ); + +/* + * Get the x element of a 4-D vector + */ +static inline float vmathV4GetX_V( VmathVector4 vec ); + +/* + * Get the y element of a 4-D vector + */ +static inline float vmathV4GetY_V( VmathVector4 vec ); + +/* + * Get the z element of a 4-D vector + */ +static inline float vmathV4GetZ_V( VmathVector4 vec ); + +/* + * Get the w element of a 4-D vector + */ +static inline float vmathV4GetW_V( VmathVector4 vec ); + +/* + * Set an x, y, z, or w element of a 4-D vector by index + */ +static inline void vmathV4SetElem_V( VmathVector4 *result, int idx, float value ); + +/* + * Get an x, y, z, or w element of a 4-D vector by index + */ +static inline float vmathV4GetElem_V( VmathVector4 vec, int idx ); + +/* + * Add two 4-D vectors + */ +static inline VmathVector4 vmathV4Add_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Subtract a 4-D vector from another 4-D vector + */ +static inline VmathVector4 vmathV4Sub_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Multiply a 4-D vector by a scalar + */ +static inline VmathVector4 vmathV4ScalarMul_V( VmathVector4 vec, float scalar ); + +/* + * Divide a 4-D vector by a scalar + */ +static inline VmathVector4 vmathV4ScalarDiv_V( VmathVector4 vec, float scalar ); + +/* + * Negate all elements of a 4-D vector + */ +static inline VmathVector4 vmathV4Neg_V( VmathVector4 vec ); + +/* + * Construct x axis + */ +static inline VmathVector4 vmathV4MakeXAxis_V( ); + +/* + * Construct y axis + */ +static inline VmathVector4 vmathV4MakeYAxis_V( ); + +/* + * Construct z axis + */ +static inline VmathVector4 vmathV4MakeZAxis_V( ); + +/* + * Construct w axis + */ +static inline VmathVector4 vmathV4MakeWAxis_V( ); + +/* + * Multiply two 4-D vectors per element + */ +static inline VmathVector4 vmathV4MulPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Divide two 4-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline VmathVector4 vmathV4DivPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Compute the reciprocal of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline VmathVector4 vmathV4RecipPerElem_V( VmathVector4 vec ); + +/* + * Compute the square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline VmathVector4 vmathV4SqrtPerElem_V( VmathVector4 vec ); + +/* + * Compute the reciprocal square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline VmathVector4 vmathV4RsqrtPerElem_V( VmathVector4 vec ); + +/* + * Compute the absolute value of a 4-D vector per element + */ +static inline VmathVector4 vmathV4AbsPerElem_V( VmathVector4 vec ); + +/* + * Copy sign from one 4-D vector to another, per element + */ +static inline VmathVector4 vmathV4CopySignPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Maximum of two 4-D vectors per element + */ +static inline VmathVector4 vmathV4MaxPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Minimum of two 4-D vectors per element + */ +static inline VmathVector4 vmathV4MinPerElem_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Maximum element of a 4-D vector + */ +static inline float vmathV4MaxElem_V( VmathVector4 vec ); + +/* + * Minimum element of a 4-D vector + */ +static inline float vmathV4MinElem_V( VmathVector4 vec ); + +/* + * Compute the sum of all elements of a 4-D vector + */ +static inline float vmathV4Sum_V( VmathVector4 vec ); + +/* + * Compute the dot product of two 4-D vectors + */ +static inline float vmathV4Dot_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Compute the square of the length of a 4-D vector + */ +static inline float vmathV4LengthSqr_V( VmathVector4 vec ); + +/* + * Compute the length of a 4-D vector + */ +static inline float vmathV4Length_V( VmathVector4 vec ); + +/* + * Normalize a 4-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline VmathVector4 vmathV4Normalize_V( VmathVector4 vec ); + +/* + * Outer product of two 4-D vectors + */ +static inline VmathMatrix4 vmathV4Outer_V( VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Linear interpolation between two 4-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathVector4 vmathV4Lerp_V( float t, VmathVector4 vec0, VmathVector4 vec1 ); + +/* + * Spherical linear interpolation between two 4-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline VmathVector4 vmathV4Slerp_V( float t, VmathVector4 unitVec0, VmathVector4 unitVec1 ); + +/* + * Conditionally select between two 4-D vectors + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathVector4 vmathV4Select_V( VmathVector4 vec0, VmathVector4 vec1, unsigned int select1 ); + +/* + * Store four 4-D vectors as half-floats + */ +static inline void vmathV4StoreHalfFloats_V( VmathVector4 vec0, VmathVector4 vec1, VmathVector4 vec2, VmathVector4 vec3, vec_ushort8 *twoQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV4Print_V( VmathVector4 vec ); + +/* + * Print a 4-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathV4Prints_V( VmathVector4 vec, const char *name ); + +#endif + +/* + * Construct a 3-D point from x, y, and z elements + */ +static inline VmathPoint3 vmathP3MakeFromElems_V( float x, float y, float z ); + +/* + * Copy elements from a 3-D vector into a 3-D point + */ +static inline VmathPoint3 vmathP3MakeFromV3_V( VmathVector3 vec ); + +/* + * Set all elements of a 3-D point to the same scalar value + */ +static inline VmathPoint3 vmathP3MakeFromScalar_V( float scalar ); + +/* + * Set vector float data in a 3-D point + */ +static inline VmathPoint3 vmathP3MakeFrom128_V( vec_float4 vf4 ); + +/* + * Get vector float data from a 3-D point + */ +static inline vec_float4 vmathP3Get128_V( VmathPoint3 pnt ); + +/* + * Set the x element of a 3-D point + */ +static inline void vmathP3SetX_V( VmathPoint3 *result, float x ); + +/* + * Set the y element of a 3-D point + */ +static inline void vmathP3SetY_V( VmathPoint3 *result, float y ); + +/* + * Set the z element of a 3-D point + */ +static inline void vmathP3SetZ_V( VmathPoint3 *result, float z ); + +/* + * Get the x element of a 3-D point + */ +static inline float vmathP3GetX_V( VmathPoint3 pnt ); + +/* + * Get the y element of a 3-D point + */ +static inline float vmathP3GetY_V( VmathPoint3 pnt ); + +/* + * Get the z element of a 3-D point + */ +static inline float vmathP3GetZ_V( VmathPoint3 pnt ); + +/* + * Set an x, y, or z element of a 3-D point by index + */ +static inline void vmathP3SetElem_V( VmathPoint3 *result, int idx, float value ); + +/* + * Get an x, y, or z element of a 3-D point by index + */ +static inline float vmathP3GetElem_V( VmathPoint3 pnt, int idx ); + +/* + * Subtract a 3-D point from another 3-D point + */ +static inline VmathVector3 vmathP3Sub_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Add a 3-D point to a 3-D vector + */ +static inline VmathPoint3 vmathP3AddV3_V( VmathPoint3 pnt, VmathVector3 vec ); + +/* + * Subtract a 3-D vector from a 3-D point + */ +static inline VmathPoint3 vmathP3SubV3_V( VmathPoint3 pnt, VmathVector3 vec ); + +/* + * Multiply two 3-D points per element + */ +static inline VmathPoint3 vmathP3MulPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Divide two 3-D points per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline VmathPoint3 vmathP3DivPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Compute the reciprocal of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline VmathPoint3 vmathP3RecipPerElem_V( VmathPoint3 pnt ); + +/* + * Compute the square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline VmathPoint3 vmathP3SqrtPerElem_V( VmathPoint3 pnt ); + +/* + * Compute the reciprocal square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline VmathPoint3 vmathP3RsqrtPerElem_V( VmathPoint3 pnt ); + +/* + * Compute the absolute value of a 3-D point per element + */ +static inline VmathPoint3 vmathP3AbsPerElem_V( VmathPoint3 pnt ); + +/* + * Copy sign from one 3-D point to another, per element + */ +static inline VmathPoint3 vmathP3CopySignPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Maximum of two 3-D points per element + */ +static inline VmathPoint3 vmathP3MaxPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Minimum of two 3-D points per element + */ +static inline VmathPoint3 vmathP3MinPerElem_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Maximum element of a 3-D point + */ +static inline float vmathP3MaxElem_V( VmathPoint3 pnt ); + +/* + * Minimum element of a 3-D point + */ +static inline float vmathP3MinElem_V( VmathPoint3 pnt ); + +/* + * Compute the sum of all elements of a 3-D point + */ +static inline float vmathP3Sum_V( VmathPoint3 pnt ); + +/* + * Apply uniform scale to a 3-D point + */ +static inline VmathPoint3 vmathP3Scale_V( VmathPoint3 pnt, float scaleVal ); + +/* + * Apply non-uniform scale to a 3-D point + */ +static inline VmathPoint3 vmathP3NonUniformScale_V( VmathPoint3 pnt, VmathVector3 scaleVec ); + +/* + * Scalar projection of a 3-D point on a unit-length 3-D vector + */ +static inline float vmathP3Projection_V( VmathPoint3 pnt, VmathVector3 unitVec ); + +/* + * Compute the square of the distance of a 3-D point from the coordinate-system origin + */ +static inline float vmathP3DistSqrFromOrigin_V( VmathPoint3 pnt ); + +/* + * Compute the distance of a 3-D point from the coordinate-system origin + */ +static inline float vmathP3DistFromOrigin_V( VmathPoint3 pnt ); + +/* + * Compute the square of the distance between two 3-D points + */ +static inline float vmathP3DistSqr_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Compute the distance between two 3-D points + */ +static inline float vmathP3Dist_V( VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Linear interpolation between two 3-D points + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathPoint3 vmathP3Lerp_V( float t, VmathPoint3 pnt0, VmathPoint3 pnt1 ); + +/* + * Conditionally select between two 3-D points + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathPoint3 vmathP3Select_V( VmathPoint3 pnt0, VmathPoint3 pnt1, unsigned int select1 ); + +/* + * Store x, y, and z elements of a 3-D point in the first three words of a quadword. + * The value of the fourth word (the word with the highest address) remains unchanged + */ +static inline void vmathP3StoreXYZ_V( VmathPoint3 pnt, vec_float4 *quad ); + +/* + * Load four three-float 3-D points, stored in three quadwords + */ +static inline void vmathP3LoadXYZArray_V( VmathPoint3 *pnt0, VmathPoint3 *pnt1, VmathPoint3 *pnt2, VmathPoint3 *pnt3, const vec_float4 *threeQuads ); + +/* + * Store four 3-D points in three quadwords + */ +static inline void vmathP3StoreXYZArray_V( VmathPoint3 pnt0, VmathPoint3 pnt1, VmathPoint3 pnt2, VmathPoint3 pnt3, vec_float4 *threeQuads ); + +/* + * Store eight 3-D points as half-floats + */ +static inline void vmathP3StoreHalfFloats_V( VmathPoint3 pnt0, VmathPoint3 pnt1, VmathPoint3 pnt2, VmathPoint3 pnt3, VmathPoint3 pnt4, VmathPoint3 pnt5, VmathPoint3 pnt6, VmathPoint3 pnt7, vec_ushort8 *threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D point + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathP3Print_V( VmathPoint3 pnt ); + +/* + * Print a 3-D point and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathP3Prints_V( VmathPoint3 pnt, const char *name ); + +#endif + +/* + * Construct a quaternion from x, y, z, and w elements + */ +static inline VmathQuat vmathQMakeFromElems_V( float x, float y, float z, float w ); + +/* + * Construct a quaternion from a 3-D vector and a scalar + */ +static inline VmathQuat vmathQMakeFromV3Scalar_V( VmathVector3 xyz, float w ); + +/* + * Copy elements from a 4-D vector into a quaternion + */ +static inline VmathQuat vmathQMakeFromV4_V( VmathVector4 vec ); + +/* + * Convert a rotation matrix to a unit-length quaternion + */ +static inline VmathQuat vmathQMakeFromM3_V( VmathMatrix3 rotMat ); + +/* + * Set all elements of a quaternion to the same scalar value + */ +static inline VmathQuat vmathQMakeFromScalar_V( float scalar ); + +/* + * Set vector float data in a quaternion + */ +static inline VmathQuat vmathQMakeFrom128_V( vec_float4 vf4 ); + +/* + * Get vector float data from a quaternion + */ +static inline vec_float4 vmathQGet128_V( VmathQuat quat ); + +/* + * Set the x, y, and z elements of a quaternion + * NOTE: + * This function does not change the w element. + */ +static inline void vmathQSetXYZ_V( VmathQuat *result, VmathVector3 vec ); + +/* + * Get the x, y, and z elements of a quaternion + */ +static inline VmathVector3 vmathQGetXYZ_V( VmathQuat quat ); + +/* + * Set the x element of a quaternion + */ +static inline void vmathQSetX_V( VmathQuat *result, float x ); + +/* + * Set the y element of a quaternion + */ +static inline void vmathQSetY_V( VmathQuat *result, float y ); + +/* + * Set the z element of a quaternion + */ +static inline void vmathQSetZ_V( VmathQuat *result, float z ); + +/* + * Set the w element of a quaternion + */ +static inline void vmathQSetW_V( VmathQuat *result, float w ); + +/* + * Get the x element of a quaternion + */ +static inline float vmathQGetX_V( VmathQuat quat ); + +/* + * Get the y element of a quaternion + */ +static inline float vmathQGetY_V( VmathQuat quat ); + +/* + * Get the z element of a quaternion + */ +static inline float vmathQGetZ_V( VmathQuat quat ); + +/* + * Get the w element of a quaternion + */ +static inline float vmathQGetW_V( VmathQuat quat ); + +/* + * Set an x, y, z, or w element of a quaternion by index + */ +static inline void vmathQSetElem_V( VmathQuat *result, int idx, float value ); + +/* + * Get an x, y, z, or w element of a quaternion by index + */ +static inline float vmathQGetElem_V( VmathQuat quat, int idx ); + +/* + * Add two quaternions + */ +static inline VmathQuat vmathQAdd_V( VmathQuat quat0, VmathQuat quat1 ); + +/* + * Subtract a quaternion from another quaternion + */ +static inline VmathQuat vmathQSub_V( VmathQuat quat0, VmathQuat quat1 ); + +/* + * Multiply two quaternions + */ +static inline VmathQuat vmathQMul_V( VmathQuat quat0, VmathQuat quat1 ); + +/* + * Multiply a quaternion by a scalar + */ +static inline VmathQuat vmathQScalarMul_V( VmathQuat quat, float scalar ); + +/* + * Divide a quaternion by a scalar + */ +static inline VmathQuat vmathQScalarDiv_V( VmathQuat quat, float scalar ); + +/* + * Negate all elements of a quaternion + */ +static inline VmathQuat vmathQNeg_V( VmathQuat quat ); + +/* + * Construct an identity quaternion + */ +static inline VmathQuat vmathQMakeIdentity_V( ); + +/* + * Construct a quaternion to rotate between two unit-length 3-D vectors + * NOTE: + * The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + */ +static inline VmathQuat vmathQMakeRotationArc_V( VmathVector3 unitVec0, VmathVector3 unitVec1 ); + +/* + * Construct a quaternion to rotate around a unit-length 3-D vector + */ +static inline VmathQuat vmathQMakeRotationAxis_V( float radians, VmathVector3 unitVec ); + +/* + * Construct a quaternion to rotate around the x axis + */ +static inline VmathQuat vmathQMakeRotationX_V( float radians ); + +/* + * Construct a quaternion to rotate around the y axis + */ +static inline VmathQuat vmathQMakeRotationY_V( float radians ); + +/* + * Construct a quaternion to rotate around the z axis + */ +static inline VmathQuat vmathQMakeRotationZ_V( float radians ); + +/* + * Compute the conjugate of a quaternion + */ +static inline VmathQuat vmathQConj_V( VmathQuat quat ); + +/* + * Use a unit-length quaternion to rotate a 3-D vector + */ +static inline VmathVector3 vmathQRotate_V( VmathQuat unitQuat, VmathVector3 vec ); + +/* + * Compute the dot product of two quaternions + */ +static inline float vmathQDot_V( VmathQuat quat0, VmathQuat quat1 ); + +/* + * Compute the norm of a quaternion + */ +static inline float vmathQNorm_V( VmathQuat quat ); + +/* + * Compute the length of a quaternion + */ +static inline float vmathQLength_V( VmathQuat quat ); + +/* + * Normalize a quaternion + * NOTE: + * The result is unpredictable when all elements of quat are at or near zero. + */ +static inline VmathQuat vmathQNormalize_V( VmathQuat quat ); + +/* + * Linear interpolation between two quaternions + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathQuat vmathQLerp_V( float t, VmathQuat quat0, VmathQuat quat1 ); + +/* + * Spherical linear interpolation between two quaternions + * NOTE: + * Interpolates along the shortest path between orientations. + * Does not clamp t between 0 and 1. + */ +static inline VmathQuat vmathQSlerp_V( float t, VmathQuat unitQuat0, VmathQuat unitQuat1 ); + +/* + * Spherical quadrangle interpolation + */ +static inline VmathQuat vmathQSquad_V( float t, VmathQuat unitQuat0, VmathQuat unitQuat1, VmathQuat unitQuat2, VmathQuat unitQuat3 ); + +/* + * Conditionally select between two quaternions + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathQuat vmathQSelect_V( VmathQuat quat0, VmathQuat quat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a quaternion + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathQPrint_V( VmathQuat quat ); + +/* + * Print a quaternion and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathQPrints_V( VmathQuat quat, const char *name ); + +#endif + +/* + * Construct a 3x3 matrix containing the specified columns + */ +static inline VmathMatrix3 vmathM3MakeFromCols_V( VmathVector3 col0, VmathVector3 col1, VmathVector3 col2 ); + +/* + * Construct a 3x3 rotation matrix from a unit-length quaternion + */ +static inline VmathMatrix3 vmathM3MakeFromQ_V( VmathQuat unitQuat ); + +/* + * Set all elements of a 3x3 matrix to the same scalar value + */ +static inline VmathMatrix3 vmathM3MakeFromScalar_V( float scalar ); + +/* + * Set column 0 of a 3x3 matrix + */ +static inline void vmathM3SetCol0_V( VmathMatrix3 *result, VmathVector3 col0 ); + +/* + * Set column 1 of a 3x3 matrix + */ +static inline void vmathM3SetCol1_V( VmathMatrix3 *result, VmathVector3 col1 ); + +/* + * Set column 2 of a 3x3 matrix + */ +static inline void vmathM3SetCol2_V( VmathMatrix3 *result, VmathVector3 col2 ); + +/* + * Get column 0 of a 3x3 matrix + */ +static inline VmathVector3 vmathM3GetCol0_V( VmathMatrix3 mat ); + +/* + * Get column 1 of a 3x3 matrix + */ +static inline VmathVector3 vmathM3GetCol1_V( VmathMatrix3 mat ); + +/* + * Get column 2 of a 3x3 matrix + */ +static inline VmathVector3 vmathM3GetCol2_V( VmathMatrix3 mat ); + +/* + * Set the column of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3SetCol_V( VmathMatrix3 *result, int col, VmathVector3 vec ); + +/* + * Set the row of a 3x3 matrix referred to by the specified index + */ +static inline void vmathM3SetRow_V( VmathMatrix3 *result, int row, VmathVector3 vec ); + +/* + * Get the column of a 3x3 matrix referred to by the specified index + */ +static inline VmathVector3 vmathM3GetCol_V( VmathMatrix3 mat, int col ); + +/* + * Get the row of a 3x3 matrix referred to by the specified index + */ +static inline VmathVector3 vmathM3GetRow_V( VmathMatrix3 mat, int row ); + +/* + * Set the element of a 3x3 matrix referred to by column and row indices + */ +static inline void vmathM3SetElem_V( VmathMatrix3 *result, int col, int row, float val ); + +/* + * Get the element of a 3x3 matrix referred to by column and row indices + */ +static inline float vmathM3GetElem_V( VmathMatrix3 mat, int col, int row ); + +/* + * Add two 3x3 matrices + */ +static inline VmathMatrix3 vmathM3Add_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ); + +/* + * Subtract a 3x3 matrix from another 3x3 matrix + */ +static inline VmathMatrix3 vmathM3Sub_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ); + +/* + * Negate all elements of a 3x3 matrix + */ +static inline VmathMatrix3 vmathM3Neg_V( VmathMatrix3 mat ); + +/* + * Multiply a 3x3 matrix by a scalar + */ +static inline VmathMatrix3 vmathM3ScalarMul_V( VmathMatrix3 mat, float scalar ); + +/* + * Multiply a 3x3 matrix by a 3-D vector + */ +static inline VmathVector3 vmathM3MulV3_V( VmathMatrix3 mat, VmathVector3 vec ); + +/* + * Multiply two 3x3 matrices + */ +static inline VmathMatrix3 vmathM3Mul_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ); + +/* + * Construct an identity 3x3 matrix + */ +static inline VmathMatrix3 vmathM3MakeIdentity_V( ); + +/* + * Construct a 3x3 matrix to rotate around the x axis + */ +static inline VmathMatrix3 vmathM3MakeRotationX_V( float radians ); + +/* + * Construct a 3x3 matrix to rotate around the y axis + */ +static inline VmathMatrix3 vmathM3MakeRotationY_V( float radians ); + +/* + * Construct a 3x3 matrix to rotate around the z axis + */ +static inline VmathMatrix3 vmathM3MakeRotationZ_V( float radians ); + +/* + * Construct a 3x3 matrix to rotate around the x, y, and z axes + */ +static inline VmathMatrix3 vmathM3MakeRotationZYX_V( VmathVector3 radiansXYZ ); + +/* + * Construct a 3x3 matrix to rotate around a unit-length 3-D vector + */ +static inline VmathMatrix3 vmathM3MakeRotationAxis_V( float radians, VmathVector3 unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline VmathMatrix3 vmathM3MakeRotationQ_V( VmathQuat unitQuat ); + +/* + * Construct a 3x3 matrix to perform scaling + */ +static inline VmathMatrix3 vmathM3MakeScale_V( VmathVector3 scaleVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathMatrix3 vmathM3AppendScale_V( VmathMatrix3 mat, VmathVector3 scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathMatrix3 vmathM3PrependScale_V( VmathVector3 scaleVec, VmathMatrix3 mat ); + +/* + * Multiply two 3x3 matrices per element + */ +static inline VmathMatrix3 vmathM3MulPerElem_V( VmathMatrix3 mat0, VmathMatrix3 mat1 ); + +/* + * Compute the absolute value of a 3x3 matrix per element + */ +static inline VmathMatrix3 vmathM3AbsPerElem_V( VmathMatrix3 mat ); + +/* + * Transpose of a 3x3 matrix + */ +static inline VmathMatrix3 vmathM3Transpose_V( VmathMatrix3 mat ); + +/* + * Compute the inverse of a 3x3 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline VmathMatrix3 vmathM3Inverse_V( VmathMatrix3 mat ); + +/* + * Determinant of a 3x3 matrix + */ +static inline float vmathM3Determinant_V( VmathMatrix3 mat ); + +/* + * Conditionally select between two 3x3 matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathMatrix3 vmathM3Select_V( VmathMatrix3 mat0, VmathMatrix3 mat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x3 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM3Print_V( VmathMatrix3 mat ); + +/* + * Print a 3x3 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM3Prints_V( VmathMatrix3 mat, const char *name ); + +#endif + +/* + * Construct a 4x4 matrix containing the specified columns + */ +static inline VmathMatrix4 vmathM4MakeFromCols_V( VmathVector4 col0, VmathVector4 col1, VmathVector4 col2, VmathVector4 col3 ); + +/* + * Construct a 4x4 matrix from a 3x4 transformation matrix + */ +static inline VmathMatrix4 vmathM4MakeFromT3_V( VmathTransform3 mat ); + +/* + * Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + */ +static inline VmathMatrix4 vmathM4MakeFromM3V3_V( VmathMatrix3 mat, VmathVector3 translateVec ); + +/* + * Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + */ +static inline VmathMatrix4 vmathM4MakeFromQV3_V( VmathQuat unitQuat, VmathVector3 translateVec ); + +/* + * Set all elements of a 4x4 matrix to the same scalar value + */ +static inline VmathMatrix4 vmathM4MakeFromScalar_V( float scalar ); + +/* + * Set the upper-left 3x3 submatrix + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathM4SetUpper3x3_V( VmathMatrix4 *result, VmathMatrix3 mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 4x4 matrix + */ +static inline VmathMatrix3 vmathM4GetUpper3x3_V( VmathMatrix4 mat ); + +/* + * Set translation component + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathM4SetTranslation_V( VmathMatrix4 *result, VmathVector3 translateVec ); + +/* + * Get the translation component of a 4x4 matrix + */ +static inline VmathVector3 vmathM4GetTranslation_V( VmathMatrix4 mat ); + +/* + * Set column 0 of a 4x4 matrix + */ +static inline void vmathM4SetCol0_V( VmathMatrix4 *result, VmathVector4 col0 ); + +/* + * Set column 1 of a 4x4 matrix + */ +static inline void vmathM4SetCol1_V( VmathMatrix4 *result, VmathVector4 col1 ); + +/* + * Set column 2 of a 4x4 matrix + */ +static inline void vmathM4SetCol2_V( VmathMatrix4 *result, VmathVector4 col2 ); + +/* + * Set column 3 of a 4x4 matrix + */ +static inline void vmathM4SetCol3_V( VmathMatrix4 *result, VmathVector4 col3 ); + +/* + * Get column 0 of a 4x4 matrix + */ +static inline VmathVector4 vmathM4GetCol0_V( VmathMatrix4 mat ); + +/* + * Get column 1 of a 4x4 matrix + */ +static inline VmathVector4 vmathM4GetCol1_V( VmathMatrix4 mat ); + +/* + * Get column 2 of a 4x4 matrix + */ +static inline VmathVector4 vmathM4GetCol2_V( VmathMatrix4 mat ); + +/* + * Get column 3 of a 4x4 matrix + */ +static inline VmathVector4 vmathM4GetCol3_V( VmathMatrix4 mat ); + +/* + * Set the column of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4SetCol_V( VmathMatrix4 *result, int col, VmathVector4 vec ); + +/* + * Set the row of a 4x4 matrix referred to by the specified index + */ +static inline void vmathM4SetRow_V( VmathMatrix4 *result, int row, VmathVector4 vec ); + +/* + * Get the column of a 4x4 matrix referred to by the specified index + */ +static inline VmathVector4 vmathM4GetCol_V( VmathMatrix4 mat, int col ); + +/* + * Get the row of a 4x4 matrix referred to by the specified index + */ +static inline VmathVector4 vmathM4GetRow_V( VmathMatrix4 mat, int row ); + +/* + * Set the element of a 4x4 matrix referred to by column and row indices + */ +static inline void vmathM4SetElem_V( VmathMatrix4 *result, int col, int row, float val ); + +/* + * Get the element of a 4x4 matrix referred to by column and row indices + */ +static inline float vmathM4GetElem_V( VmathMatrix4 mat, int col, int row ); + +/* + * Add two 4x4 matrices + */ +static inline VmathMatrix4 vmathM4Add_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ); + +/* + * Subtract a 4x4 matrix from another 4x4 matrix + */ +static inline VmathMatrix4 vmathM4Sub_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ); + +/* + * Negate all elements of a 4x4 matrix + */ +static inline VmathMatrix4 vmathM4Neg_V( VmathMatrix4 mat ); + +/* + * Multiply a 4x4 matrix by a scalar + */ +static inline VmathMatrix4 vmathM4ScalarMul_V( VmathMatrix4 mat, float scalar ); + +/* + * Multiply a 4x4 matrix by a 4-D vector + */ +static inline VmathVector4 vmathM4MulV4_V( VmathMatrix4 mat, VmathVector4 vec ); + +/* + * Multiply a 4x4 matrix by a 3-D vector + */ +static inline VmathVector4 vmathM4MulV3_V( VmathMatrix4 mat, VmathVector3 vec ); + +/* + * Multiply a 4x4 matrix by a 3-D point + */ +static inline VmathVector4 vmathM4MulP3_V( VmathMatrix4 mat, VmathPoint3 pnt ); + +/* + * Multiply two 4x4 matrices + */ +static inline VmathMatrix4 vmathM4Mul_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ); + +/* + * Multiply a 4x4 matrix by a 3x4 transformation matrix + */ +static inline VmathMatrix4 vmathM4MulT3_V( VmathMatrix4 mat, VmathTransform3 tfrm ); + +/* + * Construct an identity 4x4 matrix + */ +static inline VmathMatrix4 vmathM4MakeIdentity_V( ); + +/* + * Construct a 4x4 matrix to rotate around the x axis + */ +static inline VmathMatrix4 vmathM4MakeRotationX_V( float radians ); + +/* + * Construct a 4x4 matrix to rotate around the y axis + */ +static inline VmathMatrix4 vmathM4MakeRotationY_V( float radians ); + +/* + * Construct a 4x4 matrix to rotate around the z axis + */ +static inline VmathMatrix4 vmathM4MakeRotationZ_V( float radians ); + +/* + * Construct a 4x4 matrix to rotate around the x, y, and z axes + */ +static inline VmathMatrix4 vmathM4MakeRotationZYX_V( VmathVector3 radiansXYZ ); + +/* + * Construct a 4x4 matrix to rotate around a unit-length 3-D vector + */ +static inline VmathMatrix4 vmathM4MakeRotationAxis_V( float radians, VmathVector3 unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline VmathMatrix4 vmathM4MakeRotationQ_V( VmathQuat unitQuat ); + +/* + * Construct a 4x4 matrix to perform scaling + */ +static inline VmathMatrix4 vmathM4MakeScale_V( VmathVector3 scaleVec ); + +/* + * Construct a 4x4 matrix to perform translation + */ +static inline VmathMatrix4 vmathM4MakeTranslation_V( VmathVector3 translateVec ); + +/* + * Construct viewing matrix based on eye position, position looked at, and up direction + */ +static inline VmathMatrix4 vmathM4MakeLookAt_V( VmathPoint3 eyePos, VmathPoint3 lookAtPos, VmathVector3 upVec ); + +/* + * Construct a perspective projection matrix + */ +static inline VmathMatrix4 vmathM4MakePerspective_V( float fovyRadians, float aspect, float zNear, float zFar ); + +/* + * Construct a perspective projection matrix based on frustum + */ +static inline VmathMatrix4 vmathM4MakeFrustum_V( float left, float right, float bottom, float top, float zNear, float zFar ); + +/* + * Construct an orthographic projection matrix + */ +static inline VmathMatrix4 vmathM4MakeOrthographic_V( float left, float right, float bottom, float top, float zNear, float zFar ); + +/* + * Append (post-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathMatrix4 vmathM4AppendScale_V( VmathMatrix4 mat, VmathVector3 scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathMatrix4 vmathM4PrependScale_V( VmathVector3 scaleVec, VmathMatrix4 mat ); + +/* + * Multiply two 4x4 matrices per element + */ +static inline VmathMatrix4 vmathM4MulPerElem_V( VmathMatrix4 mat0, VmathMatrix4 mat1 ); + +/* + * Compute the absolute value of a 4x4 matrix per element + */ +static inline VmathMatrix4 vmathM4AbsPerElem_V( VmathMatrix4 mat ); + +/* + * Transpose of a 4x4 matrix + */ +static inline VmathMatrix4 vmathM4Transpose_V( VmathMatrix4 mat ); + +/* + * Compute the inverse of a 4x4 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline VmathMatrix4 vmathM4Inverse_V( VmathMatrix4 mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline VmathMatrix4 vmathM4AffineInverse_V( VmathMatrix4 mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. + */ +static inline VmathMatrix4 vmathM4OrthoInverse_V( VmathMatrix4 mat ); + +/* + * Determinant of a 4x4 matrix + */ +static inline float vmathM4Determinant_V( VmathMatrix4 mat ); + +/* + * Conditionally select between two 4x4 matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathMatrix4 vmathM4Select_V( VmathMatrix4 mat0, VmathMatrix4 mat1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4x4 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM4Print_V( VmathMatrix4 mat ); + +/* + * Print a 4x4 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathM4Prints_V( VmathMatrix4 mat, const char *name ); + +#endif + +/* + * Construct a 3x4 transformation matrix containing the specified columns + */ +static inline VmathTransform3 vmathT3MakeFromCols_V( VmathVector3 col0, VmathVector3 col1, VmathVector3 col2, VmathVector3 col3 ); + +/* + * Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + */ +static inline VmathTransform3 vmathT3MakeFromM3V3_V( VmathMatrix3 tfrm, VmathVector3 translateVec ); + +/* + * Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + */ +static inline VmathTransform3 vmathT3MakeFromQV3_V( VmathQuat unitQuat, VmathVector3 translateVec ); + +/* + * Set all elements of a 3x4 transformation matrix to the same scalar value + */ +static inline VmathTransform3 vmathT3MakeFromScalar_V( float scalar ); + +/* + * Set the upper-left 3x3 submatrix + */ +static inline void vmathT3SetUpper3x3_V( VmathTransform3 *result, VmathMatrix3 mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + */ +static inline VmathMatrix3 vmathT3GetUpper3x3_V( VmathTransform3 tfrm ); + +/* + * Set translation component + */ +static inline void vmathT3SetTranslation_V( VmathTransform3 *result, VmathVector3 translateVec ); + +/* + * Get the translation component of a 3x4 transformation matrix + */ +static inline VmathVector3 vmathT3GetTranslation_V( VmathTransform3 tfrm ); + +/* + * Set column 0 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol0_V( VmathTransform3 *result, VmathVector3 col0 ); + +/* + * Set column 1 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol1_V( VmathTransform3 *result, VmathVector3 col1 ); + +/* + * Set column 2 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol2_V( VmathTransform3 *result, VmathVector3 col2 ); + +/* + * Set column 3 of a 3x4 transformation matrix + */ +static inline void vmathT3SetCol3_V( VmathTransform3 *result, VmathVector3 col3 ); + +/* + * Get column 0 of a 3x4 transformation matrix + */ +static inline VmathVector3 vmathT3GetCol0_V( VmathTransform3 tfrm ); + +/* + * Get column 1 of a 3x4 transformation matrix + */ +static inline VmathVector3 vmathT3GetCol1_V( VmathTransform3 tfrm ); + +/* + * Get column 2 of a 3x4 transformation matrix + */ +static inline VmathVector3 vmathT3GetCol2_V( VmathTransform3 tfrm ); + +/* + * Get column 3 of a 3x4 transformation matrix + */ +static inline VmathVector3 vmathT3GetCol3_V( VmathTransform3 tfrm ); + +/* + * Set the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3SetCol_V( VmathTransform3 *result, int col, VmathVector3 vec ); + +/* + * Set the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathT3SetRow_V( VmathTransform3 *result, int row, VmathVector4 vec ); + +/* + * Get the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline VmathVector3 vmathT3GetCol_V( VmathTransform3 tfrm, int col ); + +/* + * Get the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline VmathVector4 vmathT3GetRow_V( VmathTransform3 tfrm, int row ); + +/* + * Set the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline void vmathT3SetElem_V( VmathTransform3 *result, int col, int row, float val ); + +/* + * Get the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline float vmathT3GetElem_V( VmathTransform3 tfrm, int col, int row ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D vector + */ +static inline VmathVector3 vmathT3MulV3_V( VmathTransform3 tfrm, VmathVector3 vec ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D point + */ +static inline VmathPoint3 vmathT3MulP3_V( VmathTransform3 tfrm, VmathPoint3 pnt ); + +/* + * Multiply two 3x4 transformation matrices + */ +static inline VmathTransform3 vmathT3Mul_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1 ); + +/* + * Construct an identity 3x4 transformation matrix + */ +static inline VmathTransform3 vmathT3MakeIdentity_V( ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x axis + */ +static inline VmathTransform3 vmathT3MakeRotationX_V( float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the y axis + */ +static inline VmathTransform3 vmathT3MakeRotationY_V( float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the z axis + */ +static inline VmathTransform3 vmathT3MakeRotationZ_V( float radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + */ +static inline VmathTransform3 vmathT3MakeRotationZYX_V( VmathVector3 radiansXYZ ); + +/* + * Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + */ +static inline VmathTransform3 vmathT3MakeRotationAxis_V( float radians, VmathVector3 unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline VmathTransform3 vmathT3MakeRotationQ_V( VmathQuat unitQuat ); + +/* + * Construct a 3x4 transformation matrix to perform scaling + */ +static inline VmathTransform3 vmathT3MakeScale_V( VmathVector3 scaleVec ); + +/* + * Construct a 3x4 transformation matrix to perform translation + */ +static inline VmathTransform3 vmathT3MakeTranslation_V( VmathVector3 translateVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathTransform3 vmathT3AppendScale_V( VmathTransform3 tfrm, VmathVector3 scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathTransform3 vmathT3PrependScale_V( VmathVector3 scaleVec, VmathTransform3 tfrm ); + +/* + * Multiply two 3x4 transformation matrices per element + */ +static inline VmathTransform3 vmathT3MulPerElem_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1 ); + +/* + * Compute the absolute value of a 3x4 transformation matrix per element + */ +static inline VmathTransform3 vmathT3AbsPerElem_V( VmathTransform3 tfrm ); + +/* + * Inverse of a 3x4 transformation matrix + * NOTE: + * Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. + */ +static inline VmathTransform3 vmathT3Inverse_V( VmathTransform3 tfrm ); + +/* + * Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. + */ +static inline VmathTransform3 vmathT3OrthoInverse_V( VmathTransform3 tfrm ); + +/* + * Conditionally select between two 3x4 transformation matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathTransform3 vmathT3Select_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1, unsigned int select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x4 transformation matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathT3Print_V( VmathTransform3 tfrm ); + +/* + * Print a 3x4 transformation matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathT3Prints_V( VmathTransform3 tfrm, const char *name ); + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#include "vectormath_aos.h" +#include "vec_aos_v.h" +#include "quat_aos_v.h" +#include "mat_aos_v.h" + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/c/vectormath_soa.h b/Extras/vectormathlibrary/include/vectormath/spu/c/vectormath_soa.h new file mode 100644 index 0000000..6aa9b6a --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/c/vectormath_soa.h @@ -0,0 +1,2012 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_SOA_C_SPU_H +#define _VECTORMATH_SOA_C_SPU_H + +#include +#include +#include "vectormath_aos.h" + +#ifdef _VECTORMATH_DEBUG +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef _VECTORMATH_SOA_C_TYPES_H +#define _VECTORMATH_SOA_C_TYPES_H + +/* A set of four 3-D vectors in structure-of-arrays format + */ +typedef struct _VmathSoaVector3 +{ + vec_float4 x; + vec_float4 y; + vec_float4 z; +} VmathSoaVector3; + +/* A set of four 4-D vectors in structure-of-arrays format + */ +typedef struct _VmathSoaVector4 +{ + vec_float4 x; + vec_float4 y; + vec_float4 z; + vec_float4 w; +} VmathSoaVector4; + +/* A set of four 3-D points in structure-of-arrays format + */ +typedef struct _VmathSoaPoint3 +{ + vec_float4 x; + vec_float4 y; + vec_float4 z; +} VmathSoaPoint3; + +/* A set of four quaternions in structure-of-arrays format + */ +typedef struct _VmathSoaQuat +{ + vec_float4 x; + vec_float4 y; + vec_float4 z; + vec_float4 w; +} VmathSoaQuat; + +/* A set of four 3x3 matrices in structure-of-arrays format + */ +typedef struct _VmathSoaMatrix3 +{ + VmathSoaVector3 col0; + VmathSoaVector3 col1; + VmathSoaVector3 col2; +} VmathSoaMatrix3; + +/* A set of four 4x4 matrices in structure-of-arrays format + */ +typedef struct _VmathSoaMatrix4 +{ + VmathSoaVector4 col0; + VmathSoaVector4 col1; + VmathSoaVector4 col2; + VmathSoaVector4 col3; +} VmathSoaMatrix4; + +/* A set of four 3x4 transformation matrices in structure-of-arrays format + */ +typedef struct _VmathSoaTransform3 +{ + VmathSoaVector3 col0; + VmathSoaVector3 col1; + VmathSoaVector3 col2; + VmathSoaVector3 col3; +} VmathSoaTransform3; + +#endif + +/* + * Copy a 3-D vector + */ +static inline void vmathSoaV3Copy( VmathSoaVector3 *result, const VmathSoaVector3 *vec ); + +/* + * Construct a 3-D vector from x, y, and z elements + */ +static inline void vmathSoaV3MakeFromElems( VmathSoaVector3 *result, vec_float4 x, vec_float4 y, vec_float4 z ); + +/* + * Copy elements from a 3-D point into a 3-D vector + */ +static inline void vmathSoaV3MakeFromP3( VmathSoaVector3 *result, const VmathSoaPoint3 *pnt ); + +/* + * Set all elements of a 3-D vector to the same scalar value + */ +static inline void vmathSoaV3MakeFromScalar( VmathSoaVector3 *result, vec_float4 scalar ); + +/* + * Replicate an AoS 3-D vector + */ +static inline void vmathSoaV3MakeFromAos( VmathSoaVector3 *result, const VmathVector3 *vec ); + +/* + * Insert four AoS 3-D vectors + */ +static inline void vmathSoaV3MakeFrom4Aos( VmathSoaVector3 *result, const VmathVector3 *vec0, const VmathVector3 *vec1, const VmathVector3 *vec2, const VmathVector3 *vec3 ); + +/* + * Extract four AoS 3-D vectors + */ +static inline void vmathSoaV3Get4Aos( const VmathSoaVector3 *vec, VmathVector3 *result0, VmathVector3 *result1, VmathVector3 *result2, VmathVector3 *result3 ); + +/* + * Set the x element of a 3-D vector + */ +static inline void vmathSoaV3SetX( VmathSoaVector3 *result, vec_float4 x ); + +/* + * Set the y element of a 3-D vector + */ +static inline void vmathSoaV3SetY( VmathSoaVector3 *result, vec_float4 y ); + +/* + * Set the z element of a 3-D vector + */ +static inline void vmathSoaV3SetZ( VmathSoaVector3 *result, vec_float4 z ); + +/* + * Get the x element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3GetX( const VmathSoaVector3 *vec ); + +/* + * Get the y element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3GetY( const VmathSoaVector3 *vec ); + +/* + * Get the z element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3GetZ( const VmathSoaVector3 *vec ); + +/* + * Set an x, y, or z element of a 3-D vector by index + */ +static inline void vmathSoaV3SetElem( VmathSoaVector3 *result, int idx, vec_float4 value ); + +/* + * Get an x, y, or z element of a 3-D vector by index + */ +static inline vec_float4 vmathSoaV3GetElem( const VmathSoaVector3 *vec, int idx ); + +/* + * Add two 3-D vectors + */ +static inline void vmathSoaV3Add( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Subtract a 3-D vector from another 3-D vector + */ +static inline void vmathSoaV3Sub( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Add a 3-D vector to a 3-D point + */ +static inline void vmathSoaV3AddP3( VmathSoaPoint3 *result, const VmathSoaVector3 *vec, const VmathSoaPoint3 *pnt ); + +/* + * Multiply a 3-D vector by a scalar + */ +static inline void vmathSoaV3ScalarMul( VmathSoaVector3 *result, const VmathSoaVector3 *vec, vec_float4 scalar ); + +/* + * Divide a 3-D vector by a scalar + */ +static inline void vmathSoaV3ScalarDiv( VmathSoaVector3 *result, const VmathSoaVector3 *vec, vec_float4 scalar ); + +/* + * Negate all elements of a 3-D vector + */ +static inline void vmathSoaV3Neg( VmathSoaVector3 *result, const VmathSoaVector3 *vec ); + +/* + * Construct x axis + */ +static inline void vmathSoaV3MakeXAxis( VmathSoaVector3 *result ); + +/* + * Construct y axis + */ +static inline void vmathSoaV3MakeYAxis( VmathSoaVector3 *result ); + +/* + * Construct z axis + */ +static inline void vmathSoaV3MakeZAxis( VmathSoaVector3 *result ); + +/* + * Multiply two 3-D vectors per element + */ +static inline void vmathSoaV3MulPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Divide two 3-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline void vmathSoaV3DivPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Compute the reciprocal of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline void vmathSoaV3RecipPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec ); + +/* + * Compute the square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline void vmathSoaV3SqrtPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec ); + +/* + * Compute the reciprocal square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline void vmathSoaV3RsqrtPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec ); + +/* + * Compute the absolute value of a 3-D vector per element + */ +static inline void vmathSoaV3AbsPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec ); + +/* + * Copy sign from one 3-D vector to another, per element + */ +static inline void vmathSoaV3CopySignPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Maximum of two 3-D vectors per element + */ +static inline void vmathSoaV3MaxPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Minimum of two 3-D vectors per element + */ +static inline void vmathSoaV3MinPerElem( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Maximum element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3MaxElem( const VmathSoaVector3 *vec ); + +/* + * Minimum element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3MinElem( const VmathSoaVector3 *vec ); + +/* + * Compute the sum of all elements of a 3-D vector + */ +static inline vec_float4 vmathSoaV3Sum( const VmathSoaVector3 *vec ); + +/* + * Compute the dot product of two 3-D vectors + */ +static inline vec_float4 vmathSoaV3Dot( const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Compute the square of the length of a 3-D vector + */ +static inline vec_float4 vmathSoaV3LengthSqr( const VmathSoaVector3 *vec ); + +/* + * Compute the length of a 3-D vector + */ +static inline vec_float4 vmathSoaV3Length( const VmathSoaVector3 *vec ); + +/* + * Normalize a 3-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline void vmathSoaV3Normalize( VmathSoaVector3 *result, const VmathSoaVector3 *vec ); + +/* + * Compute cross product of two 3-D vectors + */ +static inline void vmathSoaV3Cross( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Outer product of two 3-D vectors + */ +static inline void vmathSoaV3Outer( VmathSoaMatrix3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Pre-multiply a row vector by a 3x3 matrix + */ +static inline void vmathSoaV3RowMul( VmathSoaVector3 *result, const VmathSoaVector3 *vec, const VmathSoaMatrix3 *mat ); + +/* + * Cross-product matrix of a 3-D vector + */ +static inline void vmathSoaV3CrossMatrix( VmathSoaMatrix3 *result, const VmathSoaVector3 *vec ); + +/* + * Create cross-product matrix and multiply + * NOTE: + * Faster than separately creating a cross-product matrix and multiplying. + */ +static inline void vmathSoaV3CrossMatrixMul( VmathSoaMatrix3 *result, const VmathSoaVector3 *vec, const VmathSoaMatrix3 *mat ); + +/* + * Linear interpolation between two 3-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathSoaV3Lerp( VmathSoaVector3 *result, vec_float4 t, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1 ); + +/* + * Spherical linear interpolation between two 3-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline void vmathSoaV3Slerp( VmathSoaVector3 *result, vec_float4 t, const VmathSoaVector3 *unitVec0, const VmathSoaVector3 *unitVec1 ); + +/* + * Conditionally select between two 3-D vectors + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathSoaV3Select( VmathSoaVector3 *result, const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1, vec_uint4 select1 ); + +/* + * Load four three-float 3-D vectors, stored in three quadwords + */ +static inline void vmathSoaV3LoadXYZArray( VmathSoaVector3 *vec, const vec_float4 *threeQuads ); + +/* + * Store four slots of an SoA 3-D vector in three quadwords + */ +static inline void vmathSoaV3StoreXYZArray( const VmathSoaVector3 *vec, vec_float4 *threeQuads ); + +/* + * Store eight slots of two SoA 3-D vectors as half-floats + */ +static inline void vmathSoaV3StoreHalfFloats( const VmathSoaVector3 *vec0, const VmathSoaVector3 *vec1, vec_ushort8 *threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaV3Print( const VmathSoaVector3 *vec ); + +/* + * Print a 3-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaV3Prints( const VmathSoaVector3 *vec, const char *name ); + +#endif + +/* + * Copy a 4-D vector + */ +static inline void vmathSoaV4Copy( VmathSoaVector4 *result, const VmathSoaVector4 *vec ); + +/* + * Construct a 4-D vector from x, y, z, and w elements + */ +static inline void vmathSoaV4MakeFromElems( VmathSoaVector4 *result, vec_float4 x, vec_float4 y, vec_float4 z, vec_float4 w ); + +/* + * Construct a 4-D vector from a 3-D vector and a scalar + */ +static inline void vmathSoaV4MakeFromV3Scalar( VmathSoaVector4 *result, const VmathSoaVector3 *xyz, vec_float4 w ); + +/* + * Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + */ +static inline void vmathSoaV4MakeFromV3( VmathSoaVector4 *result, const VmathSoaVector3 *vec ); + +/* + * Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + */ +static inline void vmathSoaV4MakeFromP3( VmathSoaVector4 *result, const VmathSoaPoint3 *pnt ); + +/* + * Copy elements from a quaternion into a 4-D vector + */ +static inline void vmathSoaV4MakeFromQ( VmathSoaVector4 *result, const VmathSoaQuat *quat ); + +/* + * Set all elements of a 4-D vector to the same scalar value + */ +static inline void vmathSoaV4MakeFromScalar( VmathSoaVector4 *result, vec_float4 scalar ); + +/* + * Replicate an AoS 4-D vector + */ +static inline void vmathSoaV4MakeFromAos( VmathSoaVector4 *result, const VmathVector4 *vec ); + +/* + * Insert four AoS 4-D vectors + */ +static inline void vmathSoaV4MakeFrom4Aos( VmathSoaVector4 *result, const VmathVector4 *vec0, const VmathVector4 *vec1, const VmathVector4 *vec2, const VmathVector4 *vec3 ); + +/* + * Extract four AoS 4-D vectors + */ +static inline void vmathSoaV4Get4Aos( const VmathSoaVector4 *vec, VmathVector4 *result0, VmathVector4 *result1, VmathVector4 *result2, VmathVector4 *result3 ); + +/* + * Set the x, y, and z elements of a 4-D vector + * NOTE: + * This function does not change the w element. + */ +static inline void vmathSoaV4SetXYZ( VmathSoaVector4 *result, const VmathSoaVector3 *vec ); + +/* + * Get the x, y, and z elements of a 4-D vector + */ +static inline void vmathSoaV4GetXYZ( VmathSoaVector3 *result, const VmathSoaVector4 *vec ); + +/* + * Set the x element of a 4-D vector + */ +static inline void vmathSoaV4SetX( VmathSoaVector4 *result, vec_float4 x ); + +/* + * Set the y element of a 4-D vector + */ +static inline void vmathSoaV4SetY( VmathSoaVector4 *result, vec_float4 y ); + +/* + * Set the z element of a 4-D vector + */ +static inline void vmathSoaV4SetZ( VmathSoaVector4 *result, vec_float4 z ); + +/* + * Set the w element of a 4-D vector + */ +static inline void vmathSoaV4SetW( VmathSoaVector4 *result, vec_float4 w ); + +/* + * Get the x element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4GetX( const VmathSoaVector4 *vec ); + +/* + * Get the y element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4GetY( const VmathSoaVector4 *vec ); + +/* + * Get the z element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4GetZ( const VmathSoaVector4 *vec ); + +/* + * Get the w element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4GetW( const VmathSoaVector4 *vec ); + +/* + * Set an x, y, z, or w element of a 4-D vector by index + */ +static inline void vmathSoaV4SetElem( VmathSoaVector4 *result, int idx, vec_float4 value ); + +/* + * Get an x, y, z, or w element of a 4-D vector by index + */ +static inline vec_float4 vmathSoaV4GetElem( const VmathSoaVector4 *vec, int idx ); + +/* + * Add two 4-D vectors + */ +static inline void vmathSoaV4Add( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Subtract a 4-D vector from another 4-D vector + */ +static inline void vmathSoaV4Sub( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Multiply a 4-D vector by a scalar + */ +static inline void vmathSoaV4ScalarMul( VmathSoaVector4 *result, const VmathSoaVector4 *vec, vec_float4 scalar ); + +/* + * Divide a 4-D vector by a scalar + */ +static inline void vmathSoaV4ScalarDiv( VmathSoaVector4 *result, const VmathSoaVector4 *vec, vec_float4 scalar ); + +/* + * Negate all elements of a 4-D vector + */ +static inline void vmathSoaV4Neg( VmathSoaVector4 *result, const VmathSoaVector4 *vec ); + +/* + * Construct x axis + */ +static inline void vmathSoaV4MakeXAxis( VmathSoaVector4 *result ); + +/* + * Construct y axis + */ +static inline void vmathSoaV4MakeYAxis( VmathSoaVector4 *result ); + +/* + * Construct z axis + */ +static inline void vmathSoaV4MakeZAxis( VmathSoaVector4 *result ); + +/* + * Construct w axis + */ +static inline void vmathSoaV4MakeWAxis( VmathSoaVector4 *result ); + +/* + * Multiply two 4-D vectors per element + */ +static inline void vmathSoaV4MulPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Divide two 4-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline void vmathSoaV4DivPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Compute the reciprocal of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline void vmathSoaV4RecipPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec ); + +/* + * Compute the square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline void vmathSoaV4SqrtPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec ); + +/* + * Compute the reciprocal square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline void vmathSoaV4RsqrtPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec ); + +/* + * Compute the absolute value of a 4-D vector per element + */ +static inline void vmathSoaV4AbsPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec ); + +/* + * Copy sign from one 4-D vector to another, per element + */ +static inline void vmathSoaV4CopySignPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Maximum of two 4-D vectors per element + */ +static inline void vmathSoaV4MaxPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Minimum of two 4-D vectors per element + */ +static inline void vmathSoaV4MinPerElem( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Maximum element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4MaxElem( const VmathSoaVector4 *vec ); + +/* + * Minimum element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4MinElem( const VmathSoaVector4 *vec ); + +/* + * Compute the sum of all elements of a 4-D vector + */ +static inline vec_float4 vmathSoaV4Sum( const VmathSoaVector4 *vec ); + +/* + * Compute the dot product of two 4-D vectors + */ +static inline vec_float4 vmathSoaV4Dot( const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Compute the square of the length of a 4-D vector + */ +static inline vec_float4 vmathSoaV4LengthSqr( const VmathSoaVector4 *vec ); + +/* + * Compute the length of a 4-D vector + */ +static inline vec_float4 vmathSoaV4Length( const VmathSoaVector4 *vec ); + +/* + * Normalize a 4-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline void vmathSoaV4Normalize( VmathSoaVector4 *result, const VmathSoaVector4 *vec ); + +/* + * Outer product of two 4-D vectors + */ +static inline void vmathSoaV4Outer( VmathSoaMatrix4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Linear interpolation between two 4-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathSoaV4Lerp( VmathSoaVector4 *result, vec_float4 t, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1 ); + +/* + * Spherical linear interpolation between two 4-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline void vmathSoaV4Slerp( VmathSoaVector4 *result, vec_float4 t, const VmathSoaVector4 *unitVec0, const VmathSoaVector4 *unitVec1 ); + +/* + * Conditionally select between two 4-D vectors + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathSoaV4Select( VmathSoaVector4 *result, const VmathSoaVector4 *vec0, const VmathSoaVector4 *vec1, vec_uint4 select1 ); + +/* + * Store four slots of an SoA 4-D vector as half-floats + */ +static inline void vmathSoaV4StoreHalfFloats( const VmathSoaVector4 *vec, vec_ushort8 *twoQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaV4Print( const VmathSoaVector4 *vec ); + +/* + * Print a 4-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaV4Prints( const VmathSoaVector4 *vec, const char *name ); + +#endif + +/* + * Copy a 3-D point + */ +static inline void vmathSoaP3Copy( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ); + +/* + * Construct a 3-D point from x, y, and z elements + */ +static inline void vmathSoaP3MakeFromElems( VmathSoaPoint3 *result, vec_float4 x, vec_float4 y, vec_float4 z ); + +/* + * Copy elements from a 3-D vector into a 3-D point + */ +static inline void vmathSoaP3MakeFromV3( VmathSoaPoint3 *result, const VmathSoaVector3 *vec ); + +/* + * Set all elements of a 3-D point to the same scalar value + */ +static inline void vmathSoaP3MakeFromScalar( VmathSoaPoint3 *result, vec_float4 scalar ); + +/* + * Replicate an AoS 3-D point + */ +static inline void vmathSoaP3MakeFromAos( VmathSoaPoint3 *result, const VmathPoint3 *pnt ); + +/* + * Insert four AoS 3-D points + */ +static inline void vmathSoaP3MakeFrom4Aos( VmathSoaPoint3 *result, const VmathPoint3 *pnt0, const VmathPoint3 *pnt1, const VmathPoint3 *pnt2, const VmathPoint3 *pnt3 ); + +/* + * Extract four AoS 3-D points + */ +static inline void vmathSoaP3Get4Aos( const VmathSoaPoint3 *pnt, VmathPoint3 *result0, VmathPoint3 *result1, VmathPoint3 *result2, VmathPoint3 *result3 ); + +/* + * Set the x element of a 3-D point + */ +static inline void vmathSoaP3SetX( VmathSoaPoint3 *result, vec_float4 x ); + +/* + * Set the y element of a 3-D point + */ +static inline void vmathSoaP3SetY( VmathSoaPoint3 *result, vec_float4 y ); + +/* + * Set the z element of a 3-D point + */ +static inline void vmathSoaP3SetZ( VmathSoaPoint3 *result, vec_float4 z ); + +/* + * Get the x element of a 3-D point + */ +static inline vec_float4 vmathSoaP3GetX( const VmathSoaPoint3 *pnt ); + +/* + * Get the y element of a 3-D point + */ +static inline vec_float4 vmathSoaP3GetY( const VmathSoaPoint3 *pnt ); + +/* + * Get the z element of a 3-D point + */ +static inline vec_float4 vmathSoaP3GetZ( const VmathSoaPoint3 *pnt ); + +/* + * Set an x, y, or z element of a 3-D point by index + */ +static inline void vmathSoaP3SetElem( VmathSoaPoint3 *result, int idx, vec_float4 value ); + +/* + * Get an x, y, or z element of a 3-D point by index + */ +static inline vec_float4 vmathSoaP3GetElem( const VmathSoaPoint3 *pnt, int idx ); + +/* + * Subtract a 3-D point from another 3-D point + */ +static inline void vmathSoaP3Sub( VmathSoaVector3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Add a 3-D point to a 3-D vector + */ +static inline void vmathSoaP3AddV3( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, const VmathSoaVector3 *vec ); + +/* + * Subtract a 3-D vector from a 3-D point + */ +static inline void vmathSoaP3SubV3( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, const VmathSoaVector3 *vec ); + +/* + * Multiply two 3-D points per element + */ +static inline void vmathSoaP3MulPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Divide two 3-D points per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline void vmathSoaP3DivPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Compute the reciprocal of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline void vmathSoaP3RecipPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ); + +/* + * Compute the square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline void vmathSoaP3SqrtPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ); + +/* + * Compute the reciprocal square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline void vmathSoaP3RsqrtPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ); + +/* + * Compute the absolute value of a 3-D point per element + */ +static inline void vmathSoaP3AbsPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt ); + +/* + * Copy sign from one 3-D point to another, per element + */ +static inline void vmathSoaP3CopySignPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Maximum of two 3-D points per element + */ +static inline void vmathSoaP3MaxPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Minimum of two 3-D points per element + */ +static inline void vmathSoaP3MinPerElem( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Maximum element of a 3-D point + */ +static inline vec_float4 vmathSoaP3MaxElem( const VmathSoaPoint3 *pnt ); + +/* + * Minimum element of a 3-D point + */ +static inline vec_float4 vmathSoaP3MinElem( const VmathSoaPoint3 *pnt ); + +/* + * Compute the sum of all elements of a 3-D point + */ +static inline vec_float4 vmathSoaP3Sum( const VmathSoaPoint3 *pnt ); + +/* + * Apply uniform scale to a 3-D point + */ +static inline void vmathSoaP3Scale( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, vec_float4 scaleVal ); + +/* + * Apply non-uniform scale to a 3-D point + */ +static inline void vmathSoaP3NonUniformScale( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt, const VmathSoaVector3 *scaleVec ); + +/* + * Scalar projection of a 3-D point on a unit-length 3-D vector + */ +static inline vec_float4 vmathSoaP3Projection( const VmathSoaPoint3 *pnt, const VmathSoaVector3 *unitVec ); + +/* + * Compute the square of the distance of a 3-D point from the coordinate-system origin + */ +static inline vec_float4 vmathSoaP3DistSqrFromOrigin( const VmathSoaPoint3 *pnt ); + +/* + * Compute the distance of a 3-D point from the coordinate-system origin + */ +static inline vec_float4 vmathSoaP3DistFromOrigin( const VmathSoaPoint3 *pnt ); + +/* + * Compute the square of the distance between two 3-D points + */ +static inline vec_float4 vmathSoaP3DistSqr( const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Compute the distance between two 3-D points + */ +static inline vec_float4 vmathSoaP3Dist( const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Linear interpolation between two 3-D points + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathSoaP3Lerp( VmathSoaPoint3 *result, vec_float4 t, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1 ); + +/* + * Conditionally select between two 3-D points + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathSoaP3Select( VmathSoaPoint3 *result, const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1, vec_uint4 select1 ); + +/* + * Load four three-float 3-D points, stored in three quadwords + */ +static inline void vmathSoaP3LoadXYZArray( VmathSoaPoint3 *pnt, const vec_float4 *threeQuads ); + +/* + * Store four slots of an SoA 3-D point in three quadwords + */ +static inline void vmathSoaP3StoreXYZArray( const VmathSoaPoint3 *pnt, vec_float4 *threeQuads ); + +/* + * Store eight slots of two SoA 3-D points as half-floats + */ +static inline void vmathSoaP3StoreHalfFloats( const VmathSoaPoint3 *pnt0, const VmathSoaPoint3 *pnt1, vec_ushort8 *threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D point + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaP3Print( const VmathSoaPoint3 *pnt ); + +/* + * Print a 3-D point and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaP3Prints( const VmathSoaPoint3 *pnt, const char *name ); + +#endif + +/* + * Copy a quaternion + */ +static inline void vmathSoaQCopy( VmathSoaQuat *result, const VmathSoaQuat *quat ); + +/* + * Construct a quaternion from x, y, z, and w elements + */ +static inline void vmathSoaQMakeFromElems( VmathSoaQuat *result, vec_float4 x, vec_float4 y, vec_float4 z, vec_float4 w ); + +/* + * Construct a quaternion from a 3-D vector and a scalar + */ +static inline void vmathSoaQMakeFromV3Scalar( VmathSoaQuat *result, const VmathSoaVector3 *xyz, vec_float4 w ); + +/* + * Copy elements from a 4-D vector into a quaternion + */ +static inline void vmathSoaQMakeFromV4( VmathSoaQuat *result, const VmathSoaVector4 *vec ); + +/* + * Convert a rotation matrix to a unit-length quaternion + */ +static inline void vmathSoaQMakeFromM3( VmathSoaQuat *result, const VmathSoaMatrix3 *rotMat ); + +/* + * Set all elements of a quaternion to the same scalar value + */ +static inline void vmathSoaQMakeFromScalar( VmathSoaQuat *result, vec_float4 scalar ); + +/* + * Replicate an AoS quaternion + */ +static inline void vmathSoaQMakeFromAos( VmathSoaQuat *result, const VmathQuat *quat ); + +/* + * Insert four AoS quaternions + */ +static inline void vmathSoaQMakeFrom4Aos( VmathSoaQuat *result, const VmathQuat *quat0, const VmathQuat *quat1, const VmathQuat *quat2, const VmathQuat *quat3 ); + +/* + * Extract four AoS quaternions + */ +static inline void vmathSoaQGet4Aos( const VmathSoaQuat *quat, VmathQuat *result0, VmathQuat *result1, VmathQuat *result2, VmathQuat *result3 ); + +/* + * Set the x, y, and z elements of a quaternion + * NOTE: + * This function does not change the w element. + */ +static inline void vmathSoaQSetXYZ( VmathSoaQuat *result, const VmathSoaVector3 *vec ); + +/* + * Get the x, y, and z elements of a quaternion + */ +static inline void vmathSoaQGetXYZ( VmathSoaVector3 *result, const VmathSoaQuat *quat ); + +/* + * Set the x element of a quaternion + */ +static inline void vmathSoaQSetX( VmathSoaQuat *result, vec_float4 x ); + +/* + * Set the y element of a quaternion + */ +static inline void vmathSoaQSetY( VmathSoaQuat *result, vec_float4 y ); + +/* + * Set the z element of a quaternion + */ +static inline void vmathSoaQSetZ( VmathSoaQuat *result, vec_float4 z ); + +/* + * Set the w element of a quaternion + */ +static inline void vmathSoaQSetW( VmathSoaQuat *result, vec_float4 w ); + +/* + * Get the x element of a quaternion + */ +static inline vec_float4 vmathSoaQGetX( const VmathSoaQuat *quat ); + +/* + * Get the y element of a quaternion + */ +static inline vec_float4 vmathSoaQGetY( const VmathSoaQuat *quat ); + +/* + * Get the z element of a quaternion + */ +static inline vec_float4 vmathSoaQGetZ( const VmathSoaQuat *quat ); + +/* + * Get the w element of a quaternion + */ +static inline vec_float4 vmathSoaQGetW( const VmathSoaQuat *quat ); + +/* + * Set an x, y, z, or w element of a quaternion by index + */ +static inline void vmathSoaQSetElem( VmathSoaQuat *result, int idx, vec_float4 value ); + +/* + * Get an x, y, z, or w element of a quaternion by index + */ +static inline vec_float4 vmathSoaQGetElem( const VmathSoaQuat *quat, int idx ); + +/* + * Add two quaternions + */ +static inline void vmathSoaQAdd( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ); + +/* + * Subtract a quaternion from another quaternion + */ +static inline void vmathSoaQSub( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ); + +/* + * Multiply two quaternions + */ +static inline void vmathSoaQMul( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ); + +/* + * Multiply a quaternion by a scalar + */ +static inline void vmathSoaQScalarMul( VmathSoaQuat *result, const VmathSoaQuat *quat, vec_float4 scalar ); + +/* + * Divide a quaternion by a scalar + */ +static inline void vmathSoaQScalarDiv( VmathSoaQuat *result, const VmathSoaQuat *quat, vec_float4 scalar ); + +/* + * Negate all elements of a quaternion + */ +static inline void vmathSoaQNeg( VmathSoaQuat *result, const VmathSoaQuat *quat ); + +/* + * Construct an identity quaternion + */ +static inline void vmathSoaQMakeIdentity( VmathSoaQuat *result ); + +/* + * Construct a quaternion to rotate between two unit-length 3-D vectors + * NOTE: + * The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + */ +static inline void vmathSoaQMakeRotationArc( VmathSoaQuat *result, const VmathSoaVector3 *unitVec0, const VmathSoaVector3 *unitVec1 ); + +/* + * Construct a quaternion to rotate around a unit-length 3-D vector + */ +static inline void vmathSoaQMakeRotationAxis( VmathSoaQuat *result, vec_float4 radians, const VmathSoaVector3 *unitVec ); + +/* + * Construct a quaternion to rotate around the x axis + */ +static inline void vmathSoaQMakeRotationX( VmathSoaQuat *result, vec_float4 radians ); + +/* + * Construct a quaternion to rotate around the y axis + */ +static inline void vmathSoaQMakeRotationY( VmathSoaQuat *result, vec_float4 radians ); + +/* + * Construct a quaternion to rotate around the z axis + */ +static inline void vmathSoaQMakeRotationZ( VmathSoaQuat *result, vec_float4 radians ); + +/* + * Compute the conjugate of a quaternion + */ +static inline void vmathSoaQConj( VmathSoaQuat *result, const VmathSoaQuat *quat ); + +/* + * Use a unit-length quaternion to rotate a 3-D vector + */ +static inline void vmathSoaQRotate( VmathSoaVector3 *result, const VmathSoaQuat *unitQuat, const VmathSoaVector3 *vec ); + +/* + * Compute the dot product of two quaternions + */ +static inline vec_float4 vmathSoaQDot( const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ); + +/* + * Compute the norm of a quaternion + */ +static inline vec_float4 vmathSoaQNorm( const VmathSoaQuat *quat ); + +/* + * Compute the length of a quaternion + */ +static inline vec_float4 vmathSoaQLength( const VmathSoaQuat *quat ); + +/* + * Normalize a quaternion + * NOTE: + * The result is unpredictable when all elements of quat are at or near zero. + */ +static inline void vmathSoaQNormalize( VmathSoaQuat *result, const VmathSoaQuat *quat ); + +/* + * Linear interpolation between two quaternions + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline void vmathSoaQLerp( VmathSoaQuat *result, vec_float4 t, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1 ); + +/* + * Spherical linear interpolation between two quaternions + * NOTE: + * Interpolates along the shortest path between orientations. + * Does not clamp t between 0 and 1. + */ +static inline void vmathSoaQSlerp( VmathSoaQuat *result, vec_float4 t, const VmathSoaQuat *unitQuat0, const VmathSoaQuat *unitQuat1 ); + +/* + * Spherical quadrangle interpolation + */ +static inline void vmathSoaQSquad( VmathSoaQuat *result, vec_float4 t, const VmathSoaQuat *unitQuat0, const VmathSoaQuat *unitQuat1, const VmathSoaQuat *unitQuat2, const VmathSoaQuat *unitQuat3 ); + +/* + * Conditionally select between two quaternions + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathSoaQSelect( VmathSoaQuat *result, const VmathSoaQuat *quat0, const VmathSoaQuat *quat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a quaternion + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaQPrint( const VmathSoaQuat *quat ); + +/* + * Print a quaternion and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaQPrints( const VmathSoaQuat *quat, const char *name ); + +#endif + +/* + * Copy a 3x3 matrix + */ +static inline void vmathSoaM3Copy( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ); + +/* + * Construct a 3x3 matrix containing the specified columns + */ +static inline void vmathSoaM3MakeFromCols( VmathSoaMatrix3 *result, const VmathSoaVector3 *col0, const VmathSoaVector3 *col1, const VmathSoaVector3 *col2 ); + +/* + * Construct a 3x3 rotation matrix from a unit-length quaternion + */ +static inline void vmathSoaM3MakeFromQ( VmathSoaMatrix3 *result, const VmathSoaQuat *unitQuat ); + +/* + * Set all elements of a 3x3 matrix to the same scalar value + */ +static inline void vmathSoaM3MakeFromScalar( VmathSoaMatrix3 *result, vec_float4 scalar ); + +/* + * Replicate an AoS 3x3 matrix + */ +static inline void vmathSoaM3MakeFromAos( VmathSoaMatrix3 *result, const VmathMatrix3 *mat ); + +/* + * Insert four AoS 3x3 matrices + */ +static inline void vmathSoaM3MakeFrom4Aos( VmathSoaMatrix3 *result, const VmathMatrix3 *mat0, const VmathMatrix3 *mat1, const VmathMatrix3 *mat2, const VmathMatrix3 *mat3 ); + +/* + * Extract four AoS 3x3 matrices + */ +static inline void vmathSoaM3Get4Aos( const VmathSoaMatrix3 *mat, VmathMatrix3 *result0, VmathMatrix3 *result1, VmathMatrix3 *result2, VmathMatrix3 *result3 ); + +/* + * Set column 0 of a 3x3 matrix + */ +static inline void vmathSoaM3SetCol0( VmathSoaMatrix3 *result, const VmathSoaVector3 *col0 ); + +/* + * Set column 1 of a 3x3 matrix + */ +static inline void vmathSoaM3SetCol1( VmathSoaMatrix3 *result, const VmathSoaVector3 *col1 ); + +/* + * Set column 2 of a 3x3 matrix + */ +static inline void vmathSoaM3SetCol2( VmathSoaMatrix3 *result, const VmathSoaVector3 *col2 ); + +/* + * Get column 0 of a 3x3 matrix + */ +static inline void vmathSoaM3GetCol0( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat ); + +/* + * Get column 1 of a 3x3 matrix + */ +static inline void vmathSoaM3GetCol1( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat ); + +/* + * Get column 2 of a 3x3 matrix + */ +static inline void vmathSoaM3GetCol2( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat ); + +/* + * Set the column of a 3x3 matrix referred to by the specified index + */ +static inline void vmathSoaM3SetCol( VmathSoaMatrix3 *result, int col, const VmathSoaVector3 *vec ); + +/* + * Set the row of a 3x3 matrix referred to by the specified index + */ +static inline void vmathSoaM3SetRow( VmathSoaMatrix3 *result, int row, const VmathSoaVector3 *vec ); + +/* + * Get the column of a 3x3 matrix referred to by the specified index + */ +static inline void vmathSoaM3GetCol( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat, int col ); + +/* + * Get the row of a 3x3 matrix referred to by the specified index + */ +static inline void vmathSoaM3GetRow( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat, int row ); + +/* + * Set the element of a 3x3 matrix referred to by column and row indices + */ +static inline void vmathSoaM3SetElem( VmathSoaMatrix3 *result, int col, int row, vec_float4 val ); + +/* + * Get the element of a 3x3 matrix referred to by column and row indices + */ +static inline vec_float4 vmathSoaM3GetElem( const VmathSoaMatrix3 *mat, int col, int row ); + +/* + * Add two 3x3 matrices + */ +static inline void vmathSoaM3Add( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 ); + +/* + * Subtract a 3x3 matrix from another 3x3 matrix + */ +static inline void vmathSoaM3Sub( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 ); + +/* + * Negate all elements of a 3x3 matrix + */ +static inline void vmathSoaM3Neg( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ); + +/* + * Multiply a 3x3 matrix by a scalar + */ +static inline void vmathSoaM3ScalarMul( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat, vec_float4 scalar ); + +/* + * Multiply a 3x3 matrix by a 3-D vector + */ +static inline void vmathSoaM3MulV3( VmathSoaVector3 *result, const VmathSoaMatrix3 *mat, const VmathSoaVector3 *vec ); + +/* + * Multiply two 3x3 matrices + */ +static inline void vmathSoaM3Mul( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 ); + +/* + * Construct an identity 3x3 matrix + */ +static inline void vmathSoaM3MakeIdentity( VmathSoaMatrix3 *result ); + +/* + * Construct a 3x3 matrix to rotate around the x axis + */ +static inline void vmathSoaM3MakeRotationX( VmathSoaMatrix3 *result, vec_float4 radians ); + +/* + * Construct a 3x3 matrix to rotate around the y axis + */ +static inline void vmathSoaM3MakeRotationY( VmathSoaMatrix3 *result, vec_float4 radians ); + +/* + * Construct a 3x3 matrix to rotate around the z axis + */ +static inline void vmathSoaM3MakeRotationZ( VmathSoaMatrix3 *result, vec_float4 radians ); + +/* + * Construct a 3x3 matrix to rotate around the x, y, and z axes + */ +static inline void vmathSoaM3MakeRotationZYX( VmathSoaMatrix3 *result, const VmathSoaVector3 *radiansXYZ ); + +/* + * Construct a 3x3 matrix to rotate around a unit-length 3-D vector + */ +static inline void vmathSoaM3MakeRotationAxis( VmathSoaMatrix3 *result, vec_float4 radians, const VmathSoaVector3 *unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline void vmathSoaM3MakeRotationQ( VmathSoaMatrix3 *result, const VmathSoaQuat *unitQuat ); + +/* + * Construct a 3x3 matrix to perform scaling + */ +static inline void vmathSoaM3MakeScale( VmathSoaMatrix3 *result, const VmathSoaVector3 *scaleVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathSoaM3AppendScale( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat, const VmathSoaVector3 *scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathSoaM3PrependScale( VmathSoaMatrix3 *result, const VmathSoaVector3 *scaleVec, const VmathSoaMatrix3 *mat ); + +/* + * Multiply two 3x3 matrices per element + */ +static inline void vmathSoaM3MulPerElem( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1 ); + +/* + * Compute the absolute value of a 3x3 matrix per element + */ +static inline void vmathSoaM3AbsPerElem( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ); + +/* + * Transpose of a 3x3 matrix + */ +static inline void vmathSoaM3Transpose( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ); + +/* + * Compute the inverse of a 3x3 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline void vmathSoaM3Inverse( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat ); + +/* + * Determinant of a 3x3 matrix + */ +static inline vec_float4 vmathSoaM3Determinant( const VmathSoaMatrix3 *mat ); + +/* + * Conditionally select between two 3x3 matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathSoaM3Select( VmathSoaMatrix3 *result, const VmathSoaMatrix3 *mat0, const VmathSoaMatrix3 *mat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x3 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaM3Print( const VmathSoaMatrix3 *mat ); + +/* + * Print a 3x3 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaM3Prints( const VmathSoaMatrix3 *mat, const char *name ); + +#endif + +/* + * Copy a 4x4 matrix + */ +static inline void vmathSoaM4Copy( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Construct a 4x4 matrix containing the specified columns + */ +static inline void vmathSoaM4MakeFromCols( VmathSoaMatrix4 *result, const VmathSoaVector4 *col0, const VmathSoaVector4 *col1, const VmathSoaVector4 *col2, const VmathSoaVector4 *col3 ); + +/* + * Construct a 4x4 matrix from a 3x4 transformation matrix + */ +static inline void vmathSoaM4MakeFromT3( VmathSoaMatrix4 *result, const VmathSoaTransform3 *mat ); + +/* + * Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + */ +static inline void vmathSoaM4MakeFromM3V3( VmathSoaMatrix4 *result, const VmathSoaMatrix3 *mat, const VmathSoaVector3 *translateVec ); + +/* + * Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + */ +static inline void vmathSoaM4MakeFromQV3( VmathSoaMatrix4 *result, const VmathSoaQuat *unitQuat, const VmathSoaVector3 *translateVec ); + +/* + * Set all elements of a 4x4 matrix to the same scalar value + */ +static inline void vmathSoaM4MakeFromScalar( VmathSoaMatrix4 *result, vec_float4 scalar ); + +/* + * Replicate an AoS 4x4 matrix + */ +static inline void vmathSoaM4MakeFromAos( VmathSoaMatrix4 *result, const VmathMatrix4 *mat ); + +/* + * Insert four AoS 4x4 matrices + */ +static inline void vmathSoaM4MakeFrom4Aos( VmathSoaMatrix4 *result, const VmathMatrix4 *mat0, const VmathMatrix4 *mat1, const VmathMatrix4 *mat2, const VmathMatrix4 *mat3 ); + +/* + * Extract four AoS 4x4 matrices + */ +static inline void vmathSoaM4Get4Aos( const VmathSoaMatrix4 *mat, VmathMatrix4 *result0, VmathMatrix4 *result1, VmathMatrix4 *result2, VmathMatrix4 *result3 ); + +/* + * Set the upper-left 3x3 submatrix + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathSoaM4SetUpper3x3( VmathSoaMatrix4 *result, const VmathSoaMatrix3 *mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 4x4 matrix + */ +static inline void vmathSoaM4GetUpper3x3( VmathSoaMatrix3 *result, const VmathSoaMatrix4 *mat ); + +/* + * Set translation component + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathSoaM4SetTranslation( VmathSoaMatrix4 *result, const VmathSoaVector3 *translateVec ); + +/* + * Get the translation component of a 4x4 matrix + */ +static inline void vmathSoaM4GetTranslation( VmathSoaVector3 *result, const VmathSoaMatrix4 *mat ); + +/* + * Set column 0 of a 4x4 matrix + */ +static inline void vmathSoaM4SetCol0( VmathSoaMatrix4 *result, const VmathSoaVector4 *col0 ); + +/* + * Set column 1 of a 4x4 matrix + */ +static inline void vmathSoaM4SetCol1( VmathSoaMatrix4 *result, const VmathSoaVector4 *col1 ); + +/* + * Set column 2 of a 4x4 matrix + */ +static inline void vmathSoaM4SetCol2( VmathSoaMatrix4 *result, const VmathSoaVector4 *col2 ); + +/* + * Set column 3 of a 4x4 matrix + */ +static inline void vmathSoaM4SetCol3( VmathSoaMatrix4 *result, const VmathSoaVector4 *col3 ); + +/* + * Get column 0 of a 4x4 matrix + */ +static inline void vmathSoaM4GetCol0( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Get column 1 of a 4x4 matrix + */ +static inline void vmathSoaM4GetCol1( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Get column 2 of a 4x4 matrix + */ +static inline void vmathSoaM4GetCol2( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Get column 3 of a 4x4 matrix + */ +static inline void vmathSoaM4GetCol3( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Set the column of a 4x4 matrix referred to by the specified index + */ +static inline void vmathSoaM4SetCol( VmathSoaMatrix4 *result, int col, const VmathSoaVector4 *vec ); + +/* + * Set the row of a 4x4 matrix referred to by the specified index + */ +static inline void vmathSoaM4SetRow( VmathSoaMatrix4 *result, int row, const VmathSoaVector4 *vec ); + +/* + * Get the column of a 4x4 matrix referred to by the specified index + */ +static inline void vmathSoaM4GetCol( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, int col ); + +/* + * Get the row of a 4x4 matrix referred to by the specified index + */ +static inline void vmathSoaM4GetRow( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, int row ); + +/* + * Set the element of a 4x4 matrix referred to by column and row indices + */ +static inline void vmathSoaM4SetElem( VmathSoaMatrix4 *result, int col, int row, vec_float4 val ); + +/* + * Get the element of a 4x4 matrix referred to by column and row indices + */ +static inline vec_float4 vmathSoaM4GetElem( const VmathSoaMatrix4 *mat, int col, int row ); + +/* + * Add two 4x4 matrices + */ +static inline void vmathSoaM4Add( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 ); + +/* + * Subtract a 4x4 matrix from another 4x4 matrix + */ +static inline void vmathSoaM4Sub( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 ); + +/* + * Negate all elements of a 4x4 matrix + */ +static inline void vmathSoaM4Neg( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Multiply a 4x4 matrix by a scalar + */ +static inline void vmathSoaM4ScalarMul( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat, vec_float4 scalar ); + +/* + * Multiply a 4x4 matrix by a 4-D vector + */ +static inline void vmathSoaM4MulV4( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, const VmathSoaVector4 *vec ); + +/* + * Multiply a 4x4 matrix by a 3-D vector + */ +static inline void vmathSoaM4MulV3( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, const VmathSoaVector3 *vec ); + +/* + * Multiply a 4x4 matrix by a 3-D point + */ +static inline void vmathSoaM4MulP3( VmathSoaVector4 *result, const VmathSoaMatrix4 *mat, const VmathSoaPoint3 *pnt ); + +/* + * Multiply two 4x4 matrices + */ +static inline void vmathSoaM4Mul( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 ); + +/* + * Multiply a 4x4 matrix by a 3x4 transformation matrix + */ +static inline void vmathSoaM4MulT3( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat, const VmathSoaTransform3 *tfrm ); + +/* + * Construct an identity 4x4 matrix + */ +static inline void vmathSoaM4MakeIdentity( VmathSoaMatrix4 *result ); + +/* + * Construct a 4x4 matrix to rotate around the x axis + */ +static inline void vmathSoaM4MakeRotationX( VmathSoaMatrix4 *result, vec_float4 radians ); + +/* + * Construct a 4x4 matrix to rotate around the y axis + */ +static inline void vmathSoaM4MakeRotationY( VmathSoaMatrix4 *result, vec_float4 radians ); + +/* + * Construct a 4x4 matrix to rotate around the z axis + */ +static inline void vmathSoaM4MakeRotationZ( VmathSoaMatrix4 *result, vec_float4 radians ); + +/* + * Construct a 4x4 matrix to rotate around the x, y, and z axes + */ +static inline void vmathSoaM4MakeRotationZYX( VmathSoaMatrix4 *result, const VmathSoaVector3 *radiansXYZ ); + +/* + * Construct a 4x4 matrix to rotate around a unit-length 3-D vector + */ +static inline void vmathSoaM4MakeRotationAxis( VmathSoaMatrix4 *result, vec_float4 radians, const VmathSoaVector3 *unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline void vmathSoaM4MakeRotationQ( VmathSoaMatrix4 *result, const VmathSoaQuat *unitQuat ); + +/* + * Construct a 4x4 matrix to perform scaling + */ +static inline void vmathSoaM4MakeScale( VmathSoaMatrix4 *result, const VmathSoaVector3 *scaleVec ); + +/* + * Construct a 4x4 matrix to perform translation + */ +static inline void vmathSoaM4MakeTranslation( VmathSoaMatrix4 *result, const VmathSoaVector3 *translateVec ); + +/* + * Construct viewing matrix based on eye position, position looked at, and up direction + */ +static inline void vmathSoaM4MakeLookAt( VmathSoaMatrix4 *result, const VmathSoaPoint3 *eyePos, const VmathSoaPoint3 *lookAtPos, const VmathSoaVector3 *upVec ); + +/* + * Construct a perspective projection matrix + */ +static inline void vmathSoaM4MakePerspective( VmathSoaMatrix4 *result, vec_float4 fovyRadians, vec_float4 aspect, vec_float4 zNear, vec_float4 zFar ); + +/* + * Construct a perspective projection matrix based on frustum + */ +static inline void vmathSoaM4MakeFrustum( VmathSoaMatrix4 *result, vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ); + +/* + * Construct an orthographic projection matrix + */ +static inline void vmathSoaM4MakeOrthographic( VmathSoaMatrix4 *result, vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ); + +/* + * Append (post-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathSoaM4AppendScale( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat, const VmathSoaVector3 *scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathSoaM4PrependScale( VmathSoaMatrix4 *result, const VmathSoaVector3 *scaleVec, const VmathSoaMatrix4 *mat ); + +/* + * Multiply two 4x4 matrices per element + */ +static inline void vmathSoaM4MulPerElem( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1 ); + +/* + * Compute the absolute value of a 4x4 matrix per element + */ +static inline void vmathSoaM4AbsPerElem( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Transpose of a 4x4 matrix + */ +static inline void vmathSoaM4Transpose( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Compute the inverse of a 4x4 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline void vmathSoaM4Inverse( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline void vmathSoaM4AffineInverse( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. + */ +static inline void vmathSoaM4OrthoInverse( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat ); + +/* + * Determinant of a 4x4 matrix + */ +static inline vec_float4 vmathSoaM4Determinant( const VmathSoaMatrix4 *mat ); + +/* + * Conditionally select between two 4x4 matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathSoaM4Select( VmathSoaMatrix4 *result, const VmathSoaMatrix4 *mat0, const VmathSoaMatrix4 *mat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4x4 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaM4Print( const VmathSoaMatrix4 *mat ); + +/* + * Print a 4x4 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaM4Prints( const VmathSoaMatrix4 *mat, const char *name ); + +#endif + +/* + * Copy a 3x4 transformation matrix + */ +static inline void vmathSoaT3Copy( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Construct a 3x4 transformation matrix containing the specified columns + */ +static inline void vmathSoaT3MakeFromCols( VmathSoaTransform3 *result, const VmathSoaVector3 *col0, const VmathSoaVector3 *col1, const VmathSoaVector3 *col2, const VmathSoaVector3 *col3 ); + +/* + * Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + */ +static inline void vmathSoaT3MakeFromM3V3( VmathSoaTransform3 *result, const VmathSoaMatrix3 *tfrm, const VmathSoaVector3 *translateVec ); + +/* + * Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + */ +static inline void vmathSoaT3MakeFromQV3( VmathSoaTransform3 *result, const VmathSoaQuat *unitQuat, const VmathSoaVector3 *translateVec ); + +/* + * Set all elements of a 3x4 transformation matrix to the same scalar value + */ +static inline void vmathSoaT3MakeFromScalar( VmathSoaTransform3 *result, vec_float4 scalar ); + +/* + * Replicate an AoS 3x4 transformation matrix + */ +static inline void vmathSoaT3MakeFromAos( VmathSoaTransform3 *result, const VmathTransform3 *tfrm ); + +/* + * Insert four AoS 3x4 transformation matrices + */ +static inline void vmathSoaT3MakeFrom4Aos( VmathSoaTransform3 *result, const VmathTransform3 *tfrm0, const VmathTransform3 *tfrm1, const VmathTransform3 *tfrm2, const VmathTransform3 *tfrm3 ); + +/* + * Extract four AoS 3x4 transformation matrices + */ +static inline void vmathSoaT3Get4Aos( const VmathSoaTransform3 *tfrm, VmathTransform3 *result0, VmathTransform3 *result1, VmathTransform3 *result2, VmathTransform3 *result3 ); + +/* + * Set the upper-left 3x3 submatrix + */ +static inline void vmathSoaT3SetUpper3x3( VmathSoaTransform3 *result, const VmathSoaMatrix3 *mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + */ +static inline void vmathSoaT3GetUpper3x3( VmathSoaMatrix3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Set translation component + */ +static inline void vmathSoaT3SetTranslation( VmathSoaTransform3 *result, const VmathSoaVector3 *translateVec ); + +/* + * Get the translation component of a 3x4 transformation matrix + */ +static inline void vmathSoaT3GetTranslation( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Set column 0 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3SetCol0( VmathSoaTransform3 *result, const VmathSoaVector3 *col0 ); + +/* + * Set column 1 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3SetCol1( VmathSoaTransform3 *result, const VmathSoaVector3 *col1 ); + +/* + * Set column 2 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3SetCol2( VmathSoaTransform3 *result, const VmathSoaVector3 *col2 ); + +/* + * Set column 3 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3SetCol3( VmathSoaTransform3 *result, const VmathSoaVector3 *col3 ); + +/* + * Get column 0 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3GetCol0( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Get column 1 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3GetCol1( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Get column 2 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3GetCol2( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Get column 3 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3GetCol3( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Set the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathSoaT3SetCol( VmathSoaTransform3 *result, int col, const VmathSoaVector3 *vec ); + +/* + * Set the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathSoaT3SetRow( VmathSoaTransform3 *result, int row, const VmathSoaVector4 *vec ); + +/* + * Get the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathSoaT3GetCol( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm, int col ); + +/* + * Get the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathSoaT3GetRow( VmathSoaVector4 *result, const VmathSoaTransform3 *tfrm, int row ); + +/* + * Set the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline void vmathSoaT3SetElem( VmathSoaTransform3 *result, int col, int row, vec_float4 val ); + +/* + * Get the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline vec_float4 vmathSoaT3GetElem( const VmathSoaTransform3 *tfrm, int col, int row ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D vector + */ +static inline void vmathSoaT3MulV3( VmathSoaVector3 *result, const VmathSoaTransform3 *tfrm, const VmathSoaVector3 *vec ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D point + */ +static inline void vmathSoaT3MulP3( VmathSoaPoint3 *result, const VmathSoaTransform3 *tfrm, const VmathSoaPoint3 *pnt ); + +/* + * Multiply two 3x4 transformation matrices + */ +static inline void vmathSoaT3Mul( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm0, const VmathSoaTransform3 *tfrm1 ); + +/* + * Construct an identity 3x4 transformation matrix + */ +static inline void vmathSoaT3MakeIdentity( VmathSoaTransform3 *result ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x axis + */ +static inline void vmathSoaT3MakeRotationX( VmathSoaTransform3 *result, vec_float4 radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the y axis + */ +static inline void vmathSoaT3MakeRotationY( VmathSoaTransform3 *result, vec_float4 radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the z axis + */ +static inline void vmathSoaT3MakeRotationZ( VmathSoaTransform3 *result, vec_float4 radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + */ +static inline void vmathSoaT3MakeRotationZYX( VmathSoaTransform3 *result, const VmathSoaVector3 *radiansXYZ ); + +/* + * Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + */ +static inline void vmathSoaT3MakeRotationAxis( VmathSoaTransform3 *result, vec_float4 radians, const VmathSoaVector3 *unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline void vmathSoaT3MakeRotationQ( VmathSoaTransform3 *result, const VmathSoaQuat *unitQuat ); + +/* + * Construct a 3x4 transformation matrix to perform scaling + */ +static inline void vmathSoaT3MakeScale( VmathSoaTransform3 *result, const VmathSoaVector3 *scaleVec ); + +/* + * Construct a 3x4 transformation matrix to perform translation + */ +static inline void vmathSoaT3MakeTranslation( VmathSoaTransform3 *result, const VmathSoaVector3 *translateVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathSoaT3AppendScale( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm, const VmathSoaVector3 *scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline void vmathSoaT3PrependScale( VmathSoaTransform3 *result, const VmathSoaVector3 *scaleVec, const VmathSoaTransform3 *tfrm ); + +/* + * Multiply two 3x4 transformation matrices per element + */ +static inline void vmathSoaT3MulPerElem( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm0, const VmathSoaTransform3 *tfrm1 ); + +/* + * Compute the absolute value of a 3x4 transformation matrix per element + */ +static inline void vmathSoaT3AbsPerElem( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Inverse of a 3x4 transformation matrix + * NOTE: + * Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. + */ +static inline void vmathSoaT3Inverse( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. + */ +static inline void vmathSoaT3OrthoInverse( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm ); + +/* + * Conditionally select between two 3x4 transformation matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline void vmathSoaT3Select( VmathSoaTransform3 *result, const VmathSoaTransform3 *tfrm0, const VmathSoaTransform3 *tfrm1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x4 transformation matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaT3Print( const VmathSoaTransform3 *tfrm ); + +/* + * Print a 3x4 transformation matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaT3Prints( const VmathSoaTransform3 *tfrm, const char *name ); + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#include "vec_soa.h" +#include "quat_soa.h" +#include "mat_soa.h" + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/c/vectormath_soa_v.h b/Extras/vectormathlibrary/include/vectormath/spu/c/vectormath_soa_v.h new file mode 100644 index 0000000..85ebed3 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/c/vectormath_soa_v.h @@ -0,0 +1,1978 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_SOA_C_V_SPU_H +#define _VECTORMATH_SOA_C_V_SPU_H + +#include +#include +#include "vectormath_aos_v.h" + +#ifdef _VECTORMATH_DEBUG +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef _VECTORMATH_SOA_C_TYPES_H +#define _VECTORMATH_SOA_C_TYPES_H + +/* A set of four 3-D vectors in structure-of-arrays format + */ +typedef struct _VmathSoaVector3 +{ + vec_float4 x; + vec_float4 y; + vec_float4 z; +} VmathSoaVector3; + +/* A set of four 4-D vectors in structure-of-arrays format + */ +typedef struct _VmathSoaVector4 +{ + vec_float4 x; + vec_float4 y; + vec_float4 z; + vec_float4 w; +} VmathSoaVector4; + +/* A set of four 3-D points in structure-of-arrays format + */ +typedef struct _VmathSoaPoint3 +{ + vec_float4 x; + vec_float4 y; + vec_float4 z; +} VmathSoaPoint3; + +/* A set of four quaternions in structure-of-arrays format + */ +typedef struct _VmathSoaQuat +{ + vec_float4 x; + vec_float4 y; + vec_float4 z; + vec_float4 w; +} VmathSoaQuat; + +/* A set of four 3x3 matrices in structure-of-arrays format + */ +typedef struct _VmathSoaMatrix3 +{ + VmathSoaVector3 col0; + VmathSoaVector3 col1; + VmathSoaVector3 col2; +} VmathSoaMatrix3; + +/* A set of four 4x4 matrices in structure-of-arrays format + */ +typedef struct _VmathSoaMatrix4 +{ + VmathSoaVector4 col0; + VmathSoaVector4 col1; + VmathSoaVector4 col2; + VmathSoaVector4 col3; +} VmathSoaMatrix4; + +/* A set of four 3x4 transformation matrices in structure-of-arrays format + */ +typedef struct _VmathSoaTransform3 +{ + VmathSoaVector3 col0; + VmathSoaVector3 col1; + VmathSoaVector3 col2; + VmathSoaVector3 col3; +} VmathSoaTransform3; + +#endif + +/* + * Construct a 3-D vector from x, y, and z elements + */ +static inline VmathSoaVector3 vmathSoaV3MakeFromElems_V( vec_float4 x, vec_float4 y, vec_float4 z ); + +/* + * Copy elements from a 3-D point into a 3-D vector + */ +static inline VmathSoaVector3 vmathSoaV3MakeFromP3_V( VmathSoaPoint3 pnt ); + +/* + * Set all elements of a 3-D vector to the same scalar value + */ +static inline VmathSoaVector3 vmathSoaV3MakeFromScalar_V( vec_float4 scalar ); + +/* + * Replicate an AoS 3-D vector + */ +static inline VmathSoaVector3 vmathSoaV3MakeFromAos_V( VmathVector3 vec ); + +/* + * Insert four AoS 3-D vectors + */ +static inline VmathSoaVector3 vmathSoaV3MakeFrom4Aos_V( VmathVector3 vec0, VmathVector3 vec1, VmathVector3 vec2, VmathVector3 vec3 ); + +/* + * Extract four AoS 3-D vectors + */ +static inline void vmathSoaV3Get4Aos_V( VmathSoaVector3 vec, VmathVector3 *result0, VmathVector3 *result1, VmathVector3 *result2, VmathVector3 *result3 ); + +/* + * Set the x element of a 3-D vector + */ +static inline void vmathSoaV3SetX_V( VmathSoaVector3 *result, vec_float4 x ); + +/* + * Set the y element of a 3-D vector + */ +static inline void vmathSoaV3SetY_V( VmathSoaVector3 *result, vec_float4 y ); + +/* + * Set the z element of a 3-D vector + */ +static inline void vmathSoaV3SetZ_V( VmathSoaVector3 *result, vec_float4 z ); + +/* + * Get the x element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3GetX_V( VmathSoaVector3 vec ); + +/* + * Get the y element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3GetY_V( VmathSoaVector3 vec ); + +/* + * Get the z element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3GetZ_V( VmathSoaVector3 vec ); + +/* + * Set an x, y, or z element of a 3-D vector by index + */ +static inline void vmathSoaV3SetElem_V( VmathSoaVector3 *result, int idx, vec_float4 value ); + +/* + * Get an x, y, or z element of a 3-D vector by index + */ +static inline vec_float4 vmathSoaV3GetElem_V( VmathSoaVector3 vec, int idx ); + +/* + * Add two 3-D vectors + */ +static inline VmathSoaVector3 vmathSoaV3Add_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Subtract a 3-D vector from another 3-D vector + */ +static inline VmathSoaVector3 vmathSoaV3Sub_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Add a 3-D vector to a 3-D point + */ +static inline VmathSoaPoint3 vmathSoaV3AddP3_V( VmathSoaVector3 vec, VmathSoaPoint3 pnt ); + +/* + * Multiply a 3-D vector by a scalar + */ +static inline VmathSoaVector3 vmathSoaV3ScalarMul_V( VmathSoaVector3 vec, vec_float4 scalar ); + +/* + * Divide a 3-D vector by a scalar + */ +static inline VmathSoaVector3 vmathSoaV3ScalarDiv_V( VmathSoaVector3 vec, vec_float4 scalar ); + +/* + * Negate all elements of a 3-D vector + */ +static inline VmathSoaVector3 vmathSoaV3Neg_V( VmathSoaVector3 vec ); + +/* + * Construct x axis + */ +static inline VmathSoaVector3 vmathSoaV3MakeXAxis_V( ); + +/* + * Construct y axis + */ +static inline VmathSoaVector3 vmathSoaV3MakeYAxis_V( ); + +/* + * Construct z axis + */ +static inline VmathSoaVector3 vmathSoaV3MakeZAxis_V( ); + +/* + * Multiply two 3-D vectors per element + */ +static inline VmathSoaVector3 vmathSoaV3MulPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Divide two 3-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline VmathSoaVector3 vmathSoaV3DivPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Compute the reciprocal of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline VmathSoaVector3 vmathSoaV3RecipPerElem_V( VmathSoaVector3 vec ); + +/* + * Compute the square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline VmathSoaVector3 vmathSoaV3SqrtPerElem_V( VmathSoaVector3 vec ); + +/* + * Compute the reciprocal square root of a 3-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline VmathSoaVector3 vmathSoaV3RsqrtPerElem_V( VmathSoaVector3 vec ); + +/* + * Compute the absolute value of a 3-D vector per element + */ +static inline VmathSoaVector3 vmathSoaV3AbsPerElem_V( VmathSoaVector3 vec ); + +/* + * Copy sign from one 3-D vector to another, per element + */ +static inline VmathSoaVector3 vmathSoaV3CopySignPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Maximum of two 3-D vectors per element + */ +static inline VmathSoaVector3 vmathSoaV3MaxPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Minimum of two 3-D vectors per element + */ +static inline VmathSoaVector3 vmathSoaV3MinPerElem_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Maximum element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3MaxElem_V( VmathSoaVector3 vec ); + +/* + * Minimum element of a 3-D vector + */ +static inline vec_float4 vmathSoaV3MinElem_V( VmathSoaVector3 vec ); + +/* + * Compute the sum of all elements of a 3-D vector + */ +static inline vec_float4 vmathSoaV3Sum_V( VmathSoaVector3 vec ); + +/* + * Compute the dot product of two 3-D vectors + */ +static inline vec_float4 vmathSoaV3Dot_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Compute the square of the length of a 3-D vector + */ +static inline vec_float4 vmathSoaV3LengthSqr_V( VmathSoaVector3 vec ); + +/* + * Compute the length of a 3-D vector + */ +static inline vec_float4 vmathSoaV3Length_V( VmathSoaVector3 vec ); + +/* + * Normalize a 3-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline VmathSoaVector3 vmathSoaV3Normalize_V( VmathSoaVector3 vec ); + +/* + * Compute cross product of two 3-D vectors + */ +static inline VmathSoaVector3 vmathSoaV3Cross_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Outer product of two 3-D vectors + */ +static inline VmathSoaMatrix3 vmathSoaV3Outer_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Pre-multiply a row vector by a 3x3 matrix + */ +static inline VmathSoaVector3 vmathSoaV3RowMul_V( VmathSoaVector3 vec, VmathSoaMatrix3 mat ); + +/* + * Cross-product matrix of a 3-D vector + */ +static inline VmathSoaMatrix3 vmathSoaV3CrossMatrix_V( VmathSoaVector3 vec ); + +/* + * Create cross-product matrix and multiply + * NOTE: + * Faster than separately creating a cross-product matrix and multiplying. + */ +static inline VmathSoaMatrix3 vmathSoaV3CrossMatrixMul_V( VmathSoaVector3 vec, VmathSoaMatrix3 mat ); + +/* + * Linear interpolation between two 3-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathSoaVector3 vmathSoaV3Lerp_V( vec_float4 t, VmathSoaVector3 vec0, VmathSoaVector3 vec1 ); + +/* + * Spherical linear interpolation between two 3-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline VmathSoaVector3 vmathSoaV3Slerp_V( vec_float4 t, VmathSoaVector3 unitVec0, VmathSoaVector3 unitVec1 ); + +/* + * Conditionally select between two 3-D vectors + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathSoaVector3 vmathSoaV3Select_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1, vec_uint4 select1 ); + +/* + * Load four three-float 3-D vectors, stored in three quadwords + */ +static inline void vmathSoaV3LoadXYZArray_V( VmathSoaVector3 *vec, const vec_float4 *threeQuads ); + +/* + * Store four slots of an SoA 3-D vector in three quadwords + */ +static inline void vmathSoaV3StoreXYZArray_V( VmathSoaVector3 vec, vec_float4 *threeQuads ); + +/* + * Store eight slots of two SoA 3-D vectors as half-floats + */ +static inline void vmathSoaV3StoreHalfFloats_V( VmathSoaVector3 vec0, VmathSoaVector3 vec1, vec_ushort8 *threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaV3Print_V( VmathSoaVector3 vec ); + +/* + * Print a 3-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaV3Prints_V( VmathSoaVector3 vec, const char *name ); + +#endif + +/* + * Construct a 4-D vector from x, y, z, and w elements + */ +static inline VmathSoaVector4 vmathSoaV4MakeFromElems_V( vec_float4 x, vec_float4 y, vec_float4 z, vec_float4 w ); + +/* + * Construct a 4-D vector from a 3-D vector and a scalar + */ +static inline VmathSoaVector4 vmathSoaV4MakeFromV3Scalar_V( VmathSoaVector3 xyz, vec_float4 w ); + +/* + * Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + */ +static inline VmathSoaVector4 vmathSoaV4MakeFromV3_V( VmathSoaVector3 vec ); + +/* + * Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + */ +static inline VmathSoaVector4 vmathSoaV4MakeFromP3_V( VmathSoaPoint3 pnt ); + +/* + * Copy elements from a quaternion into a 4-D vector + */ +static inline VmathSoaVector4 vmathSoaV4MakeFromQ_V( VmathSoaQuat quat ); + +/* + * Set all elements of a 4-D vector to the same scalar value + */ +static inline VmathSoaVector4 vmathSoaV4MakeFromScalar_V( vec_float4 scalar ); + +/* + * Replicate an AoS 4-D vector + */ +static inline VmathSoaVector4 vmathSoaV4MakeFromAos_V( VmathVector4 vec ); + +/* + * Insert four AoS 4-D vectors + */ +static inline VmathSoaVector4 vmathSoaV4MakeFrom4Aos_V( VmathVector4 vec0, VmathVector4 vec1, VmathVector4 vec2, VmathVector4 vec3 ); + +/* + * Extract four AoS 4-D vectors + */ +static inline void vmathSoaV4Get4Aos_V( VmathSoaVector4 vec, VmathVector4 *result0, VmathVector4 *result1, VmathVector4 *result2, VmathVector4 *result3 ); + +/* + * Set the x, y, and z elements of a 4-D vector + * NOTE: + * This function does not change the w element. + */ +static inline void vmathSoaV4SetXYZ_V( VmathSoaVector4 *result, VmathSoaVector3 vec ); + +/* + * Get the x, y, and z elements of a 4-D vector + */ +static inline VmathSoaVector3 vmathSoaV4GetXYZ_V( VmathSoaVector4 vec ); + +/* + * Set the x element of a 4-D vector + */ +static inline void vmathSoaV4SetX_V( VmathSoaVector4 *result, vec_float4 x ); + +/* + * Set the y element of a 4-D vector + */ +static inline void vmathSoaV4SetY_V( VmathSoaVector4 *result, vec_float4 y ); + +/* + * Set the z element of a 4-D vector + */ +static inline void vmathSoaV4SetZ_V( VmathSoaVector4 *result, vec_float4 z ); + +/* + * Set the w element of a 4-D vector + */ +static inline void vmathSoaV4SetW_V( VmathSoaVector4 *result, vec_float4 w ); + +/* + * Get the x element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4GetX_V( VmathSoaVector4 vec ); + +/* + * Get the y element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4GetY_V( VmathSoaVector4 vec ); + +/* + * Get the z element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4GetZ_V( VmathSoaVector4 vec ); + +/* + * Get the w element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4GetW_V( VmathSoaVector4 vec ); + +/* + * Set an x, y, z, or w element of a 4-D vector by index + */ +static inline void vmathSoaV4SetElem_V( VmathSoaVector4 *result, int idx, vec_float4 value ); + +/* + * Get an x, y, z, or w element of a 4-D vector by index + */ +static inline vec_float4 vmathSoaV4GetElem_V( VmathSoaVector4 vec, int idx ); + +/* + * Add two 4-D vectors + */ +static inline VmathSoaVector4 vmathSoaV4Add_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Subtract a 4-D vector from another 4-D vector + */ +static inline VmathSoaVector4 vmathSoaV4Sub_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Multiply a 4-D vector by a scalar + */ +static inline VmathSoaVector4 vmathSoaV4ScalarMul_V( VmathSoaVector4 vec, vec_float4 scalar ); + +/* + * Divide a 4-D vector by a scalar + */ +static inline VmathSoaVector4 vmathSoaV4ScalarDiv_V( VmathSoaVector4 vec, vec_float4 scalar ); + +/* + * Negate all elements of a 4-D vector + */ +static inline VmathSoaVector4 vmathSoaV4Neg_V( VmathSoaVector4 vec ); + +/* + * Construct x axis + */ +static inline VmathSoaVector4 vmathSoaV4MakeXAxis_V( ); + +/* + * Construct y axis + */ +static inline VmathSoaVector4 vmathSoaV4MakeYAxis_V( ); + +/* + * Construct z axis + */ +static inline VmathSoaVector4 vmathSoaV4MakeZAxis_V( ); + +/* + * Construct w axis + */ +static inline VmathSoaVector4 vmathSoaV4MakeWAxis_V( ); + +/* + * Multiply two 4-D vectors per element + */ +static inline VmathSoaVector4 vmathSoaV4MulPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Divide two 4-D vectors per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline VmathSoaVector4 vmathSoaV4DivPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Compute the reciprocal of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline VmathSoaVector4 vmathSoaV4RecipPerElem_V( VmathSoaVector4 vec ); + +/* + * Compute the square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline VmathSoaVector4 vmathSoaV4SqrtPerElem_V( VmathSoaVector4 vec ); + +/* + * Compute the reciprocal square root of a 4-D vector per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline VmathSoaVector4 vmathSoaV4RsqrtPerElem_V( VmathSoaVector4 vec ); + +/* + * Compute the absolute value of a 4-D vector per element + */ +static inline VmathSoaVector4 vmathSoaV4AbsPerElem_V( VmathSoaVector4 vec ); + +/* + * Copy sign from one 4-D vector to another, per element + */ +static inline VmathSoaVector4 vmathSoaV4CopySignPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Maximum of two 4-D vectors per element + */ +static inline VmathSoaVector4 vmathSoaV4MaxPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Minimum of two 4-D vectors per element + */ +static inline VmathSoaVector4 vmathSoaV4MinPerElem_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Maximum element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4MaxElem_V( VmathSoaVector4 vec ); + +/* + * Minimum element of a 4-D vector + */ +static inline vec_float4 vmathSoaV4MinElem_V( VmathSoaVector4 vec ); + +/* + * Compute the sum of all elements of a 4-D vector + */ +static inline vec_float4 vmathSoaV4Sum_V( VmathSoaVector4 vec ); + +/* + * Compute the dot product of two 4-D vectors + */ +static inline vec_float4 vmathSoaV4Dot_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Compute the square of the length of a 4-D vector + */ +static inline vec_float4 vmathSoaV4LengthSqr_V( VmathSoaVector4 vec ); + +/* + * Compute the length of a 4-D vector + */ +static inline vec_float4 vmathSoaV4Length_V( VmathSoaVector4 vec ); + +/* + * Normalize a 4-D vector + * NOTE: + * The result is unpredictable when all elements of vec are at or near zero. + */ +static inline VmathSoaVector4 vmathSoaV4Normalize_V( VmathSoaVector4 vec ); + +/* + * Outer product of two 4-D vectors + */ +static inline VmathSoaMatrix4 vmathSoaV4Outer_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Linear interpolation between two 4-D vectors + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathSoaVector4 vmathSoaV4Lerp_V( vec_float4 t, VmathSoaVector4 vec0, VmathSoaVector4 vec1 ); + +/* + * Spherical linear interpolation between two 4-D vectors + * NOTE: + * The result is unpredictable if the vectors point in opposite directions. + * Does not clamp t between 0 and 1. + */ +static inline VmathSoaVector4 vmathSoaV4Slerp_V( vec_float4 t, VmathSoaVector4 unitVec0, VmathSoaVector4 unitVec1 ); + +/* + * Conditionally select between two 4-D vectors + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathSoaVector4 vmathSoaV4Select_V( VmathSoaVector4 vec0, VmathSoaVector4 vec1, vec_uint4 select1 ); + +/* + * Store four slots of an SoA 4-D vector as half-floats + */ +static inline void vmathSoaV4StoreHalfFloats_V( VmathSoaVector4 vec, vec_ushort8 *twoQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4-D vector + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaV4Print_V( VmathSoaVector4 vec ); + +/* + * Print a 4-D vector and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaV4Prints_V( VmathSoaVector4 vec, const char *name ); + +#endif + +/* + * Construct a 3-D point from x, y, and z elements + */ +static inline VmathSoaPoint3 vmathSoaP3MakeFromElems_V( vec_float4 x, vec_float4 y, vec_float4 z ); + +/* + * Copy elements from a 3-D vector into a 3-D point + */ +static inline VmathSoaPoint3 vmathSoaP3MakeFromV3_V( VmathSoaVector3 vec ); + +/* + * Set all elements of a 3-D point to the same scalar value + */ +static inline VmathSoaPoint3 vmathSoaP3MakeFromScalar_V( vec_float4 scalar ); + +/* + * Replicate an AoS 3-D point + */ +static inline VmathSoaPoint3 vmathSoaP3MakeFromAos_V( VmathPoint3 pnt ); + +/* + * Insert four AoS 3-D points + */ +static inline VmathSoaPoint3 vmathSoaP3MakeFrom4Aos_V( VmathPoint3 pnt0, VmathPoint3 pnt1, VmathPoint3 pnt2, VmathPoint3 pnt3 ); + +/* + * Extract four AoS 3-D points + */ +static inline void vmathSoaP3Get4Aos_V( VmathSoaPoint3 pnt, VmathPoint3 *result0, VmathPoint3 *result1, VmathPoint3 *result2, VmathPoint3 *result3 ); + +/* + * Set the x element of a 3-D point + */ +static inline void vmathSoaP3SetX_V( VmathSoaPoint3 *result, vec_float4 x ); + +/* + * Set the y element of a 3-D point + */ +static inline void vmathSoaP3SetY_V( VmathSoaPoint3 *result, vec_float4 y ); + +/* + * Set the z element of a 3-D point + */ +static inline void vmathSoaP3SetZ_V( VmathSoaPoint3 *result, vec_float4 z ); + +/* + * Get the x element of a 3-D point + */ +static inline vec_float4 vmathSoaP3GetX_V( VmathSoaPoint3 pnt ); + +/* + * Get the y element of a 3-D point + */ +static inline vec_float4 vmathSoaP3GetY_V( VmathSoaPoint3 pnt ); + +/* + * Get the z element of a 3-D point + */ +static inline vec_float4 vmathSoaP3GetZ_V( VmathSoaPoint3 pnt ); + +/* + * Set an x, y, or z element of a 3-D point by index + */ +static inline void vmathSoaP3SetElem_V( VmathSoaPoint3 *result, int idx, vec_float4 value ); + +/* + * Get an x, y, or z element of a 3-D point by index + */ +static inline vec_float4 vmathSoaP3GetElem_V( VmathSoaPoint3 pnt, int idx ); + +/* + * Subtract a 3-D point from another 3-D point + */ +static inline VmathSoaVector3 vmathSoaP3Sub_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Add a 3-D point to a 3-D vector + */ +static inline VmathSoaPoint3 vmathSoaP3AddV3_V( VmathSoaPoint3 pnt, VmathSoaVector3 vec ); + +/* + * Subtract a 3-D vector from a 3-D point + */ +static inline VmathSoaPoint3 vmathSoaP3SubV3_V( VmathSoaPoint3 pnt, VmathSoaVector3 vec ); + +/* + * Multiply two 3-D points per element + */ +static inline VmathSoaPoint3 vmathSoaP3MulPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Divide two 3-D points per element + * NOTE: + * Floating-point behavior matches standard library function divf4. + */ +static inline VmathSoaPoint3 vmathSoaP3DivPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Compute the reciprocal of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function recipf4. + */ +static inline VmathSoaPoint3 vmathSoaP3RecipPerElem_V( VmathSoaPoint3 pnt ); + +/* + * Compute the square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function sqrtf4. + */ +static inline VmathSoaPoint3 vmathSoaP3SqrtPerElem_V( VmathSoaPoint3 pnt ); + +/* + * Compute the reciprocal square root of a 3-D point per element + * NOTE: + * Floating-point behavior matches standard library function rsqrtf4. + */ +static inline VmathSoaPoint3 vmathSoaP3RsqrtPerElem_V( VmathSoaPoint3 pnt ); + +/* + * Compute the absolute value of a 3-D point per element + */ +static inline VmathSoaPoint3 vmathSoaP3AbsPerElem_V( VmathSoaPoint3 pnt ); + +/* + * Copy sign from one 3-D point to another, per element + */ +static inline VmathSoaPoint3 vmathSoaP3CopySignPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Maximum of two 3-D points per element + */ +static inline VmathSoaPoint3 vmathSoaP3MaxPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Minimum of two 3-D points per element + */ +static inline VmathSoaPoint3 vmathSoaP3MinPerElem_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Maximum element of a 3-D point + */ +static inline vec_float4 vmathSoaP3MaxElem_V( VmathSoaPoint3 pnt ); + +/* + * Minimum element of a 3-D point + */ +static inline vec_float4 vmathSoaP3MinElem_V( VmathSoaPoint3 pnt ); + +/* + * Compute the sum of all elements of a 3-D point + */ +static inline vec_float4 vmathSoaP3Sum_V( VmathSoaPoint3 pnt ); + +/* + * Apply uniform scale to a 3-D point + */ +static inline VmathSoaPoint3 vmathSoaP3Scale_V( VmathSoaPoint3 pnt, vec_float4 scaleVal ); + +/* + * Apply non-uniform scale to a 3-D point + */ +static inline VmathSoaPoint3 vmathSoaP3NonUniformScale_V( VmathSoaPoint3 pnt, VmathSoaVector3 scaleVec ); + +/* + * Scalar projection of a 3-D point on a unit-length 3-D vector + */ +static inline vec_float4 vmathSoaP3Projection_V( VmathSoaPoint3 pnt, VmathSoaVector3 unitVec ); + +/* + * Compute the square of the distance of a 3-D point from the coordinate-system origin + */ +static inline vec_float4 vmathSoaP3DistSqrFromOrigin_V( VmathSoaPoint3 pnt ); + +/* + * Compute the distance of a 3-D point from the coordinate-system origin + */ +static inline vec_float4 vmathSoaP3DistFromOrigin_V( VmathSoaPoint3 pnt ); + +/* + * Compute the square of the distance between two 3-D points + */ +static inline vec_float4 vmathSoaP3DistSqr_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Compute the distance between two 3-D points + */ +static inline vec_float4 vmathSoaP3Dist_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Linear interpolation between two 3-D points + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathSoaPoint3 vmathSoaP3Lerp_V( vec_float4 t, VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1 ); + +/* + * Conditionally select between two 3-D points + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathSoaPoint3 vmathSoaP3Select_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1, vec_uint4 select1 ); + +/* + * Load four three-float 3-D points, stored in three quadwords + */ +static inline void vmathSoaP3LoadXYZArray_V( VmathSoaPoint3 *pnt, const vec_float4 *threeQuads ); + +/* + * Store four slots of an SoA 3-D point in three quadwords + */ +static inline void vmathSoaP3StoreXYZArray_V( VmathSoaPoint3 pnt, vec_float4 *threeQuads ); + +/* + * Store eight slots of two SoA 3-D points as half-floats + */ +static inline void vmathSoaP3StoreHalfFloats_V( VmathSoaPoint3 pnt0, VmathSoaPoint3 pnt1, vec_ushort8 *threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3-D point + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaP3Print_V( VmathSoaPoint3 pnt ); + +/* + * Print a 3-D point and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaP3Prints_V( VmathSoaPoint3 pnt, const char *name ); + +#endif + +/* + * Construct a quaternion from x, y, z, and w elements + */ +static inline VmathSoaQuat vmathSoaQMakeFromElems_V( vec_float4 x, vec_float4 y, vec_float4 z, vec_float4 w ); + +/* + * Construct a quaternion from a 3-D vector and a scalar + */ +static inline VmathSoaQuat vmathSoaQMakeFromV3Scalar_V( VmathSoaVector3 xyz, vec_float4 w ); + +/* + * Copy elements from a 4-D vector into a quaternion + */ +static inline VmathSoaQuat vmathSoaQMakeFromV4_V( VmathSoaVector4 vec ); + +/* + * Convert a rotation matrix to a unit-length quaternion + */ +static inline VmathSoaQuat vmathSoaQMakeFromM3_V( VmathSoaMatrix3 rotMat ); + +/* + * Set all elements of a quaternion to the same scalar value + */ +static inline VmathSoaQuat vmathSoaQMakeFromScalar_V( vec_float4 scalar ); + +/* + * Replicate an AoS quaternion + */ +static inline VmathSoaQuat vmathSoaQMakeFromAos_V( VmathQuat quat ); + +/* + * Insert four AoS quaternions + */ +static inline VmathSoaQuat vmathSoaQMakeFrom4Aos_V( VmathQuat quat0, VmathQuat quat1, VmathQuat quat2, VmathQuat quat3 ); + +/* + * Extract four AoS quaternions + */ +static inline void vmathSoaQGet4Aos_V( VmathSoaQuat quat, VmathQuat *result0, VmathQuat *result1, VmathQuat *result2, VmathQuat *result3 ); + +/* + * Set the x, y, and z elements of a quaternion + * NOTE: + * This function does not change the w element. + */ +static inline void vmathSoaQSetXYZ_V( VmathSoaQuat *result, VmathSoaVector3 vec ); + +/* + * Get the x, y, and z elements of a quaternion + */ +static inline VmathSoaVector3 vmathSoaQGetXYZ_V( VmathSoaQuat quat ); + +/* + * Set the x element of a quaternion + */ +static inline void vmathSoaQSetX_V( VmathSoaQuat *result, vec_float4 x ); + +/* + * Set the y element of a quaternion + */ +static inline void vmathSoaQSetY_V( VmathSoaQuat *result, vec_float4 y ); + +/* + * Set the z element of a quaternion + */ +static inline void vmathSoaQSetZ_V( VmathSoaQuat *result, vec_float4 z ); + +/* + * Set the w element of a quaternion + */ +static inline void vmathSoaQSetW_V( VmathSoaQuat *result, vec_float4 w ); + +/* + * Get the x element of a quaternion + */ +static inline vec_float4 vmathSoaQGetX_V( VmathSoaQuat quat ); + +/* + * Get the y element of a quaternion + */ +static inline vec_float4 vmathSoaQGetY_V( VmathSoaQuat quat ); + +/* + * Get the z element of a quaternion + */ +static inline vec_float4 vmathSoaQGetZ_V( VmathSoaQuat quat ); + +/* + * Get the w element of a quaternion + */ +static inline vec_float4 vmathSoaQGetW_V( VmathSoaQuat quat ); + +/* + * Set an x, y, z, or w element of a quaternion by index + */ +static inline void vmathSoaQSetElem_V( VmathSoaQuat *result, int idx, vec_float4 value ); + +/* + * Get an x, y, z, or w element of a quaternion by index + */ +static inline vec_float4 vmathSoaQGetElem_V( VmathSoaQuat quat, int idx ); + +/* + * Add two quaternions + */ +static inline VmathSoaQuat vmathSoaQAdd_V( VmathSoaQuat quat0, VmathSoaQuat quat1 ); + +/* + * Subtract a quaternion from another quaternion + */ +static inline VmathSoaQuat vmathSoaQSub_V( VmathSoaQuat quat0, VmathSoaQuat quat1 ); + +/* + * Multiply two quaternions + */ +static inline VmathSoaQuat vmathSoaQMul_V( VmathSoaQuat quat0, VmathSoaQuat quat1 ); + +/* + * Multiply a quaternion by a scalar + */ +static inline VmathSoaQuat vmathSoaQScalarMul_V( VmathSoaQuat quat, vec_float4 scalar ); + +/* + * Divide a quaternion by a scalar + */ +static inline VmathSoaQuat vmathSoaQScalarDiv_V( VmathSoaQuat quat, vec_float4 scalar ); + +/* + * Negate all elements of a quaternion + */ +static inline VmathSoaQuat vmathSoaQNeg_V( VmathSoaQuat quat ); + +/* + * Construct an identity quaternion + */ +static inline VmathSoaQuat vmathSoaQMakeIdentity_V( ); + +/* + * Construct a quaternion to rotate between two unit-length 3-D vectors + * NOTE: + * The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + */ +static inline VmathSoaQuat vmathSoaQMakeRotationArc_V( VmathSoaVector3 unitVec0, VmathSoaVector3 unitVec1 ); + +/* + * Construct a quaternion to rotate around a unit-length 3-D vector + */ +static inline VmathSoaQuat vmathSoaQMakeRotationAxis_V( vec_float4 radians, VmathSoaVector3 unitVec ); + +/* + * Construct a quaternion to rotate around the x axis + */ +static inline VmathSoaQuat vmathSoaQMakeRotationX_V( vec_float4 radians ); + +/* + * Construct a quaternion to rotate around the y axis + */ +static inline VmathSoaQuat vmathSoaQMakeRotationY_V( vec_float4 radians ); + +/* + * Construct a quaternion to rotate around the z axis + */ +static inline VmathSoaQuat vmathSoaQMakeRotationZ_V( vec_float4 radians ); + +/* + * Compute the conjugate of a quaternion + */ +static inline VmathSoaQuat vmathSoaQConj_V( VmathSoaQuat quat ); + +/* + * Use a unit-length quaternion to rotate a 3-D vector + */ +static inline VmathSoaVector3 vmathSoaQRotate_V( VmathSoaQuat unitQuat, VmathSoaVector3 vec ); + +/* + * Compute the dot product of two quaternions + */ +static inline vec_float4 vmathSoaQDot_V( VmathSoaQuat quat0, VmathSoaQuat quat1 ); + +/* + * Compute the norm of a quaternion + */ +static inline vec_float4 vmathSoaQNorm_V( VmathSoaQuat quat ); + +/* + * Compute the length of a quaternion + */ +static inline vec_float4 vmathSoaQLength_V( VmathSoaQuat quat ); + +/* + * Normalize a quaternion + * NOTE: + * The result is unpredictable when all elements of quat are at or near zero. + */ +static inline VmathSoaQuat vmathSoaQNormalize_V( VmathSoaQuat quat ); + +/* + * Linear interpolation between two quaternions + * NOTE: + * Does not clamp t between 0 and 1. + */ +static inline VmathSoaQuat vmathSoaQLerp_V( vec_float4 t, VmathSoaQuat quat0, VmathSoaQuat quat1 ); + +/* + * Spherical linear interpolation between two quaternions + * NOTE: + * Interpolates along the shortest path between orientations. + * Does not clamp t between 0 and 1. + */ +static inline VmathSoaQuat vmathSoaQSlerp_V( vec_float4 t, VmathSoaQuat unitQuat0, VmathSoaQuat unitQuat1 ); + +/* + * Spherical quadrangle interpolation + */ +static inline VmathSoaQuat vmathSoaQSquad_V( vec_float4 t, VmathSoaQuat unitQuat0, VmathSoaQuat unitQuat1, VmathSoaQuat unitQuat2, VmathSoaQuat unitQuat3 ); + +/* + * Conditionally select between two quaternions + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathSoaQuat vmathSoaQSelect_V( VmathSoaQuat quat0, VmathSoaQuat quat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a quaternion + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaQPrint_V( VmathSoaQuat quat ); + +/* + * Print a quaternion and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaQPrints_V( VmathSoaQuat quat, const char *name ); + +#endif + +/* + * Construct a 3x3 matrix containing the specified columns + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeFromCols_V( VmathSoaVector3 col0, VmathSoaVector3 col1, VmathSoaVector3 col2 ); + +/* + * Construct a 3x3 rotation matrix from a unit-length quaternion + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeFromQ_V( VmathSoaQuat unitQuat ); + +/* + * Set all elements of a 3x3 matrix to the same scalar value + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeFromScalar_V( vec_float4 scalar ); + +/* + * Replicate an AoS 3x3 matrix + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeFromAos_V( VmathMatrix3 mat ); + +/* + * Insert four AoS 3x3 matrices + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeFrom4Aos_V( VmathMatrix3 mat0, VmathMatrix3 mat1, VmathMatrix3 mat2, VmathMatrix3 mat3 ); + +/* + * Extract four AoS 3x3 matrices + */ +static inline void vmathSoaM3Get4Aos_V( VmathSoaMatrix3 mat, VmathMatrix3 *result0, VmathMatrix3 *result1, VmathMatrix3 *result2, VmathMatrix3 *result3 ); + +/* + * Set column 0 of a 3x3 matrix + */ +static inline void vmathSoaM3SetCol0_V( VmathSoaMatrix3 *result, VmathSoaVector3 col0 ); + +/* + * Set column 1 of a 3x3 matrix + */ +static inline void vmathSoaM3SetCol1_V( VmathSoaMatrix3 *result, VmathSoaVector3 col1 ); + +/* + * Set column 2 of a 3x3 matrix + */ +static inline void vmathSoaM3SetCol2_V( VmathSoaMatrix3 *result, VmathSoaVector3 col2 ); + +/* + * Get column 0 of a 3x3 matrix + */ +static inline VmathSoaVector3 vmathSoaM3GetCol0_V( VmathSoaMatrix3 mat ); + +/* + * Get column 1 of a 3x3 matrix + */ +static inline VmathSoaVector3 vmathSoaM3GetCol1_V( VmathSoaMatrix3 mat ); + +/* + * Get column 2 of a 3x3 matrix + */ +static inline VmathSoaVector3 vmathSoaM3GetCol2_V( VmathSoaMatrix3 mat ); + +/* + * Set the column of a 3x3 matrix referred to by the specified index + */ +static inline void vmathSoaM3SetCol_V( VmathSoaMatrix3 *result, int col, VmathSoaVector3 vec ); + +/* + * Set the row of a 3x3 matrix referred to by the specified index + */ +static inline void vmathSoaM3SetRow_V( VmathSoaMatrix3 *result, int row, VmathSoaVector3 vec ); + +/* + * Get the column of a 3x3 matrix referred to by the specified index + */ +static inline VmathSoaVector3 vmathSoaM3GetCol_V( VmathSoaMatrix3 mat, int col ); + +/* + * Get the row of a 3x3 matrix referred to by the specified index + */ +static inline VmathSoaVector3 vmathSoaM3GetRow_V( VmathSoaMatrix3 mat, int row ); + +/* + * Set the element of a 3x3 matrix referred to by column and row indices + */ +static inline void vmathSoaM3SetElem_V( VmathSoaMatrix3 *result, int col, int row, vec_float4 val ); + +/* + * Get the element of a 3x3 matrix referred to by column and row indices + */ +static inline vec_float4 vmathSoaM3GetElem_V( VmathSoaMatrix3 mat, int col, int row ); + +/* + * Add two 3x3 matrices + */ +static inline VmathSoaMatrix3 vmathSoaM3Add_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1 ); + +/* + * Subtract a 3x3 matrix from another 3x3 matrix + */ +static inline VmathSoaMatrix3 vmathSoaM3Sub_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1 ); + +/* + * Negate all elements of a 3x3 matrix + */ +static inline VmathSoaMatrix3 vmathSoaM3Neg_V( VmathSoaMatrix3 mat ); + +/* + * Multiply a 3x3 matrix by a scalar + */ +static inline VmathSoaMatrix3 vmathSoaM3ScalarMul_V( VmathSoaMatrix3 mat, vec_float4 scalar ); + +/* + * Multiply a 3x3 matrix by a 3-D vector + */ +static inline VmathSoaVector3 vmathSoaM3MulV3_V( VmathSoaMatrix3 mat, VmathSoaVector3 vec ); + +/* + * Multiply two 3x3 matrices + */ +static inline VmathSoaMatrix3 vmathSoaM3Mul_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1 ); + +/* + * Construct an identity 3x3 matrix + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeIdentity_V( ); + +/* + * Construct a 3x3 matrix to rotate around the x axis + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationX_V( vec_float4 radians ); + +/* + * Construct a 3x3 matrix to rotate around the y axis + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationY_V( vec_float4 radians ); + +/* + * Construct a 3x3 matrix to rotate around the z axis + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationZ_V( vec_float4 radians ); + +/* + * Construct a 3x3 matrix to rotate around the x, y, and z axes + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationZYX_V( VmathSoaVector3 radiansXYZ ); + +/* + * Construct a 3x3 matrix to rotate around a unit-length 3-D vector + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationAxis_V( vec_float4 radians, VmathSoaVector3 unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeRotationQ_V( VmathSoaQuat unitQuat ); + +/* + * Construct a 3x3 matrix to perform scaling + */ +static inline VmathSoaMatrix3 vmathSoaM3MakeScale_V( VmathSoaVector3 scaleVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathSoaMatrix3 vmathSoaM3AppendScale_V( VmathSoaMatrix3 mat, VmathSoaVector3 scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x3 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathSoaMatrix3 vmathSoaM3PrependScale_V( VmathSoaVector3 scaleVec, VmathSoaMatrix3 mat ); + +/* + * Multiply two 3x3 matrices per element + */ +static inline VmathSoaMatrix3 vmathSoaM3MulPerElem_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1 ); + +/* + * Compute the absolute value of a 3x3 matrix per element + */ +static inline VmathSoaMatrix3 vmathSoaM3AbsPerElem_V( VmathSoaMatrix3 mat ); + +/* + * Transpose of a 3x3 matrix + */ +static inline VmathSoaMatrix3 vmathSoaM3Transpose_V( VmathSoaMatrix3 mat ); + +/* + * Compute the inverse of a 3x3 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline VmathSoaMatrix3 vmathSoaM3Inverse_V( VmathSoaMatrix3 mat ); + +/* + * Determinant of a 3x3 matrix + */ +static inline vec_float4 vmathSoaM3Determinant_V( VmathSoaMatrix3 mat ); + +/* + * Conditionally select between two 3x3 matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathSoaMatrix3 vmathSoaM3Select_V( VmathSoaMatrix3 mat0, VmathSoaMatrix3 mat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x3 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaM3Print_V( VmathSoaMatrix3 mat ); + +/* + * Print a 3x3 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaM3Prints_V( VmathSoaMatrix3 mat, const char *name ); + +#endif + +/* + * Construct a 4x4 matrix containing the specified columns + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeFromCols_V( VmathSoaVector4 col0, VmathSoaVector4 col1, VmathSoaVector4 col2, VmathSoaVector4 col3 ); + +/* + * Construct a 4x4 matrix from a 3x4 transformation matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeFromT3_V( VmathSoaTransform3 mat ); + +/* + * Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeFromM3V3_V( VmathSoaMatrix3 mat, VmathSoaVector3 translateVec ); + +/* + * Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeFromQV3_V( VmathSoaQuat unitQuat, VmathSoaVector3 translateVec ); + +/* + * Set all elements of a 4x4 matrix to the same scalar value + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeFromScalar_V( vec_float4 scalar ); + +/* + * Replicate an AoS 4x4 matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeFromAos_V( VmathMatrix4 mat ); + +/* + * Insert four AoS 4x4 matrices + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeFrom4Aos_V( VmathMatrix4 mat0, VmathMatrix4 mat1, VmathMatrix4 mat2, VmathMatrix4 mat3 ); + +/* + * Extract four AoS 4x4 matrices + */ +static inline void vmathSoaM4Get4Aos_V( VmathSoaMatrix4 mat, VmathMatrix4 *result0, VmathMatrix4 *result1, VmathMatrix4 *result2, VmathMatrix4 *result3 ); + +/* + * Set the upper-left 3x3 submatrix + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathSoaM4SetUpper3x3_V( VmathSoaMatrix4 *result, VmathSoaMatrix3 mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 4x4 matrix + */ +static inline VmathSoaMatrix3 vmathSoaM4GetUpper3x3_V( VmathSoaMatrix4 mat ); + +/* + * Set translation component + * NOTE: + * This function does not change the bottom row elements. + */ +static inline void vmathSoaM4SetTranslation_V( VmathSoaMatrix4 *result, VmathSoaVector3 translateVec ); + +/* + * Get the translation component of a 4x4 matrix + */ +static inline VmathSoaVector3 vmathSoaM4GetTranslation_V( VmathSoaMatrix4 mat ); + +/* + * Set column 0 of a 4x4 matrix + */ +static inline void vmathSoaM4SetCol0_V( VmathSoaMatrix4 *result, VmathSoaVector4 col0 ); + +/* + * Set column 1 of a 4x4 matrix + */ +static inline void vmathSoaM4SetCol1_V( VmathSoaMatrix4 *result, VmathSoaVector4 col1 ); + +/* + * Set column 2 of a 4x4 matrix + */ +static inline void vmathSoaM4SetCol2_V( VmathSoaMatrix4 *result, VmathSoaVector4 col2 ); + +/* + * Set column 3 of a 4x4 matrix + */ +static inline void vmathSoaM4SetCol3_V( VmathSoaMatrix4 *result, VmathSoaVector4 col3 ); + +/* + * Get column 0 of a 4x4 matrix + */ +static inline VmathSoaVector4 vmathSoaM4GetCol0_V( VmathSoaMatrix4 mat ); + +/* + * Get column 1 of a 4x4 matrix + */ +static inline VmathSoaVector4 vmathSoaM4GetCol1_V( VmathSoaMatrix4 mat ); + +/* + * Get column 2 of a 4x4 matrix + */ +static inline VmathSoaVector4 vmathSoaM4GetCol2_V( VmathSoaMatrix4 mat ); + +/* + * Get column 3 of a 4x4 matrix + */ +static inline VmathSoaVector4 vmathSoaM4GetCol3_V( VmathSoaMatrix4 mat ); + +/* + * Set the column of a 4x4 matrix referred to by the specified index + */ +static inline void vmathSoaM4SetCol_V( VmathSoaMatrix4 *result, int col, VmathSoaVector4 vec ); + +/* + * Set the row of a 4x4 matrix referred to by the specified index + */ +static inline void vmathSoaM4SetRow_V( VmathSoaMatrix4 *result, int row, VmathSoaVector4 vec ); + +/* + * Get the column of a 4x4 matrix referred to by the specified index + */ +static inline VmathSoaVector4 vmathSoaM4GetCol_V( VmathSoaMatrix4 mat, int col ); + +/* + * Get the row of a 4x4 matrix referred to by the specified index + */ +static inline VmathSoaVector4 vmathSoaM4GetRow_V( VmathSoaMatrix4 mat, int row ); + +/* + * Set the element of a 4x4 matrix referred to by column and row indices + */ +static inline void vmathSoaM4SetElem_V( VmathSoaMatrix4 *result, int col, int row, vec_float4 val ); + +/* + * Get the element of a 4x4 matrix referred to by column and row indices + */ +static inline vec_float4 vmathSoaM4GetElem_V( VmathSoaMatrix4 mat, int col, int row ); + +/* + * Add two 4x4 matrices + */ +static inline VmathSoaMatrix4 vmathSoaM4Add_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1 ); + +/* + * Subtract a 4x4 matrix from another 4x4 matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4Sub_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1 ); + +/* + * Negate all elements of a 4x4 matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4Neg_V( VmathSoaMatrix4 mat ); + +/* + * Multiply a 4x4 matrix by a scalar + */ +static inline VmathSoaMatrix4 vmathSoaM4ScalarMul_V( VmathSoaMatrix4 mat, vec_float4 scalar ); + +/* + * Multiply a 4x4 matrix by a 4-D vector + */ +static inline VmathSoaVector4 vmathSoaM4MulV4_V( VmathSoaMatrix4 mat, VmathSoaVector4 vec ); + +/* + * Multiply a 4x4 matrix by a 3-D vector + */ +static inline VmathSoaVector4 vmathSoaM4MulV3_V( VmathSoaMatrix4 mat, VmathSoaVector3 vec ); + +/* + * Multiply a 4x4 matrix by a 3-D point + */ +static inline VmathSoaVector4 vmathSoaM4MulP3_V( VmathSoaMatrix4 mat, VmathSoaPoint3 pnt ); + +/* + * Multiply two 4x4 matrices + */ +static inline VmathSoaMatrix4 vmathSoaM4Mul_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1 ); + +/* + * Multiply a 4x4 matrix by a 3x4 transformation matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4MulT3_V( VmathSoaMatrix4 mat, VmathSoaTransform3 tfrm ); + +/* + * Construct an identity 4x4 matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeIdentity_V( ); + +/* + * Construct a 4x4 matrix to rotate around the x axis + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationX_V( vec_float4 radians ); + +/* + * Construct a 4x4 matrix to rotate around the y axis + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationY_V( vec_float4 radians ); + +/* + * Construct a 4x4 matrix to rotate around the z axis + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationZ_V( vec_float4 radians ); + +/* + * Construct a 4x4 matrix to rotate around the x, y, and z axes + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationZYX_V( VmathSoaVector3 radiansXYZ ); + +/* + * Construct a 4x4 matrix to rotate around a unit-length 3-D vector + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationAxis_V( vec_float4 radians, VmathSoaVector3 unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeRotationQ_V( VmathSoaQuat unitQuat ); + +/* + * Construct a 4x4 matrix to perform scaling + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeScale_V( VmathSoaVector3 scaleVec ); + +/* + * Construct a 4x4 matrix to perform translation + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeTranslation_V( VmathSoaVector3 translateVec ); + +/* + * Construct viewing matrix based on eye position, position looked at, and up direction + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeLookAt_V( VmathSoaPoint3 eyePos, VmathSoaPoint3 lookAtPos, VmathSoaVector3 upVec ); + +/* + * Construct a perspective projection matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4MakePerspective_V( vec_float4 fovyRadians, vec_float4 aspect, vec_float4 zNear, vec_float4 zFar ); + +/* + * Construct a perspective projection matrix based on frustum + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeFrustum_V( vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ); + +/* + * Construct an orthographic projection matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4MakeOrthographic_V( vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ); + +/* + * Append (post-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathSoaMatrix4 vmathSoaM4AppendScale_V( VmathSoaMatrix4 mat, VmathSoaVector3 scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 4x4 matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathSoaMatrix4 vmathSoaM4PrependScale_V( VmathSoaVector3 scaleVec, VmathSoaMatrix4 mat ); + +/* + * Multiply two 4x4 matrices per element + */ +static inline VmathSoaMatrix4 vmathSoaM4MulPerElem_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1 ); + +/* + * Compute the absolute value of a 4x4 matrix per element + */ +static inline VmathSoaMatrix4 vmathSoaM4AbsPerElem_V( VmathSoaMatrix4 mat ); + +/* + * Transpose of a 4x4 matrix + */ +static inline VmathSoaMatrix4 vmathSoaM4Transpose_V( VmathSoaMatrix4 mat ); + +/* + * Compute the inverse of a 4x4 matrix + * NOTE: + * Result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline VmathSoaMatrix4 vmathSoaM4Inverse_V( VmathSoaMatrix4 mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. + */ +static inline VmathSoaMatrix4 vmathSoaM4AffineInverse_V( VmathSoaMatrix4 mat ); + +/* + * Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. + */ +static inline VmathSoaMatrix4 vmathSoaM4OrthoInverse_V( VmathSoaMatrix4 mat ); + +/* + * Determinant of a 4x4 matrix + */ +static inline vec_float4 vmathSoaM4Determinant_V( VmathSoaMatrix4 mat ); + +/* + * Conditionally select between two 4x4 matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathSoaMatrix4 vmathSoaM4Select_V( VmathSoaMatrix4 mat0, VmathSoaMatrix4 mat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 4x4 matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaM4Print_V( VmathSoaMatrix4 mat ); + +/* + * Print a 4x4 matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaM4Prints_V( VmathSoaMatrix4 mat, const char *name ); + +#endif + +/* + * Construct a 3x4 transformation matrix containing the specified columns + */ +static inline VmathSoaTransform3 vmathSoaT3MakeFromCols_V( VmathSoaVector3 col0, VmathSoaVector3 col1, VmathSoaVector3 col2, VmathSoaVector3 col3 ); + +/* + * Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + */ +static inline VmathSoaTransform3 vmathSoaT3MakeFromM3V3_V( VmathSoaMatrix3 tfrm, VmathSoaVector3 translateVec ); + +/* + * Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + */ +static inline VmathSoaTransform3 vmathSoaT3MakeFromQV3_V( VmathSoaQuat unitQuat, VmathSoaVector3 translateVec ); + +/* + * Set all elements of a 3x4 transformation matrix to the same scalar value + */ +static inline VmathSoaTransform3 vmathSoaT3MakeFromScalar_V( vec_float4 scalar ); + +/* + * Replicate an AoS 3x4 transformation matrix + */ +static inline VmathSoaTransform3 vmathSoaT3MakeFromAos_V( VmathTransform3 tfrm ); + +/* + * Insert four AoS 3x4 transformation matrices + */ +static inline VmathSoaTransform3 vmathSoaT3MakeFrom4Aos_V( VmathTransform3 tfrm0, VmathTransform3 tfrm1, VmathTransform3 tfrm2, VmathTransform3 tfrm3 ); + +/* + * Extract four AoS 3x4 transformation matrices + */ +static inline void vmathSoaT3Get4Aos_V( VmathSoaTransform3 tfrm, VmathTransform3 *result0, VmathTransform3 *result1, VmathTransform3 *result2, VmathTransform3 *result3 ); + +/* + * Set the upper-left 3x3 submatrix + */ +static inline void vmathSoaT3SetUpper3x3_V( VmathSoaTransform3 *result, VmathSoaMatrix3 mat3 ); + +/* + * Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + */ +static inline VmathSoaMatrix3 vmathSoaT3GetUpper3x3_V( VmathSoaTransform3 tfrm ); + +/* + * Set translation component + */ +static inline void vmathSoaT3SetTranslation_V( VmathSoaTransform3 *result, VmathSoaVector3 translateVec ); + +/* + * Get the translation component of a 3x4 transformation matrix + */ +static inline VmathSoaVector3 vmathSoaT3GetTranslation_V( VmathSoaTransform3 tfrm ); + +/* + * Set column 0 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3SetCol0_V( VmathSoaTransform3 *result, VmathSoaVector3 col0 ); + +/* + * Set column 1 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3SetCol1_V( VmathSoaTransform3 *result, VmathSoaVector3 col1 ); + +/* + * Set column 2 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3SetCol2_V( VmathSoaTransform3 *result, VmathSoaVector3 col2 ); + +/* + * Set column 3 of a 3x4 transformation matrix + */ +static inline void vmathSoaT3SetCol3_V( VmathSoaTransform3 *result, VmathSoaVector3 col3 ); + +/* + * Get column 0 of a 3x4 transformation matrix + */ +static inline VmathSoaVector3 vmathSoaT3GetCol0_V( VmathSoaTransform3 tfrm ); + +/* + * Get column 1 of a 3x4 transformation matrix + */ +static inline VmathSoaVector3 vmathSoaT3GetCol1_V( VmathSoaTransform3 tfrm ); + +/* + * Get column 2 of a 3x4 transformation matrix + */ +static inline VmathSoaVector3 vmathSoaT3GetCol2_V( VmathSoaTransform3 tfrm ); + +/* + * Get column 3 of a 3x4 transformation matrix + */ +static inline VmathSoaVector3 vmathSoaT3GetCol3_V( VmathSoaTransform3 tfrm ); + +/* + * Set the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathSoaT3SetCol_V( VmathSoaTransform3 *result, int col, VmathSoaVector3 vec ); + +/* + * Set the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline void vmathSoaT3SetRow_V( VmathSoaTransform3 *result, int row, VmathSoaVector4 vec ); + +/* + * Get the column of a 3x4 transformation matrix referred to by the specified index + */ +static inline VmathSoaVector3 vmathSoaT3GetCol_V( VmathSoaTransform3 tfrm, int col ); + +/* + * Get the row of a 3x4 transformation matrix referred to by the specified index + */ +static inline VmathSoaVector4 vmathSoaT3GetRow_V( VmathSoaTransform3 tfrm, int row ); + +/* + * Set the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline void vmathSoaT3SetElem_V( VmathSoaTransform3 *result, int col, int row, vec_float4 val ); + +/* + * Get the element of a 3x4 transformation matrix referred to by column and row indices + */ +static inline vec_float4 vmathSoaT3GetElem_V( VmathSoaTransform3 tfrm, int col, int row ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D vector + */ +static inline VmathSoaVector3 vmathSoaT3MulV3_V( VmathSoaTransform3 tfrm, VmathSoaVector3 vec ); + +/* + * Multiply a 3x4 transformation matrix by a 3-D point + */ +static inline VmathSoaPoint3 vmathSoaT3MulP3_V( VmathSoaTransform3 tfrm, VmathSoaPoint3 pnt ); + +/* + * Multiply two 3x4 transformation matrices + */ +static inline VmathSoaTransform3 vmathSoaT3Mul_V( VmathSoaTransform3 tfrm0, VmathSoaTransform3 tfrm1 ); + +/* + * Construct an identity 3x4 transformation matrix + */ +static inline VmathSoaTransform3 vmathSoaT3MakeIdentity_V( ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x axis + */ +static inline VmathSoaTransform3 vmathSoaT3MakeRotationX_V( vec_float4 radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the y axis + */ +static inline VmathSoaTransform3 vmathSoaT3MakeRotationY_V( vec_float4 radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the z axis + */ +static inline VmathSoaTransform3 vmathSoaT3MakeRotationZ_V( vec_float4 radians ); + +/* + * Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + */ +static inline VmathSoaTransform3 vmathSoaT3MakeRotationZYX_V( VmathSoaVector3 radiansXYZ ); + +/* + * Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + */ +static inline VmathSoaTransform3 vmathSoaT3MakeRotationAxis_V( vec_float4 radians, VmathSoaVector3 unitVec ); + +/* + * Construct a rotation matrix from a unit-length quaternion + */ +static inline VmathSoaTransform3 vmathSoaT3MakeRotationQ_V( VmathSoaQuat unitQuat ); + +/* + * Construct a 3x4 transformation matrix to perform scaling + */ +static inline VmathSoaTransform3 vmathSoaT3MakeScale_V( VmathSoaVector3 scaleVec ); + +/* + * Construct a 3x4 transformation matrix to perform translation + */ +static inline VmathSoaTransform3 vmathSoaT3MakeTranslation_V( VmathSoaVector3 translateVec ); + +/* + * Append (post-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathSoaTransform3 vmathSoaT3AppendScale_V( VmathSoaTransform3 tfrm, VmathSoaVector3 scaleVec ); + +/* + * Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix + * NOTE: + * Faster than creating and multiplying a scale transformation matrix. + */ +static inline VmathSoaTransform3 vmathSoaT3PrependScale_V( VmathSoaVector3 scaleVec, VmathSoaTransform3 tfrm ); + +/* + * Multiply two 3x4 transformation matrices per element + */ +static inline VmathSoaTransform3 vmathSoaT3MulPerElem_V( VmathSoaTransform3 tfrm0, VmathSoaTransform3 tfrm1 ); + +/* + * Compute the absolute value of a 3x4 transformation matrix per element + */ +static inline VmathSoaTransform3 vmathSoaT3AbsPerElem_V( VmathSoaTransform3 tfrm ); + +/* + * Inverse of a 3x4 transformation matrix + * NOTE: + * Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. + */ +static inline VmathSoaTransform3 vmathSoaT3Inverse_V( VmathSoaTransform3 tfrm ); + +/* + * Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix + * NOTE: + * This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. + */ +static inline VmathSoaTransform3 vmathSoaT3OrthoInverse_V( VmathSoaTransform3 tfrm ); + +/* + * Conditionally select between two 3x4 transformation matrices + * NOTE: + * This function uses a conditional select instruction to avoid a branch. + */ +static inline VmathSoaTransform3 vmathSoaT3Select_V( VmathSoaTransform3 tfrm0, VmathSoaTransform3 tfrm1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +/* + * Print a 3x4 transformation matrix + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaT3Print_V( VmathSoaTransform3 tfrm ); + +/* + * Print a 3x4 transformation matrix and an associated string identifier + * NOTE: + * Function is only defined when _VECTORMATH_DEBUG is defined. + */ +static inline void vmathSoaT3Prints_V( VmathSoaTransform3 tfrm, const char *name ); + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#include "vectormath_soa.h" +#include "vec_soa_v.h" +#include "quat_soa_v.h" +#include "mat_soa_v.h" + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/cpp/boolInVec.h b/Extras/vectormathlibrary/include/vectormath/spu/cpp/boolInVec.h new file mode 100644 index 0000000..93a3ad2 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/cpp/boolInVec.h @@ -0,0 +1,246 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _BOOLINVEC_H +#define _BOOLINVEC_H + +#include + +namespace Vectormath { + +class floatInVec; + +//-------------------------------------------------------------------------------------------------- +// boolInVec class +// + +class boolInVec +{ + private: + vec_uint4 mData; + + inline boolInVec(vec_uint4 vec); + public: + inline boolInVec() {} + + // matches standard type conversions + // + inline boolInVec(floatInVec vec); + + // explicit cast from bool + // + explicit inline boolInVec(bool scalar); + +#ifdef _VECTORMATH_NO_SCALAR_CAST + // explicit cast to bool + // + inline bool getAsBool() const; +#else + // implicit cast to bool + // + inline operator bool() const; +#endif + + // get vector data + // bool value is in the 0 word slot of vector as 0 (false) or -1 (true) + // + inline vec_uint4 get128() const; + + // operators + // + inline const boolInVec operator ! () const; + inline boolInVec& operator = (boolInVec vec); + inline boolInVec& operator &= (boolInVec vec); + inline boolInVec& operator ^= (boolInVec vec); + inline boolInVec& operator |= (boolInVec vec); + + // friend functions + // + friend inline const boolInVec operator == (boolInVec vec0, boolInVec vec1); + friend inline const boolInVec operator != (boolInVec vec0, boolInVec vec1); + friend inline const boolInVec operator < (floatInVec vec0, floatInVec vec1); + friend inline const boolInVec operator <= (floatInVec vec0, floatInVec vec1); + friend inline const boolInVec operator > (floatInVec vec0, floatInVec vec1); + friend inline const boolInVec operator >= (floatInVec vec0, floatInVec vec1); + friend inline const boolInVec operator == (floatInVec vec0, floatInVec vec1); + friend inline const boolInVec operator != (floatInVec vec0, floatInVec vec1); + friend inline const boolInVec operator & (boolInVec vec0, boolInVec vec1); + friend inline const boolInVec operator ^ (boolInVec vec0, boolInVec vec1); + friend inline const boolInVec operator | (boolInVec vec0, boolInVec vec1); + friend inline const boolInVec select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1); +}; + +//-------------------------------------------------------------------------------------------------- +// boolInVec functions +// + +// operators +// +inline const boolInVec operator == (boolInVec vec0, boolInVec vec1); +inline const boolInVec operator != (boolInVec vec0, boolInVec vec1); +inline const boolInVec operator & (boolInVec vec0, boolInVec vec1); +inline const boolInVec operator ^ (boolInVec vec0, boolInVec vec1); +inline const boolInVec operator | (boolInVec vec0, boolInVec vec1); + +// select between vec0 and vec1 using boolInVec. +// false selects vec0, true selects vec1 +// +inline const boolInVec select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1); + +} // namespace Vectormath + +//-------------------------------------------------------------------------------------------------- +// boolInVec implementation +// + +#include "floatInVec.h" + +namespace Vectormath { + +inline +boolInVec::boolInVec(vec_uint4 vec) +{ + mData = vec; +} + +inline +boolInVec::boolInVec(floatInVec vec) +{ + *this = (vec != floatInVec(0.0f)); +} + +inline +boolInVec::boolInVec(bool scalar) +{ + mData = spu_promote((unsigned int)-scalar, 0); +} + +#ifdef _VECTORMATH_NO_SCALAR_CAST +inline +bool +boolInVec::getAsBool() const +#else +inline +boolInVec::operator bool() const +#endif +{ + return (bool)spu_extract(mData, 0); +} + +inline +vec_uint4 +boolInVec::get128() const +{ + return mData; +} + +inline +const boolInVec +boolInVec::operator ! () const +{ + return boolInVec(spu_nor(mData, mData)); +} + +inline +boolInVec& +boolInVec::operator = (boolInVec vec) +{ + mData = vec.mData; + return *this; +} + +inline +boolInVec& +boolInVec::operator &= (boolInVec vec) +{ + *this = *this & vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator ^= (boolInVec vec) +{ + *this = *this ^ vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator |= (boolInVec vec) +{ + *this = *this | vec; + return *this; +} + +inline +const boolInVec +operator == (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(spu_cmpeq(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator != (boolInVec vec0, boolInVec vec1) +{ + return !(vec0 == vec1); +} + +inline +const boolInVec +operator & (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(spu_and(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator | (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(spu_or(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator ^ (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(spu_xor(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1) +{ + return boolInVec(spu_sel(vec0.get128(), vec1.get128(), select_vec1.get128())); +} + +} // namespace Vectormath + +#endif // boolInVec_h diff --git a/Extras/vectormathlibrary/include/vectormath/spu/cpp/floatInVec.h b/Extras/vectormathlibrary/include/vectormath/spu/cpp/floatInVec.h new file mode 100644 index 0000000..7521c0c --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/cpp/floatInVec.h @@ -0,0 +1,339 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _FLOATINVEC_H +#define _FLOATINVEC_H + +#include +#include +#include +#undef bool + +namespace Vectormath { + +class boolInVec; + +//-------------------------------------------------------------------------------------------------- +// floatInVec class +// + +class floatInVec +{ + private: + vec_float4 mData; + + inline floatInVec(vec_float4 vec); + public: + inline floatInVec() {} + + // matches standard type conversions + // + inline floatInVec(boolInVec vec); + + // construct from a slot of vec_float4 + // + inline floatInVec(vec_float4 vec, int slot); + + // explicit cast from float + // + explicit inline floatInVec(float scalar); + +#ifdef _VECTORMATH_NO_SCALAR_CAST + // explicit cast to float + // + inline float getAsFloat() const; +#else + // implicit cast to float + // + inline operator float() const; +#endif + + // get vector data + // float value is in 0 word slot of vector + // + inline vec_float4 get128() const; + + // operators + // + inline const floatInVec operator ++ (int); + inline const floatInVec operator -- (int); + inline floatInVec& operator ++ (); + inline floatInVec& operator -- (); + inline const floatInVec operator - () const; + inline floatInVec& operator = (floatInVec vec); + inline floatInVec& operator *= (floatInVec vec); + inline floatInVec& operator /= (floatInVec vec); + inline floatInVec& operator += (floatInVec vec); + inline floatInVec& operator -= (floatInVec vec); + + // friend functions + // + friend inline const floatInVec operator * (floatInVec vec0, floatInVec vec1); + friend inline const floatInVec operator / (floatInVec vec0, floatInVec vec1); + friend inline const floatInVec operator + (floatInVec vec0, floatInVec vec1); + friend inline const floatInVec operator - (floatInVec vec0, floatInVec vec1); + friend inline const floatInVec select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1); +}; + +//-------------------------------------------------------------------------------------------------- +// floatInVec functions +// + +// operators +// +inline const floatInVec operator * (floatInVec vec0, floatInVec vec1); +inline const floatInVec operator / (floatInVec vec0, floatInVec vec1); +inline const floatInVec operator + (floatInVec vec0, floatInVec vec1); +inline const floatInVec operator - (floatInVec vec0, floatInVec vec1); +inline const boolInVec operator < (floatInVec vec0, floatInVec vec1); +inline const boolInVec operator <= (floatInVec vec0, floatInVec vec1); +inline const boolInVec operator > (floatInVec vec0, floatInVec vec1); +inline const boolInVec operator >= (floatInVec vec0, floatInVec vec1); +inline const boolInVec operator == (floatInVec vec0, floatInVec vec1); +inline const boolInVec operator != (floatInVec vec0, floatInVec vec1); + +// select between vec0 and vec1 using boolInVec. +// false selects vec0, true selects vec1 +// +inline const floatInVec select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1); + +} // namespace Vectormath + +//-------------------------------------------------------------------------------------------------- +// floatInVec implementation +// + +#include "boolInVec.h" + +namespace Vectormath { + +inline +floatInVec::floatInVec(vec_float4 vec) +{ + mData = vec; +} + +inline +floatInVec::floatInVec(boolInVec vec) +{ + mData = spu_sel(spu_splats(0.0f), spu_splats(1.0f), vec.get128()); +} + +inline +floatInVec::floatInVec(vec_float4 vec, int slot) +{ + mData = spu_promote(spu_extract(vec, slot), 0); +} + +inline +floatInVec::floatInVec(float scalar) +{ + mData = spu_promote(scalar, 0); +} + +#ifdef _VECTORMATH_NO_SCALAR_CAST +inline +float +floatInVec::getAsFloat() const +#else +inline +floatInVec::operator float() const +#endif +{ + return spu_extract(mData,0); +} + +inline +vec_float4 +floatInVec::get128() const +{ + return mData; +} + +inline +const floatInVec +floatInVec::operator ++ (int) +{ + vec_float4 olddata = mData; + operator ++(); + return floatInVec(olddata); +} + +inline +const floatInVec +floatInVec::operator -- (int) +{ + vec_float4 olddata = mData; + operator --(); + return floatInVec(olddata); +} + +inline +floatInVec& +floatInVec::operator ++ () +{ + *this += floatInVec(1.0f); + return *this; +} + +inline +floatInVec& +floatInVec::operator -- () +{ + *this -= floatInVec(1.0f); + return *this; +} + +inline +const floatInVec +floatInVec::operator - () const +{ + return floatInVec((vec_float4)spu_xor((vec_uint4)mData, spu_splats(0x80000000))); +} + +inline +floatInVec& +floatInVec::operator = (floatInVec vec) +{ + mData = vec.mData; + return *this; +} + +inline +floatInVec& +floatInVec::operator *= (floatInVec vec) +{ + *this = *this * vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator /= (floatInVec vec) +{ + *this = *this / vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator += (floatInVec vec) +{ + *this = *this + vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator -= (floatInVec vec) +{ + *this = *this - vec; + return *this; +} + +inline +const floatInVec +operator * (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(spu_mul(vec0.get128(), vec1.get128())); +} + +inline +const floatInVec +operator / (floatInVec num, floatInVec den) +{ + return floatInVec(divf4(num.get128(), den.get128())); +} + +inline +const floatInVec +operator + (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(spu_add(vec0.get128(), vec1.get128())); +} + +inline +const floatInVec +operator - (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(spu_sub(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator < (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(spu_cmpgt(vec1.get128(), vec0.get128())); +} + +inline +const boolInVec +operator <= (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 > vec1); +} + +inline +const boolInVec +operator > (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(spu_cmpgt(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator >= (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 < vec1); +} + +inline +const boolInVec +operator == (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(spu_cmpeq(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator != (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 == vec1); +} + +inline +const floatInVec +select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1) +{ + return floatInVec(spu_sel(vec0.get128(), vec1.get128(), select_vec1.get128())); +} + +} // namespace Vectormath + +#endif // floatInVec_h diff --git a/Extras/vectormathlibrary/include/vectormath/spu/cpp/mat_aos.h b/Extras/vectormathlibrary/include/vectormath/spu/cpp/mat_aos.h new file mode 100644 index 0000000..a2fd611 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/cpp/mat_aos.h @@ -0,0 +1,2027 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_AOS_CPP_H +#define _VECTORMATH_MAT_AOS_CPP_H + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// Constants +// for shuffles, words are labeled [x,y,z,w] [a,b,c,d] + +#define _VECTORMATH_SHUF_XAYB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_ZCWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_ZBW0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_XCY0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_XYAB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_ZWCD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_0ZB0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_C0X0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_YA00 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_XAZC ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_C }) +#define _VECTORMATH_SHUF_YXWZ ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_Z }) +#define _VECTORMATH_SHUF_YBWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_XYCX ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_X }) +#define _VECTORMATH_SHUF_YCXY ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y }) +#define _VECTORMATH_SHUF_CXYC ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_C }) +#define _VECTORMATH_SHUF_ZAY0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_BZX0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_0ZYA ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_A }) +#define _VECTORMATH_SHUF_Z0XB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_YX0C ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_0, _VECTORMATH_SHUF_C }) +#define _VECTORMATH_SHUF_CZD0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_D, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_BBY0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_PI_OVER_2 1.570796327f + +//----------------------------------------------------------------------------- +// Definitions + +inline Matrix3::Matrix3( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; +} + +inline Matrix3::Matrix3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +inline Matrix3::Matrix3( Quat unitQuat ) +{ + vec_float4 xyzw_2, wwww, yzxw, zxyw, yzxw_2, zxyw_2; + vec_float4 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + vec_uchar16 shuffle_wwww = (vec_uchar16)spu_splats((int)0x0c0d0e0f); + vec_uint4 select_x = (vec_uint4)spu_maskb(0xf000); + vec_uint4 select_z = (vec_uint4)spu_maskb(0x00f0); + xyzw_2 = spu_add( unitQuat.get128(), unitQuat.get128() ); + wwww = spu_shuffle( unitQuat.get128(), unitQuat.get128(), shuffle_wwww ); + yzxw = spu_shuffle( unitQuat.get128(), unitQuat.get128(), _VECTORMATH_SHUF_YZXW ); + zxyw = spu_shuffle( unitQuat.get128(), unitQuat.get128(), _VECTORMATH_SHUF_ZXYW ); + yzxw_2 = spu_shuffle( xyzw_2, xyzw_2, _VECTORMATH_SHUF_YZXW ); + zxyw_2 = spu_shuffle( xyzw_2, xyzw_2, _VECTORMATH_SHUF_ZXYW ); + tmp0 = spu_mul( yzxw_2, wwww ); + tmp1 = spu_nmsub( yzxw, yzxw_2, spu_splats(1.0f) ); + tmp2 = spu_mul( yzxw, xyzw_2 ); + tmp0 = spu_madd( zxyw, xyzw_2, tmp0 ); + tmp1 = spu_nmsub( zxyw, zxyw_2, tmp1 ); + tmp2 = spu_nmsub( zxyw_2, wwww, tmp2 ); + tmp3 = spu_sel( tmp0, tmp1, select_x ); + tmp4 = spu_sel( tmp1, tmp2, select_x ); + tmp5 = spu_sel( tmp2, tmp0, select_x ); + mCol0 = Vector3( spu_sel( tmp3, tmp2, select_z ) ); + mCol1 = Vector3( spu_sel( tmp4, tmp0, select_z ) ); + mCol2 = Vector3( spu_sel( tmp5, tmp1, select_z ) ); +} + +inline Matrix3::Matrix3( Vector3 _col0, Vector3 _col1, Vector3 _col2 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; +} + +inline Matrix3 & Matrix3::setCol0( Vector3 _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix3 & Matrix3::setCol1( Vector3 _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix3 & Matrix3::setCol2( Vector3 _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix3 & Matrix3::setCol( int col, Vector3 vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix3 & Matrix3::setRow( int row, Vector3 vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + return *this; +} + +inline Matrix3 & Matrix3::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +inline float Matrix3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Matrix3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Matrix3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Matrix3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Matrix3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::getRow( int row ) const +{ + return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); +} + +inline Vector3 & Matrix3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix3 & Matrix3::operator =( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + return *this; +} + +inline const Matrix3 transpose( const Matrix3 & mat ) +{ + vec_float4 tmp0, tmp1, res0, res1, res2; + tmp0 = spu_shuffle( mat.getCol0().get128(), mat.getCol2().get128(), _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( mat.getCol0().get128(), mat.getCol2().get128(), _VECTORMATH_SHUF_ZCWD ); + res0 = spu_shuffle( tmp0, mat.getCol1().get128(), _VECTORMATH_SHUF_XAYB ); + res1 = spu_shuffle( tmp0, mat.getCol1().get128(), _VECTORMATH_SHUF_ZBW0 ); + res2 = spu_shuffle( tmp1, mat.getCol1().get128(), _VECTORMATH_SHUF_XCY0 ); + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +inline const Matrix3 inverse( const Matrix3 & mat ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet, inv0, inv1, inv2; + tmp2 = _vmathVfCross( mat.getCol0().get128(), mat.getCol1().get128() ); + tmp0 = _vmathVfCross( mat.getCol1().get128(), mat.getCol2().get128() ); + tmp1 = _vmathVfCross( mat.getCol2().get128(), mat.getCol0().get128() ); + dot = _vmathVfDot3( tmp2, mat.getCol2().get128() ); + dot = spu_shuffle( dot, dot, (vec_uchar16)spu_splats(0x00010203) ); + invdet = recipf4( dot ); + tmp3 = spu_shuffle( tmp0, tmp2, _VECTORMATH_SHUF_XAYB ); + tmp4 = spu_shuffle( tmp0, tmp2, _VECTORMATH_SHUF_ZCWD ); + inv0 = spu_shuffle( tmp3, tmp1, _VECTORMATH_SHUF_XAYB ); + inv1 = spu_shuffle( tmp3, tmp1, _VECTORMATH_SHUF_ZBW0 ); + inv2 = spu_shuffle( tmp4, tmp1, _VECTORMATH_SHUF_XCY0 ); + inv0 = spu_mul( inv0, invdet ); + inv1 = spu_mul( inv1, invdet ); + inv2 = spu_mul( inv2, invdet ); + return Matrix3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ) + ); +} + +inline float determinant( const Matrix3 & mat ) +{ + return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); +} + +inline const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ) + ); +} + +inline const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix3 Matrix3::operator -( ) const +{ + return Matrix3( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ) + ); +} + +inline const Matrix3 absPerElem( const Matrix3 & mat ) +{ + return Matrix3( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::operator *( float scalar ) const +{ + return Matrix3( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ) + ); +} + +inline Matrix3 & Matrix3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix3 operator *( float scalar, const Matrix3 & mat ) +{ + return mat * scalar; +} + +inline const Vector3 Matrix3::operator *( Vector3 vec ) const +{ + vec_float4 res; + vec_float4 xxxx, yyyy, zzzz; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + xxxx = spu_shuffle( vec.get128(), vec.get128(), shuffle_xxxx ); + yyyy = spu_shuffle( vec.get128(), vec.get128(), shuffle_yyyy ); + zzzz = spu_shuffle( vec.get128(), vec.get128(), shuffle_zzzz ); + res = spu_mul( mCol0.get128(), xxxx ); + res = spu_madd( mCol1.get128(), yyyy, res ); + res = spu_madd( mCol2.get128(), zzzz, res ); + return Vector3( res ); +} + +inline const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const +{ + return Matrix3( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) +{ + return Matrix3( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::identity( ) +{ + return Matrix3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationX( float radians ) +{ + vec_float4 s, c, res1, res2; + vec_uint4 select_y, select_z; + vec_float4 zero; + select_y = (vec_uint4)spu_maskb(0x0f00); + select_z = (vec_uint4)spu_maskb(0x00f0); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res1 = spu_sel( zero, c, select_y ); + res1 = spu_sel( res1, s, select_z ); + res2 = spu_sel( zero, negatef4(s), select_y ); + res2 = spu_sel( res2, c, select_z ); + return Matrix3( + Vector3::xAxis( ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +inline const Matrix3 Matrix3::rotationY( float radians ) +{ + vec_float4 s, c, res0, res2; + vec_uint4 select_x, select_z; + vec_float4 zero; + select_x = (vec_uint4)spu_maskb(0xf000); + select_z = (vec_uint4)spu_maskb(0x00f0); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res0 = spu_sel( zero, c, select_x ); + res0 = spu_sel( res0, negatef4(s), select_z ); + res2 = spu_sel( zero, s, select_x ); + res2 = spu_sel( res2, c, select_z ); + return Matrix3( + Vector3( res0 ), + Vector3::yAxis( ), + Vector3( res2 ) + ); +} + +inline const Matrix3 Matrix3::rotationZ( float radians ) +{ + vec_float4 s, c, res0, res1; + vec_uint4 select_x, select_y; + vec_float4 zero; + select_x = (vec_uint4)spu_maskb(0xf000); + select_y = (vec_uint4)spu_maskb(0x0f00); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res0 = spu_sel( zero, c, select_x ); + res0 = spu_sel( res0, s, select_y ); + res1 = spu_sel( zero, negatef4(s), select_x ); + res1 = spu_sel( res1, c, select_y ); + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationZYX( Vector3 radiansXYZ ) +{ + vec_float4 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + angles = radiansXYZ.get128(); + angles = spu_insert( 0.0f, angles, 3 ); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = spu_shuffle( s, c, _VECTORMATH_SHUF_CZD0 ); + Z1 = spu_shuffle( c, negS, _VECTORMATH_SHUF_CZD0 ); + Y0 = spu_shuffle( negS, c, _VECTORMATH_SHUF_BBY0 ); + Y1 = spu_shuffle( c, s, _VECTORMATH_SHUF_BBY0 ); + X0 = spu_shuffle( s, s, shuffle_xxxx ); + X1 = spu_shuffle( c, c, shuffle_xxxx ); + tmp = spu_mul( Z0, Y1 ); + return Matrix3( + Vector3( spu_mul( Z0, Y0 ) ), + Vector3( spu_madd( Z1, X1, spu_mul( tmp, X0 ) ) ), + Vector3( spu_nmsub( Z1, X0, spu_mul( tmp, X1 ) ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( float radians, Vector3 unitVec ) +{ + vec_float4 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + axis = unitVec.get128(); + sincosf4( spu_splats( radians ), &s, &c ); + xxxx = spu_shuffle( axis, axis, shuffle_xxxx ); + yyyy = spu_shuffle( axis, axis, shuffle_yyyy ); + zzzz = spu_shuffle( axis, axis, shuffle_zzzz ); + oneMinusC = spu_sub( spu_splats(1.0f), c ); + axisS = spu_mul( axis, s ); + negAxisS = negatef4( axisS ); + tmp0 = spu_shuffle( axisS, negAxisS, _VECTORMATH_SHUF_0ZB0 ); + tmp1 = spu_shuffle( axisS, negAxisS, _VECTORMATH_SHUF_C0X0 ); + tmp2 = spu_shuffle( axisS, negAxisS, _VECTORMATH_SHUF_YA00 ); + tmp0 = spu_sel( tmp0, c, (vec_uint4)spu_maskb(0xf000) ); + tmp1 = spu_sel( tmp1, c, (vec_uint4)spu_maskb(0x0f00) ); + tmp2 = spu_sel( tmp2, c, (vec_uint4)spu_maskb(0x00f0) ); + return Matrix3( + Vector3( spu_madd( spu_mul( axis, xxxx ), oneMinusC, tmp0 ) ), + Vector3( spu_madd( spu_mul( axis, yyyy ), oneMinusC, tmp1 ) ), + Vector3( spu_madd( spu_mul( axis, zzzz ), oneMinusC, tmp2 ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( Quat unitQuat ) +{ + return Matrix3( unitQuat ); +} + +inline const Matrix3 Matrix3::scale( Vector3 scaleVec ) +{ + vec_float4 zero = spu_splats(0.0f); + return Matrix3( + Vector3( spu_sel( zero, scaleVec.get128(), (vec_uint4)spu_maskb(0xf000) ) ), + Vector3( spu_sel( zero, scaleVec.get128(), (vec_uint4)spu_maskb(0x0f00) ) ), + Vector3( spu_sel( zero, scaleVec.get128(), (vec_uint4)spu_maskb(0x00f0) ) ) + ); +} + +inline const Matrix3 appendScale( const Matrix3 & mat, Vector3 scaleVec ) +{ + return Matrix3( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ) + ); +} + +inline const Matrix3 prependScale( Vector3 scaleVec, const Matrix3 & mat ) +{ + return Matrix3( + mulPerElem( mat.getCol0(), scaleVec ), + mulPerElem( mat.getCol1(), scaleVec ), + mulPerElem( mat.getCol2(), scaleVec ) + ); +} + +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix3 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); +} + +inline void print( const Matrix3 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Matrix4::Matrix4( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; +} + +inline Matrix4::Matrix4( float scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +inline Matrix4::Matrix4( const Transform3 & mat ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( mat.getCol3(), 1.0f ); +} + +inline Matrix4::Matrix4( Vector4 _col0, Vector4 _col1, Vector4 _col2, Vector4 _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Matrix4::Matrix4( const Matrix3 & mat, Vector3 translateVec ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +inline Matrix4::Matrix4( Quat unitQuat, Vector3 translateVec ) +{ + Matrix3 mat; + mat = Matrix3( unitQuat ); + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +inline Matrix4 & Matrix4::setCol0( Vector4 _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix4 & Matrix4::setCol1( Vector4 _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix4 & Matrix4::setCol2( Vector4 _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix4 & Matrix4::setCol3( Vector4 _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Matrix4 & Matrix4::setCol( int col, Vector4 vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix4 & Matrix4::setRow( int row, Vector4 vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Matrix4 & Matrix4::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +inline float Matrix4::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector4 Matrix4::getCol0( ) const +{ + return mCol0; +} + +inline const Vector4 Matrix4::getCol1( ) const +{ + return mCol1; +} + +inline const Vector4 Matrix4::getCol2( ) const +{ + return mCol2; +} + +inline const Vector4 Matrix4::getCol3( ) const +{ + return mCol3; +} + +inline const Vector4 Matrix4::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector4 & Matrix4::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix4 & Matrix4::operator =( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; + return *this; +} + +inline const Matrix4 transpose( const Matrix4 & mat ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3, res0, res1, res2, res3; + tmp0 = spu_shuffle( mat.getCol0().get128(), mat.getCol2().get128(), _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( mat.getCol1().get128(), mat.getCol3().get128(), _VECTORMATH_SHUF_XAYB ); + tmp2 = spu_shuffle( mat.getCol0().get128(), mat.getCol2().get128(), _VECTORMATH_SHUF_ZCWD ); + tmp3 = spu_shuffle( mat.getCol1().get128(), mat.getCol3().get128(), _VECTORMATH_SHUF_ZCWD ); + res0 = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_XAYB ); + res1 = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_ZCWD ); + res2 = spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_XAYB ); + res3 = spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_ZCWD ); + return Matrix4( + Vector4( res0 ), + Vector4( res1 ), + Vector4( res2 ), + Vector4( res3 ) + ); +} + +inline const Matrix4 inverse( const Matrix4 & mat ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + vec_float4 in0, in1, in2, in3; + vec_float4 tmp0, tmp1, tmp2, tmp3; + vec_float4 cof0, cof1, cof2, cof3; + vec_float4 t0, t1, t2, t3; + vec_float4 t01, t02, t03, t12, t23; + vec_float4 t1r, t2r; + vec_float4 t01r, t02r, t03r, t12r, t23r; + vec_float4 t1r3, t1r3r; + vec_float4 det, det1, det2, det3, invdet; + in0 = mat.getCol0().get128(); + in1 = mat.getCol1().get128(); + in2 = mat.getCol2().get128(); + in3 = mat.getCol3().get128(); + /* Perform transform of the input matrix of the form: + * A B C D + * E F G H + * I J K L + * M N O P + * + * The pseudo transpose of the input matrix is trans: + * A E I M + * J N B F + * C G K O + * L P D H + */ + tmp0 = spu_shuffle(in0, in1, _VECTORMATH_SHUF_XAZC); /* A E C G */ + tmp1 = spu_shuffle(in2, in3, _VECTORMATH_SHUF_XAZC); /* I M K O */ + tmp2 = spu_shuffle(in0, in1, _VECTORMATH_SHUF_YBWD); /* B F D H */ + tmp3 = spu_shuffle(in2, in3, _VECTORMATH_SHUF_YBWD); /* J N L P */ + t0 = spu_shuffle(tmp0, tmp1, _VECTORMATH_SHUF_XYAB); /* A E I M */ + t1 = spu_shuffle(tmp3, tmp2, _VECTORMATH_SHUF_XYAB); /* J N B F */ + t2 = spu_shuffle(tmp0, tmp1, _VECTORMATH_SHUF_ZWCD); /* C G K O */ + t3 = spu_shuffle(tmp3, tmp2, _VECTORMATH_SHUF_ZWCD); /* L P D H */ + /* Generate a cofactor matrix. The computed cofactors reside in + * cof0, cof1, cof2, cof3. + */ + t23 = spu_mul(t2, t3); /* CL GP KD OH */ + t23 = spu_shuffle(t23, t23, _VECTORMATH_SHUF_YXWZ); /* GP CL OH KD */ + cof0 = spu_mul(t1, t23); /* JGP NCL BOH FKD */ + cof1 = spu_mul(t0, t23); /* AGP ECL IOH MKD */ + t23r = spu_rlqwbyte(t23, 8); /* OH KD GP CL */ + cof0 = spu_msub(t1, t23r, cof0); /* JOH NKD BGP FCL - cof0 */ + cof1 = spu_msub(t0, t23r, cof1); /* AOH EKD IGP MCL - cof1 */ + cof1 = spu_rlqwbyte(cof1, 8); /* IGP MCL AOH EKD - IOH MKD AGP ECL */ + + t12 = spu_mul(t1, t2); /* JC NG BK FO */ + t12 = spu_shuffle(t12, t12, _VECTORMATH_SHUF_YXWZ); /* NG JC FO BK */ + cof0 = spu_madd(t3, t12, cof0); /* LNG PJC DFO HBK + cof0 */ + cof3 = spu_mul(t0, t12); /* ANG EJC IFO MBK */ + t12r = spu_rlqwbyte(t12, 8); /* FO BK NG JC */ + cof0 = spu_nmsub(t3, t12r, cof0); /* cof0 - LFO PBK DNG HJC */ + cof3 = spu_msub(t0, t12r, cof3); /* AFO EBK ING MJC - cof3 */ + cof3 = spu_rlqwbyte(cof3, 8); /* ING MJC AFO EBK - IFO MBK ANG EJC */ + t1r = spu_rlqwbyte(t1, 8); /* B F J N */ + t2r = spu_rlqwbyte(t2, 8); /* K O C G */ + t1r3 = spu_mul(t1r, t3); /* BL FP JD NH */ + t1r3 = spu_shuffle(t1r3, t1r3, _VECTORMATH_SHUF_YXWZ); /* FP BL NH JD */ + cof0 = spu_madd(t2r, t1r3, cof0); /* KFP OBL CNH GJD + cof0 */ + cof2 = spu_mul(t0, t1r3); /* AFP EBL INH MJD */ + t1r3r = spu_rlqwbyte(t1r3, 8); /* NH JD FP BL */ + cof0 = spu_nmsub(t2r, t1r3r, cof0); /* cof0 - KNH OJD CFP GBL */ + cof2 = spu_msub(t0, t1r3r, cof2); /* ANH EJD IFP MBL - cof2 */ + cof2 = spu_rlqwbyte(cof2, 8); /* IFP MBL ANH EJD - INH MJD AFP EBL */ + t01 = spu_mul(t0, t1); /* AJ EN IB MF */ + t01 = spu_shuffle(t01, t01, _VECTORMATH_SHUF_YXWZ); /* EN AJ MF IB */ + cof2 = spu_madd(t3, t01, cof2); /* LEN PAJ DMF HIB + cof2 */ + cof3 = spu_msub(t2r, t01, cof3); /* KEN OAJ CMF GIB - cof3 */ + t01r = spu_rlqwbyte(t01, 8); /* MF IB EN AJ */ + cof2 = spu_msub(t3, t01r, cof2); /* LMF PIB DEN HAJ - cof2 */ + cof3 = spu_nmsub(t2r, t01r, cof3); /* cof3 - KMF OIB CEN GAJ */ + t03 = spu_mul(t0, t3); /* AL EP ID MH */ + t03 = spu_shuffle(t03, t03, _VECTORMATH_SHUF_YXWZ); /* EP AL MH ID */ + cof1 = spu_nmsub(t2r, t03, cof1); /* cof1 - KEP OAL CMH GID */ + cof2 = spu_madd(t1, t03, cof2); /* JEP NAL BMH FID + cof2 */ + t03r = spu_rlqwbyte(t03, 8); /* MH ID EP AL */ + cof1 = spu_madd(t2r, t03r, cof1); /* KMH OID CEP GAL + cof1 */ + cof2 = spu_nmsub(t1, t03r, cof2); /* cof2 - JMH NID BEP FAL */ + t02 = spu_mul(t0, t2r); /* AK EO IC MG */ + t02 = spu_shuffle(t02, t02, _VECTORMATH_SHUF_YXWZ); /* E0 AK MG IC */ + cof1 = spu_madd(t3, t02, cof1); /* LEO PAK DMG HIC + cof1 */ + cof3 = spu_nmsub(t1, t02, cof3); /* cof3 - JEO NAK BMG FIC */ + t02r = spu_rlqwbyte(t02, 8); /* MG IC EO AK */ + cof1 = spu_nmsub(t3, t02r, cof1); /* cof1 - LMG PIC DEO HAK */ + cof3 = spu_madd(t1, t02r, cof3); /* JMG NIC BEO FAK + cof3 */ + /* Compute the determinant of the matrix + * + * det = sum_across(t0 * cof0); + * + * We perform a sum across the entire vector so that + * we don't have to splat the result when multiplying the + * cofactors by the inverse of the determinant. + */ + det = spu_mul(t0, cof0); + det1 = spu_rlqwbyte(det, 4); + det2 = spu_rlqwbyte(det, 8); + det3 = spu_rlqwbyte(det, 12); + det = spu_add(det, det1); + det2 = spu_add(det2, det3); + det = spu_add(det, det2); + /* Compute the reciprocal of the determinant. + */ + invdet = recipf4(det); + /* Multiply the cofactors by the reciprocal of the determinant. + */ + return Matrix4( + Vector4( spu_mul(cof0, invdet) ), + Vector4( spu_mul(cof1, invdet) ), + Vector4( spu_mul(cof2, invdet) ), + Vector4( spu_mul(cof3, invdet) ) + ); +} + +inline const Matrix4 affineInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( inverse( affineMat ) ); +} + +inline const Matrix4 orthoInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( orthoInverse( affineMat ) ); +} + +inline float determinant( const Matrix4 & mat ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + vec_float4 in0, in1, in2, in3; + vec_float4 tmp0, tmp1, tmp2, tmp3; + vec_float4 cof0; + vec_float4 t0, t1, t2, t3; + vec_float4 t12, t23; + vec_float4 t1r, t2r; + vec_float4 t12r, t23r; + vec_float4 t1r3, t1r3r; + in0 = mat.getCol0().get128(); + in1 = mat.getCol1().get128(); + in2 = mat.getCol2().get128(); + in3 = mat.getCol3().get128(); + /* Perform transform of the input matrix of the form: + * A B C D + * E F G H + * I J K L + * M N O P + * + * The pseudo transpose of the input matrix is trans: + * A E I M + * J N B F + * C G K O + * L P D H + */ + tmp0 = spu_shuffle(in0, in1, _VECTORMATH_SHUF_XAZC); /* A E C G */ + tmp1 = spu_shuffle(in2, in3, _VECTORMATH_SHUF_XAZC); /* I M K O */ + tmp2 = spu_shuffle(in0, in1, _VECTORMATH_SHUF_YBWD); /* B F D H */ + tmp3 = spu_shuffle(in2, in3, _VECTORMATH_SHUF_YBWD); /* J N L P */ + t0 = spu_shuffle(tmp0, tmp1, _VECTORMATH_SHUF_XYAB); /* A E I M */ + t1 = spu_shuffle(tmp3, tmp2, _VECTORMATH_SHUF_XYAB); /* J N B F */ + t2 = spu_shuffle(tmp0, tmp1, _VECTORMATH_SHUF_ZWCD); /* C G K O */ + t3 = spu_shuffle(tmp3, tmp2, _VECTORMATH_SHUF_ZWCD); /* L P D H */ + /* Generate a cofactor matrix. The computed cofactors reside in + * cof0, cof1, cof2, cof3. + */ + t23 = spu_mul(t2, t3); /* CL GP KD OH */ + t23 = spu_shuffle(t23, t23, _VECTORMATH_SHUF_YXWZ); /* GP CL OH KD */ + cof0 = spu_mul(t1, t23); /* JGP NCL BOH FKD */ + t23r = spu_rlqwbyte(t23, 8); /* OH KD GP CL */ + cof0 = spu_msub(t1, t23r, cof0); /* JOH NKD BGP FCL - cof0 */ + + t12 = spu_mul(t1, t2); /* JC NG BK FO */ + t12 = spu_shuffle(t12, t12, _VECTORMATH_SHUF_YXWZ); /* NG JC FO BK */ + cof0 = spu_madd(t3, t12, cof0); /* LNG PJC DFO HBK + cof0 */ + t12r = spu_rlqwbyte(t12, 8); /* FO BK NG JC */ + cof0 = spu_nmsub(t3, t12r, cof0); /* cof0 - LFO PBK DNG HJC */ + t1r = spu_rlqwbyte(t1, 8); /* B F J N */ + t2r = spu_rlqwbyte(t2, 8); /* K O C G */ + t1r3 = spu_mul(t1r, t3); /* BL FP JD NH */ + t1r3 = spu_shuffle(t1r3, t1r3, _VECTORMATH_SHUF_YXWZ); /* FP BL NH JD */ + cof0 = spu_madd(t2r, t1r3, cof0); /* KFP OBL CNH GJD + cof0 */ + t1r3r = spu_rlqwbyte(t1r3, 8); /* NH JD FP BL */ + cof0 = spu_nmsub(t2r, t1r3r, cof0); /* cof0 - KNH OJD CFP GBL */ + return spu_extract( _vmathVfDot4(t0,cof0), 0 ); +} + +inline const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ), + ( mCol3 + mat.mCol3 ) + ); +} + +inline const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ), + ( mCol3 - mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix4 Matrix4::operator -( ) const +{ + return Matrix4( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ), + ( -mCol3 ) + ); +} + +inline const Matrix4 absPerElem( const Matrix4 & mat ) +{ + return Matrix4( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ), + absPerElem( mat.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::operator *( float scalar ) const +{ + return Matrix4( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ), + ( mCol3 * scalar ) + ); +} + +inline Matrix4 & Matrix4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix4 operator *( float scalar, const Matrix4 & mat ) +{ + return mat * scalar; +} + +inline const Vector4 Matrix4::operator *( Vector4 vec ) const +{ + vec_float4 tmp0, tmp1, res; + vec_float4 xxxx, yyyy, zzzz, wwww; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + vec_uchar16 shuffle_wwww = (vec_uchar16)spu_splats((int)0x0c0d0e0f); + xxxx = spu_shuffle( vec.get128(), vec.get128(), shuffle_xxxx ); + yyyy = spu_shuffle( vec.get128(), vec.get128(), shuffle_yyyy ); + zzzz = spu_shuffle( vec.get128(), vec.get128(), shuffle_zzzz ); + wwww = spu_shuffle( vec.get128(), vec.get128(), shuffle_wwww ); + tmp0 = spu_mul( mCol0.get128(), xxxx ); + tmp1 = spu_mul( mCol1.get128(), yyyy ); + tmp0 = spu_madd( mCol2.get128(), zzzz, tmp0 ); + tmp1 = spu_madd( mCol3.get128(), wwww, tmp1 ); + res = spu_add( tmp0, tmp1 ); + return Vector4( res ); +} + +inline const Vector4 Matrix4::operator *( Vector3 vec ) const +{ + vec_float4 res; + vec_float4 xxxx, yyyy, zzzz; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + xxxx = spu_shuffle( vec.get128(), vec.get128(), shuffle_xxxx ); + yyyy = spu_shuffle( vec.get128(), vec.get128(), shuffle_yyyy ); + zzzz = spu_shuffle( vec.get128(), vec.get128(), shuffle_zzzz ); + res = spu_mul( mCol0.get128(), xxxx ); + res = spu_madd( mCol1.get128(), yyyy, res ); + res = spu_madd( mCol2.get128(), zzzz, res ); + return Vector4( res ); +} + +inline const Vector4 Matrix4::operator *( Point3 pnt ) const +{ + vec_float4 tmp0, tmp1, res; + vec_float4 xxxx, yyyy, zzzz; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + xxxx = spu_shuffle( pnt.get128(), pnt.get128(), shuffle_xxxx ); + yyyy = spu_shuffle( pnt.get128(), pnt.get128(), shuffle_yyyy ); + zzzz = spu_shuffle( pnt.get128(), pnt.get128(), shuffle_zzzz ); + tmp0 = spu_mul( mCol0.get128(), xxxx ); + tmp1 = spu_mul( mCol1.get128(), yyyy ); + tmp0 = spu_madd( mCol2.get128(), zzzz, tmp0 ); + tmp1 = spu_add( mCol3.get128(), tmp1 ); + res = spu_add( tmp0, tmp1 ); + return Vector4( res ); +} + +inline const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const +{ + return Matrix4( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ), + ( *this * mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const +{ + return Matrix4( + ( *this * tfrm.getCol0() ), + ( *this * tfrm.getCol1() ), + ( *this * tfrm.getCol2() ), + ( *this * Point3( tfrm.getCol3() ) ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) +{ + return Matrix4( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ), + mulPerElem( mat0.getCol3(), mat1.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::identity( ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) +{ + mCol0.setXYZ( mat3.getCol0() ); + mCol1.setXYZ( mat3.getCol1() ); + mCol2.setXYZ( mat3.getCol2() ); + return *this; +} + +inline const Matrix3 Matrix4::getUpper3x3( ) const +{ + return Matrix3( + mCol0.getXYZ( ), + mCol1.getXYZ( ), + mCol2.getXYZ( ) + ); +} + +inline Matrix4 & Matrix4::setTranslation( Vector3 translateVec ) +{ + mCol3.setXYZ( translateVec ); + return *this; +} + +inline const Vector3 Matrix4::getTranslation( ) const +{ + return mCol3.getXYZ( ); +} + +inline const Matrix4 Matrix4::rotationX( float radians ) +{ + vec_float4 s, c, res1, res2; + vec_uint4 select_y, select_z; + vec_float4 zero; + select_y = (vec_uint4)spu_maskb(0x0f00); + select_z = (vec_uint4)spu_maskb(0x00f0); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res1 = spu_sel( zero, c, select_y ); + res1 = spu_sel( res1, s, select_z ); + res2 = spu_sel( zero, negatef4(s), select_y ); + res2 = spu_sel( res2, c, select_z ); + return Matrix4( + Vector4::xAxis( ), + Vector4( res1 ), + Vector4( res2 ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationY( float radians ) +{ + vec_float4 s, c, res0, res2; + vec_uint4 select_x, select_z; + vec_float4 zero; + select_x = (vec_uint4)spu_maskb(0xf000); + select_z = (vec_uint4)spu_maskb(0x00f0); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res0 = spu_sel( zero, c, select_x ); + res0 = spu_sel( res0, negatef4(s), select_z ); + res2 = spu_sel( zero, s, select_x ); + res2 = spu_sel( res2, c, select_z ); + return Matrix4( + Vector4( res0 ), + Vector4::yAxis( ), + Vector4( res2 ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZ( float radians ) +{ + vec_float4 s, c, res0, res1; + vec_uint4 select_x, select_y; + vec_float4 zero; + select_x = (vec_uint4)spu_maskb(0xf000); + select_y = (vec_uint4)spu_maskb(0x0f00); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res0 = spu_sel( zero, c, select_x ); + res0 = spu_sel( res0, s, select_y ); + res1 = spu_sel( zero, negatef4(s), select_x ); + res1 = spu_sel( res1, c, select_y ); + return Matrix4( + Vector4( res0 ), + Vector4( res1 ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZYX( Vector3 radiansXYZ ) +{ + vec_float4 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + angles = radiansXYZ.get128(); + angles = spu_insert( 0.0f, angles, 3 ); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = spu_shuffle( s, c, _VECTORMATH_SHUF_CZD0 ); + Z1 = spu_shuffle( c, negS, _VECTORMATH_SHUF_CZD0 ); + Y0 = spu_shuffle( negS, c, _VECTORMATH_SHUF_BBY0 ); + Y1 = spu_shuffle( c, s, _VECTORMATH_SHUF_BBY0 ); + X0 = spu_shuffle( s, s, shuffle_xxxx ); + X1 = spu_shuffle( c, c, shuffle_xxxx ); + tmp = spu_mul( Z0, Y1 ); + return Matrix4( + Vector4( spu_mul( Z0, Y0 ) ), + Vector4( spu_madd( Z1, X1, spu_mul( tmp, X0 ) ) ), + Vector4( spu_nmsub( Z1, X0, spu_mul( tmp, X1 ) ) ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( float radians, Vector3 unitVec ) +{ + vec_float4 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2, zeroW; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + axis = unitVec.get128(); + sincosf4( spu_splats( radians ), &s, &c ); + xxxx = spu_shuffle( axis, axis, shuffle_xxxx ); + yyyy = spu_shuffle( axis, axis, shuffle_yyyy ); + zzzz = spu_shuffle( axis, axis, shuffle_zzzz ); + oneMinusC = spu_sub( spu_splats(1.0f), c ); + axisS = spu_mul( axis, s ); + negAxisS = negatef4( axisS ); + tmp0 = spu_shuffle( axisS, negAxisS, _VECTORMATH_SHUF_0ZB0 ); + tmp1 = spu_shuffle( axisS, negAxisS, _VECTORMATH_SHUF_C0X0 ); + tmp2 = spu_shuffle( axisS, negAxisS, _VECTORMATH_SHUF_YA00 ); + tmp0 = spu_sel( tmp0, c, (vec_uint4)spu_maskb(0xf000) ); + tmp1 = spu_sel( tmp1, c, (vec_uint4)spu_maskb(0x0f00) ); + tmp2 = spu_sel( tmp2, c, (vec_uint4)spu_maskb(0x00f0) ); + zeroW = (vec_float4)spu_maskb(0x000f); + axis = spu_andc( axis, zeroW ); + return Matrix4( + Vector4( spu_madd( spu_mul( axis, xxxx ), oneMinusC, tmp0 ) ), + Vector4( spu_madd( spu_mul( axis, yyyy ), oneMinusC, tmp1 ) ), + Vector4( spu_madd( spu_mul( axis, zzzz ), oneMinusC, tmp2 ) ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( Quat unitQuat ) +{ + return Matrix4( Transform3::rotation( unitQuat ) ); +} + +inline const Matrix4 Matrix4::scale( Vector3 scaleVec ) +{ + vec_float4 zero = spu_splats(0.0f); + return Matrix4( + Vector4( spu_sel( zero, scaleVec.get128(), (vec_uint4)spu_maskb(0xf000) ) ), + Vector4( spu_sel( zero, scaleVec.get128(), (vec_uint4)spu_maskb(0x0f00) ) ), + Vector4( spu_sel( zero, scaleVec.get128(), (vec_uint4)spu_maskb(0x00f0) ) ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 appendScale( const Matrix4 & mat, Vector3 scaleVec ) +{ + return Matrix4( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ), + mat.getCol3() + ); +} + +inline const Matrix4 prependScale( Vector3 scaleVec, const Matrix4 & mat ) +{ + Vector4 scale4; + scale4 = Vector4( scaleVec, 1.0f ); + return Matrix4( + mulPerElem( mat.getCol0(), scale4 ), + mulPerElem( mat.getCol1(), scale4 ), + mulPerElem( mat.getCol2(), scale4 ), + mulPerElem( mat.getCol3(), scale4 ) + ); +} + +inline const Matrix4 Matrix4::translation( Vector3 translateVec ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4( translateVec, 1.0f ) + ); +} + +inline const Matrix4 Matrix4::lookAt( Point3 eyePos, Point3 lookAtPos, Vector3 upVec ) +{ + Matrix4 m4EyeFrame; + Vector3 v3X, v3Y, v3Z; + v3Y = normalize( upVec ); + v3Z = normalize( ( eyePos - lookAtPos ) ); + v3X = normalize( cross( v3Y, v3Z ) ); + v3Y = cross( v3Z, v3X ); + m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); + return orthoInverse( m4EyeFrame ); +} + +inline const Matrix4 Matrix4::perspective( float fovyRadians, float aspect, float zNear, float zFar ) +{ + float f, rangeInv; + vec_float4 zero, col0, col1, col2, col3; + f = tanf( _VECTORMATH_PI_OVER_2 - fovyRadians * 0.5f ); + rangeInv = 1.0f / ( zNear - zFar ); + zero = spu_splats(0.0f); + col0 = zero; + col1 = zero; + col2 = zero; + col3 = zero; + col0 = spu_insert( f / aspect, col0, 0 ); + col1 = spu_insert( f, col1, 1 ); + col2 = spu_insert( ( zNear + zFar ) * rangeInv, col2, 2 ); + col2 = spu_insert( -1.0f, col2, 3 ); + col3 = spu_insert( zNear * zFar * rangeInv * 2.0f, col3, 2 ); + return Matrix4( + Vector4( col0 ), + Vector4( col1 ), + Vector4( col2 ), + Vector4( col3 ) + ); +} + +inline const Matrix4 Matrix4::frustum( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + vec_float4 lbf, rtn; + vec_float4 diff, sum, inv_diff; + vec_float4 diagonal, column, near2; + vec_float4 zero = spu_splats(0.0f); + lbf = spu_shuffle( spu_promote(left,0), spu_promote(zFar,0), _VECTORMATH_SHUF_XAYB ); + rtn = spu_shuffle( spu_promote(right,0), spu_promote(zNear,0), _VECTORMATH_SHUF_XAYB ); + lbf = spu_shuffle( lbf, spu_promote(bottom,0), _VECTORMATH_SHUF_XAYB ); + rtn = spu_shuffle( rtn, spu_promote(top,0), _VECTORMATH_SHUF_XAYB ); + diff = spu_sub( rtn, lbf ); + sum = spu_add( rtn, lbf ); + inv_diff = recipf4( diff ); + near2 = spu_splats( zNear ); + near2 = spu_add( near2, near2 ); + diagonal = spu_mul( near2, inv_diff ); + column = spu_mul( sum, inv_diff ); + return Matrix4( + Vector4( spu_sel( zero, diagonal, (vec_uint4)spu_maskb(0xf000) ) ), + Vector4( spu_sel( zero, diagonal, (vec_uint4)spu_maskb(0x0f00) ) ), + Vector4( spu_sel( column, spu_splats(-1.0f), (vec_uint4)spu_maskb(0x000f) ) ), + Vector4( spu_sel( zero, spu_mul( diagonal, spu_splats(zFar) ), (vec_uint4)spu_maskb(0x00f0) ) ) + ); +} + +inline const Matrix4 Matrix4::orthographic( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + vec_float4 lbf, rtn; + vec_float4 diff, sum, inv_diff, neg_inv_diff; + vec_float4 diagonal, column; + vec_float4 zero = spu_splats(0.0f); + lbf = spu_shuffle( spu_promote(left,0), spu_promote(zFar,0), _VECTORMATH_SHUF_XAYB ); + rtn = spu_shuffle( spu_promote(right,0), spu_promote(zNear,0), _VECTORMATH_SHUF_XAYB ); + lbf = spu_shuffle( lbf, spu_promote(bottom,0), _VECTORMATH_SHUF_XAYB ); + rtn = spu_shuffle( rtn, spu_promote(top,0), _VECTORMATH_SHUF_XAYB ); + diff = spu_sub( rtn, lbf ); + sum = spu_add( rtn, lbf ); + inv_diff = recipf4( diff ); + neg_inv_diff = negatef4( inv_diff ); + diagonal = spu_add( inv_diff, inv_diff ); + column = spu_mul( sum, spu_sel( neg_inv_diff, inv_diff, (vec_uint4)spu_maskb(0x00f0) ) ); + return Matrix4( + Vector4( spu_sel( zero, diagonal, (vec_uint4)spu_maskb(0xf000) ) ), + Vector4( spu_sel( zero, diagonal, (vec_uint4)spu_maskb(0x0f00) ) ), + Vector4( spu_sel( zero, diagonal, (vec_uint4)spu_maskb(0x00f0) ) ), + Vector4( spu_sel( column, spu_splats(1.0f), (vec_uint4)spu_maskb(0x000f) ) ) + ); +} + +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix4 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); + print( mat.getRow( 3 ) ); +} + +inline void print( const Matrix4 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Transform3::Transform3( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; +} + +inline Transform3::Transform3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +inline Transform3::Transform3( Vector3 _col0, Vector3 _col1, Vector3 _col2, Vector3 _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Transform3::Transform3( const Matrix3 & tfrm, Vector3 translateVec ) +{ + this->setUpper3x3( tfrm ); + this->setTranslation( translateVec ); +} + +inline Transform3::Transform3( Quat unitQuat, Vector3 translateVec ) +{ + this->setUpper3x3( Matrix3( unitQuat ) ); + this->setTranslation( translateVec ); +} + +inline Transform3 & Transform3::setCol0( Vector3 _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Transform3 & Transform3::setCol1( Vector3 _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Transform3 & Transform3::setCol2( Vector3 _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Transform3 & Transform3::setCol3( Vector3 _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Transform3 & Transform3::setCol( int col, Vector3 vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Transform3 & Transform3::setRow( int row, Vector4 vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Transform3 & Transform3::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +inline float Transform3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Transform3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Transform3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Transform3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Transform3::getCol3( ) const +{ + return mCol3; +} + +inline const Vector3 Transform3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Transform3::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector3 & Transform3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Transform3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Transform3 & Transform3::operator =( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; + return *this; +} + +inline const Transform3 inverse( const Transform3 & tfrm ) +{ + vec_float4 inv0, inv1, inv2, inv3; + vec_float4 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet; + vec_float4 xxxx, yyyy, zzzz; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + tmp2 = _vmathVfCross( tfrm.getCol0().get128(), tfrm.getCol1().get128() ); + tmp0 = _vmathVfCross( tfrm.getCol1().get128(), tfrm.getCol2().get128() ); + tmp1 = _vmathVfCross( tfrm.getCol2().get128(), tfrm.getCol0().get128() ); + inv3 = negatef4( tfrm.getCol3().get128() ); + dot = _vmathVfDot3( tmp2, tfrm.getCol2().get128() ); + dot = spu_shuffle( dot, dot, shuffle_xxxx ); + invdet = recipf4( dot ); + tmp3 = spu_shuffle( tmp0, tmp2, _VECTORMATH_SHUF_XAYB ); + tmp4 = spu_shuffle( tmp0, tmp2, _VECTORMATH_SHUF_ZCWD ); + inv0 = spu_shuffle( tmp3, tmp1, _VECTORMATH_SHUF_XAYB ); + xxxx = spu_shuffle( inv3, inv3, shuffle_xxxx ); + inv1 = spu_shuffle( tmp3, tmp1, _VECTORMATH_SHUF_ZBW0 ); + inv2 = spu_shuffle( tmp4, tmp1, _VECTORMATH_SHUF_XCY0 ); + yyyy = spu_shuffle( inv3, inv3, shuffle_yyyy ); + zzzz = spu_shuffle( inv3, inv3, shuffle_zzzz ); + inv3 = spu_mul( inv0, xxxx ); + inv3 = spu_madd( inv1, yyyy, inv3 ); + inv3 = spu_madd( inv2, zzzz, inv3 ); + inv0 = spu_mul( inv0, invdet ); + inv1 = spu_mul( inv1, invdet ); + inv2 = spu_mul( inv2, invdet ); + inv3 = spu_mul( inv3, invdet ); + return Transform3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ), + Vector3( inv3 ) + ); +} + +inline const Transform3 orthoInverse( const Transform3 & tfrm ) +{ + vec_float4 inv0, inv1, inv2, inv3; + vec_float4 tmp0, tmp1; + vec_float4 xxxx, yyyy, zzzz; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + tmp0 = spu_shuffle( tfrm.getCol0().get128(), tfrm.getCol2().get128(), _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( tfrm.getCol0().get128(), tfrm.getCol2().get128(), _VECTORMATH_SHUF_ZCWD ); + inv3 = negatef4( tfrm.getCol3().get128() ); + inv0 = spu_shuffle( tmp0, tfrm.getCol1().get128(), _VECTORMATH_SHUF_XAYB ); + xxxx = spu_shuffle( inv3, inv3, shuffle_xxxx ); + inv1 = spu_shuffle( tmp0, tfrm.getCol1().get128(), _VECTORMATH_SHUF_ZBW0 ); + inv2 = spu_shuffle( tmp1, tfrm.getCol1().get128(), _VECTORMATH_SHUF_XCY0 ); + yyyy = spu_shuffle( inv3, inv3, shuffle_yyyy ); + zzzz = spu_shuffle( inv3, inv3, shuffle_zzzz ); + inv3 = spu_mul( inv0, xxxx ); + inv3 = spu_madd( inv1, yyyy, inv3 ); + inv3 = spu_madd( inv2, zzzz, inv3 ); + return Transform3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ), + Vector3( inv3 ) + ); +} + +inline const Transform3 absPerElem( const Transform3 & tfrm ) +{ + return Transform3( + absPerElem( tfrm.getCol0() ), + absPerElem( tfrm.getCol1() ), + absPerElem( tfrm.getCol2() ), + absPerElem( tfrm.getCol3() ) + ); +} + +inline const Vector3 Transform3::operator *( Vector3 vec ) const +{ + vec_float4 res; + vec_float4 xxxx, yyyy, zzzz; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + xxxx = spu_shuffle( vec.get128(), vec.get128(), shuffle_xxxx ); + yyyy = spu_shuffle( vec.get128(), vec.get128(), shuffle_yyyy ); + zzzz = spu_shuffle( vec.get128(), vec.get128(), shuffle_zzzz ); + res = spu_mul( mCol0.get128(), xxxx ); + res = spu_madd( mCol1.get128(), yyyy, res ); + res = spu_madd( mCol2.get128(), zzzz, res ); + return Vector3( res ); +} + +inline const Point3 Transform3::operator *( Point3 pnt ) const +{ + vec_float4 tmp0, tmp1, res; + vec_float4 xxxx, yyyy, zzzz; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + xxxx = spu_shuffle( pnt.get128(), pnt.get128(), shuffle_xxxx ); + yyyy = spu_shuffle( pnt.get128(), pnt.get128(), shuffle_yyyy ); + zzzz = spu_shuffle( pnt.get128(), pnt.get128(), shuffle_zzzz ); + tmp0 = spu_mul( mCol0.get128(), xxxx ); + tmp1 = spu_mul( mCol1.get128(), yyyy ); + tmp0 = spu_madd( mCol2.get128(), zzzz, tmp0 ); + tmp1 = spu_add( mCol3.get128(), tmp1 ); + res = spu_add( tmp0, tmp1 ); + return Point3( res ); +} + +inline const Transform3 Transform3::operator *( const Transform3 & tfrm ) const +{ + return Transform3( + ( *this * tfrm.mCol0 ), + ( *this * tfrm.mCol1 ), + ( *this * tfrm.mCol2 ), + Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) + ); +} + +inline Transform3 & Transform3::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) +{ + return Transform3( + mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), + mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), + mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), + mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) + ); +} + +inline const Transform3 Transform3::identity( ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +inline Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) +{ + mCol0 = tfrm.getCol0(); + mCol1 = tfrm.getCol1(); + mCol2 = tfrm.getCol2(); + return *this; +} + +inline const Matrix3 Transform3::getUpper3x3( ) const +{ + return Matrix3( mCol0, mCol1, mCol2 ); +} + +inline Transform3 & Transform3::setTranslation( Vector3 translateVec ) +{ + mCol3 = translateVec; + return *this; +} + +inline const Vector3 Transform3::getTranslation( ) const +{ + return mCol3; +} + +inline const Transform3 Transform3::rotationX( float radians ) +{ + vec_float4 s, c, res1, res2; + vec_uint4 select_y, select_z; + vec_float4 zero; + select_y = (vec_uint4)spu_maskb(0x0f00); + select_z = (vec_uint4)spu_maskb(0x00f0); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res1 = spu_sel( zero, c, select_y ); + res1 = spu_sel( res1, s, select_z ); + res2 = spu_sel( zero, negatef4(s), select_y ); + res2 = spu_sel( res2, c, select_z ); + return Transform3( + Vector3::xAxis( ), + Vector3( res1 ), + Vector3( res2 ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationY( float radians ) +{ + vec_float4 s, c, res0, res2; + vec_uint4 select_x, select_z; + vec_float4 zero; + select_x = (vec_uint4)spu_maskb(0xf000); + select_z = (vec_uint4)spu_maskb(0x00f0); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res0 = spu_sel( zero, c, select_x ); + res0 = spu_sel( res0, negatef4(s), select_z ); + res2 = spu_sel( zero, s, select_x ); + res2 = spu_sel( res2, c, select_z ); + return Transform3( + Vector3( res0 ), + Vector3::yAxis( ), + Vector3( res2 ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationZ( float radians ) +{ + vec_float4 s, c, res0, res1; + vec_uint4 select_x, select_y; + vec_float4 zero; + select_x = (vec_uint4)spu_maskb(0xf000); + select_y = (vec_uint4)spu_maskb(0x0f00); + zero = spu_splats(0.0f); + sincosf4( spu_splats(radians), &s, &c ); + res0 = spu_sel( zero, c, select_x ); + res0 = spu_sel( res0, s, select_y ); + res1 = spu_sel( zero, negatef4(s), select_x ); + res1 = spu_sel( res1, c, select_y ); + return Transform3( + Vector3( res0 ), + Vector3( res1 ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationZYX( Vector3 radiansXYZ ) +{ + vec_float4 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + angles = radiansXYZ.get128(); + angles = spu_insert( 0.0f, angles, 3 ); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = spu_shuffle( s, c, _VECTORMATH_SHUF_CZD0 ); + Z1 = spu_shuffle( c, negS, _VECTORMATH_SHUF_CZD0 ); + Y0 = spu_shuffle( negS, c, _VECTORMATH_SHUF_BBY0 ); + Y1 = spu_shuffle( c, s, _VECTORMATH_SHUF_BBY0 ); + X0 = spu_shuffle( s, s, shuffle_xxxx ); + X1 = spu_shuffle( c, c, shuffle_xxxx ); + tmp = spu_mul( Z0, Y1 ); + return Transform3( + Vector3( spu_mul( Z0, Y0 ) ), + Vector3( spu_madd( Z1, X1, spu_mul( tmp, X0 ) ) ), + Vector3( spu_nmsub( Z1, X0, spu_mul( tmp, X1 ) ) ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotation( float radians, Vector3 unitVec ) +{ + return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( 0.0f ) ); +} + +inline const Transform3 Transform3::rotation( Quat unitQuat ) +{ + return Transform3( Matrix3( unitQuat ), Vector3( 0.0f ) ); +} + +inline const Transform3 Transform3::scale( Vector3 scaleVec ) +{ + vec_float4 zero = spu_splats(0.0f); + return Transform3( + Vector3( spu_sel( zero, scaleVec.get128(), (vec_uint4)spu_maskb(0xf000) ) ), + Vector3( spu_sel( zero, scaleVec.get128(), (vec_uint4)spu_maskb(0x0f00) ) ), + Vector3( spu_sel( zero, scaleVec.get128(), (vec_uint4)spu_maskb(0x00f0) ) ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 appendScale( const Transform3 & tfrm, Vector3 scaleVec ) +{ + return Transform3( + ( tfrm.getCol0() * scaleVec.getX( ) ), + ( tfrm.getCol1() * scaleVec.getY( ) ), + ( tfrm.getCol2() * scaleVec.getZ( ) ), + tfrm.getCol3() + ); +} + +inline const Transform3 prependScale( Vector3 scaleVec, const Transform3 & tfrm ) +{ + return Transform3( + mulPerElem( tfrm.getCol0(), scaleVec ), + mulPerElem( tfrm.getCol1(), scaleVec ), + mulPerElem( tfrm.getCol2(), scaleVec ), + mulPerElem( tfrm.getCol3(), scaleVec ) + ); +} + +inline const Transform3 Transform3::translation( Vector3 translateVec ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + translateVec + ); +} + +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Transform3 & tfrm ) +{ + print( tfrm.getRow( 0 ) ); + print( tfrm.getRow( 1 ) ); + print( tfrm.getRow( 2 ) ); +} + +inline void print( const Transform3 & tfrm, const char * name ) +{ + printf("%s:\n", name); + print( tfrm ); +} + +#endif + +inline Quat::Quat( const Matrix3 & tfrm ) +{ + vec_float4 res; + vec_float4 col0, col1, col2; + vec_float4 xx_yy, xx_yy_zz_xx, yy_zz_xx_yy, zz_xx_yy_zz, diagSum, diagDiff; + vec_float4 zy_xz_yx, yz_zx_xy, sum, diff; + vec_float4 radicand, invSqrt, scale; + vec_float4 res0, res1, res2, res3; + vec_float4 xx, yy, zz; + vec_uint4 select_x = (vec_uint4)spu_maskb( 0xf000 ); + vec_uint4 select_y = (vec_uint4)spu_maskb( 0x0f00 ); + vec_uint4 select_z = (vec_uint4)spu_maskb( 0x00f0 ); + vec_uint4 select_w = (vec_uint4)spu_maskb( 0x000f ); + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((unsigned int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((unsigned int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((unsigned int)0x08090a0b); + vec_uchar16 shuffle_wwww = (vec_uchar16)spu_splats((unsigned int)0x0c0d0e0f); + + col0 = tfrm.getCol0().get128(); + col1 = tfrm.getCol1().get128(); + col2 = tfrm.getCol2().get128(); + + /* four cases: */ + /* trace > 0 */ + /* else */ + /* xx largest diagonal element */ + /* yy largest diagonal element */ + /* zz largest diagonal element */ + + /* compute quaternion for each case */ + + xx_yy = spu_sel( col0, col1, select_y ); + xx_yy_zz_xx = spu_shuffle( xx_yy, col2, _VECTORMATH_SHUF_XYCX ); + yy_zz_xx_yy = spu_shuffle( xx_yy, col2, _VECTORMATH_SHUF_YCXY ); + zz_xx_yy_zz = spu_shuffle( xx_yy, col2, _VECTORMATH_SHUF_CXYC ); + + diagSum = spu_add( spu_add( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); + diagDiff = spu_sub( spu_sub( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); + radicand = spu_add( spu_sel( diagDiff, diagSum, select_w ), spu_splats(1.0f) ); + invSqrt = rsqrtf4( radicand ); + + zy_xz_yx = spu_sel( col0, col1, select_z ); + zy_xz_yx = spu_shuffle( zy_xz_yx, col2, _VECTORMATH_SHUF_ZAY0 ); + yz_zx_xy = spu_sel( col0, col1, select_x ); + yz_zx_xy = spu_shuffle( yz_zx_xy, col2, _VECTORMATH_SHUF_BZX0 ); + + sum = spu_add( zy_xz_yx, yz_zx_xy ); + diff = spu_sub( zy_xz_yx, yz_zx_xy ); + + scale = spu_mul( invSqrt, spu_splats(0.5f) ); + res0 = spu_shuffle( sum, diff, _VECTORMATH_SHUF_0ZYA ); + res1 = spu_shuffle( sum, diff, _VECTORMATH_SHUF_Z0XB ); + res2 = spu_shuffle( sum, diff, _VECTORMATH_SHUF_YX0C ); + res3 = diff; + res0 = spu_sel( res0, radicand, select_x ); + res1 = spu_sel( res1, radicand, select_y ); + res2 = spu_sel( res2, radicand, select_z ); + res3 = spu_sel( res3, radicand, select_w ); + res0 = spu_mul( res0, spu_shuffle( scale, scale, shuffle_xxxx ) ); + res1 = spu_mul( res1, spu_shuffle( scale, scale, shuffle_yyyy ) ); + res2 = spu_mul( res2, spu_shuffle( scale, scale, shuffle_zzzz ) ); + res3 = spu_mul( res3, spu_shuffle( scale, scale, shuffle_wwww ) ); + + /* determine case and select answer */ + + xx = spu_shuffle( col0, col0, shuffle_xxxx ); + yy = spu_shuffle( col1, col1, shuffle_yyyy ); + zz = spu_shuffle( col2, col2, shuffle_zzzz ); + res = spu_sel( res0, res1, spu_cmpgt( yy, xx ) ); + res = spu_sel( res, res2, spu_and( spu_cmpgt( zz, xx ), spu_cmpgt( zz, yy ) ) ); + res = spu_sel( res, res3, spu_cmpgt( spu_shuffle( diagSum, diagSum, shuffle_xxxx ), spu_splats(0.0f) ) ); + mVec128 = res; +} + +inline const Matrix3 outer( Vector3 tfrm0, Vector3 tfrm1 ) +{ + return Matrix3( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ) + ); +} + +inline const Matrix4 outer( Vector4 tfrm0, Vector4 tfrm1 ) +{ + return Matrix4( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ), + ( tfrm0 * tfrm1.getW( ) ) + ); +} + +inline const Vector3 rowMul( Vector3 vec, const Matrix3 & mat ) +{ + vec_float4 tmp0, tmp1, mcol0, mcol1, mcol2, res; + vec_float4 xxxx, yyyy, zzzz; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + tmp0 = spu_shuffle( mat.getCol0().get128(), mat.getCol2().get128(), _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( mat.getCol0().get128(), mat.getCol2().get128(), _VECTORMATH_SHUF_ZCWD ); + xxxx = spu_shuffle( vec.get128(), vec.get128(), shuffle_xxxx ); + mcol0 = spu_shuffle( tmp0, mat.getCol1().get128(), _VECTORMATH_SHUF_XAYB ); + mcol1 = spu_shuffle( tmp0, mat.getCol1().get128(), _VECTORMATH_SHUF_ZBW0 ); + mcol2 = spu_shuffle( tmp1, mat.getCol1().get128(), _VECTORMATH_SHUF_XCY0 ); + yyyy = spu_shuffle( vec.get128(), vec.get128(), shuffle_yyyy ); + res = spu_mul( mcol0, xxxx ); + zzzz = spu_shuffle( vec.get128(), vec.get128(), shuffle_zzzz ); + res = spu_madd( mcol1, yyyy, res ); + res = spu_madd( mcol2, zzzz, res ); + return Vector3( res ); +} + +inline const Matrix3 crossMatrix( Vector3 vec ) +{ + vec_float4 neg, res0, res1, res2; + neg = negatef4( vec.get128() ); + res0 = spu_shuffle( vec.get128(), neg, _VECTORMATH_SHUF_0ZB0 ); + res1 = spu_shuffle( vec.get128(), neg, _VECTORMATH_SHUF_C0X0 ); + res2 = spu_shuffle( vec.get128(), neg, _VECTORMATH_SHUF_YA00 ); + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +inline const Matrix3 crossMatrixMul( Vector3 vec, const Matrix3 & mat ) +{ + return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); +} + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/cpp/mat_soa.h b/Extras/vectormathlibrary/include/vectormath/spu/cpp/mat_soa.h new file mode 100644 index 0000000..8c884d5 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/cpp/mat_soa.h @@ -0,0 +1,1744 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_MAT_SOA_CPP_H +#define _VECTORMATH_MAT_SOA_CPP_H + +namespace Vectormath { +namespace Soa { + +//----------------------------------------------------------------------------- +// Constants + +#define _VECTORMATH_PI_OVER_2 1.570796327f + +//----------------------------------------------------------------------------- +// Definitions + +inline Matrix3::Matrix3( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; +} + +inline Matrix3::Matrix3( vec_float4 scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +inline Matrix3::Matrix3( const Quat & unitQuat ) +{ + vec_float4 qx, qy, qz, qw, qx2, qy2, qz2, qxqx2, qyqy2, qzqz2, qxqy2, qyqz2, qzqw2, qxqz2, qyqw2, qxqw2; + qx = unitQuat.getX(); + qy = unitQuat.getY(); + qz = unitQuat.getZ(); + qw = unitQuat.getW(); + qx2 = spu_add( qx, qx ); + qy2 = spu_add( qy, qy ); + qz2 = spu_add( qz, qz ); + qxqx2 = spu_mul( qx, qx2 ); + qxqy2 = spu_mul( qx, qy2 ); + qxqz2 = spu_mul( qx, qz2 ); + qxqw2 = spu_mul( qw, qx2 ); + qyqy2 = spu_mul( qy, qy2 ); + qyqz2 = spu_mul( qy, qz2 ); + qyqw2 = spu_mul( qw, qy2 ); + qzqz2 = spu_mul( qz, qz2 ); + qzqw2 = spu_mul( qw, qz2 ); + mCol0 = Vector3( spu_sub( spu_sub( spu_splats(1.0f), qyqy2 ), qzqz2 ), spu_add( qxqy2, qzqw2 ), spu_sub( qxqz2, qyqw2 ) ); + mCol1 = Vector3( spu_sub( qxqy2, qzqw2 ), spu_sub( spu_sub( spu_splats(1.0f), qxqx2 ), qzqz2 ), spu_add( qyqz2, qxqw2 ) ); + mCol2 = Vector3( spu_add( qxqz2, qyqw2 ), spu_sub( qyqz2, qxqw2 ), spu_sub( spu_sub( spu_splats(1.0f), qxqx2 ), qyqy2 ) ); +} + +inline Matrix3::Matrix3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; +} + +inline Matrix3::Matrix3( const Aos::Matrix3 & mat ) +{ + mCol0 = Vector3( mat.getCol0() ); + mCol1 = Vector3( mat.getCol1() ); + mCol2 = Vector3( mat.getCol2() ); +} + +inline Matrix3::Matrix3( const Aos::Matrix3 & mat0, const Aos::Matrix3 & mat1, const Aos::Matrix3 & mat2, const Aos::Matrix3 & mat3 ) +{ + mCol0 = Vector3( mat0.getCol0(), mat1.getCol0(), mat2.getCol0(), mat3.getCol0() ); + mCol1 = Vector3( mat0.getCol1(), mat1.getCol1(), mat2.getCol1(), mat3.getCol1() ); + mCol2 = Vector3( mat0.getCol2(), mat1.getCol2(), mat2.getCol2(), mat3.getCol2() ); +} + +inline void Matrix3::get4Aos( Aos::Matrix3 & result0, Aos::Matrix3 & result1, Aos::Matrix3 & result2, Aos::Matrix3 & result3 ) const +{ + Aos::Vector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + mCol0.get4Aos( tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3 ); + result0.setCol0( tmpV3_0 ); + result1.setCol0( tmpV3_1 ); + result2.setCol0( tmpV3_2 ); + result3.setCol0( tmpV3_3 ); + mCol1.get4Aos( tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3 ); + result0.setCol1( tmpV3_0 ); + result1.setCol1( tmpV3_1 ); + result2.setCol1( tmpV3_2 ); + result3.setCol1( tmpV3_3 ); + mCol2.get4Aos( tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3 ); + result0.setCol2( tmpV3_0 ); + result1.setCol2( tmpV3_1 ); + result2.setCol2( tmpV3_2 ); + result3.setCol2( tmpV3_3 ); +} + +inline Matrix3 & Matrix3::setCol0( const Vector3 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix3 & Matrix3::setCol1( const Vector3 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix3 & Matrix3::setCol2( const Vector3 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix3 & Matrix3::setCol( int col, const Vector3 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix3 & Matrix3::setRow( int row, const Vector3 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + return *this; +} + +inline Matrix3 & Matrix3::setElem( int col, int row, vec_float4 val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline vec_float4 Matrix3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Matrix3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Matrix3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Matrix3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Matrix3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::getRow( int row ) const +{ + return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); +} + +inline Vector3 & Matrix3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix3 & Matrix3::operator =( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + return *this; +} + +inline const Matrix3 transpose( const Matrix3 & mat ) +{ + return Matrix3( + Vector3( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX() ), + Vector3( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY() ), + Vector3( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ() ) + ); +} + +inline const Matrix3 inverse( const Matrix3 & mat ) +{ + Vector3 tmp0, tmp1, tmp2; + vec_float4 detinv; + tmp0 = cross( mat.getCol1(), mat.getCol2() ); + tmp1 = cross( mat.getCol2(), mat.getCol0() ); + tmp2 = cross( mat.getCol0(), mat.getCol1() ); + detinv = recipf4( dot( mat.getCol2(), tmp2 ) ); + return Matrix3( + Vector3( spu_mul( tmp0.getX(), detinv ), spu_mul( tmp1.getX(), detinv ), spu_mul( tmp2.getX(), detinv ) ), + Vector3( spu_mul( tmp0.getY(), detinv ), spu_mul( tmp1.getY(), detinv ), spu_mul( tmp2.getY(), detinv ) ), + Vector3( spu_mul( tmp0.getZ(), detinv ), spu_mul( tmp1.getZ(), detinv ), spu_mul( tmp2.getZ(), detinv ) ) + ); +} + +inline vec_float4 determinant( const Matrix3 & mat ) +{ + return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); +} + +inline const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ) + ); +} + +inline const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix3 Matrix3::operator -( ) const +{ + return Matrix3( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ) + ); +} + +inline const Matrix3 absPerElem( const Matrix3 & mat ) +{ + return Matrix3( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::operator *( vec_float4 scalar ) const +{ + return Matrix3( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ) + ); +} + +inline Matrix3 & Matrix3::operator *=( vec_float4 scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix3 operator *( vec_float4 scalar, const Matrix3 & mat ) +{ + return mat * scalar; +} + +inline const Vector3 Matrix3::operator *( const Vector3 & vec ) const +{ + return Vector3( + spu_add( spu_add( spu_mul( mCol0.getX(), vec.getX() ), spu_mul( mCol1.getX(), vec.getY() ) ), spu_mul( mCol2.getX(), vec.getZ() ) ), + spu_add( spu_add( spu_mul( mCol0.getY(), vec.getX() ), spu_mul( mCol1.getY(), vec.getY() ) ), spu_mul( mCol2.getY(), vec.getZ() ) ), + spu_add( spu_add( spu_mul( mCol0.getZ(), vec.getX() ), spu_mul( mCol1.getZ(), vec.getY() ) ), spu_mul( mCol2.getZ(), vec.getZ() ) ) + ); +} + +inline const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const +{ + return Matrix3( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) +{ + return Matrix3( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::identity( ) +{ + return Matrix3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationX( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Matrix3( + Vector3::xAxis( ), + Vector3( spu_splats(0.0f), c, s ), + Vector3( spu_splats(0.0f), negatef4( s ), c ) + ); +} + +inline const Matrix3 Matrix3::rotationY( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Matrix3( + Vector3( c, spu_splats(0.0f), negatef4( s ) ), + Vector3::yAxis( ), + Vector3( s, spu_splats(0.0f), c ) + ); +} + +inline const Matrix3 Matrix3::rotationZ( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Matrix3( + Vector3( c, s, spu_splats(0.0f) ), + Vector3( negatef4( s ), c, spu_splats(0.0f) ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationZYX( const Vector3 & radiansXYZ ) +{ + vec_float4 sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sincosf4( radiansXYZ.getX(), &sX, &cX ); + sincosf4( radiansXYZ.getY(), &sY, &cY ); + sincosf4( radiansXYZ.getZ(), &sZ, &cZ ); + tmp0 = spu_mul( cZ, sY ); + tmp1 = spu_mul( sZ, sY ); + return Matrix3( + Vector3( spu_mul( cZ, cY ), spu_mul( sZ, cY ), negatef4( sY ) ), + Vector3( spu_sub( spu_mul( tmp0, sX ), spu_mul( sZ, cX ) ), spu_add( spu_mul( tmp1, sX ), spu_mul( cZ, cX ) ), spu_mul( cY, sX ) ), + Vector3( spu_add( spu_mul( tmp0, cX ), spu_mul( sZ, sX ) ), spu_sub( spu_mul( tmp1, cX ), spu_mul( cZ, sX ) ), spu_mul( cY, cX ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( vec_float4 radians, const Vector3 & unitVec ) +{ + vec_float4 x, y, z, s, c, oneMinusC, xy, yz, zx; + sincosf4( radians, &s, &c ); + x = unitVec.getX(); + y = unitVec.getY(); + z = unitVec.getZ(); + xy = spu_mul( x, y ); + yz = spu_mul( y, z ); + zx = spu_mul( z, x ); + oneMinusC = spu_sub( spu_splats(1.0f), c ); + return Matrix3( + Vector3( spu_add( spu_mul( spu_mul( x, x ), oneMinusC ), c ), spu_add( spu_mul( xy, oneMinusC ), spu_mul( z, s ) ), spu_sub( spu_mul( zx, oneMinusC ), spu_mul( y, s ) ) ), + Vector3( spu_sub( spu_mul( xy, oneMinusC ), spu_mul( z, s ) ), spu_add( spu_mul( spu_mul( y, y ), oneMinusC ), c ), spu_add( spu_mul( yz, oneMinusC ), spu_mul( x, s ) ) ), + Vector3( spu_add( spu_mul( zx, oneMinusC ), spu_mul( y, s ) ), spu_sub( spu_mul( yz, oneMinusC ), spu_mul( x, s ) ), spu_add( spu_mul( spu_mul( z, z ), oneMinusC ), c ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( const Quat & unitQuat ) +{ + return Matrix3( unitQuat ); +} + +inline const Matrix3 Matrix3::scale( const Vector3 & scaleVec ) +{ + return Matrix3( + Vector3( scaleVec.getX(), spu_splats(0.0f), spu_splats(0.0f) ), + Vector3( spu_splats(0.0f), scaleVec.getY(), spu_splats(0.0f) ), + Vector3( spu_splats(0.0f), spu_splats(0.0f), scaleVec.getZ() ) + ); +} + +inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ) +{ + return Matrix3( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ) + ); +} + +inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ) +{ + return Matrix3( + mulPerElem( mat.getCol0(), scaleVec ), + mulPerElem( mat.getCol1(), scaleVec ), + mulPerElem( mat.getCol2(), scaleVec ) + ); +} + +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, vec_uint4 select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix3 & mat ) +{ + Aos::Matrix3 mat0, mat1, mat2, mat3; + mat.get4Aos( mat0, mat1, mat2, mat3 ); + printf("slot 0:\n"); + print( mat0 ); + printf("slot 1:\n"); + print( mat1 ); + printf("slot 2:\n"); + print( mat2 ); + printf("slot 3:\n"); + print( mat3 ); +} + +inline void print( const Matrix3 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Matrix4::Matrix4( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; +} + +inline Matrix4::Matrix4( vec_float4 scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +inline Matrix4::Matrix4( const Transform3 & mat ) +{ + mCol0 = Vector4( mat.getCol0(), spu_splats(0.0f) ); + mCol1 = Vector4( mat.getCol1(), spu_splats(0.0f) ); + mCol2 = Vector4( mat.getCol2(), spu_splats(0.0f) ); + mCol3 = Vector4( mat.getCol3(), spu_splats(1.0f) ); +} + +inline Matrix4::Matrix4( const Vector4 & _col0, const Vector4 & _col1, const Vector4 & _col2, const Vector4 & _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Matrix4::Matrix4( const Matrix3 & mat, const Vector3 & translateVec ) +{ + mCol0 = Vector4( mat.getCol0(), spu_splats(0.0f) ); + mCol1 = Vector4( mat.getCol1(), spu_splats(0.0f) ); + mCol2 = Vector4( mat.getCol2(), spu_splats(0.0f) ); + mCol3 = Vector4( translateVec, spu_splats(1.0f) ); +} + +inline Matrix4::Matrix4( const Quat & unitQuat, const Vector3 & translateVec ) +{ + Matrix3 mat; + mat = Matrix3( unitQuat ); + mCol0 = Vector4( mat.getCol0(), spu_splats(0.0f) ); + mCol1 = Vector4( mat.getCol1(), spu_splats(0.0f) ); + mCol2 = Vector4( mat.getCol2(), spu_splats(0.0f) ); + mCol3 = Vector4( translateVec, spu_splats(1.0f) ); +} + +inline Matrix4::Matrix4( const Aos::Matrix4 & mat ) +{ + mCol0 = Vector4( mat.getCol0() ); + mCol1 = Vector4( mat.getCol1() ); + mCol2 = Vector4( mat.getCol2() ); + mCol3 = Vector4( mat.getCol3() ); +} + +inline Matrix4::Matrix4( const Aos::Matrix4 & mat0, const Aos::Matrix4 & mat1, const Aos::Matrix4 & mat2, const Aos::Matrix4 & mat3 ) +{ + mCol0 = Vector4( mat0.getCol0(), mat1.getCol0(), mat2.getCol0(), mat3.getCol0() ); + mCol1 = Vector4( mat0.getCol1(), mat1.getCol1(), mat2.getCol1(), mat3.getCol1() ); + mCol2 = Vector4( mat0.getCol2(), mat1.getCol2(), mat2.getCol2(), mat3.getCol2() ); + mCol3 = Vector4( mat0.getCol3(), mat1.getCol3(), mat2.getCol3(), mat3.getCol3() ); +} + +inline void Matrix4::get4Aos( Aos::Matrix4 & result0, Aos::Matrix4 & result1, Aos::Matrix4 & result2, Aos::Matrix4 & result3 ) const +{ + Aos::Vector4 tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3; + mCol0.get4Aos( tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3 ); + result0.setCol0( tmpV4_0 ); + result1.setCol0( tmpV4_1 ); + result2.setCol0( tmpV4_2 ); + result3.setCol0( tmpV4_3 ); + mCol1.get4Aos( tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3 ); + result0.setCol1( tmpV4_0 ); + result1.setCol1( tmpV4_1 ); + result2.setCol1( tmpV4_2 ); + result3.setCol1( tmpV4_3 ); + mCol2.get4Aos( tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3 ); + result0.setCol2( tmpV4_0 ); + result1.setCol2( tmpV4_1 ); + result2.setCol2( tmpV4_2 ); + result3.setCol2( tmpV4_3 ); + mCol3.get4Aos( tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3 ); + result0.setCol3( tmpV4_0 ); + result1.setCol3( tmpV4_1 ); + result2.setCol3( tmpV4_2 ); + result3.setCol3( tmpV4_3 ); +} + +inline Matrix4 & Matrix4::setCol0( const Vector4 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix4 & Matrix4::setCol1( const Vector4 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix4 & Matrix4::setCol2( const Vector4 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix4 & Matrix4::setCol3( const Vector4 & _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Matrix4 & Matrix4::setCol( int col, const Vector4 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix4 & Matrix4::setRow( int row, const Vector4 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Matrix4 & Matrix4::setElem( int col, int row, vec_float4 val ) +{ + Vector4 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline vec_float4 Matrix4::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector4 Matrix4::getCol0( ) const +{ + return mCol0; +} + +inline const Vector4 Matrix4::getCol1( ) const +{ + return mCol1; +} + +inline const Vector4 Matrix4::getCol2( ) const +{ + return mCol2; +} + +inline const Vector4 Matrix4::getCol3( ) const +{ + return mCol3; +} + +inline const Vector4 Matrix4::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector4 & Matrix4::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix4 & Matrix4::operator =( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; + return *this; +} + +inline const Matrix4 transpose( const Matrix4 & mat ) +{ + return Matrix4( + Vector4( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX(), mat.getCol3().getX() ), + Vector4( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY(), mat.getCol3().getY() ), + Vector4( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ(), mat.getCol3().getZ() ), + Vector4( mat.getCol0().getW(), mat.getCol1().getW(), mat.getCol2().getW(), mat.getCol3().getW() ) + ); +} + +inline const Matrix4 inverse( const Matrix4 & mat ) +{ + Vector4 res0, res1, res2, res3; + vec_float4 mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, detInv; + mA = mat.getCol0().getX(); + mB = mat.getCol0().getY(); + mC = mat.getCol0().getZ(); + mD = mat.getCol0().getW(); + mE = mat.getCol1().getX(); + mF = mat.getCol1().getY(); + mG = mat.getCol1().getZ(); + mH = mat.getCol1().getW(); + mI = mat.getCol2().getX(); + mJ = mat.getCol2().getY(); + mK = mat.getCol2().getZ(); + mL = mat.getCol2().getW(); + mM = mat.getCol3().getX(); + mN = mat.getCol3().getY(); + mO = mat.getCol3().getZ(); + mP = mat.getCol3().getW(); + tmp0 = spu_sub( spu_mul( mK, mD ), spu_mul( mC, mL ) ); + tmp1 = spu_sub( spu_mul( mO, mH ), spu_mul( mG, mP ) ); + tmp2 = spu_sub( spu_mul( mB, mK ), spu_mul( mJ, mC ) ); + tmp3 = spu_sub( spu_mul( mF, mO ), spu_mul( mN, mG ) ); + tmp4 = spu_sub( spu_mul( mJ, mD ), spu_mul( mB, mL ) ); + tmp5 = spu_sub( spu_mul( mN, mH ), spu_mul( mF, mP ) ); + res0.setX( spu_sub( spu_sub( spu_mul( mJ, tmp1 ), spu_mul( mL, tmp3 ) ), spu_mul( mK, tmp5 ) ) ); + res0.setY( spu_sub( spu_sub( spu_mul( mN, tmp0 ), spu_mul( mP, tmp2 ) ), spu_mul( mO, tmp4 ) ) ); + res0.setZ( spu_sub( spu_add( spu_mul( mD, tmp3 ), spu_mul( mC, tmp5 ) ), spu_mul( mB, tmp1 ) ) ); + res0.setW( spu_sub( spu_add( spu_mul( mH, tmp2 ), spu_mul( mG, tmp4 ) ), spu_mul( mF, tmp0 ) ) ); + detInv = recipf4( spu_add( spu_add( spu_add( spu_mul( mA, res0.getX() ), spu_mul( mE, res0.getY() ) ), spu_mul( mI, res0.getZ() ) ), spu_mul( mM, res0.getW() ) ) ); + res1.setX( spu_mul( mI, tmp1 ) ); + res1.setY( spu_mul( mM, tmp0 ) ); + res1.setZ( spu_mul( mA, tmp1 ) ); + res1.setW( spu_mul( mE, tmp0 ) ); + res3.setX( spu_mul( mI, tmp3 ) ); + res3.setY( spu_mul( mM, tmp2 ) ); + res3.setZ( spu_mul( mA, tmp3 ) ); + res3.setW( spu_mul( mE, tmp2 ) ); + res2.setX( spu_mul( mI, tmp5 ) ); + res2.setY( spu_mul( mM, tmp4 ) ); + res2.setZ( spu_mul( mA, tmp5 ) ); + res2.setW( spu_mul( mE, tmp4 ) ); + tmp0 = spu_sub( spu_mul( mI, mB ), spu_mul( mA, mJ ) ); + tmp1 = spu_sub( spu_mul( mM, mF ), spu_mul( mE, mN ) ); + tmp2 = spu_sub( spu_mul( mI, mD ), spu_mul( mA, mL ) ); + tmp3 = spu_sub( spu_mul( mM, mH ), spu_mul( mE, mP ) ); + tmp4 = spu_sub( spu_mul( mI, mC ), spu_mul( mA, mK ) ); + tmp5 = spu_sub( spu_mul( mM, mG ), spu_mul( mE, mO ) ); + res2.setX( spu_add( spu_sub( spu_mul( mL, tmp1 ), spu_mul( mJ, tmp3 ) ), res2.getX() ) ); + res2.setY( spu_add( spu_sub( spu_mul( mP, tmp0 ), spu_mul( mN, tmp2 ) ), res2.getY() ) ); + res2.setZ( spu_sub( spu_sub( spu_mul( mB, tmp3 ), spu_mul( mD, tmp1 ) ), res2.getZ() ) ); + res2.setW( spu_sub( spu_sub( spu_mul( mF, tmp2 ), spu_mul( mH, tmp0 ) ), res2.getW() ) ); + res3.setX( spu_add( spu_sub( spu_mul( mJ, tmp5 ), spu_mul( mK, tmp1 ) ), res3.getX() ) ); + res3.setY( spu_add( spu_sub( spu_mul( mN, tmp4 ), spu_mul( mO, tmp0 ) ), res3.getY() ) ); + res3.setZ( spu_sub( spu_sub( spu_mul( mC, tmp1 ), spu_mul( mB, tmp5 ) ), res3.getZ() ) ); + res3.setW( spu_sub( spu_sub( spu_mul( mG, tmp0 ), spu_mul( mF, tmp4 ) ), res3.getW() ) ); + res1.setX( spu_sub( spu_sub( spu_mul( mK, tmp3 ), spu_mul( mL, tmp5 ) ), res1.getX() ) ); + res1.setY( spu_sub( spu_sub( spu_mul( mO, tmp2 ), spu_mul( mP, tmp4 ) ), res1.getY() ) ); + res1.setZ( spu_add( spu_sub( spu_mul( mD, tmp5 ), spu_mul( mC, tmp3 ) ), res1.getZ() ) ); + res1.setW( spu_add( spu_sub( spu_mul( mH, tmp4 ), spu_mul( mG, tmp2 ) ), res1.getW() ) ); + return Matrix4( + ( res0 * detInv ), + ( res1 * detInv ), + ( res2 * detInv ), + ( res3 * detInv ) + ); +} + +inline const Matrix4 affineInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( inverse( affineMat ) ); +} + +inline const Matrix4 orthoInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( orthoInverse( affineMat ) ); +} + +inline vec_float4 determinant( const Matrix4 & mat ) +{ + vec_float4 dx, dy, dz, dw, mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + mA = mat.getCol0().getX(); + mB = mat.getCol0().getY(); + mC = mat.getCol0().getZ(); + mD = mat.getCol0().getW(); + mE = mat.getCol1().getX(); + mF = mat.getCol1().getY(); + mG = mat.getCol1().getZ(); + mH = mat.getCol1().getW(); + mI = mat.getCol2().getX(); + mJ = mat.getCol2().getY(); + mK = mat.getCol2().getZ(); + mL = mat.getCol2().getW(); + mM = mat.getCol3().getX(); + mN = mat.getCol3().getY(); + mO = mat.getCol3().getZ(); + mP = mat.getCol3().getW(); + tmp0 = spu_sub( spu_mul( mK, mD ), spu_mul( mC, mL ) ); + tmp1 = spu_sub( spu_mul( mO, mH ), spu_mul( mG, mP ) ); + tmp2 = spu_sub( spu_mul( mB, mK ), spu_mul( mJ, mC ) ); + tmp3 = spu_sub( spu_mul( mF, mO ), spu_mul( mN, mG ) ); + tmp4 = spu_sub( spu_mul( mJ, mD ), spu_mul( mB, mL ) ); + tmp5 = spu_sub( spu_mul( mN, mH ), spu_mul( mF, mP ) ); + dx = spu_sub( spu_sub( spu_mul( mJ, tmp1 ), spu_mul( mL, tmp3 ) ), spu_mul( mK, tmp5 ) ); + dy = spu_sub( spu_sub( spu_mul( mN, tmp0 ), spu_mul( mP, tmp2 ) ), spu_mul( mO, tmp4 ) ); + dz = spu_sub( spu_add( spu_mul( mD, tmp3 ), spu_mul( mC, tmp5 ) ), spu_mul( mB, tmp1 ) ); + dw = spu_sub( spu_add( spu_mul( mH, tmp2 ), spu_mul( mG, tmp4 ) ), spu_mul( mF, tmp0 ) ); + return spu_add( spu_add( spu_add( spu_mul( mA, dx ), spu_mul( mE, dy ) ), spu_mul( mI, dz ) ), spu_mul( mM, dw ) ); +} + +inline const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ), + ( mCol3 + mat.mCol3 ) + ); +} + +inline const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ), + ( mCol3 - mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix4 Matrix4::operator -( ) const +{ + return Matrix4( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ), + ( -mCol3 ) + ); +} + +inline const Matrix4 absPerElem( const Matrix4 & mat ) +{ + return Matrix4( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ), + absPerElem( mat.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::operator *( vec_float4 scalar ) const +{ + return Matrix4( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ), + ( mCol3 * scalar ) + ); +} + +inline Matrix4 & Matrix4::operator *=( vec_float4 scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix4 operator *( vec_float4 scalar, const Matrix4 & mat ) +{ + return mat * scalar; +} + +inline const Vector4 Matrix4::operator *( const Vector4 & vec ) const +{ + return Vector4( + spu_add( spu_add( spu_add( spu_mul( mCol0.getX(), vec.getX() ), spu_mul( mCol1.getX(), vec.getY() ) ), spu_mul( mCol2.getX(), vec.getZ() ) ), spu_mul( mCol3.getX(), vec.getW() ) ), + spu_add( spu_add( spu_add( spu_mul( mCol0.getY(), vec.getX() ), spu_mul( mCol1.getY(), vec.getY() ) ), spu_mul( mCol2.getY(), vec.getZ() ) ), spu_mul( mCol3.getY(), vec.getW() ) ), + spu_add( spu_add( spu_add( spu_mul( mCol0.getZ(), vec.getX() ), spu_mul( mCol1.getZ(), vec.getY() ) ), spu_mul( mCol2.getZ(), vec.getZ() ) ), spu_mul( mCol3.getZ(), vec.getW() ) ), + spu_add( spu_add( spu_add( spu_mul( mCol0.getW(), vec.getX() ), spu_mul( mCol1.getW(), vec.getY() ) ), spu_mul( mCol2.getW(), vec.getZ() ) ), spu_mul( mCol3.getW(), vec.getW() ) ) + ); +} + +inline const Vector4 Matrix4::operator *( const Vector3 & vec ) const +{ + return Vector4( + spu_add( spu_add( spu_mul( mCol0.getX(), vec.getX() ), spu_mul( mCol1.getX(), vec.getY() ) ), spu_mul( mCol2.getX(), vec.getZ() ) ), + spu_add( spu_add( spu_mul( mCol0.getY(), vec.getX() ), spu_mul( mCol1.getY(), vec.getY() ) ), spu_mul( mCol2.getY(), vec.getZ() ) ), + spu_add( spu_add( spu_mul( mCol0.getZ(), vec.getX() ), spu_mul( mCol1.getZ(), vec.getY() ) ), spu_mul( mCol2.getZ(), vec.getZ() ) ), + spu_add( spu_add( spu_mul( mCol0.getW(), vec.getX() ), spu_mul( mCol1.getW(), vec.getY() ) ), spu_mul( mCol2.getW(), vec.getZ() ) ) + ); +} + +inline const Vector4 Matrix4::operator *( const Point3 & pnt ) const +{ + return Vector4( + spu_add( spu_add( spu_add( spu_mul( mCol0.getX(), pnt.getX() ), spu_mul( mCol1.getX(), pnt.getY() ) ), spu_mul( mCol2.getX(), pnt.getZ() ) ), mCol3.getX() ), + spu_add( spu_add( spu_add( spu_mul( mCol0.getY(), pnt.getX() ), spu_mul( mCol1.getY(), pnt.getY() ) ), spu_mul( mCol2.getY(), pnt.getZ() ) ), mCol3.getY() ), + spu_add( spu_add( spu_add( spu_mul( mCol0.getZ(), pnt.getX() ), spu_mul( mCol1.getZ(), pnt.getY() ) ), spu_mul( mCol2.getZ(), pnt.getZ() ) ), mCol3.getZ() ), + spu_add( spu_add( spu_add( spu_mul( mCol0.getW(), pnt.getX() ), spu_mul( mCol1.getW(), pnt.getY() ) ), spu_mul( mCol2.getW(), pnt.getZ() ) ), mCol3.getW() ) + ); +} + +inline const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const +{ + return Matrix4( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ), + ( *this * mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const +{ + return Matrix4( + ( *this * tfrm.getCol0() ), + ( *this * tfrm.getCol1() ), + ( *this * tfrm.getCol2() ), + ( *this * Point3( tfrm.getCol3() ) ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) +{ + return Matrix4( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ), + mulPerElem( mat0.getCol3(), mat1.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::identity( ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) +{ + mCol0.setXYZ( mat3.getCol0() ); + mCol1.setXYZ( mat3.getCol1() ); + mCol2.setXYZ( mat3.getCol2() ); + return *this; +} + +inline const Matrix3 Matrix4::getUpper3x3( ) const +{ + return Matrix3( + mCol0.getXYZ( ), + mCol1.getXYZ( ), + mCol2.getXYZ( ) + ); +} + +inline Matrix4 & Matrix4::setTranslation( const Vector3 & translateVec ) +{ + mCol3.setXYZ( translateVec ); + return *this; +} + +inline const Vector3 Matrix4::getTranslation( ) const +{ + return mCol3.getXYZ( ); +} + +inline const Matrix4 Matrix4::rotationX( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Matrix4( + Vector4::xAxis( ), + Vector4( spu_splats(0.0f), c, s, spu_splats(0.0f) ), + Vector4( spu_splats(0.0f), negatef4( s ), c, spu_splats(0.0f) ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationY( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Matrix4( + Vector4( c, spu_splats(0.0f), negatef4( s ), spu_splats(0.0f) ), + Vector4::yAxis( ), + Vector4( s, spu_splats(0.0f), c, spu_splats(0.0f) ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZ( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Matrix4( + Vector4( c, s, spu_splats(0.0f), spu_splats(0.0f) ), + Vector4( negatef4( s ), c, spu_splats(0.0f), spu_splats(0.0f) ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZYX( const Vector3 & radiansXYZ ) +{ + vec_float4 sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sincosf4( radiansXYZ.getX(), &sX, &cX ); + sincosf4( radiansXYZ.getY(), &sY, &cY ); + sincosf4( radiansXYZ.getZ(), &sZ, &cZ ); + tmp0 = spu_mul( cZ, sY ); + tmp1 = spu_mul( sZ, sY ); + return Matrix4( + Vector4( spu_mul( cZ, cY ), spu_mul( sZ, cY ), negatef4( sY ), spu_splats(0.0f) ), + Vector4( spu_sub( spu_mul( tmp0, sX ), spu_mul( sZ, cX ) ), spu_add( spu_mul( tmp1, sX ), spu_mul( cZ, cX ) ), spu_mul( cY, sX ), spu_splats(0.0f) ), + Vector4( spu_add( spu_mul( tmp0, cX ), spu_mul( sZ, sX ) ), spu_sub( spu_mul( tmp1, cX ), spu_mul( cZ, sX ) ), spu_mul( cY, cX ), spu_splats(0.0f) ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( vec_float4 radians, const Vector3 & unitVec ) +{ + vec_float4 x, y, z, s, c, oneMinusC, xy, yz, zx; + sincosf4( radians, &s, &c ); + x = unitVec.getX(); + y = unitVec.getY(); + z = unitVec.getZ(); + xy = spu_mul( x, y ); + yz = spu_mul( y, z ); + zx = spu_mul( z, x ); + oneMinusC = spu_sub( spu_splats(1.0f), c ); + return Matrix4( + Vector4( spu_add( spu_mul( spu_mul( x, x ), oneMinusC ), c ), spu_add( spu_mul( xy, oneMinusC ), spu_mul( z, s ) ), spu_sub( spu_mul( zx, oneMinusC ), spu_mul( y, s ) ), spu_splats(0.0f) ), + Vector4( spu_sub( spu_mul( xy, oneMinusC ), spu_mul( z, s ) ), spu_add( spu_mul( spu_mul( y, y ), oneMinusC ), c ), spu_add( spu_mul( yz, oneMinusC ), spu_mul( x, s ) ), spu_splats(0.0f) ), + Vector4( spu_add( spu_mul( zx, oneMinusC ), spu_mul( y, s ) ), spu_sub( spu_mul( yz, oneMinusC ), spu_mul( x, s ) ), spu_add( spu_mul( spu_mul( z, z ), oneMinusC ), c ), spu_splats(0.0f) ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( const Quat & unitQuat ) +{ + return Matrix4( Transform3::rotation( unitQuat ) ); +} + +inline const Matrix4 Matrix4::scale( const Vector3 & scaleVec ) +{ + return Matrix4( + Vector4( scaleVec.getX(), spu_splats(0.0f), spu_splats(0.0f), spu_splats(0.0f) ), + Vector4( spu_splats(0.0f), scaleVec.getY(), spu_splats(0.0f), spu_splats(0.0f) ), + Vector4( spu_splats(0.0f), spu_splats(0.0f), scaleVec.getZ(), spu_splats(0.0f) ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ) +{ + return Matrix4( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ), + mat.getCol3() + ); +} + +inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ) +{ + Vector4 scale4; + scale4 = Vector4( scaleVec, spu_splats(1.0f) ); + return Matrix4( + mulPerElem( mat.getCol0(), scale4 ), + mulPerElem( mat.getCol1(), scale4 ), + mulPerElem( mat.getCol2(), scale4 ), + mulPerElem( mat.getCol3(), scale4 ) + ); +} + +inline const Matrix4 Matrix4::translation( const Vector3 & translateVec ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4( translateVec, spu_splats(1.0f) ) + ); +} + +inline const Matrix4 Matrix4::lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ) +{ + Matrix4 m4EyeFrame; + Vector3 v3X, v3Y, v3Z; + v3Y = normalize( upVec ); + v3Z = normalize( ( eyePos - lookAtPos ) ); + v3X = normalize( cross( v3Y, v3Z ) ); + v3Y = cross( v3Z, v3X ); + m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); + return orthoInverse( m4EyeFrame ); +} + +inline const Matrix4 Matrix4::perspective( vec_float4 fovyRadians, vec_float4 aspect, vec_float4 zNear, vec_float4 zFar ) +{ + vec_float4 f, rangeInv; + f = tanf4( spu_sub( spu_splats( _VECTORMATH_PI_OVER_2 ), spu_mul( spu_splats(0.5f), fovyRadians ) ) ); + rangeInv = recipf4( spu_sub( zNear, zFar ) ); + return Matrix4( + Vector4( divf4( f, aspect ), spu_splats(0.0f), spu_splats(0.0f), spu_splats(0.0f) ), + Vector4( spu_splats(0.0f), f, spu_splats(0.0f), spu_splats(0.0f) ), + Vector4( spu_splats(0.0f), spu_splats(0.0f), spu_mul( spu_add( zNear, zFar ), rangeInv ), spu_splats(-1.0f) ), + Vector4( spu_splats(0.0f), spu_splats(0.0f), spu_mul( spu_mul( spu_mul( zNear, zFar ), rangeInv ), spu_splats(2.0f) ), spu_splats(0.0f) ) + ); +} + +inline const Matrix4 Matrix4::frustum( vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ) +{ + vec_float4 sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf, n2; + sum_rl = spu_add( right, left ); + sum_tb = spu_add( top, bottom ); + sum_nf = spu_add( zNear, zFar ); + inv_rl = recipf4( spu_sub( right, left ) ); + inv_tb = recipf4( spu_sub( top, bottom ) ); + inv_nf = recipf4( spu_sub( zNear, zFar ) ); + n2 = spu_add( zNear, zNear ); + return Matrix4( + Vector4( spu_mul( n2, inv_rl ), spu_splats(0.0f), spu_splats(0.0f), spu_splats(0.0f) ), + Vector4( spu_splats(0.0f), spu_mul( n2, inv_tb ), spu_splats(0.0f), spu_splats(0.0f) ), + Vector4( spu_mul( sum_rl, inv_rl ), spu_mul( sum_tb, inv_tb ), spu_mul( sum_nf, inv_nf ), spu_splats(-1.0f) ), + Vector4( spu_splats(0.0f), spu_splats(0.0f), spu_mul( spu_mul( n2, inv_nf ), zFar ), spu_splats(0.0f) ) + ); +} + +inline const Matrix4 Matrix4::orthographic( vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ) +{ + vec_float4 sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf; + sum_rl = spu_add( right, left ); + sum_tb = spu_add( top, bottom ); + sum_nf = spu_add( zNear, zFar ); + inv_rl = recipf4( spu_sub( right, left ) ); + inv_tb = recipf4( spu_sub( top, bottom ) ); + inv_nf = recipf4( spu_sub( zNear, zFar ) ); + return Matrix4( + Vector4( spu_add( inv_rl, inv_rl ), spu_splats(0.0f), spu_splats(0.0f), spu_splats(0.0f) ), + Vector4( spu_splats(0.0f), spu_add( inv_tb, inv_tb ), spu_splats(0.0f), spu_splats(0.0f) ), + Vector4( spu_splats(0.0f), spu_splats(0.0f), spu_add( inv_nf, inv_nf ), spu_splats(0.0f) ), + Vector4( spu_mul( negatef4( sum_rl ), inv_rl ), spu_mul( negatef4( sum_tb ), inv_tb ), spu_mul( sum_nf, inv_nf ), spu_splats(1.0f) ) + ); +} + +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, vec_uint4 select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix4 & mat ) +{ + Aos::Matrix4 mat0, mat1, mat2, mat3; + mat.get4Aos( mat0, mat1, mat2, mat3 ); + printf("slot 0:\n"); + print( mat0 ); + printf("slot 1:\n"); + print( mat1 ); + printf("slot 2:\n"); + print( mat2 ); + printf("slot 3:\n"); + print( mat3 ); +} + +inline void print( const Matrix4 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Transform3::Transform3( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; +} + +inline Transform3::Transform3( vec_float4 scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +inline Transform3::Transform3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2, const Vector3 & _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Transform3::Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ) +{ + this->setUpper3x3( tfrm ); + this->setTranslation( translateVec ); +} + +inline Transform3::Transform3( const Quat & unitQuat, const Vector3 & translateVec ) +{ + this->setUpper3x3( Matrix3( unitQuat ) ); + this->setTranslation( translateVec ); +} + +inline Transform3::Transform3( const Aos::Transform3 & tfrm ) +{ + mCol0 = Vector3( tfrm.getCol0() ); + mCol1 = Vector3( tfrm.getCol1() ); + mCol2 = Vector3( tfrm.getCol2() ); + mCol3 = Vector3( tfrm.getCol3() ); +} + +inline Transform3::Transform3( const Aos::Transform3 & tfrm0, const Aos::Transform3 & tfrm1, const Aos::Transform3 & tfrm2, const Aos::Transform3 & tfrm3 ) +{ + mCol0 = Vector3( tfrm0.getCol0(), tfrm1.getCol0(), tfrm2.getCol0(), tfrm3.getCol0() ); + mCol1 = Vector3( tfrm0.getCol1(), tfrm1.getCol1(), tfrm2.getCol1(), tfrm3.getCol1() ); + mCol2 = Vector3( tfrm0.getCol2(), tfrm1.getCol2(), tfrm2.getCol2(), tfrm3.getCol2() ); + mCol3 = Vector3( tfrm0.getCol3(), tfrm1.getCol3(), tfrm2.getCol3(), tfrm3.getCol3() ); +} + +inline void Transform3::get4Aos( Aos::Transform3 & result0, Aos::Transform3 & result1, Aos::Transform3 & result2, Aos::Transform3 & result3 ) const +{ + Aos::Vector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + mCol0.get4Aos( tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3 ); + result0.setCol0( tmpV3_0 ); + result1.setCol0( tmpV3_1 ); + result2.setCol0( tmpV3_2 ); + result3.setCol0( tmpV3_3 ); + mCol1.get4Aos( tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3 ); + result0.setCol1( tmpV3_0 ); + result1.setCol1( tmpV3_1 ); + result2.setCol1( tmpV3_2 ); + result3.setCol1( tmpV3_3 ); + mCol2.get4Aos( tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3 ); + result0.setCol2( tmpV3_0 ); + result1.setCol2( tmpV3_1 ); + result2.setCol2( tmpV3_2 ); + result3.setCol2( tmpV3_3 ); + mCol3.get4Aos( tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3 ); + result0.setCol3( tmpV3_0 ); + result1.setCol3( tmpV3_1 ); + result2.setCol3( tmpV3_2 ); + result3.setCol3( tmpV3_3 ); +} + +inline Transform3 & Transform3::setCol0( const Vector3 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Transform3 & Transform3::setCol1( const Vector3 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Transform3 & Transform3::setCol2( const Vector3 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Transform3 & Transform3::setCol3( const Vector3 & _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Transform3 & Transform3::setCol( int col, const Vector3 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Transform3 & Transform3::setRow( int row, const Vector4 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Transform3 & Transform3::setElem( int col, int row, vec_float4 val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline vec_float4 Transform3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Transform3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Transform3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Transform3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Transform3::getCol3( ) const +{ + return mCol3; +} + +inline const Vector3 Transform3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Transform3::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector3 & Transform3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Transform3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Transform3 & Transform3::operator =( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; + return *this; +} + +inline const Transform3 inverse( const Transform3 & tfrm ) +{ + Vector3 tmp0, tmp1, tmp2, inv0, inv1, inv2; + vec_float4 detinv; + tmp0 = cross( tfrm.getCol1(), tfrm.getCol2() ); + tmp1 = cross( tfrm.getCol2(), tfrm.getCol0() ); + tmp2 = cross( tfrm.getCol0(), tfrm.getCol1() ); + detinv = recipf4( dot( tfrm.getCol2(), tmp2 ) ); + inv0 = Vector3( spu_mul( tmp0.getX(), detinv ), spu_mul( tmp1.getX(), detinv ), spu_mul( tmp2.getX(), detinv ) ); + inv1 = Vector3( spu_mul( tmp0.getY(), detinv ), spu_mul( tmp1.getY(), detinv ), spu_mul( tmp2.getY(), detinv ) ); + inv2 = Vector3( spu_mul( tmp0.getZ(), detinv ), spu_mul( tmp1.getZ(), detinv ), spu_mul( tmp2.getZ(), detinv ) ); + return Transform3( + inv0, + inv1, + inv2, + Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) + ); +} + +inline const Transform3 orthoInverse( const Transform3 & tfrm ) +{ + Vector3 inv0, inv1, inv2; + inv0 = Vector3( tfrm.getCol0().getX(), tfrm.getCol1().getX(), tfrm.getCol2().getX() ); + inv1 = Vector3( tfrm.getCol0().getY(), tfrm.getCol1().getY(), tfrm.getCol2().getY() ); + inv2 = Vector3( tfrm.getCol0().getZ(), tfrm.getCol1().getZ(), tfrm.getCol2().getZ() ); + return Transform3( + inv0, + inv1, + inv2, + Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) + ); +} + +inline const Transform3 absPerElem( const Transform3 & tfrm ) +{ + return Transform3( + absPerElem( tfrm.getCol0() ), + absPerElem( tfrm.getCol1() ), + absPerElem( tfrm.getCol2() ), + absPerElem( tfrm.getCol3() ) + ); +} + +inline const Vector3 Transform3::operator *( const Vector3 & vec ) const +{ + return Vector3( + spu_add( spu_add( spu_mul( mCol0.getX(), vec.getX() ), spu_mul( mCol1.getX(), vec.getY() ) ), spu_mul( mCol2.getX(), vec.getZ() ) ), + spu_add( spu_add( spu_mul( mCol0.getY(), vec.getX() ), spu_mul( mCol1.getY(), vec.getY() ) ), spu_mul( mCol2.getY(), vec.getZ() ) ), + spu_add( spu_add( spu_mul( mCol0.getZ(), vec.getX() ), spu_mul( mCol1.getZ(), vec.getY() ) ), spu_mul( mCol2.getZ(), vec.getZ() ) ) + ); +} + +inline const Point3 Transform3::operator *( const Point3 & pnt ) const +{ + return Point3( + spu_add( spu_add( spu_add( spu_mul( mCol0.getX(), pnt.getX() ), spu_mul( mCol1.getX(), pnt.getY() ) ), spu_mul( mCol2.getX(), pnt.getZ() ) ), mCol3.getX() ), + spu_add( spu_add( spu_add( spu_mul( mCol0.getY(), pnt.getX() ), spu_mul( mCol1.getY(), pnt.getY() ) ), spu_mul( mCol2.getY(), pnt.getZ() ) ), mCol3.getY() ), + spu_add( spu_add( spu_add( spu_mul( mCol0.getZ(), pnt.getX() ), spu_mul( mCol1.getZ(), pnt.getY() ) ), spu_mul( mCol2.getZ(), pnt.getZ() ) ), mCol3.getZ() ) + ); +} + +inline const Transform3 Transform3::operator *( const Transform3 & tfrm ) const +{ + return Transform3( + ( *this * tfrm.mCol0 ), + ( *this * tfrm.mCol1 ), + ( *this * tfrm.mCol2 ), + Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) + ); +} + +inline Transform3 & Transform3::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) +{ + return Transform3( + mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), + mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), + mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), + mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) + ); +} + +inline const Transform3 Transform3::identity( ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + Vector3( spu_splats(0.0f) ) + ); +} + +inline Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) +{ + mCol0 = tfrm.getCol0(); + mCol1 = tfrm.getCol1(); + mCol2 = tfrm.getCol2(); + return *this; +} + +inline const Matrix3 Transform3::getUpper3x3( ) const +{ + return Matrix3( mCol0, mCol1, mCol2 ); +} + +inline Transform3 & Transform3::setTranslation( const Vector3 & translateVec ) +{ + mCol3 = translateVec; + return *this; +} + +inline const Vector3 Transform3::getTranslation( ) const +{ + return mCol3; +} + +inline const Transform3 Transform3::rotationX( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Transform3( + Vector3::xAxis( ), + Vector3( spu_splats(0.0f), c, s ), + Vector3( spu_splats(0.0f), negatef4( s ), c ), + Vector3( spu_splats(0.0f) ) + ); +} + +inline const Transform3 Transform3::rotationY( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Transform3( + Vector3( c, spu_splats(0.0f), negatef4( s ) ), + Vector3::yAxis( ), + Vector3( s, spu_splats(0.0f), c ), + Vector3( spu_splats(0.0f) ) + ); +} + +inline const Transform3 Transform3::rotationZ( vec_float4 radians ) +{ + vec_float4 s, c; + sincosf4( radians, &s, &c ); + return Transform3( + Vector3( c, s, spu_splats(0.0f) ), + Vector3( negatef4( s ), c, spu_splats(0.0f) ), + Vector3::zAxis( ), + Vector3( spu_splats(0.0f) ) + ); +} + +inline const Transform3 Transform3::rotationZYX( const Vector3 & radiansXYZ ) +{ + vec_float4 sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sincosf4( radiansXYZ.getX(), &sX, &cX ); + sincosf4( radiansXYZ.getY(), &sY, &cY ); + sincosf4( radiansXYZ.getZ(), &sZ, &cZ ); + tmp0 = spu_mul( cZ, sY ); + tmp1 = spu_mul( sZ, sY ); + return Transform3( + Vector3( spu_mul( cZ, cY ), spu_mul( sZ, cY ), negatef4( sY ) ), + Vector3( spu_sub( spu_mul( tmp0, sX ), spu_mul( sZ, cX ) ), spu_add( spu_mul( tmp1, sX ), spu_mul( cZ, cX ) ), spu_mul( cY, sX ) ), + Vector3( spu_add( spu_mul( tmp0, cX ), spu_mul( sZ, sX ) ), spu_sub( spu_mul( tmp1, cX ), spu_mul( cZ, sX ) ), spu_mul( cY, cX ) ), + Vector3( spu_splats(0.0f) ) + ); +} + +inline const Transform3 Transform3::rotation( vec_float4 radians, const Vector3 & unitVec ) +{ + return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( spu_splats(0.0f) ) ); +} + +inline const Transform3 Transform3::rotation( const Quat & unitQuat ) +{ + return Transform3( Matrix3( unitQuat ), Vector3( spu_splats(0.0f) ) ); +} + +inline const Transform3 Transform3::scale( const Vector3 & scaleVec ) +{ + return Transform3( + Vector3( scaleVec.getX(), spu_splats(0.0f), spu_splats(0.0f) ), + Vector3( spu_splats(0.0f), scaleVec.getY(), spu_splats(0.0f) ), + Vector3( spu_splats(0.0f), spu_splats(0.0f), scaleVec.getZ() ), + Vector3( spu_splats(0.0f) ) + ); +} + +inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ) +{ + return Transform3( + ( tfrm.getCol0() * scaleVec.getX( ) ), + ( tfrm.getCol1() * scaleVec.getY( ) ), + ( tfrm.getCol2() * scaleVec.getZ( ) ), + tfrm.getCol3() + ); +} + +inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ) +{ + return Transform3( + mulPerElem( tfrm.getCol0(), scaleVec ), + mulPerElem( tfrm.getCol1(), scaleVec ), + mulPerElem( tfrm.getCol2(), scaleVec ), + mulPerElem( tfrm.getCol3(), scaleVec ) + ); +} + +inline const Transform3 Transform3::translation( const Vector3 & translateVec ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + translateVec + ); +} + +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, vec_uint4 select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Transform3 & tfrm ) +{ + Aos::Transform3 mat0, mat1, mat2, mat3; + tfrm.get4Aos( mat0, mat1, mat2, mat3 ); + printf("slot 0:\n"); + print( mat0 ); + printf("slot 1:\n"); + print( mat1 ); + printf("slot 2:\n"); + print( mat2 ); + printf("slot 3:\n"); + print( mat3 ); +} + +inline void print( const Transform3 & tfrm, const char * name ) +{ + printf("%s:\n", name); + print( tfrm ); +} + +#endif + +inline Quat::Quat( const Matrix3 & tfrm ) +{ + vec_float4 trace, radicand, scale, xx, yx, zx, xy, yy, zy, xz, yz, zz, tmpx, tmpy, tmpz, tmpw, qx, qy, qz, qw; + vec_uint4 negTrace, ZgtX, ZgtY, YgtX; + vec_uint4 largestXorY, largestYorZ, largestZorX; + + xx = tfrm.getCol0().getX(); + yx = tfrm.getCol0().getY(); + zx = tfrm.getCol0().getZ(); + xy = tfrm.getCol1().getX(); + yy = tfrm.getCol1().getY(); + zy = tfrm.getCol1().getZ(); + xz = tfrm.getCol2().getX(); + yz = tfrm.getCol2().getY(); + zz = tfrm.getCol2().getZ(); + + trace = spu_add( spu_add( xx, yy ), zz ); + + negTrace = spu_cmpgt( spu_splats(0.0f), trace ); + ZgtX = spu_cmpgt( zz, xx ); + ZgtY = spu_cmpgt( zz, yy ); + YgtX = spu_cmpgt( yy, xx ); + largestXorY = spu_and( negTrace, spu_nand( ZgtX, ZgtY ) ); + largestYorZ = spu_and( negTrace, spu_or( YgtX, ZgtX ) ); + largestZorX = spu_and( negTrace, spu_orc( ZgtY, YgtX ) ); + + zz = spu_sel( zz, negatef4(zz), largestXorY ); + xy = spu_sel( xy, negatef4(xy), largestXorY ); + xx = spu_sel( xx, negatef4(xx), largestYorZ ); + yz = spu_sel( yz, negatef4(yz), largestYorZ ); + yy = spu_sel( yy, negatef4(yy), largestZorX ); + zx = spu_sel( zx, negatef4(zx), largestZorX ); + + radicand = spu_add( spu_add( spu_add( xx, yy ), zz ), spu_splats(1.0f) ); + scale = spu_mul( spu_splats(0.5f), rsqrtf4( radicand ) ); + + tmpx = spu_mul( spu_sub( zy, yz ), scale ); + tmpy = spu_mul( spu_sub( xz, zx ), scale ); + tmpz = spu_mul( spu_sub( yx, xy ), scale ); + tmpw = spu_mul( radicand, scale ); + qx = tmpx; + qy = tmpy; + qz = tmpz; + qw = tmpw; + + qx = spu_sel( qx, tmpw, largestXorY ); + qy = spu_sel( qy, tmpz, largestXorY ); + qz = spu_sel( qz, tmpy, largestXorY ); + qw = spu_sel( qw, tmpx, largestXorY ); + tmpx = qx; + tmpz = qz; + qx = spu_sel( qx, qy, largestYorZ ); + qy = spu_sel( qy, tmpx, largestYorZ ); + qz = spu_sel( qz, qw, largestYorZ ); + qw = spu_sel( qw, tmpz, largestYorZ ); + + mX = qx; + mY = qy; + mZ = qz; + mW = qw; +} + +inline const Matrix3 outer( const Vector3 & tfrm0, const Vector3 & tfrm1 ) +{ + return Matrix3( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ) + ); +} + +inline const Matrix4 outer( const Vector4 & tfrm0, const Vector4 & tfrm1 ) +{ + return Matrix4( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ), + ( tfrm0 * tfrm1.getW( ) ) + ); +} + +inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ) +{ + return Vector3( + spu_add( spu_add( spu_mul( vec.getX(), mat.getCol0().getX() ), spu_mul( vec.getY(), mat.getCol0().getY() ) ), spu_mul( vec.getZ(), mat.getCol0().getZ() ) ), + spu_add( spu_add( spu_mul( vec.getX(), mat.getCol1().getX() ), spu_mul( vec.getY(), mat.getCol1().getY() ) ), spu_mul( vec.getZ(), mat.getCol1().getZ() ) ), + spu_add( spu_add( spu_mul( vec.getX(), mat.getCol2().getX() ), spu_mul( vec.getY(), mat.getCol2().getY() ) ), spu_mul( vec.getZ(), mat.getCol2().getZ() ) ) + ); +} + +inline const Matrix3 crossMatrix( const Vector3 & vec ) +{ + return Matrix3( + Vector3( spu_splats(0.0f), vec.getZ(), negatef4( vec.getY() ) ), + Vector3( negatef4( vec.getZ() ), spu_splats(0.0f), vec.getX() ), + Vector3( vec.getY(), negatef4( vec.getX() ), spu_splats(0.0f) ) + ); +} + +inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ) +{ + return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); +} + +} // namespace Soa +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/cpp/quat_aos.h b/Extras/vectormathlibrary/include/vectormath/spu/cpp/quat_aos.h new file mode 100644 index 0000000..a41bc69 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/cpp/quat_aos.h @@ -0,0 +1,417 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_AOS_CPP_H +#define _VECTORMATH_QUAT_AOS_CPP_H +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +inline Quat::Quat( float _x, float _y, float _z, float _w ) +{ + mVec128 = (vec_float4){ _x, _y, _z, _w }; +} + +inline Quat::Quat( Vector3 xyz, float _w ) +{ + mVec128 = spu_shuffle( xyz.get128(), spu_promote( _w, 0 ), _VECTORMATH_SHUF_XYZA ); +} + +inline Quat::Quat( Vector4 vec ) +{ + mVec128 = vec.get128(); +} + +inline Quat::Quat( float scalar ) +{ + mVec128 = spu_splats( scalar ); +} + +inline Quat::Quat( vec_float4 vf4 ) +{ + mVec128 = vf4; +} + +inline const Quat Quat::identity( ) +{ + return Quat( _VECTORMATH_UNIT_0001 ); +} + +inline const Quat lerp( float t, Quat quat0, Quat quat1 ) +{ + return ( quat0 + ( ( quat1 - quat0 ) * t ) ); +} + +inline const Quat slerp( float t, Quat unitQuat0, Quat unitQuat1 ) +{ + Quat start; + vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + vec_uint4 selectMask; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + cosAngle = _vmathVfDot4( unitQuat0.get128(), unitQuat1.get128() ); + cosAngle = spu_shuffle( cosAngle, cosAngle, shuffle_xxxx ); + selectMask = (vec_uint4)spu_cmpgt( spu_splats(0.0f), cosAngle ); + cosAngle = spu_sel( cosAngle, negatef4( cosAngle ), selectMask ); + start = Quat( spu_sel( unitQuat0.get128(), negatef4( unitQuat0.get128() ), selectMask ) ); + selectMask = (vec_uint4)spu_cmpgt( spu_splats(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = spu_splats(t); + oneMinusT = spu_sub( spu_splats(1.0f), tttt ); + angles = spu_sel( spu_splats(1.0f), oneMinusT, (vec_uint4)spu_maskb(0x0f00) ); + angles = spu_sel( angles, tttt, (vec_uint4)spu_maskb(0x00f0) ); + angles = spu_mul( angles, angle ); + sines = sinf4( angles ); + scales = divf4( sines, spu_shuffle( sines, sines, shuffle_xxxx ) ); + scale0 = spu_sel( oneMinusT, spu_shuffle( scales, scales, shuffle_yyyy ), selectMask ); + scale1 = spu_sel( tttt, spu_shuffle( scales, scales, shuffle_zzzz ), selectMask ); + return Quat( spu_madd( start.get128(), scale0, spu_mul( unitQuat1.get128(), scale1 ) ) ); +} + +inline const Quat squad( float t, Quat unitQuat0, Quat unitQuat1, Quat unitQuat2, Quat unitQuat3 ) +{ + Quat tmp0, tmp1; + tmp0 = slerp( t, unitQuat0, unitQuat3 ); + tmp1 = slerp( t, unitQuat1, unitQuat2 ); + return slerp( ( ( 2.0f * t ) * ( 1.0f - t ) ), tmp0, tmp1 ); +} + +inline vec_float4 Quat::get128( ) const +{ + return mVec128; +} + +inline Quat & Quat::operator =( Quat quat ) +{ + mVec128 = quat.mVec128; + return *this; +} + +inline Quat & Quat::setXYZ( Vector3 vec ) +{ + mVec128 = spu_sel( vec.get128(), mVec128, (vec_uint4)spu_maskb(0x000f) ); + return *this; +} + +inline const Vector3 Quat::getXYZ( ) const +{ + return Vector3( mVec128 ); +} + +inline Quat & Quat::setX( float _x ) +{ + mVec128 = spu_insert( _x, mVec128, 0 ); + return *this; +} + +inline float Quat::getX( ) const +{ + return spu_extract( mVec128, 0 ); +} + +inline Quat & Quat::setY( float _y ) +{ + mVec128 = spu_insert( _y, mVec128, 1 ); + return *this; +} + +inline float Quat::getY( ) const +{ + return spu_extract( mVec128, 1 ); +} + +inline Quat & Quat::setZ( float _z ) +{ + mVec128 = spu_insert( _z, mVec128, 2 ); + return *this; +} + +inline float Quat::getZ( ) const +{ + return spu_extract( mVec128, 2 ); +} + +inline Quat & Quat::setW( float _w ) +{ + mVec128 = spu_insert( _w, mVec128, 3 ); + return *this; +} + +inline float Quat::getW( ) const +{ + return spu_extract( mVec128, 3 ); +} + +inline Quat & Quat::setElem( int idx, float value ) +{ + mVec128 = spu_insert( value, mVec128, idx ); + return *this; +} + +inline float Quat::getElem( int idx ) const +{ + return spu_extract( mVec128, idx ); +} + +inline VecIdx Quat::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +inline float Quat::operator []( int idx ) const +{ + return spu_extract( mVec128, idx ); +} + +inline const Quat Quat::operator +( Quat quat ) const +{ + return Quat( spu_add( mVec128, quat.mVec128 ) ); +} + +inline const Quat Quat::operator -( Quat quat ) const +{ + return Quat( spu_sub( mVec128, quat.mVec128 ) ); +} + +inline const Quat Quat::operator *( float scalar ) const +{ + return Quat( spu_mul( mVec128, spu_splats(scalar) ) ); +} + +inline Quat & Quat::operator +=( Quat quat ) +{ + *this = *this + quat; + return *this; +} + +inline Quat & Quat::operator -=( Quat quat ) +{ + *this = *this - quat; + return *this; +} + +inline Quat & Quat::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Quat Quat::operator /( float scalar ) const +{ + return Quat( divf4( mVec128, spu_splats(scalar) ) ); +} + +inline Quat & Quat::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Quat Quat::operator -( ) const +{ + return Quat( negatef4( mVec128 ) ); +} + +inline const Quat operator *( float scalar, Quat quat ) +{ + return quat * scalar; +} + +inline float dot( Quat quat0, Quat quat1 ) +{ + return spu_extract( _vmathVfDot4( quat0.get128(), quat1.get128() ), 0 ); +} + +inline float norm( Quat quat ) +{ + return spu_extract( _vmathVfDot4( quat.get128(), quat.get128() ), 0 ); +} + +inline float length( Quat quat ) +{ + return sqrtf( norm( quat ) ); +} + +inline const Quat normalize( Quat quat ) +{ + vec_float4 dot = _vmathVfDot4( quat.get128(), quat.get128() ); + return Quat( spu_mul( quat.get128(), rsqrtf4( dot ) ) ); +} + +inline const Quat Quat::rotation( Vector3 unitVec0, Vector3 unitVec1 ) +{ + Vector3 crossVec; + vec_float4 cosAngle, cosAngleX2Plus2, recipCosHalfAngleX2, cosHalfAngleX2, res; + cosAngle = _vmathVfDot3( unitVec0.get128(), unitVec1.get128() ); + cosAngle = spu_shuffle( cosAngle, cosAngle, (vec_uchar16)spu_splats(0x00010203) ); + cosAngleX2Plus2 = spu_madd( cosAngle, spu_splats(2.0f), spu_splats(2.0f) ); + recipCosHalfAngleX2 = rsqrtf4( cosAngleX2Plus2 ); + cosHalfAngleX2 = spu_mul( recipCosHalfAngleX2, cosAngleX2Plus2 ); + crossVec = cross( unitVec0, unitVec1 ); + res = spu_mul( crossVec.get128(), recipCosHalfAngleX2 ); + res = spu_sel( res, spu_mul( cosHalfAngleX2, spu_splats(0.5f) ), (vec_uint4)spu_maskb(0x000f) ); + return Quat( res ); +} + +inline const Quat Quat::rotation( float radians, Vector3 unitVec ) +{ + vec_float4 s, c, angle, res; + angle = spu_mul( spu_splats(radians), spu_splats(0.5f) ); + sincosf4( angle, &s, &c ); + res = spu_sel( spu_mul( unitVec.get128(), s ), c, (vec_uint4)spu_maskb(0x000f) ); + return Quat( res ); +} + +inline const Quat Quat::rotationX( float radians ) +{ + vec_float4 s, c, angle, res; + angle = spu_mul( spu_splats(radians), spu_splats(0.5f) ); + sincosf4( angle, &s, &c ); + res = spu_sel( spu_splats(0.0f), s, (vec_uint4)spu_maskb(0xf000) ); + res = spu_sel( res, c, (vec_uint4)spu_maskb(0x000f) ); + return Quat( res ); +} + +inline const Quat Quat::rotationY( float radians ) +{ + vec_float4 s, c, angle, res; + angle = spu_mul( spu_splats(radians), spu_splats(0.5f) ); + sincosf4( angle, &s, &c ); + res = spu_sel( spu_splats(0.0f), s, (vec_uint4)spu_maskb(0x0f00) ); + res = spu_sel( res, c, (vec_uint4)spu_maskb(0x000f) ); + return Quat( res ); +} + +inline const Quat Quat::rotationZ( float radians ) +{ + vec_float4 s, c, angle, res; + angle = spu_mul( spu_splats(radians), spu_splats(0.5f) ); + sincosf4( angle, &s, &c ); + res = spu_sel( spu_splats(0.0f), s, (vec_uint4)spu_maskb(0x00f0) ); + res = spu_sel( res, c, (vec_uint4)spu_maskb(0x000f) ); + return Quat( res ); +} + +inline const Quat Quat::operator *( Quat quat ) const +{ + vec_float4 ldata, rdata, qv, tmp0, tmp1, tmp2, tmp3; + vec_float4 product, l_wxyz, r_wxyz, xy, qw; + ldata = mVec128; + rdata = quat.mVec128; + vec_uchar16 shuffle_wwww = (vec_uchar16)spu_splats((int)0x0c0d0e0f); + tmp0 = spu_shuffle( ldata, ldata, _VECTORMATH_SHUF_YZXW ); + tmp1 = spu_shuffle( rdata, rdata, _VECTORMATH_SHUF_ZXYW ); + tmp2 = spu_shuffle( ldata, ldata, _VECTORMATH_SHUF_ZXYW ); + tmp3 = spu_shuffle( rdata, rdata, _VECTORMATH_SHUF_YZXW ); + qv = spu_mul( spu_shuffle( ldata, ldata, shuffle_wwww ), rdata ); + qv = spu_madd( spu_shuffle( rdata, rdata, shuffle_wwww ), ldata, qv ); + qv = spu_madd( tmp0, tmp1, qv ); + qv = spu_nmsub( tmp2, tmp3, qv ); + product = spu_mul( ldata, rdata ); + l_wxyz = spu_rlqwbyte( ldata, 12 ); + r_wxyz = spu_rlqwbyte( rdata, 12 ); + qw = spu_nmsub( l_wxyz, r_wxyz, product ); + xy = spu_madd( l_wxyz, r_wxyz, product ); + qw = spu_sub( qw, spu_rlqwbyte( xy, 8 ) ); + return Quat( spu_sel( qv, qw, (vec_uint4)spu_maskb( 0x000f ) ) ); +} + +inline Quat & Quat::operator *=( Quat quat ) +{ + *this = *this * quat; + return *this; +} + +inline const Vector3 rotate( Quat quat, Vector3 vec ) +{ + vec_float4 qdata, vdata, product, tmp0, tmp1, tmp2, tmp3, wwww, qv, qw, res; + qdata = quat.get128(); + vdata = vec.get128(); + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_wwww = (vec_uchar16)spu_splats((int)0x0c0d0e0f); + tmp0 = spu_shuffle( qdata, qdata, _VECTORMATH_SHUF_YZXW ); + tmp1 = spu_shuffle( vdata, vdata, _VECTORMATH_SHUF_ZXYW ); + tmp2 = spu_shuffle( qdata, qdata, _VECTORMATH_SHUF_ZXYW ); + tmp3 = spu_shuffle( vdata, vdata, _VECTORMATH_SHUF_YZXW ); + wwww = spu_shuffle( qdata, qdata, shuffle_wwww ); + qv = spu_mul( wwww, vdata ); + qv = spu_madd( tmp0, tmp1, qv ); + qv = spu_nmsub( tmp2, tmp3, qv ); + product = spu_mul( qdata, vdata ); + qw = spu_madd( spu_rlqwbyte( qdata, 4 ), spu_rlqwbyte( vdata, 4 ), product ); + qw = spu_add( spu_rlqwbyte( product, 8 ), qw ); + tmp1 = spu_shuffle( qv, qv, _VECTORMATH_SHUF_ZXYW ); + tmp3 = spu_shuffle( qv, qv, _VECTORMATH_SHUF_YZXW ); + res = spu_mul( spu_shuffle( qw, qw, shuffle_xxxx ), qdata ); + res = spu_madd( wwww, qv, res ); + res = spu_madd( tmp0, tmp1, res ); + res = spu_nmsub( tmp2, tmp3, res ); + return Vector3( res ); +} + +inline const Quat conj( Quat quat ) +{ + return Quat( spu_xor( quat.get128(), ((vec_float4)(vec_int4){0x80000000,0x80000000,0x80000000,0}) ) ); +} + +inline const Quat select( Quat quat0, Quat quat1, bool select1 ) +{ + return Quat( spu_sel( quat0.get128(), quat1.get128(), spu_splats( (unsigned int)-(select1 > 0) ) ) ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( Quat quat ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = quat.get128(); + printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +inline void print( Quat quat, const char * name ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = quat.get128(); + printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/cpp/quat_soa.h b/Extras/vectormathlibrary/include/vectormath/spu/cpp/quat_soa.h new file mode 100644 index 0000000..88c2884 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/cpp/quat_soa.h @@ -0,0 +1,483 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_QUAT_SOA_CPP_H +#define _VECTORMATH_QUAT_SOA_CPP_H +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Soa { + +inline Quat::Quat( const Quat & quat ) +{ + mX = quat.mX; + mY = quat.mY; + mZ = quat.mZ; + mW = quat.mW; +} + +inline Quat::Quat( vec_float4 _x, vec_float4 _y, vec_float4 _z, vec_float4 _w ) +{ + mX = _x; + mY = _y; + mZ = _z; + mW = _w; +} + +inline Quat::Quat( const Vector3 & xyz, vec_float4 _w ) +{ + this->setXYZ( xyz ); + this->setW( _w ); +} + +inline Quat::Quat( const Vector4 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + mW = vec.getW(); +} + +inline Quat::Quat( vec_float4 scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; + mW = scalar; +} + +inline Quat::Quat( Aos::Quat quat ) +{ + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + vec_uchar16 shuffle_wwww = (vec_uchar16)spu_splats((int)0x0c0d0e0f); + vec_float4 vec128 = quat.get128(); + mX = spu_shuffle( vec128, vec128, shuffle_xxxx ); + mY = spu_shuffle( vec128, vec128, shuffle_yyyy ); + mZ = spu_shuffle( vec128, vec128, shuffle_zzzz ); + mW = spu_shuffle( vec128, vec128, shuffle_wwww ); +} + +inline Quat::Quat( Aos::Quat quat0, Aos::Quat quat1, Aos::Quat quat2, Aos::Quat quat3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = spu_shuffle( quat0.get128(), quat2.get128(), _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( quat1.get128(), quat3.get128(), _VECTORMATH_SHUF_XAYB ); + tmp2 = spu_shuffle( quat0.get128(), quat2.get128(), _VECTORMATH_SHUF_ZCWD ); + tmp3 = spu_shuffle( quat1.get128(), quat3.get128(), _VECTORMATH_SHUF_ZCWD ); + mX = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_XAYB ); + mY = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_ZCWD ); + mZ = spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_XAYB ); + mW = spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_ZCWD ); +} + +inline const Quat Quat::identity( ) +{ + return Quat( spu_splats(0.0f), spu_splats(0.0f), spu_splats(0.0f), spu_splats(1.0f) ); +} + +inline const Quat lerp( vec_float4 t, const Quat & quat0, const Quat & quat1 ) +{ + return ( quat0 + ( ( quat1 - quat0 ) * t ) ); +} + +inline const Quat slerp( vec_float4 t, const Quat & unitQuat0, const Quat & unitQuat1 ) +{ + Quat start; + vec_float4 recipSinAngle, scale0, scale1, cosAngle, angle; + vec_uint4 selectMask; + cosAngle = dot( unitQuat0, unitQuat1 ); + selectMask = (vec_uint4)spu_cmpgt( spu_splats(0.0f), cosAngle ); + cosAngle = spu_sel( cosAngle, negatef4( cosAngle ), selectMask ); + start.setX( spu_sel( unitQuat0.getX(), negatef4( unitQuat0.getX() ), selectMask ) ); + start.setY( spu_sel( unitQuat0.getY(), negatef4( unitQuat0.getY() ), selectMask ) ); + start.setZ( spu_sel( unitQuat0.getZ(), negatef4( unitQuat0.getZ() ), selectMask ) ); + start.setW( spu_sel( unitQuat0.getW(), negatef4( unitQuat0.getW() ), selectMask ) ); + selectMask = (vec_uint4)spu_cmpgt( spu_splats(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + recipSinAngle = recipf4( sinf4( angle ) ); + scale0 = spu_sel( spu_sub( spu_splats(1.0f), t ), spu_mul( sinf4( spu_mul( spu_sub( spu_splats(1.0f), t ), angle ) ), recipSinAngle ), selectMask ); + scale1 = spu_sel( t, spu_mul( sinf4( spu_mul( t, angle ) ), recipSinAngle ), selectMask ); + return ( ( start * scale0 ) + ( unitQuat1 * scale1 ) ); +} + +inline const Quat squad( vec_float4 t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ) +{ + Quat tmp0, tmp1; + tmp0 = slerp( t, unitQuat0, unitQuat3 ); + tmp1 = slerp( t, unitQuat1, unitQuat2 ); + return slerp( spu_mul( spu_mul( spu_splats(2.0f), t ), spu_sub( spu_splats(1.0f), t ) ), tmp0, tmp1 ); +} + +inline void Quat::get4Aos( Aos::Quat & result0, Aos::Quat & result1, Aos::Quat & result2, Aos::Quat & result3 ) const +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = spu_shuffle( mX, mZ, _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( mY, mW, _VECTORMATH_SHUF_XAYB ); + tmp2 = spu_shuffle( mX, mZ, _VECTORMATH_SHUF_ZCWD ); + tmp3 = spu_shuffle( mY, mW, _VECTORMATH_SHUF_ZCWD ); + result0 = Aos::Quat( spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_XAYB ) ); + result1 = Aos::Quat( spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_ZCWD ) ); + result2 = Aos::Quat( spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_XAYB ) ); + result3 = Aos::Quat( spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_ZCWD ) ); +} + +inline Quat & Quat::operator =( const Quat & quat ) +{ + mX = quat.mX; + mY = quat.mY; + mZ = quat.mZ; + mW = quat.mW; + return *this; +} + +inline Quat & Quat::setXYZ( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + return *this; +} + +inline const Vector3 Quat::getXYZ( ) const +{ + return Vector3( mX, mY, mZ ); +} + +inline Quat & Quat::setX( vec_float4 _x ) +{ + mX = _x; + return *this; +} + +inline vec_float4 Quat::getX( ) const +{ + return mX; +} + +inline Quat & Quat::setY( vec_float4 _y ) +{ + mY = _y; + return *this; +} + +inline vec_float4 Quat::getY( ) const +{ + return mY; +} + +inline Quat & Quat::setZ( vec_float4 _z ) +{ + mZ = _z; + return *this; +} + +inline vec_float4 Quat::getZ( ) const +{ + return mZ; +} + +inline Quat & Quat::setW( vec_float4 _w ) +{ + mW = _w; + return *this; +} + +inline vec_float4 Quat::getW( ) const +{ + return mW; +} + +inline Quat & Quat::setElem( int idx, vec_float4 value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline vec_float4 Quat::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline Quat::vec_float4_t & Quat::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline vec_float4 Quat::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Quat Quat::operator +( const Quat & quat ) const +{ + return Quat( + spu_add( mX, quat.mX ), + spu_add( mY, quat.mY ), + spu_add( mZ, quat.mZ ), + spu_add( mW, quat.mW ) + ); +} + +inline const Quat Quat::operator -( const Quat & quat ) const +{ + return Quat( + spu_sub( mX, quat.mX ), + spu_sub( mY, quat.mY ), + spu_sub( mZ, quat.mZ ), + spu_sub( mW, quat.mW ) + ); +} + +inline const Quat Quat::operator *( vec_float4 scalar ) const +{ + return Quat( + spu_mul( mX, scalar ), + spu_mul( mY, scalar ), + spu_mul( mZ, scalar ), + spu_mul( mW, scalar ) + ); +} + +inline Quat & Quat::operator +=( const Quat & quat ) +{ + *this = *this + quat; + return *this; +} + +inline Quat & Quat::operator -=( const Quat & quat ) +{ + *this = *this - quat; + return *this; +} + +inline Quat & Quat::operator *=( vec_float4 scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Quat Quat::operator /( vec_float4 scalar ) const +{ + return Quat( + divf4( mX, scalar ), + divf4( mY, scalar ), + divf4( mZ, scalar ), + divf4( mW, scalar ) + ); +} + +inline Quat & Quat::operator /=( vec_float4 scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Quat Quat::operator -( ) const +{ + return Quat( + negatef4( mX ), + negatef4( mY ), + negatef4( mZ ), + negatef4( mW ) + ); +} + +inline const Quat operator *( vec_float4 scalar, const Quat & quat ) +{ + return quat * scalar; +} + +inline vec_float4 dot( const Quat & quat0, const Quat & quat1 ) +{ + vec_float4 result; + result = spu_mul( quat0.getX(), quat1.getX() ); + result = spu_add( result, spu_mul( quat0.getY(), quat1.getY() ) ); + result = spu_add( result, spu_mul( quat0.getZ(), quat1.getZ() ) ); + result = spu_add( result, spu_mul( quat0.getW(), quat1.getW() ) ); + return result; +} + +inline vec_float4 norm( const Quat & quat ) +{ + vec_float4 result; + result = spu_mul( quat.getX(), quat.getX() ); + result = spu_add( result, spu_mul( quat.getY(), quat.getY() ) ); + result = spu_add( result, spu_mul( quat.getZ(), quat.getZ() ) ); + result = spu_add( result, spu_mul( quat.getW(), quat.getW() ) ); + return result; +} + +inline vec_float4 length( const Quat & quat ) +{ + return sqrtf4( norm( quat ) ); +} + +inline const Quat normalize( const Quat & quat ) +{ + vec_float4 lenSqr, lenInv; + lenSqr = norm( quat ); + lenInv = rsqrtf4( lenSqr ); + return Quat( + spu_mul( quat.getX(), lenInv ), + spu_mul( quat.getY(), lenInv ), + spu_mul( quat.getZ(), lenInv ), + spu_mul( quat.getW(), lenInv ) + ); +} + +inline const Quat Quat::rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ) +{ + vec_float4 cosHalfAngleX2, recipCosHalfAngleX2; + cosHalfAngleX2 = sqrtf4( spu_mul( spu_splats(2.0f), spu_add( spu_splats(1.0f), dot( unitVec0, unitVec1 ) ) ) ); + recipCosHalfAngleX2 = recipf4( cosHalfAngleX2 ); + return Quat( ( cross( unitVec0, unitVec1 ) * recipCosHalfAngleX2 ), spu_mul( cosHalfAngleX2, spu_splats(0.5f) ) ); +} + +inline const Quat Quat::rotation( vec_float4 radians, const Vector3 & unitVec ) +{ + vec_float4 s, c, angle; + angle = spu_mul( radians, spu_splats(0.5f) ); + sincosf4( angle, &s, &c ); + return Quat( ( unitVec * s ), c ); +} + +inline const Quat Quat::rotationX( vec_float4 radians ) +{ + vec_float4 s, c, angle; + angle = spu_mul( radians, spu_splats(0.5f) ); + sincosf4( angle, &s, &c ); + return Quat( s, spu_splats(0.0f), spu_splats(0.0f), c ); +} + +inline const Quat Quat::rotationY( vec_float4 radians ) +{ + vec_float4 s, c, angle; + angle = spu_mul( radians, spu_splats(0.5f) ); + sincosf4( angle, &s, &c ); + return Quat( spu_splats(0.0f), s, spu_splats(0.0f), c ); +} + +inline const Quat Quat::rotationZ( vec_float4 radians ) +{ + vec_float4 s, c, angle; + angle = spu_mul( radians, spu_splats(0.5f) ); + sincosf4( angle, &s, &c ); + return Quat( spu_splats(0.0f), spu_splats(0.0f), s, c ); +} + +inline const Quat Quat::operator *( const Quat & quat ) const +{ + return Quat( + spu_sub( spu_add( spu_add( spu_mul( mW, quat.mX ), spu_mul( mX, quat.mW ) ), spu_mul( mY, quat.mZ ) ), spu_mul( mZ, quat.mY ) ), + spu_sub( spu_add( spu_add( spu_mul( mW, quat.mY ), spu_mul( mY, quat.mW ) ), spu_mul( mZ, quat.mX ) ), spu_mul( mX, quat.mZ ) ), + spu_sub( spu_add( spu_add( spu_mul( mW, quat.mZ ), spu_mul( mZ, quat.mW ) ), spu_mul( mX, quat.mY ) ), spu_mul( mY, quat.mX ) ), + spu_sub( spu_sub( spu_sub( spu_mul( mW, quat.mW ), spu_mul( mX, quat.mX ) ), spu_mul( mY, quat.mY ) ), spu_mul( mZ, quat.mZ ) ) + ); +} + +inline Quat & Quat::operator *=( const Quat & quat ) +{ + *this = *this * quat; + return *this; +} + +inline const Vector3 rotate( const Quat & quat, const Vector3 & vec ) +{ + vec_float4 tmpX, tmpY, tmpZ, tmpW; + tmpX = spu_sub( spu_add( spu_mul( quat.getW(), vec.getX() ), spu_mul( quat.getY(), vec.getZ() ) ), spu_mul( quat.getZ(), vec.getY() ) ); + tmpY = spu_sub( spu_add( spu_mul( quat.getW(), vec.getY() ), spu_mul( quat.getZ(), vec.getX() ) ), spu_mul( quat.getX(), vec.getZ() ) ); + tmpZ = spu_sub( spu_add( spu_mul( quat.getW(), vec.getZ() ), spu_mul( quat.getX(), vec.getY() ) ), spu_mul( quat.getY(), vec.getX() ) ); + tmpW = spu_add( spu_add( spu_mul( quat.getX(), vec.getX() ), spu_mul( quat.getY(), vec.getY() ) ), spu_mul( quat.getZ(), vec.getZ() ) ); + return Vector3( + spu_add( spu_sub( spu_add( spu_mul( tmpW, quat.getX() ), spu_mul( tmpX, quat.getW() ) ), spu_mul( tmpY, quat.getZ() ) ), spu_mul( tmpZ, quat.getY() ) ), + spu_add( spu_sub( spu_add( spu_mul( tmpW, quat.getY() ), spu_mul( tmpY, quat.getW() ) ), spu_mul( tmpZ, quat.getX() ) ), spu_mul( tmpX, quat.getZ() ) ), + spu_add( spu_sub( spu_add( spu_mul( tmpW, quat.getZ() ), spu_mul( tmpZ, quat.getW() ) ), spu_mul( tmpX, quat.getY() ) ), spu_mul( tmpY, quat.getX() ) ) + ); +} + +inline const Quat conj( const Quat & quat ) +{ + return Quat( negatef4( quat.getX() ), negatef4( quat.getY() ), negatef4( quat.getZ() ), quat.getW() ); +} + +inline const Quat select( const Quat & quat0, const Quat & quat1, vec_uint4 select1 ) +{ + return Quat( + spu_sel( quat0.getX(), quat1.getX(), select1 ), + spu_sel( quat0.getY(), quat1.getY(), select1 ), + spu_sel( quat0.getZ(), quat1.getZ(), select1 ), + spu_sel( quat0.getW(), quat1.getW(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Quat & quat ) +{ + Aos::Quat vec0, vec1, vec2, vec3; + quat.get4Aos( vec0, vec1, vec2, vec3 ); + printf("slot 0:\n"); + print( vec0 ); + printf("slot 1:\n"); + print( vec1 ); + printf("slot 2:\n"); + print( vec2 ); + printf("slot 3:\n"); + print( vec3 ); +} + +inline void print( const Quat & quat, const char * name ) +{ + Aos::Quat vec0, vec1, vec2, vec3; + printf( "%s:\n", name ); + quat.get4Aos( vec0, vec1, vec2, vec3 ); + printf("slot 0:\n"); + print( vec0 ); + printf("slot 1:\n"); + print( vec1 ); + printf("slot 2:\n"); + print( vec2 ); + printf("slot 3:\n"); + print( vec3 ); +} + +#endif + +} // namespace Soa +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/cpp/vec_aos.h b/Extras/vectormathlibrary/include/vectormath/spu/cpp/vec_aos.h new file mode 100644 index 0000000..c983f18 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/cpp/vec_aos.h @@ -0,0 +1,1167 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_AOS_CPP_H +#define _VECTORMATH_VEC_AOS_CPP_H +//----------------------------------------------------------------------------- +// Constants +// for shuffles, words are labeled [x,y,z,w] [a,b,c,d] + +#define _VECTORMATH_SHUF_X 0x00010203 +#define _VECTORMATH_SHUF_Y 0x04050607 +#define _VECTORMATH_SHUF_Z 0x08090a0b +#define _VECTORMATH_SHUF_W 0x0c0d0e0f +#define _VECTORMATH_SHUF_A 0x10111213 +#define _VECTORMATH_SHUF_B 0x14151617 +#define _VECTORMATH_SHUF_C 0x18191a1b +#define _VECTORMATH_SHUF_D 0x1c1d1e1f +#define _VECTORMATH_SHUF_0 0x80808080 +#define _VECTORMATH_SHUF_XYZA (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_A } +#define _VECTORMATH_SHUF_ZXYW (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_W } +#define _VECTORMATH_SHUF_YZXW (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_W } +#define _VECTORMATH_SHUF_WABC (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_C } +#define _VECTORMATH_SHUF_ZWAB (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_B } +#define _VECTORMATH_SHUF_XYZA (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_A } +#define _VECTORMATH_SHUF_YZAB (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_B } +#define _VECTORMATH_SHUF_ZABC (vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_C } +#define _VECTORMATH_UNIT_1000 (vec_float4){ 1.0f, 0.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0100 (vec_float4){ 0.0f, 1.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0010 (vec_float4){ 0.0f, 0.0f, 1.0f, 0.0f } +#define _VECTORMATH_UNIT_0001 (vec_float4){ 0.0f, 0.0f, 0.0f, 1.0f } +#define _VECTORMATH_SLERP_TOL 0.999f + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +static inline vec_float4 _vmathVfDot3( vec_float4 vec0, vec_float4 vec1 ) +{ + vec_float4 result; + result = spu_mul( vec0, vec1 ); + result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result ); + return spu_madd( spu_rlqwbyte( vec0, 8 ), spu_rlqwbyte( vec1, 8 ), result ); +} + +static inline vec_float4 _vmathVfDot4( vec_float4 vec0, vec_float4 vec1 ) +{ + vec_float4 result; + result = spu_mul( vec0, vec1 ); + result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result ); + return spu_add( spu_rlqwbyte( result, 8 ), result ); +} + +static inline vec_float4 _vmathVfCross( vec_float4 vec0, vec_float4 vec1 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3, result; + tmp0 = spu_shuffle( vec0, vec0, _VECTORMATH_SHUF_YZXW ); + tmp1 = spu_shuffle( vec1, vec1, _VECTORMATH_SHUF_ZXYW ); + tmp2 = spu_shuffle( vec0, vec0, _VECTORMATH_SHUF_ZXYW ); + tmp3 = spu_shuffle( vec1, vec1, _VECTORMATH_SHUF_YZXW ); + result = spu_mul( tmp0, tmp1 ); + result = spu_nmsub( tmp2, tmp3, result ); + return result; +} + +static inline vec_uint4 _vmathVfToHalfFloatsUnpacked(vec_float4 v) +{ + vec_int4 bexp; + vec_uint4 mant, sign, hfloat; + vec_uint4 notZero, isInf; + const vec_uint4 hfloatInf = spu_splats(0x00007c00u); + const vec_uint4 mergeMant = spu_splats(0x000003ffu); + const vec_uint4 mergeSign = spu_splats(0x00008000u); + + sign = spu_rlmask((vec_uint4)v, -16); + mant = spu_rlmask((vec_uint4)v, -13); + bexp = spu_and(spu_rlmask((vec_int4)v, -23), 0xff); + + notZero = spu_cmpgt(bexp, 112); + isInf = spu_cmpgt(bexp, 142); + + bexp = spu_add(bexp, -112); + bexp = spu_sl(bexp, 10); + + hfloat = spu_sel((vec_uint4)bexp, mant, mergeMant); + hfloat = spu_sel(spu_splats(0u), hfloat, notZero); + hfloat = spu_sel(hfloat, hfloatInf, isInf); + hfloat = spu_sel(hfloat, sign, mergeSign); + + return hfloat; +} + +static inline vec_ushort8 _vmath2VfToHalfFloats(vec_float4 u, vec_float4 v) +{ + vec_uint4 hfloat_u, hfloat_v; + const vec_uchar16 pack = (vec_uchar16){2,3,6,7,10,11,14,15,18,19,22,23,26,27,30,31}; + hfloat_u = _vmathVfToHalfFloatsUnpacked(u); + hfloat_v = _vmathVfToHalfFloatsUnpacked(v); + return (vec_ushort8)spu_shuffle(hfloat_u, hfloat_v, pack); +} + +#endif + +namespace Vectormath { +namespace Aos { + +inline VecIdx::operator float() const +{ + return spu_extract( ref, i ); +} + +inline float VecIdx::operator =( float scalar ) +{ + ref = spu_insert( scalar, ref, i ); + return scalar; +} + +inline float VecIdx::operator =( const VecIdx& scalar ) +{ + return *this = float(scalar); +} + +inline float VecIdx::operator *=( float scalar ) +{ + float tmp = spu_extract( ref, i ) * scalar; + ref = spu_insert( tmp, ref, i ); + return tmp; +} + +inline float VecIdx::operator /=( float scalar ) +{ + float tmp = spu_extract( ref, i ) / scalar; + ref = spu_insert( tmp, ref, i ); + return tmp; +} + +inline float VecIdx::operator +=( float scalar ) +{ + float tmp = spu_extract( ref, i ) + scalar; + ref = spu_insert( tmp, ref, i ); + return tmp; +} + +inline float VecIdx::operator -=( float scalar ) +{ + float tmp = spu_extract( ref, i ) - scalar; + ref = spu_insert( tmp, ref, i ); + return tmp; +} + +inline Vector3::Vector3( float _x, float _y, float _z ) +{ + mVec128 = (vec_float4){ _x, _y, _z, 0.0f }; +} + +inline Vector3::Vector3( Point3 pnt ) +{ + mVec128 = pnt.get128(); +} + +inline Vector3::Vector3( float scalar ) +{ + mVec128 = spu_splats( scalar ); +} + +inline Vector3::Vector3( vec_float4 vf4 ) +{ + mVec128 = vf4; +} + +inline const Vector3 Vector3::xAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_1000 ); +} + +inline const Vector3 Vector3::yAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_0100 ); +} + +inline const Vector3 Vector3::zAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_0010 ); +} + +inline const Vector3 lerp( float t, Vector3 vec0, Vector3 vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector3 slerp( float t, Vector3 unitVec0, Vector3 unitVec1 ) +{ + vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + vec_uint4 selectMask; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + cosAngle = _vmathVfDot3( unitVec0.get128(), unitVec1.get128() ); + cosAngle = spu_shuffle( cosAngle, cosAngle, shuffle_xxxx ); + selectMask = (vec_uint4)spu_cmpgt( spu_splats(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = spu_splats(t); + oneMinusT = spu_sub( spu_splats(1.0f), tttt ); + angles = spu_sel( spu_splats(1.0f), oneMinusT, (vec_uint4)spu_maskb(0x0f00) ); + angles = spu_sel( angles, tttt, (vec_uint4)spu_maskb(0x00f0) ); + angles = spu_mul( angles, angle ); + sines = sinf4( angles ); + scales = divf4( sines, spu_shuffle( sines, sines, shuffle_xxxx ) ); + scale0 = spu_sel( oneMinusT, spu_shuffle( scales, scales, shuffle_yyyy ), selectMask ); + scale1 = spu_sel( tttt, spu_shuffle( scales, scales, shuffle_zzzz ), selectMask ); + return Vector3( spu_madd( unitVec0.get128(), scale0, spu_mul( unitVec1.get128(), scale1 ) ) ); +} + +inline vec_float4 Vector3::get128( ) const +{ + return mVec128; +} + +inline void storeXYZ( Vector3 vec, vec_float4 * quad ) +{ + vec_float4 dstVec = *quad; + vec_uint4 mask = (vec_uint4)spu_maskb(0x000f); + dstVec = spu_sel(vec.get128(), dstVec, mask); + *quad = dstVec; +} + +inline void loadXYZArray( Vector3 & vec0, Vector3 & vec1, Vector3 & vec2, Vector3 & vec3, const vec_float4 * threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz, xyz1, xyz2, xyz3; + xyzx = threeQuads[0]; + yzxy = threeQuads[1]; + zxyz = threeQuads[2]; + xyz1 = spu_shuffle( xyzx, yzxy, _VECTORMATH_SHUF_WABC ); + xyz2 = spu_shuffle( yzxy, zxyz, _VECTORMATH_SHUF_ZWAB ); + xyz3 = spu_rlqwbyte( zxyz, 4 ); + vec0 = Vector3( xyzx ); + vec1 = Vector3( xyz1 ); + vec2 = Vector3( xyz2 ); + vec3 = Vector3( xyz3 ); +} + +inline void storeXYZArray( Vector3 vec0, Vector3 vec1, Vector3 vec2, Vector3 vec3, vec_float4 * threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz; + xyzx = spu_shuffle( vec0.get128(), vec1.get128(), _VECTORMATH_SHUF_XYZA ); + yzxy = spu_shuffle( vec1.get128(), vec2.get128(), _VECTORMATH_SHUF_YZAB ); + zxyz = spu_shuffle( vec2.get128(), vec3.get128(), _VECTORMATH_SHUF_ZABC ); + threeQuads[0] = xyzx; + threeQuads[1] = yzxy; + threeQuads[2] = zxyz; +} + +inline void storeHalfFloats( Vector3 vec0, Vector3 vec1, Vector3 vec2, Vector3 vec3, Vector3 vec4, Vector3 vec5, Vector3 vec6, Vector3 vec7, vec_ushort8 * threeQuads ) +{ + vec_float4 xyz0[3]; + vec_float4 xyz1[3]; + storeXYZArray( vec0, vec1, vec2, vec3, xyz0 ); + storeXYZArray( vec4, vec5, vec6, vec7, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +} + +inline Vector3 & Vector3::operator =( Vector3 vec ) +{ + mVec128 = vec.mVec128; + return *this; +} + +inline Vector3 & Vector3::setX( float _x ) +{ + mVec128 = spu_insert( _x, mVec128, 0 ); + return *this; +} + +inline float Vector3::getX( ) const +{ + return spu_extract( mVec128, 0 ); +} + +inline Vector3 & Vector3::setY( float _y ) +{ + mVec128 = spu_insert( _y, mVec128, 1 ); + return *this; +} + +inline float Vector3::getY( ) const +{ + return spu_extract( mVec128, 1 ); +} + +inline Vector3 & Vector3::setZ( float _z ) +{ + mVec128 = spu_insert( _z, mVec128, 2 ); + return *this; +} + +inline float Vector3::getZ( ) const +{ + return spu_extract( mVec128, 2 ); +} + +inline Vector3 & Vector3::setElem( int idx, float value ) +{ + mVec128 = spu_insert( value, mVec128, idx ); + return *this; +} + +inline float Vector3::getElem( int idx ) const +{ + return spu_extract( mVec128, idx ); +} + +inline VecIdx Vector3::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +inline float Vector3::operator []( int idx ) const +{ + return spu_extract( mVec128, idx ); +} + +inline const Vector3 Vector3::operator +( Vector3 vec ) const +{ + return Vector3( spu_add( mVec128, vec.mVec128 ) ); +} + +inline const Vector3 Vector3::operator -( Vector3 vec ) const +{ + return Vector3( spu_sub( mVec128, vec.mVec128 ) ); +} + +inline const Point3 Vector3::operator +( Point3 pnt ) const +{ + return Point3( spu_add( mVec128, pnt.get128() ) ); +} + +inline const Vector3 Vector3::operator *( float scalar ) const +{ + return Vector3( spu_mul( mVec128, spu_splats(scalar) ) ); +} + +inline Vector3 & Vector3::operator +=( Vector3 vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector3 & Vector3::operator -=( Vector3 vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector3 & Vector3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector3 Vector3::operator /( float scalar ) const +{ + return Vector3( divf4( mVec128, spu_splats(scalar) ) ); +} + +inline Vector3 & Vector3::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector3 Vector3::operator -( ) const +{ + return Vector3( negatef4( mVec128 ) ); +} + +inline const Vector3 operator *( float scalar, Vector3 vec ) +{ + return vec * scalar; +} + +inline const Vector3 mulPerElem( Vector3 vec0, Vector3 vec1 ) +{ + return Vector3( spu_mul( vec0.get128(), vec1.get128() ) ); +} + +inline const Vector3 divPerElem( Vector3 vec0, Vector3 vec1 ) +{ + return Vector3( divf4( vec0.get128(), vec1.get128() ) ); +} + +inline const Vector3 recipPerElem( Vector3 vec ) +{ + return Vector3( recipf4( vec.get128() ) ); +} + +inline const Vector3 sqrtPerElem( Vector3 vec ) +{ + return Vector3( sqrtf4( vec.get128() ) ); +} + +inline const Vector3 rsqrtPerElem( Vector3 vec ) +{ + return Vector3( rsqrtf4( vec.get128() ) ); +} + +inline const Vector3 absPerElem( Vector3 vec ) +{ + return Vector3( fabsf4( vec.get128() ) ); +} + +inline const Vector3 copySignPerElem( Vector3 vec0, Vector3 vec1 ) +{ + return Vector3( copysignf4( vec0.get128(), vec1.get128() ) ); +} + +inline const Vector3 maxPerElem( Vector3 vec0, Vector3 vec1 ) +{ + return Vector3( fmaxf4( vec0.get128(), vec1.get128() ) ); +} + +inline float maxElem( Vector3 vec ) +{ + vec_float4 result; + result = fmaxf4( spu_promote( spu_extract( vec.get128(), 1 ), 0 ), vec.get128() ); + result = fmaxf4( spu_promote( spu_extract( vec.get128(), 2 ), 0 ), result ); + return spu_extract( result, 0 ); +} + +inline const Vector3 minPerElem( Vector3 vec0, Vector3 vec1 ) +{ + return Vector3( fminf4( vec0.get128(), vec1.get128() ) ); +} + +inline float minElem( Vector3 vec ) +{ + vec_float4 result; + result = fminf4( spu_promote( spu_extract( vec.get128(), 1 ), 0 ), vec.get128() ); + result = fminf4( spu_promote( spu_extract( vec.get128(), 2 ), 0 ), result ); + return spu_extract( result, 0 ); +} + +inline float sum( Vector3 vec ) +{ + return + spu_extract( vec.get128(), 0 ) + + spu_extract( vec.get128(), 1 ) + + spu_extract( vec.get128(), 2 ); +} + +inline float dot( Vector3 vec0, Vector3 vec1 ) +{ + return spu_extract( _vmathVfDot3( vec0.get128(), vec1.get128() ), 0 ); +} + +inline float lengthSqr( Vector3 vec ) +{ + return spu_extract( _vmathVfDot3( vec.get128(), vec.get128() ), 0 ); +} + +inline float length( Vector3 vec ) +{ + return sqrtf( lengthSqr( vec ) ); +} + +inline const Vector3 normalize( Vector3 vec ) +{ + vec_float4 dot = _vmathVfDot3( vec.get128(), vec.get128() ); + dot = spu_shuffle( dot, dot, (vec_uchar16)spu_splats(0x00010203) ); + return Vector3( spu_mul( vec.get128(), rsqrtf4( dot ) ) ); +} + +inline const Vector3 cross( Vector3 vec0, Vector3 vec1 ) +{ + return Vector3( _vmathVfCross( vec0.get128(), vec1.get128() ) ); +} + +inline const Vector3 select( Vector3 vec0, Vector3 vec1, bool select1 ) +{ + return Vector3( spu_sel( vec0.get128(), vec1.get128(), spu_splats( (unsigned int)-(select1 > 0) ) ) ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( Vector3 vec ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +inline void print( Vector3 vec, const char * name ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +#endif + +inline Vector4::Vector4( float _x, float _y, float _z, float _w ) +{ + mVec128 = (vec_float4){ _x, _y, _z, _w }; +} + +inline Vector4::Vector4( Vector3 xyz, float _w ) +{ + mVec128 = spu_shuffle( xyz.get128(), spu_promote( _w, 0 ), _VECTORMATH_SHUF_XYZA ); +} + +inline Vector4::Vector4( Vector3 vec ) +{ + mVec128 = spu_sel( vec.get128(), spu_splats(0.0f), (vec_uint4)spu_maskb(0x000f) ); +} + +inline Vector4::Vector4( Point3 pnt ) +{ + mVec128 = spu_sel( pnt.get128(), spu_splats(1.0f), (vec_uint4)spu_maskb(0x000f) ); +} + +inline Vector4::Vector4( Quat quat ) +{ + mVec128 = quat.get128(); +} + +inline Vector4::Vector4( float scalar ) +{ + mVec128 = spu_splats( scalar ); +} + +inline Vector4::Vector4( vec_float4 vf4 ) +{ + mVec128 = vf4; +} + +inline const Vector4 Vector4::xAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_1000 ); +} + +inline const Vector4 Vector4::yAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0100 ); +} + +inline const Vector4 Vector4::zAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0010 ); +} + +inline const Vector4 Vector4::wAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0001 ); +} + +inline const Vector4 lerp( float t, Vector4 vec0, Vector4 vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector4 slerp( float t, Vector4 unitVec0, Vector4 unitVec1 ) +{ + vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + vec_uint4 selectMask; + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + cosAngle = _vmathVfDot4( unitVec0.get128(), unitVec1.get128() ); + cosAngle = spu_shuffle( cosAngle, cosAngle, shuffle_xxxx ); + selectMask = (vec_uint4)spu_cmpgt( spu_splats(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = spu_splats(t); + oneMinusT = spu_sub( spu_splats(1.0f), tttt ); + angles = spu_sel( spu_splats(1.0f), oneMinusT, (vec_uint4)spu_maskb(0x0f00) ); + angles = spu_sel( angles, tttt, (vec_uint4)spu_maskb(0x00f0) ); + angles = spu_mul( angles, angle ); + sines = sinf4( angles ); + scales = divf4( sines, spu_shuffle( sines, sines, shuffle_xxxx ) ); + scale0 = spu_sel( oneMinusT, spu_shuffle( scales, scales, shuffle_yyyy ), selectMask ); + scale1 = spu_sel( tttt, spu_shuffle( scales, scales, shuffle_zzzz ), selectMask ); + return Vector4( spu_madd( unitVec0.get128(), scale0, spu_mul( unitVec1.get128(), scale1 ) ) ); +} + +inline vec_float4 Vector4::get128( ) const +{ + return mVec128; +} + +inline void storeHalfFloats( Vector4 vec0, Vector4 vec1, Vector4 vec2, Vector4 vec3, vec_ushort8 * twoQuads ) +{ + twoQuads[0] = _vmath2VfToHalfFloats(vec0.get128(), vec1.get128()); + twoQuads[1] = _vmath2VfToHalfFloats(vec2.get128(), vec3.get128()); +} + +inline Vector4 & Vector4::operator =( Vector4 vec ) +{ + mVec128 = vec.mVec128; + return *this; +} + +inline Vector4 & Vector4::setXYZ( Vector3 vec ) +{ + mVec128 = spu_sel( vec.get128(), mVec128, (vec_uint4)spu_maskb(0x000f) ); + return *this; +} + +inline const Vector3 Vector4::getXYZ( ) const +{ + return Vector3( mVec128 ); +} + +inline Vector4 & Vector4::setX( float _x ) +{ + mVec128 = spu_insert( _x, mVec128, 0 ); + return *this; +} + +inline float Vector4::getX( ) const +{ + return spu_extract( mVec128, 0 ); +} + +inline Vector4 & Vector4::setY( float _y ) +{ + mVec128 = spu_insert( _y, mVec128, 1 ); + return *this; +} + +inline float Vector4::getY( ) const +{ + return spu_extract( mVec128, 1 ); +} + +inline Vector4 & Vector4::setZ( float _z ) +{ + mVec128 = spu_insert( _z, mVec128, 2 ); + return *this; +} + +inline float Vector4::getZ( ) const +{ + return spu_extract( mVec128, 2 ); +} + +inline Vector4 & Vector4::setW( float _w ) +{ + mVec128 = spu_insert( _w, mVec128, 3 ); + return *this; +} + +inline float Vector4::getW( ) const +{ + return spu_extract( mVec128, 3 ); +} + +inline Vector4 & Vector4::setElem( int idx, float value ) +{ + mVec128 = spu_insert( value, mVec128, idx ); + return *this; +} + +inline float Vector4::getElem( int idx ) const +{ + return spu_extract( mVec128, idx ); +} + +inline VecIdx Vector4::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +inline float Vector4::operator []( int idx ) const +{ + return spu_extract( mVec128, idx ); +} + +inline const Vector4 Vector4::operator +( Vector4 vec ) const +{ + return Vector4( spu_add( mVec128, vec.mVec128 ) ); +} + +inline const Vector4 Vector4::operator -( Vector4 vec ) const +{ + return Vector4( spu_sub( mVec128, vec.mVec128 ) ); +} + +inline const Vector4 Vector4::operator *( float scalar ) const +{ + return Vector4( spu_mul( mVec128, spu_splats(scalar) ) ); +} + +inline Vector4 & Vector4::operator +=( Vector4 vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector4 & Vector4::operator -=( Vector4 vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector4 & Vector4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector4 Vector4::operator /( float scalar ) const +{ + return Vector4( divf4( mVec128, spu_splats(scalar) ) ); +} + +inline Vector4 & Vector4::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector4 Vector4::operator -( ) const +{ + return Vector4( negatef4( mVec128 ) ); +} + +inline const Vector4 operator *( float scalar, Vector4 vec ) +{ + return vec * scalar; +} + +inline const Vector4 mulPerElem( Vector4 vec0, Vector4 vec1 ) +{ + return Vector4( spu_mul( vec0.get128(), vec1.get128() ) ); +} + +inline const Vector4 divPerElem( Vector4 vec0, Vector4 vec1 ) +{ + return Vector4( divf4( vec0.get128(), vec1.get128() ) ); +} + +inline const Vector4 recipPerElem( Vector4 vec ) +{ + return Vector4( recipf4( vec.get128() ) ); +} + +inline const Vector4 sqrtPerElem( Vector4 vec ) +{ + return Vector4( sqrtf4( vec.get128() ) ); +} + +inline const Vector4 rsqrtPerElem( Vector4 vec ) +{ + return Vector4( rsqrtf4( vec.get128() ) ); +} + +inline const Vector4 absPerElem( Vector4 vec ) +{ + return Vector4( fabsf4( vec.get128() ) ); +} + +inline const Vector4 copySignPerElem( Vector4 vec0, Vector4 vec1 ) +{ + return Vector4( copysignf4( vec0.get128(), vec1.get128() ) ); +} + +inline const Vector4 maxPerElem( Vector4 vec0, Vector4 vec1 ) +{ + return Vector4( fmaxf4( vec0.get128(), vec1.get128() ) ); +} + +inline float maxElem( Vector4 vec ) +{ + vec_float4 result; + result = fmaxf4( spu_promote( spu_extract( vec.get128(), 1 ), 0 ), vec.get128() ); + result = fmaxf4( spu_promote( spu_extract( vec.get128(), 2 ), 0 ), result ); + result = fmaxf4( spu_promote( spu_extract( vec.get128(), 3 ), 0 ), result ); + return spu_extract( result, 0 ); +} + +inline const Vector4 minPerElem( Vector4 vec0, Vector4 vec1 ) +{ + return Vector4( fminf4( vec0.get128(), vec1.get128() ) ); +} + +inline float minElem( Vector4 vec ) +{ + vec_float4 result; + result = fminf4( spu_promote( spu_extract( vec.get128(), 1 ), 0 ), vec.get128() ); + result = fminf4( spu_promote( spu_extract( vec.get128(), 2 ), 0 ), result ); + result = fminf4( spu_promote( spu_extract( vec.get128(), 3 ), 0 ), result ); + return spu_extract( result, 0 ); +} + +inline float sum( Vector4 vec ) +{ + return + spu_extract( vec.get128(), 0 ) + + spu_extract( vec.get128(), 1 ) + + spu_extract( vec.get128(), 2 ) + + spu_extract( vec.get128(), 3 ); +} + +inline float dot( Vector4 vec0, Vector4 vec1 ) +{ + return spu_extract( _vmathVfDot4( vec0.get128(), vec1.get128() ), 0 ); +} + +inline float lengthSqr( Vector4 vec ) +{ + return spu_extract( _vmathVfDot4( vec.get128(), vec.get128() ), 0 ); +} + +inline float length( Vector4 vec ) +{ + return sqrtf( lengthSqr( vec ) ); +} + +inline const Vector4 normalize( Vector4 vec ) +{ + vec_float4 dot = _vmathVfDot4( vec.get128(), vec.get128() ); + return Vector4( spu_mul( vec.get128(), rsqrtf4( dot ) ) ); +} + +inline const Vector4 select( Vector4 vec0, Vector4 vec1, bool select1 ) +{ + return Vector4( spu_sel( vec0.get128(), vec1.get128(), spu_splats( (unsigned int)-(select1 > 0) ) ) ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( Vector4 vec ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +inline void print( Vector4 vec, const char * name ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +#endif + +inline Point3::Point3( float _x, float _y, float _z ) +{ + mVec128 = (vec_float4){ _x, _y, _z, 0.0f }; +} + +inline Point3::Point3( Vector3 vec ) +{ + mVec128 = vec.get128(); +} + +inline Point3::Point3( float scalar ) +{ + mVec128 = spu_splats( scalar ); +} + +inline Point3::Point3( vec_float4 vf4 ) +{ + mVec128 = vf4; +} + +inline const Point3 lerp( float t, Point3 pnt0, Point3 pnt1 ) +{ + return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); +} + +inline vec_float4 Point3::get128( ) const +{ + return mVec128; +} + +inline void storeXYZ( Point3 pnt, vec_float4 * quad ) +{ + vec_float4 dstVec = *quad; + vec_uint4 mask = (vec_uint4)spu_maskb(0x000f); + dstVec = spu_sel(pnt.get128(), dstVec, mask); + *quad = dstVec; +} + +inline void loadXYZArray( Point3 & pnt0, Point3 & pnt1, Point3 & pnt2, Point3 & pnt3, const vec_float4 * threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz, xyz1, xyz2, xyz3; + xyzx = threeQuads[0]; + yzxy = threeQuads[1]; + zxyz = threeQuads[2]; + xyz1 = spu_shuffle( xyzx, yzxy, _VECTORMATH_SHUF_WABC ); + xyz2 = spu_shuffle( yzxy, zxyz, _VECTORMATH_SHUF_ZWAB ); + xyz3 = spu_rlqwbyte( zxyz, 4 ); + pnt0 = Point3( xyzx ); + pnt1 = Point3( xyz1 ); + pnt2 = Point3( xyz2 ); + pnt3 = Point3( xyz3 ); +} + +inline void storeXYZArray( Point3 pnt0, Point3 pnt1, Point3 pnt2, Point3 pnt3, vec_float4 * threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz; + xyzx = spu_shuffle( pnt0.get128(), pnt1.get128(), _VECTORMATH_SHUF_XYZA ); + yzxy = spu_shuffle( pnt1.get128(), pnt2.get128(), _VECTORMATH_SHUF_YZAB ); + zxyz = spu_shuffle( pnt2.get128(), pnt3.get128(), _VECTORMATH_SHUF_ZABC ); + threeQuads[0] = xyzx; + threeQuads[1] = yzxy; + threeQuads[2] = zxyz; +} + +inline void storeHalfFloats( Point3 pnt0, Point3 pnt1, Point3 pnt2, Point3 pnt3, Point3 pnt4, Point3 pnt5, Point3 pnt6, Point3 pnt7, vec_ushort8 * threeQuads ) +{ + vec_float4 xyz0[3]; + vec_float4 xyz1[3]; + storeXYZArray( pnt0, pnt1, pnt2, pnt3, xyz0 ); + storeXYZArray( pnt4, pnt5, pnt6, pnt7, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +} + +inline Point3 & Point3::operator =( Point3 pnt ) +{ + mVec128 = pnt.mVec128; + return *this; +} + +inline Point3 & Point3::setX( float _x ) +{ + mVec128 = spu_insert( _x, mVec128, 0 ); + return *this; +} + +inline float Point3::getX( ) const +{ + return spu_extract( mVec128, 0 ); +} + +inline Point3 & Point3::setY( float _y ) +{ + mVec128 = spu_insert( _y, mVec128, 1 ); + return *this; +} + +inline float Point3::getY( ) const +{ + return spu_extract( mVec128, 1 ); +} + +inline Point3 & Point3::setZ( float _z ) +{ + mVec128 = spu_insert( _z, mVec128, 2 ); + return *this; +} + +inline float Point3::getZ( ) const +{ + return spu_extract( mVec128, 2 ); +} + +inline Point3 & Point3::setElem( int idx, float value ) +{ + mVec128 = spu_insert( value, mVec128, idx ); + return *this; +} + +inline float Point3::getElem( int idx ) const +{ + return spu_extract( mVec128, idx ); +} + +inline VecIdx Point3::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +inline float Point3::operator []( int idx ) const +{ + return spu_extract( mVec128, idx ); +} + +inline const Vector3 Point3::operator -( Point3 pnt ) const +{ + return Vector3( spu_sub( mVec128, pnt.mVec128 ) ); +} + +inline const Point3 Point3::operator +( Vector3 vec ) const +{ + return Point3( spu_add( mVec128, vec.get128() ) ); +} + +inline const Point3 Point3::operator -( Vector3 vec ) const +{ + return Point3( spu_sub( mVec128, vec.get128() ) ); +} + +inline Point3 & Point3::operator +=( Vector3 vec ) +{ + *this = *this + vec; + return *this; +} + +inline Point3 & Point3::operator -=( Vector3 vec ) +{ + *this = *this - vec; + return *this; +} + +inline const Point3 mulPerElem( Point3 pnt0, Point3 pnt1 ) +{ + return Point3( spu_mul( pnt0.get128(), pnt1.get128() ) ); +} + +inline const Point3 divPerElem( Point3 pnt0, Point3 pnt1 ) +{ + return Point3( divf4( pnt0.get128(), pnt1.get128() ) ); +} + +inline const Point3 recipPerElem( Point3 pnt ) +{ + return Point3( recipf4( pnt.get128() ) ); +} + +inline const Point3 sqrtPerElem( Point3 pnt ) +{ + return Point3( sqrtf4( pnt.get128() ) ); +} + +inline const Point3 rsqrtPerElem( Point3 pnt ) +{ + return Point3( rsqrtf4( pnt.get128() ) ); +} + +inline const Point3 absPerElem( Point3 pnt ) +{ + return Point3( fabsf4( pnt.get128() ) ); +} + +inline const Point3 copySignPerElem( Point3 pnt0, Point3 pnt1 ) +{ + return Point3( copysignf4( pnt0.get128(), pnt1.get128() ) ); +} + +inline const Point3 maxPerElem( Point3 pnt0, Point3 pnt1 ) +{ + return Point3( fmaxf4( pnt0.get128(), pnt1.get128() ) ); +} + +inline float maxElem( Point3 pnt ) +{ + vec_float4 result; + result = fmaxf4( spu_promote( spu_extract( pnt.get128(), 1 ), 0 ), pnt.get128() ); + result = fmaxf4( spu_promote( spu_extract( pnt.get128(), 2 ), 0 ), result ); + return spu_extract( result, 0 ); +} + +inline const Point3 minPerElem( Point3 pnt0, Point3 pnt1 ) +{ + return Point3( fminf4( pnt0.get128(), pnt1.get128() ) ); +} + +inline float minElem( Point3 pnt ) +{ + vec_float4 result; + result = fminf4( spu_promote( spu_extract( pnt.get128(), 1 ), 0 ), pnt.get128() ); + result = fminf4( spu_promote( spu_extract( pnt.get128(), 2 ), 0 ), result ); + return spu_extract( result, 0 ); +} + +inline float sum( Point3 pnt ) +{ + return + spu_extract( pnt.get128(), 0 ) + + spu_extract( pnt.get128(), 1 ) + + spu_extract( pnt.get128(), 2 ); +} + +inline const Point3 scale( Point3 pnt, float scaleVal ) +{ + return mulPerElem( pnt, Point3( scaleVal ) ); +} + +inline const Point3 scale( Point3 pnt, Vector3 scaleVec ) +{ + return mulPerElem( pnt, Point3( scaleVec ) ); +} + +inline float projection( Point3 pnt, Vector3 unitVec ) +{ + return spu_extract( _vmathVfDot3( pnt.get128(), unitVec.get128() ), 0 ); +} + +inline float distSqrFromOrigin( Point3 pnt ) +{ + return lengthSqr( Vector3( pnt ) ); +} + +inline float distFromOrigin( Point3 pnt ) +{ + return length( Vector3( pnt ) ); +} + +inline float distSqr( Point3 pnt0, Point3 pnt1 ) +{ + return lengthSqr( ( pnt1 - pnt0 ) ); +} + +inline float dist( Point3 pnt0, Point3 pnt1 ) +{ + return length( ( pnt1 - pnt0 ) ); +} + +inline const Point3 select( Point3 pnt0, Point3 pnt1, bool select1 ) +{ + return Point3( spu_sel( pnt0.get128(), pnt1.get128(), spu_splats( (unsigned int)-(select1 > 0) ) ) ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( Point3 pnt ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = pnt.get128(); + printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +inline void print( Point3 pnt, const char * name ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = pnt.get128(); + printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/cpp/vec_soa.h b/Extras/vectormathlibrary/include/vectormath/spu/cpp/vec_soa.h new file mode 100644 index 0000000..1ac6577 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/cpp/vec_soa.h @@ -0,0 +1,1439 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_SOA_CPP_H +#define _VECTORMATH_VEC_SOA_CPP_H +//----------------------------------------------------------------------------- +// Constants +// for shuffles, words are labeled [x,y,z,w] [a,b,c,d] + +#define _VECTORMATH_SHUF_X 0x00010203 +#define _VECTORMATH_SHUF_Y 0x04050607 +#define _VECTORMATH_SHUF_Z 0x08090a0b +#define _VECTORMATH_SHUF_W 0x0c0d0e0f +#define _VECTORMATH_SHUF_A 0x10111213 +#define _VECTORMATH_SHUF_B 0x14151617 +#define _VECTORMATH_SHUF_C 0x18191a1b +#define _VECTORMATH_SHUF_D 0x1c1d1e1f +#define _VECTORMATH_SHUF_0 0x80808080 +#define _VECTORMATH_SHUF_XAYB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_ZCWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_ZBW0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_XCY0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_ZDW0 ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_D, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_0 }) +#define _VECTORMATH_SHUF_XAZC ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_C }) +#define _VECTORMATH_SHUF_ZDXB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_D, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_YBWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_XDZB ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_D, _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_B }) +#define _VECTORMATH_SHUF_YAWC ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_A, _VECTORMATH_SHUF_W, _VECTORMATH_SHUF_C }) +#define _VECTORMATH_SHUF_ZBXD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_Z, _VECTORMATH_SHUF_B, _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SHUF_XYCD ((vec_uchar16)(vec_uint4){ _VECTORMATH_SHUF_X, _VECTORMATH_SHUF_Y, _VECTORMATH_SHUF_C, _VECTORMATH_SHUF_D }) +#define _VECTORMATH_SLERP_TOL 0.999f + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Soa { + +inline Vector3::Vector3( const Vector3 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; +} + +inline Vector3::Vector3( vec_float4 _x, vec_float4 _y, vec_float4 _z ) +{ + mX = _x; + mY = _y; + mZ = _z; +} + +inline Vector3::Vector3( const Point3 & pnt ) +{ + mX = pnt.getX(); + mY = pnt.getY(); + mZ = pnt.getZ(); +} + +inline Vector3::Vector3( vec_float4 scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; +} + +inline Vector3::Vector3( Aos::Vector3 vec ) +{ + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + vec_float4 vec128 = vec.get128(); + mX = spu_shuffle( vec128, vec128, shuffle_xxxx ); + mY = spu_shuffle( vec128, vec128, shuffle_yyyy ); + mZ = spu_shuffle( vec128, vec128, shuffle_zzzz ); +} + +inline Vector3::Vector3( Aos::Vector3 vec0, Aos::Vector3 vec1, Aos::Vector3 vec2, Aos::Vector3 vec3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = spu_shuffle( vec0.get128(), vec2.get128(), _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( vec1.get128(), vec3.get128(), _VECTORMATH_SHUF_XAYB ); + tmp2 = spu_shuffle( vec0.get128(), vec2.get128(), _VECTORMATH_SHUF_ZCWD ); + tmp3 = spu_shuffle( vec1.get128(), vec3.get128(), _VECTORMATH_SHUF_ZCWD ); + mX = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_XAYB ); + mY = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_ZCWD ); + mZ = spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_XAYB ); +} + +inline const Vector3 Vector3::xAxis( ) +{ + return Vector3( spu_splats(1.0f), spu_splats(0.0f), spu_splats(0.0f) ); +} + +inline const Vector3 Vector3::yAxis( ) +{ + return Vector3( spu_splats(0.0f), spu_splats(1.0f), spu_splats(0.0f) ); +} + +inline const Vector3 Vector3::zAxis( ) +{ + return Vector3( spu_splats(0.0f), spu_splats(0.0f), spu_splats(1.0f) ); +} + +inline const Vector3 lerp( vec_float4 t, const Vector3 & vec0, const Vector3 & vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector3 slerp( vec_float4 t, const Vector3 & unitVec0, const Vector3 & unitVec1 ) +{ + vec_float4 recipSinAngle, scale0, scale1, cosAngle, angle; + vec_uint4 selectMask; + cosAngle = dot( unitVec0, unitVec1 ); + selectMask = (vec_uint4)spu_cmpgt( spu_splats(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + recipSinAngle = recipf4( sinf4( angle ) ); + scale0 = spu_sel( spu_sub( spu_splats(1.0f), t ), spu_mul( sinf4( spu_mul( spu_sub( spu_splats(1.0f), t ), angle ) ), recipSinAngle ), selectMask ); + scale1 = spu_sel( t, spu_mul( sinf4( spu_mul( t, angle ) ), recipSinAngle ), selectMask ); + return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); +} + +inline void Vector3::get4Aos( Aos::Vector3 & result0, Aos::Vector3 & result1, Aos::Vector3 & result2, Aos::Vector3 & result3 ) const +{ + vec_float4 tmp0, tmp1; + tmp0 = spu_shuffle( mX, mZ, _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( mX, mZ, _VECTORMATH_SHUF_ZCWD ); + result0 = Aos::Vector3( spu_shuffle( tmp0, mY, _VECTORMATH_SHUF_XAYB ) ); + result1 = Aos::Vector3( spu_shuffle( tmp0, mY, _VECTORMATH_SHUF_ZBW0 ) ); + result2 = Aos::Vector3( spu_shuffle( tmp1, mY, _VECTORMATH_SHUF_XCY0 ) ); + result3 = Aos::Vector3( spu_shuffle( tmp1, mY, _VECTORMATH_SHUF_ZDW0 ) ); +} + +inline void loadXYZArray( Vector3 & vec, const vec_float4 * threeQuads ) +{ + vec_float4 xyxy, yzyz, zxzx, xyzx, yzxy, zxyz; + xyzx = threeQuads[0]; + yzxy = threeQuads[1]; + zxyz = threeQuads[2]; + xyxy = spu_shuffle( xyzx, yzxy, _VECTORMATH_SHUF_XYCD ); + zxzx = spu_shuffle( zxyz, xyzx, _VECTORMATH_SHUF_XYCD ); + yzyz = spu_shuffle( yzxy, zxyz, _VECTORMATH_SHUF_XYCD ); + vec.setX( spu_shuffle( xyxy, zxzx, _VECTORMATH_SHUF_XDZB ) ); + vec.setY( spu_shuffle( xyxy, yzyz, _VECTORMATH_SHUF_YAWC ) ); + vec.setZ( spu_shuffle( zxzx, yzyz, _VECTORMATH_SHUF_ZBXD ) ); +} + +inline void storeXYZArray( const Vector3 & vec, vec_float4 * threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz, xyxy, zxzx, yzyz; + xyxy = spu_shuffle( vec.getX(), vec.getY(), _VECTORMATH_SHUF_XAZC ); + zxzx = spu_shuffle( vec.getZ(), vec.getX(), _VECTORMATH_SHUF_ZDXB ); + yzyz = spu_shuffle( vec.getY(), vec.getZ(), _VECTORMATH_SHUF_YBWD ); + xyzx = spu_shuffle( xyxy, zxzx, _VECTORMATH_SHUF_XYCD ); + yzxy = spu_shuffle( yzyz, xyxy, _VECTORMATH_SHUF_XYCD ); + zxyz = spu_shuffle( zxzx, yzyz, _VECTORMATH_SHUF_XYCD ); + threeQuads[0] = xyzx; + threeQuads[1] = yzxy; + threeQuads[2] = zxyz; +} + +inline void storeHalfFloats( const Vector3 & vec0, const Vector3 & vec1, vec_ushort8 * threeQuads ) +{ + vec_float4 xyz0[3]; + vec_float4 xyz1[3]; + storeXYZArray( vec0, xyz0 ); + storeXYZArray( vec1, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +} + +inline Vector3 & Vector3::operator =( const Vector3 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + return *this; +} + +inline Vector3 & Vector3::setX( vec_float4 _x ) +{ + mX = _x; + return *this; +} + +inline vec_float4 Vector3::getX( ) const +{ + return mX; +} + +inline Vector3 & Vector3::setY( vec_float4 _y ) +{ + mY = _y; + return *this; +} + +inline vec_float4 Vector3::getY( ) const +{ + return mY; +} + +inline Vector3 & Vector3::setZ( vec_float4 _z ) +{ + mZ = _z; + return *this; +} + +inline vec_float4 Vector3::getZ( ) const +{ + return mZ; +} + +inline Vector3 & Vector3::setElem( int idx, vec_float4 value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline vec_float4 Vector3::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline Vector3::vec_float4_t & Vector3::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline vec_float4 Vector3::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector3 Vector3::operator +( const Vector3 & vec ) const +{ + return Vector3( + spu_add( mX, vec.mX ), + spu_add( mY, vec.mY ), + spu_add( mZ, vec.mZ ) + ); +} + +inline const Vector3 Vector3::operator -( const Vector3 & vec ) const +{ + return Vector3( + spu_sub( mX, vec.mX ), + spu_sub( mY, vec.mY ), + spu_sub( mZ, vec.mZ ) + ); +} + +inline const Point3 Vector3::operator +( const Point3 & pnt ) const +{ + return Point3( + spu_add( mX, pnt.getX() ), + spu_add( mY, pnt.getY() ), + spu_add( mZ, pnt.getZ() ) + ); +} + +inline const Vector3 Vector3::operator *( vec_float4 scalar ) const +{ + return Vector3( + spu_mul( mX, scalar ), + spu_mul( mY, scalar ), + spu_mul( mZ, scalar ) + ); +} + +inline Vector3 & Vector3::operator +=( const Vector3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector3 & Vector3::operator -=( const Vector3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector3 & Vector3::operator *=( vec_float4 scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector3 Vector3::operator /( vec_float4 scalar ) const +{ + return Vector3( + divf4( mX, scalar ), + divf4( mY, scalar ), + divf4( mZ, scalar ) + ); +} + +inline Vector3 & Vector3::operator /=( vec_float4 scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector3 Vector3::operator -( ) const +{ + return Vector3( + negatef4( mX ), + negatef4( mY ), + negatef4( mZ ) + ); +} + +inline const Vector3 operator *( vec_float4 scalar, const Vector3 & vec ) +{ + return vec * scalar; +} + +inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + spu_mul( vec0.getX(), vec1.getX() ), + spu_mul( vec0.getY(), vec1.getY() ), + spu_mul( vec0.getZ(), vec1.getZ() ) + ); +} + +inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + divf4( vec0.getX(), vec1.getX() ), + divf4( vec0.getY(), vec1.getY() ), + divf4( vec0.getZ(), vec1.getZ() ) + ); +} + +inline const Vector3 recipPerElem( const Vector3 & vec ) +{ + return Vector3( + recipf4( vec.getX() ), + recipf4( vec.getY() ), + recipf4( vec.getZ() ) + ); +} + +inline const Vector3 sqrtPerElem( const Vector3 & vec ) +{ + return Vector3( + sqrtf4( vec.getX() ), + sqrtf4( vec.getY() ), + sqrtf4( vec.getZ() ) + ); +} + +inline const Vector3 rsqrtPerElem( const Vector3 & vec ) +{ + return Vector3( + rsqrtf4( vec.getX() ), + rsqrtf4( vec.getY() ), + rsqrtf4( vec.getZ() ) + ); +} + +inline const Vector3 absPerElem( const Vector3 & vec ) +{ + return Vector3( + fabsf4( vec.getX() ), + fabsf4( vec.getY() ), + fabsf4( vec.getZ() ) + ); +} + +inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + copysignf4( vec0.getX(), vec1.getX() ), + copysignf4( vec0.getY(), vec1.getY() ), + copysignf4( vec0.getZ(), vec1.getZ() ) + ); +} + +inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + fmaxf4( vec0.getX(), vec1.getX() ), + fmaxf4( vec0.getY(), vec1.getY() ), + fmaxf4( vec0.getZ(), vec1.getZ() ) + ); +} + +inline vec_float4 maxElem( const Vector3 & vec ) +{ + vec_float4 result; + result = fmaxf4( vec.getX(), vec.getY() ); + result = fmaxf4( vec.getZ(), result ); + return result; +} + +inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + fminf4( vec0.getX(), vec1.getX() ), + fminf4( vec0.getY(), vec1.getY() ), + fminf4( vec0.getZ(), vec1.getZ() ) + ); +} + +inline vec_float4 minElem( const Vector3 & vec ) +{ + vec_float4 result; + result = fminf4( vec.getX(), vec.getY() ); + result = fminf4( vec.getZ(), result ); + return result; +} + +inline vec_float4 sum( const Vector3 & vec ) +{ + vec_float4 result; + result = spu_add( vec.getX(), vec.getY() ); + result = spu_add( result, vec.getZ() ); + return result; +} + +inline vec_float4 dot( const Vector3 & vec0, const Vector3 & vec1 ) +{ + vec_float4 result; + result = spu_mul( vec0.getX(), vec1.getX() ); + result = spu_add( result, spu_mul( vec0.getY(), vec1.getY() ) ); + result = spu_add( result, spu_mul( vec0.getZ(), vec1.getZ() ) ); + return result; +} + +inline vec_float4 lengthSqr( const Vector3 & vec ) +{ + vec_float4 result; + result = spu_mul( vec.getX(), vec.getX() ); + result = spu_add( result, spu_mul( vec.getY(), vec.getY() ) ); + result = spu_add( result, spu_mul( vec.getZ(), vec.getZ() ) ); + return result; +} + +inline vec_float4 length( const Vector3 & vec ) +{ + return sqrtf4( lengthSqr( vec ) ); +} + +inline const Vector3 normalize( const Vector3 & vec ) +{ + vec_float4 lenSqr, lenInv; + lenSqr = lengthSqr( vec ); + lenInv = rsqrtf4( lenSqr ); + return Vector3( + spu_mul( vec.getX(), lenInv ), + spu_mul( vec.getY(), lenInv ), + spu_mul( vec.getZ(), lenInv ) + ); +} + +inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + spu_sub( spu_mul( vec0.getY(), vec1.getZ() ), spu_mul( vec0.getZ(), vec1.getY() ) ), + spu_sub( spu_mul( vec0.getZ(), vec1.getX() ), spu_mul( vec0.getX(), vec1.getZ() ) ), + spu_sub( spu_mul( vec0.getX(), vec1.getY() ), spu_mul( vec0.getY(), vec1.getX() ) ) + ); +} + +inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, vec_uint4 select1 ) +{ + return Vector3( + spu_sel( vec0.getX(), vec1.getX(), select1 ), + spu_sel( vec0.getY(), vec1.getY(), select1 ), + spu_sel( vec0.getZ(), vec1.getZ(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Vector3 & vec ) +{ + Aos::Vector3 vec0, vec1, vec2, vec3; + vec.get4Aos( vec0, vec1, vec2, vec3 ); + printf("slot 0:\n"); + print( vec0 ); + printf("slot 1:\n"); + print( vec1 ); + printf("slot 2:\n"); + print( vec2 ); + printf("slot 3:\n"); + print( vec3 ); +} + +inline void print( const Vector3 & vec, const char * name ) +{ + Aos::Vector3 vec0, vec1, vec2, vec3; + printf( "%s:\n", name ); + vec.get4Aos( vec0, vec1, vec2, vec3 ); + printf("slot 0:\n"); + print( vec0 ); + printf("slot 1:\n"); + print( vec1 ); + printf("slot 2:\n"); + print( vec2 ); + printf("slot 3:\n"); + print( vec3 ); +} + +#endif + +inline Vector4::Vector4( const Vector4 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + mW = vec.mW; +} + +inline Vector4::Vector4( vec_float4 _x, vec_float4 _y, vec_float4 _z, vec_float4 _w ) +{ + mX = _x; + mY = _y; + mZ = _z; + mW = _w; +} + +inline Vector4::Vector4( const Vector3 & xyz, vec_float4 _w ) +{ + this->setXYZ( xyz ); + this->setW( _w ); +} + +inline Vector4::Vector4( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + mW = spu_splats(0.0f); +} + +inline Vector4::Vector4( const Point3 & pnt ) +{ + mX = pnt.getX(); + mY = pnt.getY(); + mZ = pnt.getZ(); + mW = spu_splats(1.0f); +} + +inline Vector4::Vector4( const Quat & quat ) +{ + mX = quat.getX(); + mY = quat.getY(); + mZ = quat.getZ(); + mW = quat.getW(); +} + +inline Vector4::Vector4( vec_float4 scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; + mW = scalar; +} + +inline Vector4::Vector4( Aos::Vector4 vec ) +{ + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + vec_uchar16 shuffle_wwww = (vec_uchar16)spu_splats((int)0x0c0d0e0f); + vec_float4 vec128 = vec.get128(); + mX = spu_shuffle( vec128, vec128, shuffle_xxxx ); + mY = spu_shuffle( vec128, vec128, shuffle_yyyy ); + mZ = spu_shuffle( vec128, vec128, shuffle_zzzz ); + mW = spu_shuffle( vec128, vec128, shuffle_wwww ); +} + +inline Vector4::Vector4( Aos::Vector4 vec0, Aos::Vector4 vec1, Aos::Vector4 vec2, Aos::Vector4 vec3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = spu_shuffle( vec0.get128(), vec2.get128(), _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( vec1.get128(), vec3.get128(), _VECTORMATH_SHUF_XAYB ); + tmp2 = spu_shuffle( vec0.get128(), vec2.get128(), _VECTORMATH_SHUF_ZCWD ); + tmp3 = spu_shuffle( vec1.get128(), vec3.get128(), _VECTORMATH_SHUF_ZCWD ); + mX = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_XAYB ); + mY = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_ZCWD ); + mZ = spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_XAYB ); + mW = spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_ZCWD ); +} + +inline const Vector4 Vector4::xAxis( ) +{ + return Vector4( spu_splats(1.0f), spu_splats(0.0f), spu_splats(0.0f), spu_splats(0.0f) ); +} + +inline const Vector4 Vector4::yAxis( ) +{ + return Vector4( spu_splats(0.0f), spu_splats(1.0f), spu_splats(0.0f), spu_splats(0.0f) ); +} + +inline const Vector4 Vector4::zAxis( ) +{ + return Vector4( spu_splats(0.0f), spu_splats(0.0f), spu_splats(1.0f), spu_splats(0.0f) ); +} + +inline const Vector4 Vector4::wAxis( ) +{ + return Vector4( spu_splats(0.0f), spu_splats(0.0f), spu_splats(0.0f), spu_splats(1.0f) ); +} + +inline const Vector4 lerp( vec_float4 t, const Vector4 & vec0, const Vector4 & vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector4 slerp( vec_float4 t, const Vector4 & unitVec0, const Vector4 & unitVec1 ) +{ + vec_float4 recipSinAngle, scale0, scale1, cosAngle, angle; + vec_uint4 selectMask; + cosAngle = dot( unitVec0, unitVec1 ); + selectMask = (vec_uint4)spu_cmpgt( spu_splats(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + recipSinAngle = recipf4( sinf4( angle ) ); + scale0 = spu_sel( spu_sub( spu_splats(1.0f), t ), spu_mul( sinf4( spu_mul( spu_sub( spu_splats(1.0f), t ), angle ) ), recipSinAngle ), selectMask ); + scale1 = spu_sel( t, spu_mul( sinf4( spu_mul( t, angle ) ), recipSinAngle ), selectMask ); + return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); +} + +inline void Vector4::get4Aos( Aos::Vector4 & result0, Aos::Vector4 & result1, Aos::Vector4 & result2, Aos::Vector4 & result3 ) const +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = spu_shuffle( mX, mZ, _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( mY, mW, _VECTORMATH_SHUF_XAYB ); + tmp2 = spu_shuffle( mX, mZ, _VECTORMATH_SHUF_ZCWD ); + tmp3 = spu_shuffle( mY, mW, _VECTORMATH_SHUF_ZCWD ); + result0 = Aos::Vector4( spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_XAYB ) ); + result1 = Aos::Vector4( spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_ZCWD ) ); + result2 = Aos::Vector4( spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_XAYB ) ); + result3 = Aos::Vector4( spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_ZCWD ) ); +} + +inline void storeHalfFloats( const Vector4 & vec, vec_ushort8 * twoQuads ) +{ + Aos::Vector4 v0, v1, v2, v3; + vec.get4Aos( v0, v1, v2, v3 ); + twoQuads[0] = _vmath2VfToHalfFloats(v0.get128(), v1.get128()); + twoQuads[1] = _vmath2VfToHalfFloats(v2.get128(), v3.get128()); +} + +inline Vector4 & Vector4::operator =( const Vector4 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + mW = vec.mW; + return *this; +} + +inline Vector4 & Vector4::setXYZ( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + return *this; +} + +inline const Vector3 Vector4::getXYZ( ) const +{ + return Vector3( mX, mY, mZ ); +} + +inline Vector4 & Vector4::setX( vec_float4 _x ) +{ + mX = _x; + return *this; +} + +inline vec_float4 Vector4::getX( ) const +{ + return mX; +} + +inline Vector4 & Vector4::setY( vec_float4 _y ) +{ + mY = _y; + return *this; +} + +inline vec_float4 Vector4::getY( ) const +{ + return mY; +} + +inline Vector4 & Vector4::setZ( vec_float4 _z ) +{ + mZ = _z; + return *this; +} + +inline vec_float4 Vector4::getZ( ) const +{ + return mZ; +} + +inline Vector4 & Vector4::setW( vec_float4 _w ) +{ + mW = _w; + return *this; +} + +inline vec_float4 Vector4::getW( ) const +{ + return mW; +} + +inline Vector4 & Vector4::setElem( int idx, vec_float4 value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline vec_float4 Vector4::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline Vector4::vec_float4_t & Vector4::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline vec_float4 Vector4::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector4 Vector4::operator +( const Vector4 & vec ) const +{ + return Vector4( + spu_add( mX, vec.mX ), + spu_add( mY, vec.mY ), + spu_add( mZ, vec.mZ ), + spu_add( mW, vec.mW ) + ); +} + +inline const Vector4 Vector4::operator -( const Vector4 & vec ) const +{ + return Vector4( + spu_sub( mX, vec.mX ), + spu_sub( mY, vec.mY ), + spu_sub( mZ, vec.mZ ), + spu_sub( mW, vec.mW ) + ); +} + +inline const Vector4 Vector4::operator *( vec_float4 scalar ) const +{ + return Vector4( + spu_mul( mX, scalar ), + spu_mul( mY, scalar ), + spu_mul( mZ, scalar ), + spu_mul( mW, scalar ) + ); +} + +inline Vector4 & Vector4::operator +=( const Vector4 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector4 & Vector4::operator -=( const Vector4 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector4 & Vector4::operator *=( vec_float4 scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector4 Vector4::operator /( vec_float4 scalar ) const +{ + return Vector4( + divf4( mX, scalar ), + divf4( mY, scalar ), + divf4( mZ, scalar ), + divf4( mW, scalar ) + ); +} + +inline Vector4 & Vector4::operator /=( vec_float4 scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector4 Vector4::operator -( ) const +{ + return Vector4( + negatef4( mX ), + negatef4( mY ), + negatef4( mZ ), + negatef4( mW ) + ); +} + +inline const Vector4 operator *( vec_float4 scalar, const Vector4 & vec ) +{ + return vec * scalar; +} + +inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + spu_mul( vec0.getX(), vec1.getX() ), + spu_mul( vec0.getY(), vec1.getY() ), + spu_mul( vec0.getZ(), vec1.getZ() ), + spu_mul( vec0.getW(), vec1.getW() ) + ); +} + +inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + divf4( vec0.getX(), vec1.getX() ), + divf4( vec0.getY(), vec1.getY() ), + divf4( vec0.getZ(), vec1.getZ() ), + divf4( vec0.getW(), vec1.getW() ) + ); +} + +inline const Vector4 recipPerElem( const Vector4 & vec ) +{ + return Vector4( + recipf4( vec.getX() ), + recipf4( vec.getY() ), + recipf4( vec.getZ() ), + recipf4( vec.getW() ) + ); +} + +inline const Vector4 sqrtPerElem( const Vector4 & vec ) +{ + return Vector4( + sqrtf4( vec.getX() ), + sqrtf4( vec.getY() ), + sqrtf4( vec.getZ() ), + sqrtf4( vec.getW() ) + ); +} + +inline const Vector4 rsqrtPerElem( const Vector4 & vec ) +{ + return Vector4( + rsqrtf4( vec.getX() ), + rsqrtf4( vec.getY() ), + rsqrtf4( vec.getZ() ), + rsqrtf4( vec.getW() ) + ); +} + +inline const Vector4 absPerElem( const Vector4 & vec ) +{ + return Vector4( + fabsf4( vec.getX() ), + fabsf4( vec.getY() ), + fabsf4( vec.getZ() ), + fabsf4( vec.getW() ) + ); +} + +inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + copysignf4( vec0.getX(), vec1.getX() ), + copysignf4( vec0.getY(), vec1.getY() ), + copysignf4( vec0.getZ(), vec1.getZ() ), + copysignf4( vec0.getW(), vec1.getW() ) + ); +} + +inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + fmaxf4( vec0.getX(), vec1.getX() ), + fmaxf4( vec0.getY(), vec1.getY() ), + fmaxf4( vec0.getZ(), vec1.getZ() ), + fmaxf4( vec0.getW(), vec1.getW() ) + ); +} + +inline vec_float4 maxElem( const Vector4 & vec ) +{ + vec_float4 result; + result = fmaxf4( vec.getX(), vec.getY() ); + result = fmaxf4( vec.getZ(), result ); + result = fmaxf4( vec.getW(), result ); + return result; +} + +inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + fminf4( vec0.getX(), vec1.getX() ), + fminf4( vec0.getY(), vec1.getY() ), + fminf4( vec0.getZ(), vec1.getZ() ), + fminf4( vec0.getW(), vec1.getW() ) + ); +} + +inline vec_float4 minElem( const Vector4 & vec ) +{ + vec_float4 result; + result = fminf4( vec.getX(), vec.getY() ); + result = fminf4( vec.getZ(), result ); + result = fminf4( vec.getW(), result ); + return result; +} + +inline vec_float4 sum( const Vector4 & vec ) +{ + vec_float4 result; + result = spu_add( vec.getX(), vec.getY() ); + result = spu_add( result, vec.getZ() ); + result = spu_add( result, vec.getW() ); + return result; +} + +inline vec_float4 dot( const Vector4 & vec0, const Vector4 & vec1 ) +{ + vec_float4 result; + result = spu_mul( vec0.getX(), vec1.getX() ); + result = spu_add( result, spu_mul( vec0.getY(), vec1.getY() ) ); + result = spu_add( result, spu_mul( vec0.getZ(), vec1.getZ() ) ); + result = spu_add( result, spu_mul( vec0.getW(), vec1.getW() ) ); + return result; +} + +inline vec_float4 lengthSqr( const Vector4 & vec ) +{ + vec_float4 result; + result = spu_mul( vec.getX(), vec.getX() ); + result = spu_add( result, spu_mul( vec.getY(), vec.getY() ) ); + result = spu_add( result, spu_mul( vec.getZ(), vec.getZ() ) ); + result = spu_add( result, spu_mul( vec.getW(), vec.getW() ) ); + return result; +} + +inline vec_float4 length( const Vector4 & vec ) +{ + return sqrtf4( lengthSqr( vec ) ); +} + +inline const Vector4 normalize( const Vector4 & vec ) +{ + vec_float4 lenSqr, lenInv; + lenSqr = lengthSqr( vec ); + lenInv = rsqrtf4( lenSqr ); + return Vector4( + spu_mul( vec.getX(), lenInv ), + spu_mul( vec.getY(), lenInv ), + spu_mul( vec.getZ(), lenInv ), + spu_mul( vec.getW(), lenInv ) + ); +} + +inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, vec_uint4 select1 ) +{ + return Vector4( + spu_sel( vec0.getX(), vec1.getX(), select1 ), + spu_sel( vec0.getY(), vec1.getY(), select1 ), + spu_sel( vec0.getZ(), vec1.getZ(), select1 ), + spu_sel( vec0.getW(), vec1.getW(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Vector4 & vec ) +{ + Aos::Vector4 vec0, vec1, vec2, vec3; + vec.get4Aos( vec0, vec1, vec2, vec3 ); + printf("slot 0:\n"); + print( vec0 ); + printf("slot 1:\n"); + print( vec1 ); + printf("slot 2:\n"); + print( vec2 ); + printf("slot 3:\n"); + print( vec3 ); +} + +inline void print( const Vector4 & vec, const char * name ) +{ + Aos::Vector4 vec0, vec1, vec2, vec3; + printf( "%s:\n", name ); + vec.get4Aos( vec0, vec1, vec2, vec3 ); + printf("slot 0:\n"); + print( vec0 ); + printf("slot 1:\n"); + print( vec1 ); + printf("slot 2:\n"); + print( vec2 ); + printf("slot 3:\n"); + print( vec3 ); +} + +#endif + +inline Point3::Point3( const Point3 & pnt ) +{ + mX = pnt.mX; + mY = pnt.mY; + mZ = pnt.mZ; +} + +inline Point3::Point3( vec_float4 _x, vec_float4 _y, vec_float4 _z ) +{ + mX = _x; + mY = _y; + mZ = _z; +} + +inline Point3::Point3( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); +} + +inline Point3::Point3( vec_float4 scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; +} + +inline Point3::Point3( Aos::Point3 pnt ) +{ + vec_uchar16 shuffle_xxxx = (vec_uchar16)spu_splats((int)0x00010203); + vec_uchar16 shuffle_yyyy = (vec_uchar16)spu_splats((int)0x04050607); + vec_uchar16 shuffle_zzzz = (vec_uchar16)spu_splats((int)0x08090a0b); + vec_float4 vec128 = pnt.get128(); + mX = spu_shuffle( vec128, vec128, shuffle_xxxx ); + mY = spu_shuffle( vec128, vec128, shuffle_yyyy ); + mZ = spu_shuffle( vec128, vec128, shuffle_zzzz ); +} + +inline Point3::Point3( Aos::Point3 pnt0, Aos::Point3 pnt1, Aos::Point3 pnt2, Aos::Point3 pnt3 ) +{ + vec_float4 tmp0, tmp1, tmp2, tmp3; + tmp0 = spu_shuffle( pnt0.get128(), pnt2.get128(), _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( pnt1.get128(), pnt3.get128(), _VECTORMATH_SHUF_XAYB ); + tmp2 = spu_shuffle( pnt0.get128(), pnt2.get128(), _VECTORMATH_SHUF_ZCWD ); + tmp3 = spu_shuffle( pnt1.get128(), pnt3.get128(), _VECTORMATH_SHUF_ZCWD ); + mX = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_XAYB ); + mY = spu_shuffle( tmp0, tmp1, _VECTORMATH_SHUF_ZCWD ); + mZ = spu_shuffle( tmp2, tmp3, _VECTORMATH_SHUF_XAYB ); +} + +inline const Point3 lerp( vec_float4 t, const Point3 & pnt0, const Point3 & pnt1 ) +{ + return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); +} + +inline void Point3::get4Aos( Aos::Point3 & result0, Aos::Point3 & result1, Aos::Point3 & result2, Aos::Point3 & result3 ) const +{ + vec_float4 tmp0, tmp1; + tmp0 = spu_shuffle( mX, mZ, _VECTORMATH_SHUF_XAYB ); + tmp1 = spu_shuffle( mX, mZ, _VECTORMATH_SHUF_ZCWD ); + result0 = Aos::Point3( spu_shuffle( tmp0, mY, _VECTORMATH_SHUF_XAYB ) ); + result1 = Aos::Point3( spu_shuffle( tmp0, mY, _VECTORMATH_SHUF_ZBW0 ) ); + result2 = Aos::Point3( spu_shuffle( tmp1, mY, _VECTORMATH_SHUF_XCY0 ) ); + result3 = Aos::Point3( spu_shuffle( tmp1, mY, _VECTORMATH_SHUF_ZDW0 ) ); +} + +inline void loadXYZArray( Point3 & vec, const vec_float4 * threeQuads ) +{ + vec_float4 xyxy, yzyz, zxzx, xyzx, yzxy, zxyz; + xyzx = threeQuads[0]; + yzxy = threeQuads[1]; + zxyz = threeQuads[2]; + xyxy = spu_shuffle( xyzx, yzxy, _VECTORMATH_SHUF_XYCD ); + zxzx = spu_shuffle( zxyz, xyzx, _VECTORMATH_SHUF_XYCD ); + yzyz = spu_shuffle( yzxy, zxyz, _VECTORMATH_SHUF_XYCD ); + vec.setX( spu_shuffle( xyxy, zxzx, _VECTORMATH_SHUF_XDZB ) ); + vec.setY( spu_shuffle( xyxy, yzyz, _VECTORMATH_SHUF_YAWC ) ); + vec.setZ( spu_shuffle( zxzx, yzyz, _VECTORMATH_SHUF_ZBXD ) ); +} + +inline void storeXYZArray( const Point3 & vec, vec_float4 * threeQuads ) +{ + vec_float4 xyzx, yzxy, zxyz, xyxy, zxzx, yzyz; + xyxy = spu_shuffle( vec.getX(), vec.getY(), _VECTORMATH_SHUF_XAZC ); + zxzx = spu_shuffle( vec.getZ(), vec.getX(), _VECTORMATH_SHUF_ZDXB ); + yzyz = spu_shuffle( vec.getY(), vec.getZ(), _VECTORMATH_SHUF_YBWD ); + xyzx = spu_shuffle( xyxy, zxzx, _VECTORMATH_SHUF_XYCD ); + yzxy = spu_shuffle( yzyz, xyxy, _VECTORMATH_SHUF_XYCD ); + zxyz = spu_shuffle( zxzx, yzyz, _VECTORMATH_SHUF_XYCD ); + threeQuads[0] = xyzx; + threeQuads[1] = yzxy; + threeQuads[2] = zxyz; +} + +inline void storeHalfFloats( const Point3 & pnt0, const Point3 & pnt1, vec_ushort8 * threeQuads ) +{ + vec_float4 xyz0[3]; + vec_float4 xyz1[3]; + storeXYZArray( pnt0, xyz0 ); + storeXYZArray( pnt1, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +} + +inline Point3 & Point3::operator =( const Point3 & pnt ) +{ + mX = pnt.mX; + mY = pnt.mY; + mZ = pnt.mZ; + return *this; +} + +inline Point3 & Point3::setX( vec_float4 _x ) +{ + mX = _x; + return *this; +} + +inline vec_float4 Point3::getX( ) const +{ + return mX; +} + +inline Point3 & Point3::setY( vec_float4 _y ) +{ + mY = _y; + return *this; +} + +inline vec_float4 Point3::getY( ) const +{ + return mY; +} + +inline Point3 & Point3::setZ( vec_float4 _z ) +{ + mZ = _z; + return *this; +} + +inline vec_float4 Point3::getZ( ) const +{ + return mZ; +} + +inline Point3 & Point3::setElem( int idx, vec_float4 value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline vec_float4 Point3::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline Point3::vec_float4_t & Point3::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline vec_float4 Point3::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector3 Point3::operator -( const Point3 & pnt ) const +{ + return Vector3( + spu_sub( mX, pnt.mX ), + spu_sub( mY, pnt.mY ), + spu_sub( mZ, pnt.mZ ) + ); +} + +inline const Point3 Point3::operator +( const Vector3 & vec ) const +{ + return Point3( + spu_add( mX, vec.getX() ), + spu_add( mY, vec.getY() ), + spu_add( mZ, vec.getZ() ) + ); +} + +inline const Point3 Point3::operator -( const Vector3 & vec ) const +{ + return Point3( + spu_sub( mX, vec.getX() ), + spu_sub( mY, vec.getY() ), + spu_sub( mZ, vec.getZ() ) + ); +} + +inline Point3 & Point3::operator +=( const Vector3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Point3 & Point3::operator -=( const Vector3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + spu_mul( pnt0.getX(), pnt1.getX() ), + spu_mul( pnt0.getY(), pnt1.getY() ), + spu_mul( pnt0.getZ(), pnt1.getZ() ) + ); +} + +inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + divf4( pnt0.getX(), pnt1.getX() ), + divf4( pnt0.getY(), pnt1.getY() ), + divf4( pnt0.getZ(), pnt1.getZ() ) + ); +} + +inline const Point3 recipPerElem( const Point3 & pnt ) +{ + return Point3( + recipf4( pnt.getX() ), + recipf4( pnt.getY() ), + recipf4( pnt.getZ() ) + ); +} + +inline const Point3 sqrtPerElem( const Point3 & pnt ) +{ + return Point3( + sqrtf4( pnt.getX() ), + sqrtf4( pnt.getY() ), + sqrtf4( pnt.getZ() ) + ); +} + +inline const Point3 rsqrtPerElem( const Point3 & pnt ) +{ + return Point3( + rsqrtf4( pnt.getX() ), + rsqrtf4( pnt.getY() ), + rsqrtf4( pnt.getZ() ) + ); +} + +inline const Point3 absPerElem( const Point3 & pnt ) +{ + return Point3( + fabsf4( pnt.getX() ), + fabsf4( pnt.getY() ), + fabsf4( pnt.getZ() ) + ); +} + +inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + copysignf4( pnt0.getX(), pnt1.getX() ), + copysignf4( pnt0.getY(), pnt1.getY() ), + copysignf4( pnt0.getZ(), pnt1.getZ() ) + ); +} + +inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + fmaxf4( pnt0.getX(), pnt1.getX() ), + fmaxf4( pnt0.getY(), pnt1.getY() ), + fmaxf4( pnt0.getZ(), pnt1.getZ() ) + ); +} + +inline vec_float4 maxElem( const Point3 & pnt ) +{ + vec_float4 result; + result = fmaxf4( pnt.getX(), pnt.getY() ); + result = fmaxf4( pnt.getZ(), result ); + return result; +} + +inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + fminf4( pnt0.getX(), pnt1.getX() ), + fminf4( pnt0.getY(), pnt1.getY() ), + fminf4( pnt0.getZ(), pnt1.getZ() ) + ); +} + +inline vec_float4 minElem( const Point3 & pnt ) +{ + vec_float4 result; + result = fminf4( pnt.getX(), pnt.getY() ); + result = fminf4( pnt.getZ(), result ); + return result; +} + +inline vec_float4 sum( const Point3 & pnt ) +{ + vec_float4 result; + result = spu_add( pnt.getX(), pnt.getY() ); + result = spu_add( result, pnt.getZ() ); + return result; +} + +inline const Point3 scale( const Point3 & pnt, vec_float4 scaleVal ) +{ + return mulPerElem( pnt, Point3( scaleVal ) ); +} + +inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ) +{ + return mulPerElem( pnt, Point3( scaleVec ) ); +} + +inline vec_float4 projection( const Point3 & pnt, const Vector3 & unitVec ) +{ + vec_float4 result; + result = spu_mul( pnt.getX(), unitVec.getX() ); + result = spu_add( result, spu_mul( pnt.getY(), unitVec.getY() ) ); + result = spu_add( result, spu_mul( pnt.getZ(), unitVec.getZ() ) ); + return result; +} + +inline vec_float4 distSqrFromOrigin( const Point3 & pnt ) +{ + return lengthSqr( Vector3( pnt ) ); +} + +inline vec_float4 distFromOrigin( const Point3 & pnt ) +{ + return length( Vector3( pnt ) ); +} + +inline vec_float4 distSqr( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return lengthSqr( ( pnt1 - pnt0 ) ); +} + +inline vec_float4 dist( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return length( ( pnt1 - pnt0 ) ); +} + +inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, vec_uint4 select1 ) +{ + return Point3( + spu_sel( pnt0.getX(), pnt1.getX(), select1 ), + spu_sel( pnt0.getY(), pnt1.getY(), select1 ), + spu_sel( pnt0.getZ(), pnt1.getZ(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Point3 & pnt ) +{ + Aos::Point3 vec0, vec1, vec2, vec3; + pnt.get4Aos( vec0, vec1, vec2, vec3 ); + printf("slot 0:\n"); + print( vec0 ); + printf("slot 1:\n"); + print( vec1 ); + printf("slot 2:\n"); + print( vec2 ); + printf("slot 3:\n"); + print( vec3 ); +} + +inline void print( const Point3 & pnt, const char * name ) +{ + Aos::Point3 vec0, vec1, vec2, vec3; + printf( "%s:\n", name ); + pnt.get4Aos( vec0, vec1, vec2, vec3 ); + printf("slot 0:\n"); + print( vec0 ); + printf("slot 1:\n"); + print( vec1 ); + printf("slot 2:\n"); + print( vec2 ); + printf("slot 3:\n"); + print( vec3 ); +} + +#endif + +} // namespace Soa +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/cpp/vecidx_aos.h b/Extras/vectormathlibrary/include/vectormath/spu/cpp/vecidx_aos.h new file mode 100644 index 0000000..f530915 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/cpp/vecidx_aos.h @@ -0,0 +1,64 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VECIDX_AOS_H +#define _VECTORMATH_VECIDX_AOS_H + +#include + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// VecIdx +// Used in setting elements of Vector3, Vector4, Point3, or Quat with the +// subscripting operator. +// + +class VecIdx +{ +private: + typedef vec_float4 vec_float4_t; + vec_float4_t &ref __attribute__ ((aligned(16))); + int i __attribute__ ((aligned(16))); +public: + inline VecIdx( vec_float4& vec, int idx ): ref(vec) { i = idx; } + inline operator float() const; + inline float operator =( float scalar ); + inline float operator =( const VecIdx& scalar ); + inline float operator *=( float scalar ); + inline float operator /=( float scalar ); + inline float operator +=( float scalar ); + inline float operator -=( float scalar ); +}; + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/cpp/vectormath_aos.h b/Extras/vectormathlibrary/include/vectormath/spu/cpp/vectormath_aos.h new file mode 100644 index 0000000..f876c53 --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/cpp/vectormath_aos.h @@ -0,0 +1,1851 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_AOS_CPP_SPU_H +#define _VECTORMATH_AOS_CPP_SPU_H + +#include +#include +#include "floatInVec.h" +#include "boolInVec.h" +#include "vecidx_aos.h" +#include + +#ifdef _VECTORMATH_DEBUG +#endif + +namespace Vectormath { + +namespace Aos { + +//----------------------------------------------------------------------------- +// Forward Declarations +// + +class Vector3; +class Vector4; +class Point3; +class Quat; +class Matrix3; +class Matrix4; +class Transform3; + +// A 3-D vector in array-of-structures format +// +class Vector3 +{ + vec_float4 mVec128; + +public: + // Default constructor; does no initialization + // + inline Vector3( ) { }; + + // Construct a 3-D vector from x, y, and z elements + // + inline Vector3( float x, float y, float z ); + + // Copy elements from a 3-D point into a 3-D vector + // + explicit inline Vector3( Point3 pnt ); + + // Set all elements of a 3-D vector to the same scalar value + // + explicit inline Vector3( float scalar ); + + // Set vector float data in a 3-D vector + // + explicit inline Vector3( vec_float4 vf4 ); + + // Get vector float data from a 3-D vector + // + inline vec_float4 get128( ) const; + + // Assign one 3-D vector to another + // + inline Vector3 & operator =( Vector3 vec ); + + // Set the x element of a 3-D vector + // + inline Vector3 & setX( float x ); + + // Set the y element of a 3-D vector + // + inline Vector3 & setY( float y ); + + // Set the z element of a 3-D vector + // + inline Vector3 & setZ( float z ); + + // Get the x element of a 3-D vector + // + inline float getX( ) const; + + // Get the y element of a 3-D vector + // + inline float getY( ) const; + + // Get the z element of a 3-D vector + // + inline float getZ( ) const; + + // Set an x, y, or z element of a 3-D vector by index + // + inline Vector3 & setElem( int idx, float value ); + + // Get an x, y, or z element of a 3-D vector by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two 3-D vectors + // + inline const Vector3 operator +( Vector3 vec ) const; + + // Subtract a 3-D vector from another 3-D vector + // + inline const Vector3 operator -( Vector3 vec ) const; + + // Add a 3-D vector to a 3-D point + // + inline const Point3 operator +( Point3 pnt ) const; + + // Multiply a 3-D vector by a scalar + // + inline const Vector3 operator *( float scalar ) const; + + // Divide a 3-D vector by a scalar + // + inline const Vector3 operator /( float scalar ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Vector3 & operator +=( Vector3 vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Vector3 & operator -=( Vector3 vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector3 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector3 & operator /=( float scalar ); + + // Negate all elements of a 3-D vector + // + inline const Vector3 operator -( ) const; + + // Construct x axis + // + static inline const Vector3 xAxis( ); + + // Construct y axis + // + static inline const Vector3 yAxis( ); + + // Construct z axis + // + static inline const Vector3 zAxis( ); + +}; + +// Multiply a 3-D vector by a scalar +// +inline const Vector3 operator *( float scalar, Vector3 vec ); + +// Multiply two 3-D vectors per element +// +inline const Vector3 mulPerElem( Vector3 vec0, Vector3 vec1 ); + +// Divide two 3-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector3 divPerElem( Vector3 vec0, Vector3 vec1 ); + +// Compute the reciprocal of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector3 recipPerElem( Vector3 vec ); + +// Compute the square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector3 sqrtPerElem( Vector3 vec ); + +// Compute the reciprocal square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector3 rsqrtPerElem( Vector3 vec ); + +// Compute the absolute value of a 3-D vector per element +// +inline const Vector3 absPerElem( Vector3 vec ); + +// Copy sign from one 3-D vector to another, per element +// +inline const Vector3 copySignPerElem( Vector3 vec0, Vector3 vec1 ); + +// Maximum of two 3-D vectors per element +// +inline const Vector3 maxPerElem( Vector3 vec0, Vector3 vec1 ); + +// Minimum of two 3-D vectors per element +// +inline const Vector3 minPerElem( Vector3 vec0, Vector3 vec1 ); + +// Maximum element of a 3-D vector +// +inline float maxElem( Vector3 vec ); + +// Minimum element of a 3-D vector +// +inline float minElem( Vector3 vec ); + +// Compute the sum of all elements of a 3-D vector +// +inline float sum( Vector3 vec ); + +// Compute the dot product of two 3-D vectors +// +inline float dot( Vector3 vec0, Vector3 vec1 ); + +// Compute the square of the length of a 3-D vector +// +inline float lengthSqr( Vector3 vec ); + +// Compute the length of a 3-D vector +// +inline float length( Vector3 vec ); + +// Normalize a 3-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector3 normalize( Vector3 vec ); + +// Compute cross product of two 3-D vectors +// +inline const Vector3 cross( Vector3 vec0, Vector3 vec1 ); + +// Outer product of two 3-D vectors +// +inline const Matrix3 outer( Vector3 vec0, Vector3 vec1 ); + +// Pre-multiply a row vector by a 3x3 matrix +// NOTE: +// Slower than column post-multiply. +// +inline const Vector3 rowMul( Vector3 vec, const Matrix3 & mat ); + +// Cross-product matrix of a 3-D vector +// +inline const Matrix3 crossMatrix( Vector3 vec ); + +// Create cross-product matrix and multiply +// NOTE: +// Faster than separately creating a cross-product matrix and multiplying. +// +inline const Matrix3 crossMatrixMul( Vector3 vec, const Matrix3 & mat ); + +// Linear interpolation between two 3-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector3 lerp( float t, Vector3 vec0, Vector3 vec1 ); + +// Spherical linear interpolation between two 3-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector3 slerp( float t, Vector3 unitVec0, Vector3 unitVec1 ); + +// Conditionally select between two 3-D vectors +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Vector3 select( Vector3 vec0, Vector3 vec1, bool select1 ); + +// Store x, y, and z elements of a 3-D vector in the first three words of a quadword. +// The value of the fourth word (the word with the highest address) remains unchanged +// +inline void storeXYZ( Vector3 vec, vec_float4 * quad ); + +// Load four three-float 3-D vectors, stored in three quadwords +// +inline void loadXYZArray( Vector3 & vec0, Vector3 & vec1, Vector3 & vec2, Vector3 & vec3, const vec_float4 * threeQuads ); + +// Store four 3-D vectors in three quadwords +// +inline void storeXYZArray( Vector3 vec0, Vector3 vec1, Vector3 vec2, Vector3 vec3, vec_float4 * threeQuads ); + +// Store eight 3-D vectors as half-floats +// +inline void storeHalfFloats( Vector3 vec0, Vector3 vec1, Vector3 vec2, Vector3 vec3, Vector3 vec4, Vector3 vec5, Vector3 vec6, Vector3 vec7, vec_ushort8 * threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( Vector3 vec ); + +// Print a 3-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( Vector3 vec, const char * name ); + +#endif + +// A 4-D vector in array-of-structures format +// +class Vector4 +{ + vec_float4 mVec128; + +public: + // Default constructor; does no initialization + // + inline Vector4( ) { }; + + // Construct a 4-D vector from x, y, z, and w elements + // + inline Vector4( float x, float y, float z, float w ); + + // Construct a 4-D vector from a 3-D vector and a scalar + // + inline Vector4( Vector3 xyz, float w ); + + // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + // + explicit inline Vector4( Vector3 vec ); + + // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + // + explicit inline Vector4( Point3 pnt ); + + // Copy elements from a quaternion into a 4-D vector + // + explicit inline Vector4( Quat quat ); + + // Set all elements of a 4-D vector to the same scalar value + // + explicit inline Vector4( float scalar ); + + // Set vector float data in a 4-D vector + // + explicit inline Vector4( vec_float4 vf4 ); + + // Get vector float data from a 4-D vector + // + inline vec_float4 get128( ) const; + + // Assign one 4-D vector to another + // + inline Vector4 & operator =( Vector4 vec ); + + // Set the x, y, and z elements of a 4-D vector + // NOTE: + // This function does not change the w element. + // + inline Vector4 & setXYZ( Vector3 vec ); + + // Get the x, y, and z elements of a 4-D vector + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a 4-D vector + // + inline Vector4 & setX( float x ); + + // Set the y element of a 4-D vector + // + inline Vector4 & setY( float y ); + + // Set the z element of a 4-D vector + // + inline Vector4 & setZ( float z ); + + // Set the w element of a 4-D vector + // + inline Vector4 & setW( float w ); + + // Get the x element of a 4-D vector + // + inline float getX( ) const; + + // Get the y element of a 4-D vector + // + inline float getY( ) const; + + // Get the z element of a 4-D vector + // + inline float getZ( ) const; + + // Get the w element of a 4-D vector + // + inline float getW( ) const; + + // Set an x, y, z, or w element of a 4-D vector by index + // + inline Vector4 & setElem( int idx, float value ); + + // Get an x, y, z, or w element of a 4-D vector by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two 4-D vectors + // + inline const Vector4 operator +( Vector4 vec ) const; + + // Subtract a 4-D vector from another 4-D vector + // + inline const Vector4 operator -( Vector4 vec ) const; + + // Multiply a 4-D vector by a scalar + // + inline const Vector4 operator *( float scalar ) const; + + // Divide a 4-D vector by a scalar + // + inline const Vector4 operator /( float scalar ) const; + + // Perform compound assignment and addition with a 4-D vector + // + inline Vector4 & operator +=( Vector4 vec ); + + // Perform compound assignment and subtraction by a 4-D vector + // + inline Vector4 & operator -=( Vector4 vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector4 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector4 & operator /=( float scalar ); + + // Negate all elements of a 4-D vector + // + inline const Vector4 operator -( ) const; + + // Construct x axis + // + static inline const Vector4 xAxis( ); + + // Construct y axis + // + static inline const Vector4 yAxis( ); + + // Construct z axis + // + static inline const Vector4 zAxis( ); + + // Construct w axis + // + static inline const Vector4 wAxis( ); + +}; + +// Multiply a 4-D vector by a scalar +// +inline const Vector4 operator *( float scalar, Vector4 vec ); + +// Multiply two 4-D vectors per element +// +inline const Vector4 mulPerElem( Vector4 vec0, Vector4 vec1 ); + +// Divide two 4-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector4 divPerElem( Vector4 vec0, Vector4 vec1 ); + +// Compute the reciprocal of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector4 recipPerElem( Vector4 vec ); + +// Compute the square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector4 sqrtPerElem( Vector4 vec ); + +// Compute the reciprocal square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector4 rsqrtPerElem( Vector4 vec ); + +// Compute the absolute value of a 4-D vector per element +// +inline const Vector4 absPerElem( Vector4 vec ); + +// Copy sign from one 4-D vector to another, per element +// +inline const Vector4 copySignPerElem( Vector4 vec0, Vector4 vec1 ); + +// Maximum of two 4-D vectors per element +// +inline const Vector4 maxPerElem( Vector4 vec0, Vector4 vec1 ); + +// Minimum of two 4-D vectors per element +// +inline const Vector4 minPerElem( Vector4 vec0, Vector4 vec1 ); + +// Maximum element of a 4-D vector +// +inline float maxElem( Vector4 vec ); + +// Minimum element of a 4-D vector +// +inline float minElem( Vector4 vec ); + +// Compute the sum of all elements of a 4-D vector +// +inline float sum( Vector4 vec ); + +// Compute the dot product of two 4-D vectors +// +inline float dot( Vector4 vec0, Vector4 vec1 ); + +// Compute the square of the length of a 4-D vector +// +inline float lengthSqr( Vector4 vec ); + +// Compute the length of a 4-D vector +// +inline float length( Vector4 vec ); + +// Normalize a 4-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector4 normalize( Vector4 vec ); + +// Outer product of two 4-D vectors +// +inline const Matrix4 outer( Vector4 vec0, Vector4 vec1 ); + +// Linear interpolation between two 4-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector4 lerp( float t, Vector4 vec0, Vector4 vec1 ); + +// Spherical linear interpolation between two 4-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector4 slerp( float t, Vector4 unitVec0, Vector4 unitVec1 ); + +// Conditionally select between two 4-D vectors +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Vector4 select( Vector4 vec0, Vector4 vec1, bool select1 ); + +// Store four 4-D vectors as half-floats +// +inline void storeHalfFloats( Vector4 vec0, Vector4 vec1, Vector4 vec2, Vector4 vec3, vec_ushort8 * twoQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( Vector4 vec ); + +// Print a 4-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( Vector4 vec, const char * name ); + +#endif + +// A 3-D point in array-of-structures format +// +class Point3 +{ + vec_float4 mVec128; + +public: + // Default constructor; does no initialization + // + inline Point3( ) { }; + + // Construct a 3-D point from x, y, and z elements + // + inline Point3( float x, float y, float z ); + + // Copy elements from a 3-D vector into a 3-D point + // + explicit inline Point3( Vector3 vec ); + + // Set all elements of a 3-D point to the same scalar value + // + explicit inline Point3( float scalar ); + + // Set vector float data in a 3-D point + // + explicit inline Point3( vec_float4 vf4 ); + + // Get vector float data from a 3-D point + // + inline vec_float4 get128( ) const; + + // Assign one 3-D point to another + // + inline Point3 & operator =( Point3 pnt ); + + // Set the x element of a 3-D point + // + inline Point3 & setX( float x ); + + // Set the y element of a 3-D point + // + inline Point3 & setY( float y ); + + // Set the z element of a 3-D point + // + inline Point3 & setZ( float z ); + + // Get the x element of a 3-D point + // + inline float getX( ) const; + + // Get the y element of a 3-D point + // + inline float getY( ) const; + + // Get the z element of a 3-D point + // + inline float getZ( ) const; + + // Set an x, y, or z element of a 3-D point by index + // + inline Point3 & setElem( int idx, float value ); + + // Get an x, y, or z element of a 3-D point by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Subtract a 3-D point from another 3-D point + // + inline const Vector3 operator -( Point3 pnt ) const; + + // Add a 3-D point to a 3-D vector + // + inline const Point3 operator +( Vector3 vec ) const; + + // Subtract a 3-D vector from a 3-D point + // + inline const Point3 operator -( Vector3 vec ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Point3 & operator +=( Vector3 vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Point3 & operator -=( Vector3 vec ); + +}; + +// Multiply two 3-D points per element +// +inline const Point3 mulPerElem( Point3 pnt0, Point3 pnt1 ); + +// Divide two 3-D points per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Point3 divPerElem( Point3 pnt0, Point3 pnt1 ); + +// Compute the reciprocal of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Point3 recipPerElem( Point3 pnt ); + +// Compute the square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Point3 sqrtPerElem( Point3 pnt ); + +// Compute the reciprocal square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Point3 rsqrtPerElem( Point3 pnt ); + +// Compute the absolute value of a 3-D point per element +// +inline const Point3 absPerElem( Point3 pnt ); + +// Copy sign from one 3-D point to another, per element +// +inline const Point3 copySignPerElem( Point3 pnt0, Point3 pnt1 ); + +// Maximum of two 3-D points per element +// +inline const Point3 maxPerElem( Point3 pnt0, Point3 pnt1 ); + +// Minimum of two 3-D points per element +// +inline const Point3 minPerElem( Point3 pnt0, Point3 pnt1 ); + +// Maximum element of a 3-D point +// +inline float maxElem( Point3 pnt ); + +// Minimum element of a 3-D point +// +inline float minElem( Point3 pnt ); + +// Compute the sum of all elements of a 3-D point +// +inline float sum( Point3 pnt ); + +// Apply uniform scale to a 3-D point +// +inline const Point3 scale( Point3 pnt, float scaleVal ); + +// Apply non-uniform scale to a 3-D point +// +inline const Point3 scale( Point3 pnt, Vector3 scaleVec ); + +// Scalar projection of a 3-D point on a unit-length 3-D vector +// +inline float projection( Point3 pnt, Vector3 unitVec ); + +// Compute the square of the distance of a 3-D point from the coordinate-system origin +// +inline float distSqrFromOrigin( Point3 pnt ); + +// Compute the distance of a 3-D point from the coordinate-system origin +// +inline float distFromOrigin( Point3 pnt ); + +// Compute the square of the distance between two 3-D points +// +inline float distSqr( Point3 pnt0, Point3 pnt1 ); + +// Compute the distance between two 3-D points +// +inline float dist( Point3 pnt0, Point3 pnt1 ); + +// Linear interpolation between two 3-D points +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Point3 lerp( float t, Point3 pnt0, Point3 pnt1 ); + +// Conditionally select between two 3-D points +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Point3 select( Point3 pnt0, Point3 pnt1, bool select1 ); + +// Store x, y, and z elements of a 3-D point in the first three words of a quadword. +// The value of the fourth word (the word with the highest address) remains unchanged +// +inline void storeXYZ( Point3 pnt, vec_float4 * quad ); + +// Load four three-float 3-D points, stored in three quadwords +// +inline void loadXYZArray( Point3 & pnt0, Point3 & pnt1, Point3 & pnt2, Point3 & pnt3, const vec_float4 * threeQuads ); + +// Store four 3-D points in three quadwords +// +inline void storeXYZArray( Point3 pnt0, Point3 pnt1, Point3 pnt2, Point3 pnt3, vec_float4 * threeQuads ); + +// Store eight 3-D points as half-floats +// +inline void storeHalfFloats( Point3 pnt0, Point3 pnt1, Point3 pnt2, Point3 pnt3, Point3 pnt4, Point3 pnt5, Point3 pnt6, Point3 pnt7, vec_ushort8 * threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D point +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( Point3 pnt ); + +// Print a 3-D point and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( Point3 pnt, const char * name ); + +#endif + +// A quaternion in array-of-structures format +// +class Quat +{ + vec_float4 mVec128; + +public: + // Default constructor; does no initialization + // + inline Quat( ) { }; + + // Construct a quaternion from x, y, z, and w elements + // + inline Quat( float x, float y, float z, float w ); + + // Construct a quaternion from a 3-D vector and a scalar + // + inline Quat( Vector3 xyz, float w ); + + // Copy elements from a 4-D vector into a quaternion + // + explicit inline Quat( Vector4 vec ); + + // Convert a rotation matrix to a unit-length quaternion + // + explicit inline Quat( const Matrix3 & rotMat ); + + // Set all elements of a quaternion to the same scalar value + // + explicit inline Quat( float scalar ); + + // Set vector float data in a quaternion + // + explicit inline Quat( vec_float4 vf4 ); + + // Get vector float data from a quaternion + // + inline vec_float4 get128( ) const; + + // Assign one quaternion to another + // + inline Quat & operator =( Quat quat ); + + // Set the x, y, and z elements of a quaternion + // NOTE: + // This function does not change the w element. + // + inline Quat & setXYZ( Vector3 vec ); + + // Get the x, y, and z elements of a quaternion + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a quaternion + // + inline Quat & setX( float x ); + + // Set the y element of a quaternion + // + inline Quat & setY( float y ); + + // Set the z element of a quaternion + // + inline Quat & setZ( float z ); + + // Set the w element of a quaternion + // + inline Quat & setW( float w ); + + // Get the x element of a quaternion + // + inline float getX( ) const; + + // Get the y element of a quaternion + // + inline float getY( ) const; + + // Get the z element of a quaternion + // + inline float getZ( ) const; + + // Get the w element of a quaternion + // + inline float getW( ) const; + + // Set an x, y, z, or w element of a quaternion by index + // + inline Quat & setElem( int idx, float value ); + + // Get an x, y, z, or w element of a quaternion by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two quaternions + // + inline const Quat operator +( Quat quat ) const; + + // Subtract a quaternion from another quaternion + // + inline const Quat operator -( Quat quat ) const; + + // Multiply two quaternions + // + inline const Quat operator *( Quat quat ) const; + + // Multiply a quaternion by a scalar + // + inline const Quat operator *( float scalar ) const; + + // Divide a quaternion by a scalar + // + inline const Quat operator /( float scalar ) const; + + // Perform compound assignment and addition with a quaternion + // + inline Quat & operator +=( Quat quat ); + + // Perform compound assignment and subtraction by a quaternion + // + inline Quat & operator -=( Quat quat ); + + // Perform compound assignment and multiplication by a quaternion + // + inline Quat & operator *=( Quat quat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Quat & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Quat & operator /=( float scalar ); + + // Negate all elements of a quaternion + // + inline const Quat operator -( ) const; + + // Construct an identity quaternion + // + static inline const Quat identity( ); + + // Construct a quaternion to rotate between two unit-length 3-D vectors + // NOTE: + // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + // + static inline const Quat rotation( Vector3 unitVec0, Vector3 unitVec1 ); + + // Construct a quaternion to rotate around a unit-length 3-D vector + // + static inline const Quat rotation( float radians, Vector3 unitVec ); + + // Construct a quaternion to rotate around the x axis + // + static inline const Quat rotationX( float radians ); + + // Construct a quaternion to rotate around the y axis + // + static inline const Quat rotationY( float radians ); + + // Construct a quaternion to rotate around the z axis + // + static inline const Quat rotationZ( float radians ); + +}; + +// Multiply a quaternion by a scalar +// +inline const Quat operator *( float scalar, Quat quat ); + +// Compute the conjugate of a quaternion +// +inline const Quat conj( Quat quat ); + +// Use a unit-length quaternion to rotate a 3-D vector +// +inline const Vector3 rotate( Quat unitQuat, Vector3 vec ); + +// Compute the dot product of two quaternions +// +inline float dot( Quat quat0, Quat quat1 ); + +// Compute the norm of a quaternion +// +inline float norm( Quat quat ); + +// Compute the length of a quaternion +// +inline float length( Quat quat ); + +// Normalize a quaternion +// NOTE: +// The result is unpredictable when all elements of quat are at or near zero. +// +inline const Quat normalize( Quat quat ); + +// Linear interpolation between two quaternions +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Quat lerp( float t, Quat quat0, Quat quat1 ); + +// Spherical linear interpolation between two quaternions +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +inline const Quat slerp( float t, Quat unitQuat0, Quat unitQuat1 ); + +// Spherical quadrangle interpolation +// +inline const Quat squad( float t, Quat unitQuat0, Quat unitQuat1, Quat unitQuat2, Quat unitQuat3 ); + +// Conditionally select between two quaternions +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Quat select( Quat quat0, Quat quat1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a quaternion +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( Quat quat ); + +// Print a quaternion and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( Quat quat, const char * name ); + +#endif + +// A 3x3 matrix in array-of-structures format +// +class Matrix3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + +public: + // Default constructor; does no initialization + // + inline Matrix3( ) { }; + + // Copy a 3x3 matrix + // + inline Matrix3( const Matrix3 & mat ); + + // Construct a 3x3 matrix containing the specified columns + // + inline Matrix3( Vector3 col0, Vector3 col1, Vector3 col2 ); + + // Construct a 3x3 rotation matrix from a unit-length quaternion + // + explicit inline Matrix3( Quat unitQuat ); + + // Set all elements of a 3x3 matrix to the same scalar value + // + explicit inline Matrix3( float scalar ); + + // Assign one 3x3 matrix to another + // + inline Matrix3 & operator =( const Matrix3 & mat ); + + // Set column 0 of a 3x3 matrix + // + inline Matrix3 & setCol0( Vector3 col0 ); + + // Set column 1 of a 3x3 matrix + // + inline Matrix3 & setCol1( Vector3 col1 ); + + // Set column 2 of a 3x3 matrix + // + inline Matrix3 & setCol2( Vector3 col2 ); + + // Get column 0 of a 3x3 matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x3 matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x3 matrix + // + inline const Vector3 getCol2( ) const; + + // Set the column of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setCol( int col, Vector3 vec ); + + // Set the row of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setRow( int row, Vector3 vec ); + + // Get the column of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x3 matrix referred to by column and row indices + // + inline Matrix3 & setElem( int col, int row, float val ); + + // Get the element of a 3x3 matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Add two 3x3 matrices + // + inline const Matrix3 operator +( const Matrix3 & mat ) const; + + // Subtract a 3x3 matrix from another 3x3 matrix + // + inline const Matrix3 operator -( const Matrix3 & mat ) const; + + // Negate all elements of a 3x3 matrix + // + inline const Matrix3 operator -( ) const; + + // Multiply a 3x3 matrix by a scalar + // + inline const Matrix3 operator *( float scalar ) const; + + // Multiply a 3x3 matrix by a 3-D vector + // + inline const Vector3 operator *( Vector3 vec ) const; + + // Multiply two 3x3 matrices + // + inline const Matrix3 operator *( const Matrix3 & mat ) const; + + // Perform compound assignment and addition with a 3x3 matrix + // + inline Matrix3 & operator +=( const Matrix3 & mat ); + + // Perform compound assignment and subtraction by a 3x3 matrix + // + inline Matrix3 & operator -=( const Matrix3 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix3 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a 3x3 matrix + // + inline Matrix3 & operator *=( const Matrix3 & mat ); + + // Construct an identity 3x3 matrix + // + static inline const Matrix3 identity( ); + + // Construct a 3x3 matrix to rotate around the x axis + // + static inline const Matrix3 rotationX( float radians ); + + // Construct a 3x3 matrix to rotate around the y axis + // + static inline const Matrix3 rotationY( float radians ); + + // Construct a 3x3 matrix to rotate around the z axis + // + static inline const Matrix3 rotationZ( float radians ); + + // Construct a 3x3 matrix to rotate around the x, y, and z axes + // + static inline const Matrix3 rotationZYX( Vector3 radiansXYZ ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix3 rotation( float radians, Vector3 unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix3 rotation( Quat unitQuat ); + + // Construct a 3x3 matrix to perform scaling + // + static inline const Matrix3 scale( Vector3 scaleVec ); + +}; +// Multiply a 3x3 matrix by a scalar +// +inline const Matrix3 operator *( float scalar, const Matrix3 & mat ); + +// Append (post-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 appendScale( const Matrix3 & mat, Vector3 scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 prependScale( Vector3 scaleVec, const Matrix3 & mat ); + +// Multiply two 3x3 matrices per element +// +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); + +// Compute the absolute value of a 3x3 matrix per element +// +inline const Matrix3 absPerElem( const Matrix3 & mat ); + +// Transpose of a 3x3 matrix +// +inline const Matrix3 transpose( const Matrix3 & mat ); + +// Compute the inverse of a 3x3 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix3 inverse( const Matrix3 & mat ); + +// Determinant of a 3x3 matrix +// +inline float determinant( const Matrix3 & mat ); + +// Conditionally select between two 3x3 matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x3 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat ); + +// Print a 3x3 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat, const char * name ); + +#endif + +// A 4x4 matrix in array-of-structures format +// +class Matrix4 +{ + Vector4 mCol0; + Vector4 mCol1; + Vector4 mCol2; + Vector4 mCol3; + +public: + // Default constructor; does no initialization + // + inline Matrix4( ) { }; + + // Copy a 4x4 matrix + // + inline Matrix4( const Matrix4 & mat ); + + // Construct a 4x4 matrix containing the specified columns + // + inline Matrix4( Vector4 col0, Vector4 col1, Vector4 col2, Vector4 col3 ); + + // Construct a 4x4 matrix from a 3x4 transformation matrix + // + explicit inline Matrix4( const Transform3 & mat ); + + // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + // + inline Matrix4( const Matrix3 & mat, Vector3 translateVec ); + + // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + // + inline Matrix4( Quat unitQuat, Vector3 translateVec ); + + // Set all elements of a 4x4 matrix to the same scalar value + // + explicit inline Matrix4( float scalar ); + + // Assign one 4x4 matrix to another + // + inline Matrix4 & operator =( const Matrix4 & mat ); + + // Set the upper-left 3x3 submatrix + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 4x4 matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setTranslation( Vector3 translateVec ); + + // Get the translation component of a 4x4 matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 4x4 matrix + // + inline Matrix4 & setCol0( Vector4 col0 ); + + // Set column 1 of a 4x4 matrix + // + inline Matrix4 & setCol1( Vector4 col1 ); + + // Set column 2 of a 4x4 matrix + // + inline Matrix4 & setCol2( Vector4 col2 ); + + // Set column 3 of a 4x4 matrix + // + inline Matrix4 & setCol3( Vector4 col3 ); + + // Get column 0 of a 4x4 matrix + // + inline const Vector4 getCol0( ) const; + + // Get column 1 of a 4x4 matrix + // + inline const Vector4 getCol1( ) const; + + // Get column 2 of a 4x4 matrix + // + inline const Vector4 getCol2( ) const; + + // Get column 3 of a 4x4 matrix + // + inline const Vector4 getCol3( ) const; + + // Set the column of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setCol( int col, Vector4 vec ); + + // Set the row of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setRow( int row, Vector4 vec ); + + // Get the column of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getCol( int col ) const; + + // Get the row of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector4 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector4 operator []( int col ) const; + + // Set the element of a 4x4 matrix referred to by column and row indices + // + inline Matrix4 & setElem( int col, int row, float val ); + + // Get the element of a 4x4 matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Add two 4x4 matrices + // + inline const Matrix4 operator +( const Matrix4 & mat ) const; + + // Subtract a 4x4 matrix from another 4x4 matrix + // + inline const Matrix4 operator -( const Matrix4 & mat ) const; + + // Negate all elements of a 4x4 matrix + // + inline const Matrix4 operator -( ) const; + + // Multiply a 4x4 matrix by a scalar + // + inline const Matrix4 operator *( float scalar ) const; + + // Multiply a 4x4 matrix by a 4-D vector + // + inline const Vector4 operator *( Vector4 vec ) const; + + // Multiply a 4x4 matrix by a 3-D vector + // + inline const Vector4 operator *( Vector3 vec ) const; + + // Multiply a 4x4 matrix by a 3-D point + // + inline const Vector4 operator *( Point3 pnt ) const; + + // Multiply two 4x4 matrices + // + inline const Matrix4 operator *( const Matrix4 & mat ) const; + + // Multiply a 4x4 matrix by a 3x4 transformation matrix + // + inline const Matrix4 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and addition with a 4x4 matrix + // + inline Matrix4 & operator +=( const Matrix4 & mat ); + + // Perform compound assignment and subtraction by a 4x4 matrix + // + inline Matrix4 & operator -=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix4 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a 4x4 matrix + // + inline Matrix4 & operator *=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Matrix4 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 4x4 matrix + // + static inline const Matrix4 identity( ); + + // Construct a 4x4 matrix to rotate around the x axis + // + static inline const Matrix4 rotationX( float radians ); + + // Construct a 4x4 matrix to rotate around the y axis + // + static inline const Matrix4 rotationY( float radians ); + + // Construct a 4x4 matrix to rotate around the z axis + // + static inline const Matrix4 rotationZ( float radians ); + + // Construct a 4x4 matrix to rotate around the x, y, and z axes + // + static inline const Matrix4 rotationZYX( Vector3 radiansXYZ ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix4 rotation( float radians, Vector3 unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix4 rotation( Quat unitQuat ); + + // Construct a 4x4 matrix to perform scaling + // + static inline const Matrix4 scale( Vector3 scaleVec ); + + // Construct a 4x4 matrix to perform translation + // + static inline const Matrix4 translation( Vector3 translateVec ); + + // Construct viewing matrix based on eye position, position looked at, and up direction + // + static inline const Matrix4 lookAt( Point3 eyePos, Point3 lookAtPos, Vector3 upVec ); + + // Construct a perspective projection matrix + // + static inline const Matrix4 perspective( float fovyRadians, float aspect, float zNear, float zFar ); + + // Construct a perspective projection matrix based on frustum + // + static inline const Matrix4 frustum( float left, float right, float bottom, float top, float zNear, float zFar ); + + // Construct an orthographic projection matrix + // + static inline const Matrix4 orthographic( float left, float right, float bottom, float top, float zNear, float zFar ); + +}; +// Multiply a 4x4 matrix by a scalar +// +inline const Matrix4 operator *( float scalar, const Matrix4 & mat ); + +// Append (post-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 appendScale( const Matrix4 & mat, Vector3 scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 prependScale( Vector3 scaleVec, const Matrix4 & mat ); + +// Multiply two 4x4 matrices per element +// +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); + +// Compute the absolute value of a 4x4 matrix per element +// +inline const Matrix4 absPerElem( const Matrix4 & mat ); + +// Transpose of a 4x4 matrix +// +inline const Matrix4 transpose( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 inverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 affineInverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. +// +inline const Matrix4 orthoInverse( const Matrix4 & mat ); + +// Determinant of a 4x4 matrix +// +inline float determinant( const Matrix4 & mat ); + +// Conditionally select between two 4x4 matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4x4 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat ); + +// Print a 4x4 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat, const char * name ); + +#endif + +// A 3x4 transformation matrix in array-of-structures format +// +class Transform3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + Vector3 mCol3; + +public: + // Default constructor; does no initialization + // + inline Transform3( ) { }; + + // Copy a 3x4 transformation matrix + // + inline Transform3( const Transform3 & tfrm ); + + // Construct a 3x4 transformation matrix containing the specified columns + // + inline Transform3( Vector3 col0, Vector3 col1, Vector3 col2, Vector3 col3 ); + + // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + // + inline Transform3( const Matrix3 & tfrm, Vector3 translateVec ); + + // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + // + inline Transform3( Quat unitQuat, Vector3 translateVec ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value + // + explicit inline Transform3( float scalar ); + + // Assign one 3x4 transformation matrix to another + // + inline Transform3 & operator =( const Transform3 & tfrm ); + + // Set the upper-left 3x3 submatrix + // + inline Transform3 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // + inline Transform3 & setTranslation( Vector3 translateVec ); + + // Get the translation component of a 3x4 transformation matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 3x4 transformation matrix + // + inline Transform3 & setCol0( Vector3 col0 ); + + // Set column 1 of a 3x4 transformation matrix + // + inline Transform3 & setCol1( Vector3 col1 ); + + // Set column 2 of a 3x4 transformation matrix + // + inline Transform3 & setCol2( Vector3 col2 ); + + // Set column 3 of a 3x4 transformation matrix + // + inline Transform3 & setCol3( Vector3 col3 ); + + // Get column 0 of a 3x4 transformation matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x4 transformation matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x4 transformation matrix + // + inline const Vector3 getCol2( ) const; + + // Get column 3 of a 3x4 transformation matrix + // + inline const Vector3 getCol3( ) const; + + // Set the column of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setCol( int col, Vector3 vec ); + + // Set the row of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setRow( int row, Vector4 vec ); + + // Get the column of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x4 transformation matrix referred to by column and row indices + // + inline Transform3 & setElem( int col, int row, float val ); + + // Get the element of a 3x4 transformation matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Multiply a 3x4 transformation matrix by a 3-D vector + // + inline const Vector3 operator *( Vector3 vec ) const; + + // Multiply a 3x4 transformation matrix by a 3-D point + // + inline const Point3 operator *( Point3 pnt ) const; + + // Multiply two 3x4 transformation matrices + // + inline const Transform3 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Transform3 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 3x4 transformation matrix + // + static inline const Transform3 identity( ); + + // Construct a 3x4 transformation matrix to rotate around the x axis + // + static inline const Transform3 rotationX( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis + // + static inline const Transform3 rotationY( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis + // + static inline const Transform3 rotationZ( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + // + static inline const Transform3 rotationZYX( Vector3 radiansXYZ ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + // + static inline const Transform3 rotation( float radians, Vector3 unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Transform3 rotation( Quat unitQuat ); + + // Construct a 3x4 transformation matrix to perform scaling + // + static inline const Transform3 scale( Vector3 scaleVec ); + + // Construct a 3x4 transformation matrix to perform translation + // + static inline const Transform3 translation( Vector3 translateVec ); + +}; +// Append (post-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 appendScale( const Transform3 & tfrm, Vector3 scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 prependScale( Vector3 scaleVec, const Transform3 & tfrm ); + +// Multiply two 3x4 transformation matrices per element +// +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); + +// Compute the absolute value of a 3x4 transformation matrix per element +// +inline const Transform3 absPerElem( const Transform3 & tfrm ); + +// Inverse of a 3x4 transformation matrix +// NOTE: +// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. +// +inline const Transform3 inverse( const Transform3 & tfrm ); + +// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. +// +inline const Transform3 orthoInverse( const Transform3 & tfrm ); + +// Conditionally select between two 3x4 transformation matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x4 transformation matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm ); + +// Print a 3x4 transformation matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm, const char * name ); + +#endif + +} // namespace Aos +} // namespace Vectormath + +#include "vec_aos.h" +#include "quat_aos.h" +#include "mat_aos.h" + +#endif diff --git a/Extras/vectormathlibrary/include/vectormath/spu/cpp/vectormath_soa.h b/Extras/vectormathlibrary/include/vectormath/spu/cpp/vectormath_soa.h new file mode 100644 index 0000000..c37927b --- /dev/null +++ b/Extras/vectormathlibrary/include/vectormath/spu/cpp/vectormath_soa.h @@ -0,0 +1,1921 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_SOA_CPP_SPU_H +#define _VECTORMATH_SOA_CPP_SPU_H + +#include +#include +#include "floatInVec.h" +#include "boolInVec.h" +#include "vectormath_aos.h" +#include + +#ifdef _VECTORMATH_DEBUG +#endif + +namespace Vectormath { + +namespace Soa { + +//----------------------------------------------------------------------------- +// Forward Declarations +// + +class Vector3; +class Vector4; +class Point3; +class Quat; +class Matrix3; +class Matrix4; +class Transform3; + +// A set of four 3-D vectors in structure-of-arrays format +// +class Vector3 +{ + typedef vec_float4 vec_float4_t; + vec_float4 mX; + vec_float4 mY; + vec_float4 mZ; + +public: + // Default constructor; does no initialization + // + inline Vector3( ) { }; + + // Copy a 3-D vector + // + inline Vector3( const Vector3 & vec ); + + // Construct a 3-D vector from x, y, and z elements + // + inline Vector3( vec_float4 x, vec_float4 y, vec_float4 z ); + + // Copy elements from a 3-D point into a 3-D vector + // + explicit inline Vector3( const Point3 & pnt ); + + // Set all elements of a 3-D vector to the same scalar value + // + explicit inline Vector3( vec_float4 scalar ); + + // Replicate an AoS 3-D vector + // + inline Vector3( Aos::Vector3 vec ); + + // Insert four AoS 3-D vectors + // + inline Vector3( Aos::Vector3 vec0, Aos::Vector3 vec1, Aos::Vector3 vec2, Aos::Vector3 vec3 ); + + // Extract four AoS 3-D vectors + // + inline void get4Aos( Aos::Vector3 & result0, Aos::Vector3 & result1, Aos::Vector3 & result2, Aos::Vector3 & result3 ) const; + + // Assign one 3-D vector to another + // + inline Vector3 & operator =( const Vector3 & vec ); + + // Set the x element of a 3-D vector + // + inline Vector3 & setX( vec_float4 x ); + + // Set the y element of a 3-D vector + // + inline Vector3 & setY( vec_float4 y ); + + // Set the z element of a 3-D vector + // + inline Vector3 & setZ( vec_float4 z ); + + // Get the x element of a 3-D vector + // + inline vec_float4 getX( ) const; + + // Get the y element of a 3-D vector + // + inline vec_float4 getY( ) const; + + // Get the z element of a 3-D vector + // + inline vec_float4 getZ( ) const; + + // Set an x, y, or z element of a 3-D vector by index + // + inline Vector3 & setElem( int idx, vec_float4 value ); + + // Get an x, y, or z element of a 3-D vector by index + // + inline vec_float4 getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline vec_float4_t & operator []( int idx ); + + // Subscripting operator to get an element + // + inline vec_float4 operator []( int idx ) const; + + // Add two 3-D vectors + // + inline const Vector3 operator +( const Vector3 & vec ) const; + + // Subtract a 3-D vector from another 3-D vector + // + inline const Vector3 operator -( const Vector3 & vec ) const; + + // Add a 3-D vector to a 3-D point + // + inline const Point3 operator +( const Point3 & pnt ) const; + + // Multiply a 3-D vector by a scalar + // + inline const Vector3 operator *( vec_float4 scalar ) const; + + // Divide a 3-D vector by a scalar + // + inline const Vector3 operator /( vec_float4 scalar ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Vector3 & operator +=( const Vector3 & vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Vector3 & operator -=( const Vector3 & vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector3 & operator *=( vec_float4 scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector3 & operator /=( vec_float4 scalar ); + + // Negate all elements of a 3-D vector + // + inline const Vector3 operator -( ) const; + + // Construct x axis + // + static inline const Vector3 xAxis( ); + + // Construct y axis + // + static inline const Vector3 yAxis( ); + + // Construct z axis + // + static inline const Vector3 zAxis( ); + +}; + +// Multiply a 3-D vector by a scalar +// +inline const Vector3 operator *( vec_float4 scalar, const Vector3 & vec ); + +// Multiply two 3-D vectors per element +// +inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Divide two 3-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Compute the reciprocal of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector3 recipPerElem( const Vector3 & vec ); + +// Compute the square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector3 sqrtPerElem( const Vector3 & vec ); + +// Compute the reciprocal square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector3 rsqrtPerElem( const Vector3 & vec ); + +// Compute the absolute value of a 3-D vector per element +// +inline const Vector3 absPerElem( const Vector3 & vec ); + +// Copy sign from one 3-D vector to another, per element +// +inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Maximum of two 3-D vectors per element +// +inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Minimum of two 3-D vectors per element +// +inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Maximum element of a 3-D vector +// +inline vec_float4 maxElem( const Vector3 & vec ); + +// Minimum element of a 3-D vector +// +inline vec_float4 minElem( const Vector3 & vec ); + +// Compute the sum of all elements of a 3-D vector +// +inline vec_float4 sum( const Vector3 & vec ); + +// Compute the dot product of two 3-D vectors +// +inline vec_float4 dot( const Vector3 & vec0, const Vector3 & vec1 ); + +// Compute the square of the length of a 3-D vector +// +inline vec_float4 lengthSqr( const Vector3 & vec ); + +// Compute the length of a 3-D vector +// +inline vec_float4 length( const Vector3 & vec ); + +// Normalize a 3-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector3 normalize( const Vector3 & vec ); + +// Compute cross product of two 3-D vectors +// +inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ); + +// Outer product of two 3-D vectors +// +inline const Matrix3 outer( const Vector3 & vec0, const Vector3 & vec1 ); + +// Pre-multiply a row vector by a 3x3 matrix +// +inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ); + +// Cross-product matrix of a 3-D vector +// +inline const Matrix3 crossMatrix( const Vector3 & vec ); + +// Create cross-product matrix and multiply +// NOTE: +// Faster than separately creating a cross-product matrix and multiplying. +// +inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ); + +// Linear interpolation between two 3-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector3 lerp( vec_float4 t, const Vector3 & vec0, const Vector3 & vec1 ); + +// Spherical linear interpolation between two 3-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector3 slerp( vec_float4 t, const Vector3 & unitVec0, const Vector3 & unitVec1 ); + +// Conditionally select between two 3-D vectors +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, vec_uint4 select1 ); + +// Load four three-float 3-D vectors, stored in three quadwords +// +inline void loadXYZArray( Vector3 & vec, const vec_float4 * threeQuads ); + +// Store four slots of an SoA 3-D vector in three quadwords +// +inline void storeXYZArray( const Vector3 & vec, vec_float4 * threeQuads ); + +// Store eight slots of two SoA 3-D vectors as half-floats +// +inline void storeHalfFloats( const Vector3 & vec0, const Vector3 & vec1, vec_ushort8 * threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector3 & vec ); + +// Print a 3-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector3 & vec, const char * name ); + +#endif + +// A set of four 4-D vectors in structure-of-arrays format +// +class Vector4 +{ + typedef vec_float4 vec_float4_t; + vec_float4 mX; + vec_float4 mY; + vec_float4 mZ; + vec_float4 mW; + +public: + // Default constructor; does no initialization + // + inline Vector4( ) { }; + + // Copy a 4-D vector + // + inline Vector4( const Vector4 & vec ); + + // Construct a 4-D vector from x, y, z, and w elements + // + inline Vector4( vec_float4 x, vec_float4 y, vec_float4 z, vec_float4 w ); + + // Construct a 4-D vector from a 3-D vector and a scalar + // + inline Vector4( const Vector3 & xyz, vec_float4 w ); + + // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + // + explicit inline Vector4( const Vector3 & vec ); + + // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + // + explicit inline Vector4( const Point3 & pnt ); + + // Copy elements from a quaternion into a 4-D vector + // + explicit inline Vector4( const Quat & quat ); + + // Set all elements of a 4-D vector to the same scalar value + // + explicit inline Vector4( vec_float4 scalar ); + + // Replicate an AoS 4-D vector + // + inline Vector4( Aos::Vector4 vec ); + + // Insert four AoS 4-D vectors + // + inline Vector4( Aos::Vector4 vec0, Aos::Vector4 vec1, Aos::Vector4 vec2, Aos::Vector4 vec3 ); + + // Extract four AoS 4-D vectors + // + inline void get4Aos( Aos::Vector4 & result0, Aos::Vector4 & result1, Aos::Vector4 & result2, Aos::Vector4 & result3 ) const; + + // Assign one 4-D vector to another + // + inline Vector4 & operator =( const Vector4 & vec ); + + // Set the x, y, and z elements of a 4-D vector + // NOTE: + // This function does not change the w element. + // + inline Vector4 & setXYZ( const Vector3 & vec ); + + // Get the x, y, and z elements of a 4-D vector + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a 4-D vector + // + inline Vector4 & setX( vec_float4 x ); + + // Set the y element of a 4-D vector + // + inline Vector4 & setY( vec_float4 y ); + + // Set the z element of a 4-D vector + // + inline Vector4 & setZ( vec_float4 z ); + + // Set the w element of a 4-D vector + // + inline Vector4 & setW( vec_float4 w ); + + // Get the x element of a 4-D vector + // + inline vec_float4 getX( ) const; + + // Get the y element of a 4-D vector + // + inline vec_float4 getY( ) const; + + // Get the z element of a 4-D vector + // + inline vec_float4 getZ( ) const; + + // Get the w element of a 4-D vector + // + inline vec_float4 getW( ) const; + + // Set an x, y, z, or w element of a 4-D vector by index + // + inline Vector4 & setElem( int idx, vec_float4 value ); + + // Get an x, y, z, or w element of a 4-D vector by index + // + inline vec_float4 getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline vec_float4_t & operator []( int idx ); + + // Subscripting operator to get an element + // + inline vec_float4 operator []( int idx ) const; + + // Add two 4-D vectors + // + inline const Vector4 operator +( const Vector4 & vec ) const; + + // Subtract a 4-D vector from another 4-D vector + // + inline const Vector4 operator -( const Vector4 & vec ) const; + + // Multiply a 4-D vector by a scalar + // + inline const Vector4 operator *( vec_float4 scalar ) const; + + // Divide a 4-D vector by a scalar + // + inline const Vector4 operator /( vec_float4 scalar ) const; + + // Perform compound assignment and addition with a 4-D vector + // + inline Vector4 & operator +=( const Vector4 & vec ); + + // Perform compound assignment and subtraction by a 4-D vector + // + inline Vector4 & operator -=( const Vector4 & vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector4 & operator *=( vec_float4 scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector4 & operator /=( vec_float4 scalar ); + + // Negate all elements of a 4-D vector + // + inline const Vector4 operator -( ) const; + + // Construct x axis + // + static inline const Vector4 xAxis( ); + + // Construct y axis + // + static inline const Vector4 yAxis( ); + + // Construct z axis + // + static inline const Vector4 zAxis( ); + + // Construct w axis + // + static inline const Vector4 wAxis( ); + +}; + +// Multiply a 4-D vector by a scalar +// +inline const Vector4 operator *( vec_float4 scalar, const Vector4 & vec ); + +// Multiply two 4-D vectors per element +// +inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Divide two 4-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Compute the reciprocal of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector4 recipPerElem( const Vector4 & vec ); + +// Compute the square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector4 sqrtPerElem( const Vector4 & vec ); + +// Compute the reciprocal square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector4 rsqrtPerElem( const Vector4 & vec ); + +// Compute the absolute value of a 4-D vector per element +// +inline const Vector4 absPerElem( const Vector4 & vec ); + +// Copy sign from one 4-D vector to another, per element +// +inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Maximum of two 4-D vectors per element +// +inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Minimum of two 4-D vectors per element +// +inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Maximum element of a 4-D vector +// +inline vec_float4 maxElem( const Vector4 & vec ); + +// Minimum element of a 4-D vector +// +inline vec_float4 minElem( const Vector4 & vec ); + +// Compute the sum of all elements of a 4-D vector +// +inline vec_float4 sum( const Vector4 & vec ); + +// Compute the dot product of two 4-D vectors +// +inline vec_float4 dot( const Vector4 & vec0, const Vector4 & vec1 ); + +// Compute the square of the length of a 4-D vector +// +inline vec_float4 lengthSqr( const Vector4 & vec ); + +// Compute the length of a 4-D vector +// +inline vec_float4 length( const Vector4 & vec ); + +// Normalize a 4-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector4 normalize( const Vector4 & vec ); + +// Outer product of two 4-D vectors +// +inline const Matrix4 outer( const Vector4 & vec0, const Vector4 & vec1 ); + +// Linear interpolation between two 4-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector4 lerp( vec_float4 t, const Vector4 & vec0, const Vector4 & vec1 ); + +// Spherical linear interpolation between two 4-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector4 slerp( vec_float4 t, const Vector4 & unitVec0, const Vector4 & unitVec1 ); + +// Conditionally select between two 4-D vectors +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, vec_uint4 select1 ); + +// Store four slots of an SoA 4-D vector as half-floats +// +inline void storeHalfFloats( const Vector4 & vec, vec_ushort8 * twoQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector4 & vec ); + +// Print a 4-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector4 & vec, const char * name ); + +#endif + +// A set of four 3-D points in structure-of-arrays format +// +class Point3 +{ + typedef vec_float4 vec_float4_t; + vec_float4 mX; + vec_float4 mY; + vec_float4 mZ; + +public: + // Default constructor; does no initialization + // + inline Point3( ) { }; + + // Copy a 3-D point + // + inline Point3( const Point3 & pnt ); + + // Construct a 3-D point from x, y, and z elements + // + inline Point3( vec_float4 x, vec_float4 y, vec_float4 z ); + + // Copy elements from a 3-D vector into a 3-D point + // + explicit inline Point3( const Vector3 & vec ); + + // Set all elements of a 3-D point to the same scalar value + // + explicit inline Point3( vec_float4 scalar ); + + // Replicate an AoS 3-D point + // + inline Point3( Aos::Point3 pnt ); + + // Insert four AoS 3-D points + // + inline Point3( Aos::Point3 pnt0, Aos::Point3 pnt1, Aos::Point3 pnt2, Aos::Point3 pnt3 ); + + // Extract four AoS 3-D points + // + inline void get4Aos( Aos::Point3 & result0, Aos::Point3 & result1, Aos::Point3 & result2, Aos::Point3 & result3 ) const; + + // Assign one 3-D point to another + // + inline Point3 & operator =( const Point3 & pnt ); + + // Set the x element of a 3-D point + // + inline Point3 & setX( vec_float4 x ); + + // Set the y element of a 3-D point + // + inline Point3 & setY( vec_float4 y ); + + // Set the z element of a 3-D point + // + inline Point3 & setZ( vec_float4 z ); + + // Get the x element of a 3-D point + // + inline vec_float4 getX( ) const; + + // Get the y element of a 3-D point + // + inline vec_float4 getY( ) const; + + // Get the z element of a 3-D point + // + inline vec_float4 getZ( ) const; + + // Set an x, y, or z element of a 3-D point by index + // + inline Point3 & setElem( int idx, vec_float4 value ); + + // Get an x, y, or z element of a 3-D point by index + // + inline vec_float4 getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline vec_float4_t & operator []( int idx ); + + // Subscripting operator to get an element + // + inline vec_float4 operator []( int idx ) const; + + // Subtract a 3-D point from another 3-D point + // + inline const Vector3 operator -( const Point3 & pnt ) const; + + // Add a 3-D point to a 3-D vector + // + inline const Point3 operator +( const Vector3 & vec ) const; + + // Subtract a 3-D vector from a 3-D point + // + inline const Point3 operator -( const Vector3 & vec ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Point3 & operator +=( const Vector3 & vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Point3 & operator -=( const Vector3 & vec ); + +}; + +// Multiply two 3-D points per element +// +inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Divide two 3-D points per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Compute the reciprocal of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Point3 recipPerElem( const Point3 & pnt ); + +// Compute the square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Point3 sqrtPerElem( const Point3 & pnt ); + +// Compute the reciprocal square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Point3 rsqrtPerElem( const Point3 & pnt ); + +// Compute the absolute value of a 3-D point per element +// +inline const Point3 absPerElem( const Point3 & pnt ); + +// Copy sign from one 3-D point to another, per element +// +inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Maximum of two 3-D points per element +// +inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Minimum of two 3-D points per element +// +inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Maximum element of a 3-D point +// +inline vec_float4 maxElem( const Point3 & pnt ); + +// Minimum element of a 3-D point +// +inline vec_float4 minElem( const Point3 & pnt ); + +// Compute the sum of all elements of a 3-D point +// +inline vec_float4 sum( const Point3 & pnt ); + +// Apply uniform scale to a 3-D point +// +inline const Point3 scale( const Point3 & pnt, vec_float4 scaleVal ); + +// Apply non-uniform scale to a 3-D point +// +inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ); + +// Scalar projection of a 3-D point on a unit-length 3-D vector +// +inline vec_float4 projection( const Point3 & pnt, const Vector3 & unitVec ); + +// Compute the square of the distance of a 3-D point from the coordinate-system origin +// +inline vec_float4 distSqrFromOrigin( const Point3 & pnt ); + +// Compute the distance of a 3-D point from the coordinate-system origin +// +inline vec_float4 distFromOrigin( const Point3 & pnt ); + +// Compute the square of the distance between two 3-D points +// +inline vec_float4 distSqr( const Point3 & pnt0, const Point3 & pnt1 ); + +// Compute the distance between two 3-D points +// +inline vec_float4 dist( const Point3 & pnt0, const Point3 & pnt1 ); + +// Linear interpolation between two 3-D points +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Point3 lerp( vec_float4 t, const Point3 & pnt0, const Point3 & pnt1 ); + +// Conditionally select between two 3-D points +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, vec_uint4 select1 ); + +// Load four three-float 3-D points, stored in three quadwords +// +inline void loadXYZArray( Point3 & pnt, const vec_float4 * threeQuads ); + +// Store four slots of an SoA 3-D point in three quadwords +// +inline void storeXYZArray( const Point3 & pnt, vec_float4 * threeQuads ); + +// Store eight slots of two SoA 3-D points as half-floats +// +inline void storeHalfFloats( const Point3 & pnt0, const Point3 & pnt1, vec_ushort8 * threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D point +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Point3 & pnt ); + +// Print a 3-D point and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Point3 & pnt, const char * name ); + +#endif + +// A set of four quaternions in structure-of-arrays format +// +class Quat +{ + typedef vec_float4 vec_float4_t; + vec_float4 mX; + vec_float4 mY; + vec_float4 mZ; + vec_float4 mW; + +public: + // Default constructor; does no initialization + // + inline Quat( ) { }; + + // Copy a quaternion + // + inline Quat( const Quat & quat ); + + // Construct a quaternion from x, y, z, and w elements + // + inline Quat( vec_float4 x, vec_float4 y, vec_float4 z, vec_float4 w ); + + // Construct a quaternion from a 3-D vector and a scalar + // + inline Quat( const Vector3 & xyz, vec_float4 w ); + + // Copy elements from a 4-D vector into a quaternion + // + explicit inline Quat( const Vector4 & vec ); + + // Convert a rotation matrix to a unit-length quaternion + // + explicit inline Quat( const Matrix3 & rotMat ); + + // Set all elements of a quaternion to the same scalar value + // + explicit inline Quat( vec_float4 scalar ); + + // Replicate an AoS quaternion + // + inline Quat( Aos::Quat quat ); + + // Insert four AoS quaternions + // + inline Quat( Aos::Quat quat0, Aos::Quat quat1, Aos::Quat quat2, Aos::Quat quat3 ); + + // Extract four AoS quaternions + // + inline void get4Aos( Aos::Quat & result0, Aos::Quat & result1, Aos::Quat & result2, Aos::Quat & result3 ) const; + + // Assign one quaternion to another + // + inline Quat & operator =( const Quat & quat ); + + // Set the x, y, and z elements of a quaternion + // NOTE: + // This function does not change the w element. + // + inline Quat & setXYZ( const Vector3 & vec ); + + // Get the x, y, and z elements of a quaternion + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a quaternion + // + inline Quat & setX( vec_float4 x ); + + // Set the y element of a quaternion + // + inline Quat & setY( vec_float4 y ); + + // Set the z element of a quaternion + // + inline Quat & setZ( vec_float4 z ); + + // Set the w element of a quaternion + // + inline Quat & setW( vec_float4 w ); + + // Get the x element of a quaternion + // + inline vec_float4 getX( ) const; + + // Get the y element of a quaternion + // + inline vec_float4 getY( ) const; + + // Get the z element of a quaternion + // + inline vec_float4 getZ( ) const; + + // Get the w element of a quaternion + // + inline vec_float4 getW( ) const; + + // Set an x, y, z, or w element of a quaternion by index + // + inline Quat & setElem( int idx, vec_float4 value ); + + // Get an x, y, z, or w element of a quaternion by index + // + inline vec_float4 getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline vec_float4_t & operator []( int idx ); + + // Subscripting operator to get an element + // + inline vec_float4 operator []( int idx ) const; + + // Add two quaternions + // + inline const Quat operator +( const Quat & quat ) const; + + // Subtract a quaternion from another quaternion + // + inline const Quat operator -( const Quat & quat ) const; + + // Multiply two quaternions + // + inline const Quat operator *( const Quat & quat ) const; + + // Multiply a quaternion by a scalar + // + inline const Quat operator *( vec_float4 scalar ) const; + + // Divide a quaternion by a scalar + // + inline const Quat operator /( vec_float4 scalar ) const; + + // Perform compound assignment and addition with a quaternion + // + inline Quat & operator +=( const Quat & quat ); + + // Perform compound assignment and subtraction by a quaternion + // + inline Quat & operator -=( const Quat & quat ); + + // Perform compound assignment and multiplication by a quaternion + // + inline Quat & operator *=( const Quat & quat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Quat & operator *=( vec_float4 scalar ); + + // Perform compound assignment and division by a scalar + // + inline Quat & operator /=( vec_float4 scalar ); + + // Negate all elements of a quaternion + // + inline const Quat operator -( ) const; + + // Construct an identity quaternion + // + static inline const Quat identity( ); + + // Construct a quaternion to rotate between two unit-length 3-D vectors + // NOTE: + // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + // + static inline const Quat rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ); + + // Construct a quaternion to rotate around a unit-length 3-D vector + // + static inline const Quat rotation( vec_float4 radians, const Vector3 & unitVec ); + + // Construct a quaternion to rotate around the x axis + // + static inline const Quat rotationX( vec_float4 radians ); + + // Construct a quaternion to rotate around the y axis + // + static inline const Quat rotationY( vec_float4 radians ); + + // Construct a quaternion to rotate around the z axis + // + static inline const Quat rotationZ( vec_float4 radians ); + +}; + +// Multiply a quaternion by a scalar +// +inline const Quat operator *( vec_float4 scalar, const Quat & quat ); + +// Compute the conjugate of a quaternion +// +inline const Quat conj( const Quat & quat ); + +// Use a unit-length quaternion to rotate a 3-D vector +// +inline const Vector3 rotate( const Quat & unitQuat, const Vector3 & vec ); + +// Compute the dot product of two quaternions +// +inline vec_float4 dot( const Quat & quat0, const Quat & quat1 ); + +// Compute the norm of a quaternion +// +inline vec_float4 norm( const Quat & quat ); + +// Compute the length of a quaternion +// +inline vec_float4 length( const Quat & quat ); + +// Normalize a quaternion +// NOTE: +// The result is unpredictable when all elements of quat are at or near zero. +// +inline const Quat normalize( const Quat & quat ); + +// Linear interpolation between two quaternions +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Quat lerp( vec_float4 t, const Quat & quat0, const Quat & quat1 ); + +// Spherical linear interpolation between two quaternions +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +inline const Quat slerp( vec_float4 t, const Quat & unitQuat0, const Quat & unitQuat1 ); + +// Spherical quadrangle interpolation +// +inline const Quat squad( vec_float4 t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ); + +// Conditionally select between two quaternions +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Quat select( const Quat & quat0, const Quat & quat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a quaternion +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Quat & quat ); + +// Print a quaternion and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Quat & quat, const char * name ); + +#endif + +// A set of four 3x3 matrices in structure-of-arrays format +// +class Matrix3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + +public: + // Default constructor; does no initialization + // + inline Matrix3( ) { }; + + // Copy a 3x3 matrix + // + inline Matrix3( const Matrix3 & mat ); + + // Construct a 3x3 matrix containing the specified columns + // + inline Matrix3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2 ); + + // Construct a 3x3 rotation matrix from a unit-length quaternion + // + explicit inline Matrix3( const Quat & unitQuat ); + + // Set all elements of a 3x3 matrix to the same scalar value + // + explicit inline Matrix3( vec_float4 scalar ); + + // Replicate an AoS 3x3 matrix + // + inline Matrix3( const Aos::Matrix3 & mat ); + + // Insert four AoS 3x3 matrices + // + inline Matrix3( const Aos::Matrix3 & mat0, const Aos::Matrix3 & mat1, const Aos::Matrix3 & mat2, const Aos::Matrix3 & mat3 ); + + // Extract four AoS 3x3 matrices + // + inline void get4Aos( Aos::Matrix3 & result0, Aos::Matrix3 & result1, Aos::Matrix3 & result2, Aos::Matrix3 & result3 ) const; + + // Assign one 3x3 matrix to another + // + inline Matrix3 & operator =( const Matrix3 & mat ); + + // Set column 0 of a 3x3 matrix + // + inline Matrix3 & setCol0( const Vector3 & col0 ); + + // Set column 1 of a 3x3 matrix + // + inline Matrix3 & setCol1( const Vector3 & col1 ); + + // Set column 2 of a 3x3 matrix + // + inline Matrix3 & setCol2( const Vector3 & col2 ); + + // Get column 0 of a 3x3 matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x3 matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x3 matrix + // + inline const Vector3 getCol2( ) const; + + // Set the column of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setCol( int col, const Vector3 & vec ); + + // Set the row of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setRow( int row, const Vector3 & vec ); + + // Get the column of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x3 matrix referred to by column and row indices + // + inline Matrix3 & setElem( int col, int row, vec_float4 val ); + + // Get the element of a 3x3 matrix referred to by column and row indices + // + inline vec_float4 getElem( int col, int row ) const; + + // Add two 3x3 matrices + // + inline const Matrix3 operator +( const Matrix3 & mat ) const; + + // Subtract a 3x3 matrix from another 3x3 matrix + // + inline const Matrix3 operator -( const Matrix3 & mat ) const; + + // Negate all elements of a 3x3 matrix + // + inline const Matrix3 operator -( ) const; + + // Multiply a 3x3 matrix by a scalar + // + inline const Matrix3 operator *( vec_float4 scalar ) const; + + // Multiply a 3x3 matrix by a 3-D vector + // + inline const Vector3 operator *( const Vector3 & vec ) const; + + // Multiply two 3x3 matrices + // + inline const Matrix3 operator *( const Matrix3 & mat ) const; + + // Perform compound assignment and addition with a 3x3 matrix + // + inline Matrix3 & operator +=( const Matrix3 & mat ); + + // Perform compound assignment and subtraction by a 3x3 matrix + // + inline Matrix3 & operator -=( const Matrix3 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix3 & operator *=( vec_float4 scalar ); + + // Perform compound assignment and multiplication by a 3x3 matrix + // + inline Matrix3 & operator *=( const Matrix3 & mat ); + + // Construct an identity 3x3 matrix + // + static inline const Matrix3 identity( ); + + // Construct a 3x3 matrix to rotate around the x axis + // + static inline const Matrix3 rotationX( vec_float4 radians ); + + // Construct a 3x3 matrix to rotate around the y axis + // + static inline const Matrix3 rotationY( vec_float4 radians ); + + // Construct a 3x3 matrix to rotate around the z axis + // + static inline const Matrix3 rotationZ( vec_float4 radians ); + + // Construct a 3x3 matrix to rotate around the x, y, and z axes + // + static inline const Matrix3 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix3 rotation( vec_float4 radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix3 rotation( const Quat & unitQuat ); + + // Construct a 3x3 matrix to perform scaling + // + static inline const Matrix3 scale( const Vector3 & scaleVec ); + +}; +// Multiply a 3x3 matrix by a scalar +// +inline const Matrix3 operator *( vec_float4 scalar, const Matrix3 & mat ); + +// Append (post-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ); + +// Multiply two 3x3 matrices per element +// +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); + +// Compute the absolute value of a 3x3 matrix per element +// +inline const Matrix3 absPerElem( const Matrix3 & mat ); + +// Transpose of a 3x3 matrix +// +inline const Matrix3 transpose( const Matrix3 & mat ); + +// Compute the inverse of a 3x3 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix3 inverse( const Matrix3 & mat ); + +// Determinant of a 3x3 matrix +// +inline vec_float4 determinant( const Matrix3 & mat ); + +// Conditionally select between two 3x3 matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x3 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat ); + +// Print a 3x3 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat, const char * name ); + +#endif + +// A set of four 4x4 matrices in structure-of-arrays format +// +class Matrix4 +{ + Vector4 mCol0; + Vector4 mCol1; + Vector4 mCol2; + Vector4 mCol3; + +public: + // Default constructor; does no initialization + // + inline Matrix4( ) { }; + + // Copy a 4x4 matrix + // + inline Matrix4( const Matrix4 & mat ); + + // Construct a 4x4 matrix containing the specified columns + // + inline Matrix4( const Vector4 & col0, const Vector4 & col1, const Vector4 & col2, const Vector4 & col3 ); + + // Construct a 4x4 matrix from a 3x4 transformation matrix + // + explicit inline Matrix4( const Transform3 & mat ); + + // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + // + inline Matrix4( const Matrix3 & mat, const Vector3 & translateVec ); + + // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + // + inline Matrix4( const Quat & unitQuat, const Vector3 & translateVec ); + + // Set all elements of a 4x4 matrix to the same scalar value + // + explicit inline Matrix4( vec_float4 scalar ); + + // Replicate an AoS 4x4 matrix + // + inline Matrix4( const Aos::Matrix4 & mat ); + + // Insert four AoS 4x4 matrices + // + inline Matrix4( const Aos::Matrix4 & mat0, const Aos::Matrix4 & mat1, const Aos::Matrix4 & mat2, const Aos::Matrix4 & mat3 ); + + // Extract four AoS 4x4 matrices + // + inline void get4Aos( Aos::Matrix4 & result0, Aos::Matrix4 & result1, Aos::Matrix4 & result2, Aos::Matrix4 & result3 ) const; + + // Assign one 4x4 matrix to another + // + inline Matrix4 & operator =( const Matrix4 & mat ); + + // Set the upper-left 3x3 submatrix + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 4x4 matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setTranslation( const Vector3 & translateVec ); + + // Get the translation component of a 4x4 matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 4x4 matrix + // + inline Matrix4 & setCol0( const Vector4 & col0 ); + + // Set column 1 of a 4x4 matrix + // + inline Matrix4 & setCol1( const Vector4 & col1 ); + + // Set column 2 of a 4x4 matrix + // + inline Matrix4 & setCol2( const Vector4 & col2 ); + + // Set column 3 of a 4x4 matrix + // + inline Matrix4 & setCol3( const Vector4 & col3 ); + + // Get column 0 of a 4x4 matrix + // + inline const Vector4 getCol0( ) const; + + // Get column 1 of a 4x4 matrix + // + inline const Vector4 getCol1( ) const; + + // Get column 2 of a 4x4 matrix + // + inline const Vector4 getCol2( ) const; + + // Get column 3 of a 4x4 matrix + // + inline const Vector4 getCol3( ) const; + + // Set the column of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setCol( int col, const Vector4 & vec ); + + // Set the row of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setRow( int row, const Vector4 & vec ); + + // Get the column of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getCol( int col ) const; + + // Get the row of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector4 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector4 operator []( int col ) const; + + // Set the element of a 4x4 matrix referred to by column and row indices + // + inline Matrix4 & setElem( int col, int row, vec_float4 val ); + + // Get the element of a 4x4 matrix referred to by column and row indices + // + inline vec_float4 getElem( int col, int row ) const; + + // Add two 4x4 matrices + // + inline const Matrix4 operator +( const Matrix4 & mat ) const; + + // Subtract a 4x4 matrix from another 4x4 matrix + // + inline const Matrix4 operator -( const Matrix4 & mat ) const; + + // Negate all elements of a 4x4 matrix + // + inline const Matrix4 operator -( ) const; + + // Multiply a 4x4 matrix by a scalar + // + inline const Matrix4 operator *( vec_float4 scalar ) const; + + // Multiply a 4x4 matrix by a 4-D vector + // + inline const Vector4 operator *( const Vector4 & vec ) const; + + // Multiply a 4x4 matrix by a 3-D vector + // + inline const Vector4 operator *( const Vector3 & vec ) const; + + // Multiply a 4x4 matrix by a 3-D point + // + inline const Vector4 operator *( const Point3 & pnt ) const; + + // Multiply two 4x4 matrices + // + inline const Matrix4 operator *( const Matrix4 & mat ) const; + + // Multiply a 4x4 matrix by a 3x4 transformation matrix + // + inline const Matrix4 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and addition with a 4x4 matrix + // + inline Matrix4 & operator +=( const Matrix4 & mat ); + + // Perform compound assignment and subtraction by a 4x4 matrix + // + inline Matrix4 & operator -=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix4 & operator *=( vec_float4 scalar ); + + // Perform compound assignment and multiplication by a 4x4 matrix + // + inline Matrix4 & operator *=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Matrix4 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 4x4 matrix + // + static inline const Matrix4 identity( ); + + // Construct a 4x4 matrix to rotate around the x axis + // + static inline const Matrix4 rotationX( vec_float4 radians ); + + // Construct a 4x4 matrix to rotate around the y axis + // + static inline const Matrix4 rotationY( vec_float4 radians ); + + // Construct a 4x4 matrix to rotate around the z axis + // + static inline const Matrix4 rotationZ( vec_float4 radians ); + + // Construct a 4x4 matrix to rotate around the x, y, and z axes + // + static inline const Matrix4 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix4 rotation( vec_float4 radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix4 rotation( const Quat & unitQuat ); + + // Construct a 4x4 matrix to perform scaling + // + static inline const Matrix4 scale( const Vector3 & scaleVec ); + + // Construct a 4x4 matrix to perform translation + // + static inline const Matrix4 translation( const Vector3 & translateVec ); + + // Construct viewing matrix based on eye position, position looked at, and up direction + // + static inline const Matrix4 lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ); + + // Construct a perspective projection matrix + // + static inline const Matrix4 perspective( vec_float4 fovyRadians, vec_float4 aspect, vec_float4 zNear, vec_float4 zFar ); + + // Construct a perspective projection matrix based on frustum + // + static inline const Matrix4 frustum( vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ); + + // Construct an orthographic projection matrix + // + static inline const Matrix4 orthographic( vec_float4 left, vec_float4 right, vec_float4 bottom, vec_float4 top, vec_float4 zNear, vec_float4 zFar ); + +}; +// Multiply a 4x4 matrix by a scalar +// +inline const Matrix4 operator *( vec_float4 scalar, const Matrix4 & mat ); + +// Append (post-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ); + +// Multiply two 4x4 matrices per element +// +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); + +// Compute the absolute value of a 4x4 matrix per element +// +inline const Matrix4 absPerElem( const Matrix4 & mat ); + +// Transpose of a 4x4 matrix +// +inline const Matrix4 transpose( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 inverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 affineInverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. +// +inline const Matrix4 orthoInverse( const Matrix4 & mat ); + +// Determinant of a 4x4 matrix +// +inline vec_float4 determinant( const Matrix4 & mat ); + +// Conditionally select between two 4x4 matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4x4 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat ); + +// Print a 4x4 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat, const char * name ); + +#endif + +// A set of four 3x4 transformation matrices in structure-of-arrays format +// +class Transform3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + Vector3 mCol3; + +public: + // Default constructor; does no initialization + // + inline Transform3( ) { }; + + // Copy a 3x4 transformation matrix + // + inline Transform3( const Transform3 & tfrm ); + + // Construct a 3x4 transformation matrix containing the specified columns + // + inline Transform3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2, const Vector3 & col3 ); + + // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + // + inline Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ); + + // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + // + inline Transform3( const Quat & unitQuat, const Vector3 & translateVec ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value + // + explicit inline Transform3( vec_float4 scalar ); + + // Replicate an AoS 3x4 transformation matrix + // + inline Transform3( const Aos::Transform3 & tfrm ); + + // Insert four AoS 3x4 transformation matrices + // + inline Transform3( const Aos::Transform3 & tfrm0, const Aos::Transform3 & tfrm1, const Aos::Transform3 & tfrm2, const Aos::Transform3 & tfrm3 ); + + // Extract four AoS 3x4 transformation matrices + // + inline void get4Aos( Aos::Transform3 & result0, Aos::Transform3 & result1, Aos::Transform3 & result2, Aos::Transform3 & result3 ) const; + + // Assign one 3x4 transformation matrix to another + // + inline Transform3 & operator =( const Transform3 & tfrm ); + + // Set the upper-left 3x3 submatrix + // + inline Transform3 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // + inline Transform3 & setTranslation( const Vector3 & translateVec ); + + // Get the translation component of a 3x4 transformation matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 3x4 transformation matrix + // + inline Transform3 & setCol0( const Vector3 & col0 ); + + // Set column 1 of a 3x4 transformation matrix + // + inline Transform3 & setCol1( const Vector3 & col1 ); + + // Set column 2 of a 3x4 transformation matrix + // + inline Transform3 & setCol2( const Vector3 & col2 ); + + // Set column 3 of a 3x4 transformation matrix + // + inline Transform3 & setCol3( const Vector3 & col3 ); + + // Get column 0 of a 3x4 transformation matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x4 transformation matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x4 transformation matrix + // + inline const Vector3 getCol2( ) const; + + // Get column 3 of a 3x4 transformation matrix + // + inline const Vector3 getCol3( ) const; + + // Set the column of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setCol( int col, const Vector3 & vec ); + + // Set the row of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setRow( int row, const Vector4 & vec ); + + // Get the column of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x4 transformation matrix referred to by column and row indices + // + inline Transform3 & setElem( int col, int row, vec_float4 val ); + + // Get the element of a 3x4 transformation matrix referred to by column and row indices + // + inline vec_float4 getElem( int col, int row ) const; + + // Multiply a 3x4 transformation matrix by a 3-D vector + // + inline const Vector3 operator *( const Vector3 & vec ) const; + + // Multiply a 3x4 transformation matrix by a 3-D point + // + inline const Point3 operator *( const Point3 & pnt ) const; + + // Multiply two 3x4 transformation matrices + // + inline const Transform3 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Transform3 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 3x4 transformation matrix + // + static inline const Transform3 identity( ); + + // Construct a 3x4 transformation matrix to rotate around the x axis + // + static inline const Transform3 rotationX( vec_float4 radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis + // + static inline const Transform3 rotationY( vec_float4 radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis + // + static inline const Transform3 rotationZ( vec_float4 radians ); + + // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + // + static inline const Transform3 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + // + static inline const Transform3 rotation( vec_float4 radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Transform3 rotation( const Quat & unitQuat ); + + // Construct a 3x4 transformation matrix to perform scaling + // + static inline const Transform3 scale( const Vector3 & scaleVec ); + + // Construct a 3x4 transformation matrix to perform translation + // + static inline const Transform3 translation( const Vector3 & translateVec ); + +}; +// Append (post-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ); + +// Multiply two 3x4 transformation matrices per element +// +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); + +// Compute the absolute value of a 3x4 transformation matrix per element +// +inline const Transform3 absPerElem( const Transform3 & tfrm ); + +// Inverse of a 3x4 transformation matrix +// NOTE: +// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. +// +inline const Transform3 inverse( const Transform3 & tfrm ); + +// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. +// +inline const Transform3 orthoInverse( const Transform3 & tfrm ); + +// Conditionally select between two 3x4 transformation matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, vec_uint4 select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x4 transformation matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm ); + +// Print a 3x4 transformation matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm, const char * name ); + +#endif + +} // namespace Soa +} // namespace Vectormath + +#include "vec_soa.h" +#include "quat_soa.h" +#include "mat_soa.h" + +#endif diff --git a/Extras/vectormathlibrary/tests/Makefile b/Extras/vectormathlibrary/tests/Makefile new file mode 100644 index 0000000..f1c8bc1 --- /dev/null +++ b/Extras/vectormathlibrary/tests/Makefile @@ -0,0 +1,138 @@ +# Makefile for vector math library testsuite. +# +# Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. +# 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 Sony Computer Entertainment Inc 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. + +topdir = .. + +ARCH = scalar + +TESTS_all = \ + test1_aos_c.elf \ + test1_soa_c.elf \ + test2_aos_c.elf \ + test2_soa_c.elf \ + test3_aos_c.elf \ + test3_soa_c.elf \ + test4_aos_c.elf \ + test4_soa_c.elf \ + test1_aos_cpp.elf \ + test1_soa_cpp.elf \ + test2_aos_cpp.elf \ + test2_soa_cpp.elf \ + test3_aos_cpp.elf \ + test3_soa_cpp.elf \ + test4_aos_cpp.elf \ + test4_soa_cpp.elf + +TESTS_ppu = $(TESTS_all) +ARCH_CFLAGS_ppu = -maltivec -mabi=altivec -I$(SIMDMATH_DIR)/common +ARCH_LDFLAGS_ppu = -L$(SIMDMATH_DIR)/ppu -lsimdmath -static + +CROSS_spu = spu- +TESTS_spu = $(TESTS_all) +ARCH_CFLAGS_spu = -I$(SIMDMATH_DIR)/common +ARCH_LDFLAGS_spu = -L$(SIMDMATH_DIR)/spu -lsimdmath + +TESTS_SSE = \ + test1_aos_cpp.elf \ + test2_aos_cpp.elf \ + test3_aos_cpp.elf \ + test4_aos_cpp.elf +ARCH_CFLAGS_SSE = -msse + +TESTS_scalar = \ + test1_aos_c.elf \ + test2_aos_c.elf \ + test3_aos_c.elf \ + test4_aos_c.elf \ + test1_aos_cpp.elf \ + test2_aos_cpp.elf \ + test3_aos_cpp.elf \ + test4_aos_cpp.elf + +TESTS = $(TESTS_$(ARCH)) +ARCH_CFLAGS = $(ARCH_CFLAGS_$(ARCH)) +ARCH_LDFLAGS = $(ARCH_LDFLAGS_$(ARCH)) + +SIMDMATH_DIR = $(topdir)/../simdmathlibrary + +RESULTS = $(TESTS:.elf=.$(ARCH).out) +DIFFS = $(RESULTS:.out=.cmp) + +CROSS = $(CROSS_$(ARCH)) +CC = $(CROSS)gcc +CXX = $(CROSS)g++ +LD = $(CC) +LDXX = $(CXX) + +CFLAGS = -O2 -W -Wall -D_VECTORMATH_DEBUG $(ARCH_CFLAGS) +LDFLAGS = -lm $(ARCH_LDFLAGS) + +C_INCLUDES = -I$(topdir)/include/vectormath/c +CXX_INCLUDES = -I$(topdir)/include/vectormath/cpp + +PERL = perl + +all: $(TESTS) + +check: $(DIFFS) + +clean: + -rm -f *.elf + +distclean: clean + -rm -f *.out *.cmp *~ + +%_c.elf: %_c.c + $(CC) $(CFLAGS) $(C_INCLUDES) -o $@ $< $(LDFLAGS) + +%_cpp.elf: %_cpp.cpp + $(CXX) $(CFLAGS) $(CXX_INCLUDES) -o $@ $< $(LDFLAGS) + +%.$(ARCH).out: %.elf + ./$< > $@ + +test1_%.cmp: test1_%.out + $(PERL) ./clean.pl < $< > $<.tmp + $(PERL) ./compare.pl $<.tmp test1_reference.txt | tee $@ + rm $<.tmp + +test2_%.cmp: test2_%.out + $(PERL) ./clean.pl < $< > $<.tmp + $(PERL) ./compare.pl $<.tmp test2_reference.txt | tee $@ + rm $<.tmp + +test3_%.cmp: test3_%.out + $(PERL) ./clean.pl < $< > $<.tmp + $(PERL) ./compare.pl $<.tmp test3_reference.txt | tee $@ + rm $<.tmp + +test4_%.cmp: test4_%.out + $(PERL) ./clean.pl < $< > $<.tmp + $(PERL) ./compare.pl $<.tmp test4_reference.txt | tee $@ + rm $<.tmp diff --git a/Extras/vectormathlibrary/tests/clean.pl b/Extras/vectormathlibrary/tests/clean.pl new file mode 100644 index 0000000..412f596 --- /dev/null +++ b/Extras/vectormathlibrary/tests/clean.pl @@ -0,0 +1,109 @@ +#!/usr/bin/perl + +# +# Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. +# 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 Sony Computer Entertainment Inc 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. +# + +$lineno = 0; + +sub getLine +{ + local( $line ); + + $line = ; + + while( $line =~ m/^lv2\([^\)]*\)\:$/ ) + { + $line = ; + } + + $line =~ s/^lv2\([^\)]*\)\: //; + + return $line; +} + +while(($line = ) !~ m/__begin__/) +{ +} + +$countSlotLines = 0; + +while( $line = &getLine ) +{ + $lineno++; + + if ( $line =~ m/__end__/ ) + { + exit; + } + + # if soa print, only save first slot + + if ( $line =~ m/^slot ([1-3])/ ) + { + while ( $line =~ m/^slot [1-3]/ ) + { + # skip all lines for this slot + + for ( $i = 0; $i < $slotLines; $i++ ) + { + $line = &getLine; + } + + # get next line + + $line = &getLine; + } + + # stop counting slot lines + + $countSlotLines = 0; + } + elsif ( $countSlotLines ) + { + $slotLines++; + } + + if ( $line =~ m/^slot 0\:(.?)/ ) + { + $countSlotLines = 1; + + if ( $1 eq ' ' ) + { + $line =~ s/^slot 0\: //; + $slotLines = 0; + } + else + { + $line = &getLine; + $slotLines = 1; + } + } + + print $line; +} diff --git a/Extras/vectormathlibrary/tests/compare.pl b/Extras/vectormathlibrary/tests/compare.pl new file mode 100644 index 0000000..ed4c929 --- /dev/null +++ b/Extras/vectormathlibrary/tests/compare.pl @@ -0,0 +1,95 @@ +#!/usr/bin/perl + +# +# Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. +# 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 Sony Computer Entertainment Inc 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. +# + +$file1 = $ARGV[0]; +$file2 = $ARGV[1]; + +if (!open(FILE1, "<$file1")) +{ + print "Couldn't open $file1\n"; + exit; +} + +if (!open(FILE2, "<$file2")) +{ + print "Couldn't open $file2\n"; + exit; +} + +print "Comparing $file1 $file2\n"; + +$lineno1 = 0; +$lineno2 = 0; + +while(($line1 = ) && ($line2 = )) +{ + $lineno1++; + $lineno2++; + + if ( $line1 =~ m/\:$/ ) + { + $line1 = ; + $lineno1++; + } + + if ( $line2 =~ m/\:$/ ) + { + $line2 = ; + $lineno2++; + } + + $line1 =~ s/^.*\: //g; + $line2 =~ s/^.*\: //g; + + @words1 = split(/ /,$line1); + @words2 = split(/ /,$line2); + + for ($i = 0; $i < @words1; $i++) + { + $word1 = $words1[$i]; + $word2 = $words2[$i]; + + $word1 =~ s/\s//g; + $word2 =~ s/\s//g; + + if ( $word1 ne $word2 ) + { + $error = abs($word1 - $word2); + + $limit = abs(1e-4 * $word1); + + if ( $error > $limit && !( abs($word1) < 1e-4 && $error < 1e-4 ) ) + { + print "$lineno1: $word1 $lineno2: $word2\n"; + } + } + } +} diff --git a/Extras/vectormathlibrary/tests/main_vmtest.cpp b/Extras/vectormathlibrary/tests/main_vmtest.cpp new file mode 100644 index 0000000..2e8262b --- /dev/null +++ b/Extras/vectormathlibrary/tests/main_vmtest.cpp @@ -0,0 +1,163 @@ + +///Testfile to test differences between vectormath and Bullet LinearMath + +#ifdef __PPU__ +#include "include/vectormath/ppu/cpp/vectormath_aos.h" +#elif defined __SPU__ +#include "include/vectormath/spu/cpp/vectormath_aos.h" +#else +#include "include/vectormath/SSE/cpp/vectormath_aos.h" +//#include "include/vectormath/scalar/cpp/vectormath_aos.h" +#endif + +#include "../../src/LinearMath/btTransform.h" +#include + +//Bullet, a btVector can be used for both points and vectors. +//it is up to the user/developer to use the right multiplication: btTransform for points, and btQuaternion or btMatrix3x3 for vectors. +void BulletTest() +{ + + printf("Bullet Linearmath\n"); + + btTransform tr; + tr.setIdentity(); + + tr.setOrigin(btVector3(10,0,0)); + //initialization + btVector3 pointA(0,0,0); + btVector3 pointB,pointC,pointD,pointE; + //assignment + pointB = pointA; + //in-place initialization + pointB.setValue(1,2,3); + //transform over tr + pointB = tr * pointA; + printf("pointB = tr * pointA = (%f,%f,%f)\n",pointB.getX(),pointB.getY(),pointB.getZ()); + //transform over tr + pointE = tr(pointA); + //inverse transform + pointC = tr.inverse() * pointA; + printf("pointC = tr.inverse() * pointA = (%f,%f,%f)\n",pointC.getX(),pointC.getY(),pointC.getZ()); + //inverse transform + pointD = tr.invXform( pointA ); + btScalar x; + //dot product + x = pointD.dot(pointE); + //square length + x = pointD.length2(); + //length + x = pointD.length(); + + const btVector3& constPointD = pointD; + + //get a normalized vector from constPointD, without changing constPointD + btVector3 norm = constPointD.normalized(); + + //in-place normalize pointD + pointD.normalize(); + + //quaternions & matrices + btQuaternion quat(0,0,0,1); + btQuaternion quat1(btVector3(0,1,0),90.f * SIMD_RADS_PER_DEG); + btMatrix3x3 mat0(quat1); + btMatrix3x3 mat1 = mat0.inverse(); + btMatrix3x3 mat2 = mat0.transpose(); + btTransform tr1(mat2,btVector3(0,10,0)); + btTransform tr2 =tr1.inverse(); + btVector3 pt0(1,1,1); + btVector3 pt1 = tr2 * pt0; + + printf("btVector3 pt1 = tr2 * pt0 = (%f,%f,%f)\n",pt1.getX(),pt1.getY(),pt1.getZ()); + + + btVector3 pt2 = tr2.getBasis() * pt0; + btVector3 pt3 = pt0 * tr2.getBasis(); + btVector3 pt4 = tr2.getBasis().inverse() * pt0; + btTransform tr3 = tr2.inverseTimes(tr2); + + + +} + +//vectormath makes a difference between point and vector. +void VectormathTest() +{ + + printf("Vectormath\n"); + + Vectormath::Aos::Transform3 tr; + tr = Vectormath::Aos::Transform3::identity(); + + tr.setTranslation(Vectormath::Aos::Vector3(10,0,0)); + //initialization + Vectormath::Aos::Point3 pointA(0,0,0); + Vectormath::Aos::Point3 pointB,pointC,pointE; + Vectormath::Aos::Vector3 pointD; + //assignment + pointB = pointA; + //in-place initialization + pointB = Vectormath::Aos::Point3(1,2,3); //or + pointB.setElem(0,1); //or + pointB.setX(1); + + //transform over tr + pointB = tr * pointA; + + printf("pointB = tr * pointA = (%f,%f,%f)\n",(float)pointB.getX(),(float)pointB.getY(),(float)pointB.getZ()); + //transform over tr + //pointE = tr(pointA); + //inverse transform + pointC = Vectormath::Aos::inverse(tr) * pointA; + printf("Vectormath::Aos::inverse(tr) * pointA = (%f,%f,%f)\n",(float)pointC.getX(),(float)pointC.getY(),(float)pointC.getZ()); + + + + btScalar x; + //dot product + x = Vectormath::Aos::dot(Vectormath::Aos::Vector3(pointD),Vectormath::Aos::Vector3(pointE)); + //square length + x = Vectormath::Aos::lengthSqr(Vectormath::Aos::Vector3(pointD)); + //length + x = Vectormath::Aos::length(Vectormath::Aos::Vector3(pointD)); + + const Vectormath::Aos::Vector3& constPointD = (Vectormath::Aos::Vector3&)pointD; + + //get a normalized vector from constPointD, without changing constPointD + Vectormath::Aos::Vector3 norm = Vectormath::Aos::normalize(constPointD); + + //in-place normalize pointD + pointD = Vectormath::Aos::normalize(Vectormath::Aos::Vector3(pointD)); + + //quaternions & matrices + Vectormath::Aos::Quat quat(0,0,0,1); + Vectormath::Aos::Quat quat1; + quat1 = Vectormath::Aos::Quat::rotationY(90.f * SIMD_RADS_PER_DEG); + + Vectormath::Aos::Matrix3 mat0(quat1); + + Vectormath::Aos::Matrix3 mat1 = Vectormath::Aos::inverse(mat0); + Vectormath::Aos::Matrix3 mat2 = Vectormath::Aos::transpose(mat0); + Vectormath::Aos::Transform3 tr1(mat2,Vectormath::Aos::Vector3(0,10,0)); + Vectormath::Aos::Transform3 tr2 = Vectormath::Aos::inverse(tr1); + Vectormath::Aos::Point3 pt0(1,1,1); + Vectormath::Aos::Point3 pt1 = tr2 * pt0; + printf("Vectormath::Aos::Vector3 pt1 = tr2 * pt0; = (%f,%f,%f)\n",(float)pt1.getX(),(float)pt1.getY(),(float)pt1.getZ()); + + Vectormath::Aos::Vector3 pt2 = tr2.getUpper3x3() * Vectormath::Aos::Vector3(pt0); + //Vectormath::Aos::Vector3 pt3 = pt0 * tr2.getUpper3x3(); + Vectormath::Aos::Vector3 pt3 = Vectormath::Aos::inverse(tr2.getUpper3x3()) * Vectormath::Aos::Vector3(pt0); + Vectormath::Aos::Vector3 pt4 = Vectormath::Aos::inverse(tr2.getUpper3x3()) * Vectormath::Aos::Vector3(pt0); + Vectormath::Aos::Transform3 tr3 = Vectormath::Aos::inverse(tr2) * tr2; + +} + +int main() +{ + + BulletTest(); + + VectormathTest(); + + return 0; +} diff --git a/Extras/vectormathlibrary/tests/test.h b/Extras/vectormathlibrary/tests/test.h new file mode 100644 index 0000000..bc231ea --- /dev/null +++ b/Extras/vectormathlibrary/tests/test.h @@ -0,0 +1,346 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_TEST_H +#define _VECTORMATH_TEST_H + +#if defined(__SPU__) +# define vec_splats_float(v) spu_splats(v) +# define vec_mul_float(a, b) spu_mul(a, b) +# define vec_add_float(a, b) spu_add(a, b) +# define vec_sub_float(a, b) spu_sub(a, b) +#elif defined(__ALTIVEC__) +# define vec_splats_float(v) ((vec_float4){(float)(v),(float)(v),(float)(v),(float)(v)}) +# define vec_mul_float(a, b) vec_madd(a, b, vec_splats_float(0.0f)) +# define vec_add_float(a, b) vec_add(a, b) +# define vec_sub_float(a, b) vec_sub(a, b) +#elif defined(__SSE__) +# error "Not implemented." +#else +# define _VECTORMATH_SCALAR_TEST +#endif + +float randfloats[1024] = { + -0.658343927787421f,0.499803960969928f,-0.807256688752865f,0.740930454054151f, + 0.154607013590216f,0.571598517679348f,0.38438830691728f,-0.262467460159158f, + 0.747808153723618f,0.49019019690013f,-0.107908181813777f,-0.292543593813249f, + 0.465039264005078f,-0.47955599783424f,-0.211412450152245f,0.553579902451233f, + 0.690070275160572f,0.151576400965553f,0.431077190337326f,-0.833991507852247f, + -0.0883497426804851f,-0.780106371638709f,0.0904560476331469f,-0.218626858702649f, + 0.137170846428894f,0.918132898976751f,0.735438192918274f,-0.673620979495283f, + -0.448982146263369f,-0.479277810255866f,0.848189483738331f,-0.12815472579463f, + 0.578921731104181f,-0.744765966376519f,-0.83558862791913f,0.881284032895692f, + -0.948850147493964f,-0.691578137344351f,-0.235635149443688f,-0.690526600666615f, + 0.0586668362339609f,0.753696982166502f,-0.138777123323202f,-0.472187547315841f, + -0.372811001953572f,0.540183371709446f,-0.78521823389179f,0.542084510391291f, + 0.410391117788897f,-0.562720682584484f,0.523587985711991f,-0.176573908842087f, + 0.297653645858226f,0.859912509814734f,0.00483713119734119f,0.374881358857735f, + -0.127818103705344f,0.21660181589948f,0.153117267270737f,0.265243421428139f, + -0.0731487047425148f,0.264487579220173f,-0.723410134701346f,0.921522835850382f, + -0.711249997824318f,-0.106633857864438f,-0.350831080309241f,0.905168155184938f, + -0.283632179037646f,-0.203583555015513f,-0.797436915535236f,0.910171471305759f, + 0.96923389534215f,0.151940162902974f,0.731827470770519f,-0.700248217534451f, + 0.818300860563319f,0.302505017280083f,-0.872278290470156f,0.909998773124912f, + 0.932525528551317f,0.571086770427939f,0.610329635790002f,0.142507359591505f, + -0.43482856009151f,0.925102103935927f,0.158954117892613f,-0.126282746058862f, + -0.249127650925452f,0.846815218386041f,-0.942601239873774f,0.537719955431001f, + 0.446213543435171f,0.181938699625931f,-0.148222922840326f,0.284286118166037f, + 0.493525458201255f,-0.861962900371793f,-0.893410102755276f,0.548627291142694f, + 0.407006961478977f,-0.757467096890906f,-0.393126176069536f,-0.850984293029867f, + 0.375719573110992f,-0.270087780463427f,0.45888819784826f,-0.610827766442796f, + -0.690815628408266f,-0.676415221072347f,0.664465776005038f,0.101873923854313f, + -0.365713939355025f,0.0554727439164822f,-0.133556089035984f,-0.572643072647438f, + 0.459209235899415f,-0.997261395030506f,0.172408991295974f,-0.0451240115316551f, + 0.879715937508259f,0.524317125330867f,-0.744532077249495f,-0.970443523820151f, + -1.32784686215359e-05f,0.689543072301063f,0.704297111725616f,-0.817983008667298f, + 0.71550535643383f,0.577868436783262f,0.156952383805468f,-0.80102179210472f, + 0.65633547615213f,0.494393128677046f,0.816743155389922f,0.0242848471199721f, + 0.769131722839866f,0.923894866655701f,0.133021600755988f,-0.0522193159450097f, + -0.164886284373118f,0.300690282133047f,0.760403145270168f,0.171869369152077f, + -0.554975788488598f,0.998693253807744f,-0.681641007087912f,0.391194738828759f, + 0.403058705852153f,0.972411306067528f,0.297195187773745f,0.309761312769567f, + 0.688408077837671f,0.363539666742895f,0.94029653976505f,-0.336683042511069f, + 0.600164345782652f,-0.681271587780742f,0.726558239385319f,0.205513360229233f, + -0.16008221686365f,0.962714155748642f,0.737793770111715f,-0.0719258703692134f, + -0.506312816314299f,0.689277082946518f,0.686485424709581f,0.473013144786293f, + -0.735610421404026f,-0.0463900680836105f,0.568673968586005f,-0.00481466271939723f, + 0.137636823654454f,-0.111879120785687f,-0.929542605813147f,-0.336303463382606f, + -0.146740182632236f,0.165140351947514f,-0.823874099621072f,0.349776463047661f, + 0.174872304411146f,-0.528584334304156f,0.489291834762803f,0.916707538240686f, + 0.728510889338118f,-0.851139787348188f,0.0796199799283031f,-0.234369971523549f, + -0.996308342568362f,0.433228819394486f,-0.892684128206504f,-0.95791073791078f, + 0.517122298113016f,0.257920984044574f,0.862028434359466f,0.0958813977553206f, + -0.171932523577503f,-0.214077886807473f,-0.604841274532937f,-0.38383141210609f, + -0.58149997525441f,0.222182734948547f,-0.2561203625418f,-0.678699493062183f, + -0.0795530448181339f,0.605960090732907f,-0.633147389976791f,0.435875222532317f, + -0.0466270522618899f,-0.71649136999298f,0.267317414957141f,-0.514873596167021f, + -0.751699524124625f,0.742958874040227f,-0.793179510948171f,0.508814009999512f, + -0.238839286150373f,0.113471002014307f,-0.843523253083085f,-0.245249991279181f, + 0.250368454758338f,0.579243470287253f,-0.157280074848025f,0.648487464157242f, + 0.103833079240538f,0.456401128469849f,-0.0223720820167514f,-0.475631368950744f, + -0.0041782226245104f,-0.0208652308868125f,-0.0169971127675765f,0.699143621917685f, + 0.83779636548531f,-0.276082033737794f,0.0915817913013015f,0.209063902268738f, + 0.219316780269516f,-0.118359453100055f,0.413442003735092f,-0.567697560481989f, + 0.531358299984625f,-0.387225776610819f,0.572489506868486f,-0.820417090039186f, + 0.797191361229615f,0.867177919412683f,0.934764375062564f,0.237092079542023f, + -0.866161864691826f,-0.773938728379676f,0.261310530107004f,-0.851569556583101f, + 0.114814425111355f,-0.531592190789155f,0.223924683490957f,0.869104561345111f, + 0.143404566999386f,0.148517529008075f,-0.0711363985626363f,-0.758291614176514f, + -0.527633502740933f,0.99721511923596f,0.114439963849399f,0.72755837253878f, + -0.425760405626697f,0.459888066153781f,0.642515762634126f,-0.0225335867899474f, + 0.186094961562027f,-0.775678571017551f,-0.683400976752644f,0.398133764191002f, + 0.189642093838877f,0.765986315134853f,-0.137794739254879f,-0.579843714684088f, + -0.63564699482432f,0.374970154657689f,-0.563749876868947f,-0.471075422601373f, + -0.553799500723066f,-0.0146881150006948f,-0.464365244644604f,-0.10788986146774f, + -0.527503023060852f,-0.406422760262416f,0.301261161950258f,0.499528573888128f, + 0.385179609005043f,-0.150218387266079f,0.519111879977139f,-0.203208683924331f, + -0.252017508479717f,0.282193567323901f,0.0676372217166588f,0.798376368300907f, + 0.310782163860559f,0.861334103612307f,-0.980345166653173f,-0.655105604450725f, + 0.286765236319503f,0.532078410709602f,0.352670966735097f,0.540977184819425f, + 0.510961465933072f,0.791871139829084f,-0.564378698589145f,0.273199199047909f, + 0.194378063163676f,0.244636363558442f,-0.2696079922111f,-0.858162214209599f, + -0.495023067522474f,-0.277797538673553f,-0.0327403642191157f,0.00741169596342672f, + -0.420178428178723f,-0.522576683894926f,0.324971970060567f,0.795389045001329f, + 0.342900104539247f,-0.913636452280628f,0.675221839440177f,0.144052833646484f, + -0.632328982629893f,-0.947119831218089f,-0.0493673719309484f,0.126332763266575f, + -0.66420574517786f,0.220879155225703f,0.284218535482147f,-0.387215543918998f, + 0.913567998448777f,0.531906099678991f,0.271995095904906f,-0.862600551020719f, + -0.738693635668703f,0.514248487507359f,-0.0393632803376036f,0.429389595727585f, + -0.769468991576751f,0.28133632724311f,-0.203301313955485f,0.412585911285348f, + 0.567925862321268f,0.410131004328946f,-0.462918277454527f,0.560952548692129f, + -0.731715443500342f,-0.446157565377547f,-0.837491324975311f,-0.573480361464263f, + -0.607819850918752f,0.23841499693998f,0.213445432027605f,0.0986122683758737f, + 0.135072190814675f,-0.749273552937012f,-0.855977160741141f,0.765675059673342f, + -0.693447453911567f,0.131554184087008f,-0.366756547983336f,-0.330409262236842f, + -0.588815619465343f,0.352532978762866f,-0.920522750723883f,-0.915255088789323f, + 0.631923943060777f,-0.870739292438145f,0.415604498050605f,-0.180973894496887f, + 0.775697838994837f,0.879356890591083f,-0.993957564335638f,-0.298451942545356f, + 0.876855036440425f,0.982846031192253f,-0.282564044364371f,0.95346849594155f, + -0.947311505090191f,-0.317822974923359f,0.692391664998802f,-0.123566763365389f, + 0.407041678839057f,0.141204372181107f,-0.793069847914673f,-0.638275471740698f, + -0.51955405631346f,0.368499710074474f,0.970213689037045f,0.0272163305900648f, + 0.801791483976395f,-0.0663635812993562f,-0.0512834823579524f,-0.184935295126749f, + 0.516982835871183f,-0.769951152485618f,-0.708267044537941f,0.398266880674086f, + -0.479614543356881f,0.0604142126476859f,-0.867394563338259f,-0.702364045743693f, + -0.18260171523908f,-0.83280747136078f,0.278190893454216f,-0.967562302471109f, + -0.52029595778054f,0.160191201466318f,-0.677989785356466f,-0.470750261667419f, + -0.846579999787899f,-0.705750757861409f,-0.825367487626302f,-0.712890462610304f, + -0.0644873847193068f,0.444064587944183f,-0.0452257881147275f,0.116544259603998f, + -0.00728451932408092f,-0.838230133415692f,-0.410766823165496f,-0.40929905742685f, + -0.336682948179195f,-0.830699768111344f,-0.801729180453698f,-0.595152571835385f, + -0.784671779507129f,-0.653655236426147f,0.670791046451306f,0.653571468806589f, + 0.850715654625567f,0.0714334825891569f,-0.0577154211012854f,0.401895373758876f, + 0.0168605144772656f,0.5354384129881f,0.965901293540405f,-0.0726753529456374f, + 0.341689326326282f,0.781662445971847f,0.707322369548329f,0.505889413040066f, + 0.43279006682301f,-0.82579284323046f,0.597718837056043f,-0.250904847502525f, + -0.085712490334565f,-0.27284668464705f,0.552644217406645f,0.19420250718521f, + -0.884426763638054f,-0.756791257372726f,0.121106956043313f,0.312482778322803f, + -0.873316960494485f,0.0450805196969668f,0.687443898195021f,-0.684625629977333f, + -0.994046624794031f,0.800365484075002f,-0.565640229111075f,-0.625626063021869f, + 0.932584676112249f,0.636927568286012f,0.420250137262336f,0.175862511828669f, + 0.362158342804186f,0.547495978208275f,-0.534422794348934f,-0.563030463450744f, + -0.254488285756501f,0.647777595706543f,-0.674240168502628f,0.224344628949055f, + -0.754563097553635f,-0.12881655237274f,-0.997838330250381f,0.0369162049154141f, + -0.077549312424928f,0.376025736059717f,-0.935044655882827f,-0.189804125597547f, + 0.00764933224392195f,-0.440298102088747f,0.994796322297979f,-0.271484040660724f, + -0.2590701870053f,0.902148580301628f,-0.836501451887365f,0.229092669621153f, + 0.5863932076197f,-0.287825592948792f,0.942655407357726f,-0.634432455852235f, + -0.140437555704573f,0.570869095619685f,-0.764965080867434f,0.0675228424859284f, + -0.514589062662218f,0.233090988246516f,0.554487773397391f,-0.633529215840056f, + -0.0193735702003366f,0.869258510751365f,-0.369818396412519f,-0.280689998188947f, + -0.797208739895403f,-0.255233407527697f,0.780605315236578f,0.789803426518219f, + 0.974261893445153f,-0.785980203848396f,-0.701385987245636f,0.871088183435759f, + 0.566742533772562f,0.75227294222347f,-0.476301298243307f,-0.747341931420877f, + 0.0773855838641069f,-0.305599507084935f,-0.229193881336336f,-0.260009071921601f, + -0.0515187258224827f,0.459831012841761f,0.861793377659517f,-0.00839510548009059f, + -0.0535644390132504f,0.912885769359548f,-0.402379747450233f,-0.10435292389046f, + 0.644045025641198f,-0.235395897167933f,0.454549452554879f,-0.303775931682779f, + 0.321575614700528f,0.724025709176772f,0.330082831646187f,0.609903689400269f, + 0.851604270169993f,-0.356715440425745f,-0.0455002843413084f,0.13772975575408f, + -0.148995564903764f,0.892453960056798f,-0.821676934893254f,-0.14847536459807f, + -0.381886292618752f,0.398820351836747f,-0.292289360617424f,0.0702858731114446f, + -0.772469821167697f,0.474357996692333f,0.857792314833965f,-0.720558506386439f, + 0.888908862188352f,-0.950919194501893f,-0.196258139903655f,-0.59980821479941f, + -0.794413298851502f,-0.927635622930836f,-0.18747758800405f,-0.113038430406718f, + 0.366119602275866f,-0.483786056117111f,0.622670249344587f,-0.801805699607442f, + 0.295383348060291f,0.0220054959489744f,-0.000678144987013241f,-0.68933407333013f, + 0.266537772395942f,-0.785099000882013f,-0.572664686201399f,0.772760435300924f, + 0.97189582826514f,-0.961362535549199f,0.723449439795125f,-0.758441529489218f, + -0.733158222482722f,0.13966678591575f,-0.73814671277507f,0.727223546774141f, + 0.0899213092919311f,-0.113118130362636f,-0.364554501988017f,-0.137644753297124f, + 0.933846571857863f,0.615857754190102f,0.442837902751755f,0.691293553853697f, + 0.862436507424839f,-0.769632706987466f,-0.069558455823973f,-0.216368763497925f, + -0.240286864167238f,-0.494147338088084f,-0.732343541285623f,0.247500097354347f, + 0.238013165932848f,-0.0222504081638135f,0.0354097573205863f,0.562870060908224f, + -0.443182852051812f,-0.148476065390099f,-0.785559583638936f,-0.534284390277335f, + 0.804060941136193f,0.161693072162677f,0.626454348053834f,0.564290128221401f, + 0.414242183673117f,-0.314079097076757f,0.871460392700492f,-0.586016607169839f, + 0.446183340840953f,0.670697807509214f,-0.31261251323f,-0.34635111476409f, + -0.32237160168031f,0.0615992346122596f,0.108866036772035f,-0.96854607364277f, + -0.0900520153269255f,-0.000638517939648864f,-0.497526906200939f,0.0210549572282304f, + -0.513626724036349f,0.219974002433304f,-0.406318097379831f,0.829310754424156f, + 0.139888080843043f,-0.409132737685127f,-0.0296375827238435f,-0.713853913104842f, + 0.286946651436075f,-0.734473045715816f,0.649341057254212f,0.0281454231254514f, + -0.188432361127518f,-0.683807673918693f,0.432885949511977f,-0.0361810926016091f, + 0.438347837417645f,0.710651677026334f,0.673928786874676f,-0.0546809333762468f, + 0.826058562813905f,-0.832265197271681f,-0.668493142354613f,0.35502470967181f, + 0.5354983136667f,0.82137347039f,-0.143300610352533f,0.713426364459551f, + -0.297806605505109f,0.340760003596245f,-0.564118270640485f,-0.0240265108522948f, + -0.60137093958766f,-0.178866127631323f,-0.229680331692812f,0.741055717732976f, + -0.219526898682084f,0.534269946476002f,0.133115059442581f,-0.249583317941799f, + 0.811487242943805f,0.699282902509054f,-0.43331663912921f,0.71961761681392f, + 0.943524928147106f,0.523603303061634f,-0.677065472025312f,-0.636492873531878f, + 0.0384525794274069f,-0.377124785497273f,0.967031372742831f,0.435091298236713f, + 0.161520957813146f,-0.15972397671726f,-0.166845254078147f,-0.587937091804449f, + 0.910419348982238f,0.764819474485904f,-0.987496701506423f,-0.838882086564368f, + -0.41301635023239f,0.740276015423035f,0.951437768918503f,0.284889876776347f, + -0.158434377954073f,0.73838340645338f,-0.370863653408783f,0.989946556977472f, + -0.848079748582045f,-0.449771614068709f,0.663499305019705f,-0.93185425837116f, + 0.523896920061681f,-0.232489928806984f,-0.538281594630583f,-0.899682373052556f, + -0.338756398325579f,0.951550867830917f,0.494550167204373f,0.194556783574981f, + 0.243717136517866f,0.224354070146973f,0.143792613511486f,-0.333553884855363f, + 0.229952471240104f,-0.204077808365582f,0.469903146410694f,-0.958373658125808f, + -0.226054823628623f,0.229899490605959f,0.196501423332386f,0.879845549743308f, + 0.577560209175438f,0.641089277668982f,0.642316105885037f,0.232802361926147f, + -0.381538604113949f,0.640474533642731f,-0.913151229860155f,-0.614188561923768f, + 0.171776090268345f,-0.645757746280538f,-0.122217277374411f,0.00689941379876302f, + 0.019433549917359f,-0.0675691088088968f,-0.373650414044171f,-0.67103881780362f, + 0.504459382741295f,-0.14911057310502f,0.148122926701966f,0.694898716737626f, + 0.585837578674649f,-0.750790936323284f,0.853926520879604f,0.15730556487317f, + -0.113618219173468f,0.320367463625416f,-0.552134285767956f,-0.920422170186882f, + -0.338845809007829f,-0.810536065394189f,-0.177695639626343f,0.351905028679525f, + 0.0633494717407146f,-0.865174843305965f,0.634557634797282f,-0.787750206138512f, + -0.379512173859858f,0.791878043518267f,-0.704956748246282f,-0.670757904173982f, + 0.684751731590218f,-0.953277716787511f,0.985770879077755f,0.122219634876117f, + 0.1721202012071f,-0.388256876288864f,-0.73825752183587f,0.906019401398325f, + -0.803381430261645f,-0.74941181755554f,0.0727255174881734f,-0.221605735994771f, + -0.564223723915198f,-0.213656403861052f,-0.608162856680174f,0.921170937654253f, + 0.0847855661657562f,0.417987807384179f,-0.330418934403873f,0.648809934312297f, + 0.0796460930869003f,0.550628835897015f,-0.92719924470385f,0.877452232036589f, + 0.559779671355166f,-0.0896538710039181f,0.849093177103803f,-0.747330460544603f, + -0.87952842676733f,0.791614152693995f,-0.483542677352212f,0.795053306558017f, + -0.246444636768096f,-0.967515102978155f,0.159471890174437f,0.210810164441753f, + -0.874227023772981f,-0.0805964482800334f,0.567497201138046f,-0.137743608785641f, + -0.710773819308763f,-0.589571113738941f,0.83391847788473f,0.474349423613731f, + -0.495444643831966f,-0.415319533683743f,-0.688818445640273f,0.923238489082379f, + 0.688452278243922f,-0.639758117768224f,0.353458578584501f,-0.352412753977475f, + -0.667399029986676f,0.586965778853283f,0.352610916528867f,0.360697015758419f, + -0.502839728688848f,-0.539644214882799f,0.365329906944815f,-0.379932106654209f, + -0.269280779163601f,0.694895571222645f,0.727823970732565f,0.51105486079409f, + -0.761212733299821f,-0.551940664095241f,0.953323471475834f,-0.915964879494524f, + 0.199091342904332f,0.0392241713497299f,-0.19261671908783f,-0.6074206562147f, + 0.345256597791838f,0.031516093623793f,0.563117849295644f,-0.0626584858579093f, + -0.491887339392029f,-0.758788812866925f,0.265995340863064f,0.23182766277084f, + 0.069408408971249f,-0.758115582411847f,-0.495213306068685f,-0.941798830898321f, + -0.244099121724069f,-0.496495655783264f,0.217102928532306f,-0.958590442403207f, + -0.951376141167081f,-0.454184666450089f,0.886300276933433f,0.487002988091731f, + 0.0249044829036293f,-0.482416930998085f,0.949278378895364f,0.332136035903019f, + 0.667897336691517f,-0.903192712329542f,0.0759824890853551f,-0.338269985337703f, + -0.29518903317139f,-0.768719116695905f,-0.648362986306786f,0.935201134387952f, + 0.661626711929564f,0.224599917215244f,0.348525351988449f,-0.972641665331466f, + 0.996220202383405f,-0.72814219793807f,-0.921619408688976f,-0.134878186992026f, + 0.496907260713279f,0.544992091878385f,0.238303715804555f,-0.924062793629034f, + -0.630686074442814f,-0.865452949495847f,-0.222028734920293f,0.171739204767604f, + 0.997130539607845f,0.918172604643416f,-0.694626556063078f,0.672880204329672f, + -0.175982089302543f,-0.876546457819273f,-0.699672836718442f,0.809662568756764f, + 0.393205100623341f,-0.108144983913576f,-0.486322989569125f,-0.613674712751319f, + -0.317080956716971f,0.471134684264513f,-0.30417867085874f,0.696115419091356f, + -0.469268432777419f,0.236211281027806f,-0.772378939124543f,0.460249824926805f, + -0.654534877200454f,-0.934852798470303f,0.032756384083477f,-0.66677857258658f, + 0.314980215822125f,-0.289198088561079f,-0.0476688874127049f,0.0583547444711741f, + 0.941740852748786f,0.774296795413221f,-0.414622097461695f,0.638345821607103f, + -0.358465167682304f,-0.700596445490135f,0.374529194857949f,0.45456008092971f, + -0.853620900176985f,0.494280579565469f,-0.217619888424174f,0.956186128386705f, + 0.0389822381652678f,-0.19316201021536f,0.00512085504598048f,-0.0427176575011998f, + 0.547932129275615f,0.721865358296469f,0.456248153651011f,0.618884232413038f, + 0.0410425055490649f,-0.0673903257300594f,-0.218781418704999f,0.528492225462415f, + -0.0837068514807342f,0.718697939323846f,-0.603328224259776f,0.875509849594366f, + -0.0909494938322766f,-0.280637910576161f,-0.645530682341054f,-0.705120660981081f, + -0.529475884017096f,0.140296797228785f,-0.0133440668494202f,0.529843637228154f, + -0.25828493683013f,0.619866268930593f,0.47419437241583f,0.447278725151833f, + 0.821711397258731f,-0.617272470973745f,-0.212155578716597f,-0.794533711360103f, + -0.762402399229636f,-0.66554198883216f,0.86799064535122f,-0.61415791629922f, + 0.650236475570502f,0.838917668255732f,-0.658036726366966f,0.79973808497526f, + -0.583232188921549f,-0.958456594727579f,-0.670917275207309f,-0.607735262211108f, + 0.374114548594356f,0.758519548998692f,-0.831818710697753f,-0.606668498198204f, + 0.461609482669083f,0.676995424711095f,0.338856030176508f,0.5967074997629f, + -0.925180531336558f,0.4696830362291f,-0.0384243216844951f,0.649557593176482f, + 0.502765260428653f,0.513967467262376f,-0.515358199072217f,-0.444119277197828f, + -0.230720891612428f,0.348053063903166f,0.335781438011331f,0.567805000835321f, + -0.345275268793607f,0.452852845315761f,-0.823034642564643f,-0.629914051647049f, + -0.248509141280827f,0.107760047194603f,0.103293698795021f,0.347988561161273f, + -0.103424145197316f,0.151822355394586f,-0.272890315097335f,0.940838684544033f, + 0.174472591496773f,0.741124360281646f,-0.950217097467039f,-0.922017392413252f, + 0.496955384825533f,-0.588424819191232f,-0.285012984144181f,-0.292976024259858f, + 0.30303004349728f,0.748249196092075f,-0.565826698130202f,0.973592191086922f, + 0.598249548946463f,-0.926358493656323f,-0.241048287909827f,0.996364548389252f, + -0.0599127959717052f,0.174629249412504f,-0.96587410625029f,0.980693566420129f, + -0.696388116912935f,-0.900221651108609f,-0.706671628163384f,0.990309443320101f, + -0.585908086908283,0.414355789768166f,0.456957525423029f,-0.308246583228438f, +}; + +#ifdef _VECTORMATH_SOA_TEST +inline float getfloat( vec_float4 val ) +{ + union { vec_float4 v; float s[4]; } tmp; + tmp.v = val; + return tmp.s[0]; +} + +vec_float4 randfloat() +{ + static int randfloat_count = 0; + int idx = randfloat_count; + vec_float4 tmp = (vec_float4){randfloats[idx],randfloats[idx],randfloats[idx],randfloats[idx]}; + randfloat_count = (randfloat_count+1) % 1024; + return tmp; +} + +#else +inline float getfloat( float val ) +{ + return val; +} + +float randfloat() +{ + static int randfloat_count = 0; + float tmp = randfloats[randfloat_count]; + randfloat_count = (randfloat_count+1) % 1024; + return tmp; +} +#endif + +#ifdef _VECTORMATH_SCALAR_TEST +# define scalar_float(v) (v) +#else +# define scalar_float(v) floatInVec(v) +#endif + +#endif diff --git a/Extras/vectormathlibrary/tests/test1_aos_c.c b/Extras/vectormathlibrary/tests/test1_aos_c.c new file mode 100644 index 0000000..527434e --- /dev/null +++ b/Extras/vectormathlibrary/tests/test1_aos_c.c @@ -0,0 +1,1153 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +#define _VECTORMATH_AOS_TEST + +#include "vectormath_aos.h" +#include "test.h" + +int iteration = 0; + +void +Vector3_methods_test() +{ + VmathVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3, e_Vector3; + VmathVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4, e_Vector4; + VmathPoint3 a_Point3, b_Point3, c_Point3, d_Point3, e_Point3; + VmathQuat a_Quat, b_Quat, c_Quat, d_Quat, e_Quat; + VmathVector4 tmpV4; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, aos_Vector3_0, aos_Vector3_1, aos_Vector3_2, aos_Vector3_3, tmpV3_4, tmpV3_5, tmpV3_6, tmpV3_7; + VmathVector4 aos_Vector4_0, aos_Vector4_1, aos_Vector4_2; + VmathVector3 tmpV3_8, tmpV3_9; + VmathPoint3 tmpP3_0; + VmathVector3 tmpV3_10, tmpV3_11, tmpV3_12, tmpV3_13, tmpV3_14, tmpV3_15, tmpV3_16, tmpV3_17, tmpV3_18, tmpV3_19, tmpV3_20, tmpV3_21, tmpV3_22, tmpV3_23, tmpV3_24, tmpV3_25; + float rndflt1, rndflt2, rndflt3, rndflt4, pad; + float xyz4[12] __attribute__ ((aligned(16))); +#ifndef _VECTORMATH_SCALAR_TEST + vec_float4 quad; +#endif + xyz4[0] = randfloat(); + xyz4[1] = randfloat(); + xyz4[2] = randfloat(); + xyz4[3] = randfloat(); + xyz4[4] = randfloat(); + xyz4[5] = randfloat(); + xyz4[6] = randfloat(); + xyz4[7] = randfloat(); + xyz4[8] = randfloat(); + xyz4[9] = randfloat(); + xyz4[10] = randfloat(); + xyz4[11] = randfloat(); + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &b_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &a_Vector3, pad ); + vmathV4GetXYZ( &a_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &b_Vector3, pad ); + vmathV4GetXYZ( &b_Vector3, &tmpV4 ); + vmathV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathV3MakeFromScalar( &c_Vector3, 0.0f ); + vmathV3MakeFromScalar( &d_Vector3, 0.0f ); + vmathV3MakeFromScalar( &e_Vector3, 0.0f ); + vmathV3Prints( &c_Vector3, "set Vector3 elements to zero" ); + vmathV3Prints( &d_Vector3, "set Vector3 elements to zero" ); + vmathV3Prints( &e_Vector3, "set Vector3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &b_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathV4MakeFromScalar( &c_Vector4, 0.0f ); + vmathV4MakeFromScalar( &d_Vector4, 0.0f ); + vmathV4MakeFromScalar( &e_Vector4, 0.0f ); + vmathV4Prints( &c_Vector4, "set Vector4 elements to zero" ); + vmathV4Prints( &d_Vector4, "set Vector4 elements to zero" ); + vmathV4Prints( &e_Vector4, "set Vector4 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &b_Point3, rndflt1, rndflt2, rndflt3 ); + vmathV3MakeFromP3( &tmpV3_0, &a_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_0, pad ); + vmathV4GetXYZ( &tmpV3_1, &tmpV4 ); + vmathP3MakeFromV3( &a_Point3, &tmpV3_1 ); + vmathV3MakeFromP3( &tmpV3_2, &b_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_2, pad ); + vmathV4GetXYZ( &tmpV3_3, &tmpV4 ); + vmathP3MakeFromV3( &b_Point3, &tmpV3_3 ); + vmathP3Prints( &a_Point3, "set Point3 with floats" ); + vmathP3Prints( &b_Point3, "set Point3 with floats" ); + vmathP3MakeFromScalar( &c_Point3, 0.0f ); + vmathP3MakeFromScalar( &d_Point3, 0.0f ); + vmathP3MakeFromScalar( &e_Point3, 0.0f ); + vmathP3Prints( &c_Point3, "set Point3 elements to zero" ); + vmathP3Prints( &d_Point3, "set Point3 elements to zero" ); + vmathP3Prints( &e_Point3, "set Point3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &b_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathQPrints( &a_Quat, "set Quat with floats" ); + vmathQPrints( &b_Quat, "set Quat with floats" ); + vmathQMakeFromScalar( &c_Quat, 0.0f ); + vmathQMakeFromScalar( &d_Quat, 0.0f ); + vmathQMakeFromScalar( &e_Quat, 0.0f ); + vmathQPrints( &c_Quat, "set Quat elements to zero" ); + vmathQPrints( &d_Quat, "set Quat elements to zero" ); + vmathQPrints( &e_Quat, "set Quat elements to zero" ); + vmathV3MakeFromP3( &a_Vector3, &a_Point3 ); + vmathV3Prints( &a_Vector3, "construct Vector3 with Point3" ); + vmathV3MakeFromScalar( &a_Vector3, randfloat() ); + vmathV3Prints( &a_Vector3, "set Vector3 with float" ); + vmathV3MakeFromScalar( &a_Vector3, randfloat() ); + vmathV3Prints( &a_Vector3, "set Vector3 with float" ); + vmathV3MakeFromElems( &aos_Vector3_0, 0.0f, 1.0f, 2.0f ); + vmathV3MakeFromElems( &aos_Vector3_1, 3.0f, 4.0f, 5.0f ); + vmathV3MakeFromElems( &aos_Vector3_2, 6.0f, 7.0f, 8.0f ); + vmathV3MakeFromElems( &aos_Vector3_3, 9.0f, 10.0f, 11.0f ); + vmathV3Prints( &aos_Vector3_3, "aos type 0" ); + vmathV3Prints( &aos_Vector3_2, "aos type 1" ); + vmathV3Prints( &aos_Vector3_1, "aos type 2" ); + vmathV3Prints( &aos_Vector3_0, "aos type 3" ); + vmathV3Select( &tmpV3_4, &a_Vector3, &b_Vector3, 0 ); + vmathV3Prints( &tmpV3_4, "select 0" ); + vmathV3Select( &tmpV3_5, &a_Vector3, &b_Vector3, 1 ); + vmathV3Prints( &tmpV3_5, "select 1" ); + vmathV3Select( &tmpV3_6, &a_Vector3, &b_Vector3, 0 ); + vmathV3Prints( &tmpV3_6, "select 2" ); + vmathV3Select( &tmpV3_7, &a_Vector3, &b_Vector3, (unsigned int)-1 ); + vmathV3Prints( &tmpV3_7, "select 3" ); + vmathV3MakeFromElems( &a_Vector3, xyz4[0], xyz4[1], xyz4[2] ); + vmathV3Prints( &a_Vector3, "load XYZ array" ); + xyz4[0] = -xyz4[0]; + xyz4[1] = -xyz4[1]; + xyz4[2] = -xyz4[2]; + xyz4[3] = -xyz4[3]; + xyz4[4] = -xyz4[4]; + xyz4[5] = -xyz4[5]; + xyz4[6] = -xyz4[6]; + xyz4[7] = -xyz4[7]; + xyz4[8] = -xyz4[8]; + xyz4[9] = -xyz4[9]; + xyz4[10] = -xyz4[10]; + xyz4[11] = -xyz4[11]; + vmathV4MakeFromElems( &aos_Vector4_0, xyz4[0], xyz4[1], xyz4[2], xyz4[3] ); + vmathV4MakeFromElems( &aos_Vector4_1, xyz4[4], xyz4[5], xyz4[6], xyz4[7] ); + vmathV4MakeFromElems( &aos_Vector4_2, xyz4[8], xyz4[9], xyz4[10], xyz4[11] ); + vmathV4Prints( &aos_Vector4_0, "xyzx" ); + vmathV4Prints( &aos_Vector4_1, "yzxy" ); + vmathV4Prints( &aos_Vector4_2, "zxyz" ); +#ifndef _VECTORMATH_SCALAR_TEST + vmathV3LoadXYZArray( &aos_Vector3_0, &aos_Vector3_1, &aos_Vector3_2, &aos_Vector3_3, (const vec_float4 *)xyz4 ); + xyz4[0] = 0; + xyz4[1] = 1; + xyz4[2] = 2; + xyz4[3] = 3; + xyz4[4] = 4; + xyz4[5] = 5; + xyz4[6] = 6; + xyz4[7] = 7; + xyz4[8] = 8; + xyz4[9] = 9; + xyz4[10] = 10; + xyz4[11] = 11; + vmathV3StoreXYZArray( &aos_Vector3_0, &aos_Vector3_1, &aos_Vector3_2, &aos_Vector3_3, (vec_float4 *)xyz4 ); +#endif + vmathV4MakeFromElems( &aos_Vector4_0, xyz4[0], xyz4[1], xyz4[2], xyz4[3] ); + vmathV4MakeFromElems( &aos_Vector4_1, xyz4[4], xyz4[5], xyz4[6], xyz4[7] ); + vmathV4MakeFromElems( &aos_Vector4_2, xyz4[8], xyz4[9], xyz4[10], xyz4[11] ); + vmathV4Prints( &aos_Vector4_0, "xyzx" ); + vmathV4Prints( &aos_Vector4_1, "yzxy" ); + vmathV4Prints( &aos_Vector4_2, "zxyz" ); +#ifdef _VECTORMATH_SCALAR_TEST + printf("storeXYZ:-1.0 -2.0 -3.0 0.4\n"); +#else + quad = (vec_float4){-1.0f, -2.0f, -3.0f, -4.0f}; + a_Vector3.vec128 = quad; + quad = (vec_float4){0.1f, 0.2f, 0.3f, 0.4f}; + vmathV3StoreXYZ( &a_Vector3, &quad ); + printf("storeXYZ:%f %f %f %f\n", ((float *)&quad)[0], ((float *)&quad)[1], ((float *)&quad)[2], ((float *)&quad)[3]); +#endif + vmathV3Copy( &a_Vector3, &b_Vector3 ); + vmathV3Prints( &a_Vector3, "assign to Vector3 from Vector3" ); + vmathV3MakeFromScalar( &a_Vector3, 0.0f ); + vmathV3Prints( &a_Vector3, "set Vector3 elements to zero" ); + vmathV3MakeXAxis( &a_Vector3 ); + vmathV3Prints( &a_Vector3, "set to x axis" ); + vmathV3MakeYAxis( &a_Vector3 ); + vmathV3Prints( &a_Vector3, "set to y axis" ); + vmathV3MakeZAxis( &a_Vector3 ); + vmathV3Prints( &a_Vector3, "set to z axis" ); + vmathV3SetElem( &a_Vector3, 0, randfloat() ); + vmathV3Prints( &a_Vector3, "Vector3::set( 0, float )" ); + vmathV3SetElem( &a_Vector3, 0, randfloat() ); + vmathV3SetElem( &a_Vector3, 0, ( vmathV3GetElem( &a_Vector3, 0 ) * randfloat() ) ); + vmathV3SetElem( &a_Vector3, 0, ( vmathV3GetElem( &a_Vector3, 0 ) / randfloat() ) ); + vmathV3SetElem( &a_Vector3, 0, ( vmathV3GetElem( &a_Vector3, 0 ) + randfloat() ) ); + vmathV3SetElem( &a_Vector3, 0, ( vmathV3GetElem( &a_Vector3, 0 ) - randfloat() ) ); + vmathV3Prints( &a_Vector3, "Vector3::operator [](0)" ); + vmathV3SetX( &a_Vector3, randfloat() ); + vmathV3Prints( &a_Vector3, "Vector3::setX()" ); + vmathV3SetElem( &a_Vector3, 1, randfloat() ); + vmathV3Prints( &a_Vector3, "Vector3::set( 1, float )" ); + vmathV3SetElem( &a_Vector3, 1, randfloat() ); + vmathV3SetElem( &a_Vector3, 1, ( vmathV3GetElem( &a_Vector3, 1 ) * randfloat() ) ); + vmathV3SetElem( &a_Vector3, 1, ( vmathV3GetElem( &a_Vector3, 1 ) / randfloat() ) ); + vmathV3SetElem( &a_Vector3, 1, ( vmathV3GetElem( &a_Vector3, 1 ) + randfloat() ) ); + vmathV3SetElem( &a_Vector3, 1, ( vmathV3GetElem( &a_Vector3, 1 ) - randfloat() ) ); + vmathV3Prints( &a_Vector3, "Vector3::operator [](1)" ); + vmathV3SetY( &a_Vector3, randfloat() ); + vmathV3Prints( &a_Vector3, "Vector3::setY()" ); + vmathV3SetElem( &a_Vector3, 2, randfloat() ); + vmathV3Prints( &a_Vector3, "Vector3::set( 2, float )" ); + vmathV3SetElem( &a_Vector3, 2, randfloat() ); + vmathV3SetElem( &a_Vector3, 2, ( vmathV3GetElem( &a_Vector3, 2 ) * randfloat() ) ); + vmathV3SetElem( &a_Vector3, 2, ( vmathV3GetElem( &a_Vector3, 2 ) / randfloat() ) ); + vmathV3SetElem( &a_Vector3, 2, ( vmathV3GetElem( &a_Vector3, 2 ) + randfloat() ) ); + vmathV3SetElem( &a_Vector3, 2, ( vmathV3GetElem( &a_Vector3, 2 ) - randfloat() ) ); + vmathV3Prints( &a_Vector3, "Vector3::operator [](2)" ); + vmathV3SetZ( &a_Vector3, randfloat() ); + vmathV3Prints( &a_Vector3, "Vector3::setZ()" ); + printf("Vector3::get( 0 ): %f\n", getfloat(vmathV3GetElem( &a_Vector3, 0 )) ); + printf("Vector3::operator []( 0 ): %f\n", getfloat(vmathV3GetElem( &a_Vector3, 0 )) ); + printf("Vector3::getX(): %f\n", getfloat(vmathV3GetX( &a_Vector3 )) ); + printf("Vector3::get( 1 ): %f\n", getfloat(vmathV3GetElem( &a_Vector3, 1 )) ); + printf("Vector3::operator []( 1 ): %f\n", getfloat(vmathV3GetElem( &a_Vector3, 1 )) ); + printf("Vector3::getY(): %f\n", getfloat(vmathV3GetY( &a_Vector3 )) ); + printf("Vector3::get( 2 ): %f\n", getfloat(vmathV3GetElem( &a_Vector3, 2 )) ); + printf("Vector3::operator []( 2 ): %f\n", getfloat(vmathV3GetElem( &a_Vector3, 2 )) ); + printf("Vector3::getZ(): %f\n", getfloat(vmathV3GetZ( &a_Vector3 )) ); + vmathV3Add( &tmpV3_8, &a_Vector3, &b_Vector3 ); + vmathV3Prints( &tmpV3_8, "Vector3 + Vector3" ); + vmathV3Sub( &tmpV3_9, &a_Vector3, &b_Vector3 ); + vmathV3Prints( &tmpV3_9, "Vector3 - Vector3" ); + vmathV3AddP3( &tmpP3_0, &a_Vector3, &b_Point3 ); + vmathP3Prints( &tmpP3_0, "Vector3 + Point3" ); + vmathV3ScalarMul( &tmpV3_10, &a_Vector3, randfloat() ); + vmathV3Prints( &tmpV3_10, "Vector3 * float" ); + vmathV3ScalarDiv( &tmpV3_11, &a_Vector3, randfloat() ); + vmathV3Prints( &tmpV3_11, "Vector3 / float" ); + vmathV3ScalarMul( &tmpV3_12, &a_Vector3, randfloat() ); + vmathV3Prints( &tmpV3_12, "float * Vector3" ); + vmathV3Neg( &tmpV3_13, &a_Vector3 ); + vmathV3Prints( &tmpV3_13, "Vector3 negate" ); + vmathV3MulPerElem( &tmpV3_14, &a_Vector3, &b_Vector3 ); + vmathV3Prints( &tmpV3_14, "mulPerElem( Vector3, Vector3 )" ); + vmathV3DivPerElem( &tmpV3_15, &a_Vector3, &b_Vector3 ); + vmathV3Prints( &tmpV3_15, "divPerElem( Vector3, Vector3 )" ); + vmathV3RecipPerElem( &tmpV3_16, &a_Vector3 ); + vmathV3Prints( &tmpV3_16, "Vector3 recip" ); + vmathV3AbsPerElem( &tmpV3_17, &a_Vector3 ); + vmathV3SqrtPerElem( &tmpV3_18, &tmpV3_17 ); + vmathV3Prints( &tmpV3_18, "Vector3 sqrt" ); + vmathV3AbsPerElem( &tmpV3_19, &a_Vector3 ); + vmathV3RsqrtPerElem( &tmpV3_20, &tmpV3_19 ); + vmathV3Prints( &tmpV3_20, "Vector3 rsqrt" ); + vmathV3AbsPerElem( &tmpV3_21, &a_Vector3 ); + vmathV3Prints( &tmpV3_21, "Vector3 abs" ); + vmathV3CopySignPerElem( &tmpV3_22, &a_Vector3, &b_Vector3 ); + vmathV3Prints( &tmpV3_22, "Vector3 copySign" ); + vmathV3MaxPerElem( &tmpV3_23, &a_Vector3, &b_Vector3 ); + vmathV3Prints( &tmpV3_23, "Vector3 maximum Vector3" ); + vmathV3MinPerElem( &tmpV3_24, &a_Vector3, &b_Vector3 ); + vmathV3Prints( &tmpV3_24, "Vector3 minimum Vector3" ); + printf("Vector3 maximum of elements: %f\n", getfloat(vmathV3MaxElem( &a_Vector3 ))); + printf("Vector3 minimum of elements: %f\n", getfloat(vmathV3MinElem( &a_Vector3 ))); + printf("Vector3 sum of elements: %f\n", getfloat(vmathV3Sum( &a_Vector3 ))); + printf("Vector3 dot Vector3: %f\n", getfloat(vmathV3Dot( &a_Vector3, &b_Vector3 ))); + printf("Vector3 lengthSqr: %f\n", getfloat(vmathV3LengthSqr( &a_Vector3 ))); + printf("Vector3 length: %f\n", getfloat(vmathV3Length( &a_Vector3 ))); + vmathV3Normalize( &tmpV3_25, &a_Vector3 ); + vmathV3Prints( &tmpV3_25, "Vector3 normalized" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &b_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &e_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathV3Normalize( &b_Vector3, &b_Vector3 ); + vmathV3Normalize( &c_Vector3, &c_Vector3 ); + vmathV3Normalize( &d_Vector3, &d_Vector3 ); + vmathV3Normalize( &e_Vector3, &e_Vector3 ); + vmathV3Lerp( &a_Vector3, randfloat(), &b_Vector3, &c_Vector3 ); + vmathV3Prints( &a_Vector3, "Vector3 lerp" ); + vmathV3Slerp( &a_Vector3, randfloat(), &b_Vector3, &c_Vector3 ); + vmathV3Prints( &a_Vector3, "Vector3 slerp" ); +} + +void +Vector4_methods_test() +{ + VmathVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3, e_Vector3; + VmathVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4, e_Vector4; + VmathPoint3 a_Point3, b_Point3, c_Point3, d_Point3, e_Point3; + VmathQuat a_Quat, b_Quat, c_Quat, d_Quat, e_Quat; + VmathVector4 tmpV4; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + VmathVector4 aos_Vector4_0, aos_Vector4_1, aos_Vector4_2, aos_Vector4_3, tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3; + VmathVector3 tmpV3_4; + VmathVector4 tmpV4_4, tmpV4_5, tmpV4_6, tmpV4_7, tmpV4_8, tmpV4_9, tmpV4_10, tmpV4_11, tmpV4_12, tmpV4_13, tmpV4_14, tmpV4_15, tmpV4_16, tmpV4_17, tmpV4_18, tmpV4_19, tmpV4_20, tmpV4_21; + float rndflt1, rndflt2, rndflt3, rndflt4, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &b_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &a_Vector3, pad ); + vmathV4GetXYZ( &a_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &b_Vector3, pad ); + vmathV4GetXYZ( &b_Vector3, &tmpV4 ); + vmathV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathV3MakeFromScalar( &c_Vector3, 0.0f ); + vmathV3MakeFromScalar( &d_Vector3, 0.0f ); + vmathV3MakeFromScalar( &e_Vector3, 0.0f ); + vmathV3Prints( &c_Vector3, "set Vector3 elements to zero" ); + vmathV3Prints( &d_Vector3, "set Vector3 elements to zero" ); + vmathV3Prints( &e_Vector3, "set Vector3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &b_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathV4MakeFromScalar( &c_Vector4, 0.0f ); + vmathV4MakeFromScalar( &d_Vector4, 0.0f ); + vmathV4MakeFromScalar( &e_Vector4, 0.0f ); + vmathV4Prints( &c_Vector4, "set Vector4 elements to zero" ); + vmathV4Prints( &d_Vector4, "set Vector4 elements to zero" ); + vmathV4Prints( &e_Vector4, "set Vector4 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &b_Point3, rndflt1, rndflt2, rndflt3 ); + vmathV3MakeFromP3( &tmpV3_0, &a_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_0, pad ); + vmathV4GetXYZ( &tmpV3_1, &tmpV4 ); + vmathP3MakeFromV3( &a_Point3, &tmpV3_1 ); + vmathV3MakeFromP3( &tmpV3_2, &b_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_2, pad ); + vmathV4GetXYZ( &tmpV3_3, &tmpV4 ); + vmathP3MakeFromV3( &b_Point3, &tmpV3_3 ); + vmathP3Prints( &a_Point3, "set Point3 with floats" ); + vmathP3Prints( &b_Point3, "set Point3 with floats" ); + vmathP3MakeFromScalar( &c_Point3, 0.0f ); + vmathP3MakeFromScalar( &d_Point3, 0.0f ); + vmathP3MakeFromScalar( &e_Point3, 0.0f ); + vmathP3Prints( &c_Point3, "set Point3 elements to zero" ); + vmathP3Prints( &d_Point3, "set Point3 elements to zero" ); + vmathP3Prints( &e_Point3, "set Point3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &b_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathQPrints( &a_Quat, "set Quat with floats" ); + vmathQPrints( &b_Quat, "set Quat with floats" ); + vmathQMakeFromScalar( &c_Quat, 0.0f ); + vmathQMakeFromScalar( &d_Quat, 0.0f ); + vmathQMakeFromScalar( &e_Quat, 0.0f ); + vmathQPrints( &c_Quat, "set Quat elements to zero" ); + vmathQPrints( &d_Quat, "set Quat elements to zero" ); + vmathQPrints( &e_Quat, "set Quat elements to zero" ); + vmathV4MakeFromV3Scalar( &a_Vector4, &a_Vector3, randfloat() ); + vmathV4Prints( &a_Vector4, "set Vector4 with Vector3, float" ); + vmathV4MakeFromV3( &a_Vector4, &a_Vector3 ); + vmathV4Prints( &a_Vector4, "set Vector4 with Vector3" ); + vmathV4MakeFromP3( &a_Vector4, &a_Point3 ); + vmathV4Prints( &a_Vector4, "set Vector4 with Point3" ); + vmathV4MakeFromQ( &a_Vector4, &a_Quat ); + vmathV4Prints( &a_Vector4, "construct Vector4 with Quat" ); + vmathV4MakeFromScalar( &a_Vector4, randfloat() ); + vmathV4Prints( &a_Vector4, "set Vector4 with float" ); + vmathV4MakeFromScalar( &a_Vector4, randfloat() ); + vmathV4Prints( &a_Vector4, "set Vector4 with float" ); + vmathV4MakeFromElems( &aos_Vector4_0, 0.0f, 1.0f, 2.0f, 3.0f ); + vmathV4MakeFromElems( &aos_Vector4_1, 4.0f, 5.0f, 6.0f, 7.0f ); + vmathV4MakeFromElems( &aos_Vector4_2, 8.0f, 9.0f, 10.0f, 11.0f ); + vmathV4MakeFromElems( &aos_Vector4_3, 12.0f, 13.0f, 14.0f, 15.0f ); + vmathV4Prints( &aos_Vector4_3, "aos type 0" ); + vmathV4Prints( &aos_Vector4_2, "aos type 1" ); + vmathV4Prints( &aos_Vector4_1, "aos type 2" ); + vmathV4Prints( &aos_Vector4_0, "aos type 3" ); + vmathV4Select( &tmpV4_0, &a_Vector4, &b_Vector4, 0 ); + vmathV4Prints( &tmpV4_0, "select 0" ); + vmathV4Select( &tmpV4_1, &a_Vector4, &b_Vector4, 1 ); + vmathV4Prints( &tmpV4_1, "select 1" ); + vmathV4Select( &tmpV4_2, &a_Vector4, &b_Vector4, 0 ); + vmathV4Prints( &tmpV4_2, "select 2" ); + vmathV4Select( &tmpV4_3, &a_Vector4, &b_Vector4, (unsigned int)-1 ); + vmathV4Prints( &tmpV4_3, "select 3" ); + vmathV4Copy( &a_Vector4, &b_Vector4 ); + vmathV4Prints( &a_Vector4, "assign to Vector4 from Vector4" ); + vmathV4SetXYZ( &a_Vector4, &a_Vector3 ); + vmathV4Prints( &a_Vector4, "set Vector4 xyz" ); + vmathV4GetXYZ( &tmpV3_4, &a_Vector4 ); + vmathV3Prints( &tmpV3_4, "get Vector4 xyz" ); + vmathV4MakeFromScalar( &a_Vector4, 0.0f ); + vmathV4Prints( &a_Vector4, "set Vector4 elements to zero" ); + vmathV4MakeXAxis( &a_Vector4 ); + vmathV4Prints( &a_Vector4, "set to x axis" ); + vmathV4MakeYAxis( &a_Vector4 ); + vmathV4Prints( &a_Vector4, "set to y axis" ); + vmathV4MakeZAxis( &a_Vector4 ); + vmathV4Prints( &a_Vector4, "set to z axis" ); + vmathV4MakeWAxis( &a_Vector4 ); + vmathV4Prints( &a_Vector4, "set to w axis" ); + vmathV4SetElem( &a_Vector4, 0, randfloat() ); + vmathV4Prints( &a_Vector4, "Vector4::set( 0, float )" ); + vmathV4SetElem( &a_Vector4, 0, randfloat() ); + vmathV4SetElem( &a_Vector4, 0, ( vmathV4GetElem( &a_Vector4, 0 ) * randfloat() ) ); + vmathV4SetElem( &a_Vector4, 0, ( vmathV4GetElem( &a_Vector4, 0 ) / randfloat() ) ); + vmathV4SetElem( &a_Vector4, 0, ( vmathV4GetElem( &a_Vector4, 0 ) + randfloat() ) ); + vmathV4SetElem( &a_Vector4, 0, ( vmathV4GetElem( &a_Vector4, 0 ) - randfloat() ) ); + vmathV4Prints( &a_Vector4, "Vector4::operator [](0)" ); + vmathV4SetX( &a_Vector4, randfloat() ); + vmathV4Prints( &a_Vector4, "Vector4::setX()" ); + vmathV4SetElem( &a_Vector4, 1, randfloat() ); + vmathV4Prints( &a_Vector4, "Vector4::set( 1, float )" ); + vmathV4SetElem( &a_Vector4, 1, randfloat() ); + vmathV4SetElem( &a_Vector4, 1, ( vmathV4GetElem( &a_Vector4, 1 ) * randfloat() ) ); + vmathV4SetElem( &a_Vector4, 1, ( vmathV4GetElem( &a_Vector4, 1 ) / randfloat() ) ); + vmathV4SetElem( &a_Vector4, 1, ( vmathV4GetElem( &a_Vector4, 1 ) + randfloat() ) ); + vmathV4SetElem( &a_Vector4, 1, ( vmathV4GetElem( &a_Vector4, 1 ) - randfloat() ) ); + vmathV4Prints( &a_Vector4, "Vector4::operator [](1)" ); + vmathV4SetY( &a_Vector4, randfloat() ); + vmathV4Prints( &a_Vector4, "Vector4::setY()" ); + vmathV4SetElem( &a_Vector4, 2, randfloat() ); + vmathV4Prints( &a_Vector4, "Vector4::set( 2, float )" ); + vmathV4SetElem( &a_Vector4, 2, randfloat() ); + vmathV4SetElem( &a_Vector4, 2, ( vmathV4GetElem( &a_Vector4, 2 ) * randfloat() ) ); + vmathV4SetElem( &a_Vector4, 2, ( vmathV4GetElem( &a_Vector4, 2 ) / randfloat() ) ); + vmathV4SetElem( &a_Vector4, 2, ( vmathV4GetElem( &a_Vector4, 2 ) + randfloat() ) ); + vmathV4SetElem( &a_Vector4, 2, ( vmathV4GetElem( &a_Vector4, 2 ) - randfloat() ) ); + vmathV4Prints( &a_Vector4, "Vector4::operator [](2)" ); + vmathV4SetZ( &a_Vector4, randfloat() ); + vmathV4Prints( &a_Vector4, "Vector4::setZ()" ); + vmathV4SetElem( &a_Vector4, 3, randfloat() ); + vmathV4Prints( &a_Vector4, "Vector4::set( 3, float )" ); + vmathV4SetElem( &a_Vector4, 3, randfloat() ); + vmathV4SetElem( &a_Vector4, 3, ( vmathV4GetElem( &a_Vector4, 3 ) * randfloat() ) ); + vmathV4SetElem( &a_Vector4, 3, ( vmathV4GetElem( &a_Vector4, 3 ) / randfloat() ) ); + vmathV4SetElem( &a_Vector4, 3, ( vmathV4GetElem( &a_Vector4, 3 ) + randfloat() ) ); + vmathV4SetElem( &a_Vector4, 3, ( vmathV4GetElem( &a_Vector4, 3 ) - randfloat() ) ); + vmathV4Prints( &a_Vector4, "Vector4::operator [](3)" ); + vmathV4SetW( &a_Vector4, randfloat() ); + vmathV4Prints( &a_Vector4, "Vector4::setW()" ); + printf("Vector4::get( 0 ): %f\n", getfloat(vmathV4GetElem( &a_Vector4, 0 )) ); + printf("Vector4::operator []( 0 ): %f\n", getfloat(vmathV4GetElem( &a_Vector4, 0 )) ); + printf("Vector4::getX(): %f\n", getfloat(vmathV4GetX( &a_Vector4 )) ); + printf("Vector4::get( 1 ): %f\n", getfloat(vmathV4GetElem( &a_Vector4, 1 )) ); + printf("Vector4::operator []( 1 ): %f\n", getfloat(vmathV4GetElem( &a_Vector4, 1 )) ); + printf("Vector4::getY(): %f\n", getfloat(vmathV4GetY( &a_Vector4 )) ); + printf("Vector4::get( 2 ): %f\n", getfloat(vmathV4GetElem( &a_Vector4, 2 )) ); + printf("Vector4::operator []( 2 ): %f\n", getfloat(vmathV4GetElem( &a_Vector4, 2 )) ); + printf("Vector4::getZ(): %f\n", getfloat(vmathV4GetZ( &a_Vector4 )) ); + printf("Vector4::get( 3 ): %f\n", getfloat(vmathV4GetElem( &a_Vector4, 3 )) ); + printf("Vector4::operator []( 3 ): %f\n", getfloat(vmathV4GetElem( &a_Vector4, 3 )) ); + printf("Vector4::getW(): %f\n", getfloat(vmathV4GetW( &a_Vector4 )) ); + vmathV4Add( &tmpV4_4, &a_Vector4, &b_Vector4 ); + vmathV4Prints( &tmpV4_4, "Vector4 + Vector4" ); + vmathV4Sub( &tmpV4_5, &a_Vector4, &b_Vector4 ); + vmathV4Prints( &tmpV4_5, "Vector4 - Vector4" ); + vmathV4ScalarMul( &tmpV4_6, &a_Vector4, randfloat() ); + vmathV4Prints( &tmpV4_6, "Vector4 * float" ); + vmathV4ScalarDiv( &tmpV4_7, &a_Vector4, randfloat() ); + vmathV4Prints( &tmpV4_7, "Vector4 / float" ); + vmathV4ScalarMul( &tmpV4_8, &a_Vector4, randfloat() ); + vmathV4Prints( &tmpV4_8, "float * Vector4" ); + vmathV4Neg( &tmpV4_9, &a_Vector4 ); + vmathV4Prints( &tmpV4_9, "Vector4 negate" ); + vmathV4MulPerElem( &tmpV4_10, &a_Vector4, &b_Vector4 ); + vmathV4Prints( &tmpV4_10, "mulPerElem( Vector4, Vector4 )" ); + vmathV4DivPerElem( &tmpV4_11, &a_Vector4, &b_Vector4 ); + vmathV4Prints( &tmpV4_11, "divPerElem( Vector4, Vector4 )" ); + vmathV4RecipPerElem( &tmpV4_12, &a_Vector4 ); + vmathV4Prints( &tmpV4_12, "Vector4 recip" ); + vmathV4AbsPerElem( &tmpV4_13, &a_Vector4 ); + vmathV4SqrtPerElem( &tmpV4_14, &tmpV4_13 ); + vmathV4Prints( &tmpV4_14, "Vector4 sqrt" ); + vmathV4AbsPerElem( &tmpV4_15, &a_Vector4 ); + vmathV4RsqrtPerElem( &tmpV4_16, &tmpV4_15 ); + vmathV4Prints( &tmpV4_16, "Vector4 rsqrt" ); + vmathV4AbsPerElem( &tmpV4_17, &a_Vector4 ); + vmathV4Prints( &tmpV4_17, "Vector4 abs" ); + vmathV4CopySignPerElem( &tmpV4_18, &a_Vector4, &b_Vector4 ); + vmathV4Prints( &tmpV4_18, "Vector4 copySign" ); + vmathV4MaxPerElem( &tmpV4_19, &a_Vector4, &b_Vector4 ); + vmathV4Prints( &tmpV4_19, "Vector4 maximum Vector4" ); + vmathV4MinPerElem( &tmpV4_20, &a_Vector4, &b_Vector4 ); + vmathV4Prints( &tmpV4_20, "Vector4 minimum Vector4" ); + printf("Vector4 maximum of elements: %f\n", getfloat(vmathV4MaxElem( &a_Vector4 ))); + printf("Vector4 minimum of elements: %f\n", getfloat(vmathV4MinElem( &a_Vector4 ))); + printf("Vector4 sum of elements: %f\n", getfloat(vmathV4Sum( &a_Vector4 ))); + printf("Vector4 dot Vector4: %f\n", getfloat(vmathV4Dot( &a_Vector4, &b_Vector4 ))); + printf("Vector4 lengthSqr: %f\n", getfloat(vmathV4LengthSqr( &a_Vector4 ))); + printf("Vector4 length: %f\n", getfloat(vmathV4Length( &a_Vector4 ))); + vmathV4Normalize( &tmpV4_21, &a_Vector4 ); + vmathV4Prints( &tmpV4_21, "Vector4 normalized" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &b_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &e_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathV4Normalize( &b_Vector4, &b_Vector4 ); + vmathV4Normalize( &c_Vector4, &c_Vector4 ); + vmathV4Normalize( &d_Vector4, &d_Vector4 ); + vmathV4Normalize( &e_Vector4, &e_Vector4 ); + vmathV4Lerp( &a_Vector4, randfloat(), &b_Vector4, &c_Vector4 ); + vmathV4Prints( &a_Vector4, "Vector4 lerp" ); + vmathV4Slerp( &a_Vector4, randfloat(), &b_Vector4, &c_Vector4 ); + vmathV4Prints( &a_Vector4, "Vector4 slerp" ); +} + +void +Point3_methods_test() +{ + VmathVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3, e_Vector3; + VmathVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4, e_Vector4; + VmathPoint3 a_Point3, b_Point3, c_Point3, d_Point3, e_Point3; + VmathQuat a_Quat, b_Quat, c_Quat, d_Quat, e_Quat; + VmathVector4 tmpV4; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + VmathPoint3 aos_Point3_0, aos_Point3_1, aos_Point3_2, aos_Point3_3, tmpP3_0, tmpP3_1, tmpP3_2, tmpP3_3; + VmathVector4 aos_Vector4_0, aos_Vector4_1, aos_Vector4_2; + VmathVector3 tmpV3_4; + VmathPoint3 tmpP3_4, tmpP3_5, tmpP3_6, tmpP3_7, tmpP3_8, tmpP3_9, tmpP3_10, tmpP3_11, tmpP3_12, tmpP3_13, tmpP3_14, tmpP3_15, tmpP3_16; + float rndflt1, rndflt2, rndflt3, rndflt4, pad; + float xyz4[12] __attribute__ ((aligned(16))); +#ifndef _VECTORMATH_SCALAR_TEST + vec_float4 quad; +#endif + xyz4[0] = randfloat(); + xyz4[1] = randfloat(); + xyz4[2] = randfloat(); + xyz4[3] = randfloat(); + xyz4[4] = randfloat(); + xyz4[5] = randfloat(); + xyz4[6] = randfloat(); + xyz4[7] = randfloat(); + xyz4[8] = randfloat(); + xyz4[9] = randfloat(); + xyz4[10] = randfloat(); + xyz4[11] = randfloat(); + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &b_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &a_Vector3, pad ); + vmathV4GetXYZ( &a_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &b_Vector3, pad ); + vmathV4GetXYZ( &b_Vector3, &tmpV4 ); + vmathV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathV3MakeFromScalar( &c_Vector3, 0.0f ); + vmathV3MakeFromScalar( &d_Vector3, 0.0f ); + vmathV3MakeFromScalar( &e_Vector3, 0.0f ); + vmathV3Prints( &c_Vector3, "set Vector3 elements to zero" ); + vmathV3Prints( &d_Vector3, "set Vector3 elements to zero" ); + vmathV3Prints( &e_Vector3, "set Vector3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &b_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathV4MakeFromScalar( &c_Vector4, 0.0f ); + vmathV4MakeFromScalar( &d_Vector4, 0.0f ); + vmathV4MakeFromScalar( &e_Vector4, 0.0f ); + vmathV4Prints( &c_Vector4, "set Vector4 elements to zero" ); + vmathV4Prints( &d_Vector4, "set Vector4 elements to zero" ); + vmathV4Prints( &e_Vector4, "set Vector4 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &b_Point3, rndflt1, rndflt2, rndflt3 ); + vmathV3MakeFromP3( &tmpV3_0, &a_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_0, pad ); + vmathV4GetXYZ( &tmpV3_1, &tmpV4 ); + vmathP3MakeFromV3( &a_Point3, &tmpV3_1 ); + vmathV3MakeFromP3( &tmpV3_2, &b_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_2, pad ); + vmathV4GetXYZ( &tmpV3_3, &tmpV4 ); + vmathP3MakeFromV3( &b_Point3, &tmpV3_3 ); + vmathP3Prints( &a_Point3, "set Point3 with floats" ); + vmathP3Prints( &b_Point3, "set Point3 with floats" ); + vmathP3MakeFromScalar( &c_Point3, 0.0f ); + vmathP3MakeFromScalar( &d_Point3, 0.0f ); + vmathP3MakeFromScalar( &e_Point3, 0.0f ); + vmathP3Prints( &c_Point3, "set Point3 elements to zero" ); + vmathP3Prints( &d_Point3, "set Point3 elements to zero" ); + vmathP3Prints( &e_Point3, "set Point3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &b_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathQPrints( &a_Quat, "set Quat with floats" ); + vmathQPrints( &b_Quat, "set Quat with floats" ); + vmathQMakeFromScalar( &c_Quat, 0.0f ); + vmathQMakeFromScalar( &d_Quat, 0.0f ); + vmathQMakeFromScalar( &e_Quat, 0.0f ); + vmathQPrints( &c_Quat, "set Quat elements to zero" ); + vmathQPrints( &d_Quat, "set Quat elements to zero" ); + vmathQPrints( &e_Quat, "set Quat elements to zero" ); + vmathP3MakeFromV3( &a_Point3, &a_Vector3 ); + vmathP3Prints( &a_Point3, "construct Point3 with Vector3" ); + vmathP3MakeFromScalar( &a_Point3, randfloat() ); + vmathP3Prints( &a_Point3, "set Point3 with float" ); + vmathP3MakeFromScalar( &a_Point3, randfloat() ); + vmathP3Prints( &a_Point3, "set Point3 with float" ); + vmathP3MakeFromElems( &aos_Point3_0, 0.0f, 1.0f, 2.0f ); + vmathP3MakeFromElems( &aos_Point3_1, 3.0f, 4.0f, 5.0f ); + vmathP3MakeFromElems( &aos_Point3_2, 6.0f, 7.0f, 8.0f ); + vmathP3MakeFromElems( &aos_Point3_3, 9.0f, 10.0f, 11.0f ); + vmathP3Prints( &aos_Point3_3, "aos type 0" ); + vmathP3Prints( &aos_Point3_2, "aos type 1" ); + vmathP3Prints( &aos_Point3_1, "aos type 2" ); + vmathP3Prints( &aos_Point3_0, "aos type 3" ); + vmathP3Select( &tmpP3_0, &a_Point3, &b_Point3, 0 ); + vmathP3Prints( &tmpP3_0, "select 0" ); + vmathP3Select( &tmpP3_1, &a_Point3, &b_Point3, 1 ); + vmathP3Prints( &tmpP3_1, "select 1" ); + vmathP3Select( &tmpP3_2, &a_Point3, &b_Point3, 0 ); + vmathP3Prints( &tmpP3_2, "select 2" ); + vmathP3Select( &tmpP3_3, &a_Point3, &b_Point3, (unsigned int)-1 ); + vmathP3Prints( &tmpP3_3, "select 3" ); + vmathP3MakeFromElems( &a_Point3, xyz4[0], xyz4[1], xyz4[2] ); + vmathP3Prints( &a_Point3, "load XYZ array" ); + xyz4[0] = -xyz4[0]; + xyz4[1] = -xyz4[1]; + xyz4[2] = -xyz4[2]; + xyz4[3] = -xyz4[3]; + xyz4[4] = -xyz4[4]; + xyz4[5] = -xyz4[5]; + xyz4[6] = -xyz4[6]; + xyz4[7] = -xyz4[7]; + xyz4[8] = -xyz4[8]; + xyz4[9] = -xyz4[9]; + xyz4[10] = -xyz4[10]; + xyz4[11] = -xyz4[11]; + vmathV4MakeFromElems( &aos_Vector4_0, xyz4[0], xyz4[1], xyz4[2], xyz4[3] ); + vmathV4MakeFromElems( &aos_Vector4_1, xyz4[4], xyz4[5], xyz4[6], xyz4[7] ); + vmathV4MakeFromElems( &aos_Vector4_2, xyz4[8], xyz4[9], xyz4[10], xyz4[11] ); + vmathV4Prints( &aos_Vector4_0, "xyzx" ); + vmathV4Prints( &aos_Vector4_1, "yzxy" ); + vmathV4Prints( &aos_Vector4_2, "zxyz" ); +#ifndef _VECTORMATH_SCALAR_TEST + vmathP3LoadXYZArray( &aos_Point3_0, &aos_Point3_1, &aos_Point3_2, &aos_Point3_3, (const vec_float4 *)xyz4 ); + xyz4[0] = 0; + xyz4[1] = 1; + xyz4[2] = 2; + xyz4[3] = 3; + xyz4[4] = 4; + xyz4[5] = 5; + xyz4[6] = 6; + xyz4[7] = 7; + xyz4[8] = 8; + xyz4[9] = 9; + xyz4[10] = 10; + xyz4[11] = 11; + vmathP3StoreXYZArray( &aos_Point3_0, &aos_Point3_1, &aos_Point3_2, &aos_Point3_3, (vec_float4 *)xyz4 ); +#endif + vmathV4MakeFromElems( &aos_Vector4_0, xyz4[0], xyz4[1], xyz4[2], xyz4[3] ); + vmathV4MakeFromElems( &aos_Vector4_1, xyz4[4], xyz4[5], xyz4[6], xyz4[7] ); + vmathV4MakeFromElems( &aos_Vector4_2, xyz4[8], xyz4[9], xyz4[10], xyz4[11] ); + vmathV4Prints( &aos_Vector4_0, "xyzx" ); + vmathV4Prints( &aos_Vector4_1, "yzxy" ); + vmathV4Prints( &aos_Vector4_2, "zxyz" ); +#ifdef _VECTORMATH_SCALAR_TEST + printf("storeXYZ:-1.0 -2.0 -3.0 0.4\n"); +#else + quad = (vec_float4){-1.0f, -2.0f, -3.0f, -4.0f}; + a_Point3.vec128 = quad; + quad = (vec_float4){0.1f, 0.2f, 0.3f, 0.4f}; + vmathP3StoreXYZ( &a_Point3, &quad ); + printf("storeXYZ:%f %f %f %f\n", ((float *)&quad)[0], ((float *)&quad)[1], ((float *)&quad)[2], ((float *)&quad)[3]); +#endif + vmathP3Copy( &a_Point3, &b_Point3 ); + vmathP3Prints( &a_Point3, "assign to Point3 from Point3" ); + vmathP3MakeFromScalar( &a_Point3, 0.0f ); + vmathP3Prints( &a_Point3, "set Point3 elements to zero" ); + vmathP3SetElem( &a_Point3, 0, randfloat() ); + vmathP3Prints( &a_Point3, "Point3::set( 0, float )" ); + vmathP3SetElem( &a_Point3, 0, randfloat() ); + vmathP3SetElem( &a_Point3, 0, ( vmathP3GetElem( &a_Point3, 0 ) * randfloat() ) ); + vmathP3SetElem( &a_Point3, 0, ( vmathP3GetElem( &a_Point3, 0 ) / randfloat() ) ); + vmathP3SetElem( &a_Point3, 0, ( vmathP3GetElem( &a_Point3, 0 ) + randfloat() ) ); + vmathP3SetElem( &a_Point3, 0, ( vmathP3GetElem( &a_Point3, 0 ) - randfloat() ) ); + vmathP3Prints( &a_Point3, "Point3::operator [](0)" ); + vmathP3SetX( &a_Point3, randfloat() ); + vmathP3Prints( &a_Point3, "Point3::setX()" ); + vmathP3SetElem( &a_Point3, 1, randfloat() ); + vmathP3Prints( &a_Point3, "Point3::set( 1, float )" ); + vmathP3SetElem( &a_Point3, 1, randfloat() ); + vmathP3SetElem( &a_Point3, 1, ( vmathP3GetElem( &a_Point3, 1 ) * randfloat() ) ); + vmathP3SetElem( &a_Point3, 1, ( vmathP3GetElem( &a_Point3, 1 ) / randfloat() ) ); + vmathP3SetElem( &a_Point3, 1, ( vmathP3GetElem( &a_Point3, 1 ) + randfloat() ) ); + vmathP3SetElem( &a_Point3, 1, ( vmathP3GetElem( &a_Point3, 1 ) - randfloat() ) ); + vmathP3Prints( &a_Point3, "Point3::operator [](1)" ); + vmathP3SetY( &a_Point3, randfloat() ); + vmathP3Prints( &a_Point3, "Point3::setY()" ); + vmathP3SetElem( &a_Point3, 2, randfloat() ); + vmathP3Prints( &a_Point3, "Point3::set( 2, float )" ); + vmathP3SetElem( &a_Point3, 2, randfloat() ); + vmathP3SetElem( &a_Point3, 2, ( vmathP3GetElem( &a_Point3, 2 ) * randfloat() ) ); + vmathP3SetElem( &a_Point3, 2, ( vmathP3GetElem( &a_Point3, 2 ) / randfloat() ) ); + vmathP3SetElem( &a_Point3, 2, ( vmathP3GetElem( &a_Point3, 2 ) + randfloat() ) ); + vmathP3SetElem( &a_Point3, 2, ( vmathP3GetElem( &a_Point3, 2 ) - randfloat() ) ); + vmathP3Prints( &a_Point3, "Point3::operator [](2)" ); + vmathP3SetZ( &a_Point3, randfloat() ); + vmathP3Prints( &a_Point3, "Point3::setZ()" ); + printf("Point3::get( 0 ): %f\n", getfloat(vmathP3GetElem( &a_Point3, 0 )) ); + printf("Point3::operator []( 0 ): %f\n", getfloat(vmathP3GetElem( &a_Point3, 0 )) ); + printf("Point3::getX(): %f\n", getfloat(vmathP3GetX( &a_Point3 )) ); + printf("Point3::get( 1 ): %f\n", getfloat(vmathP3GetElem( &a_Point3, 1 )) ); + printf("Point3::operator []( 1 ): %f\n", getfloat(vmathP3GetElem( &a_Point3, 1 )) ); + printf("Point3::getY(): %f\n", getfloat(vmathP3GetY( &a_Point3 )) ); + printf("Point3::get( 2 ): %f\n", getfloat(vmathP3GetElem( &a_Point3, 2 )) ); + printf("Point3::operator []( 2 ): %f\n", getfloat(vmathP3GetElem( &a_Point3, 2 )) ); + printf("Point3::getZ(): %f\n", getfloat(vmathP3GetZ( &a_Point3 )) ); + vmathP3Sub( &tmpV3_4, &a_Point3, &b_Point3 ); + vmathV3Prints( &tmpV3_4, "Point3 - Point3" ); + vmathP3AddV3( &tmpP3_4, &a_Point3, &b_Vector3 ); + vmathP3Prints( &tmpP3_4, "Point3 + Vector3" ); + vmathP3SubV3( &tmpP3_5, &a_Point3, &b_Vector3 ); + vmathP3Prints( &tmpP3_5, "Point3 - Vector3" ); + vmathP3MulPerElem( &tmpP3_6, &a_Point3, &b_Point3 ); + vmathP3Prints( &tmpP3_6, "mulPerElem( Point3, Point3 )" ); + vmathP3DivPerElem( &tmpP3_7, &a_Point3, &b_Point3 ); + vmathP3Prints( &tmpP3_7, "divPerElem( Point3, Point3 )" ); + vmathP3RecipPerElem( &tmpP3_8, &a_Point3 ); + vmathP3Prints( &tmpP3_8, "Point3 recip" ); + vmathP3AbsPerElem( &tmpP3_9, &a_Point3 ); + vmathP3SqrtPerElem( &tmpP3_10, &tmpP3_9 ); + vmathP3Prints( &tmpP3_10, "Point3 sqrt" ); + vmathP3AbsPerElem( &tmpP3_11, &a_Point3 ); + vmathP3RsqrtPerElem( &tmpP3_12, &tmpP3_11 ); + vmathP3Prints( &tmpP3_12, "Point3 rsqrt" ); + vmathP3AbsPerElem( &tmpP3_13, &a_Point3 ); + vmathP3Prints( &tmpP3_13, "Point3 abs" ); + vmathP3CopySignPerElem( &tmpP3_14, &a_Point3, &b_Point3 ); + vmathP3Prints( &tmpP3_14, "Point3 copySign" ); + vmathP3MaxPerElem( &tmpP3_15, &a_Point3, &b_Point3 ); + vmathP3Prints( &tmpP3_15, "Point3 maximum Point3" ); + vmathP3MinPerElem( &tmpP3_16, &a_Point3, &b_Point3 ); + vmathP3Prints( &tmpP3_16, "Point3 minimum Point3" ); + printf("Point3 maximum of elements: %f\n", getfloat(vmathP3MaxElem( &a_Point3 ))); + printf("Point3 minimum of elements: %f\n", getfloat(vmathP3MinElem( &a_Point3 ))); + printf("Point3 sum of elements: %f\n", getfloat(vmathP3Sum( &a_Point3 ))); + printf("Point projection: %f\n", getfloat(vmathP3Projection( &a_Point3, &b_Vector3 ))); + printf("Point distSqrFromOrigin: %f\n", getfloat(vmathP3DistSqrFromOrigin( &a_Point3 )) ); + printf("Point distFromOrigin: %f\n", getfloat(vmathP3DistFromOrigin( &a_Point3 )) ); + printf("Point distSqr: %f\n", getfloat(vmathP3DistSqr( &a_Point3, &b_Point3 )) ); + printf("Point dist: %f\n", getfloat(vmathP3Dist( &a_Point3, &b_Point3 )) ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &b_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &e_Point3, rndflt1, rndflt2, rndflt3 ); + vmathP3Lerp( &a_Point3, randfloat(), &b_Point3, &c_Point3 ); + vmathP3Prints( &a_Point3, "Point3 lerp" ); +} + +void +Quat_methods_test() +{ + VmathVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3, e_Vector3; + VmathVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4, e_Vector4; + VmathPoint3 a_Point3, b_Point3, c_Point3, d_Point3, e_Point3; + VmathQuat a_Quat, b_Quat, c_Quat, d_Quat, e_Quat; + VmathVector4 tmpV4; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + VmathQuat aos_Quat_0, aos_Quat_1, aos_Quat_2, aos_Quat_3, tmpQ_0, tmpQ_1, tmpQ_2, tmpQ_3; + VmathVector3 tmpV3_4; + VmathQuat tmpQ_4, tmpQ_5, tmpQ_6, tmpQ_7, tmpQ_8, tmpQ_9, tmpQ_10, tmpQ_11; + VmathVector3 tmpV3_5; + VmathQuat tmpQ_12; + float rndflt1, rndflt2, rndflt3, rndflt4, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &b_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &a_Vector3, pad ); + vmathV4GetXYZ( &a_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &b_Vector3, pad ); + vmathV4GetXYZ( &b_Vector3, &tmpV4 ); + vmathV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathV3MakeFromScalar( &c_Vector3, 0.0f ); + vmathV3MakeFromScalar( &d_Vector3, 0.0f ); + vmathV3MakeFromScalar( &e_Vector3, 0.0f ); + vmathV3Prints( &c_Vector3, "set Vector3 elements to zero" ); + vmathV3Prints( &d_Vector3, "set Vector3 elements to zero" ); + vmathV3Prints( &e_Vector3, "set Vector3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &b_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathV4MakeFromScalar( &c_Vector4, 0.0f ); + vmathV4MakeFromScalar( &d_Vector4, 0.0f ); + vmathV4MakeFromScalar( &e_Vector4, 0.0f ); + vmathV4Prints( &c_Vector4, "set Vector4 elements to zero" ); + vmathV4Prints( &d_Vector4, "set Vector4 elements to zero" ); + vmathV4Prints( &e_Vector4, "set Vector4 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &b_Point3, rndflt1, rndflt2, rndflt3 ); + vmathV3MakeFromP3( &tmpV3_0, &a_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_0, pad ); + vmathV4GetXYZ( &tmpV3_1, &tmpV4 ); + vmathP3MakeFromV3( &a_Point3, &tmpV3_1 ); + vmathV3MakeFromP3( &tmpV3_2, &b_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_2, pad ); + vmathV4GetXYZ( &tmpV3_3, &tmpV4 ); + vmathP3MakeFromV3( &b_Point3, &tmpV3_3 ); + vmathP3Prints( &a_Point3, "set Point3 with floats" ); + vmathP3Prints( &b_Point3, "set Point3 with floats" ); + vmathP3MakeFromScalar( &c_Point3, 0.0f ); + vmathP3MakeFromScalar( &d_Point3, 0.0f ); + vmathP3MakeFromScalar( &e_Point3, 0.0f ); + vmathP3Prints( &c_Point3, "set Point3 elements to zero" ); + vmathP3Prints( &d_Point3, "set Point3 elements to zero" ); + vmathP3Prints( &e_Point3, "set Point3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &b_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathQPrints( &a_Quat, "set Quat with floats" ); + vmathQPrints( &b_Quat, "set Quat with floats" ); + vmathQMakeFromScalar( &c_Quat, 0.0f ); + vmathQMakeFromScalar( &d_Quat, 0.0f ); + vmathQMakeFromScalar( &e_Quat, 0.0f ); + vmathQPrints( &c_Quat, "set Quat elements to zero" ); + vmathQPrints( &d_Quat, "set Quat elements to zero" ); + vmathQPrints( &e_Quat, "set Quat elements to zero" ); + vmathQMakeFromV3Scalar( &a_Quat, &a_Vector3, randfloat() ); + vmathQPrints( &a_Quat, "set Quat with Vector3, float" ); + vmathQMakeFromV4( &a_Quat, &a_Vector4 ); + vmathQPrints( &a_Quat, "construct Quat with Vector4" ); + vmathQMakeFromScalar( &a_Quat, randfloat() ); + vmathQPrints( &a_Quat, "set Quat with float" ); + vmathQMakeFromScalar( &a_Quat, randfloat() ); + vmathQPrints( &a_Quat, "set Quat with float" ); + vmathQMakeFromElems( &aos_Quat_0, 0.0f, 1.0f, 2.0f, 3.0f ); + vmathQMakeFromElems( &aos_Quat_1, 4.0f, 5.0f, 6.0f, 7.0f ); + vmathQMakeFromElems( &aos_Quat_2, 8.0f, 9.0f, 10.0f, 11.0f ); + vmathQMakeFromElems( &aos_Quat_3, 12.0f, 13.0f, 14.0f, 15.0f ); + vmathQPrints( &aos_Quat_3, "aos type 0" ); + vmathQPrints( &aos_Quat_2, "aos type 1" ); + vmathQPrints( &aos_Quat_1, "aos type 2" ); + vmathQPrints( &aos_Quat_0, "aos type 3" ); + vmathQSelect( &tmpQ_0, &a_Quat, &b_Quat, 0 ); + vmathQPrints( &tmpQ_0, "select 0" ); + vmathQSelect( &tmpQ_1, &a_Quat, &b_Quat, 1 ); + vmathQPrints( &tmpQ_1, "select 1" ); + vmathQSelect( &tmpQ_2, &a_Quat, &b_Quat, 0 ); + vmathQPrints( &tmpQ_2, "select 2" ); + vmathQSelect( &tmpQ_3, &a_Quat, &b_Quat, (unsigned int)-1 ); + vmathQPrints( &tmpQ_3, "select 3" ); + vmathQCopy( &a_Quat, &b_Quat ); + vmathQPrints( &a_Quat, "assign to Quat from Quat" ); + vmathQSetXYZ( &a_Quat, &a_Vector3 ); + vmathQPrints( &a_Quat, "set Quat xyz" ); + vmathQGetXYZ( &tmpV3_4, &a_Quat ); + vmathV3Prints( &tmpV3_4, "get Quat xyz" ); + vmathQMakeFromScalar( &a_Quat, 0.0f ); + vmathQPrints( &a_Quat, "set Quat elements to zero" ); + vmathQSetElem( &a_Quat, 0, randfloat() ); + vmathQPrints( &a_Quat, "Quat::set( 0, float )" ); + vmathQSetElem( &a_Quat, 0, randfloat() ); + vmathQSetElem( &a_Quat, 0, ( vmathQGetElem( &a_Quat, 0 ) * randfloat() ) ); + vmathQSetElem( &a_Quat, 0, ( vmathQGetElem( &a_Quat, 0 ) / randfloat() ) ); + vmathQSetElem( &a_Quat, 0, ( vmathQGetElem( &a_Quat, 0 ) + randfloat() ) ); + vmathQSetElem( &a_Quat, 0, ( vmathQGetElem( &a_Quat, 0 ) - randfloat() ) ); + vmathQPrints( &a_Quat, "Quat::operator [](0)" ); + vmathQSetX( &a_Quat, randfloat() ); + vmathQPrints( &a_Quat, "Quat::setX()" ); + vmathQSetElem( &a_Quat, 1, randfloat() ); + vmathQPrints( &a_Quat, "Quat::set( 1, float )" ); + vmathQSetElem( &a_Quat, 1, randfloat() ); + vmathQSetElem( &a_Quat, 1, ( vmathQGetElem( &a_Quat, 1 ) * randfloat() ) ); + vmathQSetElem( &a_Quat, 1, ( vmathQGetElem( &a_Quat, 1 ) / randfloat() ) ); + vmathQSetElem( &a_Quat, 1, ( vmathQGetElem( &a_Quat, 1 ) + randfloat() ) ); + vmathQSetElem( &a_Quat, 1, ( vmathQGetElem( &a_Quat, 1 ) - randfloat() ) ); + vmathQPrints( &a_Quat, "Quat::operator [](1)" ); + vmathQSetY( &a_Quat, randfloat() ); + vmathQPrints( &a_Quat, "Quat::setY()" ); + vmathQSetElem( &a_Quat, 2, randfloat() ); + vmathQPrints( &a_Quat, "Quat::set( 2, float )" ); + vmathQSetElem( &a_Quat, 2, randfloat() ); + vmathQSetElem( &a_Quat, 2, ( vmathQGetElem( &a_Quat, 2 ) * randfloat() ) ); + vmathQSetElem( &a_Quat, 2, ( vmathQGetElem( &a_Quat, 2 ) / randfloat() ) ); + vmathQSetElem( &a_Quat, 2, ( vmathQGetElem( &a_Quat, 2 ) + randfloat() ) ); + vmathQSetElem( &a_Quat, 2, ( vmathQGetElem( &a_Quat, 2 ) - randfloat() ) ); + vmathQPrints( &a_Quat, "Quat::operator [](2)" ); + vmathQSetZ( &a_Quat, randfloat() ); + vmathQPrints( &a_Quat, "Quat::setZ()" ); + vmathQSetElem( &a_Quat, 3, randfloat() ); + vmathQPrints( &a_Quat, "Quat::set( 3, float )" ); + vmathQSetElem( &a_Quat, 3, randfloat() ); + vmathQSetElem( &a_Quat, 3, ( vmathQGetElem( &a_Quat, 3 ) * randfloat() ) ); + vmathQSetElem( &a_Quat, 3, ( vmathQGetElem( &a_Quat, 3 ) / randfloat() ) ); + vmathQSetElem( &a_Quat, 3, ( vmathQGetElem( &a_Quat, 3 ) + randfloat() ) ); + vmathQSetElem( &a_Quat, 3, ( vmathQGetElem( &a_Quat, 3 ) - randfloat() ) ); + vmathQPrints( &a_Quat, "Quat::operator [](3)" ); + vmathQSetW( &a_Quat, randfloat() ); + vmathQPrints( &a_Quat, "Quat::setW()" ); + printf("Quat::get( 0 ): %f\n", getfloat(vmathQGetElem( &a_Quat, 0 )) ); + printf("Quat::operator []( 0 ): %f\n", getfloat(vmathQGetElem( &a_Quat, 0 )) ); + printf("Quat::getX(): %f\n", getfloat(vmathQGetX( &a_Quat )) ); + printf("Quat::get( 1 ): %f\n", getfloat(vmathQGetElem( &a_Quat, 1 )) ); + printf("Quat::operator []( 1 ): %f\n", getfloat(vmathQGetElem( &a_Quat, 1 )) ); + printf("Quat::getY(): %f\n", getfloat(vmathQGetY( &a_Quat )) ); + printf("Quat::get( 2 ): %f\n", getfloat(vmathQGetElem( &a_Quat, 2 )) ); + printf("Quat::operator []( 2 ): %f\n", getfloat(vmathQGetElem( &a_Quat, 2 )) ); + printf("Quat::getZ(): %f\n", getfloat(vmathQGetZ( &a_Quat )) ); + printf("Quat::get( 3 ): %f\n", getfloat(vmathQGetElem( &a_Quat, 3 )) ); + printf("Quat::operator []( 3 ): %f\n", getfloat(vmathQGetElem( &a_Quat, 3 )) ); + printf("Quat::getW(): %f\n", getfloat(vmathQGetW( &a_Quat )) ); + vmathQAdd( &tmpQ_4, &a_Quat, &b_Quat ); + vmathQPrints( &tmpQ_4, "Quat + Quat" ); + vmathQSub( &tmpQ_5, &a_Quat, &b_Quat ); + vmathQPrints( &tmpQ_5, "Quat - Quat" ); + vmathQMul( &tmpQ_6, &a_Quat, &b_Quat ); + vmathQPrints( &tmpQ_6, "Quat * Quat" ); + vmathQScalarMul( &tmpQ_7, &a_Quat, randfloat() ); + vmathQPrints( &tmpQ_7, "Quat * float" ); + vmathQScalarDiv( &tmpQ_8, &a_Quat, randfloat() ); + vmathQPrints( &tmpQ_8, "Quat / float" ); + vmathQScalarMul( &tmpQ_9, &a_Quat, randfloat() ); + vmathQPrints( &tmpQ_9, "float * Quat" ); + vmathQNeg( &tmpQ_10, &a_Quat ); + vmathQPrints( &tmpQ_10, "Quat negate" ); + printf("Quat dot Quat: %f\n", getfloat(vmathQDot( &a_Quat, &b_Quat ))); + printf("Quat lengthSqr: %f\n", getfloat(vmathQNorm( &a_Quat ))); + printf("Quat length: %f\n", getfloat(vmathQLength( &a_Quat ))); + vmathQNormalize( &tmpQ_11, &a_Quat ); + vmathQPrints( &tmpQ_11, "Quat normalized" ); + vmathQMakeIdentity( &a_Quat ); + vmathQPrints( &a_Quat, "set to identity" ); + vmathQMakeRotationArc( &a_Quat, &a_Vector3, &b_Vector3 ); + vmathQPrints( &a_Quat, "Quat rotation between vectors" ); + vmathQMakeRotationAxis( &a_Quat, randfloat(), &a_Vector3 ); + vmathQPrints( &a_Quat, "Quat rotation axis angle" ); + vmathQMakeRotationX( &a_Quat, randfloat() ); + vmathQPrints( &a_Quat, "Quat rotationX" ); + vmathQMakeRotationY( &a_Quat, randfloat() ); + vmathQPrints( &a_Quat, "Quat rotationY" ); + vmathQMakeRotationZ( &a_Quat, randfloat() ); + vmathQPrints( &a_Quat, "Quat rotationZ" ); + vmathQRotate( &tmpV3_5, &a_Quat, &a_Vector3 ); + vmathV3Prints( &tmpV3_5, "Quat rotate Vector3" ); + vmathQConj( &tmpQ_12, &a_Quat ); + vmathQPrints( &tmpQ_12, "Quat conj" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &b_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &e_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathQNormalize( &b_Quat, &b_Quat ); + vmathQNormalize( &c_Quat, &c_Quat ); + vmathQNormalize( &d_Quat, &d_Quat ); + vmathQNormalize( &e_Quat, &e_Quat ); + vmathQLerp( &a_Quat, randfloat(), &b_Quat, &c_Quat ); + vmathQPrints( &a_Quat, "Quat lerp" ); + vmathQSlerp( &a_Quat, randfloat(), &b_Quat, &c_Quat ); + vmathQPrints( &a_Quat, "Quat slerp" ); + vmathQSquad( &a_Quat, randfloat(), &b_Quat, &c_Quat, &d_Quat, &e_Quat ); + vmathQPrints( &a_Quat, "Quat squad" ); +} + +int main() +{ + printf("\n __begin__ \n"); + for ( iteration = 0; iteration < 2; iteration++ ) { + Vector3_methods_test(); + Vector4_methods_test(); + Point3_methods_test(); + Quat_methods_test(); + } + printf("\n __end__ \n"); + return 0; +} diff --git a/Extras/vectormathlibrary/tests/test1_aos_cpp.cpp b/Extras/vectormathlibrary/tests/test1_aos_cpp.cpp new file mode 100644 index 0000000..2a96078 --- /dev/null +++ b/Extras/vectormathlibrary/tests/test1_aos_cpp.cpp @@ -0,0 +1,1102 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +#define _VECTORMATH_AOS_TEST + +#include "vectormath_aos.h" +#include "test.h" + +int iteration = 0; + +using namespace Vectormath; +using namespace Vectormath::Aos; + +void +Vector3_methods_test() +{ + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3, e_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4, e_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3, e_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat, e_Quat; + Vector4 tmpV4; + Vector3 aos_Vector3_0, aos_Vector3_1, aos_Vector3_2, aos_Vector3_3; + Vector4 aos_Vector4_0, aos_Vector4_1, aos_Vector4_2; + float rndflt1, rndflt2, rndflt3, rndflt4, pad; + float xyz4[12] __attribute__ ((aligned(16))); +#ifndef _VECTORMATH_SCALAR_TEST + vec_float4 quad; +#endif + xyz4[0] = randfloat(); + xyz4[1] = randfloat(); + xyz4[2] = randfloat(); + xyz4[3] = randfloat(); + xyz4[4] = randfloat(); + xyz4[5] = randfloat(); + xyz4[6] = randfloat(); + xyz4[7] = randfloat(); + xyz4[8] = randfloat(); + xyz4[9] = randfloat(); + xyz4[10] = randfloat(); + xyz4[11] = randfloat(); + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Vector3 = Vector3( scalar_float(rndflt1), scalar_float(rndflt2), scalar_float(rndflt3) ); + tmpV4 = Vector4( a_Vector3, pad ); + a_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( b_Vector3, pad ); + b_Vector3 = tmpV4.getXYZ( ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + c_Vector3 = Vector3( 0.0f ); + d_Vector3 = Vector3( 0.0f ); + e_Vector3 = Vector3( 0.0f ); + print( c_Vector3, "set Vector3 elements to zero" ); + print( d_Vector3, "set Vector3 elements to zero" ); + print( e_Vector3, "set Vector3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Vector4 = Vector4( scalar_float(rndflt1), scalar_float(rndflt2), scalar_float(rndflt3), scalar_float(rndflt4) ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + c_Vector4 = Vector4( 0.0f ); + d_Vector4 = Vector4( 0.0f ); + e_Vector4 = Vector4( 0.0f ); + print( c_Vector4, "set Vector4 elements to zero" ); + print( d_Vector4, "set Vector4 elements to zero" ); + print( e_Vector4, "set Vector4 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Point3 = Point3( scalar_float(rndflt1), scalar_float(rndflt2), scalar_float(rndflt3) ); + tmpV4 = Vector4( Vector3( a_Point3 ), pad ); + a_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( b_Point3 ), pad ); + b_Point3 = Point3( tmpV4.getXYZ( ) ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + c_Point3 = Point3( 0.0f ); + d_Point3 = Point3( 0.0f ); + e_Point3 = Point3( 0.0f ); + print( c_Point3, "set Point3 elements to zero" ); + print( d_Point3, "set Point3 elements to zero" ); + print( e_Point3, "set Point3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Quat = Quat( scalar_float(rndflt1), scalar_float(rndflt2), scalar_float(rndflt3), scalar_float(rndflt4) ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + c_Quat = Quat( 0.0f ); + d_Quat = Quat( 0.0f ); + e_Quat = Quat( 0.0f ); + print( c_Quat, "set Quat elements to zero" ); + print( d_Quat, "set Quat elements to zero" ); + print( e_Quat, "set Quat elements to zero" ); + a_Vector3 = Vector3( a_Point3 ); + print( a_Vector3, "construct Vector3 with Point3" ); + a_Vector3 = Vector3( randfloat() ); + print( a_Vector3, "set Vector3 with float" ); + a_Vector3 = Vector3( scalar_float(randfloat()) ); + print( a_Vector3, "set Vector3 with float" ); + aos_Vector3_0 = Vector3( 0.0f, 1.0f, 2.0f ); + aos_Vector3_1 = Vector3( 3.0f, 4.0f, 5.0f ); + aos_Vector3_2 = Vector3( 6.0f, 7.0f, 8.0f ); + aos_Vector3_3 = Vector3( 9.0f, 10.0f, 11.0f ); + print( aos_Vector3_3, "aos type 0" ); + print( aos_Vector3_2, "aos type 1" ); + print( aos_Vector3_1, "aos type 2" ); + print( aos_Vector3_0, "aos type 3" ); + print( select( a_Vector3, b_Vector3, 0 ), "select 0" ); + print( select( a_Vector3, b_Vector3, 1 ), "select 1" ); + print( select( a_Vector3, b_Vector3, 0 ), "select 2" ); + print( select( a_Vector3, b_Vector3, (unsigned int)-1 ), "select 3" ); + a_Vector3 = Vector3( xyz4[0], xyz4[1], xyz4[2] ); + print( a_Vector3, "load XYZ array" ); + xyz4[0] = -xyz4[0]; + xyz4[1] = -xyz4[1]; + xyz4[2] = -xyz4[2]; + xyz4[3] = -xyz4[3]; + xyz4[4] = -xyz4[4]; + xyz4[5] = -xyz4[5]; + xyz4[6] = -xyz4[6]; + xyz4[7] = -xyz4[7]; + xyz4[8] = -xyz4[8]; + xyz4[9] = -xyz4[9]; + xyz4[10] = -xyz4[10]; + xyz4[11] = -xyz4[11]; + aos_Vector4_0 = Vector4( xyz4[0], xyz4[1], xyz4[2], xyz4[3] ); + aos_Vector4_1 = Vector4( xyz4[4], xyz4[5], xyz4[6], xyz4[7] ); + aos_Vector4_2 = Vector4( xyz4[8], xyz4[9], xyz4[10], xyz4[11] ); + print( aos_Vector4_0, "xyzx" ); + print( aos_Vector4_1, "yzxy" ); + print( aos_Vector4_2, "zxyz" ); +#ifndef _VECTORMATH_SCALAR_TEST + loadXYZArray( aos_Vector3_0, aos_Vector3_1, aos_Vector3_2, aos_Vector3_3, (const vec_float4 *)xyz4 ); + xyz4[0] = 0; + xyz4[1] = 1; + xyz4[2] = 2; + xyz4[3] = 3; + xyz4[4] = 4; + xyz4[5] = 5; + xyz4[6] = 6; + xyz4[7] = 7; + xyz4[8] = 8; + xyz4[9] = 9; + xyz4[10] = 10; + xyz4[11] = 11; + storeXYZArray( aos_Vector3_0, aos_Vector3_1, aos_Vector3_2, aos_Vector3_3, (vec_float4 *)xyz4 ); +#endif + aos_Vector4_0 = Vector4( xyz4[0], xyz4[1], xyz4[2], xyz4[3] ); + aos_Vector4_1 = Vector4( xyz4[4], xyz4[5], xyz4[6], xyz4[7] ); + aos_Vector4_2 = Vector4( xyz4[8], xyz4[9], xyz4[10], xyz4[11] ); + print( aos_Vector4_0, "xyzx" ); + print( aos_Vector4_1, "yzxy" ); + print( aos_Vector4_2, "zxyz" ); +#ifdef _VECTORMATH_SCALAR_TEST + printf("storeXYZ:-1.0 -2.0 -3.0 0.4\n"); +#else + quad = (vec_float4){-1.0f, -2.0f, -3.0f, -4.0f}; + a_Vector3 = Vector3( quad ); + quad = (vec_float4){0.1f, 0.2f, 0.3f, 0.4f}; + storeXYZ( a_Vector3, &quad ); + printf("storeXYZ:%f %f %f %f\n", ((float *)&quad)[0], ((float *)&quad)[1], ((float *)&quad)[2], ((float *)&quad)[3]); +#endif + a_Vector3 = b_Vector3; + print( a_Vector3, "assign to Vector3 from Vector3" ); + a_Vector3 = Vector3( 0.0f ); + print( a_Vector3, "set Vector3 elements to zero" ); + a_Vector3 = Vector3::xAxis( ); + print( a_Vector3, "set to x axis" ); + a_Vector3 = Vector3::yAxis( ); + print( a_Vector3, "set to y axis" ); + a_Vector3 = Vector3::zAxis( ); + print( a_Vector3, "set to z axis" ); + if (iteration % 2) { + a_Vector3.setElem( 0, randfloat() ); + } else { + a_Vector3.setElem( 0, scalar_float(randfloat()) ); + } + print( a_Vector3, "Vector3::set( 0, float )" ); + a_Vector3[0] = randfloat(); + a_Vector3[0] *= randfloat(); + a_Vector3[0] /= randfloat(); + a_Vector3[0] += randfloat(); + a_Vector3[0] -= randfloat(); + print( a_Vector3, "Vector3::operator [](0)" ); + a_Vector3.setX( randfloat() ); + print( a_Vector3, "Vector3::setX()" ); + if (iteration % 2) { + a_Vector3.setElem( 1, randfloat() ); + } else { + a_Vector3.setElem( 1, scalar_float(randfloat()) ); + } + print( a_Vector3, "Vector3::set( 1, float )" ); + a_Vector3[1] = randfloat(); + a_Vector3[1] *= randfloat(); + a_Vector3[1] /= randfloat(); + a_Vector3[1] += randfloat(); + a_Vector3[1] -= randfloat(); + print( a_Vector3, "Vector3::operator [](1)" ); + a_Vector3.setY( randfloat() ); + print( a_Vector3, "Vector3::setY()" ); + if (iteration % 2) { + a_Vector3.setElem( 2, randfloat() ); + } else { + a_Vector3.setElem( 2, scalar_float(randfloat()) ); + } + print( a_Vector3, "Vector3::set( 2, float )" ); + a_Vector3[2] = randfloat(); + a_Vector3[2] *= randfloat(); + a_Vector3[2] /= randfloat(); + a_Vector3[2] += randfloat(); + a_Vector3[2] -= randfloat(); + print( a_Vector3, "Vector3::operator [](2)" ); + a_Vector3.setZ( randfloat() ); + print( a_Vector3, "Vector3::setZ()" ); + printf("Vector3::get( 0 ): %f\n", getfloat(a_Vector3.getElem( 0 )) ); + printf("Vector3::operator []( 0 ): %f\n", getfloat((float)a_Vector3[0]) ); + printf("Vector3::getX(): %f\n", getfloat(a_Vector3.getX( )) ); + printf("Vector3::get( 1 ): %f\n", getfloat(a_Vector3.getElem( 1 )) ); + printf("Vector3::operator []( 1 ): %f\n", getfloat((float)a_Vector3[1]) ); + printf("Vector3::getY(): %f\n", getfloat(a_Vector3.getY( )) ); + printf("Vector3::get( 2 ): %f\n", getfloat(a_Vector3.getElem( 2 )) ); + printf("Vector3::operator []( 2 ): %f\n", getfloat((float)a_Vector3[2]) ); + printf("Vector3::getZ(): %f\n", getfloat(a_Vector3.getZ( )) ); + print( ( a_Vector3 + b_Vector3 ), "Vector3 + Vector3" ); + print( ( a_Vector3 - b_Vector3 ), "Vector3 - Vector3" ); + print( ( a_Vector3 + b_Point3 ), "Vector3 + Point3" ); + print( ( a_Vector3 * randfloat() ), "Vector3 * float" ); + print( ( a_Vector3 / randfloat() ), "Vector3 / float" ); + print( ( randfloat() * a_Vector3 ), "float * Vector3" ); + print( ( -a_Vector3 ), "Vector3 negate" ); + print( mulPerElem( a_Vector3, b_Vector3 ), "mulPerElem( Vector3, Vector3 )" ); + print( divPerElem( a_Vector3, b_Vector3 ), "divPerElem( Vector3, Vector3 )" ); + print( recipPerElem( a_Vector3 ), "Vector3 recip" ); + print( sqrtPerElem( absPerElem( a_Vector3 ) ), "Vector3 sqrt" ); + print( rsqrtPerElem( absPerElem( a_Vector3 ) ), "Vector3 rsqrt" ); + print( absPerElem( a_Vector3 ), "Vector3 abs" ); + print( copySignPerElem( a_Vector3, b_Vector3 ), "Vector3 copySign" ); + print( maxPerElem( a_Vector3, b_Vector3 ), "Vector3 maximum Vector3" ); + print( minPerElem( a_Vector3, b_Vector3 ), "Vector3 minimum Vector3" ); + printf("Vector3 maximum of elements: %f\n", getfloat(maxElem( a_Vector3 ))); + printf("Vector3 minimum of elements: %f\n", getfloat(minElem( a_Vector3 ))); + printf("Vector3 sum of elements: %f\n", getfloat(sum( a_Vector3 ))); + printf("Vector3 dot Vector3: %f\n", getfloat(dot( a_Vector3, b_Vector3 ))); + printf("Vector3 lengthSqr: %f\n", getfloat(lengthSqr( a_Vector3 ))); + printf("Vector3 length: %f\n", getfloat(length( a_Vector3 ))); + print( normalize( a_Vector3 ), "Vector3 normalized" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + e_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + b_Vector3 = normalize( b_Vector3 ); + c_Vector3 = normalize( c_Vector3 ); + d_Vector3 = normalize( d_Vector3 ); + e_Vector3 = normalize( e_Vector3 ); + a_Vector3 = lerp( randfloat(), b_Vector3, c_Vector3 ); + print( a_Vector3, "Vector3 lerp" ); + a_Vector3 = slerp( randfloat(), b_Vector3, c_Vector3 ); + print( a_Vector3, "Vector3 slerp" ); +} + +void +Vector4_methods_test() +{ + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3, e_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4, e_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3, e_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat, e_Quat; + Vector4 tmpV4, aos_Vector4_0, aos_Vector4_1, aos_Vector4_2, aos_Vector4_3; + float rndflt1, rndflt2, rndflt3, rndflt4, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Vector3 = Vector3( scalar_float(rndflt1), scalar_float(rndflt2), scalar_float(rndflt3) ); + tmpV4 = Vector4( a_Vector3, pad ); + a_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( b_Vector3, pad ); + b_Vector3 = tmpV4.getXYZ( ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + c_Vector3 = Vector3( 0.0f ); + d_Vector3 = Vector3( 0.0f ); + e_Vector3 = Vector3( 0.0f ); + print( c_Vector3, "set Vector3 elements to zero" ); + print( d_Vector3, "set Vector3 elements to zero" ); + print( e_Vector3, "set Vector3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Vector4 = Vector4( scalar_float(rndflt1), scalar_float(rndflt2), scalar_float(rndflt3), scalar_float(rndflt4) ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + c_Vector4 = Vector4( 0.0f ); + d_Vector4 = Vector4( 0.0f ); + e_Vector4 = Vector4( 0.0f ); + print( c_Vector4, "set Vector4 elements to zero" ); + print( d_Vector4, "set Vector4 elements to zero" ); + print( e_Vector4, "set Vector4 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Point3 = Point3( scalar_float(rndflt1), scalar_float(rndflt2), scalar_float(rndflt3) ); + tmpV4 = Vector4( Vector3( a_Point3 ), pad ); + a_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( b_Point3 ), pad ); + b_Point3 = Point3( tmpV4.getXYZ( ) ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + c_Point3 = Point3( 0.0f ); + d_Point3 = Point3( 0.0f ); + e_Point3 = Point3( 0.0f ); + print( c_Point3, "set Point3 elements to zero" ); + print( d_Point3, "set Point3 elements to zero" ); + print( e_Point3, "set Point3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Quat = Quat( scalar_float(rndflt1), scalar_float(rndflt2), scalar_float(rndflt3), scalar_float(rndflt4) ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + c_Quat = Quat( 0.0f ); + d_Quat = Quat( 0.0f ); + e_Quat = Quat( 0.0f ); + print( c_Quat, "set Quat elements to zero" ); + print( d_Quat, "set Quat elements to zero" ); + print( e_Quat, "set Quat elements to zero" ); + a_Vector4 = Vector4( a_Vector3, randfloat() ); + print( a_Vector4, "set Vector4 with Vector3, float" ); + a_Vector4 = Vector4( a_Vector3 ); + print( a_Vector4, "set Vector4 with Vector3" ); + a_Vector4 = Vector4( a_Point3 ); + print( a_Vector4, "set Vector4 with Point3" ); + a_Vector4 = Vector4( a_Quat ); + print( a_Vector4, "construct Vector4 with Quat" ); + a_Vector4 = Vector4( randfloat() ); + print( a_Vector4, "set Vector4 with float" ); + a_Vector4 = Vector4( scalar_float(randfloat()) ); + print( a_Vector4, "set Vector4 with float" ); + aos_Vector4_0 = Vector4( 0.0f, 1.0f, 2.0f, 3.0f ); + aos_Vector4_1 = Vector4( 4.0f, 5.0f, 6.0f, 7.0f ); + aos_Vector4_2 = Vector4( 8.0f, 9.0f, 10.0f, 11.0f ); + aos_Vector4_3 = Vector4( 12.0f, 13.0f, 14.0f, 15.0f ); + print( aos_Vector4_3, "aos type 0" ); + print( aos_Vector4_2, "aos type 1" ); + print( aos_Vector4_1, "aos type 2" ); + print( aos_Vector4_0, "aos type 3" ); + print( select( a_Vector4, b_Vector4, 0 ), "select 0" ); + print( select( a_Vector4, b_Vector4, 1 ), "select 1" ); + print( select( a_Vector4, b_Vector4, 0 ), "select 2" ); + print( select( a_Vector4, b_Vector4, (unsigned int)-1 ), "select 3" ); + a_Vector4 = b_Vector4; + print( a_Vector4, "assign to Vector4 from Vector4" ); + a_Vector4.setXYZ( a_Vector3 ); + print( a_Vector4, "set Vector4 xyz" ); + print( a_Vector4.getXYZ( ), "get Vector4 xyz" ); + a_Vector4 = Vector4( 0.0f ); + print( a_Vector4, "set Vector4 elements to zero" ); + a_Vector4 = Vector4::xAxis( ); + print( a_Vector4, "set to x axis" ); + a_Vector4 = Vector4::yAxis( ); + print( a_Vector4, "set to y axis" ); + a_Vector4 = Vector4::zAxis( ); + print( a_Vector4, "set to z axis" ); + a_Vector4 = Vector4::wAxis( ); + print( a_Vector4, "set to w axis" ); + if (iteration % 2) { + a_Vector4.setElem( 0, randfloat() ); + } else { + a_Vector4.setElem( 0, scalar_float(randfloat()) ); + } + print( a_Vector4, "Vector4::set( 0, float )" ); + a_Vector4[0] = randfloat(); + a_Vector4[0] *= randfloat(); + a_Vector4[0] /= randfloat(); + a_Vector4[0] += randfloat(); + a_Vector4[0] -= randfloat(); + print( a_Vector4, "Vector4::operator [](0)" ); + a_Vector4.setX( randfloat() ); + print( a_Vector4, "Vector4::setX()" ); + if (iteration % 2) { + a_Vector4.setElem( 1, randfloat() ); + } else { + a_Vector4.setElem( 1, scalar_float(randfloat()) ); + } + print( a_Vector4, "Vector4::set( 1, float )" ); + a_Vector4[1] = randfloat(); + a_Vector4[1] *= randfloat(); + a_Vector4[1] /= randfloat(); + a_Vector4[1] += randfloat(); + a_Vector4[1] -= randfloat(); + print( a_Vector4, "Vector4::operator [](1)" ); + a_Vector4.setY( randfloat() ); + print( a_Vector4, "Vector4::setY()" ); + if (iteration % 2) { + a_Vector4.setElem( 2, randfloat() ); + } else { + a_Vector4.setElem( 2, scalar_float(randfloat()) ); + } + print( a_Vector4, "Vector4::set( 2, float )" ); + a_Vector4[2] = randfloat(); + a_Vector4[2] *= randfloat(); + a_Vector4[2] /= randfloat(); + a_Vector4[2] += randfloat(); + a_Vector4[2] -= randfloat(); + print( a_Vector4, "Vector4::operator [](2)" ); + a_Vector4.setZ( randfloat() ); + print( a_Vector4, "Vector4::setZ()" ); + if (iteration % 2) { + a_Vector4.setElem( 3, randfloat() ); + } else { + a_Vector4.setElem( 3, scalar_float(randfloat()) ); + } + print( a_Vector4, "Vector4::set( 3, float )" ); + a_Vector4[3] = randfloat(); + a_Vector4[3] *= randfloat(); + a_Vector4[3] /= randfloat(); + a_Vector4[3] += randfloat(); + a_Vector4[3] -= randfloat(); + print( a_Vector4, "Vector4::operator [](3)" ); + a_Vector4.setW( randfloat() ); + print( a_Vector4, "Vector4::setW()" ); + printf("Vector4::get( 0 ): %f\n", getfloat(a_Vector4.getElem( 0 )) ); + printf("Vector4::operator []( 0 ): %f\n", getfloat((float)a_Vector4[0]) ); + printf("Vector4::getX(): %f\n", getfloat(a_Vector4.getX( )) ); + printf("Vector4::get( 1 ): %f\n", getfloat(a_Vector4.getElem( 1 )) ); + printf("Vector4::operator []( 1 ): %f\n", getfloat((float)a_Vector4[1]) ); + printf("Vector4::getY(): %f\n", getfloat(a_Vector4.getY( )) ); + printf("Vector4::get( 2 ): %f\n", getfloat(a_Vector4.getElem( 2 )) ); + printf("Vector4::operator []( 2 ): %f\n", getfloat((float)a_Vector4[2]) ); + printf("Vector4::getZ(): %f\n", getfloat(a_Vector4.getZ( )) ); + printf("Vector4::get( 3 ): %f\n", getfloat(a_Vector4.getElem( 3 )) ); + printf("Vector4::operator []( 3 ): %f\n", getfloat((float)a_Vector4[3]) ); + printf("Vector4::getW(): %f\n", getfloat(a_Vector4.getW( )) ); + print( ( a_Vector4 + b_Vector4 ), "Vector4 + Vector4" ); + print( ( a_Vector4 - b_Vector4 ), "Vector4 - Vector4" ); + print( ( a_Vector4 * randfloat() ), "Vector4 * float" ); + print( ( a_Vector4 / randfloat() ), "Vector4 / float" ); + print( ( randfloat() * a_Vector4 ), "float * Vector4" ); + print( ( -a_Vector4 ), "Vector4 negate" ); + print( mulPerElem( a_Vector4, b_Vector4 ), "mulPerElem( Vector4, Vector4 )" ); + print( divPerElem( a_Vector4, b_Vector4 ), "divPerElem( Vector4, Vector4 )" ); + print( recipPerElem( a_Vector4 ), "Vector4 recip" ); + print( sqrtPerElem( absPerElem( a_Vector4 ) ), "Vector4 sqrt" ); + print( rsqrtPerElem( absPerElem( a_Vector4 ) ), "Vector4 rsqrt" ); + print( absPerElem( a_Vector4 ), "Vector4 abs" ); + print( copySignPerElem( a_Vector4, b_Vector4 ), "Vector4 copySign" ); + print( maxPerElem( a_Vector4, b_Vector4 ), "Vector4 maximum Vector4" ); + print( minPerElem( a_Vector4, b_Vector4 ), "Vector4 minimum Vector4" ); + printf("Vector4 maximum of elements: %f\n", getfloat(maxElem( a_Vector4 ))); + printf("Vector4 minimum of elements: %f\n", getfloat(minElem( a_Vector4 ))); + printf("Vector4 sum of elements: %f\n", getfloat(sum( a_Vector4 ))); + printf("Vector4 dot Vector4: %f\n", getfloat(dot( a_Vector4, b_Vector4 ))); + printf("Vector4 lengthSqr: %f\n", getfloat(lengthSqr( a_Vector4 ))); + printf("Vector4 length: %f\n", getfloat(length( a_Vector4 ))); + print( normalize( a_Vector4 ), "Vector4 normalized" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + e_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + b_Vector4 = normalize( b_Vector4 ); + c_Vector4 = normalize( c_Vector4 ); + d_Vector4 = normalize( d_Vector4 ); + e_Vector4 = normalize( e_Vector4 ); + a_Vector4 = lerp( randfloat(), b_Vector4, c_Vector4 ); + print( a_Vector4, "Vector4 lerp" ); + a_Vector4 = slerp( randfloat(), b_Vector4, c_Vector4 ); + print( a_Vector4, "Vector4 slerp" ); +} + +void +Point3_methods_test() +{ + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3, e_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4, e_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3, e_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat, e_Quat; + Vector4 tmpV4; + Point3 aos_Point3_0, aos_Point3_1, aos_Point3_2, aos_Point3_3; + Vector4 aos_Vector4_0, aos_Vector4_1, aos_Vector4_2; + float rndflt1, rndflt2, rndflt3, rndflt4, pad; + float xyz4[12] __attribute__ ((aligned(16))); +#ifndef _VECTORMATH_SCALAR_TEST + vec_float4 quad; +#endif + xyz4[0] = randfloat(); + xyz4[1] = randfloat(); + xyz4[2] = randfloat(); + xyz4[3] = randfloat(); + xyz4[4] = randfloat(); + xyz4[5] = randfloat(); + xyz4[6] = randfloat(); + xyz4[7] = randfloat(); + xyz4[8] = randfloat(); + xyz4[9] = randfloat(); + xyz4[10] = randfloat(); + xyz4[11] = randfloat(); + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Vector3 = Vector3( scalar_float(rndflt1), scalar_float(rndflt2), scalar_float(rndflt3) ); + tmpV4 = Vector4( a_Vector3, pad ); + a_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( b_Vector3, pad ); + b_Vector3 = tmpV4.getXYZ( ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + c_Vector3 = Vector3( 0.0f ); + d_Vector3 = Vector3( 0.0f ); + e_Vector3 = Vector3( 0.0f ); + print( c_Vector3, "set Vector3 elements to zero" ); + print( d_Vector3, "set Vector3 elements to zero" ); + print( e_Vector3, "set Vector3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Vector4 = Vector4( scalar_float(rndflt1), scalar_float(rndflt2), scalar_float(rndflt3), scalar_float(rndflt4) ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + c_Vector4 = Vector4( 0.0f ); + d_Vector4 = Vector4( 0.0f ); + e_Vector4 = Vector4( 0.0f ); + print( c_Vector4, "set Vector4 elements to zero" ); + print( d_Vector4, "set Vector4 elements to zero" ); + print( e_Vector4, "set Vector4 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Point3 = Point3( scalar_float(rndflt1), scalar_float(rndflt2), scalar_float(rndflt3) ); + tmpV4 = Vector4( Vector3( a_Point3 ), pad ); + a_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( b_Point3 ), pad ); + b_Point3 = Point3( tmpV4.getXYZ( ) ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + c_Point3 = Point3( 0.0f ); + d_Point3 = Point3( 0.0f ); + e_Point3 = Point3( 0.0f ); + print( c_Point3, "set Point3 elements to zero" ); + print( d_Point3, "set Point3 elements to zero" ); + print( e_Point3, "set Point3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Quat = Quat( scalar_float(rndflt1), scalar_float(rndflt2), scalar_float(rndflt3), scalar_float(rndflt4) ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + c_Quat = Quat( 0.0f ); + d_Quat = Quat( 0.0f ); + e_Quat = Quat( 0.0f ); + print( c_Quat, "set Quat elements to zero" ); + print( d_Quat, "set Quat elements to zero" ); + print( e_Quat, "set Quat elements to zero" ); + a_Point3 = Point3( a_Vector3 ); + print( a_Point3, "construct Point3 with Vector3" ); + a_Point3 = Point3( randfloat() ); + print( a_Point3, "set Point3 with float" ); + a_Point3 = Point3( scalar_float(randfloat()) ); + print( a_Point3, "set Point3 with float" ); + aos_Point3_0 = Point3( 0.0f, 1.0f, 2.0f ); + aos_Point3_1 = Point3( 3.0f, 4.0f, 5.0f ); + aos_Point3_2 = Point3( 6.0f, 7.0f, 8.0f ); + aos_Point3_3 = Point3( 9.0f, 10.0f, 11.0f ); + print( aos_Point3_3, "aos type 0" ); + print( aos_Point3_2, "aos type 1" ); + print( aos_Point3_1, "aos type 2" ); + print( aos_Point3_0, "aos type 3" ); + print( select( a_Point3, b_Point3, 0 ), "select 0" ); + print( select( a_Point3, b_Point3, 1 ), "select 1" ); + print( select( a_Point3, b_Point3, 0 ), "select 2" ); + print( select( a_Point3, b_Point3, (unsigned int)-1 ), "select 3" ); + a_Point3 = Point3( xyz4[0], xyz4[1], xyz4[2] ); + print( a_Point3, "load XYZ array" ); + xyz4[0] = -xyz4[0]; + xyz4[1] = -xyz4[1]; + xyz4[2] = -xyz4[2]; + xyz4[3] = -xyz4[3]; + xyz4[4] = -xyz4[4]; + xyz4[5] = -xyz4[5]; + xyz4[6] = -xyz4[6]; + xyz4[7] = -xyz4[7]; + xyz4[8] = -xyz4[8]; + xyz4[9] = -xyz4[9]; + xyz4[10] = -xyz4[10]; + xyz4[11] = -xyz4[11]; + aos_Vector4_0 = Vector4( xyz4[0], xyz4[1], xyz4[2], xyz4[3] ); + aos_Vector4_1 = Vector4( xyz4[4], xyz4[5], xyz4[6], xyz4[7] ); + aos_Vector4_2 = Vector4( xyz4[8], xyz4[9], xyz4[10], xyz4[11] ); + print( aos_Vector4_0, "xyzx" ); + print( aos_Vector4_1, "yzxy" ); + print( aos_Vector4_2, "zxyz" ); +#ifndef _VECTORMATH_SCALAR_TEST + loadXYZArray( aos_Point3_0, aos_Point3_1, aos_Point3_2, aos_Point3_3, (const vec_float4 *)xyz4 ); + xyz4[0] = 0; + xyz4[1] = 1; + xyz4[2] = 2; + xyz4[3] = 3; + xyz4[4] = 4; + xyz4[5] = 5; + xyz4[6] = 6; + xyz4[7] = 7; + xyz4[8] = 8; + xyz4[9] = 9; + xyz4[10] = 10; + xyz4[11] = 11; + storeXYZArray( aos_Point3_0, aos_Point3_1, aos_Point3_2, aos_Point3_3, (vec_float4 *)xyz4 ); +#endif + aos_Vector4_0 = Vector4( xyz4[0], xyz4[1], xyz4[2], xyz4[3] ); + aos_Vector4_1 = Vector4( xyz4[4], xyz4[5], xyz4[6], xyz4[7] ); + aos_Vector4_2 = Vector4( xyz4[8], xyz4[9], xyz4[10], xyz4[11] ); + print( aos_Vector4_0, "xyzx" ); + print( aos_Vector4_1, "yzxy" ); + print( aos_Vector4_2, "zxyz" ); +#ifdef _VECTORMATH_SCALAR_TEST + printf("storeXYZ:-1.0 -2.0 -3.0 0.4\n"); +#else + quad = (vec_float4){-1.0f, -2.0f, -3.0f, -4.0f}; + a_Point3 = Point3( quad ); + quad = (vec_float4){0.1f, 0.2f, 0.3f, 0.4f}; + storeXYZ( a_Point3, &quad ); + printf("storeXYZ:%f %f %f %f\n", ((float *)&quad)[0], ((float *)&quad)[1], ((float *)&quad)[2], ((float *)&quad)[3]); +#endif + a_Point3 = b_Point3; + print( a_Point3, "assign to Point3 from Point3" ); + a_Point3 = Point3( 0.0f ); + print( a_Point3, "set Point3 elements to zero" ); + if (iteration % 2) { + a_Point3.setElem( 0, randfloat() ); + } else { + a_Point3.setElem( 0, scalar_float(randfloat()) ); + } + print( a_Point3, "Point3::set( 0, float )" ); + a_Point3[0] = randfloat(); + a_Point3[0] *= randfloat(); + a_Point3[0] /= randfloat(); + a_Point3[0] += randfloat(); + a_Point3[0] -= randfloat(); + print( a_Point3, "Point3::operator [](0)" ); + a_Point3.setX( randfloat() ); + print( a_Point3, "Point3::setX()" ); + if (iteration % 2) { + a_Point3.setElem( 1, randfloat() ); + } else { + a_Point3.setElem( 1, scalar_float(randfloat()) ); + } + print( a_Point3, "Point3::set( 1, float )" ); + a_Point3[1] = randfloat(); + a_Point3[1] *= randfloat(); + a_Point3[1] /= randfloat(); + a_Point3[1] += randfloat(); + a_Point3[1] -= randfloat(); + print( a_Point3, "Point3::operator [](1)" ); + a_Point3.setY( randfloat() ); + print( a_Point3, "Point3::setY()" ); + if (iteration % 2) { + a_Point3.setElem( 2, randfloat() ); + } else { + a_Point3.setElem( 2, scalar_float(randfloat()) ); + } + print( a_Point3, "Point3::set( 2, float )" ); + a_Point3[2] = randfloat(); + a_Point3[2] *= randfloat(); + a_Point3[2] /= randfloat(); + a_Point3[2] += randfloat(); + a_Point3[2] -= randfloat(); + print( a_Point3, "Point3::operator [](2)" ); + a_Point3.setZ( randfloat() ); + print( a_Point3, "Point3::setZ()" ); + printf("Point3::get( 0 ): %f\n", getfloat(a_Point3.getElem( 0 )) ); + printf("Point3::operator []( 0 ): %f\n", getfloat((float)a_Point3[0]) ); + printf("Point3::getX(): %f\n", getfloat(a_Point3.getX( )) ); + printf("Point3::get( 1 ): %f\n", getfloat(a_Point3.getElem( 1 )) ); + printf("Point3::operator []( 1 ): %f\n", getfloat((float)a_Point3[1]) ); + printf("Point3::getY(): %f\n", getfloat(a_Point3.getY( )) ); + printf("Point3::get( 2 ): %f\n", getfloat(a_Point3.getElem( 2 )) ); + printf("Point3::operator []( 2 ): %f\n", getfloat((float)a_Point3[2]) ); + printf("Point3::getZ(): %f\n", getfloat(a_Point3.getZ( )) ); + print( ( a_Point3 - b_Point3 ), "Point3 - Point3" ); + print( ( a_Point3 + b_Vector3 ), "Point3 + Vector3" ); + print( ( a_Point3 - b_Vector3 ), "Point3 - Vector3" ); + print( mulPerElem( a_Point3, b_Point3 ), "mulPerElem( Point3, Point3 )" ); + print( divPerElem( a_Point3, b_Point3 ), "divPerElem( Point3, Point3 )" ); + print( recipPerElem( a_Point3 ), "Point3 recip" ); + print( sqrtPerElem( absPerElem( a_Point3 ) ), "Point3 sqrt" ); + print( rsqrtPerElem( absPerElem( a_Point3 ) ), "Point3 rsqrt" ); + print( absPerElem( a_Point3 ), "Point3 abs" ); + print( copySignPerElem( a_Point3, b_Point3 ), "Point3 copySign" ); + print( maxPerElem( a_Point3, b_Point3 ), "Point3 maximum Point3" ); + print( minPerElem( a_Point3, b_Point3 ), "Point3 minimum Point3" ); + printf("Point3 maximum of elements: %f\n", getfloat(maxElem( a_Point3 ))); + printf("Point3 minimum of elements: %f\n", getfloat(minElem( a_Point3 ))); + printf("Point3 sum of elements: %f\n", getfloat(sum( a_Point3 ))); + printf("Point projection: %f\n", getfloat(projection( a_Point3, b_Vector3 ))); + printf("Point distSqrFromOrigin: %f\n", getfloat(distSqrFromOrigin( a_Point3 )) ); + printf("Point distFromOrigin: %f\n", getfloat(distFromOrigin( a_Point3 )) ); + printf("Point distSqr: %f\n", getfloat(distSqr( a_Point3, b_Point3 )) ); + printf("Point dist: %f\n", getfloat(dist( a_Point3, b_Point3 )) ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + e_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + a_Point3 = lerp( randfloat(), b_Point3, c_Point3 ); + print( a_Point3, "Point3 lerp" ); +} + +void +Quat_methods_test() +{ + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3, e_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4, e_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3, e_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat, e_Quat; + Vector4 tmpV4; + Quat aos_Quat_0, aos_Quat_1, aos_Quat_2, aos_Quat_3; + float rndflt1, rndflt2, rndflt3, rndflt4, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Vector3 = Vector3( scalar_float(rndflt1), scalar_float(rndflt2), scalar_float(rndflt3) ); + tmpV4 = Vector4( a_Vector3, pad ); + a_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( b_Vector3, pad ); + b_Vector3 = tmpV4.getXYZ( ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + c_Vector3 = Vector3( 0.0f ); + d_Vector3 = Vector3( 0.0f ); + e_Vector3 = Vector3( 0.0f ); + print( c_Vector3, "set Vector3 elements to zero" ); + print( d_Vector3, "set Vector3 elements to zero" ); + print( e_Vector3, "set Vector3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Vector4 = Vector4( scalar_float(rndflt1), scalar_float(rndflt2), scalar_float(rndflt3), scalar_float(rndflt4) ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + c_Vector4 = Vector4( 0.0f ); + d_Vector4 = Vector4( 0.0f ); + e_Vector4 = Vector4( 0.0f ); + print( c_Vector4, "set Vector4 elements to zero" ); + print( d_Vector4, "set Vector4 elements to zero" ); + print( e_Vector4, "set Vector4 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Point3 = Point3( scalar_float(rndflt1), scalar_float(rndflt2), scalar_float(rndflt3) ); + tmpV4 = Vector4( Vector3( a_Point3 ), pad ); + a_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( b_Point3 ), pad ); + b_Point3 = Point3( tmpV4.getXYZ( ) ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + c_Point3 = Point3( 0.0f ); + d_Point3 = Point3( 0.0f ); + e_Point3 = Point3( 0.0f ); + print( c_Point3, "set Point3 elements to zero" ); + print( d_Point3, "set Point3 elements to zero" ); + print( e_Point3, "set Point3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Quat = Quat( scalar_float(rndflt1), scalar_float(rndflt2), scalar_float(rndflt3), scalar_float(rndflt4) ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + c_Quat = Quat( 0.0f ); + d_Quat = Quat( 0.0f ); + e_Quat = Quat( 0.0f ); + print( c_Quat, "set Quat elements to zero" ); + print( d_Quat, "set Quat elements to zero" ); + print( e_Quat, "set Quat elements to zero" ); + a_Quat = Quat( a_Vector3, randfloat() ); + print( a_Quat, "set Quat with Vector3, float" ); + a_Quat = Quat( a_Vector4 ); + print( a_Quat, "construct Quat with Vector4" ); + a_Quat = Quat( randfloat() ); + print( a_Quat, "set Quat with float" ); + a_Quat = Quat( scalar_float(randfloat()) ); + print( a_Quat, "set Quat with float" ); + aos_Quat_0 = Quat( 0.0f, 1.0f, 2.0f, 3.0f ); + aos_Quat_1 = Quat( 4.0f, 5.0f, 6.0f, 7.0f ); + aos_Quat_2 = Quat( 8.0f, 9.0f, 10.0f, 11.0f ); + aos_Quat_3 = Quat( 12.0f, 13.0f, 14.0f, 15.0f ); + print( aos_Quat_3, "aos type 0" ); + print( aos_Quat_2, "aos type 1" ); + print( aos_Quat_1, "aos type 2" ); + print( aos_Quat_0, "aos type 3" ); + print( select( a_Quat, b_Quat, 0 ), "select 0" ); + print( select( a_Quat, b_Quat, 1 ), "select 1" ); + print( select( a_Quat, b_Quat, 0 ), "select 2" ); + print( select( a_Quat, b_Quat, (unsigned int)-1 ), "select 3" ); + a_Quat = b_Quat; + print( a_Quat, "assign to Quat from Quat" ); + a_Quat.setXYZ( a_Vector3 ); + print( a_Quat, "set Quat xyz" ); + print( a_Quat.getXYZ( ), "get Quat xyz" ); + a_Quat = Quat( 0.0f ); + print( a_Quat, "set Quat elements to zero" ); + if (iteration % 2) { + a_Quat.setElem( 0, randfloat() ); + } else { + a_Quat.setElem( 0, scalar_float(randfloat()) ); + } + print( a_Quat, "Quat::set( 0, float )" ); + a_Quat[0] = randfloat(); + a_Quat[0] *= randfloat(); + a_Quat[0] /= randfloat(); + a_Quat[0] += randfloat(); + a_Quat[0] -= randfloat(); + print( a_Quat, "Quat::operator [](0)" ); + a_Quat.setX( randfloat() ); + print( a_Quat, "Quat::setX()" ); + if (iteration % 2) { + a_Quat.setElem( 1, randfloat() ); + } else { + a_Quat.setElem( 1, scalar_float(randfloat()) ); + } + print( a_Quat, "Quat::set( 1, float )" ); + a_Quat[1] = randfloat(); + a_Quat[1] *= randfloat(); + a_Quat[1] /= randfloat(); + a_Quat[1] += randfloat(); + a_Quat[1] -= randfloat(); + print( a_Quat, "Quat::operator [](1)" ); + a_Quat.setY( randfloat() ); + print( a_Quat, "Quat::setY()" ); + if (iteration % 2) { + a_Quat.setElem( 2, randfloat() ); + } else { + a_Quat.setElem( 2, scalar_float(randfloat()) ); + } + print( a_Quat, "Quat::set( 2, float )" ); + a_Quat[2] = randfloat(); + a_Quat[2] *= randfloat(); + a_Quat[2] /= randfloat(); + a_Quat[2] += randfloat(); + a_Quat[2] -= randfloat(); + print( a_Quat, "Quat::operator [](2)" ); + a_Quat.setZ( randfloat() ); + print( a_Quat, "Quat::setZ()" ); + if (iteration % 2) { + a_Quat.setElem( 3, randfloat() ); + } else { + a_Quat.setElem( 3, scalar_float(randfloat()) ); + } + print( a_Quat, "Quat::set( 3, float )" ); + a_Quat[3] = randfloat(); + a_Quat[3] *= randfloat(); + a_Quat[3] /= randfloat(); + a_Quat[3] += randfloat(); + a_Quat[3] -= randfloat(); + print( a_Quat, "Quat::operator [](3)" ); + a_Quat.setW( randfloat() ); + print( a_Quat, "Quat::setW()" ); + printf("Quat::get( 0 ): %f\n", getfloat(a_Quat.getElem( 0 )) ); + printf("Quat::operator []( 0 ): %f\n", getfloat((float)a_Quat[0]) ); + printf("Quat::getX(): %f\n", getfloat(a_Quat.getX( )) ); + printf("Quat::get( 1 ): %f\n", getfloat(a_Quat.getElem( 1 )) ); + printf("Quat::operator []( 1 ): %f\n", getfloat((float)a_Quat[1]) ); + printf("Quat::getY(): %f\n", getfloat(a_Quat.getY( )) ); + printf("Quat::get( 2 ): %f\n", getfloat(a_Quat.getElem( 2 )) ); + printf("Quat::operator []( 2 ): %f\n", getfloat((float)a_Quat[2]) ); + printf("Quat::getZ(): %f\n", getfloat(a_Quat.getZ( )) ); + printf("Quat::get( 3 ): %f\n", getfloat(a_Quat.getElem( 3 )) ); + printf("Quat::operator []( 3 ): %f\n", getfloat((float)a_Quat[3]) ); + printf("Quat::getW(): %f\n", getfloat(a_Quat.getW( )) ); + print( ( a_Quat + b_Quat ), "Quat + Quat" ); + print( ( a_Quat - b_Quat ), "Quat - Quat" ); + print( ( a_Quat * b_Quat ), "Quat * Quat" ); + print( ( a_Quat * randfloat() ), "Quat * float" ); + print( ( a_Quat / randfloat() ), "Quat / float" ); + print( ( randfloat() * a_Quat ), "float * Quat" ); + print( ( -a_Quat ), "Quat negate" ); + printf("Quat dot Quat: %f\n", getfloat(dot( a_Quat, b_Quat ))); + printf("Quat lengthSqr: %f\n", getfloat(norm( a_Quat ))); + printf("Quat length: %f\n", getfloat(length( a_Quat ))); + print( normalize( a_Quat ), "Quat normalized" ); + a_Quat = Quat::identity( ); + print( a_Quat, "set to identity" ); + a_Quat = Quat::rotation( a_Vector3, b_Vector3 ); + print( a_Quat, "Quat rotation between vectors" ); + a_Quat = Quat::rotation( randfloat(), a_Vector3 ); + print( a_Quat, "Quat rotation axis angle" ); + a_Quat = Quat::rotationX( randfloat() ); + print( a_Quat, "Quat rotationX" ); + a_Quat = Quat::rotationY( randfloat() ); + print( a_Quat, "Quat rotationY" ); + a_Quat = Quat::rotationZ( randfloat() ); + print( a_Quat, "Quat rotationZ" ); + print( rotate( a_Quat, a_Vector3 ), "Quat rotate Vector3" ); + print( conj( a_Quat ), "Quat conj" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + e_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + b_Quat = normalize( b_Quat ); + c_Quat = normalize( c_Quat ); + d_Quat = normalize( d_Quat ); + e_Quat = normalize( e_Quat ); + a_Quat = lerp( randfloat(), b_Quat, c_Quat ); + print( a_Quat, "Quat lerp" ); + a_Quat = slerp( randfloat(), b_Quat, c_Quat ); + print( a_Quat, "Quat slerp" ); + a_Quat = squad( randfloat(), b_Quat, c_Quat, d_Quat, e_Quat ); + print( a_Quat, "Quat squad" ); +} + +int main() +{ + printf("\n __begin__ \n"); + for ( iteration = 0; iteration < 2; iteration++ ) { + Vector3_methods_test(); + Vector4_methods_test(); + Point3_methods_test(); + Quat_methods_test(); + } + printf("\n __end__ \n"); + return 0; +} diff --git a/Extras/vectormathlibrary/tests/test1_reference.txt b/Extras/vectormathlibrary/tests/test1_reference.txt new file mode 100644 index 0000000..69af2d5 --- /dev/null +++ b/Extras/vectormathlibrary/tests/test1_reference.txt @@ -0,0 +1,680 @@ +set Vector3 with floats: ( 0.465039 -0.479556 -0.211412 ) +set Vector3 with floats: ( 0.553580 0.690070 0.151576 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector4 with floats: ( 0.431077 -0.833992 -0.088350 -0.780106 ) +set Vector4 with floats: ( 0.090456 -0.218627 0.137171 0.918133 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Point3 with floats: ( 0.735438 -0.673621 -0.448982 ) +set Point3 with floats: ( -0.479278 0.848189 -0.128155 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Quat with floats: ( 0.578922 -0.744766 -0.835589 0.881284 ) +set Quat with floats: ( -0.948850 -0.691578 -0.235635 -0.690527 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +construct Vector3 with Point3: ( 0.735438 -0.673621 -0.448982 ) +set Vector3 with float: ( 0.058667 0.058667 0.058667 ) +set Vector3 with float: ( 0.753697 0.753697 0.753697 ) +aos type 0: ( 9.000000 10.000000 11.000000 ) +aos type 1: ( 6.000000 7.000000 8.000000 ) +aos type 2: ( 3.000000 4.000000 5.000000 ) +aos type 3: ( 0.000000 1.000000 2.000000 ) +select 0: ( 0.753697 0.753697 0.753697 ) +select 1: ( 0.553580 0.690070 0.151576 ) +select 2: ( 0.753697 0.753697 0.753697 ) +select 3: ( 0.553580 0.690070 0.151576 ) +load XYZ array: ( -0.658344 0.499804 -0.807257 ) +xyzx: ( 0.658344 -0.499804 0.807257 -0.740930 ) +yzxy: ( -0.154607 -0.571599 -0.384388 0.262467 ) +zxyz: ( -0.747808 -0.490190 0.107908 0.292544 ) +xyzx: ( 0.658344 -0.499804 0.807257 -0.740930 ) +yzxy: ( -0.154607 -0.571599 -0.384388 0.262467 ) +zxyz: ( -0.747808 -0.490190 0.107908 0.292544 ) +storeXYZ:-1.0 -2.0 -3.0 0.4 +assign to Vector3 from Vector3: ( 0.553580 0.690070 0.151576 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set to x axis: ( 1.000000 0.000000 0.000000 ) +set to y axis: ( 0.000000 1.000000 0.000000 ) +set to z axis: ( 0.000000 0.000000 1.000000 ) +Vector3::set( 0, float ): ( -0.138777 0.000000 1.000000 ) +Vector3::operator [](0): ( -1.001420 0.000000 1.000000 ) +Vector3::setX(): ( 0.410391 0.000000 1.000000 ) +Vector3::set( 1, float ): ( 0.410391 -0.562721 1.000000 ) +Vector3::operator [](1): ( 0.410391 0.544473 1.000000 ) +Vector3::setY(): ( 0.410391 0.374881 1.000000 ) +Vector3::set( 2, float ): ( 0.410391 0.374881 -0.127818 ) +Vector3::operator [](2): ( 0.410391 0.374881 -0.212598 ) +Vector3::setZ(): ( 0.410391 0.374881 -0.723410 ) +Vector3::get( 0 ): 0.410391 +Vector3::operator []( 0 ): 0.410391 +Vector3::getX(): 0.410391 +Vector3::get( 1 ): 0.374881 +Vector3::operator []( 1 ): 0.374881 +Vector3::getY(): 0.374881 +Vector3::get( 2 ): -0.723410 +Vector3::operator []( 2 ): -0.723410 +Vector3::getZ(): -0.723410 +Vector3 + Vector3: ( 0.963971 1.064952 -0.571834 ) +Vector3 - Vector3: ( -0.143189 -0.315189 -0.874987 ) +Vector3 + Point3: ( -0.068887 1.223071 -0.851565 ) +Vector3 * float: ( 0.378185 0.345462 -0.666639 ) +Vector3 / float: ( -0.577000 -0.527074 1.017097 ) +float * Vector3: ( -0.043762 -0.039975 0.077140 ) +Vector3 negate: ( -0.410391 -0.374881 0.723410 ) +mulPerElem( Vector3, Vector3 ): ( 0.227184 0.258694 -0.109652 ) +divPerElem( Vector3, Vector3 ): ( 0.741340 0.543251 -4.772578 ) +Vector3 recip: ( 2.436700 2.667511 -1.382342 ) +Vector3 sqrt: ( 0.640618 0.612276 0.850535 ) +Vector3 rsqrt: ( 1.560993 1.633252 1.175730 ) +Vector3 abs: ( 0.410391 0.374881 0.723410 ) +Vector3 copySign: ( 0.410391 0.374881 0.723410 ) +Vector3 maximum Vector3: ( 0.553580 0.690070 0.151576 ) +Vector3 minimum Vector3: ( 0.410391 0.374881 -0.723410 ) +Vector3 maximum of elements: 0.410391 +Vector3 minimum of elements: -0.723410 +Vector3 sum of elements: 0.061862 +Vector3 dot Vector3: 0.376227 +Vector3 lengthSqr: 0.832279 +Vector3 length: 0.912293 +Vector3 normalized: ( 0.449846 0.410922 -0.792958 ) +Vector3 lerp: ( -0.504755 2.242539 -1.172064 ) +Vector3 slerp: ( -0.308956 -0.503372 0.806947 ) +set Vector3 with floats: ( 0.932526 0.571087 0.610330 ) +set Vector3 with floats: ( 0.142507 -0.434829 0.925102 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector4 with floats: ( 0.158954 -0.126283 -0.249128 0.846815 ) +set Vector4 with floats: ( -0.942601 0.537720 0.446214 0.181939 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Point3 with floats: ( -0.148223 0.284286 0.493525 ) +set Point3 with floats: ( -0.861963 -0.893410 0.548627 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Quat with floats: ( 0.407007 -0.757467 -0.393126 -0.850984 ) +set Quat with floats: ( 0.375720 -0.270088 0.458888 -0.610828 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 with Vector3, float: ( 0.932526 0.571087 0.610330 -0.690816 ) +set Vector4 with Vector3: ( 0.932526 0.571087 0.610330 0.000000 ) +set Vector4 with Point3: ( -0.148223 0.284286 0.493525 1.000000 ) +construct Vector4 with Quat: ( 0.407007 -0.757467 -0.393126 -0.850984 ) +set Vector4 with float: ( -0.676415 -0.676415 -0.676415 -0.676415 ) +set Vector4 with float: ( 0.664466 0.664466 0.664466 0.664466 ) +aos type 0: ( 12.000000 13.000000 14.000000 15.000000 ) +aos type 1: ( 8.000000 9.000000 10.000000 11.000000 ) +aos type 2: ( 4.000000 5.000000 6.000000 7.000000 ) +aos type 3: ( 0.000000 1.000000 2.000000 3.000000 ) +select 0: ( 0.664466 0.664466 0.664466 0.664466 ) +select 1: ( -0.942601 0.537720 0.446214 0.181939 ) +select 2: ( 0.664466 0.664466 0.664466 0.664466 ) +select 3: ( -0.942601 0.537720 0.446214 0.181939 ) +assign to Vector4 from Vector4: ( -0.942601 0.537720 0.446214 0.181939 ) +set Vector4 xyz: ( 0.932526 0.571087 0.610330 0.181939 ) +get Vector4 xyz: ( 0.932526 0.571087 0.610330 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set to x axis: ( 1.000000 0.000000 0.000000 0.000000 ) +set to y axis: ( 0.000000 1.000000 0.000000 0.000000 ) +set to z axis: ( 0.000000 0.000000 1.000000 0.000000 ) +set to w axis: ( 0.000000 0.000000 0.000000 1.000000 ) +Vector4::set( 0, float ): ( 0.101874 0.000000 0.000000 1.000000 ) +Vector4::operator [](0): ( -0.879952 0.000000 0.000000 1.000000 ) +Vector4::setX(): ( -0.997261 0.000000 0.000000 1.000000 ) +Vector4::set( 1, float ): ( -0.997261 0.172409 0.000000 1.000000 ) +Vector4::operator [](1): ( -0.997261 0.150201 0.000000 1.000000 ) +Vector4::setY(): ( -0.997261 -0.000013 0.000000 1.000000 ) +Vector4::set( 2, float ): ( -0.997261 -0.000013 0.689543 1.000000 ) +Vector4::operator [](2): ( -0.997261 -0.000013 -0.384253 1.000000 ) +Vector4::setZ(): ( -0.997261 -0.000013 -0.801022 1.000000 ) +Vector4::set( 3, float ): ( -0.997261 -0.000013 -0.801022 0.656335 ) +Vector4::operator [](3): ( -0.997261 -0.000013 -0.801022 16.472569 ) +Vector4::setW(): ( -0.997261 -0.000013 -0.801022 0.133022 ) +Vector4::get( 0 ): -0.997261 +Vector4::operator []( 0 ): -0.997261 +Vector4::getX(): -0.997261 +Vector4::get( 1 ): -0.000013 +Vector4::operator []( 1 ): -0.000013 +Vector4::getY(): -0.000013 +Vector4::get( 2 ): -0.801022 +Vector4::operator []( 2 ): -0.801022 +Vector4::getZ(): -0.801022 +Vector4::get( 3 ): 0.133022 +Vector4::operator []( 3 ): 0.133022 +Vector4::getW(): 0.133022 +Vector4 + Vector4: ( -1.939863 0.537707 -0.354808 0.314960 ) +Vector4 - Vector4: ( -0.054660 -0.537733 -1.247235 -0.048917 ) +Vector4 * float: ( 0.052076 0.000001 0.041829 -0.006946 ) +Vector4 / float: ( 6.048177 0.000081 4.858026 -0.806748 ) +float * Vector4: ( -0.299867 -0.000004 -0.240859 0.039998 ) +Vector4 negate: ( 0.997261 0.000013 0.801022 -0.133022 ) +mulPerElem( Vector4, Vector4 ): ( 0.940020 -0.000007 -0.357427 0.024202 ) +divPerElem( Vector4, Vector4 ): ( 1.057989 -0.000025 -1.795154 0.731134 ) +Vector4 recip: ( -1.002746 -75309.887339 -1.248405 7.517576 ) +Vector4 sqrt: ( 0.998630 0.003644 0.894998 0.364721 ) +Vector4 rsqrt: ( 1.001372 274.426483 1.117321 2.741820 ) +Vector4 abs: ( 0.997261 0.000013 0.801022 0.133022 ) +Vector4 copySign: ( -0.997261 0.000013 0.801022 0.133022 ) +Vector4 maximum Vector4: ( -0.942601 0.537720 0.446214 0.181939 ) +Vector4 minimum Vector4: ( -0.997261 -0.000013 -0.801022 0.133022 ) +Vector4 maximum of elements: 0.133022 +Vector4 minimum of elements: -0.997261 +Vector4 sum of elements: -1.665275 +Vector4 dot Vector4: 0.606788 +Vector4 lengthSqr: 1.653861 +Vector4 length: 1.286025 +Vector4 normalized: ( -0.775460 -0.000010 -0.622866 0.103436 ) +Vector4 lerp: ( -0.226675 0.250339 0.113208 0.735255 ) +Vector4 slerp: ( 0.351058 0.199306 -0.276993 0.871958 ) +set Vector3 with floats: ( 0.137637 -0.111879 -0.929543 ) +set Vector3 with floats: ( -0.336303 -0.146740 0.165140 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector4 with floats: ( -0.823874 0.349776 0.174872 -0.528584 ) +set Vector4 with floats: ( 0.489292 0.916708 0.728511 -0.851140 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Point3 with floats: ( 0.079620 -0.234370 -0.996308 ) +set Point3 with floats: ( 0.433229 -0.892684 -0.957911 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Quat with floats: ( 0.517122 0.257921 0.862028 0.095881 ) +set Quat with floats: ( -0.171933 -0.214078 -0.604841 -0.383831 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +construct Point3 with Vector3: ( 0.137637 -0.111879 -0.929543 ) +set Point3 with float: ( -0.581500 -0.581500 -0.581500 ) +set Point3 with float: ( 0.222183 0.222183 0.222183 ) +aos type 0: ( 9.000000 10.000000 11.000000 ) +aos type 1: ( 6.000000 7.000000 8.000000 ) +aos type 2: ( 3.000000 4.000000 5.000000 ) +aos type 3: ( 0.000000 1.000000 2.000000 ) +select 0: ( 0.222183 0.222183 0.222183 ) +select 1: ( 0.433229 -0.892684 -0.957911 ) +select 2: ( 0.222183 0.222183 0.222183 ) +select 3: ( 0.433229 -0.892684 -0.957911 ) +load XYZ array: ( -0.160082 0.962714 0.737794 ) +xyzx: ( 0.160082 -0.962714 -0.737794 0.071926 ) +yzxy: ( 0.506313 -0.689277 -0.686485 -0.473013 ) +zxyz: ( 0.735610 0.046390 -0.568674 0.004815 ) +xyzx: ( 0.160082 -0.962714 -0.737794 0.071926 ) +yzxy: ( 0.506313 -0.689277 -0.686485 -0.473013 ) +zxyz: ( 0.735610 0.046390 -0.568674 0.004815 ) +storeXYZ:-1.0 -2.0 -3.0 0.4 +assign to Point3 from Point3: ( 0.433229 -0.892684 -0.957911 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +Point3::set( 0, float ): ( -0.256120 0.000000 0.000000 ) +Point3::operator [](0): ( -0.979920 0.000000 0.000000 ) +Point3::setX(): ( -0.046627 0.000000 0.000000 ) +Point3::set( 1, float ): ( -0.046627 -0.716491 0.000000 ) +Point3::operator [](1): ( -0.046627 1.719236 0.000000 ) +Point3::setY(): ( -0.046627 0.508814 0.000000 ) +Point3::set( 2, float ): ( -0.046627 0.508814 -0.238839 ) +Point3::operator [](2): ( -0.046627 0.508814 0.061402 ) +Point3::setZ(): ( -0.046627 0.508814 -0.157280 ) +Point3::get( 0 ): -0.046627 +Point3::operator []( 0 ): -0.046627 +Point3::getX(): -0.046627 +Point3::get( 1 ): 0.508814 +Point3::operator []( 1 ): 0.508814 +Point3::getY(): 0.508814 +Point3::get( 2 ): -0.157280 +Point3::operator []( 2 ): -0.157280 +Point3::getZ(): -0.157280 +Point3 - Point3: ( -0.479856 1.401498 0.800631 ) +Point3 + Vector3: ( -0.382931 0.362074 0.007860 ) +Point3 - Vector3: ( 0.289676 0.655554 -0.322420 ) +mulPerElem( Point3, Point3 ): ( -0.020200 -0.454210 0.150660 ) +divPerElem( Point3, Point3 ): ( -0.107627 -0.569982 0.164191 ) +Point3 recip: ( -21.446777 1.965355 -6.358085 ) +Point3 sqrt: ( 0.215933 0.713312 0.396586 ) +Point3 rsqrt: ( 4.631066 1.401911 2.521524 ) +Point3 abs: ( 0.046627 0.508814 0.157280 ) +Point3 copySign: ( 0.046627 -0.508814 -0.157280 ) +Point3 maximum Point3: ( 0.433229 0.508814 -0.157280 ) +Point3 minimum Point3: ( -0.046627 -0.892684 -0.957911 ) +Point3 maximum of elements: 0.508814 +Point3 minimum of elements: -0.157280 +Point3 sum of elements: 0.304907 +Point projection: -0.084956 +Point distSqrFromOrigin: 0.285803 +Point distFromOrigin: 0.534605 +Point distSqr: 2.835468 +Point dist: 1.683885 +Point3 lerp: ( 0.508235 -0.017312 0.360111 ) +set Vector3 with floats: ( 0.219317 -0.118359 0.413442 ) +set Vector3 with floats: ( -0.567698 0.531358 -0.387226 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector4 with floats: ( 0.572490 -0.820417 0.797191 0.867178 ) +set Vector4 with floats: ( 0.934764 0.237092 -0.866162 -0.773939 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Point3 with floats: ( 0.261311 -0.851570 0.114814 ) +set Point3 with floats: ( -0.531592 0.223925 0.869105 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Quat with floats: ( 0.143405 0.148518 -0.071136 -0.758292 ) +set Quat with floats: ( -0.527633 0.997215 0.114440 0.727558 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat with Vector3, float: ( 0.219317 -0.118359 0.413442 -0.425760 ) +construct Quat with Vector4: ( 0.572490 -0.820417 0.797191 0.867178 ) +set Quat with float: ( 0.459888 0.459888 0.459888 0.459888 ) +set Quat with float: ( 0.642516 0.642516 0.642516 0.642516 ) +aos type 0: ( 12.000000 13.000000 14.000000 15.000000 ) +aos type 1: ( 8.000000 9.000000 10.000000 11.000000 ) +aos type 2: ( 4.000000 5.000000 6.000000 7.000000 ) +aos type 3: ( 0.000000 1.000000 2.000000 3.000000 ) +select 0: ( 0.642516 0.642516 0.642516 0.642516 ) +select 1: ( -0.527633 0.997215 0.114440 0.727558 ) +select 2: ( 0.642516 0.642516 0.642516 0.642516 ) +select 3: ( -0.527633 0.997215 0.114440 0.727558 ) +assign to Quat from Quat: ( -0.527633 0.997215 0.114440 0.727558 ) +set Quat xyz: ( 0.219317 -0.118359 0.413442 0.727558 ) +get Quat xyz: ( 0.219317 -0.118359 0.413442 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +Quat::set( 0, float ): ( -0.022534 0.000000 0.000000 0.000000 ) +Quat::operator [](0): ( 0.419714 0.000000 0.000000 0.000000 ) +Quat::setX(): ( 0.765986 0.000000 0.000000 0.000000 ) +Quat::set( 1, float ): ( 0.765986 -0.137795 0.000000 0.000000 ) +Quat::operator [](1): ( 0.765986 0.890273 0.000000 0.000000 ) +Quat::setY(): ( 0.765986 -0.553800 0.000000 0.000000 ) +Quat::set( 2, float ): ( 0.765986 -0.553800 -0.014688 0.000000 ) +Quat::operator [](2): ( 0.765986 -0.553800 -0.802660 0.000000 ) +Quat::setZ(): ( 0.765986 -0.553800 0.499529 0.000000 ) +Quat::set( 3, float ): ( 0.765986 -0.553800 0.499529 0.385180 ) +Quat::operator [](3): ( 0.765986 -0.553800 0.499529 -0.150467 ) +Quat::setW(): ( 0.765986 -0.553800 0.499529 0.067637 ) +Quat::get( 0 ): 0.765986 +Quat::operator []( 0 ): 0.765986 +Quat::getX(): 0.765986 +Quat::get( 1 ): -0.553800 +Quat::operator []( 1 ): -0.553800 +Quat::getY(): -0.553800 +Quat::get( 2 ): 0.499529 +Quat::operator []( 2 ): 0.499529 +Quat::getZ(): 0.499529 +Quat::get( 3 ): 0.067637 +Quat::operator []( 3 ): 0.067637 +Quat::getW(): 0.067637 +Quat + Quat: ( 0.238353 0.443416 0.613969 0.795196 ) +Quat - Quat: ( 1.293620 -1.551015 0.385089 -0.659921 ) +Quat * Quat: ( -0.039902 -0.686700 0.842827 0.948461 ) +Quat * float: ( 0.611545 -0.442140 0.398812 0.054000 ) +Quat / float: ( 2.464705 -1.781954 1.607327 0.217635 ) +float * Quat: ( 0.659770 -0.477006 0.430261 0.058258 ) +Quat negate: ( -0.765986 0.553800 -0.499529 -0.067637 ) +Quat dot Quat: -0.850041 +Quat lengthSqr: 1.147533 +Quat length: 1.071229 +Quat normalized: ( 0.715053 -0.516976 0.466313 0.063140 ) +set to identity: ( 0.000000 0.000000 0.000000 1.000000 ) +Quat rotation between vectors: ( -0.152187 -0.131117 0.043194 0.571186 ) +Quat rotation axis angle: ( -0.103250 0.055721 -0.194639 0.882252 ) +Quat rotationX: ( -0.321727 0.000000 0.000000 0.946833 ) +Quat rotationY: ( 0.000000 0.142892 0.000000 0.989738 ) +Quat rotationZ: ( 0.000000 0.000000 0.262912 0.964820 ) +Quat rotate Vector3: ( 0.249044 0.009268 0.413442 ) +Quat conj: ( -0.000000 -0.000000 -0.262912 0.964820 ) +Quat lerp: ( -0.053419 0.446373 0.392075 0.581368 ) +Quat slerp: ( -0.630711 0.472429 0.365730 0.495233 ) +Quat squad: ( 0.119307 -0.523957 -0.534187 -0.652594 ) +set Vector3 with floats: ( 0.531906 0.271995 -0.862601 ) +set Vector3 with floats: ( -0.738694 0.514248 -0.039363 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector4 with floats: ( 0.429390 -0.769469 0.281336 -0.203301 ) +set Vector4 with floats: ( 0.412586 0.567926 0.410131 -0.462918 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Point3 with floats: ( 0.560953 -0.731715 -0.446158 ) +set Point3 with floats: ( -0.837491 -0.573480 -0.607820 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Quat with floats: ( 0.238415 0.213445 0.098612 0.135072 ) +set Quat with floats: ( -0.749274 -0.855977 0.765675 -0.693447 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +construct Vector3 with Point3: ( 0.560953 -0.731715 -0.446158 ) +set Vector3 with float: ( 0.131554 0.131554 0.131554 ) +set Vector3 with float: ( -0.366757 -0.366757 -0.366757 ) +aos type 0: ( 9.000000 10.000000 11.000000 ) +aos type 1: ( 6.000000 7.000000 8.000000 ) +aos type 2: ( 3.000000 4.000000 5.000000 ) +aos type 3: ( 0.000000 1.000000 2.000000 ) +select 0: ( -0.366757 -0.366757 -0.366757 ) +select 1: ( -0.738694 0.514248 -0.039363 ) +select 2: ( -0.366757 -0.366757 -0.366757 ) +select 3: ( -0.738694 0.514248 -0.039363 ) +load XYZ array: ( -0.913636 0.675222 0.144053 ) +xyzx: ( 0.913636 -0.675222 -0.144053 0.632329 ) +yzxy: ( 0.947120 0.049367 -0.126333 0.664206 ) +zxyz: ( -0.220879 -0.284219 0.387216 -0.913568 ) +xyzx: ( 0.913636 -0.675222 -0.144053 0.632329 ) +yzxy: ( 0.947120 0.049367 -0.126333 0.664206 ) +zxyz: ( -0.220879 -0.284219 0.387216 -0.913568 ) +storeXYZ:-1.0 -2.0 -3.0 0.4 +assign to Vector3 from Vector3: ( -0.738694 0.514248 -0.039363 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set to x axis: ( 1.000000 0.000000 0.000000 ) +set to y axis: ( 0.000000 1.000000 0.000000 ) +set to z axis: ( 0.000000 0.000000 1.000000 ) +Vector3::set( 0, float ): ( -0.330409 0.000000 1.000000 ) +Vector3::operator [](0): ( -1.321680 0.000000 1.000000 ) +Vector3::setX(): ( -0.870739 0.000000 1.000000 ) +Vector3::set( 1, float ): ( -0.870739 0.415605 1.000000 ) +Vector3::operator [](1): ( -0.870739 -0.855146 1.000000 ) +Vector3::setY(): ( -0.870739 0.876855 1.000000 ) +Vector3::set( 2, float ): ( -0.870739 0.876855 0.982846 ) +Vector3::operator [](2): ( -0.870739 0.876855 -0.725814 ) +Vector3::setZ(): ( -0.870739 0.876855 -0.123567 ) +Vector3::get( 0 ): -0.870739 +Vector3::operator []( 0 ): -0.870739 +Vector3::getX(): -0.870739 +Vector3::get( 1 ): 0.876855 +Vector3::operator []( 1 ): 0.876855 +Vector3::getY(): 0.876855 +Vector3::get( 2 ): -0.123567 +Vector3::operator []( 2 ): -0.123567 +Vector3::getZ(): -0.123567 +Vector3 + Vector3: ( -1.609433 1.391104 -0.162930 ) +Vector3 - Vector3: ( -0.132046 0.362607 -0.084203 ) +Vector3 + Point3: ( -1.708231 0.303375 -0.731387 ) +Vector3 * float: ( -0.354427 0.356917 -0.050297 ) +Vector3 / float: ( -6.166518 6.209829 -0.875092 ) +float * Vector3: ( 0.690557 -0.695407 0.097997 ) +Vector3 negate: ( 0.870739 -0.876855 0.123567 ) +mulPerElem( Vector3, Vector3 ): ( 0.643210 0.450921 0.004864 ) +divPerElem( Vector3, Vector3 ): ( 1.178756 1.705119 3.139138 ) +Vector3 recip: ( -1.148449 1.140439 -8.092791 ) +Vector3 sqrt: ( 0.933134 0.936405 0.351521 ) +Vector3 rsqrt: ( 1.071657 1.067914 2.844783 ) +Vector3 abs: ( 0.870739 0.876855 0.123567 ) +Vector3 copySign: ( -0.870739 0.876855 -0.123567 ) +Vector3 maximum Vector3: ( -0.738694 0.876855 -0.039363 ) +Vector3 minimum Vector3: ( -0.870739 0.514248 -0.123567 ) +Vector3 maximum of elements: 0.876855 +Vector3 minimum of elements: -0.870739 +Vector3 sum of elements: -0.117451 +Vector3 dot Vector3: 1.098995 +Vector3 lengthSqr: 1.542330 +Vector3 length: 1.241906 +Vector3 normalized: ( -0.701131 0.706056 -0.099498 ) +Vector3 lerp: ( -0.118997 -0.338092 0.499550 ) +Vector3 slerp: ( -0.899759 -0.236062 -0.367027 ) +set Vector3 with floats: ( 0.060414 -0.867395 -0.702364 ) +set Vector3 with floats: ( -0.182602 -0.832807 0.278191 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector4 with floats: ( -0.967562 -0.520296 0.160191 -0.677990 ) +set Vector4 with floats: ( -0.470750 -0.846580 -0.705751 -0.825368 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Point3 with floats: ( -0.712890 -0.064487 0.444065 ) +set Point3 with floats: ( -0.045226 0.116544 -0.007285 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Quat with floats: ( -0.838230 -0.410767 -0.409299 -0.336683 ) +set Quat with floats: ( -0.830700 -0.801729 -0.595153 -0.784672 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 with Vector3, float: ( 0.060414 -0.867395 -0.702364 -0.653655 ) +set Vector4 with Vector3: ( 0.060414 -0.867395 -0.702364 0.000000 ) +set Vector4 with Point3: ( -0.712890 -0.064487 0.444065 1.000000 ) +construct Vector4 with Quat: ( -0.838230 -0.410767 -0.409299 -0.336683 ) +set Vector4 with float: ( 0.670791 0.670791 0.670791 0.670791 ) +set Vector4 with float: ( 0.653571 0.653571 0.653571 0.653571 ) +aos type 0: ( 12.000000 13.000000 14.000000 15.000000 ) +aos type 1: ( 8.000000 9.000000 10.000000 11.000000 ) +aos type 2: ( 4.000000 5.000000 6.000000 7.000000 ) +aos type 3: ( 0.000000 1.000000 2.000000 3.000000 ) +select 0: ( 0.653571 0.653571 0.653571 0.653571 ) +select 1: ( -0.470750 -0.846580 -0.705751 -0.825368 ) +select 2: ( 0.653571 0.653571 0.653571 0.653571 ) +select 3: ( -0.470750 -0.846580 -0.705751 -0.825368 ) +assign to Vector4 from Vector4: ( -0.470750 -0.846580 -0.705751 -0.825368 ) +set Vector4 xyz: ( 0.060414 -0.867395 -0.702364 -0.825368 ) +get Vector4 xyz: ( 0.060414 -0.867395 -0.702364 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set to x axis: ( 1.000000 0.000000 0.000000 0.000000 ) +set to y axis: ( 0.000000 1.000000 0.000000 0.000000 ) +set to z axis: ( 0.000000 0.000000 1.000000 0.000000 ) +set to w axis: ( 0.000000 0.000000 0.000000 1.000000 ) +Vector4::set( 0, float ): ( 0.850716 0.000000 0.000000 1.000000 ) +Vector4::operator [](0): ( -0.528836 0.000000 0.000000 1.000000 ) +Vector4::setX(): ( 0.965901 0.000000 0.000000 1.000000 ) +Vector4::set( 1, float ): ( 0.965901 -0.072675 0.000000 1.000000 ) +Vector4::operator [](1): ( 0.965901 0.450700 0.000000 1.000000 ) +Vector4::setY(): ( 0.965901 -0.825793 0.000000 1.000000 ) +Vector4::set( 2, float ): ( 0.965901 -0.825793 0.597719 1.000000 ) +Vector4::operator [](2): ( 0.965901 -0.825793 0.279622 1.000000 ) +Vector4::setZ(): ( 0.965901 -0.825793 -0.884427 1.000000 ) +Vector4::set( 3, float ): ( 0.965901 -0.825793 -0.884427 -0.756791 ) +Vector4::operator [](3): ( 0.965901 -0.825793 -0.884427 -0.685697 ) +Vector4::setW(): ( 0.965901 -0.825793 -0.884427 -0.684626 ) +Vector4::get( 0 ): 0.965901 +Vector4::operator []( 0 ): 0.965901 +Vector4::getX(): 0.965901 +Vector4::get( 1 ): -0.825793 +Vector4::operator []( 1 ): -0.825793 +Vector4::getY(): -0.825793 +Vector4::get( 2 ): -0.884427 +Vector4::operator []( 2 ): -0.884427 +Vector4::getZ(): -0.884427 +Vector4::get( 3 ): -0.684626 +Vector4::operator []( 3 ): -0.684626 +Vector4::getW(): -0.684626 +Vector4 + Vector4: ( 0.495151 -1.672373 -1.590178 -1.509993 ) +Vector4 - Vector4: ( 1.436652 0.020787 -0.178676 0.140742 ) +Vector4 * float: ( -0.960151 0.820877 0.879161 0.680550 ) +Vector4 / float: ( 1.206825 -1.031770 -1.105029 -0.855391 ) +float * Vector4: ( -0.546353 0.467102 0.500267 0.387252 ) +Vector4 negate: ( -0.965901 0.825793 0.884427 0.684626 ) +mulPerElem( Vector4, Vector4 ): ( -0.454698 0.699100 0.624185 0.565068 ) +divPerElem( Vector4, Vector4 ): ( -2.051834 0.975446 1.253172 0.829480 ) +Vector4 recip: ( 1.035302 -1.210957 -1.130676 -1.460652 ) +Vector4 sqrt: ( 0.982803 0.908731 0.940440 0.827421 ) +Vector4 rsqrt: ( 1.017498 1.100435 1.063332 1.208575 ) +Vector4 abs: ( 0.965901 0.825793 0.884427 0.684626 ) +Vector4 copySign: ( -0.965901 -0.825793 -0.884427 -0.684626 ) +Vector4 maximum Vector4: ( 0.965901 -0.825793 -0.705751 -0.684626 ) +Vector4 minimum Vector4: ( -0.470750 -0.846580 -0.884427 -0.825368 ) +Vector4 maximum of elements: 0.965901 +Vector4 minimum of elements: -0.884427 +Vector4 sum of elements: -1.428944 +Vector4 dot Vector4: 1.433654 +Vector4 lengthSqr: 2.865822 +Vector4 length: 1.692874 +Vector4 normalized: ( 0.570569 -0.487805 -0.522441 -0.404416 ) +Vector4 lerp: ( -0.436271 0.676982 0.475175 0.275280 ) +Vector4 slerp: ( -0.493672 0.661673 0.416222 0.381100 ) +set Vector3 with floats: ( -0.287826 0.942655 -0.634432 ) +set Vector3 with floats: ( -0.140438 0.570869 -0.764965 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector4 with floats: ( 0.067523 -0.514589 0.233091 0.554488 ) +set Vector4 with floats: ( -0.633529 -0.019374 0.869259 -0.369818 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Point3 with floats: ( -0.280690 -0.797209 -0.255233 ) +set Point3 with floats: ( 0.780605 0.789803 0.974262 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Quat with floats: ( -0.785980 -0.701386 0.871088 0.566743 ) +set Quat with floats: ( 0.752273 -0.476301 -0.747342 0.077386 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +construct Point3 with Vector3: ( -0.287826 0.942655 -0.634432 ) +set Point3 with float: ( -0.305600 -0.305600 -0.305600 ) +set Point3 with float: ( -0.229194 -0.229194 -0.229194 ) +aos type 0: ( 9.000000 10.000000 11.000000 ) +aos type 1: ( 6.000000 7.000000 8.000000 ) +aos type 2: ( 3.000000 4.000000 5.000000 ) +aos type 3: ( 0.000000 1.000000 2.000000 ) +select 0: ( -0.229194 -0.229194 -0.229194 ) +select 1: ( 0.780605 0.789803 0.974262 ) +select 2: ( -0.229194 -0.229194 -0.229194 ) +select 3: ( 0.780605 0.789803 0.974262 ) +load XYZ array: ( 0.376026 -0.935045 -0.189804 ) +xyzx: ( -0.376026 0.935045 0.189804 -0.007649 ) +yzxy: ( 0.440298 -0.994796 0.271484 0.259070 ) +zxyz: ( -0.902149 0.836501 -0.229093 -0.586393 ) +xyzx: ( -0.376026 0.935045 0.189804 -0.007649 ) +yzxy: ( 0.440298 -0.994796 0.271484 0.259070 ) +zxyz: ( -0.902149 0.836501 -0.229093 -0.586393 ) +storeXYZ:-1.0 -2.0 -3.0 0.4 +assign to Point3 from Point3: ( 0.780605 0.789803 0.974262 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +Point3::set( 0, float ): ( -0.260009 0.000000 0.000000 ) +Point3::operator [](0): ( 0.017680 0.000000 0.000000 ) +Point3::setX(): ( 0.912886 0.000000 0.000000 ) +Point3::set( 1, float ): ( 0.912886 -0.402380 0.000000 ) +Point3::operator [](1): ( 0.912886 1.043836 0.000000 ) +Point3::setY(): ( 0.912886 0.321576 0.000000 ) +Point3::set( 2, float ): ( 0.912886 0.321576 0.724026 ) +Point3::operator [](2): ( 0.912886 0.321576 -0.074816 ) +Point3::setZ(): ( 0.912886 0.321576 0.137730 ) +Point3::get( 0 ): 0.912886 +Point3::operator []( 0 ): 0.912886 +Point3::getX(): 0.912886 +Point3::get( 1 ): 0.321576 +Point3::operator []( 1 ): 0.321576 +Point3::getY(): 0.321576 +Point3::get( 2 ): 0.137730 +Point3::operator []( 2 ): 0.137730 +Point3::getZ(): 0.137730 +Point3 - Point3: ( 0.132280 -0.468228 -0.836532 ) +Point3 + Vector3: ( 0.772448 0.892445 -0.627235 ) +Point3 - Vector3: ( 1.053323 -0.249293 0.902695 ) +mulPerElem( Point3, Point3 ): ( 0.712603 0.253982 0.134185 ) +divPerElem( Point3, Point3 ): ( 1.169459 0.407159 0.141368 ) +Point3 recip: ( 1.095427 3.109689 7.260596 ) +Point3 sqrt: ( 0.955451 0.567076 0.371120 ) +Point3 rsqrt: ( 1.046627 1.763431 2.694549 ) +Point3 abs: ( 0.912886 0.321576 0.137730 ) +Point3 copySign: ( 0.912886 0.321576 0.137730 ) +Point3 maximum Point3: ( 0.912886 0.789803 0.974262 ) +Point3 minimum Point3: ( 0.780605 0.321576 0.137730 ) +Point3 maximum of elements: 0.912886 +Point3 minimum of elements: 0.137730 +Point3 sum of elements: 1.372191 +Point projection: -0.049984 +Point distSqrFromOrigin: 0.955741 +Point distFromOrigin: 0.977620 +Point distSqr: 0.936521 +Point dist: 0.967740 +Point3 lerp: ( -0.148533 -0.240318 0.263234 ) +set Vector3 with floats: ( -0.950919 -0.196258 -0.599808 ) +set Vector3 with floats: ( -0.794413 -0.927636 -0.187478 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Vector4 with floats: ( -0.113038 0.366120 -0.483786 0.622670 ) +set Vector4 with floats: ( -0.801806 0.295383 0.022005 -0.000678 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Vector4 elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Point3 with floats: ( -0.689334 0.266538 -0.785099 ) +set Point3 with floats: ( -0.572665 0.772760 0.971896 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Point3 elements to zero: ( 0.000000 0.000000 0.000000 ) +set Quat with floats: ( -0.961363 0.723449 -0.758442 -0.733158 ) +set Quat with floats: ( 0.139667 -0.738147 0.727224 0.089921 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +set Quat with Vector3, float: ( -0.950919 -0.196258 -0.599808 -0.113118 ) +construct Quat with Vector4: ( -0.113038 0.366120 -0.483786 0.622670 ) +set Quat with float: ( -0.364554 -0.364554 -0.364554 -0.364554 ) +set Quat with float: ( -0.137645 -0.137645 -0.137645 -0.137645 ) +aos type 0: ( 12.000000 13.000000 14.000000 15.000000 ) +aos type 1: ( 8.000000 9.000000 10.000000 11.000000 ) +aos type 2: ( 4.000000 5.000000 6.000000 7.000000 ) +aos type 3: ( 0.000000 1.000000 2.000000 3.000000 ) +select 0: ( -0.137645 -0.137645 -0.137645 -0.137645 ) +select 1: ( 0.139667 -0.738147 0.727224 0.089921 ) +select 2: ( -0.137645 -0.137645 -0.137645 -0.137645 ) +select 3: ( 0.139667 -0.738147 0.727224 0.089921 ) +assign to Quat from Quat: ( 0.139667 -0.738147 0.727224 0.089921 ) +set Quat xyz: ( -0.950919 -0.196258 -0.599808 0.089921 ) +get Quat xyz: ( -0.950919 -0.196258 -0.599808 ) +set Quat elements to zero: ( 0.000000 0.000000 0.000000 0.000000 ) +Quat::set( 0, float ): ( 0.933847 0.000000 0.000000 0.000000 ) +Quat::operator [](0): ( 2.026584 0.000000 0.000000 0.000000 ) +Quat::setX(): ( -0.069558 0.000000 0.000000 0.000000 ) +Quat::set( 1, float ): ( -0.069558 -0.216369 0.000000 0.000000 ) +Quat::operator [](1): ( -0.069558 -0.152646 0.000000 0.000000 ) +Quat::setY(): ( -0.069558 -0.022250 0.000000 0.000000 ) +Quat::set( 2, float ): ( -0.069558 -0.022250 0.035410 0.000000 ) +Quat::operator [](2): ( -0.069558 -0.022250 1.428823 0.000000 ) +Quat::setZ(): ( -0.069558 -0.022250 0.804061 0.000000 ) +Quat::set( 3, float ): ( -0.069558 -0.022250 0.804061 0.161693 ) +Quat::operator [](3): ( -0.069558 -0.022250 0.804061 -0.332169 ) +Quat::setW(): ( -0.069558 -0.022250 0.804061 -0.586017 ) +Quat::get( 0 ): -0.069558 +Quat::operator []( 0 ): -0.069558 +Quat::getX(): -0.069558 +Quat::get( 1 ): -0.022250 +Quat::operator []( 1 ): -0.022250 +Quat::getY(): -0.022250 +Quat::get( 2 ): 0.804061 +Quat::operator []( 2 ): 0.804061 +Quat::getZ(): 0.804061 +Quat::get( 3 ): -0.586017 +Quat::operator []( 3 ): -0.586017 +Quat::getW(): -0.586017 +Quat + Quat: ( 0.070108 -0.760397 1.531285 -0.496095 ) +Quat - Quat: ( -0.209225 0.715896 0.076837 -0.675938 ) +Quat * Quat: ( 0.489232 0.593451 -0.299411 -0.644137 ) +Quat * float: ( -0.031036 -0.009928 0.358759 -0.261471 ) +Quat / float: ( -0.103711 -0.033175 1.198842 -0.873742 ) +float * Quat: ( 0.021745 0.006956 -0.251360 0.183196 ) +Quat negate: ( 0.069558 0.022250 -0.804061 0.586017 ) +Quat dot Quat: 0.538746 +Quat lengthSqr: 0.995263 +Quat length: 0.997629 +Quat normalized: ( -0.069724 -0.022303 0.805972 -0.587410 ) +set to identity: ( 0.000000 0.000000 0.000000 1.000000 ) +Quat rotation between vectors: ( -0.256621 0.147283 0.358649 1.012405 ) +Quat rotation axis angle: ( 0.163854 0.033817 0.103354 0.985043 ) +Quat rotationX: ( -0.160489 0.000000 0.000000 0.987038 ) +Quat rotationY: ( 0.000000 0.030795 0.000000 0.999526 ) +Quat rotationZ: ( 0.000000 0.000000 0.054406 0.998519 ) +Quat rotate Vector3: ( -0.923966 -0.298415 -0.599808 ) +Quat conj: ( -0.000000 -0.000000 -0.054406 0.998519 ) +Quat lerp: ( -0.860671 -0.101017 0.008389 -0.459099 ) +Quat slerp: ( -0.935192 0.097684 -0.079386 -0.331015 ) +Quat squad: ( -0.208138 -0.281808 0.458751 -0.816585 ) + + __end__ diff --git a/Extras/vectormathlibrary/tests/test1_soa_c.c b/Extras/vectormathlibrary/tests/test1_soa_c.c new file mode 100644 index 0000000..985488f --- /dev/null +++ b/Extras/vectormathlibrary/tests/test1_soa_c.c @@ -0,0 +1,1006 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +#define _VECTORMATH_SOA_TEST + +#include "vectormath_soa.h" +#include "test.h" + +int iteration = 0; + +void +Vector3_methods_test() +{ + VmathSoaVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3, e_Vector3; + VmathSoaVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4, e_Vector4; + VmathSoaPoint3 a_Point3, b_Point3, c_Point3, d_Point3, e_Point3; + VmathSoaQuat a_Quat, b_Quat, c_Quat, d_Quat, e_Quat; + VmathVector3 aos_Vector3_0, aos_Vector3_1, aos_Vector3_2, aos_Vector3_3; + VmathSoaVector3 soa_Vector3; + VmathVector4 aos_Vector4_0, aos_Vector4_1, aos_Vector4_2; + VmathSoaVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3; + VmathSoaPoint3 tmpP3_0; + VmathSoaVector3 tmpV3_4, tmpV3_5, tmpV3_6, tmpV3_7, tmpV3_8, tmpV3_9, tmpV3_10, tmpV3_11, tmpV3_12, tmpV3_13, tmpV3_14, tmpV3_15, tmpV3_16, tmpV3_17, tmpV3_18, tmpV3_19; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4; + float xyz4[12] __attribute__ ((aligned(16))); + xyz4[0] = getfloat(randfloat()); + xyz4[1] = getfloat(randfloat()); + xyz4[2] = getfloat(randfloat()); + xyz4[3] = getfloat(randfloat()); + xyz4[4] = getfloat(randfloat()); + xyz4[5] = getfloat(randfloat()); + xyz4[6] = getfloat(randfloat()); + xyz4[7] = getfloat(randfloat()); + xyz4[8] = getfloat(randfloat()); + xyz4[9] = getfloat(randfloat()); + xyz4[10] = getfloat(randfloat()); + xyz4[11] = getfloat(randfloat()); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &b_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathSoaV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathSoaV3MakeFromScalar( &c_Vector3, (vec_float4){0.0f} ); + vmathSoaV3MakeFromScalar( &d_Vector3, (vec_float4){0.0f} ); + vmathSoaV3MakeFromScalar( &e_Vector3, (vec_float4){0.0f} ); + vmathSoaV3Prints( &c_Vector3, "set Vector3 elements to zero" ); + vmathSoaV3Prints( &d_Vector3, "set Vector3 elements to zero" ); + vmathSoaV3Prints( &e_Vector3, "set Vector3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &b_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathSoaV4MakeFromScalar( &c_Vector4, (vec_float4){0.0f} ); + vmathSoaV4MakeFromScalar( &d_Vector4, (vec_float4){0.0f} ); + vmathSoaV4MakeFromScalar( &e_Vector4, (vec_float4){0.0f} ); + vmathSoaV4Prints( &c_Vector4, "set Vector4 elements to zero" ); + vmathSoaV4Prints( &d_Vector4, "set Vector4 elements to zero" ); + vmathSoaV4Prints( &e_Vector4, "set Vector4 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &b_Point3, rndflt1, rndflt2, rndflt3 ); + vmathSoaP3Prints( &a_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &b_Point3, "set Point3 with floats" ); + vmathSoaP3MakeFromScalar( &c_Point3, (vec_float4){0.0f} ); + vmathSoaP3MakeFromScalar( &d_Point3, (vec_float4){0.0f} ); + vmathSoaP3MakeFromScalar( &e_Point3, (vec_float4){0.0f} ); + vmathSoaP3Prints( &c_Point3, "set Point3 elements to zero" ); + vmathSoaP3Prints( &d_Point3, "set Point3 elements to zero" ); + vmathSoaP3Prints( &e_Point3, "set Point3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &b_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaQPrints( &a_Quat, "set Quat with floats" ); + vmathSoaQPrints( &b_Quat, "set Quat with floats" ); + vmathSoaQMakeFromScalar( &c_Quat, (vec_float4){0.0f} ); + vmathSoaQMakeFromScalar( &d_Quat, (vec_float4){0.0f} ); + vmathSoaQMakeFromScalar( &e_Quat, (vec_float4){0.0f} ); + vmathSoaQPrints( &c_Quat, "set Quat elements to zero" ); + vmathSoaQPrints( &d_Quat, "set Quat elements to zero" ); + vmathSoaQPrints( &e_Quat, "set Quat elements to zero" ); + vmathSoaV3MakeFromP3( &a_Vector3, &a_Point3 ); + vmathSoaV3Prints( &a_Vector3, "construct Vector3 with Point3" ); + vmathSoaV3MakeFromScalar( &a_Vector3, randfloat() ); + vmathSoaV3Prints( &a_Vector3, "set Vector3 with float" ); + vmathSoaV3MakeFromScalar( &a_Vector3, randfloat() ); + vmathSoaV3Prints( &a_Vector3, "set Vector3 with float" ); + vmathV3MakeFromElems( &aos_Vector3_0, 0.0f, 1.0f, 2.0f ); + vmathV3MakeFromElems( &aos_Vector3_1, 3.0f, 4.0f, 5.0f ); + vmathV3MakeFromElems( &aos_Vector3_2, 6.0f, 7.0f, 8.0f ); + vmathV3MakeFromElems( &aos_Vector3_3, 9.0f, 10.0f, 11.0f ); + vmathSoaV3MakeFrom4Aos( &soa_Vector3, &aos_Vector3_0, &aos_Vector3_1, &aos_Vector3_2, &aos_Vector3_3 ); + vmathSoaV3Get4Aos( &soa_Vector3, &aos_Vector3_3, &aos_Vector3_2, &aos_Vector3_1, &aos_Vector3_0 ); + vmathV3Prints( &aos_Vector3_0, "aos type 0" ); + vmathV3Prints( &aos_Vector3_1, "aos type 1" ); + vmathV3Prints( &aos_Vector3_2, "aos type 2" ); + vmathV3Prints( &aos_Vector3_3, "aos type 3" ); + vmathSoaV3Select( &a_Vector3, &a_Vector3, &b_Vector3, ((vec_uint4){0,0xffffffff,0,0xffffffff}) ); + vmathSoaV3Get4Aos( &a_Vector3, &aos_Vector3_0, &aos_Vector3_1, &aos_Vector3_2, &aos_Vector3_3 ); + vmathV3Prints( &aos_Vector3_0, "select 0" ); + vmathV3Prints( &aos_Vector3_1, "select 1" ); + vmathV3Prints( &aos_Vector3_2, "select 2" ); + vmathV3Prints( &aos_Vector3_3, "select 3" ); + vmathSoaV3LoadXYZArray( &a_Vector3, (const vec_float4 *)xyz4 ); + vmathSoaV3Prints( &a_Vector3, "load XYZ array" ); + vmathSoaV3Copy( &tmpV3_0, &a_Vector3 ); + vmathSoaV3Neg( &tmpV3_1, &tmpV3_0 ); + vmathSoaV3Copy( &a_Vector3, &tmpV3_1 ); + vmathSoaV3StoreXYZArray( &a_Vector3, (vec_float4 *)xyz4 ); + vmathV4MakeFromElems( &aos_Vector4_0, xyz4[0], xyz4[1], xyz4[2], xyz4[3] ); + vmathV4MakeFromElems( &aos_Vector4_1, xyz4[4], xyz4[5], xyz4[6], xyz4[7] ); + vmathV4MakeFromElems( &aos_Vector4_2, xyz4[8], xyz4[9], xyz4[10], xyz4[11] ); + vmathV4Prints( &aos_Vector4_0, "xyzx" ); + vmathV4Prints( &aos_Vector4_1, "yzxy" ); + vmathV4Prints( &aos_Vector4_2, "zxyz" ); + vmathV4Prints( &aos_Vector4_0, "xyzx" ); + vmathV4Prints( &aos_Vector4_1, "yzxy" ); + vmathV4Prints( &aos_Vector4_2, "zxyz" ); + printf("storeXYZ:-1.0 -2.0 -3.0 0.4\n"); + vmathSoaV3Copy( &a_Vector3, &b_Vector3 ); + vmathSoaV3Prints( &a_Vector3, "assign to Vector3 from Vector3" ); + vmathSoaV3MakeFromScalar( &a_Vector3, (vec_float4){0.0f} ); + vmathSoaV3Prints( &a_Vector3, "set Vector3 elements to zero" ); + vmathSoaV3MakeXAxis( &a_Vector3 ); + vmathSoaV3Prints( &a_Vector3, "set to x axis" ); + vmathSoaV3MakeYAxis( &a_Vector3 ); + vmathSoaV3Prints( &a_Vector3, "set to y axis" ); + vmathSoaV3MakeZAxis( &a_Vector3 ); + vmathSoaV3Prints( &a_Vector3, "set to z axis" ); + vmathSoaV3SetElem( &a_Vector3, 0, randfloat() ); + vmathSoaV3Prints( &a_Vector3, "Vector3::set( 0, float )" ); + vmathSoaV3SetElem( &a_Vector3, 0, randfloat() ); + vmathSoaV3SetElem( &a_Vector3, 0, vec_mul_float( vmathSoaV3GetElem( &a_Vector3, 0 ), randfloat() ) ); + vmathSoaV3SetElem( &a_Vector3, 0, divf4( vmathSoaV3GetElem( &a_Vector3, 0 ), randfloat() ) ); + vmathSoaV3SetElem( &a_Vector3, 0, vec_add_float( vmathSoaV3GetElem( &a_Vector3, 0 ), randfloat() ) ); + vmathSoaV3SetElem( &a_Vector3, 0, vec_sub_float( vmathSoaV3GetElem( &a_Vector3, 0 ), randfloat() ) ); + vmathSoaV3Prints( &a_Vector3, "Vector3::operator [](0)" ); + vmathSoaV3SetX( &a_Vector3, randfloat() ); + vmathSoaV3Prints( &a_Vector3, "Vector3::setX()" ); + vmathSoaV3SetElem( &a_Vector3, 1, randfloat() ); + vmathSoaV3Prints( &a_Vector3, "Vector3::set( 1, float )" ); + vmathSoaV3SetElem( &a_Vector3, 1, randfloat() ); + vmathSoaV3SetElem( &a_Vector3, 1, vec_mul_float( vmathSoaV3GetElem( &a_Vector3, 1 ), randfloat() ) ); + vmathSoaV3SetElem( &a_Vector3, 1, divf4( vmathSoaV3GetElem( &a_Vector3, 1 ), randfloat() ) ); + vmathSoaV3SetElem( &a_Vector3, 1, vec_add_float( vmathSoaV3GetElem( &a_Vector3, 1 ), randfloat() ) ); + vmathSoaV3SetElem( &a_Vector3, 1, vec_sub_float( vmathSoaV3GetElem( &a_Vector3, 1 ), randfloat() ) ); + vmathSoaV3Prints( &a_Vector3, "Vector3::operator [](1)" ); + vmathSoaV3SetY( &a_Vector3, randfloat() ); + vmathSoaV3Prints( &a_Vector3, "Vector3::setY()" ); + vmathSoaV3SetElem( &a_Vector3, 2, randfloat() ); + vmathSoaV3Prints( &a_Vector3, "Vector3::set( 2, float )" ); + vmathSoaV3SetElem( &a_Vector3, 2, randfloat() ); + vmathSoaV3SetElem( &a_Vector3, 2, vec_mul_float( vmathSoaV3GetElem( &a_Vector3, 2 ), randfloat() ) ); + vmathSoaV3SetElem( &a_Vector3, 2, divf4( vmathSoaV3GetElem( &a_Vector3, 2 ), randfloat() ) ); + vmathSoaV3SetElem( &a_Vector3, 2, vec_add_float( vmathSoaV3GetElem( &a_Vector3, 2 ), randfloat() ) ); + vmathSoaV3SetElem( &a_Vector3, 2, vec_sub_float( vmathSoaV3GetElem( &a_Vector3, 2 ), randfloat() ) ); + vmathSoaV3Prints( &a_Vector3, "Vector3::operator [](2)" ); + vmathSoaV3SetZ( &a_Vector3, randfloat() ); + vmathSoaV3Prints( &a_Vector3, "Vector3::setZ()" ); + printf("Vector3::get( 0 ): %f\n", getfloat(vmathSoaV3GetElem( &a_Vector3, 0 )) ); + printf("Vector3::operator []( 0 ): %f\n", getfloat(vmathSoaV3GetElem( &a_Vector3, 0 )) ); + printf("Vector3::getX(): %f\n", getfloat(vmathSoaV3GetX( &a_Vector3 )) ); + printf("Vector3::get( 1 ): %f\n", getfloat(vmathSoaV3GetElem( &a_Vector3, 1 )) ); + printf("Vector3::operator []( 1 ): %f\n", getfloat(vmathSoaV3GetElem( &a_Vector3, 1 )) ); + printf("Vector3::getY(): %f\n", getfloat(vmathSoaV3GetY( &a_Vector3 )) ); + printf("Vector3::get( 2 ): %f\n", getfloat(vmathSoaV3GetElem( &a_Vector3, 2 )) ); + printf("Vector3::operator []( 2 ): %f\n", getfloat(vmathSoaV3GetElem( &a_Vector3, 2 )) ); + printf("Vector3::getZ(): %f\n", getfloat(vmathSoaV3GetZ( &a_Vector3 )) ); + vmathSoaV3Add( &tmpV3_2, &a_Vector3, &b_Vector3 ); + vmathSoaV3Prints( &tmpV3_2, "Vector3 + Vector3" ); + vmathSoaV3Sub( &tmpV3_3, &a_Vector3, &b_Vector3 ); + vmathSoaV3Prints( &tmpV3_3, "Vector3 - Vector3" ); + vmathSoaV3AddP3( &tmpP3_0, &a_Vector3, &b_Point3 ); + vmathSoaP3Prints( &tmpP3_0, "Vector3 + Point3" ); + vmathSoaV3ScalarMul( &tmpV3_4, &a_Vector3, randfloat() ); + vmathSoaV3Prints( &tmpV3_4, "Vector3 * float" ); + vmathSoaV3ScalarDiv( &tmpV3_5, &a_Vector3, randfloat() ); + vmathSoaV3Prints( &tmpV3_5, "Vector3 / float" ); + vmathSoaV3ScalarMul( &tmpV3_6, &a_Vector3, randfloat() ); + vmathSoaV3Prints( &tmpV3_6, "float * Vector3" ); + vmathSoaV3Neg( &tmpV3_7, &a_Vector3 ); + vmathSoaV3Prints( &tmpV3_7, "Vector3 negate" ); + vmathSoaV3MulPerElem( &tmpV3_8, &a_Vector3, &b_Vector3 ); + vmathSoaV3Prints( &tmpV3_8, "mulPerElem( Vector3, Vector3 )" ); + vmathSoaV3DivPerElem( &tmpV3_9, &a_Vector3, &b_Vector3 ); + vmathSoaV3Prints( &tmpV3_9, "divPerElem( Vector3, Vector3 )" ); + vmathSoaV3RecipPerElem( &tmpV3_10, &a_Vector3 ); + vmathSoaV3Prints( &tmpV3_10, "Vector3 recip" ); + vmathSoaV3AbsPerElem( &tmpV3_11, &a_Vector3 ); + vmathSoaV3SqrtPerElem( &tmpV3_12, &tmpV3_11 ); + vmathSoaV3Prints( &tmpV3_12, "Vector3 sqrt" ); + vmathSoaV3AbsPerElem( &tmpV3_13, &a_Vector3 ); + vmathSoaV3RsqrtPerElem( &tmpV3_14, &tmpV3_13 ); + vmathSoaV3Prints( &tmpV3_14, "Vector3 rsqrt" ); + vmathSoaV3AbsPerElem( &tmpV3_15, &a_Vector3 ); + vmathSoaV3Prints( &tmpV3_15, "Vector3 abs" ); + vmathSoaV3CopySignPerElem( &tmpV3_16, &a_Vector3, &b_Vector3 ); + vmathSoaV3Prints( &tmpV3_16, "Vector3 copySign" ); + vmathSoaV3MaxPerElem( &tmpV3_17, &a_Vector3, &b_Vector3 ); + vmathSoaV3Prints( &tmpV3_17, "Vector3 maximum Vector3" ); + vmathSoaV3MinPerElem( &tmpV3_18, &a_Vector3, &b_Vector3 ); + vmathSoaV3Prints( &tmpV3_18, "Vector3 minimum Vector3" ); + printf("Vector3 maximum of elements: %f\n", getfloat(vmathSoaV3MaxElem( &a_Vector3 ))); + printf("Vector3 minimum of elements: %f\n", getfloat(vmathSoaV3MinElem( &a_Vector3 ))); + printf("Vector3 sum of elements: %f\n", getfloat(vmathSoaV3Sum( &a_Vector3 ))); + printf("Vector3 dot Vector3: %f\n", getfloat(vmathSoaV3Dot( &a_Vector3, &b_Vector3 ))); + printf("Vector3 lengthSqr: %f\n", getfloat(vmathSoaV3LengthSqr( &a_Vector3 ))); + printf("Vector3 length: %f\n", getfloat(vmathSoaV3Length( &a_Vector3 ))); + vmathSoaV3Normalize( &tmpV3_19, &a_Vector3 ); + vmathSoaV3Prints( &tmpV3_19, "Vector3 normalized" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &b_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &e_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathSoaV3Normalize( &b_Vector3, &b_Vector3 ); + vmathSoaV3Normalize( &c_Vector3, &c_Vector3 ); + vmathSoaV3Normalize( &d_Vector3, &d_Vector3 ); + vmathSoaV3Normalize( &e_Vector3, &e_Vector3 ); + vmathSoaV3Lerp( &a_Vector3, randfloat(), &b_Vector3, &c_Vector3 ); + vmathSoaV3Prints( &a_Vector3, "Vector3 lerp" ); + vmathSoaV3Slerp( &a_Vector3, randfloat(), &b_Vector3, &c_Vector3 ); + vmathSoaV3Prints( &a_Vector3, "Vector3 slerp" ); +} + +void +Vector4_methods_test() +{ + VmathSoaVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3, e_Vector3; + VmathSoaVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4, e_Vector4; + VmathSoaPoint3 a_Point3, b_Point3, c_Point3, d_Point3, e_Point3; + VmathSoaQuat a_Quat, b_Quat, c_Quat, d_Quat, e_Quat; + VmathVector4 aos_Vector4_0, aos_Vector4_1, aos_Vector4_2, aos_Vector4_3; + VmathSoaVector4 soa_Vector4; + VmathSoaVector3 tmpV3_0; + VmathSoaVector4 tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3, tmpV4_4, tmpV4_5, tmpV4_6, tmpV4_7, tmpV4_8, tmpV4_9, tmpV4_10, tmpV4_11, tmpV4_12, tmpV4_13, tmpV4_14, tmpV4_15, tmpV4_16, tmpV4_17; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &b_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathSoaV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathSoaV3MakeFromScalar( &c_Vector3, (vec_float4){0.0f} ); + vmathSoaV3MakeFromScalar( &d_Vector3, (vec_float4){0.0f} ); + vmathSoaV3MakeFromScalar( &e_Vector3, (vec_float4){0.0f} ); + vmathSoaV3Prints( &c_Vector3, "set Vector3 elements to zero" ); + vmathSoaV3Prints( &d_Vector3, "set Vector3 elements to zero" ); + vmathSoaV3Prints( &e_Vector3, "set Vector3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &b_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathSoaV4MakeFromScalar( &c_Vector4, (vec_float4){0.0f} ); + vmathSoaV4MakeFromScalar( &d_Vector4, (vec_float4){0.0f} ); + vmathSoaV4MakeFromScalar( &e_Vector4, (vec_float4){0.0f} ); + vmathSoaV4Prints( &c_Vector4, "set Vector4 elements to zero" ); + vmathSoaV4Prints( &d_Vector4, "set Vector4 elements to zero" ); + vmathSoaV4Prints( &e_Vector4, "set Vector4 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &b_Point3, rndflt1, rndflt2, rndflt3 ); + vmathSoaP3Prints( &a_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &b_Point3, "set Point3 with floats" ); + vmathSoaP3MakeFromScalar( &c_Point3, (vec_float4){0.0f} ); + vmathSoaP3MakeFromScalar( &d_Point3, (vec_float4){0.0f} ); + vmathSoaP3MakeFromScalar( &e_Point3, (vec_float4){0.0f} ); + vmathSoaP3Prints( &c_Point3, "set Point3 elements to zero" ); + vmathSoaP3Prints( &d_Point3, "set Point3 elements to zero" ); + vmathSoaP3Prints( &e_Point3, "set Point3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &b_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaQPrints( &a_Quat, "set Quat with floats" ); + vmathSoaQPrints( &b_Quat, "set Quat with floats" ); + vmathSoaQMakeFromScalar( &c_Quat, (vec_float4){0.0f} ); + vmathSoaQMakeFromScalar( &d_Quat, (vec_float4){0.0f} ); + vmathSoaQMakeFromScalar( &e_Quat, (vec_float4){0.0f} ); + vmathSoaQPrints( &c_Quat, "set Quat elements to zero" ); + vmathSoaQPrints( &d_Quat, "set Quat elements to zero" ); + vmathSoaQPrints( &e_Quat, "set Quat elements to zero" ); + vmathSoaV4MakeFromV3Scalar( &a_Vector4, &a_Vector3, randfloat() ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with Vector3, float" ); + vmathSoaV4MakeFromV3( &a_Vector4, &a_Vector3 ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with Vector3" ); + vmathSoaV4MakeFromP3( &a_Vector4, &a_Point3 ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with Point3" ); + vmathSoaV4MakeFromQ( &a_Vector4, &a_Quat ); + vmathSoaV4Prints( &a_Vector4, "construct Vector4 with Quat" ); + vmathSoaV4MakeFromScalar( &a_Vector4, randfloat() ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with float" ); + vmathSoaV4MakeFromScalar( &a_Vector4, randfloat() ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with float" ); + vmathV4MakeFromElems( &aos_Vector4_0, 0.0f, 1.0f, 2.0f, 3.0f ); + vmathV4MakeFromElems( &aos_Vector4_1, 4.0f, 5.0f, 6.0f, 7.0f ); + vmathV4MakeFromElems( &aos_Vector4_2, 8.0f, 9.0f, 10.0f, 11.0f ); + vmathV4MakeFromElems( &aos_Vector4_3, 12.0f, 13.0f, 14.0f, 15.0f ); + vmathSoaV4MakeFrom4Aos( &soa_Vector4, &aos_Vector4_0, &aos_Vector4_1, &aos_Vector4_2, &aos_Vector4_3 ); + vmathSoaV4Get4Aos( &soa_Vector4, &aos_Vector4_3, &aos_Vector4_2, &aos_Vector4_1, &aos_Vector4_0 ); + vmathV4Prints( &aos_Vector4_0, "aos type 0" ); + vmathV4Prints( &aos_Vector4_1, "aos type 1" ); + vmathV4Prints( &aos_Vector4_2, "aos type 2" ); + vmathV4Prints( &aos_Vector4_3, "aos type 3" ); + vmathSoaV4Select( &a_Vector4, &a_Vector4, &b_Vector4, ((vec_uint4){0,0xffffffff,0,0xffffffff}) ); + vmathSoaV4Get4Aos( &a_Vector4, &aos_Vector4_0, &aos_Vector4_1, &aos_Vector4_2, &aos_Vector4_3 ); + vmathV4Prints( &aos_Vector4_0, "select 0" ); + vmathV4Prints( &aos_Vector4_1, "select 1" ); + vmathV4Prints( &aos_Vector4_2, "select 2" ); + vmathV4Prints( &aos_Vector4_3, "select 3" ); + vmathSoaV4Copy( &a_Vector4, &b_Vector4 ); + vmathSoaV4Prints( &a_Vector4, "assign to Vector4 from Vector4" ); + vmathSoaV4SetXYZ( &a_Vector4, &a_Vector3 ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 xyz" ); + vmathSoaV4GetXYZ( &tmpV3_0, &a_Vector4 ); + vmathSoaV3Prints( &tmpV3_0, "get Vector4 xyz" ); + vmathSoaV4MakeFromScalar( &a_Vector4, (vec_float4){0.0f} ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 elements to zero" ); + vmathSoaV4MakeXAxis( &a_Vector4 ); + vmathSoaV4Prints( &a_Vector4, "set to x axis" ); + vmathSoaV4MakeYAxis( &a_Vector4 ); + vmathSoaV4Prints( &a_Vector4, "set to y axis" ); + vmathSoaV4MakeZAxis( &a_Vector4 ); + vmathSoaV4Prints( &a_Vector4, "set to z axis" ); + vmathSoaV4MakeWAxis( &a_Vector4 ); + vmathSoaV4Prints( &a_Vector4, "set to w axis" ); + vmathSoaV4SetElem( &a_Vector4, 0, randfloat() ); + vmathSoaV4Prints( &a_Vector4, "Vector4::set( 0, float )" ); + vmathSoaV4SetElem( &a_Vector4, 0, randfloat() ); + vmathSoaV4SetElem( &a_Vector4, 0, vec_mul_float( vmathSoaV4GetElem( &a_Vector4, 0 ), randfloat() ) ); + vmathSoaV4SetElem( &a_Vector4, 0, divf4( vmathSoaV4GetElem( &a_Vector4, 0 ), randfloat() ) ); + vmathSoaV4SetElem( &a_Vector4, 0, vec_add_float( vmathSoaV4GetElem( &a_Vector4, 0 ), randfloat() ) ); + vmathSoaV4SetElem( &a_Vector4, 0, vec_sub_float( vmathSoaV4GetElem( &a_Vector4, 0 ), randfloat() ) ); + vmathSoaV4Prints( &a_Vector4, "Vector4::operator [](0)" ); + vmathSoaV4SetX( &a_Vector4, randfloat() ); + vmathSoaV4Prints( &a_Vector4, "Vector4::setX()" ); + vmathSoaV4SetElem( &a_Vector4, 1, randfloat() ); + vmathSoaV4Prints( &a_Vector4, "Vector4::set( 1, float )" ); + vmathSoaV4SetElem( &a_Vector4, 1, randfloat() ); + vmathSoaV4SetElem( &a_Vector4, 1, vec_mul_float( vmathSoaV4GetElem( &a_Vector4, 1 ), randfloat() ) ); + vmathSoaV4SetElem( &a_Vector4, 1, divf4( vmathSoaV4GetElem( &a_Vector4, 1 ), randfloat() ) ); + vmathSoaV4SetElem( &a_Vector4, 1, vec_add_float( vmathSoaV4GetElem( &a_Vector4, 1 ), randfloat() ) ); + vmathSoaV4SetElem( &a_Vector4, 1, vec_sub_float( vmathSoaV4GetElem( &a_Vector4, 1 ), randfloat() ) ); + vmathSoaV4Prints( &a_Vector4, "Vector4::operator [](1)" ); + vmathSoaV4SetY( &a_Vector4, randfloat() ); + vmathSoaV4Prints( &a_Vector4, "Vector4::setY()" ); + vmathSoaV4SetElem( &a_Vector4, 2, randfloat() ); + vmathSoaV4Prints( &a_Vector4, "Vector4::set( 2, float )" ); + vmathSoaV4SetElem( &a_Vector4, 2, randfloat() ); + vmathSoaV4SetElem( &a_Vector4, 2, vec_mul_float( vmathSoaV4GetElem( &a_Vector4, 2 ), randfloat() ) ); + vmathSoaV4SetElem( &a_Vector4, 2, divf4( vmathSoaV4GetElem( &a_Vector4, 2 ), randfloat() ) ); + vmathSoaV4SetElem( &a_Vector4, 2, vec_add_float( vmathSoaV4GetElem( &a_Vector4, 2 ), randfloat() ) ); + vmathSoaV4SetElem( &a_Vector4, 2, vec_sub_float( vmathSoaV4GetElem( &a_Vector4, 2 ), randfloat() ) ); + vmathSoaV4Prints( &a_Vector4, "Vector4::operator [](2)" ); + vmathSoaV4SetZ( &a_Vector4, randfloat() ); + vmathSoaV4Prints( &a_Vector4, "Vector4::setZ()" ); + vmathSoaV4SetElem( &a_Vector4, 3, randfloat() ); + vmathSoaV4Prints( &a_Vector4, "Vector4::set( 3, float )" ); + vmathSoaV4SetElem( &a_Vector4, 3, randfloat() ); + vmathSoaV4SetElem( &a_Vector4, 3, vec_mul_float( vmathSoaV4GetElem( &a_Vector4, 3 ), randfloat() ) ); + vmathSoaV4SetElem( &a_Vector4, 3, divf4( vmathSoaV4GetElem( &a_Vector4, 3 ), randfloat() ) ); + vmathSoaV4SetElem( &a_Vector4, 3, vec_add_float( vmathSoaV4GetElem( &a_Vector4, 3 ), randfloat() ) ); + vmathSoaV4SetElem( &a_Vector4, 3, vec_sub_float( vmathSoaV4GetElem( &a_Vector4, 3 ), randfloat() ) ); + vmathSoaV4Prints( &a_Vector4, "Vector4::operator [](3)" ); + vmathSoaV4SetW( &a_Vector4, randfloat() ); + vmathSoaV4Prints( &a_Vector4, "Vector4::setW()" ); + printf("Vector4::get( 0 ): %f\n", getfloat(vmathSoaV4GetElem( &a_Vector4, 0 )) ); + printf("Vector4::operator []( 0 ): %f\n", getfloat(vmathSoaV4GetElem( &a_Vector4, 0 )) ); + printf("Vector4::getX(): %f\n", getfloat(vmathSoaV4GetX( &a_Vector4 )) ); + printf("Vector4::get( 1 ): %f\n", getfloat(vmathSoaV4GetElem( &a_Vector4, 1 )) ); + printf("Vector4::operator []( 1 ): %f\n", getfloat(vmathSoaV4GetElem( &a_Vector4, 1 )) ); + printf("Vector4::getY(): %f\n", getfloat(vmathSoaV4GetY( &a_Vector4 )) ); + printf("Vector4::get( 2 ): %f\n", getfloat(vmathSoaV4GetElem( &a_Vector4, 2 )) ); + printf("Vector4::operator []( 2 ): %f\n", getfloat(vmathSoaV4GetElem( &a_Vector4, 2 )) ); + printf("Vector4::getZ(): %f\n", getfloat(vmathSoaV4GetZ( &a_Vector4 )) ); + printf("Vector4::get( 3 ): %f\n", getfloat(vmathSoaV4GetElem( &a_Vector4, 3 )) ); + printf("Vector4::operator []( 3 ): %f\n", getfloat(vmathSoaV4GetElem( &a_Vector4, 3 )) ); + printf("Vector4::getW(): %f\n", getfloat(vmathSoaV4GetW( &a_Vector4 )) ); + vmathSoaV4Add( &tmpV4_0, &a_Vector4, &b_Vector4 ); + vmathSoaV4Prints( &tmpV4_0, "Vector4 + Vector4" ); + vmathSoaV4Sub( &tmpV4_1, &a_Vector4, &b_Vector4 ); + vmathSoaV4Prints( &tmpV4_1, "Vector4 - Vector4" ); + vmathSoaV4ScalarMul( &tmpV4_2, &a_Vector4, randfloat() ); + vmathSoaV4Prints( &tmpV4_2, "Vector4 * float" ); + vmathSoaV4ScalarDiv( &tmpV4_3, &a_Vector4, randfloat() ); + vmathSoaV4Prints( &tmpV4_3, "Vector4 / float" ); + vmathSoaV4ScalarMul( &tmpV4_4, &a_Vector4, randfloat() ); + vmathSoaV4Prints( &tmpV4_4, "float * Vector4" ); + vmathSoaV4Neg( &tmpV4_5, &a_Vector4 ); + vmathSoaV4Prints( &tmpV4_5, "Vector4 negate" ); + vmathSoaV4MulPerElem( &tmpV4_6, &a_Vector4, &b_Vector4 ); + vmathSoaV4Prints( &tmpV4_6, "mulPerElem( Vector4, Vector4 )" ); + vmathSoaV4DivPerElem( &tmpV4_7, &a_Vector4, &b_Vector4 ); + vmathSoaV4Prints( &tmpV4_7, "divPerElem( Vector4, Vector4 )" ); + vmathSoaV4RecipPerElem( &tmpV4_8, &a_Vector4 ); + vmathSoaV4Prints( &tmpV4_8, "Vector4 recip" ); + vmathSoaV4AbsPerElem( &tmpV4_9, &a_Vector4 ); + vmathSoaV4SqrtPerElem( &tmpV4_10, &tmpV4_9 ); + vmathSoaV4Prints( &tmpV4_10, "Vector4 sqrt" ); + vmathSoaV4AbsPerElem( &tmpV4_11, &a_Vector4 ); + vmathSoaV4RsqrtPerElem( &tmpV4_12, &tmpV4_11 ); + vmathSoaV4Prints( &tmpV4_12, "Vector4 rsqrt" ); + vmathSoaV4AbsPerElem( &tmpV4_13, &a_Vector4 ); + vmathSoaV4Prints( &tmpV4_13, "Vector4 abs" ); + vmathSoaV4CopySignPerElem( &tmpV4_14, &a_Vector4, &b_Vector4 ); + vmathSoaV4Prints( &tmpV4_14, "Vector4 copySign" ); + vmathSoaV4MaxPerElem( &tmpV4_15, &a_Vector4, &b_Vector4 ); + vmathSoaV4Prints( &tmpV4_15, "Vector4 maximum Vector4" ); + vmathSoaV4MinPerElem( &tmpV4_16, &a_Vector4, &b_Vector4 ); + vmathSoaV4Prints( &tmpV4_16, "Vector4 minimum Vector4" ); + printf("Vector4 maximum of elements: %f\n", getfloat(vmathSoaV4MaxElem( &a_Vector4 ))); + printf("Vector4 minimum of elements: %f\n", getfloat(vmathSoaV4MinElem( &a_Vector4 ))); + printf("Vector4 sum of elements: %f\n", getfloat(vmathSoaV4Sum( &a_Vector4 ))); + printf("Vector4 dot Vector4: %f\n", getfloat(vmathSoaV4Dot( &a_Vector4, &b_Vector4 ))); + printf("Vector4 lengthSqr: %f\n", getfloat(vmathSoaV4LengthSqr( &a_Vector4 ))); + printf("Vector4 length: %f\n", getfloat(vmathSoaV4Length( &a_Vector4 ))); + vmathSoaV4Normalize( &tmpV4_17, &a_Vector4 ); + vmathSoaV4Prints( &tmpV4_17, "Vector4 normalized" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &b_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &e_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaV4Normalize( &b_Vector4, &b_Vector4 ); + vmathSoaV4Normalize( &c_Vector4, &c_Vector4 ); + vmathSoaV4Normalize( &d_Vector4, &d_Vector4 ); + vmathSoaV4Normalize( &e_Vector4, &e_Vector4 ); + vmathSoaV4Lerp( &a_Vector4, randfloat(), &b_Vector4, &c_Vector4 ); + vmathSoaV4Prints( &a_Vector4, "Vector4 lerp" ); + vmathSoaV4Slerp( &a_Vector4, randfloat(), &b_Vector4, &c_Vector4 ); + vmathSoaV4Prints( &a_Vector4, "Vector4 slerp" ); +} + +void +Point3_methods_test() +{ + VmathSoaVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3, e_Vector3; + VmathSoaVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4, e_Vector4; + VmathSoaPoint3 a_Point3, b_Point3, c_Point3, d_Point3, e_Point3; + VmathSoaQuat a_Quat, b_Quat, c_Quat, d_Quat, e_Quat; + VmathPoint3 aos_Point3_0, aos_Point3_1, aos_Point3_2, aos_Point3_3; + VmathSoaPoint3 soa_Point3; + VmathVector4 aos_Vector4_0, aos_Vector4_1, aos_Vector4_2; + VmathSoaVector3 tmpV3_0, tmpV3_1, tmpV3_2; + VmathSoaPoint3 tmpP3_0, tmpP3_1, tmpP3_2, tmpP3_3, tmpP3_4, tmpP3_5, tmpP3_6, tmpP3_7, tmpP3_8, tmpP3_9, tmpP3_10, tmpP3_11, tmpP3_12; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4; + float xyz4[12] __attribute__ ((aligned(16))); + xyz4[0] = getfloat(randfloat()); + xyz4[1] = getfloat(randfloat()); + xyz4[2] = getfloat(randfloat()); + xyz4[3] = getfloat(randfloat()); + xyz4[4] = getfloat(randfloat()); + xyz4[5] = getfloat(randfloat()); + xyz4[6] = getfloat(randfloat()); + xyz4[7] = getfloat(randfloat()); + xyz4[8] = getfloat(randfloat()); + xyz4[9] = getfloat(randfloat()); + xyz4[10] = getfloat(randfloat()); + xyz4[11] = getfloat(randfloat()); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &b_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathSoaV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathSoaV3MakeFromScalar( &c_Vector3, (vec_float4){0.0f} ); + vmathSoaV3MakeFromScalar( &d_Vector3, (vec_float4){0.0f} ); + vmathSoaV3MakeFromScalar( &e_Vector3, (vec_float4){0.0f} ); + vmathSoaV3Prints( &c_Vector3, "set Vector3 elements to zero" ); + vmathSoaV3Prints( &d_Vector3, "set Vector3 elements to zero" ); + vmathSoaV3Prints( &e_Vector3, "set Vector3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &b_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathSoaV4MakeFromScalar( &c_Vector4, (vec_float4){0.0f} ); + vmathSoaV4MakeFromScalar( &d_Vector4, (vec_float4){0.0f} ); + vmathSoaV4MakeFromScalar( &e_Vector4, (vec_float4){0.0f} ); + vmathSoaV4Prints( &c_Vector4, "set Vector4 elements to zero" ); + vmathSoaV4Prints( &d_Vector4, "set Vector4 elements to zero" ); + vmathSoaV4Prints( &e_Vector4, "set Vector4 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &b_Point3, rndflt1, rndflt2, rndflt3 ); + vmathSoaP3Prints( &a_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &b_Point3, "set Point3 with floats" ); + vmathSoaP3MakeFromScalar( &c_Point3, (vec_float4){0.0f} ); + vmathSoaP3MakeFromScalar( &d_Point3, (vec_float4){0.0f} ); + vmathSoaP3MakeFromScalar( &e_Point3, (vec_float4){0.0f} ); + vmathSoaP3Prints( &c_Point3, "set Point3 elements to zero" ); + vmathSoaP3Prints( &d_Point3, "set Point3 elements to zero" ); + vmathSoaP3Prints( &e_Point3, "set Point3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &b_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaQPrints( &a_Quat, "set Quat with floats" ); + vmathSoaQPrints( &b_Quat, "set Quat with floats" ); + vmathSoaQMakeFromScalar( &c_Quat, (vec_float4){0.0f} ); + vmathSoaQMakeFromScalar( &d_Quat, (vec_float4){0.0f} ); + vmathSoaQMakeFromScalar( &e_Quat, (vec_float4){0.0f} ); + vmathSoaQPrints( &c_Quat, "set Quat elements to zero" ); + vmathSoaQPrints( &d_Quat, "set Quat elements to zero" ); + vmathSoaQPrints( &e_Quat, "set Quat elements to zero" ); + vmathSoaP3MakeFromV3( &a_Point3, &a_Vector3 ); + vmathSoaP3Prints( &a_Point3, "construct Point3 with Vector3" ); + vmathSoaP3MakeFromScalar( &a_Point3, randfloat() ); + vmathSoaP3Prints( &a_Point3, "set Point3 with float" ); + vmathSoaP3MakeFromScalar( &a_Point3, randfloat() ); + vmathSoaP3Prints( &a_Point3, "set Point3 with float" ); + vmathP3MakeFromElems( &aos_Point3_0, 0.0f, 1.0f, 2.0f ); + vmathP3MakeFromElems( &aos_Point3_1, 3.0f, 4.0f, 5.0f ); + vmathP3MakeFromElems( &aos_Point3_2, 6.0f, 7.0f, 8.0f ); + vmathP3MakeFromElems( &aos_Point3_3, 9.0f, 10.0f, 11.0f ); + vmathSoaP3MakeFrom4Aos( &soa_Point3, &aos_Point3_0, &aos_Point3_1, &aos_Point3_2, &aos_Point3_3 ); + vmathSoaP3Get4Aos( &soa_Point3, &aos_Point3_3, &aos_Point3_2, &aos_Point3_1, &aos_Point3_0 ); + vmathP3Prints( &aos_Point3_0, "aos type 0" ); + vmathP3Prints( &aos_Point3_1, "aos type 1" ); + vmathP3Prints( &aos_Point3_2, "aos type 2" ); + vmathP3Prints( &aos_Point3_3, "aos type 3" ); + vmathSoaP3Select( &a_Point3, &a_Point3, &b_Point3, ((vec_uint4){0,0xffffffff,0,0xffffffff}) ); + vmathSoaP3Get4Aos( &a_Point3, &aos_Point3_0, &aos_Point3_1, &aos_Point3_2, &aos_Point3_3 ); + vmathP3Prints( &aos_Point3_0, "select 0" ); + vmathP3Prints( &aos_Point3_1, "select 1" ); + vmathP3Prints( &aos_Point3_2, "select 2" ); + vmathP3Prints( &aos_Point3_3, "select 3" ); + vmathSoaP3LoadXYZArray( &a_Point3, (const vec_float4 *)xyz4 ); + vmathSoaP3Prints( &a_Point3, "load XYZ array" ); + vmathSoaV3MakeFromP3( &tmpV3_0, &a_Point3 ); + vmathSoaV3Neg( &tmpV3_1, &tmpV3_0 ); + vmathSoaP3MakeFromV3( &a_Point3, &tmpV3_1 ); + vmathSoaP3StoreXYZArray( &a_Point3, (vec_float4 *)xyz4 ); + vmathV4MakeFromElems( &aos_Vector4_0, xyz4[0], xyz4[1], xyz4[2], xyz4[3] ); + vmathV4MakeFromElems( &aos_Vector4_1, xyz4[4], xyz4[5], xyz4[6], xyz4[7] ); + vmathV4MakeFromElems( &aos_Vector4_2, xyz4[8], xyz4[9], xyz4[10], xyz4[11] ); + vmathV4Prints( &aos_Vector4_0, "xyzx" ); + vmathV4Prints( &aos_Vector4_1, "yzxy" ); + vmathV4Prints( &aos_Vector4_2, "zxyz" ); + vmathV4Prints( &aos_Vector4_0, "xyzx" ); + vmathV4Prints( &aos_Vector4_1, "yzxy" ); + vmathV4Prints( &aos_Vector4_2, "zxyz" ); + printf("storeXYZ:-1.0 -2.0 -3.0 0.4\n"); + vmathSoaP3Copy( &a_Point3, &b_Point3 ); + vmathSoaP3Prints( &a_Point3, "assign to Point3 from Point3" ); + vmathSoaP3MakeFromScalar( &a_Point3, (vec_float4){0.0f} ); + vmathSoaP3Prints( &a_Point3, "set Point3 elements to zero" ); + vmathSoaP3SetElem( &a_Point3, 0, randfloat() ); + vmathSoaP3Prints( &a_Point3, "Point3::set( 0, float )" ); + vmathSoaP3SetElem( &a_Point3, 0, randfloat() ); + vmathSoaP3SetElem( &a_Point3, 0, vec_mul_float( vmathSoaP3GetElem( &a_Point3, 0 ), randfloat() ) ); + vmathSoaP3SetElem( &a_Point3, 0, divf4( vmathSoaP3GetElem( &a_Point3, 0 ), randfloat() ) ); + vmathSoaP3SetElem( &a_Point3, 0, vec_add_float( vmathSoaP3GetElem( &a_Point3, 0 ), randfloat() ) ); + vmathSoaP3SetElem( &a_Point3, 0, vec_sub_float( vmathSoaP3GetElem( &a_Point3, 0 ), randfloat() ) ); + vmathSoaP3Prints( &a_Point3, "Point3::operator [](0)" ); + vmathSoaP3SetX( &a_Point3, randfloat() ); + vmathSoaP3Prints( &a_Point3, "Point3::setX()" ); + vmathSoaP3SetElem( &a_Point3, 1, randfloat() ); + vmathSoaP3Prints( &a_Point3, "Point3::set( 1, float )" ); + vmathSoaP3SetElem( &a_Point3, 1, randfloat() ); + vmathSoaP3SetElem( &a_Point3, 1, vec_mul_float( vmathSoaP3GetElem( &a_Point3, 1 ), randfloat() ) ); + vmathSoaP3SetElem( &a_Point3, 1, divf4( vmathSoaP3GetElem( &a_Point3, 1 ), randfloat() ) ); + vmathSoaP3SetElem( &a_Point3, 1, vec_add_float( vmathSoaP3GetElem( &a_Point3, 1 ), randfloat() ) ); + vmathSoaP3SetElem( &a_Point3, 1, vec_sub_float( vmathSoaP3GetElem( &a_Point3, 1 ), randfloat() ) ); + vmathSoaP3Prints( &a_Point3, "Point3::operator [](1)" ); + vmathSoaP3SetY( &a_Point3, randfloat() ); + vmathSoaP3Prints( &a_Point3, "Point3::setY()" ); + vmathSoaP3SetElem( &a_Point3, 2, randfloat() ); + vmathSoaP3Prints( &a_Point3, "Point3::set( 2, float )" ); + vmathSoaP3SetElem( &a_Point3, 2, randfloat() ); + vmathSoaP3SetElem( &a_Point3, 2, vec_mul_float( vmathSoaP3GetElem( &a_Point3, 2 ), randfloat() ) ); + vmathSoaP3SetElem( &a_Point3, 2, divf4( vmathSoaP3GetElem( &a_Point3, 2 ), randfloat() ) ); + vmathSoaP3SetElem( &a_Point3, 2, vec_add_float( vmathSoaP3GetElem( &a_Point3, 2 ), randfloat() ) ); + vmathSoaP3SetElem( &a_Point3, 2, vec_sub_float( vmathSoaP3GetElem( &a_Point3, 2 ), randfloat() ) ); + vmathSoaP3Prints( &a_Point3, "Point3::operator [](2)" ); + vmathSoaP3SetZ( &a_Point3, randfloat() ); + vmathSoaP3Prints( &a_Point3, "Point3::setZ()" ); + printf("Point3::get( 0 ): %f\n", getfloat(vmathSoaP3GetElem( &a_Point3, 0 )) ); + printf("Point3::operator []( 0 ): %f\n", getfloat(vmathSoaP3GetElem( &a_Point3, 0 )) ); + printf("Point3::getX(): %f\n", getfloat(vmathSoaP3GetX( &a_Point3 )) ); + printf("Point3::get( 1 ): %f\n", getfloat(vmathSoaP3GetElem( &a_Point3, 1 )) ); + printf("Point3::operator []( 1 ): %f\n", getfloat(vmathSoaP3GetElem( &a_Point3, 1 )) ); + printf("Point3::getY(): %f\n", getfloat(vmathSoaP3GetY( &a_Point3 )) ); + printf("Point3::get( 2 ): %f\n", getfloat(vmathSoaP3GetElem( &a_Point3, 2 )) ); + printf("Point3::operator []( 2 ): %f\n", getfloat(vmathSoaP3GetElem( &a_Point3, 2 )) ); + printf("Point3::getZ(): %f\n", getfloat(vmathSoaP3GetZ( &a_Point3 )) ); + vmathSoaP3Sub( &tmpV3_2, &a_Point3, &b_Point3 ); + vmathSoaV3Prints( &tmpV3_2, "Point3 - Point3" ); + vmathSoaP3AddV3( &tmpP3_0, &a_Point3, &b_Vector3 ); + vmathSoaP3Prints( &tmpP3_0, "Point3 + Vector3" ); + vmathSoaP3SubV3( &tmpP3_1, &a_Point3, &b_Vector3 ); + vmathSoaP3Prints( &tmpP3_1, "Point3 - Vector3" ); + vmathSoaP3MulPerElem( &tmpP3_2, &a_Point3, &b_Point3 ); + vmathSoaP3Prints( &tmpP3_2, "mulPerElem( Point3, Point3 )" ); + vmathSoaP3DivPerElem( &tmpP3_3, &a_Point3, &b_Point3 ); + vmathSoaP3Prints( &tmpP3_3, "divPerElem( Point3, Point3 )" ); + vmathSoaP3RecipPerElem( &tmpP3_4, &a_Point3 ); + vmathSoaP3Prints( &tmpP3_4, "Point3 recip" ); + vmathSoaP3AbsPerElem( &tmpP3_5, &a_Point3 ); + vmathSoaP3SqrtPerElem( &tmpP3_6, &tmpP3_5 ); + vmathSoaP3Prints( &tmpP3_6, "Point3 sqrt" ); + vmathSoaP3AbsPerElem( &tmpP3_7, &a_Point3 ); + vmathSoaP3RsqrtPerElem( &tmpP3_8, &tmpP3_7 ); + vmathSoaP3Prints( &tmpP3_8, "Point3 rsqrt" ); + vmathSoaP3AbsPerElem( &tmpP3_9, &a_Point3 ); + vmathSoaP3Prints( &tmpP3_9, "Point3 abs" ); + vmathSoaP3CopySignPerElem( &tmpP3_10, &a_Point3, &b_Point3 ); + vmathSoaP3Prints( &tmpP3_10, "Point3 copySign" ); + vmathSoaP3MaxPerElem( &tmpP3_11, &a_Point3, &b_Point3 ); + vmathSoaP3Prints( &tmpP3_11, "Point3 maximum Point3" ); + vmathSoaP3MinPerElem( &tmpP3_12, &a_Point3, &b_Point3 ); + vmathSoaP3Prints( &tmpP3_12, "Point3 minimum Point3" ); + printf("Point3 maximum of elements: %f\n", getfloat(vmathSoaP3MaxElem( &a_Point3 ))); + printf("Point3 minimum of elements: %f\n", getfloat(vmathSoaP3MinElem( &a_Point3 ))); + printf("Point3 sum of elements: %f\n", getfloat(vmathSoaP3Sum( &a_Point3 ))); + printf("Point projection: %f\n", getfloat(vmathSoaP3Projection( &a_Point3, &b_Vector3 ))); + printf("Point distSqrFromOrigin: %f\n", getfloat(vmathSoaP3DistSqrFromOrigin( &a_Point3 )) ); + printf("Point distFromOrigin: %f\n", getfloat(vmathSoaP3DistFromOrigin( &a_Point3 )) ); + printf("Point distSqr: %f\n", getfloat(vmathSoaP3DistSqr( &a_Point3, &b_Point3 )) ); + printf("Point dist: %f\n", getfloat(vmathSoaP3Dist( &a_Point3, &b_Point3 )) ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &b_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &e_Point3, rndflt1, rndflt2, rndflt3 ); + vmathSoaP3Lerp( &a_Point3, randfloat(), &b_Point3, &c_Point3 ); + vmathSoaP3Prints( &a_Point3, "Point3 lerp" ); +} + +void +Quat_methods_test() +{ + VmathSoaVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3, e_Vector3; + VmathSoaVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4, e_Vector4; + VmathSoaPoint3 a_Point3, b_Point3, c_Point3, d_Point3, e_Point3; + VmathSoaQuat a_Quat, b_Quat, c_Quat, d_Quat, e_Quat; + VmathQuat aos_Quat_0, aos_Quat_1, aos_Quat_2, aos_Quat_3; + VmathSoaQuat soa_Quat; + VmathSoaVector3 tmpV3_0; + VmathSoaQuat tmpQ_0, tmpQ_1, tmpQ_2, tmpQ_3, tmpQ_4, tmpQ_5, tmpQ_6, tmpQ_7; + VmathSoaVector3 tmpV3_1; + VmathSoaQuat tmpQ_8; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &b_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathSoaV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathSoaV3MakeFromScalar( &c_Vector3, (vec_float4){0.0f} ); + vmathSoaV3MakeFromScalar( &d_Vector3, (vec_float4){0.0f} ); + vmathSoaV3MakeFromScalar( &e_Vector3, (vec_float4){0.0f} ); + vmathSoaV3Prints( &c_Vector3, "set Vector3 elements to zero" ); + vmathSoaV3Prints( &d_Vector3, "set Vector3 elements to zero" ); + vmathSoaV3Prints( &e_Vector3, "set Vector3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &b_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathSoaV4MakeFromScalar( &c_Vector4, (vec_float4){0.0f} ); + vmathSoaV4MakeFromScalar( &d_Vector4, (vec_float4){0.0f} ); + vmathSoaV4MakeFromScalar( &e_Vector4, (vec_float4){0.0f} ); + vmathSoaV4Prints( &c_Vector4, "set Vector4 elements to zero" ); + vmathSoaV4Prints( &d_Vector4, "set Vector4 elements to zero" ); + vmathSoaV4Prints( &e_Vector4, "set Vector4 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &b_Point3, rndflt1, rndflt2, rndflt3 ); + vmathSoaP3Prints( &a_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &b_Point3, "set Point3 with floats" ); + vmathSoaP3MakeFromScalar( &c_Point3, (vec_float4){0.0f} ); + vmathSoaP3MakeFromScalar( &d_Point3, (vec_float4){0.0f} ); + vmathSoaP3MakeFromScalar( &e_Point3, (vec_float4){0.0f} ); + vmathSoaP3Prints( &c_Point3, "set Point3 elements to zero" ); + vmathSoaP3Prints( &d_Point3, "set Point3 elements to zero" ); + vmathSoaP3Prints( &e_Point3, "set Point3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &b_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaQPrints( &a_Quat, "set Quat with floats" ); + vmathSoaQPrints( &b_Quat, "set Quat with floats" ); + vmathSoaQMakeFromScalar( &c_Quat, (vec_float4){0.0f} ); + vmathSoaQMakeFromScalar( &d_Quat, (vec_float4){0.0f} ); + vmathSoaQMakeFromScalar( &e_Quat, (vec_float4){0.0f} ); + vmathSoaQPrints( &c_Quat, "set Quat elements to zero" ); + vmathSoaQPrints( &d_Quat, "set Quat elements to zero" ); + vmathSoaQPrints( &e_Quat, "set Quat elements to zero" ); + vmathSoaQMakeFromV3Scalar( &a_Quat, &a_Vector3, randfloat() ); + vmathSoaQPrints( &a_Quat, "set Quat with Vector3, float" ); + vmathSoaQMakeFromV4( &a_Quat, &a_Vector4 ); + vmathSoaQPrints( &a_Quat, "construct Quat with Vector4" ); + vmathSoaQMakeFromScalar( &a_Quat, randfloat() ); + vmathSoaQPrints( &a_Quat, "set Quat with float" ); + vmathSoaQMakeFromScalar( &a_Quat, randfloat() ); + vmathSoaQPrints( &a_Quat, "set Quat with float" ); + vmathQMakeFromElems( &aos_Quat_0, 0.0f, 1.0f, 2.0f, 3.0f ); + vmathQMakeFromElems( &aos_Quat_1, 4.0f, 5.0f, 6.0f, 7.0f ); + vmathQMakeFromElems( &aos_Quat_2, 8.0f, 9.0f, 10.0f, 11.0f ); + vmathQMakeFromElems( &aos_Quat_3, 12.0f, 13.0f, 14.0f, 15.0f ); + vmathSoaQMakeFrom4Aos( &soa_Quat, &aos_Quat_0, &aos_Quat_1, &aos_Quat_2, &aos_Quat_3 ); + vmathSoaQGet4Aos( &soa_Quat, &aos_Quat_3, &aos_Quat_2, &aos_Quat_1, &aos_Quat_0 ); + vmathQPrints( &aos_Quat_0, "aos type 0" ); + vmathQPrints( &aos_Quat_1, "aos type 1" ); + vmathQPrints( &aos_Quat_2, "aos type 2" ); + vmathQPrints( &aos_Quat_3, "aos type 3" ); + vmathSoaQSelect( &a_Quat, &a_Quat, &b_Quat, ((vec_uint4){0,0xffffffff,0,0xffffffff}) ); + vmathSoaQGet4Aos( &a_Quat, &aos_Quat_0, &aos_Quat_1, &aos_Quat_2, &aos_Quat_3 ); + vmathQPrints( &aos_Quat_0, "select 0" ); + vmathQPrints( &aos_Quat_1, "select 1" ); + vmathQPrints( &aos_Quat_2, "select 2" ); + vmathQPrints( &aos_Quat_3, "select 3" ); + vmathSoaQCopy( &a_Quat, &b_Quat ); + vmathSoaQPrints( &a_Quat, "assign to Quat from Quat" ); + vmathSoaQSetXYZ( &a_Quat, &a_Vector3 ); + vmathSoaQPrints( &a_Quat, "set Quat xyz" ); + vmathSoaQGetXYZ( &tmpV3_0, &a_Quat ); + vmathSoaV3Prints( &tmpV3_0, "get Quat xyz" ); + vmathSoaQMakeFromScalar( &a_Quat, (vec_float4){0.0f} ); + vmathSoaQPrints( &a_Quat, "set Quat elements to zero" ); + vmathSoaQSetElem( &a_Quat, 0, randfloat() ); + vmathSoaQPrints( &a_Quat, "Quat::set( 0, float )" ); + vmathSoaQSetElem( &a_Quat, 0, randfloat() ); + vmathSoaQSetElem( &a_Quat, 0, vec_mul_float( vmathSoaQGetElem( &a_Quat, 0 ), randfloat() ) ); + vmathSoaQSetElem( &a_Quat, 0, divf4( vmathSoaQGetElem( &a_Quat, 0 ), randfloat() ) ); + vmathSoaQSetElem( &a_Quat, 0, vec_add_float( vmathSoaQGetElem( &a_Quat, 0 ), randfloat() ) ); + vmathSoaQSetElem( &a_Quat, 0, vec_sub_float( vmathSoaQGetElem( &a_Quat, 0 ), randfloat() ) ); + vmathSoaQPrints( &a_Quat, "Quat::operator [](0)" ); + vmathSoaQSetX( &a_Quat, randfloat() ); + vmathSoaQPrints( &a_Quat, "Quat::setX()" ); + vmathSoaQSetElem( &a_Quat, 1, randfloat() ); + vmathSoaQPrints( &a_Quat, "Quat::set( 1, float )" ); + vmathSoaQSetElem( &a_Quat, 1, randfloat() ); + vmathSoaQSetElem( &a_Quat, 1, vec_mul_float( vmathSoaQGetElem( &a_Quat, 1 ), randfloat() ) ); + vmathSoaQSetElem( &a_Quat, 1, divf4( vmathSoaQGetElem( &a_Quat, 1 ), randfloat() ) ); + vmathSoaQSetElem( &a_Quat, 1, vec_add_float( vmathSoaQGetElem( &a_Quat, 1 ), randfloat() ) ); + vmathSoaQSetElem( &a_Quat, 1, vec_sub_float( vmathSoaQGetElem( &a_Quat, 1 ), randfloat() ) ); + vmathSoaQPrints( &a_Quat, "Quat::operator [](1)" ); + vmathSoaQSetY( &a_Quat, randfloat() ); + vmathSoaQPrints( &a_Quat, "Quat::setY()" ); + vmathSoaQSetElem( &a_Quat, 2, randfloat() ); + vmathSoaQPrints( &a_Quat, "Quat::set( 2, float )" ); + vmathSoaQSetElem( &a_Quat, 2, randfloat() ); + vmathSoaQSetElem( &a_Quat, 2, vec_mul_float( vmathSoaQGetElem( &a_Quat, 2 ), randfloat() ) ); + vmathSoaQSetElem( &a_Quat, 2, divf4( vmathSoaQGetElem( &a_Quat, 2 ), randfloat() ) ); + vmathSoaQSetElem( &a_Quat, 2, vec_add_float( vmathSoaQGetElem( &a_Quat, 2 ), randfloat() ) ); + vmathSoaQSetElem( &a_Quat, 2, vec_sub_float( vmathSoaQGetElem( &a_Quat, 2 ), randfloat() ) ); + vmathSoaQPrints( &a_Quat, "Quat::operator [](2)" ); + vmathSoaQSetZ( &a_Quat, randfloat() ); + vmathSoaQPrints( &a_Quat, "Quat::setZ()" ); + vmathSoaQSetElem( &a_Quat, 3, randfloat() ); + vmathSoaQPrints( &a_Quat, "Quat::set( 3, float )" ); + vmathSoaQSetElem( &a_Quat, 3, randfloat() ); + vmathSoaQSetElem( &a_Quat, 3, vec_mul_float( vmathSoaQGetElem( &a_Quat, 3 ), randfloat() ) ); + vmathSoaQSetElem( &a_Quat, 3, divf4( vmathSoaQGetElem( &a_Quat, 3 ), randfloat() ) ); + vmathSoaQSetElem( &a_Quat, 3, vec_add_float( vmathSoaQGetElem( &a_Quat, 3 ), randfloat() ) ); + vmathSoaQSetElem( &a_Quat, 3, vec_sub_float( vmathSoaQGetElem( &a_Quat, 3 ), randfloat() ) ); + vmathSoaQPrints( &a_Quat, "Quat::operator [](3)" ); + vmathSoaQSetW( &a_Quat, randfloat() ); + vmathSoaQPrints( &a_Quat, "Quat::setW()" ); + printf("Quat::get( 0 ): %f\n", getfloat(vmathSoaQGetElem( &a_Quat, 0 )) ); + printf("Quat::operator []( 0 ): %f\n", getfloat(vmathSoaQGetElem( &a_Quat, 0 )) ); + printf("Quat::getX(): %f\n", getfloat(vmathSoaQGetX( &a_Quat )) ); + printf("Quat::get( 1 ): %f\n", getfloat(vmathSoaQGetElem( &a_Quat, 1 )) ); + printf("Quat::operator []( 1 ): %f\n", getfloat(vmathSoaQGetElem( &a_Quat, 1 )) ); + printf("Quat::getY(): %f\n", getfloat(vmathSoaQGetY( &a_Quat )) ); + printf("Quat::get( 2 ): %f\n", getfloat(vmathSoaQGetElem( &a_Quat, 2 )) ); + printf("Quat::operator []( 2 ): %f\n", getfloat(vmathSoaQGetElem( &a_Quat, 2 )) ); + printf("Quat::getZ(): %f\n", getfloat(vmathSoaQGetZ( &a_Quat )) ); + printf("Quat::get( 3 ): %f\n", getfloat(vmathSoaQGetElem( &a_Quat, 3 )) ); + printf("Quat::operator []( 3 ): %f\n", getfloat(vmathSoaQGetElem( &a_Quat, 3 )) ); + printf("Quat::getW(): %f\n", getfloat(vmathSoaQGetW( &a_Quat )) ); + vmathSoaQAdd( &tmpQ_0, &a_Quat, &b_Quat ); + vmathSoaQPrints( &tmpQ_0, "Quat + Quat" ); + vmathSoaQSub( &tmpQ_1, &a_Quat, &b_Quat ); + vmathSoaQPrints( &tmpQ_1, "Quat - Quat" ); + vmathSoaQMul( &tmpQ_2, &a_Quat, &b_Quat ); + vmathSoaQPrints( &tmpQ_2, "Quat * Quat" ); + vmathSoaQScalarMul( &tmpQ_3, &a_Quat, randfloat() ); + vmathSoaQPrints( &tmpQ_3, "Quat * float" ); + vmathSoaQScalarDiv( &tmpQ_4, &a_Quat, randfloat() ); + vmathSoaQPrints( &tmpQ_4, "Quat / float" ); + vmathSoaQScalarMul( &tmpQ_5, &a_Quat, randfloat() ); + vmathSoaQPrints( &tmpQ_5, "float * Quat" ); + vmathSoaQNeg( &tmpQ_6, &a_Quat ); + vmathSoaQPrints( &tmpQ_6, "Quat negate" ); + printf("Quat dot Quat: %f\n", getfloat(vmathSoaQDot( &a_Quat, &b_Quat ))); + printf("Quat lengthSqr: %f\n", getfloat(vmathSoaQNorm( &a_Quat ))); + printf("Quat length: %f\n", getfloat(vmathSoaQLength( &a_Quat ))); + vmathSoaQNormalize( &tmpQ_7, &a_Quat ); + vmathSoaQPrints( &tmpQ_7, "Quat normalized" ); + vmathSoaQMakeIdentity( &a_Quat ); + vmathSoaQPrints( &a_Quat, "set to identity" ); + vmathSoaQMakeRotationArc( &a_Quat, &a_Vector3, &b_Vector3 ); + vmathSoaQPrints( &a_Quat, "Quat rotation between vectors" ); + vmathSoaQMakeRotationAxis( &a_Quat, randfloat(), &a_Vector3 ); + vmathSoaQPrints( &a_Quat, "Quat rotation axis angle" ); + vmathSoaQMakeRotationX( &a_Quat, randfloat() ); + vmathSoaQPrints( &a_Quat, "Quat rotationX" ); + vmathSoaQMakeRotationY( &a_Quat, randfloat() ); + vmathSoaQPrints( &a_Quat, "Quat rotationY" ); + vmathSoaQMakeRotationZ( &a_Quat, randfloat() ); + vmathSoaQPrints( &a_Quat, "Quat rotationZ" ); + vmathSoaQRotate( &tmpV3_1, &a_Quat, &a_Vector3 ); + vmathSoaV3Prints( &tmpV3_1, "Quat rotate Vector3" ); + vmathSoaQConj( &tmpQ_8, &a_Quat ); + vmathSoaQPrints( &tmpQ_8, "Quat conj" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &b_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &e_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaQNormalize( &b_Quat, &b_Quat ); + vmathSoaQNormalize( &c_Quat, &c_Quat ); + vmathSoaQNormalize( &d_Quat, &d_Quat ); + vmathSoaQNormalize( &e_Quat, &e_Quat ); + vmathSoaQLerp( &a_Quat, randfloat(), &b_Quat, &c_Quat ); + vmathSoaQPrints( &a_Quat, "Quat lerp" ); + vmathSoaQSlerp( &a_Quat, randfloat(), &b_Quat, &c_Quat ); + vmathSoaQPrints( &a_Quat, "Quat slerp" ); + vmathSoaQSquad( &a_Quat, randfloat(), &b_Quat, &c_Quat, &d_Quat, &e_Quat ); + vmathSoaQPrints( &a_Quat, "Quat squad" ); +} + +int main() +{ + printf("\n __begin__ \n"); + for ( iteration = 0; iteration < 2; iteration++ ) { + Vector3_methods_test(); + Vector4_methods_test(); + Point3_methods_test(); + Quat_methods_test(); + } + printf("\n __end__ \n"); + return 0; +} diff --git a/Extras/vectormathlibrary/tests/test1_soa_cpp.cpp b/Extras/vectormathlibrary/tests/test1_soa_cpp.cpp new file mode 100644 index 0000000..daaeec4 --- /dev/null +++ b/Extras/vectormathlibrary/tests/test1_soa_cpp.cpp @@ -0,0 +1,931 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +#define _VECTORMATH_SOA_TEST + +#include "vectormath_soa.h" +#include "test.h" + +int iteration = 0; + +using namespace Vectormath; +using namespace Vectormath::Soa; + +void +Vector3_methods_test() +{ + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3, e_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4, e_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3, e_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat, e_Quat; + Aos::Vector3 aos_Vector3_0, aos_Vector3_1, aos_Vector3_2, aos_Vector3_3; + Vector3 soa_Vector3; + Aos::Vector4 aos_Vector4_0, aos_Vector4_1, aos_Vector4_2; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4; + float xyz4[12] __attribute__ ((aligned(16))); + xyz4[0] = getfloat(randfloat()); + xyz4[1] = getfloat(randfloat()); + xyz4[2] = getfloat(randfloat()); + xyz4[3] = getfloat(randfloat()); + xyz4[4] = getfloat(randfloat()); + xyz4[5] = getfloat(randfloat()); + xyz4[6] = getfloat(randfloat()); + xyz4[7] = getfloat(randfloat()); + xyz4[8] = getfloat(randfloat()); + xyz4[9] = getfloat(randfloat()); + xyz4[10] = getfloat(randfloat()); + xyz4[11] = getfloat(randfloat()); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + c_Vector3 = Vector3( (vec_float4){0.0f} ); + d_Vector3 = Vector3( (vec_float4){0.0f} ); + e_Vector3 = Vector3( (vec_float4){0.0f} ); + print( c_Vector3, "set Vector3 elements to zero" ); + print( d_Vector3, "set Vector3 elements to zero" ); + print( e_Vector3, "set Vector3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + c_Vector4 = Vector4( (vec_float4){0.0f} ); + d_Vector4 = Vector4( (vec_float4){0.0f} ); + e_Vector4 = Vector4( (vec_float4){0.0f} ); + print( c_Vector4, "set Vector4 elements to zero" ); + print( d_Vector4, "set Vector4 elements to zero" ); + print( e_Vector4, "set Vector4 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + c_Point3 = Point3( (vec_float4){0.0f} ); + d_Point3 = Point3( (vec_float4){0.0f} ); + e_Point3 = Point3( (vec_float4){0.0f} ); + print( c_Point3, "set Point3 elements to zero" ); + print( d_Point3, "set Point3 elements to zero" ); + print( e_Point3, "set Point3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + c_Quat = Quat( (vec_float4){0.0f} ); + d_Quat = Quat( (vec_float4){0.0f} ); + e_Quat = Quat( (vec_float4){0.0f} ); + print( c_Quat, "set Quat elements to zero" ); + print( d_Quat, "set Quat elements to zero" ); + print( e_Quat, "set Quat elements to zero" ); + a_Vector3 = Vector3( a_Point3 ); + print( a_Vector3, "construct Vector3 with Point3" ); + a_Vector3 = Vector3( randfloat() ); + print( a_Vector3, "set Vector3 with float" ); + a_Vector3 = Vector3( randfloat() ); + print( a_Vector3, "set Vector3 with float" ); + aos_Vector3_0 = Aos::Vector3( 0.0f, 1.0f, 2.0f ); + aos_Vector3_1 = Aos::Vector3( 3.0f, 4.0f, 5.0f ); + aos_Vector3_2 = Aos::Vector3( 6.0f, 7.0f, 8.0f ); + aos_Vector3_3 = Aos::Vector3( 9.0f, 10.0f, 11.0f ); + soa_Vector3 = Vector3( aos_Vector3_0, aos_Vector3_1, aos_Vector3_2, aos_Vector3_3 ); + soa_Vector3.get4Aos( aos_Vector3_3, aos_Vector3_2, aos_Vector3_1, aos_Vector3_0 ); + Aos::print( aos_Vector3_0, "aos type 0" ); + Aos::print( aos_Vector3_1, "aos type 1" ); + Aos::print( aos_Vector3_2, "aos type 2" ); + Aos::print( aos_Vector3_3, "aos type 3" ); + a_Vector3 = select( a_Vector3, b_Vector3, ((vec_uint4){0,0xffffffff,0,0xffffffff}) ); + a_Vector3.get4Aos( aos_Vector3_0, aos_Vector3_1, aos_Vector3_2, aos_Vector3_3 ); + Aos::print( aos_Vector3_0, "select 0" ); + Aos::print( aos_Vector3_1, "select 1" ); + Aos::print( aos_Vector3_2, "select 2" ); + Aos::print( aos_Vector3_3, "select 3" ); + loadXYZArray( a_Vector3, (const vec_float4 *)xyz4 ); + print( a_Vector3, "load XYZ array" ); + a_Vector3 = Vector3( ( -Vector3( a_Vector3 ) ) ); + storeXYZArray( a_Vector3, (vec_float4 *)xyz4 ); + aos_Vector4_0 = Aos::Vector4( xyz4[0], xyz4[1], xyz4[2], xyz4[3] ); + aos_Vector4_1 = Aos::Vector4( xyz4[4], xyz4[5], xyz4[6], xyz4[7] ); + aos_Vector4_2 = Aos::Vector4( xyz4[8], xyz4[9], xyz4[10], xyz4[11] ); + Aos::print( aos_Vector4_0, "xyzx" ); + Aos::print( aos_Vector4_1, "yzxy" ); + Aos::print( aos_Vector4_2, "zxyz" ); + Aos::print( aos_Vector4_0, "xyzx" ); + Aos::print( aos_Vector4_1, "yzxy" ); + Aos::print( aos_Vector4_2, "zxyz" ); + printf("storeXYZ:-1.0 -2.0 -3.0 0.4\n"); + a_Vector3 = b_Vector3; + print( a_Vector3, "assign to Vector3 from Vector3" ); + a_Vector3 = Vector3( (vec_float4){0.0f} ); + print( a_Vector3, "set Vector3 elements to zero" ); + a_Vector3 = Vector3::xAxis( ); + print( a_Vector3, "set to x axis" ); + a_Vector3 = Vector3::yAxis( ); + print( a_Vector3, "set to y axis" ); + a_Vector3 = Vector3::zAxis( ); + print( a_Vector3, "set to z axis" ); + a_Vector3.setElem( 0, randfloat() ); + print( a_Vector3, "Vector3::set( 0, float )" ); + a_Vector3[0] = randfloat(); + a_Vector3[0] = vec_mul_float( a_Vector3[0], randfloat() ); + a_Vector3[0] = divf4( a_Vector3[0], randfloat() ); + a_Vector3[0] = vec_add_float( a_Vector3[0], randfloat() ); + a_Vector3[0] = vec_sub_float( a_Vector3[0], randfloat() ); + print( a_Vector3, "Vector3::operator [](0)" ); + a_Vector3.setX( randfloat() ); + print( a_Vector3, "Vector3::setX()" ); + a_Vector3.setElem( 1, randfloat() ); + print( a_Vector3, "Vector3::set( 1, float )" ); + a_Vector3[1] = randfloat(); + a_Vector3[1] = vec_mul_float( a_Vector3[1], randfloat() ); + a_Vector3[1] = divf4( a_Vector3[1], randfloat() ); + a_Vector3[1] = vec_add_float( a_Vector3[1], randfloat() ); + a_Vector3[1] = vec_sub_float( a_Vector3[1], randfloat() ); + print( a_Vector3, "Vector3::operator [](1)" ); + a_Vector3.setY( randfloat() ); + print( a_Vector3, "Vector3::setY()" ); + a_Vector3.setElem( 2, randfloat() ); + print( a_Vector3, "Vector3::set( 2, float )" ); + a_Vector3[2] = randfloat(); + a_Vector3[2] = vec_mul_float( a_Vector3[2], randfloat() ); + a_Vector3[2] = divf4( a_Vector3[2], randfloat() ); + a_Vector3[2] = vec_add_float( a_Vector3[2], randfloat() ); + a_Vector3[2] = vec_sub_float( a_Vector3[2], randfloat() ); + print( a_Vector3, "Vector3::operator [](2)" ); + a_Vector3.setZ( randfloat() ); + print( a_Vector3, "Vector3::setZ()" ); + printf("Vector3::get( 0 ): %f\n", getfloat(a_Vector3.getElem( 0 )) ); + printf("Vector3::operator []( 0 ): %f\n", getfloat((vec_float4)a_Vector3[0]) ); + printf("Vector3::getX(): %f\n", getfloat(a_Vector3.getX( )) ); + printf("Vector3::get( 1 ): %f\n", getfloat(a_Vector3.getElem( 1 )) ); + printf("Vector3::operator []( 1 ): %f\n", getfloat((vec_float4)a_Vector3[1]) ); + printf("Vector3::getY(): %f\n", getfloat(a_Vector3.getY( )) ); + printf("Vector3::get( 2 ): %f\n", getfloat(a_Vector3.getElem( 2 )) ); + printf("Vector3::operator []( 2 ): %f\n", getfloat((vec_float4)a_Vector3[2]) ); + printf("Vector3::getZ(): %f\n", getfloat(a_Vector3.getZ( )) ); + print( ( a_Vector3 + b_Vector3 ), "Vector3 + Vector3" ); + print( ( a_Vector3 - b_Vector3 ), "Vector3 - Vector3" ); + print( ( a_Vector3 + b_Point3 ), "Vector3 + Point3" ); + print( ( a_Vector3 * randfloat() ), "Vector3 * float" ); + print( ( a_Vector3 / randfloat() ), "Vector3 / float" ); + print( ( randfloat() * a_Vector3 ), "float * Vector3" ); + print( ( -a_Vector3 ), "Vector3 negate" ); + print( mulPerElem( a_Vector3, b_Vector3 ), "mulPerElem( Vector3, Vector3 )" ); + print( divPerElem( a_Vector3, b_Vector3 ), "divPerElem( Vector3, Vector3 )" ); + print( recipPerElem( a_Vector3 ), "Vector3 recip" ); + print( sqrtPerElem( absPerElem( a_Vector3 ) ), "Vector3 sqrt" ); + print( rsqrtPerElem( absPerElem( a_Vector3 ) ), "Vector3 rsqrt" ); + print( absPerElem( a_Vector3 ), "Vector3 abs" ); + print( copySignPerElem( a_Vector3, b_Vector3 ), "Vector3 copySign" ); + print( maxPerElem( a_Vector3, b_Vector3 ), "Vector3 maximum Vector3" ); + print( minPerElem( a_Vector3, b_Vector3 ), "Vector3 minimum Vector3" ); + printf("Vector3 maximum of elements: %f\n", getfloat(maxElem( a_Vector3 ))); + printf("Vector3 minimum of elements: %f\n", getfloat(minElem( a_Vector3 ))); + printf("Vector3 sum of elements: %f\n", getfloat(sum( a_Vector3 ))); + printf("Vector3 dot Vector3: %f\n", getfloat(dot( a_Vector3, b_Vector3 ))); + printf("Vector3 lengthSqr: %f\n", getfloat(lengthSqr( a_Vector3 ))); + printf("Vector3 length: %f\n", getfloat(length( a_Vector3 ))); + print( normalize( a_Vector3 ), "Vector3 normalized" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + e_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + b_Vector3 = normalize( b_Vector3 ); + c_Vector3 = normalize( c_Vector3 ); + d_Vector3 = normalize( d_Vector3 ); + e_Vector3 = normalize( e_Vector3 ); + a_Vector3 = lerp( randfloat(), b_Vector3, c_Vector3 ); + print( a_Vector3, "Vector3 lerp" ); + a_Vector3 = slerp( randfloat(), b_Vector3, c_Vector3 ); + print( a_Vector3, "Vector3 slerp" ); +} + +void +Vector4_methods_test() +{ + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3, e_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4, e_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3, e_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat, e_Quat; + Aos::Vector4 aos_Vector4_0, aos_Vector4_1, aos_Vector4_2, aos_Vector4_3; + Vector4 soa_Vector4; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + c_Vector3 = Vector3( (vec_float4){0.0f} ); + d_Vector3 = Vector3( (vec_float4){0.0f} ); + e_Vector3 = Vector3( (vec_float4){0.0f} ); + print( c_Vector3, "set Vector3 elements to zero" ); + print( d_Vector3, "set Vector3 elements to zero" ); + print( e_Vector3, "set Vector3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + c_Vector4 = Vector4( (vec_float4){0.0f} ); + d_Vector4 = Vector4( (vec_float4){0.0f} ); + e_Vector4 = Vector4( (vec_float4){0.0f} ); + print( c_Vector4, "set Vector4 elements to zero" ); + print( d_Vector4, "set Vector4 elements to zero" ); + print( e_Vector4, "set Vector4 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + c_Point3 = Point3( (vec_float4){0.0f} ); + d_Point3 = Point3( (vec_float4){0.0f} ); + e_Point3 = Point3( (vec_float4){0.0f} ); + print( c_Point3, "set Point3 elements to zero" ); + print( d_Point3, "set Point3 elements to zero" ); + print( e_Point3, "set Point3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + c_Quat = Quat( (vec_float4){0.0f} ); + d_Quat = Quat( (vec_float4){0.0f} ); + e_Quat = Quat( (vec_float4){0.0f} ); + print( c_Quat, "set Quat elements to zero" ); + print( d_Quat, "set Quat elements to zero" ); + print( e_Quat, "set Quat elements to zero" ); + a_Vector4 = Vector4( a_Vector3, randfloat() ); + print( a_Vector4, "set Vector4 with Vector3, float" ); + a_Vector4 = Vector4( a_Vector3 ); + print( a_Vector4, "set Vector4 with Vector3" ); + a_Vector4 = Vector4( a_Point3 ); + print( a_Vector4, "set Vector4 with Point3" ); + a_Vector4 = Vector4( a_Quat ); + print( a_Vector4, "construct Vector4 with Quat" ); + a_Vector4 = Vector4( randfloat() ); + print( a_Vector4, "set Vector4 with float" ); + a_Vector4 = Vector4( randfloat() ); + print( a_Vector4, "set Vector4 with float" ); + aos_Vector4_0 = Aos::Vector4( 0.0f, 1.0f, 2.0f, 3.0f ); + aos_Vector4_1 = Aos::Vector4( 4.0f, 5.0f, 6.0f, 7.0f ); + aos_Vector4_2 = Aos::Vector4( 8.0f, 9.0f, 10.0f, 11.0f ); + aos_Vector4_3 = Aos::Vector4( 12.0f, 13.0f, 14.0f, 15.0f ); + soa_Vector4 = Vector4( aos_Vector4_0, aos_Vector4_1, aos_Vector4_2, aos_Vector4_3 ); + soa_Vector4.get4Aos( aos_Vector4_3, aos_Vector4_2, aos_Vector4_1, aos_Vector4_0 ); + Aos::print( aos_Vector4_0, "aos type 0" ); + Aos::print( aos_Vector4_1, "aos type 1" ); + Aos::print( aos_Vector4_2, "aos type 2" ); + Aos::print( aos_Vector4_3, "aos type 3" ); + a_Vector4 = select( a_Vector4, b_Vector4, ((vec_uint4){0,0xffffffff,0,0xffffffff}) ); + a_Vector4.get4Aos( aos_Vector4_0, aos_Vector4_1, aos_Vector4_2, aos_Vector4_3 ); + Aos::print( aos_Vector4_0, "select 0" ); + Aos::print( aos_Vector4_1, "select 1" ); + Aos::print( aos_Vector4_2, "select 2" ); + Aos::print( aos_Vector4_3, "select 3" ); + a_Vector4 = b_Vector4; + print( a_Vector4, "assign to Vector4 from Vector4" ); + a_Vector4.setXYZ( a_Vector3 ); + print( a_Vector4, "set Vector4 xyz" ); + print( a_Vector4.getXYZ( ), "get Vector4 xyz" ); + a_Vector4 = Vector4( (vec_float4){0.0f} ); + print( a_Vector4, "set Vector4 elements to zero" ); + a_Vector4 = Vector4::xAxis( ); + print( a_Vector4, "set to x axis" ); + a_Vector4 = Vector4::yAxis( ); + print( a_Vector4, "set to y axis" ); + a_Vector4 = Vector4::zAxis( ); + print( a_Vector4, "set to z axis" ); + a_Vector4 = Vector4::wAxis( ); + print( a_Vector4, "set to w axis" ); + a_Vector4.setElem( 0, randfloat() ); + print( a_Vector4, "Vector4::set( 0, float )" ); + a_Vector4[0] = randfloat(); + a_Vector4[0] = vec_mul_float( a_Vector4[0], randfloat() ); + a_Vector4[0] = divf4( a_Vector4[0], randfloat() ); + a_Vector4[0] = vec_add_float( a_Vector4[0], randfloat() ); + a_Vector4[0] = vec_sub_float( a_Vector4[0], randfloat() ); + print( a_Vector4, "Vector4::operator [](0)" ); + a_Vector4.setX( randfloat() ); + print( a_Vector4, "Vector4::setX()" ); + a_Vector4.setElem( 1, randfloat() ); + print( a_Vector4, "Vector4::set( 1, float )" ); + a_Vector4[1] = randfloat(); + a_Vector4[1] = vec_mul_float( a_Vector4[1], randfloat() ); + a_Vector4[1] = divf4( a_Vector4[1], randfloat() ); + a_Vector4[1] = vec_add_float( a_Vector4[1], randfloat() ); + a_Vector4[1] = vec_sub_float( a_Vector4[1], randfloat() ); + print( a_Vector4, "Vector4::operator [](1)" ); + a_Vector4.setY( randfloat() ); + print( a_Vector4, "Vector4::setY()" ); + a_Vector4.setElem( 2, randfloat() ); + print( a_Vector4, "Vector4::set( 2, float )" ); + a_Vector4[2] = randfloat(); + a_Vector4[2] = vec_mul_float( a_Vector4[2], randfloat() ); + a_Vector4[2] = divf4( a_Vector4[2], randfloat() ); + a_Vector4[2] = vec_add_float( a_Vector4[2], randfloat() ); + a_Vector4[2] = vec_sub_float( a_Vector4[2], randfloat() ); + print( a_Vector4, "Vector4::operator [](2)" ); + a_Vector4.setZ( randfloat() ); + print( a_Vector4, "Vector4::setZ()" ); + a_Vector4.setElem( 3, randfloat() ); + print( a_Vector4, "Vector4::set( 3, float )" ); + a_Vector4[3] = randfloat(); + a_Vector4[3] = vec_mul_float( a_Vector4[3], randfloat() ); + a_Vector4[3] = divf4( a_Vector4[3], randfloat() ); + a_Vector4[3] = vec_add_float( a_Vector4[3], randfloat() ); + a_Vector4[3] = vec_sub_float( a_Vector4[3], randfloat() ); + print( a_Vector4, "Vector4::operator [](3)" ); + a_Vector4.setW( randfloat() ); + print( a_Vector4, "Vector4::setW()" ); + printf("Vector4::get( 0 ): %f\n", getfloat(a_Vector4.getElem( 0 )) ); + printf("Vector4::operator []( 0 ): %f\n", getfloat((vec_float4)a_Vector4[0]) ); + printf("Vector4::getX(): %f\n", getfloat(a_Vector4.getX( )) ); + printf("Vector4::get( 1 ): %f\n", getfloat(a_Vector4.getElem( 1 )) ); + printf("Vector4::operator []( 1 ): %f\n", getfloat((vec_float4)a_Vector4[1]) ); + printf("Vector4::getY(): %f\n", getfloat(a_Vector4.getY( )) ); + printf("Vector4::get( 2 ): %f\n", getfloat(a_Vector4.getElem( 2 )) ); + printf("Vector4::operator []( 2 ): %f\n", getfloat((vec_float4)a_Vector4[2]) ); + printf("Vector4::getZ(): %f\n", getfloat(a_Vector4.getZ( )) ); + printf("Vector4::get( 3 ): %f\n", getfloat(a_Vector4.getElem( 3 )) ); + printf("Vector4::operator []( 3 ): %f\n", getfloat((vec_float4)a_Vector4[3]) ); + printf("Vector4::getW(): %f\n", getfloat(a_Vector4.getW( )) ); + print( ( a_Vector4 + b_Vector4 ), "Vector4 + Vector4" ); + print( ( a_Vector4 - b_Vector4 ), "Vector4 - Vector4" ); + print( ( a_Vector4 * randfloat() ), "Vector4 * float" ); + print( ( a_Vector4 / randfloat() ), "Vector4 / float" ); + print( ( randfloat() * a_Vector4 ), "float * Vector4" ); + print( ( -a_Vector4 ), "Vector4 negate" ); + print( mulPerElem( a_Vector4, b_Vector4 ), "mulPerElem( Vector4, Vector4 )" ); + print( divPerElem( a_Vector4, b_Vector4 ), "divPerElem( Vector4, Vector4 )" ); + print( recipPerElem( a_Vector4 ), "Vector4 recip" ); + print( sqrtPerElem( absPerElem( a_Vector4 ) ), "Vector4 sqrt" ); + print( rsqrtPerElem( absPerElem( a_Vector4 ) ), "Vector4 rsqrt" ); + print( absPerElem( a_Vector4 ), "Vector4 abs" ); + print( copySignPerElem( a_Vector4, b_Vector4 ), "Vector4 copySign" ); + print( maxPerElem( a_Vector4, b_Vector4 ), "Vector4 maximum Vector4" ); + print( minPerElem( a_Vector4, b_Vector4 ), "Vector4 minimum Vector4" ); + printf("Vector4 maximum of elements: %f\n", getfloat(maxElem( a_Vector4 ))); + printf("Vector4 minimum of elements: %f\n", getfloat(minElem( a_Vector4 ))); + printf("Vector4 sum of elements: %f\n", getfloat(sum( a_Vector4 ))); + printf("Vector4 dot Vector4: %f\n", getfloat(dot( a_Vector4, b_Vector4 ))); + printf("Vector4 lengthSqr: %f\n", getfloat(lengthSqr( a_Vector4 ))); + printf("Vector4 length: %f\n", getfloat(length( a_Vector4 ))); + print( normalize( a_Vector4 ), "Vector4 normalized" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + e_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + b_Vector4 = normalize( b_Vector4 ); + c_Vector4 = normalize( c_Vector4 ); + d_Vector4 = normalize( d_Vector4 ); + e_Vector4 = normalize( e_Vector4 ); + a_Vector4 = lerp( randfloat(), b_Vector4, c_Vector4 ); + print( a_Vector4, "Vector4 lerp" ); + a_Vector4 = slerp( randfloat(), b_Vector4, c_Vector4 ); + print( a_Vector4, "Vector4 slerp" ); +} + +void +Point3_methods_test() +{ + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3, e_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4, e_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3, e_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat, e_Quat; + Aos::Point3 aos_Point3_0, aos_Point3_1, aos_Point3_2, aos_Point3_3; + Point3 soa_Point3; + Aos::Vector4 aos_Vector4_0, aos_Vector4_1, aos_Vector4_2; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4; + float xyz4[12] __attribute__ ((aligned(16))); + xyz4[0] = getfloat(randfloat()); + xyz4[1] = getfloat(randfloat()); + xyz4[2] = getfloat(randfloat()); + xyz4[3] = getfloat(randfloat()); + xyz4[4] = getfloat(randfloat()); + xyz4[5] = getfloat(randfloat()); + xyz4[6] = getfloat(randfloat()); + xyz4[7] = getfloat(randfloat()); + xyz4[8] = getfloat(randfloat()); + xyz4[9] = getfloat(randfloat()); + xyz4[10] = getfloat(randfloat()); + xyz4[11] = getfloat(randfloat()); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + c_Vector3 = Vector3( (vec_float4){0.0f} ); + d_Vector3 = Vector3( (vec_float4){0.0f} ); + e_Vector3 = Vector3( (vec_float4){0.0f} ); + print( c_Vector3, "set Vector3 elements to zero" ); + print( d_Vector3, "set Vector3 elements to zero" ); + print( e_Vector3, "set Vector3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + c_Vector4 = Vector4( (vec_float4){0.0f} ); + d_Vector4 = Vector4( (vec_float4){0.0f} ); + e_Vector4 = Vector4( (vec_float4){0.0f} ); + print( c_Vector4, "set Vector4 elements to zero" ); + print( d_Vector4, "set Vector4 elements to zero" ); + print( e_Vector4, "set Vector4 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + c_Point3 = Point3( (vec_float4){0.0f} ); + d_Point3 = Point3( (vec_float4){0.0f} ); + e_Point3 = Point3( (vec_float4){0.0f} ); + print( c_Point3, "set Point3 elements to zero" ); + print( d_Point3, "set Point3 elements to zero" ); + print( e_Point3, "set Point3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + c_Quat = Quat( (vec_float4){0.0f} ); + d_Quat = Quat( (vec_float4){0.0f} ); + e_Quat = Quat( (vec_float4){0.0f} ); + print( c_Quat, "set Quat elements to zero" ); + print( d_Quat, "set Quat elements to zero" ); + print( e_Quat, "set Quat elements to zero" ); + a_Point3 = Point3( a_Vector3 ); + print( a_Point3, "construct Point3 with Vector3" ); + a_Point3 = Point3( randfloat() ); + print( a_Point3, "set Point3 with float" ); + a_Point3 = Point3( randfloat() ); + print( a_Point3, "set Point3 with float" ); + aos_Point3_0 = Aos::Point3( 0.0f, 1.0f, 2.0f ); + aos_Point3_1 = Aos::Point3( 3.0f, 4.0f, 5.0f ); + aos_Point3_2 = Aos::Point3( 6.0f, 7.0f, 8.0f ); + aos_Point3_3 = Aos::Point3( 9.0f, 10.0f, 11.0f ); + soa_Point3 = Point3( aos_Point3_0, aos_Point3_1, aos_Point3_2, aos_Point3_3 ); + soa_Point3.get4Aos( aos_Point3_3, aos_Point3_2, aos_Point3_1, aos_Point3_0 ); + Aos::print( aos_Point3_0, "aos type 0" ); + Aos::print( aos_Point3_1, "aos type 1" ); + Aos::print( aos_Point3_2, "aos type 2" ); + Aos::print( aos_Point3_3, "aos type 3" ); + a_Point3 = select( a_Point3, b_Point3, ((vec_uint4){0,0xffffffff,0,0xffffffff}) ); + a_Point3.get4Aos( aos_Point3_0, aos_Point3_1, aos_Point3_2, aos_Point3_3 ); + Aos::print( aos_Point3_0, "select 0" ); + Aos::print( aos_Point3_1, "select 1" ); + Aos::print( aos_Point3_2, "select 2" ); + Aos::print( aos_Point3_3, "select 3" ); + loadXYZArray( a_Point3, (const vec_float4 *)xyz4 ); + print( a_Point3, "load XYZ array" ); + a_Point3 = Point3( ( -Vector3( a_Point3 ) ) ); + storeXYZArray( a_Point3, (vec_float4 *)xyz4 ); + aos_Vector4_0 = Aos::Vector4( xyz4[0], xyz4[1], xyz4[2], xyz4[3] ); + aos_Vector4_1 = Aos::Vector4( xyz4[4], xyz4[5], xyz4[6], xyz4[7] ); + aos_Vector4_2 = Aos::Vector4( xyz4[8], xyz4[9], xyz4[10], xyz4[11] ); + Aos::print( aos_Vector4_0, "xyzx" ); + Aos::print( aos_Vector4_1, "yzxy" ); + Aos::print( aos_Vector4_2, "zxyz" ); + Aos::print( aos_Vector4_0, "xyzx" ); + Aos::print( aos_Vector4_1, "yzxy" ); + Aos::print( aos_Vector4_2, "zxyz" ); + printf("storeXYZ:-1.0 -2.0 -3.0 0.4\n"); + a_Point3 = b_Point3; + print( a_Point3, "assign to Point3 from Point3" ); + a_Point3 = Point3( (vec_float4){0.0f} ); + print( a_Point3, "set Point3 elements to zero" ); + a_Point3.setElem( 0, randfloat() ); + print( a_Point3, "Point3::set( 0, float )" ); + a_Point3[0] = randfloat(); + a_Point3[0] = vec_mul_float( a_Point3[0], randfloat() ); + a_Point3[0] = divf4( a_Point3[0], randfloat() ); + a_Point3[0] = vec_add_float( a_Point3[0], randfloat() ); + a_Point3[0] = vec_sub_float( a_Point3[0], randfloat() ); + print( a_Point3, "Point3::operator [](0)" ); + a_Point3.setX( randfloat() ); + print( a_Point3, "Point3::setX()" ); + a_Point3.setElem( 1, randfloat() ); + print( a_Point3, "Point3::set( 1, float )" ); + a_Point3[1] = randfloat(); + a_Point3[1] = vec_mul_float( a_Point3[1], randfloat() ); + a_Point3[1] = divf4( a_Point3[1], randfloat() ); + a_Point3[1] = vec_add_float( a_Point3[1], randfloat() ); + a_Point3[1] = vec_sub_float( a_Point3[1], randfloat() ); + print( a_Point3, "Point3::operator [](1)" ); + a_Point3.setY( randfloat() ); + print( a_Point3, "Point3::setY()" ); + a_Point3.setElem( 2, randfloat() ); + print( a_Point3, "Point3::set( 2, float )" ); + a_Point3[2] = randfloat(); + a_Point3[2] = vec_mul_float( a_Point3[2], randfloat() ); + a_Point3[2] = divf4( a_Point3[2], randfloat() ); + a_Point3[2] = vec_add_float( a_Point3[2], randfloat() ); + a_Point3[2] = vec_sub_float( a_Point3[2], randfloat() ); + print( a_Point3, "Point3::operator [](2)" ); + a_Point3.setZ( randfloat() ); + print( a_Point3, "Point3::setZ()" ); + printf("Point3::get( 0 ): %f\n", getfloat(a_Point3.getElem( 0 )) ); + printf("Point3::operator []( 0 ): %f\n", getfloat((vec_float4)a_Point3[0]) ); + printf("Point3::getX(): %f\n", getfloat(a_Point3.getX( )) ); + printf("Point3::get( 1 ): %f\n", getfloat(a_Point3.getElem( 1 )) ); + printf("Point3::operator []( 1 ): %f\n", getfloat((vec_float4)a_Point3[1]) ); + printf("Point3::getY(): %f\n", getfloat(a_Point3.getY( )) ); + printf("Point3::get( 2 ): %f\n", getfloat(a_Point3.getElem( 2 )) ); + printf("Point3::operator []( 2 ): %f\n", getfloat((vec_float4)a_Point3[2]) ); + printf("Point3::getZ(): %f\n", getfloat(a_Point3.getZ( )) ); + print( ( a_Point3 - b_Point3 ), "Point3 - Point3" ); + print( ( a_Point3 + b_Vector3 ), "Point3 + Vector3" ); + print( ( a_Point3 - b_Vector3 ), "Point3 - Vector3" ); + print( mulPerElem( a_Point3, b_Point3 ), "mulPerElem( Point3, Point3 )" ); + print( divPerElem( a_Point3, b_Point3 ), "divPerElem( Point3, Point3 )" ); + print( recipPerElem( a_Point3 ), "Point3 recip" ); + print( sqrtPerElem( absPerElem( a_Point3 ) ), "Point3 sqrt" ); + print( rsqrtPerElem( absPerElem( a_Point3 ) ), "Point3 rsqrt" ); + print( absPerElem( a_Point3 ), "Point3 abs" ); + print( copySignPerElem( a_Point3, b_Point3 ), "Point3 copySign" ); + print( maxPerElem( a_Point3, b_Point3 ), "Point3 maximum Point3" ); + print( minPerElem( a_Point3, b_Point3 ), "Point3 minimum Point3" ); + printf("Point3 maximum of elements: %f\n", getfloat(maxElem( a_Point3 ))); + printf("Point3 minimum of elements: %f\n", getfloat(minElem( a_Point3 ))); + printf("Point3 sum of elements: %f\n", getfloat(sum( a_Point3 ))); + printf("Point projection: %f\n", getfloat(projection( a_Point3, b_Vector3 ))); + printf("Point distSqrFromOrigin: %f\n", getfloat(distSqrFromOrigin( a_Point3 )) ); + printf("Point distFromOrigin: %f\n", getfloat(distFromOrigin( a_Point3 )) ); + printf("Point distSqr: %f\n", getfloat(distSqr( a_Point3, b_Point3 )) ); + printf("Point dist: %f\n", getfloat(dist( a_Point3, b_Point3 )) ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + e_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + a_Point3 = lerp( randfloat(), b_Point3, c_Point3 ); + print( a_Point3, "Point3 lerp" ); +} + +void +Quat_methods_test() +{ + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3, e_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4, e_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3, e_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat, e_Quat; + Aos::Quat aos_Quat_0, aos_Quat_1, aos_Quat_2, aos_Quat_3; + Quat soa_Quat; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + c_Vector3 = Vector3( (vec_float4){0.0f} ); + d_Vector3 = Vector3( (vec_float4){0.0f} ); + e_Vector3 = Vector3( (vec_float4){0.0f} ); + print( c_Vector3, "set Vector3 elements to zero" ); + print( d_Vector3, "set Vector3 elements to zero" ); + print( e_Vector3, "set Vector3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + c_Vector4 = Vector4( (vec_float4){0.0f} ); + d_Vector4 = Vector4( (vec_float4){0.0f} ); + e_Vector4 = Vector4( (vec_float4){0.0f} ); + print( c_Vector4, "set Vector4 elements to zero" ); + print( d_Vector4, "set Vector4 elements to zero" ); + print( e_Vector4, "set Vector4 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + b_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + c_Point3 = Point3( (vec_float4){0.0f} ); + d_Point3 = Point3( (vec_float4){0.0f} ); + e_Point3 = Point3( (vec_float4){0.0f} ); + print( c_Point3, "set Point3 elements to zero" ); + print( d_Point3, "set Point3 elements to zero" ); + print( e_Point3, "set Point3 elements to zero" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + c_Quat = Quat( (vec_float4){0.0f} ); + d_Quat = Quat( (vec_float4){0.0f} ); + e_Quat = Quat( (vec_float4){0.0f} ); + print( c_Quat, "set Quat elements to zero" ); + print( d_Quat, "set Quat elements to zero" ); + print( e_Quat, "set Quat elements to zero" ); + a_Quat = Quat( a_Vector3, randfloat() ); + print( a_Quat, "set Quat with Vector3, float" ); + a_Quat = Quat( a_Vector4 ); + print( a_Quat, "construct Quat with Vector4" ); + a_Quat = Quat( randfloat() ); + print( a_Quat, "set Quat with float" ); + a_Quat = Quat( randfloat() ); + print( a_Quat, "set Quat with float" ); + aos_Quat_0 = Aos::Quat( 0.0f, 1.0f, 2.0f, 3.0f ); + aos_Quat_1 = Aos::Quat( 4.0f, 5.0f, 6.0f, 7.0f ); + aos_Quat_2 = Aos::Quat( 8.0f, 9.0f, 10.0f, 11.0f ); + aos_Quat_3 = Aos::Quat( 12.0f, 13.0f, 14.0f, 15.0f ); + soa_Quat = Quat( aos_Quat_0, aos_Quat_1, aos_Quat_2, aos_Quat_3 ); + soa_Quat.get4Aos( aos_Quat_3, aos_Quat_2, aos_Quat_1, aos_Quat_0 ); + Aos::print( aos_Quat_0, "aos type 0" ); + Aos::print( aos_Quat_1, "aos type 1" ); + Aos::print( aos_Quat_2, "aos type 2" ); + Aos::print( aos_Quat_3, "aos type 3" ); + a_Quat = select( a_Quat, b_Quat, ((vec_uint4){0,0xffffffff,0,0xffffffff}) ); + a_Quat.get4Aos( aos_Quat_0, aos_Quat_1, aos_Quat_2, aos_Quat_3 ); + Aos::print( aos_Quat_0, "select 0" ); + Aos::print( aos_Quat_1, "select 1" ); + Aos::print( aos_Quat_2, "select 2" ); + Aos::print( aos_Quat_3, "select 3" ); + a_Quat = b_Quat; + print( a_Quat, "assign to Quat from Quat" ); + a_Quat.setXYZ( a_Vector3 ); + print( a_Quat, "set Quat xyz" ); + print( a_Quat.getXYZ( ), "get Quat xyz" ); + a_Quat = Quat( (vec_float4){0.0f} ); + print( a_Quat, "set Quat elements to zero" ); + a_Quat.setElem( 0, randfloat() ); + print( a_Quat, "Quat::set( 0, float )" ); + a_Quat[0] = randfloat(); + a_Quat[0] = vec_mul_float( a_Quat[0], randfloat() ); + a_Quat[0] = divf4( a_Quat[0], randfloat() ); + a_Quat[0] = vec_add_float( a_Quat[0], randfloat() ); + a_Quat[0] = vec_sub_float( a_Quat[0], randfloat() ); + print( a_Quat, "Quat::operator [](0)" ); + a_Quat.setX( randfloat() ); + print( a_Quat, "Quat::setX()" ); + a_Quat.setElem( 1, randfloat() ); + print( a_Quat, "Quat::set( 1, float )" ); + a_Quat[1] = randfloat(); + a_Quat[1] = vec_mul_float( a_Quat[1], randfloat() ); + a_Quat[1] = divf4( a_Quat[1], randfloat() ); + a_Quat[1] = vec_add_float( a_Quat[1], randfloat() ); + a_Quat[1] = vec_sub_float( a_Quat[1], randfloat() ); + print( a_Quat, "Quat::operator [](1)" ); + a_Quat.setY( randfloat() ); + print( a_Quat, "Quat::setY()" ); + a_Quat.setElem( 2, randfloat() ); + print( a_Quat, "Quat::set( 2, float )" ); + a_Quat[2] = randfloat(); + a_Quat[2] = vec_mul_float( a_Quat[2], randfloat() ); + a_Quat[2] = divf4( a_Quat[2], randfloat() ); + a_Quat[2] = vec_add_float( a_Quat[2], randfloat() ); + a_Quat[2] = vec_sub_float( a_Quat[2], randfloat() ); + print( a_Quat, "Quat::operator [](2)" ); + a_Quat.setZ( randfloat() ); + print( a_Quat, "Quat::setZ()" ); + a_Quat.setElem( 3, randfloat() ); + print( a_Quat, "Quat::set( 3, float )" ); + a_Quat[3] = randfloat(); + a_Quat[3] = vec_mul_float( a_Quat[3], randfloat() ); + a_Quat[3] = divf4( a_Quat[3], randfloat() ); + a_Quat[3] = vec_add_float( a_Quat[3], randfloat() ); + a_Quat[3] = vec_sub_float( a_Quat[3], randfloat() ); + print( a_Quat, "Quat::operator [](3)" ); + a_Quat.setW( randfloat() ); + print( a_Quat, "Quat::setW()" ); + printf("Quat::get( 0 ): %f\n", getfloat(a_Quat.getElem( 0 )) ); + printf("Quat::operator []( 0 ): %f\n", getfloat((vec_float4)a_Quat[0]) ); + printf("Quat::getX(): %f\n", getfloat(a_Quat.getX( )) ); + printf("Quat::get( 1 ): %f\n", getfloat(a_Quat.getElem( 1 )) ); + printf("Quat::operator []( 1 ): %f\n", getfloat((vec_float4)a_Quat[1]) ); + printf("Quat::getY(): %f\n", getfloat(a_Quat.getY( )) ); + printf("Quat::get( 2 ): %f\n", getfloat(a_Quat.getElem( 2 )) ); + printf("Quat::operator []( 2 ): %f\n", getfloat((vec_float4)a_Quat[2]) ); + printf("Quat::getZ(): %f\n", getfloat(a_Quat.getZ( )) ); + printf("Quat::get( 3 ): %f\n", getfloat(a_Quat.getElem( 3 )) ); + printf("Quat::operator []( 3 ): %f\n", getfloat((vec_float4)a_Quat[3]) ); + printf("Quat::getW(): %f\n", getfloat(a_Quat.getW( )) ); + print( ( a_Quat + b_Quat ), "Quat + Quat" ); + print( ( a_Quat - b_Quat ), "Quat - Quat" ); + print( ( a_Quat * b_Quat ), "Quat * Quat" ); + print( ( a_Quat * randfloat() ), "Quat * float" ); + print( ( a_Quat / randfloat() ), "Quat / float" ); + print( ( randfloat() * a_Quat ), "float * Quat" ); + print( ( -a_Quat ), "Quat negate" ); + printf("Quat dot Quat: %f\n", getfloat(dot( a_Quat, b_Quat ))); + printf("Quat lengthSqr: %f\n", getfloat(norm( a_Quat ))); + printf("Quat length: %f\n", getfloat(length( a_Quat ))); + print( normalize( a_Quat ), "Quat normalized" ); + a_Quat = Quat::identity( ); + print( a_Quat, "set to identity" ); + a_Quat = Quat::rotation( a_Vector3, b_Vector3 ); + print( a_Quat, "Quat rotation between vectors" ); + a_Quat = Quat::rotation( randfloat(), a_Vector3 ); + print( a_Quat, "Quat rotation axis angle" ); + a_Quat = Quat::rotationX( randfloat() ); + print( a_Quat, "Quat rotationX" ); + a_Quat = Quat::rotationY( randfloat() ); + print( a_Quat, "Quat rotationY" ); + a_Quat = Quat::rotationZ( randfloat() ); + print( a_Quat, "Quat rotationZ" ); + print( rotate( a_Quat, a_Vector3 ), "Quat rotate Vector3" ); + print( conj( a_Quat ), "Quat conj" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + b_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + e_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + b_Quat = normalize( b_Quat ); + c_Quat = normalize( c_Quat ); + d_Quat = normalize( d_Quat ); + e_Quat = normalize( e_Quat ); + a_Quat = lerp( randfloat(), b_Quat, c_Quat ); + print( a_Quat, "Quat lerp" ); + a_Quat = slerp( randfloat(), b_Quat, c_Quat ); + print( a_Quat, "Quat slerp" ); + a_Quat = squad( randfloat(), b_Quat, c_Quat, d_Quat, e_Quat ); + print( a_Quat, "Quat squad" ); +} + +int main() +{ + printf("\n __begin__ \n"); + for ( iteration = 0; iteration < 2; iteration++ ) { + Vector3_methods_test(); + Vector4_methods_test(); + Point3_methods_test(); + Quat_methods_test(); + } + printf("\n __end__ \n"); + return 0; +} diff --git a/Extras/vectormathlibrary/tests/test2_aos_c.c b/Extras/vectormathlibrary/tests/test2_aos_c.c new file mode 100644 index 0000000..27acec0 --- /dev/null +++ b/Extras/vectormathlibrary/tests/test2_aos_c.c @@ -0,0 +1,852 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +#define _VECTORMATH_AOS_TEST + +#include "vectormath_aos.h" +#include "test.h" + +int iteration = 0; + +void +Matrix3_methods_test() +{ + VmathMatrix3 a_Matrix3, b_Matrix3; + VmathMatrix4 a_Matrix4, b_Matrix4; + VmathTransform3 a_Transform3, b_Transform3; + VmathVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathQuat a_Quat, b_Quat, c_Quat, d_Quat; + VmathVector4 tmpV4; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5, tmpV3_6, tmpV3_7; + VmathQuat tmpQ_0; + VmathVector3 tmpV3_8, tmpV3_9, tmpV3_10, tmpV3_11, tmpV3_12, tmpV3_13, tmpV3_14, tmpV3_15, tmpV3_16, tmpV3_17, tmpV3_18, tmpV3_19, tmpV3_20, tmpV3_21; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &a_Vector3, pad ); + vmathV4GetXYZ( &a_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &b_Vector3, pad ); + vmathV4GetXYZ( &b_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &c_Vector3, pad ); + vmathV4GetXYZ( &c_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &d_Vector3, pad ); + vmathV4GetXYZ( &d_Vector3, &tmpV4 ); + vmathV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathV3MakeFromP3( &tmpV3_0, &a_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_0, pad ); + vmathV4GetXYZ( &tmpV3_1, &tmpV4 ); + vmathP3MakeFromV3( &a_Point3, &tmpV3_1 ); + vmathV3MakeFromP3( &tmpV3_2, &b_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_2, pad ); + vmathV4GetXYZ( &tmpV3_3, &tmpV4 ); + vmathP3MakeFromV3( &b_Point3, &tmpV3_3 ); + vmathV3MakeFromP3( &tmpV3_4, &c_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_4, pad ); + vmathV4GetXYZ( &tmpV3_5, &tmpV4 ); + vmathP3MakeFromV3( &c_Point3, &tmpV3_5 ); + vmathV3MakeFromP3( &tmpV3_6, &d_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_6, pad ); + vmathV4GetXYZ( &tmpV3_7, &tmpV4 ); + vmathP3MakeFromV3( &d_Point3, &tmpV3_7 ); + vmathP3Prints( &a_Point3, "set Point3 with floats" ); + vmathP3Prints( &b_Point3, "set Point3 with floats" ); + vmathP3Prints( &c_Point3, "set Point3 with floats" ); + vmathP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathQPrints( &a_Quat, "set Quat with floats" ); + vmathQPrints( &b_Quat, "set Quat with floats" ); + vmathQPrints( &c_Quat, "set Quat with floats" ); + vmathQPrints( &d_Quat, "set Quat with floats" ); + vmathM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathQNormalize( &tmpQ_0, &a_Quat ); + vmathM3MakeFromQ( &a_Matrix3, &tmpQ_0 ); + vmathM3Prints( &a_Matrix3, "construct Matrix3 with Quat" ); + vmathQMakeFromM3( &a_Quat, &a_Matrix3 ); + vmathQPrints( &a_Quat, "construct Quat with Matrix3" ); + vmathM3Copy( &a_Matrix3, &b_Matrix3 ); + vmathM3Prints( &a_Matrix3, "assign to Matrix3 from Matrix3" ); + vmathM3MakeFromScalar( &a_Matrix3, randfloat() ); + vmathM3Prints( &a_Matrix3, "set Matrix3 with float" ); + vmathM3MakeFromScalar( &a_Matrix3, randfloat() ); + vmathM3Prints( &a_Matrix3, "set Matrix3 with float" ); + vmathM3MakeFromScalar( &a_Matrix3, 0.0f ); + vmathM3Prints( &a_Matrix3, "set elements to zero" ); + vmathM3MakeIdentity( &a_Matrix3 ); + vmathM3Prints( &a_Matrix3, "set to identity" ); + vmathM3MakeRotationX( &a_Matrix3, randfloat() ); + vmathM3Prints( &a_Matrix3, "set to rotationX" ); + vmathM3MakeRotationY( &a_Matrix3, randfloat() ); + vmathM3Prints( &a_Matrix3, "set to rotationY" ); + vmathM3MakeRotationZ( &a_Matrix3, randfloat() ); + vmathM3Prints( &a_Matrix3, "set to rotationZ" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &tmpV3_8, rndflt3, rndflt2, rndflt1 ); + vmathM3MakeRotationZYX( &a_Matrix3, &tmpV3_8 ); + vmathM3Prints( &a_Matrix3, "set to rotation from Z,Y,X angles" ); + vmathV3Normalize( &tmpV3_9, &a_Vector3 ); + vmathM3MakeRotationAxis( &a_Matrix3, randfloat(), &tmpV3_9 ); + vmathM3Prints( &a_Matrix3, "set to rotation from axis angle" ); + vmathM3SetCol0( &a_Matrix3, &a_Vector3 ); + vmathM3Prints( &a_Matrix3, "Matrix3 set col 0" ); + vmathM3SetCol1( &a_Matrix3, &a_Vector3 ); + vmathM3Prints( &a_Matrix3, "Matrix3 set col 1" ); + vmathM3SetCol2( &a_Matrix3, &a_Vector3 ); + vmathM3Prints( &a_Matrix3, "Matrix3 set col 2" ); + vmathM3GetCol0( &tmpV3_10, &a_Matrix3 ); + vmathV3Prints( &tmpV3_10, "Matrix3 get col 0" ); + vmathM3GetCol1( &tmpV3_11, &a_Matrix3 ); + vmathV3Prints( &tmpV3_11, "Matrix3 get col 1" ); + vmathM3GetCol2( &tmpV3_12, &a_Matrix3 ); + vmathV3Prints( &tmpV3_12, "Matrix3 get col 2" ); + vmathM3SetCol( &a_Matrix3, 0, &b_Vector3 ); + vmathM3Prints( &a_Matrix3, "Matrix3 set col 0" ); + vmathM3SetCol( &a_Matrix3, 1, &b_Vector3 ); + vmathM3Prints( &a_Matrix3, "Matrix3 set col 1" ); + vmathM3SetCol( &a_Matrix3, 2, &b_Vector3 ); + vmathM3Prints( &a_Matrix3, "Matrix3 set col 2" ); + vmathM3GetCol( &tmpV3_13, &a_Matrix3, 0 ); + vmathV3Prints( &tmpV3_13, "Matrix3 get col 0" ); + vmathM3GetCol( &tmpV3_14, &a_Matrix3, 1 ); + vmathV3Prints( &tmpV3_14, "Matrix3 get col 1" ); + vmathM3GetCol( &tmpV3_15, &a_Matrix3, 2 ); + vmathV3Prints( &tmpV3_15, "Matrix3 get col 2" ); + vmathM3SetRow( &a_Matrix3, 0, &a_Vector3 ); + vmathM3Prints( &a_Matrix3, "Matrix3 set row 0" ); + vmathM3SetRow( &a_Matrix3, 1, &a_Vector3 ); + vmathM3Prints( &a_Matrix3, "Matrix3 set row 1" ); + vmathM3SetRow( &a_Matrix3, 2, &a_Vector3 ); + vmathM3Prints( &a_Matrix3, "Matrix3 set row 2" ); + vmathM3GetRow( &tmpV3_16, &a_Matrix3, 0 ); + vmathV3Prints( &tmpV3_16, "Matrix3 get row 0" ); + vmathM3GetRow( &tmpV3_17, &a_Matrix3, 1 ); + vmathV3Prints( &tmpV3_17, "Matrix3 get row 1" ); + vmathM3GetRow( &tmpV3_18, &a_Matrix3, 2 ); + vmathV3Prints( &tmpV3_18, "Matrix3 get row 2" ); + vmathM3SetCol( &a_Matrix3, 0, &a_Vector3 ); + vmathM3Prints( &a_Matrix3, "set " ); + vmathM3SetCol( &a_Matrix3, 1, &a_Vector3 ); + vmathM3Prints( &a_Matrix3, "set " ); + vmathM3SetCol( &a_Matrix3, 2, &a_Vector3 ); + vmathM3Prints( &a_Matrix3, "set " ); + vmathM3GetCol( &tmpV3_19, &a_Matrix3, 0 ); + vmathV3Prints( &tmpV3_19, "get " ); + vmathM3GetCol( &tmpV3_20, &a_Matrix3, 1 ); + vmathV3Prints( &tmpV3_20, "get " ); + vmathM3GetCol( &tmpV3_21, &a_Matrix3, 2 ); + vmathV3Prints( &tmpV3_21, "get " ); + vmathM3SetElem( &a_Matrix3, 0, 0, randfloat() ); + vmathM3SetElem( &a_Matrix3, 0, 1, randfloat() ); + vmathM3SetElem( &a_Matrix3, 0, 2, randfloat() ); + vmathM3SetElem( &a_Matrix3, 1, 0, randfloat() ); + vmathM3SetElem( &a_Matrix3, 1, 1, randfloat() ); + vmathM3SetElem( &a_Matrix3, 1, 2, randfloat() ); + vmathM3SetElem( &a_Matrix3, 2, 0, randfloat() ); + vmathM3SetElem( &a_Matrix3, 2, 1, randfloat() ); + vmathM3SetElem( &a_Matrix3, 2, 2, randfloat() ); + vmathM3Prints( &a_Matrix3, "Matrix3 set elements" ); + printf("%f\n", getfloat(vmathM3GetElem( &a_Matrix3, 0, 0 )) ); + printf("%f\n", getfloat(vmathM3GetElem( &a_Matrix3, 0, 1 )) ); + printf("%f\n", getfloat(vmathM3GetElem( &a_Matrix3, 0, 2 )) ); + printf("%f\n", getfloat(vmathM3GetElem( &a_Matrix3, 1, 0 )) ); + printf("%f\n", getfloat(vmathM3GetElem( &a_Matrix3, 1, 1 )) ); + printf("%f\n", getfloat(vmathM3GetElem( &a_Matrix3, 1, 2 )) ); + printf("%f\n", getfloat(vmathM3GetElem( &a_Matrix3, 2, 0 )) ); + printf("%f\n", getfloat(vmathM3GetElem( &a_Matrix3, 2, 1 )) ); + printf("%f\n", getfloat(vmathM3GetElem( &a_Matrix3, 2, 2 )) ); +} + +void +Matrix4_methods_test() +{ + VmathMatrix3 a_Matrix3, b_Matrix3; + VmathMatrix4 a_Matrix4, b_Matrix4; + VmathTransform3 a_Transform3, b_Transform3; + VmathVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathQuat a_Quat, b_Quat, c_Quat, d_Quat; + VmathVector4 tmpV4; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5, tmpV3_6, tmpV3_7, tmpV3_8, tmpV3_9; + VmathVector4 tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3, tmpV4_4, tmpV4_5, tmpV4_6, tmpV4_7, tmpV4_8, tmpV4_9, tmpV4_10, tmpV4_11, tmpV4_12, tmpV4_13, tmpV4_14, tmpV4_15; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &a_Vector3, pad ); + vmathV4GetXYZ( &a_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &b_Vector3, pad ); + vmathV4GetXYZ( &b_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &c_Vector3, pad ); + vmathV4GetXYZ( &c_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &d_Vector3, pad ); + vmathV4GetXYZ( &d_Vector3, &tmpV4 ); + vmathV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathV3MakeFromP3( &tmpV3_0, &a_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_0, pad ); + vmathV4GetXYZ( &tmpV3_1, &tmpV4 ); + vmathP3MakeFromV3( &a_Point3, &tmpV3_1 ); + vmathV3MakeFromP3( &tmpV3_2, &b_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_2, pad ); + vmathV4GetXYZ( &tmpV3_3, &tmpV4 ); + vmathP3MakeFromV3( &b_Point3, &tmpV3_3 ); + vmathV3MakeFromP3( &tmpV3_4, &c_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_4, pad ); + vmathV4GetXYZ( &tmpV3_5, &tmpV4 ); + vmathP3MakeFromV3( &c_Point3, &tmpV3_5 ); + vmathV3MakeFromP3( &tmpV3_6, &d_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_6, pad ); + vmathV4GetXYZ( &tmpV3_7, &tmpV4 ); + vmathP3MakeFromV3( &d_Point3, &tmpV3_7 ); + vmathP3Prints( &a_Point3, "set Point3 with floats" ); + vmathP3Prints( &b_Point3, "set Point3 with floats" ); + vmathP3Prints( &c_Point3, "set Point3 with floats" ); + vmathP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathQPrints( &a_Quat, "set Quat with floats" ); + vmathQPrints( &b_Quat, "set Quat with floats" ); + vmathQPrints( &c_Quat, "set Quat with floats" ); + vmathQPrints( &d_Quat, "set Quat with floats" ); + vmathM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathM4MakeFromT3( &a_Matrix4, &a_Transform3 ); + vmathM4Prints( &a_Matrix4, "construct Matrix4 with Transform3" ); + vmathM4MakeFromM3V3( &a_Matrix4, &a_Matrix3, &a_Vector3 ); + vmathM4Prints( &a_Matrix4, "construct Matrix4 with Matrix3 and Vector3" ); + vmathM4MakeFromQV3( &a_Matrix4, &a_Quat, &a_Vector3 ); + vmathM4Prints( &a_Matrix4, "construct Matrix4 with Quat and Vector3" ); + vmathM4Copy( &a_Matrix4, &b_Matrix4 ); + vmathM4Prints( &a_Matrix4, "assign to Matrix4 from Matrix4" ); + vmathM4MakeFromScalar( &a_Matrix4, randfloat() ); + vmathM4Prints( &a_Matrix4, "set Matrix4 with float" ); + vmathM4MakeFromScalar( &a_Matrix4, randfloat() ); + vmathM4Prints( &a_Matrix4, "set Matrix4 with float" ); + vmathM4MakeFromScalar( &a_Matrix4, 0.0f ); + vmathM4Prints( &a_Matrix4, "set elements to zero" ); + vmathM4MakeIdentity( &a_Matrix4 ); + vmathM4Prints( &a_Matrix4, "set to identity" ); + vmathM4MakeRotationX( &a_Matrix4, randfloat() ); + vmathM4Prints( &a_Matrix4, "set to rotationX" ); + vmathM4MakeRotationY( &a_Matrix4, randfloat() ); + vmathM4Prints( &a_Matrix4, "set to rotationY" ); + vmathM4MakeRotationZ( &a_Matrix4, randfloat() ); + vmathM4Prints( &a_Matrix4, "set to rotationZ" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &tmpV3_8, rndflt3, rndflt2, rndflt1 ); + vmathM4MakeRotationZYX( &a_Matrix4, &tmpV3_8 ); + vmathM4Prints( &a_Matrix4, "set to rotation from Z,Y,X angles" ); + vmathV3Normalize( &tmpV3_9, &a_Vector3 ); + vmathM4MakeRotationAxis( &a_Matrix4, randfloat(), &tmpV3_9 ); + vmathM4Prints( &a_Matrix4, "set to rotation from axis angle" ); + vmathM4MakeTranslation( &a_Matrix4, &a_Vector3 ); + vmathM4Prints( &a_Matrix4, "set to translation" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathM4MakePerspective( &a_Matrix4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathM4Prints( &a_Matrix4, "set to perspective matrix" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathM4MakeFrustum( &a_Matrix4, rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6 ); + vmathM4Prints( &a_Matrix4, "set to frustum matrix" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathM4MakeOrthographic( &a_Matrix4, rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6 ); + vmathM4Prints( &a_Matrix4, "set to orthographic matrix" ); + vmathM4MakeLookAt( &a_Matrix4, &a_Point3, &b_Point3, &a_Vector3 ); + vmathM4Prints( &a_Matrix4, "set to look-at matrix" ); + vmathM4SetCol0( &a_Matrix4, &a_Vector4 ); + vmathM4Prints( &a_Matrix4, "Matrix4 set col 0" ); + vmathM4SetCol1( &a_Matrix4, &a_Vector4 ); + vmathM4Prints( &a_Matrix4, "Matrix4 set col 1" ); + vmathM4SetCol2( &a_Matrix4, &a_Vector4 ); + vmathM4Prints( &a_Matrix4, "Matrix4 set col 2" ); + vmathM4SetCol3( &a_Matrix4, &a_Vector4 ); + vmathM4Prints( &a_Matrix4, "Matrix4 set col 3" ); + vmathM4GetCol0( &tmpV4_0, &a_Matrix4 ); + vmathV4Prints( &tmpV4_0, "Matrix4 get col 0" ); + vmathM4GetCol1( &tmpV4_1, &a_Matrix4 ); + vmathV4Prints( &tmpV4_1, "Matrix4 get col 1" ); + vmathM4GetCol2( &tmpV4_2, &a_Matrix4 ); + vmathV4Prints( &tmpV4_2, "Matrix4 get col 2" ); + vmathM4GetCol3( &tmpV4_3, &a_Matrix4 ); + vmathV4Prints( &tmpV4_3, "Matrix4 get col 3" ); + vmathM4SetCol( &a_Matrix4, 0, &b_Vector4 ); + vmathM4Prints( &a_Matrix4, "Matrix4 set col 0" ); + vmathM4SetCol( &a_Matrix4, 1, &b_Vector4 ); + vmathM4Prints( &a_Matrix4, "Matrix4 set col 1" ); + vmathM4SetCol( &a_Matrix4, 2, &b_Vector4 ); + vmathM4Prints( &a_Matrix4, "Matrix4 set col 2" ); + vmathM4SetCol( &a_Matrix4, 3, &b_Vector4 ); + vmathM4Prints( &a_Matrix4, "Matrix4 set col 3" ); + vmathM4GetCol( &tmpV4_4, &a_Matrix4, 0 ); + vmathV4Prints( &tmpV4_4, "Matrix4 get col 0" ); + vmathM4GetCol( &tmpV4_5, &a_Matrix4, 1 ); + vmathV4Prints( &tmpV4_5, "Matrix4 get col 1" ); + vmathM4GetCol( &tmpV4_6, &a_Matrix4, 2 ); + vmathV4Prints( &tmpV4_6, "Matrix4 get col 2" ); + vmathM4GetCol( &tmpV4_7, &a_Matrix4, 3 ); + vmathV4Prints( &tmpV4_7, "Matrix4 get col 3" ); + vmathM4SetRow( &a_Matrix4, 0, &a_Vector4 ); + vmathM4Prints( &a_Matrix4, "Matrix4 set row 0" ); + vmathM4SetRow( &a_Matrix4, 1, &a_Vector4 ); + vmathM4Prints( &a_Matrix4, "Matrix4 set row 1" ); + vmathM4SetRow( &a_Matrix4, 2, &a_Vector4 ); + vmathM4Prints( &a_Matrix4, "Matrix4 set row 2" ); + vmathM4SetRow( &a_Matrix4, 3, &a_Vector4 ); + vmathM4Prints( &a_Matrix4, "Matrix4 set row 3" ); + vmathM4GetRow( &tmpV4_8, &a_Matrix4, 0 ); + vmathV4Prints( &tmpV4_8, "Matrix4 get row 0" ); + vmathM4GetRow( &tmpV4_9, &a_Matrix4, 1 ); + vmathV4Prints( &tmpV4_9, "Matrix4 get row 1" ); + vmathM4GetRow( &tmpV4_10, &a_Matrix4, 2 ); + vmathV4Prints( &tmpV4_10, "Matrix4 get row 2" ); + vmathM4GetRow( &tmpV4_11, &a_Matrix4, 3 ); + vmathV4Prints( &tmpV4_11, "Matrix4 get row 3" ); + vmathM4SetCol( &a_Matrix4, 0, &a_Vector4 ); + vmathM4Prints( &a_Matrix4, "set " ); + vmathM4SetCol( &a_Matrix4, 1, &a_Vector4 ); + vmathM4Prints( &a_Matrix4, "set " ); + vmathM4SetCol( &a_Matrix4, 2, &a_Vector4 ); + vmathM4Prints( &a_Matrix4, "set " ); + vmathM4SetCol( &a_Matrix4, 3, &a_Vector4 ); + vmathM4Prints( &a_Matrix4, "set " ); + vmathM4GetCol( &tmpV4_12, &a_Matrix4, 0 ); + vmathV4Prints( &tmpV4_12, "get " ); + vmathM4GetCol( &tmpV4_13, &a_Matrix4, 1 ); + vmathV4Prints( &tmpV4_13, "get " ); + vmathM4GetCol( &tmpV4_14, &a_Matrix4, 2 ); + vmathV4Prints( &tmpV4_14, "get " ); + vmathM4GetCol( &tmpV4_15, &a_Matrix4, 3 ); + vmathV4Prints( &tmpV4_15, "get " ); + vmathM4SetElem( &a_Matrix4, 0, 0, randfloat() ); + vmathM4SetElem( &a_Matrix4, 0, 1, randfloat() ); + vmathM4SetElem( &a_Matrix4, 0, 2, randfloat() ); + vmathM4SetElem( &a_Matrix4, 0, 3, randfloat() ); + vmathM4SetElem( &a_Matrix4, 1, 0, randfloat() ); + vmathM4SetElem( &a_Matrix4, 1, 1, randfloat() ); + vmathM4SetElem( &a_Matrix4, 1, 2, randfloat() ); + vmathM4SetElem( &a_Matrix4, 1, 3, randfloat() ); + vmathM4SetElem( &a_Matrix4, 2, 0, randfloat() ); + vmathM4SetElem( &a_Matrix4, 2, 1, randfloat() ); + vmathM4SetElem( &a_Matrix4, 2, 2, randfloat() ); + vmathM4SetElem( &a_Matrix4, 2, 3, randfloat() ); + vmathM4SetElem( &a_Matrix4, 3, 0, randfloat() ); + vmathM4SetElem( &a_Matrix4, 3, 1, randfloat() ); + vmathM4SetElem( &a_Matrix4, 3, 2, randfloat() ); + vmathM4SetElem( &a_Matrix4, 3, 3, randfloat() ); + vmathM4Prints( &a_Matrix4, "Matrix4 set elements" ); + printf("%f\n", getfloat(vmathM4GetElem( &a_Matrix4, 0, 0 )) ); + printf("%f\n", getfloat(vmathM4GetElem( &a_Matrix4, 0, 1 )) ); + printf("%f\n", getfloat(vmathM4GetElem( &a_Matrix4, 0, 2 )) ); + printf("%f\n", getfloat(vmathM4GetElem( &a_Matrix4, 0, 3 )) ); + printf("%f\n", getfloat(vmathM4GetElem( &a_Matrix4, 1, 0 )) ); + printf("%f\n", getfloat(vmathM4GetElem( &a_Matrix4, 1, 1 )) ); + printf("%f\n", getfloat(vmathM4GetElem( &a_Matrix4, 1, 2 )) ); + printf("%f\n", getfloat(vmathM4GetElem( &a_Matrix4, 1, 3 )) ); + printf("%f\n", getfloat(vmathM4GetElem( &a_Matrix4, 2, 0 )) ); + printf("%f\n", getfloat(vmathM4GetElem( &a_Matrix4, 2, 1 )) ); + printf("%f\n", getfloat(vmathM4GetElem( &a_Matrix4, 2, 2 )) ); + printf("%f\n", getfloat(vmathM4GetElem( &a_Matrix4, 2, 3 )) ); + printf("%f\n", getfloat(vmathM4GetElem( &a_Matrix4, 3, 0 )) ); + printf("%f\n", getfloat(vmathM4GetElem( &a_Matrix4, 3, 1 )) ); + printf("%f\n", getfloat(vmathM4GetElem( &a_Matrix4, 3, 2 )) ); + printf("%f\n", getfloat(vmathM4GetElem( &a_Matrix4, 3, 3 )) ); +} + +void +Transform3_methods_test() +{ + VmathMatrix3 a_Matrix3, b_Matrix3; + VmathMatrix4 a_Matrix4, b_Matrix4; + VmathTransform3 a_Transform3, b_Transform3; + VmathVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathQuat a_Quat, b_Quat, c_Quat, d_Quat; + VmathVector4 tmpV4; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5, tmpV3_6, tmpV3_7, tmpV3_8, tmpV3_9, tmpV3_10, tmpV3_11, tmpV3_12, tmpV3_13, tmpV3_14, tmpV3_15, tmpV3_16, tmpV3_17; + VmathVector4 tmpV4_0, tmpV4_1, tmpV4_2; + VmathVector3 tmpV3_18, tmpV3_19, tmpV3_20, tmpV3_21; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &a_Vector3, pad ); + vmathV4GetXYZ( &a_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &b_Vector3, pad ); + vmathV4GetXYZ( &b_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &c_Vector3, pad ); + vmathV4GetXYZ( &c_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &d_Vector3, pad ); + vmathV4GetXYZ( &d_Vector3, &tmpV4 ); + vmathV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathV3MakeFromP3( &tmpV3_0, &a_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_0, pad ); + vmathV4GetXYZ( &tmpV3_1, &tmpV4 ); + vmathP3MakeFromV3( &a_Point3, &tmpV3_1 ); + vmathV3MakeFromP3( &tmpV3_2, &b_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_2, pad ); + vmathV4GetXYZ( &tmpV3_3, &tmpV4 ); + vmathP3MakeFromV3( &b_Point3, &tmpV3_3 ); + vmathV3MakeFromP3( &tmpV3_4, &c_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_4, pad ); + vmathV4GetXYZ( &tmpV3_5, &tmpV4 ); + vmathP3MakeFromV3( &c_Point3, &tmpV3_5 ); + vmathV3MakeFromP3( &tmpV3_6, &d_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_6, pad ); + vmathV4GetXYZ( &tmpV3_7, &tmpV4 ); + vmathP3MakeFromV3( &d_Point3, &tmpV3_7 ); + vmathP3Prints( &a_Point3, "set Point3 with floats" ); + vmathP3Prints( &b_Point3, "set Point3 with floats" ); + vmathP3Prints( &c_Point3, "set Point3 with floats" ); + vmathP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathQPrints( &a_Quat, "set Quat with floats" ); + vmathQPrints( &b_Quat, "set Quat with floats" ); + vmathQPrints( &c_Quat, "set Quat with floats" ); + vmathQPrints( &d_Quat, "set Quat with floats" ); + vmathM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathT3MakeFromM3V3( &a_Transform3, &a_Matrix3, &a_Vector3 ); + vmathT3Prints( &a_Transform3, "construct Transform3 with Matrix3 and Vector3" ); + vmathT3MakeFromQV3( &a_Transform3, &a_Quat, &a_Vector3 ); + vmathT3Prints( &a_Transform3, "construct Transform3 with Quat and Vector3" ); + vmathT3Copy( &a_Transform3, &b_Transform3 ); + vmathT3Prints( &a_Transform3, "assign to Transform3 from Transform3" ); + vmathT3MakeFromScalar( &a_Transform3, randfloat() ); + vmathT3Prints( &a_Transform3, "set Transform3 with float" ); + vmathT3MakeFromScalar( &a_Transform3, randfloat() ); + vmathT3Prints( &a_Transform3, "set Transform3 with float" ); + vmathT3MakeFromScalar( &a_Transform3, 0.0f ); + vmathT3Prints( &a_Transform3, "set elements to zero" ); + vmathT3MakeIdentity( &a_Transform3 ); + vmathT3Prints( &a_Transform3, "set to identity" ); + vmathT3MakeRotationX( &a_Transform3, randfloat() ); + vmathT3Prints( &a_Transform3, "set to rotationX" ); + vmathT3MakeRotationY( &a_Transform3, randfloat() ); + vmathT3Prints( &a_Transform3, "set to rotationY" ); + vmathT3MakeRotationZ( &a_Transform3, randfloat() ); + vmathT3Prints( &a_Transform3, "set to rotationZ" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &tmpV3_8, rndflt3, rndflt2, rndflt1 ); + vmathT3MakeRotationZYX( &a_Transform3, &tmpV3_8 ); + vmathT3Prints( &a_Transform3, "set to rotation from Z,Y,X angles" ); + vmathV3Normalize( &tmpV3_9, &a_Vector3 ); + vmathT3MakeRotationAxis( &a_Transform3, randfloat(), &tmpV3_9 ); + vmathT3Prints( &a_Transform3, "set to rotation from axis angle" ); + vmathT3MakeTranslation( &a_Transform3, &a_Vector3 ); + vmathT3Prints( &a_Transform3, "set to translation" ); + vmathT3SetCol0( &a_Transform3, &a_Vector3 ); + vmathT3Prints( &a_Transform3, "Transform3 set col 0" ); + vmathT3SetCol1( &a_Transform3, &a_Vector3 ); + vmathT3Prints( &a_Transform3, "Transform3 set col 1" ); + vmathT3SetCol2( &a_Transform3, &a_Vector3 ); + vmathT3Prints( &a_Transform3, "Transform3 set col 2" ); + vmathT3SetCol3( &a_Transform3, &a_Vector3 ); + vmathT3Prints( &a_Transform3, "Transform3 set col 3" ); + vmathT3GetCol0( &tmpV3_10, &a_Transform3 ); + vmathV3Prints( &tmpV3_10, "Transform3 get col 0" ); + vmathT3GetCol1( &tmpV3_11, &a_Transform3 ); + vmathV3Prints( &tmpV3_11, "Transform3 get col 1" ); + vmathT3GetCol2( &tmpV3_12, &a_Transform3 ); + vmathV3Prints( &tmpV3_12, "Transform3 get col 2" ); + vmathT3GetCol3( &tmpV3_13, &a_Transform3 ); + vmathV3Prints( &tmpV3_13, "Transform3 get col 3" ); + vmathT3SetCol( &a_Transform3, 0, &b_Vector3 ); + vmathT3Prints( &a_Transform3, "Transform3 set col 0" ); + vmathT3SetCol( &a_Transform3, 1, &b_Vector3 ); + vmathT3Prints( &a_Transform3, "Transform3 set col 1" ); + vmathT3SetCol( &a_Transform3, 2, &b_Vector3 ); + vmathT3Prints( &a_Transform3, "Transform3 set col 2" ); + vmathT3SetCol( &a_Transform3, 3, &b_Vector3 ); + vmathT3Prints( &a_Transform3, "Transform3 set col 3" ); + vmathT3GetCol( &tmpV3_14, &a_Transform3, 0 ); + vmathV3Prints( &tmpV3_14, "Transform3 get col 0" ); + vmathT3GetCol( &tmpV3_15, &a_Transform3, 1 ); + vmathV3Prints( &tmpV3_15, "Transform3 get col 1" ); + vmathT3GetCol( &tmpV3_16, &a_Transform3, 2 ); + vmathV3Prints( &tmpV3_16, "Transform3 get col 2" ); + vmathT3GetCol( &tmpV3_17, &a_Transform3, 3 ); + vmathV3Prints( &tmpV3_17, "Transform3 get col 3" ); + vmathT3SetRow( &a_Transform3, 0, &a_Vector4 ); + vmathT3Prints( &a_Transform3, "Transform3 set row 0" ); + vmathT3SetRow( &a_Transform3, 1, &a_Vector4 ); + vmathT3Prints( &a_Transform3, "Transform3 set row 1" ); + vmathT3SetRow( &a_Transform3, 2, &a_Vector4 ); + vmathT3Prints( &a_Transform3, "Transform3 set row 2" ); + vmathT3GetRow( &tmpV4_0, &a_Transform3, 0 ); + vmathV4Prints( &tmpV4_0, "Transform3 get row 0" ); + vmathT3GetRow( &tmpV4_1, &a_Transform3, 1 ); + vmathV4Prints( &tmpV4_1, "Transform3 get row 1" ); + vmathT3GetRow( &tmpV4_2, &a_Transform3, 2 ); + vmathV4Prints( &tmpV4_2, "Transform3 get row 2" ); + vmathT3SetCol( &a_Transform3, 0, &a_Vector3 ); + vmathT3Prints( &a_Transform3, "set " ); + vmathT3SetCol( &a_Transform3, 1, &a_Vector3 ); + vmathT3Prints( &a_Transform3, "set " ); + vmathT3SetCol( &a_Transform3, 2, &a_Vector3 ); + vmathT3Prints( &a_Transform3, "set " ); + vmathT3SetCol( &a_Transform3, 3, &a_Vector3 ); + vmathT3Prints( &a_Transform3, "set " ); + vmathT3GetCol( &tmpV3_18, &a_Transform3, 0 ); + vmathV3Prints( &tmpV3_18, "get " ); + vmathT3GetCol( &tmpV3_19, &a_Transform3, 1 ); + vmathV3Prints( &tmpV3_19, "get " ); + vmathT3GetCol( &tmpV3_20, &a_Transform3, 2 ); + vmathV3Prints( &tmpV3_20, "get " ); + vmathT3GetCol( &tmpV3_21, &a_Transform3, 3 ); + vmathV3Prints( &tmpV3_21, "get " ); + vmathT3SetElem( &a_Transform3, 0, 0, randfloat() ); + vmathT3SetElem( &a_Transform3, 0, 1, randfloat() ); + vmathT3SetElem( &a_Transform3, 0, 2, randfloat() ); + vmathT3SetElem( &a_Transform3, 1, 0, randfloat() ); + vmathT3SetElem( &a_Transform3, 1, 1, randfloat() ); + vmathT3SetElem( &a_Transform3, 1, 2, randfloat() ); + vmathT3SetElem( &a_Transform3, 2, 0, randfloat() ); + vmathT3SetElem( &a_Transform3, 2, 1, randfloat() ); + vmathT3SetElem( &a_Transform3, 2, 2, randfloat() ); + vmathT3SetElem( &a_Transform3, 3, 0, randfloat() ); + vmathT3SetElem( &a_Transform3, 3, 1, randfloat() ); + vmathT3SetElem( &a_Transform3, 3, 2, randfloat() ); + vmathT3Prints( &a_Transform3, "Transform3 set elements" ); + printf("%f\n", getfloat(vmathT3GetElem( &a_Transform3, 0, 0 )) ); + printf("%f\n", getfloat(vmathT3GetElem( &a_Transform3, 0, 1 )) ); + printf("%f\n", getfloat(vmathT3GetElem( &a_Transform3, 0, 2 )) ); + printf("%f\n", getfloat(vmathT3GetElem( &a_Transform3, 1, 0 )) ); + printf("%f\n", getfloat(vmathT3GetElem( &a_Transform3, 1, 1 )) ); + printf("%f\n", getfloat(vmathT3GetElem( &a_Transform3, 1, 2 )) ); + printf("%f\n", getfloat(vmathT3GetElem( &a_Transform3, 2, 0 )) ); + printf("%f\n", getfloat(vmathT3GetElem( &a_Transform3, 2, 1 )) ); + printf("%f\n", getfloat(vmathT3GetElem( &a_Transform3, 2, 2 )) ); + printf("%f\n", getfloat(vmathT3GetElem( &a_Transform3, 3, 0 )) ); + printf("%f\n", getfloat(vmathT3GetElem( &a_Transform3, 3, 1 )) ); + printf("%f\n", getfloat(vmathT3GetElem( &a_Transform3, 3, 2 )) ); +} + +int main() +{ + int i; + printf("\n __begin__ \n"); + for ( i = 0; i < 2; i++ ) { + Matrix3_methods_test(); + Matrix4_methods_test(); + Transform3_methods_test(); + } + printf("\n __end__ \n"); + return 0; +} diff --git a/Extras/vectormathlibrary/tests/test2_aos_cpp.cpp b/Extras/vectormathlibrary/tests/test2_aos_cpp.cpp new file mode 100644 index 0000000..6b8884a --- /dev/null +++ b/Extras/vectormathlibrary/tests/test2_aos_cpp.cpp @@ -0,0 +1,784 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +#define _VECTORMATH_AOS_TEST + +#include "vectormath_aos.h" +#include "test.h" + +int iteration = 0; + +using namespace Vectormath; +using namespace Vectormath::Aos; + +void +Matrix3_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + Vector4 tmpV4; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( a_Vector3, pad ); + a_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( b_Vector3, pad ); + b_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( c_Vector3, pad ); + c_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( d_Vector3, pad ); + d_Vector3 = tmpV4.getXYZ( ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( Vector3( a_Point3 ), pad ); + a_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( b_Point3 ), pad ); + b_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( c_Point3 ), pad ); + c_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( d_Point3 ), pad ); + d_Point3 = Point3( tmpV4.getXYZ( ) ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + a_Matrix3 = Matrix3( normalize( a_Quat ) ); + print( a_Matrix3, "construct Matrix3 with Quat" ); + a_Quat = Quat( a_Matrix3 ); + print( a_Quat, "construct Quat with Matrix3" ); + a_Matrix3 = b_Matrix3; + print( a_Matrix3, "assign to Matrix3 from Matrix3" ); + a_Matrix3 = Matrix3( randfloat() ); + print( a_Matrix3, "set Matrix3 with float" ); + a_Matrix3 = Matrix3( scalar_float(randfloat()) ); + print( a_Matrix3, "set Matrix3 with float" ); + a_Matrix3 = Matrix3( 0.0f ); + print( a_Matrix3, "set elements to zero" ); + a_Matrix3 = Matrix3::identity( ); + print( a_Matrix3, "set to identity" ); + a_Matrix3 = Matrix3::rotationX( randfloat() ); + print( a_Matrix3, "set to rotationX" ); + a_Matrix3 = Matrix3::rotationY( randfloat() ); + print( a_Matrix3, "set to rotationY" ); + a_Matrix3 = Matrix3::rotationZ( randfloat() ); + print( a_Matrix3, "set to rotationZ" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Matrix3 = Matrix3::rotationZYX( Vector3( rndflt3, rndflt2, rndflt1 ) ); + print( a_Matrix3, "set to rotation from Z,Y,X angles" ); + a_Matrix3 = Matrix3::rotation( randfloat(), normalize( a_Vector3 ) ); + print( a_Matrix3, "set to rotation from axis angle" ); + a_Matrix3.setCol0( a_Vector3 ); + print( a_Matrix3, "Matrix3 set col 0" ); + a_Matrix3.setCol1( a_Vector3 ); + print( a_Matrix3, "Matrix3 set col 1" ); + a_Matrix3.setCol2( a_Vector3 ); + print( a_Matrix3, "Matrix3 set col 2" ); + print( a_Matrix3.getCol0( ), "Matrix3 get col 0" ); + print( a_Matrix3.getCol1( ), "Matrix3 get col 1" ); + print( a_Matrix3.getCol2( ), "Matrix3 get col 2" ); + a_Matrix3.setCol( 0, b_Vector3 ); + print( a_Matrix3, "Matrix3 set col 0" ); + a_Matrix3.setCol( 1, b_Vector3 ); + print( a_Matrix3, "Matrix3 set col 1" ); + a_Matrix3.setCol( 2, b_Vector3 ); + print( a_Matrix3, "Matrix3 set col 2" ); + print( a_Matrix3.getCol( 0 ), "Matrix3 get col 0" ); + print( a_Matrix3.getCol( 1 ), "Matrix3 get col 1" ); + print( a_Matrix3.getCol( 2 ), "Matrix3 get col 2" ); + a_Matrix3.setRow( 0, a_Vector3 ); + print( a_Matrix3, "Matrix3 set row 0" ); + a_Matrix3.setRow( 1, a_Vector3 ); + print( a_Matrix3, "Matrix3 set row 1" ); + a_Matrix3.setRow( 2, a_Vector3 ); + print( a_Matrix3, "Matrix3 set row 2" ); + print( a_Matrix3.getRow( 0 ), "Matrix3 get row 0" ); + print( a_Matrix3.getRow( 1 ), "Matrix3 get row 1" ); + print( a_Matrix3.getRow( 2 ), "Matrix3 get row 2" ); + a_Matrix3[0] = a_Vector3; + print( a_Matrix3, "set Matrix3[0]" ); + a_Matrix3[1] = a_Vector3; + print( a_Matrix3, "set Matrix3[1]" ); + a_Matrix3[2] = a_Vector3; + print( a_Matrix3, "set Matrix3[2]" ); + a_Matrix3[0] = a_Vector3; + print( a_Matrix3[0], "get Matrix3[0]" ); + a_Matrix3[1] = a_Vector3; + print( a_Matrix3[1], "get Matrix3[1]" ); + a_Matrix3[2] = a_Vector3; + print( a_Matrix3[2], "get Matrix3[2]" ); + a_Matrix3.setElem( 0, 0, randfloat() ); + a_Matrix3.setElem( 0, 1, randfloat() ); + a_Matrix3.setElem( 0, 2, randfloat() ); + a_Matrix3.setElem( 1, 0, randfloat() ); + a_Matrix3.setElem( 1, 1, randfloat() ); + a_Matrix3.setElem( 1, 2, randfloat() ); + a_Matrix3.setElem( 2, 0, randfloat() ); + a_Matrix3.setElem( 2, 1, randfloat() ); + a_Matrix3.setElem( 2, 2, randfloat() ); + print( a_Matrix3, "Matrix3 set elements" ); + printf("%f\n", getfloat(a_Matrix3.getElem( 0, 0 )) ); + printf("%f\n", getfloat(a_Matrix3.getElem( 0, 1 )) ); + printf("%f\n", getfloat(a_Matrix3.getElem( 0, 2 )) ); + printf("%f\n", getfloat(a_Matrix3.getElem( 1, 0 )) ); + printf("%f\n", getfloat(a_Matrix3.getElem( 1, 1 )) ); + printf("%f\n", getfloat(a_Matrix3.getElem( 1, 2 )) ); + printf("%f\n", getfloat(a_Matrix3.getElem( 2, 0 )) ); + printf("%f\n", getfloat(a_Matrix3.getElem( 2, 1 )) ); + printf("%f\n", getfloat(a_Matrix3.getElem( 2, 2 )) ); +} + +void +Matrix4_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + Vector4 tmpV4; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( a_Vector3, pad ); + a_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( b_Vector3, pad ); + b_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( c_Vector3, pad ); + c_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( d_Vector3, pad ); + d_Vector3 = tmpV4.getXYZ( ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( Vector3( a_Point3 ), pad ); + a_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( b_Point3 ), pad ); + b_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( c_Point3 ), pad ); + c_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( d_Point3 ), pad ); + d_Point3 = Point3( tmpV4.getXYZ( ) ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + a_Matrix4 = Matrix4( a_Transform3 ); + print( a_Matrix4, "construct Matrix4 with Transform3" ); + a_Matrix4 = Matrix4( a_Matrix3, a_Vector3 ); + print( a_Matrix4, "construct Matrix4 with Matrix3 and Vector3" ); + a_Matrix4 = Matrix4( a_Quat, a_Vector3 ); + print( a_Matrix4, "construct Matrix4 with Quat and Vector3" ); + a_Matrix4 = b_Matrix4; + print( a_Matrix4, "assign to Matrix4 from Matrix4" ); + a_Matrix4 = Matrix4( randfloat() ); + print( a_Matrix4, "set Matrix4 with float" ); + a_Matrix4 = Matrix4( scalar_float(randfloat()) ); + print( a_Matrix4, "set Matrix4 with float" ); + a_Matrix4 = Matrix4( 0.0f ); + print( a_Matrix4, "set elements to zero" ); + a_Matrix4 = Matrix4::identity( ); + print( a_Matrix4, "set to identity" ); + a_Matrix4 = Matrix4::rotationX( randfloat() ); + print( a_Matrix4, "set to rotationX" ); + a_Matrix4 = Matrix4::rotationY( randfloat() ); + print( a_Matrix4, "set to rotationY" ); + a_Matrix4 = Matrix4::rotationZ( randfloat() ); + print( a_Matrix4, "set to rotationZ" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Matrix4 = Matrix4::rotationZYX( Vector3( rndflt3, rndflt2, rndflt1 ) ); + print( a_Matrix4, "set to rotation from Z,Y,X angles" ); + a_Matrix4 = Matrix4::rotation( randfloat(), normalize( a_Vector3 ) ); + print( a_Matrix4, "set to rotation from axis angle" ); + a_Matrix4 = Matrix4::translation( a_Vector3 ); + print( a_Matrix4, "set to translation" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Matrix4 = Matrix4::perspective( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Matrix4, "set to perspective matrix" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + a_Matrix4 = Matrix4::frustum( rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6 ); + print( a_Matrix4, "set to frustum matrix" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + a_Matrix4 = Matrix4::orthographic( rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6 ); + print( a_Matrix4, "set to orthographic matrix" ); + a_Matrix4 = Matrix4::lookAt( a_Point3, b_Point3, a_Vector3 ); + print( a_Matrix4, "set to look-at matrix" ); + a_Matrix4.setCol0( a_Vector4 ); + print( a_Matrix4, "Matrix4 set col 0" ); + a_Matrix4.setCol1( a_Vector4 ); + print( a_Matrix4, "Matrix4 set col 1" ); + a_Matrix4.setCol2( a_Vector4 ); + print( a_Matrix4, "Matrix4 set col 2" ); + a_Matrix4.setCol3( a_Vector4 ); + print( a_Matrix4, "Matrix4 set col 3" ); + print( a_Matrix4.getCol0( ), "Matrix4 get col 0" ); + print( a_Matrix4.getCol1( ), "Matrix4 get col 1" ); + print( a_Matrix4.getCol2( ), "Matrix4 get col 2" ); + print( a_Matrix4.getCol3( ), "Matrix4 get col 3" ); + a_Matrix4.setCol( 0, b_Vector4 ); + print( a_Matrix4, "Matrix4 set col 0" ); + a_Matrix4.setCol( 1, b_Vector4 ); + print( a_Matrix4, "Matrix4 set col 1" ); + a_Matrix4.setCol( 2, b_Vector4 ); + print( a_Matrix4, "Matrix4 set col 2" ); + a_Matrix4.setCol( 3, b_Vector4 ); + print( a_Matrix4, "Matrix4 set col 3" ); + print( a_Matrix4.getCol( 0 ), "Matrix4 get col 0" ); + print( a_Matrix4.getCol( 1 ), "Matrix4 get col 1" ); + print( a_Matrix4.getCol( 2 ), "Matrix4 get col 2" ); + print( a_Matrix4.getCol( 3 ), "Matrix4 get col 3" ); + a_Matrix4.setRow( 0, a_Vector4 ); + print( a_Matrix4, "Matrix4 set row 0" ); + a_Matrix4.setRow( 1, a_Vector4 ); + print( a_Matrix4, "Matrix4 set row 1" ); + a_Matrix4.setRow( 2, a_Vector4 ); + print( a_Matrix4, "Matrix4 set row 2" ); + a_Matrix4.setRow( 3, a_Vector4 ); + print( a_Matrix4, "Matrix4 set row 3" ); + print( a_Matrix4.getRow( 0 ), "Matrix4 get row 0" ); + print( a_Matrix4.getRow( 1 ), "Matrix4 get row 1" ); + print( a_Matrix4.getRow( 2 ), "Matrix4 get row 2" ); + print( a_Matrix4.getRow( 3 ), "Matrix4 get row 3" ); + a_Matrix4[0] = a_Vector4; + print( a_Matrix4, "set Matrix4[0]" ); + a_Matrix4[1] = a_Vector4; + print( a_Matrix4, "set Matrix4[1]" ); + a_Matrix4[2] = a_Vector4; + print( a_Matrix4, "set Matrix4[2]" ); + a_Matrix4[3] = a_Vector4; + print( a_Matrix4, "set Matrix4[3]" ); + a_Matrix4[0] = a_Vector4; + print( a_Matrix4[0], "get Matrix4[0]" ); + a_Matrix4[1] = a_Vector4; + print( a_Matrix4[1], "get Matrix4[1]" ); + a_Matrix4[2] = a_Vector4; + print( a_Matrix4[2], "get Matrix4[2]" ); + a_Matrix4[3] = a_Vector4; + print( a_Matrix4[3], "get Matrix4[3]" ); + a_Matrix4.setElem( 0, 0, randfloat() ); + a_Matrix4.setElem( 0, 1, randfloat() ); + a_Matrix4.setElem( 0, 2, randfloat() ); + a_Matrix4.setElem( 0, 3, randfloat() ); + a_Matrix4.setElem( 1, 0, randfloat() ); + a_Matrix4.setElem( 1, 1, randfloat() ); + a_Matrix4.setElem( 1, 2, randfloat() ); + a_Matrix4.setElem( 1, 3, randfloat() ); + a_Matrix4.setElem( 2, 0, randfloat() ); + a_Matrix4.setElem( 2, 1, randfloat() ); + a_Matrix4.setElem( 2, 2, randfloat() ); + a_Matrix4.setElem( 2, 3, randfloat() ); + a_Matrix4.setElem( 3, 0, randfloat() ); + a_Matrix4.setElem( 3, 1, randfloat() ); + a_Matrix4.setElem( 3, 2, randfloat() ); + a_Matrix4.setElem( 3, 3, randfloat() ); + print( a_Matrix4, "Matrix4 set elements" ); + printf("%f\n", getfloat(a_Matrix4.getElem( 0, 0 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 0, 1 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 0, 2 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 0, 3 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 1, 0 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 1, 1 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 1, 2 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 1, 3 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 2, 0 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 2, 1 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 2, 2 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 2, 3 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 3, 0 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 3, 1 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 3, 2 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 3, 3 )) ); +} + +void +Transform3_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + Vector4 tmpV4; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( a_Vector3, pad ); + a_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( b_Vector3, pad ); + b_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( c_Vector3, pad ); + c_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( d_Vector3, pad ); + d_Vector3 = tmpV4.getXYZ( ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( Vector3( a_Point3 ), pad ); + a_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( b_Point3 ), pad ); + b_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( c_Point3 ), pad ); + c_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( d_Point3 ), pad ); + d_Point3 = Point3( tmpV4.getXYZ( ) ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + a_Transform3 = Transform3( a_Matrix3, a_Vector3 ); + print( a_Transform3, "construct Transform3 with Matrix3 and Vector3" ); + a_Transform3 = Transform3( a_Quat, a_Vector3 ); + print( a_Transform3, "construct Transform3 with Quat and Vector3" ); + a_Transform3 = b_Transform3; + print( a_Transform3, "assign to Transform3 from Transform3" ); + a_Transform3 = Transform3( randfloat() ); + print( a_Transform3, "set Transform3 with float" ); + a_Transform3 = Transform3( scalar_float(randfloat()) ); + print( a_Transform3, "set Transform3 with float" ); + a_Transform3 = Transform3( 0.0f ); + print( a_Transform3, "set elements to zero" ); + a_Transform3 = Transform3::identity( ); + print( a_Transform3, "set to identity" ); + a_Transform3 = Transform3::rotationX( randfloat() ); + print( a_Transform3, "set to rotationX" ); + a_Transform3 = Transform3::rotationY( randfloat() ); + print( a_Transform3, "set to rotationY" ); + a_Transform3 = Transform3::rotationZ( randfloat() ); + print( a_Transform3, "set to rotationZ" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Transform3 = Transform3::rotationZYX( Vector3( rndflt3, rndflt2, rndflt1 ) ); + print( a_Transform3, "set to rotation from Z,Y,X angles" ); + a_Transform3 = Transform3::rotation( randfloat(), normalize( a_Vector3 ) ); + print( a_Transform3, "set to rotation from axis angle" ); + a_Transform3 = Transform3::translation( a_Vector3 ); + print( a_Transform3, "set to translation" ); + a_Transform3.setCol0( a_Vector3 ); + print( a_Transform3, "Transform3 set col 0" ); + a_Transform3.setCol1( a_Vector3 ); + print( a_Transform3, "Transform3 set col 1" ); + a_Transform3.setCol2( a_Vector3 ); + print( a_Transform3, "Transform3 set col 2" ); + a_Transform3.setCol3( a_Vector3 ); + print( a_Transform3, "Transform3 set col 3" ); + print( a_Transform3.getCol0( ), "Transform3 get col 0" ); + print( a_Transform3.getCol1( ), "Transform3 get col 1" ); + print( a_Transform3.getCol2( ), "Transform3 get col 2" ); + print( a_Transform3.getCol3( ), "Transform3 get col 3" ); + a_Transform3.setCol( 0, b_Vector3 ); + print( a_Transform3, "Transform3 set col 0" ); + a_Transform3.setCol( 1, b_Vector3 ); + print( a_Transform3, "Transform3 set col 1" ); + a_Transform3.setCol( 2, b_Vector3 ); + print( a_Transform3, "Transform3 set col 2" ); + a_Transform3.setCol( 3, b_Vector3 ); + print( a_Transform3, "Transform3 set col 3" ); + print( a_Transform3.getCol( 0 ), "Transform3 get col 0" ); + print( a_Transform3.getCol( 1 ), "Transform3 get col 1" ); + print( a_Transform3.getCol( 2 ), "Transform3 get col 2" ); + print( a_Transform3.getCol( 3 ), "Transform3 get col 3" ); + a_Transform3.setRow( 0, a_Vector4 ); + print( a_Transform3, "Transform3 set row 0" ); + a_Transform3.setRow( 1, a_Vector4 ); + print( a_Transform3, "Transform3 set row 1" ); + a_Transform3.setRow( 2, a_Vector4 ); + print( a_Transform3, "Transform3 set row 2" ); + print( a_Transform3.getRow( 0 ), "Transform3 get row 0" ); + print( a_Transform3.getRow( 1 ), "Transform3 get row 1" ); + print( a_Transform3.getRow( 2 ), "Transform3 get row 2" ); + a_Transform3[0] = a_Vector3; + print( a_Transform3, "set Transform3[0]" ); + a_Transform3[1] = a_Vector3; + print( a_Transform3, "set Transform3[1]" ); + a_Transform3[2] = a_Vector3; + print( a_Transform3, "set Transform3[2]" ); + a_Transform3[3] = a_Vector3; + print( a_Transform3, "set Transform3[3]" ); + a_Transform3[0] = a_Vector3; + print( a_Transform3[0], "get Transform3[0]" ); + a_Transform3[1] = a_Vector3; + print( a_Transform3[1], "get Transform3[1]" ); + a_Transform3[2] = a_Vector3; + print( a_Transform3[2], "get Transform3[2]" ); + a_Transform3[3] = a_Vector3; + print( a_Transform3[3], "get Transform3[3]" ); + a_Transform3.setElem( 0, 0, randfloat() ); + a_Transform3.setElem( 0, 1, randfloat() ); + a_Transform3.setElem( 0, 2, randfloat() ); + a_Transform3.setElem( 1, 0, randfloat() ); + a_Transform3.setElem( 1, 1, randfloat() ); + a_Transform3.setElem( 1, 2, randfloat() ); + a_Transform3.setElem( 2, 0, randfloat() ); + a_Transform3.setElem( 2, 1, randfloat() ); + a_Transform3.setElem( 2, 2, randfloat() ); + a_Transform3.setElem( 3, 0, randfloat() ); + a_Transform3.setElem( 3, 1, randfloat() ); + a_Transform3.setElem( 3, 2, randfloat() ); + print( a_Transform3, "Transform3 set elements" ); + printf("%f\n", getfloat(a_Transform3.getElem( 0, 0 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 0, 1 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 0, 2 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 1, 0 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 1, 1 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 1, 2 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 2, 0 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 2, 1 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 2, 2 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 3, 0 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 3, 1 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 3, 2 )) ); +} + +int main() +{ + int i; + printf("\n __begin__ \n"); + for ( i = 0; i < 2; i++ ) { + Matrix3_methods_test(); + Matrix4_methods_test(); + Transform3_methods_test(); + } + printf("\n __end__ \n"); + return 0; +} diff --git a/Extras/vectormathlibrary/tests/test2_reference.txt b/Extras/vectormathlibrary/tests/test2_reference.txt new file mode 100644 index 0000000..6f885a2 --- /dev/null +++ b/Extras/vectormathlibrary/tests/test2_reference.txt @@ -0,0 +1,1190 @@ +set Vector3 with floats: ( -0.658344 0.499804 -0.807257 ) +set Vector3 with floats: ( 0.740930 0.154607 0.571599 ) +set Vector3 with floats: ( 0.384388 -0.262467 0.747808 ) +set Vector3 with floats: ( 0.490190 -0.107908 -0.292544 ) +set Vector4 with floats: ( 0.465039 -0.479556 -0.211412 0.553580 ) +set Vector4 with floats: ( 0.690070 0.151576 0.431077 -0.833992 ) +set Vector4 with floats: ( -0.088350 -0.780106 0.090456 -0.218627 ) +set Vector4 with floats: ( 0.137171 0.918133 0.735438 -0.673621 ) +set Point3 with floats: ( -0.448982 -0.479278 0.848189 ) +set Point3 with floats: ( -0.128155 0.578922 -0.744766 ) +set Point3 with floats: ( -0.835589 0.881284 -0.948850 ) +set Point3 with floats: ( -0.691578 -0.235635 -0.690527 ) +set Quat with floats: ( 0.058667 0.753697 -0.138777 -0.472188 ) +set Quat with floats: ( -0.372811 0.540183 -0.785218 0.542085 ) +set Quat with floats: ( 0.410391 -0.562721 0.523588 -0.176574 ) +set Quat with floats: ( 0.297654 0.859913 0.004837 0.374881 ) +set Matrix3 columns: +( -0.658344 0.740930 0.384388 ) +( 0.499804 0.154607 -0.262467 ) +( -0.807257 0.571599 0.747808 ) +set Matrix3 columns: +( 0.490190 -0.658344 0.740930 ) +( -0.107908 0.499804 0.154607 ) +( -0.292544 -0.807257 0.571599 ) +set Matrix4 columns: +( 0.465039 0.690070 -0.088350 0.137171 ) +( -0.479556 0.151576 -0.780106 0.918133 ) +( -0.211412 0.431077 0.090456 0.735438 ) +( 0.553580 -0.833992 -0.218627 -0.673621 ) +set Matrix4 columns: +( 0.137171 0.465039 0.690070 -0.088350 ) +( 0.918133 -0.479556 0.151576 -0.780106 ) +( 0.735438 -0.211412 0.431077 0.090456 ) +( -0.673621 0.553580 -0.833992 -0.218627 ) +set Transform3 columns: +( -0.658344 0.740930 0.384388 0.490190 ) +( 0.499804 0.154607 -0.262467 -0.107908 ) +( -0.807257 0.571599 0.747808 -0.292544 ) +set Transform3 columns: +( 0.490190 -0.658344 0.740930 0.384388 ) +( -0.107908 0.499804 0.154607 -0.262467 ) +( -0.292544 -0.807257 0.571599 0.747808 ) +construct Matrix3 with Quat: +( -0.443537 -0.052381 -0.894724 ) +( 0.269738 0.944205 -0.188994 ) +( 0.854702 -0.325167 -0.404660 ) +construct Quat with Matrix3: ( -0.065036 -0.835524 0.153844 0.523452 ) +assign to Matrix3 from Matrix3: +( 0.490190 -0.658344 0.740930 ) +( -0.107908 0.499804 0.154607 ) +( -0.292544 -0.807257 0.571599 ) +set Matrix3 with float: +( -0.127818 -0.127818 -0.127818 ) +( -0.127818 -0.127818 -0.127818 ) +( -0.127818 -0.127818 -0.127818 ) +set Matrix3 with float: +( 0.216602 0.216602 0.216602 ) +( 0.216602 0.216602 0.216602 ) +( 0.216602 0.216602 0.216602 ) +set elements to zero: +( 0.000000 0.000000 0.000000 ) +( 0.000000 0.000000 0.000000 ) +( 0.000000 0.000000 0.000000 ) +set to identity: +( 1.000000 0.000000 0.000000 ) +( 0.000000 1.000000 0.000000 ) +( 0.000000 0.000000 1.000000 ) +set to rotationX: +( 1.000000 0.000000 0.000000 ) +( 0.000000 0.988300 -0.152520 ) +( 0.000000 0.152520 0.988300 ) +set to rotationY: +( 0.965029 0.000000 0.262144 ) +( 0.000000 1.000000 0.000000 ) +( -0.262144 0.000000 0.965029 ) +set to rotationZ: +( 0.997326 0.073083 0.000000 ) +( -0.073083 0.997326 0.000000 ) +( 0.000000 0.000000 1.000000 ) +set to rotation from Z,Y,X angles: +( 0.723488 -0.666973 -0.178077 ) +( 0.195944 0.445752 -0.873448 ) +( 0.661945 0.597036 0.453186 ) +set to rotation from axis angle: +( 0.836267 -0.515861 -0.185860 ) +( 0.396334 0.802918 -0.445244 ) +( 0.378915 0.298680 0.875907 ) +Matrix3 set col 0: +( -0.658344 -0.515861 -0.185860 ) +( 0.499804 0.802918 -0.445244 ) +( -0.807257 0.298680 0.875907 ) +Matrix3 set col 1: +( -0.658344 -0.658344 -0.185860 ) +( 0.499804 0.499804 -0.445244 ) +( -0.807257 -0.807257 0.875907 ) +Matrix3 set col 2: +( -0.658344 -0.658344 -0.658344 ) +( 0.499804 0.499804 0.499804 ) +( -0.807257 -0.807257 -0.807257 ) +Matrix3 get col 0: ( -0.658344 0.499804 -0.807257 ) +Matrix3 get col 1: ( -0.658344 0.499804 -0.807257 ) +Matrix3 get col 2: ( -0.658344 0.499804 -0.807257 ) +Matrix3 set col 0: +( 0.740930 -0.658344 -0.658344 ) +( 0.154607 0.499804 0.499804 ) +( 0.571599 -0.807257 -0.807257 ) +Matrix3 set col 1: +( 0.740930 0.740930 -0.658344 ) +( 0.154607 0.154607 0.499804 ) +( 0.571599 0.571599 -0.807257 ) +Matrix3 set col 2: +( 0.740930 0.740930 0.740930 ) +( 0.154607 0.154607 0.154607 ) +( 0.571599 0.571599 0.571599 ) +Matrix3 get col 0: ( 0.740930 0.154607 0.571599 ) +Matrix3 get col 1: ( 0.740930 0.154607 0.571599 ) +Matrix3 get col 2: ( 0.740930 0.154607 0.571599 ) +Matrix3 set row 0: +( -0.658344 0.499804 -0.807257 ) +( 0.154607 0.154607 0.154607 ) +( 0.571599 0.571599 0.571599 ) +Matrix3 set row 1: +( -0.658344 0.499804 -0.807257 ) +( -0.658344 0.499804 -0.807257 ) +( 0.571599 0.571599 0.571599 ) +Matrix3 set row 2: +( -0.658344 0.499804 -0.807257 ) +( -0.658344 0.499804 -0.807257 ) +( -0.658344 0.499804 -0.807257 ) +Matrix3 get row 0: ( -0.658344 0.499804 -0.807257 ) +Matrix3 get row 1: ( -0.658344 0.499804 -0.807257 ) +Matrix3 get row 2: ( -0.658344 0.499804 -0.807257 ) +set Matrix3[0]: +( -0.658344 0.499804 -0.807257 ) +( 0.499804 0.499804 -0.807257 ) +( -0.807257 0.499804 -0.807257 ) +set Matrix3[1]: +( -0.658344 -0.658344 -0.807257 ) +( 0.499804 0.499804 -0.807257 ) +( -0.807257 -0.807257 -0.807257 ) +set Matrix3[2]: +( -0.658344 -0.658344 -0.658344 ) +( 0.499804 0.499804 0.499804 ) +( -0.807257 -0.807257 -0.807257 ) +get Matrix3[0]: ( -0.658344 0.499804 -0.807257 ) +get Matrix3[1]: ( -0.658344 0.499804 -0.807257 ) +get Matrix3[2]: ( -0.658344 0.499804 -0.807257 ) +Matrix3 set elements: +( -0.106634 -0.283632 0.910171 ) +( -0.350831 -0.203584 0.969234 ) +( 0.905168 -0.797437 0.151940 ) +-0.106634 +-0.350831 +0.905168 +-0.283632 +-0.203584 +-0.797437 +0.910171 +0.969234 +0.151940 +set Vector3 with floats: ( 0.731827 -0.700248 0.818301 ) +set Vector3 with floats: ( 0.302505 -0.872278 0.909999 ) +set Vector3 with floats: ( 0.932526 0.571087 0.610330 ) +set Vector3 with floats: ( 0.142507 -0.434829 0.925102 ) +set Vector4 with floats: ( 0.158954 -0.126283 -0.249128 0.846815 ) +set Vector4 with floats: ( -0.942601 0.537720 0.446214 0.181939 ) +set Vector4 with floats: ( -0.148223 0.284286 0.493525 -0.861963 ) +set Vector4 with floats: ( -0.893410 0.548627 0.407007 -0.757467 ) +set Point3 with floats: ( -0.393126 -0.850984 0.375720 ) +set Point3 with floats: ( -0.270088 0.458888 -0.610828 ) +set Point3 with floats: ( -0.690816 -0.676415 0.664466 ) +set Point3 with floats: ( 0.101874 -0.365714 0.055473 ) +set Quat with floats: ( -0.133556 -0.572643 0.459209 -0.997261 ) +set Quat with floats: ( 0.172409 -0.045124 0.879716 0.524317 ) +set Quat with floats: ( -0.744532 -0.970444 -0.000013 0.689543 ) +set Quat with floats: ( 0.704297 -0.817983 0.715505 0.577868 ) +set Matrix3 columns: +( 0.731827 0.302505 0.932526 ) +( -0.700248 -0.872278 0.571087 ) +( 0.818301 0.909999 0.610330 ) +set Matrix3 columns: +( 0.142507 0.731827 0.302505 ) +( -0.434829 -0.700248 -0.872278 ) +( 0.925102 0.818301 0.909999 ) +set Matrix4 columns: +( 0.158954 -0.942601 -0.148223 -0.893410 ) +( -0.126283 0.537720 0.284286 0.548627 ) +( -0.249128 0.446214 0.493525 0.407007 ) +( 0.846815 0.181939 -0.861963 -0.757467 ) +set Matrix4 columns: +( -0.893410 0.158954 -0.942601 -0.148223 ) +( 0.548627 -0.126283 0.537720 0.284286 ) +( 0.407007 -0.249128 0.446214 0.493525 ) +( -0.757467 0.846815 0.181939 -0.861963 ) +set Transform3 columns: +( 0.731827 0.302505 0.932526 0.142507 ) +( -0.700248 -0.872278 0.571087 -0.434829 ) +( 0.818301 0.909999 0.610330 0.925102 ) +set Transform3 columns: +( 0.142507 0.731827 0.302505 0.932526 ) +( -0.434829 -0.700248 -0.872278 0.571087 ) +( 0.925102 0.818301 0.909999 0.610330 ) +construct Matrix4 with Transform3: +( 0.731827 0.302505 0.932526 0.142507 ) +( -0.700248 -0.872278 0.571087 -0.434829 ) +( 0.818301 0.909999 0.610330 0.925102 ) +( 0.000000 0.000000 0.000000 1.000000 ) +construct Matrix4 with Matrix3 and Vector3: +( 0.731827 0.302505 0.932526 0.731827 ) +( -0.700248 -0.872278 0.571087 -0.700248 ) +( 0.818301 0.909999 0.610330 0.818301 ) +( 0.000000 0.000000 0.000000 1.000000 ) +construct Matrix4 with Quat and Vector3: +( -0.077586 1.068863 1.019489 0.731827 ) +( -0.762943 0.542579 -0.792307 -0.700248 ) +( -1.264810 -0.259545 0.308485 0.818301 ) +( 0.000000 0.000000 0.000000 1.000000 ) +assign to Matrix4 from Matrix4: +( -0.893410 0.158954 -0.942601 -0.148223 ) +( 0.548627 -0.126283 0.537720 0.284286 ) +( 0.407007 -0.249128 0.446214 0.493525 ) +( -0.757467 0.846815 0.181939 -0.861963 ) +set Matrix4 with float: +( 0.156952 0.156952 0.156952 0.156952 ) +( 0.156952 0.156952 0.156952 0.156952 ) +( 0.156952 0.156952 0.156952 0.156952 ) +( 0.156952 0.156952 0.156952 0.156952 ) +set Matrix4 with float: +( -0.801022 -0.801022 -0.801022 -0.801022 ) +( -0.801022 -0.801022 -0.801022 -0.801022 ) +( -0.801022 -0.801022 -0.801022 -0.801022 ) +( -0.801022 -0.801022 -0.801022 -0.801022 ) +set elements to zero: +( 0.000000 0.000000 0.000000 0.000000 ) +( 0.000000 0.000000 0.000000 0.000000 ) +( 0.000000 0.000000 0.000000 0.000000 ) +( 0.000000 0.000000 0.000000 0.000000 ) +set to identity: +( 1.000000 0.000000 0.000000 0.000000 ) +( 0.000000 1.000000 0.000000 0.000000 ) +( 0.000000 0.000000 1.000000 0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +set to rotationX: +( 1.000000 0.000000 0.000000 0.000000 ) +( 0.000000 0.792234 -0.610218 0.000000 ) +( 0.000000 0.610218 0.792234 0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +set to rotationY: +( 0.880257 0.000000 0.474498 0.000000 ) +( 0.000000 1.000000 0.000000 0.000000 ) +( -0.474498 0.000000 0.880257 0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +set to rotationZ: +( 0.684599 -0.728920 0.000000 0.000000 ) +( 0.728920 0.684599 0.000000 0.000000 ) +( 0.000000 0.000000 1.000000 0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +set to rotation from Z,Y,X angles: +( 0.718303 0.540188 0.438449 0.000000 ) +( 0.017447 0.616016 -0.787541 0.000000 ) +( -0.695512 0.573343 0.433061 0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +set to rotation from axis angle: +( 0.993956 -0.086019 -0.068204 0.000000 ) +( 0.080679 0.993721 -0.077527 0.000000 ) +( 0.074445 0.071556 0.994655 0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +set to translation: +( 1.000000 0.000000 0.000000 0.731827 ) +( 0.000000 1.000000 0.000000 -0.700248 ) +( 0.000000 0.000000 1.000000 0.818301 ) +( 0.000000 0.000000 0.000000 1.000000 ) +set to perspective matrix: +( 232.227814 0.000000 0.000000 0.000000 ) +( 0.000000 -38.291180 0.000000 0.000000 ) +( 0.000000 0.000000 -2.308166 -0.994733 ) +( 0.000000 0.000000 -1.000000 0.000000 ) +set to frustum matrix: +( -1.076418 0.000000 0.527081 0.000000 ) +( 0.000000 -0.465615 -0.188684 0.000000 ) +( 0.000000 0.000000 -66.946648 -26.580370 ) +( 0.000000 0.000000 -1.000000 0.000000 ) +set to orthographic matrix: +( -2.962014 0.000000 0.000000 1.880296 ) +( 0.000000 5.281968 0.000000 -2.636149 ) +( 0.000000 0.000000 -3.467666 -2.260634 ) +( 0.000000 0.000000 0.000000 1.000000 ) +set to look-at matrix: +( 0.275461 -0.594716 -0.755271 -0.114033 ) +( 0.958396 0.108747 0.263914 0.370155 ) +( -0.074821 -0.796547 0.599929 -0.932668 ) +( 0.000000 0.000000 0.000000 1.000000 ) +Matrix4 set col 0: +( 0.158954 -0.594716 -0.755271 -0.114033 ) +( -0.126283 0.108747 0.263914 0.370155 ) +( -0.249128 -0.796547 0.599929 -0.932668 ) +( 0.846815 0.000000 0.000000 1.000000 ) +Matrix4 set col 1: +( 0.158954 0.158954 -0.755271 -0.114033 ) +( -0.126283 -0.126283 0.263914 0.370155 ) +( -0.249128 -0.249128 0.599929 -0.932668 ) +( 0.846815 0.846815 0.000000 1.000000 ) +Matrix4 set col 2: +( 0.158954 0.158954 0.158954 -0.114033 ) +( -0.126283 -0.126283 -0.126283 0.370155 ) +( -0.249128 -0.249128 -0.249128 -0.932668 ) +( 0.846815 0.846815 0.846815 1.000000 ) +Matrix4 set col 3: +( 0.158954 0.158954 0.158954 0.158954 ) +( -0.126283 -0.126283 -0.126283 -0.126283 ) +( -0.249128 -0.249128 -0.249128 -0.249128 ) +( 0.846815 0.846815 0.846815 0.846815 ) +Matrix4 get col 0: ( 0.158954 -0.126283 -0.249128 0.846815 ) +Matrix4 get col 1: ( 0.158954 -0.126283 -0.249128 0.846815 ) +Matrix4 get col 2: ( 0.158954 -0.126283 -0.249128 0.846815 ) +Matrix4 get col 3: ( 0.158954 -0.126283 -0.249128 0.846815 ) +Matrix4 set col 0: +( -0.942601 0.158954 0.158954 0.158954 ) +( 0.537720 -0.126283 -0.126283 -0.126283 ) +( 0.446214 -0.249128 -0.249128 -0.249128 ) +( 0.181939 0.846815 0.846815 0.846815 ) +Matrix4 set col 1: +( -0.942601 -0.942601 0.158954 0.158954 ) +( 0.537720 0.537720 -0.126283 -0.126283 ) +( 0.446214 0.446214 -0.249128 -0.249128 ) +( 0.181939 0.181939 0.846815 0.846815 ) +Matrix4 set col 2: +( -0.942601 -0.942601 -0.942601 0.158954 ) +( 0.537720 0.537720 0.537720 -0.126283 ) +( 0.446214 0.446214 0.446214 -0.249128 ) +( 0.181939 0.181939 0.181939 0.846815 ) +Matrix4 set col 3: +( -0.942601 -0.942601 -0.942601 -0.942601 ) +( 0.537720 0.537720 0.537720 0.537720 ) +( 0.446214 0.446214 0.446214 0.446214 ) +( 0.181939 0.181939 0.181939 0.181939 ) +Matrix4 get col 0: ( -0.942601 0.537720 0.446214 0.181939 ) +Matrix4 get col 1: ( -0.942601 0.537720 0.446214 0.181939 ) +Matrix4 get col 2: ( -0.942601 0.537720 0.446214 0.181939 ) +Matrix4 get col 3: ( -0.942601 0.537720 0.446214 0.181939 ) +Matrix4 set row 0: +( 0.158954 -0.126283 -0.249128 0.846815 ) +( 0.537720 0.537720 0.537720 0.537720 ) +( 0.446214 0.446214 0.446214 0.446214 ) +( 0.181939 0.181939 0.181939 0.181939 ) +Matrix4 set row 1: +( 0.158954 -0.126283 -0.249128 0.846815 ) +( 0.158954 -0.126283 -0.249128 0.846815 ) +( 0.446214 0.446214 0.446214 0.446214 ) +( 0.181939 0.181939 0.181939 0.181939 ) +Matrix4 set row 2: +( 0.158954 -0.126283 -0.249128 0.846815 ) +( 0.158954 -0.126283 -0.249128 0.846815 ) +( 0.158954 -0.126283 -0.249128 0.846815 ) +( 0.181939 0.181939 0.181939 0.181939 ) +Matrix4 set row 3: +( 0.158954 -0.126283 -0.249128 0.846815 ) +( 0.158954 -0.126283 -0.249128 0.846815 ) +( 0.158954 -0.126283 -0.249128 0.846815 ) +( 0.158954 -0.126283 -0.249128 0.846815 ) +Matrix4 get row 0: ( 0.158954 -0.126283 -0.249128 0.846815 ) +Matrix4 get row 1: ( 0.158954 -0.126283 -0.249128 0.846815 ) +Matrix4 get row 2: ( 0.158954 -0.126283 -0.249128 0.846815 ) +Matrix4 get row 3: ( 0.158954 -0.126283 -0.249128 0.846815 ) +set Matrix4[0]: +( 0.158954 -0.126283 -0.249128 0.846815 ) +( -0.126283 -0.126283 -0.249128 0.846815 ) +( -0.249128 -0.126283 -0.249128 0.846815 ) +( 0.846815 -0.126283 -0.249128 0.846815 ) +set Matrix4[1]: +( 0.158954 0.158954 -0.249128 0.846815 ) +( -0.126283 -0.126283 -0.249128 0.846815 ) +( -0.249128 -0.249128 -0.249128 0.846815 ) +( 0.846815 0.846815 -0.249128 0.846815 ) +set Matrix4[2]: +( 0.158954 0.158954 0.158954 0.846815 ) +( -0.126283 -0.126283 -0.126283 0.846815 ) +( -0.249128 -0.249128 -0.249128 0.846815 ) +( 0.846815 0.846815 0.846815 0.846815 ) +set Matrix4[3]: +( 0.158954 0.158954 0.158954 0.158954 ) +( -0.126283 -0.126283 -0.126283 -0.126283 ) +( -0.249128 -0.249128 -0.249128 -0.249128 ) +( 0.846815 0.846815 0.846815 0.846815 ) +get Matrix4[0]: ( 0.158954 -0.126283 -0.249128 0.846815 ) +get Matrix4[1]: ( 0.158954 -0.126283 -0.249128 0.846815 ) +get Matrix4[2]: ( 0.158954 -0.126283 -0.249128 0.846815 ) +get Matrix4[3]: ( 0.158954 -0.126283 -0.249128 0.846815 ) +Matrix4 set elements: +( -0.336683 0.205513 -0.071926 0.473013 ) +( 0.600164 -0.160082 -0.506313 -0.735610 ) +( -0.681272 0.962714 0.689277 -0.046390 ) +( 0.726558 0.737794 0.686485 0.568674 ) +-0.336683 +0.600164 +-0.681272 +0.726558 +0.205513 +-0.160082 +0.962714 +0.737794 +-0.071926 +-0.506313 +0.689277 +0.686485 +0.473013 +-0.735610 +-0.046390 +0.568674 +set Vector3 with floats: ( -0.004815 0.137637 -0.111879 ) +set Vector3 with floats: ( -0.929543 -0.336303 -0.146740 ) +set Vector3 with floats: ( 0.165140 -0.823874 0.349776 ) +set Vector3 with floats: ( 0.174872 -0.528584 0.489292 ) +set Vector4 with floats: ( 0.916708 0.728511 -0.851140 0.079620 ) +set Vector4 with floats: ( -0.234370 -0.996308 0.433229 -0.892684 ) +set Vector4 with floats: ( -0.957911 0.517122 0.257921 0.862028 ) +set Vector4 with floats: ( 0.095881 -0.171933 -0.214078 -0.604841 ) +set Point3 with floats: ( -0.383831 -0.581500 0.222183 ) +set Point3 with floats: ( -0.256120 -0.678699 -0.079553 ) +set Point3 with floats: ( 0.605960 -0.633147 0.435875 ) +set Point3 with floats: ( -0.046627 -0.716491 0.267317 ) +set Quat with floats: ( -0.514874 -0.751700 0.742959 -0.793180 ) +set Quat with floats: ( 0.508814 -0.238839 0.113471 -0.843523 ) +set Quat with floats: ( -0.245250 0.250368 0.579243 -0.157280 ) +set Quat with floats: ( 0.648487 0.103833 0.456401 -0.022372 ) +set Matrix3 columns: +( -0.004815 -0.929543 0.165140 ) +( 0.137637 -0.336303 -0.823874 ) +( -0.111879 -0.146740 0.349776 ) +set Matrix3 columns: +( 0.174872 -0.004815 -0.929543 ) +( -0.528584 0.137637 -0.336303 ) +( 0.489292 -0.111879 -0.146740 ) +set Matrix4 columns: +( 0.916708 -0.234370 -0.957911 0.095881 ) +( 0.728511 -0.996308 0.517122 -0.171933 ) +( -0.851140 0.433229 0.257921 -0.214078 ) +( 0.079620 -0.892684 0.862028 -0.604841 ) +set Matrix4 columns: +( 0.095881 0.916708 -0.234370 -0.957911 ) +( -0.171933 0.728511 -0.996308 0.517122 ) +( -0.214078 -0.851140 0.433229 0.257921 ) +( -0.604841 0.079620 -0.892684 0.862028 ) +set Transform3 columns: +( -0.004815 -0.929543 0.165140 0.174872 ) +( 0.137637 -0.336303 -0.823874 -0.528584 ) +( -0.111879 -0.146740 0.349776 0.489292 ) +set Transform3 columns: +( 0.174872 -0.004815 -0.929543 0.165140 ) +( -0.528584 0.137637 -0.336303 -0.823874 ) +( 0.489292 -0.111879 -0.146740 0.349776 ) +construct Transform3 with Matrix3 and Vector3: +( -0.004815 -0.929543 0.165140 -0.004815 ) +( 0.137637 -0.336303 -0.823874 0.137637 ) +( -0.111879 -0.146740 0.349776 -0.111879 ) +construct Transform3 with Quat and Vector3: +( -1.234080 1.952660 0.427405 -0.004815 ) +( -0.404539 -0.634166 -1.933738 0.137637 ) +( -1.957525 -0.300189 -0.660294 -0.111879 ) +assign to Transform3 from Transform3: +( 0.174872 -0.004815 -0.929543 0.165140 ) +( -0.528584 0.137637 -0.336303 -0.823874 ) +( 0.489292 -0.111879 -0.146740 0.349776 ) +set Transform3 with float: +( -0.475631 -0.475631 -0.475631 -0.475631 ) +( -0.475631 -0.475631 -0.475631 -0.475631 ) +( -0.475631 -0.475631 -0.475631 -0.475631 ) +set Transform3 with float: +( -0.004178 -0.004178 -0.004178 -0.004178 ) +( -0.004178 -0.004178 -0.004178 -0.004178 ) +( -0.004178 -0.004178 -0.004178 -0.004178 ) +set elements to zero: +( 0.000000 0.000000 0.000000 0.000000 ) +( 0.000000 0.000000 0.000000 0.000000 ) +( 0.000000 0.000000 0.000000 0.000000 ) +set to identity: +( 1.000000 0.000000 0.000000 0.000000 ) +( 0.000000 1.000000 0.000000 0.000000 ) +( 0.000000 0.000000 1.000000 0.000000 ) +set to rotationX: +( 1.000000 0.000000 0.000000 0.000000 ) +( 0.000000 0.999782 0.020864 0.000000 ) +( 0.000000 -0.020864 0.999782 0.000000 ) +set to rotationY: +( 0.999856 0.000000 -0.016996 0.000000 ) +( 0.000000 1.000000 0.000000 0.000000 ) +( 0.016996 0.000000 0.999856 0.000000 ) +set to rotationZ: +( 0.765394 -0.643562 0.000000 0.000000 ) +( 0.643562 0.765394 0.000000 0.000000 ) +( 0.000000 0.000000 1.000000 0.000000 ) +set to rotation from Z,Y,X angles: +( 0.643764 -0.756736 -0.113659 0.000000 ) +( 0.715027 0.647771 -0.262922 0.000000 ) +( 0.272588 0.087991 0.958099 0.000000 ) +set to rotation from axis angle: +( 0.978242 0.130404 0.161363 0.000000 ) +( -0.131321 0.991327 -0.005018 0.000000 ) +( -0.160618 -0.016281 0.986882 0.000000 ) +set to translation: +( 1.000000 0.000000 0.000000 -0.004815 ) +( 0.000000 1.000000 0.000000 0.137637 ) +( 0.000000 0.000000 1.000000 -0.111879 ) +Transform3 set col 0: +( -0.004815 0.000000 0.000000 -0.004815 ) +( 0.137637 1.000000 0.000000 0.137637 ) +( -0.111879 0.000000 1.000000 -0.111879 ) +Transform3 set col 1: +( -0.004815 -0.004815 0.000000 -0.004815 ) +( 0.137637 0.137637 0.000000 0.137637 ) +( -0.111879 -0.111879 1.000000 -0.111879 ) +Transform3 set col 2: +( -0.004815 -0.004815 -0.004815 -0.004815 ) +( 0.137637 0.137637 0.137637 0.137637 ) +( -0.111879 -0.111879 -0.111879 -0.111879 ) +Transform3 set col 3: +( -0.004815 -0.004815 -0.004815 -0.004815 ) +( 0.137637 0.137637 0.137637 0.137637 ) +( -0.111879 -0.111879 -0.111879 -0.111879 ) +Transform3 get col 0: ( -0.004815 0.137637 -0.111879 ) +Transform3 get col 1: ( -0.004815 0.137637 -0.111879 ) +Transform3 get col 2: ( -0.004815 0.137637 -0.111879 ) +Transform3 get col 3: ( -0.004815 0.137637 -0.111879 ) +Transform3 set col 0: +( -0.929543 -0.004815 -0.004815 -0.004815 ) +( -0.336303 0.137637 0.137637 0.137637 ) +( -0.146740 -0.111879 -0.111879 -0.111879 ) +Transform3 set col 1: +( -0.929543 -0.929543 -0.004815 -0.004815 ) +( -0.336303 -0.336303 0.137637 0.137637 ) +( -0.146740 -0.146740 -0.111879 -0.111879 ) +Transform3 set col 2: +( -0.929543 -0.929543 -0.929543 -0.004815 ) +( -0.336303 -0.336303 -0.336303 0.137637 ) +( -0.146740 -0.146740 -0.146740 -0.111879 ) +Transform3 set col 3: +( -0.929543 -0.929543 -0.929543 -0.929543 ) +( -0.336303 -0.336303 -0.336303 -0.336303 ) +( -0.146740 -0.146740 -0.146740 -0.146740 ) +Transform3 get col 0: ( -0.929543 -0.336303 -0.146740 ) +Transform3 get col 1: ( -0.929543 -0.336303 -0.146740 ) +Transform3 get col 2: ( -0.929543 -0.336303 -0.146740 ) +Transform3 get col 3: ( -0.929543 -0.336303 -0.146740 ) +Transform3 set row 0: +( 0.916708 0.728511 -0.851140 0.079620 ) +( -0.336303 -0.336303 -0.336303 -0.336303 ) +( -0.146740 -0.146740 -0.146740 -0.146740 ) +Transform3 set row 1: +( 0.916708 0.728511 -0.851140 0.079620 ) +( 0.916708 0.728511 -0.851140 0.079620 ) +( -0.146740 -0.146740 -0.146740 -0.146740 ) +Transform3 set row 2: +( 0.916708 0.728511 -0.851140 0.079620 ) +( 0.916708 0.728511 -0.851140 0.079620 ) +( 0.916708 0.728511 -0.851140 0.079620 ) +Transform3 get row 0: ( 0.916708 0.728511 -0.851140 0.079620 ) +Transform3 get row 1: ( 0.916708 0.728511 -0.851140 0.079620 ) +Transform3 get row 2: ( 0.916708 0.728511 -0.851140 0.079620 ) +set Transform3[0]: +( -0.004815 0.728511 -0.851140 0.079620 ) +( 0.137637 0.728511 -0.851140 0.079620 ) +( -0.111879 0.728511 -0.851140 0.079620 ) +set Transform3[1]: +( -0.004815 -0.004815 -0.851140 0.079620 ) +( 0.137637 0.137637 -0.851140 0.079620 ) +( -0.111879 -0.111879 -0.851140 0.079620 ) +set Transform3[2]: +( -0.004815 -0.004815 -0.004815 0.079620 ) +( 0.137637 0.137637 0.137637 0.079620 ) +( -0.111879 -0.111879 -0.111879 0.079620 ) +set Transform3[3]: +( -0.004815 -0.004815 -0.004815 -0.004815 ) +( 0.137637 0.137637 0.137637 0.137637 ) +( -0.111879 -0.111879 -0.111879 -0.111879 ) +get Transform3[0]: ( -0.004815 0.137637 -0.111879 ) +get Transform3[1]: ( -0.004815 0.137637 -0.111879 ) +get Transform3[2]: ( -0.004815 0.137637 -0.111879 ) +get Transform3[3]: ( -0.004815 0.137637 -0.111879 ) +Transform3 set elements: +( 0.219317 -0.567698 0.572490 0.867178 ) +( -0.118359 0.531358 -0.820417 0.934764 ) +( 0.413442 -0.387226 0.797191 0.237092 ) +0.219317 +-0.118359 +0.413442 +-0.567698 +0.531358 +-0.387226 +0.572490 +-0.820417 +0.797191 +0.867178 +0.934764 +0.237092 +set Vector3 with floats: ( -0.866162 -0.773939 0.261311 ) +set Vector3 with floats: ( -0.851570 0.114814 -0.531592 ) +set Vector3 with floats: ( 0.223925 0.869105 0.143405 ) +set Vector3 with floats: ( 0.148518 -0.071136 -0.758292 ) +set Vector4 with floats: ( -0.527633 0.997215 0.114440 0.727558 ) +set Vector4 with floats: ( -0.425760 0.459888 0.642516 -0.022534 ) +set Vector4 with floats: ( 0.186095 -0.775679 -0.683401 0.398134 ) +set Vector4 with floats: ( 0.189642 0.765986 -0.137795 -0.579844 ) +set Point3 with floats: ( -0.635647 0.374970 -0.563750 ) +set Point3 with floats: ( -0.471075 -0.553800 -0.014688 ) +set Point3 with floats: ( -0.464365 -0.107890 -0.527503 ) +set Point3 with floats: ( -0.406423 0.301261 0.499529 ) +set Quat with floats: ( 0.385180 -0.150218 0.519112 -0.203209 ) +set Quat with floats: ( -0.252017 0.282194 0.067637 0.798376 ) +set Quat with floats: ( 0.310782 0.861334 -0.980345 -0.655106 ) +set Quat with floats: ( 0.286765 0.532078 0.352671 0.540977 ) +set Matrix3 columns: +( -0.866162 -0.851570 0.223925 ) +( -0.773939 0.114814 0.869105 ) +( 0.261311 -0.531592 0.143405 ) +set Matrix3 columns: +( 0.148518 -0.866162 -0.851570 ) +( -0.071136 -0.773939 0.114814 ) +( -0.758292 0.261311 -0.531592 ) +set Matrix4 columns: +( -0.527633 -0.425760 0.186095 0.189642 ) +( 0.997215 0.459888 -0.775679 0.765986 ) +( 0.114440 0.642516 -0.683401 -0.137795 ) +( 0.727558 -0.022534 0.398134 -0.579844 ) +set Matrix4 columns: +( 0.189642 -0.527633 -0.425760 0.186095 ) +( 0.765986 0.997215 0.459888 -0.775679 ) +( -0.137795 0.114440 0.642516 -0.683401 ) +( -0.579844 0.727558 -0.022534 0.398134 ) +set Transform3 columns: +( -0.866162 -0.851570 0.223925 0.148518 ) +( -0.773939 0.114814 0.869105 -0.071136 ) +( 0.261311 -0.531592 0.143405 -0.758292 ) +set Transform3 columns: +( 0.148518 -0.866162 -0.851570 0.223925 ) +( -0.071136 -0.773939 0.114814 0.869105 ) +( -0.758292 0.261311 -0.531592 0.143405 ) +construct Matrix3 with Quat: +( -0.212551 0.197745 0.956932 ) +( -0.678219 -0.734858 0.001211 ) +( 0.703449 -0.648753 0.290309 ) +construct Quat with Matrix3: ( 0.554977 -0.216439 0.747950 -0.292789 ) +assign to Matrix3 from Matrix3: +( 0.148518 -0.866162 -0.851570 ) +( -0.071136 -0.773939 0.114814 ) +( -0.758292 0.261311 -0.531592 ) +set Matrix3 with float: +( 0.510961 0.510961 0.510961 ) +( 0.510961 0.510961 0.510961 ) +( 0.510961 0.510961 0.510961 ) +set Matrix3 with float: +( 0.791871 0.791871 0.791871 ) +( 0.791871 0.791871 0.791871 ) +( 0.791871 0.791871 0.791871 ) +set elements to zero: +( 0.000000 0.000000 0.000000 ) +( 0.000000 0.000000 0.000000 ) +( 0.000000 0.000000 0.000000 ) +set to identity: +( 1.000000 0.000000 0.000000 ) +( 0.000000 1.000000 0.000000 ) +( 0.000000 0.000000 1.000000 ) +set to rotationX: +( 1.000000 0.000000 0.000000 ) +( 0.000000 0.844921 0.534891 ) +( 0.000000 -0.534891 0.844921 ) +set to rotationY: +( 0.962913 0.000000 0.269813 ) +( 0.000000 1.000000 0.000000 ) +( -0.269813 0.000000 0.962913 ) +set to rotationZ: +( 0.981168 -0.193156 0.000000 ) +( 0.193156 0.981168 0.000000 ) +( 0.000000 0.000000 1.000000 ) +set to rotation from Z,Y,X angles: +( 0.935176 0.037174 -0.352226 ) +( 0.233454 0.683174 0.691934 ) +( 0.266354 -0.729309 0.630210 ) +set to rotation from axis angle: +( 0.943492 0.161034 0.289639 ) +( -0.047495 0.930683 -0.362731 ) +( -0.327974 0.328477 0.885740 ) +Matrix3 set col 0: +( -0.866162 0.161034 0.289639 ) +( -0.773939 0.930683 -0.362731 ) +( 0.261311 0.328477 0.885740 ) +Matrix3 set col 1: +( -0.866162 -0.866162 0.289639 ) +( -0.773939 -0.773939 -0.362731 ) +( 0.261311 0.261311 0.885740 ) +Matrix3 set col 2: +( -0.866162 -0.866162 -0.866162 ) +( -0.773939 -0.773939 -0.773939 ) +( 0.261311 0.261311 0.261311 ) +Matrix3 get col 0: ( -0.866162 -0.773939 0.261311 ) +Matrix3 get col 1: ( -0.866162 -0.773939 0.261311 ) +Matrix3 get col 2: ( -0.866162 -0.773939 0.261311 ) +Matrix3 set col 0: +( -0.851570 -0.866162 -0.866162 ) +( 0.114814 -0.773939 -0.773939 ) +( -0.531592 0.261311 0.261311 ) +Matrix3 set col 1: +( -0.851570 -0.851570 -0.866162 ) +( 0.114814 0.114814 -0.773939 ) +( -0.531592 -0.531592 0.261311 ) +Matrix3 set col 2: +( -0.851570 -0.851570 -0.851570 ) +( 0.114814 0.114814 0.114814 ) +( -0.531592 -0.531592 -0.531592 ) +Matrix3 get col 0: ( -0.851570 0.114814 -0.531592 ) +Matrix3 get col 1: ( -0.851570 0.114814 -0.531592 ) +Matrix3 get col 2: ( -0.851570 0.114814 -0.531592 ) +Matrix3 set row 0: +( -0.866162 -0.773939 0.261311 ) +( 0.114814 0.114814 0.114814 ) +( -0.531592 -0.531592 -0.531592 ) +Matrix3 set row 1: +( -0.866162 -0.773939 0.261311 ) +( -0.866162 -0.773939 0.261311 ) +( -0.531592 -0.531592 -0.531592 ) +Matrix3 set row 2: +( -0.866162 -0.773939 0.261311 ) +( -0.866162 -0.773939 0.261311 ) +( -0.866162 -0.773939 0.261311 ) +Matrix3 get row 0: ( -0.866162 -0.773939 0.261311 ) +Matrix3 get row 1: ( -0.866162 -0.773939 0.261311 ) +Matrix3 get row 2: ( -0.866162 -0.773939 0.261311 ) +set Matrix3[0]: +( -0.866162 -0.773939 0.261311 ) +( -0.773939 -0.773939 0.261311 ) +( 0.261311 -0.773939 0.261311 ) +set Matrix3[1]: +( -0.866162 -0.866162 0.261311 ) +( -0.773939 -0.773939 0.261311 ) +( 0.261311 0.261311 0.261311 ) +set Matrix3[2]: +( -0.866162 -0.866162 -0.866162 ) +( -0.773939 -0.773939 -0.773939 ) +( 0.261311 0.261311 0.261311 ) +get Matrix3[0]: ( -0.866162 -0.773939 0.261311 ) +get Matrix3[1]: ( -0.866162 -0.773939 0.261311 ) +get Matrix3[2]: ( -0.866162 -0.773939 0.261311 ) +Matrix3 set elements: +( -0.277798 -0.420178 0.795389 ) +( -0.032740 -0.522577 0.342900 ) +( 0.007412 0.324972 -0.913636 ) +-0.277798 +-0.032740 +0.007412 +-0.420178 +-0.522577 +0.324972 +0.795389 +0.342900 +-0.913636 +set Vector3 with floats: ( 0.675222 0.144053 -0.632329 ) +set Vector3 with floats: ( -0.947120 -0.049367 0.126333 ) +set Vector3 with floats: ( -0.664206 0.220879 0.284219 ) +set Vector3 with floats: ( -0.387216 0.913568 0.531906 ) +set Vector4 with floats: ( 0.271995 -0.862601 -0.738694 0.514248 ) +set Vector4 with floats: ( -0.039363 0.429390 -0.769469 0.281336 ) +set Vector4 with floats: ( -0.203301 0.412586 0.567926 0.410131 ) +set Vector4 with floats: ( -0.462918 0.560953 -0.731715 -0.446158 ) +set Point3 with floats: ( -0.837491 -0.573480 -0.607820 ) +set Point3 with floats: ( 0.238415 0.213445 0.098612 ) +set Point3 with floats: ( 0.135072 -0.749274 -0.855977 ) +set Point3 with floats: ( 0.765675 -0.693447 0.131554 ) +set Quat with floats: ( -0.366757 -0.330409 -0.588816 0.352533 ) +set Quat with floats: ( -0.920523 -0.915255 0.631924 -0.870739 ) +set Quat with floats: ( 0.415605 -0.180974 0.775698 0.879357 ) +set Quat with floats: ( -0.993958 -0.298452 0.876855 0.982846 ) +set Matrix3 columns: +( 0.675222 -0.947120 -0.664206 ) +( 0.144053 -0.049367 0.220879 ) +( -0.632329 0.126333 0.284219 ) +set Matrix3 columns: +( -0.387216 0.675222 -0.947120 ) +( 0.913568 0.144053 -0.049367 ) +( 0.531906 -0.632329 0.126333 ) +set Matrix4 columns: +( 0.271995 -0.039363 -0.203301 -0.462918 ) +( -0.862601 0.429390 0.412586 0.560953 ) +( -0.738694 -0.769469 0.567926 -0.731715 ) +( 0.514248 0.281336 0.410131 -0.446158 ) +set Matrix4 columns: +( -0.462918 0.271995 -0.039363 -0.203301 ) +( 0.560953 -0.862601 0.429390 0.412586 ) +( -0.731715 -0.738694 -0.769469 0.567926 ) +( -0.446158 0.514248 0.281336 0.410131 ) +set Transform3 columns: +( 0.675222 -0.947120 -0.664206 -0.387216 ) +( 0.144053 -0.049367 0.220879 0.913568 ) +( -0.632329 0.126333 0.284219 0.531906 ) +set Transform3 columns: +( -0.387216 0.675222 -0.947120 -0.664206 ) +( 0.913568 0.144053 -0.049367 0.220879 ) +( 0.531906 -0.632329 0.126333 0.284219 ) +construct Matrix4 with Transform3: +( 0.675222 -0.947120 -0.664206 -0.387216 ) +( 0.144053 -0.049367 0.220879 0.913568 ) +( -0.632329 0.126333 0.284219 0.531906 ) +( 0.000000 0.000000 0.000000 1.000000 ) +construct Matrix4 with Matrix3 and Vector3: +( 0.675222 -0.947120 -0.664206 0.675222 ) +( 0.144053 -0.049367 0.220879 0.144053 ) +( -0.632329 0.126333 0.284219 -0.632329 ) +( 0.000000 0.000000 0.000000 1.000000 ) +construct Matrix4 with Quat and Vector3: +( 0.088252 0.657513 0.198944 0.675222 ) +( -0.172794 0.037572 0.647688 0.144053 ) +( 0.664864 0.130513 0.512639 -0.632329 ) +( 0.000000 0.000000 0.000000 1.000000 ) +assign to Matrix4 from Matrix4: +( -0.462918 0.271995 -0.039363 -0.203301 ) +( 0.560953 -0.862601 0.429390 0.412586 ) +( -0.731715 -0.738694 -0.769469 0.567926 ) +( -0.446158 0.514248 0.281336 0.410131 ) +set Matrix4 with float: +( -0.282564 -0.282564 -0.282564 -0.282564 ) +( -0.282564 -0.282564 -0.282564 -0.282564 ) +( -0.282564 -0.282564 -0.282564 -0.282564 ) +( -0.282564 -0.282564 -0.282564 -0.282564 ) +set Matrix4 with float: +( 0.953469 0.953469 0.953469 0.953469 ) +( 0.953469 0.953469 0.953469 0.953469 ) +( 0.953469 0.953469 0.953469 0.953469 ) +( 0.953469 0.953469 0.953469 0.953469 ) +set elements to zero: +( 0.000000 0.000000 0.000000 0.000000 ) +( 0.000000 0.000000 0.000000 0.000000 ) +( 0.000000 0.000000 0.000000 0.000000 ) +( 0.000000 0.000000 0.000000 0.000000 ) +set to identity: +( 1.000000 0.000000 0.000000 0.000000 ) +( 0.000000 1.000000 0.000000 0.000000 ) +( 0.000000 0.000000 1.000000 0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +set to rotationX: +( 1.000000 0.000000 0.000000 0.000000 ) +( 0.000000 0.583868 0.811849 0.000000 ) +( 0.000000 -0.811849 0.583868 0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +set to rotationY: +( 0.949918 0.000000 -0.312499 0.000000 ) +( 0.000000 1.000000 0.000000 0.000000 ) +( 0.312499 0.000000 0.949918 0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +set to rotationZ: +( 0.769721 -0.638380 0.000000 0.000000 ) +( 0.638380 0.769721 0.000000 0.000000 ) +( 0.000000 0.000000 1.000000 0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +set to rotation from Z,Y,X angles: +( 0.911294 0.177317 0.371620 0.000000 ) +( -0.113182 0.975631 -0.187972 0.000000 ) +( -0.395894 0.129237 0.909156 0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +set to rotation from axis angle: +( 0.856844 -0.448125 -0.254956 0.000000 ) +( 0.514339 0.708724 0.482872 0.000000 ) +( -0.035694 -0.544879 0.837754 0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +set to translation: +( 1.000000 0.000000 0.000000 0.675222 ) +( 0.000000 1.000000 0.000000 0.144053 ) +( 0.000000 0.000000 1.000000 -0.632329 ) +( 0.000000 0.000000 0.000000 1.000000 ) +set to perspective matrix: +( 5.824870 0.000000 0.000000 0.000000 ) +( 0.000000 -3.026335 0.000000 0.000000 ) +( 0.000000 0.000000 -2.224833 -1.188350 ) +( 0.000000 0.000000 -1.000000 0.000000 ) +set to frustum matrix: +( -0.477514 0.000000 1.070274 0.000000 ) +( 0.000000 -24.527069 -7.801479 0.000000 ) +( 0.000000 0.000000 -0.473057 0.272420 ) +( 0.000000 0.000000 -1.000000 0.000000 ) +set to orthographic matrix: +( 32.423248 0.000000 0.000000 23.964319 ) +( 0.000000 -2.278212 0.000000 -0.092664 ) +( 0.000000 0.000000 2.155617 -0.869770 ) +( 0.000000 0.000000 0.000000 1.000000 ) +set to look-at matrix: +( -0.441820 0.853126 -0.277437 -0.049401 ) +( 0.544212 0.009028 -0.838899 -0.048950 ) +( -0.713182 -0.521627 -0.468270 -1.181050 ) +( 0.000000 0.000000 0.000000 1.000000 ) +Matrix4 set col 0: +( 0.271995 0.853126 -0.277437 -0.049401 ) +( -0.862601 0.009028 -0.838899 -0.048950 ) +( -0.738694 -0.521627 -0.468270 -1.181050 ) +( 0.514248 0.000000 0.000000 1.000000 ) +Matrix4 set col 1: +( 0.271995 0.271995 -0.277437 -0.049401 ) +( -0.862601 -0.862601 -0.838899 -0.048950 ) +( -0.738694 -0.738694 -0.468270 -1.181050 ) +( 0.514248 0.514248 0.000000 1.000000 ) +Matrix4 set col 2: +( 0.271995 0.271995 0.271995 -0.049401 ) +( -0.862601 -0.862601 -0.862601 -0.048950 ) +( -0.738694 -0.738694 -0.738694 -1.181050 ) +( 0.514248 0.514248 0.514248 1.000000 ) +Matrix4 set col 3: +( 0.271995 0.271995 0.271995 0.271995 ) +( -0.862601 -0.862601 -0.862601 -0.862601 ) +( -0.738694 -0.738694 -0.738694 -0.738694 ) +( 0.514248 0.514248 0.514248 0.514248 ) +Matrix4 get col 0: ( 0.271995 -0.862601 -0.738694 0.514248 ) +Matrix4 get col 1: ( 0.271995 -0.862601 -0.738694 0.514248 ) +Matrix4 get col 2: ( 0.271995 -0.862601 -0.738694 0.514248 ) +Matrix4 get col 3: ( 0.271995 -0.862601 -0.738694 0.514248 ) +Matrix4 set col 0: +( -0.039363 0.271995 0.271995 0.271995 ) +( 0.429390 -0.862601 -0.862601 -0.862601 ) +( -0.769469 -0.738694 -0.738694 -0.738694 ) +( 0.281336 0.514248 0.514248 0.514248 ) +Matrix4 set col 1: +( -0.039363 -0.039363 0.271995 0.271995 ) +( 0.429390 0.429390 -0.862601 -0.862601 ) +( -0.769469 -0.769469 -0.738694 -0.738694 ) +( 0.281336 0.281336 0.514248 0.514248 ) +Matrix4 set col 2: +( -0.039363 -0.039363 -0.039363 0.271995 ) +( 0.429390 0.429390 0.429390 -0.862601 ) +( -0.769469 -0.769469 -0.769469 -0.738694 ) +( 0.281336 0.281336 0.281336 0.514248 ) +Matrix4 set col 3: +( -0.039363 -0.039363 -0.039363 -0.039363 ) +( 0.429390 0.429390 0.429390 0.429390 ) +( -0.769469 -0.769469 -0.769469 -0.769469 ) +( 0.281336 0.281336 0.281336 0.281336 ) +Matrix4 get col 0: ( -0.039363 0.429390 -0.769469 0.281336 ) +Matrix4 get col 1: ( -0.039363 0.429390 -0.769469 0.281336 ) +Matrix4 get col 2: ( -0.039363 0.429390 -0.769469 0.281336 ) +Matrix4 get col 3: ( -0.039363 0.429390 -0.769469 0.281336 ) +Matrix4 set row 0: +( 0.271995 -0.862601 -0.738694 0.514248 ) +( 0.429390 0.429390 0.429390 0.429390 ) +( -0.769469 -0.769469 -0.769469 -0.769469 ) +( 0.281336 0.281336 0.281336 0.281336 ) +Matrix4 set row 1: +( 0.271995 -0.862601 -0.738694 0.514248 ) +( 0.271995 -0.862601 -0.738694 0.514248 ) +( -0.769469 -0.769469 -0.769469 -0.769469 ) +( 0.281336 0.281336 0.281336 0.281336 ) +Matrix4 set row 2: +( 0.271995 -0.862601 -0.738694 0.514248 ) +( 0.271995 -0.862601 -0.738694 0.514248 ) +( 0.271995 -0.862601 -0.738694 0.514248 ) +( 0.281336 0.281336 0.281336 0.281336 ) +Matrix4 set row 3: +( 0.271995 -0.862601 -0.738694 0.514248 ) +( 0.271995 -0.862601 -0.738694 0.514248 ) +( 0.271995 -0.862601 -0.738694 0.514248 ) +( 0.271995 -0.862601 -0.738694 0.514248 ) +Matrix4 get row 0: ( 0.271995 -0.862601 -0.738694 0.514248 ) +Matrix4 get row 1: ( 0.271995 -0.862601 -0.738694 0.514248 ) +Matrix4 get row 2: ( 0.271995 -0.862601 -0.738694 0.514248 ) +Matrix4 get row 3: ( 0.271995 -0.862601 -0.738694 0.514248 ) +set Matrix4[0]: +( 0.271995 -0.862601 -0.738694 0.514248 ) +( -0.862601 -0.862601 -0.738694 0.514248 ) +( -0.738694 -0.862601 -0.738694 0.514248 ) +( 0.514248 -0.862601 -0.738694 0.514248 ) +set Matrix4[1]: +( 0.271995 0.271995 -0.738694 0.514248 ) +( -0.862601 -0.862601 -0.738694 0.514248 ) +( -0.738694 -0.738694 -0.738694 0.514248 ) +( 0.514248 0.514248 -0.738694 0.514248 ) +set Matrix4[2]: +( 0.271995 0.271995 0.271995 0.514248 ) +( -0.862601 -0.862601 -0.862601 0.514248 ) +( -0.738694 -0.738694 -0.738694 0.514248 ) +( 0.514248 0.514248 0.514248 0.514248 ) +set Matrix4[3]: +( 0.271995 0.271995 0.271995 0.271995 ) +( -0.862601 -0.862601 -0.862601 -0.862601 ) +( -0.738694 -0.738694 -0.738694 -0.738694 ) +( 0.514248 0.514248 0.514248 0.514248 ) +get Matrix4[0]: ( 0.271995 -0.862601 -0.738694 0.514248 ) +get Matrix4[1]: ( 0.271995 -0.862601 -0.738694 0.514248 ) +get Matrix4[2]: ( 0.271995 -0.862601 -0.738694 0.514248 ) +get Matrix4[3]: ( 0.271995 -0.862601 -0.738694 0.514248 ) +Matrix4 set elements: +( -0.702364 -0.967562 -0.470750 -0.712890 ) +( -0.182602 -0.520296 -0.846580 -0.064487 ) +( -0.832807 0.160191 -0.705751 0.444065 ) +( 0.278191 -0.677990 -0.825368 -0.045226 ) +-0.702364 +-0.182602 +-0.832807 +0.278191 +-0.967562 +-0.520296 +0.160191 +-0.677990 +-0.470750 +-0.846580 +-0.705751 +-0.825368 +-0.712890 +-0.064487 +0.444065 +-0.045226 +set Vector3 with floats: ( 0.116544 -0.007285 -0.838230 ) +set Vector3 with floats: ( -0.410767 -0.409299 -0.336683 ) +set Vector3 with floats: ( -0.830700 -0.801729 -0.595153 ) +set Vector3 with floats: ( -0.784672 -0.653655 0.670791 ) +set Vector4 with floats: ( 0.653571 0.850716 0.071433 -0.057715 ) +set Vector4 with floats: ( 0.401895 0.016861 0.535438 0.965901 ) +set Vector4 with floats: ( -0.072675 0.341689 0.781662 0.707322 ) +set Vector4 with floats: ( 0.505889 0.432790 -0.825793 0.597719 ) +set Point3 with floats: ( -0.250905 -0.085712 -0.272847 ) +set Point3 with floats: ( 0.552644 0.194203 -0.884427 ) +set Point3 with floats: ( -0.756791 0.121107 0.312483 ) +set Point3 with floats: ( -0.873317 0.045081 0.687444 ) +set Quat with floats: ( -0.684626 -0.994047 0.800366 -0.565640 ) +set Quat with floats: ( -0.625626 0.932585 0.636928 0.420250 ) +set Quat with floats: ( 0.175863 0.362158 0.547496 -0.534423 ) +set Quat with floats: ( -0.563030 -0.254488 0.647778 -0.674240 ) +set Matrix3 columns: +( 0.116544 -0.410767 -0.830700 ) +( -0.007285 -0.409299 -0.801729 ) +( -0.838230 -0.336683 -0.595153 ) +set Matrix3 columns: +( -0.784672 0.116544 -0.410767 ) +( -0.653655 -0.007285 -0.409299 ) +( 0.670791 -0.838230 -0.336683 ) +set Matrix4 columns: +( 0.653571 0.401895 -0.072675 0.505889 ) +( 0.850716 0.016861 0.341689 0.432790 ) +( 0.071433 0.535438 0.781662 -0.825793 ) +( -0.057715 0.965901 0.707322 0.597719 ) +set Matrix4 columns: +( 0.505889 0.653571 0.401895 -0.072675 ) +( 0.432790 0.850716 0.016861 0.341689 ) +( -0.825793 0.071433 0.535438 0.781662 ) +( 0.597719 -0.057715 0.965901 0.707322 ) +set Transform3 columns: +( 0.116544 -0.410767 -0.830700 -0.784672 ) +( -0.007285 -0.409299 -0.801729 -0.653655 ) +( -0.838230 -0.336683 -0.595153 0.670791 ) +set Transform3 columns: +( -0.784672 0.116544 -0.410767 -0.830700 ) +( -0.653655 -0.007285 -0.409299 -0.801729 ) +( 0.670791 -0.838230 -0.336683 -0.595153 ) +construct Transform3 with Matrix3 and Vector3: +( 0.116544 -0.410767 -0.830700 0.116544 ) +( -0.007285 -0.409299 -0.801729 -0.007285 ) +( -0.838230 -0.336683 -0.595153 -0.838230 ) +construct Transform3 with Quat and Vector3: +( -2.257427 2.266537 0.028644 0.116544 ) +( 0.455662 -1.218594 -2.365705 -0.007285 ) +( -2.220447 -0.816698 -1.913682 -0.838230 ) +assign to Transform3 from Transform3: +( -0.784672 0.116544 -0.410767 -0.830700 ) +( -0.653655 -0.007285 -0.409299 -0.801729 ) +( 0.670791 -0.838230 -0.336683 -0.595153 ) +set Transform3 with float: +( 0.224345 0.224345 0.224345 0.224345 ) +( 0.224345 0.224345 0.224345 0.224345 ) +( 0.224345 0.224345 0.224345 0.224345 ) +set Transform3 with float: +( -0.754563 -0.754563 -0.754563 -0.754563 ) +( -0.754563 -0.754563 -0.754563 -0.754563 ) +( -0.754563 -0.754563 -0.754563 -0.754563 ) +set elements to zero: +( 0.000000 0.000000 0.000000 0.000000 ) +( 0.000000 0.000000 0.000000 0.000000 ) +( 0.000000 0.000000 0.000000 0.000000 ) +set to identity: +( 1.000000 0.000000 0.000000 0.000000 ) +( 0.000000 1.000000 0.000000 0.000000 ) +( 0.000000 0.000000 1.000000 0.000000 ) +set to rotationX: +( 1.000000 0.000000 0.000000 0.000000 ) +( 0.000000 0.991715 0.128461 0.000000 ) +( 0.000000 -0.128461 0.991715 0.000000 ) +set to rotationY: +( 0.542120 0.000000 -0.840301 0.000000 ) +( 0.000000 1.000000 0.000000 0.000000 ) +( 0.840301 0.000000 0.542120 0.000000 ) +set to rotationZ: +( 0.999319 -0.036908 0.000000 0.000000 ) +( 0.036908 0.999319 0.000000 0.000000 ) +( 0.000000 0.000000 1.000000 0.000000 ) +set to rotation from Z,Y,X angles: +( 0.927336 -0.248591 0.279733 0.000000 ) +( -0.072059 0.614889 0.785314 0.000000 ) +( -0.367227 -0.748408 0.552296 0.000000 ) +set to rotation from axis angle: +( 0.982382 -0.186883 -0.000825 0.000000 ) +( 0.186841 0.982043 0.026134 0.000000 ) +( -0.004073 -0.025827 0.999658 0.000000 ) +set to translation: +( 1.000000 0.000000 0.000000 0.116544 ) +( 0.000000 1.000000 0.000000 -0.007285 ) +( 0.000000 0.000000 1.000000 -0.838230 ) +Transform3 set col 0: +( 0.116544 0.000000 0.000000 0.116544 ) +( -0.007285 1.000000 0.000000 -0.007285 ) +( -0.838230 0.000000 1.000000 -0.838230 ) +Transform3 set col 1: +( 0.116544 0.116544 0.000000 0.116544 ) +( -0.007285 -0.007285 0.000000 -0.007285 ) +( -0.838230 -0.838230 1.000000 -0.838230 ) +Transform3 set col 2: +( 0.116544 0.116544 0.116544 0.116544 ) +( -0.007285 -0.007285 -0.007285 -0.007285 ) +( -0.838230 -0.838230 -0.838230 -0.838230 ) +Transform3 set col 3: +( 0.116544 0.116544 0.116544 0.116544 ) +( -0.007285 -0.007285 -0.007285 -0.007285 ) +( -0.838230 -0.838230 -0.838230 -0.838230 ) +Transform3 get col 0: ( 0.116544 -0.007285 -0.838230 ) +Transform3 get col 1: ( 0.116544 -0.007285 -0.838230 ) +Transform3 get col 2: ( 0.116544 -0.007285 -0.838230 ) +Transform3 get col 3: ( 0.116544 -0.007285 -0.838230 ) +Transform3 set col 0: +( -0.410767 0.116544 0.116544 0.116544 ) +( -0.409299 -0.007285 -0.007285 -0.007285 ) +( -0.336683 -0.838230 -0.838230 -0.838230 ) +Transform3 set col 1: +( -0.410767 -0.410767 0.116544 0.116544 ) +( -0.409299 -0.409299 -0.007285 -0.007285 ) +( -0.336683 -0.336683 -0.838230 -0.838230 ) +Transform3 set col 2: +( -0.410767 -0.410767 -0.410767 0.116544 ) +( -0.409299 -0.409299 -0.409299 -0.007285 ) +( -0.336683 -0.336683 -0.336683 -0.838230 ) +Transform3 set col 3: +( -0.410767 -0.410767 -0.410767 -0.410767 ) +( -0.409299 -0.409299 -0.409299 -0.409299 ) +( -0.336683 -0.336683 -0.336683 -0.336683 ) +Transform3 get col 0: ( -0.410767 -0.409299 -0.336683 ) +Transform3 get col 1: ( -0.410767 -0.409299 -0.336683 ) +Transform3 get col 2: ( -0.410767 -0.409299 -0.336683 ) +Transform3 get col 3: ( -0.410767 -0.409299 -0.336683 ) +Transform3 set row 0: +( 0.653571 0.850716 0.071433 -0.057715 ) +( -0.409299 -0.409299 -0.409299 -0.409299 ) +( -0.336683 -0.336683 -0.336683 -0.336683 ) +Transform3 set row 1: +( 0.653571 0.850716 0.071433 -0.057715 ) +( 0.653571 0.850716 0.071433 -0.057715 ) +( -0.336683 -0.336683 -0.336683 -0.336683 ) +Transform3 set row 2: +( 0.653571 0.850716 0.071433 -0.057715 ) +( 0.653571 0.850716 0.071433 -0.057715 ) +( 0.653571 0.850716 0.071433 -0.057715 ) +Transform3 get row 0: ( 0.653571 0.850716 0.071433 -0.057715 ) +Transform3 get row 1: ( 0.653571 0.850716 0.071433 -0.057715 ) +Transform3 get row 2: ( 0.653571 0.850716 0.071433 -0.057715 ) +set Transform3[0]: +( 0.116544 0.850716 0.071433 -0.057715 ) +( -0.007285 0.850716 0.071433 -0.057715 ) +( -0.838230 0.850716 0.071433 -0.057715 ) +set Transform3[1]: +( 0.116544 0.116544 0.071433 -0.057715 ) +( -0.007285 -0.007285 0.071433 -0.057715 ) +( -0.838230 -0.838230 0.071433 -0.057715 ) +set Transform3[2]: +( 0.116544 0.116544 0.116544 -0.057715 ) +( -0.007285 -0.007285 -0.007285 -0.057715 ) +( -0.838230 -0.838230 -0.838230 -0.057715 ) +set Transform3[3]: +( 0.116544 0.116544 0.116544 0.116544 ) +( -0.007285 -0.007285 -0.007285 -0.007285 ) +( -0.838230 -0.838230 -0.838230 -0.838230 ) +get Transform3[0]: ( 0.116544 -0.007285 -0.838230 ) +get Transform3[1]: ( 0.116544 -0.007285 -0.838230 ) +get Transform3[2]: ( 0.116544 -0.007285 -0.838230 ) +get Transform3[3]: ( 0.116544 -0.007285 -0.838230 ) +Transform3 set elements: +( 0.007649 -0.271484 -0.836501 -0.287826 ) +( -0.440298 -0.259070 0.229093 0.942655 ) +( 0.994796 0.902149 0.586393 -0.634432 ) +0.007649 +-0.440298 +0.994796 +-0.271484 +-0.259070 +0.902149 +-0.836501 +0.229093 +0.586393 +-0.287826 +0.942655 +-0.634432 + + __end__ diff --git a/Extras/vectormathlibrary/tests/test2_soa_c.c b/Extras/vectormathlibrary/tests/test2_soa_c.c new file mode 100644 index 0000000..6c64bf1 --- /dev/null +++ b/Extras/vectormathlibrary/tests/test2_soa_c.c @@ -0,0 +1,760 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +#define _VECTORMATH_SOA_TEST + +#include "vectormath_soa.h" +#include "test.h" + +int iteration = 0; + +void +Matrix3_methods_test() +{ + VmathSoaMatrix3 a_Matrix3, b_Matrix3; + VmathSoaMatrix4 a_Matrix4, b_Matrix4; + VmathSoaTransform3 a_Transform3, b_Transform3; + VmathSoaVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathSoaVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathSoaPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathSoaQuat a_Quat, b_Quat, c_Quat, d_Quat, tmpQ_0; + VmathSoaVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5, tmpV3_6, tmpV3_7, tmpV3_8, tmpV3_9, tmpV3_10, tmpV3_11, tmpV3_12, tmpV3_13; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathSoaV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathSoaP3Prints( &a_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &b_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &c_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaQPrints( &a_Quat, "set Quat with floats" ); + vmathSoaQPrints( &b_Quat, "set Quat with floats" ); + vmathSoaQPrints( &c_Quat, "set Quat with floats" ); + vmathSoaQPrints( &d_Quat, "set Quat with floats" ); + vmathSoaM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathSoaM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathSoaM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathSoaM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathSoaM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathSoaT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathSoaT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathSoaT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathSoaQNormalize( &tmpQ_0, &a_Quat ); + vmathSoaM3MakeFromQ( &a_Matrix3, &tmpQ_0 ); + vmathSoaM3Prints( &a_Matrix3, "construct Matrix3 with Quat" ); + vmathSoaQMakeFromM3( &a_Quat, &a_Matrix3 ); + vmathSoaQPrints( &a_Quat, "construct Quat with Matrix3" ); + vmathSoaM3Copy( &a_Matrix3, &b_Matrix3 ); + vmathSoaM3Prints( &a_Matrix3, "assign to Matrix3 from Matrix3" ); + vmathSoaM3MakeFromScalar( &a_Matrix3, randfloat() ); + vmathSoaM3Prints( &a_Matrix3, "set Matrix3 with float" ); + vmathSoaM3MakeFromScalar( &a_Matrix3, randfloat() ); + vmathSoaM3Prints( &a_Matrix3, "set Matrix3 with float" ); + vmathSoaM3MakeFromScalar( &a_Matrix3, (vec_float4){0.0f} ); + vmathSoaM3Prints( &a_Matrix3, "set elements to zero" ); + vmathSoaM3MakeIdentity( &a_Matrix3 ); + vmathSoaM3Prints( &a_Matrix3, "set to identity" ); + vmathSoaM3MakeRotationX( &a_Matrix3, randfloat() ); + vmathSoaM3Prints( &a_Matrix3, "set to rotationX" ); + vmathSoaM3MakeRotationY( &a_Matrix3, randfloat() ); + vmathSoaM3Prints( &a_Matrix3, "set to rotationY" ); + vmathSoaM3MakeRotationZ( &a_Matrix3, randfloat() ); + vmathSoaM3Prints( &a_Matrix3, "set to rotationZ" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &tmpV3_0, rndflt3, rndflt2, rndflt1 ); + vmathSoaM3MakeRotationZYX( &a_Matrix3, &tmpV3_0 ); + vmathSoaM3Prints( &a_Matrix3, "set to rotation from Z,Y,X angles" ); + vmathSoaV3Normalize( &tmpV3_1, &a_Vector3 ); + vmathSoaM3MakeRotationAxis( &a_Matrix3, randfloat(), &tmpV3_1 ); + vmathSoaM3Prints( &a_Matrix3, "set to rotation from axis angle" ); + vmathSoaM3SetCol0( &a_Matrix3, &a_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "Matrix3 set col 0" ); + vmathSoaM3SetCol1( &a_Matrix3, &a_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "Matrix3 set col 1" ); + vmathSoaM3SetCol2( &a_Matrix3, &a_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "Matrix3 set col 2" ); + vmathSoaM3GetCol0( &tmpV3_2, &a_Matrix3 ); + vmathSoaV3Prints( &tmpV3_2, "Matrix3 get col 0" ); + vmathSoaM3GetCol1( &tmpV3_3, &a_Matrix3 ); + vmathSoaV3Prints( &tmpV3_3, "Matrix3 get col 1" ); + vmathSoaM3GetCol2( &tmpV3_4, &a_Matrix3 ); + vmathSoaV3Prints( &tmpV3_4, "Matrix3 get col 2" ); + vmathSoaM3SetCol( &a_Matrix3, 0, &b_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "Matrix3 set col 0" ); + vmathSoaM3SetCol( &a_Matrix3, 1, &b_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "Matrix3 set col 1" ); + vmathSoaM3SetCol( &a_Matrix3, 2, &b_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "Matrix3 set col 2" ); + vmathSoaM3GetCol( &tmpV3_5, &a_Matrix3, 0 ); + vmathSoaV3Prints( &tmpV3_5, "Matrix3 get col 0" ); + vmathSoaM3GetCol( &tmpV3_6, &a_Matrix3, 1 ); + vmathSoaV3Prints( &tmpV3_6, "Matrix3 get col 1" ); + vmathSoaM3GetCol( &tmpV3_7, &a_Matrix3, 2 ); + vmathSoaV3Prints( &tmpV3_7, "Matrix3 get col 2" ); + vmathSoaM3SetRow( &a_Matrix3, 0, &a_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "Matrix3 set row 0" ); + vmathSoaM3SetRow( &a_Matrix3, 1, &a_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "Matrix3 set row 1" ); + vmathSoaM3SetRow( &a_Matrix3, 2, &a_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "Matrix3 set row 2" ); + vmathSoaM3GetRow( &tmpV3_8, &a_Matrix3, 0 ); + vmathSoaV3Prints( &tmpV3_8, "Matrix3 get row 0" ); + vmathSoaM3GetRow( &tmpV3_9, &a_Matrix3, 1 ); + vmathSoaV3Prints( &tmpV3_9, "Matrix3 get row 1" ); + vmathSoaM3GetRow( &tmpV3_10, &a_Matrix3, 2 ); + vmathSoaV3Prints( &tmpV3_10, "Matrix3 get row 2" ); + vmathSoaM3SetCol( &a_Matrix3, 0, &a_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "set " ); + vmathSoaM3SetCol( &a_Matrix3, 1, &a_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "set " ); + vmathSoaM3SetCol( &a_Matrix3, 2, &a_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "set " ); + vmathSoaM3GetCol( &tmpV3_11, &a_Matrix3, 0 ); + vmathSoaV3Prints( &tmpV3_11, "get " ); + vmathSoaM3GetCol( &tmpV3_12, &a_Matrix3, 1 ); + vmathSoaV3Prints( &tmpV3_12, "get " ); + vmathSoaM3GetCol( &tmpV3_13, &a_Matrix3, 2 ); + vmathSoaV3Prints( &tmpV3_13, "get " ); + vmathSoaM3SetElem( &a_Matrix3, 0, 0, randfloat() ); + vmathSoaM3SetElem( &a_Matrix3, 0, 1, randfloat() ); + vmathSoaM3SetElem( &a_Matrix3, 0, 2, randfloat() ); + vmathSoaM3SetElem( &a_Matrix3, 1, 0, randfloat() ); + vmathSoaM3SetElem( &a_Matrix3, 1, 1, randfloat() ); + vmathSoaM3SetElem( &a_Matrix3, 1, 2, randfloat() ); + vmathSoaM3SetElem( &a_Matrix3, 2, 0, randfloat() ); + vmathSoaM3SetElem( &a_Matrix3, 2, 1, randfloat() ); + vmathSoaM3SetElem( &a_Matrix3, 2, 2, randfloat() ); + vmathSoaM3Prints( &a_Matrix3, "Matrix3 set elements" ); + printf("%f\n", getfloat(vmathSoaM3GetElem( &a_Matrix3, 0, 0 )) ); + printf("%f\n", getfloat(vmathSoaM3GetElem( &a_Matrix3, 0, 1 )) ); + printf("%f\n", getfloat(vmathSoaM3GetElem( &a_Matrix3, 0, 2 )) ); + printf("%f\n", getfloat(vmathSoaM3GetElem( &a_Matrix3, 1, 0 )) ); + printf("%f\n", getfloat(vmathSoaM3GetElem( &a_Matrix3, 1, 1 )) ); + printf("%f\n", getfloat(vmathSoaM3GetElem( &a_Matrix3, 1, 2 )) ); + printf("%f\n", getfloat(vmathSoaM3GetElem( &a_Matrix3, 2, 0 )) ); + printf("%f\n", getfloat(vmathSoaM3GetElem( &a_Matrix3, 2, 1 )) ); + printf("%f\n", getfloat(vmathSoaM3GetElem( &a_Matrix3, 2, 2 )) ); +} + +void +Matrix4_methods_test() +{ + VmathSoaMatrix3 a_Matrix3, b_Matrix3; + VmathSoaMatrix4 a_Matrix4, b_Matrix4; + VmathSoaTransform3 a_Transform3, b_Transform3; + VmathSoaVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathSoaVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathSoaPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathSoaQuat a_Quat, b_Quat, c_Quat, d_Quat; + VmathSoaVector3 tmpV3_0, tmpV3_1; + VmathSoaVector4 tmpV4_0, tmpV4_1, tmpV4_2, tmpV4_3, tmpV4_4, tmpV4_5, tmpV4_6, tmpV4_7, tmpV4_8, tmpV4_9, tmpV4_10, tmpV4_11, tmpV4_12, tmpV4_13, tmpV4_14, tmpV4_15; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathSoaV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathSoaP3Prints( &a_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &b_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &c_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaQPrints( &a_Quat, "set Quat with floats" ); + vmathSoaQPrints( &b_Quat, "set Quat with floats" ); + vmathSoaQPrints( &c_Quat, "set Quat with floats" ); + vmathSoaQPrints( &d_Quat, "set Quat with floats" ); + vmathSoaM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathSoaM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathSoaM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathSoaM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathSoaM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathSoaT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathSoaT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathSoaT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathSoaM4MakeFromT3( &a_Matrix4, &a_Transform3 ); + vmathSoaM4Prints( &a_Matrix4, "construct Matrix4 with Transform3" ); + vmathSoaM4MakeFromM3V3( &a_Matrix4, &a_Matrix3, &a_Vector3 ); + vmathSoaM4Prints( &a_Matrix4, "construct Matrix4 with Matrix3 and Vector3" ); + vmathSoaM4MakeFromQV3( &a_Matrix4, &a_Quat, &a_Vector3 ); + vmathSoaM4Prints( &a_Matrix4, "construct Matrix4 with Quat and Vector3" ); + vmathSoaM4Copy( &a_Matrix4, &b_Matrix4 ); + vmathSoaM4Prints( &a_Matrix4, "assign to Matrix4 from Matrix4" ); + vmathSoaM4MakeFromScalar( &a_Matrix4, randfloat() ); + vmathSoaM4Prints( &a_Matrix4, "set Matrix4 with float" ); + vmathSoaM4MakeFromScalar( &a_Matrix4, randfloat() ); + vmathSoaM4Prints( &a_Matrix4, "set Matrix4 with float" ); + vmathSoaM4MakeFromScalar( &a_Matrix4, (vec_float4){0.0f} ); + vmathSoaM4Prints( &a_Matrix4, "set elements to zero" ); + vmathSoaM4MakeIdentity( &a_Matrix4 ); + vmathSoaM4Prints( &a_Matrix4, "set to identity" ); + vmathSoaM4MakeRotationX( &a_Matrix4, randfloat() ); + vmathSoaM4Prints( &a_Matrix4, "set to rotationX" ); + vmathSoaM4MakeRotationY( &a_Matrix4, randfloat() ); + vmathSoaM4Prints( &a_Matrix4, "set to rotationY" ); + vmathSoaM4MakeRotationZ( &a_Matrix4, randfloat() ); + vmathSoaM4Prints( &a_Matrix4, "set to rotationZ" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &tmpV3_0, rndflt3, rndflt2, rndflt1 ); + vmathSoaM4MakeRotationZYX( &a_Matrix4, &tmpV3_0 ); + vmathSoaM4Prints( &a_Matrix4, "set to rotation from Z,Y,X angles" ); + vmathSoaV3Normalize( &tmpV3_1, &a_Vector3 ); + vmathSoaM4MakeRotationAxis( &a_Matrix4, randfloat(), &tmpV3_1 ); + vmathSoaM4Prints( &a_Matrix4, "set to rotation from axis angle" ); + vmathSoaM4MakeTranslation( &a_Matrix4, &a_Vector3 ); + vmathSoaM4Prints( &a_Matrix4, "set to translation" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaM4MakePerspective( &a_Matrix4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaM4Prints( &a_Matrix4, "set to perspective matrix" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaM4MakeFrustum( &a_Matrix4, rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6 ); + vmathSoaM4Prints( &a_Matrix4, "set to frustum matrix" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaM4MakeOrthographic( &a_Matrix4, rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6 ); + vmathSoaM4Prints( &a_Matrix4, "set to orthographic matrix" ); + vmathSoaM4MakeLookAt( &a_Matrix4, &a_Point3, &b_Point3, &a_Vector3 ); + vmathSoaM4Prints( &a_Matrix4, "set to look-at matrix" ); + vmathSoaM4SetCol0( &a_Matrix4, &a_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "Matrix4 set col 0" ); + vmathSoaM4SetCol1( &a_Matrix4, &a_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "Matrix4 set col 1" ); + vmathSoaM4SetCol2( &a_Matrix4, &a_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "Matrix4 set col 2" ); + vmathSoaM4SetCol3( &a_Matrix4, &a_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "Matrix4 set col 3" ); + vmathSoaM4GetCol0( &tmpV4_0, &a_Matrix4 ); + vmathSoaV4Prints( &tmpV4_0, "Matrix4 get col 0" ); + vmathSoaM4GetCol1( &tmpV4_1, &a_Matrix4 ); + vmathSoaV4Prints( &tmpV4_1, "Matrix4 get col 1" ); + vmathSoaM4GetCol2( &tmpV4_2, &a_Matrix4 ); + vmathSoaV4Prints( &tmpV4_2, "Matrix4 get col 2" ); + vmathSoaM4GetCol3( &tmpV4_3, &a_Matrix4 ); + vmathSoaV4Prints( &tmpV4_3, "Matrix4 get col 3" ); + vmathSoaM4SetCol( &a_Matrix4, 0, &b_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "Matrix4 set col 0" ); + vmathSoaM4SetCol( &a_Matrix4, 1, &b_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "Matrix4 set col 1" ); + vmathSoaM4SetCol( &a_Matrix4, 2, &b_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "Matrix4 set col 2" ); + vmathSoaM4SetCol( &a_Matrix4, 3, &b_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "Matrix4 set col 3" ); + vmathSoaM4GetCol( &tmpV4_4, &a_Matrix4, 0 ); + vmathSoaV4Prints( &tmpV4_4, "Matrix4 get col 0" ); + vmathSoaM4GetCol( &tmpV4_5, &a_Matrix4, 1 ); + vmathSoaV4Prints( &tmpV4_5, "Matrix4 get col 1" ); + vmathSoaM4GetCol( &tmpV4_6, &a_Matrix4, 2 ); + vmathSoaV4Prints( &tmpV4_6, "Matrix4 get col 2" ); + vmathSoaM4GetCol( &tmpV4_7, &a_Matrix4, 3 ); + vmathSoaV4Prints( &tmpV4_7, "Matrix4 get col 3" ); + vmathSoaM4SetRow( &a_Matrix4, 0, &a_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "Matrix4 set row 0" ); + vmathSoaM4SetRow( &a_Matrix4, 1, &a_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "Matrix4 set row 1" ); + vmathSoaM4SetRow( &a_Matrix4, 2, &a_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "Matrix4 set row 2" ); + vmathSoaM4SetRow( &a_Matrix4, 3, &a_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "Matrix4 set row 3" ); + vmathSoaM4GetRow( &tmpV4_8, &a_Matrix4, 0 ); + vmathSoaV4Prints( &tmpV4_8, "Matrix4 get row 0" ); + vmathSoaM4GetRow( &tmpV4_9, &a_Matrix4, 1 ); + vmathSoaV4Prints( &tmpV4_9, "Matrix4 get row 1" ); + vmathSoaM4GetRow( &tmpV4_10, &a_Matrix4, 2 ); + vmathSoaV4Prints( &tmpV4_10, "Matrix4 get row 2" ); + vmathSoaM4GetRow( &tmpV4_11, &a_Matrix4, 3 ); + vmathSoaV4Prints( &tmpV4_11, "Matrix4 get row 3" ); + vmathSoaM4SetCol( &a_Matrix4, 0, &a_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "set " ); + vmathSoaM4SetCol( &a_Matrix4, 1, &a_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "set " ); + vmathSoaM4SetCol( &a_Matrix4, 2, &a_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "set " ); + vmathSoaM4SetCol( &a_Matrix4, 3, &a_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "set " ); + vmathSoaM4GetCol( &tmpV4_12, &a_Matrix4, 0 ); + vmathSoaV4Prints( &tmpV4_12, "get " ); + vmathSoaM4GetCol( &tmpV4_13, &a_Matrix4, 1 ); + vmathSoaV4Prints( &tmpV4_13, "get " ); + vmathSoaM4GetCol( &tmpV4_14, &a_Matrix4, 2 ); + vmathSoaV4Prints( &tmpV4_14, "get " ); + vmathSoaM4GetCol( &tmpV4_15, &a_Matrix4, 3 ); + vmathSoaV4Prints( &tmpV4_15, "get " ); + vmathSoaM4SetElem( &a_Matrix4, 0, 0, randfloat() ); + vmathSoaM4SetElem( &a_Matrix4, 0, 1, randfloat() ); + vmathSoaM4SetElem( &a_Matrix4, 0, 2, randfloat() ); + vmathSoaM4SetElem( &a_Matrix4, 0, 3, randfloat() ); + vmathSoaM4SetElem( &a_Matrix4, 1, 0, randfloat() ); + vmathSoaM4SetElem( &a_Matrix4, 1, 1, randfloat() ); + vmathSoaM4SetElem( &a_Matrix4, 1, 2, randfloat() ); + vmathSoaM4SetElem( &a_Matrix4, 1, 3, randfloat() ); + vmathSoaM4SetElem( &a_Matrix4, 2, 0, randfloat() ); + vmathSoaM4SetElem( &a_Matrix4, 2, 1, randfloat() ); + vmathSoaM4SetElem( &a_Matrix4, 2, 2, randfloat() ); + vmathSoaM4SetElem( &a_Matrix4, 2, 3, randfloat() ); + vmathSoaM4SetElem( &a_Matrix4, 3, 0, randfloat() ); + vmathSoaM4SetElem( &a_Matrix4, 3, 1, randfloat() ); + vmathSoaM4SetElem( &a_Matrix4, 3, 2, randfloat() ); + vmathSoaM4SetElem( &a_Matrix4, 3, 3, randfloat() ); + vmathSoaM4Prints( &a_Matrix4, "Matrix4 set elements" ); + printf("%f\n", getfloat(vmathSoaM4GetElem( &a_Matrix4, 0, 0 )) ); + printf("%f\n", getfloat(vmathSoaM4GetElem( &a_Matrix4, 0, 1 )) ); + printf("%f\n", getfloat(vmathSoaM4GetElem( &a_Matrix4, 0, 2 )) ); + printf("%f\n", getfloat(vmathSoaM4GetElem( &a_Matrix4, 0, 3 )) ); + printf("%f\n", getfloat(vmathSoaM4GetElem( &a_Matrix4, 1, 0 )) ); + printf("%f\n", getfloat(vmathSoaM4GetElem( &a_Matrix4, 1, 1 )) ); + printf("%f\n", getfloat(vmathSoaM4GetElem( &a_Matrix4, 1, 2 )) ); + printf("%f\n", getfloat(vmathSoaM4GetElem( &a_Matrix4, 1, 3 )) ); + printf("%f\n", getfloat(vmathSoaM4GetElem( &a_Matrix4, 2, 0 )) ); + printf("%f\n", getfloat(vmathSoaM4GetElem( &a_Matrix4, 2, 1 )) ); + printf("%f\n", getfloat(vmathSoaM4GetElem( &a_Matrix4, 2, 2 )) ); + printf("%f\n", getfloat(vmathSoaM4GetElem( &a_Matrix4, 2, 3 )) ); + printf("%f\n", getfloat(vmathSoaM4GetElem( &a_Matrix4, 3, 0 )) ); + printf("%f\n", getfloat(vmathSoaM4GetElem( &a_Matrix4, 3, 1 )) ); + printf("%f\n", getfloat(vmathSoaM4GetElem( &a_Matrix4, 3, 2 )) ); + printf("%f\n", getfloat(vmathSoaM4GetElem( &a_Matrix4, 3, 3 )) ); +} + +void +Transform3_methods_test() +{ + VmathSoaMatrix3 a_Matrix3, b_Matrix3; + VmathSoaMatrix4 a_Matrix4, b_Matrix4; + VmathSoaTransform3 a_Transform3, b_Transform3; + VmathSoaVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathSoaVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathSoaPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathSoaQuat a_Quat, b_Quat, c_Quat, d_Quat; + VmathSoaVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5, tmpV3_6, tmpV3_7, tmpV3_8, tmpV3_9; + VmathSoaVector4 tmpV4_0, tmpV4_1, tmpV4_2; + VmathSoaVector3 tmpV3_10, tmpV3_11, tmpV3_12, tmpV3_13; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathSoaV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathSoaP3Prints( &a_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &b_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &c_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaQPrints( &a_Quat, "set Quat with floats" ); + vmathSoaQPrints( &b_Quat, "set Quat with floats" ); + vmathSoaQPrints( &c_Quat, "set Quat with floats" ); + vmathSoaQPrints( &d_Quat, "set Quat with floats" ); + vmathSoaM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathSoaM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathSoaM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathSoaM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathSoaM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathSoaT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathSoaT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathSoaT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathSoaT3MakeFromM3V3( &a_Transform3, &a_Matrix3, &a_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "construct Transform3 with Matrix3 and Vector3" ); + vmathSoaT3MakeFromQV3( &a_Transform3, &a_Quat, &a_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "construct Transform3 with Quat and Vector3" ); + vmathSoaT3Copy( &a_Transform3, &b_Transform3 ); + vmathSoaT3Prints( &a_Transform3, "assign to Transform3 from Transform3" ); + vmathSoaT3MakeFromScalar( &a_Transform3, randfloat() ); + vmathSoaT3Prints( &a_Transform3, "set Transform3 with float" ); + vmathSoaT3MakeFromScalar( &a_Transform3, randfloat() ); + vmathSoaT3Prints( &a_Transform3, "set Transform3 with float" ); + vmathSoaT3MakeFromScalar( &a_Transform3, (vec_float4){0.0f} ); + vmathSoaT3Prints( &a_Transform3, "set elements to zero" ); + vmathSoaT3MakeIdentity( &a_Transform3 ); + vmathSoaT3Prints( &a_Transform3, "set to identity" ); + vmathSoaT3MakeRotationX( &a_Transform3, randfloat() ); + vmathSoaT3Prints( &a_Transform3, "set to rotationX" ); + vmathSoaT3MakeRotationY( &a_Transform3, randfloat() ); + vmathSoaT3Prints( &a_Transform3, "set to rotationY" ); + vmathSoaT3MakeRotationZ( &a_Transform3, randfloat() ); + vmathSoaT3Prints( &a_Transform3, "set to rotationZ" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &tmpV3_0, rndflt3, rndflt2, rndflt1 ); + vmathSoaT3MakeRotationZYX( &a_Transform3, &tmpV3_0 ); + vmathSoaT3Prints( &a_Transform3, "set to rotation from Z,Y,X angles" ); + vmathSoaV3Normalize( &tmpV3_1, &a_Vector3 ); + vmathSoaT3MakeRotationAxis( &a_Transform3, randfloat(), &tmpV3_1 ); + vmathSoaT3Prints( &a_Transform3, "set to rotation from axis angle" ); + vmathSoaT3MakeTranslation( &a_Transform3, &a_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "set to translation" ); + vmathSoaT3SetCol0( &a_Transform3, &a_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "Transform3 set col 0" ); + vmathSoaT3SetCol1( &a_Transform3, &a_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "Transform3 set col 1" ); + vmathSoaT3SetCol2( &a_Transform3, &a_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "Transform3 set col 2" ); + vmathSoaT3SetCol3( &a_Transform3, &a_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "Transform3 set col 3" ); + vmathSoaT3GetCol0( &tmpV3_2, &a_Transform3 ); + vmathSoaV3Prints( &tmpV3_2, "Transform3 get col 0" ); + vmathSoaT3GetCol1( &tmpV3_3, &a_Transform3 ); + vmathSoaV3Prints( &tmpV3_3, "Transform3 get col 1" ); + vmathSoaT3GetCol2( &tmpV3_4, &a_Transform3 ); + vmathSoaV3Prints( &tmpV3_4, "Transform3 get col 2" ); + vmathSoaT3GetCol3( &tmpV3_5, &a_Transform3 ); + vmathSoaV3Prints( &tmpV3_5, "Transform3 get col 3" ); + vmathSoaT3SetCol( &a_Transform3, 0, &b_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "Transform3 set col 0" ); + vmathSoaT3SetCol( &a_Transform3, 1, &b_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "Transform3 set col 1" ); + vmathSoaT3SetCol( &a_Transform3, 2, &b_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "Transform3 set col 2" ); + vmathSoaT3SetCol( &a_Transform3, 3, &b_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "Transform3 set col 3" ); + vmathSoaT3GetCol( &tmpV3_6, &a_Transform3, 0 ); + vmathSoaV3Prints( &tmpV3_6, "Transform3 get col 0" ); + vmathSoaT3GetCol( &tmpV3_7, &a_Transform3, 1 ); + vmathSoaV3Prints( &tmpV3_7, "Transform3 get col 1" ); + vmathSoaT3GetCol( &tmpV3_8, &a_Transform3, 2 ); + vmathSoaV3Prints( &tmpV3_8, "Transform3 get col 2" ); + vmathSoaT3GetCol( &tmpV3_9, &a_Transform3, 3 ); + vmathSoaV3Prints( &tmpV3_9, "Transform3 get col 3" ); + vmathSoaT3SetRow( &a_Transform3, 0, &a_Vector4 ); + vmathSoaT3Prints( &a_Transform3, "Transform3 set row 0" ); + vmathSoaT3SetRow( &a_Transform3, 1, &a_Vector4 ); + vmathSoaT3Prints( &a_Transform3, "Transform3 set row 1" ); + vmathSoaT3SetRow( &a_Transform3, 2, &a_Vector4 ); + vmathSoaT3Prints( &a_Transform3, "Transform3 set row 2" ); + vmathSoaT3GetRow( &tmpV4_0, &a_Transform3, 0 ); + vmathSoaV4Prints( &tmpV4_0, "Transform3 get row 0" ); + vmathSoaT3GetRow( &tmpV4_1, &a_Transform3, 1 ); + vmathSoaV4Prints( &tmpV4_1, "Transform3 get row 1" ); + vmathSoaT3GetRow( &tmpV4_2, &a_Transform3, 2 ); + vmathSoaV4Prints( &tmpV4_2, "Transform3 get row 2" ); + vmathSoaT3SetCol( &a_Transform3, 0, &a_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "set " ); + vmathSoaT3SetCol( &a_Transform3, 1, &a_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "set " ); + vmathSoaT3SetCol( &a_Transform3, 2, &a_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "set " ); + vmathSoaT3SetCol( &a_Transform3, 3, &a_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "set " ); + vmathSoaT3GetCol( &tmpV3_10, &a_Transform3, 0 ); + vmathSoaV3Prints( &tmpV3_10, "get " ); + vmathSoaT3GetCol( &tmpV3_11, &a_Transform3, 1 ); + vmathSoaV3Prints( &tmpV3_11, "get " ); + vmathSoaT3GetCol( &tmpV3_12, &a_Transform3, 2 ); + vmathSoaV3Prints( &tmpV3_12, "get " ); + vmathSoaT3GetCol( &tmpV3_13, &a_Transform3, 3 ); + vmathSoaV3Prints( &tmpV3_13, "get " ); + vmathSoaT3SetElem( &a_Transform3, 0, 0, randfloat() ); + vmathSoaT3SetElem( &a_Transform3, 0, 1, randfloat() ); + vmathSoaT3SetElem( &a_Transform3, 0, 2, randfloat() ); + vmathSoaT3SetElem( &a_Transform3, 1, 0, randfloat() ); + vmathSoaT3SetElem( &a_Transform3, 1, 1, randfloat() ); + vmathSoaT3SetElem( &a_Transform3, 1, 2, randfloat() ); + vmathSoaT3SetElem( &a_Transform3, 2, 0, randfloat() ); + vmathSoaT3SetElem( &a_Transform3, 2, 1, randfloat() ); + vmathSoaT3SetElem( &a_Transform3, 2, 2, randfloat() ); + vmathSoaT3SetElem( &a_Transform3, 3, 0, randfloat() ); + vmathSoaT3SetElem( &a_Transform3, 3, 1, randfloat() ); + vmathSoaT3SetElem( &a_Transform3, 3, 2, randfloat() ); + vmathSoaT3Prints( &a_Transform3, "Transform3 set elements" ); + printf("%f\n", getfloat(vmathSoaT3GetElem( &a_Transform3, 0, 0 )) ); + printf("%f\n", getfloat(vmathSoaT3GetElem( &a_Transform3, 0, 1 )) ); + printf("%f\n", getfloat(vmathSoaT3GetElem( &a_Transform3, 0, 2 )) ); + printf("%f\n", getfloat(vmathSoaT3GetElem( &a_Transform3, 1, 0 )) ); + printf("%f\n", getfloat(vmathSoaT3GetElem( &a_Transform3, 1, 1 )) ); + printf("%f\n", getfloat(vmathSoaT3GetElem( &a_Transform3, 1, 2 )) ); + printf("%f\n", getfloat(vmathSoaT3GetElem( &a_Transform3, 2, 0 )) ); + printf("%f\n", getfloat(vmathSoaT3GetElem( &a_Transform3, 2, 1 )) ); + printf("%f\n", getfloat(vmathSoaT3GetElem( &a_Transform3, 2, 2 )) ); + printf("%f\n", getfloat(vmathSoaT3GetElem( &a_Transform3, 3, 0 )) ); + printf("%f\n", getfloat(vmathSoaT3GetElem( &a_Transform3, 3, 1 )) ); + printf("%f\n", getfloat(vmathSoaT3GetElem( &a_Transform3, 3, 2 )) ); +} + +int main() +{ + int i; + printf("\n __begin__ \n"); + for ( i = 0; i < 2; i++ ) { + Matrix3_methods_test(); + Matrix4_methods_test(); + Transform3_methods_test(); + } + printf("\n __end__ \n"); + return 0; +} diff --git a/Extras/vectormathlibrary/tests/test2_soa_cpp.cpp b/Extras/vectormathlibrary/tests/test2_soa_cpp.cpp new file mode 100644 index 0000000..6ec5815 --- /dev/null +++ b/Extras/vectormathlibrary/tests/test2_soa_cpp.cpp @@ -0,0 +1,718 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +#define _VECTORMATH_SOA_TEST + +#include "vectormath_soa.h" +#include "test.h" + +int iteration = 0; + +using namespace Vectormath; +using namespace Vectormath::Soa; + +void +Matrix3_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + a_Matrix3 = Matrix3( normalize( a_Quat ) ); + print( a_Matrix3, "construct Matrix3 with Quat" ); + a_Quat = Quat( a_Matrix3 ); + print( a_Quat, "construct Quat with Matrix3" ); + a_Matrix3 = b_Matrix3; + print( a_Matrix3, "assign to Matrix3 from Matrix3" ); + a_Matrix3 = Matrix3( randfloat() ); + print( a_Matrix3, "set Matrix3 with float" ); + a_Matrix3 = Matrix3( randfloat() ); + print( a_Matrix3, "set Matrix3 with float" ); + a_Matrix3 = Matrix3( (vec_float4){0.0f} ); + print( a_Matrix3, "set elements to zero" ); + a_Matrix3 = Matrix3::identity( ); + print( a_Matrix3, "set to identity" ); + a_Matrix3 = Matrix3::rotationX( randfloat() ); + print( a_Matrix3, "set to rotationX" ); + a_Matrix3 = Matrix3::rotationY( randfloat() ); + print( a_Matrix3, "set to rotationY" ); + a_Matrix3 = Matrix3::rotationZ( randfloat() ); + print( a_Matrix3, "set to rotationZ" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Matrix3 = Matrix3::rotationZYX( Vector3( rndflt3, rndflt2, rndflt1 ) ); + print( a_Matrix3, "set to rotation from Z,Y,X angles" ); + a_Matrix3 = Matrix3::rotation( randfloat(), normalize( a_Vector3 ) ); + print( a_Matrix3, "set to rotation from axis angle" ); + a_Matrix3.setCol0( a_Vector3 ); + print( a_Matrix3, "Matrix3 set col 0" ); + a_Matrix3.setCol1( a_Vector3 ); + print( a_Matrix3, "Matrix3 set col 1" ); + a_Matrix3.setCol2( a_Vector3 ); + print( a_Matrix3, "Matrix3 set col 2" ); + print( a_Matrix3.getCol0( ), "Matrix3 get col 0" ); + print( a_Matrix3.getCol1( ), "Matrix3 get col 1" ); + print( a_Matrix3.getCol2( ), "Matrix3 get col 2" ); + a_Matrix3.setCol( 0, b_Vector3 ); + print( a_Matrix3, "Matrix3 set col 0" ); + a_Matrix3.setCol( 1, b_Vector3 ); + print( a_Matrix3, "Matrix3 set col 1" ); + a_Matrix3.setCol( 2, b_Vector3 ); + print( a_Matrix3, "Matrix3 set col 2" ); + print( a_Matrix3.getCol( 0 ), "Matrix3 get col 0" ); + print( a_Matrix3.getCol( 1 ), "Matrix3 get col 1" ); + print( a_Matrix3.getCol( 2 ), "Matrix3 get col 2" ); + a_Matrix3.setRow( 0, a_Vector3 ); + print( a_Matrix3, "Matrix3 set row 0" ); + a_Matrix3.setRow( 1, a_Vector3 ); + print( a_Matrix3, "Matrix3 set row 1" ); + a_Matrix3.setRow( 2, a_Vector3 ); + print( a_Matrix3, "Matrix3 set row 2" ); + print( a_Matrix3.getRow( 0 ), "Matrix3 get row 0" ); + print( a_Matrix3.getRow( 1 ), "Matrix3 get row 1" ); + print( a_Matrix3.getRow( 2 ), "Matrix3 get row 2" ); + a_Matrix3[0] = a_Vector3; + print( a_Matrix3, "set Matrix3[0]" ); + a_Matrix3[1] = a_Vector3; + print( a_Matrix3, "set Matrix3[1]" ); + a_Matrix3[2] = a_Vector3; + print( a_Matrix3, "set Matrix3[2]" ); + a_Matrix3[0] = a_Vector3; + print( a_Matrix3[0], "get Matrix3[0]" ); + a_Matrix3[1] = a_Vector3; + print( a_Matrix3[1], "get Matrix3[1]" ); + a_Matrix3[2] = a_Vector3; + print( a_Matrix3[2], "get Matrix3[2]" ); + a_Matrix3.setElem( 0, 0, randfloat() ); + a_Matrix3.setElem( 0, 1, randfloat() ); + a_Matrix3.setElem( 0, 2, randfloat() ); + a_Matrix3.setElem( 1, 0, randfloat() ); + a_Matrix3.setElem( 1, 1, randfloat() ); + a_Matrix3.setElem( 1, 2, randfloat() ); + a_Matrix3.setElem( 2, 0, randfloat() ); + a_Matrix3.setElem( 2, 1, randfloat() ); + a_Matrix3.setElem( 2, 2, randfloat() ); + print( a_Matrix3, "Matrix3 set elements" ); + printf("%f\n", getfloat(a_Matrix3.getElem( 0, 0 )) ); + printf("%f\n", getfloat(a_Matrix3.getElem( 0, 1 )) ); + printf("%f\n", getfloat(a_Matrix3.getElem( 0, 2 )) ); + printf("%f\n", getfloat(a_Matrix3.getElem( 1, 0 )) ); + printf("%f\n", getfloat(a_Matrix3.getElem( 1, 1 )) ); + printf("%f\n", getfloat(a_Matrix3.getElem( 1, 2 )) ); + printf("%f\n", getfloat(a_Matrix3.getElem( 2, 0 )) ); + printf("%f\n", getfloat(a_Matrix3.getElem( 2, 1 )) ); + printf("%f\n", getfloat(a_Matrix3.getElem( 2, 2 )) ); +} + +void +Matrix4_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + a_Matrix4 = Matrix4( a_Transform3 ); + print( a_Matrix4, "construct Matrix4 with Transform3" ); + a_Matrix4 = Matrix4( a_Matrix3, a_Vector3 ); + print( a_Matrix4, "construct Matrix4 with Matrix3 and Vector3" ); + a_Matrix4 = Matrix4( a_Quat, a_Vector3 ); + print( a_Matrix4, "construct Matrix4 with Quat and Vector3" ); + a_Matrix4 = b_Matrix4; + print( a_Matrix4, "assign to Matrix4 from Matrix4" ); + a_Matrix4 = Matrix4( randfloat() ); + print( a_Matrix4, "set Matrix4 with float" ); + a_Matrix4 = Matrix4( randfloat() ); + print( a_Matrix4, "set Matrix4 with float" ); + a_Matrix4 = Matrix4( (vec_float4){0.0f} ); + print( a_Matrix4, "set elements to zero" ); + a_Matrix4 = Matrix4::identity( ); + print( a_Matrix4, "set to identity" ); + a_Matrix4 = Matrix4::rotationX( randfloat() ); + print( a_Matrix4, "set to rotationX" ); + a_Matrix4 = Matrix4::rotationY( randfloat() ); + print( a_Matrix4, "set to rotationY" ); + a_Matrix4 = Matrix4::rotationZ( randfloat() ); + print( a_Matrix4, "set to rotationZ" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Matrix4 = Matrix4::rotationZYX( Vector3( rndflt3, rndflt2, rndflt1 ) ); + print( a_Matrix4, "set to rotation from Z,Y,X angles" ); + a_Matrix4 = Matrix4::rotation( randfloat(), normalize( a_Vector3 ) ); + print( a_Matrix4, "set to rotation from axis angle" ); + a_Matrix4 = Matrix4::translation( a_Vector3 ); + print( a_Matrix4, "set to translation" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Matrix4 = Matrix4::perspective( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Matrix4, "set to perspective matrix" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + a_Matrix4 = Matrix4::frustum( rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6 ); + print( a_Matrix4, "set to frustum matrix" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + a_Matrix4 = Matrix4::orthographic( rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6 ); + print( a_Matrix4, "set to orthographic matrix" ); + a_Matrix4 = Matrix4::lookAt( a_Point3, b_Point3, a_Vector3 ); + print( a_Matrix4, "set to look-at matrix" ); + a_Matrix4.setCol0( a_Vector4 ); + print( a_Matrix4, "Matrix4 set col 0" ); + a_Matrix4.setCol1( a_Vector4 ); + print( a_Matrix4, "Matrix4 set col 1" ); + a_Matrix4.setCol2( a_Vector4 ); + print( a_Matrix4, "Matrix4 set col 2" ); + a_Matrix4.setCol3( a_Vector4 ); + print( a_Matrix4, "Matrix4 set col 3" ); + print( a_Matrix4.getCol0( ), "Matrix4 get col 0" ); + print( a_Matrix4.getCol1( ), "Matrix4 get col 1" ); + print( a_Matrix4.getCol2( ), "Matrix4 get col 2" ); + print( a_Matrix4.getCol3( ), "Matrix4 get col 3" ); + a_Matrix4.setCol( 0, b_Vector4 ); + print( a_Matrix4, "Matrix4 set col 0" ); + a_Matrix4.setCol( 1, b_Vector4 ); + print( a_Matrix4, "Matrix4 set col 1" ); + a_Matrix4.setCol( 2, b_Vector4 ); + print( a_Matrix4, "Matrix4 set col 2" ); + a_Matrix4.setCol( 3, b_Vector4 ); + print( a_Matrix4, "Matrix4 set col 3" ); + print( a_Matrix4.getCol( 0 ), "Matrix4 get col 0" ); + print( a_Matrix4.getCol( 1 ), "Matrix4 get col 1" ); + print( a_Matrix4.getCol( 2 ), "Matrix4 get col 2" ); + print( a_Matrix4.getCol( 3 ), "Matrix4 get col 3" ); + a_Matrix4.setRow( 0, a_Vector4 ); + print( a_Matrix4, "Matrix4 set row 0" ); + a_Matrix4.setRow( 1, a_Vector4 ); + print( a_Matrix4, "Matrix4 set row 1" ); + a_Matrix4.setRow( 2, a_Vector4 ); + print( a_Matrix4, "Matrix4 set row 2" ); + a_Matrix4.setRow( 3, a_Vector4 ); + print( a_Matrix4, "Matrix4 set row 3" ); + print( a_Matrix4.getRow( 0 ), "Matrix4 get row 0" ); + print( a_Matrix4.getRow( 1 ), "Matrix4 get row 1" ); + print( a_Matrix4.getRow( 2 ), "Matrix4 get row 2" ); + print( a_Matrix4.getRow( 3 ), "Matrix4 get row 3" ); + a_Matrix4[0] = a_Vector4; + print( a_Matrix4, "set Matrix4[0]" ); + a_Matrix4[1] = a_Vector4; + print( a_Matrix4, "set Matrix4[1]" ); + a_Matrix4[2] = a_Vector4; + print( a_Matrix4, "set Matrix4[2]" ); + a_Matrix4[3] = a_Vector4; + print( a_Matrix4, "set Matrix4[3]" ); + a_Matrix4[0] = a_Vector4; + print( a_Matrix4[0], "get Matrix4[0]" ); + a_Matrix4[1] = a_Vector4; + print( a_Matrix4[1], "get Matrix4[1]" ); + a_Matrix4[2] = a_Vector4; + print( a_Matrix4[2], "get Matrix4[2]" ); + a_Matrix4[3] = a_Vector4; + print( a_Matrix4[3], "get Matrix4[3]" ); + a_Matrix4.setElem( 0, 0, randfloat() ); + a_Matrix4.setElem( 0, 1, randfloat() ); + a_Matrix4.setElem( 0, 2, randfloat() ); + a_Matrix4.setElem( 0, 3, randfloat() ); + a_Matrix4.setElem( 1, 0, randfloat() ); + a_Matrix4.setElem( 1, 1, randfloat() ); + a_Matrix4.setElem( 1, 2, randfloat() ); + a_Matrix4.setElem( 1, 3, randfloat() ); + a_Matrix4.setElem( 2, 0, randfloat() ); + a_Matrix4.setElem( 2, 1, randfloat() ); + a_Matrix4.setElem( 2, 2, randfloat() ); + a_Matrix4.setElem( 2, 3, randfloat() ); + a_Matrix4.setElem( 3, 0, randfloat() ); + a_Matrix4.setElem( 3, 1, randfloat() ); + a_Matrix4.setElem( 3, 2, randfloat() ); + a_Matrix4.setElem( 3, 3, randfloat() ); + print( a_Matrix4, "Matrix4 set elements" ); + printf("%f\n", getfloat(a_Matrix4.getElem( 0, 0 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 0, 1 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 0, 2 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 0, 3 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 1, 0 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 1, 1 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 1, 2 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 1, 3 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 2, 0 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 2, 1 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 2, 2 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 2, 3 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 3, 0 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 3, 1 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 3, 2 )) ); + printf("%f\n", getfloat(a_Matrix4.getElem( 3, 3 )) ); +} + +void +Transform3_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + a_Transform3 = Transform3( a_Matrix3, a_Vector3 ); + print( a_Transform3, "construct Transform3 with Matrix3 and Vector3" ); + a_Transform3 = Transform3( a_Quat, a_Vector3 ); + print( a_Transform3, "construct Transform3 with Quat and Vector3" ); + a_Transform3 = b_Transform3; + print( a_Transform3, "assign to Transform3 from Transform3" ); + a_Transform3 = Transform3( randfloat() ); + print( a_Transform3, "set Transform3 with float" ); + a_Transform3 = Transform3( randfloat() ); + print( a_Transform3, "set Transform3 with float" ); + a_Transform3 = Transform3( (vec_float4){0.0f} ); + print( a_Transform3, "set elements to zero" ); + a_Transform3 = Transform3::identity( ); + print( a_Transform3, "set to identity" ); + a_Transform3 = Transform3::rotationX( randfloat() ); + print( a_Transform3, "set to rotationX" ); + a_Transform3 = Transform3::rotationY( randfloat() ); + print( a_Transform3, "set to rotationY" ); + a_Transform3 = Transform3::rotationZ( randfloat() ); + print( a_Transform3, "set to rotationZ" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Transform3 = Transform3::rotationZYX( Vector3( rndflt3, rndflt2, rndflt1 ) ); + print( a_Transform3, "set to rotation from Z,Y,X angles" ); + a_Transform3 = Transform3::rotation( randfloat(), normalize( a_Vector3 ) ); + print( a_Transform3, "set to rotation from axis angle" ); + a_Transform3 = Transform3::translation( a_Vector3 ); + print( a_Transform3, "set to translation" ); + a_Transform3.setCol0( a_Vector3 ); + print( a_Transform3, "Transform3 set col 0" ); + a_Transform3.setCol1( a_Vector3 ); + print( a_Transform3, "Transform3 set col 1" ); + a_Transform3.setCol2( a_Vector3 ); + print( a_Transform3, "Transform3 set col 2" ); + a_Transform3.setCol3( a_Vector3 ); + print( a_Transform3, "Transform3 set col 3" ); + print( a_Transform3.getCol0( ), "Transform3 get col 0" ); + print( a_Transform3.getCol1( ), "Transform3 get col 1" ); + print( a_Transform3.getCol2( ), "Transform3 get col 2" ); + print( a_Transform3.getCol3( ), "Transform3 get col 3" ); + a_Transform3.setCol( 0, b_Vector3 ); + print( a_Transform3, "Transform3 set col 0" ); + a_Transform3.setCol( 1, b_Vector3 ); + print( a_Transform3, "Transform3 set col 1" ); + a_Transform3.setCol( 2, b_Vector3 ); + print( a_Transform3, "Transform3 set col 2" ); + a_Transform3.setCol( 3, b_Vector3 ); + print( a_Transform3, "Transform3 set col 3" ); + print( a_Transform3.getCol( 0 ), "Transform3 get col 0" ); + print( a_Transform3.getCol( 1 ), "Transform3 get col 1" ); + print( a_Transform3.getCol( 2 ), "Transform3 get col 2" ); + print( a_Transform3.getCol( 3 ), "Transform3 get col 3" ); + a_Transform3.setRow( 0, a_Vector4 ); + print( a_Transform3, "Transform3 set row 0" ); + a_Transform3.setRow( 1, a_Vector4 ); + print( a_Transform3, "Transform3 set row 1" ); + a_Transform3.setRow( 2, a_Vector4 ); + print( a_Transform3, "Transform3 set row 2" ); + print( a_Transform3.getRow( 0 ), "Transform3 get row 0" ); + print( a_Transform3.getRow( 1 ), "Transform3 get row 1" ); + print( a_Transform3.getRow( 2 ), "Transform3 get row 2" ); + a_Transform3[0] = a_Vector3; + print( a_Transform3, "set Transform3[0]" ); + a_Transform3[1] = a_Vector3; + print( a_Transform3, "set Transform3[1]" ); + a_Transform3[2] = a_Vector3; + print( a_Transform3, "set Transform3[2]" ); + a_Transform3[3] = a_Vector3; + print( a_Transform3, "set Transform3[3]" ); + a_Transform3[0] = a_Vector3; + print( a_Transform3[0], "get Transform3[0]" ); + a_Transform3[1] = a_Vector3; + print( a_Transform3[1], "get Transform3[1]" ); + a_Transform3[2] = a_Vector3; + print( a_Transform3[2], "get Transform3[2]" ); + a_Transform3[3] = a_Vector3; + print( a_Transform3[3], "get Transform3[3]" ); + a_Transform3.setElem( 0, 0, randfloat() ); + a_Transform3.setElem( 0, 1, randfloat() ); + a_Transform3.setElem( 0, 2, randfloat() ); + a_Transform3.setElem( 1, 0, randfloat() ); + a_Transform3.setElem( 1, 1, randfloat() ); + a_Transform3.setElem( 1, 2, randfloat() ); + a_Transform3.setElem( 2, 0, randfloat() ); + a_Transform3.setElem( 2, 1, randfloat() ); + a_Transform3.setElem( 2, 2, randfloat() ); + a_Transform3.setElem( 3, 0, randfloat() ); + a_Transform3.setElem( 3, 1, randfloat() ); + a_Transform3.setElem( 3, 2, randfloat() ); + print( a_Transform3, "Transform3 set elements" ); + printf("%f\n", getfloat(a_Transform3.getElem( 0, 0 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 0, 1 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 0, 2 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 1, 0 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 1, 1 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 1, 2 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 2, 0 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 2, 1 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 2, 2 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 3, 0 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 3, 1 )) ); + printf("%f\n", getfloat(a_Transform3.getElem( 3, 2 )) ); +} + +int main() +{ + int i; + printf("\n __begin__ \n"); + for ( i = 0; i < 2; i++ ) { + Matrix3_methods_test(); + Matrix4_methods_test(); + Transform3_methods_test(); + } + printf("\n __end__ \n"); + return 0; +} diff --git a/Extras/vectormathlibrary/tests/test3_aos_c.c b/Extras/vectormathlibrary/tests/test3_aos_c.c new file mode 100644 index 0000000..22afb69 --- /dev/null +++ b/Extras/vectormathlibrary/tests/test3_aos_c.c @@ -0,0 +1,524 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +#define _VECTORMATH_AOS_TEST + +#include "vectormath_aos.h" +#include "test.h" + +int iteration = 0; + +void +Matrix3_methods_test() +{ + VmathMatrix3 a_Matrix3, b_Matrix3; + VmathMatrix4 a_Matrix4, b_Matrix4; + VmathTransform3 a_Transform3, b_Transform3; + VmathMatrix3 tmpM3_0, tmpM3_1, tmpM3_2, tmpM3_3, tmpM3_4, tmpM3_5; + VmathVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathQuat a_Quat, b_Quat, c_Quat, d_Quat; + VmathVector4 tmpV4; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5, tmpV3_6, tmpV3_7, tmpV3_8; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &a_Vector3, pad ); + vmathV4GetXYZ( &a_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &b_Vector3, pad ); + vmathV4GetXYZ( &b_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &c_Vector3, pad ); + vmathV4GetXYZ( &c_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &d_Vector3, pad ); + vmathV4GetXYZ( &d_Vector3, &tmpV4 ); + vmathV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathV3MakeFromP3( &tmpV3_0, &a_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_0, pad ); + vmathV4GetXYZ( &tmpV3_1, &tmpV4 ); + vmathP3MakeFromV3( &a_Point3, &tmpV3_1 ); + vmathV3MakeFromP3( &tmpV3_2, &b_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_2, pad ); + vmathV4GetXYZ( &tmpV3_3, &tmpV4 ); + vmathP3MakeFromV3( &b_Point3, &tmpV3_3 ); + vmathV3MakeFromP3( &tmpV3_4, &c_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_4, pad ); + vmathV4GetXYZ( &tmpV3_5, &tmpV4 ); + vmathP3MakeFromV3( &c_Point3, &tmpV3_5 ); + vmathV3MakeFromP3( &tmpV3_6, &d_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_6, pad ); + vmathV4GetXYZ( &tmpV3_7, &tmpV4 ); + vmathP3MakeFromV3( &d_Point3, &tmpV3_7 ); + vmathP3Prints( &a_Point3, "set Point3 with floats" ); + vmathP3Prints( &b_Point3, "set Point3 with floats" ); + vmathP3Prints( &c_Point3, "set Point3 with floats" ); + vmathP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathQPrints( &a_Quat, "set Quat with floats" ); + vmathQPrints( &b_Quat, "set Quat with floats" ); + vmathQPrints( &c_Quat, "set Quat with floats" ); + vmathQPrints( &d_Quat, "set Quat with floats" ); + vmathM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathM3Add( &tmpM3_0, &a_Matrix3, &b_Matrix3 ); + vmathM3Prints( &tmpM3_0, "Matrix3 + Matrix3" ); + vmathM3Sub( &tmpM3_1, &a_Matrix3, &b_Matrix3 ); + vmathM3Prints( &tmpM3_1, "Matrix3 - Matrix3" ); + vmathM3Neg( &tmpM3_2, &a_Matrix3 ); + vmathM3Prints( &tmpM3_2, "-Matrix3" ); + vmathM3ScalarMul( &tmpM3_3, &a_Matrix3, randfloat() ); + vmathM3Prints( &tmpM3_3, "Matrix3 * float" ); + vmathM3ScalarMul( &tmpM3_4, &a_Matrix3, randfloat() ); + vmathM3Prints( &tmpM3_4, "float * Matrix3" ); + vmathM3MulV3( &tmpV3_8, &a_Matrix3, &a_Vector3 ); + vmathV3Prints( &tmpV3_8, "Matrix3 * Vector3" ); + vmathM3Mul( &tmpM3_5, &a_Matrix3, &b_Matrix3 ); + vmathM3Prints( &tmpM3_5, "Matrix3 * Matrix3" ); +} + +void +Matrix4_methods_test() +{ + VmathMatrix3 a_Matrix3, b_Matrix3; + VmathMatrix4 a_Matrix4, b_Matrix4; + VmathTransform3 a_Transform3, b_Transform3; + VmathMatrix4 tmpM4_0, tmpM4_1, tmpM4_2, tmpM4_3, tmpM4_4, tmpM4_5, tmpM4_6; + VmathVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathQuat a_Quat, b_Quat, c_Quat, d_Quat; + VmathVector4 tmpV4; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5, tmpV3_6, tmpV3_7; + VmathVector4 tmpV4_0, tmpV4_1, tmpV4_2; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &a_Vector3, pad ); + vmathV4GetXYZ( &a_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &b_Vector3, pad ); + vmathV4GetXYZ( &b_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &c_Vector3, pad ); + vmathV4GetXYZ( &c_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &d_Vector3, pad ); + vmathV4GetXYZ( &d_Vector3, &tmpV4 ); + vmathV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathV3MakeFromP3( &tmpV3_0, &a_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_0, pad ); + vmathV4GetXYZ( &tmpV3_1, &tmpV4 ); + vmathP3MakeFromV3( &a_Point3, &tmpV3_1 ); + vmathV3MakeFromP3( &tmpV3_2, &b_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_2, pad ); + vmathV4GetXYZ( &tmpV3_3, &tmpV4 ); + vmathP3MakeFromV3( &b_Point3, &tmpV3_3 ); + vmathV3MakeFromP3( &tmpV3_4, &c_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_4, pad ); + vmathV4GetXYZ( &tmpV3_5, &tmpV4 ); + vmathP3MakeFromV3( &c_Point3, &tmpV3_5 ); + vmathV3MakeFromP3( &tmpV3_6, &d_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_6, pad ); + vmathV4GetXYZ( &tmpV3_7, &tmpV4 ); + vmathP3MakeFromV3( &d_Point3, &tmpV3_7 ); + vmathP3Prints( &a_Point3, "set Point3 with floats" ); + vmathP3Prints( &b_Point3, "set Point3 with floats" ); + vmathP3Prints( &c_Point3, "set Point3 with floats" ); + vmathP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathQPrints( &a_Quat, "set Quat with floats" ); + vmathQPrints( &b_Quat, "set Quat with floats" ); + vmathQPrints( &c_Quat, "set Quat with floats" ); + vmathQPrints( &d_Quat, "set Quat with floats" ); + vmathM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathM4Add( &tmpM4_0, &a_Matrix4, &b_Matrix4 ); + vmathM4Prints( &tmpM4_0, "Matrix4 + Matrix4" ); + vmathM4Sub( &tmpM4_1, &a_Matrix4, &b_Matrix4 ); + vmathM4Prints( &tmpM4_1, "Matrix4 - Matrix4" ); + vmathM4Neg( &tmpM4_2, &a_Matrix4 ); + vmathM4Prints( &tmpM4_2, "-Matrix4" ); + vmathM4ScalarMul( &tmpM4_3, &a_Matrix4, randfloat() ); + vmathM4Prints( &tmpM4_3, "Matrix4 * float" ); + vmathM4ScalarMul( &tmpM4_4, &a_Matrix4, randfloat() ); + vmathM4Prints( &tmpM4_4, "float * Matrix4" ); + vmathM4MulV4( &tmpV4_0, &a_Matrix4, &a_Vector4 ); + vmathV4Prints( &tmpV4_0, "Matrix4 * Vector4" ); + vmathM4MulV3( &tmpV4_1, &a_Matrix4, &a_Vector3 ); + vmathV4Prints( &tmpV4_1, "Matrix4 * Vector3" ); + vmathM4MulP3( &tmpV4_2, &a_Matrix4, &a_Point3 ); + vmathV4Prints( &tmpV4_2, "Matrix4 * Point3" ); + vmathM4Mul( &tmpM4_5, &a_Matrix4, &b_Matrix4 ); + vmathM4Prints( &tmpM4_5, "Matrix4 * Matrix4" ); + vmathM4MulT3( &tmpM4_6, &a_Matrix4, &b_Transform3 ); + vmathM4Prints( &tmpM4_6, "Matrix4 * Transform3" ); +} + +void +Transform3_methods_test() +{ + VmathMatrix3 a_Matrix3, b_Matrix3; + VmathMatrix4 a_Matrix4, b_Matrix4; + VmathTransform3 a_Transform3, b_Transform3, tmpT3_0; + VmathVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathQuat a_Quat, b_Quat, c_Quat, d_Quat; + VmathVector4 tmpV4; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5, tmpV3_6, tmpV3_7, tmpV3_8; + VmathPoint3 tmpP3_0; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &a_Vector3, pad ); + vmathV4GetXYZ( &a_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &b_Vector3, pad ); + vmathV4GetXYZ( &b_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &c_Vector3, pad ); + vmathV4GetXYZ( &c_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &d_Vector3, pad ); + vmathV4GetXYZ( &d_Vector3, &tmpV4 ); + vmathV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathV3MakeFromP3( &tmpV3_0, &a_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_0, pad ); + vmathV4GetXYZ( &tmpV3_1, &tmpV4 ); + vmathP3MakeFromV3( &a_Point3, &tmpV3_1 ); + vmathV3MakeFromP3( &tmpV3_2, &b_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_2, pad ); + vmathV4GetXYZ( &tmpV3_3, &tmpV4 ); + vmathP3MakeFromV3( &b_Point3, &tmpV3_3 ); + vmathV3MakeFromP3( &tmpV3_4, &c_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_4, pad ); + vmathV4GetXYZ( &tmpV3_5, &tmpV4 ); + vmathP3MakeFromV3( &c_Point3, &tmpV3_5 ); + vmathV3MakeFromP3( &tmpV3_6, &d_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_6, pad ); + vmathV4GetXYZ( &tmpV3_7, &tmpV4 ); + vmathP3MakeFromV3( &d_Point3, &tmpV3_7 ); + vmathP3Prints( &a_Point3, "set Point3 with floats" ); + vmathP3Prints( &b_Point3, "set Point3 with floats" ); + vmathP3Prints( &c_Point3, "set Point3 with floats" ); + vmathP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathQPrints( &a_Quat, "set Quat with floats" ); + vmathQPrints( &b_Quat, "set Quat with floats" ); + vmathQPrints( &c_Quat, "set Quat with floats" ); + vmathQPrints( &d_Quat, "set Quat with floats" ); + vmathM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathT3MulV3( &tmpV3_8, &a_Transform3, &a_Vector3 ); + vmathV3Prints( &tmpV3_8, "Transform3 * Vector3" ); + vmathT3MulP3( &tmpP3_0, &a_Transform3, &a_Point3 ); + vmathP3Prints( &tmpP3_0, "Transform3 * Point3" ); + vmathT3Mul( &tmpT3_0, &a_Transform3, &b_Transform3 ); + vmathT3Prints( &tmpT3_0, "Transform3 * Transform3" ); +} + +int main() +{ + int i; + printf("\n __begin__ \n"); + for ( i = 0; i < 2; i++ ) { + Matrix3_methods_test(); + Matrix4_methods_test(); + Transform3_methods_test(); + } + printf("\n __end__ \n"); + return 0; +} diff --git a/Extras/vectormathlibrary/tests/test3_aos_cpp.cpp b/Extras/vectormathlibrary/tests/test3_aos_cpp.cpp new file mode 100644 index 0000000..09427d4 --- /dev/null +++ b/Extras/vectormathlibrary/tests/test3_aos_cpp.cpp @@ -0,0 +1,476 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +#define _VECTORMATH_AOS_TEST + +#include "vectormath_aos.h" +#include "test.h" + +int iteration = 0; + +using namespace Vectormath; +using namespace Vectormath::Aos; + +void +Matrix3_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + Vector4 tmpV4; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( a_Vector3, pad ); + a_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( b_Vector3, pad ); + b_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( c_Vector3, pad ); + c_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( d_Vector3, pad ); + d_Vector3 = tmpV4.getXYZ( ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( Vector3( a_Point3 ), pad ); + a_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( b_Point3 ), pad ); + b_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( c_Point3 ), pad ); + c_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( d_Point3 ), pad ); + d_Point3 = Point3( tmpV4.getXYZ( ) ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + print( ( a_Matrix3 + b_Matrix3 ), "Matrix3 + Matrix3" ); + print( ( a_Matrix3 - b_Matrix3 ), "Matrix3 - Matrix3" ); + print( ( -a_Matrix3 ), "-Matrix3" ); + print( ( a_Matrix3 * randfloat() ), "Matrix3 * float" ); + print( ( randfloat() * a_Matrix3 ), "float * Matrix3" ); + print( ( a_Matrix3 * a_Vector3 ), "Matrix3 * Vector3" ); + print( ( a_Matrix3 * b_Matrix3 ), "Matrix3 * Matrix3" ); +} + +void +Matrix4_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + Vector4 tmpV4; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( a_Vector3, pad ); + a_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( b_Vector3, pad ); + b_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( c_Vector3, pad ); + c_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( d_Vector3, pad ); + d_Vector3 = tmpV4.getXYZ( ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( Vector3( a_Point3 ), pad ); + a_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( b_Point3 ), pad ); + b_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( c_Point3 ), pad ); + c_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( d_Point3 ), pad ); + d_Point3 = Point3( tmpV4.getXYZ( ) ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + print( ( a_Matrix4 + b_Matrix4 ), "Matrix4 + Matrix4" ); + print( ( a_Matrix4 - b_Matrix4 ), "Matrix4 - Matrix4" ); + print( ( -a_Matrix4 ), "-Matrix4" ); + print( ( a_Matrix4 * randfloat() ), "Matrix4 * float" ); + print( ( randfloat() * a_Matrix4 ), "float * Matrix4" ); + print( ( a_Matrix4 * a_Vector4 ), "Matrix4 * Vector4" ); + print( ( a_Matrix4 * a_Vector3 ), "Matrix4 * Vector3" ); + print( ( a_Matrix4 * a_Point3 ), "Matrix4 * Point3" ); + print( ( a_Matrix4 * b_Matrix4 ), "Matrix4 * Matrix4" ); + print( ( a_Matrix4 * b_Transform3 ), "Matrix4 * Transform3" ); +} + +void +Transform3_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + Vector4 tmpV4; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( a_Vector3, pad ); + a_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( b_Vector3, pad ); + b_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( c_Vector3, pad ); + c_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( d_Vector3, pad ); + d_Vector3 = tmpV4.getXYZ( ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( Vector3( a_Point3 ), pad ); + a_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( b_Point3 ), pad ); + b_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( c_Point3 ), pad ); + c_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( d_Point3 ), pad ); + d_Point3 = Point3( tmpV4.getXYZ( ) ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + print( ( a_Transform3 * a_Vector3 ), "Transform3 * Vector3" ); + print( ( a_Transform3 * a_Point3 ), "Transform3 * Point3" ); + print( ( a_Transform3 * b_Transform3 ), "Transform3 * Transform3" ); +} + +int main() +{ + int i; + printf("\n __begin__ \n"); + for ( i = 0; i < 2; i++ ) { + Matrix3_methods_test(); + Matrix4_methods_test(); + Transform3_methods_test(); + } + printf("\n __end__ \n"); + return 0; +} diff --git a/Extras/vectormathlibrary/tests/test3_reference.txt b/Extras/vectormathlibrary/tests/test3_reference.txt new file mode 100644 index 0000000..834b0fe --- /dev/null +++ b/Extras/vectormathlibrary/tests/test3_reference.txt @@ -0,0 +1,392 @@ +set Vector3 with floats: ( -0.658344 0.499804 -0.807257 ) +set Vector3 with floats: ( 0.740930 0.154607 0.571599 ) +set Vector3 with floats: ( 0.384388 -0.262467 0.747808 ) +set Vector3 with floats: ( 0.490190 -0.107908 -0.292544 ) +set Vector4 with floats: ( 0.465039 -0.479556 -0.211412 0.553580 ) +set Vector4 with floats: ( 0.690070 0.151576 0.431077 -0.833992 ) +set Vector4 with floats: ( -0.088350 -0.780106 0.090456 -0.218627 ) +set Vector4 with floats: ( 0.137171 0.918133 0.735438 -0.673621 ) +set Point3 with floats: ( -0.448982 -0.479278 0.848189 ) +set Point3 with floats: ( -0.128155 0.578922 -0.744766 ) +set Point3 with floats: ( -0.835589 0.881284 -0.948850 ) +set Point3 with floats: ( -0.691578 -0.235635 -0.690527 ) +set Quat with floats: ( 0.058667 0.753697 -0.138777 -0.472188 ) +set Quat with floats: ( -0.372811 0.540183 -0.785218 0.542085 ) +set Quat with floats: ( 0.410391 -0.562721 0.523588 -0.176574 ) +set Quat with floats: ( 0.297654 0.859913 0.004837 0.374881 ) +set Matrix3 columns: +( -0.658344 0.740930 0.384388 ) +( 0.499804 0.154607 -0.262467 ) +( -0.807257 0.571599 0.747808 ) +set Matrix3 columns: +( 0.490190 -0.658344 0.740930 ) +( -0.107908 0.499804 0.154607 ) +( -0.292544 -0.807257 0.571599 ) +set Matrix4 columns: +( 0.465039 0.690070 -0.088350 0.137171 ) +( -0.479556 0.151576 -0.780106 0.918133 ) +( -0.211412 0.431077 0.090456 0.735438 ) +( 0.553580 -0.833992 -0.218627 -0.673621 ) +set Matrix4 columns: +( 0.137171 0.465039 0.690070 -0.088350 ) +( 0.918133 -0.479556 0.151576 -0.780106 ) +( 0.735438 -0.211412 0.431077 0.090456 ) +( -0.673621 0.553580 -0.833992 -0.218627 ) +set Transform3 columns: +( -0.658344 0.740930 0.384388 0.490190 ) +( 0.499804 0.154607 -0.262467 -0.107908 ) +( -0.807257 0.571599 0.747808 -0.292544 ) +set Transform3 columns: +( 0.490190 -0.658344 0.740930 0.384388 ) +( -0.107908 0.499804 0.154607 -0.262467 ) +( -0.292544 -0.807257 0.571599 0.747808 ) +Matrix3 + Matrix3: +( -0.168154 0.082587 1.125319 ) +( 0.391896 0.654411 -0.107860 ) +( -1.099800 -0.235658 1.319407 ) +Matrix3 - Matrix3: +( -1.148534 1.399274 -0.356542 ) +( 0.607712 -0.345197 -0.417075 ) +( -0.514713 1.378855 0.176210 ) +-Matrix3: +( 0.658344 -0.740930 -0.384388 ) +( -0.499804 -0.154607 0.262467 ) +( 0.807257 -0.571599 -0.747808 ) +Matrix3 * float: +( 0.084148 -0.094704 -0.049132 ) +( -0.063884 -0.019762 0.033548 ) +( 0.103182 -0.073061 -0.095583 ) +float * Matrix3: +( -0.142598 0.160487 0.083259 ) +( 0.108258 0.033488 -0.056851 ) +( -0.174853 0.123809 0.161977 ) +Matrix3 * Vector3: ( 0.493437 -0.039891 0.213467 ) +Matrix3 * Matrix3: +( -0.515117 0.493437 -0.153518 ) +( 0.305099 -0.039891 0.244197 ) +( -0.676156 0.213467 -0.082302 ) +set Vector3 with floats: ( 0.153117 0.265243 -0.073149 ) +set Vector3 with floats: ( 0.264488 -0.723410 0.921523 ) +set Vector3 with floats: ( -0.711250 -0.106634 -0.350831 ) +set Vector3 with floats: ( 0.905168 -0.283632 -0.203584 ) +set Vector4 with floats: ( -0.797437 0.910171 0.969234 0.151940 ) +set Vector4 with floats: ( 0.731827 -0.700248 0.818301 0.302505 ) +set Vector4 with floats: ( -0.872278 0.909999 0.932526 0.571087 ) +set Vector4 with floats: ( 0.610330 0.142507 -0.434829 0.925102 ) +set Point3 with floats: ( 0.158954 -0.126283 -0.249128 ) +set Point3 with floats: ( 0.846815 -0.942601 0.537720 ) +set Point3 with floats: ( 0.446214 0.181939 -0.148223 ) +set Point3 with floats: ( 0.284286 0.493525 -0.861963 ) +set Quat with floats: ( -0.893410 0.548627 0.407007 -0.757467 ) +set Quat with floats: ( -0.393126 -0.850984 0.375720 -0.270088 ) +set Quat with floats: ( 0.458888 -0.610828 -0.690816 -0.676415 ) +set Quat with floats: ( 0.664466 0.101874 -0.365714 0.055473 ) +set Matrix3 columns: +( 0.153117 0.264488 -0.711250 ) +( 0.265243 -0.723410 -0.106634 ) +( -0.073149 0.921523 -0.350831 ) +set Matrix3 columns: +( 0.905168 0.153117 0.264488 ) +( -0.283632 0.265243 -0.723410 ) +( -0.203584 -0.073149 0.921523 ) +set Matrix4 columns: +( -0.797437 0.731827 -0.872278 0.610330 ) +( 0.910171 -0.700248 0.909999 0.142507 ) +( 0.969234 0.818301 0.932526 -0.434829 ) +( 0.151940 0.302505 0.571087 0.925102 ) +set Matrix4 columns: +( 0.610330 -0.797437 0.731827 -0.872278 ) +( 0.142507 0.910171 -0.700248 0.909999 ) +( -0.434829 0.969234 0.818301 0.932526 ) +( 0.925102 0.151940 0.302505 0.571087 ) +set Transform3 columns: +( 0.153117 0.264488 -0.711250 0.905168 ) +( 0.265243 -0.723410 -0.106634 -0.283632 ) +( -0.073149 0.921523 -0.350831 -0.203584 ) +set Transform3 columns: +( 0.905168 0.153117 0.264488 -0.711250 ) +( -0.283632 0.265243 -0.723410 -0.106634 ) +( -0.203584 -0.073149 0.921523 -0.350831 ) +Matrix4 + Matrix4: +( -0.187107 -0.065609 -0.140451 -0.261949 ) +( 1.052679 0.209923 0.209751 1.052506 ) +( 0.534405 1.787535 1.750826 0.497697 ) +( 1.077042 0.454445 0.873592 1.496189 ) +Matrix4 - Matrix4: +( -1.407767 1.529264 -1.604106 1.482608 ) +( 0.767664 -1.610420 1.610247 -0.767491 ) +( 1.404062 -0.150933 0.114225 -1.367354 ) +( -0.773162 0.150565 0.268582 0.354015 ) +-Matrix4: +( 0.797437 -0.731827 0.872278 -0.610330 ) +( -0.910171 0.700248 -0.909999 -0.142507 ) +( -0.969234 -0.818301 -0.932526 0.434829 ) +( -0.151940 -0.302505 -0.571087 -0.925102 ) +Matrix4 * float: +( 0.106503 -0.097740 0.116498 -0.081513 ) +( -0.121559 0.093522 -0.121536 -0.019033 ) +( -0.129447 -0.109289 -0.124544 0.058074 ) +( -0.020293 -0.040401 -0.076272 -0.123553 ) +float * Matrix4: +( 0.456647 -0.419076 0.499504 -0.349501 ) +( -0.521203 0.400992 -0.521105 -0.081606 ) +( -0.555025 -0.468594 -0.534004 0.249002 ) +( -0.087007 -0.173227 -0.327029 -0.529753 ) +Matrix4 * Vector4: ( 0.549286 -0.459496 0.809659 0.848246 ) +Matrix4 * Vector3: ( 0.135817 -0.112939 0.297242 0.061728 ) +Matrix4 * Point3: ( 0.608465 0.148906 -0.616420 0.768779 ) +Matrix4 * Matrix4: +( 0.561500 0.549286 -1.625205 0.896678 ) +( 0.191855 -0.459496 1.944198 -0.501167 ) +( -0.099583 0.809659 0.767847 0.520490 ) +( 0.743332 0.848246 0.646534 1.203612 ) +Matrix4 * Transform3: +( -0.751803 0.135817 -1.544148 1.405491 ) +( 0.837210 -0.112939 1.585880 -0.749438 ) +( 0.455376 0.297242 0.523727 -1.538614 ) +( -0.064533 0.061728 0.347621 0.584422 ) +set Vector3 with floats: ( 0.459209 -0.997261 0.172409 ) +set Vector3 with floats: ( -0.045124 0.879716 0.524317 ) +set Vector3 with floats: ( -0.744532 -0.970444 -0.000013 ) +set Vector3 with floats: ( 0.689543 0.704297 -0.817983 ) +set Vector4 with floats: ( 0.715505 0.577868 0.156952 -0.801022 ) +set Vector4 with floats: ( 0.656335 0.494393 0.816743 0.024285 ) +set Vector4 with floats: ( 0.769132 0.923895 0.133022 -0.052219 ) +set Vector4 with floats: ( -0.164886 0.300690 0.760403 0.171869 ) +set Point3 with floats: ( -0.554976 0.998693 -0.681641 ) +set Point3 with floats: ( 0.391195 0.403059 0.972411 ) +set Point3 with floats: ( 0.297195 0.309761 0.688408 ) +set Point3 with floats: ( 0.363540 0.940297 -0.336683 ) +set Quat with floats: ( 0.600164 -0.681272 0.726558 0.205513 ) +set Quat with floats: ( -0.160082 0.962714 0.737794 -0.071926 ) +set Quat with floats: ( -0.506313 0.689277 0.686485 0.473013 ) +set Quat with floats: ( -0.735610 -0.046390 0.568674 -0.004815 ) +set Matrix3 columns: +( 0.459209 -0.045124 -0.744532 ) +( -0.997261 0.879716 -0.970444 ) +( 0.172409 0.524317 -0.000013 ) +set Matrix3 columns: +( 0.689543 0.459209 -0.045124 ) +( 0.704297 -0.997261 0.879716 ) +( -0.817983 0.172409 0.524317 ) +set Matrix4 columns: +( 0.715505 0.656335 0.769132 -0.164886 ) +( 0.577868 0.494393 0.923895 0.300690 ) +( 0.156952 0.816743 0.133022 0.760403 ) +( -0.801022 0.024285 -0.052219 0.171869 ) +set Matrix4 columns: +( -0.164886 0.715505 0.656335 0.769132 ) +( 0.300690 0.577868 0.494393 0.923895 ) +( 0.760403 0.156952 0.816743 0.133022 ) +( 0.171869 -0.801022 0.024285 -0.052219 ) +set Transform3 columns: +( 0.459209 -0.045124 -0.744532 0.689543 ) +( -0.997261 0.879716 -0.970444 0.704297 ) +( 0.172409 0.524317 -0.000013 -0.817983 ) +set Transform3 columns: +( 0.689543 0.459209 -0.045124 -0.744532 ) +( 0.704297 -0.997261 0.879716 -0.970444 ) +( -0.817983 0.172409 0.524317 -0.000013 ) +Transform3 * Vector3: ( 0.127510 -1.502572 -0.443712 ) +Transform3 * Point3: ( 0.897132 2.797814 -0.390025 ) +Transform3 * Transform3: +( 0.893878 0.127510 -0.450789 0.391447 ) +( 0.725733 -1.502572 0.310080 0.593088 ) +( 0.488169 -0.443712 0.453463 -1.455167 ) +set Vector3 with floats: ( 0.137637 -0.111879 -0.929543 ) +set Vector3 with floats: ( -0.336303 -0.146740 0.165140 ) +set Vector3 with floats: ( -0.823874 0.349776 0.174872 ) +set Vector3 with floats: ( -0.528584 0.489292 0.916708 ) +set Vector4 with floats: ( 0.728511 -0.851140 0.079620 -0.234370 ) +set Vector4 with floats: ( -0.996308 0.433229 -0.892684 -0.957911 ) +set Vector4 with floats: ( 0.517122 0.257921 0.862028 0.095881 ) +set Vector4 with floats: ( -0.171933 -0.214078 -0.604841 -0.383831 ) +set Point3 with floats: ( -0.581500 0.222183 -0.256120 ) +set Point3 with floats: ( -0.678699 -0.079553 0.605960 ) +set Point3 with floats: ( -0.633147 0.435875 -0.046627 ) +set Point3 with floats: ( -0.716491 0.267317 -0.514874 ) +set Quat with floats: ( -0.751700 0.742959 -0.793180 0.508814 ) +set Quat with floats: ( -0.238839 0.113471 -0.843523 -0.245250 ) +set Quat with floats: ( 0.250368 0.579243 -0.157280 0.648487 ) +set Quat with floats: ( 0.103833 0.456401 -0.022372 -0.475631 ) +set Matrix3 columns: +( 0.137637 -0.336303 -0.823874 ) +( -0.111879 -0.146740 0.349776 ) +( -0.929543 0.165140 0.174872 ) +set Matrix3 columns: +( -0.528584 0.137637 -0.336303 ) +( 0.489292 -0.111879 -0.146740 ) +( 0.916708 -0.929543 0.165140 ) +set Matrix4 columns: +( 0.728511 -0.996308 0.517122 -0.171933 ) +( -0.851140 0.433229 0.257921 -0.214078 ) +( 0.079620 -0.892684 0.862028 -0.604841 ) +( -0.234370 -0.957911 0.095881 -0.383831 ) +set Matrix4 columns: +( -0.171933 0.728511 -0.996308 0.517122 ) +( -0.214078 -0.851140 0.433229 0.257921 ) +( -0.604841 0.079620 -0.892684 0.862028 ) +( -0.383831 -0.234370 -0.957911 0.095881 ) +set Transform3 columns: +( 0.137637 -0.336303 -0.823874 -0.528584 ) +( -0.111879 -0.146740 0.349776 0.489292 ) +( -0.929543 0.165140 0.174872 0.916708 ) +set Transform3 columns: +( -0.528584 0.137637 -0.336303 -0.823874 ) +( 0.489292 -0.111879 -0.146740 0.349776 ) +( 0.916708 -0.929543 0.165140 0.174872 ) +Matrix3 + Matrix3: +( -0.390948 -0.198667 -1.160178 ) +( 0.377413 -0.258619 0.203036 ) +( -0.012835 -0.764402 0.340013 ) +Matrix3 - Matrix3: +( 0.666221 -0.473940 -0.487571 ) +( -0.601171 -0.034861 0.496517 ) +( -1.846250 1.094683 0.009732 ) +-Matrix3: +( -0.137637 0.336303 0.823874 ) +( 0.111879 0.146740 -0.349776 ) +( 0.929543 -0.165140 -0.174872 ) +Matrix3 * float: +( -0.000575 0.001405 0.003442 ) +( 0.000467 0.000613 -0.001461 ) +( 0.003884 -0.000690 -0.000731 ) +float * Matrix3: +( -0.002872 0.007017 0.017190 ) +( 0.002334 0.003062 -0.007298 ) +( 0.019395 -0.003446 -0.003649 ) +Matrix3 * Vector3: ( 0.822395 -0.324114 -0.308966 ) +Matrix3 * Matrix3: +( -0.992555 0.822395 -0.132993 ) +( 0.307981 -0.324114 0.116920 ) +( 0.732450 -0.308966 0.317254 ) +set Vector3 with floats: ( -0.016997 0.699144 0.837796 ) +set Vector3 with floats: ( -0.276082 0.091582 0.209064 ) +set Vector3 with floats: ( 0.219317 -0.118359 0.413442 ) +set Vector3 with floats: ( -0.567698 0.531358 -0.387226 ) +set Vector4 with floats: ( 0.572490 -0.820417 0.797191 0.867178 ) +set Vector4 with floats: ( 0.934764 0.237092 -0.866162 -0.773939 ) +set Vector4 with floats: ( 0.261311 -0.851570 0.114814 -0.531592 ) +set Vector4 with floats: ( 0.223925 0.869105 0.143405 0.148518 ) +set Point3 with floats: ( -0.071136 -0.758292 -0.527633 ) +set Point3 with floats: ( 0.997215 0.114440 0.727558 ) +set Point3 with floats: ( -0.425760 0.459888 0.642516 ) +set Point3 with floats: ( -0.022534 0.186095 -0.775679 ) +set Quat with floats: ( -0.683401 0.398134 0.189642 0.765986 ) +set Quat with floats: ( -0.137795 -0.579844 -0.635647 0.374970 ) +set Quat with floats: ( -0.563750 -0.471075 -0.553800 -0.014688 ) +set Quat with floats: ( -0.464365 -0.107890 -0.527503 -0.406423 ) +set Matrix3 columns: +( -0.016997 -0.276082 0.219317 ) +( 0.699144 0.091582 -0.118359 ) +( 0.837796 0.209064 0.413442 ) +set Matrix3 columns: +( -0.567698 -0.016997 -0.276082 ) +( 0.531358 0.699144 0.091582 ) +( -0.387226 0.837796 0.209064 ) +set Matrix4 columns: +( 0.572490 0.934764 0.261311 0.223925 ) +( -0.820417 0.237092 -0.851570 0.869105 ) +( 0.797191 -0.866162 0.114814 0.143405 ) +( 0.867178 -0.773939 -0.531592 0.148518 ) +set Matrix4 columns: +( 0.223925 0.572490 0.934764 0.261311 ) +( 0.869105 -0.820417 0.237092 -0.851570 ) +( 0.143405 0.797191 -0.866162 0.114814 ) +( 0.148518 0.867178 -0.773939 -0.531592 ) +set Transform3 columns: +( -0.016997 -0.276082 0.219317 -0.567698 ) +( 0.699144 0.091582 -0.118359 0.531358 ) +( 0.837796 0.209064 0.413442 -0.387226 ) +set Transform3 columns: +( -0.567698 -0.016997 -0.276082 0.219317 ) +( 0.531358 0.699144 0.091582 -0.118359 ) +( -0.387226 0.837796 0.209064 0.413442 ) +Matrix4 + Matrix4: +( 0.796414 1.507254 1.196075 0.485235 ) +( 0.048687 -0.583325 -0.614477 0.017535 ) +( 0.940596 -0.068971 -0.751347 0.258219 ) +( 1.015695 0.093239 -1.305531 -0.383075 ) +Matrix4 - Matrix4: +( 0.348565 0.362275 -0.673454 -0.037386 ) +( -1.689522 1.057509 -1.088662 1.720674 ) +( 0.653787 -1.663353 0.980976 0.028590 ) +( 0.718660 -1.641117 0.242347 0.680110 ) +-Matrix4: +( -0.572490 -0.934764 -0.261311 -0.223925 ) +( 0.820417 -0.237092 0.851570 -0.869105 ) +( -0.797191 0.866162 -0.114814 -0.143405 ) +( -0.867178 0.773939 0.531592 -0.148518 ) +Matrix4 * float: +( 0.172469 0.281608 0.078723 0.067460 ) +( -0.247160 0.071427 -0.256545 0.261827 ) +( 0.240163 -0.260941 0.034589 0.043202 ) +( 0.261247 -0.233158 -0.160148 0.044743 ) +float * Matrix4: +( 0.285975 0.466942 0.130532 0.111857 ) +( -0.409822 0.118434 -0.425383 0.434143 ) +( 0.398220 -0.432673 0.057353 0.071635 ) +( 0.433180 -0.386605 -0.265545 0.074189 ) +Matrix4 * Vector4: ( -0.036655 -0.589390 1.382884 0.836413 ) +Matrix4 * Vector3: ( 0.862729 -0.533736 -0.522930 -1.001200 ) +Matrix4 * Point3: ( -0.663500 1.196998 0.682919 0.954187 ) +Matrix4 * Matrix4: +( 1.011332 -0.036655 0.357127 -0.735454 ) +( 0.029304 -0.589390 -0.645721 -0.976066 ) +( -0.536511 1.382884 0.329392 0.882861 ) +( -0.532626 0.836413 0.972614 0.745680 ) +Matrix4 * Transform3: +( 0.070508 0.862729 -0.017816 0.346880 ) +( 0.921479 -0.533736 0.070183 0.309037 ) +( -0.957265 -0.522930 -0.275411 0.468230 ) +( -0.697687 -1.001200 -0.421428 0.210525 ) +set Vector3 with floats: ( 0.385180 -0.150218 0.519112 ) +set Vector3 with floats: ( -0.203209 -0.252017 0.282194 ) +set Vector3 with floats: ( 0.067637 0.798376 0.310782 ) +set Vector3 with floats: ( 0.861334 -0.980345 -0.655106 ) +set Vector4 with floats: ( 0.286765 0.532078 0.352671 0.540977 ) +set Vector4 with floats: ( 0.510961 0.791871 -0.564379 0.273199 ) +set Vector4 with floats: ( 0.194378 0.244636 -0.269608 -0.858162 ) +set Vector4 with floats: ( -0.495023 -0.277798 -0.032740 0.007412 ) +set Point3 with floats: ( -0.420178 -0.522577 0.324972 ) +set Point3 with floats: ( 0.795389 0.342900 -0.913636 ) +set Point3 with floats: ( 0.675222 0.144053 -0.632329 ) +set Point3 with floats: ( -0.947120 -0.049367 0.126333 ) +set Quat with floats: ( -0.664206 0.220879 0.284219 -0.387216 ) +set Quat with floats: ( 0.913568 0.531906 0.271995 -0.862601 ) +set Quat with floats: ( -0.738694 0.514248 -0.039363 0.429390 ) +set Quat with floats: ( -0.769469 0.281336 -0.203301 0.412586 ) +set Matrix3 columns: +( 0.385180 -0.203209 0.067637 ) +( -0.150218 -0.252017 0.798376 ) +( 0.519112 0.282194 0.310782 ) +set Matrix3 columns: +( 0.861334 0.385180 -0.203209 ) +( -0.980345 -0.150218 -0.252017 ) +( -0.655106 0.519112 0.282194 ) +set Matrix4 columns: +( 0.286765 0.510961 0.194378 -0.495023 ) +( 0.532078 0.791871 0.244636 -0.277798 ) +( 0.352671 -0.564379 -0.269608 -0.032740 ) +( 0.540977 0.273199 -0.858162 0.007412 ) +set Matrix4 columns: +( -0.495023 0.286765 0.510961 0.194378 ) +( -0.277798 0.532078 0.791871 0.244636 ) +( -0.032740 0.352671 -0.564379 -0.269608 ) +( 0.007412 0.540977 0.273199 -0.858162 ) +set Transform3 columns: +( 0.385180 -0.203209 0.067637 0.861334 ) +( -0.150218 -0.252017 0.798376 -0.980345 ) +( 0.519112 0.282194 0.310782 -0.655106 ) +set Transform3 columns: +( 0.861334 0.385180 -0.203209 0.067637 ) +( -0.980345 -0.150218 -0.252017 0.798376 ) +( -0.655106 0.519112 0.282194 0.310782 ) +Transform3 * Vector3: ( 0.214000 0.394443 0.318891 ) +Transform3 * Point3: ( 0.827662 -0.526078 -0.919697 ) +Transform3 * Transform3: +( 0.486673 0.214000 -0.007973 0.746170 ) +( -0.405345 0.394443 0.319335 -0.943589 ) +( -0.033113 0.318891 -0.088905 -0.298112 ) + + __end__ diff --git a/Extras/vectormathlibrary/tests/test3_soa_c.c b/Extras/vectormathlibrary/tests/test3_soa_c.c new file mode 100644 index 0000000..36cda98 --- /dev/null +++ b/Extras/vectormathlibrary/tests/test3_soa_c.c @@ -0,0 +1,433 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +#define _VECTORMATH_SOA_TEST + +#include "vectormath_soa.h" +#include "test.h" + +int iteration = 0; + +void +Matrix3_methods_test() +{ + VmathSoaMatrix3 a_Matrix3, b_Matrix3; + VmathSoaMatrix4 a_Matrix4, b_Matrix4; + VmathSoaTransform3 a_Transform3, b_Transform3; + VmathSoaMatrix3 tmpM3_0, tmpM3_1, tmpM3_2, tmpM3_3, tmpM3_4, tmpM3_5; + VmathSoaVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathSoaVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathSoaPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathSoaQuat a_Quat, b_Quat, c_Quat, d_Quat; + VmathSoaVector3 tmpV3_0; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathSoaV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathSoaP3Prints( &a_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &b_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &c_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaQPrints( &a_Quat, "set Quat with floats" ); + vmathSoaQPrints( &b_Quat, "set Quat with floats" ); + vmathSoaQPrints( &c_Quat, "set Quat with floats" ); + vmathSoaQPrints( &d_Quat, "set Quat with floats" ); + vmathSoaM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathSoaM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathSoaM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathSoaM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathSoaM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathSoaT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathSoaT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathSoaT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathSoaM3Add( &tmpM3_0, &a_Matrix3, &b_Matrix3 ); + vmathSoaM3Prints( &tmpM3_0, "Matrix3 + Matrix3" ); + vmathSoaM3Sub( &tmpM3_1, &a_Matrix3, &b_Matrix3 ); + vmathSoaM3Prints( &tmpM3_1, "Matrix3 - Matrix3" ); + vmathSoaM3Neg( &tmpM3_2, &a_Matrix3 ); + vmathSoaM3Prints( &tmpM3_2, "-Matrix3" ); + vmathSoaM3ScalarMul( &tmpM3_3, &a_Matrix3, randfloat() ); + vmathSoaM3Prints( &tmpM3_3, "Matrix3 * float" ); + vmathSoaM3ScalarMul( &tmpM3_4, &a_Matrix3, randfloat() ); + vmathSoaM3Prints( &tmpM3_4, "float * Matrix3" ); + vmathSoaM3MulV3( &tmpV3_0, &a_Matrix3, &a_Vector3 ); + vmathSoaV3Prints( &tmpV3_0, "Matrix3 * Vector3" ); + vmathSoaM3Mul( &tmpM3_5, &a_Matrix3, &b_Matrix3 ); + vmathSoaM3Prints( &tmpM3_5, "Matrix3 * Matrix3" ); +} + +void +Matrix4_methods_test() +{ + VmathSoaMatrix3 a_Matrix3, b_Matrix3; + VmathSoaMatrix4 a_Matrix4, b_Matrix4; + VmathSoaTransform3 a_Transform3, b_Transform3; + VmathSoaMatrix4 tmpM4_0, tmpM4_1, tmpM4_2, tmpM4_3, tmpM4_4, tmpM4_5, tmpM4_6; + VmathSoaVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathSoaVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathSoaPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathSoaQuat a_Quat, b_Quat, c_Quat, d_Quat; + VmathSoaVector4 tmpV4_0, tmpV4_1, tmpV4_2; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathSoaV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathSoaP3Prints( &a_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &b_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &c_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaQPrints( &a_Quat, "set Quat with floats" ); + vmathSoaQPrints( &b_Quat, "set Quat with floats" ); + vmathSoaQPrints( &c_Quat, "set Quat with floats" ); + vmathSoaQPrints( &d_Quat, "set Quat with floats" ); + vmathSoaM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathSoaM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathSoaM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathSoaM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathSoaM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathSoaT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathSoaT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathSoaT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathSoaM4Add( &tmpM4_0, &a_Matrix4, &b_Matrix4 ); + vmathSoaM4Prints( &tmpM4_0, "Matrix4 + Matrix4" ); + vmathSoaM4Sub( &tmpM4_1, &a_Matrix4, &b_Matrix4 ); + vmathSoaM4Prints( &tmpM4_1, "Matrix4 - Matrix4" ); + vmathSoaM4Neg( &tmpM4_2, &a_Matrix4 ); + vmathSoaM4Prints( &tmpM4_2, "-Matrix4" ); + vmathSoaM4ScalarMul( &tmpM4_3, &a_Matrix4, randfloat() ); + vmathSoaM4Prints( &tmpM4_3, "Matrix4 * float" ); + vmathSoaM4ScalarMul( &tmpM4_4, &a_Matrix4, randfloat() ); + vmathSoaM4Prints( &tmpM4_4, "float * Matrix4" ); + vmathSoaM4MulV4( &tmpV4_0, &a_Matrix4, &a_Vector4 ); + vmathSoaV4Prints( &tmpV4_0, "Matrix4 * Vector4" ); + vmathSoaM4MulV3( &tmpV4_1, &a_Matrix4, &a_Vector3 ); + vmathSoaV4Prints( &tmpV4_1, "Matrix4 * Vector3" ); + vmathSoaM4MulP3( &tmpV4_2, &a_Matrix4, &a_Point3 ); + vmathSoaV4Prints( &tmpV4_2, "Matrix4 * Point3" ); + vmathSoaM4Mul( &tmpM4_5, &a_Matrix4, &b_Matrix4 ); + vmathSoaM4Prints( &tmpM4_5, "Matrix4 * Matrix4" ); + vmathSoaM4MulT3( &tmpM4_6, &a_Matrix4, &b_Transform3 ); + vmathSoaM4Prints( &tmpM4_6, "Matrix4 * Transform3" ); +} + +void +Transform3_methods_test() +{ + VmathSoaMatrix3 a_Matrix3, b_Matrix3; + VmathSoaMatrix4 a_Matrix4, b_Matrix4; + VmathSoaTransform3 a_Transform3, b_Transform3, tmpT3_0; + VmathSoaVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathSoaVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathSoaPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathSoaQuat a_Quat, b_Quat, c_Quat, d_Quat; + VmathSoaVector3 tmpV3_0; + VmathSoaPoint3 tmpP3_0; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathSoaV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathSoaP3Prints( &a_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &b_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &c_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaQPrints( &a_Quat, "set Quat with floats" ); + vmathSoaQPrints( &b_Quat, "set Quat with floats" ); + vmathSoaQPrints( &c_Quat, "set Quat with floats" ); + vmathSoaQPrints( &d_Quat, "set Quat with floats" ); + vmathSoaM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathSoaM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathSoaM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathSoaM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathSoaM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathSoaT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathSoaT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathSoaT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathSoaT3MulV3( &tmpV3_0, &a_Transform3, &a_Vector3 ); + vmathSoaV3Prints( &tmpV3_0, "Transform3 * Vector3" ); + vmathSoaT3MulP3( &tmpP3_0, &a_Transform3, &a_Point3 ); + vmathSoaP3Prints( &tmpP3_0, "Transform3 * Point3" ); + vmathSoaT3Mul( &tmpT3_0, &a_Transform3, &b_Transform3 ); + vmathSoaT3Prints( &tmpT3_0, "Transform3 * Transform3" ); +} + +int main() +{ + int i; + printf("\n __begin__ \n"); + for ( i = 0; i < 2; i++ ) { + Matrix3_methods_test(); + Matrix4_methods_test(); + Transform3_methods_test(); + } + printf("\n __end__ \n"); + return 0; +} diff --git a/Extras/vectormathlibrary/tests/test3_soa_cpp.cpp b/Extras/vectormathlibrary/tests/test3_soa_cpp.cpp new file mode 100644 index 0000000..dafcad1 --- /dev/null +++ b/Extras/vectormathlibrary/tests/test3_soa_cpp.cpp @@ -0,0 +1,410 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +#define _VECTORMATH_SOA_TEST + +#include "vectormath_soa.h" +#include "test.h" + +int iteration = 0; + +using namespace Vectormath; +using namespace Vectormath::Soa; + +void +Matrix3_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + print( ( a_Matrix3 + b_Matrix3 ), "Matrix3 + Matrix3" ); + print( ( a_Matrix3 - b_Matrix3 ), "Matrix3 - Matrix3" ); + print( ( -a_Matrix3 ), "-Matrix3" ); + print( ( a_Matrix3 * randfloat() ), "Matrix3 * float" ); + print( ( randfloat() * a_Matrix3 ), "float * Matrix3" ); + print( ( a_Matrix3 * a_Vector3 ), "Matrix3 * Vector3" ); + print( ( a_Matrix3 * b_Matrix3 ), "Matrix3 * Matrix3" ); +} + +void +Matrix4_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + print( ( a_Matrix4 + b_Matrix4 ), "Matrix4 + Matrix4" ); + print( ( a_Matrix4 - b_Matrix4 ), "Matrix4 - Matrix4" ); + print( ( -a_Matrix4 ), "-Matrix4" ); + print( ( a_Matrix4 * randfloat() ), "Matrix4 * float" ); + print( ( randfloat() * a_Matrix4 ), "float * Matrix4" ); + print( ( a_Matrix4 * a_Vector4 ), "Matrix4 * Vector4" ); + print( ( a_Matrix4 * a_Vector3 ), "Matrix4 * Vector3" ); + print( ( a_Matrix4 * a_Point3 ), "Matrix4 * Point3" ); + print( ( a_Matrix4 * b_Matrix4 ), "Matrix4 * Matrix4" ); + print( ( a_Matrix4 * b_Transform3 ), "Matrix4 * Transform3" ); +} + +void +Transform3_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + print( ( a_Transform3 * a_Vector3 ), "Transform3 * Vector3" ); + print( ( a_Transform3 * a_Point3 ), "Transform3 * Point3" ); + print( ( a_Transform3 * b_Transform3 ), "Transform3 * Transform3" ); +} + +int main() +{ + int i; + printf("\n __begin__ \n"); + for ( i = 0; i < 2; i++ ) { + Matrix3_methods_test(); + Matrix4_methods_test(); + Transform3_methods_test(); + } + printf("\n __end__ \n"); + return 0; +} diff --git a/Extras/vectormathlibrary/tests/test4_aos_c.c b/Extras/vectormathlibrary/tests/test4_aos_c.c new file mode 100644 index 0000000..94b47f8 --- /dev/null +++ b/Extras/vectormathlibrary/tests/test4_aos_c.c @@ -0,0 +1,567 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +#define _VECTORMATH_AOS_TEST + +#include "vectormath_aos.h" +#include "test.h" + +int iteration = 0; + +void +Matrix3_methods_test() +{ + VmathMatrix3 a_Matrix3, b_Matrix3; + VmathMatrix4 a_Matrix4, b_Matrix4; + VmathTransform3 a_Transform3, b_Transform3; + VmathMatrix3 tmpM3_0, tmpM3_1, tmpM3_2, tmpM3_3, tmpM3_4, tmpM3_5, tmpM3_6, tmpM3_7, tmpM3_8, tmpM3_9, tmpM3_10; + VmathVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathQuat a_Quat, b_Quat, c_Quat, d_Quat; + VmathVector4 tmpV4; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5, tmpV3_6, tmpV3_7, tmpV3_8; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &a_Vector3, pad ); + vmathV4GetXYZ( &a_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &b_Vector3, pad ); + vmathV4GetXYZ( &b_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &c_Vector3, pad ); + vmathV4GetXYZ( &c_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &d_Vector3, pad ); + vmathV4GetXYZ( &d_Vector3, &tmpV4 ); + vmathV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathV3MakeFromP3( &tmpV3_0, &a_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_0, pad ); + vmathV4GetXYZ( &tmpV3_1, &tmpV4 ); + vmathP3MakeFromV3( &a_Point3, &tmpV3_1 ); + vmathV3MakeFromP3( &tmpV3_2, &b_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_2, pad ); + vmathV4GetXYZ( &tmpV3_3, &tmpV4 ); + vmathP3MakeFromV3( &b_Point3, &tmpV3_3 ); + vmathV3MakeFromP3( &tmpV3_4, &c_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_4, pad ); + vmathV4GetXYZ( &tmpV3_5, &tmpV4 ); + vmathP3MakeFromV3( &c_Point3, &tmpV3_5 ); + vmathV3MakeFromP3( &tmpV3_6, &d_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_6, pad ); + vmathV4GetXYZ( &tmpV3_7, &tmpV4 ); + vmathP3MakeFromV3( &d_Point3, &tmpV3_7 ); + vmathP3Prints( &a_Point3, "set Point3 with floats" ); + vmathP3Prints( &b_Point3, "set Point3 with floats" ); + vmathP3Prints( &c_Point3, "set Point3 with floats" ); + vmathP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathQPrints( &a_Quat, "set Quat with floats" ); + vmathQPrints( &b_Quat, "set Quat with floats" ); + vmathQPrints( &c_Quat, "set Quat with floats" ); + vmathQPrints( &d_Quat, "set Quat with floats" ); + vmathM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathM3AppendScale( &tmpM3_0, &a_Matrix3, &a_Vector3 ); + vmathM3Prints( &tmpM3_0, "appendScale Matrix3 Vector3" ); + vmathM3PrependScale( &tmpM3_1, &a_Vector3, &a_Matrix3 ); + vmathM3Prints( &tmpM3_1, "prependScale Vector3 Matrix3" ); + vmathM3MulPerElem( &tmpM3_2, &a_Matrix3, &b_Matrix3 ); + vmathM3Prints( &tmpM3_2, "mulPerElem Matrix3" ); + vmathM3AbsPerElem( &tmpM3_3, &a_Matrix3 ); + vmathM3Prints( &tmpM3_3, "absPerElem Matrix3" ); + vmathM3Transpose( &tmpM3_4, &a_Matrix3 ); + vmathM3Prints( &tmpM3_4, "transpose Matrix3" ); + vmathM3Inverse( &tmpM3_5, &a_Matrix3 ); + vmathM3Prints( &tmpM3_5, "inverse Matrix3" ); + vmathM3Inverse( &tmpM3_6, &a_Matrix3 ); + vmathM3Mul( &tmpM3_7, &tmpM3_6, &a_Matrix3 ); + vmathM3Prints( &tmpM3_7, "inverse(Matrix3) * Matrix3" ); + printf("%f\n", getfloat(vmathM3Determinant( &a_Matrix3 )) ); + vmathV3Outer( &tmpM3_8, &a_Vector3, &b_Vector3 ); + vmathM3Prints( &tmpM3_8, "outer Vector3" ); + vmathV3RowMul( &tmpV3_8, &a_Vector3, &a_Matrix3 ); + vmathV3Prints( &tmpV3_8, "rowMul Vector3" ); + vmathV3CrossMatrix( &tmpM3_9, &a_Vector3 ); + vmathM3Prints( &tmpM3_9, "crossMatrix" ); + vmathV3CrossMatrixMul( &tmpM3_10, &a_Vector3, &a_Matrix3 ); + vmathM3Prints( &tmpM3_10, "crossMatrixMul" ); +} + +void +Matrix4_methods_test() +{ + VmathMatrix3 a_Matrix3, b_Matrix3; + VmathMatrix4 a_Matrix4, b_Matrix4; + VmathTransform3 a_Transform3, b_Transform3; + VmathMatrix4 tmpM4_0, tmpM4_1, tmpM4_2, tmpM4_3, tmpM4_4, tmpM4_5, tmpM4_6, tmpM4_7; + VmathMatrix3 tmpM3_0; + VmathMatrix4 tmpM4_8, tmpM4_9, tmpM4_10, tmpM4_11, tmpM4_12, tmpM4_13, tmpM4_14; + VmathVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathQuat a_Quat, b_Quat, c_Quat, d_Quat; + VmathVector4 tmpV4; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5, tmpV3_6, tmpV3_7; + VmathVector4 tmpV4_0; + VmathQuat tmpQ_0; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &a_Vector3, pad ); + vmathV4GetXYZ( &a_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &b_Vector3, pad ); + vmathV4GetXYZ( &b_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &c_Vector3, pad ); + vmathV4GetXYZ( &c_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &d_Vector3, pad ); + vmathV4GetXYZ( &d_Vector3, &tmpV4 ); + vmathV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathV3MakeFromP3( &tmpV3_0, &a_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_0, pad ); + vmathV4GetXYZ( &tmpV3_1, &tmpV4 ); + vmathP3MakeFromV3( &a_Point3, &tmpV3_1 ); + vmathV3MakeFromP3( &tmpV3_2, &b_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_2, pad ); + vmathV4GetXYZ( &tmpV3_3, &tmpV4 ); + vmathP3MakeFromV3( &b_Point3, &tmpV3_3 ); + vmathV3MakeFromP3( &tmpV3_4, &c_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_4, pad ); + vmathV4GetXYZ( &tmpV3_5, &tmpV4 ); + vmathP3MakeFromV3( &c_Point3, &tmpV3_5 ); + vmathV3MakeFromP3( &tmpV3_6, &d_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_6, pad ); + vmathV4GetXYZ( &tmpV3_7, &tmpV4 ); + vmathP3MakeFromV3( &d_Point3, &tmpV3_7 ); + vmathP3Prints( &a_Point3, "set Point3 with floats" ); + vmathP3Prints( &b_Point3, "set Point3 with floats" ); + vmathP3Prints( &c_Point3, "set Point3 with floats" ); + vmathP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathQPrints( &a_Quat, "set Quat with floats" ); + vmathQPrints( &b_Quat, "set Quat with floats" ); + vmathQPrints( &c_Quat, "set Quat with floats" ); + vmathQPrints( &d_Quat, "set Quat with floats" ); + vmathM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathM4AppendScale( &tmpM4_0, &a_Matrix4, &a_Vector3 ); + vmathM4Prints( &tmpM4_0, "appendScale Matrix4 Vector3" ); + vmathM4PrependScale( &tmpM4_1, &a_Vector3, &a_Matrix4 ); + vmathM4Prints( &tmpM4_1, "prependScale Vector3 Matrix4" ); + vmathM4MulPerElem( &tmpM4_2, &a_Matrix4, &b_Matrix4 ); + vmathM4Prints( &tmpM4_2, "mulPerElem Matrix4" ); + vmathM4AbsPerElem( &tmpM4_3, &a_Matrix4 ); + vmathM4Prints( &tmpM4_3, "absPerElem Matrix4" ); + vmathM4Transpose( &tmpM4_4, &a_Matrix4 ); + vmathM4Prints( &tmpM4_4, "transpose Matrix4" ); + vmathM4Inverse( &tmpM4_5, &a_Matrix4 ); + vmathM4Prints( &tmpM4_5, "inverse Matrix4" ); + vmathM4Inverse( &tmpM4_6, &a_Matrix4 ); + vmathM4Mul( &tmpM4_7, &tmpM4_6, &a_Matrix4 ); + vmathM4Prints( &tmpM4_7, "inverse(Matrix4) * Matrix4" ); + vmathV4MakeFromElems( &tmpV4_0, 0.0f, 0.0f, 0.0f, 1.0f ); + vmathM4SetRow( &a_Matrix4, 3, &tmpV4_0 ); + vmathQNormalize( &tmpQ_0, &a_Quat ); + vmathM3MakeFromQ( &tmpM3_0, &tmpQ_0 ); + vmathM4SetUpper3x3( &a_Matrix4, &tmpM3_0 ); + vmathM4AffineInverse( &tmpM4_8, &a_Matrix4 ); + vmathM4Prints( &tmpM4_8, "affineInverse Matrix4" ); + vmathM4AffineInverse( &tmpM4_9, &a_Matrix4 ); + vmathM4Mul( &tmpM4_10, &tmpM4_9, &a_Matrix4 ); + vmathM4Prints( &tmpM4_10, "affineInverse(Matrix4) * Matrix4" ); + vmathM4OrthoInverse( &tmpM4_11, &a_Matrix4 ); + vmathM4Prints( &tmpM4_11, "orthoInverse Matrix4" ); + vmathM4OrthoInverse( &tmpM4_12, &a_Matrix4 ); + vmathM4Mul( &tmpM4_13, &tmpM4_12, &a_Matrix4 ); + vmathM4Prints( &tmpM4_13, "orthoInverse(Matrix4) * Matrix4" ); + printf("%f\n", getfloat(vmathM4Determinant( &a_Matrix4 )) ); + vmathV4Outer( &tmpM4_14, &a_Vector4, &b_Vector4 ); + vmathM4Prints( &tmpM4_14, "outer Vector4" ); +} + +void +Transform3_methods_test() +{ + VmathMatrix3 a_Matrix3, b_Matrix3; + VmathMatrix4 a_Matrix4, b_Matrix4; + VmathTransform3 a_Transform3, b_Transform3, tmpT3_0, tmpT3_1, tmpT3_2, tmpT3_3, tmpT3_4, tmpT3_5, tmpT3_6; + VmathMatrix3 tmpM3_0; + VmathTransform3 tmpT3_7, tmpT3_8, tmpT3_9; + VmathVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathQuat a_Quat, b_Quat, c_Quat, d_Quat; + VmathVector4 tmpV4; + VmathVector3 tmpV3_0, tmpV3_1, tmpV3_2, tmpV3_3, tmpV3_4, tmpV3_5, tmpV3_6, tmpV3_7; + VmathQuat tmpQ_0; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &a_Vector3, pad ); + vmathV4GetXYZ( &a_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &b_Vector3, pad ); + vmathV4GetXYZ( &b_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &c_Vector3, pad ); + vmathV4GetXYZ( &c_Vector3, &tmpV4 ); + vmathV4MakeFromV3Scalar( &tmpV4, &d_Vector3, pad ); + vmathV4GetXYZ( &d_Vector3, &tmpV4 ); + vmathV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathV3MakeFromP3( &tmpV3_0, &a_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_0, pad ); + vmathV4GetXYZ( &tmpV3_1, &tmpV4 ); + vmathP3MakeFromV3( &a_Point3, &tmpV3_1 ); + vmathV3MakeFromP3( &tmpV3_2, &b_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_2, pad ); + vmathV4GetXYZ( &tmpV3_3, &tmpV4 ); + vmathP3MakeFromV3( &b_Point3, &tmpV3_3 ); + vmathV3MakeFromP3( &tmpV3_4, &c_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_4, pad ); + vmathV4GetXYZ( &tmpV3_5, &tmpV4 ); + vmathP3MakeFromV3( &c_Point3, &tmpV3_5 ); + vmathV3MakeFromP3( &tmpV3_6, &d_Point3 ); + vmathV4MakeFromV3Scalar( &tmpV4, &tmpV3_6, pad ); + vmathV4GetXYZ( &tmpV3_7, &tmpV4 ); + vmathP3MakeFromV3( &d_Point3, &tmpV3_7 ); + vmathP3Prints( &a_Point3, "set Point3 with floats" ); + vmathP3Prints( &b_Point3, "set Point3 with floats" ); + vmathP3Prints( &c_Point3, "set Point3 with floats" ); + vmathP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathQPrints( &a_Quat, "set Quat with floats" ); + vmathQPrints( &b_Quat, "set Quat with floats" ); + vmathQPrints( &c_Quat, "set Quat with floats" ); + vmathQPrints( &d_Quat, "set Quat with floats" ); + vmathM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathT3AppendScale( &tmpT3_0, &a_Transform3, &a_Vector3 ); + vmathT3Prints( &tmpT3_0, "appendScale Transform3 Vector3" ); + vmathT3PrependScale( &tmpT3_1, &a_Vector3, &a_Transform3 ); + vmathT3Prints( &tmpT3_1, "prependScale Vector3 Transform3" ); + vmathT3MulPerElem( &tmpT3_2, &a_Transform3, &b_Transform3 ); + vmathT3Prints( &tmpT3_2, "mulPerElem Transform3" ); + vmathT3AbsPerElem( &tmpT3_3, &a_Transform3 ); + vmathT3Prints( &tmpT3_3, "absPerElem Transform3" ); + vmathT3Inverse( &tmpT3_4, &a_Transform3 ); + vmathT3Prints( &tmpT3_4, "inverse Transform3" ); + vmathT3Inverse( &tmpT3_5, &a_Transform3 ); + vmathT3Mul( &tmpT3_6, &tmpT3_5, &a_Transform3 ); + vmathT3Prints( &tmpT3_6, "inverse(Transform3) * Transform3" ); + vmathQNormalize( &tmpQ_0, &a_Quat ); + vmathM3MakeFromQ( &tmpM3_0, &tmpQ_0 ); + vmathT3SetUpper3x3( &a_Transform3, &tmpM3_0 ); + vmathT3OrthoInverse( &tmpT3_7, &a_Transform3 ); + vmathT3Prints( &tmpT3_7, "orthoInverse Transform3" ); + vmathT3OrthoInverse( &tmpT3_8, &a_Transform3 ); + vmathT3Mul( &tmpT3_9, &tmpT3_8, &a_Transform3 ); + vmathT3Prints( &tmpT3_9, "orthoInverse(Transform3) * Transform3" ); +} + +int main() +{ + int i; + printf("\n __begin__ \n"); + for ( i = 0; i < 2; i++ ) { + Matrix3_methods_test(); + Matrix4_methods_test(); + Transform3_methods_test(); + } + printf("\n __end__ \n"); + return 0; +} diff --git a/Extras/vectormathlibrary/tests/test4_aos_cpp.cpp b/Extras/vectormathlibrary/tests/test4_aos_cpp.cpp new file mode 100644 index 0000000..e55bee0 --- /dev/null +++ b/Extras/vectormathlibrary/tests/test4_aos_cpp.cpp @@ -0,0 +1,492 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +#define _VECTORMATH_AOS_TEST + +#include "vectormath_aos.h" +#include "test.h" + +int iteration = 0; + +using namespace Vectormath; +using namespace Vectormath::Aos; + +void +Matrix3_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + Vector4 tmpV4; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( a_Vector3, pad ); + a_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( b_Vector3, pad ); + b_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( c_Vector3, pad ); + c_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( d_Vector3, pad ); + d_Vector3 = tmpV4.getXYZ( ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( Vector3( a_Point3 ), pad ); + a_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( b_Point3 ), pad ); + b_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( c_Point3 ), pad ); + c_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( d_Point3 ), pad ); + d_Point3 = Point3( tmpV4.getXYZ( ) ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + print( appendScale( a_Matrix3, a_Vector3 ), "appendScale Matrix3 Vector3" ); + print( prependScale( a_Vector3, a_Matrix3 ), "prependScale Vector3 Matrix3" ); + print( mulPerElem( a_Matrix3, b_Matrix3 ), "mulPerElem Matrix3" ); + print( absPerElem( a_Matrix3 ), "absPerElem Matrix3" ); + print( transpose( a_Matrix3 ), "transpose Matrix3" ); + print( inverse( a_Matrix3 ), "inverse Matrix3" ); + print( ( inverse( a_Matrix3 ) * a_Matrix3 ), "inverse(Matrix3) * Matrix3" ); + printf("%f\n", getfloat(determinant( a_Matrix3 )) ); + print( outer( a_Vector3, b_Vector3 ), "outer Vector3" ); + print( rowMul( a_Vector3, a_Matrix3 ), "rowMul Vector3" ); + print( crossMatrix( a_Vector3 ), "crossMatrix" ); + print( crossMatrixMul( a_Vector3, a_Matrix3 ), "crossMatrixMul" ); +} + +void +Matrix4_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + Vector4 tmpV4; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( a_Vector3, pad ); + a_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( b_Vector3, pad ); + b_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( c_Vector3, pad ); + c_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( d_Vector3, pad ); + d_Vector3 = tmpV4.getXYZ( ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( Vector3( a_Point3 ), pad ); + a_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( b_Point3 ), pad ); + b_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( c_Point3 ), pad ); + c_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( d_Point3 ), pad ); + d_Point3 = Point3( tmpV4.getXYZ( ) ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + print( appendScale( a_Matrix4, a_Vector3 ), "appendScale Matrix4 Vector3" ); + print( prependScale( a_Vector3, a_Matrix4 ), "prependScale Vector3 Matrix4" ); + print( mulPerElem( a_Matrix4, b_Matrix4 ), "mulPerElem Matrix4" ); + print( absPerElem( a_Matrix4 ), "absPerElem Matrix4" ); + print( transpose( a_Matrix4 ), "transpose Matrix4" ); + print( inverse( a_Matrix4 ), "inverse Matrix4" ); + print( ( inverse( a_Matrix4 ) * a_Matrix4 ), "inverse(Matrix4) * Matrix4" ); + a_Matrix4.setRow( 3, Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ); + a_Matrix4.setUpper3x3( Matrix3( normalize( a_Quat ) ) ); + print( affineInverse( a_Matrix4 ), "affineInverse Matrix4" ); + print( ( affineInverse( a_Matrix4 ) * a_Matrix4 ), "affineInverse(Matrix4) * Matrix4" ); + print( orthoInverse( a_Matrix4 ), "orthoInverse Matrix4" ); + print( ( orthoInverse( a_Matrix4 ) * a_Matrix4 ), "orthoInverse(Matrix4) * Matrix4" ); + printf("%f\n", getfloat(determinant( a_Matrix4 )) ); + print( outer( a_Vector4, b_Vector4 ), "outer Vector4" ); +} + +void +Transform3_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + Vector4 tmpV4; + float rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6, pad; + // set a pad value to detect invalid use of padding. + // this will be nan for scalar/ppu implementations, max. float for spu + union { float f; unsigned int u; } tmp; + tmp.u = 0x7fffffff; + pad = tmp.f; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( a_Vector3, pad ); + a_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( b_Vector3, pad ); + b_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( c_Vector3, pad ); + c_Vector3 = tmpV4.getXYZ( ); + tmpV4 = Vector4( d_Vector3, pad ); + d_Vector3 = tmpV4.getXYZ( ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + tmpV4 = Vector4( Vector3( a_Point3 ), pad ); + a_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( b_Point3 ), pad ); + b_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( c_Point3 ), pad ); + c_Point3 = Point3( tmpV4.getXYZ( ) ); + tmpV4 = Vector4( Vector3( d_Point3 ), pad ); + d_Point3 = Point3( tmpV4.getXYZ( ) ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + print( appendScale( a_Transform3, a_Vector3 ), "appendScale Transform3 Vector3" ); + print( prependScale( a_Vector3, a_Transform3 ), "prependScale Vector3 Transform3" ); + print( mulPerElem( a_Transform3, b_Transform3 ), "mulPerElem Transform3" ); + print( absPerElem( a_Transform3 ), "absPerElem Transform3" ); + print( inverse( a_Transform3 ), "inverse Transform3" ); + print( ( inverse( a_Transform3 ) * a_Transform3 ), "inverse(Transform3) * Transform3" ); + a_Transform3.setUpper3x3( Matrix3( normalize( a_Quat ) ) ); + print( orthoInverse( a_Transform3 ), "orthoInverse Transform3" ); + print( ( orthoInverse( a_Transform3 ) * a_Transform3 ), "orthoInverse(Transform3) * Transform3" ); +} + +int main() +{ + int i; + printf("\n __begin__ \n"); + for ( i = 0; i < 2; i++ ) { + Matrix3_methods_test(); + Matrix4_methods_test(); + Transform3_methods_test(); + } + printf("\n __end__ \n"); + return 0; +} diff --git a/Extras/vectormathlibrary/tests/test4_reference.txt b/Extras/vectormathlibrary/tests/test4_reference.txt new file mode 100644 index 0000000..23afd2d --- /dev/null +++ b/Extras/vectormathlibrary/tests/test4_reference.txt @@ -0,0 +1,524 @@ +set Vector3 with floats: ( -0.658344 0.499804 -0.807257 ) +set Vector3 with floats: ( 0.740930 0.154607 0.571599 ) +set Vector3 with floats: ( 0.384388 -0.262467 0.747808 ) +set Vector3 with floats: ( 0.490190 -0.107908 -0.292544 ) +set Vector4 with floats: ( 0.465039 -0.479556 -0.211412 0.553580 ) +set Vector4 with floats: ( 0.690070 0.151576 0.431077 -0.833992 ) +set Vector4 with floats: ( -0.088350 -0.780106 0.090456 -0.218627 ) +set Vector4 with floats: ( 0.137171 0.918133 0.735438 -0.673621 ) +set Point3 with floats: ( -0.448982 -0.479278 0.848189 ) +set Point3 with floats: ( -0.128155 0.578922 -0.744766 ) +set Point3 with floats: ( -0.835589 0.881284 -0.948850 ) +set Point3 with floats: ( -0.691578 -0.235635 -0.690527 ) +set Quat with floats: ( 0.058667 0.753697 -0.138777 -0.472188 ) +set Quat with floats: ( -0.372811 0.540183 -0.785218 0.542085 ) +set Quat with floats: ( 0.410391 -0.562721 0.523588 -0.176574 ) +set Quat with floats: ( 0.297654 0.859913 0.004837 0.374881 ) +set Matrix3 columns: +( -0.658344 0.740930 0.384388 ) +( 0.499804 0.154607 -0.262467 ) +( -0.807257 0.571599 0.747808 ) +set Matrix3 columns: +( 0.490190 -0.658344 0.740930 ) +( -0.107908 0.499804 0.154607 ) +( -0.292544 -0.807257 0.571599 ) +set Matrix4 columns: +( 0.465039 0.690070 -0.088350 0.137171 ) +( -0.479556 0.151576 -0.780106 0.918133 ) +( -0.211412 0.431077 0.090456 0.735438 ) +( 0.553580 -0.833992 -0.218627 -0.673621 ) +set Matrix4 columns: +( 0.137171 0.465039 0.690070 -0.088350 ) +( 0.918133 -0.479556 0.151576 -0.780106 ) +( 0.735438 -0.211412 0.431077 0.090456 ) +( -0.673621 0.553580 -0.833992 -0.218627 ) +set Transform3 columns: +( -0.658344 0.740930 0.384388 0.490190 ) +( 0.499804 0.154607 -0.262467 -0.107908 ) +( -0.807257 0.571599 0.747808 -0.292544 ) +set Transform3 columns: +( 0.490190 -0.658344 0.740930 0.384388 ) +( -0.107908 0.499804 0.154607 -0.262467 ) +( -0.292544 -0.807257 0.571599 0.747808 ) +appendScale Matrix3 Vector3: +( 0.433417 0.370320 -0.310300 ) +( -0.329043 0.077273 0.211879 ) +( 0.531453 0.285687 -0.603673 ) +prependScale Vector3 Matrix3: +( 0.433417 -0.487787 -0.253060 ) +( 0.249804 0.077273 -0.131182 ) +( 0.651663 -0.461427 -0.603673 ) +mulPerElem Matrix3: +( -0.322714 -0.487787 0.284805 ) +( -0.053933 0.077273 -0.040579 ) +( 0.236158 -0.461427 0.427446 ) +absPerElem Matrix3: +( 0.658344 0.740930 0.384388 ) +( 0.499804 0.154607 0.262467 ) +( 0.807257 0.571599 0.747808 ) +transpose Matrix3: +( -0.658344 0.499804 -0.807257 ) +( 0.740930 0.154607 0.571599 ) +( 0.384388 -0.262467 0.747808 ) +inverse Matrix3: +( -1.938491 2.439935 1.852797 ) +( 1.181290 1.328230 -0.141021 ) +( -2.995533 1.618649 3.445122 ) +inverse(Matrix3) * Matrix3: +( 1.000000 0.000000 0.000000 ) +( 0.000000 1.000000 -0.000000 ) +( 0.000000 -0.000000 1.000000 ) +-0.137036 +outer Vector3: +( -0.487787 -0.101785 -0.376308 ) +( 0.370320 0.077273 0.285687 ) +( -0.598121 -0.124808 -0.461427 ) +rowMul Vector3: ( 1.334884 -0.871941 -0.987915 ) +crossMatrix: +( 0.000000 0.807257 0.499804 ) +( -0.807257 0.000000 0.658344 ) +( -0.499804 -0.658344 0.000000 ) +crossMatrixMul: +( 0.000000 0.410495 0.161879 ) +( 0.000000 -0.221813 0.182015 ) +( 0.000000 -0.472105 -0.019325 ) +set Vector3 with floats: ( -0.127818 0.216602 0.153117 ) +set Vector3 with floats: ( 0.265243 -0.073149 0.264488 ) +set Vector3 with floats: ( -0.723410 0.921523 -0.711250 ) +set Vector3 with floats: ( -0.106634 -0.350831 0.905168 ) +set Vector4 with floats: ( -0.283632 -0.203584 -0.797437 0.910171 ) +set Vector4 with floats: ( 0.969234 0.151940 0.731827 -0.700248 ) +set Vector4 with floats: ( 0.818301 0.302505 -0.872278 0.909999 ) +set Vector4 with floats: ( 0.932526 0.571087 0.610330 0.142507 ) +set Point3 with floats: ( -0.434829 0.925102 0.158954 ) +set Point3 with floats: ( -0.126283 -0.249128 0.846815 ) +set Point3 with floats: ( -0.942601 0.537720 0.446214 ) +set Point3 with floats: ( 0.181939 -0.148223 0.284286 ) +set Quat with floats: ( 0.493525 -0.861963 -0.893410 0.548627 ) +set Quat with floats: ( 0.407007 -0.757467 -0.393126 -0.850984 ) +set Quat with floats: ( 0.375720 -0.270088 0.458888 -0.610828 ) +set Quat with floats: ( -0.690816 -0.676415 0.664466 0.101874 ) +set Matrix3 columns: +( -0.127818 0.265243 -0.723410 ) +( 0.216602 -0.073149 0.921523 ) +( 0.153117 0.264488 -0.711250 ) +set Matrix3 columns: +( -0.106634 -0.127818 0.265243 ) +( -0.350831 0.216602 -0.073149 ) +( 0.905168 0.153117 0.264488 ) +set Matrix4 columns: +( -0.283632 0.969234 0.818301 0.932526 ) +( -0.203584 0.151940 0.302505 0.571087 ) +( -0.797437 0.731827 -0.872278 0.610330 ) +( 0.910171 -0.700248 0.909999 0.142507 ) +set Matrix4 columns: +( 0.932526 -0.283632 0.969234 0.818301 ) +( 0.571087 -0.203584 0.151940 0.302505 ) +( 0.610330 -0.797437 0.731827 -0.872278 ) +( 0.142507 0.910171 -0.700248 0.909999 ) +set Transform3 columns: +( -0.127818 0.265243 -0.723410 -0.106634 ) +( 0.216602 -0.073149 0.921523 -0.350831 ) +( 0.153117 0.264488 -0.711250 0.905168 ) +set Transform3 columns: +( -0.106634 -0.127818 0.265243 -0.723410 ) +( -0.350831 0.216602 -0.073149 0.921523 ) +( 0.905168 0.153117 0.264488 -0.711250 ) +appendScale Matrix4 Vector3: +( 0.036253 0.209938 0.125296 0.932526 ) +( 0.026022 0.032911 0.046319 0.571087 ) +( 0.101927 0.158515 -0.133561 0.610330 ) +( -0.116336 -0.151675 0.139337 0.142507 ) +prependScale Vector3 Matrix4: +( 0.036253 -0.123886 -0.104594 -0.119194 ) +( -0.044097 0.032911 0.065523 0.123698 ) +( -0.122101 0.112055 -0.133561 0.093452 ) +( 0.910171 -0.700248 0.909999 0.142507 ) +mulPerElem Matrix4: +( -0.264494 -0.274906 0.793125 0.763086 ) +( -0.116264 -0.030933 0.045963 0.172757 ) +( -0.486699 -0.583586 -0.638357 -0.532377 ) +( 0.129706 -0.637346 -0.637225 0.129682 ) +absPerElem Matrix4: +( 0.283632 0.969234 0.818301 0.932526 ) +( 0.203584 0.151940 0.302505 0.571087 ) +( 0.797437 0.731827 0.872278 0.610330 ) +( 0.910171 0.700248 0.909999 0.142507 ) +transpose Matrix4: +( -0.283632 -0.203584 -0.797437 0.910171 ) +( 0.969234 0.151940 0.731827 -0.700248 ) +( 0.818301 0.302505 -0.872278 0.909999 ) +( 0.932526 0.571087 0.610330 0.142507 ) +inverse Matrix4: +( 0.756962 -3.392262 1.563321 1.945501 ) +( 1.235862 -2.616357 0.503558 0.241096 ) +( 0.221503 1.293015 -1.354804 -0.828755 ) +( -0.176291 0.552941 1.140966 1.068388 ) +inverse(Matrix4) * Matrix4: +( 1.000000 0.000000 -0.000000 0.000000 ) +( -0.000000 1.000000 -0.000000 -0.000000 ) +( 0.000000 -0.000000 1.000000 -0.000000 ) +( -0.000000 0.000000 0.000000 1.000000 ) +affineInverse Matrix4: +( -0.477821 -0.877922 0.030662 0.928236 ) +( 0.062087 0.001066 0.998070 -0.667659 ) +( -0.876260 0.478803 0.053999 0.510740 ) +( 0.000000 0.000000 0.000000 1.000000 ) +affineInverse(Matrix4) * Matrix4: +( 1.000000 0.000000 -0.000000 0.000000 ) +( 0.000000 1.000000 0.000000 0.000000 ) +( -0.000000 0.000000 1.000000 0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +orthoInverse Matrix4: +( -0.477822 -0.877922 0.030662 0.928237 ) +( 0.062087 0.001066 0.998070 -0.667659 ) +( -0.876260 0.478803 0.053999 0.510740 ) +( 0.000000 0.000000 0.000000 1.000000 ) +orthoInverse(Matrix4) * Matrix4: +( 1.000000 0.000000 0.000000 0.000000 ) +( 0.000000 1.000000 -0.000000 -0.000000 ) +( 0.000000 -0.000000 1.000000 -0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +1.000000 +outer Vector4: +( -0.274906 -0.043095 -0.207570 0.198613 ) +( -0.197320 -0.030933 -0.148988 0.142559 ) +( -0.772903 -0.121163 -0.583586 0.558404 ) +( 0.882169 0.138292 0.666089 -0.637346 ) +set Vector3 with floats: ( -0.365714 0.055473 -0.133556 ) +set Vector3 with floats: ( -0.572643 0.459209 -0.997261 ) +set Vector3 with floats: ( 0.172409 -0.045124 0.879716 ) +set Vector3 with floats: ( 0.524317 -0.744532 -0.970444 ) +set Vector4 with floats: ( -0.000013 0.689543 0.704297 -0.817983 ) +set Vector4 with floats: ( 0.715505 0.577868 0.156952 -0.801022 ) +set Vector4 with floats: ( 0.656335 0.494393 0.816743 0.024285 ) +set Vector4 with floats: ( 0.769132 0.923895 0.133022 -0.052219 ) +set Point3 with floats: ( -0.164886 0.300690 0.760403 ) +set Point3 with floats: ( 0.171869 -0.554976 0.998693 ) +set Point3 with floats: ( -0.681641 0.391195 0.403059 ) +set Point3 with floats: ( 0.972411 0.297195 0.309761 ) +set Quat with floats: ( 0.688408 0.363540 0.940297 -0.336683 ) +set Quat with floats: ( 0.600164 -0.681272 0.726558 0.205513 ) +set Quat with floats: ( -0.160082 0.962714 0.737794 -0.071926 ) +set Quat with floats: ( -0.506313 0.689277 0.686485 0.473013 ) +set Matrix3 columns: +( -0.365714 -0.572643 0.172409 ) +( 0.055473 0.459209 -0.045124 ) +( -0.133556 -0.997261 0.879716 ) +set Matrix3 columns: +( 0.524317 -0.365714 -0.572643 ) +( -0.744532 0.055473 0.459209 ) +( -0.970444 -0.133556 -0.997261 ) +set Matrix4 columns: +( -0.000013 0.715505 0.656335 0.769132 ) +( 0.689543 0.577868 0.494393 0.923895 ) +( 0.704297 0.156952 0.816743 0.133022 ) +( -0.817983 -0.801022 0.024285 -0.052219 ) +set Matrix4 columns: +( 0.769132 -0.000013 0.715505 0.656335 ) +( 0.923895 0.689543 0.577868 0.494393 ) +( 0.133022 0.704297 0.156952 0.816743 ) +( -0.052219 -0.817983 -0.801022 0.024285 ) +set Transform3 columns: +( -0.365714 -0.572643 0.172409 0.524317 ) +( 0.055473 0.459209 -0.045124 -0.744532 ) +( -0.133556 -0.997261 0.879716 -0.970444 ) +set Transform3 columns: +( 0.524317 -0.365714 -0.572643 0.172409 ) +( -0.744532 0.055473 0.459209 -0.045124 ) +( -0.970444 -0.133556 -0.997261 0.879716 ) +appendScale Transform3 Vector3: +( 0.133747 -0.031766 -0.023026 0.524317 ) +( -0.020287 0.025474 0.006027 -0.744532 ) +( 0.048843 -0.055321 -0.117491 -0.970444 ) +prependScale Vector3 Transform3: +( 0.133747 0.209424 -0.063052 -0.191750 ) +( 0.003077 0.025474 -0.002503 -0.041301 ) +( 0.017837 0.133190 -0.117491 0.129609 ) +mulPerElem Transform3: +( -0.191750 0.209424 -0.098729 0.090397 ) +( -0.041301 0.025474 -0.020721 0.033596 ) +( 0.129609 0.133190 -0.877307 -0.853715 ) +absPerElem Transform3: +( 0.365714 0.572643 0.172409 0.524317 ) +( 0.055473 0.459209 0.045124 0.744532 ) +( 0.133556 0.997261 0.879716 0.970444 ) +inverse Transform3: +( -3.394501 -3.137797 0.504313 -0.066988 ) +( 0.404474 2.824531 0.065611 1.954553 ) +( -0.056825 2.725566 1.287672 3.308679 ) +inverse(Transform3) * Transform3: +( 1.000000 -0.000000 0.000000 0.000000 ) +( 0.000000 1.000000 -0.000000 -0.000000 ) +( -0.000000 -0.000000 1.000000 0.000000 ) +orthoInverse Transform3: +( -0.267562 -0.082713 0.959984 1.010315 ) +( 0.706975 -0.693789 0.137268 -0.754017 ) +( 0.654673 0.715412 0.244108 0.426284 ) +orthoInverse(Transform3) * Transform3: +( 1.000000 0.000000 0.000000 -0.000000 ) +( 0.000000 1.000000 0.000000 -0.000000 ) +( 0.000000 0.000000 1.000000 -0.000000 ) +set Vector3 with floats: ( -0.735610 -0.046390 0.568674 ) +set Vector3 with floats: ( -0.004815 0.137637 -0.111879 ) +set Vector3 with floats: ( -0.929543 -0.336303 -0.146740 ) +set Vector3 with floats: ( 0.165140 -0.823874 0.349776 ) +set Vector4 with floats: ( 0.174872 -0.528584 0.489292 0.916708 ) +set Vector4 with floats: ( 0.728511 -0.851140 0.079620 -0.234370 ) +set Vector4 with floats: ( -0.996308 0.433229 -0.892684 -0.957911 ) +set Vector4 with floats: ( 0.517122 0.257921 0.862028 0.095881 ) +set Point3 with floats: ( -0.171933 -0.214078 -0.604841 ) +set Point3 with floats: ( -0.383831 -0.581500 0.222183 ) +set Point3 with floats: ( -0.256120 -0.678699 -0.079553 ) +set Point3 with floats: ( 0.605960 -0.633147 0.435875 ) +set Quat with floats: ( -0.046627 -0.716491 0.267317 -0.514874 ) +set Quat with floats: ( -0.751700 0.742959 -0.793180 0.508814 ) +set Quat with floats: ( -0.238839 0.113471 -0.843523 -0.245250 ) +set Quat with floats: ( 0.250368 0.579243 -0.157280 0.648487 ) +set Matrix3 columns: +( -0.735610 -0.004815 -0.929543 ) +( -0.046390 0.137637 -0.336303 ) +( 0.568674 -0.111879 -0.146740 ) +set Matrix3 columns: +( 0.165140 -0.735610 -0.004815 ) +( -0.823874 -0.046390 0.137637 ) +( 0.349776 0.568674 -0.111879 ) +set Matrix4 columns: +( 0.174872 0.728511 -0.996308 0.517122 ) +( -0.528584 -0.851140 0.433229 0.257921 ) +( 0.489292 0.079620 -0.892684 0.862028 ) +( 0.916708 -0.234370 -0.957911 0.095881 ) +set Matrix4 columns: +( 0.517122 0.174872 0.728511 -0.996308 ) +( 0.257921 -0.528584 -0.851140 0.433229 ) +( 0.862028 0.489292 0.079620 -0.892684 ) +( 0.095881 0.916708 -0.234370 -0.957911 ) +set Transform3 columns: +( -0.735610 -0.004815 -0.929543 0.165140 ) +( -0.046390 0.137637 -0.336303 -0.823874 ) +( 0.568674 -0.111879 -0.146740 0.349776 ) +set Transform3 columns: +( 0.165140 -0.735610 -0.004815 -0.929543 ) +( -0.823874 -0.046390 0.137637 -0.336303 ) +( 0.349776 0.568674 -0.111879 -0.146740 ) +appendScale Matrix3 Vector3: +( 0.541123 0.000223 -0.528607 ) +( 0.034125 -0.006385 -0.191247 ) +( -0.418323 0.005190 -0.083447 ) +prependScale Vector3 Matrix3: +( 0.541123 0.003542 0.683781 ) +( 0.002152 -0.006385 0.015601 ) +( 0.323390 -0.063623 -0.083447 ) +mulPerElem Matrix3: +( -0.121479 0.003542 0.004475 ) +( 0.038220 -0.006385 -0.046288 ) +( 0.198909 -0.063623 0.016417 ) +absPerElem Matrix3: +( 0.735610 0.004815 0.929543 ) +( 0.046390 0.137637 0.336303 ) +( 0.568674 0.111879 0.146740 ) +transpose Matrix3: +( -0.735610 -0.046390 0.568674 ) +( -0.004815 0.137637 -0.111879 ) +( -0.929543 -0.336303 -0.146740 ) +inverse Matrix3: +( -0.518959 0.927036 1.162799 ) +( -1.777555 5.713095 -1.833313 ) +( -0.655903 -0.763218 -0.910706 ) +inverse(Matrix3) * Matrix3: +( 1.000000 0.000000 0.000000 ) +( -0.000000 1.000000 -0.000000 ) +( -0.000000 0.000000 1.000000 ) +0.111420 +outer Vector3: +( 0.003542 -0.101247 0.082299 ) +( 0.000223 -0.006385 0.005190 ) +( -0.002738 0.078270 -0.063623 ) +rowMul Vector3: ( 0.866665 -0.066466 0.615935 ) +crossMatrix: +( 0.000000 -0.568674 -0.046390 ) +( 0.568674 0.000000 0.735610 ) +( 0.046390 -0.735610 0.000000 ) +crossMatrixMul: +( 0.000000 -0.073080 0.198054 ) +( 0.000000 -0.085037 -0.636550 ) +( 0.000000 -0.101470 0.204267 ) +set Vector3 with floats: ( 0.103833 0.456401 -0.022372 ) +set Vector3 with floats: ( -0.475631 -0.004178 -0.020865 ) +set Vector3 with floats: ( -0.016997 0.699144 0.837796 ) +set Vector3 with floats: ( -0.276082 0.091582 0.209064 ) +set Vector4 with floats: ( 0.219317 -0.118359 0.413442 -0.567698 ) +set Vector4 with floats: ( 0.531358 -0.387226 0.572490 -0.820417 ) +set Vector4 with floats: ( 0.797191 0.867178 0.934764 0.237092 ) +set Vector4 with floats: ( -0.866162 -0.773939 0.261311 -0.851570 ) +set Point3 with floats: ( 0.114814 -0.531592 0.223925 ) +set Point3 with floats: ( 0.869105 0.143405 0.148518 ) +set Point3 with floats: ( -0.071136 -0.758292 -0.527633 ) +set Point3 with floats: ( 0.997215 0.114440 0.727558 ) +set Quat with floats: ( -0.425760 0.459888 0.642516 -0.022534 ) +set Quat with floats: ( 0.186095 -0.775679 -0.683401 0.398134 ) +set Quat with floats: ( 0.189642 0.765986 -0.137795 -0.579844 ) +set Quat with floats: ( -0.635647 0.374970 -0.563750 -0.471075 ) +set Matrix3 columns: +( 0.103833 -0.475631 -0.016997 ) +( 0.456401 -0.004178 0.699144 ) +( -0.022372 -0.020865 0.837796 ) +set Matrix3 columns: +( -0.276082 0.103833 -0.475631 ) +( 0.091582 0.456401 -0.004178 ) +( 0.209064 -0.022372 -0.020865 ) +set Matrix4 columns: +( 0.219317 0.531358 0.797191 -0.866162 ) +( -0.118359 -0.387226 0.867178 -0.773939 ) +( 0.413442 0.572490 0.934764 0.261311 ) +( -0.567698 -0.820417 0.237092 -0.851570 ) +set Matrix4 columns: +( -0.866162 0.219317 0.531358 0.797191 ) +( -0.773939 -0.118359 -0.387226 0.867178 ) +( 0.261311 0.413442 0.572490 0.934764 ) +( -0.851570 -0.567698 -0.820417 0.237092 ) +set Transform3 columns: +( 0.103833 -0.475631 -0.016997 -0.276082 ) +( 0.456401 -0.004178 0.699144 0.091582 ) +( -0.022372 -0.020865 0.837796 0.209064 ) +set Transform3 columns: +( -0.276082 0.103833 -0.475631 -0.016997 ) +( 0.091582 0.456401 -0.004178 0.699144 ) +( 0.209064 -0.022372 -0.020865 0.837796 ) +appendScale Matrix4 Vector3: +( 0.022772 0.242513 -0.017835 -0.866162 ) +( -0.012290 -0.176730 -0.019401 -0.773939 ) +( 0.042929 0.261285 -0.020913 0.261311 ) +( -0.058946 -0.374439 -0.005304 -0.851570 ) +prependScale Vector3 Matrix4: +( 0.022772 0.055173 0.082775 -0.089936 ) +( -0.054019 -0.176730 0.395781 -0.353227 ) +( -0.009250 -0.012808 -0.020913 -0.005846 ) +( -0.567698 -0.820417 0.237092 -0.851570 ) +mulPerElem Matrix4: +( -0.189964 0.116536 0.423594 -0.690497 ) +( 0.091603 0.045832 -0.335794 -0.671143 ) +( 0.108037 0.236691 0.535143 0.244264 ) +( 0.483434 0.465749 -0.194514 -0.201900 ) +absPerElem Matrix4: +( 0.219317 0.531358 0.797191 0.866162 ) +( 0.118359 0.387226 0.867178 0.773939 ) +( 0.413442 0.572490 0.934764 0.261311 ) +( 0.567698 0.820417 0.237092 0.851570 ) +transpose Matrix4: +( 0.219317 -0.118359 0.413442 -0.567698 ) +( 0.531358 -0.387226 0.572490 -0.820417 ) +( 0.797191 0.867178 0.934764 0.237092 ) +( -0.866162 -0.773939 0.261311 -0.851570 ) +inverse Matrix4: +( -0.801304 6.311381 -3.640203 -6.038011 ) +( 1.289204 -3.528897 1.571125 2.378011 ) +( -0.220138 -0.375260 1.356762 0.981293 ) +( -0.769143 -0.912151 1.290834 0.833121 ) +inverse(Matrix4) * Matrix4: +( 1.000000 -0.000000 -0.000000 0.000000 ) +( 0.000000 1.000000 -0.000000 0.000000 ) +( -0.000000 0.000000 1.000000 -0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +affineInverse Matrix4: +( -0.548992 -0.521721 -0.653005 -0.708658 ) +( -0.449878 -0.474001 0.756923 -0.954307 ) +( -0.704428 0.709317 0.025512 -0.067847 ) +( 0.000000 0.000000 0.000000 1.000000 ) +affineInverse(Matrix4) * Matrix4: +( 1.000000 0.000000 0.000000 0.000000 ) +( 0.000000 1.000000 -0.000000 0.000000 ) +( 0.000000 0.000000 1.000000 -0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +orthoInverse Matrix4: +( -0.548992 -0.521721 -0.653005 -0.708658 ) +( -0.449878 -0.474001 0.756923 -0.954307 ) +( -0.704428 0.709317 0.025512 -0.067847 ) +( 0.000000 0.000000 0.000000 1.000000 ) +orthoInverse(Matrix4) * Matrix4: +( 1.000000 0.000000 0.000000 -0.000000 ) +( 0.000000 1.000000 -0.000000 0.000000 ) +( 0.000000 -0.000000 1.000000 0.000000 ) +( 0.000000 0.000000 0.000000 1.000000 ) +1.000000 +outer Vector4: +( 0.116536 -0.084925 0.125557 -0.179931 ) +( -0.062891 0.045832 -0.067760 0.097104 ) +( 0.219686 -0.160095 0.236691 -0.339195 ) +( -0.301651 0.219827 -0.325001 0.465749 ) +set Vector3 with floats: ( -0.553800 -0.014688 -0.464365 ) +set Vector3 with floats: ( -0.107890 -0.527503 -0.406423 ) +set Vector3 with floats: ( 0.301261 0.499529 0.385180 ) +set Vector3 with floats: ( -0.150218 0.519112 -0.203209 ) +set Vector4 with floats: ( -0.252017 0.282194 0.067637 0.798376 ) +set Vector4 with floats: ( 0.310782 0.861334 -0.980345 -0.655106 ) +set Vector4 with floats: ( 0.286765 0.532078 0.352671 0.540977 ) +set Vector4 with floats: ( 0.510961 0.791871 -0.564379 0.273199 ) +set Point3 with floats: ( 0.194378 0.244636 -0.269608 ) +set Point3 with floats: ( -0.858162 -0.495023 -0.277798 ) +set Point3 with floats: ( -0.032740 0.007412 -0.420178 ) +set Point3 with floats: ( -0.522577 0.324972 0.795389 ) +set Quat with floats: ( 0.342900 -0.913636 0.675222 0.144053 ) +set Quat with floats: ( -0.632329 -0.947120 -0.049367 0.126333 ) +set Quat with floats: ( -0.664206 0.220879 0.284219 -0.387216 ) +set Quat with floats: ( 0.913568 0.531906 0.271995 -0.862601 ) +set Matrix3 columns: +( -0.553800 -0.107890 0.301261 ) +( -0.014688 -0.527503 0.499529 ) +( -0.464365 -0.406423 0.385180 ) +set Matrix3 columns: +( -0.150218 -0.553800 -0.107890 ) +( 0.519112 -0.014688 -0.527503 ) +( -0.203209 -0.464365 -0.406423 ) +set Matrix4 columns: +( -0.252017 0.310782 0.286765 0.510961 ) +( 0.282194 0.861334 0.532078 0.791871 ) +( 0.067637 -0.980345 0.352671 -0.564379 ) +( 0.798376 -0.655106 0.540977 0.273199 ) +set Matrix4 columns: +( 0.510961 -0.252017 0.310782 0.286765 ) +( 0.791871 0.282194 0.861334 0.532078 ) +( -0.564379 0.067637 -0.980345 0.352671 ) +( 0.273199 0.798376 -0.655106 0.540977 ) +set Transform3 columns: +( -0.553800 -0.107890 0.301261 -0.150218 ) +( -0.014688 -0.527503 0.499529 0.519112 ) +( -0.464365 -0.406423 0.385180 -0.203209 ) +set Transform3 columns: +( -0.150218 -0.553800 -0.107890 0.301261 ) +( 0.519112 -0.014688 -0.527503 0.499529 ) +( -0.203209 -0.464365 -0.406423 0.385180 ) +appendScale Transform3 Vector3: +( 0.306694 0.001585 -0.139895 -0.150218 ) +( 0.008134 0.007748 -0.231964 0.519112 ) +( 0.257165 0.005970 -0.178864 -0.203209 ) +prependScale Vector3 Transform3: +( 0.306694 0.059749 -0.166838 0.083191 ) +( 0.000216 0.007748 -0.007337 -0.007625 ) +( 0.215635 0.188729 -0.178864 0.094363 ) +mulPerElem Transform3: +( 0.083191 0.059749 -0.032503 -0.045255 ) +( -0.007625 0.007748 -0.263503 0.259311 ) +( 0.094363 0.188729 -0.156546 -0.078272 ) +absPerElem Transform3: +( 0.553800 0.107890 0.301261 0.150218 ) +( 0.014688 0.527503 0.499529 0.519112 ) +( 0.464365 0.406423 0.385180 0.203209 ) +inverse Transform3: +( 0.003445 1.703147 -2.211457 -1.332994 ) +( 4.765344 1.545948 -5.732023 -1.251475 ) +( 5.032312 3.684490 -6.118052 -2.399958 ) +inverse(Transform3) * Transform3: +( 1.000000 0.000000 -0.000000 -0.000000 ) +( 0.000000 1.000000 -0.000000 0.000000 ) +( 0.000000 0.000000 1.000000 -0.000000 ) +orthoInverse Transform3: +( -0.806392 -0.302338 0.508256 0.139094 ) +( -0.574608 0.197327 -0.794285 -0.350157 ) +( 0.139850 -0.932552 -0.332848 0.437469 ) +orthoInverse(Transform3) * Transform3: +( 1.000000 0.000000 0.000000 -0.000000 ) +( 0.000000 1.000000 -0.000000 0.000000 ) +( 0.000000 -0.000000 1.000000 0.000000 ) + + __end__ diff --git a/Extras/vectormathlibrary/tests/test4_soa_c.c b/Extras/vectormathlibrary/tests/test4_soa_c.c new file mode 100644 index 0000000..dbd0150 --- /dev/null +++ b/Extras/vectormathlibrary/tests/test4_soa_c.c @@ -0,0 +1,474 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +#define _VECTORMATH_SOA_TEST + +#include "vectormath_soa.h" +#include "test.h" + +int iteration = 0; + +void +Matrix3_methods_test() +{ + VmathSoaMatrix3 a_Matrix3, b_Matrix3; + VmathSoaMatrix4 a_Matrix4, b_Matrix4; + VmathSoaTransform3 a_Transform3, b_Transform3; + VmathSoaMatrix3 tmpM3_0, tmpM3_1, tmpM3_2, tmpM3_3, tmpM3_4, tmpM3_5, tmpM3_6, tmpM3_7, tmpM3_8, tmpM3_9, tmpM3_10; + VmathSoaVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathSoaVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathSoaPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathSoaQuat a_Quat, b_Quat, c_Quat, d_Quat; + VmathSoaVector3 tmpV3_0; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathSoaV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathSoaP3Prints( &a_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &b_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &c_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaQPrints( &a_Quat, "set Quat with floats" ); + vmathSoaQPrints( &b_Quat, "set Quat with floats" ); + vmathSoaQPrints( &c_Quat, "set Quat with floats" ); + vmathSoaQPrints( &d_Quat, "set Quat with floats" ); + vmathSoaM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathSoaM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathSoaM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathSoaM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathSoaM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathSoaT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathSoaT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathSoaT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathSoaM3AppendScale( &tmpM3_0, &a_Matrix3, &a_Vector3 ); + vmathSoaM3Prints( &tmpM3_0, "appendScale Matrix3 Vector3" ); + vmathSoaM3PrependScale( &tmpM3_1, &a_Vector3, &a_Matrix3 ); + vmathSoaM3Prints( &tmpM3_1, "prependScale Vector3 Matrix3" ); + vmathSoaM3MulPerElem( &tmpM3_2, &a_Matrix3, &b_Matrix3 ); + vmathSoaM3Prints( &tmpM3_2, "mulPerElem Matrix3" ); + vmathSoaM3AbsPerElem( &tmpM3_3, &a_Matrix3 ); + vmathSoaM3Prints( &tmpM3_3, "absPerElem Matrix3" ); + vmathSoaM3Transpose( &tmpM3_4, &a_Matrix3 ); + vmathSoaM3Prints( &tmpM3_4, "transpose Matrix3" ); + vmathSoaM3Inverse( &tmpM3_5, &a_Matrix3 ); + vmathSoaM3Prints( &tmpM3_5, "inverse Matrix3" ); + vmathSoaM3Inverse( &tmpM3_6, &a_Matrix3 ); + vmathSoaM3Mul( &tmpM3_7, &tmpM3_6, &a_Matrix3 ); + vmathSoaM3Prints( &tmpM3_7, "inverse(Matrix3) * Matrix3" ); + printf("%f\n", getfloat(vmathSoaM3Determinant( &a_Matrix3 )) ); + vmathSoaV3Outer( &tmpM3_8, &a_Vector3, &b_Vector3 ); + vmathSoaM3Prints( &tmpM3_8, "outer Vector3" ); + vmathSoaV3RowMul( &tmpV3_0, &a_Vector3, &a_Matrix3 ); + vmathSoaV3Prints( &tmpV3_0, "rowMul Vector3" ); + vmathSoaV3CrossMatrix( &tmpM3_9, &a_Vector3 ); + vmathSoaM3Prints( &tmpM3_9, "crossMatrix" ); + vmathSoaV3CrossMatrixMul( &tmpM3_10, &a_Vector3, &a_Matrix3 ); + vmathSoaM3Prints( &tmpM3_10, "crossMatrixMul" ); +} + +void +Matrix4_methods_test() +{ + VmathSoaMatrix3 a_Matrix3, b_Matrix3; + VmathSoaMatrix4 a_Matrix4, b_Matrix4; + VmathSoaTransform3 a_Transform3, b_Transform3; + VmathSoaMatrix4 tmpM4_0, tmpM4_1, tmpM4_2, tmpM4_3, tmpM4_4, tmpM4_5, tmpM4_6, tmpM4_7; + VmathSoaMatrix3 tmpM3_0; + VmathSoaMatrix4 tmpM4_8, tmpM4_9, tmpM4_10, tmpM4_11, tmpM4_12, tmpM4_13, tmpM4_14; + VmathSoaVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathSoaVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathSoaPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathSoaQuat a_Quat, b_Quat, c_Quat, d_Quat; + VmathSoaVector4 tmpV4_0; + VmathSoaQuat tmpQ_0; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathSoaV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathSoaP3Prints( &a_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &b_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &c_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaQPrints( &a_Quat, "set Quat with floats" ); + vmathSoaQPrints( &b_Quat, "set Quat with floats" ); + vmathSoaQPrints( &c_Quat, "set Quat with floats" ); + vmathSoaQPrints( &d_Quat, "set Quat with floats" ); + vmathSoaM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathSoaM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathSoaM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathSoaM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathSoaM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathSoaT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathSoaT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathSoaT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathSoaM4AppendScale( &tmpM4_0, &a_Matrix4, &a_Vector3 ); + vmathSoaM4Prints( &tmpM4_0, "appendScale Matrix4 Vector3" ); + vmathSoaM4PrependScale( &tmpM4_1, &a_Vector3, &a_Matrix4 ); + vmathSoaM4Prints( &tmpM4_1, "prependScale Vector3 Matrix4" ); + vmathSoaM4MulPerElem( &tmpM4_2, &a_Matrix4, &b_Matrix4 ); + vmathSoaM4Prints( &tmpM4_2, "mulPerElem Matrix4" ); + vmathSoaM4AbsPerElem( &tmpM4_3, &a_Matrix4 ); + vmathSoaM4Prints( &tmpM4_3, "absPerElem Matrix4" ); + vmathSoaM4Transpose( &tmpM4_4, &a_Matrix4 ); + vmathSoaM4Prints( &tmpM4_4, "transpose Matrix4" ); + vmathSoaM4Inverse( &tmpM4_5, &a_Matrix4 ); + vmathSoaM4Prints( &tmpM4_5, "inverse Matrix4" ); + vmathSoaM4Inverse( &tmpM4_6, &a_Matrix4 ); + vmathSoaM4Mul( &tmpM4_7, &tmpM4_6, &a_Matrix4 ); + vmathSoaM4Prints( &tmpM4_7, "inverse(Matrix4) * Matrix4" ); + vmathSoaV4MakeFromElems( &tmpV4_0, ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ); + vmathSoaM4SetRow( &a_Matrix4, 3, &tmpV4_0 ); + vmathSoaQNormalize( &tmpQ_0, &a_Quat ); + vmathSoaM3MakeFromQ( &tmpM3_0, &tmpQ_0 ); + vmathSoaM4SetUpper3x3( &a_Matrix4, &tmpM3_0 ); + vmathSoaM4AffineInverse( &tmpM4_8, &a_Matrix4 ); + vmathSoaM4Prints( &tmpM4_8, "affineInverse Matrix4" ); + vmathSoaM4AffineInverse( &tmpM4_9, &a_Matrix4 ); + vmathSoaM4Mul( &tmpM4_10, &tmpM4_9, &a_Matrix4 ); + vmathSoaM4Prints( &tmpM4_10, "affineInverse(Matrix4) * Matrix4" ); + vmathSoaM4OrthoInverse( &tmpM4_11, &a_Matrix4 ); + vmathSoaM4Prints( &tmpM4_11, "orthoInverse Matrix4" ); + vmathSoaM4OrthoInverse( &tmpM4_12, &a_Matrix4 ); + vmathSoaM4Mul( &tmpM4_13, &tmpM4_12, &a_Matrix4 ); + vmathSoaM4Prints( &tmpM4_13, "orthoInverse(Matrix4) * Matrix4" ); + printf("%f\n", getfloat(vmathSoaM4Determinant( &a_Matrix4 )) ); + vmathSoaV4Outer( &tmpM4_14, &a_Vector4, &b_Vector4 ); + vmathSoaM4Prints( &tmpM4_14, "outer Vector4" ); +} + +void +Transform3_methods_test() +{ + VmathSoaMatrix3 a_Matrix3, b_Matrix3; + VmathSoaMatrix4 a_Matrix4, b_Matrix4; + VmathSoaTransform3 a_Transform3, b_Transform3, tmpT3_0, tmpT3_1, tmpT3_2, tmpT3_3, tmpT3_4, tmpT3_5, tmpT3_6; + VmathSoaMatrix3 tmpM3_0; + VmathSoaTransform3 tmpT3_7, tmpT3_8, tmpT3_9; + VmathSoaVector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + VmathSoaVector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + VmathSoaPoint3 a_Point3, b_Point3, c_Point3, d_Point3; + VmathSoaQuat a_Quat, b_Quat, c_Quat, d_Quat, tmpQ_0; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &a_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV3MakeFromElems( &b_Vector3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &c_Vector3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaV3MakeFromElems( &d_Vector3, rndflt1, rndflt2, rndflt3 ); + vmathSoaV3Prints( &a_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &b_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &c_Vector3, "set Vector3 with floats" ); + vmathSoaV3Prints( &d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &a_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaV4MakeFromElems( &b_Vector4, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &c_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaV4MakeFromElems( &d_Vector4, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaV4Prints( &a_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &b_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &c_Vector4, "set Vector4 with floats" ); + vmathSoaV4Prints( &d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &a_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaP3MakeFromElems( &b_Point3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &c_Point3, rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + vmathSoaP3MakeFromElems( &d_Point3, rndflt1, rndflt2, rndflt3 ); + vmathSoaP3Prints( &a_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &b_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &c_Point3, "set Point3 with floats" ); + vmathSoaP3Prints( &d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &a_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + vmathSoaQMakeFromElems( &b_Quat, rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &c_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + vmathSoaQMakeFromElems( &d_Quat, rndflt1, rndflt2, rndflt3, rndflt4 ); + vmathSoaQPrints( &a_Quat, "set Quat with floats" ); + vmathSoaQPrints( &b_Quat, "set Quat with floats" ); + vmathSoaQPrints( &c_Quat, "set Quat with floats" ); + vmathSoaQPrints( &d_Quat, "set Quat with floats" ); + vmathSoaM3MakeFromCols( &a_Matrix3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaM3MakeFromCols( &b_Matrix3, &d_Vector3, &a_Vector3, &b_Vector3 ); + vmathSoaM3Prints( &a_Matrix3, "set Matrix3 columns" ); + vmathSoaM3Prints( &b_Matrix3, "set Matrix3 columns" ); + vmathSoaM4MakeFromCols( &a_Matrix4, &a_Vector4, &b_Vector4, &c_Vector4, &d_Vector4 ); + vmathSoaM4MakeFromCols( &b_Matrix4, &d_Vector4, &a_Vector4, &b_Vector4, &c_Vector4 ); + vmathSoaM4Prints( &a_Matrix4, "set Matrix4 columns" ); + vmathSoaM4Prints( &b_Matrix4, "set Matrix4 columns" ); + vmathSoaT3MakeFromCols( &a_Transform3, &a_Vector3, &b_Vector3, &c_Vector3, &d_Vector3 ); + vmathSoaT3MakeFromCols( &b_Transform3, &d_Vector3, &a_Vector3, &b_Vector3, &c_Vector3 ); + vmathSoaT3Prints( &a_Transform3, "set Transform3 columns" ); + vmathSoaT3Prints( &b_Transform3, "set Transform3 columns" ); + vmathSoaT3AppendScale( &tmpT3_0, &a_Transform3, &a_Vector3 ); + vmathSoaT3Prints( &tmpT3_0, "appendScale Transform3 Vector3" ); + vmathSoaT3PrependScale( &tmpT3_1, &a_Vector3, &a_Transform3 ); + vmathSoaT3Prints( &tmpT3_1, "prependScale Vector3 Transform3" ); + vmathSoaT3MulPerElem( &tmpT3_2, &a_Transform3, &b_Transform3 ); + vmathSoaT3Prints( &tmpT3_2, "mulPerElem Transform3" ); + vmathSoaT3AbsPerElem( &tmpT3_3, &a_Transform3 ); + vmathSoaT3Prints( &tmpT3_3, "absPerElem Transform3" ); + vmathSoaT3Inverse( &tmpT3_4, &a_Transform3 ); + vmathSoaT3Prints( &tmpT3_4, "inverse Transform3" ); + vmathSoaT3Inverse( &tmpT3_5, &a_Transform3 ); + vmathSoaT3Mul( &tmpT3_6, &tmpT3_5, &a_Transform3 ); + vmathSoaT3Prints( &tmpT3_6, "inverse(Transform3) * Transform3" ); + vmathSoaQNormalize( &tmpQ_0, &a_Quat ); + vmathSoaM3MakeFromQ( &tmpM3_0, &tmpQ_0 ); + vmathSoaT3SetUpper3x3( &a_Transform3, &tmpM3_0 ); + vmathSoaT3OrthoInverse( &tmpT3_7, &a_Transform3 ); + vmathSoaT3Prints( &tmpT3_7, "orthoInverse Transform3" ); + vmathSoaT3OrthoInverse( &tmpT3_8, &a_Transform3 ); + vmathSoaT3Mul( &tmpT3_9, &tmpT3_8, &a_Transform3 ); + vmathSoaT3Prints( &tmpT3_9, "orthoInverse(Transform3) * Transform3" ); +} + +int main() +{ + int i; + printf("\n __begin__ \n"); + for ( i = 0; i < 2; i++ ) { + Matrix3_methods_test(); + Matrix4_methods_test(); + Transform3_methods_test(); + } + printf("\n __end__ \n"); + return 0; +} diff --git a/Extras/vectormathlibrary/tests/test4_soa_cpp.cpp b/Extras/vectormathlibrary/tests/test4_soa_cpp.cpp new file mode 100644 index 0000000..3a71aef --- /dev/null +++ b/Extras/vectormathlibrary/tests/test4_soa_cpp.cpp @@ -0,0 +1,426 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. +*/ + +#define _VECTORMATH_SOA_TEST + +#include "vectormath_soa.h" +#include "test.h" + +int iteration = 0; + +using namespace Vectormath; +using namespace Vectormath::Soa; + +void +Matrix3_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + print( appendScale( a_Matrix3, a_Vector3 ), "appendScale Matrix3 Vector3" ); + print( prependScale( a_Vector3, a_Matrix3 ), "prependScale Vector3 Matrix3" ); + print( mulPerElem( a_Matrix3, b_Matrix3 ), "mulPerElem Matrix3" ); + print( absPerElem( a_Matrix3 ), "absPerElem Matrix3" ); + print( transpose( a_Matrix3 ), "transpose Matrix3" ); + print( inverse( a_Matrix3 ), "inverse Matrix3" ); + print( ( inverse( a_Matrix3 ) * a_Matrix3 ), "inverse(Matrix3) * Matrix3" ); + printf("%f\n", getfloat(determinant( a_Matrix3 )) ); + print( outer( a_Vector3, b_Vector3 ), "outer Vector3" ); + print( rowMul( a_Vector3, a_Matrix3 ), "rowMul Vector3" ); + print( crossMatrix( a_Vector3 ), "crossMatrix" ); + print( crossMatrixMul( a_Vector3, a_Matrix3 ), "crossMatrixMul" ); +} + +void +Matrix4_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + print( appendScale( a_Matrix4, a_Vector3 ), "appendScale Matrix4 Vector3" ); + print( prependScale( a_Vector3, a_Matrix4 ), "prependScale Vector3 Matrix4" ); + print( mulPerElem( a_Matrix4, b_Matrix4 ), "mulPerElem Matrix4" ); + print( absPerElem( a_Matrix4 ), "absPerElem Matrix4" ); + print( transpose( a_Matrix4 ), "transpose Matrix4" ); + print( inverse( a_Matrix4 ), "inverse Matrix4" ); + print( ( inverse( a_Matrix4 ) * a_Matrix4 ), "inverse(Matrix4) * Matrix4" ); + a_Matrix4.setRow( 3, Vector4( ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){0.0f,0.0f,0.0f,0.0f}), ((vec_float4){1.0f,1.0f,1.0f,1.0f}) ) ); + a_Matrix4.setUpper3x3( Matrix3( normalize( a_Quat ) ) ); + print( affineInverse( a_Matrix4 ), "affineInverse Matrix4" ); + print( ( affineInverse( a_Matrix4 ) * a_Matrix4 ), "affineInverse(Matrix4) * Matrix4" ); + print( orthoInverse( a_Matrix4 ), "orthoInverse Matrix4" ); + print( ( orthoInverse( a_Matrix4 ) * a_Matrix4 ), "orthoInverse(Matrix4) * Matrix4" ); + printf("%f\n", getfloat(determinant( a_Matrix4 )) ); + print( outer( a_Vector4, b_Vector4 ), "outer Vector4" ); +} + +void +Transform3_methods_test() +{ + Matrix3 a_Matrix3, b_Matrix3; + Matrix4 a_Matrix4, b_Matrix4; + Transform3 a_Transform3, b_Transform3; + Vector3 a_Vector3, b_Vector3, c_Vector3, d_Vector3; + Vector4 a_Vector4, b_Vector4, c_Vector4, d_Vector4; + Point3 a_Point3, b_Point3, c_Point3, d_Point3; + Quat a_Quat, b_Quat, c_Quat, d_Quat; + vec_float4 rndflt1, rndflt2, rndflt3, rndflt4, rndflt5, rndflt6; + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector3 = Vector3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Vector3 = Vector3( rndflt1, rndflt2, rndflt3 ); + print( a_Vector3, "set Vector3 with floats" ); + print( b_Vector3, "set Vector3 with floats" ); + print( c_Vector3, "set Vector3 with floats" ); + print( d_Vector3, "set Vector3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Vector4 = Vector4( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Vector4 = Vector4( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Vector4, "set Vector4 with floats" ); + print( b_Vector4, "set Vector4 with floats" ); + print( c_Vector4, "set Vector4 with floats" ); + print( d_Vector4, "set Vector4 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + a_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Point3 = Point3( rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + c_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + d_Point3 = Point3( rndflt1, rndflt2, rndflt3 ); + print( a_Point3, "set Point3 with floats" ); + print( b_Point3, "set Point3 with floats" ); + print( c_Point3, "set Point3 with floats" ); + print( d_Point3, "set Point3 with floats" ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + a_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + rndflt5 = randfloat(); + rndflt6 = randfloat(); + b_Quat = Quat( rndflt3, rndflt4, rndflt5, rndflt6 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + c_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + rndflt1 = randfloat(); + rndflt2 = randfloat(); + rndflt3 = randfloat(); + rndflt4 = randfloat(); + d_Quat = Quat( rndflt1, rndflt2, rndflt3, rndflt4 ); + print( a_Quat, "set Quat with floats" ); + print( b_Quat, "set Quat with floats" ); + print( c_Quat, "set Quat with floats" ); + print( d_Quat, "set Quat with floats" ); + a_Matrix3 = Matrix3( a_Vector3, b_Vector3, c_Vector3 ); + b_Matrix3 = Matrix3( d_Vector3, a_Vector3, b_Vector3 ); + print( a_Matrix3, "set Matrix3 columns" ); + print( b_Matrix3, "set Matrix3 columns" ); + a_Matrix4 = Matrix4( a_Vector4, b_Vector4, c_Vector4, d_Vector4 ); + b_Matrix4 = Matrix4( d_Vector4, a_Vector4, b_Vector4, c_Vector4 ); + print( a_Matrix4, "set Matrix4 columns" ); + print( b_Matrix4, "set Matrix4 columns" ); + a_Transform3 = Transform3( a_Vector3, b_Vector3, c_Vector3, d_Vector3 ); + b_Transform3 = Transform3( d_Vector3, a_Vector3, b_Vector3, c_Vector3 ); + print( a_Transform3, "set Transform3 columns" ); + print( b_Transform3, "set Transform3 columns" ); + print( appendScale( a_Transform3, a_Vector3 ), "appendScale Transform3 Vector3" ); + print( prependScale( a_Vector3, a_Transform3 ), "prependScale Vector3 Transform3" ); + print( mulPerElem( a_Transform3, b_Transform3 ), "mulPerElem Transform3" ); + print( absPerElem( a_Transform3 ), "absPerElem Transform3" ); + print( inverse( a_Transform3 ), "inverse Transform3" ); + print( ( inverse( a_Transform3 ) * a_Transform3 ), "inverse(Transform3) * Transform3" ); + a_Transform3.setUpper3x3( Matrix3( normalize( a_Quat ) ) ); + print( orthoInverse( a_Transform3 ), "orthoInverse Transform3" ); + print( ( orthoInverse( a_Transform3 ) * a_Transform3 ), "orthoInverse(Transform3) * Transform3" ); +} + +int main() +{ + int i; + printf("\n __begin__ \n"); + for ( i = 0; i < 2; i++ ) { + Matrix3_methods_test(); + Matrix4_methods_test(); + Transform3_methods_test(); + } + printf("\n __end__ \n"); + return 0; +} diff --git a/Extras/vectormathlibrary/vectormath.spec b/Extras/vectormathlibrary/vectormath.spec new file mode 100644 index 0000000..9507485 --- /dev/null +++ b/Extras/vectormathlibrary/vectormath.spec @@ -0,0 +1,81 @@ +%define lib_version 1.0.1 + +Summary: Vector math library +Name: vectormath +Version: %{lib_version} +Release: 1 +License: BSD +Group: Development/Libraries +Source0: %{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root + +%description +Vector math library. + +%ifarch ppc ppc64 +%define _lib_arch ppu +%endif + +%ifarch i386 x86_64 +%define _lib_arch SSE +%endif + +%if %{undefined _lib_arch} +%define _lib_arch scalar +%endif + +%package -n %{name}-devel +Summary: Vector math library. +Group: Development/Libraries +%ifarch ppc ppc64 +Requires: simdmath-devel +%endif + +%description -n %{name}-devel +Vector math library. + +%ifarch ppc ppc64 +%package -n spu-%{name}-devel +Summary: Vector math library. +Group: Development/Libraries +Requires: spu-simdmath-devel + +%description -n spu-%{name}-devel +Vector math library. +%endif + +%prep +%setup -q + +%build + +%install +rm -rf %{buildroot} + +make ARCH=%{_lib_arch} DESTDIR=%{buildroot} install + +%ifarch ppc ppc64 +make ARCH=spu DESTDIR=%{buildroot} install +%endif + +mkdir -p %{buildroot}/%{_docdir}/%{name}-%{version} +cp README LICENSE doc/*.pdf %{buildroot}/%{_docdir}/%{name}-%{version}/ + + +%clean +rm -rf %{buildroot} + +%files -n %{name}-devel +%defattr(-,root,root,-) +%{_includedir}/* +%{_docdir}/* + +%ifarch ppc ppc64 +%files -n spu-%{name}-devel +%defattr(-,root,root,-) +%{_prefix}/spu/include/* +%endif + +%changelog +* Wed Aug 8 2007 Kazunori Asayama - 1.0.1-1 +- Initial build. diff --git a/GLUT32.DLL b/GLUT32.DLL new file mode 100644 index 0000000000000000000000000000000000000000..3297bd0783b702755a952ad50e518d3e1a922595 GIT binary patch literal 160256 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 + +// include log tokens + +#include + +// include simple void functions we ignore + +#include + +// include functions that need a bit of work, but we don't log + +#include + +// include functions we log + +#ifdef EGL_LOG_PTR + +extern unsigned int *EGL_LOG_PTR; + +inline void xGLL(int a) { *EGL_LOG_PTR=(unsigned int)a; EGL_LOG_PTR++; }; +inline void xGLL(unsigned int a) { *EGL_LOG_PTR=a; EGL_LOG_PTR++; }; +inline void xGLL(float a) { *(float *)EGL_LOG_PTR=a; EGL_LOG_PTR++; }; +inline void xGLL(double a) { *(float *)EGL_LOG_PTR=(float)a; EGL_LOG_PTR++; }; +inline void xGLL(const float *a) { for(int t=0;t!=16;t++) xGLL(a[t]); }; +inline void xGLL(const double *a) { for(int t=0;t!=16;t++) xGLL(a[t]); }; +#else + +inline void xGLL(int a) {}; +inline void xGLL(unsigned int a) {}; +inline void xGLL(float a) {}; +inline void xGLL(double a) {}; +inline void xGLL(const float *a) {}; +inline void xGLL(const double *a) {}; + +#endif + +// functions we might log + +#include + +#endif diff --git a/Glut/EmptyGL/GL/glu.h b/Glut/EmptyGL/GL/glu.h new file mode 100644 index 0000000..95a40b2 --- /dev/null +++ b/Glut/EmptyGL/GL/glu.h @@ -0,0 +1,23 @@ +#ifndef EMPTY_GLU +#define EMPTY_GLU + +inline void gluOrtho2D( int a,int b, int c ,int d ) { } ; +inline void gluLookAt( + GLfloat a,GLfloat b, GLfloat c, + GLfloat d,GLfloat e, GLfloat f, + GLfloat g,GLfloat h, GLfloat i ) { }; + +#define GLU_FILL 1 +#define GLU_SMOOTH 2 + +typedef int GLUquadric; +typedef GLUquadric GLUquadricObj; + +inline GLUquadric *gluNewQuadric() { return (GLUquadric *)1; }; +inline void gluQuadricDrawStyle( GLUquadric *o, int mode) {}; +inline void gluQuadricNormals( GLUquadric *o, int mode) {}; +inline void gluDeleteQuadric( GLUquadric *q) {}; +inline void gluDisk (GLUquadric* quad, GLdouble inner, GLdouble outer, GLint slices, GLint loops) {}; +inline void gluCylinder (GLUquadric* quad, GLdouble base, GLdouble top, GLdouble height, GLint slices, GLint stacks) {}; +inline int gluBuild2DMipmaps (GLenum target, GLint components, GLint width, GLint height, GLenum format, GLenum type, const void *data) { return 0;} +#endif diff --git a/Glut/EmptyGL/GL/glut.h b/Glut/EmptyGL/GL/glut.h new file mode 100644 index 0000000..9007ecd --- /dev/null +++ b/Glut/EmptyGL/GL/glut.h @@ -0,0 +1,60 @@ +#ifndef EMPTY_GLUT_H +#define EMPTY_GLUT_H + +#include +#include + + +#define GLUT_KEY_F1 0 +#define GLUT_KEY_F2 1 +#define GLUT_KEY_END 2 +#define GLUT_KEY_LEFT 3 +#define GLUT_KEY_RIGHT 4 +#define GLUT_KEY_UP 5 +#define GLUT_KEY_DOWN 6 +#define GLUT_KEY_PAGE_UP 7 +#define GLUT_KEY_PAGE_DOWN 8 +#define GLUT_KEY_HOME 9 +#define GLUT_KEY_F3 10 +#define GLUT_KEY_F4 11 +#define GLUT_KEY_F5 12 +#define GLUT_ACTIVE_SHIFT 13 + + +#define GLUT_DOUBLE 1 +#define GLUT_RGBA 2 +#define GLUT_DEPTH 4 +#define GLUT_STENCIL 8 +#define GLUT_WINDOW_WIDTH 16 +#define GLUT_WINDOW_HEIGHT 32 +#define GLUT_RGB 64 + + + + +inline void glutSwapBuffers() {} +inline void glutShowWindow() {} +inline void glutPostRedisplay() {} +inline void glutInit(int *argc, char **argv) {} +inline void glutInitDisplayMode( unsigned int ) {} +inline void glutInitWindowPosition(int x, int y) {} +inline void glutInitWindowSize(int x, int y) {} +inline int glutCreateWindow( const char *str) {return 0;} +inline void glutKeyboardFunc( void (*func)(unsigned char, int ,int ) ) {} +inline void glutSpecialFunc( void (*func)(int key, int x,int y) ) {} +inline void glutSpecialUpFunc( void (*func)(int key, int x,int y) ) {} +inline void glutReshapeFunc( void (*func)(int w,int h) ) {} +inline void glutDisplayFunc( void (*func)() ) {} +inline void glutIdleFunc( void (*func)() ) {} +inline void glutMotionFunc( void (*func)(int x,int y) ) {} +inline void glutMouseFunc( void (*func)(int button,int state,int x,int y) ) {} +inline void glutMainLoop() {} +inline void glutSetWindow(int bla) {} + +inline void glutSolidCube(GLfloat ) {} +inline void glutSolidSphere(GLfloat , int a , int b) {} +inline void glutSolidCone(GLfloat ,GLfloat , int a , int b) {} +inline int glutGetModifiers() { return 0;} +inline void gluPerspective(float a,float b,float c,float d) {} +inline float glutGet(int code) { return 0.f;} +#endif diff --git a/Glut/GL/glew.h b/Glut/GL/glew.h new file mode 100644 index 0000000..f70103d --- /dev/null +++ b/Glut/GL/glew.h @@ -0,0 +1,15507 @@ +/* +** The OpenGL Extension Wrangler Library +** Copyright (C) 2002-2008, Milan Ikits +** Copyright (C) 2002-2008, Marcelo E. Magallon +** Copyright (C) 2002, Lev Povalahev +** 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. +** * The name of the author 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. +*/ + +/* + * Mesa 3-D graphics library + * Version: 7.0 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL 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. + */ + +/* +** Copyright (c) 2007 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are 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 Materials. +** +** THE MATERIALS ARE 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 +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#ifndef __glew_h__ +#define __glew_h__ +#define __GLEW_H__ + +#if defined(__gl_h_) || defined(__GL_H__) || defined(__X_GL_H) +#error gl.h included before glew.h +#endif +#if defined(__glext_h_) || defined(__GLEXT_H_) +#error glext.h included before glew.h +#endif +#if defined(__gl_ATI_h_) +#error glATI.h included before glew.h +#endif + +#define __gl_h_ +#define __GL_H__ +#define __X_GL_H +#define __glext_h_ +#define __GLEXT_H_ +#define __gl_ATI_h_ + +#if defined(_WIN32) + +/* + * GLEW does not include to avoid name space pollution. + * GL needs GLAPI and GLAPIENTRY, GLU needs APIENTRY, CALLBACK, and wchar_t + * defined properly. + */ +/* */ +#ifndef APIENTRY +#define GLEW_APIENTRY_DEFINED +# if defined(__MINGW32__) || defined(__CYGWIN__) +# define APIENTRY __stdcall +# elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__) +# define APIENTRY __stdcall +# else +# define APIENTRY +# endif +#endif +#ifndef GLAPI +# if defined(__MINGW32__) || defined(__CYGWIN__) +# define GLAPI extern +# endif +#endif +/* */ +#ifndef CALLBACK +#define GLEW_CALLBACK_DEFINED +# if defined(__MINGW32__) || defined(__CYGWIN__) +# define CALLBACK __attribute__ ((__stdcall__)) +# elif (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) +# define CALLBACK __stdcall +# else +# define CALLBACK +# endif +#endif +/* and */ +#ifndef WINGDIAPI +#define GLEW_WINGDIAPI_DEFINED +#define WINGDIAPI __declspec(dllimport) +#endif +/* */ +#if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(_WCHAR_T_DEFINED) +typedef unsigned short wchar_t; +# define _WCHAR_T_DEFINED +#endif +/* */ +#if !defined(_W64) +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && defined(_MSC_VER) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif +#if !defined(_PTRDIFF_T_DEFINED) && !defined(_PTRDIFF_T_) && !defined(__MINGW64__) +# ifdef _WIN64 +typedef __int64 ptrdiff_t; +# else +typedef _W64 int ptrdiff_t; +# endif +# define _PTRDIFF_T_DEFINED +# define _PTRDIFF_T_ +#endif + +#ifndef GLAPI +# if defined(__MINGW32__) || defined(__CYGWIN__) +# define GLAPI extern +# else +# define GLAPI WINGDIAPI +# endif +#endif + +#ifndef GLAPIENTRY +#define GLAPIENTRY APIENTRY +#endif + +/* + * GLEW_STATIC is defined for static library. + * GLEW_BUILD is defined for building the DLL library. + */ + +#ifdef GLEW_STATIC +# define GLEWAPI extern +#else +# ifdef GLEW_BUILD +# define GLEWAPI extern __declspec(dllexport) +# else +# define GLEWAPI extern __declspec(dllimport) +# endif +#endif + +#else /* _UNIX */ + +/* + * Needed for ptrdiff_t in turn needed by VBO. This is defined by ISO + * C. On my system, this amounts to _3 lines_ of included code, all of + * them pretty much harmless. If you know of a way of detecting 32 vs + * 64 _targets_ at compile time you are free to replace this with + * something that's portable. For now, _this_ is the portable solution. + * (mem, 2004-01-04) + */ + +#include + +/* SGI MIPSPro doesn't like stdint.h in C++ mode */ + +#if defined(__sgi) && !defined(__GNUC__) +#include +#else +#include +#endif + +#define GLEW_APIENTRY_DEFINED +#define APIENTRY + +/* + * GLEW_STATIC is defined for static library. + */ + +#ifdef GLEW_STATIC +# define GLEWAPI extern +#else +# if defined(__GNUC__) && __GNUC__>=4 +# define GLEWAPI extern __attribute__ ((visibility("default"))) +# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) +# define GLEWAPI extern __global +# else +# define GLEWAPI extern +# endif +#endif + +/* */ +#ifndef GLAPI +#define GLAPI extern +#endif +#ifndef GLAPIENTRY +#define GLAPIENTRY +#endif + +#endif /* _WIN32 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----------------------------- GL_VERSION_1_1 ---------------------------- */ + +#ifndef GL_VERSION_1_1 +#define GL_VERSION_1_1 1 + +typedef unsigned int GLenum; +typedef unsigned int GLbitfield; +typedef unsigned int GLuint; +typedef int GLint; +typedef int GLsizei; +typedef unsigned char GLboolean; +typedef signed char GLbyte; +typedef short GLshort; +typedef unsigned char GLubyte; +typedef unsigned short GLushort; +typedef unsigned long GLulong; +typedef float GLfloat; +typedef float GLclampf; +typedef double GLdouble; +typedef double GLclampd; +typedef void GLvoid; +#if defined(_MSC_VER) && _MSC_VER < 1400 +typedef __int64 GLint64EXT; +typedef unsigned __int64 GLuint64EXT; +#elif defined(_MSC_VER) || defined(__BORLANDC__) +typedef signed long long GLint64EXT; +typedef unsigned long long GLuint64EXT; +#else +# if defined(__MINGW32__) || defined(__CYGWIN__) +#include +# endif +typedef int64_t GLint64EXT; +typedef uint64_t GLuint64EXT; +#endif +typedef GLint64EXT GLint64; +typedef GLuint64EXT GLuint64; +typedef struct __GLsync *GLsync; + +typedef char GLchar; + +#define GL_ZERO 0 +#define GL_FALSE 0 +#define GL_LOGIC_OP 0x0BF1 +#define GL_NONE 0 +#define GL_TEXTURE_COMPONENTS 0x1003 +#define GL_NO_ERROR 0 +#define GL_POINTS 0x0000 +#define GL_CURRENT_BIT 0x00000001 +#define GL_TRUE 1 +#define GL_ONE 1 +#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_POINT_BIT 0x00000002 +#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002 +#define GL_LINE_STRIP 0x0003 +#define GL_LINE_BIT 0x00000004 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_QUADS 0x0007 +#define GL_QUAD_STRIP 0x0008 +#define GL_POLYGON_BIT 0x00000008 +#define GL_POLYGON 0x0009 +#define GL_POLYGON_STIPPLE_BIT 0x00000010 +#define GL_PIXEL_MODE_BIT 0x00000020 +#define GL_LIGHTING_BIT 0x00000040 +#define GL_FOG_BIT 0x00000080 +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_ACCUM 0x0100 +#define GL_LOAD 0x0101 +#define GL_RETURN 0x0102 +#define GL_MULT 0x0103 +#define GL_ADD 0x0104 +#define GL_NEVER 0x0200 +#define GL_ACCUM_BUFFER_BIT 0x00000200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_FRONT_LEFT 0x0400 +#define GL_FRONT_RIGHT 0x0401 +#define GL_BACK_LEFT 0x0402 +#define GL_BACK_RIGHT 0x0403 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_LEFT 0x0406 +#define GL_RIGHT 0x0407 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_AUX0 0x0409 +#define GL_AUX1 0x040A +#define GL_AUX2 0x040B +#define GL_AUX3 0x040C +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_2D 0x0600 +#define GL_3D 0x0601 +#define GL_3D_COLOR 0x0602 +#define GL_3D_COLOR_TEXTURE 0x0603 +#define GL_4D_COLOR_TEXTURE 0x0604 +#define GL_PASS_THROUGH_TOKEN 0x0700 +#define GL_POINT_TOKEN 0x0701 +#define GL_LINE_TOKEN 0x0702 +#define GL_POLYGON_TOKEN 0x0703 +#define GL_BITMAP_TOKEN 0x0704 +#define GL_DRAW_PIXEL_TOKEN 0x0705 +#define GL_COPY_PIXEL_TOKEN 0x0706 +#define GL_LINE_RESET_TOKEN 0x0707 +#define GL_EXP 0x0800 +#define GL_VIEWPORT_BIT 0x00000800 +#define GL_EXP2 0x0801 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_COEFF 0x0A00 +#define GL_ORDER 0x0A01 +#define GL_DOMAIN 0x0A02 +#define GL_CURRENT_COLOR 0x0B00 +#define GL_CURRENT_INDEX 0x0B01 +#define GL_CURRENT_NORMAL 0x0B02 +#define GL_CURRENT_TEXTURE_COORDS 0x0B03 +#define GL_CURRENT_RASTER_COLOR 0x0B04 +#define GL_CURRENT_RASTER_INDEX 0x0B05 +#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06 +#define GL_CURRENT_RASTER_POSITION 0x0B07 +#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08 +#define GL_CURRENT_RASTER_DISTANCE 0x0B09 +#define GL_POINT_SMOOTH 0x0B10 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_RANGE 0x0B12 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_RANGE 0x0B22 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_LINE_STIPPLE 0x0B24 +#define GL_LINE_STIPPLE_PATTERN 0x0B25 +#define GL_LINE_STIPPLE_REPEAT 0x0B26 +#define GL_LIST_MODE 0x0B30 +#define GL_MAX_LIST_NESTING 0x0B31 +#define GL_LIST_BASE 0x0B32 +#define GL_LIST_INDEX 0x0B33 +#define GL_POLYGON_MODE 0x0B40 +#define GL_POLYGON_SMOOTH 0x0B41 +#define GL_POLYGON_STIPPLE 0x0B42 +#define GL_EDGE_FLAG 0x0B43 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_LIGHTING 0x0B50 +#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 +#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 +#define GL_LIGHT_MODEL_AMBIENT 0x0B53 +#define GL_SHADE_MODEL 0x0B54 +#define GL_COLOR_MATERIAL_FACE 0x0B55 +#define GL_COLOR_MATERIAL_PARAMETER 0x0B56 +#define GL_COLOR_MATERIAL 0x0B57 +#define GL_FOG 0x0B60 +#define GL_FOG_INDEX 0x0B61 +#define GL_FOG_DENSITY 0x0B62 +#define GL_FOG_START 0x0B63 +#define GL_FOG_END 0x0B64 +#define GL_FOG_MODE 0x0B65 +#define GL_FOG_COLOR 0x0B66 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_ACCUM_CLEAR_VALUE 0x0B80 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_MATRIX_MODE 0x0BA0 +#define GL_NORMALIZE 0x0BA1 +#define GL_VIEWPORT 0x0BA2 +#define GL_MODELVIEW_STACK_DEPTH 0x0BA3 +#define GL_PROJECTION_STACK_DEPTH 0x0BA4 +#define GL_TEXTURE_STACK_DEPTH 0x0BA5 +#define GL_MODELVIEW_MATRIX 0x0BA6 +#define GL_PROJECTION_MATRIX 0x0BA7 +#define GL_TEXTURE_MATRIX 0x0BA8 +#define GL_ATTRIB_STACK_DEPTH 0x0BB0 +#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1 +#define GL_ALPHA_TEST 0x0BC0 +#define GL_ALPHA_TEST_FUNC 0x0BC1 +#define GL_ALPHA_TEST_REF 0x0BC2 +#define GL_DITHER 0x0BD0 +#define GL_BLEND_DST 0x0BE0 +#define GL_BLEND_SRC 0x0BE1 +#define GL_BLEND 0x0BE2 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_INDEX_LOGIC_OP 0x0BF1 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_AUX_BUFFERS 0x0C00 +#define GL_DRAW_BUFFER 0x0C01 +#define GL_READ_BUFFER 0x0C02 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_INDEX_CLEAR_VALUE 0x0C20 +#define GL_INDEX_WRITEMASK 0x0C21 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_INDEX_MODE 0x0C30 +#define GL_RGBA_MODE 0x0C31 +#define GL_DOUBLEBUFFER 0x0C32 +#define GL_STEREO 0x0C33 +#define GL_RENDER_MODE 0x0C40 +#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 +#define GL_POINT_SMOOTH_HINT 0x0C51 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_FOG_HINT 0x0C54 +#define GL_TEXTURE_GEN_S 0x0C60 +#define GL_TEXTURE_GEN_T 0x0C61 +#define GL_TEXTURE_GEN_R 0x0C62 +#define GL_TEXTURE_GEN_Q 0x0C63 +#define GL_PIXEL_MAP_I_TO_I 0x0C70 +#define GL_PIXEL_MAP_S_TO_S 0x0C71 +#define GL_PIXEL_MAP_I_TO_R 0x0C72 +#define GL_PIXEL_MAP_I_TO_G 0x0C73 +#define GL_PIXEL_MAP_I_TO_B 0x0C74 +#define GL_PIXEL_MAP_I_TO_A 0x0C75 +#define GL_PIXEL_MAP_R_TO_R 0x0C76 +#define GL_PIXEL_MAP_G_TO_G 0x0C77 +#define GL_PIXEL_MAP_B_TO_B 0x0C78 +#define GL_PIXEL_MAP_A_TO_A 0x0C79 +#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0 +#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1 +#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2 +#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3 +#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4 +#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5 +#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6 +#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7 +#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8 +#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9 +#define GL_UNPACK_SWAP_BYTES 0x0CF0 +#define GL_UNPACK_LSB_FIRST 0x0CF1 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_SWAP_BYTES 0x0D00 +#define GL_PACK_LSB_FIRST 0x0D01 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAP_COLOR 0x0D10 +#define GL_MAP_STENCIL 0x0D11 +#define GL_INDEX_SHIFT 0x0D12 +#define GL_INDEX_OFFSET 0x0D13 +#define GL_RED_SCALE 0x0D14 +#define GL_RED_BIAS 0x0D15 +#define GL_ZOOM_X 0x0D16 +#define GL_ZOOM_Y 0x0D17 +#define GL_GREEN_SCALE 0x0D18 +#define GL_GREEN_BIAS 0x0D19 +#define GL_BLUE_SCALE 0x0D1A +#define GL_BLUE_BIAS 0x0D1B +#define GL_ALPHA_SCALE 0x0D1C +#define GL_ALPHA_BIAS 0x0D1D +#define GL_DEPTH_SCALE 0x0D1E +#define GL_DEPTH_BIAS 0x0D1F +#define GL_MAX_EVAL_ORDER 0x0D30 +#define GL_MAX_LIGHTS 0x0D31 +#define GL_MAX_CLIP_PLANES 0x0D32 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_PIXEL_MAP_TABLE 0x0D34 +#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35 +#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 +#define GL_MAX_NAME_STACK_DEPTH 0x0D37 +#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 +#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_INDEX_BITS 0x0D51 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_ACCUM_RED_BITS 0x0D58 +#define GL_ACCUM_GREEN_BITS 0x0D59 +#define GL_ACCUM_BLUE_BITS 0x0D5A +#define GL_ACCUM_ALPHA_BITS 0x0D5B +#define GL_NAME_STACK_DEPTH 0x0D70 +#define GL_AUTO_NORMAL 0x0D80 +#define GL_MAP1_COLOR_4 0x0D90 +#define GL_MAP1_INDEX 0x0D91 +#define GL_MAP1_NORMAL 0x0D92 +#define GL_MAP1_TEXTURE_COORD_1 0x0D93 +#define GL_MAP1_TEXTURE_COORD_2 0x0D94 +#define GL_MAP1_TEXTURE_COORD_3 0x0D95 +#define GL_MAP1_TEXTURE_COORD_4 0x0D96 +#define GL_MAP1_VERTEX_3 0x0D97 +#define GL_MAP1_VERTEX_4 0x0D98 +#define GL_MAP2_COLOR_4 0x0DB0 +#define GL_MAP2_INDEX 0x0DB1 +#define GL_MAP2_NORMAL 0x0DB2 +#define GL_MAP2_TEXTURE_COORD_1 0x0DB3 +#define GL_MAP2_TEXTURE_COORD_2 0x0DB4 +#define GL_MAP2_TEXTURE_COORD_3 0x0DB5 +#define GL_MAP2_TEXTURE_COORD_4 0x0DB6 +#define GL_MAP2_VERTEX_3 0x0DB7 +#define GL_MAP2_VERTEX_4 0x0DB8 +#define GL_MAP1_GRID_DOMAIN 0x0DD0 +#define GL_MAP1_GRID_SEGMENTS 0x0DD1 +#define GL_MAP2_GRID_DOMAIN 0x0DD2 +#define GL_MAP2_GRID_SEGMENTS 0x0DD3 +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0 +#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1 +#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2 +#define GL_SELECTION_BUFFER_POINTER 0x0DF3 +#define GL_SELECTION_BUFFER_SIZE 0x0DF4 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TRANSFORM_BIT 0x00001000 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_TEXTURE_BORDER 0x1005 +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_AMBIENT 0x1200 +#define GL_DIFFUSE 0x1201 +#define GL_SPECULAR 0x1202 +#define GL_POSITION 0x1203 +#define GL_SPOT_DIRECTION 0x1204 +#define GL_SPOT_EXPONENT 0x1205 +#define GL_SPOT_CUTOFF 0x1206 +#define GL_CONSTANT_ATTENUATION 0x1207 +#define GL_LINEAR_ATTENUATION 0x1208 +#define GL_QUADRATIC_ATTENUATION 0x1209 +#define GL_COMPILE 0x1300 +#define GL_COMPILE_AND_EXECUTE 0x1301 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_2_BYTES 0x1407 +#define GL_3_BYTES 0x1408 +#define GL_4_BYTES 0x1409 +#define GL_DOUBLE 0x140A +#define GL_CLEAR 0x1500 +#define GL_AND 0x1501 +#define GL_AND_REVERSE 0x1502 +#define GL_COPY 0x1503 +#define GL_AND_INVERTED 0x1504 +#define GL_NOOP 0x1505 +#define GL_XOR 0x1506 +#define GL_OR 0x1507 +#define GL_NOR 0x1508 +#define GL_EQUIV 0x1509 +#define GL_INVERT 0x150A +#define GL_OR_REVERSE 0x150B +#define GL_COPY_INVERTED 0x150C +#define GL_OR_INVERTED 0x150D +#define GL_NAND 0x150E +#define GL_SET 0x150F +#define GL_EMISSION 0x1600 +#define GL_SHININESS 0x1601 +#define GL_AMBIENT_AND_DIFFUSE 0x1602 +#define GL_COLOR_INDEXES 0x1603 +#define GL_MODELVIEW 0x1700 +#define GL_PROJECTION 0x1701 +#define GL_TEXTURE 0x1702 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_COLOR_INDEX 0x1900 +#define GL_STENCIL_INDEX 0x1901 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_RED 0x1903 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A +#define GL_BITMAP 0x1A00 +#define GL_POINT 0x1B00 +#define GL_LINE 0x1B01 +#define GL_FILL 0x1B02 +#define GL_RENDER 0x1C00 +#define GL_FEEDBACK 0x1C01 +#define GL_SELECT 0x1C02 +#define GL_FLAT 0x1D00 +#define GL_SMOOTH 0x1D01 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_S 0x2000 +#define GL_ENABLE_BIT 0x00002000 +#define GL_T 0x2001 +#define GL_R 0x2002 +#define GL_Q 0x2003 +#define GL_MODULATE 0x2100 +#define GL_DECAL 0x2101 +#define GL_TEXTURE_ENV_MODE 0x2200 +#define GL_TEXTURE_ENV_COLOR 0x2201 +#define GL_TEXTURE_ENV 0x2300 +#define GL_EYE_LINEAR 0x2400 +#define GL_OBJECT_LINEAR 0x2401 +#define GL_SPHERE_MAP 0x2402 +#define GL_TEXTURE_GEN_MODE 0x2500 +#define GL_OBJECT_PLANE 0x2501 +#define GL_EYE_PLANE 0x2502 +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_CLAMP 0x2900 +#define GL_REPEAT 0x2901 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_POINT 0x2A01 +#define GL_POLYGON_OFFSET_LINE 0x2A02 +#define GL_R3_G3_B2 0x2A10 +#define GL_V2F 0x2A20 +#define GL_V3F 0x2A21 +#define GL_C4UB_V2F 0x2A22 +#define GL_C4UB_V3F 0x2A23 +#define GL_C3F_V3F 0x2A24 +#define GL_N3F_V3F 0x2A25 +#define GL_C4F_N3F_V3F 0x2A26 +#define GL_T2F_V3F 0x2A27 +#define GL_T4F_V4F 0x2A28 +#define GL_T2F_C4UB_V3F 0x2A29 +#define GL_T2F_C3F_V3F 0x2A2A +#define GL_T2F_N3F_V3F 0x2A2B +#define GL_T2F_C4F_N3F_V3F 0x2A2C +#define GL_T4F_C4F_N3F_V4F 0x2A2D +#define GL_CLIP_PLANE0 0x3000 +#define GL_CLIP_PLANE1 0x3001 +#define GL_CLIP_PLANE2 0x3002 +#define GL_CLIP_PLANE3 0x3003 +#define GL_CLIP_PLANE4 0x3004 +#define GL_CLIP_PLANE5 0x3005 +#define GL_LIGHT0 0x4000 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_LIGHT1 0x4001 +#define GL_LIGHT2 0x4002 +#define GL_LIGHT3 0x4003 +#define GL_LIGHT4 0x4004 +#define GL_LIGHT5 0x4005 +#define GL_LIGHT6 0x4006 +#define GL_LIGHT7 0x4007 +#define GL_HINT_BIT 0x00008000 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_ALPHA4 0x803B +#define GL_ALPHA8 0x803C +#define GL_ALPHA12 0x803D +#define GL_ALPHA16 0x803E +#define GL_LUMINANCE4 0x803F +#define GL_LUMINANCE8 0x8040 +#define GL_LUMINANCE12 0x8041 +#define GL_LUMINANCE16 0x8042 +#define GL_LUMINANCE4_ALPHA4 0x8043 +#define GL_LUMINANCE6_ALPHA2 0x8044 +#define GL_LUMINANCE8_ALPHA8 0x8045 +#define GL_LUMINANCE12_ALPHA4 0x8046 +#define GL_LUMINANCE12_ALPHA12 0x8047 +#define GL_LUMINANCE16_ALPHA16 0x8048 +#define GL_INTENSITY 0x8049 +#define GL_INTENSITY4 0x804A +#define GL_INTENSITY8 0x804B +#define GL_INTENSITY12 0x804C +#define GL_INTENSITY16 0x804D +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB8 0x8051 +#define GL_RGB10 0x8052 +#define GL_RGB12 0x8053 +#define GL_RGB16 0x8054 +#define GL_RGBA2 0x8055 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE 0x8061 +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_TEXTURE_PRIORITY 0x8066 +#define GL_TEXTURE_RESIDENT 0x8067 +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_VERTEX_ARRAY 0x8074 +#define GL_NORMAL_ARRAY 0x8075 +#define GL_COLOR_ARRAY 0x8076 +#define GL_INDEX_ARRAY 0x8077 +#define GL_TEXTURE_COORD_ARRAY 0x8078 +#define GL_EDGE_FLAG_ARRAY 0x8079 +#define GL_VERTEX_ARRAY_SIZE 0x807A +#define GL_VERTEX_ARRAY_TYPE 0x807B +#define GL_VERTEX_ARRAY_STRIDE 0x807C +#define GL_NORMAL_ARRAY_TYPE 0x807E +#define GL_NORMAL_ARRAY_STRIDE 0x807F +#define GL_COLOR_ARRAY_SIZE 0x8081 +#define GL_COLOR_ARRAY_TYPE 0x8082 +#define GL_COLOR_ARRAY_STRIDE 0x8083 +#define GL_INDEX_ARRAY_TYPE 0x8085 +#define GL_INDEX_ARRAY_STRIDE 0x8086 +#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A +#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C +#define GL_VERTEX_ARRAY_POINTER 0x808E +#define GL_NORMAL_ARRAY_POINTER 0x808F +#define GL_COLOR_ARRAY_POINTER 0x8090 +#define GL_INDEX_ARRAY_POINTER 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093 +#define GL_COLOR_INDEX1_EXT 0x80E2 +#define GL_COLOR_INDEX2_EXT 0x80E3 +#define GL_COLOR_INDEX4_EXT 0x80E4 +#define GL_COLOR_INDEX8_EXT 0x80E5 +#define GL_COLOR_INDEX12_EXT 0x80E6 +#define GL_COLOR_INDEX16_EXT 0x80E7 +#define GL_EVAL_BIT 0x00010000 +#define GL_LIST_BIT 0x00020000 +#define GL_TEXTURE_BIT 0x00040000 +#define GL_SCISSOR_BIT 0x00080000 +#define GL_ALL_ATTRIB_BITS 0x000fffff +#define GL_CLIENT_ALL_ATTRIB_BITS 0xffffffff + +GLAPI void GLAPIENTRY glAccum (GLenum op, GLfloat value); +GLAPI void GLAPIENTRY glAlphaFunc (GLenum func, GLclampf ref); +GLAPI GLboolean GLAPIENTRY glAreTexturesResident (GLsizei n, const GLuint *textures, GLboolean *residences); +GLAPI void GLAPIENTRY glArrayElement (GLint i); +GLAPI void GLAPIENTRY glBegin (GLenum mode); +GLAPI void GLAPIENTRY glBindTexture (GLenum target, GLuint texture); +GLAPI void GLAPIENTRY glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); +GLAPI void GLAPIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GLAPI void GLAPIENTRY glCallList (GLuint list); +GLAPI void GLAPIENTRY glCallLists (GLsizei n, GLenum type, const GLvoid *lists); +GLAPI void GLAPIENTRY glClear (GLbitfield mask); +GLAPI void GLAPIENTRY glClearAccum (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI void GLAPIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +GLAPI void GLAPIENTRY glClearDepth (GLclampd depth); +GLAPI void GLAPIENTRY glClearIndex (GLfloat c); +GLAPI void GLAPIENTRY glClearStencil (GLint s); +GLAPI void GLAPIENTRY glClipPlane (GLenum plane, const GLdouble *equation); +GLAPI void GLAPIENTRY glColor3b (GLbyte red, GLbyte green, GLbyte blue); +GLAPI void GLAPIENTRY glColor3bv (const GLbyte *v); +GLAPI void GLAPIENTRY glColor3d (GLdouble red, GLdouble green, GLdouble blue); +GLAPI void GLAPIENTRY glColor3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glColor3f (GLfloat red, GLfloat green, GLfloat blue); +GLAPI void GLAPIENTRY glColor3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glColor3i (GLint red, GLint green, GLint blue); +GLAPI void GLAPIENTRY glColor3iv (const GLint *v); +GLAPI void GLAPIENTRY glColor3s (GLshort red, GLshort green, GLshort blue); +GLAPI void GLAPIENTRY glColor3sv (const GLshort *v); +GLAPI void GLAPIENTRY glColor3ub (GLubyte red, GLubyte green, GLubyte blue); +GLAPI void GLAPIENTRY glColor3ubv (const GLubyte *v); +GLAPI void GLAPIENTRY glColor3ui (GLuint red, GLuint green, GLuint blue); +GLAPI void GLAPIENTRY glColor3uiv (const GLuint *v); +GLAPI void GLAPIENTRY glColor3us (GLushort red, GLushort green, GLushort blue); +GLAPI void GLAPIENTRY glColor3usv (const GLushort *v); +GLAPI void GLAPIENTRY glColor4b (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); +GLAPI void GLAPIENTRY glColor4bv (const GLbyte *v); +GLAPI void GLAPIENTRY glColor4d (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); +GLAPI void GLAPIENTRY glColor4dv (const GLdouble *v); +GLAPI void GLAPIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI void GLAPIENTRY glColor4fv (const GLfloat *v); +GLAPI void GLAPIENTRY glColor4i (GLint red, GLint green, GLint blue, GLint alpha); +GLAPI void GLAPIENTRY glColor4iv (const GLint *v); +GLAPI void GLAPIENTRY glColor4s (GLshort red, GLshort green, GLshort blue, GLshort alpha); +GLAPI void GLAPIENTRY glColor4sv (const GLshort *v); +GLAPI void GLAPIENTRY glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +GLAPI void GLAPIENTRY glColor4ubv (const GLubyte *v); +GLAPI void GLAPIENTRY glColor4ui (GLuint red, GLuint green, GLuint blue, GLuint alpha); +GLAPI void GLAPIENTRY glColor4uiv (const GLuint *v); +GLAPI void GLAPIENTRY glColor4us (GLushort red, GLushort green, GLushort blue, GLushort alpha); +GLAPI void GLAPIENTRY glColor4usv (const GLushort *v); +GLAPI void GLAPIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GLAPI void GLAPIENTRY glColorMaterial (GLenum face, GLenum mode); +GLAPI void GLAPIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); +GLAPI void GLAPIENTRY glCopyTexImage1D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); +GLAPI void GLAPIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLAPI void GLAPIENTRY glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +GLAPI void GLAPIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void GLAPIENTRY glCullFace (GLenum mode); +GLAPI void GLAPIENTRY glDeleteLists (GLuint list, GLsizei range); +GLAPI void GLAPIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); +GLAPI void GLAPIENTRY glDepthFunc (GLenum func); +GLAPI void GLAPIENTRY glDepthMask (GLboolean flag); +GLAPI void GLAPIENTRY glDepthRange (GLclampd zNear, GLclampd zFar); +GLAPI void GLAPIENTRY glDisable (GLenum cap); +GLAPI void GLAPIENTRY glDisableClientState (GLenum array); +GLAPI void GLAPIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GLAPI void GLAPIENTRY glDrawBuffer (GLenum mode); +GLAPI void GLAPIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +GLAPI void GLAPIENTRY glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glEdgeFlag (GLboolean flag); +GLAPI void GLAPIENTRY glEdgeFlagPointer (GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glEdgeFlagv (const GLboolean *flag); +GLAPI void GLAPIENTRY glEnable (GLenum cap); +GLAPI void GLAPIENTRY glEnableClientState (GLenum array); +GLAPI void GLAPIENTRY glEnd (void); +GLAPI void GLAPIENTRY glEndList (void); +GLAPI void GLAPIENTRY glEvalCoord1d (GLdouble u); +GLAPI void GLAPIENTRY glEvalCoord1dv (const GLdouble *u); +GLAPI void GLAPIENTRY glEvalCoord1f (GLfloat u); +GLAPI void GLAPIENTRY glEvalCoord1fv (const GLfloat *u); +GLAPI void GLAPIENTRY glEvalCoord2d (GLdouble u, GLdouble v); +GLAPI void GLAPIENTRY glEvalCoord2dv (const GLdouble *u); +GLAPI void GLAPIENTRY glEvalCoord2f (GLfloat u, GLfloat v); +GLAPI void GLAPIENTRY glEvalCoord2fv (const GLfloat *u); +GLAPI void GLAPIENTRY glEvalMesh1 (GLenum mode, GLint i1, GLint i2); +GLAPI void GLAPIENTRY glEvalMesh2 (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); +GLAPI void GLAPIENTRY glEvalPoint1 (GLint i); +GLAPI void GLAPIENTRY glEvalPoint2 (GLint i, GLint j); +GLAPI void GLAPIENTRY glFeedbackBuffer (GLsizei size, GLenum type, GLfloat *buffer); +GLAPI void GLAPIENTRY glFinish (void); +GLAPI void GLAPIENTRY glFlush (void); +GLAPI void GLAPIENTRY glFogf (GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glFogfv (GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glFogi (GLenum pname, GLint param); +GLAPI void GLAPIENTRY glFogiv (GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glFrontFace (GLenum mode); +GLAPI void GLAPIENTRY glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +GLAPI GLuint GLAPIENTRY glGenLists (GLsizei range); +GLAPI void GLAPIENTRY glGenTextures (GLsizei n, GLuint *textures); +GLAPI void GLAPIENTRY glGetBooleanv (GLenum pname, GLboolean *params); +GLAPI void GLAPIENTRY glGetClipPlane (GLenum plane, GLdouble *equation); +GLAPI void GLAPIENTRY glGetDoublev (GLenum pname, GLdouble *params); +GLAPI GLenum GLAPIENTRY glGetError (void); +GLAPI void GLAPIENTRY glGetFloatv (GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetIntegerv (GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetLightfv (GLenum light, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetLightiv (GLenum light, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetMapdv (GLenum target, GLenum query, GLdouble *v); +GLAPI void GLAPIENTRY glGetMapfv (GLenum target, GLenum query, GLfloat *v); +GLAPI void GLAPIENTRY glGetMapiv (GLenum target, GLenum query, GLint *v); +GLAPI void GLAPIENTRY glGetMaterialfv (GLenum face, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetMaterialiv (GLenum face, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetPixelMapfv (GLenum map, GLfloat *values); +GLAPI void GLAPIENTRY glGetPixelMapuiv (GLenum map, GLuint *values); +GLAPI void GLAPIENTRY glGetPixelMapusv (GLenum map, GLushort *values); +GLAPI void GLAPIENTRY glGetPointerv (GLenum pname, GLvoid* *params); +GLAPI void GLAPIENTRY glGetPolygonStipple (GLubyte *mask); +GLAPI const GLubyte * GLAPIENTRY glGetString (GLenum name); +GLAPI void GLAPIENTRY glGetTexEnvfv (GLenum target, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexEnviv (GLenum target, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetTexGendv (GLenum coord, GLenum pname, GLdouble *params); +GLAPI void GLAPIENTRY glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexGeniv (GLenum coord, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +GLAPI void GLAPIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glHint (GLenum target, GLenum mode); +GLAPI void GLAPIENTRY glIndexMask (GLuint mask); +GLAPI void GLAPIENTRY glIndexPointer (GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glIndexd (GLdouble c); +GLAPI void GLAPIENTRY glIndexdv (const GLdouble *c); +GLAPI void GLAPIENTRY glIndexf (GLfloat c); +GLAPI void GLAPIENTRY glIndexfv (const GLfloat *c); +GLAPI void GLAPIENTRY glIndexi (GLint c); +GLAPI void GLAPIENTRY glIndexiv (const GLint *c); +GLAPI void GLAPIENTRY glIndexs (GLshort c); +GLAPI void GLAPIENTRY glIndexsv (const GLshort *c); +GLAPI void GLAPIENTRY glIndexub (GLubyte c); +GLAPI void GLAPIENTRY glIndexubv (const GLubyte *c); +GLAPI void GLAPIENTRY glInitNames (void); +GLAPI void GLAPIENTRY glInterleavedArrays (GLenum format, GLsizei stride, const GLvoid *pointer); +GLAPI GLboolean GLAPIENTRY glIsEnabled (GLenum cap); +GLAPI GLboolean GLAPIENTRY glIsList (GLuint list); +GLAPI GLboolean GLAPIENTRY glIsTexture (GLuint texture); +GLAPI void GLAPIENTRY glLightModelf (GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glLightModelfv (GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glLightModeli (GLenum pname, GLint param); +GLAPI void GLAPIENTRY glLightModeliv (GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glLightf (GLenum light, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glLighti (GLenum light, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glLightiv (GLenum light, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glLineStipple (GLint factor, GLushort pattern); +GLAPI void GLAPIENTRY glLineWidth (GLfloat width); +GLAPI void GLAPIENTRY glListBase (GLuint base); +GLAPI void GLAPIENTRY glLoadIdentity (void); +GLAPI void GLAPIENTRY glLoadMatrixd (const GLdouble *m); +GLAPI void GLAPIENTRY glLoadMatrixf (const GLfloat *m); +GLAPI void GLAPIENTRY glLoadName (GLuint name); +GLAPI void GLAPIENTRY glLogicOp (GLenum opcode); +GLAPI void GLAPIENTRY glMap1d (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); +GLAPI void GLAPIENTRY glMap1f (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); +GLAPI void GLAPIENTRY glMap2d (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); +GLAPI void GLAPIENTRY glMap2f (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); +GLAPI void GLAPIENTRY glMapGrid1d (GLint un, GLdouble u1, GLdouble u2); +GLAPI void GLAPIENTRY glMapGrid1f (GLint un, GLfloat u1, GLfloat u2); +GLAPI void GLAPIENTRY glMapGrid2d (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); +GLAPI void GLAPIENTRY glMapGrid2f (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); +GLAPI void GLAPIENTRY glMaterialf (GLenum face, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glMateriali (GLenum face, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glMaterialiv (GLenum face, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glMatrixMode (GLenum mode); +GLAPI void GLAPIENTRY glMultMatrixd (const GLdouble *m); +GLAPI void GLAPIENTRY glMultMatrixf (const GLfloat *m); +GLAPI void GLAPIENTRY glNewList (GLuint list, GLenum mode); +GLAPI void GLAPIENTRY glNormal3b (GLbyte nx, GLbyte ny, GLbyte nz); +GLAPI void GLAPIENTRY glNormal3bv (const GLbyte *v); +GLAPI void GLAPIENTRY glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz); +GLAPI void GLAPIENTRY glNormal3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz); +GLAPI void GLAPIENTRY glNormal3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glNormal3i (GLint nx, GLint ny, GLint nz); +GLAPI void GLAPIENTRY glNormal3iv (const GLint *v); +GLAPI void GLAPIENTRY glNormal3s (GLshort nx, GLshort ny, GLshort nz); +GLAPI void GLAPIENTRY glNormal3sv (const GLshort *v); +GLAPI void GLAPIENTRY glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +GLAPI void GLAPIENTRY glPassThrough (GLfloat token); +GLAPI void GLAPIENTRY glPixelMapfv (GLenum map, GLsizei mapsize, const GLfloat *values); +GLAPI void GLAPIENTRY glPixelMapuiv (GLenum map, GLsizei mapsize, const GLuint *values); +GLAPI void GLAPIENTRY glPixelMapusv (GLenum map, GLsizei mapsize, const GLushort *values); +GLAPI void GLAPIENTRY glPixelStoref (GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glPixelStorei (GLenum pname, GLint param); +GLAPI void GLAPIENTRY glPixelTransferf (GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glPixelTransferi (GLenum pname, GLint param); +GLAPI void GLAPIENTRY glPixelZoom (GLfloat xfactor, GLfloat yfactor); +GLAPI void GLAPIENTRY glPointSize (GLfloat size); +GLAPI void GLAPIENTRY glPolygonMode (GLenum face, GLenum mode); +GLAPI void GLAPIENTRY glPolygonOffset (GLfloat factor, GLfloat units); +GLAPI void GLAPIENTRY glPolygonStipple (const GLubyte *mask); +GLAPI void GLAPIENTRY glPopAttrib (void); +GLAPI void GLAPIENTRY glPopClientAttrib (void); +GLAPI void GLAPIENTRY glPopMatrix (void); +GLAPI void GLAPIENTRY glPopName (void); +GLAPI void GLAPIENTRY glPrioritizeTextures (GLsizei n, const GLuint *textures, const GLclampf *priorities); +GLAPI void GLAPIENTRY glPushAttrib (GLbitfield mask); +GLAPI void GLAPIENTRY glPushClientAttrib (GLbitfield mask); +GLAPI void GLAPIENTRY glPushMatrix (void); +GLAPI void GLAPIENTRY glPushName (GLuint name); +GLAPI void GLAPIENTRY glRasterPos2d (GLdouble x, GLdouble y); +GLAPI void GLAPIENTRY glRasterPos2dv (const GLdouble *v); +GLAPI void GLAPIENTRY glRasterPos2f (GLfloat x, GLfloat y); +GLAPI void GLAPIENTRY glRasterPos2fv (const GLfloat *v); +GLAPI void GLAPIENTRY glRasterPos2i (GLint x, GLint y); +GLAPI void GLAPIENTRY glRasterPos2iv (const GLint *v); +GLAPI void GLAPIENTRY glRasterPos2s (GLshort x, GLshort y); +GLAPI void GLAPIENTRY glRasterPos2sv (const GLshort *v); +GLAPI void GLAPIENTRY glRasterPos3d (GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glRasterPos3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glRasterPos3f (GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glRasterPos3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glRasterPos3i (GLint x, GLint y, GLint z); +GLAPI void GLAPIENTRY glRasterPos3iv (const GLint *v); +GLAPI void GLAPIENTRY glRasterPos3s (GLshort x, GLshort y, GLshort z); +GLAPI void GLAPIENTRY glRasterPos3sv (const GLshort *v); +GLAPI void GLAPIENTRY glRasterPos4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void GLAPIENTRY glRasterPos4dv (const GLdouble *v); +GLAPI void GLAPIENTRY glRasterPos4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void GLAPIENTRY glRasterPos4fv (const GLfloat *v); +GLAPI void GLAPIENTRY glRasterPos4i (GLint x, GLint y, GLint z, GLint w); +GLAPI void GLAPIENTRY glRasterPos4iv (const GLint *v); +GLAPI void GLAPIENTRY glRasterPos4s (GLshort x, GLshort y, GLshort z, GLshort w); +GLAPI void GLAPIENTRY glRasterPos4sv (const GLshort *v); +GLAPI void GLAPIENTRY glReadBuffer (GLenum mode); +GLAPI void GLAPIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); +GLAPI void GLAPIENTRY glRectd (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); +GLAPI void GLAPIENTRY glRectdv (const GLdouble *v1, const GLdouble *v2); +GLAPI void GLAPIENTRY glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); +GLAPI void GLAPIENTRY glRectfv (const GLfloat *v1, const GLfloat *v2); +GLAPI void GLAPIENTRY glRecti (GLint x1, GLint y1, GLint x2, GLint y2); +GLAPI void GLAPIENTRY glRectiv (const GLint *v1, const GLint *v2); +GLAPI void GLAPIENTRY glRects (GLshort x1, GLshort y1, GLshort x2, GLshort y2); +GLAPI void GLAPIENTRY glRectsv (const GLshort *v1, const GLshort *v2); +GLAPI GLint GLAPIENTRY glRenderMode (GLenum mode); +GLAPI void GLAPIENTRY glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glScaled (GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void GLAPIENTRY glSelectBuffer (GLsizei size, GLuint *buffer); +GLAPI void GLAPIENTRY glShadeModel (GLenum mode); +GLAPI void GLAPIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GLAPI void GLAPIENTRY glStencilMask (GLuint mask); +GLAPI void GLAPIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +GLAPI void GLAPIENTRY glTexCoord1d (GLdouble s); +GLAPI void GLAPIENTRY glTexCoord1dv (const GLdouble *v); +GLAPI void GLAPIENTRY glTexCoord1f (GLfloat s); +GLAPI void GLAPIENTRY glTexCoord1fv (const GLfloat *v); +GLAPI void GLAPIENTRY glTexCoord1i (GLint s); +GLAPI void GLAPIENTRY glTexCoord1iv (const GLint *v); +GLAPI void GLAPIENTRY glTexCoord1s (GLshort s); +GLAPI void GLAPIENTRY glTexCoord1sv (const GLshort *v); +GLAPI void GLAPIENTRY glTexCoord2d (GLdouble s, GLdouble t); +GLAPI void GLAPIENTRY glTexCoord2dv (const GLdouble *v); +GLAPI void GLAPIENTRY glTexCoord2f (GLfloat s, GLfloat t); +GLAPI void GLAPIENTRY glTexCoord2fv (const GLfloat *v); +GLAPI void GLAPIENTRY glTexCoord2i (GLint s, GLint t); +GLAPI void GLAPIENTRY glTexCoord2iv (const GLint *v); +GLAPI void GLAPIENTRY glTexCoord2s (GLshort s, GLshort t); +GLAPI void GLAPIENTRY glTexCoord2sv (const GLshort *v); +GLAPI void GLAPIENTRY glTexCoord3d (GLdouble s, GLdouble t, GLdouble r); +GLAPI void GLAPIENTRY glTexCoord3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glTexCoord3f (GLfloat s, GLfloat t, GLfloat r); +GLAPI void GLAPIENTRY glTexCoord3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glTexCoord3i (GLint s, GLint t, GLint r); +GLAPI void GLAPIENTRY glTexCoord3iv (const GLint *v); +GLAPI void GLAPIENTRY glTexCoord3s (GLshort s, GLshort t, GLshort r); +GLAPI void GLAPIENTRY glTexCoord3sv (const GLshort *v); +GLAPI void GLAPIENTRY glTexCoord4d (GLdouble s, GLdouble t, GLdouble r, GLdouble q); +GLAPI void GLAPIENTRY glTexCoord4dv (const GLdouble *v); +GLAPI void GLAPIENTRY glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q); +GLAPI void GLAPIENTRY glTexCoord4fv (const GLfloat *v); +GLAPI void GLAPIENTRY glTexCoord4i (GLint s, GLint t, GLint r, GLint q); +GLAPI void GLAPIENTRY glTexCoord4iv (const GLint *v); +GLAPI void GLAPIENTRY glTexCoord4s (GLshort s, GLshort t, GLshort r, GLshort q); +GLAPI void GLAPIENTRY glTexCoord4sv (const GLshort *v); +GLAPI void GLAPIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glTexEnvf (GLenum target, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glTexEnvi (GLenum target, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glTexEnviv (GLenum target, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glTexGend (GLenum coord, GLenum pname, GLdouble param); +GLAPI void GLAPIENTRY glTexGendv (GLenum coord, GLenum pname, const GLdouble *params); +GLAPI void GLAPIENTRY glTexGenf (GLenum coord, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glTexGeni (GLenum coord, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glTexGeniv (GLenum coord, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTranslated (GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glVertex2d (GLdouble x, GLdouble y); +GLAPI void GLAPIENTRY glVertex2dv (const GLdouble *v); +GLAPI void GLAPIENTRY glVertex2f (GLfloat x, GLfloat y); +GLAPI void GLAPIENTRY glVertex2fv (const GLfloat *v); +GLAPI void GLAPIENTRY glVertex2i (GLint x, GLint y); +GLAPI void GLAPIENTRY glVertex2iv (const GLint *v); +GLAPI void GLAPIENTRY glVertex2s (GLshort x, GLshort y); +GLAPI void GLAPIENTRY glVertex2sv (const GLshort *v); +GLAPI void GLAPIENTRY glVertex3d (GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glVertex3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glVertex3f (GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glVertex3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glVertex3i (GLint x, GLint y, GLint z); +GLAPI void GLAPIENTRY glVertex3iv (const GLint *v); +GLAPI void GLAPIENTRY glVertex3s (GLshort x, GLshort y, GLshort z); +GLAPI void GLAPIENTRY glVertex3sv (const GLshort *v); +GLAPI void GLAPIENTRY glVertex4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void GLAPIENTRY glVertex4dv (const GLdouble *v); +GLAPI void GLAPIENTRY glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void GLAPIENTRY glVertex4fv (const GLfloat *v); +GLAPI void GLAPIENTRY glVertex4i (GLint x, GLint y, GLint z, GLint w); +GLAPI void GLAPIENTRY glVertex4iv (const GLint *v); +GLAPI void GLAPIENTRY glVertex4s (GLshort x, GLshort y, GLshort z, GLshort w); +GLAPI void GLAPIENTRY glVertex4sv (const GLshort *v); +GLAPI void GLAPIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); + +#define GLEW_VERSION_1_1 GLEW_GET_VAR(__GLEW_VERSION_1_1) + +#endif /* GL_VERSION_1_1 */ + +/* ---------------------------------- GLU ---------------------------------- */ + +#ifndef GLEW_NO_GLU +/* this is where we can safely include GLU */ +# if defined(__APPLE__) && defined(__MACH__) +# include +# else +# include +# endif +#endif + +/* ----------------------------- GL_VERSION_1_2 ---------------------------- */ + +#ifndef GL_VERSION_1_2 +#define GL_VERSION_1_2 1 + +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_RESCALE_NORMAL 0x803A +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 +#define GL_SINGLE_COLOR 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR 0x81FA +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E + +typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); + +#define glCopyTexSubImage3D GLEW_GET_FUN(__glewCopyTexSubImage3D) +#define glDrawRangeElements GLEW_GET_FUN(__glewDrawRangeElements) +#define glTexImage3D GLEW_GET_FUN(__glewTexImage3D) +#define glTexSubImage3D GLEW_GET_FUN(__glewTexSubImage3D) + +#define GLEW_VERSION_1_2 GLEW_GET_VAR(__GLEW_VERSION_1_2) + +#endif /* GL_VERSION_1_2 */ + +/* ---------------------------- GL_VERSION_1_2_1 --------------------------- */ + +#ifndef GL_VERSION_1_2_1 +#define GL_VERSION_1_2_1 1 + +#define GLEW_VERSION_1_2_1 GLEW_GET_VAR(__GLEW_VERSION_1_2_1) + +#endif /* GL_VERSION_1_2_1 */ + +/* ----------------------------- GL_VERSION_1_3 ---------------------------- */ + +#ifndef GL_VERSION_1_3 +#define GL_VERSION_1_3 1 + +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 +#define GL_MAX_TEXTURE_UNITS 0x84E2 +#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 +#define GL_SUBTRACT 0x84E7 +#define GL_COMPRESSED_ALPHA 0x84E9 +#define GL_COMPRESSED_LUMINANCE 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB +#define GL_COMPRESSED_INTENSITY 0x84EC +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_NORMAL_MAP 0x8511 +#define GL_REFLECTION_MAP 0x8512 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_COMBINE 0x8570 +#define GL_COMBINE_RGB 0x8571 +#define GL_COMBINE_ALPHA 0x8572 +#define GL_RGB_SCALE 0x8573 +#define GL_ADD_SIGNED 0x8574 +#define GL_INTERPOLATE 0x8575 +#define GL_CONSTANT 0x8576 +#define GL_PRIMARY_COLOR 0x8577 +#define GL_PREVIOUS 0x8578 +#define GL_SOURCE0_RGB 0x8580 +#define GL_SOURCE1_RGB 0x8581 +#define GL_SOURCE2_RGB 0x8582 +#define GL_SOURCE0_ALPHA 0x8588 +#define GL_SOURCE1_ALPHA 0x8589 +#define GL_SOURCE2_ALPHA 0x858A +#define GL_OPERAND0_RGB 0x8590 +#define GL_OPERAND1_RGB 0x8591 +#define GL_OPERAND2_RGB 0x8592 +#define GL_OPERAND0_ALPHA 0x8598 +#define GL_OPERAND1_ALPHA 0x8599 +#define GL_OPERAND2_ALPHA 0x859A +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_DOT3_RGB 0x86AE +#define GL_DOT3_RGBA 0x86AF +#define GL_MULTISAMPLE_BIT 0x20000000 + +typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture); +typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint lod, GLvoid *img); +typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble m[16]); +typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat m[16]); +typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble m[16]); +typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat m[16]); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert); + +#define glActiveTexture GLEW_GET_FUN(__glewActiveTexture) +#define glClientActiveTexture GLEW_GET_FUN(__glewClientActiveTexture) +#define glCompressedTexImage1D GLEW_GET_FUN(__glewCompressedTexImage1D) +#define glCompressedTexImage2D GLEW_GET_FUN(__glewCompressedTexImage2D) +#define glCompressedTexImage3D GLEW_GET_FUN(__glewCompressedTexImage3D) +#define glCompressedTexSubImage1D GLEW_GET_FUN(__glewCompressedTexSubImage1D) +#define glCompressedTexSubImage2D GLEW_GET_FUN(__glewCompressedTexSubImage2D) +#define glCompressedTexSubImage3D GLEW_GET_FUN(__glewCompressedTexSubImage3D) +#define glGetCompressedTexImage GLEW_GET_FUN(__glewGetCompressedTexImage) +#define glLoadTransposeMatrixd GLEW_GET_FUN(__glewLoadTransposeMatrixd) +#define glLoadTransposeMatrixf GLEW_GET_FUN(__glewLoadTransposeMatrixf) +#define glMultTransposeMatrixd GLEW_GET_FUN(__glewMultTransposeMatrixd) +#define glMultTransposeMatrixf GLEW_GET_FUN(__glewMultTransposeMatrixf) +#define glMultiTexCoord1d GLEW_GET_FUN(__glewMultiTexCoord1d) +#define glMultiTexCoord1dv GLEW_GET_FUN(__glewMultiTexCoord1dv) +#define glMultiTexCoord1f GLEW_GET_FUN(__glewMultiTexCoord1f) +#define glMultiTexCoord1fv GLEW_GET_FUN(__glewMultiTexCoord1fv) +#define glMultiTexCoord1i GLEW_GET_FUN(__glewMultiTexCoord1i) +#define glMultiTexCoord1iv GLEW_GET_FUN(__glewMultiTexCoord1iv) +#define glMultiTexCoord1s GLEW_GET_FUN(__glewMultiTexCoord1s) +#define glMultiTexCoord1sv GLEW_GET_FUN(__glewMultiTexCoord1sv) +#define glMultiTexCoord2d GLEW_GET_FUN(__glewMultiTexCoord2d) +#define glMultiTexCoord2dv GLEW_GET_FUN(__glewMultiTexCoord2dv) +#define glMultiTexCoord2f GLEW_GET_FUN(__glewMultiTexCoord2f) +#define glMultiTexCoord2fv GLEW_GET_FUN(__glewMultiTexCoord2fv) +#define glMultiTexCoord2i GLEW_GET_FUN(__glewMultiTexCoord2i) +#define glMultiTexCoord2iv GLEW_GET_FUN(__glewMultiTexCoord2iv) +#define glMultiTexCoord2s GLEW_GET_FUN(__glewMultiTexCoord2s) +#define glMultiTexCoord2sv GLEW_GET_FUN(__glewMultiTexCoord2sv) +#define glMultiTexCoord3d GLEW_GET_FUN(__glewMultiTexCoord3d) +#define glMultiTexCoord3dv GLEW_GET_FUN(__glewMultiTexCoord3dv) +#define glMultiTexCoord3f GLEW_GET_FUN(__glewMultiTexCoord3f) +#define glMultiTexCoord3fv GLEW_GET_FUN(__glewMultiTexCoord3fv) +#define glMultiTexCoord3i GLEW_GET_FUN(__glewMultiTexCoord3i) +#define glMultiTexCoord3iv GLEW_GET_FUN(__glewMultiTexCoord3iv) +#define glMultiTexCoord3s GLEW_GET_FUN(__glewMultiTexCoord3s) +#define glMultiTexCoord3sv GLEW_GET_FUN(__glewMultiTexCoord3sv) +#define glMultiTexCoord4d GLEW_GET_FUN(__glewMultiTexCoord4d) +#define glMultiTexCoord4dv GLEW_GET_FUN(__glewMultiTexCoord4dv) +#define glMultiTexCoord4f GLEW_GET_FUN(__glewMultiTexCoord4f) +#define glMultiTexCoord4fv GLEW_GET_FUN(__glewMultiTexCoord4fv) +#define glMultiTexCoord4i GLEW_GET_FUN(__glewMultiTexCoord4i) +#define glMultiTexCoord4iv GLEW_GET_FUN(__glewMultiTexCoord4iv) +#define glMultiTexCoord4s GLEW_GET_FUN(__glewMultiTexCoord4s) +#define glMultiTexCoord4sv GLEW_GET_FUN(__glewMultiTexCoord4sv) +#define glSampleCoverage GLEW_GET_FUN(__glewSampleCoverage) + +#define GLEW_VERSION_1_3 GLEW_GET_VAR(__GLEW_VERSION_1_3) + +#endif /* GL_VERSION_1_3 */ + +/* ----------------------------- GL_VERSION_1_4 ---------------------------- */ + +#ifndef GL_VERSION_1_4 +#define GL_VERSION_1_4 1 + +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_POINT_SIZE_MIN 0x8126 +#define GL_POINT_SIZE_MAX 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION 0x8129 +#define GL_GENERATE_MIPMAP 0x8191 +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_FOG_COORDINATE_SOURCE 0x8450 +#define GL_FOG_COORDINATE 0x8451 +#define GL_FRAGMENT_DEPTH 0x8452 +#define GL_CURRENT_FOG_COORDINATE 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456 +#define GL_FOG_COORDINATE_ARRAY 0x8457 +#define GL_COLOR_SUM 0x8458 +#define GL_CURRENT_SECONDARY_COLOR 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D +#define GL_SECONDARY_COLOR_ARRAY 0x845E +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_FILTER_CONTROL 0x8500 +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_DEPTH_TEXTURE_MODE 0x884B +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_COMPARE_R_TO_TEXTURE 0x884E + +typedef void (GLAPIENTRY * PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONPROC) (GLenum mode); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLFOGCOORDDPROC) (GLdouble coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDDVPROC) (const GLdouble *coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFPROC) (GLfloat coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFVPROC) (const GLfloat *coord); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVPROC) (const GLdouble *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVPROC) (const GLfloat *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IPROC) (GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVPROC) (const GLint *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVPROC) (const GLshort *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVPROC) (const GLdouble *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVPROC) (const GLfloat *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVPROC) (const GLint *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVPROC) (const GLshort *p); + +#define glBlendColor GLEW_GET_FUN(__glewBlendColor) +#define glBlendEquation GLEW_GET_FUN(__glewBlendEquation) +#define glBlendFuncSeparate GLEW_GET_FUN(__glewBlendFuncSeparate) +#define glFogCoordPointer GLEW_GET_FUN(__glewFogCoordPointer) +#define glFogCoordd GLEW_GET_FUN(__glewFogCoordd) +#define glFogCoorddv GLEW_GET_FUN(__glewFogCoorddv) +#define glFogCoordf GLEW_GET_FUN(__glewFogCoordf) +#define glFogCoordfv GLEW_GET_FUN(__glewFogCoordfv) +#define glMultiDrawArrays GLEW_GET_FUN(__glewMultiDrawArrays) +#define glMultiDrawElements GLEW_GET_FUN(__glewMultiDrawElements) +#define glPointParameterf GLEW_GET_FUN(__glewPointParameterf) +#define glPointParameterfv GLEW_GET_FUN(__glewPointParameterfv) +#define glPointParameteri GLEW_GET_FUN(__glewPointParameteri) +#define glPointParameteriv GLEW_GET_FUN(__glewPointParameteriv) +#define glSecondaryColor3b GLEW_GET_FUN(__glewSecondaryColor3b) +#define glSecondaryColor3bv GLEW_GET_FUN(__glewSecondaryColor3bv) +#define glSecondaryColor3d GLEW_GET_FUN(__glewSecondaryColor3d) +#define glSecondaryColor3dv GLEW_GET_FUN(__glewSecondaryColor3dv) +#define glSecondaryColor3f GLEW_GET_FUN(__glewSecondaryColor3f) +#define glSecondaryColor3fv GLEW_GET_FUN(__glewSecondaryColor3fv) +#define glSecondaryColor3i GLEW_GET_FUN(__glewSecondaryColor3i) +#define glSecondaryColor3iv GLEW_GET_FUN(__glewSecondaryColor3iv) +#define glSecondaryColor3s GLEW_GET_FUN(__glewSecondaryColor3s) +#define glSecondaryColor3sv GLEW_GET_FUN(__glewSecondaryColor3sv) +#define glSecondaryColor3ub GLEW_GET_FUN(__glewSecondaryColor3ub) +#define glSecondaryColor3ubv GLEW_GET_FUN(__glewSecondaryColor3ubv) +#define glSecondaryColor3ui GLEW_GET_FUN(__glewSecondaryColor3ui) +#define glSecondaryColor3uiv GLEW_GET_FUN(__glewSecondaryColor3uiv) +#define glSecondaryColor3us GLEW_GET_FUN(__glewSecondaryColor3us) +#define glSecondaryColor3usv GLEW_GET_FUN(__glewSecondaryColor3usv) +#define glSecondaryColorPointer GLEW_GET_FUN(__glewSecondaryColorPointer) +#define glWindowPos2d GLEW_GET_FUN(__glewWindowPos2d) +#define glWindowPos2dv GLEW_GET_FUN(__glewWindowPos2dv) +#define glWindowPos2f GLEW_GET_FUN(__glewWindowPos2f) +#define glWindowPos2fv GLEW_GET_FUN(__glewWindowPos2fv) +#define glWindowPos2i GLEW_GET_FUN(__glewWindowPos2i) +#define glWindowPos2iv GLEW_GET_FUN(__glewWindowPos2iv) +#define glWindowPos2s GLEW_GET_FUN(__glewWindowPos2s) +#define glWindowPos2sv GLEW_GET_FUN(__glewWindowPos2sv) +#define glWindowPos3d GLEW_GET_FUN(__glewWindowPos3d) +#define glWindowPos3dv GLEW_GET_FUN(__glewWindowPos3dv) +#define glWindowPos3f GLEW_GET_FUN(__glewWindowPos3f) +#define glWindowPos3fv GLEW_GET_FUN(__glewWindowPos3fv) +#define glWindowPos3i GLEW_GET_FUN(__glewWindowPos3i) +#define glWindowPos3iv GLEW_GET_FUN(__glewWindowPos3iv) +#define glWindowPos3s GLEW_GET_FUN(__glewWindowPos3s) +#define glWindowPos3sv GLEW_GET_FUN(__glewWindowPos3sv) + +#define GLEW_VERSION_1_4 GLEW_GET_VAR(__GLEW_VERSION_1_4) + +#endif /* GL_VERSION_1_4 */ + +/* ----------------------------- GL_VERSION_1_5 ---------------------------- */ + +#ifndef GL_VERSION_1_5 +#define GL_VERSION_1_5 1 + +#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE +#define GL_FOG_COORD GL_FOG_COORDINATE +#define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY +#define GL_SRC0_RGB GL_SOURCE0_RGB +#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER +#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE +#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA +#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE +#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE +#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA +#define GL_SRC1_RGB GL_SOURCE1_RGB +#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING +#define GL_SRC2_ALPHA GL_SOURCE2_ALPHA +#define GL_SRC2_RGB GL_SOURCE2_RGB +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_SAMPLES_PASSED 0x8914 + +typedef ptrdiff_t GLintptr; +typedef ptrdiff_t GLsizeiptr; + +typedef void (GLAPIENTRY * PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); +typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLENDQUERYPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLGENQUERIESPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid** params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERPROC) (GLuint buffer); +typedef GLboolean (GLAPIENTRY * PFNGLISQUERYPROC) (GLuint id); +typedef GLvoid* (GLAPIENTRY * PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); +typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERPROC) (GLenum target); + +#define glBeginQuery GLEW_GET_FUN(__glewBeginQuery) +#define glBindBuffer GLEW_GET_FUN(__glewBindBuffer) +#define glBufferData GLEW_GET_FUN(__glewBufferData) +#define glBufferSubData GLEW_GET_FUN(__glewBufferSubData) +#define glDeleteBuffers GLEW_GET_FUN(__glewDeleteBuffers) +#define glDeleteQueries GLEW_GET_FUN(__glewDeleteQueries) +#define glEndQuery GLEW_GET_FUN(__glewEndQuery) +#define glGenBuffers GLEW_GET_FUN(__glewGenBuffers) +#define glGenQueries GLEW_GET_FUN(__glewGenQueries) +#define glGetBufferParameteriv GLEW_GET_FUN(__glewGetBufferParameteriv) +#define glGetBufferPointerv GLEW_GET_FUN(__glewGetBufferPointerv) +#define glGetBufferSubData GLEW_GET_FUN(__glewGetBufferSubData) +#define glGetQueryObjectiv GLEW_GET_FUN(__glewGetQueryObjectiv) +#define glGetQueryObjectuiv GLEW_GET_FUN(__glewGetQueryObjectuiv) +#define glGetQueryiv GLEW_GET_FUN(__glewGetQueryiv) +#define glIsBuffer GLEW_GET_FUN(__glewIsBuffer) +#define glIsQuery GLEW_GET_FUN(__glewIsQuery) +#define glMapBuffer GLEW_GET_FUN(__glewMapBuffer) +#define glUnmapBuffer GLEW_GET_FUN(__glewUnmapBuffer) + +#define GLEW_VERSION_1_5 GLEW_GET_VAR(__GLEW_VERSION_1_5) + +#endif /* GL_VERSION_1_5 */ + +/* ----------------------------- GL_VERSION_2_0 ---------------------------- */ + +#ifndef GL_VERSION_2_0 +#define GL_VERSION_2_0 1 + +#define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_POINT_SPRITE 0x8861 +#define GL_COORD_REPLACE 0x8862 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_MAX_TEXTURE_COORDS 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_SHADER_TYPE 0x8B4F +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_DELETE_STATUS 0x8B80 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 + +typedef void (GLAPIENTRY * PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar* name); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum, GLenum); +typedef void (GLAPIENTRY * PFNGLCOMPILESHADERPROC) (GLuint shader); +typedef GLuint (GLAPIENTRY * PFNGLCREATEPROGRAMPROC) (void); +typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROC) (GLenum type); +typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLDELETESHADERPROC) (GLuint shader); +typedef void (GLAPIENTRY * PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint); +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum* bufs); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint); +typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders); +typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint* param); +typedef void (GLAPIENTRY * PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog); +typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEPROC) (GLuint obj, GLsizei maxLength, GLsizei* length, GLchar* source); +typedef void (GLAPIENTRY * PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint* param); +typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint, GLenum, GLvoid**); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVPROC) (GLuint, GLenum, GLdouble*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVPROC) (GLuint, GLenum, GLfloat*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVPROC) (GLuint, GLenum, GLint*); +typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPROC) (GLuint program); +typedef GLboolean (GLAPIENTRY * PFNGLISSHADERPROC) (GLuint shader); +typedef void (GLAPIENTRY * PFNGLLINKPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar** strings, const GLint* lengths); +typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); +typedef void (GLAPIENTRY * PFNGLSTENCILMASKSEPARATEPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (GLAPIENTRY * PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1IPROC) (GLint location, GLint v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUSEPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer); + +#define glAttachShader GLEW_GET_FUN(__glewAttachShader) +#define glBindAttribLocation GLEW_GET_FUN(__glewBindAttribLocation) +#define glBlendEquationSeparate GLEW_GET_FUN(__glewBlendEquationSeparate) +#define glCompileShader GLEW_GET_FUN(__glewCompileShader) +#define glCreateProgram GLEW_GET_FUN(__glewCreateProgram) +#define glCreateShader GLEW_GET_FUN(__glewCreateShader) +#define glDeleteProgram GLEW_GET_FUN(__glewDeleteProgram) +#define glDeleteShader GLEW_GET_FUN(__glewDeleteShader) +#define glDetachShader GLEW_GET_FUN(__glewDetachShader) +#define glDisableVertexAttribArray GLEW_GET_FUN(__glewDisableVertexAttribArray) +#define glDrawBuffers GLEW_GET_FUN(__glewDrawBuffers) +#define glEnableVertexAttribArray GLEW_GET_FUN(__glewEnableVertexAttribArray) +#define glGetActiveAttrib GLEW_GET_FUN(__glewGetActiveAttrib) +#define glGetActiveUniform GLEW_GET_FUN(__glewGetActiveUniform) +#define glGetAttachedShaders GLEW_GET_FUN(__glewGetAttachedShaders) +#define glGetAttribLocation GLEW_GET_FUN(__glewGetAttribLocation) +#define glGetProgramInfoLog GLEW_GET_FUN(__glewGetProgramInfoLog) +#define glGetProgramiv GLEW_GET_FUN(__glewGetProgramiv) +#define glGetShaderInfoLog GLEW_GET_FUN(__glewGetShaderInfoLog) +#define glGetShaderSource GLEW_GET_FUN(__glewGetShaderSource) +#define glGetShaderiv GLEW_GET_FUN(__glewGetShaderiv) +#define glGetUniformLocation GLEW_GET_FUN(__glewGetUniformLocation) +#define glGetUniformfv GLEW_GET_FUN(__glewGetUniformfv) +#define glGetUniformiv GLEW_GET_FUN(__glewGetUniformiv) +#define glGetVertexAttribPointerv GLEW_GET_FUN(__glewGetVertexAttribPointerv) +#define glGetVertexAttribdv GLEW_GET_FUN(__glewGetVertexAttribdv) +#define glGetVertexAttribfv GLEW_GET_FUN(__glewGetVertexAttribfv) +#define glGetVertexAttribiv GLEW_GET_FUN(__glewGetVertexAttribiv) +#define glIsProgram GLEW_GET_FUN(__glewIsProgram) +#define glIsShader GLEW_GET_FUN(__glewIsShader) +#define glLinkProgram GLEW_GET_FUN(__glewLinkProgram) +#define glShaderSource GLEW_GET_FUN(__glewShaderSource) +#define glStencilFuncSeparate GLEW_GET_FUN(__glewStencilFuncSeparate) +#define glStencilMaskSeparate GLEW_GET_FUN(__glewStencilMaskSeparate) +#define glStencilOpSeparate GLEW_GET_FUN(__glewStencilOpSeparate) +#define glUniform1f GLEW_GET_FUN(__glewUniform1f) +#define glUniform1fv GLEW_GET_FUN(__glewUniform1fv) +#define glUniform1i GLEW_GET_FUN(__glewUniform1i) +#define glUniform1iv GLEW_GET_FUN(__glewUniform1iv) +#define glUniform2f GLEW_GET_FUN(__glewUniform2f) +#define glUniform2fv GLEW_GET_FUN(__glewUniform2fv) +#define glUniform2i GLEW_GET_FUN(__glewUniform2i) +#define glUniform2iv GLEW_GET_FUN(__glewUniform2iv) +#define glUniform3f GLEW_GET_FUN(__glewUniform3f) +#define glUniform3fv GLEW_GET_FUN(__glewUniform3fv) +#define glUniform3i GLEW_GET_FUN(__glewUniform3i) +#define glUniform3iv GLEW_GET_FUN(__glewUniform3iv) +#define glUniform4f GLEW_GET_FUN(__glewUniform4f) +#define glUniform4fv GLEW_GET_FUN(__glewUniform4fv) +#define glUniform4i GLEW_GET_FUN(__glewUniform4i) +#define glUniform4iv GLEW_GET_FUN(__glewUniform4iv) +#define glUniformMatrix2fv GLEW_GET_FUN(__glewUniformMatrix2fv) +#define glUniformMatrix3fv GLEW_GET_FUN(__glewUniformMatrix3fv) +#define glUniformMatrix4fv GLEW_GET_FUN(__glewUniformMatrix4fv) +#define glUseProgram GLEW_GET_FUN(__glewUseProgram) +#define glValidateProgram GLEW_GET_FUN(__glewValidateProgram) +#define glVertexAttrib1d GLEW_GET_FUN(__glewVertexAttrib1d) +#define glVertexAttrib1dv GLEW_GET_FUN(__glewVertexAttrib1dv) +#define glVertexAttrib1f GLEW_GET_FUN(__glewVertexAttrib1f) +#define glVertexAttrib1fv GLEW_GET_FUN(__glewVertexAttrib1fv) +#define glVertexAttrib1s GLEW_GET_FUN(__glewVertexAttrib1s) +#define glVertexAttrib1sv GLEW_GET_FUN(__glewVertexAttrib1sv) +#define glVertexAttrib2d GLEW_GET_FUN(__glewVertexAttrib2d) +#define glVertexAttrib2dv GLEW_GET_FUN(__glewVertexAttrib2dv) +#define glVertexAttrib2f GLEW_GET_FUN(__glewVertexAttrib2f) +#define glVertexAttrib2fv GLEW_GET_FUN(__glewVertexAttrib2fv) +#define glVertexAttrib2s GLEW_GET_FUN(__glewVertexAttrib2s) +#define glVertexAttrib2sv GLEW_GET_FUN(__glewVertexAttrib2sv) +#define glVertexAttrib3d GLEW_GET_FUN(__glewVertexAttrib3d) +#define glVertexAttrib3dv GLEW_GET_FUN(__glewVertexAttrib3dv) +#define glVertexAttrib3f GLEW_GET_FUN(__glewVertexAttrib3f) +#define glVertexAttrib3fv GLEW_GET_FUN(__glewVertexAttrib3fv) +#define glVertexAttrib3s GLEW_GET_FUN(__glewVertexAttrib3s) +#define glVertexAttrib3sv GLEW_GET_FUN(__glewVertexAttrib3sv) +#define glVertexAttrib4Nbv GLEW_GET_FUN(__glewVertexAttrib4Nbv) +#define glVertexAttrib4Niv GLEW_GET_FUN(__glewVertexAttrib4Niv) +#define glVertexAttrib4Nsv GLEW_GET_FUN(__glewVertexAttrib4Nsv) +#define glVertexAttrib4Nub GLEW_GET_FUN(__glewVertexAttrib4Nub) +#define glVertexAttrib4Nubv GLEW_GET_FUN(__glewVertexAttrib4Nubv) +#define glVertexAttrib4Nuiv GLEW_GET_FUN(__glewVertexAttrib4Nuiv) +#define glVertexAttrib4Nusv GLEW_GET_FUN(__glewVertexAttrib4Nusv) +#define glVertexAttrib4bv GLEW_GET_FUN(__glewVertexAttrib4bv) +#define glVertexAttrib4d GLEW_GET_FUN(__glewVertexAttrib4d) +#define glVertexAttrib4dv GLEW_GET_FUN(__glewVertexAttrib4dv) +#define glVertexAttrib4f GLEW_GET_FUN(__glewVertexAttrib4f) +#define glVertexAttrib4fv GLEW_GET_FUN(__glewVertexAttrib4fv) +#define glVertexAttrib4iv GLEW_GET_FUN(__glewVertexAttrib4iv) +#define glVertexAttrib4s GLEW_GET_FUN(__glewVertexAttrib4s) +#define glVertexAttrib4sv GLEW_GET_FUN(__glewVertexAttrib4sv) +#define glVertexAttrib4ubv GLEW_GET_FUN(__glewVertexAttrib4ubv) +#define glVertexAttrib4uiv GLEW_GET_FUN(__glewVertexAttrib4uiv) +#define glVertexAttrib4usv GLEW_GET_FUN(__glewVertexAttrib4usv) +#define glVertexAttribPointer GLEW_GET_FUN(__glewVertexAttribPointer) + +#define GLEW_VERSION_2_0 GLEW_GET_VAR(__GLEW_VERSION_2_0) + +#endif /* GL_VERSION_2_0 */ + +/* ----------------------------- GL_VERSION_2_1 ---------------------------- */ + +#ifndef GL_VERSION_2_1 +#define GL_VERSION_2_1 1 + +#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB_ALPHA 0x8C42 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_SLUMINANCE_ALPHA 0x8C44 +#define GL_SLUMINANCE8_ALPHA8 0x8C45 +#define GL_SLUMINANCE 0x8C46 +#define GL_SLUMINANCE8 0x8C47 +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 +#define GL_COMPRESSED_SLUMINANCE 0x8C4A +#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B + +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + +#define glUniformMatrix2x3fv GLEW_GET_FUN(__glewUniformMatrix2x3fv) +#define glUniformMatrix2x4fv GLEW_GET_FUN(__glewUniformMatrix2x4fv) +#define glUniformMatrix3x2fv GLEW_GET_FUN(__glewUniformMatrix3x2fv) +#define glUniformMatrix3x4fv GLEW_GET_FUN(__glewUniformMatrix3x4fv) +#define glUniformMatrix4x2fv GLEW_GET_FUN(__glewUniformMatrix4x2fv) +#define glUniformMatrix4x3fv GLEW_GET_FUN(__glewUniformMatrix4x3fv) + +#define GLEW_VERSION_2_1 GLEW_GET_VAR(__GLEW_VERSION_2_1) + +#endif /* GL_VERSION_2_1 */ + +/* ----------------------------- GL_VERSION_3_0 ---------------------------- */ + +#ifndef GL_VERSION_3_0 +#define GL_VERSION_3_0 1 + +#define GL_MAX_CLIP_DISTANCES GL_MAX_CLIP_PLANES +#define GL_CLIP_DISTANCE5 GL_CLIP_PLANE5 +#define GL_CLIP_DISTANCE1 GL_CLIP_PLANE1 +#define GL_CLIP_DISTANCE3 GL_CLIP_PLANE3 +#define GL_COMPARE_REF_TO_TEXTURE GL_COMPARE_R_TO_TEXTURE_ARB +#define GL_CLIP_DISTANCE0 GL_CLIP_PLANE0 +#define GL_CLIP_DISTANCE4 GL_CLIP_PLANE4 +#define GL_CLIP_DISTANCE2 GL_CLIP_PLANE2 +#define GL_MAX_VARYING_COMPONENTS GL_MAX_VARYING_FLOATS +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001 +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_CONTEXT_FLAGS 0x821E +#define GL_DEPTH_BUFFER 0x8223 +#define GL_STENCIL_BUFFER 0x8224 +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RG 0x8226 +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_CLAMP_VERTEX_COLOR 0x891A +#define GL_CLAMP_FRAGMENT_COLOR 0x891B +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_FIXED_ONLY 0x891D +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14 +#define GL_TEXTURE_INTENSITY_TYPE 0x8C15 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_TEXTURE_1D_ARRAY 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_GREEN_INTEGER 0x8D95 +#define GL_BLUE_INTEGER 0x8D96 +#define GL_ALPHA_INTEGER 0x8D97 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_BGR_INTEGER 0x8D9A +#define GL_BGRA_INTEGER 0x8D9B +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_QUERY_WAIT 0x8E13 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 + +typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERPROC) (GLuint, GLenum); +typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum); +typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONPROC) (GLuint, GLuint, const GLchar*); +typedef void (GLAPIENTRY * PFNGLCLAMPCOLORPROC) (GLenum, GLenum); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFIPROC) (GLenum, GLint, GLfloat, GLint); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFVPROC) (GLenum, GLint, const GLfloat*); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERIVPROC) (GLenum, GLint, const GLint*); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERUIVPROC) (GLenum, GLint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLCOLORMASKIPROC) (GLuint, GLboolean, GLboolean, GLboolean, GLboolean); +typedef void (GLAPIENTRY * PFNGLDISABLEIPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLENABLEIPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERPROC) (void); +typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKPROC) (void); +typedef void (GLAPIENTRY * PFNGLGETBOOLEANI_VPROC) (GLenum, GLuint, GLboolean*); +typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATALOCATIONPROC) (GLuint, const GLchar*); +typedef const GLubyte* (GLAPIENTRY * PFNGLGETSTRINGIPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIIVPROC) (GLenum, GLenum, GLint*); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIUIVPROC) (GLenum, GLenum, GLuint*); +typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVPROC) (GLuint, GLint, GLuint*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVPROC) (GLuint, GLenum, GLint*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint, GLenum, GLuint*); +typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDIPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIIVPROC) (GLenum, GLenum, const GLint*); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIUIVPROC) (GLenum, GLenum, const GLuint*); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint, GLsizei, const GLchar **, GLenum); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UIPROC) (GLint, GLuint); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVPROC) (GLint, GLsizei, const GLuint*); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UIPROC) (GLint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UIVPROC) (GLint, GLsizei, const GLuint*); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UIPROC) (GLint, GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UIVPROC) (GLint, GLsizei, const GLuint*); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UIPROC) (GLint, GLuint, GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UIVPROC) (GLint, GLsizei, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IPROC) (GLuint, GLint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IVPROC) (GLuint, const GLint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIPROC) (GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIVPROC) (GLuint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IPROC) (GLuint, GLint, GLint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IVPROC) (GLuint, const GLint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIPROC) (GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIVPROC) (GLuint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IPROC) (GLuint, GLint, GLint, GLint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IVPROC) (GLuint, const GLint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIPROC) (GLuint, GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIVPROC) (GLuint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4BVPROC) (GLuint, const GLbyte*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IPROC) (GLuint, GLint, GLint, GLint, GLint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVPROC) (GLuint, const GLint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4SVPROC) (GLuint, const GLshort*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVPROC) (GLuint, const GLubyte*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIPROC) (GLuint, GLuint, GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVPROC) (GLuint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVPROC) (GLuint, const GLushort*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint, GLint, GLenum, GLsizei, const GLvoid*); + +#define glBeginConditionalRender GLEW_GET_FUN(__glewBeginConditionalRender) +#define glBeginTransformFeedback GLEW_GET_FUN(__glewBeginTransformFeedback) +#define glBindFragDataLocation GLEW_GET_FUN(__glewBindFragDataLocation) +#define glClampColor GLEW_GET_FUN(__glewClampColor) +#define glClearBufferfi GLEW_GET_FUN(__glewClearBufferfi) +#define glClearBufferfv GLEW_GET_FUN(__glewClearBufferfv) +#define glClearBufferiv GLEW_GET_FUN(__glewClearBufferiv) +#define glClearBufferuiv GLEW_GET_FUN(__glewClearBufferuiv) +#define glColorMaski GLEW_GET_FUN(__glewColorMaski) +#define glDisablei GLEW_GET_FUN(__glewDisablei) +#define glEnablei GLEW_GET_FUN(__glewEnablei) +#define glEndConditionalRender GLEW_GET_FUN(__glewEndConditionalRender) +#define glEndTransformFeedback GLEW_GET_FUN(__glewEndTransformFeedback) +#define glGetBooleani_v GLEW_GET_FUN(__glewGetBooleani_v) +#define glGetFragDataLocation GLEW_GET_FUN(__glewGetFragDataLocation) +#define glGetStringi GLEW_GET_FUN(__glewGetStringi) +#define glGetTexParameterIiv GLEW_GET_FUN(__glewGetTexParameterIiv) +#define glGetTexParameterIuiv GLEW_GET_FUN(__glewGetTexParameterIuiv) +#define glGetTransformFeedbackVarying GLEW_GET_FUN(__glewGetTransformFeedbackVarying) +#define glGetUniformuiv GLEW_GET_FUN(__glewGetUniformuiv) +#define glGetVertexAttribIiv GLEW_GET_FUN(__glewGetVertexAttribIiv) +#define glGetVertexAttribIuiv GLEW_GET_FUN(__glewGetVertexAttribIuiv) +#define glIsEnabledi GLEW_GET_FUN(__glewIsEnabledi) +#define glTexParameterIiv GLEW_GET_FUN(__glewTexParameterIiv) +#define glTexParameterIuiv GLEW_GET_FUN(__glewTexParameterIuiv) +#define glTransformFeedbackVaryings GLEW_GET_FUN(__glewTransformFeedbackVaryings) +#define glUniform1ui GLEW_GET_FUN(__glewUniform1ui) +#define glUniform1uiv GLEW_GET_FUN(__glewUniform1uiv) +#define glUniform2ui GLEW_GET_FUN(__glewUniform2ui) +#define glUniform2uiv GLEW_GET_FUN(__glewUniform2uiv) +#define glUniform3ui GLEW_GET_FUN(__glewUniform3ui) +#define glUniform3uiv GLEW_GET_FUN(__glewUniform3uiv) +#define glUniform4ui GLEW_GET_FUN(__glewUniform4ui) +#define glUniform4uiv GLEW_GET_FUN(__glewUniform4uiv) +#define glVertexAttribI1i GLEW_GET_FUN(__glewVertexAttribI1i) +#define glVertexAttribI1iv GLEW_GET_FUN(__glewVertexAttribI1iv) +#define glVertexAttribI1ui GLEW_GET_FUN(__glewVertexAttribI1ui) +#define glVertexAttribI1uiv GLEW_GET_FUN(__glewVertexAttribI1uiv) +#define glVertexAttribI2i GLEW_GET_FUN(__glewVertexAttribI2i) +#define glVertexAttribI2iv GLEW_GET_FUN(__glewVertexAttribI2iv) +#define glVertexAttribI2ui GLEW_GET_FUN(__glewVertexAttribI2ui) +#define glVertexAttribI2uiv GLEW_GET_FUN(__glewVertexAttribI2uiv) +#define glVertexAttribI3i GLEW_GET_FUN(__glewVertexAttribI3i) +#define glVertexAttribI3iv GLEW_GET_FUN(__glewVertexAttribI3iv) +#define glVertexAttribI3ui GLEW_GET_FUN(__glewVertexAttribI3ui) +#define glVertexAttribI3uiv GLEW_GET_FUN(__glewVertexAttribI3uiv) +#define glVertexAttribI4bv GLEW_GET_FUN(__glewVertexAttribI4bv) +#define glVertexAttribI4i GLEW_GET_FUN(__glewVertexAttribI4i) +#define glVertexAttribI4iv GLEW_GET_FUN(__glewVertexAttribI4iv) +#define glVertexAttribI4sv GLEW_GET_FUN(__glewVertexAttribI4sv) +#define glVertexAttribI4ubv GLEW_GET_FUN(__glewVertexAttribI4ubv) +#define glVertexAttribI4ui GLEW_GET_FUN(__glewVertexAttribI4ui) +#define glVertexAttribI4uiv GLEW_GET_FUN(__glewVertexAttribI4uiv) +#define glVertexAttribI4usv GLEW_GET_FUN(__glewVertexAttribI4usv) +#define glVertexAttribIPointer GLEW_GET_FUN(__glewVertexAttribIPointer) + +#define GLEW_VERSION_3_0 GLEW_GET_VAR(__GLEW_VERSION_3_0) + +#endif /* GL_VERSION_3_0 */ + +/* ----------------------------- GL_VERSION_3_1 ---------------------------- */ + +#ifndef GL_VERSION_3_1 +#define GL_VERSION_3_1 1 + +#define GL_TEXTURE_RECTANGLE 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT 0x8C2E +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_RED_SNORM 0x8F90 +#define GL_RG_SNORM 0x8F91 +#define GL_RGB_SNORM 0x8F92 +#define GL_RGBA_SNORM 0x8F93 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_R16_SNORM 0x8F98 +#define GL_RG16_SNORM 0x8F99 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGBA16_SNORM 0x8F9B +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART 0x8F9D +#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 + +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum, GLint, GLsizei, GLsizei); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum, GLsizei, GLenum, const GLvoid*, GLsizei); +typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint); +typedef void (GLAPIENTRY * PFNGLTEXBUFFERPROC) (GLenum, GLenum, GLuint); + +#define glDrawArraysInstanced GLEW_GET_FUN(__glewDrawArraysInstanced) +#define glDrawElementsInstanced GLEW_GET_FUN(__glewDrawElementsInstanced) +#define glPrimitiveRestartIndex GLEW_GET_FUN(__glewPrimitiveRestartIndex) +#define glTexBuffer GLEW_GET_FUN(__glewTexBuffer) + +#define GLEW_VERSION_3_1 GLEW_GET_VAR(__GLEW_VERSION_3_1) + +#endif /* GL_VERSION_3_1 */ + +/* ----------------------------- GL_VERSION_3_2 ---------------------------- */ + +#ifndef GL_VERSION_3_2 +#define GL_VERSION_3_2 1 + +#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 +#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define GL_LINES_ADJACENCY 0x000A +#define GL_LINE_STRIP_ADJACENCY 0x000B +#define GL_TRIANGLES_ADJACENCY 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D +#define GL_PROGRAM_POINT_SIZE 0x8642 +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 +#define GL_GEOMETRY_SHADER 0x8DD9 +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_CONTEXT_PROFILE_MASK 0x9126 + +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum, GLenum, GLuint, GLint); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum, GLenum, GLint64 *); +typedef void (GLAPIENTRY * PFNGLGETINTEGER64I_VPROC) (GLenum, GLuint, GLint64 *); + +#define glFramebufferTexture GLEW_GET_FUN(__glewFramebufferTexture) +#define glGetBufferParameteri64v GLEW_GET_FUN(__glewGetBufferParameteri64v) +#define glGetInteger64i_v GLEW_GET_FUN(__glewGetInteger64i_v) + +#define GLEW_VERSION_3_2 GLEW_GET_VAR(__GLEW_VERSION_3_2) + +#endif /* GL_VERSION_3_2 */ + +/* ----------------------------- GL_VERSION_3_3 ---------------------------- */ + +#ifndef GL_VERSION_3_3 +#define GL_VERSION_3_3 1 + +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 +#define GL_RGB10_A2UI 0x906F + +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor); + +#define glVertexAttribDivisor GLEW_GET_FUN(__glewVertexAttribDivisor) + +#define GLEW_VERSION_3_3 GLEW_GET_VAR(__GLEW_VERSION_3_3) + +#endif /* GL_VERSION_3_3 */ + +/* ----------------------------- GL_VERSION_4_0 ---------------------------- */ + +#ifndef GL_VERSION_4_0 +#define GL_VERSION_4_0 1 + +#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F +#define GL_SAMPLE_SHADING 0x8C36 +#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37 +#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C +#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F +#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS 0x8F9F +#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B +#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (GLAPIENTRY * PFNGLMINSAMPLESHADINGPROC) (GLclampf value); + +#define glBlendEquationSeparatei GLEW_GET_FUN(__glewBlendEquationSeparatei) +#define glBlendEquationi GLEW_GET_FUN(__glewBlendEquationi) +#define glBlendFuncSeparatei GLEW_GET_FUN(__glewBlendFuncSeparatei) +#define glBlendFunci GLEW_GET_FUN(__glewBlendFunci) +#define glMinSampleShading GLEW_GET_FUN(__glewMinSampleShading) + +#define GLEW_VERSION_4_0 GLEW_GET_VAR(__GLEW_VERSION_4_0) + +#endif /* GL_VERSION_4_0 */ + +/* ----------------------------- GL_VERSION_4_1 ---------------------------- */ + +#ifndef GL_VERSION_4_1 +#define GL_VERSION_4_1 1 + +#define GLEW_VERSION_4_1 GLEW_GET_VAR(__GLEW_VERSION_4_1) + +#endif /* GL_VERSION_4_1 */ + +/* -------------------------- GL_3DFX_multisample -------------------------- */ + +#ifndef GL_3DFX_multisample +#define GL_3DFX_multisample 1 + +#define GL_MULTISAMPLE_3DFX 0x86B2 +#define GL_SAMPLE_BUFFERS_3DFX 0x86B3 +#define GL_SAMPLES_3DFX 0x86B4 +#define GL_MULTISAMPLE_BIT_3DFX 0x20000000 + +#define GLEW_3DFX_multisample GLEW_GET_VAR(__GLEW_3DFX_multisample) + +#endif /* GL_3DFX_multisample */ + +/* ---------------------------- GL_3DFX_tbuffer ---------------------------- */ + +#ifndef GL_3DFX_tbuffer +#define GL_3DFX_tbuffer 1 + +typedef void (GLAPIENTRY * PFNGLTBUFFERMASK3DFXPROC) (GLuint mask); + +#define glTbufferMask3DFX GLEW_GET_FUN(__glewTbufferMask3DFX) + +#define GLEW_3DFX_tbuffer GLEW_GET_VAR(__GLEW_3DFX_tbuffer) + +#endif /* GL_3DFX_tbuffer */ + +/* -------------------- GL_3DFX_texture_compression_FXT1 ------------------- */ + +#ifndef GL_3DFX_texture_compression_FXT1 +#define GL_3DFX_texture_compression_FXT1 1 + +#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0 +#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1 + +#define GLEW_3DFX_texture_compression_FXT1 GLEW_GET_VAR(__GLEW_3DFX_texture_compression_FXT1) + +#endif /* GL_3DFX_texture_compression_FXT1 */ + +/* ----------------------- GL_AMD_blend_minmax_factor ---------------------- */ + +#ifndef GL_AMD_blend_minmax_factor +#define GL_AMD_blend_minmax_factor 1 + +#define GL_FACTOR_MIN_AMD 0x901C +#define GL_FACTOR_MAX_AMD 0x901D + +#define GLEW_AMD_blend_minmax_factor GLEW_GET_VAR(__GLEW_AMD_blend_minmax_factor) + +#endif /* GL_AMD_blend_minmax_factor */ + +/* ----------------------- GL_AMD_conservative_depth ----------------------- */ + +#ifndef GL_AMD_conservative_depth +#define GL_AMD_conservative_depth 1 + +#define GLEW_AMD_conservative_depth GLEW_GET_VAR(__GLEW_AMD_conservative_depth) + +#endif /* GL_AMD_conservative_depth */ + +/* -------------------------- GL_AMD_debug_output -------------------------- */ + +#ifndef GL_AMD_debug_output +#define GL_AMD_debug_output 1 + +#define GL_MAX_DEBUG_MESSAGE_LENGTH_AMD 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES_AMD 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES_AMD 0x9145 +#define GL_DEBUG_SEVERITY_HIGH_AMD 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM_AMD 0x9147 +#define GL_DEBUG_SEVERITY_LOW_AMD 0x9148 +#define GL_DEBUG_CATEGORY_API_ERROR_AMD 0x9149 +#define GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A +#define GL_DEBUG_CATEGORY_DEPRECATION_AMD 0x914B +#define GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C +#define GL_DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D +#define GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E +#define GL_DEBUG_CATEGORY_APPLICATION_AMD 0x914F +#define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150 + +typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam); + +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void* userParam); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const char* buf); +typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum* categories, GLuint* severities, GLuint* ids, GLsizei* lengths, char* message); + +#define glDebugMessageCallbackAMD GLEW_GET_FUN(__glewDebugMessageCallbackAMD) +#define glDebugMessageEnableAMD GLEW_GET_FUN(__glewDebugMessageEnableAMD) +#define glDebugMessageInsertAMD GLEW_GET_FUN(__glewDebugMessageInsertAMD) +#define glGetDebugMessageLogAMD GLEW_GET_FUN(__glewGetDebugMessageLogAMD) + +#define GLEW_AMD_debug_output GLEW_GET_VAR(__GLEW_AMD_debug_output) + +#endif /* GL_AMD_debug_output */ + +/* ---------------------- GL_AMD_depth_clamp_separate ---------------------- */ + +#ifndef GL_AMD_depth_clamp_separate +#define GL_AMD_depth_clamp_separate 1 + +#define GL_DEPTH_CLAMP_NEAR_AMD 0x901E +#define GL_DEPTH_CLAMP_FAR_AMD 0x901F + +#define GLEW_AMD_depth_clamp_separate GLEW_GET_VAR(__GLEW_AMD_depth_clamp_separate) + +#endif /* GL_AMD_depth_clamp_separate */ + +/* ----------------------- GL_AMD_draw_buffers_blend ----------------------- */ + +#ifndef GL_AMD_draw_buffers_blend +#define GL_AMD_draw_buffers_blend 1 + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONINDEXEDAMDPROC) (GLuint buf, GLenum mode); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCINDEXEDAMDPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + +#define glBlendEquationIndexedAMD GLEW_GET_FUN(__glewBlendEquationIndexedAMD) +#define glBlendEquationSeparateIndexedAMD GLEW_GET_FUN(__glewBlendEquationSeparateIndexedAMD) +#define glBlendFuncIndexedAMD GLEW_GET_FUN(__glewBlendFuncIndexedAMD) +#define glBlendFuncSeparateIndexedAMD GLEW_GET_FUN(__glewBlendFuncSeparateIndexedAMD) + +#define GLEW_AMD_draw_buffers_blend GLEW_GET_VAR(__GLEW_AMD_draw_buffers_blend) + +#endif /* GL_AMD_draw_buffers_blend */ + +/* ------------------------- GL_AMD_name_gen_delete ------------------------ */ + +#ifndef GL_AMD_name_gen_delete +#define GL_AMD_name_gen_delete 1 + +#define GL_DATA_BUFFER_AMD 0x9151 +#define GL_PERFORMANCE_MONITOR_AMD 0x9152 +#define GL_QUERY_OBJECT_AMD 0x9153 +#define GL_VERTEX_ARRAY_OBJECT_AMD 0x9154 +#define GL_SAMPLER_OBJECT_AMD 0x9155 + +typedef void (GLAPIENTRY * PFNGLDELETENAMESAMDPROC) (GLenum identifier, GLuint num, const GLuint* names); +typedef void (GLAPIENTRY * PFNGLGENNAMESAMDPROC) (GLenum identifier, GLuint num, GLuint* names); +typedef GLboolean (GLAPIENTRY * PFNGLISNAMEAMDPROC) (GLenum identifier, GLuint name); + +#define glDeleteNamesAMD GLEW_GET_FUN(__glewDeleteNamesAMD) +#define glGenNamesAMD GLEW_GET_FUN(__glewGenNamesAMD) +#define glIsNameAMD GLEW_GET_FUN(__glewIsNameAMD) + +#define GLEW_AMD_name_gen_delete GLEW_GET_VAR(__GLEW_AMD_name_gen_delete) + +#endif /* GL_AMD_name_gen_delete */ + +/* ----------------------- GL_AMD_performance_monitor ---------------------- */ + +#ifndef GL_AMD_performance_monitor +#define GL_AMD_performance_monitor 1 + +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_COUNTER_TYPE_AMD 0x8BC0 +#define GL_COUNTER_RANGE_AMD 0x8BC1 +#define GL_UNSIGNED_INT64_AMD 0x8BC2 +#define GL_PERCENTAGE_AMD 0x8BC3 +#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4 +#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5 +#define GL_PERFMON_RESULT_AMD 0x8BC6 + +typedef void (GLAPIENTRY * PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor); +typedef void (GLAPIENTRY * PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors); +typedef void (GLAPIENTRY * PFNGLENDPERFMONITORAMDPROC) (GLuint monitor); +typedef void (GLAPIENTRY * PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint* data, GLint *bytesWritten); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void* data); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei* length, char *counterString); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint* numCounters, GLint *maxActiveCounters, GLsizei countersSize, GLuint *counters); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei* length, char *groupString); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint* numGroups, GLsizei groupsSize, GLuint *groups); +typedef void (GLAPIENTRY * PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint* counterList); + +#define glBeginPerfMonitorAMD GLEW_GET_FUN(__glewBeginPerfMonitorAMD) +#define glDeletePerfMonitorsAMD GLEW_GET_FUN(__glewDeletePerfMonitorsAMD) +#define glEndPerfMonitorAMD GLEW_GET_FUN(__glewEndPerfMonitorAMD) +#define glGenPerfMonitorsAMD GLEW_GET_FUN(__glewGenPerfMonitorsAMD) +#define glGetPerfMonitorCounterDataAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterDataAMD) +#define glGetPerfMonitorCounterInfoAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterInfoAMD) +#define glGetPerfMonitorCounterStringAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterStringAMD) +#define glGetPerfMonitorCountersAMD GLEW_GET_FUN(__glewGetPerfMonitorCountersAMD) +#define glGetPerfMonitorGroupStringAMD GLEW_GET_FUN(__glewGetPerfMonitorGroupStringAMD) +#define glGetPerfMonitorGroupsAMD GLEW_GET_FUN(__glewGetPerfMonitorGroupsAMD) +#define glSelectPerfMonitorCountersAMD GLEW_GET_FUN(__glewSelectPerfMonitorCountersAMD) + +#define GLEW_AMD_performance_monitor GLEW_GET_VAR(__GLEW_AMD_performance_monitor) + +#endif /* GL_AMD_performance_monitor */ + +/* ------------------------ GL_AMD_sample_positions ------------------------ */ + +#ifndef GL_AMD_sample_positions +#define GL_AMD_sample_positions 1 + +#define GL_SUBSAMPLE_DISTANCE_AMD 0x883F + +typedef void (GLAPIENTRY * PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint index, const GLfloat* val); + +#define glSetMultisamplefvAMD GLEW_GET_FUN(__glewSetMultisamplefvAMD) + +#define GLEW_AMD_sample_positions GLEW_GET_VAR(__GLEW_AMD_sample_positions) + +#endif /* GL_AMD_sample_positions */ + +/* ------------------ GL_AMD_seamless_cubemap_per_texture ------------------ */ + +#ifndef GL_AMD_seamless_cubemap_per_texture +#define GL_AMD_seamless_cubemap_per_texture 1 + +#define GL_TEXTURE_CUBE_MAP_SEAMLESS_ARB 0x884F + +#define GLEW_AMD_seamless_cubemap_per_texture GLEW_GET_VAR(__GLEW_AMD_seamless_cubemap_per_texture) + +#endif /* GL_AMD_seamless_cubemap_per_texture */ + +/* ---------------------- GL_AMD_shader_stencil_export --------------------- */ + +#ifndef GL_AMD_shader_stencil_export +#define GL_AMD_shader_stencil_export 1 + +#define GLEW_AMD_shader_stencil_export GLEW_GET_VAR(__GLEW_AMD_shader_stencil_export) + +#endif /* GL_AMD_shader_stencil_export */ + +/* ------------------------ GL_AMD_texture_texture4 ------------------------ */ + +#ifndef GL_AMD_texture_texture4 +#define GL_AMD_texture_texture4 1 + +#define GLEW_AMD_texture_texture4 GLEW_GET_VAR(__GLEW_AMD_texture_texture4) + +#endif /* GL_AMD_texture_texture4 */ + +/* --------------- GL_AMD_transform_feedback3_lines_triangles -------------- */ + +#ifndef GL_AMD_transform_feedback3_lines_triangles +#define GL_AMD_transform_feedback3_lines_triangles 1 + +#define GLEW_AMD_transform_feedback3_lines_triangles GLEW_GET_VAR(__GLEW_AMD_transform_feedback3_lines_triangles) + +#endif /* GL_AMD_transform_feedback3_lines_triangles */ + +/* -------------------- GL_AMD_vertex_shader_tessellator ------------------- */ + +#ifndef GL_AMD_vertex_shader_tessellator +#define GL_AMD_vertex_shader_tessellator 1 + +#define GL_SAMPLER_BUFFER_AMD 0x9001 +#define GL_INT_SAMPLER_BUFFER_AMD 0x9002 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER_AMD 0x9003 +#define GL_TESSELLATION_MODE_AMD 0x9004 +#define GL_TESSELLATION_FACTOR_AMD 0x9005 +#define GL_DISCRETE_AMD 0x9006 +#define GL_CONTINUOUS_AMD 0x9007 + +typedef void (GLAPIENTRY * PFNGLTESSELLATIONFACTORAMDPROC) (GLfloat factor); +typedef void (GLAPIENTRY * PFNGLTESSELLATIONMODEAMDPROC) (GLenum mode); + +#define glTessellationFactorAMD GLEW_GET_FUN(__glewTessellationFactorAMD) +#define glTessellationModeAMD GLEW_GET_FUN(__glewTessellationModeAMD) + +#define GLEW_AMD_vertex_shader_tessellator GLEW_GET_VAR(__GLEW_AMD_vertex_shader_tessellator) + +#endif /* GL_AMD_vertex_shader_tessellator */ + +/* ----------------------- GL_APPLE_aux_depth_stencil ---------------------- */ + +#ifndef GL_APPLE_aux_depth_stencil +#define GL_APPLE_aux_depth_stencil 1 + +#define GL_AUX_DEPTH_STENCIL_APPLE 0x8A14 + +#define GLEW_APPLE_aux_depth_stencil GLEW_GET_VAR(__GLEW_APPLE_aux_depth_stencil) + +#endif /* GL_APPLE_aux_depth_stencil */ + +/* ------------------------ GL_APPLE_client_storage ------------------------ */ + +#ifndef GL_APPLE_client_storage +#define GL_APPLE_client_storage 1 + +#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2 + +#define GLEW_APPLE_client_storage GLEW_GET_VAR(__GLEW_APPLE_client_storage) + +#endif /* GL_APPLE_client_storage */ + +/* ------------------------- GL_APPLE_element_array ------------------------ */ + +#ifndef GL_APPLE_element_array +#define GL_APPLE_element_array 1 + +#define GL_ELEMENT_ARRAY_APPLE 0x8A0C +#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8A0D +#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x8A0E + +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); +typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const void* pointer); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint* first, const GLsizei *count, GLsizei primcount); + +#define glDrawElementArrayAPPLE GLEW_GET_FUN(__glewDrawElementArrayAPPLE) +#define glDrawRangeElementArrayAPPLE GLEW_GET_FUN(__glewDrawRangeElementArrayAPPLE) +#define glElementPointerAPPLE GLEW_GET_FUN(__glewElementPointerAPPLE) +#define glMultiDrawElementArrayAPPLE GLEW_GET_FUN(__glewMultiDrawElementArrayAPPLE) +#define glMultiDrawRangeElementArrayAPPLE GLEW_GET_FUN(__glewMultiDrawRangeElementArrayAPPLE) + +#define GLEW_APPLE_element_array GLEW_GET_VAR(__GLEW_APPLE_element_array) + +#endif /* GL_APPLE_element_array */ + +/* ----------------------------- GL_APPLE_fence ---------------------------- */ + +#ifndef GL_APPLE_fence +#define GL_APPLE_fence 1 + +#define GL_DRAW_PIXELS_APPLE 0x8A0A +#define GL_FENCE_APPLE 0x8A0B + +typedef void (GLAPIENTRY * PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint* fences); +typedef void (GLAPIENTRY * PFNGLFINISHFENCEAPPLEPROC) (GLuint fence); +typedef void (GLAPIENTRY * PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name); +typedef void (GLAPIENTRY * PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint* fences); +typedef GLboolean (GLAPIENTRY * PFNGLISFENCEAPPLEPROC) (GLuint fence); +typedef void (GLAPIENTRY * PFNGLSETFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (GLAPIENTRY * PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name); + +#define glDeleteFencesAPPLE GLEW_GET_FUN(__glewDeleteFencesAPPLE) +#define glFinishFenceAPPLE GLEW_GET_FUN(__glewFinishFenceAPPLE) +#define glFinishObjectAPPLE GLEW_GET_FUN(__glewFinishObjectAPPLE) +#define glGenFencesAPPLE GLEW_GET_FUN(__glewGenFencesAPPLE) +#define glIsFenceAPPLE GLEW_GET_FUN(__glewIsFenceAPPLE) +#define glSetFenceAPPLE GLEW_GET_FUN(__glewSetFenceAPPLE) +#define glTestFenceAPPLE GLEW_GET_FUN(__glewTestFenceAPPLE) +#define glTestObjectAPPLE GLEW_GET_FUN(__glewTestObjectAPPLE) + +#define GLEW_APPLE_fence GLEW_GET_VAR(__GLEW_APPLE_fence) + +#endif /* GL_APPLE_fence */ + +/* ------------------------- GL_APPLE_float_pixels ------------------------- */ + +#ifndef GL_APPLE_float_pixels +#define GL_APPLE_float_pixels 1 + +#define GL_HALF_APPLE 0x140B +#define GL_RGBA_FLOAT32_APPLE 0x8814 +#define GL_RGB_FLOAT32_APPLE 0x8815 +#define GL_ALPHA_FLOAT32_APPLE 0x8816 +#define GL_INTENSITY_FLOAT32_APPLE 0x8817 +#define GL_LUMINANCE_FLOAT32_APPLE 0x8818 +#define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819 +#define GL_RGBA_FLOAT16_APPLE 0x881A +#define GL_RGB_FLOAT16_APPLE 0x881B +#define GL_ALPHA_FLOAT16_APPLE 0x881C +#define GL_INTENSITY_FLOAT16_APPLE 0x881D +#define GL_LUMINANCE_FLOAT16_APPLE 0x881E +#define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F +#define GL_COLOR_FLOAT_APPLE 0x8A0F + +#define GLEW_APPLE_float_pixels GLEW_GET_VAR(__GLEW_APPLE_float_pixels) + +#endif /* GL_APPLE_float_pixels */ + +/* ---------------------- GL_APPLE_flush_buffer_range ---------------------- */ + +#ifndef GL_APPLE_flush_buffer_range +#define GL_APPLE_flush_buffer_range 1 + +#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12 +#define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13 + +typedef void (GLAPIENTRY * PFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size); + +#define glBufferParameteriAPPLE GLEW_GET_FUN(__glewBufferParameteriAPPLE) +#define glFlushMappedBufferRangeAPPLE GLEW_GET_FUN(__glewFlushMappedBufferRangeAPPLE) + +#define GLEW_APPLE_flush_buffer_range GLEW_GET_VAR(__GLEW_APPLE_flush_buffer_range) + +#endif /* GL_APPLE_flush_buffer_range */ + +/* ----------------------- GL_APPLE_object_purgeable ----------------------- */ + +#ifndef GL_APPLE_object_purgeable +#define GL_APPLE_object_purgeable 1 + +#define GL_BUFFER_OBJECT_APPLE 0x85B3 +#define GL_RELEASED_APPLE 0x8A19 +#define GL_VOLATILE_APPLE 0x8A1A +#define GL_RETAINED_APPLE 0x8A1B +#define GL_UNDEFINED_APPLE 0x8A1C +#define GL_PURGEABLE_APPLE 0x8A1D + +typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERIVAPPLEPROC) (GLenum objectType, GLuint name, GLenum pname, GLint* params); +typedef GLenum (GLAPIENTRY * PFNGLOBJECTPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option); +typedef GLenum (GLAPIENTRY * PFNGLOBJECTUNPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option); + +#define glGetObjectParameterivAPPLE GLEW_GET_FUN(__glewGetObjectParameterivAPPLE) +#define glObjectPurgeableAPPLE GLEW_GET_FUN(__glewObjectPurgeableAPPLE) +#define glObjectUnpurgeableAPPLE GLEW_GET_FUN(__glewObjectUnpurgeableAPPLE) + +#define GLEW_APPLE_object_purgeable GLEW_GET_VAR(__GLEW_APPLE_object_purgeable) + +#endif /* GL_APPLE_object_purgeable */ + +/* ------------------------- GL_APPLE_pixel_buffer ------------------------- */ + +#ifndef GL_APPLE_pixel_buffer +#define GL_APPLE_pixel_buffer 1 + +#define GL_MIN_PBUFFER_VIEWPORT_DIMS_APPLE 0x8A10 + +#define GLEW_APPLE_pixel_buffer GLEW_GET_VAR(__GLEW_APPLE_pixel_buffer) + +#endif /* GL_APPLE_pixel_buffer */ + +/* ---------------------------- GL_APPLE_rgb_422 --------------------------- */ + +#ifndef GL_APPLE_rgb_422 +#define GL_APPLE_rgb_422 1 + +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB +#define GL_RGB_422_APPLE 0x8A1F + +#define GLEW_APPLE_rgb_422 GLEW_GET_VAR(__GLEW_APPLE_rgb_422) + +#endif /* GL_APPLE_rgb_422 */ + +/* --------------------------- GL_APPLE_row_bytes -------------------------- */ + +#ifndef GL_APPLE_row_bytes +#define GL_APPLE_row_bytes 1 + +#define GL_PACK_ROW_BYTES_APPLE 0x8A15 +#define GL_UNPACK_ROW_BYTES_APPLE 0x8A16 + +#define GLEW_APPLE_row_bytes GLEW_GET_VAR(__GLEW_APPLE_row_bytes) + +#endif /* GL_APPLE_row_bytes */ + +/* ------------------------ GL_APPLE_specular_vector ----------------------- */ + +#ifndef GL_APPLE_specular_vector +#define GL_APPLE_specular_vector 1 + +#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0 + +#define GLEW_APPLE_specular_vector GLEW_GET_VAR(__GLEW_APPLE_specular_vector) + +#endif /* GL_APPLE_specular_vector */ + +/* ------------------------- GL_APPLE_texture_range ------------------------ */ + +#ifndef GL_APPLE_texture_range +#define GL_APPLE_texture_range 1 + +#define GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7 +#define GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8 +#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC +#define GL_STORAGE_PRIVATE_APPLE 0x85BD +#define GL_STORAGE_CACHED_APPLE 0x85BE +#define GL_STORAGE_SHARED_APPLE 0x85BF + +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, GLvoid **params); +typedef void (GLAPIENTRY * PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, GLvoid *pointer); + +#define glGetTexParameterPointervAPPLE GLEW_GET_FUN(__glewGetTexParameterPointervAPPLE) +#define glTextureRangeAPPLE GLEW_GET_FUN(__glewTextureRangeAPPLE) + +#define GLEW_APPLE_texture_range GLEW_GET_VAR(__GLEW_APPLE_texture_range) + +#endif /* GL_APPLE_texture_range */ + +/* ------------------------ GL_APPLE_transform_hint ------------------------ */ + +#ifndef GL_APPLE_transform_hint +#define GL_APPLE_transform_hint 1 + +#define GL_TRANSFORM_HINT_APPLE 0x85B1 + +#define GLEW_APPLE_transform_hint GLEW_GET_VAR(__GLEW_APPLE_transform_hint) + +#endif /* GL_APPLE_transform_hint */ + +/* ---------------------- GL_APPLE_vertex_array_object --------------------- */ + +#ifndef GL_APPLE_vertex_array_object +#define GL_APPLE_vertex_array_object 1 + +#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5 + +typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array); +typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays); +typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays); +typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array); + +#define glBindVertexArrayAPPLE GLEW_GET_FUN(__glewBindVertexArrayAPPLE) +#define glDeleteVertexArraysAPPLE GLEW_GET_FUN(__glewDeleteVertexArraysAPPLE) +#define glGenVertexArraysAPPLE GLEW_GET_FUN(__glewGenVertexArraysAPPLE) +#define glIsVertexArrayAPPLE GLEW_GET_FUN(__glewIsVertexArrayAPPLE) + +#define GLEW_APPLE_vertex_array_object GLEW_GET_VAR(__GLEW_APPLE_vertex_array_object) + +#endif /* GL_APPLE_vertex_array_object */ + +/* ---------------------- GL_APPLE_vertex_array_range ---------------------- */ + +#ifndef GL_APPLE_vertex_array_range +#define GL_APPLE_vertex_array_range 1 + +#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E +#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F +#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE 0x8520 +#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521 +#define GL_STORAGE_CLIENT_APPLE 0x85B4 +#define GL_STORAGE_CACHED_APPLE 0x85BE +#define GL_STORAGE_SHARED_APPLE 0x85BF + +typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer); + +#define glFlushVertexArrayRangeAPPLE GLEW_GET_FUN(__glewFlushVertexArrayRangeAPPLE) +#define glVertexArrayParameteriAPPLE GLEW_GET_FUN(__glewVertexArrayParameteriAPPLE) +#define glVertexArrayRangeAPPLE GLEW_GET_FUN(__glewVertexArrayRangeAPPLE) + +#define GLEW_APPLE_vertex_array_range GLEW_GET_VAR(__GLEW_APPLE_vertex_array_range) + +#endif /* GL_APPLE_vertex_array_range */ + +/* ------------------- GL_APPLE_vertex_program_evaluators ------------------ */ + +#ifndef GL_APPLE_vertex_program_evaluators +#define GL_APPLE_vertex_program_evaluators 1 + +#define GL_VERTEX_ATTRIB_MAP1_APPLE 0x8A00 +#define GL_VERTEX_ATTRIB_MAP2_APPLE 0x8A01 +#define GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE 0x8A02 +#define GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE 0x8A03 +#define GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE 0x8A04 +#define GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE 0x8A05 +#define GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE 0x8A06 +#define GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE 0x8A07 +#define GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE 0x8A08 +#define GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE 0x8A09 + +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname); +typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXATTRIBENABLEDAPPLEPROC) (GLuint index, GLenum pname); +typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB1DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble* points); +typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB1FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat* points); +typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble* points); +typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat* points); + +#define glDisableVertexAttribAPPLE GLEW_GET_FUN(__glewDisableVertexAttribAPPLE) +#define glEnableVertexAttribAPPLE GLEW_GET_FUN(__glewEnableVertexAttribAPPLE) +#define glIsVertexAttribEnabledAPPLE GLEW_GET_FUN(__glewIsVertexAttribEnabledAPPLE) +#define glMapVertexAttrib1dAPPLE GLEW_GET_FUN(__glewMapVertexAttrib1dAPPLE) +#define glMapVertexAttrib1fAPPLE GLEW_GET_FUN(__glewMapVertexAttrib1fAPPLE) +#define glMapVertexAttrib2dAPPLE GLEW_GET_FUN(__glewMapVertexAttrib2dAPPLE) +#define glMapVertexAttrib2fAPPLE GLEW_GET_FUN(__glewMapVertexAttrib2fAPPLE) + +#define GLEW_APPLE_vertex_program_evaluators GLEW_GET_VAR(__GLEW_APPLE_vertex_program_evaluators) + +#endif /* GL_APPLE_vertex_program_evaluators */ + +/* --------------------------- GL_APPLE_ycbcr_422 -------------------------- */ + +#ifndef GL_APPLE_ycbcr_422 +#define GL_APPLE_ycbcr_422 1 + +#define GL_YCBCR_422_APPLE 0x85B9 +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB + +#define GLEW_APPLE_ycbcr_422 GLEW_GET_VAR(__GLEW_APPLE_ycbcr_422) + +#endif /* GL_APPLE_ycbcr_422 */ + +/* ------------------------ GL_ARB_ES2_compatibility ----------------------- */ + +#ifndef GL_ARB_ES2_compatibility +#define GL_ARB_ES2_compatibility 1 + +#define GL_FIXED 0x140C +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#define GL_SHADER_COMPILER 0x8DFA +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD + +typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFPROC) (GLclampf d); +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFPROC) (GLclampf n, GLclampf f); +typedef void (GLAPIENTRY * PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint* range, GLint *precision); +typedef void (GLAPIENTRY * PFNGLRELEASESHADERCOMPILERPROC) (void); +typedef void (GLAPIENTRY * PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint* shaders, GLenum binaryformat, const GLvoid*binary, GLsizei length); + +#define glClearDepthf GLEW_GET_FUN(__glewClearDepthf) +#define glDepthRangef GLEW_GET_FUN(__glewDepthRangef) +#define glGetShaderPrecisionFormat GLEW_GET_FUN(__glewGetShaderPrecisionFormat) +#define glReleaseShaderCompiler GLEW_GET_FUN(__glewReleaseShaderCompiler) +#define glShaderBinary GLEW_GET_FUN(__glewShaderBinary) + +#define GLEW_ARB_ES2_compatibility GLEW_GET_VAR(__GLEW_ARB_ES2_compatibility) + +#endif /* GL_ARB_ES2_compatibility */ + +/* ----------------------- GL_ARB_blend_func_extended ---------------------- */ + +#ifndef GL_ARB_blend_func_extended +#define GL_ARB_blend_func_extended 1 + +#define GL_SRC1_COLOR 0x88F9 +#define GL_ONE_MINUS_SRC1_COLOR 0x88FA +#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB +#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC + +typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const char * name); +typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const char * name); + +#define glBindFragDataLocationIndexed GLEW_GET_FUN(__glewBindFragDataLocationIndexed) +#define glGetFragDataIndex GLEW_GET_FUN(__glewGetFragDataIndex) + +#define GLEW_ARB_blend_func_extended GLEW_GET_VAR(__GLEW_ARB_blend_func_extended) + +#endif /* GL_ARB_blend_func_extended */ + +/* ---------------------------- GL_ARB_cl_event ---------------------------- */ + +#ifndef GL_ARB_cl_event +#define GL_ARB_cl_event 1 + +#define GL_SYNC_CL_EVENT_ARB 0x8240 +#define GL_SYNC_CL_EVENT_COMPLETE_ARB 0x8241 + +typedef struct _cl_context *cl_context; +typedef struct _cl_event *cl_event; + +typedef GLsync (GLAPIENTRY * PFNGLCREATESYNCFROMCLEVENTARBPROC) (cl_context context, cl_event event, GLbitfield flags); + +#define glCreateSyncFromCLeventARB GLEW_GET_FUN(__glewCreateSyncFromCLeventARB) + +#define GLEW_ARB_cl_event GLEW_GET_VAR(__GLEW_ARB_cl_event) + +#endif /* GL_ARB_cl_event */ + +/* ----------------------- GL_ARB_color_buffer_float ----------------------- */ + +#ifndef GL_ARB_color_buffer_float +#define GL_ARB_color_buffer_float 1 + +#define GL_RGBA_FLOAT_MODE_ARB 0x8820 +#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A +#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B +#define GL_CLAMP_READ_COLOR_ARB 0x891C +#define GL_FIXED_ONLY_ARB 0x891D + +typedef void (GLAPIENTRY * PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp); + +#define glClampColorARB GLEW_GET_FUN(__glewClampColorARB) + +#define GLEW_ARB_color_buffer_float GLEW_GET_VAR(__GLEW_ARB_color_buffer_float) + +#endif /* GL_ARB_color_buffer_float */ + +/* -------------------------- GL_ARB_compatibility ------------------------- */ + +#ifndef GL_ARB_compatibility +#define GL_ARB_compatibility 1 + +#define GLEW_ARB_compatibility GLEW_GET_VAR(__GLEW_ARB_compatibility) + +#endif /* GL_ARB_compatibility */ + +/* --------------------------- GL_ARB_copy_buffer -------------------------- */ + +#ifndef GL_ARB_copy_buffer +#define GL_ARB_copy_buffer 1 + +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 + +typedef void (GLAPIENTRY * PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size); + +#define glCopyBufferSubData GLEW_GET_FUN(__glewCopyBufferSubData) + +#define GLEW_ARB_copy_buffer GLEW_GET_VAR(__GLEW_ARB_copy_buffer) + +#endif /* GL_ARB_copy_buffer */ + +/* -------------------------- GL_ARB_debug_output -------------------------- */ + +#ifndef GL_ARB_debug_output +#define GL_ARB_debug_output 1 + +#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243 +#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245 +#define GL_DEBUG_SOURCE_API_ARB 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A +#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B +#define GL_DEBUG_TYPE_ERROR_ARB 0x824C +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E +#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250 +#define GL_DEBUG_TYPE_OTHER_ARB 0x8251 +#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145 +#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147 +#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148 + +typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam); + +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, void* userParam); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* buf); +typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, char* messageLog); + +#define glDebugMessageCallbackARB GLEW_GET_FUN(__glewDebugMessageCallbackARB) +#define glDebugMessageControlARB GLEW_GET_FUN(__glewDebugMessageControlARB) +#define glDebugMessageInsertARB GLEW_GET_FUN(__glewDebugMessageInsertARB) +#define glGetDebugMessageLogARB GLEW_GET_FUN(__glewGetDebugMessageLogARB) + +#define GLEW_ARB_debug_output GLEW_GET_VAR(__GLEW_ARB_debug_output) + +#endif /* GL_ARB_debug_output */ + +/* ----------------------- GL_ARB_depth_buffer_float ----------------------- */ + +#ifndef GL_ARB_depth_buffer_float +#define GL_ARB_depth_buffer_float 1 + +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD + +#define GLEW_ARB_depth_buffer_float GLEW_GET_VAR(__GLEW_ARB_depth_buffer_float) + +#endif /* GL_ARB_depth_buffer_float */ + +/* --------------------------- GL_ARB_depth_clamp -------------------------- */ + +#ifndef GL_ARB_depth_clamp +#define GL_ARB_depth_clamp 1 + +#define GL_DEPTH_CLAMP 0x864F + +#define GLEW_ARB_depth_clamp GLEW_GET_VAR(__GLEW_ARB_depth_clamp) + +#endif /* GL_ARB_depth_clamp */ + +/* -------------------------- GL_ARB_depth_texture ------------------------- */ + +#ifndef GL_ARB_depth_texture +#define GL_ARB_depth_texture 1 + +#define GL_DEPTH_COMPONENT16_ARB 0x81A5 +#define GL_DEPTH_COMPONENT24_ARB 0x81A6 +#define GL_DEPTH_COMPONENT32_ARB 0x81A7 +#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A +#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B + +#define GLEW_ARB_depth_texture GLEW_GET_VAR(__GLEW_ARB_depth_texture) + +#endif /* GL_ARB_depth_texture */ + +/* -------------------------- GL_ARB_draw_buffers -------------------------- */ + +#ifndef GL_ARB_draw_buffers +#define GL_ARB_draw_buffers 1 + +#define GL_MAX_DRAW_BUFFERS_ARB 0x8824 +#define GL_DRAW_BUFFER0_ARB 0x8825 +#define GL_DRAW_BUFFER1_ARB 0x8826 +#define GL_DRAW_BUFFER2_ARB 0x8827 +#define GL_DRAW_BUFFER3_ARB 0x8828 +#define GL_DRAW_BUFFER4_ARB 0x8829 +#define GL_DRAW_BUFFER5_ARB 0x882A +#define GL_DRAW_BUFFER6_ARB 0x882B +#define GL_DRAW_BUFFER7_ARB 0x882C +#define GL_DRAW_BUFFER8_ARB 0x882D +#define GL_DRAW_BUFFER9_ARB 0x882E +#define GL_DRAW_BUFFER10_ARB 0x882F +#define GL_DRAW_BUFFER11_ARB 0x8830 +#define GL_DRAW_BUFFER12_ARB 0x8831 +#define GL_DRAW_BUFFER13_ARB 0x8832 +#define GL_DRAW_BUFFER14_ARB 0x8833 +#define GL_DRAW_BUFFER15_ARB 0x8834 + +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum* bufs); + +#define glDrawBuffersARB GLEW_GET_FUN(__glewDrawBuffersARB) + +#define GLEW_ARB_draw_buffers GLEW_GET_VAR(__GLEW_ARB_draw_buffers) + +#endif /* GL_ARB_draw_buffers */ + +/* ----------------------- GL_ARB_draw_buffers_blend ----------------------- */ + +#ifndef GL_ARB_draw_buffers_blend +#define GL_ARB_draw_buffers_blend 1 + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEIARBPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONIARBPROC) (GLuint buf, GLenum mode); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEIARBPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLenum dst); + +#define glBlendEquationSeparateiARB GLEW_GET_FUN(__glewBlendEquationSeparateiARB) +#define glBlendEquationiARB GLEW_GET_FUN(__glewBlendEquationiARB) +#define glBlendFuncSeparateiARB GLEW_GET_FUN(__glewBlendFuncSeparateiARB) +#define glBlendFunciARB GLEW_GET_FUN(__glewBlendFunciARB) + +#define GLEW_ARB_draw_buffers_blend GLEW_GET_VAR(__GLEW_ARB_draw_buffers_blend) + +#endif /* GL_ARB_draw_buffers_blend */ + +/* -------------------- GL_ARB_draw_elements_base_vertex ------------------- */ + +#ifndef GL_ARB_draw_elements_base_vertex +#define GL_ARB_draw_elements_base_vertex 1 + +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, void* indices, GLint basevertex); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount, GLint basevertex); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, void* indices, GLint basevertex); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei* count, GLenum type, GLvoid**indices, GLsizei primcount, GLint *basevertex); + +#define glDrawElementsBaseVertex GLEW_GET_FUN(__glewDrawElementsBaseVertex) +#define glDrawElementsInstancedBaseVertex GLEW_GET_FUN(__glewDrawElementsInstancedBaseVertex) +#define glDrawRangeElementsBaseVertex GLEW_GET_FUN(__glewDrawRangeElementsBaseVertex) +#define glMultiDrawElementsBaseVertex GLEW_GET_FUN(__glewMultiDrawElementsBaseVertex) + +#define GLEW_ARB_draw_elements_base_vertex GLEW_GET_VAR(__GLEW_ARB_draw_elements_base_vertex) + +#endif /* GL_ARB_draw_elements_base_vertex */ + +/* -------------------------- GL_ARB_draw_indirect ------------------------- */ + +#ifndef GL_ARB_draw_indirect +#define GL_ARB_draw_indirect 1 + +#define GL_DRAW_INDIRECT_BUFFER 0x8F3F +#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 + +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void* indirect); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void* indirect); + +#define glDrawArraysIndirect GLEW_GET_FUN(__glewDrawArraysIndirect) +#define glDrawElementsIndirect GLEW_GET_FUN(__glewDrawElementsIndirect) + +#define GLEW_ARB_draw_indirect GLEW_GET_VAR(__GLEW_ARB_draw_indirect) + +#endif /* GL_ARB_draw_indirect */ + +/* ------------------------- GL_ARB_draw_instanced ------------------------- */ + +#ifndef GL_ARB_draw_instanced +#define GL_ARB_draw_instanced 1 + +#define GLEW_ARB_draw_instanced GLEW_GET_VAR(__GLEW_ARB_draw_instanced) + +#endif /* GL_ARB_draw_instanced */ + +/* -------------------- GL_ARB_explicit_attrib_location -------------------- */ + +#ifndef GL_ARB_explicit_attrib_location +#define GL_ARB_explicit_attrib_location 1 + +#define GLEW_ARB_explicit_attrib_location GLEW_GET_VAR(__GLEW_ARB_explicit_attrib_location) + +#endif /* GL_ARB_explicit_attrib_location */ + +/* ------------------- GL_ARB_fragment_coord_conventions ------------------- */ + +#ifndef GL_ARB_fragment_coord_conventions +#define GL_ARB_fragment_coord_conventions 1 + +#define GLEW_ARB_fragment_coord_conventions GLEW_GET_VAR(__GLEW_ARB_fragment_coord_conventions) + +#endif /* GL_ARB_fragment_coord_conventions */ + +/* ------------------------ GL_ARB_fragment_program ------------------------ */ + +#ifndef GL_ARB_fragment_program +#define GL_ARB_fragment_program 1 + +#define GL_FRAGMENT_PROGRAM_ARB 0x8804 +#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805 +#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806 +#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807 +#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808 +#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809 +#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A +#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B +#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C +#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D +#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E +#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F +#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810 +#define GL_MAX_TEXTURE_COORDS_ARB 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 + +#define GLEW_ARB_fragment_program GLEW_GET_VAR(__GLEW_ARB_fragment_program) + +#endif /* GL_ARB_fragment_program */ + +/* --------------------- GL_ARB_fragment_program_shadow -------------------- */ + +#ifndef GL_ARB_fragment_program_shadow +#define GL_ARB_fragment_program_shadow 1 + +#define GLEW_ARB_fragment_program_shadow GLEW_GET_VAR(__GLEW_ARB_fragment_program_shadow) + +#endif /* GL_ARB_fragment_program_shadow */ + +/* ------------------------- GL_ARB_fragment_shader ------------------------ */ + +#ifndef GL_ARB_fragment_shader +#define GL_ARB_fragment_shader 1 + +#define GL_FRAGMENT_SHADER_ARB 0x8B30 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B + +#define GLEW_ARB_fragment_shader GLEW_GET_VAR(__GLEW_ARB_fragment_shader) + +#endif /* GL_ARB_fragment_shader */ + +/* ----------------------- GL_ARB_framebuffer_object ----------------------- */ + +#ifndef GL_ARB_framebuffer_object +#define GL_ARB_framebuffer_object 1 + +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_INDEX 0x8222 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_SRGB 0x8C40 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_STENCIL_INDEX1 0x8D46 +#define GL_STENCIL_INDEX4 0x8D47 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_STENCIL_INDEX16 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 + +typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer); +typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint* framebuffers); +typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint* renderbuffers); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target,GLenum attachment, GLuint texture,GLint level,GLint layer); +typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint* framebuffers); +typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint* renderbuffers); +typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer); +typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + +#define glBindFramebuffer GLEW_GET_FUN(__glewBindFramebuffer) +#define glBindRenderbuffer GLEW_GET_FUN(__glewBindRenderbuffer) +#define glBlitFramebuffer GLEW_GET_FUN(__glewBlitFramebuffer) +#define glCheckFramebufferStatus GLEW_GET_FUN(__glewCheckFramebufferStatus) +#define glDeleteFramebuffers GLEW_GET_FUN(__glewDeleteFramebuffers) +#define glDeleteRenderbuffers GLEW_GET_FUN(__glewDeleteRenderbuffers) +#define glFramebufferRenderbuffer GLEW_GET_FUN(__glewFramebufferRenderbuffer) +#define glFramebufferTexture1D GLEW_GET_FUN(__glewFramebufferTexture1D) +#define glFramebufferTexture2D GLEW_GET_FUN(__glewFramebufferTexture2D) +#define glFramebufferTexture3D GLEW_GET_FUN(__glewFramebufferTexture3D) +#define glFramebufferTextureLayer GLEW_GET_FUN(__glewFramebufferTextureLayer) +#define glGenFramebuffers GLEW_GET_FUN(__glewGenFramebuffers) +#define glGenRenderbuffers GLEW_GET_FUN(__glewGenRenderbuffers) +#define glGenerateMipmap GLEW_GET_FUN(__glewGenerateMipmap) +#define glGetFramebufferAttachmentParameteriv GLEW_GET_FUN(__glewGetFramebufferAttachmentParameteriv) +#define glGetRenderbufferParameteriv GLEW_GET_FUN(__glewGetRenderbufferParameteriv) +#define glIsFramebuffer GLEW_GET_FUN(__glewIsFramebuffer) +#define glIsRenderbuffer GLEW_GET_FUN(__glewIsRenderbuffer) +#define glRenderbufferStorage GLEW_GET_FUN(__glewRenderbufferStorage) +#define glRenderbufferStorageMultisample GLEW_GET_FUN(__glewRenderbufferStorageMultisample) + +#define GLEW_ARB_framebuffer_object GLEW_GET_VAR(__GLEW_ARB_framebuffer_object) + +#endif /* GL_ARB_framebuffer_object */ + +/* ------------------------ GL_ARB_framebuffer_sRGB ------------------------ */ + +#ifndef GL_ARB_framebuffer_sRGB +#define GL_ARB_framebuffer_sRGB 1 + +#define GL_FRAMEBUFFER_SRGB 0x8DB9 + +#define GLEW_ARB_framebuffer_sRGB GLEW_GET_VAR(__GLEW_ARB_framebuffer_sRGB) + +#endif /* GL_ARB_framebuffer_sRGB */ + +/* ------------------------ GL_ARB_geometry_shader4 ------------------------ */ + +#ifndef GL_ARB_geometry_shader4 +#define GL_ARB_geometry_shader4 1 + +#define GL_LINES_ADJACENCY_ARB 0xA +#define GL_LINE_STRIP_ADJACENCY_ARB 0xB +#define GL_TRIANGLES_ADJACENCY_ARB 0xC +#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0xD +#define GL_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9 +#define GL_GEOMETRY_SHADER_ARB 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA +#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD +#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1 + +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value); + +#define glFramebufferTextureARB GLEW_GET_FUN(__glewFramebufferTextureARB) +#define glFramebufferTextureFaceARB GLEW_GET_FUN(__glewFramebufferTextureFaceARB) +#define glFramebufferTextureLayerARB GLEW_GET_FUN(__glewFramebufferTextureLayerARB) +#define glProgramParameteriARB GLEW_GET_FUN(__glewProgramParameteriARB) + +#define GLEW_ARB_geometry_shader4 GLEW_GET_VAR(__GLEW_ARB_geometry_shader4) + +#endif /* GL_ARB_geometry_shader4 */ + +/* ----------------------- GL_ARB_get_program_binary ----------------------- */ + +#ifndef GL_ARB_get_program_binary +#define GL_ARB_get_program_binary 1 + +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF + +typedef void (GLAPIENTRY * PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum *binaryFormat, GLvoid*binary); +typedef void (GLAPIENTRY * PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void* binary, GLsizei length); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value); + +#define glGetProgramBinary GLEW_GET_FUN(__glewGetProgramBinary) +#define glProgramBinary GLEW_GET_FUN(__glewProgramBinary) +#define glProgramParameteri GLEW_GET_FUN(__glewProgramParameteri) + +#define GLEW_ARB_get_program_binary GLEW_GET_VAR(__GLEW_ARB_get_program_binary) + +#endif /* GL_ARB_get_program_binary */ + +/* --------------------------- GL_ARB_gpu_shader5 -------------------------- */ + +#ifndef GL_ARB_gpu_shader5 +#define GL_ARB_gpu_shader5 1 + +#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F +#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C +#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D +#define GL_MAX_VERTEX_STREAMS 0x8E71 + +#define GLEW_ARB_gpu_shader5 GLEW_GET_VAR(__GLEW_ARB_gpu_shader5) + +#endif /* GL_ARB_gpu_shader5 */ + +/* ------------------------- GL_ARB_gpu_shader_fp64 ------------------------ */ + +#ifndef GL_ARB_gpu_shader_fp64 +#define GL_ARB_gpu_shader_fp64 1 + +#define GL_DOUBLE_MAT2 0x8F46 +#define GL_DOUBLE_MAT3 0x8F47 +#define GL_DOUBLE_MAT4 0x8F48 +#define GL_DOUBLE_MAT2x3 0x8F49 +#define GL_DOUBLE_MAT2x4 0x8F4A +#define GL_DOUBLE_MAT3x2 0x8F4B +#define GL_DOUBLE_MAT3x4 0x8F4C +#define GL_DOUBLE_MAT4x2 0x8F4D +#define GL_DOUBLE_MAT4x3 0x8F4E +#define GL_DOUBLE_VEC2 0x8FFC +#define GL_DOUBLE_VEC3 0x8FFD +#define GL_DOUBLE_VEC4 0x8FFE + +typedef void (GLAPIENTRY * PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DEXTPROC) (GLuint program, GLint location, GLdouble x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1DPROC) (GLint location, GLdouble x); +typedef void (GLAPIENTRY * PFNGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLUNIFORM2DVPROC) (GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLUNIFORM3DVPROC) (GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLUNIFORM4DVPROC) (GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + +#define glGetUniformdv GLEW_GET_FUN(__glewGetUniformdv) +#define glProgramUniform1dEXT GLEW_GET_FUN(__glewProgramUniform1dEXT) +#define glProgramUniform1dvEXT GLEW_GET_FUN(__glewProgramUniform1dvEXT) +#define glProgramUniform2dEXT GLEW_GET_FUN(__glewProgramUniform2dEXT) +#define glProgramUniform2dvEXT GLEW_GET_FUN(__glewProgramUniform2dvEXT) +#define glProgramUniform3dEXT GLEW_GET_FUN(__glewProgramUniform3dEXT) +#define glProgramUniform3dvEXT GLEW_GET_FUN(__glewProgramUniform3dvEXT) +#define glProgramUniform4dEXT GLEW_GET_FUN(__glewProgramUniform4dEXT) +#define glProgramUniform4dvEXT GLEW_GET_FUN(__glewProgramUniform4dvEXT) +#define glProgramUniformMatrix2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2dvEXT) +#define glProgramUniformMatrix2x3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x3dvEXT) +#define glProgramUniformMatrix2x4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x4dvEXT) +#define glProgramUniformMatrix3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3dvEXT) +#define glProgramUniformMatrix3x2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x2dvEXT) +#define glProgramUniformMatrix3x4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x4dvEXT) +#define glProgramUniformMatrix4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4dvEXT) +#define glProgramUniformMatrix4x2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x2dvEXT) +#define glProgramUniformMatrix4x3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x3dvEXT) +#define glUniform1d GLEW_GET_FUN(__glewUniform1d) +#define glUniform1dv GLEW_GET_FUN(__glewUniform1dv) +#define glUniform2d GLEW_GET_FUN(__glewUniform2d) +#define glUniform2dv GLEW_GET_FUN(__glewUniform2dv) +#define glUniform3d GLEW_GET_FUN(__glewUniform3d) +#define glUniform3dv GLEW_GET_FUN(__glewUniform3dv) +#define glUniform4d GLEW_GET_FUN(__glewUniform4d) +#define glUniform4dv GLEW_GET_FUN(__glewUniform4dv) +#define glUniformMatrix2dv GLEW_GET_FUN(__glewUniformMatrix2dv) +#define glUniformMatrix2x3dv GLEW_GET_FUN(__glewUniformMatrix2x3dv) +#define glUniformMatrix2x4dv GLEW_GET_FUN(__glewUniformMatrix2x4dv) +#define glUniformMatrix3dv GLEW_GET_FUN(__glewUniformMatrix3dv) +#define glUniformMatrix3x2dv GLEW_GET_FUN(__glewUniformMatrix3x2dv) +#define glUniformMatrix3x4dv GLEW_GET_FUN(__glewUniformMatrix3x4dv) +#define glUniformMatrix4dv GLEW_GET_FUN(__glewUniformMatrix4dv) +#define glUniformMatrix4x2dv GLEW_GET_FUN(__glewUniformMatrix4x2dv) +#define glUniformMatrix4x3dv GLEW_GET_FUN(__glewUniformMatrix4x3dv) + +#define GLEW_ARB_gpu_shader_fp64 GLEW_GET_VAR(__GLEW_ARB_gpu_shader_fp64) + +#endif /* GL_ARB_gpu_shader_fp64 */ + +/* ------------------------ GL_ARB_half_float_pixel ------------------------ */ + +#ifndef GL_ARB_half_float_pixel +#define GL_ARB_half_float_pixel 1 + +#define GL_HALF_FLOAT_ARB 0x140B + +#define GLEW_ARB_half_float_pixel GLEW_GET_VAR(__GLEW_ARB_half_float_pixel) + +#endif /* GL_ARB_half_float_pixel */ + +/* ------------------------ GL_ARB_half_float_vertex ----------------------- */ + +#ifndef GL_ARB_half_float_vertex +#define GL_ARB_half_float_vertex 1 + +#define GL_HALF_FLOAT 0x140B + +#define GLEW_ARB_half_float_vertex GLEW_GET_VAR(__GLEW_ARB_half_float_vertex) + +#endif /* GL_ARB_half_float_vertex */ + +/* ----------------------------- GL_ARB_imaging ---------------------------- */ + +#ifndef GL_ARB_imaging +#define GL_ARB_imaging 1 + +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 +#define GL_FUNC_ADD 0x8006 +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_BLEND_EQUATION 0x8009 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_CONVOLUTION_1D 0x8010 +#define GL_CONVOLUTION_2D 0x8011 +#define GL_SEPARABLE_2D 0x8012 +#define GL_CONVOLUTION_BORDER_MODE 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS 0x8015 +#define GL_REDUCE 0x8016 +#define GL_CONVOLUTION_FORMAT 0x8017 +#define GL_CONVOLUTION_WIDTH 0x8018 +#define GL_CONVOLUTION_HEIGHT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 +#define GL_HISTOGRAM 0x8024 +#define GL_PROXY_HISTOGRAM 0x8025 +#define GL_HISTOGRAM_WIDTH 0x8026 +#define GL_HISTOGRAM_FORMAT 0x8027 +#define GL_HISTOGRAM_RED_SIZE 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C +#define GL_HISTOGRAM_SINK 0x802D +#define GL_MINMAX 0x802E +#define GL_MINMAX_FORMAT 0x802F +#define GL_MINMAX_SINK 0x8030 +#define GL_TABLE_TOO_LARGE 0x8031 +#define GL_COLOR_MATRIX 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB +#define GL_COLOR_TABLE 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 +#define GL_PROXY_COLOR_TABLE 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 +#define GL_COLOR_TABLE_SCALE 0x80D6 +#define GL_COLOR_TABLE_BIAS 0x80D7 +#define GL_COLOR_TABLE_FORMAT 0x80D8 +#define GL_COLOR_TABLE_WIDTH 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF +#define GL_IGNORE_BORDER 0x8150 +#define GL_CONSTANT_BORDER 0x8151 +#define GL_WRAP_BORDER 0x8152 +#define GL_REPLICATE_BORDER 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR 0x8154 + +typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum types, GLvoid *values); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); +typedef void (GLAPIENTRY * PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRY * PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLRESETMINMAXPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); + +#define glColorSubTable GLEW_GET_FUN(__glewColorSubTable) +#define glColorTable GLEW_GET_FUN(__glewColorTable) +#define glColorTableParameterfv GLEW_GET_FUN(__glewColorTableParameterfv) +#define glColorTableParameteriv GLEW_GET_FUN(__glewColorTableParameteriv) +#define glConvolutionFilter1D GLEW_GET_FUN(__glewConvolutionFilter1D) +#define glConvolutionFilter2D GLEW_GET_FUN(__glewConvolutionFilter2D) +#define glConvolutionParameterf GLEW_GET_FUN(__glewConvolutionParameterf) +#define glConvolutionParameterfv GLEW_GET_FUN(__glewConvolutionParameterfv) +#define glConvolutionParameteri GLEW_GET_FUN(__glewConvolutionParameteri) +#define glConvolutionParameteriv GLEW_GET_FUN(__glewConvolutionParameteriv) +#define glCopyColorSubTable GLEW_GET_FUN(__glewCopyColorSubTable) +#define glCopyColorTable GLEW_GET_FUN(__glewCopyColorTable) +#define glCopyConvolutionFilter1D GLEW_GET_FUN(__glewCopyConvolutionFilter1D) +#define glCopyConvolutionFilter2D GLEW_GET_FUN(__glewCopyConvolutionFilter2D) +#define glGetColorTable GLEW_GET_FUN(__glewGetColorTable) +#define glGetColorTableParameterfv GLEW_GET_FUN(__glewGetColorTableParameterfv) +#define glGetColorTableParameteriv GLEW_GET_FUN(__glewGetColorTableParameteriv) +#define glGetConvolutionFilter GLEW_GET_FUN(__glewGetConvolutionFilter) +#define glGetConvolutionParameterfv GLEW_GET_FUN(__glewGetConvolutionParameterfv) +#define glGetConvolutionParameteriv GLEW_GET_FUN(__glewGetConvolutionParameteriv) +#define glGetHistogram GLEW_GET_FUN(__glewGetHistogram) +#define glGetHistogramParameterfv GLEW_GET_FUN(__glewGetHistogramParameterfv) +#define glGetHistogramParameteriv GLEW_GET_FUN(__glewGetHistogramParameteriv) +#define glGetMinmax GLEW_GET_FUN(__glewGetMinmax) +#define glGetMinmaxParameterfv GLEW_GET_FUN(__glewGetMinmaxParameterfv) +#define glGetMinmaxParameteriv GLEW_GET_FUN(__glewGetMinmaxParameteriv) +#define glGetSeparableFilter GLEW_GET_FUN(__glewGetSeparableFilter) +#define glHistogram GLEW_GET_FUN(__glewHistogram) +#define glMinmax GLEW_GET_FUN(__glewMinmax) +#define glResetHistogram GLEW_GET_FUN(__glewResetHistogram) +#define glResetMinmax GLEW_GET_FUN(__glewResetMinmax) +#define glSeparableFilter2D GLEW_GET_FUN(__glewSeparableFilter2D) + +#define GLEW_ARB_imaging GLEW_GET_VAR(__GLEW_ARB_imaging) + +#endif /* GL_ARB_imaging */ + +/* ------------------------ GL_ARB_instanced_arrays ------------------------ */ + +#ifndef GL_ARB_instanced_arrays +#define GL_ARB_instanced_arrays 1 + +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE + +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor); + +#define glDrawArraysInstancedARB GLEW_GET_FUN(__glewDrawArraysInstancedARB) +#define glDrawElementsInstancedARB GLEW_GET_FUN(__glewDrawElementsInstancedARB) +#define glVertexAttribDivisorARB GLEW_GET_FUN(__glewVertexAttribDivisorARB) + +#define GLEW_ARB_instanced_arrays GLEW_GET_VAR(__GLEW_ARB_instanced_arrays) + +#endif /* GL_ARB_instanced_arrays */ + +/* ------------------------ GL_ARB_map_buffer_range ------------------------ */ + +#ifndef GL_ARB_map_buffer_range +#define GL_ARB_map_buffer_range 1 + +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 + +typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length); +typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); + +#define glFlushMappedBufferRange GLEW_GET_FUN(__glewFlushMappedBufferRange) +#define glMapBufferRange GLEW_GET_FUN(__glewMapBufferRange) + +#define GLEW_ARB_map_buffer_range GLEW_GET_VAR(__GLEW_ARB_map_buffer_range) + +#endif /* GL_ARB_map_buffer_range */ + +/* ------------------------- GL_ARB_matrix_palette ------------------------- */ + +#ifndef GL_ARB_matrix_palette +#define GL_ARB_matrix_palette 1 + +#define GL_MATRIX_PALETTE_ARB 0x8840 +#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841 +#define GL_MAX_PALETTE_MATRICES_ARB 0x8842 +#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843 +#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844 +#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845 +#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846 +#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847 +#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848 +#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849 + +typedef void (GLAPIENTRY * PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUBVARBPROC) (GLint size, GLubyte *indices); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUIVARBPROC) (GLint size, GLuint *indices); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUSVARBPROC) (GLint size, GLushort *indices); + +#define glCurrentPaletteMatrixARB GLEW_GET_FUN(__glewCurrentPaletteMatrixARB) +#define glMatrixIndexPointerARB GLEW_GET_FUN(__glewMatrixIndexPointerARB) +#define glMatrixIndexubvARB GLEW_GET_FUN(__glewMatrixIndexubvARB) +#define glMatrixIndexuivARB GLEW_GET_FUN(__glewMatrixIndexuivARB) +#define glMatrixIndexusvARB GLEW_GET_FUN(__glewMatrixIndexusvARB) + +#define GLEW_ARB_matrix_palette GLEW_GET_VAR(__GLEW_ARB_matrix_palette) + +#endif /* GL_ARB_matrix_palette */ + +/* --------------------------- GL_ARB_multisample -------------------------- */ + +#ifndef GL_ARB_multisample +#define GL_ARB_multisample 1 + +#define GL_MULTISAMPLE_ARB 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F +#define GL_SAMPLE_COVERAGE_ARB 0x80A0 +#define GL_SAMPLE_BUFFERS_ARB 0x80A8 +#define GL_SAMPLES_ARB 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB +#define GL_MULTISAMPLE_BIT_ARB 0x20000000 + +typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert); + +#define glSampleCoverageARB GLEW_GET_FUN(__glewSampleCoverageARB) + +#define GLEW_ARB_multisample GLEW_GET_VAR(__GLEW_ARB_multisample) + +#endif /* GL_ARB_multisample */ + +/* -------------------------- GL_ARB_multitexture -------------------------- */ + +#ifndef GL_ARB_multitexture +#define GL_ARB_multitexture 1 + +#define GL_TEXTURE0_ARB 0x84C0 +#define GL_TEXTURE1_ARB 0x84C1 +#define GL_TEXTURE2_ARB 0x84C2 +#define GL_TEXTURE3_ARB 0x84C3 +#define GL_TEXTURE4_ARB 0x84C4 +#define GL_TEXTURE5_ARB 0x84C5 +#define GL_TEXTURE6_ARB 0x84C6 +#define GL_TEXTURE7_ARB 0x84C7 +#define GL_TEXTURE8_ARB 0x84C8 +#define GL_TEXTURE9_ARB 0x84C9 +#define GL_TEXTURE10_ARB 0x84CA +#define GL_TEXTURE11_ARB 0x84CB +#define GL_TEXTURE12_ARB 0x84CC +#define GL_TEXTURE13_ARB 0x84CD +#define GL_TEXTURE14_ARB 0x84CE +#define GL_TEXTURE15_ARB 0x84CF +#define GL_TEXTURE16_ARB 0x84D0 +#define GL_TEXTURE17_ARB 0x84D1 +#define GL_TEXTURE18_ARB 0x84D2 +#define GL_TEXTURE19_ARB 0x84D3 +#define GL_TEXTURE20_ARB 0x84D4 +#define GL_TEXTURE21_ARB 0x84D5 +#define GL_TEXTURE22_ARB 0x84D6 +#define GL_TEXTURE23_ARB 0x84D7 +#define GL_TEXTURE24_ARB 0x84D8 +#define GL_TEXTURE25_ARB 0x84D9 +#define GL_TEXTURE26_ARB 0x84DA +#define GL_TEXTURE27_ARB 0x84DB +#define GL_TEXTURE28_ARB 0x84DC +#define GL_TEXTURE29_ARB 0x84DD +#define GL_TEXTURE30_ARB 0x84DE +#define GL_TEXTURE31_ARB 0x84DF +#define GL_ACTIVE_TEXTURE_ARB 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 +#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 + +typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v); + +#define glActiveTextureARB GLEW_GET_FUN(__glewActiveTextureARB) +#define glClientActiveTextureARB GLEW_GET_FUN(__glewClientActiveTextureARB) +#define glMultiTexCoord1dARB GLEW_GET_FUN(__glewMultiTexCoord1dARB) +#define glMultiTexCoord1dvARB GLEW_GET_FUN(__glewMultiTexCoord1dvARB) +#define glMultiTexCoord1fARB GLEW_GET_FUN(__glewMultiTexCoord1fARB) +#define glMultiTexCoord1fvARB GLEW_GET_FUN(__glewMultiTexCoord1fvARB) +#define glMultiTexCoord1iARB GLEW_GET_FUN(__glewMultiTexCoord1iARB) +#define glMultiTexCoord1ivARB GLEW_GET_FUN(__glewMultiTexCoord1ivARB) +#define glMultiTexCoord1sARB GLEW_GET_FUN(__glewMultiTexCoord1sARB) +#define glMultiTexCoord1svARB GLEW_GET_FUN(__glewMultiTexCoord1svARB) +#define glMultiTexCoord2dARB GLEW_GET_FUN(__glewMultiTexCoord2dARB) +#define glMultiTexCoord2dvARB GLEW_GET_FUN(__glewMultiTexCoord2dvARB) +#define glMultiTexCoord2fARB GLEW_GET_FUN(__glewMultiTexCoord2fARB) +#define glMultiTexCoord2fvARB GLEW_GET_FUN(__glewMultiTexCoord2fvARB) +#define glMultiTexCoord2iARB GLEW_GET_FUN(__glewMultiTexCoord2iARB) +#define glMultiTexCoord2ivARB GLEW_GET_FUN(__glewMultiTexCoord2ivARB) +#define glMultiTexCoord2sARB GLEW_GET_FUN(__glewMultiTexCoord2sARB) +#define glMultiTexCoord2svARB GLEW_GET_FUN(__glewMultiTexCoord2svARB) +#define glMultiTexCoord3dARB GLEW_GET_FUN(__glewMultiTexCoord3dARB) +#define glMultiTexCoord3dvARB GLEW_GET_FUN(__glewMultiTexCoord3dvARB) +#define glMultiTexCoord3fARB GLEW_GET_FUN(__glewMultiTexCoord3fARB) +#define glMultiTexCoord3fvARB GLEW_GET_FUN(__glewMultiTexCoord3fvARB) +#define glMultiTexCoord3iARB GLEW_GET_FUN(__glewMultiTexCoord3iARB) +#define glMultiTexCoord3ivARB GLEW_GET_FUN(__glewMultiTexCoord3ivARB) +#define glMultiTexCoord3sARB GLEW_GET_FUN(__glewMultiTexCoord3sARB) +#define glMultiTexCoord3svARB GLEW_GET_FUN(__glewMultiTexCoord3svARB) +#define glMultiTexCoord4dARB GLEW_GET_FUN(__glewMultiTexCoord4dARB) +#define glMultiTexCoord4dvARB GLEW_GET_FUN(__glewMultiTexCoord4dvARB) +#define glMultiTexCoord4fARB GLEW_GET_FUN(__glewMultiTexCoord4fARB) +#define glMultiTexCoord4fvARB GLEW_GET_FUN(__glewMultiTexCoord4fvARB) +#define glMultiTexCoord4iARB GLEW_GET_FUN(__glewMultiTexCoord4iARB) +#define glMultiTexCoord4ivARB GLEW_GET_FUN(__glewMultiTexCoord4ivARB) +#define glMultiTexCoord4sARB GLEW_GET_FUN(__glewMultiTexCoord4sARB) +#define glMultiTexCoord4svARB GLEW_GET_FUN(__glewMultiTexCoord4svARB) + +#define GLEW_ARB_multitexture GLEW_GET_VAR(__GLEW_ARB_multitexture) + +#endif /* GL_ARB_multitexture */ + +/* ------------------------- GL_ARB_occlusion_query ------------------------ */ + +#ifndef GL_ARB_occlusion_query +#define GL_ARB_occlusion_query 1 + +#define GL_QUERY_COUNTER_BITS_ARB 0x8864 +#define GL_CURRENT_QUERY_ARB 0x8865 +#define GL_QUERY_RESULT_ARB 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 +#define GL_SAMPLES_PASSED_ARB 0x8914 + +typedef void (GLAPIENTRY * PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLENDQUERYARBPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISQUERYARBPROC) (GLuint id); + +#define glBeginQueryARB GLEW_GET_FUN(__glewBeginQueryARB) +#define glDeleteQueriesARB GLEW_GET_FUN(__glewDeleteQueriesARB) +#define glEndQueryARB GLEW_GET_FUN(__glewEndQueryARB) +#define glGenQueriesARB GLEW_GET_FUN(__glewGenQueriesARB) +#define glGetQueryObjectivARB GLEW_GET_FUN(__glewGetQueryObjectivARB) +#define glGetQueryObjectuivARB GLEW_GET_FUN(__glewGetQueryObjectuivARB) +#define glGetQueryivARB GLEW_GET_FUN(__glewGetQueryivARB) +#define glIsQueryARB GLEW_GET_FUN(__glewIsQueryARB) + +#define GLEW_ARB_occlusion_query GLEW_GET_VAR(__GLEW_ARB_occlusion_query) + +#endif /* GL_ARB_occlusion_query */ + +/* ------------------------ GL_ARB_occlusion_query2 ------------------------ */ + +#ifndef GL_ARB_occlusion_query2 +#define GL_ARB_occlusion_query2 1 + +#define GL_ANY_SAMPLES_PASSED 0x8C2F + +#define GLEW_ARB_occlusion_query2 GLEW_GET_VAR(__GLEW_ARB_occlusion_query2) + +#endif /* GL_ARB_occlusion_query2 */ + +/* ----------------------- GL_ARB_pixel_buffer_object ---------------------- */ + +#ifndef GL_ARB_pixel_buffer_object +#define GL_ARB_pixel_buffer_object 1 + +#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF + +#define GLEW_ARB_pixel_buffer_object GLEW_GET_VAR(__GLEW_ARB_pixel_buffer_object) + +#endif /* GL_ARB_pixel_buffer_object */ + +/* ------------------------ GL_ARB_point_parameters ------------------------ */ + +#ifndef GL_ARB_point_parameters +#define GL_ARB_point_parameters 1 + +#define GL_POINT_SIZE_MIN_ARB 0x8126 +#define GL_POINT_SIZE_MAX_ARB 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129 + +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat* params); + +#define glPointParameterfARB GLEW_GET_FUN(__glewPointParameterfARB) +#define glPointParameterfvARB GLEW_GET_FUN(__glewPointParameterfvARB) + +#define GLEW_ARB_point_parameters GLEW_GET_VAR(__GLEW_ARB_point_parameters) + +#endif /* GL_ARB_point_parameters */ + +/* -------------------------- GL_ARB_point_sprite -------------------------- */ + +#ifndef GL_ARB_point_sprite +#define GL_ARB_point_sprite 1 + +#define GL_POINT_SPRITE_ARB 0x8861 +#define GL_COORD_REPLACE_ARB 0x8862 + +#define GLEW_ARB_point_sprite GLEW_GET_VAR(__GLEW_ARB_point_sprite) + +#endif /* GL_ARB_point_sprite */ + +/* ------------------------ GL_ARB_provoking_vertex ------------------------ */ + +#ifndef GL_ARB_provoking_vertex +#define GL_ARB_provoking_vertex 1 + +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_PROVOKING_VERTEX 0x8E4F + +typedef void (GLAPIENTRY * PFNGLPROVOKINGVERTEXPROC) (GLenum mode); + +#define glProvokingVertex GLEW_GET_FUN(__glewProvokingVertex) + +#define GLEW_ARB_provoking_vertex GLEW_GET_VAR(__GLEW_ARB_provoking_vertex) + +#endif /* GL_ARB_provoking_vertex */ + +/* --------------------------- GL_ARB_robustness --------------------------- */ + +#ifndef GL_ARB_robustness +#define GL_ARB_robustness 1 + +#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253 +#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254 +#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255 +#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define GL_NO_RESET_NOTIFICATION_ARB 0x8261 + +typedef void (GLAPIENTRY * PFNGLGETNCOLORTABLEARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void* table); +typedef void (GLAPIENTRY * PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLsizei bufSize, void* img); +typedef void (GLAPIENTRY * PFNGLGETNCONVOLUTIONFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void* image); +typedef void (GLAPIENTRY * PFNGLGETNHISTOGRAMARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void* values); +typedef void (GLAPIENTRY * PFNGLGETNMAPDVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLdouble* v); +typedef void (GLAPIENTRY * PFNGLGETNMAPFVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLfloat* v); +typedef void (GLAPIENTRY * PFNGLGETNMAPIVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLint* v); +typedef void (GLAPIENTRY * PFNGLGETNMINMAXARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void* values); +typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPFVARBPROC) (GLenum map, GLsizei bufSize, GLfloat* values); +typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPUIVARBPROC) (GLenum map, GLsizei bufSize, GLuint* values); +typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPUSVARBPROC) (GLenum map, GLsizei bufSize, GLushort* values); +typedef void (GLAPIENTRY * PFNGLGETNPOLYGONSTIPPLEARBPROC) (GLsizei bufSize, GLubyte* pattern); +typedef void (GLAPIENTRY * PFNGLGETNSEPARABLEFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void* row, GLsizei columnBufSize, GLvoid*column, GLvoid*span); +typedef void (GLAPIENTRY * PFNGLGETNTEXIMAGEARBPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* img); +typedef void (GLAPIENTRY * PFNGLGETNUNIFORMDVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETNUNIFORMFVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETNUNIFORMIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNUNIFORMUIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint* params); +typedef void (GLAPIENTRY * PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void* data); + +#define glGetnColorTableARB GLEW_GET_FUN(__glewGetnColorTableARB) +#define glGetnCompressedTexImageARB GLEW_GET_FUN(__glewGetnCompressedTexImageARB) +#define glGetnConvolutionFilterARB GLEW_GET_FUN(__glewGetnConvolutionFilterARB) +#define glGetnHistogramARB GLEW_GET_FUN(__glewGetnHistogramARB) +#define glGetnMapdvARB GLEW_GET_FUN(__glewGetnMapdvARB) +#define glGetnMapfvARB GLEW_GET_FUN(__glewGetnMapfvARB) +#define glGetnMapivARB GLEW_GET_FUN(__glewGetnMapivARB) +#define glGetnMinmaxARB GLEW_GET_FUN(__glewGetnMinmaxARB) +#define glGetnPixelMapfvARB GLEW_GET_FUN(__glewGetnPixelMapfvARB) +#define glGetnPixelMapuivARB GLEW_GET_FUN(__glewGetnPixelMapuivARB) +#define glGetnPixelMapusvARB GLEW_GET_FUN(__glewGetnPixelMapusvARB) +#define glGetnPolygonStippleARB GLEW_GET_FUN(__glewGetnPolygonStippleARB) +#define glGetnSeparableFilterARB GLEW_GET_FUN(__glewGetnSeparableFilterARB) +#define glGetnTexImageARB GLEW_GET_FUN(__glewGetnTexImageARB) +#define glGetnUniformdvARB GLEW_GET_FUN(__glewGetnUniformdvARB) +#define glGetnUniformfvARB GLEW_GET_FUN(__glewGetnUniformfvARB) +#define glGetnUniformivARB GLEW_GET_FUN(__glewGetnUniformivARB) +#define glGetnUniformuivARB GLEW_GET_FUN(__glewGetnUniformuivARB) +#define glReadnPixelsARB GLEW_GET_FUN(__glewReadnPixelsARB) + +#define GLEW_ARB_robustness GLEW_GET_VAR(__GLEW_ARB_robustness) + +#endif /* GL_ARB_robustness */ + +/* ------------------------- GL_ARB_sample_shading ------------------------- */ + +#ifndef GL_ARB_sample_shading +#define GL_ARB_sample_shading 1 + +#define GL_SAMPLE_SHADING_ARB 0x8C36 +#define GL_MIN_SAMPLE_SHADING_VALUE_ARB 0x8C37 + +typedef void (GLAPIENTRY * PFNGLMINSAMPLESHADINGARBPROC) (GLclampf value); + +#define glMinSampleShadingARB GLEW_GET_FUN(__glewMinSampleShadingARB) + +#define GLEW_ARB_sample_shading GLEW_GET_VAR(__GLEW_ARB_sample_shading) + +#endif /* GL_ARB_sample_shading */ + +/* ------------------------- GL_ARB_sampler_objects ------------------------ */ + +#ifndef GL_ARB_sampler_objects +#define GL_ARB_sampler_objects 1 + +#define GL_SAMPLER_BINDING 0x8919 + +typedef void (GLAPIENTRY * PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); +typedef void (GLAPIENTRY * PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint * samplers); +typedef void (GLAPIENTRY * PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint* samplers); +typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISSAMPLERPROC) (GLuint sampler); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint* params); + +#define glBindSampler GLEW_GET_FUN(__glewBindSampler) +#define glDeleteSamplers GLEW_GET_FUN(__glewDeleteSamplers) +#define glGenSamplers GLEW_GET_FUN(__glewGenSamplers) +#define glGetSamplerParameterIiv GLEW_GET_FUN(__glewGetSamplerParameterIiv) +#define glGetSamplerParameterIuiv GLEW_GET_FUN(__glewGetSamplerParameterIuiv) +#define glGetSamplerParameterfv GLEW_GET_FUN(__glewGetSamplerParameterfv) +#define glGetSamplerParameteriv GLEW_GET_FUN(__glewGetSamplerParameteriv) +#define glIsSampler GLEW_GET_FUN(__glewIsSampler) +#define glSamplerParameterIiv GLEW_GET_FUN(__glewSamplerParameterIiv) +#define glSamplerParameterIuiv GLEW_GET_FUN(__glewSamplerParameterIuiv) +#define glSamplerParameterf GLEW_GET_FUN(__glewSamplerParameterf) +#define glSamplerParameterfv GLEW_GET_FUN(__glewSamplerParameterfv) +#define glSamplerParameteri GLEW_GET_FUN(__glewSamplerParameteri) +#define glSamplerParameteriv GLEW_GET_FUN(__glewSamplerParameteriv) + +#define GLEW_ARB_sampler_objects GLEW_GET_VAR(__GLEW_ARB_sampler_objects) + +#endif /* GL_ARB_sampler_objects */ + +/* ------------------------ GL_ARB_seamless_cube_map ----------------------- */ + +#ifndef GL_ARB_seamless_cube_map +#define GL_ARB_seamless_cube_map 1 + +#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F + +#define GLEW_ARB_seamless_cube_map GLEW_GET_VAR(__GLEW_ARB_seamless_cube_map) + +#endif /* GL_ARB_seamless_cube_map */ + +/* --------------------- GL_ARB_separate_shader_objects -------------------- */ + +#ifndef GL_ARB_separate_shader_objects +#define GL_ARB_separate_shader_objects 1 + +#define GL_VERTEX_SHADER_BIT 0x00000001 +#define GL_FRAGMENT_SHADER_BIT 0x00000002 +#define GL_GEOMETRY_SHADER_BIT 0x00000004 +#define GL_TESS_CONTROL_SHADER_BIT 0x00000008 +#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010 +#define GL_PROGRAM_SEPARABLE 0x8258 +#define GL_ACTIVE_PROGRAM 0x8259 +#define GL_PROGRAM_PIPELINE_BINDING 0x825A +#define GL_ALL_SHADER_BITS 0xFFFFFFFF + +typedef void (GLAPIENTRY * PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program); +typedef void (GLAPIENTRY * PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const char ** strings); +typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint* pipelines); +typedef void (GLAPIENTRY * PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint* pipelines); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei* length, char *infoLog); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint x, GLuint y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint x, GLuint y, GLuint z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program); +typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline); + +#define glActiveShaderProgram GLEW_GET_FUN(__glewActiveShaderProgram) +#define glBindProgramPipeline GLEW_GET_FUN(__glewBindProgramPipeline) +#define glCreateShaderProgramv GLEW_GET_FUN(__glewCreateShaderProgramv) +#define glDeleteProgramPipelines GLEW_GET_FUN(__glewDeleteProgramPipelines) +#define glGenProgramPipelines GLEW_GET_FUN(__glewGenProgramPipelines) +#define glGetProgramPipelineInfoLog GLEW_GET_FUN(__glewGetProgramPipelineInfoLog) +#define glGetProgramPipelineiv GLEW_GET_FUN(__glewGetProgramPipelineiv) +#define glIsProgramPipeline GLEW_GET_FUN(__glewIsProgramPipeline) +#define glProgramUniform1d GLEW_GET_FUN(__glewProgramUniform1d) +#define glProgramUniform1dv GLEW_GET_FUN(__glewProgramUniform1dv) +#define glProgramUniform1f GLEW_GET_FUN(__glewProgramUniform1f) +#define glProgramUniform1fv GLEW_GET_FUN(__glewProgramUniform1fv) +#define glProgramUniform1i GLEW_GET_FUN(__glewProgramUniform1i) +#define glProgramUniform1iv GLEW_GET_FUN(__glewProgramUniform1iv) +#define glProgramUniform1ui GLEW_GET_FUN(__glewProgramUniform1ui) +#define glProgramUniform1uiv GLEW_GET_FUN(__glewProgramUniform1uiv) +#define glProgramUniform2d GLEW_GET_FUN(__glewProgramUniform2d) +#define glProgramUniform2dv GLEW_GET_FUN(__glewProgramUniform2dv) +#define glProgramUniform2f GLEW_GET_FUN(__glewProgramUniform2f) +#define glProgramUniform2fv GLEW_GET_FUN(__glewProgramUniform2fv) +#define glProgramUniform2i GLEW_GET_FUN(__glewProgramUniform2i) +#define glProgramUniform2iv GLEW_GET_FUN(__glewProgramUniform2iv) +#define glProgramUniform2ui GLEW_GET_FUN(__glewProgramUniform2ui) +#define glProgramUniform2uiv GLEW_GET_FUN(__glewProgramUniform2uiv) +#define glProgramUniform3d GLEW_GET_FUN(__glewProgramUniform3d) +#define glProgramUniform3dv GLEW_GET_FUN(__glewProgramUniform3dv) +#define glProgramUniform3f GLEW_GET_FUN(__glewProgramUniform3f) +#define glProgramUniform3fv GLEW_GET_FUN(__glewProgramUniform3fv) +#define glProgramUniform3i GLEW_GET_FUN(__glewProgramUniform3i) +#define glProgramUniform3iv GLEW_GET_FUN(__glewProgramUniform3iv) +#define glProgramUniform3ui GLEW_GET_FUN(__glewProgramUniform3ui) +#define glProgramUniform3uiv GLEW_GET_FUN(__glewProgramUniform3uiv) +#define glProgramUniform4d GLEW_GET_FUN(__glewProgramUniform4d) +#define glProgramUniform4dv GLEW_GET_FUN(__glewProgramUniform4dv) +#define glProgramUniform4f GLEW_GET_FUN(__glewProgramUniform4f) +#define glProgramUniform4fv GLEW_GET_FUN(__glewProgramUniform4fv) +#define glProgramUniform4i GLEW_GET_FUN(__glewProgramUniform4i) +#define glProgramUniform4iv GLEW_GET_FUN(__glewProgramUniform4iv) +#define glProgramUniform4ui GLEW_GET_FUN(__glewProgramUniform4ui) +#define glProgramUniform4uiv GLEW_GET_FUN(__glewProgramUniform4uiv) +#define glProgramUniformMatrix2dv GLEW_GET_FUN(__glewProgramUniformMatrix2dv) +#define glProgramUniformMatrix2fv GLEW_GET_FUN(__glewProgramUniformMatrix2fv) +#define glProgramUniformMatrix2x3dv GLEW_GET_FUN(__glewProgramUniformMatrix2x3dv) +#define glProgramUniformMatrix2x3fv GLEW_GET_FUN(__glewProgramUniformMatrix2x3fv) +#define glProgramUniformMatrix2x4dv GLEW_GET_FUN(__glewProgramUniformMatrix2x4dv) +#define glProgramUniformMatrix2x4fv GLEW_GET_FUN(__glewProgramUniformMatrix2x4fv) +#define glProgramUniformMatrix3dv GLEW_GET_FUN(__glewProgramUniformMatrix3dv) +#define glProgramUniformMatrix3fv GLEW_GET_FUN(__glewProgramUniformMatrix3fv) +#define glProgramUniformMatrix3x2dv GLEW_GET_FUN(__glewProgramUniformMatrix3x2dv) +#define glProgramUniformMatrix3x2fv GLEW_GET_FUN(__glewProgramUniformMatrix3x2fv) +#define glProgramUniformMatrix3x4dv GLEW_GET_FUN(__glewProgramUniformMatrix3x4dv) +#define glProgramUniformMatrix3x4fv GLEW_GET_FUN(__glewProgramUniformMatrix3x4fv) +#define glProgramUniformMatrix4dv GLEW_GET_FUN(__glewProgramUniformMatrix4dv) +#define glProgramUniformMatrix4fv GLEW_GET_FUN(__glewProgramUniformMatrix4fv) +#define glProgramUniformMatrix4x2dv GLEW_GET_FUN(__glewProgramUniformMatrix4x2dv) +#define glProgramUniformMatrix4x2fv GLEW_GET_FUN(__glewProgramUniformMatrix4x2fv) +#define glProgramUniformMatrix4x3dv GLEW_GET_FUN(__glewProgramUniformMatrix4x3dv) +#define glProgramUniformMatrix4x3fv GLEW_GET_FUN(__glewProgramUniformMatrix4x3fv) +#define glUseProgramStages GLEW_GET_FUN(__glewUseProgramStages) +#define glValidateProgramPipeline GLEW_GET_FUN(__glewValidateProgramPipeline) + +#define GLEW_ARB_separate_shader_objects GLEW_GET_VAR(__GLEW_ARB_separate_shader_objects) + +#endif /* GL_ARB_separate_shader_objects */ + +/* ----------------------- GL_ARB_shader_bit_encoding ---------------------- */ + +#ifndef GL_ARB_shader_bit_encoding +#define GL_ARB_shader_bit_encoding 1 + +#define GLEW_ARB_shader_bit_encoding GLEW_GET_VAR(__GLEW_ARB_shader_bit_encoding) + +#endif /* GL_ARB_shader_bit_encoding */ + +/* ------------------------- GL_ARB_shader_objects ------------------------- */ + +#ifndef GL_ARB_shader_objects +#define GL_ARB_shader_objects 1 + +#define GL_PROGRAM_OBJECT_ARB 0x8B40 +#define GL_SHADER_OBJECT_ARB 0x8B48 +#define GL_OBJECT_TYPE_ARB 0x8B4E +#define GL_OBJECT_SUBTYPE_ARB 0x8B4F +#define GL_FLOAT_VEC2_ARB 0x8B50 +#define GL_FLOAT_VEC3_ARB 0x8B51 +#define GL_FLOAT_VEC4_ARB 0x8B52 +#define GL_INT_VEC2_ARB 0x8B53 +#define GL_INT_VEC3_ARB 0x8B54 +#define GL_INT_VEC4_ARB 0x8B55 +#define GL_BOOL_ARB 0x8B56 +#define GL_BOOL_VEC2_ARB 0x8B57 +#define GL_BOOL_VEC3_ARB 0x8B58 +#define GL_BOOL_VEC4_ARB 0x8B59 +#define GL_FLOAT_MAT2_ARB 0x8B5A +#define GL_FLOAT_MAT3_ARB 0x8B5B +#define GL_FLOAT_MAT4_ARB 0x8B5C +#define GL_SAMPLER_1D_ARB 0x8B5D +#define GL_SAMPLER_2D_ARB 0x8B5E +#define GL_SAMPLER_3D_ARB 0x8B5F +#define GL_SAMPLER_CUBE_ARB 0x8B60 +#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61 +#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62 +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 +#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80 +#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 +#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 +#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83 +#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 +#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85 +#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86 +#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87 +#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88 + +typedef char GLcharARB; +typedef unsigned int GLhandleARB; + +typedef void (GLAPIENTRY * PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj); +typedef void (GLAPIENTRY * PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj); +typedef GLhandleARB (GLAPIENTRY * PFNGLCREATEPROGRAMOBJECTARBPROC) (void); +typedef GLhandleARB (GLAPIENTRY * PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType); +typedef void (GLAPIENTRY * PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj); +typedef void (GLAPIENTRY * PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint *size, GLenum *type, GLcharARB *name); +typedef void (GLAPIENTRY * PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei* count, GLhandleARB *obj); +typedef GLhandleARB (GLAPIENTRY * PFNGLGETHANDLEARBPROC) (GLenum pname); +typedef void (GLAPIENTRY * PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB *infoLog); +typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB *source); +typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB* name); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint* params); +typedef void (GLAPIENTRY * PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj); +typedef void (GLAPIENTRY * PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB ** string, const GLint *length); +typedef void (GLAPIENTRY * PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj); +typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj); + +#define glAttachObjectARB GLEW_GET_FUN(__glewAttachObjectARB) +#define glCompileShaderARB GLEW_GET_FUN(__glewCompileShaderARB) +#define glCreateProgramObjectARB GLEW_GET_FUN(__glewCreateProgramObjectARB) +#define glCreateShaderObjectARB GLEW_GET_FUN(__glewCreateShaderObjectARB) +#define glDeleteObjectARB GLEW_GET_FUN(__glewDeleteObjectARB) +#define glDetachObjectARB GLEW_GET_FUN(__glewDetachObjectARB) +#define glGetActiveUniformARB GLEW_GET_FUN(__glewGetActiveUniformARB) +#define glGetAttachedObjectsARB GLEW_GET_FUN(__glewGetAttachedObjectsARB) +#define glGetHandleARB GLEW_GET_FUN(__glewGetHandleARB) +#define glGetInfoLogARB GLEW_GET_FUN(__glewGetInfoLogARB) +#define glGetObjectParameterfvARB GLEW_GET_FUN(__glewGetObjectParameterfvARB) +#define glGetObjectParameterivARB GLEW_GET_FUN(__glewGetObjectParameterivARB) +#define glGetShaderSourceARB GLEW_GET_FUN(__glewGetShaderSourceARB) +#define glGetUniformLocationARB GLEW_GET_FUN(__glewGetUniformLocationARB) +#define glGetUniformfvARB GLEW_GET_FUN(__glewGetUniformfvARB) +#define glGetUniformivARB GLEW_GET_FUN(__glewGetUniformivARB) +#define glLinkProgramARB GLEW_GET_FUN(__glewLinkProgramARB) +#define glShaderSourceARB GLEW_GET_FUN(__glewShaderSourceARB) +#define glUniform1fARB GLEW_GET_FUN(__glewUniform1fARB) +#define glUniform1fvARB GLEW_GET_FUN(__glewUniform1fvARB) +#define glUniform1iARB GLEW_GET_FUN(__glewUniform1iARB) +#define glUniform1ivARB GLEW_GET_FUN(__glewUniform1ivARB) +#define glUniform2fARB GLEW_GET_FUN(__glewUniform2fARB) +#define glUniform2fvARB GLEW_GET_FUN(__glewUniform2fvARB) +#define glUniform2iARB GLEW_GET_FUN(__glewUniform2iARB) +#define glUniform2ivARB GLEW_GET_FUN(__glewUniform2ivARB) +#define glUniform3fARB GLEW_GET_FUN(__glewUniform3fARB) +#define glUniform3fvARB GLEW_GET_FUN(__glewUniform3fvARB) +#define glUniform3iARB GLEW_GET_FUN(__glewUniform3iARB) +#define glUniform3ivARB GLEW_GET_FUN(__glewUniform3ivARB) +#define glUniform4fARB GLEW_GET_FUN(__glewUniform4fARB) +#define glUniform4fvARB GLEW_GET_FUN(__glewUniform4fvARB) +#define glUniform4iARB GLEW_GET_FUN(__glewUniform4iARB) +#define glUniform4ivARB GLEW_GET_FUN(__glewUniform4ivARB) +#define glUniformMatrix2fvARB GLEW_GET_FUN(__glewUniformMatrix2fvARB) +#define glUniformMatrix3fvARB GLEW_GET_FUN(__glewUniformMatrix3fvARB) +#define glUniformMatrix4fvARB GLEW_GET_FUN(__glewUniformMatrix4fvARB) +#define glUseProgramObjectARB GLEW_GET_FUN(__glewUseProgramObjectARB) +#define glValidateProgramARB GLEW_GET_FUN(__glewValidateProgramARB) + +#define GLEW_ARB_shader_objects GLEW_GET_VAR(__GLEW_ARB_shader_objects) + +#endif /* GL_ARB_shader_objects */ + +/* ------------------------ GL_ARB_shader_precision ------------------------ */ + +#ifndef GL_ARB_shader_precision +#define GL_ARB_shader_precision 1 + +#define GLEW_ARB_shader_precision GLEW_GET_VAR(__GLEW_ARB_shader_precision) + +#endif /* GL_ARB_shader_precision */ + +/* ---------------------- GL_ARB_shader_stencil_export --------------------- */ + +#ifndef GL_ARB_shader_stencil_export +#define GL_ARB_shader_stencil_export 1 + +#define GLEW_ARB_shader_stencil_export GLEW_GET_VAR(__GLEW_ARB_shader_stencil_export) + +#endif /* GL_ARB_shader_stencil_export */ + +/* ------------------------ GL_ARB_shader_subroutine ----------------------- */ + +#ifndef GL_ARB_shader_subroutine +#define GL_ARB_shader_subroutine 1 + +#define GL_ACTIVE_SUBROUTINES 0x8DE5 +#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6 +#define GL_MAX_SUBROUTINES 0x8DE7 +#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8 +#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47 +#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48 +#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49 +#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A +#define GL_COMPATIBLE_SUBROUTINES 0x8E4B + +typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, char *name); +typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, char *name); +typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint* values); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint* values); +typedef GLuint (GLAPIENTRY * PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const char* name); +typedef GLint (GLAPIENTRY * PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const char* name); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint* params); +typedef void (GLAPIENTRY * PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint* indices); + +#define glGetActiveSubroutineName GLEW_GET_FUN(__glewGetActiveSubroutineName) +#define glGetActiveSubroutineUniformName GLEW_GET_FUN(__glewGetActiveSubroutineUniformName) +#define glGetActiveSubroutineUniformiv GLEW_GET_FUN(__glewGetActiveSubroutineUniformiv) +#define glGetProgramStageiv GLEW_GET_FUN(__glewGetProgramStageiv) +#define glGetSubroutineIndex GLEW_GET_FUN(__glewGetSubroutineIndex) +#define glGetSubroutineUniformLocation GLEW_GET_FUN(__glewGetSubroutineUniformLocation) +#define glGetUniformSubroutineuiv GLEW_GET_FUN(__glewGetUniformSubroutineuiv) +#define glUniformSubroutinesuiv GLEW_GET_FUN(__glewUniformSubroutinesuiv) + +#define GLEW_ARB_shader_subroutine GLEW_GET_VAR(__GLEW_ARB_shader_subroutine) + +#endif /* GL_ARB_shader_subroutine */ + +/* ----------------------- GL_ARB_shader_texture_lod ----------------------- */ + +#ifndef GL_ARB_shader_texture_lod +#define GL_ARB_shader_texture_lod 1 + +#define GLEW_ARB_shader_texture_lod GLEW_GET_VAR(__GLEW_ARB_shader_texture_lod) + +#endif /* GL_ARB_shader_texture_lod */ + +/* ---------------------- GL_ARB_shading_language_100 ---------------------- */ + +#ifndef GL_ARB_shading_language_100 +#define GL_ARB_shading_language_100 1 + +#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C + +#define GLEW_ARB_shading_language_100 GLEW_GET_VAR(__GLEW_ARB_shading_language_100) + +#endif /* GL_ARB_shading_language_100 */ + +/* -------------------- GL_ARB_shading_language_include -------------------- */ + +#ifndef GL_ARB_shading_language_include +#define GL_ARB_shading_language_include 1 + +#define GL_SHADER_INCLUDE_ARB 0x8DAE +#define GL_NAMED_STRING_LENGTH_ARB 0x8DE9 +#define GL_NAMED_STRING_TYPE_ARB 0x8DEA + +typedef void (GLAPIENTRY * PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const char ** path, const GLint *length); +typedef void (GLAPIENTRY * PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const char* name); +typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const char* name, GLsizei bufSize, GLint *stringlen, char *string); +typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const char* name, GLenum pname, GLint *params); +typedef GLboolean (GLAPIENTRY * PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const char* name); +typedef void (GLAPIENTRY * PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const char* name, GLint stringlen, const char *string); + +#define glCompileShaderIncludeARB GLEW_GET_FUN(__glewCompileShaderIncludeARB) +#define glDeleteNamedStringARB GLEW_GET_FUN(__glewDeleteNamedStringARB) +#define glGetNamedStringARB GLEW_GET_FUN(__glewGetNamedStringARB) +#define glGetNamedStringivARB GLEW_GET_FUN(__glewGetNamedStringivARB) +#define glIsNamedStringARB GLEW_GET_FUN(__glewIsNamedStringARB) +#define glNamedStringARB GLEW_GET_FUN(__glewNamedStringARB) + +#define GLEW_ARB_shading_language_include GLEW_GET_VAR(__GLEW_ARB_shading_language_include) + +#endif /* GL_ARB_shading_language_include */ + +/* ----------------------------- GL_ARB_shadow ----------------------------- */ + +#ifndef GL_ARB_shadow +#define GL_ARB_shadow 1 + +#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C +#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D +#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E + +#define GLEW_ARB_shadow GLEW_GET_VAR(__GLEW_ARB_shadow) + +#endif /* GL_ARB_shadow */ + +/* ------------------------- GL_ARB_shadow_ambient ------------------------- */ + +#ifndef GL_ARB_shadow_ambient +#define GL_ARB_shadow_ambient 1 + +#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF + +#define GLEW_ARB_shadow_ambient GLEW_GET_VAR(__GLEW_ARB_shadow_ambient) + +#endif /* GL_ARB_shadow_ambient */ + +/* ------------------------------ GL_ARB_sync ------------------------------ */ + +#ifndef GL_ARB_sync +#define GL_ARB_sync 1 + +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF + +typedef GLenum (GLAPIENTRY * PFNGLCLIENTWAITSYNCPROC) (GLsync GLsync,GLbitfield flags,GLuint64 timeout); +typedef void (GLAPIENTRY * PFNGLDELETESYNCPROC) (GLsync GLsync); +typedef GLsync (GLAPIENTRY * PFNGLFENCESYNCPROC) (GLenum condition,GLbitfield flags); +typedef void (GLAPIENTRY * PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64* params); +typedef void (GLAPIENTRY * PFNGLGETSYNCIVPROC) (GLsync GLsync,GLenum pname,GLsizei bufSize,GLsizei* length, GLint *values); +typedef GLboolean (GLAPIENTRY * PFNGLISSYNCPROC) (GLsync GLsync); +typedef void (GLAPIENTRY * PFNGLWAITSYNCPROC) (GLsync GLsync,GLbitfield flags,GLuint64 timeout); + +#define glClientWaitSync GLEW_GET_FUN(__glewClientWaitSync) +#define glDeleteSync GLEW_GET_FUN(__glewDeleteSync) +#define glFenceSync GLEW_GET_FUN(__glewFenceSync) +#define glGetInteger64v GLEW_GET_FUN(__glewGetInteger64v) +#define glGetSynciv GLEW_GET_FUN(__glewGetSynciv) +#define glIsSync GLEW_GET_FUN(__glewIsSync) +#define glWaitSync GLEW_GET_FUN(__glewWaitSync) + +#define GLEW_ARB_sync GLEW_GET_VAR(__GLEW_ARB_sync) + +#endif /* GL_ARB_sync */ + +/* ----------------------- GL_ARB_tessellation_shader ---------------------- */ + +#ifndef GL_ARB_tessellation_shader +#define GL_ARB_tessellation_shader 1 + +#define GL_PATCHES 0xE +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1 +#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C +#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D +#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E +#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F +#define GL_PATCH_VERTICES 0x8E72 +#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73 +#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74 +#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75 +#define GL_TESS_GEN_MODE 0x8E76 +#define GL_TESS_GEN_SPACING 0x8E77 +#define GL_TESS_GEN_VERTEX_ORDER 0x8E78 +#define GL_TESS_GEN_POINT_MODE 0x8E79 +#define GL_ISOLINES 0x8E7A +#define GL_FRACTIONAL_ODD 0x8E7B +#define GL_FRACTIONAL_EVEN 0x8E7C +#define GL_MAX_PATCH_VERTICES 0x8E7D +#define GL_MAX_TESS_GEN_LEVEL 0x8E7E +#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F +#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80 +#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81 +#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82 +#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83 +#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84 +#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85 +#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86 +#define GL_TESS_EVALUATION_SHADER 0x8E87 +#define GL_TESS_CONTROL_SHADER 0x8E88 +#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89 +#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A + +typedef void (GLAPIENTRY * PFNGLPATCHPARAMETERFVPROC) (GLenum pname, const GLfloat* values); +typedef void (GLAPIENTRY * PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value); + +#define glPatchParameterfv GLEW_GET_FUN(__glewPatchParameterfv) +#define glPatchParameteri GLEW_GET_FUN(__glewPatchParameteri) + +#define GLEW_ARB_tessellation_shader GLEW_GET_VAR(__GLEW_ARB_tessellation_shader) + +#endif /* GL_ARB_tessellation_shader */ + +/* ---------------------- GL_ARB_texture_border_clamp ---------------------- */ + +#ifndef GL_ARB_texture_border_clamp +#define GL_ARB_texture_border_clamp 1 + +#define GL_CLAMP_TO_BORDER_ARB 0x812D + +#define GLEW_ARB_texture_border_clamp GLEW_GET_VAR(__GLEW_ARB_texture_border_clamp) + +#endif /* GL_ARB_texture_border_clamp */ + +/* ---------------------- GL_ARB_texture_buffer_object --------------------- */ + +#ifndef GL_ARB_texture_buffer_object +#define GL_ARB_texture_buffer_object 1 + +#define GL_TEXTURE_BUFFER_ARB 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E + +typedef void (GLAPIENTRY * PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer); + +#define glTexBufferARB GLEW_GET_FUN(__glewTexBufferARB) + +#define GLEW_ARB_texture_buffer_object GLEW_GET_VAR(__GLEW_ARB_texture_buffer_object) + +#endif /* GL_ARB_texture_buffer_object */ + +/* ------------------- GL_ARB_texture_buffer_object_rgb32 ------------------ */ + +#ifndef GL_ARB_texture_buffer_object_rgb32 +#define GL_ARB_texture_buffer_object_rgb32 1 + +#define GLEW_ARB_texture_buffer_object_rgb32 GLEW_GET_VAR(__GLEW_ARB_texture_buffer_object_rgb32) + +#endif /* GL_ARB_texture_buffer_object_rgb32 */ + +/* ----------------------- GL_ARB_texture_compression ---------------------- */ + +#ifndef GL_ARB_texture_compression +#define GL_ARB_texture_compression 1 + +#define GL_COMPRESSED_ALPHA_ARB 0x84E9 +#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB +#define GL_COMPRESSED_INTENSITY_ARB 0x84EC +#define GL_COMPRESSED_RGB_ARB 0x84ED +#define GL_COMPRESSED_RGBA_ARB 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 +#define GL_TEXTURE_COMPRESSED_ARB 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 + +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, void* img); + +#define glCompressedTexImage1DARB GLEW_GET_FUN(__glewCompressedTexImage1DARB) +#define glCompressedTexImage2DARB GLEW_GET_FUN(__glewCompressedTexImage2DARB) +#define glCompressedTexImage3DARB GLEW_GET_FUN(__glewCompressedTexImage3DARB) +#define glCompressedTexSubImage1DARB GLEW_GET_FUN(__glewCompressedTexSubImage1DARB) +#define glCompressedTexSubImage2DARB GLEW_GET_FUN(__glewCompressedTexSubImage2DARB) +#define glCompressedTexSubImage3DARB GLEW_GET_FUN(__glewCompressedTexSubImage3DARB) +#define glGetCompressedTexImageARB GLEW_GET_FUN(__glewGetCompressedTexImageARB) + +#define GLEW_ARB_texture_compression GLEW_GET_VAR(__GLEW_ARB_texture_compression) + +#endif /* GL_ARB_texture_compression */ + +/* -------------------- GL_ARB_texture_compression_bptc -------------------- */ + +#ifndef GL_ARB_texture_compression_bptc +#define GL_ARB_texture_compression_bptc 1 + +#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C +#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D +#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E +#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F + +#define GLEW_ARB_texture_compression_bptc GLEW_GET_VAR(__GLEW_ARB_texture_compression_bptc) + +#endif /* GL_ARB_texture_compression_bptc */ + +/* -------------------- GL_ARB_texture_compression_rgtc -------------------- */ + +#ifndef GL_ARB_texture_compression_rgtc +#define GL_ARB_texture_compression_rgtc 1 + +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE + +#define GLEW_ARB_texture_compression_rgtc GLEW_GET_VAR(__GLEW_ARB_texture_compression_rgtc) + +#endif /* GL_ARB_texture_compression_rgtc */ + +/* ------------------------ GL_ARB_texture_cube_map ------------------------ */ + +#ifndef GL_ARB_texture_cube_map +#define GL_ARB_texture_cube_map 1 + +#define GL_NORMAL_MAP_ARB 0x8511 +#define GL_REFLECTION_MAP_ARB 0x8512 +#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C + +#define GLEW_ARB_texture_cube_map GLEW_GET_VAR(__GLEW_ARB_texture_cube_map) + +#endif /* GL_ARB_texture_cube_map */ + +/* --------------------- GL_ARB_texture_cube_map_array --------------------- */ + +#ifndef GL_ARB_texture_cube_map_array +#define GL_ARB_texture_cube_map_array 1 + +#define GL_TEXTURE_CUBE_MAP_ARRAY_ARB 0x9009 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB 0x900A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB 0x900B +#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F + +#define GLEW_ARB_texture_cube_map_array GLEW_GET_VAR(__GLEW_ARB_texture_cube_map_array) + +#endif /* GL_ARB_texture_cube_map_array */ + +/* ------------------------- GL_ARB_texture_env_add ------------------------ */ + +#ifndef GL_ARB_texture_env_add +#define GL_ARB_texture_env_add 1 + +#define GLEW_ARB_texture_env_add GLEW_GET_VAR(__GLEW_ARB_texture_env_add) + +#endif /* GL_ARB_texture_env_add */ + +/* ----------------------- GL_ARB_texture_env_combine ---------------------- */ + +#ifndef GL_ARB_texture_env_combine +#define GL_ARB_texture_env_combine 1 + +#define GL_SUBTRACT_ARB 0x84E7 +#define GL_COMBINE_ARB 0x8570 +#define GL_COMBINE_RGB_ARB 0x8571 +#define GL_COMBINE_ALPHA_ARB 0x8572 +#define GL_RGB_SCALE_ARB 0x8573 +#define GL_ADD_SIGNED_ARB 0x8574 +#define GL_INTERPOLATE_ARB 0x8575 +#define GL_CONSTANT_ARB 0x8576 +#define GL_PRIMARY_COLOR_ARB 0x8577 +#define GL_PREVIOUS_ARB 0x8578 +#define GL_SOURCE0_RGB_ARB 0x8580 +#define GL_SOURCE1_RGB_ARB 0x8581 +#define GL_SOURCE2_RGB_ARB 0x8582 +#define GL_SOURCE0_ALPHA_ARB 0x8588 +#define GL_SOURCE1_ALPHA_ARB 0x8589 +#define GL_SOURCE2_ALPHA_ARB 0x858A +#define GL_OPERAND0_RGB_ARB 0x8590 +#define GL_OPERAND1_RGB_ARB 0x8591 +#define GL_OPERAND2_RGB_ARB 0x8592 +#define GL_OPERAND0_ALPHA_ARB 0x8598 +#define GL_OPERAND1_ALPHA_ARB 0x8599 +#define GL_OPERAND2_ALPHA_ARB 0x859A + +#define GLEW_ARB_texture_env_combine GLEW_GET_VAR(__GLEW_ARB_texture_env_combine) + +#endif /* GL_ARB_texture_env_combine */ + +/* ---------------------- GL_ARB_texture_env_crossbar ---------------------- */ + +#ifndef GL_ARB_texture_env_crossbar +#define GL_ARB_texture_env_crossbar 1 + +#define GLEW_ARB_texture_env_crossbar GLEW_GET_VAR(__GLEW_ARB_texture_env_crossbar) + +#endif /* GL_ARB_texture_env_crossbar */ + +/* ------------------------ GL_ARB_texture_env_dot3 ------------------------ */ + +#ifndef GL_ARB_texture_env_dot3 +#define GL_ARB_texture_env_dot3 1 + +#define GL_DOT3_RGB_ARB 0x86AE +#define GL_DOT3_RGBA_ARB 0x86AF + +#define GLEW_ARB_texture_env_dot3 GLEW_GET_VAR(__GLEW_ARB_texture_env_dot3) + +#endif /* GL_ARB_texture_env_dot3 */ + +/* -------------------------- GL_ARB_texture_float ------------------------- */ + +#ifndef GL_ARB_texture_float +#define GL_ARB_texture_float 1 + +#define GL_RGBA32F_ARB 0x8814 +#define GL_RGB32F_ARB 0x8815 +#define GL_ALPHA32F_ARB 0x8816 +#define GL_INTENSITY32F_ARB 0x8817 +#define GL_LUMINANCE32F_ARB 0x8818 +#define GL_LUMINANCE_ALPHA32F_ARB 0x8819 +#define GL_RGBA16F_ARB 0x881A +#define GL_RGB16F_ARB 0x881B +#define GL_ALPHA16F_ARB 0x881C +#define GL_INTENSITY16F_ARB 0x881D +#define GL_LUMINANCE16F_ARB 0x881E +#define GL_LUMINANCE_ALPHA16F_ARB 0x881F +#define GL_TEXTURE_RED_TYPE_ARB 0x8C10 +#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11 +#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13 +#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14 +#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15 +#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16 +#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17 + +#define GLEW_ARB_texture_float GLEW_GET_VAR(__GLEW_ARB_texture_float) + +#endif /* GL_ARB_texture_float */ + +/* ------------------------- GL_ARB_texture_gather ------------------------- */ + +#ifndef GL_ARB_texture_gather +#define GL_ARB_texture_gather 1 + +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5F +#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB 0x8F9F + +#define GLEW_ARB_texture_gather GLEW_GET_VAR(__GLEW_ARB_texture_gather) + +#endif /* GL_ARB_texture_gather */ + +/* --------------------- GL_ARB_texture_mirrored_repeat -------------------- */ + +#ifndef GL_ARB_texture_mirrored_repeat +#define GL_ARB_texture_mirrored_repeat 1 + +#define GL_MIRRORED_REPEAT_ARB 0x8370 + +#define GLEW_ARB_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_ARB_texture_mirrored_repeat) + +#endif /* GL_ARB_texture_mirrored_repeat */ + +/* ----------------------- GL_ARB_texture_multisample ---------------------- */ + +#ifndef GL_ARB_texture_multisample +#define GL_ARB_texture_multisample 1 + +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_INTEGER_SAMPLES 0x9110 + +typedef void (GLAPIENTRY * PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat* val); +typedef void (GLAPIENTRY * PFNGLSAMPLEMASKIPROC) (GLuint index, GLbitfield mask); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); + +#define glGetMultisamplefv GLEW_GET_FUN(__glewGetMultisamplefv) +#define glSampleMaski GLEW_GET_FUN(__glewSampleMaski) +#define glTexImage2DMultisample GLEW_GET_FUN(__glewTexImage2DMultisample) +#define glTexImage3DMultisample GLEW_GET_FUN(__glewTexImage3DMultisample) + +#define GLEW_ARB_texture_multisample GLEW_GET_VAR(__GLEW_ARB_texture_multisample) + +#endif /* GL_ARB_texture_multisample */ + +/* -------------------- GL_ARB_texture_non_power_of_two -------------------- */ + +#ifndef GL_ARB_texture_non_power_of_two +#define GL_ARB_texture_non_power_of_two 1 + +#define GLEW_ARB_texture_non_power_of_two GLEW_GET_VAR(__GLEW_ARB_texture_non_power_of_two) + +#endif /* GL_ARB_texture_non_power_of_two */ + +/* ------------------------ GL_ARB_texture_query_lod ----------------------- */ + +#ifndef GL_ARB_texture_query_lod +#define GL_ARB_texture_query_lod 1 + +#define GLEW_ARB_texture_query_lod GLEW_GET_VAR(__GLEW_ARB_texture_query_lod) + +#endif /* GL_ARB_texture_query_lod */ + +/* ------------------------ GL_ARB_texture_rectangle ----------------------- */ + +#ifndef GL_ARB_texture_rectangle +#define GL_ARB_texture_rectangle 1 + +#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 + +#define GLEW_ARB_texture_rectangle GLEW_GET_VAR(__GLEW_ARB_texture_rectangle) + +#endif /* GL_ARB_texture_rectangle */ + +/* --------------------------- GL_ARB_texture_rg --------------------------- */ + +#ifndef GL_ARB_texture_rg +#define GL_ARB_texture_rg 1 + +#define GL_RED 0x1903 +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RG 0x8226 +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_R16 0x822A +#define GL_RG8 0x822B +#define GL_RG16 0x822C +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C + +#define GLEW_ARB_texture_rg GLEW_GET_VAR(__GLEW_ARB_texture_rg) + +#endif /* GL_ARB_texture_rg */ + +/* ----------------------- GL_ARB_texture_rgb10_a2ui ----------------------- */ + +#ifndef GL_ARB_texture_rgb10_a2ui +#define GL_ARB_texture_rgb10_a2ui 1 + +#define GL_RGB10_A2UI 0x906F + +#define GLEW_ARB_texture_rgb10_a2ui GLEW_GET_VAR(__GLEW_ARB_texture_rgb10_a2ui) + +#endif /* GL_ARB_texture_rgb10_a2ui */ + +/* ------------------------- GL_ARB_texture_swizzle ------------------------ */ + +#ifndef GL_ARB_texture_swizzle +#define GL_ARB_texture_swizzle 1 + +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 + +#define GLEW_ARB_texture_swizzle GLEW_GET_VAR(__GLEW_ARB_texture_swizzle) + +#endif /* GL_ARB_texture_swizzle */ + +/* --------------------------- GL_ARB_timer_query -------------------------- */ + +#ifndef GL_ARB_timer_query +#define GL_ARB_timer_query 1 + +#define GL_TIME_ELAPSED 0x88BF +#define GL_TIMESTAMP 0x8E28 + +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64* params); +typedef void (GLAPIENTRY * PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target); + +#define glGetQueryObjecti64v GLEW_GET_FUN(__glewGetQueryObjecti64v) +#define glGetQueryObjectui64v GLEW_GET_FUN(__glewGetQueryObjectui64v) +#define glQueryCounter GLEW_GET_FUN(__glewQueryCounter) + +#define GLEW_ARB_timer_query GLEW_GET_VAR(__GLEW_ARB_timer_query) + +#endif /* GL_ARB_timer_query */ + +/* ----------------------- GL_ARB_transform_feedback2 ---------------------- */ + +#ifndef GL_ARB_transform_feedback2 +#define GL_ARB_transform_feedback2 1 + +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 + +typedef void (GLAPIENTRY * PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKPROC) (GLenum mode, GLuint id); +typedef void (GLAPIENTRY * PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint* ids); +typedef GLboolean (GLAPIENTRY * PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLPAUSETRANSFORMFEEDBACKPROC) (void); +typedef void (GLAPIENTRY * PFNGLRESUMETRANSFORMFEEDBACKPROC) (void); + +#define glBindTransformFeedback GLEW_GET_FUN(__glewBindTransformFeedback) +#define glDeleteTransformFeedbacks GLEW_GET_FUN(__glewDeleteTransformFeedbacks) +#define glDrawTransformFeedback GLEW_GET_FUN(__glewDrawTransformFeedback) +#define glGenTransformFeedbacks GLEW_GET_FUN(__glewGenTransformFeedbacks) +#define glIsTransformFeedback GLEW_GET_FUN(__glewIsTransformFeedback) +#define glPauseTransformFeedback GLEW_GET_FUN(__glewPauseTransformFeedback) +#define glResumeTransformFeedback GLEW_GET_FUN(__glewResumeTransformFeedback) + +#define GLEW_ARB_transform_feedback2 GLEW_GET_VAR(__GLEW_ARB_transform_feedback2) + +#endif /* GL_ARB_transform_feedback2 */ + +/* ----------------------- GL_ARB_transform_feedback3 ---------------------- */ + +#ifndef GL_ARB_transform_feedback3 +#define GL_ARB_transform_feedback3 1 + +#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70 +#define GL_MAX_VERTEX_STREAMS 0x8E71 + +typedef void (GLAPIENTRY * PFNGLBEGINQUERYINDEXEDPROC) (GLenum target, GLuint index, GLuint id); +typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC) (GLenum mode, GLuint id, GLuint stream); +typedef void (GLAPIENTRY * PFNGLENDQUERYINDEXEDPROC) (GLenum target, GLuint index); +typedef void (GLAPIENTRY * PFNGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params); + +#define glBeginQueryIndexed GLEW_GET_FUN(__glewBeginQueryIndexed) +#define glDrawTransformFeedbackStream GLEW_GET_FUN(__glewDrawTransformFeedbackStream) +#define glEndQueryIndexed GLEW_GET_FUN(__glewEndQueryIndexed) +#define glGetQueryIndexediv GLEW_GET_FUN(__glewGetQueryIndexediv) + +#define GLEW_ARB_transform_feedback3 GLEW_GET_VAR(__GLEW_ARB_transform_feedback3) + +#endif /* GL_ARB_transform_feedback3 */ + +/* ------------------------ GL_ARB_transpose_matrix ------------------------ */ + +#ifndef GL_ARB_transpose_matrix +#define GL_ARB_transpose_matrix 1 + +#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6 + +typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDARBPROC) (GLdouble m[16]); +typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFARBPROC) (GLfloat m[16]); +typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDARBPROC) (GLdouble m[16]); +typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFARBPROC) (GLfloat m[16]); + +#define glLoadTransposeMatrixdARB GLEW_GET_FUN(__glewLoadTransposeMatrixdARB) +#define glLoadTransposeMatrixfARB GLEW_GET_FUN(__glewLoadTransposeMatrixfARB) +#define glMultTransposeMatrixdARB GLEW_GET_FUN(__glewMultTransposeMatrixdARB) +#define glMultTransposeMatrixfARB GLEW_GET_FUN(__glewMultTransposeMatrixfARB) + +#define GLEW_ARB_transpose_matrix GLEW_GET_VAR(__GLEW_ARB_transpose_matrix) + +#endif /* GL_ARB_transpose_matrix */ + +/* ---------------------- GL_ARB_uniform_buffer_object --------------------- */ + +#ifndef GL_ARB_uniform_buffer_object +#define GL_ARB_uniform_buffer_object 1 + +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFF + +typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, char* uniformBlockName); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length, char* uniformName); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint* data); +typedef GLuint (GLAPIENTRY * PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const char* uniformBlockName); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const char** uniformNames, GLuint* uniformIndices); +typedef void (GLAPIENTRY * PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); + +#define glBindBufferBase GLEW_GET_FUN(__glewBindBufferBase) +#define glBindBufferRange GLEW_GET_FUN(__glewBindBufferRange) +#define glGetActiveUniformBlockName GLEW_GET_FUN(__glewGetActiveUniformBlockName) +#define glGetActiveUniformBlockiv GLEW_GET_FUN(__glewGetActiveUniformBlockiv) +#define glGetActiveUniformName GLEW_GET_FUN(__glewGetActiveUniformName) +#define glGetActiveUniformsiv GLEW_GET_FUN(__glewGetActiveUniformsiv) +#define glGetIntegeri_v GLEW_GET_FUN(__glewGetIntegeri_v) +#define glGetUniformBlockIndex GLEW_GET_FUN(__glewGetUniformBlockIndex) +#define glGetUniformIndices GLEW_GET_FUN(__glewGetUniformIndices) +#define glUniformBlockBinding GLEW_GET_FUN(__glewUniformBlockBinding) + +#define GLEW_ARB_uniform_buffer_object GLEW_GET_VAR(__GLEW_ARB_uniform_buffer_object) + +#endif /* GL_ARB_uniform_buffer_object */ + +/* ------------------------ GL_ARB_vertex_array_bgra ----------------------- */ + +#ifndef GL_ARB_vertex_array_bgra +#define GL_ARB_vertex_array_bgra 1 + +#define GL_BGRA 0x80E1 + +#define GLEW_ARB_vertex_array_bgra GLEW_GET_VAR(__GLEW_ARB_vertex_array_bgra) + +#endif /* GL_ARB_vertex_array_bgra */ + +/* ----------------------- GL_ARB_vertex_array_object ---------------------- */ + +#ifndef GL_ARB_vertex_array_object +#define GL_ARB_vertex_array_object 1 + +#define GL_VERTEX_ARRAY_BINDING 0x85B5 + +typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYPROC) (GLuint array); +typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays); +typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays); +typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYPROC) (GLuint array); + +#define glBindVertexArray GLEW_GET_FUN(__glewBindVertexArray) +#define glDeleteVertexArrays GLEW_GET_FUN(__glewDeleteVertexArrays) +#define glGenVertexArrays GLEW_GET_FUN(__glewGenVertexArrays) +#define glIsVertexArray GLEW_GET_FUN(__glewIsVertexArray) + +#define GLEW_ARB_vertex_array_object GLEW_GET_VAR(__GLEW_ARB_vertex_array_object) + +#endif /* GL_ARB_vertex_array_object */ + +/* ----------------------- GL_ARB_vertex_attrib_64bit ---------------------- */ + +#ifndef GL_ARB_vertex_attrib_64bit +#define GL_ARB_vertex_attrib_64bit 1 + +#define GL_DOUBLE_MAT2 0x8F46 +#define GL_DOUBLE_MAT3 0x8F47 +#define GL_DOUBLE_MAT4 0x8F48 +#define GL_DOUBLE_VEC2 0x8FFC +#define GL_DOUBLE_VEC3 0x8FFD +#define GL_DOUBLE_VEC4 0x8FFE + +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); + +#define glGetVertexAttribLdv GLEW_GET_FUN(__glewGetVertexAttribLdv) +#define glVertexAttribL1d GLEW_GET_FUN(__glewVertexAttribL1d) +#define glVertexAttribL1dv GLEW_GET_FUN(__glewVertexAttribL1dv) +#define glVertexAttribL2d GLEW_GET_FUN(__glewVertexAttribL2d) +#define glVertexAttribL2dv GLEW_GET_FUN(__glewVertexAttribL2dv) +#define glVertexAttribL3d GLEW_GET_FUN(__glewVertexAttribL3d) +#define glVertexAttribL3dv GLEW_GET_FUN(__glewVertexAttribL3dv) +#define glVertexAttribL4d GLEW_GET_FUN(__glewVertexAttribL4d) +#define glVertexAttribL4dv GLEW_GET_FUN(__glewVertexAttribL4dv) +#define glVertexAttribLPointer GLEW_GET_FUN(__glewVertexAttribLPointer) + +#define GLEW_ARB_vertex_attrib_64bit GLEW_GET_VAR(__GLEW_ARB_vertex_attrib_64bit) + +#endif /* GL_ARB_vertex_attrib_64bit */ + +/* -------------------------- GL_ARB_vertex_blend -------------------------- */ + +#ifndef GL_ARB_vertex_blend +#define GL_ARB_vertex_blend 1 + +#define GL_MODELVIEW0_ARB 0x1700 +#define GL_MODELVIEW1_ARB 0x850A +#define GL_MAX_VERTEX_UNITS_ARB 0x86A4 +#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5 +#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6 +#define GL_VERTEX_BLEND_ARB 0x86A7 +#define GL_CURRENT_WEIGHT_ARB 0x86A8 +#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9 +#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA +#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB +#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC +#define GL_WEIGHT_ARRAY_ARB 0x86AD +#define GL_MODELVIEW2_ARB 0x8722 +#define GL_MODELVIEW3_ARB 0x8723 +#define GL_MODELVIEW4_ARB 0x8724 +#define GL_MODELVIEW5_ARB 0x8725 +#define GL_MODELVIEW6_ARB 0x8726 +#define GL_MODELVIEW7_ARB 0x8727 +#define GL_MODELVIEW8_ARB 0x8728 +#define GL_MODELVIEW9_ARB 0x8729 +#define GL_MODELVIEW10_ARB 0x872A +#define GL_MODELVIEW11_ARB 0x872B +#define GL_MODELVIEW12_ARB 0x872C +#define GL_MODELVIEW13_ARB 0x872D +#define GL_MODELVIEW14_ARB 0x872E +#define GL_MODELVIEW15_ARB 0x872F +#define GL_MODELVIEW16_ARB 0x8730 +#define GL_MODELVIEW17_ARB 0x8731 +#define GL_MODELVIEW18_ARB 0x8732 +#define GL_MODELVIEW19_ARB 0x8733 +#define GL_MODELVIEW20_ARB 0x8734 +#define GL_MODELVIEW21_ARB 0x8735 +#define GL_MODELVIEW22_ARB 0x8736 +#define GL_MODELVIEW23_ARB 0x8737 +#define GL_MODELVIEW24_ARB 0x8738 +#define GL_MODELVIEW25_ARB 0x8739 +#define GL_MODELVIEW26_ARB 0x873A +#define GL_MODELVIEW27_ARB 0x873B +#define GL_MODELVIEW28_ARB 0x873C +#define GL_MODELVIEW29_ARB 0x873D +#define GL_MODELVIEW30_ARB 0x873E +#define GL_MODELVIEW31_ARB 0x873F + +typedef void (GLAPIENTRY * PFNGLVERTEXBLENDARBPROC) (GLint count); +typedef void (GLAPIENTRY * PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLWEIGHTBVARBPROC) (GLint size, GLbyte *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTDVARBPROC) (GLint size, GLdouble *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTFVARBPROC) (GLint size, GLfloat *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTIVARBPROC) (GLint size, GLint *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTSVARBPROC) (GLint size, GLshort *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTUBVARBPROC) (GLint size, GLubyte *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTUIVARBPROC) (GLint size, GLuint *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTUSVARBPROC) (GLint size, GLushort *weights); + +#define glVertexBlendARB GLEW_GET_FUN(__glewVertexBlendARB) +#define glWeightPointerARB GLEW_GET_FUN(__glewWeightPointerARB) +#define glWeightbvARB GLEW_GET_FUN(__glewWeightbvARB) +#define glWeightdvARB GLEW_GET_FUN(__glewWeightdvARB) +#define glWeightfvARB GLEW_GET_FUN(__glewWeightfvARB) +#define glWeightivARB GLEW_GET_FUN(__glewWeightivARB) +#define glWeightsvARB GLEW_GET_FUN(__glewWeightsvARB) +#define glWeightubvARB GLEW_GET_FUN(__glewWeightubvARB) +#define glWeightuivARB GLEW_GET_FUN(__glewWeightuivARB) +#define glWeightusvARB GLEW_GET_FUN(__glewWeightusvARB) + +#define GLEW_ARB_vertex_blend GLEW_GET_VAR(__GLEW_ARB_vertex_blend) + +#endif /* GL_ARB_vertex_blend */ + +/* ---------------------- GL_ARB_vertex_buffer_object ---------------------- */ + +#ifndef GL_ARB_vertex_buffer_object +#define GL_ARB_vertex_buffer_object 1 + +#define GL_BUFFER_SIZE_ARB 0x8764 +#define GL_BUFFER_USAGE_ARB 0x8765 +#define GL_ARRAY_BUFFER_ARB 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 +#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F +#define GL_READ_ONLY_ARB 0x88B8 +#define GL_WRITE_ONLY_ARB 0x88B9 +#define GL_READ_WRITE_ARB 0x88BA +#define GL_BUFFER_ACCESS_ARB 0x88BB +#define GL_BUFFER_MAPPED_ARB 0x88BC +#define GL_BUFFER_MAP_POINTER_ARB 0x88BD +#define GL_STREAM_DRAW_ARB 0x88E0 +#define GL_STREAM_READ_ARB 0x88E1 +#define GL_STREAM_COPY_ARB 0x88E2 +#define GL_STATIC_DRAW_ARB 0x88E4 +#define GL_STATIC_READ_ARB 0x88E5 +#define GL_STATIC_COPY_ARB 0x88E6 +#define GL_DYNAMIC_DRAW_ARB 0x88E8 +#define GL_DYNAMIC_READ_ARB 0x88E9 +#define GL_DYNAMIC_COPY_ARB 0x88EA + +typedef ptrdiff_t GLintptrARB; +typedef ptrdiff_t GLsizeiptrARB; + +typedef void (GLAPIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid* data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid* data); +typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid** params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid* data); +typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERARBPROC) (GLuint buffer); +typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access); +typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERARBPROC) (GLenum target); + +#define glBindBufferARB GLEW_GET_FUN(__glewBindBufferARB) +#define glBufferDataARB GLEW_GET_FUN(__glewBufferDataARB) +#define glBufferSubDataARB GLEW_GET_FUN(__glewBufferSubDataARB) +#define glDeleteBuffersARB GLEW_GET_FUN(__glewDeleteBuffersARB) +#define glGenBuffersARB GLEW_GET_FUN(__glewGenBuffersARB) +#define glGetBufferParameterivARB GLEW_GET_FUN(__glewGetBufferParameterivARB) +#define glGetBufferPointervARB GLEW_GET_FUN(__glewGetBufferPointervARB) +#define glGetBufferSubDataARB GLEW_GET_FUN(__glewGetBufferSubDataARB) +#define glIsBufferARB GLEW_GET_FUN(__glewIsBufferARB) +#define glMapBufferARB GLEW_GET_FUN(__glewMapBufferARB) +#define glUnmapBufferARB GLEW_GET_FUN(__glewUnmapBufferARB) + +#define GLEW_ARB_vertex_buffer_object GLEW_GET_VAR(__GLEW_ARB_vertex_buffer_object) + +#endif /* GL_ARB_vertex_buffer_object */ + +/* ------------------------- GL_ARB_vertex_program ------------------------- */ + +#ifndef GL_ARB_vertex_program +#define GL_ARB_vertex_program 1 + +#define GL_COLOR_SUM_ARB 0x8458 +#define GL_VERTEX_PROGRAM_ARB 0x8620 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 +#define GL_PROGRAM_LENGTH_ARB 0x8627 +#define GL_PROGRAM_STRING_ARB 0x8628 +#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E +#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F +#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 +#define GL_CURRENT_MATRIX_ARB 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 +#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B +#define GL_PROGRAM_BINDING_ARB 0x8677 +#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A +#define GL_PROGRAM_ERROR_STRING_ARB 0x8874 +#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 +#define GL_PROGRAM_FORMAT_ARB 0x8876 +#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0 +#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 +#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 +#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 +#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4 +#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 +#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 +#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 +#define GL_PROGRAM_PARAMETERS_ARB 0x88A8 +#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9 +#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA +#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB +#define GL_PROGRAM_ATTRIBS_ARB 0x88AC +#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD +#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE +#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF +#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 +#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 +#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 +#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 +#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 +#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 +#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 +#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 +#define GL_MATRIX0_ARB 0x88C0 +#define GL_MATRIX1_ARB 0x88C1 +#define GL_MATRIX2_ARB 0x88C2 +#define GL_MATRIX3_ARB 0x88C3 +#define GL_MATRIX4_ARB 0x88C4 +#define GL_MATRIX5_ARB 0x88C5 +#define GL_MATRIX6_ARB 0x88C6 +#define GL_MATRIX7_ARB 0x88C7 +#define GL_MATRIX8_ARB 0x88C8 +#define GL_MATRIX9_ARB 0x88C9 +#define GL_MATRIX10_ARB 0x88CA +#define GL_MATRIX11_ARB 0x88CB +#define GL_MATRIX12_ARB 0x88CC +#define GL_MATRIX13_ARB 0x88CD +#define GL_MATRIX14_ARB 0x88CE +#define GL_MATRIX15_ARB 0x88CF +#define GL_MATRIX16_ARB 0x88D0 +#define GL_MATRIX17_ARB 0x88D1 +#define GL_MATRIX18_ARB 0x88D2 +#define GL_MATRIX19_ARB 0x88D3 +#define GL_MATRIX20_ARB 0x88D4 +#define GL_MATRIX21_ARB 0x88D5 +#define GL_MATRIX22_ARB 0x88D6 +#define GL_MATRIX23_ARB 0x88D7 +#define GL_MATRIX24_ARB 0x88D8 +#define GL_MATRIX25_ARB 0x88D9 +#define GL_MATRIX26_ARB 0x88DA +#define GL_MATRIX27_ARB 0x88DB +#define GL_MATRIX28_ARB 0x88DC +#define GL_MATRIX29_ARB 0x88DD +#define GL_MATRIX30_ARB 0x88DE +#define GL_MATRIX31_ARB 0x88DF + +typedef void (GLAPIENTRY * PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program); +typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint* programs); +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); +typedef void (GLAPIENTRY * PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint* programs); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void* string); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid** pointer); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMARBPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void* string); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer); + +#define glBindProgramARB GLEW_GET_FUN(__glewBindProgramARB) +#define glDeleteProgramsARB GLEW_GET_FUN(__glewDeleteProgramsARB) +#define glDisableVertexAttribArrayARB GLEW_GET_FUN(__glewDisableVertexAttribArrayARB) +#define glEnableVertexAttribArrayARB GLEW_GET_FUN(__glewEnableVertexAttribArrayARB) +#define glGenProgramsARB GLEW_GET_FUN(__glewGenProgramsARB) +#define glGetProgramEnvParameterdvARB GLEW_GET_FUN(__glewGetProgramEnvParameterdvARB) +#define glGetProgramEnvParameterfvARB GLEW_GET_FUN(__glewGetProgramEnvParameterfvARB) +#define glGetProgramLocalParameterdvARB GLEW_GET_FUN(__glewGetProgramLocalParameterdvARB) +#define glGetProgramLocalParameterfvARB GLEW_GET_FUN(__glewGetProgramLocalParameterfvARB) +#define glGetProgramStringARB GLEW_GET_FUN(__glewGetProgramStringARB) +#define glGetProgramivARB GLEW_GET_FUN(__glewGetProgramivARB) +#define glGetVertexAttribPointervARB GLEW_GET_FUN(__glewGetVertexAttribPointervARB) +#define glGetVertexAttribdvARB GLEW_GET_FUN(__glewGetVertexAttribdvARB) +#define glGetVertexAttribfvARB GLEW_GET_FUN(__glewGetVertexAttribfvARB) +#define glGetVertexAttribivARB GLEW_GET_FUN(__glewGetVertexAttribivARB) +#define glIsProgramARB GLEW_GET_FUN(__glewIsProgramARB) +#define glProgramEnvParameter4dARB GLEW_GET_FUN(__glewProgramEnvParameter4dARB) +#define glProgramEnvParameter4dvARB GLEW_GET_FUN(__glewProgramEnvParameter4dvARB) +#define glProgramEnvParameter4fARB GLEW_GET_FUN(__glewProgramEnvParameter4fARB) +#define glProgramEnvParameter4fvARB GLEW_GET_FUN(__glewProgramEnvParameter4fvARB) +#define glProgramLocalParameter4dARB GLEW_GET_FUN(__glewProgramLocalParameter4dARB) +#define glProgramLocalParameter4dvARB GLEW_GET_FUN(__glewProgramLocalParameter4dvARB) +#define glProgramLocalParameter4fARB GLEW_GET_FUN(__glewProgramLocalParameter4fARB) +#define glProgramLocalParameter4fvARB GLEW_GET_FUN(__glewProgramLocalParameter4fvARB) +#define glProgramStringARB GLEW_GET_FUN(__glewProgramStringARB) +#define glVertexAttrib1dARB GLEW_GET_FUN(__glewVertexAttrib1dARB) +#define glVertexAttrib1dvARB GLEW_GET_FUN(__glewVertexAttrib1dvARB) +#define glVertexAttrib1fARB GLEW_GET_FUN(__glewVertexAttrib1fARB) +#define glVertexAttrib1fvARB GLEW_GET_FUN(__glewVertexAttrib1fvARB) +#define glVertexAttrib1sARB GLEW_GET_FUN(__glewVertexAttrib1sARB) +#define glVertexAttrib1svARB GLEW_GET_FUN(__glewVertexAttrib1svARB) +#define glVertexAttrib2dARB GLEW_GET_FUN(__glewVertexAttrib2dARB) +#define glVertexAttrib2dvARB GLEW_GET_FUN(__glewVertexAttrib2dvARB) +#define glVertexAttrib2fARB GLEW_GET_FUN(__glewVertexAttrib2fARB) +#define glVertexAttrib2fvARB GLEW_GET_FUN(__glewVertexAttrib2fvARB) +#define glVertexAttrib2sARB GLEW_GET_FUN(__glewVertexAttrib2sARB) +#define glVertexAttrib2svARB GLEW_GET_FUN(__glewVertexAttrib2svARB) +#define glVertexAttrib3dARB GLEW_GET_FUN(__glewVertexAttrib3dARB) +#define glVertexAttrib3dvARB GLEW_GET_FUN(__glewVertexAttrib3dvARB) +#define glVertexAttrib3fARB GLEW_GET_FUN(__glewVertexAttrib3fARB) +#define glVertexAttrib3fvARB GLEW_GET_FUN(__glewVertexAttrib3fvARB) +#define glVertexAttrib3sARB GLEW_GET_FUN(__glewVertexAttrib3sARB) +#define glVertexAttrib3svARB GLEW_GET_FUN(__glewVertexAttrib3svARB) +#define glVertexAttrib4NbvARB GLEW_GET_FUN(__glewVertexAttrib4NbvARB) +#define glVertexAttrib4NivARB GLEW_GET_FUN(__glewVertexAttrib4NivARB) +#define glVertexAttrib4NsvARB GLEW_GET_FUN(__glewVertexAttrib4NsvARB) +#define glVertexAttrib4NubARB GLEW_GET_FUN(__glewVertexAttrib4NubARB) +#define glVertexAttrib4NubvARB GLEW_GET_FUN(__glewVertexAttrib4NubvARB) +#define glVertexAttrib4NuivARB GLEW_GET_FUN(__glewVertexAttrib4NuivARB) +#define glVertexAttrib4NusvARB GLEW_GET_FUN(__glewVertexAttrib4NusvARB) +#define glVertexAttrib4bvARB GLEW_GET_FUN(__glewVertexAttrib4bvARB) +#define glVertexAttrib4dARB GLEW_GET_FUN(__glewVertexAttrib4dARB) +#define glVertexAttrib4dvARB GLEW_GET_FUN(__glewVertexAttrib4dvARB) +#define glVertexAttrib4fARB GLEW_GET_FUN(__glewVertexAttrib4fARB) +#define glVertexAttrib4fvARB GLEW_GET_FUN(__glewVertexAttrib4fvARB) +#define glVertexAttrib4ivARB GLEW_GET_FUN(__glewVertexAttrib4ivARB) +#define glVertexAttrib4sARB GLEW_GET_FUN(__glewVertexAttrib4sARB) +#define glVertexAttrib4svARB GLEW_GET_FUN(__glewVertexAttrib4svARB) +#define glVertexAttrib4ubvARB GLEW_GET_FUN(__glewVertexAttrib4ubvARB) +#define glVertexAttrib4uivARB GLEW_GET_FUN(__glewVertexAttrib4uivARB) +#define glVertexAttrib4usvARB GLEW_GET_FUN(__glewVertexAttrib4usvARB) +#define glVertexAttribPointerARB GLEW_GET_FUN(__glewVertexAttribPointerARB) + +#define GLEW_ARB_vertex_program GLEW_GET_VAR(__GLEW_ARB_vertex_program) + +#endif /* GL_ARB_vertex_program */ + +/* -------------------------- GL_ARB_vertex_shader ------------------------- */ + +#ifndef GL_ARB_vertex_shader +#define GL_ARB_vertex_shader 1 + +#define GL_VERTEX_SHADER_ARB 0x8B31 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A +#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D +#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89 +#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A + +typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB* name); +typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint *size, GLenum *type, GLcharARB *name); +typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB* name); + +#define glBindAttribLocationARB GLEW_GET_FUN(__glewBindAttribLocationARB) +#define glGetActiveAttribARB GLEW_GET_FUN(__glewGetActiveAttribARB) +#define glGetAttribLocationARB GLEW_GET_FUN(__glewGetAttribLocationARB) + +#define GLEW_ARB_vertex_shader GLEW_GET_VAR(__GLEW_ARB_vertex_shader) + +#endif /* GL_ARB_vertex_shader */ + +/* ------------------- GL_ARB_vertex_type_2_10_10_10_rev ------------------- */ + +#ifndef GL_ARB_vertex_type_2_10_10_10_rev +#define GL_ARB_vertex_type_2_10_10_10_rev 1 + +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_INT_2_10_10_10_REV 0x8D9F + +typedef void (GLAPIENTRY * PFNGLCOLORP3UIPROC) (GLenum type, GLuint color); +typedef void (GLAPIENTRY * PFNGLCOLORP3UIVPROC) (GLenum type, const GLuint* color); +typedef void (GLAPIENTRY * PFNGLCOLORP4UIPROC) (GLenum type, GLuint color); +typedef void (GLAPIENTRY * PFNGLCOLORP4UIVPROC) (GLenum type, const GLuint* color); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP1UIPROC) (GLenum texture, GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP1UIVPROC) (GLenum texture, GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP2UIPROC) (GLenum texture, GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP2UIVPROC) (GLenum texture, GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP3UIPROC) (GLenum texture, GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP3UIVPROC) (GLenum texture, GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP4UIPROC) (GLenum texture, GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP4UIVPROC) (GLenum texture, GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLNORMALP3UIPROC) (GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLNORMALP3UIVPROC) (GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORP3UIPROC) (GLenum type, GLuint color); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORP3UIVPROC) (GLenum type, const GLuint* color); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP1UIPROC) (GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP1UIVPROC) (GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP2UIPROC) (GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP2UIVPROC) (GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP3UIPROC) (GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP3UIVPROC) (GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP4UIPROC) (GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP4UIVPROC) (GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP1UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP1UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP2UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP2UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP3UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP3UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP4UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP4UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXP2UIPROC) (GLenum type, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXP2UIVPROC) (GLenum type, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXP3UIPROC) (GLenum type, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXP3UIVPROC) (GLenum type, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXP4UIPROC) (GLenum type, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXP4UIVPROC) (GLenum type, const GLuint* value); + +#define glColorP3ui GLEW_GET_FUN(__glewColorP3ui) +#define glColorP3uiv GLEW_GET_FUN(__glewColorP3uiv) +#define glColorP4ui GLEW_GET_FUN(__glewColorP4ui) +#define glColorP4uiv GLEW_GET_FUN(__glewColorP4uiv) +#define glMultiTexCoordP1ui GLEW_GET_FUN(__glewMultiTexCoordP1ui) +#define glMultiTexCoordP1uiv GLEW_GET_FUN(__glewMultiTexCoordP1uiv) +#define glMultiTexCoordP2ui GLEW_GET_FUN(__glewMultiTexCoordP2ui) +#define glMultiTexCoordP2uiv GLEW_GET_FUN(__glewMultiTexCoordP2uiv) +#define glMultiTexCoordP3ui GLEW_GET_FUN(__glewMultiTexCoordP3ui) +#define glMultiTexCoordP3uiv GLEW_GET_FUN(__glewMultiTexCoordP3uiv) +#define glMultiTexCoordP4ui GLEW_GET_FUN(__glewMultiTexCoordP4ui) +#define glMultiTexCoordP4uiv GLEW_GET_FUN(__glewMultiTexCoordP4uiv) +#define glNormalP3ui GLEW_GET_FUN(__glewNormalP3ui) +#define glNormalP3uiv GLEW_GET_FUN(__glewNormalP3uiv) +#define glSecondaryColorP3ui GLEW_GET_FUN(__glewSecondaryColorP3ui) +#define glSecondaryColorP3uiv GLEW_GET_FUN(__glewSecondaryColorP3uiv) +#define glTexCoordP1ui GLEW_GET_FUN(__glewTexCoordP1ui) +#define glTexCoordP1uiv GLEW_GET_FUN(__glewTexCoordP1uiv) +#define glTexCoordP2ui GLEW_GET_FUN(__glewTexCoordP2ui) +#define glTexCoordP2uiv GLEW_GET_FUN(__glewTexCoordP2uiv) +#define glTexCoordP3ui GLEW_GET_FUN(__glewTexCoordP3ui) +#define glTexCoordP3uiv GLEW_GET_FUN(__glewTexCoordP3uiv) +#define glTexCoordP4ui GLEW_GET_FUN(__glewTexCoordP4ui) +#define glTexCoordP4uiv GLEW_GET_FUN(__glewTexCoordP4uiv) +#define glVertexAttribP1ui GLEW_GET_FUN(__glewVertexAttribP1ui) +#define glVertexAttribP1uiv GLEW_GET_FUN(__glewVertexAttribP1uiv) +#define glVertexAttribP2ui GLEW_GET_FUN(__glewVertexAttribP2ui) +#define glVertexAttribP2uiv GLEW_GET_FUN(__glewVertexAttribP2uiv) +#define glVertexAttribP3ui GLEW_GET_FUN(__glewVertexAttribP3ui) +#define glVertexAttribP3uiv GLEW_GET_FUN(__glewVertexAttribP3uiv) +#define glVertexAttribP4ui GLEW_GET_FUN(__glewVertexAttribP4ui) +#define glVertexAttribP4uiv GLEW_GET_FUN(__glewVertexAttribP4uiv) +#define glVertexP2ui GLEW_GET_FUN(__glewVertexP2ui) +#define glVertexP2uiv GLEW_GET_FUN(__glewVertexP2uiv) +#define glVertexP3ui GLEW_GET_FUN(__glewVertexP3ui) +#define glVertexP3uiv GLEW_GET_FUN(__glewVertexP3uiv) +#define glVertexP4ui GLEW_GET_FUN(__glewVertexP4ui) +#define glVertexP4uiv GLEW_GET_FUN(__glewVertexP4uiv) + +#define GLEW_ARB_vertex_type_2_10_10_10_rev GLEW_GET_VAR(__GLEW_ARB_vertex_type_2_10_10_10_rev) + +#endif /* GL_ARB_vertex_type_2_10_10_10_rev */ + +/* ------------------------- GL_ARB_viewport_array ------------------------- */ + +#ifndef GL_ARB_viewport_array +#define GL_ARB_viewport_array 1 + +#define GL_DEPTH_RANGE 0x0B70 +#define GL_VIEWPORT 0x0BA2 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_MAX_VIEWPORTS 0x825B +#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C +#define GL_VIEWPORT_BOUNDS_RANGE 0x825D +#define GL_LAYER_PROVOKING_VERTEX 0x825E +#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F +#define GL_UNDEFINED_VERTEX 0x8260 +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_PROVOKING_VERTEX 0x8E4F + +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLclampd * v); +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLclampd n, GLclampd f); +typedef void (GLAPIENTRY * PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble* data); +typedef void (GLAPIENTRY * PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat* data); +typedef void (GLAPIENTRY * PFNGLSCISSORARRAYVPROC) (GLuint first, GLsizei count, const GLint * v); +typedef void (GLAPIENTRY * PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLSCISSORINDEXEDVPROC) (GLuint index, const GLint * v); +typedef void (GLAPIENTRY * PFNGLVIEWPORTARRAYVPROC) (GLuint first, GLsizei count, const GLfloat * v); +typedef void (GLAPIENTRY * PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); +typedef void (GLAPIENTRY * PFNGLVIEWPORTINDEXEDFVPROC) (GLuint index, const GLfloat * v); + +#define glDepthRangeArrayv GLEW_GET_FUN(__glewDepthRangeArrayv) +#define glDepthRangeIndexed GLEW_GET_FUN(__glewDepthRangeIndexed) +#define glGetDoublei_v GLEW_GET_FUN(__glewGetDoublei_v) +#define glGetFloati_v GLEW_GET_FUN(__glewGetFloati_v) +#define glScissorArrayv GLEW_GET_FUN(__glewScissorArrayv) +#define glScissorIndexed GLEW_GET_FUN(__glewScissorIndexed) +#define glScissorIndexedv GLEW_GET_FUN(__glewScissorIndexedv) +#define glViewportArrayv GLEW_GET_FUN(__glewViewportArrayv) +#define glViewportIndexedf GLEW_GET_FUN(__glewViewportIndexedf) +#define glViewportIndexedfv GLEW_GET_FUN(__glewViewportIndexedfv) + +#define GLEW_ARB_viewport_array GLEW_GET_VAR(__GLEW_ARB_viewport_array) + +#endif /* GL_ARB_viewport_array */ + +/* --------------------------- GL_ARB_window_pos --------------------------- */ + +#ifndef GL_ARB_window_pos +#define GL_ARB_window_pos 1 + +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVARBPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVARBPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVARBPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVARBPROC) (const GLshort* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVARBPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVARBPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVARBPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVARBPROC) (const GLshort* p); + +#define glWindowPos2dARB GLEW_GET_FUN(__glewWindowPos2dARB) +#define glWindowPos2dvARB GLEW_GET_FUN(__glewWindowPos2dvARB) +#define glWindowPos2fARB GLEW_GET_FUN(__glewWindowPos2fARB) +#define glWindowPos2fvARB GLEW_GET_FUN(__glewWindowPos2fvARB) +#define glWindowPos2iARB GLEW_GET_FUN(__glewWindowPos2iARB) +#define glWindowPos2ivARB GLEW_GET_FUN(__glewWindowPos2ivARB) +#define glWindowPos2sARB GLEW_GET_FUN(__glewWindowPos2sARB) +#define glWindowPos2svARB GLEW_GET_FUN(__glewWindowPos2svARB) +#define glWindowPos3dARB GLEW_GET_FUN(__glewWindowPos3dARB) +#define glWindowPos3dvARB GLEW_GET_FUN(__glewWindowPos3dvARB) +#define glWindowPos3fARB GLEW_GET_FUN(__glewWindowPos3fARB) +#define glWindowPos3fvARB GLEW_GET_FUN(__glewWindowPos3fvARB) +#define glWindowPos3iARB GLEW_GET_FUN(__glewWindowPos3iARB) +#define glWindowPos3ivARB GLEW_GET_FUN(__glewWindowPos3ivARB) +#define glWindowPos3sARB GLEW_GET_FUN(__glewWindowPos3sARB) +#define glWindowPos3svARB GLEW_GET_FUN(__glewWindowPos3svARB) + +#define GLEW_ARB_window_pos GLEW_GET_VAR(__GLEW_ARB_window_pos) + +#endif /* GL_ARB_window_pos */ + +/* ------------------------- GL_ATIX_point_sprites ------------------------- */ + +#ifndef GL_ATIX_point_sprites +#define GL_ATIX_point_sprites 1 + +#define GL_TEXTURE_POINT_MODE_ATIX 0x60B0 +#define GL_TEXTURE_POINT_ONE_COORD_ATIX 0x60B1 +#define GL_TEXTURE_POINT_SPRITE_ATIX 0x60B2 +#define GL_POINT_SPRITE_CULL_MODE_ATIX 0x60B3 +#define GL_POINT_SPRITE_CULL_CENTER_ATIX 0x60B4 +#define GL_POINT_SPRITE_CULL_CLIP_ATIX 0x60B5 + +#define GLEW_ATIX_point_sprites GLEW_GET_VAR(__GLEW_ATIX_point_sprites) + +#endif /* GL_ATIX_point_sprites */ + +/* ---------------------- GL_ATIX_texture_env_combine3 --------------------- */ + +#ifndef GL_ATIX_texture_env_combine3 +#define GL_ATIX_texture_env_combine3 1 + +#define GL_MODULATE_ADD_ATIX 0x8744 +#define GL_MODULATE_SIGNED_ADD_ATIX 0x8745 +#define GL_MODULATE_SUBTRACT_ATIX 0x8746 + +#define GLEW_ATIX_texture_env_combine3 GLEW_GET_VAR(__GLEW_ATIX_texture_env_combine3) + +#endif /* GL_ATIX_texture_env_combine3 */ + +/* ----------------------- GL_ATIX_texture_env_route ----------------------- */ + +#ifndef GL_ATIX_texture_env_route +#define GL_ATIX_texture_env_route 1 + +#define GL_SECONDARY_COLOR_ATIX 0x8747 +#define GL_TEXTURE_OUTPUT_RGB_ATIX 0x8748 +#define GL_TEXTURE_OUTPUT_ALPHA_ATIX 0x8749 + +#define GLEW_ATIX_texture_env_route GLEW_GET_VAR(__GLEW_ATIX_texture_env_route) + +#endif /* GL_ATIX_texture_env_route */ + +/* ---------------- GL_ATIX_vertex_shader_output_point_size ---------------- */ + +#ifndef GL_ATIX_vertex_shader_output_point_size +#define GL_ATIX_vertex_shader_output_point_size 1 + +#define GL_OUTPUT_POINT_SIZE_ATIX 0x610E + +#define GLEW_ATIX_vertex_shader_output_point_size GLEW_GET_VAR(__GLEW_ATIX_vertex_shader_output_point_size) + +#endif /* GL_ATIX_vertex_shader_output_point_size */ + +/* -------------------------- GL_ATI_draw_buffers -------------------------- */ + +#ifndef GL_ATI_draw_buffers +#define GL_ATI_draw_buffers 1 + +#define GL_MAX_DRAW_BUFFERS_ATI 0x8824 +#define GL_DRAW_BUFFER0_ATI 0x8825 +#define GL_DRAW_BUFFER1_ATI 0x8826 +#define GL_DRAW_BUFFER2_ATI 0x8827 +#define GL_DRAW_BUFFER3_ATI 0x8828 +#define GL_DRAW_BUFFER4_ATI 0x8829 +#define GL_DRAW_BUFFER5_ATI 0x882A +#define GL_DRAW_BUFFER6_ATI 0x882B +#define GL_DRAW_BUFFER7_ATI 0x882C +#define GL_DRAW_BUFFER8_ATI 0x882D +#define GL_DRAW_BUFFER9_ATI 0x882E +#define GL_DRAW_BUFFER10_ATI 0x882F +#define GL_DRAW_BUFFER11_ATI 0x8830 +#define GL_DRAW_BUFFER12_ATI 0x8831 +#define GL_DRAW_BUFFER13_ATI 0x8832 +#define GL_DRAW_BUFFER14_ATI 0x8833 +#define GL_DRAW_BUFFER15_ATI 0x8834 + +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum* bufs); + +#define glDrawBuffersATI GLEW_GET_FUN(__glewDrawBuffersATI) + +#define GLEW_ATI_draw_buffers GLEW_GET_VAR(__GLEW_ATI_draw_buffers) + +#endif /* GL_ATI_draw_buffers */ + +/* -------------------------- GL_ATI_element_array ------------------------- */ + +#ifndef GL_ATI_element_array +#define GL_ATI_element_array 1 + +#define GL_ELEMENT_ARRAY_ATI 0x8768 +#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769 +#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A + +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count); +typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERATIPROC) (GLenum type, const void* pointer); + +#define glDrawElementArrayATI GLEW_GET_FUN(__glewDrawElementArrayATI) +#define glDrawRangeElementArrayATI GLEW_GET_FUN(__glewDrawRangeElementArrayATI) +#define glElementPointerATI GLEW_GET_FUN(__glewElementPointerATI) + +#define GLEW_ATI_element_array GLEW_GET_VAR(__GLEW_ATI_element_array) + +#endif /* GL_ATI_element_array */ + +/* ------------------------- GL_ATI_envmap_bumpmap ------------------------- */ + +#ifndef GL_ATI_envmap_bumpmap +#define GL_ATI_envmap_bumpmap 1 + +#define GL_BUMP_ROT_MATRIX_ATI 0x8775 +#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776 +#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777 +#define GL_BUMP_TEX_UNITS_ATI 0x8778 +#define GL_DUDV_ATI 0x8779 +#define GL_DU8DV8_ATI 0x877A +#define GL_BUMP_ENVMAP_ATI 0x877B +#define GL_BUMP_TARGET_ATI 0x877C + +typedef void (GLAPIENTRY * PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param); +typedef void (GLAPIENTRY * PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param); +typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param); +typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param); + +#define glGetTexBumpParameterfvATI GLEW_GET_FUN(__glewGetTexBumpParameterfvATI) +#define glGetTexBumpParameterivATI GLEW_GET_FUN(__glewGetTexBumpParameterivATI) +#define glTexBumpParameterfvATI GLEW_GET_FUN(__glewTexBumpParameterfvATI) +#define glTexBumpParameterivATI GLEW_GET_FUN(__glewTexBumpParameterivATI) + +#define GLEW_ATI_envmap_bumpmap GLEW_GET_VAR(__GLEW_ATI_envmap_bumpmap) + +#endif /* GL_ATI_envmap_bumpmap */ + +/* ------------------------- GL_ATI_fragment_shader ------------------------ */ + +#ifndef GL_ATI_fragment_shader +#define GL_ATI_fragment_shader 1 + +#define GL_RED_BIT_ATI 0x00000001 +#define GL_2X_BIT_ATI 0x00000001 +#define GL_4X_BIT_ATI 0x00000002 +#define GL_GREEN_BIT_ATI 0x00000002 +#define GL_COMP_BIT_ATI 0x00000002 +#define GL_BLUE_BIT_ATI 0x00000004 +#define GL_8X_BIT_ATI 0x00000004 +#define GL_NEGATE_BIT_ATI 0x00000004 +#define GL_BIAS_BIT_ATI 0x00000008 +#define GL_HALF_BIT_ATI 0x00000008 +#define GL_QUARTER_BIT_ATI 0x00000010 +#define GL_EIGHTH_BIT_ATI 0x00000020 +#define GL_SATURATE_BIT_ATI 0x00000040 +#define GL_FRAGMENT_SHADER_ATI 0x8920 +#define GL_REG_0_ATI 0x8921 +#define GL_REG_1_ATI 0x8922 +#define GL_REG_2_ATI 0x8923 +#define GL_REG_3_ATI 0x8924 +#define GL_REG_4_ATI 0x8925 +#define GL_REG_5_ATI 0x8926 +#define GL_CON_0_ATI 0x8941 +#define GL_CON_1_ATI 0x8942 +#define GL_CON_2_ATI 0x8943 +#define GL_CON_3_ATI 0x8944 +#define GL_CON_4_ATI 0x8945 +#define GL_CON_5_ATI 0x8946 +#define GL_CON_6_ATI 0x8947 +#define GL_CON_7_ATI 0x8948 +#define GL_MOV_ATI 0x8961 +#define GL_ADD_ATI 0x8963 +#define GL_MUL_ATI 0x8964 +#define GL_SUB_ATI 0x8965 +#define GL_DOT3_ATI 0x8966 +#define GL_DOT4_ATI 0x8967 +#define GL_MAD_ATI 0x8968 +#define GL_LERP_ATI 0x8969 +#define GL_CND_ATI 0x896A +#define GL_CND0_ATI 0x896B +#define GL_DOT2_ADD_ATI 0x896C +#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D +#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E +#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F +#define GL_NUM_PASSES_ATI 0x8970 +#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971 +#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972 +#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973 +#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974 +#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975 +#define GL_SWIZZLE_STR_ATI 0x8976 +#define GL_SWIZZLE_STQ_ATI 0x8977 +#define GL_SWIZZLE_STR_DR_ATI 0x8978 +#define GL_SWIZZLE_STQ_DQ_ATI 0x8979 +#define GL_SWIZZLE_STRQ_ATI 0x897A +#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B + +typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +typedef void (GLAPIENTRY * PFNGLBEGINFRAGMENTSHADERATIPROC) (void); +typedef void (GLAPIENTRY * PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +typedef void (GLAPIENTRY * PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLENDFRAGMENTSHADERATIPROC) (void); +typedef GLuint (GLAPIENTRY * PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range); +typedef void (GLAPIENTRY * PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle); +typedef void (GLAPIENTRY * PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle); +typedef void (GLAPIENTRY * PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat* value); + +#define glAlphaFragmentOp1ATI GLEW_GET_FUN(__glewAlphaFragmentOp1ATI) +#define glAlphaFragmentOp2ATI GLEW_GET_FUN(__glewAlphaFragmentOp2ATI) +#define glAlphaFragmentOp3ATI GLEW_GET_FUN(__glewAlphaFragmentOp3ATI) +#define glBeginFragmentShaderATI GLEW_GET_FUN(__glewBeginFragmentShaderATI) +#define glBindFragmentShaderATI GLEW_GET_FUN(__glewBindFragmentShaderATI) +#define glColorFragmentOp1ATI GLEW_GET_FUN(__glewColorFragmentOp1ATI) +#define glColorFragmentOp2ATI GLEW_GET_FUN(__glewColorFragmentOp2ATI) +#define glColorFragmentOp3ATI GLEW_GET_FUN(__glewColorFragmentOp3ATI) +#define glDeleteFragmentShaderATI GLEW_GET_FUN(__glewDeleteFragmentShaderATI) +#define glEndFragmentShaderATI GLEW_GET_FUN(__glewEndFragmentShaderATI) +#define glGenFragmentShadersATI GLEW_GET_FUN(__glewGenFragmentShadersATI) +#define glPassTexCoordATI GLEW_GET_FUN(__glewPassTexCoordATI) +#define glSampleMapATI GLEW_GET_FUN(__glewSampleMapATI) +#define glSetFragmentShaderConstantATI GLEW_GET_FUN(__glewSetFragmentShaderConstantATI) + +#define GLEW_ATI_fragment_shader GLEW_GET_VAR(__GLEW_ATI_fragment_shader) + +#endif /* GL_ATI_fragment_shader */ + +/* ------------------------ GL_ATI_map_object_buffer ----------------------- */ + +#ifndef GL_ATI_map_object_buffer +#define GL_ATI_map_object_buffer 1 + +typedef void* (GLAPIENTRY * PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer); + +#define glMapObjectBufferATI GLEW_GET_FUN(__glewMapObjectBufferATI) +#define glUnmapObjectBufferATI GLEW_GET_FUN(__glewUnmapObjectBufferATI) + +#define GLEW_ATI_map_object_buffer GLEW_GET_VAR(__GLEW_ATI_map_object_buffer) + +#endif /* GL_ATI_map_object_buffer */ + +/* ----------------------------- GL_ATI_meminfo ---------------------------- */ + +#ifndef GL_ATI_meminfo +#define GL_ATI_meminfo 1 + +#define GL_VBO_FREE_MEMORY_ATI 0x87FB +#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC +#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD + +#define GLEW_ATI_meminfo GLEW_GET_VAR(__GLEW_ATI_meminfo) + +#endif /* GL_ATI_meminfo */ + +/* -------------------------- GL_ATI_pn_triangles -------------------------- */ + +#ifndef GL_ATI_pn_triangles +#define GL_ATI_pn_triangles 1 + +#define GL_PN_TRIANGLES_ATI 0x87F0 +#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1 +#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2 +#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3 +#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4 +#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5 +#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6 +#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7 +#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8 + +typedef void (GLAPIENTRY * PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param); + +#define glPNTrianglesfATI GLEW_GET_FUN(__glewPNTrianglesfATI) +#define glPNTrianglesiATI GLEW_GET_FUN(__glewPNTrianglesiATI) + +#define GLEW_ATI_pn_triangles GLEW_GET_VAR(__GLEW_ATI_pn_triangles) + +#endif /* GL_ATI_pn_triangles */ + +/* ------------------------ GL_ATI_separate_stencil ------------------------ */ + +#ifndef GL_ATI_separate_stencil +#define GL_ATI_separate_stencil 1 + +#define GL_STENCIL_BACK_FUNC_ATI 0x8800 +#define GL_STENCIL_BACK_FAIL_ATI 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803 + +typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); +typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); + +#define glStencilFuncSeparateATI GLEW_GET_FUN(__glewStencilFuncSeparateATI) +#define glStencilOpSeparateATI GLEW_GET_FUN(__glewStencilOpSeparateATI) + +#define GLEW_ATI_separate_stencil GLEW_GET_VAR(__GLEW_ATI_separate_stencil) + +#endif /* GL_ATI_separate_stencil */ + +/* ----------------------- GL_ATI_shader_texture_lod ----------------------- */ + +#ifndef GL_ATI_shader_texture_lod +#define GL_ATI_shader_texture_lod 1 + +#define GLEW_ATI_shader_texture_lod GLEW_GET_VAR(__GLEW_ATI_shader_texture_lod) + +#endif /* GL_ATI_shader_texture_lod */ + +/* ---------------------- GL_ATI_text_fragment_shader ---------------------- */ + +#ifndef GL_ATI_text_fragment_shader +#define GL_ATI_text_fragment_shader 1 + +#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200 + +#define GLEW_ATI_text_fragment_shader GLEW_GET_VAR(__GLEW_ATI_text_fragment_shader) + +#endif /* GL_ATI_text_fragment_shader */ + +/* --------------------- GL_ATI_texture_compression_3dc -------------------- */ + +#ifndef GL_ATI_texture_compression_3dc +#define GL_ATI_texture_compression_3dc 1 + +#define GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI 0x8837 + +#define GLEW_ATI_texture_compression_3dc GLEW_GET_VAR(__GLEW_ATI_texture_compression_3dc) + +#endif /* GL_ATI_texture_compression_3dc */ + +/* ---------------------- GL_ATI_texture_env_combine3 ---------------------- */ + +#ifndef GL_ATI_texture_env_combine3 +#define GL_ATI_texture_env_combine3 1 + +#define GL_MODULATE_ADD_ATI 0x8744 +#define GL_MODULATE_SIGNED_ADD_ATI 0x8745 +#define GL_MODULATE_SUBTRACT_ATI 0x8746 + +#define GLEW_ATI_texture_env_combine3 GLEW_GET_VAR(__GLEW_ATI_texture_env_combine3) + +#endif /* GL_ATI_texture_env_combine3 */ + +/* -------------------------- GL_ATI_texture_float ------------------------- */ + +#ifndef GL_ATI_texture_float +#define GL_ATI_texture_float 1 + +#define GL_RGBA_FLOAT32_ATI 0x8814 +#define GL_RGB_FLOAT32_ATI 0x8815 +#define GL_ALPHA_FLOAT32_ATI 0x8816 +#define GL_INTENSITY_FLOAT32_ATI 0x8817 +#define GL_LUMINANCE_FLOAT32_ATI 0x8818 +#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819 +#define GL_RGBA_FLOAT16_ATI 0x881A +#define GL_RGB_FLOAT16_ATI 0x881B +#define GL_ALPHA_FLOAT16_ATI 0x881C +#define GL_INTENSITY_FLOAT16_ATI 0x881D +#define GL_LUMINANCE_FLOAT16_ATI 0x881E +#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F + +#define GLEW_ATI_texture_float GLEW_GET_VAR(__GLEW_ATI_texture_float) + +#endif /* GL_ATI_texture_float */ + +/* ----------------------- GL_ATI_texture_mirror_once ---------------------- */ + +#ifndef GL_ATI_texture_mirror_once +#define GL_ATI_texture_mirror_once 1 + +#define GL_MIRROR_CLAMP_ATI 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743 + +#define GLEW_ATI_texture_mirror_once GLEW_GET_VAR(__GLEW_ATI_texture_mirror_once) + +#endif /* GL_ATI_texture_mirror_once */ + +/* ----------------------- GL_ATI_vertex_array_object ---------------------- */ + +#ifndef GL_ATI_vertex_array_object +#define GL_ATI_vertex_array_object 1 + +#define GL_STATIC_ATI 0x8760 +#define GL_DYNAMIC_ATI 0x8761 +#define GL_PRESERVE_ATI 0x8762 +#define GL_DISCARD_ATI 0x8763 +#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764 +#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765 +#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766 +#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767 + +typedef void (GLAPIENTRY * PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); +typedef void (GLAPIENTRY * PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer); +typedef GLuint (GLAPIENTRY * PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const void* pointer, GLenum usage); +typedef void (GLAPIENTRY * PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const void* pointer, GLenum preserve); +typedef void (GLAPIENTRY * PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); + +#define glArrayObjectATI GLEW_GET_FUN(__glewArrayObjectATI) +#define glFreeObjectBufferATI GLEW_GET_FUN(__glewFreeObjectBufferATI) +#define glGetArrayObjectfvATI GLEW_GET_FUN(__glewGetArrayObjectfvATI) +#define glGetArrayObjectivATI GLEW_GET_FUN(__glewGetArrayObjectivATI) +#define glGetObjectBufferfvATI GLEW_GET_FUN(__glewGetObjectBufferfvATI) +#define glGetObjectBufferivATI GLEW_GET_FUN(__glewGetObjectBufferivATI) +#define glGetVariantArrayObjectfvATI GLEW_GET_FUN(__glewGetVariantArrayObjectfvATI) +#define glGetVariantArrayObjectivATI GLEW_GET_FUN(__glewGetVariantArrayObjectivATI) +#define glIsObjectBufferATI GLEW_GET_FUN(__glewIsObjectBufferATI) +#define glNewObjectBufferATI GLEW_GET_FUN(__glewNewObjectBufferATI) +#define glUpdateObjectBufferATI GLEW_GET_FUN(__glewUpdateObjectBufferATI) +#define glVariantArrayObjectATI GLEW_GET_FUN(__glewVariantArrayObjectATI) + +#define GLEW_ATI_vertex_array_object GLEW_GET_VAR(__GLEW_ATI_vertex_array_object) + +#endif /* GL_ATI_vertex_array_object */ + +/* ------------------- GL_ATI_vertex_attrib_array_object ------------------- */ + +#ifndef GL_ATI_vertex_attrib_array_object +#define GL_ATI_vertex_attrib_array_object 1 + +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset); + +#define glGetVertexAttribArrayObjectfvATI GLEW_GET_FUN(__glewGetVertexAttribArrayObjectfvATI) +#define glGetVertexAttribArrayObjectivATI GLEW_GET_FUN(__glewGetVertexAttribArrayObjectivATI) +#define glVertexAttribArrayObjectATI GLEW_GET_FUN(__glewVertexAttribArrayObjectATI) + +#define GLEW_ATI_vertex_attrib_array_object GLEW_GET_VAR(__GLEW_ATI_vertex_attrib_array_object) + +#endif /* GL_ATI_vertex_attrib_array_object */ + +/* ------------------------- GL_ATI_vertex_streams ------------------------- */ + +#ifndef GL_ATI_vertex_streams +#define GL_ATI_vertex_streams 1 + +#define GL_MAX_VERTEX_STREAMS_ATI 0x876B +#define GL_VERTEX_SOURCE_ATI 0x876C +#define GL_VERTEX_STREAM0_ATI 0x876D +#define GL_VERTEX_STREAM1_ATI 0x876E +#define GL_VERTEX_STREAM2_ATI 0x876F +#define GL_VERTEX_STREAM3_ATI 0x8770 +#define GL_VERTEX_STREAM4_ATI 0x8771 +#define GL_VERTEX_STREAM5_ATI 0x8772 +#define GL_VERTEX_STREAM6_ATI 0x8773 +#define GL_VERTEX_STREAM7_ATI 0x8774 + +typedef void (GLAPIENTRY * PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte x, GLbyte y, GLbyte z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *v); + +#define glClientActiveVertexStreamATI GLEW_GET_FUN(__glewClientActiveVertexStreamATI) +#define glNormalStream3bATI GLEW_GET_FUN(__glewNormalStream3bATI) +#define glNormalStream3bvATI GLEW_GET_FUN(__glewNormalStream3bvATI) +#define glNormalStream3dATI GLEW_GET_FUN(__glewNormalStream3dATI) +#define glNormalStream3dvATI GLEW_GET_FUN(__glewNormalStream3dvATI) +#define glNormalStream3fATI GLEW_GET_FUN(__glewNormalStream3fATI) +#define glNormalStream3fvATI GLEW_GET_FUN(__glewNormalStream3fvATI) +#define glNormalStream3iATI GLEW_GET_FUN(__glewNormalStream3iATI) +#define glNormalStream3ivATI GLEW_GET_FUN(__glewNormalStream3ivATI) +#define glNormalStream3sATI GLEW_GET_FUN(__glewNormalStream3sATI) +#define glNormalStream3svATI GLEW_GET_FUN(__glewNormalStream3svATI) +#define glVertexBlendEnvfATI GLEW_GET_FUN(__glewVertexBlendEnvfATI) +#define glVertexBlendEnviATI GLEW_GET_FUN(__glewVertexBlendEnviATI) +#define glVertexStream2dATI GLEW_GET_FUN(__glewVertexStream2dATI) +#define glVertexStream2dvATI GLEW_GET_FUN(__glewVertexStream2dvATI) +#define glVertexStream2fATI GLEW_GET_FUN(__glewVertexStream2fATI) +#define glVertexStream2fvATI GLEW_GET_FUN(__glewVertexStream2fvATI) +#define glVertexStream2iATI GLEW_GET_FUN(__glewVertexStream2iATI) +#define glVertexStream2ivATI GLEW_GET_FUN(__glewVertexStream2ivATI) +#define glVertexStream2sATI GLEW_GET_FUN(__glewVertexStream2sATI) +#define glVertexStream2svATI GLEW_GET_FUN(__glewVertexStream2svATI) +#define glVertexStream3dATI GLEW_GET_FUN(__glewVertexStream3dATI) +#define glVertexStream3dvATI GLEW_GET_FUN(__glewVertexStream3dvATI) +#define glVertexStream3fATI GLEW_GET_FUN(__glewVertexStream3fATI) +#define glVertexStream3fvATI GLEW_GET_FUN(__glewVertexStream3fvATI) +#define glVertexStream3iATI GLEW_GET_FUN(__glewVertexStream3iATI) +#define glVertexStream3ivATI GLEW_GET_FUN(__glewVertexStream3ivATI) +#define glVertexStream3sATI GLEW_GET_FUN(__glewVertexStream3sATI) +#define glVertexStream3svATI GLEW_GET_FUN(__glewVertexStream3svATI) +#define glVertexStream4dATI GLEW_GET_FUN(__glewVertexStream4dATI) +#define glVertexStream4dvATI GLEW_GET_FUN(__glewVertexStream4dvATI) +#define glVertexStream4fATI GLEW_GET_FUN(__glewVertexStream4fATI) +#define glVertexStream4fvATI GLEW_GET_FUN(__glewVertexStream4fvATI) +#define glVertexStream4iATI GLEW_GET_FUN(__glewVertexStream4iATI) +#define glVertexStream4ivATI GLEW_GET_FUN(__glewVertexStream4ivATI) +#define glVertexStream4sATI GLEW_GET_FUN(__glewVertexStream4sATI) +#define glVertexStream4svATI GLEW_GET_FUN(__glewVertexStream4svATI) + +#define GLEW_ATI_vertex_streams GLEW_GET_VAR(__GLEW_ATI_vertex_streams) + +#endif /* GL_ATI_vertex_streams */ + +/* --------------------------- GL_EXT_422_pixels --------------------------- */ + +#ifndef GL_EXT_422_pixels +#define GL_EXT_422_pixels 1 + +#define GL_422_EXT 0x80CC +#define GL_422_REV_EXT 0x80CD +#define GL_422_AVERAGE_EXT 0x80CE +#define GL_422_REV_AVERAGE_EXT 0x80CF + +#define GLEW_EXT_422_pixels GLEW_GET_VAR(__GLEW_EXT_422_pixels) + +#endif /* GL_EXT_422_pixels */ + +/* ---------------------------- GL_EXT_Cg_shader --------------------------- */ + +#ifndef GL_EXT_Cg_shader +#define GL_EXT_Cg_shader 1 + +#define GL_CG_VERTEX_SHADER_EXT 0x890E +#define GL_CG_FRAGMENT_SHADER_EXT 0x890F + +#define GLEW_EXT_Cg_shader GLEW_GET_VAR(__GLEW_EXT_Cg_shader) + +#endif /* GL_EXT_Cg_shader */ + +/* ------------------------------ GL_EXT_abgr ------------------------------ */ + +#ifndef GL_EXT_abgr +#define GL_EXT_abgr 1 + +#define GL_ABGR_EXT 0x8000 + +#define GLEW_EXT_abgr GLEW_GET_VAR(__GLEW_EXT_abgr) + +#endif /* GL_EXT_abgr */ + +/* ------------------------------ GL_EXT_bgra ------------------------------ */ + +#ifndef GL_EXT_bgra +#define GL_EXT_bgra 1 + +#define GL_BGR_EXT 0x80E0 +#define GL_BGRA_EXT 0x80E1 + +#define GLEW_EXT_bgra GLEW_GET_VAR(__GLEW_EXT_bgra) + +#endif /* GL_EXT_bgra */ + +/* ------------------------ GL_EXT_bindable_uniform ------------------------ */ + +#ifndef GL_EXT_bindable_uniform +#define GL_EXT_bindable_uniform 1 + +#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2 +#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3 +#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4 +#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED +#define GL_UNIFORM_BUFFER_EXT 0x8DEE +#define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF + +typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location); +typedef GLintptr (GLAPIENTRY * PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location); +typedef void (GLAPIENTRY * PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer); + +#define glGetUniformBufferSizeEXT GLEW_GET_FUN(__glewGetUniformBufferSizeEXT) +#define glGetUniformOffsetEXT GLEW_GET_FUN(__glewGetUniformOffsetEXT) +#define glUniformBufferEXT GLEW_GET_FUN(__glewUniformBufferEXT) + +#define GLEW_EXT_bindable_uniform GLEW_GET_VAR(__GLEW_EXT_bindable_uniform) + +#endif /* GL_EXT_bindable_uniform */ + +/* --------------------------- GL_EXT_blend_color -------------------------- */ + +#ifndef GL_EXT_blend_color +#define GL_EXT_blend_color 1 + +#define GL_CONSTANT_COLOR_EXT 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002 +#define GL_CONSTANT_ALPHA_EXT 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004 +#define GL_BLEND_COLOR_EXT 0x8005 + +typedef void (GLAPIENTRY * PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + +#define glBlendColorEXT GLEW_GET_FUN(__glewBlendColorEXT) + +#define GLEW_EXT_blend_color GLEW_GET_VAR(__GLEW_EXT_blend_color) + +#endif /* GL_EXT_blend_color */ + +/* --------------------- GL_EXT_blend_equation_separate -------------------- */ + +#ifndef GL_EXT_blend_equation_separate +#define GL_EXT_blend_equation_separate 1 + +#define GL_BLEND_EQUATION_RGB_EXT 0x8009 +#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha); + +#define glBlendEquationSeparateEXT GLEW_GET_FUN(__glewBlendEquationSeparateEXT) + +#define GLEW_EXT_blend_equation_separate GLEW_GET_VAR(__GLEW_EXT_blend_equation_separate) + +#endif /* GL_EXT_blend_equation_separate */ + +/* ----------------------- GL_EXT_blend_func_separate ---------------------- */ + +#ifndef GL_EXT_blend_func_separate +#define GL_EXT_blend_func_separate 1 + +#define GL_BLEND_DST_RGB_EXT 0x80C8 +#define GL_BLEND_SRC_RGB_EXT 0x80C9 +#define GL_BLEND_DST_ALPHA_EXT 0x80CA +#define GL_BLEND_SRC_ALPHA_EXT 0x80CB + +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + +#define glBlendFuncSeparateEXT GLEW_GET_FUN(__glewBlendFuncSeparateEXT) + +#define GLEW_EXT_blend_func_separate GLEW_GET_VAR(__GLEW_EXT_blend_func_separate) + +#endif /* GL_EXT_blend_func_separate */ + +/* ------------------------- GL_EXT_blend_logic_op ------------------------- */ + +#ifndef GL_EXT_blend_logic_op +#define GL_EXT_blend_logic_op 1 + +#define GLEW_EXT_blend_logic_op GLEW_GET_VAR(__GLEW_EXT_blend_logic_op) + +#endif /* GL_EXT_blend_logic_op */ + +/* -------------------------- GL_EXT_blend_minmax -------------------------- */ + +#ifndef GL_EXT_blend_minmax +#define GL_EXT_blend_minmax 1 + +#define GL_FUNC_ADD_EXT 0x8006 +#define GL_MIN_EXT 0x8007 +#define GL_MAX_EXT 0x8008 +#define GL_BLEND_EQUATION_EXT 0x8009 + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONEXTPROC) (GLenum mode); + +#define glBlendEquationEXT GLEW_GET_FUN(__glewBlendEquationEXT) + +#define GLEW_EXT_blend_minmax GLEW_GET_VAR(__GLEW_EXT_blend_minmax) + +#endif /* GL_EXT_blend_minmax */ + +/* ------------------------- GL_EXT_blend_subtract ------------------------- */ + +#ifndef GL_EXT_blend_subtract +#define GL_EXT_blend_subtract 1 + +#define GL_FUNC_SUBTRACT_EXT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B + +#define GLEW_EXT_blend_subtract GLEW_GET_VAR(__GLEW_EXT_blend_subtract) + +#endif /* GL_EXT_blend_subtract */ + +/* ------------------------ GL_EXT_clip_volume_hint ------------------------ */ + +#ifndef GL_EXT_clip_volume_hint +#define GL_EXT_clip_volume_hint 1 + +#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0 + +#define GLEW_EXT_clip_volume_hint GLEW_GET_VAR(__GLEW_EXT_clip_volume_hint) + +#endif /* GL_EXT_clip_volume_hint */ + +/* ------------------------------ GL_EXT_cmyka ----------------------------- */ + +#ifndef GL_EXT_cmyka +#define GL_EXT_cmyka 1 + +#define GL_CMYK_EXT 0x800C +#define GL_CMYKA_EXT 0x800D +#define GL_PACK_CMYK_HINT_EXT 0x800E +#define GL_UNPACK_CMYK_HINT_EXT 0x800F + +#define GLEW_EXT_cmyka GLEW_GET_VAR(__GLEW_EXT_cmyka) + +#endif /* GL_EXT_cmyka */ + +/* ------------------------- GL_EXT_color_subtable ------------------------- */ + +#ifndef GL_EXT_color_subtable +#define GL_EXT_color_subtable 1 + +typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void* data); +typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); + +#define glColorSubTableEXT GLEW_GET_FUN(__glewColorSubTableEXT) +#define glCopyColorSubTableEXT GLEW_GET_FUN(__glewCopyColorSubTableEXT) + +#define GLEW_EXT_color_subtable GLEW_GET_VAR(__GLEW_EXT_color_subtable) + +#endif /* GL_EXT_color_subtable */ + +/* ---------------------- GL_EXT_compiled_vertex_array --------------------- */ + +#ifndef GL_EXT_compiled_vertex_array +#define GL_EXT_compiled_vertex_array 1 + +#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8 +#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9 + +typedef void (GLAPIENTRY * PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count); +typedef void (GLAPIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void); + +#define glLockArraysEXT GLEW_GET_FUN(__glewLockArraysEXT) +#define glUnlockArraysEXT GLEW_GET_FUN(__glewUnlockArraysEXT) + +#define GLEW_EXT_compiled_vertex_array GLEW_GET_VAR(__GLEW_EXT_compiled_vertex_array) + +#endif /* GL_EXT_compiled_vertex_array */ + +/* --------------------------- GL_EXT_convolution -------------------------- */ + +#ifndef GL_EXT_convolution +#define GL_EXT_convolution 1 + +#define GL_CONVOLUTION_1D_EXT 0x8010 +#define GL_CONVOLUTION_2D_EXT 0x8011 +#define GL_SEPARABLE_2D_EXT 0x8012 +#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015 +#define GL_REDUCE_EXT 0x8016 +#define GL_CONVOLUTION_FORMAT_EXT 0x8017 +#define GL_CONVOLUTION_WIDTH_EXT 0x8018 +#define GL_CONVOLUTION_HEIGHT_EXT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 + +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* image); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* row, void* column, void* span); +typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* row, const void* column); + +#define glConvolutionFilter1DEXT GLEW_GET_FUN(__glewConvolutionFilter1DEXT) +#define glConvolutionFilter2DEXT GLEW_GET_FUN(__glewConvolutionFilter2DEXT) +#define glConvolutionParameterfEXT GLEW_GET_FUN(__glewConvolutionParameterfEXT) +#define glConvolutionParameterfvEXT GLEW_GET_FUN(__glewConvolutionParameterfvEXT) +#define glConvolutionParameteriEXT GLEW_GET_FUN(__glewConvolutionParameteriEXT) +#define glConvolutionParameterivEXT GLEW_GET_FUN(__glewConvolutionParameterivEXT) +#define glCopyConvolutionFilter1DEXT GLEW_GET_FUN(__glewCopyConvolutionFilter1DEXT) +#define glCopyConvolutionFilter2DEXT GLEW_GET_FUN(__glewCopyConvolutionFilter2DEXT) +#define glGetConvolutionFilterEXT GLEW_GET_FUN(__glewGetConvolutionFilterEXT) +#define glGetConvolutionParameterfvEXT GLEW_GET_FUN(__glewGetConvolutionParameterfvEXT) +#define glGetConvolutionParameterivEXT GLEW_GET_FUN(__glewGetConvolutionParameterivEXT) +#define glGetSeparableFilterEXT GLEW_GET_FUN(__glewGetSeparableFilterEXT) +#define glSeparableFilter2DEXT GLEW_GET_FUN(__glewSeparableFilter2DEXT) + +#define GLEW_EXT_convolution GLEW_GET_VAR(__GLEW_EXT_convolution) + +#endif /* GL_EXT_convolution */ + +/* ------------------------ GL_EXT_coordinate_frame ------------------------ */ + +#ifndef GL_EXT_coordinate_frame +#define GL_EXT_coordinate_frame 1 + +#define GL_TANGENT_ARRAY_EXT 0x8439 +#define GL_BINORMAL_ARRAY_EXT 0x843A +#define GL_CURRENT_TANGENT_EXT 0x843B +#define GL_CURRENT_BINORMAL_EXT 0x843C +#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E +#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F +#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440 +#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441 +#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442 +#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443 +#define GL_MAP1_TANGENT_EXT 0x8444 +#define GL_MAP2_TANGENT_EXT 0x8445 +#define GL_MAP1_BINORMAL_EXT 0x8446 +#define GL_MAP2_BINORMAL_EXT 0x8447 + +typedef void (GLAPIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer); +typedef void (GLAPIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer); + +#define glBinormalPointerEXT GLEW_GET_FUN(__glewBinormalPointerEXT) +#define glTangentPointerEXT GLEW_GET_FUN(__glewTangentPointerEXT) + +#define GLEW_EXT_coordinate_frame GLEW_GET_VAR(__GLEW_EXT_coordinate_frame) + +#endif /* GL_EXT_coordinate_frame */ + +/* -------------------------- GL_EXT_copy_texture -------------------------- */ + +#ifndef GL_EXT_copy_texture +#define GL_EXT_copy_texture 1 + +typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); + +#define glCopyTexImage1DEXT GLEW_GET_FUN(__glewCopyTexImage1DEXT) +#define glCopyTexImage2DEXT GLEW_GET_FUN(__glewCopyTexImage2DEXT) +#define glCopyTexSubImage1DEXT GLEW_GET_FUN(__glewCopyTexSubImage1DEXT) +#define glCopyTexSubImage2DEXT GLEW_GET_FUN(__glewCopyTexSubImage2DEXT) +#define glCopyTexSubImage3DEXT GLEW_GET_FUN(__glewCopyTexSubImage3DEXT) + +#define GLEW_EXT_copy_texture GLEW_GET_VAR(__GLEW_EXT_copy_texture) + +#endif /* GL_EXT_copy_texture */ + +/* --------------------------- GL_EXT_cull_vertex -------------------------- */ + +#ifndef GL_EXT_cull_vertex +#define GL_EXT_cull_vertex 1 + +#define GL_CULL_VERTEX_EXT 0x81AA +#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB +#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC + +typedef void (GLAPIENTRY * PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat* params); + +#define glCullParameterdvEXT GLEW_GET_FUN(__glewCullParameterdvEXT) +#define glCullParameterfvEXT GLEW_GET_FUN(__glewCullParameterfvEXT) + +#define GLEW_EXT_cull_vertex GLEW_GET_VAR(__GLEW_EXT_cull_vertex) + +#endif /* GL_EXT_cull_vertex */ + +/* ------------------------ GL_EXT_depth_bounds_test ----------------------- */ + +#ifndef GL_EXT_depth_bounds_test +#define GL_EXT_depth_bounds_test 1 + +#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890 +#define GL_DEPTH_BOUNDS_EXT 0x8891 + +typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax); + +#define glDepthBoundsEXT GLEW_GET_FUN(__glewDepthBoundsEXT) + +#define GLEW_EXT_depth_bounds_test GLEW_GET_VAR(__GLEW_EXT_depth_bounds_test) + +#endif /* GL_EXT_depth_bounds_test */ + +/* ----------------------- GL_EXT_direct_state_access ---------------------- */ + +#ifndef GL_EXT_direct_state_access +#define GL_EXT_direct_state_access 1 + +#define GL_PROGRAM_MATRIX_EXT 0x8E2D +#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E +#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F + +typedef void (GLAPIENTRY * PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture); +typedef GLenum (GLAPIENTRY * PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target); +typedef void (GLAPIENTRY * PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); +typedef void (GLAPIENTRY * PFNGLDISABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index); +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index); +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array); +typedef void (GLAPIENTRY * PFNGLENABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array); +typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuffer, GLsizei n, const GLenum* bufs); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); +typedef void (GLAPIENTRY * PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target); +typedef void (GLAPIENTRY * PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, void* img); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, void* img); +typedef void (GLAPIENTRY * PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint* param); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void* pixels); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, void** params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void* data); +typedef void (GLAPIENTRY * PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, void* string); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLvoid** params); +typedef void (GLAPIENTRY * PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, GLvoid** params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void* pixels); +typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint* param); +typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYINTEGERVEXTPROC) (GLuint vaobj, GLenum pname, GLint* param); +typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLvoid** param); +typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYPOINTERVEXTPROC) (GLuint vaobj, GLenum pname, GLvoid** param); +typedef GLvoid * (GLAPIENTRY * PFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access); +typedef GLvoid * (GLAPIENTRY * PFNGLMAPNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (GLAPIENTRY * PFNGLMATRIXFRUSTUMEXTPROC) (GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum matrixMode); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum matrixMode, const GLdouble* m); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADTRANSPOSEFEXTPROC) (GLenum matrixMode, const GLfloat* m); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADDEXTPROC) (GLenum matrixMode, const GLdouble* m); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADFEXTPROC) (GLenum matrixMode, const GLfloat* m); +typedef void (GLAPIENTRY * PFNGLMATRIXMULTTRANSPOSEDEXTPROC) (GLenum matrixMode, const GLdouble* m); +typedef void (GLAPIENTRY * PFNGLMATRIXMULTTRANSPOSEFEXTPROC) (GLenum matrixMode, const GLfloat* m); +typedef void (GLAPIENTRY * PFNGLMATRIXMULTDEXTPROC) (GLenum matrixMode, const GLdouble* m); +typedef void (GLAPIENTRY * PFNGLMATRIXMULTFEXTPROC) (GLenum matrixMode, const GLfloat* m); +typedef void (GLAPIENTRY * PFNGLMATRIXORTHOEXTPROC) (GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f); +typedef void (GLAPIENTRY * PFNGLMATRIXPOPEXTPROC) (GLenum matrixMode); +typedef void (GLAPIENTRY * PFNGLMATRIXPUSHEXTPROC) (GLenum matrixMode); +typedef void (GLAPIENTRY * PFNGLMATRIXROTATEDEXTPROC) (GLenum matrixMode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLMATRIXROTATEFEXTPROC) (GLenum matrixMode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLMATRIXSCALEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLMATRIXSCALEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENDEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble param); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* param); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* param); +typedef void (GLAPIENTRY * PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const void* data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void* data); +typedef void (GLAPIENTRY * PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const void* string); +typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); +typedef void (GLAPIENTRY * PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLfloat* param); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* param); +typedef void (GLAPIENTRY * PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); +typedef GLboolean (GLAPIENTRY * PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYINDEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum texunit, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYNORMALOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); + +#define glBindMultiTextureEXT GLEW_GET_FUN(__glewBindMultiTextureEXT) +#define glCheckNamedFramebufferStatusEXT GLEW_GET_FUN(__glewCheckNamedFramebufferStatusEXT) +#define glClientAttribDefaultEXT GLEW_GET_FUN(__glewClientAttribDefaultEXT) +#define glCompressedMultiTexImage1DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage1DEXT) +#define glCompressedMultiTexImage2DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage2DEXT) +#define glCompressedMultiTexImage3DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage3DEXT) +#define glCompressedMultiTexSubImage1DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage1DEXT) +#define glCompressedMultiTexSubImage2DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage2DEXT) +#define glCompressedMultiTexSubImage3DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage3DEXT) +#define glCompressedTextureImage1DEXT GLEW_GET_FUN(__glewCompressedTextureImage1DEXT) +#define glCompressedTextureImage2DEXT GLEW_GET_FUN(__glewCompressedTextureImage2DEXT) +#define glCompressedTextureImage3DEXT GLEW_GET_FUN(__glewCompressedTextureImage3DEXT) +#define glCompressedTextureSubImage1DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage1DEXT) +#define glCompressedTextureSubImage2DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage2DEXT) +#define glCompressedTextureSubImage3DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage3DEXT) +#define glCopyMultiTexImage1DEXT GLEW_GET_FUN(__glewCopyMultiTexImage1DEXT) +#define glCopyMultiTexImage2DEXT GLEW_GET_FUN(__glewCopyMultiTexImage2DEXT) +#define glCopyMultiTexSubImage1DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage1DEXT) +#define glCopyMultiTexSubImage2DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage2DEXT) +#define glCopyMultiTexSubImage3DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage3DEXT) +#define glCopyTextureImage1DEXT GLEW_GET_FUN(__glewCopyTextureImage1DEXT) +#define glCopyTextureImage2DEXT GLEW_GET_FUN(__glewCopyTextureImage2DEXT) +#define glCopyTextureSubImage1DEXT GLEW_GET_FUN(__glewCopyTextureSubImage1DEXT) +#define glCopyTextureSubImage2DEXT GLEW_GET_FUN(__glewCopyTextureSubImage2DEXT) +#define glCopyTextureSubImage3DEXT GLEW_GET_FUN(__glewCopyTextureSubImage3DEXT) +#define glDisableClientStateIndexedEXT GLEW_GET_FUN(__glewDisableClientStateIndexedEXT) +#define glDisableClientStateiEXT GLEW_GET_FUN(__glewDisableClientStateiEXT) +#define glDisableVertexArrayAttribEXT GLEW_GET_FUN(__glewDisableVertexArrayAttribEXT) +#define glDisableVertexArrayEXT GLEW_GET_FUN(__glewDisableVertexArrayEXT) +#define glEnableClientStateIndexedEXT GLEW_GET_FUN(__glewEnableClientStateIndexedEXT) +#define glEnableClientStateiEXT GLEW_GET_FUN(__glewEnableClientStateiEXT) +#define glEnableVertexArrayAttribEXT GLEW_GET_FUN(__glewEnableVertexArrayAttribEXT) +#define glEnableVertexArrayEXT GLEW_GET_FUN(__glewEnableVertexArrayEXT) +#define glFlushMappedNamedBufferRangeEXT GLEW_GET_FUN(__glewFlushMappedNamedBufferRangeEXT) +#define glFramebufferDrawBufferEXT GLEW_GET_FUN(__glewFramebufferDrawBufferEXT) +#define glFramebufferDrawBuffersEXT GLEW_GET_FUN(__glewFramebufferDrawBuffersEXT) +#define glFramebufferReadBufferEXT GLEW_GET_FUN(__glewFramebufferReadBufferEXT) +#define glGenerateMultiTexMipmapEXT GLEW_GET_FUN(__glewGenerateMultiTexMipmapEXT) +#define glGenerateTextureMipmapEXT GLEW_GET_FUN(__glewGenerateTextureMipmapEXT) +#define glGetCompressedMultiTexImageEXT GLEW_GET_FUN(__glewGetCompressedMultiTexImageEXT) +#define glGetCompressedTextureImageEXT GLEW_GET_FUN(__glewGetCompressedTextureImageEXT) +#define glGetDoubleIndexedvEXT GLEW_GET_FUN(__glewGetDoubleIndexedvEXT) +#define glGetDoublei_vEXT GLEW_GET_FUN(__glewGetDoublei_vEXT) +#define glGetFloatIndexedvEXT GLEW_GET_FUN(__glewGetFloatIndexedvEXT) +#define glGetFloati_vEXT GLEW_GET_FUN(__glewGetFloati_vEXT) +#define glGetFramebufferParameterivEXT GLEW_GET_FUN(__glewGetFramebufferParameterivEXT) +#define glGetMultiTexEnvfvEXT GLEW_GET_FUN(__glewGetMultiTexEnvfvEXT) +#define glGetMultiTexEnvivEXT GLEW_GET_FUN(__glewGetMultiTexEnvivEXT) +#define glGetMultiTexGendvEXT GLEW_GET_FUN(__glewGetMultiTexGendvEXT) +#define glGetMultiTexGenfvEXT GLEW_GET_FUN(__glewGetMultiTexGenfvEXT) +#define glGetMultiTexGenivEXT GLEW_GET_FUN(__glewGetMultiTexGenivEXT) +#define glGetMultiTexImageEXT GLEW_GET_FUN(__glewGetMultiTexImageEXT) +#define glGetMultiTexLevelParameterfvEXT GLEW_GET_FUN(__glewGetMultiTexLevelParameterfvEXT) +#define glGetMultiTexLevelParameterivEXT GLEW_GET_FUN(__glewGetMultiTexLevelParameterivEXT) +#define glGetMultiTexParameterIivEXT GLEW_GET_FUN(__glewGetMultiTexParameterIivEXT) +#define glGetMultiTexParameterIuivEXT GLEW_GET_FUN(__glewGetMultiTexParameterIuivEXT) +#define glGetMultiTexParameterfvEXT GLEW_GET_FUN(__glewGetMultiTexParameterfvEXT) +#define glGetMultiTexParameterivEXT GLEW_GET_FUN(__glewGetMultiTexParameterivEXT) +#define glGetNamedBufferParameterivEXT GLEW_GET_FUN(__glewGetNamedBufferParameterivEXT) +#define glGetNamedBufferPointervEXT GLEW_GET_FUN(__glewGetNamedBufferPointervEXT) +#define glGetNamedBufferSubDataEXT GLEW_GET_FUN(__glewGetNamedBufferSubDataEXT) +#define glGetNamedFramebufferAttachmentParameterivEXT GLEW_GET_FUN(__glewGetNamedFramebufferAttachmentParameterivEXT) +#define glGetNamedProgramLocalParameterIivEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterIivEXT) +#define glGetNamedProgramLocalParameterIuivEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterIuivEXT) +#define glGetNamedProgramLocalParameterdvEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterdvEXT) +#define glGetNamedProgramLocalParameterfvEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterfvEXT) +#define glGetNamedProgramStringEXT GLEW_GET_FUN(__glewGetNamedProgramStringEXT) +#define glGetNamedProgramivEXT GLEW_GET_FUN(__glewGetNamedProgramivEXT) +#define glGetNamedRenderbufferParameterivEXT GLEW_GET_FUN(__glewGetNamedRenderbufferParameterivEXT) +#define glGetPointerIndexedvEXT GLEW_GET_FUN(__glewGetPointerIndexedvEXT) +#define glGetPointeri_vEXT GLEW_GET_FUN(__glewGetPointeri_vEXT) +#define glGetTextureImageEXT GLEW_GET_FUN(__glewGetTextureImageEXT) +#define glGetTextureLevelParameterfvEXT GLEW_GET_FUN(__glewGetTextureLevelParameterfvEXT) +#define glGetTextureLevelParameterivEXT GLEW_GET_FUN(__glewGetTextureLevelParameterivEXT) +#define glGetTextureParameterIivEXT GLEW_GET_FUN(__glewGetTextureParameterIivEXT) +#define glGetTextureParameterIuivEXT GLEW_GET_FUN(__glewGetTextureParameterIuivEXT) +#define glGetTextureParameterfvEXT GLEW_GET_FUN(__glewGetTextureParameterfvEXT) +#define glGetTextureParameterivEXT GLEW_GET_FUN(__glewGetTextureParameterivEXT) +#define glGetVertexArrayIntegeri_vEXT GLEW_GET_FUN(__glewGetVertexArrayIntegeri_vEXT) +#define glGetVertexArrayIntegervEXT GLEW_GET_FUN(__glewGetVertexArrayIntegervEXT) +#define glGetVertexArrayPointeri_vEXT GLEW_GET_FUN(__glewGetVertexArrayPointeri_vEXT) +#define glGetVertexArrayPointervEXT GLEW_GET_FUN(__glewGetVertexArrayPointervEXT) +#define glMapNamedBufferEXT GLEW_GET_FUN(__glewMapNamedBufferEXT) +#define glMapNamedBufferRangeEXT GLEW_GET_FUN(__glewMapNamedBufferRangeEXT) +#define glMatrixFrustumEXT GLEW_GET_FUN(__glewMatrixFrustumEXT) +#define glMatrixLoadIdentityEXT GLEW_GET_FUN(__glewMatrixLoadIdentityEXT) +#define glMatrixLoadTransposedEXT GLEW_GET_FUN(__glewMatrixLoadTransposedEXT) +#define glMatrixLoadTransposefEXT GLEW_GET_FUN(__glewMatrixLoadTransposefEXT) +#define glMatrixLoaddEXT GLEW_GET_FUN(__glewMatrixLoaddEXT) +#define glMatrixLoadfEXT GLEW_GET_FUN(__glewMatrixLoadfEXT) +#define glMatrixMultTransposedEXT GLEW_GET_FUN(__glewMatrixMultTransposedEXT) +#define glMatrixMultTransposefEXT GLEW_GET_FUN(__glewMatrixMultTransposefEXT) +#define glMatrixMultdEXT GLEW_GET_FUN(__glewMatrixMultdEXT) +#define glMatrixMultfEXT GLEW_GET_FUN(__glewMatrixMultfEXT) +#define glMatrixOrthoEXT GLEW_GET_FUN(__glewMatrixOrthoEXT) +#define glMatrixPopEXT GLEW_GET_FUN(__glewMatrixPopEXT) +#define glMatrixPushEXT GLEW_GET_FUN(__glewMatrixPushEXT) +#define glMatrixRotatedEXT GLEW_GET_FUN(__glewMatrixRotatedEXT) +#define glMatrixRotatefEXT GLEW_GET_FUN(__glewMatrixRotatefEXT) +#define glMatrixScaledEXT GLEW_GET_FUN(__glewMatrixScaledEXT) +#define glMatrixScalefEXT GLEW_GET_FUN(__glewMatrixScalefEXT) +#define glMatrixTranslatedEXT GLEW_GET_FUN(__glewMatrixTranslatedEXT) +#define glMatrixTranslatefEXT GLEW_GET_FUN(__glewMatrixTranslatefEXT) +#define glMultiTexBufferEXT GLEW_GET_FUN(__glewMultiTexBufferEXT) +#define glMultiTexCoordPointerEXT GLEW_GET_FUN(__glewMultiTexCoordPointerEXT) +#define glMultiTexEnvfEXT GLEW_GET_FUN(__glewMultiTexEnvfEXT) +#define glMultiTexEnvfvEXT GLEW_GET_FUN(__glewMultiTexEnvfvEXT) +#define glMultiTexEnviEXT GLEW_GET_FUN(__glewMultiTexEnviEXT) +#define glMultiTexEnvivEXT GLEW_GET_FUN(__glewMultiTexEnvivEXT) +#define glMultiTexGendEXT GLEW_GET_FUN(__glewMultiTexGendEXT) +#define glMultiTexGendvEXT GLEW_GET_FUN(__glewMultiTexGendvEXT) +#define glMultiTexGenfEXT GLEW_GET_FUN(__glewMultiTexGenfEXT) +#define glMultiTexGenfvEXT GLEW_GET_FUN(__glewMultiTexGenfvEXT) +#define glMultiTexGeniEXT GLEW_GET_FUN(__glewMultiTexGeniEXT) +#define glMultiTexGenivEXT GLEW_GET_FUN(__glewMultiTexGenivEXT) +#define glMultiTexImage1DEXT GLEW_GET_FUN(__glewMultiTexImage1DEXT) +#define glMultiTexImage2DEXT GLEW_GET_FUN(__glewMultiTexImage2DEXT) +#define glMultiTexImage3DEXT GLEW_GET_FUN(__glewMultiTexImage3DEXT) +#define glMultiTexParameterIivEXT GLEW_GET_FUN(__glewMultiTexParameterIivEXT) +#define glMultiTexParameterIuivEXT GLEW_GET_FUN(__glewMultiTexParameterIuivEXT) +#define glMultiTexParameterfEXT GLEW_GET_FUN(__glewMultiTexParameterfEXT) +#define glMultiTexParameterfvEXT GLEW_GET_FUN(__glewMultiTexParameterfvEXT) +#define glMultiTexParameteriEXT GLEW_GET_FUN(__glewMultiTexParameteriEXT) +#define glMultiTexParameterivEXT GLEW_GET_FUN(__glewMultiTexParameterivEXT) +#define glMultiTexRenderbufferEXT GLEW_GET_FUN(__glewMultiTexRenderbufferEXT) +#define glMultiTexSubImage1DEXT GLEW_GET_FUN(__glewMultiTexSubImage1DEXT) +#define glMultiTexSubImage2DEXT GLEW_GET_FUN(__glewMultiTexSubImage2DEXT) +#define glMultiTexSubImage3DEXT GLEW_GET_FUN(__glewMultiTexSubImage3DEXT) +#define glNamedBufferDataEXT GLEW_GET_FUN(__glewNamedBufferDataEXT) +#define glNamedBufferSubDataEXT GLEW_GET_FUN(__glewNamedBufferSubDataEXT) +#define glNamedCopyBufferSubDataEXT GLEW_GET_FUN(__glewNamedCopyBufferSubDataEXT) +#define glNamedFramebufferRenderbufferEXT GLEW_GET_FUN(__glewNamedFramebufferRenderbufferEXT) +#define glNamedFramebufferTexture1DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture1DEXT) +#define glNamedFramebufferTexture2DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture2DEXT) +#define glNamedFramebufferTexture3DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture3DEXT) +#define glNamedFramebufferTextureEXT GLEW_GET_FUN(__glewNamedFramebufferTextureEXT) +#define glNamedFramebufferTextureFaceEXT GLEW_GET_FUN(__glewNamedFramebufferTextureFaceEXT) +#define glNamedFramebufferTextureLayerEXT GLEW_GET_FUN(__glewNamedFramebufferTextureLayerEXT) +#define glNamedProgramLocalParameter4dEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4dEXT) +#define glNamedProgramLocalParameter4dvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4dvEXT) +#define glNamedProgramLocalParameter4fEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4fEXT) +#define glNamedProgramLocalParameter4fvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4fvEXT) +#define glNamedProgramLocalParameterI4iEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4iEXT) +#define glNamedProgramLocalParameterI4ivEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4ivEXT) +#define glNamedProgramLocalParameterI4uiEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4uiEXT) +#define glNamedProgramLocalParameterI4uivEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4uivEXT) +#define glNamedProgramLocalParameters4fvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameters4fvEXT) +#define glNamedProgramLocalParametersI4ivEXT GLEW_GET_FUN(__glewNamedProgramLocalParametersI4ivEXT) +#define glNamedProgramLocalParametersI4uivEXT GLEW_GET_FUN(__glewNamedProgramLocalParametersI4uivEXT) +#define glNamedProgramStringEXT GLEW_GET_FUN(__glewNamedProgramStringEXT) +#define glNamedRenderbufferStorageEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageEXT) +#define glNamedRenderbufferStorageMultisampleCoverageEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageMultisampleCoverageEXT) +#define glNamedRenderbufferStorageMultisampleEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageMultisampleEXT) +#define glProgramUniform1fEXT GLEW_GET_FUN(__glewProgramUniform1fEXT) +#define glProgramUniform1fvEXT GLEW_GET_FUN(__glewProgramUniform1fvEXT) +#define glProgramUniform1iEXT GLEW_GET_FUN(__glewProgramUniform1iEXT) +#define glProgramUniform1ivEXT GLEW_GET_FUN(__glewProgramUniform1ivEXT) +#define glProgramUniform1uiEXT GLEW_GET_FUN(__glewProgramUniform1uiEXT) +#define glProgramUniform1uivEXT GLEW_GET_FUN(__glewProgramUniform1uivEXT) +#define glProgramUniform2fEXT GLEW_GET_FUN(__glewProgramUniform2fEXT) +#define glProgramUniform2fvEXT GLEW_GET_FUN(__glewProgramUniform2fvEXT) +#define glProgramUniform2iEXT GLEW_GET_FUN(__glewProgramUniform2iEXT) +#define glProgramUniform2ivEXT GLEW_GET_FUN(__glewProgramUniform2ivEXT) +#define glProgramUniform2uiEXT GLEW_GET_FUN(__glewProgramUniform2uiEXT) +#define glProgramUniform2uivEXT GLEW_GET_FUN(__glewProgramUniform2uivEXT) +#define glProgramUniform3fEXT GLEW_GET_FUN(__glewProgramUniform3fEXT) +#define glProgramUniform3fvEXT GLEW_GET_FUN(__glewProgramUniform3fvEXT) +#define glProgramUniform3iEXT GLEW_GET_FUN(__glewProgramUniform3iEXT) +#define glProgramUniform3ivEXT GLEW_GET_FUN(__glewProgramUniform3ivEXT) +#define glProgramUniform3uiEXT GLEW_GET_FUN(__glewProgramUniform3uiEXT) +#define glProgramUniform3uivEXT GLEW_GET_FUN(__glewProgramUniform3uivEXT) +#define glProgramUniform4fEXT GLEW_GET_FUN(__glewProgramUniform4fEXT) +#define glProgramUniform4fvEXT GLEW_GET_FUN(__glewProgramUniform4fvEXT) +#define glProgramUniform4iEXT GLEW_GET_FUN(__glewProgramUniform4iEXT) +#define glProgramUniform4ivEXT GLEW_GET_FUN(__glewProgramUniform4ivEXT) +#define glProgramUniform4uiEXT GLEW_GET_FUN(__glewProgramUniform4uiEXT) +#define glProgramUniform4uivEXT GLEW_GET_FUN(__glewProgramUniform4uivEXT) +#define glProgramUniformMatrix2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2fvEXT) +#define glProgramUniformMatrix2x3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x3fvEXT) +#define glProgramUniformMatrix2x4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x4fvEXT) +#define glProgramUniformMatrix3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3fvEXT) +#define glProgramUniformMatrix3x2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x2fvEXT) +#define glProgramUniformMatrix3x4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x4fvEXT) +#define glProgramUniformMatrix4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4fvEXT) +#define glProgramUniformMatrix4x2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x2fvEXT) +#define glProgramUniformMatrix4x3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x3fvEXT) +#define glPushClientAttribDefaultEXT GLEW_GET_FUN(__glewPushClientAttribDefaultEXT) +#define glTextureBufferEXT GLEW_GET_FUN(__glewTextureBufferEXT) +#define glTextureImage1DEXT GLEW_GET_FUN(__glewTextureImage1DEXT) +#define glTextureImage2DEXT GLEW_GET_FUN(__glewTextureImage2DEXT) +#define glTextureImage3DEXT GLEW_GET_FUN(__glewTextureImage3DEXT) +#define glTextureParameterIivEXT GLEW_GET_FUN(__glewTextureParameterIivEXT) +#define glTextureParameterIuivEXT GLEW_GET_FUN(__glewTextureParameterIuivEXT) +#define glTextureParameterfEXT GLEW_GET_FUN(__glewTextureParameterfEXT) +#define glTextureParameterfvEXT GLEW_GET_FUN(__glewTextureParameterfvEXT) +#define glTextureParameteriEXT GLEW_GET_FUN(__glewTextureParameteriEXT) +#define glTextureParameterivEXT GLEW_GET_FUN(__glewTextureParameterivEXT) +#define glTextureRenderbufferEXT GLEW_GET_FUN(__glewTextureRenderbufferEXT) +#define glTextureSubImage1DEXT GLEW_GET_FUN(__glewTextureSubImage1DEXT) +#define glTextureSubImage2DEXT GLEW_GET_FUN(__glewTextureSubImage2DEXT) +#define glTextureSubImage3DEXT GLEW_GET_FUN(__glewTextureSubImage3DEXT) +#define glUnmapNamedBufferEXT GLEW_GET_FUN(__glewUnmapNamedBufferEXT) +#define glVertexArrayColorOffsetEXT GLEW_GET_FUN(__glewVertexArrayColorOffsetEXT) +#define glVertexArrayEdgeFlagOffsetEXT GLEW_GET_FUN(__glewVertexArrayEdgeFlagOffsetEXT) +#define glVertexArrayFogCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayFogCoordOffsetEXT) +#define glVertexArrayIndexOffsetEXT GLEW_GET_FUN(__glewVertexArrayIndexOffsetEXT) +#define glVertexArrayMultiTexCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayMultiTexCoordOffsetEXT) +#define glVertexArrayNormalOffsetEXT GLEW_GET_FUN(__glewVertexArrayNormalOffsetEXT) +#define glVertexArraySecondaryColorOffsetEXT GLEW_GET_FUN(__glewVertexArraySecondaryColorOffsetEXT) +#define glVertexArrayTexCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayTexCoordOffsetEXT) +#define glVertexArrayVertexAttribIOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribIOffsetEXT) +#define glVertexArrayVertexAttribOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribOffsetEXT) +#define glVertexArrayVertexOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexOffsetEXT) + +#define GLEW_EXT_direct_state_access GLEW_GET_VAR(__GLEW_EXT_direct_state_access) + +#endif /* GL_EXT_direct_state_access */ + +/* -------------------------- GL_EXT_draw_buffers2 ------------------------- */ + +#ifndef GL_EXT_draw_buffers2 +#define GL_EXT_draw_buffers2 1 + +typedef void (GLAPIENTRY * PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint buf, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef void (GLAPIENTRY * PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index); +typedef void (GLAPIENTRY * PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum value, GLuint index, GLboolean* data); +typedef void (GLAPIENTRY * PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum value, GLuint index, GLint* data); +typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index); + +#define glColorMaskIndexedEXT GLEW_GET_FUN(__glewColorMaskIndexedEXT) +#define glDisableIndexedEXT GLEW_GET_FUN(__glewDisableIndexedEXT) +#define glEnableIndexedEXT GLEW_GET_FUN(__glewEnableIndexedEXT) +#define glGetBooleanIndexedvEXT GLEW_GET_FUN(__glewGetBooleanIndexedvEXT) +#define glGetIntegerIndexedvEXT GLEW_GET_FUN(__glewGetIntegerIndexedvEXT) +#define glIsEnabledIndexedEXT GLEW_GET_FUN(__glewIsEnabledIndexedEXT) + +#define GLEW_EXT_draw_buffers2 GLEW_GET_VAR(__GLEW_EXT_draw_buffers2) + +#endif /* GL_EXT_draw_buffers2 */ + +/* ------------------------- GL_EXT_draw_instanced ------------------------- */ + +#ifndef GL_EXT_draw_instanced +#define GL_EXT_draw_instanced 1 + +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); + +#define glDrawArraysInstancedEXT GLEW_GET_FUN(__glewDrawArraysInstancedEXT) +#define glDrawElementsInstancedEXT GLEW_GET_FUN(__glewDrawElementsInstancedEXT) + +#define GLEW_EXT_draw_instanced GLEW_GET_VAR(__GLEW_EXT_draw_instanced) + +#endif /* GL_EXT_draw_instanced */ + +/* ----------------------- GL_EXT_draw_range_elements ---------------------- */ + +#ifndef GL_EXT_draw_range_elements +#define GL_EXT_draw_range_elements 1 + +#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8 +#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9 + +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); + +#define glDrawRangeElementsEXT GLEW_GET_FUN(__glewDrawRangeElementsEXT) + +#define GLEW_EXT_draw_range_elements GLEW_GET_VAR(__GLEW_EXT_draw_range_elements) + +#endif /* GL_EXT_draw_range_elements */ + +/* ---------------------------- GL_EXT_fog_coord --------------------------- */ + +#ifndef GL_EXT_fog_coord +#define GL_EXT_fog_coord 1 + +#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450 +#define GL_FOG_COORDINATE_EXT 0x8451 +#define GL_FRAGMENT_DEPTH_EXT 0x8452 +#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456 +#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457 + +typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLFOGCOORDDEXTPROC) (GLdouble coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFEXTPROC) (GLfloat coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord); + +#define glFogCoordPointerEXT GLEW_GET_FUN(__glewFogCoordPointerEXT) +#define glFogCoorddEXT GLEW_GET_FUN(__glewFogCoorddEXT) +#define glFogCoorddvEXT GLEW_GET_FUN(__glewFogCoorddvEXT) +#define glFogCoordfEXT GLEW_GET_FUN(__glewFogCoordfEXT) +#define glFogCoordfvEXT GLEW_GET_FUN(__glewFogCoordfvEXT) + +#define GLEW_EXT_fog_coord GLEW_GET_VAR(__GLEW_EXT_fog_coord) + +#endif /* GL_EXT_fog_coord */ + +/* ------------------------ GL_EXT_fragment_lighting ----------------------- */ + +#ifndef GL_EXT_fragment_lighting +#define GL_EXT_fragment_lighting 1 + +#define GL_FRAGMENT_LIGHTING_EXT 0x8400 +#define GL_FRAGMENT_COLOR_MATERIAL_EXT 0x8401 +#define GL_FRAGMENT_COLOR_MATERIAL_FACE_EXT 0x8402 +#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_EXT 0x8403 +#define GL_MAX_FRAGMENT_LIGHTS_EXT 0x8404 +#define GL_MAX_ACTIVE_LIGHTS_EXT 0x8405 +#define GL_CURRENT_RASTER_NORMAL_EXT 0x8406 +#define GL_LIGHT_ENV_MODE_EXT 0x8407 +#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_EXT 0x8408 +#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_EXT 0x8409 +#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_EXT 0x840A +#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_EXT 0x840B +#define GL_FRAGMENT_LIGHT0_EXT 0x840C +#define GL_FRAGMENT_LIGHT7_EXT 0x8413 + +typedef void (GLAPIENTRY * PFNGLFRAGMENTCOLORMATERIALEXTPROC) (GLenum face, GLenum mode); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFEXTPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFVEXTPROC) (GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIEXTPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIVEXTPROC) (GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFEXTPROC) (GLenum light, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIEXTPROC) (GLenum light, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFEXTPROC) (GLenum face, GLenum pname, const GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIEXTPROC) (GLenum face, GLenum pname, const GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLLIGHTENVIEXTPROC) (GLenum pname, GLint param); + +#define glFragmentColorMaterialEXT GLEW_GET_FUN(__glewFragmentColorMaterialEXT) +#define glFragmentLightModelfEXT GLEW_GET_FUN(__glewFragmentLightModelfEXT) +#define glFragmentLightModelfvEXT GLEW_GET_FUN(__glewFragmentLightModelfvEXT) +#define glFragmentLightModeliEXT GLEW_GET_FUN(__glewFragmentLightModeliEXT) +#define glFragmentLightModelivEXT GLEW_GET_FUN(__glewFragmentLightModelivEXT) +#define glFragmentLightfEXT GLEW_GET_FUN(__glewFragmentLightfEXT) +#define glFragmentLightfvEXT GLEW_GET_FUN(__glewFragmentLightfvEXT) +#define glFragmentLightiEXT GLEW_GET_FUN(__glewFragmentLightiEXT) +#define glFragmentLightivEXT GLEW_GET_FUN(__glewFragmentLightivEXT) +#define glFragmentMaterialfEXT GLEW_GET_FUN(__glewFragmentMaterialfEXT) +#define glFragmentMaterialfvEXT GLEW_GET_FUN(__glewFragmentMaterialfvEXT) +#define glFragmentMaterialiEXT GLEW_GET_FUN(__glewFragmentMaterialiEXT) +#define glFragmentMaterialivEXT GLEW_GET_FUN(__glewFragmentMaterialivEXT) +#define glGetFragmentLightfvEXT GLEW_GET_FUN(__glewGetFragmentLightfvEXT) +#define glGetFragmentLightivEXT GLEW_GET_FUN(__glewGetFragmentLightivEXT) +#define glGetFragmentMaterialfvEXT GLEW_GET_FUN(__glewGetFragmentMaterialfvEXT) +#define glGetFragmentMaterialivEXT GLEW_GET_FUN(__glewGetFragmentMaterialivEXT) +#define glLightEnviEXT GLEW_GET_FUN(__glewLightEnviEXT) + +#define GLEW_EXT_fragment_lighting GLEW_GET_VAR(__GLEW_EXT_fragment_lighting) + +#endif /* GL_EXT_fragment_lighting */ + +/* ------------------------ GL_EXT_framebuffer_blit ------------------------ */ + +#ifndef GL_EXT_framebuffer_blit +#define GL_EXT_framebuffer_blit 1 + +#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_READ_FRAMEBUFFER_EXT 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA + +typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + +#define glBlitFramebufferEXT GLEW_GET_FUN(__glewBlitFramebufferEXT) + +#define GLEW_EXT_framebuffer_blit GLEW_GET_VAR(__GLEW_EXT_framebuffer_blit) + +#endif /* GL_EXT_framebuffer_blit */ + +/* --------------------- GL_EXT_framebuffer_multisample -------------------- */ + +#ifndef GL_EXT_framebuffer_multisample +#define GL_EXT_framebuffer_multisample 1 + +#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 +#define GL_MAX_SAMPLES_EXT 0x8D57 + +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + +#define glRenderbufferStorageMultisampleEXT GLEW_GET_FUN(__glewRenderbufferStorageMultisampleEXT) + +#define GLEW_EXT_framebuffer_multisample GLEW_GET_VAR(__GLEW_EXT_framebuffer_multisample) + +#endif /* GL_EXT_framebuffer_multisample */ + +/* ----------------------- GL_EXT_framebuffer_object ----------------------- */ + +#ifndef GL_EXT_framebuffer_object +#define GL_EXT_framebuffer_object 1 + +#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 +#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 +#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 +#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF +#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 +#define GL_STENCIL_ATTACHMENT_EXT 0x8D20 +#define GL_FRAMEBUFFER_EXT 0x8D40 +#define GL_RENDERBUFFER_EXT 0x8D41 +#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 +#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 +#define GL_STENCIL_INDEX1_EXT 0x8D46 +#define GL_STENCIL_INDEX4_EXT 0x8D47 +#define GL_STENCIL_INDEX8_EXT 0x8D48 +#define GL_STENCIL_INDEX16_EXT 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55 + +typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer); +typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer); +typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint* framebuffers); +typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint* renderbuffers); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint* framebuffers); +typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint* renderbuffers); +typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPEXTPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer); +typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + +#define glBindFramebufferEXT GLEW_GET_FUN(__glewBindFramebufferEXT) +#define glBindRenderbufferEXT GLEW_GET_FUN(__glewBindRenderbufferEXT) +#define glCheckFramebufferStatusEXT GLEW_GET_FUN(__glewCheckFramebufferStatusEXT) +#define glDeleteFramebuffersEXT GLEW_GET_FUN(__glewDeleteFramebuffersEXT) +#define glDeleteRenderbuffersEXT GLEW_GET_FUN(__glewDeleteRenderbuffersEXT) +#define glFramebufferRenderbufferEXT GLEW_GET_FUN(__glewFramebufferRenderbufferEXT) +#define glFramebufferTexture1DEXT GLEW_GET_FUN(__glewFramebufferTexture1DEXT) +#define glFramebufferTexture2DEXT GLEW_GET_FUN(__glewFramebufferTexture2DEXT) +#define glFramebufferTexture3DEXT GLEW_GET_FUN(__glewFramebufferTexture3DEXT) +#define glGenFramebuffersEXT GLEW_GET_FUN(__glewGenFramebuffersEXT) +#define glGenRenderbuffersEXT GLEW_GET_FUN(__glewGenRenderbuffersEXT) +#define glGenerateMipmapEXT GLEW_GET_FUN(__glewGenerateMipmapEXT) +#define glGetFramebufferAttachmentParameterivEXT GLEW_GET_FUN(__glewGetFramebufferAttachmentParameterivEXT) +#define glGetRenderbufferParameterivEXT GLEW_GET_FUN(__glewGetRenderbufferParameterivEXT) +#define glIsFramebufferEXT GLEW_GET_FUN(__glewIsFramebufferEXT) +#define glIsRenderbufferEXT GLEW_GET_FUN(__glewIsRenderbufferEXT) +#define glRenderbufferStorageEXT GLEW_GET_FUN(__glewRenderbufferStorageEXT) + +#define GLEW_EXT_framebuffer_object GLEW_GET_VAR(__GLEW_EXT_framebuffer_object) + +#endif /* GL_EXT_framebuffer_object */ + +/* ------------------------ GL_EXT_framebuffer_sRGB ------------------------ */ + +#ifndef GL_EXT_framebuffer_sRGB +#define GL_EXT_framebuffer_sRGB 1 + +#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 +#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA + +#define GLEW_EXT_framebuffer_sRGB GLEW_GET_VAR(__GLEW_EXT_framebuffer_sRGB) + +#endif /* GL_EXT_framebuffer_sRGB */ + +/* ------------------------ GL_EXT_geometry_shader4 ------------------------ */ + +#ifndef GL_EXT_geometry_shader4 +#define GL_EXT_geometry_shader4 1 + +#define GL_LINES_ADJACENCY_EXT 0xA +#define GL_LINE_STRIP_ADJACENCY_EXT 0xB +#define GL_TRIANGLES_ADJACENCY_EXT 0xC +#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD +#define GL_PROGRAM_POINT_SIZE_EXT 0x8642 +#define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9 +#define GL_GEOMETRY_SHADER_EXT 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA +#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD +#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1 + +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); + +#define glFramebufferTextureEXT GLEW_GET_FUN(__glewFramebufferTextureEXT) +#define glFramebufferTextureFaceEXT GLEW_GET_FUN(__glewFramebufferTextureFaceEXT) +#define glProgramParameteriEXT GLEW_GET_FUN(__glewProgramParameteriEXT) + +#define GLEW_EXT_geometry_shader4 GLEW_GET_VAR(__GLEW_EXT_geometry_shader4) + +#endif /* GL_EXT_geometry_shader4 */ + +/* --------------------- GL_EXT_gpu_program_parameters --------------------- */ + +#ifndef GL_EXT_gpu_program_parameters +#define GL_EXT_gpu_program_parameters 1 + +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat* params); + +#define glProgramEnvParameters4fvEXT GLEW_GET_FUN(__glewProgramEnvParameters4fvEXT) +#define glProgramLocalParameters4fvEXT GLEW_GET_FUN(__glewProgramLocalParameters4fvEXT) + +#define GLEW_EXT_gpu_program_parameters GLEW_GET_VAR(__GLEW_EXT_gpu_program_parameters) + +#endif /* GL_EXT_gpu_program_parameters */ + +/* --------------------------- GL_EXT_gpu_shader4 -------------------------- */ + +#ifndef GL_EXT_gpu_shader4 +#define GL_EXT_gpu_shader4 1 + +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD +#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0 +#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1 +#define GL_SAMPLER_BUFFER_EXT 0x8DC2 +#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5 +#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6 +#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7 +#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8 +#define GL_INT_SAMPLER_1D_EXT 0x8DC9 +#define GL_INT_SAMPLER_2D_EXT 0x8DCA +#define GL_INT_SAMPLER_3D_EXT 0x8DCB +#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC +#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD +#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF +#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8 + +typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name); +typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + +#define glBindFragDataLocationEXT GLEW_GET_FUN(__glewBindFragDataLocationEXT) +#define glGetFragDataLocationEXT GLEW_GET_FUN(__glewGetFragDataLocationEXT) +#define glGetUniformuivEXT GLEW_GET_FUN(__glewGetUniformuivEXT) +#define glGetVertexAttribIivEXT GLEW_GET_FUN(__glewGetVertexAttribIivEXT) +#define glGetVertexAttribIuivEXT GLEW_GET_FUN(__glewGetVertexAttribIuivEXT) +#define glUniform1uiEXT GLEW_GET_FUN(__glewUniform1uiEXT) +#define glUniform1uivEXT GLEW_GET_FUN(__glewUniform1uivEXT) +#define glUniform2uiEXT GLEW_GET_FUN(__glewUniform2uiEXT) +#define glUniform2uivEXT GLEW_GET_FUN(__glewUniform2uivEXT) +#define glUniform3uiEXT GLEW_GET_FUN(__glewUniform3uiEXT) +#define glUniform3uivEXT GLEW_GET_FUN(__glewUniform3uivEXT) +#define glUniform4uiEXT GLEW_GET_FUN(__glewUniform4uiEXT) +#define glUniform4uivEXT GLEW_GET_FUN(__glewUniform4uivEXT) +#define glVertexAttribI1iEXT GLEW_GET_FUN(__glewVertexAttribI1iEXT) +#define glVertexAttribI1ivEXT GLEW_GET_FUN(__glewVertexAttribI1ivEXT) +#define glVertexAttribI1uiEXT GLEW_GET_FUN(__glewVertexAttribI1uiEXT) +#define glVertexAttribI1uivEXT GLEW_GET_FUN(__glewVertexAttribI1uivEXT) +#define glVertexAttribI2iEXT GLEW_GET_FUN(__glewVertexAttribI2iEXT) +#define glVertexAttribI2ivEXT GLEW_GET_FUN(__glewVertexAttribI2ivEXT) +#define glVertexAttribI2uiEXT GLEW_GET_FUN(__glewVertexAttribI2uiEXT) +#define glVertexAttribI2uivEXT GLEW_GET_FUN(__glewVertexAttribI2uivEXT) +#define glVertexAttribI3iEXT GLEW_GET_FUN(__glewVertexAttribI3iEXT) +#define glVertexAttribI3ivEXT GLEW_GET_FUN(__glewVertexAttribI3ivEXT) +#define glVertexAttribI3uiEXT GLEW_GET_FUN(__glewVertexAttribI3uiEXT) +#define glVertexAttribI3uivEXT GLEW_GET_FUN(__glewVertexAttribI3uivEXT) +#define glVertexAttribI4bvEXT GLEW_GET_FUN(__glewVertexAttribI4bvEXT) +#define glVertexAttribI4iEXT GLEW_GET_FUN(__glewVertexAttribI4iEXT) +#define glVertexAttribI4ivEXT GLEW_GET_FUN(__glewVertexAttribI4ivEXT) +#define glVertexAttribI4svEXT GLEW_GET_FUN(__glewVertexAttribI4svEXT) +#define glVertexAttribI4ubvEXT GLEW_GET_FUN(__glewVertexAttribI4ubvEXT) +#define glVertexAttribI4uiEXT GLEW_GET_FUN(__glewVertexAttribI4uiEXT) +#define glVertexAttribI4uivEXT GLEW_GET_FUN(__glewVertexAttribI4uivEXT) +#define glVertexAttribI4usvEXT GLEW_GET_FUN(__glewVertexAttribI4usvEXT) +#define glVertexAttribIPointerEXT GLEW_GET_FUN(__glewVertexAttribIPointerEXT) + +#define GLEW_EXT_gpu_shader4 GLEW_GET_VAR(__GLEW_EXT_gpu_shader4) + +#endif /* GL_EXT_gpu_shader4 */ + +/* ---------------------------- GL_EXT_histogram --------------------------- */ + +#ifndef GL_EXT_histogram +#define GL_EXT_histogram 1 + +#define GL_HISTOGRAM_EXT 0x8024 +#define GL_PROXY_HISTOGRAM_EXT 0x8025 +#define GL_HISTOGRAM_WIDTH_EXT 0x8026 +#define GL_HISTOGRAM_FORMAT_EXT 0x8027 +#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C +#define GL_HISTOGRAM_SINK_EXT 0x802D +#define GL_MINMAX_EXT 0x802E +#define GL_MINMAX_FORMAT_EXT 0x802F +#define GL_MINMAX_SINK_EXT 0x8030 + +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRY * PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMEXTPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLRESETMINMAXEXTPROC) (GLenum target); + +#define glGetHistogramEXT GLEW_GET_FUN(__glewGetHistogramEXT) +#define glGetHistogramParameterfvEXT GLEW_GET_FUN(__glewGetHistogramParameterfvEXT) +#define glGetHistogramParameterivEXT GLEW_GET_FUN(__glewGetHistogramParameterivEXT) +#define glGetMinmaxEXT GLEW_GET_FUN(__glewGetMinmaxEXT) +#define glGetMinmaxParameterfvEXT GLEW_GET_FUN(__glewGetMinmaxParameterfvEXT) +#define glGetMinmaxParameterivEXT GLEW_GET_FUN(__glewGetMinmaxParameterivEXT) +#define glHistogramEXT GLEW_GET_FUN(__glewHistogramEXT) +#define glMinmaxEXT GLEW_GET_FUN(__glewMinmaxEXT) +#define glResetHistogramEXT GLEW_GET_FUN(__glewResetHistogramEXT) +#define glResetMinmaxEXT GLEW_GET_FUN(__glewResetMinmaxEXT) + +#define GLEW_EXT_histogram GLEW_GET_VAR(__GLEW_EXT_histogram) + +#endif /* GL_EXT_histogram */ + +/* ----------------------- GL_EXT_index_array_formats ---------------------- */ + +#ifndef GL_EXT_index_array_formats +#define GL_EXT_index_array_formats 1 + +#define GLEW_EXT_index_array_formats GLEW_GET_VAR(__GLEW_EXT_index_array_formats) + +#endif /* GL_EXT_index_array_formats */ + +/* --------------------------- GL_EXT_index_func --------------------------- */ + +#ifndef GL_EXT_index_func +#define GL_EXT_index_func 1 + +typedef void (GLAPIENTRY * PFNGLINDEXFUNCEXTPROC) (GLenum func, GLfloat ref); + +#define glIndexFuncEXT GLEW_GET_FUN(__glewIndexFuncEXT) + +#define GLEW_EXT_index_func GLEW_GET_VAR(__GLEW_EXT_index_func) + +#endif /* GL_EXT_index_func */ + +/* ------------------------- GL_EXT_index_material ------------------------- */ + +#ifndef GL_EXT_index_material +#define GL_EXT_index_material 1 + +typedef void (GLAPIENTRY * PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode); + +#define glIndexMaterialEXT GLEW_GET_FUN(__glewIndexMaterialEXT) + +#define GLEW_EXT_index_material GLEW_GET_VAR(__GLEW_EXT_index_material) + +#endif /* GL_EXT_index_material */ + +/* -------------------------- GL_EXT_index_texture ------------------------- */ + +#ifndef GL_EXT_index_texture +#define GL_EXT_index_texture 1 + +#define GLEW_EXT_index_texture GLEW_GET_VAR(__GLEW_EXT_index_texture) + +#endif /* GL_EXT_index_texture */ + +/* -------------------------- GL_EXT_light_texture ------------------------- */ + +#ifndef GL_EXT_light_texture +#define GL_EXT_light_texture 1 + +#define GL_FRAGMENT_MATERIAL_EXT 0x8349 +#define GL_FRAGMENT_NORMAL_EXT 0x834A +#define GL_FRAGMENT_COLOR_EXT 0x834C +#define GL_ATTENUATION_EXT 0x834D +#define GL_SHADOW_ATTENUATION_EXT 0x834E +#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F +#define GL_TEXTURE_LIGHT_EXT 0x8350 +#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351 +#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352 +#define GL_FRAGMENT_DEPTH_EXT 0x8452 + +typedef void (GLAPIENTRY * PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode); +typedef void (GLAPIENTRY * PFNGLTEXTURELIGHTEXTPROC) (GLenum pname); +typedef void (GLAPIENTRY * PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode); + +#define glApplyTextureEXT GLEW_GET_FUN(__glewApplyTextureEXT) +#define glTextureLightEXT GLEW_GET_FUN(__glewTextureLightEXT) +#define glTextureMaterialEXT GLEW_GET_FUN(__glewTextureMaterialEXT) + +#define GLEW_EXT_light_texture GLEW_GET_VAR(__GLEW_EXT_light_texture) + +#endif /* GL_EXT_light_texture */ + +/* ------------------------- GL_EXT_misc_attribute ------------------------- */ + +#ifndef GL_EXT_misc_attribute +#define GL_EXT_misc_attribute 1 + +#define GLEW_EXT_misc_attribute GLEW_GET_VAR(__GLEW_EXT_misc_attribute) + +#endif /* GL_EXT_misc_attribute */ + +/* ------------------------ GL_EXT_multi_draw_arrays ----------------------- */ + +#ifndef GL_EXT_multi_draw_arrays +#define GL_EXT_multi_draw_arrays 1 + +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, GLsizei* count, GLenum type, const GLvoid **indices, GLsizei primcount); + +#define glMultiDrawArraysEXT GLEW_GET_FUN(__glewMultiDrawArraysEXT) +#define glMultiDrawElementsEXT GLEW_GET_FUN(__glewMultiDrawElementsEXT) + +#define GLEW_EXT_multi_draw_arrays GLEW_GET_VAR(__GLEW_EXT_multi_draw_arrays) + +#endif /* GL_EXT_multi_draw_arrays */ + +/* --------------------------- GL_EXT_multisample -------------------------- */ + +#ifndef GL_EXT_multisample +#define GL_EXT_multisample 1 + +#define GL_MULTISAMPLE_EXT 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F +#define GL_SAMPLE_MASK_EXT 0x80A0 +#define GL_1PASS_EXT 0x80A1 +#define GL_2PASS_0_EXT 0x80A2 +#define GL_2PASS_1_EXT 0x80A3 +#define GL_4PASS_0_EXT 0x80A4 +#define GL_4PASS_1_EXT 0x80A5 +#define GL_4PASS_2_EXT 0x80A6 +#define GL_4PASS_3_EXT 0x80A7 +#define GL_SAMPLE_BUFFERS_EXT 0x80A8 +#define GL_SAMPLES_EXT 0x80A9 +#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA +#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB +#define GL_SAMPLE_PATTERN_EXT 0x80AC +#define GL_MULTISAMPLE_BIT_EXT 0x20000000 + +typedef void (GLAPIENTRY * PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert); +typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); + +#define glSampleMaskEXT GLEW_GET_FUN(__glewSampleMaskEXT) +#define glSamplePatternEXT GLEW_GET_FUN(__glewSamplePatternEXT) + +#define GLEW_EXT_multisample GLEW_GET_VAR(__GLEW_EXT_multisample) + +#endif /* GL_EXT_multisample */ + +/* ---------------------- GL_EXT_packed_depth_stencil ---------------------- */ + +#ifndef GL_EXT_packed_depth_stencil +#define GL_EXT_packed_depth_stencil 1 + +#define GL_DEPTH_STENCIL_EXT 0x84F9 +#define GL_UNSIGNED_INT_24_8_EXT 0x84FA +#define GL_DEPTH24_STENCIL8_EXT 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1 + +#define GLEW_EXT_packed_depth_stencil GLEW_GET_VAR(__GLEW_EXT_packed_depth_stencil) + +#endif /* GL_EXT_packed_depth_stencil */ + +/* -------------------------- GL_EXT_packed_float -------------------------- */ + +#ifndef GL_EXT_packed_float +#define GL_EXT_packed_float 1 + +#define GL_R11F_G11F_B10F_EXT 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B +#define GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C + +#define GLEW_EXT_packed_float GLEW_GET_VAR(__GLEW_EXT_packed_float) + +#endif /* GL_EXT_packed_float */ + +/* -------------------------- GL_EXT_packed_pixels ------------------------- */ + +#ifndef GL_EXT_packed_pixels +#define GL_EXT_packed_pixels 1 + +#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036 + +#define GLEW_EXT_packed_pixels GLEW_GET_VAR(__GLEW_EXT_packed_pixels) + +#endif /* GL_EXT_packed_pixels */ + +/* ------------------------ GL_EXT_paletted_texture ------------------------ */ + +#ifndef GL_EXT_paletted_texture +#define GL_EXT_paletted_texture 1 + +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_TEXTURE_3D_EXT 0x806F +#define GL_PROXY_TEXTURE_3D_EXT 0x8070 +#define GL_COLOR_TABLE_FORMAT_EXT 0x80D8 +#define GL_COLOR_TABLE_WIDTH_EXT 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE_EXT 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE_EXT 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE_EXT 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE_EXT 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE_EXT 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE_EXT 0x80DF +#define GL_COLOR_INDEX1_EXT 0x80E2 +#define GL_COLOR_INDEX2_EXT 0x80E3 +#define GL_COLOR_INDEX4_EXT 0x80E4 +#define GL_COLOR_INDEX8_EXT 0x80E5 +#define GL_COLOR_INDEX12_EXT 0x80E6 +#define GL_COLOR_INDEX16_EXT 0x80E7 +#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED +#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 +#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B + +typedef void (GLAPIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void* data); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, void* data); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); + +#define glColorTableEXT GLEW_GET_FUN(__glewColorTableEXT) +#define glGetColorTableEXT GLEW_GET_FUN(__glewGetColorTableEXT) +#define glGetColorTableParameterfvEXT GLEW_GET_FUN(__glewGetColorTableParameterfvEXT) +#define glGetColorTableParameterivEXT GLEW_GET_FUN(__glewGetColorTableParameterivEXT) + +#define GLEW_EXT_paletted_texture GLEW_GET_VAR(__GLEW_EXT_paletted_texture) + +#endif /* GL_EXT_paletted_texture */ + +/* ----------------------- GL_EXT_pixel_buffer_object ---------------------- */ + +#ifndef GL_EXT_pixel_buffer_object +#define GL_EXT_pixel_buffer_object 1 + +#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF + +#define GLEW_EXT_pixel_buffer_object GLEW_GET_VAR(__GLEW_EXT_pixel_buffer_object) + +#endif /* GL_EXT_pixel_buffer_object */ + +/* ------------------------- GL_EXT_pixel_transform ------------------------ */ + +#ifndef GL_EXT_pixel_transform +#define GL_EXT_pixel_transform 1 + +#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330 +#define GL_PIXEL_MAG_FILTER_EXT 0x8331 +#define GL_PIXEL_MIN_FILTER_EXT 0x8332 +#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333 +#define GL_CUBIC_EXT 0x8334 +#define GL_AVERAGE_EXT 0x8335 +#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336 +#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337 +#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338 + +typedef void (GLAPIENTRY * PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, const GLfloat param); +typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, const GLint param); +typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); + +#define glGetPixelTransformParameterfvEXT GLEW_GET_FUN(__glewGetPixelTransformParameterfvEXT) +#define glGetPixelTransformParameterivEXT GLEW_GET_FUN(__glewGetPixelTransformParameterivEXT) +#define glPixelTransformParameterfEXT GLEW_GET_FUN(__glewPixelTransformParameterfEXT) +#define glPixelTransformParameterfvEXT GLEW_GET_FUN(__glewPixelTransformParameterfvEXT) +#define glPixelTransformParameteriEXT GLEW_GET_FUN(__glewPixelTransformParameteriEXT) +#define glPixelTransformParameterivEXT GLEW_GET_FUN(__glewPixelTransformParameterivEXT) + +#define GLEW_EXT_pixel_transform GLEW_GET_VAR(__GLEW_EXT_pixel_transform) + +#endif /* GL_EXT_pixel_transform */ + +/* ------------------- GL_EXT_pixel_transform_color_table ------------------ */ + +#ifndef GL_EXT_pixel_transform_color_table +#define GL_EXT_pixel_transform_color_table 1 + +#define GLEW_EXT_pixel_transform_color_table GLEW_GET_VAR(__GLEW_EXT_pixel_transform_color_table) + +#endif /* GL_EXT_pixel_transform_color_table */ + +/* ------------------------ GL_EXT_point_parameters ------------------------ */ + +#ifndef GL_EXT_point_parameters +#define GL_EXT_point_parameters 1 + +#define GL_POINT_SIZE_MIN_EXT 0x8126 +#define GL_POINT_SIZE_MAX_EXT 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 +#define GL_DISTANCE_ATTENUATION_EXT 0x8129 + +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat* params); + +#define glPointParameterfEXT GLEW_GET_FUN(__glewPointParameterfEXT) +#define glPointParameterfvEXT GLEW_GET_FUN(__glewPointParameterfvEXT) + +#define GLEW_EXT_point_parameters GLEW_GET_VAR(__GLEW_EXT_point_parameters) + +#endif /* GL_EXT_point_parameters */ + +/* ------------------------- GL_EXT_polygon_offset ------------------------- */ + +#ifndef GL_EXT_polygon_offset +#define GL_EXT_polygon_offset 1 + +#define GL_POLYGON_OFFSET_EXT 0x8037 +#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038 +#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039 + +typedef void (GLAPIENTRY * PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias); + +#define glPolygonOffsetEXT GLEW_GET_FUN(__glewPolygonOffsetEXT) + +#define GLEW_EXT_polygon_offset GLEW_GET_VAR(__GLEW_EXT_polygon_offset) + +#endif /* GL_EXT_polygon_offset */ + +/* ------------------------ GL_EXT_provoking_vertex ------------------------ */ + +#ifndef GL_EXT_provoking_vertex +#define GL_EXT_provoking_vertex 1 + +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C +#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D +#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E +#define GL_PROVOKING_VERTEX_EXT 0x8E4F + +typedef void (GLAPIENTRY * PFNGLPROVOKINGVERTEXEXTPROC) (GLenum mode); + +#define glProvokingVertexEXT GLEW_GET_FUN(__glewProvokingVertexEXT) + +#define GLEW_EXT_provoking_vertex GLEW_GET_VAR(__GLEW_EXT_provoking_vertex) + +#endif /* GL_EXT_provoking_vertex */ + +/* ------------------------- GL_EXT_rescale_normal ------------------------- */ + +#ifndef GL_EXT_rescale_normal +#define GL_EXT_rescale_normal 1 + +#define GL_RESCALE_NORMAL_EXT 0x803A + +#define GLEW_EXT_rescale_normal GLEW_GET_VAR(__GLEW_EXT_rescale_normal) + +#endif /* GL_EXT_rescale_normal */ + +/* -------------------------- GL_EXT_scene_marker -------------------------- */ + +#ifndef GL_EXT_scene_marker +#define GL_EXT_scene_marker 1 + +typedef void (GLAPIENTRY * PFNGLBEGINSCENEEXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLENDSCENEEXTPROC) (void); + +#define glBeginSceneEXT GLEW_GET_FUN(__glewBeginSceneEXT) +#define glEndSceneEXT GLEW_GET_FUN(__glewEndSceneEXT) + +#define GLEW_EXT_scene_marker GLEW_GET_VAR(__GLEW_EXT_scene_marker) + +#endif /* GL_EXT_scene_marker */ + +/* ------------------------- GL_EXT_secondary_color ------------------------ */ + +#ifndef GL_EXT_secondary_color +#define GL_EXT_secondary_color 1 + +#define GL_COLOR_SUM_EXT 0x8458 +#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D +#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E + +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + +#define glSecondaryColor3bEXT GLEW_GET_FUN(__glewSecondaryColor3bEXT) +#define glSecondaryColor3bvEXT GLEW_GET_FUN(__glewSecondaryColor3bvEXT) +#define glSecondaryColor3dEXT GLEW_GET_FUN(__glewSecondaryColor3dEXT) +#define glSecondaryColor3dvEXT GLEW_GET_FUN(__glewSecondaryColor3dvEXT) +#define glSecondaryColor3fEXT GLEW_GET_FUN(__glewSecondaryColor3fEXT) +#define glSecondaryColor3fvEXT GLEW_GET_FUN(__glewSecondaryColor3fvEXT) +#define glSecondaryColor3iEXT GLEW_GET_FUN(__glewSecondaryColor3iEXT) +#define glSecondaryColor3ivEXT GLEW_GET_FUN(__glewSecondaryColor3ivEXT) +#define glSecondaryColor3sEXT GLEW_GET_FUN(__glewSecondaryColor3sEXT) +#define glSecondaryColor3svEXT GLEW_GET_FUN(__glewSecondaryColor3svEXT) +#define glSecondaryColor3ubEXT GLEW_GET_FUN(__glewSecondaryColor3ubEXT) +#define glSecondaryColor3ubvEXT GLEW_GET_FUN(__glewSecondaryColor3ubvEXT) +#define glSecondaryColor3uiEXT GLEW_GET_FUN(__glewSecondaryColor3uiEXT) +#define glSecondaryColor3uivEXT GLEW_GET_FUN(__glewSecondaryColor3uivEXT) +#define glSecondaryColor3usEXT GLEW_GET_FUN(__glewSecondaryColor3usEXT) +#define glSecondaryColor3usvEXT GLEW_GET_FUN(__glewSecondaryColor3usvEXT) +#define glSecondaryColorPointerEXT GLEW_GET_FUN(__glewSecondaryColorPointerEXT) + +#define GLEW_EXT_secondary_color GLEW_GET_VAR(__GLEW_EXT_secondary_color) + +#endif /* GL_EXT_secondary_color */ + +/* --------------------- GL_EXT_separate_shader_objects -------------------- */ + +#ifndef GL_EXT_separate_shader_objects +#define GL_EXT_separate_shader_objects 1 + +#define GL_ACTIVE_PROGRAM_EXT 0x8B8D + +typedef void (GLAPIENTRY * PFNGLACTIVEPROGRAMEXTPROC) (GLuint program); +typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const char* string); +typedef void (GLAPIENTRY * PFNGLUSESHADERPROGRAMEXTPROC) (GLenum type, GLuint program); + +#define glActiveProgramEXT GLEW_GET_FUN(__glewActiveProgramEXT) +#define glCreateShaderProgramEXT GLEW_GET_FUN(__glewCreateShaderProgramEXT) +#define glUseShaderProgramEXT GLEW_GET_FUN(__glewUseShaderProgramEXT) + +#define GLEW_EXT_separate_shader_objects GLEW_GET_VAR(__GLEW_EXT_separate_shader_objects) + +#endif /* GL_EXT_separate_shader_objects */ + +/* --------------------- GL_EXT_separate_specular_color -------------------- */ + +#ifndef GL_EXT_separate_specular_color +#define GL_EXT_separate_specular_color 1 + +#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 +#define GL_SINGLE_COLOR_EXT 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA + +#define GLEW_EXT_separate_specular_color GLEW_GET_VAR(__GLEW_EXT_separate_specular_color) + +#endif /* GL_EXT_separate_specular_color */ + +/* --------------------- GL_EXT_shader_image_load_store -------------------- */ + +#ifndef GL_EXT_shader_image_load_store +#define GL_EXT_shader_image_load_store 1 + +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT 0x00000001 +#define GL_ELEMENT_ARRAY_BARRIER_BIT_EXT 0x00000002 +#define GL_UNIFORM_BARRIER_BIT_EXT 0x00000004 +#define GL_TEXTURE_FETCH_BARRIER_BIT_EXT 0x00000008 +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT 0x00000020 +#define GL_COMMAND_BARRIER_BIT_EXT 0x00000040 +#define GL_PIXEL_BUFFER_BARRIER_BIT_EXT 0x00000080 +#define GL_TEXTURE_UPDATE_BARRIER_BIT_EXT 0x00000100 +#define GL_BUFFER_UPDATE_BARRIER_BIT_EXT 0x00000200 +#define GL_FRAMEBUFFER_BARRIER_BIT_EXT 0x00000400 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT 0x00000800 +#define GL_ATOMIC_COUNTER_BARRIER_BIT_EXT 0x00001000 +#define GL_MAX_IMAGE_UNITS_EXT 0x8F38 +#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39 +#define GL_IMAGE_BINDING_NAME_EXT 0x8F3A +#define GL_IMAGE_BINDING_LEVEL_EXT 0x8F3B +#define GL_IMAGE_BINDING_LAYERED_EXT 0x8F3C +#define GL_IMAGE_BINDING_LAYER_EXT 0x8F3D +#define GL_IMAGE_BINDING_ACCESS_EXT 0x8F3E +#define GL_IMAGE_1D_EXT 0x904C +#define GL_IMAGE_2D_EXT 0x904D +#define GL_IMAGE_3D_EXT 0x904E +#define GL_IMAGE_2D_RECT_EXT 0x904F +#define GL_IMAGE_CUBE_EXT 0x9050 +#define GL_IMAGE_BUFFER_EXT 0x9051 +#define GL_IMAGE_1D_ARRAY_EXT 0x9052 +#define GL_IMAGE_2D_ARRAY_EXT 0x9053 +#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054 +#define GL_IMAGE_2D_MULTISAMPLE_EXT 0x9055 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9056 +#define GL_INT_IMAGE_1D_EXT 0x9057 +#define GL_INT_IMAGE_2D_EXT 0x9058 +#define GL_INT_IMAGE_3D_EXT 0x9059 +#define GL_INT_IMAGE_2D_RECT_EXT 0x905A +#define GL_INT_IMAGE_CUBE_EXT 0x905B +#define GL_INT_IMAGE_BUFFER_EXT 0x905C +#define GL_INT_IMAGE_1D_ARRAY_EXT 0x905D +#define GL_INT_IMAGE_2D_ARRAY_EXT 0x905E +#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F +#define GL_INT_IMAGE_2D_MULTISAMPLE_EXT 0x9060 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9061 +#define GL_UNSIGNED_INT_IMAGE_1D_EXT 0x9062 +#define GL_UNSIGNED_INT_IMAGE_2D_EXT 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D_EXT 0x9064 +#define GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_CUBE_EXT 0x9066 +#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT 0x9068 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT 0x9069 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x906C +#define GL_MAX_IMAGE_SAMPLES_EXT 0x906D +#define GL_IMAGE_BINDING_FORMAT_EXT 0x906E +#define GL_ALL_BARRIER_BITS_EXT 0xFFFFFFFF + +typedef void (GLAPIENTRY * PFNGLBINDIMAGETEXTUREEXTPROC) (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format); +typedef void (GLAPIENTRY * PFNGLMEMORYBARRIEREXTPROC) (GLbitfield barriers); + +#define glBindImageTextureEXT GLEW_GET_FUN(__glewBindImageTextureEXT) +#define glMemoryBarrierEXT GLEW_GET_FUN(__glewMemoryBarrierEXT) + +#define GLEW_EXT_shader_image_load_store GLEW_GET_VAR(__GLEW_EXT_shader_image_load_store) + +#endif /* GL_EXT_shader_image_load_store */ + +/* -------------------------- GL_EXT_shadow_funcs -------------------------- */ + +#ifndef GL_EXT_shadow_funcs +#define GL_EXT_shadow_funcs 1 + +#define GLEW_EXT_shadow_funcs GLEW_GET_VAR(__GLEW_EXT_shadow_funcs) + +#endif /* GL_EXT_shadow_funcs */ + +/* --------------------- GL_EXT_shared_texture_palette --------------------- */ + +#ifndef GL_EXT_shared_texture_palette +#define GL_EXT_shared_texture_palette 1 + +#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB + +#define GLEW_EXT_shared_texture_palette GLEW_GET_VAR(__GLEW_EXT_shared_texture_palette) + +#endif /* GL_EXT_shared_texture_palette */ + +/* ------------------------ GL_EXT_stencil_clear_tag ----------------------- */ + +#ifndef GL_EXT_stencil_clear_tag +#define GL_EXT_stencil_clear_tag 1 + +#define GL_STENCIL_TAG_BITS_EXT 0x88F2 +#define GL_STENCIL_CLEAR_TAG_VALUE_EXT 0x88F3 + +#define GLEW_EXT_stencil_clear_tag GLEW_GET_VAR(__GLEW_EXT_stencil_clear_tag) + +#endif /* GL_EXT_stencil_clear_tag */ + +/* ------------------------ GL_EXT_stencil_two_side ------------------------ */ + +#ifndef GL_EXT_stencil_two_side +#define GL_EXT_stencil_two_side 1 + +#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910 +#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911 + +typedef void (GLAPIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face); + +#define glActiveStencilFaceEXT GLEW_GET_FUN(__glewActiveStencilFaceEXT) + +#define GLEW_EXT_stencil_two_side GLEW_GET_VAR(__GLEW_EXT_stencil_two_side) + +#endif /* GL_EXT_stencil_two_side */ + +/* -------------------------- GL_EXT_stencil_wrap -------------------------- */ + +#ifndef GL_EXT_stencil_wrap +#define GL_EXT_stencil_wrap 1 + +#define GL_INCR_WRAP_EXT 0x8507 +#define GL_DECR_WRAP_EXT 0x8508 + +#define GLEW_EXT_stencil_wrap GLEW_GET_VAR(__GLEW_EXT_stencil_wrap) + +#endif /* GL_EXT_stencil_wrap */ + +/* --------------------------- GL_EXT_subtexture --------------------------- */ + +#ifndef GL_EXT_subtexture +#define GL_EXT_subtexture 1 + +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); + +#define glTexSubImage1DEXT GLEW_GET_FUN(__glewTexSubImage1DEXT) +#define glTexSubImage2DEXT GLEW_GET_FUN(__glewTexSubImage2DEXT) +#define glTexSubImage3DEXT GLEW_GET_FUN(__glewTexSubImage3DEXT) + +#define GLEW_EXT_subtexture GLEW_GET_VAR(__GLEW_EXT_subtexture) + +#endif /* GL_EXT_subtexture */ + +/* ----------------------------- GL_EXT_texture ---------------------------- */ + +#ifndef GL_EXT_texture +#define GL_EXT_texture 1 + +#define GL_ALPHA4_EXT 0x803B +#define GL_ALPHA8_EXT 0x803C +#define GL_ALPHA12_EXT 0x803D +#define GL_ALPHA16_EXT 0x803E +#define GL_LUMINANCE4_EXT 0x803F +#define GL_LUMINANCE8_EXT 0x8040 +#define GL_LUMINANCE12_EXT 0x8041 +#define GL_LUMINANCE16_EXT 0x8042 +#define GL_LUMINANCE4_ALPHA4_EXT 0x8043 +#define GL_LUMINANCE6_ALPHA2_EXT 0x8044 +#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +#define GL_LUMINANCE12_ALPHA4_EXT 0x8046 +#define GL_LUMINANCE12_ALPHA12_EXT 0x8047 +#define GL_LUMINANCE16_ALPHA16_EXT 0x8048 +#define GL_INTENSITY_EXT 0x8049 +#define GL_INTENSITY4_EXT 0x804A +#define GL_INTENSITY8_EXT 0x804B +#define GL_INTENSITY12_EXT 0x804C +#define GL_INTENSITY16_EXT 0x804D +#define GL_RGB2_EXT 0x804E +#define GL_RGB4_EXT 0x804F +#define GL_RGB5_EXT 0x8050 +#define GL_RGB8_EXT 0x8051 +#define GL_RGB10_EXT 0x8052 +#define GL_RGB12_EXT 0x8053 +#define GL_RGB16_EXT 0x8054 +#define GL_RGBA2_EXT 0x8055 +#define GL_RGBA4_EXT 0x8056 +#define GL_RGB5_A1_EXT 0x8057 +#define GL_RGBA8_EXT 0x8058 +#define GL_RGB10_A2_EXT 0x8059 +#define GL_RGBA12_EXT 0x805A +#define GL_RGBA16_EXT 0x805B +#define GL_TEXTURE_RED_SIZE_EXT 0x805C +#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D +#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E +#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061 +#define GL_REPLACE_EXT 0x8062 +#define GL_PROXY_TEXTURE_1D_EXT 0x8063 +#define GL_PROXY_TEXTURE_2D_EXT 0x8064 + +#define GLEW_EXT_texture GLEW_GET_VAR(__GLEW_EXT_texture) + +#endif /* GL_EXT_texture */ + +/* ---------------------------- GL_EXT_texture3D --------------------------- */ + +#ifndef GL_EXT_texture3D +#define GL_EXT_texture3D 1 + +#define GL_PACK_SKIP_IMAGES_EXT 0x806B +#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C +#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D +#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E +#define GL_TEXTURE_3D_EXT 0x806F +#define GL_PROXY_TEXTURE_3D_EXT 0x8070 +#define GL_TEXTURE_DEPTH_EXT 0x8071 +#define GL_TEXTURE_WRAP_R_EXT 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 + +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); + +#define glTexImage3DEXT GLEW_GET_FUN(__glewTexImage3DEXT) + +#define GLEW_EXT_texture3D GLEW_GET_VAR(__GLEW_EXT_texture3D) + +#endif /* GL_EXT_texture3D */ + +/* -------------------------- GL_EXT_texture_array ------------------------- */ + +#ifndef GL_EXT_texture_array +#define GL_EXT_texture_array 1 + +#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E +#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF +#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19 +#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D + +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); + +#define glFramebufferTextureLayerEXT GLEW_GET_FUN(__glewFramebufferTextureLayerEXT) + +#define GLEW_EXT_texture_array GLEW_GET_VAR(__GLEW_EXT_texture_array) + +#endif /* GL_EXT_texture_array */ + +/* ---------------------- GL_EXT_texture_buffer_object --------------------- */ + +#ifndef GL_EXT_texture_buffer_object +#define GL_EXT_texture_buffer_object 1 + +#define GL_TEXTURE_BUFFER_EXT 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E + +typedef void (GLAPIENTRY * PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer); + +#define glTexBufferEXT GLEW_GET_FUN(__glewTexBufferEXT) + +#define GLEW_EXT_texture_buffer_object GLEW_GET_VAR(__GLEW_EXT_texture_buffer_object) + +#endif /* GL_EXT_texture_buffer_object */ + +/* -------------------- GL_EXT_texture_compression_dxt1 -------------------- */ + +#ifndef GL_EXT_texture_compression_dxt1 +#define GL_EXT_texture_compression_dxt1 1 + +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 + +#define GLEW_EXT_texture_compression_dxt1 GLEW_GET_VAR(__GLEW_EXT_texture_compression_dxt1) + +#endif /* GL_EXT_texture_compression_dxt1 */ + +/* -------------------- GL_EXT_texture_compression_latc -------------------- */ + +#ifndef GL_EXT_texture_compression_latc +#define GL_EXT_texture_compression_latc 1 + +#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 +#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71 +#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 +#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73 + +#define GLEW_EXT_texture_compression_latc GLEW_GET_VAR(__GLEW_EXT_texture_compression_latc) + +#endif /* GL_EXT_texture_compression_latc */ + +/* -------------------- GL_EXT_texture_compression_rgtc -------------------- */ + +#ifndef GL_EXT_texture_compression_rgtc +#define GL_EXT_texture_compression_rgtc 1 + +#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC +#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD +#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE + +#define GLEW_EXT_texture_compression_rgtc GLEW_GET_VAR(__GLEW_EXT_texture_compression_rgtc) + +#endif /* GL_EXT_texture_compression_rgtc */ + +/* -------------------- GL_EXT_texture_compression_s3tc -------------------- */ + +#ifndef GL_EXT_texture_compression_s3tc +#define GL_EXT_texture_compression_s3tc 1 + +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 + +#define GLEW_EXT_texture_compression_s3tc GLEW_GET_VAR(__GLEW_EXT_texture_compression_s3tc) + +#endif /* GL_EXT_texture_compression_s3tc */ + +/* ------------------------ GL_EXT_texture_cube_map ------------------------ */ + +#ifndef GL_EXT_texture_cube_map +#define GL_EXT_texture_cube_map 1 + +#define GL_NORMAL_MAP_EXT 0x8511 +#define GL_REFLECTION_MAP_EXT 0x8512 +#define GL_TEXTURE_CUBE_MAP_EXT 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C + +#define GLEW_EXT_texture_cube_map GLEW_GET_VAR(__GLEW_EXT_texture_cube_map) + +#endif /* GL_EXT_texture_cube_map */ + +/* ----------------------- GL_EXT_texture_edge_clamp ----------------------- */ + +#ifndef GL_EXT_texture_edge_clamp +#define GL_EXT_texture_edge_clamp 1 + +#define GL_CLAMP_TO_EDGE_EXT 0x812F + +#define GLEW_EXT_texture_edge_clamp GLEW_GET_VAR(__GLEW_EXT_texture_edge_clamp) + +#endif /* GL_EXT_texture_edge_clamp */ + +/* --------------------------- GL_EXT_texture_env -------------------------- */ + +#ifndef GL_EXT_texture_env +#define GL_EXT_texture_env 1 + +#define GL_TEXTURE_ENV0_EXT 0 +#define GL_ENV_BLEND_EXT 0 +#define GL_TEXTURE_ENV_SHIFT_EXT 0 +#define GL_ENV_REPLACE_EXT 0 +#define GL_ENV_ADD_EXT 0 +#define GL_ENV_SUBTRACT_EXT 0 +#define GL_TEXTURE_ENV_MODE_ALPHA_EXT 0 +#define GL_ENV_REVERSE_SUBTRACT_EXT 0 +#define GL_ENV_REVERSE_BLEND_EXT 0 +#define GL_ENV_COPY_EXT 0 +#define GL_ENV_MODULATE_EXT 0 + +#define GLEW_EXT_texture_env GLEW_GET_VAR(__GLEW_EXT_texture_env) + +#endif /* GL_EXT_texture_env */ + +/* ------------------------- GL_EXT_texture_env_add ------------------------ */ + +#ifndef GL_EXT_texture_env_add +#define GL_EXT_texture_env_add 1 + +#define GLEW_EXT_texture_env_add GLEW_GET_VAR(__GLEW_EXT_texture_env_add) + +#endif /* GL_EXT_texture_env_add */ + +/* ----------------------- GL_EXT_texture_env_combine ---------------------- */ + +#ifndef GL_EXT_texture_env_combine +#define GL_EXT_texture_env_combine 1 + +#define GL_COMBINE_EXT 0x8570 +#define GL_COMBINE_RGB_EXT 0x8571 +#define GL_COMBINE_ALPHA_EXT 0x8572 +#define GL_RGB_SCALE_EXT 0x8573 +#define GL_ADD_SIGNED_EXT 0x8574 +#define GL_INTERPOLATE_EXT 0x8575 +#define GL_CONSTANT_EXT 0x8576 +#define GL_PRIMARY_COLOR_EXT 0x8577 +#define GL_PREVIOUS_EXT 0x8578 +#define GL_SOURCE0_RGB_EXT 0x8580 +#define GL_SOURCE1_RGB_EXT 0x8581 +#define GL_SOURCE2_RGB_EXT 0x8582 +#define GL_SOURCE0_ALPHA_EXT 0x8588 +#define GL_SOURCE1_ALPHA_EXT 0x8589 +#define GL_SOURCE2_ALPHA_EXT 0x858A +#define GL_OPERAND0_RGB_EXT 0x8590 +#define GL_OPERAND1_RGB_EXT 0x8591 +#define GL_OPERAND2_RGB_EXT 0x8592 +#define GL_OPERAND0_ALPHA_EXT 0x8598 +#define GL_OPERAND1_ALPHA_EXT 0x8599 +#define GL_OPERAND2_ALPHA_EXT 0x859A + +#define GLEW_EXT_texture_env_combine GLEW_GET_VAR(__GLEW_EXT_texture_env_combine) + +#endif /* GL_EXT_texture_env_combine */ + +/* ------------------------ GL_EXT_texture_env_dot3 ------------------------ */ + +#ifndef GL_EXT_texture_env_dot3 +#define GL_EXT_texture_env_dot3 1 + +#define GL_DOT3_RGB_EXT 0x8740 +#define GL_DOT3_RGBA_EXT 0x8741 + +#define GLEW_EXT_texture_env_dot3 GLEW_GET_VAR(__GLEW_EXT_texture_env_dot3) + +#endif /* GL_EXT_texture_env_dot3 */ + +/* ------------------- GL_EXT_texture_filter_anisotropic ------------------- */ + +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_EXT_texture_filter_anisotropic 1 + +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF + +#define GLEW_EXT_texture_filter_anisotropic GLEW_GET_VAR(__GLEW_EXT_texture_filter_anisotropic) + +#endif /* GL_EXT_texture_filter_anisotropic */ + +/* ------------------------- GL_EXT_texture_integer ------------------------ */ + +#ifndef GL_EXT_texture_integer +#define GL_EXT_texture_integer 1 + +#define GL_RGBA32UI_EXT 0x8D70 +#define GL_RGB32UI_EXT 0x8D71 +#define GL_ALPHA32UI_EXT 0x8D72 +#define GL_INTENSITY32UI_EXT 0x8D73 +#define GL_LUMINANCE32UI_EXT 0x8D74 +#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75 +#define GL_RGBA16UI_EXT 0x8D76 +#define GL_RGB16UI_EXT 0x8D77 +#define GL_ALPHA16UI_EXT 0x8D78 +#define GL_INTENSITY16UI_EXT 0x8D79 +#define GL_LUMINANCE16UI_EXT 0x8D7A +#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B +#define GL_RGBA8UI_EXT 0x8D7C +#define GL_RGB8UI_EXT 0x8D7D +#define GL_ALPHA8UI_EXT 0x8D7E +#define GL_INTENSITY8UI_EXT 0x8D7F +#define GL_LUMINANCE8UI_EXT 0x8D80 +#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81 +#define GL_RGBA32I_EXT 0x8D82 +#define GL_RGB32I_EXT 0x8D83 +#define GL_ALPHA32I_EXT 0x8D84 +#define GL_INTENSITY32I_EXT 0x8D85 +#define GL_LUMINANCE32I_EXT 0x8D86 +#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87 +#define GL_RGBA16I_EXT 0x8D88 +#define GL_RGB16I_EXT 0x8D89 +#define GL_ALPHA16I_EXT 0x8D8A +#define GL_INTENSITY16I_EXT 0x8D8B +#define GL_LUMINANCE16I_EXT 0x8D8C +#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D +#define GL_RGBA8I_EXT 0x8D8E +#define GL_RGB8I_EXT 0x8D8F +#define GL_ALPHA8I_EXT 0x8D90 +#define GL_INTENSITY8I_EXT 0x8D91 +#define GL_LUMINANCE8I_EXT 0x8D92 +#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93 +#define GL_RED_INTEGER_EXT 0x8D94 +#define GL_GREEN_INTEGER_EXT 0x8D95 +#define GL_BLUE_INTEGER_EXT 0x8D96 +#define GL_ALPHA_INTEGER_EXT 0x8D97 +#define GL_RGB_INTEGER_EXT 0x8D98 +#define GL_RGBA_INTEGER_EXT 0x8D99 +#define GL_BGR_INTEGER_EXT 0x8D9A +#define GL_BGRA_INTEGER_EXT 0x8D9B +#define GL_LUMINANCE_INTEGER_EXT 0x8D9C +#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D +#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E + +typedef void (GLAPIENTRY * PFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha); +typedef void (GLAPIENTRY * PFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params); + +#define glClearColorIiEXT GLEW_GET_FUN(__glewClearColorIiEXT) +#define glClearColorIuiEXT GLEW_GET_FUN(__glewClearColorIuiEXT) +#define glGetTexParameterIivEXT GLEW_GET_FUN(__glewGetTexParameterIivEXT) +#define glGetTexParameterIuivEXT GLEW_GET_FUN(__glewGetTexParameterIuivEXT) +#define glTexParameterIivEXT GLEW_GET_FUN(__glewTexParameterIivEXT) +#define glTexParameterIuivEXT GLEW_GET_FUN(__glewTexParameterIuivEXT) + +#define GLEW_EXT_texture_integer GLEW_GET_VAR(__GLEW_EXT_texture_integer) + +#endif /* GL_EXT_texture_integer */ + +/* ------------------------ GL_EXT_texture_lod_bias ------------------------ */ + +#ifndef GL_EXT_texture_lod_bias +#define GL_EXT_texture_lod_bias 1 + +#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD +#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500 +#define GL_TEXTURE_LOD_BIAS_EXT 0x8501 + +#define GLEW_EXT_texture_lod_bias GLEW_GET_VAR(__GLEW_EXT_texture_lod_bias) + +#endif /* GL_EXT_texture_lod_bias */ + +/* ---------------------- GL_EXT_texture_mirror_clamp ---------------------- */ + +#ifndef GL_EXT_texture_mirror_clamp +#define GL_EXT_texture_mirror_clamp 1 + +#define GL_MIRROR_CLAMP_EXT 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743 +#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912 + +#define GLEW_EXT_texture_mirror_clamp GLEW_GET_VAR(__GLEW_EXT_texture_mirror_clamp) + +#endif /* GL_EXT_texture_mirror_clamp */ + +/* ------------------------- GL_EXT_texture_object ------------------------- */ + +#ifndef GL_EXT_texture_object +#define GL_EXT_texture_object 1 + +#define GL_TEXTURE_PRIORITY_EXT 0x8066 +#define GL_TEXTURE_RESIDENT_EXT 0x8067 +#define GL_TEXTURE_1D_BINDING_EXT 0x8068 +#define GL_TEXTURE_2D_BINDING_EXT 0x8069 +#define GL_TEXTURE_3D_BINDING_EXT 0x806A + +typedef GLboolean (GLAPIENTRY * PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint* textures, GLboolean* residences); +typedef void (GLAPIENTRY * PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture); +typedef void (GLAPIENTRY * PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint* textures); +typedef void (GLAPIENTRY * PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint* textures); +typedef GLboolean (GLAPIENTRY * PFNGLISTEXTUREEXTPROC) (GLuint texture); +typedef void (GLAPIENTRY * PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint* textures, const GLclampf* priorities); + +#define glAreTexturesResidentEXT GLEW_GET_FUN(__glewAreTexturesResidentEXT) +#define glBindTextureEXT GLEW_GET_FUN(__glewBindTextureEXT) +#define glDeleteTexturesEXT GLEW_GET_FUN(__glewDeleteTexturesEXT) +#define glGenTexturesEXT GLEW_GET_FUN(__glewGenTexturesEXT) +#define glIsTextureEXT GLEW_GET_FUN(__glewIsTextureEXT) +#define glPrioritizeTexturesEXT GLEW_GET_FUN(__glewPrioritizeTexturesEXT) + +#define GLEW_EXT_texture_object GLEW_GET_VAR(__GLEW_EXT_texture_object) + +#endif /* GL_EXT_texture_object */ + +/* --------------------- GL_EXT_texture_perturb_normal --------------------- */ + +#ifndef GL_EXT_texture_perturb_normal +#define GL_EXT_texture_perturb_normal 1 + +#define GL_PERTURB_EXT 0x85AE +#define GL_TEXTURE_NORMAL_EXT 0x85AF + +typedef void (GLAPIENTRY * PFNGLTEXTURENORMALEXTPROC) (GLenum mode); + +#define glTextureNormalEXT GLEW_GET_FUN(__glewTextureNormalEXT) + +#define GLEW_EXT_texture_perturb_normal GLEW_GET_VAR(__GLEW_EXT_texture_perturb_normal) + +#endif /* GL_EXT_texture_perturb_normal */ + +/* ------------------------ GL_EXT_texture_rectangle ----------------------- */ + +#ifndef GL_EXT_texture_rectangle +#define GL_EXT_texture_rectangle 1 + +#define GL_TEXTURE_RECTANGLE_EXT 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_EXT 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_EXT 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT 0x84F8 + +#define GLEW_EXT_texture_rectangle GLEW_GET_VAR(__GLEW_EXT_texture_rectangle) + +#endif /* GL_EXT_texture_rectangle */ + +/* -------------------------- GL_EXT_texture_sRGB -------------------------- */ + +#ifndef GL_EXT_texture_sRGB +#define GL_EXT_texture_sRGB 1 + +#define GL_SRGB_EXT 0x8C40 +#define GL_SRGB8_EXT 0x8C41 +#define GL_SRGB_ALPHA_EXT 0x8C42 +#define GL_SRGB8_ALPHA8_EXT 0x8C43 +#define GL_SLUMINANCE_ALPHA_EXT 0x8C44 +#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45 +#define GL_SLUMINANCE_EXT 0x8C46 +#define GL_SLUMINANCE8_EXT 0x8C47 +#define GL_COMPRESSED_SRGB_EXT 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49 +#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A +#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B +#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F + +#define GLEW_EXT_texture_sRGB GLEW_GET_VAR(__GLEW_EXT_texture_sRGB) + +#endif /* GL_EXT_texture_sRGB */ + +/* ----------------------- GL_EXT_texture_sRGB_decode ---------------------- */ + +#ifndef GL_EXT_texture_sRGB_decode +#define GL_EXT_texture_sRGB_decode 1 + +#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48 +#define GL_DECODE_EXT 0x8A49 +#define GL_SKIP_DECODE_EXT 0x8A4A + +#define GLEW_EXT_texture_sRGB_decode GLEW_GET_VAR(__GLEW_EXT_texture_sRGB_decode) + +#endif /* GL_EXT_texture_sRGB_decode */ + +/* --------------------- GL_EXT_texture_shared_exponent -------------------- */ + +#ifndef GL_EXT_texture_shared_exponent +#define GL_EXT_texture_shared_exponent 1 + +#define GL_RGB9_E5_EXT 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E +#define GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F + +#define GLEW_EXT_texture_shared_exponent GLEW_GET_VAR(__GLEW_EXT_texture_shared_exponent) + +#endif /* GL_EXT_texture_shared_exponent */ + +/* -------------------------- GL_EXT_texture_snorm ------------------------- */ + +#ifndef GL_EXT_texture_snorm +#define GL_EXT_texture_snorm 1 + +#define GL_RED_SNORM 0x8F90 +#define GL_RG_SNORM 0x8F91 +#define GL_RGB_SNORM 0x8F92 +#define GL_RGBA_SNORM 0x8F93 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_R16_SNORM 0x8F98 +#define GL_RG16_SNORM 0x8F99 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGBA16_SNORM 0x8F9B +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_ALPHA_SNORM 0x9010 +#define GL_LUMINANCE_SNORM 0x9011 +#define GL_LUMINANCE_ALPHA_SNORM 0x9012 +#define GL_INTENSITY_SNORM 0x9013 +#define GL_ALPHA8_SNORM 0x9014 +#define GL_LUMINANCE8_SNORM 0x9015 +#define GL_LUMINANCE8_ALPHA8_SNORM 0x9016 +#define GL_INTENSITY8_SNORM 0x9017 +#define GL_ALPHA16_SNORM 0x9018 +#define GL_LUMINANCE16_SNORM 0x9019 +#define GL_LUMINANCE16_ALPHA16_SNORM 0x901A +#define GL_INTENSITY16_SNORM 0x901B + +#define GLEW_EXT_texture_snorm GLEW_GET_VAR(__GLEW_EXT_texture_snorm) + +#endif /* GL_EXT_texture_snorm */ + +/* ------------------------- GL_EXT_texture_swizzle ------------------------ */ + +#ifndef GL_EXT_texture_swizzle +#define GL_EXT_texture_swizzle 1 + +#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42 +#define GL_TEXTURE_SWIZZLE_G_EXT 0x8E43 +#define GL_TEXTURE_SWIZZLE_B_EXT 0x8E44 +#define GL_TEXTURE_SWIZZLE_A_EXT 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46 + +#define GLEW_EXT_texture_swizzle GLEW_GET_VAR(__GLEW_EXT_texture_swizzle) + +#endif /* GL_EXT_texture_swizzle */ + +/* --------------------------- GL_EXT_timer_query -------------------------- */ + +#ifndef GL_EXT_timer_query +#define GL_EXT_timer_query 1 + +#define GL_TIME_ELAPSED_EXT 0x88BF + +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64EXT *params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64EXT *params); + +#define glGetQueryObjecti64vEXT GLEW_GET_FUN(__glewGetQueryObjecti64vEXT) +#define glGetQueryObjectui64vEXT GLEW_GET_FUN(__glewGetQueryObjectui64vEXT) + +#define GLEW_EXT_timer_query GLEW_GET_VAR(__GLEW_EXT_timer_query) + +#endif /* GL_EXT_timer_query */ + +/* ----------------------- GL_EXT_transform_feedback ----------------------- */ + +#ifndef GL_EXT_transform_feedback +#define GL_EXT_transform_feedback 1 + +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85 +#define GL_PRIMITIVES_GENERATED_EXT 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88 +#define GL_RASTERIZER_DISCARD_EXT 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B +#define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C +#define GL_SEPARATE_ATTRIBS_EXT 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F + +typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKEXTPROC) (GLenum primitiveMode); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKEXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei *size, GLenum *type, char *name); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const char ** varyings, GLenum bufferMode); + +#define glBeginTransformFeedbackEXT GLEW_GET_FUN(__glewBeginTransformFeedbackEXT) +#define glBindBufferBaseEXT GLEW_GET_FUN(__glewBindBufferBaseEXT) +#define glBindBufferOffsetEXT GLEW_GET_FUN(__glewBindBufferOffsetEXT) +#define glBindBufferRangeEXT GLEW_GET_FUN(__glewBindBufferRangeEXT) +#define glEndTransformFeedbackEXT GLEW_GET_FUN(__glewEndTransformFeedbackEXT) +#define glGetTransformFeedbackVaryingEXT GLEW_GET_FUN(__glewGetTransformFeedbackVaryingEXT) +#define glTransformFeedbackVaryingsEXT GLEW_GET_FUN(__glewTransformFeedbackVaryingsEXT) + +#define GLEW_EXT_transform_feedback GLEW_GET_VAR(__GLEW_EXT_transform_feedback) + +#endif /* GL_EXT_transform_feedback */ + +/* -------------------------- GL_EXT_vertex_array -------------------------- */ + +#ifndef GL_EXT_vertex_array +#define GL_EXT_vertex_array 1 + +#define GL_DOUBLE_EXT 0x140A +#define GL_VERTEX_ARRAY_EXT 0x8074 +#define GL_NORMAL_ARRAY_EXT 0x8075 +#define GL_COLOR_ARRAY_EXT 0x8076 +#define GL_INDEX_ARRAY_EXT 0x8077 +#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078 +#define GL_EDGE_FLAG_ARRAY_EXT 0x8079 +#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A +#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B +#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C +#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D +#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E +#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F +#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080 +#define GL_COLOR_ARRAY_SIZE_EXT 0x8081 +#define GL_COLOR_ARRAY_TYPE_EXT 0x8082 +#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083 +#define GL_COLOR_ARRAY_COUNT_EXT 0x8084 +#define GL_INDEX_ARRAY_TYPE_EXT 0x8085 +#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086 +#define GL_INDEX_ARRAY_COUNT_EXT 0x8087 +#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A +#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B +#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C +#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D +#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E +#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F +#define GL_COLOR_ARRAY_POINTER_EXT 0x8090 +#define GL_INDEX_ARRAY_POINTER_EXT 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 + +typedef void (GLAPIENTRY * PFNGLARRAYELEMENTEXTPROC) (GLint i); +typedef void (GLAPIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean* pointer); +typedef void (GLAPIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); + +#define glArrayElementEXT GLEW_GET_FUN(__glewArrayElementEXT) +#define glColorPointerEXT GLEW_GET_FUN(__glewColorPointerEXT) +#define glDrawArraysEXT GLEW_GET_FUN(__glewDrawArraysEXT) +#define glEdgeFlagPointerEXT GLEW_GET_FUN(__glewEdgeFlagPointerEXT) +#define glIndexPointerEXT GLEW_GET_FUN(__glewIndexPointerEXT) +#define glNormalPointerEXT GLEW_GET_FUN(__glewNormalPointerEXT) +#define glTexCoordPointerEXT GLEW_GET_FUN(__glewTexCoordPointerEXT) +#define glVertexPointerEXT GLEW_GET_FUN(__glewVertexPointerEXT) + +#define GLEW_EXT_vertex_array GLEW_GET_VAR(__GLEW_EXT_vertex_array) + +#endif /* GL_EXT_vertex_array */ + +/* ------------------------ GL_EXT_vertex_array_bgra ----------------------- */ + +#ifndef GL_EXT_vertex_array_bgra +#define GL_EXT_vertex_array_bgra 1 + +#define GL_BGRA 0x80E1 + +#define GLEW_EXT_vertex_array_bgra GLEW_GET_VAR(__GLEW_EXT_vertex_array_bgra) + +#endif /* GL_EXT_vertex_array_bgra */ + +/* ----------------------- GL_EXT_vertex_attrib_64bit ---------------------- */ + +#ifndef GL_EXT_vertex_attrib_64bit +#define GL_EXT_vertex_attrib_64bit 1 + +#define GL_DOUBLE_MAT2_EXT 0x8F46 +#define GL_DOUBLE_MAT3_EXT 0x8F47 +#define GL_DOUBLE_MAT4_EXT 0x8F48 +#define GL_DOUBLE_MAT2x3_EXT 0x8F49 +#define GL_DOUBLE_MAT2x4_EXT 0x8F4A +#define GL_DOUBLE_MAT3x2_EXT 0x8F4B +#define GL_DOUBLE_MAT3x4_EXT 0x8F4C +#define GL_DOUBLE_MAT4x2_EXT 0x8F4D +#define GL_DOUBLE_MAT4x3_EXT 0x8F4E +#define GL_DOUBLE_VEC2_EXT 0x8FFC +#define GL_DOUBLE_VEC3_EXT 0x8FFD +#define GL_DOUBLE_VEC4_EXT 0x8FFE + +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLDVEXTPROC) (GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DEXTPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DVEXTPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DEXTPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DVEXTPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DVEXTPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DVEXTPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); + +#define glGetVertexAttribLdvEXT GLEW_GET_FUN(__glewGetVertexAttribLdvEXT) +#define glVertexArrayVertexAttribLOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribLOffsetEXT) +#define glVertexAttribL1dEXT GLEW_GET_FUN(__glewVertexAttribL1dEXT) +#define glVertexAttribL1dvEXT GLEW_GET_FUN(__glewVertexAttribL1dvEXT) +#define glVertexAttribL2dEXT GLEW_GET_FUN(__glewVertexAttribL2dEXT) +#define glVertexAttribL2dvEXT GLEW_GET_FUN(__glewVertexAttribL2dvEXT) +#define glVertexAttribL3dEXT GLEW_GET_FUN(__glewVertexAttribL3dEXT) +#define glVertexAttribL3dvEXT GLEW_GET_FUN(__glewVertexAttribL3dvEXT) +#define glVertexAttribL4dEXT GLEW_GET_FUN(__glewVertexAttribL4dEXT) +#define glVertexAttribL4dvEXT GLEW_GET_FUN(__glewVertexAttribL4dvEXT) +#define glVertexAttribLPointerEXT GLEW_GET_FUN(__glewVertexAttribLPointerEXT) + +#define GLEW_EXT_vertex_attrib_64bit GLEW_GET_VAR(__GLEW_EXT_vertex_attrib_64bit) + +#endif /* GL_EXT_vertex_attrib_64bit */ + +/* -------------------------- GL_EXT_vertex_shader ------------------------- */ + +#ifndef GL_EXT_vertex_shader +#define GL_EXT_vertex_shader 1 + +#define GL_VERTEX_SHADER_EXT 0x8780 +#define GL_VERTEX_SHADER_BINDING_EXT 0x8781 +#define GL_OP_INDEX_EXT 0x8782 +#define GL_OP_NEGATE_EXT 0x8783 +#define GL_OP_DOT3_EXT 0x8784 +#define GL_OP_DOT4_EXT 0x8785 +#define GL_OP_MUL_EXT 0x8786 +#define GL_OP_ADD_EXT 0x8787 +#define GL_OP_MADD_EXT 0x8788 +#define GL_OP_FRAC_EXT 0x8789 +#define GL_OP_MAX_EXT 0x878A +#define GL_OP_MIN_EXT 0x878B +#define GL_OP_SET_GE_EXT 0x878C +#define GL_OP_SET_LT_EXT 0x878D +#define GL_OP_CLAMP_EXT 0x878E +#define GL_OP_FLOOR_EXT 0x878F +#define GL_OP_ROUND_EXT 0x8790 +#define GL_OP_EXP_BASE_2_EXT 0x8791 +#define GL_OP_LOG_BASE_2_EXT 0x8792 +#define GL_OP_POWER_EXT 0x8793 +#define GL_OP_RECIP_EXT 0x8794 +#define GL_OP_RECIP_SQRT_EXT 0x8795 +#define GL_OP_SUB_EXT 0x8796 +#define GL_OP_CROSS_PRODUCT_EXT 0x8797 +#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798 +#define GL_OP_MOV_EXT 0x8799 +#define GL_OUTPUT_VERTEX_EXT 0x879A +#define GL_OUTPUT_COLOR0_EXT 0x879B +#define GL_OUTPUT_COLOR1_EXT 0x879C +#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D +#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E +#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F +#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0 +#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1 +#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2 +#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3 +#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4 +#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5 +#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6 +#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7 +#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8 +#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9 +#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA +#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB +#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC +#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD +#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE +#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF +#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0 +#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1 +#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2 +#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3 +#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4 +#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5 +#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6 +#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7 +#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8 +#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9 +#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA +#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB +#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC +#define GL_OUTPUT_FOG_EXT 0x87BD +#define GL_SCALAR_EXT 0x87BE +#define GL_VECTOR_EXT 0x87BF +#define GL_MATRIX_EXT 0x87C0 +#define GL_VARIANT_EXT 0x87C1 +#define GL_INVARIANT_EXT 0x87C2 +#define GL_LOCAL_CONSTANT_EXT 0x87C3 +#define GL_LOCAL_EXT 0x87C4 +#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5 +#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6 +#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7 +#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8 +#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9 +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CC +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CD +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE +#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF +#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0 +#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1 +#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2 +#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3 +#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4 +#define GL_X_EXT 0x87D5 +#define GL_Y_EXT 0x87D6 +#define GL_Z_EXT 0x87D7 +#define GL_W_EXT 0x87D8 +#define GL_NEGATIVE_X_EXT 0x87D9 +#define GL_NEGATIVE_Y_EXT 0x87DA +#define GL_NEGATIVE_Z_EXT 0x87DB +#define GL_NEGATIVE_W_EXT 0x87DC +#define GL_ZERO_EXT 0x87DD +#define GL_ONE_EXT 0x87DE +#define GL_NEGATIVE_ONE_EXT 0x87DF +#define GL_NORMALIZED_RANGE_EXT 0x87E0 +#define GL_FULL_RANGE_EXT 0x87E1 +#define GL_CURRENT_VERTEX_EXT 0x87E2 +#define GL_MVP_MATRIX_EXT 0x87E3 +#define GL_VARIANT_VALUE_EXT 0x87E4 +#define GL_VARIANT_DATATYPE_EXT 0x87E5 +#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6 +#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7 +#define GL_VARIANT_ARRAY_EXT 0x87E8 +#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9 +#define GL_INVARIANT_VALUE_EXT 0x87EA +#define GL_INVARIANT_DATATYPE_EXT 0x87EB +#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC +#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED + +typedef void (GLAPIENTRY * PFNGLBEGINVERTEXSHADEREXTPROC) (void); +typedef GLuint (GLAPIENTRY * PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value); +typedef GLuint (GLAPIENTRY * PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value); +typedef GLuint (GLAPIENTRY * PFNGLBINDPARAMETEREXTPROC) (GLenum value); +typedef GLuint (GLAPIENTRY * PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value); +typedef GLuint (GLAPIENTRY * PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value); +typedef void (GLAPIENTRY * PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLENDVERTEXSHADEREXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); +typedef GLuint (GLAPIENTRY * PFNGLGENSYMBOLSEXTPROC) (GLenum dataType, GLenum storageType, GLenum range, GLuint components); +typedef GLuint (GLAPIENTRY * PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range); +typedef void (GLAPIENTRY * PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (GLAPIENTRY * PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (GLAPIENTRY * PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid **data); +typedef void (GLAPIENTRY * PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); +typedef GLboolean (GLAPIENTRY * PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap); +typedef void (GLAPIENTRY * PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr); +typedef void (GLAPIENTRY * PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr); +typedef void (GLAPIENTRY * PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1); +typedef void (GLAPIENTRY * PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2); +typedef void (GLAPIENTRY * PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); +typedef void (GLAPIENTRY * PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); +typedef void (GLAPIENTRY * PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, GLvoid *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTBVEXTPROC) (GLuint id, GLbyte *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTDVEXTPROC) (GLuint id, GLdouble *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTFVEXTPROC) (GLuint id, GLfloat *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTIVEXTPROC) (GLuint id, GLint *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTSVEXTPROC) (GLuint id, GLshort *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTUBVEXTPROC) (GLuint id, GLubyte *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTUIVEXTPROC) (GLuint id, GLuint *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTUSVEXTPROC) (GLuint id, GLushort *addr); +typedef void (GLAPIENTRY * PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); + +#define glBeginVertexShaderEXT GLEW_GET_FUN(__glewBeginVertexShaderEXT) +#define glBindLightParameterEXT GLEW_GET_FUN(__glewBindLightParameterEXT) +#define glBindMaterialParameterEXT GLEW_GET_FUN(__glewBindMaterialParameterEXT) +#define glBindParameterEXT GLEW_GET_FUN(__glewBindParameterEXT) +#define glBindTexGenParameterEXT GLEW_GET_FUN(__glewBindTexGenParameterEXT) +#define glBindTextureUnitParameterEXT GLEW_GET_FUN(__glewBindTextureUnitParameterEXT) +#define glBindVertexShaderEXT GLEW_GET_FUN(__glewBindVertexShaderEXT) +#define glDeleteVertexShaderEXT GLEW_GET_FUN(__glewDeleteVertexShaderEXT) +#define glDisableVariantClientStateEXT GLEW_GET_FUN(__glewDisableVariantClientStateEXT) +#define glEnableVariantClientStateEXT GLEW_GET_FUN(__glewEnableVariantClientStateEXT) +#define glEndVertexShaderEXT GLEW_GET_FUN(__glewEndVertexShaderEXT) +#define glExtractComponentEXT GLEW_GET_FUN(__glewExtractComponentEXT) +#define glGenSymbolsEXT GLEW_GET_FUN(__glewGenSymbolsEXT) +#define glGenVertexShadersEXT GLEW_GET_FUN(__glewGenVertexShadersEXT) +#define glGetInvariantBooleanvEXT GLEW_GET_FUN(__glewGetInvariantBooleanvEXT) +#define glGetInvariantFloatvEXT GLEW_GET_FUN(__glewGetInvariantFloatvEXT) +#define glGetInvariantIntegervEXT GLEW_GET_FUN(__glewGetInvariantIntegervEXT) +#define glGetLocalConstantBooleanvEXT GLEW_GET_FUN(__glewGetLocalConstantBooleanvEXT) +#define glGetLocalConstantFloatvEXT GLEW_GET_FUN(__glewGetLocalConstantFloatvEXT) +#define glGetLocalConstantIntegervEXT GLEW_GET_FUN(__glewGetLocalConstantIntegervEXT) +#define glGetVariantBooleanvEXT GLEW_GET_FUN(__glewGetVariantBooleanvEXT) +#define glGetVariantFloatvEXT GLEW_GET_FUN(__glewGetVariantFloatvEXT) +#define glGetVariantIntegervEXT GLEW_GET_FUN(__glewGetVariantIntegervEXT) +#define glGetVariantPointervEXT GLEW_GET_FUN(__glewGetVariantPointervEXT) +#define glInsertComponentEXT GLEW_GET_FUN(__glewInsertComponentEXT) +#define glIsVariantEnabledEXT GLEW_GET_FUN(__glewIsVariantEnabledEXT) +#define glSetInvariantEXT GLEW_GET_FUN(__glewSetInvariantEXT) +#define glSetLocalConstantEXT GLEW_GET_FUN(__glewSetLocalConstantEXT) +#define glShaderOp1EXT GLEW_GET_FUN(__glewShaderOp1EXT) +#define glShaderOp2EXT GLEW_GET_FUN(__glewShaderOp2EXT) +#define glShaderOp3EXT GLEW_GET_FUN(__glewShaderOp3EXT) +#define glSwizzleEXT GLEW_GET_FUN(__glewSwizzleEXT) +#define glVariantPointerEXT GLEW_GET_FUN(__glewVariantPointerEXT) +#define glVariantbvEXT GLEW_GET_FUN(__glewVariantbvEXT) +#define glVariantdvEXT GLEW_GET_FUN(__glewVariantdvEXT) +#define glVariantfvEXT GLEW_GET_FUN(__glewVariantfvEXT) +#define glVariantivEXT GLEW_GET_FUN(__glewVariantivEXT) +#define glVariantsvEXT GLEW_GET_FUN(__glewVariantsvEXT) +#define glVariantubvEXT GLEW_GET_FUN(__glewVariantubvEXT) +#define glVariantuivEXT GLEW_GET_FUN(__glewVariantuivEXT) +#define glVariantusvEXT GLEW_GET_FUN(__glewVariantusvEXT) +#define glWriteMaskEXT GLEW_GET_FUN(__glewWriteMaskEXT) + +#define GLEW_EXT_vertex_shader GLEW_GET_VAR(__GLEW_EXT_vertex_shader) + +#endif /* GL_EXT_vertex_shader */ + +/* ------------------------ GL_EXT_vertex_weighting ------------------------ */ + +#ifndef GL_EXT_vertex_weighting +#define GL_EXT_vertex_weighting 1 + +#define GL_MODELVIEW0_STACK_DEPTH_EXT 0x0BA3 +#define GL_MODELVIEW0_MATRIX_EXT 0x0BA6 +#define GL_MODELVIEW0_EXT 0x1700 +#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502 +#define GL_MODELVIEW1_MATRIX_EXT 0x8506 +#define GL_VERTEX_WEIGHTING_EXT 0x8509 +#define GL_MODELVIEW1_EXT 0x850A +#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B +#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C +#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D +#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E +#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F +#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 + +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFVEXTPROC) (GLfloat* weight); + +#define glVertexWeightPointerEXT GLEW_GET_FUN(__glewVertexWeightPointerEXT) +#define glVertexWeightfEXT GLEW_GET_FUN(__glewVertexWeightfEXT) +#define glVertexWeightfvEXT GLEW_GET_FUN(__glewVertexWeightfvEXT) + +#define GLEW_EXT_vertex_weighting GLEW_GET_VAR(__GLEW_EXT_vertex_weighting) + +#endif /* GL_EXT_vertex_weighting */ + +/* ------------------------- GL_EXT_x11_sync_object ------------------------ */ + +#ifndef GL_EXT_x11_sync_object +#define GL_EXT_x11_sync_object 1 + +#define GL_SYNC_X11_FENCE_EXT 0x90E1 + +typedef GLsync (GLAPIENTRY * PFNGLIMPORTSYNCEXTPROC) (GLenum external_sync_type, GLintptr external_sync, GLbitfield flags); + +#define glImportSyncEXT GLEW_GET_FUN(__glewImportSyncEXT) + +#define GLEW_EXT_x11_sync_object GLEW_GET_VAR(__GLEW_EXT_x11_sync_object) + +#endif /* GL_EXT_x11_sync_object */ + +/* ---------------------- GL_GREMEDY_frame_terminator ---------------------- */ + +#ifndef GL_GREMEDY_frame_terminator +#define GL_GREMEDY_frame_terminator 1 + +typedef void (GLAPIENTRY * PFNGLFRAMETERMINATORGREMEDYPROC) (void); + +#define glFrameTerminatorGREMEDY GLEW_GET_FUN(__glewFrameTerminatorGREMEDY) + +#define GLEW_GREMEDY_frame_terminator GLEW_GET_VAR(__GLEW_GREMEDY_frame_terminator) + +#endif /* GL_GREMEDY_frame_terminator */ + +/* ------------------------ GL_GREMEDY_string_marker ----------------------- */ + +#ifndef GL_GREMEDY_string_marker +#define GL_GREMEDY_string_marker 1 + +typedef void (GLAPIENTRY * PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const void* string); + +#define glStringMarkerGREMEDY GLEW_GET_FUN(__glewStringMarkerGREMEDY) + +#define GLEW_GREMEDY_string_marker GLEW_GET_VAR(__GLEW_GREMEDY_string_marker) + +#endif /* GL_GREMEDY_string_marker */ + +/* --------------------- GL_HP_convolution_border_modes -------------------- */ + +#ifndef GL_HP_convolution_border_modes +#define GL_HP_convolution_border_modes 1 + +#define GLEW_HP_convolution_border_modes GLEW_GET_VAR(__GLEW_HP_convolution_border_modes) + +#endif /* GL_HP_convolution_border_modes */ + +/* ------------------------- GL_HP_image_transform ------------------------- */ + +#ifndef GL_HP_image_transform +#define GL_HP_image_transform 1 + +typedef void (GLAPIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, const GLfloat param); +typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, const GLint param); +typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint* params); + +#define glGetImageTransformParameterfvHP GLEW_GET_FUN(__glewGetImageTransformParameterfvHP) +#define glGetImageTransformParameterivHP GLEW_GET_FUN(__glewGetImageTransformParameterivHP) +#define glImageTransformParameterfHP GLEW_GET_FUN(__glewImageTransformParameterfHP) +#define glImageTransformParameterfvHP GLEW_GET_FUN(__glewImageTransformParameterfvHP) +#define glImageTransformParameteriHP GLEW_GET_FUN(__glewImageTransformParameteriHP) +#define glImageTransformParameterivHP GLEW_GET_FUN(__glewImageTransformParameterivHP) + +#define GLEW_HP_image_transform GLEW_GET_VAR(__GLEW_HP_image_transform) + +#endif /* GL_HP_image_transform */ + +/* -------------------------- GL_HP_occlusion_test ------------------------- */ + +#ifndef GL_HP_occlusion_test +#define GL_HP_occlusion_test 1 + +#define GL_OCCLUSION_TEST_HP 0x8165 +#define GL_OCCLUSION_TEST_RESULT_HP 0x8166 + +#define GLEW_HP_occlusion_test GLEW_GET_VAR(__GLEW_HP_occlusion_test) + +#endif /* GL_HP_occlusion_test */ + +/* ------------------------- GL_HP_texture_lighting ------------------------ */ + +#ifndef GL_HP_texture_lighting +#define GL_HP_texture_lighting 1 + +#define GLEW_HP_texture_lighting GLEW_GET_VAR(__GLEW_HP_texture_lighting) + +#endif /* GL_HP_texture_lighting */ + +/* --------------------------- GL_IBM_cull_vertex -------------------------- */ + +#ifndef GL_IBM_cull_vertex +#define GL_IBM_cull_vertex 1 + +#define GL_CULL_VERTEX_IBM 103050 + +#define GLEW_IBM_cull_vertex GLEW_GET_VAR(__GLEW_IBM_cull_vertex) + +#endif /* GL_IBM_cull_vertex */ + +/* ---------------------- GL_IBM_multimode_draw_arrays --------------------- */ + +#ifndef GL_IBM_multimode_draw_arrays +#define GL_IBM_multimode_draw_arrays 1 + +typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum* mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); +typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum* mode, const GLsizei *count, GLenum type, const GLvoid * const *indices, GLsizei primcount, GLint modestride); + +#define glMultiModeDrawArraysIBM GLEW_GET_FUN(__glewMultiModeDrawArraysIBM) +#define glMultiModeDrawElementsIBM GLEW_GET_FUN(__glewMultiModeDrawElementsIBM) + +#define GLEW_IBM_multimode_draw_arrays GLEW_GET_VAR(__GLEW_IBM_multimode_draw_arrays) + +#endif /* GL_IBM_multimode_draw_arrays */ + +/* ------------------------- GL_IBM_rasterpos_clip ------------------------- */ + +#ifndef GL_IBM_rasterpos_clip +#define GL_IBM_rasterpos_clip 1 + +#define GL_RASTER_POSITION_UNCLIPPED_IBM 103010 + +#define GLEW_IBM_rasterpos_clip GLEW_GET_VAR(__GLEW_IBM_rasterpos_clip) + +#endif /* GL_IBM_rasterpos_clip */ + +/* --------------------------- GL_IBM_static_data -------------------------- */ + +#ifndef GL_IBM_static_data +#define GL_IBM_static_data 1 + +#define GL_ALL_STATIC_DATA_IBM 103060 +#define GL_STATIC_VERTEX_ARRAY_IBM 103061 + +#define GLEW_IBM_static_data GLEW_GET_VAR(__GLEW_IBM_static_data) + +#endif /* GL_IBM_static_data */ + +/* --------------------- GL_IBM_texture_mirrored_repeat -------------------- */ + +#ifndef GL_IBM_texture_mirrored_repeat +#define GL_IBM_texture_mirrored_repeat 1 + +#define GL_MIRRORED_REPEAT_IBM 0x8370 + +#define GLEW_IBM_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_IBM_texture_mirrored_repeat) + +#endif /* GL_IBM_texture_mirrored_repeat */ + +/* ----------------------- GL_IBM_vertex_array_lists ----------------------- */ + +#ifndef GL_IBM_vertex_array_lists +#define GL_IBM_vertex_array_lists 1 + +#define GL_VERTEX_ARRAY_LIST_IBM 103070 +#define GL_NORMAL_ARRAY_LIST_IBM 103071 +#define GL_COLOR_ARRAY_LIST_IBM 103072 +#define GL_INDEX_ARRAY_LIST_IBM 103073 +#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074 +#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075 +#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076 +#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077 +#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080 +#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081 +#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082 +#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083 +#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084 +#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085 +#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086 +#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087 + +typedef void (GLAPIENTRY * PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); + +#define glColorPointerListIBM GLEW_GET_FUN(__glewColorPointerListIBM) +#define glEdgeFlagPointerListIBM GLEW_GET_FUN(__glewEdgeFlagPointerListIBM) +#define glFogCoordPointerListIBM GLEW_GET_FUN(__glewFogCoordPointerListIBM) +#define glIndexPointerListIBM GLEW_GET_FUN(__glewIndexPointerListIBM) +#define glNormalPointerListIBM GLEW_GET_FUN(__glewNormalPointerListIBM) +#define glSecondaryColorPointerListIBM GLEW_GET_FUN(__glewSecondaryColorPointerListIBM) +#define glTexCoordPointerListIBM GLEW_GET_FUN(__glewTexCoordPointerListIBM) +#define glVertexPointerListIBM GLEW_GET_FUN(__glewVertexPointerListIBM) + +#define GLEW_IBM_vertex_array_lists GLEW_GET_VAR(__GLEW_IBM_vertex_array_lists) + +#endif /* GL_IBM_vertex_array_lists */ + +/* -------------------------- GL_INGR_color_clamp -------------------------- */ + +#ifndef GL_INGR_color_clamp +#define GL_INGR_color_clamp 1 + +#define GL_RED_MIN_CLAMP_INGR 0x8560 +#define GL_GREEN_MIN_CLAMP_INGR 0x8561 +#define GL_BLUE_MIN_CLAMP_INGR 0x8562 +#define GL_ALPHA_MIN_CLAMP_INGR 0x8563 +#define GL_RED_MAX_CLAMP_INGR 0x8564 +#define GL_GREEN_MAX_CLAMP_INGR 0x8565 +#define GL_BLUE_MAX_CLAMP_INGR 0x8566 +#define GL_ALPHA_MAX_CLAMP_INGR 0x8567 + +#define GLEW_INGR_color_clamp GLEW_GET_VAR(__GLEW_INGR_color_clamp) + +#endif /* GL_INGR_color_clamp */ + +/* ------------------------- GL_INGR_interlace_read ------------------------ */ + +#ifndef GL_INGR_interlace_read +#define GL_INGR_interlace_read 1 + +#define GL_INTERLACE_READ_INGR 0x8568 + +#define GLEW_INGR_interlace_read GLEW_GET_VAR(__GLEW_INGR_interlace_read) + +#endif /* GL_INGR_interlace_read */ + +/* ------------------------ GL_INTEL_parallel_arrays ----------------------- */ + +#ifndef GL_INTEL_parallel_arrays +#define GL_INTEL_parallel_arrays 1 + +#define GL_PARALLEL_ARRAYS_INTEL 0x83F4 +#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5 +#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6 +#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7 +#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8 + +typedef void (GLAPIENTRY * PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer); +typedef void (GLAPIENTRY * PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const void** pointer); +typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer); + +#define glColorPointervINTEL GLEW_GET_FUN(__glewColorPointervINTEL) +#define glNormalPointervINTEL GLEW_GET_FUN(__glewNormalPointervINTEL) +#define glTexCoordPointervINTEL GLEW_GET_FUN(__glewTexCoordPointervINTEL) +#define glVertexPointervINTEL GLEW_GET_FUN(__glewVertexPointervINTEL) + +#define GLEW_INTEL_parallel_arrays GLEW_GET_VAR(__GLEW_INTEL_parallel_arrays) + +#endif /* GL_INTEL_parallel_arrays */ + +/* ------------------------ GL_INTEL_texture_scissor ----------------------- */ + +#ifndef GL_INTEL_texture_scissor +#define GL_INTEL_texture_scissor 1 + +typedef void (GLAPIENTRY * PFNGLTEXSCISSORFUNCINTELPROC) (GLenum target, GLenum lfunc, GLenum hfunc); +typedef void (GLAPIENTRY * PFNGLTEXSCISSORINTELPROC) (GLenum target, GLclampf tlow, GLclampf thigh); + +#define glTexScissorFuncINTEL GLEW_GET_FUN(__glewTexScissorFuncINTEL) +#define glTexScissorINTEL GLEW_GET_FUN(__glewTexScissorINTEL) + +#define GLEW_INTEL_texture_scissor GLEW_GET_VAR(__GLEW_INTEL_texture_scissor) + +#endif /* GL_INTEL_texture_scissor */ + +/* -------------------------- GL_KTX_buffer_region ------------------------- */ + +#ifndef GL_KTX_buffer_region +#define GL_KTX_buffer_region 1 + +#define GL_KTX_FRONT_REGION 0x0 +#define GL_KTX_BACK_REGION 0x1 +#define GL_KTX_Z_REGION 0x2 +#define GL_KTX_STENCIL_REGION 0x3 + +typedef GLuint (GLAPIENTRY * PFNGLBUFFERREGIONENABLEDEXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLDELETEBUFFERREGIONEXTPROC) (GLenum region); +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERREGIONEXTPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height, GLint xDest, GLint yDest); +typedef GLuint (GLAPIENTRY * PFNGLNEWBUFFERREGIONEXTPROC) (GLenum region); +typedef void (GLAPIENTRY * PFNGLREADBUFFERREGIONEXTPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height); + +#define glBufferRegionEnabledEXT GLEW_GET_FUN(__glewBufferRegionEnabledEXT) +#define glDeleteBufferRegionEXT GLEW_GET_FUN(__glewDeleteBufferRegionEXT) +#define glDrawBufferRegionEXT GLEW_GET_FUN(__glewDrawBufferRegionEXT) +#define glNewBufferRegionEXT GLEW_GET_FUN(__glewNewBufferRegionEXT) +#define glReadBufferRegionEXT GLEW_GET_FUN(__glewReadBufferRegionEXT) + +#define GLEW_KTX_buffer_region GLEW_GET_VAR(__GLEW_KTX_buffer_region) + +#endif /* GL_KTX_buffer_region */ + +/* ------------------------- GL_MESAX_texture_stack ------------------------ */ + +#ifndef GL_MESAX_texture_stack +#define GL_MESAX_texture_stack 1 + +#define GL_TEXTURE_1D_STACK_MESAX 0x8759 +#define GL_TEXTURE_2D_STACK_MESAX 0x875A +#define GL_PROXY_TEXTURE_1D_STACK_MESAX 0x875B +#define GL_PROXY_TEXTURE_2D_STACK_MESAX 0x875C +#define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D +#define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E + +#define GLEW_MESAX_texture_stack GLEW_GET_VAR(__GLEW_MESAX_texture_stack) + +#endif /* GL_MESAX_texture_stack */ + +/* -------------------------- GL_MESA_pack_invert -------------------------- */ + +#ifndef GL_MESA_pack_invert +#define GL_MESA_pack_invert 1 + +#define GL_PACK_INVERT_MESA 0x8758 + +#define GLEW_MESA_pack_invert GLEW_GET_VAR(__GLEW_MESA_pack_invert) + +#endif /* GL_MESA_pack_invert */ + +/* ------------------------- GL_MESA_resize_buffers ------------------------ */ + +#ifndef GL_MESA_resize_buffers +#define GL_MESA_resize_buffers 1 + +typedef void (GLAPIENTRY * PFNGLRESIZEBUFFERSMESAPROC) (void); + +#define glResizeBuffersMESA GLEW_GET_FUN(__glewResizeBuffersMESA) + +#define GLEW_MESA_resize_buffers GLEW_GET_VAR(__GLEW_MESA_resize_buffers) + +#endif /* GL_MESA_resize_buffers */ + +/* --------------------------- GL_MESA_window_pos -------------------------- */ + +#ifndef GL_MESA_window_pos +#define GL_MESA_window_pos 1 + +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVMESAPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVMESAPROC) (const GLshort* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVMESAPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVMESAPROC) (const GLshort* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4IVMESAPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort* p); + +#define glWindowPos2dMESA GLEW_GET_FUN(__glewWindowPos2dMESA) +#define glWindowPos2dvMESA GLEW_GET_FUN(__glewWindowPos2dvMESA) +#define glWindowPos2fMESA GLEW_GET_FUN(__glewWindowPos2fMESA) +#define glWindowPos2fvMESA GLEW_GET_FUN(__glewWindowPos2fvMESA) +#define glWindowPos2iMESA GLEW_GET_FUN(__glewWindowPos2iMESA) +#define glWindowPos2ivMESA GLEW_GET_FUN(__glewWindowPos2ivMESA) +#define glWindowPos2sMESA GLEW_GET_FUN(__glewWindowPos2sMESA) +#define glWindowPos2svMESA GLEW_GET_FUN(__glewWindowPos2svMESA) +#define glWindowPos3dMESA GLEW_GET_FUN(__glewWindowPos3dMESA) +#define glWindowPos3dvMESA GLEW_GET_FUN(__glewWindowPos3dvMESA) +#define glWindowPos3fMESA GLEW_GET_FUN(__glewWindowPos3fMESA) +#define glWindowPos3fvMESA GLEW_GET_FUN(__glewWindowPos3fvMESA) +#define glWindowPos3iMESA GLEW_GET_FUN(__glewWindowPos3iMESA) +#define glWindowPos3ivMESA GLEW_GET_FUN(__glewWindowPos3ivMESA) +#define glWindowPos3sMESA GLEW_GET_FUN(__glewWindowPos3sMESA) +#define glWindowPos3svMESA GLEW_GET_FUN(__glewWindowPos3svMESA) +#define glWindowPos4dMESA GLEW_GET_FUN(__glewWindowPos4dMESA) +#define glWindowPos4dvMESA GLEW_GET_FUN(__glewWindowPos4dvMESA) +#define glWindowPos4fMESA GLEW_GET_FUN(__glewWindowPos4fMESA) +#define glWindowPos4fvMESA GLEW_GET_FUN(__glewWindowPos4fvMESA) +#define glWindowPos4iMESA GLEW_GET_FUN(__glewWindowPos4iMESA) +#define glWindowPos4ivMESA GLEW_GET_FUN(__glewWindowPos4ivMESA) +#define glWindowPos4sMESA GLEW_GET_FUN(__glewWindowPos4sMESA) +#define glWindowPos4svMESA GLEW_GET_FUN(__glewWindowPos4svMESA) + +#define GLEW_MESA_window_pos GLEW_GET_VAR(__GLEW_MESA_window_pos) + +#endif /* GL_MESA_window_pos */ + +/* ------------------------- GL_MESA_ycbcr_texture ------------------------- */ + +#ifndef GL_MESA_ycbcr_texture +#define GL_MESA_ycbcr_texture 1 + +#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB +#define GL_YCBCR_MESA 0x8757 + +#define GLEW_MESA_ycbcr_texture GLEW_GET_VAR(__GLEW_MESA_ycbcr_texture) + +#endif /* GL_MESA_ycbcr_texture */ + +/* ------------------------- GL_NVX_gpu_memory_info ------------------------ */ + +#ifndef GL_NVX_gpu_memory_info +#define GL_NVX_gpu_memory_info 1 + +#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047 +#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 +#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 +#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A +#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B + +#define GLEW_NVX_gpu_memory_info GLEW_GET_VAR(__GLEW_NVX_gpu_memory_info) + +#endif /* GL_NVX_gpu_memory_info */ + +/* --------------------------- GL_NV_blend_square -------------------------- */ + +#ifndef GL_NV_blend_square +#define GL_NV_blend_square 1 + +#define GLEW_NV_blend_square GLEW_GET_VAR(__GLEW_NV_blend_square) + +#endif /* GL_NV_blend_square */ + +/* ------------------------ GL_NV_conditional_render ----------------------- */ + +#ifndef GL_NV_conditional_render +#define GL_NV_conditional_render 1 + +#define GL_QUERY_WAIT_NV 0x8E13 +#define GL_QUERY_NO_WAIT_NV 0x8E14 +#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16 + +typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode); +typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERNVPROC) (void); + +#define glBeginConditionalRenderNV GLEW_GET_FUN(__glewBeginConditionalRenderNV) +#define glEndConditionalRenderNV GLEW_GET_FUN(__glewEndConditionalRenderNV) + +#define GLEW_NV_conditional_render GLEW_GET_VAR(__GLEW_NV_conditional_render) + +#endif /* GL_NV_conditional_render */ + +/* ----------------------- GL_NV_copy_depth_to_color ----------------------- */ + +#ifndef GL_NV_copy_depth_to_color +#define GL_NV_copy_depth_to_color 1 + +#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E +#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F + +#define GLEW_NV_copy_depth_to_color GLEW_GET_VAR(__GLEW_NV_copy_depth_to_color) + +#endif /* GL_NV_copy_depth_to_color */ + +/* ---------------------------- GL_NV_copy_image --------------------------- */ + +#ifndef GL_NV_copy_image +#define GL_NV_copy_image 1 + +typedef void (GLAPIENTRY * PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); + +#define glCopyImageSubDataNV GLEW_GET_FUN(__glewCopyImageSubDataNV) + +#define GLEW_NV_copy_image GLEW_GET_VAR(__GLEW_NV_copy_image) + +#endif /* GL_NV_copy_image */ + +/* ------------------------ GL_NV_depth_buffer_float ----------------------- */ + +#ifndef GL_NV_depth_buffer_float +#define GL_NV_depth_buffer_float 1 + +#define GL_DEPTH_COMPONENT32F_NV 0x8DAB +#define GL_DEPTH32F_STENCIL8_NV 0x8DAC +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD +#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF + +typedef void (GLAPIENTRY * PFNGLCLEARDEPTHDNVPROC) (GLdouble depth); +typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax); +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar); + +#define glClearDepthdNV GLEW_GET_FUN(__glewClearDepthdNV) +#define glDepthBoundsdNV GLEW_GET_FUN(__glewDepthBoundsdNV) +#define glDepthRangedNV GLEW_GET_FUN(__glewDepthRangedNV) + +#define GLEW_NV_depth_buffer_float GLEW_GET_VAR(__GLEW_NV_depth_buffer_float) + +#endif /* GL_NV_depth_buffer_float */ + +/* --------------------------- GL_NV_depth_clamp --------------------------- */ + +#ifndef GL_NV_depth_clamp +#define GL_NV_depth_clamp 1 + +#define GL_DEPTH_CLAMP_NV 0x864F + +#define GLEW_NV_depth_clamp GLEW_GET_VAR(__GLEW_NV_depth_clamp) + +#endif /* GL_NV_depth_clamp */ + +/* ---------------------- GL_NV_depth_range_unclamped ---------------------- */ + +#ifndef GL_NV_depth_range_unclamped +#define GL_NV_depth_range_unclamped 1 + +#define GL_SAMPLE_COUNT_BITS_NV 0x8864 +#define GL_CURRENT_SAMPLE_COUNT_QUERY_NV 0x8865 +#define GL_QUERY_RESULT_NV 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_NV 0x8867 +#define GL_SAMPLE_COUNT_NV 0x8914 + +#define GLEW_NV_depth_range_unclamped GLEW_GET_VAR(__GLEW_NV_depth_range_unclamped) + +#endif /* GL_NV_depth_range_unclamped */ + +/* ---------------------------- GL_NV_evaluators --------------------------- */ + +#ifndef GL_NV_evaluators +#define GL_NV_evaluators 1 + +#define GL_EVAL_2D_NV 0x86C0 +#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1 +#define GL_MAP_TESSELLATION_NV 0x86C2 +#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3 +#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4 +#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5 +#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6 +#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7 +#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8 +#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9 +#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA +#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB +#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC +#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD +#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE +#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF +#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0 +#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1 +#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2 +#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3 +#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4 +#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5 +#define GL_MAX_MAP_TESSELLATION_NV 0x86D6 +#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7 + +typedef void (GLAPIENTRY * PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode); +typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void* points); +typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void* points); +typedef void (GLAPIENTRY * PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint* params); + +#define glEvalMapsNV GLEW_GET_FUN(__glewEvalMapsNV) +#define glGetMapAttribParameterfvNV GLEW_GET_FUN(__glewGetMapAttribParameterfvNV) +#define glGetMapAttribParameterivNV GLEW_GET_FUN(__glewGetMapAttribParameterivNV) +#define glGetMapControlPointsNV GLEW_GET_FUN(__glewGetMapControlPointsNV) +#define glGetMapParameterfvNV GLEW_GET_FUN(__glewGetMapParameterfvNV) +#define glGetMapParameterivNV GLEW_GET_FUN(__glewGetMapParameterivNV) +#define glMapControlPointsNV GLEW_GET_FUN(__glewMapControlPointsNV) +#define glMapParameterfvNV GLEW_GET_FUN(__glewMapParameterfvNV) +#define glMapParameterivNV GLEW_GET_FUN(__glewMapParameterivNV) + +#define GLEW_NV_evaluators GLEW_GET_VAR(__GLEW_NV_evaluators) + +#endif /* GL_NV_evaluators */ + +/* ----------------------- GL_NV_explicit_multisample ---------------------- */ + +#ifndef GL_NV_explicit_multisample +#define GL_NV_explicit_multisample 1 + +#define GL_SAMPLE_POSITION_NV 0x8E50 +#define GL_SAMPLE_MASK_NV 0x8E51 +#define GL_SAMPLE_MASK_VALUE_NV 0x8E52 +#define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53 +#define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54 +#define GL_TEXTURE_RENDERBUFFER_NV 0x8E55 +#define GL_SAMPLER_RENDERBUFFER_NV 0x8E56 +#define GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57 +#define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58 +#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59 + +typedef void (GLAPIENTRY * PFNGLGETMULTISAMPLEFVNVPROC) (GLenum pname, GLuint index, GLfloat* val); +typedef void (GLAPIENTRY * PFNGLSAMPLEMASKINDEXEDNVPROC) (GLuint index, GLbitfield mask); +typedef void (GLAPIENTRY * PFNGLTEXRENDERBUFFERNVPROC) (GLenum target, GLuint renderbuffer); + +#define glGetMultisamplefvNV GLEW_GET_FUN(__glewGetMultisamplefvNV) +#define glSampleMaskIndexedNV GLEW_GET_FUN(__glewSampleMaskIndexedNV) +#define glTexRenderbufferNV GLEW_GET_FUN(__glewTexRenderbufferNV) + +#define GLEW_NV_explicit_multisample GLEW_GET_VAR(__GLEW_NV_explicit_multisample) + +#endif /* GL_NV_explicit_multisample */ + +/* ------------------------------ GL_NV_fence ------------------------------ */ + +#ifndef GL_NV_fence +#define GL_NV_fence 1 + +#define GL_ALL_COMPLETED_NV 0x84F2 +#define GL_FENCE_STATUS_NV 0x84F3 +#define GL_FENCE_CONDITION_NV 0x84F4 + +typedef void (GLAPIENTRY * PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint* fences); +typedef void (GLAPIENTRY * PFNGLFINISHFENCENVPROC) (GLuint fence); +typedef void (GLAPIENTRY * PFNGLGENFENCESNVPROC) (GLsizei n, GLuint* fences); +typedef void (GLAPIENTRY * PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISFENCENVPROC) (GLuint fence); +typedef void (GLAPIENTRY * PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); +typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCENVPROC) (GLuint fence); + +#define glDeleteFencesNV GLEW_GET_FUN(__glewDeleteFencesNV) +#define glFinishFenceNV GLEW_GET_FUN(__glewFinishFenceNV) +#define glGenFencesNV GLEW_GET_FUN(__glewGenFencesNV) +#define glGetFenceivNV GLEW_GET_FUN(__glewGetFenceivNV) +#define glIsFenceNV GLEW_GET_FUN(__glewIsFenceNV) +#define glSetFenceNV GLEW_GET_FUN(__glewSetFenceNV) +#define glTestFenceNV GLEW_GET_FUN(__glewTestFenceNV) + +#define GLEW_NV_fence GLEW_GET_VAR(__GLEW_NV_fence) + +#endif /* GL_NV_fence */ + +/* --------------------------- GL_NV_float_buffer -------------------------- */ + +#ifndef GL_NV_float_buffer +#define GL_NV_float_buffer 1 + +#define GL_FLOAT_R_NV 0x8880 +#define GL_FLOAT_RG_NV 0x8881 +#define GL_FLOAT_RGB_NV 0x8882 +#define GL_FLOAT_RGBA_NV 0x8883 +#define GL_FLOAT_R16_NV 0x8884 +#define GL_FLOAT_R32_NV 0x8885 +#define GL_FLOAT_RG16_NV 0x8886 +#define GL_FLOAT_RG32_NV 0x8887 +#define GL_FLOAT_RGB16_NV 0x8888 +#define GL_FLOAT_RGB32_NV 0x8889 +#define GL_FLOAT_RGBA16_NV 0x888A +#define GL_FLOAT_RGBA32_NV 0x888B +#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C +#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D +#define GL_FLOAT_RGBA_MODE_NV 0x888E + +#define GLEW_NV_float_buffer GLEW_GET_VAR(__GLEW_NV_float_buffer) + +#endif /* GL_NV_float_buffer */ + +/* --------------------------- GL_NV_fog_distance -------------------------- */ + +#ifndef GL_NV_fog_distance +#define GL_NV_fog_distance 1 + +#define GL_FOG_DISTANCE_MODE_NV 0x855A +#define GL_EYE_RADIAL_NV 0x855B +#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C + +#define GLEW_NV_fog_distance GLEW_GET_VAR(__GLEW_NV_fog_distance) + +#endif /* GL_NV_fog_distance */ + +/* ------------------------- GL_NV_fragment_program ------------------------ */ + +#ifndef GL_NV_fragment_program +#define GL_NV_fragment_program 1 + +#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868 +#define GL_FRAGMENT_PROGRAM_NV 0x8870 +#define GL_MAX_TEXTURE_COORDS_NV 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872 +#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873 +#define GL_PROGRAM_ERROR_STRING_NV 0x8874 + +typedef void (GLAPIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLdouble *params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, const GLdouble v[]); +typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, const GLfloat v[]); + +#define glGetProgramNamedParameterdvNV GLEW_GET_FUN(__glewGetProgramNamedParameterdvNV) +#define glGetProgramNamedParameterfvNV GLEW_GET_FUN(__glewGetProgramNamedParameterfvNV) +#define glProgramNamedParameter4dNV GLEW_GET_FUN(__glewProgramNamedParameter4dNV) +#define glProgramNamedParameter4dvNV GLEW_GET_FUN(__glewProgramNamedParameter4dvNV) +#define glProgramNamedParameter4fNV GLEW_GET_FUN(__glewProgramNamedParameter4fNV) +#define glProgramNamedParameter4fvNV GLEW_GET_FUN(__glewProgramNamedParameter4fvNV) + +#define GLEW_NV_fragment_program GLEW_GET_VAR(__GLEW_NV_fragment_program) + +#endif /* GL_NV_fragment_program */ + +/* ------------------------ GL_NV_fragment_program2 ------------------------ */ + +#ifndef GL_NV_fragment_program2 +#define GL_NV_fragment_program2 1 + +#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 +#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 +#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6 +#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7 +#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8 + +#define GLEW_NV_fragment_program2 GLEW_GET_VAR(__GLEW_NV_fragment_program2) + +#endif /* GL_NV_fragment_program2 */ + +/* ------------------------ GL_NV_fragment_program4 ------------------------ */ + +#ifndef GL_NV_fragment_program4 +#define GL_NV_fragment_program4 1 + +#define GLEW_NV_fragment_program4 GLEW_GET_VAR(__GLEW_NV_fragment_program4) + +#endif /* GL_NV_fragment_program4 */ + +/* --------------------- GL_NV_fragment_program_option --------------------- */ + +#ifndef GL_NV_fragment_program_option +#define GL_NV_fragment_program_option 1 + +#define GLEW_NV_fragment_program_option GLEW_GET_VAR(__GLEW_NV_fragment_program_option) + +#endif /* GL_NV_fragment_program_option */ + +/* ----------------- GL_NV_framebuffer_multisample_coverage ---------------- */ + +#ifndef GL_NV_framebuffer_multisample_coverage +#define GL_NV_framebuffer_multisample_coverage 1 + +#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB +#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10 +#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11 +#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12 + +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); + +#define glRenderbufferStorageMultisampleCoverageNV GLEW_GET_FUN(__glewRenderbufferStorageMultisampleCoverageNV) + +#define GLEW_NV_framebuffer_multisample_coverage GLEW_GET_VAR(__GLEW_NV_framebuffer_multisample_coverage) + +#endif /* GL_NV_framebuffer_multisample_coverage */ + +/* ------------------------ GL_NV_geometry_program4 ------------------------ */ + +#ifndef GL_NV_geometry_program4 +#define GL_NV_geometry_program4 1 + +#define GL_GEOMETRY_PROGRAM_NV 0x8C26 +#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27 +#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28 + +typedef void (GLAPIENTRY * PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit); + +#define glProgramVertexLimitNV GLEW_GET_FUN(__glewProgramVertexLimitNV) + +#define GLEW_NV_geometry_program4 GLEW_GET_VAR(__GLEW_NV_geometry_program4) + +#endif /* GL_NV_geometry_program4 */ + +/* ------------------------- GL_NV_geometry_shader4 ------------------------ */ + +#ifndef GL_NV_geometry_shader4 +#define GL_NV_geometry_shader4 1 + +#define GLEW_NV_geometry_shader4 GLEW_GET_VAR(__GLEW_NV_geometry_shader4) + +#endif /* GL_NV_geometry_shader4 */ + +/* --------------------------- GL_NV_gpu_program4 -------------------------- */ + +#ifndef GL_NV_gpu_program4 +#define GL_NV_gpu_program4 1 + +#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET_NV 0x8905 +#define GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906 +#define GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907 +#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908 +#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909 +#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5 +#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6 + +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params); + +#define glProgramEnvParameterI4iNV GLEW_GET_FUN(__glewProgramEnvParameterI4iNV) +#define glProgramEnvParameterI4ivNV GLEW_GET_FUN(__glewProgramEnvParameterI4ivNV) +#define glProgramEnvParameterI4uiNV GLEW_GET_FUN(__glewProgramEnvParameterI4uiNV) +#define glProgramEnvParameterI4uivNV GLEW_GET_FUN(__glewProgramEnvParameterI4uivNV) +#define glProgramEnvParametersI4ivNV GLEW_GET_FUN(__glewProgramEnvParametersI4ivNV) +#define glProgramEnvParametersI4uivNV GLEW_GET_FUN(__glewProgramEnvParametersI4uivNV) +#define glProgramLocalParameterI4iNV GLEW_GET_FUN(__glewProgramLocalParameterI4iNV) +#define glProgramLocalParameterI4ivNV GLEW_GET_FUN(__glewProgramLocalParameterI4ivNV) +#define glProgramLocalParameterI4uiNV GLEW_GET_FUN(__glewProgramLocalParameterI4uiNV) +#define glProgramLocalParameterI4uivNV GLEW_GET_FUN(__glewProgramLocalParameterI4uivNV) +#define glProgramLocalParametersI4ivNV GLEW_GET_FUN(__glewProgramLocalParametersI4ivNV) +#define glProgramLocalParametersI4uivNV GLEW_GET_FUN(__glewProgramLocalParametersI4uivNV) + +#define GLEW_NV_gpu_program4 GLEW_GET_VAR(__GLEW_NV_gpu_program4) + +#endif /* GL_NV_gpu_program4 */ + +/* --------------------------- GL_NV_gpu_program5 -------------------------- */ + +#ifndef GL_NV_gpu_program5 +#define GL_NV_gpu_program5 1 + +#define GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV 0x8E5A +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5B +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5C +#define GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV 0x8E5D +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5F + +#define GLEW_NV_gpu_program5 GLEW_GET_VAR(__GLEW_NV_gpu_program5) + +#endif /* GL_NV_gpu_program5 */ + +/* ------------------------- GL_NV_gpu_program_fp64 ------------------------ */ + +#ifndef GL_NV_gpu_program_fp64 +#define GL_NV_gpu_program_fp64 1 + +#define GLEW_NV_gpu_program_fp64 GLEW_GET_VAR(__GLEW_NV_gpu_program_fp64) + +#endif /* GL_NV_gpu_program_fp64 */ + +/* --------------------------- GL_NV_gpu_shader5 --------------------------- */ + +#ifndef GL_NV_gpu_shader5 +#define GL_NV_gpu_shader5 1 + +#define GL_INT64_NV 0x140E +#define GL_UNSIGNED_INT64_NV 0x140F +#define GL_INT8_NV 0x8FE0 +#define GL_INT8_VEC2_NV 0x8FE1 +#define GL_INT8_VEC3_NV 0x8FE2 +#define GL_INT8_VEC4_NV 0x8FE3 +#define GL_INT16_NV 0x8FE4 +#define GL_INT16_VEC2_NV 0x8FE5 +#define GL_INT16_VEC3_NV 0x8FE6 +#define GL_INT16_VEC4_NV 0x8FE7 +#define GL_INT64_VEC2_NV 0x8FE9 +#define GL_INT64_VEC3_NV 0x8FEA +#define GL_INT64_VEC4_NV 0x8FEB +#define GL_UNSIGNED_INT8_NV 0x8FEC +#define GL_UNSIGNED_INT8_VEC2_NV 0x8FED +#define GL_UNSIGNED_INT8_VEC3_NV 0x8FEE +#define GL_UNSIGNED_INT8_VEC4_NV 0x8FEF +#define GL_UNSIGNED_INT16_NV 0x8FF0 +#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1 +#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2 +#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3 +#define GL_UNSIGNED_INT64_VEC2_NV 0x8FF5 +#define GL_UNSIGNED_INT64_VEC3_NV 0x8FF6 +#define GL_UNSIGNED_INT64_VEC4_NV 0x8FF7 +#define GL_FLOAT16_NV 0x8FF8 +#define GL_FLOAT16_VEC2_NV 0x8FF9 +#define GL_FLOAT16_VEC3_NV 0x8FFA +#define GL_FLOAT16_VEC4_NV 0x8FFB + +typedef void (GLAPIENTRY * PFNGLGETUNIFORMI64VNVPROC) (GLuint program, GLint location, GLint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLuint64EXT* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1I64NVPROC) (GLuint program, GLint location, GLint64EXT x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x); +typedef void (GLAPIENTRY * PFNGLUNIFORM1I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UI64NVPROC) (GLint location, GLuint64EXT x); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y); +typedef void (GLAPIENTRY * PFNGLUNIFORM2I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); +typedef void (GLAPIENTRY * PFNGLUNIFORM3I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +typedef void (GLAPIENTRY * PFNGLUNIFORM4I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); + +#define glGetUniformi64vNV GLEW_GET_FUN(__glewGetUniformi64vNV) +#define glGetUniformui64vNV GLEW_GET_FUN(__glewGetUniformui64vNV) +#define glProgramUniform1i64NV GLEW_GET_FUN(__glewProgramUniform1i64NV) +#define glProgramUniform1i64vNV GLEW_GET_FUN(__glewProgramUniform1i64vNV) +#define glProgramUniform1ui64NV GLEW_GET_FUN(__glewProgramUniform1ui64NV) +#define glProgramUniform1ui64vNV GLEW_GET_FUN(__glewProgramUniform1ui64vNV) +#define glProgramUniform2i64NV GLEW_GET_FUN(__glewProgramUniform2i64NV) +#define glProgramUniform2i64vNV GLEW_GET_FUN(__glewProgramUniform2i64vNV) +#define glProgramUniform2ui64NV GLEW_GET_FUN(__glewProgramUniform2ui64NV) +#define glProgramUniform2ui64vNV GLEW_GET_FUN(__glewProgramUniform2ui64vNV) +#define glProgramUniform3i64NV GLEW_GET_FUN(__glewProgramUniform3i64NV) +#define glProgramUniform3i64vNV GLEW_GET_FUN(__glewProgramUniform3i64vNV) +#define glProgramUniform3ui64NV GLEW_GET_FUN(__glewProgramUniform3ui64NV) +#define glProgramUniform3ui64vNV GLEW_GET_FUN(__glewProgramUniform3ui64vNV) +#define glProgramUniform4i64NV GLEW_GET_FUN(__glewProgramUniform4i64NV) +#define glProgramUniform4i64vNV GLEW_GET_FUN(__glewProgramUniform4i64vNV) +#define glProgramUniform4ui64NV GLEW_GET_FUN(__glewProgramUniform4ui64NV) +#define glProgramUniform4ui64vNV GLEW_GET_FUN(__glewProgramUniform4ui64vNV) +#define glUniform1i64NV GLEW_GET_FUN(__glewUniform1i64NV) +#define glUniform1i64vNV GLEW_GET_FUN(__glewUniform1i64vNV) +#define glUniform1ui64NV GLEW_GET_FUN(__glewUniform1ui64NV) +#define glUniform1ui64vNV GLEW_GET_FUN(__glewUniform1ui64vNV) +#define glUniform2i64NV GLEW_GET_FUN(__glewUniform2i64NV) +#define glUniform2i64vNV GLEW_GET_FUN(__glewUniform2i64vNV) +#define glUniform2ui64NV GLEW_GET_FUN(__glewUniform2ui64NV) +#define glUniform2ui64vNV GLEW_GET_FUN(__glewUniform2ui64vNV) +#define glUniform3i64NV GLEW_GET_FUN(__glewUniform3i64NV) +#define glUniform3i64vNV GLEW_GET_FUN(__glewUniform3i64vNV) +#define glUniform3ui64NV GLEW_GET_FUN(__glewUniform3ui64NV) +#define glUniform3ui64vNV GLEW_GET_FUN(__glewUniform3ui64vNV) +#define glUniform4i64NV GLEW_GET_FUN(__glewUniform4i64NV) +#define glUniform4i64vNV GLEW_GET_FUN(__glewUniform4i64vNV) +#define glUniform4ui64NV GLEW_GET_FUN(__glewUniform4ui64NV) +#define glUniform4ui64vNV GLEW_GET_FUN(__glewUniform4ui64vNV) + +#define GLEW_NV_gpu_shader5 GLEW_GET_VAR(__GLEW_NV_gpu_shader5) + +#endif /* GL_NV_gpu_shader5 */ + +/* ---------------------------- GL_NV_half_float --------------------------- */ + +#ifndef GL_NV_half_float +#define GL_NV_half_float 1 + +#define GL_HALF_FLOAT_NV 0x140B + +typedef unsigned short GLhalf; + +typedef void (GLAPIENTRY * PFNGLCOLOR3HNVPROC) (GLhalf red, GLhalf green, GLhalf blue); +typedef void (GLAPIENTRY * PFNGLCOLOR3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLCOLOR4HNVPROC) (GLhalf red, GLhalf green, GLhalf blue, GLhalf alpha); +typedef void (GLAPIENTRY * PFNGLCOLOR4HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLFOGCOORDHNVPROC) (GLhalf fog); +typedef void (GLAPIENTRY * PFNGLFOGCOORDHVNVPROC) (const GLhalf* fog); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalf s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalf s, GLhalf t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalf s, GLhalf t, GLhalf r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalf s, GLhalf t, GLhalf r, GLhalf q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLNORMAL3HNVPROC) (GLhalf nx, GLhalf ny, GLhalf nz); +typedef void (GLAPIENTRY * PFNGLNORMAL3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3HNVPROC) (GLhalf red, GLhalf green, GLhalf blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD1HNVPROC) (GLhalf s); +typedef void (GLAPIENTRY * PFNGLTEXCOORD1HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2HNVPROC) (GLhalf s, GLhalf t); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD3HNVPROC) (GLhalf s, GLhalf t, GLhalf r); +typedef void (GLAPIENTRY * PFNGLTEXCOORD3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4HNVPROC) (GLhalf s, GLhalf t, GLhalf r, GLhalf q); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEX2HNVPROC) (GLhalf x, GLhalf y); +typedef void (GLAPIENTRY * PFNGLVERTEX2HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEX3HNVPROC) (GLhalf x, GLhalf y, GLhalf z); +typedef void (GLAPIENTRY * PFNGLVERTEX3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEX4HNVPROC) (GLhalf x, GLhalf y, GLhalf z, GLhalf w); +typedef void (GLAPIENTRY * PFNGLVERTEX4HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalf x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalf x, GLhalf y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalf x, GLhalf y, GLhalf z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalf x, GLhalf y, GLhalf z, GLhalf w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHNVPROC) (GLhalf weight); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalf* weight); + +#define glColor3hNV GLEW_GET_FUN(__glewColor3hNV) +#define glColor3hvNV GLEW_GET_FUN(__glewColor3hvNV) +#define glColor4hNV GLEW_GET_FUN(__glewColor4hNV) +#define glColor4hvNV GLEW_GET_FUN(__glewColor4hvNV) +#define glFogCoordhNV GLEW_GET_FUN(__glewFogCoordhNV) +#define glFogCoordhvNV GLEW_GET_FUN(__glewFogCoordhvNV) +#define glMultiTexCoord1hNV GLEW_GET_FUN(__glewMultiTexCoord1hNV) +#define glMultiTexCoord1hvNV GLEW_GET_FUN(__glewMultiTexCoord1hvNV) +#define glMultiTexCoord2hNV GLEW_GET_FUN(__glewMultiTexCoord2hNV) +#define glMultiTexCoord2hvNV GLEW_GET_FUN(__glewMultiTexCoord2hvNV) +#define glMultiTexCoord3hNV GLEW_GET_FUN(__glewMultiTexCoord3hNV) +#define glMultiTexCoord3hvNV GLEW_GET_FUN(__glewMultiTexCoord3hvNV) +#define glMultiTexCoord4hNV GLEW_GET_FUN(__glewMultiTexCoord4hNV) +#define glMultiTexCoord4hvNV GLEW_GET_FUN(__glewMultiTexCoord4hvNV) +#define glNormal3hNV GLEW_GET_FUN(__glewNormal3hNV) +#define glNormal3hvNV GLEW_GET_FUN(__glewNormal3hvNV) +#define glSecondaryColor3hNV GLEW_GET_FUN(__glewSecondaryColor3hNV) +#define glSecondaryColor3hvNV GLEW_GET_FUN(__glewSecondaryColor3hvNV) +#define glTexCoord1hNV GLEW_GET_FUN(__glewTexCoord1hNV) +#define glTexCoord1hvNV GLEW_GET_FUN(__glewTexCoord1hvNV) +#define glTexCoord2hNV GLEW_GET_FUN(__glewTexCoord2hNV) +#define glTexCoord2hvNV GLEW_GET_FUN(__glewTexCoord2hvNV) +#define glTexCoord3hNV GLEW_GET_FUN(__glewTexCoord3hNV) +#define glTexCoord3hvNV GLEW_GET_FUN(__glewTexCoord3hvNV) +#define glTexCoord4hNV GLEW_GET_FUN(__glewTexCoord4hNV) +#define glTexCoord4hvNV GLEW_GET_FUN(__glewTexCoord4hvNV) +#define glVertex2hNV GLEW_GET_FUN(__glewVertex2hNV) +#define glVertex2hvNV GLEW_GET_FUN(__glewVertex2hvNV) +#define glVertex3hNV GLEW_GET_FUN(__glewVertex3hNV) +#define glVertex3hvNV GLEW_GET_FUN(__glewVertex3hvNV) +#define glVertex4hNV GLEW_GET_FUN(__glewVertex4hNV) +#define glVertex4hvNV GLEW_GET_FUN(__glewVertex4hvNV) +#define glVertexAttrib1hNV GLEW_GET_FUN(__glewVertexAttrib1hNV) +#define glVertexAttrib1hvNV GLEW_GET_FUN(__glewVertexAttrib1hvNV) +#define glVertexAttrib2hNV GLEW_GET_FUN(__glewVertexAttrib2hNV) +#define glVertexAttrib2hvNV GLEW_GET_FUN(__glewVertexAttrib2hvNV) +#define glVertexAttrib3hNV GLEW_GET_FUN(__glewVertexAttrib3hNV) +#define glVertexAttrib3hvNV GLEW_GET_FUN(__glewVertexAttrib3hvNV) +#define glVertexAttrib4hNV GLEW_GET_FUN(__glewVertexAttrib4hNV) +#define glVertexAttrib4hvNV GLEW_GET_FUN(__glewVertexAttrib4hvNV) +#define glVertexAttribs1hvNV GLEW_GET_FUN(__glewVertexAttribs1hvNV) +#define glVertexAttribs2hvNV GLEW_GET_FUN(__glewVertexAttribs2hvNV) +#define glVertexAttribs3hvNV GLEW_GET_FUN(__glewVertexAttribs3hvNV) +#define glVertexAttribs4hvNV GLEW_GET_FUN(__glewVertexAttribs4hvNV) +#define glVertexWeighthNV GLEW_GET_FUN(__glewVertexWeighthNV) +#define glVertexWeighthvNV GLEW_GET_FUN(__glewVertexWeighthvNV) + +#define GLEW_NV_half_float GLEW_GET_VAR(__GLEW_NV_half_float) + +#endif /* GL_NV_half_float */ + +/* ------------------------ GL_NV_light_max_exponent ----------------------- */ + +#ifndef GL_NV_light_max_exponent +#define GL_NV_light_max_exponent 1 + +#define GL_MAX_SHININESS_NV 0x8504 +#define GL_MAX_SPOT_EXPONENT_NV 0x8505 + +#define GLEW_NV_light_max_exponent GLEW_GET_VAR(__GLEW_NV_light_max_exponent) + +#endif /* GL_NV_light_max_exponent */ + +/* ----------------------- GL_NV_multisample_coverage ---------------------- */ + +#ifndef GL_NV_multisample_coverage +#define GL_NV_multisample_coverage 1 + +#define GL_COVERAGE_SAMPLES_NV 0x80A9 +#define GL_COLOR_SAMPLES_NV 0x8E20 + +#define GLEW_NV_multisample_coverage GLEW_GET_VAR(__GLEW_NV_multisample_coverage) + +#endif /* GL_NV_multisample_coverage */ + +/* --------------------- GL_NV_multisample_filter_hint --------------------- */ + +#ifndef GL_NV_multisample_filter_hint +#define GL_NV_multisample_filter_hint 1 + +#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 + +#define GLEW_NV_multisample_filter_hint GLEW_GET_VAR(__GLEW_NV_multisample_filter_hint) + +#endif /* GL_NV_multisample_filter_hint */ + +/* ------------------------- GL_NV_occlusion_query ------------------------- */ + +#ifndef GL_NV_occlusion_query +#define GL_NV_occlusion_query 1 + +#define GL_PIXEL_COUNTER_BITS_NV 0x8864 +#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865 +#define GL_PIXEL_COUNT_NV 0x8866 +#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867 + +typedef void (GLAPIENTRY * PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLENDOCCLUSIONQUERYNVPROC) (void); +typedef void (GLAPIENTRY * PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id); + +#define glBeginOcclusionQueryNV GLEW_GET_FUN(__glewBeginOcclusionQueryNV) +#define glDeleteOcclusionQueriesNV GLEW_GET_FUN(__glewDeleteOcclusionQueriesNV) +#define glEndOcclusionQueryNV GLEW_GET_FUN(__glewEndOcclusionQueryNV) +#define glGenOcclusionQueriesNV GLEW_GET_FUN(__glewGenOcclusionQueriesNV) +#define glGetOcclusionQueryivNV GLEW_GET_FUN(__glewGetOcclusionQueryivNV) +#define glGetOcclusionQueryuivNV GLEW_GET_FUN(__glewGetOcclusionQueryuivNV) +#define glIsOcclusionQueryNV GLEW_GET_FUN(__glewIsOcclusionQueryNV) + +#define GLEW_NV_occlusion_query GLEW_GET_VAR(__GLEW_NV_occlusion_query) + +#endif /* GL_NV_occlusion_query */ + +/* ----------------------- GL_NV_packed_depth_stencil ---------------------- */ + +#ifndef GL_NV_packed_depth_stencil +#define GL_NV_packed_depth_stencil 1 + +#define GL_DEPTH_STENCIL_NV 0x84F9 +#define GL_UNSIGNED_INT_24_8_NV 0x84FA + +#define GLEW_NV_packed_depth_stencil GLEW_GET_VAR(__GLEW_NV_packed_depth_stencil) + +#endif /* GL_NV_packed_depth_stencil */ + +/* --------------------- GL_NV_parameter_buffer_object --------------------- */ + +#ifndef GL_NV_parameter_buffer_object +#define GL_NV_parameter_buffer_object 1 + +#define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0 +#define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1 +#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2 +#define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3 +#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4 + +typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat *params); + +#define glProgramBufferParametersIivNV GLEW_GET_FUN(__glewProgramBufferParametersIivNV) +#define glProgramBufferParametersIuivNV GLEW_GET_FUN(__glewProgramBufferParametersIuivNV) +#define glProgramBufferParametersfvNV GLEW_GET_FUN(__glewProgramBufferParametersfvNV) + +#define GLEW_NV_parameter_buffer_object GLEW_GET_VAR(__GLEW_NV_parameter_buffer_object) + +#endif /* GL_NV_parameter_buffer_object */ + +/* --------------------- GL_NV_parameter_buffer_object2 -------------------- */ + +#ifndef GL_NV_parameter_buffer_object2 +#define GL_NV_parameter_buffer_object2 1 + +#define GLEW_NV_parameter_buffer_object2 GLEW_GET_VAR(__GLEW_NV_parameter_buffer_object2) + +#endif /* GL_NV_parameter_buffer_object2 */ + +/* ------------------------- GL_NV_pixel_data_range ------------------------ */ + +#ifndef GL_NV_pixel_data_range +#define GL_NV_pixel_data_range 1 + +#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878 +#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879 +#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A +#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B +#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C +#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D + +typedef void (GLAPIENTRY * PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, void* pointer); + +#define glFlushPixelDataRangeNV GLEW_GET_FUN(__glewFlushPixelDataRangeNV) +#define glPixelDataRangeNV GLEW_GET_FUN(__glewPixelDataRangeNV) + +#define GLEW_NV_pixel_data_range GLEW_GET_VAR(__GLEW_NV_pixel_data_range) + +#endif /* GL_NV_pixel_data_range */ + +/* --------------------------- GL_NV_point_sprite -------------------------- */ + +#ifndef GL_NV_point_sprite +#define GL_NV_point_sprite 1 + +#define GL_POINT_SPRITE_NV 0x8861 +#define GL_COORD_REPLACE_NV 0x8862 +#define GL_POINT_SPRITE_R_MODE_NV 0x8863 + +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint* params); + +#define glPointParameteriNV GLEW_GET_FUN(__glewPointParameteriNV) +#define glPointParameterivNV GLEW_GET_FUN(__glewPointParameterivNV) + +#define GLEW_NV_point_sprite GLEW_GET_VAR(__GLEW_NV_point_sprite) + +#endif /* GL_NV_point_sprite */ + +/* -------------------------- GL_NV_present_video -------------------------- */ + +#ifndef GL_NV_present_video +#define GL_NV_present_video 1 + +#define GL_FRAME_NV 0x8E26 +#define GL_FIELDS_NV 0x8E27 +#define GL_CURRENT_TIME_NV 0x8E28 +#define GL_NUM_FILL_STREAMS_NV 0x8E29 +#define GL_PRESENT_TIME_NV 0x8E2A +#define GL_PRESENT_DURATION_NV 0x8E2B + +typedef void (GLAPIENTRY * PFNGLGETVIDEOI64VNVPROC) (GLuint video_slot, GLenum pname, GLint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOIVNVPROC) (GLuint video_slot, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOUI64VNVPROC) (GLuint video_slot, GLenum pname, GLuint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOUIVNVPROC) (GLuint video_slot, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLPRESENTFRAMEDUALFILLNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3); +typedef void (GLAPIENTRY * PFNGLPRESENTFRAMEKEYEDNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1); + +#define glGetVideoi64vNV GLEW_GET_FUN(__glewGetVideoi64vNV) +#define glGetVideoivNV GLEW_GET_FUN(__glewGetVideoivNV) +#define glGetVideoui64vNV GLEW_GET_FUN(__glewGetVideoui64vNV) +#define glGetVideouivNV GLEW_GET_FUN(__glewGetVideouivNV) +#define glPresentFrameDualFillNV GLEW_GET_FUN(__glewPresentFrameDualFillNV) +#define glPresentFrameKeyedNV GLEW_GET_FUN(__glewPresentFrameKeyedNV) + +#define GLEW_NV_present_video GLEW_GET_VAR(__GLEW_NV_present_video) + +#endif /* GL_NV_present_video */ + +/* ------------------------ GL_NV_primitive_restart ------------------------ */ + +#ifndef GL_NV_primitive_restart +#define GL_NV_primitive_restart 1 + +#define GL_PRIMITIVE_RESTART_NV 0x8558 +#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559 + +typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index); +typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTNVPROC) (void); + +#define glPrimitiveRestartIndexNV GLEW_GET_FUN(__glewPrimitiveRestartIndexNV) +#define glPrimitiveRestartNV GLEW_GET_FUN(__glewPrimitiveRestartNV) + +#define GLEW_NV_primitive_restart GLEW_GET_VAR(__GLEW_NV_primitive_restart) + +#endif /* GL_NV_primitive_restart */ + +/* ------------------------ GL_NV_register_combiners ----------------------- */ + +#ifndef GL_NV_register_combiners +#define GL_NV_register_combiners 1 + +#define GL_REGISTER_COMBINERS_NV 0x8522 +#define GL_VARIABLE_A_NV 0x8523 +#define GL_VARIABLE_B_NV 0x8524 +#define GL_VARIABLE_C_NV 0x8525 +#define GL_VARIABLE_D_NV 0x8526 +#define GL_VARIABLE_E_NV 0x8527 +#define GL_VARIABLE_F_NV 0x8528 +#define GL_VARIABLE_G_NV 0x8529 +#define GL_CONSTANT_COLOR0_NV 0x852A +#define GL_CONSTANT_COLOR1_NV 0x852B +#define GL_PRIMARY_COLOR_NV 0x852C +#define GL_SECONDARY_COLOR_NV 0x852D +#define GL_SPARE0_NV 0x852E +#define GL_SPARE1_NV 0x852F +#define GL_DISCARD_NV 0x8530 +#define GL_E_TIMES_F_NV 0x8531 +#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532 +#define GL_UNSIGNED_IDENTITY_NV 0x8536 +#define GL_UNSIGNED_INVERT_NV 0x8537 +#define GL_EXPAND_NORMAL_NV 0x8538 +#define GL_EXPAND_NEGATE_NV 0x8539 +#define GL_HALF_BIAS_NORMAL_NV 0x853A +#define GL_HALF_BIAS_NEGATE_NV 0x853B +#define GL_SIGNED_IDENTITY_NV 0x853C +#define GL_SIGNED_NEGATE_NV 0x853D +#define GL_SCALE_BY_TWO_NV 0x853E +#define GL_SCALE_BY_FOUR_NV 0x853F +#define GL_SCALE_BY_ONE_HALF_NV 0x8540 +#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541 +#define GL_COMBINER_INPUT_NV 0x8542 +#define GL_COMBINER_MAPPING_NV 0x8543 +#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544 +#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545 +#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546 +#define GL_COMBINER_MUX_SUM_NV 0x8547 +#define GL_COMBINER_SCALE_NV 0x8548 +#define GL_COMBINER_BIAS_NV 0x8549 +#define GL_COMBINER_AB_OUTPUT_NV 0x854A +#define GL_COMBINER_CD_OUTPUT_NV 0x854B +#define GL_COMBINER_SUM_OUTPUT_NV 0x854C +#define GL_MAX_GENERAL_COMBINERS_NV 0x854D +#define GL_NUM_GENERAL_COMBINERS_NV 0x854E +#define GL_COLOR_SUM_CLAMP_NV 0x854F +#define GL_COMBINER0_NV 0x8550 +#define GL_COMBINER1_NV 0x8551 +#define GL_COMBINER2_NV 0x8552 +#define GL_COMBINER3_NV 0x8553 +#define GL_COMBINER4_NV 0x8554 +#define GL_COMBINER5_NV 0x8555 +#define GL_COMBINER6_NV 0x8556 +#define GL_COMBINER7_NV 0x8557 + +typedef void (GLAPIENTRY * PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (GLAPIENTRY * PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); +typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (GLAPIENTRY * PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint* params); + +#define glCombinerInputNV GLEW_GET_FUN(__glewCombinerInputNV) +#define glCombinerOutputNV GLEW_GET_FUN(__glewCombinerOutputNV) +#define glCombinerParameterfNV GLEW_GET_FUN(__glewCombinerParameterfNV) +#define glCombinerParameterfvNV GLEW_GET_FUN(__glewCombinerParameterfvNV) +#define glCombinerParameteriNV GLEW_GET_FUN(__glewCombinerParameteriNV) +#define glCombinerParameterivNV GLEW_GET_FUN(__glewCombinerParameterivNV) +#define glFinalCombinerInputNV GLEW_GET_FUN(__glewFinalCombinerInputNV) +#define glGetCombinerInputParameterfvNV GLEW_GET_FUN(__glewGetCombinerInputParameterfvNV) +#define glGetCombinerInputParameterivNV GLEW_GET_FUN(__glewGetCombinerInputParameterivNV) +#define glGetCombinerOutputParameterfvNV GLEW_GET_FUN(__glewGetCombinerOutputParameterfvNV) +#define glGetCombinerOutputParameterivNV GLEW_GET_FUN(__glewGetCombinerOutputParameterivNV) +#define glGetFinalCombinerInputParameterfvNV GLEW_GET_FUN(__glewGetFinalCombinerInputParameterfvNV) +#define glGetFinalCombinerInputParameterivNV GLEW_GET_FUN(__glewGetFinalCombinerInputParameterivNV) + +#define GLEW_NV_register_combiners GLEW_GET_VAR(__GLEW_NV_register_combiners) + +#endif /* GL_NV_register_combiners */ + +/* ----------------------- GL_NV_register_combiners2 ----------------------- */ + +#ifndef GL_NV_register_combiners2 +#define GL_NV_register_combiners2 1 + +#define GL_PER_STAGE_CONSTANTS_NV 0x8535 + +typedef void (GLAPIENTRY * PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat* params); + +#define glCombinerStageParameterfvNV GLEW_GET_FUN(__glewCombinerStageParameterfvNV) +#define glGetCombinerStageParameterfvNV GLEW_GET_FUN(__glewGetCombinerStageParameterfvNV) + +#define GLEW_NV_register_combiners2 GLEW_GET_VAR(__GLEW_NV_register_combiners2) + +#endif /* GL_NV_register_combiners2 */ + +/* ------------------------ GL_NV_shader_buffer_load ----------------------- */ + +#ifndef GL_NV_shader_buffer_load +#define GL_NV_shader_buffer_load 1 + +#define GL_BUFFER_GPU_ADDRESS_NV 0x8F1D +#define GL_GPU_ADDRESS_NV 0x8F34 +#define GL_MAX_SHADER_BUFFER_ADDRESS_NV 0x8F35 + +typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERUI64VNVPROC) (GLenum target, GLenum pname, GLuint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETINTEGERUI64VNVPROC) (GLenum value, GLuint64EXT* result); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC) (GLuint buffer, GLenum pname, GLuint64EXT* params); +typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERRESIDENTNVPROC) (GLenum target); +typedef GLboolean (GLAPIENTRY * PFNGLISNAMEDBUFFERRESIDENTNVPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLMAKEBUFFERNONRESIDENTNVPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLMAKEBUFFERRESIDENTNVPROC) (GLenum target, GLenum access); +typedef void (GLAPIENTRY * PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLMAKENAMEDBUFFERRESIDENTNVPROC) (GLuint buffer, GLenum access); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMUI64NVPROC) (GLuint program, GLint location, GLuint64EXT value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMUI64NVPROC) (GLint location, GLuint64EXT value); +typedef void (GLAPIENTRY * PFNGLUNIFORMUI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); + +#define glGetBufferParameterui64vNV GLEW_GET_FUN(__glewGetBufferParameterui64vNV) +#define glGetIntegerui64vNV GLEW_GET_FUN(__glewGetIntegerui64vNV) +#define glGetNamedBufferParameterui64vNV GLEW_GET_FUN(__glewGetNamedBufferParameterui64vNV) +#define glIsBufferResidentNV GLEW_GET_FUN(__glewIsBufferResidentNV) +#define glIsNamedBufferResidentNV GLEW_GET_FUN(__glewIsNamedBufferResidentNV) +#define glMakeBufferNonResidentNV GLEW_GET_FUN(__glewMakeBufferNonResidentNV) +#define glMakeBufferResidentNV GLEW_GET_FUN(__glewMakeBufferResidentNV) +#define glMakeNamedBufferNonResidentNV GLEW_GET_FUN(__glewMakeNamedBufferNonResidentNV) +#define glMakeNamedBufferResidentNV GLEW_GET_FUN(__glewMakeNamedBufferResidentNV) +#define glProgramUniformui64NV GLEW_GET_FUN(__glewProgramUniformui64NV) +#define glProgramUniformui64vNV GLEW_GET_FUN(__glewProgramUniformui64vNV) +#define glUniformui64NV GLEW_GET_FUN(__glewUniformui64NV) +#define glUniformui64vNV GLEW_GET_FUN(__glewUniformui64vNV) + +#define GLEW_NV_shader_buffer_load GLEW_GET_VAR(__GLEW_NV_shader_buffer_load) + +#endif /* GL_NV_shader_buffer_load */ + +/* ---------------------- GL_NV_tessellation_program5 ---------------------- */ + +#ifndef GL_NV_tessellation_program5 +#define GL_NV_tessellation_program5 1 + +#define GL_MAX_PROGRAM_PATCH_ATTRIBS_NV 0x86D8 +#define GL_TESS_CONTROL_PROGRAM_NV 0x891E +#define GL_TESS_EVALUATION_PROGRAM_NV 0x891F +#define GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV 0x8C74 +#define GL_TESS_EVALUATION_PROGRAM_PARAMETER_BUFFER_NV 0x8C75 + +#define GLEW_NV_tessellation_program5 GLEW_GET_VAR(__GLEW_NV_tessellation_program5) + +#endif /* GL_NV_tessellation_program5 */ + +/* -------------------------- GL_NV_texgen_emboss -------------------------- */ + +#ifndef GL_NV_texgen_emboss +#define GL_NV_texgen_emboss 1 + +#define GL_EMBOSS_LIGHT_NV 0x855D +#define GL_EMBOSS_CONSTANT_NV 0x855E +#define GL_EMBOSS_MAP_NV 0x855F + +#define GLEW_NV_texgen_emboss GLEW_GET_VAR(__GLEW_NV_texgen_emboss) + +#endif /* GL_NV_texgen_emboss */ + +/* ------------------------ GL_NV_texgen_reflection ------------------------ */ + +#ifndef GL_NV_texgen_reflection +#define GL_NV_texgen_reflection 1 + +#define GL_NORMAL_MAP_NV 0x8511 +#define GL_REFLECTION_MAP_NV 0x8512 + +#define GLEW_NV_texgen_reflection GLEW_GET_VAR(__GLEW_NV_texgen_reflection) + +#endif /* GL_NV_texgen_reflection */ + +/* ------------------------- GL_NV_texture_barrier ------------------------- */ + +#ifndef GL_NV_texture_barrier +#define GL_NV_texture_barrier 1 + +typedef void (GLAPIENTRY * PFNGLTEXTUREBARRIERNVPROC) (void); + +#define glTextureBarrierNV GLEW_GET_FUN(__glewTextureBarrierNV) + +#define GLEW_NV_texture_barrier GLEW_GET_VAR(__GLEW_NV_texture_barrier) + +#endif /* GL_NV_texture_barrier */ + +/* --------------------- GL_NV_texture_compression_vtc --------------------- */ + +#ifndef GL_NV_texture_compression_vtc +#define GL_NV_texture_compression_vtc 1 + +#define GLEW_NV_texture_compression_vtc GLEW_GET_VAR(__GLEW_NV_texture_compression_vtc) + +#endif /* GL_NV_texture_compression_vtc */ + +/* ----------------------- GL_NV_texture_env_combine4 ---------------------- */ + +#ifndef GL_NV_texture_env_combine4 +#define GL_NV_texture_env_combine4 1 + +#define GL_COMBINE4_NV 0x8503 +#define GL_SOURCE3_RGB_NV 0x8583 +#define GL_SOURCE3_ALPHA_NV 0x858B +#define GL_OPERAND3_RGB_NV 0x8593 +#define GL_OPERAND3_ALPHA_NV 0x859B + +#define GLEW_NV_texture_env_combine4 GLEW_GET_VAR(__GLEW_NV_texture_env_combine4) + +#endif /* GL_NV_texture_env_combine4 */ + +/* ---------------------- GL_NV_texture_expand_normal ---------------------- */ + +#ifndef GL_NV_texture_expand_normal +#define GL_NV_texture_expand_normal 1 + +#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F + +#define GLEW_NV_texture_expand_normal GLEW_GET_VAR(__GLEW_NV_texture_expand_normal) + +#endif /* GL_NV_texture_expand_normal */ + +/* ----------------------- GL_NV_texture_multisample ----------------------- */ + +#ifndef GL_NV_texture_multisample +#define GL_NV_texture_multisample 1 + +#define GL_TEXTURE_COVERAGE_SAMPLES_NV 0x9045 +#define GL_TEXTURE_COLOR_SAMPLES_NV 0x9046 + +typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); + +#define glTexImage2DMultisampleCoverageNV GLEW_GET_FUN(__glewTexImage2DMultisampleCoverageNV) +#define glTexImage3DMultisampleCoverageNV GLEW_GET_FUN(__glewTexImage3DMultisampleCoverageNV) +#define glTextureImage2DMultisampleCoverageNV GLEW_GET_FUN(__glewTextureImage2DMultisampleCoverageNV) +#define glTextureImage2DMultisampleNV GLEW_GET_FUN(__glewTextureImage2DMultisampleNV) +#define glTextureImage3DMultisampleCoverageNV GLEW_GET_FUN(__glewTextureImage3DMultisampleCoverageNV) +#define glTextureImage3DMultisampleNV GLEW_GET_FUN(__glewTextureImage3DMultisampleNV) + +#define GLEW_NV_texture_multisample GLEW_GET_VAR(__GLEW_NV_texture_multisample) + +#endif /* GL_NV_texture_multisample */ + +/* ------------------------ GL_NV_texture_rectangle ------------------------ */ + +#ifndef GL_NV_texture_rectangle +#define GL_NV_texture_rectangle 1 + +#define GL_TEXTURE_RECTANGLE_NV 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 + +#define GLEW_NV_texture_rectangle GLEW_GET_VAR(__GLEW_NV_texture_rectangle) + +#endif /* GL_NV_texture_rectangle */ + +/* -------------------------- GL_NV_texture_shader ------------------------- */ + +#ifndef GL_NV_texture_shader +#define GL_NV_texture_shader 1 + +#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C +#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D +#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E +#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9 +#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA +#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB +#define GL_DSDT_MAG_INTENSITY_NV 0x86DC +#define GL_SHADER_CONSISTENT_NV 0x86DD +#define GL_TEXTURE_SHADER_NV 0x86DE +#define GL_SHADER_OPERATION_NV 0x86DF +#define GL_CULL_MODES_NV 0x86E0 +#define GL_OFFSET_TEXTURE_2D_MATRIX_NV 0x86E1 +#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1 +#define GL_OFFSET_TEXTURE_2D_SCALE_NV 0x86E2 +#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2 +#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 +#define GL_OFFSET_TEXTURE_2D_BIAS_NV 0x86E3 +#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4 +#define GL_CONST_EYE_NV 0x86E5 +#define GL_PASS_THROUGH_NV 0x86E6 +#define GL_CULL_FRAGMENT_NV 0x86E7 +#define GL_OFFSET_TEXTURE_2D_NV 0x86E8 +#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9 +#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA +#define GL_DOT_PRODUCT_NV 0x86EC +#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED +#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE +#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0 +#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1 +#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2 +#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3 +#define GL_HILO_NV 0x86F4 +#define GL_DSDT_NV 0x86F5 +#define GL_DSDT_MAG_NV 0x86F6 +#define GL_DSDT_MAG_VIB_NV 0x86F7 +#define GL_HILO16_NV 0x86F8 +#define GL_SIGNED_HILO_NV 0x86F9 +#define GL_SIGNED_HILO16_NV 0x86FA +#define GL_SIGNED_RGBA_NV 0x86FB +#define GL_SIGNED_RGBA8_NV 0x86FC +#define GL_SIGNED_RGB_NV 0x86FE +#define GL_SIGNED_RGB8_NV 0x86FF +#define GL_SIGNED_LUMINANCE_NV 0x8701 +#define GL_SIGNED_LUMINANCE8_NV 0x8702 +#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 +#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 +#define GL_SIGNED_ALPHA_NV 0x8705 +#define GL_SIGNED_ALPHA8_NV 0x8706 +#define GL_SIGNED_INTENSITY_NV 0x8707 +#define GL_SIGNED_INTENSITY8_NV 0x8708 +#define GL_DSDT8_NV 0x8709 +#define GL_DSDT8_MAG8_NV 0x870A +#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B +#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C +#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D +#define GL_HI_SCALE_NV 0x870E +#define GL_LO_SCALE_NV 0x870F +#define GL_DS_SCALE_NV 0x8710 +#define GL_DT_SCALE_NV 0x8711 +#define GL_MAGNITUDE_SCALE_NV 0x8712 +#define GL_VIBRANCE_SCALE_NV 0x8713 +#define GL_HI_BIAS_NV 0x8714 +#define GL_LO_BIAS_NV 0x8715 +#define GL_DS_BIAS_NV 0x8716 +#define GL_DT_BIAS_NV 0x8717 +#define GL_MAGNITUDE_BIAS_NV 0x8718 +#define GL_VIBRANCE_BIAS_NV 0x8719 +#define GL_TEXTURE_BORDER_VALUES_NV 0x871A +#define GL_TEXTURE_HI_SIZE_NV 0x871B +#define GL_TEXTURE_LO_SIZE_NV 0x871C +#define GL_TEXTURE_DS_SIZE_NV 0x871D +#define GL_TEXTURE_DT_SIZE_NV 0x871E +#define GL_TEXTURE_MAG_SIZE_NV 0x871F + +#define GLEW_NV_texture_shader GLEW_GET_VAR(__GLEW_NV_texture_shader) + +#endif /* GL_NV_texture_shader */ + +/* ------------------------- GL_NV_texture_shader2 ------------------------- */ + +#ifndef GL_NV_texture_shader2 +#define GL_NV_texture_shader2 1 + +#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA +#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB +#define GL_DSDT_MAG_INTENSITY_NV 0x86DC +#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF +#define GL_HILO_NV 0x86F4 +#define GL_DSDT_NV 0x86F5 +#define GL_DSDT_MAG_NV 0x86F6 +#define GL_DSDT_MAG_VIB_NV 0x86F7 +#define GL_HILO16_NV 0x86F8 +#define GL_SIGNED_HILO_NV 0x86F9 +#define GL_SIGNED_HILO16_NV 0x86FA +#define GL_SIGNED_RGBA_NV 0x86FB +#define GL_SIGNED_RGBA8_NV 0x86FC +#define GL_SIGNED_RGB_NV 0x86FE +#define GL_SIGNED_RGB8_NV 0x86FF +#define GL_SIGNED_LUMINANCE_NV 0x8701 +#define GL_SIGNED_LUMINANCE8_NV 0x8702 +#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 +#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 +#define GL_SIGNED_ALPHA_NV 0x8705 +#define GL_SIGNED_ALPHA8_NV 0x8706 +#define GL_SIGNED_INTENSITY_NV 0x8707 +#define GL_SIGNED_INTENSITY8_NV 0x8708 +#define GL_DSDT8_NV 0x8709 +#define GL_DSDT8_MAG8_NV 0x870A +#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B +#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C +#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D + +#define GLEW_NV_texture_shader2 GLEW_GET_VAR(__GLEW_NV_texture_shader2) + +#endif /* GL_NV_texture_shader2 */ + +/* ------------------------- GL_NV_texture_shader3 ------------------------- */ + +#ifndef GL_NV_texture_shader3 +#define GL_NV_texture_shader3 1 + +#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850 +#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851 +#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852 +#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853 +#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854 +#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855 +#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856 +#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857 +#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858 +#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859 +#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A +#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B +#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C +#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D +#define GL_HILO8_NV 0x885E +#define GL_SIGNED_HILO8_NV 0x885F +#define GL_FORCE_BLUE_TO_ONE_NV 0x8860 + +#define GLEW_NV_texture_shader3 GLEW_GET_VAR(__GLEW_NV_texture_shader3) + +#endif /* GL_NV_texture_shader3 */ + +/* ------------------------ GL_NV_transform_feedback ----------------------- */ + +#ifndef GL_NV_transform_feedback +#define GL_NV_transform_feedback 1 + +#define GL_BACK_PRIMARY_COLOR_NV 0x8C77 +#define GL_BACK_SECONDARY_COLOR_NV 0x8C78 +#define GL_TEXTURE_COORD_NV 0x8C79 +#define GL_CLIP_DISTANCE_NV 0x8C7A +#define GL_VERTEX_ID_NV 0x8C7B +#define GL_PRIMITIVE_ID_NV 0x8C7C +#define GL_GENERIC_ATTRIB_NV 0x8C7D +#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80 +#define GL_ACTIVE_VARYINGS_NV 0x8C81 +#define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82 +#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85 +#define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86 +#define GL_PRIMITIVES_GENERATED_NV 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88 +#define GL_RASTERIZER_DISCARD_NV 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B +#define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C +#define GL_SEPARATE_ATTRIBS_NV 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F + +typedef void (GLAPIENTRY * PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name); +typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKNVPROC) (void); +typedef void (GLAPIENTRY * PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint *location); +typedef GLint (GLAPIENTRY * PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint *attribs, GLenum bufferMode); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode); + +#define glActiveVaryingNV GLEW_GET_FUN(__glewActiveVaryingNV) +#define glBeginTransformFeedbackNV GLEW_GET_FUN(__glewBeginTransformFeedbackNV) +#define glBindBufferBaseNV GLEW_GET_FUN(__glewBindBufferBaseNV) +#define glBindBufferOffsetNV GLEW_GET_FUN(__glewBindBufferOffsetNV) +#define glBindBufferRangeNV GLEW_GET_FUN(__glewBindBufferRangeNV) +#define glEndTransformFeedbackNV GLEW_GET_FUN(__glewEndTransformFeedbackNV) +#define glGetActiveVaryingNV GLEW_GET_FUN(__glewGetActiveVaryingNV) +#define glGetTransformFeedbackVaryingNV GLEW_GET_FUN(__glewGetTransformFeedbackVaryingNV) +#define glGetVaryingLocationNV GLEW_GET_FUN(__glewGetVaryingLocationNV) +#define glTransformFeedbackAttribsNV GLEW_GET_FUN(__glewTransformFeedbackAttribsNV) +#define glTransformFeedbackVaryingsNV GLEW_GET_FUN(__glewTransformFeedbackVaryingsNV) + +#define GLEW_NV_transform_feedback GLEW_GET_VAR(__GLEW_NV_transform_feedback) + +#endif /* GL_NV_transform_feedback */ + +/* ----------------------- GL_NV_transform_feedback2 ----------------------- */ + +#ifndef GL_NV_transform_feedback2 +#define GL_NV_transform_feedback2 1 + +#define GL_TRANSFORM_FEEDBACK_NV 0x8E22 +#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV 0x8E23 +#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING_NV 0x8E25 + +typedef void (GLAPIENTRY * PFNGLBINDTRANSFORMFEEDBACKNVPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETETRANSFORMFEEDBACKSNVPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKNVPROC) (GLenum mode, GLuint id); +typedef void (GLAPIENTRY * PFNGLGENTRANSFORMFEEDBACKSNVPROC) (GLsizei n, GLuint* ids); +typedef GLboolean (GLAPIENTRY * PFNGLISTRANSFORMFEEDBACKNVPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLPAUSETRANSFORMFEEDBACKNVPROC) (void); +typedef void (GLAPIENTRY * PFNGLRESUMETRANSFORMFEEDBACKNVPROC) (void); + +#define glBindTransformFeedbackNV GLEW_GET_FUN(__glewBindTransformFeedbackNV) +#define glDeleteTransformFeedbacksNV GLEW_GET_FUN(__glewDeleteTransformFeedbacksNV) +#define glDrawTransformFeedbackNV GLEW_GET_FUN(__glewDrawTransformFeedbackNV) +#define glGenTransformFeedbacksNV GLEW_GET_FUN(__glewGenTransformFeedbacksNV) +#define glIsTransformFeedbackNV GLEW_GET_FUN(__glewIsTransformFeedbackNV) +#define glPauseTransformFeedbackNV GLEW_GET_FUN(__glewPauseTransformFeedbackNV) +#define glResumeTransformFeedbackNV GLEW_GET_FUN(__glewResumeTransformFeedbackNV) + +#define GLEW_NV_transform_feedback2 GLEW_GET_VAR(__GLEW_NV_transform_feedback2) + +#endif /* GL_NV_transform_feedback2 */ + +/* -------------------------- GL_NV_vdpau_interop -------------------------- */ + +#ifndef GL_NV_vdpau_interop +#define GL_NV_vdpau_interop 1 + +#define GL_SURFACE_STATE_NV 0x86EB +#define GL_SURFACE_REGISTERED_NV 0x86FD +#define GL_SURFACE_MAPPED_NV 0x8700 +#define GL_WRITE_DISCARD_NV 0x88BE + +typedef GLintptr GLvdpauSurfaceNV; + +typedef void (GLAPIENTRY * PFNGLVDPAUFININVPROC) (void); +typedef void (GLAPIENTRY * PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei* length, GLint *values); +typedef void (GLAPIENTRY * PFNGLVDPAUINITNVPROC) (const void* vdpDevice, const GLvoid*getProcAddress); +typedef void (GLAPIENTRY * PFNGLVDPAUISSURFACENVPROC) (GLvdpauSurfaceNV surface); +typedef void (GLAPIENTRY * PFNGLVDPAUMAPSURFACESNVPROC) (GLsizei numSurfaces, const GLvdpauSurfaceNV* surfaces); +typedef GLvdpauSurfaceNV (GLAPIENTRY * PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC) (const void* vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); +typedef GLvdpauSurfaceNV (GLAPIENTRY * PFNGLVDPAUREGISTERVIDEOSURFACENVPROC) (const void* vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); +typedef void (GLAPIENTRY * PFNGLVDPAUSURFACEACCESSNVPROC) (GLvdpauSurfaceNV surface, GLenum access); +typedef void (GLAPIENTRY * PFNGLVDPAUUNMAPSURFACESNVPROC) (GLsizei numSurface, const GLvdpauSurfaceNV* surfaces); +typedef void (GLAPIENTRY * PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV surface); + +#define glVDPAUFiniNV GLEW_GET_FUN(__glewVDPAUFiniNV) +#define glVDPAUGetSurfaceivNV GLEW_GET_FUN(__glewVDPAUGetSurfaceivNV) +#define glVDPAUInitNV GLEW_GET_FUN(__glewVDPAUInitNV) +#define glVDPAUIsSurfaceNV GLEW_GET_FUN(__glewVDPAUIsSurfaceNV) +#define glVDPAUMapSurfacesNV GLEW_GET_FUN(__glewVDPAUMapSurfacesNV) +#define glVDPAURegisterOutputSurfaceNV GLEW_GET_FUN(__glewVDPAURegisterOutputSurfaceNV) +#define glVDPAURegisterVideoSurfaceNV GLEW_GET_FUN(__glewVDPAURegisterVideoSurfaceNV) +#define glVDPAUSurfaceAccessNV GLEW_GET_FUN(__glewVDPAUSurfaceAccessNV) +#define glVDPAUUnmapSurfacesNV GLEW_GET_FUN(__glewVDPAUUnmapSurfacesNV) +#define glVDPAUUnregisterSurfaceNV GLEW_GET_FUN(__glewVDPAUUnregisterSurfaceNV) + +#define GLEW_NV_vdpau_interop GLEW_GET_VAR(__GLEW_NV_vdpau_interop) + +#endif /* GL_NV_vdpau_interop */ + +/* ------------------------ GL_NV_vertex_array_range ----------------------- */ + +#ifndef GL_NV_vertex_array_range +#define GL_NV_vertex_array_range 1 + +#define GL_VERTEX_ARRAY_RANGE_NV 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E +#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F +#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520 +#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 + +typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, void* pointer); + +#define glFlushVertexArrayRangeNV GLEW_GET_FUN(__glewFlushVertexArrayRangeNV) +#define glVertexArrayRangeNV GLEW_GET_FUN(__glewVertexArrayRangeNV) + +#define GLEW_NV_vertex_array_range GLEW_GET_VAR(__GLEW_NV_vertex_array_range) + +#endif /* GL_NV_vertex_array_range */ + +/* ----------------------- GL_NV_vertex_array_range2 ----------------------- */ + +#ifndef GL_NV_vertex_array_range2 +#define GL_NV_vertex_array_range2 1 + +#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 + +#define GLEW_NV_vertex_array_range2 GLEW_GET_VAR(__GLEW_NV_vertex_array_range2) + +#endif /* GL_NV_vertex_array_range2 */ + +/* ------------------- GL_NV_vertex_attrib_integer_64bit ------------------- */ + +#ifndef GL_NV_vertex_attrib_integer_64bit +#define GL_NV_vertex_attrib_integer_64bit 1 + +#define GL_INT64_NV 0x140E +#define GL_UNSIGNED_INT64_NV 0x140F + +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLI64VNVPROC) (GLuint index, GLenum pname, GLint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLUI64VNVPROC) (GLuint index, GLenum pname, GLuint64EXT* params); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1I64NVPROC) (GLuint index, GLint64EXT x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1I64VNVPROC) (GLuint index, const GLint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1UI64NVPROC) (GLuint index, GLuint64EXT x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1UI64VNVPROC) (GLuint index, const GLuint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2I64VNVPROC) (GLuint index, const GLint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2UI64VNVPROC) (GLuint index, const GLuint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3I64VNVPROC) (GLuint index, const GLint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3UI64VNVPROC) (GLuint index, const GLuint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4I64VNVPROC) (GLuint index, const GLint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4UI64VNVPROC) (GLuint index, const GLuint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride); + +#define glGetVertexAttribLi64vNV GLEW_GET_FUN(__glewGetVertexAttribLi64vNV) +#define glGetVertexAttribLui64vNV GLEW_GET_FUN(__glewGetVertexAttribLui64vNV) +#define glVertexAttribL1i64NV GLEW_GET_FUN(__glewVertexAttribL1i64NV) +#define glVertexAttribL1i64vNV GLEW_GET_FUN(__glewVertexAttribL1i64vNV) +#define glVertexAttribL1ui64NV GLEW_GET_FUN(__glewVertexAttribL1ui64NV) +#define glVertexAttribL1ui64vNV GLEW_GET_FUN(__glewVertexAttribL1ui64vNV) +#define glVertexAttribL2i64NV GLEW_GET_FUN(__glewVertexAttribL2i64NV) +#define glVertexAttribL2i64vNV GLEW_GET_FUN(__glewVertexAttribL2i64vNV) +#define glVertexAttribL2ui64NV GLEW_GET_FUN(__glewVertexAttribL2ui64NV) +#define glVertexAttribL2ui64vNV GLEW_GET_FUN(__glewVertexAttribL2ui64vNV) +#define glVertexAttribL3i64NV GLEW_GET_FUN(__glewVertexAttribL3i64NV) +#define glVertexAttribL3i64vNV GLEW_GET_FUN(__glewVertexAttribL3i64vNV) +#define glVertexAttribL3ui64NV GLEW_GET_FUN(__glewVertexAttribL3ui64NV) +#define glVertexAttribL3ui64vNV GLEW_GET_FUN(__glewVertexAttribL3ui64vNV) +#define glVertexAttribL4i64NV GLEW_GET_FUN(__glewVertexAttribL4i64NV) +#define glVertexAttribL4i64vNV GLEW_GET_FUN(__glewVertexAttribL4i64vNV) +#define glVertexAttribL4ui64NV GLEW_GET_FUN(__glewVertexAttribL4ui64NV) +#define glVertexAttribL4ui64vNV GLEW_GET_FUN(__glewVertexAttribL4ui64vNV) +#define glVertexAttribLFormatNV GLEW_GET_FUN(__glewVertexAttribLFormatNV) + +#define GLEW_NV_vertex_attrib_integer_64bit GLEW_GET_VAR(__GLEW_NV_vertex_attrib_integer_64bit) + +#endif /* GL_NV_vertex_attrib_integer_64bit */ + +/* ------------------- GL_NV_vertex_buffer_unified_memory ------------------ */ + +#ifndef GL_NV_vertex_buffer_unified_memory +#define GL_NV_vertex_buffer_unified_memory 1 + +#define GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV 0x8F1E +#define GL_ELEMENT_ARRAY_UNIFIED_NV 0x8F1F +#define GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV 0x8F20 +#define GL_VERTEX_ARRAY_ADDRESS_NV 0x8F21 +#define GL_NORMAL_ARRAY_ADDRESS_NV 0x8F22 +#define GL_COLOR_ARRAY_ADDRESS_NV 0x8F23 +#define GL_INDEX_ARRAY_ADDRESS_NV 0x8F24 +#define GL_TEXTURE_COORD_ARRAY_ADDRESS_NV 0x8F25 +#define GL_EDGE_FLAG_ARRAY_ADDRESS_NV 0x8F26 +#define GL_SECONDARY_COLOR_ARRAY_ADDRESS_NV 0x8F27 +#define GL_FOG_COORD_ARRAY_ADDRESS_NV 0x8F28 +#define GL_ELEMENT_ARRAY_ADDRESS_NV 0x8F29 +#define GL_VERTEX_ATTRIB_ARRAY_LENGTH_NV 0x8F2A +#define GL_VERTEX_ARRAY_LENGTH_NV 0x8F2B +#define GL_NORMAL_ARRAY_LENGTH_NV 0x8F2C +#define GL_COLOR_ARRAY_LENGTH_NV 0x8F2D +#define GL_INDEX_ARRAY_LENGTH_NV 0x8F2E +#define GL_TEXTURE_COORD_ARRAY_LENGTH_NV 0x8F2F +#define GL_EDGE_FLAG_ARRAY_LENGTH_NV 0x8F30 +#define GL_SECONDARY_COLOR_ARRAY_LENGTH_NV 0x8F31 +#define GL_FOG_COORD_ARRAY_LENGTH_NV 0x8F32 +#define GL_ELEMENT_ARRAY_LENGTH_NV 0x8F33 +#define GL_DRAW_INDIRECT_UNIFIED_NV 0x8F40 +#define GL_DRAW_INDIRECT_ADDRESS_NV 0x8F41 +#define GL_DRAW_INDIRECT_LENGTH_NV 0x8F42 + +typedef void (GLAPIENTRY * PFNGLBUFFERADDRESSRANGENVPROC) (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length); +typedef void (GLAPIENTRY * PFNGLCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLEDGEFLAGFORMATNVPROC) (GLsizei stride); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFORMATNVPROC) (GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT result[]); +typedef void (GLAPIENTRY * PFNGLINDEXFORMATNVPROC) (GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLNORMALFORMATNVPROC) (GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLTEXCOORDFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLVERTEXFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); + +#define glBufferAddressRangeNV GLEW_GET_FUN(__glewBufferAddressRangeNV) +#define glColorFormatNV GLEW_GET_FUN(__glewColorFormatNV) +#define glEdgeFlagFormatNV GLEW_GET_FUN(__glewEdgeFlagFormatNV) +#define glFogCoordFormatNV GLEW_GET_FUN(__glewFogCoordFormatNV) +#define glGetIntegerui64i_vNV GLEW_GET_FUN(__glewGetIntegerui64i_vNV) +#define glIndexFormatNV GLEW_GET_FUN(__glewIndexFormatNV) +#define glNormalFormatNV GLEW_GET_FUN(__glewNormalFormatNV) +#define glSecondaryColorFormatNV GLEW_GET_FUN(__glewSecondaryColorFormatNV) +#define glTexCoordFormatNV GLEW_GET_FUN(__glewTexCoordFormatNV) +#define glVertexAttribFormatNV GLEW_GET_FUN(__glewVertexAttribFormatNV) +#define glVertexAttribIFormatNV GLEW_GET_FUN(__glewVertexAttribIFormatNV) +#define glVertexFormatNV GLEW_GET_FUN(__glewVertexFormatNV) + +#define GLEW_NV_vertex_buffer_unified_memory GLEW_GET_VAR(__GLEW_NV_vertex_buffer_unified_memory) + +#endif /* GL_NV_vertex_buffer_unified_memory */ + +/* -------------------------- GL_NV_vertex_program ------------------------- */ + +#ifndef GL_NV_vertex_program +#define GL_NV_vertex_program 1 + +#define GL_VERTEX_PROGRAM_NV 0x8620 +#define GL_VERTEX_STATE_PROGRAM_NV 0x8621 +#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623 +#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624 +#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625 +#define GL_CURRENT_ATTRIB_NV 0x8626 +#define GL_PROGRAM_LENGTH_NV 0x8627 +#define GL_PROGRAM_STRING_NV 0x8628 +#define GL_MODELVIEW_PROJECTION_NV 0x8629 +#define GL_IDENTITY_NV 0x862A +#define GL_INVERSE_NV 0x862B +#define GL_TRANSPOSE_NV 0x862C +#define GL_INVERSE_TRANSPOSE_NV 0x862D +#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E +#define GL_MAX_TRACK_MATRICES_NV 0x862F +#define GL_MATRIX0_NV 0x8630 +#define GL_MATRIX1_NV 0x8631 +#define GL_MATRIX2_NV 0x8632 +#define GL_MATRIX3_NV 0x8633 +#define GL_MATRIX4_NV 0x8634 +#define GL_MATRIX5_NV 0x8635 +#define GL_MATRIX6_NV 0x8636 +#define GL_MATRIX7_NV 0x8637 +#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 +#define GL_CURRENT_MATRIX_NV 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 +#define GL_PROGRAM_PARAMETER_NV 0x8644 +#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645 +#define GL_PROGRAM_TARGET_NV 0x8646 +#define GL_PROGRAM_RESIDENT_NV 0x8647 +#define GL_TRACK_MATRIX_NV 0x8648 +#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649 +#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A +#define GL_PROGRAM_ERROR_POSITION_NV 0x864B +#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650 +#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651 +#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652 +#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653 +#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654 +#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655 +#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656 +#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657 +#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658 +#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659 +#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A +#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B +#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C +#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D +#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E +#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F +#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660 +#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661 +#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662 +#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663 +#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664 +#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665 +#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666 +#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667 +#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668 +#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669 +#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A +#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B +#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C +#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D +#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E +#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F +#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670 +#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671 +#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672 +#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673 +#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674 +#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675 +#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676 +#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677 +#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678 +#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679 +#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A +#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B +#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C +#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D +#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E +#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F + +typedef GLboolean (GLAPIENTRY * PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint* ids, GLboolean *residences); +typedef void (GLAPIENTRY * PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte* program); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid** pointer); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMNVPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte* program); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLsizei num, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLsizei num, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei n, const GLubyte* v); + +#define glAreProgramsResidentNV GLEW_GET_FUN(__glewAreProgramsResidentNV) +#define glBindProgramNV GLEW_GET_FUN(__glewBindProgramNV) +#define glDeleteProgramsNV GLEW_GET_FUN(__glewDeleteProgramsNV) +#define glExecuteProgramNV GLEW_GET_FUN(__glewExecuteProgramNV) +#define glGenProgramsNV GLEW_GET_FUN(__glewGenProgramsNV) +#define glGetProgramParameterdvNV GLEW_GET_FUN(__glewGetProgramParameterdvNV) +#define glGetProgramParameterfvNV GLEW_GET_FUN(__glewGetProgramParameterfvNV) +#define glGetProgramStringNV GLEW_GET_FUN(__glewGetProgramStringNV) +#define glGetProgramivNV GLEW_GET_FUN(__glewGetProgramivNV) +#define glGetTrackMatrixivNV GLEW_GET_FUN(__glewGetTrackMatrixivNV) +#define glGetVertexAttribPointervNV GLEW_GET_FUN(__glewGetVertexAttribPointervNV) +#define glGetVertexAttribdvNV GLEW_GET_FUN(__glewGetVertexAttribdvNV) +#define glGetVertexAttribfvNV GLEW_GET_FUN(__glewGetVertexAttribfvNV) +#define glGetVertexAttribivNV GLEW_GET_FUN(__glewGetVertexAttribivNV) +#define glIsProgramNV GLEW_GET_FUN(__glewIsProgramNV) +#define glLoadProgramNV GLEW_GET_FUN(__glewLoadProgramNV) +#define glProgramParameter4dNV GLEW_GET_FUN(__glewProgramParameter4dNV) +#define glProgramParameter4dvNV GLEW_GET_FUN(__glewProgramParameter4dvNV) +#define glProgramParameter4fNV GLEW_GET_FUN(__glewProgramParameter4fNV) +#define glProgramParameter4fvNV GLEW_GET_FUN(__glewProgramParameter4fvNV) +#define glProgramParameters4dvNV GLEW_GET_FUN(__glewProgramParameters4dvNV) +#define glProgramParameters4fvNV GLEW_GET_FUN(__glewProgramParameters4fvNV) +#define glRequestResidentProgramsNV GLEW_GET_FUN(__glewRequestResidentProgramsNV) +#define glTrackMatrixNV GLEW_GET_FUN(__glewTrackMatrixNV) +#define glVertexAttrib1dNV GLEW_GET_FUN(__glewVertexAttrib1dNV) +#define glVertexAttrib1dvNV GLEW_GET_FUN(__glewVertexAttrib1dvNV) +#define glVertexAttrib1fNV GLEW_GET_FUN(__glewVertexAttrib1fNV) +#define glVertexAttrib1fvNV GLEW_GET_FUN(__glewVertexAttrib1fvNV) +#define glVertexAttrib1sNV GLEW_GET_FUN(__glewVertexAttrib1sNV) +#define glVertexAttrib1svNV GLEW_GET_FUN(__glewVertexAttrib1svNV) +#define glVertexAttrib2dNV GLEW_GET_FUN(__glewVertexAttrib2dNV) +#define glVertexAttrib2dvNV GLEW_GET_FUN(__glewVertexAttrib2dvNV) +#define glVertexAttrib2fNV GLEW_GET_FUN(__glewVertexAttrib2fNV) +#define glVertexAttrib2fvNV GLEW_GET_FUN(__glewVertexAttrib2fvNV) +#define glVertexAttrib2sNV GLEW_GET_FUN(__glewVertexAttrib2sNV) +#define glVertexAttrib2svNV GLEW_GET_FUN(__glewVertexAttrib2svNV) +#define glVertexAttrib3dNV GLEW_GET_FUN(__glewVertexAttrib3dNV) +#define glVertexAttrib3dvNV GLEW_GET_FUN(__glewVertexAttrib3dvNV) +#define glVertexAttrib3fNV GLEW_GET_FUN(__glewVertexAttrib3fNV) +#define glVertexAttrib3fvNV GLEW_GET_FUN(__glewVertexAttrib3fvNV) +#define glVertexAttrib3sNV GLEW_GET_FUN(__glewVertexAttrib3sNV) +#define glVertexAttrib3svNV GLEW_GET_FUN(__glewVertexAttrib3svNV) +#define glVertexAttrib4dNV GLEW_GET_FUN(__glewVertexAttrib4dNV) +#define glVertexAttrib4dvNV GLEW_GET_FUN(__glewVertexAttrib4dvNV) +#define glVertexAttrib4fNV GLEW_GET_FUN(__glewVertexAttrib4fNV) +#define glVertexAttrib4fvNV GLEW_GET_FUN(__glewVertexAttrib4fvNV) +#define glVertexAttrib4sNV GLEW_GET_FUN(__glewVertexAttrib4sNV) +#define glVertexAttrib4svNV GLEW_GET_FUN(__glewVertexAttrib4svNV) +#define glVertexAttrib4ubNV GLEW_GET_FUN(__glewVertexAttrib4ubNV) +#define glVertexAttrib4ubvNV GLEW_GET_FUN(__glewVertexAttrib4ubvNV) +#define glVertexAttribPointerNV GLEW_GET_FUN(__glewVertexAttribPointerNV) +#define glVertexAttribs1dvNV GLEW_GET_FUN(__glewVertexAttribs1dvNV) +#define glVertexAttribs1fvNV GLEW_GET_FUN(__glewVertexAttribs1fvNV) +#define glVertexAttribs1svNV GLEW_GET_FUN(__glewVertexAttribs1svNV) +#define glVertexAttribs2dvNV GLEW_GET_FUN(__glewVertexAttribs2dvNV) +#define glVertexAttribs2fvNV GLEW_GET_FUN(__glewVertexAttribs2fvNV) +#define glVertexAttribs2svNV GLEW_GET_FUN(__glewVertexAttribs2svNV) +#define glVertexAttribs3dvNV GLEW_GET_FUN(__glewVertexAttribs3dvNV) +#define glVertexAttribs3fvNV GLEW_GET_FUN(__glewVertexAttribs3fvNV) +#define glVertexAttribs3svNV GLEW_GET_FUN(__glewVertexAttribs3svNV) +#define glVertexAttribs4dvNV GLEW_GET_FUN(__glewVertexAttribs4dvNV) +#define glVertexAttribs4fvNV GLEW_GET_FUN(__glewVertexAttribs4fvNV) +#define glVertexAttribs4svNV GLEW_GET_FUN(__glewVertexAttribs4svNV) +#define glVertexAttribs4ubvNV GLEW_GET_FUN(__glewVertexAttribs4ubvNV) + +#define GLEW_NV_vertex_program GLEW_GET_VAR(__GLEW_NV_vertex_program) + +#endif /* GL_NV_vertex_program */ + +/* ------------------------ GL_NV_vertex_program1_1 ------------------------ */ + +#ifndef GL_NV_vertex_program1_1 +#define GL_NV_vertex_program1_1 1 + +#define GLEW_NV_vertex_program1_1 GLEW_GET_VAR(__GLEW_NV_vertex_program1_1) + +#endif /* GL_NV_vertex_program1_1 */ + +/* ------------------------- GL_NV_vertex_program2 ------------------------- */ + +#ifndef GL_NV_vertex_program2 +#define GL_NV_vertex_program2 1 + +#define GLEW_NV_vertex_program2 GLEW_GET_VAR(__GLEW_NV_vertex_program2) + +#endif /* GL_NV_vertex_program2 */ + +/* ---------------------- GL_NV_vertex_program2_option --------------------- */ + +#ifndef GL_NV_vertex_program2_option +#define GL_NV_vertex_program2_option 1 + +#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 +#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 + +#define GLEW_NV_vertex_program2_option GLEW_GET_VAR(__GLEW_NV_vertex_program2_option) + +#endif /* GL_NV_vertex_program2_option */ + +/* ------------------------- GL_NV_vertex_program3 ------------------------- */ + +#ifndef GL_NV_vertex_program3 +#define GL_NV_vertex_program3 1 + +#define MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C + +#define GLEW_NV_vertex_program3 GLEW_GET_VAR(__GLEW_NV_vertex_program3) + +#endif /* GL_NV_vertex_program3 */ + +/* ------------------------- GL_NV_vertex_program4 ------------------------- */ + +#ifndef GL_NV_vertex_program4 +#define GL_NV_vertex_program4 1 + +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD + +#define GLEW_NV_vertex_program4 GLEW_GET_VAR(__GLEW_NV_vertex_program4) + +#endif /* GL_NV_vertex_program4 */ + +/* -------------------------- GL_NV_video_capture -------------------------- */ + +#ifndef GL_NV_video_capture +#define GL_NV_video_capture 1 + +#define GL_VIDEO_BUFFER_NV 0x9020 +#define GL_VIDEO_BUFFER_BINDING_NV 0x9021 +#define GL_FIELD_UPPER_NV 0x9022 +#define GL_FIELD_LOWER_NV 0x9023 +#define GL_NUM_VIDEO_CAPTURE_STREAMS_NV 0x9024 +#define GL_NEXT_VIDEO_CAPTURE_BUFFER_STATUS_NV 0x9025 +#define GL_VIDEO_CAPTURE_TO_422_SUPPORTED_NV 0x9026 +#define GL_LAST_VIDEO_CAPTURE_STATUS_NV 0x9027 +#define GL_VIDEO_BUFFER_PITCH_NV 0x9028 +#define GL_VIDEO_COLOR_CONVERSION_MATRIX_NV 0x9029 +#define GL_VIDEO_COLOR_CONVERSION_MAX_NV 0x902A +#define GL_VIDEO_COLOR_CONVERSION_MIN_NV 0x902B +#define GL_VIDEO_COLOR_CONVERSION_OFFSET_NV 0x902C +#define GL_VIDEO_BUFFER_INTERNAL_FORMAT_NV 0x902D +#define GL_PARTIAL_SUCCESS_NV 0x902E +#define GL_SUCCESS_NV 0x902F +#define GL_FAILURE_NV 0x9030 +#define GL_YCBYCR8_422_NV 0x9031 +#define GL_YCBAYCR8A_4224_NV 0x9032 +#define GL_Z6Y10Z6CB10Z6Y10Z6CR10_422_NV 0x9033 +#define GL_Z6Y10Z6CB10Z6A10Z6Y10Z6CR10Z6A10_4224_NV 0x9034 +#define GL_Z4Y12Z4CB12Z4Y12Z4CR12_422_NV 0x9035 +#define GL_Z4Y12Z4CB12Z4A12Z4Y12Z4CR12Z4A12_4224_NV 0x9036 +#define GL_Z4Y12Z4CB12Z4CR12_444_NV 0x9037 +#define GL_VIDEO_CAPTURE_FRAME_WIDTH_NV 0x9038 +#define GL_VIDEO_CAPTURE_FRAME_HEIGHT_NV 0x9039 +#define GL_VIDEO_CAPTURE_FIELD_UPPER_HEIGHT_NV 0x903A +#define GL_VIDEO_CAPTURE_FIELD_LOWER_HEIGHT_NV 0x903B +#define GL_VIDEO_CAPTURE_SURFACE_ORIGIN_NV 0x903C + +typedef void (GLAPIENTRY * PFNGLBEGINVIDEOCAPTURENVPROC) (GLuint video_capture_slot); +typedef void (GLAPIENTRY * PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset); +typedef void (GLAPIENTRY * PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture); +typedef void (GLAPIENTRY * PFNGLENDVIDEOCAPTURENVPROC) (GLuint video_capture_slot); +typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTUREIVNVPROC) (GLuint video_capture_slot, GLenum pname, GLint* params); +typedef GLenum (GLAPIENTRY * PFNGLVIDEOCAPTURENVPROC) (GLuint video_capture_slot, GLuint* sequence_num, GLuint64EXT *capture_time); +typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint* params); + +#define glBeginVideoCaptureNV GLEW_GET_FUN(__glewBeginVideoCaptureNV) +#define glBindVideoCaptureStreamBufferNV GLEW_GET_FUN(__glewBindVideoCaptureStreamBufferNV) +#define glBindVideoCaptureStreamTextureNV GLEW_GET_FUN(__glewBindVideoCaptureStreamTextureNV) +#define glEndVideoCaptureNV GLEW_GET_FUN(__glewEndVideoCaptureNV) +#define glGetVideoCaptureStreamdvNV GLEW_GET_FUN(__glewGetVideoCaptureStreamdvNV) +#define glGetVideoCaptureStreamfvNV GLEW_GET_FUN(__glewGetVideoCaptureStreamfvNV) +#define glGetVideoCaptureStreamivNV GLEW_GET_FUN(__glewGetVideoCaptureStreamivNV) +#define glGetVideoCaptureivNV GLEW_GET_FUN(__glewGetVideoCaptureivNV) +#define glVideoCaptureNV GLEW_GET_FUN(__glewVideoCaptureNV) +#define glVideoCaptureStreamParameterdvNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterdvNV) +#define glVideoCaptureStreamParameterfvNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterfvNV) +#define glVideoCaptureStreamParameterivNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterivNV) + +#define GLEW_NV_video_capture GLEW_GET_VAR(__GLEW_NV_video_capture) + +#endif /* GL_NV_video_capture */ + +/* ------------------------ GL_OES_byte_coordinates ------------------------ */ + +#ifndef GL_OES_byte_coordinates +#define GL_OES_byte_coordinates 1 + +#define GL_BYTE 0x1400 + +#define GLEW_OES_byte_coordinates GLEW_GET_VAR(__GLEW_OES_byte_coordinates) + +#endif /* GL_OES_byte_coordinates */ + +/* ------------------- GL_OES_compressed_paletted_texture ------------------ */ + +#ifndef GL_OES_compressed_paletted_texture +#define GL_OES_compressed_paletted_texture 1 + +#define GL_PALETTE4_RGB8_OES 0x8B90 +#define GL_PALETTE4_RGBA8_OES 0x8B91 +#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 +#define GL_PALETTE4_RGBA4_OES 0x8B93 +#define GL_PALETTE4_RGB5_A1_OES 0x8B94 +#define GL_PALETTE8_RGB8_OES 0x8B95 +#define GL_PALETTE8_RGBA8_OES 0x8B96 +#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 +#define GL_PALETTE8_RGBA4_OES 0x8B98 +#define GL_PALETTE8_RGB5_A1_OES 0x8B99 + +#define GLEW_OES_compressed_paletted_texture GLEW_GET_VAR(__GLEW_OES_compressed_paletted_texture) + +#endif /* GL_OES_compressed_paletted_texture */ + +/* --------------------------- GL_OES_read_format -------------------------- */ + +#ifndef GL_OES_read_format +#define GL_OES_read_format 1 + +#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B + +#define GLEW_OES_read_format GLEW_GET_VAR(__GLEW_OES_read_format) + +#endif /* GL_OES_read_format */ + +/* ------------------------ GL_OES_single_precision ------------------------ */ + +#ifndef GL_OES_single_precision +#define GL_OES_single_precision 1 + +typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFOESPROC) (GLclampd depth); +typedef void (GLAPIENTRY * PFNGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat* equation); +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFOESPROC) (GLclampf n, GLclampf f); +typedef void (GLAPIENTRY * PFNGLFRUSTUMFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); +typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEFOESPROC) (GLenum plane, GLfloat* equation); +typedef void (GLAPIENTRY * PFNGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); + +#define glClearDepthfOES GLEW_GET_FUN(__glewClearDepthfOES) +#define glClipPlanefOES GLEW_GET_FUN(__glewClipPlanefOES) +#define glDepthRangefOES GLEW_GET_FUN(__glewDepthRangefOES) +#define glFrustumfOES GLEW_GET_FUN(__glewFrustumfOES) +#define glGetClipPlanefOES GLEW_GET_FUN(__glewGetClipPlanefOES) +#define glOrthofOES GLEW_GET_FUN(__glewOrthofOES) + +#define GLEW_OES_single_precision GLEW_GET_VAR(__GLEW_OES_single_precision) + +#endif /* GL_OES_single_precision */ + +/* ---------------------------- GL_OML_interlace --------------------------- */ + +#ifndef GL_OML_interlace +#define GL_OML_interlace 1 + +#define GL_INTERLACE_OML 0x8980 +#define GL_INTERLACE_READ_OML 0x8981 + +#define GLEW_OML_interlace GLEW_GET_VAR(__GLEW_OML_interlace) + +#endif /* GL_OML_interlace */ + +/* ---------------------------- GL_OML_resample ---------------------------- */ + +#ifndef GL_OML_resample +#define GL_OML_resample 1 + +#define GL_PACK_RESAMPLE_OML 0x8984 +#define GL_UNPACK_RESAMPLE_OML 0x8985 +#define GL_RESAMPLE_REPLICATE_OML 0x8986 +#define GL_RESAMPLE_ZERO_FILL_OML 0x8987 +#define GL_RESAMPLE_AVERAGE_OML 0x8988 +#define GL_RESAMPLE_DECIMATE_OML 0x8989 + +#define GLEW_OML_resample GLEW_GET_VAR(__GLEW_OML_resample) + +#endif /* GL_OML_resample */ + +/* ---------------------------- GL_OML_subsample --------------------------- */ + +#ifndef GL_OML_subsample +#define GL_OML_subsample 1 + +#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982 +#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983 + +#define GLEW_OML_subsample GLEW_GET_VAR(__GLEW_OML_subsample) + +#endif /* GL_OML_subsample */ + +/* --------------------------- GL_PGI_misc_hints --------------------------- */ + +#ifndef GL_PGI_misc_hints +#define GL_PGI_misc_hints 1 + +#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 107000 +#define GL_CONSERVE_MEMORY_HINT_PGI 107005 +#define GL_RECLAIM_MEMORY_HINT_PGI 107006 +#define GL_NATIVE_GRAPHICS_HANDLE_PGI 107010 +#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 107011 +#define GL_NATIVE_GRAPHICS_END_HINT_PGI 107012 +#define GL_ALWAYS_FAST_HINT_PGI 107020 +#define GL_ALWAYS_SOFT_HINT_PGI 107021 +#define GL_ALLOW_DRAW_OBJ_HINT_PGI 107022 +#define GL_ALLOW_DRAW_WIN_HINT_PGI 107023 +#define GL_ALLOW_DRAW_FRG_HINT_PGI 107024 +#define GL_ALLOW_DRAW_MEM_HINT_PGI 107025 +#define GL_STRICT_DEPTHFUNC_HINT_PGI 107030 +#define GL_STRICT_LIGHTING_HINT_PGI 107031 +#define GL_STRICT_SCISSOR_HINT_PGI 107032 +#define GL_FULL_STIPPLE_HINT_PGI 107033 +#define GL_CLIP_NEAR_HINT_PGI 107040 +#define GL_CLIP_FAR_HINT_PGI 107041 +#define GL_WIDE_LINE_HINT_PGI 107042 +#define GL_BACK_NORMALS_HINT_PGI 107043 + +#define GLEW_PGI_misc_hints GLEW_GET_VAR(__GLEW_PGI_misc_hints) + +#endif /* GL_PGI_misc_hints */ + +/* -------------------------- GL_PGI_vertex_hints -------------------------- */ + +#ifndef GL_PGI_vertex_hints +#define GL_PGI_vertex_hints 1 + +#define GL_VERTEX23_BIT_PGI 0x00000004 +#define GL_VERTEX4_BIT_PGI 0x00000008 +#define GL_COLOR3_BIT_PGI 0x00010000 +#define GL_COLOR4_BIT_PGI 0x00020000 +#define GL_EDGEFLAG_BIT_PGI 0x00040000 +#define GL_INDEX_BIT_PGI 0x00080000 +#define GL_MAT_AMBIENT_BIT_PGI 0x00100000 +#define GL_VERTEX_DATA_HINT_PGI 107050 +#define GL_VERTEX_CONSISTENT_HINT_PGI 107051 +#define GL_MATERIAL_SIDE_HINT_PGI 107052 +#define GL_MAX_VERTEX_HINT_PGI 107053 +#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000 +#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000 +#define GL_MAT_EMISSION_BIT_PGI 0x00800000 +#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000 +#define GL_MAT_SHININESS_BIT_PGI 0x02000000 +#define GL_MAT_SPECULAR_BIT_PGI 0x04000000 +#define GL_NORMAL_BIT_PGI 0x08000000 +#define GL_TEXCOORD1_BIT_PGI 0x10000000 +#define GL_TEXCOORD2_BIT_PGI 0x20000000 +#define GL_TEXCOORD3_BIT_PGI 0x40000000 +#define GL_TEXCOORD4_BIT_PGI 0x80000000 + +#define GLEW_PGI_vertex_hints GLEW_GET_VAR(__GLEW_PGI_vertex_hints) + +#endif /* GL_PGI_vertex_hints */ + +/* ----------------------- GL_REND_screen_coordinates ---------------------- */ + +#ifndef GL_REND_screen_coordinates +#define GL_REND_screen_coordinates 1 + +#define GL_SCREEN_COORDINATES_REND 0x8490 +#define GL_INVERTED_SCREEN_W_REND 0x8491 + +#define GLEW_REND_screen_coordinates GLEW_GET_VAR(__GLEW_REND_screen_coordinates) + +#endif /* GL_REND_screen_coordinates */ + +/* ------------------------------- GL_S3_s3tc ------------------------------ */ + +#ifndef GL_S3_s3tc +#define GL_S3_s3tc 1 + +#define GL_RGB_S3TC 0x83A0 +#define GL_RGB4_S3TC 0x83A1 +#define GL_RGBA_S3TC 0x83A2 +#define GL_RGBA4_S3TC 0x83A3 +#define GL_RGBA_DXT5_S3TC 0x83A4 +#define GL_RGBA4_DXT5_S3TC 0x83A5 + +#define GLEW_S3_s3tc GLEW_GET_VAR(__GLEW_S3_s3tc) + +#endif /* GL_S3_s3tc */ + +/* -------------------------- GL_SGIS_color_range -------------------------- */ + +#ifndef GL_SGIS_color_range +#define GL_SGIS_color_range 1 + +#define GL_EXTENDED_RANGE_SGIS 0x85A5 +#define GL_MIN_RED_SGIS 0x85A6 +#define GL_MAX_RED_SGIS 0x85A7 +#define GL_MIN_GREEN_SGIS 0x85A8 +#define GL_MAX_GREEN_SGIS 0x85A9 +#define GL_MIN_BLUE_SGIS 0x85AA +#define GL_MAX_BLUE_SGIS 0x85AB +#define GL_MIN_ALPHA_SGIS 0x85AC +#define GL_MAX_ALPHA_SGIS 0x85AD + +#define GLEW_SGIS_color_range GLEW_GET_VAR(__GLEW_SGIS_color_range) + +#endif /* GL_SGIS_color_range */ + +/* ------------------------- GL_SGIS_detail_texture ------------------------ */ + +#ifndef GL_SGIS_detail_texture +#define GL_SGIS_detail_texture 1 + +typedef void (GLAPIENTRY * PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat* points); +typedef void (GLAPIENTRY * PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat* points); + +#define glDetailTexFuncSGIS GLEW_GET_FUN(__glewDetailTexFuncSGIS) +#define glGetDetailTexFuncSGIS GLEW_GET_FUN(__glewGetDetailTexFuncSGIS) + +#define GLEW_SGIS_detail_texture GLEW_GET_VAR(__GLEW_SGIS_detail_texture) + +#endif /* GL_SGIS_detail_texture */ + +/* -------------------------- GL_SGIS_fog_function ------------------------- */ + +#ifndef GL_SGIS_fog_function +#define GL_SGIS_fog_function 1 + +typedef void (GLAPIENTRY * PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat* points); +typedef void (GLAPIENTRY * PFNGLGETFOGFUNCSGISPROC) (GLfloat* points); + +#define glFogFuncSGIS GLEW_GET_FUN(__glewFogFuncSGIS) +#define glGetFogFuncSGIS GLEW_GET_FUN(__glewGetFogFuncSGIS) + +#define GLEW_SGIS_fog_function GLEW_GET_VAR(__GLEW_SGIS_fog_function) + +#endif /* GL_SGIS_fog_function */ + +/* ------------------------ GL_SGIS_generate_mipmap ------------------------ */ + +#ifndef GL_SGIS_generate_mipmap +#define GL_SGIS_generate_mipmap 1 + +#define GL_GENERATE_MIPMAP_SGIS 0x8191 +#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 + +#define GLEW_SGIS_generate_mipmap GLEW_GET_VAR(__GLEW_SGIS_generate_mipmap) + +#endif /* GL_SGIS_generate_mipmap */ + +/* -------------------------- GL_SGIS_multisample -------------------------- */ + +#ifndef GL_SGIS_multisample +#define GL_SGIS_multisample 1 + +#define GL_MULTISAMPLE_SGIS 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F +#define GL_SAMPLE_MASK_SGIS 0x80A0 +#define GL_1PASS_SGIS 0x80A1 +#define GL_2PASS_0_SGIS 0x80A2 +#define GL_2PASS_1_SGIS 0x80A3 +#define GL_4PASS_0_SGIS 0x80A4 +#define GL_4PASS_1_SGIS 0x80A5 +#define GL_4PASS_2_SGIS 0x80A6 +#define GL_4PASS_3_SGIS 0x80A7 +#define GL_SAMPLE_BUFFERS_SGIS 0x80A8 +#define GL_SAMPLES_SGIS 0x80A9 +#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA +#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB +#define GL_SAMPLE_PATTERN_SGIS 0x80AC +#define GL_MULTISAMPLE_BIT_EXT 0x20000000 + +typedef void (GLAPIENTRY * PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert); +typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern); + +#define glSampleMaskSGIS GLEW_GET_FUN(__glewSampleMaskSGIS) +#define glSamplePatternSGIS GLEW_GET_FUN(__glewSamplePatternSGIS) + +#define GLEW_SGIS_multisample GLEW_GET_VAR(__GLEW_SGIS_multisample) + +#endif /* GL_SGIS_multisample */ + +/* ------------------------- GL_SGIS_pixel_texture ------------------------- */ + +#ifndef GL_SGIS_pixel_texture +#define GL_SGIS_pixel_texture 1 + +#define GLEW_SGIS_pixel_texture GLEW_GET_VAR(__GLEW_SGIS_pixel_texture) + +#endif /* GL_SGIS_pixel_texture */ + +/* ----------------------- GL_SGIS_point_line_texgen ----------------------- */ + +#ifndef GL_SGIS_point_line_texgen +#define GL_SGIS_point_line_texgen 1 + +#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0 +#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1 +#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2 +#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3 +#define GL_EYE_POINT_SGIS 0x81F4 +#define GL_OBJECT_POINT_SGIS 0x81F5 +#define GL_EYE_LINE_SGIS 0x81F6 +#define GL_OBJECT_LINE_SGIS 0x81F7 + +#define GLEW_SGIS_point_line_texgen GLEW_GET_VAR(__GLEW_SGIS_point_line_texgen) + +#endif /* GL_SGIS_point_line_texgen */ + +/* ------------------------ GL_SGIS_sharpen_texture ------------------------ */ + +#ifndef GL_SGIS_sharpen_texture +#define GL_SGIS_sharpen_texture 1 + +typedef void (GLAPIENTRY * PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat* points); +typedef void (GLAPIENTRY * PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat* points); + +#define glGetSharpenTexFuncSGIS GLEW_GET_FUN(__glewGetSharpenTexFuncSGIS) +#define glSharpenTexFuncSGIS GLEW_GET_FUN(__glewSharpenTexFuncSGIS) + +#define GLEW_SGIS_sharpen_texture GLEW_GET_VAR(__GLEW_SGIS_sharpen_texture) + +#endif /* GL_SGIS_sharpen_texture */ + +/* --------------------------- GL_SGIS_texture4D --------------------------- */ + +#ifndef GL_SGIS_texture4D +#define GL_SGIS_texture4D 1 + +typedef void (GLAPIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLenum format, GLenum type, const void* pixels); + +#define glTexImage4DSGIS GLEW_GET_FUN(__glewTexImage4DSGIS) +#define glTexSubImage4DSGIS GLEW_GET_FUN(__glewTexSubImage4DSGIS) + +#define GLEW_SGIS_texture4D GLEW_GET_VAR(__GLEW_SGIS_texture4D) + +#endif /* GL_SGIS_texture4D */ + +/* ---------------------- GL_SGIS_texture_border_clamp --------------------- */ + +#ifndef GL_SGIS_texture_border_clamp +#define GL_SGIS_texture_border_clamp 1 + +#define GL_CLAMP_TO_BORDER_SGIS 0x812D + +#define GLEW_SGIS_texture_border_clamp GLEW_GET_VAR(__GLEW_SGIS_texture_border_clamp) + +#endif /* GL_SGIS_texture_border_clamp */ + +/* ----------------------- GL_SGIS_texture_edge_clamp ---------------------- */ + +#ifndef GL_SGIS_texture_edge_clamp +#define GL_SGIS_texture_edge_clamp 1 + +#define GL_CLAMP_TO_EDGE_SGIS 0x812F + +#define GLEW_SGIS_texture_edge_clamp GLEW_GET_VAR(__GLEW_SGIS_texture_edge_clamp) + +#endif /* GL_SGIS_texture_edge_clamp */ + +/* ------------------------ GL_SGIS_texture_filter4 ------------------------ */ + +#ifndef GL_SGIS_texture_filter4 +#define GL_SGIS_texture_filter4 1 + +typedef void (GLAPIENTRY * PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat* weights); +typedef void (GLAPIENTRY * PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat* weights); + +#define glGetTexFilterFuncSGIS GLEW_GET_FUN(__glewGetTexFilterFuncSGIS) +#define glTexFilterFuncSGIS GLEW_GET_FUN(__glewTexFilterFuncSGIS) + +#define GLEW_SGIS_texture_filter4 GLEW_GET_VAR(__GLEW_SGIS_texture_filter4) + +#endif /* GL_SGIS_texture_filter4 */ + +/* -------------------------- GL_SGIS_texture_lod -------------------------- */ + +#ifndef GL_SGIS_texture_lod +#define GL_SGIS_texture_lod 1 + +#define GL_TEXTURE_MIN_LOD_SGIS 0x813A +#define GL_TEXTURE_MAX_LOD_SGIS 0x813B +#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C +#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D + +#define GLEW_SGIS_texture_lod GLEW_GET_VAR(__GLEW_SGIS_texture_lod) + +#endif /* GL_SGIS_texture_lod */ + +/* ------------------------- GL_SGIS_texture_select ------------------------ */ + +#ifndef GL_SGIS_texture_select +#define GL_SGIS_texture_select 1 + +#define GLEW_SGIS_texture_select GLEW_GET_VAR(__GLEW_SGIS_texture_select) + +#endif /* GL_SGIS_texture_select */ + +/* ----------------------------- GL_SGIX_async ----------------------------- */ + +#ifndef GL_SGIX_async +#define GL_SGIX_async 1 + +#define GL_ASYNC_MARKER_SGIX 0x8329 + +typedef void (GLAPIENTRY * PFNGLASYNCMARKERSGIXPROC) (GLuint marker); +typedef void (GLAPIENTRY * PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range); +typedef GLint (GLAPIENTRY * PFNGLFINISHASYNCSGIXPROC) (GLuint* markerp); +typedef GLuint (GLAPIENTRY * PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range); +typedef GLboolean (GLAPIENTRY * PFNGLISASYNCMARKERSGIXPROC) (GLuint marker); +typedef GLint (GLAPIENTRY * PFNGLPOLLASYNCSGIXPROC) (GLuint* markerp); + +#define glAsyncMarkerSGIX GLEW_GET_FUN(__glewAsyncMarkerSGIX) +#define glDeleteAsyncMarkersSGIX GLEW_GET_FUN(__glewDeleteAsyncMarkersSGIX) +#define glFinishAsyncSGIX GLEW_GET_FUN(__glewFinishAsyncSGIX) +#define glGenAsyncMarkersSGIX GLEW_GET_FUN(__glewGenAsyncMarkersSGIX) +#define glIsAsyncMarkerSGIX GLEW_GET_FUN(__glewIsAsyncMarkerSGIX) +#define glPollAsyncSGIX GLEW_GET_FUN(__glewPollAsyncSGIX) + +#define GLEW_SGIX_async GLEW_GET_VAR(__GLEW_SGIX_async) + +#endif /* GL_SGIX_async */ + +/* ------------------------ GL_SGIX_async_histogram ------------------------ */ + +#ifndef GL_SGIX_async_histogram +#define GL_SGIX_async_histogram 1 + +#define GL_ASYNC_HISTOGRAM_SGIX 0x832C +#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D + +#define GLEW_SGIX_async_histogram GLEW_GET_VAR(__GLEW_SGIX_async_histogram) + +#endif /* GL_SGIX_async_histogram */ + +/* -------------------------- GL_SGIX_async_pixel -------------------------- */ + +#ifndef GL_SGIX_async_pixel +#define GL_SGIX_async_pixel 1 + +#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C +#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D +#define GL_ASYNC_READ_PIXELS_SGIX 0x835E +#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F +#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360 +#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361 + +#define GLEW_SGIX_async_pixel GLEW_GET_VAR(__GLEW_SGIX_async_pixel) + +#endif /* GL_SGIX_async_pixel */ + +/* ----------------------- GL_SGIX_blend_alpha_minmax ---------------------- */ + +#ifndef GL_SGIX_blend_alpha_minmax +#define GL_SGIX_blend_alpha_minmax 1 + +#define GL_ALPHA_MIN_SGIX 0x8320 +#define GL_ALPHA_MAX_SGIX 0x8321 + +#define GLEW_SGIX_blend_alpha_minmax GLEW_GET_VAR(__GLEW_SGIX_blend_alpha_minmax) + +#endif /* GL_SGIX_blend_alpha_minmax */ + +/* ---------------------------- GL_SGIX_clipmap ---------------------------- */ + +#ifndef GL_SGIX_clipmap +#define GL_SGIX_clipmap 1 + +#define GLEW_SGIX_clipmap GLEW_GET_VAR(__GLEW_SGIX_clipmap) + +#endif /* GL_SGIX_clipmap */ + +/* ---------------------- GL_SGIX_convolution_accuracy --------------------- */ + +#ifndef GL_SGIX_convolution_accuracy +#define GL_SGIX_convolution_accuracy 1 + +#define GL_CONVOLUTION_HINT_SGIX 0x8316 + +#define GLEW_SGIX_convolution_accuracy GLEW_GET_VAR(__GLEW_SGIX_convolution_accuracy) + +#endif /* GL_SGIX_convolution_accuracy */ + +/* ------------------------- GL_SGIX_depth_texture ------------------------- */ + +#ifndef GL_SGIX_depth_texture +#define GL_SGIX_depth_texture 1 + +#define GL_DEPTH_COMPONENT16_SGIX 0x81A5 +#define GL_DEPTH_COMPONENT24_SGIX 0x81A6 +#define GL_DEPTH_COMPONENT32_SGIX 0x81A7 + +#define GLEW_SGIX_depth_texture GLEW_GET_VAR(__GLEW_SGIX_depth_texture) + +#endif /* GL_SGIX_depth_texture */ + +/* -------------------------- GL_SGIX_flush_raster ------------------------- */ + +#ifndef GL_SGIX_flush_raster +#define GL_SGIX_flush_raster 1 + +typedef void (GLAPIENTRY * PFNGLFLUSHRASTERSGIXPROC) (void); + +#define glFlushRasterSGIX GLEW_GET_FUN(__glewFlushRasterSGIX) + +#define GLEW_SGIX_flush_raster GLEW_GET_VAR(__GLEW_SGIX_flush_raster) + +#endif /* GL_SGIX_flush_raster */ + +/* --------------------------- GL_SGIX_fog_offset -------------------------- */ + +#ifndef GL_SGIX_fog_offset +#define GL_SGIX_fog_offset 1 + +#define GL_FOG_OFFSET_SGIX 0x8198 +#define GL_FOG_OFFSET_VALUE_SGIX 0x8199 + +#define GLEW_SGIX_fog_offset GLEW_GET_VAR(__GLEW_SGIX_fog_offset) + +#endif /* GL_SGIX_fog_offset */ + +/* -------------------------- GL_SGIX_fog_texture -------------------------- */ + +#ifndef GL_SGIX_fog_texture +#define GL_SGIX_fog_texture 1 + +#define GL_TEXTURE_FOG_SGIX 0 +#define GL_FOG_PATCHY_FACTOR_SGIX 0 +#define GL_FRAGMENT_FOG_SGIX 0 + +typedef void (GLAPIENTRY * PFNGLTEXTUREFOGSGIXPROC) (GLenum pname); + +#define glTextureFogSGIX GLEW_GET_FUN(__glewTextureFogSGIX) + +#define GLEW_SGIX_fog_texture GLEW_GET_VAR(__GLEW_SGIX_fog_texture) + +#endif /* GL_SGIX_fog_texture */ + +/* ------------------- GL_SGIX_fragment_specular_lighting ------------------ */ + +#ifndef GL_SGIX_fragment_specular_lighting +#define GL_SGIX_fragment_specular_lighting 1 + +typedef void (GLAPIENTRY * PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, const GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, const GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum value, GLfloat* data); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum value, GLint* data); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat* data); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint* data); + +#define glFragmentColorMaterialSGIX GLEW_GET_FUN(__glewFragmentColorMaterialSGIX) +#define glFragmentLightModelfSGIX GLEW_GET_FUN(__glewFragmentLightModelfSGIX) +#define glFragmentLightModelfvSGIX GLEW_GET_FUN(__glewFragmentLightModelfvSGIX) +#define glFragmentLightModeliSGIX GLEW_GET_FUN(__glewFragmentLightModeliSGIX) +#define glFragmentLightModelivSGIX GLEW_GET_FUN(__glewFragmentLightModelivSGIX) +#define glFragmentLightfSGIX GLEW_GET_FUN(__glewFragmentLightfSGIX) +#define glFragmentLightfvSGIX GLEW_GET_FUN(__glewFragmentLightfvSGIX) +#define glFragmentLightiSGIX GLEW_GET_FUN(__glewFragmentLightiSGIX) +#define glFragmentLightivSGIX GLEW_GET_FUN(__glewFragmentLightivSGIX) +#define glFragmentMaterialfSGIX GLEW_GET_FUN(__glewFragmentMaterialfSGIX) +#define glFragmentMaterialfvSGIX GLEW_GET_FUN(__glewFragmentMaterialfvSGIX) +#define glFragmentMaterialiSGIX GLEW_GET_FUN(__glewFragmentMaterialiSGIX) +#define glFragmentMaterialivSGIX GLEW_GET_FUN(__glewFragmentMaterialivSGIX) +#define glGetFragmentLightfvSGIX GLEW_GET_FUN(__glewGetFragmentLightfvSGIX) +#define glGetFragmentLightivSGIX GLEW_GET_FUN(__glewGetFragmentLightivSGIX) +#define glGetFragmentMaterialfvSGIX GLEW_GET_FUN(__glewGetFragmentMaterialfvSGIX) +#define glGetFragmentMaterialivSGIX GLEW_GET_FUN(__glewGetFragmentMaterialivSGIX) + +#define GLEW_SGIX_fragment_specular_lighting GLEW_GET_VAR(__GLEW_SGIX_fragment_specular_lighting) + +#endif /* GL_SGIX_fragment_specular_lighting */ + +/* --------------------------- GL_SGIX_framezoom --------------------------- */ + +#ifndef GL_SGIX_framezoom +#define GL_SGIX_framezoom 1 + +typedef void (GLAPIENTRY * PFNGLFRAMEZOOMSGIXPROC) (GLint factor); + +#define glFrameZoomSGIX GLEW_GET_FUN(__glewFrameZoomSGIX) + +#define GLEW_SGIX_framezoom GLEW_GET_VAR(__GLEW_SGIX_framezoom) + +#endif /* GL_SGIX_framezoom */ + +/* --------------------------- GL_SGIX_interlace --------------------------- */ + +#ifndef GL_SGIX_interlace +#define GL_SGIX_interlace 1 + +#define GL_INTERLACE_SGIX 0x8094 + +#define GLEW_SGIX_interlace GLEW_GET_VAR(__GLEW_SGIX_interlace) + +#endif /* GL_SGIX_interlace */ + +/* ------------------------- GL_SGIX_ir_instrument1 ------------------------ */ + +#ifndef GL_SGIX_ir_instrument1 +#define GL_SGIX_ir_instrument1 1 + +#define GLEW_SGIX_ir_instrument1 GLEW_GET_VAR(__GLEW_SGIX_ir_instrument1) + +#endif /* GL_SGIX_ir_instrument1 */ + +/* ------------------------- GL_SGIX_list_priority ------------------------- */ + +#ifndef GL_SGIX_list_priority +#define GL_SGIX_list_priority 1 + +#define GLEW_SGIX_list_priority GLEW_GET_VAR(__GLEW_SGIX_list_priority) + +#endif /* GL_SGIX_list_priority */ + +/* ------------------------- GL_SGIX_pixel_texture ------------------------- */ + +#ifndef GL_SGIX_pixel_texture +#define GL_SGIX_pixel_texture 1 + +typedef void (GLAPIENTRY * PFNGLPIXELTEXGENSGIXPROC) (GLenum mode); + +#define glPixelTexGenSGIX GLEW_GET_FUN(__glewPixelTexGenSGIX) + +#define GLEW_SGIX_pixel_texture GLEW_GET_VAR(__GLEW_SGIX_pixel_texture) + +#endif /* GL_SGIX_pixel_texture */ + +/* ----------------------- GL_SGIX_pixel_texture_bits ---------------------- */ + +#ifndef GL_SGIX_pixel_texture_bits +#define GL_SGIX_pixel_texture_bits 1 + +#define GLEW_SGIX_pixel_texture_bits GLEW_GET_VAR(__GLEW_SGIX_pixel_texture_bits) + +#endif /* GL_SGIX_pixel_texture_bits */ + +/* ------------------------ GL_SGIX_reference_plane ------------------------ */ + +#ifndef GL_SGIX_reference_plane +#define GL_SGIX_reference_plane 1 + +typedef void (GLAPIENTRY * PFNGLREFERENCEPLANESGIXPROC) (const GLdouble* equation); + +#define glReferencePlaneSGIX GLEW_GET_FUN(__glewReferencePlaneSGIX) + +#define GLEW_SGIX_reference_plane GLEW_GET_VAR(__GLEW_SGIX_reference_plane) + +#endif /* GL_SGIX_reference_plane */ + +/* ---------------------------- GL_SGIX_resample --------------------------- */ + +#ifndef GL_SGIX_resample +#define GL_SGIX_resample 1 + +#define GL_PACK_RESAMPLE_SGIX 0x842E +#define GL_UNPACK_RESAMPLE_SGIX 0x842F +#define GL_RESAMPLE_DECIMATE_SGIX 0x8430 +#define GL_RESAMPLE_REPLICATE_SGIX 0x8433 +#define GL_RESAMPLE_ZERO_FILL_SGIX 0x8434 + +#define GLEW_SGIX_resample GLEW_GET_VAR(__GLEW_SGIX_resample) + +#endif /* GL_SGIX_resample */ + +/* ----------------------------- GL_SGIX_shadow ---------------------------- */ + +#ifndef GL_SGIX_shadow +#define GL_SGIX_shadow 1 + +#define GL_TEXTURE_COMPARE_SGIX 0x819A +#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B +#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C +#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D + +#define GLEW_SGIX_shadow GLEW_GET_VAR(__GLEW_SGIX_shadow) + +#endif /* GL_SGIX_shadow */ + +/* ------------------------- GL_SGIX_shadow_ambient ------------------------ */ + +#ifndef GL_SGIX_shadow_ambient +#define GL_SGIX_shadow_ambient 1 + +#define GL_SHADOW_AMBIENT_SGIX 0x80BF + +#define GLEW_SGIX_shadow_ambient GLEW_GET_VAR(__GLEW_SGIX_shadow_ambient) + +#endif /* GL_SGIX_shadow_ambient */ + +/* ----------------------------- GL_SGIX_sprite ---------------------------- */ + +#ifndef GL_SGIX_sprite +#define GL_SGIX_sprite 1 + +typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, GLint* params); + +#define glSpriteParameterfSGIX GLEW_GET_FUN(__glewSpriteParameterfSGIX) +#define glSpriteParameterfvSGIX GLEW_GET_FUN(__glewSpriteParameterfvSGIX) +#define glSpriteParameteriSGIX GLEW_GET_FUN(__glewSpriteParameteriSGIX) +#define glSpriteParameterivSGIX GLEW_GET_FUN(__glewSpriteParameterivSGIX) + +#define GLEW_SGIX_sprite GLEW_GET_VAR(__GLEW_SGIX_sprite) + +#endif /* GL_SGIX_sprite */ + +/* ----------------------- GL_SGIX_tag_sample_buffer ----------------------- */ + +#ifndef GL_SGIX_tag_sample_buffer +#define GL_SGIX_tag_sample_buffer 1 + +typedef void (GLAPIENTRY * PFNGLTAGSAMPLEBUFFERSGIXPROC) (void); + +#define glTagSampleBufferSGIX GLEW_GET_FUN(__glewTagSampleBufferSGIX) + +#define GLEW_SGIX_tag_sample_buffer GLEW_GET_VAR(__GLEW_SGIX_tag_sample_buffer) + +#endif /* GL_SGIX_tag_sample_buffer */ + +/* ------------------------ GL_SGIX_texture_add_env ------------------------ */ + +#ifndef GL_SGIX_texture_add_env +#define GL_SGIX_texture_add_env 1 + +#define GLEW_SGIX_texture_add_env GLEW_GET_VAR(__GLEW_SGIX_texture_add_env) + +#endif /* GL_SGIX_texture_add_env */ + +/* -------------------- GL_SGIX_texture_coordinate_clamp ------------------- */ + +#ifndef GL_SGIX_texture_coordinate_clamp +#define GL_SGIX_texture_coordinate_clamp 1 + +#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369 +#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A +#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B + +#define GLEW_SGIX_texture_coordinate_clamp GLEW_GET_VAR(__GLEW_SGIX_texture_coordinate_clamp) + +#endif /* GL_SGIX_texture_coordinate_clamp */ + +/* ------------------------ GL_SGIX_texture_lod_bias ----------------------- */ + +#ifndef GL_SGIX_texture_lod_bias +#define GL_SGIX_texture_lod_bias 1 + +#define GLEW_SGIX_texture_lod_bias GLEW_GET_VAR(__GLEW_SGIX_texture_lod_bias) + +#endif /* GL_SGIX_texture_lod_bias */ + +/* ---------------------- GL_SGIX_texture_multi_buffer --------------------- */ + +#ifndef GL_SGIX_texture_multi_buffer +#define GL_SGIX_texture_multi_buffer 1 + +#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E + +#define GLEW_SGIX_texture_multi_buffer GLEW_GET_VAR(__GLEW_SGIX_texture_multi_buffer) + +#endif /* GL_SGIX_texture_multi_buffer */ + +/* ------------------------- GL_SGIX_texture_range ------------------------- */ + +#ifndef GL_SGIX_texture_range +#define GL_SGIX_texture_range 1 + +#define GL_RGB_SIGNED_SGIX 0x85E0 +#define GL_RGBA_SIGNED_SGIX 0x85E1 +#define GL_ALPHA_SIGNED_SGIX 0x85E2 +#define GL_LUMINANCE_SIGNED_SGIX 0x85E3 +#define GL_INTENSITY_SIGNED_SGIX 0x85E4 +#define GL_LUMINANCE_ALPHA_SIGNED_SGIX 0x85E5 +#define GL_RGB16_SIGNED_SGIX 0x85E6 +#define GL_RGBA16_SIGNED_SGIX 0x85E7 +#define GL_ALPHA16_SIGNED_SGIX 0x85E8 +#define GL_LUMINANCE16_SIGNED_SGIX 0x85E9 +#define GL_INTENSITY16_SIGNED_SGIX 0x85EA +#define GL_LUMINANCE16_ALPHA16_SIGNED_SGIX 0x85EB +#define GL_RGB_EXTENDED_RANGE_SGIX 0x85EC +#define GL_RGBA_EXTENDED_RANGE_SGIX 0x85ED +#define GL_ALPHA_EXTENDED_RANGE_SGIX 0x85EE +#define GL_LUMINANCE_EXTENDED_RANGE_SGIX 0x85EF +#define GL_INTENSITY_EXTENDED_RANGE_SGIX 0x85F0 +#define GL_LUMINANCE_ALPHA_EXTENDED_RANGE_SGIX 0x85F1 +#define GL_RGB16_EXTENDED_RANGE_SGIX 0x85F2 +#define GL_RGBA16_EXTENDED_RANGE_SGIX 0x85F3 +#define GL_ALPHA16_EXTENDED_RANGE_SGIX 0x85F4 +#define GL_LUMINANCE16_EXTENDED_RANGE_SGIX 0x85F5 +#define GL_INTENSITY16_EXTENDED_RANGE_SGIX 0x85F6 +#define GL_LUMINANCE16_ALPHA16_EXTENDED_RANGE_SGIX 0x85F7 +#define GL_MIN_LUMINANCE_SGIS 0x85F8 +#define GL_MAX_LUMINANCE_SGIS 0x85F9 +#define GL_MIN_INTENSITY_SGIS 0x85FA +#define GL_MAX_INTENSITY_SGIS 0x85FB + +#define GLEW_SGIX_texture_range GLEW_GET_VAR(__GLEW_SGIX_texture_range) + +#endif /* GL_SGIX_texture_range */ + +/* ----------------------- GL_SGIX_texture_scale_bias ---------------------- */ + +#ifndef GL_SGIX_texture_scale_bias +#define GL_SGIX_texture_scale_bias 1 + +#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179 +#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A +#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B +#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C + +#define GLEW_SGIX_texture_scale_bias GLEW_GET_VAR(__GLEW_SGIX_texture_scale_bias) + +#endif /* GL_SGIX_texture_scale_bias */ + +/* ------------------------- GL_SGIX_vertex_preclip ------------------------ */ + +#ifndef GL_SGIX_vertex_preclip +#define GL_SGIX_vertex_preclip 1 + +#define GL_VERTEX_PRECLIP_SGIX 0x83EE +#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF + +#define GLEW_SGIX_vertex_preclip GLEW_GET_VAR(__GLEW_SGIX_vertex_preclip) + +#endif /* GL_SGIX_vertex_preclip */ + +/* ---------------------- GL_SGIX_vertex_preclip_hint ---------------------- */ + +#ifndef GL_SGIX_vertex_preclip_hint +#define GL_SGIX_vertex_preclip_hint 1 + +#define GL_VERTEX_PRECLIP_SGIX 0x83EE +#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF + +#define GLEW_SGIX_vertex_preclip_hint GLEW_GET_VAR(__GLEW_SGIX_vertex_preclip_hint) + +#endif /* GL_SGIX_vertex_preclip_hint */ + +/* ----------------------------- GL_SGIX_ycrcb ----------------------------- */ + +#ifndef GL_SGIX_ycrcb +#define GL_SGIX_ycrcb 1 + +#define GLEW_SGIX_ycrcb GLEW_GET_VAR(__GLEW_SGIX_ycrcb) + +#endif /* GL_SGIX_ycrcb */ + +/* -------------------------- GL_SGI_color_matrix -------------------------- */ + +#ifndef GL_SGI_color_matrix +#define GL_SGI_color_matrix 1 + +#define GL_COLOR_MATRIX_SGI 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB + +#define GLEW_SGI_color_matrix GLEW_GET_VAR(__GLEW_SGI_color_matrix) + +#endif /* GL_SGI_color_matrix */ + +/* --------------------------- GL_SGI_color_table -------------------------- */ + +#ifndef GL_SGI_color_table +#define GL_SGI_color_table 1 + +#define GL_COLOR_TABLE_SGI 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2 +#define GL_PROXY_COLOR_TABLE_SGI 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5 +#define GL_COLOR_TABLE_SCALE_SGI 0x80D6 +#define GL_COLOR_TABLE_BIAS_SGI 0x80D7 +#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8 +#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF + +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* table); +typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, void* table); + +#define glColorTableParameterfvSGI GLEW_GET_FUN(__glewColorTableParameterfvSGI) +#define glColorTableParameterivSGI GLEW_GET_FUN(__glewColorTableParameterivSGI) +#define glColorTableSGI GLEW_GET_FUN(__glewColorTableSGI) +#define glCopyColorTableSGI GLEW_GET_FUN(__glewCopyColorTableSGI) +#define glGetColorTableParameterfvSGI GLEW_GET_FUN(__glewGetColorTableParameterfvSGI) +#define glGetColorTableParameterivSGI GLEW_GET_FUN(__glewGetColorTableParameterivSGI) +#define glGetColorTableSGI GLEW_GET_FUN(__glewGetColorTableSGI) + +#define GLEW_SGI_color_table GLEW_GET_VAR(__GLEW_SGI_color_table) + +#endif /* GL_SGI_color_table */ + +/* ----------------------- GL_SGI_texture_color_table ---------------------- */ + +#ifndef GL_SGI_texture_color_table +#define GL_SGI_texture_color_table 1 + +#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC +#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD + +#define GLEW_SGI_texture_color_table GLEW_GET_VAR(__GLEW_SGI_texture_color_table) + +#endif /* GL_SGI_texture_color_table */ + +/* ------------------------- GL_SUNX_constant_data ------------------------- */ + +#ifndef GL_SUNX_constant_data +#define GL_SUNX_constant_data 1 + +#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5 +#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6 + +typedef void (GLAPIENTRY * PFNGLFINISHTEXTURESUNXPROC) (void); + +#define glFinishTextureSUNX GLEW_GET_FUN(__glewFinishTextureSUNX) + +#define GLEW_SUNX_constant_data GLEW_GET_VAR(__GLEW_SUNX_constant_data) + +#endif /* GL_SUNX_constant_data */ + +/* -------------------- GL_SUN_convolution_border_modes -------------------- */ + +#ifndef GL_SUN_convolution_border_modes +#define GL_SUN_convolution_border_modes 1 + +#define GL_WRAP_BORDER_SUN 0x81D4 + +#define GLEW_SUN_convolution_border_modes GLEW_GET_VAR(__GLEW_SUN_convolution_border_modes) + +#endif /* GL_SUN_convolution_border_modes */ + +/* -------------------------- GL_SUN_global_alpha -------------------------- */ + +#ifndef GL_SUN_global_alpha +#define GL_SUN_global_alpha 1 + +#define GL_GLOBAL_ALPHA_SUN 0x81D9 +#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA + +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor); + +#define glGlobalAlphaFactorbSUN GLEW_GET_FUN(__glewGlobalAlphaFactorbSUN) +#define glGlobalAlphaFactordSUN GLEW_GET_FUN(__glewGlobalAlphaFactordSUN) +#define glGlobalAlphaFactorfSUN GLEW_GET_FUN(__glewGlobalAlphaFactorfSUN) +#define glGlobalAlphaFactoriSUN GLEW_GET_FUN(__glewGlobalAlphaFactoriSUN) +#define glGlobalAlphaFactorsSUN GLEW_GET_FUN(__glewGlobalAlphaFactorsSUN) +#define glGlobalAlphaFactorubSUN GLEW_GET_FUN(__glewGlobalAlphaFactorubSUN) +#define glGlobalAlphaFactoruiSUN GLEW_GET_FUN(__glewGlobalAlphaFactoruiSUN) +#define glGlobalAlphaFactorusSUN GLEW_GET_FUN(__glewGlobalAlphaFactorusSUN) + +#define GLEW_SUN_global_alpha GLEW_GET_VAR(__GLEW_SUN_global_alpha) + +#endif /* GL_SUN_global_alpha */ + +/* --------------------------- GL_SUN_mesh_array --------------------------- */ + +#ifndef GL_SUN_mesh_array +#define GL_SUN_mesh_array 1 + +#define GL_QUAD_MESH_SUN 0x8614 +#define GL_TRIANGLE_MESH_SUN 0x8615 + +#define GLEW_SUN_mesh_array GLEW_GET_VAR(__GLEW_SUN_mesh_array) + +#endif /* GL_SUN_mesh_array */ + +/* ------------------------ GL_SUN_read_video_pixels ----------------------- */ + +#ifndef GL_SUN_read_video_pixels +#define GL_SUN_read_video_pixels 1 + +typedef void (GLAPIENTRY * PFNGLREADVIDEOPIXELSSUNPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); + +#define glReadVideoPixelsSUN GLEW_GET_FUN(__glewReadVideoPixelsSUN) + +#define GLEW_SUN_read_video_pixels GLEW_GET_VAR(__GLEW_SUN_read_video_pixels) + +#endif /* GL_SUN_read_video_pixels */ + +/* --------------------------- GL_SUN_slice_accum -------------------------- */ + +#ifndef GL_SUN_slice_accum +#define GL_SUN_slice_accum 1 + +#define GL_SLICE_ACCUM_SUN 0x85CC + +#define GLEW_SUN_slice_accum GLEW_GET_VAR(__GLEW_SUN_slice_accum) + +#endif /* GL_SUN_slice_accum */ + +/* -------------------------- GL_SUN_triangle_list ------------------------- */ + +#ifndef GL_SUN_triangle_list +#define GL_SUN_triangle_list 1 + +#define GL_RESTART_SUN 0x01 +#define GL_REPLACE_MIDDLE_SUN 0x02 +#define GL_REPLACE_OLDEST_SUN 0x03 +#define GL_TRIANGLE_LIST_SUN 0x81D7 +#define GL_REPLACEMENT_CODE_SUN 0x81D8 +#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0 +#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 +#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 +#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 +#define GL_R1UI_V3F_SUN 0x85C4 +#define GL_R1UI_C4UB_V3F_SUN 0x85C5 +#define GL_R1UI_C3F_V3F_SUN 0x85C6 +#define GL_R1UI_N3F_V3F_SUN 0x85C7 +#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8 +#define GL_R1UI_T2F_V3F_SUN 0x85C9 +#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA +#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB + +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte* code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint* code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort* code); + +#define glReplacementCodePointerSUN GLEW_GET_FUN(__glewReplacementCodePointerSUN) +#define glReplacementCodeubSUN GLEW_GET_FUN(__glewReplacementCodeubSUN) +#define glReplacementCodeubvSUN GLEW_GET_FUN(__glewReplacementCodeubvSUN) +#define glReplacementCodeuiSUN GLEW_GET_FUN(__glewReplacementCodeuiSUN) +#define glReplacementCodeuivSUN GLEW_GET_FUN(__glewReplacementCodeuivSUN) +#define glReplacementCodeusSUN GLEW_GET_FUN(__glewReplacementCodeusSUN) +#define glReplacementCodeusvSUN GLEW_GET_FUN(__glewReplacementCodeusvSUN) + +#define GLEW_SUN_triangle_list GLEW_GET_VAR(__GLEW_SUN_triangle_list) + +#endif /* GL_SUN_triangle_list */ + +/* ----------------------------- GL_SUN_vertex ----------------------------- */ + +#ifndef GL_SUN_vertex +#define GL_SUN_vertex 1 + +typedef void (GLAPIENTRY * PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat* c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte* c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte* c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint* rc, const GLubyte *c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat* tc, const GLubyte *c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat* tc, const GLfloat *v); + +#define glColor3fVertex3fSUN GLEW_GET_FUN(__glewColor3fVertex3fSUN) +#define glColor3fVertex3fvSUN GLEW_GET_FUN(__glewColor3fVertex3fvSUN) +#define glColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewColor4fNormal3fVertex3fSUN) +#define glColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewColor4fNormal3fVertex3fvSUN) +#define glColor4ubVertex2fSUN GLEW_GET_FUN(__glewColor4ubVertex2fSUN) +#define glColor4ubVertex2fvSUN GLEW_GET_FUN(__glewColor4ubVertex2fvSUN) +#define glColor4ubVertex3fSUN GLEW_GET_FUN(__glewColor4ubVertex3fSUN) +#define glColor4ubVertex3fvSUN GLEW_GET_FUN(__glewColor4ubVertex3fvSUN) +#define glNormal3fVertex3fSUN GLEW_GET_FUN(__glewNormal3fVertex3fSUN) +#define glNormal3fVertex3fvSUN GLEW_GET_FUN(__glewNormal3fVertex3fvSUN) +#define glReplacementCodeuiColor3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor3fVertex3fSUN) +#define glReplacementCodeuiColor3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor3fVertex3fvSUN) +#define glReplacementCodeuiColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4fNormal3fVertex3fSUN) +#define glReplacementCodeuiColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4fNormal3fVertex3fvSUN) +#define glReplacementCodeuiColor4ubVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4ubVertex3fSUN) +#define glReplacementCodeuiColor4ubVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4ubVertex3fvSUN) +#define glReplacementCodeuiNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiNormal3fVertex3fSUN) +#define glReplacementCodeuiNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fVertex3fvSUN) +#define glReplacementCodeuiVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiVertex3fSUN) +#define glReplacementCodeuiVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiVertex3fvSUN) +#define glTexCoord2fColor3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor3fVertex3fSUN) +#define glTexCoord2fColor3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor3fVertex3fvSUN) +#define glTexCoord2fColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor4fNormal3fVertex3fSUN) +#define glTexCoord2fColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor4fNormal3fVertex3fvSUN) +#define glTexCoord2fColor4ubVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor4ubVertex3fSUN) +#define glTexCoord2fColor4ubVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor4ubVertex3fvSUN) +#define glTexCoord2fNormal3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fNormal3fVertex3fSUN) +#define glTexCoord2fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fNormal3fVertex3fvSUN) +#define glTexCoord2fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fVertex3fSUN) +#define glTexCoord2fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fVertex3fvSUN) +#define glTexCoord4fColor4fNormal3fVertex4fSUN GLEW_GET_FUN(__glewTexCoord4fColor4fNormal3fVertex4fSUN) +#define glTexCoord4fColor4fNormal3fVertex4fvSUN GLEW_GET_FUN(__glewTexCoord4fColor4fNormal3fVertex4fvSUN) +#define glTexCoord4fVertex4fSUN GLEW_GET_FUN(__glewTexCoord4fVertex4fSUN) +#define glTexCoord4fVertex4fvSUN GLEW_GET_FUN(__glewTexCoord4fVertex4fvSUN) + +#define GLEW_SUN_vertex GLEW_GET_VAR(__GLEW_SUN_vertex) + +#endif /* GL_SUN_vertex */ + +/* -------------------------- GL_WIN_phong_shading ------------------------- */ + +#ifndef GL_WIN_phong_shading +#define GL_WIN_phong_shading 1 + +#define GL_PHONG_WIN 0x80EA +#define GL_PHONG_HINT_WIN 0x80EB + +#define GLEW_WIN_phong_shading GLEW_GET_VAR(__GLEW_WIN_phong_shading) + +#endif /* GL_WIN_phong_shading */ + +/* -------------------------- GL_WIN_specular_fog -------------------------- */ + +#ifndef GL_WIN_specular_fog +#define GL_WIN_specular_fog 1 + +#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC + +#define GLEW_WIN_specular_fog GLEW_GET_VAR(__GLEW_WIN_specular_fog) + +#endif /* GL_WIN_specular_fog */ + +/* ---------------------------- GL_WIN_swap_hint --------------------------- */ + +#ifndef GL_WIN_swap_hint +#define GL_WIN_swap_hint 1 + +typedef void (GLAPIENTRY * PFNGLADDSWAPHINTRECTWINPROC) (GLint x, GLint y, GLsizei width, GLsizei height); + +#define glAddSwapHintRectWIN GLEW_GET_FUN(__glewAddSwapHintRectWIN) + +#define GLEW_WIN_swap_hint GLEW_GET_VAR(__GLEW_WIN_swap_hint) + +#endif /* GL_WIN_swap_hint */ + +/* ------------------------------------------------------------------------- */ + +#if defined(GLEW_MX) && defined(_WIN32) +#define GLEW_FUN_EXPORT +#else +#define GLEW_FUN_EXPORT GLEWAPI +#endif /* GLEW_MX */ + +#if defined(GLEW_MX) +#define GLEW_VAR_EXPORT +#else +#define GLEW_VAR_EXPORT GLEWAPI +#endif /* GLEW_MX */ + +#if defined(GLEW_MX) && defined(_WIN32) +struct GLEWContextStruct +{ +#endif /* GLEW_MX */ + +GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DPROC __glewCopyTexSubImage3D; +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSPROC __glewDrawRangeElements; +GLEW_FUN_EXPORT PFNGLTEXIMAGE3DPROC __glewTexImage3D; +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DPROC __glewTexSubImage3D; + +GLEW_FUN_EXPORT PFNGLACTIVETEXTUREPROC __glewActiveTexture; +GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREPROC __glewClientActiveTexture; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DPROC __glewCompressedTexImage1D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DPROC __glewCompressedTexImage2D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DPROC __glewCompressedTexImage3D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC __glewCompressedTexSubImage1D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC __glewCompressedTexSubImage2D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC __glewCompressedTexSubImage3D; +GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXIMAGEPROC __glewGetCompressedTexImage; +GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXDPROC __glewLoadTransposeMatrixd; +GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXFPROC __glewLoadTransposeMatrixf; +GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXDPROC __glewMultTransposeMatrixd; +GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXFPROC __glewMultTransposeMatrixf; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DPROC __glewMultiTexCoord1d; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DVPROC __glewMultiTexCoord1dv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FPROC __glewMultiTexCoord1f; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FVPROC __glewMultiTexCoord1fv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IPROC __glewMultiTexCoord1i; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IVPROC __glewMultiTexCoord1iv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SPROC __glewMultiTexCoord1s; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SVPROC __glewMultiTexCoord1sv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DPROC __glewMultiTexCoord2d; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DVPROC __glewMultiTexCoord2dv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FPROC __glewMultiTexCoord2f; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FVPROC __glewMultiTexCoord2fv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IPROC __glewMultiTexCoord2i; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IVPROC __glewMultiTexCoord2iv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SPROC __glewMultiTexCoord2s; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SVPROC __glewMultiTexCoord2sv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DPROC __glewMultiTexCoord3d; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DVPROC __glewMultiTexCoord3dv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FPROC __glewMultiTexCoord3f; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FVPROC __glewMultiTexCoord3fv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IPROC __glewMultiTexCoord3i; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IVPROC __glewMultiTexCoord3iv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SPROC __glewMultiTexCoord3s; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SVPROC __glewMultiTexCoord3sv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DPROC __glewMultiTexCoord4d; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DVPROC __glewMultiTexCoord4dv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FPROC __glewMultiTexCoord4f; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FVPROC __glewMultiTexCoord4fv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IPROC __glewMultiTexCoord4i; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IVPROC __glewMultiTexCoord4iv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SPROC __glewMultiTexCoord4s; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SVPROC __glewMultiTexCoord4sv; +GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEPROC __glewSampleCoverage; + +GLEW_FUN_EXPORT PFNGLBLENDCOLORPROC __glewBlendColor; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONPROC __glewBlendEquation; +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEPROC __glewBlendFuncSeparate; +GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTERPROC __glewFogCoordPointer; +GLEW_FUN_EXPORT PFNGLFOGCOORDDPROC __glewFogCoordd; +GLEW_FUN_EXPORT PFNGLFOGCOORDDVPROC __glewFogCoorddv; +GLEW_FUN_EXPORT PFNGLFOGCOORDFPROC __glewFogCoordf; +GLEW_FUN_EXPORT PFNGLFOGCOORDFVPROC __glewFogCoordfv; +GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSPROC __glewMultiDrawArrays; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSPROC __glewMultiDrawElements; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFPROC __glewPointParameterf; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVPROC __glewPointParameterfv; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIPROC __glewPointParameteri; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIVPROC __glewPointParameteriv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BPROC __glewSecondaryColor3b; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BVPROC __glewSecondaryColor3bv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DPROC __glewSecondaryColor3d; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DVPROC __glewSecondaryColor3dv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FPROC __glewSecondaryColor3f; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FVPROC __glewSecondaryColor3fv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IPROC __glewSecondaryColor3i; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IVPROC __glewSecondaryColor3iv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SPROC __glewSecondaryColor3s; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SVPROC __glewSecondaryColor3sv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBPROC __glewSecondaryColor3ub; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBVPROC __glewSecondaryColor3ubv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIPROC __glewSecondaryColor3ui; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIVPROC __glewSecondaryColor3uiv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USPROC __glewSecondaryColor3us; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USVPROC __glewSecondaryColor3usv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERPROC __glewSecondaryColorPointer; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DPROC __glewWindowPos2d; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVPROC __glewWindowPos2dv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FPROC __glewWindowPos2f; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVPROC __glewWindowPos2fv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IPROC __glewWindowPos2i; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVPROC __glewWindowPos2iv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SPROC __glewWindowPos2s; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVPROC __glewWindowPos2sv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DPROC __glewWindowPos3d; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVPROC __glewWindowPos3dv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FPROC __glewWindowPos3f; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVPROC __glewWindowPos3fv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IPROC __glewWindowPos3i; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVPROC __glewWindowPos3iv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SPROC __glewWindowPos3s; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVPROC __glewWindowPos3sv; + +GLEW_FUN_EXPORT PFNGLBEGINQUERYPROC __glewBeginQuery; +GLEW_FUN_EXPORT PFNGLBINDBUFFERPROC __glewBindBuffer; +GLEW_FUN_EXPORT PFNGLBUFFERDATAPROC __glewBufferData; +GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAPROC __glewBufferSubData; +GLEW_FUN_EXPORT PFNGLDELETEBUFFERSPROC __glewDeleteBuffers; +GLEW_FUN_EXPORT PFNGLDELETEQUERIESPROC __glewDeleteQueries; +GLEW_FUN_EXPORT PFNGLENDQUERYPROC __glewEndQuery; +GLEW_FUN_EXPORT PFNGLGENBUFFERSPROC __glewGenBuffers; +GLEW_FUN_EXPORT PFNGLGENQUERIESPROC __glewGenQueries; +GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVPROC __glewGetBufferParameteriv; +GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVPROC __glewGetBufferPointerv; +GLEW_FUN_EXPORT PFNGLGETBUFFERSUBDATAPROC __glewGetBufferSubData; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVPROC __glewGetQueryObjectiv; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVPROC __glewGetQueryObjectuiv; +GLEW_FUN_EXPORT PFNGLGETQUERYIVPROC __glewGetQueryiv; +GLEW_FUN_EXPORT PFNGLISBUFFERPROC __glewIsBuffer; +GLEW_FUN_EXPORT PFNGLISQUERYPROC __glewIsQuery; +GLEW_FUN_EXPORT PFNGLMAPBUFFERPROC __glewMapBuffer; +GLEW_FUN_EXPORT PFNGLUNMAPBUFFERPROC __glewUnmapBuffer; + +GLEW_FUN_EXPORT PFNGLATTACHSHADERPROC __glewAttachShader; +GLEW_FUN_EXPORT PFNGLBINDATTRIBLOCATIONPROC __glewBindAttribLocation; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEPROC __glewBlendEquationSeparate; +GLEW_FUN_EXPORT PFNGLCOMPILESHADERPROC __glewCompileShader; +GLEW_FUN_EXPORT PFNGLCREATEPROGRAMPROC __glewCreateProgram; +GLEW_FUN_EXPORT PFNGLCREATESHADERPROC __glewCreateShader; +GLEW_FUN_EXPORT PFNGLDELETEPROGRAMPROC __glewDeleteProgram; +GLEW_FUN_EXPORT PFNGLDELETESHADERPROC __glewDeleteShader; +GLEW_FUN_EXPORT PFNGLDETACHSHADERPROC __glewDetachShader; +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBARRAYPROC __glewDisableVertexAttribArray; +GLEW_FUN_EXPORT PFNGLDRAWBUFFERSPROC __glewDrawBuffers; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBARRAYPROC __glewEnableVertexAttribArray; +GLEW_FUN_EXPORT PFNGLGETACTIVEATTRIBPROC __glewGetActiveAttrib; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMPROC __glewGetActiveUniform; +GLEW_FUN_EXPORT PFNGLGETATTACHEDSHADERSPROC __glewGetAttachedShaders; +GLEW_FUN_EXPORT PFNGLGETATTRIBLOCATIONPROC __glewGetAttribLocation; +GLEW_FUN_EXPORT PFNGLGETPROGRAMINFOLOGPROC __glewGetProgramInfoLog; +GLEW_FUN_EXPORT PFNGLGETPROGRAMIVPROC __glewGetProgramiv; +GLEW_FUN_EXPORT PFNGLGETSHADERINFOLOGPROC __glewGetShaderInfoLog; +GLEW_FUN_EXPORT PFNGLGETSHADERSOURCEPROC __glewGetShaderSource; +GLEW_FUN_EXPORT PFNGLGETSHADERIVPROC __glewGetShaderiv; +GLEW_FUN_EXPORT PFNGLGETUNIFORMLOCATIONPROC __glewGetUniformLocation; +GLEW_FUN_EXPORT PFNGLGETUNIFORMFVPROC __glewGetUniformfv; +GLEW_FUN_EXPORT PFNGLGETUNIFORMIVPROC __glewGetUniformiv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVPROC __glewGetVertexAttribPointerv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVPROC __glewGetVertexAttribdv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVPROC __glewGetVertexAttribfv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVPROC __glewGetVertexAttribiv; +GLEW_FUN_EXPORT PFNGLISPROGRAMPROC __glewIsProgram; +GLEW_FUN_EXPORT PFNGLISSHADERPROC __glewIsShader; +GLEW_FUN_EXPORT PFNGLLINKPROGRAMPROC __glewLinkProgram; +GLEW_FUN_EXPORT PFNGLSHADERSOURCEPROC __glewShaderSource; +GLEW_FUN_EXPORT PFNGLSTENCILFUNCSEPARATEPROC __glewStencilFuncSeparate; +GLEW_FUN_EXPORT PFNGLSTENCILMASKSEPARATEPROC __glewStencilMaskSeparate; +GLEW_FUN_EXPORT PFNGLSTENCILOPSEPARATEPROC __glewStencilOpSeparate; +GLEW_FUN_EXPORT PFNGLUNIFORM1FPROC __glewUniform1f; +GLEW_FUN_EXPORT PFNGLUNIFORM1FVPROC __glewUniform1fv; +GLEW_FUN_EXPORT PFNGLUNIFORM1IPROC __glewUniform1i; +GLEW_FUN_EXPORT PFNGLUNIFORM1IVPROC __glewUniform1iv; +GLEW_FUN_EXPORT PFNGLUNIFORM2FPROC __glewUniform2f; +GLEW_FUN_EXPORT PFNGLUNIFORM2FVPROC __glewUniform2fv; +GLEW_FUN_EXPORT PFNGLUNIFORM2IPROC __glewUniform2i; +GLEW_FUN_EXPORT PFNGLUNIFORM2IVPROC __glewUniform2iv; +GLEW_FUN_EXPORT PFNGLUNIFORM3FPROC __glewUniform3f; +GLEW_FUN_EXPORT PFNGLUNIFORM3FVPROC __glewUniform3fv; +GLEW_FUN_EXPORT PFNGLUNIFORM3IPROC __glewUniform3i; +GLEW_FUN_EXPORT PFNGLUNIFORM3IVPROC __glewUniform3iv; +GLEW_FUN_EXPORT PFNGLUNIFORM4FPROC __glewUniform4f; +GLEW_FUN_EXPORT PFNGLUNIFORM4FVPROC __glewUniform4fv; +GLEW_FUN_EXPORT PFNGLUNIFORM4IPROC __glewUniform4i; +GLEW_FUN_EXPORT PFNGLUNIFORM4IVPROC __glewUniform4iv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2FVPROC __glewUniformMatrix2fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3FVPROC __glewUniformMatrix3fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVPROC __glewUniformMatrix4fv; +GLEW_FUN_EXPORT PFNGLUSEPROGRAMPROC __glewUseProgram; +GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMPROC __glewValidateProgram; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DPROC __glewVertexAttrib1d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVPROC __glewVertexAttrib1dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FPROC __glewVertexAttrib1f; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVPROC __glewVertexAttrib1fv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SPROC __glewVertexAttrib1s; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVPROC __glewVertexAttrib1sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DPROC __glewVertexAttrib2d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVPROC __glewVertexAttrib2dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FPROC __glewVertexAttrib2f; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVPROC __glewVertexAttrib2fv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SPROC __glewVertexAttrib2s; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVPROC __glewVertexAttrib2sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DPROC __glewVertexAttrib3d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVPROC __glewVertexAttrib3dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FPROC __glewVertexAttrib3f; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVPROC __glewVertexAttrib3fv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SPROC __glewVertexAttrib3s; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVPROC __glewVertexAttrib3sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NBVPROC __glewVertexAttrib4Nbv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NIVPROC __glewVertexAttrib4Niv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NSVPROC __glewVertexAttrib4Nsv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBPROC __glewVertexAttrib4Nub; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBVPROC __glewVertexAttrib4Nubv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUIVPROC __glewVertexAttrib4Nuiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUSVPROC __glewVertexAttrib4Nusv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4BVPROC __glewVertexAttrib4bv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DPROC __glewVertexAttrib4d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVPROC __glewVertexAttrib4dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FPROC __glewVertexAttrib4f; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVPROC __glewVertexAttrib4fv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4IVPROC __glewVertexAttrib4iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SPROC __glewVertexAttrib4s; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVPROC __glewVertexAttrib4sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVPROC __glewVertexAttrib4ubv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UIVPROC __glewVertexAttrib4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4USVPROC __glewVertexAttrib4usv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERPROC __glewVertexAttribPointer; + +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X3FVPROC __glewUniformMatrix2x3fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X4FVPROC __glewUniformMatrix2x4fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X2FVPROC __glewUniformMatrix3x2fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X4FVPROC __glewUniformMatrix3x4fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X2FVPROC __glewUniformMatrix4x2fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X3FVPROC __glewUniformMatrix4x3fv; + +GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERPROC __glewBeginConditionalRender; +GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKPROC __glewBeginTransformFeedback; +GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONPROC __glewBindFragDataLocation; +GLEW_FUN_EXPORT PFNGLCLAMPCOLORPROC __glewClampColor; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERFIPROC __glewClearBufferfi; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERFVPROC __glewClearBufferfv; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERIVPROC __glewClearBufferiv; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERUIVPROC __glewClearBufferuiv; +GLEW_FUN_EXPORT PFNGLCOLORMASKIPROC __glewColorMaski; +GLEW_FUN_EXPORT PFNGLDISABLEIPROC __glewDisablei; +GLEW_FUN_EXPORT PFNGLENABLEIPROC __glewEnablei; +GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERPROC __glewEndConditionalRender; +GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKPROC __glewEndTransformFeedback; +GLEW_FUN_EXPORT PFNGLGETBOOLEANI_VPROC __glewGetBooleani_v; +GLEW_FUN_EXPORT PFNGLGETFRAGDATALOCATIONPROC __glewGetFragDataLocation; +GLEW_FUN_EXPORT PFNGLGETSTRINGIPROC __glewGetStringi; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIIVPROC __glewGetTexParameterIiv; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIUIVPROC __glewGetTexParameterIuiv; +GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGPROC __glewGetTransformFeedbackVarying; +GLEW_FUN_EXPORT PFNGLGETUNIFORMUIVPROC __glewGetUniformuiv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIIVPROC __glewGetVertexAttribIiv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIUIVPROC __glewGetVertexAttribIuiv; +GLEW_FUN_EXPORT PFNGLISENABLEDIPROC __glewIsEnabledi; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERIIVPROC __glewTexParameterIiv; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERIUIVPROC __glewTexParameterIuiv; +GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSPROC __glewTransformFeedbackVaryings; +GLEW_FUN_EXPORT PFNGLUNIFORM1UIPROC __glewUniform1ui; +GLEW_FUN_EXPORT PFNGLUNIFORM1UIVPROC __glewUniform1uiv; +GLEW_FUN_EXPORT PFNGLUNIFORM2UIPROC __glewUniform2ui; +GLEW_FUN_EXPORT PFNGLUNIFORM2UIVPROC __glewUniform2uiv; +GLEW_FUN_EXPORT PFNGLUNIFORM3UIPROC __glewUniform3ui; +GLEW_FUN_EXPORT PFNGLUNIFORM3UIVPROC __glewUniform3uiv; +GLEW_FUN_EXPORT PFNGLUNIFORM4UIPROC __glewUniform4ui; +GLEW_FUN_EXPORT PFNGLUNIFORM4UIVPROC __glewUniform4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IPROC __glewVertexAttribI1i; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IVPROC __glewVertexAttribI1iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIPROC __glewVertexAttribI1ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIVPROC __glewVertexAttribI1uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IPROC __glewVertexAttribI2i; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IVPROC __glewVertexAttribI2iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIPROC __glewVertexAttribI2ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIVPROC __glewVertexAttribI2uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IPROC __glewVertexAttribI3i; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IVPROC __glewVertexAttribI3iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIPROC __glewVertexAttribI3ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIVPROC __glewVertexAttribI3uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4BVPROC __glewVertexAttribI4bv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IPROC __glewVertexAttribI4i; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IVPROC __glewVertexAttribI4iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4SVPROC __glewVertexAttribI4sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UBVPROC __glewVertexAttribI4ubv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIPROC __glewVertexAttribI4ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIVPROC __glewVertexAttribI4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4USVPROC __glewVertexAttribI4usv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIPOINTERPROC __glewVertexAttribIPointer; + +GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDPROC __glewDrawArraysInstanced; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDPROC __glewDrawElementsInstanced; +GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTINDEXPROC __glewPrimitiveRestartIndex; +GLEW_FUN_EXPORT PFNGLTEXBUFFERPROC __glewTexBuffer; + +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREPROC __glewFramebufferTexture; +GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERI64VPROC __glewGetBufferParameteri64v; +GLEW_FUN_EXPORT PFNGLGETINTEGER64I_VPROC __glewGetInteger64i_v; + +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORPROC __glewVertexAttribDivisor; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEIPROC __glewBlendEquationSeparatei; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONIPROC __glewBlendEquationi; +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEIPROC __glewBlendFuncSeparatei; +GLEW_FUN_EXPORT PFNGLBLENDFUNCIPROC __glewBlendFunci; +GLEW_FUN_EXPORT PFNGLMINSAMPLESHADINGPROC __glewMinSampleShading; + +GLEW_FUN_EXPORT PFNGLTBUFFERMASK3DFXPROC __glewTbufferMask3DFX; + +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKAMDPROC __glewDebugMessageCallbackAMD; +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEENABLEAMDPROC __glewDebugMessageEnableAMD; +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTAMDPROC __glewDebugMessageInsertAMD; +GLEW_FUN_EXPORT PFNGLGETDEBUGMESSAGELOGAMDPROC __glewGetDebugMessageLogAMD; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONINDEXEDAMDPROC __glewBlendEquationIndexedAMD; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC __glewBlendEquationSeparateIndexedAMD; +GLEW_FUN_EXPORT PFNGLBLENDFUNCINDEXEDAMDPROC __glewBlendFuncIndexedAMD; +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC __glewBlendFuncSeparateIndexedAMD; + +GLEW_FUN_EXPORT PFNGLDELETENAMESAMDPROC __glewDeleteNamesAMD; +GLEW_FUN_EXPORT PFNGLGENNAMESAMDPROC __glewGenNamesAMD; +GLEW_FUN_EXPORT PFNGLISNAMEAMDPROC __glewIsNameAMD; + +GLEW_FUN_EXPORT PFNGLBEGINPERFMONITORAMDPROC __glewBeginPerfMonitorAMD; +GLEW_FUN_EXPORT PFNGLDELETEPERFMONITORSAMDPROC __glewDeletePerfMonitorsAMD; +GLEW_FUN_EXPORT PFNGLENDPERFMONITORAMDPROC __glewEndPerfMonitorAMD; +GLEW_FUN_EXPORT PFNGLGENPERFMONITORSAMDPROC __glewGenPerfMonitorsAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERDATAAMDPROC __glewGetPerfMonitorCounterDataAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERINFOAMDPROC __glewGetPerfMonitorCounterInfoAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC __glewGetPerfMonitorCounterStringAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERSAMDPROC __glewGetPerfMonitorCountersAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORGROUPSTRINGAMDPROC __glewGetPerfMonitorGroupStringAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORGROUPSAMDPROC __glewGetPerfMonitorGroupsAMD; +GLEW_FUN_EXPORT PFNGLSELECTPERFMONITORCOUNTERSAMDPROC __glewSelectPerfMonitorCountersAMD; + +GLEW_FUN_EXPORT PFNGLSETMULTISAMPLEFVAMDPROC __glewSetMultisamplefvAMD; + +GLEW_FUN_EXPORT PFNGLTESSELLATIONFACTORAMDPROC __glewTessellationFactorAMD; +GLEW_FUN_EXPORT PFNGLTESSELLATIONMODEAMDPROC __glewTessellationModeAMD; + +GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYAPPLEPROC __glewDrawElementArrayAPPLE; +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC __glewDrawRangeElementArrayAPPLE; +GLEW_FUN_EXPORT PFNGLELEMENTPOINTERAPPLEPROC __glewElementPointerAPPLE; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC __glewMultiDrawElementArrayAPPLE; +GLEW_FUN_EXPORT PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC __glewMultiDrawRangeElementArrayAPPLE; + +GLEW_FUN_EXPORT PFNGLDELETEFENCESAPPLEPROC __glewDeleteFencesAPPLE; +GLEW_FUN_EXPORT PFNGLFINISHFENCEAPPLEPROC __glewFinishFenceAPPLE; +GLEW_FUN_EXPORT PFNGLFINISHOBJECTAPPLEPROC __glewFinishObjectAPPLE; +GLEW_FUN_EXPORT PFNGLGENFENCESAPPLEPROC __glewGenFencesAPPLE; +GLEW_FUN_EXPORT PFNGLISFENCEAPPLEPROC __glewIsFenceAPPLE; +GLEW_FUN_EXPORT PFNGLSETFENCEAPPLEPROC __glewSetFenceAPPLE; +GLEW_FUN_EXPORT PFNGLTESTFENCEAPPLEPROC __glewTestFenceAPPLE; +GLEW_FUN_EXPORT PFNGLTESTOBJECTAPPLEPROC __glewTestObjectAPPLE; + +GLEW_FUN_EXPORT PFNGLBUFFERPARAMETERIAPPLEPROC __glewBufferParameteriAPPLE; +GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC __glewFlushMappedBufferRangeAPPLE; + +GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERIVAPPLEPROC __glewGetObjectParameterivAPPLE; +GLEW_FUN_EXPORT PFNGLOBJECTPURGEABLEAPPLEPROC __glewObjectPurgeableAPPLE; +GLEW_FUN_EXPORT PFNGLOBJECTUNPURGEABLEAPPLEPROC __glewObjectUnpurgeableAPPLE; + +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC __glewGetTexParameterPointervAPPLE; +GLEW_FUN_EXPORT PFNGLTEXTURERANGEAPPLEPROC __glewTextureRangeAPPLE; + +GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYAPPLEPROC __glewBindVertexArrayAPPLE; +GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSAPPLEPROC __glewDeleteVertexArraysAPPLE; +GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSAPPLEPROC __glewGenVertexArraysAPPLE; +GLEW_FUN_EXPORT PFNGLISVERTEXARRAYAPPLEPROC __glewIsVertexArrayAPPLE; + +GLEW_FUN_EXPORT PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC __glewFlushVertexArrayRangeAPPLE; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYPARAMETERIAPPLEPROC __glewVertexArrayParameteriAPPLE; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYRANGEAPPLEPROC __glewVertexArrayRangeAPPLE; + +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBAPPLEPROC __glewDisableVertexAttribAPPLE; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBAPPLEPROC __glewEnableVertexAttribAPPLE; +GLEW_FUN_EXPORT PFNGLISVERTEXATTRIBENABLEDAPPLEPROC __glewIsVertexAttribEnabledAPPLE; +GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB1DAPPLEPROC __glewMapVertexAttrib1dAPPLE; +GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB1FAPPLEPROC __glewMapVertexAttrib1fAPPLE; +GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB2DAPPLEPROC __glewMapVertexAttrib2dAPPLE; +GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB2FAPPLEPROC __glewMapVertexAttrib2fAPPLE; + +GLEW_FUN_EXPORT PFNGLCLEARDEPTHFPROC __glewClearDepthf; +GLEW_FUN_EXPORT PFNGLDEPTHRANGEFPROC __glewDepthRangef; +GLEW_FUN_EXPORT PFNGLGETSHADERPRECISIONFORMATPROC __glewGetShaderPrecisionFormat; +GLEW_FUN_EXPORT PFNGLRELEASESHADERCOMPILERPROC __glewReleaseShaderCompiler; +GLEW_FUN_EXPORT PFNGLSHADERBINARYPROC __glewShaderBinary; + +GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONINDEXEDPROC __glewBindFragDataLocationIndexed; +GLEW_FUN_EXPORT PFNGLGETFRAGDATAINDEXPROC __glewGetFragDataIndex; + +GLEW_FUN_EXPORT PFNGLCREATESYNCFROMCLEVENTARBPROC __glewCreateSyncFromCLeventARB; + +GLEW_FUN_EXPORT PFNGLCLAMPCOLORARBPROC __glewClampColorARB; + +GLEW_FUN_EXPORT PFNGLCOPYBUFFERSUBDATAPROC __glewCopyBufferSubData; + +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKARBPROC __glewDebugMessageCallbackARB; +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECONTROLARBPROC __glewDebugMessageControlARB; +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTARBPROC __glewDebugMessageInsertARB; +GLEW_FUN_EXPORT PFNGLGETDEBUGMESSAGELOGARBPROC __glewGetDebugMessageLogARB; + +GLEW_FUN_EXPORT PFNGLDRAWBUFFERSARBPROC __glewDrawBuffersARB; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEIARBPROC __glewBlendEquationSeparateiARB; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONIARBPROC __glewBlendEquationiARB; +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEIARBPROC __glewBlendFuncSeparateiARB; +GLEW_FUN_EXPORT PFNGLBLENDFUNCIARBPROC __glewBlendFunciARB; + +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSBASEVERTEXPROC __glewDrawElementsBaseVertex; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC __glewDrawElementsInstancedBaseVertex; +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC __glewDrawRangeElementsBaseVertex; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC __glewMultiDrawElementsBaseVertex; + +GLEW_FUN_EXPORT PFNGLDRAWARRAYSINDIRECTPROC __glewDrawArraysIndirect; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINDIRECTPROC __glewDrawElementsIndirect; + +GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFERPROC __glewBindFramebuffer; +GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFERPROC __glewBindRenderbuffer; +GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFERPROC __glewBlitFramebuffer; +GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSPROC __glewCheckFramebufferStatus; +GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSPROC __glewDeleteFramebuffers; +GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSPROC __glewDeleteRenderbuffers; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFERPROC __glewFramebufferRenderbuffer; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE1DPROC __glewFramebufferTexture1D; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DPROC __glewFramebufferTexture2D; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE3DPROC __glewFramebufferTexture3D; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYERPROC __glewFramebufferTextureLayer; +GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSPROC __glewGenFramebuffers; +GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSPROC __glewGenRenderbuffers; +GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPPROC __glewGenerateMipmap; +GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC __glewGetFramebufferAttachmentParameteriv; +GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVPROC __glewGetRenderbufferParameteriv; +GLEW_FUN_EXPORT PFNGLISFRAMEBUFFERPROC __glewIsFramebuffer; +GLEW_FUN_EXPORT PFNGLISRENDERBUFFERPROC __glewIsRenderbuffer; +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEPROC __glewRenderbufferStorage; +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC __glewRenderbufferStorageMultisample; + +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREARBPROC __glewFramebufferTextureARB; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREFACEARBPROC __glewFramebufferTextureFaceARB; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYERARBPROC __glewFramebufferTextureLayerARB; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIARBPROC __glewProgramParameteriARB; + +GLEW_FUN_EXPORT PFNGLGETPROGRAMBINARYPROC __glewGetProgramBinary; +GLEW_FUN_EXPORT PFNGLPROGRAMBINARYPROC __glewProgramBinary; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIPROC __glewProgramParameteri; + +GLEW_FUN_EXPORT PFNGLGETUNIFORMDVPROC __glewGetUniformdv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DEXTPROC __glewProgramUniform1dEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DVEXTPROC __glewProgramUniform1dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DEXTPROC __glewProgramUniform2dEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DVEXTPROC __glewProgramUniform2dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DEXTPROC __glewProgramUniform3dEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DVEXTPROC __glewProgramUniform3dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DEXTPROC __glewProgramUniform4dEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DVEXTPROC __glewProgramUniform4dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC __glewProgramUniformMatrix2dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC __glewProgramUniformMatrix2x3dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC __glewProgramUniformMatrix2x4dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC __glewProgramUniformMatrix3dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC __glewProgramUniformMatrix3x2dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC __glewProgramUniformMatrix3x4dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC __glewProgramUniformMatrix4dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC __glewProgramUniformMatrix4x2dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC __glewProgramUniformMatrix4x3dvEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM1DPROC __glewUniform1d; +GLEW_FUN_EXPORT PFNGLUNIFORM1DVPROC __glewUniform1dv; +GLEW_FUN_EXPORT PFNGLUNIFORM2DPROC __glewUniform2d; +GLEW_FUN_EXPORT PFNGLUNIFORM2DVPROC __glewUniform2dv; +GLEW_FUN_EXPORT PFNGLUNIFORM3DPROC __glewUniform3d; +GLEW_FUN_EXPORT PFNGLUNIFORM3DVPROC __glewUniform3dv; +GLEW_FUN_EXPORT PFNGLUNIFORM4DPROC __glewUniform4d; +GLEW_FUN_EXPORT PFNGLUNIFORM4DVPROC __glewUniform4dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2DVPROC __glewUniformMatrix2dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X3DVPROC __glewUniformMatrix2x3dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X4DVPROC __glewUniformMatrix2x4dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3DVPROC __glewUniformMatrix3dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X2DVPROC __glewUniformMatrix3x2dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X4DVPROC __glewUniformMatrix3x4dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4DVPROC __glewUniformMatrix4dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X2DVPROC __glewUniformMatrix4x2dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X3DVPROC __glewUniformMatrix4x3dv; + +GLEW_FUN_EXPORT PFNGLCOLORSUBTABLEPROC __glewColorSubTable; +GLEW_FUN_EXPORT PFNGLCOLORTABLEPROC __glewColorTable; +GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERFVPROC __glewColorTableParameterfv; +GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERIVPROC __glewColorTableParameteriv; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER1DPROC __glewConvolutionFilter1D; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER2DPROC __glewConvolutionFilter2D; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFPROC __glewConvolutionParameterf; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFVPROC __glewConvolutionParameterfv; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIPROC __glewConvolutionParameteri; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIVPROC __glewConvolutionParameteriv; +GLEW_FUN_EXPORT PFNGLCOPYCOLORSUBTABLEPROC __glewCopyColorSubTable; +GLEW_FUN_EXPORT PFNGLCOPYCOLORTABLEPROC __glewCopyColorTable; +GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER1DPROC __glewCopyConvolutionFilter1D; +GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER2DPROC __glewCopyConvolutionFilter2D; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPROC __glewGetColorTable; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVPROC __glewGetColorTableParameterfv; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVPROC __glewGetColorTableParameteriv; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONFILTERPROC __glewGetConvolutionFilter; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERFVPROC __glewGetConvolutionParameterfv; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERIVPROC __glewGetConvolutionParameteriv; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPROC __glewGetHistogram; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERFVPROC __glewGetHistogramParameterfv; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERIVPROC __glewGetHistogramParameteriv; +GLEW_FUN_EXPORT PFNGLGETMINMAXPROC __glewGetMinmax; +GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERFVPROC __glewGetMinmaxParameterfv; +GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERIVPROC __glewGetMinmaxParameteriv; +GLEW_FUN_EXPORT PFNGLGETSEPARABLEFILTERPROC __glewGetSeparableFilter; +GLEW_FUN_EXPORT PFNGLHISTOGRAMPROC __glewHistogram; +GLEW_FUN_EXPORT PFNGLMINMAXPROC __glewMinmax; +GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMPROC __glewResetHistogram; +GLEW_FUN_EXPORT PFNGLRESETMINMAXPROC __glewResetMinmax; +GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DPROC __glewSeparableFilter2D; + +GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDARBPROC __glewDrawArraysInstancedARB; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDARBPROC __glewDrawElementsInstancedARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORARBPROC __glewVertexAttribDivisorARB; + +GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEPROC __glewFlushMappedBufferRange; +GLEW_FUN_EXPORT PFNGLMAPBUFFERRANGEPROC __glewMapBufferRange; + +GLEW_FUN_EXPORT PFNGLCURRENTPALETTEMATRIXARBPROC __glewCurrentPaletteMatrixARB; +GLEW_FUN_EXPORT PFNGLMATRIXINDEXPOINTERARBPROC __glewMatrixIndexPointerARB; +GLEW_FUN_EXPORT PFNGLMATRIXINDEXUBVARBPROC __glewMatrixIndexubvARB; +GLEW_FUN_EXPORT PFNGLMATRIXINDEXUIVARBPROC __glewMatrixIndexuivARB; +GLEW_FUN_EXPORT PFNGLMATRIXINDEXUSVARBPROC __glewMatrixIndexusvARB; + +GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEARBPROC __glewSampleCoverageARB; + +GLEW_FUN_EXPORT PFNGLACTIVETEXTUREARBPROC __glewActiveTextureARB; +GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREARBPROC __glewClientActiveTextureARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DARBPROC __glewMultiTexCoord1dARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DVARBPROC __glewMultiTexCoord1dvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FARBPROC __glewMultiTexCoord1fARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FVARBPROC __glewMultiTexCoord1fvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IARBPROC __glewMultiTexCoord1iARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IVARBPROC __glewMultiTexCoord1ivARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SARBPROC __glewMultiTexCoord1sARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SVARBPROC __glewMultiTexCoord1svARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DARBPROC __glewMultiTexCoord2dARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DVARBPROC __glewMultiTexCoord2dvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FARBPROC __glewMultiTexCoord2fARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FVARBPROC __glewMultiTexCoord2fvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IARBPROC __glewMultiTexCoord2iARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IVARBPROC __glewMultiTexCoord2ivARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SARBPROC __glewMultiTexCoord2sARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SVARBPROC __glewMultiTexCoord2svARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DARBPROC __glewMultiTexCoord3dARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DVARBPROC __glewMultiTexCoord3dvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FARBPROC __glewMultiTexCoord3fARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FVARBPROC __glewMultiTexCoord3fvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IARBPROC __glewMultiTexCoord3iARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IVARBPROC __glewMultiTexCoord3ivARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SARBPROC __glewMultiTexCoord3sARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SVARBPROC __glewMultiTexCoord3svARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DARBPROC __glewMultiTexCoord4dARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DVARBPROC __glewMultiTexCoord4dvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FARBPROC __glewMultiTexCoord4fARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FVARBPROC __glewMultiTexCoord4fvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IARBPROC __glewMultiTexCoord4iARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IVARBPROC __glewMultiTexCoord4ivARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SARBPROC __glewMultiTexCoord4sARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SVARBPROC __glewMultiTexCoord4svARB; + +GLEW_FUN_EXPORT PFNGLBEGINQUERYARBPROC __glewBeginQueryARB; +GLEW_FUN_EXPORT PFNGLDELETEQUERIESARBPROC __glewDeleteQueriesARB; +GLEW_FUN_EXPORT PFNGLENDQUERYARBPROC __glewEndQueryARB; +GLEW_FUN_EXPORT PFNGLGENQUERIESARBPROC __glewGenQueriesARB; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVARBPROC __glewGetQueryObjectivARB; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVARBPROC __glewGetQueryObjectuivARB; +GLEW_FUN_EXPORT PFNGLGETQUERYIVARBPROC __glewGetQueryivARB; +GLEW_FUN_EXPORT PFNGLISQUERYARBPROC __glewIsQueryARB; + +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFARBPROC __glewPointParameterfARB; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVARBPROC __glewPointParameterfvARB; + +GLEW_FUN_EXPORT PFNGLPROVOKINGVERTEXPROC __glewProvokingVertex; + +GLEW_FUN_EXPORT PFNGLGETNCOLORTABLEARBPROC __glewGetnColorTableARB; +GLEW_FUN_EXPORT PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC __glewGetnCompressedTexImageARB; +GLEW_FUN_EXPORT PFNGLGETNCONVOLUTIONFILTERARBPROC __glewGetnConvolutionFilterARB; +GLEW_FUN_EXPORT PFNGLGETNHISTOGRAMARBPROC __glewGetnHistogramARB; +GLEW_FUN_EXPORT PFNGLGETNMAPDVARBPROC __glewGetnMapdvARB; +GLEW_FUN_EXPORT PFNGLGETNMAPFVARBPROC __glewGetnMapfvARB; +GLEW_FUN_EXPORT PFNGLGETNMAPIVARBPROC __glewGetnMapivARB; +GLEW_FUN_EXPORT PFNGLGETNMINMAXARBPROC __glewGetnMinmaxARB; +GLEW_FUN_EXPORT PFNGLGETNPIXELMAPFVARBPROC __glewGetnPixelMapfvARB; +GLEW_FUN_EXPORT PFNGLGETNPIXELMAPUIVARBPROC __glewGetnPixelMapuivARB; +GLEW_FUN_EXPORT PFNGLGETNPIXELMAPUSVARBPROC __glewGetnPixelMapusvARB; +GLEW_FUN_EXPORT PFNGLGETNPOLYGONSTIPPLEARBPROC __glewGetnPolygonStippleARB; +GLEW_FUN_EXPORT PFNGLGETNSEPARABLEFILTERARBPROC __glewGetnSeparableFilterARB; +GLEW_FUN_EXPORT PFNGLGETNTEXIMAGEARBPROC __glewGetnTexImageARB; +GLEW_FUN_EXPORT PFNGLGETNUNIFORMDVARBPROC __glewGetnUniformdvARB; +GLEW_FUN_EXPORT PFNGLGETNUNIFORMFVARBPROC __glewGetnUniformfvARB; +GLEW_FUN_EXPORT PFNGLGETNUNIFORMIVARBPROC __glewGetnUniformivARB; +GLEW_FUN_EXPORT PFNGLGETNUNIFORMUIVARBPROC __glewGetnUniformuivARB; +GLEW_FUN_EXPORT PFNGLREADNPIXELSARBPROC __glewReadnPixelsARB; + +GLEW_FUN_EXPORT PFNGLMINSAMPLESHADINGARBPROC __glewMinSampleShadingARB; + +GLEW_FUN_EXPORT PFNGLBINDSAMPLERPROC __glewBindSampler; +GLEW_FUN_EXPORT PFNGLDELETESAMPLERSPROC __glewDeleteSamplers; +GLEW_FUN_EXPORT PFNGLGENSAMPLERSPROC __glewGenSamplers; +GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIIVPROC __glewGetSamplerParameterIiv; +GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIUIVPROC __glewGetSamplerParameterIuiv; +GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERFVPROC __glewGetSamplerParameterfv; +GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIVPROC __glewGetSamplerParameteriv; +GLEW_FUN_EXPORT PFNGLISSAMPLERPROC __glewIsSampler; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIIVPROC __glewSamplerParameterIiv; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIUIVPROC __glewSamplerParameterIuiv; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERFPROC __glewSamplerParameterf; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERFVPROC __glewSamplerParameterfv; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIPROC __glewSamplerParameteri; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIVPROC __glewSamplerParameteriv; + +GLEW_FUN_EXPORT PFNGLACTIVESHADERPROGRAMPROC __glewActiveShaderProgram; +GLEW_FUN_EXPORT PFNGLBINDPROGRAMPIPELINEPROC __glewBindProgramPipeline; +GLEW_FUN_EXPORT PFNGLCREATESHADERPROGRAMVPROC __glewCreateShaderProgramv; +GLEW_FUN_EXPORT PFNGLDELETEPROGRAMPIPELINESPROC __glewDeleteProgramPipelines; +GLEW_FUN_EXPORT PFNGLGENPROGRAMPIPELINESPROC __glewGenProgramPipelines; +GLEW_FUN_EXPORT PFNGLGETPROGRAMPIPELINEINFOLOGPROC __glewGetProgramPipelineInfoLog; +GLEW_FUN_EXPORT PFNGLGETPROGRAMPIPELINEIVPROC __glewGetProgramPipelineiv; +GLEW_FUN_EXPORT PFNGLISPROGRAMPIPELINEPROC __glewIsProgramPipeline; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DPROC __glewProgramUniform1d; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DVPROC __glewProgramUniform1dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FPROC __glewProgramUniform1f; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FVPROC __glewProgramUniform1fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IPROC __glewProgramUniform1i; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IVPROC __glewProgramUniform1iv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIPROC __glewProgramUniform1ui; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIVPROC __glewProgramUniform1uiv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DPROC __glewProgramUniform2d; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DVPROC __glewProgramUniform2dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FPROC __glewProgramUniform2f; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FVPROC __glewProgramUniform2fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IPROC __glewProgramUniform2i; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IVPROC __glewProgramUniform2iv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIPROC __glewProgramUniform2ui; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIVPROC __glewProgramUniform2uiv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DPROC __glewProgramUniform3d; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DVPROC __glewProgramUniform3dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FPROC __glewProgramUniform3f; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FVPROC __glewProgramUniform3fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IPROC __glewProgramUniform3i; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IVPROC __glewProgramUniform3iv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIPROC __glewProgramUniform3ui; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIVPROC __glewProgramUniform3uiv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DPROC __glewProgramUniform4d; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DVPROC __glewProgramUniform4dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FPROC __glewProgramUniform4f; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FVPROC __glewProgramUniform4fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IPROC __glewProgramUniform4i; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IVPROC __glewProgramUniform4iv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIPROC __glewProgramUniform4ui; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIVPROC __glewProgramUniform4uiv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2DVPROC __glewProgramUniformMatrix2dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2FVPROC __glewProgramUniformMatrix2fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC __glewProgramUniformMatrix2x3dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC __glewProgramUniformMatrix2x3fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC __glewProgramUniformMatrix2x4dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC __glewProgramUniformMatrix2x4fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3DVPROC __glewProgramUniformMatrix3dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3FVPROC __glewProgramUniformMatrix3fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC __glewProgramUniformMatrix3x2dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC __glewProgramUniformMatrix3x2fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC __glewProgramUniformMatrix3x4dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC __glewProgramUniformMatrix3x4fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4DVPROC __glewProgramUniformMatrix4dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4FVPROC __glewProgramUniformMatrix4fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC __glewProgramUniformMatrix4x2dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC __glewProgramUniformMatrix4x2fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC __glewProgramUniformMatrix4x3dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC __glewProgramUniformMatrix4x3fv; +GLEW_FUN_EXPORT PFNGLUSEPROGRAMSTAGESPROC __glewUseProgramStages; +GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMPIPELINEPROC __glewValidateProgramPipeline; + +GLEW_FUN_EXPORT PFNGLATTACHOBJECTARBPROC __glewAttachObjectARB; +GLEW_FUN_EXPORT PFNGLCOMPILESHADERARBPROC __glewCompileShaderARB; +GLEW_FUN_EXPORT PFNGLCREATEPROGRAMOBJECTARBPROC __glewCreateProgramObjectARB; +GLEW_FUN_EXPORT PFNGLCREATESHADEROBJECTARBPROC __glewCreateShaderObjectARB; +GLEW_FUN_EXPORT PFNGLDELETEOBJECTARBPROC __glewDeleteObjectARB; +GLEW_FUN_EXPORT PFNGLDETACHOBJECTARBPROC __glewDetachObjectARB; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMARBPROC __glewGetActiveUniformARB; +GLEW_FUN_EXPORT PFNGLGETATTACHEDOBJECTSARBPROC __glewGetAttachedObjectsARB; +GLEW_FUN_EXPORT PFNGLGETHANDLEARBPROC __glewGetHandleARB; +GLEW_FUN_EXPORT PFNGLGETINFOLOGARBPROC __glewGetInfoLogARB; +GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERFVARBPROC __glewGetObjectParameterfvARB; +GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERIVARBPROC __glewGetObjectParameterivARB; +GLEW_FUN_EXPORT PFNGLGETSHADERSOURCEARBPROC __glewGetShaderSourceARB; +GLEW_FUN_EXPORT PFNGLGETUNIFORMLOCATIONARBPROC __glewGetUniformLocationARB; +GLEW_FUN_EXPORT PFNGLGETUNIFORMFVARBPROC __glewGetUniformfvARB; +GLEW_FUN_EXPORT PFNGLGETUNIFORMIVARBPROC __glewGetUniformivARB; +GLEW_FUN_EXPORT PFNGLLINKPROGRAMARBPROC __glewLinkProgramARB; +GLEW_FUN_EXPORT PFNGLSHADERSOURCEARBPROC __glewShaderSourceARB; +GLEW_FUN_EXPORT PFNGLUNIFORM1FARBPROC __glewUniform1fARB; +GLEW_FUN_EXPORT PFNGLUNIFORM1FVARBPROC __glewUniform1fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORM1IARBPROC __glewUniform1iARB; +GLEW_FUN_EXPORT PFNGLUNIFORM1IVARBPROC __glewUniform1ivARB; +GLEW_FUN_EXPORT PFNGLUNIFORM2FARBPROC __glewUniform2fARB; +GLEW_FUN_EXPORT PFNGLUNIFORM2FVARBPROC __glewUniform2fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORM2IARBPROC __glewUniform2iARB; +GLEW_FUN_EXPORT PFNGLUNIFORM2IVARBPROC __glewUniform2ivARB; +GLEW_FUN_EXPORT PFNGLUNIFORM3FARBPROC __glewUniform3fARB; +GLEW_FUN_EXPORT PFNGLUNIFORM3FVARBPROC __glewUniform3fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORM3IARBPROC __glewUniform3iARB; +GLEW_FUN_EXPORT PFNGLUNIFORM3IVARBPROC __glewUniform3ivARB; +GLEW_FUN_EXPORT PFNGLUNIFORM4FARBPROC __glewUniform4fARB; +GLEW_FUN_EXPORT PFNGLUNIFORM4FVARBPROC __glewUniform4fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORM4IARBPROC __glewUniform4iARB; +GLEW_FUN_EXPORT PFNGLUNIFORM4IVARBPROC __glewUniform4ivARB; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2FVARBPROC __glewUniformMatrix2fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3FVARBPROC __glewUniformMatrix3fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVARBPROC __glewUniformMatrix4fvARB; +GLEW_FUN_EXPORT PFNGLUSEPROGRAMOBJECTARBPROC __glewUseProgramObjectARB; +GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMARBPROC __glewValidateProgramARB; + +GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINENAMEPROC __glewGetActiveSubroutineName; +GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC __glewGetActiveSubroutineUniformName; +GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC __glewGetActiveSubroutineUniformiv; +GLEW_FUN_EXPORT PFNGLGETPROGRAMSTAGEIVPROC __glewGetProgramStageiv; +GLEW_FUN_EXPORT PFNGLGETSUBROUTINEINDEXPROC __glewGetSubroutineIndex; +GLEW_FUN_EXPORT PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC __glewGetSubroutineUniformLocation; +GLEW_FUN_EXPORT PFNGLGETUNIFORMSUBROUTINEUIVPROC __glewGetUniformSubroutineuiv; +GLEW_FUN_EXPORT PFNGLUNIFORMSUBROUTINESUIVPROC __glewUniformSubroutinesuiv; + +GLEW_FUN_EXPORT PFNGLCOMPILESHADERINCLUDEARBPROC __glewCompileShaderIncludeARB; +GLEW_FUN_EXPORT PFNGLDELETENAMEDSTRINGARBPROC __glewDeleteNamedStringARB; +GLEW_FUN_EXPORT PFNGLGETNAMEDSTRINGARBPROC __glewGetNamedStringARB; +GLEW_FUN_EXPORT PFNGLGETNAMEDSTRINGIVARBPROC __glewGetNamedStringivARB; +GLEW_FUN_EXPORT PFNGLISNAMEDSTRINGARBPROC __glewIsNamedStringARB; +GLEW_FUN_EXPORT PFNGLNAMEDSTRINGARBPROC __glewNamedStringARB; + +GLEW_FUN_EXPORT PFNGLCLIENTWAITSYNCPROC __glewClientWaitSync; +GLEW_FUN_EXPORT PFNGLDELETESYNCPROC __glewDeleteSync; +GLEW_FUN_EXPORT PFNGLFENCESYNCPROC __glewFenceSync; +GLEW_FUN_EXPORT PFNGLGETINTEGER64VPROC __glewGetInteger64v; +GLEW_FUN_EXPORT PFNGLGETSYNCIVPROC __glewGetSynciv; +GLEW_FUN_EXPORT PFNGLISSYNCPROC __glewIsSync; +GLEW_FUN_EXPORT PFNGLWAITSYNCPROC __glewWaitSync; + +GLEW_FUN_EXPORT PFNGLPATCHPARAMETERFVPROC __glewPatchParameterfv; +GLEW_FUN_EXPORT PFNGLPATCHPARAMETERIPROC __glewPatchParameteri; + +GLEW_FUN_EXPORT PFNGLTEXBUFFERARBPROC __glewTexBufferARB; + +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DARBPROC __glewCompressedTexImage1DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DARBPROC __glewCompressedTexImage2DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DARBPROC __glewCompressedTexImage3DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC __glewCompressedTexSubImage1DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC __glewCompressedTexSubImage2DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC __glewCompressedTexSubImage3DARB; +GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXIMAGEARBPROC __glewGetCompressedTexImageARB; + +GLEW_FUN_EXPORT PFNGLGETMULTISAMPLEFVPROC __glewGetMultisamplefv; +GLEW_FUN_EXPORT PFNGLSAMPLEMASKIPROC __glewSampleMaski; +GLEW_FUN_EXPORT PFNGLTEXIMAGE2DMULTISAMPLEPROC __glewTexImage2DMultisample; +GLEW_FUN_EXPORT PFNGLTEXIMAGE3DMULTISAMPLEPROC __glewTexImage3DMultisample; + +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VPROC __glewGetQueryObjecti64v; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VPROC __glewGetQueryObjectui64v; +GLEW_FUN_EXPORT PFNGLQUERYCOUNTERPROC __glewQueryCounter; + +GLEW_FUN_EXPORT PFNGLBINDTRANSFORMFEEDBACKPROC __glewBindTransformFeedback; +GLEW_FUN_EXPORT PFNGLDELETETRANSFORMFEEDBACKSPROC __glewDeleteTransformFeedbacks; +GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKPROC __glewDrawTransformFeedback; +GLEW_FUN_EXPORT PFNGLGENTRANSFORMFEEDBACKSPROC __glewGenTransformFeedbacks; +GLEW_FUN_EXPORT PFNGLISTRANSFORMFEEDBACKPROC __glewIsTransformFeedback; +GLEW_FUN_EXPORT PFNGLPAUSETRANSFORMFEEDBACKPROC __glewPauseTransformFeedback; +GLEW_FUN_EXPORT PFNGLRESUMETRANSFORMFEEDBACKPROC __glewResumeTransformFeedback; + +GLEW_FUN_EXPORT PFNGLBEGINQUERYINDEXEDPROC __glewBeginQueryIndexed; +GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC __glewDrawTransformFeedbackStream; +GLEW_FUN_EXPORT PFNGLENDQUERYINDEXEDPROC __glewEndQueryIndexed; +GLEW_FUN_EXPORT PFNGLGETQUERYINDEXEDIVPROC __glewGetQueryIndexediv; + +GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXDARBPROC __glewLoadTransposeMatrixdARB; +GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXFARBPROC __glewLoadTransposeMatrixfARB; +GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXDARBPROC __glewMultTransposeMatrixdARB; +GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXFARBPROC __glewMultTransposeMatrixfARB; + +GLEW_FUN_EXPORT PFNGLBINDBUFFERBASEPROC __glewBindBufferBase; +GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGEPROC __glewBindBufferRange; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC __glewGetActiveUniformBlockName; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMBLOCKIVPROC __glewGetActiveUniformBlockiv; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMNAMEPROC __glewGetActiveUniformName; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMSIVPROC __glewGetActiveUniformsiv; +GLEW_FUN_EXPORT PFNGLGETINTEGERI_VPROC __glewGetIntegeri_v; +GLEW_FUN_EXPORT PFNGLGETUNIFORMBLOCKINDEXPROC __glewGetUniformBlockIndex; +GLEW_FUN_EXPORT PFNGLGETUNIFORMINDICESPROC __glewGetUniformIndices; +GLEW_FUN_EXPORT PFNGLUNIFORMBLOCKBINDINGPROC __glewUniformBlockBinding; + +GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYPROC __glewBindVertexArray; +GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSPROC __glewDeleteVertexArrays; +GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSPROC __glewGenVertexArrays; +GLEW_FUN_EXPORT PFNGLISVERTEXARRAYPROC __glewIsVertexArray; + +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLDVPROC __glewGetVertexAttribLdv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DPROC __glewVertexAttribL1d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DVPROC __glewVertexAttribL1dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DPROC __glewVertexAttribL2d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DVPROC __glewVertexAttribL2dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DPROC __glewVertexAttribL3d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DVPROC __glewVertexAttribL3dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DPROC __glewVertexAttribL4d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DVPROC __glewVertexAttribL4dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLPOINTERPROC __glewVertexAttribLPointer; + +GLEW_FUN_EXPORT PFNGLVERTEXBLENDARBPROC __glewVertexBlendARB; +GLEW_FUN_EXPORT PFNGLWEIGHTPOINTERARBPROC __glewWeightPointerARB; +GLEW_FUN_EXPORT PFNGLWEIGHTBVARBPROC __glewWeightbvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTDVARBPROC __glewWeightdvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTFVARBPROC __glewWeightfvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTIVARBPROC __glewWeightivARB; +GLEW_FUN_EXPORT PFNGLWEIGHTSVARBPROC __glewWeightsvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTUBVARBPROC __glewWeightubvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTUIVARBPROC __glewWeightuivARB; +GLEW_FUN_EXPORT PFNGLWEIGHTUSVARBPROC __glewWeightusvARB; + +GLEW_FUN_EXPORT PFNGLBINDBUFFERARBPROC __glewBindBufferARB; +GLEW_FUN_EXPORT PFNGLBUFFERDATAARBPROC __glewBufferDataARB; +GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAARBPROC __glewBufferSubDataARB; +GLEW_FUN_EXPORT PFNGLDELETEBUFFERSARBPROC __glewDeleteBuffersARB; +GLEW_FUN_EXPORT PFNGLGENBUFFERSARBPROC __glewGenBuffersARB; +GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVARBPROC __glewGetBufferParameterivARB; +GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVARBPROC __glewGetBufferPointervARB; +GLEW_FUN_EXPORT PFNGLGETBUFFERSUBDATAARBPROC __glewGetBufferSubDataARB; +GLEW_FUN_EXPORT PFNGLISBUFFERARBPROC __glewIsBufferARB; +GLEW_FUN_EXPORT PFNGLMAPBUFFERARBPROC __glewMapBufferARB; +GLEW_FUN_EXPORT PFNGLUNMAPBUFFERARBPROC __glewUnmapBufferARB; + +GLEW_FUN_EXPORT PFNGLBINDPROGRAMARBPROC __glewBindProgramARB; +GLEW_FUN_EXPORT PFNGLDELETEPROGRAMSARBPROC __glewDeleteProgramsARB; +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBARRAYARBPROC __glewDisableVertexAttribArrayARB; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBARRAYARBPROC __glewEnableVertexAttribArrayARB; +GLEW_FUN_EXPORT PFNGLGENPROGRAMSARBPROC __glewGenProgramsARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMENVPARAMETERDVARBPROC __glewGetProgramEnvParameterdvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMENVPARAMETERFVARBPROC __glewGetProgramEnvParameterfvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC __glewGetProgramLocalParameterdvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC __glewGetProgramLocalParameterfvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMSTRINGARBPROC __glewGetProgramStringARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMIVARBPROC __glewGetProgramivARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVARBPROC __glewGetVertexAttribPointervARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVARBPROC __glewGetVertexAttribdvARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVARBPROC __glewGetVertexAttribfvARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVARBPROC __glewGetVertexAttribivARB; +GLEW_FUN_EXPORT PFNGLISPROGRAMARBPROC __glewIsProgramARB; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4DARBPROC __glewProgramEnvParameter4dARB; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4DVARBPROC __glewProgramEnvParameter4dvARB; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4FARBPROC __glewProgramEnvParameter4fARB; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4FVARBPROC __glewProgramEnvParameter4fvARB; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4DARBPROC __glewProgramLocalParameter4dARB; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4DVARBPROC __glewProgramLocalParameter4dvARB; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4FARBPROC __glewProgramLocalParameter4fARB; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4FVARBPROC __glewProgramLocalParameter4fvARB; +GLEW_FUN_EXPORT PFNGLPROGRAMSTRINGARBPROC __glewProgramStringARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DARBPROC __glewVertexAttrib1dARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVARBPROC __glewVertexAttrib1dvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FARBPROC __glewVertexAttrib1fARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVARBPROC __glewVertexAttrib1fvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SARBPROC __glewVertexAttrib1sARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVARBPROC __glewVertexAttrib1svARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DARBPROC __glewVertexAttrib2dARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVARBPROC __glewVertexAttrib2dvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FARBPROC __glewVertexAttrib2fARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVARBPROC __glewVertexAttrib2fvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SARBPROC __glewVertexAttrib2sARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVARBPROC __glewVertexAttrib2svARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DARBPROC __glewVertexAttrib3dARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVARBPROC __glewVertexAttrib3dvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FARBPROC __glewVertexAttrib3fARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVARBPROC __glewVertexAttrib3fvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SARBPROC __glewVertexAttrib3sARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVARBPROC __glewVertexAttrib3svARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NBVARBPROC __glewVertexAttrib4NbvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NIVARBPROC __glewVertexAttrib4NivARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NSVARBPROC __glewVertexAttrib4NsvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBARBPROC __glewVertexAttrib4NubARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBVARBPROC __glewVertexAttrib4NubvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUIVARBPROC __glewVertexAttrib4NuivARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUSVARBPROC __glewVertexAttrib4NusvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4BVARBPROC __glewVertexAttrib4bvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DARBPROC __glewVertexAttrib4dARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVARBPROC __glewVertexAttrib4dvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FARBPROC __glewVertexAttrib4fARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVARBPROC __glewVertexAttrib4fvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4IVARBPROC __glewVertexAttrib4ivARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SARBPROC __glewVertexAttrib4sARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVARBPROC __glewVertexAttrib4svARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVARBPROC __glewVertexAttrib4ubvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UIVARBPROC __glewVertexAttrib4uivARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4USVARBPROC __glewVertexAttrib4usvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERARBPROC __glewVertexAttribPointerARB; + +GLEW_FUN_EXPORT PFNGLBINDATTRIBLOCATIONARBPROC __glewBindAttribLocationARB; +GLEW_FUN_EXPORT PFNGLGETACTIVEATTRIBARBPROC __glewGetActiveAttribARB; +GLEW_FUN_EXPORT PFNGLGETATTRIBLOCATIONARBPROC __glewGetAttribLocationARB; + +GLEW_FUN_EXPORT PFNGLCOLORP3UIPROC __glewColorP3ui; +GLEW_FUN_EXPORT PFNGLCOLORP3UIVPROC __glewColorP3uiv; +GLEW_FUN_EXPORT PFNGLCOLORP4UIPROC __glewColorP4ui; +GLEW_FUN_EXPORT PFNGLCOLORP4UIVPROC __glewColorP4uiv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP1UIPROC __glewMultiTexCoordP1ui; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP1UIVPROC __glewMultiTexCoordP1uiv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP2UIPROC __glewMultiTexCoordP2ui; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP2UIVPROC __glewMultiTexCoordP2uiv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP3UIPROC __glewMultiTexCoordP3ui; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP3UIVPROC __glewMultiTexCoordP3uiv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP4UIPROC __glewMultiTexCoordP4ui; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP4UIVPROC __glewMultiTexCoordP4uiv; +GLEW_FUN_EXPORT PFNGLNORMALP3UIPROC __glewNormalP3ui; +GLEW_FUN_EXPORT PFNGLNORMALP3UIVPROC __glewNormalP3uiv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORP3UIPROC __glewSecondaryColorP3ui; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORP3UIVPROC __glewSecondaryColorP3uiv; +GLEW_FUN_EXPORT PFNGLTEXCOORDP1UIPROC __glewTexCoordP1ui; +GLEW_FUN_EXPORT PFNGLTEXCOORDP1UIVPROC __glewTexCoordP1uiv; +GLEW_FUN_EXPORT PFNGLTEXCOORDP2UIPROC __glewTexCoordP2ui; +GLEW_FUN_EXPORT PFNGLTEXCOORDP2UIVPROC __glewTexCoordP2uiv; +GLEW_FUN_EXPORT PFNGLTEXCOORDP3UIPROC __glewTexCoordP3ui; +GLEW_FUN_EXPORT PFNGLTEXCOORDP3UIVPROC __glewTexCoordP3uiv; +GLEW_FUN_EXPORT PFNGLTEXCOORDP4UIPROC __glewTexCoordP4ui; +GLEW_FUN_EXPORT PFNGLTEXCOORDP4UIVPROC __glewTexCoordP4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP1UIPROC __glewVertexAttribP1ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP1UIVPROC __glewVertexAttribP1uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP2UIPROC __glewVertexAttribP2ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP2UIVPROC __glewVertexAttribP2uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP3UIPROC __glewVertexAttribP3ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP3UIVPROC __glewVertexAttribP3uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP4UIPROC __glewVertexAttribP4ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP4UIVPROC __glewVertexAttribP4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXP2UIPROC __glewVertexP2ui; +GLEW_FUN_EXPORT PFNGLVERTEXP2UIVPROC __glewVertexP2uiv; +GLEW_FUN_EXPORT PFNGLVERTEXP3UIPROC __glewVertexP3ui; +GLEW_FUN_EXPORT PFNGLVERTEXP3UIVPROC __glewVertexP3uiv; +GLEW_FUN_EXPORT PFNGLVERTEXP4UIPROC __glewVertexP4ui; +GLEW_FUN_EXPORT PFNGLVERTEXP4UIVPROC __glewVertexP4uiv; + +GLEW_FUN_EXPORT PFNGLDEPTHRANGEARRAYVPROC __glewDepthRangeArrayv; +GLEW_FUN_EXPORT PFNGLDEPTHRANGEINDEXEDPROC __glewDepthRangeIndexed; +GLEW_FUN_EXPORT PFNGLGETDOUBLEI_VPROC __glewGetDoublei_v; +GLEW_FUN_EXPORT PFNGLGETFLOATI_VPROC __glewGetFloati_v; +GLEW_FUN_EXPORT PFNGLSCISSORARRAYVPROC __glewScissorArrayv; +GLEW_FUN_EXPORT PFNGLSCISSORINDEXEDPROC __glewScissorIndexed; +GLEW_FUN_EXPORT PFNGLSCISSORINDEXEDVPROC __glewScissorIndexedv; +GLEW_FUN_EXPORT PFNGLVIEWPORTARRAYVPROC __glewViewportArrayv; +GLEW_FUN_EXPORT PFNGLVIEWPORTINDEXEDFPROC __glewViewportIndexedf; +GLEW_FUN_EXPORT PFNGLVIEWPORTINDEXEDFVPROC __glewViewportIndexedfv; + +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DARBPROC __glewWindowPos2dARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVARBPROC __glewWindowPos2dvARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FARBPROC __glewWindowPos2fARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVARBPROC __glewWindowPos2fvARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IARBPROC __glewWindowPos2iARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVARBPROC __glewWindowPos2ivARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SARBPROC __glewWindowPos2sARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVARBPROC __glewWindowPos2svARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DARBPROC __glewWindowPos3dARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVARBPROC __glewWindowPos3dvARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FARBPROC __glewWindowPos3fARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVARBPROC __glewWindowPos3fvARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IARBPROC __glewWindowPos3iARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVARBPROC __glewWindowPos3ivARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SARBPROC __glewWindowPos3sARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVARBPROC __glewWindowPos3svARB; + +GLEW_FUN_EXPORT PFNGLDRAWBUFFERSATIPROC __glewDrawBuffersATI; + +GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYATIPROC __glewDrawElementArrayATI; +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYATIPROC __glewDrawRangeElementArrayATI; +GLEW_FUN_EXPORT PFNGLELEMENTPOINTERATIPROC __glewElementPointerATI; + +GLEW_FUN_EXPORT PFNGLGETTEXBUMPPARAMETERFVATIPROC __glewGetTexBumpParameterfvATI; +GLEW_FUN_EXPORT PFNGLGETTEXBUMPPARAMETERIVATIPROC __glewGetTexBumpParameterivATI; +GLEW_FUN_EXPORT PFNGLTEXBUMPPARAMETERFVATIPROC __glewTexBumpParameterfvATI; +GLEW_FUN_EXPORT PFNGLTEXBUMPPARAMETERIVATIPROC __glewTexBumpParameterivATI; + +GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP1ATIPROC __glewAlphaFragmentOp1ATI; +GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP2ATIPROC __glewAlphaFragmentOp2ATI; +GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP3ATIPROC __glewAlphaFragmentOp3ATI; +GLEW_FUN_EXPORT PFNGLBEGINFRAGMENTSHADERATIPROC __glewBeginFragmentShaderATI; +GLEW_FUN_EXPORT PFNGLBINDFRAGMENTSHADERATIPROC __glewBindFragmentShaderATI; +GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP1ATIPROC __glewColorFragmentOp1ATI; +GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP2ATIPROC __glewColorFragmentOp2ATI; +GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP3ATIPROC __glewColorFragmentOp3ATI; +GLEW_FUN_EXPORT PFNGLDELETEFRAGMENTSHADERATIPROC __glewDeleteFragmentShaderATI; +GLEW_FUN_EXPORT PFNGLENDFRAGMENTSHADERATIPROC __glewEndFragmentShaderATI; +GLEW_FUN_EXPORT PFNGLGENFRAGMENTSHADERSATIPROC __glewGenFragmentShadersATI; +GLEW_FUN_EXPORT PFNGLPASSTEXCOORDATIPROC __glewPassTexCoordATI; +GLEW_FUN_EXPORT PFNGLSAMPLEMAPATIPROC __glewSampleMapATI; +GLEW_FUN_EXPORT PFNGLSETFRAGMENTSHADERCONSTANTATIPROC __glewSetFragmentShaderConstantATI; + +GLEW_FUN_EXPORT PFNGLMAPOBJECTBUFFERATIPROC __glewMapObjectBufferATI; +GLEW_FUN_EXPORT PFNGLUNMAPOBJECTBUFFERATIPROC __glewUnmapObjectBufferATI; + +GLEW_FUN_EXPORT PFNGLPNTRIANGLESFATIPROC __glewPNTrianglesfATI; +GLEW_FUN_EXPORT PFNGLPNTRIANGLESIATIPROC __glewPNTrianglesiATI; + +GLEW_FUN_EXPORT PFNGLSTENCILFUNCSEPARATEATIPROC __glewStencilFuncSeparateATI; +GLEW_FUN_EXPORT PFNGLSTENCILOPSEPARATEATIPROC __glewStencilOpSeparateATI; + +GLEW_FUN_EXPORT PFNGLARRAYOBJECTATIPROC __glewArrayObjectATI; +GLEW_FUN_EXPORT PFNGLFREEOBJECTBUFFERATIPROC __glewFreeObjectBufferATI; +GLEW_FUN_EXPORT PFNGLGETARRAYOBJECTFVATIPROC __glewGetArrayObjectfvATI; +GLEW_FUN_EXPORT PFNGLGETARRAYOBJECTIVATIPROC __glewGetArrayObjectivATI; +GLEW_FUN_EXPORT PFNGLGETOBJECTBUFFERFVATIPROC __glewGetObjectBufferfvATI; +GLEW_FUN_EXPORT PFNGLGETOBJECTBUFFERIVATIPROC __glewGetObjectBufferivATI; +GLEW_FUN_EXPORT PFNGLGETVARIANTARRAYOBJECTFVATIPROC __glewGetVariantArrayObjectfvATI; +GLEW_FUN_EXPORT PFNGLGETVARIANTARRAYOBJECTIVATIPROC __glewGetVariantArrayObjectivATI; +GLEW_FUN_EXPORT PFNGLISOBJECTBUFFERATIPROC __glewIsObjectBufferATI; +GLEW_FUN_EXPORT PFNGLNEWOBJECTBUFFERATIPROC __glewNewObjectBufferATI; +GLEW_FUN_EXPORT PFNGLUPDATEOBJECTBUFFERATIPROC __glewUpdateObjectBufferATI; +GLEW_FUN_EXPORT PFNGLVARIANTARRAYOBJECTATIPROC __glewVariantArrayObjectATI; + +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC __glewGetVertexAttribArrayObjectfvATI; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC __glewGetVertexAttribArrayObjectivATI; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBARRAYOBJECTATIPROC __glewVertexAttribArrayObjectATI; + +GLEW_FUN_EXPORT PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC __glewClientActiveVertexStreamATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3BATIPROC __glewNormalStream3bATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3BVATIPROC __glewNormalStream3bvATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3DATIPROC __glewNormalStream3dATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3DVATIPROC __glewNormalStream3dvATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3FATIPROC __glewNormalStream3fATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3FVATIPROC __glewNormalStream3fvATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3IATIPROC __glewNormalStream3iATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3IVATIPROC __glewNormalStream3ivATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SATIPROC __glewNormalStream3sATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SVATIPROC __glewNormalStream3svATI; +GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVFATIPROC __glewVertexBlendEnvfATI; +GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVIATIPROC __glewVertexBlendEnviATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DATIPROC __glewVertexStream2dATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DVATIPROC __glewVertexStream2dvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FATIPROC __glewVertexStream2fATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FVATIPROC __glewVertexStream2fvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2IATIPROC __glewVertexStream2iATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2IVATIPROC __glewVertexStream2ivATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2SATIPROC __glewVertexStream2sATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2SVATIPROC __glewVertexStream2svATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3DATIPROC __glewVertexStream3dATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3DVATIPROC __glewVertexStream3dvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3FATIPROC __glewVertexStream3fATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3FVATIPROC __glewVertexStream3fvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3IATIPROC __glewVertexStream3iATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3IVATIPROC __glewVertexStream3ivATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3SATIPROC __glewVertexStream3sATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3SVATIPROC __glewVertexStream3svATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4DATIPROC __glewVertexStream4dATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4DVATIPROC __glewVertexStream4dvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4FATIPROC __glewVertexStream4fATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4FVATIPROC __glewVertexStream4fvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4IATIPROC __glewVertexStream4iATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4IVATIPROC __glewVertexStream4ivATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4SATIPROC __glewVertexStream4sATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4SVATIPROC __glewVertexStream4svATI; + +GLEW_FUN_EXPORT PFNGLGETUNIFORMBUFFERSIZEEXTPROC __glewGetUniformBufferSizeEXT; +GLEW_FUN_EXPORT PFNGLGETUNIFORMOFFSETEXTPROC __glewGetUniformOffsetEXT; +GLEW_FUN_EXPORT PFNGLUNIFORMBUFFEREXTPROC __glewUniformBufferEXT; + +GLEW_FUN_EXPORT PFNGLBLENDCOLOREXTPROC __glewBlendColorEXT; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEEXTPROC __glewBlendEquationSeparateEXT; + +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEEXTPROC __glewBlendFuncSeparateEXT; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONEXTPROC __glewBlendEquationEXT; + +GLEW_FUN_EXPORT PFNGLCOLORSUBTABLEEXTPROC __glewColorSubTableEXT; +GLEW_FUN_EXPORT PFNGLCOPYCOLORSUBTABLEEXTPROC __glewCopyColorSubTableEXT; + +GLEW_FUN_EXPORT PFNGLLOCKARRAYSEXTPROC __glewLockArraysEXT; +GLEW_FUN_EXPORT PFNGLUNLOCKARRAYSEXTPROC __glewUnlockArraysEXT; + +GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER1DEXTPROC __glewConvolutionFilter1DEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER2DEXTPROC __glewConvolutionFilter2DEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFEXTPROC __glewConvolutionParameterfEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFVEXTPROC __glewConvolutionParameterfvEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIEXTPROC __glewConvolutionParameteriEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIVEXTPROC __glewConvolutionParameterivEXT; +GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC __glewCopyConvolutionFilter1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC __glewCopyConvolutionFilter2DEXT; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONFILTEREXTPROC __glewGetConvolutionFilterEXT; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC __glewGetConvolutionParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC __glewGetConvolutionParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETSEPARABLEFILTEREXTPROC __glewGetSeparableFilterEXT; +GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DEXTPROC __glewSeparableFilter2DEXT; + +GLEW_FUN_EXPORT PFNGLBINORMALPOINTEREXTPROC __glewBinormalPointerEXT; +GLEW_FUN_EXPORT PFNGLTANGENTPOINTEREXTPROC __glewTangentPointerEXT; + +GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE1DEXTPROC __glewCopyTexImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE2DEXTPROC __glewCopyTexImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE1DEXTPROC __glewCopyTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE2DEXTPROC __glewCopyTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT; + +GLEW_FUN_EXPORT PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT; +GLEW_FUN_EXPORT PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT; + +GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSEXTPROC __glewDepthBoundsEXT; + +GLEW_FUN_EXPORT PFNGLBINDMULTITEXTUREEXTPROC __glewBindMultiTextureEXT; +GLEW_FUN_EXPORT PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC __glewCheckNamedFramebufferStatusEXT; +GLEW_FUN_EXPORT PFNGLCLIENTATTRIBDEFAULTEXTPROC __glewClientAttribDefaultEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC __glewCompressedMultiTexImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC __glewCompressedMultiTexImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC __glewCompressedMultiTexImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC __glewCompressedMultiTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC __glewCompressedMultiTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC __glewCompressedMultiTexSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC __glewCompressedTextureImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC __glewCompressedTextureImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC __glewCompressedTextureImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC __glewCompressedTextureSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC __glewCompressedTextureSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC __glewCompressedTextureSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXIMAGE1DEXTPROC __glewCopyMultiTexImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXIMAGE2DEXTPROC __glewCopyMultiTexImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC __glewCopyMultiTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC __glewCopyMultiTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC __glewCopyMultiTexSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTUREIMAGE1DEXTPROC __glewCopyTextureImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTUREIMAGE2DEXTPROC __glewCopyTextureImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC __glewCopyTextureSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC __glewCopyTextureSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC __glewCopyTextureSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC __glewDisableClientStateIndexedEXT; +GLEW_FUN_EXPORT PFNGLDISABLECLIENTSTATEIEXTPROC __glewDisableClientStateiEXT; +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC __glewDisableVertexArrayAttribEXT; +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXARRAYEXTPROC __glewDisableVertexArrayEXT; +GLEW_FUN_EXPORT PFNGLENABLECLIENTSTATEINDEXEDEXTPROC __glewEnableClientStateIndexedEXT; +GLEW_FUN_EXPORT PFNGLENABLECLIENTSTATEIEXTPROC __glewEnableClientStateiEXT; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXARRAYATTRIBEXTPROC __glewEnableVertexArrayAttribEXT; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXARRAYEXTPROC __glewEnableVertexArrayEXT; +GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC __glewFlushMappedNamedBufferRangeEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC __glewFramebufferDrawBufferEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC __glewFramebufferDrawBuffersEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERREADBUFFEREXTPROC __glewFramebufferReadBufferEXT; +GLEW_FUN_EXPORT PFNGLGENERATEMULTITEXMIPMAPEXTPROC __glewGenerateMultiTexMipmapEXT; +GLEW_FUN_EXPORT PFNGLGENERATETEXTUREMIPMAPEXTPROC __glewGenerateTextureMipmapEXT; +GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC __glewGetCompressedMultiTexImageEXT; +GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC __glewGetCompressedTextureImageEXT; +GLEW_FUN_EXPORT PFNGLGETDOUBLEINDEXEDVEXTPROC __glewGetDoubleIndexedvEXT; +GLEW_FUN_EXPORT PFNGLGETDOUBLEI_VEXTPROC __glewGetDoublei_vEXT; +GLEW_FUN_EXPORT PFNGLGETFLOATINDEXEDVEXTPROC __glewGetFloatIndexedvEXT; +GLEW_FUN_EXPORT PFNGLGETFLOATI_VEXTPROC __glewGetFloati_vEXT; +GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC __glewGetFramebufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXENVFVEXTPROC __glewGetMultiTexEnvfvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXENVIVEXTPROC __glewGetMultiTexEnvivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXGENDVEXTPROC __glewGetMultiTexGendvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXGENFVEXTPROC __glewGetMultiTexGenfvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXGENIVEXTPROC __glewGetMultiTexGenivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXIMAGEEXTPROC __glewGetMultiTexImageEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC __glewGetMultiTexLevelParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC __glewGetMultiTexLevelParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIIVEXTPROC __glewGetMultiTexParameterIivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIUIVEXTPROC __glewGetMultiTexParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERFVEXTPROC __glewGetMultiTexParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIVEXTPROC __glewGetMultiTexParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC __glewGetNamedBufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPOINTERVEXTPROC __glewGetNamedBufferPointervEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERSUBDATAEXTPROC __glewGetNamedBufferSubDataEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetNamedFramebufferAttachmentParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC __glewGetNamedProgramLocalParameterIivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC __glewGetNamedProgramLocalParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC __glewGetNamedProgramLocalParameterdvEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC __glewGetNamedProgramLocalParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMSTRINGEXTPROC __glewGetNamedProgramStringEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMIVEXTPROC __glewGetNamedProgramivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC __glewGetNamedRenderbufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETPOINTERINDEXEDVEXTPROC __glewGetPointerIndexedvEXT; +GLEW_FUN_EXPORT PFNGLGETPOINTERI_VEXTPROC __glewGetPointeri_vEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREIMAGEEXTPROC __glewGetTextureImageEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC __glewGetTextureLevelParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC __glewGetTextureLevelParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIIVEXTPROC __glewGetTextureParameterIivEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIUIVEXTPROC __glewGetTextureParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERFVEXTPROC __glewGetTextureParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIVEXTPROC __glewGetTextureParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC __glewGetVertexArrayIntegeri_vEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYINTEGERVEXTPROC __glewGetVertexArrayIntegervEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC __glewGetVertexArrayPointeri_vEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYPOINTERVEXTPROC __glewGetVertexArrayPointervEXT; +GLEW_FUN_EXPORT PFNGLMAPNAMEDBUFFEREXTPROC __glewMapNamedBufferEXT; +GLEW_FUN_EXPORT PFNGLMAPNAMEDBUFFERRANGEEXTPROC __glewMapNamedBufferRangeEXT; +GLEW_FUN_EXPORT PFNGLMATRIXFRUSTUMEXTPROC __glewMatrixFrustumEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADIDENTITYEXTPROC __glewMatrixLoadIdentityEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADTRANSPOSEDEXTPROC __glewMatrixLoadTransposedEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADTRANSPOSEFEXTPROC __glewMatrixLoadTransposefEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADDEXTPROC __glewMatrixLoaddEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADFEXTPROC __glewMatrixLoadfEXT; +GLEW_FUN_EXPORT PFNGLMATRIXMULTTRANSPOSEDEXTPROC __glewMatrixMultTransposedEXT; +GLEW_FUN_EXPORT PFNGLMATRIXMULTTRANSPOSEFEXTPROC __glewMatrixMultTransposefEXT; +GLEW_FUN_EXPORT PFNGLMATRIXMULTDEXTPROC __glewMatrixMultdEXT; +GLEW_FUN_EXPORT PFNGLMATRIXMULTFEXTPROC __glewMatrixMultfEXT; +GLEW_FUN_EXPORT PFNGLMATRIXORTHOEXTPROC __glewMatrixOrthoEXT; +GLEW_FUN_EXPORT PFNGLMATRIXPOPEXTPROC __glewMatrixPopEXT; +GLEW_FUN_EXPORT PFNGLMATRIXPUSHEXTPROC __glewMatrixPushEXT; +GLEW_FUN_EXPORT PFNGLMATRIXROTATEDEXTPROC __glewMatrixRotatedEXT; +GLEW_FUN_EXPORT PFNGLMATRIXROTATEFEXTPROC __glewMatrixRotatefEXT; +GLEW_FUN_EXPORT PFNGLMATRIXSCALEDEXTPROC __glewMatrixScaledEXT; +GLEW_FUN_EXPORT PFNGLMATRIXSCALEFEXTPROC __glewMatrixScalefEXT; +GLEW_FUN_EXPORT PFNGLMATRIXTRANSLATEDEXTPROC __glewMatrixTranslatedEXT; +GLEW_FUN_EXPORT PFNGLMATRIXTRANSLATEFEXTPROC __glewMatrixTranslatefEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXBUFFEREXTPROC __glewMultiTexBufferEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDPOINTEREXTPROC __glewMultiTexCoordPointerEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXENVFEXTPROC __glewMultiTexEnvfEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXENVFVEXTPROC __glewMultiTexEnvfvEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXENVIEXTPROC __glewMultiTexEnviEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXENVIVEXTPROC __glewMultiTexEnvivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENDEXTPROC __glewMultiTexGendEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENDVEXTPROC __glewMultiTexGendvEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENFEXTPROC __glewMultiTexGenfEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENFVEXTPROC __glewMultiTexGenfvEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENIEXTPROC __glewMultiTexGeniEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENIVEXTPROC __glewMultiTexGenivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE1DEXTPROC __glewMultiTexImage1DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE2DEXTPROC __glewMultiTexImage2DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE3DEXTPROC __glewMultiTexImage3DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIIVEXTPROC __glewMultiTexParameterIivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIUIVEXTPROC __glewMultiTexParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERFEXTPROC __glewMultiTexParameterfEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERFVEXTPROC __glewMultiTexParameterfvEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIEXTPROC __glewMultiTexParameteriEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIVEXTPROC __glewMultiTexParameterivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXRENDERBUFFEREXTPROC __glewMultiTexRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE1DEXTPROC __glewMultiTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE2DEXTPROC __glewMultiTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE3DEXTPROC __glewMultiTexSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLNAMEDBUFFERDATAEXTPROC __glewNamedBufferDataEXT; +GLEW_FUN_EXPORT PFNGLNAMEDBUFFERSUBDATAEXTPROC __glewNamedBufferSubDataEXT; +GLEW_FUN_EXPORT PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC __glewNamedCopyBufferSubDataEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC __glewNamedFramebufferRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC __glewNamedFramebufferTexture1DEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC __glewNamedFramebufferTexture2DEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC __glewNamedFramebufferTexture3DEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC __glewNamedFramebufferTextureEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC __glewNamedFramebufferTextureFaceEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC __glewNamedFramebufferTextureLayerEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC __glewNamedProgramLocalParameter4dEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC __glewNamedProgramLocalParameter4dvEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC __glewNamedProgramLocalParameter4fEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC __glewNamedProgramLocalParameter4fvEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC __glewNamedProgramLocalParameterI4iEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC __glewNamedProgramLocalParameterI4ivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC __glewNamedProgramLocalParameterI4uiEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC __glewNamedProgramLocalParameterI4uivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC __glewNamedProgramLocalParameters4fvEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC __glewNamedProgramLocalParametersI4ivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC __glewNamedProgramLocalParametersI4uivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMSTRINGEXTPROC __glewNamedProgramStringEXT; +GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC __glewNamedRenderbufferStorageEXT; +GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC __glewNamedRenderbufferStorageMultisampleCoverageEXT; +GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewNamedRenderbufferStorageMultisampleEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FEXTPROC __glewProgramUniform1fEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FVEXTPROC __glewProgramUniform1fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IEXTPROC __glewProgramUniform1iEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IVEXTPROC __glewProgramUniform1ivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIEXTPROC __glewProgramUniform1uiEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIVEXTPROC __glewProgramUniform1uivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FEXTPROC __glewProgramUniform2fEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FVEXTPROC __glewProgramUniform2fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IEXTPROC __glewProgramUniform2iEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IVEXTPROC __glewProgramUniform2ivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIEXTPROC __glewProgramUniform2uiEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIVEXTPROC __glewProgramUniform2uivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FEXTPROC __glewProgramUniform3fEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FVEXTPROC __glewProgramUniform3fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IEXTPROC __glewProgramUniform3iEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IVEXTPROC __glewProgramUniform3ivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIEXTPROC __glewProgramUniform3uiEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIVEXTPROC __glewProgramUniform3uivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FEXTPROC __glewProgramUniform4fEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FVEXTPROC __glewProgramUniform4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IEXTPROC __glewProgramUniform4iEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IVEXTPROC __glewProgramUniform4ivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIEXTPROC __glewProgramUniform4uiEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIVEXTPROC __glewProgramUniform4uivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC __glewProgramUniformMatrix2fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC __glewProgramUniformMatrix2x3fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC __glewProgramUniformMatrix2x4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC __glewProgramUniformMatrix3fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC __glewProgramUniformMatrix3x2fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC __glewProgramUniformMatrix3x4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC __glewProgramUniformMatrix4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC __glewProgramUniformMatrix4x2fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC __glewProgramUniformMatrix4x3fvEXT; +GLEW_FUN_EXPORT PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC __glewPushClientAttribDefaultEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREBUFFEREXTPROC __glewTextureBufferEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE1DEXTPROC __glewTextureImage1DEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DEXTPROC __glewTextureImage2DEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DEXTPROC __glewTextureImage3DEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIIVEXTPROC __glewTextureParameterIivEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIUIVEXTPROC __glewTextureParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERFEXTPROC __glewTextureParameterfEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERFVEXTPROC __glewTextureParameterfvEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIEXTPROC __glewTextureParameteriEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIVEXTPROC __glewTextureParameterivEXT; +GLEW_FUN_EXPORT PFNGLTEXTURERENDERBUFFEREXTPROC __glewTextureRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE1DEXTPROC __glewTextureSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE2DEXTPROC __glewTextureSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE3DEXTPROC __glewTextureSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLUNMAPNAMEDBUFFEREXTPROC __glewUnmapNamedBufferEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYCOLOROFFSETEXTPROC __glewVertexArrayColorOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC __glewVertexArrayEdgeFlagOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC __glewVertexArrayFogCoordOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYINDEXOFFSETEXTPROC __glewVertexArrayIndexOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC __glewVertexArrayMultiTexCoordOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYNORMALOFFSETEXTPROC __glewVertexArrayNormalOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC __glewVertexArraySecondaryColorOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC __glewVertexArrayTexCoordOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC __glewVertexArrayVertexAttribIOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC __glewVertexArrayVertexAttribOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC __glewVertexArrayVertexOffsetEXT; + +GLEW_FUN_EXPORT PFNGLCOLORMASKINDEXEDEXTPROC __glewColorMaskIndexedEXT; +GLEW_FUN_EXPORT PFNGLDISABLEINDEXEDEXTPROC __glewDisableIndexedEXT; +GLEW_FUN_EXPORT PFNGLENABLEINDEXEDEXTPROC __glewEnableIndexedEXT; +GLEW_FUN_EXPORT PFNGLGETBOOLEANINDEXEDVEXTPROC __glewGetBooleanIndexedvEXT; +GLEW_FUN_EXPORT PFNGLGETINTEGERINDEXEDVEXTPROC __glewGetIntegerIndexedvEXT; +GLEW_FUN_EXPORT PFNGLISENABLEDINDEXEDEXTPROC __glewIsEnabledIndexedEXT; + +GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDEXTPROC __glewDrawArraysInstancedEXT; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDEXTPROC __glewDrawElementsInstancedEXT; + +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSEXTPROC __glewDrawRangeElementsEXT; + +GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTEREXTPROC __glewFogCoordPointerEXT; +GLEW_FUN_EXPORT PFNGLFOGCOORDDEXTPROC __glewFogCoorddEXT; +GLEW_FUN_EXPORT PFNGLFOGCOORDDVEXTPROC __glewFogCoorddvEXT; +GLEW_FUN_EXPORT PFNGLFOGCOORDFEXTPROC __glewFogCoordfEXT; +GLEW_FUN_EXPORT PFNGLFOGCOORDFVEXTPROC __glewFogCoordfvEXT; + +GLEW_FUN_EXPORT PFNGLFRAGMENTCOLORMATERIALEXTPROC __glewFragmentColorMaterialEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFEXTPROC __glewFragmentLightModelfEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFVEXTPROC __glewFragmentLightModelfvEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIEXTPROC __glewFragmentLightModeliEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIVEXTPROC __glewFragmentLightModelivEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFEXTPROC __glewFragmentLightfEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFVEXTPROC __glewFragmentLightfvEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIEXTPROC __glewFragmentLightiEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIVEXTPROC __glewFragmentLightivEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFEXTPROC __glewFragmentMaterialfEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFVEXTPROC __glewFragmentMaterialfvEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIEXTPROC __glewFragmentMaterialiEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIVEXTPROC __glewFragmentMaterialivEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTFVEXTPROC __glewGetFragmentLightfvEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTIVEXTPROC __glewGetFragmentLightivEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALFVEXTPROC __glewGetFragmentMaterialfvEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALIVEXTPROC __glewGetFragmentMaterialivEXT; +GLEW_FUN_EXPORT PFNGLLIGHTENVIEXTPROC __glewLightEnviEXT; + +GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFEREXTPROC __glewBlitFramebufferEXT; + +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewRenderbufferStorageMultisampleEXT; + +GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFEREXTPROC __glewBindFramebufferEXT; +GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFEREXTPROC __glewBindRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC __glewCheckFramebufferStatusEXT; +GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSEXTPROC __glewDeleteFramebuffersEXT; +GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSEXTPROC __glewDeleteRenderbuffersEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC __glewFramebufferRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE1DEXTPROC __glewFramebufferTexture1DEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DEXTPROC __glewFramebufferTexture2DEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE3DEXTPROC __glewFramebufferTexture3DEXT; +GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSEXTPROC __glewGenFramebuffersEXT; +GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSEXTPROC __glewGenRenderbuffersEXT; +GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPEXTPROC __glewGenerateMipmapEXT; +GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetFramebufferAttachmentParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC __glewGetRenderbufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLISFRAMEBUFFEREXTPROC __glewIsFramebufferEXT; +GLEW_FUN_EXPORT PFNGLISRENDERBUFFEREXTPROC __glewIsRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEEXTPROC __glewRenderbufferStorageEXT; + +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREEXTPROC __glewFramebufferTextureEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC __glewFramebufferTextureFaceEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIEXTPROC __glewProgramParameteriEXT; + +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERS4FVEXTPROC __glewProgramEnvParameters4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC __glewProgramLocalParameters4fvEXT; + +GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONEXTPROC __glewBindFragDataLocationEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGDATALOCATIONEXTPROC __glewGetFragDataLocationEXT; +GLEW_FUN_EXPORT PFNGLGETUNIFORMUIVEXTPROC __glewGetUniformuivEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIIVEXTPROC __glewGetVertexAttribIivEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIUIVEXTPROC __glewGetVertexAttribIuivEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM1UIEXTPROC __glewUniform1uiEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM1UIVEXTPROC __glewUniform1uivEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM2UIEXTPROC __glewUniform2uiEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM2UIVEXTPROC __glewUniform2uivEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM3UIEXTPROC __glewUniform3uiEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM3UIVEXTPROC __glewUniform3uivEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM4UIEXTPROC __glewUniform4uiEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM4UIVEXTPROC __glewUniform4uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IEXTPROC __glewVertexAttribI1iEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IVEXTPROC __glewVertexAttribI1ivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIEXTPROC __glewVertexAttribI1uiEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIVEXTPROC __glewVertexAttribI1uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IEXTPROC __glewVertexAttribI2iEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IVEXTPROC __glewVertexAttribI2ivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIEXTPROC __glewVertexAttribI2uiEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIVEXTPROC __glewVertexAttribI2uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IEXTPROC __glewVertexAttribI3iEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IVEXTPROC __glewVertexAttribI3ivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIEXTPROC __glewVertexAttribI3uiEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIVEXTPROC __glewVertexAttribI3uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4BVEXTPROC __glewVertexAttribI4bvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IEXTPROC __glewVertexAttribI4iEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IVEXTPROC __glewVertexAttribI4ivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4SVEXTPROC __glewVertexAttribI4svEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UBVEXTPROC __glewVertexAttribI4ubvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIEXTPROC __glewVertexAttribI4uiEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIVEXTPROC __glewVertexAttribI4uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4USVEXTPROC __glewVertexAttribI4usvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIPOINTEREXTPROC __glewVertexAttribIPointerEXT; + +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMEXTPROC __glewGetHistogramEXT; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERFVEXTPROC __glewGetHistogramParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERIVEXTPROC __glewGetHistogramParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETMINMAXEXTPROC __glewGetMinmaxEXT; +GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERFVEXTPROC __glewGetMinmaxParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERIVEXTPROC __glewGetMinmaxParameterivEXT; +GLEW_FUN_EXPORT PFNGLHISTOGRAMEXTPROC __glewHistogramEXT; +GLEW_FUN_EXPORT PFNGLMINMAXEXTPROC __glewMinmaxEXT; +GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMEXTPROC __glewResetHistogramEXT; +GLEW_FUN_EXPORT PFNGLRESETMINMAXEXTPROC __glewResetMinmaxEXT; + +GLEW_FUN_EXPORT PFNGLINDEXFUNCEXTPROC __glewIndexFuncEXT; + +GLEW_FUN_EXPORT PFNGLINDEXMATERIALEXTPROC __glewIndexMaterialEXT; + +GLEW_FUN_EXPORT PFNGLAPPLYTEXTUREEXTPROC __glewApplyTextureEXT; +GLEW_FUN_EXPORT PFNGLTEXTURELIGHTEXTPROC __glewTextureLightEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREMATERIALEXTPROC __glewTextureMaterialEXT; + +GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSEXTPROC __glewMultiDrawArraysEXT; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSEXTPROC __glewMultiDrawElementsEXT; + +GLEW_FUN_EXPORT PFNGLSAMPLEMASKEXTPROC __glewSampleMaskEXT; +GLEW_FUN_EXPORT PFNGLSAMPLEPATTERNEXTPROC __glewSamplePatternEXT; + +GLEW_FUN_EXPORT PFNGLCOLORTABLEEXTPROC __glewColorTableEXT; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEEXTPROC __glewGetColorTableEXT; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVEXTPROC __glewGetColorTableParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVEXTPROC __glewGetColorTableParameterivEXT; + +GLEW_FUN_EXPORT PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC __glewGetPixelTransformParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC __glewGetPixelTransformParameterivEXT; +GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERFEXTPROC __glewPixelTransformParameterfEXT; +GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC __glewPixelTransformParameterfvEXT; +GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERIEXTPROC __glewPixelTransformParameteriEXT; +GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC __glewPixelTransformParameterivEXT; + +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFEXTPROC __glewPointParameterfEXT; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVEXTPROC __glewPointParameterfvEXT; + +GLEW_FUN_EXPORT PFNGLPOLYGONOFFSETEXTPROC __glewPolygonOffsetEXT; + +GLEW_FUN_EXPORT PFNGLPROVOKINGVERTEXEXTPROC __glewProvokingVertexEXT; + +GLEW_FUN_EXPORT PFNGLBEGINSCENEEXTPROC __glewBeginSceneEXT; +GLEW_FUN_EXPORT PFNGLENDSCENEEXTPROC __glewEndSceneEXT; + +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BEXTPROC __glewSecondaryColor3bEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BVEXTPROC __glewSecondaryColor3bvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DEXTPROC __glewSecondaryColor3dEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DVEXTPROC __glewSecondaryColor3dvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FEXTPROC __glewSecondaryColor3fEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FVEXTPROC __glewSecondaryColor3fvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IEXTPROC __glewSecondaryColor3iEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IVEXTPROC __glewSecondaryColor3ivEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SEXTPROC __glewSecondaryColor3sEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SVEXTPROC __glewSecondaryColor3svEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBEXTPROC __glewSecondaryColor3ubEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBVEXTPROC __glewSecondaryColor3ubvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIEXTPROC __glewSecondaryColor3uiEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIVEXTPROC __glewSecondaryColor3uivEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USEXTPROC __glewSecondaryColor3usEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USVEXTPROC __glewSecondaryColor3usvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTEREXTPROC __glewSecondaryColorPointerEXT; + +GLEW_FUN_EXPORT PFNGLACTIVEPROGRAMEXTPROC __glewActiveProgramEXT; +GLEW_FUN_EXPORT PFNGLCREATESHADERPROGRAMEXTPROC __glewCreateShaderProgramEXT; +GLEW_FUN_EXPORT PFNGLUSESHADERPROGRAMEXTPROC __glewUseShaderProgramEXT; + +GLEW_FUN_EXPORT PFNGLBINDIMAGETEXTUREEXTPROC __glewBindImageTextureEXT; +GLEW_FUN_EXPORT PFNGLMEMORYBARRIEREXTPROC __glewMemoryBarrierEXT; + +GLEW_FUN_EXPORT PFNGLACTIVESTENCILFACEEXTPROC __glewActiveStencilFaceEXT; + +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE1DEXTPROC __glewTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE2DEXTPROC __glewTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DEXTPROC __glewTexSubImage3DEXT; + +GLEW_FUN_EXPORT PFNGLTEXIMAGE3DEXTPROC __glewTexImage3DEXT; + +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC __glewFramebufferTextureLayerEXT; + +GLEW_FUN_EXPORT PFNGLTEXBUFFEREXTPROC __glewTexBufferEXT; + +GLEW_FUN_EXPORT PFNGLCLEARCOLORIIEXTPROC __glewClearColorIiEXT; +GLEW_FUN_EXPORT PFNGLCLEARCOLORIUIEXTPROC __glewClearColorIuiEXT; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIIVEXTPROC __glewGetTexParameterIivEXT; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIUIVEXTPROC __glewGetTexParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERIIVEXTPROC __glewTexParameterIivEXT; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERIUIVEXTPROC __glewTexParameterIuivEXT; + +GLEW_FUN_EXPORT PFNGLARETEXTURESRESIDENTEXTPROC __glewAreTexturesResidentEXT; +GLEW_FUN_EXPORT PFNGLBINDTEXTUREEXTPROC __glewBindTextureEXT; +GLEW_FUN_EXPORT PFNGLDELETETEXTURESEXTPROC __glewDeleteTexturesEXT; +GLEW_FUN_EXPORT PFNGLGENTEXTURESEXTPROC __glewGenTexturesEXT; +GLEW_FUN_EXPORT PFNGLISTEXTUREEXTPROC __glewIsTextureEXT; +GLEW_FUN_EXPORT PFNGLPRIORITIZETEXTURESEXTPROC __glewPrioritizeTexturesEXT; + +GLEW_FUN_EXPORT PFNGLTEXTURENORMALEXTPROC __glewTextureNormalEXT; + +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VEXTPROC __glewGetQueryObjecti64vEXT; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VEXTPROC __glewGetQueryObjectui64vEXT; + +GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKEXTPROC __glewBeginTransformFeedbackEXT; +GLEW_FUN_EXPORT PFNGLBINDBUFFERBASEEXTPROC __glewBindBufferBaseEXT; +GLEW_FUN_EXPORT PFNGLBINDBUFFEROFFSETEXTPROC __glewBindBufferOffsetEXT; +GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGEEXTPROC __glewBindBufferRangeEXT; +GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKEXTPROC __glewEndTransformFeedbackEXT; +GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC __glewGetTransformFeedbackVaryingEXT; +GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC __glewTransformFeedbackVaryingsEXT; + +GLEW_FUN_EXPORT PFNGLARRAYELEMENTEXTPROC __glewArrayElementEXT; +GLEW_FUN_EXPORT PFNGLCOLORPOINTEREXTPROC __glewColorPointerEXT; +GLEW_FUN_EXPORT PFNGLDRAWARRAYSEXTPROC __glewDrawArraysEXT; +GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTEREXTPROC __glewEdgeFlagPointerEXT; +GLEW_FUN_EXPORT PFNGLINDEXPOINTEREXTPROC __glewIndexPointerEXT; +GLEW_FUN_EXPORT PFNGLNORMALPOINTEREXTPROC __glewNormalPointerEXT; +GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTEREXTPROC __glewTexCoordPointerEXT; +GLEW_FUN_EXPORT PFNGLVERTEXPOINTEREXTPROC __glewVertexPointerEXT; + +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLDVEXTPROC __glewGetVertexAttribLdvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC __glewVertexArrayVertexAttribLOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DEXTPROC __glewVertexAttribL1dEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DVEXTPROC __glewVertexAttribL1dvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DEXTPROC __glewVertexAttribL2dEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DVEXTPROC __glewVertexAttribL2dvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DEXTPROC __glewVertexAttribL3dEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DVEXTPROC __glewVertexAttribL3dvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DEXTPROC __glewVertexAttribL4dEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DVEXTPROC __glewVertexAttribL4dvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLPOINTEREXTPROC __glewVertexAttribLPointerEXT; + +GLEW_FUN_EXPORT PFNGLBEGINVERTEXSHADEREXTPROC __glewBeginVertexShaderEXT; +GLEW_FUN_EXPORT PFNGLBINDLIGHTPARAMETEREXTPROC __glewBindLightParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDMATERIALPARAMETEREXTPROC __glewBindMaterialParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDPARAMETEREXTPROC __glewBindParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDTEXGENPARAMETEREXTPROC __glewBindTexGenParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDTEXTUREUNITPARAMETEREXTPROC __glewBindTextureUnitParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDVERTEXSHADEREXTPROC __glewBindVertexShaderEXT; +GLEW_FUN_EXPORT PFNGLDELETEVERTEXSHADEREXTPROC __glewDeleteVertexShaderEXT; +GLEW_FUN_EXPORT PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC __glewDisableVariantClientStateEXT; +GLEW_FUN_EXPORT PFNGLENABLEVARIANTCLIENTSTATEEXTPROC __glewEnableVariantClientStateEXT; +GLEW_FUN_EXPORT PFNGLENDVERTEXSHADEREXTPROC __glewEndVertexShaderEXT; +GLEW_FUN_EXPORT PFNGLEXTRACTCOMPONENTEXTPROC __glewExtractComponentEXT; +GLEW_FUN_EXPORT PFNGLGENSYMBOLSEXTPROC __glewGenSymbolsEXT; +GLEW_FUN_EXPORT PFNGLGENVERTEXSHADERSEXTPROC __glewGenVertexShadersEXT; +GLEW_FUN_EXPORT PFNGLGETINVARIANTBOOLEANVEXTPROC __glewGetInvariantBooleanvEXT; +GLEW_FUN_EXPORT PFNGLGETINVARIANTFLOATVEXTPROC __glewGetInvariantFloatvEXT; +GLEW_FUN_EXPORT PFNGLGETINVARIANTINTEGERVEXTPROC __glewGetInvariantIntegervEXT; +GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC __glewGetLocalConstantBooleanvEXT; +GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTFLOATVEXTPROC __glewGetLocalConstantFloatvEXT; +GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTINTEGERVEXTPROC __glewGetLocalConstantIntegervEXT; +GLEW_FUN_EXPORT PFNGLGETVARIANTBOOLEANVEXTPROC __glewGetVariantBooleanvEXT; +GLEW_FUN_EXPORT PFNGLGETVARIANTFLOATVEXTPROC __glewGetVariantFloatvEXT; +GLEW_FUN_EXPORT PFNGLGETVARIANTINTEGERVEXTPROC __glewGetVariantIntegervEXT; +GLEW_FUN_EXPORT PFNGLGETVARIANTPOINTERVEXTPROC __glewGetVariantPointervEXT; +GLEW_FUN_EXPORT PFNGLINSERTCOMPONENTEXTPROC __glewInsertComponentEXT; +GLEW_FUN_EXPORT PFNGLISVARIANTENABLEDEXTPROC __glewIsVariantEnabledEXT; +GLEW_FUN_EXPORT PFNGLSETINVARIANTEXTPROC __glewSetInvariantEXT; +GLEW_FUN_EXPORT PFNGLSETLOCALCONSTANTEXTPROC __glewSetLocalConstantEXT; +GLEW_FUN_EXPORT PFNGLSHADEROP1EXTPROC __glewShaderOp1EXT; +GLEW_FUN_EXPORT PFNGLSHADEROP2EXTPROC __glewShaderOp2EXT; +GLEW_FUN_EXPORT PFNGLSHADEROP3EXTPROC __glewShaderOp3EXT; +GLEW_FUN_EXPORT PFNGLSWIZZLEEXTPROC __glewSwizzleEXT; +GLEW_FUN_EXPORT PFNGLVARIANTPOINTEREXTPROC __glewVariantPointerEXT; +GLEW_FUN_EXPORT PFNGLVARIANTBVEXTPROC __glewVariantbvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTDVEXTPROC __glewVariantdvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTFVEXTPROC __glewVariantfvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTIVEXTPROC __glewVariantivEXT; +GLEW_FUN_EXPORT PFNGLVARIANTSVEXTPROC __glewVariantsvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTUBVEXTPROC __glewVariantubvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTUIVEXTPROC __glewVariantuivEXT; +GLEW_FUN_EXPORT PFNGLVARIANTUSVEXTPROC __glewVariantusvEXT; +GLEW_FUN_EXPORT PFNGLWRITEMASKEXTPROC __glewWriteMaskEXT; + +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTPOINTEREXTPROC __glewVertexWeightPointerEXT; +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTFEXTPROC __glewVertexWeightfEXT; +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTFVEXTPROC __glewVertexWeightfvEXT; + +GLEW_FUN_EXPORT PFNGLIMPORTSYNCEXTPROC __glewImportSyncEXT; + +GLEW_FUN_EXPORT PFNGLFRAMETERMINATORGREMEDYPROC __glewFrameTerminatorGREMEDY; + +GLEW_FUN_EXPORT PFNGLSTRINGMARKERGREMEDYPROC __glewStringMarkerGREMEDY; + +GLEW_FUN_EXPORT PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC __glewGetImageTransformParameterfvHP; +GLEW_FUN_EXPORT PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC __glewGetImageTransformParameterivHP; +GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERFHPPROC __glewImageTransformParameterfHP; +GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERFVHPPROC __glewImageTransformParameterfvHP; +GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERIHPPROC __glewImageTransformParameteriHP; +GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERIVHPPROC __glewImageTransformParameterivHP; + +GLEW_FUN_EXPORT PFNGLMULTIMODEDRAWARRAYSIBMPROC __glewMultiModeDrawArraysIBM; +GLEW_FUN_EXPORT PFNGLMULTIMODEDRAWELEMENTSIBMPROC __glewMultiModeDrawElementsIBM; + +GLEW_FUN_EXPORT PFNGLCOLORPOINTERLISTIBMPROC __glewColorPointerListIBM; +GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTERLISTIBMPROC __glewEdgeFlagPointerListIBM; +GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTERLISTIBMPROC __glewFogCoordPointerListIBM; +GLEW_FUN_EXPORT PFNGLINDEXPOINTERLISTIBMPROC __glewIndexPointerListIBM; +GLEW_FUN_EXPORT PFNGLNORMALPOINTERLISTIBMPROC __glewNormalPointerListIBM; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERLISTIBMPROC __glewSecondaryColorPointerListIBM; +GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERLISTIBMPROC __glewTexCoordPointerListIBM; +GLEW_FUN_EXPORT PFNGLVERTEXPOINTERLISTIBMPROC __glewVertexPointerListIBM; + +GLEW_FUN_EXPORT PFNGLCOLORPOINTERVINTELPROC __glewColorPointervINTEL; +GLEW_FUN_EXPORT PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL; +GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL; +GLEW_FUN_EXPORT PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL; + +GLEW_FUN_EXPORT PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL; +GLEW_FUN_EXPORT PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL; + +GLEW_FUN_EXPORT PFNGLBUFFERREGIONENABLEDEXTPROC __glewBufferRegionEnabledEXT; +GLEW_FUN_EXPORT PFNGLDELETEBUFFERREGIONEXTPROC __glewDeleteBufferRegionEXT; +GLEW_FUN_EXPORT PFNGLDRAWBUFFERREGIONEXTPROC __glewDrawBufferRegionEXT; +GLEW_FUN_EXPORT PFNGLNEWBUFFERREGIONEXTPROC __glewNewBufferRegionEXT; +GLEW_FUN_EXPORT PFNGLREADBUFFERREGIONEXTPROC __glewReadBufferRegionEXT; + +GLEW_FUN_EXPORT PFNGLRESIZEBUFFERSMESAPROC __glewResizeBuffersMESA; + +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DMESAPROC __glewWindowPos2dMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVMESAPROC __glewWindowPos2dvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FMESAPROC __glewWindowPos2fMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVMESAPROC __glewWindowPos2fvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IMESAPROC __glewWindowPos2iMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVMESAPROC __glewWindowPos2ivMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SMESAPROC __glewWindowPos2sMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVMESAPROC __glewWindowPos2svMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DMESAPROC __glewWindowPos3dMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVMESAPROC __glewWindowPos3dvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FMESAPROC __glewWindowPos3fMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVMESAPROC __glewWindowPos3fvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IMESAPROC __glewWindowPos3iMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVMESAPROC __glewWindowPos3ivMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SMESAPROC __glewWindowPos3sMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVMESAPROC __glewWindowPos3svMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4DMESAPROC __glewWindowPos4dMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4DVMESAPROC __glewWindowPos4dvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4FMESAPROC __glewWindowPos4fMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4FVMESAPROC __glewWindowPos4fvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4IMESAPROC __glewWindowPos4iMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4IVMESAPROC __glewWindowPos4ivMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4SMESAPROC __glewWindowPos4sMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4SVMESAPROC __glewWindowPos4svMESA; + +GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERNVPROC __glewBeginConditionalRenderNV; +GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERNVPROC __glewEndConditionalRenderNV; + +GLEW_FUN_EXPORT PFNGLCOPYIMAGESUBDATANVPROC __glewCopyImageSubDataNV; + +GLEW_FUN_EXPORT PFNGLCLEARDEPTHDNVPROC __glewClearDepthdNV; +GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSDNVPROC __glewDepthBoundsdNV; +GLEW_FUN_EXPORT PFNGLDEPTHRANGEDNVPROC __glewDepthRangedNV; + +GLEW_FUN_EXPORT PFNGLEVALMAPSNVPROC __glewEvalMapsNV; +GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERFVNVPROC __glewGetMapAttribParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERIVNVPROC __glewGetMapAttribParameterivNV; +GLEW_FUN_EXPORT PFNGLGETMAPCONTROLPOINTSNVPROC __glewGetMapControlPointsNV; +GLEW_FUN_EXPORT PFNGLGETMAPPARAMETERFVNVPROC __glewGetMapParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETMAPPARAMETERIVNVPROC __glewGetMapParameterivNV; +GLEW_FUN_EXPORT PFNGLMAPCONTROLPOINTSNVPROC __glewMapControlPointsNV; +GLEW_FUN_EXPORT PFNGLMAPPARAMETERFVNVPROC __glewMapParameterfvNV; +GLEW_FUN_EXPORT PFNGLMAPPARAMETERIVNVPROC __glewMapParameterivNV; + +GLEW_FUN_EXPORT PFNGLGETMULTISAMPLEFVNVPROC __glewGetMultisamplefvNV; +GLEW_FUN_EXPORT PFNGLSAMPLEMASKINDEXEDNVPROC __glewSampleMaskIndexedNV; +GLEW_FUN_EXPORT PFNGLTEXRENDERBUFFERNVPROC __glewTexRenderbufferNV; + +GLEW_FUN_EXPORT PFNGLDELETEFENCESNVPROC __glewDeleteFencesNV; +GLEW_FUN_EXPORT PFNGLFINISHFENCENVPROC __glewFinishFenceNV; +GLEW_FUN_EXPORT PFNGLGENFENCESNVPROC __glewGenFencesNV; +GLEW_FUN_EXPORT PFNGLGETFENCEIVNVPROC __glewGetFenceivNV; +GLEW_FUN_EXPORT PFNGLISFENCENVPROC __glewIsFenceNV; +GLEW_FUN_EXPORT PFNGLSETFENCENVPROC __glewSetFenceNV; +GLEW_FUN_EXPORT PFNGLTESTFENCENVPROC __glewTestFenceNV; + +GLEW_FUN_EXPORT PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC __glewGetProgramNamedParameterdvNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC __glewGetProgramNamedParameterfvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4DNVPROC __glewProgramNamedParameter4dNV; +GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC __glewProgramNamedParameter4dvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4FNVPROC __glewProgramNamedParameter4fNV; +GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC __glewProgramNamedParameter4fvNV; + +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC __glewRenderbufferStorageMultisampleCoverageNV; + +GLEW_FUN_EXPORT PFNGLPROGRAMVERTEXLIMITNVPROC __glewProgramVertexLimitNV; + +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4INVPROC __glewProgramEnvParameterI4iNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4IVNVPROC __glewProgramEnvParameterI4ivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4UINVPROC __glewProgramEnvParameterI4uiNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4UIVNVPROC __glewProgramEnvParameterI4uivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERSI4IVNVPROC __glewProgramEnvParametersI4ivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC __glewProgramEnvParametersI4uivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4INVPROC __glewProgramLocalParameterI4iNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC __glewProgramLocalParameterI4ivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4UINVPROC __glewProgramLocalParameterI4uiNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC __glewProgramLocalParameterI4uivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC __glewProgramLocalParametersI4ivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC __glewProgramLocalParametersI4uivNV; + +GLEW_FUN_EXPORT PFNGLGETUNIFORMI64VNVPROC __glewGetUniformi64vNV; +GLEW_FUN_EXPORT PFNGLGETUNIFORMUI64VNVPROC __glewGetUniformui64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1I64NVPROC __glewProgramUniform1i64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1I64VNVPROC __glewProgramUniform1i64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UI64NVPROC __glewProgramUniform1ui64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UI64VNVPROC __glewProgramUniform1ui64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2I64NVPROC __glewProgramUniform2i64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2I64VNVPROC __glewProgramUniform2i64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UI64NVPROC __glewProgramUniform2ui64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UI64VNVPROC __glewProgramUniform2ui64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3I64NVPROC __glewProgramUniform3i64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3I64VNVPROC __glewProgramUniform3i64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UI64NVPROC __glewProgramUniform3ui64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UI64VNVPROC __glewProgramUniform3ui64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4I64NVPROC __glewProgramUniform4i64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4I64VNVPROC __glewProgramUniform4i64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UI64NVPROC __glewProgramUniform4ui64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UI64VNVPROC __glewProgramUniform4ui64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM1I64NVPROC __glewUniform1i64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM1I64VNVPROC __glewUniform1i64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM1UI64NVPROC __glewUniform1ui64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM1UI64VNVPROC __glewUniform1ui64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM2I64NVPROC __glewUniform2i64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM2I64VNVPROC __glewUniform2i64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM2UI64NVPROC __glewUniform2ui64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM2UI64VNVPROC __glewUniform2ui64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM3I64NVPROC __glewUniform3i64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM3I64VNVPROC __glewUniform3i64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM3UI64NVPROC __glewUniform3ui64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM3UI64VNVPROC __glewUniform3ui64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM4I64NVPROC __glewUniform4i64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM4I64VNVPROC __glewUniform4i64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM4UI64NVPROC __glewUniform4ui64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM4UI64VNVPROC __glewUniform4ui64vNV; + +GLEW_FUN_EXPORT PFNGLCOLOR3HNVPROC __glewColor3hNV; +GLEW_FUN_EXPORT PFNGLCOLOR3HVNVPROC __glewColor3hvNV; +GLEW_FUN_EXPORT PFNGLCOLOR4HNVPROC __glewColor4hNV; +GLEW_FUN_EXPORT PFNGLCOLOR4HVNVPROC __glewColor4hvNV; +GLEW_FUN_EXPORT PFNGLFOGCOORDHNVPROC __glewFogCoordhNV; +GLEW_FUN_EXPORT PFNGLFOGCOORDHVNVPROC __glewFogCoordhvNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1HNVPROC __glewMultiTexCoord1hNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1HVNVPROC __glewMultiTexCoord1hvNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2HNVPROC __glewMultiTexCoord2hNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2HVNVPROC __glewMultiTexCoord2hvNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3HNVPROC __glewMultiTexCoord3hNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3HVNVPROC __glewMultiTexCoord3hvNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4HNVPROC __glewMultiTexCoord4hNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4HVNVPROC __glewMultiTexCoord4hvNV; +GLEW_FUN_EXPORT PFNGLNORMAL3HNVPROC __glewNormal3hNV; +GLEW_FUN_EXPORT PFNGLNORMAL3HVNVPROC __glewNormal3hvNV; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3HNVPROC __glewSecondaryColor3hNV; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3HVNVPROC __glewSecondaryColor3hvNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD1HNVPROC __glewTexCoord1hNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD1HVNVPROC __glewTexCoord1hvNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD2HNVPROC __glewTexCoord2hNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD2HVNVPROC __glewTexCoord2hvNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD3HNVPROC __glewTexCoord3hNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD3HVNVPROC __glewTexCoord3hvNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD4HNVPROC __glewTexCoord4hNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD4HVNVPROC __glewTexCoord4hvNV; +GLEW_FUN_EXPORT PFNGLVERTEX2HNVPROC __glewVertex2hNV; +GLEW_FUN_EXPORT PFNGLVERTEX2HVNVPROC __glewVertex2hvNV; +GLEW_FUN_EXPORT PFNGLVERTEX3HNVPROC __glewVertex3hNV; +GLEW_FUN_EXPORT PFNGLVERTEX3HVNVPROC __glewVertex3hvNV; +GLEW_FUN_EXPORT PFNGLVERTEX4HNVPROC __glewVertex4hNV; +GLEW_FUN_EXPORT PFNGLVERTEX4HVNVPROC __glewVertex4hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1HNVPROC __glewVertexAttrib1hNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1HVNVPROC __glewVertexAttrib1hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2HNVPROC __glewVertexAttrib2hNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2HVNVPROC __glewVertexAttrib2hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3HNVPROC __glewVertexAttrib3hNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3HVNVPROC __glewVertexAttrib3hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4HNVPROC __glewVertexAttrib4hNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4HVNVPROC __glewVertexAttrib4hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1HVNVPROC __glewVertexAttribs1hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2HVNVPROC __glewVertexAttribs2hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3HVNVPROC __glewVertexAttribs3hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4HVNVPROC __glewVertexAttribs4hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTHNVPROC __glewVertexWeighthNV; +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTHVNVPROC __glewVertexWeighthvNV; + +GLEW_FUN_EXPORT PFNGLBEGINOCCLUSIONQUERYNVPROC __glewBeginOcclusionQueryNV; +GLEW_FUN_EXPORT PFNGLDELETEOCCLUSIONQUERIESNVPROC __glewDeleteOcclusionQueriesNV; +GLEW_FUN_EXPORT PFNGLENDOCCLUSIONQUERYNVPROC __glewEndOcclusionQueryNV; +GLEW_FUN_EXPORT PFNGLGENOCCLUSIONQUERIESNVPROC __glewGenOcclusionQueriesNV; +GLEW_FUN_EXPORT PFNGLGETOCCLUSIONQUERYIVNVPROC __glewGetOcclusionQueryivNV; +GLEW_FUN_EXPORT PFNGLGETOCCLUSIONQUERYUIVNVPROC __glewGetOcclusionQueryuivNV; +GLEW_FUN_EXPORT PFNGLISOCCLUSIONQUERYNVPROC __glewIsOcclusionQueryNV; + +GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC __glewProgramBufferParametersIivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC __glewProgramBufferParametersIuivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC __glewProgramBufferParametersfvNV; + +GLEW_FUN_EXPORT PFNGLFLUSHPIXELDATARANGENVPROC __glewFlushPixelDataRangeNV; +GLEW_FUN_EXPORT PFNGLPIXELDATARANGENVPROC __glewPixelDataRangeNV; + +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERINVPROC __glewPointParameteriNV; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIVNVPROC __glewPointParameterivNV; + +GLEW_FUN_EXPORT PFNGLGETVIDEOI64VNVPROC __glewGetVideoi64vNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOIVNVPROC __glewGetVideoivNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOUI64VNVPROC __glewGetVideoui64vNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOUIVNVPROC __glewGetVideouivNV; +GLEW_FUN_EXPORT PFNGLPRESENTFRAMEDUALFILLNVPROC __glewPresentFrameDualFillNV; +GLEW_FUN_EXPORT PFNGLPRESENTFRAMEKEYEDNVPROC __glewPresentFrameKeyedNV; + +GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTINDEXNVPROC __glewPrimitiveRestartIndexNV; +GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTNVPROC __glewPrimitiveRestartNV; + +GLEW_FUN_EXPORT PFNGLCOMBINERINPUTNVPROC __glewCombinerInputNV; +GLEW_FUN_EXPORT PFNGLCOMBINEROUTPUTNVPROC __glewCombinerOutputNV; +GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERFNVPROC __glewCombinerParameterfNV; +GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERFVNVPROC __glewCombinerParameterfvNV; +GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERINVPROC __glewCombinerParameteriNV; +GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERIVNVPROC __glewCombinerParameterivNV; +GLEW_FUN_EXPORT PFNGLFINALCOMBINERINPUTNVPROC __glewFinalCombinerInputNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC __glewGetCombinerInputParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC __glewGetCombinerInputParameterivNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC __glewGetCombinerOutputParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC __glewGetCombinerOutputParameterivNV; +GLEW_FUN_EXPORT PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC __glewGetFinalCombinerInputParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC __glewGetFinalCombinerInputParameterivNV; + +GLEW_FUN_EXPORT PFNGLCOMBINERSTAGEPARAMETERFVNVPROC __glewCombinerStageParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC __glewGetCombinerStageParameterfvNV; + +GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERUI64VNVPROC __glewGetBufferParameterui64vNV; +GLEW_FUN_EXPORT PFNGLGETINTEGERUI64VNVPROC __glewGetIntegerui64vNV; +GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC __glewGetNamedBufferParameterui64vNV; +GLEW_FUN_EXPORT PFNGLISBUFFERRESIDENTNVPROC __glewIsBufferResidentNV; +GLEW_FUN_EXPORT PFNGLISNAMEDBUFFERRESIDENTNVPROC __glewIsNamedBufferResidentNV; +GLEW_FUN_EXPORT PFNGLMAKEBUFFERNONRESIDENTNVPROC __glewMakeBufferNonResidentNV; +GLEW_FUN_EXPORT PFNGLMAKEBUFFERRESIDENTNVPROC __glewMakeBufferResidentNV; +GLEW_FUN_EXPORT PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC __glewMakeNamedBufferNonResidentNV; +GLEW_FUN_EXPORT PFNGLMAKENAMEDBUFFERRESIDENTNVPROC __glewMakeNamedBufferResidentNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMUI64NVPROC __glewProgramUniformui64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMUI64VNVPROC __glewProgramUniformui64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORMUI64NVPROC __glewUniformui64NV; +GLEW_FUN_EXPORT PFNGLUNIFORMUI64VNVPROC __glewUniformui64vNV; + +GLEW_FUN_EXPORT PFNGLTEXTUREBARRIERNVPROC __glewTextureBarrierNV; + +GLEW_FUN_EXPORT PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC __glewTexImage2DMultisampleCoverageNV; +GLEW_FUN_EXPORT PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC __glewTexImage3DMultisampleCoverageNV; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC __glewTextureImage2DMultisampleCoverageNV; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC __glewTextureImage2DMultisampleNV; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC __glewTextureImage3DMultisampleCoverageNV; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC __glewTextureImage3DMultisampleNV; + +GLEW_FUN_EXPORT PFNGLACTIVEVARYINGNVPROC __glewActiveVaryingNV; +GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKNVPROC __glewBeginTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLBINDBUFFERBASENVPROC __glewBindBufferBaseNV; +GLEW_FUN_EXPORT PFNGLBINDBUFFEROFFSETNVPROC __glewBindBufferOffsetNV; +GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGENVPROC __glewBindBufferRangeNV; +GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKNVPROC __glewEndTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLGETACTIVEVARYINGNVPROC __glewGetActiveVaryingNV; +GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC __glewGetTransformFeedbackVaryingNV; +GLEW_FUN_EXPORT PFNGLGETVARYINGLOCATIONNVPROC __glewGetVaryingLocationNV; +GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC __glewTransformFeedbackAttribsNV; +GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC __glewTransformFeedbackVaryingsNV; + +GLEW_FUN_EXPORT PFNGLBINDTRANSFORMFEEDBACKNVPROC __glewBindTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLDELETETRANSFORMFEEDBACKSNVPROC __glewDeleteTransformFeedbacksNV; +GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKNVPROC __glewDrawTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLGENTRANSFORMFEEDBACKSNVPROC __glewGenTransformFeedbacksNV; +GLEW_FUN_EXPORT PFNGLISTRANSFORMFEEDBACKNVPROC __glewIsTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLPAUSETRANSFORMFEEDBACKNVPROC __glewPauseTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLRESUMETRANSFORMFEEDBACKNVPROC __glewResumeTransformFeedbackNV; + +GLEW_FUN_EXPORT PFNGLVDPAUFININVPROC __glewVDPAUFiniNV; +GLEW_FUN_EXPORT PFNGLVDPAUGETSURFACEIVNVPROC __glewVDPAUGetSurfaceivNV; +GLEW_FUN_EXPORT PFNGLVDPAUINITNVPROC __glewVDPAUInitNV; +GLEW_FUN_EXPORT PFNGLVDPAUISSURFACENVPROC __glewVDPAUIsSurfaceNV; +GLEW_FUN_EXPORT PFNGLVDPAUMAPSURFACESNVPROC __glewVDPAUMapSurfacesNV; +GLEW_FUN_EXPORT PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC __glewVDPAURegisterOutputSurfaceNV; +GLEW_FUN_EXPORT PFNGLVDPAUREGISTERVIDEOSURFACENVPROC __glewVDPAURegisterVideoSurfaceNV; +GLEW_FUN_EXPORT PFNGLVDPAUSURFACEACCESSNVPROC __glewVDPAUSurfaceAccessNV; +GLEW_FUN_EXPORT PFNGLVDPAUUNMAPSURFACESNVPROC __glewVDPAUUnmapSurfacesNV; +GLEW_FUN_EXPORT PFNGLVDPAUUNREGISTERSURFACENVPROC __glewVDPAUUnregisterSurfaceNV; + +GLEW_FUN_EXPORT PFNGLFLUSHVERTEXARRAYRANGENVPROC __glewFlushVertexArrayRangeNV; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYRANGENVPROC __glewVertexArrayRangeNV; + +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLI64VNVPROC __glewGetVertexAttribLi64vNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLUI64VNVPROC __glewGetVertexAttribLui64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1I64NVPROC __glewVertexAttribL1i64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1I64VNVPROC __glewVertexAttribL1i64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1UI64NVPROC __glewVertexAttribL1ui64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1UI64VNVPROC __glewVertexAttribL1ui64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2I64NVPROC __glewVertexAttribL2i64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2I64VNVPROC __glewVertexAttribL2i64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2UI64NVPROC __glewVertexAttribL2ui64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2UI64VNVPROC __glewVertexAttribL2ui64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3I64NVPROC __glewVertexAttribL3i64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3I64VNVPROC __glewVertexAttribL3i64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3UI64NVPROC __glewVertexAttribL3ui64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3UI64VNVPROC __glewVertexAttribL3ui64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4I64NVPROC __glewVertexAttribL4i64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4I64VNVPROC __glewVertexAttribL4i64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4UI64NVPROC __glewVertexAttribL4ui64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4UI64VNVPROC __glewVertexAttribL4ui64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLFORMATNVPROC __glewVertexAttribLFormatNV; + +GLEW_FUN_EXPORT PFNGLBUFFERADDRESSRANGENVPROC __glewBufferAddressRangeNV; +GLEW_FUN_EXPORT PFNGLCOLORFORMATNVPROC __glewColorFormatNV; +GLEW_FUN_EXPORT PFNGLEDGEFLAGFORMATNVPROC __glewEdgeFlagFormatNV; +GLEW_FUN_EXPORT PFNGLFOGCOORDFORMATNVPROC __glewFogCoordFormatNV; +GLEW_FUN_EXPORT PFNGLGETINTEGERUI64I_VNVPROC __glewGetIntegerui64i_vNV; +GLEW_FUN_EXPORT PFNGLINDEXFORMATNVPROC __glewIndexFormatNV; +GLEW_FUN_EXPORT PFNGLNORMALFORMATNVPROC __glewNormalFormatNV; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORFORMATNVPROC __glewSecondaryColorFormatNV; +GLEW_FUN_EXPORT PFNGLTEXCOORDFORMATNVPROC __glewTexCoordFormatNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBFORMATNVPROC __glewVertexAttribFormatNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIFORMATNVPROC __glewVertexAttribIFormatNV; +GLEW_FUN_EXPORT PFNGLVERTEXFORMATNVPROC __glewVertexFormatNV; + +GLEW_FUN_EXPORT PFNGLAREPROGRAMSRESIDENTNVPROC __glewAreProgramsResidentNV; +GLEW_FUN_EXPORT PFNGLBINDPROGRAMNVPROC __glewBindProgramNV; +GLEW_FUN_EXPORT PFNGLDELETEPROGRAMSNVPROC __glewDeleteProgramsNV; +GLEW_FUN_EXPORT PFNGLEXECUTEPROGRAMNVPROC __glewExecuteProgramNV; +GLEW_FUN_EXPORT PFNGLGENPROGRAMSNVPROC __glewGenProgramsNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMPARAMETERDVNVPROC __glewGetProgramParameterdvNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMPARAMETERFVNVPROC __glewGetProgramParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMSTRINGNVPROC __glewGetProgramStringNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMIVNVPROC __glewGetProgramivNV; +GLEW_FUN_EXPORT PFNGLGETTRACKMATRIXIVNVPROC __glewGetTrackMatrixivNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVNVPROC __glewGetVertexAttribPointervNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVNVPROC __glewGetVertexAttribdvNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVNVPROC __glewGetVertexAttribfvNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVNVPROC __glewGetVertexAttribivNV; +GLEW_FUN_EXPORT PFNGLISPROGRAMNVPROC __glewIsProgramNV; +GLEW_FUN_EXPORT PFNGLLOADPROGRAMNVPROC __glewLoadProgramNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4DNVPROC __glewProgramParameter4dNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4DVNVPROC __glewProgramParameter4dvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4FNVPROC __glewProgramParameter4fNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4FVNVPROC __glewProgramParameter4fvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERS4DVNVPROC __glewProgramParameters4dvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERS4FVNVPROC __glewProgramParameters4fvNV; +GLEW_FUN_EXPORT PFNGLREQUESTRESIDENTPROGRAMSNVPROC __glewRequestResidentProgramsNV; +GLEW_FUN_EXPORT PFNGLTRACKMATRIXNVPROC __glewTrackMatrixNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DNVPROC __glewVertexAttrib1dNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVNVPROC __glewVertexAttrib1dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FNVPROC __glewVertexAttrib1fNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVNVPROC __glewVertexAttrib1fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SNVPROC __glewVertexAttrib1sNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVNVPROC __glewVertexAttrib1svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DNVPROC __glewVertexAttrib2dNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVNVPROC __glewVertexAttrib2dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FNVPROC __glewVertexAttrib2fNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVNVPROC __glewVertexAttrib2fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SNVPROC __glewVertexAttrib2sNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVNVPROC __glewVertexAttrib2svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DNVPROC __glewVertexAttrib3dNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVNVPROC __glewVertexAttrib3dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FNVPROC __glewVertexAttrib3fNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVNVPROC __glewVertexAttrib3fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SNVPROC __glewVertexAttrib3sNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVNVPROC __glewVertexAttrib3svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DNVPROC __glewVertexAttrib4dNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVNVPROC __glewVertexAttrib4dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FNVPROC __glewVertexAttrib4fNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVNVPROC __glewVertexAttrib4fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SNVPROC __glewVertexAttrib4sNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVNVPROC __glewVertexAttrib4svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBNVPROC __glewVertexAttrib4ubNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVNVPROC __glewVertexAttrib4ubvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERNVPROC __glewVertexAttribPointerNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1DVNVPROC __glewVertexAttribs1dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1FVNVPROC __glewVertexAttribs1fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1SVNVPROC __glewVertexAttribs1svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2DVNVPROC __glewVertexAttribs2dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2FVNVPROC __glewVertexAttribs2fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2SVNVPROC __glewVertexAttribs2svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3DVNVPROC __glewVertexAttribs3dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3FVNVPROC __glewVertexAttribs3fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3SVNVPROC __glewVertexAttribs3svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4DVNVPROC __glewVertexAttribs4dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4FVNVPROC __glewVertexAttribs4fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4SVNVPROC __glewVertexAttribs4svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4UBVNVPROC __glewVertexAttribs4ubvNV; + +GLEW_FUN_EXPORT PFNGLBEGINVIDEOCAPTURENVPROC __glewBeginVideoCaptureNV; +GLEW_FUN_EXPORT PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC __glewBindVideoCaptureStreamBufferNV; +GLEW_FUN_EXPORT PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC __glewBindVideoCaptureStreamTextureNV; +GLEW_FUN_EXPORT PFNGLENDVIDEOCAPTURENVPROC __glewEndVideoCaptureNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMDVNVPROC __glewGetVideoCaptureStreamdvNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMFVNVPROC __glewGetVideoCaptureStreamfvNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMIVNVPROC __glewGetVideoCaptureStreamivNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTUREIVNVPROC __glewGetVideoCaptureivNV; +GLEW_FUN_EXPORT PFNGLVIDEOCAPTURENVPROC __glewVideoCaptureNV; +GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC __glewVideoCaptureStreamParameterdvNV; +GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC __glewVideoCaptureStreamParameterfvNV; +GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC __glewVideoCaptureStreamParameterivNV; + +GLEW_FUN_EXPORT PFNGLCLEARDEPTHFOESPROC __glewClearDepthfOES; +GLEW_FUN_EXPORT PFNGLCLIPPLANEFOESPROC __glewClipPlanefOES; +GLEW_FUN_EXPORT PFNGLDEPTHRANGEFOESPROC __glewDepthRangefOES; +GLEW_FUN_EXPORT PFNGLFRUSTUMFOESPROC __glewFrustumfOES; +GLEW_FUN_EXPORT PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES; +GLEW_FUN_EXPORT PFNGLORTHOFOESPROC __glewOrthofOES; + +GLEW_FUN_EXPORT PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS; +GLEW_FUN_EXPORT PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS; + +GLEW_FUN_EXPORT PFNGLFOGFUNCSGISPROC __glewFogFuncSGIS; +GLEW_FUN_EXPORT PFNGLGETFOGFUNCSGISPROC __glewGetFogFuncSGIS; + +GLEW_FUN_EXPORT PFNGLSAMPLEMASKSGISPROC __glewSampleMaskSGIS; +GLEW_FUN_EXPORT PFNGLSAMPLEPATTERNSGISPROC __glewSamplePatternSGIS; + +GLEW_FUN_EXPORT PFNGLGETSHARPENTEXFUNCSGISPROC __glewGetSharpenTexFuncSGIS; +GLEW_FUN_EXPORT PFNGLSHARPENTEXFUNCSGISPROC __glewSharpenTexFuncSGIS; + +GLEW_FUN_EXPORT PFNGLTEXIMAGE4DSGISPROC __glewTexImage4DSGIS; +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE4DSGISPROC __glewTexSubImage4DSGIS; + +GLEW_FUN_EXPORT PFNGLGETTEXFILTERFUNCSGISPROC __glewGetTexFilterFuncSGIS; +GLEW_FUN_EXPORT PFNGLTEXFILTERFUNCSGISPROC __glewTexFilterFuncSGIS; + +GLEW_FUN_EXPORT PFNGLASYNCMARKERSGIXPROC __glewAsyncMarkerSGIX; +GLEW_FUN_EXPORT PFNGLDELETEASYNCMARKERSSGIXPROC __glewDeleteAsyncMarkersSGIX; +GLEW_FUN_EXPORT PFNGLFINISHASYNCSGIXPROC __glewFinishAsyncSGIX; +GLEW_FUN_EXPORT PFNGLGENASYNCMARKERSSGIXPROC __glewGenAsyncMarkersSGIX; +GLEW_FUN_EXPORT PFNGLISASYNCMARKERSGIXPROC __glewIsAsyncMarkerSGIX; +GLEW_FUN_EXPORT PFNGLPOLLASYNCSGIXPROC __glewPollAsyncSGIX; + +GLEW_FUN_EXPORT PFNGLFLUSHRASTERSGIXPROC __glewFlushRasterSGIX; + +GLEW_FUN_EXPORT PFNGLTEXTUREFOGSGIXPROC __glewTextureFogSGIX; + +GLEW_FUN_EXPORT PFNGLFRAGMENTCOLORMATERIALSGIXPROC __glewFragmentColorMaterialSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFSGIXPROC __glewFragmentLightModelfSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFVSGIXPROC __glewFragmentLightModelfvSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELISGIXPROC __glewFragmentLightModeliSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIVSGIXPROC __glewFragmentLightModelivSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFSGIXPROC __glewFragmentLightfSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFVSGIXPROC __glewFragmentLightfvSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTISGIXPROC __glewFragmentLightiSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIVSGIXPROC __glewFragmentLightivSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFSGIXPROC __glewFragmentMaterialfSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFVSGIXPROC __glewFragmentMaterialfvSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALISGIXPROC __glewFragmentMaterialiSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIVSGIXPROC __glewFragmentMaterialivSGIX; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTFVSGIXPROC __glewGetFragmentLightfvSGIX; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTIVSGIXPROC __glewGetFragmentLightivSGIX; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALFVSGIXPROC __glewGetFragmentMaterialfvSGIX; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALIVSGIXPROC __glewGetFragmentMaterialivSGIX; + +GLEW_FUN_EXPORT PFNGLFRAMEZOOMSGIXPROC __glewFrameZoomSGIX; + +GLEW_FUN_EXPORT PFNGLPIXELTEXGENSGIXPROC __glewPixelTexGenSGIX; + +GLEW_FUN_EXPORT PFNGLREFERENCEPLANESGIXPROC __glewReferencePlaneSGIX; + +GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERFSGIXPROC __glewSpriteParameterfSGIX; +GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERFVSGIXPROC __glewSpriteParameterfvSGIX; +GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERISGIXPROC __glewSpriteParameteriSGIX; +GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERIVSGIXPROC __glewSpriteParameterivSGIX; + +GLEW_FUN_EXPORT PFNGLTAGSAMPLEBUFFERSGIXPROC __glewTagSampleBufferSGIX; + +GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERFVSGIPROC __glewColorTableParameterfvSGI; +GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERIVSGIPROC __glewColorTableParameterivSGI; +GLEW_FUN_EXPORT PFNGLCOLORTABLESGIPROC __glewColorTableSGI; +GLEW_FUN_EXPORT PFNGLCOPYCOLORTABLESGIPROC __glewCopyColorTableSGI; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVSGIPROC __glewGetColorTableParameterfvSGI; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVSGIPROC __glewGetColorTableParameterivSGI; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLESGIPROC __glewGetColorTableSGI; + +GLEW_FUN_EXPORT PFNGLFINISHTEXTURESUNXPROC __glewFinishTextureSUNX; + +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORBSUNPROC __glewGlobalAlphaFactorbSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORDSUNPROC __glewGlobalAlphaFactordSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORFSUNPROC __glewGlobalAlphaFactorfSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORISUNPROC __glewGlobalAlphaFactoriSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORSSUNPROC __glewGlobalAlphaFactorsSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUBSUNPROC __glewGlobalAlphaFactorubSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUISUNPROC __glewGlobalAlphaFactoruiSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUSSUNPROC __glewGlobalAlphaFactorusSUN; + +GLEW_FUN_EXPORT PFNGLREADVIDEOPIXELSSUNPROC __glewReadVideoPixelsSUN; + +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEPOINTERSUNPROC __glewReplacementCodePointerSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUBSUNPROC __glewReplacementCodeubSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUBVSUNPROC __glewReplacementCodeubvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUISUNPROC __glewReplacementCodeuiSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVSUNPROC __glewReplacementCodeuivSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUSSUNPROC __glewReplacementCodeusSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUSVSUNPROC __glewReplacementCodeusvSUN; + +GLEW_FUN_EXPORT PFNGLCOLOR3FVERTEX3FSUNPROC __glewColor3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLCOLOR3FVERTEX3FVSUNPROC __glewColor3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewColor4fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewColor4fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX2FSUNPROC __glewColor4ubVertex2fSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX2FVSUNPROC __glewColor4ubVertex2fvSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX3FSUNPROC __glewColor4ubVertex3fSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX3FVSUNPROC __glewColor4ubVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLNORMAL3FVERTEX3FSUNPROC __glewNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLNORMAL3FVERTEX3FVSUNPROC __glewNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC __glewReplacementCodeuiColor3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC __glewReplacementCodeuiColor4ubVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC __glewReplacementCodeuiColor4ubVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC __glewReplacementCodeuiVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC __glewReplacementCodeuiVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC __glewTexCoord2fColor3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC __glewTexCoord2fColor3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC __glewTexCoord2fColor4ubVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC __glewTexCoord2fColor4ubVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FVERTEX3FSUNPROC __glewTexCoord2fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FVERTEX3FVSUNPROC __glewTexCoord2fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD4FVERTEX4FSUNPROC __glewTexCoord4fVertex4fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD4FVERTEX4FVSUNPROC __glewTexCoord4fVertex4fvSUN; + +GLEW_FUN_EXPORT PFNGLADDSWAPHINTRECTWINPROC __glewAddSwapHintRectWIN; + +#if defined(GLEW_MX) && !defined(_WIN32) +struct GLEWContextStruct +{ +#endif /* GLEW_MX */ + +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_1; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2_1; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_3; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_4; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_5; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_2_0; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_2_1; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_0; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_1; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_2; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_3; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_0; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_1; +GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_tbuffer; +GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_texture_compression_FXT1; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_blend_minmax_factor; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_conservative_depth; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_debug_output; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_depth_clamp_separate; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_draw_buffers_blend; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_name_gen_delete; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_performance_monitor; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_sample_positions; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_seamless_cubemap_per_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_shader_stencil_export; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_texture_texture4; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_transform_feedback3_lines_triangles; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_tessellator; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_aux_depth_stencil; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_client_storage; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_element_array; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_fence; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_float_pixels; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_flush_buffer_range; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_object_purgeable; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_pixel_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_rgb_422; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_row_bytes; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_specular_vector; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_texture_range; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_transform_hint; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_object; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_range; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_program_evaluators; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_ycbcr_422; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_ES2_compatibility; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_blend_func_extended; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_cl_event; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_color_buffer_float; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compatibility; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_copy_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_debug_output; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_buffer_float; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_buffers; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_buffers_blend; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_elements_base_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_indirect; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_instanced; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_explicit_attrib_location; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_coord_conventions; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program_shadow; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_sRGB; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_geometry_shader4; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_get_program_binary; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_gpu_shader5; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_gpu_shader_fp64; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_pixel; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_imaging; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_instanced_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_map_buffer_range; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_matrix_palette; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multitexture; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query2; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_pixel_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_parameters; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_sprite; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_provoking_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robustness; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sample_shading; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sampler_objects; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_seamless_cube_map; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_separate_shader_objects; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_bit_encoding; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_objects; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_precision; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_stencil_export; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_subroutine; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_texture_lod; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_100; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_include; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow_ambient; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sync; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_tessellation_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_border_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object_rgb32; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_bptc; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_rgtc; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_cube_map; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_cube_map_array; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_add; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_combine; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_crossbar; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_dot3; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_float; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_gather; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_mirrored_repeat; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_non_power_of_two; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_query_lod; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rectangle; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rg; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rgb10_a2ui; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_swizzle; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_timer_query; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback2; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback3; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transpose_matrix; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_uniform_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_bgra; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_attrib_64bit; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_blend; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_program; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_type_2_10_10_10_rev; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_viewport_array; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_window_pos; +GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_point_sprites; +GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_texture_env_combine3; +GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_texture_env_route; +GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_vertex_shader_output_point_size; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_draw_buffers; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_element_array; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_envmap_bumpmap; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_fragment_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_map_object_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_meminfo; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_pn_triangles; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_separate_stencil; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_shader_texture_lod; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_text_fragment_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_compression_3dc; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_env_combine3; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_float; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_mirror_once; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_array_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_attrib_array_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_streams; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_422_pixels; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_Cg_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_abgr; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_bgra; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_bindable_uniform; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_color; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_equation_separate; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_func_separate; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_logic_op; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_minmax; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_subtract; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_clip_volume_hint; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cmyka; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_color_subtable; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_compiled_vertex_array; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_convolution; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_coordinate_frame; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_copy_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cull_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_depth_bounds_test; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_direct_state_access; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_buffers2; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_instanced; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_range_elements; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fog_coord; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fragment_lighting; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_blit; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_sRGB; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_geometry_shader4; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_gpu_program_parameters; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_gpu_shader4; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_histogram; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_array_formats; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_func; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_material; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_light_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_misc_attribute; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multi_draw_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_depth_stencil; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_float; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_pixels; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_paletted_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_transform; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_transform_color_table; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_point_parameters; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_polygon_offset; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_provoking_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_rescale_normal; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_scene_marker; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_secondary_color; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_shader_objects; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_specular_color; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shader_image_load_store; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shadow_funcs; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shared_texture_palette; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_clear_tag; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_two_side; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_wrap; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_subtexture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture3D; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_array; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_dxt1; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_latc; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_rgtc; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_s3tc; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_cube_map; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_edge_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_add; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_combine; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_dot3; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_filter_anisotropic; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_integer; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_lod_bias; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_mirror_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_object; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_perturb_normal; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_rectangle; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_sRGB; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_sRGB_decode; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_shared_exponent; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_snorm; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_swizzle; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_timer_query; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_transform_feedback; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_array; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_array_bgra; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_attrib_64bit; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_weighting; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_x11_sync_object; +GLEW_VAR_EXPORT GLboolean __GLEW_GREMEDY_frame_terminator; +GLEW_VAR_EXPORT GLboolean __GLEW_GREMEDY_string_marker; +GLEW_VAR_EXPORT GLboolean __GLEW_HP_convolution_border_modes; +GLEW_VAR_EXPORT GLboolean __GLEW_HP_image_transform; +GLEW_VAR_EXPORT GLboolean __GLEW_HP_occlusion_test; +GLEW_VAR_EXPORT GLboolean __GLEW_HP_texture_lighting; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_cull_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_multimode_draw_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_rasterpos_clip; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_static_data; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_texture_mirrored_repeat; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_vertex_array_lists; +GLEW_VAR_EXPORT GLboolean __GLEW_INGR_color_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_INGR_interlace_read; +GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_parallel_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_texture_scissor; +GLEW_VAR_EXPORT GLboolean __GLEW_KTX_buffer_region; +GLEW_VAR_EXPORT GLboolean __GLEW_MESAX_texture_stack; +GLEW_VAR_EXPORT GLboolean __GLEW_MESA_pack_invert; +GLEW_VAR_EXPORT GLboolean __GLEW_MESA_resize_buffers; +GLEW_VAR_EXPORT GLboolean __GLEW_MESA_window_pos; +GLEW_VAR_EXPORT GLboolean __GLEW_MESA_ycbcr_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_NVX_gpu_memory_info; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_blend_square; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_conditional_render; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_depth_to_color; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_image; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_buffer_float; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_range_unclamped; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_evaluators; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_explicit_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fence; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_float_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fog_distance; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program_option; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_framebuffer_multisample_coverage; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_program4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_shader4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program5; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program_fp64; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_shader5; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_half_float; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_light_max_exponent; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_multisample_coverage; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_multisample_filter_hint; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_occlusion_query; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_packed_depth_stencil; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_parameter_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_parameter_buffer_object2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_pixel_data_range; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_point_sprite; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_present_video; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_primitive_restart; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_buffer_load; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_tessellation_program5; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_emboss; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_reflection; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_barrier; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_compression_vtc; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_env_combine4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_expand_normal; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_rectangle; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader3; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_transform_feedback; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_transform_feedback2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vdpau_interop; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_array_range; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_array_range2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_attrib_integer_64bit; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_buffer_unified_memory; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program1_1; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program2_option; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program3; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_video_capture; +GLEW_VAR_EXPORT GLboolean __GLEW_OES_byte_coordinates; +GLEW_VAR_EXPORT GLboolean __GLEW_OES_compressed_paletted_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_OES_read_format; +GLEW_VAR_EXPORT GLboolean __GLEW_OES_single_precision; +GLEW_VAR_EXPORT GLboolean __GLEW_OML_interlace; +GLEW_VAR_EXPORT GLboolean __GLEW_OML_resample; +GLEW_VAR_EXPORT GLboolean __GLEW_OML_subsample; +GLEW_VAR_EXPORT GLboolean __GLEW_PGI_misc_hints; +GLEW_VAR_EXPORT GLboolean __GLEW_PGI_vertex_hints; +GLEW_VAR_EXPORT GLboolean __GLEW_REND_screen_coordinates; +GLEW_VAR_EXPORT GLboolean __GLEW_S3_s3tc; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_color_range; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_detail_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_fog_function; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_generate_mipmap; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_pixel_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_point_line_texgen; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_sharpen_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture4D; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_border_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_edge_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_filter4; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_lod; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_select; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async_histogram; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async_pixel; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_blend_alpha_minmax; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_clipmap; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_convolution_accuracy; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_depth_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_flush_raster; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fog_offset; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fog_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fragment_specular_lighting; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_framezoom; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_interlace; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_ir_instrument1; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_list_priority; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_pixel_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_pixel_texture_bits; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_reference_plane; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_resample; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_shadow; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_shadow_ambient; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_sprite; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_tag_sample_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_add_env; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_coordinate_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_lod_bias; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_multi_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_range; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_scale_bias; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_vertex_preclip; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_vertex_preclip_hint; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_ycrcb; +GLEW_VAR_EXPORT GLboolean __GLEW_SGI_color_matrix; +GLEW_VAR_EXPORT GLboolean __GLEW_SGI_color_table; +GLEW_VAR_EXPORT GLboolean __GLEW_SGI_texture_color_table; +GLEW_VAR_EXPORT GLboolean __GLEW_SUNX_constant_data; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_convolution_border_modes; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_global_alpha; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_mesh_array; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_read_video_pixels; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_slice_accum; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_triangle_list; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_WIN_phong_shading; +GLEW_VAR_EXPORT GLboolean __GLEW_WIN_specular_fog; +GLEW_VAR_EXPORT GLboolean __GLEW_WIN_swap_hint; + +#ifdef GLEW_MX +}; /* GLEWContextStruct */ +#endif /* GLEW_MX */ + +/* ------------------------------------------------------------------------- */ + +/* error codes */ +#define GLEW_OK 0 +#define GLEW_NO_ERROR 0 +#define GLEW_ERROR_NO_GL_VERSION 1 /* missing GL version */ +#define GLEW_ERROR_GL_VERSION_10_ONLY 2 /* Need at least OpenGL 1.1 */ +#define GLEW_ERROR_GLX_VERSION_11_ONLY 3 /* Need at least GLX 1.2 */ + +/* string codes */ +#define GLEW_VERSION 1 +#define GLEW_VERSION_MAJOR 2 +#define GLEW_VERSION_MINOR 3 +#define GLEW_VERSION_MICRO 4 + +/* API */ +#ifdef GLEW_MX + +typedef struct GLEWContextStruct GLEWContext; +GLEWAPI GLenum glewContextInit (GLEWContext* ctx); +GLEWAPI GLboolean glewContextIsSupported (const GLEWContext* ctx, const char* name); + +#define glewInit() glewContextInit(glewGetContext()) +#define glewIsSupported(x) glewContextIsSupported(glewGetContext(), x) +#define glewIsExtensionSupported(x) glewIsSupported(x) + +#define GLEW_GET_VAR(x) (*(const GLboolean*)&(glewGetContext()->x)) +#ifdef _WIN32 +# define GLEW_GET_FUN(x) glewGetContext()->x +#else +# define GLEW_GET_FUN(x) x +#endif + +#else /* GLEW_MX */ + +GLEWAPI GLenum glewInit (); +GLEWAPI GLboolean glewIsSupported (const char* name); +#define glewIsExtensionSupported(x) glewIsSupported(x) + +#define GLEW_GET_VAR(x) (*(const GLboolean*)&x) +#define GLEW_GET_FUN(x) x + +#endif /* GLEW_MX */ + +GLEWAPI GLboolean glewExperimental; +GLEWAPI GLboolean glewGetExtension (const char* name); +GLEWAPI const GLubyte* glewGetErrorString (GLenum error); +GLEWAPI const GLubyte* glewGetString (GLenum name); + +#ifdef __cplusplus +} +#endif + +#ifdef GLEW_APIENTRY_DEFINED +#undef GLEW_APIENTRY_DEFINED +#undef APIENTRY +#undef GLAPIENTRY +#define GLAPIENTRY +#endif + +#ifdef GLEW_CALLBACK_DEFINED +#undef GLEW_CALLBACK_DEFINED +#undef CALLBACK +#endif + +#ifdef GLEW_WINGDIAPI_DEFINED +#undef GLEW_WINGDIAPI_DEFINED +#undef WINGDIAPI +#endif + +#undef GLAPI +/* #undef GLEWAPI */ + +#endif /* __glew_h__ */ diff --git a/Glut/GL/glext.h b/Glut/GL/glext.h new file mode 100644 index 0000000..10c2bc0 --- /dev/null +++ b/Glut/GL/glext.h @@ -0,0 +1,3326 @@ +#ifndef __glext_h_ +#define __glext_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright 1998, 1999, 2000, 2001, NVIDIA Corporation. +** All rights Reserved. +** +** THE INFORMATION CONTAINED HEREIN IS PROPRIETARY AND CONFIDENTIAL TO +** NVIDIA, CORPORATION. USE, REPRODUCTION OR DISCLOSURE TO ANY THIRD PARTY +** IS SUBJECT TO WRITTEN PRE-APPROVAL BY NVIDIA, CORPORATION. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +*/ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) +#define WIN32_LEAN_AND_MEAN 1 +#include +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif + +/*************************************************************/ + +/* Header file version number, required by OpenGL ABI for Linux */ +#define GL_GLEXT_VERSION 6 + +#ifndef GL_VERSION_1_2 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 +#define GL_FUNC_ADD 0x8006 +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_BLEND_EQUATION 0x8009 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_CONVOLUTION_1D 0x8010 +#define GL_CONVOLUTION_2D 0x8011 +#define GL_SEPARABLE_2D 0x8012 +#define GL_CONVOLUTION_BORDER_MODE 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS 0x8015 +#define GL_REDUCE 0x8016 +#define GL_CONVOLUTION_FORMAT 0x8017 +#define GL_CONVOLUTION_WIDTH 0x8018 +#define GL_CONVOLUTION_HEIGHT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 +#define GL_HISTOGRAM 0x8024 +#define GL_PROXY_HISTOGRAM 0x8025 +#define GL_HISTOGRAM_WIDTH 0x8026 +#define GL_HISTOGRAM_FORMAT 0x8027 +#define GL_HISTOGRAM_RED_SIZE 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C +#define GL_HISTOGRAM_SINK 0x802D +#define GL_MINMAX 0x802E +#define GL_MINMAX_FORMAT 0x802F +#define GL_MINMAX_SINK 0x8030 +#define GL_TABLE_TOO_LARGE 0x8031 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_RESCALE_NORMAL 0x803A +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_COLOR_MATRIX 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA +#define GL_COLOR_TABLE 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 +#define GL_PROXY_COLOR_TABLE 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 +#define GL_COLOR_TABLE_SCALE 0x80D6 +#define GL_COLOR_TABLE_BIAS 0x80D7 +#define GL_COLOR_TABLE_FORMAT 0x80D8 +#define GL_COLOR_TABLE_WIDTH 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#endif + +#ifndef GL_ARB_multitexture +#define GL_TEXTURE0_ARB 0x84C0 +#define GL_TEXTURE1_ARB 0x84C1 +#define GL_TEXTURE2_ARB 0x84C2 +#define GL_TEXTURE3_ARB 0x84C3 +#define GL_TEXTURE4_ARB 0x84C4 +#define GL_TEXTURE5_ARB 0x84C5 +#define GL_TEXTURE6_ARB 0x84C6 +#define GL_TEXTURE7_ARB 0x84C7 +#define GL_TEXTURE8_ARB 0x84C8 +#define GL_TEXTURE9_ARB 0x84C9 +#define GL_TEXTURE10_ARB 0x84CA +#define GL_TEXTURE11_ARB 0x84CB +#define GL_TEXTURE12_ARB 0x84CC +#define GL_TEXTURE13_ARB 0x84CD +#define GL_TEXTURE14_ARB 0x84CE +#define GL_TEXTURE15_ARB 0x84CF +#define GL_TEXTURE16_ARB 0x84D0 +#define GL_TEXTURE17_ARB 0x84D1 +#define GL_TEXTURE18_ARB 0x84D2 +#define GL_TEXTURE19_ARB 0x84D3 +#define GL_TEXTURE20_ARB 0x84D4 +#define GL_TEXTURE21_ARB 0x84D5 +#define GL_TEXTURE22_ARB 0x84D6 +#define GL_TEXTURE23_ARB 0x84D7 +#define GL_TEXTURE24_ARB 0x84D8 +#define GL_TEXTURE25_ARB 0x84D9 +#define GL_TEXTURE26_ARB 0x84DA +#define GL_TEXTURE27_ARB 0x84DB +#define GL_TEXTURE28_ARB 0x84DC +#define GL_TEXTURE29_ARB 0x84DD +#define GL_TEXTURE30_ARB 0x84DE +#define GL_TEXTURE31_ARB 0x84DF +#define GL_ACTIVE_TEXTURE_ARB 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 +#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 +#endif + +#ifndef GL_ARB_transpose_matrix +#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6 +#endif + +#ifndef GL_ARB_multisample +#define GL_MULTISAMPLE_ARB 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F +#define GL_SAMPLE_COVERAGE_ARB 0x80A0 +#define GL_SAMPLE_BUFFERS_ARB 0x80A8 +#define GL_SAMPLES_ARB 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB +#define GL_MULTISAMPLE_BIT_ARB 0x20000000 +#endif + +#ifndef GL_ARB_texture_cube_map +#define GL_NORMAL_MAP_ARB 0x8511 +#define GL_REFLECTION_MAP_ARB 0x8512 +#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C +#endif + +#ifndef GL_ARB_texture_compression +#define GL_COMPRESSED_ALPHA_ARB 0x84E9 +#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB +#define GL_COMPRESSED_INTENSITY_ARB 0x84EC +#define GL_COMPRESSED_RGB_ARB 0x84ED +#define GL_COMPRESSED_RGBA_ARB 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF +#define GL_TEXTURE_IMAGE_SIZE_ARB 0x86A0 +#define GL_TEXTURE_COMPRESSED_ARB 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 +#endif + +#ifndef GL_EXT_abgr +#define GL_ABGR_EXT 0x8000 +#endif + +#ifndef GL_EXT_blend_color +#define GL_CONSTANT_COLOR_EXT 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002 +#define GL_CONSTANT_ALPHA_EXT 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004 +#define GL_BLEND_COLOR_EXT 0x8005 +#endif + +#ifndef GL_EXT_polygon_offset +#define GL_POLYGON_OFFSET_EXT 0x8037 +#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038 +#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039 +#endif + +#ifndef GL_EXT_texture +#define GL_ALPHA4_EXT 0x803B +#define GL_ALPHA8_EXT 0x803C +#define GL_ALPHA12_EXT 0x803D +#define GL_ALPHA16_EXT 0x803E +#define GL_LUMINANCE4_EXT 0x803F +#define GL_LUMINANCE8_EXT 0x8040 +#define GL_LUMINANCE12_EXT 0x8041 +#define GL_LUMINANCE16_EXT 0x8042 +#define GL_LUMINANCE4_ALPHA4_EXT 0x8043 +#define GL_LUMINANCE6_ALPHA2_EXT 0x8044 +#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +#define GL_LUMINANCE12_ALPHA4_EXT 0x8046 +#define GL_LUMINANCE12_ALPHA12_EXT 0x8047 +#define GL_LUMINANCE16_ALPHA16_EXT 0x8048 +#define GL_INTENSITY_EXT 0x8049 +#define GL_INTENSITY4_EXT 0x804A +#define GL_INTENSITY8_EXT 0x804B +#define GL_INTENSITY12_EXT 0x804C +#define GL_INTENSITY16_EXT 0x804D +#define GL_RGB2_EXT 0x804E +#define GL_RGB4_EXT 0x804F +#define GL_RGB5_EXT 0x8050 +#define GL_RGB8_EXT 0x8051 +#define GL_RGB10_EXT 0x8052 +#define GL_RGB12_EXT 0x8053 +#define GL_RGB16_EXT 0x8054 +#define GL_RGBA2_EXT 0x8055 +#define GL_RGBA4_EXT 0x8056 +#define GL_RGB5_A1_EXT 0x8057 +#define GL_RGBA8_EXT 0x8058 +#define GL_RGB10_A2_EXT 0x8059 +#define GL_RGBA12_EXT 0x805A +#define GL_RGBA16_EXT 0x805B +#define GL_TEXTURE_RED_SIZE_EXT 0x805C +#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D +#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E +#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061 +#define GL_REPLACE_EXT 0x8062 +#define GL_PROXY_TEXTURE_1D_EXT 0x8063 +#define GL_PROXY_TEXTURE_2D_EXT 0x8064 +#define GL_TEXTURE_TOO_LARGE_EXT 0x8065 +#endif + +#ifndef GL_EXT_texture3D +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_SKIP_IMAGES_EXT 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_3D_EXT 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_PROXY_TEXTURE_3D_EXT 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_DEPTH_EXT 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_TEXTURE_WRAP_R_EXT 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 +#endif + +#ifndef GL_SGIS_texture_filter4 +#define GL_FILTER4_SGIS 0x8146 +#define GL_TEXTURE_FILTER4_SIZE_SGIS 0x8147 +#endif + +#ifndef GL_EXT_subtexture +#endif + +#ifndef GL_EXT_copy_texture +#endif + +#ifndef GL_EXT_histogram +#define GL_HISTOGRAM_EXT 0x8024 +#define GL_PROXY_HISTOGRAM_EXT 0x8025 +#define GL_HISTOGRAM_WIDTH_EXT 0x8026 +#define GL_HISTOGRAM_FORMAT_EXT 0x8027 +#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C +#define GL_HISTOGRAM_SINK_EXT 0x802D +#define GL_MINMAX_EXT 0x802E +#define GL_MINMAX_FORMAT_EXT 0x802F +#define GL_MINMAX_SINK_EXT 0x8030 +#define GL_TABLE_TOO_LARGE_EXT 0x8031 +#endif + +#ifndef GL_EXT_convolution +#define GL_CONVOLUTION_1D_EXT 0x8010 +#define GL_CONVOLUTION_2D_EXT 0x8011 +#define GL_SEPARABLE_2D_EXT 0x8012 +#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015 +#define GL_REDUCE_EXT 0x8016 +#define GL_CONVOLUTION_FORMAT_EXT 0x8017 +#define GL_CONVOLUTION_WIDTH_EXT 0x8018 +#define GL_CONVOLUTION_HEIGHT_EXT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 +#endif + +#ifndef GL_SGI_color_matrix +#define GL_COLOR_MATRIX_SGI 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB +#endif + +#ifndef GL_SGI_color_table +#define GL_COLOR_TABLE_SGI 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2 +#define GL_PROXY_COLOR_TABLE_SGI 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5 +#define GL_COLOR_TABLE_SCALE_SGI 0x80D6 +#define GL_COLOR_TABLE_BIAS_SGI 0x80D7 +#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8 +#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF +#endif + +#ifndef GL_SGIS_pixel_texture +#define GL_PIXEL_TEXTURE_SGIS 0x8353 +#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354 +#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355 +#define GL_PIXEL_GROUP_COLOR_SGIS 0x8356 +#endif + +#ifndef GL_SGIX_pixel_texture +#define GL_PIXEL_TEX_BUM_SGIX 0x8139 +#define GL_PIXEL_TEX_BUM_MODE_SGIX 0x832B +#endif + +#ifndef GL_SGIS_texture4D +#define GL_PACK_SKIP_VOLUMES_SGIS 0x8130 +#define GL_PACK_IMAGE_DEPTH_SGIS 0x8131 +#define GL_UNPACK_SKIP_VOLUMES_SGIS 0x8132 +#define GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133 +#define GL_TEXTURE_4D_SGIS 0x8134 +#define GL_PROXY_TEXTURE_4D_SGIS 0x8135 +#define GL_TEXTURE_4DSIZE_SGIS 0x8136 +#define GL_TEXTURE_WRAP_Q_SGIS 0x8137 +#define GL_MAX_4D_TEXTURE_SIZE_SGIS 0x8138 +#define GL_TEXTURE_4D_BINDING_SGIS 0x814F +#endif + +#ifndef GL_SGI_texture_color_table +#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC +#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD +#endif + +#ifndef GL_EXT_cmyka +#define GL_CMYK_EXT 0x800C +#define GL_CMYKA_EXT 0x800D +#define GL_PACK_CMYK_HINT_EXT 0x800E +#define GL_UNPACK_CMYK_HINT_EXT 0x800F +#endif + +#ifndef GL_EXT_texture_object +#define GL_TEXTURE_PRIORITY_EXT 0x8066 +#define GL_TEXTURE_RESIDENT_EXT 0x8067 +#define GL_TEXTURE_1D_BINDING_EXT 0x8068 +#define GL_TEXTURE_2D_BINDING_EXT 0x8069 +#define GL_TEXTURE_3D_BINDING_EXT 0x806A +#endif + +#ifndef GL_SGIS_detail_texture +#define GL_DETAIL_TEXTURE_2D_SGIS 0x8095 +#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096 +#define GL_LINEAR_DETAIL_SGIS 0x8097 +#define GL_LINEAR_DETAIL_ALPHA_SGIS 0x8098 +#define GL_LINEAR_DETAIL_COLOR_SGIS 0x8099 +#define GL_DETAIL_TEXTURE_LEVEL_SGIS 0x809A +#define GL_DETAIL_TEXTURE_MODE_SGIS 0x809B +#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C +#endif + +#ifndef GL_SGIS_sharpen_texture +#define GL_LINEAR_SHARPEN_SGIS 0x80AD +#define GL_LINEAR_SHARPEN_ALPHA_SGIS 0x80AE +#define GL_LINEAR_SHARPEN_COLOR_SGIS 0x80AF +#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0 +#endif + +#ifndef GL_EXT_packed_pixels +#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036 +#endif + +#ifndef GL_SGIS_texture_lod +#define GL_TEXTURE_MIN_LOD_SGIS 0x813A +#define GL_TEXTURE_MAX_LOD_SGIS 0x813B +#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C +#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D +#endif + +#ifndef GL_SGIS_multisample +#define GL_MULTISAMPLE_SGIS 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F +#define GL_SAMPLE_MASK_SGIS 0x80A0 +#define GL_1PASS_SGIS 0x80A1 +#define GL_2PASS_0_SGIS 0x80A2 +#define GL_2PASS_1_SGIS 0x80A3 +#define GL_4PASS_0_SGIS 0x80A4 +#define GL_4PASS_1_SGIS 0x80A5 +#define GL_4PASS_2_SGIS 0x80A6 +#define GL_4PASS_3_SGIS 0x80A7 +#define GL_SAMPLE_BUFFERS_SGIS 0x80A8 +#define GL_SAMPLES_SGIS 0x80A9 +#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA +#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB +#define GL_SAMPLE_PATTERN_SGIS 0x80AC +#endif + +#ifndef GL_EXT_rescale_normal +#define GL_RESCALE_NORMAL_EXT 0x803A +#endif + +#ifndef GL_EXT_vertex_array +#define GL_VERTEX_ARRAY_EXT 0x8074 +#define GL_NORMAL_ARRAY_EXT 0x8075 +#define GL_COLOR_ARRAY_EXT 0x8076 +#define GL_INDEX_ARRAY_EXT 0x8077 +#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078 +#define GL_EDGE_FLAG_ARRAY_EXT 0x8079 +#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A +#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B +#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C +#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D +#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E +#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F +#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080 +#define GL_COLOR_ARRAY_SIZE_EXT 0x8081 +#define GL_COLOR_ARRAY_TYPE_EXT 0x8082 +#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083 +#define GL_COLOR_ARRAY_COUNT_EXT 0x8084 +#define GL_INDEX_ARRAY_TYPE_EXT 0x8085 +#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086 +#define GL_INDEX_ARRAY_COUNT_EXT 0x8087 +#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A +#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B +#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C +#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D +#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E +#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F +#define GL_COLOR_ARRAY_POINTER_EXT 0x8090 +#define GL_INDEX_ARRAY_POINTER_EXT 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 +#endif + +#ifndef GL_EXT_misc_attribute +#endif + +#ifndef GL_SGIS_generate_mipmap +#define GL_GENERATE_MIPMAP_SGIS 0x8191 +#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 +#endif + +#ifndef GL_SGIX_clipmap +#define GL_LINEAR_CLIPMAP_LINEAR_SGIX 0x8170 +#define GL_TEXTURE_CLIPMAP_CENTER_SGIX 0x8171 +#define GL_TEXTURE_CLIPMAP_FRAME_SGIX 0x8172 +#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX 0x8173 +#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174 +#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175 +#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX 0x8176 +#define GL_MAX_CLIPMAP_DEPTH_SGIX 0x8177 +#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178 +#define GL_NEAREST_CLIPMAP_NEAREST_SGIX 0x844D +#define GL_NEAREST_CLIPMAP_LINEAR_SGIX 0x844E +#define GL_LINEAR_CLIPMAP_NEAREST_SGIX 0x844F +#endif + +#ifndef GL_SGIX_shadow +#define GL_TEXTURE_COMPARE_SGIX 0x819A +#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B +#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C +#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D +#endif + +#ifndef GL_SGIS_texture_edge_clamp +#define GL_CLAMP_TO_EDGE_SGIS 0x812F +#endif + +#ifndef GL_SGIS_texture_border_clamp +#define GL_CLAMP_TO_BORDER_SGIS 0x812D +#endif + +#ifndef GL_EXT_blend_minmax +#define GL_FUNC_ADD_EXT 0x8006 +#define GL_MIN_EXT 0x8007 +#define GL_MAX_EXT 0x8008 +#define GL_BLEND_EQUATION_EXT 0x8009 +#endif + +#ifndef GL_EXT_blend_subtract +#define GL_FUNC_SUBTRACT_EXT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B +#endif + +#ifndef GL_EXT_blend_logic_op +#endif + +#ifndef GL_SGIX_interlace +#define GL_INTERLACE_SGIX 0x8094 +#endif + +#ifndef GL_SGIX_pixel_tiles +#define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E +#define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F +#define GL_PIXEL_TILE_WIDTH_SGIX 0x8140 +#define GL_PIXEL_TILE_HEIGHT_SGIX 0x8141 +#define GL_PIXEL_TILE_GRID_WIDTH_SGIX 0x8142 +#define GL_PIXEL_TILE_GRID_HEIGHT_SGIX 0x8143 +#define GL_PIXEL_TILE_GRID_DEPTH_SGIX 0x8144 +#define GL_PIXEL_TILE_CACHE_SIZE_SGIX 0x8145 +#endif + +#ifndef GL_SGIS_texture_select +#define GL_DUAL_ALPHA4_SGIS 0x8110 +#define GL_DUAL_ALPHA8_SGIS 0x8111 +#define GL_DUAL_ALPHA12_SGIS 0x8112 +#define GL_DUAL_ALPHA16_SGIS 0x8113 +#define GL_DUAL_LUMINANCE4_SGIS 0x8114 +#define GL_DUAL_LUMINANCE8_SGIS 0x8115 +#define GL_DUAL_LUMINANCE12_SGIS 0x8116 +#define GL_DUAL_LUMINANCE16_SGIS 0x8117 +#define GL_DUAL_INTENSITY4_SGIS 0x8118 +#define GL_DUAL_INTENSITY8_SGIS 0x8119 +#define GL_DUAL_INTENSITY12_SGIS 0x811A +#define GL_DUAL_INTENSITY16_SGIS 0x811B +#define GL_DUAL_LUMINANCE_ALPHA4_SGIS 0x811C +#define GL_DUAL_LUMINANCE_ALPHA8_SGIS 0x811D +#define GL_QUAD_ALPHA4_SGIS 0x811E +#define GL_QUAD_ALPHA8_SGIS 0x811F +#define GL_QUAD_LUMINANCE4_SGIS 0x8120 +#define GL_QUAD_LUMINANCE8_SGIS 0x8121 +#define GL_QUAD_INTENSITY4_SGIS 0x8122 +#define GL_QUAD_INTENSITY8_SGIS 0x8123 +#define GL_DUAL_TEXTURE_SELECT_SGIS 0x8124 +#define GL_QUAD_TEXTURE_SELECT_SGIS 0x8125 +#endif + +#ifndef GL_SGIX_sprite +#define GL_SPRITE_SGIX 0x8148 +#define GL_SPRITE_MODE_SGIX 0x8149 +#define GL_SPRITE_AXIS_SGIX 0x814A +#define GL_SPRITE_TRANSLATION_SGIX 0x814B +#define GL_SPRITE_AXIAL_SGIX 0x814C +#define GL_SPRITE_OBJECT_ALIGNED_SGIX 0x814D +#define GL_SPRITE_EYE_ALIGNED_SGIX 0x814E +#endif + +#ifndef GL_SGIX_texture_multi_buffer +#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E +#endif + +#ifndef GL_SGIS_point_parameters +#define GL_POINT_SIZE_MIN_EXT 0x8126 +#define GL_POINT_SIZE_MIN_SGIS 0x8126 +#define GL_POINT_SIZE_MAX_EXT 0x8127 +#define GL_POINT_SIZE_MAX_SGIS 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 +#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128 +#define GL_DISTANCE_ATTENUATION_EXT 0x8129 +#define GL_DISTANCE_ATTENUATION_SGIS 0x8129 +#endif + +#ifndef GL_SGIX_instruments +#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180 +#define GL_INSTRUMENT_MEASUREMENTS_SGIX 0x8181 +#endif + +#ifndef GL_SGIX_texture_scale_bias +#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179 +#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A +#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B +#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C +#endif + +#ifndef GL_SGIX_framezoom +#define GL_FRAMEZOOM_SGIX 0x818B +#define GL_FRAMEZOOM_FACTOR_SGIX 0x818C +#define GL_MAX_FRAMEZOOM_FACTOR_SGIX 0x818D +#endif + +#ifndef GL_SGIX_tag_sample_buffer +#endif + +#ifndef GL_SGIX_reference_plane +#define GL_REFERENCE_PLANE_SGIX 0x817D +#define GL_REFERENCE_PLANE_EQUATION_SGIX 0x817E +#endif + +#ifndef GL_SGIX_flush_raster +#endif + +#ifndef GL_SGIX_depth_texture +#define GL_DEPTH_COMPONENT16_SGIX 0x81A5 +#define GL_DEPTH_COMPONENT24_SGIX 0x81A6 +#define GL_DEPTH_COMPONENT32_SGIX 0x81A7 +#endif + +#ifndef GL_SGIS_fog_function +#define GL_FOG_FUNC_SGIS 0x812A +#define GL_FOG_FUNC_POINTS_SGIS 0x812B +#define GL_MAX_FOG_FUNC_POINTS_SGIS 0x812C +#endif + +#ifndef GL_SGIX_fog_offset +#define GL_FOG_OFFSET_SGIX 0x8198 +#define GL_FOG_OFFSET_VALUE_SGIX 0x8199 +#endif + +#ifndef GL_HP_image_transform +#define GL_IMAGE_SCALE_X_HP 0x8155 +#define GL_IMAGE_SCALE_Y_HP 0x8156 +#define GL_IMAGE_TRANSLATE_X_HP 0x8157 +#define GL_IMAGE_TRANSLATE_Y_HP 0x8158 +#define GL_IMAGE_ROTATE_ANGLE_HP 0x8159 +#define GL_IMAGE_ROTATE_ORIGIN_X_HP 0x815A +#define GL_IMAGE_ROTATE_ORIGIN_Y_HP 0x815B +#define GL_IMAGE_MAG_FILTER_HP 0x815C +#define GL_IMAGE_MIN_FILTER_HP 0x815D +#define GL_IMAGE_CUBIC_WEIGHT_HP 0x815E +#define GL_CUBIC_HP 0x815F +#define GL_AVERAGE_HP 0x8160 +#define GL_IMAGE_TRANSFORM_2D_HP 0x8161 +#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162 +#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163 +#endif + +#ifndef GL_HP_convolution_border_modes +#define GL_IGNORE_BORDER_HP 0x8150 +#define GL_CONSTANT_BORDER_HP 0x8151 +#define GL_REPLICATE_BORDER_HP 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR_HP 0x8154 +#endif + +#ifndef GL_INGR_palette_buffer +#endif + +#ifndef GL_SGIX_texture_add_env +#define GL_TEXTURE_ENV_BIAS_SGIX 0x80BE +#endif + +#ifndef GL_EXT_color_subtable +#endif + +#ifndef GL_PGI_vertex_hints +#define GL_VERTEX_DATA_HINT_PGI 0x1A22A +#define GL_VERTEX_CONSISTENT_HINT_PGI 0x1A22B +#define GL_MATERIAL_SIDE_HINT_PGI 0x1A22C +#define GL_MAX_VERTEX_HINT_PGI 0x1A22D +#define GL_COLOR3_BIT_PGI 0x00010000 +#define GL_COLOR4_BIT_PGI 0x00020000 +#define GL_EDGEFLAG_BIT_PGI 0x00040000 +#define GL_INDEX_BIT_PGI 0x00080000 +#define GL_MAT_AMBIENT_BIT_PGI 0x00100000 +#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000 +#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000 +#define GL_MAT_EMISSION_BIT_PGI 0x00800000 +#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000 +#define GL_MAT_SHININESS_BIT_PGI 0x02000000 +#define GL_MAT_SPECULAR_BIT_PGI 0x04000000 +#define GL_NORMAL_BIT_PGI 0x08000000 +#define GL_TEXCOORD1_BIT_PGI 0x10000000 +#define GL_TEXCOORD2_BIT_PGI 0x20000000 +#define GL_TEXCOORD3_BIT_PGI 0x40000000 +#define GL_TEXCOORD4_BIT_PGI 0x80000000 +#define GL_VERTEX23_BIT_PGI 0x00000004 +#define GL_VERTEX4_BIT_PGI 0x00000008 +#endif + +#ifndef GL_PGI_misc_hints +#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8 +#define GL_CONSERVE_MEMORY_HINT_PGI 0x1A1FD +#define GL_RECLAIM_MEMORY_HINT_PGI 0x1A1FE +#define GL_NATIVE_GRAPHICS_HANDLE_PGI 0x1A202 +#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203 +#define GL_NATIVE_GRAPHICS_END_HINT_PGI 0x1A204 +#define GL_ALWAYS_FAST_HINT_PGI 0x1A20C +#define GL_ALWAYS_SOFT_HINT_PGI 0x1A20D +#define GL_ALLOW_DRAW_OBJ_HINT_PGI 0x1A20E +#define GL_ALLOW_DRAW_WIN_HINT_PGI 0x1A20F +#define GL_ALLOW_DRAW_FRG_HINT_PGI 0x1A210 +#define GL_ALLOW_DRAW_MEM_HINT_PGI 0x1A211 +#define GL_STRICT_DEPTHFUNC_HINT_PGI 0x1A216 +#define GL_STRICT_LIGHTING_HINT_PGI 0x1A217 +#define GL_STRICT_SCISSOR_HINT_PGI 0x1A218 +#define GL_FULL_STIPPLE_HINT_PGI 0x1A219 +#define GL_CLIP_NEAR_HINT_PGI 0x1A220 +#define GL_CLIP_FAR_HINT_PGI 0x1A221 +#define GL_WIDE_LINE_HINT_PGI 0x1A222 +#define GL_BACK_NORMALS_HINT_PGI 0x1A223 +#endif + +#ifndef GL_EXT_paletted_texture +#define GL_COLOR_INDEX1_EXT 0x80E2 +#define GL_COLOR_INDEX2_EXT 0x80E3 +#define GL_COLOR_INDEX4_EXT 0x80E4 +#define GL_COLOR_INDEX8_EXT 0x80E5 +#define GL_COLOR_INDEX12_EXT 0x80E6 +#define GL_COLOR_INDEX16_EXT 0x80E7 +#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED +#endif + +#ifndef GL_EXT_clip_volume_hint +#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0 +#endif + +#ifndef GL_SGIX_list_priority +#define GL_LIST_PRIORITY_SGIX 0x8182 +#endif + +#ifndef GL_SGIX_ir_instrument1 +#define GL_IR_INSTRUMENT1_SGIX 0x817F +#endif + +#ifndef GL_SGIX_calligraphic_fragment +#define GL_CALLIGRAPHIC_FRAGMENT_SGIX 0x8183 +#endif + +#ifndef GL_SGIX_texture_lod_bias +#define GL_TEXTURE_LOD_BIAS_S_SGIX 0x818E +#define GL_TEXTURE_LOD_BIAS_T_SGIX 0x818F +#define GL_TEXTURE_LOD_BIAS_R_SGIX 0x8190 +#endif + +#ifndef GL_SGIX_shadow_ambient +#define GL_SHADOW_AMBIENT_SGIX 0x80BF +#endif + +#ifndef GL_EXT_index_texture +#endif + +#ifndef GL_EXT_index_material +#define GL_INDEX_MATERIAL_EXT 0x81B8 +#define GL_INDEX_MATERIAL_PARAMETER_EXT 0x81B9 +#define GL_INDEX_MATERIAL_FACE_EXT 0x81BA +#endif + +#ifndef GL_EXT_index_func +#define GL_INDEX_TEST_EXT 0x81B5 +#define GL_INDEX_TEST_FUNC_EXT 0x81B6 +#define GL_INDEX_TEST_REF_EXT 0x81B7 +#endif + +#ifndef GL_EXT_index_array_formats +#define GL_IUI_V2F_EXT 0x81AD +#define GL_IUI_V3F_EXT 0x81AE +#define GL_IUI_N3F_V2F_EXT 0x81AF +#define GL_IUI_N3F_V3F_EXT 0x81B0 +#define GL_T2F_IUI_V2F_EXT 0x81B1 +#define GL_T2F_IUI_V3F_EXT 0x81B2 +#define GL_T2F_IUI_N3F_V2F_EXT 0x81B3 +#define GL_T2F_IUI_N3F_V3F_EXT 0x81B4 +#endif + +#ifndef GL_EXT_compiled_vertex_array +#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8 +#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9 +#endif + +#ifndef GL_EXT_cull_vertex +#define GL_CULL_VERTEX_EXT 0x81AA +#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB +#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC +#endif + +#ifndef GL_SGIX_ycrcb +#define GL_YCRCB_422_SGIX 0x81BB +#define GL_YCRCB_444_SGIX 0x81BC +#endif + +#ifndef GL_SGIX_fragment_lighting +#define GL_FRAGMENT_LIGHTING_SGIX 0x8400 +#define GL_FRAGMENT_COLOR_MATERIAL_SGIX 0x8401 +#define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402 +#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403 +#define GL_MAX_FRAGMENT_LIGHTS_SGIX 0x8404 +#define GL_MAX_ACTIVE_LIGHTS_SGIX 0x8405 +#define GL_CURRENT_RASTER_NORMAL_SGIX 0x8406 +#define GL_LIGHT_ENV_MODE_SGIX 0x8407 +#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408 +#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409 +#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A +#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B +#define GL_FRAGMENT_LIGHT0_SGIX 0x840C +#define GL_FRAGMENT_LIGHT1_SGIX 0x840D +#define GL_FRAGMENT_LIGHT2_SGIX 0x840E +#define GL_FRAGMENT_LIGHT3_SGIX 0x840F +#define GL_FRAGMENT_LIGHT4_SGIX 0x8410 +#define GL_FRAGMENT_LIGHT5_SGIX 0x8411 +#define GL_FRAGMENT_LIGHT6_SGIX 0x8412 +#define GL_FRAGMENT_LIGHT7_SGIX 0x8413 +#endif + +#ifndef GL_IBM_rasterpos_clip +#define GL_RASTER_POSITION_UNCLIPPED_IBM 0x19262 +#endif + +#ifndef GL_HP_texture_lighting +#define GL_TEXTURE_LIGHTING_MODE_HP 0x8167 +#define GL_TEXTURE_POST_SPECULAR_HP 0x8168 +#define GL_TEXTURE_PRE_SPECULAR_HP 0x8169 +#endif + +#ifndef GL_EXT_draw_range_elements +#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8 +#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9 +#endif + +#ifndef GL_WIN_phong_shading +#define GL_PHONG_WIN 0x80EA +#define GL_PHONG_HINT_WIN 0x80EB +#endif + +#ifndef GL_WIN_specular_fog +#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC +#endif + +#ifndef GL_EXT_light_texture +#define GL_FRAGMENT_MATERIAL_EXT 0x8349 +#define GL_FRAGMENT_NORMAL_EXT 0x834A +#define GL_FRAGMENT_COLOR_EXT 0x834C +#define GL_ATTENUATION_EXT 0x834D +#define GL_SHADOW_ATTENUATION_EXT 0x834E +#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F +#define GL_TEXTURE_LIGHT_EXT 0x8350 +#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351 +#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352 +/* reuse GL_FRAGMENT_DEPTH_EXT */ +#endif + +#ifndef GL_SGIX_blend_alpha_minmax +#define GL_ALPHA_MIN_SGIX 0x8320 +#define GL_ALPHA_MAX_SGIX 0x8321 +#endif + +#ifndef GL_EXT_bgra +#define GL_BGR_EXT 0x80E0 +#define GL_BGRA_EXT 0x80E1 +#endif + +#ifndef GL_INTEL_texture_scissor +#endif + +#ifndef GL_INTEL_parallel_arrays +#define GL_PARALLEL_ARRAYS_INTEL 0x83F4 +#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5 +#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6 +#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7 +#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8 +#endif + +#ifndef GL_HP_occlusion_test +#define GL_OCCLUSION_TEST_HP 0x8165 +#define GL_OCCLUSION_TEST_RESULT_HP 0x8166 +#endif + +#ifndef GL_EXT_pixel_transform +#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330 +#define GL_PIXEL_MAG_FILTER_EXT 0x8331 +#define GL_PIXEL_MIN_FILTER_EXT 0x8332 +#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333 +#define GL_CUBIC_EXT 0x8334 +#define GL_AVERAGE_EXT 0x8335 +#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336 +#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337 +#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338 +#endif + +#ifndef GL_EXT_pixel_transform_color_table +#endif + +#ifndef GL_EXT_shared_texture_palette +#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB +#endif + +#ifndef GL_EXT_separate_specular_color +#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 +#define GL_SINGLE_COLOR_EXT 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA +#endif + +#ifndef GL_EXT_secondary_color +#define GL_COLOR_SUM_EXT 0x8458 +#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D +#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E +#endif + +#ifndef GL_EXT_texture_perturb_normal +#define GL_PERTURB_EXT 0x85AE +#define GL_TEXTURE_NORMAL_EXT 0x85AF +#endif + +#ifndef GL_EXT_multi_draw_arrays +#endif + +#ifndef GL_EXT_fog_coord +#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450 +#define GL_FOG_COORDINATE_EXT 0x8451 +#define GL_FRAGMENT_DEPTH_EXT 0x8452 +#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456 +#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457 +#endif + +#ifndef GL_REND_screen_coordinates +#define GL_SCREEN_COORDINATES_REND 0x8490 +#define GL_INVERTED_SCREEN_W_REND 0x8491 +#endif + +#ifndef GL_EXT_coordinate_frame +#define GL_TANGENT_ARRAY_EXT 0x8439 +#define GL_BINORMAL_ARRAY_EXT 0x843A +#define GL_CURRENT_TANGENT_EXT 0x843B +#define GL_CURRENT_BINORMAL_EXT 0x843C +#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E +#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F +#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440 +#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441 +#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442 +#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443 +#define GL_MAP1_TANGENT_EXT 0x8444 +#define GL_MAP2_TANGENT_EXT 0x8445 +#define GL_MAP1_BINORMAL_EXT 0x8446 +#define GL_MAP2_BINORMAL_EXT 0x8447 +#endif + +#ifndef GL_EXT_texture_env_combine +#define GL_COMBINE_EXT 0x8570 +#define GL_COMBINE_RGB_EXT 0x8571 +#define GL_COMBINE_ALPHA_EXT 0x8572 +#define GL_RGB_SCALE_EXT 0x8573 +#define GL_ADD_SIGNED_EXT 0x8574 +#define GL_INTERPOLATE_EXT 0x8575 +#define GL_CONSTANT_EXT 0x8576 +#define GL_PRIMARY_COLOR_EXT 0x8577 +#define GL_PREVIOUS_EXT 0x8578 +#define GL_SOURCE0_RGB_EXT 0x8580 +#define GL_SOURCE1_RGB_EXT 0x8581 +#define GL_SOURCE2_RGB_EXT 0x8582 +#define GL_SOURCE3_RGB_EXT 0x8583 +#define GL_SOURCE4_RGB_EXT 0x8584 +#define GL_SOURCE5_RGB_EXT 0x8585 +#define GL_SOURCE6_RGB_EXT 0x8586 +#define GL_SOURCE7_RGB_EXT 0x8587 +#define GL_SOURCE0_ALPHA_EXT 0x8588 +#define GL_SOURCE1_ALPHA_EXT 0x8589 +#define GL_SOURCE2_ALPHA_EXT 0x858A +#define GL_SOURCE3_ALPHA_EXT 0x858B +#define GL_SOURCE4_ALPHA_EXT 0x858C +#define GL_SOURCE5_ALPHA_EXT 0x858D +#define GL_SOURCE6_ALPHA_EXT 0x858E +#define GL_SOURCE7_ALPHA_EXT 0x858F +#define GL_OPERAND0_RGB_EXT 0x8590 +#define GL_OPERAND1_RGB_EXT 0x8591 +#define GL_OPERAND2_RGB_EXT 0x8592 +#define GL_OPERAND3_RGB_EXT 0x8593 +#define GL_OPERAND4_RGB_EXT 0x8594 +#define GL_OPERAND5_RGB_EXT 0x8595 +#define GL_OPERAND6_RGB_EXT 0x8596 +#define GL_OPERAND7_RGB_EXT 0x8597 +#define GL_OPERAND0_ALPHA_EXT 0x8598 +#define GL_OPERAND1_ALPHA_EXT 0x8599 +#define GL_OPERAND2_ALPHA_EXT 0x859A +#define GL_OPERAND3_ALPHA_EXT 0x859B +#define GL_OPERAND4_ALPHA_EXT 0x859C +#define GL_OPERAND5_ALPHA_EXT 0x859D +#define GL_OPERAND6_ALPHA_EXT 0x859E +#define GL_OPERAND7_ALPHA_EXT 0x859F +#endif + +#ifndef GL_APPLE_specular_vector +#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0 +#endif + +#ifndef GL_APPLE_transform_hint +#define GL_TRANSFORM_HINT_APPLE 0x85B1 +#endif + +#ifndef GL_SGIX_fog_scale +#define GL_FOG_SCALE_SGIX 0x81FC +#define GL_FOG_SCALE_VALUE_SGIX 0x81FD +#endif + +#ifndef GL_SUNX_constant_data +#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5 +#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6 +#endif + +#ifndef GL_SUN_global_alpha +#define GL_GLOBAL_ALPHA_SUN 0x81D9 +#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA +#endif + +#ifndef GL_SUN_triangle_list +#define GL_RESTART_SUN 0x01 +#define GL_REPLACE_MIDDLE_SUN 0x02 +#define GL_REPLACE_OLDEST_SUN 0x03 +#define GL_TRIANGLE_LIST_SUN 0x81D7 +#define GL_REPLACEMENT_CODE_SUN 0x81D8 +#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0 +#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 +#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 +#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 +#define GL_R1UI_V3F_SUN 0x85C4 +#define GL_R1UI_C4UB_V3F_SUN 0x85C5 +#define GL_R1UI_C3F_V3F_SUN 0x85C6 +#define GL_R1UI_N3F_V3F_SUN 0x85C7 +#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8 +#define GL_R1UI_T2F_V3F_SUN 0x85C9 +#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA +#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB +#endif + +#ifndef GL_SUN_vertex +#endif + +#ifndef GL_EXT_blend_func_separate +#define GL_BLEND_DST_RGB_EXT 0x80C8 +#define GL_BLEND_SRC_RGB_EXT 0x80C9 +#define GL_BLEND_DST_ALPHA_EXT 0x80CA +#define GL_BLEND_SRC_ALPHA_EXT 0x80CB +#endif + +#ifndef GL_INGR_color_clamp +#define GL_RED_MIN_CLAMP_INGR 0x8560 +#define GL_GREEN_MIN_CLAMP_INGR 0x8561 +#define GL_BLUE_MIN_CLAMP_INGR 0x8562 +#define GL_ALPHA_MIN_CLAMP_INGR 0x8563 +#define GL_RED_MAX_CLAMP_INGR 0x8564 +#define GL_GREEN_MAX_CLAMP_INGR 0x8565 +#define GL_BLUE_MAX_CLAMP_INGR 0x8566 +#define GL_ALPHA_MAX_CLAMP_INGR 0x8567 +#endif + +#ifndef GL_INGR_interlace_read +#define GL_INTERLACE_READ_INGR 0x8568 +#endif + +#ifndef GL_EXT_stencil_wrap +#define GL_INCR_WRAP_EXT 0x8507 +#define GL_DECR_WRAP_EXT 0x8508 +#endif + +#ifndef GL_EXT_422_pixels +#define GL_422_EXT 0x80CC +#define GL_422_REV_EXT 0x80CD +#define GL_422_AVERAGE_EXT 0x80CE +#define GL_422_REV_AVERAGE_EXT 0x80CF +#endif + +#ifndef GL_NV_texgen_reflection +#define GL_NORMAL_MAP_NV 0x8511 +#define GL_REFLECTION_MAP_NV 0x8512 +#endif + +#ifndef GL_EXT_texture_cube_map +#define GL_NORMAL_MAP_EXT 0x8511 +#define GL_REFLECTION_MAP_EXT 0x8512 +#define GL_TEXTURE_CUBE_MAP_EXT 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C +#endif + +#ifndef GL_SUN_convolution_border_modes +#define GL_WRAP_BORDER_SUN 0x81D4 +#endif + +#ifndef GL_EXT_texture_env_add +#endif + +#ifndef GL_EXT_texture_lod_bias +#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD +#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500 +#define GL_TEXTURE_LOD_BIAS_EXT 0x8501 +#endif + +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#endif + +#ifndef GL_EXT_vertex_weighting +#define GL_MODELVIEW0_STACK_DEPTH_EXT GL_MODELVIEW_STACK_DEPTH +#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502 +#define GL_MODELVIEW0_MATRIX_EXT GL_MODELVIEW_MATRIX +#define GL_MODELVIEW_MATRIX1_EXT 0x8506 +#define GL_VERTEX_WEIGHTING_EXT 0x8509 +#define GL_MODELVIEW0_EXT GL_MODELVIEW +#define GL_MODELVIEW1_EXT 0x850A +#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B +#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C +#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D +#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E +#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F +#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 +#endif + +#ifndef GL_NV_light_max_exponent +#define GL_MAX_SHININESS_NV 0x8504 +#define GL_MAX_SPOT_EXPONENT_NV 0x8505 +#endif + +#ifndef GL_NV_vertex_array_range +#define GL_VERTEX_ARRAY_RANGE_NV 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E +#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F +#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520 +#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 +#endif + +#ifndef GL_NV_vertex_array_range2 +#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 +#endif + +#ifndef GL_NV_register_combiners +#define GL_REGISTER_COMBINERS_NV 0x8522 +#define GL_VARIABLE_A_NV 0x8523 +#define GL_VARIABLE_B_NV 0x8524 +#define GL_VARIABLE_C_NV 0x8525 +#define GL_VARIABLE_D_NV 0x8526 +#define GL_VARIABLE_E_NV 0x8527 +#define GL_VARIABLE_F_NV 0x8528 +#define GL_VARIABLE_G_NV 0x8529 +#define GL_CONSTANT_COLOR0_NV 0x852A +#define GL_CONSTANT_COLOR1_NV 0x852B +#define GL_PRIMARY_COLOR_NV 0x852C +#define GL_SECONDARY_COLOR_NV 0x852D +#define GL_SPARE0_NV 0x852E +#define GL_SPARE1_NV 0x852F +#define GL_DISCARD_NV 0x8530 +#define GL_E_TIMES_F_NV 0x8531 +#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532 +#define GL_UNSIGNED_IDENTITY_NV 0x8536 +#define GL_UNSIGNED_INVERT_NV 0x8537 +#define GL_EXPAND_NORMAL_NV 0x8538 +#define GL_EXPAND_NEGATE_NV 0x8539 +#define GL_HALF_BIAS_NORMAL_NV 0x853A +#define GL_HALF_BIAS_NEGATE_NV 0x853B +#define GL_SIGNED_IDENTITY_NV 0x853C +#define GL_SIGNED_NEGATE_NV 0x853D +#define GL_SCALE_BY_TWO_NV 0x853E +#define GL_SCALE_BY_FOUR_NV 0x853F +#define GL_SCALE_BY_ONE_HALF_NV 0x8540 +#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541 +#define GL_COMBINER_INPUT_NV 0x8542 +#define GL_COMBINER_MAPPING_NV 0x8543 +#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544 +#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545 +#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546 +#define GL_COMBINER_MUX_SUM_NV 0x8547 +#define GL_COMBINER_SCALE_NV 0x8548 +#define GL_COMBINER_BIAS_NV 0x8549 +#define GL_COMBINER_AB_OUTPUT_NV 0x854A +#define GL_COMBINER_CD_OUTPUT_NV 0x854B +#define GL_COMBINER_SUM_OUTPUT_NV 0x854C +#define GL_MAX_GENERAL_COMBINERS_NV 0x854D +#define GL_NUM_GENERAL_COMBINERS_NV 0x854E +#define GL_COLOR_SUM_CLAMP_NV 0x854F +#define GL_COMBINER0_NV 0x8550 +#define GL_COMBINER1_NV 0x8551 +#define GL_COMBINER2_NV 0x8552 +#define GL_COMBINER3_NV 0x8553 +#define GL_COMBINER4_NV 0x8554 +#define GL_COMBINER5_NV 0x8555 +#define GL_COMBINER6_NV 0x8556 +#define GL_COMBINER7_NV 0x8557 +/* reuse GL_TEXTURE0_ARB */ +/* reuse GL_TEXTURE1_ARB */ +/* reuse GL_ZERO */ +/* reuse GL_NONE */ +/* reuse GL_FOG */ +#endif + +#ifndef GL_NV_fog_distance +#define GL_FOG_DISTANCE_MODE_NV 0x855A +#define GL_EYE_RADIAL_NV 0x855B +#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C +/* reuse GL_EYE_PLANE */ +#endif + +#ifndef GL_NV_texgen_emboss +#define GL_EMBOSS_LIGHT_NV 0x855D +#define GL_EMBOSS_CONSTANT_NV 0x855E +#define GL_EMBOSS_MAP_NV 0x855F +#endif + +#ifndef GL_NV_blend_square +#endif + +#ifndef GL_NV_texture_env_combine4 +#define GL_COMBINE4_NV 0x8503 +#define GL_SOURCE3_RGB_NV 0x8583 +#define GL_SOURCE3_ALPHA_NV 0x858B +#define GL_OPERAND3_RGB_NV 0x8593 +#define GL_OPERAND3_ALPHA_NV 0x859B +#endif + + +#ifndef GL_MESA_resize_buffers +#endif + +#ifndef GL_MESA_window_pos +#endif + +#ifndef GL_EXT_texture_compression_s3tc +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 +#endif + +#ifndef GL_IBM_cull_vertex +#define GL_CULL_VERTEX_IBM 103050 +#endif + +#ifndef GL_IBM_multimode_draw_arrays +#endif + +#ifndef GL_IBM_vertex_array_lists +#define GL_VERTEX_ARRAY_LIST_IBM 103070 +#define GL_NORMAL_ARRAY_LIST_IBM 103071 +#define GL_COLOR_ARRAY_LIST_IBM 103072 +#define GL_INDEX_ARRAY_LIST_IBM 103073 +#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074 +#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075 +#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076 +#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077 +#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080 +#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081 +#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082 +#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083 +#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084 +#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085 +#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086 +#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087 +#endif + +#ifndef GL_SGIX_subsample +#define GL_PACK_SUBSAMPLE_RATE_SGIX 0x85A0 +#define GL_UNPACK_SUBSAMPLE_RATE_SGIX 0x85A1 +#define GL_PIXEL_SUBSAMPLE_4444_SGIX 0x85A2 +#define GL_PIXEL_SUBSAMPLE_2424_SGIX 0x85A3 +#define GL_PIXEL_SUBSAMPLE_4242_SGIX 0x85A4 +#endif + +#ifndef GL_SGIX_ycrcb_subsample +#endif + +#ifndef GL_SGIX_ycrcba +#define GL_YCRCB_SGIX 0x8318 +#define GL_YCRCBA_SGIX 0x8319 +#endif + +#ifndef GL_SGI_depth_pass_instrument +#define GL_DEPTH_PASS_INSTRUMENT_SGIX 0x8310 +#define GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX 0x8311 +#define GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX 0x8312 +#endif + +#ifndef GL_3DFX_texture_compression_FXT1 +#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0 +#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1 +#endif + +#ifndef GL_3DFX_multisample +#define GL_MULTISAMPLE_3DFX 0x86B2 +#define GL_SAMPLE_BUFFERS_3DFX 0x86B3 +#define GL_SAMPLES_3DFX 0x86B4 +#define GL_MULTISAMPLE_BIT_3DFX 0x20000000 +#endif + +#ifndef GL_3DFX_tbuffer +#endif + +#ifndef GL_EXT_multisample +#define GL_MULTISAMPLE_EXT 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F +#define GL_SAMPLE_MASK_EXT 0x80A0 +#define GL_1PASS_EXT 0x80A1 +#define GL_2PASS_0_EXT 0x80A2 +#define GL_2PASS_1_EXT 0x80A3 +#define GL_4PASS_0_EXT 0x80A4 +#define GL_4PASS_1_EXT 0x80A5 +#define GL_4PASS_2_EXT 0x80A6 +#define GL_4PASS_3_EXT 0x80A7 +#define GL_SAMPLE_BUFFERS_EXT 0x80A8 +#define GL_SAMPLES_EXT 0x80A9 +#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA +#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB +#define GL_SAMPLE_PATTERN_EXT 0x80AC +#endif + +#ifndef GL_SGIX_vertex_preclip +#define GL_VERTEX_PRECLIP_SGIX 0x83EE +#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF +#endif + +#ifndef GL_SGIX_convolution_accuracy +#define GL_CONVOLUTION_HINT_SGIX 0x8316 +#endif + +#ifndef GL_SGIX_resample +#define GL_PACK_RESAMPLE_SGIX 0x842C +#define GL_UNPACK_RESAMPLE_SGIX 0x842D +#define GL_RESAMPLE_REPLICATE_SGIX 0x842E +#define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F +#define GL_RESAMPLE_DECIMATE_SGIX 0x8430 +#endif + +#ifndef GL_SGIS_point_line_texgen +#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0 +#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1 +#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2 +#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3 +#define GL_EYE_POINT_SGIS 0x81F4 +#define GL_OBJECT_POINT_SGIS 0x81F5 +#define GL_EYE_LINE_SGIS 0x81F6 +#define GL_OBJECT_LINE_SGIS 0x81F7 +#endif + +#ifndef GL_SGIS_texture_color_mask +#define GL_TEXTURE_COLOR_WRITEMASK_SGIS 0x81EF +#endif + + +/*************************************************************/ + +#ifndef GL_VERSION_1_2 +#define GL_VERSION_1_2 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glBlendColor (GLclampf, GLclampf, GLclampf, GLclampf); +extern void APIENTRY glBlendEquation (GLenum); +extern void APIENTRY glDrawRangeElements (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); +extern void APIENTRY glColorTable (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glColorTableParameterfv (GLenum, GLenum, const GLfloat *); +extern void APIENTRY glColorTableParameteriv (GLenum, GLenum, const GLint *); +extern void APIENTRY glCopyColorTable (GLenum, GLenum, GLint, GLint, GLsizei); +extern void APIENTRY glGetColorTable (GLenum, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetColorTableParameterfv (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetColorTableParameteriv (GLenum, GLenum, GLint *); +extern void APIENTRY glColorSubTable (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glCopyColorSubTable (GLenum, GLsizei, GLint, GLint, GLsizei); +extern void APIENTRY glConvolutionFilter1D (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glConvolutionFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glConvolutionParameterf (GLenum, GLenum, GLfloat); +extern void APIENTRY glConvolutionParameterfv (GLenum, GLenum, const GLfloat *); +extern void APIENTRY glConvolutionParameteri (GLenum, GLenum, GLint); +extern void APIENTRY glConvolutionParameteriv (GLenum, GLenum, const GLint *); +extern void APIENTRY glCopyConvolutionFilter1D (GLenum, GLenum, GLint, GLint, GLsizei); +extern void APIENTRY glCopyConvolutionFilter2D (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei); +extern void APIENTRY glGetConvolutionFilter (GLenum, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetConvolutionParameterfv (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetConvolutionParameteriv (GLenum, GLenum, GLint *); +extern void APIENTRY glGetSeparableFilter (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *); +extern void APIENTRY glSeparableFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *); +extern void APIENTRY glGetHistogram (GLenum, GLboolean, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetHistogramParameterfv (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetHistogramParameteriv (GLenum, GLenum, GLint *); +extern void APIENTRY glGetMinmax (GLenum, GLboolean, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetMinmaxParameterfv (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetMinmaxParameteriv (GLenum, GLenum, GLint *); +extern void APIENTRY glHistogram (GLenum, GLsizei, GLenum, GLboolean); +extern void APIENTRY glMinmax (GLenum, GLenum, GLboolean); +extern void APIENTRY glResetHistogram (GLenum); +extern void APIENTRY glResetMinmax (GLenum); +extern void APIENTRY glTexImage3D (GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glCopyTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +typedef void (APIENTRY * PFNGLBLENDEQUATIONPROC) (GLenum mode); +typedef void (APIENTRY * PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); +typedef void (APIENTRY * PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (APIENTRY * PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (APIENTRY * PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); +typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); +typedef void (APIENTRY * PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +typedef void (APIENTRY * PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); +typedef void (APIENTRY * PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); +typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params); +typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params); +typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (APIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRY * PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); +typedef void (APIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); +typedef void (APIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); +typedef void (APIENTRY * PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (APIENTRY * PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (APIENTRY * PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (APIENTRY * PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (APIENTRY * PFNGLRESETHISTOGRAMPROC) (GLenum target); +typedef void (APIENTRY * PFNGLRESETMINMAXPROC) (GLenum target); +typedef void (APIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRY * PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#endif + +#ifndef GL_ARB_multitexture +#define GL_ARB_multitexture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glActiveTextureARB (GLenum); +extern void APIENTRY glClientActiveTextureARB (GLenum); +extern void APIENTRY glMultiTexCoord1dARB (GLenum, GLdouble); +extern void APIENTRY glMultiTexCoord1dvARB (GLenum, const GLdouble *); +extern void APIENTRY glMultiTexCoord1fARB (GLenum, GLfloat); +extern void APIENTRY glMultiTexCoord1fvARB (GLenum, const GLfloat *); +extern void APIENTRY glMultiTexCoord1iARB (GLenum, GLint); +extern void APIENTRY glMultiTexCoord1ivARB (GLenum, const GLint *); +extern void APIENTRY glMultiTexCoord1sARB (GLenum, GLshort); +extern void APIENTRY glMultiTexCoord1svARB (GLenum, const GLshort *); +extern void APIENTRY glMultiTexCoord2dARB (GLenum, GLdouble, GLdouble); +extern void APIENTRY glMultiTexCoord2dvARB (GLenum, const GLdouble *); +extern void APIENTRY glMultiTexCoord2fARB (GLenum, GLfloat, GLfloat); +extern void APIENTRY glMultiTexCoord2fvARB (GLenum, const GLfloat *); +extern void APIENTRY glMultiTexCoord2iARB (GLenum, GLint, GLint); +extern void APIENTRY glMultiTexCoord2ivARB (GLenum, const GLint *); +extern void APIENTRY glMultiTexCoord2sARB (GLenum, GLshort, GLshort); +extern void APIENTRY glMultiTexCoord2svARB (GLenum, const GLshort *); +extern void APIENTRY glMultiTexCoord3dARB (GLenum, GLdouble, GLdouble, GLdouble); +extern void APIENTRY glMultiTexCoord3dvARB (GLenum, const GLdouble *); +extern void APIENTRY glMultiTexCoord3fARB (GLenum, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glMultiTexCoord3fvARB (GLenum, const GLfloat *); +extern void APIENTRY glMultiTexCoord3iARB (GLenum, GLint, GLint, GLint); +extern void APIENTRY glMultiTexCoord3ivARB (GLenum, const GLint *); +extern void APIENTRY glMultiTexCoord3sARB (GLenum, GLshort, GLshort, GLshort); +extern void APIENTRY glMultiTexCoord3svARB (GLenum, const GLshort *); +extern void APIENTRY glMultiTexCoord4dARB (GLenum, GLdouble, GLdouble, GLdouble, GLdouble); +extern void APIENTRY glMultiTexCoord4dvARB (GLenum, const GLdouble *); +extern void APIENTRY glMultiTexCoord4fARB (GLenum, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glMultiTexCoord4fvARB (GLenum, const GLfloat *); +extern void APIENTRY glMultiTexCoord4iARB (GLenum, GLint, GLint, GLint, GLint); +extern void APIENTRY glMultiTexCoord4ivARB (GLenum, const GLint *); +extern void APIENTRY glMultiTexCoord4sARB (GLenum, GLshort, GLshort, GLshort, GLshort); +extern void APIENTRY glMultiTexCoord4svARB (GLenum, const GLshort *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (APIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v); +#endif + +#ifndef GL_ARB_transpose_matrix +#define GL_ARB_transpose_matrix 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glLoadTransposeMatrixfARB (const GLfloat *); +extern void APIENTRY glLoadTransposeMatrixdARB (const GLdouble *); +extern void APIENTRY glMultTransposeMatrixfARB (const GLfloat *); +extern void APIENTRY glMultTransposeMatrixdARB (const GLdouble *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); +typedef void (APIENTRY * PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); +typedef void (APIENTRY * PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); +typedef void (APIENTRY * PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); +#endif + +#ifndef GL_ARB_multisample +#define GL_ARB_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glSampleCoverageARB (GLclampf, GLboolean); +extern void APIENTRY glSamplePassARB (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert); +typedef void (APIENTRY * PFNGLSAMPLEPASSARBPROC) (GLenum pass); +#endif + +#ifndef GL_ARB_texture_env_add +#define GL_ARB_texture_env_add 1 +#endif + +#ifndef GL_ARB_texture_cube_map +#define GL_ARB_texture_cube_map 1 +#endif + +#ifndef GL_ARB_texture_compression +#define GL_ARB_texture_compression 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glCompressedTexImage3DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); +extern void APIENTRY glCompressedTexImage2DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); +extern void APIENTRY glCompressedTexImage1DARB (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *); +extern void APIENTRY glCompressedTexSubImage3DARB (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); +extern void APIENTRY glCompressedTexSubImage2DARB (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); +extern void APIENTRY glCompressedTexSubImage1DARB (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *); +extern void APIENTRY glGetCompressedTexImageARB (GLenum, GLint, void *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, void *img); +#endif + +#ifndef GL_EXT_abgr +#define GL_EXT_abgr 1 +#endif + +#ifndef GL_EXT_blend_color +#define GL_EXT_blend_color 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glBlendColorEXT (GLclampf, GLclampf, GLclampf, GLclampf); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +#endif + +#ifndef GL_EXT_polygon_offset +#define GL_EXT_polygon_offset 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glPolygonOffsetEXT (GLfloat, GLfloat); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias); +#endif + +#ifndef GL_EXT_texture +#define GL_EXT_texture 1 +#endif + +#ifndef GL_EXT_texture3D +#define GL_EXT_texture3D 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glTexImage3DEXT (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); +#endif + +#ifndef GL_SGIS_texture_filter4 +#define GL_SGIS_texture_filter4 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glGetTexFilterFuncSGIS (GLenum, GLenum, GLfloat *); +extern void APIENTRY glTexFilterFuncSGIS (GLenum, GLenum, GLsizei, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat *weights); +typedef void (APIENTRY * PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights); +#endif + +#ifndef GL_EXT_subtexture +#define GL_EXT_subtexture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glTexSubImage1DEXT (GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +#endif + +#ifndef GL_EXT_copy_texture +#define GL_EXT_copy_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glCopyTexImage1DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint); +extern void APIENTRY glCopyTexImage2DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint); +extern void APIENTRY glCopyTexSubImage1DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei); +extern void APIENTRY glCopyTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +extern void APIENTRY glCopyTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (APIENTRY * PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (APIENTRY * PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (APIENTRY * PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRY * PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#endif + +#ifndef GL_EXT_histogram +#define GL_EXT_histogram 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glGetHistogramEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetHistogramParameterfvEXT (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetHistogramParameterivEXT (GLenum, GLenum, GLint *); +extern void APIENTRY glGetMinmaxEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetMinmaxParameterfvEXT (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetMinmaxParameterivEXT (GLenum, GLenum, GLint *); +extern void APIENTRY glHistogramEXT (GLenum, GLsizei, GLenum, GLboolean); +extern void APIENTRY glMinmaxEXT (GLenum, GLenum, GLboolean); +extern void APIENTRY glResetHistogramEXT (GLenum); +extern void APIENTRY glResetMinmaxEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (APIENTRY * PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (APIENTRY * PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (APIENTRY * PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (APIENTRY * PFNGLRESETHISTOGRAMEXTPROC) (GLenum target); +typedef void (APIENTRY * PFNGLRESETMINMAXEXTPROC) (GLenum target); +#endif + +#ifndef GL_EXT_convolution +#define GL_EXT_convolution 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glConvolutionFilter1DEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glConvolutionFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glConvolutionParameterfEXT (GLenum, GLenum, GLfloat); +extern void APIENTRY glConvolutionParameterfvEXT (GLenum, GLenum, const GLfloat *); +extern void APIENTRY glConvolutionParameteriEXT (GLenum, GLenum, GLint); +extern void APIENTRY glConvolutionParameterivEXT (GLenum, GLenum, const GLint *); +extern void APIENTRY glCopyConvolutionFilter1DEXT (GLenum, GLenum, GLint, GLint, GLsizei); +extern void APIENTRY glCopyConvolutionFilter2DEXT (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei); +extern void APIENTRY glGetConvolutionFilterEXT (GLenum, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetConvolutionParameterfvEXT (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetConvolutionParameterivEXT (GLenum, GLenum, GLint *); +extern void APIENTRY glGetSeparableFilterEXT (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *); +extern void APIENTRY glSeparableFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); +typedef void (APIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); +typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params); +typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params); +typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (APIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); +typedef void (APIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); +typedef void (APIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); +#endif + +#ifndef GL_EXT_color_matrix +#define GL_EXT_color_matrix 1 +#endif + +#ifndef GL_SGI_color_table +#define GL_SGI_color_table 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glColorTableSGI (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glColorTableParameterfvSGI (GLenum, GLenum, const GLfloat *); +extern void APIENTRY glColorTableParameterivSGI (GLenum, GLenum, const GLint *); +extern void APIENTRY glCopyColorTableSGI (GLenum, GLenum, GLint, GLint, GLsizei); +extern void APIENTRY glGetColorTableSGI (GLenum, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetColorTableParameterfvSGI (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetColorTableParameterivSGI (GLenum, GLenum, GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (APIENTRY * PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (APIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); +typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint *params); +#endif + +#ifndef GL_SGIX_pixel_texture +#define GL_SGIX_pixel_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glPixelTexGenSGIX (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLPIXELTEXGENSGIXPROC) (GLenum mode); +#endif + +#ifndef GL_SGIS_pixel_texture +#define GL_SGIS_pixel_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glPixelTexGenParameteriSGIS (GLenum, GLint); +extern void APIENTRY glPixelTexGenParameterivSGIS (GLenum, const GLint *); +extern void APIENTRY glPixelTexGenParameterfSGIS (GLenum, GLfloat); +extern void APIENTRY glPixelTexGenParameterfvSGIS (GLenum, const GLfloat *); +extern void APIENTRY glGetPixelTexGenParameterivSGIS (GLenum, GLint *); +extern void APIENTRY glGetPixelTexGenParameterfvSGIS (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat *params); +#endif + +#ifndef GL_SGIS_texture4D +#define GL_SGIS_texture4D 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glTexImage4DSGIS (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glTexSubImage4DSGIS (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels); +#endif + +#ifndef GL_SGI_texture_color_table +#define GL_SGI_texture_color_table 1 +#endif + +#ifndef GL_EXT_cmyka +#define GL_EXT_cmyka 1 +#endif + +#ifndef GL_EXT_texture_object +#define GL_EXT_texture_object 1 +#ifdef GL_GLEXT_PROTOTYPES +extern GLboolean APIENTRY glAreTexturesResidentEXT (GLsizei, const GLuint *, GLboolean *); +extern void APIENTRY glBindTextureEXT (GLenum, GLuint); +extern void APIENTRY glDeleteTexturesEXT (GLsizei, const GLuint *); +extern void APIENTRY glGenTexturesEXT (GLsizei, GLuint *); +extern GLboolean APIENTRY glIsTextureEXT (GLuint); +extern void APIENTRY glPrioritizeTexturesEXT (GLsizei, const GLuint *, const GLclampf *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLboolean (APIENTRY * PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences); +typedef void (APIENTRY * PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture); +typedef void (APIENTRY * PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures); +typedef void (APIENTRY * PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures); +typedef GLboolean (APIENTRY * PFNGLISTEXTUREEXTPROC) (GLuint texture); +typedef void (APIENTRY * PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities); +#endif + +#ifndef GL_SGIS_detail_texture +#define GL_SGIS_detail_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glDetailTexFuncSGIS (GLenum, GLsizei, const GLfloat *); +extern void APIENTRY glGetDetailTexFuncSGIS (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points); +typedef void (APIENTRY * PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat *points); +#endif + +#ifndef GL_SGIS_sharpen_texture +#define GL_SGIS_sharpen_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glSharpenTexFuncSGIS (GLenum, GLsizei, const GLfloat *); +extern void APIENTRY glGetSharpenTexFuncSGIS (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points); +typedef void (APIENTRY * PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat *points); +#endif + +#ifndef GL_EXT_packed_pixels +#define GL_EXT_packed_pixels 1 +#endif + +#ifndef GL_SGIS_texture_lod +#define GL_SGIS_texture_lod 1 +#endif + +#ifndef GL_SGIS_multisample +#define GL_SGIS_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glSampleMaskSGIS (GLclampf, GLboolean); +extern void APIENTRY glSamplePatternSGIS (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert); +typedef void (APIENTRY * PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern); +#endif + +#ifndef GL_EXT_rescale_normal +#define GL_EXT_rescale_normal 1 +#endif + +#ifndef GL_EXT_vertex_array +#define GL_EXT_vertex_array 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glArrayElementEXT (GLint); +extern void APIENTRY glColorPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); +extern void APIENTRY glDrawArraysEXT (GLenum, GLint, GLsizei); +extern void APIENTRY glEdgeFlagPointerEXT (GLsizei, GLsizei, const GLboolean *); +extern void APIENTRY glGetPointervEXT (GLenum, GLvoid* *); +extern void APIENTRY glIndexPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *); +extern void APIENTRY glNormalPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *); +extern void APIENTRY glTexCoordPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); +extern void APIENTRY glVertexPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLARRAYELEMENTEXTPROC) (GLint i); +typedef void (APIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (APIENTRY * PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (APIENTRY * PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer); +typedef void (APIENTRY * PFNGLGETPOINTERVEXTPROC) (GLenum pname, GLvoid* *params); +typedef void (APIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (APIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (APIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (APIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +#endif + +#ifndef GL_EXT_misc_attribute +#define GL_EXT_misc_attribute 1 +#endif + +#ifndef GL_SGIS_generate_mipmap +#define GL_SGIS_generate_mipmap 1 +#endif + +#ifndef GL_SGIX_clipmap +#define GL_SGIX_clipmap 1 +#endif + +#ifndef GL_SGIX_shadow +#define GL_SGIX_shadow 1 +#endif + +#ifndef GL_SGIS_texture_edge_clamp +#define GL_SGIS_texture_edge_clamp 1 +#endif + +#ifndef GL_SGIS_texture_border_clamp +#define GL_SGIS_texture_border_clamp 1 +#endif + +#ifndef GL_EXT_blend_minmax +#define GL_EXT_blend_minmax 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glBlendEquationEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLBLENDEQUATIONEXTPROC) (GLenum mode); +#endif + +#ifndef GL_EXT_blend_subtract +#define GL_EXT_blend_subtract 1 +#endif + +#ifndef GL_EXT_blend_logic_op +#define GL_EXT_blend_logic_op 1 +#endif + +#ifndef GL_SGIX_interlace +#define GL_SGIX_interlace 1 +#endif + +#ifndef GL_SGIX_pixel_tiles +#define GL_SGIX_pixel_tiles 1 +#endif + +#ifndef GL_SGIX_texture_select +#define GL_SGIX_texture_select 1 +#endif + +#ifndef GL_SGIX_sprite +#define GL_SGIX_sprite 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glSpriteParameterfSGIX (GLenum, GLfloat); +extern void APIENTRY glSpriteParameterfvSGIX (GLenum, const GLfloat *); +extern void APIENTRY glSpriteParameteriSGIX (GLenum, GLint); +extern void APIENTRY glSpriteParameterivSGIX (GLenum, const GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint *params); +#endif + +#ifndef GL_SGIX_texture_multi_buffer +#define GL_SGIX_texture_multi_buffer 1 +#endif + +#ifndef GL_EXT_point_parameters +#define GL_EXT_point_parameters 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glPointParameterfEXT (GLenum, GLfloat); +extern void APIENTRY glPointParameterfvEXT (GLenum, const GLfloat *); +extern void APIENTRY glPointParameterfSGIS (GLenum, GLfloat); +extern void APIENTRY glPointParameterfvSGIS (GLenum, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params); +#endif + +#ifndef GL_SGIX_instruments +#define GL_SGIX_instruments 1 +#ifdef GL_GLEXT_PROTOTYPES +extern GLint APIENTRY glGetInstrumentsSGIX (void); +extern void APIENTRY glInstrumentsBufferSGIX (GLsizei, GLint *); +extern GLint APIENTRY glPollInstrumentsSGIX (GLint *); +extern void APIENTRY glReadInstrumentsSGIX (GLint); +extern void APIENTRY glStartInstrumentsSGIX (void); +extern void APIENTRY glStopInstrumentsSGIX (GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLint (APIENTRY * PFNGLGETINSTRUMENTSSGIXPROC) (void); +typedef void (APIENTRY * PFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint *buffer); +typedef GLint (APIENTRY * PFNGLPOLLINSTRUMENTSSGIXPROC) (GLint *marker_p); +typedef void (APIENTRY * PFNGLREADINSTRUMENTSSGIXPROC) (GLint marker); +typedef void (APIENTRY * PFNGLSTARTINSTRUMENTSSGIXPROC) (void); +typedef void (APIENTRY * PFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker); +#endif + +#ifndef GL_SGIX_texture_scale_bias +#define GL_SGIX_texture_scale_bias 1 +#endif + +#ifndef GL_SGIX_framezoom +#define GL_SGIX_framezoom 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glFrameZoomSGIX (GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLFRAMEZOOMSGIXPROC) (GLint factor); +#endif + +#ifndef GL_SGIX_tag_sample_buffer +#define GL_SGIX_tag_sample_buffer 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glTagSampleBufferSGIX (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLTAGSAMPLEBUFFERSGIXPROC) (void); +#endif + +#ifndef GL_SGIX_reference_plane +#define GL_SGIX_reference_plane 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glReferencePlaneSGIX (const GLdouble *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLREFERENCEPLANESGIXPROC) (const GLdouble *equation); +#endif + +#ifndef GL_SGIX_flush_raster +#define GL_SGIX_flush_raster 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glFlushRasterSGIX (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLFLUSHRASTERSGIXPROC) (void); +#endif + +#ifndef GL_SGIX_depth_texture +#define GL_SGIX_depth_texture 1 +#endif + +#ifndef GL_SGIS_fog_function +#define GL_SGIS_fog_function 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glFogFuncSGIS (GLsizei, const GLfloat *); +extern void APIENTRY glGetFogFuncSGIS (const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat *points); +typedef void (APIENTRY * PFNGLGETFOGFUNCSGISPROC) (const GLfloat *points); +#endif + +#ifndef GL_SGIX_fog_offset +#define GL_SGIX_fog_offset 1 +#endif + +#ifndef GL_HP_image_transform +#define GL_HP_image_transform 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glImageTransformParameteriHP (GLenum, GLenum, GLint); +extern void APIENTRY glImageTransformParameterfHP (GLenum, GLenum, GLfloat); +extern void APIENTRY glImageTransformParameterivHP (GLenum, GLenum, const GLint *); +extern void APIENTRY glImageTransformParameterfvHP (GLenum, GLenum, const GLfloat *); +extern void APIENTRY glGetImageTransformParameterivHP (GLenum, GLenum, GLint *); +extern void APIENTRY glGetImageTransformParameterfvHP (GLenum, GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params); +#endif + +#ifndef GL_HP_convolution_border_modes +#define GL_HP_convolution_border_modes 1 +#endif + +#ifndef GL_SGIX_texture_add_env +#define GL_SGIX_texture_add_env 1 +#endif + +#ifndef GL_EXT_color_subtable +#define GL_EXT_color_subtable 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glColorSubTableEXT (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glCopyColorSubTableEXT (GLenum, GLsizei, GLint, GLint, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); +typedef void (APIENTRY * PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +#endif + +#ifndef GL_PGI_vertex_hints +#define GL_PGI_vertex_hints 1 +#endif + +#ifndef GL_PGI_misc_hints +#define GL_PGI_misc_hints 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glHintPGI (GLenum, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLHINTPGIPROC) (GLenum target, GLint mode); +#endif + +#ifndef GL_EXT_paletted_texture +#define GL_EXT_paletted_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glColorTableEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glGetColorTableEXT (GLenum, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetColorTableParameterivEXT (GLenum, GLenum, GLint *); +extern void APIENTRY glGetColorTableParameterfvEXT (GLenum, GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (APIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *data); +typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +#endif + +#ifndef GL_EXT_clip_volume_hint +#define GL_EXT_clip_volume_hint 1 +#endif + +#ifndef GL_SGIX_list_priority +#define GL_SGIX_list_priority 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glGetListParameterfvSGIX (GLuint, GLenum, GLfloat *); +extern void APIENTRY glGetListParameterivSGIX (GLuint, GLenum, GLint *); +extern void APIENTRY glListParameterfSGIX (GLuint, GLenum, GLfloat); +extern void APIENTRY glListParameterfvSGIX (GLuint, GLenum, const GLfloat *); +extern void APIENTRY glListParameteriSGIX (GLuint, GLenum, GLint); +extern void APIENTRY glListParameterivSGIX (GLuint, GLenum, const GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint *params); +#endif + +#ifndef GL_SGIX_ir_instrument1 +#define GL_SGIX_ir_instrument1 1 +#endif + +#ifndef GL_SGIX_calligraphic_fragment +#define GL_SGIX_calligraphic_fragment 1 +#endif + +#ifndef GL_SGIX_texture_lod_bias +#define GL_SGIX_texture_lod_bias 1 +#endif + +#ifndef GL_SGIX_shadow_ambient +#define GL_SGIX_shadow_ambient 1 +#endif + +#ifndef GL_EXT_index_texture +#define GL_EXT_index_texture 1 +#endif + +#ifndef GL_EXT_index_material +#define GL_EXT_index_material 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glIndexMaterialEXT (GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode); +#endif + +#ifndef GL_EXT_index_func +#define GL_EXT_index_func 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glIndexFuncEXT (GLenum, GLclampf); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref); +#endif + +#ifndef GL_EXT_index_array_formats +#define GL_EXT_index_array_formats 1 +#endif + +#ifndef GL_EXT_compiled_vertex_array +#define GL_EXT_compiled_vertex_array 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glLockArraysEXT (GLint, GLsizei); +extern void APIENTRY glUnlockArraysEXT (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count); +typedef void (APIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void); +#endif + +#ifndef GL_EXT_cull_vertex +#define GL_EXT_cull_vertex 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glCullParameterdvEXT (GLenum, GLdouble *); +extern void APIENTRY glCullParameterfvEXT (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble *params); +typedef void (APIENTRY * PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat *params); +#endif + +#ifndef GL_SGIX_ycrcb +#define GL_SGIX_ycrcb 1 +#endif + +#ifndef GL_SGIX_fragment_lighting +#define GL_SGIX_fragment_lighting 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glFragmentColorMaterialSGIX (GLenum, GLenum); +extern void APIENTRY glFragmentLightfSGIX (GLenum, GLenum, GLfloat); +extern void APIENTRY glFragmentLightfvSGIX (GLenum, GLenum, const GLfloat *); +extern void APIENTRY glFragmentLightiSGIX (GLenum, GLenum, GLint); +extern void APIENTRY glFragmentLightivSGIX (GLenum, GLenum, const GLint *); +extern void APIENTRY glFragmentLightModelfSGIX (GLenum, GLfloat); +extern void APIENTRY glFragmentLightModelfvSGIX (GLenum, const GLfloat *); +extern void APIENTRY glFragmentLightModeliSGIX (GLenum, GLint); +extern void APIENTRY glFragmentLightModelivSGIX (GLenum, const GLint *); +extern void APIENTRY glFragmentMaterialfSGIX (GLenum, GLenum, GLfloat); +extern void APIENTRY glFragmentMaterialfvSGIX (GLenum, GLenum, const GLfloat *); +extern void APIENTRY glFragmentMaterialiSGIX (GLenum, GLenum, GLint); +extern void APIENTRY glFragmentMaterialivSGIX (GLenum, GLenum, const GLint *); +extern void APIENTRY glGetFragmentLightfvSGIX (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetFragmentLightivSGIX (GLenum, GLenum, GLint *); +extern void APIENTRY glGetFragmentMaterialfvSGIX (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetFragmentMaterialivSGIX (GLenum, GLenum, GLint *); +extern void APIENTRY glLightEnviSGIX (GLenum, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode); +typedef void (APIENTRY * PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param); +#endif + +#ifndef GL_IBM_rasterpos_clip +#define GL_IBM_rasterpos_clip 1 +#endif + +#ifndef GL_HP_texture_lighting +#define GL_HP_texture_lighting 1 +#endif + +#ifndef GL_EXT_draw_range_elements +#define GL_EXT_draw_range_elements 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glDrawRangeElementsEXT (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); +#endif + +#ifndef GL_WIN_phong_shading +#define GL_WIN_phong_shading 1 +#endif + +#ifndef GL_WIN_specular_fog +#define GL_WIN_specular_fog 1 +#endif + +#ifndef GL_EXT_light_texture +#define GL_EXT_light_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glApplyTextureEXT (GLenum); +extern void APIENTRY glTextureLightEXT (GLenum); +extern void APIENTRY glTextureMaterialEXT (GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode); +typedef void (APIENTRY * PFNGLTEXTURELIGHTEXTPROC) (GLenum pname); +typedef void (APIENTRY * PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode); +#endif + +#ifndef GL_SGIX_blend_alpha_minmax +#define GL_SGIX_blend_alpha_minmax 1 +#endif + +#ifndef GL_EXT_bgra +#define GL_EXT_bgra 1 +#endif + +#ifndef GL_INTEL_parallel_arrays +#define GL_INTEL_parallel_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glVertexPointervINTEL (GLint, GLenum, const GLvoid* *); +extern void APIENTRY glNormalPointervINTEL (GLenum, const GLvoid* *); +extern void APIENTRY glColorPointervINTEL (GLint, GLenum, const GLvoid* *); +extern void APIENTRY glTexCoordPointervINTEL (GLint, GLenum, const GLvoid* *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); +typedef void (APIENTRY * PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const GLvoid* *pointer); +typedef void (APIENTRY * PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); +typedef void (APIENTRY * PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); +#endif + +#ifndef GL_HP_occlusion_test +#define GL_HP_occlusion_test 1 +#endif + +#ifndef GL_EXT_pixel_transform +#define GL_EXT_pixel_transform 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glPixelTransformParameteriEXT (GLenum, GLenum, GLint); +extern void APIENTRY glPixelTransformParameterfEXT (GLenum, GLenum, GLfloat); +extern void APIENTRY glPixelTransformParameterivEXT (GLenum, GLenum, const GLint *); +extern void APIENTRY glPixelTransformParameterfvEXT (GLenum, GLenum, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params); +#endif + +#ifndef GL_EXT_pixel_transform_color_table +#define GL_EXT_pixel_transform_color_table 1 +#endif + +#ifndef GL_EXT_shared_texture_palette +#define GL_EXT_shared_texture_palette 1 +#endif + +#ifndef GL_EXT_separate_specular_color +#define GL_EXT_separate_specular_color 1 +#endif + +#ifndef GL_EXT_secondary_color +#define GL_EXT_secondary_color 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glSecondaryColor3bEXT (GLbyte, GLbyte, GLbyte); +extern void APIENTRY glSecondaryColor3bvEXT (const GLbyte *); +extern void APIENTRY glSecondaryColor3dEXT (GLdouble, GLdouble, GLdouble); +extern void APIENTRY glSecondaryColor3dvEXT (const GLdouble *); +extern void APIENTRY glSecondaryColor3fEXT (GLfloat, GLfloat, GLfloat); +extern void APIENTRY glSecondaryColor3fvEXT (const GLfloat *); +extern void APIENTRY glSecondaryColor3iEXT (GLint, GLint, GLint); +extern void APIENTRY glSecondaryColor3ivEXT (const GLint *); +extern void APIENTRY glSecondaryColor3sEXT (GLshort, GLshort, GLshort); +extern void APIENTRY glSecondaryColor3svEXT (const GLshort *); +extern void APIENTRY glSecondaryColor3ubEXT (GLubyte, GLubyte, GLubyte); +extern void APIENTRY glSecondaryColor3ubvEXT (const GLubyte *); +extern void APIENTRY glSecondaryColor3uiEXT (GLuint, GLuint, GLuint); +extern void APIENTRY glSecondaryColor3uivEXT (const GLuint *); +extern void APIENTRY glSecondaryColor3usEXT (GLushort, GLushort, GLushort); +extern void APIENTRY glSecondaryColor3usvEXT (const GLushort *); +extern void APIENTRY glSecondaryColorPointerEXT (GLint, GLenum, GLsizei, GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v); +typedef void (APIENTRY * PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); +#endif + +#ifndef GL_EXT_texture_perturb_normal +#define GL_EXT_texture_perturb_normal 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glTextureNormalEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLTEXTURENORMALEXTPROC) (GLenum mode); +#endif + +#ifndef GL_EXT_multi_draw_arrays +#define GL_EXT_multi_draw_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei); +extern void APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); +typedef void (APIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); +#endif + +#ifndef GL_EXT_fog_coord +#define GL_EXT_fog_coord 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glFogCoordfEXT (GLfloat); +extern void APIENTRY glFogCoordfvEXT (const GLfloat *); +extern void APIENTRY glFogCoorddEXT (GLdouble); +extern void APIENTRY glFogCoorddvEXT (const GLdouble *); +extern void APIENTRY glFogCoordPointerEXT (GLenum, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLFOGCOORDFEXTPROC) (GLfloat coord); +typedef void (APIENTRY * PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord); +typedef void (APIENTRY * PFNGLFOGCOORDDEXTPROC) (GLdouble coord); +typedef void (APIENTRY * PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord); +typedef void (APIENTRY * PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_REND_screen_coordinates +#define GL_REND_screen_coordinates 1 +#endif + +#ifndef GL_EXT_coordinate_frame +#define GL_EXT_coordinate_frame 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glTangent3bEXT (GLbyte, GLbyte, GLbyte); +extern void APIENTRY glTangent3bvEXT (const GLbyte *); +extern void APIENTRY glTangent3dEXT (GLdouble, GLdouble, GLdouble); +extern void APIENTRY glTangent3dvEXT (const GLdouble *); +extern void APIENTRY glTangent3fEXT (GLfloat, GLfloat, GLfloat); +extern void APIENTRY glTangent3fvEXT (const GLfloat *); +extern void APIENTRY glTangent3iEXT (GLint, GLint, GLint); +extern void APIENTRY glTangent3ivEXT (const GLint *); +extern void APIENTRY glTangent3sEXT (GLshort, GLshort, GLshort); +extern void APIENTRY glTangent3svEXT (const GLshort *); +extern void APIENTRY glBinormal3bEXT (GLbyte, GLbyte, GLbyte); +extern void APIENTRY glBinormal3bvEXT (const GLbyte *); +extern void APIENTRY glBinormal3dEXT (GLdouble, GLdouble, GLdouble); +extern void APIENTRY glBinormal3dvEXT (const GLdouble *); +extern void APIENTRY glBinormal3fEXT (GLfloat, GLfloat, GLfloat); +extern void APIENTRY glBinormal3fvEXT (const GLfloat *); +extern void APIENTRY glBinormal3iEXT (GLint, GLint, GLint); +extern void APIENTRY glBinormal3ivEXT (const GLint *); +extern void APIENTRY glBinormal3sEXT (GLshort, GLshort, GLshort); +extern void APIENTRY glBinormal3svEXT (const GLshort *); +extern void APIENTRY glTangentPointerEXT (GLenum, GLsizei, const GLvoid *); +extern void APIENTRY glBinormalPointerEXT (GLenum, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz); +typedef void (APIENTRY * PFNGLTANGENT3BVEXTPROC) (const GLbyte *v); +typedef void (APIENTRY * PFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz); +typedef void (APIENTRY * PFNGLTANGENT3DVEXTPROC) (const GLdouble *v); +typedef void (APIENTRY * PFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz); +typedef void (APIENTRY * PFNGLTANGENT3FVEXTPROC) (const GLfloat *v); +typedef void (APIENTRY * PFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz); +typedef void (APIENTRY * PFNGLTANGENT3IVEXTPROC) (const GLint *v); +typedef void (APIENTRY * PFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz); +typedef void (APIENTRY * PFNGLTANGENT3SVEXTPROC) (const GLshort *v); +typedef void (APIENTRY * PFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz); +typedef void (APIENTRY * PFNGLBINORMAL3BVEXTPROC) (const GLbyte *v); +typedef void (APIENTRY * PFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz); +typedef void (APIENTRY * PFNGLBINORMAL3DVEXTPROC) (const GLdouble *v); +typedef void (APIENTRY * PFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz); +typedef void (APIENTRY * PFNGLBINORMAL3FVEXTPROC) (const GLfloat *v); +typedef void (APIENTRY * PFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz); +typedef void (APIENTRY * PFNGLBINORMAL3IVEXTPROC) (const GLint *v); +typedef void (APIENTRY * PFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz); +typedef void (APIENTRY * PFNGLBINORMAL3SVEXTPROC) (const GLshort *v); +typedef void (APIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_EXT_texture_env_combine +#define GL_EXT_texture_env_combine 1 +#endif + +#ifndef GL_APPLE_specular_vector +#define GL_APPLE_specular_vector 1 +#endif + +#ifndef GL_APPLE_transform_hint +#define GL_APPLE_transform_hint 1 +#endif + +#ifndef GL_SGIX_fog_scale +#define GL_SGIX_fog_scale 1 +#endif + +#ifndef GL_SUNX_constant_data +#define GL_SUNX_constant_data 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glFinishTextureSUNX (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLFINISHTEXTURESUNXPROC) (void); +#endif + +#ifndef GL_SUN_global_alpha +#define GL_SUN_global_alpha 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glGlobalAlphaFactorbSUN (GLbyte); +extern void APIENTRY glGlobalAlphaFactorsSUN (GLshort); +extern void APIENTRY glGlobalAlphaFactoriSUN (GLint); +extern void APIENTRY glGlobalAlphaFactorfSUN (GLfloat); +extern void APIENTRY glGlobalAlphaFactordSUN (GLdouble); +extern void APIENTRY glGlobalAlphaFactorubSUN (GLubyte); +extern void APIENTRY glGlobalAlphaFactorusSUN (GLushort); +extern void APIENTRY glGlobalAlphaFactoruiSUN (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor); +typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor); +typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor); +typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor); +typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor); +typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor); +typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor); +typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor); +#endif + +#ifndef GL_SUN_triangle_list +#define GL_SUN_triangle_list 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glReplacementCodeuiSUN (GLuint); +extern void APIENTRY glReplacementCodeusSUN (GLushort); +extern void APIENTRY glReplacementCodeubSUN (GLubyte); +extern void APIENTRY glReplacementCodeuivSUN (const GLuint *); +extern void APIENTRY glReplacementCodeusvSUN (const GLushort *); +extern void APIENTRY glReplacementCodeubvSUN (const GLubyte *); +extern void APIENTRY glReplacementCodePointerSUN (GLenum, GLsizei, const GLvoid* *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint *code); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort *code); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte *code); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const GLvoid* *pointer); +#endif + +#ifndef GL_SUN_vertex +#define GL_SUN_vertex 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glColor4ubVertex2fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat); +extern void APIENTRY glColor4ubVertex2fvSUN (const GLubyte *, const GLfloat *); +extern void APIENTRY glColor4ubVertex3fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glColor4ubVertex3fvSUN (const GLubyte *, const GLfloat *); +extern void APIENTRY glColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glColor3fVertex3fvSUN (const GLfloat *, const GLfloat *); +extern void APIENTRY glNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *); +extern void APIENTRY glColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); +extern void APIENTRY glTexCoord2fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glTexCoord2fVertex3fvSUN (const GLfloat *, const GLfloat *); +extern void APIENTRY glTexCoord4fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glTexCoord4fVertex4fvSUN (const GLfloat *, const GLfloat *); +extern void APIENTRY glTexCoord2fColor4ubVertex3fSUN (GLfloat, GLfloat, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glTexCoord2fColor4ubVertex3fvSUN (const GLfloat *, const GLubyte *, const GLfloat *); +extern void APIENTRY glTexCoord2fColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glTexCoord2fColor3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); +extern void APIENTRY glTexCoord2fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glTexCoord2fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); +extern void APIENTRY glTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); +extern void APIENTRY glTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); +extern void APIENTRY glReplacementCodeuiVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glReplacementCodeuiVertex3fvSUN (const GLenum *, const GLfloat *); +extern void APIENTRY glReplacementCodeuiColor4ubVertex3fSUN (GLenum, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glReplacementCodeuiColor4ubVertex3fvSUN (const GLenum *, const GLubyte *, const GLfloat *); +extern void APIENTRY glReplacementCodeuiColor3fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glReplacementCodeuiColor3fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *); +extern void APIENTRY glReplacementCodeuiNormal3fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glReplacementCodeuiNormal3fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *); +extern void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *, const GLfloat *); +extern void APIENTRY glReplacementCodeuiTexCoord2fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glReplacementCodeuiTexCoord2fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *); +extern void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *, const GLfloat *); +extern void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); +typedef void (APIENTRY * PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte *c, const GLfloat *v); +typedef void (APIENTRY * PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte *c, const GLfloat *v); +typedef void (APIENTRY * PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *v); +typedef void (APIENTRY * PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *n, const GLfloat *v); +typedef void (APIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRY * PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *v); +typedef void (APIENTRY * PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRY * PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *v); +typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat *tc, const GLubyte *c, const GLfloat *v); +typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *v); +typedef void (APIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLenum rc, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *v); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLenum rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLenum *rc, const GLubyte *c, const GLfloat *v); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLenum rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *c, const GLfloat *v); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLenum rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLenum rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLenum rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *tc, const GLfloat *v); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLenum rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLenum rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +#endif + +#ifndef GL_EXT_blend_func_separate +#define GL_EXT_blend_func_separate 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glBlendFuncSeparateEXT (GLenum, GLenum, GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +#endif + +#ifndef GL_INGR_color_clamp +#define GL_INGR_color_clamp 1 +#endif + +#ifndef GL_INGR_interlace_read +#define GL_INGR_interlace_read 1 +#endif + +#ifndef GL_EXT_stencil_wrap +#define GL_EXT_stencil_wrap 1 +#endif + +#ifndef GL_EXT_422_pixels +#define GL_EXT_422_pixels 1 +#endif + +#ifndef GL_NV_texgen_reflection +#define GL_NV_texgen_reflection 1 +#endif + +#ifndef GL_SUN_convolution_border_modes +#define GL_SUN_convolution_border_modes 1 +#endif + +#ifndef GL_EXT_texture_env_add +#define GL_EXT_texture_env_add 1 +#endif + +#ifndef GL_EXT_texture_lod_bias +#define GL_EXT_texture_lod_bias 1 +#endif + +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_EXT_texture_filter_anisotropic 1 +#endif + +#ifndef GL_EXT_vertex_weighting +#define GL_EXT_vertex_weighting 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glVertexWeightfEXT (GLfloat); +extern void APIENTRY glVertexWeightfvEXT (const GLfloat *); +extern void APIENTRY glVertexWeightPointerEXT (GLsizei, GLenum, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight); +typedef void (APIENTRY * PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight); +typedef void (APIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_NV_light_max_exponent +#define GL_NV_light_max_exponent 1 +#endif + +#ifndef GL_NV_vertex_array_range +#define GL_NV_vertex_array_range 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glFlushVertexArrayRangeNV (void); +extern void APIENTRY glVertexArrayRangeNV (GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void); +typedef void (APIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei size, const GLvoid *pointer); +#endif + +#ifndef GL_NV_vertex_array_range2 +#define GL_NV_vertex_array_range2 1 +#endif + +#ifndef GL_NV_register_combiners +#define GL_NV_register_combiners 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glCombinerParameterfvNV (GLenum, const GLfloat *); +extern void APIENTRY glCombinerParameterfNV (GLenum, GLfloat); +extern void APIENTRY glCombinerParameterivNV (GLenum, const GLint *); +extern void APIENTRY glCombinerParameteriNV (GLenum, GLint); +extern void APIENTRY glCombinerInputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum); +extern void APIENTRY glCombinerOutputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLboolean, GLboolean, GLboolean); +extern void APIENTRY glFinalCombinerInputNV (GLenum, GLenum, GLenum, GLenum); +extern void APIENTRY glGetCombinerInputParameterfvNV (GLenum, GLenum, GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetCombinerInputParameterivNV (GLenum, GLenum, GLenum, GLenum, GLint *); +extern void APIENTRY glGetCombinerOutputParameterfvNV (GLenum, GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetCombinerOutputParameterivNV (GLenum, GLenum, GLenum, GLint *); +extern void APIENTRY glGetFinalCombinerInputParameterfvNV (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetFinalCombinerInputParameterivNV (GLenum, GLenum, GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (APIENTRY * PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); +typedef void (APIENTRY * PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (APIENTRY * PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params); +#endif + +#ifndef GL_NV_fog_distance +#define GL_NV_fog_distance 1 +#endif + +#ifndef GL_NV_texgen_emboss +#define GL_NV_texgen_emboss 1 +#endif + +#ifndef GL_NV_blend_square +#define GL_NV_blend_square 1 +#endif + +#ifndef GL_NV_texture_env_combine4 +#define GL_NV_texture_env_combine4 1 +#endif + +#ifndef GL_MESA_resize_buffers +#define GL_MESA_resize_buffers 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glResizeBuffersMESA (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLRESIZEBUFFERSMESAPROC) (void); +#endif + +#ifndef GL_MESA_window_pos +#define GL_MESA_window_pos 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glWindowPos2dMESA (GLdouble, GLdouble); +extern void APIENTRY glWindowPos2dvMESA (const GLdouble *); +extern void APIENTRY glWindowPos2fMESA (GLfloat, GLfloat); +extern void APIENTRY glWindowPos2fvMESA (const GLfloat *); +extern void APIENTRY glWindowPos2iMESA (GLint, GLint); +extern void APIENTRY glWindowPos2ivMESA (const GLint *); +extern void APIENTRY glWindowPos2sMESA (GLshort, GLshort); +extern void APIENTRY glWindowPos2svMESA (const GLshort *); +extern void APIENTRY glWindowPos3dMESA (GLdouble, GLdouble, GLdouble); +extern void APIENTRY glWindowPos3dvMESA (const GLdouble *); +extern void APIENTRY glWindowPos3fMESA (GLfloat, GLfloat, GLfloat); +extern void APIENTRY glWindowPos3fvMESA (const GLfloat *); +extern void APIENTRY glWindowPos3iMESA (GLint, GLint, GLint); +extern void APIENTRY glWindowPos3ivMESA (const GLint *); +extern void APIENTRY glWindowPos3sMESA (GLshort, GLshort, GLshort); +extern void APIENTRY glWindowPos3svMESA (const GLshort *); +extern void APIENTRY glWindowPos4dMESA (GLdouble, GLdouble, GLdouble, GLdouble); +extern void APIENTRY glWindowPos4dvMESA (const GLdouble *); +extern void APIENTRY glWindowPos4fMESA (GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glWindowPos4fvMESA (const GLfloat *); +extern void APIENTRY glWindowPos4iMESA (GLint, GLint, GLint, GLint); +extern void APIENTRY glWindowPos4ivMESA (const GLint *); +extern void APIENTRY glWindowPos4sMESA (GLshort, GLshort, GLshort, GLshort); +extern void APIENTRY glWindowPos4svMESA (const GLshort *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y); +typedef void (APIENTRY * PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble *v); +typedef void (APIENTRY * PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y); +typedef void (APIENTRY * PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat *v); +typedef void (APIENTRY * PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y); +typedef void (APIENTRY * PFNGLWINDOWPOS2IVMESAPROC) (const GLint *v); +typedef void (APIENTRY * PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y); +typedef void (APIENTRY * PFNGLWINDOWPOS2SVMESAPROC) (const GLshort *v); +typedef void (APIENTRY * PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRY * PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble *v); +typedef void (APIENTRY * PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat *v); +typedef void (APIENTRY * PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z); +typedef void (APIENTRY * PFNGLWINDOWPOS3IVMESAPROC) (const GLint *v); +typedef void (APIENTRY * PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z); +typedef void (APIENTRY * PFNGLWINDOWPOS3SVMESAPROC) (const GLshort *v); +typedef void (APIENTRY * PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRY * PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble *v); +typedef void (APIENTRY * PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRY * PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat *v); +typedef void (APIENTRY * PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w); +typedef void (APIENTRY * PFNGLWINDOWPOS4IVMESAPROC) (const GLint *v); +typedef void (APIENTRY * PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (APIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort *v); +#endif + +#ifndef GL_IBM_cull_vertex +#define GL_IBM_cull_vertex 1 +#endif + +#ifndef GL_IBM_multimode_draw_arrays +#define GL_IBM_multimode_draw_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glMultiModeDrawArraysIBM (GLenum, const GLint *, const GLsizei *, GLsizei, GLint); +extern void APIENTRY glMultiModeDrawElementsIBM (const GLenum *, const GLsizei *, GLenum, const GLvoid* *, GLsizei, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLMULTIMODEDRAWARRAYSIBMPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); +typedef void (APIENTRY * PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount, GLint modestride); +#endif + +#ifndef GL_IBM_vertex_array_lists +#define GL_IBM_vertex_array_lists 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); +extern void APIENTRY glSecondaryColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); +extern void APIENTRY glEdgeFlagPointerListIBM (GLint, const GLboolean* *, GLint); +extern void APIENTRY glFogCoordPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); +extern void APIENTRY glIndexPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); +extern void APIENTRY glNormalPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); +extern void APIENTRY glTexCoordPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); +extern void APIENTRY glVertexPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRY * PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRY * PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean* *pointer, GLint ptrstride); +typedef void (APIENTRY * PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRY * PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRY * PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRY * PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +#endif + +#ifndef GL_SGIX_subsample +#define GL_SGIX_subsample 1 +#endif + +#ifndef GL_SGIX_ycrcba +#define GL_SGIX_ycrcba 1 +#endif + +#ifndef GL_SGIX_ycrcb_subsample +#define GL_SGIX_ycrcb_subsample 1 +#endif + +#ifndef GL_SGIX_depth_pass_instrument +#define GL_SGIX_depth_pass_instrument 1 +#endif + +#ifndef GL_3DFX_texture_compression_FXT1 +#define GL_3DFX_texture_compression_FXT1 1 +#endif + +#ifndef GL_3DFX_multisample +#define GL_3DFX_multisample 1 +#endif + +#ifndef GL_3DFX_tbuffer +#define GL_3DFX_tbuffer 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glTbufferMask3DFX (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLTBUFFERMASK3DFXPROC) (GLuint mask); +#endif + +#ifndef GL_EXT_multisample +#define GL_EXT_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glSampleMaskEXT (GLclampf, GLboolean); +extern void APIENTRY glSamplePatternEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert); +typedef void (APIENTRY * PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); +#endif + +#ifndef GL_SGI_vertex_preclip +#define GL_SGI_vertex_preclip 1 +#endif + +#ifndef GL_SGIX_convolution_accuracy +#define GL_SGIX_convolution_accuracy 1 +#endif + +#ifndef GL_SGIX_resample +#define GL_SGIX_resample 1 +#endif + +#ifndef GL_SGIS_point_line_texgen +#define GL_SGIS_point_line_texgen 1 +#endif + +#ifndef GL_SGIS_texture_color_mask +#define GL_SGIS_texture_color_mask 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glTextureColorMaskSGIS (GLboolean, GLboolean, GLboolean, GLboolean); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +#endif + + + +/* added by Cass -- this part will be auto-generated in the future*/ + +#ifndef GL_EXT_texture_compression_s3tc +#define GL_EXT_texture_compression_s3tc 1 +#endif + +/* Extensions */ +#define GL_ARB_texture_border_clamp 1 +#define GL_ARB_texture_env_combine 1 +#define GL_ARB_texture_env_dot3 1 +#define GL_EXT_texture_env_dot3 1 +#define GL_IBM_texture_mirrored_repeat 1 +#define GL_NV_evaluators 1 +#define GL_NV_fence 1 +#define GL_NV_multisample_filter_hint 1 +#define GL_NV_packed_depth_stencil 1 +#define GL_NV_register_combiners2 1 +#define GL_NV_texture_compression_vtc 1 +#define GL_NV_texture_rectangle 1 +#define GL_NV_texture_shader 1 +#define GL_NV_texture_shader2 1 +#define GL_NV_vertex_program 1 +#define GL_NV_point_sprite 1 +#define GL_NV_occlusion_query 1 + +/* ARB_texture_border_clamp */ +#define GL_CLAMP_TO_BORDER_ARB 0x812D + +/* ARB_texture_env_combine */ +#define GL_COMBINE_ARB 0x8570 +#define GL_COMBINE_RGB_ARB 0x8571 +#define GL_COMBINE_ALPHA_ARB 0x8572 +#define GL_RGB_SCALE_ARB 0x8573 +#define GL_ADD_SIGNED_ARB 0x8574 +#define GL_INTERPOLATE_ARB 0x8575 +#define GL_CONSTANT_ARB 0x8576 +#define GL_PRIMARY_COLOR_ARB 0x8577 +#define GL_PREVIOUS_ARB 0x8578 +#define GL_SOURCE0_RGB_ARB 0x8580 +#define GL_SOURCE1_RGB_ARB 0x8581 +#define GL_SOURCE2_RGB_ARB 0x8582 +#define GL_SOURCE0_ALPHA_ARB 0x8588 +#define GL_SOURCE1_ALPHA_ARB 0x8589 +#define GL_SOURCE2_ALPHA_ARB 0x858A +#define GL_OPERAND0_RGB_ARB 0x8590 +#define GL_OPERAND1_RGB_ARB 0x8591 +#define GL_OPERAND2_RGB_ARB 0x8592 +#define GL_OPERAND0_ALPHA_ARB 0x8598 +#define GL_OPERAND1_ALPHA_ARB 0x8599 +#define GL_OPERAND2_ALPHA_ARB 0x859A +#define GL_SUBTRACT_ARB 0x84E7 + +/* ARB_texture_env_dot3 */ +#define GL_DOT3_RGB_ARB 0x86AE +#define GL_DOT3_RGBA_ARB 0x86AF + +/* EXT_texture_env_dot3 */ +#define GL_DOT3_RGB_EXT 0x8740 +#define GL_DOT3_RGBA_EXT 0x8741 + +/* IBM_texture_mirrored_repeat */ +#define GL_MIRRORED_REPEAT_IBM 0x8370 + +/* NV_vertex_program */ +#define GL_VERTEX_PROGRAM_NV 0x8620 +#define GL_VERTEX_STATE_PROGRAM_NV 0x8621 +#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623 +#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624 +#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625 +#define GL_CURRENT_ATTRIB_NV 0x8626 +#define GL_PROGRAM_LENGTH_NV 0x8627 +#define GL_PROGRAM_STRING_NV 0x8628 +#define GL_MODELVIEW_PROJECTION_NV 0x8629 +#define GL_IDENTITY_NV 0x862A +#define GL_INVERSE_NV 0x862B +#define GL_TRANSPOSE_NV 0x862C +#define GL_INVERSE_TRANSPOSE_NV 0x862D +#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E +#define GL_MAX_TRACK_MATRICES_NV 0x862F +#define GL_MATRIX0_NV 0x8630 +#define GL_MATRIX1_NV 0x8631 +#define GL_MATRIX2_NV 0x8632 +#define GL_MATRIX3_NV 0x8633 +#define GL_MATRIX4_NV 0x8634 +#define GL_MATRIX5_NV 0x8635 +#define GL_MATRIX6_NV 0x8636 +#define GL_MATRIX7_NV 0x8637 +#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 +#define GL_CURRENT_MATRIX_NV 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 +#define GL_PROGRAM_PARAMETER_NV 0x8644 +#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645 +#define GL_PROGRAM_TARGET_NV 0x8646 +#define GL_PROGRAM_RESIDENT_NV 0x8647 +#define GL_TRACK_MATRIX_NV 0x8648 +#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649 +#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A +#define GL_PROGRAM_ERROR_POSITION_NV 0x864B +#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650 +#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651 +#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652 +#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653 +#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654 +#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655 +#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656 +#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657 +#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658 +#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659 +#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A +#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B +#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C +#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D +#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E +#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F +#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660 +#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661 +#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662 +#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663 +#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664 +#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665 +#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666 +#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667 +#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668 +#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669 +#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A +#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B +#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C +#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D +#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E +#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F +#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670 +#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671 +#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672 +#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673 +#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674 +#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675 +#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676 +#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677 +#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678 +#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679 +#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A +#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B +#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C +#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D +#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E +#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F + +/* NV_evaluators */ +#define GL_EVAL_2D_NV 0x86C0 +#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1 +#define GL_MAP_TESSELLATION_NV 0x86C2 +#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3 +#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4 +#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5 +#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6 +#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7 +#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8 +#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9 +#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA +#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB +#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC +#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD +#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE +#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF +#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0 +#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1 +#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2 +#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3 +#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4 +#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5 +#define GL_MAX_MAP_TESSELLATION_NV 0x86D6 +#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7 + +/* NV_fence */ +#define GL_ALL_COMPLETED_NV 0x84F2 +#define GL_FENCE_STATUS_NV 0x84F3 +#define GL_FENCE_CONDITION_NV 0x84F4 + +/* NV_occlusion_query */ +#define GL_PIXEL_COUNTER_BITS_NV 0x8864 +#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865 +#define GL_PIXEL_COUNT_NV 0x8866 +#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867 + +/* NV_point_sprite */ +#define GL_POINT_SPRITE_NV 0x8861 +#define GL_COORD_REPLACE_NV 0x8862 +#define GL_POINT_SPRITE_R_MODE_NV 0x8863 + +/* NV_texture_rectangle */ +#define GL_TEXTURE_RECTANGLE_NV 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 + +/* NV_texture_shader */ +#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C +#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D +#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E +#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9 +#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA +#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB +#define GL_DSDT_MAG_INTENSITY_NV 0x86DC +#define GL_SHADER_CONSISTENT_NV 0x86DD +#define GL_TEXTURE_SHADER_NV 0x86DE +#define GL_SHADER_OPERATION_NV 0x86DF +#define GL_CULL_MODES_NV 0x86E0 +#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1 +#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2 +#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 +#define GL_OFFSET_TEXTURE_2D_MATRIX_NV GL_OFFSET_TEXTURE_MATRIX_NV +#define GL_OFFSET_TEXTURE_2D_SCALE_NV GL_OFFSET_TEXTURE_SCALE_NV +#define GL_OFFSET_TEXTURE_2D_BIAS_NV GL_OFFSET_TEXTURE_BIAS_NV +#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4 +#define GL_CONST_EYE_NV 0x86E5 +#define GL_PASS_THROUGH_NV 0x86E6 +#define GL_CULL_FRAGMENT_NV 0x86E7 +#define GL_OFFSET_TEXTURE_2D_NV 0x86E8 +#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9 +#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA +#define GL_ISOTROPIC_BRDF_NV 0x86EB +#define GL_DOT_PRODUCT_NV 0x86EC +#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED +#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE +#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF +#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0 +#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1 +#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2 +#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3 +#define GL_HILO_NV 0x86F4 +#define GL_DSDT_NV 0x86F5 +#define GL_DSDT_MAG_NV 0x86F6 +#define GL_DSDT_MAG_VIB_NV 0x86F7 +#define GL_HILO16_NV 0x86F8 +#define GL_SIGNED_HILO_NV 0x86F9 +#define GL_SIGNED_HILO16_NV 0x86FA +#define GL_SIGNED_RGBA_NV 0x86FB +#define GL_SIGNED_RGBA8_NV 0x86FC +#define GL_SIGNED_RGB_NV 0x86FE +#define GL_SIGNED_RGB8_NV 0x86FF +#define GL_SIGNED_LUMINANCE_NV 0x8701 +#define GL_SIGNED_LUMINANCE8_NV 0x8702 +#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 +#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 +#define GL_SIGNED_ALPHA_NV 0x8705 +#define GL_SIGNED_ALPHA8_NV 0x8706 +#define GL_SIGNED_INTENSITY_NV 0x8707 +#define GL_SIGNED_INTENSITY8_NV 0x8708 +#define GL_DSDT8_NV 0x8709 +#define GL_DSDT8_MAG8_NV 0x870A +#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B +#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C +#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D +#define GL_HI_SCALE_NV 0x870E +#define GL_LO_SCALE_NV 0x870F +#define GL_DS_SCALE_NV 0x8710 +#define GL_DT_SCALE_NV 0x8711 +#define GL_MAGNITUDE_SCALE_NV 0x8712 +#define GL_VIBRANCE_SCALE_NV 0x8713 +#define GL_HI_BIAS_NV 0x8714 +#define GL_LO_BIAS_NV 0x8715 +#define GL_DS_BIAS_NV 0x8716 +#define GL_DT_BIAS_NV 0x8717 +#define GL_MAGNITUDE_BIAS_NV 0x8718 +#define GL_VIBRANCE_BIAS_NV 0x8719 +#define GL_TEXTURE_BORDER_VALUES_NV 0x871A +#define GL_TEXTURE_HI_SIZE_NV 0x871B +#define GL_TEXTURE_LO_SIZE_NV 0x871C +#define GL_TEXTURE_DS_SIZE_NV 0x871D +#define GL_TEXTURE_DT_SIZE_NV 0x871E +#define GL_TEXTURE_MAG_SIZE_NV 0x871F + +/* NV_texture_shader2 */ +#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF + +/* NV_register_combiners2 */ +#define GL_PER_STAGE_CONSTANTS_NV 0x8535 + +/* NV_packed_depth_stencil */ +#define GL_DEPTH_STENCIL_NV 0x84F9 +#define GL_UNSIGNED_INT_24_8_NV 0x84FA + +/* NV_multisample_filter_hint */ +#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 + +/* NV_texture_compression_vtc */ + +/* NV_vertex_program */ +typedef GLboolean (APIENTRY * PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences); +typedef void (APIENTRY * PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id); +typedef void (APIENTRY * PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs); +typedef void (APIENTRY * PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params); +typedef void (APIENTRY * PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs); +typedef void (APIENTRY * PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params); +typedef void (APIENTRY * PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program); +typedef void (APIENTRY * PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params); +typedef void (APIENTRY * PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid* *pointer); +typedef GLboolean (APIENTRY * PFNGLISPROGRAMNVPROC) (GLuint id); +typedef void (APIENTRY * PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program); +typedef void (APIENTRY * PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRY * PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v); +typedef void (APIENTRY * PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRY * PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v); +typedef void (APIENTRY * PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRY * PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRY * PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs); +typedef void (APIENTRY * PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform); +typedef void (APIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v); + +/* NV_evaluators */ +typedef void (APIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points); +typedef void (APIENTRY * PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points); +typedef void (APIENTRY * PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode); + +/* NV_fence */ +typedef void (APIENTRY * PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences); +typedef void (APIENTRY * PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences); +typedef GLboolean (APIENTRY * PFNGLISFENCENVPROC) (GLuint fence); +typedef GLboolean (APIENTRY * PFNGLTESTFENCENVPROC) (GLuint fence); +typedef void (APIENTRY * PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLFINISHFENCENVPROC) (GLuint fence); +typedef void (APIENTRY * PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); + +/* NV_occlusion_query */ +typedef void (APIENTRY * PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids); +typedef void (APIENTRY * PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids); +typedef void (APIENTRY * PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id); +typedef void (APIENTRY * PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id); +typedef void (APIENTRY * PFNGLENDOCCLUSIONQUERYNVPROC) (GLvoid); +typedef void (APIENTRY * PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params); + +/* NV_point_sprite */ +typedef void (APIENTRY * PFNGLPOINTPARAMETERINVPROC) (GLenum pname, int param); +typedef void (APIENTRY * PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const int *params); + +/* NV_register_combiners2 */ +typedef void (APIENTRY * PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Glut/GL/glut.h b/Glut/GL/glut.h new file mode 100644 index 0000000..612f332 --- /dev/null +++ b/Glut/GL/glut.h @@ -0,0 +1,607 @@ +#ifndef __glut_h__ +#define __glut_h__ + +/* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998. */ + +/* This program is freely distributable without licensing fees and is + provided without guarantee or warrantee expressed or implied. This + program is -not- in the public domain. */ + +#if defined(_WIN32) + +/* GLUT 3.7 now tries to avoid including + to avoid name space pollution, but Win32's + needs APIENTRY and WINGDIAPI defined properly. */ +# if 0 +# define WIN32_LEAN_AND_MEAN +# include +# else + /* XXX This is from Win32's */ +# ifndef APIENTRY +# define GLUT_APIENTRY_DEFINED +# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) +# define APIENTRY __stdcall +# else +# define APIENTRY +# endif +# endif + /* XXX This is from Win32's */ +# ifndef CALLBACK +# if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) +# define CALLBACK __stdcall +# else +# define CALLBACK +# endif +# endif + /* XXX This is from Win32's and */ +# ifndef WINGDIAPI +# define GLUT_WINGDIAPI_DEFINED +# define WINGDIAPI __declspec(dllimport) +# endif + /* XXX This is from Win32's */ +# ifndef _WCHAR_T_DEFINED +/* MinGW32 chokes on the next line */ +#ifndef __MINGW32__ +typedef unsigned short int wchar_t; +#endif //__MINGW32__ +# define _WCHAR_T_DEFINED +# endif +# endif + +#pragma comment (lib, "winmm.lib") /* link with Windows MultiMedia lib */ +#pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */ +#pragma comment (lib, "glu32.lib") /* link with OpenGL Utility lib */ + +#ifdef _WIN64 +#pragma message("Note: including lib: glut64.lib\n") +#pragma comment (lib, "glut64.lib") /* link with Win32 GLUT lib */ +#else +#pragma message("Note: including lib: glut32.lib\n") +#pragma comment (lib, "glut32.lib") /* link with Win32 GLUT lib */ +#endif + +#pragma warning (disable:4244) /* Disable bogus conversion warnings. */ +#pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */ + +#endif + +#include +#include + +/* define APIENTRY and CALLBACK to null string if we aren't on Win32 */ +#if !defined(_WIN32) +#define APIENTRY +#define GLUT_APIENTRY_DEFINED +#define CALLBACK +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + GLUT API revision history: + + GLUT_API_VERSION is updated to reflect incompatible GLUT + API changes (interface changes, semantic changes, deletions, + or additions). + + GLUT_API_VERSION=1 First public release of GLUT. 11/29/94 + + GLUT_API_VERSION=2 Added support for OpenGL/GLX multisampling, + extension. Supports new input devices like tablet, dial and button + box, and Spaceball. Easy to query OpenGL extensions. + + GLUT_API_VERSION=3 glutMenuStatus added. + + GLUT_API_VERSION=4 glutInitDisplayString, glutWarpPointer, + glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic + video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc, + glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat, + glutJoystickFunc, glutForceJoystickFunc (NOT FINALIZED!). +**/ +#ifndef GLUT_API_VERSION /* allow this to be overriden */ +//#define GLUT_API_VERSION 3 +#define GLUT_API_VERSION 4 +#endif + +/** + GLUT implementation revision history: + + GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT + API revisions and implementation revisions (ie, bug fixes). + + GLUT_XLIB_IMPLEMENTATION=1 mjk's first public release of + GLUT Xlib-based implementation. 11/29/94 + + GLUT_XLIB_IMPLEMENTATION=2 mjk's second public release of + GLUT Xlib-based implementation providing GLUT version 2 + interfaces. + + GLUT_XLIB_IMPLEMENTATION=3 mjk's GLUT 2.2 images. 4/17/95 + + GLUT_XLIB_IMPLEMENTATION=4 mjk's GLUT 2.3 images. 6/?/95 + + GLUT_XLIB_IMPLEMENTATION=5 mjk's GLUT 3.0 images. 10/?/95 + + GLUT_XLIB_IMPLEMENTATION=7 mjk's GLUT 3.1+ with glutWarpPoitner. 7/24/96 + + GLUT_XLIB_IMPLEMENTATION=8 mjk's GLUT 3.1+ with glutWarpPoitner + and video resize. 1/3/97 + + GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines. + + GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release. + + GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling. + + GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 release with GameGLUT support. +**/ +#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */ +#define GLUT_XLIB_IMPLEMENTATION 13 +#endif + +/* Display mode bit masks. */ +#define GLUT_RGB 0 +#define GLUT_RGBA GLUT_RGB +#define GLUT_INDEX 1 +#define GLUT_SINGLE 0 +#define GLUT_DOUBLE 2 +#define GLUT_ACCUM 4 +#define GLUT_ALPHA 8 +#define GLUT_DEPTH 16 +#define GLUT_STENCIL 32 +#if (GLUT_API_VERSION >= 2) +#define GLUT_MULTISAMPLE 128 +#define GLUT_STEREO 256 +#endif +#if (GLUT_API_VERSION >= 3) +#define GLUT_LUMINANCE 512 +#endif + +/* Mouse buttons. */ +#define GLUT_LEFT_BUTTON 0 +#define GLUT_MIDDLE_BUTTON 1 +#define GLUT_RIGHT_BUTTON 2 + +/* Mouse button state. */ +#define GLUT_DOWN 0 +#define GLUT_UP 1 + +#if (GLUT_API_VERSION >= 2) +/* function keys */ +#define GLUT_KEY_F1 1 +#define GLUT_KEY_F2 2 +#define GLUT_KEY_F3 3 +#define GLUT_KEY_F4 4 +#define GLUT_KEY_F5 5 +#define GLUT_KEY_F6 6 +#define GLUT_KEY_F7 7 +#define GLUT_KEY_F8 8 +#define GLUT_KEY_F9 9 +#define GLUT_KEY_F10 10 +#define GLUT_KEY_F11 11 +#define GLUT_KEY_F12 12 +/* directional keys */ +#define GLUT_KEY_LEFT 100 +#define GLUT_KEY_UP 101 +#define GLUT_KEY_RIGHT 102 +#define GLUT_KEY_DOWN 103 +#define GLUT_KEY_PAGE_UP 104 +#define GLUT_KEY_PAGE_DOWN 105 +#define GLUT_KEY_HOME 106 +#define GLUT_KEY_END 107 +#define GLUT_KEY_INSERT 108 +#endif + +/* Entry/exit state. */ +#define GLUT_LEFT 0 +#define GLUT_ENTERED 1 + +/* Menu usage state. */ +#define GLUT_MENU_NOT_IN_USE 0 +#define GLUT_MENU_IN_USE 1 + +/* Visibility state. */ +#define GLUT_NOT_VISIBLE 0 +#define GLUT_VISIBLE 1 + +/* Window status state. */ +#define GLUT_HIDDEN 0 +#define GLUT_FULLY_RETAINED 1 +#define GLUT_PARTIALLY_RETAINED 2 +#define GLUT_FULLY_COVERED 3 + +/* Color index component selection values. */ +#define GLUT_RED 0 +#define GLUT_GREEN 1 +#define GLUT_BLUE 2 + +/* Layers for use. */ +#define GLUT_NORMAL 0 +#define GLUT_OVERLAY 1 + +#if defined(_WIN32) +/* Stroke font constants (use these in GLUT program). */ +#define GLUT_STROKE_ROMAN ((void*)0) +#define GLUT_STROKE_MONO_ROMAN ((void*)1) + +/* Bitmap font constants (use these in GLUT program). */ +#define GLUT_BITMAP_9_BY_15 ((void*)2) +#define GLUT_BITMAP_8_BY_13 ((void*)3) +#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4) +#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5) +#if (GLUT_API_VERSION >= 3) +#define GLUT_BITMAP_HELVETICA_10 ((void*)6) +#define GLUT_BITMAP_HELVETICA_12 ((void*)7) +#define GLUT_BITMAP_HELVETICA_18 ((void*)8) +#endif +#else +/* Stroke font opaque addresses (use constants instead in source code). */ +extern void *glutStrokeRoman; +extern void *glutStrokeMonoRoman; + +/* Stroke font constants (use these in GLUT program). */ +#define GLUT_STROKE_ROMAN (&glutStrokeRoman) +#define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman) + +/* Bitmap font opaque addresses (use constants instead in source code). */ +extern void *glutBitmap9By15; +extern void *glutBitmap8By13; +extern void *glutBitmapTimesRoman10; +extern void *glutBitmapTimesRoman24; +extern void *glutBitmapHelvetica10; +extern void *glutBitmapHelvetica12; +extern void *glutBitmapHelvetica18; + +/* Bitmap font constants (use these in GLUT program). */ +#define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15) +#define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13) +#define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10) +#define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24) +#if (GLUT_API_VERSION >= 3) +#define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10) +#define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12) +#define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18) +#endif +#endif + +/* glutGet parameters. */ +#define GLUT_WINDOW_X 100 +#define GLUT_WINDOW_Y 101 +#define GLUT_WINDOW_WIDTH 102 +#define GLUT_WINDOW_HEIGHT 103 +#define GLUT_WINDOW_BUFFER_SIZE 104 +#define GLUT_WINDOW_STENCIL_SIZE 105 +#define GLUT_WINDOW_DEPTH_SIZE 106 +#define GLUT_WINDOW_RED_SIZE 107 +#define GLUT_WINDOW_GREEN_SIZE 108 +#define GLUT_WINDOW_BLUE_SIZE 109 +#define GLUT_WINDOW_ALPHA_SIZE 110 +#define GLUT_WINDOW_ACCUM_RED_SIZE 111 +#define GLUT_WINDOW_ACCUM_GREEN_SIZE 112 +#define GLUT_WINDOW_ACCUM_BLUE_SIZE 113 +#define GLUT_WINDOW_ACCUM_ALPHA_SIZE 114 +#define GLUT_WINDOW_DOUBLEBUFFER 115 +#define GLUT_WINDOW_RGBA 116 +#define GLUT_WINDOW_PARENT 117 +#define GLUT_WINDOW_NUM_CHILDREN 118 +#define GLUT_WINDOW_COLORMAP_SIZE 119 +#if (GLUT_API_VERSION >= 2) +#define GLUT_WINDOW_NUM_SAMPLES 120 +#define GLUT_WINDOW_STEREO 121 +#endif +#if (GLUT_API_VERSION >= 3) +#define GLUT_WINDOW_CURSOR 122 +#endif +#define GLUT_SCREEN_WIDTH 200 +#define GLUT_SCREEN_HEIGHT 201 +#define GLUT_SCREEN_WIDTH_MM 202 +#define GLUT_SCREEN_HEIGHT_MM 203 +#define GLUT_MENU_NUM_ITEMS 300 +#define GLUT_DISPLAY_MODE_POSSIBLE 400 +#define GLUT_INIT_WINDOW_X 500 +#define GLUT_INIT_WINDOW_Y 501 +#define GLUT_INIT_WINDOW_WIDTH 502 +#define GLUT_INIT_WINDOW_HEIGHT 503 +#define GLUT_INIT_DISPLAY_MODE 504 +#if (GLUT_API_VERSION >= 2) +#define GLUT_ELAPSED_TIME 700 +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +#define GLUT_WINDOW_FORMAT_ID 123 +#endif + +#if (GLUT_API_VERSION >= 2) +/* glutDeviceGet parameters. */ +#define GLUT_HAS_KEYBOARD 600 +#define GLUT_HAS_MOUSE 601 +#define GLUT_HAS_SPACEBALL 602 +#define GLUT_HAS_DIAL_AND_BUTTON_BOX 603 +#define GLUT_HAS_TABLET 604 +#define GLUT_NUM_MOUSE_BUTTONS 605 +#define GLUT_NUM_SPACEBALL_BUTTONS 606 +#define GLUT_NUM_BUTTON_BOX_BUTTONS 607 +#define GLUT_NUM_DIALS 608 +#define GLUT_NUM_TABLET_BUTTONS 609 +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +#define GLUT_DEVICE_IGNORE_KEY_REPEAT 610 +#define GLUT_DEVICE_KEY_REPEAT 611 +#define GLUT_HAS_JOYSTICK 612 +#define GLUT_OWNS_JOYSTICK 613 +#define GLUT_JOYSTICK_BUTTONS 614 +#define GLUT_JOYSTICK_AXES 615 +#define GLUT_JOYSTICK_POLL_RATE 616 +#endif + +#if (GLUT_API_VERSION >= 3) +/* glutLayerGet parameters. */ +#define GLUT_OVERLAY_POSSIBLE 800 +#define GLUT_LAYER_IN_USE 801 +#define GLUT_HAS_OVERLAY 802 +#define GLUT_TRANSPARENT_INDEX 803 +#define GLUT_NORMAL_DAMAGED 804 +#define GLUT_OVERLAY_DAMAGED 805 + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +/* glutVideoResizeGet parameters. */ +#define GLUT_VIDEO_RESIZE_POSSIBLE 900 +#define GLUT_VIDEO_RESIZE_IN_USE 901 +#define GLUT_VIDEO_RESIZE_X_DELTA 902 +#define GLUT_VIDEO_RESIZE_Y_DELTA 903 +#define GLUT_VIDEO_RESIZE_WIDTH_DELTA 904 +#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 905 +#define GLUT_VIDEO_RESIZE_X 906 +#define GLUT_VIDEO_RESIZE_Y 907 +#define GLUT_VIDEO_RESIZE_WIDTH 908 +#define GLUT_VIDEO_RESIZE_HEIGHT 909 +#endif + +/* glutUseLayer parameters. */ +#define GLUT_NORMAL 0 +#define GLUT_OVERLAY 1 + +/* glutGetModifiers return mask. */ +#define GLUT_ACTIVE_SHIFT 1 +#define GLUT_ACTIVE_CTRL 2 +#define GLUT_ACTIVE_ALT 4 + +/* glutSetCursor parameters. */ +/* Basic arrows. */ +#define GLUT_CURSOR_RIGHT_ARROW 0 +#define GLUT_CURSOR_LEFT_ARROW 1 +/* Symbolic cursor shapes. */ +#define GLUT_CURSOR_INFO 2 +#define GLUT_CURSOR_DESTROY 3 +#define GLUT_CURSOR_HELP 4 +#define GLUT_CURSOR_CYCLE 5 +#define GLUT_CURSOR_SPRAY 6 +#define GLUT_CURSOR_WAIT 7 +#define GLUT_CURSOR_TEXT 8 +#define GLUT_CURSOR_CROSSHAIR 9 +/* Directional cursors. */ +#define GLUT_CURSOR_UP_DOWN 10 +#define GLUT_CURSOR_LEFT_RIGHT 11 +/* Sizing cursors. */ +#define GLUT_CURSOR_TOP_SIDE 12 +#define GLUT_CURSOR_BOTTOM_SIDE 13 +#define GLUT_CURSOR_LEFT_SIDE 14 +#define GLUT_CURSOR_RIGHT_SIDE 15 +#define GLUT_CURSOR_TOP_LEFT_CORNER 16 +#define GLUT_CURSOR_TOP_RIGHT_CORNER 17 +#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18 +#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 19 +/* Inherit from parent window. */ +#define GLUT_CURSOR_INHERIT 100 +/* Blank cursor. */ +#define GLUT_CURSOR_NONE 101 +/* Fullscreen crosshair (if available). */ +#define GLUT_CURSOR_FULL_CROSSHAIR 102 +#endif + +/* GLUT initialization sub-API. */ +extern void APIENTRY glutInit(int *argcp, char **argv); +extern void APIENTRY glutInitDisplayMode(unsigned int mode); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +extern void APIENTRY glutInitDisplayString(const char *string); +#endif +extern void APIENTRY glutInitWindowPosition(int x, int y); +extern void APIENTRY glutInitWindowSize(int width, int height); +extern void APIENTRY glutMainLoop(void); + +/* GLUT window sub-API. */ +extern int APIENTRY glutCreateWindow(const char *title); +extern int APIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height); +extern void APIENTRY glutDestroyWindow(int win); +extern void APIENTRY glutPostRedisplay(void); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) +extern void APIENTRY glutPostWindowRedisplay(int win); +#endif +extern void APIENTRY glutSwapBuffers(void); +extern int APIENTRY glutGetWindow(void); +extern void APIENTRY glutSetWindow(int win); +extern void APIENTRY glutSetWindowTitle(const char *title); +extern void APIENTRY glutSetIconTitle(const char *title); +extern void APIENTRY glutPositionWindow(int x, int y); +extern void APIENTRY glutReshapeWindow(int width, int height); +extern void APIENTRY glutPopWindow(void); +extern void APIENTRY glutPushWindow(void); +extern void APIENTRY glutIconifyWindow(void); +extern void APIENTRY glutShowWindow(void); +extern void APIENTRY glutHideWindow(void); +#if (GLUT_API_VERSION >= 3) +extern void APIENTRY glutFullScreen(void); +extern void APIENTRY glutSetCursor(int cursor); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +extern void APIENTRY glutWarpPointer(int x, int y); +#endif + +/* GLUT overlay sub-API. */ +extern void APIENTRY glutEstablishOverlay(void); +extern void APIENTRY glutRemoveOverlay(void); +extern void APIENTRY glutUseLayer(GLenum layer); +extern void APIENTRY glutPostOverlayRedisplay(void); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) +extern void APIENTRY glutPostWindowOverlayRedisplay(int win); +#endif +extern void APIENTRY glutShowOverlay(void); +extern void APIENTRY glutHideOverlay(void); +#endif + +/* GLUT menu sub-API. */ +extern int APIENTRY glutCreateMenu(void (*)(int)); +extern void APIENTRY glutDestroyMenu(int menu); +extern int APIENTRY glutGetMenu(void); +extern void APIENTRY glutSetMenu(int menu); +extern void APIENTRY glutAddMenuEntry(const char *label, int value); +extern void APIENTRY glutAddSubMenu(const char *label, int submenu); +extern void APIENTRY glutChangeToMenuEntry(int item, const char *label, int value); +extern void APIENTRY glutChangeToSubMenu(int item, const char *label, int submenu); +extern void APIENTRY glutRemoveMenuItem(int item); +extern void APIENTRY glutAttachMenu(int button); +extern void APIENTRY glutDetachMenu(int button); + +/* GLUT window callback sub-API. */ +extern void APIENTRY glutDisplayFunc(void (*func)(void)); +extern void APIENTRY glutReshapeFunc(void (*func)(int width, int height)); +extern void APIENTRY glutKeyboardFunc(void (*func)(unsigned char key, int x, int y)); +extern void APIENTRY glutMouseFunc(void (*func)(int button, int state, int x, int y)); +extern void APIENTRY glutMotionFunc(void (*func)(int x, int y)); +extern void APIENTRY glutPassiveMotionFunc(void (*func)(int x, int y)); +extern void APIENTRY glutEntryFunc(void (*func)(int state)); +extern void APIENTRY glutVisibilityFunc(void (*func)(int state)); +extern void APIENTRY glutIdleFunc(void (*func)(void)); +extern void APIENTRY glutTimerFunc(unsigned int millis, void (*func)(int value), int value); +extern void APIENTRY glutMenuStateFunc(void (*func)(int state)); +#if (GLUT_API_VERSION >= 2) +extern void APIENTRY glutSpecialFunc(void (*func)(int key, int x, int y)); +extern void APIENTRY glutSpaceballMotionFunc(void (*func)(int x, int y, int z)); +extern void APIENTRY glutSpaceballRotateFunc(void (*func)(int x, int y, int z)); +extern void APIENTRY glutSpaceballButtonFunc(void (*func)(int button, int state)); +extern void APIENTRY glutButtonBoxFunc(void (*func)(int button, int state)); +extern void APIENTRY glutDialsFunc(void (*func)(int dial, int value)); +extern void APIENTRY glutTabletMotionFunc(void (*func)(int x, int y)); +extern void APIENTRY glutTabletButtonFunc(void (*func)(int button, int state, int x, int y)); +#if (GLUT_API_VERSION >= 3) +extern void APIENTRY glutMenuStatusFunc(void (*func)(int status, int x, int y)); +extern void APIENTRY glutOverlayDisplayFunc(void (*func)(void)); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +extern void APIENTRY glutWindowStatusFunc(void (*func)(int state)); +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +extern void APIENTRY glutKeyboardUpFunc(void (*func)(unsigned char key, int x, int y)); +extern void APIENTRY glutSpecialUpFunc(void (*func)(int key, int x, int y)); +extern void APIENTRY glutJoystickFunc(void (*func)(unsigned int buttonMask, int x, int y, int z), int pollInterval); +#endif +#endif +#endif + +/* GLUT color index sub-API. */ +extern void APIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); +extern GLfloat APIENTRY glutGetColor(int ndx, int component); +extern void APIENTRY glutCopyColormap(int win); + +/* GLUT state retrieval sub-API. */ +extern int APIENTRY glutGet(GLenum type); +extern int APIENTRY glutDeviceGet(GLenum type); +#if (GLUT_API_VERSION >= 2) +/* GLUT extension support sub-API */ +extern int APIENTRY glutExtensionSupported(const char *name); +#endif +#if (GLUT_API_VERSION >= 3) +extern int APIENTRY glutGetModifiers(void); +extern int APIENTRY glutLayerGet(GLenum type); +#endif + +/* GLUT font sub-API */ +extern void APIENTRY glutBitmapCharacter(void *font, int character); +extern int APIENTRY glutBitmapWidth(void *font, int character); +extern void APIENTRY glutStrokeCharacter(void *font, int character); +extern int APIENTRY glutStrokeWidth(void *font, int character); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +extern int APIENTRY glutBitmapLength(void *font, const unsigned char *string); +extern int APIENTRY glutStrokeLength(void *font, const unsigned char *string); +#endif + +/* GLUT pre-built models sub-API */ +extern void APIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks); +extern void APIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); +extern void APIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); +extern void APIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); +extern void APIENTRY glutWireCube(GLdouble size); +extern void APIENTRY glutSolidCube(GLdouble size); +extern void APIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); +extern void APIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); +extern void APIENTRY glutWireDodecahedron(void); +extern void APIENTRY glutSolidDodecahedron(void); +extern void APIENTRY glutWireTeapot(GLdouble size); +extern void APIENTRY glutSolidTeapot(GLdouble size); +extern void APIENTRY glutWireOctahedron(void); +extern void APIENTRY glutSolidOctahedron(void); +extern void APIENTRY glutWireTetrahedron(void); +extern void APIENTRY glutSolidTetrahedron(void); +extern void APIENTRY glutWireIcosahedron(void); +extern void APIENTRY glutSolidIcosahedron(void); + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +/* GLUT video resize sub-API. */ +extern int APIENTRY glutVideoResizeGet(GLenum param); +extern void APIENTRY glutSetupVideoResizing(void); +extern void APIENTRY glutStopVideoResizing(void); +extern void APIENTRY glutVideoResize(int x, int y, int width, int height); +extern void APIENTRY glutVideoPan(int x, int y, int width, int height); + +/* GLUT debugging sub-API. */ +extern void APIENTRY glutReportErrors(void); +#endif + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +/* GLUT device control sub-API. */ +/* glutSetKeyRepeat modes. */ +#define GLUT_KEY_REPEAT_OFF 0 +#define GLUT_KEY_REPEAT_ON 1 +#define GLUT_KEY_REPEAT_DEFAULT 2 + +/* Joystick button masks. */ +#define GLUT_JOYSTICK_BUTTON_A 1 +#define GLUT_JOYSTICK_BUTTON_B 2 +#define GLUT_JOYSTICK_BUTTON_C 4 +#define GLUT_JOYSTICK_BUTTON_D 8 + +extern void APIENTRY glutIgnoreKeyRepeat(int ignore); +extern void APIENTRY glutSetKeyRepeat(int repeatMode); +extern void APIENTRY glutForceJoystickFunc(void); + +/* GLUT game mode sub-API. */ +/* glutGameModeGet. */ +#define GLUT_GAME_MODE_ACTIVE 0 +#define GLUT_GAME_MODE_POSSIBLE 1 +#define GLUT_GAME_MODE_WIDTH 2 +#define GLUT_GAME_MODE_HEIGHT 3 +#define GLUT_GAME_MODE_PIXEL_DEPTH 4 +#define GLUT_GAME_MODE_REFRESH_RATE 5 +#define GLUT_GAME_MODE_DISPLAY_CHANGED 6 + +extern void APIENTRY glutGameModeString(const char *string); +extern int APIENTRY glutEnterGameMode(void); +extern void APIENTRY glutLeaveGameMode(void); +extern int APIENTRY glutGameModeGet(GLenum mode); +#endif + +#ifdef __cplusplus +} + +#endif + +#ifdef GLUT_APIENTRY_DEFINED +# undef GLUT_APIENTRY_DEFINED +# undef APIENTRY +#endif + +#ifdef GLUT_WINGDIAPI_DEFINED +# undef GLUT_WINGDIAPI_DEFINED +# undef WINGDIAPI +#endif + +#endif /* __glut_h__ */ diff --git a/Glut/GL/glxew.h b/Glut/GL/glxew.h new file mode 100644 index 0000000..6d249f7 --- /dev/null +++ b/Glut/GL/glxew.h @@ -0,0 +1,1587 @@ +/* +** The OpenGL Extension Wrangler Library +** Copyright (C) 2002-2008, Milan Ikits +** Copyright (C) 2002-2008, Marcelo E. Magallon +** Copyright (C) 2002, Lev Povalahev +** 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. +** * The name of the author 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. +*/ + +/* + * Mesa 3-D graphics library + * Version: 7.0 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL 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. + */ + +/* +** Copyright (c) 2007 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are 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 Materials. +** +** THE MATERIALS ARE 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 +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#ifndef __glxew_h__ +#define __glxew_h__ +#define __GLXEW_H__ + +#ifdef __glxext_h_ +#error glxext.h included before glxew.h +#endif + +#if defined(GLX_H) || defined(__GLX_glx_h__) || defined(__glx_h__) +#error glx.h included before glxew.h +#endif + +#define __glxext_h_ + +#define GLX_H +#define __GLX_glx_h__ +#define __glx_h__ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ---------------------------- GLX_VERSION_1_0 --------------------------- */ + +#ifndef GLX_VERSION_1_0 +#define GLX_VERSION_1_0 1 + +#define GLX_USE_GL 1 +#define GLX_BUFFER_SIZE 2 +#define GLX_LEVEL 3 +#define GLX_RGBA 4 +#define GLX_DOUBLEBUFFER 5 +#define GLX_STEREO 6 +#define GLX_AUX_BUFFERS 7 +#define GLX_RED_SIZE 8 +#define GLX_GREEN_SIZE 9 +#define GLX_BLUE_SIZE 10 +#define GLX_ALPHA_SIZE 11 +#define GLX_DEPTH_SIZE 12 +#define GLX_STENCIL_SIZE 13 +#define GLX_ACCUM_RED_SIZE 14 +#define GLX_ACCUM_GREEN_SIZE 15 +#define GLX_ACCUM_BLUE_SIZE 16 +#define GLX_ACCUM_ALPHA_SIZE 17 +#define GLX_BAD_SCREEN 1 +#define GLX_BAD_ATTRIBUTE 2 +#define GLX_NO_EXTENSION 3 +#define GLX_BAD_VISUAL 4 +#define GLX_BAD_CONTEXT 5 +#define GLX_BAD_VALUE 6 +#define GLX_BAD_ENUM 7 + +typedef XID GLXDrawable; +typedef XID GLXPixmap; +#ifdef __sun +typedef struct __glXContextRec *GLXContext; +#else +typedef struct __GLXcontextRec *GLXContext; +#endif + +typedef unsigned int GLXVideoDeviceNV; + +extern Bool glXQueryExtension (Display *dpy, int *errorBase, int *eventBase); +extern Bool glXQueryVersion (Display *dpy, int *major, int *minor); +extern int glXGetConfig (Display *dpy, XVisualInfo *vis, int attrib, int *value); +extern XVisualInfo* glXChooseVisual (Display *dpy, int screen, int *attribList); +extern GLXPixmap glXCreateGLXPixmap (Display *dpy, XVisualInfo *vis, Pixmap pixmap); +extern void glXDestroyGLXPixmap (Display *dpy, GLXPixmap pix); +extern GLXContext glXCreateContext (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct); +extern void glXDestroyContext (Display *dpy, GLXContext ctx); +extern Bool glXIsDirect (Display *dpy, GLXContext ctx); +extern void glXCopyContext (Display *dpy, GLXContext src, GLXContext dst, GLulong mask); +extern Bool glXMakeCurrent (Display *dpy, GLXDrawable drawable, GLXContext ctx); +extern GLXContext glXGetCurrentContext (void); +extern GLXDrawable glXGetCurrentDrawable (void); +extern void glXWaitGL (void); +extern void glXWaitX (void); +extern void glXSwapBuffers (Display *dpy, GLXDrawable drawable); +extern void glXUseXFont (Font font, int first, int count, int listBase); + +#define GLXEW_VERSION_1_0 GLXEW_GET_VAR(__GLXEW_VERSION_1_0) + +#endif /* GLX_VERSION_1_0 */ + +/* ---------------------------- GLX_VERSION_1_1 --------------------------- */ + +#ifndef GLX_VERSION_1_1 +#define GLX_VERSION_1_1 + +#define GLX_VENDOR 0x1 +#define GLX_VERSION 0x2 +#define GLX_EXTENSIONS 0x3 + +extern const char* glXQueryExtensionsString (Display *dpy, int screen); +extern const char* glXGetClientString (Display *dpy, int name); +extern const char* glXQueryServerString (Display *dpy, int screen, int name); + +#define GLXEW_VERSION_1_1 GLXEW_GET_VAR(__GLXEW_VERSION_1_1) + +#endif /* GLX_VERSION_1_1 */ + +/* ---------------------------- GLX_VERSION_1_2 ---------------------------- */ + +#ifndef GLX_VERSION_1_2 +#define GLX_VERSION_1_2 1 + +typedef Display* ( * PFNGLXGETCURRENTDISPLAYPROC) (void); + +#define glXGetCurrentDisplay GLXEW_GET_FUN(__glewXGetCurrentDisplay) + +#define GLXEW_VERSION_1_2 GLXEW_GET_VAR(__GLXEW_VERSION_1_2) + +#endif /* GLX_VERSION_1_2 */ + +/* ---------------------------- GLX_VERSION_1_3 ---------------------------- */ + +#ifndef GLX_VERSION_1_3 +#define GLX_VERSION_1_3 1 + +#define GLX_RGBA_BIT 0x00000001 +#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 +#define GLX_WINDOW_BIT 0x00000001 +#define GLX_COLOR_INDEX_BIT 0x00000002 +#define GLX_PIXMAP_BIT 0x00000002 +#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 +#define GLX_PBUFFER_BIT 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 +#define GLX_AUX_BUFFERS_BIT 0x00000010 +#define GLX_CONFIG_CAVEAT 0x20 +#define GLX_DEPTH_BUFFER_BIT 0x00000020 +#define GLX_X_VISUAL_TYPE 0x22 +#define GLX_TRANSPARENT_TYPE 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE 0x24 +#define GLX_TRANSPARENT_RED_VALUE 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE 0x28 +#define GLX_STENCIL_BUFFER_BIT 0x00000040 +#define GLX_ACCUM_BUFFER_BIT 0x00000080 +#define GLX_NONE 0x8000 +#define GLX_SLOW_CONFIG 0x8001 +#define GLX_TRUE_COLOR 0x8002 +#define GLX_DIRECT_COLOR 0x8003 +#define GLX_PSEUDO_COLOR 0x8004 +#define GLX_STATIC_COLOR 0x8005 +#define GLX_GRAY_SCALE 0x8006 +#define GLX_STATIC_GRAY 0x8007 +#define GLX_TRANSPARENT_RGB 0x8008 +#define GLX_TRANSPARENT_INDEX 0x8009 +#define GLX_VISUAL_ID 0x800B +#define GLX_SCREEN 0x800C +#define GLX_NON_CONFORMANT_CONFIG 0x800D +#define GLX_DRAWABLE_TYPE 0x8010 +#define GLX_RENDER_TYPE 0x8011 +#define GLX_X_RENDERABLE 0x8012 +#define GLX_FBCONFIG_ID 0x8013 +#define GLX_RGBA_TYPE 0x8014 +#define GLX_COLOR_INDEX_TYPE 0x8015 +#define GLX_MAX_PBUFFER_WIDTH 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT 0x8017 +#define GLX_MAX_PBUFFER_PIXELS 0x8018 +#define GLX_PRESERVED_CONTENTS 0x801B +#define GLX_LARGEST_PBUFFER 0x801C +#define GLX_WIDTH 0x801D +#define GLX_HEIGHT 0x801E +#define GLX_EVENT_MASK 0x801F +#define GLX_DAMAGED 0x8020 +#define GLX_SAVED 0x8021 +#define GLX_WINDOW 0x8022 +#define GLX_PBUFFER 0x8023 +#define GLX_PBUFFER_HEIGHT 0x8040 +#define GLX_PBUFFER_WIDTH 0x8041 +#define GLX_PBUFFER_CLOBBER_MASK 0x08000000 +#define GLX_DONT_CARE 0xFFFFFFFF + +typedef XID GLXFBConfigID; +typedef XID GLXPbuffer; +typedef XID GLXWindow; +typedef struct __GLXFBConfigRec *GLXFBConfig; + +typedef struct { + int event_type; + int draw_type; + unsigned long serial; + Bool send_event; + Display *display; + GLXDrawable drawable; + unsigned int buffer_mask; + unsigned int aux_buffer; + int x, y; + int width, height; + int count; +} GLXPbufferClobberEvent; +typedef union __GLXEvent { + GLXPbufferClobberEvent glxpbufferclobber; + long pad[24]; +} GLXEvent; + +typedef GLXFBConfig* ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); +typedef GLXContext ( * PFNGLXCREATENEWCONTEXTPROC) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +typedef GLXPbuffer ( * PFNGLXCREATEPBUFFERPROC) (Display *dpy, GLXFBConfig config, const int *attrib_list); +typedef GLXPixmap ( * PFNGLXCREATEPIXMAPPROC) (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list); +typedef GLXWindow ( * PFNGLXCREATEWINDOWPROC) (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list); +typedef void ( * PFNGLXDESTROYPBUFFERPROC) (Display *dpy, GLXPbuffer pbuf); +typedef void ( * PFNGLXDESTROYPIXMAPPROC) (Display *dpy, GLXPixmap pixmap); +typedef void ( * PFNGLXDESTROYWINDOWPROC) (Display *dpy, GLXWindow win); +typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLEPROC) (void); +typedef int ( * PFNGLXGETFBCONFIGATTRIBPROC) (Display *dpy, GLXFBConfig config, int attribute, int *value); +typedef GLXFBConfig* ( * PFNGLXGETFBCONFIGSPROC) (Display *dpy, int screen, int *nelements); +typedef void ( * PFNGLXGETSELECTEDEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long *event_mask); +typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config); +typedef Bool ( * PFNGLXMAKECONTEXTCURRENTPROC) (Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +typedef int ( * PFNGLXQUERYCONTEXTPROC) (Display *dpy, GLXContext ctx, int attribute, int *value); +typedef void ( * PFNGLXQUERYDRAWABLEPROC) (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); +typedef void ( * PFNGLXSELECTEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long event_mask); + +#define glXChooseFBConfig GLXEW_GET_FUN(__glewXChooseFBConfig) +#define glXCreateNewContext GLXEW_GET_FUN(__glewXCreateNewContext) +#define glXCreatePbuffer GLXEW_GET_FUN(__glewXCreatePbuffer) +#define glXCreatePixmap GLXEW_GET_FUN(__glewXCreatePixmap) +#define glXCreateWindow GLXEW_GET_FUN(__glewXCreateWindow) +#define glXDestroyPbuffer GLXEW_GET_FUN(__glewXDestroyPbuffer) +#define glXDestroyPixmap GLXEW_GET_FUN(__glewXDestroyPixmap) +#define glXDestroyWindow GLXEW_GET_FUN(__glewXDestroyWindow) +#define glXGetCurrentReadDrawable GLXEW_GET_FUN(__glewXGetCurrentReadDrawable) +#define glXGetFBConfigAttrib GLXEW_GET_FUN(__glewXGetFBConfigAttrib) +#define glXGetFBConfigs GLXEW_GET_FUN(__glewXGetFBConfigs) +#define glXGetSelectedEvent GLXEW_GET_FUN(__glewXGetSelectedEvent) +#define glXGetVisualFromFBConfig GLXEW_GET_FUN(__glewXGetVisualFromFBConfig) +#define glXMakeContextCurrent GLXEW_GET_FUN(__glewXMakeContextCurrent) +#define glXQueryContext GLXEW_GET_FUN(__glewXQueryContext) +#define glXQueryDrawable GLXEW_GET_FUN(__glewXQueryDrawable) +#define glXSelectEvent GLXEW_GET_FUN(__glewXSelectEvent) + +#define GLXEW_VERSION_1_3 GLXEW_GET_VAR(__GLXEW_VERSION_1_3) + +#endif /* GLX_VERSION_1_3 */ + +/* ---------------------------- GLX_VERSION_1_4 ---------------------------- */ + +#ifndef GLX_VERSION_1_4 +#define GLX_VERSION_1_4 1 + +#define GLX_SAMPLE_BUFFERS 100000 +#define GLX_SAMPLES 100001 + +extern void ( * glXGetProcAddress (const GLubyte *procName)) (void); + +#define GLXEW_VERSION_1_4 GLXEW_GET_VAR(__GLXEW_VERSION_1_4) + +#endif /* GLX_VERSION_1_4 */ + +/* -------------------------- GLX_3DFX_multisample ------------------------- */ + +#ifndef GLX_3DFX_multisample +#define GLX_3DFX_multisample 1 + +#define GLX_SAMPLE_BUFFERS_3DFX 0x8050 +#define GLX_SAMPLES_3DFX 0x8051 + +#define GLXEW_3DFX_multisample GLXEW_GET_VAR(__GLXEW_3DFX_multisample) + +#endif /* GLX_3DFX_multisample */ + +/* ------------------------ GLX_AMD_gpu_association ------------------------ */ + +#ifndef GLX_AMD_gpu_association +#define GLX_AMD_gpu_association 1 + +#define GLX_GPU_VENDOR_AMD 0x1F00 +#define GLX_GPU_RENDERER_STRING_AMD 0x1F01 +#define GLX_GPU_OPENGL_VERSION_STRING_AMD 0x1F02 +#define GLX_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2 +#define GLX_GPU_RAM_AMD 0x21A3 +#define GLX_GPU_CLOCK_AMD 0x21A4 +#define GLX_GPU_NUM_PIPES_AMD 0x21A5 +#define GLX_GPU_NUM_SIMD_AMD 0x21A6 +#define GLX_GPU_NUM_RB_AMD 0x21A7 +#define GLX_GPU_NUM_SPI_AMD 0x21A8 + +#define GLXEW_AMD_gpu_association GLXEW_GET_VAR(__GLXEW_AMD_gpu_association) + +#endif /* GLX_AMD_gpu_association */ + +/* ------------------------- GLX_ARB_create_context ------------------------ */ + +#ifndef GLX_ARB_create_context +#define GLX_ARB_create_context 1 + +#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define GLX_CONTEXT_FLAGS_ARB 0x2094 + +typedef GLXContext ( * PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list); + +#define glXCreateContextAttribsARB GLXEW_GET_FUN(__glewXCreateContextAttribsARB) + +#define GLXEW_ARB_create_context GLXEW_GET_VAR(__GLXEW_ARB_create_context) + +#endif /* GLX_ARB_create_context */ + +/* --------------------- GLX_ARB_create_context_profile -------------------- */ + +#ifndef GLX_ARB_create_context_profile +#define GLX_ARB_create_context_profile 1 + +#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 + +#define GLXEW_ARB_create_context_profile GLXEW_GET_VAR(__GLXEW_ARB_create_context_profile) + +#endif /* GLX_ARB_create_context_profile */ + +/* ------------------- GLX_ARB_create_context_robustness ------------------- */ + +#ifndef GLX_ARB_create_context_robustness +#define GLX_ARB_create_context_robustness 1 + +#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261 + +#define GLXEW_ARB_create_context_robustness GLXEW_GET_VAR(__GLXEW_ARB_create_context_robustness) + +#endif /* GLX_ARB_create_context_robustness */ + +/* ------------------------- GLX_ARB_fbconfig_float ------------------------ */ + +#ifndef GLX_ARB_fbconfig_float +#define GLX_ARB_fbconfig_float 1 + +#define GLX_RGBA_FLOAT_BIT 0x00000004 +#define GLX_RGBA_FLOAT_TYPE 0x20B9 + +#define GLXEW_ARB_fbconfig_float GLXEW_GET_VAR(__GLXEW_ARB_fbconfig_float) + +#endif /* GLX_ARB_fbconfig_float */ + +/* ------------------------ GLX_ARB_framebuffer_sRGB ----------------------- */ + +#ifndef GLX_ARB_framebuffer_sRGB +#define GLX_ARB_framebuffer_sRGB 1 + +#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2 + +#define GLXEW_ARB_framebuffer_sRGB GLXEW_GET_VAR(__GLXEW_ARB_framebuffer_sRGB) + +#endif /* GLX_ARB_framebuffer_sRGB */ + +/* ------------------------ GLX_ARB_get_proc_address ----------------------- */ + +#ifndef GLX_ARB_get_proc_address +#define GLX_ARB_get_proc_address 1 + +extern void ( * glXGetProcAddressARB (const GLubyte *procName)) (void); + +#define GLXEW_ARB_get_proc_address GLXEW_GET_VAR(__GLXEW_ARB_get_proc_address) + +#endif /* GLX_ARB_get_proc_address */ + +/* -------------------------- GLX_ARB_multisample -------------------------- */ + +#ifndef GLX_ARB_multisample +#define GLX_ARB_multisample 1 + +#define GLX_SAMPLE_BUFFERS_ARB 100000 +#define GLX_SAMPLES_ARB 100001 + +#define GLXEW_ARB_multisample GLXEW_GET_VAR(__GLXEW_ARB_multisample) + +#endif /* GLX_ARB_multisample */ + +/* ---------------------- GLX_ARB_vertex_buffer_object --------------------- */ + +#ifndef GLX_ARB_vertex_buffer_object +#define GLX_ARB_vertex_buffer_object 1 + +#define GLX_CONTEXT_ALLOW_BUFFER_BYTE_ORDER_MISMATCH_ARB 0x2095 + +#define GLXEW_ARB_vertex_buffer_object GLXEW_GET_VAR(__GLXEW_ARB_vertex_buffer_object) + +#endif /* GLX_ARB_vertex_buffer_object */ + +/* ----------------------- GLX_ATI_pixel_format_float ---------------------- */ + +#ifndef GLX_ATI_pixel_format_float +#define GLX_ATI_pixel_format_float 1 + +#define GLX_RGBA_FLOAT_ATI_BIT 0x00000100 + +#define GLXEW_ATI_pixel_format_float GLXEW_GET_VAR(__GLXEW_ATI_pixel_format_float) + +#endif /* GLX_ATI_pixel_format_float */ + +/* ------------------------- GLX_ATI_render_texture ------------------------ */ + +#ifndef GLX_ATI_render_texture +#define GLX_ATI_render_texture 1 + +#define GLX_BIND_TO_TEXTURE_RGB_ATI 0x9800 +#define GLX_BIND_TO_TEXTURE_RGBA_ATI 0x9801 +#define GLX_TEXTURE_FORMAT_ATI 0x9802 +#define GLX_TEXTURE_TARGET_ATI 0x9803 +#define GLX_MIPMAP_TEXTURE_ATI 0x9804 +#define GLX_TEXTURE_RGB_ATI 0x9805 +#define GLX_TEXTURE_RGBA_ATI 0x9806 +#define GLX_NO_TEXTURE_ATI 0x9807 +#define GLX_TEXTURE_CUBE_MAP_ATI 0x9808 +#define GLX_TEXTURE_1D_ATI 0x9809 +#define GLX_TEXTURE_2D_ATI 0x980A +#define GLX_MIPMAP_LEVEL_ATI 0x980B +#define GLX_CUBE_MAP_FACE_ATI 0x980C +#define GLX_TEXTURE_CUBE_MAP_POSITIVE_X_ATI 0x980D +#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_X_ATI 0x980E +#define GLX_TEXTURE_CUBE_MAP_POSITIVE_Y_ATI 0x980F +#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_Y_ATI 0x9810 +#define GLX_TEXTURE_CUBE_MAP_POSITIVE_Z_ATI 0x9811 +#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_Z_ATI 0x9812 +#define GLX_FRONT_LEFT_ATI 0x9813 +#define GLX_FRONT_RIGHT_ATI 0x9814 +#define GLX_BACK_LEFT_ATI 0x9815 +#define GLX_BACK_RIGHT_ATI 0x9816 +#define GLX_AUX0_ATI 0x9817 +#define GLX_AUX1_ATI 0x9818 +#define GLX_AUX2_ATI 0x9819 +#define GLX_AUX3_ATI 0x981A +#define GLX_AUX4_ATI 0x981B +#define GLX_AUX5_ATI 0x981C +#define GLX_AUX6_ATI 0x981D +#define GLX_AUX7_ATI 0x981E +#define GLX_AUX8_ATI 0x981F +#define GLX_AUX9_ATI 0x9820 +#define GLX_BIND_TO_TEXTURE_LUMINANCE_ATI 0x9821 +#define GLX_BIND_TO_TEXTURE_INTENSITY_ATI 0x9822 + +typedef void ( * PFNGLXBINDTEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, int buffer); +typedef void ( * PFNGLXDRAWABLEATTRIBATIPROC) (Display *dpy, GLXDrawable draw, const int *attrib_list); +typedef void ( * PFNGLXRELEASETEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, int buffer); + +#define glXBindTexImageATI GLXEW_GET_FUN(__glewXBindTexImageATI) +#define glXDrawableAttribATI GLXEW_GET_FUN(__glewXDrawableAttribATI) +#define glXReleaseTexImageATI GLXEW_GET_FUN(__glewXReleaseTexImageATI) + +#define GLXEW_ATI_render_texture GLXEW_GET_VAR(__GLXEW_ATI_render_texture) + +#endif /* GLX_ATI_render_texture */ + +/* ------------------- GLX_EXT_create_context_es2_profile ------------------ */ + +#ifndef GLX_EXT_create_context_es2_profile +#define GLX_EXT_create_context_es2_profile 1 + +#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 + +#define GLXEW_EXT_create_context_es2_profile GLXEW_GET_VAR(__GLXEW_EXT_create_context_es2_profile) + +#endif /* GLX_EXT_create_context_es2_profile */ + +/* --------------------- GLX_EXT_fbconfig_packed_float --------------------- */ + +#ifndef GLX_EXT_fbconfig_packed_float +#define GLX_EXT_fbconfig_packed_float 1 + +#define GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT 0x00000008 +#define GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT 0x20B1 + +#define GLXEW_EXT_fbconfig_packed_float GLXEW_GET_VAR(__GLXEW_EXT_fbconfig_packed_float) + +#endif /* GLX_EXT_fbconfig_packed_float */ + +/* ------------------------ GLX_EXT_framebuffer_sRGB ----------------------- */ + +#ifndef GLX_EXT_framebuffer_sRGB +#define GLX_EXT_framebuffer_sRGB 1 + +#define GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20B2 + +#define GLXEW_EXT_framebuffer_sRGB GLXEW_GET_VAR(__GLXEW_EXT_framebuffer_sRGB) + +#endif /* GLX_EXT_framebuffer_sRGB */ + +/* ------------------------- GLX_EXT_import_context ------------------------ */ + +#ifndef GLX_EXT_import_context +#define GLX_EXT_import_context 1 + +#define GLX_SHARE_CONTEXT_EXT 0x800A +#define GLX_VISUAL_ID_EXT 0x800B +#define GLX_SCREEN_EXT 0x800C + +typedef XID GLXContextID; + +typedef void ( * PFNGLXFREECONTEXTEXTPROC) (Display* dpy, GLXContext context); +typedef GLXContextID ( * PFNGLXGETCONTEXTIDEXTPROC) (const GLXContext context); +typedef GLXContext ( * PFNGLXIMPORTCONTEXTEXTPROC) (Display* dpy, GLXContextID contextID); +typedef int ( * PFNGLXQUERYCONTEXTINFOEXTPROC) (Display* dpy, GLXContext context, int attribute,int *value); + +#define glXFreeContextEXT GLXEW_GET_FUN(__glewXFreeContextEXT) +#define glXGetContextIDEXT GLXEW_GET_FUN(__glewXGetContextIDEXT) +#define glXImportContextEXT GLXEW_GET_FUN(__glewXImportContextEXT) +#define glXQueryContextInfoEXT GLXEW_GET_FUN(__glewXQueryContextInfoEXT) + +#define GLXEW_EXT_import_context GLXEW_GET_VAR(__GLXEW_EXT_import_context) + +#endif /* GLX_EXT_import_context */ + +/* -------------------------- GLX_EXT_scene_marker ------------------------- */ + +#ifndef GLX_EXT_scene_marker +#define GLX_EXT_scene_marker 1 + +#define GLXEW_EXT_scene_marker GLXEW_GET_VAR(__GLXEW_EXT_scene_marker) + +#endif /* GLX_EXT_scene_marker */ + +/* -------------------------- GLX_EXT_swap_control ------------------------- */ + +#ifndef GLX_EXT_swap_control +#define GLX_EXT_swap_control 1 + +#define GLX_SWAP_INTERVAL_EXT 0x20F1 +#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2 + +typedef void ( * PFNGLXSWAPINTERVALEXTPROC) (Display* dpy, GLXDrawable drawable, int interval); + +#define glXSwapIntervalEXT GLXEW_GET_FUN(__glewXSwapIntervalEXT) + +#define GLXEW_EXT_swap_control GLXEW_GET_VAR(__GLXEW_EXT_swap_control) + +#endif /* GLX_EXT_swap_control */ + +/* ---------------------- GLX_EXT_texture_from_pixmap ---------------------- */ + +#ifndef GLX_EXT_texture_from_pixmap +#define GLX_EXT_texture_from_pixmap 1 + +#define GLX_TEXTURE_1D_BIT_EXT 0x00000001 +#define GLX_TEXTURE_2D_BIT_EXT 0x00000002 +#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004 +#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0 +#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1 +#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2 +#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3 +#define GLX_Y_INVERTED_EXT 0x20D4 +#define GLX_TEXTURE_FORMAT_EXT 0x20D5 +#define GLX_TEXTURE_TARGET_EXT 0x20D6 +#define GLX_MIPMAP_TEXTURE_EXT 0x20D7 +#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8 +#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9 +#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA +#define GLX_TEXTURE_1D_EXT 0x20DB +#define GLX_TEXTURE_2D_EXT 0x20DC +#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD +#define GLX_FRONT_LEFT_EXT 0x20DE +#define GLX_FRONT_RIGHT_EXT 0x20DF +#define GLX_BACK_LEFT_EXT 0x20E0 +#define GLX_BACK_RIGHT_EXT 0x20E1 +#define GLX_AUX0_EXT 0x20E2 +#define GLX_AUX1_EXT 0x20E3 +#define GLX_AUX2_EXT 0x20E4 +#define GLX_AUX3_EXT 0x20E5 +#define GLX_AUX4_EXT 0x20E6 +#define GLX_AUX5_EXT 0x20E7 +#define GLX_AUX6_EXT 0x20E8 +#define GLX_AUX7_EXT 0x20E9 +#define GLX_AUX8_EXT 0x20EA +#define GLX_AUX9_EXT 0x20EB + +typedef void ( * PFNGLXBINDTEXIMAGEEXTPROC) (Display* display, GLXDrawable drawable, int buffer, const int *attrib_list); +typedef void ( * PFNGLXRELEASETEXIMAGEEXTPROC) (Display* display, GLXDrawable drawable, int buffer); + +#define glXBindTexImageEXT GLXEW_GET_FUN(__glewXBindTexImageEXT) +#define glXReleaseTexImageEXT GLXEW_GET_FUN(__glewXReleaseTexImageEXT) + +#define GLXEW_EXT_texture_from_pixmap GLXEW_GET_VAR(__GLXEW_EXT_texture_from_pixmap) + +#endif /* GLX_EXT_texture_from_pixmap */ + +/* -------------------------- GLX_EXT_visual_info -------------------------- */ + +#ifndef GLX_EXT_visual_info +#define GLX_EXT_visual_info 1 + +#define GLX_X_VISUAL_TYPE_EXT 0x22 +#define GLX_TRANSPARENT_TYPE_EXT 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24 +#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28 +#define GLX_NONE_EXT 0x8000 +#define GLX_TRUE_COLOR_EXT 0x8002 +#define GLX_DIRECT_COLOR_EXT 0x8003 +#define GLX_PSEUDO_COLOR_EXT 0x8004 +#define GLX_STATIC_COLOR_EXT 0x8005 +#define GLX_GRAY_SCALE_EXT 0x8006 +#define GLX_STATIC_GRAY_EXT 0x8007 +#define GLX_TRANSPARENT_RGB_EXT 0x8008 +#define GLX_TRANSPARENT_INDEX_EXT 0x8009 + +#define GLXEW_EXT_visual_info GLXEW_GET_VAR(__GLXEW_EXT_visual_info) + +#endif /* GLX_EXT_visual_info */ + +/* ------------------------- GLX_EXT_visual_rating ------------------------- */ + +#ifndef GLX_EXT_visual_rating +#define GLX_EXT_visual_rating 1 + +#define GLX_VISUAL_CAVEAT_EXT 0x20 +#define GLX_SLOW_VISUAL_EXT 0x8001 +#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D + +#define GLXEW_EXT_visual_rating GLXEW_GET_VAR(__GLXEW_EXT_visual_rating) + +#endif /* GLX_EXT_visual_rating */ + +/* -------------------------- GLX_INTEL_swap_event ------------------------- */ + +#ifndef GLX_INTEL_swap_event +#define GLX_INTEL_swap_event 1 + +#define GLX_EXCHANGE_COMPLETE_INTEL 0x8180 +#define GLX_COPY_COMPLETE_INTEL 0x8181 +#define GLX_FLIP_COMPLETE_INTEL 0x8182 +#define GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK 0x04000000 + +#define GLXEW_INTEL_swap_event GLXEW_GET_VAR(__GLXEW_INTEL_swap_event) + +#endif /* GLX_INTEL_swap_event */ + +/* -------------------------- GLX_MESA_agp_offset -------------------------- */ + +#ifndef GLX_MESA_agp_offset +#define GLX_MESA_agp_offset 1 + +typedef unsigned int ( * PFNGLXGETAGPOFFSETMESAPROC) (const void* pointer); + +#define glXGetAGPOffsetMESA GLXEW_GET_FUN(__glewXGetAGPOffsetMESA) + +#define GLXEW_MESA_agp_offset GLXEW_GET_VAR(__GLXEW_MESA_agp_offset) + +#endif /* GLX_MESA_agp_offset */ + +/* ------------------------ GLX_MESA_copy_sub_buffer ----------------------- */ + +#ifndef GLX_MESA_copy_sub_buffer +#define GLX_MESA_copy_sub_buffer 1 + +typedef void ( * PFNGLXCOPYSUBBUFFERMESAPROC) (Display* dpy, GLXDrawable drawable, int x, int y, int width, int height); + +#define glXCopySubBufferMESA GLXEW_GET_FUN(__glewXCopySubBufferMESA) + +#define GLXEW_MESA_copy_sub_buffer GLXEW_GET_VAR(__GLXEW_MESA_copy_sub_buffer) + +#endif /* GLX_MESA_copy_sub_buffer */ + +/* ------------------------ GLX_MESA_pixmap_colormap ----------------------- */ + +#ifndef GLX_MESA_pixmap_colormap +#define GLX_MESA_pixmap_colormap 1 + +typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPMESAPROC) (Display* dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap); + +#define glXCreateGLXPixmapMESA GLXEW_GET_FUN(__glewXCreateGLXPixmapMESA) + +#define GLXEW_MESA_pixmap_colormap GLXEW_GET_VAR(__GLXEW_MESA_pixmap_colormap) + +#endif /* GLX_MESA_pixmap_colormap */ + +/* ------------------------ GLX_MESA_release_buffers ----------------------- */ + +#ifndef GLX_MESA_release_buffers +#define GLX_MESA_release_buffers 1 + +typedef Bool ( * PFNGLXRELEASEBUFFERSMESAPROC) (Display* dpy, GLXDrawable d); + +#define glXReleaseBuffersMESA GLXEW_GET_FUN(__glewXReleaseBuffersMESA) + +#define GLXEW_MESA_release_buffers GLXEW_GET_VAR(__GLXEW_MESA_release_buffers) + +#endif /* GLX_MESA_release_buffers */ + +/* ------------------------- GLX_MESA_set_3dfx_mode ------------------------ */ + +#ifndef GLX_MESA_set_3dfx_mode +#define GLX_MESA_set_3dfx_mode 1 + +#define GLX_3DFX_WINDOW_MODE_MESA 0x1 +#define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2 + +typedef GLboolean ( * PFNGLXSET3DFXMODEMESAPROC) (GLint mode); + +#define glXSet3DfxModeMESA GLXEW_GET_FUN(__glewXSet3DfxModeMESA) + +#define GLXEW_MESA_set_3dfx_mode GLXEW_GET_VAR(__GLXEW_MESA_set_3dfx_mode) + +#endif /* GLX_MESA_set_3dfx_mode */ + +/* ------------------------- GLX_MESA_swap_control ------------------------- */ + +#ifndef GLX_MESA_swap_control +#define GLX_MESA_swap_control 1 + +typedef int ( * PFNGLXGETSWAPINTERVALMESAPROC) (void); +typedef int ( * PFNGLXSWAPINTERVALMESAPROC) (unsigned int interval); + +#define glXGetSwapIntervalMESA GLXEW_GET_FUN(__glewXGetSwapIntervalMESA) +#define glXSwapIntervalMESA GLXEW_GET_FUN(__glewXSwapIntervalMESA) + +#define GLXEW_MESA_swap_control GLXEW_GET_VAR(__GLXEW_MESA_swap_control) + +#endif /* GLX_MESA_swap_control */ + +/* --------------------------- GLX_NV_copy_image --------------------------- */ + +#ifndef GLX_NV_copy_image +#define GLX_NV_copy_image 1 + +typedef void ( * PFNGLXCOPYIMAGESUBDATANVPROC) (Display *dpy, GLXContext srcCtx, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLXContext dstCtx, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); + +#define glXCopyImageSubDataNV GLXEW_GET_FUN(__glewXCopyImageSubDataNV) + +#define GLXEW_NV_copy_image GLXEW_GET_VAR(__GLXEW_NV_copy_image) + +#endif /* GLX_NV_copy_image */ + +/* -------------------------- GLX_NV_float_buffer -------------------------- */ + +#ifndef GLX_NV_float_buffer +#define GLX_NV_float_buffer 1 + +#define GLX_FLOAT_COMPONENTS_NV 0x20B0 + +#define GLXEW_NV_float_buffer GLXEW_GET_VAR(__GLXEW_NV_float_buffer) + +#endif /* GLX_NV_float_buffer */ + +/* ---------------------- GLX_NV_multisample_coverage ---------------------- */ + +#ifndef GLX_NV_multisample_coverage +#define GLX_NV_multisample_coverage 1 + +#define GLX_COLOR_SAMPLES_NV 0x20B3 +#define GLX_COVERAGE_SAMPLES_NV 100001 + +#define GLXEW_NV_multisample_coverage GLXEW_GET_VAR(__GLXEW_NV_multisample_coverage) + +#endif /* GLX_NV_multisample_coverage */ + +/* -------------------------- GLX_NV_present_video ------------------------- */ + +#ifndef GLX_NV_present_video +#define GLX_NV_present_video 1 + +#define GLX_NUM_VIDEO_SLOTS_NV 0x20F0 + +typedef int ( * PFNGLXBINDVIDEODEVICENVPROC) (Display* dpy, unsigned int video_slot, unsigned int video_device, const int *attrib_list); +typedef unsigned int* ( * PFNGLXENUMERATEVIDEODEVICESNVPROC) (Display *dpy, int screen, int *nelements); + +#define glXBindVideoDeviceNV GLXEW_GET_FUN(__glewXBindVideoDeviceNV) +#define glXEnumerateVideoDevicesNV GLXEW_GET_FUN(__glewXEnumerateVideoDevicesNV) + +#define GLXEW_NV_present_video GLXEW_GET_VAR(__GLXEW_NV_present_video) + +#endif /* GLX_NV_present_video */ + +/* --------------------------- GLX_NV_swap_group --------------------------- */ + +#ifndef GLX_NV_swap_group +#define GLX_NV_swap_group 1 + +typedef Bool ( * PFNGLXBINDSWAPBARRIERNVPROC) (Display* dpy, GLuint group, GLuint barrier); +typedef Bool ( * PFNGLXJOINSWAPGROUPNVPROC) (Display* dpy, GLXDrawable drawable, GLuint group); +typedef Bool ( * PFNGLXQUERYFRAMECOUNTNVPROC) (Display* dpy, int screen, GLuint *count); +typedef Bool ( * PFNGLXQUERYMAXSWAPGROUPSNVPROC) (Display* dpy, int screen, GLuint *maxGroups, GLuint *maxBarriers); +typedef Bool ( * PFNGLXQUERYSWAPGROUPNVPROC) (Display* dpy, GLXDrawable drawable, GLuint *group, GLuint *barrier); +typedef Bool ( * PFNGLXRESETFRAMECOUNTNVPROC) (Display* dpy, int screen); + +#define glXBindSwapBarrierNV GLXEW_GET_FUN(__glewXBindSwapBarrierNV) +#define glXJoinSwapGroupNV GLXEW_GET_FUN(__glewXJoinSwapGroupNV) +#define glXQueryFrameCountNV GLXEW_GET_FUN(__glewXQueryFrameCountNV) +#define glXQueryMaxSwapGroupsNV GLXEW_GET_FUN(__glewXQueryMaxSwapGroupsNV) +#define glXQuerySwapGroupNV GLXEW_GET_FUN(__glewXQuerySwapGroupNV) +#define glXResetFrameCountNV GLXEW_GET_FUN(__glewXResetFrameCountNV) + +#define GLXEW_NV_swap_group GLXEW_GET_VAR(__GLXEW_NV_swap_group) + +#endif /* GLX_NV_swap_group */ + +/* ----------------------- GLX_NV_vertex_array_range ----------------------- */ + +#ifndef GLX_NV_vertex_array_range +#define GLX_NV_vertex_array_range 1 + +typedef void * ( * PFNGLXALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority); +typedef void ( * PFNGLXFREEMEMORYNVPROC) (void *pointer); + +#define glXAllocateMemoryNV GLXEW_GET_FUN(__glewXAllocateMemoryNV) +#define glXFreeMemoryNV GLXEW_GET_FUN(__glewXFreeMemoryNV) + +#define GLXEW_NV_vertex_array_range GLXEW_GET_VAR(__GLXEW_NV_vertex_array_range) + +#endif /* GLX_NV_vertex_array_range */ + +/* -------------------------- GLX_NV_video_capture ------------------------- */ + +#ifndef GLX_NV_video_capture +#define GLX_NV_video_capture 1 + +#define GLX_DEVICE_ID_NV 0x20CD +#define GLX_UNIQUE_ID_NV 0x20CE +#define GLX_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF + +typedef XID GLXVideoCaptureDeviceNV; + +typedef int ( * PFNGLXBINDVIDEOCAPTUREDEVICENVPROC) (Display* dpy, unsigned int video_capture_slot, GLXVideoCaptureDeviceNV device); +typedef GLXVideoCaptureDeviceNV * ( * PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC) (Display* dpy, int screen, int *nelements); +typedef void ( * PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device); +typedef int ( * PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device, int attribute, int *value); +typedef void ( * PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device); + +#define glXBindVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXBindVideoCaptureDeviceNV) +#define glXEnumerateVideoCaptureDevicesNV GLXEW_GET_FUN(__glewXEnumerateVideoCaptureDevicesNV) +#define glXLockVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXLockVideoCaptureDeviceNV) +#define glXQueryVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXQueryVideoCaptureDeviceNV) +#define glXReleaseVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXReleaseVideoCaptureDeviceNV) + +#define GLXEW_NV_video_capture GLXEW_GET_VAR(__GLXEW_NV_video_capture) + +#endif /* GLX_NV_video_capture */ + +/* -------------------------- GLX_NV_video_output -------------------------- */ + +#ifndef GLX_NV_video_output +#define GLX_NV_video_output 1 + +#define GLX_VIDEO_OUT_COLOR_NV 0x20C3 +#define GLX_VIDEO_OUT_ALPHA_NV 0x20C4 +#define GLX_VIDEO_OUT_DEPTH_NV 0x20C5 +#define GLX_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 +#define GLX_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 +#define GLX_VIDEO_OUT_FRAME_NV 0x20C8 +#define GLX_VIDEO_OUT_FIELD_1_NV 0x20C9 +#define GLX_VIDEO_OUT_FIELD_2_NV 0x20CA +#define GLX_VIDEO_OUT_STACKED_FIELDS_1_2_NV 0x20CB +#define GLX_VIDEO_OUT_STACKED_FIELDS_2_1_NV 0x20CC + +typedef int ( * PFNGLXBINDVIDEOIMAGENVPROC) (Display* dpy, GLXVideoDeviceNV VideoDevice, GLXPbuffer pbuf, int iVideoBuffer); +typedef int ( * PFNGLXGETVIDEODEVICENVPROC) (Display* dpy, int screen, int numVideoDevices, GLXVideoDeviceNV *pVideoDevice); +typedef int ( * PFNGLXGETVIDEOINFONVPROC) (Display* dpy, int screen, GLXVideoDeviceNV VideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); +typedef int ( * PFNGLXRELEASEVIDEODEVICENVPROC) (Display* dpy, int screen, GLXVideoDeviceNV VideoDevice); +typedef int ( * PFNGLXRELEASEVIDEOIMAGENVPROC) (Display* dpy, GLXPbuffer pbuf); +typedef int ( * PFNGLXSENDPBUFFERTOVIDEONVPROC) (Display* dpy, GLXPbuffer pbuf, int iBufferType, unsigned long *pulCounterPbuffer, GLboolean bBlock); + +#define glXBindVideoImageNV GLXEW_GET_FUN(__glewXBindVideoImageNV) +#define glXGetVideoDeviceNV GLXEW_GET_FUN(__glewXGetVideoDeviceNV) +#define glXGetVideoInfoNV GLXEW_GET_FUN(__glewXGetVideoInfoNV) +#define glXReleaseVideoDeviceNV GLXEW_GET_FUN(__glewXReleaseVideoDeviceNV) +#define glXReleaseVideoImageNV GLXEW_GET_FUN(__glewXReleaseVideoImageNV) +#define glXSendPbufferToVideoNV GLXEW_GET_FUN(__glewXSendPbufferToVideoNV) + +#define GLXEW_NV_video_output GLXEW_GET_VAR(__GLXEW_NV_video_output) + +#endif /* GLX_NV_video_output */ + +/* -------------------------- GLX_OML_swap_method -------------------------- */ + +#ifndef GLX_OML_swap_method +#define GLX_OML_swap_method 1 + +#define GLX_SWAP_METHOD_OML 0x8060 +#define GLX_SWAP_EXCHANGE_OML 0x8061 +#define GLX_SWAP_COPY_OML 0x8062 +#define GLX_SWAP_UNDEFINED_OML 0x8063 + +#define GLXEW_OML_swap_method GLXEW_GET_VAR(__GLXEW_OML_swap_method) + +#endif /* GLX_OML_swap_method */ + +/* -------------------------- GLX_OML_sync_control ------------------------- */ + +#ifndef GLX_OML_sync_control +#define GLX_OML_sync_control 1 + +typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display* dpy, GLXDrawable drawable, int32_t* numerator, int32_t* denominator); +typedef Bool ( * PFNGLXGETSYNCVALUESOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t* ust, int64_t* msc, int64_t* sbc); +typedef int64_t ( * PFNGLXSWAPBUFFERSMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder); +typedef Bool ( * PFNGLXWAITFORMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t* ust, int64_t* msc, int64_t* sbc); +typedef Bool ( * PFNGLXWAITFORSBCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_sbc, int64_t* ust, int64_t* msc, int64_t* sbc); + +#define glXGetMscRateOML GLXEW_GET_FUN(__glewXGetMscRateOML) +#define glXGetSyncValuesOML GLXEW_GET_FUN(__glewXGetSyncValuesOML) +#define glXSwapBuffersMscOML GLXEW_GET_FUN(__glewXSwapBuffersMscOML) +#define glXWaitForMscOML GLXEW_GET_FUN(__glewXWaitForMscOML) +#define glXWaitForSbcOML GLXEW_GET_FUN(__glewXWaitForSbcOML) + +#define GLXEW_OML_sync_control GLXEW_GET_VAR(__GLXEW_OML_sync_control) + +#endif /* GLX_OML_sync_control */ + +/* ------------------------ GLX_SGIS_blended_overlay ----------------------- */ + +#ifndef GLX_SGIS_blended_overlay +#define GLX_SGIS_blended_overlay 1 + +#define GLX_BLENDED_RGBA_SGIS 0x8025 + +#define GLXEW_SGIS_blended_overlay GLXEW_GET_VAR(__GLXEW_SGIS_blended_overlay) + +#endif /* GLX_SGIS_blended_overlay */ + +/* -------------------------- GLX_SGIS_color_range ------------------------- */ + +#ifndef GLX_SGIS_color_range +#define GLX_SGIS_color_range 1 + +#define GLX_MIN_RED_SGIS 0 +#define GLX_MAX_GREEN_SGIS 0 +#define GLX_MIN_BLUE_SGIS 0 +#define GLX_MAX_ALPHA_SGIS 0 +#define GLX_MIN_GREEN_SGIS 0 +#define GLX_MIN_ALPHA_SGIS 0 +#define GLX_MAX_RED_SGIS 0 +#define GLX_EXTENDED_RANGE_SGIS 0 +#define GLX_MAX_BLUE_SGIS 0 + +#define GLXEW_SGIS_color_range GLXEW_GET_VAR(__GLXEW_SGIS_color_range) + +#endif /* GLX_SGIS_color_range */ + +/* -------------------------- GLX_SGIS_multisample ------------------------- */ + +#ifndef GLX_SGIS_multisample +#define GLX_SGIS_multisample 1 + +#define GLX_SAMPLE_BUFFERS_SGIS 100000 +#define GLX_SAMPLES_SGIS 100001 + +#define GLXEW_SGIS_multisample GLXEW_GET_VAR(__GLXEW_SGIS_multisample) + +#endif /* GLX_SGIS_multisample */ + +/* ---------------------- GLX_SGIS_shared_multisample ---------------------- */ + +#ifndef GLX_SGIS_shared_multisample +#define GLX_SGIS_shared_multisample 1 + +#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026 +#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027 + +#define GLXEW_SGIS_shared_multisample GLXEW_GET_VAR(__GLXEW_SGIS_shared_multisample) + +#endif /* GLX_SGIS_shared_multisample */ + +/* --------------------------- GLX_SGIX_fbconfig --------------------------- */ + +#ifndef GLX_SGIX_fbconfig +#define GLX_SGIX_fbconfig 1 + +#define GLX_WINDOW_BIT_SGIX 0x00000001 +#define GLX_RGBA_BIT_SGIX 0x00000001 +#define GLX_PIXMAP_BIT_SGIX 0x00000002 +#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002 +#define GLX_SCREEN_EXT 0x800C +#define GLX_DRAWABLE_TYPE_SGIX 0x8010 +#define GLX_RENDER_TYPE_SGIX 0x8011 +#define GLX_X_RENDERABLE_SGIX 0x8012 +#define GLX_FBCONFIG_ID_SGIX 0x8013 +#define GLX_RGBA_TYPE_SGIX 0x8014 +#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015 + +typedef XID GLXFBConfigIDSGIX; +typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; + +typedef GLXFBConfigSGIX* ( * PFNGLXCHOOSEFBCONFIGSGIXPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); +typedef GLXContext ( * PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display* dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (Display* dpy, GLXFBConfig config, Pixmap pixmap); +typedef int ( * PFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display* dpy, GLXFBConfigSGIX config, int attribute, int *value); +typedef GLXFBConfigSGIX ( * PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (Display* dpy, XVisualInfo *vis); +typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLXFBConfig config); + +#define glXChooseFBConfigSGIX GLXEW_GET_FUN(__glewXChooseFBConfigSGIX) +#define glXCreateContextWithConfigSGIX GLXEW_GET_FUN(__glewXCreateContextWithConfigSGIX) +#define glXCreateGLXPixmapWithConfigSGIX GLXEW_GET_FUN(__glewXCreateGLXPixmapWithConfigSGIX) +#define glXGetFBConfigAttribSGIX GLXEW_GET_FUN(__glewXGetFBConfigAttribSGIX) +#define glXGetFBConfigFromVisualSGIX GLXEW_GET_FUN(__glewXGetFBConfigFromVisualSGIX) +#define glXGetVisualFromFBConfigSGIX GLXEW_GET_FUN(__glewXGetVisualFromFBConfigSGIX) + +#define GLXEW_SGIX_fbconfig GLXEW_GET_VAR(__GLXEW_SGIX_fbconfig) + +#endif /* GLX_SGIX_fbconfig */ + +/* --------------------------- GLX_SGIX_hyperpipe -------------------------- */ + +#ifndef GLX_SGIX_hyperpipe +#define GLX_SGIX_hyperpipe 1 + +#define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001 +#define GLX_PIPE_RECT_SGIX 0x00000001 +#define GLX_PIPE_RECT_LIMITS_SGIX 0x00000002 +#define GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002 +#define GLX_HYPERPIPE_STEREO_SGIX 0x00000003 +#define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004 +#define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80 +#define GLX_BAD_HYPERPIPE_CONFIG_SGIX 91 +#define GLX_BAD_HYPERPIPE_SGIX 92 +#define GLX_HYPERPIPE_ID_SGIX 0x8030 + +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int networkId; +} GLXHyperpipeNetworkSGIX; +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int XOrigin; + int YOrigin; + int maxHeight; + int maxWidth; +} GLXPipeRectLimits; +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int channel; + unsigned int participationType; + int timeSlice; +} GLXHyperpipeConfigSGIX; +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int srcXOrigin; + int srcYOrigin; + int srcWidth; + int srcHeight; + int destXOrigin; + int destYOrigin; + int destWidth; + int destHeight; +} GLXPipeRect; + +typedef int ( * PFNGLXBINDHYPERPIPESGIXPROC) (Display *dpy, int hpId); +typedef int ( * PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId); +typedef int ( * PFNGLXHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList); +typedef int ( * PFNGLXHYPERPIPECONFIGSGIXPROC) (Display *dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX *cfg, int *hpId); +typedef int ( * PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *returnAttribList); +typedef int ( * PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList, void *returnAttribList); +typedef GLXHyperpipeConfigSGIX * ( * PFNGLXQUERYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId, int *npipes); +typedef GLXHyperpipeNetworkSGIX * ( * PFNGLXQUERYHYPERPIPENETWORKSGIXPROC) (Display *dpy, int *npipes); + +#define glXBindHyperpipeSGIX GLXEW_GET_FUN(__glewXBindHyperpipeSGIX) +#define glXDestroyHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXDestroyHyperpipeConfigSGIX) +#define glXHyperpipeAttribSGIX GLXEW_GET_FUN(__glewXHyperpipeAttribSGIX) +#define glXHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXHyperpipeConfigSGIX) +#define glXQueryHyperpipeAttribSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeAttribSGIX) +#define glXQueryHyperpipeBestAttribSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeBestAttribSGIX) +#define glXQueryHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeConfigSGIX) +#define glXQueryHyperpipeNetworkSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeNetworkSGIX) + +#define GLXEW_SGIX_hyperpipe GLXEW_GET_VAR(__GLXEW_SGIX_hyperpipe) + +#endif /* GLX_SGIX_hyperpipe */ + +/* ---------------------------- GLX_SGIX_pbuffer --------------------------- */ + +#ifndef GLX_SGIX_pbuffer +#define GLX_SGIX_pbuffer 1 + +#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002 +#define GLX_PBUFFER_BIT_SGIX 0x00000004 +#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008 +#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010 +#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020 +#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040 +#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080 +#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100 +#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017 +#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018 +#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019 +#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A +#define GLX_PRESERVED_CONTENTS_SGIX 0x801B +#define GLX_LARGEST_PBUFFER_SGIX 0x801C +#define GLX_WIDTH_SGIX 0x801D +#define GLX_HEIGHT_SGIX 0x801E +#define GLX_EVENT_MASK_SGIX 0x801F +#define GLX_DAMAGED_SGIX 0x8020 +#define GLX_SAVED_SGIX 0x8021 +#define GLX_WINDOW_SGIX 0x8022 +#define GLX_PBUFFER_SGIX 0x8023 +#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000 + +typedef XID GLXPbufferSGIX; +typedef struct { int type; unsigned long serial; Bool send_event; Display *display; GLXDrawable drawable; int event_type; int draw_type; unsigned int mask; int x, y; int width, height; int count; } GLXBufferClobberEventSGIX; + +typedef GLXPbuffer ( * PFNGLXCREATEGLXPBUFFERSGIXPROC) (Display* dpy, GLXFBConfig config, unsigned int width, unsigned int height, int *attrib_list); +typedef void ( * PFNGLXDESTROYGLXPBUFFERSGIXPROC) (Display* dpy, GLXPbuffer pbuf); +typedef void ( * PFNGLXGETSELECTEDEVENTSGIXPROC) (Display* dpy, GLXDrawable drawable, unsigned long *mask); +typedef void ( * PFNGLXQUERYGLXPBUFFERSGIXPROC) (Display* dpy, GLXPbuffer pbuf, int attribute, unsigned int *value); +typedef void ( * PFNGLXSELECTEVENTSGIXPROC) (Display* dpy, GLXDrawable drawable, unsigned long mask); + +#define glXCreateGLXPbufferSGIX GLXEW_GET_FUN(__glewXCreateGLXPbufferSGIX) +#define glXDestroyGLXPbufferSGIX GLXEW_GET_FUN(__glewXDestroyGLXPbufferSGIX) +#define glXGetSelectedEventSGIX GLXEW_GET_FUN(__glewXGetSelectedEventSGIX) +#define glXQueryGLXPbufferSGIX GLXEW_GET_FUN(__glewXQueryGLXPbufferSGIX) +#define glXSelectEventSGIX GLXEW_GET_FUN(__glewXSelectEventSGIX) + +#define GLXEW_SGIX_pbuffer GLXEW_GET_VAR(__GLXEW_SGIX_pbuffer) + +#endif /* GLX_SGIX_pbuffer */ + +/* ------------------------- GLX_SGIX_swap_barrier ------------------------- */ + +#ifndef GLX_SGIX_swap_barrier +#define GLX_SGIX_swap_barrier 1 + +typedef void ( * PFNGLXBINDSWAPBARRIERSGIXPROC) (Display *dpy, GLXDrawable drawable, int barrier); +typedef Bool ( * PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (Display *dpy, int screen, int *max); + +#define glXBindSwapBarrierSGIX GLXEW_GET_FUN(__glewXBindSwapBarrierSGIX) +#define glXQueryMaxSwapBarriersSGIX GLXEW_GET_FUN(__glewXQueryMaxSwapBarriersSGIX) + +#define GLXEW_SGIX_swap_barrier GLXEW_GET_VAR(__GLXEW_SGIX_swap_barrier) + +#endif /* GLX_SGIX_swap_barrier */ + +/* -------------------------- GLX_SGIX_swap_group -------------------------- */ + +#ifndef GLX_SGIX_swap_group +#define GLX_SGIX_swap_group 1 + +typedef void ( * PFNGLXJOINSWAPGROUPSGIXPROC) (Display *dpy, GLXDrawable drawable, GLXDrawable member); + +#define glXJoinSwapGroupSGIX GLXEW_GET_FUN(__glewXJoinSwapGroupSGIX) + +#define GLXEW_SGIX_swap_group GLXEW_GET_VAR(__GLXEW_SGIX_swap_group) + +#endif /* GLX_SGIX_swap_group */ + +/* ------------------------- GLX_SGIX_video_resize ------------------------- */ + +#ifndef GLX_SGIX_video_resize +#define GLX_SGIX_video_resize 1 + +#define GLX_SYNC_FRAME_SGIX 0x00000000 +#define GLX_SYNC_SWAP_SGIX 0x00000001 + +typedef int ( * PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (Display* display, int screen, int channel, Window window); +typedef int ( * PFNGLXCHANNELRECTSGIXPROC) (Display* display, int screen, int channel, int x, int y, int w, int h); +typedef int ( * PFNGLXCHANNELRECTSYNCSGIXPROC) (Display* display, int screen, int channel, GLenum synctype); +typedef int ( * PFNGLXQUERYCHANNELDELTASSGIXPROC) (Display* display, int screen, int channel, int *x, int *y, int *w, int *h); +typedef int ( * PFNGLXQUERYCHANNELRECTSGIXPROC) (Display* display, int screen, int channel, int *dx, int *dy, int *dw, int *dh); + +#define glXBindChannelToWindowSGIX GLXEW_GET_FUN(__glewXBindChannelToWindowSGIX) +#define glXChannelRectSGIX GLXEW_GET_FUN(__glewXChannelRectSGIX) +#define glXChannelRectSyncSGIX GLXEW_GET_FUN(__glewXChannelRectSyncSGIX) +#define glXQueryChannelDeltasSGIX GLXEW_GET_FUN(__glewXQueryChannelDeltasSGIX) +#define glXQueryChannelRectSGIX GLXEW_GET_FUN(__glewXQueryChannelRectSGIX) + +#define GLXEW_SGIX_video_resize GLXEW_GET_VAR(__GLXEW_SGIX_video_resize) + +#endif /* GLX_SGIX_video_resize */ + +/* ---------------------- GLX_SGIX_visual_select_group --------------------- */ + +#ifndef GLX_SGIX_visual_select_group +#define GLX_SGIX_visual_select_group 1 + +#define GLX_VISUAL_SELECT_GROUP_SGIX 0x8028 + +#define GLXEW_SGIX_visual_select_group GLXEW_GET_VAR(__GLXEW_SGIX_visual_select_group) + +#endif /* GLX_SGIX_visual_select_group */ + +/* ---------------------------- GLX_SGI_cushion ---------------------------- */ + +#ifndef GLX_SGI_cushion +#define GLX_SGI_cushion 1 + +typedef void ( * PFNGLXCUSHIONSGIPROC) (Display* dpy, Window window, float cushion); + +#define glXCushionSGI GLXEW_GET_FUN(__glewXCushionSGI) + +#define GLXEW_SGI_cushion GLXEW_GET_VAR(__GLXEW_SGI_cushion) + +#endif /* GLX_SGI_cushion */ + +/* ----------------------- GLX_SGI_make_current_read ----------------------- */ + +#ifndef GLX_SGI_make_current_read +#define GLX_SGI_make_current_read 1 + +typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLESGIPROC) (void); +typedef Bool ( * PFNGLXMAKECURRENTREADSGIPROC) (Display* dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); + +#define glXGetCurrentReadDrawableSGI GLXEW_GET_FUN(__glewXGetCurrentReadDrawableSGI) +#define glXMakeCurrentReadSGI GLXEW_GET_FUN(__glewXMakeCurrentReadSGI) + +#define GLXEW_SGI_make_current_read GLXEW_GET_VAR(__GLXEW_SGI_make_current_read) + +#endif /* GLX_SGI_make_current_read */ + +/* -------------------------- GLX_SGI_swap_control ------------------------- */ + +#ifndef GLX_SGI_swap_control +#define GLX_SGI_swap_control 1 + +typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval); + +#define glXSwapIntervalSGI GLXEW_GET_FUN(__glewXSwapIntervalSGI) + +#define GLXEW_SGI_swap_control GLXEW_GET_VAR(__GLXEW_SGI_swap_control) + +#endif /* GLX_SGI_swap_control */ + +/* --------------------------- GLX_SGI_video_sync -------------------------- */ + +#ifndef GLX_SGI_video_sync +#define GLX_SGI_video_sync 1 + +typedef int ( * PFNGLXGETVIDEOSYNCSGIPROC) (unsigned int* count); +typedef int ( * PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int* count); + +#define glXGetVideoSyncSGI GLXEW_GET_FUN(__glewXGetVideoSyncSGI) +#define glXWaitVideoSyncSGI GLXEW_GET_FUN(__glewXWaitVideoSyncSGI) + +#define GLXEW_SGI_video_sync GLXEW_GET_VAR(__GLXEW_SGI_video_sync) + +#endif /* GLX_SGI_video_sync */ + +/* --------------------- GLX_SUN_get_transparent_index --------------------- */ + +#ifndef GLX_SUN_get_transparent_index +#define GLX_SUN_get_transparent_index 1 + +typedef Status ( * PFNGLXGETTRANSPARENTINDEXSUNPROC) (Display* dpy, Window overlay, Window underlay, unsigned long *pTransparentIndex); + +#define glXGetTransparentIndexSUN GLXEW_GET_FUN(__glewXGetTransparentIndexSUN) + +#define GLXEW_SUN_get_transparent_index GLXEW_GET_VAR(__GLXEW_SUN_get_transparent_index) + +#endif /* GLX_SUN_get_transparent_index */ + +/* -------------------------- GLX_SUN_video_resize ------------------------- */ + +#ifndef GLX_SUN_video_resize +#define GLX_SUN_video_resize 1 + +#define GLX_VIDEO_RESIZE_SUN 0x8171 +#define GL_VIDEO_RESIZE_COMPENSATION_SUN 0x85CD + +typedef int ( * PFNGLXGETVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, float* factor); +typedef int ( * PFNGLXVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, float factor); + +#define glXGetVideoResizeSUN GLXEW_GET_FUN(__glewXGetVideoResizeSUN) +#define glXVideoResizeSUN GLXEW_GET_FUN(__glewXVideoResizeSUN) + +#define GLXEW_SUN_video_resize GLXEW_GET_VAR(__GLXEW_SUN_video_resize) + +#endif /* GLX_SUN_video_resize */ + +/* ------------------------------------------------------------------------- */ + +#ifdef GLEW_MX +#define GLXEW_EXPORT +#else +#define GLXEW_EXPORT extern +#endif /* GLEW_MX */ + +extern PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay; + +extern PFNGLXCHOOSEFBCONFIGPROC __glewXChooseFBConfig; +extern PFNGLXCREATENEWCONTEXTPROC __glewXCreateNewContext; +extern PFNGLXCREATEPBUFFERPROC __glewXCreatePbuffer; +extern PFNGLXCREATEPIXMAPPROC __glewXCreatePixmap; +extern PFNGLXCREATEWINDOWPROC __glewXCreateWindow; +extern PFNGLXDESTROYPBUFFERPROC __glewXDestroyPbuffer; +extern PFNGLXDESTROYPIXMAPPROC __glewXDestroyPixmap; +extern PFNGLXDESTROYWINDOWPROC __glewXDestroyWindow; +extern PFNGLXGETCURRENTREADDRAWABLEPROC __glewXGetCurrentReadDrawable; +extern PFNGLXGETFBCONFIGATTRIBPROC __glewXGetFBConfigAttrib; +extern PFNGLXGETFBCONFIGSPROC __glewXGetFBConfigs; +extern PFNGLXGETSELECTEDEVENTPROC __glewXGetSelectedEvent; +extern PFNGLXGETVISUALFROMFBCONFIGPROC __glewXGetVisualFromFBConfig; +extern PFNGLXMAKECONTEXTCURRENTPROC __glewXMakeContextCurrent; +extern PFNGLXQUERYCONTEXTPROC __glewXQueryContext; +extern PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable; +extern PFNGLXSELECTEVENTPROC __glewXSelectEvent; + +extern PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB; + +extern PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI; +extern PFNGLXDRAWABLEATTRIBATIPROC __glewXDrawableAttribATI; +extern PFNGLXRELEASETEXIMAGEATIPROC __glewXReleaseTexImageATI; + +extern PFNGLXFREECONTEXTEXTPROC __glewXFreeContextEXT; +extern PFNGLXGETCONTEXTIDEXTPROC __glewXGetContextIDEXT; +extern PFNGLXIMPORTCONTEXTEXTPROC __glewXImportContextEXT; +extern PFNGLXQUERYCONTEXTINFOEXTPROC __glewXQueryContextInfoEXT; + +extern PFNGLXSWAPINTERVALEXTPROC __glewXSwapIntervalEXT; + +extern PFNGLXBINDTEXIMAGEEXTPROC __glewXBindTexImageEXT; +extern PFNGLXRELEASETEXIMAGEEXTPROC __glewXReleaseTexImageEXT; + +extern PFNGLXGETAGPOFFSETMESAPROC __glewXGetAGPOffsetMESA; + +extern PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA; + +extern PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA; + +extern PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA; + +extern PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA; + +extern PFNGLXGETSWAPINTERVALMESAPROC __glewXGetSwapIntervalMESA; +extern PFNGLXSWAPINTERVALMESAPROC __glewXSwapIntervalMESA; + +extern PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV; + +extern PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV; +extern PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV; + +extern PFNGLXBINDSWAPBARRIERNVPROC __glewXBindSwapBarrierNV; +extern PFNGLXJOINSWAPGROUPNVPROC __glewXJoinSwapGroupNV; +extern PFNGLXQUERYFRAMECOUNTNVPROC __glewXQueryFrameCountNV; +extern PFNGLXQUERYMAXSWAPGROUPSNVPROC __glewXQueryMaxSwapGroupsNV; +extern PFNGLXQUERYSWAPGROUPNVPROC __glewXQuerySwapGroupNV; +extern PFNGLXRESETFRAMECOUNTNVPROC __glewXResetFrameCountNV; + +extern PFNGLXALLOCATEMEMORYNVPROC __glewXAllocateMemoryNV; +extern PFNGLXFREEMEMORYNVPROC __glewXFreeMemoryNV; + +extern PFNGLXBINDVIDEOCAPTUREDEVICENVPROC __glewXBindVideoCaptureDeviceNV; +extern PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC __glewXEnumerateVideoCaptureDevicesNV; +extern PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC __glewXLockVideoCaptureDeviceNV; +extern PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC __glewXQueryVideoCaptureDeviceNV; +extern PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC __glewXReleaseVideoCaptureDeviceNV; + +extern PFNGLXBINDVIDEOIMAGENVPROC __glewXBindVideoImageNV; +extern PFNGLXGETVIDEODEVICENVPROC __glewXGetVideoDeviceNV; +extern PFNGLXGETVIDEOINFONVPROC __glewXGetVideoInfoNV; +extern PFNGLXRELEASEVIDEODEVICENVPROC __glewXReleaseVideoDeviceNV; +extern PFNGLXRELEASEVIDEOIMAGENVPROC __glewXReleaseVideoImageNV; +extern PFNGLXSENDPBUFFERTOVIDEONVPROC __glewXSendPbufferToVideoNV; + +extern PFNGLXGETMSCRATEOMLPROC __glewXGetMscRateOML; +extern PFNGLXGETSYNCVALUESOMLPROC __glewXGetSyncValuesOML; +extern PFNGLXSWAPBUFFERSMSCOMLPROC __glewXSwapBuffersMscOML; +extern PFNGLXWAITFORMSCOMLPROC __glewXWaitForMscOML; +extern PFNGLXWAITFORSBCOMLPROC __glewXWaitForSbcOML; + +extern PFNGLXCHOOSEFBCONFIGSGIXPROC __glewXChooseFBConfigSGIX; +extern PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC __glewXCreateContextWithConfigSGIX; +extern PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC __glewXCreateGLXPixmapWithConfigSGIX; +extern PFNGLXGETFBCONFIGATTRIBSGIXPROC __glewXGetFBConfigAttribSGIX; +extern PFNGLXGETFBCONFIGFROMVISUALSGIXPROC __glewXGetFBConfigFromVisualSGIX; +extern PFNGLXGETVISUALFROMFBCONFIGSGIXPROC __glewXGetVisualFromFBConfigSGIX; + +extern PFNGLXBINDHYPERPIPESGIXPROC __glewXBindHyperpipeSGIX; +extern PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC __glewXDestroyHyperpipeConfigSGIX; +extern PFNGLXHYPERPIPEATTRIBSGIXPROC __glewXHyperpipeAttribSGIX; +extern PFNGLXHYPERPIPECONFIGSGIXPROC __glewXHyperpipeConfigSGIX; +extern PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC __glewXQueryHyperpipeAttribSGIX; +extern PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC __glewXQueryHyperpipeBestAttribSGIX; +extern PFNGLXQUERYHYPERPIPECONFIGSGIXPROC __glewXQueryHyperpipeConfigSGIX; +extern PFNGLXQUERYHYPERPIPENETWORKSGIXPROC __glewXQueryHyperpipeNetworkSGIX; + +extern PFNGLXCREATEGLXPBUFFERSGIXPROC __glewXCreateGLXPbufferSGIX; +extern PFNGLXDESTROYGLXPBUFFERSGIXPROC __glewXDestroyGLXPbufferSGIX; +extern PFNGLXGETSELECTEDEVENTSGIXPROC __glewXGetSelectedEventSGIX; +extern PFNGLXQUERYGLXPBUFFERSGIXPROC __glewXQueryGLXPbufferSGIX; +extern PFNGLXSELECTEVENTSGIXPROC __glewXSelectEventSGIX; + +extern PFNGLXBINDSWAPBARRIERSGIXPROC __glewXBindSwapBarrierSGIX; +extern PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC __glewXQueryMaxSwapBarriersSGIX; + +extern PFNGLXJOINSWAPGROUPSGIXPROC __glewXJoinSwapGroupSGIX; + +extern PFNGLXBINDCHANNELTOWINDOWSGIXPROC __glewXBindChannelToWindowSGIX; +extern PFNGLXCHANNELRECTSGIXPROC __glewXChannelRectSGIX; +extern PFNGLXCHANNELRECTSYNCSGIXPROC __glewXChannelRectSyncSGIX; +extern PFNGLXQUERYCHANNELDELTASSGIXPROC __glewXQueryChannelDeltasSGIX; +extern PFNGLXQUERYCHANNELRECTSGIXPROC __glewXQueryChannelRectSGIX; + +extern PFNGLXCUSHIONSGIPROC __glewXCushionSGI; + +extern PFNGLXGETCURRENTREADDRAWABLESGIPROC __glewXGetCurrentReadDrawableSGI; +extern PFNGLXMAKECURRENTREADSGIPROC __glewXMakeCurrentReadSGI; + +extern PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI; + +extern PFNGLXGETVIDEOSYNCSGIPROC __glewXGetVideoSyncSGI; +extern PFNGLXWAITVIDEOSYNCSGIPROC __glewXWaitVideoSyncSGI; + +extern PFNGLXGETTRANSPARENTINDEXSUNPROC __glewXGetTransparentIndexSUN; + +extern PFNGLXGETVIDEORESIZESUNPROC __glewXGetVideoResizeSUN; +extern PFNGLXVIDEORESIZESUNPROC __glewXVideoResizeSUN; + +#if defined(GLEW_MX) +struct GLXEWContextStruct +{ +#endif /* GLEW_MX */ + +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_0; +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_1; +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_2; +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_3; +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_4; +GLXEW_EXPORT GLboolean __GLXEW_3DFX_multisample; +GLXEW_EXPORT GLboolean __GLXEW_AMD_gpu_association; +GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context; +GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context_profile; +GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context_robustness; +GLXEW_EXPORT GLboolean __GLXEW_ARB_fbconfig_float; +GLXEW_EXPORT GLboolean __GLXEW_ARB_framebuffer_sRGB; +GLXEW_EXPORT GLboolean __GLXEW_ARB_get_proc_address; +GLXEW_EXPORT GLboolean __GLXEW_ARB_multisample; +GLXEW_EXPORT GLboolean __GLXEW_ARB_vertex_buffer_object; +GLXEW_EXPORT GLboolean __GLXEW_ATI_pixel_format_float; +GLXEW_EXPORT GLboolean __GLXEW_ATI_render_texture; +GLXEW_EXPORT GLboolean __GLXEW_EXT_create_context_es2_profile; +GLXEW_EXPORT GLboolean __GLXEW_EXT_fbconfig_packed_float; +GLXEW_EXPORT GLboolean __GLXEW_EXT_framebuffer_sRGB; +GLXEW_EXPORT GLboolean __GLXEW_EXT_import_context; +GLXEW_EXPORT GLboolean __GLXEW_EXT_scene_marker; +GLXEW_EXPORT GLboolean __GLXEW_EXT_swap_control; +GLXEW_EXPORT GLboolean __GLXEW_EXT_texture_from_pixmap; +GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_info; +GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_rating; +GLXEW_EXPORT GLboolean __GLXEW_INTEL_swap_event; +GLXEW_EXPORT GLboolean __GLXEW_MESA_agp_offset; +GLXEW_EXPORT GLboolean __GLXEW_MESA_copy_sub_buffer; +GLXEW_EXPORT GLboolean __GLXEW_MESA_pixmap_colormap; +GLXEW_EXPORT GLboolean __GLXEW_MESA_release_buffers; +GLXEW_EXPORT GLboolean __GLXEW_MESA_set_3dfx_mode; +GLXEW_EXPORT GLboolean __GLXEW_MESA_swap_control; +GLXEW_EXPORT GLboolean __GLXEW_NV_copy_image; +GLXEW_EXPORT GLboolean __GLXEW_NV_float_buffer; +GLXEW_EXPORT GLboolean __GLXEW_NV_multisample_coverage; +GLXEW_EXPORT GLboolean __GLXEW_NV_present_video; +GLXEW_EXPORT GLboolean __GLXEW_NV_swap_group; +GLXEW_EXPORT GLboolean __GLXEW_NV_vertex_array_range; +GLXEW_EXPORT GLboolean __GLXEW_NV_video_capture; +GLXEW_EXPORT GLboolean __GLXEW_NV_video_output; +GLXEW_EXPORT GLboolean __GLXEW_OML_swap_method; +GLXEW_EXPORT GLboolean __GLXEW_OML_sync_control; +GLXEW_EXPORT GLboolean __GLXEW_SGIS_blended_overlay; +GLXEW_EXPORT GLboolean __GLXEW_SGIS_color_range; +GLXEW_EXPORT GLboolean __GLXEW_SGIS_multisample; +GLXEW_EXPORT GLboolean __GLXEW_SGIS_shared_multisample; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_fbconfig; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_hyperpipe; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_pbuffer; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_barrier; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_group; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_video_resize; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_visual_select_group; +GLXEW_EXPORT GLboolean __GLXEW_SGI_cushion; +GLXEW_EXPORT GLboolean __GLXEW_SGI_make_current_read; +GLXEW_EXPORT GLboolean __GLXEW_SGI_swap_control; +GLXEW_EXPORT GLboolean __GLXEW_SGI_video_sync; +GLXEW_EXPORT GLboolean __GLXEW_SUN_get_transparent_index; +GLXEW_EXPORT GLboolean __GLXEW_SUN_video_resize; + +#ifdef GLEW_MX +}; /* GLXEWContextStruct */ +#endif /* GLEW_MX */ + +/* ------------------------------------------------------------------------ */ + +#ifdef GLEW_MX + +typedef struct GLXEWContextStruct GLXEWContext; +extern GLenum glxewContextInit (GLXEWContext* ctx); +extern GLboolean glxewContextIsSupported (const GLXEWContext* ctx, const char* name); + +#define glxewInit() glxewContextInit(glxewGetContext()) +#define glxewIsSupported(x) glxewContextIsSupported(glxewGetContext(), x) + +#define GLXEW_GET_VAR(x) (*(const GLboolean*)&(glxewGetContext()->x)) +#define GLXEW_GET_FUN(x) x + +#else /* GLEW_MX */ + +#define GLXEW_GET_VAR(x) (*(const GLboolean*)&x) +#define GLXEW_GET_FUN(x) x + +extern GLboolean glxewIsSupported (const char* name); + +#endif /* GLEW_MX */ + +extern GLboolean glxewGetExtension (const char* name); + +#ifdef __cplusplus +} +#endif + +#endif /* __glxew_h__ */ diff --git a/Glut/GL/glxext.h b/Glut/GL/glxext.h new file mode 100644 index 0000000..b3de958 --- /dev/null +++ b/Glut/GL/glxext.h @@ -0,0 +1,546 @@ +#ifndef __glxext_h_ +#define __glxext_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +*/ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) +#define WIN32_LEAN_AND_MEAN 1 +#include +#else +#include +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif + + +/*************************************************************/ + +/* Header file version number, required by OpenGL ABI for Linux */ +#define GLX_GLXEXT_VERSION 2 + +#ifndef GLX_VERSION_1_3 +#define GLX_WINDOW_BIT 0x00000001 +#define GLX_PIXMAP_BIT 0x00000002 +#define GLX_PBUFFER_BIT 0x00000004 +#define GLX_RGBA_BIT 0x00000001 +#define GLX_COLOR_INDEX_BIT 0x00000002 +#define GLX_PBUFFER_CLOBBER_MASK 0x08000000 +#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 +#define GLX_AUX_BUFFERS_BIT 0x00000010 +#define GLX_DEPTH_BUFFER_BIT 0x00000020 +#define GLX_STENCIL_BUFFER_BIT 0x00000040 +#define GLX_ACCUM_BUFFER_BIT 0x00000080 +#define GLX_CONFIG_CAVEAT 0x20 +#define GLX_X_VISUAL_TYPE 0x22 +#define GLX_TRANSPARENT_TYPE 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE 0x24 +#define GLX_TRANSPARENT_RED_VALUE 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE 0x28 +#define GLX_DONT_CARE 0xFFFFFFFF +#define GLX_NONE 0x8000 +#define GLX_SLOW_CONFIG 0x8001 +#define GLX_TRUE_COLOR 0x8002 +#define GLX_DIRECT_COLOR 0x8003 +#define GLX_PSEUDO_COLOR 0x8004 +#define GLX_STATIC_COLOR 0x8005 +#define GLX_GRAY_SCALE 0x8006 +#define GLX_STATIC_GRAY 0x8007 +#define GLX_TRANSPARENT_RGB 0x8008 +#define GLX_TRANSPARENT_INDEX 0x8009 +#define GLX_VISUAL_ID 0x800B +#define GLX_SCREEN 0x800C +#define GLX_NON_CONFORMANT_CONFIG 0x800D +#define GLX_DRAWABLE_TYPE 0x8010 +#define GLX_RENDER_TYPE 0x8011 +#define GLX_X_RENDERABLE 0x8012 +#define GLX_FBCONFIG_ID 0x8013 +#define GLX_RGBA_TYPE 0x8014 +#define GLX_COLOR_INDEX_TYPE 0x8015 +#define GLX_MAX_PBUFFER_WIDTH 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT 0x8017 +#define GLX_MAX_PBUFFER_PIXELS 0x8018 +#define GLX_PRESERVED_CONTENTS 0x801B +#define GLX_LARGEST_PBUFFER 0x801C +#define GLX_WIDTH 0x801D +#define GLX_HEIGHT 0x801E +#define GLX_EVENT_MASK 0x801F +#define GLX_DAMAGED 0x8020 +#define GLX_SAVED 0x8021 +#define GLX_WINDOW 0x8022 +#define GLX_PBUFFER 0x8023 +#define GLX_PBUFFER_HEIGHT 0x8040 +#define GLX_PBUFFER_WIDTH 0x8041 +#endif + +#ifndef GLX_EXT_visual_info +#define GLX_X_VISUAL_TYPE_EXT 0x22 +#define GLX_TRANSPARENT_TYPE_EXT 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24 +#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28 +#define GLX_NONE_EXT 0x8000 +#define GLX_TRUE_COLOR_EXT 0x8002 +#define GLX_DIRECT_COLOR_EXT 0x8003 +#define GLX_PSEUDO_COLOR_EXT 0x8004 +#define GLX_STATIC_COLOR_EXT 0x8005 +#define GLX_GRAY_SCALE_EXT 0x8006 +#define GLX_STATIC_GRAY_EXT 0x8007 +#define GLX_TRANSPARENT_RGB_EXT 0x8008 +#define GLX_TRANSPARENT_INDEX_EXT 0x8009 +#endif + +#ifndef GLX_SGI_swap_control +#endif + +#ifndef GLX_SGI_video_sync +#endif + +#ifndef GLX_SGI_make_current_read +#endif + +#ifndef GLX_SGIX_video_source +#endif + +#ifndef GLX_EXT_visual_rating +#define GLX_VISUAL_CAVEAT_EXT 0x20 +#define GLX_SLOW_VISUAL_EXT 0x8001 +#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D +/* reuse GLX_NONE_EXT */ +#endif + +#ifndef GLX_EXT_import_context +#define GLX_SHARE_CONTEXT_EXT 0x800A +#define GLX_VISUAL_ID_EXT 0x800B +#define GLX_SCREEN_EXT 0x800C +#endif + +#ifndef GLX_SGIX_fbconfig +#define GLX_WINDOW_BIT_SGIX 0x00000001 +#define GLX_PIXMAP_BIT_SGIX 0x00000002 +#define GLX_RGBA_BIT_SGIX 0x00000001 +#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002 +#define GLX_DRAWABLE_TYPE_SGIX 0x8010 +#define GLX_RENDER_TYPE_SGIX 0x8011 +#define GLX_X_RENDERABLE_SGIX 0x8012 +#define GLX_FBCONFIG_ID_SGIX 0x8013 +#define GLX_RGBA_TYPE_SGIX 0x8014 +#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015 +/* reuse GLX_SCREEN_EXT */ +#endif + +#ifndef GLX_SGIX_pbuffer +#define GLX_PBUFFER_BIT_SGIX 0x00000004 +#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000 +#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008 +#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010 +#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020 +#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040 +#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080 +#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100 +#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017 +#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018 +#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019 +#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A +#define GLX_PRESERVED_CONTENTS_SGIX 0x801B +#define GLX_LARGEST_PBUFFER_SGIX 0x801C +#define GLX_WIDTH_SGIX 0x801D +#define GLX_HEIGHT_SGIX 0x801E +#define GLX_EVENT_MASK_SGIX 0x801F +#define GLX_DAMAGED_SGIX 0x8020 +#define GLX_SAVED_SGIX 0x8021 +#define GLX_WINDOW_SGIX 0x8022 +#define GLX_PBUFFER_SGIX 0x8023 +#endif + +#ifndef GLX_SGI_cushion +#endif + +#ifndef GLX_SGIX_video_resize +#define GLX_SYNC_FRAME_SGIX 0x00000000 +#define GLX_SYNC_SWAP_SGIX 0x00000001 +#endif + +#ifndef GLX_SGIX_dmbuffer +#define GLX_DIGITAL_MEDIA_PBUFFER_SGIX 0x8024 +#endif + +#ifndef GLX_SGIX_swap_group +#endif + +#ifndef GLX_SGIX_swap_barrier +#endif + +#ifndef GLX_SGIS_blended_overlay +#define GLX_BLENDED_RGBA_SGIS 0x8025 +#endif + +#ifndef GLX_SGIS_shared_multisample +#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026 +#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027 +#endif + +#ifndef GLX_SUN_get_transparent_index +#endif + +#ifndef GLX_3DFX_multisample +#define GLX_SAMPLE_BUFFERS_3DFX 0x8050 +#define GLX_SAMPLES_3DFX 0x8051 +#endif + +#ifndef GLX_MESA_copy_sub_buffer +#endif + +#ifndef GLX_MESA_pixmap_colormap +#endif + +#ifndef GLX_MESA_release_buffers +#endif + +#ifndef GLX_MESA_set_3dfx_mode +#define GLX_3DFX_WINDOW_MODE_MESA 0x1 +#define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2 +#endif + + +/*************************************************************/ + +#ifndef GLX_ARB_get_proc_address +typedef void (*__GLXextFuncPtr)(); +#endif + +#ifndef GLX_SGIX_video_source +typedef XID GLXVideoSourceSGIX; +#endif + +#ifndef GLX_SGIX_fbconfig +typedef XID GLXFBConfigIDSGIX; +typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; +#endif + +#ifndef GLX_SGIX_pbuffer +typedef XID GLXPbufferSGIX; +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came for SendEvent request */ + Display *display; /* display the event was read from */ + GLXDrawable drawable; /* i.d. of Drawable */ + int event_type; /* GLX_DAMAGED_SGIX or GLX_SAVED_SGIX */ + int draw_type; /* GLX_WINDOW_SGIX or GLX_PBUFFER_SGIX */ + unsigned int mask; /* mask indicating which buffers are affected*/ + int x, y; + int width, height; + int count; /* if nonzero, at least this many more */ +} GLXBufferClobberEventSGIX; +#endif + +#ifdef GL_NV_vertex_array_range +#ifndef PFNGLXALLOCATEMEMORYNVPROC +#ifdef GLX_GLXEXT_PROTOTYPES +extern void *glXAllocateMemoryNV (GLsizei, GLfloat, GLfloat, GLfloat); +#endif +typedef void * ( * PFNGLXALLOCATEMEMORYNVPROC) (GLsizei, GLfloat, GLfloat, GLfloat); +#endif +#ifndef PFNGLXFREEMEMORYNVPROC +#ifdef GLX_GLXEXT_PROTOTYPES +extern void glXFreeMemoryNV (void *); +#endif +typedef void ( * PFNGLXFREEMEMORYNVPROC) (void *); +#endif +#endif + +#ifndef GLX_VERSION_1_3 +#define GLX_VERSION_1_3 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern GLXFBConfig * glXGetFBConfigs (Display *, int, int *); +extern GLXFBConfig * glXChooseFBConfig (Display *, int, const int *, int *); +extern int glXGetFBConfigAttrib (Display *, GLXFBConfig, int, int *); +extern XVisualInfo * glXGetVisualFromFBConfig (Display *, GLXFBConfig); +extern GLXWindow glXCreateWindow (Display *, GLXFBConfig, Window, const int *); +extern void glXDestroyWindow (Display *, GLXWindow); +extern GLXPixmap glXCreatePixmap (Display *, GLXFBConfig, Pixmap, const int *); +extern void glXDestroyPixmap (Display *, GLXPixmap); +extern GLXPbuffer glXCreatePbuffer (Display *, GLXFBConfig, const int *); +extern void glXDestroyPbuffer (Display *, GLXPbuffer); +extern void glXQueryDrawable (Display *, GLXDrawable, int, unsigned int *); +extern GLXContext glXCreateNewContext (Display *, GLXFBConfig, int, GLXContext, Bool); +extern Bool glXMakeContextCurrent (Display *, GLXDrawable, GLXDrawable, GLXContext); +extern GLXDrawable glXGetCurrentReadDrawable (void); +extern Display * glXGetCurrentDisplay (void); +extern int glXQueryContext (Display *, GLXContext, int, int *); +extern void glXSelectEvent (Display *, GLXDrawable, unsigned long); +extern void glXGetSelectedEvent (Display *, GLXDrawable, unsigned long *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef GLXFBConfig * ( * PFNGLXGETFBCONFIGSPROC) (Display *dpy, int screen, int *nelements); +typedef GLXFBConfig * ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); +typedef int ( * PFNGLXGETFBCONFIGATTRIBPROC) (Display *dpy, GLXFBConfig config, int attribute, int *value); +typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config); +typedef GLXWindow ( * PFNGLXCREATEWINDOWPROC) (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list); +typedef void ( * PFNGLXDESTROYWINDOWPROC) (Display *dpy, GLXWindow win); +typedef GLXPixmap ( * PFNGLXCREATEPIXMAPPROC) (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list); +typedef void ( * PFNGLXDESTROYPIXMAPPROC) (Display *dpy, GLXPixmap pixmap); +typedef GLXPbuffer ( * PFNGLXCREATEPBUFFERPROC) (Display *dpy, GLXFBConfig config, const int *attrib_list); +typedef void ( * PFNGLXDESTROYPBUFFERPROC) (Display *dpy, GLXPbuffer pbuf); +typedef void ( * PFNGLXQUERYDRAWABLEPROC) (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); +typedef GLXContext ( * PFNGLXCREATENEWCONTEXTPROC) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +typedef Bool ( * PFNGLXMAKECONTEXTCURRENTPROC) (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLEPROC) (void); +typedef Display * ( * PFNGLXGETCURRENTDISPLAYPROC) (void); +typedef int ( * PFNGLXQUERYCONTEXTPROC) (Display *dpy, GLXContext ctx, int attribute, int *value); +typedef void ( * PFNGLXSELECTEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long event_mask); +typedef void ( * PFNGLXGETSELECTEDEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long *event_mask); +#endif + +#ifndef GLX_ARB_get_proc_address +#define GLX_ARB_get_proc_address 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern __GLXextFuncPtr glXGetProcAddressARB (const GLubyte *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef __GLXextFuncPtr ( * PFNGLXGETPROCADDRESSARBPROC) (const GLubyte *procName); +#endif + +#ifndef GLX_SGIS_multisample +#define GLX_SGIS_multisample 1 +#endif + +#ifndef GLX_EXT_visual_info +#define GLX_EXT_visual_info 1 +#endif + +#ifndef GLX_SGI_swap_control +#define GLX_SGI_swap_control 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern int glXSwapIntervalSGI (int); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval); +#endif + +#ifndef GLX_SGI_video_sync +#define GLX_SGI_video_sync 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern int glXGetVideoSyncSGI (unsigned int *); +extern int glXWaitVideoSyncSGI (int, int, unsigned int *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef int ( * PFNGLXGETVIDEOSYNCSGIPROC) (unsigned int *count); +typedef int ( * PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int *count); +#endif + +#ifndef GLX_SGI_make_current_read +#define GLX_SGI_make_current_read 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Bool glXMakeCurrentReadSGI (Display *, GLXDrawable, GLXDrawable, GLXContext); +extern GLXDrawable glXGetCurrentReadDrawableSGI (void); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Bool ( * PFNGLXMAKECURRENTREADSGIPROC) (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLESGIPROC) (void); +#endif + +#ifdef _VL_H +#ifndef GLX_SGIX_video_source +#define GLX_SGIX_video_source 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern GLXVideoSourceSGIX glXCreateGLXVideoSourceSGIX (Display *, int, VLServer, VLPath, int, VLNode); +extern void glXDestroyGLXVideoSourceSGIX (Display *, GLXVideoSourceSGIX); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef GLXVideoSourceSGIX ( * PFNGLXCREATEGLXVIDEOSOURCESGIXPROC) (Display *display, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode); +typedef void ( * PFNGLXDESTROYGLXVIDEOSOURCESGIXPROC) (Display *dpy, GLXVideoSourceSGIX glxvideosource); +#endif + +#endif /* _VL_H */ +#ifndef GLX_EXT_visual_rating +#define GLX_EXT_visual_rating 1 +#endif + +#ifndef GLX_EXT_import_context +#define GLX_EXT_import_context 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Display * glXGetCurrentDisplayEXT (void); +extern int glXQueryContextInfoEXT (Display *, GLXContext, int, int *); +extern GLXContextID glXGetContextIDEXT (GLXContext); +extern GLXContext glXImportContextEXT (Display *, GLXContextID); +extern void glXFreeContextEXT (Display *, GLXContext); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Display * ( * PFNGLXGETCURRENTDISPLAYEXTPROC) (void); +typedef int ( * PFNGLXQUERYCONTEXTINFOEXTPROC) (Display *dpy, GLXContext context, int attribute, int *value); +typedef GLXContextID ( * PFNGLXGETCONTEXTIDEXTPROC) (GLXContext context); +typedef GLXContext ( * PFNGLXIMPORTCONTEXTEXTPROC) (Display *dpy, GLXContextID contextID); +typedef void ( * PFNGLXFREECONTEXTEXTPROC) (Display *dpy, GLXContext context); +#endif + +#ifndef GLX_SGIX_fbconfig +#define GLX_SGIX_fbconfig 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern int glXGetFBConfigAttribSGIX (Display *, GLXFBConfigSGIX, int, int *); +extern GLXFBConfigSGIX * glXChooseFBConfigSGIX (Display *, int, int *, int *); +extern GLXPixmap glXCreateGLXPixmapWithConfigSGIX (Display *, GLXFBConfigSGIX, Pixmap); +extern GLXContext glXCreateContextWithConfigSGIX (Display *, GLXFBConfigSGIX, int, GLXContext, Bool); +extern XVisualInfo * glXGetVisualFromFBConfigSGIX (Display *, GLXFBConfigSGIX); +extern GLXFBConfigSGIX glXGetFBConfigFromVisualSGIX (Display *, XVisualInfo *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef int ( * PFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, int attribute, int *value); +typedef GLXFBConfigSGIX * ( * PFNGLXCHOOSEFBCONFIGSGIXPROC) (Display *dpy, int screen, int *attrib_list, int *nelements); +typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap); +typedef GLXContext ( * PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct); +typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config); +typedef GLXFBConfigSGIX ( * PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (Display *dpy, XVisualInfo *vis); +#endif + +#ifndef GLX_SGIX_pbuffer +#define GLX_SGIX_pbuffer 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern GLXPbufferSGIX glXCreateGLXPbufferSGIX (Display *, GLXFBConfigSGIX, unsigned int, unsigned int, int *); +extern void glXDestroyGLXPbufferSGIX (Display *, GLXPbufferSGIX); +extern int glXQueryGLXPbufferSGIX (Display *, GLXPbufferSGIX, int, unsigned int *); +extern void glXSelectEventSGIX (Display *, GLXDrawable, unsigned long); +extern void glXGetSelectedEventSGIX (Display *, GLXDrawable, unsigned long *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef GLXPbufferSGIX ( * PFNGLXCREATEGLXPBUFFERSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list); +typedef void ( * PFNGLXDESTROYGLXPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuf); +typedef int ( * PFNGLXQUERYGLXPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value); +typedef void ( * PFNGLXSELECTEVENTSGIXPROC) (Display *dpy, GLXDrawable drawable, unsigned long mask); +typedef void ( * PFNGLXGETSELECTEDEVENTSGIXPROC) (Display *dpy, GLXDrawable drawable, unsigned long *mask); +#endif + +#ifndef GLX_SGI_cushion +#define GLX_SGI_cushion 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern void glXCushionSGI (Display *, Window, float); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef void ( * PFNGLXCUSHIONSGIPROC) (Display *dpy, Window window, float cushion); +#endif + +#ifndef GLX_SGIX_video_resize +#define GLX_SGIX_video_resize 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern int glXBindChannelToWindowSGIX (Display *, int, int, Window); +extern int glXChannelRectSGIX (Display *, int, int, int, int, int, int); +extern int glXQueryChannelRectSGIX (Display *, int, int, int *, int *, int *, int *); +extern int glXQueryChannelDeltasSGIX (Display *, int, int, int *, int *, int *, int *); +extern int glXChannelRectSyncSGIX (Display *, int, int, GLenum); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef int ( * PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (Display *display, int screen, int channel, Window window); +typedef int ( * PFNGLXCHANNELRECTSGIXPROC) (Display *display, int screen, int channel, int x, int y, int w, int h); +typedef int ( * PFNGLXQUERYCHANNELRECTSGIXPROC) (Display *display, int screen, int channel, int *dx, int *dy, int *dw, int *dh); +typedef int ( * PFNGLXQUERYCHANNELDELTASSGIXPROC) (Display *display, int screen, int channel, int *x, int *y, int *w, int *h); +typedef int ( * PFNGLXCHANNELRECTSYNCSGIXPROC) (Display *display, int screen, int channel, GLenum synctype); +#endif + +#ifdef _DM_BUFFER_H_ +#ifndef GLX_SGIX_dmbuffer +#define GLX_SGIX_dmbuffer 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Bool glXAssociateDMPbufferSGIX (Display *, GLXPbufferSGIX, DMparams *, DMbuffer); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Bool ( * PFNGLXASSOCIATEDMPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer); +#endif + +#endif /* _DM_BUFFER_H_ */ +#ifndef GLX_SGIX_swap_group +#define GLX_SGIX_swap_group 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern void glXJoinSwapGroupSGIX (Display *, GLXDrawable, GLXDrawable); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef void ( * PFNGLXJOINSWAPGROUPSGIXPROC) (Display *dpy, GLXDrawable drawable, GLXDrawable member); +#endif + +#ifndef GLX_SGIX_swap_barrier +#define GLX_SGIX_swap_barrier 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern void glXBindSwapBarrierSGIX (Display *, GLXDrawable, int); +extern Bool glXQueryMaxSwapBarriersSGIX (Display *, int, int *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef void ( * PFNGLXBINDSWAPBARRIERSGIXPROC) (Display *dpy, GLXDrawable drawable, int barrier); +typedef Bool ( * PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (Display *dpy, int screen, int *max); +#endif + +#ifndef GLX_SUN_get_transparent_index +#define GLX_SUN_get_transparent_index 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Status glXGetTransparentIndexSUN (Display *, Window, Window, long *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Status ( * PFNGLXGETTRANSPARENTINDEXSUNPROC) (Display *dpy, Window overlay, Window underlay, long *pTransparentIndex); +#endif + +#ifndef GLX_MESA_copy_sub_buffer +#define GLX_MESA_copy_sub_buffer 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern void glXCopySubBufferMESA (Display *, GLXDrawable, int, int, int, int); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef void ( * PFNGLXCOPYSUBBUFFERMESAPROC) (Display *dpy, GLXDrawable drawable, int x, int y, int width, int height); +#endif + +#ifndef GLX_MESA_pixmap_colormap +#define GLX_MESA_pixmap_colormap 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern GLXPixmap glXCreateGLXPixmapMESA (Display *, XVisualInfo *, Pixmap, Colormap); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPMESAPROC) (Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap); +#endif + +#ifndef GLX_MESA_release_buffers +#define GLX_MESA_release_buffers 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Bool glXReleaseBuffersMESA (Display *, GLXDrawable); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Bool ( * PFNGLXRELEASEBUFFERSMESAPROC) (Display *dpy, GLXDrawable drawable); +#endif + +#ifndef GLX_MESA_set_3dfx_mode +#define GLX_MESA_set_3dfx_mode 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Bool glXSet3DfxModeMESA (int); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Bool ( * PFNGLXSET3DFXMODEMESAPROC) (int mode); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Glut/GL/wglew.h b/Glut/GL/wglew.h new file mode 100644 index 0000000..05f054f --- /dev/null +++ b/Glut/GL/wglew.h @@ -0,0 +1,1363 @@ +/* +** The OpenGL Extension Wrangler Library +** Copyright (C) 2002-2008, Milan Ikits +** Copyright (C) 2002-2008, Marcelo E. Magallon +** Copyright (C) 2002, Lev Povalahev +** 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. +** * The name of the author 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. +*/ + +/* +** Copyright (c) 2007 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are 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 Materials. +** +** THE MATERIALS ARE 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 +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#ifndef __wglew_h__ +#define __wglew_h__ +#define __WGLEW_H__ + +#ifdef __wglext_h_ +#error wglext.h included before wglew.h +#endif + +#define __wglext_h_ + +#if !defined(WINAPI) +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif +#include +# undef WIN32_LEAN_AND_MEAN +#endif + +/* + * GLEW_STATIC needs to be set when using the static version. + * GLEW_BUILD is set when building the DLL version. + */ +#ifdef GLEW_STATIC +# define GLEWAPI extern +#else +# ifdef GLEW_BUILD +# define GLEWAPI extern __declspec(dllexport) +# else +# define GLEWAPI extern __declspec(dllimport) +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* -------------------------- WGL_3DFX_multisample ------------------------- */ + +#ifndef WGL_3DFX_multisample +#define WGL_3DFX_multisample 1 + +#define WGL_SAMPLE_BUFFERS_3DFX 0x2060 +#define WGL_SAMPLES_3DFX 0x2061 + +#define WGLEW_3DFX_multisample WGLEW_GET_VAR(__WGLEW_3DFX_multisample) + +#endif /* WGL_3DFX_multisample */ + +/* ------------------------- WGL_3DL_stereo_control ------------------------ */ + +#ifndef WGL_3DL_stereo_control +#define WGL_3DL_stereo_control 1 + +#define WGL_STEREO_EMITTER_ENABLE_3DL 0x2055 +#define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056 +#define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057 +#define WGL_STEREO_POLARITY_INVERT_3DL 0x2058 + +typedef BOOL (WINAPI * PFNWGLSETSTEREOEMITTERSTATE3DLPROC) (HDC hDC, UINT uState); + +#define wglSetStereoEmitterState3DL WGLEW_GET_FUN(__wglewSetStereoEmitterState3DL) + +#define WGLEW_3DL_stereo_control WGLEW_GET_VAR(__WGLEW_3DL_stereo_control) + +#endif /* WGL_3DL_stereo_control */ + +/* ------------------------ WGL_AMD_gpu_association ------------------------ */ + +#ifndef WGL_AMD_gpu_association +#define WGL_AMD_gpu_association 1 + +#define WGL_GPU_VENDOR_AMD 0x1F00 +#define WGL_GPU_RENDERER_STRING_AMD 0x1F01 +#define WGL_GPU_OPENGL_VERSION_STRING_AMD 0x1F02 +#define WGL_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2 +#define WGL_GPU_RAM_AMD 0x21A3 +#define WGL_GPU_CLOCK_AMD 0x21A4 +#define WGL_GPU_NUM_PIPES_AMD 0x21A5 +#define WGL_GPU_NUM_SIMD_AMD 0x21A6 +#define WGL_GPU_NUM_RB_AMD 0x21A7 +#define WGL_GPU_NUM_SPI_AMD 0x21A8 + +typedef VOID (WINAPI * PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC) (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC) (UINT id); +typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (UINT id, HGLRC hShareContext, const int* attribList); +typedef BOOL (WINAPI * PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC) (HGLRC hglrc); +typedef UINT (WINAPI * PFNWGLGETCONTEXTGPUIDAMDPROC) (HGLRC hglrc); +typedef HGLRC (WINAPI * PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void); +typedef UINT (WINAPI * PFNWGLGETGPUIDSAMDPROC) (UINT maxCount, UINT* ids); +typedef INT (WINAPI * PFNWGLGETGPUINFOAMDPROC) (UINT id, INT property, GLenum dataType, UINT size, void* data); +typedef BOOL (WINAPI * PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (HGLRC hglrc); + +#define wglBlitContextFramebufferAMD WGLEW_GET_FUN(__wglewBlitContextFramebufferAMD) +#define wglCreateAssociatedContextAMD WGLEW_GET_FUN(__wglewCreateAssociatedContextAMD) +#define wglCreateAssociatedContextAttribsAMD WGLEW_GET_FUN(__wglewCreateAssociatedContextAttribsAMD) +#define wglDeleteAssociatedContextAMD WGLEW_GET_FUN(__wglewDeleteAssociatedContextAMD) +#define wglGetContextGPUIDAMD WGLEW_GET_FUN(__wglewGetContextGPUIDAMD) +#define wglGetCurrentAssociatedContextAMD WGLEW_GET_FUN(__wglewGetCurrentAssociatedContextAMD) +#define wglGetGPUIDsAMD WGLEW_GET_FUN(__wglewGetGPUIDsAMD) +#define wglGetGPUInfoAMD WGLEW_GET_FUN(__wglewGetGPUInfoAMD) +#define wglMakeAssociatedContextCurrentAMD WGLEW_GET_FUN(__wglewMakeAssociatedContextCurrentAMD) + +#define WGLEW_AMD_gpu_association WGLEW_GET_VAR(__WGLEW_AMD_gpu_association) + +#endif /* WGL_AMD_gpu_association */ + +/* ------------------------- WGL_ARB_buffer_region ------------------------- */ + +#ifndef WGL_ARB_buffer_region +#define WGL_ARB_buffer_region 1 + +#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 +#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 +#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 +#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 + +typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); +typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); +typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); +typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); + +#define wglCreateBufferRegionARB WGLEW_GET_FUN(__wglewCreateBufferRegionARB) +#define wglDeleteBufferRegionARB WGLEW_GET_FUN(__wglewDeleteBufferRegionARB) +#define wglRestoreBufferRegionARB WGLEW_GET_FUN(__wglewRestoreBufferRegionARB) +#define wglSaveBufferRegionARB WGLEW_GET_FUN(__wglewSaveBufferRegionARB) + +#define WGLEW_ARB_buffer_region WGLEW_GET_VAR(__WGLEW_ARB_buffer_region) + +#endif /* WGL_ARB_buffer_region */ + +/* ------------------------- WGL_ARB_create_context ------------------------ */ + +#ifndef WGL_ARB_create_context +#define WGL_ARB_create_context 1 + +#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 +#define WGL_CONTEXT_FLAGS_ARB 0x2094 +#define ERROR_INVALID_VERSION_ARB 0x2095 +#define ERROR_INVALID_PROFILE_ARB 0x2096 + +typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int* attribList); + +#define wglCreateContextAttribsARB WGLEW_GET_FUN(__wglewCreateContextAttribsARB) + +#define WGLEW_ARB_create_context WGLEW_GET_VAR(__WGLEW_ARB_create_context) + +#endif /* WGL_ARB_create_context */ + +/* --------------------- WGL_ARB_create_context_profile -------------------- */ + +#ifndef WGL_ARB_create_context_profile +#define WGL_ARB_create_context_profile 1 + +#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 + +#define WGLEW_ARB_create_context_profile WGLEW_GET_VAR(__WGLEW_ARB_create_context_profile) + +#endif /* WGL_ARB_create_context_profile */ + +/* ------------------- WGL_ARB_create_context_robustness ------------------- */ + +#ifndef WGL_ARB_create_context_robustness +#define WGL_ARB_create_context_robustness 1 + +#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261 + +#define WGLEW_ARB_create_context_robustness WGLEW_GET_VAR(__WGLEW_ARB_create_context_robustness) + +#endif /* WGL_ARB_create_context_robustness */ + +/* ----------------------- WGL_ARB_extensions_string ----------------------- */ + +#ifndef WGL_ARB_extensions_string +#define WGL_ARB_extensions_string 1 + +typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); + +#define wglGetExtensionsStringARB WGLEW_GET_FUN(__wglewGetExtensionsStringARB) + +#define WGLEW_ARB_extensions_string WGLEW_GET_VAR(__WGLEW_ARB_extensions_string) + +#endif /* WGL_ARB_extensions_string */ + +/* ------------------------ WGL_ARB_framebuffer_sRGB ----------------------- */ + +#ifndef WGL_ARB_framebuffer_sRGB +#define WGL_ARB_framebuffer_sRGB 1 + +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 + +#define WGLEW_ARB_framebuffer_sRGB WGLEW_GET_VAR(__WGLEW_ARB_framebuffer_sRGB) + +#endif /* WGL_ARB_framebuffer_sRGB */ + +/* ----------------------- WGL_ARB_make_current_read ----------------------- */ + +#ifndef WGL_ARB_make_current_read +#define WGL_ARB_make_current_read 1 + +#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 +#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 + +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (VOID); +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); + +#define wglGetCurrentReadDCARB WGLEW_GET_FUN(__wglewGetCurrentReadDCARB) +#define wglMakeContextCurrentARB WGLEW_GET_FUN(__wglewMakeContextCurrentARB) + +#define WGLEW_ARB_make_current_read WGLEW_GET_VAR(__WGLEW_ARB_make_current_read) + +#endif /* WGL_ARB_make_current_read */ + +/* -------------------------- WGL_ARB_multisample -------------------------- */ + +#ifndef WGL_ARB_multisample +#define WGL_ARB_multisample 1 + +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 + +#define WGLEW_ARB_multisample WGLEW_GET_VAR(__WGLEW_ARB_multisample) + +#endif /* WGL_ARB_multisample */ + +/* ---------------------------- WGL_ARB_pbuffer ---------------------------- */ + +#ifndef WGL_ARB_pbuffer +#define WGL_ARB_pbuffer 1 + +#define WGL_DRAW_TO_PBUFFER_ARB 0x202D +#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E +#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 +#define WGL_PBUFFER_LARGEST_ARB 0x2033 +#define WGL_PBUFFER_WIDTH_ARB 0x2034 +#define WGL_PBUFFER_HEIGHT_ARB 0x2035 +#define WGL_PBUFFER_LOST_ARB 0x2036 + +DECLARE_HANDLE(HPBUFFERARB); + +typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int* piValue); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); + +#define wglCreatePbufferARB WGLEW_GET_FUN(__wglewCreatePbufferARB) +#define wglDestroyPbufferARB WGLEW_GET_FUN(__wglewDestroyPbufferARB) +#define wglGetPbufferDCARB WGLEW_GET_FUN(__wglewGetPbufferDCARB) +#define wglQueryPbufferARB WGLEW_GET_FUN(__wglewQueryPbufferARB) +#define wglReleasePbufferDCARB WGLEW_GET_FUN(__wglewReleasePbufferDCARB) + +#define WGLEW_ARB_pbuffer WGLEW_GET_VAR(__WGLEW_ARB_pbuffer) + +#endif /* WGL_ARB_pbuffer */ + +/* -------------------------- WGL_ARB_pixel_format ------------------------- */ + +#ifndef WGL_ARB_pixel_format +#define WGL_ARB_pixel_format 1 + +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B + +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, int *piValues); + +#define wglChoosePixelFormatARB WGLEW_GET_FUN(__wglewChoosePixelFormatARB) +#define wglGetPixelFormatAttribfvARB WGLEW_GET_FUN(__wglewGetPixelFormatAttribfvARB) +#define wglGetPixelFormatAttribivARB WGLEW_GET_FUN(__wglewGetPixelFormatAttribivARB) + +#define WGLEW_ARB_pixel_format WGLEW_GET_VAR(__WGLEW_ARB_pixel_format) + +#endif /* WGL_ARB_pixel_format */ + +/* ----------------------- WGL_ARB_pixel_format_float ---------------------- */ + +#ifndef WGL_ARB_pixel_format_float +#define WGL_ARB_pixel_format_float 1 + +#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 + +#define WGLEW_ARB_pixel_format_float WGLEW_GET_VAR(__WGLEW_ARB_pixel_format_float) + +#endif /* WGL_ARB_pixel_format_float */ + +/* ------------------------- WGL_ARB_render_texture ------------------------ */ + +#ifndef WGL_ARB_render_texture +#define WGL_ARB_render_texture 1 + +#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 +#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 +#define WGL_TEXTURE_FORMAT_ARB 0x2072 +#define WGL_TEXTURE_TARGET_ARB 0x2073 +#define WGL_MIPMAP_TEXTURE_ARB 0x2074 +#define WGL_TEXTURE_RGB_ARB 0x2075 +#define WGL_TEXTURE_RGBA_ARB 0x2076 +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 +#define WGL_TEXTURE_1D_ARB 0x2079 +#define WGL_TEXTURE_2D_ARB 0x207A +#define WGL_MIPMAP_LEVEL_ARB 0x207B +#define WGL_CUBE_MAP_FACE_ARB 0x207C +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 +#define WGL_FRONT_LEFT_ARB 0x2083 +#define WGL_FRONT_RIGHT_ARB 0x2084 +#define WGL_BACK_LEFT_ARB 0x2085 +#define WGL_BACK_RIGHT_ARB 0x2086 +#define WGL_AUX0_ARB 0x2087 +#define WGL_AUX1_ARB 0x2088 +#define WGL_AUX2_ARB 0x2089 +#define WGL_AUX3_ARB 0x208A +#define WGL_AUX4_ARB 0x208B +#define WGL_AUX5_ARB 0x208C +#define WGL_AUX6_ARB 0x208D +#define WGL_AUX7_ARB 0x208E +#define WGL_AUX8_ARB 0x208F +#define WGL_AUX9_ARB 0x2090 + +typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int* piAttribList); + +#define wglBindTexImageARB WGLEW_GET_FUN(__wglewBindTexImageARB) +#define wglReleaseTexImageARB WGLEW_GET_FUN(__wglewReleaseTexImageARB) +#define wglSetPbufferAttribARB WGLEW_GET_FUN(__wglewSetPbufferAttribARB) + +#define WGLEW_ARB_render_texture WGLEW_GET_VAR(__WGLEW_ARB_render_texture) + +#endif /* WGL_ARB_render_texture */ + +/* ----------------------- WGL_ATI_pixel_format_float ---------------------- */ + +#ifndef WGL_ATI_pixel_format_float +#define WGL_ATI_pixel_format_float 1 + +#define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0 +#define GL_RGBA_FLOAT_MODE_ATI 0x8820 +#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835 + +#define WGLEW_ATI_pixel_format_float WGLEW_GET_VAR(__WGLEW_ATI_pixel_format_float) + +#endif /* WGL_ATI_pixel_format_float */ + +/* -------------------- WGL_ATI_render_texture_rectangle ------------------- */ + +#ifndef WGL_ATI_render_texture_rectangle +#define WGL_ATI_render_texture_rectangle 1 + +#define WGL_TEXTURE_RECTANGLE_ATI 0x21A5 + +#define WGLEW_ATI_render_texture_rectangle WGLEW_GET_VAR(__WGLEW_ATI_render_texture_rectangle) + +#endif /* WGL_ATI_render_texture_rectangle */ + +/* ------------------- WGL_EXT_create_context_es2_profile ------------------ */ + +#ifndef WGL_EXT_create_context_es2_profile +#define WGL_EXT_create_context_es2_profile 1 + +#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 + +#define WGLEW_EXT_create_context_es2_profile WGLEW_GET_VAR(__WGLEW_EXT_create_context_es2_profile) + +#endif /* WGL_EXT_create_context_es2_profile */ + +/* -------------------------- WGL_EXT_depth_float -------------------------- */ + +#ifndef WGL_EXT_depth_float +#define WGL_EXT_depth_float 1 + +#define WGL_DEPTH_FLOAT_EXT 0x2040 + +#define WGLEW_EXT_depth_float WGLEW_GET_VAR(__WGLEW_EXT_depth_float) + +#endif /* WGL_EXT_depth_float */ + +/* ---------------------- WGL_EXT_display_color_table ---------------------- */ + +#ifndef WGL_EXT_display_color_table +#define WGL_EXT_display_color_table 1 + +typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef void (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (GLushort* table, GLuint length); + +#define wglBindDisplayColorTableEXT WGLEW_GET_FUN(__wglewBindDisplayColorTableEXT) +#define wglCreateDisplayColorTableEXT WGLEW_GET_FUN(__wglewCreateDisplayColorTableEXT) +#define wglDestroyDisplayColorTableEXT WGLEW_GET_FUN(__wglewDestroyDisplayColorTableEXT) +#define wglLoadDisplayColorTableEXT WGLEW_GET_FUN(__wglewLoadDisplayColorTableEXT) + +#define WGLEW_EXT_display_color_table WGLEW_GET_VAR(__WGLEW_EXT_display_color_table) + +#endif /* WGL_EXT_display_color_table */ + +/* ----------------------- WGL_EXT_extensions_string ----------------------- */ + +#ifndef WGL_EXT_extensions_string +#define WGL_EXT_extensions_string 1 + +typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); + +#define wglGetExtensionsStringEXT WGLEW_GET_FUN(__wglewGetExtensionsStringEXT) + +#define WGLEW_EXT_extensions_string WGLEW_GET_VAR(__WGLEW_EXT_extensions_string) + +#endif /* WGL_EXT_extensions_string */ + +/* ------------------------ WGL_EXT_framebuffer_sRGB ----------------------- */ + +#ifndef WGL_EXT_framebuffer_sRGB +#define WGL_EXT_framebuffer_sRGB 1 + +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9 + +#define WGLEW_EXT_framebuffer_sRGB WGLEW_GET_VAR(__WGLEW_EXT_framebuffer_sRGB) + +#endif /* WGL_EXT_framebuffer_sRGB */ + +/* ----------------------- WGL_EXT_make_current_read ----------------------- */ + +#ifndef WGL_EXT_make_current_read +#define WGL_EXT_make_current_read 1 + +#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 + +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (VOID); +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); + +#define wglGetCurrentReadDCEXT WGLEW_GET_FUN(__wglewGetCurrentReadDCEXT) +#define wglMakeContextCurrentEXT WGLEW_GET_FUN(__wglewMakeContextCurrentEXT) + +#define WGLEW_EXT_make_current_read WGLEW_GET_VAR(__WGLEW_EXT_make_current_read) + +#endif /* WGL_EXT_make_current_read */ + +/* -------------------------- WGL_EXT_multisample -------------------------- */ + +#ifndef WGL_EXT_multisample +#define WGL_EXT_multisample 1 + +#define WGL_SAMPLE_BUFFERS_EXT 0x2041 +#define WGL_SAMPLES_EXT 0x2042 + +#define WGLEW_EXT_multisample WGLEW_GET_VAR(__WGLEW_EXT_multisample) + +#endif /* WGL_EXT_multisample */ + +/* ---------------------------- WGL_EXT_pbuffer ---------------------------- */ + +#ifndef WGL_EXT_pbuffer +#define WGL_EXT_pbuffer 1 + +#define WGL_DRAW_TO_PBUFFER_EXT 0x202D +#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E +#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 +#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 +#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 +#define WGL_PBUFFER_LARGEST_EXT 0x2033 +#define WGL_PBUFFER_WIDTH_EXT 0x2034 +#define WGL_PBUFFER_HEIGHT_EXT 0x2035 + +DECLARE_HANDLE(HPBUFFEREXT); + +typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int* piValue); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); + +#define wglCreatePbufferEXT WGLEW_GET_FUN(__wglewCreatePbufferEXT) +#define wglDestroyPbufferEXT WGLEW_GET_FUN(__wglewDestroyPbufferEXT) +#define wglGetPbufferDCEXT WGLEW_GET_FUN(__wglewGetPbufferDCEXT) +#define wglQueryPbufferEXT WGLEW_GET_FUN(__wglewQueryPbufferEXT) +#define wglReleasePbufferDCEXT WGLEW_GET_FUN(__wglewReleasePbufferDCEXT) + +#define WGLEW_EXT_pbuffer WGLEW_GET_VAR(__WGLEW_EXT_pbuffer) + +#endif /* WGL_EXT_pbuffer */ + +/* -------------------------- WGL_EXT_pixel_format ------------------------- */ + +#ifndef WGL_EXT_pixel_format +#define WGL_EXT_pixel_format 1 + +#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 +#define WGL_DRAW_TO_WINDOW_EXT 0x2001 +#define WGL_DRAW_TO_BITMAP_EXT 0x2002 +#define WGL_ACCELERATION_EXT 0x2003 +#define WGL_NEED_PALETTE_EXT 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 +#define WGL_SWAP_METHOD_EXT 0x2007 +#define WGL_NUMBER_OVERLAYS_EXT 0x2008 +#define WGL_NUMBER_UNDERLAYS_EXT 0x2009 +#define WGL_TRANSPARENT_EXT 0x200A +#define WGL_TRANSPARENT_VALUE_EXT 0x200B +#define WGL_SHARE_DEPTH_EXT 0x200C +#define WGL_SHARE_STENCIL_EXT 0x200D +#define WGL_SHARE_ACCUM_EXT 0x200E +#define WGL_SUPPORT_GDI_EXT 0x200F +#define WGL_SUPPORT_OPENGL_EXT 0x2010 +#define WGL_DOUBLE_BUFFER_EXT 0x2011 +#define WGL_STEREO_EXT 0x2012 +#define WGL_PIXEL_TYPE_EXT 0x2013 +#define WGL_COLOR_BITS_EXT 0x2014 +#define WGL_RED_BITS_EXT 0x2015 +#define WGL_RED_SHIFT_EXT 0x2016 +#define WGL_GREEN_BITS_EXT 0x2017 +#define WGL_GREEN_SHIFT_EXT 0x2018 +#define WGL_BLUE_BITS_EXT 0x2019 +#define WGL_BLUE_SHIFT_EXT 0x201A +#define WGL_ALPHA_BITS_EXT 0x201B +#define WGL_ALPHA_SHIFT_EXT 0x201C +#define WGL_ACCUM_BITS_EXT 0x201D +#define WGL_ACCUM_RED_BITS_EXT 0x201E +#define WGL_ACCUM_GREEN_BITS_EXT 0x201F +#define WGL_ACCUM_BLUE_BITS_EXT 0x2020 +#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 +#define WGL_DEPTH_BITS_EXT 0x2022 +#define WGL_STENCIL_BITS_EXT 0x2023 +#define WGL_AUX_BUFFERS_EXT 0x2024 +#define WGL_NO_ACCELERATION_EXT 0x2025 +#define WGL_GENERIC_ACCELERATION_EXT 0x2026 +#define WGL_FULL_ACCELERATION_EXT 0x2027 +#define WGL_SWAP_EXCHANGE_EXT 0x2028 +#define WGL_SWAP_COPY_EXT 0x2029 +#define WGL_SWAP_UNDEFINED_EXT 0x202A +#define WGL_TYPE_RGBA_EXT 0x202B +#define WGL_TYPE_COLORINDEX_EXT 0x202C + +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int *piValues); + +#define wglChoosePixelFormatEXT WGLEW_GET_FUN(__wglewChoosePixelFormatEXT) +#define wglGetPixelFormatAttribfvEXT WGLEW_GET_FUN(__wglewGetPixelFormatAttribfvEXT) +#define wglGetPixelFormatAttribivEXT WGLEW_GET_FUN(__wglewGetPixelFormatAttribivEXT) + +#define WGLEW_EXT_pixel_format WGLEW_GET_VAR(__WGLEW_EXT_pixel_format) + +#endif /* WGL_EXT_pixel_format */ + +/* ------------------- WGL_EXT_pixel_format_packed_float ------------------- */ + +#ifndef WGL_EXT_pixel_format_packed_float +#define WGL_EXT_pixel_format_packed_float 1 + +#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8 + +#define WGLEW_EXT_pixel_format_packed_float WGLEW_GET_VAR(__WGLEW_EXT_pixel_format_packed_float) + +#endif /* WGL_EXT_pixel_format_packed_float */ + +/* -------------------------- WGL_EXT_swap_control ------------------------- */ + +#ifndef WGL_EXT_swap_control +#define WGL_EXT_swap_control 1 + +typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); +typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); + +#define wglGetSwapIntervalEXT WGLEW_GET_FUN(__wglewGetSwapIntervalEXT) +#define wglSwapIntervalEXT WGLEW_GET_FUN(__wglewSwapIntervalEXT) + +#define WGLEW_EXT_swap_control WGLEW_GET_VAR(__WGLEW_EXT_swap_control) + +#endif /* WGL_EXT_swap_control */ + +/* --------------------- WGL_I3D_digital_video_control --------------------- */ + +#ifndef WGL_I3D_digital_video_control +#define WGL_I3D_digital_video_control 1 + +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 +#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 +#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 + +typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int* piValue); +typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int* piValue); + +#define wglGetDigitalVideoParametersI3D WGLEW_GET_FUN(__wglewGetDigitalVideoParametersI3D) +#define wglSetDigitalVideoParametersI3D WGLEW_GET_FUN(__wglewSetDigitalVideoParametersI3D) + +#define WGLEW_I3D_digital_video_control WGLEW_GET_VAR(__WGLEW_I3D_digital_video_control) + +#endif /* WGL_I3D_digital_video_control */ + +/* ----------------------------- WGL_I3D_gamma ----------------------------- */ + +#ifndef WGL_I3D_gamma +#define WGL_I3D_gamma 1 + +#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E +#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F + +typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT* puRed, USHORT *puGreen, USHORT *puBlue); +typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int* piValue); +typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT* puRed, const USHORT *puGreen, const USHORT *puBlue); +typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int* piValue); + +#define wglGetGammaTableI3D WGLEW_GET_FUN(__wglewGetGammaTableI3D) +#define wglGetGammaTableParametersI3D WGLEW_GET_FUN(__wglewGetGammaTableParametersI3D) +#define wglSetGammaTableI3D WGLEW_GET_FUN(__wglewSetGammaTableI3D) +#define wglSetGammaTableParametersI3D WGLEW_GET_FUN(__wglewSetGammaTableParametersI3D) + +#define WGLEW_I3D_gamma WGLEW_GET_VAR(__WGLEW_I3D_gamma) + +#endif /* WGL_I3D_gamma */ + +/* ---------------------------- WGL_I3D_genlock ---------------------------- */ + +#ifndef WGL_I3D_genlock +#define WGL_I3D_genlock 1 + +#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 +#define WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D 0x2045 +#define WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D 0x2046 +#define WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D 0x2047 +#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 +#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 +#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A +#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B +#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C + +typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC); +typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC); +typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT* uRate); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT* uDelay); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT* uEdge); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT* uSource); +typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL* pFlag); +typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT* uMaxLineDelay, UINT *uMaxPixelDelay); + +#define wglDisableGenlockI3D WGLEW_GET_FUN(__wglewDisableGenlockI3D) +#define wglEnableGenlockI3D WGLEW_GET_FUN(__wglewEnableGenlockI3D) +#define wglGenlockSampleRateI3D WGLEW_GET_FUN(__wglewGenlockSampleRateI3D) +#define wglGenlockSourceDelayI3D WGLEW_GET_FUN(__wglewGenlockSourceDelayI3D) +#define wglGenlockSourceEdgeI3D WGLEW_GET_FUN(__wglewGenlockSourceEdgeI3D) +#define wglGenlockSourceI3D WGLEW_GET_FUN(__wglewGenlockSourceI3D) +#define wglGetGenlockSampleRateI3D WGLEW_GET_FUN(__wglewGetGenlockSampleRateI3D) +#define wglGetGenlockSourceDelayI3D WGLEW_GET_FUN(__wglewGetGenlockSourceDelayI3D) +#define wglGetGenlockSourceEdgeI3D WGLEW_GET_FUN(__wglewGetGenlockSourceEdgeI3D) +#define wglGetGenlockSourceI3D WGLEW_GET_FUN(__wglewGetGenlockSourceI3D) +#define wglIsEnabledGenlockI3D WGLEW_GET_FUN(__wglewIsEnabledGenlockI3D) +#define wglQueryGenlockMaxSourceDelayI3D WGLEW_GET_FUN(__wglewQueryGenlockMaxSourceDelayI3D) + +#define WGLEW_I3D_genlock WGLEW_GET_VAR(__WGLEW_I3D_genlock) + +#endif /* WGL_I3D_genlock */ + +/* -------------------------- WGL_I3D_image_buffer ------------------------- */ + +#ifndef WGL_I3D_image_buffer +#define WGL_I3D_image_buffer 1 + +#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001 +#define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002 + +typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hdc, HANDLE* pEvent, LPVOID *pAddress, DWORD *pSize, UINT count); +typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags); +typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress); +typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hdc, LPVOID* pAddress, UINT count); + +#define wglAssociateImageBufferEventsI3D WGLEW_GET_FUN(__wglewAssociateImageBufferEventsI3D) +#define wglCreateImageBufferI3D WGLEW_GET_FUN(__wglewCreateImageBufferI3D) +#define wglDestroyImageBufferI3D WGLEW_GET_FUN(__wglewDestroyImageBufferI3D) +#define wglReleaseImageBufferEventsI3D WGLEW_GET_FUN(__wglewReleaseImageBufferEventsI3D) + +#define WGLEW_I3D_image_buffer WGLEW_GET_VAR(__WGLEW_I3D_image_buffer) + +#endif /* WGL_I3D_image_buffer */ + +/* ------------------------ WGL_I3D_swap_frame_lock ------------------------ */ + +#ifndef WGL_I3D_swap_frame_lock +#define WGL_I3D_swap_frame_lock 1 + +typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (VOID); +typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (VOID); +typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL* pFlag); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL* pFlag); + +#define wglDisableFrameLockI3D WGLEW_GET_FUN(__wglewDisableFrameLockI3D) +#define wglEnableFrameLockI3D WGLEW_GET_FUN(__wglewEnableFrameLockI3D) +#define wglIsEnabledFrameLockI3D WGLEW_GET_FUN(__wglewIsEnabledFrameLockI3D) +#define wglQueryFrameLockMasterI3D WGLEW_GET_FUN(__wglewQueryFrameLockMasterI3D) + +#define WGLEW_I3D_swap_frame_lock WGLEW_GET_VAR(__WGLEW_I3D_swap_frame_lock) + +#endif /* WGL_I3D_swap_frame_lock */ + +/* ------------------------ WGL_I3D_swap_frame_usage ----------------------- */ + +#ifndef WGL_I3D_swap_frame_usage +#define WGL_I3D_swap_frame_usage 1 + +typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float* pUsage); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD* pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); + +#define wglBeginFrameTrackingI3D WGLEW_GET_FUN(__wglewBeginFrameTrackingI3D) +#define wglEndFrameTrackingI3D WGLEW_GET_FUN(__wglewEndFrameTrackingI3D) +#define wglGetFrameUsageI3D WGLEW_GET_FUN(__wglewGetFrameUsageI3D) +#define wglQueryFrameTrackingI3D WGLEW_GET_FUN(__wglewQueryFrameTrackingI3D) + +#define WGLEW_I3D_swap_frame_usage WGLEW_GET_VAR(__WGLEW_I3D_swap_frame_usage) + +#endif /* WGL_I3D_swap_frame_usage */ + +/* --------------------------- WGL_NV_DX_interop --------------------------- */ + +#ifndef WGL_NV_DX_interop +#define WGL_NV_DX_interop 1 + +#define WGL_ACCESS_READ_ONLY_NV 0x0000 +#define WGL_ACCESS_READ_WRITE_NV 0x0001 +#define WGL_ACCESS_WRITE_DISCARD_NV 0x0002 + +typedef BOOL (WINAPI * PFNWGLDXCLOSEDEVICENVPROC) (HANDLE hDevice); +typedef BOOL (WINAPI * PFNWGLDXLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects); +typedef BOOL (WINAPI * PFNWGLDXOBJECTACCESSNVPROC) (HANDLE hObject, GLenum access); +typedef HANDLE (WINAPI * PFNWGLDXOPENDEVICENVPROC) (void* dxDevice); +typedef HANDLE (WINAPI * PFNWGLDXREGISTEROBJECTNVPROC) (HANDLE hDevice, void* dxObject, GLuint name, GLenum type, GLenum access); +typedef BOOL (WINAPI * PFNWGLDXSETRESOURCESHAREHANDLENVPROC) (void* dxObject, HANDLE shareHandle); +typedef BOOL (WINAPI * PFNWGLDXUNLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects); +typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECTNVPROC) (HANDLE hDevice, HANDLE hObject); + +#define wglDXCloseDeviceNV WGLEW_GET_FUN(__wglewDXCloseDeviceNV) +#define wglDXLockObjectsNV WGLEW_GET_FUN(__wglewDXLockObjectsNV) +#define wglDXObjectAccessNV WGLEW_GET_FUN(__wglewDXObjectAccessNV) +#define wglDXOpenDeviceNV WGLEW_GET_FUN(__wglewDXOpenDeviceNV) +#define wglDXRegisterObjectNV WGLEW_GET_FUN(__wglewDXRegisterObjectNV) +#define wglDXSetResourceShareHandleNV WGLEW_GET_FUN(__wglewDXSetResourceShareHandleNV) +#define wglDXUnlockObjectsNV WGLEW_GET_FUN(__wglewDXUnlockObjectsNV) +#define wglDXUnregisterObjectNV WGLEW_GET_FUN(__wglewDXUnregisterObjectNV) + +#define WGLEW_NV_DX_interop WGLEW_GET_VAR(__WGLEW_NV_DX_interop) + +#endif /* WGL_NV_DX_interop */ + +/* --------------------------- WGL_NV_copy_image --------------------------- */ + +#ifndef WGL_NV_copy_image +#define WGL_NV_copy_image 1 + +typedef BOOL (WINAPI * PFNWGLCOPYIMAGESUBDATANVPROC) (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); + +#define wglCopyImageSubDataNV WGLEW_GET_FUN(__wglewCopyImageSubDataNV) + +#define WGLEW_NV_copy_image WGLEW_GET_VAR(__WGLEW_NV_copy_image) + +#endif /* WGL_NV_copy_image */ + +/* -------------------------- WGL_NV_float_buffer -------------------------- */ + +#ifndef WGL_NV_float_buffer +#define WGL_NV_float_buffer 1 + +#define WGL_FLOAT_COMPONENTS_NV 0x20B0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4 +#define WGL_TEXTURE_FLOAT_R_NV 0x20B5 +#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6 +#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7 +#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8 + +#define WGLEW_NV_float_buffer WGLEW_GET_VAR(__WGLEW_NV_float_buffer) + +#endif /* WGL_NV_float_buffer */ + +/* -------------------------- WGL_NV_gpu_affinity -------------------------- */ + +#ifndef WGL_NV_gpu_affinity +#define WGL_NV_gpu_affinity 1 + +#define WGL_ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0 +#define WGL_ERROR_MISSING_AFFINITY_MASK_NV 0x20D1 + +DECLARE_HANDLE(HGPUNV); +typedef struct _GPU_DEVICE { + DWORD cb; + CHAR DeviceName[32]; + CHAR DeviceString[128]; + DWORD Flags; + RECT rcVirtualScreen; +} GPU_DEVICE, *PGPU_DEVICE; + +typedef HDC (WINAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *phGpuList); +typedef BOOL (WINAPI * PFNWGLDELETEDCNVPROC) (HDC hdc); +typedef BOOL (WINAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice); +typedef BOOL (WINAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu); +typedef BOOL (WINAPI * PFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV *phGpu); + +#define wglCreateAffinityDCNV WGLEW_GET_FUN(__wglewCreateAffinityDCNV) +#define wglDeleteDCNV WGLEW_GET_FUN(__wglewDeleteDCNV) +#define wglEnumGpuDevicesNV WGLEW_GET_FUN(__wglewEnumGpuDevicesNV) +#define wglEnumGpusFromAffinityDCNV WGLEW_GET_FUN(__wglewEnumGpusFromAffinityDCNV) +#define wglEnumGpusNV WGLEW_GET_FUN(__wglewEnumGpusNV) + +#define WGLEW_NV_gpu_affinity WGLEW_GET_VAR(__WGLEW_NV_gpu_affinity) + +#endif /* WGL_NV_gpu_affinity */ + +/* ---------------------- WGL_NV_multisample_coverage ---------------------- */ + +#ifndef WGL_NV_multisample_coverage +#define WGL_NV_multisample_coverage 1 + +#define WGL_COVERAGE_SAMPLES_NV 0x2042 +#define WGL_COLOR_SAMPLES_NV 0x20B9 + +#define WGLEW_NV_multisample_coverage WGLEW_GET_VAR(__WGLEW_NV_multisample_coverage) + +#endif /* WGL_NV_multisample_coverage */ + +/* -------------------------- WGL_NV_present_video ------------------------- */ + +#ifndef WGL_NV_present_video +#define WGL_NV_present_video 1 + +#define WGL_NUM_VIDEO_SLOTS_NV 0x20F0 + +DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV); + +typedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDc, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int* piAttribList); +typedef int (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDc, HVIDEOOUTPUTDEVICENV* phDeviceList); +typedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int* piValue); + +#define wglBindVideoDeviceNV WGLEW_GET_FUN(__wglewBindVideoDeviceNV) +#define wglEnumerateVideoDevicesNV WGLEW_GET_FUN(__wglewEnumerateVideoDevicesNV) +#define wglQueryCurrentContextNV WGLEW_GET_FUN(__wglewQueryCurrentContextNV) + +#define WGLEW_NV_present_video WGLEW_GET_VAR(__WGLEW_NV_present_video) + +#endif /* WGL_NV_present_video */ + +/* ---------------------- WGL_NV_render_depth_texture ---------------------- */ + +#ifndef WGL_NV_render_depth_texture +#define WGL_NV_render_depth_texture 1 + +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 +#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 +#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 +#define WGL_DEPTH_COMPONENT_NV 0x20A7 + +#define WGLEW_NV_render_depth_texture WGLEW_GET_VAR(__WGLEW_NV_render_depth_texture) + +#endif /* WGL_NV_render_depth_texture */ + +/* -------------------- WGL_NV_render_texture_rectangle -------------------- */ + +#ifndef WGL_NV_render_texture_rectangle +#define WGL_NV_render_texture_rectangle 1 + +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 +#define WGL_TEXTURE_RECTANGLE_NV 0x20A2 + +#define WGLEW_NV_render_texture_rectangle WGLEW_GET_VAR(__WGLEW_NV_render_texture_rectangle) + +#endif /* WGL_NV_render_texture_rectangle */ + +/* --------------------------- WGL_NV_swap_group --------------------------- */ + +#ifndef WGL_NV_swap_group +#define WGL_NV_swap_group 1 + +typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier); +typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint* count); +typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint* maxGroups, GLuint *maxBarriers); +typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint* group, GLuint *barrier); +typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC); + +#define wglBindSwapBarrierNV WGLEW_GET_FUN(__wglewBindSwapBarrierNV) +#define wglJoinSwapGroupNV WGLEW_GET_FUN(__wglewJoinSwapGroupNV) +#define wglQueryFrameCountNV WGLEW_GET_FUN(__wglewQueryFrameCountNV) +#define wglQueryMaxSwapGroupsNV WGLEW_GET_FUN(__wglewQueryMaxSwapGroupsNV) +#define wglQuerySwapGroupNV WGLEW_GET_FUN(__wglewQuerySwapGroupNV) +#define wglResetFrameCountNV WGLEW_GET_FUN(__wglewResetFrameCountNV) + +#define WGLEW_NV_swap_group WGLEW_GET_VAR(__WGLEW_NV_swap_group) + +#endif /* WGL_NV_swap_group */ + +/* ----------------------- WGL_NV_vertex_array_range ----------------------- */ + +#ifndef WGL_NV_vertex_array_range +#define WGL_NV_vertex_array_range 1 + +typedef void * (WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority); +typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer); + +#define wglAllocateMemoryNV WGLEW_GET_FUN(__wglewAllocateMemoryNV) +#define wglFreeMemoryNV WGLEW_GET_FUN(__wglewFreeMemoryNV) + +#define WGLEW_NV_vertex_array_range WGLEW_GET_VAR(__WGLEW_NV_vertex_array_range) + +#endif /* WGL_NV_vertex_array_range */ + +/* -------------------------- WGL_NV_video_capture ------------------------- */ + +#ifndef WGL_NV_video_capture +#define WGL_NV_video_capture 1 + +#define WGL_UNIQUE_ID_NV 0x20CE +#define WGL_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF + +DECLARE_HANDLE(HVIDEOINPUTDEVICENV); + +typedef BOOL (WINAPI * PFNWGLBINDVIDEOCAPTUREDEVICENVPROC) (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice); +typedef UINT (WINAPI * PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC) (HDC hDc, HVIDEOINPUTDEVICENV* phDeviceList); +typedef BOOL (WINAPI * PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice); +typedef BOOL (WINAPI * PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int* piValue); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice); + +#define wglBindVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewBindVideoCaptureDeviceNV) +#define wglEnumerateVideoCaptureDevicesNV WGLEW_GET_FUN(__wglewEnumerateVideoCaptureDevicesNV) +#define wglLockVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewLockVideoCaptureDeviceNV) +#define wglQueryVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewQueryVideoCaptureDeviceNV) +#define wglReleaseVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewReleaseVideoCaptureDeviceNV) + +#define WGLEW_NV_video_capture WGLEW_GET_VAR(__WGLEW_NV_video_capture) + +#endif /* WGL_NV_video_capture */ + +/* -------------------------- WGL_NV_video_output -------------------------- */ + +#ifndef WGL_NV_video_output +#define WGL_NV_video_output 1 + +#define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0 +#define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1 +#define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2 +#define WGL_VIDEO_OUT_COLOR_NV 0x20C3 +#define WGL_VIDEO_OUT_ALPHA_NV 0x20C4 +#define WGL_VIDEO_OUT_DEPTH_NV 0x20C5 +#define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 +#define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 +#define WGL_VIDEO_OUT_FRAME 0x20C8 +#define WGL_VIDEO_OUT_FIELD_1 0x20C9 +#define WGL_VIDEO_OUT_FIELD_2 0x20CA +#define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB +#define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC + +DECLARE_HANDLE(HPVIDEODEV); + +typedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer); +typedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV* hVideoDevice); +typedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long* pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer); +typedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long* pulCounterPbuffer, BOOL bBlock); + +#define wglBindVideoImageNV WGLEW_GET_FUN(__wglewBindVideoImageNV) +#define wglGetVideoDeviceNV WGLEW_GET_FUN(__wglewGetVideoDeviceNV) +#define wglGetVideoInfoNV WGLEW_GET_FUN(__wglewGetVideoInfoNV) +#define wglReleaseVideoDeviceNV WGLEW_GET_FUN(__wglewReleaseVideoDeviceNV) +#define wglReleaseVideoImageNV WGLEW_GET_FUN(__wglewReleaseVideoImageNV) +#define wglSendPbufferToVideoNV WGLEW_GET_FUN(__wglewSendPbufferToVideoNV) + +#define WGLEW_NV_video_output WGLEW_GET_VAR(__WGLEW_NV_video_output) + +#endif /* WGL_NV_video_output */ + +/* -------------------------- WGL_OML_sync_control ------------------------- */ + +#ifndef WGL_OML_sync_control +#define WGL_OML_sync_control 1 + +typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32* numerator, INT32 *denominator); +typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64* ust, INT64 *msc, INT64 *sbc); +typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); +typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, INT fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); +typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64* ust, INT64 *msc, INT64 *sbc); +typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64* ust, INT64 *msc, INT64 *sbc); + +#define wglGetMscRateOML WGLEW_GET_FUN(__wglewGetMscRateOML) +#define wglGetSyncValuesOML WGLEW_GET_FUN(__wglewGetSyncValuesOML) +#define wglSwapBuffersMscOML WGLEW_GET_FUN(__wglewSwapBuffersMscOML) +#define wglSwapLayerBuffersMscOML WGLEW_GET_FUN(__wglewSwapLayerBuffersMscOML) +#define wglWaitForMscOML WGLEW_GET_FUN(__wglewWaitForMscOML) +#define wglWaitForSbcOML WGLEW_GET_FUN(__wglewWaitForSbcOML) + +#define WGLEW_OML_sync_control WGLEW_GET_VAR(__WGLEW_OML_sync_control) + +#endif /* WGL_OML_sync_control */ + +/* ------------------------------------------------------------------------- */ + +#ifdef GLEW_MX +#define WGLEW_EXPORT +#else +#define WGLEW_EXPORT GLEWAPI +#endif /* GLEW_MX */ + +#ifdef GLEW_MX +struct WGLEWContextStruct +{ +#endif /* GLEW_MX */ + +WGLEW_EXPORT PFNWGLSETSTEREOEMITTERSTATE3DLPROC __wglewSetStereoEmitterState3DL; + +WGLEW_EXPORT PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC __wglewBlitContextFramebufferAMD; +WGLEW_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC __wglewCreateAssociatedContextAMD; +WGLEW_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __wglewCreateAssociatedContextAttribsAMD; +WGLEW_EXPORT PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC __wglewDeleteAssociatedContextAMD; +WGLEW_EXPORT PFNWGLGETCONTEXTGPUIDAMDPROC __wglewGetContextGPUIDAMD; +WGLEW_EXPORT PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC __wglewGetCurrentAssociatedContextAMD; +WGLEW_EXPORT PFNWGLGETGPUIDSAMDPROC __wglewGetGPUIDsAMD; +WGLEW_EXPORT PFNWGLGETGPUINFOAMDPROC __wglewGetGPUInfoAMD; +WGLEW_EXPORT PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __wglewMakeAssociatedContextCurrentAMD; + +WGLEW_EXPORT PFNWGLCREATEBUFFERREGIONARBPROC __wglewCreateBufferRegionARB; +WGLEW_EXPORT PFNWGLDELETEBUFFERREGIONARBPROC __wglewDeleteBufferRegionARB; +WGLEW_EXPORT PFNWGLRESTOREBUFFERREGIONARBPROC __wglewRestoreBufferRegionARB; +WGLEW_EXPORT PFNWGLSAVEBUFFERREGIONARBPROC __wglewSaveBufferRegionARB; + +WGLEW_EXPORT PFNWGLCREATECONTEXTATTRIBSARBPROC __wglewCreateContextAttribsARB; + +WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGARBPROC __wglewGetExtensionsStringARB; + +WGLEW_EXPORT PFNWGLGETCURRENTREADDCARBPROC __wglewGetCurrentReadDCARB; +WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTARBPROC __wglewMakeContextCurrentARB; + +WGLEW_EXPORT PFNWGLCREATEPBUFFERARBPROC __wglewCreatePbufferARB; +WGLEW_EXPORT PFNWGLDESTROYPBUFFERARBPROC __wglewDestroyPbufferARB; +WGLEW_EXPORT PFNWGLGETPBUFFERDCARBPROC __wglewGetPbufferDCARB; +WGLEW_EXPORT PFNWGLQUERYPBUFFERARBPROC __wglewQueryPbufferARB; +WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCARBPROC __wglewReleasePbufferDCARB; + +WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB; +WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVARBPROC __wglewGetPixelFormatAttribfvARB; +WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVARBPROC __wglewGetPixelFormatAttribivARB; + +WGLEW_EXPORT PFNWGLBINDTEXIMAGEARBPROC __wglewBindTexImageARB; +WGLEW_EXPORT PFNWGLRELEASETEXIMAGEARBPROC __wglewReleaseTexImageARB; +WGLEW_EXPORT PFNWGLSETPBUFFERATTRIBARBPROC __wglewSetPbufferAttribARB; + +WGLEW_EXPORT PFNWGLBINDDISPLAYCOLORTABLEEXTPROC __wglewBindDisplayColorTableEXT; +WGLEW_EXPORT PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC __wglewCreateDisplayColorTableEXT; +WGLEW_EXPORT PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC __wglewDestroyDisplayColorTableEXT; +WGLEW_EXPORT PFNWGLLOADDISPLAYCOLORTABLEEXTPROC __wglewLoadDisplayColorTableEXT; + +WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGEXTPROC __wglewGetExtensionsStringEXT; + +WGLEW_EXPORT PFNWGLGETCURRENTREADDCEXTPROC __wglewGetCurrentReadDCEXT; +WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTEXTPROC __wglewMakeContextCurrentEXT; + +WGLEW_EXPORT PFNWGLCREATEPBUFFEREXTPROC __wglewCreatePbufferEXT; +WGLEW_EXPORT PFNWGLDESTROYPBUFFEREXTPROC __wglewDestroyPbufferEXT; +WGLEW_EXPORT PFNWGLGETPBUFFERDCEXTPROC __wglewGetPbufferDCEXT; +WGLEW_EXPORT PFNWGLQUERYPBUFFEREXTPROC __wglewQueryPbufferEXT; +WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCEXTPROC __wglewReleasePbufferDCEXT; + +WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATEXTPROC __wglewChoosePixelFormatEXT; +WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVEXTPROC __wglewGetPixelFormatAttribfvEXT; +WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVEXTPROC __wglewGetPixelFormatAttribivEXT; + +WGLEW_EXPORT PFNWGLGETSWAPINTERVALEXTPROC __wglewGetSwapIntervalEXT; +WGLEW_EXPORT PFNWGLSWAPINTERVALEXTPROC __wglewSwapIntervalEXT; + +WGLEW_EXPORT PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC __wglewGetDigitalVideoParametersI3D; +WGLEW_EXPORT PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC __wglewSetDigitalVideoParametersI3D; + +WGLEW_EXPORT PFNWGLGETGAMMATABLEI3DPROC __wglewGetGammaTableI3D; +WGLEW_EXPORT PFNWGLGETGAMMATABLEPARAMETERSI3DPROC __wglewGetGammaTableParametersI3D; +WGLEW_EXPORT PFNWGLSETGAMMATABLEI3DPROC __wglewSetGammaTableI3D; +WGLEW_EXPORT PFNWGLSETGAMMATABLEPARAMETERSI3DPROC __wglewSetGammaTableParametersI3D; + +WGLEW_EXPORT PFNWGLDISABLEGENLOCKI3DPROC __wglewDisableGenlockI3D; +WGLEW_EXPORT PFNWGLENABLEGENLOCKI3DPROC __wglewEnableGenlockI3D; +WGLEW_EXPORT PFNWGLGENLOCKSAMPLERATEI3DPROC __wglewGenlockSampleRateI3D; +WGLEW_EXPORT PFNWGLGENLOCKSOURCEDELAYI3DPROC __wglewGenlockSourceDelayI3D; +WGLEW_EXPORT PFNWGLGENLOCKSOURCEEDGEI3DPROC __wglewGenlockSourceEdgeI3D; +WGLEW_EXPORT PFNWGLGENLOCKSOURCEI3DPROC __wglewGenlockSourceI3D; +WGLEW_EXPORT PFNWGLGETGENLOCKSAMPLERATEI3DPROC __wglewGetGenlockSampleRateI3D; +WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEDELAYI3DPROC __wglewGetGenlockSourceDelayI3D; +WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEEDGEI3DPROC __wglewGetGenlockSourceEdgeI3D; +WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEI3DPROC __wglewGetGenlockSourceI3D; +WGLEW_EXPORT PFNWGLISENABLEDGENLOCKI3DPROC __wglewIsEnabledGenlockI3D; +WGLEW_EXPORT PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC __wglewQueryGenlockMaxSourceDelayI3D; + +WGLEW_EXPORT PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC __wglewAssociateImageBufferEventsI3D; +WGLEW_EXPORT PFNWGLCREATEIMAGEBUFFERI3DPROC __wglewCreateImageBufferI3D; +WGLEW_EXPORT PFNWGLDESTROYIMAGEBUFFERI3DPROC __wglewDestroyImageBufferI3D; +WGLEW_EXPORT PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC __wglewReleaseImageBufferEventsI3D; + +WGLEW_EXPORT PFNWGLDISABLEFRAMELOCKI3DPROC __wglewDisableFrameLockI3D; +WGLEW_EXPORT PFNWGLENABLEFRAMELOCKI3DPROC __wglewEnableFrameLockI3D; +WGLEW_EXPORT PFNWGLISENABLEDFRAMELOCKI3DPROC __wglewIsEnabledFrameLockI3D; +WGLEW_EXPORT PFNWGLQUERYFRAMELOCKMASTERI3DPROC __wglewQueryFrameLockMasterI3D; + +WGLEW_EXPORT PFNWGLBEGINFRAMETRACKINGI3DPROC __wglewBeginFrameTrackingI3D; +WGLEW_EXPORT PFNWGLENDFRAMETRACKINGI3DPROC __wglewEndFrameTrackingI3D; +WGLEW_EXPORT PFNWGLGETFRAMEUSAGEI3DPROC __wglewGetFrameUsageI3D; +WGLEW_EXPORT PFNWGLQUERYFRAMETRACKINGI3DPROC __wglewQueryFrameTrackingI3D; + +WGLEW_EXPORT PFNWGLDXCLOSEDEVICENVPROC __wglewDXCloseDeviceNV; +WGLEW_EXPORT PFNWGLDXLOCKOBJECTSNVPROC __wglewDXLockObjectsNV; +WGLEW_EXPORT PFNWGLDXOBJECTACCESSNVPROC __wglewDXObjectAccessNV; +WGLEW_EXPORT PFNWGLDXOPENDEVICENVPROC __wglewDXOpenDeviceNV; +WGLEW_EXPORT PFNWGLDXREGISTEROBJECTNVPROC __wglewDXRegisterObjectNV; +WGLEW_EXPORT PFNWGLDXSETRESOURCESHAREHANDLENVPROC __wglewDXSetResourceShareHandleNV; +WGLEW_EXPORT PFNWGLDXUNLOCKOBJECTSNVPROC __wglewDXUnlockObjectsNV; +WGLEW_EXPORT PFNWGLDXUNREGISTEROBJECTNVPROC __wglewDXUnregisterObjectNV; + +WGLEW_EXPORT PFNWGLCOPYIMAGESUBDATANVPROC __wglewCopyImageSubDataNV; + +WGLEW_EXPORT PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV; +WGLEW_EXPORT PFNWGLDELETEDCNVPROC __wglewDeleteDCNV; +WGLEW_EXPORT PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV; +WGLEW_EXPORT PFNWGLENUMGPUSFROMAFFINITYDCNVPROC __wglewEnumGpusFromAffinityDCNV; +WGLEW_EXPORT PFNWGLENUMGPUSNVPROC __wglewEnumGpusNV; + +WGLEW_EXPORT PFNWGLBINDVIDEODEVICENVPROC __wglewBindVideoDeviceNV; +WGLEW_EXPORT PFNWGLENUMERATEVIDEODEVICESNVPROC __wglewEnumerateVideoDevicesNV; +WGLEW_EXPORT PFNWGLQUERYCURRENTCONTEXTNVPROC __wglewQueryCurrentContextNV; + +WGLEW_EXPORT PFNWGLBINDSWAPBARRIERNVPROC __wglewBindSwapBarrierNV; +WGLEW_EXPORT PFNWGLJOINSWAPGROUPNVPROC __wglewJoinSwapGroupNV; +WGLEW_EXPORT PFNWGLQUERYFRAMECOUNTNVPROC __wglewQueryFrameCountNV; +WGLEW_EXPORT PFNWGLQUERYMAXSWAPGROUPSNVPROC __wglewQueryMaxSwapGroupsNV; +WGLEW_EXPORT PFNWGLQUERYSWAPGROUPNVPROC __wglewQuerySwapGroupNV; +WGLEW_EXPORT PFNWGLRESETFRAMECOUNTNVPROC __wglewResetFrameCountNV; + +WGLEW_EXPORT PFNWGLALLOCATEMEMORYNVPROC __wglewAllocateMemoryNV; +WGLEW_EXPORT PFNWGLFREEMEMORYNVPROC __wglewFreeMemoryNV; + +WGLEW_EXPORT PFNWGLBINDVIDEOCAPTUREDEVICENVPROC __wglewBindVideoCaptureDeviceNV; +WGLEW_EXPORT PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC __wglewEnumerateVideoCaptureDevicesNV; +WGLEW_EXPORT PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC __wglewLockVideoCaptureDeviceNV; +WGLEW_EXPORT PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC __wglewQueryVideoCaptureDeviceNV; +WGLEW_EXPORT PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC __wglewReleaseVideoCaptureDeviceNV; + +WGLEW_EXPORT PFNWGLBINDVIDEOIMAGENVPROC __wglewBindVideoImageNV; +WGLEW_EXPORT PFNWGLGETVIDEODEVICENVPROC __wglewGetVideoDeviceNV; +WGLEW_EXPORT PFNWGLGETVIDEOINFONVPROC __wglewGetVideoInfoNV; +WGLEW_EXPORT PFNWGLRELEASEVIDEODEVICENVPROC __wglewReleaseVideoDeviceNV; +WGLEW_EXPORT PFNWGLRELEASEVIDEOIMAGENVPROC __wglewReleaseVideoImageNV; +WGLEW_EXPORT PFNWGLSENDPBUFFERTOVIDEONVPROC __wglewSendPbufferToVideoNV; + +WGLEW_EXPORT PFNWGLGETMSCRATEOMLPROC __wglewGetMscRateOML; +WGLEW_EXPORT PFNWGLGETSYNCVALUESOMLPROC __wglewGetSyncValuesOML; +WGLEW_EXPORT PFNWGLSWAPBUFFERSMSCOMLPROC __wglewSwapBuffersMscOML; +WGLEW_EXPORT PFNWGLSWAPLAYERBUFFERSMSCOMLPROC __wglewSwapLayerBuffersMscOML; +WGLEW_EXPORT PFNWGLWAITFORMSCOMLPROC __wglewWaitForMscOML; +WGLEW_EXPORT PFNWGLWAITFORSBCOMLPROC __wglewWaitForSbcOML; +WGLEW_EXPORT GLboolean __WGLEW_3DFX_multisample; +WGLEW_EXPORT GLboolean __WGLEW_3DL_stereo_control; +WGLEW_EXPORT GLboolean __WGLEW_AMD_gpu_association; +WGLEW_EXPORT GLboolean __WGLEW_ARB_buffer_region; +WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context; +WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context_profile; +WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context_robustness; +WGLEW_EXPORT GLboolean __WGLEW_ARB_extensions_string; +WGLEW_EXPORT GLboolean __WGLEW_ARB_framebuffer_sRGB; +WGLEW_EXPORT GLboolean __WGLEW_ARB_make_current_read; +WGLEW_EXPORT GLboolean __WGLEW_ARB_multisample; +WGLEW_EXPORT GLboolean __WGLEW_ARB_pbuffer; +WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format; +WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format_float; +WGLEW_EXPORT GLboolean __WGLEW_ARB_render_texture; +WGLEW_EXPORT GLboolean __WGLEW_ATI_pixel_format_float; +WGLEW_EXPORT GLboolean __WGLEW_ATI_render_texture_rectangle; +WGLEW_EXPORT GLboolean __WGLEW_EXT_create_context_es2_profile; +WGLEW_EXPORT GLboolean __WGLEW_EXT_depth_float; +WGLEW_EXPORT GLboolean __WGLEW_EXT_display_color_table; +WGLEW_EXPORT GLboolean __WGLEW_EXT_extensions_string; +WGLEW_EXPORT GLboolean __WGLEW_EXT_framebuffer_sRGB; +WGLEW_EXPORT GLboolean __WGLEW_EXT_make_current_read; +WGLEW_EXPORT GLboolean __WGLEW_EXT_multisample; +WGLEW_EXPORT GLboolean __WGLEW_EXT_pbuffer; +WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format; +WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format_packed_float; +WGLEW_EXPORT GLboolean __WGLEW_EXT_swap_control; +WGLEW_EXPORT GLboolean __WGLEW_I3D_digital_video_control; +WGLEW_EXPORT GLboolean __WGLEW_I3D_gamma; +WGLEW_EXPORT GLboolean __WGLEW_I3D_genlock; +WGLEW_EXPORT GLboolean __WGLEW_I3D_image_buffer; +WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_lock; +WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_usage; +WGLEW_EXPORT GLboolean __WGLEW_NV_DX_interop; +WGLEW_EXPORT GLboolean __WGLEW_NV_copy_image; +WGLEW_EXPORT GLboolean __WGLEW_NV_float_buffer; +WGLEW_EXPORT GLboolean __WGLEW_NV_gpu_affinity; +WGLEW_EXPORT GLboolean __WGLEW_NV_multisample_coverage; +WGLEW_EXPORT GLboolean __WGLEW_NV_present_video; +WGLEW_EXPORT GLboolean __WGLEW_NV_render_depth_texture; +WGLEW_EXPORT GLboolean __WGLEW_NV_render_texture_rectangle; +WGLEW_EXPORT GLboolean __WGLEW_NV_swap_group; +WGLEW_EXPORT GLboolean __WGLEW_NV_vertex_array_range; +WGLEW_EXPORT GLboolean __WGLEW_NV_video_capture; +WGLEW_EXPORT GLboolean __WGLEW_NV_video_output; +WGLEW_EXPORT GLboolean __WGLEW_OML_sync_control; + +#ifdef GLEW_MX +}; /* WGLEWContextStruct */ +#endif /* GLEW_MX */ + +/* ------------------------------------------------------------------------- */ + +#ifdef GLEW_MX + +typedef struct WGLEWContextStruct WGLEWContext; +GLEWAPI GLenum wglewContextInit (WGLEWContext* ctx); +GLEWAPI GLboolean wglewContextIsSupported (const WGLEWContext* ctx, const char* name); + +#define wglewInit() wglewContextInit(wglewGetContext()) +#define wglewIsSupported(x) wglewContextIsSupported(wglewGetContext(), x) + +#define WGLEW_GET_VAR(x) (*(const GLboolean*)&(wglewGetContext()->x)) +#define WGLEW_GET_FUN(x) wglewGetContext()->x + +#else /* GLEW_MX */ + +#define WGLEW_GET_VAR(x) (*(const GLboolean*)&x) +#define WGLEW_GET_FUN(x) x + +GLEWAPI GLboolean wglewIsSupported (const char* name); + +#endif /* GLEW_MX */ + +GLEWAPI GLboolean wglewGetExtension (const char* name); + +#ifdef __cplusplus +} +#endif + +#undef GLEWAPI + +#endif /* __wglew_h__ */ diff --git a/Glut/GL/wglext.h b/Glut/GL/wglext.h new file mode 100644 index 0000000..8c6192c --- /dev/null +++ b/Glut/GL/wglext.h @@ -0,0 +1,466 @@ +#ifndef __wglext_h_ +#define __wglext_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +*/ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) +#define WIN32_LEAN_AND_MEAN 1 +#include +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif + +/*************************************************************/ + +/* Header file version number */ +#define WGL_WGLEXT_VERSION 1 + +#ifndef WGL_ARB_buffer_region +#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 +#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 +#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 +#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 +#endif + +#ifndef WGL_ARB_extensions_string +#endif + +#ifndef WGL_ARB_pixel_format +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +#endif + +#ifndef WGL_ARB_make_current_read +#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 +#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 +#endif + +#ifndef WGL_ARB_pbuffer +#define WGL_DRAW_TO_PBUFFER_ARB 0x202D +#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E +#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 +#define WGL_PBUFFER_LARGEST_ARB 0x2033 +#define WGL_PBUFFER_WIDTH_ARB 0x2034 +#define WGL_PBUFFER_HEIGHT_ARB 0x2035 +#define WGL_PBUFFER_LOST_ARB 0x2036 +#endif + +#ifndef WGL_ARB_render_texture +#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 +#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 +#define WGL_TEXTURE_FORMAT_ARB 0x2072 +#define WGL_TEXTURE_TARGET_ARB 0x2073 +#define WGL_MIPMAP_TEXTURE_ARB 0x2074 +#define WGL_TEXTURE_RGB_ARB 0x2075 +#define WGL_TEXTURE_RGBA_ARB 0x2076 +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 +#define WGL_TEXTURE_1D_ARB 0x2079 +#define WGL_TEXTURE_2D_ARB 0x207A +#define WGL_MIPMAP_LEVEL_ARB 0x207B +#define WGL_CUBE_MAP_FACE_ARB 0x207C +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 +#define WGL_FRONT_LEFT_ARB 0x2083 +#define WGL_FRONT_RIGHT_ARB 0x2084 +#define WGL_BACK_LEFT_ARB 0x2085 +#define WGL_BACK_RIGHT_ARB 0x2086 +#define WGL_AUX0_ARB 0x2087 +#define WGL_AUX1_ARB 0x2088 +#define WGL_AUX2_ARB 0x2089 +#define WGL_AUX3_ARB 0x208A +#define WGL_AUX4_ARB 0x208B +#define WGL_AUX5_ARB 0x208C +#define WGL_AUX6_ARB 0x208D +#define WGL_AUX7_ARB 0x208E +#define WGL_AUX8_ARB 0x208F +#define WGL_AUX9_ARB 0x2090 +#endif + +#ifndef WGL_EXT_make_current_read +#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 +#endif + +#ifndef WGL_EXT_pixel_format +#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 +#define WGL_DRAW_TO_WINDOW_EXT 0x2001 +#define WGL_DRAW_TO_BITMAP_EXT 0x2002 +#define WGL_ACCELERATION_EXT 0x2003 +#define WGL_NEED_PALETTE_EXT 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 +#define WGL_SWAP_METHOD_EXT 0x2007 +#define WGL_NUMBER_OVERLAYS_EXT 0x2008 +#define WGL_NUMBER_UNDERLAYS_EXT 0x2009 +#define WGL_TRANSPARENT_EXT 0x200A +#define WGL_TRANSPARENT_VALUE_EXT 0x200B +#define WGL_SHARE_DEPTH_EXT 0x200C +#define WGL_SHARE_STENCIL_EXT 0x200D +#define WGL_SHARE_ACCUM_EXT 0x200E +#define WGL_SUPPORT_GDI_EXT 0x200F +#define WGL_SUPPORT_OPENGL_EXT 0x2010 +#define WGL_DOUBLE_BUFFER_EXT 0x2011 +#define WGL_STEREO_EXT 0x2012 +#define WGL_PIXEL_TYPE_EXT 0x2013 +#define WGL_COLOR_BITS_EXT 0x2014 +#define WGL_RED_BITS_EXT 0x2015 +#define WGL_RED_SHIFT_EXT 0x2016 +#define WGL_GREEN_BITS_EXT 0x2017 +#define WGL_GREEN_SHIFT_EXT 0x2018 +#define WGL_BLUE_BITS_EXT 0x2019 +#define WGL_BLUE_SHIFT_EXT 0x201A +#define WGL_ALPHA_BITS_EXT 0x201B +#define WGL_ALPHA_SHIFT_EXT 0x201C +#define WGL_ACCUM_BITS_EXT 0x201D +#define WGL_ACCUM_RED_BITS_EXT 0x201E +#define WGL_ACCUM_GREEN_BITS_EXT 0x201F +#define WGL_ACCUM_BLUE_BITS_EXT 0x2020 +#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 +#define WGL_DEPTH_BITS_EXT 0x2022 +#define WGL_STENCIL_BITS_EXT 0x2023 +#define WGL_AUX_BUFFERS_EXT 0x2024 +#define WGL_NO_ACCELERATION_EXT 0x2025 +#define WGL_GENERIC_ACCELERATION_EXT 0x2026 +#define WGL_FULL_ACCELERATION_EXT 0x2027 +#define WGL_SWAP_EXCHANGE_EXT 0x2028 +#define WGL_SWAP_COPY_EXT 0x2029 +#define WGL_SWAP_UNDEFINED_EXT 0x202A +#define WGL_TYPE_RGBA_EXT 0x202B +#define WGL_TYPE_COLORINDEX_EXT 0x202C +#endif + +#ifndef WGL_EXT_pbuffer +#define WGL_DRAW_TO_PBUFFER_EXT 0x202D +#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E +#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 +#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 +#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 +#define WGL_PBUFFER_LARGEST_EXT 0x2033 +#define WGL_PBUFFER_WIDTH_EXT 0x2034 +#define WGL_PBUFFER_HEIGHT_EXT 0x2035 +#endif + +#ifndef WGL_EXT_depth_float +#define WGL_DEPTH_FLOAT_EXT 0x2040 +#endif + +#ifndef WGL_NV_render_texture_rectangle +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 +#define WGL_TEXTURE_RECTANGLE_NV 0x20A2 +#endif + +#ifndef WGL_NV_render_depth_texture +#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 +#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 +#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 +#define WGL_DEPTH_COMPONENT_NV 0x20A7 +#endif + +#ifndef WGL_3DFX_multisample +#define WGL_SAMPLE_BUFFERS_3DFX 0x2060 +#define WGL_SAMPLES_3DFX 0x2061 +#endif + +#ifndef WGL_EXT_multisample +#define WGL_SAMPLE_BUFFERS_EXT 0x2041 +#define WGL_SAMPLES_EXT 0x2042 +#endif + +#ifndef WGL_I3D_unknown_genlock_extension_name +#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 +#define WGL_GENLOCK_SOURCE_EXTENAL_SYNC_I3D 0x2045 +#define WGL_GENLOCK_SOURCE_EXTENAL_FIELD_I3D 0x2046 +#define WGL_GENLOCK_SOURCE_EXTENAL_TTL_I3D 0x2047 +#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 +#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 +#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A +#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B +#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C +#endif + +#ifndef WGL_I3D_unknown_gamma_extension_name +#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E +#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F +#endif + +#ifndef WGL_I3D_unknown_digital_video_cursor_extension_name +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 +#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 +#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 +#endif + + +/*************************************************************/ + +#ifndef WGL_ARB_pbuffer +DECLARE_HANDLE(HPBUFFERARB); +#endif +#ifndef WGL_EXT_pbuffer +DECLARE_HANDLE(HPBUFFEREXT); +#endif + +#ifndef WGL_ARB_buffer_region +#define WGL_ARB_buffer_region 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HANDLE WINAPI wglCreateBufferRegionARB (HDC, int, UINT); +extern VOID WINAPI wglDeleteBufferRegionARB (HANDLE); +extern BOOL WINAPI wglSaveBufferRegionARB (HANDLE, int, int, int, int); +extern BOOL WINAPI wglRestoreBufferRegionARB (HANDLE, int, int, int, int, int, int); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); +typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); +typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); +typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); +#endif + +#ifndef WGL_ARB_extensions_string +#define WGL_ARB_extensions_string 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern const char * WINAPI wglGetExtensionsStringARB (HDC); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); +#endif + +#ifndef WGL_ARB_pixel_format +#define WGL_ARB_pixel_format 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetPixelFormatAttribivARB (HDC, int, int, UINT, const int *, int *); +extern BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC, int, int, UINT, const int *, FLOAT *); +extern BOOL WINAPI wglChoosePixelFormatARB (HDC, const int *, const FLOAT *, UINT, int *, UINT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +#endif + +#ifndef WGL_ARB_make_current_read +#define WGL_ARB_make_current_read 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglMakeContextCurrentARB (HDC, HDC, HGLRC); +extern HDC WINAPI wglGetCurrentReadDCARB (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void); +#endif + +#ifndef WGL_ARB_pbuffer +#define WGL_ARB_pbuffer 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HPBUFFERARB WINAPI wglCreatePbufferARB (HDC, int, int, int, const int *); +extern HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB); +extern int WINAPI wglReleasePbufferDCARB (HPBUFFERARB, HDC); +extern BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB); +extern BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB, int, int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); +#endif + +#ifndef WGL_EXT_display_color_table +#define WGL_EXT_display_color_table 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort); +extern GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *, GLuint); +extern GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort); +extern VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort *table, GLuint length); +typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef VOID (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); +#endif + +#ifndef WGL_EXT_extensions_string +#define WGL_EXT_extensions_string 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern const char * WINAPI wglGetExtensionsStringEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); +#endif + +#ifndef WGL_EXT_make_current_read +#define WGL_EXT_make_current_read 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglMakeContextCurrentEXT (HDC, HDC, HGLRC); +extern HDC WINAPI wglGetCurrentReadDCEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (void); +#endif + +#ifndef WGL_EXT_pbuffer +#define WGL_EXT_pbuffer 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC, int, int, int, const int *); +extern HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT); +extern int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT, HDC); +extern BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT); +extern BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT, int, int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); +#endif + +#ifndef WGL_EXT_pixel_format +#define WGL_EXT_pixel_format 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC, int, int, UINT, int *, int *); +extern BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC, int, int, UINT, int *, FLOAT *); +extern BOOL WINAPI wglChoosePixelFormatEXT (HDC, const int *, const FLOAT *, UINT, int *, UINT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +#endif + +#ifndef WGL_EXT_swap_control +#define WGL_EXT_swap_control 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglSwapIntervalEXT (int); +extern int WINAPI wglGetSwapIntervalEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); +typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); +#endif + +#ifndef WGL_WGL_EXT_depth_float +#define WGL_WGL_EXT_depth_float 1 +#endif + +#ifndef WGL_WGL_3DFX_multisample +#define WGL_WGL_3DFX_multisample 1 +#endif + +#ifndef WGL_WGL_EXT_multisample +#define WGL_WGL_EXT_multisample 1 +#endif + +/* added by Cass -- but this should already be in here! */ +#ifndef WGL_NV_allocate_memory +#define WGL_NV_allocate_memory 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern void * wglAllocateMemoryNV(int size, float readfreq, float writefreq, float priority); +extern void wglFreeMemoryNV(void * pointer); +#endif +typedef void * (APIENTRY * PFNWGLALLOCATEMEMORYNVPROC) (int size, float readfreq, float writefreq, float priority); +typedef void (APIENTRY * PFNWGLFREEMEMORYNVPROC) (void *pointer); +#endif + +/* WGL_ARB_render_texture */ +#ifndef WGL_ARB_render_texture +#define WGL_ARB_render_texture 1 +typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int * piAttribList); +#endif + +#ifndef WGL_NV_render_texture_rectangle +#define WGL_NV_render_texture_rectangle 1 +#endif + +#ifndef WGL_NV_render_depth_texture +#define WGL_NV_render_depth_texture 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/Glut/btGlutInclude.h b/Glut/btGlutInclude.h new file mode 100644 index 0000000..d79cb56 --- /dev/null +++ b/Glut/btGlutInclude.h @@ -0,0 +1,43 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_GLUT_INCLUDE_H +#define BT_GLUT_INCLUDE_H + + +#ifdef _WIN32//for glut.h +#include +#endif + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#include +#else + + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif //_WINDOWS +#endif //APPLE + +#endif //BT_GLUT_INCLUDE_H diff --git a/Glut/glew32s.lib b/Glut/glew32s.lib new file mode 100644 index 0000000000000000000000000000000000000000..eb2d718e0f45203b49244f4df3f446334cf0f89c GIT binary patch literal 1288450 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 !?fvm4KiCjbNnN(`zHX;ES##71Y~~GnA){ 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 literal 0 HcmV?d00001 diff --git a/Glut/glew64s.lib b/Glut/glew64s.lib new file mode 100644 index 0000000000000000000000000000000000000000..e9b15a6823bcf68d247d1b0347ec8375a9511db9 GIT binary patch literal 1378464 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νQ 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 literal 0 HcmV?d00001 diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..0f42fb5 --- /dev/null +++ b/INSTALL @@ -0,0 +1,111 @@ +Bullet Collision Detection and Physics Library + +See also http://bulletphysics.org/mediawiki-1.5.8/index.php/Creating_a_project_from_scratch + +** Windows Compilation ** + + Open the Microsoft Visual Studio solution in msvc/20xx/BULLET_PHYSICS.sln + +Alternatively, use CMake to autogenerate a build system for Windows: + + - Download/install CMake from www.cmake.org or package manager + - Use cmake-gui or + - List available build systems by running 'cmake' in the Bullet root folder + - Use cmake-gui + - Create a build system using the -G option for example: + + cmake . -G "Visual Studio 9 2008" or + cmake . -G "Visual Studio 9 2008 Win64" + + +** Linux Compilation ** + + - Download/install CMake from www.cmake.org or package manager + CMake is like autoconf in that it will create build scripts which are then + used for the actual compilation + + - List available build systems by running 'cmake' in the Bullet root folder + - Create a build system using the -G option for example: + + cmake . -G "Unix Makefiles" + + - There are some options for cmake builds: + BUILD_SHARED_LIBS: default 'OFF', set to 'ON' to build .so libraries + BUILD_EXTRAS: default 'ON', compiles additional libraries in 'Extras' + BUILD_DEMOS: default 'ON', compiles applications found in 'Demos' + CMAKE_INSTALL_PREFIX: default '/usr/local', the installation path. + CMAKE_INSTALL_RPATH: if you install outside a standard ld search path, + then you should set this to the installation lib path. + CMAKE_BUILD_TYPE: default 'Release', can include debug symbols with + either 'Debug' or 'RelWithDebInfo'. + Other options may be discovered by 'cmake --help-variable-list' and + 'cmake --help-variable OPTION' + + - Run 'cmake' with desired options of the form -DOPTION=VALUE + By default this will create the usual Makefile build system, but CMake can + also produce Eclipse or KDevelop project files. See 'cmake --help' to see + what "generators" are available in your environment, selected via '-G'. + For example: + cmake -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=RelWithDebugInfo + + - Assuming using the default Makefile output from cmake, run 'make' to + build, and then 'make install' if you wish to install. + + +** Mac OS X Compilation ** + + - Download/install CMake from www.cmake.org or package manager + CMake is like autoconf in that it will create build scripts which are then + used for the actual compilation + + - List available build systems by running 'cmake' in the Bullet root folder + - Create a build system using the -G option for example: + + cmake . -G Xcode + cmake . -G "Unix Makefiles" + + - There are some options for cmake builds: + BUILD_SHARED_LIBS: default 'OFF', set to 'ON' to build .dylib libraries + BUILD_EXTRAS: default 'ON', compiles additional libraries in 'Extras' + BUILD_DEMOS: default 'ON', compiles applications found in 'Demos' + CMAKE_INSTALL_PREFIX: default '/usr/local', the installation path. + CMAKE_INSTALL_NAME_DIR: if you install outside a standard ld search + path, then you should set this to the installation lib/framework path. + CMAKE_OSX_ARCHITECTURES: defaults to the native architecture, but can be + set to a semicolon separated list for fat binaries, e.g. ppc;i386;x86_64 + CMAKE_BUILD_TYPE: default 'Release', can include debug symbols with + either 'Debug' or 'RelWithDebInfo'. + + To build framework bundles: + FRAMEWORK: default 'OFF', also requires 'BUILD_SHARED_LIBS' set ON + If both FRAMEWORK and BUILD_SHARED_LIBS are set, will create + OS X style Framework Bundles which can be placed in + linked via the -framework gcc argument or drag into Xcode projects. + (If not framework, then UNIX style 'include' and 'lib' will be produced) + + Other options may be discovered by 'cmake --help-variable-list' and + 'cmake --help-variable OPTION' + + - Run 'cmake' with desired options of the form -DOPTION=VALUE + By default this will create the usual Makefile build system, but CMake can + also produce Eclipse or KDevelop project files. See 'cmake --help' to see + what "generators" are available in your environment, selected via '-G'. + For example: + cmake -DBUILD_SHARED_LIBS=ON -DFRAMEWORK=ON \ + -DCMAKE_INSTALL_PREFIX=/Library/Frameworks \ + -DCMAKE_INSTALL_NAME_DIR=/Library/Frameworks \ + -DCMAKE_OSX_ARCHITECTURES='ppc;i386;x86_64' \ + -DCMAKE_BUILD_TYPE=RelWithDebugInfo + + - Assuming using the default Makefile output from cmake, run 'make' to build + and then 'make install'. + + +** Alternative Mac OS X and Linux via autoconf/make ** + - at the command line: + ./autogen.sh + ./configure + make + + +** For more help, visit http://www.bulletphysics.org ** diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..a9b97a8 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,7 @@ +if CONDITIONAL_BUILD_DEMOS +SUBDIRS=src Extras Demos +else +SUBDIRS=src +endif +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = bullet.pc diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..dec9f0f --- /dev/null +++ b/NEWS @@ -0,0 +1,5 @@ + +For news, visit the Bullet Physics forums at +http://www.bulletphysics.org and http://bullet.googlecode.com + + diff --git a/README b/README new file mode 100644 index 0000000..1eda762 --- /dev/null +++ b/README @@ -0,0 +1,6 @@ + +Bullet is a 3D Collision Detection and Rigid Body Dynamics Library for games and animation. +Free for commercial use, including Playstation 3, open source under the ZLib License. + +See the Bullet_User_Manual.pdf for more info and visit the Bullet Physics Forum at +http://bulletphysics.org diff --git a/RELEASING.TXT b/RELEASING.TXT new file mode 100644 index 0000000..8fba4a5 --- /dev/null +++ b/RELEASING.TXT @@ -0,0 +1,34 @@ +This document details the steps necessary to package a release of Bullet. + +1) Preparing for release: + +update VERSION in several places +update ChangeLog +regenerate MSVC project files + +2) Generating the release .zip: +Do an SVN export on a Windows machine into the directory: bullet-X.YY +prepare a zip file containing the directory + +3) Generating the release .tar.gz: +Do an SVN export on a Unix machine into the directory: bullet-X.YY +prepare a .tar.gz file containing the directory + +4) Uploading release to google code: + +Google Code Bullet downloads URL: http://code.google.com/p/bullet/downloads/list + +Title of release should follow this guide line: Bullet Physics SDK (revision) + +It is better to upload the .tar.gz before the .zip so that the .zip appears first in the list + +If the release is an Alpha/Beta or RC the tags should be: Type-Source, OpSys-ALL +If the release is a final release the tags should be: Type-Source, OpSys-ALL, Featured + +5) Obsoleting old releases + +Edit the tags on old releases and add the 'Deprecated' tag + +6) Announcing final releases: + +Final release announcements are done here: http://bulletphysics.com/Bullet/phpBB3/viewforum.php?f=18 diff --git a/UnitTests/BulletUnitTests/CMakeLists.txt b/UnitTests/BulletUnitTests/CMakeLists.txt new file mode 100644 index 0000000..560a642 --- /dev/null +++ b/UnitTests/BulletUnitTests/CMakeLists.txt @@ -0,0 +1,18 @@ + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${BULLET_PHYSICS_SOURCE_DIR}/UnitTests/cppunit/include + + + ${VECTOR_MATH_INCLUDE} +) + +LINK_LIBRARIES( + cppunit BulletMultiThreaded BulletDynamics BulletCollision LinearMath +) + +ADD_EXECUTABLE(AppBulletUnitTests + Main.cpp + TestBulletOnly.h + TestLinearMath.h +) \ No newline at end of file diff --git a/UnitTests/BulletUnitTests/Main.cpp b/UnitTests/BulletUnitTests/Main.cpp new file mode 100644 index 0000000..4a3fad3 --- /dev/null +++ b/UnitTests/BulletUnitTests/Main.cpp @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include + +#include "TestBulletOnly.h" +#include "TestLinearMath.h" + +CPPUNIT_TEST_SUITE_REGISTRATION( TestLinearMath ); +CPPUNIT_TEST_SUITE_REGISTRATION( TestBulletOnly ); + + +int main(int argc, char* argv[]) +{ + // Create the event manager and test controller + CPPUNIT_NS::TestResult controller; + + // Add a listener that colllects test result + CPPUNIT_NS::TestResultCollector result; + controller.addListener( &result ); + + // Add a listener that print dots as test run. + CPPUNIT_NS::BriefTestProgressListener progress; + controller.addListener( &progress ); + + // Add the top suite to the test runner + CPPUNIT_NS::TestRunner runner; + runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() ); + runner.run( controller ); + + // Print test in a compiler compatible format. + CPPUNIT_NS::CompilerOutputter outputter( &result, CPPUNIT_NS::stdCOut() ); + outputter.write(); + + getchar(); + + return result.wasSuccessful() ? 0 : 1; +} + diff --git a/UnitTests/BulletUnitTests/TestBulletOnly.h b/UnitTests/BulletUnitTests/TestBulletOnly.h new file mode 100644 index 0000000..bdac6f8 --- /dev/null +++ b/UnitTests/BulletUnitTests/TestBulletOnly.h @@ -0,0 +1,119 @@ +#ifndef TESTBULLETONLY_HAS_BEEN_INCLUDED +#define TESTBULLETONLY_HAS_BEEN_INCLUDED + +#include "cppunit/TestFixture.h" +#include "cppunit/extensions/HelperMacros.h" + +#include "btBulletDynamicsCommon.h" +#include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h" + +// --------------------------------------------------------------------------- + +class TestBulletOnly : public CppUnit::TestFixture +{ + btCollisionConfiguration * mCollisionConfig; + btCollisionDispatcher * mCollisionDispatch; + btBroadphaseInterface * mBroadphase; + btConstraintSolver * mConstraintSolver; + btDiscreteDynamicsWorld * mWorld; + btCollisionShape* mBodyShape; + btRigidBody* mRigidBody; + btDefaultMotionState* mMotionState; + +public: + + void setUp() + { + // Setup the world -- + mCollisionConfig = new btDefaultCollisionConfiguration; + mCollisionDispatch = new btCollisionDispatcher( mCollisionConfig ); + mBroadphase = new btDbvtBroadphase(); + mConstraintSolver = new btSequentialImpulseConstraintSolver(); + mWorld = new btDiscreteDynamicsWorld( mCollisionDispatch, mBroadphase, mConstraintSolver, mCollisionConfig ); + mWorld->setGravity( btVector3( 0, -9.81, 0 )); + + // Set up the rigid body -- + mBodyShape = new btBoxShape( btVector3( 1, 1, 1 ) ); + btScalar mass = 1; + btVector3 localInertia(0,0,0); + mBodyShape->calculateLocalInertia(mass,localInertia); + btTransform bodyInitial; + + mMotionState = new btDefaultMotionState(); + + bodyInitial.setIdentity(); + bodyInitial.setOrigin( btVector3( 0, 0, 0 ) ); + mRigidBody = new btRigidBody( buildConstructionInfo(mass, 0.5, 0.5, 0, 0, *mMotionState, mBodyShape ) ); + + mWorld->addRigidBody( mRigidBody ); + } + + void tearDown() + { + mWorld->removeRigidBody(mRigidBody); + delete mRigidBody; + delete mMotionState; + delete mBodyShape; + delete mWorld; + delete mConstraintSolver; + delete mBroadphase; + delete mCollisionDispatch; + delete mCollisionConfig; + + } + + btRigidBody::btRigidBodyConstructionInfo buildConstructionInfo( btScalar mass, btScalar friction, btScalar restitution, btScalar linearDamping, + btScalar angularDamping, btDefaultMotionState & state, btCollisionShape * shape ) + { + btVector3 inertia(0,0,0); + if (mass>0) + shape->calculateLocalInertia( mass, inertia ); + + btRigidBody::btRigidBodyConstructionInfo info( mass, &state, shape, inertia ); + + info.m_friction = friction; + info.m_restitution = restitution; + info.m_linearDamping = linearDamping; + info.m_angularDamping = angularDamping; + + return info; + } + + void testKinematicVelocity0() + { + mRigidBody->setMassProps( 1, btVector3( 1, 1, 1 ) ); + mRigidBody->updateInertiaTensor(); + mRigidBody->setCollisionFlags( btCollisionObject::CF_KINEMATIC_OBJECT ); + // -- . + + // Interpolate the velocity -- + + //btVector3 velocity( 1., 2., 3. ), spin( 0.1, 0.2, 0.3 ); + btVector3 velocity( 1., 2., 3. ), spin( 0.1, 0.2, .3 ); + btTransform interpolated; + + // TODO: This is inaccurate for small spins. + btTransformUtil::integrateTransform( mRigidBody->getCenterOfMassTransform(), velocity, spin, 1.0f/60.f, interpolated ); + + mRigidBody->setInterpolationWorldTransform( interpolated ); + + mWorld->stepSimulation( 1.f/60.f, 60, 1.0f/60.f ); + + CPPUNIT_ASSERT_DOUBLES_EQUAL( mRigidBody->getLinearVelocity().length2(), velocity.length2(), 1e-8 ); +#ifdef BT_USE_DOUBLE_PRECISION + CPPUNIT_ASSERT_DOUBLES_EQUAL( mRigidBody->getAngularVelocity().length2(), spin.length2(), 1e-4 ); +#else + CPPUNIT_ASSERT_DOUBLES_EQUAL( mRigidBody->getAngularVelocity().length2(), spin.length2(), 5e-3 ); +#endif //CPPUNIT_ASSERT_DOUBLES_EQUAL + + } + + CPPUNIT_TEST_SUITE(TestBulletOnly); + CPPUNIT_TEST(testKinematicVelocity0); + CPPUNIT_TEST_SUITE_END(); + +private: + +}; + +#endif diff --git a/UnitTests/BulletUnitTests/TestLinearMath.h b/UnitTests/BulletUnitTests/TestLinearMath.h new file mode 100644 index 0000000..cf88fff --- /dev/null +++ b/UnitTests/BulletUnitTests/TestLinearMath.h @@ -0,0 +1,206 @@ +#ifndef TEST_LINEAR_MATH_HAS_BEEN_INCLUDED +#define TEST_LINEAR_MATH_HAS_BEEN_INCLUDED + +#include "cppunit/TestFixture.h" +#include "cppunit/extensions/HelperMacros.h" + +#include "LinearMath/btScalar.h" + +#define TEST_NUM_UNITSPHERE_POINTS 42 + +static btVector3 sPenetrationDirections[TEST_NUM_UNITSPHERE_POINTS] = + { + btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)), + btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)), + btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)), + btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)), + btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)), + btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)), + btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)), + btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)), + btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)), + btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)), + btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)), + btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)), + btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)), + btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)), + btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)), + btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)), + btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)), + btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)), + btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)), + btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)), + btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)), + btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)), + btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)), + btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)), + btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)), + btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)), + btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)), + btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)), + btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)), + btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)), + btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)), + btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)), + btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)), + btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)), + btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)), + btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)), + btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)), + btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)), + btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)), + btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)), + btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)), + btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654)) + }; + + + +// --------------------------------------------------------------------------- + +class TestLinearMath : public CppUnit::TestFixture +{ + + + +public: + + void setUp() + { + } + + void tearDown() + { + } + + + void testNormalize() + { + + const btVector3 xaxis(1,0,0); + const btVector3 yaxis(0,1,0); + const btVector3 zaxis(0,0,1); + + const btVector3 negxaxis(-1,0,0); + const btVector3 negyaxis(0,-1,0); + const btVector3 negzaxis(0,0,-1); + + btVector3 vec; + + vec.setValue(1e-20,0,0); + vec.safeNormalize(); + CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0, vec.length2(), 1e-6 ); + + vec.setValue(1e20,0,0); + vec.safeNormalize(); + CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0, vec.length2(), 1e-6 ); + + vec.setValue(1e-20,0,0); + vec.normalize(); + CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0, vec.length2(), 1e-5 ); + + vec.setValue(1e19,0,0); + vec.normalize(); + CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0, vec.length2(), 1e-5 ); + + } + + void testQuicksort() + { + int tests = 0; + int numElems = 100; + btAlignedObjectArray m_unsortedIntegers; + m_unsortedIntegers.resize(numElems); + for (int i=0;i=0) + CPPUNIT_ASSERT_DOUBLES_EQUAL( angle, compAngle, 1e-5 ); + else + { + CPPUNIT_ASSERT_DOUBLES_EQUAL( btFabs(angle), btFabs(compAngle), 1e-5 ); + } + btVector3 compAxis = quat.getAxis(); + + if (compAngle>SIMD_EPSILON) + { + if (i>=0) + { + CPPUNIT_ASSERT_DOUBLES_EQUAL( axis.getX(), compAxis.getX(), 1e-4 ); + CPPUNIT_ASSERT_DOUBLES_EQUAL( axis.getY(), compAxis.getY(), 1e-4 ); + CPPUNIT_ASSERT_DOUBLES_EQUAL( axis.getZ(), compAxis.getZ(), 1e-4 ); + } else + { + btScalar sign = compAngle*angle<0? -1 : 1; + CPPUNIT_ASSERT_DOUBLES_EQUAL( sign*axis.getX(), compAxis.getX(), 1e-4 ); + CPPUNIT_ASSERT_DOUBLES_EQUAL( sign*axis.getY(), compAxis.getY(), 1e-4 ); + CPPUNIT_ASSERT_DOUBLES_EQUAL( sign*axis.getZ(), compAxis.getZ(), 1e-4 ); + } + } else + { + CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.f, compAxis.getX(), 1e-4 ); + CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.f, compAxis.getY(), 1e-4 ); + CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.f, compAxis.getZ(), 1e-4 ); + + } + } + } + } + + + + + CPPUNIT_TEST_SUITE(TestLinearMath); + CPPUNIT_TEST(testQuicksort); + CPPUNIT_TEST(testNormalize); + CPPUNIT_TEST(testQuaternionGetAxisAngle); + + CPPUNIT_TEST_SUITE_END(); + +private: + +}; + +#endif //TEST_LINEAR_MATH_HAS_BEEN_INCLUDED diff --git a/UnitTests/CMakeLists.txt b/UnitTests/CMakeLists.txt new file mode 100644 index 0000000..275633b --- /dev/null +++ b/UnitTests/CMakeLists.txt @@ -0,0 +1,2 @@ + +SUBDIRS( cppunit BulletUnitTests) diff --git a/UnitTests/cppunit/AUTHORS b/UnitTests/cppunit/AUTHORS new file mode 100644 index 0000000..b600073 --- /dev/null +++ b/UnitTests/cppunit/AUTHORS @@ -0,0 +1,6 @@ +Michael Feathers +Jerome Lacoste +E. Sommerlade +Baptiste Lepilleur +Bastiaan Bakker +Steve Robbins diff --git a/UnitTests/cppunit/BUGS b/UnitTests/cppunit/BUGS new file mode 100644 index 0000000..64fb00f --- /dev/null +++ b/UnitTests/cppunit/BUGS @@ -0,0 +1,6 @@ + KNOWN BUGS + ---------- + +The handling of html and man pages in doc/Makefile.am is +flawed. It will not pass "make distcheck". + diff --git a/UnitTests/cppunit/CMakeLists.txt b/UnitTests/cppunit/CMakeLists.txt new file mode 100644 index 0000000..1468214 --- /dev/null +++ b/UnitTests/cppunit/CMakeLists.txt @@ -0,0 +1,74 @@ +INCLUDE_DIRECTORIES( + include +) + +ADD_LIBRARY(cppunit + +#core + src/cppunit/AdditionalMessage.cpp + src/cppunit/Asserter.cpp + src/cppunit/Exception.cpp + src/cppunit/Message.cpp + src/cppunit/SourceLine.cpp + src/cppunit/SynchronizedObject.cpp + src/cppunit/Test.cpp + src/cppunit/TestAssert.cpp + src/cppunit/TestCase.cpp + src/cppunit/TestComposite.cpp + src/cppunit/TestFailure.cpp + src/cppunit/TestLeaf.cpp + src/cppunit/TestPath.cpp + src/cppunit/TestResult.cpp + src/cppunit/TestRunner.cpp + src/cppunit/TestSuite.cpp + +#extension + src/cppunit/RepeatedTest.cpp + src/cppunit/TestCaseDecorator.cpp + src/cppunit/TestDecorator.cpp + src/cppunit/TestSetUp.cpp + +#helper + src/cppunit/TestFactoryRegistry.cpp + src/cppunit/TestNamer.cpp + src/cppunit/TestSuiteBuilderContext.cpp + src/cppunit/TypeInfoHelper.cpp + +#listener + src/cppunit/BriefTestProgressListener.cpp + src/cppunit/TestResultCollector.cpp + src/cppunit/TestSuccessListener.cpp + src/cppunit/TextTestProgressListener.cpp + src/cppunit/TextTestResult.cpp + +#output + src/cppunit/CompilerOutputter.cpp + src/cppunit/TextOutputter.cpp + src/cppunit/XmlOutputter.cpp + src/cppunit/XmlOutputterHook.cpp + +#plugin + src/cppunit/BeOsDynamicLibraryManager.cpp + src/cppunit/DynamicLibraryManager.cpp + src/cppunit/DynamicLibraryManagerException.cpp + src/cppunit/PlugInManager.cpp + src/cppunit/PlugInParameters.cpp + src/cppunit/ShlDynamicLibraryManager.cpp + src/cppunit/TestPlugInDefaultImpl.cpp + src/cppunit/UnixDynamicLibraryManager.cpp + src/cppunit/Win32DynamicLibraryManager.cpp + +#protector + src/cppunit/DefaultProtector.cpp + src/cppunit/Protector.cpp + src/cppunit/ProtectorChain.cpp + +#textui + src/cppunit/TextTestRunner.cpp + +#tools + src/cppunit/StringTools.cpp + src/cppunit/XmlDocument.cpp + src/cppunit/XmlElement.cpp + +) \ No newline at end of file diff --git a/UnitTests/cppunit/ChangeLog b/UnitTests/cppunit/ChangeLog new file mode 100644 index 0000000..210aae3 --- /dev/null +++ b/UnitTests/cppunit/ChangeLog @@ -0,0 +1,3749 @@ +2010-July-23 Erwin Coumans + * add cmake build support, removed other build systems + +2009-11-24 Baptiste Lepilleur + * src/cppunit/TestResult.cpp: flush stdout & stderr in destructor + to avoid message loss in case of crash (bug #2832029). + + * include/cppunit/plugin/TestPlugIn.h: + * include/cppunit/plugin/TestPlugInDefaultImpl.h: added missing dllexport + for CppUnitTestPlugIn. + + * include/cppunit/portability/config-msvc6.h: + * include/cppunit/portability/Portability.h: Added macro + CPPUNIT_UNIQUE_COUNTER on MSVS 7.0+ using __COUNTER__ to + fix bug #2031696. + + * examples/examples2008.sln: Fixed compilation issue in debug + configuration with VS2008 (due to incorrect configuration + being picked up). + + * src/msvc6/testpluginrunner/TestPlugInRunnerDlg.cpp: fixed + memory leak in getCommandLineArguments() (bug #1721408). + + * config/ax_cxx_gcc_abi_demangle.m4: + * src/cppunit/TypeInfoHelper.cpp: Fixed demangling of symbols on gcc 4.3 + (bug #2796543). + +2009-11-23 Baptiste Lepilleur + + * src/DllPlugInTester/Makefile.am: + * examples/cppunittest/Makefile.am: + * examples/money/Makefile.am: + * examples/simple/Makefile.am: + * examples/hierarchy/Makefile.am: Applied patch #2807259 + contributed by Jan Echternach. LIBADD_DL contains a list of libraries + like "-ldl". Thus, it should be in LDADD instead of LDFLAGS in case + one of the libraries depends on a path set in LDFLAGS. + +2008-12-16 Andy Dent + * src/msvc6/testrunner/MsDevCallerListCtrl.cpp: + * INSTALL-VS.Net2008.txt: Added updated project and instructions for + building under Visual Studio.Net 2008 and fixed compilation issue. + +2008-10-12 Baptiste Lepilleur + + * doc/cookbook.dox: fixed typos. + +2008-02-21 Steve M. Robbins + * examples/cppunittest/OrthodoxTest.h: + * examples/cppunittest/XMLOutputterTest.cpp: + * examples/hierarchy/main.cpp: + * include/cppunit/extensions/ExceptionTestCaseDecorator.h: + * src/cppunit/BriefTestProgressListener.cpp: + * src/cppunit/TestFactoryRegistry.cpp: + * src/cppunit/TestPlugInDefaultImpl.cpp: + * src/cppunit/TestSuccessListener.cpp: + * src/cppunit/TextProgressListener.cpp: + * src/cppunit/XmlOutputterHook.cpp: + * src/DllPlugInTester/CommandLineParserTest.cpp: + * src/DllPlugInTester/DllPlugInTesterTest.cpp: Changes to suppress + warnings of gcc -Wall -W -ansi, mainly from patch [1898225]. + +2008-02-20 Steve M. Robbins + + * examples/money/MoneyTest.h (TestFixture): Change deprecated + CPPUNIT_TEST_EXCEPTION to simple CPPUNIT_TEST. + * examples/money/MoneyTest.cpp (testAddThrow): Wrap throwing + expression "money += money123FF" inside CPPUNIT_ASSERT_THROW(). + + * Changes to build without warnings using gcc -Wall -W -ansi. + Applied patch [1898225] to remove name of unused argument and use + no-arg version of main(). Tested on both GCC 4.2.3 and a + prerelease of GCC 4.3.0. + * examples/cppunittest/assertion_traitsTest.cpp (test_toString): + Change template parameter of + CPPUNIT_NS::assertion_traits::toString() to const char*, + avoiding a deprecated conversion from string literal to char*. + * src/DllPlugInTester/CommandLineParserTest.cpp (parse): move + semicolon of empty loop body to its own line, avoiding a warning + in GCC 4.3. + +2008-02-20 Steve M. Robbins + + * configure.in: Update CPPUNIT_MICRO_VERSION for release 1.12.1. + +2008-02-07 Steve M. Robbins + + * src/qttestrunner/MostRecentTests.h: + * src/qttestrunner/TestRunnerModel.h: Change from to + replacment ; avoids use of compatibility headers. + +2007-03-04 Steve M. Robbins + + * include/cppunit/portability/FloatingPoint.h (floatingPointIsFinite): Change + return type to int, following the convention of isfinite(), finite(), etc. + +2007-02-25 Baptiste Lepilleur + + * doc/cookbook.dox: changed suite() to return a TestSuite instead + of a Test to avoid introducing unnecessary complexity. + +2007-02-24 Steve M. Robbins + + * include/cppunit/portability/FloatingPoint.h: Include Portability.h. + +2007-02-24 Baptiste Lepilleur + + * src/cppunit/TestAssert.cpp (assertDoubleEquals): Moved finite & NaN + tests to include/cppunit/portability/FloatingPoint.h. Changed + implementation assertDoubleEquals to explicitly test for NaN + in case of non-finite values to force equality failure in the + presence of NaN. Previous implementation failed on Microsoft + Visual Studio 6 (on this platform: NaN == NaN). + * examples/cppunittest/TestAssertTest.cpp: Add more unit tests to + test the portable floating-point primitive. Added missing + include . + + * include/cppunit/portability/Makefile.am: + * include/cppunit/portability/FloatingPoint.h: Added file. Extracted + isfinite() from TestAssert.cpp. + + * include/cppunit/config-evc4: + * include/cppunit/config-msvc6: Added support for _finite(). + +2007-01-30 Steve M. Robbins + + * examples/cppunittest/assertion_traitsTest.h: + * examples/cppunittest/assertion_traitsTest.cpp: New. Test + assertion_traits<>. + + * examples/cppunittest/Makefile.am: Add + assertion_traitsTest.{h,cpp}. + + * examples/cppunittest/TestAssertTest.h: + * examples/cppunittest/TestAssertTest.cpp: Add + testAssertDoubleEqualsPrecision() to test precision of failure + message. + +2007-01-27 Steve M. Robbins + + * examples/cppunittest/TestAssertTest.cpp: + * examples/cppunittest/TestAssertTest.h: Remove declaration of + unimplemented functions testAssertDoubleNotEquals1 and + testAssertDoubleNotEquals2. Factor new method + testAssertDoubleNonFinite out of existing testAssertDoubleEquals. + + * src/cppunit/Win32DynamicLibraryManager.cpp (doLoadLibrary): + Unconditionally use ANSI version of LoadLibrary() and other + functions with string arguments. + +2007-01-26 Steve M. Robbins + + * config/ax_cxx_have_isfinite.m4: New. Autoconf macro that tests + for finite() in C++ mode. + * configure.in: Check for isfinite() and finite(). + + * examples/cppunittest/TestAssertTest.cpp (testAssertDoubleEquals): + * src/cppunit/TestAssert.cpp (assertDoubleEquals): Account for + non-finite values. + +2007-01-11 Steve M. Robbins + + * examples/cppunittest/MockFunctor.h: + * examples/cppunittest/MockProtector.h: + * examples/cppunittest/XmlOutputterTest.cpp: + * examples/cppunittest/XmlUniformiser.cpp: + * src/DllPlugInTester/CommandLineParser.cpp: + * src/cppunit/DynamicLibraryManagerException.cpp: + * src/cppunit/TestCaseDecorator.cpp: + * src/cppunit/TextTestRunner.cpp: + * src/cppunit/XmlDocument.cpp: Arrange field initializers in + correct order. + + * include/cppunit/plugin/TestPlugIn.h (struct CppUnitTestPlugIn): + * include/cppunit/extensions/TestFixtureFactory.h (class TestFixtureFactory): + * include/cppunit/XmlOutputterHook.h (XmlOutputterHook): Add + virtual destructor to virtual class. + + * examples/cppunittest/TestAssertTest.cpp: Put a C++ statement in + the first argument of CPPUNIT_ASSERT_THROW() and + CPPUNIT_ASSERT_NO_THROW(). + + * examples/hierarchy/main.cpp (main): Return value now reflects + whether tests passed. + * examples/hierarchy/Makefile.am (XFAIL_TESTS): New. Mark hierachy + test program as an expected failure. + + * Makefile.am (dist-hook): Don't fail if $(distdir)/lib already + exists. + + * config/bb_enable_doxygen.m4 (BB_ENABLE_DOXYGEN): Add quotes + around function name, BB_ENABLE_DOXYGEN. + +2006-10-26 Baptiste Lepilleur + * include/cppunit/TestResult.h: + * include/cppunit/ui/Config.h: fixed compilation issues with QtTestRunner. + +2006-06-29 Baptiste Lepilleur + * Makefile.am: + * lib/.keepme: added dummy file to prevent lib/ removal by some + unzip clients. Fixed bug #1527877 . + + * src/msvc6/TesRunner/TestRunner.rc: + * src/msvc6/testpluginrunner/TestPlugInRunner.rc: Fixed bug #1528212 + (some resources wrongly tagged as French). + +2006-06-29 Baptiste Lepilleur + * include/cppunit/ui/text/TextTestRunner.h + * src/cppunit/TextTestRunner.cpp: applied patch #1210013 to remove + hidden virtual function warning. + + * autogen.sh: applied patch #1449380 contributed by Sander Temme + to allow running autogen on Mac OS X. + + * doc/header.html: updated to handle new tabs css required for + html doc generated with doxygen 1.4.7. + + * src/msvc6/testrunner/MsDevCallerListCtrl.cpp: applied correction + provided to fix bug #1498175 (double click on failure does not + goto failure). + +2006-03-04 Baptiste Lepilleur + * contrib/xml-xsl/report.xsl: reported correction posted on the wiki. + + * removed debian/ directory. An up to date patch can be found at: + packages.debian.org. + + * cppunit.spec.in: applied patch #1242905 partially (%post and %postun). + + * cppunit.pc.in: + * configure.in: + * Makefile.am: integrated patch from Robert Leight to generate pkg-config. + +2006-02-04 Baptiste Lepilleur + * include/cppunit/TestListener.h: + * src/qttestrunner/TestRunnerModel.cpp: removed compilation warning. + +2006-02-01 Baptiste Lepilleur + * examples/qt: integrated Ernst patch from qt examples. + +2005-12-12 Baptiste Lepilleur + * src/qttestrunner: integrated Ernst patch for QtTestRunner and Qt 3.x. + Enhanced qmake project files to handle multiple build configuration + +2005-11-27 Baptiste Lepilleur + * doc/cookbook.dox: fixed type (patch #1334567) + +2005-11-06 Baptiste Lepilleur + * include/cppunit/config/SourcePrefix.h: disable warning #4996 + (sprintf is deprecated) for visual studio 2005. + + * include/cppunit/TestAssert.h: use sprintf_s instead of sprintf for + visual studio 2005. + + * examples/ClockerPlugIn/ClockerPlugIn.cpp + * examples/DumperPlugIn/DumperPlugIn.cpp: use SourcePrefix.h. Fixed + wrong macro usage to implement DllMain. + + * examples/msvc6/HostApp/ExamplesTestCase.h + * examples/msvc6/HostApp/ExamplesTestCase.cpp + * examples/simple/ExamplesTestCase.h + * examples/simple/ExamplesTestCase.cpp: removed divideByZero test case + as it cause some crash on some platforms. + + +2005-10-27 Baptiste Lepilleur + * include/cppunit/TestAssert.h: added missing #include + +2005-07-30 Baptiste Lepilleur + * include/cppunit/config/SourcePrefix.h: added, prefix added at begining of sources + to remove warning. Removed most warning when compiling with VC++ 6sp6. + + * examples/money/Money.h: + * examples/money/MoneyTest.cpp: added assert equal usage. + +2005-07-30 Baptiste Lepilleur + + * include/cppunit/config/config-msvc6.h: auto-detect if RTTI are enabled + the _CPPRTTI macro (defined by the compiler when enabling RTTI). + + * include/cppunit/config/config-msvc6.h: added missing macro definition + CPPUNIT_HAVE_CPP_CAST. + + * src/cppunit/TestResultCollector.cpp: fixed memory leak in destructor. + +2005-07-15 Baptiste Lepilleur + + * config/bb_enable_doxygen.m4: Rolled back Brad Hards patch as it break + generation of doc/Makefile.am. + + * cppunit.spec.in: Applied patch #1232555 from Patrice Dumas. This file is + use for RPM packaging. + + * development snapshot release 1.11.0. + +2005-07-09 Baptiste Lepilleur + + * doc/Money.dox: + * include/cppunit/TestSuite.h: + * include/cppunit/XmlOutputterHook.h: applied Brad Hards patch + that correct miscellaneous doc generation issues (unescaped <>, \...). + + * include/cppunit/plugin/TestPlugIn.h: + * include/cppunit/CompilerOutputter.h: + * doc/CppUnit-win.dox: removed a few documentation generation warnings. + + * config/bb_enable_doxygen.m4: applied Brad Hards patch to remove warning + when running ./autogen.sh or aclocal. + + * doc/money.dox: fixed bad usage of CPPUNIT_ASSERT_EQUALS. + +2005-07-05 Baptiste Lepilleur + + * Examples/simple/Makefile.am: do not install 'simple' programm + (patch #1230784). + +2005-07-05 Baptiste Lepilleur + + * include/cppunit/TestResultCollector.h + * src/cppunit/TestResultCollector.cpp: fixed memory leak + occuring when calling reset(). + + * src/cppunit/DllMain.cpp: added work-around for mingw compilation + for BLENDFUNCTION macro issue when including windows.h. + + * src/qttestrunner/TestRunnerDlgImpl.cpp: fixed display of multiline + messages. + + * include/cppunit/Portability.h: better integration of compiler output + for gcc on Mac OS X with Xcode (contributed by Claus Broch). + +2005-06-14 Baptiste Lepilleur + * src/msvc6/testrunner/ProgressBar.cpp: applied patch from bug #1165875, + (use system color for border instead of hard-coded color). + + * src/cppunit/Makefile.am: + * configure.in: MinGW, cygwin: enable build of shared library when using + libtool. patch #1194394 contributed by Stéphane Fillod. + + * cppunit.m4: applied patch #1076398 contributed by Henner Sudek. Fix + version number comparison in AM_PATH_CPPUNIT. + + * contrib/xml-xsl/cppunit2junit.txt + * contrib/xml-xsl/cppunit2junit.xsl + * contrib/readme.txt: XSLT for compatibility with Ant junit xml formatter. + Patch #1112053 contributed by Norbert Barbosa. + +2005-02-23 Baptiste Lepilleur + + * examples/hierarchy/BoardGameTest.h: + * examples/hierarchy/ChessTest.h: fixed compilation issue, prefixed access + to class member with 'this' (inheriting from template parameter + dependent class). + +2004-11-19 Baptiste Lepilleur + + * include/cppunit/Message.h + * include/cppunit/SourceLine.h: + * src/cppunit/Message.cpp: + * src/cppunit/SourceLine.cpp: provided thread-safe copy constructor on + platform that do not provide thread-safe copy constructor for std::string. + +2004-11-08 Baptiste Lepilleur + + * include/cppunit/TestAssert.h: fixed portability bug pointed out by + Neil Ferguson. + +2004-11-06 Baptiste Lepilleur + + * include/cppunit/TestAssert.h: integrated Neil Ferguson patch for high + precision conversion to string for double number. Modified the patch + to works even if DBL_DIG C99 macro is not defined. + + * include/cppunit/Portability.h: fixed EVC++ 4 detection. + + * src/cppunit/Win32DynamicLibraryManager.cpp: integrated patch #1024428, + MinGW compilation under Windows XP. + +2004-11-05 Baptiste Lepilleur + + * include/cppunit/TestAssert.h: + * src/cppunit/TestAssert.cpp: integrated Neil Ferguson patch for missing + _MESSAGE assertion variants. Also enhanced the failure message of a + few assertions. + +2004-09-10 Baptiste Lepilleur + + * src/msvc6/DSPlugIn/StdAfx.h: add #error to prevent compilation on VC 7. + + * src/msvc6/testrunner/MsDevCallerListCtrl.cpp: + * src/msvc6/testrunner/MsDevCallerListCtrl.h: integrated go to source line + features on double click contributed by Max Quatember and + Andreas Pfaffenbichler. + +2004-08-01 Baptiste Lepilleur + + * include/cppunit/XmlOutputter.h: + * include/cppunit/tools/XmlDocument.h: + * src/cppunit/XmlDocument.cpp: + * src/cppunit/XmlOutputter.cpp: integrated patch #997006 from Akos Maroy. + This patch makes the 'standalone' attribute in XML header optional. + +2004-06-25 Baptiste Lepilleur + + * include/cppunit/Portability.h: moved OStringStream alias definition to + portability/Stream.h. User need to define EVC4 to indicate that + config-evc4.h should be used. (how to we detect this automatically ?). + Notes that this means it might be needed to add #include to some + headers since its no longer included by Portability.h. + + * include/cppunit/portability/Stream.h: define alias OStringStream, stdCOut(), + and OFileStream. If CPPUNIT_NO_STREAM is defined (evc4 config), then provides + our own implementation (based on sprintf and fwrite). + + * include/cppunit/config/config-evc4.h: config file for embedded visual c++ 4. + Still need to detect for this platform in Portability.h (currently relying on + EVC4 being defined...) + + * *.[cpp/h]: most source files have been impacted with the following change: + #include -> #include + std::ostream -> CPPUNIT_NS::OStream + std::ofstream -> CPPUNIT_NS::OFileStream + std::cout -> CPPUNIT_NS::stdCOut() + std::endl -> "\n" + Also, code using std::cin as been defined out if CPPUNIT_NO_STREAM was defined. + The exact list of impact files can be obtain in CVS using tags: + TG_CPPUNIT_NO_STREAM_BEFORE & TG_CPPUNIT_NO_STREAM_AFTER. + +2004-06-19 Baptiste Lepilleur + + * cppunit.m4: patch #946302, AM_PATH_CPPUNIT doesn't report result + if CppUnit is missing. + + +2004-06-18 Baptiste Lepilleur + + * Release 10.0.2 + + * include/cppunit/extension/TestSuiteBuilderContext.h: + * src/cppunit/TestSuiteBuilderContext.cpp: fixed bug #921843. This bug + was caused by a known STL bug in VC++ 6. + See http://www.dinkumware.com/vc_fixes.html issue with shared + std::map in dll. As a work-around the map has been replaced by a vector. + + * src/DllPlugInTester/*.cpp: bug #941625, string literal using char * + instead of const char *. Patch contributed by Curt Arnold has been + applied. + + * src/msvc6/testrunner/TestRunnerDlg.h: + * src/msvc6/testrunner/TestRunnerDlg.cpp: + * src/msvc6/testpluginrunner/TestPlugIn.cpp: + * src/msvc6/testpluginrunner/TestPlugInRunnerApp.cpp: + * src/msvc6/testpluginrunner/TestPlugInRunnerModel.cpp: + * src/msvc6/testpluginrunner/TestPlugInRunnerModel.h: bug #952912, + memory leaks when loading/reloading plug-ins. + +2004-06-17 Baptiste Lepilleur + + * include/cppunit/Portability.h: + * include/cppunit/plugin/TestPlugIn.h: fixed report compilation issue + with mingw & cygwin. WIN32 is now always defined if _WIN32 is defined. + Bug #945737 & #930338. + + * doc/Makefile.am: fixed bug #940650 => cp -dpR, removed option -p since + there is no link to preserve anyway (does not exist on SunOs). + + * src/cppunit/TestPath.cpp: bug #938753, array bound read in + splitPathString() with substr if an empty string is passed. + + * src/*/*.dsp: bug #933154, post build fail in directory with spaces. + + +2004-06-16 Baptiste Lepilleur + + * release 1.10.0 + + * install-UNIX.txt: added some notes concerning Sun CC 5.5 & AIX. + + * examples/*/*.dsp: fixed project settings (rtti not enabled). + +2004-03-13 Baptiste Lepilleur + + * release 1.9.14 + +2004-03-13 Baptiste Lepilleur + + * cppunit-config.in: bug #903363, missing -ldl from the output of + cppunit-config --libs. Fixed thanks Eric Blossom patch. + + * examples/qt/Main.cpp: + * examples/qt/ExampleTestCase.h: fixed bug #789672: QT example should + use CPPUNIT_NS macro. + + * src/cppunit/UnixDynamicLibraryManager.cpp: applied patch #816563 + from Gareth Sylvester. Adding RTLD_GLOBAL allows test plug-ins + to provide symbols to shared objects they load themselves. + + * examples/cppunittest/TestAssertTest.h: + * examples/cppunittest/TestAssertTest.cpp: + * examples/cppunittest/XmlUniformiserTest.h: + * examples/cppunittest/XmlUniformiserTest.cpp: + * include/cppunit/TestAssert.h: add the exception assertion macros + from cppunit 2: CPPUNIT_ASSERT_THROW, CPPUNIT_ASSERT_NO_THROW, + CPPUNIT_ASSERT_ASSERTION_FAIL, CPPUNIT_ASSERT_ASSERTION_PASS. + Updated unit test to use and test the new macros. + + * include/cppunit/extensions/HelperMacros.h: deprecated the + test case factory that check for exception (CPPUNIT_TEST_FAIL & + CPPUNIT_TEST_EXCEPTION). + + +2004-02-20 Baptiste Lepilleur + + * release 1.9.12 + +2004-02-18 Baptiste Lepilleur + + * configure.in: + * makefile.am: + * config/ax_cxx_gcc_abi_demangle.m4: + * src/cppunit/TypeInfoHelper.cpp: added patch from + Neil Ferguson to use gcc c++ abi to demangle typeinfo + name when available. + +2003-05-15 Baptiste Lepilleur + + * include/cppunit/plugin/testplugin.h: fixed bug #767358, wrong + preprocessor symbol for SHL_LOADER. + +2003-05-15 Baptiste Lepilleur + + * include/cppunit/config/config-msvc6.h: changed the compiler outputter + default format (CPPUNIT_COMPILER_LOCATION_FORMAT) for Visual Studio 7.0. + Assertion now appears in the task list. + +2003-05-07 Baptiste Lepilleur + + * include/cppunit/extensions/Makefile.am: removed TestSuiteBuilder.h + + * Makefile.am + * configure.in + * config/ac_dll.m4 + * examples/cppunittest/Makefile.am + * examples/hierarchy/Makefile.am + * examples/money/Makefile.am + * examples/simple/Makefile.am + * include/cppunit/config/SelectDllLoader.h + * include/cppunit/plugin/TestPlugIn.h + * include/cppunit/tools/Algorithm.h + * src/DllPlugInTester/Makefile.am + * src/cppunit/Makefile.am + * src/cppunit/TestDecorator.cpp + * src/cppunit/ShlDynamicLibraryManager.cpp + * src/cppunit/UnixDynamicLibraryManager.cpp + * src/cppunit/Win32DynamicLibraryManager.cpp: applied patch from + Abdessattar Sassi to add support + for plug-in to hp-ux (patch #721546). + + * INSTALL-unix: added build instruction for HP-UX. + +2003-04-06 Baptiste Lepilleur + + * include/cppunit/extensions/TestSuiteBuilder.h: removed (unused) + +2003-03-31 Baptiste Lepilleur + + * src/cppunit/DynamicLibraryManager.cpp: fixed compilation issue on Mingw + (bug #711583) + +2003-03-20 Baptiste Lepilleur + + * include/cppunit/extensions/TestNamer.h: + * src/cppunit/TestNamer.cpp: Fixed bug #704684, TestNamer has non-virtual + destructor. + +2003-03-15 Baptiste Lepilleur + + * src/msvc6/testrunner/DynamicWindow/cdxCDynamicWndEx.cpp: + * examples/msvc6/CppUnitTestApp/CppUnitTestApp.cpp: + * examples/msvc6/HostApp/HostApp.cpp: + * src/msvc6/testpluginrunner/TestPlugInRunnerApp.cpp: fixed compatibility + issues with vc7 MFC. + + * include/cppunit/tools/Algorithm.h: + * examples/cppunittest/XmlOutputterTest.cpp: + * examples/cppunittest/XmlUniformiser.*: + * src/cppunit/CompilerOutputter.cpp: + * src/cppunit/ProtectorChain.cpp: + * src/cppunit/StringTools.cpp: + * src/cppunit/TestPath.cpp: + * src/cppunit/TypeInfoHelper.cpp: + * src/cppunit/XmlElement.cpp: + * src/cppunit/XmlOutputter.cpp: + * src/DllPlugInTester/CommandLineParser.h: + * src/msvc6/testrunner/TestRunnerDlg.cpp: switched to using unsigned index in loop to + avoid signed/unsigned warning in vc7. + + * include/cppunit/extension/ExceptionTestCaseDecorator.h: removed dll export + on template (caused link error on vc7). + +2003-03-11 Baptiste Lepilleur + * config/bb_enable_doxygen.m4: + * doc/Makefile.am: applied Luke Dunstan's fix for bug #700730 (spaces not + allowed in doxygen path) + + * src/cppunit/XmlElement.cpp: + * src/examples/cppunittest/XmlUniformser.cpp: fixed bug #676505 (no space + between attributes of XmlElement). + + * include/cppunit/tools/Algorithm.h: + * src/cppunit/TestResult.cpp: + * src/msvc6/testrunner/TestRunnerModel.cpp: added removeFromSequence + algorithm in Algorithm.h to fix STLPort compatibility issue + (std::remove use the one of cstdio instead of algorithm). Bug #694971. + + * src/examples/cppunittest/TrackedTestCase.cpp: + * src/examples/cppunittest/CppUnitTestMain.cpp: + * src/examples/money/Money.h: partially applied patch #699794. Fixed + compilation issues with Borland C++ 6. + +2003-01-23 Baptiste Lepilleur + + * include/cppunit/extensions/TestNamer.h: fixed bug #662666 (missing include + for typeinfo). + +2002-12-12 Baptiste Lepilleur + + * src/cppunit/TestResult.cpp: TestFailure are no longer passed as temporary, + but explicitely instantiated on the stack. Work around AIX compiler bug. + +2002-12-03 Baptiste Lepilleur + + * include/cppunit/TextTestResult.h: added missing dll export for + operator << (bug #610119). + +2002-12-02 Baptiste Lepilleur + + * include/cppunit/plugin/DynamicLibraryManagerException.h: added constructor + to fix compilation issues on recents version of gcc and sun CC (bug #619059) + + * include/cppunit/input/XmlInputHelper.h: added. + + * src/cppunit/XmlOuputter.cpp: use iterator instead of const_iterator. + + * src/src/msvc6/testrunner/DynamicWindow/cdxCDynamicWnd.cpp: added call to + IsUp() in cdxCDynamicWnd::DoOnGetMinMaxInfo() before calling + GetBorderSize() which caused an assertion. Bug #643612. + +2002-09-10 Baptiste Lepilleur + + * include/cppunit/extensions/TestSuiteBuilderContext.h: + * src/cppunit/TestSuiteBuilderContext.cpp: added addProperty() and + getStringProperty(). Added macros CPPUNIT_TEST_SUITE_PROPERTY. + + * src/msvc6/testrunner/TestRunnerDlg.cpp: integrated Tim Threlkeld's + bug fix #610162: browse button was disabled if history was empty. + + * src/msvc6/testrunner/DynamicWindow/cdxCSizeIconCtrl.cpp: integrated + Tim Threlkeld's bug fix #610191: common control were not initialized. + + * include/cppunit/extensions/ExceptionTestCaseDecorator.h: bug #603172, + missing Message construction. + + * src/cppunit/DefaultProtector.cpp: bug #603172. Fixed missing ';'. + + * src/cppunit/TestCase.cpp: bug #603671. Removed unguarded typeinfo + include. + + * examples/cppunittests/*Suite.h: bug #603666. Added missing Portability.h + include. + +2002-09-01 Baptiste Lepilleur + + * include/cppunit/ui/text/TextTestRunner.h: fixed header guards. + +2002-08-29 Baptiste Lepilleur + + * include/cppunit/TestResult.h: + * src/cppunit/TestResult.cpp: fixed shouldStop() bug. + +2002-08-29 Baptiste Lepilleur + + * include/cppunit/CompilerOutputter.h: + * include/cppunit/Exception.h: + * include/cppunit/Protector.h: + * include/cppunit/TestListener.h: + * include/cppunit/TestPath.h: + * include/cppunit/TestResult.h: + * include/cppunit/TestRunner.h: + * include/cppunit/XmlOutputter.h: + * include/cppunit/plugin/DynamicLibraryManager.h: + * include/cppunit/plugin/PlugInManager.h: + * include/cppunit/plugin/PlugInParameters.h: + * include/cppunit/TestPlugIn.h: + * src/cppunit/DefaultProtector.h: + * src/cppunit/ProtectorChain.h: + * src/cppunit/ProtectorContext.h: + * src/cppunit/TestCase.cpp: + * src/cppunit/TestResult.cpp: fixed a dew documentation bugs. + + * include/cppunit/TestResult.h: + * src/cppunit/TestResult.cpp: moved documentation to header. + +2002-08-29 Baptiste Lepilleur + + * include/cppunit/Asserter.h: + * include/cppunit/Message.h: + * include/cppunit/extensions/TestNamer.h: + * include/cppunit/extensions/TestSuiteBuilder.h: + * include/cppunit/tools/XmlDocument.h: + * include/cppunit/tools/XmlElement.h: Fixed a few documentation bugs. + +2002-08-28 Baptiste Lepilleur + + * include/cppunit/Portability.h: added CPPUNIT_STATIC_CAST. + + * include/cppunit/extensions/TestFixtureFactory.h: extracted from + HelperMacros.h. Added template class ConcretTestFixtureFactory. + + * include/cppunit/extensions/TestSuiteBuilderContext.h: + * src/cppunit/TestSuiteBuilderContext.cpp: added. Context used + to add test case to the fixture suite. Prevent future + compatibility break for custom test API. + + * include/cppunit/extensions/HelperMacros.h: mostly rewritten. No + longer use TestSuiteBuilder. Added support for abstract test fixture + through macro CPPUNIT_TEST_SUITE_END_ABSTRACT. Made custom test API + easier to use. + + * examples/cppunittest/HelperMacrosTest.h: + * examples/cppunittest/HelperMacrosTest.cpp: updated against + HelperMacros.h changes. + +2002-08-27 Baptiste Lepilleur + + * CodingGuideLines.txt: updated for OS/390 C++ limitation. + + * examples/cppunittests/MockFunctor.h: added. Mock Functor to help + testing. + + * examples/cppunittests/MockProtector.h: qdded. Mock Protector to help + testing. + + * examples/cppunittests/TestResultTest.h + * examples/cppunittests/TestResultTest.cpp: added tests for + pushProtector(), popProtector() and protect(). + + * include/cppunit/TestAssert.h: removed default message value from + assertEquals(). Caused compilation error on OS/390. + + * include/cppunit/plugin/PlugInParameters.h: + * src/cppunit/PlugInParameters.cpp: renamed commandLine() to + getCommandLine(). + + * src/msvc6/testrunner/TestRunnerDlg.h: + * src/msvc6/testrunner/TestRunnerDlg.cpp: bug fix, disabled Browse + button while running tests. + +2002-08-22 Steve M. Robbins + + * cppunit.m4: Doc fix: MINIMUM-VERSION is not optional when using + this macro. + +2002-08-04 Baptiste Lepilleur + + * src/cppunit/XmlDocument.cpp: fixed compatility bug with C++ builder. + + * include/cppunit/plugin/Parameters.h: renamed PlugInParameters.h. + + * src/cppunit/PlugInParameter.cpp: added. Implementation of class + PlugInParameters. + + * examples/DumperPlugIn/DumperPlugIn.cpp: + * examples/ClockerPlugIn/ClockerPlugIn.cpp: + * src/DllPlugInTester/CommandLineParser.h: + * src/DllPlugInTester/CommandLineParser.cpp: + * include/cppunit/plugin/TestPlugInDefaultImpl.h: + * src/cppunit/TestPlugInDefaultImpl.cpp: + * include/cppunit/plugin/PlugInManager.h: + * src/cppunit/PlugInManager.cpp: updated against PlugInParameter + change. + +2002-08-03 Baptiste Lepilleur + + * include/cppunit/XmlOutputterHook.h: integrated Stephan Stapel + documentation update. + +2002-08-03 Baptiste Lepilleur + + * include/cppunit/Exception.h: + * src/cppunit/Exception.h: added setMessage(). + + * include/cppunit/Protector.h: + * src/cppunit/Protector.cpp: added class ProtectorGuard. Change the + reportXXX() method to support Exception passing and SourceLine. + + * include/cppunit/TestCaller.h: removed 'expect exception' features. + It is now handled by ExceptionTestCaseDecorator and TestCaller no + longer need default template argument support. + + * include/cppunit/TestCase.h: + * include/cppunit/extensions/TestCaller.h: runTest() is now public + instead of protected, so that it can be decorated. + + * include/cppunit/TestResult.h: + * src/cppunit/TestResult.h: added pushProtector() and popProtector() + methods. This allow user to specify their own exception trap when + running test case. + + * include/cppunit/extensions/TestDecorator.h: + * src/cppunit/TestDecorator.cpp: added. Extracted from TestDecorator.h. + The test passed to the constructor is now owned by the decorator. + + * include/cppunit/extensions/TestCaseDecorator.h: + * src/cppunit/TestCaseDecorator.cpp: added. Decorator for TestCase + setUp(), tearDown() and runTest(). + + * include/cppunit/extensions/ExceptionTestCaseDecorator.h: added. + TestCaseDecorator to expect that a specific exception is thrown. + + * include/cppunit/extensions/HelperMacros.h: updated against TestCaller + change. + + * src/cppunit/DefaultFunctor.h: fixed bug (did not return underlying + test return code). + + * src/cppunit/ProtectorChain.cpp: fixed bug in chaing return code. + + * src/cppunit/DefaultFunctor.h: fixed bug. + + * src/msvc6/testrunner/ActiveTest.h: + * src/msvc6/testrunner/ActiveTest.cpp: updated against + TestCaseDecorator ownership policy change. Moved inline functions + to .cpp. + + * examples/cppunittest/TestSetUpTest.cpp: updated to use MockTestCase + and against the new ownership policy. + + * examples/cppunittest/TestDecoratorTest.cpp: + * examples/cppunittest/RepeatedTestTest.cpp: updated against + TestDecorator ownership policy change. + + * examples/cppunittest/ExceptionTestCaseDecoratorTest.h: + * examples/cppunittest/ExceptionTestCaseDecoratorTest.cpp: added. Unit + tests for ExceptionTestCaseDecoratorTest. + +2002-07-16 Baptiste Lepilleur + + * include/cppunit/Protector.h: + * src/cppunit/Protector.cpp: added. Base class for protectors. + + * src/cppunit/DefaultProtector.h: + * src/cppunit/DefaultProtector.cpp: added. Implementation of the default + protector used to catch std::exception and any other exception. + + * src/cppunit/ProtectorChain.h: + * src/cppunit/ProtectorChain.cpp: added. Implementation of a chain of + protector, allowing catching custom exception and implementation of + expected exception. + + * src/cppunit/TestCase.cpp: + * src/cppunit/TestResult.cpp: updated to use protector. + +2002-07-14 Baptiste Lepilleur + + * CodingGuideLines.txt: added. CppUnit's coding guidelines for portability. + + * include/cppunit/portability/CppUnitStack.h: added. wrapper for std::stack. + + * include/cppunit/portability/CppUnitSet.h: added. wrapper for std::set. + + * include/cppunit/ui/text/TestRunner.h: fixed namespace definition for + deprecated TestRunner. + + * include/cppunit/TestAssert.h: + * src/cppunit/TestAssert.cpp: removed old deprecated functions that did + not use SourceLine. Moved assertEquals() and assertDoubleEquals() into + CppUnit namespace. + + * src/cppunit/TestFactoryRegistry.cpp: use CppUnitMap instead of std::map. + + * src/DllPlugInTester/CommandLineParser.h: use CppUnitDeque instead + std::deque. + + * examples/cppunittest/*.h: + * examples/cppunittest/*.cpp: removed all usage of CppUnitTest namespace. + Everything is now in global space. + + * examples/*/*.h: + * examples/*/*.cpp: replaced usage of CppUnit:: with CPPUNIT_NS::. + + * examples/ClockerPlugIn/ClockerModel.h: use CppUnit STL wrapper instead + of STL container. + +2002-07-13 Baptiste Lepilleur + + * include/cppunit/ui/text/TestRunner.h: + * src/cppunit/TextTestRunner.cpp: Renamed TextUi::TestRunner + TextTestRunner and moved it to the CppUnit namespace. Added + a deprecated typedef for compatibility with previous version. + + * include/cppunit/ui/text/TextTestRunner.h: added. + + * include/cppunit/ui/mfc/TestRunner.h: + * src/cppunit/msvc6/testrunner/TestRunner.cpp: Renamed MfcUi::TestRunner + MfcTestRunner. Added deprecated typedef for compatibility. Renamed + TestRunner.cpp to MfcTestRunner.cpp. + + * include/cppunit/ui/mfc/MfcTestRunner.h: added. + + * include/cppunit/ui/qt/TestRunner.h: + * src/qttestrunner/TestRunner.cpp: renamed QtUi::TestRunner QtTestRunner + and moved it to CppUnit namespace. Added a deprecated typedef for + compatibility. Renamed TestRunner.cpp to QtTestRunner.cpp. + + * include/cppunit/ui/qt/TestRunner.h: + * src/qttestrunner/TestRunner.h: Moved TestRunner to CppUnit namespace + and renamed it QtTestRunner. Added deprecated typedef for compatibility. + + * include/cppunit/Asserter.h: + * src/cppunit/Asserter.cpp: changed namespace Asserter to a struct and + made all methods static. + + * include/cppunit/extensions/HelperMacros.h: + * include/cppunit/extensions/SourceLine.h: + * include/cppunit/extensions/TestAssert.h: + * include/cppunit/extensions/TestPlugIn.h: + * include/cppunit/Portability.h: changed CPPUNIT_NS(symbol) to a + symbol macro that expand either to CppUnit or nothing. The symbol is + no longer a parameter. + + * include/cppunit/portability/CppUnitVector.h: + * include/cppunit/portability/CppUnitDeque.h: + * include/cppunit/portability/CppUnitMap.h: added. STL Wrapper for + compilers that do not support template default argumenent and need + the allocator to be passed when instantiating STL container. + + * examples/cppunittest/*.h: + * examples/cppunittest/*.cpp: + * src/msvc6/testrunner/*.h: + * src/msvc6/testrunner/*.cpp: + * src/msvc6/testpluginrunner/*.h: + * src/msvc6/testpluginrunner/*.cpp: + * src/qttestrunner/*.h: + * src/qttestrunner/*.cpp: replaced occurence of CppUnit:: by CPPUNIT_NS. + + * src/cppunit/TestSuite.h: + replaced occurence of std::vector by CppUnitVector. + +2002-07-12 Baptiste Lepilleur + + * include/cppunit/config/Portability.h: If the compiler does not support + namespace (CPPUNIT_HAVE_NAMESPACES=0), define CPPUNIT_NO_STD_NAMESPACE + and CPPUNIT_NO_NAMESPACE. If CPPUNIT_NO_STD_NAMESPACE is defined, then + CppUnit assumes that STL are in the global namespace. If + CPPUNIT_NO_NAMESPACE is defined, then CppUnit classes are placed in the + global namespace instead of the CppUnit namespace. + + * include/cppunit/config/config-bcb5.h: + * include/cppunit/config/config-msvc6.h: added definition of macro + CPPUNIT_HAVE_NAMESPACES. + + * include/cppunit/tools/StringTools.h: use CPPUNIT_WRAP_COLUMN as default + parameter value for wrap(). + + * include/cppunit/*/*.h: + * src/cppunit/*.cpp: changed all CppUnit namespace declaration to use + macros CPPUNIT_NS_BEGIN and CPPUNIT_NS_END. Also, changed reference + to CppUnit namespace (essentially in macros) using CPPUNIT_NS macro. + + * doc/doxyfile.in: + * doc/CppUnit-Win.dox: updated doxygen configuration files so that + CPPUNIT_NS_BEGIN and CPPUNIT_NS_END macros are expanded. This help + generates the documentation using the CppUnit namespace. + +2002-07-11 Baptiste Lepilleur + + * include/cppunit/Portability.h: added macro CPPUNIT_CONST_CAST. + + * src/cppunit/Exception.cpp: + * src/cppunit/Test.cpp: + * examples/cppunittest/MockTestCase.cpp: replaced usage of const_cast with + CPPUNIT_CONST_CAST. + + * include/cppunit/Test.h: + * src/cppunit/Test.cpp: made findTestPath(), findTest() and resolvePath() + const methods. + +2002-07-10 Baptiste Lepilleur + + * include/cppunit/extensions/AutoRegisterSuite.h: + * include/cppunit/extensions/Orthodox.h: + * include/cppunit/extensions/TestSuiteBuilder.h: + * include/cppunit/extensions/TestSuiteFactory.h: + * include/cppunit/TestCaller.h: + * examples/hierarchy/BoardGameTest.h: + * examples/hierarchy/ChessTest.h: replaced usage of 'typename' in template + declaration with 'class'. + + * include/cppunit/ui/text/TestRunner.h: + * src/cppunit/TextTestRunner.cpp: updated to use the generic TestRunner. + Removed methods runTestByName() and runTest(). Inherits + CppUnit::TestRunner. + + * include/cppunit/extensions/TestSuiteBuilder.h: removed templatized method + addTestCallerForException(). It is no longer used since release 1.9.8. + + * examples/cppunittest/MockTestCase.h + * examples/cppunittest/MockTestCase.cpp: removed the usage of 'mutable' + keyword. + +2002-07-04 Baptiste Lepilleur + + * src/msvc6/DSPlugIn/DSPlugIn.dsp: updated so that only the release + configuration get copied to the lib/ directory. + +2002-07-03 Baptiste Lepilleur + + * include/cppunit/XmlOutputter.h: fixed XmlOutputter constructed default + value initializatino which caused compilation error with BC5. + + * src/cppunit/PlugInManager.cpp: added missing CPPUNIT_NO_TESTPLUGIN guard. + + * src/msvc6/testrunner/TestRunner.dsp: + * src/msvc6/testrunner/TestRunner.rc: + * src/msvc6/testrunner/TestRunnerDlg.cpp: + * src/msvc6/testrunner/TestRunnerDlg.h: + * src/msvc6/testrunner/TreeHierarchyDlg.cpp: + * src/msvc6/testrunner/TreeHierarchyDlg.h: + * src/msvc6/testpluginrunner/TestPlugInRunner.dsp: + * src/msvc6/testpluginrunner/TestPlugInRunner.rc: + * src/msvc6/testpluginrunner/TestPlugInRunnerApp.cpp: + * src/msvc6/testpluginrunner/TestPlugInRunnerDlg.cpp: + * src/msvc6/testpluginrunner/TestPlugInRunnerDlg.h: applied Steven Mitter + patch to fix bug #530426 (conflict between TestRunner and host + application's resources). Adapted patch to compile work with Unicode. + + * src/msvc6/testrunner/ResourceLoaders.h: + * src/msvc6/testrunner/ResourceLoaders.cpp: + * src/msvc6/testrunner/Change-Diary-ResourceBugFix.txt: added, from + Steven Mitter's patch. Simplified loadCString() to compile with Unicode. + + * src/cppunit/cppunit.dsp: + * src/cppunit/cppunit_dll.dsp: + * src/DllPlugInTester/DllPlugInTester.dsp: + * src/msvc6/testrunner/TestRunner.dsp: + * src/msvc6/testpluginrunner/TestPlugInRunner.dsp: all lib, dll and exe are + now created in the intermediate directory. A post-build rule is used to + copy them to the lib/ directory. + +2002-06-17 Baptiste Lepilleur + + * include/cppunit/AdditionalMessage.h: + * src/cppunit/AdditionalMessage.cpp: added. Class to help passing + additional message parameter. + + * include/cppunit/Asserter.h: added makeExpected(), makeActual() and + makeNotEqualMessage(). Removed methods made unnecessary by the + use of AdditionalMessage. + + * include/cppunit/Portability.h: added CPPUNIT_WRAP_COLUMN to define + CppUnit default wrap column. + + * src/cppunit/CompilerOutputter.cpp: use CPPUNIT_WRAP_COLUMN instead + of hard-coded value. + +2002-06-16 Baptiste Lepilleur + + * bumped version to 1.9.9 + + * release 1.9.8 + + * include/cppunit/plugin/TestPlugIn.h: updated documentation. + + * include/cppunit/tools/XmlDocument.h: updated documentation. + + * include/cppunit/tools/StringTools.h: + * src/cppunit/StringTools.cpp: added split() and wrap() functions. + + * include/cppunit/CompilerOutputter.h: + * src/cppunit/CompilerOutputter.cpp: extracted wrap() and + splitMessageIntoLines() to StringTools. + + * include/cppunit/XmlOutputterHook.h: + * src/cppunit/XmlOutputterHook.cpp: removed rooNode parameter from + beginDocument() and endDocument(). It can be retreive from document. + Renamed 'node' occurences to 'element'. + + * include/cppunit/XmlOutputter.h: + * src/cppunit/XmlOutputter.cpp: updated against + XmlOutputterHook changes. Renamed 'node' occurences to 'element'. + + * src/cppunit/Message.cpp: + * src/cppunit/XmlElement.cpp: added missing include + + * examples/ClockerPlugIn/ClockerXmlHook.h: + * examples/ClockerPlugIn/ClockerXmlHook.cpp: updated against + XmlOutputterHook changes. + + * examples/cppunittest/MessageTest.cpp: removed std::string() from + assertion. Somehow gcc can't parse it. Added missing include . + + * examples/cppunittest/XmlElement.cpp: added missing include . + + * examples/cppunittest/XmlElementTest.h: + * examples/cppunittest/XmlElementTest.cpp: Renamed 'node' occurences + to 'element'. + + * examples/cppunittest/XmlOutputterTest.cpp: updated against + XmlOutputterHook changes. + + * examples/cppunittest/StringToolsTest.h: + * examples/cppunittest/StringToolsTest.cpp: added. Unit tests for + StringTools. Turn out that VC++ dismiss empty lines in tools output, + which is the reason why empty lines where not printed in + CompilerOutputter. + +2002-06-14 Baptiste Lepilleur + + * include/cppunit/plugin/PlugInManager.h: + * src/cppunit/PlugInManager.cpp: added two methods to use the plug-in + interface for Xml Outputter hooks. + + * include/cppunit/plugin/TestPlugIn.h: added two methods to the plug-in + interface for Xml Outputter hooks. + + * include/cppunit/plugin/TestPlugInAdapter.h: + * src/cppunit/plugin/TestPlugInAdapter.cpp: renamed TestPlugInDefaultImpl. + Added empty implementation for Xml outputter hook methods. + + * include/cppunit/tools/StringTools.h: + * src/cppunit/tools/StringTools.cpp: added. Functions to manipulate string + (conversion, wrapping...) + + * include/cppunit/tools/XmlElement.h: + * src/cppunit/XmlElement.cpp: renamed addNode() to addElement(). Added + methods to walk and modify XmlElement (for hook). Added documentation. + Use StringTools. + + * include/cppunit/XmlOutputter.h: + * src/cppunit/XmlOutputter.cpp: added hook calls & management. + + * include/cppunit/XmlOutputterHook.h: + * src/cppunit/XmlOutputterHook.cpp: added. Hook to customize XML output. + + * src/DllPlugInTester/DllPlugInTester.cpp: call plug-in XmlOutputterHook + when writing XML output. Modified so that memory is freed before + unloading the test plug-in (caused crash when freeing the XmlDocument). + + * examples/ReadMe.txt: + * examples/ClockerPlugIn/ReadMe.txt: added details about the plug-in + (usage, xml content...) + + * examples/ClockerPlugIn/ClockerModel.h: + * examples/ClockerPlugIn/ClockerModel.cpp: extracted from ClockerListener. + Represents the test hierarchy and tracked time for each test. + + * examples/ClockerPlugIn/ClockerListener.h: + * examples/ClockerPlugIn/ClockerListener.cpp: extracted test hierarchy + tracking to ClockerModel. Replaced the 'flat' view option with a 'text' + option to print the timed test tree to stdout. + + * examples/ClockerPlugIn/ClockerPlugIn.cpp: updated to hook the XML + output and use the new classes. + + * examples/ClockerPlugIn/ClockerXmlHook.h: + * examples/ClockerPlugIn/ClockerXmlHook.cpp: added. XmlOutputterHook to + includes the timed test hierarchy and test timing in the XML output. + + * examples/cppunittest/XmlElementTest.h: + * examples/cppunittest/XmlElementTest.cpp: added new test cases. + + * examples/cppunittest/XmlOutputterTest.h: + * examples/cppunittest/XmlOutputterTest.cpp: added tests for + XmlOutputterHook. + +2002-06-14 Baptiste Lepilleur + + * src/cppunit/TypeInfoHelper.cpp: added work around for bug #565481. + gcc 3.0 RTTI name() returns the type prefixed with a number (the + length of the type). The work around strip the number. + + * src/msvc6/testpluginrunner/TestPlugInRunnerApp.cpp: registry key is now + set. Allow to save settings. + + * src/msvc6/testpluginrunner/TestPlugInRunnerDlg.h: + * src/msvc6/testpluginrunner/TestPlugInRunnerDlg.cpp: added layout + initialization for resizing. + + * src/msvc6/testpluginrunner/TestPlugRunner.rc: + * src/msvc6/testpluginrunner/TestPlugInRunner.dsp: added TestRunner + project files. Somehow I can't get cdxCDynamicDialog to compile + as a MFC extension. Included all sources files and resources + as a very dirt work around. + + * src/msvc6/testrunner/TestRunnerDlg.h: + * src/msvc6/testrunner/TestRunnerDlg.cpp: + * src/msvc6/testrunner/TestRunnerModel.h: those classes are no longer + exported in the MFC extension. See TestPlugInRunner issue with + cdxCDynamicDialog. + + * include/cppunit/Message.h: + * include/cppunit/TestPath.h: + * include/cppunit/TestResult.h: + * include/cppunit/TestResultCollector.h: + * include/cppunit/TestSuite.h: + * include/cppunit/TestFactoryRegistry.h: + * include/cppunit/XmlElement.h: + * include/cppunit/TypeInfoHelper.h: commented out STL template export + in DLL. This caused conflicts when instantiting the same template in + a user project. + +2002-06-14 Baptiste Lepilleur + + * src/cppunit/CompilerOutputter.cpp: fixed bug #549762 (line wrap). + + * src/msvc6/testrunner/DynamicWindow/*: added. Dynamic Window library + from Hans Bühler (hans.buehler@topmail.de) to resize window. + + * src/msvc6/testrunner/TestRunnerModel.h: + * src/msvc6/testrunner/TestRunnerModel.cpp: removed dialog bounds from + settings. Added public registry keys for cppunit, main dialog, and + browse dialog. + + * src/msvc6/testrunner/TreeHierarchyDlg.h: + * src/msvc6/testrunner/TreeHierarchyDlg.cpp: dialog is now resizable. + Window placement is stored and restored. + + * src/msvc6/testrunner/TestRunnerDlg.h: + * src/msvc6/testrunner/TestRunnerDlg.cpp: replaced dialog resizing code + by usage of Hans Bühler's Dynamic Window library. Dialog placement + is stored/restored by that library. ProgressBar is now a child window. + Added edit field to see the details of the failure. List on show + the short description of the failure. + + * src/msvc6/testrunner/ProgressBar.h: + * src/msvc6/testrunner/ProgressBar.cpp: is now a CWnd. + + * src/msvc6/testrunner/TestRunner.rc: named all static fill ID for resizing. + Added an invisble static field for progress bar placement. + +2002-06-13 Baptiste Lepilleur + + * doc/other_documentation.dox: fixed some typos. + + * include/cppunit/NotEqualException.h: + * src/cppunit/NotEqualException.cpp: removed. + + * include/cppunit/Exception.h: + * src/cppunit/Exception.cpp: removed 'type' related stuffs. + + * include/cppunit/TextTestResult.h: + * src/cppunit/TextTestResult.cpp: delegate printing to TextOutputter. + + * examples/simple/ExampleTestCase.h: + * examples/simple/ExampleTestCase.cpp: reindented. + + * src/qttestrunner/build: + * src/qttestrunner/qttestrunner.pro: + * src/qttestrunner/TestBrowserDlgImpl.h: + * src/qttestrunner/TestRunnerModel.h: applied Thomas Neidhart's patch, + 'Some minor fixes to compile QTTestrunner under Linux.'. + +2002-06-13 Baptiste Lepilleur + + * include/cppunit/Asserter.h: + * src/cppunit/Asserter.cpp: added functions that take a Message as a + parameter. Existing function have a short description indicating + an assertion failure. + + * include/cppunit/CompilerOuputter.h: + * src/cppunit/CompilerOuputter.cpp: removed printNotEqualMessage() and + printDefaultMessage(). Updated to use Message. + + * include/cppunit/Message.h: + * src/cppunit/Message.cpp: added. Represents a message associated to an + Exception. + + * include/cppunit/Exception.h: + * src/cppunit/Exception.cpp: the message associated to the exception is now + stored as a Message instead of a string. + + * include/cppunit/NotEqualException.cpp: constructs a Message instead of a + string. + + * include/cppunit/TestAssert.h: + * src/cppunit/TestAssert.cpp: updated to use Asserter functions that + take a message when pertinent (CPPUNIT_FAIL...). + + * include/cppunit/TestCaller.h: + * src/cppunit/TestCaller.cpp: exception not caught failure has a better + short description. + + * src/cppunit/TestCase.cpp: better short description when setUp() or + tearDown() fail. + + * src/msvc6/testrunner/TestRunnerDlg.cpp: replace '/n' in failure message + with space. + + * examples/cppunittest/ExceptionTest.cpp: + * examples/cppunittest/NotEqualExceptionTest.cpp: + * examples/cppunittest/TestCallerTest.cpp: + * examples/cppunittest/TestFailureTest.cpp: + * examples/cppunittest/TestResultCollectorTest.h: + * examples/cppunittest/TestResultCollectorTest.cpp: + * examples/cppunittest/TestResultTest.cpp: + * examples/cppunittest/XmlOutputterTest.h: + * examples/cppunittest/XmlOutputterTest.cpp: updated to use Exception/Message. + + * examples/cppunittest/MessageTest.h: + * examples/cppunittest/MessageTest.cpp: added. Unit test for Message. + +2002-06-11 Baptiste Lepilleur + + * install-unix: added some hints extracted from bug #544684 on how to compile + for Solaris/Forte C++ compiler. + + * TODO: cleaned-up and added new things. + + * include/cppunit/extensions/HelperMacros.h: CPPUNIT_TEST_SUITE now declares + a class named ThisTestFixtureFactory which is a wrapper for the fixture + factory. This removes the need to cast the fixture to the correct type when + using the factory. Updated other macros implementation to use this new + factory. Modified CPPUNIT_TEST_CUSTOM(S) macros to use this new factory + class. Added macro CPPUNIT_TEST_ADD to help create new macros like + CPPUNIT_TEST_xxx. + + * examples/cppunittest/HelperMacrosTest.h: + * examples/cppunittest/HelperMacrosTest.cpp: added unit tests for + CPPUNIT_TEST_CUSTOM, CPPUNIT_TEST_CUSTOMS and CPPUNIT_TEST_ADD. + +2002-06-01 Baptiste Lepilleur + + * doc/cookbook.dox: fixed bug. + + * install-unix: added compilation instruction for Solaris/Sun 6.0 + +2002-05-25 Baptiste Lepilleur + + * include/cppunit/extensions/TestSuiteBuilder.h: updated to use TestNamer. Removed + template method addTestCallerForException() which should solve the compilation + issue with Sun 5.0/6.0 compiler. + + * include/cppunit/extensions/HelperMacros.h: updated against TestSuiteBuilder + change. Added CPPUNIT_TEST_CUSTOM and CPPUNIT_TEST_CUSTOMS to add custom + tests to the fixture suite. + + * include/cppunit/extensions/TestNamer.h: + * src/cppunit/TestNamer.cpp: added, TestNamer to name test case and fixture. + +2002-05-23 Baptiste Lepilleur + + * include/cppunit/XmlOutputter.h: + * src/cppunit/XmlOutputter.cpp: extracted class XmlOutputter::Node to + XmlElement. Extracted xml 'prolog' generation to XmlDocument. + + * include/cppunit/tools/XmlElement.h: + * src/cppunit/tools/XmlElement.cpp: added, extracted from XmlOutputter::Node. + + * include/cppunit/tools/XmlDocument.h: + * src/cppunit/tools/XmlDocument.cpp: added, extracted from XmlOutputter. Handle + XML document prolog (encoding & style-sheet) and manage the root element. + + * src/DllPlugInTester/DllPlugInTester.cpp: bug fix, flag --xsl was ignored. + + * examples/cppunittest/XmlOutputterTest.h: + * examples/cppunittest/XmlOutputterTest.cpp: updated for XmlOuputter changes. + extracted tests for XmlOutputter::Node to XmlElementTest + + * examples/cppunittest/XmlElementTest.h: + * examples/cppunittest/XmlElementTest.cpp: added, tests extracted from + XmlOutputterTest. + +2002-05-21 Baptiste Lepilleur + + * src/msvc6/testrunner/MsDevCallerListCtrl.h: + * src/msvc6/testrunner/MsDevCallerListCtrl.cpp: + * src/msvc6/testrunner/Resource.h: + * src/msvc6/testrunner/TestRunner.rc: + * src/msvc6/testrunner/TestRunnerDlg.cpp: + * src/msvc6/testrunner/TestRunnerModel.h: + * src/msvc6/testpluginrunner/TestPlugInRunner.rc: + * src/msvc6/testpluginrunner/TestPlugInRunnerDlg.cpp: + * src/msvc6/testpluginrunner/TestPlugInRunnerDlg.h: + * src/msvc6/testpluginrunner/TestPlugInRunnerModel.cpp: integrated patch from + Marco Welti (Welti@GretagMacbeth.ch) with a few clean up. + Display the name of the test being run during above the progress bar. Allow the + VC++ add-ins to works with TestPlugInRunner (COM init). DLL name can be specified + on the command line after flag '-testsuite'. Display wait cursor, clear and reload + history when reloading DLL. + + * THANKS: added Marco Welti to the list. + +2002-05-07 Baptiste Lepilleur + + * src/DllPlugInTester/CommandLineParser.cpp: fixed compilation issue. + + * src/msvc6/TestRunner/ActiveTest.h: + * src/msvc6/TestRunner/ActiveTest.cpp: reindented. bugfix: thread + handle resource leak (bug #553424). + +2002-04-25 Baptiste Lepilleur + + * src/cppunit/XmlOutputter.cpp: bugfix, use ISO-8859-1 encoding if an + empty string is given. + + * src/DllPlugInTester/CommandLineParser.h: + * src/DllPlugInTester/CommandLineParser.cpp: + * src/DllPlugInTester/DllPlugInTester.cpp: added option -w to wait for + the user to press a key before exiting (Philippe Lavoie patch, + with change). + +2002-04-22 Baptiste Lepilleur + + * include/cppunit/plugin/DynamicLibraryManagerException.h: removed + trailing ',' in enum. + + * examples/ClockerPlugIn/ClockerListener.cpp: bugfix, average test + case time computation. + +2002-04-21 Baptiste Lepilleur + + * bumped version to 1.9.7 + + * comitted stuffs I forgot to in 1.9.6. + +2002-04-21 Baptiste Lepilleur + + * contrib/bc5/bcc-makefile.zip: updated, generic makefile for + Borland 5.5, contributed by project cuppa. + + * examples/cppunittest/*Suite.h: integrated Jeffrey Morgan's patch, + to remove warning with gcc. + + * release 1.9.6 + +2002-04-21 Baptiste Lepilleur + + * src/DllPlugInTester/makefile.am: removed ld.so from LDADD flags. + + * src/DllPlugInTester/CommandLineParser.h: + * src/DllPlugInTester/CommandLineParser.cpp: rewrote, fixed problem + with double quotes in command line... + + * src/DllPlugInTester/CommandLineParserTest.h: + * src/DllPlugInTester/CommandLineParserTest.cpp: + * src/DllPlugInTester/DllPlugInTesterTest.cpp: added, unit tests for + CommandLineParser. + + * src/msvc6/TestPlugIn/*: removed. + + * examples/Money/*: added. New 'hello world' example. + + * doc/Money.dox: added. Article that go along with the Money example. + +2002-04-21 Baptiste Lepilleur + + * THANKS: updated + + * src/cppunit/DynamicLibraryManager.cpp: bugfix: did not pass + library name to exception. + + * include/cppunit/TestPath.h: + * src/cppunit/TestPath.cpp: changed into value object. + + * src/cppunit/BeosDynamicLibraryManager.cpp: integrated patch from + Shibu Yoshiki for BeOS ('cuppa' project team). + + * src/DllPlugInTester/CommandLineParser.h: + * src/DllPlugInTester/CommandLineParser.cpp: added. Command line + parsing. + + * src/DllPlugInTester/DllPlugInTester.cpp: full command line support + with parameters for plug-ins. + + * src/DllPlugInTester/makefile.am: + * examples/simple/makefile.am: + * examples/cppunittest/makefile.am: integrated Jeffrey Morgan's patch, + Unix side should be working again. + + * examples/ReadMe.txt: added. Brief description of each example. + + * examples/cppunittest/CppUnitTestPlugIn.cpp: + * examples/cppunittest/CppUnitTestPlugIn.dsp: added. New project to + build CppUnit's test suite as a test plug-in. + + * examples/cppunittest/CppUnitTestSuite.cpp: updated. Use new + helper macros to create the test suite hierarchy. + + * examples/simple/simple_plugin.opt: added. Contains debug tab + settings. + + * examples/ClockerPlugIn/ClockerListener.cpp: + * examples/ClockerPlugIn/ClockerListener.h: + * examples/ClockerPlugIn/Timer.cpp: + * examples/ClockerPlugIn/Timer.h: + * examples/ClockerPlugIn/WinNtTimer.cpp: + * examples/ClockerPlugIn/WinNtTimer.h: + * examples/ClockerPlugIn/ClockerPlugIn.cpp: + * examples/ClockerPlugIn/ClockerPlugIn.dsp: added. test listener + plug-in that times tests. + + * examples/DumperPlugIn/DumperListener.cpp: + * examples/DumperPlugIn/DumperListener.h: + * examples/DumperPlugIn/DumperPlugIn.cpp: + * examples/DumperPlugIn/DumperPlugIn.dsp: added. test listener + plug-in that dump the test tree. + + +2002-04-19 Baptiste Lepilleur + + * src/cppunit/PlugInManager.cpp: fixed bug in unload(). + + * include/cppunit/TypeInfoHelper.h: + * src/cppunit/TypeInfoHelper.cpp: Implementation is now always available + is CPPUNIT_HAVE_RTTI is not 0. This removes the need to use + different libraries. CPPUNIT_USE_TYPEINFO_NAME can be set on a + case by case basis for HelperMacros. + + * src/cppunit/TestFactoryRegistry.cpp: removed unused include of + TypeInfoHelper.h. + + * include/cppunit/TextTestProgressListener.h: + * src/cppunit/TextTestProgressListener.cpp: used endTest() instead + of done() to finalize. + + * src/msvc6/TestPlugInRunner/TestPlugIn.h: + * src/msvc6/TestPlugInRunner/TestPlugIn.cpp: updated to use the + new test plug-in system. + + * examples/simple/SimplePlugIn.cpp: + * examples/simple/simple_plugin.dsp: crossplatform test plug-in + example using 'simple'. + + * examples/msvc6/EasyTestPlugIn/*: projects replaced with the + crossplatform projecct examples/simple/simple_plugin.dsp. + +2002-04-19 Baptiste Lepilleur + + * configure.in: added some makefile.am + + * contrib/readme.txt: updated. + + * contrib/bc5/bc5-makefile.zip: added borland 5.5 makefile. Contributed by + project cuppa. + + * src/cppunit/TypeInfoHelper.cpp: fixed implementation to be more + portable. + + +2002-04-18 Baptiste Lepilleur + + * bumped version to 1.9.3 + + * FAQ: added question about 4786 warning on VC++. + + * NEWS: updated. + + * contrib/msvc/readme.txt: moved to contrib/readme.txt. + + * contrib/xml-xsl/report.xsl: added XML style sheet contributed by + 'cuppa' project team (http://sourceforge.jp/projects/cuppa/) + + * examples/cppunittest/TestResultTest.h: + * examples/cppunittest/TestResultTest.cpp: added tests for + startTestRun()/endTestRun(). + + * examples/simple/*: added. A simple example. + + * include/cppunit/BriefTestProgressListener.h: + * src/cppunit/BriefTestProgressListener.cpp: added. Verbose progess listener + that print the test name before running the test. + + * include/cppunit/TestListener.h: added startTestRun()/endTestRun(). + + * include/cppunit/TestResult.h: + * src/cppunit/TestResult.cpp: added runTest(), to be called to run + a test by test runner. + + * src/cppunit/TextTestRunner.cpp: + * src/cppunit/TestRunner.cpp: updated to use TestResult::runTest(). + + * include/cppunit/plugin/PlugInManager.h: + * src/cppunit/PlugInManager.cpp: added. Managers for all loaded plug-ins. + + * include/cppunit/plugin/TestPlugInDefaultImpl.h: + * src/cppunit/TestPlugInDefaultImpl.cpp: renamed TestPlugInAdapter. All + implementations are empty. + + * include/cppunit/plugin/TestPlugInSuite.h: removed. + * src/cppunit/TestPlugInSuite.cpp: removed. Replaced by PlugInManager. + + * include/cppunit/plugin/TestPlugIn.h: rewrote the plug-in interface to + provide more versatility. updated macros to match new interface. + + * include/cppunit/extensions/TestFactoryRegistry.h: + * include/cppunit/extensions/TestFactoryRegistry.cpp: Added unregisterFactory(). + Added convenience method addRegistry(). Rewrote registry life cycle + management. AutoRegisterSuite can now detect that the registry has been + destroy and not call to it to unregister its test factory. + + * include/cppunit/extensions/AutoRegisterTest.h: on destruction, the registered + factory is unregistered from the registry. + + * include/cppunit/extensions/HelperMacros.h: added macros + CPPUNIT_REGISTRY_ADD_TO_DEFAULT and CPPUNIT_REGISTRY_ADD to help + build test suite hierarchy. + + * src/cppunit/msvc/DllPlugInTester/*: moved to src/cppunit/DllPlugInTester/. + + * src/cppunit/DllPlugInTester/DllPlugInTester.cpp: removed UNICODE stuffs. Use + the PlugInManager instead of PlugInTestSuite. Simplified: only one test on + command line, but many DLL can be specified. Added configurations to link + against cppunit dll, those are now the default configuration (static linking + don't make much sense for plug-in). + +2002-04-15 Baptiste Lepilleur + + * release 1.9.2. + + * NEWS: updated. + + * configure.in: added include/cppunit/config/Makefile and + include/cppunit/plugin/Makefile to the list of target. + + * doc/CppUnit-win.dox: enabled generation of HTML Help documentation. + + * include/cppunit/config/Makefile.am: + * include/cppunit/plugin/Makefile.am: added. + + * include/cppunit/config-bcb5.h: + * include/cppunit/config-msvc6.h: + * include/cppunit/config-mac.h: moved to include/cppunit/config/. + + * include/cppunit/Portability.h: updated config files location. Added macros + CPPUNIT_STRINGIZE and CPPUNIT_JOIN (implementation adapted from boost.org). + Added macro CPPUNIT_MAKE_UNIQUE_NAME. + + * include/cppunit/Test.h: modified methods order. + + * include/cppunit/extensions/HelperMacros.h: renamed macro + __CPPUNIT_MAKE_UNIQUE_NAME to CPPUNIT_MAKE_UNIQUE_NAME and moved its + definition to include/cppunit/Portability.h. + + * include/cppunit/extensions/TestDecorator.h: Inherits Test instead of TestLeaf. + + * include/cppunit/plugin/DynamicLibraryManager.h: + * src/cppunit/DynamicLibraryManager.cpp: added. DLL manager (load & lookup + symbol). + + * src/cppunit/BeOsDynamicLibraryManager.cpp: + * src/cppunit/UnixDynamicLibraryManager.cpp: + * src/cppunit/Win32DynamicLibraryManager.cpp: added. Implementation of + platform dependent methods of DynamicLibraryManager. + + * include/cppunit/plugin/DynamicLibraryManagerException.h: + * src/cppunit/DynamicLibraryManagerException.cpp: added. Exception thrown + by DynamicLibraryManager. + + * include/cppunit/plugin/TestPlugIn.h: added. CppUnitTestPlugIn interface + definition. Helper macros to implements plug-in. + + * include/cppunit/plugin/TestPlugInSuite.h: + * src/cppunit/plugin/TestPlugInSuite.cpp: added. A suite to wrap a test + plug-in. + + * include/cppunit/plugin/TestPlugInDefaultImpl.h: + * src/cppunit/TestPlugInDefaultImpl.cpp: added. A default implementation + of the test plug-in interface. + + * src/msvc6/DllPlugInTester/DllPlugInTester.cpp: updated to use the + new TestPlugIn. + + * examples/cppunittest/TestResultCollectorTest.cpp: fixed typo. + +2002-04-14 Baptiste Lepilleur + + * NEWS: updated. + + * include/cppunit/TestSucessListener.h: + * src/cppunit/TestSucessListener.cpp: renamed TestSuccessListener + + * doc/cookbook.dox: + * src/msvc6/DllPlugInTester/DllPlugInTester.cpp: + * examples/cppunittest/TestResultCollectorTest.h: + * examples/cppunittest/TestResultCollectorTest.cpp: + * examples/cppunittest/XmlOutputterTest.h: + * examples/cppunittest/XmlOutputterTest.cpp: + * include/cppunit/CompilerOutputter.h: + * include/cppunit/TestListener.h: + * include/cppunit/XmlOutputter.h: + * src/cppunit/XmlOutputter.cpp: + * src/cppunit/CompilerOutputter.cpp: fixed 'success' typo (was misspelled + 'sucess'). + + * include/cppunit/TestResultCollector.h: + * src/cppunit/TestResultCollector.cpp: updated (renaming of + TestSucessListener). + + * src/cppunit/XmlOutputter.cpp: + * examples/cppunittest/XmlOutputterTest.cpp: Changed SucessfulTests tag to + SucessfulTests. + +2002-04-13 Baptiste Lepilleur + + * include/cppunit/XmlOutputter.h: + * src/cppunit/XmlOutputter.cpp: Made XML output more human readable. Idented element. + + * examples/cppunittest/XmlUniformiser.h: + * examples/cppunittest/XmlUniformiser.cpp: + * examples/cppunittest/XmlUniformiserTest.cpp: modified to ignore trailing space + at the end of element content. + +2002-04-13 Baptiste Lepilleur + + * Snapshot 1.9.0 + + * NEWS: updated + + * doc/other_documentation.dox: addded new module for test plug-in. + + * include/msvc6/DSPlugin/TestRunnerDSPlugin.h: + * include/msvc6/DSPlugin/TestRunnerDSPlugin_i.c: added. Those file are + generated by project src/msvc/DSPlugin. They are provided to allow + compilation of TestRunner without compiling DSPlugIn which does not + build on VC++ 7. + + * examples/examples.dsw: removed DSPlugIn for workspace (fail to build + with VC++ 7). Added DllPlugInTester.dsp to workspace. + + * examples/msvc6/TestPlugIn/TestPlugIn.dsp: added post-build unit testing + using the new DllPlugInTester. + + * examples/msvc6/EasyTestPlugIn/*: a new project that + demonstrates the use of CPPUNIT_TESTPLUGIN_IMPL to create a test plug-in. + + * src/cppunit/cppunit.dsw: + * src/TestPlugInRunner.dsw: + * src/TestRunner.dsw: removed. Should use src/CppUnitLibraries.dsw instead. + + * include/cppunit/ui/text/TestRunner.h: + * src/cppunit/TextTestRunner.cpp: removed findTestName() method. Replaced + by Test::findTest(). + + * src/msvc6/DSPlugIn/DSPlugIn.dsp: + * src/msvc6/DSPlugIn/DSAddIn.h: changed include for add-in. MIDL generates + files in sub-directory ToAddToDistribution. Generated file should be + copied to include/msvc6/DSPlugin when modified. This remove the dependecy + of MfcTestRunner on DSPlugIn. + + * src/msvc6/testrunner/ListCtrlFormatter.h: + * src/msvc6/testrunner/ListCtrlFormatter.cpp: added GetNextColumnIndex(). + + * src/msvc6/testrunner/src/TestRunnerDlg.h: + * src/msvc6/testrunner/src/TestRunnerDlg.cpp: set column number in + MsDevCallerListCtrl when initializing the list. + + * src/msvc6/testrunner/src/MsDevCallerListCtrl.h: + * src/msvc6/testrunner/src/MsDevCallerListCtrl.cpp: column indexes for + file and line number are no longer static. Added methods to set those + indexes. Changed DSPlugIn header name. + + * include/msvc6/testrunner/TestPlugInInterface.h: fixed inclusion of + windows header for WINAPI. Added macro CPPUNIT_TESTPLUGIN_IMPL to + automatically implements a test plug-in. + + * src/msvc6/DllPlugInTester/*: added new project. A application to test DLL + and report using CompilerOutputter. Target for post-build testing and + debugging of DLL. + + +2002-04-13 Baptiste Lepilleur + + * include/cppunit/CompilerOutputter.h: + * src/cppunit/CompilerOutputter.h: deprecated defaultOuputter(). Added + setLocationFormat() and format specifiation in constructor. A string + that represent the location format is used to output the location. + Default format is defined by CPPUNIT_COMPILER_LOCATION_FORMAT. + + * include/cppunit/config-msvc6.h: + * include/cppunit/Portability.h: added CPPUNIT_COMPILER_LOCATION_FORMAT. + Use gcc location format if VC++ is not detected. + + * include/cppunit/Test.h: fixed documentation. + + * include/cppunit/TestListener.h: added startSuite() and endSuite() + callbacks. Added new example to documentation. + + * include/cppunit/TestResult.h: + * src/cppunit/TestResult.cpp: + * include/cppunit/TestComposite.h: + * src/cppunit/TestComposite.cpp: Updated to inform the listeners. + + * src/qttestrunner/TestBrowserDlgImpl.cpp: used Test new composite + interface instead of RTTI to explore the test hierarchy. + + * examples/cppunittest/MockTestListener.h: + * examples/cppunittest/MockTestListener.cpp: updated,added support for + startSuite() and endSuite(). + + * examples/cppunittest/TestResultTest.h: + * examples/cppunittest/TestResultTest.cpp: added tests for startSuite() + and endSuite(). + +2002-04-12 Baptiste Lepilleur + + * Makefile.am: added examples/qt to tar ball release. + + * TODO: heavily updated. + + * contrib/msvc/CppUnit*.wwtpl: changed base class for unit test to TestFixture. + + * include/cppunit/Test.h: removed toString() method. Not used by the framework + and source of confusions with getName(). + Added getChildTestCount() and getChildTestAt(), introducing the composite pattern + at top level. Added utility methods findTest() and findTestPath(). + + * src/cppunit/Test.cpp: added. Implementation of new utility methods. + + * include/cppunit/TestCase.h: + * src/cppunit/TestCase.cpp: inherits TestLeaf. Removed toString(), run(void) and + defaultResult(). Removed default constructor. + + * src/cppunit/TestCase.cpp: + * src/cppunit/TestSuite.cpp: fixed some includes that used "" instead of <>. + + * include/cppunit/TestComposite.h: + * src/cppunit/TestComposite.cpp: added. Common implementation of Test for composite + tests (TestSuite). + + * include/cppunit/TestFailure.h: + * src/cppunit/TestFailure.cpp: removed toString(). + + * include/cppunit/TestLeaf.h: + * src/cppunit/TestLeaf.cpp: added. Common implementation of Test for single test + (TestCase). + + * include/cppunit/TestListener.h: added TimingListener example to documentation. + + * include/cppunit/TestPath.h: + * src/cppunit/TestPath.cpp: added. List of test traversed to access a test in the + test hierarchy. + + * include/cppunit/TestRunner.h: added. Generic TestRunner. + + * src/cppunit/TestRunner.cpp: moved to TextTestRunner.cpp. Added new implementation + of includecppunit/TestRunner.h. + + * include/cppunit/TestSuite.h: + * src/cppunit/TestSuite.cpp: inherits TestComposite and implements new Test + interface. Removed toString(). + + * src/cppunit/TextTestRunner.cpp: moved from TestRunner.cpp. Implementation of + include/cppunit/ui/text/TestRunner.h. + + * include/cppunit/extensions/RepeatedTest.h: + * src/cppunit/RepeatedTest.cpp: removed toString(). + + * include/cppunit/extensions/TestDecorator.h: inherits TestLeaf. + Removed toString() + + * include/cppunit/XmlOutputter.h: + * src/cppunit/XmlOutputter.cpp: + * examples/cppunittest/XmlOutputterTest.cpp: + * examples/cppunittest/XmlOutputterTest.h: XML outputter now escape node content. + Add unit test for that bug (#540944). Added style sheet support. Modified + XML structure: failure message as its own element. + + * src/msvc/testrunner/TestRunnerModel.h: + * src/msvc/testrunner/TestRunnerModel.cpp: used Test::findTest() to find a test + by name instead of using RTTI. Added toAnsiString() for convertion when + compiling as UNICODE. + + * src/msvc/testrunner/TreeHierarchyDlg.h: + * src/msvc/testrunner/TreeHierarchyDlg.cpp: used new composite interface of Test + to explorer the test hierarchy instead of RTTI. + + * examples/cppunittest/TestPathTest.h: + * examples/cppunittest/TestPathTest.cpp: added, unit tests for TestPath. + + * examples/cppunittest/TestCaseTest.h: + * examples/cppunittest/TestCaseTest.cpp: added test for TestLeaf. + + * examples/cppunittest/TestSuiteTest.h: + * examples/cppunittest/TestSuiteTest.cpp: added test for TestComposite and + new Test interface. + +2002-04-11 Baptiste Lepilleur + + * configure.in: bumped version to 1.9.0 + + * NEWS: added version 1.9.0 + +2002-04-11 Baptiste Lepilleur + + * doc/FAQ: removed question about the Exception::operator =() problem. + + * release 1.8.0 + +2002-04-11 Steve M. Robbins + + * include/cppunit/ui/mfc/Makefile.am: + * include/cppunit/ui/qt/Makefile.am: + * include/cppunit/ui/text/Makefile.am: Set the libcppunitincludedir + variable. Correct case of header file ui/qt/Config.h. + + * configure.in: Output the new include/*/Makefiles. + +2002-04-10 Baptiste Lepilleur + + * Makefile.am: removed directory cppunitui from copy when making + the dist. + + * include/cppunit/ui: added Makefile.am for dist and install. + +2002-04-10 Baptiste Lepilleur + + * include/cppunitui/: moved to include/cppunit/ui (fix unix + install problem). + + * doc/cookbook.dox: + * examples/cppunittest/CppUnitTestMain.cpp: + * examples/msvc/CppUnitTestApp/HostApp.cpp: + * examples/msvc/HostApp/HostApp.cpp: + * examples/qt/Main.Cpp: + * examples/src/cppunit/TestRunner.cpp: + * examples/src/msvc6/TestRunner/TestRunner.cpp: + * examples/src/qttestrunner/TestRunner.cpp: updated to use + instead of in include directives. + + * doc/CppUnit-win.dox: generated documentation give the include + path at the bottom of the page for each class. + + * NEWS: added compatibility break for 1.7.10 users. + +2002-04-05 Baptiste Lepilleur + + * examples/cppunittest/CppUnitTestMain.cpp: never wait for a key press. + +2002-04-04 Baptiste Lepilleur + + * NEW: added CPPUNIT_ASSERT_EQUAL_MESSAGE compatiblity break. + + * include/cppunit/TestAssert.h: changed arguments order for + CPPUNIT_ASSERT_EQUAL_MESSAGE. 'message' is now the first argument + instead of the last (like CPPUNIT_ASSERT_MESSAGE). + + * examples/cppunittest/MockTestCase.cpp: + * examples/cppunittest/MockTestListener.cpp: updated to reflect + change on CPPUNIT_ASSERT_EQUAL_MESSAGE. + +2002-03-28 Baptiste Lepilleur + + * configure.in: bumped version to 1.7.11 + +2002-03-28 Baptiste Lepilleur + + * doc/cookbook.html: removed. Replaced by cookbook.doc. + + * doc/cookbook.dox: added, conversion of cookbook.html to Doxygen + format. + + * doc/other_documentation.dox: added groups definition. + + * doc/Makefile.am: replaced cookbook.html by cookbook.dox + + * doc/Doxyfile.in: added predefined CPPUNIT_HAVE_CPP_SOURCE_ANNOTATION. + Replaced cookbook.html by cookbook.dox. + + * include/cppunitui/mfc/TestRunner.h: added, extracted from + include/msvc6/testrunner/TestRunner.h. Moved class TestRunner to + namespace CppUnit::MfcUi. + + * include/msvc6/testrunner/TestRunner.h: deprecated. A simple + typedef to CppUnit::MfcUi::TestRunner. + + * include/textui/TestRuner.h: added, extracted from + include/cppunit/TextTestRunner.h. + + * src/cppunit/TextTestRunner.cpp: renamed TestRunner.cpp. Moved + into namespace CppUnit::TextUi. + + * src/msvc6/testruner/TestRunner.cpp: moved into namespace + CppUnit::MfcUi. + + * src/cppunit/CompilerOutputter.cpp: removed printing "- " before + NotEqualException addional message, for consistency between + different TestRunner (Mfc,Text...) + + * include/cppunit/Asserter.h: + * include/cppunit/CompilerOutputter.h: + * include/cppunit/Exception.h: + * include/cppunit/NotEqualException.h: + * include/cppunit/Outputter.h: + * include/cppunit/SourceLine.h: + * include/cppunit/TestAssert.h: + * include/cppunit/TestCaller.h: + * include/cppunit/TestFailure.h: + * include/cppunit/TestFixture.h: + * include/cppunit/TestListener.h: + * include/cppunit/TestResult.h: + * include/cppunit/TestResultCollector.h: + * include/cppunit/TestSucessListener.h: + * include/cppunit/TestSuite.h: + * include/cppunit/TextTestProgressListener.h: + * include/cppunit/TextTestRunner.h: + * include/cppunit/XmlOutputter.h: + * include/cppunit/extensions/AutoRegisterSuite.h: + * include/cppunit/extensions/HelperMacros.h: + * include/cppunit/extensions/TestFactoryRegistry.h: + * include/cppunit/extensions/TestSuiteBuilder.h: + * include/cppunit/extensions/TestSuiteFactory.h: doc + update. organization in groups. + + * examples/msvc6/CppUnitTestApp/CppUnitTestApp.cpp: + * examples/msvc6/HostApp/HostApp.cpp: updated to use + CppUnit::MfcUi::TestRunner. + + * examples/cppunittest/CppUnitTestMain.cpp: updated to use + CppUnit::TextUi::TestRunner. + +2002-03-27 Baptiste Lepilleur + + * include/msvc/testrunner/TestRunner.h: updated doc. reindented. + + * include/cppunit/Asserter.h: + * include/cppunit/Asserter.cpp: + * include/cppunit/TestResultCollector.h: + * include/cppunit/TestResult.h: + * include/cppunit/SynchronizedObject.h: + * include/cppunit/extensions/TestCaller.h: doc update. + + * include/cppunitui/qt/TestRunner.h: doc update. + +2002-03-27 Baptiste Lepilleur + + * makefile.am: added src/CppUnitLibraries.dsw, new contribution, and + src/qttestrunner. + + * TODO: updated (doc). + + * contrib/msvc/AddingUnitTestMethod.dsm: added, submitted by + bloodchen@hotmail.com. + + * constrib/msvc/readme.txt: updated. + + * include/cppunit/TestAsserter.h: + * include/cppunit/SourceLine.h: updated doc. + + * include/cppunit/TestCaller.h: reindented. updated doc. + + * include/cppunit/extensions/HelperMacros.h: relaxed constraint on fixture. + Fixture base class may be TestFixture instead of TestCase. + + * include/cppunit/TestCase.h: + * src/cppunit/TestCase.h: TestCase inherits TestFixture for setUp() and + tearDown() definition. Moved documentation to TestFixture. + + * include/cppunit/TestFixture.h: updated documentation. + + * include/cppunit/TestRegistry.h: + * src/cppunit/TestRegistry.cpp: Removed. Replaced by TestFactoryRegistry. + + * include/cppunit/TextTestRunner.h: + * src/cppunit/TextTestRunner.cpp: made printing progress using a + TextTestProgressListener optional. + + * examples/cppunittest/ExceptionTest.h: + * examples/cppunittest/HelperMacrosTest.h: + * examples/cppunittest/HelperMacrosTest.cpp: + * examples/cppunittest/NotEqualException.h: + * examples/cppunittest/OrthodoxTest.h: + * examples/cppunittest/RepeatedTest.h: + * examples/cppunittest/TestAssertTest.h: + * examples/cppunittest/TestCallerTest.h: + * examples/cppunittest/TestDecoratorTest.h: + * examples/cppunittest/TestFailureTest.h: + * examples/cppunittest/TestResultCollectorTest.h: + * examples/cppunittest/TestResultTest.h: + * examples/cppunittest/TestSetUpTest.h: + * examples/cppunittest/TestSuiteTest.h: + * examples/cppunittest/XmlOutputterTest.h: + * examples/cppunittest/XmlOutputterTest.cpp: + * examples/cppunittest/XmlUniformizerTest.h: + * examples/cppunittest/XmlUniformizerTest.cpp: changed base class for fixture + from TestCase to TestFixture. + + * examples/hierarchy/BoardGameTest.h: + * examples/hierarchy/ChessTest.h: + * examples/hierarchy/main.cpp: updated to use HelperMacros for correct + fixture instantiation (the ChessBoard::testReset test case was using + BoardGame fixture instance instead of ChessBoard). + +2002-03-26 Baptiste Lepilleur + + * configure.in: bumped version to 1.7.9 + +2002-03-26 Baptiste Lepilleur + + * src/msvc6/testpluginrunner/TestPlugInRunner.dsp: fixed release configuration. + +2002-03-25 Baptiste Lepilleur + + * include/cppunit/makefile.am: removed TestRegistry.h + + * include/cppunit/TestRegistry.h: removed. Obsolete, replaced by + TestFactoryRegistry. + + * src/cppunit/makefile.am: removed TestRegistry.cpp. Added cppunit_dll.dsp. + + * include/cppunit/CompilerOutputter.h: + * include/cppunit/NotEqualException.h: + * include/cppunit/SynchronizedObject.h: + * include/cppunit/TestFixture.h: + * include/cppunit/TestListener.h: + * include/cppunit/TestResult.h: + * include/cppunit/TestSucessListener.h: + * include/cppunit/TextOutputter.h: + * include/cppunit/TextTestProgressListener.h: + * include/cppunit/TextTestResult.h: + * include/cppunit/XmlOutputter.h: + * include/cppunit/extensions/TestFactory.h: + * include/cppunit/extensions/TestFactoryRegistry.h: + * include/cppunit/extensions/TestSuiteBuilder.h: + * include/cppunit/extensions/TestSuiteFactory.h: minor doc update. + + * include/cppunit/TestFixture.h: added DLL export. + + * include/cppunit/msvc6/TestPlugInInterface.h: updated doc. Added automatic + exportation of TestPlugIn publishing function. + + * src/cppunit/TestCase.cpp: + * include/cppunit/TestCase.h: inherits setUp() and tearDown() from + class TestFixture. + +2002-03-25 Baptiste Lepilleur + + * configure.in: bumped version to 1.7.7 + +2002-03-25 Baptiste Lepilleur + + * include/cppunit/config-msvc6.h: + * include/cppunit/Portability.h + * include/cppunit/extensions/TestFactoryRegistry.h + * include/cppunit/TestResult.h + * include/cppunit/TestResultCollector.h + * include/cppunit/TestSuite.h + * include/cppunit/TextTestRunner.h + * include/cppunit/XmlOutputter.h: removed warning when compiling CppUnit + as DLL. + + * src/cppunit/DllMain.cpp: added some defines to speed up compilation a bit. + +2002-03-25 Baptiste Lepilleur + + * INSTALL-WIN32.txt: updated for MFC Unicode TestRunner. + + * src/msvc6/testrunner/TestRunner.dsp: added Unicode configurations. + + * src/msvc6/testrunner/ListCtrlSetter.cpp: + * src/msvc6/testrunner/ListCtrlSetter.h: replaced usage of std::string by + CString for easier ansi/unicode switch. + + * src/msvc6/testrunner/MsDevCallerListCtrl.cpp: + * src/msvc6/testrunner/TestRunnerDlg.cpp: + * src/msvc6/testrunner/TestRunnerModel.cpp: + * src/msvc6/testrunner/TestRunnerModel.h: + * src/msvc6/testrunner/TreeHierarchyDlg.cpp: made changes to compile with + either ANSI and UNICODE support. + + * examples/msvc6/HostApp/HostApp.cpp: + * examples/msvc6/HostApp/HostApp.h: + * examples/msvc6/HostApp/HostAppDoc.cpp: + * examples/msvc6/HostApp/HostAppDoc.h: moved TestRunner execution to + HostApp::RunUnitTests() and removed the MainFrame application window. + + * examples/msvc6/HostApp/HostApp.dsp: added Unicode configurations. + +2002-03-24 Baptiste Lepilleur + + * INSTALL-WIN32.txt: added some info to build cppunit as a DLL. + + * include/cppunit/config-msvc6.h: added definition of macro CPPUNIT_API + when building or linking DLL. Defined CPPUNIT_BUILD_DLL when building, and + CPPUNIT_DLL when linking. + + * include/cppunit/Portability.h: added empty definition of macro + CPPUNIT_API when not building or using CppUnit as a DLL. When any of + those symbol is defined, the symbol CPPUNIT_NEED_DLL_DECL is set to 1. + + * include/cppunit/extensions/RepeatedTest.h: + * include/cppunit/extensions/TestDecorator.h: + * include/cppunit/extensions/TestSetUp.h: + * include/cppunit/TestCaller.h + * include/cppunit/extensions/TestFactory.h + * include/cppunit/extensions/TestFactoryRegistry.h + * include/cppunit/extensions/TypeInfoHelper.h + * include/cppunit/Asserter.h + * include/cppunit/Exception.h + * include/cppunit/NotEqualException.h + * include/cppunit/SourceLine.h + * include/cppunit/SynchronizedObject.h + * include/cppunit/Test.h + * include/cppunit/TestAssert.h + * include/cppunit/TestCase.h + * include/cppunit/TestFailure.h + * include/cppunit/TestListener.h + * include/cppunit/TestResult.h + * include/cppunit/TestSuite.h + * include/cppunit/CompilerOutputter.h + * include/cppunit/Outputter.h + * include/cppunit/TestResultCollector.h + * include/cppunit/TestSuccessListener.h + * include/cppunit/TextOutputter.h + * include/cppunit/TextTestProgressListener.h + * include/cppunit/TextTestResult.h + * include/cppunit/TextTestRunner.h + * include/cppunit/XmlOutputter.h: added CPPUNIT_API for DLL export. + + * include/cppunit/TestSuite.h: + * src/cppunit/TestSuite.cpp: reindented + + * include/cppunit/extensions/TestSetUp.h: + * src/cppunit/TestSetUp.cpp: added .cpp. extracted inline method and moved + them to cpp file. + + * src/cppunit/DllMain.cpp: added, contains Dll entry point. + +2002-03-06 Baptiste Lepilleur + + * src/cppunit/TextTestProgressListener.cpp: flush the stream after each + progess step. + +2002-03-03 Baptiste Lepilleur + + * configure.in: updated version number to 1.7.4 + +2002-03-03 Baptiste Lepilleur + + * include/cppunit/makefile.am: + * src/cppunit/makefile.am: added missing SynchronizedObject and + TextOutputter.h. + + * generated 1.7.3 tar ball. + +2002-02-29 Baptiste Lepilleur + + * inclued/cppunit/XmlOutputter.h: + * inclued/cppunit/XmlOutputter.cpp: added optional parameter to constructor + to specify the encoding. + + * configure.in: updated version number to 1.7.3 + +2002-02-28 Baptiste Lepilleur + + * NEW: updated and restructured. + + * include/cppunit/CompilerOutputter.h: + * src/cppunit/CompilerOutputter.cpp: + updated against TestResultChange. Changed TestResult to TestResultCollector. + + * include/cppunit/extensions/HelperMacros.h: minor documentation fix. + + * include/cppunit/Outputter.h: added. Abstract base class for all Outputter. + + * include/cppunit/Portability.h: made the fix on OStringStream suggested by + Bob Summerwill to remove level 4 warning with VC++. + + * include/cppunit/TestAssert.h: added macro CPPUNIT_ASSERT_EQUAL_MESSAGE. + + * src/cppunit/TestFailure.cpp: + * include/cppunit/TestFailure.h: added method clone() to duplicate a + failure. Made all method virtual. + + * include/cppunit/TestListener.h: changed signature of addFailure() to + addFailure( const TestFailure &failure ). Failure is now only a temporary + object. + + * include/cppunit/Outputter.h: added. Abstract base class for all + outputter. Used by TextTestRunner. + + * include/cppunit/SynchronizedObject.h: + * src/cppunit/SynchronizedObject.cpp: added. Class extracted from + TestResult. Base class for objects that can be accessed from different + threads. + + * include/cppunit/TestResult.h: TestFailure.h is no longer included. + + * include/cppunit/TestResult.h: + * src/cppunit/TestResult.cpp: extracted all methods related to keeping track + of the result to the new TestResultCollector class which is a TestListener. + + * include/cppunit/TestResultCollector.h: + * src/cppunit/TestResultCollector.cpp: added. TestListener which kept track + of the result of the test run. All failure/error, and tests are tracked. + + * include/cppunit/TestSucessListener.h: + * src/cppunit/TestSucessListener.cpp: added. TestListener extracted from + TestResult. Is responsible for wasSucessful(). + + * include/cppunit/TestCase.h: + * src/cppunit/TestCase.cpp: reindented. + + * include/cppunit/TextOutputter.h: + * src/cppunit/TextOutputter.cpp: added. Copied from the deprecated + TextTestResult and modified to act as an Ouputter. + + * include/cppunit/TextTestProgressListener.h: + * src/cppunit/TextTestProgressListener.cpp: Copied from the deprecated + TextTestResult and modified to print the dot while the test are running. + + * include/cppunit/TextTestResult.h: + * src/cppunit/TextTestResult.cpp: updated against TestResult change. + No compatiblity break. Deprecated. + + * include/cppunit/TextTestRunner.h: + * src/cppunit/TextTestRunner.cpp: updated to work with the new TestResult. + Use TextTestProgressListener and TextOutputter instead of TextTestResult. + Any outputter with interface Outputter can be used to print the test result + (CompilerOutputter, XmlOutputter, TextOutputter...) + + * include/cppunit/XmlOutputter.h: + * src/cppunit/XmlOutputter.cpp: updated against TestResultChange. + Changed TestResult to TestResultCollector. + + * src/msvc6/TestRunnerDlg.h: + * src/msvc6/TestRunnerDlg.cpp: fixed the 'fullrowselect' feature of the + list view. The dialog is a TestListener itself, it no longer use the + GUITestResult class. + + * src/msvc6/TestRunner.rc: moved the "autorun test button" in such a way that + it did not overlap the progress bar anymore. + + * src/msvc6/MfcSynchronizationObject.h: added. Generic SynchronizedObject + lock for MFC. + + * src/msvc6/GUITestResult.h : + * src/msvc6/GUITestResult.cpp : removed. + + * src/qttestrunner/TestRunnerModel.h: + * src/qttestrunner/TestRunnerModel.cpp: changed addFailure() signature to + reflect change on TestListener. + + * examples/cppunittest/CppUnitTestMain.cpp: updated to use the new Outputter + abstraction and TextTestRunner facilities. + + * examples/cppunittest/FailingTestCase.h: + * examples/cppunittest/FailingTestCase.cpp: removed. Replaced by MockTestCase. + + * examples/cppunittest/FailingTestCase.h: + * examples/cppunittest/FailingTestCase.h: + + * examples/cppunittest/HelperMacrosTest.h: + * examples/cppunittest/HelperMacrosTest.cpp: Updated against TestResult change. + Use MockTestListener instead of TestResult to check for sucess or failure. + + * examples/cppunittest/MockTestListener.h: + * examples/cppunittest/MockTestListener.cpp: the class now behave like a mock + object. + + * examples/cppunittest/MockTestCase.h: + * examples/cppunittest/MockTestCase.cpp: added. Mock TestCase object. + + * examples/cppunittest/OrthodoxTest.h: + * examples/cppunittest/OrthodoxTest.cpp: Updated against TestResult change. + Use MockTestListener instead of TestResult to check for sucess or failure. + + * examples/cppunittest/SynchronizedTestResult.h: Updated against TestResult + change. + + * examples/cppunittest/TestCallerTest.h: + * examples/cppunittest/TestCallerTest.cpp: Updated against TestResult change. + Use MockTestListener instead of TestResult. + + * examples/cppunittest/TestCaseTest.h: + * examples/cppunittest/TestCaseTest.cpp: Updated against TestResult change. + Use MockTestListener and MockTestCase instead of FailingTestCase and TestResult. + + * examples/cppunittest/TestDecoratorTest.h: + * examples/cppunittest/TestDecoratorTest.cpp: Updated against TestResult change. + Use MockTestCase instead of FailingTestCase. + + * examples/cppunittest/TestListenerTest.h: + * examples/cppunittest/TestListenerTest.cpp: removed. Those unit tests have been + rewrote and moved to TestResultTest. + + * examples/cppunittest/TestResultTest.h: + * examples/cppunittest/TestResultTest.cpp: Updated to test the new interface. + Tests from TestListenerTest have been moved here. + + * examples/cppunittest/TestResultCollectorTest.h: + * examples/cppunittest/TestResultCollectorTest.cpp: added. Tests for the class + that been extracted from TestResult. + + * examples/cppunittest/TestSetUpTest.h: + * examples/cppunittest/TestSetUpTest.cpp: renamed SetUp inner class to MockSetUp. + Changed interface to be more akin to a Mock object. + + * examples/cppunittest/TestSuiteTest.h: + * examples/cppunittest/TestSuiteTest.cpp: Updated against TestResult change, + and rewrote to use MockTestCase instead of FailingTestCase. + + * examples/cppunittest/XmlOutputterTest.h: + * examples/cppunittest/XmlOutputterTest.cpp: Updated against TestResult change. + Added some utility methods to make the update easier. + +2001-10-28 Steve M. Robbins + + * INSTALL-unix: Add note about cygwin. + +2001-10-24 Baptiste Lepilleur + + * examples/msvc6/CppUnitTestApp/CppUnitTestApp.dsp: + * examples/msvc6/HostApp/HostApp.dsp: use custom file build instead + of post-build/pre-link step to copy the TestRunner DLL to the + Release/Debug directory. + + * src/msvc6/ProgressBar.cpp: + * src/msvc6/ProgressBar.h: + * src/msvc6/TestRunner.rc: + * src/msvc6/TestRunnerDlg.cpp: + * src/msvc6/TestRunnerDlg.h: + * src/msvc6/testRunner.dsp: + * src/msvc6/TestRunnerModel.cpp: + * src/msvc6/TestRunnerModel.h: included Gigi Sayfan (gigi@morphink.com) + patch. The dialog can now be resized, and list view columns and dialog + sizes are saved. + + * src/msvc6/ProgressBar.cpp: + * src/msvc6/ProgressBar.h: Minor refactoring. + + * THANKS: added Gigi Sayfan to the list. + +2001-10-21 Steve M. Robbins + + * configure.in: Bump version to 1.7.2. + + * Release 1.7.1 (alpha). + + * Merged changes from cvs BRANCH_1_6; details follow. + + * examples/cppunittest/TestSetUpTest.h (class SetUp): Add + namespace qualifier to CppUnit::TestSetup() constructor call. + + * include/cppunit/Makefile.am (dist-hook): Restore hook to + remove config-auto.h from distribution. + + * doc/Makefile.am: Move the definition of htmldir inside if DOC + conditional. Add "else" branch to conditional with dummy targets + for install-data-hook and uninstall-local. Move all-local outside + the conditional, and move "dox" target into both branches of the + conditional. + +2001-10-20 Steve M. Robbins + + * examples/cppunittest/Makefile.am (cppunittestmain_SOURCES): + Include XmlUnformiserTest files. + + * doc/Doxyfile.in (GENERATE_MAN): Do not generate man pages. + * doc/Makefile.am: Do not make man directories. + +2001-10-19 Baptiste Lepilleur + + * include/cppunit/Exception.h: + * src/cppunit/Exception.cpp: what(), added back the throw() qualifier. + +2001-10-14 Baptiste Lepilleur + + * include/cppunitui/* : added, Qt TestRunner. + + * examples/qt/* : added, example showing the use of Qt TestRunner. + + * src/qttestrunner : added, source of the Qt TestRunner DLL. + +2001-10-08 Steve M. Robbins + + * src/cppunit/Exception.cpp (what): Remove "throw()" qualifier, to + match earlier change to header. + +2001-10-07 Baptiste Lepilleur + + * include/cppunit/CompilerTestResultOutputter.h : + renamed CompilerOutputter.h + + * src/cppunit/CompilerTestResultOutputter.cpp : + renamed CompilerOutputter.cpp + + * include/cppunit/CompilerTestResultOutputter.h : + * src/cppunit/CompilerTestResultOutputter.cpp : ajust max line length + for wrapping. Added static factory method defaultOutputter(). Print + the number of test runs on success. + + * include/cppunit/CompilerTestResultOutputter.h : renamed + CompilerOutputter.h. + + * src/cppunit/CompilerTestResultOutputter.cpp : renamed + CompilerOutputter.cpp. + + * examples/cppunittest/CppUnitTestMain.cpp : use factory method + CompilerTestResultOutputter::defaultOutputter(). + + * src/msvc6/DSPlugIn/DSPlugIn.dsp : removed COM registration in + post-build step. IT is automatically done by VC++ when the add-in is + added. Caused build to failed if the add-in was used in VC++. + + * NEWS : updated. + + * src/cppunit/TestAssert.cpp : modified deprecated assert + implementations to use Asserter. + + * examples/cppunittest/XmlTestResultOutputterTest.h : + renamed XmlOutputterTest.h. + + * examples/cppunittest/XmlTestResultOutputterTest.cpp : + renamed XmlOutputterTest.cpp. + + * NEWS : + * examples/cppunittest/CppUnitTestMain.cpp : + * examples/cppunittest/CppUnitTestMain.dsp : + * examples/cppunittest/Makefile.am : + * examples/cppunittest/XmlTestResultOutputterTest.h : + * examples/cppunittest/XmlTestResultOutputterTest.cpp : + * examples/msvc6/CppUniTestApp/CppUnitTestApp.dsp + * include/cppunit/CompilerOutputter.h : + * include/cppunit/Makefile.am : + * include/cppunit/XmlTestResultOutputter.h : + * src/cppunit/CompilerOutputter.cpp : + * src/cppunit/cppunit.dsp : + * src/cppunit/Makefile.am : + * src/cppunit/XmlTestResultOutputter.cpp : change due to renaming + CompilerTestResultOutputter to CompilerOutputter, + XmlTestResultOutputter to XmlOuputter, XmlTestResultOutputterTest + to XmlOutputterTest. + +2001-10-06 Baptiste Lepilleur + + * include/cppunit/CompilerTestResultOutputter.h : + * src/cppunit/CompilerTestResultOutputter.cpp : added. Output result + in a compiler compatible format. + + * src/cppunit/CppUnit.dsp : + * include/cppunit/MakeFile.am : + * src/cppunit/MakeFile.am : added CompilerTestResultOutputter.cpp + and CompilerTestResultOutputter.h. + + * examples/cppunittest/CppUnitTestMain.cpp : if -selftest is specified + on the command line, no standard test result are printed, but compiler + compatible result at printed. + + * examples/cppunittest/CppUnitTestMain.dsp : added post-build step to + run the test suite with -selftest. + + * NEWS : updated. + + * src/cppunit/TextTestRunner.cpp : skip a line after printing + progress. + +2001-10-06 Baptiste Lepilleur + + * examples/cppunittest/CppUnitTestMain.cpp : application returns + 0 is test suite run sucessfuly, 1 otherwise. + + * src/cppunit/Exception.cpp : bug fix, operator =() with VC++. + Removed call to std::exception::operator =() which is bugged + on VC++. + + * doc/FAQ : added a note explaining why the test + ExceptionTest.testAssignment used to fail. + + * NEWS : updated and detailed. + + * include/cppunit/TestResult.h : + * src/cppunit/TestResult.cpp : added reset(). + + * include/cppunit/TextTestRunner.h : + * src/cppunit/TextTestRunner.cpp : Constructor take an optional + TextTestRestult. The TextTestResult remain alive as long as + the runner. Added result() to retreive the result. Printing the + result is now optinal (enabled by default). + +2001-10-05 Baptiste Lepilleur + + * include/cppunit/Asserter.h : + * src/cppunit/Asserter.cpp : added. Helper to create assertion macros. + + * src/cppunit/cppunit.dsp : + * src/cppunit/Makefile.am : + * include/cppunit/Makefile.am : added Asserter.h and Asserter.cpp. + + * include/cppunit/Exception.h : + * src/cppunit/Exception.cpp : added constructor that take a + SourceLine argument. Deprecated static constant and old constructor. + Fixed some constness issues. + + * examples/cppunittest/ExceptionTest.cpp : Refactored. + + * NEWS : partially updated (need to be more detailed) + + * include/cppunit/NotEqualException.h : + * src/cppunit/NotEqualException.cpp : added constructor that take a + SourceLine argument. Deprecated old constructor. Added a third element + to compose message. + + * examples/cppunittest/NotEqualExceptionTest.cpp : moved to "Core" + suite. Added test for SourceLine() and additionalMessage(). + Refactored. + + * include/cppunit/SourceLine.h : + * src/cppunit/SourceLine.cpp : added. Result of applying + IntroduceParameterObject refactoring on filename & line number... + + * include/cppunit/TestAssert.h : + * src/cppunit/TestAssert.cpp : deprecated old assert functions. + added functions assertEquals() and assertDoubleEquals() which use + SourceLine. + + * src/cppunit/TestCase.cpp : Modified for SourceLine. + + * include/cppunit/TestFailure.h : + * src/cppunit/TestFailure.cpp : added failedTestName(), and + sourceLine(). + + * src/msvc6/testrunner/TestRunnerDlg.cpp : modified to use SourceLine. + + * include/cppunit/TextTestResult.h : + * src/cppunit/TextTestResult.cpp : corrected include order and + switched to angled brackets. Refactored. Don't print failure location + if not available. Not equal failure dump additional message if + available. + + * src/cppunit/TextTestRunner.cpp : run() now returns a boolean to + indicate if the run was sucessful. + + * src/cppunit/XmlTestResultOutputter.cpp : replaced itoa() with + OStringStream. Refactored. + + * examples/cppunittest/XmlUniformiser.h : + * examples/cppunittest/XmlUniformiser.cpp : + CPPUNITTEST_ASSERT_XML_EQUAL capture failure location. Refactored + checkXmlEqual(). + + * examples/cppunittest/XmlUniformiserTest.h : + * examples/cppunittest/XmlUniformiserTest.cpp : added test for + CPPUNITTEST_ASSERT_XML_EQUAL. + + * include/cppunit/XmlTestResultOutputter.h : + * src/cppunit/XmlTestResultOutputter.cpp : updated to use SourceLine. + +2001-10-05 Baptiste Lepilleur + + * NEWS : updated. + + * include/cppunit/Exception.h : added include Portability.h. + + * include/cppunit/TestResult.* : changed TestFailures to a deque. + added tests(). + + * examples/cppunittest/CppUnitTest.dsp : + * examples/cppunittest/MakeFile.am : + * examples/msvc6/CppUnitTestApp/CppUnitTestApp.dsp : Added + XmlTestResultOutputterTest.*, XmlUniformiser.*, XmlUniformiserTest.*, + UnitTestToolSuite.h, OutputSuite.h. + + * examples/msvc6/CppUnitTestApp/CppUnitTestApp.dsp : revised project + folders structure. Added missing NoteEqualExceptionTest.*. + + * examples/cppunittest/CppUnitTestSuite.cpp : added 'Output' and + 'UnitTestTool' suites. + + * src/cppunit/cppunit.dsp: removed estring.h. Revised project folders + structure. Removed TestRegistry.*. Added TestSetUp.h, + XmlTestResultOutputter.*. + + * src/cppunit/MakeFile.am: added XmlTestResultOutputter.*. + + * src/testrunner/TestRunnerDlg.cpp: removed disabled code. + +2001-10-03 Baptiste Lepilleur + + * include/cppunit/TestFailure.cpp : + * include/cppunit/TestFailure.h : fixed some constness issues. Added + argument to indicate the type of failure to constructor. Added + isError(). + + * include/cppunit/TestListener.h : removed addError(). addFailure() + now take a TestFailure as argument. + + * include/cppunit/TestResult.h : + * include/cppunit/TestResult.cpp : removed errors(). Refactored. Fixed + some constness issues. Added typedef TestFailures for vector returned + by failures(). failures() returns a const reference on the list of + failure. added testFailuresTotal(). Constructor can take an optional + synchronization object. + + * include/cppunit/TextTestResult.h : + * include/cppunit/TextTestResult.cpp : removed printErrors(). + Refactored. Updated to suit new TestResult, errors and failures are + reported in the same list. + + * examples/cppunittest/TestFailureTest.cpp : + * examples/cppunittest/TestFailureTest.h : modified to use the new + TestFailure constructor. Added one test. + + * examples/cppunittest/TestListenerTest.cpp: removed addError(). + Refactored to suit new TestListener. + + * examples/cppunittest/TestResultTest.h : + * examples/cppunittest/TestResultTest.cpp : modified to suit the + new TestResult. + +2001-10-02 Baptiste Lepilleur + + * include/cppunit/extensions/TestFactoryRegistry.h + * src/cppunit/TestFactoryRegistry.cpp : fixed memory leaks that + occured when a TestFactoryRegistry was registered into another + TestFactoryRegistry. + + * include/cppunit/extensions/AutoRegisterSuite.h : updated doc. + + * include/cppunit/extensions/HelperMacros.h : added macro + CPPUNIT_TEST_SUITE_NAMED_REGISTRATION to register a suite into + a named suite. Updated doc. + + * examples/cppunittest/CoreSuite.h: + * examples/cppunittest/ExtensionSuite.h: + * examples/cppunittest/HelperSuite.h: added, declaration of suite for + use with CPPUNIT_TEST_SUITE_NAMED_REGISTRATION. + + * examples/cppunittest/makefile.am : added HelperSuite.h, CoreSuite.h, + ExtensionSuite.h, CppUnitTestSuite.h and CppUnitTestSuite.cpp. + + * examples/cppunittest/CppUnitTestSuite.*: added. + + * examples/cppunittest/ExceptionTest.cpp: + * examples/cppunittest/TestAssertTest.cpp: + * examples/cppunittest/TestCaseTest.cpp: + * examples/cppunittest/TestFailureTest.cpp: + * examples/cppunittest/TestListenerTest.cpp: + * examples/cppunittest/TestResultTest.cpp: + * examples/cppunittest/TestSuiteTest.cpp: moved into named suite + "Core" using CPPUNIT_TEST_SUITE_NAMED_REGISTRATION. + + * examples/cppunittest/OrthodoxTest.cpp: + * examples/cppunittest/RepeatedTest.cpp: + * examples/cppunittest/TestDecoratorTest.cpp: + * examples/cppunittest/TestSetUpTest.cpp: moved into named suite + "Extension" using CPPUNIT_TEST_SUITE_NAMED_REGISTRATION. + + * examples/cppunittest/HelperMacrosTest.cpp: + * examples/cppunittest/TestCallerTest.cpp: moved into named suite + "Helper" using CPPUNIT_TEST_SUITE_NAMED_REGISTRATION. + + * examples/cppunittest/CppUnitTest.dsp : + * examples/msvc6/CppUnitTestApp/CppUnitTestApp.dsp : added + Makefile.am, HelperSuite.h, CoreSuite.h, ExtensionSuite.h, + CppUnitTestSuite.h and CppUnitTestSuite.cpp. + +2001-10-01 Baptiste Lepilleur + + * NEWS : updated. + + * doc/other_documentation.dox : added all the authors to the list of + authors. + + * examples/cppunittest/HelperMacrosTest.*: added unit tests for + CPPUNIT_TEST_FAIL & CPPUNIT_TEST_EXCEPTION. + + * examples/cppunittest/TestAssertTest.*: added unit tests for + CPPUNIT_FAIL. Corrected spelling error. Relaxed constraint on message + produced by CPPUNIT_ASSERT_MESSAGE. Refactored some tests. + + * include/cppunit/extensions/HelperMacros.h : added macro + CPPUNIT_TEST_EXCEPTION to create a test case for the specified method + that must throw an exception of the specified type. + + * include/cppunit/extensions/TestSuiteBuilder.h : made + makeTestName() public. Added addTestCallerForException() to add a + test case expecting an exception of the specified type to be + caught. + + * include/cppunit/TestAssert.h : added macro CPPUNIT_FAIL as a + shortcut for CPPUNIT_ASSERT_MESSAGE( message, false ). + +2001-09-30 Steve M. Robbins + + * configure.in: Set version to 1.7.0. + +2001-09-30 Steve M. Robbins + + * Release 1.6.1. + + * doc/footer.html: Do not meddle with font size. + + * doc/header.html: Add link to FAQ. Do not meddle with font size. + + * doc/Doxyfile.in (PROJECT_NAME): Set to "CppUnit", to be + consistent on capitalization. + (PROJECT_NUMBER): Include "Version" in the string. + + * doc/Makefile.am (EXTRA_DIST): Distribute FAQ. + + * Makefile.am (EXTRA_DIST): Distribute contrib/msvc/CppUnit.WWTpl + and contrib/msvc/readme.txt. + (dist-hook): Change line endings of these files. + + * include/cppunit/extensions/RepeatedTest.h + * src/cppunit/RepeatedTest.cpp (countTestCases, toString): + Add const qualifier to function. + +2001-09-30 Baptiste Lepilleur + + * contrib/msvc/CppUnit.WWTpl: added, template for WorkSpace Whiz! + to create new classes and unit tests. + + * doc/FAQ: + * INSTALL-WIN32.txt: moved FAQ from install-WIN32 to that file. Added + a generic question to hint at the helper macros. + + * include/cppunit/extensions/HelperMacros.h: bug #464844, moved + declaration of ThisTestCaseFactory from CPPUNIT_TEST_SUITE_END to + CPPUNIT_TEST_SUITE where the Fixture class name is available from + the macro parameter. + +2001-09-30 Steve M. Robbins + + * include/cppunit/config-mac.h: New. Macintosh configuration, + courtesy of Duane Murphy. + + * include/cppunit/Portability.h: Move include inside + #if-block that needs it. + + * doc/Makefile.am (doc-dist): Creates tar file of HTML doc files. + Remove all wildcarded filenames. Do not bother with manpages. + + * Makefile.am (EXTRA_DIST): Distribute INSTALL-unix and + cppunit-config.1. + (man_MANS): Install cppunit-config.1. + (doc-dist): Use "make doc-dist" in doc directory. + + * cppunit-config.1: Document --prefix and --exec-prefix. + + * cppunit-config.in (Usage): Remove "[LIBRARIES]" from help string. + +2001-09-29 Steve M. Robbins + + * configure.in: Set version to 1.6.1. + +2001-09-29 Baptiste Lepilleur + + * example/cppunittest/TestCaller.*: remove some memory leaks. + TestCaller exception catching features is now tested correctly. + Previous test tested nothing! + +2001-09-23 Steve M. Robbins + + * configure.in: Set version to 1.6.0. + + * Makefile.am (EXTRA_DIST): Add BUGS. + + * NEWS: Incorporate Baptiste's notes. + + * BUGS: New file for list of known bugs. + + * README: Note about file BUGS. + +2001-09-24 Baptiste Lepilleur + + * include/cppunit/TestAssert.h : changed header order to remove + warning on VC++ + + * include/cppunit/TestCaller.h : bugfix: threw 'new Exception' + instead of 'Exception'. + +2001-09-23 Steve M. Robbins + + * doc/footer.html: Put devel list in mailto tag. + + * doc/Makefile.am (man_MANS): Restore ability to install manpages. + (htmldir): HTML pages installed under $(pkgdatadir). + + * doc/other_documentation.dox: Reference cookbook.html + in same directory. Remove obsolete text. + + * configure.in: Do not set CFLAGS; remove --enable-debug-mode. + + * include/cppunit/Portability.h: + * include/cppunit/extensions/HelperMacros.h: Allow user + to request the old-style CU_TEST family of macros. + + * doc/Doxyfile.in (EXCLUDE_PATTERNS): Remove estring.h. + + * README: Add contact and bug-reporting info. + + * INSTALL-unix: New. Move the unix install notes here + from README. + + * AUTHORS: Put myself on the list. + +2001-09-21 Baptiste Lepilleur + + * include/cppunit/TestFailure.h : made destructor virtual. + + * INSTALL-WIN32.txt : added some more infos about DSPlugIn. + + * src/msvc6/DSPlugIn/DSPlugIn.rgs: added some registry data + that where missing to register the COM object. + + * src/msvc6/DSPlugIn/DSPlugIn.rc: updated some dll version info. + + * src/msvc6/DSPlugIn/DSPlugIn.dsp: fixed the custom build step to + register the DLL using regsvr32.exe. Added a post-build step to + copy the dll to the lib/ directory. This prevent a blocking + compilation error if the DLL is in use by VC++. + +2001-09-20 Steve M. Robbins + + * Makefile.am (snapshot): Replace "date -I" GNUism with portable + specification for ISO date format. + (dist-hook): Correct rule to change line endings for INSTALL-WIN32.txt. + + * include/cppunit/Portability.h: + * config/ac_cxx_have_strstream.m4 (AC_CXX_HAVE_STRSTREAM): Extend + to check for and use in preference to . + Patrick Hartling reports the former is required for the SGI + MIPSpro 7.3.1.2 compiler. + +2001-09-19 Baptiste Lepilleur + + * examples/cppunittest/makefile.am : added TestSetupTest.(cpp/h) + + * examples/examples.dsw: removed some unnecessary dependencies. + + * examples/msvc6/HostApp/HostApp.dsp: fixed release configuration + + * src/msvc6/DSPlugIn/DSPlugIn.dsp: fixed release configuration, and + disabled the custom build command that does not work. + + * include/cppunit/extensions/HelperMacros.h: reordered header to remove + some warning with VC++. + + * INSTALL-WIN32.txt : detailed what was in each project. Added a FAQ + about the failing test case in cppunittest. + +2001-09-19 Steve M. Robbins + + * README: Describe how to check if libtool is fixed. + + * Makefile.am (dist-hook): Include INSTALL-WIN32.txt in the list + of files to convert to MSDOS line endings. + (snapshot): Use ISO-8601 compliant date for filename. + (ACLOCAL_AMFLAGS): Specify local directory. + +2001-09-18 Steve M. Robbins + + * include/cppunit/TextTestResult.h: Change include from + to . Sugggested by Peer Sommerlund. + + * include/cppunit/Portability.h: Qualify ostrstream with std. + Suggested by Patrick Hartling. + +2001-09-18 Baptiste Lepilleur + + * examples/examples.dsw: + * examples/msvc6/CppUnitTestApp/CppUnitTestApp.dsw: + * examples/msvc6/HostApp/HostApp.dsw: + * examples/msvc6/TestPlugIn/TestPlugIn.dsw: Added missing + project dependency. + + * src/msvc6/DSPlugIn/DSPlugIn.dsp: fixed *.tlb output directory. + + * include/msvc6/testrunner/TestPlugInInterface.h: does not define + NOMINMAX if already defined. + +2001-09-17 Baptiste Lepilleur + + * Makefile.am: Added INSTALL-WIN32.txt to EXTRA_DIST. + + * INSTALL-WIN32.txt: added, short documentation for CppUnit and VC++. + + * include/cppunit/extensions/HelperMacros.h: bug #448363, removed + an extraneous ';' at the end of CPPUNIT_TEST_SUITE_END macro. + + * examples/cppunittest/TestCallerTest.cpp: bug #448332, fixed + memory leaks. + + * src/msvc6/testrunner/TestRunnerDlg.h: + * src/msvc6/testpluginrunner/TestPlugInRunnerDlg.h: + * src/msvc6/testpluginrunner/TestPlugInRunnerDlg.cpp: change to define + IDD to a dummy value when subclassing the dialog. + + * src/cppunit/cppunit.dsp: + * src/msvc6/testrunner/TestRunner.dsp: + * src/msvc6/testpluginrunner/TestPlugInRunner.dsp: + * examples/cppunitttest/CppUnitTestMain.dsp: + * examples/hierarchy.dsp: + * examples/msvc6/TestPlugIn/TestPlugIn.dsp: + * examples/msvc6/HostApp/HostApp.dsp: all configurations can be compiled. + + * src/msvc6/testpluginrunner/TestPlugInRunner.dsw: added dependency to + cppunit.dsp and TestRunner.dsp. + +2001-09-16 Steve M. Robbins + + * Revert TestFixture-related changes from 2001-07-15: + + * src/cppunit/cppunit.dsp (SOURCE): Remove TestFixture.h. + + * src/cppunit/TestCase.cpp (setUp, tearDown): Restore function + bodies. + + * include/cppunit/TestCase.h (class TestCase): Do not derive + from class TestFixture. Restore member functions setUp() + and tearDown(). + + * include/cppunit/TestCaller.h: Do not include + . + + * include/cppunit/Makefile.am (libcppunitinclude_HEADERS): Remove + TestFixture.h. + +2001-09-14 Baptiste Lepilleur + * src/msvc6/testrunner/TestRunner.dsp: fixed release configuration. + + * src/msvc6/testrunner/TestRunner.dsw: added DSPlugIn.dsp. TestRunner + depends on DSPlugIn. + + * src/msvc6/testrunner/TestRunner.cpp: + * src/msvc6/testrunner/TestRunnerDlg.h: + * src/msvc6/testrunner/TestRunnerDlg.cpp: + * src/msvc6/testrunner/MsDevCallerListCtrl.cpp: + * src/msvc6/testrunner/MsDevCallerListCtrl.h: + * src/msvc6/DSPlugIn/*: integrated patch from + Patrick Berny (PPBerny@web.de). An add-ins for VC++. Double-cliking + a failed test in the TestRunner, VC++ will open the source file and + go to the failure location. + + * src/cppunit/Exception.cpp: + * include/cppunit/Exception.h: compile fix, call to overrided + operator = of parent class failed. Using typedef to the parent + class fix that. + + * src/cppunit/cppunit.dsp: added TestFixture.h + + * src/cppunit/TestFactoryRegistry.cpp: removed which isn't + needed any more. + + * include/cppunit/TestCase.h: + * include/cppunit/TestSuite.h: + * include/cppunit/extensions/TestFactoryRegistry.h: added + include before any other includes to remove warning + with VC++. + + * include/cppunit/Portability.h: moved platform specific includes at + the beginning of the header. fixed CPPUNIT_HAVE_CPP_SOURCE_ANNOTATION + declaration. + + * include/cppunit/config-msvc6.h: removed pragma once (useless, should + be put in each header to have an effect). + +2001-08-07 Steve M. Robbins + + * doc/Makefile.am: Add workaround for broken Doxygen. + + * src/cppunit/TextTestResult.cpp (operator<<): Remove CppUnit:: + prefix. + + * configure.in: Add check for . + * src/cppunit/TestAssert.cpp: Use if not + available. + * src/cppunit/TestCase.cpp: Do not include . + + * include/cppunit/config-bcb5.h (HAVE_CMATH): + * include/cppunit/config-msvc6.h (HAVE_CMATH): Add. + + * src/cppunit/Exception.cpp: Qualify std::exception. + + * examples/cppunittest/OrthodoxTest.h (TestCase): Add assignment + operator. MIPSpro fails to compile without one. + + * Makefile.am: Removed automake conditional "DOC". + * doc/Makefile.am: Placed "DOC" conditional around + rules that invoke Doxygen. + + * config/Makefile.am: Removed. + * configure.in: Do not create config/Makefile. + * Makefile.am (EXTRA_DIST): Distribute config/*.m4. + (SUBDIRS): Do not descend into config. + +2001-07-15 Steve M. Robbins + + * include/cppunit/TestFixture.h: New. Declare class TextFixture. + + * include/cppunit/TestCaller.h: + * include/cppunit/TestCase.h: + * src/cppunit/TestCase.cpp: + * include/cppunit/Makefile.am: Subclass TestCase from TestFixture. + +2001-07-14 Steve M. Robbins + + * include/cppunit/Exception.h: + * include/cppunit/Test.h: + * include/cppunit/TestCaller.h: + * include/cppunit/TestCase.h: + * include/cppunit/TestFailure.h: + * include/cppunit/TestListener.h: + * include/cppunit/TestSuite.h: + * include/cppunit/extensions/RepeatedTest.h: + * include/cppunit/extensions/TestDecorator.h: + * src/cppunit/TestCase.cpp: Add documentation. + +2001-07-13 Steve M. Robbins + + * examples/cppunittest/TestAssertTest.h: + * examples/cppunittest/TestAssertTest.cpp: Add tests + for CPPUNIT_ASSERT_EQUAL. + +2001-07-12 Steve M. Robbins + + * configure.in: Set to version 1.5.6. On the assumption that + backwards compatibility has been broken (though I'm not certain), + set the binary age and interface age to zero. + + * examples/cppunittest/TestFailureTest.h: + * include/cppunit/Exception.h: + * include/cppunit/NotEqualException.h: + * src/cppunit/Exception.cpp: + * src/cppunit/NotEqualException.cpp: Add "throw()" to overridden + std::exception destructors; required for GCC 3.0. + +2001-07-07 Steve M. Robbins + + * include/cppunit/Makefile.am: Clean config-auto.h using + DISTCLEANFILES. + + * doc/Makefile.am: Temporarily disable manpage installation. + Fix html installation to ensure files removed by uninstall. + + * src/cppunit/estring.h: Removed. + + * src/cppunit/Makefile.am: + * src/cppunit/TestCase.cpp: + * src/cppunit/TextTestResult.cpp: Recode to avoid use of estring. + + * examples/cppunittest/OrthodoxTest.h: Add const qualifier + to operator== methods. + + * include/cppunit/config-bcb5.h: + * include/cppunit/config-msvc6.h: Define CPPUNIT_HAVE_SSTREAM to 1. + + * config/ac_cxx_have_sstream.m4: New. Defines macro + AC_CXX_HAVE_SSTREAM. Taken from the autoconf archive. + + * config/ac_cxx_have_strstream.m4: New. Copy of above, + modified to check for presence of strstream; defines + macro AC_CXX_HAVE_STRSTREAM. + + * configure.in: Invoke AC_CXX_HAVE_SSTREAM and + AC_CXX_HAVE_STRSTREAM. + + * include/cppunit/Portability.h: Define class + CppUnit::OStringStream. + + * include/cppunit/TestAssert.h: + * src/cppunit/TestFactoryRegistry.cpp: Replace std::ostringstream + by CppUnit::OStringStream. + + +2001-07-06 Steve M. Robbins + + * configure.in: Add --disable-typeinfo-name option. + + * README: Add note about new configure option. + + * configure.in: Remove AM_DISABLE_STATIC. + + * INSTALL: Update to version from autoconf 2.50. + +2001-07-05 Steve M. Robbins + + * include/cppunit/Portability.h: Remove definition of + CPPUNIT_USE_TYPEINFO. + + * configure.in: Define USE_TYPEINFO_NAME in config.h. + + * include/cppunit/config-msvc6.h (CPPUNIT_USE_TYPEINFO_NAME): + * include/cppunit/config-bcb5.h (CPPUNIT_USE_TYPEINFO_NAME): Add + definition. + + * include/cppunit/TestCaller.h: + * include/cppunit/extensions/TypeInfoHelper.h: + * include/cppunit/extensions/TestSuiteBuilder.h: + * include/cppunit/extensions/HelperMacros.h: + * src/cppunit/TypeInfoHelper.cpp: + * src/cppunit/TestFactoryRegistry.cpp: + * src/cppunit/TestCase.cpp (toString): + Switch from CPPUNIT_USE_TYPEINFO to CPPUNIT_USE_TYPEINFO_NAME. + + * src/cppunit/TestAssert.cpp: Remove include of estring.h. + + * configure.in: Invoke AC_PROG_CC to workaround a automake + bug. Move probes for CC/CXX ahead of the libtool macros. + + * examples/hierarchy/Makefile.am: + * examples/cppunittest/Makefile.am: + * src/cppunit/Makefile.am (INCLUDES): Search + $(top_builddir)/include for . + +2001-06-27 Baptiste Lepilleur + + * examples/msvc6/CppUnitTestApp/CppUnitTestApp.dsp: + moved dll copy from post-build to custom build setting, so that the + dll is copied even if the CppUnitTestApp was not modified. + + * examples/msvc6/TestPlugIn/: a new example of test plug in. + + * src/msvc6/TestRunner/ListCtrlFormatter.* + * src/msvc6/TestRunner/ListCtrlSetter.*: + added, helper to manipulate list control. + + * src/msvc6/TestRunner/TestRunnerDlg.*: change to make the error list + more compact. text moved to string resources. icons added for typ + test tfailure type. + + * src/msvc6/TestRunner/MostRecentTests.*: added, classes that will + replace the current implementation of MRU test which make it hard + to subclass the dialog. + + * src/msvc6/TestRunner/res/errortype.bmp: added, bitmap with error + types (failure and error). + + * src/msvc6/TestPlugInRunner/: A test runner to run test plug in. + Test plug in are DLL that publish a specified plug in interface. + Those DLL are loaded and reloaded by the TestPlugInRunner to run + tests. This remove the need to wrap DLL with a executable to test + them. + + * src/cppunit/cppunit.dsp: + removed config.h from project + added Portability.h and config-msvc6.h + + * include/cppunit/config-msvc6.h: + undef CPPUNIT_FUNC_STRING_COMPARE_STRING_FIRST + + +2001-06-20 Steve M. Robbins + + * autogen.sh: Stop when tool fails. Try /usr/local/share/aclocal + only if aclocal fails without it. + + * README.CVS: New. + +2001-06-18 Steve M. Robbins + + * include/cppunit/Portability.h (CPPUNIT_USE_TYPEINFO): + (CPPUNIT_ENABLE_NAKED_ASSERT): + (CPPUNIT_HAVE_CPP_SOURCEANNOTATION): Fix setting of + default values. + +2001-06-17 Steve M. Robbins + + * configure.in: Require autoconf 2.50 or better. + +2001-06-17 Bastiaan Bakker + + * configure.in: moved config.h from include/ to config/ + + * configure.in: added AC_CREATE_PREFIX_CONFIG_H call + + * config/ac_create_prefix_config_h.m4: added + + * configure.in: removed include/cppunit/config.h from AC_OUTPUT + * include/cppunit/config.h.in: obsoleted by + AC_CREATE_PREFIX_CONFIG_H macro. + + * configure.in: + * config/bb_enable_doxygen.m4: moved doxygen stuff into + BB_ENABLE_DOXYGEN macro + + * include/cppunit/Makefile.am: removed config.h, added config-auto.h, + config-msvc6.h, config-bcb5.h, Portability.h + + * include/cppunit/Makefile.am: added dist-hook to exclude + config-auto.h from dist tar + + * include/cppunit/TestAssert.h: + * include/cppunit/extensions/TypeInfoHelper.h: + * include/cppunit/extensions/TestSuiteBuilder.h: + * include/cppunit/extensions/HelperMacros.h: + * src/cppunit/TypeInfoHelper.cpp: + * src/cppunit/TestRegistry.cpp: + * src/cppunit/TestFactoryRegistry.cpp: + * src/cppunit/TestCase.cpp: replaced #include of with + + + * src/cppunit/TypeInfoHelper.cpp: use new macro name + CPPUNIT_FUNC_STRING_COMPARE_STRING_FIRST + + +2001-06-12 Baptiste Lepilleur + + * include/cppunit/NotEqualException.h + * src/cppunit/NotEqualException.h: + Fixed constructor and operator = (aren't unit test nice?). Added + methods expectedValue() and actualValue(). + + * include/cppunit/TestAssert.h: + * src/cppunit/TestAssert.cpp: + Use NotEqualException to report equality failure. + + * src/cppunit/TestFactoryRegistry.cpp: fixed makeTest(). It did not use m_name for + naming the suite. + + * src/cppunit/TestResult.cpp: + Report expect/was on different line for assertEquals failure. + + * examples/cppunittest/NotEqualExceptionTest.*: added unit tests for + NotEqualException. + + * examples/cppunittest/OrthodoxTest.*: operator ! use explicit construction. + + * examples/msvc6/CppUnitTestApp/CppUnitTestApp.cpp: modified so that the dialog + is not displayed after the tests are run. + +2001-06-11 Steve M. Robbins + + * examples/cppunittest/TestResultTest.cpp (testAddTwoErrors, + testAddTwoFailures): Replace vector::at() with more portable + vector::operator[]; GCC doesn't have the former. + + * include/cppunit/extensions/TestDecorator.h (countTestCases): + Declare return type. + + * src/cppunit/Makefile.am (libcppunit_la_SOURCES): Add + TestAssert.cpp, RepeatedTest.cpp. + + * include/cppunit/TestCaller.h (NoExceptionExpected): Fix + constructor name. + +2001-06-11 Baptiste Lepilleur + + * include/cppunit/Exception.h: now inherit from std::exception + instead of ::exception. Added clone(), type(), and isInstanceOf() + methods for subclassing support. Changed UNKNOWNLINENUMBER type to + long for consistence with lineNumber(). + + * include/cppunit/NotEqualException.h: addded, exception to be + used with assertEquals(). + + * include/cppunit/TestAssert.h: changed TestAssert into a + namespace instead of a class. This remove the need of template + member methods and does not cause compiler internal error on + VC++. Macro CPPUNIT_ASSERT_MESSAGE has been added to fail test + with a specified message. + + * include/cppunit/TestCaller.h: added "Expected exception" + support. Based on Tim Jansen patch (#403745), but use a traits + instead of RTTI to distingh between "No expected exception" and + "Excepted exception". Exception type name is reported using RTTI + if CPPUNIT_USE_TYPEINFO is defined. + + * include/cppunit/extensions/HelperMacros.h: static method suite() + implemented by CPPUNIT_TEST_SUITE_END macro now returns a + TestSuite instead of a Test. + + * include/cppunit/extensions/RepeatedTest.h: corrected + countTestCases, operator = declaration. + + * include/cppunit/extensions/TestDecorator.h: removed const from + run() method. Did not match run() declaration of Test class. + + * include/cppunit/extensions/TestFactory.h: fixed a comment. + + * include/cppunit/extensions/TestSetup.h: corrected run() method + declaration. Methods setUp() and tearDown() were not declared + virtual. + + * include/cppunit/extensions/TestSuiteBuilder.h: added a method + addTestCaller() which take a pointer on a fixture. + + * include/cppunit/NotEqualException.cpp: addded, exception to be + used with assertEquals(). + + * src/cppunit/RepeatedTest.cpp: added to reduce header dependency + (TestResult.h was missing). + + * src/cppunit/TestAssert.cpp: added to put non template functions + there. + + * src/cppunit/TestCase.cpp: added std:: prefix to catch + (exception& e). Integrated a modified version of Tim Jansen patch + (#403745) for TestCase to make the unit test (TestCaseTest) + pass. If the setUp() fail then neither the runTest() nor the + tearDown() method is called. + + * examples/examples.dsw: added cppunittest projects to workspace. + + * examples/cppunittest/TestResultTest.*: renamed + TestListenerTest.* + + * examples/cppunittest/*: added unit tests for: HelperMacros, + TestAssert, TestCaller, TestCase, TestFailure, TestResult, + TestSuite, TestDecoratorTest, TestSetUp, RepeatedTestTest, + Orthodox, Exception. + +2001-06-05 Baptiste Lepilleur + + * src/cppunit/TypeInfoHelper.cpp: removed #include , + cppunit/config.h was already included. + + * src/cppunit/cppunit.dsp: removed TestAssert.cpp from project. + + * added/updated .cvsignore files for beter handling of windows + projects. + + * added include/cppunit/config.h with a default configuration for + VC++ 6.0. + + * include/cppunit/.cvsignore: removed config.h from the list of + ignored file. + + * renamed VC++ configurations without RTTI from "Debug No + CU_USE_TYPEINFO" to "Debug Crossplatform". + + * include/cppunit/TestAssert.h: added include for fabs(). + +2001-06-02 Steve M. Robbins + + * src/cppunit/Exception.cpp: Remove unnecessary namespace + declaration; it confuses Doxygen. + +2001-06-02 Steve M. Robbins + + * configure.in: Add AC_CXX_STRING_COMPARE_STRING_FIRST. + + * autogen.sh: Add "-I config" to aclocal flags, to pick up + the new .m4 files. + + * config/ac_cxx_namespaces.m4: New. Taken from + http://cryp.to/autoconf-archive. + + * config/ac_cxx_string_compare_string_first.m4: New. Detect + if std::string::compare() takes string argument first. + +2001-06-02 Steve M. Robbins + + * include/cppunit/TestAssert.h: Declare generic assertion_traits + class. Replace notEqualsMessage functions for long and double by + a generic, template function. Replace assertEquals for longs by a + generic template function. Inline all class methods. Define new + assertion macros CPPUNIT_ASSERT, CPPUNIT_ASSERT_EQUAL, and + CPPUNIT_ASSERT_DOUBLES_EQUAL; the old names are available by + editing . + + * src/cppunit/TestAssert.cpp: Removed. Move code to inline + functions. + + * config/ac_cxx_rtti.m4: New. Taken from + http://cryp.to/autoconf-archive. + + * include/cppunit/config.h.in: New. Input file for installable, + generated config.h file. + + * configure.in: Use AC_CXX_RTTI; generate include/cppunit/config.h. + + * include/cppunit/extensions/HelperMacros.h: + * include/cppunit/extensions/TestSuiteBuilder.h: + * include/cppunit/extensions/TypeInfoHelper.h: + * src/cppunit/TestCase.cpp: + * src/cppunit/TestFactoryRegistry.cpp: + * src/cppunit/TypeInfoHelper.cpp: + Use "#if CPPUNIT_USE_TYPEINFO" rather than "#ifdef". + + * src/cppunit/TypeInfoHelper.cpp: Allow for std::string::compare() + that takes the string in the first argument. + + * doc/cookbook.html: + * examples/cppunittest/TestCallerTest.cpp: + * examples/cppunittest/TestResultTest.cpp: + * examples/hierarchy/BoardGameTest.h: + * examples/hierarchy/ChessTest.h: + * examples/msvc6/HostApp/ExampleTestCase.cpp: + * include/cppunit/TestCase.h: + * include/cppunit/extensions/Orthodox.h: + Replace assert by CPPUNIT_ASSERT. + Replace assertLongsEqual by CPPUNIT_ASSERT_EQUAL. + Replace assertDoublesEqual by CPPUNIT_ASSERT_DOUBLES_EQUAL. + + * * (CU_TEST_SUITE, CU_TEST, CU_TEST_SUITE_END, + CU_TEST_SUITE_REGISTRATION): Replace prefix CU_ with CPPUNIT_. + + * examples/cppunittest/.cvsignore: Add UNIX generated files. + +2001-06-01 Bastiaan Bakker + + * examples/cppunittest/Makefile.am: added + + * configure.in: added examples/cppunittest/Makefile to AC_OUTPUT. + + * examples/cppunittest/TestCallerTest (suite), + examples/cppunittest/TestResultTest (suite): fixed 'ISO C++ + forbids taking the address of a bound member function to form + a pointer to member function' bug reported by g++. + + * examples/cppunittest/TestCallerTest (suite), + examples/cppunittest/TestResultTest (suite): removed dependency on + RTTI. + +2001-06-01 Baptiste Lepilleur + + * added project cppunittest to examples/: unit tests to test cppunit. + The main file is CppUnitTestMain.cpp. Unit tests have been implemented + for TestCaller and TestListener. + + * added project CppUnitTestApp to examples/msvc6: graphical runner + for cppunittest. + + * added TestListener to TestResult. It is a port of junit + TestListener. + + * updated some .cvsignore to ignore files generated with VC++. + +2001-05-30 Bastiaan Bakker + + * src/cppunit/TestCase.cpp (toString): put type_info in std + namespace and inside CU_USE_TYPEINFO ifdef. + +2001-05-29 Steve M. Robbins + + * examples/hierarchy/main.cpp: Remove extraneous includes. + + * src/cppunit/TextTestResult.cpp (addError, addFailure): Do not + emit a newline. + + * include/cppunit/extensions/HelperMacros.h: Rework documentation. + (CU_TEST_SUITE): Move definition of member function suite() ... + (CU_TEST_SUITE_END): ... to here. + (CU_TEST): Use '&' to take address of member function + "testMethod". + + * include/cppunit/extensions/AutoRegisterSuite.h: Declare "factory" + as a TestFactory*. + +2001-05-28 Steve M. Robbins + + * doc/other_documentation.dox: Don't include "CppUnit" in + anchor text, since Doxygen puts its own anchor around it. + + * doc/Makefile.am (html/index.html): Depend on + other_documentation.dox. + + * doc/Doxyfile.in (EXCLUDE): Move config.h and estring.h to + EXCLUDE_PATTERNS; they were not being excluded. + + * ChangeLog: Reformat all entries to start with . See + for change log + format. + + * doc/cookbook.html: Update all code examples, except for TestRunner + section. + +2001-05-23 Baptiste Lepilleur + + * Updated CU_TEST_SUITE macro documentation. It is now stated + explicitly that you do not need to specify template parameter as + macro argument. The documentation example has been updated to + reflect that. + +2001-05-23 Bastiaan Bakker + + * autogen.sh: added '--add-missing' option to automake. + * autogen.sh: added '--force' option to libtoolize and removed + '--copy'. + * config: removed generated files from CVS. + +2001-05-20 Baptiste Lepilleur + + * Fixed bug #424320 (VC++ TestRunner): access violation caused by + NULL pointer in history list. NULL pointer are not added to the + history anymore. + +2001-05-19 Baptiste Lepilleur + + * Added some items to the TODO list for VC++ TestRunner. + + * "Debug" configuration is now the default configuration in VC++ + project. + + * Modified sort order in the test browser of VC++ TestRunner so + that tests are in the same order as in the suite. Suites are still + sorted alphabetically. + + * Merged Steve M. Robbins patch to replace assertImplementation + with assert in hierarchy example. + + * Added a TextTestRunner to runner tests. It is based on Michael + Feather's version, but have been rewriten. + + * Removed traces that printed the test name in TextTestResult + while running. + + * Added the test name to error and failure report in + TextTestResult. + + * Updated hierarchy example to use TextTestRunner. + +2001-05-18 Baptiste Lepilleur + + * Symbol CU_USE_TYPEINFO must be defined instead of USE_TYPEINFO + to compile RTTI. + + * Added back default constructor to TestSuiteBuilder which use + RTTI. It is available only if CU_USE_TYPEINFO is defined. + + * Moved TypeInfoHelper.h from src/cppunit to + include/cppunit/extensions. + + * Macro CU_TEST_SUITE in HelperMacros.h now use TestSuiteBuilder + default constructor if CU_USE_TYPEINFO is defined, otherwise it + use the type name given to the CU_TEST_SUITE macro. + + * TestFactoryRegistry::registerFactory(factory) now generate a + dummy name based on a serial number instead of using RTTI. The + macro CU_TEST_SUITE_REGISTRATION and class AutoRegisterSuite can + now when CU_USE_TYPEINFO is not defined. + + * Added a new Configuration named "Debug Without CU_USE_TYPEINFO" + to msvc6 projects. The flag CU_USE_TYPEINFO is not defined in that + configuration. + +2001-05-17 Steve M. Robbins + + * Makefile.am (dist-hook): Copy files relative to $(top_srcdir). + + * doc/Makefile.am: Generated doc files depend on Doxyfile. + + * doc/Doxyfile.in: Use autoconf substitutions in file names. + + * examples/hierarchy/Makefile.am (check_PROGRAMS): Build hierarchy + with "make check", not "make all". + + * examples/hierarchy/Makefile.am (INCLUDES): + + * src/cppunit/Makefile.am (INCLUDES): Search in + $(top_srcdir)/include. + + * Added .cvsignore files. + +2001-05-16 Bastiaan Bakker + + * Merged Debian packaging support files by Christian Leutloff from + debian package version 1.5.4-2. Added make target 'debian' for + debian package creation. + +2001-05-09 Bastiaan Bakker + + * Release as 1.5.5. + + * Finished CppUnitW 1.2 merge. Removed RTTI depency from + TestSuite. Added TestCaller constructor for calling methods in + existing TestCases. + +2001-04-29 Bastiaan Bakker + + * Merged Baptiste Lepilleurs CppUnitW 1.2. Some differences: + TypeInfo stuff (in TestSuite) compiled in only if USE_TYPEINFO is + set. TestSuite.getTests now returns a const ref instead of taking + a ref as parameter. Removed auto_ptr stuff from + TestFactoryRegistry: auto_ptr cannot be used in containers. + +2001-04-28 Bastiaan Bakker + + * Merged MSVC++ specific TestRunner and example adapted from + Micheal Feathers version by Baptiste Lepilleur. + + * Moved cppunit subdir into src. + +2001-04-24 Bastiaan Bakker + + * Merged Baptiste Lepilleurs patch for TestRegistry: now TestCases + do not automatically register with the Registry anymore. + + * Added extension headers from Micheal Feathers port to + include/cppunit/extensions. + +2001-04-19 Bastiaan Bakker + + * Added MSVC++ workspace and project files, submitted by Baptiste + Lepilleur. + +2001-04-15 Bastiaan Bakker + + * Moved public headers from cppunit into new subdir + include/cppunit. This should make more clear which headers are + used internally only (like estring.h). + + * Moved autoconf auxiliary stuff into new subdir config, to make + the top dir less crowded. + + * Prefixed std:: to cerr, cout and endl. + +2001-04-14 Bastiaan Bakker + + * Release as 1.5.4 + + * Added support for RPM generation. + + * Added autoconf support for Doxygen document generation: Doxygen + and GraphViz dot are automatically detected and LaTeX and HTML can + be switch on or off. + + * cppunit/TextTestResult.cpp: changed cout to stream. Fixes bug + #232636 + + * cppunit/TextTestReulst.cpp: add '#include '. Fixes + bug #223290 + + * cppunit/*.cpp: removed bogus 'inline' specifiers. Fixes bug + #224542 and #223291. + + * doc/header.html: corrected link to CppUnit project page Fixes + bug #414073 + + * cppunit/*.cpp, examples/hierarchy/main.cpp: removed all 'using + namespace ...' occurences. + +2001-01-31 Tim Jansen + + * cppunit/TestCase.cpp, cppunit/TestCase.h, cppunit/TestSuite.h, + cppunit/TestSuite.cpp: applied patch #402271 by bwithrow. Fixes + bug #220207 + + * cppunit/TestSuite.cpp (deleteContents): clear vector after + contents have been deleted (so there are no invalid pointers in + the vector) Patch #403540 / #403542 + + * cppunit/TestCaller.h: create Fixture with empty constructor so + that only the TestCaller but not the Fixture instance is + registered in the TestRegistry Patch #403541 / #403542 + + * examples/hierarchy/BoardGameTest.h, + examples/hierarchy/ChessTest.h, examples/hierarchy/main.cpp: + initialize example TestCases with TestSuite so that the + TestCallers are registered in the TestRegistry Patch + #403542. Fixes bug #415249 + + * cppunit/TestCaller.h, cppunit/TestCase.cpp, cppunit/TestCase.h: + changed documentation; made hopefully clearer which constructor + registers the instance in the TestRegistry; corrected syntax in + code example Patch #403542. diff --git a/UnitTests/cppunit/CodingGuideLines.txt b/UnitTests/cppunit/CodingGuideLines.txt new file mode 100644 index 0000000..5651ee8 --- /dev/null +++ b/UnitTests/cppunit/CodingGuideLines.txt @@ -0,0 +1,61 @@ +CppUnit's coding guidelines for portability: +-------------------------------------------- + +- don't explicitly declare CppUnit namespace, instead use macro + CPPUNIT_NS_BEGIN and CPPUNIT_NS_END. + +- don't explicitly use 'CppUnit' to refer to class in CppUnit namespace, + instead use macro CPPUNIT_NS which expands to either 'CppUnit' or + nothing depending on the configuration. + +- don't use the 'using directive', always use full qualification. For STL, + always use std::. + +- don't use C++ style cast directly, instead use CppUnit's cast macro + (CPPUNIT_CONST_CAST). + +- don't use the mutable keyword, instead do a const cast. + +- don't use the typename keyword in template declaration, instead use 'class'. + +- don't make use of RTTI (typeid) or dynamic_cast mandatory. + +- don't use STL container directly, instead use CppUnit's wrapper located + in include/cppunit/portability. This help support compilers that don't + support default template parameter and require an allocator to be + specified. + +- don't use default template parameters. If needed, use STLPort wrapper + technic (see include/cppunit/portability/). + +- don't use templatized member functions (template method declared inside a + class), instead declares them as simple template functions (even + mainstream compiler such as VC++ 6 as trouble with them). + +- don't use default parameter value in template function. Not supported + by all compiler (on OS/390 for instance). + +- don't use STL container at() method, instead use the array accessor []. + at() is not supported on some gcc versions. + +- dereferencing containers must be done by (*ref_ptr).data instead of + ref_ptr->data. + +In brief, it should be possible to compile CppUnit on a C++ compiler that do +not have the following features: +- C++ style cast +- mutable and typename keyword +- RTTI +- template default parameters +- templatized member functions (that is a template function declared within a + class). +- namespace + +As such, usage of those features should always be optional. + +Following those guidelines should allow to compile on most compilers, as long +as STL are available (in std namespace or not), with some form of strstream and +iostream, as well as exception support. + +-- +Baptiste Lepilleur diff --git a/UnitTests/cppunit/THANKS b/UnitTests/cppunit/THANKS new file mode 100644 index 0000000..89cfa9c --- /dev/null +++ b/UnitTests/cppunit/THANKS @@ -0,0 +1,23 @@ +Tim Jansen +Christian Leutloff +Steve M. Robbins +Patrick Berny +Patrick Hartling +Peer Sommerlund +Duane Murphy +Gigi Sayfan +Armin "bored" Michel +Jeffrey Morgan +'cuppa' project team (http://sourceforge.jp/projects/cuppa/) +Phil Verghese +Lavoie Philippe +Pavel Zabelin +Marco Welti +Thomas Neidhart +Hans Bühler (Dynamic Window library used by MFC UI) +John Sisson +Steven Mitter +Stephan Stapel +Abdessattar Sassi (hp-ux plug-in support) +Max Quatember and Andreas Pfaffenbichler (VC++ 7 MFC TestRunner go to source line) +Vincent Rivière diff --git a/UnitTests/cppunit/TODO b/UnitTests/cppunit/TODO new file mode 100644 index 0000000..19fa324 --- /dev/null +++ b/UnitTests/cppunit/TODO @@ -0,0 +1,35 @@ +* Bugs: +Asserter::makeNotEqualMessage() strip the shortDescription of the additional message. + +* CppUnit: + - STL concept checker. + - Memory leak tracking: setUp/tearDown should be leak safe if no failure occured. + +* UnitTest + - add tests for XmlOutputter::setStyleSheet (current assertion macro strip when + testing ) + +* VC++ TestRunner: + - Modify MfcUi::TestRunner to expose TestResult (which allow specific TestListener + for global initialization). + - Update MfcTestRunner to use TestPath to store test in the registry + +* Documentation: + CookBook: + - how to create simple test cases (with CppUnit namespace) + - test case using only CPPUINT_ASSERT + - test case using CPPUNIT_ASSERT_EQUAL + - advanced assertions with the CPPUNIT_ASSERT_MESSAGE + - Helper Macros for convenience + - Creating a suite + - Composing a suite from more suites (i.e. compose tests for n modules to + form a big test for the whole program) + - customizing output using an user defined TestListener + - how to write the TestListener (subclass of TestListener) + - how to hook it in + - how to use the GUI + - MSVC++ special stuff + - other custmization stuff I haven't understood yet + + CppUnit: architecture overview. + diff --git a/UnitTests/cppunit/include/cppunit/AdditionalMessage.h b/UnitTests/cppunit/include/cppunit/AdditionalMessage.h new file mode 100644 index 0000000..917d754 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/AdditionalMessage.h @@ -0,0 +1,76 @@ +#ifndef CPPUNIT_ADDITIONALMESSAGE_H +#define CPPUNIT_ADDITIONALMESSAGE_H + +#include + + +CPPUNIT_NS_BEGIN + + +/*! \brief An additional Message for assertions. + * \ingroup CreatingNewAssertions + * + * Provides a implicit constructor that takes a single string. This allow this + * class to be used as the message arguments in macros. + * + * The constructed object is either a Message with a single detail string if + * a string was passed to the macro, or a copy of the Message passed to the macro. + * + * Here is an example of usage: + * \code + * + * void checkStringEquals( const std::string &expected, + * const std::string &actual, + * const CppUnit::SourceLine &sourceLine, + * const CppUnit::AdditionalMessage &message ); + * + * #define XTLUT_ASSERT_STRING_EQUAL_MESSAGE( expected, actual, message ) \ + * ::XtlUt::Impl::checkStringEquals( ::Xtl::toString(expected), \ + * ::Xtl::toString(actual), \ + * CPPUNIT_SOURCELINE(), \ + * message ) + * \endcode + * + * In the previous example, the user can specify a simple string for \a message, + * or a complex Message object. + * + * \see Message + */ +class CPPUNIT_API AdditionalMessage : public Message +{ +public: + typedef Message SuperClass; + + /// Constructs an empty Message. + AdditionalMessage(); + + /*! \brief Constructs a Message with the specified detail string. + * \param detail1 Detail string of the message. If empty, then it is not added. + */ + AdditionalMessage( const std::string &detail1 ); + + /*! \brief Constructs a Message with the specified detail string. + * \param detail1 Detail string of the message. If empty, then it is not added. + */ + AdditionalMessage( const char *detail1 ); + + /*! \brief Constructs a copy of the specified message. + * \param other Message to copy. + */ + AdditionalMessage( const Message &other ); + + /*! \brief Assignment operator. + * \param other Message to copy. + * \return Reference on this object. + */ + AdditionalMessage &operator =( const Message &other ); + +private: +}; + + +CPPUNIT_NS_END + + + +#endif // CPPUNIT_ADDITIONALMESSAGE_H diff --git a/UnitTests/cppunit/include/cppunit/Asserter.h b/UnitTests/cppunit/include/cppunit/Asserter.h new file mode 100644 index 0000000..94dadaa --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/Asserter.h @@ -0,0 +1,143 @@ +#ifndef CPPUNIT_ASSERTER_H +#define CPPUNIT_ASSERTER_H + +#include +#include +#include + +CPPUNIT_NS_BEGIN + + +class Message; + + +/*! \brief A set of functions to help writing assertion macros. + * \ingroup CreatingNewAssertions + * + * Here is an example of assertion, a simplified version of the + * actual assertion implemented in examples/cppunittest/XmlUniformiser.h: + * \code + * #include + * #include + * + * void + * checkXmlEqual( std::string expectedXml, + * std::string actualXml, + * CppUnit::SourceLine sourceLine ) + * { + * std::string expected = XmlUniformiser( expectedXml ).stripped(); + * std::string actual = XmlUniformiser( actualXml ).stripped(); + * + * if ( expected == actual ) + * return; + * + * ::CppUnit::Asserter::failNotEqual( expected, + * actual, + * sourceLine ); + * } + * + * /// Asserts that two XML strings are equivalent. + * #define CPPUNITTEST_ASSERT_XML_EQUAL( expected, actual ) \ + * checkXmlEqual( expected, actual, \ + * CPPUNIT_SOURCELINE() ) + * \endcode + */ +struct Asserter +{ + /*! \brief Throws a Exception with the specified message and location. + */ + static void CPPUNIT_API fail( const Message &message, + const SourceLine &sourceLine = SourceLine() ); + + /*! \brief Throws a Exception with the specified message and location. + * \deprecated Use fail( Message, SourceLine ) instead. + */ + static void CPPUNIT_API fail( std::string message, + const SourceLine &sourceLine = SourceLine() ); + + /*! \brief Throws a Exception with the specified message and location. + * \param shouldFail if \c true then the exception is thrown. Otherwise + * nothing happen. + * \param message Message explaining the assertion failiure. + * \param sourceLine Location of the assertion. + */ + static void CPPUNIT_API failIf( bool shouldFail, + const Message &message, + const SourceLine &sourceLine = SourceLine() ); + + /*! \brief Throws a Exception with the specified message and location. + * \deprecated Use failIf( bool, Message, SourceLine ) instead. + * \param shouldFail if \c true then the exception is thrown. Otherwise + * nothing happen. + * \param message Message explaining the assertion failiure. + * \param sourceLine Location of the assertion. + */ + static void CPPUNIT_API failIf( bool shouldFail, + std::string message, + const SourceLine &sourceLine = SourceLine() ); + + /*! \brief Returns a expected value string for a message. + * Typically used to create 'not equal' message, or to check that a message + * contains the expected content when writing unit tests for your custom + * assertions. + * + * \param expectedValue String that represents the expected value. + * \return \a expectedValue prefixed with "Expected: ". + * \see makeActual(). + */ + static std::string CPPUNIT_API makeExpected( const std::string &expectedValue ); + + /*! \brief Returns an actual value string for a message. + * Typically used to create 'not equal' message, or to check that a message + * contains the expected content when writing unit tests for your custom + * assertions. + * + * \param actualValue String that represents the actual value. + * \return \a actualValue prefixed with "Actual : ". + * \see makeExpected(). + */ + static std::string CPPUNIT_API makeActual( const std::string &actualValue ); + + static Message CPPUNIT_API makeNotEqualMessage( const std::string &expectedValue, + const std::string &actualValue, + const AdditionalMessage &additionalMessage = AdditionalMessage(), + const std::string &shortDescription = "equality assertion failed"); + + /*! \brief Throws an Exception with the specified message and location. + * \param expected Text describing the expected value. + * \param actual Text describing the actual value. + * \param sourceLine Location of the assertion. + * \param additionalMessage Additional message. Usually used to report + * what are the differences between the expected and actual value. + * \param shortDescription Short description for the failure message. + */ + static void CPPUNIT_API failNotEqual( std::string expected, + std::string actual, + const SourceLine &sourceLine, + const AdditionalMessage &additionalMessage = AdditionalMessage(), + std::string shortDescription = "equality assertion failed" ); + + /*! \brief Throws an Exception with the specified message and location. + * \param shouldFail if \c true then the exception is thrown. Otherwise + * nothing happen. + * \param expected Text describing the expected value. + * \param actual Text describing the actual value. + * \param sourceLine Location of the assertion. + * \param additionalMessage Additional message. Usually used to report + * where the "difference" is located. + * \param shortDescription Short description for the failure message. + */ + static void CPPUNIT_API failNotEqualIf( bool shouldFail, + std::string expected, + std::string actual, + const SourceLine &sourceLine, + const AdditionalMessage &additionalMessage = AdditionalMessage(), + std::string shortDescription = "equality assertion failed" ); + +}; + + +CPPUNIT_NS_END + + +#endif // CPPUNIT_ASSERTER_H diff --git a/UnitTests/cppunit/include/cppunit/BriefTestProgressListener.h b/UnitTests/cppunit/include/cppunit/BriefTestProgressListener.h new file mode 100644 index 0000000..137ca44 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/BriefTestProgressListener.h @@ -0,0 +1,43 @@ +#ifndef CPPUNIT_BRIEFTESTPROGRESSLISTENER_H +#define CPPUNIT_BRIEFTESTPROGRESSLISTENER_H + +#include + + +CPPUNIT_NS_BEGIN + + +/*! \brief TestListener that prints the name of each test before running it. + * \ingroup TrackingTestExecution + */ +class CPPUNIT_API BriefTestProgressListener : public TestListener +{ +public: + /*! Constructs a BriefTestProgressListener object. + */ + BriefTestProgressListener(); + + /// Destructor. + virtual ~BriefTestProgressListener(); + + void startTest( Test *test ); + + void addFailure( const TestFailure &failure ); + + void endTest( Test *test ); + +private: + /// Prevents the use of the copy constructor. + BriefTestProgressListener( const BriefTestProgressListener © ); + + /// Prevents the use of the copy operator. + void operator =( const BriefTestProgressListener © ); + +private: + bool m_lastTestFailed; +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_BRIEFTESTPROGRESSLISTENER_H diff --git a/UnitTests/cppunit/include/cppunit/CompilerOutputter.h b/UnitTests/cppunit/include/cppunit/CompilerOutputter.h new file mode 100644 index 0000000..885fe65 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/CompilerOutputter.h @@ -0,0 +1,146 @@ +#ifndef CPPUNIT_COMPILERTESTRESULTOUTPUTTER_H +#define CPPUNIT_COMPILERTESTRESULTOUTPUTTER_H + +#include +#include +#include + +CPPUNIT_NS_BEGIN + + +class Exception; +class SourceLine; +class Test; +class TestFailure; +class TestResultCollector; + +/*! + * \brief Outputs a TestResultCollector in a compiler compatible format. + * \ingroup WritingTestResult + * + * Printing the test results in a compiler compatible format (assertion + * location has the same format as compiler error), allow you to use your + * IDE to jump to the assertion failure. Location format can be customized (see + * setLocationFormat() ). + * + * For example, when running the test in a post-build with VC++, if an assertion + * fails, you can jump to the assertion by pressing F4 (jump to next error). + * + * Heres is an example of usage (from examples/cppunittest/CppUnitTestMain.cpp): + * \code + * int main( int argc, char* argv[] ) { + * // if command line contains "-selftest" then this is the post build check + * // => the output must be in the compiler error format. + * bool selfTest = (argc > 1) && + * (std::string("-selftest") == argv[1]); + * + * CppUnit::TextUi::TestRunner runner; + * runner.addTest( CppUnitTest::suite() ); // Add the top suite to the test runner + * + * if ( selfTest ) + * { // Change the default outputter to a compiler error format outputter + * // The test runner owns the new outputter. + * runner.setOutputter( new CppUnit::CompilerOutputter( &runner.result(), + * std::cerr ) ); + * } + * + * // Run the test and don't wait a key if post build check. + * bool wasSuccessful = runner.run( "", !selfTest ); + * + * // Return error code 1 if the one of test failed. + * return wasSuccessful ? 0 : 1; + * } + * \endcode + */ +class CPPUNIT_API CompilerOutputter : public Outputter +{ +public: + /*! \brief Constructs a CompilerOutputter object. + * \param result Result of the test run. + * \param stream Stream used to output test result. + * \param locationFormat Error location format used by your compiler. Default + * to \c CPPUNIT_COMPILER_LOCATION_FORMAT which is defined + * in the configuration file. See setLocationFormat() for detail. + * \see setLocationFormat(). + */ + CompilerOutputter( TestResultCollector *result, + OStream &stream, + const std::string &locationFormat = CPPUNIT_COMPILER_LOCATION_FORMAT ); + + /// Destructor. + virtual ~CompilerOutputter(); + + /*! \brief Sets the error location format. + * + * Indicates the format used to report location of failed assertion. This format should + * match the one used by your compiler. + * + * The location format is a string in which the occurence of the following character + * sequence are replaced: + * + * - "%l" => replaced by the line number + * - "%p" => replaced by the full path name of the file ("G:\prg\vc\cppunit\MyTest.cpp") + * - "%f" => replaced by the base name of the file ("MyTest.cpp") + * + * Some examples: + * + * - VC++ error location format: "%p(%l):" => produce "G:\prg\MyTest.cpp(43):" + * - GCC error location format: "%f:%l:" => produce "MyTest.cpp:43:" + * + * Thoses are the two compilers currently supported (gcc format is used if + * VC++ is not detected). If you want your compiler to be automatically supported by + * CppUnit, send a mail to the mailing list (preferred), or submit a feature request + * that indicates how to detect your compiler with the preprocessor (\#ifdef...) and + * your compiler location format. + */ + void setLocationFormat( const std::string &locationFormat ); + + /*! \brief Creates an instance of an outputter that matches your current compiler. + * \deprecated This class is specialized through parameterization instead of subclassing... + * Use CompilerOutputter::CompilerOutputter instead. + */ + static CompilerOutputter *defaultOutputter( TestResultCollector *result, + OStream &stream ); + + void write(); + + void setNoWrap(); + + void setWrapColumn( int wrapColumn ); + + int wrapColumn() const; + + virtual void printSuccess(); + virtual void printFailureReport(); + virtual void printFailuresList(); + virtual void printStatistics(); + virtual void printFailureDetail( TestFailure *failure ); + virtual void printFailureLocation( SourceLine sourceLine ); + virtual void printFailureType( TestFailure *failure ); + virtual void printFailedTestName( TestFailure *failure ); + virtual void printFailureMessage( TestFailure *failure ); + +private: + /// Prevents the use of the copy constructor. + CompilerOutputter( const CompilerOutputter © ); + + /// Prevents the use of the copy operator. + void operator =( const CompilerOutputter © ); + + virtual bool processLocationFormatCommand( char command, + const SourceLine &sourceLine ); + + virtual std::string extractBaseName( const std::string &fileName ) const; + +private: + TestResultCollector *m_result; + OStream &m_stream; + std::string m_locationFormat; + int m_wrapColumn; +}; + + +CPPUNIT_NS_END + + +#endif // CPPUNIT_COMPILERTESTRESULTOUTPUTTER_H diff --git a/UnitTests/cppunit/include/cppunit/Exception.h b/UnitTests/cppunit/include/cppunit/Exception.h new file mode 100644 index 0000000..bf5fcac --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/Exception.h @@ -0,0 +1,90 @@ +#ifndef CPPUNIT_EXCEPTION_H +#define CPPUNIT_EXCEPTION_H + +#include +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +/*! \brief Exceptions thrown by failed assertions. + * \ingroup BrowsingCollectedTestResult + * + * Exception is an exception that serves + * descriptive strings through its what() method + */ +class CPPUNIT_API Exception : public std::exception +{ +public: + /*! \brief Constructs the exception with the specified message and source location. + * \param message Message associated to the exception. + * \param sourceLine Source location related to the exception. + */ + Exception( const Message &message = Message(), + const SourceLine &sourceLine = SourceLine() ); + +#ifdef CPPUNIT_ENABLE_SOURCELINE_DEPRECATED + /*! + * \deprecated Use other constructor instead. + */ + Exception( std::string message, + long lineNumber, + std::string fileName ); +#endif + + /*! \brief Constructs a copy of an exception. + * \param other Exception to copy. + */ + Exception( const Exception &other ); + + /// Destructs the exception + virtual ~Exception() throw(); + + /// Performs an assignment + Exception &operator =( const Exception &other ); + + /// Returns descriptive message + const char *what() const throw(); + + /// Location where the error occured + SourceLine sourceLine() const; + + /// Message related to the exception. + Message message() const; + + /// Set the message. + void setMessage( const Message &message ); + +#ifdef CPPUNIT_ENABLE_SOURCELINE_DEPRECATED + /// The line on which the error occurred + long lineNumber() const; + + /// The file in which the error occurred + std::string fileName() const; + + static const std::string UNKNOWNFILENAME; + static const long UNKNOWNLINENUMBER; +#endif + + /// Clones the exception. + virtual Exception *clone() const; + +protected: + // VC++ does not recognize call to parent class when prefixed + // with a namespace. This is a workaround. + typedef std::exception SuperClass; + + Message m_message; + SourceLine m_sourceLine; + std::string m_whatMessage; +}; + + +CPPUNIT_NS_END + + +#endif // CPPUNIT_EXCEPTION_H + diff --git a/UnitTests/cppunit/include/cppunit/Message.h b/UnitTests/cppunit/include/cppunit/Message.h new file mode 100644 index 0000000..1ae51cc --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/Message.h @@ -0,0 +1,156 @@ +#ifndef CPPUNIT_MESSAGE_H +#define CPPUNIT_MESSAGE_H + +#include + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( push ) +#pragma warning( disable: 4251 ) // X needs to have dll-interface to be used by clients of class Z +#endif + +#include +#include + + +CPPUNIT_NS_BEGIN + + +#if CPPUNIT_NEED_DLL_DECL +// template class CPPUNIT_API std::deque; +#endif + +/*! \brief Message associated to an Exception. + * \ingroup CreatingNewAssertions + * A message is composed of two items: + * - a short description (~20/30 characters) + * - a list of detail strings + * + * The short description is used to indicate how the detail strings should be + * interpreted. It usually indicates the failure types, such as + * "assertion failed", "forced failure", "unexpected exception caught", + * "equality assertion failed"... It should not contains new line character (\n). + * + * Detail strings are used to provide more information about the failure. It + * can contains the asserted expression, the expected and actual values in an + * equality assertion, some addional messages... Detail strings can contains + * new line characters (\n). + */ +class CPPUNIT_API Message +{ +public: + Message(); + + // Ensure thread-safe copy by detaching the string. + Message( const Message &other ); + + explicit Message( const std::string &shortDescription ); + + Message( const std::string &shortDescription, + const std::string &detail1 ); + + Message( const std::string &shortDescription, + const std::string &detail1, + const std::string &detail2 ); + + Message( const std::string &shortDescription, + const std::string &detail1, + const std::string &detail2, + const std::string &detail3 ); + + Message &operator =( const Message &other ); + + /*! \brief Returns the short description. + * \return Short description. + */ + const std::string &shortDescription() const; + + /*! \brief Returns the number of detail string. + * \return Number of detail string. + */ + int detailCount() const; + + /*! \brief Returns the detail at the specified index. + * \param index Zero based index of the detail string to return. + * \returns Detail string at the specified index. + * \exception std::invalid_argument if \a index < 0 or index >= detailCount(). + */ + std::string detailAt( int index ) const; + + /*! \brief Returns a string that represents a list of the detail strings. + * + * Example: + * \code + * Message message( "not equal", "Expected: 3", "Actual: 7" ); + * std::string details = message.details(); + * // details contains: + * // "- Expected: 3\n- Actual: 7\n" \endcode + * + * \return A string that is a concatenation of all the detail strings. Each detail + * string is prefixed with '- ' and suffixed with '\n' before being + * concatenated to the other. + */ + std::string details() const; + + /*! \brief Removes all detail strings. + */ + void clearDetails(); + + /*! \brief Adds a single detail string. + * \param detail Detail string to add. + */ + void addDetail( const std::string &detail ); + + /*! \brief Adds two detail strings. + * \param detail1 Detail string to add. + * \param detail2 Detail string to add. + */ + void addDetail( const std::string &detail1, + const std::string &detail2 ); + + /*! \brief Adds three detail strings. + * \param detail1 Detail string to add. + * \param detail2 Detail string to add. + * \param detail3 Detail string to add. + */ + void addDetail( const std::string &detail1, + const std::string &detail2, + const std::string &detail3 ); + + /*! \brief Adds the detail strings of the specified message. + * \param message All the detail strings of this message are added to this one. + */ + void addDetail( const Message &message ); + + /*! \brief Sets the short description. + * \param shortDescription New short description. + */ + void setShortDescription( const std::string &shortDescription ); + + /*! \brief Tests if a message is identical to another one. + * \param other Message this message is compared to. + * \return \c true if the two message are identical, \c false otherwise. + */ + bool operator ==( const Message &other ) const; + + /*! \brief Tests if a message is different from another one. + * \param other Message this message is compared to. + * \return \c true if the two message are not identical, \c false otherwise. + */ + bool operator !=( const Message &other ) const; + +private: + std::string m_shortDescription; + + typedef CppUnitDeque Details; + Details m_details; +}; + + +CPPUNIT_NS_END + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( pop ) +#endif + + +#endif // CPPUNIT_MESSAGE_H diff --git a/UnitTests/cppunit/include/cppunit/Outputter.h b/UnitTests/cppunit/include/cppunit/Outputter.h new file mode 100644 index 0000000..f31d681 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/Outputter.h @@ -0,0 +1,26 @@ +#ifndef CPPUNIT_OUTPUTTER_H +#define CPPUNIT_OUTPUTTER_H + +#include + + +CPPUNIT_NS_BEGIN + + +/*! \brief Abstract outputter to print test result summary. + * \ingroup WritingTestResult + */ +class CPPUNIT_API Outputter +{ +public: + /// Destructor. + virtual ~Outputter() {} + + virtual void write() =0; +}; + + +CPPUNIT_NS_END + + +#endif // CPPUNIT_OUTPUTTER_H diff --git a/UnitTests/cppunit/include/cppunit/Portability.h b/UnitTests/cppunit/include/cppunit/Portability.h new file mode 100644 index 0000000..591eb86 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/Portability.h @@ -0,0 +1,183 @@ +#ifndef CPPUNIT_PORTABILITY_H +#define CPPUNIT_PORTABILITY_H + +#if defined(_WIN32) && !defined(WIN32) +# define WIN32 1 +#endif + +/* include platform specific config */ +#if defined(__BORLANDC__) +# include +#elif defined (_MSC_VER) +# if _MSC_VER == 1200 && defined(_WIN32_WCE) //evc4 +# include +# else +# include +# endif +#else +# include +#endif + +// Version number of package +#ifndef CPPUNIT_VERSION +#define CPPUNIT_VERSION "1.12.0" +#endif + +#include // define CPPUNIT_API & CPPUNIT_NEED_DLL_DECL +#include + + +/* Options that the library user may switch on or off. + * If the user has not done so, we chose default values. + */ + + +/* Define to 1 if you wish to have the old-style macros + assert(), assertEqual(), assertDoublesEqual(), and assertLongsEqual() */ +#if !defined(CPPUNIT_ENABLE_NAKED_ASSERT) +# define CPPUNIT_ENABLE_NAKED_ASSERT 0 +#endif + +/* Define to 1 if you wish to have the old-style CU_TEST family + of macros. */ +#if !defined(CPPUNIT_ENABLE_CU_TEST_MACROS) +# define CPPUNIT_ENABLE_CU_TEST_MACROS 0 +#endif + +/* Define to 1 if the preprocessor expands (#foo) to "foo" (quotes incl.) + I don't think there is any C preprocess that does NOT support this! */ +#if !defined(CPPUNIT_HAVE_CPP_SOURCE_ANNOTATION) +# define CPPUNIT_HAVE_CPP_SOURCE_ANNOTATION 1 +#endif + +/* Assumes that STL and CppUnit are in global space if the compiler does not + support namespace. */ +#if !defined(CPPUNIT_HAVE_NAMESPACES) +# if !defined(CPPUNIT_NO_NAMESPACE) +# define CPPUNIT_NO_NAMESPACE 1 +# endif // !defined(CPPUNIT_NO_NAMESPACE) +# if !defined(CPPUNIT_NO_STD_NAMESPACE) +# define CPPUNIT_NO_STD_NAMESPACE 1 +# endif // !defined(CPPUNIT_NO_STD_NAMESPACE) +#endif // !defined(CPPUNIT_HAVE_NAMESPACES) + +/* Define CPPUNIT_STD_NEED_ALLOCATOR to 1 if you need to specify + * the allocator you used when instantiating STL container. Typically + * used for compilers that do not support template default parameter. + * CPPUNIT_STD_ALLOCATOR will be used as the allocator. Default is + * std::allocator. On some compilers, you may need to change this to + * std::allocator. + */ +#if CPPUNIT_STD_NEED_ALLOCATOR +# if !defined(CPPUNIT_STD_ALLOCATOR) +# define CPPUNIT_STD_ALLOCATOR std::allocator +# endif // !defined(CPPUNIT_STD_ALLOCATOR) +#endif // defined(CPPUNIT_STD_NEED_ALLOCATOR) + + +// Compiler error location format for CompilerOutputter +// If not define, assumes that it's gcc +// See class CompilerOutputter for format. +#if !defined(CPPUNIT_COMPILER_LOCATION_FORMAT) +#if defined(__GNUC__) && ( defined(__APPLE_CPP__) || defined(__APPLE_CC__) ) +// gcc/Xcode integration on Mac OS X +# define CPPUNIT_COMPILER_LOCATION_FORMAT "%p:%l: " +#else +# define CPPUNIT_COMPILER_LOCATION_FORMAT "%f:%l:" +#endif +#endif + +// If CPPUNIT_HAVE_CPP_CAST is defined, then c++ style cast will be used, +// otherwise, C style cast are used. +#if defined( CPPUNIT_HAVE_CPP_CAST ) +# define CPPUNIT_CONST_CAST( TargetType, pointer ) \ + const_cast( pointer ) + +# define CPPUNIT_STATIC_CAST( TargetType, pointer ) \ + static_cast( pointer ) +#else // defined( CPPUNIT_HAVE_CPP_CAST ) +# define CPPUNIT_CONST_CAST( TargetType, pointer ) \ + ((TargetType)( pointer )) +# define CPPUNIT_STATIC_CAST( TargetType, pointer ) \ + ((TargetType)( pointer )) +#endif // defined( CPPUNIT_HAVE_CPP_CAST ) + +// If CPPUNIT_NO_STD_NAMESPACE is defined then STL are in the global space. +// => Define macro 'std' to nothing +#if defined(CPPUNIT_NO_STD_NAMESPACE) +# undef std +# define std +#endif // defined(CPPUNIT_NO_STD_NAMESPACE) + +// If CPPUNIT_NO_NAMESPACE is defined, then put CppUnit classes in the +// global namespace: the compiler does not support namespace. +#if defined(CPPUNIT_NO_NAMESPACE) +# define CPPUNIT_NS_BEGIN +# define CPPUNIT_NS_END +# define CPPUNIT_NS +#else // defined(CPPUNIT_NO_NAMESPACE) +# define CPPUNIT_NS_BEGIN namespace CppUnit { +# define CPPUNIT_NS_END } +# define CPPUNIT_NS CppUnit +#endif // defined(CPPUNIT_NO_NAMESPACE) + +/*! Stringize a symbol. + * + * Use this macro to convert a preprocessor symbol to a string. + * + * Example of usage: + * \code + * #define CPPUNIT_PLUGIN_EXPORTED_NAME cppunitTestPlugIn + * const char *name = CPPUNIT_STRINGIZE( CPPUNIT_PLUGIN_EXPORTED_NAME ); + * \endcode + */ +#define CPPUNIT_STRINGIZE( symbol ) _CPPUNIT_DO_STRINGIZE( symbol ) + +/// \internal +#define _CPPUNIT_DO_STRINGIZE( symbol ) #symbol + +/*! Joins to symbol after expanding them into string. + * + * Use this macro to join two symbols. Example of usage: + * + * \code + * #define MAKE_UNIQUE_NAME(prefix) CPPUNIT_JOIN( prefix, __LINE__ ) + * \endcode + * + * The macro defined in the example concatenate a given prefix with the line number + * to obtain a 'unique' identifier. + * + * \internal From boost documentation: + * The following piece of macro magic joins the two + * arguments together, even when one of the arguments is + * itself a macro (see 16.3.1 in C++ standard). The key + * is that macro expansion of macro arguments does not + * occur in CPPUNIT_JOIN2 but does in CPPUNIT_JOIN. + */ +#define CPPUNIT_JOIN( symbol1, symbol2 ) _CPPUNIT_DO_JOIN( symbol1, symbol2 ) + +/// \internal +#define _CPPUNIT_DO_JOIN( symbol1, symbol2 ) _CPPUNIT_DO_JOIN2( symbol1, symbol2 ) + +/// \internal +#define _CPPUNIT_DO_JOIN2( symbol1, symbol2 ) symbol1##symbol2 + +/// \internal Unique suffix for variable name. Can be overridden in platform specific +/// config-*.h. Default to line number. +#ifndef CPPUNIT_UNIQUE_COUNTER +# define CPPUNIT_UNIQUE_COUNTER __LINE__ +#endif + +/*! Adds the line number to the specified string to create a unique identifier. + * \param prefix Prefix added to the line number to create a unique identifier. + * \see CPPUNIT_TEST_SUITE_REGISTRATION for an example of usage. + */ +#define CPPUNIT_MAKE_UNIQUE_NAME( prefix ) CPPUNIT_JOIN( prefix, CPPUNIT_UNIQUE_COUNTER ) + +/*! Defines wrap colunm for %CppUnit. Used by CompilerOuputter. + */ +#if !defined(CPPUNIT_WRAP_COLUMN) +# define CPPUNIT_WRAP_COLUMN 79 +#endif + +#endif // CPPUNIT_PORTABILITY_H diff --git a/UnitTests/cppunit/include/cppunit/Protector.h b/UnitTests/cppunit/include/cppunit/Protector.h new file mode 100644 index 0000000..d14e75f --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/Protector.h @@ -0,0 +1,94 @@ +#ifndef CPPUNIT_PROTECTOR_H +#define CPPUNIT_PROTECTOR_H + +#include + +CPPUNIT_NS_BEGIN + +class Exception; +class Message; +class ProtectorContext; +class TestResult; + + +class CPPUNIT_API Functor +{ +public: + virtual ~Functor(); + + virtual bool operator()() const =0; +}; + + +/*! \brief Protects one or more test case run. + * + * Protector are used to globably 'decorate' a test case. The most common + * usage of Protector is to catch exception that do not subclass std::exception, + * such as MFC CException class or Rogue Wave RWXMsg class, and capture the + * message associated to the exception. In fact, CppUnit capture message from + * Exception and std::exception using a Protector. + * + * Protector are chained. When you add a Protector using + * TestResult::pushProtector(), your protector is in fact passed as a Functor + * to the first protector of the chain. + * + * TestCase protects call to setUp(), runTest() and tearDown() by calling + * TestResult::protect(). + * + * Because the protector chain is handled by TestResult, a protector can be + * active for a single test, or a complete test run. + * + * Here are some possible usages: + * - run all test case in a separate thread and assumes the test failed if it + * did not finish in a given time (infinite loop work around) + * - performance tracing : time only the runTest() time. + * \sa TestResult, TestCase, TestListener. + */ +class CPPUNIT_API Protector +{ +public: + virtual ~Protector(); + + virtual bool protect( const Functor &functor, + const ProtectorContext &context ) =0; + +protected: + void reportError( const ProtectorContext &context, + const Exception &error ) const; + + void reportError( const ProtectorContext &context, + const Message &message, + const SourceLine &sourceLine = SourceLine() ) const; + + void reportFailure( const ProtectorContext &context, + const Exception &failure ) const; + + Message actualMessage( const Message &message, + const ProtectorContext &context ) const; +}; + + +/*! \brief Scoped protector push to TestResult. + * + * Adds the specified Protector to the specified TestResult for the object + * life-time. + */ +class CPPUNIT_API ProtectorGuard +{ +public: + /// Pushes the specified protector. + ProtectorGuard( TestResult *result, + Protector *protector ); + + /// Pops the protector. + ~ProtectorGuard(); + +private: + TestResult *m_result; +}; + +CPPUNIT_NS_END + + +#endif // CPPUNIT_PROTECTOR_H + diff --git a/UnitTests/cppunit/include/cppunit/SourceLine.h b/UnitTests/cppunit/include/cppunit/SourceLine.h new file mode 100644 index 0000000..f7a85df --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/SourceLine.h @@ -0,0 +1,63 @@ +#ifndef CPPUNIT_SOURCELINE_H +#define CPPUNIT_SOURCELINE_H + +#include +#include + +/*! \brief Constructs a SourceLine object initialized with the location where the macro is expanded. + * \ingroup CreatingNewAssertions + * \relates CppUnit::SourceLine + * Used to write your own assertion macros. + * \see Asserter for example of usage. + */ +#define CPPUNIT_SOURCELINE() CPPUNIT_NS::SourceLine( __FILE__, __LINE__ ) + + +CPPUNIT_NS_BEGIN + + +/*! \brief Represents a source line location. + * \ingroup CreatingNewAssertions + * \ingroup BrowsingCollectedTestResult + * + * Used to capture the failure location in assertion. + * + * Use the CPPUNIT_SOURCELINE() macro to construct that object. Typically used when + * writing an assertion macro in association with Asserter. + * + * \see Asserter. + */ +class CPPUNIT_API SourceLine +{ +public: + SourceLine(); + + // Ensure thread-safe copy by detaching the string buffer. + SourceLine( const SourceLine &other ); + + SourceLine( const std::string &fileName, + int lineNumber ); + + SourceLine &operator =( const SourceLine &other ); + + /// Destructor. + virtual ~SourceLine(); + + bool isValid() const; + + int lineNumber() const; + + std::string fileName() const; + + bool operator ==( const SourceLine &other ) const; + bool operator !=( const SourceLine &other ) const; + +private: + std::string m_fileName; + int m_lineNumber; +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_SOURCELINE_H diff --git a/UnitTests/cppunit/include/cppunit/SynchronizedObject.h b/UnitTests/cppunit/include/cppunit/SynchronizedObject.h new file mode 100644 index 0000000..0f7d094 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/SynchronizedObject.h @@ -0,0 +1,80 @@ +#ifndef CPPUNIT_SYNCHRONIZEDOBJECT_H +#define CPPUNIT_SYNCHRONIZEDOBJECT_H + +#include + + +CPPUNIT_NS_BEGIN + + +/*! \brief Base class for synchronized object. + * + * Synchronized object are object which members are used concurrently by mutiple + * threads. + * + * This class define the class SynchronizationObject which must be subclassed + * to implement an actual lock. + * + * Each instance of this class holds a pointer on a lock object. + * + * See src/msvc6/MfcSynchronizedObject.h for an example. + */ +class CPPUNIT_API SynchronizedObject +{ +public: + /*! \brief Abstract synchronization object (mutex) + */ + class SynchronizationObject + { + public: + SynchronizationObject() {} + virtual ~SynchronizationObject() {} + + virtual void lock() {} + virtual void unlock() {} + }; + + /*! Constructs a SynchronizedObject object. + */ + SynchronizedObject( SynchronizationObject *syncObject =0 ); + + /// Destructor. + virtual ~SynchronizedObject(); + +protected: + /*! \brief Locks a synchronization object in the current scope. + */ + class ExclusiveZone + { + SynchronizationObject *m_syncObject; + + public: + ExclusiveZone( SynchronizationObject *syncObject ) + : m_syncObject( syncObject ) + { + m_syncObject->lock(); + } + + ~ExclusiveZone() + { + m_syncObject->unlock (); + } + }; + + virtual void setSynchronizationObject( SynchronizationObject *syncObject ); + +protected: + SynchronizationObject *m_syncObject; + +private: + /// Prevents the use of the copy constructor. + SynchronizedObject( const SynchronizedObject © ); + + /// Prevents the use of the copy operator. + void operator =( const SynchronizedObject © ); +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_SYNCHRONIZEDOBJECT_H diff --git a/UnitTests/cppunit/include/cppunit/Test.h b/UnitTests/cppunit/include/cppunit/Test.h new file mode 100644 index 0000000..a56be0f --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/Test.h @@ -0,0 +1,117 @@ +#ifndef CPPUNIT_TEST_H +#define CPPUNIT_TEST_H + +#include +#include + +CPPUNIT_NS_BEGIN + + +class TestResult; +class TestPath; + +/*! \brief Base class for all test objects. + * \ingroup BrowsingCollectedTestResult + * + * All test objects should be a subclass of Test. Some test objects, + * TestCase for example, represent one individual test. Other test + * objects, such as TestSuite, are comprised of several tests. + * + * When a Test is run, the result is collected by a TestResult object. + * + * \see TestCase + * \see TestSuite + */ +class CPPUNIT_API Test +{ +public: + virtual ~Test() {}; + + /*! \brief Run the test, collecting results. + */ + virtual void run( TestResult *result ) =0; + + /*! \brief Return the number of test cases invoked by run(). + * + * The base unit of testing is the class TestCase. This + * method returns the number of TestCase objects invoked by + * the run() method. + */ + virtual int countTestCases () const =0; + + /*! \brief Returns the number of direct child of the test. + */ + virtual int getChildTestCount() const =0; + + /*! \brief Returns the child test of the specified index. + * + * This method test if the index is valid, then call doGetChildTestAt() if + * the index is valid. Otherwise std::out_of_range exception is thrown. + * + * You should override doGetChildTestAt() method. + * + * \param index Zero based index of the child test to return. + * \return Pointer on the test. Never \c NULL. + * \exception std::out_of_range is \a index is < 0 or >= getChildTestCount(). + */ + virtual Test *getChildTestAt( int index ) const; + + /*! \brief Returns the test name. + * + * Each test has a name. This name may be used to find the + * test in a suite or registry of tests. + */ + virtual std::string getName () const =0; + + /*! \brief Finds the test with the specified name and its parents test. + * \param testName Name of the test to find. + * \param testPath If the test is found, then all the tests traversed to access + * \a test are added to \a testPath, including \c this and \a test. + * \return \c true if a test with the specified name is found, \c false otherwise. + */ + virtual bool findTestPath( const std::string &testName, + TestPath &testPath ) const; + + /*! \brief Finds the specified test and its parents test. + * \param test Test to find. + * \param testPath If the test is found, then all the tests traversed to access + * \a test are added to \a testPath, including \c this and \a test. + * \return \c true if the specified test is found, \c false otherwise. + */ + virtual bool findTestPath( const Test *test, + TestPath &testPath ) const; + + /*! \brief Finds the test with the specified name in the hierarchy. + * \param testName Name of the test to find. + * \return Pointer on the first test found that is named \a testName. Never \c NULL. + * \exception std::invalid_argument if no test named \a testName is found. + */ + virtual Test *findTest( const std::string &testName ) const; + + /*! \brief Resolved the specified test path with this test acting as 'root'. + * \param testPath Test path string to resolve. + * \return Resolved TestPath. + * \exception std::invalid_argument if \a testPath could not be resolved. + * \see TestPath. + */ + virtual TestPath resolveTestPath( const std::string &testPath ) const; + +protected: + /*! Throws an exception if the specified index is invalid. + * \param index Zero base index of a child test. + * \exception std::out_of_range is \a index is < 0 or >= getChildTestCount(). + */ + virtual void checkIsValidIndex( int index ) const; + + /*! \brief Returns the child test of the specified valid index. + * \param index Zero based valid index of the child test to return. + * \return Pointer on the test. Never \c NULL. + */ + virtual Test *doGetChildTestAt( int index ) const =0; +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_TEST_H + diff --git a/UnitTests/cppunit/include/cppunit/TestAssert.h b/UnitTests/cppunit/include/cppunit/TestAssert.h new file mode 100644 index 0000000..f74797b --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TestAssert.h @@ -0,0 +1,428 @@ +#ifndef CPPUNIT_TESTASSERT_H +#define CPPUNIT_TESTASSERT_H + +#include +#include +#include +#include +#include +#include // For struct assertion_traits + + +CPPUNIT_NS_BEGIN + + +/*! \brief Traits used by CPPUNIT_ASSERT_EQUAL(). + * + * Here is an example of specialising these traits: + * + * \code + * template<> + * struct assertion_traits // specialization for the std::string type + * { + * static bool equal( const std::string& x, const std::string& y ) + * { + * return x == y; + * } + * + * static std::string toString( const std::string& x ) + * { + * std::string text = '"' + x + '"'; // adds quote around the string to see whitespace + * OStringStream ost; + * ost << text; + * return ost.str(); + * } + * }; + * \endcode + */ +template +struct assertion_traits +{ + static bool equal( const T& x, const T& y ) + { + return x == y; + } + + static std::string toString( const T& x ) + { + OStringStream ost; + ost << x; + return ost.str(); + } +}; + + +/*! \brief Traits used by CPPUNIT_ASSERT_DOUBLES_EQUAL(). + * + * This specialisation from @c struct @c assertion_traits<> ensures that + * doubles are converted in full, instead of being rounded to the default + * 6 digits of precision. Use the system defined ISO C99 macro DBL_DIG + * within float.h is available to define the maximum precision, otherwise + * use the hard-coded maximum precision of 15. + */ +template <> +struct assertion_traits +{ + static bool equal( double x, double y ) + { + return x == y; + } + + static std::string toString( double x ) + { +#ifdef DBL_DIG + const int precision = DBL_DIG; +#else + const int precision = 15; +#endif // #ifdef DBL_DIG + char buffer[128]; +#ifdef __STDC_SECURE_LIB__ // Use secure version with visual studio 2005 to avoid warning. + sprintf_s(buffer, sizeof(buffer), "%.*g", precision, x); +#else + sprintf(buffer, "%.*g", precision, x); +#endif + return buffer; + } +}; + + +/*! \brief (Implementation) Asserts that two objects of the same type are equals. + * Use CPPUNIT_ASSERT_EQUAL instead of this function. + * \sa assertion_traits, Asserter::failNotEqual(). + */ +template +void assertEquals( const T& expected, + const T& actual, + SourceLine sourceLine, + const std::string &message ) +{ + if ( !assertion_traits::equal(expected,actual) ) // lazy toString conversion... + { + Asserter::failNotEqual( assertion_traits::toString(expected), + assertion_traits::toString(actual), + sourceLine, + message ); + } +} + + +/*! \brief (Implementation) Asserts that two double are equals given a tolerance. + * Use CPPUNIT_ASSERT_DOUBLES_EQUAL instead of this function. + * \sa Asserter::failNotEqual(). + * \sa CPPUNIT_ASSERT_DOUBLES_EQUAL for detailed semantic of the assertion. + */ +void CPPUNIT_API assertDoubleEquals( double expected, + double actual, + double delta, + SourceLine sourceLine, + const std::string &message ); + + +/* A set of macros which allow us to get the line number + * and file name at the point of an error. + * Just goes to show that preprocessors do have some + * redeeming qualities. + */ +#if CPPUNIT_HAVE_CPP_SOURCE_ANNOTATION +/** Assertions that a condition is \c true. + * \ingroup Assertions + */ +#define CPPUNIT_ASSERT(condition) \ + ( CPPUNIT_NS::Asserter::failIf( !(condition), \ + CPPUNIT_NS::Message( "assertion failed", \ + "Expression: " #condition), \ + CPPUNIT_SOURCELINE() ) ) +#else +#define CPPUNIT_ASSERT(condition) \ + ( CPPUNIT_NS::Asserter::failIf( !(condition), \ + CPPUNIT_NS::Message( "assertion failed" ), \ + CPPUNIT_SOURCELINE() ) ) +#endif + +/** Assertion with a user specified message. + * \ingroup Assertions + * \param message Message reported in diagnostic if \a condition evaluates + * to \c false. + * \param condition If this condition evaluates to \c false then the + * test failed. + */ +#define CPPUNIT_ASSERT_MESSAGE(message,condition) \ + ( CPPUNIT_NS::Asserter::failIf( !(condition), \ + CPPUNIT_NS::Message( "assertion failed", \ + "Expression: " \ + #condition, \ + message ), \ + CPPUNIT_SOURCELINE() ) ) + +/** Fails with the specified message. + * \ingroup Assertions + * \param message Message reported in diagnostic. + */ +#define CPPUNIT_FAIL( message ) \ + ( CPPUNIT_NS::Asserter::fail( CPPUNIT_NS::Message( "forced failure", \ + message ), \ + CPPUNIT_SOURCELINE() ) ) + +#ifdef CPPUNIT_ENABLE_SOURCELINE_DEPRECATED +/// Generalized macro for primitive value comparisons +#define CPPUNIT_ASSERT_EQUAL(expected,actual) \ + ( CPPUNIT_NS::assertEquals( (expected), \ + (actual), \ + __LINE__, __FILE__ ) ) +#else +/** Asserts that two values are equals. + * \ingroup Assertions + * + * Equality and string representation can be defined with + * an appropriate CppUnit::assertion_traits class. + * + * A diagnostic is printed if actual and expected values disagree. + * + * Requirement for \a expected and \a actual parameters: + * - They are exactly of the same type + * - They are serializable into a std::strstream using operator <<. + * - They can be compared using operator ==. + * + * The last two requirements (serialization and comparison) can be + * removed by specializing the CppUnit::assertion_traits. + */ +#define CPPUNIT_ASSERT_EQUAL(expected,actual) \ + ( CPPUNIT_NS::assertEquals( (expected), \ + (actual), \ + CPPUNIT_SOURCELINE(), \ + "" ) ) + +/** Asserts that two values are equals, provides additional message on failure. + * \ingroup Assertions + * + * Equality and string representation can be defined with + * an appropriate assertion_traits class. + * + * A diagnostic is printed if actual and expected values disagree. + * The message is printed in addition to the expected and actual value + * to provide additional information. + * + * Requirement for \a expected and \a actual parameters: + * - They are exactly of the same type + * - They are serializable into a std::strstream using operator <<. + * - They can be compared using operator ==. + * + * The last two requirements (serialization and comparison) can be + * removed by specializing the CppUnit::assertion_traits. + */ +#define CPPUNIT_ASSERT_EQUAL_MESSAGE(message,expected,actual) \ + ( CPPUNIT_NS::assertEquals( (expected), \ + (actual), \ + CPPUNIT_SOURCELINE(), \ + (message) ) ) +#endif + +/*! \brief Macro for primitive double value comparisons. + * \ingroup Assertions + * + * The assertion pass if both expected and actual are finite and + * \c fabs( \c expected - \c actual ) <= \c delta. + * If either \c expected or actual are infinite (+/- inf), the + * assertion pass if \c expected == \c actual. + * If either \c expected or \c actual is a NaN (not a number), then + * the assertion fails. + */ +#define CPPUNIT_ASSERT_DOUBLES_EQUAL(expected,actual,delta) \ + ( CPPUNIT_NS::assertDoubleEquals( (expected), \ + (actual), \ + (delta), \ + CPPUNIT_SOURCELINE(), \ + "" ) ) + + +/*! \brief Macro for primitive double value comparisons, setting a + * user-supplied message in case of failure. + * \ingroup Assertions + * \sa CPPUNIT_ASSERT_DOUBLES_EQUAL for detailed semantic of the assertion. + */ +#define CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(message,expected,actual,delta) \ + ( CPPUNIT_NS::assertDoubleEquals( (expected), \ + (actual), \ + (delta), \ + CPPUNIT_SOURCELINE(), \ + (message) ) ) + + +/** Asserts that the given expression throws an exception of the specified type. + * \ingroup Assertions + * Example of usage: + * \code + * std::vector v; + * CPPUNIT_ASSERT_THROW( v.at( 50 ), std::out_of_range ); + * \endcode + */ +# define CPPUNIT_ASSERT_THROW( expression, ExceptionType ) \ + CPPUNIT_ASSERT_THROW_MESSAGE( CPPUNIT_NS::AdditionalMessage(), \ + expression, \ + ExceptionType ) + + +// implementation detail +#if CPPUNIT_USE_TYPEINFO_NAME +#define CPPUNIT_EXTRACT_EXCEPTION_TYPE_( exception, no_rtti_message ) \ + CPPUNIT_NS::TypeInfoHelper::getClassName( typeid(exception) ) +#else +#define CPPUNIT_EXTRACT_EXCEPTION_TYPE_( exception, no_rtti_message ) \ + std::string( no_rtti_message ) +#endif // CPPUNIT_USE_TYPEINFO_NAME + +// implementation detail +#define CPPUNIT_GET_PARAMETER_STRING( parameter ) #parameter + +/** Asserts that the given expression throws an exception of the specified type, + * setting a user supplied message in case of failure. + * \ingroup Assertions + * Example of usage: + * \code + * std::vector v; + * CPPUNIT_ASSERT_THROW_MESSAGE( "- std::vector v;", v.at( 50 ), std::out_of_range ); + * \endcode + */ +# define CPPUNIT_ASSERT_THROW_MESSAGE( message, expression, ExceptionType ) \ + do { \ + bool cpputCorrectExceptionThrown_ = false; \ + CPPUNIT_NS::Message cpputMsg_( "expected exception not thrown" ); \ + cpputMsg_.addDetail( message ); \ + cpputMsg_.addDetail( "Expected: " \ + CPPUNIT_GET_PARAMETER_STRING( ExceptionType ) ); \ + \ + try { \ + expression; \ + } catch ( const ExceptionType & ) { \ + cpputCorrectExceptionThrown_ = true; \ + } catch ( const std::exception &e) { \ + cpputMsg_.addDetail( "Actual : " + \ + CPPUNIT_EXTRACT_EXCEPTION_TYPE_( e, \ + "std::exception or derived") ); \ + cpputMsg_.addDetail( std::string("What() : ") + e.what() ); \ + } catch ( ... ) { \ + cpputMsg_.addDetail( "Actual : unknown."); \ + } \ + \ + if ( cpputCorrectExceptionThrown_ ) \ + break; \ + \ + CPPUNIT_NS::Asserter::fail( cpputMsg_, \ + CPPUNIT_SOURCELINE() ); \ + } while ( false ) + + +/** Asserts that the given expression does not throw any exceptions. + * \ingroup Assertions + * Example of usage: + * \code + * std::vector v; + * v.push_back( 10 ); + * CPPUNIT_ASSERT_NO_THROW( v.at( 0 ) ); + * \endcode + */ +# define CPPUNIT_ASSERT_NO_THROW( expression ) \ + CPPUNIT_ASSERT_NO_THROW_MESSAGE( CPPUNIT_NS::AdditionalMessage(), \ + expression ) + + +/** Asserts that the given expression does not throw any exceptions, + * setting a user supplied message in case of failure. + * \ingroup Assertions + * Example of usage: + * \code + * std::vector v; + * v.push_back( 10 ); + * CPPUNIT_ASSERT_NO_THROW( "std::vector v;", v.at( 0 ) ); + * \endcode + */ +# define CPPUNIT_ASSERT_NO_THROW_MESSAGE( message, expression ) \ + do { \ + CPPUNIT_NS::Message cpputMsg_( "unexpected exception caught" ); \ + cpputMsg_.addDetail( message ); \ + \ + try { \ + expression; \ + } catch ( const std::exception &e ) { \ + cpputMsg_.addDetail( "Caught: " + \ + CPPUNIT_EXTRACT_EXCEPTION_TYPE_( e, \ + "std::exception or derived" ) ); \ + cpputMsg_.addDetail( std::string("What(): ") + e.what() ); \ + CPPUNIT_NS::Asserter::fail( cpputMsg_, \ + CPPUNIT_SOURCELINE() ); \ + } catch ( ... ) { \ + cpputMsg_.addDetail( "Caught: unknown." ); \ + CPPUNIT_NS::Asserter::fail( cpputMsg_, \ + CPPUNIT_SOURCELINE() ); \ + } \ + } while ( false ) + + +/** Asserts that an assertion fail. + * \ingroup Assertions + * Use to test assertions. + * Example of usage: + * \code + * CPPUNIT_ASSERT_ASSERTION_FAIL( CPPUNIT_ASSERT( 1 == 2 ) ); + * \endcode + */ +# define CPPUNIT_ASSERT_ASSERTION_FAIL( assertion ) \ + CPPUNIT_ASSERT_THROW( assertion, CPPUNIT_NS::Exception ) + + +/** Asserts that an assertion fail, with a user-supplied message in + * case of error. + * \ingroup Assertions + * Use to test assertions. + * Example of usage: + * \code + * CPPUNIT_ASSERT_ASSERTION_FAIL_MESSAGE( "1 == 2", CPPUNIT_ASSERT( 1 == 2 ) ); + * \endcode + */ +# define CPPUNIT_ASSERT_ASSERTION_FAIL_MESSAGE( message, assertion ) \ + CPPUNIT_ASSERT_THROW_MESSAGE( message, assertion, CPPUNIT_NS::Exception ) + + +/** Asserts that an assertion pass. + * \ingroup Assertions + * Use to test assertions. + * Example of usage: + * \code + * CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( 1 == 1 ) ); + * \endcode + */ +# define CPPUNIT_ASSERT_ASSERTION_PASS( assertion ) \ + CPPUNIT_ASSERT_NO_THROW( assertion ) + + +/** Asserts that an assertion pass, with a user-supplied message in + * case of failure. + * \ingroup Assertions + * Use to test assertions. + * Example of usage: + * \code + * CPPUNIT_ASSERT_ASSERTION_PASS_MESSAGE( "1 != 1", CPPUNIT_ASSERT( 1 == 1 ) ); + * \endcode + */ +# define CPPUNIT_ASSERT_ASSERTION_PASS_MESSAGE( message, assertion ) \ + CPPUNIT_ASSERT_NO_THROW_MESSAGE( message, assertion ) + + + + +// Backwards compatibility + +#if CPPUNIT_ENABLE_NAKED_ASSERT + +#undef assert +#define assert(c) CPPUNIT_ASSERT(c) +#define assertEqual(e,a) CPPUNIT_ASSERT_EQUAL(e,a) +#define assertDoublesEqual(e,a,d) CPPUNIT_ASSERT_DOUBLES_EQUAL(e,a,d) +#define assertLongsEqual(e,a) CPPUNIT_ASSERT_EQUAL(e,a) + +#endif + + +CPPUNIT_NS_END + +#endif // CPPUNIT_TESTASSERT_H diff --git a/UnitTests/cppunit/include/cppunit/TestCaller.h b/UnitTests/cppunit/include/cppunit/TestCaller.h new file mode 100644 index 0000000..dc4d82e --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TestCaller.h @@ -0,0 +1,204 @@ +#ifndef CPPUNIT_TESTCALLER_H // -*- C++ -*- +#define CPPUNIT_TESTCALLER_H + +#include +#include + + +#if CPPUNIT_USE_TYPEINFO_NAME +# include +#endif + + +CPPUNIT_NS_BEGIN + +#if 0 +/*! \brief Marker class indicating that no exception is expected by TestCaller. + * This class is an implementation detail. You should never use this class directly. + */ +class CPPUNIT_API NoExceptionExpected +{ +private: + //! Prevent class instantiation. + NoExceptionExpected(); +}; + + +/*! \brief (Implementation) Traits used by TestCaller to expect an exception. + * + * This class is an implementation detail. You should never use this class directly. + */ +template +struct ExpectedExceptionTraits +{ + static void expectedException() + { +#if CPPUNIT_USE_TYPEINFO_NAME + throw Exception( Message( + "expected exception not thrown", + "Expected exception type: " + + TypeInfoHelper::getClassName( typeid( ExceptionType ) ) ) ); +#else + throw Exception( "expected exception not thrown" ); +#endif + } +}; + + +/*! \brief (Implementation) Traits specialization used by TestCaller to + * expect no exception. + * + * This class is an implementation detail. You should never use this class directly. + */ +template<> +struct ExpectedExceptionTraits +{ + static void expectedException() + { + } +}; + + +#endif + +//*** FIXME: rework this when class Fixture is implemented. ***// + + +/*! \brief Generate a test case from a fixture method. + * \ingroup WritingTestFixture + * + * A test caller provides access to a test case method + * on a test fixture class. Test callers are useful when + * you want to run an individual test or add it to a + * suite. + * Test Callers invoke only one Test (i.e. test method) on one + * Fixture of a TestFixture. + * + * Here is an example: + * \code + * class MathTest : public CppUnit::TestFixture { + * ... + * public: + * void setUp(); + * void tearDown(); + * + * void testAdd(); + * void testSubtract(); + * }; + * + * CppUnit::Test *MathTest::suite() { + * CppUnit::TestSuite *suite = new CppUnit::TestSuite; + * + * suite->addTest( new CppUnit::TestCaller( "testAdd", testAdd ) ); + * return suite; + * } + * \endcode + * + * You can use a TestCaller to bind any test method on a TestFixture + * class, as long as it accepts void and returns void. + * + * \see TestCase + */ + +template +class TestCaller : public TestCase +{ + typedef void (Fixture::*TestMethod)(); + +public: + /*! + * Constructor for TestCaller. This constructor builds a new Fixture + * instance owned by the TestCaller. + * \param name name of this TestCaller + * \param test the method this TestCaller calls in runTest() + */ + TestCaller( std::string name, TestMethod test ) : + TestCase( name ), + m_ownFixture( true ), + m_fixture( new Fixture() ), + m_test( test ) + { + } + + /*! + * Constructor for TestCaller. + * This constructor does not create a new Fixture instance but accepts + * an existing one as parameter. The TestCaller will not own the + * Fixture object. + * \param name name of this TestCaller + * \param test the method this TestCaller calls in runTest() + * \param fixture the Fixture to invoke the test method on. + */ + TestCaller(std::string name, TestMethod test, Fixture& fixture) : + TestCase( name ), + m_ownFixture( false ), + m_fixture( &fixture ), + m_test( test ) + { + } + + /*! + * Constructor for TestCaller. + * This constructor does not create a new Fixture instance but accepts + * an existing one as parameter. The TestCaller will own the + * Fixture object and delete it in its destructor. + * \param name name of this TestCaller + * \param test the method this TestCaller calls in runTest() + * \param fixture the Fixture to invoke the test method on. + */ + TestCaller(std::string name, TestMethod test, Fixture* fixture) : + TestCase( name ), + m_ownFixture( true ), + m_fixture( fixture ), + m_test( test ) + { + } + + ~TestCaller() + { + if (m_ownFixture) + delete m_fixture; + } + + void runTest() + { +// try { + (m_fixture->*m_test)(); +// } +// catch ( ExpectedException & ) { +// return; +// } + +// ExpectedExceptionTraits::expectedException(); + } + + void setUp() + { + m_fixture->setUp (); + } + + void tearDown() + { + m_fixture->tearDown (); + } + + std::string toString() const + { + return "TestCaller " + getName(); + } + +private: + TestCaller( const TestCaller &other ); + TestCaller &operator =( const TestCaller &other ); + +private: + bool m_ownFixture; + Fixture *m_fixture; + TestMethod m_test; +}; + + + +CPPUNIT_NS_END + +#endif // CPPUNIT_TESTCALLER_H diff --git a/UnitTests/cppunit/include/cppunit/TestCase.h b/UnitTests/cppunit/include/cppunit/TestCase.h new file mode 100644 index 0000000..d4b7a46 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TestCase.h @@ -0,0 +1,55 @@ +#ifndef CPPUNIT_TESTCASE_H +#define CPPUNIT_TESTCASE_H + +#include +#include +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +class TestResult; + + +/*! \brief A single test object. + * + * This class is used to implement a simple test case: define a subclass + * that overrides the runTest method. + * + * You don't usually need to use that class, but TestFixture and TestCaller instead. + * + * You are expected to subclass TestCase is you need to write a class similiar + * to TestCaller. + */ +class CPPUNIT_API TestCase : public TestLeaf, + public TestFixture +{ +public: + + TestCase( const std::string &name ); + + TestCase(); + + ~TestCase(); + + virtual void run(TestResult *result); + + std::string getName() const; + + //! FIXME: this should probably be pure virtual. + virtual void runTest(); + +private: + TestCase( const TestCase &other ); + TestCase &operator=( const TestCase &other ); + +private: + const std::string m_name; +}; + +CPPUNIT_NS_END + +#endif // CPPUNIT_TESTCASE_H diff --git a/UnitTests/cppunit/include/cppunit/TestComposite.h b/UnitTests/cppunit/include/cppunit/TestComposite.h new file mode 100644 index 0000000..0ded95f --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TestComposite.h @@ -0,0 +1,45 @@ +#ifndef CPPUNIT_TESTCOMPSITE_H // -*- C++ -*- +#define CPPUNIT_TESTCOMPSITE_H + +#include +#include + +CPPUNIT_NS_BEGIN + + +/*! \brief A Composite of Tests. + * + * Base class for all test composites. Subclass this class if you need to implement + * a custom TestSuite. + * + * \see Test, TestSuite. + */ +class CPPUNIT_API TestComposite : public Test +{ +public: + TestComposite( const std::string &name = "" ); + + ~TestComposite(); + + void run( TestResult *result ); + + int countTestCases() const; + + std::string getName() const; + +private: + TestComposite( const TestComposite &other ); + TestComposite &operator =( const TestComposite &other ); + + virtual void doStartSuite( TestResult *controller ); + virtual void doRunChildTests( TestResult *controller ); + virtual void doEndSuite( TestResult *controller ); + +private: + const std::string m_name; +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_TESTCOMPSITE_H diff --git a/UnitTests/cppunit/include/cppunit/TestFailure.h b/UnitTests/cppunit/include/cppunit/TestFailure.h new file mode 100644 index 0000000..6419979 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TestFailure.h @@ -0,0 +1,58 @@ +#ifndef CPPUNIT_TESTFAILURE_H // -*- C++ -*- +#define CPPUNIT_TESTFAILURE_H + +#include +#include + +CPPUNIT_NS_BEGIN + + +class Exception; +class SourceLine; +class Test; + + +/*! \brief Record of a failed Test execution. + * \ingroup BrowsingCollectedTestResult + * + * A TestFailure collects a failed test together with + * the caught exception. + * + * TestFailure assumes lifetime control for any exception + * passed to it. + */ +class CPPUNIT_API TestFailure +{ +public: + TestFailure( Test *failedTest, + Exception *thrownException, + bool isError ); + + virtual ~TestFailure (); + + virtual Test *failedTest() const; + + virtual Exception *thrownException() const; + + virtual SourceLine sourceLine() const; + + virtual bool isError() const; + + virtual std::string failedTestName() const; + + virtual TestFailure *clone() const; + +protected: + Test *m_failedTest; + Exception *m_thrownException; + bool m_isError; + +private: + TestFailure( const TestFailure &other ); + TestFailure &operator =( const TestFailure& other ); +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_TESTFAILURE_H diff --git a/UnitTests/cppunit/include/cppunit/TestFixture.h b/UnitTests/cppunit/include/cppunit/TestFixture.h new file mode 100644 index 0000000..1223adb --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TestFixture.h @@ -0,0 +1,99 @@ +#ifndef CPPUNIT_TESTFIXTURE_H // -*- C++ -*- +#define CPPUNIT_TESTFIXTURE_H + +#include + +CPPUNIT_NS_BEGIN + + +/*! \brief Wraps a test case with setUp and tearDown methods. + * \ingroup WritingTestFixture + * + * A TestFixture is used to provide a common environment for a set + * of test cases. + * + * To define a test fixture, do the following: + * - implement a subclass of TestCase + * - the fixture is defined by instance variables + * - initialize the fixture state by overriding setUp + * (i.e. construct the instance variables of the fixture) + * - clean-up after a test by overriding tearDown. + * + * Each test runs in its own fixture so there + * can be no side effects among test runs. + * Here is an example: + * + * \code + * class MathTest : public CppUnit::TestFixture { + * protected: + * int m_value1, m_value2; + * + * public: + * MathTest() {} + * + * void setUp () { + * m_value1 = 2; + * m_value2 = 3; + * } + * } + * \endcode + * + * For each test implement a method which interacts + * with the fixture. Verify the expected results with assertions specified + * by calling CPPUNIT_ASSERT on the expression you want to test: + * + * \code + * public: + * void testAdd () { + * int result = m_value1 + m_value2; + * CPPUNIT_ASSERT( result == 5 ); + * } + * \endcode + * + * Once the methods are defined you can run them. To do this, use + * a TestCaller. + * + * \code + * CppUnit::Test *test = new CppUnit::TestCaller( "testAdd", + * &MathTest::testAdd ); + * test->run(); + * \endcode + * + * + * The tests to be run can be collected into a TestSuite. + * + * \code + * public: + * static CppUnit::TestSuite *MathTest::suite () { + * CppUnit::TestSuite *suiteOfTests = new CppUnit::TestSuite; + * suiteOfTests->addTest(new CppUnit::TestCaller( + * "testAdd", &MathTest::testAdd)); + * suiteOfTests->addTest(new CppUnit::TestCaller( + * "testDivideByZero", &MathTest::testDivideByZero)); + * return suiteOfTests; + * } + * \endcode + * + * A set of macros have been created for convenience. They are located in HelperMacros.h. + * + * \see TestResult, TestSuite, TestCaller, + * \see CPPUNIT_TEST_SUB_SUITE, CPPUNIT_TEST, CPPUNIT_TEST_SUITE_END, + * \see CPPUNIT_TEST_SUITE_REGISTRATION, CPPUNIT_TEST_EXCEPTION, CPPUNIT_TEST_FAIL. + */ +class CPPUNIT_API TestFixture +{ +public: + virtual ~TestFixture() {}; + + //! \brief Set up context before running a test. + virtual void setUp() {}; + + //! Clean up after the test run. + virtual void tearDown() {}; +}; + + +CPPUNIT_NS_END + + +#endif diff --git a/UnitTests/cppunit/include/cppunit/TestLeaf.h b/UnitTests/cppunit/include/cppunit/TestLeaf.h new file mode 100644 index 0000000..c83b075 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TestLeaf.h @@ -0,0 +1,44 @@ +#ifndef CPPUNIT_TESTLEAF_H +#define CPPUNIT_TESTLEAF_H + +#include + + +CPPUNIT_NS_BEGIN + + +/*! \brief A single test object. + * + * Base class for single test case: a test that doesn't have any children. + * + */ +class CPPUNIT_API TestLeaf: public Test +{ +public: + /*! Returns 1 as the default number of test cases invoked by run(). + * + * You may override this method when many test cases are invoked (RepeatedTest + * for example). + * + * \return 1. + * \see Test::countTestCases(). + */ + int countTestCases() const; + + /*! Returns the number of child of this test case: 0. + * + * You should never override this method: a TestLeaf as no children by definition. + * + * \return 0. + */ + int getChildTestCount() const; + + /*! Always throws std::out_of_range. + * \see Test::doGetChildTestAt(). + */ + Test *doGetChildTestAt( int index ) const; +}; + +CPPUNIT_NS_END + +#endif // CPPUNIT_TESTLEAF_H diff --git a/UnitTests/cppunit/include/cppunit/TestListener.h b/UnitTests/cppunit/include/cppunit/TestListener.h new file mode 100644 index 0000000..330262d --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TestListener.h @@ -0,0 +1,148 @@ +#ifndef CPPUNIT_TESTLISTENER_H // -*- C++ -*- +#define CPPUNIT_TESTLISTENER_H + +#include + + +CPPUNIT_NS_BEGIN + + +class Exception; +class Test; +class TestFailure; +class TestResult; + + +/*! \brief Listener for test progress and result. + * \ingroup TrackingTestExecution + * + * Implementing the Observer pattern a TestListener may be registered + * to a TestResult to obtain information on the testing progress. Use + * specialized sub classes of TestListener for text output + * (TextTestProgressListener). Do not use the Listener for the test + * result output, use a subclass of Outputter instead. + * + * The test framework distinguishes between failures and errors. + * A failure is anticipated and checked for with assertions. Errors are + * unanticipated problems signified by exceptions that are not generated + * by the framework. + * + * Here is an example to track test time: + * + * + * \code + * #include + * #include + * #include // for clock() + * + * class TimingListener : public CppUnit::TestListener + * { + * public: + * void startTest( CppUnit::Test *test ) + * { + * _chronometer.start(); + * } + * + * void endTest( CppUnit::Test *test ) + * { + * _chronometer.end(); + * addTest( test, _chronometer.elapsedTime() ); + * } + * + * // ... (interface to add/read test timing result) + * + * private: + * Clock _chronometer; + * }; + * \endcode + * + * And another example that track failure/success at test suite level and captures + * the TestPath of each suite: + * \code + * class SuiteTracker : public CppUnit::TestListener + * { + * public: + * void startSuite( CppUnit::Test *suite ) + * { + * m_currentPath.add( suite ); + * } + * + * void addFailure( const TestFailure &failure ) + * { + * m_suiteFailure.top() = false; + * } + * + * void endSuite( CppUnit::Test *suite ) + * { + * m_suiteStatus.insert( std::make_pair( suite, m_suiteFailure.top() ) ); + * m_suitePaths.insert( std::make_pair( suite, m_currentPath ) ); + * + * m_currentPath.up(); + * m_suiteFailure.pop(); + * } + * + * private: + * std::stack m_suiteFailure; + * CppUnit::TestPath m_currentPath; + * std::map m_suiteStatus; + * std::map m_suitePaths; + * }; + * \endcode + * + * \see TestResult + */ +class CPPUNIT_API TestListener +{ +public: + virtual ~TestListener() {} + + /// Called when just before a TestCase is run. + virtual void startTest( Test * /*test*/ ) {} + + /*! \brief Called when a failure occurs while running a test. + * \see TestFailure. + * \warning \a failure is a temporary object that is destroyed after the + * method call. Use TestFailure::clone() to create a duplicate. + */ + virtual void addFailure( const TestFailure & /*failure*/ ) {} + + /// Called just after a TestCase was run (even if a failure occured). + virtual void endTest( Test * /*test*/ ) {} + + /*! \brief Called by a TestComposite just before running its child tests. + */ + virtual void startSuite( Test * /*suite*/ ) {} + + /*! \brief Called by a TestComposite after running its child tests. + */ + virtual void endSuite( Test * /*suite*/ ) {} + + /*! \brief Called by a TestRunner before running the test. + * + * You can use this to do some global initialisation. A listener + * could also use to output a 'prolog' to the test run. + * + * \param test Test that is going to be run. + * \param eventManager Event manager used for the test run. + */ + virtual void startTestRun( Test * /*test*/, + TestResult * /*eventManager*/ ) {} + + /*! \brief Called by a TestRunner after running the test. + * + * TextTestProgressListener use this to emit a line break. You can also use this + * to do some global uninitialisation. + * + * \param test Test that was run. + * \param eventManager Event manager used for the test run. + */ + virtual void endTestRun( Test * /*test*/, + TestResult * /*eventManager*/ ) {} +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_TESTLISTENER_H + + diff --git a/UnitTests/cppunit/include/cppunit/TestPath.h b/UnitTests/cppunit/include/cppunit/TestPath.h new file mode 100644 index 0000000..c3c851c --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TestPath.h @@ -0,0 +1,211 @@ +#ifndef CPPUNIT_TESTPATH_H +#define CPPUNIT_TESTPATH_H + +#include + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( push ) +#pragma warning( disable: 4251 ) // X needs to have dll-interface to be used by clients of class Z +#endif + +#include +#include + +CPPUNIT_NS_BEGIN + + +class Test; + +#if CPPUNIT_NEED_DLL_DECL +// template class CPPUNIT_API std::deque; +#endif + + +/*! \brief A List of Test representing a path to access a Test. + * \ingroup ExecutingTest + * + * The path can be converted to a string and resolved from a string with toString() + * and TestPath( Test *root, const std::string &pathAsString ). + * + * Pointed tests are not owned by the class. + * + * \see Test::resolvedTestPath() + */ +class CPPUNIT_API TestPath +{ +public: + /*! \brief Constructs an invalid path. + * + * The path is invalid until a test is added with add(). + */ + TestPath(); + + /*! \brief Constructs a valid path. + * + * \param root Test to add. + */ + TestPath( Test *root ); + + /*! \brief Constructs a path using a slice of another path. + * \param otherPath Path the test are copied from. + * \param indexFirst Zero based index of the first test to copy. Adjusted to be in valid + * range. \a count is adjusted with \a indexFirst. + * \param count Number of tests to copy. If < 0 then all test starting from index + * \a indexFirst are copied. + */ + TestPath( const TestPath &otherPath, + int indexFirst, + int count = -1 ); + + /*! \brief Resolves a path from a string returned by toString(). + * + * If \a pathAsString is an absolute path (begins with '/'), then the first test name + * of the path must be the name of \a searchRoot. Otherwise, \a pathAsString is a + * relative path, and the first test found using Test::findTest() matching the first + * test name is used as root. An empty string resolve to a path containing + * \a searchRoot. + * + * The resolved path is always valid. + * + * \param searchRoot Test used to resolve the path. + * \param pathAsString String that contains the path as a string created by toString(). + * \exception std::invalid_argument if one of the test names can not be resolved. + * \see toString(). + */ + TestPath( Test *searchRoot, + const std::string &pathAsString ); + + /*! \brief Copy constructor. + * \param other Object to copy. + */ + TestPath( const TestPath &other ); + + virtual ~TestPath(); + + /*! \brief Tests if the path contains at least one test. + * \return \c true if the path contains at least one test, otherwise returns \c false. + */ + virtual bool isValid() const; + + /*! \brief Adds a test to the path. + * \param test Pointer on the test to add. Must not be \c NULL. + */ + virtual void add( Test *test ); + + /*! \brief Adds all the tests of the specified path. + * \param path Path that contains the test to add. + */ + virtual void add( const TestPath &path ); + + /*! \brief Inserts a test at the specified index. + * \param test Pointer on the test to insert. Must not be \c NULL. + * \param index Zero based index indicating where the test is inserted. + * \exception std::out_of_range is \a index < 0 or \a index > getTestCount(). + */ + virtual void insert( Test *test, int index ); + + /*! \brief Inserts all the tests at the specified path at a given index. + * \param path Path that contains the test to insert. + * \param index Zero based index indicating where the tests are inserted. + * \exception std::out_of_range is \a index < 0 or \a index > getTestCount(), and + * \a path is valid. + */ + virtual void insert( const TestPath &path, int index ); + + /*! \brief Removes all the test from the path. + * + * The path becomes invalid after this call. + */ + virtual void removeTests(); + + /*! \brief Removes the test at the specified index of the path. + * \param index Zero based index of the test to remove. + * \exception std::out_of_range is \a index < 0 or \a index >= getTestCount(). + */ + virtual void removeTest( int index ); + + /*! \brief Removes the last test. + * \exception std::out_of_range is the path is invalid. + * \see isValid(). + */ + virtual void up(); + + /*! \brief Returns the number of tests in the path. + * \return Number of tests in the path. + */ + virtual int getTestCount() const; + + /*! \brief Returns the test of the specified index. + * \param index Zero based index of the test to return. + * \return Pointer on the test at index \a index. Never \c NULL. + * \exception std::out_of_range is \a index < 0 or \a index >= getTestCount(). + */ + virtual Test *getTestAt( int index ) const; + + /*! \brief Get the last test of the path. + * \return Pointer on the last test (test at the bottom of the hierarchy). Never \c NULL. + * \exception std::out_of_range if the path is not valid ( isValid() returns \c false ). + */ + virtual Test *getChildTest() const; + + /*! \brief Returns the path as a string. + * + * For example, if a path is composed of three tests named "All Tests", "Math" and + * "Math::testAdd", toString() will return: + * + * "All Tests/Math/Math::testAdd". + * + * \return A string composed of the test names separated with a '/'. It is a relative + * path. + */ + virtual std::string toString() const; + + /*! \brief Assignment operator. + * \param other Object to copy. + * \return This object. + */ + TestPath &operator =( const TestPath &other ); + +protected: + /*! \brief Checks that the specified test index is within valid range. + * \param index Zero based index to check. + * \exception std::out_of_range is \a index < 0 or \a index >= getTestCount(). + */ + void checkIndexValid( int index ) const; + + /// A list of test names. + typedef CppUnitDeque PathTestNames; + + /*! \brief Splits a path string into its test name components. + * \param pathAsString Path string created with toString(). + * \param testNames Test name components are added to that container. + * \return \c true if the path is relative (does not begin with '/'), \c false + * if it is absolute (begin with '/'). + */ + bool splitPathString( const std::string &pathAsString, + PathTestNames &testNames ); + + /*! \brief Finds the actual root of a path string and get the path string name components. + * \param searchRoot Test used as root if the path string is absolute, or to search + * the root test if the path string is relative. + * \param pathAsString Path string. May be absolute or relative. + * \param testNames Test name components are added to that container. + * \return Pointer on the resolved root test. Never \c NULL. + * \exception std::invalid_argument if either the root name can not be resolved or if + * pathAsString contains no name components. + */ + Test *findActualRoot( Test *searchRoot, + const std::string &pathAsString, + PathTestNames &testNames ); + +protected: + typedef CppUnitDeque Tests; + Tests m_tests; + +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_TESTPATH_H + diff --git a/UnitTests/cppunit/include/cppunit/TestResult.h b/UnitTests/cppunit/include/cppunit/TestResult.h new file mode 100644 index 0000000..e7e1050 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TestResult.h @@ -0,0 +1,156 @@ +#ifndef CPPUNIT_TESTRESULT_H +#define CPPUNIT_TESTRESULT_H + +#include + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( push ) +#pragma warning( disable: 4251 ) // X needs to have dll-interface to be used by clients of class Z +#endif + +#include +#include +#include + +CPPUNIT_NS_BEGIN + + +class Exception; +class Functor; +class Protector; +class ProtectorChain; +class Test; +class TestFailure; +class TestListener; + + +#if CPPUNIT_NEED_DLL_DECL +// template class CPPUNIT_API std::deque; +#endif + +/*! \brief Manages TestListener. + * \ingroup TrackingTestExecution + * + * A single instance of this class is used when running the test. It is usually + * created by the test runner (TestRunner). + * + * This class shouldn't have to be inherited from. Use a TestListener + * or one of its subclasses to be informed of the ongoing tests. + * Use a Outputter to receive a test summary once it has finished + * + * TestResult supplies a template method 'setSynchronizationObject()' + * so that subclasses can provide mutual exclusion in the face of multiple + * threads. This can be useful when tests execute in one thread and + * they fill a subclass of TestResult which effects change in another + * thread. To have mutual exclusion, override setSynchronizationObject() + * and make sure that you create an instance of ExclusiveZone at the + * beginning of each method. + * + * \see Test, TestListener, TestResultCollector, Outputter. + */ +class CPPUNIT_API TestResult : protected SynchronizedObject +{ +public: + /// Construct a TestResult + TestResult( SynchronizationObject *syncObject = 0 ); + + /// Destroys a test result + virtual ~TestResult(); + + virtual void addListener( TestListener *listener ); + + virtual void removeListener( TestListener *listener ); + + /// Resets the stop flag. + virtual void reset(); + + /// Stop testing + virtual void stop(); + + /// Returns whether testing should be stopped + virtual bool shouldStop() const; + + /// Informs TestListener that a test will be started. + virtual void startTest( Test *test ); + + /*! \brief Adds an error to the list of errors. + * The passed in exception + * caused the error + */ + virtual void addError( Test *test, Exception *e ); + + /*! \brief Adds a failure to the list of failures. The passed in exception + * caused the failure. + */ + virtual void addFailure( Test *test, Exception *e ); + + /// Informs TestListener that a test was completed. + virtual void endTest( Test *test ); + + /// Informs TestListener that a test suite will be started. + virtual void startSuite( Test *test ); + + /// Informs TestListener that a test suite was completed. + virtual void endSuite( Test *test ); + + /*! \brief Run the specified test. + * + * Calls startTestRun(), test->run(this), and finally endTestRun(). + */ + virtual void runTest( Test *test ); + + /*! \brief Protects a call to the specified functor. + * + * See Protector to understand how protector works. A default protector is + * always present. It captures CppUnit::Exception, std::exception and + * any other exceptions, retrieving as much as possible information about + * the exception as possible. + * + * Additional Protector can be added to the chain to support other exception + * types using pushProtector() and popProtector(). + * + * \param functor Functor to call (typically a call to setUp(), runTest() or + * tearDown(). + * \param test Test the functor is associated to (used for failure reporting). + * \param shortDescription Short description override for the failure message. + */ + virtual bool protect( const Functor &functor, + Test *test, + const std::string &shortDescription = std::string("") ); + + /// Adds the specified protector to the protector chain. + virtual void pushProtector( Protector *protector ); + + /// Removes the last protector from the protector chain. + virtual void popProtector(); + +protected: + /*! \brief Called to add a failure to the list of failures. + */ + void addFailure( const TestFailure &failure ); + + virtual void startTestRun( Test *test ); + virtual void endTestRun( Test *test ); + +protected: + typedef CppUnitDeque TestListeners; + TestListeners m_listeners; + ProtectorChain *m_protectorChain; + bool m_stop; + +private: + TestResult( const TestResult &other ); + TestResult &operator =( const TestResult &other ); +}; + + +CPPUNIT_NS_END + + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( pop ) +#endif + +#endif // CPPUNIT_TESTRESULT_H + + diff --git a/UnitTests/cppunit/include/cppunit/TestResultCollector.h b/UnitTests/cppunit/include/cppunit/TestResultCollector.h new file mode 100644 index 0000000..01b0a54 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TestResultCollector.h @@ -0,0 +1,87 @@ +#ifndef CPPUNIT_TESTRESULTCOLLECTOR_H +#define CPPUNIT_TESTRESULTCOLLECTOR_H + +#include + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( push ) +#pragma warning( disable: 4251 4660 ) // X needs to have dll-interface to be used by clients of class Z +#endif + +#include +#include + + +CPPUNIT_NS_BEGIN + +#if CPPUNIT_NEED_DLL_DECL +// template class CPPUNIT_API std::deque; +// template class CPPUNIT_API std::deque; +#endif + + +/*! \brief Collects test result. + * \ingroup WritingTestResult + * \ingroup BrowsingCollectedTestResult + * + * A TestResultCollector is a TestListener which collects the results of executing + * a test case. It is an instance of the Collecting Parameter pattern. + * + * The test framework distinguishes between failures and errors. + * A failure is anticipated and checked for with assertions. Errors are + * unanticipated problems signified by exceptions that are not generated + * by the framework. + * \see TestListener, TestFailure. + */ +class CPPUNIT_API TestResultCollector : public TestSuccessListener +{ +public: + typedef CppUnitDeque TestFailures; + typedef CppUnitDeque Tests; + + + /*! Constructs a TestResultCollector object. + */ + TestResultCollector( SynchronizationObject *syncObject = 0 ); + + /// Destructor. + virtual ~TestResultCollector(); + + void startTest( Test *test ); + void addFailure( const TestFailure &failure ); + + virtual void reset(); + + virtual int runTests() const; + virtual int testErrors() const; + virtual int testFailures() const; + virtual int testFailuresTotal() const; + + virtual const TestFailures& failures() const; + virtual const Tests &tests() const; + +protected: + void freeFailures(); + + Tests m_tests; + TestFailures m_failures; + int m_testErrors; + +private: + /// Prevents the use of the copy constructor. + TestResultCollector( const TestResultCollector © ); + + /// Prevents the use of the copy operator. + void operator =( const TestResultCollector © ); +}; + + + +CPPUNIT_NS_END + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( pop ) +#endif + + +#endif // CPPUNIT_TESTRESULTCOLLECTOR_H diff --git a/UnitTests/cppunit/include/cppunit/TestRunner.h b/UnitTests/cppunit/include/cppunit/TestRunner.h new file mode 100644 index 0000000..930370a --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TestRunner.h @@ -0,0 +1,135 @@ +#ifndef CPPUNIT_TESTRUNNER_H +#define CPPUNIT_TESTRUNNER_H + +#include +#include + +CPPUNIT_NS_BEGIN + + +class Test; +class TestResult; + + +/*! \brief Generic test runner. + * \ingroup ExecutingTest + * + * The TestRunner assumes ownership of all added tests: you can not add test + * or suite that are local variable since they can't be deleted. + * + * Example of usage: + * \code + * #include + * #include + * #include + * #include + * #include + * #include + * + * + * int + * main( int argc, char* argv[] ) + * { + * std::string testPath = (argc > 1) ? std::string(argv[1]) : ""; + * + * // Create the event manager and test controller + * CppUnit::TestResult controller; + * + * // Add a listener that colllects test result + * CppUnit::TestResultCollector result; + * controller.addListener( &result ); + * + * // Add a listener that print dots as test run. + * CppUnit::TextTestProgressListener progress; + * controller.addListener( &progress ); + * + * // Add the top suite to the test runner + * CppUnit::TestRunner runner; + * runner.addTest( CppUnit::TestFactoryRegistry::getRegistry().makeTest() ); + * try + * { + * std::cout << "Running " << testPath; + * runner.run( controller, testPath ); + * + * std::cerr << std::endl; + * + * // Print test in a compiler compatible format. + * CppUnit::CompilerOutputter outputter( &result, std::cerr ); + * outputter.write(); + * } + * catch ( std::invalid_argument &e ) // Test path not resolved + * { + * std::cerr << std::endl + * << "ERROR: " << e.what() + * << std::endl; + * return 0; + * } + * + * return result.wasSuccessful() ? 0 : 1; + * } + * \endcode + */ +class CPPUNIT_API TestRunner +{ +public: + /*! \brief Constructs a TestRunner object. + */ + TestRunner( ); + + /// Destructor. + virtual ~TestRunner(); + + /*! \brief Adds the specified test. + * \param test Test to add. The TestRunner takes ownership of the test. + */ + virtual void addTest( Test *test ); + + /*! \brief Runs a test using the specified controller. + * \param controller Event manager and controller used for testing + * \param testPath Test path string. See Test::resolveTestPath() for detail. + * \exception std::invalid_argument if no test matching \a testPath is found. + * see TestPath::TestPath( Test*, const std::string &) + * for detail. + */ + virtual void run( TestResult &controller, + const std::string &testPath = "" ); + +protected: + /*! \brief (INTERNAL) Mutating test suite. + */ + class CPPUNIT_API WrappingSuite : public TestSuite + { + public: + WrappingSuite( const std::string &name = "All Tests" ); + + int getChildTestCount() const; + + std::string getName() const; + + void run( TestResult *result ); + + protected: + Test *doGetChildTestAt( int index ) const; + + bool hasOnlyOneTest() const; + + Test *getUniqueChildTest() const; + }; + +protected: + WrappingSuite *m_suite; + +private: + /// Prevents the use of the copy constructor. + TestRunner( const TestRunner © ); + + /// Prevents the use of the copy operator. + void operator =( const TestRunner © ); + +private: +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_TESTRUNNER_H diff --git a/UnitTests/cppunit/include/cppunit/TestSuccessListener.h b/UnitTests/cppunit/include/cppunit/TestSuccessListener.h new file mode 100644 index 0000000..60c5ff5 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TestSuccessListener.h @@ -0,0 +1,39 @@ +#ifndef CPPUNIT_TESTSUCCESSLISTENER_H +#define CPPUNIT_TESTSUCCESSLISTENER_H + +#include +#include + + +CPPUNIT_NS_BEGIN + + +/*! \brief TestListener that checks if any test case failed. + * \ingroup TrackingTestExecution + */ +class CPPUNIT_API TestSuccessListener : public TestListener, + public SynchronizedObject +{ +public: + /*! Constructs a TestSuccessListener object. + */ + TestSuccessListener( SynchronizationObject *syncObject = 0 ); + + /// Destructor. + virtual ~TestSuccessListener(); + + virtual void reset(); + + void addFailure( const TestFailure &failure ); + + /// Returns whether the entire test was successful or not. + virtual bool wasSuccessful() const; + +private: + bool m_success; +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_TESTSUCCESSLISTENER_H diff --git a/UnitTests/cppunit/include/cppunit/TestSuite.h b/UnitTests/cppunit/include/cppunit/TestSuite.h new file mode 100644 index 0000000..2b9cd8d --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TestSuite.h @@ -0,0 +1,80 @@ +#ifndef CPPUNIT_TESTSUITE_H // -*- C++ -*- +#define CPPUNIT_TESTSUITE_H + +#include + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( push ) +#pragma warning( disable: 4251 ) // X needs to have dll-interface to be used by clients of class Z +#endif + +#include +#include + +CPPUNIT_NS_BEGIN + + +#if CPPUNIT_NEED_DLL_DECL +// template class CPPUNIT_API std::vector; +#endif + + +/*! \brief A Composite of Tests. + * \ingroup CreatingTestSuite + * + * It runs a collection of test cases. Here is an example. + * \code + * CppUnit::TestSuite *suite= new CppUnit::TestSuite(); + * suite->addTest(new CppUnit::TestCaller ( + * "testAdd", testAdd)); + * suite->addTest(new CppUnit::TestCaller ( + * "testDivideByZero", testDivideByZero)); + * \endcode + * Note that \link TestSuite TestSuites \endlink assume lifetime + * control for any tests added to them. + * + * TestSuites do not register themselves in the TestRegistry. + * \see Test + * \see TestCaller + */ +class CPPUNIT_API TestSuite : public TestComposite +{ +public: + /*! Constructs a test suite with the specified name. + */ + TestSuite( std::string name = "" ); + + ~TestSuite(); + + /*! Adds the specified test to the suite. + * \param test Test to add. Must not be \c NULL. + */ + void addTest( Test *test ); + + /*! Returns the list of the tests (DEPRECATED). + * \deprecated Use getChildTestCount() & getChildTestAt() of the + * TestComposite interface instead. + * \return Reference on a vector that contains the tests of the suite. + */ + const CppUnitVector &getTests() const; + + /*! Destroys all the tests of the suite. + */ + virtual void deleteContents(); + + int getChildTestCount() const; + + Test *doGetChildTestAt( int index ) const; + +private: + CppUnitVector m_tests; +}; + + +CPPUNIT_NS_END + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( pop ) +#endif + +#endif // CPPUNIT_TESTSUITE_H diff --git a/UnitTests/cppunit/include/cppunit/TextOutputter.h b/UnitTests/cppunit/include/cppunit/TextOutputter.h new file mode 100644 index 0000000..6bd9cea --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TextOutputter.h @@ -0,0 +1,59 @@ +#ifndef CPPUNIT_TEXTOUTPUTTER_H +#define CPPUNIT_TEXTOUTPUTTER_H + +#include +#include +#include + +CPPUNIT_NS_BEGIN + + +class Exception; +class SourceLine; +class TestResultCollector; +class TestFailure; + + +/*! \brief Prints a TestResultCollector to a text stream. + * \ingroup WritingTestResult + */ +class CPPUNIT_API TextOutputter : public Outputter +{ +public: + TextOutputter( TestResultCollector *result, + OStream &stream ); + + /// Destructor. + virtual ~TextOutputter(); + + void write(); + virtual void printFailures(); + virtual void printHeader(); + + virtual void printFailure( TestFailure *failure, + int failureNumber ); + virtual void printFailureListMark( int failureNumber ); + virtual void printFailureTestName( TestFailure *failure ); + virtual void printFailureType( TestFailure *failure ); + virtual void printFailureLocation( SourceLine sourceLine ); + virtual void printFailureDetail( Exception *thrownException ); + virtual void printFailureWarning(); + virtual void printStatistics(); + +protected: + TestResultCollector *m_result; + OStream &m_stream; + +private: + /// Prevents the use of the copy constructor. + TextOutputter( const TextOutputter © ); + + /// Prevents the use of the copy operator. + void operator =( const TextOutputter © ); +}; + + + +CPPUNIT_NS_END + +#endif // CPPUNIT_TEXTOUTPUTTER_H diff --git a/UnitTests/cppunit/include/cppunit/TextTestProgressListener.h b/UnitTests/cppunit/include/cppunit/TextTestProgressListener.h new file mode 100644 index 0000000..7521c40 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TextTestProgressListener.h @@ -0,0 +1,44 @@ +#ifndef CPPUNIT_TEXTTESTPROGRESSLISTENER_H +#define CPPUNIT_TEXTTESTPROGRESSLISTENER_H + +#include + + +CPPUNIT_NS_BEGIN + + +/*! + * \brief TestListener that show the status of each TestCase test result. + * \ingroup TrackingTestExecution + */ +class CPPUNIT_API TextTestProgressListener : public TestListener +{ +public: + /*! Constructs a TextTestProgressListener object. + */ + TextTestProgressListener(); + + /// Destructor. + virtual ~TextTestProgressListener(); + + void startTest( Test *test ); + + void addFailure( const TestFailure &failure ); + + void endTestRun( Test *test, + TestResult *eventManager ); + +private: + /// Prevents the use of the copy constructor. + TextTestProgressListener( const TextTestProgressListener © ); + + /// Prevents the use of the copy operator. + void operator =( const TextTestProgressListener © ); + +private: +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_TEXTTESTPROGRESSLISTENER_H diff --git a/UnitTests/cppunit/include/cppunit/TextTestResult.h b/UnitTests/cppunit/include/cppunit/TextTestResult.h new file mode 100644 index 0000000..e7b1fa3 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TextTestResult.h @@ -0,0 +1,39 @@ +#ifndef CPPUNIT_TEXTTESTRESULT_H +#define CPPUNIT_TEXTTESTRESULT_H + +#include +#include +#include + +CPPUNIT_NS_BEGIN + + +class SourceLine; +class Exception; +class Test; + +/*! \brief Holds printable test result (DEPRECATED). + * \ingroup TrackingTestExecution + * + * deprecated Use class TextTestProgressListener and TextOutputter instead. + */ +class CPPUNIT_API TextTestResult : public TestResult, + public TestResultCollector +{ +public: + TextTestResult(); + + virtual void addFailure( const TestFailure &failure ); + virtual void startTest( Test *test ); + virtual void print( OStream &stream ); +}; + +/** insertion operator for easy output */ +CPPUNIT_API OStream &operator <<( OStream &stream, + TextTestResult &result ); + +CPPUNIT_NS_END + +#endif // CPPUNIT_TEXTTESTRESULT_H + + diff --git a/UnitTests/cppunit/include/cppunit/TextTestRunner.h b/UnitTests/cppunit/include/cppunit/TextTestRunner.h new file mode 100644 index 0000000..23890e0 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/TextTestRunner.h @@ -0,0 +1,6 @@ +#ifndef CPPUNIT_TEXTTESTRUNNER_H +#define CPPUNIT_TEXTTESTRUNNER_H + +#include + +#endif // CPPUNIT_TEXTTESTRUNNER_H diff --git a/UnitTests/cppunit/include/cppunit/XmlOutputter.h b/UnitTests/cppunit/include/cppunit/XmlOutputter.h new file mode 100644 index 0000000..0de9676 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/XmlOutputter.h @@ -0,0 +1,167 @@ +#ifndef CPPUNIT_XMLTESTRESULTOUTPUTTER_H +#define CPPUNIT_XMLTESTRESULTOUTPUTTER_H + +#include + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( push ) +#pragma warning( disable: 4251 ) // X needs to have dll-interface to be used by clients of class Z +#endif + +#include +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +class Test; +class TestFailure; +class TestResultCollector; +class XmlDocument; +class XmlElement; +class XmlOutputterHook; + + +/*! \brief Outputs a TestResultCollector in XML format. + * \ingroup WritingTestResult + * + * Save the test result as a XML stream. + * + * Additional datas can be added to the XML document using XmlOutputterHook. + * Hook are not owned by the XmlOutputter. They should be valid until + * destruction of the XmlOutputter. They can be removed with removeHook(). + * + * \see XmlDocument, XmlElement, XmlOutputterHook. + */ +class CPPUNIT_API XmlOutputter : public Outputter +{ +public: + /*! \brief Constructs a XmlOutputter object. + * \param result Result of the test run. + * \param stream Stream used to output the XML output. + * \param encoding Encoding used in the XML file (default is Latin-1). + */ + XmlOutputter( TestResultCollector *result, + OStream &stream, + std::string encoding = std::string("ISO-8859-1") ); + + /// Destructor. + virtual ~XmlOutputter(); + + /*! \brief Adds the specified hook to the outputter. + * \param hook Hook to add. Must not be \c NULL. + */ + virtual void addHook( XmlOutputterHook *hook ); + + /*! \brief Removes the specified hook from the outputter. + * \param hook Hook to remove. + */ + virtual void removeHook( XmlOutputterHook *hook ); + + /*! \brief Writes the specified result as an XML document to the stream. + * + * Refer to examples/cppunittest/XmlOutputterTest.cpp for example + * of use and XML document structure. + */ + virtual void write(); + + /*! \brief Sets the XSL style sheet used. + * + * \param styleSheet Name of the style sheet used. If empty, then no style sheet + * is used (default). + */ + virtual void setStyleSheet( const std::string &styleSheet ); + + /*! \brief set the output document as standalone or not. + * + * For the output document, specify wether it's a standalone XML + * document, or not. + * + * \param standalone if true, the output will be specified as standalone. + * if false, it will be not. + */ + virtual void setStandalone( bool standalone ); + + typedef CppUnitMap > FailedTests; + + /*! \brief Sets the root element and adds its children. + * + * Set the root element of the XML Document and add its child elements. + * + * For all hooks, call beginDocument() just after creating the root element (it + * is empty at this time), and endDocument() once all the datas have been added + * to the root element. + */ + virtual void setRootNode(); + + virtual void addFailedTests( FailedTests &failedTests, + XmlElement *rootNode ); + + virtual void addSuccessfulTests( FailedTests &failedTests, + XmlElement *rootNode ); + + /*! \brief Adds the statics element to the root node. + * + * Creates a new element containing statistics data and adds it to the root element. + * Then, for all hooks, call statisticsAdded(). + * \param rootNode Root element. + */ + virtual void addStatistics( XmlElement *rootNode ); + + /*! \brief Adds a failed test to the failed tests node. + * Creates a new element containing datas about the failed test, and adds it to + * the failed tests element. + * Then, for all hooks, call failTestAdded(). + */ + virtual void addFailedTest( Test *test, + TestFailure *failure, + int testNumber, + XmlElement *testsNode ); + + virtual void addFailureLocation( TestFailure *failure, + XmlElement *testElement ); + + + /*! \brief Adds a successful test to the successful tests node. + * Creates a new element containing datas about the successful test, and adds it to + * the successful tests element. + * Then, for all hooks, call successfulTestAdded(). + */ + virtual void addSuccessfulTest( Test *test, + int testNumber, + XmlElement *testsNode ); +protected: + virtual void fillFailedTestsMap( FailedTests &failedTests ); + +protected: + typedef CppUnitDeque Hooks; + + TestResultCollector *m_result; + OStream &m_stream; + std::string m_encoding; + std::string m_styleSheet; + XmlDocument *m_xml; + Hooks m_hooks; + +private: + /// Prevents the use of the copy constructor. + XmlOutputter( const XmlOutputter © ); + + /// Prevents the use of the copy operator. + void operator =( const XmlOutputter © ); + +private: +}; + + +CPPUNIT_NS_END + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( pop ) +#endif + + +#endif // CPPUNIT_XMLTESTRESULTOUTPUTTER_H diff --git a/UnitTests/cppunit/include/cppunit/XmlOutputterHook.h b/UnitTests/cppunit/include/cppunit/XmlOutputterHook.h new file mode 100644 index 0000000..5ded3b1 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/XmlOutputterHook.h @@ -0,0 +1,163 @@ +#ifndef CPPUNIT_XMLOUTPUTTERHOOK_H +#define CPPUNIT_XMLOUTPUTTERHOOK_H + +#include + + +CPPUNIT_NS_BEGIN + + +class Test; +class TestFailure; +class XmlDocument; +class XmlElement; + + + +/*! \brief Hook to customize Xml output. + * + * XmlOutputterHook can be passed to XmlOutputter to customize the XmlDocument. + * + * Common customizations are: + * - adding some datas to successfull or failed test with + * failTestAdded() and successfulTestAdded(), + * - adding some statistics with statisticsAdded(), + * - adding other datas with beginDocument() or endDocument(). + * + * See examples/ClockerPlugIn which makes use of most the hook. + * + * Another simple example of an outputter hook is shown below. It may be + * used to add some meta information to your result files. In the example, + * the author name as well as the project name and test creation date is + * added to the head of the xml file. + * + * In order to make this information stored within the xml file, the virtual + * member function beginDocument() is overriden where a new + * XmlElement object is created. + * + * This element is simply added to the root node of the document which + * makes the information automatically being stored when the xml file + * is written. + * + * \code + * #include + * #include + * #include + * + * ... + * + * class MyXmlOutputterHook : public CppUnit::XmlOutputterHook + * { + * public: + * MyXmlOutputterHook(const std::string projectName, + * const std::string author) + * { + * m_projectName = projectName; + * m_author = author; + * }; + * + * virtual ~MyXmlOutputterHook() + * { + * }; + * + * void beginDocument(CppUnit::XmlDocument* document) + * { + * if (!document) + * return; + * + * // dump current time + * std::string szDate = CppUnit::StringTools::toString( (int)time(0) ); + * CppUnit::XmlElement* metaEl = new CppUnit::XmlElement("SuiteInfo", + * ""); + * + * metaEl->addElement( new CppUnit::XmlElement("Author", m_author) ); + * metaEl->addElement( new CppUnit::XmlElement("Project", m_projectName) ); + * metaEl->addElement( new CppUnit::XmlElement("Date", szDate ) ); + * + * document->rootElement().addElement(metaEl); + * }; + * private: + * std::string m_projectName; + * std::string m_author; + * }; + * \endcode + * + * Within your application's main code, you need to snap the hook + * object into your xml outputter object like shown below: + * + * \code + * CppUnit::TextUi::TestRunner runner; + * std::ofstream outputFile("testResults.xml"); + * + * CppUnit::XmlOutputter* outputter = new CppUnit::XmlOutputter( &runner.result(), + * outputFile ); + * MyXmlOutputterHook hook("myProject", "meAuthor"); + * outputter->addHook(&hook); + * runner.setOutputter(outputter); + * runner.addTest( VectorFixture::suite() ); + * runner.run(); + * outputFile.close(); + * \endcode + * + * This results into the following output: + * + * \code + * + * + * meAuthor + * myProject + * 1028143912 + * + * + * ... + * \endcode + * + * \see XmlOutputter, CppUnitTestPlugIn. + */ +class CPPUNIT_API XmlOutputterHook +{ +public: + /*! Called before any elements is added to the root element. + * \param document XML Document being created. + */ + virtual void beginDocument( XmlDocument *document ); + + /*! Called after adding all elements to the root element. + * \param document XML Document being created. + */ + virtual void endDocument( XmlDocument *document ); + + /*! Called after adding a fail test element. + * \param document XML Document being created. + * \param testElement \ element. + * \param test Test that failed. + * \param failure Test failure data. + */ + virtual void failTestAdded( XmlDocument *document, + XmlElement *testElement, + Test *test, + TestFailure *failure ); + + /*! Called after adding a successful test element. + * \param document XML Document being created. + * \param testElement \ element. + * \param test Test that was successful. + */ + virtual void successfulTestAdded( XmlDocument *document, + XmlElement *testElement, + Test *test ); + + /*! Called after adding the statistic element. + * \param document XML Document being created. + * \param statisticsElement \ element. + */ + virtual void statisticsAdded( XmlDocument *document, + XmlElement *statisticsElement ); + + virtual ~XmlOutputterHook() {} +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_XMLOUTPUTTERHOOK_H diff --git a/UnitTests/cppunit/include/cppunit/config-auto.h b/UnitTests/cppunit/include/cppunit/config-auto.h new file mode 100644 index 0000000..337baf7 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/config-auto.h @@ -0,0 +1,179 @@ +#ifndef _INCLUDE_CPPUNIT_CONFIG_AUTO_H +#define _INCLUDE_CPPUNIT_CONFIG_AUTO_H 1 + +/* include/cppunit/config-auto.h. Generated automatically at end of configure. */ +/* config/config.h. Generated from config.h.in by configure. */ +/* config/config.h.in. Generated from configure.in by autoheader. */ + +/* define if library uses std::string::compare(string,pos,n) */ +/* #undef CPPUNIT_FUNC_STRING_COMPARE_STRING_FIRST */ + +/* define if the library defines strstream */ +#ifndef CPPUNIT_HAVE_CLASS_STRSTREAM +#define CPPUNIT_HAVE_CLASS_STRSTREAM 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef CPPUNIT_HAVE_CMATH +#define CPPUNIT_HAVE_CMATH 1 +#endif + +/* Define if you have the GNU dld library. */ +/* #undef CPPUNIT_HAVE_DLD */ + +/* Define to 1 if you have the `dlerror' function. */ +#ifndef CPPUNIT_HAVE_DLERROR +#define CPPUNIT_HAVE_DLERROR 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef CPPUNIT_HAVE_DLFCN_H +#define CPPUNIT_HAVE_DLFCN_H 1 +#endif + +/* Define to 1 if you have the `finite' function. */ +#ifndef CPPUNIT_HAVE_FINITE +#define CPPUNIT_HAVE_FINITE 1 +#endif + +/* define if the compiler supports GCC C++ ABI name demangling */ +#ifndef CPPUNIT_HAVE_GCC_ABI_DEMANGLE +#define CPPUNIT_HAVE_GCC_ABI_DEMANGLE 0 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef CPPUNIT_HAVE_INTTYPES_H +#define CPPUNIT_HAVE_INTTYPES_H 1 +#endif + +/* define if compiler has isfinite */ +#ifndef CPPUNIT_HAVE_ISFINITE +#define CPPUNIT_HAVE_ISFINITE 1 +#endif + +/* Define if you have the libdl library or equivalent. */ +#ifndef CPPUNIT_HAVE_LIBDL +#define CPPUNIT_HAVE_LIBDL 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef CPPUNIT_HAVE_MEMORY_H +#define CPPUNIT_HAVE_MEMORY_H 1 +#endif + +/* define to 1 if the compiler implements namespaces */ +#ifndef CPPUNIT_HAVE_NAMESPACES +#define CPPUNIT_HAVE_NAMESPACES 1 +#endif + +/* define if the compiler supports Run-Time Type Identification */ +#ifndef CPPUNIT_HAVE_RTTI +#define CPPUNIT_HAVE_RTTI 0 +#endif + +/* Define if you have the shl_load function. */ +/* #undef CPPUNIT_HAVE_SHL_LOAD */ + +/* define if the compiler has stringstream */ +#ifndef CPPUNIT_HAVE_SSTREAM +#define CPPUNIT_HAVE_SSTREAM 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef CPPUNIT_HAVE_STDINT_H +#define CPPUNIT_HAVE_STDINT_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef CPPUNIT_HAVE_STDLIB_H +#define CPPUNIT_HAVE_STDLIB_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef CPPUNIT_HAVE_STRINGS_H +#define CPPUNIT_HAVE_STRINGS_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef CPPUNIT_HAVE_STRING_H +#define CPPUNIT_HAVE_STRING_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef CPPUNIT_HAVE_STRSTREAM +#define CPPUNIT_HAVE_STRSTREAM 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef CPPUNIT_HAVE_SYS_STAT_H +#define CPPUNIT_HAVE_SYS_STAT_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef CPPUNIT_HAVE_SYS_TYPES_H +#define CPPUNIT_HAVE_SYS_TYPES_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef CPPUNIT_HAVE_UNISTD_H +#define CPPUNIT_HAVE_UNISTD_H 1 +#endif + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#ifndef CPPUNIT_LT_OBJDIR +#define CPPUNIT_LT_OBJDIR ".libs/" +#endif + +/* Name of package */ +#ifndef CPPUNIT_PACKAGE +#define CPPUNIT_PACKAGE "cppunit" +#endif + +/* Define to the address where bug reports for this package should be sent. */ +#ifndef CPPUNIT_PACKAGE_BUGREPORT +#define CPPUNIT_PACKAGE_BUGREPORT "" +#endif + +/* Define to the full name of this package. */ +#ifndef CPPUNIT_PACKAGE_NAME +#define CPPUNIT_PACKAGE_NAME "" +#endif + +/* Define to the full name and version of this package. */ +#ifndef CPPUNIT_PACKAGE_STRING +#define CPPUNIT_PACKAGE_STRING "" +#endif + +/* Define to the one symbol short name of this package. */ +#ifndef CPPUNIT_PACKAGE_TARNAME +#define CPPUNIT_PACKAGE_TARNAME "" +#endif + +/* Define to the home page for this package. */ +#ifndef CPPUNIT_PACKAGE_URL +#define CPPUNIT_PACKAGE_URL "" +#endif + +/* Define to the version of this package. */ +#ifndef CPPUNIT_PACKAGE_VERSION +#define CPPUNIT_PACKAGE_VERSION "" +#endif + +/* Define to 1 if you have the ANSI C header files. */ +#ifndef CPPUNIT_STDC_HEADERS +#define CPPUNIT_STDC_HEADERS 1 +#endif + +/* Define to 1 to use type_info::name() for class names */ +#ifndef CPPUNIT_USE_TYPEINFO_NAME +#define CPPUNIT_USE_TYPEINFO_NAME CPPUNIT_HAVE_RTTI +#endif + +/* Version number of package */ +#ifndef CPPUNIT_VERSION +#define CPPUNIT_VERSION "1.12.1" +#endif + +/* _INCLUDE_CPPUNIT_CONFIG_AUTO_H */ +#endif diff --git a/UnitTests/cppunit/include/cppunit/config/CppUnitApi.h b/UnitTests/cppunit/include/cppunit/config/CppUnitApi.h new file mode 100644 index 0000000..a068bbd --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/config/CppUnitApi.h @@ -0,0 +1,33 @@ +#ifndef CPPUNIT_CONFIG_CPPUNITAPI +#define CPPUNIT_CONFIG_CPPUNITAPI + +#undef CPPUNIT_API + +#ifdef WIN32 + +// define CPPUNIT_DLL_BUILD when building CppUnit dll. +#ifdef CPPUNIT_BUILD_DLL +#define CPPUNIT_API __declspec(dllexport) +#endif + +// define CPPUNIT_DLL when linking to CppUnit dll. +#ifdef CPPUNIT_DLL +#define CPPUNIT_API __declspec(dllimport) +#endif + +#ifdef CPPUNIT_API +#undef CPPUNIT_NEED_DLL_DECL +#define CPPUNIT_NEED_DLL_DECL 1 +#endif + +#endif + + +#ifndef CPPUNIT_API +#define CPPUNIT_API +#undef CPPUNIT_NEED_DLL_DECL +#define CPPUNIT_NEED_DLL_DECL 0 +#endif + + +#endif // CPPUNIT_CONFIG_CPPUNITAPI diff --git a/UnitTests/cppunit/include/cppunit/config/SelectDllLoader.h b/UnitTests/cppunit/include/cppunit/config/SelectDllLoader.h new file mode 100644 index 0000000..dc1c011 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/config/SelectDllLoader.h @@ -0,0 +1,76 @@ +#ifndef CPPUNIT_CONFIG_SELECTDLLLOADER_H +#define CPPUNIT_CONFIG_SELECTDLLLOADER_H + +/*! \file + * Selects DynamicLibraryManager implementation. + * + * Don't include this file directly. Include Portability.h instead. + */ + +/*! + * \def CPPUNIT_NO_TESTPLUGIN + * \brief If defined, then plug-in related classes and functions will not be compiled. + * + * \internal + * CPPUNIT_HAVE_WIN32_DLL_LOADER + * If defined, Win32 implementation of DynamicLibraryManager will be used. + * + * CPPUNIT_HAVE_BEOS_DLL_LOADER + * If defined, BeOs implementation of DynamicLibraryManager will be used. + * + * CPPUNIT_HAVE_UNIX_DLL_LOADER + * If defined, Unix implementation (dlfcn.h) of DynamicLibraryManager will be used. + */ + +/*! + * \def CPPUNIT_PLUGIN_EXPORT + * \ingroup WritingTestPlugIn + * \brief A macro to export a function from a dynamic library + * + * This macro export the C function following it from a dynamic library. + * Exporting the function makes it accessible to the DynamicLibraryManager. + * + * Example of usage: + * \code + * #include + * + * CPPUNIT_PLUGIN_EXPORT CppUnitTestPlugIn *CPPUNIT_PLUGIN_EXPORTED_NAME(void) + * { + * ... + * return &myPlugInInterface; + * } + * \endcode + */ + +#if !defined(CPPUNIT_NO_TESTPLUGIN) + +// Is WIN32 platform ? +#if defined(WIN32) +#define CPPUNIT_HAVE_WIN32_DLL_LOADER 1 +#undef CPPUNIT_PLUGIN_EXPORT +#define CPPUNIT_PLUGIN_EXPORT extern "C" __declspec(dllexport) + +// Is BeOS platform ? +#elif defined(__BEOS__) +#define CPPUNIT_HAVE_BEOS_DLL_LOADER 1 + +// Is Unix platform and have shl_load() (hp-ux) +#elif defined(CPPUNIT_HAVE_SHL_LOAD) +#define CPPUNIT_HAVE_UNIX_SHL_LOADER 1 + +// Is Unix platform and have include +#elif defined(CPPUNIT_HAVE_LIBDL) +#define CPPUNIT_HAVE_UNIX_DLL_LOADER 1 + +// Otherwise, disable support for DllLoader +#else +#define CPPUNIT_NO_TESTPLUGIN 1 +#endif + +#if !defined(CPPUNIT_PLUGIN_EXPORT) +#define CPPUNIT_PLUGIN_EXPORT extern "C" +#endif // !defined(CPPUNIT_PLUGIN_EXPORT) + +#endif // !defined(CPPUNIT_NO_TESTPLUGIN) + +#endif // CPPUNIT_CONFIG_SELECTDLLLOADER_H diff --git a/UnitTests/cppunit/include/cppunit/config/SourcePrefix.h b/UnitTests/cppunit/include/cppunit/config/SourcePrefix.h new file mode 100644 index 0000000..2334601 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/config/SourcePrefix.h @@ -0,0 +1,14 @@ +#ifndef CPPUNIT_CONFIG_H_INCLUDED +#define CPPUNIT_CONFIG_H_INCLUDED + +#include + +#ifdef _MSC_VER +#pragma warning(disable: 4018 4284 4146) +#if _MSC_VER >= 1400 +#pragma warning(disable: 4996) // sprintf is deprecated +#endif +#endif + + +#endif // CPPUNIT_CONFIG_H_INCLUDED diff --git a/UnitTests/cppunit/include/cppunit/config/config-bcb5.h b/UnitTests/cppunit/include/cppunit/config/config-bcb5.h new file mode 100644 index 0000000..d491452 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/config/config-bcb5.h @@ -0,0 +1,47 @@ +#ifndef _INCLUDE_CPPUNIT_CONFIG_BCB5_H +#define _INCLUDE_CPPUNIT_CONFIG_BCB5_H 1 + +#define HAVE_CMATH 1 + +/* include/cppunit/config-bcb5.h. Manually adapted from + include/cppunit/config-auto.h */ + +/* define to 1 if the compiler implements namespaces */ +#ifndef CPPUNIT_HAVE_NAMESPACES +#define CPPUNIT_HAVE_NAMESPACES 1 +#endif + +/* define if library uses std::string::compare(string,pos,n) */ +#ifndef CPPUNIT_FUNC_STRING_COMPARE_STRING_FIRST +#define CPPUNIT_FUNC_STRING_COMPARE_STRING_FIRST 0 +#endif + +/* Define if you have the header file. */ +#ifdef CPPUNIT_HAVE_DLFCN_H +#undef CPPUNIT_HAVE_DLFCN_H +#endif + +/* define to 1 if the compiler implements namespaces */ +#ifndef CPPUNIT_HAVE_NAMESPACES +#define CPPUNIT_HAVE_NAMESPACES 1 +#endif + +/* define if the compiler supports Run-Time Type Identification */ +#ifndef CPPUNIT_HAVE_RTTI +#define CPPUNIT_HAVE_RTTI 1 +#endif + +/* Define to 1 to use type_info::name() for class names */ +#ifndef CPPUNIT_USE_TYPEINFO_NAME +#define CPPUNIT_USE_TYPEINFO_NAME CPPUNIT_HAVE_RTTI +#endif + +#define CPPUNIT_HAVE_SSTREAM 1 + +/* Name of package */ +#ifndef CPPUNIT_PACKAGE +#define CPPUNIT_PACKAGE "cppunit" +#endif + +/* _INCLUDE_CPPUNIT_CONFIG_BCB5_H */ +#endif diff --git a/UnitTests/cppunit/include/cppunit/config/config-evc4.h b/UnitTests/cppunit/include/cppunit/config/config-evc4.h new file mode 100644 index 0000000..a791698 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/config/config-evc4.h @@ -0,0 +1,78 @@ +#ifndef _INCLUDE_CPPUNIT_CONFIG_EVC4_H +#define _INCLUDE_CPPUNIT_CONFIG_EVC4_H 1 + +#if _MSC_VER > 1000 // VC++ +#pragma warning( disable : 4786 ) // disable warning debug symbol > 255... +#endif // _MSC_VER > 1000 + +#define HAVE_CMATH 1 + +/* include/cppunit/config-msvc6.h. Manually adapted from + include/cppunit/config-auto.h */ + +/* define to 1 if the compiler implements namespaces */ +#ifndef CPPUNIT_HAVE_NAMESPACES +#define CPPUNIT_HAVE_NAMESPACES 1 +#endif + +/* define if library uses std::string::compare(string,pos,n) */ +#ifdef CPPUNIT_FUNC_STRING_COMPARE_STRING_FIRST +#undef CPPUNIT_FUNC_STRING_COMPARE_STRING_FIRST +#endif + +/* Define if you have the header file. */ +#ifdef CPPUNIT_HAVE_DLFCN_H +#undef CPPUNIT_HAVE_DLFCN_H +#endif + +/* define to 1 if the compiler implements namespaces */ +#ifndef CPPUNIT_HAVE_NAMESPACES +#define CPPUNIT_HAVE_NAMESPACES 1 +#endif + +/* define if the compiler supports Run-Time Type Identification */ +#ifndef CPPUNIT_HAVE_RTTI +#define CPPUNIT_HAVE_RTTI 0 +#endif + +/* Define to 1 to use type_info::name() for class names */ +#ifndef CPPUNIT_USE_TYPEINFO_NAME +#define CPPUNIT_USE_TYPEINFO_NAME CPPUNIT_HAVE_RTTI +#endif + +#define CPPUNIT_NO_STREAM 1 +#define CPPUNIT_NO_ASSERT 1 + +#define CPPUNIT_HAVE_SSTREAM 0 + +/* Name of package */ +#ifndef CPPUNIT_PACKAGE +#define CPPUNIT_PACKAGE "cppunit" +#endif + + +// Compiler error location format for CompilerOutputter +// See class CompilerOutputter for format. +#undef CPPUNIT_COMPILER_LOCATION_FORMAT +#if _MSC_VER >= 1300 // VS 7.0 +# define CPPUNIT_COMPILER_LOCATION_FORMAT "%p(%l) : error : " +#else +# define CPPUNIT_COMPILER_LOCATION_FORMAT "%p(%l):" +#endif + +/* define to 1 if the compiler has _finite() */ +#ifndef CPPUNIT_HAVE__FINITE +#define CPPUNIT_HAVE__FINITE 1 +#endif + +// Uncomment to turn on STL wrapping => use this to test compilation. +// This will make CppUnit subclass std::vector & co to provide default +// parameter. +/*#define CPPUNIT_STD_NEED_ALLOCATOR 1 +#define CPPUNIT_STD_ALLOCATOR std::allocator +//#define CPPUNIT_NO_NAMESPACE 1 +*/ + + +/* _INCLUDE_CPPUNIT_CONFIG_EVC4_H */ +#endif diff --git a/UnitTests/cppunit/include/cppunit/config/config-mac.h b/UnitTests/cppunit/include/cppunit/config/config-mac.h new file mode 100644 index 0000000..4ace906 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/config/config-mac.h @@ -0,0 +1,58 @@ +#ifndef _INCLUDE_CPPUNIT_CONFIG_MAC_H +#define _INCLUDE_CPPUNIT_CONFIG_MAC_H 1 + +/* MacOS X should be installed using the configure script. + This file is for other macs. + + It is not integrated into because we don't + know a suitable preprocessor symbol that will distinguish MacOS X + from other MacOS versions. Email us if you know the answer. +*/ + +/* define if library uses std::string::compare(string,pos,n) */ +#ifdef CPPUNIT_FUNC_STRING_COMPARE_STRING_FIRST +#undef CPPUNIT_FUNC_STRING_COMPARE_STRING_FIRST +#endif + +/* define if the library defines strstream */ +#ifndef CPPUNIT_HAVE_CLASS_STRSTREAM +#define CPPUNIT_HAVE_CLASS_STRSTREAM 1 +#endif + +/* Define if you have the header file. */ +#ifdef CPPUNIT_HAVE_CMATH +#undef CPPUNIT_HAVE_CMATH +#endif + +/* Define if you have the header file. */ +#ifdef CPPUNIT_HAVE_DLFCN_H +#undef CPPUNIT_HAVE_DLFCN_H +#endif + +/* define to 1 if the compiler implements namespaces */ +#ifndef CPPUNIT_HAVE_NAMESPACES +#define CPPUNIT_HAVE_NAMESPACES 1 +#endif + +/* define if the compiler supports Run-Time Type Identification */ +#ifndef CPPUNIT_HAVE_RTTI +#define CPPUNIT_HAVE_RTTI 1 +#endif + +/* define if the compiler has stringstream */ +#ifndef CPPUNIT_HAVE_SSTREAM +#define CPPUNIT_HAVE_SSTREAM 1 +#endif + +/* Define if you have the header file. */ +#ifndef CPPUNIT_HAVE_STRSTREAM +#define CPPUNIT_HAVE_STRSTREAM 1 +#endif + +/* Define to 1 to use type_info::name() for class names */ +#ifndef CPPUNIT_USE_TYPEINFO_NAME +#define CPPUNIT_USE_TYPEINFO_NAME CPPUNIT_HAVE_RTTI +#endif + +/* _INCLUDE_CPPUNIT_CONFIG_MAC_H */ +#endif diff --git a/UnitTests/cppunit/include/cppunit/config/config-msvc6.h b/UnitTests/cppunit/include/cppunit/config/config-msvc6.h new file mode 100644 index 0000000..54bce82 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/config/config-msvc6.h @@ -0,0 +1,86 @@ +#ifndef _INCLUDE_CPPUNIT_CONFIG_MSVC6_H +#define _INCLUDE_CPPUNIT_CONFIG_MSVC6_H 1 + +#if _MSC_VER > 1000 // VC++ +#pragma warning( disable : 4786 ) // disable warning debug symbol > 255... +#endif // _MSC_VER > 1000 + +#define HAVE_CMATH 1 + +/* include/cppunit/config-msvc6.h. Manually adapted from + include/cppunit/config-auto.h */ + +/* define to 1 if the compiler implements namespaces */ +#ifndef CPPUNIT_HAVE_NAMESPACES +#define CPPUNIT_HAVE_NAMESPACES 1 +#endif + +/* define if library uses std::string::compare(string,pos,n) */ +#ifdef CPPUNIT_FUNC_STRING_COMPARE_STRING_FIRST +#undef CPPUNIT_FUNC_STRING_COMPARE_STRING_FIRST +#endif + +/* Define if you have the header file. */ +#ifdef CPPUNIT_HAVE_DLFCN_H +#undef CPPUNIT_HAVE_DLFCN_H +#endif + +/* define to 1 if the compiler implements namespaces */ +#ifndef CPPUNIT_HAVE_NAMESPACES +#define CPPUNIT_HAVE_NAMESPACES 1 +#endif + +/* define if the compiler supports Run-Time Type Identification */ +#ifndef CPPUNIT_HAVE_RTTI +# ifdef _CPPRTTI // Defined by the compiler option /GR +# define CPPUNIT_HAVE_RTTI 1 +# else +# define CPPUNIT_HAVE_RTTI 0 +# endif +#endif + +/* Define to 1 to use type_info::name() for class names */ +#ifndef CPPUNIT_USE_TYPEINFO_NAME +#define CPPUNIT_USE_TYPEINFO_NAME CPPUNIT_HAVE_RTTI +#endif + +#define CPPUNIT_HAVE_SSTREAM 1 + +/* Name of package */ +#ifndef CPPUNIT_PACKAGE +#define CPPUNIT_PACKAGE "cppunit" +#endif + + +// Compiler error location format for CompilerOutputter +// See class CompilerOutputter for format. +#undef CPPUNIT_COMPILER_LOCATION_FORMAT +#if _MSC_VER >= 1300 // VS 7.0 +# define CPPUNIT_COMPILER_LOCATION_FORMAT "%p(%l) : error : " +#else +# define CPPUNIT_COMPILER_LOCATION_FORMAT "%p(%l):" +#endif + +// Define to 1 if the compiler support C++ style cast. +#define CPPUNIT_HAVE_CPP_CAST 1 + +/* define to 1 if the compiler has _finite() */ +#ifndef CPPUNIT_HAVE__FINITE +#define CPPUNIT_HAVE__FINITE 1 +#endif + + +// Uncomment to turn on STL wrapping => use this to test compilation. +// This will make CppUnit subclass std::vector & co to provide default +// parameter. +/*#define CPPUNIT_STD_NEED_ALLOCATOR 1 +#define CPPUNIT_STD_ALLOCATOR std::allocator +//#define CPPUNIT_NO_NAMESPACE 1 +*/ + +#if _MSC_VER >= 1300 // VS 7.0 +#define CPPUNIT_UNIQUE_COUNTER __COUNTER__ +#endif // if _MSC_VER >= 1300 // VS 7.0 + +/* _INCLUDE_CPPUNIT_CONFIG_MSVC6_H */ +#endif diff --git a/UnitTests/cppunit/include/cppunit/extensions/AutoRegisterSuite.h b/UnitTests/cppunit/include/cppunit/extensions/AutoRegisterSuite.h new file mode 100644 index 0000000..e04adb5 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/extensions/AutoRegisterSuite.h @@ -0,0 +1,83 @@ +#ifndef CPPUNIT_EXTENSIONS_AUTOREGISTERSUITE_H +#define CPPUNIT_EXTENSIONS_AUTOREGISTERSUITE_H + +#include +#include +#include + +CPPUNIT_NS_BEGIN + + +/*! \brief (Implementation) Automatically register the test suite of the specified type. + * + * You should not use this class directly. Instead, use the following macros: + * - CPPUNIT_TEST_SUITE_REGISTRATION() + * - CPPUNIT_TEST_SUITE_NAMED_REGISTRATION() + * + * This object will register the test returned by TestCaseType::suite() + * when constructed to the test registry. + * + * This object is intented to be used as a static variable. + * + * + * \param TestCaseType Type of the test case which suite is registered. + * \see CPPUNIT_TEST_SUITE_REGISTRATION, CPPUNIT_TEST_SUITE_NAMED_REGISTRATION + * \see CppUnit::TestFactoryRegistry. + */ +template +class AutoRegisterSuite +{ +public: + /** Auto-register the suite factory in the global registry. + */ + AutoRegisterSuite() + : m_registry( &TestFactoryRegistry::getRegistry() ) + { + m_registry->registerFactory( &m_factory ); + } + + /** Auto-register the suite factory in the specified registry. + * \param name Name of the registry. + */ + AutoRegisterSuite( const std::string &name ) + : m_registry( &TestFactoryRegistry::getRegistry( name ) ) + { + m_registry->registerFactory( &m_factory ); + } + + ~AutoRegisterSuite() + { + if ( TestFactoryRegistry::isValid() ) + m_registry->unregisterFactory( &m_factory ); + } + +private: + TestFactoryRegistry *m_registry; + TestSuiteFactory m_factory; +}; + + +/*! \brief (Implementation) Automatically adds a registry into another registry. + * + * Don't use this class. Use the macros CPPUNIT_REGISTRY_ADD() and + * CPPUNIT_REGISTRY_ADD_TO_DEFAULT() instead. + */ +class AutoRegisterRegistry +{ +public: + AutoRegisterRegistry( const std::string &which, + const std::string &to ) + { + TestFactoryRegistry::getRegistry( to ).addRegistry( which ); + } + + AutoRegisterRegistry( const std::string &which ) + { + TestFactoryRegistry::getRegistry().addRegistry( which ); + } +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_EXTENSIONS_AUTOREGISTERSUITE_H diff --git a/UnitTests/cppunit/include/cppunit/extensions/ExceptionTestCaseDecorator.h b/UnitTests/cppunit/include/cppunit/extensions/ExceptionTestCaseDecorator.h new file mode 100644 index 0000000..2929a00 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/extensions/ExceptionTestCaseDecorator.h @@ -0,0 +1,104 @@ +#ifndef CPPUNIT_EXTENSIONS_EXCEPTIONTESTCASEDECORATOR_H +#define CPPUNIT_EXTENSIONS_EXCEPTIONTESTCASEDECORATOR_H + +#include +#include +#include + +CPPUNIT_NS_BEGIN + + +/*! \brief Expected exception test case decorator. + * + * A decorator used to assert that a specific test case should throw an + * exception of a given type. + * + * You should use this class only if you need to check the exception object + * state (that a specific cause is set for example). If you don't need to + * do that, you might consider using CPPUNIT_TEST_EXCEPTION() instead. + * + * Intended use is to subclass and override checkException(). Example: + * + * \code + * + * class NetworkErrorTestCaseDecorator : + * public ExceptionTestCaseDecorator + * { + * public: + * NetworkErrorTestCaseDecorator( NetworkError::Cause expectedCause ) + * : m_expectedCause( expectedCause ) + * { + * } + * private: + * void checkException( ExpectedExceptionType &e ) + * { + * CPPUNIT_ASSERT_EQUAL( m_expectedCause, e.getCause() ); + * } + * + * NetworkError::Cause m_expectedCause; + * }; + * \endcode + * + */ +template +class ExceptionTestCaseDecorator : public TestCaseDecorator +{ +public: + typedef ExpectedException ExpectedExceptionType; + + /*! \brief Decorates the specified test. + * \param test TestCase to decorate. Assumes ownership of the test. + */ + ExceptionTestCaseDecorator( TestCase *test ) + : TestCaseDecorator( test ) + { + } + + /*! \brief Checks that the expected exception is thrown by the decorated test. + * is thrown. + * + * Calls the decorated test runTest() and checks that an exception of + * type ExpectedException is thrown. Call checkException() passing the + * exception that was caught so that some assertions can be made if + * needed. + */ + void runTest() + { + try + { + TestCaseDecorator::runTest(); + } + catch ( ExpectedExceptionType &e ) + { + checkException( e ); + return; + } + + // Moved outside the try{} statement to handle the case where the + // expected exception type is Exception (expecting assertion failure). +#if CPPUNIT_USE_TYPEINFO_NAME + throw Exception( Message( + "expected exception not thrown", + "Expected exception type: " + + TypeInfoHelper::getClassName( + typeid( ExpectedExceptionType ) ) ) ); +#else + throw Exception( Message("expected exception not thrown") ); +#endif + } + +private: + /*! \brief Called when the exception is caught. + * + * Should be overriden to check the exception. + */ + virtual void checkException( ExpectedExceptionType & ) + { + } +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_EXTENSIONS_EXCEPTIONTESTCASEDECORATOR_H + diff --git a/UnitTests/cppunit/include/cppunit/extensions/HelperMacros.h b/UnitTests/cppunit/include/cppunit/extensions/HelperMacros.h new file mode 100644 index 0000000..12431e4 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/extensions/HelperMacros.h @@ -0,0 +1,541 @@ +// ////////////////////////////////////////////////////////////////////////// +// Header file HelperMacros.h +// (c)Copyright 2000, Baptiste Lepilleur. +// Created: 2001/04/15 +// ////////////////////////////////////////////////////////////////////////// +#ifndef CPPUNIT_EXTENSIONS_HELPERMACROS_H +#define CPPUNIT_EXTENSIONS_HELPERMACROS_H + +#include +#include +#include +#include +#include +#include +#include +#include + + +/*! \addtogroup WritingTestFixture Writing test fixture + */ +/** @{ + */ + + +/** \file + * Macros intended to ease the definition of test suites. + * + * The macros + * CPPUNIT_TEST_SUITE(), CPPUNIT_TEST(), and CPPUNIT_TEST_SUITE_END() + * are designed to facilitate easy creation of a test suite. + * For example, + * + * \code + * #include + * class MyTest : public CppUnit::TestFixture { + * CPPUNIT_TEST_SUITE( MyTest ); + * CPPUNIT_TEST( testEquality ); + * CPPUNIT_TEST( testSetName ); + * CPPUNIT_TEST_SUITE_END(); + * public: + * void testEquality(); + * void testSetName(); + * }; + * \endcode + * + * The effect of these macros is to define two methods in the + * class MyTest. The first method is an auxiliary function + * named registerTests that you will not need to call directly. + * The second function + * \code static CppUnit::TestSuite *suite()\endcode + * returns a pointer to the suite of tests defined by the CPPUNIT_TEST() + * macros. + * + * Rather than invoking suite() directly, + * the macro CPPUNIT_TEST_SUITE_REGISTRATION() is + * used to create a static variable that automatically + * registers its test suite in a global registry. + * The registry yields a Test instance containing all the + * registered suites. + * \code + * CPPUNIT_TEST_SUITE_REGISTRATION( MyTest ); + * CppUnit::Test* tp = + * CppUnit::TestFactoryRegistry::getRegistry().makeTest(); + * \endcode + * + * The test suite macros can even be used with templated test classes. + * For example: + * + * \code + * template + * class StringTest : public CppUnit::TestFixture { + * CPPUNIT_TEST_SUITE( StringTest ); + * CPPUNIT_TEST( testAppend ); + * CPPUNIT_TEST_SUITE_END(); + * public: + * ... + * }; + * \endcode + * + * You need to add in an implementation file: + * + * \code + * CPPUNIT_TEST_SUITE_REGISTRATION( StringTest ); + * CPPUNIT_TEST_SUITE_REGISTRATION( StringTest ); + * \endcode + */ + + +/*! \brief Begin test suite + * + * This macro starts the declaration of a new test suite. + * Use CPPUNIT_TEST_SUB_SUITE() instead, if you wish to include the + * test suite of the parent class. + * + * \param ATestFixtureType Type of the test case class. This type \b MUST + * be derived from TestFixture. + * \see CPPUNIT_TEST_SUB_SUITE, CPPUNIT_TEST, CPPUNIT_TEST_SUITE_END, + * \see CPPUNIT_TEST_SUITE_REGISTRATION, CPPUNIT_TEST_EXCEPTION, CPPUNIT_TEST_FAIL. + */ +#define CPPUNIT_TEST_SUITE( ATestFixtureType ) \ + public: \ + typedef ATestFixtureType TestFixtureType; \ + \ + private: \ + static const CPPUNIT_NS::TestNamer &getTestNamer__() \ + { \ + static CPPUNIT_TESTNAMER_DECL( testNamer, ATestFixtureType ); \ + return testNamer; \ + } \ + \ + public: \ + typedef CPPUNIT_NS::TestSuiteBuilderContext \ + TestSuiteBuilderContextType; \ + \ + static void \ + addTestsToSuite( CPPUNIT_NS::TestSuiteBuilderContextBase &baseContext ) \ + { \ + TestSuiteBuilderContextType context( baseContext ) + + +/*! \brief Begin test suite (includes parent suite) + * + * This macro may only be used in a class whose parent class + * defines a test suite using CPPUNIT_TEST_SUITE() or CPPUNIT_TEST_SUB_SUITE(). + * + * This macro begins the declaration of a test suite, in the same + * manner as CPPUNIT_TEST_SUITE(). In addition, the test suite of the + * parent is automatically inserted in the test suite being + * defined. + * + * Here is an example: + * + * \code + * #include + * class MySubTest : public MyTest { + * CPPUNIT_TEST_SUB_SUITE( MySubTest, MyTest ); + * CPPUNIT_TEST( testAdd ); + * CPPUNIT_TEST( testSub ); + * CPPUNIT_TEST_SUITE_END(); + * public: + * void testAdd(); + * void testSub(); + * }; + * \endcode + * + * \param ATestFixtureType Type of the test case class. This type \b MUST + * be derived from TestFixture. + * \param ASuperClass Type of the parent class. + * \see CPPUNIT_TEST_SUITE. + */ +#define CPPUNIT_TEST_SUB_SUITE( ATestFixtureType, ASuperClass ) \ + public: \ + typedef ASuperClass ParentTestFixtureType; \ + private: \ + CPPUNIT_TEST_SUITE( ATestFixtureType ); \ + ParentTestFixtureType::addTestsToSuite( baseContext ) + + +/*! \brief End declaration of the test suite. + * + * After this macro, member access is set to "private". + * + * \see CPPUNIT_TEST_SUITE. + * \see CPPUNIT_TEST_SUITE_REGISTRATION. + */ +#define CPPUNIT_TEST_SUITE_END() \ + } \ + \ + static CPPUNIT_NS::TestSuite *suite() \ + { \ + const CPPUNIT_NS::TestNamer &namer = getTestNamer__(); \ + std::auto_ptr suite( \ + new CPPUNIT_NS::TestSuite( namer.getFixtureName() )); \ + CPPUNIT_NS::ConcretTestFixtureFactory factory; \ + CPPUNIT_NS::TestSuiteBuilderContextBase context( *suite.get(), \ + namer, \ + factory ); \ + TestFixtureType::addTestsToSuite( context ); \ + return suite.release(); \ + } \ + private: /* dummy typedef so that the macro can still end with ';'*/ \ + typedef int CppUnitDummyTypedefForSemiColonEnding__ + +/*! \brief End declaration of an abstract test suite. + * + * Use this macro to indicate that the %TestFixture is abstract. No + * static suite() method will be declared. + * + * After this macro, member access is set to "private". + * + * Here is an example of usage: + * + * The abstract test fixture: + * \code + * #include + * class AbstractDocument; + * class AbstractDocumentTest : public CppUnit::TestFixture { + * CPPUNIT_TEST_SUITE( AbstractDocumentTest ); + * CPPUNIT_TEST( testInsertText ); + * CPPUNIT_TEST_SUITE_END_ABSTRACT(); + * public: + * void testInsertText(); + * + * void setUp() + * { + * m_document = makeDocument(); + * } + * + * void tearDown() + * { + * delete m_document; + * } + * protected: + * virtual AbstractDocument *makeDocument() =0; + * + * AbstractDocument *m_document; + * };\endcode + * + * The concret test fixture: + * \code + * class RichTextDocumentTest : public AbstractDocumentTest { + * CPPUNIT_TEST_SUB_SUITE( RichTextDocumentTest, AbstractDocumentTest ); + * CPPUNIT_TEST( testInsertFormatedText ); + * CPPUNIT_TEST_SUITE_END(); + * public: + * void testInsertFormatedText(); + * protected: + * AbstractDocument *makeDocument() + * { + * return new RichTextDocument(); + * } + * };\endcode + * + * \see CPPUNIT_TEST_SUB_SUITE. + * \see CPPUNIT_TEST_SUITE_REGISTRATION. + */ +#define CPPUNIT_TEST_SUITE_END_ABSTRACT() \ + } \ + private: /* dummy typedef so that the macro can still end with ';'*/ \ + typedef int CppUnitDummyTypedefForSemiColonEnding__ + + +/*! \brief Add a test to the suite (for custom test macro). + * + * The specified test will be added to the test suite being declared. This macro + * is intended for \e advanced usage, to extend %CppUnit by creating new macro such + * as CPPUNIT_TEST_EXCEPTION()... + * + * Between macro CPPUNIT_TEST_SUITE() and CPPUNIT_TEST_SUITE_END(), you can assume + * that the following variables can be used: + * \code + * typedef TestSuiteBuilder TestSuiteBuilderType; + * TestSuiteBuilderType &context; + * \endcode + * + * \c context can be used to name test case, create new test fixture instance, + * or add test case to the test fixture suite. + * + * Below is an example that show how to use this macro to create new macro to add + * test to the fixture suite. The macro below show how you would add a new type + * of test case which fails if the execution last more than a given time limit. + * It relies on an imaginary TimeOutTestCaller class which has an interface similar + * to TestCaller. + * + * \code + * #define CPPUNITEX_TEST_TIMELIMIT( testMethod, timeLimit ) \ + * CPPUNIT_TEST_SUITE_ADD_TEST( (new TimeOutTestCaller( \ + * namer.getTestNameFor( #testMethod ), \ + * &TestFixtureType::testMethod, \ + * factory.makeFixture(), \ + * timeLimit ) ) ) + * + * class PerformanceTest : CppUnit::TestFixture + * { + * public: + * CPPUNIT_TEST_SUITE( PerformanceTest ); + * CPPUNITEX_TEST_TIMELIMIT( testSortReverseOrder, 5.0 ); + * CPPUNIT_TEST_SUITE_END(); + * + * void testSortReverseOrder(); + * }; + * \endcode + * + * \param test Test to add to the suite. Must be a subclass of Test. The test name + * should have been obtained using TestNamer::getTestNameFor(). + */ +#define CPPUNIT_TEST_SUITE_ADD_TEST( test ) \ + context.addTest( test ) + +/*! \brief Add a method to the suite. + * \param testMethod Name of the method of the test case to add to the + * suite. The signature of the method must be of + * type: void testMethod(); + * \see CPPUNIT_TEST_SUITE. + */ +#define CPPUNIT_TEST( testMethod ) \ + CPPUNIT_TEST_SUITE_ADD_TEST( \ + ( new CPPUNIT_NS::TestCaller( \ + context.getTestNameFor( #testMethod), \ + &TestFixtureType::testMethod, \ + context.makeFixture() ) ) ) + +/*! \brief Add a test which fail if the specified exception is not caught. + * + * Example: + * \code + * #include + * #include + * class MyTest : public CppUnit::TestFixture { + * CPPUNIT_TEST_SUITE( MyTest ); + * CPPUNIT_TEST_EXCEPTION( testVectorAtThrow, std::invalid_argument ); + * CPPUNIT_TEST_SUITE_END(); + * public: + * void testVectorAtThrow() + * { + * std::vector v; + * v.at( 1 ); // must throw exception std::invalid_argument + * } + * }; + * \endcode + * + * \param testMethod Name of the method of the test case to add to the suite. + * \param ExceptionType Type of the exception that must be thrown by the test + * method. + * \deprecated Use the assertion macro CPPUNIT_ASSERT_THROW instead. + */ +#define CPPUNIT_TEST_EXCEPTION( testMethod, ExceptionType ) \ + CPPUNIT_TEST_SUITE_ADD_TEST( \ + (new CPPUNIT_NS::ExceptionTestCaseDecorator< ExceptionType >( \ + new CPPUNIT_NS::TestCaller< TestFixtureType >( \ + context.getTestNameFor( #testMethod ), \ + &TestFixtureType::testMethod, \ + context.makeFixture() ) ) ) ) + +/*! \brief Adds a test case which is excepted to fail. + * + * The added test case expect an assertion to fail. You usually used that type + * of test case when testing custom assertion macros. + * + * \code + * CPPUNIT_TEST_FAIL( testAssertFalseFail ); + * + * void testAssertFalseFail() + * { + * CPPUNIT_ASSERT( false ); + * } + * \endcode + * \see CreatingNewAssertions. + * \deprecated Use the assertion macro CPPUNIT_ASSERT_ASSERTION_FAIL instead. + */ +#define CPPUNIT_TEST_FAIL( testMethod ) \ + CPPUNIT_TEST_EXCEPTION( testMethod, CPPUNIT_NS::Exception ) + +/*! \brief Adds some custom test cases. + * + * Use this to add one or more test cases to the fixture suite. The specified + * method is called with a context parameter that can be used to name, + * instantiate fixture, and add instantiated test case to the fixture suite. + * The specified method must have the following signature: + * \code + * static void aMethodName( TestSuiteBuilderContextType &context ); + * \endcode + * + * \c TestSuiteBuilderContextType is typedef to + * TestSuiteBuilderContext declared by CPPUNIT_TEST_SUITE(). + * + * Here is an example that add two custom tests: + * + * \code + * #include + * + * class MyTest : public CppUnit::TestFixture { + * CPPUNIT_TEST_SUITE( MyTest ); + * CPPUNIT_TEST_SUITE_ADD_CUSTOM_TESTS( addTimeOutTests ); + * CPPUNIT_TEST_SUITE_END(); + * public: + * static void addTimeOutTests( TestSuiteBuilderContextType &context ) + * { + * context.addTest( new TimeOutTestCaller( context.getTestNameFor( "test1" ) ), + * &MyTest::test1, + * context.makeFixture(), + * 5.0 ); + * context.addTest( new TimeOutTestCaller( context.getTestNameFor( "test2" ) ), + * &MyTest::test2, + * context.makeFixture(), + * 5.0 ); + * } + * + * void test1() + * { + * // Do some test that may never end... + * } + * + * void test2() + * { + * // Do some test that may never end... + * } + * }; + * \endcode + * @param testAdderMethod Name of the method called to add the test cases. + */ +#define CPPUNIT_TEST_SUITE_ADD_CUSTOM_TESTS( testAdderMethod ) \ + testAdderMethod( context ) + +/*! \brief Adds a property to the test suite builder context. + * \param APropertyKey Key of the property to add. + * \param APropertyValue Value for the added property. + * Example: + * \code + * CPPUNIT_TEST_SUITE_PROPERTY("XmlFileName", "paraTest.xml"); \endcode + */ +#define CPPUNIT_TEST_SUITE_PROPERTY( APropertyKey, APropertyValue ) \ + context.addProperty( std::string(APropertyKey), \ + std::string(APropertyValue) ) + +/** @} + */ + + +/*! Adds the specified fixture suite to the unnamed registry. + * \ingroup CreatingTestSuite + * + * This macro declares a static variable whose construction + * causes a test suite factory to be inserted in a global registry + * of such factories. The registry is available by calling + * the static function CppUnit::TestFactoryRegistry::getRegistry(). + * + * \param ATestFixtureType Type of the test case class. + * \warning This macro should be used only once per line of code (the line + * number is used to name a hidden static variable). + * \see CPPUNIT_TEST_SUITE_NAMED_REGISTRATION + * \see CPPUNIT_REGISTRY_ADD_TO_DEFAULT + * \see CPPUNIT_REGISTRY_ADD + * \see CPPUNIT_TEST_SUITE, CppUnit::AutoRegisterSuite, + * CppUnit::TestFactoryRegistry. + */ +#define CPPUNIT_TEST_SUITE_REGISTRATION( ATestFixtureType ) \ + static CPPUNIT_NS::AutoRegisterSuite< ATestFixtureType > \ + CPPUNIT_MAKE_UNIQUE_NAME(autoRegisterRegistry__ ) + + +/** Adds the specified fixture suite to the specified registry suite. + * \ingroup CreatingTestSuite + * + * This macro declares a static variable whose construction + * causes a test suite factory to be inserted in the global registry + * suite of the specified name. The registry is available by calling + * the static function CppUnit::TestFactoryRegistry::getRegistry(). + * + * For the suite name, use a string returned by a static function rather + * than a hardcoded string. That way, you can know what are the name of + * named registry and you don't risk mistyping the registry name. + * + * \code + * // MySuites.h + * namespace MySuites { + * std::string math() { + * return "Math"; + * } + * } + * + * // ComplexNumberTest.cpp + * #include "MySuites.h" + * + * CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ComplexNumberTest, MySuites::math() ); + * \endcode + * + * \param ATestFixtureType Type of the test case class. + * \param suiteName Name of the global registry suite the test suite is + * registered into. + * \warning This macro should be used only once per line of code (the line + * number is used to name a hidden static variable). + * \see CPPUNIT_TEST_SUITE_REGISTRATION + * \see CPPUNIT_REGISTRY_ADD_TO_DEFAULT + * \see CPPUNIT_REGISTRY_ADD + * \see CPPUNIT_TEST_SUITE, CppUnit::AutoRegisterSuite, + * CppUnit::TestFactoryRegistry.. + */ +#define CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ATestFixtureType, suiteName ) \ + static CPPUNIT_NS::AutoRegisterSuite< ATestFixtureType > \ + CPPUNIT_MAKE_UNIQUE_NAME(autoRegisterRegistry__ )(suiteName) + +/*! Adds that the specified registry suite to another registry suite. + * \ingroup CreatingTestSuite + * + * Use this macros to automatically create test registry suite hierarchy. For example, + * if you want to create the following hierarchy: + * - Math + * - IntegerMath + * - FloatMath + * - FastFloat + * - StandardFloat + * + * You can do this automatically with: + * \code + * CPPUNIT_REGISTRY_ADD( "FastFloat", "FloatMath" ); + * CPPUNIT_REGISTRY_ADD( "IntegerMath", "Math" ); + * CPPUNIT_REGISTRY_ADD( "FloatMath", "Math" ); + * CPPUNIT_REGISTRY_ADD( "StandardFloat", "FloatMath" ); + * \endcode + * + * There is no specific order of declaration. Think of it as declaring links. + * + * You register the test in each suite using CPPUNIT_TEST_SUITE_NAMED_REGISTRATION. + * + * \param which Name of the registry suite to add to the registry suite named \a to. + * \param to Name of the registry suite \a which is added to. + * \see CPPUNIT_REGISTRY_ADD_TO_DEFAULT, CPPUNIT_TEST_SUITE_NAMED_REGISTRATION. + */ +#define CPPUNIT_REGISTRY_ADD( which, to ) \ + static CPPUNIT_NS::AutoRegisterRegistry \ + CPPUNIT_MAKE_UNIQUE_NAME( autoRegisterRegistry__ )( which, to ) + +/*! Adds that the specified registry suite to the default registry suite. + * \ingroup CreatingTestSuite + * + * This macro is just like CPPUNIT_REGISTRY_ADD except the specified registry + * suite is added to the default suite (root suite). + * + * \param which Name of the registry suite to add to the default registry suite. + * \see CPPUNIT_REGISTRY_ADD. + */ +#define CPPUNIT_REGISTRY_ADD_TO_DEFAULT( which ) \ + static CPPUNIT_NS::AutoRegisterRegistry \ + CPPUNIT_MAKE_UNIQUE_NAME( autoRegisterRegistry__ )( which ) + +// Backwards compatibility +// (Not tested!) + +#if CPPUNIT_ENABLE_CU_TEST_MACROS + +#define CU_TEST_SUITE(tc) CPPUNIT_TEST_SUITE(tc) +#define CU_TEST_SUB_SUITE(tc,sc) CPPUNIT_TEST_SUB_SUITE(tc,sc) +#define CU_TEST(tm) CPPUNIT_TEST(tm) +#define CU_TEST_SUITE_END() CPPUNIT_TEST_SUITE_END() +#define CU_TEST_SUITE_REGISTRATION(tc) CPPUNIT_TEST_SUITE_REGISTRATION(tc) + +#endif + + +#endif // CPPUNIT_EXTENSIONS_HELPERMACROS_H diff --git a/UnitTests/cppunit/include/cppunit/extensions/Orthodox.h b/UnitTests/cppunit/include/cppunit/extensions/Orthodox.h new file mode 100644 index 0000000..7221259 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/extensions/Orthodox.h @@ -0,0 +1,95 @@ +#ifndef CPPUNIT_EXTENSIONS_ORTHODOX_H +#define CPPUNIT_EXTENSIONS_ORTHODOX_H + +#include + +CPPUNIT_NS_BEGIN + + +/* + * Orthodox performs a simple set of tests on an arbitary + * class to make sure that it supports at least the + * following operations: + * + * default construction - constructor + * equality/inequality - operator== && operator!= + * assignment - operator= + * negation - operator! + * safe passage - copy construction + * + * If operations for each of these are not declared + * the template will not instantiate. If it does + * instantiate, tests are performed to make sure + * that the operations have correct semantics. + * + * Adding an orthodox test to a suite is very + * easy: + * + * public: Test *suite () { + * TestSuite *suiteOfTests = new TestSuite; + * suiteOfTests->addTest (new ComplexNumberTest ("testAdd"); + * suiteOfTests->addTest (new TestCaller > ()); + * return suiteOfTests; + * } + * + * Templated test cases be very useful when you are want to + * make sure that a group of classes have the same form. + * + * see TestSuite + */ + + +template class Orthodox : public TestCase +{ +public: + Orthodox () : TestCase ("Orthodox") {} + +protected: + ClassUnderTest call (ClassUnderTest object); + void runTest (); + + +}; + + +// Run an orthodoxy test +template void Orthodox::runTest () +{ + // make sure we have a default constructor + ClassUnderTest a, b, c; + + // make sure we have an equality operator + CPPUNIT_ASSERT (a == b); + + // check the inverse + b.operator= (a.operator! ()); + CPPUNIT_ASSERT (a != b); + + // double inversion + b = !!a; + CPPUNIT_ASSERT (a == b); + + // invert again + b = !a; + + // check calls + c = a; + CPPUNIT_ASSERT (c == call (a)); + + c = b; + CPPUNIT_ASSERT (c == call (b)); + +} + + +// Exercise a call +template +ClassUnderTest Orthodox::call (ClassUnderTest object) +{ + return object; +} + + +CPPUNIT_NS_END + +#endif diff --git a/UnitTests/cppunit/include/cppunit/extensions/RepeatedTest.h b/UnitTests/cppunit/include/cppunit/extensions/RepeatedTest.h new file mode 100644 index 0000000..390ce48 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/extensions/RepeatedTest.h @@ -0,0 +1,43 @@ +#ifndef CPPUNIT_EXTENSIONS_REPEATEDTEST_H +#define CPPUNIT_EXTENSIONS_REPEATEDTEST_H + +#include +#include + +CPPUNIT_NS_BEGIN + + +class Test; +class TestResult; + + +/*! \brief Decorator that runs a test repeatedly. + * + * Does not assume ownership of the test it decorates + */ +class CPPUNIT_API RepeatedTest : public TestDecorator +{ +public: + RepeatedTest( Test *test, + int timesRepeat ) : + TestDecorator( test ), + m_timesRepeat(timesRepeat) + { + } + + void run( TestResult *result ); + + int countTestCases() const; + +private: + RepeatedTest( const RepeatedTest & ); + void operator=( const RepeatedTest & ); + + const int m_timesRepeat; +}; + + +CPPUNIT_NS_END + + +#endif // CPPUNIT_EXTENSIONS_REPEATEDTEST_H diff --git a/UnitTests/cppunit/include/cppunit/extensions/TestCaseDecorator.h b/UnitTests/cppunit/include/cppunit/extensions/TestCaseDecorator.h new file mode 100644 index 0000000..3a15ba9 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/extensions/TestCaseDecorator.h @@ -0,0 +1,40 @@ +#ifndef CPPUNIT_EXTENSIONS_TESTCASEDECORATOR_H +#define CPPUNIT_EXTENSIONS_TESTCASEDECORATOR_H + +#include +#include + +CPPUNIT_NS_BEGIN + + +/*! \brief Decorator for Test cases. + * + * TestCaseDecorator provides an alternate means to extend functionality + * of a test class without subclassing the test. Instead, one can + * subclass the decorater and use it to wrap the test class. + * + * Does not assume ownership of the test it decorates + */ +class CPPUNIT_API TestCaseDecorator : public TestCase +{ +public: + TestCaseDecorator( TestCase *test ); + ~TestCaseDecorator(); + + std::string getName() const; + + void setUp(); + + void tearDown(); + + void runTest(); + +protected: + TestCase *m_test; +}; + + +CPPUNIT_NS_END + +#endif + diff --git a/UnitTests/cppunit/include/cppunit/extensions/TestDecorator.h b/UnitTests/cppunit/include/cppunit/extensions/TestDecorator.h new file mode 100644 index 0000000..59d9a30 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/extensions/TestDecorator.h @@ -0,0 +1,49 @@ +#ifndef CPPUNIT_EXTENSIONS_TESTDECORATOR_H +#define CPPUNIT_EXTENSIONS_TESTDECORATOR_H + +#include +#include + +CPPUNIT_NS_BEGIN + + +class TestResult; + + +/*! \brief Decorator for Tests. + * + * TestDecorator provides an alternate means to extend functionality + * of a test class without subclassing the test. Instead, one can + * subclass the decorater and use it to wrap the test class. + * + * Does not assume ownership of the test it decorates + */ +class CPPUNIT_API TestDecorator : public Test +{ +public: + TestDecorator( Test *test ); + ~TestDecorator(); + + int countTestCases() const; + + std::string getName() const; + + void run( TestResult *result ); + + int getChildTestCount() const; + +protected: + Test *doGetChildTestAt( int index ) const; + + Test *m_test; + +private: + TestDecorator( const TestDecorator &); + void operator =( const TestDecorator & ); +}; + + +CPPUNIT_NS_END + +#endif + diff --git a/UnitTests/cppunit/include/cppunit/extensions/TestFactory.h b/UnitTests/cppunit/include/cppunit/extensions/TestFactory.h new file mode 100644 index 0000000..214d353 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/extensions/TestFactory.h @@ -0,0 +1,27 @@ +#ifndef CPPUNIT_EXTENSIONS_TESTFACTORY_H +#define CPPUNIT_EXTENSIONS_TESTFACTORY_H + +#include + +CPPUNIT_NS_BEGIN + + +class Test; + +/*! \brief Abstract Test factory. + */ +class CPPUNIT_API TestFactory +{ +public: + virtual ~TestFactory() {} + + /*! Makes a new test. + * \return A new Test. + */ + virtual Test* makeTest() = 0; +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_EXTENSIONS_TESTFACTORY_H diff --git a/UnitTests/cppunit/include/cppunit/extensions/TestFactoryRegistry.h b/UnitTests/cppunit/include/cppunit/extensions/TestFactoryRegistry.h new file mode 100644 index 0000000..fc8723e --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/extensions/TestFactoryRegistry.h @@ -0,0 +1,182 @@ +#ifndef CPPUNIT_EXTENSIONS_TESTFACTORYREGISTRY_H +#define CPPUNIT_EXTENSIONS_TESTFACTORYREGISTRY_H + +#include + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( push ) +#pragma warning( disable: 4251) // X needs to have dll-interface to be used by clients of class Z +#endif + +#include +#include +#include + +CPPUNIT_NS_BEGIN + + +class TestSuite; + +#if CPPUNIT_NEED_DLL_DECL +// template class CPPUNIT_API std::set; +#endif + + +/*! \brief Registry for TestFactory. + * \ingroup CreatingTestSuite + * + * Notes that the registry \b DON'T assumes lifetime control for any registered tests + * anymore. + * + * The default registry is the registry returned by getRegistry() with the + * default name parameter value. + * + * To register tests, use the macros: + * - CPPUNIT_TEST_SUITE_REGISTRATION(): to add tests in the default registry. + * - CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(): to add tests in a named registry. + * + * Example 1: retreiving a suite that contains all the test registered with + * CPPUNIT_TEST_SUITE_REGISTRATION(). + * \code + * CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry(); + * CppUnit::TestSuite *suite = registry.makeTest(); + * \endcode + * + * Example 2: retreiving a suite that contains all the test registered with + * \link CPPUNIT_TEST_SUITE_NAMED_REGISTRATION() CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ..., "Math" )\endlink. + * \code + * CppUnit::TestFactoryRegistry &mathRegistry = CppUnit::TestFactoryRegistry::getRegistry( "Math" ); + * CppUnit::TestSuite *mathSuite = mathRegistry.makeTest(); + * \endcode + * + * Example 3: creating a test suite hierarchy composed of unnamed registration and + * named registration: + * - All Tests + * - tests registered with CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ..., "Graph" ) + * - tests registered with CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ..., "Math" ) + * - tests registered with CPPUNIT_TEST_SUITE_REGISTRATION + * + * \code + * CppUnit::TestSuite *rootSuite = new CppUnit::TestSuite( "All tests" ); + * rootSuite->addTest( CppUnit::TestFactoryRegistry::getRegistry( "Graph" ).makeTest() ); + * rootSuite->addTest( CppUnit::TestFactoryRegistry::getRegistry( "Math" ).makeTest() ); + * CppUnit::TestFactoryRegistry::getRegistry().addTestToSuite( rootSuite ); + * \endcode + * + * The same result can be obtained with: + * \code + * CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry(); + * registry.addRegistry( "Graph" ); + * registry.addRegistry( "Math" ); + * CppUnit::TestSuite *suite = registry.makeTest(); + * \endcode + * + * Since a TestFactoryRegistry is a TestFactory, the named registries can be + * registered in the unnamed registry, creating the hierarchy links. + * + * \see TestSuiteFactory, AutoRegisterSuite + * \see CPPUNIT_TEST_SUITE_REGISTRATION, CPPUNIT_TEST_SUITE_NAMED_REGISTRATION + */ +class CPPUNIT_API TestFactoryRegistry : public TestFactory +{ +public: + /** Constructs the registry with the specified name. + * \param name Name of the registry. It is the name of TestSuite returned by + * makeTest(). + */ + TestFactoryRegistry( std::string name ); + + /// Destructor. + virtual ~TestFactoryRegistry(); + + /** Returns a new TestSuite that contains the registered test. + * \return A new TestSuite which contains all the test added using + * registerFactory(TestFactory *). + */ + virtual Test *makeTest(); + + /** Returns a named registry. + * + * If the \a name is left to its default value, then the registry that is returned is + * the one used by CPPUNIT_TEST_SUITE_REGISTRATION(): the 'top' level registry. + * + * \param name Name of the registry to return. + * \return Registry. If the registry does not exist, it is created with the + * specified name. + */ + static TestFactoryRegistry &getRegistry( const std::string &name = "All Tests" ); + + /** Adds the registered tests to the specified suite. + * \param suite Suite the tests are added to. + */ + void addTestToSuite( TestSuite *suite ); + + /** Adds the specified TestFactory to the registry. + * + * \param factory Factory to register. + */ + void registerFactory( TestFactory *factory ); + + /*! Removes the specified TestFactory from the registry. + * + * The specified factory is not destroyed. + * \param factory Factory to remove from the registry. + * \todo Address case when trying to remove a TestRegistryFactory. + */ + void unregisterFactory( TestFactory *factory ); + + /*! Adds a registry to the registry. + * + * Convenience method to help create test hierarchy. See TestFactoryRegistry detail + * for examples of use. Calling this method is equivalent to: + * \code + * this->registerFactory( TestFactoryRegistry::getRegistry( name ) ); + * \endcode + * + * \param name Name of the registry to add. + */ + void addRegistry( const std::string &name ); + + /*! Tests if the registry is valid. + * + * This method should be used when unregistering test factory on static variable + * destruction to ensure that the registry has not been already destroyed (in + * that case there is no need to unregister the test factory). + * + * You should not concern yourself with this method unless you are writing a class + * like AutoRegisterSuite. + * + * \return \c true if the specified registry has not been destroyed, + * otherwise returns \c false. + * \see AutoRegisterSuite. + */ + static bool isValid(); + + /** Adds the specified TestFactory with a specific name (DEPRECATED). + * \param name Name associated to the factory. + * \param factory Factory to register. + * \deprecated Use registerFactory( TestFactory *) instead. + */ + void registerFactory( const std::string &name, + TestFactory *factory ); + +private: + TestFactoryRegistry( const TestFactoryRegistry © ); + void operator =( const TestFactoryRegistry © ); + +private: + typedef CppUnitSet > Factories; + Factories m_factories; + + std::string m_name; +}; + + +CPPUNIT_NS_END + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( pop ) +#endif + + +#endif // CPPUNIT_EXTENSIONS_TESTFACTORYREGISTRY_H diff --git a/UnitTests/cppunit/include/cppunit/extensions/TestFixtureFactory.h b/UnitTests/cppunit/include/cppunit/extensions/TestFixtureFactory.h new file mode 100644 index 0000000..45354c6 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/extensions/TestFixtureFactory.h @@ -0,0 +1,50 @@ +#ifndef CPPUNIT_EXTENSIONS_TESTFIXTUREFACTORY_H +#define CPPUNIT_EXTENSIONS_TESTFIXTUREFACTORY_H + +#include + + +CPPUNIT_NS_BEGIN + + +class TestFixture; + +/*! \brief Abstract TestFixture factory (Implementation). + * + * Implementation detail. Use by HelperMacros to handle TestFixture hierarchy. + */ +class TestFixtureFactory +{ +public: + //! Creates a new TestFixture instance. + virtual TestFixture *makeFixture() =0; + + virtual ~TestFixtureFactory() {} +}; + + +/*! \brief Concret TestFixture factory (Implementation). + * + * Implementation detail. Use by HelperMacros to handle TestFixture hierarchy. + */ +template +class ConcretTestFixtureFactory : public CPPUNIT_NS::TestFixtureFactory +{ + /*! \brief Returns a new TestFixture instance. + * \return A new fixture instance. The fixture instance is returned by + * the TestFixtureFactory passed on construction. The actual type + * is that of the fixture on which the static method suite() + * was called. + */ + TestFixture *makeFixture() + { + return new TestFixtureType(); + } +}; + + +CPPUNIT_NS_END + + +#endif // CPPUNIT_EXTENSIONS_TESTFIXTUREFACTORY_H + diff --git a/UnitTests/cppunit/include/cppunit/extensions/TestNamer.h b/UnitTests/cppunit/include/cppunit/extensions/TestNamer.h new file mode 100644 index 0000000..5a6471c --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/extensions/TestNamer.h @@ -0,0 +1,89 @@ +#ifndef CPPUNIT_EXTENSIONS_TESTNAMER_H +#define CPPUNIT_EXTENSIONS_TESTNAMER_H + +#include +#include + +#if CPPUNIT_HAVE_RTTI +# include +#endif + + + +/*! \def CPPUNIT_TESTNAMER_DECL( variableName, FixtureType ) + * \brief Declares a TestNamer. + * + * Declares a TestNamer for the specified type, using RTTI if enabled, otherwise + * using macro string expansion. + * + * RTTI is used if CPPUNIT_USE_TYPEINFO_NAME is defined and not null. + * + * \code + * void someMethod() + * { + * CPPUNIT_TESTNAMER_DECL( namer, AFixtureType ); + * std::string fixtureName = namer.getFixtureName(); + * ... + * \endcode + * + * \relates TestNamer + * \see TestNamer + */ +#if CPPUNIT_USE_TYPEINFO_NAME +# define CPPUNIT_TESTNAMER_DECL( variableName, FixtureType ) \ + CPPUNIT_NS::TestNamer variableName( typeid(FixtureType) ) +#else +# define CPPUNIT_TESTNAMER_DECL( variableName, FixtureType ) \ + CPPUNIT_NS::TestNamer variableName( std::string(#FixtureType) ) +#endif + + + +CPPUNIT_NS_BEGIN + + +/*! \brief Names a test or a fixture suite. + * + * TestNamer is usually instantiated using CPPUNIT_TESTNAMER_DECL. + * + */ +class CPPUNIT_API TestNamer +{ +public: +#if CPPUNIT_HAVE_RTTI + /*! \brief Constructs a namer using the fixture's type-info. + * \param typeInfo Type-info of the fixture type. Use to name the fixture suite. + */ + TestNamer( const std::type_info &typeInfo ); +#endif + + /*! \brief Constructs a namer using the specified fixture name. + * \param fixtureName Name of the fixture suite. Usually extracted using a macro. + */ + TestNamer( const std::string &fixtureName ); + + virtual ~TestNamer(); + + /*! \brief Returns the name of the fixture. + * \return Name of the fixture. + */ + virtual std::string getFixtureName() const; + + /*! \brief Returns the name of the test for the specified method. + * \param testMethodName Name of the method that implements a test. + * \return A string that is the concatenation of the test fixture name + * (returned by getFixtureName()) and\a testMethodName, + * separated using '::'. This provides a fairly unique name for a given + * test. + */ + virtual std::string getTestNameFor( const std::string &testMethodName ) const; + +protected: + std::string m_fixtureName; +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_EXTENSIONS_TESTNAMER_H + diff --git a/UnitTests/cppunit/include/cppunit/extensions/TestSetUp.h b/UnitTests/cppunit/include/cppunit/extensions/TestSetUp.h new file mode 100644 index 0000000..f2128ec --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/extensions/TestSetUp.h @@ -0,0 +1,34 @@ +#ifndef CPPUNIT_EXTENSIONS_TESTSETUP_H +#define CPPUNIT_EXTENSIONS_TESTSETUP_H + +#include + +CPPUNIT_NS_BEGIN + + +class Test; +class TestResult; + +/*! \brief Decorates a test by providing a specific setUp() and tearDown(). + */ +class CPPUNIT_API TestSetUp : public TestDecorator +{ +public: + TestSetUp( Test *test ); + + void run( TestResult *result ); + +protected: + virtual void setUp(); + virtual void tearDown(); + +private: + TestSetUp( const TestSetUp & ); + void operator =( const TestSetUp & ); +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_EXTENSIONS_TESTSETUP_H + diff --git a/UnitTests/cppunit/include/cppunit/extensions/TestSuiteBuilderContext.h b/UnitTests/cppunit/include/cppunit/extensions/TestSuiteBuilderContext.h new file mode 100644 index 0000000..db26926 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/extensions/TestSuiteBuilderContext.h @@ -0,0 +1,131 @@ +#ifndef CPPUNIT_HELPER_TESTSUITEBUILDERCONTEXT_H +#define CPPUNIT_HELPER_TESTSUITEBUILDERCONTEXT_H + +#include +#include +#include + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( push ) +#pragma warning( disable: 4251 ) // X needs to have dll-interface to be used by clients of class Z +#endif + + +CPPUNIT_NS_BEGIN + +class TestSuite; +class TestFixture; +class TestFixtureFactory; +class TestNamer; + +/*! \brief Context used when creating test suite in HelperMacros. + * + * Base class for all context used when creating test suite. The + * actual context type during test suite creation is TestSuiteBuilderContext. + * + * \sa CPPUNIT_TEST_SUITE, CPPUNIT_TEST_SUITE_ADD_TEST, + * CPPUNIT_TEST_SUITE_ADD_CUSTOM_TESTS. + */ +class CPPUNIT_API TestSuiteBuilderContextBase +{ +public: + /*! \brief Constructs a new context. + * + * You should not use this. The context is created in + * CPPUNIT_TEST_SUITE(). + */ + TestSuiteBuilderContextBase( TestSuite &suite, + const TestNamer &namer, + TestFixtureFactory &factory ); + + virtual ~TestSuiteBuilderContextBase(); + + /*! \brief Adds a test to the fixture suite. + * + * \param test Test to add to the fixture suite. Must not be \c NULL. + */ + void addTest( Test *test ); + + /*! \brief Returns the fixture name. + * \return Fixture name. It is the name used to name the fixture + * suite. + */ + std::string getFixtureName() const; + + /*! \brief Returns the name of the test for the specified method. + * + * \param testMethodName Name of the method that implements a test. + * \return A string that is the concatenation of the test fixture name + * (returned by getFixtureName()) and\a testMethodName, + * separated using '::'. This provides a fairly unique name for a given + * test. + */ + std::string getTestNameFor( const std::string &testMethodName ) const; + + /*! \brief Adds property pair. + * \param key PropertyKey string to add. + * \param value PropertyValue string to add. + */ + void addProperty( const std::string &key, + const std::string &value ); + + /*! \brief Returns property value assigned to param key. + * \param key PropertyKey string. + */ + const std::string getStringProperty( const std::string &key ) const; + +protected: + TestFixture *makeTestFixture() const; + + // Notes: we use a vector here instead of a map to work-around the + // shared std::map in dll bug in VC6. + // See http://www.dinkumware.com/vc_fixes.html for detail. + typedef std::pair Property; + typedef CppUnitVector Properties; + + TestSuite &m_suite; + const TestNamer &m_namer; + TestFixtureFactory &m_factory; + +private: + Properties m_properties; +}; + + +/*! \brief Type-sage context used when creating test suite in HelperMacros. + * + * \sa TestSuiteBuilderContextBase. + */ +template +class TestSuiteBuilderContext : public TestSuiteBuilderContextBase +{ +public: + typedef Fixture FixtureType; + + TestSuiteBuilderContext( TestSuiteBuilderContextBase &contextBase ) + : TestSuiteBuilderContextBase( contextBase ) + { + } + + /*! \brief Returns a new TestFixture instance. + * \return A new fixture instance. The fixture instance is returned by + * the TestFixtureFactory passed on construction. The actual type + * is that of the fixture on which the static method suite() + * was called. + */ + FixtureType *makeFixture() const + { + return CPPUNIT_STATIC_CAST( FixtureType *, + TestSuiteBuilderContextBase::makeTestFixture() ); + } +}; + + +CPPUNIT_NS_END + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( pop ) +#endif + +#endif // CPPUNIT_HELPER_TESTSUITEBUILDERCONTEXT_H + diff --git a/UnitTests/cppunit/include/cppunit/extensions/TestSuiteFactory.h b/UnitTests/cppunit/include/cppunit/extensions/TestSuiteFactory.h new file mode 100644 index 0000000..260b483 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/extensions/TestSuiteFactory.h @@ -0,0 +1,27 @@ +#ifndef CPPUNIT_EXTENSIONS_TESTSUITEFACTORY_H +#define CPPUNIT_EXTENSIONS_TESTSUITEFACTORY_H + +#include + +CPPUNIT_NS_BEGIN + + + class Test; + + /*! \brief TestFactory for TestFixture that implements a static suite() method. + * \see AutoRegisterSuite. + */ + template + class TestSuiteFactory : public TestFactory + { + public: + virtual Test *makeTest() + { + return TestCaseType::suite(); + } + }; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_EXTENSIONS_TESTSUITEFACTORY_H diff --git a/UnitTests/cppunit/include/cppunit/extensions/TypeInfoHelper.h b/UnitTests/cppunit/include/cppunit/extensions/TypeInfoHelper.h new file mode 100644 index 0000000..c0ecdbc --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/extensions/TypeInfoHelper.h @@ -0,0 +1,33 @@ +#ifndef CPPUNIT_TYPEINFOHELPER_H +#define CPPUNIT_TYPEINFOHELPER_H + +#include + +#if CPPUNIT_HAVE_RTTI + +#include +#include + +CPPUNIT_NS_BEGIN + + + /**! \brief Helper to use type_info. + */ + class CPPUNIT_API TypeInfoHelper + { + public: + /*! \brief Get the class name of the specified type_info. + * \param info Info which the class name is extracted from. + * \return The string returned by type_info::name() without + * the "class" prefix. If the name is not prefixed + * by "class", it is returned as this. + */ + static std::string getClassName( const std::type_info &info ); + }; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_HAVE_RTTI + +#endif // CPPUNIT_TYPEINFOHELPER_H diff --git a/UnitTests/cppunit/include/cppunit/extensions/XmlInputHelper.h b/UnitTests/cppunit/include/cppunit/extensions/XmlInputHelper.h new file mode 100644 index 0000000..4f06e5b --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/extensions/XmlInputHelper.h @@ -0,0 +1,23 @@ +#ifndef CPPUNIT_EXTENSIONS_XMLINPUTHELPER_H +#define CPPUNIT_EXTENSIONS_XMLINPUTHELPER_H + +#include + + +/*! \brief Adds a parameterized test method to the suite. + * \param testMethod Name of the method of the test case to add to the + * suite. The signature of the method must be of + * type: void testMethod(std::istream& param_in, std::istream& exp_in); + * \see CPPUNIT_TEST_SUITE. + */ +#define CPPUNIT_TEST_XML( testMethod) \ + CPPUNIT_TEST_ADD( new CppUnit::ParameterizedTestCase( \ + context.getTestNameFor( #testMethod ), \ + #testMethod, \ + &TestFixtureType::testMethod, \ + context.makeFixture(), \ + context.getStringProperty( std::string("XmlFileName") ) ) ) + + + +#endif // CPPUNIT_EXTENSIONS_XMLINPUTHELPER_H \ No newline at end of file diff --git a/UnitTests/cppunit/include/cppunit/plugin/DynamicLibraryManager.h b/UnitTests/cppunit/include/cppunit/plugin/DynamicLibraryManager.h new file mode 100644 index 0000000..d70ccde --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/plugin/DynamicLibraryManager.h @@ -0,0 +1,121 @@ +#ifndef CPPUNIT_PLUGIN_DYNAMICLIBRARYMANAGER_H +#define CPPUNIT_PLUGIN_DYNAMICLIBRARYMANAGER_H + +#include +#include + +#if !defined(CPPUNIT_NO_TESTPLUGIN) + +CPPUNIT_NS_BEGIN + + +/*! \brief Manages dynamic libraries. + * + * The Dynamic Library Manager provides a platform independent way to work with + * dynamic library. It load a specific dynamic library, and can returns specific + * symbol exported by the dynamic library. + * + * If an error occurs, a DynamicLibraryManagerException is thrown. + * + * \internal Implementation of the OS independent methods is in + * DynamicLibraryManager.cpp. + * + * \internal Porting to a new platform: + * - Adds platform detection in config/SelectDllLoader.h. Should define a specific + * macro for that platform of the form: CPPUNIT_HAVE_XYZ_DLL_LOADER, where + * XYZ is the platform. + * - Makes a copy of UnixDynamicLibraryManager.cpp and named it after the platform. + * - Updated the 'guard' in your file (CPPUNIT_HAVE_XYZ_DLL_LOADER) so that it is + * only processed if the matching platform has been detected. + * - Change the implementation of methods doLoadLibrary(), doReleaseLibrary(), + * doFindSymbol() in your copy. Those methods usually maps directly to OS calls. + * - Adds the file to the project. + */ +class DynamicLibraryManager +{ +public: + typedef void *Symbol; + typedef void *LibraryHandle; + + /*! \brief Loads the specified library. + * \param libraryFileName Name of the library to load. + * \exception DynamicLibraryManagerException if a failure occurs while loading + * the library (fail to found or load the library). + */ + DynamicLibraryManager( const std::string &libraryFileName ); + + /// Releases the loaded library.. + ~DynamicLibraryManager(); + + /*! \brief Returns a pointer on the specified symbol exported by the library. + * \param symbol Name of the symbol exported by the library. + * \return Pointer on the symbol. Should be casted to the actual type. Never \c NULL. + * \exception DynamicLibraryManagerException if the symbol is not found. + */ + Symbol findSymbol( const std::string &symbol ); + +private: + /*! Loads the specified library. + * \param libraryName Name of the library to load. + * \exception DynamicLibraryManagerException if a failure occurs while loading + * the library (fail to found or load the library). + */ + void loadLibrary( const std::string &libraryName ); + + /*! Releases the loaded library. + * + * \warning Must NOT throw any exceptions (called from destructor). + */ + void releaseLibrary(); + + /*! Loads the specified library. + * + * May throw any exceptions (indicates failure). + * \param libraryName Name of the library to load. + * \return Handle of the loaded library. \c NULL indicates failure. + */ + LibraryHandle doLoadLibrary( const std::string &libraryName ); + + /*! Releases the loaded library. + * + * The handle of the library to free is in \c m_libraryHandle. It is never + * \c NULL. + * \warning Must NOT throw any exceptions (called from destructor). + */ + void doReleaseLibrary(); + + /*! Returns a pointer on the specified symbol exported by the library. + * + * May throw any exceptions (indicates failure). + * \param symbol Name of the symbol exported by the library. + * \return Pointer on the symbol. \c NULL indicates failure. + */ + Symbol doFindSymbol( const std::string &symbol ); + + /*! Returns detailed information about doLoadLibrary() failure. + * + * Called just after a failed call to doLoadLibrary() to get extra + * error information. + * + * \return Detailed information about the failure of the call to + * doLoadLibrary() that just failed. + */ + std::string getLastErrorDetail() const; + + /// Prevents the use of the copy constructor. + DynamicLibraryManager( const DynamicLibraryManager © ); + + /// Prevents the use of the copy operator. + void operator =( const DynamicLibraryManager © ); + +private: + LibraryHandle m_libraryHandle; + std::string m_libraryName; +}; + + +CPPUNIT_NS_END + +#endif // !defined(CPPUNIT_NO_TESTPLUGIN) + +#endif // CPPUNIT_PLUGIN_DYNAMICLIBRARYMANAGER_H diff --git a/UnitTests/cppunit/include/cppunit/plugin/DynamicLibraryManagerException.h b/UnitTests/cppunit/include/cppunit/plugin/DynamicLibraryManagerException.h new file mode 100644 index 0000000..11ebbd9 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/plugin/DynamicLibraryManagerException.h @@ -0,0 +1,53 @@ +#ifndef CPPUNIT_PLUGIN_DYNAMICLIBRARYMANAGEREXCEPTION_H +#define CPPUNIT_PLUGIN_DYNAMICLIBRARYMANAGEREXCEPTION_H + +#include + +#if !defined(CPPUNIT_NO_TESTPLUGIN) +#include +#include + + +CPPUNIT_NS_BEGIN + + +/*! \brief Exception thrown by DynamicLibraryManager when a failure occurs. + * + * Use getCause() to know what function caused the failure. + * + */ +class DynamicLibraryManagerException : public std::runtime_error +{ +public: + enum Cause + { + /// Failed to load the dynamic library + loadingFailed =0, + /// Symbol not found in the dynamic library + symbolNotFound + }; + + /// Failed to load the dynamic library or Symbol not found in the dynamic library. + DynamicLibraryManagerException( const std::string &libraryName, + const std::string &errorDetail, + Cause cause ); + + ~DynamicLibraryManagerException() throw() + { + } + + Cause getCause() const; + + const char *what() const throw(); + +private: + std::string m_message; + Cause m_cause; +}; + + +CPPUNIT_NS_END + +#endif // !defined(CPPUNIT_NO_TESTPLUGIN) + +#endif // CPPUNIT_PLUGIN_DYNAMICLIBRARYMANAGEREXCEPTION_H diff --git a/UnitTests/cppunit/include/cppunit/plugin/PlugInManager.h b/UnitTests/cppunit/include/cppunit/plugin/PlugInManager.h new file mode 100644 index 0000000..6ecedc8 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/plugin/PlugInManager.h @@ -0,0 +1,113 @@ +#ifndef CPPUNIT_PLUGIN_PLUGINMANAGER_H +#define CPPUNIT_PLUGIN_PLUGINMANAGER_H + +#include + +#if !defined(CPPUNIT_NO_TESTPLUGIN) + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( push ) +#pragma warning( disable: 4251 ) // X needs to have dll-interface to be used by clients of class Z +#endif + +#include +struct CppUnitTestPlugIn; + +CPPUNIT_NS_BEGIN + + +class DynamicLibraryManager; +class TestResult; +class XmlOutputter; + + +/*! \brief Manges TestPlugIn. + */ +class CPPUNIT_API PlugInManager +{ +public: + /*! Constructs a PlugInManager object. + */ + PlugInManager(); + + /// Destructor. + virtual ~PlugInManager(); + + /*! \brief Loads the specified plug-in. + * + * After being loaded, the CppUnitTestPlugIn::initialize() is called. + * + * \param libraryFileName Name of the file that contains the TestPlugIn. + * \param parameters List of string passed to the plug-in. + * \return Pointer on the DynamicLibraryManager associated to the library. + * Valid until the library is unloaded. Never \c NULL. + * \exception DynamicLibraryManagerException is thrown if an error occurs during loading. + */ + void load( const std::string &libraryFileName, + const PlugInParameters ¶meters = PlugInParameters() ); + + /*! \brief Unloads the specified plug-in. + * \param libraryFileName Name of the file that contains the TestPlugIn passed + * to a previous call to load(). + */ + void unload( const std::string &libraryFileName ); + + /*! \brief Gives a chance to each loaded plug-in to register TestListener. + * + * For each plug-in, call CppUnitTestPlugIn::addListener(). + */ + void addListener( TestResult *eventManager ); + + /*! \brief Gives a chance to each loaded plug-in to unregister TestListener. + * For each plug-in, call CppUnitTestPlugIn::removeListener(). + */ + void removeListener( TestResult *eventManager ); + + /*! \brief Provides a way for the plug-in to register some XmlOutputterHook. + */ + void addXmlOutputterHooks( XmlOutputter *outputter ); + + /*! \brief Called when the XmlOutputter is destroyed. + * + * Can be used to free some resources allocated by addXmlOutputterHooks(). + */ + void removeXmlOutputterHooks(); + +protected: + /*! \brief (INTERNAL) Information about a specific plug-in. + */ + struct PlugInInfo + { + std::string m_fileName; + DynamicLibraryManager *m_manager; + CppUnitTestPlugIn *m_interface; + }; + + /*! Unloads the specified plug-in. + * \param plugIn Information about the plug-in. + */ + void unload( PlugInInfo &plugIn ); + +private: + /// Prevents the use of the copy constructor. + PlugInManager( const PlugInManager © ); + + /// Prevents the use of the copy operator. + void operator =( const PlugInManager © ); + +private: + typedef CppUnitDeque PlugIns; + PlugIns m_plugIns; +}; + + +CPPUNIT_NS_END + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( pop ) +#endif + +#endif // !defined(CPPUNIT_NO_TESTPLUGIN) + + +#endif // CPPUNIT_PLUGIN_PLUGINMANAGER_H diff --git a/UnitTests/cppunit/include/cppunit/plugin/PlugInParameters.h b/UnitTests/cppunit/include/cppunit/plugin/PlugInParameters.h new file mode 100644 index 0000000..c67d0f1 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/plugin/PlugInParameters.h @@ -0,0 +1,36 @@ +#ifndef CPPUNIT_PLUGIN_PARAMETERS +#define CPPUNIT_PLUGIN_PARAMETERS + +#include + +#if !defined(CPPUNIT_NO_TESTPLUGIN) + +#include +#include + +CPPUNIT_NS_BEGIN + +/*! \brief Test plug-ins parameters. + */ +class CPPUNIT_API PlugInParameters +{ +public: + /// Constructs plug-in parameters from the specified command-line. + PlugInParameters( const std::string &commandLine = "" ); + + virtual ~PlugInParameters(); + + /// Returns the command line that was passed on construction. + std::string getCommandLine() const; + +private: + std::string m_commandLine; +}; + + +CPPUNIT_NS_END + +#endif // !defined(CPPUNIT_NO_TESTPLUGIN) + + +#endif // CPPUNIT_PLUGIN_PARAMETERS diff --git a/UnitTests/cppunit/include/cppunit/plugin/TestPlugIn.h b/UnitTests/cppunit/include/cppunit/plugin/TestPlugIn.h new file mode 100644 index 0000000..bd0565c --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/plugin/TestPlugIn.h @@ -0,0 +1,200 @@ +#ifndef CPPUNIT_PLUGIN_TESTPLUGIN +#define CPPUNIT_PLUGIN_TESTPLUGIN + +#include + +#if !defined(CPPUNIT_NO_TESTPLUGIN) + +#include + +CPPUNIT_NS_BEGIN + + +class Test; +class TestFactoryRegistry; +class TestResult; +class XmlOutputter; + +CPPUNIT_NS_END + +/*! \file + */ + + +/*! \brief Test plug-in interface. + * \ingroup WritingTestPlugIn + * + * This class define the interface implemented by test plug-in. A pointer to that + * interface is returned by the function exported by the test plug-in. + * + * Plug-in are loaded/unloaded by PlugInManager. When a plug-in is loaded, + * initialize() is called. Before unloading the plug-in, the PlugInManager + * call uninitialize(). + * + * addListener() and removeListener() are called respectively before and after + * the test run. + * + * addXmlOutputterHooks() and removeXmlOutputterHooks() are called respectively + * before and after writing the XML output using a XmlOutputter. + * + * \see CPPUNIT_PLUGIN_IMPLEMENT, CPPUNIT_PLUGIN_EXPORTED_FUNCTION_IMPL + * \see CppUnit::TestPlugInDefaultImpl, CppUnit::XmlOutputter. + */ +struct CPPUNIT_API CppUnitTestPlugIn +{ + /*! \brief Called just after loading the dynamic library. + * + * Override this method to add additional suite to the registry, though this + * is preferably done using the macros (CPPUNIT_TEST_SUITE_REGISTRATION...). + * If you are creating a custom listener to extends the plug-in runner, + * you can use this to configure the listener using the \a parameters. + * + * You could also use the parameters to specify some global parameter, such + * as test datas location, database name... + * + * N.B.: Parameters interface is not define yet, and the plug-in runner does + * not yet support plug-in parameter. + */ + virtual void initialize( CPPUNIT_NS::TestFactoryRegistry *registry, + const CPPUNIT_NS::PlugInParameters ¶meters ) =0; + + /*! \brief Gives a chance to the plug-in to register TestListener. + * + * Override this method to add a TestListener for the test run. This is useful + * if you are writing a custom TestListener, but also if you need to + * setUp some global resource: listen to TestListener::startTestRun(), + * and TestListener::endTestRun(). + */ + virtual void addListener( CPPUNIT_NS::TestResult *eventManager ) =0; + + /*! \brief Gives a chance to the plug-in to remove its registered TestListener. + * + * Override this method to remove a TestListener that has been added. + */ + virtual void removeListener( CPPUNIT_NS::TestResult *eventManager ) =0; + + /*! \brief Provides a way for the plug-in to register some XmlOutputterHook. + */ + virtual void addXmlOutputterHooks( CPPUNIT_NS::XmlOutputter *outputter ) =0; + + /*! \brief Called when the XmlOutputter is destroyed. + * + * Can be used to free some resources allocated by addXmlOutputterHooks(). + */ + virtual void removeXmlOutputterHooks() = 0; + + /*! \brief Called just before unloading the dynamic library. + * + * Override this method to unregister test factory added in initialize(). + * This is necessary to keep the TestFactoryRegistry 'clean'. When + * the plug-in is unloaded from memory, the TestFactoryRegistry will hold + * reference on test that are no longer available if they are not + * unregistered. + */ + virtual void uninitialize( CPPUNIT_NS::TestFactoryRegistry *registry ) =0; + + virtual ~CppUnitTestPlugIn() {} +}; + + + +/*! \brief Name of the function exported by a test plug-in. + * \ingroup WritingTestPlugIn + * + * The signature of the exported function is: + * \code + * CppUnitTestPlugIn *CPPUNIT_PLUGIN_EXPORTED_NAME(void); + * \endcode + */ +#define CPPUNIT_PLUGIN_EXPORTED_NAME cppunitTestPlugIn + +/*! \brief Type of the function exported by a plug-in. + * \ingroup WritingTestPlugIn + */ +typedef CppUnitTestPlugIn *(*TestPlugInSignature)(); + + +/*! \brief Implements the function exported by the test plug-in + * \ingroup WritingTestPlugIn + */ +#define CPPUNIT_PLUGIN_EXPORTED_FUNCTION_IMPL( TestPlugInInterfaceType ) \ + CPPUNIT_PLUGIN_EXPORT CppUnitTestPlugIn *CPPUNIT_PLUGIN_EXPORTED_NAME(void) \ + { \ + static TestPlugInInterfaceType plugIn; \ + return &plugIn; \ + } \ + typedef char __CppUnitPlugInExportFunctionDummyTypeDef // dummy typedef so it can end with ';' + + +// Note: This include should remain after definition of CppUnitTestPlugIn +#include + + +/*! \def CPPUNIT_PLUGIN_IMPLEMENT_MAIN() + * \brief Implements the 'main' function for the plug-in. + * + * This macros implements the main() function for dynamic library. + * For example, WIN32 requires a DllMain function, while some Unix + * requires a main() function. This macros takes care of the implementation. + */ + +// Win32 +#if defined(CPPUNIT_HAVE_WIN32_DLL_LOADER) +#if !defined(APIENTRY) +#define WIN32_LEAN_AND_MEAN +#define NOGDI +#define NOUSER +#define NOKERNEL +#define NOSOUND +#define NOMINMAX +#define BLENDFUNCTION void // for mingw & gcc +#include +#endif +#define CPPUNIT_PLUGIN_IMPLEMENT_MAIN() \ + BOOL APIENTRY DllMain( HANDLE hModule, \ + DWORD ul_reason_for_call, \ + LPVOID lpReserved ) \ + { \ + return TRUE; \ + } \ + typedef char __CppUnitPlugInImplementMainDummyTypeDef + +// Unix +#elif defined(CPPUNIT_HAVE_UNIX_DLL_LOADER) || defined(CPPUNIT_HAVE_UNIX_SHL_LOADER) +#define CPPUNIT_PLUGIN_IMPLEMENT_MAIN() \ + int main( int argc, char *argv[] ) \ + { \ + return 0; \ + } \ + typedef char __CppUnitPlugInImplementMainDummyTypeDef + + +// Other +#else // other platforms don't require anything specifics +#endif + + + +/*! \brief Implements and exports the test plug-in interface. + * \ingroup WritingTestPlugIn + * + * This macro exports the test plug-in function using the subclass, + * and implements the 'main' function for the plug-in using + * CPPUNIT_PLUGIN_IMPLEMENT_MAIN(). + * + * When using this macro, CppUnit must be linked as a DLL (shared library). + * Otherwise, tests registered to the TestFactoryRegistry in the DLL will + * not be visible to the DllPlugInTester. + * + * \see CppUnitTestPlugIn + * \see CPPUNIT_PLUGIN_EXPORTED_FUNCTION_IMPL(), CPPUNIT_PLUGIN_IMPLEMENT_MAIN(). + */ +#define CPPUNIT_PLUGIN_IMPLEMENT() \ + CPPUNIT_PLUGIN_EXPORTED_FUNCTION_IMPL( CPPUNIT_NS::TestPlugInDefaultImpl ); \ + CPPUNIT_PLUGIN_IMPLEMENT_MAIN() + + +#endif // !defined(CPPUNIT_NO_TESTPLUGIN) + + +#endif // CPPUNIT_PLUGIN_TESTPLUGIN diff --git a/UnitTests/cppunit/include/cppunit/plugin/TestPlugInDefaultImpl.h b/UnitTests/cppunit/include/cppunit/plugin/TestPlugInDefaultImpl.h new file mode 100644 index 0000000..8040b79 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/plugin/TestPlugInDefaultImpl.h @@ -0,0 +1,61 @@ +#ifndef CPPUNIT_PLUGIN_TESTPLUGINADAPTER +#define CPPUNIT_PLUGIN_TESTPLUGINADAPTER + +#include + +#if !defined(CPPUNIT_NO_TESTPLUGIN) + +#include + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( push ) +#pragma warning( disable: 4251 4660 ) // X needs to have dll-interface to be used by clients of class Z +#endif + +CPPUNIT_NS_BEGIN + + +class TestSuite; + + +/*! \brief Default implementation of test plug-in interface. + * \ingroup WritingTestPlugIn + * + * Override getSuiteName() to specify the suite name. Default is "All Tests". + * + * CppUnitTestPlugIn::getTestSuite() returns a suite that contains + * all the test registered to the default test factory registry + * ( TestFactoryRegistry::getRegistry() ). + * + */ +class CPPUNIT_API TestPlugInDefaultImpl : public CppUnitTestPlugIn +{ +public: + TestPlugInDefaultImpl(); + + virtual ~TestPlugInDefaultImpl(); + + void initialize( TestFactoryRegistry *registry, + const PlugInParameters ¶meters ); + + void addListener( TestResult *eventManager ); + + void removeListener( TestResult *eventManager ); + + void addXmlOutputterHooks( XmlOutputter *outputter ); + + void removeXmlOutputterHooks(); + + void uninitialize( TestFactoryRegistry *registry ); +}; + + +CPPUNIT_NS_END + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( pop ) +#endif + +#endif // !defined(CPPUNIT_NO_TESTPLUGIN) + +#endif // CPPUNIT_PLUGIN_TESTPLUGINADAPTER diff --git a/UnitTests/cppunit/include/cppunit/portability/CppUnitDeque.h b/UnitTests/cppunit/include/cppunit/portability/CppUnitDeque.h new file mode 100644 index 0000000..bbab21f --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/portability/CppUnitDeque.h @@ -0,0 +1,25 @@ +#ifndef CPPUNIT_PORTABILITY_CPPUNITDEQUE_H +#define CPPUNIT_PORTABILITY_CPPUNITDEQUE_H + +// The technic used is similar to the wrapper of STLPort. + +#include +#include + + +#if CPPUNIT_STD_NEED_ALLOCATOR + +template +class CppUnitDeque : public std::deque +{ +public: +}; + +#else // CPPUNIT_STD_NEED_ALLOCATOR + +#define CppUnitDeque std::deque + +#endif + +#endif // CPPUNIT_PORTABILITY_CPPUNITDEQUE_H + diff --git a/UnitTests/cppunit/include/cppunit/portability/CppUnitMap.h b/UnitTests/cppunit/include/cppunit/portability/CppUnitMap.h new file mode 100644 index 0000000..0cdc723 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/portability/CppUnitMap.h @@ -0,0 +1,29 @@ +#ifndef CPPUNIT_PORTABILITY_CPPUNITMAP_H +#define CPPUNIT_PORTABILITY_CPPUNITMAP_H + +// The technic used is similar to the wrapper of STLPort. + +#include +#include +#include + + +#if CPPUNIT_STD_NEED_ALLOCATOR + +template +class CppUnitMap : public std::map + ,CPPUNIT_STD_ALLOCATOR> +{ +public: +}; + +#else // CPPUNIT_STD_NEED_ALLOCATOR + +#define CppUnitMap std::map + +#endif + +#endif // CPPUNIT_PORTABILITY_CPPUNITMAP_H + diff --git a/UnitTests/cppunit/include/cppunit/portability/CppUnitSet.h b/UnitTests/cppunit/include/cppunit/portability/CppUnitSet.h new file mode 100644 index 0000000..18b8662 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/portability/CppUnitSet.h @@ -0,0 +1,28 @@ +#ifndef CPPUNIT_PORTABILITY_CPPUNITSET_H +#define CPPUNIT_PORTABILITY_CPPUNITSET_H + +// The technic used is similar to the wrapper of STLPort. + +#include +#include +#include + + +#if CPPUNIT_STD_NEED_ALLOCATOR + +template +class CppUnitSet : public std::set + ,CPPUNIT_STD_ALLOCATOR> +{ +public: +}; + +#else // CPPUNIT_STD_NEED_ALLOCATOR + +#define CppUnitSet std::set + +#endif + +#endif // CPPUNIT_PORTABILITY_CPPUNITSET_H + diff --git a/UnitTests/cppunit/include/cppunit/portability/CppUnitStack.h b/UnitTests/cppunit/include/cppunit/portability/CppUnitStack.h new file mode 100644 index 0000000..bc7785b --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/portability/CppUnitStack.h @@ -0,0 +1,26 @@ +#ifndef CPPUNIT_PORTABILITY_CPPUNITSTACK_H +#define CPPUNIT_PORTABILITY_CPPUNITSTACK_H + +// The technic used is similar to the wrapper of STLPort. + +#include +#include +#include + + +#if CPPUNIT_STD_NEED_ALLOCATOR + +template +class CppUnitStack : public std::stack > +{ +public: +}; + +#else // CPPUNIT_STD_NEED_ALLOCATOR + +#define CppUnitStack std::stack + +#endif + +#endif // CPPUNIT_PORTABILITY_CPPUNITSTACK_H \ No newline at end of file diff --git a/UnitTests/cppunit/include/cppunit/portability/CppUnitVector.h b/UnitTests/cppunit/include/cppunit/portability/CppUnitVector.h new file mode 100644 index 0000000..6666a63 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/portability/CppUnitVector.h @@ -0,0 +1,25 @@ +#ifndef CPPUNIT_PORTABILITY_CPPUNITVECTOR_H +#define CPPUNIT_PORTABILITY_CPPUNITVECTOR_H + +// The technic used is similar to the wrapper of STLPort. + +#include +#include + + +#if CPPUNIT_STD_NEED_ALLOCATOR + +template +class CppUnitVector : public std::vector +{ +public: +}; + +#else // CPPUNIT_STD_NEED_ALLOCATOR + +#define CppUnitVector std::vector + +#endif + +#endif // CPPUNIT_PORTABILITY_CPPUNITVECTOR_H + diff --git a/UnitTests/cppunit/include/cppunit/portability/FloatingPoint.h b/UnitTests/cppunit/include/cppunit/portability/FloatingPoint.h new file mode 100644 index 0000000..e8c91b3 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/portability/FloatingPoint.h @@ -0,0 +1,54 @@ +#ifndef CPPUNIT_PORTABILITY_FLOATINGPOINT_H_INCLUDED +#define CPPUNIT_PORTABILITY_FLOATINGPOINT_H_INCLUDED + +#include +#include + +CPPUNIT_NS_BEGIN + +/// \brief Tests if a floating-point is a NaN. +// According to IEEE-754 floating point standard, +// (see e.g. page 8 of +// http://www.cs.berkeley.edu/~wkahan/ieee754status/ieee754.ps) +// all comparisons with NaN are false except "x != x", which is true. +// +// At least Microsoft Visual Studio 6 is known not to implement this test correctly. +// It emits the following code to test equality: +// fcomp qword ptr [nan] +// fnstsw ax // copie fp (floating-point) status register to ax +// test ah,40h // test bit 14 of ax (0x4000) => C3 of fp status register +// According to the following documentation on the x86 floating point status register, +// the C2 bit should be tested to test for NaN value. +// http://webster.cs.ucr.edu/AoA/Windows/HTML/RealArithmetic.html#1000117 +// In Microsoft Visual Studio 2003 & 2005, the test is implemented with: +// test ah,44h // Visual Studio 2005 test both C2 & C3... +// +// To work around this, a NaN is assumed to be detected if no strict ordering is found. +inline bool floatingPointIsUnordered( double x ) +{ + // x != x will detect a NaN on conformant platform + // (2.0 < x && x < 1.0) will detect a NaN on non conformant platform: + // => no ordering can be found for x. + return (x != x) || (2.0 < x && x < 1.0); +} + + +/// \brief Tests if a floating-point is finite. +/// @return \c true if x is neither a NaN, nor +inf, nor -inf, \c false otherwise. +inline int floatingPointIsFinite( double x ) +{ +#if defined(CPPUNIT_HAVE_ISFINITE) + return isfinite( x ); +#elif defined(CPPUNIT_HAVE_FINITE) + return finite( x ); +#elif defined(CPPUNIT_HAVE__FINITE) + return _finite(x); +#else + double testInf = x * 0.0; // Produce 0.0 if x is finite, a NaN otherwise. + return testInf == 0.0 && !floatingPointIsUnordered(testInf); +#endif +} + +CPPUNIT_NS_END + +#endif // CPPUNIT_PORTABILITY_FLOATINGPOINT_H_INCLUDED diff --git a/UnitTests/cppunit/include/cppunit/portability/Stream.h b/UnitTests/cppunit/include/cppunit/portability/Stream.h new file mode 100644 index 0000000..e9beb8c --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/portability/Stream.h @@ -0,0 +1,347 @@ +#ifndef CPPUNIT_PORTABILITY_STREAM_H_INCLUDED +#define CPPUNIT_PORTABILITY_STREAM_H_INCLUDED + +// This module define: +// Type CppUT::Stream (either std::stream or a custom type) +// Type CppUT::OStringStream (eitjer std::ostringstream, older alternate or a custom type) +// Functions stdCOut() & stdCErr() which returns a reference on cout & cerr stream (or our +// custom stream). + +#include + + +#if defined( CPPUNIT_NO_STREAM ) + +#include +#include +#include + +CPPUNIT_NS_BEGIN + +class StreamBuffer +{ +public: + virtual ~StreamBuffer() {} + + virtual void write( const char *text, unsigned int length ) = 0; + + virtual void flush() {} +}; + + +class StringStreamBuffer : public StreamBuffer +{ +public: + std::string str() const + { + return str_; + } + +public: // overridden from StreamBuffer + void write( const char *text, unsigned int length ) + { + str_.append( text, length ); + } + +private: + std::string str_; +}; + + +class FileStreamBuffer : public StreamBuffer +{ +public: + FileStreamBuffer( FILE *file ) + : file_( file ) + { + } + + FILE *file() const + { + return file_; + } + +public: // overridden from StreamBuffer + void write( const char *text, unsigned int length ) + { + if ( file_ ) + fwrite( text, sizeof(char), length, file_ ); + } + + void flush() + { + if ( file_ ) + fflush( file_ ); + } + +private: + FILE *file_; +}; + + +class OStream +{ +public: + OStream() + : buffer_( 0 ) + { + } + + OStream( StreamBuffer *buffer ) + : buffer_( buffer ) + { + } + + virtual ~OStream() + { + flush(); + } + + OStream &flush() + { + if ( buffer_ ) + buffer_->flush(); + return *this; + } + + void setBuffer( StreamBuffer *buffer ) + { + buffer_ = buffer; + } + + OStream &write( const char *text, unsigned int length ) + { + if ( buffer_ ) + buffer_->write( text, length ); + return *this; + } + + OStream &write( const char *text ) + { + return write( text, strlen(text) ); + } + + OStream &operator <<( bool v ) + { + const char *out = v ? "true" : "false"; + return write( out ); + } + + OStream &operator <<( short v ) + { + char buffer[64]; + sprintf( buffer, "%hd", v ); + return write( buffer ); + } + + OStream &operator <<( unsigned short v ) + { + char buffer[64]; + sprintf( buffer, "%hu", v ); + return write( buffer ); + } + + OStream &operator <<( int v ) + { + char buffer[64]; + sprintf( buffer, "%d", v ); + return write( buffer ); + } + + OStream &operator <<( unsigned int v ) + { + char buffer[64]; + sprintf( buffer, "%u", v ); + return write( buffer ); + } + + OStream &operator <<( long v ) + { + char buffer[64]; + sprintf( buffer, "%ld", v ); + return write( buffer ); + } + + OStream &operator <<( unsigned long v ) + { + char buffer[64]; + sprintf( buffer, "%lu", v ); + return write( buffer ); + } + + OStream &operator <<( float v ) + { + char buffer[128]; + sprintf( buffer, "%.16g", double(v) ); + return write( buffer ); + } + + OStream &operator <<( double v ) + { + char buffer[128]; + sprintf( buffer, "%.16g", v ); + return write( buffer ); + } + + OStream &operator <<( long double v ) + { + char buffer[128]; + sprintf( buffer, "%.16g", double(v) ); + return write( buffer ); + } + + OStream &operator <<( const void *v ) + { + char buffer[64]; + sprintf( buffer, "%p", v ); + return write( buffer ); + } + + OStream &operator <<( const char *v ) + { + return write( v ? v : "NULL" ); + } + + OStream &operator <<( char c ) + { + char buffer[16]; + sprintf( buffer, "%c", c ); + return write( buffer ); + } + + OStream &operator <<( const std::string &s ) + { + return write( s.c_str(), s.length() ); + } + +private: + StreamBuffer *buffer_; +}; + + +class OStringStream : public OStream +{ +public: + OStringStream() + : OStream( &buffer_ ) + { + } + + std::string str() const + { + return buffer_.str(); + } + +private: + StringStreamBuffer buffer_; +}; + + +class OFileStream : public OStream +{ +public: + OFileStream( FILE *file ) + : OStream( &buffer_ ) + , buffer_( file ) + , ownFile_( false ) + { + } + + OFileStream( const char *path ) + : OStream( &buffer_ ) + , buffer_( fopen( path, "wt" ) ) + , ownFile_( true ) + { + } + + virtual ~OFileStream() + { + if ( ownFile_ && buffer_.file() ) + fclose( buffer_.file() ); + } + +private: + FileStreamBuffer buffer_; + bool ownFile_; +}; + +inline OStream &stdCOut() +{ + static OFileStream stream( stdout ); + return stream; +} + +inline OStream &stdCErr() +{ + static OFileStream stream( stderr ); + return stream; +} + +CPPUNIT_NS_END + +#elif CPPUNIT_HAVE_SSTREAM // #if defined( CPPUNIT_NO_STREAM ) +# include +# include + + CPPUNIT_NS_BEGIN + typedef std::ostringstream OStringStream; // The standard C++ way + typedef std::ofstream OFileStream; + CPPUNIT_NS_END + + +#elif CPPUNIT_HAVE_CLASS_STRSTREAM +# include +# if CPPUNIT_HAVE_STRSTREAM +# include +# else // CPPUNIT_HAVE_STRSTREAM +# include +# endif // CPPUNIT_HAVE_CLASS_STRSTREAM + + CPPUNIT_NS_BEGIN + + class OStringStream : public std::ostrstream + { + public: + std::string str() + { +// (*this) << '\0'; +// std::string msg(std::ostrstream::str()); +// std::ostrstream::freeze(false); +// return msg; +// Alternative implementation that don't rely on freeze which is not +// available on some platforms: + return std::string( std::ostrstream::str(), pcount() ); + } + }; + + CPPUNIT_NS_END +#else // CPPUNIT_HAVE_CLASS_STRSTREAM +# error Cannot define CppUnit::OStringStream. +#endif // #if defined( CPPUNIT_NO_STREAM ) + + + +#if !defined( CPPUNIT_NO_STREAM ) + +#include + + CPPUNIT_NS_BEGIN + + typedef std::ostream OStream; + + inline OStream &stdCOut() + { + return std::cout; + } + + inline OStream &stdCErr() + { + return std::cerr; + } + + CPPUNIT_NS_END + +#endif // #if !defined( CPPUNIT_NO_STREAM ) + +#endif // CPPUNIT_PORTABILITY_STREAM_H_INCLUDED + diff --git a/UnitTests/cppunit/include/cppunit/tools/Algorithm.h b/UnitTests/cppunit/include/cppunit/tools/Algorithm.h new file mode 100644 index 0000000..e5746a2 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/tools/Algorithm.h @@ -0,0 +1,23 @@ +#ifndef CPPUNIT_TOOLS_ALGORITHM_H_INCLUDED +#define CPPUNIT_TOOLS_ALGORITHM_H_INCLUDED + +#include + +CPPUNIT_NS_BEGIN + +template +void +removeFromSequence( SequenceType &sequence, + const ValueType &valueToRemove ) +{ + for ( unsigned int index =0; index < sequence.size(); ++index ) + { + if ( sequence[ index ] == valueToRemove ) + sequence.erase( sequence.begin() + index ); + } +} + +CPPUNIT_NS_END + + +#endif // CPPUNIT_TOOLS_ALGORITHM_H_INCLUDED diff --git a/UnitTests/cppunit/include/cppunit/tools/StringTools.h b/UnitTests/cppunit/include/cppunit/tools/StringTools.h new file mode 100644 index 0000000..7a6b6d7 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/tools/StringTools.h @@ -0,0 +1,34 @@ +#ifndef CPPUNIT_TOOLS_STRINGTOOLS_H +#define CPPUNIT_TOOLS_STRINGTOOLS_H + +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +/*! \brief Tool functions to manipulate string. + */ +struct StringTools +{ + + typedef CppUnitVector Strings; + + static std::string CPPUNIT_API toString( int value ); + + static std::string CPPUNIT_API toString( double value ); + + static Strings CPPUNIT_API split( const std::string &text, + char separator ); + + static std::string CPPUNIT_API wrap( const std::string &text, + int wrapColumn = CPPUNIT_WRAP_COLUMN ); + +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_TOOLS_STRINGTOOLS_H diff --git a/UnitTests/cppunit/include/cppunit/tools/XmlDocument.h b/UnitTests/cppunit/include/cppunit/tools/XmlDocument.h new file mode 100644 index 0000000..4ee7325 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/tools/XmlDocument.h @@ -0,0 +1,86 @@ +#ifndef CPPUNIT_TOOLS_XMLDOCUMENT_H +#define CPPUNIT_TOOLS_XMLDOCUMENT_H + +#include + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( push ) +#pragma warning( disable: 4251 ) // X needs to have dll-interface to be used by clients of class Z +#endif + +#include + + +CPPUNIT_NS_BEGIN + + +class XmlElement; + + +/*! \brief A XML Document. + * + * A XmlDocument represents a XML file. It holds a pointer on the root XmlElement + * of the document. It also holds the encoding and style sheet used. + * + * By default, the XML document is stand-alone and tagged with enconding "ISO-8859-1". + */ +class CPPUNIT_API XmlDocument +{ +public: + /*! \brief Constructs a XmlDocument object. + * \param encoding Encoding used in the XML file (default is Latin-1, ISO-8859-1 ). + * \param styleSheet Name of the XSL style sheet file used. If empty then no + * style sheet will be specified in the output. + */ + XmlDocument( const std::string &encoding = "", + const std::string &styleSheet = "" ); + + /// Destructor. + virtual ~XmlDocument(); + + std::string encoding() const; + void setEncoding( const std::string &encoding = "" ); + + std::string styleSheet() const; + void setStyleSheet( const std::string &styleSheet = "" ); + + bool standalone() const; + + /*! \brief set the output document as standalone or not. + * + * For the output document, specify wether it's a standalone XML + * document, or not. + * + * \param standalone if true, the output will be specified as standalone. + * if false, it will be not. + */ + void setStandalone( bool standalone ); + + void setRootElement( XmlElement *rootElement ); + XmlElement &rootElement() const; + + std::string toString() const; + +private: + /// Prevents the use of the copy constructor. + XmlDocument( const XmlDocument © ); + + /// Prevents the use of the copy operator. + void operator =( const XmlDocument © ); + +protected: + std::string m_encoding; + std::string m_styleSheet; + XmlElement *m_rootElement; + bool m_standalone; +}; + + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( pop ) +#endif + + +CPPUNIT_NS_END + +#endif // CPPUNIT_TOOLS_XMLDOCUMENT_H diff --git a/UnitTests/cppunit/include/cppunit/tools/XmlElement.h b/UnitTests/cppunit/include/cppunit/tools/XmlElement.h new file mode 100644 index 0000000..0b36bd2 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/tools/XmlElement.h @@ -0,0 +1,149 @@ +#ifndef CPPUNIT_TOOLS_XMLELEMENT_H +#define CPPUNIT_TOOLS_XMLELEMENT_H + +#include + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( push ) +#pragma warning( disable: 4251 ) // X needs to have dll-interface to be used by clients of class Z +#endif + +#include +#include + + +CPPUNIT_NS_BEGIN + + +class XmlElement; + +#if CPPUNIT_NEED_DLL_DECL +// template class CPPUNIT_API std::deque; +#endif + + +/*! \brief A XML Element. + * + * A XML element has: + * - a name, specified on construction, + * - a content, specified on construction (may be empty), + * - zero or more attributes, added with addAttribute(), + * - zero or more child elements, added with addElement(). + */ +class CPPUNIT_API XmlElement +{ +public: + /*! \brief Constructs an element with the specified name and string content. + * \param elementName Name of the element. Must not be empty. + * \param content Content of the element. + */ + XmlElement( std::string elementName, + std::string content ="" ); + + /*! \brief Constructs an element with the specified name and numeric content. + * \param elementName Name of the element. Must not be empty. + * \param numericContent Content of the element. + */ + XmlElement( std::string elementName, + int numericContent ); + + /*! \brief Destructs the element and its child elements. + */ + virtual ~XmlElement(); + + /*! \brief Returns the name of the element. + * \return Name of the element. + */ + std::string name() const; + + /*! \brief Returns the content of the element. + * \return Content of the element. + */ + std::string content() const; + + /*! \brief Sets the name of the element. + * \param name New name for the element. + */ + void setName( const std::string &name ); + + /*! \brief Sets the content of the element. + * \param content New content for the element. + */ + void setContent( const std::string &content ); + + /*! \overload void setContent( const std::string &content ) + */ + void setContent( int numericContent ); + + /*! \brief Adds an attribute with the specified string value. + * \param attributeName Name of the attribute. Must not be an empty. + * \param value Value of the attribute. + */ + void addAttribute( std::string attributeName, + std::string value ); + + /*! \brief Adds an attribute with the specified numeric value. + * \param attributeName Name of the attribute. Must not be empty. + * \param numericValue Numeric value of the attribute. + */ + void addAttribute( std::string attributeName, + int numericValue ); + + /*! \brief Adds a child element to the element. + * \param element Child element to add. Must not be \c NULL. + */ + void addElement( XmlElement *element ); + + /*! \brief Returns the number of child elements. + * \return Number of child elements (element added with addElement()). + */ + int elementCount() const; + + /*! \brief Returns the child element at the specified index. + * \param index Zero based index of the element to return. + * \returns Element at the specified index. Never \c NULL. + * \exception std::invalid_argument if \a index < 0 or index >= elementCount(). + */ + XmlElement *elementAt( int index ) const; + + /*! \brief Returns the first child element with the specified name. + * \param name Name of the child element to return. + * \return First child element found which is named \a name. + * \exception std::invalid_argument if there is no child element with the specified + * name. + */ + XmlElement *elementFor( const std::string &name ) const; + + /*! \brief Returns a XML string that represents the element. + * \param indent String of spaces representing the amount of 'indent'. + * \return XML string that represents the element, its attributes and its + * child elements. + */ + std::string toString( const std::string &indent = "" ) const; + +private: + typedef std::pair Attribute; + + std::string attributesAsString() const; + std::string escape( std::string value ) const; + +private: + std::string m_name; + std::string m_content; + + typedef CppUnitDeque Attributes; + Attributes m_attributes; + + typedef CppUnitDeque Elements; + Elements m_elements; +}; + + +CPPUNIT_NS_END + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( pop ) +#endif + + +#endif // CPPUNIT_TOOLS_XMLELEMENT_H diff --git a/UnitTests/cppunit/include/cppunit/ui/text/TestRunner.h b/UnitTests/cppunit/include/cppunit/ui/text/TestRunner.h new file mode 100644 index 0000000..023eb83 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/ui/text/TestRunner.h @@ -0,0 +1,24 @@ +#ifndef CPPUNIT_UI_TEXT_TESTRUNNER_H +#define CPPUNIT_UI_TEXT_TESTRUNNER_H + +#include + + +#if defined(CPPUNIT_HAVE_NAMESPACES) + +CPPUNIT_NS_BEGIN +namespace TextUi +{ + + /*! Text TestRunner (DEPRECATED). + * \deprecated Use TextTestRunner instead. + */ + typedef TextTestRunner TestRunner; + +} +CPPUNIT_NS_END + +#endif // defined(CPPUNIT_HAVE_NAMESPACES) + + +#endif // CPPUNIT_UI_TEXT_TESTRUNNER_H diff --git a/UnitTests/cppunit/include/cppunit/ui/text/TextTestRunner.h b/UnitTests/cppunit/include/cppunit/ui/text/TextTestRunner.h new file mode 100644 index 0000000..86da4d4 --- /dev/null +++ b/UnitTests/cppunit/include/cppunit/ui/text/TextTestRunner.h @@ -0,0 +1,97 @@ +#ifndef CPPUNIT_UI_TEXT_TEXTTESTRUNNER_H +#define CPPUNIT_UI_TEXT_TEXTTESTRUNNER_H + + +#include +#include +#include + +CPPUNIT_NS_BEGIN + + +class Outputter; +class Test; +class TestSuite; +class TextOutputter; +class TestResult; +class TestResultCollector; + + + +/*! + * \brief A text mode test runner. + * \ingroup WritingTestResult + * \ingroup ExecutingTest + * + * The test runner manage the life cycle of the added tests. + * + * The test runner can run only one of the added tests or all the tests. + * + * TestRunner prints out a trace as the tests are executed followed by a + * summary at the end. The trace and summary print are optional. + * + * Here is an example of use: + * + * \code + * CppUnit::TextTestRunner runner; + * runner.addTest( ExampleTestCase::suite() ); + * runner.run( "", true ); // Run all tests and wait + * \endcode + * + * The trace is printed using a TextTestProgressListener. The summary is printed + * using a TextOutputter. + * + * You can specify an alternate Outputter at construction + * or later with setOutputter(). + * + * After construction, you can register additional TestListener to eventManager(), + * for a custom progress trace, for example. + * + * \code + * CppUnit::TextTestRunner runner; + * runner.addTest( ExampleTestCase::suite() ); + * runner.setOutputter( CppUnit::CompilerOutputter::defaultOutputter( + * &runner.result(), + * std::cerr ) ); + * MyCustomProgressTestListener progress; + * runner.eventManager().addListener( &progress ); + * runner.run( "", true ); // Run all tests and wait + * \endcode + * + * \see CompilerOutputter, XmlOutputter, TextOutputter. + */ +class CPPUNIT_API TextTestRunner : public CPPUNIT_NS::TestRunner +{ +public: + TextTestRunner( Outputter *outputter =NULL ); + + virtual ~TextTestRunner(); + + bool run( std::string testPath ="", + bool doWait = false, + bool doPrintResult = true, + bool doPrintProgress = true ); + + void setOutputter( Outputter *outputter ); + + TestResultCollector &result() const; + + TestResult &eventManager() const; + +public: // overridden from TestRunner (to avoid hidden virtual function warning) + virtual void run( TestResult &controller, + const std::string &testPath = "" ); + +protected: + virtual void wait( bool doWait ); + virtual void printResult( bool doPrintResult ); + + TestResultCollector *m_result; + TestResult *m_eventManager; + Outputter *m_outputter; +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_UI_TEXT_TEXTTESTRUNNER_H diff --git a/UnitTests/cppunit/src/cppunit/AdditionalMessage.cpp b/UnitTests/cppunit/src/cppunit/AdditionalMessage.cpp new file mode 100644 index 0000000..9f3da13 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/AdditionalMessage.cpp @@ -0,0 +1,41 @@ +#include + + +CPPUNIT_NS_BEGIN + + +AdditionalMessage::AdditionalMessage() +{ +} + + +AdditionalMessage::AdditionalMessage( const std::string &detail1 ) +{ + if ( !detail1.empty() ) + addDetail( detail1 ); +} + + +AdditionalMessage::AdditionalMessage( const char *detail1 ) +{ + if ( detail1 && !std::string( detail1 ).empty() ) + addDetail( std::string(detail1) ); +} + + +AdditionalMessage::AdditionalMessage( const Message &other ) + : SuperClass( other ) +{ +} + + +AdditionalMessage & +AdditionalMessage::operator =( const Message &other ) +{ + SuperClass::operator =( other ); + + return *this; +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/Asserter.cpp b/UnitTests/cppunit/src/cppunit/Asserter.cpp new file mode 100644 index 0000000..a9cf95c --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/Asserter.cpp @@ -0,0 +1,101 @@ +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +void +Asserter::fail( std::string message, + const SourceLine &sourceLine ) +{ + fail( Message( "assertion failed", message ), sourceLine ); +} + + +void +Asserter::fail( const Message &message, + const SourceLine &sourceLine ) +{ + throw Exception( message, sourceLine ); +} + + +void +Asserter::failIf( bool shouldFail, + const Message &message, + const SourceLine &sourceLine ) +{ + if ( shouldFail ) + fail( message, sourceLine ); +} + + +void +Asserter::failIf( bool shouldFail, + std::string message, + const SourceLine &sourceLine ) +{ + failIf( shouldFail, Message( "assertion failed", message ), sourceLine ); +} + + +std::string +Asserter::makeExpected( const std::string &expectedValue ) +{ + return "Expected: " + expectedValue; +} + + +std::string +Asserter::makeActual( const std::string &actualValue ) +{ + return "Actual : " + actualValue; +} + + +Message +Asserter::makeNotEqualMessage( const std::string &expectedValue, + const std::string &actualValue, + const AdditionalMessage &additionalMessage, + const std::string &shortDescription ) +{ + Message message( shortDescription, + makeExpected( expectedValue ), + makeActual( actualValue ) ); + message.addDetail( additionalMessage ); + + return message; +} + + +void +Asserter::failNotEqual( std::string expected, + std::string actual, + const SourceLine &sourceLine, + const AdditionalMessage &additionalMessage, + std::string shortDescription ) +{ + fail( makeNotEqualMessage( expected, + actual, + additionalMessage, + shortDescription ), + sourceLine ); +} + + +void +Asserter::failNotEqualIf( bool shouldFail, + std::string expected, + std::string actual, + const SourceLine &sourceLine, + const AdditionalMessage &additionalMessage, + std::string shortDescription ) +{ + if ( shouldFail ) + failNotEqual( expected, actual, sourceLine, additionalMessage, shortDescription ); +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/BeOsDynamicLibraryManager.cpp b/UnitTests/cppunit/src/cppunit/BeOsDynamicLibraryManager.cpp new file mode 100644 index 0000000..b8568be --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/BeOsDynamicLibraryManager.cpp @@ -0,0 +1,49 @@ +#include + +#if defined(CPPUNIT_HAVE_BEOS_DLL_LOADER) +#include + +#include + + +CPPUNIT_NS_BEGIN + + +DynamicLibraryManager::LibraryHandle +DynamicLibraryManager::doLoadLibrary( const std::string &libraryName ) +{ + return (LibraryHandle)::load_add_on( libraryName.c_str() ); +} + + +void +DynamicLibraryManager::doReleaseLibrary() +{ + ::unload_add_on( (image_id)m_libraryHandle ); +} + + +DynamicLibraryManager::Symbol +DynamicLibraryManager::doFindSymbol( const std::string &symbol ) +{ + void *symbolPointer; + if ( ::get_image_symbol( (image_id)m_libraryHandle, + symbol.c_str(), + B_SYMBOL_TYPE_TEXT, + &symbolPointer ) == B_OK ) + return symnolPointer; + return NULL; +} + + +std::string +DynamicLibraryManager::getLastErrorDetail() const +{ + return ""; +} + + +CPPUNIT_NS_END + + +#endif // defined(CPPUNIT_HAVE_BEOS_DLL_LOADER) diff --git a/UnitTests/cppunit/src/cppunit/BriefTestProgressListener.cpp b/UnitTests/cppunit/src/cppunit/BriefTestProgressListener.cpp new file mode 100644 index 0000000..4ea8d35 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/BriefTestProgressListener.cpp @@ -0,0 +1,49 @@ +#include +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +BriefTestProgressListener::BriefTestProgressListener() + : m_lastTestFailed( false ) +{ +} + + +BriefTestProgressListener::~BriefTestProgressListener() +{ +} + + +void +BriefTestProgressListener::startTest( Test *test ) +{ + stdCOut() << test->getName(); + stdCOut().flush(); + + m_lastTestFailed = false; +} + + +void +BriefTestProgressListener::addFailure( const TestFailure &failure ) +{ + stdCOut() << " : " << (failure.isError() ? "error" : "assertion"); + m_lastTestFailed = true; +} + + +void +BriefTestProgressListener::endTest( Test * ) +{ + if ( !m_lastTestFailed ) + stdCOut() << " : OK"; + stdCOut() << "\n"; +} + + +CPPUNIT_NS_END + diff --git a/UnitTests/cppunit/src/cppunit/CompilerOutputter.cpp b/UnitTests/cppunit/src/cppunit/CompilerOutputter.cpp new file mode 100644 index 0000000..8196a5f --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/CompilerOutputter.cpp @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +CompilerOutputter::CompilerOutputter( TestResultCollector *result, + OStream &stream, + const std::string &locationFormat ) + : m_result( result ) + , m_stream( stream ) + , m_locationFormat( locationFormat ) + , m_wrapColumn( CPPUNIT_WRAP_COLUMN ) +{ +} + + +CompilerOutputter::~CompilerOutputter() +{ +} + + +void +CompilerOutputter::setLocationFormat( const std::string &locationFormat ) +{ + m_locationFormat = locationFormat; +} + + +CompilerOutputter * +CompilerOutputter::defaultOutputter( TestResultCollector *result, + OStream &stream ) +{ + return new CompilerOutputter( result, stream ); +} + + +void +CompilerOutputter::write() +{ + if ( m_result->wasSuccessful() ) + printSuccess(); + else + printFailureReport(); +} + + +void +CompilerOutputter::printSuccess() +{ + m_stream << "OK (" << m_result->runTests() << ")\n"; +} + + +void +CompilerOutputter::printFailureReport() +{ + printFailuresList(); + printStatistics(); +} + + +void +CompilerOutputter::printFailuresList() +{ + for ( int index =0; index < m_result->testFailuresTotal(); ++index) + { + printFailureDetail( m_result->failures()[ index ] ); + } +} + + +void +CompilerOutputter::printFailureDetail( TestFailure *failure ) +{ + printFailureLocation( failure->sourceLine() ); + printFailureType( failure ); + printFailedTestName( failure ); + printFailureMessage( failure ); +} + + +void +CompilerOutputter::printFailureLocation( SourceLine sourceLine ) +{ + if ( !sourceLine.isValid() ) + { + m_stream << "##Failure Location unknown## : "; + return; + } + + std::string location; + for ( unsigned int index = 0; index < m_locationFormat.length(); ++index ) + { + char c = m_locationFormat[ index ]; + if ( c == '%' && ( index+1 < m_locationFormat.length() ) ) + { + char command = m_locationFormat[index+1]; + if ( processLocationFormatCommand( command, sourceLine ) ) + { + ++index; + continue; + } + } + + m_stream << c; + } +} + + +bool +CompilerOutputter::processLocationFormatCommand( char command, + const SourceLine &sourceLine ) +{ + switch ( command ) + { + case 'p': + m_stream << sourceLine.fileName(); + return true; + case 'l': + m_stream << sourceLine.lineNumber(); + return true; + case 'f': + m_stream << extractBaseName( sourceLine.fileName() ); + return true; + } + + return false; +} + + +std::string +CompilerOutputter::extractBaseName( const std::string &fileName ) const +{ + int indexLastDirectorySeparator = fileName.find_last_of( '/' ); + + if ( indexLastDirectorySeparator < 0 ) + indexLastDirectorySeparator = fileName.find_last_of( '\\' ); + + if ( indexLastDirectorySeparator < 0 ) + return fileName; + + return fileName.substr( indexLastDirectorySeparator +1 ); +} + + +void +CompilerOutputter::printFailureType( TestFailure *failure ) +{ + m_stream << (failure->isError() ? "Error" : "Assertion"); +} + + +void +CompilerOutputter::printFailedTestName( TestFailure *failure ) +{ + m_stream << "\nTest name: " << failure->failedTestName(); +} + + +void +CompilerOutputter::printFailureMessage( TestFailure *failure ) +{ + m_stream << "\n"; + Exception *thrownException = failure->thrownException(); + m_stream << thrownException->message().shortDescription() << "\n"; + + std::string message = thrownException->message().details(); + if ( m_wrapColumn > 0 ) + message = StringTools::wrap( message, m_wrapColumn ); + + m_stream << message << "\n"; +} + + +void +CompilerOutputter::printStatistics() +{ + m_stream << "Failures !!!\n"; + m_stream << "Run: " << m_result->runTests() << " " + << "Failure total: " << m_result->testFailuresTotal() << " " + << "Failures: " << m_result->testFailures() << " " + << "Errors: " << m_result->testErrors() + << "\n"; +} + + +void +CompilerOutputter::setWrapColumn( int wrapColumn ) +{ + m_wrapColumn = wrapColumn; +} + + +void +CompilerOutputter::setNoWrap() +{ + m_wrapColumn = 0; +} + + +int +CompilerOutputter::wrapColumn() const +{ + return m_wrapColumn; +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/DefaultProtector.cpp b/UnitTests/cppunit/src/cppunit/DefaultProtector.cpp new file mode 100644 index 0000000..6fb306b --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/DefaultProtector.cpp @@ -0,0 +1,42 @@ +#include +#include +#include "DefaultProtector.h" + + +CPPUNIT_NS_BEGIN + + +bool +DefaultProtector::protect( const Functor &functor, + const ProtectorContext &context ) +{ + try + { + return functor(); + } + catch ( Exception &failure ) + { + reportFailure( context, failure ); + } + catch ( std::exception &e ) + { + std::string shortDescription( "uncaught exception of type " ); +#if CPPUNIT_USE_TYPEINFO_NAME + shortDescription += TypeInfoHelper::getClassName( typeid(e) ); +#else + shortDescription += "std::exception (or derived)."; +#endif + Message message( shortDescription, e.what() ); + reportError( context, message ); + } + catch ( ... ) + { + reportError( context, + Message( "uncaught exception of unknown type") ); + } + + return false; +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/DefaultProtector.h b/UnitTests/cppunit/src/cppunit/DefaultProtector.h new file mode 100644 index 0000000..4a76ea0 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/DefaultProtector.h @@ -0,0 +1,27 @@ +#ifndef CPPUNIT_DEFAULTPROTECTOR_H +#define CPPUNIT_DEFAULTPROTECTOR_H + +#include + +CPPUNIT_NS_BEGIN + +/*! \brief Default protector that catch all exceptions (Implementation). + * + * Implementation detail. + * \internal This protector catch and generate a failure for the following + * exception types: + * - Exception + * - std::exception + * - ... + */ +class DefaultProtector : public Protector +{ +public: + bool protect( const Functor &functor, + const ProtectorContext &context ); +}; + +CPPUNIT_NS_END + +#endif // CPPUNIT_DEFAULTPROTECTOR_H + diff --git a/UnitTests/cppunit/src/cppunit/DllMain.cpp b/UnitTests/cppunit/src/cppunit/DllMain.cpp new file mode 100644 index 0000000..51fe31e --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/DllMain.cpp @@ -0,0 +1,16 @@ +#define WIN32_LEAN_AND_MEAN +#define NOGDI +#define NOUSER +#define NOKERNEL +#define NOSOUND +#define BLENDFUNCTION void // for mingw & gcc + +#include + +BOOL APIENTRY +DllMain( HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved ) +{ + return TRUE; +} diff --git a/UnitTests/cppunit/src/cppunit/DynamicLibraryManager.cpp b/UnitTests/cppunit/src/cppunit/DynamicLibraryManager.cpp new file mode 100644 index 0000000..e6f6294 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/DynamicLibraryManager.cpp @@ -0,0 +1,77 @@ +#include + +#if !defined(CPPUNIT_NO_TESTPLUGIN) +#include + +CPPUNIT_NS_BEGIN + + +DynamicLibraryManager::DynamicLibraryManager( const std::string &libraryFileName ) + : m_libraryHandle( NULL ) + , m_libraryName( libraryFileName ) +{ + loadLibrary( libraryFileName ); +} + + +DynamicLibraryManager::~DynamicLibraryManager() +{ + releaseLibrary(); +} + + +DynamicLibraryManager::Symbol +DynamicLibraryManager::findSymbol( const std::string &symbol ) +{ + try + { + Symbol symbolPointer = doFindSymbol( symbol ); + if ( symbolPointer != NULL ) + return symbolPointer; + } + catch ( ... ) + { + } + + throw DynamicLibraryManagerException( m_libraryName, + symbol, + DynamicLibraryManagerException::symbolNotFound ); + return NULL; // keep compiler happy +} + + +void +DynamicLibraryManager::loadLibrary( const std::string &libraryName ) +{ + try + { + releaseLibrary(); + m_libraryHandle = doLoadLibrary( libraryName ); + if ( m_libraryHandle != NULL ) + return; + } + catch (...) + { + } + + throw DynamicLibraryManagerException( m_libraryName, + getLastErrorDetail(), + DynamicLibraryManagerException::loadingFailed ); +} + + +void +DynamicLibraryManager::releaseLibrary() +{ + if ( m_libraryHandle != NULL ) + { + doReleaseLibrary(); + m_libraryHandle = NULL; + } +} + + +CPPUNIT_NS_END + + +#endif // !defined(CPPUNIT_NO_TESTPLUGIN) diff --git a/UnitTests/cppunit/src/cppunit/DynamicLibraryManagerException.cpp b/UnitTests/cppunit/src/cppunit/DynamicLibraryManagerException.cpp new file mode 100644 index 0000000..8498652 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/DynamicLibraryManagerException.cpp @@ -0,0 +1,41 @@ +#include + +#if !defined(CPPUNIT_NO_TESTPLUGIN) + +CPPUNIT_NS_BEGIN + + +DynamicLibraryManagerException::DynamicLibraryManagerException( + const std::string &libraryName, + const std::string &errorDetail, + Cause cause ) + : std::runtime_error( "" ), + m_cause( cause ) +{ + if ( cause == loadingFailed ) + m_message = "Failed to load dynamic library: " + libraryName + "\n" + + errorDetail; + else + m_message = "Symbol [" + errorDetail + "] not found in dynamic libary:" + + libraryName; +} + + +DynamicLibraryManagerException::Cause +DynamicLibraryManagerException::getCause() const +{ + return m_cause; +} + + +const char * +DynamicLibraryManagerException::what() const throw() +{ + return m_message.c_str(); +} + + +CPPUNIT_NS_END + + +#endif // !defined(CPPUNIT_NO_TESTPLUGIN) diff --git a/UnitTests/cppunit/src/cppunit/Exception.cpp b/UnitTests/cppunit/src/cppunit/Exception.cpp new file mode 100644 index 0000000..3bbe24b --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/Exception.cpp @@ -0,0 +1,126 @@ +#include + + +CPPUNIT_NS_BEGIN + + +#ifdef CPPUNIT_ENABLE_SOURCELINE_DEPRECATED +/*! + * \deprecated Use SourceLine::isValid() instead. + */ +const std::string Exception::UNKNOWNFILENAME = ""; + +/*! + * \deprecated Use SourceLine::isValid() instead. + */ +const long Exception::UNKNOWNLINENUMBER = -1; +#endif + + +Exception::Exception( const Exception &other ) + : std::exception( other ) +{ + m_message = other.m_message; + m_sourceLine = other.m_sourceLine; +} + + +Exception::Exception( const Message &message, + const SourceLine &sourceLine ) + : m_message( message ) + , m_sourceLine( sourceLine ) +{ +} + + +#ifdef CPPUNIT_ENABLE_SOURCELINE_DEPRECATED +Exception::Exception( std::string message, + long lineNumber, + std::string fileName ) + : m_message( message ) + , m_sourceLine( fileName, lineNumber ) +{ +} +#endif + + +Exception::~Exception() throw() +{ +} + + +Exception & +Exception::operator =( const Exception& other ) +{ +// Don't call superclass operator =(). VC++ STL implementation +// has a bug. It calls the destructor and copy constructor of +// std::exception() which reset the virtual table to std::exception. +// SuperClass::operator =(other); + + if ( &other != this ) + { + m_message = other.m_message; + m_sourceLine = other.m_sourceLine; + } + + return *this; +} + + +const char* +Exception::what() const throw() +{ + Exception *mutableThis = CPPUNIT_CONST_CAST( Exception *, this ); + mutableThis->m_whatMessage = m_message.shortDescription() + "\n" + + m_message.details(); + return m_whatMessage.c_str(); +} + + +SourceLine +Exception::sourceLine() const +{ + return m_sourceLine; +} + + +Message +Exception::message() const +{ + return m_message; +} + + +void +Exception::setMessage( const Message &message ) +{ + m_message = message; +} + + +#ifdef CPPUNIT_ENABLE_SOURCELINE_DEPRECATED +long +Exception::lineNumber() const +{ + return m_sourceLine.isValid() ? m_sourceLine.lineNumber() : + UNKNOWNLINENUMBER; +} + + +std::string +Exception::fileName() const +{ + return m_sourceLine.isValid() ? m_sourceLine.fileName() : + UNKNOWNFILENAME; +} +#endif + + +Exception * +Exception::clone() const +{ + return new Exception( *this ); +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/Message.cpp b/UnitTests/cppunit/src/cppunit/Message.cpp new file mode 100644 index 0000000..9d6a0e9 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/Message.cpp @@ -0,0 +1,170 @@ +#include +#include + + +CPPUNIT_NS_BEGIN + + +Message::Message() +{ +} + +Message::Message( const Message &other ) +{ + *this = other; +} + + +Message::Message( const std::string &shortDescription ) + : m_shortDescription( shortDescription ) +{ +} + + +Message::Message( const std::string &shortDescription, + const std::string &detail1 ) + : m_shortDescription( shortDescription ) +{ + addDetail( detail1 ); +} + + +Message::Message( const std::string &shortDescription, + const std::string &detail1, + const std::string &detail2 ) + : m_shortDescription( shortDescription ) +{ + addDetail( detail1, detail2 ); +} + + +Message::Message( const std::string &shortDescription, + const std::string &detail1, + const std::string &detail2, + const std::string &detail3 ) + : m_shortDescription( shortDescription ) +{ + addDetail( detail1, detail2, detail3 ); +} + +Message & +Message::operator =( const Message &other ) +{ + if ( this != &other ) + { + m_shortDescription = other.m_shortDescription.c_str(); + m_details.clear(); + Details::const_iterator it = other.m_details.begin(); + Details::const_iterator itEnd = other.m_details.end(); + while ( it != itEnd ) + m_details.push_back( (*it++).c_str() ); + } + + return *this; +} + + +const std::string & +Message::shortDescription() const +{ + return m_shortDescription; +} + + +int +Message::detailCount() const +{ + return m_details.size(); +} + + +std::string +Message::detailAt( int index ) const +{ + if ( index < 0 || index >= detailCount() ) + throw std::invalid_argument( "Message::detailAt() : invalid index" ); + + return m_details[ index ]; +} + + +std::string +Message::details() const +{ + std::string details; + for ( Details::const_iterator it = m_details.begin(); it != m_details.end(); ++it ) + { + details += "- "; + details += *it; + details += '\n'; + } + return details; +} + + +void +Message::clearDetails() +{ + m_details.clear(); +} + + +void +Message::addDetail( const std::string &detail ) +{ + m_details.push_back( detail ); +} + + +void +Message::addDetail( const std::string &detail1, + const std::string &detail2 ) +{ + addDetail( detail1 ); + addDetail( detail2 ); +} + + +void +Message::addDetail( const std::string &detail1, + const std::string &detail2, + const std::string &detail3 ) +{ + addDetail( detail1, detail2 ); + addDetail( detail3 ); +} + + +void +Message::addDetail( const Message &message ) +{ + m_details.insert( m_details.end(), + message.m_details.begin(), + message.m_details.end() ); +} + + +void +Message::setShortDescription( const std::string &shortDescription ) +{ + m_shortDescription = shortDescription; +} + + +bool +Message::operator ==( const Message &other ) const +{ + return m_shortDescription == other.m_shortDescription && + m_details == other.m_details; +} + + +bool +Message::operator !=( const Message &other ) const +{ + return !( *this == other ); +} + + +CPPUNIT_NS_END + diff --git a/UnitTests/cppunit/src/cppunit/PlugInManager.cpp b/UnitTests/cppunit/src/cppunit/PlugInManager.cpp new file mode 100644 index 0000000..b595dee --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/PlugInManager.cpp @@ -0,0 +1,110 @@ +#include +#include + +#if !defined(CPPUNIT_NO_TESTPLUGIN) +#include +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +PlugInManager::PlugInManager() +{ +} + + +PlugInManager::~PlugInManager() +{ + for ( PlugIns::iterator it = m_plugIns.begin(); it != m_plugIns.end(); ++it ) + unload( *it ); +} + + +void +PlugInManager::load( const std::string &libraryFileName, + const PlugInParameters ¶meters ) +{ + PlugInInfo info; + info.m_fileName = libraryFileName; + info.m_manager = new DynamicLibraryManager( libraryFileName ); + + TestPlugInSignature plug = (TestPlugInSignature)info.m_manager->findSymbol( + CPPUNIT_STRINGIZE( CPPUNIT_PLUGIN_EXPORTED_NAME ) ); + info.m_interface = (*plug)(); + + m_plugIns.push_back( info ); + + info.m_interface->initialize( &TestFactoryRegistry::getRegistry(), parameters ); +} + + +void +PlugInManager::unload( const std::string &libraryFileName ) +{ + for ( PlugIns::iterator it = m_plugIns.begin(); it != m_plugIns.end(); ++it ) + { + if ( (*it).m_fileName == libraryFileName ) + { + unload( *it ); + m_plugIns.erase( it ); + break; + } + } +} + + +void +PlugInManager::addListener( TestResult *eventManager ) +{ + for ( PlugIns::iterator it = m_plugIns.begin(); it != m_plugIns.end(); ++it ) + (*it).m_interface->addListener( eventManager ); +} + + +void +PlugInManager::removeListener( TestResult *eventManager ) +{ + for ( PlugIns::iterator it = m_plugIns.begin(); it != m_plugIns.end(); ++it ) + (*it).m_interface->removeListener( eventManager ); +} + + +void +PlugInManager::unload( PlugInInfo &plugIn ) +{ + try + { + plugIn.m_interface->uninitialize( &TestFactoryRegistry::getRegistry() ); + delete plugIn.m_manager; + } + catch (...) + { + delete plugIn.m_manager; + plugIn.m_manager = NULL; + throw; + } +} + + +void +PlugInManager::addXmlOutputterHooks( XmlOutputter *outputter ) +{ + for ( PlugIns::iterator it = m_plugIns.begin(); it != m_plugIns.end(); ++it ) + (*it).m_interface->addXmlOutputterHooks( outputter ); +} + + +void +PlugInManager::removeXmlOutputterHooks() +{ + for ( PlugIns::iterator it = m_plugIns.begin(); it != m_plugIns.end(); ++it ) + (*it).m_interface->removeXmlOutputterHooks(); +} + + +CPPUNIT_NS_END + +#endif // !defined(CPPUNIT_NO_TESTPLUGIN) diff --git a/UnitTests/cppunit/src/cppunit/PlugInParameters.cpp b/UnitTests/cppunit/src/cppunit/PlugInParameters.cpp new file mode 100644 index 0000000..1b532f9 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/PlugInParameters.cpp @@ -0,0 +1,28 @@ +#include + +#if !defined(CPPUNIT_NO_TESTPLUGIN) + +CPPUNIT_NS_BEGIN + + +PlugInParameters::PlugInParameters( const std::string &commandLine ) + : m_commandLine( commandLine ) +{ +} + + +PlugInParameters::~PlugInParameters() +{ +} + + +std::string +PlugInParameters::getCommandLine() const +{ + return m_commandLine; +} + + +CPPUNIT_NS_END + +#endif // !defined(CPPUNIT_NO_TESTPLUGIN) diff --git a/UnitTests/cppunit/src/cppunit/Protector.cpp b/UnitTests/cppunit/src/cppunit/Protector.cpp new file mode 100644 index 0000000..5c171ec --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/Protector.cpp @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include "ProtectorContext.h" +#include + +CPPUNIT_NS_BEGIN + +Functor::~Functor() +{ +} + + +Protector::~Protector() +{ +} + + +void +Protector::reportError( const ProtectorContext &context, + const Exception &error ) const +{ + std::auto_ptr actualError( error.clone() ); + actualError->setMessage( actualMessage( actualError->message(), context ) ); + context.m_result->addError( context.m_test, + actualError.release() ); +} + + + +void +Protector::reportError( const ProtectorContext &context, + const Message &message, + const SourceLine &sourceLine ) const +{ + reportError( context, Exception( message, sourceLine ) ); +} + + +void +Protector::reportFailure( const ProtectorContext &context, + const Exception &failure ) const +{ + std::auto_ptr actualFailure( failure.clone() ); + actualFailure->setMessage( actualMessage( actualFailure->message(), context ) ); + context.m_result->addFailure( context.m_test, + actualFailure.release() ); +} + + +Message +Protector::actualMessage( const Message &message, + const ProtectorContext &context ) const +{ + Message theActualMessage; + if ( context.m_shortDescription.empty() ) + theActualMessage = message; + else + { + theActualMessage = Message( context.m_shortDescription, + message.shortDescription() ); + theActualMessage.addDetail( message ); + } + + return theActualMessage; +} + + + + +ProtectorGuard::ProtectorGuard( TestResult *result, + Protector *protector ) + : m_result( result ) +{ + m_result->pushProtector( protector ); +} + + +ProtectorGuard::~ProtectorGuard() +{ + m_result->popProtector(); +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/ProtectorChain.cpp b/UnitTests/cppunit/src/cppunit/ProtectorChain.cpp new file mode 100644 index 0000000..f528341 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/ProtectorChain.cpp @@ -0,0 +1,86 @@ +#include "ProtectorChain.h" + +CPPUNIT_NS_BEGIN + + +class ProtectorChain::ProtectFunctor : public Functor +{ +public: + ProtectFunctor( Protector *protector, + const Functor &functor, + const ProtectorContext &context ) + : m_protector( protector ) + , m_functor( functor ) + , m_context( context ) + { + } + + bool operator()() const + { + return m_protector->protect( m_functor, m_context ); + } + +private: + Protector *m_protector; + const Functor &m_functor; + const ProtectorContext &m_context; +}; + + +ProtectorChain::~ProtectorChain() +{ + while ( count() > 0 ) + pop(); +} + + +void +ProtectorChain::push( Protector *protector ) +{ + m_protectors.push_back( protector ); +} + + +void +ProtectorChain::pop() +{ + delete m_protectors.back(); + m_protectors.pop_back(); +} + +int +ProtectorChain::count() const +{ + return m_protectors.size(); +} + + +bool +ProtectorChain::protect( const Functor &functor, + const ProtectorContext &context ) +{ + if ( m_protectors.empty() ) + return functor(); + + Functors functors; + for ( int index = m_protectors.size()-1; index >= 0; --index ) + { + const Functor &protectedFunctor = + functors.empty() ? functor : *functors.back(); + + functors.push_back( new ProtectFunctor( m_protectors[index], + protectedFunctor, + context ) ); + } + + const Functor &outermostFunctor = *functors.back(); + bool succeed = outermostFunctor(); + + for ( unsigned int deletingIndex = 0; deletingIndex < m_protectors.size(); ++deletingIndex ) + delete functors[deletingIndex]; + + return succeed; +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/ProtectorChain.h b/UnitTests/cppunit/src/cppunit/ProtectorChain.h new file mode 100644 index 0000000..711b56f --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/ProtectorChain.h @@ -0,0 +1,51 @@ +#ifndef CPPUNIT_PROTECTORCHAIN_H +#define CPPUNIT_PROTECTORCHAIN_H + +#include +#include + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( push ) +#pragma warning( disable: 4251 ) // X needs to have dll-interface to be used by clients of class Z +#endif + + +CPPUNIT_NS_BEGIN + +/*! \brief Protector chain (Implementation). + * Implementation detail. + * \internal Protector that protect a Functor using a chain of nested Protector. + */ +class CPPUNIT_API ProtectorChain : public Protector +{ +public: + ~ProtectorChain(); + + void push( Protector *protector ); + + void pop(); + + int count() const; + + bool protect( const Functor &functor, + const ProtectorContext &context ); + +private: + class ProtectFunctor; + +private: + typedef CppUnitDeque Protectors; + Protectors m_protectors; + + typedef CppUnitDeque Functors; +}; + + +CPPUNIT_NS_END + +#if CPPUNIT_NEED_DLL_DECL +#pragma warning( pop ) +#endif + +#endif // CPPUNIT_PROTECTORCHAIN_H + diff --git a/UnitTests/cppunit/src/cppunit/ProtectorContext.h b/UnitTests/cppunit/src/cppunit/ProtectorContext.h new file mode 100644 index 0000000..c3d496c --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/ProtectorContext.h @@ -0,0 +1,38 @@ +#ifndef CPPUNIT_PROTECTORCONTEXT_H +#define CPPUNIT_PROTECTORCONTEXT_H + +#include +#include + +CPPUNIT_NS_BEGIN + +class Test; +class TestResult; + + +/*! \brief Protector context (Implementation). + * Implementation detail. + * \internal Context use to report failure in Protector. + */ +class CPPUNIT_API ProtectorContext +{ +public: + ProtectorContext( Test *test, + TestResult *result, + const std::string &shortDescription ) + : m_test( test ) + , m_result( result ) + , m_shortDescription( shortDescription ) + { + } + + Test *m_test; + TestResult *m_result; + std::string m_shortDescription; +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_PROTECTORCONTEXT_H + diff --git a/UnitTests/cppunit/src/cppunit/RepeatedTest.cpp b/UnitTests/cppunit/src/cppunit/RepeatedTest.cpp new file mode 100644 index 0000000..2533ca1 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/RepeatedTest.cpp @@ -0,0 +1,29 @@ +#include +#include + +CPPUNIT_NS_BEGIN + + +// Counts the number of test cases that will be run by this test. +int +RepeatedTest::countTestCases() const +{ + return TestDecorator::countTestCases() * m_timesRepeat; +} + + +// Runs a repeated test +void +RepeatedTest::run( TestResult *result ) +{ + for ( int n = 0; n < m_timesRepeat; n++ ) + { + if ( result->shouldStop() ) + break; + + TestDecorator::run( result ); + } +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/ShlDynamicLibraryManager.cpp b/UnitTests/cppunit/src/cppunit/ShlDynamicLibraryManager.cpp new file mode 100644 index 0000000..9f4be22 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/ShlDynamicLibraryManager.cpp @@ -0,0 +1,53 @@ +#include + +#if defined(CPPUNIT_HAVE_UNIX_SHL_LOADER) +#include + +#include +#include + + +CPPUNIT_NS_BEGIN + + +DynamicLibraryManager::LibraryHandle +DynamicLibraryManager::doLoadLibrary( const std::string &libraryName ) +{ + return ::shl_load(libraryName.c_str(), BIND_IMMEDIATE, 0L); +} + + +void +DynamicLibraryManager::doReleaseLibrary() +{ + ::shl_unload( (shl_t)m_libraryHandle); +} + + +DynamicLibraryManager::Symbol +DynamicLibraryManager::doFindSymbol( const std::string &symbol ) +{ + DynamicLibraryManager::Symbol L_symaddr = 0; + if ( ::shl_findsym( (shl_t*)(&m_libraryHandle), + symbol.c_str(), + TYPE_UNDEFINED, + &L_symaddr ) == 0 ) + { + return L_symaddr; + } + + return 0; +} + + +std::string +DynamicLibraryManager::getLastErrorDetail() const +{ + return ""; +} + + +CPPUNIT_NS_END + + +#endif // defined(CPPUNIT_HAVE_UNIX_SHL_LOADER) diff --git a/UnitTests/cppunit/src/cppunit/SourceLine.cpp b/UnitTests/cppunit/src/cppunit/SourceLine.cpp new file mode 100644 index 0000000..dfadae3 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/SourceLine.cpp @@ -0,0 +1,81 @@ +#include + + +CPPUNIT_NS_BEGIN + + +SourceLine::SourceLine() : + m_lineNumber( -1 ) +{ +} + + +SourceLine::SourceLine( const SourceLine &other ) + : m_fileName( other.m_fileName.c_str() ) + , m_lineNumber( other.m_lineNumber ) +{ +} + + +SourceLine::SourceLine( const std::string &fileName, + int lineNumber ) + : m_fileName( fileName.c_str() ) + , m_lineNumber( lineNumber ) +{ +} + + +SourceLine & +SourceLine::operator =( const SourceLine &other ) +{ + if ( this != &other ) + { + m_fileName = other.m_fileName.c_str(); + m_lineNumber = other.m_lineNumber; + } + return *this; +} + + +SourceLine::~SourceLine() +{ +} + + +bool +SourceLine::isValid() const +{ + return !m_fileName.empty(); +} + + +int +SourceLine::lineNumber() const +{ + return m_lineNumber; +} + + +std::string +SourceLine::fileName() const +{ + return m_fileName; +} + + +bool +SourceLine::operator ==( const SourceLine &other ) const +{ + return m_fileName == other.m_fileName && + m_lineNumber == other.m_lineNumber; +} + + +bool +SourceLine::operator !=( const SourceLine &other ) const +{ + return !( *this == other ); +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/StringTools.cpp b/UnitTests/cppunit/src/cppunit/StringTools.cpp new file mode 100644 index 0000000..dc995d8 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/StringTools.cpp @@ -0,0 +1,80 @@ +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +std::string +StringTools::toString( int value ) +{ + OStringStream stream; + stream << value; + return stream.str(); +} + + +std::string +StringTools::toString( double value ) +{ + OStringStream stream; + stream << value; + return stream.str(); +} + + +StringTools::Strings +StringTools::split( const std::string &text, + char separator ) +{ + Strings splittedText; + + std::string::const_iterator itStart = text.begin(); + while ( !text.empty() ) + { + std::string::const_iterator itSeparator = std::find( itStart, + text.end(), + separator ); + splittedText.push_back( text.substr( itStart - text.begin(), + itSeparator - itStart ) ); + if ( itSeparator == text.end() ) + break; + itStart = itSeparator +1; + } + + return splittedText; +} + + +std::string +StringTools::wrap( const std::string &text, + int wrapColumn ) +{ + const char lineBreak = '\n'; + Strings lines = split( text, lineBreak ); + + std::string wrapped; + for ( Strings::const_iterator it = lines.begin(); it != lines.end(); ++it ) + { + if ( it != lines.begin() ) + wrapped += lineBreak; + + const std::string &line = *it; + unsigned int index =0; + while ( index < line.length() ) + { + std::string lineSlice( line.substr( index, wrapColumn ) ); + wrapped += lineSlice; + index += wrapColumn; + if ( index < line.length() ) + wrapped += lineBreak; + } + } + + return wrapped; +} + + +CPPUNIT_NS_END + diff --git a/UnitTests/cppunit/src/cppunit/SynchronizedObject.cpp b/UnitTests/cppunit/src/cppunit/SynchronizedObject.cpp new file mode 100644 index 0000000..1764538 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/SynchronizedObject.cpp @@ -0,0 +1,32 @@ +#include + + +CPPUNIT_NS_BEGIN + + +SynchronizedObject::SynchronizedObject( SynchronizationObject *syncObject ) + : m_syncObject( syncObject == 0 ? new SynchronizationObject() : + syncObject ) +{ +} + + +SynchronizedObject::~SynchronizedObject() +{ + delete m_syncObject; +} + + +/** Accept a new synchronization object for protection of this instance + * TestResult assumes ownership of the object + */ +void +SynchronizedObject::setSynchronizationObject( SynchronizationObject *syncObject ) +{ + delete m_syncObject; + m_syncObject = syncObject; +} + + +CPPUNIT_NS_END + diff --git a/UnitTests/cppunit/src/cppunit/Test.cpp b/UnitTests/cppunit/src/cppunit/Test.cpp new file mode 100644 index 0000000..fef8be7 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/Test.cpp @@ -0,0 +1,97 @@ +#include +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +Test * +Test::getChildTestAt( int index ) const +{ + checkIsValidIndex( index ); + return doGetChildTestAt( index ); +} + + +Test * +Test::findTest( const std::string &testName ) const +{ + TestPath path; + Test *mutableThis = CPPUNIT_CONST_CAST( Test *, this ); + mutableThis->findTestPath( testName, path ); + if ( !path.isValid() ) + throw std::invalid_argument( "No test named <" + testName + "> found in test <" + + getName() + ">." ); + return path.getChildTest(); +} + + +bool +Test::findTestPath( const std::string &testName, + TestPath &testPath ) const +{ + Test *mutableThis = CPPUNIT_CONST_CAST( Test *, this ); + if ( getName() == testName ) + { + testPath.add( mutableThis ); + return true; + } + + int childCount = getChildTestCount(); + for ( int childIndex =0; childIndex < childCount; ++childIndex ) + { + if ( getChildTestAt( childIndex )->findTestPath( testName, testPath ) ) + { + testPath.insert( mutableThis, 0 ); + return true; + } + } + + return false; +} + + +bool +Test::findTestPath( const Test *test, + TestPath &testPath ) const +{ + Test *mutableThis = CPPUNIT_CONST_CAST( Test *, this ); + if ( this == test ) + { + testPath.add( mutableThis ); + return true; + } + + int childCount = getChildTestCount(); + for ( int childIndex =0; childIndex < childCount; ++childIndex ) + { + if ( getChildTestAt( childIndex )->findTestPath( test, testPath ) ) + { + testPath.insert( mutableThis, 0 ); + return true; + } + } + + return false; +} + + +TestPath +Test::resolveTestPath( const std::string &testPath ) const +{ + Test *mutableThis = CPPUNIT_CONST_CAST( Test *, this ); + return TestPath( mutableThis, testPath ); +} + + +void +Test::checkIsValidIndex( int index ) const +{ + if ( index < 0 || index >= getChildTestCount() ) + throw std::out_of_range( "Test::checkValidIndex(): invalid index" ); +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/TestAssert.cpp b/UnitTests/cppunit/src/cppunit/TestAssert.cpp new file mode 100644 index 0000000..6e4e794 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestAssert.cpp @@ -0,0 +1,46 @@ +#include +#include + +CPPUNIT_NS_BEGIN + + +void +assertDoubleEquals( double expected, + double actual, + double delta, + SourceLine sourceLine, + const std::string &message ) +{ + AdditionalMessage msg( "Delta : " + + assertion_traits::toString(delta) ); + msg.addDetail( AdditionalMessage(message) ); + + bool equal; + if ( floatingPointIsFinite(expected) && floatingPointIsFinite(actual) ) + equal = fabs( expected - actual ) <= delta; + else + { + // If expected or actual is not finite, it may be +inf, -inf or NaN (Not a Number). + // Value of +inf or -inf leads to a true equality regardless of delta if both + // expected and actual have the same value (infinity sign). + // NaN Value should always lead to a failed equality. + if ( floatingPointIsUnordered(expected) || floatingPointIsUnordered(actual) ) + { + equal = false; // expected or actual is a NaN + } + else // ordered values, +inf or -inf comparison + { + equal = expected == actual; + } + } + + Asserter::failNotEqualIf( !equal, + assertion_traits::toString(expected), + assertion_traits::toString(actual), + sourceLine, + msg, + "double equality assertion failed" ); +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/TestCase.cpp b/UnitTests/cppunit/src/cppunit/TestCase.cpp new file mode 100644 index 0000000..13c0525 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestCase.cpp @@ -0,0 +1,137 @@ +#include +#include +#include +#include +#include +#include + +#if CPPUNIT_USE_TYPEINFO_NAME +# include +#endif + +CPPUNIT_NS_BEGIN + +/*! \brief Functor to call test case method (Implementation). + * + * Implementation detail. + */ +class TestCaseMethodFunctor : public Functor +{ +public: + typedef void (TestCase::*Method)(); + + TestCaseMethodFunctor( TestCase *target, + Method method ) + : m_target( target ) + , m_method( method ) + { + } + + bool operator()() const + { + (m_target->*m_method)(); + return true; + } + +private: + TestCase *m_target; + Method m_method; +}; + + +/** Constructs a test case. + * \param name the name of the TestCase. + **/ +TestCase::TestCase( const std::string &name ) + : m_name(name) +{ +} + + +/// Run the test and catch any exceptions that are triggered by it +void +TestCase::run( TestResult *result ) +{ + result->startTest(this); +/* + try { + setUp(); + + try { + runTest(); + } + catch ( Exception &e ) { + Exception *copy = e.clone(); + result->addFailure( this, copy ); + } + catch ( std::exception &e ) { + result->addError( this, new Exception( Message( "uncaught std::exception", + e.what() ) ) ); + } + catch (...) { + Exception *e = new Exception( Message( "uncaught unknown exception" ) ); + result->addError( this, e ); + } + + try { + tearDown(); + } + catch (...) { + result->addError( this, new Exception( Message( "tearDown() failed" ) ) ); + } + } + catch (...) { + result->addError( this, new Exception( Message( "setUp() failed" ) ) ); + } +*/ + if ( result->protect( TestCaseMethodFunctor( this, &TestCase::setUp ), + this, + "setUp() failed" ) ) + { + result->protect( TestCaseMethodFunctor( this, &TestCase::runTest ), + this ); + } + + result->protect( TestCaseMethodFunctor( this, &TestCase::tearDown ), + this, + "tearDown() failed" ); + + result->endTest( this ); +} + + +/// All the work for runTest is deferred to subclasses +void +TestCase::runTest() +{ +} + + +/** Constructs a test case for a suite. + * \deprecated This constructor was used by fixture when TestFixture did not exist. + * Have your fixture inherits TestFixture instead of TestCase. + * \internal + * This TestCase was intended for use by the TestCaller and should not + * be used by a test case for which run() is called. + **/ +TestCase::TestCase() + : m_name( "" ) +{ +} + + +/// Destructs a test case +TestCase::~TestCase() +{ +} + + +/// Returns the name of the test case +std::string +TestCase::getName() const +{ + return m_name; +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/TestCaseDecorator.cpp b/UnitTests/cppunit/src/cppunit/TestCaseDecorator.cpp new file mode 100644 index 0000000..a7229f4 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestCaseDecorator.cpp @@ -0,0 +1,47 @@ +#include + +CPPUNIT_NS_BEGIN + + +TestCaseDecorator::TestCaseDecorator( TestCase *test ) + : TestCase( test->getName() ), + m_test( test ) +{ +} + + +TestCaseDecorator::~TestCaseDecorator() +{ + delete m_test; +} + + +std::string +TestCaseDecorator::getName() const +{ + return m_test->getName(); +} + + +void +TestCaseDecorator::setUp() +{ + m_test->setUp(); +} + + +void +TestCaseDecorator::tearDown() +{ + m_test->tearDown(); +} + + +void +TestCaseDecorator::runTest() +{ + m_test->runTest(); +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/TestComposite.cpp b/UnitTests/cppunit/src/cppunit/TestComposite.cpp new file mode 100644 index 0000000..4768791 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestComposite.cpp @@ -0,0 +1,77 @@ +#include +#include + + +CPPUNIT_NS_BEGIN + + +TestComposite::TestComposite( const std::string &name ) + : m_name( name ) +{ +} + + +TestComposite::~TestComposite() +{ +} + + +void +TestComposite::run( TestResult *result ) +{ + doStartSuite( result ); + doRunChildTests( result ); + doEndSuite( result ); +} + + +int +TestComposite::countTestCases() const +{ + int count = 0; + + int childCount = getChildTestCount(); + for ( int index =0; index < childCount; ++index ) + count += getChildTestAt( index )->countTestCases(); + + return count; +} + + +std::string +TestComposite::getName() const +{ + return m_name; +} + + +void +TestComposite::doStartSuite( TestResult *controller ) +{ + controller->startSuite( this ); +} + + +void +TestComposite::doRunChildTests( TestResult *controller ) +{ + int childCount = getChildTestCount(); + for ( int index =0; index < childCount; ++index ) + { + if ( controller->shouldStop() ) + break; + + getChildTestAt( index )->run( controller ); + } +} + + +void +TestComposite::doEndSuite( TestResult *controller ) +{ + controller->endSuite( this ); +} + + +CPPUNIT_NS_END + diff --git a/UnitTests/cppunit/src/cppunit/TestDecorator.cpp b/UnitTests/cppunit/src/cppunit/TestDecorator.cpp new file mode 100644 index 0000000..4e25a6a --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestDecorator.cpp @@ -0,0 +1,53 @@ +#include + +CPPUNIT_NS_BEGIN + + +TestDecorator::TestDecorator( Test *test ) + : m_test( test) +{ +} + + +TestDecorator::~TestDecorator() +{ + delete m_test; +} + + +int +TestDecorator::countTestCases() const +{ + return m_test->countTestCases(); +} + + +void +TestDecorator::run( TestResult *result ) +{ + m_test->run(result); +} + + +std::string +TestDecorator::getName() const +{ + return m_test->getName(); +} + + +int +TestDecorator::getChildTestCount() const +{ + return m_test->getChildTestCount(); +} + + +Test * +TestDecorator::doGetChildTestAt( int index ) const +{ + return m_test->getChildTestAt( index ); +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/TestFactoryRegistry.cpp b/UnitTests/cppunit/src/cppunit/TestFactoryRegistry.cpp new file mode 100644 index 0000000..3457da3 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestFactoryRegistry.cpp @@ -0,0 +1,161 @@ +#include +#include +#include +#include +#include + + +CPPUNIT_NS_BEGIN + +/*! \brief (INTERNAL) List of all TestFactoryRegistry. + */ +class TestFactoryRegistryList +{ +private: + typedef CppUnitMap > Registries; + Registries m_registries; + + enum State { + doNotChange =0, + notCreated, + exist, + destroyed + }; + + static State stateFlag( State newState = doNotChange ) + { + static State state = notCreated; + if ( newState != doNotChange ) + state = newState; + return state; + } + + static TestFactoryRegistryList *getInstance() + { + static TestFactoryRegistryList list; + return &list; + } + + TestFactoryRegistry *getInternalRegistry( const std::string &name ) + { + Registries::const_iterator foundIt = m_registries.find( name ); + if ( foundIt == m_registries.end() ) + { + TestFactoryRegistry *factory = new TestFactoryRegistry( name ); + m_registries.insert( std::pair( name, factory ) ); + return factory; + } + return (*foundIt).second; + } + +public: + TestFactoryRegistryList() + { + stateFlag( exist ); + } + + ~TestFactoryRegistryList() + { + for ( Registries::iterator it = m_registries.begin(); it != m_registries.end(); ++it ) + delete (*it).second; + + stateFlag( destroyed ); + } + + static TestFactoryRegistry *getRegistry( const std::string &name ) + { + // If the following assertion failed, then TestFactoryRegistry::getRegistry() + // was called during static variable destruction without checking the registry + // validity beforehand using TestFactoryRegistry::isValid() beforehand. + assert( isValid() ); + if ( !isValid() ) // release mode + return NULL; // => force CRASH + + return getInstance()->getInternalRegistry( name ); + } + + static bool isValid() + { + return stateFlag() != destroyed; + } +}; + + + +TestFactoryRegistry::TestFactoryRegistry( std::string name ) : + m_name( name ) +{ +} + + +TestFactoryRegistry::~TestFactoryRegistry() +{ +} + + +TestFactoryRegistry & +TestFactoryRegistry::getRegistry( const std::string &name ) +{ + return *TestFactoryRegistryList::getRegistry( name ); +} + + +void +TestFactoryRegistry::registerFactory( const std::string &, + TestFactory *factory ) +{ + registerFactory( factory ); +} + + +void +TestFactoryRegistry::registerFactory( TestFactory *factory ) +{ + m_factories.insert( factory ); +} + + +void +TestFactoryRegistry::unregisterFactory( TestFactory *factory ) +{ + m_factories.erase( factory ); +} + + +void +TestFactoryRegistry::addRegistry( const std::string &name ) +{ + registerFactory( &getRegistry( name ) ); +} + + +Test * +TestFactoryRegistry::makeTest() +{ + TestSuite *suite = new TestSuite( m_name ); + addTestToSuite( suite ); + return suite; +} + + +void +TestFactoryRegistry::addTestToSuite( TestSuite *suite ) +{ + for ( Factories::iterator it = m_factories.begin(); + it != m_factories.end(); + ++it ) + { + TestFactory *factory = *it; + suite->addTest( factory->makeTest() ); + } +} + + +bool +TestFactoryRegistry::isValid() +{ + return TestFactoryRegistryList::isValid(); +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/TestFailure.cpp b/UnitTests/cppunit/src/cppunit/TestFailure.cpp new file mode 100644 index 0000000..e31e138 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestFailure.cpp @@ -0,0 +1,71 @@ +#include +#include +#include + +CPPUNIT_NS_BEGIN + + +/// Constructs a TestFailure with the given test and exception. +TestFailure::TestFailure( Test *failedTest, + Exception *thrownException, + bool isError ) : + m_failedTest( failedTest ), + m_thrownException( thrownException ), + m_isError( isError ) +{ +} + +/// Deletes the owned exception. +TestFailure::~TestFailure() +{ + delete m_thrownException; +} + +/// Gets the failed test. +Test * +TestFailure::failedTest() const +{ + return m_failedTest; +} + + +/// Gets the thrown exception. Never \c NULL. +Exception * +TestFailure::thrownException() const +{ + return m_thrownException; +} + + +/// Gets the failure location. +SourceLine +TestFailure::sourceLine() const +{ + return m_thrownException->sourceLine(); +} + + +/// Indicates if the failure is a failed assertion or an error. +bool +TestFailure::isError() const +{ + return m_isError; +} + + +/// Gets the name of the failed test. +std::string +TestFailure::failedTestName() const +{ + return m_failedTest->getName(); +} + + +TestFailure * +TestFailure::clone() const +{ + return new TestFailure( m_failedTest, m_thrownException->clone(), m_isError ); +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/TestLeaf.cpp b/UnitTests/cppunit/src/cppunit/TestLeaf.cpp new file mode 100644 index 0000000..3d8767c --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestLeaf.cpp @@ -0,0 +1,28 @@ +#include + + +CPPUNIT_NS_BEGIN + + +int +TestLeaf::countTestCases() const +{ + return 1; +} + + +int +TestLeaf::getChildTestCount() const +{ + return 0; +} + + +Test * +TestLeaf::doGetChildTestAt( int index ) const +{ + checkIsValidIndex( index ); + return NULL; // never called, checkIsValidIndex() always throw. +} + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/TestNamer.cpp b/UnitTests/cppunit/src/cppunit/TestNamer.cpp new file mode 100644 index 0000000..eec9be9 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestNamer.cpp @@ -0,0 +1,44 @@ +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +#if CPPUNIT_HAVE_RTTI +TestNamer::TestNamer( const std::type_info &typeInfo ) +{ + m_fixtureName = TypeInfoHelper::getClassName( typeInfo ); +} +#endif + + +TestNamer::TestNamer( const std::string &fixtureName ) + : m_fixtureName( fixtureName ) +{ +} + + +TestNamer::~TestNamer() +{ +} + + +std::string +TestNamer::getFixtureName() const +{ + return m_fixtureName; +} + + +std::string +TestNamer::getTestNameFor( const std::string &testMethodName ) const +{ + return getFixtureName() + "::" + testMethodName; +} + + + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/TestPath.cpp b/UnitTests/cppunit/src/cppunit/TestPath.cpp new file mode 100644 index 0000000..a2783a2 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestPath.cpp @@ -0,0 +1,254 @@ +#include +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +TestPath::TestPath() +{ +} + + +TestPath::TestPath( Test *root ) +{ + add( root ); +} + + +TestPath::TestPath( const TestPath &other, + int indexFirst, + int count ) +{ + int countAdjustment = 0; + if ( indexFirst < 0 ) + { + countAdjustment = indexFirst; + indexFirst = 0; + } + + if ( count < 0 ) + count = other.getTestCount(); + else + count += countAdjustment; + + int index = indexFirst; + while ( count-- > 0 && index < other.getTestCount() ) + add( other.getTestAt( index++ ) ); +} + + +TestPath::TestPath( Test *searchRoot, + const std::string &pathAsString ) +{ + PathTestNames testNames; + + Test *parentTest = findActualRoot( searchRoot, pathAsString, testNames ); + add( parentTest ); + + for ( unsigned int index = 1; index < testNames.size(); ++index ) + { + bool childFound = false; + for ( int childIndex =0; childIndex < parentTest->getChildTestCount(); ++childIndex ) + { + if ( parentTest->getChildTestAt( childIndex )->getName() == testNames[index] ) + { + childFound = true; + parentTest = parentTest->getChildTestAt( childIndex ); + break; + } + } + + if ( !childFound ) + throw std::invalid_argument( "TestPath::TestPath(): failed to resolve test name <"+ + testNames[index] + "> of path <" + pathAsString + ">" ); + + add( parentTest ); + } +} + + +TestPath::TestPath( const TestPath &other ) + : m_tests( other.m_tests ) +{ +} + + +TestPath::~TestPath() +{ +} + + +TestPath & +TestPath::operator =( const TestPath &other ) +{ + if ( &other != this ) + m_tests = other.m_tests; + return *this; +} + + +bool +TestPath::isValid() const +{ + return getTestCount() > 0; +} + + +void +TestPath::add( Test *test ) +{ + m_tests.push_back( test ); +} + + +void +TestPath::add( const TestPath &path ) +{ + for ( int index =0; index < path.getTestCount(); ++index ) + add( path.getTestAt( index ) ); +} + + +void +TestPath::insert( Test *test, + int index ) +{ + if ( index < 0 || index > getTestCount() ) + throw std::out_of_range( "TestPath::insert(): index out of range" ); + m_tests.insert( m_tests.begin() + index, test ); +} + +void +TestPath::insert( const TestPath &path, + int index ) +{ + int itemIndex = path.getTestCount() -1; + while ( itemIndex >= 0 ) + insert( path.getTestAt( itemIndex-- ), index ); +} + + +void +TestPath::removeTests() +{ + while ( isValid() ) + removeTest( 0 ); +} + + +void +TestPath::removeTest( int index ) +{ + checkIndexValid( index ); + m_tests.erase( m_tests.begin() + index ); +} + + +void +TestPath::up() +{ + checkIndexValid( 0 ); + removeTest( getTestCount() -1 ); +} + + +int +TestPath::getTestCount() const +{ + return m_tests.size(); +} + + +Test * +TestPath::getTestAt( int index ) const +{ + checkIndexValid( index ); + return m_tests[index]; +} + + +Test * +TestPath::getChildTest() const +{ + return getTestAt( getTestCount() -1 ); +} + + +void +TestPath::checkIndexValid( int index ) const +{ + if ( index < 0 || index >= getTestCount() ) + throw std::out_of_range( "TestPath::checkIndexValid(): index out of range" ); +} + + +std::string +TestPath::toString() const +{ + std::string asString( "/" ); + for ( int index =0; index < getTestCount(); ++index ) + { + if ( index > 0 ) + asString += '/'; + asString += getTestAt(index)->getName(); + } + + return asString; +} + + +Test * +TestPath::findActualRoot( Test *searchRoot, + const std::string &pathAsString, + PathTestNames &testNames ) +{ + bool isRelative = splitPathString( pathAsString, testNames ); + + if ( isRelative && pathAsString.empty() ) + return searchRoot; + + if ( testNames.empty() ) + throw std::invalid_argument( "TestPath::TestPath(): invalid root or root name in absolute path" ); + + Test *root = isRelative ? searchRoot->findTest( testNames[0] ) // throw if bad test name + : searchRoot; + if ( root->getName() != testNames[0] ) + throw std::invalid_argument( "TestPath::TestPath(): searchRoot does not match path root name" ); + + return root; +} + + +bool +TestPath::splitPathString( const std::string &pathAsString, + PathTestNames &testNames ) +{ + if ( pathAsString.empty() ) + return true; + + bool isRelative = pathAsString[0] != '/'; + + int index = (isRelative ? 0 : 1); + while ( true ) + { + int separatorIndex = pathAsString.find( '/', index ); + if ( separatorIndex >= 0 ) + { + testNames.push_back( pathAsString.substr( index, separatorIndex - index ) ); + index = separatorIndex + 1; + } + else + { + testNames.push_back( pathAsString.substr( index ) ); + break; + } + } + + return isRelative; +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/TestPlugInDefaultImpl.cpp b/UnitTests/cppunit/src/cppunit/TestPlugInDefaultImpl.cpp new file mode 100644 index 0000000..086dea0 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestPlugInDefaultImpl.cpp @@ -0,0 +1,63 @@ +#include + +#if !defined(CPPUNIT_NO_TESTPLUGIN) + +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +TestPlugInDefaultImpl::TestPlugInDefaultImpl() +{ +} + + +TestPlugInDefaultImpl::~TestPlugInDefaultImpl() +{ +} + + +void +TestPlugInDefaultImpl::initialize( TestFactoryRegistry *, + const PlugInParameters & ) +{ +} + + +void +TestPlugInDefaultImpl::addListener( TestResult * ) +{ +} + + +void +TestPlugInDefaultImpl::removeListener( TestResult * ) +{ +} + + +void +TestPlugInDefaultImpl::addXmlOutputterHooks( XmlOutputter * ) +{ +} + + +void +TestPlugInDefaultImpl::removeXmlOutputterHooks() +{ +} + + +void +TestPlugInDefaultImpl::uninitialize( TestFactoryRegistry * ) +{ +} + + +CPPUNIT_NS_END + + +#endif // !defined(CPPUNIT_NO_TESTPLUGIN) diff --git a/UnitTests/cppunit/src/cppunit/TestResult.cpp b/UnitTests/cppunit/src/cppunit/TestResult.cpp new file mode 100644 index 0000000..4b02c30 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestResult.cpp @@ -0,0 +1,199 @@ +#include +#include +#include +#include +#include +#include +#include +#include "DefaultProtector.h" +#include "ProtectorChain.h" +#include "ProtectorContext.h" + +CPPUNIT_NS_BEGIN + + +TestResult::TestResult( SynchronizationObject *syncObject ) + : SynchronizedObject( syncObject ) + , m_protectorChain( new ProtectorChain() ) + , m_stop( false ) +{ + m_protectorChain->push( new DefaultProtector() ); +} + + +TestResult::~TestResult() +{ + stdCOut().flush(); + stdCErr().flush(); + delete m_protectorChain; +} + + +void +TestResult::reset() +{ + ExclusiveZone zone( m_syncObject ); + m_stop = false; +} + + +void +TestResult::addError( Test *test, + Exception *e ) +{ + TestFailure failure( test, e, true ); + addFailure( failure ); +} + + +void +TestResult::addFailure( Test *test, Exception *e ) +{ + TestFailure failure( test, e, false ); + addFailure( failure ); +} + + +void +TestResult::addFailure( const TestFailure &failure ) +{ + ExclusiveZone zone( m_syncObject ); + for ( TestListeners::iterator it = m_listeners.begin(); + it != m_listeners.end(); + ++it ) + (*it)->addFailure( failure ); +} + + +void +TestResult::startTest( Test *test ) +{ + ExclusiveZone zone( m_syncObject ); + for ( TestListeners::iterator it = m_listeners.begin(); + it != m_listeners.end(); + ++it ) + (*it)->startTest( test ); +} + + +void +TestResult::endTest( Test *test ) +{ + ExclusiveZone zone( m_syncObject ); + for ( TestListeners::iterator it = m_listeners.begin(); + it != m_listeners.end(); + ++it ) + (*it)->endTest( test ); +} + + +void +TestResult::startSuite( Test *test ) +{ + ExclusiveZone zone( m_syncObject ); + for ( TestListeners::iterator it = m_listeners.begin(); + it != m_listeners.end(); + ++it ) + (*it)->startSuite( test ); +} + + +void +TestResult::endSuite( Test *test ) +{ + ExclusiveZone zone( m_syncObject ); + for ( TestListeners::iterator it = m_listeners.begin(); + it != m_listeners.end(); + ++it ) + (*it)->endSuite( test ); +} + + +bool +TestResult::shouldStop() const +{ + ExclusiveZone zone( m_syncObject ); + return m_stop; +} + + +void +TestResult::stop() +{ + ExclusiveZone zone( m_syncObject ); + m_stop = true; +} + + +void +TestResult::addListener( TestListener *listener ) +{ + ExclusiveZone zone( m_syncObject ); + m_listeners.push_back( listener ); +} + + +void +TestResult::removeListener ( TestListener *listener ) +{ + ExclusiveZone zone( m_syncObject ); + removeFromSequence( m_listeners, listener ); +} + + +void +TestResult::runTest( Test *test ) +{ + startTestRun( test ); + test->run( this ); + endTestRun( test ); +} + + +void +TestResult::startTestRun( Test *test ) +{ + ExclusiveZone zone( m_syncObject ); + for ( TestListeners::iterator it = m_listeners.begin(); + it != m_listeners.end(); + ++it ) + (*it)->startTestRun( test, this ); +} + + +void +TestResult::endTestRun( Test *test ) +{ + ExclusiveZone zone( m_syncObject ); + for ( TestListeners::iterator it = m_listeners.begin(); + it != m_listeners.end(); + ++it ) + (*it)->endTestRun( test, this ); +} + + +bool +TestResult::protect( const Functor &functor, + Test *test, + const std::string &shortDescription ) +{ + ProtectorContext context( test, this, shortDescription ); + return m_protectorChain->protect( functor, context ); +} + + +void +TestResult::pushProtector( Protector *protector ) +{ + m_protectorChain->push( protector ); +} + + +void +TestResult::popProtector() +{ + m_protectorChain->pop(); +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/TestResultCollector.cpp b/UnitTests/cppunit/src/cppunit/TestResultCollector.cpp new file mode 100644 index 0000000..4371c50 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestResultCollector.cpp @@ -0,0 +1,117 @@ +#include +#include + + +CPPUNIT_NS_BEGIN + + +TestResultCollector::TestResultCollector( SynchronizationObject *syncObject ) + : TestSuccessListener( syncObject ) +{ + reset(); +} + + +TestResultCollector::~TestResultCollector() +{ + freeFailures(); +} + + +void +TestResultCollector::freeFailures() +{ + TestFailures::iterator itFailure = m_failures.begin(); + while ( itFailure != m_failures.end() ) + delete *itFailure++; + m_failures.clear(); +} + + +void +TestResultCollector::reset() +{ + TestSuccessListener::reset(); + + ExclusiveZone zone( m_syncObject ); + freeFailures(); + m_testErrors = 0; + m_tests.clear(); +} + + +void +TestResultCollector::startTest( Test *test ) +{ + ExclusiveZone zone (m_syncObject); + m_tests.push_back( test ); +} + + +void +TestResultCollector::addFailure( const TestFailure &failure ) +{ + TestSuccessListener::addFailure( failure ); + + ExclusiveZone zone( m_syncObject ); + if ( failure.isError() ) + ++m_testErrors; + m_failures.push_back( failure.clone() ); +} + + +/// Gets the number of run tests. +int +TestResultCollector::runTests() const +{ + ExclusiveZone zone( m_syncObject ); + return m_tests.size(); +} + + +/// Gets the number of detected errors (uncaught exception). +int +TestResultCollector::testErrors() const +{ + ExclusiveZone zone( m_syncObject ); + return m_testErrors; +} + + +/// Gets the number of detected failures (failed assertion). +int +TestResultCollector::testFailures() const +{ + ExclusiveZone zone( m_syncObject ); + return m_failures.size() - m_testErrors; +} + + +/// Gets the total number of detected failures. +int +TestResultCollector::testFailuresTotal() const +{ + ExclusiveZone zone( m_syncObject ); + return m_failures.size(); +} + + +/// Returns a the list failures (random access collection). +const TestResultCollector::TestFailures & +TestResultCollector::failures() const +{ + ExclusiveZone zone( m_syncObject ); + return m_failures; +} + + +const TestResultCollector::Tests & +TestResultCollector::tests() const +{ + ExclusiveZone zone( m_syncObject ); + return m_tests; +} + + +CPPUNIT_NS_END + diff --git a/UnitTests/cppunit/src/cppunit/TestRunner.cpp b/UnitTests/cppunit/src/cppunit/TestRunner.cpp new file mode 100644 index 0000000..8d95a63 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestRunner.cpp @@ -0,0 +1,101 @@ +#include +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +TestRunner::WrappingSuite::WrappingSuite( const std::string &name ) + : TestSuite( name ) +{ +} + + +int +TestRunner::WrappingSuite::getChildTestCount() const +{ + if ( hasOnlyOneTest() ) + return getUniqueChildTest()->getChildTestCount(); + return TestSuite::getChildTestCount(); +} + + +std::string +TestRunner::WrappingSuite::getName() const +{ + if ( hasOnlyOneTest() ) + return getUniqueChildTest()->getName(); + return TestSuite::getName(); +} + + +Test * +TestRunner::WrappingSuite::doGetChildTestAt( int index ) const +{ + if ( hasOnlyOneTest() ) + return getUniqueChildTest()->getChildTestAt( index ); + return TestSuite::doGetChildTestAt( index ); +} + + +void +TestRunner::WrappingSuite::run( TestResult *result ) +{ + if ( hasOnlyOneTest() ) + getUniqueChildTest()->run( result ); + else + TestSuite::run( result ); +} + + +bool +TestRunner::WrappingSuite::hasOnlyOneTest() const +{ + return TestSuite::getChildTestCount() == 1; +} + + +Test * +TestRunner::WrappingSuite::getUniqueChildTest() const +{ + return TestSuite::doGetChildTestAt( 0 ); +} + + + + + +TestRunner::TestRunner() + : m_suite( new WrappingSuite() ) +{ +} + + +TestRunner::~TestRunner() +{ + delete m_suite; +} + + +void +TestRunner::addTest( Test *test ) +{ + m_suite->addTest( test ); +} + + +void +TestRunner::run( TestResult &controller, + const std::string &testPath ) +{ + TestPath path = m_suite->resolveTestPath( testPath ); + Test *testToRun = path.getChildTest(); + + controller.runTest( testToRun ); +} + + +CPPUNIT_NS_END + diff --git a/UnitTests/cppunit/src/cppunit/TestSetUp.cpp b/UnitTests/cppunit/src/cppunit/TestSetUp.cpp new file mode 100644 index 0000000..d4d8530 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestSetUp.cpp @@ -0,0 +1,32 @@ +#include + +CPPUNIT_NS_BEGIN + + +TestSetUp::TestSetUp( Test *test ) : TestDecorator( test ) +{ +} + + +void +TestSetUp::setUp() +{ +} + + +void +TestSetUp::tearDown() +{ +} + + +void +TestSetUp::run( TestResult *result ) +{ + setUp(); + TestDecorator::run(result); + tearDown(); +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/TestSuccessListener.cpp b/UnitTests/cppunit/src/cppunit/TestSuccessListener.cpp new file mode 100644 index 0000000..a5572a9 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestSuccessListener.cpp @@ -0,0 +1,44 @@ +#include + + +CPPUNIT_NS_BEGIN + + +TestSuccessListener::TestSuccessListener( SynchronizationObject *syncObject ) + : SynchronizedObject( syncObject ) + , m_success( true ) +{ +} + + +TestSuccessListener::~TestSuccessListener() +{ +} + + +void +TestSuccessListener::reset() +{ + ExclusiveZone zone( m_syncObject ); + m_success = true; +} + + +void +TestSuccessListener::addFailure( const TestFailure & ) +{ + ExclusiveZone zone( m_syncObject ); + m_success = false; +} + + +bool +TestSuccessListener::wasSuccessful() const +{ + ExclusiveZone zone( m_syncObject ); + return m_success; +} + + +CPPUNIT_NS_END + diff --git a/UnitTests/cppunit/src/cppunit/TestSuite.cpp b/UnitTests/cppunit/src/cppunit/TestSuite.cpp new file mode 100644 index 0000000..8dd2ea6 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestSuite.cpp @@ -0,0 +1,64 @@ +#include +#include +#include + +CPPUNIT_NS_BEGIN + + +/// Default constructor +TestSuite::TestSuite( std::string name ) + : TestComposite( name ) +{ +} + + +/// Destructor +TestSuite::~TestSuite() +{ + deleteContents(); +} + + +/// Deletes all tests in the suite. +void +TestSuite::deleteContents() +{ + int childCount = getChildTestCount(); + for ( int index =0; index < childCount; ++index ) + delete getChildTestAt( index ); + + m_tests.clear(); +} + + +/// Adds a test to the suite. +void +TestSuite::addTest( Test *test ) +{ + m_tests.push_back( test ); +} + + +const CppUnitVector & +TestSuite::getTests() const +{ + return m_tests; +} + + +int +TestSuite::getChildTestCount() const +{ + return m_tests.size(); +} + + +Test * +TestSuite::doGetChildTestAt( int index ) const +{ + return m_tests[index]; +} + + +CPPUNIT_NS_END + diff --git a/UnitTests/cppunit/src/cppunit/TestSuiteBuilderContext.cpp b/UnitTests/cppunit/src/cppunit/TestSuiteBuilderContext.cpp new file mode 100644 index 0000000..ff71b52 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TestSuiteBuilderContext.cpp @@ -0,0 +1,85 @@ +#include +#include +#include +#include + + +CPPUNIT_NS_BEGIN + +TestSuiteBuilderContextBase::TestSuiteBuilderContextBase( + TestSuite &suite, + const TestNamer &namer, + TestFixtureFactory &factory ) + : m_suite( suite ) + , m_namer( namer ) + , m_factory( factory ) +{ +} + + +TestSuiteBuilderContextBase::~TestSuiteBuilderContextBase() +{ +} + + +void +TestSuiteBuilderContextBase::addTest( Test *test ) +{ + m_suite.addTest( test ); +} + + +std::string +TestSuiteBuilderContextBase::getFixtureName() const +{ + return m_namer.getFixtureName(); +} + + +std::string +TestSuiteBuilderContextBase::getTestNameFor( + const std::string &testMethodName ) const +{ + return m_namer.getTestNameFor( testMethodName ); +} + + +TestFixture * +TestSuiteBuilderContextBase::makeTestFixture() const +{ + return m_factory.makeFixture(); +} + + +void +TestSuiteBuilderContextBase::addProperty( const std::string &key, + const std::string &value ) +{ + Properties::iterator it = m_properties.begin(); + for ( ; it != m_properties.end(); ++it ) + { + if ( (*it).first == key ) + { + (*it).second = value; + return; + } + } + + Property property( key, value ); + m_properties.push_back( property ); +} + +const std::string +TestSuiteBuilderContextBase::getStringProperty( const std::string &key ) const +{ + Properties::const_iterator it = m_properties.begin(); + for ( ; it != m_properties.end(); ++it ) + { + if ( (*it).first == key ) + return (*it).second; + } + return ""; +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/TextOutputter.cpp b/UnitTests/cppunit/src/cppunit/TextOutputter.cpp new file mode 100644 index 0000000..f74214f --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TextOutputter.cpp @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +TextOutputter::TextOutputter( TestResultCollector *result, + OStream &stream ) + : m_result( result ) + , m_stream( stream ) +{ +} + + +TextOutputter::~TextOutputter() +{ +} + + +void +TextOutputter::write() +{ + printHeader(); + m_stream << "\n"; + printFailures(); + m_stream << "\n"; +} + + +void +TextOutputter::printFailures() +{ + TestResultCollector::TestFailures::const_iterator itFailure = m_result->failures().begin(); + int failureNumber = 1; + while ( itFailure != m_result->failures().end() ) + { + m_stream << "\n"; + printFailure( *itFailure++, failureNumber++ ); + } +} + + +void +TextOutputter::printFailure( TestFailure *failure, + int failureNumber ) +{ + printFailureListMark( failureNumber ); + m_stream << ' '; + printFailureTestName( failure ); + m_stream << ' '; + printFailureType( failure ); + m_stream << ' '; + printFailureLocation( failure->sourceLine() ); + m_stream << "\n"; + printFailureDetail( failure->thrownException() ); + m_stream << "\n"; +} + + +void +TextOutputter::printFailureListMark( int failureNumber ) +{ + m_stream << failureNumber << ")"; +} + + +void +TextOutputter::printFailureTestName( TestFailure *failure ) +{ + m_stream << "test: " << failure->failedTestName(); +} + + +void +TextOutputter::printFailureType( TestFailure *failure ) +{ + m_stream << "(" + << (failure->isError() ? "E" : "F") + << ")"; +} + + +void +TextOutputter::printFailureLocation( SourceLine sourceLine ) +{ + if ( !sourceLine.isValid() ) + return; + + m_stream << "line: " << sourceLine.lineNumber() + << ' ' << sourceLine.fileName(); +} + + +void +TextOutputter::printFailureDetail( Exception *thrownException ) +{ + m_stream << thrownException->message().shortDescription() << "\n"; + m_stream << thrownException->message().details(); +} + + +void +TextOutputter::printHeader() +{ + if ( m_result->wasSuccessful() ) + m_stream << "\nOK (" << m_result->runTests () << " tests)\n" ; + else + { + m_stream << "\n"; + printFailureWarning(); + printStatistics(); + } +} + + +void +TextOutputter::printFailureWarning() +{ + m_stream << "!!!FAILURES!!!\n"; +} + + +void +TextOutputter::printStatistics() +{ + m_stream << "Test Results:\n"; + + m_stream << "Run: " << m_result->runTests() + << " Failures: " << m_result->testFailures() + << " Errors: " << m_result->testErrors() + << "\n"; +} + + +CPPUNIT_NS_END + diff --git a/UnitTests/cppunit/src/cppunit/TextTestProgressListener.cpp b/UnitTests/cppunit/src/cppunit/TextTestProgressListener.cpp new file mode 100644 index 0000000..ea4fb17 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TextTestProgressListener.cpp @@ -0,0 +1,45 @@ +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +TextTestProgressListener::TextTestProgressListener() +{ +} + + +TextTestProgressListener::~TextTestProgressListener() +{ +} + + +void +TextTestProgressListener::startTest( Test * ) +{ + stdCOut() << "."; + stdCOut().flush(); +} + + +void +TextTestProgressListener::addFailure( const TestFailure &failure ) +{ + stdCOut() << ( failure.isError() ? "E" : "F" ); + stdCOut().flush(); +} + + +void +TextTestProgressListener::endTestRun( Test *, + TestResult * ) +{ + stdCOut() << "\n"; + stdCOut().flush(); +} + + +CPPUNIT_NS_END + diff --git a/UnitTests/cppunit/src/cppunit/TextTestResult.cpp b/UnitTests/cppunit/src/cppunit/TextTestResult.cpp new file mode 100644 index 0000000..871eb6d --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TextTestResult.cpp @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +TextTestResult::TextTestResult() +{ + addListener( this ); +} + + +void +TextTestResult::addFailure( const TestFailure &failure ) +{ + TestResultCollector::addFailure( failure ); + stdCOut() << ( failure.isError() ? "E" : "F" ); +} + + +void +TextTestResult::startTest( Test *test ) +{ + TestResultCollector::startTest (test); + stdCOut() << "."; +} + + +void +TextTestResult::print( OStream &stream ) +{ + TextOutputter outputter( this, stream ); + outputter.write(); +} + + +OStream & +operator <<( OStream &stream, + TextTestResult &result ) +{ + result.print (stream); return stream; +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/TextTestRunner.cpp b/UnitTests/cppunit/src/cppunit/TextTestRunner.cpp new file mode 100644 index 0000000..1534ec0 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TextTestRunner.cpp @@ -0,0 +1,144 @@ +// ==> Implementation of cppunit/ui/text/TestRunner.h + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +/*! Constructs a new text runner. + * \param outputter used to print text result. Owned by the runner. + */ +TextTestRunner::TextTestRunner( Outputter *outputter ) + : m_result( new TestResultCollector() ) + , m_eventManager( new TestResult() ) + , m_outputter( outputter ) +{ + if ( !m_outputter ) + m_outputter = new TextOutputter( m_result, stdCOut() ); + m_eventManager->addListener( m_result ); +} + + +TextTestRunner::~TextTestRunner() +{ + delete m_eventManager; + delete m_outputter; + delete m_result; +} + + +/*! Runs the named test case. + * + * \param testName Name of the test case to run. If an empty is given, then + * all added tests are run. The name can be the name of any + * test in the hierarchy. + * \param doWait if \c true then the user must press the RETURN key + * before the run() method exit. + * \param doPrintResult if \c true (default) then the test result are printed + * on the standard output. + * \param doPrintProgress if \c true (default) then TextTestProgressListener is + * used to show the progress. + * \return \c true is the test was successful, \c false if the test + * failed or was not found. + */ +bool +TextTestRunner::run( std::string testName, + bool doWait, + bool doPrintResult, + bool doPrintProgress ) +{ + TextTestProgressListener progress; + if ( doPrintProgress ) + m_eventManager->addListener( &progress ); + + TestRunner *pThis = this; + pThis->run( *m_eventManager, testName ); + + if ( doPrintProgress ) + m_eventManager->removeListener( &progress ); + + printResult( doPrintResult ); + wait( doWait ); + + return m_result->wasSuccessful(); +} + + +void +TextTestRunner::wait( bool doWait ) +{ +#if !defined( CPPUNIT_NO_STREAM ) + if ( doWait ) + { + stdCOut() << " to continue\n"; + stdCOut().flush(); + std::cin.get (); + } +#endif +} + + +void +TextTestRunner::printResult( bool doPrintResult ) +{ + stdCOut() << "\n"; + if ( doPrintResult ) + m_outputter->write(); +} + + +/*! Returns the result of the test run. + * Use this after calling run() to access the result of the test run. + */ +TestResultCollector & +TextTestRunner::result() const +{ + return *m_result; +} + + +/*! Returns the event manager. + * The instance of TestResult results returned is the one that is used to run the + * test. Use this to register additional TestListener before running the tests. + */ +TestResult & +TextTestRunner::eventManager() const +{ + return *m_eventManager; +} + + +/*! Specifies an alternate outputter. + * + * Notes that the outputter will be use after the test run only if \a printResult was + * \c true. + * \param outputter New outputter to use. The previous outputter is destroyed. + * The TextTestRunner assumes ownership of the outputter. + * \see CompilerOutputter, XmlOutputter, TextOutputter. + */ +void +TextTestRunner::setOutputter( Outputter *outputter ) +{ + delete m_outputter; + m_outputter = outputter; +} + + +void +TextTestRunner::run( TestResult &controller, + const std::string &testPath ) +{ + TestRunner::run( controller, testPath ); +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/TypeInfoHelper.cpp b/UnitTests/cppunit/src/cppunit/TypeInfoHelper.cpp new file mode 100644 index 0000000..ff1d662 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/TypeInfoHelper.cpp @@ -0,0 +1,54 @@ +#include +#include + +#if CPPUNIT_HAVE_RTTI + +#include + +#if CPPUNIT_HAVE_GCC_ABI_DEMANGLE +#include +#include +#endif + + +CPPUNIT_NS_BEGIN + + +std::string +TypeInfoHelper::getClassName( const std::type_info &info ) +{ +#if defined(CPPUNIT_HAVE_GCC_ABI_DEMANGLE) && CPPUNIT_HAVE_GCC_ABI_DEMANGLE + + int status = 0; + char* c_name = 0; + + c_name = abi::__cxa_demangle( info.name(), 0, 0, &status ); + + std::string name( c_name ); + free( c_name ); + +#else // CPPUNIT_HAVE_GCC_ABI_DEMANGLE + + static std::string classPrefix( "class " ); + std::string name( info.name() ); + + // Work around gcc 3.0 bug: strip number before type name. + unsigned int firstNotDigitIndex = 0; + while ( firstNotDigitIndex < name.length() && + name[firstNotDigitIndex] >= '0' && + name[firstNotDigitIndex] <= '9' ) + ++firstNotDigitIndex; + name = name.substr( firstNotDigitIndex ); + + if ( name.substr( 0, classPrefix.length() ) == classPrefix ) + return name.substr( classPrefix.length() ); + +#endif // CPPUNIT_HAVE_GCC_ABI_DEMANGLE + + return name; +} + + +CPPUNIT_NS_END + +#endif // CPPUNIT_HAVE_RTTI diff --git a/UnitTests/cppunit/src/cppunit/UnixDynamicLibraryManager.cpp b/UnitTests/cppunit/src/cppunit/UnixDynamicLibraryManager.cpp new file mode 100644 index 0000000..f235cce --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/UnixDynamicLibraryManager.cpp @@ -0,0 +1,44 @@ +#include + +#if defined(CPPUNIT_HAVE_UNIX_DLL_LOADER) +#include + +#include +#include + + +CPPUNIT_NS_BEGIN + + +DynamicLibraryManager::LibraryHandle +DynamicLibraryManager::doLoadLibrary( const std::string &libraryName ) +{ + return ::dlopen( libraryName.c_str(), RTLD_NOW | RTLD_GLOBAL ); +} + + +void +DynamicLibraryManager::doReleaseLibrary() +{ + ::dlclose( m_libraryHandle); +} + + +DynamicLibraryManager::Symbol +DynamicLibraryManager::doFindSymbol( const std::string &symbol ) +{ + return ::dlsym ( m_libraryHandle, symbol.c_str() ); +} + + +std::string +DynamicLibraryManager::getLastErrorDetail() const +{ + return ""; +} + + +CPPUNIT_NS_END + + +#endif // defined(CPPUNIT_HAVE_UNIX_DLL_LOADER) diff --git a/UnitTests/cppunit/src/cppunit/Win32DynamicLibraryManager.cpp b/UnitTests/cppunit/src/cppunit/Win32DynamicLibraryManager.cpp new file mode 100644 index 0000000..acadf46 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/Win32DynamicLibraryManager.cpp @@ -0,0 +1,73 @@ +#include + +#if defined(CPPUNIT_HAVE_WIN32_DLL_LOADER) +#include + +#define WIN32_LEAN_AND_MEAN +#define NOGDI +#define NOUSER +#define NOKERNEL +#define NOSOUND +#define NOMINMAX +#define BLENDFUNCTION void // for mingw & gcc +#include + + +CPPUNIT_NS_BEGIN + + +DynamicLibraryManager::LibraryHandle +DynamicLibraryManager::doLoadLibrary( const std::string &libraryName ) +{ + return ::LoadLibraryA( libraryName.c_str() ); +} + + +void +DynamicLibraryManager::doReleaseLibrary() +{ + ::FreeLibrary( (HINSTANCE)m_libraryHandle ); +} + + +DynamicLibraryManager::Symbol +DynamicLibraryManager::doFindSymbol( const std::string &symbol ) +{ + return (DynamicLibraryManager::Symbol)::GetProcAddress( + (HINSTANCE)m_libraryHandle, + symbol.c_str() ); +} + + +std::string +DynamicLibraryManager::getLastErrorDetail() const +{ + LPVOID lpMsgBuf; + ::FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPSTR) &lpMsgBuf, + 0, + NULL + ); + + std::string message = (LPCSTR)lpMsgBuf; + + // Display the string. +// ::MessageBoxA( NULL, (LPCSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION ); + + // Free the buffer. + ::LocalFree( lpMsgBuf ); + + return message; +} + + +CPPUNIT_NS_END + + +#endif // defined(CPPUNIT_HAVE_WIN32_DLL_LOADER) diff --git a/UnitTests/cppunit/src/cppunit/XmlDocument.cpp b/UnitTests/cppunit/src/cppunit/XmlDocument.cpp new file mode 100644 index 0000000..31f9115 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/XmlDocument.cpp @@ -0,0 +1,106 @@ +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +XmlDocument::XmlDocument( const std::string &encoding, + const std::string &styleSheet ) + : m_styleSheet( styleSheet ) + , m_rootElement( new XmlElement( "DummyRoot" ) ) + , m_standalone( true ) +{ + setEncoding( encoding ); +} + + +XmlDocument::~XmlDocument() +{ + delete m_rootElement; +} + + + +std::string +XmlDocument::encoding() const +{ + return m_encoding; +} + + +void +XmlDocument::setEncoding( const std::string &encoding ) +{ + m_encoding = encoding.empty() ? std::string("ISO-8859-1") : encoding; +} + + +std::string +XmlDocument::styleSheet() const +{ + return m_styleSheet; +} + + +void +XmlDocument::setStyleSheet( const std::string &styleSheet ) +{ + m_styleSheet = styleSheet; +} + + +bool +XmlDocument::standalone() const +{ + return m_standalone; +} + + +void +XmlDocument::setStandalone( bool standalone ) +{ + m_standalone = standalone; +} + + +void +XmlDocument::setRootElement( XmlElement *rootElement ) +{ + if ( rootElement == m_rootElement ) + return; + + delete m_rootElement; + m_rootElement = rootElement; +} + + +XmlElement & +XmlDocument::rootElement() const +{ + return *m_rootElement; +} + + +std::string +XmlDocument::toString() const +{ + std::string asString = "\n"; + + if ( !m_styleSheet.empty() ) + asString += "\n"; + + asString += m_rootElement->toString(); + + return asString; +} + + +CPPUNIT_NS_END + diff --git a/UnitTests/cppunit/src/cppunit/XmlElement.cpp b/UnitTests/cppunit/src/cppunit/XmlElement.cpp new file mode 100644 index 0000000..f930ad4 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/XmlElement.cpp @@ -0,0 +1,226 @@ +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +XmlElement::XmlElement( std::string elementName, + std::string content ) + : m_name( elementName ) + , m_content( content ) +{ +} + + +XmlElement::XmlElement( std::string elementName, + int numericContent ) + : m_name( elementName ) +{ + setContent( numericContent ); +} + + +XmlElement::~XmlElement() +{ + Elements::iterator itNode = m_elements.begin(); + while ( itNode != m_elements.end() ) + { + XmlElement *element = *itNode++; + delete element; + } +} + + +std::string +XmlElement::name() const +{ + return m_name; +} + + +std::string +XmlElement::content() const +{ + return m_content; +} + + +void +XmlElement::setName( const std::string &name ) +{ + m_name = name; +} + + +void +XmlElement::setContent( const std::string &content ) +{ + m_content = content; +} + + +void +XmlElement::setContent( int numericContent ) +{ + m_content = StringTools::toString( numericContent ); +} + + +void +XmlElement::addAttribute( std::string attributeName, + std::string value ) +{ + m_attributes.push_back( Attribute( attributeName, value ) ); +} + + +void +XmlElement::addAttribute( std::string attributeName, + int numericValue ) +{ + addAttribute( attributeName, StringTools::toString( numericValue ) ); +} + + +void +XmlElement::addElement( XmlElement *node ) +{ + m_elements.push_back( node ); +} + + +int +XmlElement::elementCount() const +{ + return m_elements.size(); +} + + +XmlElement * +XmlElement::elementAt( int index ) const +{ + if ( index < 0 || index >= elementCount() ) + throw std::invalid_argument( "XmlElement::elementAt(), out of range index" ); + + return m_elements[ index ]; +} + + +XmlElement * +XmlElement::elementFor( const std::string &name ) const +{ + Elements::const_iterator itElement = m_elements.begin(); + for ( ; itElement != m_elements.end(); ++itElement ) + { + if ( (*itElement)->name() == name ) + return *itElement; + } + + throw std::invalid_argument( "XmlElement::elementFor(), not matching child element found" ); + return NULL; // make some compilers happy. +} + + +std::string +XmlElement::toString( const std::string &indent ) const +{ + std::string element( indent ); + element += "<"; + element += m_name; + if ( !m_attributes.empty() ) + { + element += " "; + element += attributesAsString(); + } + element += ">"; + + if ( !m_elements.empty() ) + { + element += "\n"; + + std::string subNodeIndent( indent + " " ); + Elements::const_iterator itNode = m_elements.begin(); + while ( itNode != m_elements.end() ) + { + const XmlElement *node = *itNode++; + element += node->toString( subNodeIndent ); + } + + element += indent; + } + + if ( !m_content.empty() ) + { + element += escape( m_content ); + if ( !m_elements.empty() ) + { + element += "\n"; + element += indent; + } + } + + element += "\n"; + + return element; +} + + +std::string +XmlElement::attributesAsString() const +{ + std::string attributes; + Attributes::const_iterator itAttribute = m_attributes.begin(); + while ( itAttribute != m_attributes.end() ) + { + if ( !attributes.empty() ) + attributes += " "; + + const Attribute &attribute = *itAttribute++; + attributes += attribute.first; + attributes += "=\""; + attributes += escape( attribute.second ); + attributes += "\""; + } + return attributes; +} + + +std::string +XmlElement::escape( std::string value ) const +{ + std::string escaped; + for ( unsigned int index =0; index < value.length(); ++index ) + { + char c = value[index ]; + switch ( c ) // escape all predefined XML entity (safe?) + { + case '<': + escaped += "<"; + break; + case '>': + escaped += ">"; + break; + case '&': + escaped += "&"; + break; + case '\'': + escaped += "'"; + break; + case '"': + escaped += """; + break; + default: + escaped += c; + } + } + + return escaped; +} + + +CPPUNIT_NS_END + diff --git a/UnitTests/cppunit/src/cppunit/XmlOutputter.cpp b/UnitTests/cppunit/src/cppunit/XmlOutputter.cpp new file mode 100644 index 0000000..c605e33 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/XmlOutputter.cpp @@ -0,0 +1,205 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +XmlOutputter::XmlOutputter( TestResultCollector *result, + OStream &stream, + std::string encoding ) + : m_result( result ) + , m_stream( stream ) + , m_xml( new XmlDocument( encoding ) ) +{ +} + + +XmlOutputter::~XmlOutputter() +{ + delete m_xml; +} + + +void +XmlOutputter::addHook( XmlOutputterHook *hook ) +{ + m_hooks.push_back( hook ); +} + + +void +XmlOutputter::removeHook( XmlOutputterHook *hook ) +{ + m_hooks.erase( std::find( m_hooks.begin(), m_hooks.end(), hook ) ); +} + + +void +XmlOutputter::write() +{ + setRootNode(); + m_stream << m_xml->toString(); +} + + +void +XmlOutputter::setStyleSheet( const std::string &styleSheet ) +{ + m_xml->setStyleSheet( styleSheet ); +} + + +void +XmlOutputter::setStandalone( bool standalone ) +{ + m_xml->setStandalone( standalone ); +} + + +void +XmlOutputter::setRootNode() +{ + XmlElement *rootNode = new XmlElement( "TestRun" ); + m_xml->setRootElement( rootNode ); + + for ( Hooks::iterator it = m_hooks.begin(); it != m_hooks.end(); ++it ) + (*it)->beginDocument( m_xml ); + + FailedTests failedTests; + fillFailedTestsMap( failedTests ); + + addFailedTests( failedTests, rootNode ); + addSuccessfulTests( failedTests, rootNode ); + addStatistics( rootNode ); + + for ( Hooks::iterator itEnd = m_hooks.begin(); itEnd != m_hooks.end(); ++itEnd ) + (*itEnd)->endDocument( m_xml ); +} + + +void +XmlOutputter::fillFailedTestsMap( FailedTests &failedTests ) +{ + const TestResultCollector::TestFailures &failures = m_result->failures(); + TestResultCollector::TestFailures::const_iterator itFailure = failures.begin(); + while ( itFailure != failures.end() ) + { + TestFailure *failure = *itFailure++; + failedTests.insert( std::pair(failure->failedTest(), failure ) ); + } +} + + +void +XmlOutputter::addFailedTests( FailedTests &failedTests, + XmlElement *rootNode ) +{ + XmlElement *testsNode = new XmlElement( "FailedTests" ); + rootNode->addElement( testsNode ); + + const TestResultCollector::Tests &tests = m_result->tests(); + for ( unsigned int testNumber = 0; testNumber < tests.size(); ++testNumber ) + { + Test *test = tests[testNumber]; + if ( failedTests.find( test ) != failedTests.end() ) + addFailedTest( test, failedTests[test], testNumber+1, testsNode ); + } +} + + +void +XmlOutputter::addSuccessfulTests( FailedTests &failedTests, + XmlElement *rootNode ) +{ + XmlElement *testsNode = new XmlElement( "SuccessfulTests" ); + rootNode->addElement( testsNode ); + + const TestResultCollector::Tests &tests = m_result->tests(); + for ( unsigned int testNumber = 0; testNumber < tests.size(); ++testNumber ) + { + Test *test = tests[testNumber]; + if ( failedTests.find( test ) == failedTests.end() ) + addSuccessfulTest( test, testNumber+1, testsNode ); + } +} + + +void +XmlOutputter::addStatistics( XmlElement *rootNode ) +{ + XmlElement *statisticsElement = new XmlElement( "Statistics" ); + rootNode->addElement( statisticsElement ); + statisticsElement->addElement( new XmlElement( "Tests", m_result->runTests() ) ); + statisticsElement->addElement( new XmlElement( "FailuresTotal", + m_result->testFailuresTotal() ) ); + statisticsElement->addElement( new XmlElement( "Errors", m_result->testErrors() ) ); + statisticsElement->addElement( new XmlElement( "Failures", m_result->testFailures() ) ); + + for ( Hooks::iterator it = m_hooks.begin(); it != m_hooks.end(); ++it ) + (*it)->statisticsAdded( m_xml, statisticsElement ); +} + + +void +XmlOutputter::addFailedTest( Test *test, + TestFailure *failure, + int testNumber, + XmlElement *testsNode ) +{ + Exception *thrownException = failure->thrownException(); + + XmlElement *testElement = new XmlElement( "FailedTest" ); + testsNode->addElement( testElement ); + testElement->addAttribute( "id", testNumber ); + testElement->addElement( new XmlElement( "Name", test->getName() ) ); + testElement->addElement( new XmlElement( "FailureType", + failure->isError() ? "Error" : + "Assertion" ) ); + + if ( failure->sourceLine().isValid() ) + addFailureLocation( failure, testElement ); + + testElement->addElement( new XmlElement( "Message", thrownException->what() ) ); + + for ( Hooks::iterator it = m_hooks.begin(); it != m_hooks.end(); ++it ) + (*it)->failTestAdded( m_xml, testElement, test, failure ); +} + + +void +XmlOutputter::addFailureLocation( TestFailure *failure, + XmlElement *testElement ) +{ + XmlElement *locationNode = new XmlElement( "Location" ); + testElement->addElement( locationNode ); + SourceLine sourceLine = failure->sourceLine(); + locationNode->addElement( new XmlElement( "File", sourceLine.fileName() ) ); + locationNode->addElement( new XmlElement( "Line", sourceLine.lineNumber() ) ); +} + + +void +XmlOutputter::addSuccessfulTest( Test *test, + int testNumber, + XmlElement *testsNode ) +{ + XmlElement *testElement = new XmlElement( "Test" ); + testsNode->addElement( testElement ); + testElement->addAttribute( "id", testNumber ); + testElement->addElement( new XmlElement( "Name", test->getName() ) ); + + for ( Hooks::iterator it = m_hooks.begin(); it != m_hooks.end(); ++it ) + (*it)->successfulTestAdded( m_xml, testElement, test ); +} + + +CPPUNIT_NS_END diff --git a/UnitTests/cppunit/src/cppunit/XmlOutputterHook.cpp b/UnitTests/cppunit/src/cppunit/XmlOutputterHook.cpp new file mode 100644 index 0000000..53d10f6 --- /dev/null +++ b/UnitTests/cppunit/src/cppunit/XmlOutputterHook.cpp @@ -0,0 +1,44 @@ +#include + + +CPPUNIT_NS_BEGIN + + +void +XmlOutputterHook::beginDocument( XmlDocument * ) +{ +} + + +void +XmlOutputterHook::endDocument( XmlDocument * ) +{ +} + + +void +XmlOutputterHook::failTestAdded( XmlDocument *, + XmlElement *, + Test *, + TestFailure * ) +{ +} + + +void +XmlOutputterHook::successfulTestAdded( XmlDocument *, + XmlElement *, + Test * ) +{ +} + + +void +XmlOutputterHook::statisticsAdded( XmlDocument *, + XmlElement * ) +{ +} + + +CPPUNIT_NS_END + diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..8517cb1 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +2.80 diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 0000000..0505895 --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,3054 @@ +# checkbuild.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_SPLIT_TUPLE(TUPLE, OUTPUT-VARIABLES) +# Split a build-tuple into its component parts. A build tuple is +# constructed by CS_CREATE_TUPLE() and is comprised of compiler flags, +# linker flags, and library references. OUTPUT-VARIABLES is a +# comma-delimited list of shell variables which should receive the +# extracted compiler flags, linker flags, and library references, +# respectively. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_SPLIT_TUPLE], + [CS_SPLIT([$1], [cs_dummy,$2], [@]) + m4_map([_CS_SPLIT_TUPLE], [$2])]) + +AC_DEFUN([_CS_SPLIT_TUPLE], + [$1=`echo $$1 | sed 'y%@%:@% %'` + ]) + + + +#------------------------------------------------------------------------------ +# CS_CREATE_TUPLE([CFLAGS], [LFLAGS], [LIBS]) +# Construct a build-tuple which is comprised of compiler flags, linker +# flags, and library references. Build tuples are encoded so as to +# preserve whitespace in each component. This makes it possible for +# macros (such as CS_BUILD_IFELSE) which employ build tuples to accept +# whitespace-delimited lists of tuples, and for shell "for" statements to +# iterate over tuple lists without compromising whitespace embedded +# within individual flags or library references. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CREATE_TUPLE], [`echo @$1@$2@$3 | sed 'y% %@%:@%'`]) + + + +#------------------------------------------------------------------------------ +# CS_LANG_CFLAGS +# Return the literal string CFLAGS if the current language is C. Return +# the literal string CXXFLAGS if the current language is C++. Generic +# compiler test macros which need to modify or save the compiler flags +# can invoke this macro to get the name of the compiler flags environment +# variable (either CFLAGS or CXXFLAGS) depending upon the current +# language. For example: +# CS_LANG_CFLAGS="$CS_LANG_CFLAGS -Wall" +# With C, this expands to: +# CFLAGS="$CFLAGS -Wall" +# With C++, it expands to: +# CXXFLAGS="$CXXFLAGS -Wall" +#------------------------------------------------------------------------------ +AC_DEFUN([CS_LANG_CFLAGS], [AC_LANG_CASE([C], [CFLAGS], [C++], [CXXFLAGS])]) + + + +#------------------------------------------------------------------------------ +# CS_BUILD_IFELSE([PROGRAM], [FLAGS], [LANGUAGE], [ACTION-IF-BUILT], +# [ACTION-IF-NOT-BUILT], [OTHER-CFLAGS], [OTHER-LFLAGS], +# [OTHER-LIBS], [INHIBIT-OTHER-FLAGS], [ERROR-REGEX]) +# Try building a program using the supplied compiler flags, linker flags, +# and library references. PROGRAM is typically a program composed via +# AC_LANG_PROGRAM(). PROGRAM may be omitted if you are interested only +# in learning if the compiler or linker respects certain flags. LANGUAGE +# is typically either C or C++ and specifies which compiler to use for +# the test. If LANGUAGE is omitted, C is used. FLAGS is a whitespace +# delimited list of build tuples. Tuples are created with +# CS_CREATE_TUPLE() and are composed of up to three elements each. The +# first element represents compiler flags, the second linker flags, and +# the third libraries used when linking the program. Each tuple from +# FLAGS is attempted in order. If you want a build attempted with no +# special flags prior to builds with specialized flags, create an empty +# tuple with CS_CREATE_TUPLE() at the start of the FLAGS list. If the +# build is successful, then the shell variables cs_build_ok is set to +# "yes", cs_build_cflags, cs_build_lflags, and cs_build_libs are set to +# the tuple elements which resulted in the successful build, and +# ACTION-IF-BUILT is invoked. Upon successful build, no further tuples +# are consulted. If no tuple results in a successful build, then +# cs_build_ok is set to "no" and ACTION-IF-NOT-BUILT is invoked. +# OTHER-CFLAGS, OTHER-LFLAGS, and OTHER-LIBS specify additional compiler +# flags, linker flags, and libraries which should be used with each tuple +# build attempt. Upon successful build, these additional flags are also +# reflected in the variables cs_build_cflags, cs_build_lflags, and +# cs_build_libs unless INHIBIT-OTHER-FLAGS is a non-empty string. The +# optional ERROR-REGEX places an additional constraint upon the build +# check. If specified, ERROR-REGEX, which is a standard `grep' regular +# expression, is applied to output captured from the compiler and linker. +# If ERROR-REGEX matches, then the build is deemed a failure, and +# cs_build_ok is set to "no". This facility is useful for broken build +# tools which emit an error message yet still return success as a result. +# In such cases, it should be possible to detect the failure by scanning +# the tools' output. +# +# IMPLEMENTATION NOTES +# +# In Autoconf 2.57 and earlier, AC_LINK_IFELSE() invokes AC_TRY_EVAL(), +# which does not provide access to the captured output. To work around +# this limitation, we temporarily re-define AC_TRY_EVAL() as +# _AC_EVAL_STDERR(), which leaves the captured output in conftest.err +# (which we must also delete). In Autoconf 2.58, however, +# AC_LINK_IFELSE() instead already invokes _AC_EVAL_STDERR() on our +# behalf, however we must be careful to apply ERROR-REGEX within the +# invocation AC_LINK_IFELSE(), since AC_LINK_IFELSE() deletes +# conftest.err before it returns. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_BUILD_IFELSE], + [AC_LANG_PUSH(m4_default([$3],[C])) + cs_cflags_save="$CS_LANG_CFLAGS" + cs_lflags_save="$LDFLAGS" + cs_libs_save="$LIBS" + cs_build_ok=no + m4_ifval([$10], [m4_pushdef([AC_TRY_EVAL], [_AC_EVAL_STDERR]($$[1]))]) + + for cs_build_item in m4_default([$2],[CS_CREATE_TUPLE()]) + do + CS_SPLIT_TUPLE( + [$cs_build_item],[cs_cflags_test,cs_lflags_test,cs_libs_test]) + CS_LANG_CFLAGS="$cs_cflags_test $6 $cs_cflags_save" + LDFLAGS="$cs_lflags_test $7 $cs_lflags_save" + LIBS="$cs_libs_test $8 $cs_libs_save" + AC_LINK_IFELSE(m4_default([$1], [AC_LANG_PROGRAM([],[])]), + [m4_ifval([$10], + [AS_IF([AC_TRY_COMMAND( + [grep "AS_ESCAPE([$10])" conftest.err >/dev/null 2>&1])], + [cs_build_ok=no], [cs_build_ok=yes])], + [cs_build_ok=yes])]) + AS_IF([test $cs_build_ok = yes], [break]) + done + + m4_ifval([$10], [m4_popdef([AC_TRY_EVAL]) rm -f conftest.err]) + CS_LANG_CFLAGS=$cs_cflags_save + LDFLAGS=$cs_lflags_save + LIBS=$cs_libs_save + AC_LANG_POP(m4_default([$3],[C])) + + AS_IF([test $cs_build_ok = yes], + [cs_build_cflags=CS_TRIM([$cs_cflags_test[]m4_ifval([$9],[],[ $6])]) + cs_build_lflags=CS_TRIM([$cs_lflags_test[]m4_ifval([$9],[],[ $7])]) + cs_build_libs=CS_TRIM([$cs_libs_test[]m4_ifval([$9],[],[ $8])]) + $4], + [$5])]) + + + +#------------------------------------------------------------------------------ +# CS_CHECK_BUILD(MESSAGE, CACHE-VAR, [PROGRAM], [FLAGS], [LANGUAGE], +# [ACTION-IF-BUILT], [ACTION-IF-NOT-BUILT], [IGNORE-CACHE], +# [OTHER-CFLAGS], [OTHER-LFLAGS], [OTHER-LIBS], +# [INHIBIT-OTHER-FLAGS], [ERROR-REGEX]) +# Like CS_BUILD_IFELSE() but also prints "checking" and result messages, +# and optionally respects the cache. Sets CACHE-VAR to "yes" upon +# success, else "no" upon failure. Additionally, sets CACHE-VAR_cflags, +# CACHE-VAR_lflags, and CACHE-VAR_libs to the values which resulted in a +# successful build. If IGNORE-CACHE is "yes", then the cache variables +# are ignored upon entry to this macro, however they are still set to +# appropriate values upon exit. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_BUILD], + [AS_IF([test "$8" != yes], + [AC_CACHE_CHECK([$1], [$2], + [CS_BUILD_IFELSE([$3], [$4], [$5], + [$2=yes + $2_cflags=$cs_build_cflags + $2_lflags=$cs_build_lflags + $2_libs=$cs_build_libs], + [$2=no], [$9], [$10], [$11], [$12], [$13])])], + [AC_MSG_CHECKING([$1]) + CS_BUILD_IFELSE([$3], [$4], [$5], + [$2=yes + $2_cflags=$cs_build_cflags + $2_lflags=$cs_build_lflags + $2_libs=$cs_build_libs], + [$2=no], [$9], [$10], [$11], [$12], [$13]) + AC_MSG_RESULT([$$2])]) + AS_IF([test $$2 = yes], [$6], + [$2_cflags='' + $2_lflags='' + $2_libs='' + $7])]) + + + +#------------------------------------------------------------------------------ +# CS_CHECK_BUILD_FLAGS(MESSAGE, CACHE-VAR, FLAGS, [LANGUAGE], +# [ACTION-IF-RECOGNIZED], [ACTION-IF-NOT-RECOGNIZED], +# [OTHER-CFLAGS], [OTHER-LFLAGS], [OTHER-LIBS], +# [ERROR-REGEX]) +# Like CS_CHECK_BUILD(), but checks only if the compiler or linker +# recognizes a command-line option or options. MESSAGE is the "checking" +# message. CACHE-VAR is the shell cache variable which receives the flag +# or flags recognized by the compiler or linker. FLAGS is a +# whitespace-delimited list of build tuples created with +# CS_CREATE_TUPLE(). Each tuple from FLAGS is attempted in order until +# one is found which is recognized by the compiler. After that, no +# further flags are checked. LANGUAGE is typically either C or C++ and +# specifies which compiler to use for the test. If LANGUAGE is omitted, +# C is used. If a command-line option is recognized, then CACHE-VAR is +# set to the composite value of $cs_build_cflags, $cs_build_lflags, and +# $cs_build_libs of the FLAGS element which succeeded (not including the +# "other" flags) and ACTION-IF-RECOGNIZED is invoked. If no options are +# recognized, then CACHE-VAR is set to the empty string, and +# ACTION-IF-NOT-RECOGNIZED is invoked. As a convenience, in case +# comparing CACHE-VAR against the empty string to test for failure is +# undesirable, a second variable named CACHE-VAR_ok is set to the literal +# "no" upon failure, and to the same value as CACHE-VAR upon success. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_BUILD_FLAGS], + [AC_CACHE_CHECK([$1], [$2_ok], + [CS_BUILD_IFELSE([], [$3], [$4], + [$2=CS_TRIM([$cs_build_cflags $cs_build_lflags $cs_build_libs]) + $2_ok="$$2"], + [$2='' + $2_ok=no], [$7], [$8], [$9], [Y], [$10])]) + AS_IF([test "$$2_ok" != no], [$5], [$6])]) +#============================================================================== +# Copyright (C)2003-2006 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_CHECK_COMMON_TOOLS_LINK +# Checks for common tools related to linking. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_COMMON_TOOLS_LINK], + [ + # The default RANLIB in Jambase is wrong on some platforms, and is also + # unsuitable during cross-compilation, so we set the value unconditionally + # (sixth argument of CS_EMIT_BUILD_PROPERTY). + AC_PROG_RANLIB + CS_EMIT_BUILD_PROPERTY([RANLIB], [$RANLIB], [], [], [], [Y]) + + CS_CHECK_TOOLS([DLLTOOL], [dlltool]) + CS_EMIT_BUILD_PROPERTY([CMD.DLLTOOL], [$DLLTOOL]) + + CS_CHECK_TOOLS([DLLWRAP], [dllwrap]) + CS_EMIT_BUILD_PROPERTY([CMD.DLLWRAP], [$DLLWRAP]) + + CS_CHECK_TOOLS([WINDRES], [windres]) + CS_EMIT_BUILD_PROPERTY([CMD.WINDRES], [$WINDRES]) + + CS_CHECK_TOOLS([STRINGS], [strings]) + CS_EMIT_BUILD_PROPERTY([CMD.STRINGS], [$STRINGS]) + + CS_CHECK_TOOLS([OBJCOPY], [objcopy]) + CS_EMIT_BUILD_PROPERTY([CMD.OBJCOPY], [$OBJCOPY]) + + CS_CHECK_LIBTOOL + CS_EMIT_BUILD_PROPERTY([LIBTOOL], [$LIBTOOL]) + CS_EMIT_BUILD_PROPERTY([APPLE_LIBTOOL], [$APPLE_LIBTOOL]) + ]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_COMMON_TOOLS_BASIC +# Checks for basic tools for building things. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_COMMON_TOOLS_BASIC], + [CS_CHECK_MKDIR + CS_EMIT_BUILD_PROPERTY([CMD.MKDIR], [$MKDIR]) + CS_EMIT_BUILD_PROPERTY([CMD.MKDIRS], [$MKDIRS]) + + CS_CHECK_PROGS([INSTALL], [install]) + CS_EMIT_BUILD_PROPERTY([INSTALL], [$INSTALL])]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_COMMON_TOOLS_DOC_TEXINFO +# Checks for tools to generate documentation from texinfo files. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_COMMON_TOOLS_DOC_TEXINFO], + [CS_CHECK_PROGS([TEXI2DVI], [texi2dvi]) + CS_EMIT_BUILD_PROPERTY([CMD.TEXI2DVI], [$TEXI2DVI]) + + CS_CHECK_PROGS([TEXI2PDF], [texi2pdf]) + CS_EMIT_BUILD_PROPERTY([CMD.TEXI2PDF], [$TEXI2PDF]) + + CS_CHECK_PROGS([DVIPS], [dvips]) + CS_EMIT_BUILD_PROPERTY([CMD.DVIPS], [$DVIPS]) + + CS_CHECK_PROGS([DVIPDF], [dvipdf]) + CS_EMIT_BUILD_PROPERTY([CMD.DVIPDF], [$DVIPDF]) + + CS_CHECK_PROGS([MAKEINFO], [makeinfo]) + CS_EMIT_BUILD_PROPERTY([CMD.MAKEINFO], [$MAKEINFO])]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_COMMON_TOOLS_DOC_DOXYGEN +# Checks for tools to generate source documentation via doxygen. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_COMMON_TOOLS_DOC_DOXYGEN], + [CS_CHECK_PROGS([DOXYGEN], [doxygen]) + CS_EMIT_BUILD_PROPERTY([CMD.DOXYGEN], [$DOXYGEN]) + + CS_CHECK_TOOLS([DOT], [dot]) + CS_EMIT_BUILD_PROPERTY([CMD.DOT], [$DOT])]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_COMMON_LIBS +# Check for typical required libraries (libm, libmx, libdl, libnsl). +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_COMMON_LIBS], + [AC_LANG_PUSH([C]) + AC_CHECK_LIB([m], [pow], [cs_cv_libm_libs=-lm], [cs_cv_libm_libs=]) + AC_CHECK_LIB([m], [cosf], [cs_cv_libm_libs=-lm]) + AC_CHECK_LIB([mx], [cosf]) + AC_CHECK_LIB([dl], [dlopen], [cs_cv_libdl_libs=-ldl], [cs_cv_libdl_libs=]) + AC_CHECK_LIB([nsl], [gethostbyname]) + AC_LANG_POP([C])]) +# checkcppunit.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_CHECK_CPPUNIT([EMITTER]) +# Check if CppUnit (http://cppunit.sourceforge.net/), the unit-testing +# framework is available. The shell variable cs_cv_libcppunit is set to +# "yes" if CppUnit is discovered, else "no". If available, then the +# variables cs_cv_libcppunit_cflags, cs_cv_libcppunit_lflags, and +# cs_cv_libcppunit_libs are set. If EMITTER is provided, then +# CS_EMIT_BUILD_RESULT() is invoked with EMITTER in order to record the +# results in an output file. As a convenience, if EMITTER is the literal +# value "emit" or "yes", then CS_EMIT_BUILD_RESULT()'s default emitter +# will be used. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_CPPUNIT], + [CS_CHECK_LIB_WITH([cppunit], + [AC_LANG_PROGRAM([[#include ]], + [CppUnit::TextUi::TestRunner r; r.run();])], + [], [C++]) + + AS_IF([test $cs_cv_libcppunit = yes], + [CS_CHECK_BUILD([if cppunit is sufficiently recent], + [cs_cv_libcppunit_recent], + [AC_LANG_PROGRAM( + [[#include ]], + [CppUnit::BriefTestProgressListener b; b.startTest(0);])], + [], [C++], + [CS_EMIT_BUILD_RESULT([cs_cv_libcppunit], [CPPUNIT], + CS_EMITTER_OPTIONAL([$1]))], [], [], + [$cs_cv_libcppunit_cflags], + [$cs_cv_libcppunit_lflags], + [$cs_cv_libcppunit_libs])])]) +# checklib.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003-2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# cs_lib_paths_default +# Whitespace delimited list of directory tuples in which to search, by +# default, for external libraries. Each list item can specify an +# include|library directory tuple (for example, "/usr/include|/usr/lib"), +# or a single directory (for example, "/usr"). If the second form is +# used, then "include" and "lib" subdirectories of the directory are +# searched. If the library resources are not found, then the directory +# itself is searched. Thus, "/proj" is shorthand for +# "/proj/include|/proj/lib /proj|/proj". +# +# Present Cases: +# /usr/local -- Not all compilers search here by default, so we specify +# it manually. +# /sw -- Fink, the MacOS/X manager of Unix packages, installs here by +# default. +# /opt/local -- DarwinPorts installs here by default. +#------------------------------------------------------------------------------ +m4_define([cs_lib_paths_default], + [/usr/local/include|/usr/local/lib \ + /sw/include|/sw/lib \ + /opt/local/include|/opt/local/lib \ + /opt/include|/opt/lib]) + + + +#------------------------------------------------------------------------------ +# cs_pkg_paths_default +# Comma delimited list of additional directories in which the +# `pkg-config' command should search for its `.pc' files. +# +# Present Cases: +# /usr/local/lib/pkgconfig -- Although a common location for .pc files +# installed by "make install", many `pkg-config' commands neglect +# to search here automatically. +# /sw/lib/pkgconfig -- Fink, the MacOS/X manager of Unix packages, +# installs .pc files here by default. +# /opt/local/lib/pkgconfig -- DarwinPorts installs .pc files here by +# default. +#------------------------------------------------------------------------------ +m4_define([cs_pkg_paths_default], + [/usr/local/lib/pkgconfig, + /sw/lib/pkgconfig, + /opt/local/lib/pkgconfig, + /opt/lib/pkgconfig]) + + + +#------------------------------------------------------------------------------ +# CS_CHECK_LIB_WITH(LIBRARY, PROGRAM, [SEARCH-LIST], [LANGUAGE], +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], [OTHER-CFLAGS], +# [OTHER-LFLAGS], [OTHER-LIBS], [ALIASES]) +# Very roughly similar in concept to AC_CHECK_LIB(), but allows caller to +# to provide list of directories in which to search for LIBRARY; allows +# user to override library location via --with-LIBRARY=dir; and consults +# `pkg-config' (if present) and `LIBRARY-config' (if present, i.e. +# `sdl-config') in order to obtain compiler and linker flags. LIBRARY is +# the name of the library or MacOS/X framework which is to be located +# (for example, "readline" for `libreadline.a' or `readline.framework'). +# PROGRAM, which is typically composed with AC_LANG_PROGRAM(), is a +# program which references at least one function or symbol in LIBRARY. +# SEARCH-LIST is a whitespace-delimited list of paths in which to search +# for the library and its header files, in addition to those searched by +# the compiler and linker by default, and those referenced by the +# cs_lib_paths_default macro. Each list item can specify an +# `include|library' directory tuple (for example, +# "/usr/include|/usr/lib"), or a single directory (for example, "/usr"). +# If the second form is used, then "include" and "lib" subdirectories of +# the directory are searched. If the library resources are not found, +# then the directory itself is searched. Thus, "/proj" is shorthand for +# "/proj/include|/proj/lib /proj|/proj". Items in the search list can +# include wildcards. SEARCH-LIST can be overridden by the user with the +# --with-LIBRARY=dir option, in which case only "dir/include|dir/lib" and +# "dir|dir" are searched. If SEARCH-LIST is omitted and the user did not +# override the search list via --with-LIBRARY=dir, then only the +# directories normally searched by the compiler and the directories +# mentioned via cs_lib_paths_default are searched. LANGUAGE is typically +# either C or C++ and specifies which compiler to use for the test. If +# LANGUAGE is omitted, C is used. OTHER-CFLAGS, OTHER-LFLAGS, and +# OTHER-LIBS can specify additional compiler flags, linker flags, and +# libraries needed to successfully link with LIBRARY. The optional +# ALIASES is a comma-delimited list of library names for which to search +# in case LIBRARY is not located (for example "[sdl1.2, sdl12]" for +# libsdl1.2.a, sdl1.2.framework, libsdl12.a, and sdl12.framework). If +# the library or one of its aliases is found and can be successfully +# linked into a program, then the shell cache variable cs_cv_libLIBRARY +# is set to "yes"; cs_cv_libLIBRARY_cflags, cs_cv_libLIBRARY_lflags, and +# cs_cv_libLIBRARY_libs are set, respectively, to the compiler flags +# (including OTHER-CFLAGS), linker flags (including OTHER-LFLAGS), and +# library references (including OTHER-LIBS) which resulted in a +# successful build; and ACTION-IF-FOUND is invoked. If the library was +# not found or was unlinkable, or if the user disabled the library via +# --without-LIBRARY, then cs_cv_libLIBRARY is set to "no" and +# ACTION-IF-NOT-FOUND is invoked. Note that the exported shell variable +# names are always composed from LIBRARY regardless of whether the test +# succeeded because the primary library was discovered or one of the +# aliases. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_LIB_WITH], + [AC_ARG_WITH([$1], [AC_HELP_STRING([--with-$1=dir], + [specify location of lib$1 if not detected automatically; searches + dir/include, dir/lib, and dir])]) + + # Backward compatibility: Recognize --with-lib$1 as alias for --with-$1. + AS_IF([test -n "$with_lib$1" && test -z "$with_$1"], + [with_$1="$with_lib$1"]) + + AS_IF([test -z "$with_$1"], [with_$1=yes]) + AS_IF([test "$with_$1" != no], + [# If --with-$1 value is same as cached value, then assume other + # cached values are also valid; otherwise, ignore all cached values. + AS_IF([test "$with_$1" != "$cs_cv_with_$1"], + [cs_ignore_cache=yes], [cs_ignore_cache=no]) + + cs_check_lib_flags='' + AS_IF([test $with_$1 = yes], + [m4_foreach([cs_check_lib_alias], [$1, $10], + [_CS_CHECK_LIB_PKG_CONFIG_FLAGS([cs_check_lib_flags], + cs_check_lib_alias) + _CS_CHECK_LIB_CONFIG_FLAGS([cs_check_lib_flags], + cs_check_lib_alias) + ])]) + + AS_IF([test $with_$1 != yes], + [cs_check_lib_paths=$with_$1], + [cs_check_lib_paths="| cs_lib_paths_default $3"]) + m4_foreach([cs_check_lib_alias], [$1, $10], + [_CS_CHECK_LIB_CREATE_FLAGS([cs_check_lib_flags], + cs_check_lib_alias, [$cs_check_lib_paths]) + ]) + + CS_CHECK_BUILD([for lib$1], [cs_cv_lib$1], [$2], [$cs_check_lib_flags], + [$4], [], [], [$cs_ignore_cache], [$7], [$8], [$9])], + [cs_cv_lib$1=no]) + + cs_cv_with_$1="$with_$1" + AS_IF([test "$cs_cv_lib$1" = yes], [$5], [$6])]) + + + +#------------------------------------------------------------------------------ +# CS_CHECK_PKG_CONFIG +# Check if the `pkg-config' command is available and reasonably recent. +# This program acts as a central repository of build flags for various +# packages. For example, to determine the compiler flags for FreeType2 +# use, "pkg-config --cflags freetype2"; and "pkg-config --libs freetype2" +# to determine the linker flags. If `pkg-config' is found and is +# sufficiently recent, PKG_CONFIG is set and AC_SUBST() invoked. +#------------------------------------------------------------------------------ +m4_define([CS_PKG_CONFIG_MIN], [0.9.0]) +AC_DEFUN([CS_CHECK_PKG_CONFIG], + [AS_IF([test "$cs_prog_pkg_config_checked" != yes], + [CS_CHECK_TOOLS([PKG_CONFIG], [pkg-config]) + _CS_CHECK_PKG_CONFIG_PREPARE_PATH + cs_prog_pkg_config_checked=yes]) + AS_IF([test -z "$cs_cv_prog_pkg_config_ok"], + [AS_IF([test -n "$PKG_CONFIG"], + [AS_IF([$PKG_CONFIG --atleast-pkgconfig-version=CS_PKG_CONFIG_MIN], + [cs_cv_prog_pkg_config_ok=yes], + [cs_cv_prog_pkg_config_ok=no])], + [cs_cv_prog_pkg_config_ok=no])])]) + +AC_DEFUN([_CS_CHECK_PKG_CONFIG_PREPARE_PATH], + [PKG_CONFIG_PATH="m4_foreach([cs_pkg_path], [cs_pkg_paths_default], + [cs_pkg_path$PATH_SEPARATOR])$PKG_CONFIG_PATH" + export PKG_CONFIG_PATH]) + + + +#------------------------------------------------------------------------------ +# _CS_CHECK_LIB_PKG_CONFIG_FLAGS(VARIABLE, LIBRARY) +# Helper macro for CS_CHECK_LIB_WITH(). Checks if `pkg-config' knows +# about LIBRARY and, if so, appends a build tuple consisting of the +# compiler and linker flags reported by `pkg-config' to the list of +# tuples stored in the shell variable VARIABLE. +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_CHECK_LIB_PKG_CONFIG_FLAGS], + [CS_CHECK_PKG_CONFIG + AS_IF([test $cs_cv_prog_pkg_config_ok = yes], + [AC_CACHE_CHECK([if $PKG_CONFIG recognizes $2], [_CS_CLPCF_CVAR([$2])], + [AS_IF([$PKG_CONFIG --exists $2], + [_CS_CLPCF_CVAR([$2])=yes], [_CS_CLPCF_CVAR([$2])=no])]) + AS_IF([test $_CS_CLPCF_CVAR([$2]) = yes], + [_CS_CHECK_LIB_CONFIG_PROG_FLAGS([$1], [pkg_config_$2], + [$PKG_CONFIG], [$2])])])]) + +AC_DEFUN([_CS_CLPCF_CVAR], [AS_TR_SH([cs_cv_prog_pkg_config_$1])]) + + + +#------------------------------------------------------------------------------ +# _CS_CHECK_LIB_CONFIG_FLAGS(VARIABLE, LIBRARY) +# Helper macro for CS_CHECK_LIB_WITH(). Checks if `LIBRARY-config' +# (i.e. `sdl-config') exists and, if so, appends a build tuple consisting +# of the compiler and linker flags reported by `LIBRARY-config' to the +# list of tuples stored in the shell variable VARIABLE. +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_CHECK_LIB_CONFIG_FLAGS], + [CS_CHECK_TOOLS(_CS_CLCF_SHVAR([$2]), [$2-config]) + AS_IF([test -n "$_CS_CLCF_SHVAR([$2])"], + [AS_IF([test -z "$_CS_CLCF_CVAR([$2])"], + [AS_IF([$_CS_CLCF_SHVAR([$2]) --cflags --libs >/dev/null 2>&1], + [_CS_CLCF_CVAR([$2])=yes], [_CS_CLCF_CVAR([$2])=no])]) + AS_IF([test $_CS_CLCF_CVAR([$2]) = yes], + [_CS_CHECK_LIB_CONFIG_PROG_FLAGS([$1], [config_$2], + [$_CS_CLCF_SHVAR([$2])])])])]) + +AC_DEFUN([_CS_CLCF_CVAR], [AS_TR_SH([cs_cv_prog_config_$1_ok])]) +AC_DEFUN([_CS_CLCF_SHVAR], [m4_toupper(AS_TR_SH([CONFIG_$1]))]) + + + +#------------------------------------------------------------------------------ +# _CS_CHECK_LIB_CONFIG_PROG_FLAGS(VARIABLE, TAG, CONFIG-PROGRAM, [ARGS]) +# Helper macro for _CS_CHECK_LIB_PKG_CONFIG_FLAGS() and +# _CS_CHECK_LIB_CONFIG_FLAGS(). CONFIG-PROGRAM is a command which +# responds to the --cflags and --libs options and returns suitable +# compiler and linker flags for some package. ARGS, if supplied, is +# passed to CONFIG-PROGRAM after the --cflags or --libs argument. The +# results of the --cflags and --libs options are packed into a build +# tuple and appended to the list of tuples stored in the shell variable +# VARIABLE. TAG is used to compose the name of the cache variable. A good +# choice for TAG is some unique combination of the library name and +# configuration program. +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_CHECK_LIB_CONFIG_PROG_FLAGS], + [AS_IF([test -z "$_CS_CLCPF_CVAR([$2])"], + [cs_check_lib_cflag=CS_RUN_PATH_NORMALIZE([$3 --cflags $4]) + cs_check_lib_lflag='' + cs_check_lib_libs=CS_RUN_PATH_NORMALIZE([$3 --libs $4]) + _CS_CLCPF_CVAR([$2])=CS_CREATE_TUPLE( + [$cs_check_lib_cflag], + [$cs_check_lib_lflag], + [$cs_check_lib_libs])]) + $1="$$1 $_CS_CLCPF_CVAR([$2])"]) + +AC_DEFUN([_CS_CLCPF_CVAR], [AS_TR_SH([cs_cv_prog_$1_flags])]) + + + +#------------------------------------------------------------------------------ +# _CS_CHECK_LIB_CREATE_FLAGS(VARIABLE, LIBRARY, PATHS) +# Helper macro for CS_CHECK_LIB_WITH(). Constructs a list of build +# tuples suitable for CS_CHECK_BUILD() and appends the tuple list to the +# shell variable VARIABLE. LIBRARY and PATHS have the same meanings as +# the like-named arguments of CS_CHECK_LIB_WITH(). +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_CHECK_LIB_CREATE_FLAGS], + [for cs_lib_item in $3 + do + case $cs_lib_item in + *\|*) CS_SPLIT( + [$cs_lib_item], [cs_check_incdir,cs_check_libdir], [|]) + _CS_CHECK_LIB_CREATE_FLAG([$1], + [$cs_check_incdir], [$cs_check_libdir], [$2]) + ;; + *) _CS_CHECK_LIB_CREATE_FLAG([$1], + [$cs_lib_item/include], [$cs_lib_item/lib], [$2]) + _CS_CHECK_LIB_CREATE_FLAG( + [$1], [$cs_lib_item], [$cs_lib_item], [$2]) + ;; + esac + done]) + + + +#------------------------------------------------------------------------------ +# _CS_CHECK_LIB_CREATE_FLAG(VARIABLE, HEADER-DIR, LIBRARY-DIR, LIBRARY) +# Helper macro for _CS_CHECK_LIB_CREATE_FLAGS(). Constructs build tuples +# suitable for CS_CHECK_BUILD() for given header and library directories, +# and appends the tuples to the shell variable VARIABLE. Synthesizes +# tuples which check for LIBRARY as a MacOS/X framework, and a standard +# link library. +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_CHECK_LIB_CREATE_FLAG], + [AS_IF([test -n "$2"], [cs_check_lib_cflag="-I$2"], [cs_check_lib_cflag='']) + AS_IF([test -n "$3"], [cs_check_lib_lflag="-L$3"], [cs_check_lib_lflag='']) + AS_IF([test -n "$4"], + [cs_check_lib_libs="-l$4" + cs_check_lib_framework="-framework $4"], + [cs_check_lib_libs='' + cs_check_lib_framework='']) + $1="$$1 + CS_CREATE_TUPLE( + [$cs_check_lib_cflag], + [$cs_check_lib_lflag], + [$cs_check_lib_framework]) + CS_CREATE_TUPLE( + [$cs_check_lib_cflag], + [$cs_check_lib_lflag], + [$cs_check_lib_libs])"]) +# checklibtool.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2004 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_CHECK_LIBTOOL +# Find and identify the various implementations of libtool. In +# particular, this macro is aware of GNU libtool and Apple's libtool +# (which serves a completely different purpose). On MacOS/X, GNU libtool +# is typically named glibtool, however a user might also use Fink to +# install the unadorned libtool; and the Fink-installed version might +# shadow Apple's own libtool if it appears in the PATH before the Apple +# tool. This macro jumps through the necessary hoops to distinguish and +# locate the various implementations. Sets the shell variable LIBTOOL to +# the located GNU libtool (if any), and APPLE_LIBTOOL to the located +# Apple libtool. Invokes AC_SUBST() for LIBTOOL and APPLE_LIBTOOL. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_LIBTOOL], +[# GNU: Search for libtool before glibtool since Fink version is likely newer. +m4_define([cs_lt_path_gnu], + [/sw/bin$PATH_SEPARATOR/usr/local/bin$PATH_SEPARATOR$PATH]) +AS_IF([test -z "$LIBTOOL"], + [CS_CHECK_TOOLS([LIBTOOL_TEST], [libtool glibtool gnulibtool], [], + [cs_lt_path_gnu]) + AS_IF([test -n "$LIBTOOL_TEST"], + [CS_PATH_PROG([LIBTOOL_PATH], [$LIBTOOL_TEST], [], [cs_lt_path_gnu]) + CS_LIBTOOL_CLASSIFY([$LIBTOOL_PATH], + [LIBTOOL="$LIBTOOL_PATH"], + [AS_IF([test -z "$APPLE_LIBTOOL"], [APPLE_LIBTOOL="$LIBTOOL_PATH"]) + CS_CHECK_TOOLS([LIBTOOL], [glibtool gnulibtool])])])]) +AC_SUBST([LIBTOOL]) + +# Apple: Ensure that Apple libtool will be found before GNU libtool from Fink. +m4_define([cs_lt_path_apple],[/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH]) +AS_IF([test -z "$APPLE_LIBTOOL"], + [CS_PATH_PROG([CS_LT_APPLE], [libtool], [], [cs_lt_path_apple]) + CS_LIBTOOL_CLASSIFY([$CS_LT_APPLE], [], + [APPLE_LIBTOOL="$CS_LT_APPLE"])]) +AC_SUBST([APPLE_LIBTOOL])]) + +AC_DEFUN([CS_LIBTOOL_CLASSIFY], + [AS_IF([test -n "$1"], + [AC_MSG_CHECKING([classification of $1]) + CS_LIBTOOL_GNU_IFELSE([$1], + [AC_MSG_RESULT([gnu]) + $2], + [AC_MSG_RESULT([apple]) + $3])])]) + +AC_DEFUN([CS_LIBTOOL_GNU_IFELSE], + [AS_IF([AC_RUN_LOG([$1 --version 1>&2])], [$2], [$3])]) +#============================================================================== +# Copyright (C)2003-2006 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_CHECK_OPENGL +# Check for OpenGL. +# +# IMPLEMENTATION NOTES +# +# Some Mesa installations require pthread, so pthread flags are employed if +# available. +# +# The check for opengl32 needs to precede other checks because Cygwin users +# often have Mesa installed, and Mesa's OpenGL library is compiled without the +# __stdcall flags which results in link errors, whereas Microsoft's native +# opengl32 works fine. Conversely, some Unix implementations have Wine +# installed (Windows emulation layer) which includes an opengl32.so library. +# We need to avoid detection of this library on Unix since it would cause an +# undesirable dependence upon Wine. +# +# Many OpenGL libraries on Unix already contain GLX, so there is no separate +# GLX library, thus we first check for GLX using the discovered OpenGL library +# before attempting to locate a separate GLX-specific library. +# +# On MacOS/X, some users have XFree86 installed which creates a link from +# /usr/include/GL to /usr/X11R6/include/GL. We want to ignore this directory +# and instead check for Apple's OpenGL.framework, if we are not cross-building +# for Darwin. We accomplish this by placing the OpenGL.framework test ahead of +# the other tests. +# +# At least one user (Jorrit) has a strange installation in which inclusion of +# fails if an int32 is not present, thus we must take this into +# account. +#------------------------------------------------------------------------------ +m4_define([cs_define_int32], + [[#if !HAVE_TYPE_INT32 + typedef long int32; + #endif + ]]) + +# CS_GL_INCLUDE(CPP-MACRO,FALLBACK,HEADER) +AC_DEFUN([CS_GL_INCLUDE], + [[#if HAVE_WINDOWS_H + #if !HAVE_TYPE_INT32 + typedef long int32; + #endif + #include + #endif + #ifndef CS_HEADER_GLOBAL + #define CS_HEADER_GLOBAL(X,Y) CS_HEADER_GLOBAL_COMPOSE(X,Y) + #define CS_HEADER_GLOBAL_COMPOSE(X,Y) + #endif + #ifdef $1 + #include CS_HEADER_GLOBAL($1,$3) + #else + #include <$2/$3> + #endif]]) + +AC_DEFUN([CS_CHECK_OPENGL], + [AC_REQUIRE([CS_CHECK_HOST]) + AC_REQUIRE([CS_CHECK_COMMON_LIBS]) + AC_REQUIRE([CS_CHECK_PTHREAD]) + AC_REQUIRE([AC_PATH_X]) + AC_REQUIRE([AC_PATH_XTRA]) + AC_CHECK_TYPE([int32], [AC_DEFINE([HAVE_TYPE_INT32], [], + [Whether the int32 type is available])], []) + AC_CHECK_HEADERS([windows.h], [], [], [cs_define_int32]) + + # Apply plaform-specific flags if necessary. + cs_gl_plat_cflags='' + cs_gl_plat_lflags='' + cs_gl_plat_libs='' + AS_IF([test -n "$cs_cv_libm_cflags$cs_cv_libm_lflags$cs_cv_libm_libs"], + [cs_gl_plat_cflags="$cs_cv_libm_cflags $cs_gl_plat_cflags" + cs_gl_plat_lflags="$cs_cv_libm_lflags $cs_gl_plat_lflags" + cs_gl_plat_libs="$cs_cv_libm_libs $cs_gl_plat_libs"]) + AS_IF([test $cs_cv_sys_pthread = yes], + [cs_gl_plat_cflags="$cs_cv_sys_pthread_cflags $cs_gl_plat_cflags" + cs_gl_plat_lflags="$cs_cv_sys_pthread_lflags $cs_gl_plat_lflags" + cs_gl_plat_libs="$cs_cv_sys_pthread_libs $cs_gl_plat_libs"]) + AS_IF([test "$no_x" != yes], + [cs_gl_plat_cflags="$X_CFLAGS $cs_gl_plat_cflags" + cs_gl_plat_lflags="$cs_gl_plat_lflags" + cs_gl_plat_libs=" + $X_PRE_LIBS $X_LIBS -lX11 -lXext $X_EXTRA_LIBS $cs_gl_plat_libs"]) + + # Mesa requested? + AC_ARG_WITH([mesa], [AC_HELP_STRING([--with-mesa], + [use Mesa OpenGL library if available (default YES)])], + [], [with_mesa=yes]) + + AS_IF([test $with_mesa != no], + [cs_mesa_gl=CS_CREATE_TUPLE([],[],[-lMesaGL])]) + + # MacOS/X or Darwin? + AS_IF([test "x$cs_host_macosx" = "xyes"], + [cs_osx_gl=CS_CREATE_TUPLE([-DCS_OPENGL_PATH=OpenGL],[],[-framework OpenGL])]) + AS_IF([test "x$cs_host_macosx" = "xyes"], + [cs_gl_plat_lflags="$cs_plat_lflags -Wl,-dylib_file,/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib"]) + + # Windows? + AS_IF([test $cs_host_family = windows], + [cs_win32_gl=CS_CREATE_TUPLE([],[],[-lopengl32])]) + + # Check for OpenGL. + CS_CHECK_BUILD([for OpenGL], [cs_cv_libgl], + [AC_LANG_PROGRAM([CS_GL_INCLUDE([CS_OPENGL_PATH],[GL],[gl.h])],[glEnd()])], + [$cs_win32_gl \ + $cs_osx_gl \ + CS_CREATE_TUPLE([],[],[-lGL]) \ + CS_CREATE_TUPLE([],[],[-lgl]) \ + $cs_mesa_gl], [], + [CS_EMIT_BUILD_RESULT([cs_cv_libgl], [GL])], [], [], + [$cs_gl_plat_cflags], [$cs_gl_plat_lflags], [$cs_gl_plat_libs])]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_GLU +# Check for GLU. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_GLU], + [AC_REQUIRE([CS_CHECK_OPENGL]) + AS_IF([test $cs_cv_libgl = yes], + [AS_IF([test $with_mesa != no], + [cs_mesa_glu=CS_CREATE_TUPLE([],[],[-lMesaGLU])]) + + # MacOS/X or Darwin? + AS_IF([test "x$cs_host_macosx" = "xyes"], + [cs_osx_glu=CS_CREATE_TUPLE([-DCS_GLU_PATH=OpenGL],[],[-framework OpenGL])]) + + # Windows? + AS_IF([test $cs_host_family = windows], + [cs_win32_glu=CS_CREATE_TUPLE([],[],[-lglu32])]) + + # Check for GLU. + CS_CHECK_BUILD([for GLU], [cs_cv_libglu], + [AC_LANG_PROGRAM( + [CS_GL_INCLUDE([CS_GLU_PATH],[GL],[glu.h])], [gluNewQuadric()])], + [$cs_osx_glu \ + CS_CREATE_TUPLE() \ + $cs_win32_glu \ + CS_CREATE_TUPLE([],[],[-lGLU]) \ + CS_CREATE_TUPLE([],[],[-lglu]) \ + $cs_mesa_glu], [], + [CS_EMIT_BUILD_RESULT([cs_cv_libglu], [GLU])], [], [], + [$cs_cv_libgl_cflags], [$cs_cv_libgl_lflags], [$cs_cv_libgl_libs])])]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_GLX +# Check for GLX. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_GLX], + [AC_REQUIRE([CS_CHECK_OPENGL]) + AS_IF([test $cs_cv_libgl = yes], + [AS_IF([test $with_mesa != no], + [cs_mesa_glx=CS_CREATE_TUPLE([],[],[-lMesaGLX])]) + + # Check for GLX. + AS_IF([test "$no_x" != yes], + [CS_CHECK_BUILD([for GLX], [cs_cv_libglx], + [AC_LANG_PROGRAM([[#include ]], [glXWaitGL()])], + [CS_CREATE_TUPLE() \ + CS_CREATE_TUPLE([],[],[-lGLX]) \ + CS_CREATE_TUPLE([],[],[-lglx]) \ + $cs_mesa_glx], [], + [CS_EMIT_BUILD_RESULT([cs_cv_libglx], [GLX])], [], [], + [$cs_cv_libgl_cflags], [$cs_cv_libgl_lflags], [$cs_cv_libgl_libs])])])]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_GLXEXT([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# Check for GLX extensions. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_GLXEXT], + [AC_REQUIRE([CS_CHECK_GLX]) + AS_IF([test x$cs_cv_libglx = "xyes"], + [# Check for GLX extensions. + CS_CHECK_BUILD([for GLX extensions], [cs_cv_libglx_extensions], + [AC_LANG_PROGRAM( + [[#define GLX_GLXEXT_PROTOTYPES + #include ]], + [glXGetProcAddressARB(0)])], + [CS_CREATE_TUPLE( + [$cs_cv_libglx_cflags], + [$cs_cv_libglx_lflags], + [$cs_cv_libglx_libs])], + [], [$1], [$2])])]) + + + +#------------------------------------------------------------------------------ +# CS_CHECK_GLUT +# Check for GLUT. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_GLUT], + [AC_REQUIRE([CS_CHECK_GLU]) + AS_IF([test x$cs_cv_libglu = "xyes"], + [# MacOS/X or Darwin? + AS_IF([test "x$cs_host_macosx" = "xyes"], + [cs_osx_glut=CS_CREATE_TUPLE([-DCS_GLUT_PATH=GLUT],[],[-framework GLUT])]) + + # Windows? + AS_IF([test $cs_host_family = windows], + [cs_win32_glut=CS_CREATE_TUPLE([],[],[-lglut32])]) + + # Check for GLUT. + CS_CHECK_BUILD([for GLUT], [cs_cv_libglut], + [AC_LANG_PROGRAM( + [CS_GL_INCLUDE([CS_GLUT_PATH],[GL],[glut.h])], [glutSwapBuffers()])], + [$cs_osx_glut \ + CS_CREATE_TUPLE() \ + $cs_win32_glut \ + CS_CREATE_TUPLE([],[],[-lGLUT]) \ + CS_CREATE_TUPLE([],[],[-lglut])], [], + [CS_EMIT_BUILD_RESULT([cs_cv_libglut], [GLUT])], [], [], + [$cs_cv_libgl_cflags $cs_cv_libglu_cflags], + [$cs_cv_libgl_lflags $cs_cv_libglu_lflags], + [$cs_cv_libgl_libs $cs_cv_libglu_libs])])]) + +# checkpic.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_COMPILER_PIC([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# Check if compiler can be instructed to produce +# position-independent-code (PIC). This feature is required by some +# platforms when building plugin modules and shared libraries. If +# LANGUAGE is not provided, then `C' is assumed (other options include +# `C++'). If CACHE-VAR is not provided, then it defaults to the name +# "cs_cv_prog_compiler_pic". If a PIC-enabling option (such as `-fPIC') +# is discovered, then it is assigned to CACHE-VAR and ACTION-IF-FOUND is +# invoked; otherwise the empty string is assigned to CACHE-VAR and +# ACTION-IF-NOT-FOUND is invoked. +# +# IMPLEMENTATION NOTES +# +# On some platforms (such as Windows), the -fPIC option is superfluous +# and emits a warning "-fPIC ignored for target (all code is position +# independent)", despite the fact that the compiler accepts the option +# and returns a success code. We want to re-interpret the warning as a +# failure in order to avoid unnecessary compiler diagnostics in case the +# client inserts the result of this check into CFLAGS, for instance. We +# do so by attempting to promote warnings to errors using the result of +# CS_COMPILER_ERRORS(). As an extra safe-guard, we also scan the compiler +# output for an appropriate diagnostic because some gcc warnings fail to +# promote to error status despite use of -Werror. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_COMPILER_PIC], + [CS_COMPILER_ERRORS([$1], + [m4_default([$2_werror],[cs_cv_prog_compiler_pic_werror])]) + CS_CHECK_BUILD_FLAGS( + [how to enable m4_default([$1],[C]) PIC generation], + [m4_default([$2],[cs_cv_prog_compiler_pic])], + [CS_CREATE_TUPLE([-fPIC])], [$1], [$3], [$4], + [m4_default([$$2_werror],[$cs_cv_prog_compiler_pic_werror])], [], [], + [fPIC])]) + +# Backward-compatiblity alias. +AC_DEFUN([CS_CHECK_COMPILER_PIC], [CS_COMPILER_PIC([$1],[$2],[$3],[$4])]) +# checkprog.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2004 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# cs_bin_paths_default +# Comma delimited list of additional directories in which tools and +# commands might be found. +# +# Present Cases: +# /usr/local/bin -- Although a common location for executables, it is +# now-and-then absent from the default PATH setting. +# /sw/bin -- Fink, the MacOS/X manager of Unix packages, installs +# executables here. +#------------------------------------------------------------------------------ +m4_define([cs_bin_paths_default], [/usr/local/bin, /sw/bin]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_PROG(VARIABLE, PROGRAM, VALUE-IF-FOUND, [VALUE-IF-NOT-FOUND], +# [PATH], [REJECT]) +# Simple wrapper for AC_CHECK_PROG() which ensures that the search path +# is augmented by the directories mentioned in cs_bin_paths_default. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_PROG], + [_CS_PROG_PATH_PREPARE + AC_CHECK_PROG([$1], [$2], [$3], [$4], + m4_ifval([$5], [_CS_PROG_CLIENT_PATH([$5])]), [$6])]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_PROGS(VARIABLE, PROGRAMS, [VALUE-IF-NOT-FOUND], [PATH]) +# Simple wrapper for AC_CHECK_PROGS() which ensures that the search path +# is augmented by the directories mentioned in cs_bin_paths_default. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_PROGS], + [_CS_PROG_PATH_PREPARE + AC_CHECK_PROGS([$1], [$2], [$3], + m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_TOOL(VARIABLE, TOOL, [VALUE-IF-NOT-FOUND], [PATH]) +# Simple wrapper for AC_CHECK_TOOL() which ensures that the search path +# is augmented by the directories mentioned in cs_bin_paths_default. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_TOOL], + [_CS_PROG_PATH_PREPARE + AC_CHECK_TOOL([$1], [$2], [$3], + m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_TOOLS(VARIABLE, TOOLS, [VALUE-IF-NOT-FOUND], [PATH]) +# Simple wrapper for AC_CHECK_TOOLS() which ensures that the search path +# is augmented by the directories mentioned in cs_bin_paths_default. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_TOOLS], + [_CS_PROG_PATH_PREPARE + AC_CHECK_TOOLS([$1], [$2], [$3], + m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) + + +#------------------------------------------------------------------------------ +# CS_PATH_PROG(VARIABLE, PROGRAM, [VALUE-IF-NOT-FOUND], [PATH]) +# Simple wrapper for AC_PATH_PROG() which ensures that the search path +# is augmented by the directories mentioned in cs_bin_paths_default. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_PATH_PROG], + [_CS_PROG_PATH_PREPARE + AC_PATH_PROG([$1], [$2], [$3], + m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) + + +#------------------------------------------------------------------------------ +# CS_PATH_PROGS(VARIABLE, PROGRAMS, [VALUE-IF-NOT-FOUND], [PATH]) +# Simple wrapper for AC_PATH_PROGS() which ensures that the search path +# is augmented by the directories mentioned in cs_bin_paths_default. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_PATH_PROGS], + [_CS_PROG_PATH_PREPARE + AC_PATH_PROGS([$1], [$2], [$3], + m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) + + +#------------------------------------------------------------------------------ +# CS_PATH_TOOL(VARIABLE, TOOL, [VALUE-IF-NOT-FOUND], [PATH]) +# Simple wrapper for AC_PATH_TOOL() which ensures that the search path +# is augmented by the directories mentioned in cs_bin_paths_default. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_PATH_TOOL], + [_CS_PROG_PATH_PREPARE + AC_PATH_TOOL([$1], [$2], [$3], + m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) + + +#------------------------------------------------------------------------------ +# _CS_PROG_PATH_PREPARE +# Ensure that the PATH environment variable mentions the set of +# directories listed in cs_bin_paths_default. These directories may not +# appear by default in the typical PATH, yet they might be common +# locations for tools and commands. +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_PROG_PATH_PREPARE], + [AS_REQUIRE([_AS_PATH_SEPARATOR_PREPARE]) + AS_IF([test "$cs_prog_path_prepared" != yes], + [cs_prog_path_prepared=yes + PATH="$PATH[]m4_foreach([cs_bin_path], [cs_bin_paths_default], + [$PATH_SEPARATOR[]cs_bin_path])" + export PATH])]) + + +#------------------------------------------------------------------------------ +# _CS_PROG_CLIENT_PATH(CLIENT-PATH) +# Given a client-supplied replacement for PATH, augment the list by +# appending the locations mentioned in cs_bin_paths_default. +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_PROG_CLIENT_PATH], + [AS_REQUIRE([_AS_PATH_SEPARATOR_PREPARE])dnl + $1[]m4_foreach([cs_bin_path], [cs_bin_paths_default], + [$PATH_SEPARATOR[]cs_bin_path])]) +# checkpthread.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003-2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_CHECK_PTHREAD([REJECT-MASK]) +# Check for pthread. Also check if the pthread implementation supports +# the recursive and timed mutex extensions. (Timed mutexes are needed for +# the NPTL: New Posix Thread Library on GNU/Linux if the mutex is going +# to be used with any of the timed condition-wait functions.) The shell +# variable cs_cv_sys_pthread is set to "yes" if pthread is available, +# else "no". If available, then the variables cs_cv_sys_pthread_cflags, +# cs_cv_sys_pthread_lflags, and cs_cv_sys_pthread_libs are set. (As a +# convenience, these variables can be emitted to an output file with +# CS_EMIT_BUILD_RESULT() by passing "cs_cv_sys_pthread" as its CACHE-VAR +# argument.) If the recursive mutex extension is supported, then +# cs_cv_sys_pthread_mutex_recursive will be set with the literal name of +# the constant which must be passed to pthread_mutexattr_settype() to +# enable this feature. The constant name will be typically +# PTHREAD_MUTEX_RECURSIVE or PTHREAD_MUTEX_RECURSIVE_NP. If the recursive +# mutex extension is not available, then +# cs_cv_sys_pthread_mutex_recursive will be set to "no". If the timed +# mutex extension is supported, then cs_cv_sys_pthread_mutex_timed will +# be set with the literal name of the constant which must be passed to +# pthread_mutexattr_settype() to enable this feature. The constant name +# will be typically PTHREAD_MUTEX_TIMED or PTHREAD_MUTEX_TIMED_NP. If the +# timed mutex extension is not available, then +# cs_cv_sys_pthread_mutex_timed will be set to "no". REJECT-MASK can be +# used to limit the platforms on which the pthread test is performed. It +# is compared against $host_os; matches are rejected. If omitted, then +# the test is performed on all platforms. Examples: To avoid testing on +# Cygwin, use "cygwin*"; to avoid testing on Cygwin and AIX, use +# "cygwin*|aix*". +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_PTHREAD], + [AC_REQUIRE([AC_CANONICAL_HOST]) + case $host_os in + m4_ifval([$1], + [$1) + cs_cv_sys_pthread=no + ;; + ]) + *) + CS_CHECK_BUILD([for pthread], [cs_cv_sys_pthread], + [AC_LANG_PROGRAM( + [[#include + #include + void* worker(void* p) { (void)p; return p; }]], + [pthread_t tid; + sem_t sem; + pthread_create(&tid, 0, worker, 0); + sem_init(&sem, 0, 0); + sem_destroy(&sem);])], + [cs_pthread_flags]) + ;; + esac + _CS_CHECK_MUTEX_FEATURE([PTHREAD_MUTEX_RECURSIVE], + [cs_cv_sys_pthread_mutex_recursive], [for pthread recursive mutexes])]) + +# _CS_CHECK_MUTEX_FEATURE(FEATURE, CACHE-VAR, MESSAGE) +AC_DEFUN([_CS_CHECK_MUTEX_FEATURE], + [AS_IF([test $cs_cv_sys_pthread = yes], + [AC_CACHE_CHECK([$3], [$2], + [CS_BUILD_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [pthread_mutexattr_t attr; + pthread_mutexattr_settype(&attr, CS_MUTEX_FEATURE);])], + [CS_CREATE_TUPLE([-DCS_MUTEX_FEATURE=$1]) \ + CS_CREATE_TUPLE([-DCS_MUTEX_FEATURE=$1_NP])], + [], + [$2=`echo $cs_build_cflags | sed 's/.*\($1_*N*P*\).*/\1/'`], + [$2=no], + [$cs_cv_sys_pthread_cflags -D_GNU_SOURCE], + [$cs_cv_sys_pthread_lflags], + [$cs_cv_sys_pthread_libs])])], + [$2=no])]) + +#------------------------------------------------------------------------------ +# CS_CHECK_PTHREAD_ATFORK(CACHE-VAR) +# Checks whether the pthread library contains pthread_atfork(). Sets +# CACHE-VAR to "yes" or "no", according to the test result. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_PTHREAD_ATFORK], + [AS_IF([test $cs_cv_sys_pthread = yes], + [AC_CACHE_CHECK([for pthread_atfork support], [$1], + [CS_BUILD_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [pthread_atfork (0, 0, 0);])], + [], [], + [$1=yes], [$1=no], + [$cs_cv_sys_pthread_cflags -D_GNU_SOURCE], + [$cs_cv_sys_pthread_lflags], + [$cs_cv_sys_pthread_libs])])], + [$1=no])]) + +m4_define([cs_pthread_flags], + [CS_CREATE_TUPLE() \ + CS_CREATE_TUPLE([], [], [-lpthread]) \ + CS_CREATE_TUPLE([], [], [-lpthread -lrt]) \ + CS_CREATE_TUPLE([-pthread], [-pthread], []) \ + CS_CREATE_TUPLE([-pthread], [-pthread], [-lpthread]) \ + CS_CREATE_TUPLE([-pthread], [-pthread], [-lc_r])]) +# checktt2.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2004,2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_CHECK_TEMPLATE_TOOLKIT2([EMITTER]) +# Check if Template Toolkit 2 (http://www.tt2.org/) is available. The +# shell variable cs_cv_perl_tt2 is set to "yes" if the package is +# discovered, else "no". Also sets the shell variable TTREE to the name +# path of the 'ttree' utility program and invokes AC_SUBST(). If EMITTER +# is provided and the package was discovered, then +# CS_EMIT_BUILD_PROPERTY() is invoked with EMITTER in order to record the +# value of the TTREE variable in an output file. As a convenience, if +# EMITTER is the literal value "emit" or "yes", then +# CS_EMIT_BUILD_RESULT()'s default emitter will be used. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_TEMPLATE_TOOLKIT2], + [CS_CHECK_PROGS([PERL], [perl5 perl]) + AS_IF([test -n "$PERL"], + [AC_CACHE_CHECK([for TemplateToolkit], [cs_cv_perl_tt2], + [AS_IF([AC_RUN_LOG( + [$PERL -M'Template 2.11' -MTemplate::Plugin -e 0 1>&2])], + [cs_cv_perl_tt2=yes], + [cs_cv_perl_tt2=no])]) + CS_PATH_PROGS([TTREE], [ttree]) + AS_IF([test $cs_cv_perl_tt2 = yes && test -n "$TTREE"], + [CS_EMIT_BUILD_PROPERTY([TTREE], [$TTREE], [], [], + CS_EMITTER_OPTIONAL([$1]))])])]) +# compiler.m4 -*- Autoconf -*- +#============================================================================= +# Copyright (C)2003 by Matze Braun +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================= + +#----------------------------------------------------------------------------- +# Detection of C and C++ compilers and setting flags +# +# CS_PROG_CC +# Detects the C compiler. Also takes care of the CFLAGS, CPPFLAGS and CC +# environment variables. This will filter out all -g and -O from the +# CFLAGS variable because Autoconf's -g and -O defaults are not always +# desired. This will also set the CMD.CC and COMPILER.CFLAGS variables +# in Jamconfig +# CS_PROG_CXX +# Detects the C++ compiler. Also takes care of the CXXFLAGS, CPPFLAGS +# and CXX environment variables. This will filter out all -g and -O from +# the CXXFLAGS variable because Autoconf's -g and -O defaults are not +# always desired. This will also set the CMD.C++ and COMPILER.C++FLAGS +# variables in Jamconfig +# CS_PROG_LINK +# Tries to determine a linker. This is done by checking if a C++ or +# Objecctive-C++ compiler is available in which case it is used for +# linking; otherwise the C or Objective-C compiler is used. This also +# sets the CMD.LINK and COMPILER.LFLAGS variables in Jamconfig and +# respects the LDFLAGS environment variable. Finally, checks if linker +# recognizes -shared and sets PLUGIN.LFLAGS; and checks if linker +# recognizes -soname and sets PLUGIN.LFLAGS.USE_SONAME to "yes". +#----------------------------------------------------------------------------- +AC_DEFUN([CS_PROG_CC],[ + CFLAGS="$CFLAGS" # Filter undesired flags + AS_IF([test -n "$CC"],[ + CS_EMIT_BUILD_PROPERTY([CMD.CC], [$CC]) + CS_EMIT_BUILD_PROPERTY([COMPILER.CFLAGS], [$CPPFLAGS $CFLAGS], [+]) + + # Check if compiler recognizes -pipe directive. + CS_EMIT_BUILD_FLAGS([if $CC accepts -pipe], [cs_cv_prog_cc_pipe], + [CS_CREATE_TUPLE([-pipe])], [C], [COMPILER.CFLAGS], [+]) + ]) +]) + +AC_DEFUN([CS_PROG_CXX],[ + CXXFLAGS="$CXXFLAGS" # Filter undesired flags + AS_IF([test -n "$CXX"],[ + CS_EMIT_BUILD_PROPERTY([CMD.C++], [$CXX]) + + CS_EMIT_BUILD_PROPERTY([COMPILER.C++FLAGS], [$CPPFLAGS $CXXFLAGS], [+]) + + # Check if compiler can be instructed to produce position-independent-code + # (PIC). This feature is required by some platforms when building plugin + # modules and shared libraries. + CS_COMPILER_PIC([C++], [cs_cv_prog_cxx_pic], + [CS_EMIT_BUILD_PROPERTY([COMPILER.C++FLAGS.PIC], + [$cs_cv_prog_cxx_pic])]) + ]) +]) + +AC_DEFUN([CS_PROG_LINK],[ + AC_REQUIRE([CS_PROG_CXX]) + AS_IF([test -n "$CXX"], + [CS_EMIT_BUILD_PROPERTY([CMD.LINK], [AS_ESCAPE([$(CMD.C++)])])], + [CS_EMIT_BUILD_PROPERTY([CMD.LINK], [AS_ESCAPE([$(CMD.CC)])])]) + + CS_EMIT_BUILD_PROPERTY([COMPILER.LFLAGS], [$LDFLAGS], [+]) + + # Check if compiler/linker recognizes -shared directive which is needed for + # linking plugin modules. Unfortunately, the Apple compiler (and possibly + # others) requires extra effort. Even though the compiler does not recognize + # the -shared option, it nevertheless returns a "success" result after emitting + # the warning "unrecognized option `-shared'". Worse, even -Werror fails to + # promote the warning to an error, so we must instead scan the compiler's + # output for an appropriate diagnostic. + CS_CHECK_BUILD_FLAGS([if -shared is accepted], [cs_cv_prog_link_shared], + [CS_CREATE_TUPLE([-shared $cs_cv_prog_cxx_pic])], [C++], + [CS_EMIT_BUILD_PROPERTY([PLUGIN.LFLAGS], [-shared], [+])], [], + [], [], [], [shared]) + + # Check if linker recognizes -soname which is used to assign a name internally + # to plugin modules. + CS_CHECK_BUILD([if -soname is accepted], [cs_cv_prog_link_soname], [], + [CS_CREATE_TUPLE([-Wl,-soname,foobar])], [C++], + [CS_EMIT_BUILD_PROPERTY([PLUGIN.LFLAGS.USE_SONAME], [yes])]) +]) +#------------------------------------------------------------------------------ +# Determine host platform. Recognized families: Unix, Windows, MacOS/X. +# Orginial Macros Copyright (C)2003 Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Determine host CPU. +# +# CS_CHECK_HOST_CPU +# Set the shell variable cs_host_cpu to a normalized form of the CPU name +# returned by config.guess/config.sub. Typically, Crystal Space's +# conception of CPU name is the same as that returned by +# config.guess/config.sub, but there may be exceptions as seen in the +# `case' statement. Also takes the normalized name, uppercases it to +# form a name suitable for the C preprocessor. Additionally sets the +# TARGET.PROCESSOR Jamconfig property. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_HOST_CPU], + [AC_REQUIRE([AC_CANONICAL_HOST]) + case $host_cpu in + [[Ii][3-9]86*|[Xx]86*]) cs_host_cpu=x86 ;; + *) cs_host_cpu=$host_cpu ;; + esac + cs_host_cpu_normalized="AS_TR_CPP([$cs_host_cpu])" + CS_JAMCONFIG_PROPERTY([TARGET.PROCESSOR], [$cs_host_cpu_normalized]) + ]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_HOST +# Sets the shell variables cs_host_target cs_host_family, +# cs_host_os_normalized, and cs_host_os_normalized_uc. Emits appropriate +# CS_PLATFORM_UNIX, CS_PLATFORM_WIN32, CS_PLATFORM_MACOSX via +# AC_DEFINE(), and TARGET.OS and TARGET.OS.NORMALIZED to Jamconfig. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_HOST], + [AC_REQUIRE([AC_CANONICAL_HOST]) + CS_CHECK_HOST_CPU + cs_host_os_normalized='' + case $host_os in + mingw*|cygwin*) + cs_host_target=win32gcc + cs_host_family=windows + ;; + darwin*) + _CS_CHECK_HOST_DARWIN + ;; + *) + # Everything else is assumed to be Unix or Unix-like. + cs_host_target=unix + cs_host_family=unix + ;; + esac + + case $cs_host_family in + windows) + AC_DEFINE([CS_PLATFORM_WIN32], [], + [Define when compiling for Win32]) + AS_IF([test -z "$cs_host_os_normalized"], + [cs_host_os_normalized='Win32']) + ;; + unix) + AC_DEFINE([CS_PLATFORM_UNIX], [], + [Define when compiling for Unix and Unix-like (i.e. MacOS/X)]) + AS_IF([test -z "$cs_host_os_normalized"], + [cs_host_os_normalized='Unix']) + ;; + esac + + cs_host_os_normalized_uc="AS_TR_CPP([$cs_host_os_normalized])" + CS_JAMCONFIG_PROPERTY([TARGET.OS], [$cs_host_os_normalized_uc]) + CS_JAMCONFIG_PROPERTY([TARGET.OS.NORMALIZED], [$cs_host_os_normalized]) +]) + +AC_DEFUN([_CS_CHECK_HOST_DARWIN], + [AC_REQUIRE([CS_PROG_CC]) + AC_REQUIRE([CS_PROG_CXX]) + + # Both MacOS/X and Darwin are identified via $host_os as "darwin". We need + # a way to distinguish between the two. If Carbon.h is present, then + # assume MacOX/S; if not, assume Darwin. If --with-x=yes was invoked, and + # Carbon.h is present, then assume that user wants to cross-build for + # Darwin even though build host is MacOS/X. + # IMPLEMENTATION NOTE *1* + # The QuickTime 7.0 installer removes , which + # causes #include to fail unconditionally. Re-installing + # the QuickTime SDK should restore the header, however not all developers + # know to do this, so we work around the problem of the missing + # CarbonSound.h by #defining __CARBONSOUND__ in the test in order to + # prevent Carbon.h from attempting to #include the missing header. + # IMPLEMENTATION NOTE *2* + # At least one MacOS/X user switches between gcc 2.95 and gcc 3.3 with a + # script which toggles the values of CC, CXX, and CPP. Unfortunately, CPP + # was being set to run the preprocessor directly ("cpp", for instance) + # rather than running it via the compiler ("gcc -E", for instance). The + # problem with running the preprocessor directly is that __APPLE__ and + # __GNUC__ are not defined, which causes the Carbon.h check to fail. We + # avoid this problem by supplying a non-empty fourth argument to + # AC_CHECK_HEADER(), which causes it to test compile the header only (which + # is a more robust test), rather than also testing it via the preprocessor. + + AC_DEFINE([__CARBONSOUND__], [], + [Avoid problem caused by missing ]) + AC_CHECK_HEADER([Carbon/Carbon.h], + [cs_host_macosx=yes], [cs_host_macosx=no], [/* force compile */]) + + AS_IF([test $cs_host_macosx = yes], + [AC_MSG_CHECKING([for --with-x]) + AS_IF([test "${with_x+set}" = set && test "$with_x" = "yes"], + [AC_MSG_RESULT([yes (assume Darwin)]) + cs_host_macosx=no], + [AC_MSG_RESULT([no])])]) + + AS_IF([test $cs_host_macosx = yes], + [cs_host_target=macosx + cs_host_family=unix + cs_host_os_normalized='MacOS/X' + AC_DEFINE([CS_PLATFORM_MACOSX], [], + [Define when compiling for MacOS/X]) + + AC_CACHE_CHECK([for Objective-C compiler], [cs_cv_prog_objc], + [cs_cv_prog_objc="$CC"]) + CS_JAMCONFIG_PROPERTY([CMD.OBJC], [$cs_cv_prog_objc]) + AC_CACHE_CHECK([for Objective-C++ compiler], [cs_cv_prog_objcxx], + [cs_cv_prog_objcxx="$CXX"]) + CS_JAMCONFIG_PROPERTY([CMD.OBJC++], [$cs_cv_prog_objcxx])], + + [cs_host_target=unix + cs_host_family=unix])]) +# diagnose.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_MSG_ERROR(ERROR-DESCRIPTION, [EXIT-STATUS]) +# A convenience wrapper for AC_MSG_ERROR() which invokes AC_CACHE_SAVE() +# before aborting the script. Saving the cache should make subsequent +# re-invocations of the configure script faster once the user has +# corrected the problem(s) which caused the failure. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_MSG_ERROR], + [AC_CACHE_SAVE + AC_MSG_ERROR([$1], [$2])]) +# embed.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003,2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_META_INFO_EMBED([EMITTER], [GPL-OKAY]) +# Determine if plugin meta-information should be embedded or if it should +# exist in a stand-alone .csplugin file, and check if necessary tools and +# libraries are present. Sets the shell variable +# enable_meta_info_embedding to "yes" if the user requested embedding or +# if it was enabled by default; otherwise sets it to "no". +# +# If EMITTER is provided, then a subset of the following variables +# (depending upon platform and availability) are recorded by invoking +# CS_EMIT_BUILD_PROPERTY() with EMITTER. As a convenience, if EMITTER is +# the literal value "emit" or "yes", then CS_EMIT_BUILD_RESULT()'s +# default emitter will be used. +# +# EMBED_META := yes or no +# EMBED_META.CFLAGS := compiler flags +# EMBED_META.LFLAGS := linker flags +# CMD.WINDRES := windres.exe +# OBJCOPY.AVAILABLE := yes or no +# CMD.OBJCOPY := objcopy.exe +# LIBBFD.AVAILABLE := yes or no +# LIBBFD.CFLAGS := libbfd compiler flags +# LIBBFD.LFLAGS := libbfd linker flags +# ELF.AVAILABLE := yes or no +# +# In general, clients need only concern themselves with the various +# EMBED_META-related variables. For building plugin modules, utilize +# EMBED_META.CFLAGS when compiling, and EMBED_META.LFLAGS when linking. +# +# On Unix, when CS' own ELF metadata reader can't be used (because the +# necessary header file elf.h was not found) embedding is accomplished +# via libbfd, which carries a GPL license. Projects which carry licenses +# not compatible with GPL should consider carefully before enabling +# embedding on Unix. If your project is GPL-compatible, then set GPL-OKAY +# to "yes". This will indicate that it is safe to use libbfd if the ELF +# reader can not be used. If your project is not GPL-compatible, then +# set it to "no" in order to disable embedding on Unix if the ELF reader +# is not usable. (The user can still manually override the setting via +# the --enable-meta-info-embedding option.) +# +# IMPLEMENTATION NOTES +# +# Recent versions of Mingw supply libbfd and libiberty. Since Crystal +# Space uses native Win32 API for meta-information embedding on Windows, +# we do not require these libraries on Windows. More importantly, users +# do not want to see these GPL-licensed libraries appear in the link +# statement for plugin modules, thus we explicitly disable the libbfd +# test on Windows. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_META_INFO_EMBED], + [AC_REQUIRE([AC_CANONICAL_HOST]) + _CS_META_INFO_EMBED_ENABLE([$1], [$2]) + AS_IF([test $enable_meta_info_embedding = yes], + [_CS_META_INFO_EMBED_TOOLS([$1]) + AS_IF([test $cs_header_elf_h = yes], + [CS_EMIT_BUILD_PROPERTY([ELF.AVAILABLE], [yes], [], [], + CS_EMITTER_OPTIONAL([$1]))], + [case $host_os in + mingw*|cygwin*) ;; + *) + CS_CHECK_LIBBFD([$1], + [CS_EMIT_BUILD_PROPERTY([EMBED_META.CFLAGS], + [$cs_cv_libbfd_ok_cflags], [+], [], + CS_EMITTER_OPTIONAL([$1])) + CS_EMIT_BUILD_PROPERTY([EMBED_META.LFLAGS], + [$cs_cv_libbfd_ok_lflags $cs_cv_libbfd_ok_libs], + [+], [], CS_EMITTER_OPTIONAL([$1]))]) + ;; + esac])])]) + + +#------------------------------------------------------------------------------ +# _CS_META_INFO_EMBED_ENABLE([EMITTER], [GPL-OKAY]) +# Helper for CS_META_INFO_EMBED which adds an +# --enable-meta-info-embedding option to the configure script allowing +# the user to control embedding. Sets the shell variable +# enable_meta_info_embedding to yes or no. +# +# IMPLEMENTATION NOTES +# +# On Unix, embedding is enabled by default if elf.h is found and disabled +# by default unless overridden via GPL-OKAY because libbfd carries a GPL +# license which may be incompatible with a project's own license (such as +# LGPL). +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_META_INFO_EMBED_ENABLE], + [AC_REQUIRE([CS_CHECK_HOST]) + AC_CHECK_HEADERS([elf.h], [cs_header_elf_h=yes], [cs_header_elf_h=no]) + AC_MSG_CHECKING([whether to embed plugin meta-information]) + case $cs_host_target in + unix) AS_IF([test $cs_header_elf_h = yes], + [cs_embed_meta_info_default=yes], + [cs_embed_meta_info_default=m4_ifval([$2],[$2],[no])]) ;; + *) cs_embed_meta_info_default=yes ;; + esac + AC_ARG_ENABLE([meta-info-embedding], + [AC_HELP_STRING([--enable-meta-info-embedding], + [store plugin meta-information directly inside plugin modules if + supported by platform; if disabled, meta-information is stored in + stand-alone .csplugin files; this option is enabled by default for + non-Unix platforms and on Unix platforms with ELF-format object + files; it is disabled by default on Unix platforms if ELF is not + available and the project uses a non-GPL-compatible license (such + as LGPL) since the non-ELF Unix embedding technology requires the + GPL-licensed libbfd library; if ELF is not available, enable this + option on Unix only if you are certain you want a GPL-licensed + library infecting your project])], + [], [enable_meta_info_embedding=$cs_embed_meta_info_default]) + AC_MSG_RESULT([$enable_meta_info_embedding]) + CS_EMIT_BUILD_PROPERTY([EMBED_META], [$enable_meta_info_embedding], + [], [], CS_EMITTER_OPTIONAL([$1]))]) + + + +#------------------------------------------------------------------------------ +# _CS_META_INFO_EMBED_TOOLS([EMITTER]) +# Helper for CS_META_INFO_EMBED() which searches for tools required for +# plugin meta-info embedding. +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_META_INFO_EMBED_TOOLS], + [CS_CHECK_TOOLS([WINDRES], [windres]) + CS_EMIT_BUILD_PROPERTY([CMD.WINDRES], [$WINDRES], [], [], + CS_EMITTER_OPTIONAL([$1])) + + CS_CHECK_TOOLS([OBJCOPY], [objcopy]) + AS_IF([test -n "$OBJCOPY"], + [CS_EMIT_BUILD_PROPERTY([OBJCOPY.AVAILABLE], [yes], [], [], + CS_EMITTER_OPTIONAL([$1])) + CS_EMIT_BUILD_PROPERTY([CMD.OBJCOPY], [$OBJCOPY], [], [], + CS_EMITTER_OPTIONAL([$1]))])]) + + + +#------------------------------------------------------------------------------ +# CS_CHECK_LIBBFD([EMITTER], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# Exhaustive check for a usable GPL-licensed libbfd, the Binary File +# Descriptor library, a component of binutils, which allows low-level +# manipulation of executable and object files. If EMITTER is provided, +# then the following variables are recorded by invoking +# CS_EMIT_BUILD_PROPERTY() with EMITTER. As a convenience, if EMITTER is +# the literal value "emit" or "yes", then CS_EMIT_BUILD_RESULT()'s +# default emitter will be used. +# +# LIBBFD.AVAILABLE := yes or no +# LIBBFD.CFLAGS := libbfd compiler flags +# LIBBFD.LFLAGS := libbfd linker flags +# +# The shell variable cs_cv_libbfd_ok is set to yes if a usable libbfd was +# discovered, else no. If found, the additional shell variables +# cs_cv_libbfd_ok_cflags, cs_cv_libbfd_ok_lflags, and +# cs_cv_libbfd_ok_libs are also set. +# +# WARNING +# +# libbfd carries a GPL license which is incompatible with the LGPL +# license of Crystal Space. Do not use this library with projects under +# less restrictive licenses, such as LGPL. +# +# IMPLEMENTATION NOTES +# +# It seems that some platforms have two version of libiberty installed: +# one from binutils and one from gcc. The binutils version resides in +# /usr/lib, whereas the gcc version resides in the gcc installation +# directory. The gcc version, by default, takes precedence at link time +# over the binutils version. Unfortunately, in broken cases, the gcc +# version of libiberty is missing htab_create_alloc() which is required +# by some libbfd functions. The extensive secondary check of libbfd +# catches this anomalous case of broken gcc libiberty. It turns out that +# it is possible to make the linker prefer the binutils version by +# specifying -L/usr/lib, thus the extensive test attempts to do so in an +# effort to resolve this unfortunate issue. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_LIBBFD], + [CS_CHECK_LIB_WITH([bfd], + [AC_LANG_PROGRAM([[#include ]], [bfd_init();])], + [], [], [], [], [], [], [-liberty]) + + AS_IF([test $cs_cv_libbfd = yes], + [CS_CHECK_BUILD([if libbfd is usable], [cs_cv_libbfd_ok], + [AC_LANG_PROGRAM([[#include ]], + [bfd* p; + asection* s; + bfd_init(); + p = bfd_openr(0,0); + bfd_check_format(p,bfd_object); + bfd_get_section_by_name(p,0); + bfd_section_size(p,s); + bfd_get_section_contents(p,s,0,0,0); + bfd_close(p);])], + [CS_CREATE_TUPLE() CS_CREATE_TUPLE([],[-L/usr/lib],[])], + [], [], [], [], + [$cs_cv_libbfd_cflags], + [$cs_cv_libbfd_lflags], + [$cs_cv_libbfd_libs])], + [cs_cv_libbfd_ok=no]) + + AS_IF([test $cs_cv_libbfd_ok = yes], + [CS_EMIT_BUILD_RESULT([cs_cv_libbfd_ok], [LIBBFD], + CS_EMITTER_OPTIONAL([$1])) + $2], + [$3])]) +# emit.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003-2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_EMIT_BUILD_PROPERTY(KEY, VALUE, [APPEND], [EMPTY-OKAY], [EMITTER], +# [UNCONDITIONAL]) +# A utility function which invokes an emitter to record the KEY/VALUE +# tuple if VALUE is not the empty string (after leading and trailing +# whitespace is stripped). If EMPTY-OKAY is not an empty string, then the +# property is emitted even if VALUE is empty; that is, it is emitted +# unconditionally. If APPEND is the empty string, then the emitter sets +# the key's value directly (though it may be overridden by the +# environment), otherwise the emitter appends VALUE to the existing value +# of the key. EMITTER is a macro name, such as CS_JAMCONFIG_PROPERTY or +# CS_MAKEFILE_PROPERTY, which performs the actual task of emitting the +# KEY/VALUE tuple; it should also accept APPEND as an optional third +# argument. If EMITTER is omitted, CS_JAMCONFIG_PROPERTY is used. Some +# emitters accept an optional fourth argument, UNCONDITIONAL, which +# instructs it to set KEY's value unconditionally, even if KEY already +# had been assigned a value via some other mechanism (such as imported +# from the environment, or from Jambase, in the case of +# CS_JAMCONFIG_PROPERTY). +#------------------------------------------------------------------------------ +AC_DEFUN([CS_EMIT_BUILD_PROPERTY], + [cs_build_prop_val="$2" + cs_build_prop_val=CS_TRIM([$cs_build_prop_val]) + m4_ifval([$4], + [CS_JAMCONFIG_PROPERTY([$1], [$cs_build_prop_val], [$3])], + AS_IF([test -n "$cs_build_prop_val"], + [m4_default([$5],[CS_JAMCONFIG_PROPERTY])( + [$1], [$cs_build_prop_val], [$3], [$6])]))]) + + + +#------------------------------------------------------------------------------ +# CS_EMIT_BUILD_RESULT(CACHE-VAR, PREFIX, [EMITTER]) +# Record the results of CS_CHECK_BUILD() or CS_CHECK_LIB_WITH() via some +# emitter. If CACHE-VAR indicates that the build succeeded, then the +# following properties are emitted: +# +# PREFIX.AVAILABLE = yes +# PREFIX.CFLAGS = $CACHE-VAR_cflags +# PREFIX.LFLAGS = $CACHE-VAR_lflags $CACHE-VAR_libs +# +# EMITTER is a macro name, such as CS_JAMCONFIG_PROPERTY or +# CS_MAKEFILE_PROPERTY, which performs the actual task of emitting the +# KEY/VALUE tuple. If EMITTER is omitted, CS_JAMCONFIG_PROPERTY is used. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_EMIT_BUILD_RESULT], + [AS_IF([test "$$1" = yes], + [CS_EMIT_BUILD_PROPERTY([$2.AVAILABLE], [yes], [], [], [$3]) + CS_EMIT_BUILD_PROPERTY([$2.CFLAGS], [$$1_cflags], [], [], [$3]) + CS_EMIT_BUILD_PROPERTY([$2.LFLAGS], [$$1_lflags $$1_libs], + [], [], [$3])])]) + + + +#------------------------------------------------------------------------------ +# CS_EMIT_BUILD_FLAGS(MESSAGE, CACHE-VAR, FLAGS, [LANGUAGE], EMITTER-KEY, +# [APPEND], [ACTION-IF-RECOGNIZED], +# [ACTION-IF-NOT-RECOGNIZED], [EMITTER]) +# A convenience wrapper for CS_CHECK_BUILD_FLAGS() which also records the +# results via CS_EMIT_BUILD_PROPERTY(). Checks if the compiler or linker +# recognizes a command-line option. MESSAGE is the "checking" message. +# CACHE-VAR is the shell cache variable which receives the flag +# recognized by the compiler or linker, or "no" if the flag was not +# recognized. FLAGS is a whitespace- delimited list of build tuples +# created with CS_CREATE_TUPLE(). Each tuple from FLAGS is attempted in +# order until one is found which is recognized by the compiler. After +# that, no further flags are checked. LANGUAGE is typically either C or +# C++ and specifies which compiler to use for the test. If LANGUAGE is +# omitted, C is used. EMITTER-KEY is the name to pass as the emitter's +# "key" argument if a usable flag is encountered. If APPEND is not the +# empty string, then the discovered flag is appended to the existing +# value of the EMITTER-KEY. If the command-line option was recognized, +# then ACTION-IF-RECOGNIZED is invoked, otherwise +# ACTION-IF-NOT-RECOGNIZED is invoked. EMITTER is a macro name, such as +# CS_JAMCONFIG_PROPERTY or CS_MAKEFILE_PROPERTY, which performs the +# actual task of emitting the KEY/VALUE tuple; it should also accept +# APPEND as an optional third argument. If EMITTER is omitted, +# CS_JAMCONFIG_PROPERTY is used. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_EMIT_BUILD_FLAGS], + [CS_CHECK_BUILD_FLAGS([$1], [$2], [$3], [$4], + [CS_EMIT_BUILD_PROPERTY([$5], [$$2], [$6], [], [$9]) + $7], + [$8])]) + + + +#------------------------------------------------------------------------------ +# CS_EMITTER_OPTIONAL([EMITTER]) +# The CS_EMIT_FOO() macros optionally accept an emitter. If no emitter is +# supplied to those macros, then a default emitter is chosen. Other +# macros, however, which perform testing and optionally emit the results +# may wish to interpret an omitted EMITTER as a request not to emit the +# results. CS_EMITTER_OPTIONAL() is a convenience macro to help in these +# cases. It should be passed to one of the CS_EMIT_FOO() macros in place +# of the literal EMITTER argument. It functions by re-interpretating +# EMITTER as follows: +# +# - If EMITTER is omitted, then CS_NULL_EMITTER is returned, effectively +# disabling output by the CS_EMIT_FOO() macro. +# - If EMITTER is the literal string "emit" or "yes", then it returns an +# empty string, which signals to the CS_EMIT_FOO() macro that is should +# use its default emitter. +# - Any other value for EMITTER is passed along as-is to the +# CS_EMIT_FOO() macro. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_EMITTER_OPTIONAL], + [m4_case([$1], + [], [[CS_NULL_EMITTER]], + [emit], [], + [yes], [], + [[$1]])]) + + + +#------------------------------------------------------------------------------ +# CS_NULL_EMITTER(KEY, VALUE, [APPEND]) +# A do-nothing emitter suitable for use as the EMITTER argument of one of +# the CS_EMIT_FOO() macros. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_NULL_EMITTER], [: +]) + + + +#------------------------------------------------------------------------------ +# CS_SUBST_EMITTER(KEY, VALUE, [APPEND]) +# An emitter wrapped around AC_SUBST(). Invokes +# AC_SUBST(AS_TR_SH(KEY),VALUE). The APPEND argument is ignored. +# Suitable for use as the EMITTER argument of one of the CS_EMIT_FOO() +# macros. The call to AS_TR_SH() ensures that KEY is transformed into a +# valid shell variable. For instance, if a macro attempts to emit +# MYLIB.CFLAGS and MYLIB.LFLAGS via CS_SUBST_EMITTER(), then the names +# will be transformed to MYLIB_CFLAGS and MYLIB_LFLAGS, respectively, for +# the invocation of AC_SUBST(). +#------------------------------------------------------------------------------ +AC_DEFUN([CS_SUBST_EMITTER], [AC_SUBST(AS_TR_SH([$1]),[$2])]) + + + +#------------------------------------------------------------------------------ +# CS_DEFINE_EMITTER(KEY, VALUE, [APPEND]) +# An emitter wrapped around AC_DEFINE_UNQUOTED(). Invokes +# AC_DEFINE_UNQUOTED(AS_TR_CPP(KEY),VALUE). The APPEND argument is +# ignored. Suitable for use as the EMITTER argument of one of the +# CS_EMIT_FOO() macros. The call to AS_TR_CPP() ensures that KEY is a +# well-formed token for the C-preprocessor. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_DEFINE_EMITTER], + [AC_DEFINE_UNQUOTED(AS_TR_CPP([$1]),[$2], + [Define when feature is available])]) +# headercache.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# Text cache facility for C-style #define properties. The cache is stored in +# the shell variable cs_header_text. +# +# CS_HEADER_APPEND(TEXT) +# Append text to the C header text cache. This is a cover for +# CS_TEXT_CACHE_APPEND(). +# +# CS_HEADER_PREPEND(TEXT) +# Prepend text to the C header text cache. This is a cover for +# CS_TEXT_CACHE_PREPEND(). +# +# CS_HEADER_PROPERTY(KEY, [VALUE]) +# Append a line of the form "#define KEY VALUE" to the C header text +# cache. If the VALUE argument is omitted, then the appended line has +# the simplified form "#define KEY". +# +# CS_HEADER_OUTPUT(FILENAME) +# Instruct config.status to write the C header text cache to the given +# filename. This is a cover for CS_TEXT_CACHE_OUTPUT(). +#------------------------------------------------------------------------------ +AC_DEFUN([CS_HEADER_APPEND], [CS_TEXT_CACHE_APPEND([cs_header_text], [$1])]) +AC_DEFUN([CS_HEADER_PREPEND], [CS_TEXT_CACHE_PREPEND([cs_header_text], [$1])]) +AC_DEFUN([CS_HEADER_PROPERTY], +[CS_HEADER_APPEND([@%:@define $1[]m4_ifval([$2], [ $2], []) +])]) +AC_DEFUN([CS_HEADER_OUTPUT], [CS_TEXT_CACHE_OUTPUT([cs_header_text], [$1])]) +#----------------------------------------------------------------------------- +# installdirs.m4 (c) Matze Braun +# Macro for emitting the installation paths gathered by Autoconf. +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# CS_OUTPUT_INSTALLDIRS([EMITTER], [RAW-BACKSLASHES]) +# Emit installation directories collected by Autoconf. EMITTER is a macro +# name, such as CS_JAMCONFIG_PROPERTY or CS_MAKEFILE_PROPERTY, which performs +# the actual task of emitting the KEY/VALUE tuple. If EMITTER is omitted, +# CS_JAMCONFIG_PROPERTY is used. If RAW-BACKSLASHES is not provided, then +# backslashes in emitted values are each escaped with an additional +# backslash. If RAW-BACKSLASHES is not the null value, then backslashes are +# emitted raw. The following properties are emitted: +# +# prefix +# exec_prefix +# bindir +# sbindir +# libexecdir +# datadir +# sysconfdir +# sharedstatedir +# localstatedir +# libdir +# includedir +# oldincludedir +# infodir +# mandir +#----------------------------------------------------------------------------- +AC_DEFUN([CS_OUTPUT_INSTALLDIRS],[ +# Handle the case when no prefix is given, and the special case when a path +# contains more than 2 slashes, these paths seem to be correct but Jam fails +# on them. +AS_IF([test $prefix = NONE], + [cs_install_prefix="$ac_default_prefix"], + [cs_install_prefix=`echo "$prefix" | sed -e 's:///*:/:g'`]) +AS_IF([test $exec_prefix = NONE], + [cs_install_exec_prefix="AS_ESCAPE([$(prefix)])"], + [cs_install_exec_prefix=`echo "$exec_prefix" | sed -e 's:///*:/:g'`]) + +_CS_OUTPUT_INSTALL_DIRS([$1], [prefix], + [CS_PREPARE_INSTALLPATH([$cs_install_prefix], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [exec_prefix], + [CS_PREPARE_INSTALLPATH([$cs_install_exec_prefix], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [bindir], + [CS_PREPARE_INSTALLPATH([$bindir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [sbindir], + [CS_PREPARE_INSTALLPATH([$sbindir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [libexecdir], + [CS_PREPARE_INSTALLPATH([$libexecdir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [datadir], + [CS_PREPARE_INSTALLPATH([$datadir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [sysconfdir], + [CS_PREPARE_INSTALLPATH([$sysconfdir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [sharedstatedir], + [CS_PREPARE_INSTALLPATH([$sharedstatedir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [localstatedir], + [CS_PREPARE_INSTALLPATH([$localstatedir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [libdir], + [CS_PREPARE_INSTALLPATH([$libdir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [includedir], + [CS_PREPARE_INSTALLPATH([$includedir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [oldincludedir], + [CS_PREPARE_INSTALLPATH([$oldincludedir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [infodir], + [CS_PREPARE_INSTALLPATH([$infodir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [mandir], + [CS_PREPARE_INSTALLPATH([$mandir], [$2])]) +]) + +AC_DEFUN([_CS_OUTPUT_INSTALL_DIRS], + [m4_default([$1], [CS_JAMCONFIG_PROPERTY])([$2], [$3])]) + + +#----------------------------------------------------------------------------- +# CS_PREPARE_INSTALLPATH(VALUE, [RAW-BACKSLASHES]) +# Transform variable references of the form ${bla} to $(bla) in VALUE and +# correctly quotes backslashes. This is needed if you need to emit some of +# the paths from Autoconf. RAW-BACKSLASHES has the same meaning as in +# CS_OUTPUT_INSTALLDIRS. +#----------------------------------------------------------------------------- +AC_DEFUN([CS_PREPARE_INSTALLPATH], +[`echo "$1" | sed 's/\${\([[a-zA-Z_][a-zA-Z_]]*\)}/$(\1)/g;m4_ifval([$2], + [s/\\/\\\\/g], [s/\\\\/\\\\\\\\/g])'`]) +# jamcache.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# Text cache facility for Jam-style properties. The cache is stored in +# the shell variable cs_jamfile_text. +# +# CS_JAMCONFIG_APPEND(TEXT) +# Append text to the Jam text cache. This is a cover for +# CS_TEXT_CACHE_APPEND(). +# +# CS_JAMCONFIG_PREPEND(TEXT) +# Prepend text to the Jam text cache. This is a cover for +# CS_TEXT_CACHE_PREPEND(). +# +# CS_JAMCONFIG_PROPERTY(KEY, VALUE, [APPEND], [UNCONDITIONAL]) +# Append a line of the form "KEY ?= VALUE" to the Jam text cache. If the +# APPEND argument is not the empty string, then VALUE is appended to the +# existing value of KEY using the form "KEY += VALUE". If the +# UNCONDITIONAL argument is not empty, then the value of KEY is set +# unconditionally "KEY = VALUE", rather than via "KEY ?= VALUE". APPEND +# takes precedence over UNCONDITIONAL. Note that if VALUE references +# other Jam variables, for example $(OBJS), then be sure to protect the +# value with AS_ESCAPE(). For example: +# CS_JAMCONFIG_PROPERTY([ALLOBJS], [AS_ESCAPE([$(OBJS) $(LIBOBJS)])]) +# +# CS_JAMCONFIG_OUTPUT(FILENAME) +# Instruct config.status to write the Jam text cache to the given +# filename. This is a cover for CS_TEXT_CACHE_OUTPUT(). +#------------------------------------------------------------------------------ +AC_DEFUN([CS_JAMCONFIG_APPEND], + [CS_TEXT_CACHE_APPEND([cs_jamconfig_text], [$1])]) +AC_DEFUN([CS_JAMCONFIG_PREPEND], + [CS_TEXT_CACHE_PREPEND([cs_jamconfig_text], [$1])]) +AC_DEFUN([CS_JAMCONFIG_PROPERTY], + [CS_JAMCONFIG_APPEND( + [$1 m4_ifval([$3], [+=], m4_ifval([$4], [=], [?=])) \"$2\" ; +])]) +AC_DEFUN([CS_JAMCONFIG_OUTPUT], + [CS_TEXT_CACHE_OUTPUT([cs_jamconfig_text], [$1])]) +# makecache.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# Text cache facility for makefile-style properties. The cache is stored in +# the shell variable cs_makefile_text. +# +# CS_MAKEFILE_APPEND(TEXT) +# Append text to the makefile text cache. This is a cover for +# CS_TEXT_CACHE_APPEND(). +# +# CS_MAKEFILE_PREPEND(TEXT) +# Prepend text to the makefile text cache. This is a cover for +# CS_TEXT_CACHE_PREPEND(). +# +# CS_MAKEFILE_PROPERTY(KEY, VALUE, [APPEND]) +# Append a line of the form "KEY = VALUE" to the makefile text cache. If +# the APPEND argument is not the empty string, then VALUE is appended to +# the existing value of KEY using the form "KEY += VALUE". Note that if +# VALUE references other makefile variables, for example $(OBJS), then be +# sure to protect the value with AS_ESCAPE(). For example: +# CS_MAKEFILE_PROPERTY([ALLOBJS], [AS_ESCAPE([$(OBJS) $(LIBOBJS)])]) +# +# CS_MAKEFILE_OUTPUT(FILENAME) +# Instruct config.status to write the makefile text cache to the given +# filename. This is a cover for CS_TEXT_CACHE_OUTPUT(). +#------------------------------------------------------------------------------ +AC_DEFUN([CS_MAKEFILE_APPEND], + [CS_TEXT_CACHE_APPEND([cs_makefile_text], [$1])]) +AC_DEFUN([CS_MAKEFILE_PREPEND], + [CS_TEXT_CACHE_PREPEND([cs_makefile_text], [$1])]) +AC_DEFUN([CS_MAKEFILE_PROPERTY], + [CS_MAKEFILE_APPEND([$1 m4_ifval([$3], [+=], [=]) $2 +])]) +AC_DEFUN([CS_MAKEFILE_OUTPUT],[CS_TEXT_CACHE_OUTPUT([cs_makefile_text], [$1])]) +# mkdir.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_CHECK_MKDIR +# Determine how to create a directory and a directory tree. Sets the +# shell variable MKDIR to the command which creates a directory, and +# MKDIRS to the command which creates a directory tree. Invokes +# AC_SUBST() for MKDIR and MKDIRS. +# +# IMPLEMENTATION NOTES +# We need to know the exact commands, so that we can emit them, thus the +# AS_MKDIR_P function is not what we want to use here since it does not +# provide access to the commands (and might not even discover suitable +# commands). First try "mkdir -p", then try the older "mkdirs". +# Finally, if the mkdir command failed to recognize -p, then it might +# have created a directory named "-p", so clean up that bogus directory. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_MKDIR], + [AC_CACHE_CHECK([how to create a directory], [cs_cv_shell_mkdir], + [cs_cv_shell_mkdir='mkdir']) + AC_SUBST([MKDIR], [$cs_cv_shell_mkdir]) + + AC_CACHE_CHECK([how to create a directory tree], [cs_cv_shell_mkdir_p], + [if $cs_cv_shell_mkdir -p . 2>/dev/null; then + cs_cv_shell_mkdir_p='mkdir -p' + elif mkdirs . 2>/dev/null; then + cs_cv_shell_mkdir_p='mkdirs' + fi + test -d ./-p && rmdir ./-p]) + AS_VAR_SET_IF([cs_cv_shell_mkdir_p], + [AC_SUBST([MKDIRS], [$cs_cv_shell_mkdir_p])], + [CS_MSG_ERROR([do not know how to create a directory tree])])]) + + + +#------------------------------------------------------------------------------ +# Replacement for AS_MKDIR_P() from m4sugar/m4sh.m4 which fixes two problems +# which are present in Autoconf 2.57 and probably all earlier 2.5x versions. +# This bug, along with a patch, was submitted to the Autoconf GNATS database by +# Eric Sunshine as #227 on 17-Dec-2002. The bogus "-p" directory bug was fixed +# for Autoconf 2.58 on 26-Sep-2003. The "mkdirs" optimization was not accepted +# (since it is unnecessary; it's only an optimization). +# +# 1) Removes bogus "-p" directory which the stock AS_MKDIR_P() leaves laying +# around in the working directory if the mkdir command does not recognize +# the -p option. +# 2) Takes advantage of the older "mkdirs" program if it exists and if "mkdir +# -p" does not work. +#------------------------------------------------------------------------------ +m4_defun([_AS_MKDIR_P_PREPARE], +[if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p' +elif mkdirs . 2>/dev/null; then + as_mkdir_p='mkdirs' +else + as_mkdir_p='' +fi +test -d ./-p && rmdir ./-p +])# _AS_MKDIR_P_PREPARE + +m4_define([AS_MKDIR_P], +[AS_REQUIRE([_$0_PREPARE])dnl +{ if test -n "$as_mkdir_p"; then + $as_mkdir_p $1 + else + as_dir=$1 + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`AS_DIRNAME("$as_dir")` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || AS_ERROR([cannot create directory $1]); } +])# AS_MKDIR_P +#============================================================================== +# packageinfo.m4 +# Macros for setting general info on the package, such as name and version +# numbers and propagate them to the generated make and Jam property files. +# +# Copyright (C)2003 by Matthias Braun +# Copyright (C)2003,2004 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== + +#------------------------------------------------------------------------------ +# CS_PACKAGEINFO([LONGNAME], [COPYRIGHT, [HOMEPAGE]) +# Set additional information for the package. Note that the version +# number of your application should only contain numbers, because on +# Windows you can only set numerical values in some of the file +# properties (such as versioninfo .rc files). +#------------------------------------------------------------------------------ +AC_DEFUN([CS_PACKAGEINFO], + [PACKAGE_LONGNAME="[$1]" + PACKAGE_COPYRIGHT="[$2]" + PACKAGE_HOMEPAGE="[$3]" +]) + + +#------------------------------------------------------------------------------ +# CS_EMIT_PACKAGEINFO([EMITTER]) +# Emit extended package information using the provided EMITTER. EMITTER +# is a macro name, such as CS_JAMCONFIG_PROPERTY or CS_MAKEFILE_PROPERTY, +# which performs the actual task of emitting the KEY/VALUE tuple. If +# EMITTER is omitted, CS_JAMCONFIG_PROPERTY is used. For backward +# compatibility, if EMITTER is the literal value "jam", then +# CS_JAMCONFIG_PROPERTY is used; if it is "make", then +# CS_MAKEFILE_PROPERTY is used; however use of these literal names is +# highly discouraged. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_EMIT_PACKAGEINFO], + [_CS_EMIT_PACKAGEINFO([$1], [PACKAGE_NAME], [$PACKAGE_NAME]) + _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_VERSION], [$PACKAGE_VERSION]) + _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_STRING], [$PACKAGE_STRING]) + _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_BUGREPORT], [$PACKAGE_BUGREPORT]) + _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_LONGNAME], [$PACKAGE_LONGNAME]) + _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_HOMEPAGE], [$PACKAGE_HOMEPAGE]) + _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_COPYRIGHT], [$PACKAGE_COPYRIGHT]) + for cs_veritem in m4_translit(AC_PACKAGE_VERSION, [.], [ ]); do + _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_VERSION_LIST], [$cs_veritem], [+]) + done + ]) + +AC_DEFUN([_CS_EMIT_PACKAGEINFO], + [m4_case([$1], + [make], [CS_MAKEFILE_PROPERTY([$2], [$3], [$4])], + [jam], [CS_JAMCONFIG_PROPERTY([$2], [$3], [$4])], + [], [CS_JAMCONFIG_PROPERTY([$2], [$3], [$4])], + [$1([$2], [$3], [$4])])]) +# path.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2004 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_PATH_NORMALIZE(STRING) +# Normalize a pathname at run-time by transliterating Windows/DOS +# backslashes to forward slashes. Also collapses whitespace. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_PATH_NORMALIZE], +[`echo "x$1" | tr '\\\\' '/' | sed 's/^x//;s/ */ /g;s/^ //;s/ $//'`]) + + +#------------------------------------------------------------------------------ +# CS_RUN_PATH_NORMALIZE(COMMAND) +# Normalize the pathname emitted by COMMAND by transliterating +# Windows/DOS backslashes to forward slashes. Also collapses whitespace. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_RUN_PATH_NORMALIZE], +[`AC_RUN_LOG([$1]) | tr '\\\\' '/' | sed 's/^x//;s/ */ /g;s/^ //;s/ $//'`]) +############################################################################### +# progver.m4 +# Written by Norman Kramer +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +############################################################################### +# +# From the input pattern we create regular expressions we send through sed +# to extract the version information from the standard input to sed. +# Then we extract from the resulting version string subparts. +# The same happens with the supplied version string. It too is split into its +# subparts according to the pattern. +# Then the subparts from the gathered version string and the supplied one are +# compared. +# +# How does the pattern look like ? +# It is a sequence of 9s and _s and separators. +# 9 denotes a non empty sequence of digits. +# _ denotes a non empty sequence of characters from the class [a-zA-Z]. +# | everything behind is optional +# Everything else is treated as a separator. +# Consecutive 9s and _s are compressed to contain only one of each type. +# For instance "99_.9.__abc9_" will become "9_.9._abc9_". +# +# How we find the parts we compare ? +# From this transformed string we yield the parts we will later compare. +# We break up the string as follows: +# Any sequence of separators represent one breakup. Additional breakups are +# placed behind every 9 and _ . +# So the example from above will give: +# +# "99_.9.__abc9_" ===compress==> "9_.9._abc9_" ===breakup==> "9" "_" "9" "_" "9" "_" +# +# How we create the regular expressions ? +# We take the compressed pattern and quote every separator. +# The we replace the 9s with [0-9][0-9]* +# and the _s with [a-zA-Z][a-zA-Z]* . +# The above example will become: +# +# "99_.9.__abc9_" ===compress==> "9_.9._abc9_" ===rexify==> +# [0-9][0-9]*[a-zA-Z][a-zA-Z]*\.[0-9][0-9]*\.[a-zA-Z][a-zA-Z]*\a\b\c[0-9][0-9]*[a-zA-Z][a-zA-Z]* +# +# Voila. +# +# To yield the subparts from the string we additionally enclose the +# 9s and _s with \( and \). +# +############################################################################### + +# **************************************************************** +# ** helper definitions ** +# **************************************************************** +m4_define([CS_VCHK_RUNTH], [m4_pushdef([i], [$1])m4_if($1,0,,[CS_VCHK_RUNTH(m4_decr($1), [$2])][$2])m4_popdef([i])]) +m4_define([CS_VCHK_PREFIX], []) +m4_define([CS_VCHK_SUFFIX], []) +m4_define([CS_VCHK_GROUPPREFIX], [\(]) +m4_define([CS_VCHK_GROUPSUFFIX], [\)]) +m4_define([CS_VCHK_CHAR], [[[[a-zA-Z]]]]) +m4_define([CS_VCHK_DIGIT], [[[0-9]]]) +m4_define([CS_VCHK_SEQUENCE], [CS_VCHK_PREFIX[]CS_VCHK_SINGLE[]CS_VCHK_SINGLE[]*CS_VCHK_SUFFIX[]]) +m4_define([CS_VCHK_OPTSEQUENCE], [CS_VCHK_PREFIX[]CS_VCHK_SINGLE[]*CS_VCHK_SUFFIX[]]) +m4_define([CS_VCHK_REXSEQ], [m4_bpatsubst($1, [$2], [[]CS_VCHK_SEQUENCE[]])]) +m4_define([CS_VCHK_GROUPINGON], [m4_pushdef([CS_VCHK_PREFIX], [CS_VCHK_GROUPPREFIX])m4_pushdef([CS_VCHK_SUFFIX], [CS_VCHK_GROUPSUFFIX])]) +m4_define([CS_VCHK_GROUPINGOFF], [m4_popdef([CS_VCHK_SUFFIX])m4_popdef([CS_VCHK_PREFIX])]) +m4_define([CS_VCHK_OPTON], [m4_pushdef([CS_VCHK_SEQUENCE], [CS_VCHK_OPTSEQUENCE])]) +m4_define([CS_VCHK_OPTOFF], [m4_popdef([CS_VCHK_SEQUENCE])]) +m4_define([CS_VCHK_RMOPT], [CS_VCHK_RMCHAR([$1], m4_index([$1], [|]))]) +m4_define([CS_VCHK_RMCHAR], [m4_if($2,-1,[$1],m4_substr([$1], 0, $2)[]m4_substr([$1], m4_incr($2)))]) +m4_define([CS_VCHK_RMALL], [m4_translit([$1], [|], [])]) +m4_define([CS_VCHK_CUTOFF], [m4_if(m4_index($1,[|]),-1, [$1], [m4_substr($1, 0, m4_index($1,[|]))])]) +m4_define([CS_VCHK_CYCLEOPT], [ +m4_if($2,-1,, [m4_pushdef([i], CS_VCHK_CUTOFF([$1])) m4_pushdef([j], CS_VCHK_DUMMY_TAIL([$1])) CS_VCHK_CYCLEOPT( CS_VCHK_RMOPT([$1]), m4_index($1, [|]), [$3])$3 m4_popdef([i]) m4_popdef([j])]) +]) +m4_define([CS_VCHK_TAIL], [m4_if(m4_index($1,[|]),-1, [], [m4_substr($1, m4_incr(m4_index($1,[|])))])]) +m4_define([CS_VCHK_DUMMY_COMPRESS], [m4_bpatsubst(m4_bpatsubst([$1], [__*], [A]), [99*], [0])]) +m4_define([CS_VCHK_DUMMY_TAIL], [CS_VCHK_DUMMY_COMPRESS(m4_translit(CS_VCHK_TAIL([$1]), [|], []))]) + +# **************************************************************** +# ** FlagsOn / FlagsOff ** +# **************************************************************** +m4_define([CS_VCHK_FLAGSON], +[m4_if($#, 0, [], + $1, [], [], + [$1], [group], [CS_VCHK_GROUPINGON[]], + [$1], [opt], [CS_VCHK_OPTON[]])dnl +m4_if($#, 0, [], $1, [], [], [CS_VCHK_FLAGSON(m4_shift($@))])]) + +m4_define([CS_VCHK_FLAGSOFF], +[m4_if($#, 0, [], + $1, [], [], + $1, [group], [CS_VCHK_GROUPINGOFF[]], + [$1], [opt], [CS_VCHK_OPTOFF[]])dnl +m4_if($#, 0, [], $1, [], [], [CS_VCHK_FLAGSOFF(m4_shift($@))])]) + +# **************************************************************** +# ** rexify / sedify ** +# **************************************************************** +m4_define([CS_VCHK_REXIFY], +[m4_pushdef([CS_VCHK_SINGLE], [$1])dnl +CS_VCHK_FLAGSON(m4_shift(m4_shift(m4_shift($@))))dnl +CS_VCHK_REXSEQ([$3], [$2])dnl +CS_VCHK_FLAGSOFF(m4_shift(m4_shift(m4_shift($@))))dnl +m4_popdef([CS_VCHK_SINGLE])]) + +m4_define([CS_VCHK_QUOTESEP], [m4_bpatsubst($1, [[^9_]], [\\\&])]) + +m4_define([CS_VCHK_REXCHAR], [CS_VCHK_REXIFY([CS_VCHK_CHAR], [__*], $@)]) +m4_define([CS_VCHK_REXDIGIT], [CS_VCHK_REXIFY([CS_VCHK_DIGIT], [99*], $@)]) +m4_define([CS_VCHK_SEDIFY], [CS_VCHK_REXDIGIT([CS_VCHK_REXCHAR([CS_VCHK_QUOTESEP([$1])], m4_shift($@))], m4_shift($@))]) +m4_define([CS_VCHK_SEDEXPRALL], [/CS_VCHK_SEDIFY([$1])/!d;s/.*\(CS_VCHK_SEDIFY([$1])\).*/\1/;q]) +m4_define([CS_VCHK_SEDEXPRNTH], [/CS_VCHK_SEDIFY([$1])/!d;s/.*CS_VCHK_SEDIFY([$1],[group]).*/\$2/]) + +# **************************************************************** +# ** Pattern splitting ** +# **************************************************************** +m4_define([CS_VCHK_SPLITSEP], [CS_VCHK_REXIFY([s], [[^9_][^9_]*], $@)]) +m4_define([CS_VCHK_SPLITDIGIT], [CS_VCHK_REXIFY([d], [99*], $@)]) +m4_define([CS_VCHK_SPLITCHAR], [CS_VCHK_REXIFY([c], [__*], $@)]) + +# **************************************************************** +# ** return a list of 's' 'd' 'c' 'e' chars denoting the kind ** +# ** pattern parts: separator, digit, char, end ** +# **************************************************************** +m4_define([CS_VCHK_PATTERNLIST], [m4_pushdef([CS_VCHK_SEQUENCE], [CS_VCHK_SINGLE ])dnl +m4_translit(CS_VCHK_SPLITDIGIT([CS_VCHK_SPLITCHAR([CS_VCHK_SPLITSEP([$1])])]), [ ], m4_if([$2],[],[ ],[$2]))e[]dnl +m4_popdef([CS_VCHK_SEQUENCE])]) + +# **************************************************************** +# ** Build the shell commands we emit to the configure script. ** +# **************************************************************** +m4_define([CS_VCHK_PATCOUNT], [m4_len(m4_bpatsubst(CS_VCHK_PATTERNLIST([$1]), [[^dc]]))]) + +# **************************************************************************************** +# ** CS_VCHK_EXTRACTVERSION(EXTRACT_CALL, MIN_VERSION, PATTERN, PRGPREFIX, COMPARISION) ** +# **************************************************************************************** +m4_define([CS_VCHK_EXTRACTVERSION], +[cs_prog_$4_is_version= +cs_prog_$4_min_version= +cs_prog_$4_is_suffix= +cs_prog_$4_min_suffix= +cs_prog_$4_is_suffix_done= +cs_prog_$4_min_suffix_done= +CS_VCHK_CYCLEOPT([$3], [], +[test -z $cs_prog_$4_is_version && cs_prog_$4_is_version=`$1 | sed 'CS_VCHK_SEDEXPRALL([i])'` +test -n "$cs_prog_$4_is_version" && test -z $cs_prog_$4_is_suffix_done && { cs_prog_$4_is_suffix_done=yes ; cs_prog_$4_is_suffix=j ; } +]) +CS_VCHK_CYCLEOPT([$3], , +[test -z $cs_prog_$4_min_version && cs_prog_$4_min_version=`echo $2 | sed 'CS_VCHK_SEDEXPRALL([i])'` +test -n "$cs_prog_$4_min_version" && test -z $cs_prog_$4_min_suffix_done && { cs_prog_$4_min_suffix_done=yes ; cs_prog_$4_min_suffix=j ; } +]) +CS_VCHK_RUNTH([CS_VCHK_PATCOUNT([$3])], + [cs_prog_$4_is_ver_[]i=`echo ${cs_prog_$4_is_version}${cs_prog_$4_is_suffix} | sed 'CS_VCHK_SEDEXPRNTH([CS_VCHK_RMALL([$3])], [i])'` +]) +CS_VCHK_RUNTH([CS_VCHK_PATCOUNT([$3])], + [cs_prog_$4_min_ver_[]i=`echo $cs_prog_$4_min_version${cs_prog_$4_min_suffix} | sed 'CS_VCHK_SEDEXPRNTH([CS_VCHK_RMALL([$3])], [i])'` +]) +cs_cv_prog_$4_version_ok='' +CS_VCHK_RUNTH([CS_VCHK_PATCOUNT([$3])], +[test -z "$cs_cv_prog_$4_version_ok" && { expr "$cs_prog_$4_is_ver_[]i" "$5" "$cs_prog_$4_min_ver_[]i" >/dev/null || cs_cv_prog_$4_version_ok=no ; } +test -z "$cs_cv_prog_$4_version_ok" && { expr "$cs_prog_$4_min_ver_[]i" "$5" "$cs_prog_$4_is_ver_[]i" >/dev/null || cs_cv_prog_$4_version_ok=yes ; } +]) +AS_IF([test -z "$cs_cv_prog_$4_version_ok"], [cs_cv_prog_$4_version_ok=yes]) +cs_cv_prog_$4_version_ok_annotated="$cs_cv_prog_$4_version_ok" +AS_IF([test -n "$cs_prog_$4_is_version"], + [cs_cv_prog_$4_version_ok_annotated="$cs_cv_prog_$4_version_ok_annotated (version $cs_prog_$4_is_version)"]) +]) + +############################################################################## +# CS_CHECK_PROG_VERSION(PROG, EXTRACT_CALL, VERSION, PATTERN, +# [ACTION-IF-OKAY], [ACTION-IF-NOT-OKAY], [CMP]) +# Check the version of a program PROG. +# Version information is emitted by EXTRACT_CALL (for instance "bison -V"). +# The discovered program version is compared against VERSION. +# The pattern of the version string matches PATTERN +# The extracted version and the supplied version are compared with the CMP +# operator. i.e. EXTRACTED_VERSION CMP SUPPLIED_VERSION +# CMP defaults to >= if not specified. +# ACTION-IF-OKAY is invoked if comparision yields true, otherwise +# ACTION-IF-NOT-OKAY is invoked. +# +# PATTERN literals: 9 .. marks a non empty sequence of digits +# _ .. marks a non empty sequence of characters from [a-zA-Z] +# | .. everything behind is optional +# .. everything else is taken as separator - it is better +# to not try stuff like space, slash or comma. +# +# The test results in cs_cv_prog_PROG_version_ok being either yes or no. +############################################################################## +AC_DEFUN([CS_CHECK_PROG_VERSION], +[AC_CACHE_CHECK([if $1 version m4_default([$7],[>=]) $3], + [AS_TR_SH([cs_cv_prog_$1_version_ok_annotated])], + [CS_VCHK_EXTRACTVERSION([$2], [$3], [$4], AS_TR_SH([$1]), + m4_default([$7],[>=]))]) +AS_IF([test "$AS_TR_SH([cs_cv_prog_$1_version_ok])" = yes], [$5], [$6])]) +# qualify.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_SYMBOL_QUALIFIER(MESSAGE, CACHE-VAR, QUALIFIERS, [SYMBOL], [LANG], +# [ACTION-IF-ACCEPTED], [ACTION-IF-NOT-ACCEPTED]) +# Test if a symbol can be qualified by one of the elements of the +# comma-separated list of QUALIFIERS. Examples of qualifiers include +# __attribute__((deprecated)), __declspec(dllimport), etc. MESSAGE is the +# "checking" message. CACHE-VAR is the variable which receives the +# qualifier which succeeded, or the the literal "no" if none were +# accepted. SYMBOL is the symbol to which the qualifier should be +# applied. If omitted, then SYMBOL defaults to "void f();". LANG is the +# language of the test, typically "C" or "C++". It defaults to "C" if +# omitted. ACTION-IF-ACCEPTED is invoked after CACHE-VAR is set if one of +# the qualifiers is accepted, else ACTION-IF-NOT-ACCEPTED is invoked. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_SYMBOL_QUALIFIER], + [AC_CACHE_CHECK([$1], [$2], + [$2='no' + m4_foreach([cs_symbol_qualifier], [$3], + [AS_IF([test "$$2" = no], + [CS_BUILD_IFELSE( + [AC_LANG_PROGRAM( + [cs_symbol_qualifier m4_default([$4],[void f()]);], + [])], + [], [$5], [$2='cs_symbol_qualifier'], [$2='no'])])])]) + AS_IF([test $$2 != no], [$6], [$7])]) +# split.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_SPLIT(LINE, [OUTPUT-VARIABLES], [DELIMITER], [FILLER]) +# Split LINE into individual tokens. Tokens are delimited by DELIMITER, +# which is the space character if omitted. OUTPUT-VARIABLES is a +# comma-delimited list of shell variables which should receive the +# extracted tokens. If there are too few tokens to fill the output +# variables, then the excess variables will be assigned the empty string. +# If there are too few output variables, then the excess tokens will be +# ignored. If OUTPUT-VARIABLES is omitted, then the split tokens will be +# assigned to the shell meta-variables $1, $2, $3, etc. When +# OUTPUT-VARIABLES is omitted, FILLER is assigned to meta-variables in +# cases where DELIMITER delimits a zero-length token. FILLER defaults +# to "filler". For example, if DELIMITER is "+" and OUTPUT-VARIABLES is +# omitted, given the line "one++three", $1 will be "one", $2 will be +# "filler", and $3 will be "three". +#------------------------------------------------------------------------------ +AC_DEFUN([CS_SPLIT], + [m4_define([cs_split_filler], m4_default([$4],[filler])) + set cs_split_filler `echo "$1" | awk 'BEGIN { FS="m4_default([$3],[ ])" } + { for (i=1; i <= NF; ++i) + { if ($i == "") print "cs_split_filler"; else print $i } }'` + shift + m4_map([_CS_SPLIT], [$2])]) + +AC_DEFUN([_CS_SPLIT], + [AS_IF([test $[@%:@] -eq 0], [$1=''], + [AS_IF([test "$[1]" = cs_split_filler], [$1=''], [$1=$[1]]) + shift])]) +# textcache.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# Text cache facility. These macros provide a way to incrementally store +# arbitrary text in a shell variable, and to write the saved text to a file. +# +# CS_TEXT_CACHE_APPEND(VARIABLE, TEXT) +# Append text to the contents of the named shell variable. If the text +# contains references to shell variables (such as $foo), then those +# references will be expanded. If expansion is not desired, then protect +# the text with AS_ESCAPE(). +# +# CS_TEXT_CACHE_PREPEND(VARIABLE, TEXT) +# Prepend text to the contents of the named shell variable. If the text +# contains references to shell variables (such as $foo), then those +# references will be expanded. If expansion is not desired, then protect +# the text with AS_ESCAPE(). +# +# CS_TEXT_CACHE_OUTPUT(VARIABLE, FILENAME) +# Instruct config.status to write the contents of the named shell +# variable to the given filename. If the file resides in a directory, +# the directory will be created, if necessary. If the output file +# already exists, and if the cached text is identical to the contents of +# the existing file, then the existing file is left alone, thus its time +# stamp remains unmolested. This heuristic may help to minimize rebuilds +# when the file is listed as a dependency in a makefile. +# +# *NOTE* +# There is a bug in Autoconf 2.57 and probably all earlier 2.5x versions +# which results in errors if AC_CONFIG_COMMANDS is invoked for a `tag' +# which represents a file in a directory which does not yet exist. +# Unfortunately, even invoking AS_MKDIR_P in the `cmd' portion of +# AC_CONFIG_COMMANDS does not solve the problem because the generated +# configure script attempts to access information about the directory +# before AS_MKDIR_P has a chance to create it. This forces us to invoke +# AS_MKDIR_P in the third argument to AC_CONFIG_COMMANDS (the +# `init-cmds') rather than the second (the `cmds'). This is undesirable +# because it means that the directory will be created anytime +# config.status is invoked (even for a simple --help), rather than being +# created only when requested to output the text cache. This bug was +# submitted to the Autoconf GNATS database by Eric Sunshine as #228 on +# 27-Dec-2002. It was fixed for Autoconf 2.58 on 26-Sep-2003. The +# official fix makes the assumption that `tag' always represents a file +# (as opposed to some generic target), and creates the file's directory +# is not present. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_TEXT_CACHE_APPEND], [$1="${$1}$2"]) +AC_DEFUN([CS_TEXT_CACHE_PREPEND], [$1="$2${$1}"]) +AC_DEFUN([CS_TEXT_CACHE_OUTPUT], + [AC_CONFIG_COMMANDS([$2], + [echo $ECHO_N "$$1$ECHO_C" > $tmp/tcache + AS_IF([diff $2 $tmp/tcache >/dev/null 2>&1], + [AC_MSG_NOTICE([$2 is unchanged])], + [rm -f $2 + cp $tmp/tcache $2]) + rm -f $tmp/tcache], + [$1='$$1' + cs_dir=`AS_DIRNAME([$2])` + AS_ESCAPE(AS_MKDIR_P([$cs_dir]), [$`\])])]) +# trim.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_TRIM(STRING) +# Strip leading and trailing spaces from STRING and collapse internal +# runs of multiple spaces to a single space. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_TRIM], [`echo x$1 | sed 's/^x//;s/ */ /g;s/^ //;s/ $//'`]) +# warnings.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_COMPILER_WARNINGS([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# Check how to enable compilation warnings. If LANGUAGE is not provided, +# then `C' is assumed (other options include `C++'). If CACHE-VAR is not +# provided, then it defaults to the name +# "cs_cv_prog_compiler_enable_warnings". If an option for enabling +# warnings (such as `-Wall') is discovered, then it is assigned to +# CACHE-VAR and ACTION-IF-FOUND is invoked; otherwise the empty string is +# assigned to CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. +# +# IMPLEMENTATION NOTES +# +# On some platforms, it is more appropriate to use -Wmost rather than +# -Wall even if the compiler understands both, thus we attempt -Wmost +# before -Wall. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_COMPILER_WARNINGS], + [CS_CHECK_BUILD_FLAGS( + [how to enable m4_default([$1],[C]) compilation warnings], + [m4_default([$2],[cs_cv_prog_compiler_enable_warnings])], + [CS_CREATE_TUPLE([-Wmost]) CS_CREATE_TUPLE([-Wall])], + [$1], [$3], [$4])]) + + + +#------------------------------------------------------------------------------ +# CS_COMPILER_ERRORS([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# Check how to promote compilation diganostics from warning to error +# status. If LANGUAGE is not provided, then `C' is assumed (other options +# include `C++'). If CACHE-VAR is not provided, then it defaults to the +# name "cs_cv_prog_compiler_enable_errors". If an option for performing +# this promotion (such as `-Werror') is discovered, then it is assigned +# to CACHE-VAR and ACTION-IF-FOUND is invoked; otherwise the empty string +# is assigned to CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_COMPILER_ERRORS], + [CS_CHECK_BUILD_FLAGS( + [how to treat m4_default([$1],[C]) warnings as errors], + [m4_default([$2],[cs_cv_prog_compiler_enable_errors])], + [CS_CREATE_TUPLE([-Werror])], [$1], [$3], [$4])]) + + + +#------------------------------------------------------------------------------ +# CS_COMPILER_IGNORE_UNUSED([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# Check how to instruct compiler to ignore unused variables and +# arguments. This option may be useful for code generated by tools, such +# as Swig, Bison, and Flex, over which the client has no control, yet +# wishes to compile without excessive diagnostic spew. If LANGUAGE is +# not provided, then `C' is assumed (other options include `C++'). If +# CACHE-VAR is not provided, then it defaults to the name +# "cs_cv_prog_compiler_ignore_unused". If an option (such as +# `-Wno-unused') is discovered, then it is assigned to CACHE-VAR and +# ACTION-IF-FOUND is invoked; otherwise the empty string is assigned to +# CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_COMPILER_IGNORE_UNUSED], + [CS_CHECK_BUILD_FLAGS( + [how to suppress m4_default([$1],[C]) unused variable warnings], + [m4_default([$2],[cs_cv_prog_compiler_ignore_unused])], + [CS_CREATE_TUPLE([-Wno-unused])], [$1], [$3], [$4])]) + + + +#------------------------------------------------------------------------------ +# CS_COMPILER_IGNORE_UNINITIALIZED([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# Check how to instruct compiler to ignore uninitialized variables. This +# option may be useful for code generated by tools, such as Swig, Bison, +# and Flex, over which the client has no control, yet wishes to compile +# without excessive diagnostic spew. If LANGUAGE is not provided, then +# `C' is assumed (other options include `C++'). If CACHE-VAR is not +# provided, then it defaults to the name +# "cs_cv_prog_compiler_ignore_uninitialized". If an option (such as +# `-Wno-uninitialized') is discovered, then it is assigned to CACHE-VAR +# and ACTION-IF-FOUND is invoked; otherwise the empty string is assigned +# to CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_COMPILER_IGNORE_UNINITIALIZED], + [CS_CHECK_BUILD_FLAGS( + [how to suppress m4_default([$1],[C]) uninitialized warnings], + [m4_default([$2], + [cs_cv_prog_compiler_ignore_uninitialized_variables])], + [CS_CREATE_TUPLE([-Wno-uninitialized])], [$1], [$3], [$4])]) + + + +#------------------------------------------------------------------------------ +# CS_COMPILER_IGNORE_PRAGMAS([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# Check how to instruct compiler to ignore unrecognized #pragma +# directives. This option may be useful for code which contains +# unprotected #pragmas which are not understood by all compilers. If +# LANGUAGE is not provided, then `C' is assumed (other options include +# `C++'). If CACHE-VAR is not provided, then it defaults to the name +# "cs_cv_prog_compiler_ignore_unknown_pragmas". If an option (such as +# `-Wno-unknown-pragmas') is discovered, then it is assigned to CACHE-VAR +# and ACTION-IF-FOUND is invoked; otherwise the empty string is assigned +# to CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_COMPILER_IGNORE_PRAGMAS], + [CS_CHECK_BUILD_FLAGS( + [how to suppress m4_default([$1],[C]) unknown [#pragma] warnings], + [m4_default([$2],[cs_cv_prog_compiler_ignore_unknown_pragmas])], + [CS_CREATE_TUPLE([-Wno-unknown-pragmas])], [$1], [$3], [$4])]) + + + +#------------------------------------------------------------------------------ +# CS_COMPILER_IGNORE_LONG_DOUBLE([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# Check how to instruct compiler to suppress warnings about `long double' +# usage. This option may be useful for code generated by tools, such as +# Swig, Bison, and Flex, over which the client has no control, yet wishes +# to compile without excessive diagnostic spew. If LANGUAGE is not +# provided, then `C' is assumed (other options include `C++'). If +# CACHE-VAR is not provided, then it defaults to the name +# "cs_cv_prog_compiler_ignore_long_double". If an option (such as +# `-Wno-long-double') is discovered, then it is assigned to CACHE-VAR and +# ACTION-IF-FOUND is invoked; otherwise the empty string is assigned to +# CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_COMPILER_IGNORE_LONG_DOUBLE], + [CS_CHECK_BUILD_FLAGS( + [how to suppress m4_default([$1],[C]) `long double' warnings], + [m4_default([$2],[cs_cv_prog_compiler_ignore_long_double])], + [CS_CREATE_TUPLE([-Wno-long-double])], [$1], [$3], [$4])]) diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..35623fa --- /dev/null +++ b/autogen.sh @@ -0,0 +1,61 @@ +#! /bin/sh + +if [ "$USER" = "root" ]; then + echo "*** You cannot do this as "$USER" please use a normal user account." + exit 1 +fi +if test ! -f configure.ac ; then + echo "*** Please invoke this script from directory containing configure.ac." + exit 1 +fi + +echo "running aclocal" +aclocal +rc=$? + +if test $rc -eq 0; then + echo "running libtool" + libtoolize --force --automake --copy + rc=$? +else + echo "An error occured, autogen.sh stopping." + exit $rc +fi + +if test $rc -eq 0; then + echo "libtool worked." +else + echo "libtool not found. trying glibtool." + glibtoolize --force --automake --copy + rc=$? +fi + +if test $rc -eq 0; then + echo "running automake" + automake --add-missing --copy + rc=$? +else + echo "An error occured, autogen.sh stopping." + exit $rc +fi + +if test $rc -eq 0; then + echo "running autoheader" + autoheader + rc=$? +else + echo "An error occured, autogen.sh stopping." + exit $rc +fi + +if test $rc -eq 0; then + echo "running autoconf" + autoconf + rc=$? +else + echo "An error occured, autogen.sh stopping." + exit $rc +fi + +echo "autogen.sh complete" +exit $rc diff --git a/bullet.pc.cmake b/bullet.pc.cmake new file mode 100644 index 0000000..c5649d5 --- /dev/null +++ b/bullet.pc.cmake @@ -0,0 +1,6 @@ +Name: bullet +Description: Bullet Continuous Collision Detection and Physics Library +Requires: +Version: @BULLET_VERSION@ +Libs: -L@LIB_DESTINATION@ -lBulletSoftBody -lBulletDynamics -lBulletCollision -lLinearMath +Cflags: @BULLET_DOUBLE_DEF@ -I@INCLUDE_INSTALL_DIR@ diff --git a/bullet.pc.in b/bullet.pc.in new file mode 100644 index 0000000..ffcd4f3 --- /dev/null +++ b/bullet.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: bullet +Description: Bullet Continuous Collision Detection and Physics Library +Requires: +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lBulletSoftBody -lBulletDynamics -lBulletCollision -lLinearMath +Cflags: -I${includedir}/bullet diff --git a/bullet_logo.png b/bullet_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d3a1b4b5588fbed303a9a15051b560a26af5dde2 GIT binary patch literal 3380 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 KMNUMnLSTZl?!Ko0 literal 0 HcmV?d00001 diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..11b564d --- /dev/null +++ b/config.h.in @@ -0,0 +1,113 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + +/* Architecture is PowerPC */ +#undef ARCH_PPC + +/* Architecture is x86 */ +#undef ARCH_X86 + +/* Architecture is x86-64 */ +#undef ARCH_X86_64 + +/* Use the Apple OpenGL framework. */ +#undef HAVE_APPLE_OPENGL_FRAMEWORK + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GL_GLEXT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GL_GLUT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GL_GLU_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GL_GL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Platform is Apple */ +#undef PLATFORM_APPLE + +/* Platform is Linux */ +#undef PLATFORM_LINUX + +/* Platform is Win32 */ +#undef PLATFORM_WIN32 + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..762f55f --- /dev/null +++ b/configure.ac @@ -0,0 +1,160 @@ +#---------------------------------------------------------------------------- +# Autoconf input script. Invoke the ./autogen.sh script to generate a +# configure script from this file. +#---------------------------------------------------------------------------- +AC_PREREQ([2.54]) + +#---------------------------------------------------------------------------- +# Initialize Autoconf. +#---------------------------------------------------------------------------- +AC_INIT( + [bullet], + [2.80], + [bullet@erwincoumans.com]) +AC_CANONICAL_HOST +AC_CONFIG_SRCDIR([configure.ac]) +AM_INIT_AUTOMAKE +AM_PROG_CC_C_O +AC_PROG_CXX +AC_PROG_LIBTOOL + +case "$host" in + *-*-mingw*|*-*-cygwin*) + AC_DEFINE(PLATFORM_WIN32, 1, [Platform is Win32]) + opengl_LIBS="-lunsupported_platform" + PLATFORM_STRING="Win32" + ;; + *-*-linux*) + AC_DEFINE(PLATFORM_LINUX, 1, [Platform is Linux]) + opengl_LIBS="-lGL -lGLU -lglut" + PLATFORM_STRING="Linux" + ;; + *-*-darwin*) + AC_DEFINE(PLATFORM_APPLE, 1, [Platform is Apple]) + opengl_LIBS="-framework AGL -framework OpenGL -framework GLUT" + PLATFORM_STRING="Apple" + ;; + *) + AC_MSG_WARN([*** Please add $host to configure.ac checks!]) + ;; +esac +AC_SUBST(opengl_LIBS) + +case "$host" in + i?86-* | k?-* | athlon-* | pentium*-) + AC_DEFINE(ARCH_X86, 1, [Architecture is x86]) + ARCH_SPECIFIC_CFLAGS="" + ARCH_STRING="X86" + ;; + x86_64-*) + AC_DEFINE(ARCH_X86_64, 1, [Architecture is x86-64]) + ARCH_SPECIFIC_CFLAGS="-DUSE_ADDR64" + ARCH_STRING="X86-64" + ;; + ppc-* | powerpc-*) + AC_DEFINE(ARCH_PPC, 1, [Architecture is PowerPC]) + ARCH_SPECIFIC_CFLAGS="" + ARCH_STRING="PowerPC" + ;; + *) + AC_MSG_ERROR([Unknown Architecture]) + ;; +esac +AC_C_BIGENDIAN + + +#---------------------------------------------------------------------------- +# Setup for the configuration header. +#---------------------------------------------------------------------------- +AC_CONFIG_HEADERS([config.h]) +#---------------------------------------------------------------------------- +# Package configuration switches. +#---------------------------------------------------------------------------- +AC_ARG_ENABLE([multithreaded], + [AC_HELP_STRING([--enable-multithreaded], + [build BulletMultiThreaded (default NO)])], + [disable_multithreaded=no], [disable_multithreaded=yes]) +AC_MSG_CHECKING([BulletMultiThreaded]) +AS_IF([test "$disable_multithreaded" = yes], [build_multithreaded=no], [build_multithreaded=yes]) +AC_MSG_RESULT([$build_multithreaded]) +AM_CONDITIONAL([CONDITIONAL_BUILD_MULTITHREADED], [test "$build_multithreaded" = yes]) + +AC_ARG_ENABLE([demos], + [AS_HELP_STRING([--disable-demos], + [disable Bullet demos])], + [], + [enable_demos=yes]) +AM_CONDITIONAL([CONDITIONAL_BUILD_DEMOS], [false]) + +dnl Check for OpenGL and GLUT +if test "x$drawstuff" = "xOSX"; then + AC_DEFINE([HAVE_APPLE_OPENGL_FRAMEWORK], [1], + [Use the Apple OpenGL framework.]) + GL_LIBS="-framework GLUT -framework OpenGL -framework Carbon -framework AGL" + have_glut=yes +else + have_gl_headers=yes + AC_CHECK_HEADERS(GL/gl.h GL/glu.h GL/glext.h GL/glut.h, , + [have_gl_headers=no], + [[#ifdef WIN32 + #include + #endif + #if HAVE_GL_GL_H + #include + #endif + #if HAVE_GL_GLU_H + #include + #endif + ]]) + have_gl=no + have_glu=no + have_glut=no + TEMP_LDFLAGS="$LDFLAGS" + AC_CHECK_LIB(GL, main, [GL_LIBS="-lGL"; have_gl=yes]) + AC_CHECK_LIB(GLU, main, [GL_LIBS="-lGLU $GL_LIBS"; have_glu=yes], , -lGL) + AC_CHECK_LIB(GLUT, main, [GL_LIBS="-lGLUT -LGLU $GL_LIBS"; have_glut=yes], ,-lGLUT) + AC_CHECK_LIB(opengl32, main, [GL_LIBS="-lopengl32"; have_gl=yes]) + AC_CHECK_LIB(glu32, main, [GL_LIBS="-lglu32 $GL_LIBS"; have_glu=yes], , -lopengl32) + LDFLAGS="$TEMP_LDFLAGS" + if test $have_gl = no -o $have_glu = no -o $have_gl_headers = no; then + if test x$enable_demos = xyes; then + AC_MSG_WARN([Demos and Extras will not be built because OpenGL and GLUT doesn't seem to work. See `config.log' for details.]) + fi + enable_demos=no + else + AC_MSG_NOTICE([Found OpenGL]) + fi +fi +AC_SUBST(GL_LIBS) + + +if test "x$enable_demos" != xno; then + AC_MSG_NOTICE([Building Bullet demos]) + AM_CONDITIONAL([CONDITIONAL_BUILD_DEMOS],[true]) +fi + + + +AC_ARG_ENABLE([debug], + [AC_HELP_STRING([--enable-debug], + [build with debugging information (default NO)])], + [], [enable_debug=no]) + +AC_MSG_CHECKING([build mode]) +AS_IF([test $enable_debug = yes], [build_mode=debug], [build_mode=optimize]) +AC_MSG_RESULT([$build_mode]) + + + +CFLAGS="$ARCH_SPECIFIC_CFLAGS $CFLAGS" +CXXFLAGS="$ARCH_SPECIFIC_CFLAGS $CXXFLAGS $CFLAGS" +#---------------------------------------------------------------------------- +# Emit generated files. +#---------------------------------------------------------------------------- +AC_CONFIG_FILES([bullet.pc Makefile Demos/Makefile Demos/SoftDemo/Makefile Demos/AllBulletDemos/Makefile Demos/MultiThreadedDemo/Makefile Demos/OpenGL/Makefile Demos/BasicDemo/Makefile Demos/CcdPhysicsDemo/Makefile Demos/VehicleDemo/Makefile Demos/TerrainDemo/Makefile src/Makefile Extras/Makefile]) +AC_OUTPUT + +AC_MSG_NOTICE([ + +Please type 'make' to build Bullet +]) diff --git a/convex0.bin b/convex0.bin new file mode 100644 index 0000000000000000000000000000000000000000..83493fca3834f02b26c09a25e2a5d77f515bc876 GIT binary patch literal 548 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 G;J*P491%kR literal 0 HcmV?d00001 diff --git a/heightfield128x128.raw b/heightfield128x128.raw new file mode 100644 index 0000000..21656bb --- /dev/null +++ b/heightfield128x128.raw @@ -0,0 +1,37 @@ +ˆ}u]OYQC=104?KNXo~‚tmqvŽ¡¹ÆÆÅÌÈ¿¾µ¦u`V_cV;4102238CFIO[go}„‹£¹ÆÏÏ¿©—†r`]]Y]]QD=5+!"+5FE=968AAK]irn|“®ºÆÒåéòûúïåÜ̵žœž¥Ÿžœvy|…‚weYSSE:,-6@IFPfyyifjrŽœ®ÅÌÉž»»²Ÿƒi\TceS8-%#&%.G^sƒ—ª±·ÁÏÞÛ˹§Žvqttsh\ZTLC;49DIRSF>52449:?Jex† ¯ÅÒàææããàØÌ»­œ–’ŠŠyt‚u²œ‹xiYOC?KORm|x€zƒ‹’ž§µ¼¾¹²®¤ŽlWJSljWB/#',162-6CVl|”¬ºÅÊÑÜÜÊ°¡˜‘‹‘€ohlocQG;8?FROD=2284**:Lgt}¤²ÅÊÕÛßÕÓÑÌÁ°©«¦™†ŠƒŠ|x‡„ȳ¢ ›‡k^UMN_km}‹‘Œ„Œ‘’–¡¬·±«©ˆjULPb`T>% %(('(,5DP\q“¯ÀÌÐÕ×Ò¼¤ž£§¡›š•‹}€qTF8.0;6,+'""(-,,0:F@>AGO]o€‘­ÂÏ×ÑÌÉÁ´¶ÇÐÉþ·¯Ÿ‹}jP;,%! +:ALLKOU^krr‡Ÿª®©žys~•¡´º¾µº¾¿ËÓÜÔÀ¢ôôôïåÚÑ××Ð×ϼ¦—„mXXdg^Q[R>6329CE6*+*+)(#"!##'-5>IONHBGQj‡ž­¼ÄÍÌÊʼ´¸ÆÎÈÊȾª‚yiM6(## +?Nfƒ™¨·ÁÊÁ·µ±­°¿ÇÀÅËÁ¯ŽzucC+#$$!%4CGFFO`kmgdduƒ—¡”‡†€…‹—«´¸»ºÁÁÏÕÚØÏ»¯ûûúüûîçäààÞ̲Ÿ“yhWRORM:76(""$!&"!# %/1389DNQTLA>AWo†™¤®¸²²²¦¡¤¯µ­°·µ¦…qiW?+$%##$).?HEFNehffebsˆ”‘ƒ…‡›˜ª·¼¹ÄÏÏÓÑÓÐ̼³üÿýýü÷öñëåÚħ™€iWMOIA.&$ &-49?>CVbZPE=AGO^aghkmpxz|rou‰“¥¬¤¢­¾ÑÜ×ÎÁ±¬°®ìõùöó÷üöìØË·¥š™“qO;20*#  + (2?GP_noi_XZ]nvrx€ž ›­ÌÖÑÉÿ»°ž–“‡rk]L9##(.:@BIU[^qsmipwz~}vot~…’Ÿ¨¨«²ÂÔÜÐǺ¯œ£ãñôñêòöôåÏŵ¦›˜…mG0*# #+6DIRciid^bgqzvx†“Ÿ¡¤¼ØäæâÚÕÏɳ–Ž‰yi]RE-#,9CJJLTVZmppt~yyxrjir}Š›¥¯§¯ÃÎÕÏÀ¨›‡…ŠÍäêæàåæßÑËÀ´¤˜“~^C2!  ##(+07ARac\^cnzŠ’”“ž¨·ÊßèéëìåßÖ½œŒƒxl`RJ6 +1@GF;7:DLT[kpnpsund]cjl~”°¶¯²®¡Ž~wtoh¢¡®°¼º°¬¬£ª¡|vqeG*  +&8;1,/;JP[jqpt•§©ªª¯¶¯«·ÅÌÕÞÞÞáÚË°šŽˆˆrWHD7&#.78;=@B>658DIJY[dqpfhd^f`_i€› ¤Ÿ‚tikopŒ‹–›Ÿ¤œ™•…Ž‡vc^ZM;#  %4:979?O]`fnq}ŽŸ°·²­®©©¯¸ÄÒÙÛÛÚÚÒ¿«š“‘…~mVLF9.-16>?CFDDLKE?7:@BNRWa`emk^bZXYpŠ‘•‰vupjgi|x…€…Š†„zmabaTJE=9#  + + + (4<7GJJJKGFQSPD9?CGAIS]`jo_URMRVat…’tpefjuxw~yxx}|vshVLNPIA?=9$    "6B=AKRY^gqx…—±ÃÊÎĪ £«ÀÎÎÌÏØÜÍ¿³¬¦‘|ptnSA8;DMTY^\TTU[[ZM=DLOKV_a^bZQECIMONZu‡whgddnplqwpqt{ypj\KFA?:59;6$ %$)39?JTYVX^en ¼ÄÌÖÒ¿²«°ÄÎÐÍÌÛàÕÁ®•…ulnoYD64AO\gkhc]cjoiYDDNTZ^__QKHF<;AJNJ\jri]cjjpjaikhemxsujRBB=5-,.8>,!#-2/*+-10$".03AKNPKOY]g‚¡»ÂÐáàÓdz¬ºÄÊÑÔÖÖϲ™“”‡qimf]O?:HWdrvumkqolkXJOUWa[U[JFC>::=IEGXeqnhqmntrfc[XTYelniPG<91*,*387+%2<;5234981)#!!,206CONE?ALQ\v—°¼ËÜàÙÒ¿®­ºÃËÕÐÌÆ»«š’„posj]QHKbszƒ„Š†~xwvm^RXZ^`ROOJG@56AEFVbmbNB:81)*146>9++.-2DD96424:9872.-398?MXP>9?BGZu‘§²½Í×ØѲ­µ¼ÈÎÄÀÅ»¯›†uorj^SVbt‹“Ž“–‡‚‚}g][\fc[YRPOE13;ENT]\Q?6;=1)-;MUO@:@IVXX]VL=4435NqŸ¬¯¹¼°±¸»º¹¼ÀÄÄƾ°­¨¡ ˆyokegyš¬®¦œ‘™œ˜››‹vwwtxƒˆ~sab^\e]bf_[ZaT\fn{xok]Q(5:FVWSRNSOMDCJSSQOWU[ZZQKGFD83@QPOJEOV]Z`\QA620.0Gi†–Ÿ¦®©›’ž´»¹··¼ÁÀ²ª°µ´²¥—ƒ}{|Ž­º¶³«¡›œ¢§¡’‹€ƒˆ™—ˆqnkh_[ffbWQ\bifhnha_ZM$+8BCMW[TSWSLEJRVQUW]akaVXURQRJAJURONNVX\Y^bT@3322;Ni}†™˜’ˆ€Ž¤®¯««µ¸±¯®±µ¸µ§–”••™¢¸ÉÊÆ»µ š£¬§œ•Œ~‚Œš¡£˜‹{~xkZ^hf^XWcwp``]YTPUQ27?EJU\[W\``ZNNV_]`ceim__gjii`_XW]^XWZ``_^YXUOEFB=KZiux}}y{‚‚‰š¥¦¢§°±®°°¬«°ª¡œ˜™£©«¯½ÑÛâÙÊ®˜“›™‡€}}Œ’›¥ œŒ„‚zmph^^fot‹‚h[PPNNUP?DIO]e`aefjjhZLO]kmoljgkty…†~xg`bfb_cec]YJGIKKPMCJ^ikilifp€ƒ…–›˜˜£««© šž¢ š›Ÿ£±¾ÄËØäêèÖÁ¤•Žv€‡Ž‹Šœ«²¹© ™|qg^grvyw]IELYRRHHS[ipfquntmncRJYjqrslfvŠŽ“–˜Ž€oefjc_bXJA866J[nqk\R[gv„‰‰‰‘’†€Ž––›Ÿ°ÉÞæåêõóòéÕÁ§Žˆ‰“Ÿ¢¦®§§¬·¼»½¸¯¦…ldXKRS]s……{u~njffkz‚‹ŒŠ–•ƒugSJRW\aklkw|Š“¢¯º±ŸwjfkhWE8,""''-3006849BR`a`[RQ_wŒ”ŠŽ™–“‡y~‰¦¬ÄÖÛÜçôøñçʸ¥„†—¥©«¬¨ª±¶¿Åľµ¦|mdSJFUm‚€}||wyx\h‡•ŠˆŒ–ž›‰ql]MAFGQX\]kt•©¸Æ½«šŠ}qjcSFC1#"" "$+1.48604CNRRQPOZrˆ•”™¤Ÿ~njvžŸ£µËÕ×ãñ÷íÝ̽©•ŒŠ™©¬¤ ©¯´¹»ÄÄÇÆ·¥m\NN^n{{|}‰T^{‰’“•–œ¡zoreUIA=FMOTgu‡š³ÂÇż¬ ’|nbRLH6" $+-475106;@?@EHWnƒ“–œ¥Ÿˆwqgp‹—™¢²ÅÓÜæïòèÒÉø¦¥¡¤´®Ÿœ«²¯³¸ÅÆÇɽª’…w\RS`r|ˆƒ~y‚–`ezš¤¯«ž›™†zynm`OFCIJJP`|—¦»ÆÉÐÍÅ´œ€scUTL<,$"#,104;;6:;9;@EC?F½±¥–ŒˆŠˆŒ†ƒ•”œŸœ¢¨§«ÃÖÕÑÏÕßÜÙÎÎÌÏÓÔȱxme\O<7119?6.+))*,.009KZ``fmvƒ†zux{}¤£¦¸¹±²´®¦¨§¤›———‡wqz†‰ƒ†Ž’•šxp_XbYI:;@@:<:;BD?<½®¨šŠ~uz„ƒ~‡”Ÿ›¤©±¶½ÓÛÚ×ÏÐÜåçÜÙØÒÕÖɬyhYJA;3/2>@6.*'&$%*.2>S`dcer{xvzwuxƒ†š­±´´½Á»¸¹²¦˜› ¢ —ŽŠ‚ƒ“Ž‹‡‰‰{gd^WZUL>?>CDEEB@AA9°¨¦”€qq{yy~˜¤§¶¾ÄÊÐÞçæáÜÛâíòêáÙÑÖ̸™…vdQ@84--8>;4,(%! '/8CTiupmq|‡~rpptz‰‘¨¿ÂÊÎÌȾ²¯¯©˜–™ž¨¤“’–¦Ÿ›‘‡‚…zkXITVXOJ?DBKMNOMC?=9ª¦¥£œƒxs}xy€œ¨´ÁÈÑÕØãçìîììñõóìâÜÔÌ»©˜…ycG9/(#(7B:1,&$#(08GVk†‚‹‚oefo~‘™³ÉÎÓÚ×ÌÁ´ª©§™•›Ÿ¦£šŸ¡¨®¨§”ƒ{xgWE:DPUQMFEEOSSXVNGCEµ´°­ ƒy|„ˆˆŠ‘¦­»ÉÏÕØáéèñ÷ôó÷óëåÝÜØÊ°¡™†zb=.*%&&2B=53/+*1:FWgz‰˜š”Œ†‚vgeu‡‘›¨½ÐÙ×ÕÎĽ¼±¦¡•‘¡¥§¯²¬«¯·­¢¤—†vk]O>92/))&2DF;;;717BOd}‘ ©®¦–†~xnm|‡‹–¨ÁØÞÖÍÁ¶¶»¸¯¨œš¦«±¼º²®¹»®›”˜ŠxbXVJCDGPZUUZPLS]^PDKNX¹Èȳ¦‰…‹”””›«¾ÍÙÚÙáñïïõôéìèÙ×ÕÛÙDz–‡sWG;63-('7LM;48>:=IVlŽ§´µ¸¾²¡—Š„yqr|ƒ‰–®ÇÔÑɶ­¯°½À»­®»¾À¼±­©°·­–”‹w^SRRMKV][TZfeZWYXLELRXª·Ãƾ°™‰‡ˆ‡‘š«¸Ç×åæéñðïñìÞÜÚÌËÈËÌ¿­“v\G=772.+-:NN=36>=>N`xš±ÀÇÈô§›•‹vlou{‚‘ªÀÅ÷­ª±¼ÄÇÂÈÏÒм¥™œ§ª¤™‡}m_QLQ[^hifbgnvhZUTQOUYZ­¯´¹µªž…€‚”¨°ºÍáðõõöõðìä×ÑÎÁ¼¼Âǹ¢ZG:5350002>OQLDABDJ^u‡œ°ÄÊÅ·©šŒ‹†|vsqrx€‚•¯ºÀÀµ°¸¿ÈËÐÒÑÕÒº¤˜Œ™£¢~l\YRKOcpmhnqr{yhYXYTY\`dú®¨¢˜‹~u|‚—«¯½Îçô÷öôöðçÚÓÎÆ¿¸ºÅÅ­’kJ<5-)'&-6=EOVWOOSY_u‹’™¬ÀĶ¨‰„}{xyunr€…™³¾½µ´¿ÀÅÅËÌÈÇõª¢Œ–“‰yeRVVPSjwnfnw||l^aZRVXjoÎö¢““‘ƒyos™©±½ÏãïòðïóêÝÊÉÅ»¼»¿Á¾žxXD0+%!+@JLT[]YY]ir‡œ¢¢ª¸Ã·§ž“‡vrtxwrr}ƒ~ˆ¢¬°³´¹·´¹»¾½¹°ª§Ÿ“ˆ€‚ƒ€o]U^XZhx~~ywz€‚}ug_PNMUqpÇ·¡Š…†}utu–©±¼ÐØáæîðìáÓÅÈÇÁ¾¾½¹´—kP>,$$.=LYbfijiqˆ—ª°¯±ºÄ­œŽxpkktvv{}‚†|Š–¥°°«¥«±²¦˜•š—•‹wnof]UZc^dv{‡‰†‰Žzn^QGIPWmp¹²­¥”€}€ƒ‹™ ©´ÂÆÐÝìóíßÏÄÇËÌÈ¿»³ª’nUE4&)29J_hgmv€Ž”—¡­´·º¿Äų–‚m]^iqmhu„{uw{‡—§¦—‹‘ž¨ª—„†‘˜˜€scRR]glhemxŠ™ƒ‡t]JDCIU_pj¢•˜¡‰Œ‰‰‰‡Ÿž£¯±´ÁÕâîëÛƾ½ÃÈÆ¿¼±¤‘vcVE/+18FU_gmw†–Ÿ¡¦ª­®±³¸¿³—~iRP]d\S_prtolpw†ŒŒ~€Š”¡˜€€Ž”’ŽŠiTXiqsne`tŠ“’ŠshmdKDJ[mwrou~†‹“ˆ}}‹Œ•Ÿ£«¸ÇÔÚÜÑƽ»±±Ã¿º²¢Š}ujY8))127?CTdjy‚ˆ”š“˜››£ª¨«¬qP<9<=91>Ykkgehec`]Y]hs~‡~~‡‹†|pkcflhjwworz}zl^QB8458DZq}|]eŽˆŒŽ}mp|…Ž’•š§¸ÊÖÒÐËù¶¸¿º³§•„}uthJ3.9<>FLSafw‡—–“–•¥´¶®¦™…a=./121.9Sbfb\ROWXPIK[jdcgqxvsutttupeYWees„wwtoi]IJFA86F_r{VWr‹‘‹†‚n\`lx„“™¬ºÂº¿Ãº¦©´°¯§›‹†„nX?6>AAJW]enŽ‘‹‹“›¬¶·°¢˜€\>005534:@NZXQFHNNGA=?@K[msx‡‘“’ŽŠ†Œ™©´·±¡‘qTF=::720/081+-.17>>843-!#)./.489@CJTSJGWksxƒ†˜ ª¯­¡“||we\TPLUYZ\dBSdo„ƒkO:=EVn}|‡Š„{ŠŠˆ…{mdcgkxqmp|…‚wbPLIGS^femzvy‚‰‡„Œ—¦¯¦vbXOCFA96240**+&$$$" *50/4BVZVUer|”™©¯®»¸¨›‰Œˆo`RIGIPZ]d?LVcy~|p\JAKXm}„„}~…ƒ„ƒ€teXQPU^ZVYcw€}m`YTV[\`]aq{vutu}}€‡Š—Ÿš‰viXMGD>9><60%#./'-?TZ]_m‡Š›©´³µ½¹ª–‹€€iVGD@@IY]`=JUanfkgdUCHRcuƒƒyƒŒ„…‚uhXODEHGKLPSas}rkjddkigc^eywmc\ivƒ|ƒ’ŽqhWKJKH@EB8/' '+$*CX\`jt’—˜¥»Ã¼¾¹´§}pjm^F?<8;DTYa;FVaaW\dcTLFMYn|Œ”ŽƒzhXLKIIB74>ISYb:AO[STU\^[YOVZo|ŒŠ‰~uobMAEPO=8@FHJHLYnyzy€€{ofgoxxpjt}~|xtssn`ZYY\\]WKH7(#!%!!'-/:BMZahvv~•£¸ÆÅ÷¬®šƒskgXWKD<7DKP]b>GGKGMMN[`aac`s‡ŽŽ}th]M>CKH?7=C=;9BPe{Š‹‡zpfgv‡ŒŠ‰ˆ‰€|tf^_c_VX^cc\TKF8'"""%%(*/-*+00=>CKZdchhcy’”œ•}zk[SJFC?>9:?64;CVk›© ”Š}umsŠœ¡Ÿ˜’pmaTSW[Z[bbdcYQG8*'.+" !(*+.320/17>@FQ]fibY^lx~œ²¸²©¨Ÿ‰yaMITYVMSQLORd~AGC?<;FSbjiidj”™šž •{vi^YMD>;713/0:I_o—¥¢œ–…yux¦­ª¡—‚siYLINZbhrqkig_SH;8;40.(,63684028DLNPbmmmjajigj€­±¦ž„zcPOPPKGKKGJPnGEC<;HV_bdmg[hwŽš›¤œ“‚uy|riXL@7,'&$'7N`l{’œ˜‰|t€–®»´¤„‚udYOKNVanz€|sppgVLOKHE=2,349?>:?AFHHSq}nnxz{tkk{¢¨•‰€qhYRNJDGGH??>GZ_aclmaR[_yŠ‘›š’€w}~ri_N=/%! 2Ofov‰Ž‡†€zŒ¡³¿· ˆ}yk\XVURYbm{„‰…}}saY_\WUN>114;HPKLFEDJ[x…}w„…zzywuˆ˜—•†wmlbPONRPMI;5Fhy;:=GVacelqdWMNPc}”š¡›…†‚vleX@8/+ -Gemn~„‚ƒ‹‡ƒ’¤·¼¯œ‘…~t_W\_Z`l{‡Ž‘Ž†yrkhge_WL?8?N][Vgyƒ†Š…z…ymZL7*" !)4IVfkls‡Ÿµ³ŸžŸ¢¶Ã¶¢£«§œ“–‰‡ƒƒ‰‘››’’…Š’“‰xl[LKRfyŠ’‡…††„ywsivuyxh\WYahoz„…Ž“”œ˜‚geffkgkoa\2-'!#)/9JYddt€ˆ†|ndcikfleVB,$ $')0=CIFET^USNC:31.--.4@JXk{||z{‚‰’•ŽŠ‹“˜‘˜–”™§®°·³©¥ž–˜¡¡¤§¦¨­³­ž˜ ««³µºÆÄ·ªŸ‰{phqkbbuynrƒ‘‘‰‚ttt}†Ž”–™†„}|ƒ~E7$""$,@IIBBD=756:AJNIJFMJG:)**%&/7>E]t€‡„€ƒ~{…‹„|‡ž¦™“š–•¦¬ªª«¦œ•‡‚Œ––™¢§°º»ª›¡«ª©²½À»°ž’vm`aeahs{y~Œ—˜˜‰qnow„ˆšŸ™ŽŒ””‡E4'*(!&6<91.30/*./6=IFC?DJJA,++''+37A]t€›™‘Œ‡‚|vxyƒ—¤§™’Š–¥©§£¥¤—€zˆ—•–¢¦­¿Å² ž¨¨§±¸¹¸¬ž|pdYV`[gr}†‡Ž’•šƒigiou€ƒ‹ž«£ž–œŸ˜‹G=73.)$#'(--&&'&'#(*/0?AA@@FF?2*+&&)08Har“œž—‘ƒvru|Š”œˆŒ“—¥§¢¡ ˜„‚—™¢¬§ª¹À´¦£¥ª¨­³¹¶£š~j\TT[\cn~Š‘•‹‰ydZZ^bp…Ž›­°µµ®¥ž“SOK=1/+#'('$#!")-/:>KXkz††……yu|€ˆ‘’Œ‚”¢š’œ¢Ÿœœ™‹’œ©´¶¨©¶¿À··»¶´¸º¾¸ž”‡ucWSMP\fp†•›ž’‚uldVTWT`vŠ“¥´ÀË»´­¦bZYE3.,*)+'&.0575=CE=?935;CM\bm{€Œƒvmrypmt‰‹„ƒ…†ŸªŸ˜¢¥ ž§© —•›¨²»º°±¹ÂÍÏËÊÃÀÀÇÇįžŽ}nd^ROXesŽ™¡£’}kbZSQTYVj€Œ—§ºÆÅ¿½¸iZZI50,*&&#!(,.*-;ORPUNLFO]gvx‚†•‡ukpqljmwyropx…“¢­¤š¢¬«¯«Ÿ”‘‘™¬·»»¿¾¿ÎØÜÔÈÄÈÄÊÉÍðš‡viddV\ev‰–£ {h_XOPQZ]mzˆ’Ÿ¸ÅÈÄËÅaMMD<3,# #%!!3R___abcmx~†‡‡‰‡–Œxozypgdilc]_i~Š•¤¥›š¤®±¦œ™›˜œ­ºÀÁÉÏÕååäÝÒÊËÆÇÐÐÌÀ®{nii`[Zf–‹n^\QKNW\ju€‰˜¢µÁÇÈÌÈQFA<9/#  .MZVWcl•“•‘‘”–Œ~y{ue[Z]^[[jx¤”¤£¡¡œŸž «¸ÀÇÓÜçñêèäÞÝÒÌÎÓÍû®•sod_SN]nv|unbTMDANZcyƒ™Ÿ§«¹À»·I;2+*#  +,GOLTj€›­§›”‘“–•¢™†‚ˆvhXQRVYiw{‡“‚‰Ÿ£•’™¤³¿ÇÍÖÚâéââåæéÝÒÐÐʺ³¦ŽulibZMEMR^a_bd[OIEN]q€Œˆ” ¤ž–ž±«¤F5.# + !(2AJQ`¢¹É¾±¨ž˜“˜Ÿ©¦ˆ‘‹wdQNMRery|†‰yz–¨Ÿ”Œ’¡³ÁÈÈÎÖÜÚ×ÙäîíàÕÌÍʽ®ž‡qg]VTJ<=HNKMM[_TPLPcs‹•œŸ¢ž–˜žŸ¢>.' "+6>FOXpš·ÈÚÛÏü¬Ÿ ¦®«›¢™Žƒr_TJGR_hnw‚ƒ~z‰Ÿš‹Šˆ¢²¼¾½½ÂÇËÑØáëçÚÍÁ¸´¯¡“}jb[OHE96=?B?=FQOQQVlw‹—¢§¤«¡––—7-"   ,4>LMZl‰¦ÃÔäæÚÏË¿´­©±·³¬¦˜ˆ}viUMHADTejmpxv€’…}„Ž£²·¹º·¶¸¿ÉÔÛÝ×Ç»®Ÿ––eSNMA=?<>657732@KNXan¦±°°³£•“•+% +!19AJQa‚¯ÄÔßàÓÓÐÇÆ¿¹ÃÉĵ ™—„wpaWPJA9AQWQQ\\dqztkvŠ ­µ´¸¸±¯²¸Æ̼µªš–Œ€xviP?><>=@@E:31.+.8CMUbwˆ“¡®³°­±©ž˜›Ÿ&  + ,7@IHUj‚¡¸ÆÉÓÜØÖÕËÊÍÓÜÛÒ»¥Ÿ’yfjcQIG>6>HE@AEFM[b]Zi„£³²°¶²£œ› ­«›–‹ƒ…~wiYH:143AJEBE?761/*1>IW_w‡‘™¦«¨¦¬­¦¥¯±' + + +  (1BQRWg}š·ÊÌÓÜãâà××ÕÜèßÔ¿¦šŒxfh`NE?:8?BA<:417?BKPZxœ²¹»¹±©›“™Ž‡pnuoieSC7,+3>EKLH><;2/++=Q[fuˆ“ž§©¦¤¬ª®²º-   "&/@Wdhl}”¸ÌÐÔÛîïìëèäçãÙÓĬ™qmeXLC:68=><4*$''&1DWo¥¶¼±§£•ŠzrodXVWUXZSH;,,55:LYQCA?520-DZbk…‘§¦ ¤««¯²°³¸6"  +  $*3IWfx{|®ÀÈÒàíïññìëéßÚÖǵ¦–‰{weO?2.2675*$7RlŸ©£”†xk[W]VNH??C@??1)'.38EVSCA93-.3G`rx‘©´º®®¯¯¼½²µ±E2&   $0;GVi}~‡“Ÿ«½ÆÛêòõóñîçáÜ×Í»¥—ŠrbPD7.,**)#+BUez‹”‹†ƒufZIAIK?407=967*!$(-9M^VI;,'$,9Tu‡‘¢§²¼Ëĵ¬ª»¸³»ºT?,$+.2?MQ^vz„’œŸªµÄÚìñôðíéàÛÔÓ̺¢”Œ‡ocVC0),*'!-9Mgv€zjdhaK?<=?6,&+145+ (09N]UH8+%%(6_{¦¯¹ÀÅÎÎƶ­¼½¾¸ÄSE1!"-:?CCGX]esŽ¢³´¸ÁÍáñîïçãåßÔÑ̸¨—ˆ„|q_LC?90+)),*#!%03<;1+++5=Qbz’¤§°¶ÇÊÑÈÁÊÓÏÌÏÙMIA75/*"$)0>SZcbcl}€ƒ…ž©©«´ÂÑâèïêÝŸ¸ÅÈ¿½Áº©—‰|aUE0)+( #$ #030+,24ALG?1('''%"#24/2/+(*=HXh‚™©¡©½ÉÅÊÌÍÎÈÊÊÎËMPK><13+#*)2>Tchinmx‰‹Š‰’¥¨›¦¹ÊØÝßÙѾ©£¨©«©®²§†j`WJ7+**"#*%&3>BGH:+# "" #/44752.19CKbwŠ£«µÀ»ÊÌËÀ¹ÄÉƹV^WKDAE=//2>N`heiokzˆŒ——š¢“‘ž®¿ÔØÐƸ´¥–”š™„h^XOB-"   $#&/69591%#)8>=54;824AXf{—­¼»½½Æ˽²­½¼±¯dpi^PSWG:8@ESdnlmwuvƒ”§¦¢œ›‘–š±ÀÄƹª¥˜ˆ||z{ˆ…yaNORI3%"  +&*0+,)%$139BLJC@67CKTRh‡ªª«³¹Àµ§¥°º²°flom`geRBHMX`jjmou~|‰¡®®œ•˜˜•‘‘™§µ¿Ä¶Ÿ•“‘‰€}|~ƒ„xgTGIJA2)#  + +  $# "!!%(# (2=BDKNH=;=MSWM[w™¢¨£±½¬¨±¶®¦iqyyvxp`[XV[gmkmuz‰…Œ¢®©Ÿ˜›¦¤ £§¨°·»¯––•‡{~‚ˆy^L=::62)    (*1,''5DLHDF?>6ANW^SXks˜˜˜¥·³­²´«žuzyy|yf^Xgkilx„†‘£«ªŸ¡£¯­¯´±±±³³ª™–’“Š‡}…‡†~kU:/10/& + +%0857;=LLFAD@A?LX_c]]i~ˆŒ…“›ž°­±´³¬¢u~wv{|Š}gb_hignq{†Š“¤«¥Ÿ¤¬¸·µ´³«©«©˜¦¨Š•“ƒkR:*+23%  &09>EPOUTL?ABHKVfkgcdnˆ‰‡†™™Ÿ±¯·¼¾º±irgkt{Šzqngs}z‚‡”•—¡§ žœ§´´·³°ª¦¤¤š¡¥²·ª›––œšŒqUE30?OY_ilqz‰”˜•––¦¬«P?:9==;>Ncx‰ž¦¢¦°¯®§ ©®­³¹¿Ä¾Â¿¼°ª§²½¼³´ÃÉÎËĶ£™Ž~whXNE4#   + %)15.-24B?>KLPNJKLOT_ndfsx~zŒ€vz}|ˆ™••QFC@A@@W[UUYk€ £¥Ÿ—’œ˜Œ˜›‘¯´¤¢¤¦¬¢¢°³®«¯½ÕãÛžºµ³¯ž‹„}tdK7-##)2?QYM<,$&% %(""&-99@S]lleedp{tkdgjeegq}Œž˜‰~rnnlrq€†~|r:=>=ETca`lr–– ¨ª ™’…€‚zr‡¢¥–›¡š˜™š˜œ¤²ÎÝØËÉÎÍÇÆ´ž–‘ƒsbM=.),3>BET^VE6(&%!',! #$$&7BR^euxru{ˆ‰ƒzumfky|‰•ž¤“Šviknlhnz{nl37:EP[jrwƒ‚Ž ¢¥¦¨¢šŠ†zgd`Ykƒ‹’š–Žz€„~™¯¿ÈÊÍÓ×Õ×ÙÊ´¦žƒw]E20&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/jenga.dae b/jenga.dae new file mode 100644 index 0000000..19c85d0 --- /dev/null +++ b/jenga.dae @@ -0,0 +1,5632 @@ + + + + + Illusoft Collada 1.4.0 plugin for Blender - http://colladablender.illusoft.com + Blender v:242 - Illusoft Collada Exporter v:0.2.65 + + + file:///Users/erwin/Desktop/physics_demos-2.42-preview34/jenga_physics_test.blend + + 2006-07-18T10:32:54.891550 + 2006-07-18T10:32:54.891607 + Z_UP + + + + + + + 49.13434 + 0.1 + 100.0 + + + + + + + + + + + + + + + + + + + + + + + 0.0 0.0 0.0 1.0 + + + 0.4 0.4 0.4 1.0 + + + 0.8 0.8 0.8 1.0 + + + 0.5 0.5 0.5 1.0 + + + 12.5 + + + 1.0 1.0 1.0 1.0 + + + 0.8 + + + 1 1 1 1 + + + 0.0 + + + + + + + + + + + 4.628 0.542 0.0 4.461 0.379 0.0 4.461 0.369 0.0 4.539 0.369 0.0 4.539 0.132 0.0 4.54308 0.09343 0.0 4.5553 0.05944 0.0 4.57563 0.03112 0.0 4.60404 0.00956 0.0 4.6405 -0.00418 0.0 4.685 -0.009 0.0 4.70092 -0.00796 0.0 4.719 -0.005 0.0 4.73825 -0.00038 0.0 4.75767 0.00567 0.0 4.77625 0.01288 0.0 4.793 0.021 0.0 4.793 0.104 0.0 4.77524 0.09392 0.0 4.75793 0.08567 0.0 4.741 0.07925 0.0 4.72441 0.07467 0.0 4.70809 0.07192 0.0 4.692 0.071 0.0 4.67823 0.07236 0.0 4.66385 0.07685 0.0 4.65025 0.08513 0.0 4.63882 0.09781 0.0 4.63094 0.11556 0.0 4.628 0.139 0.0 4.628 0.369 0.0 4.77 0.369 0.0 4.77 0.449 0.0 4.628 0.449 0.0 4.134 0.449 0.0 4.134 0.0 0.0 4.223 0.0 0.0 4.223 0.235 0.0 4.22684 0.27196 0.0 4.2377 0.305 0.0 4.25463 0.33288 0.0 4.27663 0.35433 0.0 4.30275 0.36813 0.0 4.332 0.373 0.0 4.34357 0.37155 0.0 4.35685 0.36737 0.0 4.37125 0.36075 0.0 4.38615 0.35196 0.0 4.40094 0.34129 0.0 4.415 0.329 0.0 4.462 0.406 0.0 4.44373 0.422 0.0 4.42582 0.43504 0.0 4.40813 0.44513 0.0 4.39052 0.4523 0.0 4.37286 0.45658 0.0 4.355 0.458 0.0 4.33391 0.45519 0.0 4.31263 0.44652 0.0 4.29113 0.43163 0.0 4.26937 0.41015 0.0 4.24734 0.38173 0.0 4.225 0.346 0.0 4.223 0.346 0.0 4.223 0.449 0.0 4.049 0.08 0.0 4.0392 0.07301 0.0 4.02993 0.06711 0.0 4.02138 0.06238 0.0 4.01374 0.05889 0.0 4.00722 0.05674 0.0 4.002 0.056 0.0 3.99692 0.05652 0.0 3.9927 0.05819 0.0 3.98938 0.06113 0.0 3.98696 0.06548 0.0 3.9855 0.07139 0.0 3.985 0.079 0.0 3.985 0.31 0.0 3.97925 0.35638 0.0 3.96296 0.3937 0.0 3.93763 0.42225 0.0 3.9047 0.4423 0.0 3.86567 0.45412 0.0 3.822 0.458 0.0 3.79082 0.45633 0.0 3.76226 0.4513 0.0 3.73625 0.44288 0.0 3.71274 0.43104 0.0 3.69168 0.41575 0.0 3.673 0.397 0.0 3.673 0.3 0.0 3.69505 0.32319 0.0 3.71804 0.34185 0.0 3.74175 0.35612 0.0 3.76596 0.36615 0.0 3.79045 0.37206 0.0 3.815 0.374 0.0 3.83975 0.37204 0.0 3.86 0.36596 0.0 3.87575 0.3555 0.0 3.887 0.34037 0.0 3.89375 0.3203 0.0 3.896 0.295 0.0 3.896 0.271 0.0 3.817 0.243 0.0 3.78067 0.22963 0.0 3.74533 0.21441 0.0 3.7135 0.19563 0.0 3.68767 0.17159 0.0 3.67033 0.14062 0.0 3.664 0.101 0.0 3.66757 0.07271 0.0 3.67785 0.0467 0.0 3.69425 0.02425 0.0 3.71615 0.00663 0.0 3.74294 -0.00488 0.0 3.774 -0.009 0.0 3.79449 -0.00775 0.0 3.81493 -0.00396 0.0 3.83525 0.00238 0.0 3.85541 0.0113 0.0 3.87534 0.02283 0.0 3.895 0.037 0.0 3.90011 0.02248 0.0 3.90752 0.01085 0.0 3.91738 0.002 0.0 3.92982 -0.00419 0.0 3.94498 -0.00781 0.0 3.963 -0.009 0.0 3.97625 -0.00828 0.0 3.98863 -0.00593 0.0 4.00113 -0.00163 0.0 4.0147 0.00493 0.0 4.03034 0.01403 0.0 4.049 0.026 0.0 3.896 0.091 0.0 3.88383 0.08027 0.0 3.87133 0.07119 0.0 3.8585 0.06387 0.0 3.84533 0.05848 0.0 3.83183 0.05514 0.0 3.818 0.054 0.0 3.80041 0.0561 0.0 3.78496 0.06211 0.0 3.77213 0.07163 0.0 3.76237 0.08422 0.0 3.75617 0.09949 0.0 3.754 0.117 0.0 3.75924 0.14138 0.0 3.77393 0.162 0.0 3.7965 0.17963 0.0 3.82541 0.195 0.0 3.85909 0.20888 0.0 3.896 0.222 0.0 3.472 0.542 0.0 3.305 0.379 0.0 3.305 0.369 0.0 3.383 0.369 0.0 3.383 0.132 0.0 3.38708 0.09343 0.0 3.3993 0.05944 0.0 3.41963 0.03112 0.0 3.44804 0.00956 0.0 3.48451 -0.00418 0.0 3.529 -0.009 0.0 3.54492 -0.00796 0.0 3.563 -0.005 0.0 3.58225 -0.00038 0.0 3.60167 0.00567 0.0 3.62025 0.01288 0.0 3.637 0.021 0.0 3.637 0.104 0.0 3.61924 0.09392 0.0 3.60193 0.08567 0.0 3.585 0.07925 0.0 3.56841 0.07467 0.0 3.55209 0.07192 0.0 3.536 0.071 0.0 3.52223 0.07236 0.0 3.50785 0.07685 0.0 3.49425 0.08513 0.0 3.48282 0.09781 0.0 3.47494 0.11556 0.0 3.472 0.139 0.0 3.472 0.369 0.0 3.614 0.369 0.0 3.614 0.449 0.0 3.472 0.449 0.0 3.244 0.421 0.0 3.22082 0.43242 0.0 3.19822 0.4417 0.0 3.17613 0.44888 0.0 3.15444 0.45396 0.0 3.1331 0.457 0.0 3.112 0.458 0.0 3.06979 0.45424 0.0 3.03363 0.44326 0.0 3.00425 0.4255 0.0 2.98237 0.40141 0.0 2.96871 0.37143 0.0 2.964 0.336 0.0 2.97956 0.28229 0.0 3.01845 0.24 0.0 3.069 0.20588 0.0 3.11956 0.17667 0.0 3.15844 0.14913 0.0 3.174 0.12 0.0 3.17161 0.10525 0.0 3.16489 0.093 0.0 3.1545 0.08325 0.0 3.14111 0.076 0.0 3.12539 0.07125 0.0 3.108 0.069 0.0 3.08864 0.07059 0.0 3.06678 0.07541 0.0 3.04275 0.0835 0.0 3.01689 0.09493 0.0 2.98953 0.10974 0.0 2.961 0.128 0.0 2.961 0.032 0.0 2.98888 0.01855 0.0 3.015 0.00804 0.0 3.04013 0.00025 0.0 3.065 -0.00504 0.0 3.09038 -0.00805 0.0 3.117 -0.009 0.0 3.15748 -0.00471 0.0 3.19315 0.00767 0.0 3.22288 0.02737 0.0 3.24552 0.05367 0.0 3.25994 0.08579 0.0 3.265 0.123 0.0 3.26266 0.1449 0.0 3.25526 0.16522 0.0 3.24225 0.18488 0.0 3.22307 0.20478 0.0 3.19718 0.22585 0.0 3.164 0.249 0.0 3.1285 0.27025 0.0 3.10063 0.28833 0.0 3.07988 0.30375 0.0 3.0657 0.317 0.0 3.05759 0.32858 0.0 3.055 0.339 0.0 3.05687 0.35037 0.0 3.0623 0.3603 0.0 3.071 0.3685 0.0 3.0827 0.3747 0.0 3.09713 0.37863 0.0 3.114 0.38 0.0 3.13162 0.37881 0.0 3.15126 0.37515 0.0 3.17263 0.36887 0.0 3.19541 0.35985 0.0 3.2193 0.34794 0.0 3.244 0.333 0.0 2.879 0.13 0.0 2.85307 0.11419 0.0 2.82719 0.10089 0.0 2.80125 0.09025 0.0 2.77515 0.08244 0.0 2.74877 0.07764 0.0 2.722 0.076 0.0 2.68193 0.07982 0.0 2.64774 0.09122 0.0 2.6195 0.11013 0.0 2.59726 0.13644 0.0 2.58107 0.1701 0.0 2.571 0.211 0.0 2.887 0.211 0.0 2.88082 0.28694 0.0 2.86289 0.34881 0.0 2.83413 0.39675 0.0 2.79544 0.43085 0.0 2.74776 0.45123 0.0 2.692 0.458 0.0 2.63339 0.45056 0.0 2.58244 0.42911 0.0 2.5405 0.395 0.0 2.50889 0.34956 0.0 2.48894 0.29411 0.0 2.482 0.23 0.0 2.48843 0.16924 0.0 2.50741 0.11293 0.0 2.5385 0.064 0.0 2.58126 0.02541 0.0 2.63524 9e-05 0.0 2.7 -0.009 0.0 2.7359 -0.00757 0.0 2.76819 -0.00326 0.0 2.79775 0.004 0.0 2.82548 0.01426 0.0 2.85227 0.02757 0.0 2.879 0.044 0.0 2.573 0.27 0.0 2.58141 0.30288 0.0 2.59459 0.33033 0.0 2.6125 0.35213 0.0 2.63507 0.368 0.0 2.66226 0.37771 0.0 2.694 0.381 0.0 2.72344 0.3775 0.0 2.74856 0.36733 0.0 2.769 0.351 0.0 2.78445 0.329 0.0 2.79456 0.30183 0.0 2.799 0.27 0.0 2.114 0.449 0.0 2.114 0.0 0.0 2.203 0.0 0.0 2.203 0.235 0.0 2.20684 0.27196 0.0 2.2177 0.305 0.0 2.23463 0.33288 0.0 2.25663 0.35433 0.0 2.28275 0.36813 0.0 2.312 0.373 0.0 2.32357 0.37155 0.0 2.33685 0.36737 0.0 2.35125 0.36075 0.0 2.36615 0.35196 0.0 2.38094 0.34129 0.0 2.395 0.329 0.0 2.442 0.406 0.0 2.42373 0.422 0.0 2.40582 0.43504 0.0 2.38813 0.44513 0.0 2.37052 0.4523 0.0 2.35286 0.45658 0.0 2.335 0.458 0.0 2.31391 0.45519 0.0 2.29263 0.44652 0.0 2.27113 0.43163 0.0 2.24937 0.41015 0.0 2.22734 0.38173 0.0 2.205 0.346 0.0 2.203 0.346 0.0 2.203 0.449 0.0 1.488 0.458 0.0 1.42392 0.45 0.0 1.367 0.4273 0.0 1.31925 0.39187 0.0 1.28267 0.3457 0.0 1.25925 0.29075 0.0 1.251 0.229 0.0 1.25897 0.16345 0.0 1.28178 0.10596 0.0 1.31775 0.05825 0.0 1.36522 0.02204 0.0 1.42253 -0.00095 0.0 1.488 -0.009 0.0 1.556 -0.00123 0.0 1.615 0.02115 0.0 1.6635 0.05675 0.0 1.7 0.10419 0.0 1.723 0.16206 0.0 1.731 0.229 0.0 1.72279 0.29214 0.0 1.69933 0.34748 0.0 1.66238 0.39338 0.0 1.61367 0.42819 0.0 1.55496 0.45027 0.0 1.487 0.378 0.0 1.52924 0.37293 0.0 1.56622 0.35844 0.0 1.59688 0.33563 0.0 1.62011 0.30556 0.0 1.63485 0.26932 0.0 1.64 0.228 0.0 1.63519 0.18269 0.0 1.62122 0.14419 0.0 1.59875 0.11313 0.0 1.56844 0.09015 0.0 1.53097 0.07589 0.0 1.487 0.071 0.0 1.4464 0.07611 0.0 1.41119 0.09085 0.0 1.38225 0.11437 0.0 1.36048 0.14581 0.0 1.34677 0.18431 0.0 1.342 0.229 0.0 1.34691 0.2699 0.0 1.36093 0.30585 0.0 1.383 0.33575 0.0 1.41207 0.35848 0.0 1.44709 0.37294 0.0 1.049 0.542 0.0 0.882 0.379 0.0 0.882 0.369 0.0 0.96 0.369 0.0 0.96 0.132 0.0 0.96408 0.09343 0.0 0.9763 0.05944 0.0 0.99663 0.03112 0.0 1.02504 0.00956 0.0 1.0615 -0.00418 0.0 1.106 -0.009 0.0 1.12192 -0.00796 0.0 1.14 -0.005 0.0 1.15925 -0.00038 0.0 1.17867 0.00567 0.0 1.19725 0.01288 0.0 1.214 0.021 0.0 1.214 0.104 0.0 1.19624 0.09392 0.0 1.17893 0.08567 0.0 1.162 0.07925 0.0 1.14541 0.07467 0.0 1.12909 0.07192 0.0 1.113 0.071 0.0 1.09923 0.07236 0.0 1.08485 0.07685 0.0 1.07125 0.08513 0.0 1.05981 0.09781 0.0 1.05194 0.11556 0.0 1.049 0.139 0.0 1.049 0.369 0.0 1.191 0.369 0.0 1.191 0.449 0.0 1.049 0.449 0.0 0.077 0.682 0.0 0.077 0.0 0.0 0.175 0.0 0.0 0.175 0.296 0.0 0.216 0.296 0.0 0.24052 0.29417 0.0 0.26515 0.28667 0.0 0.2915 0.2705 0.0 0.32119 0.24267 0.0 0.35581 0.20017 0.0 0.397 0.14 0.0 0.487 0.0 0.0 0.604 0.0 0.0 0.58281 0.02931 0.0 0.56544 0.05344 0.0 0.55075 0.07425 0.0 0.53756 0.09356 0.0 0.52469 0.11319 0.0 0.511 0.135 0.0 0.48599 0.17567 0.0 0.46226 0.21267 0.0 0.43875 0.246 0.0 0.41441 0.27567 0.0 0.38818 0.30167 0.0 0.359 0.324 0.0 0.39279 0.34095 0.0 0.421 0.36263 0.0 0.44337 0.38875 0.0 0.45967 0.41904 0.0 0.46962 0.45321 0.0 0.473 0.491 0.0 0.46599 0.54612 0.0 0.44559 0.59296 0.0 0.41275 0.63075 0.0 0.36841 0.6587 0.0 0.31351 0.67605 0.0 0.249 0.682 0.0 0.175 0.598 0.0 0.238 0.598 0.0 0.28084 0.59481 0.0 0.31474 0.58552 0.0 0.34025 0.5705 0.0 0.35793 0.55015 0.0 0.36832 0.52485 0.0 0.372 0.495 0.0 0.36971 0.46699 0.0 0.36104 0.44089 0.0 0.34475 0.41813 0.0 0.31963 0.40011 0.0 0.28445 0.38826 0.0 0.238 0.384 0.0 0.175 0.384 0.0 + + + + + + + + + + 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

      1 0 0 1 33 2 1 3 33 4 32 5 1 6 32 7 31 8 2 9 1 10 31 11 3 12 2 13 31 14 4 15 3 16 30 17 30 18 3 19 31 20 4 21 30 22 29 23 4 24 29 25 28 26 5 27 4 28 28 29 5 30 28 31 27 32 18 33 17 34 16 35 5 36 27 37 26 38 19 39 18 40 16 41 6 42 5 43 26 44 20 45 19 46 16 47 6 48 26 49 25 50 21 51 20 52 16 53 6 54 25 55 24 56 22 57 21 58 16 59 6 60 24 61 23 62 23 63 22 64 16 65 6 66 23 67 16 68 7 69 6 70 16 71 8 72 7 73 16 74 8 75 16 76 15 77 8 78 15 79 14 80 9 81 8 82 14 83 9 84 14 85 13 86 9 87 13 88 12 89 10 90 9 91 12 92 10 93 12 94 11 95 57 96 56 97 55 98 57 99 55 100 54 101 58 102 57 103 54 104 58 105 54 106 53 107 35 108 34 109 64 110 35 111 64 112 63 113 59 114 58 115 53 116 59 117 53 118 52 119 59 120 52 121 51 122 60 123 59 124 51 125 60 126 51 127 50 128 61 129 60 130 50 131 61 132 50 133 43 134 43 135 50 136 44 137 44 138 50 139 45 140 45 141 50 142 46 143 46 144 50 145 47 146 47 147 50 148 48 149 48 150 50 151 49 152 62 153 61 154 42 155 42 156 61 157 43 158 62 159 42 160 41 161 62 162 41 163 40 164 35 165 63 166 62 167 35 168 62 169 39 170 39 171 62 172 40 173 35 174 39 175 38 176 35 177 38 178 37 179 35 180 37 181 36 182 85 183 84 184 83 185 86 186 85 187 83 188 86 189 83 190 82 191 87 192 86 193 82 194 88 195 87 196 82 197 88 198 82 199 81 200 89 201 88 202 81 203 89 204 81 205 80 206 90 207 89 208 80 209 91 210 90 211 92 212 92 213 90 214 93 215 93 216 90 217 94 218 94 219 90 220 95 221 95 222 90 223 96 224 96 225 90 226 97 227 97 228 90 229 80 230 97 231 80 232 98 233 98 234 80 235 79 236 99 237 98 238 79 239 100 240 99 241 79 242 100 243 79 244 78 245 101 246 100 247 78 248 102 249 101 250 78 251 103 252 102 253 78 254 103 255 78 256 77 257 104 258 103 259 77 260 105 261 104 262 154 263 154 264 104 265 77 266 106 267 105 268 154 269 107 270 106 271 154 272 107 273 154 274 153 275 136 276 154 277 77 278 108 279 107 280 153 281 108 282 153 283 152 284 109 285 108 286 152 287 109 288 152 289 151 290 109 291 151 292 150 293 110 294 109 295 150 296 110 297 150 298 149 299 110 300 149 301 148 302 111 303 110 304 148 305 111 306 148 307 147 308 112 309 111 310 147 311 112 312 147 313 146 314 137 315 136 316 77 317 112 318 146 319 145 320 138 321 137 322 77 323 66 324 65 325 135 326 138 327 77 328 76 329 67 330 66 331 135 332 113 333 112 334 145 335 113 336 145 337 144 338 138 339 76 340 75 341 139 342 138 343 75 344 68 345 67 346 135 347 139 348 75 349 74 350 140 351 139 352 74 353 69 354 68 355 135 356 113 357 144 358 143 359 140 360 74 361 73 362 70 363 69 364 135 365 141 366 140 367 73 368 141 369 73 370 72 371 71 372 70 373 135 374 141 375 72 376 71 377 113 378 143 379 142 380 141 381 71 382 135 383 142 384 141 385 135 386 113 387 142 388 123 389 123 390 142 391 135 392 114 393 113 394 123 395 114 396 123 397 122 398 124 399 123 400 135 401 124 402 135 403 134 404 115 405 114 406 122 407 115 408 122 409 121 410 125 411 124 412 134 413 125 414 134 415 133 416 115 417 121 418 120 419 126 420 125 421 133 422 116 423 115 424 120 425 126 426 133 427 132 428 116 429 120 430 119 431 127 432 126 433 132 434 127 435 132 436 131 437 116 438 119 439 118 440 128 441 127 442 131 443 117 444 116 445 118 446 128 447 131 448 130 449 129 450 128 451 130 452 156 453 155 454 188 455 156 456 188 457 187 458 156 459 187 460 186 461 157 462 156 463 186 464 158 465 157 466 186 467 159 468 158 469 185 470 185 471 158 472 186 473 159 474 185 475 184 476 159 477 184 478 183 479 160 480 159 481 183 482 160 483 183 484 182 485 173 486 172 487 171 488 160 489 182 490 181 491 174 492 173 493 171 494 161 495 160 496 181 497 175 498 174 499 171 500 161 501 181 502 180 503 176 504 175 505 171 506 161 507 180 508 179 509 177 510 176 511 171 512 161 513 179 514 178 515 178 516 177 517 171 518 161 519 178 520 171 521 162 522 161 523 171 524 163 525 162 526 171 527 163 528 171 529 170 530 163 531 170 532 169 533 164 534 163 535 169 536 164 537 169 538 168 539 164 540 168 541 167 542 165 543 164 544 167 545 165 546 167 547 166 548 196 549 195 550 194 551 196 552 194 553 193 554 197 555 196 556 193 557 197 558 193 559 192 560 197 561 192 562 191 563 198 564 197 565 191 566 198 567 191 568 190 569 198 570 190 571 189 572 199 573 198 574 189 575 199 576 189 577 250 578 250 579 189 580 251 581 251 582 189 583 252 584 252 585 189 586 253 587 253 588 189 589 254 590 254 591 189 592 255 593 255 594 189 595 256 596 200 597 199 598 250 599 200 600 250 601 249 602 200 603 249 604 248 605 200 606 248 607 247 608 201 609 200 610 247 611 201 612 247 613 246 614 201 615 246 616 245 617 201 618 245 619 244 620 201 621 244 622 243 623 202 624 201 625 243 626 202 627 243 628 242 629 202 630 242 631 241 632 202 633 241 634 240 635 202 636 240 637 239 638 203 639 202 640 239 641 203 642 239 643 238 644 203 645 238 646 237 647 204 648 203 649 237 650 204 651 237 652 236 653 205 654 204 655 236 656 205 657 236 658 235 659 205 660 235 661 234 662 206 663 205 664 234 665 206 666 234 667 233 668 207 669 206 670 233 671 207 672 233 673 232 674 220 675 219 676 218 677 207 678 232 679 231 680 208 681 207 682 231 683 220 684 218 685 217 686 209 687 208 688 231 689 220 690 217 691 216 692 210 693 209 694 231 695 210 696 231 697 230 698 220 699 216 700 215 701 211 702 210 703 230 704 212 705 211 706 230 707 220 708 215 709 214 710 213 711 212 712 230 713 220 714 214 715 213 716 220 717 213 718 230 719 220 720 230 721 229 722 221 723 220 724 229 725 221 726 229 727 228 728 222 729 221 730 228 731 223 732 222 733 228 734 223 735 228 736 227 737 224 738 223 739 227 740 224 741 227 742 226 743 225 744 224 745 226 746 277 747 276 748 275 749 277 750 275 751 274 752 278 753 277 754 274 755 278 756 274 757 273 758 279 759 278 760 273 761 279 762 273 763 301 764 301 765 273 766 302 767 302 768 273 769 272 770 280 771 279 772 300 773 300 774 279 775 301 776 280 777 300 778 299 779 303 780 302 781 272 782 280 783 299 784 298 785 304 786 303 787 272 788 280 789 298 790 297 791 305 792 304 793 272 794 281 795 280 796 297 797 305 798 272 799 271 800 281 801 297 802 296 803 306 804 305 805 271 806 281 807 296 808 295 809 307 810 306 811 271 812 282 813 281 814 295 815 307 816 271 817 270 818 282 819 295 820 307 821 282 822 307 823 270 824 283 825 282 826 269 827 269 828 282 829 270 830 283 831 269 832 268 833 283 834 268 835 267 836 284 837 283 838 267 839 284 840 267 841 266 842 258 843 257 844 294 845 259 846 258 847 294 848 285 849 284 850 266 851 285 852 266 853 265 854 260 855 259 856 294 857 285 858 265 859 264 860 261 861 260 862 294 863 262 864 261 865 294 866 285 867 264 868 263 869 263 870 262 871 294 872 285 873 263 874 294 875 286 876 285 877 294 878 286 879 294 880 293 881 286 882 293 883 292 884 287 885 286 886 292 887 287 888 292 889 291 890 287 891 291 892 290 893 288 894 287 895 290 896 288 897 290 898 289 899 331 900 330 901 329 902 331 903 329 904 328 905 332 906 331 907 328 908 332 909 328 910 327 911 309 912 308 913 338 914 309 915 338 916 337 917 333 918 332 919 327 920 333 921 327 922 326 923 333 924 326 925 325 926 334 927 333 928 325 929 334 930 325 931 324 932 335 933 334 934 324 935 335 936 324 937 317 938 317 939 324 940 318 941 318 942 324 943 319 944 319 945 324 946 320 947 320 948 324 949 321 950 321 951 324 952 322 953 322 954 324 955 323 956 336 957 335 958 316 959 316 960 335 961 317 962 336 963 316 964 315 965 336 966 315 967 314 968 309 969 337 970 336 971 309 972 336 973 313 974 313 975 336 976 314 977 309 978 313 979 312 980 309 981 312 982 311 983 309 984 311 985 310 986 340 987 339 988 362 989 340 990 362 991 361 992 341 993 340 994 361 995 341 996 361 997 360 998 342 999 341 1000 360 1001 342 1002 360 1003 363 1004 363 1005 360 1006 364 1007 364 1008 360 1009 359 1010 343 1011 342 1012 386 1013 386 1014 342 1015 363 1016 343 1017 386 1018 385 1019 365 1020 364 1021 359 1022 343 1023 385 1024 384 1025 366 1026 365 1027 359 1028 366 1029 359 1030 358 1031 344 1032 343 1033 384 1034 344 1035 384 1036 383 1037 367 1038 366 1039 358 1040 344 1041 383 1042 382 1043 368 1044 367 1045 358 1046 368 1047 358 1048 357 1049 345 1050 344 1051 382 1052 345 1053 382 1054 381 1055 369 1056 368 1057 357 1058 346 1059 345 1060 381 1061 346 1062 381 1063 380 1064 369 1065 357 1066 356 1067 370 1068 369 1069 356 1070 346 1071 380 1072 379 1073 371 1074 370 1075 356 1076 347 1077 346 1078 379 1079 371 1080 356 1081 355 1082 347 1083 379 1084 378 1085 372 1086 371 1087 355 1088 347 1089 378 1090 377 1091 373 1092 372 1093 355 1094 348 1095 347 1096 377 1097 373 1098 355 1099 354 1100 348 1101 377 1102 376 1103 374 1104 373 1105 354 1106 348 1107 376 1108 375 1109 375 1110 374 1111 354 1112 348 1113 375 1114 354 1115 349 1116 348 1117 354 1118 349 1119 354 1120 353 1121 350 1122 349 1123 353 1124 350 1125 353 1126 352 1127 351 1128 350 1129 352 1130 388 1131 387 1132 420 1133 388 1134 420 1135 419 1136 388 1137 419 1138 418 1139 389 1140 388 1141 418 1142 390 1143 389 1144 418 1145 391 1146 390 1147 417 1148 417 1149 390 1150 418 1151 391 1152 417 1153 416 1154 391 1155 416 1156 415 1157 392 1158 391 1159 415 1160 392 1161 415 1162 414 1163 405 1164 404 1165 403 1166 392 1167 414 1168 413 1169 406 1170 405 1171 403 1172 393 1173 392 1174 413 1175 407 1176 406 1177 403 1178 393 1179 413 1180 412 1181 408 1182 407 1183 403 1184 393 1185 412 1186 411 1187 409 1188 408 1189 403 1190 393 1191 411 1192 410 1193 410 1194 409 1195 403 1196 393 1197 410 1198 403 1199 394 1200 393 1201 403 1202 395 1203 394 1204 403 1205 395 1206 403 1207 402 1208 395 1209 402 1210 401 1211 396 1212 395 1213 401 1214 396 1215 401 1216 400 1217 396 1218 400 1219 399 1220 397 1221 396 1222 399 1223 397 1224 399 1225 398 1226 422 1227 421 1228 458 1229 458 1230 421 1231 457 1232 458 1233 457 1234 456 1235 458 1236 456 1237 455 1238 458 1239 455 1240 454 1241 458 1242 454 1243 459 1244 459 1245 454 1246 453 1247 422 1248 458 1249 472 1250 460 1251 459 1252 453 1253 461 1254 460 1255 453 1256 461 1257 453 1258 452 1259 462 1260 461 1261 452 1262 463 1263 462 1264 452 1265 464 1266 463 1267 452 1268 464 1269 452 1270 451 1271 465 1272 464 1273 451 1274 466 1275 465 1276 451 1277 466 1278 451 1279 450 1280 467 1281 466 1282 450 1283 467 1284 450 1285 449 1286 468 1287 467 1288 449 1289 468 1290 449 1291 448 1292 469 1293 468 1294 448 1295 470 1296 469 1297 448 1298 470 1299 448 1300 447 1301 471 1302 470 1303 447 1304 422 1305 472 1306 424 1307 424 1308 472 1309 471 1310 424 1311 471 1312 447 1313 424 1314 447 1315 446 1316 424 1317 446 1318 445 1319 424 1320 445 1321 444 1322 424 1323 444 1324 425 1325 425 1326 444 1327 426 1328 426 1329 444 1330 443 1331 422 1332 424 1333 423 1334 427 1335 426 1336 443 1337 428 1338 427 1339 443 1340 428 1341 443 1342 442 1343 429 1344 428 1345 442 1346 429 1347 442 1348 441 1349 430 1350 429 1351 441 1352 430 1353 441 1354 440 1355 431 1356 430 1357 440 1358 431 1359 440 1360 439 1361 432 1362 431 1363 439 1364 432 1365 439 1366 438 1367 432 1368 438 1369 437 1370 432 1371 437 1372 436 1373 432 1374 436 1375 435 1376 432 1377 435 1378 434 1379 432 1380 434 1381 433 1382

      + + + + + + + 9.646 -1.87 0.0 9.62007 -1.88581 0.0 9.59419 -1.89911 0.0 9.56825 -1.90975 0.0 9.54215 -1.91756 0.0 9.51577 -1.92236 0.0 9.489 -1.924 0.0 9.44893 -1.92018 0.0 9.41474 -1.90878 0.0 9.3865 -1.88988 0.0 9.36426 -1.86356 0.0 9.34807 -1.8299 0.0 9.338 -1.789 0.0 9.654 -1.789 0.0 9.64782 -1.71306 0.0 9.62989 -1.65119 0.0 9.60113 -1.60325 0.0 9.56245 -1.56915 0.0 9.51476 -1.54877 0.0 9.459 -1.542 0.0 9.40039 -1.54944 0.0 9.34945 -1.57089 0.0 9.3075 -1.605 0.0 9.27589 -1.65044 0.0 9.25595 -1.70589 0.0 9.249 -1.77 0.0 9.25543 -1.83076 0.0 9.27441 -1.88707 0.0 9.3055 -1.936 0.0 9.34826 -1.97459 0.0 9.40224 -1.99991 0.0 9.467 -2.009 0.0 9.5029 -2.00757 0.0 9.53519 -2.00326 0.0 9.56475 -1.996 0.0 9.59248 -1.98574 0.0 9.61927 -1.97243 0.0 9.646 -1.956 0.0 9.34 -1.73 0.0 9.34841 -1.69712 0.0 9.36159 -1.66967 0.0 9.3795 -1.64787 0.0 9.40208 -1.632 0.0 9.42926 -1.62229 0.0 9.461 -1.619 0.0 9.49045 -1.6225 0.0 9.51556 -1.63267 0.0 9.536 -1.649 0.0 9.55145 -1.671 0.0 9.56156 -1.69817 0.0 9.566 -1.73 0.0 9.042 -1.458 0.0 8.875 -1.621 0.0 8.875 -1.631 0.0 8.953 -1.631 0.0 8.953 -1.868 0.0 8.95708 -1.90657 0.0 8.9693 -1.94056 0.0 8.98963 -1.96888 0.0 9.01804 -1.99044 0.0 9.05451 -2.00418 0.0 9.099 -2.009 0.0 9.11492 -2.00796 0.0 9.133 -2.005 0.0 9.15225 -2.00038 0.0 9.17167 -1.99433 0.0 9.19025 -1.98713 0.0 9.207 -1.979 0.0 9.207 -1.896 0.0 9.18924 -1.90608 0.0 9.17193 -1.91433 0.0 9.155 -1.92075 0.0 9.13841 -1.92533 0.0 9.12209 -1.92808 0.0 9.106 -1.929 0.0 9.09223 -1.92764 0.0 9.07785 -1.92315 0.0 9.06425 -1.91488 0.0 9.05282 -1.90219 0.0 9.04494 -1.88444 0.0 9.042 -1.861 0.0 9.042 -1.631 0.0 9.184 -1.631 0.0 9.184 -1.551 0.0 9.042 -1.551 0.0 8.859 -1.92 0.0 8.8492 -1.92699 0.0 8.83993 -1.93289 0.0 8.83138 -1.93762 0.0 8.82374 -1.94111 0.0 8.81722 -1.94326 0.0 8.812 -1.944 0.0 8.80692 -1.94348 0.0 8.8027 -1.94181 0.0 8.79938 -1.93887 0.0 8.79696 -1.93452 0.0 8.7955 -1.92861 0.0 8.795 -1.921 0.0 8.795 -1.69 0.0 8.78925 -1.64362 0.0 8.77296 -1.6063 0.0 8.74763 -1.57775 0.0 8.7147 -1.5577 0.0 8.67567 -1.54588 0.0 8.632 -1.542 0.0 8.60083 -1.54367 0.0 8.57226 -1.5487 0.0 8.54625 -1.55712 0.0 8.52274 -1.56896 0.0 8.50168 -1.58425 0.0 8.483 -1.603 0.0 8.483 -1.7 0.0 8.50505 -1.67681 0.0 8.52804 -1.65815 0.0 8.55175 -1.64387 0.0 8.57596 -1.63385 0.0 8.60045 -1.62794 0.0 8.625 -1.626 0.0 8.64975 -1.62796 0.0 8.67 -1.63404 0.0 8.68575 -1.6445 0.0 8.697 -1.65963 0.0 8.70375 -1.6797 0.0 8.706 -1.705 0.0 8.706 -1.729 0.0 8.627 -1.757 0.0 8.59067 -1.77037 0.0 8.55533 -1.78559 0.0 8.5235 -1.80437 0.0 8.49767 -1.82841 0.0 8.48033 -1.85938 0.0 8.474 -1.899 0.0 8.47757 -1.92729 0.0 8.48785 -1.9533 0.0 8.50425 -1.97575 0.0 8.52615 -1.99337 0.0 8.55294 -2.00488 0.0 8.584 -2.009 0.0 8.60449 -2.00775 0.0 8.62493 -2.00396 0.0 8.64525 -1.99762 0.0 8.66541 -1.9887 0.0 8.68534 -1.97717 0.0 8.705 -1.963 0.0 8.71011 -1.97752 0.0 8.71752 -1.98915 0.0 8.72738 -1.998 0.0 8.73982 -2.00419 0.0 8.75498 -2.00781 0.0 8.773 -2.009 0.0 8.78625 -2.00828 0.0 8.79863 -2.00593 0.0 8.81113 -2.00162 0.0 8.8247 -1.99507 0.0 8.84034 -1.98597 0.0 8.859 -1.974 0.0 8.706 -1.909 0.0 8.69383 -1.91973 0.0 8.68133 -1.92881 0.0 8.6685 -1.93612 0.0 8.65533 -1.94152 0.0 8.64183 -1.94486 0.0 8.628 -1.946 0.0 8.61041 -1.9439 0.0 8.59496 -1.93789 0.0 8.58212 -1.92838 0.0 8.57237 -1.91578 0.0 8.56617 -1.90051 0.0 8.564 -1.883 0.0 8.56924 -1.85863 0.0 8.58393 -1.838 0.0 8.6065 -1.82038 0.0 8.63541 -1.805 0.0 8.6691 -1.79113 0.0 8.706 -1.778 0.0 8.442 -1.551 0.0 8.257 -1.551 0.0 8.20047 -1.55581 0.0 8.15241 -1.56985 0.0 8.11363 -1.5925 0.0 8.08493 -1.62315 0.0 8.06712 -1.66119 0.0 8.061 -1.706 0.0 8.06167 -1.72208 0.0 8.06367 -1.73733 0.0 8.067 -1.75175 0.0 8.07167 -1.76533 0.0 8.07767 -1.77808 0.0 8.085 -1.79 0.0 8.09417 -1.80158 0.0 8.10467 -1.81233 0.0 8.1165 -1.82225 0.0 8.12967 -1.83133 0.0 8.14417 -1.83958 0.0 8.16 -1.847 0.0 8.16 -1.849 0.0 8.13981 -1.8552 0.0 8.12248 -1.86359 0.0 8.10837 -1.87388 0.0 8.09785 -1.88574 0.0 8.09127 -1.89888 0.0 8.089 -1.913 0.0 8.09018 -1.92285 0.0 8.09378 -1.93244 0.0 8.09988 -1.94187 0.0 8.10856 -1.95122 0.0 8.1199 -1.96057 0.0 8.134 -1.97 0.0 8.09855 -1.9812 0.0 8.07004 -1.99593 0.0 8.04825 -2.01438 0.0 8.03296 -2.03674 0.0 8.02395 -2.06322 0.0 8.021 -2.094 0.0 8.02793 -2.1315 0.0 8.04778 -2.16437 0.0 8.07913 -2.19163 0.0 8.12056 -2.2123 0.0 8.17065 -2.22541 0.0 8.228 -2.23 0.0 8.28988 -2.22559 0.0 8.34207 -2.2127 0.0 8.38387 -2.19188 0.0 8.41459 -2.16363 0.0 8.43353 -2.1285 0.0 8.44 -2.087 0.0 8.43704 -2.05927 0.0 8.42763 -2.03348 0.0 8.411 -2.01025 0.0 8.38637 -1.99019 0.0 8.35296 -1.9739 0.0 8.31 -1.962 0.0 8.2686 -1.95319 0.0 8.23448 -1.94452 0.0 8.20775 -1.93563 0.0 8.18852 -1.92615 0.0 8.1769 -1.91573 0.0 8.173 -1.904 0.0 8.18232 -1.88375 0.0 8.20685 -1.87263 0.0 8.2415 -1.86563 0.0 8.28115 -1.8577 0.0 8.32069 -1.84384 0.0 8.355 -1.819 0.0 8.3654 -1.8068 0.0 8.37522 -1.7917 0.0 8.38388 -1.7745 0.0 8.39078 -1.75596 0.0 8.39535 -1.73687 0.0 8.397 -1.718 0.0 8.39595 -1.69998 0.0 8.39259 -1.68348 0.0 8.38663 -1.66787 0.0 8.37774 -1.65252 0.0 8.36563 -1.63677 0.0 8.35 -1.62 0.0 8.442 -1.62 0.0 8.317 -1.707 0.0 8.3141 -1.73024 0.0 8.30582 -1.75056 0.0 8.29275 -1.76738 0.0 8.27552 -1.78011 0.0 8.25473 -1.78818 0.0 8.231 -1.791 0.0 8.20558 -1.78833 0.0 8.18367 -1.78063 0.0 8.16575 -1.76838 0.0 8.15234 -1.75204 0.0 8.14392 -1.73209 0.0 8.141 -1.709 0.0 8.14419 -1.68772 0.0 8.15319 -1.66844 0.0 8.16713 -1.652 0.0 8.18515 -1.63922 0.0 8.20639 -1.63094 0.0 8.23 -1.628 0.0 8.25276 -1.63087 0.0 8.27345 -1.63893 0.0 8.29113 -1.65138 0.0 8.30489 -1.66741 0.0 8.31382 -1.68622 0.0 8.354 -2.094 0.0 8.35023 -2.11305 0.0 8.33919 -2.12907 0.0 8.32125 -2.14188 0.0 8.29681 -2.15126 0.0 8.26627 -2.15703 0.0 8.23 -2.159 0.0 8.19262 -2.15701 0.0 8.16159 -2.15111 0.0 8.13713 -2.14138 0.0 8.11941 -2.12789 0.0 8.10863 -2.11074 0.0 8.105 -2.09 0.0 8.10839 -2.07107 0.0 8.11811 -2.05459 0.0 8.1335 -2.041 0.0 8.15389 -2.03074 0.0 8.17861 -2.02426 0.0 8.207 -2.022 0.0 8.23699 -2.02338 0.0 8.26956 -2.028 0.0 8.30113 -2.03663 0.0 8.32811 -2.05 0.0 8.34693 -2.06888 0.0 7.956 -1.551 0.0 7.867 -1.551 0.0 7.867 -2.0 0.0 7.956 -2.0 0.0 7.965 -1.415 0.0 7.96309 -1.401 0.0 7.9577 -1.38837 0.0 7.94938 -1.37762 0.0 7.93863 -1.3693 0.0 7.926 -1.36391 0.0 7.912 -1.362 0.0 7.89801 -1.36391 0.0 7.88537 -1.3693 0.0 7.87463 -1.37762 0.0 7.8663 -1.38837 0.0 7.86091 -1.401 0.0 7.859 -1.415 0.0 7.86091 -1.429 0.0 7.8663 -1.44163 0.0 7.87463 -1.45238 0.0 7.88537 -1.4607 0.0 7.89801 -1.46609 0.0 7.912 -1.468 0.0 7.926 -1.46609 0.0 7.93863 -1.4607 0.0 7.94938 -1.45238 0.0 7.9577 -1.44163 0.0 7.96309 -1.429 0.0 7.57 -2.009 0.0 7.6 -2.009 0.0 7.798 -1.551 0.0 7.703 -1.551 0.0 7.585 -1.827 0.0 7.464 -1.551 0.0 7.367 -1.551 0.0 7.348 -1.92 0.0 7.3382 -1.92699 0.0 7.32893 -1.93289 0.0 7.32038 -1.93762 0.0 7.31274 -1.94111 0.0 7.30622 -1.94326 0.0 7.301 -1.944 0.0 7.29592 -1.94348 0.0 7.2917 -1.94181 0.0 7.28837 -1.93887 0.0 7.28596 -1.93452 0.0 7.2845 -1.92861 0.0 7.284 -1.921 0.0 7.284 -1.69 0.0 7.27825 -1.64362 0.0 7.26196 -1.6063 0.0 7.23663 -1.57775 0.0 7.2037 -1.5577 0.0 7.16467 -1.54588 0.0 7.121 -1.542 0.0 7.08982 -1.54367 0.0 7.06126 -1.5487 0.0 7.03525 -1.55712 0.0 7.01174 -1.56896 0.0 6.99068 -1.58425 0.0 6.972 -1.603 0.0 6.972 -1.7 0.0 6.99405 -1.67681 0.0 7.01704 -1.65815 0.0 7.04075 -1.64387 0.0 7.06496 -1.63385 0.0 7.08945 -1.62794 0.0 7.114 -1.626 0.0 7.13875 -1.62796 0.0 7.159 -1.63404 0.0 7.17475 -1.6445 0.0 7.186 -1.65963 0.0 7.19275 -1.6797 0.0 7.195 -1.705 0.0 7.195 -1.729 0.0 7.116 -1.757 0.0 7.07967 -1.77037 0.0 7.04433 -1.78559 0.0 7.0125 -1.80437 0.0 6.98667 -1.82841 0.0 6.96933 -1.85938 0.0 6.963 -1.899 0.0 6.96657 -1.92729 0.0 6.97685 -1.9533 0.0 6.99325 -1.97575 0.0 7.01515 -1.99337 0.0 7.04194 -2.00488 0.0 7.073 -2.009 0.0 7.09349 -2.00775 0.0 7.11393 -2.00396 0.0 7.13425 -1.99762 0.0 7.15441 -1.9887 0.0 7.17434 -1.97717 0.0 7.194 -1.963 0.0 7.19911 -1.97752 0.0 7.20652 -1.98915 0.0 7.21638 -1.998 0.0 7.22882 -2.00419 0.0 7.24398 -2.00781 0.0 7.262 -2.009 0.0 7.27525 -2.00828 0.0 7.28763 -2.00593 0.0 7.30013 -2.00162 0.0 7.3137 -1.99507 0.0 7.32934 -1.98597 0.0 7.348 -1.974 0.0 7.195 -1.909 0.0 7.18283 -1.91973 0.0 7.17033 -1.92881 0.0 7.1575 -1.93612 0.0 7.14433 -1.94152 0.0 7.13083 -1.94486 0.0 7.117 -1.946 0.0 7.09941 -1.9439 0.0 7.08396 -1.93789 0.0 7.07113 -1.92838 0.0 7.06137 -1.91578 0.0 7.05517 -1.90051 0.0 7.053 -1.883 0.0 7.05824 -1.85863 0.0 7.07293 -1.838 0.0 7.0955 -1.82038 0.0 7.12441 -1.805 0.0 7.15809 -1.79113 0.0 7.195 -1.778 0.0 6.587 -1.551 0.0 6.498 -1.551 0.0 6.498 -2.0 0.0 6.587 -2.0 0.0 6.587 -1.678 0.0 6.60717 -1.65687 0.0 6.62604 -1.64026 0.0 6.64412 -1.62787 0.0 6.66196 -1.61941 0.0 6.68008 -1.61455 0.0 6.699 -1.613 0.0 6.72427 -1.61649 0.0 6.74582 -1.62659 0.0 6.76325 -1.64275 0.0 6.77619 -1.66441 0.0 6.78423 -1.69101 0.0 6.787 -1.722 0.0 6.787 -2.0 0.0 6.876 -2.0 0.0 6.876 -1.723 0.0 6.87057 -1.66688 0.0 6.85522 -1.62141 0.0 6.83138 -1.58637 0.0 6.80044 -1.56159 0.0 6.76385 -1.54687 0.0 6.723 -1.542 0.0 6.69807 -1.54405 0.0 6.67359 -1.55007 0.0 6.65 -1.55987 0.0 6.62774 -1.57326 0.0 6.60726 -1.59003 0.0 6.589 -1.61 0.0 6.587 -1.61 0.0 5.88 -1.542 0.0 5.81592 -1.55 0.0 5.759 -1.5727 0.0 5.71125 -1.60812 0.0 5.67467 -1.6543 0.0 5.65125 -1.70925 0.0 5.643 -1.771 0.0 5.65097 -1.83655 0.0 5.67378 -1.89404 0.0 5.70975 -1.94175 0.0 5.75722 -1.97796 0.0 5.81453 -2.00095 0.0 5.88 -2.009 0.0 5.948 -2.00123 0.0 6.007 -1.97885 0.0 6.0555 -1.94325 0.0 6.092 -1.89581 0.0 6.115 -1.83794 0.0 6.123 -1.771 0.0 6.11479 -1.70786 0.0 6.09133 -1.65252 0.0 6.05438 -1.60662 0.0 6.00567 -1.57181 0.0 5.94696 -1.54973 0.0 5.879 -1.622 0.0 5.92124 -1.62707 0.0 5.95822 -1.64156 0.0 5.98888 -1.66437 0.0 6.01211 -1.69444 0.0 6.02685 -1.73068 0.0 6.032 -1.772 0.0 6.02719 -1.81731 0.0 6.01322 -1.85581 0.0 5.99075 -1.88687 0.0 5.96044 -1.90985 0.0 5.92297 -1.92411 0.0 5.879 -1.929 0.0 5.8384 -1.92389 0.0 5.80319 -1.90915 0.0 5.77425 -1.88563 0.0 5.75248 -1.85419 0.0 5.73877 -1.81569 0.0 5.734 -1.771 0.0 5.73891 -1.7301 0.0 5.75293 -1.69415 0.0 5.775 -1.66425 0.0 5.80407 -1.64152 0.0 5.83909 -1.62706 0.0 5.441 -1.458 0.0 5.274 -1.621 0.0 5.274 -1.631 0.0 5.352 -1.631 0.0 5.352 -1.868 0.0 5.35608 -1.90657 0.0 5.3683 -1.94056 0.0 5.38863 -1.96888 0.0 5.41704 -1.99044 0.0 5.4535 -2.00418 0.0 5.498 -2.009 0.0 5.51392 -2.00796 0.0 5.532 -2.005 0.0 5.55125 -2.00038 0.0 5.57067 -1.99433 0.0 5.58925 -1.98713 0.0 5.606 -1.979 0.0 5.606 -1.896 0.0 5.58824 -1.90608 0.0 5.57093 -1.91433 0.0 5.554 -1.92075 0.0 5.53741 -1.92533 0.0 5.52109 -1.92808 0.0 5.505 -1.929 0.0 5.49123 -1.92764 0.0 5.47685 -1.92315 0.0 5.46325 -1.91488 0.0 5.45182 -1.90219 0.0 5.44394 -1.88444 0.0 5.441 -1.861 0.0 5.441 -1.631 0.0 5.583 -1.631 0.0 5.583 -1.551 0.0 5.441 -1.551 0.0 4.935 -1.579 0.0 4.91182 -1.56758 0.0 4.88922 -1.5583 0.0 4.86713 -1.55112 0.0 4.84544 -1.54604 0.0 4.8241 -1.543 0.0 4.803 -1.542 0.0 4.76079 -1.54576 0.0 4.72463 -1.55674 0.0 4.69525 -1.5745 0.0 4.67337 -1.59859 0.0 4.65971 -1.62857 0.0 4.655 -1.664 0.0 4.67056 -1.71771 0.0 4.70944 -1.76 0.0 4.76 -1.79412 0.0 4.81056 -1.82333 0.0 4.84944 -1.85087 0.0 4.865 -1.88 0.0 4.86261 -1.89475 0.0 4.85589 -1.907 0.0 4.8455 -1.91675 0.0 4.83211 -1.924 0.0 4.81639 -1.92875 0.0 4.799 -1.931 0.0 4.77964 -1.92941 0.0 4.75778 -1.92459 0.0 4.73375 -1.9165 0.0 4.70789 -1.90507 0.0 4.68053 -1.89026 0.0 4.652 -1.872 0.0 4.652 -1.968 0.0 4.67987 -1.98145 0.0 4.706 -1.99196 0.0 4.73112 -1.99975 0.0 4.756 -2.00504 0.0 4.78137 -2.00805 0.0 4.808 -2.009 0.0 4.84848 -2.00471 0.0 4.88415 -1.99233 0.0 4.91388 -1.97262 0.0 4.93652 -1.94633 0.0 4.95094 -1.91421 0.0 4.956 -1.877 0.0 4.95366 -1.8551 0.0 4.94626 -1.83478 0.0 4.93325 -1.81512 0.0 4.91407 -1.79522 0.0 4.88818 -1.77415 0.0 4.855 -1.751 0.0 4.8195 -1.72975 0.0 4.79163 -1.71167 0.0 4.77087 -1.69625 0.0 4.7567 -1.683 0.0 4.74859 -1.67142 0.0 4.746 -1.661 0.0 4.74787 -1.64963 0.0 4.7533 -1.6397 0.0 4.762 -1.6315 0.0 4.7737 -1.6253 0.0 4.78813 -1.62137 0.0 4.805 -1.62 0.0 4.82262 -1.62119 0.0 4.84226 -1.62485 0.0 4.86363 -1.63112 0.0 4.88641 -1.64015 0.0 4.9103 -1.65206 0.0 4.935 -1.667 0.0 4.611 -1.551 0.0 4.511 -1.551 0.0 4.395 -1.804 0.0 4.274 -1.551 0.0 4.173 -1.551 0.0 4.347 -1.904 0.0 4.194 -2.23 0.0 4.293 -2.23 0.0 4.132 -1.87 0.0 4.10606 -1.88581 0.0 4.08018 -1.89911 0.0 4.05425 -1.90975 0.0 4.02815 -1.91756 0.0 4.00177 -1.92236 0.0 3.975 -1.924 0.0 3.93493 -1.92018 0.0 3.90074 -1.90878 0.0 3.8725 -1.88988 0.0 3.85026 -1.86356 0.0 3.83407 -1.8299 0.0 3.824 -1.789 0.0 4.14 -1.789 0.0 4.13382 -1.71306 0.0 4.11589 -1.65119 0.0 4.08712 -1.60325 0.0 4.04844 -1.56915 0.0 4.00076 -1.54877 0.0 3.945 -1.542 0.0 3.88639 -1.54944 0.0 3.83544 -1.57089 0.0 3.7935 -1.605 0.0 3.76189 -1.65044 0.0 3.74194 -1.70589 0.0 3.735 -1.77 0.0 3.74143 -1.83076 0.0 3.76041 -1.88707 0.0 3.7915 -1.936 0.0 3.83426 -1.97459 0.0 3.88824 -1.99991 0.0 3.953 -2.009 0.0 3.9889 -2.00757 0.0 4.02118 -2.00326 0.0 4.05075 -1.996 0.0 4.07848 -1.98574 0.0 4.10527 -1.97243 0.0 4.132 -1.956 0.0 3.826 -1.73 0.0 3.83441 -1.69712 0.0 3.84759 -1.66967 0.0 3.8655 -1.64787 0.0 3.88807 -1.632 0.0 3.91526 -1.62229 0.0 3.947 -1.619 0.0 3.97644 -1.6225 0.0 4.00156 -1.63267 0.0 4.022 -1.649 0.0 4.03744 -1.671 0.0 4.04756 -1.69817 0.0 4.052 -1.73 0.0 3.675 -1.551 0.0 3.569 -1.551 0.0 3.37 -1.771 0.0 3.595 -2.0 0.0 3.715 -2.0 0.0 3.483 -1.771 0.0 3.366 -1.318 0.0 3.277 -1.318 0.0 3.277 -2.0 0.0 3.366 -2.0 0.0 2.61 -1.551 0.0 2.61 -2.0 0.0 2.699 -2.0 0.0 2.699 -1.765 0.0 2.70284 -1.72804 0.0 2.7137 -1.695 0.0 2.73062 -1.66712 0.0 2.75263 -1.64567 0.0 2.77875 -1.63187 0.0 2.808 -1.627 0.0 2.81956 -1.62845 0.0 2.83285 -1.63263 0.0 2.84725 -1.63925 0.0 2.86215 -1.64804 0.0 2.87694 -1.65871 0.0 2.891 -1.671 0.0 2.938 -1.594 0.0 2.91973 -1.578 0.0 2.90181 -1.56496 0.0 2.88412 -1.55487 0.0 2.86652 -1.5477 0.0 2.84886 -1.54342 0.0 2.831 -1.542 0.0 2.80991 -1.54481 0.0 2.78863 -1.55348 0.0 2.76712 -1.56837 0.0 2.74537 -1.58985 0.0 2.72334 -1.61827 0.0 2.701 -1.654 0.0 2.699 -1.654 0.0 2.699 -1.551 0.0 2.262 -1.542 0.0 2.19792 -1.55 0.0 2.141 -1.5727 0.0 2.09325 -1.60812 0.0 2.05667 -1.6543 0.0 2.03325 -1.70925 0.0 2.025 -1.771 0.0 2.03297 -1.83655 0.0 2.05578 -1.89404 0.0 2.09175 -1.94175 0.0 2.13922 -1.97796 0.0 2.19653 -2.00095 0.0 2.262 -2.009 0.0 2.33 -2.00123 0.0 2.389 -1.97885 0.0 2.4375 -1.94325 0.0 2.474 -1.89581 0.0 2.497 -1.83794 0.0 2.505 -1.771 0.0 2.49679 -1.70786 0.0 2.47333 -1.65252 0.0 2.43637 -1.60662 0.0 2.38767 -1.57181 0.0 2.32896 -1.54973 0.0 2.261 -1.622 0.0 2.30324 -1.62707 0.0 2.34022 -1.64156 0.0 2.37087 -1.66437 0.0 2.39411 -1.69444 0.0 2.40885 -1.73068 0.0 2.414 -1.772 0.0 2.40919 -1.81731 0.0 2.39522 -1.85581 0.0 2.37275 -1.88687 0.0 2.34244 -1.90985 0.0 2.30497 -1.92411 0.0 2.261 -1.929 0.0 2.2204 -1.92389 0.0 2.18519 -1.90915 0.0 2.15625 -1.88563 0.0 2.13448 -1.85419 0.0 2.12077 -1.81569 0.0 2.116 -1.771 0.0 2.12091 -1.7301 0.0 2.13493 -1.69415 0.0 2.157 -1.66425 0.0 2.18607 -1.64152 0.0 2.22109 -1.62706 0.0 1.928 -1.579 0.0 1.90482 -1.56758 0.0 1.88222 -1.5583 0.0 1.86013 -1.55112 0.0 1.83844 -1.54604 0.0 1.8171 -1.543 0.0 1.796 -1.542 0.0 1.75379 -1.54576 0.0 1.71763 -1.55674 0.0 1.68825 -1.5745 0.0 1.66637 -1.59859 0.0 1.65271 -1.62857 0.0 1.648 -1.664 0.0 1.66356 -1.71771 0.0 1.70244 -1.76 0.0 1.753 -1.79412 0.0 1.80356 -1.82333 0.0 1.84244 -1.85087 0.0 1.858 -1.88 0.0 1.85561 -1.89475 0.0 1.84889 -1.907 0.0 1.8385 -1.91675 0.0 1.82511 -1.924 0.0 1.80939 -1.92875 0.0 1.792 -1.931 0.0 1.77264 -1.92941 0.0 1.75078 -1.92459 0.0 1.72675 -1.9165 0.0 1.70089 -1.90507 0.0 1.67353 -1.89026 0.0 1.645 -1.872 0.0 1.645 -1.968 0.0 1.67287 -1.98145 0.0 1.699 -1.99196 0.0 1.72412 -1.99975 0.0 1.749 -2.00504 0.0 1.77437 -2.00805 0.0 1.801 -2.009 0.0 1.84148 -2.00471 0.0 1.87715 -1.99233 0.0 1.90687 -1.97262 0.0 1.92952 -1.94633 0.0 1.94394 -1.91421 0.0 1.949 -1.877 0.0 1.94666 -1.8551 0.0 1.93926 -1.83478 0.0 1.92625 -1.81512 0.0 1.90707 -1.79522 0.0 1.88118 -1.77415 0.0 1.848 -1.751 0.0 1.8125 -1.72975 0.0 1.78463 -1.71167 0.0 1.76387 -1.69625 0.0 1.7497 -1.683 0.0 1.74159 -1.67142 0.0 1.739 -1.661 0.0 1.74087 -1.64963 0.0 1.7463 -1.6397 0.0 1.755 -1.6315 0.0 1.7667 -1.6253 0.0 1.78113 -1.62137 0.0 1.798 -1.62 0.0 1.81562 -1.62119 0.0 1.83526 -1.62485 0.0 1.85663 -1.63112 0.0 1.87941 -1.64015 0.0 1.9033 -1.65206 0.0 1.928 -1.667 0.0 1.277 -1.551 0.0 1.277 -2.0 0.0 1.366 -2.0 0.0 1.366 -1.765 0.0 1.36984 -1.72804 0.0 1.3807 -1.695 0.0 1.39762 -1.66712 0.0 1.41963 -1.64567 0.0 1.44575 -1.63187 0.0 1.475 -1.627 0.0 1.48656 -1.62845 0.0 1.49985 -1.63263 0.0 1.51425 -1.63925 0.0 1.52915 -1.64804 0.0 1.54394 -1.65871 0.0 1.558 -1.671 0.0 1.605 -1.594 0.0 1.58673 -1.578 0.0 1.56881 -1.56496 0.0 1.55112 -1.55487 0.0 1.53352 -1.5477 0.0 1.51586 -1.54342 0.0 1.498 -1.542 0.0 1.47691 -1.54481 0.0 1.45563 -1.55348 0.0 1.43412 -1.56837 0.0 1.41237 -1.58985 0.0 1.39034 -1.61827 0.0 1.368 -1.654 0.0 1.366 -1.654 0.0 1.366 -1.551 0.0 1.145 -2.0 0.0 1.145 -1.551 0.0 1.056 -1.551 0.0 1.056 -1.872 0.0 1.04078 -1.8909 0.0 1.02426 -1.90656 0.0 1.00662 -1.91887 0.0 0.98807 -1.92778 0.0 0.9688 -1.93318 0.0 0.949 -1.935 0.0 0.921 -1.93204 0.0 0.89804 -1.92333 0.0 0.88013 -1.90912 0.0 0.8673 -1.88967 0.0 0.85958 -1.86521 0.0 0.857 -1.836 0.0 0.857 -1.551 0.0 0.768 -1.551 0.0 0.768 -1.83 0.0 0.77316 -1.88284 0.0 0.78796 -1.92707 0.0 0.81138 -1.96225 0.0 0.84237 -1.98793 0.0 0.87992 -2.00366 0.0 0.923 -2.009 0.0 0.94556 -2.00689 0.0 0.96881 -2.00078 0.0 0.99212 -1.991 0.0 1.01485 -1.97789 0.0 1.03636 -1.96178 0.0 1.056 -1.943 0.0 1.056 -2.0 0.0 0.656 -1.365 0.0 0.61124 -1.34731 0.0 0.56956 -1.33315 0.0 0.53038 -1.32237 0.0 0.49311 -1.31485 0.0 0.45718 -1.31044 0.0 0.422 -1.309 0.0 0.31895 -1.32122 0.0 0.22859 -1.35611 0.0 0.15363 -1.411 0.0 0.09674 -1.48322 0.0 0.06063 -1.57011 0.0 0.048 -1.669 0.0 0.05748 -1.74384 0.0 0.08652 -1.8207 0.0 0.136 -1.89263 0.0 0.20681 -1.95263 0.0 0.29985 -1.99375 0.0 0.416 -2.009 0.0 0.4668 -2.00699 0.0 0.5127 -2.00122 0.0 0.5545 -1.99212 0.0 0.59296 -1.98011 0.0 0.62887 -1.9656 0.0 0.663 -1.949 0.0 0.663 -1.842 0.0 0.62398 -1.86506 0.0 0.58419 -1.88419 0.0 0.544 -1.89925 0.0 0.50381 -1.91015 0.0 0.46402 -1.91677 0.0 0.425 -1.919 0.0 0.34761 -1.91044 0.0 0.28056 -1.88585 0.0 0.2255 -1.84687 0.0 0.18411 -1.79515 0.0 0.15806 -1.73231 0.0 0.149 -1.66 0.0 0.15831 -1.58858 0.0 0.18485 -1.52567 0.0 0.2265 -1.47325 0.0 0.28115 -1.43333 0.0 0.34669 -1.40792 0.0 0.421 -1.399 0.0 0.46 -1.40086 0.0 0.49837 -1.40652 0.0 0.53663 -1.41612 0.0 0.5753 -1.42981 0.0 0.61491 -1.44773 0.0 0.656 -1.47 0.0 14.542 -0.458 0.0 14.375 -0.621 0.0 14.375 -0.631 0.0 14.453 -0.631 0.0 14.453 -0.868 0.0 14.45708 -0.90657 0.0 14.4693 -0.94056 0.0 14.48962 -0.96887 0.0 14.51804 -0.99044 0.0 14.5545 -1.00418 0.0 14.599 -1.009 0.0 14.61492 -1.00796 0.0 14.633 -1.005 0.0 14.65225 -1.00038 0.0 14.67167 -0.99433 0.0 14.69025 -0.98713 0.0 14.707 -0.979 0.0 14.707 -0.896 0.0 14.68924 -0.90608 0.0 14.67193 -0.91433 0.0 14.655 -0.92075 0.0 14.63841 -0.92533 0.0 14.62209 -0.92808 0.0 14.606 -0.929 0.0 14.59223 -0.92764 0.0 14.57785 -0.92315 0.0 14.56425 -0.91487 0.0 14.55281 -0.90219 0.0 14.54494 -0.88444 0.0 14.542 -0.861 0.0 14.542 -0.631 0.0 14.684 -0.631 0.0 14.684 -0.551 0.0 14.542 -0.551 0.0 14.096 -0.542 0.0 14.03192 -0.55 0.0 13.975 -0.5727 0.0 13.92725 -0.60812 0.0 13.89067 -0.6543 0.0 13.86725 -0.70925 0.0 13.859 -0.771 0.0 13.86697 -0.83655 0.0 13.88978 -0.89404 0.0 13.92575 -0.94175 0.0 13.97322 -0.97796 0.0 14.03053 -1.00095 0.0 14.096 -1.009 0.0 14.164 -1.00123 0.0 14.223 -0.97885 0.0 14.2715 -0.94325 0.0 14.308 -0.89581 0.0 14.331 -0.83794 0.0 14.339 -0.771 0.0 14.33079 -0.70786 0.0 14.30733 -0.65252 0.0 14.27037 -0.60662 0.0 14.22167 -0.57181 0.0 14.16296 -0.54973 0.0 14.095 -0.622 0.0 14.13724 -0.62707 0.0 14.17422 -0.64156 0.0 14.20488 -0.66438 0.0 14.22811 -0.69444 0.0 14.24285 -0.73068 0.0 14.248 -0.772 0.0 14.24319 -0.81731 0.0 14.22922 -0.85581 0.0 14.20675 -0.88688 0.0 14.17644 -0.90985 0.0 14.13897 -0.92411 0.0 14.095 -0.929 0.0 14.0544 -0.92389 0.0 14.01919 -0.90915 0.0 13.99025 -0.88563 0.0 13.96848 -0.85419 0.0 13.95477 -0.81569 0.0 13.95 -0.771 0.0 13.95491 -0.7301 0.0 13.96893 -0.69415 0.0 13.991 -0.66425 0.0 14.02007 -0.64152 0.0 14.05509 -0.62706 0.0 13.473 -0.318 0.0 13.384 -0.318 0.0 13.384 -1.0 0.0 13.473 -1.0 0.0 13.473 -0.678 0.0 13.49317 -0.65687 0.0 13.51204 -0.64026 0.0 13.53012 -0.62788 0.0 13.54796 -0.61941 0.0 13.56608 -0.61455 0.0 13.585 -0.613 0.0 13.61027 -0.61649 0.0 13.63181 -0.62659 0.0 13.64925 -0.64275 0.0 13.66219 -0.66441 0.0 13.67023 -0.69101 0.0 13.673 -0.722 0.0 13.673 -1.0 0.0 13.762 -1.0 0.0 13.762 -0.725 0.0 13.75678 -0.66874 0.0 13.74189 -0.62289 0.0 13.7185 -0.58737 0.0 13.68778 -0.56211 0.0 13.65089 -0.54701 0.0 13.609 -0.542 0.0 13.58407 -0.54405 0.0 13.55959 -0.55007 0.0 13.536 -0.55987 0.0 13.51374 -0.57326 0.0 13.49326 -0.59003 0.0 13.475 -0.61 0.0 13.473 -0.61 0.0 13.262 -0.579 0.0 13.23882 -0.56758 0.0 13.21622 -0.5583 0.0 13.19412 -0.55112 0.0 13.17244 -0.54604 0.0 13.1511 -0.543 0.0 13.13 -0.542 0.0 13.08779 -0.54576 0.0 13.05163 -0.55674 0.0 13.02225 -0.5745 0.0 13.00037 -0.59859 0.0 12.98671 -0.62857 0.0 12.982 -0.664 0.0 12.99755 -0.71771 0.0 13.03644 -0.76 0.0 13.087 -0.79412 0.0 13.13755 -0.82333 0.0 13.17644 -0.85088 0.0 13.192 -0.88 0.0 13.18961 -0.89475 0.0 13.18289 -0.907 0.0 13.1725 -0.91675 0.0 13.15911 -0.924 0.0 13.14339 -0.92875 0.0 13.126 -0.931 0.0 13.10664 -0.92941 0.0 13.08478 -0.92459 0.0 13.06075 -0.9165 0.0 13.03489 -0.90507 0.0 13.00753 -0.89026 0.0 12.979 -0.872 0.0 12.979 -0.968 0.0 13.00688 -0.98145 0.0 13.033 -0.99196 0.0 13.05812 -0.99975 0.0 13.083 -1.00504 0.0 13.10837 -1.00805 0.0 13.135 -1.009 0.0 13.17548 -1.00471 0.0 13.21115 -0.99233 0.0 13.24087 -0.97262 0.0 13.26352 -0.94633 0.0 13.27794 -0.91421 0.0 13.283 -0.877 0.0 13.28066 -0.8551 0.0 13.27326 -0.83478 0.0 13.26025 -0.81512 0.0 13.24107 -0.79522 0.0 13.21518 -0.77415 0.0 13.182 -0.751 0.0 13.1465 -0.72975 0.0 13.11863 -0.71167 0.0 13.09788 -0.69625 0.0 13.0837 -0.683 0.0 13.07559 -0.67142 0.0 13.073 -0.661 0.0 13.07487 -0.64963 0.0 13.0803 -0.6397 0.0 13.089 -0.6315 0.0 13.1007 -0.6253 0.0 13.11513 -0.62137 0.0 13.132 -0.62 0.0 13.14962 -0.62119 0.0 13.16926 -0.62485 0.0 13.19063 -0.63113 0.0 13.21341 -0.64015 0.0 13.2373 -0.65206 0.0 13.262 -0.667 0.0 12.66 -0.551 0.0 12.56 -0.551 0.0 12.444 -0.804 0.0 12.323 -0.551 0.0 12.222 -0.551 0.0 12.396 -0.904 0.0 12.243 -1.23 0.0 12.342 -1.23 0.0 12.157 -0.318 0.0 12.068 -0.318 0.0 12.068 -1.0 0.0 12.157 -1.0 0.0 11.649 -0.989 0.0 11.66546 -0.99534 0.0 11.681 -1.00041 0.0 11.69588 -1.00425 0.0 11.71033 -1.00693 0.0 11.72463 -1.00849 0.0 11.739 -1.009 0.0 11.80207 -1.00134 0.0 11.85722 -0.97937 0.0 11.90287 -0.94462 0.0 11.93744 -0.89863 0.0 11.95935 -0.84291 0.0 11.967 -0.779 0.0 11.95965 -0.71072 0.0 11.93785 -0.65411 0.0 11.902 -0.6095 0.0 11.85248 -0.57722 0.0 11.78969 -0.55761 0.0 11.714 -0.551 0.0 11.56 -0.551 0.0 11.56 -1.23 0.0 11.649 -1.23 0.0 11.649 -0.631 0.0 11.73 -0.631 0.0 11.7745 -0.63543 0.0 11.81096 -0.64844 0.0 11.83938 -0.66962 0.0 11.8597 -0.69856 0.0 11.87192 -0.73482 0.0 11.876 -0.778 0.0 11.87117 -0.81939 0.0 11.85737 -0.85581 0.0 11.83563 -0.88613 0.0 11.80696 -0.90919 0.0 11.77241 -0.92386 0.0 11.733 -0.929 0.0 11.71893 -0.92842 0.0 11.70478 -0.9267 0.0 11.69063 -0.92387 0.0 11.67656 -0.91996 0.0 11.66265 -0.915 0.0 11.649 -0.909 0.0 11.149 -0.989 0.0 11.16546 -0.99534 0.0 11.181 -1.00041 0.0 11.19588 -1.00425 0.0 11.21033 -1.00693 0.0 11.22463 -1.00849 0.0 11.239 -1.009 0.0 11.30207 -1.00134 0.0 11.35722 -0.97937 0.0 11.40287 -0.94462 0.0 11.43744 -0.89863 0.0 11.45935 -0.84291 0.0 11.467 -0.779 0.0 11.45965 -0.71072 0.0 11.43785 -0.65411 0.0 11.402 -0.6095 0.0 11.35248 -0.57722 0.0 11.28969 -0.55761 0.0 11.214 -0.551 0.0 11.06 -0.551 0.0 11.06 -1.23 0.0 11.149 -1.23 0.0 11.149 -0.631 0.0 11.23 -0.631 0.0 11.2745 -0.63543 0.0 11.31096 -0.64844 0.0 11.33938 -0.66962 0.0 11.3597 -0.69856 0.0 11.37192 -0.73482 0.0 11.376 -0.778 0.0 11.37117 -0.81939 0.0 11.35737 -0.85581 0.0 11.33563 -0.88613 0.0 11.30696 -0.90919 0.0 11.27241 -0.92386 0.0 11.233 -0.929 0.0 11.21893 -0.92842 0.0 11.20478 -0.9267 0.0 11.19063 -0.92387 0.0 11.17656 -0.91996 0.0 11.16265 -0.915 0.0 11.149 -0.909 0.0 10.987 -0.92 0.0 10.9772 -0.92699 0.0 10.96793 -0.93289 0.0 10.95938 -0.93762 0.0 10.95174 -0.94111 0.0 10.94522 -0.94326 0.0 10.94 -0.944 0.0 10.93492 -0.94348 0.0 10.9307 -0.94181 0.0 10.92737 -0.93888 0.0 10.92496 -0.93452 0.0 10.9235 -0.92861 0.0 10.923 -0.921 0.0 10.923 -0.69 0.0 10.91725 -0.64362 0.0 10.90096 -0.6063 0.0 10.87563 -0.57775 0.0 10.8427 -0.5577 0.0 10.80367 -0.54588 0.0 10.76 -0.542 0.0 10.72882 -0.54367 0.0 10.70026 -0.5487 0.0 10.67425 -0.55712 0.0 10.65074 -0.56896 0.0 10.62968 -0.58425 0.0 10.611 -0.603 0.0 10.611 -0.7 0.0 10.63305 -0.67681 0.0 10.65604 -0.65815 0.0 10.67975 -0.64387 0.0 10.70396 -0.63385 0.0 10.72845 -0.62794 0.0 10.753 -0.626 0.0 10.77775 -0.62796 0.0 10.798 -0.63404 0.0 10.81375 -0.6445 0.0 10.825 -0.65963 0.0 10.83175 -0.6797 0.0 10.834 -0.705 0.0 10.834 -0.729 0.0 10.755 -0.757 0.0 10.71867 -0.77037 0.0 10.68333 -0.78559 0.0 10.6515 -0.80437 0.0 10.62567 -0.82841 0.0 10.60833 -0.85938 0.0 10.602 -0.899 0.0 10.60557 -0.92729 0.0 10.61585 -0.9533 0.0 10.63225 -0.97575 0.0 10.65415 -0.99337 0.0 10.68094 -1.00488 0.0 10.712 -1.009 0.0 10.73249 -1.00775 0.0 10.75293 -1.00396 0.0 10.77325 -0.99762 0.0 10.79341 -0.9887 0.0 10.81334 -0.97717 0.0 10.833 -0.963 0.0 10.83811 -0.97752 0.0 10.84552 -0.98915 0.0 10.85538 -0.998 0.0 10.86782 -1.00419 0.0 10.88298 -1.00781 0.0 10.901 -1.009 0.0 10.91425 -1.00828 0.0 10.92663 -1.00593 0.0 10.93913 -1.00162 0.0 10.9527 -0.99507 0.0 10.96834 -0.98597 0.0 10.987 -0.974 0.0 10.834 -0.909 0.0 10.82183 -0.91973 0.0 10.80933 -0.92881 0.0 10.7965 -0.93613 0.0 10.78333 -0.94152 0.0 10.76983 -0.94486 0.0 10.756 -0.946 0.0 10.73841 -0.9439 0.0 10.72296 -0.93789 0.0 10.71012 -0.92838 0.0 10.70037 -0.91578 0.0 10.69417 -0.90051 0.0 10.692 -0.883 0.0 10.69724 -0.85862 0.0 10.71193 -0.838 0.0 10.7345 -0.82038 0.0 10.76341 -0.805 0.0 10.79709 -0.79112 0.0 10.834 -0.778 0.0 10.019 -0.542 0.0 9.95492 -0.55 0.0 9.898 -0.5727 0.0 9.85025 -0.60812 0.0 9.81367 -0.6543 0.0 9.79025 -0.70925 0.0 9.782 -0.771 0.0 9.78997 -0.83655 0.0 9.81278 -0.89404 0.0 9.84875 -0.94175 0.0 9.89622 -0.97796 0.0 9.95353 -1.00095 0.0 10.019 -1.009 0.0 10.087 -1.00123 0.0 10.146 -0.97885 0.0 10.1945 -0.94325 0.0 10.231 -0.89581 0.0 10.254 -0.83794 0.0 10.262 -0.771 0.0 10.25379 -0.70786 0.0 10.23033 -0.65252 0.0 10.19337 -0.60662 0.0 10.14467 -0.57181 0.0 10.08596 -0.54973 0.0 10.018 -0.622 0.0 10.06024 -0.62707 0.0 10.09722 -0.64156 0.0 10.12788 -0.66438 0.0 10.15111 -0.69444 0.0 10.16585 -0.73068 0.0 10.171 -0.772 0.0 10.16619 -0.81731 0.0 10.15222 -0.85581 0.0 10.12975 -0.88688 0.0 10.09944 -0.90985 0.0 10.06197 -0.92411 0.0 10.018 -0.929 0.0 9.9774 -0.92389 0.0 9.94219 -0.90915 0.0 9.91325 -0.88563 0.0 9.89148 -0.85419 0.0 9.87777 -0.81569 0.0 9.873 -0.771 0.0 9.87791 -0.7301 0.0 9.89193 -0.69415 0.0 9.914 -0.66425 0.0 9.94307 -0.64152 0.0 9.97809 -0.62706 0.0 9.58 -0.458 0.0 9.413 -0.621 0.0 9.413 -0.631 0.0 9.491 -0.631 0.0 9.491 -0.868 0.0 9.49508 -0.90657 0.0 9.5073 -0.94056 0.0 9.52763 -0.96887 0.0 9.55604 -0.99044 0.0 9.5925 -1.00418 0.0 9.637 -1.009 0.0 9.65292 -1.00796 0.0 9.671 -1.005 0.0 9.69025 -1.00038 0.0 9.70967 -0.99433 0.0 9.72825 -0.98713 0.0 9.745 -0.979 0.0 9.745 -0.896 0.0 9.72724 -0.90608 0.0 9.70993 -0.91433 0.0 9.693 -0.92075 0.0 9.67641 -0.92533 0.0 9.66009 -0.92808 0.0 9.644 -0.929 0.0 9.63023 -0.92764 0.0 9.61585 -0.92315 0.0 9.60225 -0.91487 0.0 9.59081 -0.90219 0.0 9.58294 -0.88444 0.0 9.58 -0.861 0.0 9.58 -0.631 0.0 9.722 -0.631 0.0 9.722 -0.551 0.0 9.58 -0.551 0.0 9.094 -0.87 0.0 9.06806 -0.88581 0.0 9.04218 -0.89911 0.0 9.01625 -0.90975 0.0 8.99015 -0.91756 0.0 8.96377 -0.92236 0.0 8.937 -0.924 0.0 8.89693 -0.92018 0.0 8.86274 -0.90878 0.0 8.8345 -0.88987 0.0 8.81226 -0.86356 0.0 8.79607 -0.8299 0.0 8.786 -0.789 0.0 9.102 -0.789 0.0 9.09582 -0.71306 0.0 9.07789 -0.65119 0.0 9.04912 -0.60325 0.0 9.01044 -0.56915 0.0 8.96276 -0.54877 0.0 8.907 -0.542 0.0 8.84839 -0.54944 0.0 8.79745 -0.57089 0.0 8.7555 -0.605 0.0 8.72389 -0.65044 0.0 8.70395 -0.70589 0.0 8.697 -0.77 0.0 8.70343 -0.83076 0.0 8.72241 -0.88707 0.0 8.7535 -0.936 0.0 8.79626 -0.97459 0.0 8.85024 -0.99991 0.0 8.915 -1.009 0.0 8.9509 -1.00757 0.0 8.98318 -1.00326 0.0 9.01275 -0.996 0.0 9.04048 -0.98574 0.0 9.06727 -0.97243 0.0 9.094 -0.956 0.0 8.788 -0.73 0.0 8.79641 -0.69713 0.0 8.80959 -0.66967 0.0 8.8275 -0.64787 0.0 8.85007 -0.632 0.0 8.87726 -0.62229 0.0 8.909 -0.619 0.0 8.93845 -0.6225 0.0 8.96356 -0.63267 0.0 8.984 -0.649 0.0 8.99944 -0.671 0.0 9.00956 -0.69817 0.0 9.014 -0.73 0.0 8.595 -0.579 0.0 8.57182 -0.56758 0.0 8.54922 -0.5583 0.0 8.52712 -0.55112 0.0 8.50544 -0.54604 0.0 8.4841 -0.543 0.0 8.463 -0.542 0.0 8.42079 -0.54576 0.0 8.38463 -0.55674 0.0 8.35525 -0.5745 0.0 8.33337 -0.59859 0.0 8.31971 -0.62857 0.0 8.315 -0.664 0.0 8.33055 -0.71771 0.0 8.36944 -0.76 0.0 8.42 -0.79412 0.0 8.47055 -0.82333 0.0 8.50944 -0.85088 0.0 8.525 -0.88 0.0 8.52261 -0.89475 0.0 8.51589 -0.907 0.0 8.5055 -0.91675 0.0 8.49211 -0.924 0.0 8.47639 -0.92875 0.0 8.459 -0.931 0.0 8.43964 -0.92941 0.0 8.41778 -0.92459 0.0 8.39375 -0.9165 0.0 8.36789 -0.90507 0.0 8.34053 -0.89026 0.0 8.312 -0.872 0.0 8.312 -0.968 0.0 8.33988 -0.98145 0.0 8.366 -0.99196 0.0 8.39112 -0.99975 0.0 8.416 -1.00504 0.0 8.44137 -1.00805 0.0 8.468 -1.009 0.0 8.50848 -1.00471 0.0 8.54415 -0.99233 0.0 8.57387 -0.97262 0.0 8.59652 -0.94633 0.0 8.61094 -0.91421 0.0 8.616 -0.877 0.0 8.61366 -0.8551 0.0 8.60626 -0.83478 0.0 8.59325 -0.81512 0.0 8.57407 -0.79522 0.0 8.54818 -0.77415 0.0 8.515 -0.751 0.0 8.4795 -0.72975 0.0 8.45163 -0.71167 0.0 8.43088 -0.69625 0.0 8.4167 -0.683 0.0 8.40859 -0.67142 0.0 8.406 -0.661 0.0 8.40787 -0.64963 0.0 8.4133 -0.6397 0.0 8.422 -0.6315 0.0 8.4337 -0.6253 0.0 8.44813 -0.62137 0.0 8.465 -0.62 0.0 8.48262 -0.62119 0.0 8.50226 -0.62485 0.0 8.52363 -0.63113 0.0 8.54641 -0.64015 0.0 8.5703 -0.65206 0.0 8.595 -0.667 0.0 8.208 -1.0 0.0 8.208 -0.551 0.0 8.119 -0.551 0.0 8.119 -0.872 0.0 8.10378 -0.8909 0.0 8.08726 -0.90656 0.0 8.06962 -0.91887 0.0 8.05107 -0.92778 0.0 8.0318 -0.93318 0.0 8.012 -0.935 0.0 7.984 -0.93204 0.0 7.96104 -0.92333 0.0 7.94313 -0.90912 0.0 7.9303 -0.88967 0.0 7.92258 -0.86521 0.0 7.92 -0.836 0.0 7.92 -0.551 0.0 7.831 -0.551 0.0 7.831 -0.83 0.0 7.83616 -0.88284 0.0 7.85096 -0.92707 0.0 7.87438 -0.96225 0.0 7.90537 -0.98793 0.0 7.94292 -1.00366 0.0 7.986 -1.009 0.0 8.00856 -1.00689 0.0 8.03182 -1.00078 0.0 8.05513 -0.991 0.0 8.07785 -0.97789 0.0 8.09936 -0.96178 0.0 8.119 -0.943 0.0 8.119 -1.0 0.0 7.492 -0.542 0.0 7.42792 -0.55 0.0 7.371 -0.5727 0.0 7.32325 -0.60812 0.0 7.28667 -0.6543 0.0 7.26325 -0.70925 0.0 7.255 -0.771 0.0 7.26297 -0.83655 0.0 7.28578 -0.89404 0.0 7.32175 -0.94175 0.0 7.36922 -0.97796 0.0 7.42653 -1.00095 0.0 7.492 -1.009 0.0 7.56 -1.00123 0.0 7.619 -0.97885 0.0 7.6675 -0.94325 0.0 7.704 -0.89581 0.0 7.727 -0.83794 0.0 7.735 -0.771 0.0 7.72679 -0.70786 0.0 7.70333 -0.65252 0.0 7.66638 -0.60662 0.0 7.61767 -0.57181 0.0 7.55896 -0.54973 0.0 7.491 -0.622 0.0 7.53324 -0.62707 0.0 7.57022 -0.64156 0.0 7.60088 -0.66438 0.0 7.62411 -0.69444 0.0 7.63885 -0.73068 0.0 7.644 -0.772 0.0 7.63919 -0.81731 0.0 7.62522 -0.85581 0.0 7.60275 -0.88688 0.0 7.57244 -0.90985 0.0 7.53497 -0.92411 0.0 7.491 -0.929 0.0 7.4504 -0.92389 0.0 7.41519 -0.90915 0.0 7.38625 -0.88563 0.0 7.36448 -0.85419 0.0 7.35077 -0.81569 0.0 7.346 -0.771 0.0 7.35091 -0.7301 0.0 7.36493 -0.69415 0.0 7.387 -0.66425 0.0 7.41607 -0.64152 0.0 7.45109 -0.62706 0.0 6.507 -0.551 0.0 6.507 -1.0 0.0 6.596 -1.0 0.0 6.596 -0.674 0.0 6.61402 -0.65485 0.0 6.63148 -0.64011 0.0 6.649 -0.62937 0.0 6.66719 -0.62222 0.0 6.68665 -0.61824 0.0 6.708 -0.617 0.0 6.72928 -0.61963 0.0 6.74856 -0.62774 0.0 6.765 -0.64162 0.0 6.77778 -0.66159 0.0 6.78606 -0.68795 0.0 6.789 -0.721 0.0 6.789 -1.0 0.0 6.878 -1.0 0.0 6.878 -0.674 0.0 6.89451 -0.65825 0.0 6.9117 -0.64433 0.0 6.92913 -0.63275 0.0 6.9463 -0.624 0.0 6.96275 -0.61858 0.0 6.978 -0.617 0.0 7.0026 -0.62006 0.0 7.02478 -0.62911 0.0 7.04363 -0.644 0.0 7.05822 -0.66456 0.0 7.06765 -0.69061 0.0 7.071 -0.722 0.0 7.071 -1.0 0.0 7.16 -1.0 0.0 7.16 -0.718 0.0 7.15528 -0.66816 0.0 7.14159 -0.62526 0.0 7.11963 -0.59025 0.0 7.09007 -0.56407 0.0 7.05363 -0.54768 0.0 7.011 -0.542 0.0 6.98038 -0.54494 0.0 6.95233 -0.55322 0.0 6.92663 -0.566 0.0 6.903 -0.58244 0.0 6.88121 -0.60172 0.0 6.861 -0.623 0.0 6.84462 -0.5986 0.0 6.82559 -0.57844 0.0 6.80413 -0.56262 0.0 6.78041 -0.55122 0.0 6.75463 -0.54432 0.0 6.727 -0.542 0.0 6.70591 -0.54384 0.0 6.68459 -0.54941 0.0 6.663 -0.55875 0.0 6.64107 -0.57193 0.0 6.61876 -0.58899 0.0 6.596 -0.61 0.0 6.596 -0.551 0.0 6.004 -0.458 0.0 5.837 -0.621 0.0 5.837 -0.631 0.0 5.915 -0.631 0.0 5.915 -0.868 0.0 5.91908 -0.90657 0.0 5.9313 -0.94056 0.0 5.95163 -0.96887 0.0 5.98004 -0.99044 0.0 6.0165 -1.00418 0.0 6.061 -1.009 0.0 6.07692 -1.00796 0.0 6.095 -1.005 0.0 6.11425 -1.00038 0.0 6.13367 -0.99433 0.0 6.15225 -0.98713 0.0 6.169 -0.979 0.0 6.169 -0.896 0.0 6.15124 -0.90608 0.0 6.13393 -0.91433 0.0 6.117 -0.92075 0.0 6.10041 -0.92533 0.0 6.08409 -0.92808 0.0 6.068 -0.929 0.0 6.05423 -0.92764 0.0 6.03985 -0.92315 0.0 6.02625 -0.91487 0.0 6.01482 -0.90219 0.0 6.00694 -0.88444 0.0 6.004 -0.861 0.0 6.004 -0.631 0.0 6.146 -0.631 0.0 6.146 -0.551 0.0 6.004 -0.551 0.0 5.883 -0.318 0.0 5.84619 -0.31024 0.0 5.81348 -0.30859 0.0 5.7845 -0.3125 0.0 5.75885 -0.32141 0.0 5.73615 -0.33476 0.0 5.716 -0.352 0.0 5.69928 -0.37069 0.0 5.68522 -0.39148 0.0 5.674 -0.4155 0.0 5.66578 -0.44385 0.0 5.66072 -0.47765 0.0 5.659 -0.518 0.0 5.659 -0.551 0.0 5.596 -0.551 0.0 5.596 -0.631 0.0 5.659 -0.631 0.0 5.659 -1.0 0.0 5.748 -1.0 0.0 5.748 -0.631 0.0 5.829 -0.631 0.0 5.829 -0.551 0.0 5.748 -0.551 0.0 5.748 -0.508 0.0 5.75004 -0.47582 0.0 5.75663 -0.44856 0.0 5.7685 -0.42662 0.0 5.78637 -0.41044 0.0 5.81096 -0.40043 0.0 5.843 -0.397 0.0 5.85048 -0.39718 0.0 5.85715 -0.39774 0.0 5.86338 -0.39875 0.0 5.86952 -0.40026 0.0 5.87594 -0.40232 0.0 5.883 -0.405 0.0 5.546 -0.87 0.0 5.52007 -0.88581 0.0 5.49419 -0.89911 0.0 5.46825 -0.90975 0.0 5.44215 -0.91756 0.0 5.41577 -0.92236 0.0 5.389 -0.924 0.0 5.34893 -0.92018 0.0 5.31474 -0.90878 0.0 5.2865 -0.88987 0.0 5.26426 -0.86356 0.0 5.24807 -0.8299 0.0 5.238 -0.789 0.0 5.554 -0.789 0.0 5.54782 -0.71306 0.0 5.52989 -0.65119 0.0 5.50113 -0.60325 0.0 5.46244 -0.56915 0.0 5.41476 -0.54877 0.0 5.359 -0.542 0.0 5.30039 -0.54944 0.0 5.24944 -0.57089 0.0 5.2075 -0.605 0.0 5.17589 -0.65044 0.0 5.15594 -0.70589 0.0 5.149 -0.77 0.0 5.15543 -0.83076 0.0 5.17441 -0.88707 0.0 5.2055 -0.936 0.0 5.24826 -0.97459 0.0 5.30224 -0.99991 0.0 5.367 -1.009 0.0 5.4029 -1.00757 0.0 5.43519 -1.00326 0.0 5.46475 -0.996 0.0 5.49248 -0.98574 0.0 5.51927 -0.97243 0.0 5.546 -0.956 0.0 5.24 -0.73 0.0 5.24841 -0.69713 0.0 5.26159 -0.66967 0.0 5.2795 -0.64787 0.0 5.30207 -0.632 0.0 5.32926 -0.62229 0.0 5.361 -0.619 0.0 5.39044 -0.6225 0.0 5.41556 -0.63267 0.0 5.436 -0.649 0.0 5.45144 -0.671 0.0 5.46156 -0.69817 0.0 5.466 -0.73 0.0 5.043 -0.318 0.0 4.954 -0.318 0.0 4.954 -1.0 0.0 5.043 -1.0 0.0 4.451 -1.118 0.0 4.4871 -1.10365 0.0 4.51645 -1.08356 0.0 4.53913 -1.05913 0.0 4.55522 -1.03178 0.0 4.56482 -1.00293 0.0 4.568 -0.974 0.0 4.56573 -0.94633 0.0 4.55915 -0.92263 0.0 4.54863 -0.90338 0.0 4.53452 -0.88904 0.0 4.51719 -0.88009 0.0 4.497 -0.877 0.0 4.48082 -0.87893 0.0 4.46659 -0.88444 0.0 4.45475 -0.89312 0.0 4.44574 -0.90456 0.0 4.44001 -0.91832 0.0 4.438 -0.934 0.0 4.43962 -0.94954 0.0 4.44426 -0.96296 0.0 4.45163 -0.974 0.0 4.46141 -0.98237 0.0 4.4733 -0.9878 0.0 4.487 -0.99 0.0 4.48975 -1.00905 0.0 4.489 -1.02937 0.0 4.48475 -1.04975 0.0 4.477 -1.06896 0.0 4.46575 -1.08579 0.0 4.451 -1.099 0.0 3.68 -0.551 0.0 3.68 -1.0 0.0 3.769 -1.0 0.0 3.769 -0.674 0.0 3.78702 -0.65485 0.0 3.80448 -0.64011 0.0 3.822 -0.62937 0.0 3.84019 -0.62222 0.0 3.85965 -0.61824 0.0 3.881 -0.617 0.0 3.90228 -0.61963 0.0 3.92156 -0.62774 0.0 3.938 -0.64162 0.0 3.95078 -0.66159 0.0 3.95906 -0.68795 0.0 3.962 -0.721 0.0 3.962 -1.0 0.0 4.051 -1.0 0.0 4.051 -0.674 0.0 4.06751 -0.65825 0.0 4.0847 -0.64433 0.0 4.10213 -0.63275 0.0 4.1193 -0.624 0.0 4.13575 -0.61858 0.0 4.151 -0.617 0.0 4.1756 -0.62006 0.0 4.19778 -0.62911 0.0 4.21663 -0.644 0.0 4.23122 -0.66456 0.0 4.24065 -0.69061 0.0 4.244 -0.722 0.0 4.244 -1.0 0.0 4.333 -1.0 0.0 4.333 -0.718 0.0 4.32828 -0.66816 0.0 4.31459 -0.62526 0.0 4.29263 -0.59025 0.0 4.26307 -0.56407 0.0 4.22663 -0.54768 0.0 4.184 -0.542 0.0 4.15338 -0.54494 0.0 4.12533 -0.55322 0.0 4.09963 -0.566 0.0 4.076 -0.58244 0.0 4.05421 -0.60172 0.0 4.034 -0.623 0.0 4.01762 -0.5986 0.0 3.99859 -0.57844 0.0 3.97713 -0.56262 0.0 3.95341 -0.55122 0.0 3.92763 -0.54432 0.0 3.9 -0.542 0.0 3.87891 -0.54384 0.0 3.85759 -0.54941 0.0 3.836 -0.55875 0.0 3.81407 -0.57193 0.0 3.79176 -0.58899 0.0 3.769 -0.61 0.0 3.769 -0.551 0.0 3.556 -0.551 0.0 3.467 -0.551 0.0 3.467 -1.0 0.0 3.556 -1.0 0.0 3.565 -0.415 0.0 3.56309 -0.401 0.0 3.5577 -0.38837 0.0 3.54938 -0.37762 0.0 3.53863 -0.3693 0.0 3.526 -0.36391 0.0 3.512 -0.362 0.0 3.498 -0.36391 0.0 3.48537 -0.3693 0.0 3.47463 -0.37762 0.0 3.4663 -0.38837 0.0 3.46091 -0.401 0.0 3.459 -0.415 0.0 3.46091 -0.429 0.0 3.4663 -0.44163 0.0 3.47463 -0.45237 0.0 3.48537 -0.4607 0.0 3.498 -0.46609 0.0 3.512 -0.468 0.0 3.526 -0.46609 0.0 3.53863 -0.4607 0.0 3.54938 -0.45237 0.0 3.5577 -0.44163 0.0 3.56309 -0.429 0.0 3.386 -0.92 0.0 3.3762 -0.92699 0.0 3.36693 -0.93289 0.0 3.35838 -0.93762 0.0 3.35074 -0.94111 0.0 3.34422 -0.94326 0.0 3.339 -0.944 0.0 3.33392 -0.94348 0.0 3.3297 -0.94181 0.0 3.32638 -0.93888 0.0 3.32396 -0.93452 0.0 3.3225 -0.92861 0.0 3.322 -0.921 0.0 3.322 -0.69 0.0 3.31625 -0.64362 0.0 3.29996 -0.6063 0.0 3.27463 -0.57775 0.0 3.2417 -0.5577 0.0 3.20267 -0.54588 0.0 3.159 -0.542 0.0 3.12782 -0.54367 0.0 3.09926 -0.5487 0.0 3.07325 -0.55712 0.0 3.04974 -0.56896 0.0 3.02868 -0.58425 0.0 3.01 -0.603 0.0 3.01 -0.7 0.0 3.03205 -0.67681 0.0 3.05504 -0.65815 0.0 3.07875 -0.64387 0.0 3.10296 -0.63385 0.0 3.12745 -0.62794 0.0 3.152 -0.626 0.0 3.17675 -0.62796 0.0 3.197 -0.63404 0.0 3.21275 -0.6445 0.0 3.224 -0.65963 0.0 3.23075 -0.6797 0.0 3.233 -0.705 0.0 3.233 -0.729 0.0 3.154 -0.757 0.0 3.11767 -0.77037 0.0 3.08233 -0.78559 0.0 3.0505 -0.80437 0.0 3.02467 -0.82841 0.0 3.00733 -0.85938 0.0 3.001 -0.899 0.0 3.00457 -0.92729 0.0 3.01485 -0.9533 0.0 3.03125 -0.97575 0.0 3.05315 -0.99337 0.0 3.07994 -1.00488 0.0 3.111 -1.009 0.0 3.13149 -1.00775 0.0 3.15193 -1.00396 0.0 3.17225 -0.99762 0.0 3.19241 -0.9887 0.0 3.21234 -0.97717 0.0 3.232 -0.963 0.0 3.23711 -0.97752 0.0 3.24452 -0.98915 0.0 3.25438 -0.998 0.0 3.26681 -1.00419 0.0 3.28198 -1.00781 0.0 3.3 -1.009 0.0 3.31325 -1.00828 0.0 3.32563 -1.00593 0.0 3.33813 -1.00162 0.0 3.3517 -0.99507 0.0 3.36734 -0.98597 0.0 3.386 -0.974 0.0 3.233 -0.909 0.0 3.22083 -0.91973 0.0 3.20833 -0.92881 0.0 3.1955 -0.93613 0.0 3.18233 -0.94152 0.0 3.16883 -0.94486 0.0 3.155 -0.946 0.0 3.13741 -0.9439 0.0 3.12196 -0.93789 0.0 3.10913 -0.92838 0.0 3.09937 -0.91578 0.0 3.09317 -0.90051 0.0 3.091 -0.883 0.0 3.09624 -0.85862 0.0 3.11093 -0.838 0.0 3.1335 -0.82038 0.0 3.16241 -0.805 0.0 3.19609 -0.79112 0.0 3.233 -0.778 0.0 2.656 -0.87 0.0 2.63006 -0.88581 0.0 2.60419 -0.89911 0.0 2.57825 -0.90975 0.0 2.55215 -0.91756 0.0 2.52577 -0.92236 0.0 2.499 -0.924 0.0 2.45893 -0.92018 0.0 2.42474 -0.90878 0.0 2.3965 -0.88987 0.0 2.37426 -0.86356 0.0 2.35807 -0.8299 0.0 2.348 -0.789 0.0 2.664 -0.789 0.0 2.65782 -0.71306 0.0 2.63989 -0.65119 0.0 2.61113 -0.60325 0.0 2.57244 -0.56915 0.0 2.52476 -0.54877 0.0 2.469 -0.542 0.0 2.41039 -0.54944 0.0 2.35944 -0.57089 0.0 2.3175 -0.605 0.0 2.28589 -0.65044 0.0 2.26594 -0.70589 0.0 2.259 -0.77 0.0 2.26543 -0.83076 0.0 2.28441 -0.88707 0.0 2.3155 -0.936 0.0 2.35826 -0.97459 0.0 2.41224 -0.99991 0.0 2.477 -1.009 0.0 2.5129 -1.00757 0.0 2.54519 -1.00326 0.0 2.57475 -0.996 0.0 2.60248 -0.98574 0.0 2.62927 -0.97243 0.0 2.656 -0.956 0.0 2.35 -0.73 0.0 2.35841 -0.69713 0.0 2.37159 -0.66967 0.0 2.3895 -0.64787 0.0 2.41207 -0.632 0.0 2.43926 -0.62229 0.0 2.471 -0.619 0.0 2.50044 -0.6225 0.0 2.52556 -0.63267 0.0 2.546 -0.649 0.0 2.56144 -0.671 0.0 2.57156 -0.69817 0.0 2.576 -0.73 0.0 2.157 -0.579 0.0 2.13382 -0.56758 0.0 2.11122 -0.5583 0.0 2.08913 -0.55112 0.0 2.06744 -0.54604 0.0 2.0461 -0.543 0.0 2.025 -0.542 0.0 1.98279 -0.54576 0.0 1.94663 -0.55674 0.0 1.91725 -0.5745 0.0 1.89537 -0.59859 0.0 1.88171 -0.62857 0.0 1.877 -0.664 0.0 1.89256 -0.71771 0.0 1.93144 -0.76 0.0 1.982 -0.79412 0.0 2.03256 -0.82333 0.0 2.07144 -0.85088 0.0 2.087 -0.88 0.0 2.08461 -0.89475 0.0 2.07789 -0.907 0.0 2.0675 -0.91675 0.0 2.05411 -0.924 0.0 2.03839 -0.92875 0.0 2.021 -0.931 0.0 2.00164 -0.92941 0.0 1.97978 -0.92459 0.0 1.95575 -0.9165 0.0 1.92989 -0.90507 0.0 1.90253 -0.89026 0.0 1.874 -0.872 0.0 1.874 -0.968 0.0 1.90188 -0.98145 0.0 1.928 -0.99196 0.0 1.95313 -0.99975 0.0 1.978 -1.00504 0.0 2.00337 -1.00805 0.0 2.03 -1.009 0.0 2.07048 -1.00471 0.0 2.10615 -0.99233 0.0 2.13587 -0.97262 0.0 2.15852 -0.94633 0.0 2.17294 -0.91421 0.0 2.178 -0.877 0.0 2.17566 -0.8551 0.0 2.16826 -0.83478 0.0 2.15525 -0.81512 0.0 2.13607 -0.79522 0.0 2.11018 -0.77415 0.0 2.077 -0.751 0.0 2.0415 -0.72975 0.0 2.01363 -0.71167 0.0 1.99288 -0.69625 0.0 1.9787 -0.683 0.0 1.97059 -0.67142 0.0 1.968 -0.661 0.0 1.96987 -0.64963 0.0 1.9753 -0.6397 0.0 1.984 -0.6315 0.0 1.9957 -0.6253 0.0 2.01013 -0.62137 0.0 2.027 -0.62 0.0 2.04462 -0.62119 0.0 2.06426 -0.62485 0.0 2.08562 -0.63113 0.0 2.10841 -0.64015 0.0 2.1323 -0.65206 0.0 2.157 -0.667 0.0 1.77 -1.0 0.0 1.77 -0.551 0.0 1.681 -0.551 0.0 1.681 -0.872 0.0 1.66578 -0.8909 0.0 1.64926 -0.90656 0.0 1.63163 -0.91887 0.0 1.61307 -0.92778 0.0 1.5938 -0.93318 0.0 1.574 -0.935 0.0 1.546 -0.93204 0.0 1.52304 -0.92333 0.0 1.50513 -0.90912 0.0 1.4923 -0.88967 0.0 1.48458 -0.86521 0.0 1.482 -0.836 0.0 1.482 -0.551 0.0 1.393 -0.551 0.0 1.393 -0.83 0.0 1.39816 -0.88284 0.0 1.41296 -0.92707 0.0 1.43638 -0.96225 0.0 1.46737 -0.98793 0.0 1.50492 -1.00366 0.0 1.548 -1.009 0.0 1.57056 -1.00689 0.0 1.59381 -1.00078 0.0 1.61713 -0.991 0.0 1.63985 -0.97789 0.0 1.66136 -0.96178 0.0 1.681 -0.943 0.0 1.681 -1.0 0.0 1.054 -0.542 0.0 0.98992 -0.55 0.0 0.933 -0.5727 0.0 0.88525 -0.60812 0.0 0.84867 -0.6543 0.0 0.82525 -0.70925 0.0 0.817 -0.771 0.0 0.82497 -0.83655 0.0 0.84778 -0.89404 0.0 0.88375 -0.94175 0.0 0.93122 -0.97796 0.0 0.98853 -1.00095 0.0 1.054 -1.009 0.0 1.122 -1.00123 0.0 1.181 -0.97885 0.0 1.2295 -0.94325 0.0 1.266 -0.89581 0.0 1.289 -0.83794 0.0 1.297 -0.771 0.0 1.28879 -0.70786 0.0 1.26533 -0.65252 0.0 1.22838 -0.60662 0.0 1.17967 -0.57181 0.0 1.12096 -0.54973 0.0 1.053 -0.622 0.0 1.09524 -0.62707 0.0 1.13222 -0.64156 0.0 1.16288 -0.66438 0.0 1.18611 -0.69444 0.0 1.20085 -0.73068 0.0 1.206 -0.772 0.0 1.20119 -0.81731 0.0 1.18722 -0.85581 0.0 1.16475 -0.88688 0.0 1.13444 -0.90985 0.0 1.09697 -0.92411 0.0 1.053 -0.929 0.0 1.0124 -0.92389 0.0 0.97719 -0.90915 0.0 0.94825 -0.88563 0.0 0.92648 -0.85419 0.0 0.91277 -0.81569 0.0 0.908 -0.771 0.0 0.91291 -0.7301 0.0 0.92693 -0.69415 0.0 0.949 -0.66425 0.0 0.97807 -0.64152 0.0 1.01309 -0.62706 0.0 0.709 -0.318 0.0 0.618 -0.318 0.0 0.391 -0.598 0.0 0.165 -0.318 0.0 0.073 -0.318 0.0 0.073 -1.0 0.0 0.171 -1.0 0.0 0.171 -0.469 0.0 0.173 -0.469 0.0 0.383 -0.733 0.0 0.399 -0.733 0.0 0.609 -0.469 0.0 0.611 -0.469 0.0 0.611 -1.0 0.0 0.709 -1.0 0.0 7.379 0.542 0.0 7.212 0.379 0.0 7.212 0.369 0.0 7.29 0.369 0.0 7.29 0.132 0.0 7.29408 0.09343 0.0 7.3063 0.05944 0.0 7.32663 0.03112 0.0 7.35504 0.00956 0.0 7.39151 -0.00418 0.0 7.436 -0.009 0.0 7.45192 -0.00796 0.0 7.47 -0.005 0.0 7.48925 -0.00038 0.0 7.50867 0.00567 0.0 7.52725 0.01288 0.0 7.544 0.021 0.0 7.544 0.104 0.0 7.52624 0.09392 0.0 7.50893 0.08567 0.0 7.492 0.07925 0.0 7.47541 0.07467 0.0 7.45909 0.07192 0.0 7.443 0.071 0.0 7.42923 0.07236 0.0 7.41485 0.07685 0.0 7.40125 0.08513 0.0 7.38982 0.09781 0.0 7.38194 0.11556 0.0 7.379 0.139 0.0 7.379 0.369 0.0 7.521 0.369 0.0 7.521 0.449 0.0 7.379 0.449 0.0 7.151 0.421 0.0 7.12782 0.43242 0.0 7.10522 0.4417 0.0 7.08313 0.44888 0.0 7.06145 0.45396 0.0 7.0401 0.457 0.0 7.019 0.458 0.0 6.97679 0.45424 0.0 6.94063 0.44326 0.0 6.91125 0.4255 0.0 6.88937 0.40141 0.0 6.87571 0.37143 0.0 6.871 0.336 0.0 6.88656 0.28229 0.0 6.92545 0.24 0.0 6.976 0.20588 0.0 7.02656 0.17667 0.0 7.06545 0.14913 0.0 7.081 0.12 0.0 7.07861 0.10525 0.0 7.07189 0.093 0.0 7.0615 0.08325 0.0 7.04811 0.076 0.0 7.03239 0.07125 0.0 7.015 0.069 0.0 6.99564 0.07059 0.0 6.97378 0.07541 0.0 6.94975 0.0835 0.0 6.92389 0.09493 0.0 6.89653 0.10974 0.0 6.868 0.128 0.0 6.868 0.032 0.0 6.89588 0.01855 0.0 6.922 0.00804 0.0 6.94713 0.00025 0.0 6.972 -0.00504 0.0 6.99738 -0.00805 0.0 7.024 -0.009 0.0 7.06448 -0.00471 0.0 7.10015 0.00767 0.0 7.12988 0.02737 0.0 7.15252 0.05367 0.0 7.16694 0.08579 0.0 7.172 0.123 0.0 7.16966 0.1449 0.0 7.16226 0.16522 0.0 7.14925 0.18488 0.0 7.13007 0.20478 0.0 7.10418 0.22585 0.0 7.071 0.249 0.0 7.0355 0.27025 0.0 7.00763 0.28833 0.0 6.98688 0.30375 0.0 6.9727 0.317 0.0 6.96459 0.32858 0.0 6.962 0.339 0.0 6.96387 0.35037 0.0 6.9693 0.3603 0.0 6.978 0.3685 0.0 6.9897 0.3747 0.0 7.00413 0.37863 0.0 7.021 0.38 0.0 7.03862 0.37881 0.0 7.05826 0.37515 0.0 7.07963 0.36887 0.0 7.10241 0.35985 0.0 7.1263 0.34794 0.0 7.151 0.333 0.0 6.786 0.13 0.0 6.76007 0.11419 0.0 6.73419 0.10089 0.0 6.70825 0.09025 0.0 6.68215 0.08244 0.0 6.65577 0.07764 0.0 6.629 0.076 0.0 6.58893 0.07982 0.0 6.55474 0.09122 0.0 6.5265 0.11013 0.0 6.50426 0.13644 0.0 6.48807 0.1701 0.0 6.478 0.211 0.0 6.794 0.211 0.0 6.78782 0.28694 0.0 6.76989 0.34881 0.0 6.74113 0.39675 0.0 6.70245 0.43085 0.0 6.65476 0.45123 0.0 6.599 0.458 0.0 6.54039 0.45056 0.0 6.48945 0.42911 0.0 6.4475 0.395 0.0 6.41589 0.34956 0.0 6.39595 0.29411 0.0 6.389 0.23 0.0 6.39543 0.16924 0.0 6.41441 0.11293 0.0 6.4455 0.064 0.0 6.48826 0.02541 0.0 6.54224 9e-05 0.0 6.607 -0.009 0.0 6.6429 -0.00757 0.0 6.67519 -0.00326 0.0 6.70475 0.004 0.0 6.73248 0.01426 0.0 6.75927 0.02757 0.0 6.786 0.044 0.0 6.48 0.27 0.0 6.48841 0.30288 0.0 6.50159 0.33033 0.0 6.5195 0.35213 0.0 6.54207 0.368 0.0 6.56926 0.37771 0.0 6.601 0.381 0.0 6.63045 0.3775 0.0 6.65556 0.36733 0.0 6.676 0.351 0.0 6.69144 0.329 0.0 6.70156 0.30183 0.0 6.706 0.27 0.0 6.331 0.682 0.0 5.761 0.682 0.0 5.761 0.594 0.0 5.997 0.594 0.0 5.997 0.0 0.0 6.095 0.0 0.0 6.095 0.594 0.0 6.331 0.594 0.0 5.405 0.421 0.0 5.38182 0.43242 0.0 5.35922 0.4417 0.0 5.33713 0.44888 0.0 5.31544 0.45396 0.0 5.2941 0.457 0.0 5.273 0.458 0.0 5.23079 0.45424 0.0 5.19463 0.44326 0.0 5.16525 0.4255 0.0 5.14337 0.40141 0.0 5.12971 0.37143 0.0 5.125 0.336 0.0 5.14056 0.28229 0.0 5.17944 0.24 0.0 5.23 0.20588 0.0 5.28056 0.17667 0.0 5.31945 0.14913 0.0 5.335 0.12 0.0 5.33261 0.10525 0.0 5.32589 0.093 0.0 5.3155 0.08325 0.0 5.30211 0.076 0.0 5.28639 0.07125 0.0 5.269 0.069 0.0 5.24964 0.07059 0.0 5.22778 0.07541 0.0 5.20375 0.0835 0.0 5.17789 0.09493 0.0 5.15053 0.10974 0.0 5.122 0.128 0.0 5.122 0.032 0.0 5.14988 0.01855 0.0 5.176 0.00804 0.0 5.20113 0.00025 0.0 5.226 -0.00504 0.0 5.25138 -0.00805 0.0 5.278 -0.009 0.0 5.31848 -0.00471 0.0 5.35415 0.00767 0.0 5.38388 0.02737 0.0 5.40652 0.05367 0.0 5.42094 0.08579 0.0 5.426 0.123 0.0 5.42366 0.1449 0.0 5.41626 0.16522 0.0 5.40325 0.18488 0.0 5.38407 0.20478 0.0 5.35818 0.22585 0.0 5.325 0.249 0.0 5.2895 0.27025 0.0 5.26163 0.28833 0.0 5.24088 0.30375 0.0 5.2267 0.317 0.0 5.21859 0.32858 0.0 5.216 0.339 0.0 5.21787 0.35037 0.0 5.2233 0.3603 0.0 5.232 0.3685 0.0 5.2437 0.3747 0.0 5.25813 0.37863 0.0 5.275 0.38 0.0 5.29262 0.37881 0.0 5.31226 0.37515 0.0 5.33363 0.36887 0.0 5.35641 0.35985 0.0 5.3803 0.34794 0.0 5.405 0.333 0.0 5.036 0.427 0.0 5.01505 0.43589 0.0 4.99474 0.44348 0.0 4.97437 0.44963 0.0 4.95326 0.45419 0.0 4.9307 0.45702 0.0 4.906 0.458 0.0 4.84233 0.45035 0.0 4.788 0.42815 0.0 4.744 0.3925 0.0 4.71133 0.34452 0.0 4.691 0.28531 0.0 4.684 0.216 0.0 4.69158 0.1535 0.0 4.71333 0.099 0.0 4.74775 0.054 0.0 4.79333 0.02 0.0 4.84858 -0.0015 0.0 4.912 -0.009 0.0 4.93616 -0.00805 0.0 4.96096 -0.00537 0.0 4.98537 -0.00125 0.0 5.00837 0.00404 0.0 5.02892 0.01021 0.0 5.046 0.017 0.0 5.046 0.105 0.0 5.0242 0.09583 0.0 5.00359 0.08833 0.0 4.98387 0.0825 0.0 4.96474 0.07833 0.0 4.94588 0.07583 0.0 4.927 0.075 0.0 4.8838 0.07958 0.0 4.8467 0.09296 0.0 4.8165 0.11463 0.0 4.79396 0.14404 0.0 4.77987 0.18067 0.0 4.775 0.224 0.0 4.77952 0.26686 0.0 4.79252 0.30385 0.0 4.81313 0.33413 0.0 4.84048 0.35681 0.0 4.87373 0.37106 0.0 4.912 0.376 0.0 4.93119 0.3751 0.0 4.95015 0.37215 0.0 4.9695 0.36675 0.0 4.98985 0.35852 0.0 5.01182 0.34706 0.0 5.036 0.332 0.0 4.578 0.449 0.0 4.489 0.449 0.0 4.489 0.0 0.0 4.578 0.0 0.0 4.587 0.585 0.0 4.58509 0.599 0.0 4.5797 0.61163 0.0 4.57137 0.62238 0.0 4.56063 0.6307 0.0 4.548 0.63609 0.0 4.534 0.638 0.0 4.52 0.63609 0.0 4.50737 0.6307 0.0 4.49662 0.62238 0.0 4.4883 0.61163 0.0 4.48291 0.599 0.0 4.481 0.585 0.0 4.48291 0.571 0.0 4.4883 0.55837 0.0 4.49663 0.54763 0.0 4.50737 0.5393 0.0 4.52001 0.53391 0.0 4.534 0.532 0.0 4.548 0.53391 0.0 4.56063 0.5393 0.0 4.57138 0.54763 0.0 4.5797 0.55837 0.0 4.58509 0.571 0.0 4.363 0.421 0.0 4.33982 0.43242 0.0 4.31722 0.4417 0.0 4.29513 0.44888 0.0 4.27344 0.45396 0.0 4.2521 0.457 0.0 4.231 0.458 0.0 4.18879 0.45424 0.0 4.15263 0.44326 0.0 4.12325 0.4255 0.0 4.10137 0.40141 0.0 4.08771 0.37143 0.0 4.083 0.336 0.0 4.09856 0.28229 0.0 4.13744 0.24 0.0 4.188 0.20588 0.0 4.23856 0.17667 0.0 4.27744 0.14913 0.0 4.293 0.12 0.0 4.29061 0.10525 0.0 4.28389 0.093 0.0 4.2735 0.08325 0.0 4.26011 0.076 0.0 4.24439 0.07125 0.0 4.227 0.069 0.0 4.20764 0.07059 0.0 4.18578 0.07541 0.0 4.16175 0.0835 0.0 4.13589 0.09493 0.0 4.10853 0.10974 0.0 4.08 0.128 0.0 4.08 0.032 0.0 4.10787 0.01855 0.0 4.134 0.00804 0.0 4.15912 0.00025 0.0 4.184 -0.00504 0.0 4.20937 -0.00805 0.0 4.236 -0.009 0.0 4.27648 -0.00471 0.0 4.31215 0.00767 0.0 4.34188 0.02737 0.0 4.36452 0.05367 0.0 4.37894 0.08579 0.0 4.384 0.123 0.0 4.38166 0.1449 0.0 4.37426 0.16522 0.0 4.36125 0.18488 0.0 4.34207 0.20478 0.0 4.31618 0.22585 0.0 4.283 0.249 0.0 4.2475 0.27025 0.0 4.21963 0.28833 0.0 4.19887 0.30375 0.0 4.1847 0.317 0.0 4.17659 0.32858 0.0 4.174 0.339 0.0 4.17587 0.35037 0.0 4.1813 0.3603 0.0 4.19 0.3685 0.0 4.2017 0.3747 0.0 4.21613 0.37863 0.0 4.233 0.38 0.0 4.25062 0.37881 0.0 4.27026 0.37515 0.0 4.29163 0.36887 0.0 4.31441 0.35985 0.0 4.3383 0.34794 0.0 4.363 0.333 0.0 4.039 0.449 0.0 3.939 0.449 0.0 3.823 0.196 0.0 3.702 0.449 0.0 3.601 0.449 0.0 3.775 0.096 0.0 3.622 -0.23 0.0 3.721 -0.23 0.0 3.251 0.682 0.0 3.162 0.682 0.0 3.162 0.0 0.0 3.251 0.0 0.0 3.251 0.322 0.0 3.27117 0.34313 0.0 3.29004 0.35974 0.0 3.30813 0.37213 0.0 3.32596 0.38059 0.0 3.34408 0.38545 0.0 3.363 0.387 0.0 3.38827 0.38351 0.0 3.40982 0.37341 0.0 3.42725 0.35725 0.0 3.44019 0.33559 0.0 3.44823 0.30899 0.0 3.451 0.278 0.0 3.451 0.0 0.0 3.54 0.0 0.0 3.54 0.275 0.0 3.53478 0.33126 0.0 3.51989 0.37711 0.0 3.4965 0.41263 0.0 3.46578 0.43789 0.0 3.42889 0.45299 0.0 3.387 0.458 0.0 3.36207 0.45595 0.0 3.33759 0.44993 0.0 3.314 0.44013 0.0 3.29174 0.42674 0.0 3.27126 0.40997 0.0 3.253 0.39 0.0 3.251 0.39 0.0 2.661 0.682 0.0 2.661 0.0 0.0 2.759 0.0 0.0 2.759 0.295 0.0 2.861 0.295 0.0 2.9329 0.30172 0.0 2.99085 0.32074 0.0 3.03525 0.35038 0.0 3.06648 0.38893 0.0 3.08493 0.4347 0.0 3.091 0.486 0.0 3.08527 0.53802 0.0 3.06785 0.58481 0.0 3.03838 0.6245 0.0 2.99648 0.65519 0.0 2.94181 0.67498 0.0 2.874 0.682 0.0 2.759 0.594 0.0 2.874 0.594 0.0 2.9135 0.58977 0.0 2.94363 0.57815 0.0 2.96538 0.56075 0.0 2.9797 0.53919 0.0 2.98759 0.51506 0.0 2.99 0.49 0.0 2.98618 0.45846 0.0 2.97511 0.43204 0.0 2.95737 0.411 0.0 2.93356 0.39563 0.0 2.90424 0.3862 0.0 2.87 0.383 0.0 2.759 0.383 0.0 2.147 0.542 0.0 1.98 0.379 0.0 1.98 0.369 0.0 2.058 0.369 0.0 2.058 0.132 0.0 2.06208 0.09343 0.0 2.0743 0.05944 0.0 2.09462 0.03112 0.0 2.12304 0.00956 0.0 2.1595 -0.00418 0.0 2.204 -0.009 0.0 2.21992 -0.00796 0.0 2.238 -0.005 0.0 2.25725 -0.00038 0.0 2.27667 0.00567 0.0 2.29525 0.01288 0.0 2.312 0.021 0.0 2.312 0.104 0.0 2.29424 0.09392 0.0 2.27693 0.08567 0.0 2.26 0.07925 0.0 2.24341 0.07467 0.0 2.22709 0.07192 0.0 2.211 0.071 0.0 2.19723 0.07236 0.0 2.18285 0.07685 0.0 2.16925 0.08513 0.0 2.15781 0.09781 0.0 2.14994 0.11556 0.0 2.147 0.139 0.0 2.147 0.369 0.0 2.289 0.369 0.0 2.289 0.449 0.0 2.147 0.449 0.0 1.939 0.13 0.0 1.91306 0.11419 0.0 1.88719 0.10089 0.0 1.86125 0.09025 0.0 1.83515 0.08244 0.0 1.80877 0.07764 0.0 1.782 0.076 0.0 1.74193 0.07982 0.0 1.70774 0.09122 0.0 1.6795 0.11013 0.0 1.65726 0.13644 0.0 1.64107 0.1701 0.0 1.631 0.211 0.0 1.947 0.211 0.0 1.94082 0.28694 0.0 1.92289 0.34881 0.0 1.89412 0.39675 0.0 1.85544 0.43085 0.0 1.80776 0.45123 0.0 1.752 0.458 0.0 1.69339 0.45056 0.0 1.64244 0.42911 0.0 1.6005 0.395 0.0 1.56889 0.34956 0.0 1.54894 0.29411 0.0 1.542 0.23 0.0 1.54843 0.16924 0.0 1.56741 0.11293 0.0 1.5985 0.064 0.0 1.64126 0.02541 0.0 1.69524 9e-05 0.0 1.76 -0.009 0.0 1.7959 -0.00757 0.0 1.82819 -0.00326 0.0 1.85775 0.004 0.0 1.88548 0.01426 0.0 1.91227 0.02757 0.0 1.939 0.044 0.0 1.633 0.27 0.0 1.64141 0.30288 0.0 1.65459 0.33033 0.0 1.6725 0.35213 0.0 1.69507 0.368 0.0 1.72226 0.37771 0.0 1.754 0.381 0.0 1.78344 0.3775 0.0 1.80856 0.36733 0.0 1.829 0.351 0.0 1.84444 0.329 0.0 1.85456 0.30183 0.0 1.859 0.27 0.0 1.436 0.682 0.0 1.347 0.682 0.0 1.347 0.0 0.0 1.436 0.0 0.0 1.217 0.682 0.0 1.128 0.682 0.0 1.128 0.0 0.0 1.217 0.0 0.0 1.0 0.0 0.0 1.0 0.449 0.0 0.911 0.449 0.0 0.911 0.128 0.0 0.89578 0.1091 0.0 0.87926 0.09344 0.0 0.86163 0.08113 0.0 0.84307 0.07222 0.0 0.8238 0.06682 0.0 0.804 0.065 0.0 0.776 0.06796 0.0 0.75304 0.07667 0.0 0.73513 0.09088 0.0 0.7223 0.11033 0.0 0.71458 0.13479 0.0 0.712 0.164 0.0 0.712 0.449 0.0 0.623 0.449 0.0 0.623 0.17 0.0 0.62816 0.11716 0.0 0.64296 0.07293 0.0 0.66638 0.03775 0.0 0.69737 0.01207 0.0 0.73492 -0.00366 0.0 0.778 -0.009 0.0 0.80056 -0.00689 0.0 0.82381 -0.00078 0.0 0.84712 0.009 0.0 0.86985 0.02211 0.0 0.89136 0.03822 0.0 0.911 0.057 0.0 0.911 0.0 0.0 0.075 0.0 0.0 0.309 0.0 0.0 0.38571 0.00765 0.0 0.44567 0.02852 0.0 0.49013 0.0595 0.0 0.52033 0.09748 0.0 0.53754 0.13935 0.0 0.543 0.182 0.0 0.53794 0.22581 0.0 0.52315 0.26481 0.0 0.49925 0.29838 0.0 0.46685 0.32585 0.0 0.42656 0.34661 0.0 0.379 0.36 0.0 0.379 0.362 0.0 0.41136 0.37795 0.0 0.43752 0.39696 0.0 0.45763 0.41925 0.0 0.47181 0.44504 0.0 0.48023 0.47455 0.0 0.483 0.508 0.0 0.47765 0.55075 0.0 0.46122 0.59133 0.0 0.43313 0.62725 0.0 0.39278 0.656 0.0 0.3396 0.67508 0.0 0.273 0.682 0.0 0.075 0.682 0.0 0.173 0.594 0.0 0.263 0.594 0.0 0.30306 0.5905 0.0 0.33385 0.5807 0.0 0.35625 0.56563 0.0 0.37115 0.5463 0.0 0.37944 0.52375 0.0 0.382 0.499 0.0 0.37807 0.46558 0.0 0.36622 0.4383 0.0 0.34638 0.41713 0.0 0.31844 0.40204 0.0 0.28235 0.393 0.0 0.238 0.39 0.0 0.173 0.39 0.0 0.173 0.302 0.0 0.291 0.302 0.0 0.33795 0.29845 0.0 0.37593 0.2883 0.0 0.40513 0.27225 0.0 0.42574 0.25104 0.0 0.43797 0.22538 0.0 0.442 0.196 0.0 0.43917 0.17029 0.0 0.4297 0.14533 0.0 0.41212 0.12288 0.0 0.38496 0.10467 0.0 0.34675 0.09246 0.0 0.296 0.088 0.0 0.173 0.088 0.0 + + + + + + + + + + 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

      20 0 19 1 18 2 20 3 18 4 17 5 21 6 20 7 17 8 21 9 17 10 16 11 22 12 21 13 16 14 22 15 16 16 44 17 44 18 16 19 45 20 45 21 16 22 15 23 23 24 22 25 43 26 43 27 22 28 44 29 23 30 43 31 42 32 46 33 45 34 15 35 23 36 42 37 41 38 47 39 46 40 15 41 23 42 41 43 40 44 48 45 47 46 15 47 24 48 23 49 40 50 48 51 15 52 14 53 24 54 40 55 39 56 49 57 48 58 14 59 24 60 39 61 38 62 50 63 49 64 14 65 25 66 24 67 38 68 50 69 14 70 13 71 25 72 38 73 50 74 25 75 50 76 13 77 26 78 25 79 12 80 12 81 25 82 13 83 26 84 12 85 11 86 26 87 11 88 10 89 27 90 26 91 10 92 27 93 10 94 9 95 1 96 0 97 37 98 2 99 1 100 37 101 28 102 27 103 9 104 28 105 9 106 8 107 3 108 2 109 37 110 28 111 8 112 7 113 4 114 3 115 37 116 5 117 4 118 37 119 28 120 7 121 6 122 6 123 5 124 37 125 28 126 6 127 37 128 29 129 28 130 37 131 29 132 37 133 36 134 29 135 36 136 35 137 30 138 29 139 35 140 30 141 35 142 34 143 30 144 34 145 33 146 31 147 30 148 33 149 31 150 33 151 32 152 52 153 51 154 84 155 52 156 84 157 83 158 52 159 83 160 82 161 53 162 52 163 82 164 54 165 53 166 82 167 55 168 54 169 81 170 81 171 54 172 82 173 55 174 81 175 80 176 55 177 80 178 79 179 56 180 55 181 79 182 56 183 79 184 78 185 69 186 68 187 67 188 56 189 78 190 77 191 70 192 69 193 67 194 57 195 56 196 77 197 71 198 70 199 67 200 57 201 77 202 76 203 72 204 71 205 67 206 57 207 76 208 75 209 73 210 72 211 67 212 57 213 75 214 74 215 74 216 73 217 67 218 57 219 74 220 67 221 58 222 57 223 67 224 59 225 58 226 67 227 59 228 67 229 66 230 59 231 66 232 65 233 60 234 59 235 65 236 60 237 65 238 64 239 60 240 64 241 63 242 61 243 60 244 63 245 61 246 63 247 62 248 105 249 104 250 103 251 106 252 105 253 103 254 106 255 103 256 102 257 107 258 106 259 102 260 108 261 107 262 102 263 108 264 102 265 101 266 109 267 108 268 101 269 109 270 101 271 100 272 110 273 109 274 100 275 111 276 110 277 112 278 112 279 110 280 113 281 113 282 110 283 114 284 114 285 110 286 115 287 115 288 110 289 116 290 116 291 110 292 117 293 117 294 110 295 100 296 117 297 100 298 118 299 118 300 100 301 99 302 119 303 118 304 99 305 120 306 119 307 99 308 120 309 99 310 98 311 121 312 120 313 98 314 122 315 121 316 98 317 123 318 122 319 98 320 123 321 98 322 97 323 124 324 123 325 97 326 125 327 124 328 174 329 174 330 124 331 97 332 126 333 125 334 174 335 127 336 126 337 174 338 127 339 174 340 173 341 156 342 174 343 97 344 128 345 127 346 173 347 128 348 173 349 172 350 129 351 128 352 172 353 129 354 172 355 171 356 129 357 171 358 170 359 130 360 129 361 170 362 130 363 170 364 169 365 130 366 169 367 168 368 131 369 130 370 168 371 131 372 168 373 167 374 132 375 131 376 167 377 132 378 167 379 166 380 157 381 156 382 97 383 132 384 166 385 165 386 158 387 157 388 97 389 86 390 85 391 155 392 158 393 97 394 96 395 87 396 86 397 155 398 133 399 132 400 165 401 133 402 165 403 164 404 158 405 96 406 95 407 159 408 158 409 95 410 88 411 87 412 155 413 159 414 95 415 94 416 160 417 159 418 94 419 89 420 88 421 155 422 133 423 164 424 163 425 160 426 94 427 93 428 90 429 89 430 155 431 161 432 160 433 93 434 161 435 93 436 92 437 91 438 90 439 155 440 161 441 92 442 91 443 133 444 163 445 162 446 161 447 91 448 155 449 162 450 161 451 155 452 133 453 162 454 143 455 143 456 162 457 155 458 134 459 133 460 143 461 134 462 143 463 142 464 144 465 143 466 155 467 144 468 155 469 154 470 135 471 134 472 142 473 135 474 142 475 141 476 145 477 144 478 154 479 145 480 154 481 153 482 135 483 141 484 140 485 146 486 145 487 153 488 136 489 135 490 140 491 146 492 153 493 152 494 136 495 140 496 139 497 147 498 146 499 152 500 147 501 152 502 151 503 136 504 139 505 138 506 148 507 147 508 151 509 137 510 136 511 138 512 148 513 151 514 150 515 149 516 148 517 150 518 177 519 176 520 175 521 177 522 175 523 256 524 178 525 177 526 256 527 179 528 178 529 256 530 180 531 179 532 255 533 255 534 179 535 256 536 180 537 255 538 275 539 275 540 255 541 254 542 181 543 180 544 274 545 274 546 180 547 275 548 276 549 275 550 254 551 277 552 276 553 254 554 181 555 274 556 273 557 277 558 254 559 253 560 278 561 277 562 253 563 181 564 273 565 272 566 279 567 278 568 253 569 181 570 272 571 271 572 279 573 253 574 252 575 182 576 181 577 271 578 280 579 279 580 252 581 280 582 252 583 251 584 182 585 271 586 270 587 280 588 251 589 250 590 257 591 280 592 250 593 182 594 270 595 269 596 257 597 250 598 249 599 183 600 182 601 269 602 258 603 257 604 249 605 183 606 269 607 268 608 258 609 249 610 248 611 184 612 183 613 268 614 259 615 258 616 248 617 184 618 268 619 267 620 259 621 248 622 247 623 185 624 184 625 267 626 260 627 259 628 247 629 186 630 185 631 267 632 186 633 267 634 266 635 260 636 247 637 246 638 187 639 186 640 266 641 261 642 260 643 246 644 187 645 266 646 265 647 261 648 246 649 245 650 188 651 187 652 265 653 262 654 261 655 245 656 188 657 265 658 264 659 263 660 262 661 245 662 188 663 264 664 263 665 189 666 188 667 263 668 189 669 263 670 245 671 189 672 245 673 244 674 190 675 189 676 244 677 190 678 244 679 243 680 191 681 190 682 243 683 191 684 243 685 242 686 192 687 191 688 242 689 193 690 192 691 242 692 194 693 193 694 242 695 194 696 242 697 241 698 195 699 194 700 241 701 196 702 195 703 241 704 197 705 196 706 241 707 197 708 241 709 240 710 198 711 197 712 240 713 198 714 240 715 239 716 198 717 239 718 238 719 199 720 198 721 238 722 199 723 238 724 237 725 200 726 199 727 237 728 201 729 200 730 237 731 201 732 237 733 236 734 202 735 201 736 236 737 202 738 236 739 235 740 203 741 202 742 235 743 203 744 235 745 234 746 204 747 203 748 234 749 204 750 234 751 233 752 205 753 204 754 233 755 205 756 233 757 232 758 206 759 205 760 232 761 206 762 232 763 231 764 207 765 206 766 231 767 207 768 231 769 230 770 208 771 207 772 230 773 208 774 230 775 229 776 209 777 208 778 229 779 209 780 229 781 228 782 210 783 209 784 228 785 210 786 228 787 299 788 299 789 228 790 300 791 300 792 228 793 227 794 211 795 210 796 298 797 298 798 210 799 299 800 301 801 300 802 227 803 211 804 298 805 297 806 302 807 301 808 227 809 211 810 297 811 296 812 302 813 227 814 226 815 303 816 302 817 226 818 212 819 211 820 296 821 212 822 296 823 295 824 304 825 303 826 226 827 212 828 295 829 294 830 304 831 226 832 225 833 213 834 212 835 294 836 281 837 304 838 225 839 213 840 294 841 293 842 281 843 225 844 224 845 213 846 293 847 292 848 214 849 213 850 292 851 282 852 281 853 224 854 214 855 292 856 291 857 283 858 282 859 224 860 214 861 291 862 290 863 283 864 224 865 223 866 284 867 283 868 223 869 215 870 214 871 290 872 215 873 290 874 289 875 285 876 284 877 223 878 215 879 289 880 288 881 286 882 285 883 223 884 215 885 288 886 287 887 287 888 286 889 223 890 215 891 287 892 223 893 215 894 223 895 222 896 216 897 215 898 222 899 217 900 216 901 222 902 217 903 222 904 221 905 218 906 217 907 221 908 218 909 221 910 220 911 219 912 218 913 220 914 316 915 315 916 314 917 317 918 316 919 314 920 317 921 314 922 313 923 318 924 317 925 313 926 318 927 313 928 312 929 319 930 318 931 312 932 319 933 312 934 311 935 320 936 319 937 311 938 320 939 311 940 310 941 321 942 320 943 310 944 321 945 310 946 309 947 322 948 321 949 309 950 322 951 309 952 332 953 323 954 322 955 332 956 323 957 332 958 331 959 324 960 323 961 331 962 324 963 331 964 330 965 325 966 324 967 330 968 325 969 330 970 329 971 326 972 325 973 329 974 326 975 329 976 328 977 327 978 326 979 328 980 307 981 306 982 305 983 307 984 305 985 308 986 333 987 339 988 338 989 333 990 338 991 337 992 337 993 336 994 335 995 337 996 335 997 334 998 333 999 337 1000 334 1001 360 1002 359 1003 358 1004 361 1005 360 1006 358 1007 361 1008 358 1009 357 1010 362 1011 361 1012 357 1013 363 1014 362 1015 357 1016 363 1017 357 1018 356 1019 364 1020 363 1021 356 1022 364 1023 356 1024 355 1025 365 1026 364 1027 355 1028 366 1029 365 1030 367 1031 367 1032 365 1033 368 1034 368 1035 365 1036 369 1037 369 1038 365 1039 370 1040 370 1041 365 1042 371 1043 371 1044 365 1045 372 1046 372 1047 365 1048 355 1049 372 1050 355 1051 373 1052 373 1053 355 1054 354 1055 374 1056 373 1057 354 1058 375 1059 374 1060 354 1061 375 1062 354 1063 353 1064 376 1065 375 1066 353 1067 377 1068 376 1069 353 1070 378 1071 377 1072 353 1073 378 1074 353 1075 352 1076 379 1077 378 1078 352 1079 380 1080 379 1081 429 1082 429 1083 379 1084 352 1085 381 1086 380 1087 429 1088 382 1089 381 1090 429 1091 382 1092 429 1093 428 1094 411 1095 429 1096 352 1097 383 1098 382 1099 428 1100 383 1101 428 1102 427 1103 384 1104 383 1105 427 1106 384 1107 427 1108 426 1109 384 1110 426 1111 425 1112 385 1113 384 1114 425 1115 385 1116 425 1117 424 1118 385 1119 424 1120 423 1121 386 1122 385 1123 423 1124 386 1125 423 1126 422 1127 387 1128 386 1129 422 1130 387 1131 422 1132 421 1133 412 1134 411 1135 352 1136 387 1137 421 1138 420 1139 413 1140 412 1141 352 1142 341 1143 340 1144 410 1145 413 1146 352 1147 351 1148 342 1149 341 1150 410 1151 388 1152 387 1153 420 1154 388 1155 420 1156 419 1157 413 1158 351 1159 350 1160 414 1161 413 1162 350 1163 343 1164 342 1165 410 1166 414 1167 350 1168 349 1169 415 1170 414 1171 349 1172 344 1173 343 1174 410 1175 388 1176 419 1177 418 1178 415 1179 349 1180 348 1181 345 1182 344 1183 410 1184 416 1185 415 1186 348 1187 416 1188 348 1189 347 1190 346 1191 345 1192 410 1193 416 1194 347 1195 346 1196 388 1197 418 1198 417 1199 416 1200 346 1201 410 1202 417 1203 416 1204 410 1205 388 1206 417 1207 398 1208 398 1209 417 1210 410 1211 389 1212 388 1213 398 1214 389 1215 398 1216 397 1217 399 1218 398 1219 410 1220 399 1221 410 1222 409 1223 390 1224 389 1225 397 1226 390 1227 397 1228 396 1229 400 1230 399 1231 409 1232 400 1233 409 1234 408 1235 390 1236 396 1237 395 1238 401 1239 400 1240 408 1241 391 1242 390 1243 395 1244 401 1245 408 1246 407 1247 391 1248 395 1249 394 1250 402 1251 401 1252 407 1253 402 1254 407 1255 406 1256 391 1257 394 1258 393 1259 403 1260 402 1261 406 1262 392 1263 391 1264 393 1265 403 1266 406 1267 405 1268 404 1269 403 1270 405 1271 456 1272 455 1273 454 1274 457 1275 456 1276 454 1277 457 1278 454 1279 453 1280 458 1281 457 1282 453 1283 432 1284 431 1285 430 1286 432 1287 430 1288 462 1289 459 1290 458 1291 453 1292 459 1293 453 1294 452 1295 460 1296 459 1297 452 1298 460 1299 452 1300 451 1301 461 1302 460 1303 440 1304 440 1305 460 1306 451 1307 432 1308 462 1309 461 1310 432 1311 461 1312 434 1313 434 1314 461 1315 435 1316 435 1317 461 1318 436 1319 436 1320 461 1321 437 1322 437 1323 461 1324 438 1325 438 1326 461 1327 439 1328 439 1329 461 1330 440 1331 441 1332 440 1333 451 1334 442 1335 441 1336 451 1337 442 1338 451 1339 450 1340 443 1341 442 1342 450 1343 444 1344 443 1345 450 1346 445 1347 444 1348 450 1349 445 1350 450 1351 449 1352 432 1353 434 1354 433 1355 446 1356 445 1357 449 1358 447 1359 446 1360 449 1361 447 1362 449 1363 448 1364 464 1365 463 1366 486 1367 464 1368 486 1369 485 1370 465 1371 464 1372 485 1373 465 1374 485 1375 484 1376 466 1377 465 1378 484 1379 466 1380 484 1381 487 1382 487 1383 484 1384 488 1385 488 1386 484 1387 483 1388 467 1389 466 1390 510 1391 510 1392 466 1393 487 1394 467 1395 510 1396 509 1397 489 1398 488 1399 483 1400 467 1401 509 1402 508 1403 490 1404 489 1405 483 1406 490 1407 483 1408 482 1409 468 1410 467 1411 508 1412 468 1413 508 1414 507 1415 491 1416 490 1417 482 1418 468 1419 507 1420 506 1421 492 1422 491 1423 482 1424 492 1425 482 1426 481 1427 469 1428 468 1429 506 1430 469 1431 506 1432 505 1433 493 1434 492 1435 481 1436 470 1437 469 1438 505 1439 470 1440 505 1441 504 1442 493 1443 481 1444 480 1445 494 1446 493 1447 480 1448 470 1449 504 1450 503 1451 495 1452 494 1453 480 1454 471 1455 470 1456 503 1457 495 1458 480 1459 479 1460 471 1461 503 1462 502 1463 496 1464 495 1465 479 1466 471 1467 502 1468 501 1469 497 1470 496 1471 479 1472 472 1473 471 1474 501 1475 497 1476 479 1477 478 1478 472 1479 501 1480 500 1481 498 1482 497 1483 478 1484 472 1485 500 1486 499 1487 499 1488 498 1489 478 1490 472 1491 499 1492 478 1493 473 1494 472 1495 478 1496 473 1497 478 1498 477 1499 474 1500 473 1501 477 1502 474 1503 477 1504 476 1505 475 1506 474 1507 476 1508 512 1509 511 1510 544 1511 512 1512 544 1513 543 1514 512 1515 543 1516 542 1517 513 1518 512 1519 542 1520 514 1521 513 1522 542 1523 515 1524 514 1525 541 1526 541 1527 514 1528 542 1529 515 1530 541 1531 540 1532 515 1533 540 1534 539 1535 516 1536 515 1537 539 1538 516 1539 539 1540 538 1541 529 1542 528 1543 527 1544 516 1545 538 1546 537 1547 530 1548 529 1549 527 1550 517 1551 516 1552 537 1553 531 1554 530 1555 527 1556 517 1557 537 1558 536 1559 532 1560 531 1561 527 1562 517 1563 536 1564 535 1565 533 1566 532 1567 527 1568 517 1569 535 1570 534 1571 534 1572 533 1573 527 1574 517 1575 534 1576 527 1577 518 1578 517 1579 527 1580 519 1581 518 1582 527 1583 519 1584 527 1585 526 1586 519 1587 526 1588 525 1589 520 1590 519 1591 525 1592 520 1593 525 1594 524 1595 520 1596 524 1597 523 1598 521 1599 520 1600 523 1601 521 1602 523 1603 522 1604 552 1605 551 1606 550 1607 552 1608 550 1609 549 1610 553 1611 552 1612 549 1613 553 1614 549 1615 548 1616 553 1617 548 1618 547 1619 554 1620 553 1621 547 1622 554 1623 547 1624 546 1625 554 1626 546 1627 545 1628 555 1629 554 1630 545 1631 555 1632 545 1633 606 1634 606 1635 545 1636 607 1637 607 1638 545 1639 608 1640 608 1641 545 1642 609 1643 609 1644 545 1645 610 1646 610 1647 545 1648 611 1649 611 1650 545 1651 612 1652 556 1653 555 1654 606 1655 556 1656 606 1657 605 1658 556 1659 605 1660 604 1661 556 1662 604 1663 603 1664 557 1665 556 1666 603 1667 557 1668 603 1669 602 1670 557 1671 602 1672 601 1673 557 1674 601 1675 600 1676 557 1677 600 1678 599 1679 558 1680 557 1681 599 1682 558 1683 599 1684 598 1685 558 1686 598 1687 597 1688 558 1689 597 1690 596 1691 558 1692 596 1693 595 1694 559 1695 558 1696 595 1697 559 1698 595 1699 594 1700 559 1701 594 1702 593 1703 560 1704 559 1705 593 1706 560 1707 593 1708 592 1709 561 1710 560 1711 592 1712 561 1713 592 1714 591 1715 561 1716 591 1717 590 1718 562 1719 561 1720 590 1721 562 1722 590 1723 589 1724 563 1725 562 1726 589 1727 563 1728 589 1729 588 1730 576 1731 575 1732 574 1733 563 1734 588 1735 587 1736 564 1737 563 1738 587 1739 576 1740 574 1741 573 1742 565 1743 564 1744 587 1745 576 1746 573 1747 572 1748 566 1749 565 1750 587 1751 566 1752 587 1753 586 1754 576 1755 572 1756 571 1757 567 1758 566 1759 586 1760 568 1761 567 1762 586 1763 576 1764 571 1765 570 1766 569 1767 568 1768 586 1769 576 1770 570 1771 569 1772 576 1773 569 1774 586 1775 576 1776 586 1777 585 1778 577 1779 576 1780 585 1781 577 1782 585 1783 584 1784 578 1785 577 1786 584 1787 579 1788 578 1789 584 1790 579 1791 584 1792 583 1793 580 1794 579 1795 583 1796 580 1797 583 1798 582 1799 581 1800 580 1801 582 1802 618 1803 617 1804 616 1805 618 1806 616 1807 615 1808 615 1809 614 1810 613 1811 615 1812 613 1813 620 1814 618 1815 615 1816 620 1817 619 1818 618 1819 620 1820 641 1821 640 1822 639 1823 641 1824 639 1825 638 1826 642 1827 641 1828 638 1829 642 1830 638 1831 637 1832 643 1833 642 1834 637 1835 643 1836 637 1837 665 1838 665 1839 637 1840 666 1841 666 1842 637 1843 636 1844 644 1845 643 1846 664 1847 664 1848 643 1849 665 1850 644 1851 664 1852 663 1853 667 1854 666 1855 636 1856 644 1857 663 1858 662 1859 668 1860 667 1861 636 1862 644 1863 662 1864 661 1865 669 1866 668 1867 636 1868 645 1869 644 1870 661 1871 669 1872 636 1873 635 1874 645 1875 661 1876 660 1877 670 1878 669 1879 635 1880 645 1881 660 1882 659 1883 671 1884 670 1885 635 1886 646 1887 645 1888 659 1889 671 1890 635 1891 634 1892 646 1893 659 1894 671 1895 646 1896 671 1897 634 1898 647 1899 646 1900 633 1901 633 1902 646 1903 634 1904 647 1905 633 1906 632 1907 647 1908 632 1909 631 1910 648 1911 647 1912 631 1913 648 1914 631 1915 630 1916 622 1917 621 1918 658 1919 623 1920 622 1921 658 1922 649 1923 648 1924 630 1925 649 1926 630 1927 629 1928 624 1929 623 1930 658 1931 649 1932 629 1933 628 1934 625 1935 624 1936 658 1937 626 1938 625 1939 658 1940 649 1941 628 1942 627 1943 627 1944 626 1945 658 1946 649 1947 627 1948 658 1949 650 1950 649 1951 658 1952 650 1953 658 1954 657 1955 650 1956 657 1957 656 1958 651 1959 650 1960 656 1961 651 1962 656 1963 655 1964 651 1965 655 1966 654 1967 652 1968 651 1969 654 1970 652 1971 654 1972 653 1973 680 1974 679 1975 678 1976 680 1977 678 1978 681 1979 674 1980 673 1981 672 1982 674 1983 672 1984 677 1985 675 1986 674 1987 677 1988 675 1989 677 1990 676 1991 705 1992 704 1993 703 1994 705 1995 703 1996 702 1997 706 1998 705 1999 702 2000 706 2001 702 2002 701 2003 683 2004 682 2005 712 2006 683 2007 712 2008 711 2009 707 2010 706 2011 701 2012 707 2013 701 2014 700 2015 707 2016 700 2017 699 2018 708 2019 707 2020 699 2021 708 2022 699 2023 698 2024 709 2025 708 2026 698 2027 709 2028 698 2029 691 2030 691 2031 698 2032 692 2033 692 2034 698 2035 693 2036 693 2037 698 2038 694 2039 694 2040 698 2041 695 2042 695 2043 698 2044 696 2045 696 2046 698 2047 697 2048 710 2049 709 2050 690 2051 690 2052 709 2053 691 2054 710 2055 690 2056 689 2057 710 2058 689 2059 688 2060 683 2061 711 2062 710 2063 683 2064 710 2065 687 2066 687 2067 710 2068 688 2069 683 2070 687 2071 686 2072 683 2073 686 2074 685 2075 683 2076 685 2077 684 2078 714 2079 713 2080 736 2081 714 2082 736 2083 735 2084 715 2085 714 2086 735 2087 715 2088 735 2089 734 2090 716 2091 715 2092 734 2093 716 2094 734 2095 737 2096 737 2097 734 2098 738 2099 738 2100 734 2101 733 2102 717 2103 716 2104 760 2105 760 2106 716 2107 737 2108 717 2109 760 2110 759 2111 739 2112 738 2113 733 2114 717 2115 759 2116 758 2117 740 2118 739 2119 733 2120 740 2121 733 2122 732 2123 718 2124 717 2125 758 2126 718 2127 758 2128 757 2129 741 2130 740 2131 732 2132 718 2133 757 2134 756 2135 742 2136 741 2137 732 2138 742 2139 732 2140 731 2141 719 2142 718 2143 756 2144 719 2145 756 2146 755 2147 743 2148 742 2149 731 2150 720 2151 719 2152 755 2153 720 2154 755 2155 754 2156 743 2157 731 2158 730 2159 744 2160 743 2161 730 2162 720 2163 754 2164 753 2165 745 2166 744 2167 730 2168 721 2169 720 2170 753 2171 745 2172 730 2173 729 2174 721 2175 753 2176 752 2177 746 2178 745 2179 729 2180 721 2181 752 2182 751 2183 747 2184 746 2185 729 2186 722 2187 721 2188 751 2189 747 2190 729 2191 728 2192 722 2193 751 2194 750 2195 748 2196 747 2197 728 2198 722 2199 750 2200 749 2201 749 2202 748 2203 728 2204 722 2205 749 2206 728 2207 723 2208 722 2209 728 2210 723 2211 728 2212 727 2213 724 2214 723 2215 727 2216 724 2217 727 2218 726 2219 725 2220 724 2221 726 2222 768 2223 767 2224 766 2225 768 2226 766 2227 765 2228 769 2229 768 2230 765 2231 769 2232 765 2233 764 2234 769 2235 764 2236 763 2237 770 2238 769 2239 763 2240 770 2241 763 2242 762 2243 770 2244 762 2245 761 2246 771 2247 770 2248 761 2249 771 2250 761 2251 822 2252 822 2253 761 2254 823 2255 823 2256 761 2257 824 2258 824 2259 761 2260 825 2261 825 2262 761 2263 826 2264 826 2265 761 2266 827 2267 827 2268 761 2269 828 2270 772 2271 771 2272 822 2273 772 2274 822 2275 821 2276 772 2277 821 2278 820 2279 772 2280 820 2281 819 2282 773 2283 772 2284 819 2285 773 2286 819 2287 818 2288 773 2289 818 2290 817 2291 773 2292 817 2293 816 2294 773 2295 816 2296 815 2297 774 2298 773 2299 815 2300 774 2301 815 2302 814 2303 774 2304 814 2305 813 2306 774 2307 813 2308 812 2309 774 2310 812 2311 811 2312 775 2313 774 2314 811 2315 775 2316 811 2317 810 2318 775 2319 810 2320 809 2321 776 2322 775 2323 809 2324 776 2325 809 2326 808 2327 777 2328 776 2329 808 2330 777 2331 808 2332 807 2333 777 2334 807 2335 806 2336 778 2337 777 2338 806 2339 778 2340 806 2341 805 2342 779 2343 778 2344 805 2345 779 2346 805 2347 804 2348 792 2349 791 2350 790 2351 779 2352 804 2353 803 2354 780 2355 779 2356 803 2357 792 2358 790 2359 789 2360 781 2361 780 2362 803 2363 792 2364 789 2365 788 2366 782 2367 781 2368 803 2369 782 2370 803 2371 802 2372 792 2373 788 2374 787 2375 783 2376 782 2377 802 2378 784 2379 783 2380 802 2381 792 2382 787 2383 786 2384 785 2385 784 2386 802 2387 792 2388 786 2389 785 2390 792 2391 785 2392 802 2393 792 2394 802 2395 801 2396 793 2397 792 2398 801 2399 793 2400 801 2401 800 2402 794 2403 793 2404 800 2405 795 2406 794 2407 800 2408 795 2409 800 2410 799 2411 796 2412 795 2413 799 2414 796 2415 799 2416 798 2417 797 2418 796 2419 798 2420 852 2421 851 2422 850 2423 852 2424 850 2425 849 2426 853 2427 852 2428 849 2429 853 2430 849 2431 848 2432 830 2433 829 2434 859 2435 830 2436 859 2437 858 2438 854 2439 853 2440 848 2441 854 2442 848 2443 847 2444 854 2445 847 2446 846 2447 855 2448 854 2449 846 2450 855 2451 846 2452 845 2453 856 2454 855 2455 845 2456 856 2457 845 2458 838 2459 838 2460 845 2461 839 2462 839 2463 845 2464 840 2465 840 2466 845 2467 841 2468 841 2469 845 2470 842 2471 842 2472 845 2473 843 2474 843 2475 845 2476 844 2477 857 2478 856 2479 837 2480 837 2481 856 2482 838 2483 857 2484 837 2485 836 2486 857 2487 836 2488 835 2489 830 2490 858 2491 857 2492 830 2493 857 2494 834 2495 834 2496 857 2497 835 2498 830 2499 834 2500 833 2501 830 2502 833 2503 832 2504 830 2505 832 2506 831 2507 878 2508 877 2509 876 2510 878 2511 876 2512 875 2513 863 2514 862 2515 861 2516 863 2517 861 2518 860 2519 879 2520 878 2521 875 2522 879 2523 875 2524 874 2525 879 2526 874 2527 873 2528 864 2529 863 2530 860 2531 880 2532 879 2533 873 2534 880 2535 873 2536 872 2537 865 2538 864 2539 860 2540 866 2541 865 2542 890 2543 890 2544 865 2545 860 2546 880 2547 872 2548 871 2549 867 2550 866 2551 890 2552 880 2553 871 2554 870 2555 881 2556 880 2557 870 2558 868 2559 867 2560 890 2561 881 2562 870 2563 869 2564 869 2565 868 2566 890 2567 881 2568 869 2569 890 2570 881 2571 890 2572 889 2573 891 2574 890 2575 860 2576 881 2577 889 2578 888 2579 882 2580 881 2581 888 2582 882 2583 888 2584 887 2585 883 2586 882 2587 887 2588 883 2589 887 2590 886 2591 883 2592 886 2593 885 2594 884 2595 883 2596 885 2597 899 2598 898 2599 897 2600 899 2601 897 2602 896 2603 899 2604 896 2605 895 2606 900 2607 899 2608 895 2609 900 2610 895 2611 894 2612 900 2613 894 2614 893 2615 900 2616 893 2617 892 2618 901 2619 900 2620 892 2621 901 2622 892 2623 935 2624 935 2625 892 2626 936 2627 936 2628 892 2629 937 2630 937 2631 892 2632 938 2633 938 2634 892 2635 939 2636 939 2637 892 2638 940 2639 940 2640 892 2641 941 2642 901 2643 935 2644 934 2645 901 2646 934 2647 933 2648 902 2649 901 2650 933 2651 902 2652 933 2653 932 2654 902 2655 932 2656 931 2657 903 2658 902 2659 931 2660 903 2661 931 2662 930 2663 904 2664 903 2665 930 2666 904 2667 930 2668 929 2669 904 2670 929 2671 928 2672 905 2673 904 2674 928 2675 905 2676 928 2677 927 2678 906 2679 905 2680 927 2681 906 2682 927 2683 926 2684 907 2685 906 2686 926 2687 918 2688 917 2689 916 2690 907 2691 926 2692 925 2693 919 2694 918 2695 916 2696 920 2697 919 2698 916 2699 907 2700 925 2701 924 2702 908 2703 907 2704 924 2705 921 2706 920 2707 916 2708 922 2709 921 2710 916 2711 908 2712 924 2713 923 2714 923 2715 922 2716 916 2717 908 2718 923 2719 916 2720 908 2721 916 2722 915 2723 909 2724 908 2725 915 2726 909 2727 915 2728 914 2729 909 2730 914 2731 913 2732 909 2733 913 2734 912 2735 910 2736 909 2737 912 2738 910 2739 912 2740 911 2741 943 2742 942 2743 975 2744 943 2745 975 2746 974 2747 943 2748 974 2749 973 2750 944 2751 943 2752 973 2753 945 2754 944 2755 973 2756 946 2757 945 2758 972 2759 972 2760 945 2761 973 2762 946 2763 972 2764 971 2765 946 2766 971 2767 970 2768 947 2769 946 2770 970 2771 947 2772 970 2773 969 2774 960 2775 959 2776 958 2777 947 2778 969 2779 968 2780 961 2781 960 2782 958 2783 948 2784 947 2785 968 2786 962 2787 961 2788 958 2789 948 2790 968 2791 967 2792 963 2793 962 2794 958 2795 948 2796 967 2797 966 2798 964 2799 963 2800 958 2801 948 2802 966 2803 965 2804 965 2805 964 2806 958 2807 948 2808 965 2809 958 2810 949 2811 948 2812 958 2813 950 2814 949 2815 958 2816 950 2817 958 2818 957 2819 950 2820 957 2821 956 2822 951 2823 950 2824 956 2825 951 2826 956 2827 955 2828 951 2829 955 2830 954 2831 952 2832 951 2833 954 2834 952 2835 954 2836 953 2837 977 2838 976 2839 999 2840 977 2841 999 2842 998 2843 978 2844 977 2845 998 2846 978 2847 998 2848 997 2849 979 2850 978 2851 997 2852 979 2853 997 2854 1000 2855 1000 2856 997 2857 1001 2858 1001 2859 997 2860 996 2861 980 2862 979 2863 1023 2864 1023 2865 979 2866 1000 2867 980 2868 1023 2869 1022 2870 1002 2871 1001 2872 996 2873 980 2874 1022 2875 1021 2876 1003 2877 1002 2878 996 2879 1003 2880 996 2881 995 2882 981 2883 980 2884 1021 2885 981 2886 1021 2887 1020 2888 1004 2889 1003 2890 995 2891 981 2892 1020 2893 1019 2894 1005 2895 1004 2896 995 2897 1005 2898 995 2899 994 2900 982 2901 981 2902 1019 2903 982 2904 1019 2905 1018 2906 1006 2907 1005 2908 994 2909 983 2910 982 2911 1018 2912 983 2913 1018 2914 1017 2915 1006 2916 994 2917 993 2918 1007 2919 1006 2920 993 2921 983 2922 1017 2923 1016 2924 1008 2925 1007 2926 993 2927 984 2928 983 2929 1016 2930 1008 2931 993 2932 992 2933 984 2934 1016 2935 1015 2936 1009 2937 1008 2938 992 2939 984 2940 1015 2941 1014 2942 1010 2943 1009 2944 992 2945 985 2946 984 2947 1014 2948 1010 2949 992 2950 991 2951 985 2952 1014 2953 1013 2954 1011 2955 1010 2956 991 2957 985 2958 1013 2959 1012 2960 1012 2961 1011 2962 991 2963 985 2964 1012 2965 991 2966 986 2967 985 2968 991 2969 986 2970 991 2971 990 2972 987 2973 986 2974 990 2975 987 2976 990 2977 989 2978 988 2979 987 2980 989 2981 1026 2982 1025 2983 1024 2984 1026 2985 1024 2986 1056 2987 1050 2988 1049 2989 1048 2990 1051 2991 1050 2992 1048 2993 1051 2994 1048 2995 1047 2996 1052 2997 1051 2998 1047 2999 1053 3000 1052 3001 1047 3002 1053 3003 1047 3004 1046 3005 1054 3006 1053 3007 1046 3008 1054 3009 1046 3010 1045 3011 1055 3012 1054 3013 1034 3014 1034 3015 1054 3016 1045 3017 1026 3018 1056 3019 1055 3020 1026 3021 1055 3022 1028 3023 1028 3024 1055 3025 1029 3026 1029 3027 1055 3028 1030 3029 1030 3030 1055 3031 1031 3032 1031 3033 1055 3034 1032 3035 1032 3036 1055 3037 1033 3038 1033 3039 1055 3040 1034 3041 1035 3042 1034 3043 1045 3044 1036 3045 1035 3046 1045 3047 1036 3048 1045 3049 1044 3050 1037 3051 1036 3052 1044 3053 1038 3054 1037 3055 1044 3056 1039 3057 1038 3058 1044 3059 1039 3060 1044 3061 1043 3062 1026 3063 1028 3064 1027 3065 1040 3066 1039 3067 1043 3068 1041 3069 1040 3070 1043 3071 1041 3072 1043 3073 1042 3074 1064 3075 1063 3076 1062 3077 1064 3078 1062 3079 1061 3080 1065 3081 1064 3082 1061 3083 1065 3084 1061 3085 1060 3086 1065 3087 1060 3088 1059 3089 1066 3090 1065 3091 1059 3092 1066 3093 1059 3094 1058 3095 1066 3096 1058 3097 1057 3098 1067 3099 1066 3100 1057 3101 1067 3102 1057 3103 1118 3104 1118 3105 1057 3106 1119 3107 1119 3108 1057 3109 1120 3110 1120 3111 1057 3112 1121 3113 1121 3114 1057 3115 1122 3116 1122 3117 1057 3118 1123 3119 1123 3120 1057 3121 1124 3122 1068 3123 1067 3124 1118 3125 1068 3126 1118 3127 1117 3128 1068 3129 1117 3130 1116 3131 1068 3132 1116 3133 1115 3134 1069 3135 1068 3136 1115 3137 1069 3138 1115 3139 1114 3140 1069 3141 1114 3142 1113 3143 1069 3144 1113 3145 1112 3146 1069 3147 1112 3148 1111 3149 1070 3150 1069 3151 1111 3152 1070 3153 1111 3154 1110 3155 1070 3156 1110 3157 1109 3158 1070 3159 1109 3160 1108 3161 1070 3162 1108 3163 1107 3164 1071 3165 1070 3166 1107 3167 1071 3168 1107 3169 1106 3170 1071 3171 1106 3172 1105 3173 1072 3174 1071 3175 1105 3176 1072 3177 1105 3178 1104 3179 1073 3180 1072 3181 1104 3182 1073 3183 1104 3184 1103 3185 1073 3186 1103 3187 1102 3188 1074 3189 1073 3190 1102 3191 1074 3192 1102 3193 1101 3194 1075 3195 1074 3196 1101 3197 1075 3198 1101 3199 1100 3200 1088 3201 1087 3202 1086 3203 1075 3204 1100 3205 1099 3206 1076 3207 1075 3208 1099 3209 1088 3210 1086 3211 1085 3212 1077 3213 1076 3214 1099 3215 1088 3216 1085 3217 1084 3218 1078 3219 1077 3220 1099 3221 1078 3222 1099 3223 1098 3224 1088 3225 1084 3226 1083 3227 1079 3228 1078 3229 1098 3230 1080 3231 1079 3232 1098 3233 1088 3234 1083 3235 1082 3236 1081 3237 1080 3238 1098 3239 1088 3240 1082 3241 1081 3242 1088 3243 1081 3244 1098 3245 1088 3246 1098 3247 1097 3248 1089 3249 1088 3250 1097 3251 1089 3252 1097 3253 1096 3254 1090 3255 1089 3256 1096 3257 1091 3258 1090 3259 1096 3260 1091 3261 1096 3262 1095 3263 1092 3264 1091 3265 1095 3266 1092 3267 1095 3268 1094 3269 1093 3270 1092 3271 1094 3272 1130 3273 1129 3274 1128 3275 1130 3276 1128 3277 1127 3278 1127 3279 1126 3280 1125 3281 1127 3282 1125 3283 1132 3284 1130 3285 1127 3286 1132 3287 1131 3288 1130 3289 1132 3290 1135 3291 1134 3292 1133 3293 1135 3294 1133 3295 1136 3296 1157 3297 1156 3298 1159 3299 1159 3300 1156 3301 1155 3302 1159 3303 1155 3304 1154 3305 1159 3306 1154 3307 1153 3308 1159 3309 1153 3310 1152 3311 1159 3312 1152 3313 1160 3314 1160 3315 1152 3316 1161 3317 1161 3318 1152 3319 1151 3320 1157 3321 1159 3322 1178 3323 1162 3324 1161 3325 1151 3326 1163 3327 1162 3328 1151 3329 1163 3330 1151 3331 1150 3332 1164 3333 1163 3334 1150 3335 1165 3336 1164 3337 1150 3338 1165 3339 1150 3340 1149 3341 1166 3342 1165 3343 1149 3344 1167 3345 1166 3346 1149 3347 1167 3348 1149 3349 1148 3350 1168 3351 1167 3352 1148 3353 1168 3354 1148 3355 1147 3356 1169 3357 1168 3358 1147 3359 1170 3360 1169 3361 1147 3362 1170 3363 1147 3364 1146 3365 1157 3366 1178 3367 1177 3368 1171 3369 1170 3370 1146 3371 1157 3372 1177 3373 1137 3374 1137 3375 1177 3376 1176 3377 1137 3378 1176 3379 1175 3380 1172 3381 1171 3382 1146 3383 1137 3384 1175 3385 1174 3386 1137 3387 1174 3388 1173 3389 1137 3390 1173 3391 1172 3392 1137 3393 1172 3394 1146 3395 1137 3396 1146 3397 1145 3398 1137 3399 1145 3400 1144 3401 1157 3402 1137 3403 1158 3404 1138 3405 1137 3406 1144 3407 1139 3408 1138 3409 1144 3410 1140 3411 1139 3412 1144 3413 1140 3414 1144 3415 1143 3416 1141 3417 1140 3418 1143 3419 1142 3420 1141 3421 1143 3422 1199 3423 1198 3424 1201 3425 1201 3426 1198 3427 1197 3428 1201 3429 1197 3430 1196 3431 1201 3432 1196 3433 1195 3434 1201 3435 1195 3436 1194 3437 1201 3438 1194 3439 1202 3440 1202 3441 1194 3442 1203 3443 1203 3444 1194 3445 1193 3446 1199 3447 1201 3448 1220 3449 1204 3450 1203 3451 1193 3452 1205 3453 1204 3454 1193 3455 1205 3456 1193 3457 1192 3458 1206 3459 1205 3460 1192 3461 1207 3462 1206 3463 1192 3464 1207 3465 1192 3466 1191 3467 1208 3468 1207 3469 1191 3470 1209 3471 1208 3472 1191 3473 1209 3474 1191 3475 1190 3476 1210 3477 1209 3478 1190 3479 1210 3480 1190 3481 1189 3482 1211 3483 1210 3484 1189 3485 1212 3486 1211 3487 1189 3488 1212 3489 1189 3490 1188 3491 1199 3492 1220 3493 1219 3494 1213 3495 1212 3496 1188 3497 1199 3498 1219 3499 1179 3500 1179 3501 1219 3502 1218 3503 1179 3504 1218 3505 1217 3506 1214 3507 1213 3508 1188 3509 1179 3510 1217 3511 1216 3512 1179 3513 1216 3514 1215 3515 1179 3516 1215 3517 1214 3518 1179 3519 1214 3520 1188 3521 1179 3522 1188 3523 1187 3524 1179 3525 1187 3526 1186 3527 1199 3528 1179 3529 1200 3530 1180 3531 1179 3532 1186 3533 1181 3534 1180 3535 1186 3536 1182 3537 1181 3538 1186 3539 1182 3540 1186 3541 1185 3542 1183 3543 1182 3544 1185 3545 1184 3546 1183 3547 1185 3548 1241 3549 1240 3550 1239 3551 1242 3552 1241 3553 1239 3554 1242 3555 1239 3556 1238 3557 1243 3558 1242 3559 1238 3560 1244 3561 1243 3562 1238 3563 1244 3564 1238 3565 1237 3566 1245 3567 1244 3568 1237 3569 1245 3570 1237 3571 1236 3572 1246 3573 1245 3574 1236 3575 1247 3576 1246 3577 1248 3578 1248 3579 1246 3580 1249 3581 1249 3582 1246 3583 1250 3584 1250 3585 1246 3586 1251 3587 1251 3588 1246 3589 1252 3590 1252 3591 1246 3592 1253 3593 1253 3594 1246 3595 1236 3596 1253 3597 1236 3598 1254 3599 1254 3600 1236 3601 1235 3602 1255 3603 1254 3604 1235 3605 1256 3606 1255 3607 1235 3608 1256 3609 1235 3610 1234 3611 1257 3612 1256 3613 1234 3614 1258 3615 1257 3616 1234 3617 1259 3618 1258 3619 1234 3620 1259 3621 1234 3622 1233 3623 1260 3624 1259 3625 1233 3626 1261 3627 1260 3628 1310 3629 1310 3630 1260 3631 1233 3632 1262 3633 1261 3634 1310 3635 1263 3636 1262 3637 1310 3638 1263 3639 1310 3640 1309 3641 1292 3642 1310 3643 1233 3644 1264 3645 1263 3646 1309 3647 1264 3648 1309 3649 1308 3650 1265 3651 1264 3652 1308 3653 1265 3654 1308 3655 1307 3656 1265 3657 1307 3658 1306 3659 1266 3660 1265 3661 1306 3662 1266 3663 1306 3664 1305 3665 1266 3666 1305 3667 1304 3668 1267 3669 1266 3670 1304 3671 1267 3672 1304 3673 1303 3674 1268 3675 1267 3676 1303 3677 1268 3678 1303 3679 1302 3680 1293 3681 1292 3682 1233 3683 1268 3684 1302 3685 1301 3686 1294 3687 1293 3688 1233 3689 1222 3690 1221 3691 1291 3692 1294 3693 1233 3694 1232 3695 1223 3696 1222 3697 1291 3698 1269 3699 1268 3700 1301 3701 1269 3702 1301 3703 1300 3704 1294 3705 1232 3706 1231 3707 1295 3708 1294 3709 1231 3710 1224 3711 1223 3712 1291 3713 1295 3714 1231 3715 1230 3716 1296 3717 1295 3718 1230 3719 1225 3720 1224 3721 1291 3722 1269 3723 1300 3724 1299 3725 1296 3726 1230 3727 1229 3728 1226 3729 1225 3730 1291 3731 1297 3732 1296 3733 1229 3734 1297 3735 1229 3736 1228 3737 1227 3738 1226 3739 1291 3740 1297 3741 1228 3742 1227 3743 1269 3744 1299 3745 1298 3746 1297 3747 1227 3748 1291 3749 1298 3750 1297 3751 1291 3752 1269 3753 1298 3754 1279 3755 1279 3756 1298 3757 1291 3758 1270 3759 1269 3760 1279 3761 1270 3762 1279 3763 1278 3764 1280 3765 1279 3766 1291 3767 1280 3768 1291 3769 1290 3770 1271 3771 1270 3772 1278 3773 1271 3774 1278 3775 1277 3776 1281 3777 1280 3778 1290 3779 1281 3780 1290 3781 1289 3782 1271 3783 1277 3784 1276 3785 1282 3786 1281 3787 1289 3788 1272 3789 1271 3790 1276 3791 1282 3792 1289 3793 1288 3794 1272 3795 1276 3796 1275 3797 1283 3798 1282 3799 1288 3800 1283 3801 1288 3802 1287 3803 1272 3804 1275 3805 1274 3806 1284 3807 1283 3808 1287 3809 1273 3810 1272 3811 1274 3812 1284 3813 1287 3814 1286 3815 1285 3816 1284 3817 1286 3818 1312 3819 1311 3820 1334 3821 1312 3822 1334 3823 1333 3824 1313 3825 1312 3826 1333 3827 1313 3828 1333 3829 1332 3830 1314 3831 1313 3832 1332 3833 1314 3834 1332 3835 1335 3836 1335 3837 1332 3838 1336 3839 1336 3840 1332 3841 1331 3842 1315 3843 1314 3844 1358 3845 1358 3846 1314 3847 1335 3848 1315 3849 1358 3850 1357 3851 1337 3852 1336 3853 1331 3854 1315 3855 1357 3856 1356 3857 1338 3858 1337 3859 1331 3860 1338 3861 1331 3862 1330 3863 1316 3864 1315 3865 1356 3866 1316 3867 1356 3868 1355 3869 1339 3870 1338 3871 1330 3872 1316 3873 1355 3874 1354 3875 1340 3876 1339 3877 1330 3878 1340 3879 1330 3880 1329 3881 1317 3882 1316 3883 1354 3884 1317 3885 1354 3886 1353 3887 1341 3888 1340 3889 1329 3890 1318 3891 1317 3892 1353 3893 1318 3894 1353 3895 1352 3896 1341 3897 1329 3898 1328 3899 1342 3900 1341 3901 1328 3902 1318 3903 1352 3904 1351 3905 1343 3906 1342 3907 1328 3908 1319 3909 1318 3910 1351 3911 1343 3912 1328 3913 1327 3914 1319 3915 1351 3916 1350 3917 1344 3918 1343 3919 1327 3920 1319 3921 1350 3922 1349 3923 1345 3924 1344 3925 1327 3926 1320 3927 1319 3928 1349 3929 1345 3930 1327 3931 1326 3932 1320 3933 1349 3934 1348 3935 1346 3936 1345 3937 1326 3938 1320 3939 1348 3940 1347 3941 1347 3942 1346 3943 1326 3944 1320 3945 1347 3946 1326 3947 1321 3948 1320 3949 1326 3950 1321 3951 1326 3952 1325 3953 1322 3954 1321 3955 1325 3956 1322 3957 1325 3958 1324 3959 1323 3960 1322 3961 1324 3962 1360 3963 1359 3964 1392 3965 1360 3966 1392 3967 1391 3968 1360 3969 1391 3970 1390 3971 1361 3972 1360 3973 1390 3974 1362 3975 1361 3976 1390 3977 1363 3978 1362 3979 1389 3980 1389 3981 1362 3982 1390 3983 1363 3984 1389 3985 1388 3986 1363 3987 1388 3988 1387 3989 1364 3990 1363 3991 1387 3992 1364 3993 1387 3994 1386 3995 1377 3996 1376 3997 1375 3998 1364 3999 1386 4000 1385 4001 1378 4002 1377 4003 1375 4004 1365 4005 1364 4006 1385 4007 1379 4008 1378 4009 1375 4010 1365 4011 1385 4012 1384 4013 1380 4014 1379 4015 1375 4016 1365 4017 1384 4018 1383 4019 1381 4020 1380 4021 1375 4022 1365 4023 1383 4024 1382 4025 1382 4026 1381 4027 1375 4028 1365 4029 1382 4030 1375 4031 1366 4032 1365 4033 1375 4034 1367 4035 1366 4036 1375 4037 1367 4038 1375 4039 1374 4040 1367 4041 1374 4042 1373 4043 1368 4044 1367 4045 1373 4046 1368 4047 1373 4048 1372 4049 1368 4050 1372 4051 1371 4052 1369 4053 1368 4054 1371 4055 1369 4056 1371 4057 1370 4058 1413 4059 1412 4060 1411 4061 1413 4062 1411 4063 1410 4064 1414 4065 1413 4066 1410 4067 1414 4068 1410 4069 1409 4070 1415 4071 1414 4072 1409 4073 1415 4074 1409 4075 1437 4076 1437 4077 1409 4078 1438 4079 1438 4080 1409 4081 1408 4082 1416 4083 1415 4084 1436 4085 1436 4086 1415 4087 1437 4088 1416 4089 1436 4090 1435 4091 1439 4092 1438 4093 1408 4094 1416 4095 1435 4096 1434 4097 1440 4098 1439 4099 1408 4100 1416 4101 1434 4102 1433 4103 1441 4104 1440 4105 1408 4106 1417 4107 1416 4108 1433 4109 1441 4110 1408 4111 1407 4112 1417 4113 1433 4114 1432 4115 1442 4116 1441 4117 1407 4118 1417 4119 1432 4120 1431 4121 1443 4122 1442 4123 1407 4124 1418 4125 1417 4126 1431 4127 1443 4128 1407 4129 1406 4130 1418 4131 1431 4132 1443 4133 1418 4134 1443 4135 1406 4136 1419 4137 1418 4138 1405 4139 1405 4140 1418 4141 1406 4142 1419 4143 1405 4144 1404 4145 1419 4146 1404 4147 1403 4148 1420 4149 1419 4150 1403 4151 1420 4152 1403 4153 1402 4154 1394 4155 1393 4156 1430 4157 1395 4158 1394 4159 1430 4160 1421 4161 1420 4162 1402 4163 1421 4164 1402 4165 1401 4166 1396 4167 1395 4168 1430 4169 1421 4170 1401 4171 1400 4172 1397 4173 1396 4174 1430 4175 1398 4176 1397 4177 1430 4178 1421 4179 1400 4180 1399 4181 1399 4182 1398 4183 1430 4184 1421 4185 1399 4186 1430 4187 1422 4188 1421 4189 1430 4190 1422 4191 1430 4192 1429 4193 1422 4194 1429 4195 1428 4196 1423 4197 1422 4198 1428 4199 1423 4200 1428 4201 1427 4202 1423 4203 1427 4204 1426 4205 1424 4206 1423 4207 1426 4208 1424 4209 1426 4210 1425 4211 1451 4212 1450 4213 1449 4214 1451 4215 1449 4216 1448 4217 1452 4218 1451 4219 1448 4220 1452 4221 1448 4222 1447 4223 1452 4224 1447 4225 1446 4226 1453 4227 1452 4228 1446 4229 1453 4230 1446 4231 1445 4232 1453 4233 1445 4234 1444 4235 1454 4236 1453 4237 1444 4238 1454 4239 1444 4240 1505 4241 1505 4242 1444 4243 1506 4244 1506 4245 1444 4246 1507 4247 1507 4248 1444 4249 1508 4250 1508 4251 1444 4252 1509 4253 1509 4254 1444 4255 1510 4256 1510 4257 1444 4258 1511 4259 1455 4260 1454 4261 1505 4262 1455 4263 1505 4264 1504 4265 1455 4266 1504 4267 1503 4268 1455 4269 1503 4270 1502 4271 1456 4272 1455 4273 1502 4274 1456 4275 1502 4276 1501 4277 1456 4278 1501 4279 1500 4280 1456 4281 1500 4282 1499 4283 1456 4284 1499 4285 1498 4286 1457 4287 1456 4288 1498 4289 1457 4290 1498 4291 1497 4292 1457 4293 1497 4294 1496 4295 1457 4296 1496 4297 1495 4298 1457 4299 1495 4300 1494 4301 1458 4302 1457 4303 1494 4304 1458 4305 1494 4306 1493 4307 1458 4308 1493 4309 1492 4310 1459 4311 1458 4312 1492 4313 1459 4314 1492 4315 1491 4316 1460 4317 1459 4318 1491 4319 1460 4320 1491 4321 1490 4322 1460 4323 1490 4324 1489 4325 1461 4326 1460 4327 1489 4328 1461 4329 1489 4330 1488 4331 1462 4332 1461 4333 1488 4334 1462 4335 1488 4336 1487 4337 1475 4338 1474 4339 1473 4340 1462 4341 1487 4342 1486 4343 1463 4344 1462 4345 1486 4346 1475 4347 1473 4348 1472 4349 1464 4350 1463 4351 1486 4352 1475 4353 1472 4354 1471 4355 1465 4356 1464 4357 1486 4358 1465 4359 1486 4360 1485 4361 1475 4362 1471 4363 1470 4364 1466 4365 1465 4366 1485 4367 1467 4368 1466 4369 1485 4370 1475 4371 1470 4372 1469 4373 1468 4374 1467 4375 1485 4376 1475 4377 1469 4378 1468 4379 1475 4380 1468 4381 1485 4382 1475 4383 1485 4384 1484 4385 1476 4386 1475 4387 1484 4388 1476 4389 1484 4390 1483 4391 1477 4392 1476 4393 1483 4394 1478 4395 1477 4396 1483 4397 1478 4398 1483 4399 1482 4400 1479 4401 1478 4402 1482 4403 1479 4404 1482 4405 1481 4406 1480 4407 1479 4408 1481 4409 1530 4410 1529 4411 1528 4412 1530 4413 1528 4414 1527 4415 1515 4416 1514 4417 1513 4418 1515 4419 1513 4420 1512 4421 1531 4422 1530 4423 1527 4424 1531 4425 1527 4426 1526 4427 1531 4428 1526 4429 1525 4430 1516 4431 1515 4432 1512 4433 1532 4434 1531 4435 1525 4436 1532 4437 1525 4438 1524 4439 1517 4440 1516 4441 1512 4442 1518 4443 1517 4444 1542 4445 1542 4446 1517 4447 1512 4448 1532 4449 1524 4450 1523 4451 1519 4452 1518 4453 1542 4454 1532 4455 1523 4456 1522 4457 1533 4458 1532 4459 1522 4460 1520 4461 1519 4462 1542 4463 1533 4464 1522 4465 1521 4466 1521 4467 1520 4468 1542 4469 1533 4470 1521 4471 1542 4472 1533 4473 1542 4474 1541 4475 1543 4476 1542 4477 1512 4478 1533 4479 1541 4480 1540 4481 1534 4482 1533 4483 1540 4484 1534 4485 1540 4486 1539 4487 1535 4488 1534 4489 1539 4490 1535 4491 1539 4492 1538 4493 1535 4494 1538 4495 1537 4496 1536 4497 1535 4498 1537 4499 1545 4500 1544 4501 1567 4502 1545 4503 1567 4504 1566 4505 1546 4506 1545 4507 1566 4508 1546 4509 1566 4510 1565 4511 1547 4512 1546 4513 1565 4514 1547 4515 1565 4516 1568 4517 1568 4518 1565 4519 1569 4520 1569 4521 1565 4522 1564 4523 1548 4524 1547 4525 1591 4526 1591 4527 1547 4528 1568 4529 1548 4530 1591 4531 1590 4532 1570 4533 1569 4534 1564 4535 1548 4536 1590 4537 1589 4538 1571 4539 1570 4540 1564 4541 1571 4542 1564 4543 1563 4544 1549 4545 1548 4546 1589 4547 1549 4548 1589 4549 1588 4550 1572 4551 1571 4552 1563 4553 1549 4554 1588 4555 1587 4556 1573 4557 1572 4558 1563 4559 1573 4560 1563 4561 1562 4562 1550 4563 1549 4564 1587 4565 1550 4566 1587 4567 1586 4568 1574 4569 1573 4570 1562 4571 1551 4572 1550 4573 1586 4574 1551 4575 1586 4576 1585 4577 1574 4578 1562 4579 1561 4580 1575 4581 1574 4582 1561 4583 1551 4584 1585 4585 1584 4586 1576 4587 1575 4588 1561 4589 1552 4590 1551 4591 1584 4592 1576 4593 1561 4594 1560 4595 1552 4596 1584 4597 1583 4598 1577 4599 1576 4600 1560 4601 1552 4602 1583 4603 1582 4604 1578 4605 1577 4606 1560 4607 1553 4608 1552 4609 1582 4610 1578 4611 1560 4612 1559 4613 1553 4614 1582 4615 1581 4616 1579 4617 1578 4618 1559 4619 1553 4620 1581 4621 1580 4622 1580 4623 1579 4624 1559 4625 1553 4626 1580 4627 1559 4628 1554 4629 1553 4630 1559 4631 1554 4632 1559 4633 1558 4634 1555 4635 1554 4636 1558 4637 1555 4638 1558 4639 1557 4640 1556 4641 1555 4642 1557 4643 1644 4644 1643 4645 1642 4646 1632 4647 1631 4648 1630 4649 1645 4650 1644 4651 1642 4652 1645 4653 1642 4654 1641 4655 1633 4656 1632 4657 1630 4658 1633 4659 1630 4660 1629 4661 1646 4662 1645 4663 1641 4664 1593 4665 1592 4666 1650 4667 1593 4668 1650 4669 1649 4670 1646 4671 1641 4672 1640 4673 1634 4674 1633 4675 1629 4676 1647 4677 1646 4678 1640 4679 1647 4680 1640 4681 1639 4682 1634 4683 1629 4684 1628 4685 1635 4686 1634 4687 1628 4688 1648 4689 1647 4690 1639 4691 1648 4692 1639 4693 1638 4694 1636 4695 1635 4696 1628 4697 1649 4698 1648 4699 1638 4700 1636 4701 1628 4702 1627 4703 1649 4704 1638 4705 1637 4706 1637 4707 1636 4708 1616 4709 1616 4710 1636 4711 1627 4712 1593 4713 1649 4714 1595 4715 1595 4716 1649 4717 1596 4718 1596 4719 1649 4720 1597 4721 1597 4722 1649 4723 1598 4724 1598 4725 1649 4726 1599 4727 1599 4728 1649 4729 1600 4730 1600 4731 1649 4732 1601 4733 1601 4734 1649 4735 1637 4736 1602 4737 1601 4738 1637 4739 1637 4740 1616 4741 1615 4742 1617 4743 1616 4744 1627 4745 1637 4746 1615 4747 1614 4748 1603 4749 1602 4750 1637 4751 1618 4752 1617 4753 1627 4754 1603 4755 1637 4756 1614 4757 1603 4758 1614 4759 1613 4760 1618 4761 1627 4762 1626 4763 1604 4764 1603 4765 1613 4766 1619 4767 1618 4768 1626 4769 1604 4770 1613 4771 1612 4772 1605 4773 1604 4774 1612 4775 1620 4776 1619 4777 1626 4778 1605 4779 1612 4780 1611 4781 1605 4782 1611 4783 1610 4784 1606 4785 1605 4786 1610 4787 1621 4788 1620 4789 1626 4790 1621 4791 1626 4792 1625 4793 1593 4794 1595 4795 1594 4796 1606 4797 1610 4798 1609 4799 1607 4800 1606 4801 1609 4802 1622 4803 1621 4804 1625 4805 1622 4806 1625 4807 1624 4808 1608 4809 1607 4810 1609 4811 1623 4812 1622 4813 1624 4814 1652 4815 1651 4816 1684 4817 1652 4818 1684 4819 1683 4820 1652 4821 1683 4822 1682 4823 1653 4824 1652 4825 1682 4826 1654 4827 1653 4828 1682 4829 1655 4830 1654 4831 1681 4832 1681 4833 1654 4834 1682 4835 1655 4836 1681 4837 1680 4838 1655 4839 1680 4840 1679 4841 1656 4842 1655 4843 1679 4844 1656 4845 1679 4846 1678 4847 1669 4848 1668 4849 1667 4850 1656 4851 1678 4852 1677 4853 1670 4854 1669 4855 1667 4856 1657 4857 1656 4858 1677 4859 1671 4860 1670 4861 1667 4862 1657 4863 1677 4864 1676 4865 1672 4866 1671 4867 1667 4868 1657 4869 1676 4870 1675 4871 1673 4872 1672 4873 1667 4874 1657 4875 1675 4876 1674 4877 1674 4878 1673 4879 1667 4880 1657 4881 1674 4882 1667 4883 1658 4884 1657 4885 1667 4886 1659 4887 1658 4888 1667 4889 1659 4890 1667 4891 1666 4892 1659 4893 1666 4894 1665 4895 1660 4896 1659 4897 1665 4898 1660 4899 1665 4900 1664 4901 1660 4902 1664 4903 1663 4904 1661 4905 1660 4906 1663 4907 1661 4908 1663 4909 1662 4910 1688 4911 1687 4912 1686 4913 1688 4914 1686 4915 1685 4916 1689 4917 1688 4918 1685 4919 1689 4920 1685 4921 1720 4922 1690 4923 1689 4924 1720 4925 1691 4926 1690 4927 1717 4928 1717 4929 1690 4930 1718 4931 1718 4932 1690 4933 1719 4934 1719 4935 1690 4936 1720 4937 1692 4938 1691 4939 1717 4940 1693 4941 1692 4942 1714 4943 1714 4944 1692 4945 1715 4946 1715 4947 1692 4948 1716 4949 1716 4950 1692 4951 1717 4952 1694 4953 1693 4954 1713 4955 1713 4956 1693 4957 1714 4958 1694 4959 1713 4960 1712 4961 1694 4962 1712 4963 1711 4964 1695 4965 1694 4966 1711 4967 1695 4968 1711 4969 1710 4970 1696 4971 1695 4972 1710 4973 1696 4974 1710 4975 1709 4976 1696 4977 1709 4978 1708 4979 1697 4980 1696 4981 1708 4982 1697 4983 1708 4984 1707 4985 1698 4986 1697 4987 1707 4988 1700 4989 1699 4990 1698 4991 1700 4992 1698 4993 1707 4994 1700 4995 1707 4996 1706 4997 1700 4998 1706 4999 1705 5000 1701 5001 1700 5002 1705 5003 1702 5004 1701 5005 1704 5006 1704 5007 1701 5008 1705 5009 1702 5010 1704 5011 1703 5012 1741 5013 1740 5014 1739 5015 1741 5016 1739 5017 1738 5018 1742 5019 1741 5020 1738 5021 1742 5022 1738 5023 1737 5024 1743 5025 1742 5026 1737 5027 1743 5028 1737 5029 1765 5030 1765 5031 1737 5032 1766 5033 1766 5034 1737 5035 1736 5036 1744 5037 1743 5038 1764 5039 1764 5040 1743 5041 1765 5042 1744 5043 1764 5044 1763 5045 1767 5046 1766 5047 1736 5048 1744 5049 1763 5050 1762 5051 1768 5052 1767 5053 1736 5054 1744 5055 1762 5056 1761 5057 1769 5058 1768 5059 1736 5060 1745 5061 1744 5062 1761 5063 1769 5064 1736 5065 1735 5066 1745 5067 1761 5068 1760 5069 1770 5070 1769 5071 1735 5072 1745 5073 1760 5074 1759 5075 1771 5076 1770 5077 1735 5078 1746 5079 1745 5080 1759 5081 1771 5082 1735 5083 1734 5084 1746 5085 1759 5086 1771 5087 1746 5088 1771 5089 1734 5090 1747 5091 1746 5092 1733 5093 1733 5094 1746 5095 1734 5096 1747 5097 1733 5098 1732 5099 1747 5100 1732 5101 1731 5102 1748 5103 1747 5104 1731 5105 1748 5106 1731 5107 1730 5108 1722 5109 1721 5110 1758 5111 1723 5112 1722 5113 1758 5114 1749 5115 1748 5116 1730 5117 1749 5118 1730 5119 1729 5120 1724 5121 1723 5122 1758 5123 1749 5124 1729 5125 1728 5126 1725 5127 1724 5128 1758 5129 1726 5130 1725 5131 1758 5132 1749 5133 1728 5134 1727 5135 1727 5136 1726 5137 1758 5138 1749 5139 1727 5140 1758 5141 1750 5142 1749 5143 1758 5144 1750 5145 1758 5146 1757 5147 1750 5148 1757 5149 1756 5150 1751 5151 1750 5152 1756 5153 1751 5154 1756 5155 1755 5156 1751 5157 1755 5158 1754 5159 1752 5160 1751 5161 1754 5162 1752 5163 1754 5164 1753 5165 1774 5166 1773 5167 1772 5168 1774 5169 1772 5170 1775 5171 1789 5172 1788 5173 1787 5174 1790 5175 1789 5176 1787 5177 1790 5178 1787 5179 1786 5180 1791 5181 1790 5182 1786 5183 1791 5184 1786 5185 1785 5186 1792 5187 1791 5188 1785 5189 1792 5190 1785 5191 1784 5192 1793 5193 1792 5194 1784 5195 1794 5196 1793 5197 1784 5198 1794 5199 1784 5200 1783 5201 1795 5202 1794 5203 1783 5204 1795 5205 1783 5206 1782 5207 1796 5208 1795 5209 1782 5210 1797 5211 1796 5212 1782 5213 1797 5214 1782 5215 1781 5216 1798 5217 1797 5218 1781 5219 1799 5220 1798 5221 1800 5222 1800 5223 1798 5224 1781 5225 1801 5226 1800 5227 1781 5228 1801 5229 1781 5230 1780 5231 1802 5232 1801 5233 1780 5234 1803 5235 1802 5236 1780 5237 1803 5238 1780 5239 1779 5240 1804 5241 1803 5242 1779 5243 1804 5244 1779 5245 1778 5246 1805 5247 1804 5248 1778 5249 1805 5250 1778 5251 1777 5252 1806 5253 1805 5254 1777 5255 1776 5256 1806 5257 1777 5258 1859 5259 1858 5260 1857 5261 1847 5262 1846 5263 1845 5264 1860 5265 1859 5266 1857 5267 1860 5268 1857 5269 1856 5270 1848 5271 1847 5272 1845 5273 1848 5274 1845 5275 1844 5276 1861 5277 1860 5278 1856 5279 1808 5280 1807 5281 1865 5282 1808 5283 1865 5284 1864 5285 1861 5286 1856 5287 1855 5288 1849 5289 1848 5290 1844 5291 1862 5292 1861 5293 1855 5294 1862 5295 1855 5296 1854 5297 1849 5298 1844 5299 1843 5300 1850 5301 1849 5302 1843 5303 1863 5304 1862 5305 1854 5306 1863 5307 1854 5308 1853 5309 1851 5310 1850 5311 1843 5312 1864 5313 1863 5314 1853 5315 1851 5316 1843 5317 1842 5318 1864 5319 1853 5320 1852 5321 1852 5322 1851 5323 1831 5324 1831 5325 1851 5326 1842 5327 1808 5328 1864 5329 1810 5330 1810 5331 1864 5332 1811 5333 1811 5334 1864 5335 1812 5336 1812 5337 1864 5338 1813 5339 1813 5340 1864 5341 1814 5342 1814 5343 1864 5344 1815 5345 1815 5346 1864 5347 1816 5348 1816 5349 1864 5350 1852 5351 1817 5352 1816 5353 1852 5354 1852 5355 1831 5356 1830 5357 1832 5358 1831 5359 1842 5360 1852 5361 1830 5362 1829 5363 1818 5364 1817 5365 1852 5366 1833 5367 1832 5368 1842 5369 1818 5370 1852 5371 1829 5372 1818 5373 1829 5374 1828 5375 1833 5376 1842 5377 1841 5378 1819 5379 1818 5380 1828 5381 1834 5382 1833 5383 1841 5384 1819 5385 1828 5386 1827 5387 1820 5388 1819 5389 1827 5390 1835 5391 1834 5392 1841 5393 1820 5394 1827 5395 1826 5396 1820 5397 1826 5398 1825 5399 1821 5400 1820 5401 1825 5402 1836 5403 1835 5404 1841 5405 1836 5406 1841 5407 1840 5408 1808 5409 1810 5410 1809 5411 1821 5412 1825 5413 1824 5414 1822 5415 1821 5416 1824 5417 1837 5418 1836 5419 1840 5420 1837 5421 1840 5422 1839 5423 1823 5424 1822 5425 1824 5426 1838 5427 1837 5428 1839 5429 1877 5430 1876 5431 1875 5432 1878 5433 1877 5434 1875 5435 1878 5436 1875 5437 1874 5438 1879 5439 1878 5440 1874 5441 1879 5442 1874 5443 1873 5444 1880 5445 1879 5446 1873 5447 1880 5448 1873 5449 1872 5450 1881 5451 1880 5452 1872 5453 1881 5454 1872 5455 1871 5456 1882 5457 1881 5458 1871 5459 1882 5460 1871 5461 1870 5462 1883 5463 1882 5464 1870 5465 1883 5466 1870 5467 1893 5468 1884 5469 1883 5470 1893 5471 1884 5472 1893 5473 1892 5474 1885 5475 1884 5476 1892 5477 1885 5478 1892 5479 1891 5480 1886 5481 1885 5482 1891 5483 1886 5484 1891 5485 1890 5486 1887 5487 1886 5488 1890 5489 1887 5490 1890 5491 1889 5492 1888 5493 1887 5494 1889 5495 1868 5496 1867 5497 1866 5498 1868 5499 1866 5500 1869 5501 1914 5502 1913 5503 1912 5504 1915 5505 1914 5506 1912 5507 1915 5508 1912 5509 1911 5510 1916 5511 1915 5512 1911 5513 1917 5514 1916 5515 1911 5516 1917 5517 1911 5518 1910 5519 1918 5520 1917 5521 1910 5522 1918 5523 1910 5524 1909 5525 1919 5526 1918 5527 1909 5528 1920 5529 1919 5530 1921 5531 1921 5532 1919 5533 1922 5534 1922 5535 1919 5536 1923 5537 1923 5538 1919 5539 1924 5540 1924 5541 1919 5542 1925 5543 1925 5544 1919 5545 1926 5546 1926 5547 1919 5548 1909 5549 1926 5550 1909 5551 1927 5552 1927 5553 1909 5554 1908 5555 1928 5556 1927 5557 1908 5558 1929 5559 1928 5560 1908 5561 1929 5562 1908 5563 1907 5564 1930 5565 1929 5566 1907 5567 1931 5568 1930 5569 1907 5570 1932 5571 1931 5572 1907 5573 1932 5574 1907 5575 1906 5576 1933 5577 1932 5578 1906 5579 1934 5580 1933 5581 1983 5582 1983 5583 1933 5584 1906 5585 1935 5586 1934 5587 1983 5588 1936 5589 1935 5590 1983 5591 1936 5592 1983 5593 1982 5594 1965 5595 1983 5596 1906 5597 1937 5598 1936 5599 1982 5600 1937 5601 1982 5602 1981 5603 1938 5604 1937 5605 1981 5606 1938 5607 1981 5608 1980 5609 1938 5610 1980 5611 1979 5612 1939 5613 1938 5614 1979 5615 1939 5616 1979 5617 1978 5618 1939 5619 1978 5620 1977 5621 1940 5622 1939 5623 1977 5624 1940 5625 1977 5626 1976 5627 1941 5628 1940 5629 1976 5630 1941 5631 1976 5632 1975 5633 1966 5634 1965 5635 1906 5636 1941 5637 1975 5638 1974 5639 1967 5640 1966 5641 1906 5642 1895 5643 1894 5644 1964 5645 1967 5646 1906 5647 1905 5648 1896 5649 1895 5650 1964 5651 1942 5652 1941 5653 1974 5654 1942 5655 1974 5656 1973 5657 1967 5658 1905 5659 1904 5660 1968 5661 1967 5662 1904 5663 1897 5664 1896 5665 1964 5666 1968 5667 1904 5668 1903 5669 1969 5670 1968 5671 1903 5672 1898 5673 1897 5674 1964 5675 1942 5676 1973 5677 1972 5678 1969 5679 1903 5680 1902 5681 1899 5682 1898 5683 1964 5684 1970 5685 1969 5686 1902 5687 1970 5688 1902 5689 1901 5690 1900 5691 1899 5692 1964 5693 1970 5694 1901 5695 1900 5696 1942 5697 1972 5698 1971 5699 1970 5700 1900 5701 1964 5702 1971 5703 1970 5704 1964 5705 1942 5706 1971 5707 1952 5708 1952 5709 1971 5710 1964 5711 1943 5712 1942 5713 1952 5714 1943 5715 1952 5716 1951 5717 1953 5718 1952 5719 1964 5720 1953 5721 1964 5722 1963 5723 1944 5724 1943 5725 1951 5726 1944 5727 1951 5728 1950 5729 1954 5730 1953 5731 1963 5732 1954 5733 1963 5734 1962 5735 1944 5736 1950 5737 1949 5738 1955 5739 1954 5740 1962 5741 1945 5742 1944 5743 1949 5744 1955 5745 1962 5746 1961 5747 1945 5748 1949 5749 1948 5750 1956 5751 1955 5752 1961 5753 1956 5754 1961 5755 1960 5756 1945 5757 1948 5758 1947 5759 1957 5760 1956 5761 1960 5762 1946 5763 1945 5764 1947 5765 1957 5766 1960 5767 1959 5768 1958 5769 1957 5770 1959 5771 2004 5772 2003 5773 2002 5774 2004 5775 2002 5776 2001 5777 2005 5778 2004 5779 2001 5780 2005 5781 2001 5782 2000 5783 2006 5784 2005 5785 2000 5786 2006 5787 2000 5788 2028 5789 2028 5790 2000 5791 2029 5792 2029 5793 2000 5794 1999 5795 2007 5796 2006 5797 2027 5798 2027 5799 2006 5800 2028 5801 2007 5802 2027 5803 2026 5804 2030 5805 2029 5806 1999 5807 2007 5808 2026 5809 2025 5810 2031 5811 2030 5812 1999 5813 2007 5814 2025 5815 2024 5816 2032 5817 2031 5818 1999 5819 2008 5820 2007 5821 2024 5822 2032 5823 1999 5824 1998 5825 2008 5826 2024 5827 2023 5828 2033 5829 2032 5830 1998 5831 2008 5832 2023 5833 2022 5834 2034 5835 2033 5836 1998 5837 2009 5838 2008 5839 2022 5840 2034 5841 1998 5842 1997 5843 2009 5844 2022 5845 2034 5846 2009 5847 2034 5848 1997 5849 2010 5850 2009 5851 1996 5852 1996 5853 2009 5854 1997 5855 2010 5856 1996 5857 1995 5858 2010 5859 1995 5860 1994 5861 2011 5862 2010 5863 1994 5864 2011 5865 1994 5866 1993 5867 1985 5868 1984 5869 2021 5870 1986 5871 1985 5872 2021 5873 2012 5874 2011 5875 1993 5876 2012 5877 1993 5878 1992 5879 1987 5880 1986 5881 2021 5882 2012 5883 1992 5884 1991 5885 1988 5886 1987 5887 2021 5888 1989 5889 1988 5890 2021 5891 2012 5892 1991 5893 1990 5894 1990 5895 1989 5896 2021 5897 2012 5898 1990 5899 2021 5900 2013 5901 2012 5902 2021 5903 2013 5904 2021 5905 2020 5906 2013 5907 2020 5908 2019 5909 2014 5910 2013 5911 2019 5912 2014 5913 2019 5914 2018 5915 2014 5916 2018 5917 2017 5918 2015 5919 2014 5920 2017 5921 2015 5922 2017 5923 2016 5924 2042 5925 2041 5926 2040 5927 2042 5928 2040 5929 2039 5930 2043 5931 2042 5932 2039 5933 2043 5934 2039 5935 2038 5936 2043 5937 2038 5938 2037 5939 2044 5940 2043 5941 2037 5942 2044 5943 2037 5944 2036 5945 2044 5946 2036 5947 2035 5948 2045 5949 2044 5950 2035 5951 2045 5952 2035 5953 2096 5954 2096 5955 2035 5956 2097 5957 2097 5958 2035 5959 2098 5960 2098 5961 2035 5962 2099 5963 2099 5964 2035 5965 2100 5966 2100 5967 2035 5968 2101 5969 2101 5970 2035 5971 2102 5972 2046 5973 2045 5974 2096 5975 2046 5976 2096 5977 2095 5978 2046 5979 2095 5980 2094 5981 2046 5982 2094 5983 2093 5984 2047 5985 2046 5986 2093 5987 2047 5988 2093 5989 2092 5990 2047 5991 2092 5992 2091 5993 2047 5994 2091 5995 2090 5996 2047 5997 2090 5998 2089 5999 2048 6000 2047 6001 2089 6002 2048 6003 2089 6004 2088 6005 2048 6006 2088 6007 2087 6008 2048 6009 2087 6010 2086 6011 2048 6012 2086 6013 2085 6014 2049 6015 2048 6016 2085 6017 2049 6018 2085 6019 2084 6020 2049 6021 2084 6022 2083 6023 2050 6024 2049 6025 2083 6026 2050 6027 2083 6028 2082 6029 2051 6030 2050 6031 2082 6032 2051 6033 2082 6034 2081 6035 2051 6036 2081 6037 2080 6038 2052 6039 2051 6040 2080 6041 2052 6042 2080 6043 2079 6044 2053 6045 2052 6046 2079 6047 2053 6048 2079 6049 2078 6050 2066 6051 2065 6052 2064 6053 2053 6054 2078 6055 2077 6056 2054 6057 2053 6058 2077 6059 2066 6060 2064 6061 2063 6062 2055 6063 2054 6064 2077 6065 2066 6066 2063 6067 2062 6068 2056 6069 2055 6070 2077 6071 2056 6072 2077 6073 2076 6074 2066 6075 2062 6076 2061 6077 2057 6078 2056 6079 2076 6080 2058 6081 2057 6082 2076 6083 2066 6084 2061 6085 2060 6086 2059 6087 2058 6088 2076 6089 2066 6090 2060 6091 2059 6092 2066 6093 2059 6094 2076 6095 2066 6096 2076 6097 2075 6098 2067 6099 2066 6100 2075 6101 2067 6102 2075 6103 2074 6104 2068 6105 2067 6106 2074 6107 2069 6108 2068 6109 2074 6110 2069 6111 2074 6112 2073 6113 2070 6114 2069 6115 2073 6116 2070 6117 2073 6118 2072 6119 2071 6120 2070 6121 2072 6122 2121 6123 2120 6124 2119 6125 2121 6126 2119 6127 2118 6128 2106 6129 2105 6130 2104 6131 2106 6132 2104 6133 2103 6134 2122 6135 2121 6136 2118 6137 2122 6138 2118 6139 2117 6140 2122 6141 2117 6142 2116 6143 2107 6144 2106 6145 2103 6146 2123 6147 2122 6148 2116 6149 2123 6150 2116 6151 2115 6152 2108 6153 2107 6154 2103 6155 2109 6156 2108 6157 2133 6158 2133 6159 2108 6160 2103 6161 2123 6162 2115 6163 2114 6164 2110 6165 2109 6166 2133 6167 2123 6168 2114 6169 2113 6170 2124 6171 2123 6172 2113 6173 2111 6174 2110 6175 2133 6176 2124 6177 2113 6178 2112 6179 2112 6180 2111 6181 2133 6182 2124 6183 2112 6184 2133 6185 2124 6186 2133 6187 2132 6188 2134 6189 2133 6190 2103 6191 2124 6192 2132 6193 2131 6194 2125 6195 2124 6196 2131 6197 2125 6198 2131 6199 2130 6200 2126 6201 2125 6202 2130 6203 2126 6204 2130 6205 2129 6206 2126 6207 2129 6208 2128 6209 2127 6210 2126 6211 2128 6212 2136 6213 2135 6214 2158 6215 2136 6216 2158 6217 2157 6218 2137 6219 2136 6220 2157 6221 2137 6222 2157 6223 2156 6224 2138 6225 2137 6226 2156 6227 2138 6228 2156 6229 2159 6230 2159 6231 2156 6232 2160 6233 2160 6234 2156 6235 2155 6236 2139 6237 2138 6238 2182 6239 2182 6240 2138 6241 2159 6242 2139 6243 2182 6244 2181 6245 2161 6246 2160 6247 2155 6248 2139 6249 2181 6250 2180 6251 2162 6252 2161 6253 2155 6254 2162 6255 2155 6256 2154 6257 2140 6258 2139 6259 2180 6260 2140 6261 2180 6262 2179 6263 2163 6264 2162 6265 2154 6266 2140 6267 2179 6268 2178 6269 2164 6270 2163 6271 2154 6272 2164 6273 2154 6274 2153 6275 2141 6276 2140 6277 2178 6278 2141 6279 2178 6280 2177 6281 2165 6282 2164 6283 2153 6284 2142 6285 2141 6286 2177 6287 2142 6288 2177 6289 2176 6290 2165 6291 2153 6292 2152 6293 2166 6294 2165 6295 2152 6296 2142 6297 2176 6298 2175 6299 2167 6300 2166 6301 2152 6302 2143 6303 2142 6304 2175 6305 2167 6306 2152 6307 2151 6308 2143 6309 2175 6310 2174 6311 2168 6312 2167 6313 2151 6314 2143 6315 2174 6316 2173 6317 2169 6318 2168 6319 2151 6320 2144 6321 2143 6322 2173 6323 2169 6324 2151 6325 2150 6326 2144 6327 2173 6328 2172 6329 2170 6330 2169 6331 2150 6332 2144 6333 2172 6334 2171 6335 2171 6336 2170 6337 2150 6338 2144 6339 2171 6340 2150 6341 2145 6342 2144 6343 2150 6344 2145 6345 2150 6346 2149 6347 2146 6348 2145 6349 2149 6350 2146 6351 2149 6352 2148 6353 2147 6354 2146 6355 2148 6356 2188 6357 2187 6358 2186 6359 2188 6360 2186 6361 2190 6362 2190 6363 2186 6364 2191 6365 2191 6366 2186 6367 2185 6368 2185 6369 2184 6370 2183 6371 2185 6372 2183 6373 2194 6374 2194 6375 2183 6376 2195 6377 2195 6378 2183 6379 2197 6380 2188 6381 2190 6382 2189 6383 2192 6384 2191 6385 2185 6386 2185 6387 2194 6388 2193 6389 2196 6390 2195 6391 2197 6392 2192 6393 2185 6394 2193 6395 2199 6396 2198 6397 2231 6398 2199 6399 2231 6400 2230 6401 2199 6402 2230 6403 2229 6404 2200 6405 2199 6406 2229 6407 2201 6408 2200 6409 2229 6410 2202 6411 2201 6412 2228 6413 2228 6414 2201 6415 2229 6416 2202 6417 2228 6418 2227 6419 2202 6420 2227 6421 2226 6422 2203 6423 2202 6424 2226 6425 2203 6426 2226 6427 2225 6428 2216 6429 2215 6430 2214 6431 2203 6432 2225 6433 2224 6434 2217 6435 2216 6436 2214 6437 2204 6438 2203 6439 2224 6440 2218 6441 2217 6442 2214 6443 2204 6444 2224 6445 2223 6446 2219 6447 2218 6448 2214 6449 2204 6450 2223 6451 2222 6452 2220 6453 2219 6454 2214 6455 2204 6456 2222 6457 2221 6458 2221 6459 2220 6460 2214 6461 2204 6462 2221 6463 2214 6464 2205 6465 2204 6466 2214 6467 2206 6468 2205 6469 2214 6470 2206 6471 2214 6472 2213 6473 2206 6474 2213 6475 2212 6476 2207 6477 2206 6478 2212 6479 2207 6480 2212 6481 2211 6482 2207 6483 2211 6484 2210 6485 2208 6486 2207 6487 2210 6488 2208 6489 2210 6490 2209 6491 2239 6492 2238 6493 2237 6494 2239 6495 2237 6496 2236 6497 2240 6498 2239 6499 2236 6500 2240 6501 2236 6502 2235 6503 2240 6504 2235 6505 2234 6506 2241 6507 2240 6508 2234 6509 2241 6510 2234 6511 2233 6512 2241 6513 2233 6514 2232 6515 2242 6516 2241 6517 2232 6518 2242 6519 2232 6520 2293 6521 2293 6522 2232 6523 2294 6524 2294 6525 2232 6526 2295 6527 2295 6528 2232 6529 2296 6530 2296 6531 2232 6532 2297 6533 2297 6534 2232 6535 2298 6536 2298 6537 2232 6538 2299 6539 2243 6540 2242 6541 2293 6542 2243 6543 2293 6544 2292 6545 2243 6546 2292 6547 2291 6548 2243 6549 2291 6550 2290 6551 2244 6552 2243 6553 2290 6554 2244 6555 2290 6556 2289 6557 2244 6558 2289 6559 2288 6560 2244 6561 2288 6562 2287 6563 2244 6564 2287 6565 2286 6566 2245 6567 2244 6568 2286 6569 2245 6570 2286 6571 2285 6572 2245 6573 2285 6574 2284 6575 2245 6576 2284 6577 2283 6578 2245 6579 2283 6580 2282 6581 2246 6582 2245 6583 2282 6584 2246 6585 2282 6586 2281 6587 2246 6588 2281 6589 2280 6590 2247 6591 2246 6592 2280 6593 2247 6594 2280 6595 2279 6596 2248 6597 2247 6598 2279 6599 2248 6600 2279 6601 2278 6602 2248 6603 2278 6604 2277 6605 2249 6606 2248 6607 2277 6608 2249 6609 2277 6610 2276 6611 2250 6612 2249 6613 2276 6614 2250 6615 2276 6616 2275 6617 2263 6618 2262 6619 2261 6620 2250 6621 2275 6622 2274 6623 2251 6624 2250 6625 2274 6626 2263 6627 2261 6628 2260 6629 2252 6630 2251 6631 2274 6632 2263 6633 2260 6634 2259 6635 2253 6636 2252 6637 2274 6638 2253 6639 2274 6640 2273 6641 2263 6642 2259 6643 2258 6644 2254 6645 2253 6646 2273 6647 2255 6648 2254 6649 2273 6650 2263 6651 2258 6652 2257 6653 2256 6654 2255 6655 2273 6656 2263 6657 2257 6658 2256 6659 2263 6660 2256 6661 2273 6662 2263 6663 2273 6664 2272 6665 2264 6666 2263 6667 2272 6668 2264 6669 2272 6670 2271 6671 2265 6672 2264 6673 2271 6674 2266 6675 2265 6676 2271 6677 2266 6678 2271 6679 2270 6680 2267 6681 2266 6682 2270 6683 2267 6684 2270 6685 2269 6686 2268 6687 2267 6688 2269 6689 2320 6690 2319 6691 2318 6692 2320 6693 2318 6694 2317 6695 2321 6696 2320 6697 2317 6698 2321 6699 2317 6700 2316 6701 2322 6702 2321 6703 2316 6704 2322 6705 2316 6706 2344 6707 2344 6708 2316 6709 2345 6710 2345 6711 2316 6712 2315 6713 2323 6714 2322 6715 2343 6716 2343 6717 2322 6718 2344 6719 2323 6720 2343 6721 2342 6722 2346 6723 2345 6724 2315 6725 2323 6726 2342 6727 2341 6728 2347 6729 2346 6730 2315 6731 2323 6732 2341 6733 2340 6734 2348 6735 2347 6736 2315 6737 2324 6738 2323 6739 2340 6740 2348 6741 2315 6742 2314 6743 2324 6744 2340 6745 2339 6746 2349 6747 2348 6748 2314 6749 2324 6750 2339 6751 2338 6752 2350 6753 2349 6754 2314 6755 2325 6756 2324 6757 2338 6758 2350 6759 2314 6760 2313 6761 2325 6762 2338 6763 2350 6764 2325 6765 2350 6766 2313 6767 2326 6768 2325 6769 2312 6770 2312 6771 2325 6772 2313 6773 2326 6774 2312 6775 2311 6776 2326 6777 2311 6778 2310 6779 2327 6780 2326 6781 2310 6782 2327 6783 2310 6784 2309 6785 2301 6786 2300 6787 2337 6788 2302 6789 2301 6790 2337 6791 2328 6792 2327 6793 2309 6794 2328 6795 2309 6796 2308 6797 2303 6798 2302 6799 2337 6800 2328 6801 2308 6802 2307 6803 2304 6804 2303 6805 2337 6806 2305 6807 2304 6808 2337 6809 2328 6810 2307 6811 2306 6812 2306 6813 2305 6814 2337 6815 2328 6816 2306 6817 2337 6818 2329 6819 2328 6820 2337 6821 2329 6822 2337 6823 2336 6824 2329 6825 2336 6826 2335 6827 2330 6828 2329 6829 2335 6830 2330 6831 2335 6832 2334 6833 2330 6834 2334 6835 2333 6836 2331 6837 2330 6838 2333 6839 2331 6840 2333 6841 2332 6842 2353 6843 2352 6844 2351 6845 2353 6846 2351 6847 2358 6848 2354 6849 2353 6850 2358 6851 2355 6852 2354 6853 2357 6854 2357 6855 2354 6856 2358 6857 2355 6858 2357 6859 2356 6860 2366 6861 2365 6862 2364 6863 2366 6864 2364 6865 2363 6866 2367 6867 2366 6868 2363 6869 2367 6870 2363 6871 2362 6872 2367 6873 2362 6874 2361 6875 2368 6876 2367 6877 2361 6878 2368 6879 2361 6880 2360 6881 2368 6882 2360 6883 2359 6884 2369 6885 2368 6886 2359 6887 2369 6888 2359 6889 2420 6890 2420 6891 2359 6892 2421 6893 2421 6894 2359 6895 2422 6896 2422 6897 2359 6898 2423 6899 2423 6900 2359 6901 2424 6902 2424 6903 2359 6904 2425 6905 2425 6906 2359 6907 2426 6908 2370 6909 2369 6910 2420 6911 2370 6912 2420 6913 2419 6914 2370 6915 2419 6916 2418 6917 2370 6918 2418 6919 2417 6920 2371 6921 2370 6922 2417 6923 2371 6924 2417 6925 2416 6926 2371 6927 2416 6928 2415 6929 2371 6930 2415 6931 2414 6932 2371 6933 2414 6934 2413 6935 2372 6936 2371 6937 2413 6938 2372 6939 2413 6940 2412 6941 2372 6942 2412 6943 2411 6944 2372 6945 2411 6946 2410 6947 2372 6948 2410 6949 2409 6950 2373 6951 2372 6952 2409 6953 2373 6954 2409 6955 2408 6956 2373 6957 2408 6958 2407 6959 2374 6960 2373 6961 2407 6962 2374 6963 2407 6964 2406 6965 2375 6966 2374 6967 2406 6968 2375 6969 2406 6970 2405 6971 2375 6972 2405 6973 2404 6974 2376 6975 2375 6976 2404 6977 2376 6978 2404 6979 2403 6980 2377 6981 2376 6982 2403 6983 2377 6984 2403 6985 2402 6986 2390 6987 2389 6988 2388 6989 2377 6990 2402 6991 2401 6992 2378 6993 2377 6994 2401 6995 2390 6996 2388 6997 2387 6998 2379 6999 2378 7000 2401 7001 2390 7002 2387 7003 2386 7004 2380 7005 2379 7006 2401 7007 2380 7008 2401 7009 2400 7010 2390 7011 2386 7012 2385 7013 2381 7014 2380 7015 2400 7016 2382 7017 2381 7018 2400 7019 2390 7020 2385 7021 2384 7022 2383 7023 2382 7024 2400 7025 2390 7026 2384 7027 2383 7028 2390 7029 2383 7030 2400 7031 2390 7032 2400 7033 2399 7034 2391 7035 2390 7036 2399 7037 2391 7038 2399 7039 2398 7040 2392 7041 2391 7042 2398 7043 2393 7044 2392 7045 2398 7046 2393 7047 2398 7048 2397 7049 2394 7050 2393 7051 2397 7052 2394 7053 2397 7054 2396 7055 2395 7056 2394 7057 2396 7058 2434 7059 2433 7060 2432 7061 2434 7062 2432 7063 2431 7064 2434 7065 2431 7066 2430 7067 2435 7068 2434 7069 2430 7070 2435 7071 2430 7072 2429 7073 2435 7074 2429 7075 2428 7076 2435 7077 2428 7078 2427 7079 2436 7080 2435 7081 2427 7082 2436 7083 2427 7084 2470 7085 2470 7086 2427 7087 2471 7088 2471 7089 2427 7090 2472 7091 2472 7092 2427 7093 2473 7094 2473 7095 2427 7096 2474 7097 2474 7098 2427 7099 2475 7100 2475 7101 2427 7102 2476 7103 2437 7104 2436 7105 2469 7106 2469 7107 2436 7108 2470 7109 2437 7110 2469 7111 2468 7112 2437 7113 2468 7114 2467 7115 2438 7116 2437 7117 2467 7118 2438 7119 2467 7120 2466 7121 2438 7122 2466 7123 2465 7124 2439 7125 2438 7126 2465 7127 2439 7128 2465 7129 2464 7130 2439 7131 2464 7132 2463 7133 2440 7134 2439 7135 2463 7136 2440 7137 2463 7138 2462 7139 2441 7140 2440 7141 2462 7142 2441 7143 2462 7144 2461 7145 2441 7146 2461 7147 2460 7148 2453 7149 2452 7150 2451 7151 2442 7152 2441 7153 2460 7154 2454 7155 2453 7156 2451 7157 2442 7158 2460 7159 2459 7160 2455 7161 2454 7162 2451 7163 2456 7164 2455 7165 2451 7166 2442 7167 2459 7168 2458 7169 2457 7170 2456 7171 2451 7172 2458 7173 2457 7174 2451 7175 2442 7176 2458 7177 2451 7178 2443 7179 2442 7180 2451 7181 2444 7182 2443 7183 2451 7184 2444 7185 2451 7186 2450 7187 2444 7188 2450 7189 2449 7190 2444 7191 2449 7192 2448 7193 2444 7194 2448 7195 2447 7196 2445 7197 2444 7198 2447 7199 2445 7200 2447 7201 2446 7202 2488 7203 2487 7204 2486 7205 2489 7206 2488 7207 2486 7208 2489 7209 2486 7210 2485 7211 2490 7212 2489 7213 2485 7214 2490 7215 2485 7216 2484 7217 2491 7218 2490 7219 2484 7220 2491 7221 2484 7222 2483 7223 2492 7224 2491 7225 2483 7226 2492 7227 2483 7228 2482 7229 2493 7230 2492 7231 2482 7232 2493 7233 2482 7234 2481 7235 2494 7236 2493 7237 2481 7238 2494 7239 2481 7240 2504 7241 2494 7242 2504 7243 2503 7244 2495 7245 2494 7246 2503 7247 2495 7248 2503 7249 2502 7250 2496 7251 2495 7252 2502 7253 2496 7254 2502 7255 2501 7256 2497 7257 2496 7258 2501 7259 2497 7260 2501 7261 2500 7262 2498 7263 2497 7264 2500 7265 2498 7266 2500 7267 2499 7268 2479 7269 2478 7270 2477 7271 2479 7272 2477 7273 2480 7274 2512 7275 2511 7276 2510 7277 2512 7278 2510 7279 2509 7280 2513 7281 2512 7282 2509 7283 2513 7284 2509 7285 2508 7286 2513 7287 2508 7288 2507 7289 2514 7290 2513 7291 2507 7292 2514 7293 2507 7294 2506 7295 2514 7296 2506 7297 2505 7298 2515 7299 2514 7300 2505 7301 2515 7302 2505 7303 2566 7304 2566 7305 2505 7306 2567 7307 2567 7308 2505 7309 2568 7310 2568 7311 2505 7312 2569 7313 2569 7314 2505 7315 2570 7316 2570 7317 2505 7318 2571 7319 2571 7320 2505 7321 2572 7322 2516 7323 2515 7324 2566 7325 2516 7326 2566 7327 2565 7328 2516 7329 2565 7330 2564 7331 2516 7332 2564 7333 2563 7334 2517 7335 2516 7336 2563 7337 2517 7338 2563 7339 2562 7340 2517 7341 2562 7342 2561 7343 2517 7344 2561 7345 2560 7346 2517 7347 2560 7348 2559 7349 2518 7350 2517 7351 2559 7352 2518 7353 2559 7354 2558 7355 2518 7356 2558 7357 2557 7358 2518 7359 2557 7360 2556 7361 2518 7362 2556 7363 2555 7364 2519 7365 2518 7366 2555 7367 2519 7368 2555 7369 2554 7370 2519 7371 2554 7372 2553 7373 2520 7374 2519 7375 2553 7376 2520 7377 2553 7378 2552 7379 2521 7380 2520 7381 2552 7382 2521 7383 2552 7384 2551 7385 2521 7386 2551 7387 2550 7388 2522 7389 2521 7390 2550 7391 2522 7392 2550 7393 2549 7394 2523 7395 2522 7396 2549 7397 2523 7398 2549 7399 2548 7400 2536 7401 2535 7402 2534 7403 2523 7404 2548 7405 2547 7406 2524 7407 2523 7408 2547 7409 2536 7410 2534 7411 2533 7412 2525 7413 2524 7414 2547 7415 2536 7416 2533 7417 2532 7418 2526 7419 2525 7420 2547 7421 2526 7422 2547 7423 2546 7424 2536 7425 2532 7426 2531 7427 2527 7428 2526 7429 2546 7430 2528 7431 2527 7432 2546 7433 2536 7434 2531 7435 2530 7436 2529 7437 2528 7438 2546 7439 2536 7440 2530 7441 2529 7442 2536 7443 2529 7444 2546 7445 2536 7446 2546 7447 2545 7448 2537 7449 2536 7450 2545 7451 2537 7452 2545 7453 2544 7454 2538 7455 2537 7456 2544 7457 2539 7458 2538 7459 2544 7460 2539 7461 2544 7462 2543 7463 2540 7464 2539 7465 2543 7466 2540 7467 2543 7468 2542 7469 2541 7470 2540 7471 2542 7472 2578 7473 2577 7474 2576 7475 2578 7476 2576 7477 2575 7478 2575 7479 2574 7480 2573 7481 2575 7482 2573 7483 2580 7484 2578 7485 2575 7486 2580 7487 2579 7488 2578 7489 2580 7490 2583 7491 2582 7492 2581 7493 2583 7494 2581 7495 2613 7496 2607 7497 2606 7498 2605 7499 2608 7500 2607 7501 2605 7502 2608 7503 2605 7504 2604 7505 2609 7506 2608 7507 2604 7508 2610 7509 2609 7510 2604 7511 2610 7512 2604 7513 2603 7514 2611 7515 2610 7516 2603 7517 2611 7518 2603 7519 2602 7520 2612 7521 2611 7522 2591 7523 2591 7524 2611 7525 2602 7526 2583 7527 2613 7528 2612 7529 2583 7530 2612 7531 2585 7532 2585 7533 2612 7534 2586 7535 2586 7536 2612 7537 2587 7538 2587 7539 2612 7540 2588 7541 2588 7542 2612 7543 2589 7544 2589 7545 2612 7546 2590 7547 2590 7548 2612 7549 2591 7550 2592 7551 2591 7552 2602 7553 2593 7554 2592 7555 2602 7556 2593 7557 2602 7558 2601 7559 2594 7560 2593 7561 2601 7562 2595 7563 2594 7564 2601 7565 2596 7566 2595 7567 2601 7568 2596 7569 2601 7570 2600 7571 2583 7572 2585 7573 2584 7574 2597 7575 2596 7576 2600 7577 2598 7578 2597 7579 2600 7580 2598 7581 2600 7582 2599 7583 2615 7584 2614 7585 2631 7586 2631 7587 2614 7588 2630 7589 2631 7590 2630 7591 2629 7592 2631 7593 2629 7594 2628 7595 2631 7596 2628 7597 2627 7598 2631 7599 2627 7600 2632 7601 2632 7602 2627 7603 2626 7604 2615 7605 2631 7606 2645 7607 2633 7608 2632 7609 2626 7610 2634 7611 2633 7612 2626 7613 2634 7614 2626 7615 2625 7616 2635 7617 2634 7618 2625 7619 2636 7620 2635 7621 2625 7622 2637 7623 2636 7624 2625 7625 2637 7626 2625 7627 2624 7628 2638 7629 2637 7630 2624 7631 2639 7632 2638 7633 2624 7634 2639 7635 2624 7636 2623 7637 2640 7638 2639 7639 2623 7640 2640 7641 2623 7642 2622 7643 2641 7644 2640 7645 2622 7646 2642 7647 2641 7648 2622 7649 2643 7650 2642 7651 2622 7652 2643 7653 2622 7654 2621 7655 2644 7656 2643 7657 2621 7658 2615 7659 2645 7660 2617 7661 2617 7662 2645 7663 2644 7664 2617 7665 2644 7666 2621 7667 2617 7668 2621 7669 2620 7670 2617 7671 2620 7672 2619 7673 2617 7674 2619 7675 2618 7676 2615 7677 2617 7678 2616 7679 2647 7680 2646 7681 2679 7682 2647 7683 2679 7684 2678 7685 2647 7686 2678 7687 2677 7688 2648 7689 2647 7690 2677 7691 2649 7692 2648 7693 2677 7694 2650 7695 2649 7696 2676 7697 2676 7698 2649 7699 2677 7700 2650 7701 2676 7702 2675 7703 2650 7704 2675 7705 2674 7706 2651 7707 2650 7708 2674 7709 2651 7710 2674 7711 2673 7712 2664 7713 2663 7714 2662 7715 2651 7716 2673 7717 2672 7718 2665 7719 2664 7720 2662 7721 2652 7722 2651 7723 2672 7724 2666 7725 2665 7726 2662 7727 2652 7728 2672 7729 2671 7730 2667 7731 2666 7732 2662 7733 2652 7734 2671 7735 2670 7736 2668 7737 2667 7738 2662 7739 2652 7740 2670 7741 2669 7742 2669 7743 2668 7744 2662 7745 2652 7746 2669 7747 2662 7748 2653 7749 2652 7750 2662 7751 2654 7752 2653 7753 2662 7754 2654 7755 2662 7756 2661 7757 2654 7758 2661 7759 2660 7760 2655 7761 2654 7762 2660 7763 2655 7764 2660 7765 2659 7766 2655 7767 2659 7768 2658 7769 2656 7770 2655 7771 2658 7772 2656 7773 2658 7774 2657 7775 2700 7776 2699 7777 2698 7778 2700 7779 2698 7780 2697 7781 2701 7782 2700 7783 2697 7784 2701 7785 2697 7786 2696 7787 2702 7788 2701 7789 2696 7790 2702 7791 2696 7792 2724 7793 2724 7794 2696 7795 2725 7796 2725 7797 2696 7798 2695 7799 2703 7800 2702 7801 2723 7802 2723 7803 2702 7804 2724 7805 2703 7806 2723 7807 2722 7808 2726 7809 2725 7810 2695 7811 2703 7812 2722 7813 2721 7814 2727 7815 2726 7816 2695 7817 2703 7818 2721 7819 2720 7820 2728 7821 2727 7822 2695 7823 2704 7824 2703 7825 2720 7826 2728 7827 2695 7828 2694 7829 2704 7830 2720 7831 2719 7832 2729 7833 2728 7834 2694 7835 2704 7836 2719 7837 2718 7838 2730 7839 2729 7840 2694 7841 2705 7842 2704 7843 2718 7844 2730 7845 2694 7846 2693 7847 2705 7848 2718 7849 2730 7850 2705 7851 2730 7852 2693 7853 2706 7854 2705 7855 2692 7856 2692 7857 2705 7858 2693 7859 2706 7860 2692 7861 2691 7862 2706 7863 2691 7864 2690 7865 2707 7866 2706 7867 2690 7868 2707 7869 2690 7870 2689 7871 2681 7872 2680 7873 2717 7874 2682 7875 2681 7876 2717 7877 2708 7878 2707 7879 2689 7880 2708 7881 2689 7882 2688 7883 2683 7884 2682 7885 2717 7886 2708 7887 2688 7888 2687 7889 2684 7890 2683 7891 2717 7892 2685 7893 2684 7894 2717 7895 2708 7896 2687 7897 2686 7898 2686 7899 2685 7900 2717 7901 2708 7902 2686 7903 2717 7904 2709 7905 2708 7906 2717 7907 2709 7908 2717 7909 2716 7910 2709 7911 2716 7912 2715 7913 2710 7914 2709 7915 2715 7916 2710 7917 2715 7918 2714 7919 2710 7920 2714 7921 2713 7922 2711 7923 2710 7924 2713 7925 2711 7926 2713 7927 2712 7928 2733 7929 2732 7930 2731 7931 2733 7932 2731 7933 2734 7934 2737 7935 2736 7936 2735 7937 2737 7938 2735 7939 2738 7940 2757 7941 2756 7942 2755 7943 2757 7944 2755 7945 2754 7946 2742 7947 2741 7948 2740 7949 2742 7950 2740 7951 2739 7952 2758 7953 2757 7954 2754 7955 2758 7956 2754 7957 2753 7958 2758 7959 2753 7960 2752 7961 2743 7962 2742 7963 2739 7964 2759 7965 2758 7966 2752 7967 2759 7968 2752 7969 2751 7970 2744 7971 2743 7972 2739 7973 2745 7974 2744 7975 2769 7976 2769 7977 2744 7978 2739 7979 2759 7980 2751 7981 2750 7982 2746 7983 2745 7984 2769 7985 2759 7986 2750 7987 2749 7988 2760 7989 2759 7990 2749 7991 2747 7992 2746 7993 2769 7994 2760 7995 2749 7996 2748 7997 2748 7998 2747 7999 2769 8000 2760 8001 2748 8002 2769 8003 2760 8004 2769 8005 2768 8006 2770 8007 2769 8008 2739 8009 2760 8010 2768 8011 2767 8012 2761 8013 2760 8014 2767 8015 2761 8016 2767 8017 2766 8018 2762 8019 2761 8020 2766 8021 2762 8022 2766 8023 2765 8024 2762 8025 2765 8026 2764 8027 2763 8028 2762 8029 2764 8030 2771 8031 2798 8032 2799 8033 2799 8034 2798 8035 2797 8036 2799 8037 2797 8038 2796 8039 2799 8040 2796 8041 2795 8042 2799 8043 2795 8044 2794 8045 2799 8046 2794 8047 2800 8048 2800 8049 2794 8050 2793 8051 2771 8052 2799 8053 2813 8054 2801 8055 2800 8056 2793 8057 2801 8058 2793 8059 2792 8060 2802 8061 2801 8062 2792 8063 2803 8064 2802 8065 2792 8066 2804 8067 2803 8068 2792 8069 2804 8070 2792 8071 2791 8072 2805 8073 2804 8074 2791 8075 2806 8076 2805 8077 2791 8078 2806 8079 2791 8080 2790 8081 2807 8082 2806 8083 2790 8084 2807 8085 2790 8086 2789 8087 2808 8088 2807 8089 2789 8090 2808 8091 2789 8092 2788 8093 2809 8094 2808 8095 2788 8096 2809 8097 2788 8098 2787 8099 2810 8100 2809 8101 2787 8102 2811 8103 2810 8104 2787 8105 2811 8106 2787 8107 2786 8108 2812 8109 2811 8110 2786 8111 2771 8112 2813 8113 2814 8114 2814 8115 2813 8116 2812 8117 2814 8118 2812 8119 2786 8120 2814 8121 2786 8122 2785 8123 2814 8124 2785 8125 2784 8126 2814 8127 2784 8128 2783 8129 2814 8130 2783 8131 2782 8132 2814 8133 2782 8134 2815 8135 2815 8136 2782 8137 2781 8138 2771 8139 2814 8140 2828 8141 2816 8142 2815 8143 2781 8144 2817 8145 2816 8146 2781 8147 2817 8148 2781 8149 2780 8150 2818 8151 2817 8152 2780 8153 2819 8154 2818 8155 2780 8156 2819 8157 2780 8158 2779 8159 2820 8160 2819 8161 2779 8162 2820 8163 2779 8164 2778 8165 2821 8166 2820 8167 2778 8168 2822 8169 2821 8170 2778 8171 2822 8172 2778 8173 2777 8174 2823 8175 2822 8176 2777 8177 2824 8178 2823 8179 2777 8180 2824 8181 2777 8182 2776 8183 2825 8184 2824 8185 2776 8186 2826 8187 2825 8188 2776 8189 2826 8190 2776 8191 2775 8192 2827 8193 2826 8194 2775 8195 2771 8196 2828 8197 2827 8198 2771 8199 2827 8200 2775 8201 2771 8202 2775 8203 2774 8204 2771 8205 2774 8206 2773 8207 2771 8208 2773 8209 2772 8210

      +
      +
      +
      + + + + 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 0.0 -0.0 1.0 -0.0 0.0 -1.0 + + + + + + + + + + 0.62694 0.62694 -0.46245 0.73721 0.49257 -0.46245 0.81912 0.33927 -0.46245 0.86959 0.17295 -0.46245 0.88662 0.0 -0.46245 0.86959 -0.17295 -0.46245 0.81912 -0.33927 -0.46245 0.73721 -0.49257 -0.46245 0.62694 -0.62694 -0.46245 0.49257 -0.73721 -0.46245 0.33927 -0.81912 -0.46245 0.17295 -0.86959 -0.46245 0.0 -0.88662 -0.46245 -0.17295 -0.86959 -0.46245 -0.33927 -0.81912 -0.46245 -0.49257 -0.73721 -0.46245 -0.62694 -0.62694 -0.46245 -0.73721 -0.49257 -0.46245 -0.81912 -0.33927 -0.46245 -0.86959 -0.17295 -0.46245 -0.88662 0.0 -0.46245 -0.86959 0.17295 -0.46245 -0.81912 0.33927 -0.46245 -0.73721 0.49257 -0.46245 -0.62694 0.62694 -0.46245 -0.49257 0.73721 -0.46245 -0.33927 0.81915 -0.46245 -0.17295 0.86959 -0.46245 0.0 0.88662 -0.46245 0.17295 0.86959 -0.46245 0.33927 0.81912 -0.46245 0.49257 0.73721 -0.46245 0.0 0.0 1.0 0.0 0.0 -1.0 + + + + + + + + + + 0.89466 0.14214 1.02385 0.18062 0.53437 0.50208 0.53437 0.50208 0.77134 0.1159 0.89466 0.14214 0.53437 0.50208 0.65189 0.10064 0.77134 0.1159 0.53437 0.50208 0.53438 0.09564 0.65189 0.10064 0.53437 0.50208 0.41686 0.10064 0.53438 0.09564 0.53437 0.50208 0.29742 0.1159 0.41686 0.10064 0.53437 0.50208 0.17409 0.14214 0.29742 0.1159 0.53437 0.50208 0.0449 0.18062 0.17409 0.14214 0.53437 0.50208 -0.09221 0.23313 0.0449 0.18062 0.53437 0.50208 -0.23937 0.30206 -0.09221 0.23313 0.53437 0.50208 -0.39881 0.39046 -0.23937 0.30206 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.6137 -0.57289 0.50208 0.53437 0.50208 -0.23937 0.70209 -0.39881 0.6137 0.53437 0.50208 -0.09221 0.77103 -0.23937 0.70209 0.53437 0.50208 0.0449 0.82354 -0.09221 0.77103 0.53437 0.50208 0.17409 0.86202 0.0449 0.82354 0.53437 0.50208 0.29741 0.88826 0.17409 0.86202 0.53437 0.50208 0.41686 0.90351 0.29741 0.88826 0.53437 0.50208 0.53437 0.90852 0.41686 0.90351 0.53437 0.50208 0.65189 0.90351 0.53437 0.90852 0.53437 0.50208 0.77133 0.88826 0.65189 0.90351 0.53437 0.50208 0.89466 0.86202 0.77133 0.88826 0.53437 0.50208 1.02385 0.82354 0.89466 0.86202 0.53437 0.50208 1.16096 0.77103 1.02385 0.82354 0.53437 0.50208 1.30812 0.70209 1.16096 0.77103 0.53437 0.50208 1.46756 0.6137 1.30812 0.70209 0.53437 0.50208 1.64164 0.50208 1.46756 0.6137 0.53437 0.50208 1.46756 0.39046 1.64164 0.50208 0.53437 0.50208 1.30812 0.30207 1.46756 0.39046 0.53437 0.50208 1.16096 0.23313 1.30812 0.30207 0.53437 0.50208 1.02385 0.18062 1.16096 0.23313 0.53437 0.50208 1.02385 0.18062 0.89466 0.14214 0.53437 0.50208 0.89466 0.14214 0.77134 0.1159 0.53437 0.50208 0.77134 0.1159 0.65189 0.10064 0.53437 0.50208 0.65189 0.10064 0.53438 0.09564 0.53437 0.50208 0.53438 0.09564 0.41686 0.10064 0.53437 0.50208 0.41686 0.10064 0.29742 0.1159 0.53437 0.50208 0.29742 0.1159 0.17409 0.14214 0.53437 0.50208 0.17409 0.14214 0.0449 0.18062 0.53437 0.50208 0.0449 0.18062 -0.09221 0.23313 0.53437 0.50208 -0.09221 0.23313 -0.23937 0.30206 0.53437 0.50208 -0.23937 0.30206 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.39046 -0.57289 0.50208 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.6137 0.53437 0.50208 -0.39881 0.6137 -0.23937 0.70209 0.53437 0.50208 -0.23937 0.70209 -0.09221 0.77103 0.53437 0.50208 -0.09221 0.77103 0.0449 0.82354 0.53437 0.50208 0.0449 0.82354 0.17409 0.86202 0.53437 0.50208 0.17409 0.86202 0.29741 0.88826 0.53437 0.50208 0.29741 0.88826 0.41686 0.90351 0.53437 0.50208 0.41686 0.90351 0.53437 0.90852 0.53437 0.50208 0.53437 0.90852 0.65189 0.90351 0.53437 0.50208 0.65189 0.90351 0.77133 0.88826 0.53437 0.50208 0.77133 0.88826 0.89466 0.86202 0.53437 0.50208 0.89466 0.86202 1.02385 0.82354 0.53437 0.50208 1.02385 0.82354 1.16096 0.77103 0.53437 0.50208 1.16096 0.77103 1.30812 0.70209 0.53437 0.50208 1.30812 0.70209 1.46756 0.6137 0.53437 0.50208 1.46756 0.6137 1.64164 0.50208 0.53437 0.50208 1.64164 0.50208 1.46756 0.39046 0.53437 0.50208 1.46756 0.39046 1.30812 0.30207 0.53437 0.50208 1.30812 0.30207 1.16096 0.23313 1.16096 0.23313 1.02385 0.18062 0.53437 0.50208 + + + + + + + + + + + + + + +

      1 0 0 1 32 2 32 3 2 4 1 5 32 6 3 7 2 8 32 9 4 10 3 11 32 12 5 13 4 14 32 15 6 16 5 17 32 18 7 19 6 20 32 21 8 22 7 23 32 24 9 25 8 26 32 27 10 28 9 29 32 30 11 31 10 32 32 33 12 34 11 35 32 36 13 37 12 38 32 39 14 40 13 41 32 42 15 43 14 44 32 45 16 46 15 47 32 48 17 49 16 50 32 51 18 52 17 53 32 54 19 55 18 56 32 57 20 58 19 59 32 60 21 61 20 62 32 63 22 64 21 65 32 66 23 67 22 68 32 69 24 70 23 71 32 72 25 73 24 74 32 75 26 76 25 77 32 78 27 79 26 80 32 81 28 82 27 83 32 84 29 85 28 86 32 87 30 88 29 89 32 90 31 91 30 92 32 93 0 94 31 95 33 96 0 97 1 98 33 99 1 100 2 101 33 102 2 103 3 104 33 105 3 106 4 107 33 108 4 109 5 110 33 111 5 112 6 113 33 114 6 115 7 116 33 117 7 118 8 119 33 120 8 121 9 122 33 123 9 124 10 125 33 126 10 127 11 128 33 129 11 130 12 131 33 132 12 133 13 134 33 135 13 136 14 137 33 138 14 139 15 140 33 141 15 142 16 143 33 144 16 145 17 146 33 147 17 148 18 149 33 150 18 151 19 152 33 153 19 154 20 155 33 156 20 157 21 158 33 159 21 160 22 161 33 162 22 163 23 164 33 165 23 166 24 167 33 168 24 169 25 170 33 171 25 172 26 173 33 174 26 175 27 176 33 177 27 178 28 179 33 180 28 181 29 182 33 183 29 184 30 185 33 186 30 187 31 188 31 189 0 190 33 191

      +
      +
      +
      + + + + 1.19619 0.58226 -1.0 0.41454 -0.7869 -1.0 -1.39461 0.06574 -1.0 -0.80381 0.58226 -1.0 1.19619 0.58226 1.0 0.41454 -0.7869 1.0 -1.39461 0.06574 1.0 -0.80381 0.58226 1.0 + + + + + + + + + + 0.61278 0.35575 -0.70562 0.24885 -0.7882 -0.56285 -0.73128 -0.1023 -0.67431 -0.31007 0.82577 -0.47108 0.61278 0.35575 0.70562 0.24885 -0.7882 0.56285 -0.73128 -0.1023 0.67431 -0.31007 0.82577 0.47108 + + + + + + + + + + 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + + + + 1.12341 0.59904 -1.0 0.34176 -0.77012 -1.0 -1.46739 0.08252 -1.0 -0.87659 0.59904 -1.0 1.12341 0.59904 1.0 0.34176 -0.77012 1.0 -1.46739 0.08252 1.0 -0.87659 0.59904 1.0 + + + + + + + + + + 0.61278 0.35575 -0.70562 0.24885 -0.7882 -0.56285 -0.73128 -0.1023 -0.67431 -0.31007 0.82577 -0.47108 0.61278 0.35575 0.70562 0.24885 -0.7882 0.56285 -0.73128 -0.1023 0.67431 -0.31007 0.82577 0.47108 + + + + + + + + + + 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + + + + 1.35033 0.45305 -1.0 0.56868 -0.9161 -1.0 -1.24047 -0.06347 -1.0 -0.64967 0.45305 -1.0 1.35033 0.45305 1.0 0.56868 -0.9161 1.0 -1.24047 -0.06347 1.0 -0.64967 0.45305 1.0 + + + + + + + + + + 0.61278 0.35575 -0.70562 0.24885 -0.7882 -0.56285 -0.73128 -0.1023 -0.67431 -0.31007 0.82577 -0.47108 0.61278 0.35575 0.70562 0.24885 -0.7882 0.56285 -0.73128 -0.1023 0.67431 -0.31007 0.82577 0.47108 + + + + + + + + + + 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + + + + 0.0 -0.0 -1.41421 1.02332 -0.74348 -0.63246 -0.39087 -1.20299 -0.63246 -1.26491 -0.0 -0.63246 -0.39087 1.20299 -0.63246 1.02332 0.74348 -0.63246 0.39087 -1.20299 0.63246 -1.02332 -0.74348 0.63246 -1.02332 0.74348 0.63246 0.39087 1.20299 0.63246 1.26491 0.0 0.63246 -0.0 0.0 1.41421 0.6015 -0.43701 -1.20301 -0.22975 -0.7071 -1.20301 0.37175 -1.14412 -0.74351 0.6015 0.43701 -1.20301 1.203 -0.0 -0.7435 -0.74349 -0.0 -1.203 -0.97325 -0.7071 -0.7435 -0.22975 0.7071 -1.20301 -0.97325 0.7071 -0.7435 0.37175 1.14412 -0.74351 1.345 0.43701 -0.0 1.345 -0.43701 0.0 0.83125 -1.14412 0.0 -0.0 -1.41421 0.0 -0.83125 -1.14412 0.0 -1.345 -0.43701 0.0 -1.345 0.43701 -0.0 -0.83125 1.14412 -0.0 0.0 1.41421 -0.0 0.83125 1.14412 -0.0 0.97325 -0.7071 0.7435 -0.37175 -1.14412 0.74351 -1.203 0.0 0.7435 -0.37175 1.14412 0.74351 0.97325 0.7071 0.7435 0.74349 0.0 1.203 0.22975 -0.7071 1.20301 -0.6015 -0.43701 1.20301 -0.6015 0.43701 1.20301 0.22975 0.7071 1.20301 + + + + + + + + + + 0.0 0.0 -1.0 0.72359 -0.52571 -0.44719 -0.27638 -0.85064 -0.44719 -0.89441 0.0 -0.44719 -0.27638 0.85064 -0.44719 0.72359 0.52571 -0.44719 0.27638 -0.85064 0.44722 -0.72359 -0.52571 0.44719 -0.72359 0.52571 0.44719 0.27638 0.85064 0.44719 0.89441 0.0 0.44719 0.0 0.0 1.0 0.42531 -0.309 -0.85064 -0.16245 -0.49998 -0.85064 0.26286 -0.80898 -0.52571 0.42531 0.309 -0.85064 0.85064 0.0 -0.52571 -0.52571 0.0 -0.85064 -0.68816 -0.49998 -0.52571 -0.16245 0.49998 -0.85064 -0.68816 0.49998 -0.52571 0.26286 0.80898 -0.52571 0.95105 0.309 0.0 0.95105 -0.309 0.0 0.58776 -0.80902 0.0 0.0 -1.0 0.0 -0.58776 -0.80902 0.0 -0.95105 -0.309 0.0 -0.95105 0.309 0.0 -0.58776 0.80902 0.0 0.0 1.0 0.0 0.58776 0.80902 0.0 0.68816 -0.49998 0.52571 -0.26286 -0.80898 0.52571 -0.85064 0.0 0.52571 -0.26286 0.80898 0.52571 0.68816 0.49998 0.52571 0.52571 0.0 0.85064 0.16245 -0.49998 0.85064 -0.42531 -0.309 0.85064 -0.42531 0.309 0.85064 0.16245 0.49998 0.85064 + + + + + + + + + + 0.75311 0.11158 0.95018 0.21117 0.82689 0.27054 0.95018 0.21117 0.75311 0.11158 1.14943 0.09989 0.46246 0.11286 1.14943 0.09989 0.75311 0.11158 1.14943 0.09989 1.07744 0.2618 0.95018 0.21117 0.90005 0.39508 0.82689 0.27054 0.95018 0.21117 0.95018 0.21117 1.00617 0.39104 0.90005 0.39508 0.95447 0.53487 0.90005 0.39508 1.00617 0.39104 0.95018 0.21117 1.07744 0.2618 1.00617 0.39104 0.32261 0.22952 0.14943 0.09989 0.46246 0.11286 0.14943 0.09989 0.32261 0.22952 0.19133 0.29524 0.27674 0.38955 0.19133 0.29524 0.32261 0.22952 0.19133 0.29524 0.07744 0.2618 0.14943 0.09989 0.20413 0.49383 0.19133 0.29524 0.27674 0.38955 0.19133 0.29524 0.20413 0.49383 0.10855 0.42958 0.13244 0.59936 0.10855 0.42958 0.20413 0.49383 0.10855 0.42958 0.07744 0.2618 0.19133 0.29524 0.04129 0.57872 0.10855 0.42958 0.13244 0.59936 0.10855 0.42958 0.04129 0.57872 0.00617 0.39104 0.95447 0.53487 1.00617 0.39104 1.04129 0.57872 0.00617 0.39104 0.07744 0.2618 0.10855 0.42958 0.79899 0.43978 0.82689 0.27054 0.90005 0.39508 0.90005 0.39508 0.86836 0.58509 0.79899 0.43978 0.77674 0.61045 0.79899 0.43978 0.86836 0.58509 0.86836 0.58509 0.90005 0.39508 0.95447 0.53487 0.59019 0.23871 0.46246 0.11286 0.75311 0.11158 0.75311 0.11158 0.71658 0.30753 0.59019 0.23871 0.63244 0.40064 0.59019 0.23871 0.71658 0.30753 0.71658 0.30753 0.75311 0.11158 0.82689 0.27054 0.36836 0.41491 0.27674 0.38955 0.32261 0.22952 0.32261 0.22952 0.45654 0.28896 0.36836 0.41491 0.45447 0.46513 0.36836 0.41491 0.45654 0.28896 0.45654 0.28896 0.32261 0.22952 0.46246 0.11286 0.21658 0.69247 0.13244 0.59936 0.20413 0.49383 0.20413 0.49383 0.29899 0.56022 0.21658 0.69247 0.32689 0.72946 0.21658 0.69247 0.29899 0.56022 0.29899 0.56022 0.20413 0.49383 0.27674 0.38955 0.95654 0.71104 0.95447 0.53487 1.04129 0.57872 1.04129 0.57872 1.09019 0.76129 0.95654 0.71104 0.96246 0.88714 0.95654 0.71104 1.09019 0.76129 0.09019 0.76129 0.04129 0.57872 0.13244 0.59936 0.70413 0.50617 0.79899 0.43978 0.77674 0.61045 0.79899 0.43978 0.70413 0.50617 0.71658 0.30753 0.63244 0.40064 0.71658 0.30753 0.70413 0.50617 0.71658 0.30753 0.82689 0.27054 0.79899 0.43978 0.54129 0.42128 0.59019 0.23871 0.63244 0.40064 0.59019 0.23871 0.54129 0.42128 0.45654 0.28896 0.45447 0.46513 0.45654 0.28896 0.54129 0.42128 0.45654 0.28896 0.46246 0.11286 0.59019 0.23871 0.40005 0.60492 0.36836 0.41491 0.45447 0.46513 0.36836 0.41491 0.40005 0.60492 0.29899 0.56022 0.32689 0.72946 0.29899 0.56022 0.40005 0.60492 0.29899 0.56022 0.27674 0.38955 0.36836 0.41491 0.25311 0.88842 0.21658 0.69247 0.32689 0.72946 0.21658 0.69247 0.25311 0.88842 0.09019 0.76129 0.96246 0.88714 1.09019 0.76129 1.25311 0.88842 0.09019 0.76129 0.13244 0.59936 0.21658 0.69247 0.82261 0.77048 0.95654 0.71104 0.96246 0.88714 0.95654 0.71104 0.82261 0.77048 0.86836 0.58509 0.77674 0.61045 0.86836 0.58509 0.82261 0.77048 0.86836 0.58509 0.95447 0.53487 0.95654 0.71104 0.60855 0.57042 0.63244 0.40064 0.70413 0.50617 0.70413 0.50617 0.69133 0.70476 0.60855 0.57042 0.57744 0.7382 0.60855 0.57042 0.69133 0.70476 0.69133 0.70476 0.70413 0.50617 0.77674 0.61045 0.50617 0.60896 0.45447 0.46513 0.54129 0.42128 0.54129 0.42128 0.60855 0.57042 0.50617 0.60896 0.57744 0.7382 0.50617 0.60896 0.60855 0.57042 0.60855 0.57042 0.54129 0.42128 0.63244 0.40064 0.45018 0.78883 0.32689 0.72946 0.40005 0.60492 0.40005 0.60492 0.50617 0.60896 0.45018 0.78883 0.57744 0.7382 0.45018 0.78883 0.50617 0.60896 0.50617 0.60896 0.40005 0.60492 0.45447 0.46513 0.64943 0.90011 0.96246 0.88714 1.25311 0.88842 0.25311 0.88842 0.45018 0.78883 0.64943 0.90011 0.57744 0.7382 0.64943 0.90011 0.45018 0.78883 0.45018 0.78883 0.25311 0.88842 0.32689 0.72946 0.69133 0.70476 0.77674 0.61045 0.82261 0.77048 0.82261 0.77048 0.64943 0.90011 0.69133 0.70476 0.57744 0.7382 0.69133 0.70476 0.64943 0.90011 0.64943 0.90011 0.82261 0.77048 0.96246 0.88714 + + + + + + + + + + + + + + +

      14 0 12 1 1 2 12 3 14 4 13 5 2 6 13 7 14 8 13 9 0 10 12 11 16 12 1 13 12 14 12 15 15 16 16 17 5 18 16 19 15 20 12 21 0 22 15 23 18 24 13 25 2 26 13 27 18 28 17 29 3 30 17 31 18 32 17 33 0 34 13 35 20 36 17 37 3 38 17 39 20 40 19 41 4 42 19 43 20 44 19 45 0 46 17 47 21 48 19 49 4 50 19 51 21 52 15 53 5 54 15 55 21 56 15 57 0 58 19 59 23 60 1 61 16 62 16 63 22 64 23 65 10 66 23 67 22 68 22 69 16 70 5 71 25 72 2 73 14 74 14 75 24 76 25 77 6 78 25 79 24 80 24 81 14 82 1 83 27 84 3 85 18 86 18 87 26 88 27 89 7 90 27 91 26 92 26 93 18 94 2 95 29 96 4 97 20 98 20 99 28 100 29 101 8 102 29 103 28 104 28 105 20 106 3 107 31 108 5 109 21 110 21 111 30 112 31 113 9 114 31 115 30 116 30 117 21 118 4 119 32 120 23 121 10 122 23 123 32 124 24 125 6 126 24 127 32 128 24 129 1 130 23 131 33 132 25 133 6 134 25 135 33 136 26 137 7 138 26 139 33 140 26 141 2 142 25 143 34 144 27 145 7 146 27 147 34 148 28 149 8 150 28 151 34 152 28 153 3 154 27 155 35 156 29 157 8 158 29 159 35 160 30 161 9 162 30 163 35 164 30 165 4 166 29 167 36 168 31 169 9 170 31 171 36 172 22 173 10 174 22 175 36 176 22 177 5 178 31 179 38 180 6 181 32 182 32 183 37 184 38 185 11 186 38 187 37 188 37 189 32 190 10 191 39 192 7 193 33 194 33 195 38 196 39 197 11 198 39 199 38 200 38 201 33 202 6 203 40 204 8 205 34 206 34 207 39 208 40 209 11 210 40 211 39 212 39 213 34 214 7 215 41 216 9 217 35 218 35 219 40 220 41 221 11 222 41 223 40 224 40 225 35 226 8 227 37 228 10 229 36 230 36 231 41 232 37 233 11 234 37 235 41 236 41 237 36 238 9 239

      +
      +
      +
      + + + + 1.0 1.0 -1.0 1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 1.0 -1.0 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0 -1.0 1.0 -1.0 1.0 1.0 + + + + + + + + + + 0.57735 0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

      0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

      +
      +
      +
      + + + + 0.42013 0.42013 -0.42013 0.49402 0.33009 -0.42013 0.54892 0.22737 -0.42013 0.58273 0.11591 -0.42013 0.59415 0.0 -0.42013 0.58273 -0.11591 -0.42013 0.54892 -0.22737 -0.42013 0.49402 -0.33009 -0.42013 0.42013 -0.42013 -0.42013 0.33009 -0.49402 -0.42013 0.22737 -0.54892 -0.42013 0.11591 -0.58273 -0.42013 -0.0 -0.59415 -0.42013 -0.11591 -0.58273 -0.42013 -0.22737 -0.54892 -0.42013 -0.33009 -0.49402 -0.42013 -0.42013 -0.42013 -0.42013 -0.49402 -0.33009 -0.42013 -0.54892 -0.22737 -0.42013 -0.58273 -0.11591 -0.42013 -0.59415 0.0 -0.42013 -0.58273 0.11591 -0.42013 -0.54892 0.22737 -0.42013 -0.49402 0.33009 -0.42013 -0.42013 0.42013 -0.42013 -0.33009 0.49402 -0.42013 -0.22737 0.54892 -0.42013 -0.11591 0.58273 -0.42013 0.0 0.59415 -0.42013 0.11591 0.58273 -0.42013 0.22737 0.54892 -0.42013 0.33009 0.49402 -0.42013 -0.0 0.0 0.42013 -0.0 0.0 -0.42013 + + + + + + + + + + 0.62694 0.62694 -0.46245 0.73721 0.49257 -0.46245 0.81912 0.33927 -0.46245 0.86959 0.17295 -0.46245 0.88662 0.0 -0.46245 0.86959 -0.17295 -0.46245 0.81912 -0.33927 -0.46245 0.73721 -0.49257 -0.46245 0.62694 -0.62694 -0.46245 0.49257 -0.73721 -0.46245 0.33927 -0.81912 -0.46245 0.17295 -0.86959 -0.46245 0.0 -0.88662 -0.46245 -0.17295 -0.86959 -0.46245 -0.33927 -0.81912 -0.46245 -0.49257 -0.73721 -0.46245 -0.62694 -0.62694 -0.46245 -0.73721 -0.49257 -0.46245 -0.81912 -0.33927 -0.46245 -0.86959 -0.17295 -0.46245 -0.88662 0.0 -0.46245 -0.86959 0.17295 -0.46245 -0.81912 0.33927 -0.46245 -0.73721 0.49257 -0.46245 -0.62694 0.62694 -0.46245 -0.49257 0.73721 -0.46245 -0.33927 0.81915 -0.46245 -0.17295 0.86959 -0.46245 0.0 0.88662 -0.46245 0.17295 0.86959 -0.46245 0.33927 0.81912 -0.46245 0.49257 0.73721 -0.46245 0.0 0.0 1.0 0.0 0.0 -1.0 + + + + + + + + + + 0.89466 0.14214 1.02385 0.18062 0.53437 0.50208 0.53437 0.50208 0.77134 0.1159 0.89466 0.14214 0.53437 0.50208 0.65189 0.10064 0.77134 0.1159 0.53437 0.50208 0.53438 0.09564 0.65189 0.10064 0.53437 0.50208 0.41686 0.10064 0.53438 0.09564 0.53437 0.50208 0.29742 0.1159 0.41686 0.10064 0.53437 0.50208 0.17409 0.14214 0.29742 0.1159 0.53437 0.50208 0.0449 0.18062 0.17409 0.14214 0.53437 0.50208 -0.09221 0.23313 0.0449 0.18062 0.53437 0.50208 -0.23937 0.30206 -0.09221 0.23313 0.53437 0.50208 -0.39881 0.39046 -0.23937 0.30206 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.6137 -0.57289 0.50208 0.53437 0.50208 -0.23937 0.70209 -0.39881 0.6137 0.53437 0.50208 -0.09221 0.77103 -0.23937 0.70209 0.53437 0.50208 0.0449 0.82354 -0.09221 0.77103 0.53437 0.50208 0.17409 0.86202 0.0449 0.82354 0.53437 0.50208 0.29741 0.88826 0.17409 0.86202 0.53437 0.50208 0.41686 0.90351 0.29741 0.88826 0.53437 0.50208 0.53437 0.90852 0.41686 0.90351 0.53437 0.50208 0.65189 0.90351 0.53437 0.90852 0.53437 0.50208 0.77133 0.88826 0.65189 0.90351 0.53437 0.50208 0.89466 0.86202 0.77133 0.88826 0.53437 0.50208 1.02385 0.82354 0.89466 0.86202 0.53437 0.50208 1.16096 0.77103 1.02385 0.82354 0.53437 0.50208 1.30812 0.70209 1.16096 0.77103 0.53437 0.50208 1.46756 0.6137 1.30812 0.70209 0.53437 0.50208 1.64164 0.50208 1.46756 0.6137 0.53437 0.50208 1.46756 0.39046 1.64164 0.50208 0.53437 0.50208 1.30812 0.30207 1.46756 0.39046 0.53437 0.50208 1.16096 0.23313 1.30812 0.30207 0.53437 0.50208 1.02385 0.18062 1.16096 0.23313 0.53437 0.50208 1.02385 0.18062 0.89466 0.14214 0.53437 0.50208 0.89466 0.14214 0.77134 0.1159 0.53437 0.50208 0.77134 0.1159 0.65189 0.10064 0.53437 0.50208 0.65189 0.10064 0.53438 0.09564 0.53437 0.50208 0.53438 0.09564 0.41686 0.10064 0.53437 0.50208 0.41686 0.10064 0.29742 0.1159 0.53437 0.50208 0.29742 0.1159 0.17409 0.14214 0.53437 0.50208 0.17409 0.14214 0.0449 0.18062 0.53437 0.50208 0.0449 0.18062 -0.09221 0.23313 0.53437 0.50208 -0.09221 0.23313 -0.23937 0.30206 0.53437 0.50208 -0.23937 0.30206 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.39046 -0.57289 0.50208 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.6137 0.53437 0.50208 -0.39881 0.6137 -0.23937 0.70209 0.53437 0.50208 -0.23937 0.70209 -0.09221 0.77103 0.53437 0.50208 -0.09221 0.77103 0.0449 0.82354 0.53437 0.50208 0.0449 0.82354 0.17409 0.86202 0.53437 0.50208 0.17409 0.86202 0.29741 0.88826 0.53437 0.50208 0.29741 0.88826 0.41686 0.90351 0.53437 0.50208 0.41686 0.90351 0.53437 0.90852 0.53437 0.50208 0.53437 0.90852 0.65189 0.90351 0.53437 0.50208 0.65189 0.90351 0.77133 0.88826 0.53437 0.50208 0.77133 0.88826 0.89466 0.86202 0.53437 0.50208 0.89466 0.86202 1.02385 0.82354 0.53437 0.50208 1.02385 0.82354 1.16096 0.77103 0.53437 0.50208 1.16096 0.77103 1.30812 0.70209 0.53437 0.50208 1.30812 0.70209 1.46756 0.6137 0.53437 0.50208 1.46756 0.6137 1.64164 0.50208 0.53437 0.50208 1.64164 0.50208 1.46756 0.39046 0.53437 0.50208 1.46756 0.39046 1.30812 0.30207 0.53437 0.50208 1.30812 0.30207 1.16096 0.23313 1.16096 0.23313 1.02385 0.18062 0.53437 0.50208 + + + + + + + + + + + + + + +

      1 0 0 1 32 2 32 3 2 4 1 5 32 6 3 7 2 8 32 9 4 10 3 11 32 12 5 13 4 14 32 15 6 16 5 17 32 18 7 19 6 20 32 21 8 22 7 23 32 24 9 25 8 26 32 27 10 28 9 29 32 30 11 31 10 32 32 33 12 34 11 35 32 36 13 37 12 38 32 39 14 40 13 41 32 42 15 43 14 44 32 45 16 46 15 47 32 48 17 49 16 50 32 51 18 52 17 53 32 54 19 55 18 56 32 57 20 58 19 59 32 60 21 61 20 62 32 63 22 64 21 65 32 66 23 67 22 68 32 69 24 70 23 71 32 72 25 73 24 74 32 75 26 76 25 77 32 78 27 79 26 80 32 81 28 82 27 83 32 84 29 85 28 86 32 87 30 88 29 89 32 90 31 91 30 92 32 93 0 94 31 95 33 96 0 97 1 98 33 99 1 100 2 101 33 102 2 103 3 104 33 105 3 106 4 107 33 108 4 109 5 110 33 111 5 112 6 113 33 114 6 115 7 116 33 117 7 118 8 119 33 120 8 121 9 122 33 123 9 124 10 125 33 126 10 127 11 128 33 129 11 130 12 131 33 132 12 133 13 134 33 135 13 136 14 137 33 138 14 139 15 140 33 141 15 142 16 143 33 144 16 145 17 146 33 147 17 148 18 149 33 150 18 151 19 152 33 153 19 154 20 155 33 156 20 157 21 158 33 159 21 160 22 161 33 162 22 163 23 164 33 165 23 166 24 167 33 168 24 169 25 170 33 171 25 172 26 173 33 174 26 175 27 176 33 177 27 178 28 179 33 180 28 181 29 182 33 183 29 184 30 185 33 186 30 187 31 188 31 189 0 190 33 191

      +
      +
      +
      + + + + 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 0.0 -0.0 1.0 -0.0 0.0 -1.0 + + + + + + + + + + 0.62694 0.62694 -0.46245 0.73721 0.49257 -0.46245 0.81912 0.33927 -0.46245 0.86959 0.17295 -0.46245 0.88662 0.0 -0.46245 0.86959 -0.17295 -0.46245 0.81912 -0.33927 -0.46245 0.73721 -0.49257 -0.46245 0.62694 -0.62694 -0.46245 0.49257 -0.73721 -0.46245 0.33927 -0.81912 -0.46245 0.17295 -0.86959 -0.46245 0.0 -0.88662 -0.46245 -0.17295 -0.86959 -0.46245 -0.33927 -0.81912 -0.46245 -0.49257 -0.73721 -0.46245 -0.62694 -0.62694 -0.46245 -0.73721 -0.49257 -0.46245 -0.81912 -0.33927 -0.46245 -0.86959 -0.17295 -0.46245 -0.88662 0.0 -0.46245 -0.86959 0.17295 -0.46245 -0.81912 0.33927 -0.46245 -0.73721 0.49257 -0.46245 -0.62694 0.62694 -0.46245 -0.49257 0.73721 -0.46245 -0.33927 0.81915 -0.46245 -0.17295 0.86959 -0.46245 0.0 0.88662 -0.46245 0.17295 0.86959 -0.46245 0.33927 0.81912 -0.46245 0.49257 0.73721 -0.46245 0.0 0.0 1.0 0.0 0.0 -1.0 + + + + + + + + + + 0.89466 0.14214 1.02385 0.18062 0.53437 0.50208 0.53437 0.50208 0.77134 0.1159 0.89466 0.14214 0.53437 0.50208 0.65189 0.10064 0.77134 0.1159 0.53437 0.50208 0.53438 0.09564 0.65189 0.10064 0.53437 0.50208 0.41686 0.10064 0.53438 0.09564 0.53437 0.50208 0.29742 0.1159 0.41686 0.10064 0.53437 0.50208 0.17409 0.14214 0.29742 0.1159 0.53437 0.50208 0.0449 0.18062 0.17409 0.14214 0.53437 0.50208 -0.09221 0.23313 0.0449 0.18062 0.53437 0.50208 -0.23937 0.30206 -0.09221 0.23313 0.53437 0.50208 -0.39881 0.39046 -0.23937 0.30206 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.6137 -0.57289 0.50208 0.53437 0.50208 -0.23937 0.70209 -0.39881 0.6137 0.53437 0.50208 -0.09221 0.77103 -0.23937 0.70209 0.53437 0.50208 0.0449 0.82354 -0.09221 0.77103 0.53437 0.50208 0.17409 0.86202 0.0449 0.82354 0.53437 0.50208 0.29741 0.88826 0.17409 0.86202 0.53437 0.50208 0.41686 0.90351 0.29741 0.88826 0.53437 0.50208 0.53437 0.90852 0.41686 0.90351 0.53437 0.50208 0.65189 0.90351 0.53437 0.90852 0.53437 0.50208 0.77133 0.88826 0.65189 0.90351 0.53437 0.50208 0.89466 0.86202 0.77133 0.88826 0.53437 0.50208 1.02385 0.82354 0.89466 0.86202 0.53437 0.50208 1.16096 0.77103 1.02385 0.82354 0.53437 0.50208 1.30812 0.70209 1.16096 0.77103 0.53437 0.50208 1.46756 0.6137 1.30812 0.70209 0.53437 0.50208 1.64164 0.50208 1.46756 0.6137 0.53437 0.50208 1.46756 0.39046 1.64164 0.50208 0.53437 0.50208 1.30812 0.30207 1.46756 0.39046 0.53437 0.50208 1.16096 0.23313 1.30812 0.30207 0.53437 0.50208 1.02385 0.18062 1.16096 0.23313 0.53437 0.50208 1.02385 0.18062 0.89466 0.14214 0.53437 0.50208 0.89466 0.14214 0.77134 0.1159 0.53437 0.50208 0.77134 0.1159 0.65189 0.10064 0.53437 0.50208 0.65189 0.10064 0.53438 0.09564 0.53437 0.50208 0.53438 0.09564 0.41686 0.10064 0.53437 0.50208 0.41686 0.10064 0.29742 0.1159 0.53437 0.50208 0.29742 0.1159 0.17409 0.14214 0.53437 0.50208 0.17409 0.14214 0.0449 0.18062 0.53437 0.50208 0.0449 0.18062 -0.09221 0.23313 0.53437 0.50208 -0.09221 0.23313 -0.23937 0.30206 0.53437 0.50208 -0.23937 0.30206 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.39046 -0.57289 0.50208 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.6137 0.53437 0.50208 -0.39881 0.6137 -0.23937 0.70209 0.53437 0.50208 -0.23937 0.70209 -0.09221 0.77103 0.53437 0.50208 -0.09221 0.77103 0.0449 0.82354 0.53437 0.50208 0.0449 0.82354 0.17409 0.86202 0.53437 0.50208 0.17409 0.86202 0.29741 0.88826 0.53437 0.50208 0.29741 0.88826 0.41686 0.90351 0.53437 0.50208 0.41686 0.90351 0.53437 0.90852 0.53437 0.50208 0.53437 0.90852 0.65189 0.90351 0.53437 0.50208 0.65189 0.90351 0.77133 0.88826 0.53437 0.50208 0.77133 0.88826 0.89466 0.86202 0.53437 0.50208 0.89466 0.86202 1.02385 0.82354 0.53437 0.50208 1.02385 0.82354 1.16096 0.77103 0.53437 0.50208 1.16096 0.77103 1.30812 0.70209 0.53437 0.50208 1.30812 0.70209 1.46756 0.6137 0.53437 0.50208 1.46756 0.6137 1.64164 0.50208 0.53437 0.50208 1.64164 0.50208 1.46756 0.39046 0.53437 0.50208 1.46756 0.39046 1.30812 0.30207 0.53437 0.50208 1.30812 0.30207 1.16096 0.23313 1.16096 0.23313 1.02385 0.18062 0.53437 0.50208 + + + + + + + + + + + + + + +

      1 0 0 1 32 2 32 3 2 4 1 5 32 6 3 7 2 8 32 9 4 10 3 11 32 12 5 13 4 14 32 15 6 16 5 17 32 18 7 19 6 20 32 21 8 22 7 23 32 24 9 25 8 26 32 27 10 28 9 29 32 30 11 31 10 32 32 33 12 34 11 35 32 36 13 37 12 38 32 39 14 40 13 41 32 42 15 43 14 44 32 45 16 46 15 47 32 48 17 49 16 50 32 51 18 52 17 53 32 54 19 55 18 56 32 57 20 58 19 59 32 60 21 61 20 62 32 63 22 64 21 65 32 66 23 67 22 68 32 69 24 70 23 71 32 72 25 73 24 74 32 75 26 76 25 77 32 78 27 79 26 80 32 81 28 82 27 83 32 84 29 85 28 86 32 87 30 88 29 89 32 90 31 91 30 92 32 93 0 94 31 95 33 96 0 97 1 98 33 99 1 100 2 101 33 102 2 103 3 104 33 105 3 106 4 107 33 108 4 109 5 110 33 111 5 112 6 113 33 114 6 115 7 116 33 117 7 118 8 119 33 120 8 121 9 122 33 123 9 124 10 125 33 126 10 127 11 128 33 129 11 130 12 131 33 132 12 133 13 134 33 135 13 136 14 137 33 138 14 139 15 140 33 141 15 142 16 143 33 144 16 145 17 146 33 147 17 148 18 149 33 150 18 151 19 152 33 153 19 154 20 155 33 156 20 157 21 158 33 159 21 160 22 161 33 162 22 163 23 164 33 165 23 166 24 167 33 168 24 169 25 170 33 171 25 172 26 173 33 174 26 175 27 176 33 177 27 178 28 179 33 180 28 181 29 182 33 183 29 184 30 185 33 186 30 187 31 188 31 189 0 190 33 191

      +
      +
      +
      + + + + 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 1.0 1.0 1.0 1.17588 0.78569 1.0 1.30656 0.54119 1.0 1.38704 0.2759 1.0 1.41421 -0.0 1.0 1.38704 -0.2759 1.0 1.30656 -0.5412 1.0 1.17587 -0.7857 1.0 1.0 -1.0 1.0 0.78569 -1.17588 1.0 0.5412 -1.30656 1.0 0.2759 -1.38704 1.0 0.0 -1.41421 1.0 -0.2759 -1.38704 1.0 -0.54119 -1.30656 1.0 -0.78569 -1.17588 1.0 -1.0 -1.0 1.0 -1.17587 -0.7857 1.0 -1.30656 -0.5412 1.0 -1.38704 -0.2759 1.0 -1.41421 -1e-05 1.0 -1.38704 0.27589 1.0 -1.30657 0.54119 1.0 -1.17588 0.78569 1.0 -1.00001 0.99999 1.0 -0.7857 1.17587 1.0 -0.5412 1.30656 1.0 -0.27591 1.38704 1.0 -1e-05 1.41421 1.0 0.27589 1.38704 1.0 0.54119 1.30657 1.0 0.78569 1.17588 1.0 -0.0 0.0 -1.0 0.0 -0.0 1.0 + + + + + + + + + + 0.49876 0.49876 -0.70879 0.5865 0.39189 -0.70879 0.65169 0.26994 -0.70879 0.69182 0.13761 -0.70879 0.70537 0.0 -0.70879 0.69182 -0.13761 -0.70879 0.65169 -0.26994 -0.70879 0.5865 -0.39189 -0.70879 0.49876 -0.49876 -0.70879 0.39189 -0.5865 -0.70879 0.26994 -0.65169 -0.70879 0.13761 -0.69182 -0.70879 0.0 -0.70537 -0.70879 -0.13761 -0.69182 -0.70879 -0.26994 -0.65169 -0.70879 -0.39189 -0.5865 -0.70879 -0.49876 -0.49876 -0.70879 -0.5865 -0.39189 -0.70879 -0.65169 -0.26994 -0.70879 -0.69182 -0.13761 -0.70879 -0.70537 0.0 -0.70879 -0.69182 0.13761 -0.70879 -0.65169 0.26994 -0.70879 -0.5865 0.39189 -0.70879 -0.49876 0.49876 -0.70879 -0.39189 0.5865 -0.70879 -0.26994 0.65169 -0.70879 -0.13761 0.69182 -0.70879 0.0 0.70537 -0.70879 0.13761 0.69182 -0.70879 0.26994 0.65169 -0.70879 0.39189 0.5865 -0.70879 0.49876 0.49876 0.70879 0.5865 0.39189 0.70879 0.65169 0.26994 0.70879 0.69182 0.13761 0.70879 0.70537 0.0 0.70879 0.69182 -0.13761 0.70879 0.65169 -0.26994 0.70879 0.5865 -0.39189 0.70879 0.49876 -0.49876 0.70879 0.39189 -0.5865 0.70879 0.26994 -0.65169 0.70879 0.13761 -0.69182 0.70879 0.0 -0.70537 0.70879 -0.13761 -0.69182 0.70879 -0.26994 -0.65169 0.70879 -0.39189 -0.5865 0.70879 -0.49876 -0.49876 0.70879 -0.5865 -0.39189 0.70879 -0.65169 -0.26994 0.70879 -0.69182 -0.13761 0.70879 -0.70537 0.0 0.70879 -0.69182 0.13761 0.70879 -0.65169 0.26994 0.70879 -0.5865 0.39189 0.70879 -0.49876 0.49876 0.70879 -0.39189 0.5865 0.70879 -0.26994 0.65169 0.70879 -0.13761 0.69182 0.70879 0.0 0.70537 0.70879 0.13761 0.69182 0.70879 0.26994 0.65169 0.70879 0.39189 0.5865 0.70879 0.0 0.0 -1.0 0.0 0.0 1.0 + + + + + + + + + + 1.10675 0.0 0.625 0.0 0.59375 0.0 0.60675 1.0 0.59375 1.0 0.625 1.0 0.10675 0.0 0.59375 0.0 0.5625 0.0 0.60675 1.0 0.5625 1.0 0.59375 1.0 0.10675 0.0 0.5625 0.0 0.53125 0.0 0.60675 1.0 0.53125 1.0 0.5625 1.0 0.10675 0.0 0.53125 0.0 0.5 0.0 0.60675 1.0 0.5 1.0 0.53125 1.0 0.10675 0.0 0.5 0.0 0.46875 0.0 0.60675 1.0 0.46875 1.0 0.5 1.0 0.10675 0.0 0.46875 0.0 0.4375 0.0 0.60675 1.0 0.4375 1.0 0.46875 1.0 0.10675 0.0 0.4375 0.0 0.40625 0.0 0.60675 1.0 0.40625 1.0 0.4375 1.0 0.10675 0.0 0.40625 0.0 0.375 0.0 0.60675 1.0 0.375 1.0 0.40625 1.0 0.10675 0.0 0.375 0.0 0.34375 0.0 0.60675 1.0 0.34375 1.0 0.375 1.0 0.10675 0.0 0.34375 0.0 0.3125 0.0 0.60675 1.0 0.3125 1.0 0.34375 1.0 0.10675 0.0 0.3125 0.0 0.28125 0.0 0.60675 1.0 0.28125 1.0 0.3125 1.0 0.10675 0.0 0.28125 0.0 0.25 0.0 0.60675 1.0 0.25 1.0 0.28125 1.0 0.10675 0.0 0.25 0.0 0.21875 0.0 0.60675 1.0 0.21875 1.0 0.25 1.0 0.10675 0.0 0.21875 0.0 0.1875 0.0 0.60675 1.0 0.1875 1.0 0.21875 1.0 0.10675 0.0 0.1875 0.0 0.15625 0.0 0.60675 1.0 0.15625 1.0 0.1875 1.0 0.10675 0.0 0.15625 0.0 0.125 0.0 0.60675 1.0 0.125 1.0 0.15625 1.0 0.10675 0.0 0.125 0.0 0.09375 0.0 0.60675 1.0 1.09375 1.0 0.125 1.0 0.10675 0.0 0.09375 0.0 0.0625 0.0 0.60675 1.0 1.0625 1.0 1.09375 1.0 0.10675 0.0 0.0625 0.0 0.03125 0.0 0.60675 1.0 1.03125 1.0 1.0625 1.0 1.10675 0.0 1.03125 0.0 1.0 0.0 0.60675 1.0 1.0 1.0 1.03125 1.0 1.10675 0.0 1.0 0.0 0.96875 -0.0 0.60675 1.0 0.96875 1.0 1.0 1.0 1.10675 0.0 0.96875 -0.0 0.9375 -0.0 0.60675 1.0 0.9375 1.0 0.96875 1.0 1.10675 0.0 0.9375 -0.0 0.90625 0.0 0.60675 1.0 0.90625 1.0 0.9375 1.0 1.10675 0.0 0.90625 0.0 0.875 0.0 0.60675 1.0 0.875 1.0 0.90625 1.0 1.10675 0.0 0.875 0.0 0.84375 -0.0 0.60675 1.0 0.84375 1.0 0.875 1.0 1.10675 0.0 0.84375 -0.0 0.8125 -0.0 0.60675 1.0 0.8125 1.0 0.84375 1.0 1.10675 0.0 0.8125 -0.0 0.78125 -0.0 0.60675 1.0 0.78125 1.0 0.8125 1.0 1.10675 0.0 0.78125 -0.0 0.75 -0.0 0.60675 1.0 0.75 1.0 0.78125 1.0 1.10675 0.0 0.75 -0.0 0.71875 -0.0 0.60675 1.0 0.71875 1.0 0.75 1.0 1.10675 0.0 0.71875 -0.0 0.6875 -0.0 0.60675 1.0 0.6875 1.0 0.71875 1.0 1.10675 0.0 0.6875 -0.0 0.65625 -0.0 0.60675 1.0 0.65625 1.0 0.6875 1.0 0.65625 -0.0 0.625 0.0 1.10675 0.0 0.60675 1.0 0.625 1.0 0.65625 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.625 1.0 0.625 0.0 0.65625 -0.0 0.625 1.0 0.625 0.0 0.65625 -0.0 + + + + + + + + + + + + + + +

      64 0 0 1 1 2 65 3 33 4 32 5 64 6 1 7 2 8 65 9 34 10 33 11 64 12 2 13 3 14 65 15 35 16 34 17 64 18 3 19 4 20 65 21 36 22 35 23 64 24 4 25 5 26 65 27 37 28 36 29 64 30 5 31 6 32 65 33 38 34 37 35 64 36 6 37 7 38 65 39 39 40 38 41 64 42 7 43 8 44 65 45 40 46 39 47 64 48 8 49 9 50 65 51 41 52 40 53 64 54 9 55 10 56 65 57 42 58 41 59 64 60 10 61 11 62 65 63 43 64 42 65 64 66 11 67 12 68 65 69 44 70 43 71 64 72 12 73 13 74 65 75 45 76 44 77 64 78 13 79 14 80 65 81 46 82 45 83 64 84 14 85 15 86 65 87 47 88 46 89 64 90 15 91 16 92 65 93 48 94 47 95 64 96 16 97 17 98 65 99 49 100 48 101 64 102 17 103 18 104 65 105 50 106 49 107 64 108 18 109 19 110 65 111 51 112 50 113 64 114 19 115 20 116 65 117 52 118 51 119 64 120 20 121 21 122 65 123 53 124 52 125 64 126 21 127 22 128 65 129 54 130 53 131 64 132 22 133 23 134 65 135 55 136 54 137 64 138 23 139 24 140 65 141 56 142 55 143 64 144 24 145 25 146 65 147 57 148 56 149 64 150 25 151 26 152 65 153 58 154 57 155 64 156 26 157 27 158 65 159 59 160 58 161 64 162 27 163 28 164 65 165 60 166 59 167 64 168 28 169 29 170 65 171 61 172 60 173 64 174 29 175 30 176 65 177 62 178 61 179 64 180 30 181 31 182 65 183 63 184 62 185 31 186 0 187 64 188 65 189 32 190 63 191 0 192 32 193 33 194 33 195 1 196 0 197 1 198 33 199 34 200 34 201 2 202 1 203 2 204 34 205 35 206 35 207 3 208 2 209 3 210 35 211 36 212 36 213 4 214 3 215 4 216 36 217 37 218 37 219 5 220 4 221 5 222 37 223 38 224 38 225 6 226 5 227 6 228 38 229 39 230 39 231 7 232 6 233 7 234 39 235 40 236 40 237 8 238 7 239 8 240 40 241 41 242 41 243 9 244 8 245 9 246 41 247 42 248 42 249 10 250 9 251 10 252 42 253 43 254 43 255 11 256 10 257 11 258 43 259 44 260 44 261 12 262 11 263 12 264 44 265 45 266 45 267 13 268 12 269 13 270 45 271 46 272 46 273 14 274 13 275 14 276 46 277 47 278 47 279 15 280 14 281 15 282 47 283 48 284 48 285 16 286 15 287 16 288 48 289 49 290 49 291 17 292 16 293 17 294 49 295 50 296 50 297 18 298 17 299 18 300 50 301 51 302 51 303 19 304 18 305 19 306 51 307 52 308 52 309 20 310 19 311 20 312 52 313 53 314 53 315 21 316 20 317 21 318 53 319 54 320 54 321 22 322 21 323 22 324 54 325 55 326 55 327 23 328 22 329 23 330 55 331 56 332 56 333 24 334 23 335 24 336 56 337 57 338 57 339 25 340 24 341 25 342 57 343 58 344 58 345 26 346 25 347 26 348 58 349 59 350 59 351 27 352 26 353 27 354 59 355 60 356 60 357 28 358 27 359 28 360 60 361 61 362 61 363 29 364 28 365 29 366 61 367 62 368 62 369 30 370 29 371 30 372 62 373 63 374 63 375 31 376 30 377 32 378 0 379 31 380 31 381 63 382 32 383

      +
      +
      +
      + + + + 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 1.0 1.0 1.0 1.17588 0.78569 1.0 1.30656 0.54119 1.0 1.38704 0.2759 1.0 1.41421 -0.0 1.0 1.38704 -0.2759 1.0 1.30656 -0.5412 1.0 1.17587 -0.7857 1.0 1.0 -1.0 1.0 0.78569 -1.17588 1.0 0.5412 -1.30656 1.0 0.2759 -1.38704 1.0 0.0 -1.41421 1.0 -0.2759 -1.38704 1.0 -0.54119 -1.30656 1.0 -0.78569 -1.17588 1.0 -1.0 -1.0 1.0 -1.17587 -0.7857 1.0 -1.30656 -0.5412 1.0 -1.38704 -0.2759 1.0 -1.41421 -1e-05 1.0 -1.38704 0.27589 1.0 -1.30657 0.54119 1.0 -1.17588 0.78569 1.0 -1.00001 0.99999 1.0 -0.7857 1.17587 1.0 -0.5412 1.30656 1.0 -0.27591 1.38704 1.0 -1e-05 1.41421 1.0 0.27589 1.38704 1.0 0.54119 1.30657 1.0 0.78569 1.17588 1.0 -0.0 0.0 -1.0 0.0 -0.0 1.0 + + + + + + + + + + 0.49876 0.49876 -0.70879 0.5865 0.39189 -0.70879 0.65169 0.26994 -0.70879 0.69182 0.13761 -0.70879 0.70537 0.0 -0.70879 0.69182 -0.13761 -0.70879 0.65169 -0.26994 -0.70879 0.5865 -0.39189 -0.70879 0.49876 -0.49876 -0.70879 0.39189 -0.5865 -0.70879 0.26994 -0.65169 -0.70879 0.13761 -0.69182 -0.70879 0.0 -0.70537 -0.70879 -0.13761 -0.69182 -0.70879 -0.26994 -0.65169 -0.70879 -0.39189 -0.5865 -0.70879 -0.49876 -0.49876 -0.70879 -0.5865 -0.39189 -0.70879 -0.65169 -0.26994 -0.70879 -0.69182 -0.13761 -0.70879 -0.70537 0.0 -0.70879 -0.69182 0.13761 -0.70879 -0.65169 0.26994 -0.70879 -0.5865 0.39189 -0.70879 -0.49876 0.49876 -0.70879 -0.39189 0.5865 -0.70879 -0.26994 0.65169 -0.70879 -0.13761 0.69182 -0.70879 0.0 0.70537 -0.70879 0.13761 0.69182 -0.70879 0.26994 0.65169 -0.70879 0.39189 0.5865 -0.70879 0.49876 0.49876 0.70879 0.5865 0.39189 0.70879 0.65169 0.26994 0.70879 0.69182 0.13761 0.70879 0.70537 0.0 0.70879 0.69182 -0.13761 0.70879 0.65169 -0.26994 0.70879 0.5865 -0.39189 0.70879 0.49876 -0.49876 0.70879 0.39189 -0.5865 0.70879 0.26994 -0.65169 0.70879 0.13761 -0.69182 0.70879 0.0 -0.70537 0.70879 -0.13761 -0.69182 0.70879 -0.26994 -0.65169 0.70879 -0.39189 -0.5865 0.70879 -0.49876 -0.49876 0.70879 -0.5865 -0.39189 0.70879 -0.65169 -0.26994 0.70879 -0.69182 -0.13761 0.70879 -0.70537 0.0 0.70879 -0.69182 0.13761 0.70879 -0.65169 0.26994 0.70879 -0.5865 0.39189 0.70879 -0.49876 0.49876 0.70879 -0.39189 0.5865 0.70879 -0.26994 0.65169 0.70879 -0.13761 0.69182 0.70879 0.0 0.70537 0.70879 0.13761 0.69182 0.70879 0.26994 0.65169 0.70879 0.39189 0.5865 0.70879 0.0 0.0 -1.0 0.0 0.0 1.0 + + + + + + + + + + 1.10675 0.0 0.625 0.0 0.59375 0.0 0.60675 1.0 0.59375 1.0 0.625 1.0 0.10675 0.0 0.59375 0.0 0.5625 0.0 0.60675 1.0 0.5625 1.0 0.59375 1.0 0.10675 0.0 0.5625 0.0 0.53125 0.0 0.60675 1.0 0.53125 1.0 0.5625 1.0 0.10675 0.0 0.53125 0.0 0.5 0.0 0.60675 1.0 0.5 1.0 0.53125 1.0 0.10675 0.0 0.5 0.0 0.46875 0.0 0.60675 1.0 0.46875 1.0 0.5 1.0 0.10675 0.0 0.46875 0.0 0.4375 0.0 0.60675 1.0 0.4375 1.0 0.46875 1.0 0.10675 0.0 0.4375 0.0 0.40625 0.0 0.60675 1.0 0.40625 1.0 0.4375 1.0 0.10675 0.0 0.40625 0.0 0.375 0.0 0.60675 1.0 0.375 1.0 0.40625 1.0 0.10675 0.0 0.375 0.0 0.34375 0.0 0.60675 1.0 0.34375 1.0 0.375 1.0 0.10675 0.0 0.34375 0.0 0.3125 0.0 0.60675 1.0 0.3125 1.0 0.34375 1.0 0.10675 0.0 0.3125 0.0 0.28125 0.0 0.60675 1.0 0.28125 1.0 0.3125 1.0 0.10675 0.0 0.28125 0.0 0.25 0.0 0.60675 1.0 0.25 1.0 0.28125 1.0 0.10675 0.0 0.25 0.0 0.21875 0.0 0.60675 1.0 0.21875 1.0 0.25 1.0 0.10675 0.0 0.21875 0.0 0.1875 0.0 0.60675 1.0 0.1875 1.0 0.21875 1.0 0.10675 0.0 0.1875 0.0 0.15625 0.0 0.60675 1.0 0.15625 1.0 0.1875 1.0 0.10675 0.0 0.15625 0.0 0.125 0.0 0.60675 1.0 0.125 1.0 0.15625 1.0 0.10675 0.0 0.125 0.0 0.09375 0.0 0.60675 1.0 1.09375 1.0 0.125 1.0 0.10675 0.0 0.09375 0.0 0.0625 0.0 0.60675 1.0 1.0625 1.0 1.09375 1.0 0.10675 0.0 0.0625 0.0 0.03125 0.0 0.60675 1.0 1.03125 1.0 1.0625 1.0 1.10675 0.0 1.03125 0.0 1.0 0.0 0.60675 1.0 1.0 1.0 1.03125 1.0 1.10675 0.0 1.0 0.0 0.96875 -0.0 0.60675 1.0 0.96875 1.0 1.0 1.0 1.10675 0.0 0.96875 -0.0 0.9375 -0.0 0.60675 1.0 0.9375 1.0 0.96875 1.0 1.10675 0.0 0.9375 -0.0 0.90625 0.0 0.60675 1.0 0.90625 1.0 0.9375 1.0 1.10675 0.0 0.90625 0.0 0.875 0.0 0.60675 1.0 0.875 1.0 0.90625 1.0 1.10675 0.0 0.875 0.0 0.84375 -0.0 0.60675 1.0 0.84375 1.0 0.875 1.0 1.10675 0.0 0.84375 -0.0 0.8125 -0.0 0.60675 1.0 0.8125 1.0 0.84375 1.0 1.10675 0.0 0.8125 -0.0 0.78125 -0.0 0.60675 1.0 0.78125 1.0 0.8125 1.0 1.10675 0.0 0.78125 -0.0 0.75 -0.0 0.60675 1.0 0.75 1.0 0.78125 1.0 1.10675 0.0 0.75 -0.0 0.71875 -0.0 0.60675 1.0 0.71875 1.0 0.75 1.0 1.10675 0.0 0.71875 -0.0 0.6875 -0.0 0.60675 1.0 0.6875 1.0 0.71875 1.0 1.10675 0.0 0.6875 -0.0 0.65625 -0.0 0.60675 1.0 0.65625 1.0 0.6875 1.0 0.65625 -0.0 0.625 0.0 1.10675 0.0 0.60675 1.0 0.625 1.0 0.65625 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.625 1.0 0.625 0.0 0.65625 -0.0 0.625 1.0 0.625 0.0 0.65625 -0.0 + + + + + + + + + + + + + + +

      64 0 0 1 1 2 65 3 33 4 32 5 64 6 1 7 2 8 65 9 34 10 33 11 64 12 2 13 3 14 65 15 35 16 34 17 64 18 3 19 4 20 65 21 36 22 35 23 64 24 4 25 5 26 65 27 37 28 36 29 64 30 5 31 6 32 65 33 38 34 37 35 64 36 6 37 7 38 65 39 39 40 38 41 64 42 7 43 8 44 65 45 40 46 39 47 64 48 8 49 9 50 65 51 41 52 40 53 64 54 9 55 10 56 65 57 42 58 41 59 64 60 10 61 11 62 65 63 43 64 42 65 64 66 11 67 12 68 65 69 44 70 43 71 64 72 12 73 13 74 65 75 45 76 44 77 64 78 13 79 14 80 65 81 46 82 45 83 64 84 14 85 15 86 65 87 47 88 46 89 64 90 15 91 16 92 65 93 48 94 47 95 64 96 16 97 17 98 65 99 49 100 48 101 64 102 17 103 18 104 65 105 50 106 49 107 64 108 18 109 19 110 65 111 51 112 50 113 64 114 19 115 20 116 65 117 52 118 51 119 64 120 20 121 21 122 65 123 53 124 52 125 64 126 21 127 22 128 65 129 54 130 53 131 64 132 22 133 23 134 65 135 55 136 54 137 64 138 23 139 24 140 65 141 56 142 55 143 64 144 24 145 25 146 65 147 57 148 56 149 64 150 25 151 26 152 65 153 58 154 57 155 64 156 26 157 27 158 65 159 59 160 58 161 64 162 27 163 28 164 65 165 60 166 59 167 64 168 28 169 29 170 65 171 61 172 60 173 64 174 29 175 30 176 65 177 62 178 61 179 64 180 30 181 31 182 65 183 63 184 62 185 31 186 0 187 64 188 65 189 32 190 63 191 0 192 32 193 33 194 33 195 1 196 0 197 1 198 33 199 34 200 34 201 2 202 1 203 2 204 34 205 35 206 35 207 3 208 2 209 3 210 35 211 36 212 36 213 4 214 3 215 4 216 36 217 37 218 37 219 5 220 4 221 5 222 37 223 38 224 38 225 6 226 5 227 6 228 38 229 39 230 39 231 7 232 6 233 7 234 39 235 40 236 40 237 8 238 7 239 8 240 40 241 41 242 41 243 9 244 8 245 9 246 41 247 42 248 42 249 10 250 9 251 10 252 42 253 43 254 43 255 11 256 10 257 11 258 43 259 44 260 44 261 12 262 11 263 12 264 44 265 45 266 45 267 13 268 12 269 13 270 45 271 46 272 46 273 14 274 13 275 14 276 46 277 47 278 47 279 15 280 14 281 15 282 47 283 48 284 48 285 16 286 15 287 16 288 48 289 49 290 49 291 17 292 16 293 17 294 49 295 50 296 50 297 18 298 17 299 18 300 50 301 51 302 51 303 19 304 18 305 19 306 51 307 52 308 52 309 20 310 19 311 20 312 52 313 53 314 53 315 21 316 20 317 21 318 53 319 54 320 54 321 22 322 21 323 22 324 54 325 55 326 55 327 23 328 22 329 23 330 55 331 56 332 56 333 24 334 23 335 24 336 56 337 57 338 57 339 25 340 24 341 25 342 57 343 58 344 58 345 26 346 25 347 26 348 58 349 59 350 59 351 27 352 26 353 27 354 59 355 60 356 60 357 28 358 27 359 28 360 60 361 61 362 61 363 29 364 28 365 29 366 61 367 62 368 62 369 30 370 29 371 30 372 62 373 63 374 63 375 31 376 30 377 32 378 0 379 31 380 31 381 63 382 32 383

      +
      +
      +
      + + + + 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 1.0 1.0 1.0 1.17588 0.78569 1.0 1.30656 0.54119 1.0 1.38704 0.2759 1.0 1.41421 -0.0 1.0 1.38704 -0.2759 1.0 1.30656 -0.5412 1.0 1.17587 -0.7857 1.0 1.0 -1.0 1.0 0.78569 -1.17588 1.0 0.5412 -1.30656 1.0 0.2759 -1.38704 1.0 0.0 -1.41421 1.0 -0.2759 -1.38704 1.0 -0.54119 -1.30656 1.0 -0.78569 -1.17588 1.0 -1.0 -1.0 1.0 -1.17587 -0.7857 1.0 -1.30656 -0.5412 1.0 -1.38704 -0.2759 1.0 -1.41421 -1e-05 1.0 -1.38704 0.27589 1.0 -1.30657 0.54119 1.0 -1.17588 0.78569 1.0 -1.00001 0.99999 1.0 -0.7857 1.17587 1.0 -0.5412 1.30656 1.0 -0.27591 1.38704 1.0 -1e-05 1.41421 1.0 0.27589 1.38704 1.0 0.54119 1.30657 1.0 0.78569 1.17588 1.0 -0.0 0.0 -1.0 0.0 -0.0 1.0 + + + + + + + + + + 0.49876 0.49876 -0.70879 0.5865 0.39189 -0.70879 0.65169 0.26994 -0.70879 0.69182 0.13761 -0.70879 0.70537 0.0 -0.70879 0.69182 -0.13761 -0.70879 0.65169 -0.26994 -0.70879 0.5865 -0.39189 -0.70879 0.49876 -0.49876 -0.70879 0.39189 -0.5865 -0.70879 0.26994 -0.65169 -0.70879 0.13761 -0.69182 -0.70879 0.0 -0.70537 -0.70879 -0.13761 -0.69182 -0.70879 -0.26994 -0.65169 -0.70879 -0.39189 -0.5865 -0.70879 -0.49876 -0.49876 -0.70879 -0.5865 -0.39189 -0.70879 -0.65169 -0.26994 -0.70879 -0.69182 -0.13761 -0.70879 -0.70537 0.0 -0.70879 -0.69182 0.13761 -0.70879 -0.65169 0.26994 -0.70879 -0.5865 0.39189 -0.70879 -0.49876 0.49876 -0.70879 -0.39189 0.5865 -0.70879 -0.26994 0.65169 -0.70879 -0.13761 0.69182 -0.70879 0.0 0.70537 -0.70879 0.13761 0.69182 -0.70879 0.26994 0.65169 -0.70879 0.39189 0.5865 -0.70879 0.49876 0.49876 0.70879 0.5865 0.39189 0.70879 0.65169 0.26994 0.70879 0.69182 0.13761 0.70879 0.70537 0.0 0.70879 0.69182 -0.13761 0.70879 0.65169 -0.26994 0.70879 0.5865 -0.39189 0.70879 0.49876 -0.49876 0.70879 0.39189 -0.5865 0.70879 0.26994 -0.65169 0.70879 0.13761 -0.69182 0.70879 0.0 -0.70537 0.70879 -0.13761 -0.69182 0.70879 -0.26994 -0.65169 0.70879 -0.39189 -0.5865 0.70879 -0.49876 -0.49876 0.70879 -0.5865 -0.39189 0.70879 -0.65169 -0.26994 0.70879 -0.69182 -0.13761 0.70879 -0.70537 0.0 0.70879 -0.69182 0.13761 0.70879 -0.65169 0.26994 0.70879 -0.5865 0.39189 0.70879 -0.49876 0.49876 0.70879 -0.39189 0.5865 0.70879 -0.26994 0.65169 0.70879 -0.13761 0.69182 0.70879 0.0 0.70537 0.70879 0.13761 0.69182 0.70879 0.26994 0.65169 0.70879 0.39189 0.5865 0.70879 0.0 0.0 -1.0 0.0 0.0 1.0 + + + + + + + + + + 1.10675 0.0 0.625 0.0 0.59375 0.0 0.60675 1.0 0.59375 1.0 0.625 1.0 0.10675 0.0 0.59375 0.0 0.5625 0.0 0.60675 1.0 0.5625 1.0 0.59375 1.0 0.10675 0.0 0.5625 0.0 0.53125 0.0 0.60675 1.0 0.53125 1.0 0.5625 1.0 0.10675 0.0 0.53125 0.0 0.5 0.0 0.60675 1.0 0.5 1.0 0.53125 1.0 0.10675 0.0 0.5 0.0 0.46875 0.0 0.60675 1.0 0.46875 1.0 0.5 1.0 0.10675 0.0 0.46875 0.0 0.4375 0.0 0.60675 1.0 0.4375 1.0 0.46875 1.0 0.10675 0.0 0.4375 0.0 0.40625 0.0 0.60675 1.0 0.40625 1.0 0.4375 1.0 0.10675 0.0 0.40625 0.0 0.375 0.0 0.60675 1.0 0.375 1.0 0.40625 1.0 0.10675 0.0 0.375 0.0 0.34375 0.0 0.60675 1.0 0.34375 1.0 0.375 1.0 0.10675 0.0 0.34375 0.0 0.3125 0.0 0.60675 1.0 0.3125 1.0 0.34375 1.0 0.10675 0.0 0.3125 0.0 0.28125 0.0 0.60675 1.0 0.28125 1.0 0.3125 1.0 0.10675 0.0 0.28125 0.0 0.25 0.0 0.60675 1.0 0.25 1.0 0.28125 1.0 0.10675 0.0 0.25 0.0 0.21875 0.0 0.60675 1.0 0.21875 1.0 0.25 1.0 0.10675 0.0 0.21875 0.0 0.1875 0.0 0.60675 1.0 0.1875 1.0 0.21875 1.0 0.10675 0.0 0.1875 0.0 0.15625 0.0 0.60675 1.0 0.15625 1.0 0.1875 1.0 0.10675 0.0 0.15625 0.0 0.125 0.0 0.60675 1.0 0.125 1.0 0.15625 1.0 0.10675 0.0 0.125 0.0 0.09375 0.0 0.60675 1.0 1.09375 1.0 0.125 1.0 0.10675 0.0 0.09375 0.0 0.0625 0.0 0.60675 1.0 1.0625 1.0 1.09375 1.0 0.10675 0.0 0.0625 0.0 0.03125 0.0 0.60675 1.0 1.03125 1.0 1.0625 1.0 1.10675 0.0 1.03125 0.0 1.0 0.0 0.60675 1.0 1.0 1.0 1.03125 1.0 1.10675 0.0 1.0 0.0 0.96875 -0.0 0.60675 1.0 0.96875 1.0 1.0 1.0 1.10675 0.0 0.96875 -0.0 0.9375 -0.0 0.60675 1.0 0.9375 1.0 0.96875 1.0 1.10675 0.0 0.9375 -0.0 0.90625 0.0 0.60675 1.0 0.90625 1.0 0.9375 1.0 1.10675 0.0 0.90625 0.0 0.875 0.0 0.60675 1.0 0.875 1.0 0.90625 1.0 1.10675 0.0 0.875 0.0 0.84375 -0.0 0.60675 1.0 0.84375 1.0 0.875 1.0 1.10675 0.0 0.84375 -0.0 0.8125 -0.0 0.60675 1.0 0.8125 1.0 0.84375 1.0 1.10675 0.0 0.8125 -0.0 0.78125 -0.0 0.60675 1.0 0.78125 1.0 0.8125 1.0 1.10675 0.0 0.78125 -0.0 0.75 -0.0 0.60675 1.0 0.75 1.0 0.78125 1.0 1.10675 0.0 0.75 -0.0 0.71875 -0.0 0.60675 1.0 0.71875 1.0 0.75 1.0 1.10675 0.0 0.71875 -0.0 0.6875 -0.0 0.60675 1.0 0.6875 1.0 0.71875 1.0 1.10675 0.0 0.6875 -0.0 0.65625 -0.0 0.60675 1.0 0.65625 1.0 0.6875 1.0 0.65625 -0.0 0.625 0.0 1.10675 0.0 0.60675 1.0 0.625 1.0 0.65625 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.625 1.0 0.625 0.0 0.65625 -0.0 0.625 1.0 0.625 0.0 0.65625 -0.0 + + + + + + + + + + + + + + +

      64 0 0 1 1 2 65 3 33 4 32 5 64 6 1 7 2 8 65 9 34 10 33 11 64 12 2 13 3 14 65 15 35 16 34 17 64 18 3 19 4 20 65 21 36 22 35 23 64 24 4 25 5 26 65 27 37 28 36 29 64 30 5 31 6 32 65 33 38 34 37 35 64 36 6 37 7 38 65 39 39 40 38 41 64 42 7 43 8 44 65 45 40 46 39 47 64 48 8 49 9 50 65 51 41 52 40 53 64 54 9 55 10 56 65 57 42 58 41 59 64 60 10 61 11 62 65 63 43 64 42 65 64 66 11 67 12 68 65 69 44 70 43 71 64 72 12 73 13 74 65 75 45 76 44 77 64 78 13 79 14 80 65 81 46 82 45 83 64 84 14 85 15 86 65 87 47 88 46 89 64 90 15 91 16 92 65 93 48 94 47 95 64 96 16 97 17 98 65 99 49 100 48 101 64 102 17 103 18 104 65 105 50 106 49 107 64 108 18 109 19 110 65 111 51 112 50 113 64 114 19 115 20 116 65 117 52 118 51 119 64 120 20 121 21 122 65 123 53 124 52 125 64 126 21 127 22 128 65 129 54 130 53 131 64 132 22 133 23 134 65 135 55 136 54 137 64 138 23 139 24 140 65 141 56 142 55 143 64 144 24 145 25 146 65 147 57 148 56 149 64 150 25 151 26 152 65 153 58 154 57 155 64 156 26 157 27 158 65 159 59 160 58 161 64 162 27 163 28 164 65 165 60 166 59 167 64 168 28 169 29 170 65 171 61 172 60 173 64 174 29 175 30 176 65 177 62 178 61 179 64 180 30 181 31 182 65 183 63 184 62 185 31 186 0 187 64 188 65 189 32 190 63 191 0 192 32 193 33 194 33 195 1 196 0 197 1 198 33 199 34 200 34 201 2 202 1 203 2 204 34 205 35 206 35 207 3 208 2 209 3 210 35 211 36 212 36 213 4 214 3 215 4 216 36 217 37 218 37 219 5 220 4 221 5 222 37 223 38 224 38 225 6 226 5 227 6 228 38 229 39 230 39 231 7 232 6 233 7 234 39 235 40 236 40 237 8 238 7 239 8 240 40 241 41 242 41 243 9 244 8 245 9 246 41 247 42 248 42 249 10 250 9 251 10 252 42 253 43 254 43 255 11 256 10 257 11 258 43 259 44 260 44 261 12 262 11 263 12 264 44 265 45 266 45 267 13 268 12 269 13 270 45 271 46 272 46 273 14 274 13 275 14 276 46 277 47 278 47 279 15 280 14 281 15 282 47 283 48 284 48 285 16 286 15 287 16 288 48 289 49 290 49 291 17 292 16 293 17 294 49 295 50 296 50 297 18 298 17 299 18 300 50 301 51 302 51 303 19 304 18 305 19 306 51 307 52 308 52 309 20 310 19 311 20 312 52 313 53 314 53 315 21 316 20 317 21 318 53 319 54 320 54 321 22 322 21 323 22 324 54 325 55 326 55 327 23 328 22 329 23 330 55 331 56 332 56 333 24 334 23 335 24 336 56 337 57 338 57 339 25 340 24 341 25 342 57 343 58 344 58 345 26 346 25 347 26 348 58 349 59 350 59 351 27 352 26 353 27 354 59 355 60 356 60 357 28 358 27 359 28 360 60 361 61 362 61 363 29 364 28 365 29 366 61 367 62 368 62 369 30 370 29 371 30 372 62 373 63 374 63 375 31 376 30 377 32 378 0 379 31 380 31 381 63 382 32 383

      +
      +
      +
      + + + + 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 1.0 1.0 1.0 1.17588 0.78569 1.0 1.30656 0.54119 1.0 1.38704 0.2759 1.0 1.41421 -0.0 1.0 1.38704 -0.2759 1.0 1.30656 -0.5412 1.0 1.17587 -0.7857 1.0 1.0 -1.0 1.0 0.78569 -1.17588 1.0 0.5412 -1.30656 1.0 0.2759 -1.38704 1.0 0.0 -1.41421 1.0 -0.2759 -1.38704 1.0 -0.54119 -1.30656 1.0 -0.78569 -1.17588 1.0 -1.0 -1.0 1.0 -1.17587 -0.7857 1.0 -1.30656 -0.5412 1.0 -1.38704 -0.2759 1.0 -1.41421 -1e-05 1.0 -1.38704 0.27589 1.0 -1.30657 0.54119 1.0 -1.17588 0.78569 1.0 -1.00001 0.99999 1.0 -0.7857 1.17587 1.0 -0.5412 1.30656 1.0 -0.27591 1.38704 1.0 -1e-05 1.41421 1.0 0.27589 1.38704 1.0 0.54119 1.30657 1.0 0.78569 1.17588 1.0 -0.0 0.0 -1.0 0.0 -0.0 1.0 + + + + + + + + + + 0.49876 0.49876 -0.70879 0.5865 0.39189 -0.70879 0.65169 0.26994 -0.70879 0.69182 0.13761 -0.70879 0.70537 0.0 -0.70879 0.69182 -0.13761 -0.70879 0.65169 -0.26994 -0.70879 0.5865 -0.39189 -0.70879 0.49876 -0.49876 -0.70879 0.39189 -0.5865 -0.70879 0.26994 -0.65169 -0.70879 0.13761 -0.69182 -0.70879 0.0 -0.70537 -0.70879 -0.13761 -0.69182 -0.70879 -0.26994 -0.65169 -0.70879 -0.39189 -0.5865 -0.70879 -0.49876 -0.49876 -0.70879 -0.5865 -0.39189 -0.70879 -0.65169 -0.26994 -0.70879 -0.69182 -0.13761 -0.70879 -0.70537 0.0 -0.70879 -0.69182 0.13761 -0.70879 -0.65169 0.26994 -0.70879 -0.5865 0.39189 -0.70879 -0.49876 0.49876 -0.70879 -0.39189 0.5865 -0.70879 -0.26994 0.65169 -0.70879 -0.13761 0.69182 -0.70879 0.0 0.70537 -0.70879 0.13761 0.69182 -0.70879 0.26994 0.65169 -0.70879 0.39189 0.5865 -0.70879 0.49876 0.49876 0.70879 0.5865 0.39189 0.70879 0.65169 0.26994 0.70879 0.69182 0.13761 0.70879 0.70537 0.0 0.70879 0.69182 -0.13761 0.70879 0.65169 -0.26994 0.70879 0.5865 -0.39189 0.70879 0.49876 -0.49876 0.70879 0.39189 -0.5865 0.70879 0.26994 -0.65169 0.70879 0.13761 -0.69182 0.70879 0.0 -0.70537 0.70879 -0.13761 -0.69182 0.70879 -0.26994 -0.65169 0.70879 -0.39189 -0.5865 0.70879 -0.49876 -0.49876 0.70879 -0.5865 -0.39189 0.70879 -0.65169 -0.26994 0.70879 -0.69182 -0.13761 0.70879 -0.70537 0.0 0.70879 -0.69182 0.13761 0.70879 -0.65169 0.26994 0.70879 -0.5865 0.39189 0.70879 -0.49876 0.49876 0.70879 -0.39189 0.5865 0.70879 -0.26994 0.65169 0.70879 -0.13761 0.69182 0.70879 0.0 0.70537 0.70879 0.13761 0.69182 0.70879 0.26994 0.65169 0.70879 0.39189 0.5865 0.70879 0.0 0.0 -1.0 0.0 0.0 1.0 + + + + + + + + + + 1.10675 0.0 0.625 0.0 0.59375 0.0 0.60675 1.0 0.59375 1.0 0.625 1.0 0.10675 0.0 0.59375 0.0 0.5625 0.0 0.60675 1.0 0.5625 1.0 0.59375 1.0 0.10675 0.0 0.5625 0.0 0.53125 0.0 0.60675 1.0 0.53125 1.0 0.5625 1.0 0.10675 0.0 0.53125 0.0 0.5 0.0 0.60675 1.0 0.5 1.0 0.53125 1.0 0.10675 0.0 0.5 0.0 0.46875 0.0 0.60675 1.0 0.46875 1.0 0.5 1.0 0.10675 0.0 0.46875 0.0 0.4375 0.0 0.60675 1.0 0.4375 1.0 0.46875 1.0 0.10675 0.0 0.4375 0.0 0.40625 0.0 0.60675 1.0 0.40625 1.0 0.4375 1.0 0.10675 0.0 0.40625 0.0 0.375 0.0 0.60675 1.0 0.375 1.0 0.40625 1.0 0.10675 0.0 0.375 0.0 0.34375 0.0 0.60675 1.0 0.34375 1.0 0.375 1.0 0.10675 0.0 0.34375 0.0 0.3125 0.0 0.60675 1.0 0.3125 1.0 0.34375 1.0 0.10675 0.0 0.3125 0.0 0.28125 0.0 0.60675 1.0 0.28125 1.0 0.3125 1.0 0.10675 0.0 0.28125 0.0 0.25 0.0 0.60675 1.0 0.25 1.0 0.28125 1.0 0.10675 0.0 0.25 0.0 0.21875 0.0 0.60675 1.0 0.21875 1.0 0.25 1.0 0.10675 0.0 0.21875 0.0 0.1875 0.0 0.60675 1.0 0.1875 1.0 0.21875 1.0 0.10675 0.0 0.1875 0.0 0.15625 0.0 0.60675 1.0 0.15625 1.0 0.1875 1.0 0.10675 0.0 0.15625 0.0 0.125 0.0 0.60675 1.0 0.125 1.0 0.15625 1.0 0.10675 0.0 0.125 0.0 0.09375 0.0 0.60675 1.0 1.09375 1.0 0.125 1.0 0.10675 0.0 0.09375 0.0 0.0625 0.0 0.60675 1.0 1.0625 1.0 1.09375 1.0 0.10675 0.0 0.0625 0.0 0.03125 0.0 0.60675 1.0 1.03125 1.0 1.0625 1.0 1.10675 0.0 1.03125 0.0 1.0 0.0 0.60675 1.0 1.0 1.0 1.03125 1.0 1.10675 0.0 1.0 0.0 0.96875 -0.0 0.60675 1.0 0.96875 1.0 1.0 1.0 1.10675 0.0 0.96875 -0.0 0.9375 -0.0 0.60675 1.0 0.9375 1.0 0.96875 1.0 1.10675 0.0 0.9375 -0.0 0.90625 0.0 0.60675 1.0 0.90625 1.0 0.9375 1.0 1.10675 0.0 0.90625 0.0 0.875 0.0 0.60675 1.0 0.875 1.0 0.90625 1.0 1.10675 0.0 0.875 0.0 0.84375 -0.0 0.60675 1.0 0.84375 1.0 0.875 1.0 1.10675 0.0 0.84375 -0.0 0.8125 -0.0 0.60675 1.0 0.8125 1.0 0.84375 1.0 1.10675 0.0 0.8125 -0.0 0.78125 -0.0 0.60675 1.0 0.78125 1.0 0.8125 1.0 1.10675 0.0 0.78125 -0.0 0.75 -0.0 0.60675 1.0 0.75 1.0 0.78125 1.0 1.10675 0.0 0.75 -0.0 0.71875 -0.0 0.60675 1.0 0.71875 1.0 0.75 1.0 1.10675 0.0 0.71875 -0.0 0.6875 -0.0 0.60675 1.0 0.6875 1.0 0.71875 1.0 1.10675 0.0 0.6875 -0.0 0.65625 -0.0 0.60675 1.0 0.65625 1.0 0.6875 1.0 0.65625 -0.0 0.625 0.0 1.10675 0.0 0.60675 1.0 0.625 1.0 0.65625 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.625 1.0 0.625 0.0 0.65625 -0.0 0.625 1.0 0.625 0.0 0.65625 -0.0 + + + + + + + + + + + + + + +

      64 0 0 1 1 2 65 3 33 4 32 5 64 6 1 7 2 8 65 9 34 10 33 11 64 12 2 13 3 14 65 15 35 16 34 17 64 18 3 19 4 20 65 21 36 22 35 23 64 24 4 25 5 26 65 27 37 28 36 29 64 30 5 31 6 32 65 33 38 34 37 35 64 36 6 37 7 38 65 39 39 40 38 41 64 42 7 43 8 44 65 45 40 46 39 47 64 48 8 49 9 50 65 51 41 52 40 53 64 54 9 55 10 56 65 57 42 58 41 59 64 60 10 61 11 62 65 63 43 64 42 65 64 66 11 67 12 68 65 69 44 70 43 71 64 72 12 73 13 74 65 75 45 76 44 77 64 78 13 79 14 80 65 81 46 82 45 83 64 84 14 85 15 86 65 87 47 88 46 89 64 90 15 91 16 92 65 93 48 94 47 95 64 96 16 97 17 98 65 99 49 100 48 101 64 102 17 103 18 104 65 105 50 106 49 107 64 108 18 109 19 110 65 111 51 112 50 113 64 114 19 115 20 116 65 117 52 118 51 119 64 120 20 121 21 122 65 123 53 124 52 125 64 126 21 127 22 128 65 129 54 130 53 131 64 132 22 133 23 134 65 135 55 136 54 137 64 138 23 139 24 140 65 141 56 142 55 143 64 144 24 145 25 146 65 147 57 148 56 149 64 150 25 151 26 152 65 153 58 154 57 155 64 156 26 157 27 158 65 159 59 160 58 161 64 162 27 163 28 164 65 165 60 166 59 167 64 168 28 169 29 170 65 171 61 172 60 173 64 174 29 175 30 176 65 177 62 178 61 179 64 180 30 181 31 182 65 183 63 184 62 185 31 186 0 187 64 188 65 189 32 190 63 191 0 192 32 193 33 194 33 195 1 196 0 197 1 198 33 199 34 200 34 201 2 202 1 203 2 204 34 205 35 206 35 207 3 208 2 209 3 210 35 211 36 212 36 213 4 214 3 215 4 216 36 217 37 218 37 219 5 220 4 221 5 222 37 223 38 224 38 225 6 226 5 227 6 228 38 229 39 230 39 231 7 232 6 233 7 234 39 235 40 236 40 237 8 238 7 239 8 240 40 241 41 242 41 243 9 244 8 245 9 246 41 247 42 248 42 249 10 250 9 251 10 252 42 253 43 254 43 255 11 256 10 257 11 258 43 259 44 260 44 261 12 262 11 263 12 264 44 265 45 266 45 267 13 268 12 269 13 270 45 271 46 272 46 273 14 274 13 275 14 276 46 277 47 278 47 279 15 280 14 281 15 282 47 283 48 284 48 285 16 286 15 287 16 288 48 289 49 290 49 291 17 292 16 293 17 294 49 295 50 296 50 297 18 298 17 299 18 300 50 301 51 302 51 303 19 304 18 305 19 306 51 307 52 308 52 309 20 310 19 311 20 312 52 313 53 314 53 315 21 316 20 317 21 318 53 319 54 320 54 321 22 322 21 323 22 324 54 325 55 326 55 327 23 328 22 329 23 330 55 331 56 332 56 333 24 334 23 335 24 336 56 337 57 338 57 339 25 340 24 341 25 342 57 343 58 344 58 345 26 346 25 347 26 348 58 349 59 350 59 351 27 352 26 353 27 354 59 355 60 356 60 357 28 358 27 359 28 360 60 361 61 362 61 363 29 364 28 365 29 366 61 367 62 368 62 369 30 370 29 371 30 372 62 373 63 374 63 375 31 376 30 377 32 378 0 379 31 380 31 381 63 382 32 383

      +
      +
      +
      + + + + 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 1.0 1.0 1.0 1.17588 0.78569 1.0 1.30656 0.54119 1.0 1.38704 0.2759 1.0 1.41421 -0.0 1.0 1.38704 -0.2759 1.0 1.30656 -0.5412 1.0 1.17587 -0.7857 1.0 1.0 -1.0 1.0 0.78569 -1.17588 1.0 0.5412 -1.30656 1.0 0.2759 -1.38704 1.0 0.0 -1.41421 1.0 -0.2759 -1.38704 1.0 -0.54119 -1.30656 1.0 -0.78569 -1.17588 1.0 -1.0 -1.0 1.0 -1.17587 -0.7857 1.0 -1.30656 -0.5412 1.0 -1.38704 -0.2759 1.0 -1.41421 -1e-05 1.0 -1.38704 0.27589 1.0 -1.30657 0.54119 1.0 -1.17588 0.78569 1.0 -1.00001 0.99999 1.0 -0.7857 1.17587 1.0 -0.5412 1.30656 1.0 -0.27591 1.38704 1.0 -1e-05 1.41421 1.0 0.27589 1.38704 1.0 0.54119 1.30657 1.0 0.78569 1.17588 1.0 -0.0 0.0 -1.0 0.0 -0.0 1.0 + + + + + + + + + + 0.49876 0.49876 -0.70879 0.5865 0.39189 -0.70879 0.65169 0.26994 -0.70879 0.69182 0.13761 -0.70879 0.70537 0.0 -0.70879 0.69182 -0.13761 -0.70879 0.65169 -0.26994 -0.70879 0.5865 -0.39189 -0.70879 0.49876 -0.49876 -0.70879 0.39189 -0.5865 -0.70879 0.26994 -0.65169 -0.70879 0.13761 -0.69182 -0.70879 0.0 -0.70537 -0.70879 -0.13761 -0.69182 -0.70879 -0.26994 -0.65169 -0.70879 -0.39189 -0.5865 -0.70879 -0.49876 -0.49876 -0.70879 -0.5865 -0.39189 -0.70879 -0.65169 -0.26994 -0.70879 -0.69182 -0.13761 -0.70879 -0.70537 0.0 -0.70879 -0.69182 0.13761 -0.70879 -0.65169 0.26994 -0.70879 -0.5865 0.39189 -0.70879 -0.49876 0.49876 -0.70879 -0.39189 0.5865 -0.70879 -0.26994 0.65169 -0.70879 -0.13761 0.69182 -0.70879 0.0 0.70537 -0.70879 0.13761 0.69182 -0.70879 0.26994 0.65169 -0.70879 0.39189 0.5865 -0.70879 0.49876 0.49876 0.70879 0.5865 0.39189 0.70879 0.65169 0.26994 0.70879 0.69182 0.13761 0.70879 0.70537 0.0 0.70879 0.69182 -0.13761 0.70879 0.65169 -0.26994 0.70879 0.5865 -0.39189 0.70879 0.49876 -0.49876 0.70879 0.39189 -0.5865 0.70879 0.26994 -0.65169 0.70879 0.13761 -0.69182 0.70879 0.0 -0.70537 0.70879 -0.13761 -0.69182 0.70879 -0.26994 -0.65169 0.70879 -0.39189 -0.5865 0.70879 -0.49876 -0.49876 0.70879 -0.5865 -0.39189 0.70879 -0.65169 -0.26994 0.70879 -0.69182 -0.13761 0.70879 -0.70537 0.0 0.70879 -0.69182 0.13761 0.70879 -0.65169 0.26994 0.70879 -0.5865 0.39189 0.70879 -0.49876 0.49876 0.70879 -0.39189 0.5865 0.70879 -0.26994 0.65169 0.70879 -0.13761 0.69182 0.70879 0.0 0.70537 0.70879 0.13761 0.69182 0.70879 0.26994 0.65169 0.70879 0.39189 0.5865 0.70879 0.0 0.0 -1.0 0.0 0.0 1.0 + + + + + + + + + + 1.10675 0.0 0.625 0.0 0.59375 0.0 0.60675 1.0 0.59375 1.0 0.625 1.0 0.10675 0.0 0.59375 0.0 0.5625 0.0 0.60675 1.0 0.5625 1.0 0.59375 1.0 0.10675 0.0 0.5625 0.0 0.53125 0.0 0.60675 1.0 0.53125 1.0 0.5625 1.0 0.10675 0.0 0.53125 0.0 0.5 0.0 0.60675 1.0 0.5 1.0 0.53125 1.0 0.10675 0.0 0.5 0.0 0.46875 0.0 0.60675 1.0 0.46875 1.0 0.5 1.0 0.10675 0.0 0.46875 0.0 0.4375 0.0 0.60675 1.0 0.4375 1.0 0.46875 1.0 0.10675 0.0 0.4375 0.0 0.40625 0.0 0.60675 1.0 0.40625 1.0 0.4375 1.0 0.10675 0.0 0.40625 0.0 0.375 0.0 0.60675 1.0 0.375 1.0 0.40625 1.0 0.10675 0.0 0.375 0.0 0.34375 0.0 0.60675 1.0 0.34375 1.0 0.375 1.0 0.10675 0.0 0.34375 0.0 0.3125 0.0 0.60675 1.0 0.3125 1.0 0.34375 1.0 0.10675 0.0 0.3125 0.0 0.28125 0.0 0.60675 1.0 0.28125 1.0 0.3125 1.0 0.10675 0.0 0.28125 0.0 0.25 0.0 0.60675 1.0 0.25 1.0 0.28125 1.0 0.10675 0.0 0.25 0.0 0.21875 0.0 0.60675 1.0 0.21875 1.0 0.25 1.0 0.10675 0.0 0.21875 0.0 0.1875 0.0 0.60675 1.0 0.1875 1.0 0.21875 1.0 0.10675 0.0 0.1875 0.0 0.15625 0.0 0.60675 1.0 0.15625 1.0 0.1875 1.0 0.10675 0.0 0.15625 0.0 0.125 0.0 0.60675 1.0 0.125 1.0 0.15625 1.0 0.10675 0.0 0.125 0.0 0.09375 0.0 0.60675 1.0 1.09375 1.0 0.125 1.0 0.10675 0.0 0.09375 0.0 0.0625 0.0 0.60675 1.0 1.0625 1.0 1.09375 1.0 0.10675 0.0 0.0625 0.0 0.03125 0.0 0.60675 1.0 1.03125 1.0 1.0625 1.0 1.10675 0.0 1.03125 0.0 1.0 0.0 0.60675 1.0 1.0 1.0 1.03125 1.0 1.10675 0.0 1.0 0.0 0.96875 -0.0 0.60675 1.0 0.96875 1.0 1.0 1.0 1.10675 0.0 0.96875 -0.0 0.9375 -0.0 0.60675 1.0 0.9375 1.0 0.96875 1.0 1.10675 0.0 0.9375 -0.0 0.90625 0.0 0.60675 1.0 0.90625 1.0 0.9375 1.0 1.10675 0.0 0.90625 0.0 0.875 0.0 0.60675 1.0 0.875 1.0 0.90625 1.0 1.10675 0.0 0.875 0.0 0.84375 -0.0 0.60675 1.0 0.84375 1.0 0.875 1.0 1.10675 0.0 0.84375 -0.0 0.8125 -0.0 0.60675 1.0 0.8125 1.0 0.84375 1.0 1.10675 0.0 0.8125 -0.0 0.78125 -0.0 0.60675 1.0 0.78125 1.0 0.8125 1.0 1.10675 0.0 0.78125 -0.0 0.75 -0.0 0.60675 1.0 0.75 1.0 0.78125 1.0 1.10675 0.0 0.75 -0.0 0.71875 -0.0 0.60675 1.0 0.71875 1.0 0.75 1.0 1.10675 0.0 0.71875 -0.0 0.6875 -0.0 0.60675 1.0 0.6875 1.0 0.71875 1.0 1.10675 0.0 0.6875 -0.0 0.65625 -0.0 0.60675 1.0 0.65625 1.0 0.6875 1.0 0.65625 -0.0 0.625 0.0 1.10675 0.0 0.60675 1.0 0.625 1.0 0.65625 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.625 1.0 0.625 0.0 0.65625 -0.0 0.625 1.0 0.625 0.0 0.65625 -0.0 + + + + + + + + + + + + + + +

      64 0 0 1 1 2 65 3 33 4 32 5 64 6 1 7 2 8 65 9 34 10 33 11 64 12 2 13 3 14 65 15 35 16 34 17 64 18 3 19 4 20 65 21 36 22 35 23 64 24 4 25 5 26 65 27 37 28 36 29 64 30 5 31 6 32 65 33 38 34 37 35 64 36 6 37 7 38 65 39 39 40 38 41 64 42 7 43 8 44 65 45 40 46 39 47 64 48 8 49 9 50 65 51 41 52 40 53 64 54 9 55 10 56 65 57 42 58 41 59 64 60 10 61 11 62 65 63 43 64 42 65 64 66 11 67 12 68 65 69 44 70 43 71 64 72 12 73 13 74 65 75 45 76 44 77 64 78 13 79 14 80 65 81 46 82 45 83 64 84 14 85 15 86 65 87 47 88 46 89 64 90 15 91 16 92 65 93 48 94 47 95 64 96 16 97 17 98 65 99 49 100 48 101 64 102 17 103 18 104 65 105 50 106 49 107 64 108 18 109 19 110 65 111 51 112 50 113 64 114 19 115 20 116 65 117 52 118 51 119 64 120 20 121 21 122 65 123 53 124 52 125 64 126 21 127 22 128 65 129 54 130 53 131 64 132 22 133 23 134 65 135 55 136 54 137 64 138 23 139 24 140 65 141 56 142 55 143 64 144 24 145 25 146 65 147 57 148 56 149 64 150 25 151 26 152 65 153 58 154 57 155 64 156 26 157 27 158 65 159 59 160 58 161 64 162 27 163 28 164 65 165 60 166 59 167 64 168 28 169 29 170 65 171 61 172 60 173 64 174 29 175 30 176 65 177 62 178 61 179 64 180 30 181 31 182 65 183 63 184 62 185 31 186 0 187 64 188 65 189 32 190 63 191 0 192 32 193 33 194 33 195 1 196 0 197 1 198 33 199 34 200 34 201 2 202 1 203 2 204 34 205 35 206 35 207 3 208 2 209 3 210 35 211 36 212 36 213 4 214 3 215 4 216 36 217 37 218 37 219 5 220 4 221 5 222 37 223 38 224 38 225 6 226 5 227 6 228 38 229 39 230 39 231 7 232 6 233 7 234 39 235 40 236 40 237 8 238 7 239 8 240 40 241 41 242 41 243 9 244 8 245 9 246 41 247 42 248 42 249 10 250 9 251 10 252 42 253 43 254 43 255 11 256 10 257 11 258 43 259 44 260 44 261 12 262 11 263 12 264 44 265 45 266 45 267 13 268 12 269 13 270 45 271 46 272 46 273 14 274 13 275 14 276 46 277 47 278 47 279 15 280 14 281 15 282 47 283 48 284 48 285 16 286 15 287 16 288 48 289 49 290 49 291 17 292 16 293 17 294 49 295 50 296 50 297 18 298 17 299 18 300 50 301 51 302 51 303 19 304 18 305 19 306 51 307 52 308 52 309 20 310 19 311 20 312 52 313 53 314 53 315 21 316 20 317 21 318 53 319 54 320 54 321 22 322 21 323 22 324 54 325 55 326 55 327 23 328 22 329 23 330 55 331 56 332 56 333 24 334 23 335 24 336 56 337 57 338 57 339 25 340 24 341 25 342 57 343 58 344 58 345 26 346 25 347 26 348 58 349 59 350 59 351 27 352 26 353 27 354 59 355 60 356 60 357 28 358 27 359 28 360 60 361 61 362 61 363 29 364 28 365 29 366 61 367 62 368 62 369 30 370 29 371 30 372 62 373 63 374 63 375 31 376 30 377 32 378 0 379 31 380 31 381 63 382 32 383

      +
      +
      +
      + + + + 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 0.22491 -0.46923 0.2223 0.22491 -0.46923 -0.2223 0.22491 0.46923 -0.2223 0.22491 0.46923 0.2223 -0.22491 -0.46923 0.2223 -0.22491 -0.46923 -0.2223 -0.22491 0.46923 -0.2223 -0.22491 0.46923 0.2223 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.5076 0.17099 0.5076 0.02724 0.81102 0.02724 0.5076 0.17099 0.5076 0.02724 0.81102 0.02724 0.5076 0.17099 0.81102 0.17099 0.81102 0.02724 0.5076 0.17099 0.81102 0.17099 0.81102 0.02724 0.2494 0.17099 0.10396 0.17099 0.10396 0.02724 0.2494 0.17099 0.10396 0.17099 0.10396 0.02724 0.2494 0.48019 0.10396 0.48019 0.10396 0.78361 0.2494 0.48019 0.10396 0.48019 0.10396 0.78361 0.2494 0.67389 0.10396 0.67389 0.10396 0.81764 0.2494 0.67389 0.10396 0.67389 0.10396 0.81764 0.7506 0.48019 0.89604 0.48019 0.89604 0.78361 0.7506 0.48019 0.89604 0.48019 0.89604 0.78361 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 0.22491 -0.46923 0.2223 0.22491 -0.46923 -0.2223 0.22491 0.46923 -0.2223 0.22491 0.46923 0.2223 -0.22491 -0.46923 0.2223 -0.22491 -0.46923 -0.2223 -0.22491 0.46923 -0.2223 -0.22491 0.46923 0.2223 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

      0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

      +
      +
      +
      + + + + 0.22491 -0.46923 0.2223 0.22491 -0.46923 -0.2223 0.22491 0.46923 -0.2223 0.22491 0.46923 0.2223 -0.22491 -0.46923 0.2223 -0.22491 -0.46923 -0.2223 -0.22491 0.46923 -0.2223 -0.22491 0.46923 0.2223 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

      0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

      +
      +
      +
      + + + + 0.22491 -0.46923 0.2223 0.22491 -0.46923 -0.2223 0.22491 0.46923 -0.2223 0.22491 0.46923 0.2223 -0.22491 -0.46923 0.2223 -0.22491 -0.46923 -0.2223 -0.22491 0.46923 -0.2223 -0.22491 0.46923 0.2223 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

      0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

      +
      +
      +
      + + + + 0.22491 -0.46923 0.2223 0.22491 -0.46923 -0.2223 0.22491 0.46923 -0.2223 0.22491 0.46923 0.2223 -0.22491 -0.46923 0.2223 -0.22491 -0.46923 -0.2223 -0.22491 0.46923 -0.2223 -0.22491 0.46923 0.2223 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

      0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

      +
      +
      +
      + + + + 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

      0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

      +
      +
      +
      + + + + 1.0 1.0 -1.0 1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 1.0 -1.0 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0 -1.0 1.0 -1.0 1.0 1.0 + + + + + + + + + + 0.57735 0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

      0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

      +
      +
      +
      + + + + 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

      0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

      +
      +
      +
      + + + + 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

      0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

      +
      +
      +
      + + + + 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

      0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

      +
      +
      +
      + + + + 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

      0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

      +
      +
      +
      + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

      0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

      +
      +
      +
      + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

      0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

      +
      +
      +
      + + + + 15.68421 15.68421 0.0 15.68421 -15.68421 0.0 -15.68421 -15.68421 0.0 -15.6842 15.68421 0.0 0.0 15.68421 0.0 -15.68421 0.0 0.0 0.0 -15.68421 0.0 15.68421 -0.0 0.0 0.0 -0.0 0.0 7.84211 15.68421 0.0 -7.8421 15.68421 0.0 -15.68421 -7.8421 0.0 -15.68421 7.84211 0.0 7.84211 -15.68421 0.0 -7.84211 -15.68421 0.0 15.68421 7.8421 0.0 15.68421 -7.84211 0.0 -7.8421 0.0 0.0 0.0 7.8421 0.0 7.84211 -0.0 0.0 0.0 -7.84211 0.0 -7.8421 7.84211 0.0 7.84211 7.8421 0.0 -7.8421 -7.84211 0.0 7.84211 -7.84211 0.0 + + + + + + + + + + 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 + + + + + + + + + + + + + + +

      10 3 12 12 21 10 4 10 21 21 18 4 21 12 5 5 17 21 18 21 17 17 8 18 9 4 18 18 22 9 0 9 22 22 15 0 22 18 8 8 19 22 15 22 19 19 7 15 17 5 11 11 23 17 8 17 23 23 20 8 23 11 2 2 14 23 20 23 14 14 6 20 19 8 20 20 24 19 7 19 24 24 16 7 24 20 6 6 13 24 16 24 13 13 1 16

      +
      +
      +
      + + + + d:/bullet_logo.JPG + + + + + + + 1.0 1.0 0.71397 + 0.0 + 0.0 + 0.0 + + + + + + + + + + + + + + + + + + + + + + -14.55524 -12.21748 -0.85392 + 0.0 0.0 1.0 -0.0 + 0.0 1.0 0.0 -0.0 + 1.0 0.0 0.0 90.0 + + + + + + + + -14.51144 -12.21746 1.49207 + 0.0 0.0 1.0 -0.0 + 0.0 1.0 0.0 -0.0 + 1.0 0.0 0.0 90.0 + 0.59992 0.59992 0.59992 + + + + + + + + -10.54595 9.00056 -7.95634 + 0.0 0.0 1.0 161.23931 + 0.0 1.0 0.0 7.87085 + 1.0 0.0 0.0 -1.43785 + + + + + + + + + + -11.51412 -12.21752 -6.47685 + 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 -40.16574 + 1.0 0.0 0.0 89.99999 + + + + + + + + + + -10.80608 -12.21753 -8.20963 + 0.0 0.0 1.0 179.99999 + 0.0 1.0 0.0 -68.68968 + 1.0 0.0 0.0 -90.0 + + + + + + + + + + -12.13872 -12.21753 -8.73677 + 0.0 0.0 1.0 -0.0 + 0.0 1.0 0.0 61.88929 + 1.0 0.0 0.0 89.99999 + + + + + + + + + + -11.09567 -3.46707 -5.6227 + 0.0 0.0 1.0 13.53526 + 0.0 1.0 0.0 -3.36769 + 1.0 0.0 0.0 31.10502 + + + + + + + + + + -5.6758 9.44806 -7.98855 + 0.0 0.0 1.0 90.0 + 0.0 1.0 0.0 -30.45178 + 1.0 0.0 0.0 90.0 + + + + 5.76483 -5.12569 1.3994 + 0.0 0.0 1.0 -5.78135 + 0.0 1.0 0.0 8.39643 + 1.0 0.0 0.0 -226.35694 + + + + + + + + + + -4.6651 -3.31256 -8.47664 + 0.0 0.0 1.0 165.33786 + 0.0 1.0 0.0 -9.4701 + 1.0 0.0 0.0 164.1133 + + + + + + + + + + 12.0373 6.52345 -7.84086 + 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 -0.0 + 1.0 0.0 0.0 -36.81686 + + + + + + + + + + 10.69918 0.32979 -8.69131 + 0.0 0.0 1.0 -38.06934 + 0.0 1.0 0.0 0.0 + 1.0 0.0 0.0 0.0 + + + + + + + + + + 10.6716 0.3339 -6.5472 + 0.0 0.0 1.0 -38.06934 + 0.0 1.0 0.0 0.0 + 1.0 0.0 0.0 0.0 + + + + + + + + + + 10.64675 0.37131 -4.4428 + 0.0 0.0 1.0 -38.06934 + 0.0 1.0 0.0 0.0 + 1.0 0.0 0.0 0.0 + + + + + + + + + + 13.39988 -6.62079 -7.48373 + 0.0 0.0 1.0 -23.42368 + 0.0 1.0 0.0 -47.70962 + 1.0 0.0 0.0 14.68375 + + + + + + + + + + 1.07068 1.0946 -9.17122 + + + + + + + + + + 3.07068 1.0946 -9.17122 + + + + + + + + + + -0.92932 1.0946 -9.17122 + + + + + + + + + + -0.92932 1.0946 -7.17122 + + + + + + + + + + 3.07068 1.0946 -7.17122 + + + + + + + + + + 1.07068 1.0946 -7.17122 + + + + + + + + + + 1.07068 3.0946 -8.17122 + + + + + + + + + + 1.07068 -0.9054 -8.17122 + + + + + + + + + + 1.07068 1.0946 -8.17122 + + + + + + + + + + 1.07068 1.0946 -6.17122 + + + + + + + + + + 1.07068 -0.9054 -6.17122 + + + + + + + + + + 1.07068 3.0946 -6.17122 + + + + + + + + + + 1.07068 1.0946 -5.17122 + + + + + + + + + + 3.07068 1.0946 -5.17122 + + + + + + + + + + -0.92932 1.0946 -5.17122 + + + + + + + + + + -0.92932 1.0946 -3.17122 + + + + + + + + + + 3.07068 1.0946 -3.17122 + + + + + + + + + + 1.07068 1.0946 -3.17122 + + + + + + + + + + 1.07068 3.0946 -4.17122 + + + + + + + + + + 1.07068 -0.9054 -4.17122 + + + + + + + + + + 1.07068 1.0946 -4.17122 + + + + + + + + + + 1.07068 1.0946 -2.17122 + + + + + + + + + + 1.07068 -0.9054 -2.17122 + + + + + + + + + + 1.07068 3.0946 -2.17122 + + + + + + + + + + 1.07068 1.0946 -1.17122 + + + + + + + + + + 3.07068 1.0946 -1.17122 + + + + + + + + + + -0.92932 1.0946 -1.17122 + + + + + + + + + + -0.92932 1.0946 0.82878 + + + + + + + + + + 3.07068 1.0946 0.82878 + + + + + + + + + + 1.07068 1.0946 0.82878 + + + + + + + + + + 1.07068 3.0946 -0.17122 + + + + + + + + + + 1.07068 -0.9054 -0.17122 + + + + + + + + + + 1.07068 1.0946 -0.17122 + + + + + + + + + + 1.07068 1.0946 1.82878 + + + + + + + + + + 1.07068 -0.9054 1.82878 + + + + + + + + + + 1.07068 3.0946 1.82878 + + + + + + + + + + 1.07068 1.0946 2.82878 + + + + + + + + + + 3.07068 1.0946 2.82878 + + + + + + + + + + -0.92932 1.0946 2.82878 + + + + + + + + + + 1.07068 -12.41267 -2.84635 + 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 -0.0 + 1.0 0.0 0.0 -146.99812 + + + + + + + + + + 1.07068 -12.65713 -3.97696 + 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 -0.0 + 1.0 0.0 0.0 -146.99812 + + + + + + + + + + 1.07068 -12.93214 -4.92423 + 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 -0.0 + 1.0 0.0 0.0 -146.99812 + + + + + + + + + + 1.07068 -15.19337 -5.0159 + 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 -0.0 + 1.0 0.0 0.0 -146.99812 + + + + + + + + + + 1.07068 -13.57384 -7.5827 + 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 -0.0 + 1.0 0.0 0.0 -146.99812 + + + + + + + + + + 0.62583 12.00328 -8.00472 + 0.0 0.0 1.0 3.21265 + 0.0 1.0 0.0 -12.03335 + 1.0 0.0 0.0 66.50218 + + + + + + + + + + 1.28844 9.15244 -3.68906 + + + + 1.07068 -7.9054 -7.17122 + + + + + + + + + + 1.07068 -8.9054 -8.17122 + + + + + + + + + + 1.07068 -6.9054 -8.17122 + + + + + + + + + + 1.07068 -7.9054 -9.17122 + + + + + + + + + + -6.69969 -10.22419 -7.75589 + 0.0 0.0 1.0 -0.18482 + 0.0 1.0 0.0 -14.9718 + 1.0 0.0 0.0 -1.78118 + + + + + + + + + + 3.07068 1.0946 4.82878 + + + + + + + + + + 1.07068 1.0946 4.82878 + + + + + + + + + + 1.07068 -5.9054 -9.17122 + + + + + + + + + + 1.07068 3.0946 3.82878 + + + + + + + + + + 1.07068 -0.9054 3.82878 + + + + + + + + + + 1.07068 1.0946 3.82878 + + + + + + + + + + 0.31712 0.02145 -9.78565 + + + + + + + + + + 9.62214 -5.88949 -0.13709 + 0.0 0.0 1.0 106.93632 + 0.0 1.0 0.0 3.16371 + 1.0 0.0 0.0 37.26105 + + + + -7.40201 -33.19793 -3.19828 + 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 0.0 + 1.0 0.0 0.0 90.0 + + + + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + + + + + 2.358 0.3455 0.0 + + + false + 1.0 + + + + + + + + + + 7.3295 1.456 0.0 + + + false + 1.0 + + + + + + + + + + 1.0 + 1.0 + 0 0 + 1.0 + + + true + 1.0 + + + + + + + + + + + true + 1.0 + + + + + + + + + + + true + 1.0 + + + + + + + + + + + true + 1.0 + + + + + + + + + + 1.4 + + + true + 1.0 + + + + + + + + + + 1.0 1.0 1.0 + + + true + 1.0 + + + + + + + + + + 1.0 + 1.0 + 0 0 + 0.42013 + + + true + 1.0 + + + + + + + + + + 1.0 + 1.0 + 0 0 + 1.0 + + + true + 1.0 + + + + + + + + + + 1.0 + 1.0 + 1.0 + + + true + 1.0 + + + + + + + + + + 1.0 + 1.0 + 1.0 + + + true + 1.0 + + + + + + + + + + 1.0 + 1.0 + 1.0 + + + true + 1.0 + + + + + + + + + + 1.0 + 1.0 + 1.0 + + + true + 1.0 + + + + + + + + + + 1.0 + 1.0 + 1.0 + + + true + 1.0 + + + + + + + + + + 0.97962 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 0.97962 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 0.98954 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 0.98954 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 0.97962 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 0.97962 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 0.98954 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 0.98954 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 0.97962 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 0.97962 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 0.98954 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 0.98954 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 0.97962 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 0.22491 0.46923 0.2223 + + + true + 1.0 + + + + + + + + + + 0.22491 0.46923 0.2223 + + + true + 1.0 + + + + + + + + + + 0.22491 0.46923 0.2223 + + + true + 1.0 + + + + + + + + + + 0.22491 0.46923 0.2223 + + + true + 1.0 + + + + + + + + + + 0.22491 0.46923 0.2223 + + + true + 1.0 + + + + + + + + + + 0.47933 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 1.0 1.0 1.0 + + + false + 1.0 + + + + + + + + + + 0.47933 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 0.47933 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 0.47933 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 0.47933 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 0.97962 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 0.47933 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 0.98954 0.47376 + + + true + 1.0 + + + + + + + + + + + false + 1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 0 -9.810000 + 0.0166666 + + + + + + + + diff --git a/lib/readme.txt b/lib/readme.txt new file mode 100644 index 0000000..b384ca2 --- /dev/null +++ b/lib/readme.txt @@ -0,0 +1,13 @@ +At the moment there are no binary packages from Bullet library. +Once this is done, the libraries will be placed here + +LinearMath +BulletCollision +BulletDynamics + +The C-API will be available in the include folder. + +For now, there is only C++ files, see src/btBulletCollisionCommon.h and src/btBulletDynamicsCommon.h + +http://bullet.googlecode.com +Erwin Coumans diff --git a/msvc/autoexp_dat.txt b/msvc/autoexp_dat.txt new file mode 100644 index 0000000..386edf4 --- /dev/null +++ b/msvc/autoexp_dat.txt @@ -0,0 +1,66 @@ + +;------------------------------------------------------------------------------ +; Microsoft Visual Studio Debug Visualization for Bullet btVector3 and btAlignedObjectArray +; +; Copy and paste the contents of this file to the end of autoexp.dat, usually located at +; C:\Program Files\Microsoft Visual Studio 8\Common7\Packages\Debugger\autoexp.dat +;------------------------------------------------------------------------------ + + +[Visualizer] +;------------------------------------------------------------------------------ +; btVector3 +;------------------------------------------------------------------------------ +btVector3{ + children + ( + #array + ( + expr : ($c.m_floats)[$i], + size : 4 + ) + ) + + preview + ( + #( + "[", + #array + ( + expr : ($c.m_floats)[$i], + size : 4 + ), + "]" + ) + ) +} + +;------------------------------------------------------------------------------ +; btAlignedObjectArray +;------------------------------------------------------------------------------ +btAlignedObjectArray<*>{ + children + ( + #array + ( + expr : ($c.m_data)[$i], + size : $c.m_size + ) + ) + + preview + ( + #( + "[", + $c.m_size , + "](", + + #array + ( + expr : ($c.m_data)[$i], + size : $c.m_size + ), + ")" + ) + ) +} diff --git a/msvc/bullet.rc b/msvc/bullet.rc new file mode 100644 index 0000000..704b4d2 --- /dev/null +++ b/msvc/bullet.rc @@ -0,0 +1,29 @@ +// This file is generated automatically. + +1 VERSIONINFO +FILEVERSION 2, 79, 0, 0 +PRODUCTVERSION 2, 79, 0, 0 +#ifdef CS_DEBUG +FILEFLAGS 0x1 +#else +FILEFLAGS 0x0 +#endif +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "ProductName", "Bullet Continuous Collision Detection and Physics Library" + VALUE "ProductVersion", "2.79" + VALUE "FileVersion", "2.79" + VALUE "LegalCopyright", "Copyright (c) 2005-2011 Erwin Coumans" +#ifdef CS_DEBUG + VALUE "Comments", "Debug build" +#else + VALUE "Comments", "Release build" +#endif + VALUE "WWW", "http://www.bulletphysics.org" + } + } +} +1 ICON "bullet_ico.ico" diff --git a/msvc/bullet_ico.ico b/msvc/bullet_ico.ico new file mode 100644 index 0000000000000000000000000000000000000000..b006325fddc884810a0988639b4e631ad634a5ae GIT binary patch literal 21630 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 A;{X5v literal 0 HcmV?d00001 diff --git a/msvc/findDirectX11.lua b/msvc/findDirectX11.lua new file mode 100644 index 0000000..7f41abc --- /dev/null +++ b/msvc/findDirectX11.lua @@ -0,0 +1,36 @@ +function findDirectX11() + local dx11path = os.getenv("DXSDK_DIR") + if (dx11path) then + local filepath = string.format("%s%s",dx11path,"Include/D3D11.h") + headerdx11 = io.open(filepath, "r") + if (headerdx11) then + printf("Found DX11: '%s'", filepath) + return true + end + end + return false + end + +function initDirectX11() + configuration {} + + local dx11path = os.getenv("DXSDK_DIR") + defines { "ADL_ENABLE_DX11"} + includedirs {"$(DXSDK_DIR)/include"} + + configuration "x32" + libdirs {"$(DXSDK_DIR)/Lib/x86"} + configuration "x64" + libdirs {"$(DXSDK_DIR)/Lib/x64"} + configuration {} + links {"d3dcompiler", + "dxerr", + "dxguid", + "d3dx9", + "d3d9", + "winmm", + "comctl32", + "d3dx11" + } + return true +end \ No newline at end of file diff --git a/msvc/findOpenCL.lua b/msvc/findOpenCL.lua new file mode 100644 index 0000000..c77631f --- /dev/null +++ b/msvc/findOpenCL.lua @@ -0,0 +1,84 @@ + -- todo: add Apple OpenCL environment vars + + function findOpenCL_AMD() + local amdopenclpath = os.getenv("AMDAPPSDKROOT") + if (amdopenclpath) then + return true + end + return false + end + + function findOpenCL_NVIDIA() + local nvidiaopenclpath = os.getenv("CUDA_PATH") + if (nvidiaopenclpath) then + return true + end + return false + end + + function findOpenCL_Intel() + local intelopenclpath = os.getenv("INTELOCLSDKROOT") + if (intelopenclpath) then + return true + end + return false + end + + function initOpenCL_AMD() + configuration {} + local amdopenclpath = os.getenv("AMDAPPSDKROOT") + if (amdopenclpath) then + defines { "ADL_ENABLE_CL" , "CL_PLATFORM_AMD"} + includedirs { + "$(AMDAPPSDKROOT)/include" + } + configuration "x32" + libdirs {"$(AMDAPPSDKROOT)/lib/x86"} + configuration "x64" + libdirs {"$(AMDAPPSDKROOT)/lib/x86_64"} + configuration {} + links {"OpenCL"} + return true + end + return false + end + + + function initOpenCL_NVIDIA() + configuration {} + local nvidiaopenclpath = os.getenv("CUDA_PATH") + if (nvidiaopenclpath) then + defines { "ADL_ENABLE_CL" , "CL_PLATFORM_NVIDIA"} + includedirs { + "$(CUDA_PATH)/include" + } + configuration "x32" + libdirs {"$(CUDA_PATH)/lib/Win32"} + configuration "x64" + libdirs {"$(CUDA_PATH)/lib/x64"} + configuration {} + links {"OpenCL"} + return true + end + return false + end + + function initOpenCL_Intel() + configuration {} + local intelopenclpath = os.getenv("INTELOCLSDKROOT") + if (intelopenclpath) then + defines { "ADL_ENABLE_CL" , "CL_PLATFORM_INTEL"} + includedirs { + "$(INTELOCLSDKROOT)/include" + } + configuration "x32" + libdirs {"$(INTELOCLSDKROOT)/lib/x86"} + configuration "x64" + libdirs {"$(INTELOCLSDKROOT)/lib/x64"} + configuration {} + links {"OpenCL"} + return true + end + return false + end + \ No newline at end of file diff --git a/msvc/premake4.exe b/msvc/premake4.exe new file mode 100644 index 0000000000000000000000000000000000000000..072560edb578d278f98ca3cb216ce9b9cfce3604 GIT binary patch literal 281088 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¨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�u8p(9~&C5FlR*e4cr2W zkeheTCh8zMuHFLIxx-XLJVuG}(b≥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 literal 0 HcmV?d00001 diff --git a/msvc/premake4.lua b/msvc/premake4.lua new file mode 100644 index 0000000..f8a3866 --- /dev/null +++ b/msvc/premake4.lua @@ -0,0 +1,142 @@ +--add the 0 so the solution comes first in the directory (when sorted on name) +--print "uncomment this hello premake4 world for debugging the script" + +solution "0BulletSolution" + + + + newoption { + trigger = "with-nacl", + description = "Enable Native Client build" + } + + newoption { + trigger = "with-dx11", + description = "Enable DirectX11 build" + } + + newoption { + trigger = "with-opencl", + description = "Enable OpenCL builds (various SDKs)" + } + + newoption { + trigger = "with-opencl-amd", + description = "Enable OpenCL builds (AMD SDK)" + } + + newoption { + trigger = "with-opencl-intel", + description = "Enable OpenCL builds (Intel SDK)" + } + newoption { + trigger = "with-opencl-nvidia", + description = "Enable OpenCL builds (NVIDIA SDK)" + } + + + configurations {"Release", "Debug"} + configuration "Release" + flags { "Optimize", "StaticRuntime", "NoMinimalRebuild", "FloatFast"} + configuration "Debug" + flags { "Symbols", "StaticRuntime" , "NoMinimalRebuild", "NoEditAndContinue" ,"FloatFast"} + + platforms {"x32", "x64"} + + configuration "x64" + targetsuffix "_64" + configuration {"x64", "debug"} + targetsuffix "_x64_debug" + configuration {"x64", "release"} + targetsuffix "_x64" + configuration {"x32", "debug"} + targetsuffix "_debug" + + configuration {"Windows"} + defines { "_CRT_SECURE_NO_WARNINGS","_CRT_SECURE_NO_DEPRECATE"} + + configuration{} + + + +if not _OPTIONS["with-nacl"] then + + flags { "NoRTTI"} + targetdir "../bin" + + -- Disable exception handling on MSVC 2008 and higher. MSVC 2005 without service pack has some linker issue (ConvexDecompositionDemo uses STL through HACD library) + if _ACTION == "vs2010" or _ACTION=="vs2008" then + flags { "NoExceptions"} + defines { "_HAS_EXCEPTIONS=0" } + end + + -- Multithreaded compiling + if _ACTION == "vs2010" then + buildoptions { "/MP" } + end + + +else + targetdir "../bin_html" +end + + + dofile ("findOpenCL.lua") + dofile ("findDirectX11.lua") + + language "C++" + + location("./" .. _ACTION) + + if _OPTIONS["with-dx11"] then + include "../Demos/DX11ClothDemo" + include "../src/BulletMultiThreaded/GpuSoftBodySolvers/DX11" + end + +--choose any OpenCL sdk that is installed on the system + if _OPTIONS["with-opencl"] then + include "../Demos/OpenCLClothDemo/AMD" + include "../src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD" + include "../Demos/OpenCLClothDemo/NVidia" + include "../src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia" + include "../Demos/OpenCLClothDemo/Intel" + include "../src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel" + end + +--choose a particular OpenCL sdk, this is useful for distributing project files that just work for one OpenCL SDK + if _OPTIONS["with-opencl-amd"] then + include "../Demos/OpenCLClothDemo/AMD" + include "../Demos/OpenGL" + include "../Demos/SoftDemo/AMD" + include "../src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD" + end + + if _OPTIONS["with-opencl-intel"] then + include "../Demos/OpenCLClothDemo/Intel" + include "../src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel" + end + + if _OPTIONS["with-opencl-nvidia"] then + include "../Demos/OpenCLClothDemo/NVidia" + include "../src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia" + end + + if not _OPTIONS["with-opencl-amd"] and + not _OPTIONS["with-opencl-nvidia"] and + not _OPTIONS["with-opencl-intel"] and + not _OPTIONS["with-opencl"] and + not _OPTIONS["with-dx11"] and + not _OPTIONS["with-nacl"] then + + include "../Demos" + include "../Extras" + end + + if _OPTIONS["with-nacl"] then + include "../Demos/NativeClient" + else + include "../src/LinearMath" + include "../src/BulletCollision" + include "../src/BulletDynamics" + include "../src/BulletSoftBody" + end diff --git a/msvc/vs2005.bat b/msvc/vs2005.bat new file mode 100644 index 0000000..2bd3f8e --- /dev/null +++ b/msvc/vs2005.bat @@ -0,0 +1,4 @@ + +premake4 vs2005 + +pause \ No newline at end of file diff --git a/msvc/vs2008.bat b/msvc/vs2008.bat new file mode 100644 index 0000000..f172640 --- /dev/null +++ b/msvc/vs2008.bat @@ -0,0 +1,10 @@ + +rem premake4 --no-pelibs vs2008 +rem premake4 --no-pedemos vs2008 +rem premake4 --no-bulletlibs --no-pelibs vs2008 +rem premake4 --with-nacl vs2008 + +premake4 vs2008 + + +pause \ No newline at end of file diff --git a/msvc/vs2010.bat b/msvc/vs2010.bat new file mode 100644 index 0000000..8394561 --- /dev/null +++ b/msvc/vs2010.bat @@ -0,0 +1,4 @@ + +premake4 vs2010 + +pause \ No newline at end of file diff --git a/msvc/vs2010_dx11.bat b/msvc/vs2010_dx11.bat new file mode 100644 index 0000000..dd956da --- /dev/null +++ b/msvc/vs2010_dx11.bat @@ -0,0 +1,5 @@ + +premake4 --with-dx11 vs2010 + +rename vs2010 vs2010_dx11 +pause \ No newline at end of file diff --git a/msvc/vs2010_opencl.bat b/msvc/vs2010_opencl.bat new file mode 100644 index 0000000..fdb77cc --- /dev/null +++ b/msvc/vs2010_opencl.bat @@ -0,0 +1,8 @@ + + +premake4 --with-opencl-amd vs2010 + + +rename vs2010 vs2010_opencl_amd + +pause \ No newline at end of file diff --git a/msvc/vs_all.bat b/msvc/vs_all.bat new file mode 100644 index 0000000..60bf79b --- /dev/null +++ b/msvc/vs_all.bat @@ -0,0 +1,36 @@ +rem this script is mainly to create distributable visual studio project file + + +premake4 --with-opencl-nvidia vs2008 +rename vs2008 vs2008_opencl_nvidia + +premake4 --with-opencl-intel vs2008 +rename vs2008 vs2008_opencl_intel + +premake4 --with-opencl-amd vs2008 +rename vs2008 vs2008_opencl_amd + +premake4 --with-opencl-nvidia vs2010 +rename vs2010 vs2010_opencl_nvidia + +premake4 --with-opencl-intel vs2010 +rename vs2010 vs2010_opencl_intel + +premake4 --with-opencl-amd vs2010 +rename vs2010 vs2010_opencl_amd + +premake4 --with-dx11 vs2008 +rename vs2008 vs2008_dx11 + +premake4 --with-dx11 vs2010 +rename vs2010 vs2010_dx11 + +premake4 --with-dx11 vs2005 +rename vs2005 vs2005_dx11 + +premake4 vs2005 +premake4 vs2008 +premake4 vs2010 + + +pause \ No newline at end of file diff --git a/packaging/bullet.spec b/packaging/bullet.spec new file mode 100644 index 0000000..afc28bd --- /dev/null +++ b/packaging/bullet.spec @@ -0,0 +1,67 @@ +#sbs-git:slp/unmodified/libbullet bullet 2.77 ef5f1217bdb947807e117963430e967f0360817a +Name: libbullet +Version: 2.80 +Release: 1 +Summary: Bullet Continuous Collision Detection and Physics Library +License: Zlib +Group: TO_BE/FILLED_IN +Source: %{name}-%{version}.tar.gz +BuildRequires: cmake +#BuildRequires: pkgconfig(opengl-es-11) +#BuildRequires: pkgconfig(opengl-es-20) + +%description +Bullet Continuous Collision Detection and Physics Library + +%package devel +Summary: Development components for the bullet +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +Bullet Continuous Collision Detection and Physics Library (devel) + +%prep +%setup -q + + +%build + +cmake . -G "Unix Makefiles" -DBUILD_SHARED_LIBS=ON -DBUILD_EXTRAS=OFF -DBUILD_DEMOS=OFF -DBUILD_CPU_DEMOS=OFF -DUSE_GRAPHICAL_BENCHMARK=OFF -DCMAKE_INSTALL_PREFIX=/usr -DUSE_GLUT=OFF + +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + + +%post -p /sbin/ldconfig +%postun -p /sbin/ldconfig + + +%files +%defattr(-,root,root,-) +/usr/lib/libBulletCollision.so.2.80 +/usr/lib/libBulletDynamics.so.2.80 +/usr/lib/libBulletMultiThreaded.so.2.80 +/usr/lib/libBulletSoftBody.so.2.80 +/usr/lib/libBulletSoftBodySolvers_OpenCL_Mini.so.2.80 +/usr/lib/libLinearMath.so.2.80 +/usr/lib/libMiniCL.so.2.80 + + +%files devel +%defattr(-,root,root,-) +/usr/include/bullet/*.h +/usr/include/bullet/*/*/*/*.h +/usr/include/bullet/*/*/*.h +/usr/include/bullet/*/*.h +/usr/lib/libBulletCollision.so +/usr/lib/libBulletDynamics.so +/usr/lib/libBulletMultiThreaded.so +/usr/lib/libBulletSoftBody.so +/usr/lib/libBulletSoftBodySolvers_OpenCL_Mini.so +/usr/lib/libLinearMath.so +/usr/lib/libMiniCL.so +/usr/lib/pkgconfig/bullet.pc diff --git a/src/Bullet-C-Api.h b/src/Bullet-C-Api.h new file mode 100644 index 0000000..f27a17d --- /dev/null +++ b/src/Bullet-C-Api.h @@ -0,0 +1,176 @@ +/* +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. +*/ + +/* + Draft high-level generic physics C-API. For low-level access, use the physics SDK native API's. + Work in progress, functionality will be added on demand. + + If possible, use the richer Bullet C++ API, by including "btBulletDynamicsCommon.h" +*/ + +#ifndef BULLET_C_API_H +#define BULLET_C_API_H + +#define PL_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name + +#ifdef BT_USE_DOUBLE_PRECISION +typedef double plReal; +#else +typedef float plReal; +#endif + +typedef plReal plVector3[3]; +typedef plReal plQuaternion[4]; + +#ifdef __cplusplus +extern "C" { +#endif + +/** Particular physics SDK (C-API) */ + PL_DECLARE_HANDLE(plPhysicsSdkHandle); + +/** Dynamics world, belonging to some physics SDK (C-API)*/ + PL_DECLARE_HANDLE(plDynamicsWorldHandle); + +/** Rigid Body that can be part of a Dynamics World (C-API)*/ + PL_DECLARE_HANDLE(plRigidBodyHandle); + +/** Collision Shape/Geometry, property of a Rigid Body (C-API)*/ + PL_DECLARE_HANDLE(plCollisionShapeHandle); + +/** Constraint for Rigid Bodies (C-API)*/ + PL_DECLARE_HANDLE(plConstraintHandle); + +/** Triangle Mesh interface (C-API)*/ + PL_DECLARE_HANDLE(plMeshInterfaceHandle); + +/** Broadphase Scene/Proxy Handles (C-API)*/ + PL_DECLARE_HANDLE(plCollisionBroadphaseHandle); + PL_DECLARE_HANDLE(plBroadphaseProxyHandle); + PL_DECLARE_HANDLE(plCollisionWorldHandle); + +/** + Create and Delete a Physics SDK +*/ + + extern plPhysicsSdkHandle plNewBulletSdk(void); //this could be also another sdk, like ODE, PhysX etc. + extern void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk); + +/** Collision World, not strictly necessary, you can also just create a Dynamics World with Rigid Bodies which internally manages the Collision World with Collision Objects */ + + typedef void(*btBroadphaseCallback)(void* clientData, void* object1,void* object2); + + extern plCollisionBroadphaseHandle plCreateSapBroadphase(btBroadphaseCallback beginCallback,btBroadphaseCallback endCallback); + + extern void plDestroyBroadphase(plCollisionBroadphaseHandle bp); + + extern plBroadphaseProxyHandle plCreateProxy(plCollisionBroadphaseHandle bp, void* clientData, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ); + + extern void plDestroyProxy(plCollisionBroadphaseHandle bp, plBroadphaseProxyHandle proxyHandle); + + extern void plSetBoundingBox(plBroadphaseProxyHandle proxyHandle, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ); + +/* todo: add pair cache support with queries like add/remove/find pair */ + + extern plCollisionWorldHandle plCreateCollisionWorld(plPhysicsSdkHandle physicsSdk); + +/* todo: add/remove objects */ + + +/* Dynamics World */ + + extern plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdk); + + extern void plDeleteDynamicsWorld(plDynamicsWorldHandle world); + + extern void plStepSimulation(plDynamicsWorldHandle, plReal timeStep); + + extern void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object); + + extern void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object); + + +/* Rigid Body */ + + extern plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape ); + + extern void plDeleteRigidBody(plRigidBodyHandle body); + + +/* Collision Shape definition */ + + extern plCollisionShapeHandle plNewSphereShape(plReal radius); + extern plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z); + extern plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height); + extern plCollisionShapeHandle plNewConeShape(plReal radius, plReal height); + extern plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height); + extern plCollisionShapeHandle plNewCompoundShape(void); + extern void plAddChildShape(plCollisionShapeHandle compoundShape,plCollisionShapeHandle childShape, plVector3 childPos,plQuaternion childOrn); + + extern void plDeleteShape(plCollisionShapeHandle shape); + + /* Convex Meshes */ + extern plCollisionShapeHandle plNewConvexHullShape(void); + extern void plAddVertex(plCollisionShapeHandle convexHull, plReal x,plReal y,plReal z); +/* Concave static triangle meshes */ + extern plMeshInterfaceHandle plNewMeshInterface(void); + extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2); + extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle); + + extern void plSetScaling(plCollisionShapeHandle shape, plVector3 scaling); + +/* SOLID has Response Callback/Table/Management */ +/* PhysX has Triggers, User Callbacks and filtering */ +/* ODE has the typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2); */ + +/* typedef void plUpdatedPositionCallback(void* userData, plRigidBodyHandle rbHandle, plVector3 pos); */ +/* typedef void plUpdatedOrientationCallback(void* userData, plRigidBodyHandle rbHandle, plQuaternion orientation); */ + + /* get world transform */ + extern void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix); + extern void plGetPosition(plRigidBodyHandle object,plVector3 position); + extern void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation); + + /* set world transform (position/orientation) */ + extern void plSetPosition(plRigidBodyHandle object, const plVector3 position); + extern void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation); + extern void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient); + extern void plSetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix); + + typedef struct plRayCastResult { + plRigidBodyHandle m_body; + plCollisionShapeHandle m_shape; + plVector3 m_positionWorld; + plVector3 m_normalWorld; + } plRayCastResult; + + extern int plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plRayCastResult res); + + /* Sweep API */ + + /* extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); */ + + /* Continuous Collision Detection API */ + + // needed for source/blender/blenkernel/intern/collision.c + double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]); + +#ifdef __cplusplus +} +#endif + + +#endif //BULLET_C_API_H + diff --git a/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp new file mode 100644 index 0000000..7776330 --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp @@ -0,0 +1,37 @@ + +//Bullet Continuous Collision Detection and Physics Library +//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + + +// +// btAxisSweep3 +// +// Copyright (c) 2006 Simon Hobbs +// +// 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 "btAxisSweep3.h" + + +btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator) +:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache,disableRaycastAccelerator) +{ + // 1 handle is reserved as sentinel + btAssert(maxHandles > 1 && maxHandles < 32767); + +} + + +bt32BitAxisSweep3::bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache , bool disableRaycastAccelerator) +:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache,disableRaycastAccelerator) +{ + // 1 handle is reserved as sentinel + btAssert(maxHandles > 1 && maxHandles < 2147483647); +} diff --git a/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h new file mode 100644 index 0000000..4f4d94b --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h @@ -0,0 +1,1051 @@ +//Bullet Continuous Collision Detection and Physics Library +//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +// +// btAxisSweep3.h +// +// Copyright (c) 2006 Simon Hobbs +// +// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. + +#ifndef BT_AXIS_SWEEP_3_H +#define BT_AXIS_SWEEP_3_H + +#include "LinearMath/btVector3.h" +#include "btOverlappingPairCache.h" +#include "btBroadphaseInterface.h" +#include "btBroadphaseProxy.h" +#include "btOverlappingPairCallback.h" +#include "btDbvtBroadphase.h" + +//#define DEBUG_BROADPHASE 1 +#define USE_OVERLAP_TEST_ON_REMOVES 1 + +/// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase. +/// It uses quantized integers to represent the begin and end points for each of the 3 axis. +/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead. +template +class btAxisSweep3Internal : public btBroadphaseInterface +{ +protected: + + BP_FP_INT_TYPE m_bpHandleMask; + BP_FP_INT_TYPE m_handleSentinel; + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + class Edge + { + public: + BP_FP_INT_TYPE m_pos; // low bit is min/max + BP_FP_INT_TYPE m_handle; + + BP_FP_INT_TYPE IsMax() const {return static_cast(m_pos & 1);} + }; + +public: + class Handle : public btBroadphaseProxy + { + public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + // indexes into the edge arrays + BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12 +// BP_FP_INT_TYPE m_uniqueId; + btBroadphaseProxy* m_dbvtProxy;//for faster raycast + //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject + + SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;} + SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];} + }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry + + +protected: + btVector3 m_worldAabbMin; // overall system bounds + btVector3 m_worldAabbMax; // overall system bounds + + btVector3 m_quantize; // scaling factor for quantization + + BP_FP_INT_TYPE m_numHandles; // number of active handles + BP_FP_INT_TYPE m_maxHandles; // max number of handles + Handle* m_pHandles; // handles pool + + BP_FP_INT_TYPE m_firstFreeHandle; // free handles list + + Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries) + void* m_pEdgesRawPtr[3]; + + btOverlappingPairCache* m_pairCache; + + ///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache. + btOverlappingPairCallback* m_userPairCallback; + + bool m_ownsPairCache; + + int m_invalidPair; + + ///additional dynamic aabb structure, used to accelerate ray cast queries. + ///can be disabled using a optional argument in the constructor + btDbvtBroadphase* m_raycastAccelerator; + btOverlappingPairCache* m_nullPairCache; + + + // allocation/deallocation + BP_FP_INT_TYPE allocHandle(); + void freeHandle(BP_FP_INT_TYPE handle); + + + bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1); + +#ifdef DEBUG_BROADPHASE + void debugPrintAxis(int axis,bool checkCardinality=true); +#endif //DEBUG_BROADPHASE + + //Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB); + //void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB); + + + + void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + +public: + + btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0,bool disableRaycastAccelerator = false); + + virtual ~btAxisSweep3Internal(); + + BP_FP_INT_TYPE getNumHandles() const + { + return m_numHandles; + } + + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); + + BP_FP_INT_TYPE addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); + void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher); + void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); + SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;} + + virtual void resetPool(btDispatcher* dispatcher); + + void processAllOverlappingPairs(btOverlapCallback* callback); + + //Broadphase Interface + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); + virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; + + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)); + virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback); + + + void quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const; + ///unQuantize should be conservative: aabbMin/aabbMax should be larger then 'getAabb' result + void unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; + + bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + btOverlappingPairCache* getOverlappingPairCache() + { + return m_pairCache; + } + const btOverlappingPairCache* getOverlappingPairCache() const + { + return m_pairCache; + } + + void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback) + { + m_userPairCallback = pairCallback; + } + const btOverlappingPairCallback* getOverlappingPairUserCallback() const + { + return m_userPairCallback; + } + + ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame + ///will add some transform later + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin = m_worldAabbMin; + aabbMax = m_worldAabbMax; + } + + virtual void printStats() + { +/* printf("btAxisSweep3.h\n"); + printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles); + printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(), + m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ()); + */ + + } + +}; + +//////////////////////////////////////////////////////////////////// + + + + +#ifdef DEBUG_BROADPHASE +#include + +template +void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality) +{ + int numEdges = m_pHandles[0].m_maxEdges[axis]; + printf("SAP Axis %d, numEdges=%d\n",axis,numEdges); + + int i; + for (i=0;im_handle); + int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis]; + char beginOrEnd; + beginOrEnd=pEdge->IsMax()?'E':'B'; + printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex); + } + + if (checkCardinality) + btAssert(numEdges == m_numHandles*2+1); +} +#endif //DEBUG_BROADPHASE + +template +btBroadphaseProxy* btAxisSweep3Internal::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy) +{ + (void)shapeType; + BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,multiSapProxy); + + Handle* handle = getHandle(handleId); + + if (m_raycastAccelerator) + { + btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,0); + handle->m_dbvtProxy = rayProxy; + } + return handle; +} + + + +template +void btAxisSweep3Internal::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + Handle* handle = static_cast(proxy); + if (m_raycastAccelerator) + m_raycastAccelerator->destroyProxy(handle->m_dbvtProxy,dispatcher); + removeHandle(static_cast(handle->m_uniqueId), dispatcher); +} + +template +void btAxisSweep3Internal::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher) +{ + Handle* handle = static_cast(proxy); + handle->m_aabbMin = aabbMin; + handle->m_aabbMax = aabbMax; + updateHandle(static_cast(handle->m_uniqueId), aabbMin, aabbMax,dispatcher); + if (m_raycastAccelerator) + m_raycastAccelerator->setAabb(handle->m_dbvtProxy,aabbMin,aabbMax,dispatcher); + +} + +template +void btAxisSweep3Internal::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax) +{ + if (m_raycastAccelerator) + { + m_raycastAccelerator->rayTest(rayFrom,rayTo,rayCallback,aabbMin,aabbMax); + } else + { + //choose axis? + BP_FP_INT_TYPE axis = 0; + //for each proxy + for (BP_FP_INT_TYPE i=1;i +void btAxisSweep3Internal::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) +{ + if (m_raycastAccelerator) + { + m_raycastAccelerator->aabbTest(aabbMin,aabbMax,callback); + } else + { + //choose axis? + BP_FP_INT_TYPE axis = 0; + //for each proxy + for (BP_FP_INT_TYPE i=1;im_aabbMin,handle->m_aabbMax)) + { + callback.process(handle); + } + } + } + } +} + + + +template +void btAxisSweep3Internal::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const +{ + Handle* pHandle = static_cast(proxy); + aabbMin = pHandle->m_aabbMin; + aabbMax = pHandle->m_aabbMax; +} + + +template +void btAxisSweep3Internal::unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const +{ + Handle* pHandle = static_cast(proxy); + + unsigned short vecInMin[3]; + unsigned short vecInMax[3]; + + vecInMin[0] = m_pEdges[0][pHandle->m_minEdges[0]].m_pos ; + vecInMax[0] = m_pEdges[0][pHandle->m_maxEdges[0]].m_pos +1 ; + vecInMin[1] = m_pEdges[1][pHandle->m_minEdges[1]].m_pos ; + vecInMax[1] = m_pEdges[1][pHandle->m_maxEdges[1]].m_pos +1 ; + vecInMin[2] = m_pEdges[2][pHandle->m_minEdges[2]].m_pos ; + vecInMax[2] = m_pEdges[2][pHandle->m_maxEdges[2]].m_pos +1 ; + + aabbMin.setValue((btScalar)(vecInMin[0]) / (m_quantize.getX()),(btScalar)(vecInMin[1]) / (m_quantize.getY()),(btScalar)(vecInMin[2]) / (m_quantize.getZ())); + aabbMin += m_worldAabbMin; + + aabbMax.setValue((btScalar)(vecInMax[0]) / (m_quantize.getX()),(btScalar)(vecInMax[1]) / (m_quantize.getY()),(btScalar)(vecInMax[2]) / (m_quantize.getZ())); + aabbMax += m_worldAabbMin; +} + + + + +template +btAxisSweep3Internal::btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache , bool disableRaycastAccelerator) +:m_bpHandleMask(handleMask), +m_handleSentinel(handleSentinel), +m_pairCache(pairCache), +m_userPairCallback(0), +m_ownsPairCache(false), +m_invalidPair(0), +m_raycastAccelerator(0) +{ + BP_FP_INT_TYPE maxHandles = static_cast(userMaxHandles+1);//need to add one sentinel handle + + if (!m_pairCache) + { + void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16); + m_pairCache = new(ptr) btHashedOverlappingPairCache(); + m_ownsPairCache = true; + } + + if (!disableRaycastAccelerator) + { + m_nullPairCache = new (btAlignedAlloc(sizeof(btNullPairCache),16)) btNullPairCache(); + m_raycastAccelerator = new (btAlignedAlloc(sizeof(btDbvtBroadphase),16)) btDbvtBroadphase(m_nullPairCache);//m_pairCache); + m_raycastAccelerator->m_deferedcollide = true;//don't add/remove pairs + } + + //btAssert(bounds.HasVolume()); + + // init bounds + m_worldAabbMin = worldAabbMin; + m_worldAabbMax = worldAabbMax; + + btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin; + + BP_FP_INT_TYPE maxInt = m_handleSentinel; + + m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize; + + // allocate handles buffer, using btAlignedAlloc, and put all handles on free list + m_pHandles = new Handle[maxHandles]; + + m_maxHandles = maxHandles; + m_numHandles = 0; + + // handle 0 is reserved as the null index, and is also used as the sentinel + m_firstFreeHandle = 1; + { + for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++) + m_pHandles[i].SetNextFree(static_cast(i + 1)); + m_pHandles[maxHandles - 1].SetNextFree(0); + } + + { + // allocate edge buffers + for (int i = 0; i < 3; i++) + { + m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16); + m_pEdges[i] = new(m_pEdgesRawPtr[i]) Edge[maxHandles * 2]; + } + } + //removed overlap management + + // make boundary sentinels + + m_pHandles[0].m_clientObject = 0; + + for (int axis = 0; axis < 3; axis++) + { + m_pHandles[0].m_minEdges[axis] = 0; + m_pHandles[0].m_maxEdges[axis] = 1; + + m_pEdges[axis][0].m_pos = 0; + m_pEdges[axis][0].m_handle = 0; + m_pEdges[axis][1].m_pos = m_handleSentinel; + m_pEdges[axis][1].m_handle = 0; +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + + } + +} + +template +btAxisSweep3Internal::~btAxisSweep3Internal() +{ + if (m_raycastAccelerator) + { + m_nullPairCache->~btOverlappingPairCache(); + btAlignedFree(m_nullPairCache); + m_raycastAccelerator->~btDbvtBroadphase(); + btAlignedFree (m_raycastAccelerator); + } + + for (int i = 2; i >= 0; i--) + { + btAlignedFree(m_pEdgesRawPtr[i]); + } + delete [] m_pHandles; + + if (m_ownsPairCache) + { + m_pairCache->~btOverlappingPairCache(); + btAlignedFree(m_pairCache); + } +} + +template +void btAxisSweep3Internal::quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const +{ +#ifdef OLD_CLAMPING_METHOD + ///problem with this clamping method is that the floating point during quantization might still go outside the range [(0|isMax) .. (m_handleSentinel&m_bpHandleMask]|isMax] + ///see http://code.google.com/p/bullet/issues/detail?id=87 + btVector3 clampedPoint(point); + clampedPoint.setMax(m_worldAabbMin); + clampedPoint.setMin(m_worldAabbMax); + btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize; + out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax); + out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax); + out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax); +#else + btVector3 v = (point - m_worldAabbMin) * m_quantize; + out[0]=(v[0]<=0)?(BP_FP_INT_TYPE)isMax:(v[0]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[0]&m_bpHandleMask)|isMax); + out[1]=(v[1]<=0)?(BP_FP_INT_TYPE)isMax:(v[1]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[1]&m_bpHandleMask)|isMax); + out[2]=(v[2]<=0)?(BP_FP_INT_TYPE)isMax:(v[2]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[2]&m_bpHandleMask)|isMax); +#endif //OLD_CLAMPING_METHOD +} + + +template +BP_FP_INT_TYPE btAxisSweep3Internal::allocHandle() +{ + btAssert(m_firstFreeHandle); + + BP_FP_INT_TYPE handle = m_firstFreeHandle; + m_firstFreeHandle = getHandle(handle)->GetNextFree(); + m_numHandles++; + + return handle; +} + +template +void btAxisSweep3Internal::freeHandle(BP_FP_INT_TYPE handle) +{ + btAssert(handle > 0 && handle < m_maxHandles); + + getHandle(handle)->SetNextFree(m_firstFreeHandle); + m_firstFreeHandle = handle; + + m_numHandles--; +} + + +template +BP_FP_INT_TYPE btAxisSweep3Internal::addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy) +{ + // quantize the bounds + BP_FP_INT_TYPE min[3], max[3]; + quantize(min, aabbMin, 0); + quantize(max, aabbMax, 1); + + // allocate a handle + BP_FP_INT_TYPE handle = allocHandle(); + + + Handle* pHandle = getHandle(handle); + + pHandle->m_uniqueId = static_cast(handle); + //pHandle->m_pOverlaps = 0; + pHandle->m_clientObject = pOwner; + pHandle->m_collisionFilterGroup = collisionFilterGroup; + pHandle->m_collisionFilterMask = collisionFilterMask; + pHandle->m_multiSapParentProxy = multiSapProxy; + + // compute current limit of edge arrays + BP_FP_INT_TYPE limit = static_cast(m_numHandles * 2); + + + // insert new edges just inside the max boundary edge + for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++) + { + + m_pHandles[0].m_maxEdges[axis] += 2; + + m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1]; + + m_pEdges[axis][limit - 1].m_pos = min[axis]; + m_pEdges[axis][limit - 1].m_handle = handle; + + m_pEdges[axis][limit].m_pos = max[axis]; + m_pEdges[axis][limit].m_handle = handle; + + pHandle->m_minEdges[axis] = static_cast(limit - 1); + pHandle->m_maxEdges[axis] = limit; + } + + // now sort the new edges to their correct position + sortMinDown(0, pHandle->m_minEdges[0], dispatcher,false); + sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher,false); + sortMinDown(1, pHandle->m_minEdges[1], dispatcher,false); + sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher,false); + sortMinDown(2, pHandle->m_minEdges[2], dispatcher,true); + sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher,true); + + + return handle; +} + + +template +void btAxisSweep3Internal::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher) +{ + + Handle* pHandle = getHandle(handle); + + //explicitly remove the pairs containing the proxy + //we could do it also in the sortMinUp (passing true) + ///@todo: compare performance + if (!m_pairCache->hasDeferredRemoval()) + { + m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher); + } + + // compute current limit of edge arrays + int limit = static_cast(m_numHandles * 2); + + int axis; + + for (axis = 0;axis<3;axis++) + { + m_pHandles[0].m_maxEdges[axis] -= 2; + } + + // remove the edges by sorting them up to the end of the list + for ( axis = 0; axis < 3; axis++) + { + Edge* pEdges = m_pEdges[axis]; + BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis]; + pEdges[max].m_pos = m_handleSentinel; + + sortMaxUp(axis,max,dispatcher,false); + + + BP_FP_INT_TYPE i = pHandle->m_minEdges[axis]; + pEdges[i].m_pos = m_handleSentinel; + + + sortMinUp(axis,i,dispatcher,false); + + pEdges[limit-1].m_handle = 0; + pEdges[limit-1].m_pos = m_handleSentinel; + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis,false); +#endif //DEBUG_BROADPHASE + + + } + + + // free the handle + freeHandle(handle); + + +} + +template +void btAxisSweep3Internal::resetPool(btDispatcher* dispatcher) +{ + if (m_numHandles == 0) + { + m_firstFreeHandle = 1; + { + for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < m_maxHandles; i++) + m_pHandles[i].SetNextFree(static_cast(i + 1)); + m_pHandles[m_maxHandles - 1].SetNextFree(0); + } + } +} + + +extern int gOverlappingPairs; +//#include + +template +void btAxisSweep3Internal::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + + if (m_pairCache->hasDeferredRemoval()) + { + + btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray(); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + + + int i; + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;iprocessOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + m_pairCache->cleanOverlappingPair(pair,dispatcher); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } + + ///if you don't like to skip the invalid pairs in the array, execute following code: + #define CLEAN_INVALID_PAIRS 1 + #ifdef CLEAN_INVALID_PAIRS + + //perform a sort, to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + #endif//CLEAN_INVALID_PAIRS + + //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size()); + } + +} + + +template +bool btAxisSweep3Internal::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + const Handle* pHandleA = static_cast(proxy0); + const Handle* pHandleB = static_cast(proxy1); + + //optimization 1: check the array index (memory address), instead of the m_pos + + for (int axis = 0; axis < 3; axis++) + { + if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || + pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) + { + return false; + } + } + return true; +} + +template +bool btAxisSweep3Internal::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1) +{ + //optimization 1: check the array index (memory address), instead of the m_pos + + if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] || + pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] || + pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] || + pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1]) + { + return false; + } + return true; +} + +template +void btAxisSweep3Internal::updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher) +{ +// btAssert(bounds.IsFinite()); + //btAssert(bounds.HasVolume()); + + Handle* pHandle = getHandle(handle); + + // quantize the new bounds + BP_FP_INT_TYPE min[3], max[3]; + quantize(min, aabbMin, 0); + quantize(max, aabbMax, 1); + + // update changed edges + for (int axis = 0; axis < 3; axis++) + { + BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis]; + BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis]; + + int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos; + int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos; + + m_pEdges[axis][emin].m_pos = min[axis]; + m_pEdges[axis][emax].m_pos = max[axis]; + + // expand (only adds overlaps) + if (dmin < 0) + sortMinDown(axis, emin,dispatcher,true); + + if (dmax > 0) + sortMaxUp(axis, emax,dispatcher,true); + + // shrink (only removes overlaps) + if (dmin > 0) + sortMinUp(axis, emin,dispatcher,true); + + if (dmax < 0) + sortMaxDown(axis, emax,dispatcher,true); + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + } + + +} + + + + +// sorting a min edge downwards can only ever *add* overlaps +template +void btAxisSweep3Internal::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps) +{ + + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pPrev = pEdge - 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pEdge->m_pos < pPrev->m_pos) + { + Handle* pHandlePrev = getHandle(pPrev->m_handle); + + if (pPrev->IsMax()) + { + // if previous edge is a maximum check the bounds and add an overlap if necessary + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev,axis1,axis2)) + { + m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev); + if (m_userPairCallback) + m_userPairCallback->addOverlappingPair(pHandleEdge,pHandlePrev); + + //AddOverlap(pEdge->m_handle, pPrev->m_handle); + + } + + // update edge reference in other handle + pHandlePrev->m_maxEdges[axis]++; + } + else + pHandlePrev->m_minEdges[axis]++; + + pHandleEdge->m_minEdges[axis]--; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pPrev; + *pPrev = swap; + + // decrement + pEdge--; + pPrev--; + } + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + +} + +// sorting a min edge upwards can only ever *remove* overlaps +template +void btAxisSweep3Internal::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) +{ + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pNext = pEdge + 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) + { + Handle* pHandleNext = getHandle(pNext->m_handle); + + if (pNext->IsMax()) + { + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pNext->m_handle); + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + + // if next edge is maximum remove any overlap between the two handles + if (updateOverlaps +#ifdef USE_OVERLAP_TEST_ON_REMOVES + && testOverlap2D(handle0,handle1,axis1,axis2) +#endif //USE_OVERLAP_TEST_ON_REMOVES + ) + { + + + m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); + if (m_userPairCallback) + m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher); + + } + + + // update edge reference in other handle + pHandleNext->m_maxEdges[axis]--; + } + else + pHandleNext->m_minEdges[axis]--; + + pHandleEdge->m_minEdges[axis]++; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pNext; + *pNext = swap; + + // increment + pEdge++; + pNext++; + } + + +} + +// sorting a max edge downwards can only ever *remove* overlaps +template +void btAxisSweep3Internal::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) +{ + + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pPrev = pEdge - 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pEdge->m_pos < pPrev->m_pos) + { + Handle* pHandlePrev = getHandle(pPrev->m_handle); + + if (!pPrev->IsMax()) + { + // if previous edge was a minimum remove any overlap between the two handles + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pPrev->m_handle); + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + + if (updateOverlaps +#ifdef USE_OVERLAP_TEST_ON_REMOVES + && testOverlap2D(handle0,handle1,axis1,axis2) +#endif //USE_OVERLAP_TEST_ON_REMOVES + ) + { + //this is done during the overlappingpairarray iteration/narrowphase collision + + + m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); + if (m_userPairCallback) + m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher); + + + + } + + // update edge reference in other handle + pHandlePrev->m_minEdges[axis]++;; + } + else + pHandlePrev->m_maxEdges[axis]++; + + pHandleEdge->m_maxEdges[axis]--; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pPrev; + *pPrev = swap; + + // decrement + pEdge--; + pPrev--; + } + + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + +} + +// sorting a max edge upwards can only ever *add* overlaps +template +void btAxisSweep3Internal::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps) +{ + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pNext = pEdge + 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) + { + Handle* pHandleNext = getHandle(pNext->m_handle); + + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + + if (!pNext->IsMax()) + { + // if next edge is a minimum check the bounds and add an overlap if necessary + if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext,axis1,axis2)) + { + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pNext->m_handle); + m_pairCache->addOverlappingPair(handle0,handle1); + if (m_userPairCallback) + m_userPairCallback->addOverlappingPair(handle0,handle1); + } + + // update edge reference in other handle + pHandleNext->m_minEdges[axis]--; + } + else + pHandleNext->m_maxEdges[axis]--; + + pHandleEdge->m_maxEdges[axis]++; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pNext; + *pNext = swap; + + // increment + pEdge++; + pNext++; + } + +} + + + +//////////////////////////////////////////////////////////////////// + + +/// The btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase. +/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats. +/// For large worlds and many objects, use bt32BitAxisSweep3 or btDbvtBroadphase instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance. +class btAxisSweep3 : public btAxisSweep3Internal +{ +public: + + btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false); + +}; + +/// The bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune. +/// This comes at the cost of more memory per handle, and a bit slower performance. +/// It uses arrays rather then lists for storage of the 3 axis. +class bt32BitAxisSweep3 : public btAxisSweep3Internal +{ +public: + + bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false); + +}; + +#endif + diff --git a/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h new file mode 100644 index 0000000..f1bf005 --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h @@ -0,0 +1,82 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_BROADPHASE_INTERFACE_H +#define BT_BROADPHASE_INTERFACE_H + + + +struct btDispatcherInfo; +class btDispatcher; +#include "btBroadphaseProxy.h" + +class btOverlappingPairCache; + + + +struct btBroadphaseAabbCallback +{ + virtual ~btBroadphaseAabbCallback() {} + virtual bool process(const btBroadphaseProxy* proxy) = 0; +}; + + +struct btBroadphaseRayCallback : public btBroadphaseAabbCallback +{ + ///added some cached data to accelerate ray-AABB tests + btVector3 m_rayDirectionInverse; + unsigned int m_signs[3]; + btScalar m_lambda_max; + + virtual ~btBroadphaseRayCallback() {} +}; + +#include "LinearMath/btVector3.h" + +///The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs. +///Some implementations for this broadphase interface include btAxisSweep3, bt32BitAxisSweep3 and btDbvtBroadphase. +///The actual overlapping pair management, storage, adding and removing of pairs is dealt by the btOverlappingPairCache class. +class btBroadphaseInterface +{ +public: + virtual ~btBroadphaseInterface() {} + + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) =0; + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0; + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0; + virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const =0; + + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)) = 0; + + virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) = 0; + + ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb + virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0; + + virtual btOverlappingPairCache* getOverlappingPairCache()=0; + virtual const btOverlappingPairCache* getOverlappingPairCache() const =0; + + ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame + ///will add some transform later + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0; + + ///reset broadphase internal structures, to ensure determinism/reproducability + virtual void resetPool(btDispatcher* dispatcher) { (void) dispatcher; }; + + virtual void printStats() = 0; + +}; + +#endif //BT_BROADPHASE_INTERFACE_H diff --git a/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp b/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp new file mode 100644 index 0000000..f4d7341 --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp @@ -0,0 +1,17 @@ +/* +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 "btBroadphaseProxy.h" + diff --git a/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h new file mode 100644 index 0000000..bb58b82 --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h @@ -0,0 +1,270 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_BROADPHASE_PROXY_H +#define BT_BROADPHASE_PROXY_H + +#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedAllocator.h" + + +/// btDispatcher uses these types +/// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave +/// to facilitate type checking +/// CUSTOM_POLYHEDRAL_SHAPE_TYPE,CUSTOM_CONVEX_SHAPE_TYPE and CUSTOM_CONCAVE_SHAPE_TYPE can be used to extend Bullet without modifying source code +enum BroadphaseNativeTypes +{ + // polyhedral convex shapes + BOX_SHAPE_PROXYTYPE, + TRIANGLE_SHAPE_PROXYTYPE, + TETRAHEDRAL_SHAPE_PROXYTYPE, + CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE, + CONVEX_HULL_SHAPE_PROXYTYPE, + CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE, + CUSTOM_POLYHEDRAL_SHAPE_TYPE, +//implicit convex shapes +IMPLICIT_CONVEX_SHAPES_START_HERE, + SPHERE_SHAPE_PROXYTYPE, + MULTI_SPHERE_SHAPE_PROXYTYPE, + CAPSULE_SHAPE_PROXYTYPE, + CONE_SHAPE_PROXYTYPE, + CONVEX_SHAPE_PROXYTYPE, + CYLINDER_SHAPE_PROXYTYPE, + UNIFORM_SCALING_SHAPE_PROXYTYPE, + MINKOWSKI_SUM_SHAPE_PROXYTYPE, + MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE, + BOX_2D_SHAPE_PROXYTYPE, + CONVEX_2D_SHAPE_PROXYTYPE, + CUSTOM_CONVEX_SHAPE_TYPE, +//concave shapes +CONCAVE_SHAPES_START_HERE, + //keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy! + TRIANGLE_MESH_SHAPE_PROXYTYPE, + SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE, + ///used for demo integration FAST/Swift collision library and Bullet + FAST_CONCAVE_MESH_PROXYTYPE, + //terrain + TERRAIN_SHAPE_PROXYTYPE, +///Used for GIMPACT Trimesh integration + GIMPACT_SHAPE_PROXYTYPE, +///Multimaterial mesh + MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE, + + EMPTY_SHAPE_PROXYTYPE, + STATIC_PLANE_PROXYTYPE, + CUSTOM_CONCAVE_SHAPE_TYPE, +CONCAVE_SHAPES_END_HERE, + + COMPOUND_SHAPE_PROXYTYPE, + + SOFTBODY_SHAPE_PROXYTYPE, + HFFLUID_SHAPE_PROXYTYPE, + HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE, + INVALID_SHAPE_PROXYTYPE, + + MAX_BROADPHASE_COLLISION_TYPES + +}; + + +///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases. +///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody. +ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy +{ + +BT_DECLARE_ALIGNED_ALLOCATOR(); + + ///optional filtering to cull potential collisions + enum CollisionFilterGroups + { + DefaultFilter = 1, + StaticFilter = 2, + KinematicFilter = 4, + DebrisFilter = 8, + SensorTrigger = 16, + CharacterFilter = 32, + AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger + }; + + //Usually the client btCollisionObject or Rigidbody class + void* m_clientObject; + short int m_collisionFilterGroup; + short int m_collisionFilterMask; + void* m_multiSapParentProxy; + int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc. + + btVector3 m_aabbMin; + btVector3 m_aabbMax; + + SIMD_FORCE_INLINE int getUid() const + { + return m_uniqueId; + } + + //used for memory pools + btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0) + { + } + + btBroadphaseProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0) + :m_clientObject(userPtr), + m_collisionFilterGroup(collisionFilterGroup), + m_collisionFilterMask(collisionFilterMask), + m_aabbMin(aabbMin), + m_aabbMax(aabbMax) + { + m_multiSapParentProxy = multiSapParentProxy; + } + + + + static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType) + { + return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE); + } + + static SIMD_FORCE_INLINE bool isConvex(int proxyType) + { + return (proxyType < CONCAVE_SHAPES_START_HERE); + } + + static SIMD_FORCE_INLINE bool isNonMoving(int proxyType) + { + return (isConcave(proxyType) && !(proxyType==GIMPACT_SHAPE_PROXYTYPE)); + } + + static SIMD_FORCE_INLINE bool isConcave(int proxyType) + { + return ((proxyType > CONCAVE_SHAPES_START_HERE) && + (proxyType < CONCAVE_SHAPES_END_HERE)); + } + static SIMD_FORCE_INLINE bool isCompound(int proxyType) + { + return (proxyType == COMPOUND_SHAPE_PROXYTYPE); + } + + static SIMD_FORCE_INLINE bool isSoftBody(int proxyType) + { + return (proxyType == SOFTBODY_SHAPE_PROXYTYPE); + } + + static SIMD_FORCE_INLINE bool isInfinite(int proxyType) + { + return (proxyType == STATIC_PLANE_PROXYTYPE); + } + + static SIMD_FORCE_INLINE bool isConvex2d(int proxyType) + { + return (proxyType == BOX_2D_SHAPE_PROXYTYPE) || (proxyType == CONVEX_2D_SHAPE_PROXYTYPE); + } + + +} +; + +class btCollisionAlgorithm; + +struct btBroadphaseProxy; + + + +///The btBroadphasePair class contains a pair of aabb-overlapping objects. +///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes. +ATTRIBUTE_ALIGNED16(struct) btBroadphasePair +{ + btBroadphasePair () + : + m_pProxy0(0), + m_pProxy1(0), + m_algorithm(0), + m_internalInfo1(0) + { + } + +BT_DECLARE_ALIGNED_ALLOCATOR(); + + btBroadphasePair(const btBroadphasePair& other) + : m_pProxy0(other.m_pProxy0), + m_pProxy1(other.m_pProxy1), + m_algorithm(other.m_algorithm), + m_internalInfo1(other.m_internalInfo1) + { + } + btBroadphasePair(btBroadphaseProxy& proxy0,btBroadphaseProxy& proxy1) + { + + //keep them sorted, so the std::set operations work + if (proxy0.m_uniqueId < proxy1.m_uniqueId) + { + m_pProxy0 = &proxy0; + m_pProxy1 = &proxy1; + } + else + { + m_pProxy0 = &proxy1; + m_pProxy1 = &proxy0; + } + + m_algorithm = 0; + m_internalInfo1 = 0; + + } + + btBroadphaseProxy* m_pProxy0; + btBroadphaseProxy* m_pProxy1; + + mutable btCollisionAlgorithm* m_algorithm; + union { void* m_internalInfo1; int m_internalTmpValue;};//don't use this data, it will be removed in future version. + +}; + +/* +//comparison for set operation, see Solid DT_Encounter +SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePair& b) +{ + return a.m_pProxy0 < b.m_pProxy0 || + (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 < b.m_pProxy1); +} +*/ + + + +class btBroadphasePairSortPredicate +{ + public: + + bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b ) const + { + const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1; + const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1; + const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1; + const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1; + + return uidA0 > uidB0 || + (a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) || + (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm); + } +}; + + +SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b) +{ + return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1); +} + + +#endif //BT_BROADPHASE_PROXY_H + diff --git a/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp new file mode 100644 index 0000000..c95d1be --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp @@ -0,0 +1,23 @@ +/* +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 "btCollisionAlgorithm.h" +#include "btDispatcher.h" + +btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) +{ + m_dispatcher = ci.m_dispatcher1; +} + diff --git a/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h new file mode 100644 index 0000000..36eec97 --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h @@ -0,0 +1,80 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COLLISION_ALGORITHM_H +#define BT_COLLISION_ALGORITHM_H + +#include "LinearMath/btScalar.h" +#include "LinearMath/btAlignedObjectArray.h" + +struct btBroadphaseProxy; +class btDispatcher; +class btManifoldResult; +class btCollisionObject; +struct btDispatcherInfo; +class btPersistentManifold; + +typedef btAlignedObjectArray btManifoldArray; + +struct btCollisionAlgorithmConstructionInfo +{ + btCollisionAlgorithmConstructionInfo() + :m_dispatcher1(0), + m_manifold(0) + { + } + btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp) + :m_dispatcher1(dispatcher) + { + (void)temp; + } + + btDispatcher* m_dispatcher1; + btPersistentManifold* m_manifold; + +// int getDispatcherId(); + +}; + + +///btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatcher. +///It is persistent over frames +class btCollisionAlgorithm +{ + +protected: + + btDispatcher* m_dispatcher; + +protected: +// int getDispatcherId(); + +public: + + btCollisionAlgorithm() {}; + + btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci); + + virtual ~btCollisionAlgorithm() {}; + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0; + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0; + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0; +}; + + +#endif //BT_COLLISION_ALGORITHM_H diff --git a/src/BulletCollision/BroadphaseCollision/btDbvt.cpp b/src/BulletCollision/BroadphaseCollision/btDbvt.cpp new file mode 100644 index 0000000..95443af --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btDbvt.cpp @@ -0,0 +1,1295 @@ +/* +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. +*/ +///btDbvt implementation by Nathanael Presson + +#include "btDbvt.h" + +// +typedef btAlignedObjectArray tNodeArray; +typedef btAlignedObjectArray tConstNodeArray; + +// +struct btDbvtNodeEnumerator : btDbvt::ICollide +{ + tConstNodeArray nodes; + void Process(const btDbvtNode* n) { nodes.push_back(n); } +}; + +// +static DBVT_INLINE int indexof(const btDbvtNode* node) +{ + return(node->parent->childs[1]==node); +} + +// +static DBVT_INLINE btDbvtVolume merge( const btDbvtVolume& a, + const btDbvtVolume& b) +{ +#if (DBVT_MERGE_IMPL==DBVT_IMPL_SSE) + ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtAabbMm)]); + btDbvtVolume& res=*(btDbvtVolume*)locals; +#else + btDbvtVolume res; +#endif + Merge(a,b,res); + return(res); +} + +// volume+edge lengths +static DBVT_INLINE btScalar size(const btDbvtVolume& a) +{ + const btVector3 edges=a.Lengths(); + return( edges.x()*edges.y()*edges.z()+ + edges.x()+edges.y()+edges.z()); +} + +// +static void getmaxdepth(const btDbvtNode* node,int depth,int& maxdepth) +{ + if(node->isinternal()) + { + getmaxdepth(node->childs[0],depth+1,maxdepth); + getmaxdepth(node->childs[1],depth+1,maxdepth); + } else maxdepth=btMax(maxdepth,depth); +} + +// +static DBVT_INLINE void deletenode( btDbvt* pdbvt, + btDbvtNode* node) +{ + btAlignedFree(pdbvt->m_free); + pdbvt->m_free=node; +} + +// +static void recursedeletenode( btDbvt* pdbvt, + btDbvtNode* node) +{ + if(!node->isleaf()) + { + recursedeletenode(pdbvt,node->childs[0]); + recursedeletenode(pdbvt,node->childs[1]); + } + if(node==pdbvt->m_root) pdbvt->m_root=0; + deletenode(pdbvt,node); +} + +// +static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt, + btDbvtNode* parent, + void* data) +{ + btDbvtNode* node; + if(pdbvt->m_free) + { node=pdbvt->m_free;pdbvt->m_free=0; } + else + { node=new(btAlignedAlloc(sizeof(btDbvtNode),16)) btDbvtNode(); } + node->parent = parent; + node->data = data; + node->childs[1] = 0; + return(node); +} + +// +static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt, + btDbvtNode* parent, + const btDbvtVolume& volume, + void* data) +{ + btDbvtNode* node=createnode(pdbvt,parent,data); + node->volume=volume; + return(node); +} + +// +static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt, + btDbvtNode* parent, + const btDbvtVolume& volume0, + const btDbvtVolume& volume1, + void* data) +{ + btDbvtNode* node=createnode(pdbvt,parent,data); + Merge(volume0,volume1,node->volume); + return(node); +} + +// +static void insertleaf( btDbvt* pdbvt, + btDbvtNode* root, + btDbvtNode* leaf) +{ + if(!pdbvt->m_root) + { + pdbvt->m_root = leaf; + leaf->parent = 0; + } + else + { + if(!root->isleaf()) + { + do { + root=root->childs[Select( leaf->volume, + root->childs[0]->volume, + root->childs[1]->volume)]; + } while(!root->isleaf()); + } + btDbvtNode* prev=root->parent; + btDbvtNode* node=createnode(pdbvt,prev,leaf->volume,root->volume,0); + if(prev) + { + prev->childs[indexof(root)] = node; + node->childs[0] = root;root->parent=node; + node->childs[1] = leaf;leaf->parent=node; + do { + if(!prev->volume.Contain(node->volume)) + Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume); + else + break; + node=prev; + } while(0!=(prev=node->parent)); + } + else + { + node->childs[0] = root;root->parent=node; + node->childs[1] = leaf;leaf->parent=node; + pdbvt->m_root = node; + } + } +} + +// +static btDbvtNode* removeleaf( btDbvt* pdbvt, + btDbvtNode* leaf) +{ + if(leaf==pdbvt->m_root) + { + pdbvt->m_root=0; + return(0); + } + else + { + btDbvtNode* parent=leaf->parent; + btDbvtNode* prev=parent->parent; + btDbvtNode* sibling=parent->childs[1-indexof(leaf)]; + if(prev) + { + prev->childs[indexof(parent)]=sibling; + sibling->parent=prev; + deletenode(pdbvt,parent); + while(prev) + { + const btDbvtVolume pb=prev->volume; + Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume); + if(NotEqual(pb,prev->volume)) + { + prev=prev->parent; + } else break; + } + return(prev?prev:pdbvt->m_root); + } + else + { + pdbvt->m_root=sibling; + sibling->parent=0; + deletenode(pdbvt,parent); + return(pdbvt->m_root); + } + } +} + +// +static void fetchleaves(btDbvt* pdbvt, + btDbvtNode* root, + tNodeArray& leaves, + int depth=-1) +{ + if(root->isinternal()&&depth) + { + fetchleaves(pdbvt,root->childs[0],leaves,depth-1); + fetchleaves(pdbvt,root->childs[1],leaves,depth-1); + deletenode(pdbvt,root); + } + else + { + leaves.push_back(root); + } +} + +// +static void split( const tNodeArray& leaves, + tNodeArray& left, + tNodeArray& right, + const btVector3& org, + const btVector3& axis) +{ + left.resize(0); + right.resize(0); + for(int i=0,ni=leaves.size();ivolume.Center()-org)<0) + left.push_back(leaves[i]); + else + right.push_back(leaves[i]); + } +} + +// +static btDbvtVolume bounds( const tNodeArray& leaves) +{ +#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE + ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]); + btDbvtVolume& volume=*(btDbvtVolume*)locals; + volume=leaves[0]->volume; +#else + btDbvtVolume volume=leaves[0]->volume; +#endif + for(int i=1,ni=leaves.size();ivolume,volume); + } + return(volume); +} + +// +static void bottomup( btDbvt* pdbvt, + tNodeArray& leaves) +{ + while(leaves.size()>1) + { + btScalar minsize=SIMD_INFINITY; + int minidx[2]={-1,-1}; + for(int i=0;ivolume,leaves[j]->volume)); + if(szvolume,n[1]->volume,0); + p->childs[0] = n[0]; + p->childs[1] = n[1]; + n[0]->parent = p; + n[1]->parent = p; + leaves[minidx[0]] = p; + leaves.swap(minidx[1],leaves.size()-1); + leaves.pop_back(); + } +} + +// +static btDbvtNode* topdown(btDbvt* pdbvt, + tNodeArray& leaves, + int bu_treshold) +{ + static const btVector3 axis[]={btVector3(1,0,0), + btVector3(0,1,0), + btVector3(0,0,1)}; + if(leaves.size()>1) + { + if(leaves.size()>bu_treshold) + { + const btDbvtVolume vol=bounds(leaves); + const btVector3 org=vol.Center(); + tNodeArray sets[2]; + int bestaxis=-1; + int bestmidp=leaves.size(); + int splitcount[3][2]={{0,0},{0,0},{0,0}}; + int i; + for( i=0;ivolume.Center()-org; + for(int j=0;j<3;++j) + { + ++splitcount[j][btDot(x,axis[j])>0?1:0]; + } + } + for( i=0;i<3;++i) + { + if((splitcount[i][0]>0)&&(splitcount[i][1]>0)) + { + const int midp=(int)btFabs(btScalar(splitcount[i][0]-splitcount[i][1])); + if(midp=0) + { + sets[0].reserve(splitcount[bestaxis][0]); + sets[1].reserve(splitcount[bestaxis][1]); + split(leaves,sets[0],sets[1],org,axis[bestaxis]); + } + else + { + sets[0].reserve(leaves.size()/2+1); + sets[1].reserve(leaves.size()/2); + for(int i=0,ni=leaves.size();ichilds[0]=topdown(pdbvt,sets[0],bu_treshold); + node->childs[1]=topdown(pdbvt,sets[1],bu_treshold); + node->childs[0]->parent=node; + node->childs[1]->parent=node; + return(node); + } + else + { + bottomup(pdbvt,leaves); + return(leaves[0]); + } + } + return(leaves[0]); +} + +// +static DBVT_INLINE btDbvtNode* sort(btDbvtNode* n,btDbvtNode*& r) +{ + btDbvtNode* p=n->parent; + btAssert(n->isinternal()); + if(p>n) + { + const int i=indexof(n); + const int j=1-i; + btDbvtNode* s=p->childs[j]; + btDbvtNode* q=p->parent; + btAssert(n==p->childs[i]); + if(q) q->childs[indexof(p)]=n; else r=n; + s->parent=n; + p->parent=n; + n->parent=q; + p->childs[0]=n->childs[0]; + p->childs[1]=n->childs[1]; + n->childs[0]->parent=p; + n->childs[1]->parent=p; + n->childs[i]=p; + n->childs[j]=s; + btSwap(p->volume,n->volume); + return(p); + } + return(n); +} + +#if 0 +static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count) +{ + while(n&&(count--)) n=n->parent; + return(n); +} +#endif + +// +// Api +// + +// +btDbvt::btDbvt() +{ + m_root = 0; + m_free = 0; + m_lkhd = -1; + m_leaves = 0; + m_opath = 0; +} + +// +btDbvt::~btDbvt() +{ + clear(); +} + +// +void btDbvt::clear() +{ + if(m_root) + recursedeletenode(this,m_root); + btAlignedFree(m_free); + m_free=0; + m_lkhd = -1; + m_stkStack.clear(); + m_opath = 0; + +} + +// +void btDbvt::optimizeBottomUp() +{ + if(m_root) + { + tNodeArray leaves; + leaves.reserve(m_leaves); + fetchleaves(this,m_root,leaves); + bottomup(this,leaves); + m_root=leaves[0]; + } +} + +// +void btDbvt::optimizeTopDown(int bu_treshold) +{ + if(m_root) + { + tNodeArray leaves; + leaves.reserve(m_leaves); + fetchleaves(this,m_root,leaves); + m_root=topdown(this,leaves,bu_treshold); + } +} + +// +void btDbvt::optimizeIncremental(int passes) +{ + if(passes<0) passes=m_leaves; + if(m_root&&(passes>0)) + { + do { + btDbvtNode* node=m_root; + unsigned bit=0; + while(node->isinternal()) + { + node=sort(node,m_root)->childs[(m_opath>>bit)&1]; + bit=(bit+1)&(sizeof(unsigned)*8-1); + } + update(node); + ++m_opath; + } while(--passes); + } +} + +// +btDbvtNode* btDbvt::insert(const btDbvtVolume& volume,void* data) +{ + btDbvtNode* leaf=createnode(this,0,volume,data); + insertleaf(this,m_root,leaf); + ++m_leaves; + return(leaf); +} + +// +void btDbvt::update(btDbvtNode* leaf,int lookahead) +{ + btDbvtNode* root=removeleaf(this,leaf); + if(root) + { + if(lookahead>=0) + { + for(int i=0;(iparent;++i) + { + root=root->parent; + } + } else root=m_root; + } + insertleaf(this,root,leaf); +} + +// +void btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume) +{ + btDbvtNode* root=removeleaf(this,leaf); + if(root) + { + if(m_lkhd>=0) + { + for(int i=0;(iparent;++i) + { + root=root->parent; + } + } else root=m_root; + } + leaf->volume=volume; + insertleaf(this,root,leaf); +} + +// +bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin) +{ + if(leaf->volume.Contain(volume)) return(false); + volume.Expand(btVector3(margin,margin,margin)); + volume.SignedExpand(velocity); + update(leaf,volume); + return(true); +} + +// +bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity) +{ + if(leaf->volume.Contain(volume)) return(false); + volume.SignedExpand(velocity); + update(leaf,volume); + return(true); +} + +// +bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin) +{ + if(leaf->volume.Contain(volume)) return(false); + volume.Expand(btVector3(margin,margin,margin)); + update(leaf,volume); + return(true); +} + +// +void btDbvt::remove(btDbvtNode* leaf) +{ + removeleaf(this,leaf); + deletenode(this,leaf); + --m_leaves; +} + +// +void btDbvt::write(IWriter* iwriter) const +{ + btDbvtNodeEnumerator nodes; + nodes.nodes.reserve(m_leaves*2); + enumNodes(m_root,nodes); + iwriter->Prepare(m_root,nodes.nodes.size()); + for(int i=0;iparent) p=nodes.nodes.findLinearSearch(n->parent); + if(n->isinternal()) + { + const int c0=nodes.nodes.findLinearSearch(n->childs[0]); + const int c1=nodes.nodes.findLinearSearch(n->childs[1]); + iwriter->WriteNode(n,i,p,c0,c1); + } + else + { + iwriter->WriteLeaf(n,i,p); + } + } +} + +// +void btDbvt::clone(btDbvt& dest,IClone* iclone) const +{ + dest.clear(); + if(m_root!=0) + { + btAlignedObjectArray stack; + stack.reserve(m_leaves); + stack.push_back(sStkCLN(m_root,0)); + do { + const int i=stack.size()-1; + const sStkCLN e=stack[i]; + btDbvtNode* n=createnode(&dest,e.parent,e.node->volume,e.node->data); + stack.pop_back(); + if(e.parent!=0) + e.parent->childs[i&1]=n; + else + dest.m_root=n; + if(e.node->isinternal()) + { + stack.push_back(sStkCLN(e.node->childs[0],n)); + stack.push_back(sStkCLN(e.node->childs[1],n)); + } + else + { + iclone->CloneLeaf(n); + } + } while(stack.size()>0); + } +} + +// +int btDbvt::maxdepth(const btDbvtNode* node) +{ + int depth=0; + if(node) getmaxdepth(node,1,depth); + return(depth); +} + +// +int btDbvt::countLeaves(const btDbvtNode* node) +{ + if(node->isinternal()) + return(countLeaves(node->childs[0])+countLeaves(node->childs[1])); + else + return(1); +} + +// +void btDbvt::extractLeaves(const btDbvtNode* node,btAlignedObjectArray& leaves) +{ + if(node->isinternal()) + { + extractLeaves(node->childs[0],leaves); + extractLeaves(node->childs[1],leaves); + } + else + { + leaves.push_back(node); + } +} + +// +#if DBVT_ENABLE_BENCHMARK + +#include +#include +#include "LinearMath/btQuickProf.h" + +/* +q6600,2.4ghz + +/Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32" +/GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch" +/Fo"..\..\out\release8\build\libbulletcollision\\" +/Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb" +/W3 /nologo /c /Wp64 /Zi /errorReport:prompt + +Benchmarking dbvt... +World scale: 100.000000 +Extents base: 1.000000 +Extents range: 4.000000 +Leaves: 8192 +sizeof(btDbvtVolume): 32 bytes +sizeof(btDbvtNode): 44 bytes +[1] btDbvtVolume intersections: 3499 ms (-1%) +[2] btDbvtVolume merges: 1934 ms (0%) +[3] btDbvt::collideTT: 5485 ms (-21%) +[4] btDbvt::collideTT self: 2814 ms (-20%) +[5] btDbvt::collideTT xform: 7379 ms (-1%) +[6] btDbvt::collideTT xform,self: 7270 ms (-2%) +[7] btDbvt::rayTest: 6314 ms (0%),(332143 r/s) +[8] insert/remove: 2093 ms (0%),(1001983 ir/s) +[9] updates (teleport): 1879 ms (-3%),(1116100 u/s) +[10] updates (jitter): 1244 ms (-4%),(1685813 u/s) +[11] optimize (incremental): 2514 ms (0%),(1668000 o/s) +[12] btDbvtVolume notequal: 3659 ms (0%) +[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s) +[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s) +[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s) +[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s) +[17] btDbvtVolume select: 3419 ms (0%) +*/ + +struct btDbvtBenchmark +{ + struct NilPolicy : btDbvt::ICollide + { + NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true) {} + void Process(const btDbvtNode*,const btDbvtNode*) { ++m_pcount; } + void Process(const btDbvtNode*) { ++m_pcount; } + void Process(const btDbvtNode*,btScalar depth) + { + ++m_pcount; + if(m_checksort) + { if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); } + } + int m_pcount; + btScalar m_depth; + bool m_checksort; + }; + struct P14 : btDbvt::ICollide + { + struct Node + { + const btDbvtNode* leaf; + btScalar depth; + }; + void Process(const btDbvtNode* leaf,btScalar depth) + { + Node n; + n.leaf = leaf; + n.depth = depth; + } + static int sortfnc(const Node& a,const Node& b) + { + if(a.depthb.depth) return(-1); + return(0); + } + btAlignedObjectArray m_nodes; + }; + struct P15 : btDbvt::ICollide + { + struct Node + { + const btDbvtNode* leaf; + btScalar depth; + }; + void Process(const btDbvtNode* leaf) + { + Node n; + n.leaf = leaf; + n.depth = dot(leaf->volume.Center(),m_axis); + } + static int sortfnc(const Node& a,const Node& b) + { + if(a.depthb.depth) return(-1); + return(0); + } + btAlignedObjectArray m_nodes; + btVector3 m_axis; + }; + static btScalar RandUnit() + { + return(rand()/(btScalar)RAND_MAX); + } + static btVector3 RandVector3() + { + return(btVector3(RandUnit(),RandUnit(),RandUnit())); + } + static btVector3 RandVector3(btScalar cs) + { + return(RandVector3()*cs-btVector3(cs,cs,cs)/2); + } + static btDbvtVolume RandVolume(btScalar cs,btScalar eb,btScalar es) + { + return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es)); + } + static btTransform RandTransform(btScalar cs) + { + btTransform t; + t.setOrigin(RandVector3(cs)); + t.setRotation(btQuaternion(RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2).normalized()); + return(t); + } + static void RandTree(btScalar cs,btScalar eb,btScalar es,int leaves,btDbvt& dbvt) + { + dbvt.clear(); + for(int i=0;i volumes; + btAlignedObjectArray results; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + for(int i=0;i volumes; + btAlignedObjectArray results; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + for(int i=0;i transforms; + btDbvtBenchmark::NilPolicy policy; + transforms.resize(cfgBenchmark5_Iterations); + for(int i=0;i transforms; + btDbvtBenchmark::NilPolicy policy; + transforms.resize(cfgBenchmark6_Iterations); + for(int i=0;i rayorg; + btAlignedObjectArray raydir; + btDbvtBenchmark::NilPolicy policy; + rayorg.resize(cfgBenchmark7_Iterations); + raydir.resize(cfgBenchmark7_Iterations); + for(int i=0;i leaves; + btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); + dbvt.optimizeTopDown(); + dbvt.extractLeaves(dbvt.m_root,leaves); + printf("[9] updates (teleport): "); + wallclock.reset(); + for(int i=0;i(leaves[rand()%cfgLeaves]), + btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale)); + } + } + const int time=(int)wallclock.getTimeMilliseconds(); + const int up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations; + printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time); + } + if(cfgBenchmark10_Enable) + {// Benchmark 10 + srand(380843); + btDbvt dbvt; + btAlignedObjectArray leaves; + btAlignedObjectArray vectors; + vectors.resize(cfgBenchmark10_Iterations); + for(int i=0;i(leaves[rand()%cfgLeaves]); + btDbvtVolume v=btDbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d); + dbvt.update(l,v); + } + } + const int time=(int)wallclock.getTimeMilliseconds(); + const int up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations; + printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time); + } + if(cfgBenchmark11_Enable) + {// Benchmark 11 + srand(380843); + btDbvt dbvt; + btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); + dbvt.optimizeTopDown(); + printf("[11] optimize (incremental): "); + wallclock.reset(); + for(int i=0;i volumes; + btAlignedObjectArray results; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + for(int i=0;i vectors; + btDbvtBenchmark::NilPolicy policy; + vectors.resize(cfgBenchmark13_Iterations); + for(int i=0;i vectors; + btDbvtBenchmark::P14 policy; + vectors.resize(cfgBenchmark14_Iterations); + for(int i=0;i vectors; + btDbvtBenchmark::P15 policy; + vectors.resize(cfgBenchmark15_Iterations); + for(int i=0;i batch; + btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); + dbvt.optimizeTopDown(); + batch.reserve(cfgBenchmark16_BatchCount); + printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount); + wallclock.reset(); + for(int i=0;i volumes; + btAlignedObjectArray results; + btAlignedObjectArray indices; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + indices.resize(cfgLeaves); + for(int i=0;i= 1400) +#define DBVT_USE_TEMPLATE 1 +#else +#define DBVT_USE_TEMPLATE 0 +#endif +#else +#define DBVT_USE_TEMPLATE 0 +#endif + +// Use only intrinsics instead of inline asm +#define DBVT_USE_INTRINSIC_SSE 1 + +// Using memmov for collideOCL +#define DBVT_USE_MEMMOVE 1 + +// Enable benchmarking code +#define DBVT_ENABLE_BENCHMARK 0 + +// Inlining +#define DBVT_INLINE SIMD_FORCE_INLINE + +// Specific methods implementation + +//SSE gives errors on a MSVC 7.1 +#if defined (BT_USE_SSE) && defined (_WIN32) +#define DBVT_SELECT_IMPL DBVT_IMPL_SSE +#define DBVT_MERGE_IMPL DBVT_IMPL_SSE +#define DBVT_INT0_IMPL DBVT_IMPL_SSE +#else +#define DBVT_SELECT_IMPL DBVT_IMPL_GENERIC +#define DBVT_MERGE_IMPL DBVT_IMPL_GENERIC +#define DBVT_INT0_IMPL DBVT_IMPL_GENERIC +#endif + +#if (DBVT_SELECT_IMPL==DBVT_IMPL_SSE)|| \ + (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)|| \ + (DBVT_INT0_IMPL==DBVT_IMPL_SSE) +#include +#endif + +// +// Auto config and checks +// + +#if DBVT_USE_TEMPLATE +#define DBVT_VIRTUAL +#define DBVT_VIRTUAL_DTOR(a) +#define DBVT_PREFIX template +#define DBVT_IPOLICY T& policy +#define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)1;(void)typechecker; +#else +#define DBVT_VIRTUAL_DTOR(a) virtual ~a() {} +#define DBVT_VIRTUAL virtual +#define DBVT_PREFIX +#define DBVT_IPOLICY ICollide& policy +#define DBVT_CHECKTYPE +#endif + +#if DBVT_USE_MEMMOVE +#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__) +#include +#endif +#include +#endif + +#ifndef DBVT_USE_TEMPLATE +#error "DBVT_USE_TEMPLATE undefined" +#endif + +#ifndef DBVT_USE_MEMMOVE +#error "DBVT_USE_MEMMOVE undefined" +#endif + +#ifndef DBVT_ENABLE_BENCHMARK +#error "DBVT_ENABLE_BENCHMARK undefined" +#endif + +#ifndef DBVT_SELECT_IMPL +#error "DBVT_SELECT_IMPL undefined" +#endif + +#ifndef DBVT_MERGE_IMPL +#error "DBVT_MERGE_IMPL undefined" +#endif + +#ifndef DBVT_INT0_IMPL +#error "DBVT_INT0_IMPL undefined" +#endif + +// +// Defaults volumes +// + +/* btDbvtAabbMm */ +struct btDbvtAabbMm +{ + DBVT_INLINE btVector3 Center() const { return((mi+mx)/2); } + DBVT_INLINE btVector3 Lengths() const { return(mx-mi); } + DBVT_INLINE btVector3 Extents() const { return((mx-mi)/2); } + DBVT_INLINE const btVector3& Mins() const { return(mi); } + DBVT_INLINE const btVector3& Maxs() const { return(mx); } + static inline btDbvtAabbMm FromCE(const btVector3& c,const btVector3& e); + static inline btDbvtAabbMm FromCR(const btVector3& c,btScalar r); + static inline btDbvtAabbMm FromMM(const btVector3& mi,const btVector3& mx); + static inline btDbvtAabbMm FromPoints(const btVector3* pts,int n); + static inline btDbvtAabbMm FromPoints(const btVector3** ppts,int n); + DBVT_INLINE void Expand(const btVector3& e); + DBVT_INLINE void SignedExpand(const btVector3& e); + DBVT_INLINE bool Contain(const btDbvtAabbMm& a) const; + DBVT_INLINE int Classify(const btVector3& n,btScalar o,int s) const; + DBVT_INLINE btScalar ProjectMinimum(const btVector3& v,unsigned signs) const; + DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, + const btDbvtAabbMm& b); + + DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, + const btVector3& b); + + DBVT_INLINE friend btScalar Proximity( const btDbvtAabbMm& a, + const btDbvtAabbMm& b); + DBVT_INLINE friend int Select( const btDbvtAabbMm& o, + const btDbvtAabbMm& a, + const btDbvtAabbMm& b); + DBVT_INLINE friend void Merge( const btDbvtAabbMm& a, + const btDbvtAabbMm& b, + btDbvtAabbMm& r); + DBVT_INLINE friend bool NotEqual( const btDbvtAabbMm& a, + const btDbvtAabbMm& b); +private: + DBVT_INLINE void AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const; +private: + btVector3 mi,mx; +}; + +// Types +typedef btDbvtAabbMm btDbvtVolume; + +/* btDbvtNode */ +struct btDbvtNode +{ + btDbvtVolume volume; + btDbvtNode* parent; + DBVT_INLINE bool isleaf() const { return(childs[1]==0); } + DBVT_INLINE bool isinternal() const { return(!isleaf()); } + union + { + btDbvtNode* childs[2]; + void* data; + int dataAsInt; + }; +}; + +///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree). +///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes. +///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure. +struct btDbvt +{ + /* Stack element */ + struct sStkNN + { + const btDbvtNode* a; + const btDbvtNode* b; + sStkNN() {} + sStkNN(const btDbvtNode* na,const btDbvtNode* nb) : a(na),b(nb) {} + }; + struct sStkNP + { + const btDbvtNode* node; + int mask; + sStkNP(const btDbvtNode* n,unsigned m) : node(n),mask(m) {} + }; + struct sStkNPS + { + const btDbvtNode* node; + int mask; + btScalar value; + sStkNPS() {} + sStkNPS(const btDbvtNode* n,unsigned m,btScalar v) : node(n),mask(m),value(v) {} + }; + struct sStkCLN + { + const btDbvtNode* node; + btDbvtNode* parent; + sStkCLN(const btDbvtNode* n,btDbvtNode* p) : node(n),parent(p) {} + }; + // Policies/Interfaces + + /* ICollide */ + struct ICollide + { + DBVT_VIRTUAL_DTOR(ICollide) + DBVT_VIRTUAL void Process(const btDbvtNode*,const btDbvtNode*) {} + DBVT_VIRTUAL void Process(const btDbvtNode*) {} + DBVT_VIRTUAL void Process(const btDbvtNode* n,btScalar) { Process(n); } + DBVT_VIRTUAL bool Descent(const btDbvtNode*) { return(true); } + DBVT_VIRTUAL bool AllLeaves(const btDbvtNode*) { return(true); } + }; + /* IWriter */ + struct IWriter + { + virtual ~IWriter() {} + virtual void Prepare(const btDbvtNode* root,int numnodes)=0; + virtual void WriteNode(const btDbvtNode*,int index,int parent,int child0,int child1)=0; + virtual void WriteLeaf(const btDbvtNode*,int index,int parent)=0; + }; + /* IClone */ + struct IClone + { + virtual ~IClone() {} + virtual void CloneLeaf(btDbvtNode*) {} + }; + + // Constants + enum { + SIMPLE_STACKSIZE = 64, + DOUBLE_STACKSIZE = SIMPLE_STACKSIZE*2 + }; + + // Fields + btDbvtNode* m_root; + btDbvtNode* m_free; + int m_lkhd; + int m_leaves; + unsigned m_opath; + + + btAlignedObjectArray m_stkStack; + mutable btAlignedObjectArray m_rayTestStack; + + + // Methods + btDbvt(); + ~btDbvt(); + void clear(); + bool empty() const { return(0==m_root); } + void optimizeBottomUp(); + void optimizeTopDown(int bu_treshold=128); + void optimizeIncremental(int passes); + btDbvtNode* insert(const btDbvtVolume& box,void* data); + void update(btDbvtNode* leaf,int lookahead=-1); + void update(btDbvtNode* leaf,btDbvtVolume& volume); + bool update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin); + bool update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity); + bool update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin); + void remove(btDbvtNode* leaf); + void write(IWriter* iwriter) const; + void clone(btDbvt& dest,IClone* iclone=0) const; + static int maxdepth(const btDbvtNode* node); + static int countLeaves(const btDbvtNode* node); + static void extractLeaves(const btDbvtNode* node,btAlignedObjectArray& leaves); +#if DBVT_ENABLE_BENCHMARK + static void benchmark(); +#else + static void benchmark(){} +#endif + // DBVT_IPOLICY must support ICollide policy/interface + DBVT_PREFIX + static void enumNodes( const btDbvtNode* root, + DBVT_IPOLICY); + DBVT_PREFIX + static void enumLeaves( const btDbvtNode* root, + DBVT_IPOLICY); + DBVT_PREFIX + void collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + DBVT_IPOLICY); + + DBVT_PREFIX + void collideTTpersistentStack( const btDbvtNode* root0, + const btDbvtNode* root1, + DBVT_IPOLICY); +#if 0 + DBVT_PREFIX + void collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + const btTransform& xform, + DBVT_IPOLICY); + DBVT_PREFIX + void collideTT( const btDbvtNode* root0, + const btTransform& xform0, + const btDbvtNode* root1, + const btTransform& xform1, + DBVT_IPOLICY); +#endif + + DBVT_PREFIX + void collideTV( const btDbvtNode* root, + const btDbvtVolume& volume, + DBVT_IPOLICY); + ///rayTest is a re-entrant ray test, and can be called in parallel as long as the btAlignedAlloc is thread-safe (uses locking etc) + ///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time + DBVT_PREFIX + static void rayTest( const btDbvtNode* root, + const btVector3& rayFrom, + const btVector3& rayTo, + DBVT_IPOLICY); + ///rayTestInternal is faster than rayTest, because it uses a persistent stack (to reduce dynamic memory allocations to a minimum) and it uses precomputed signs/rayInverseDirections + ///rayTestInternal is used by btDbvtBroadphase to accelerate world ray casts + DBVT_PREFIX + void rayTestInternal( const btDbvtNode* root, + const btVector3& rayFrom, + const btVector3& rayTo, + const btVector3& rayDirectionInverse, + unsigned int signs[3], + btScalar lambda_max, + const btVector3& aabbMin, + const btVector3& aabbMax, + DBVT_IPOLICY) const; + + DBVT_PREFIX + static void collideKDOP(const btDbvtNode* root, + const btVector3* normals, + const btScalar* offsets, + int count, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideOCL( const btDbvtNode* root, + const btVector3* normals, + const btScalar* offsets, + const btVector3& sortaxis, + int count, + DBVT_IPOLICY, + bool fullsort=true); + DBVT_PREFIX + static void collideTU( const btDbvtNode* root, + DBVT_IPOLICY); + // Helpers + static DBVT_INLINE int nearest(const int* i,const btDbvt::sStkNPS* a,btScalar v,int l,int h) + { + int m=0; + while(l>1; + if(a[i[m]].value>=v) l=m+1; else h=m; + } + return(h); + } + static DBVT_INLINE int allocate( btAlignedObjectArray& ifree, + btAlignedObjectArray& stock, + const sStkNPS& value) + { + int i; + if(ifree.size()>0) + { i=ifree[ifree.size()-1];ifree.pop_back();stock[i]=value; } + else + { i=stock.size();stock.push_back(value); } + return(i); + } + // +private: + btDbvt(const btDbvt&) {} +}; + +// +// Inline's +// + +// +inline btDbvtAabbMm btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e) +{ + btDbvtAabbMm box; + box.mi=c-e;box.mx=c+e; + return(box); +} + +// +inline btDbvtAabbMm btDbvtAabbMm::FromCR(const btVector3& c,btScalar r) +{ + return(FromCE(c,btVector3(r,r,r))); +} + +// +inline btDbvtAabbMm btDbvtAabbMm::FromMM(const btVector3& mi,const btVector3& mx) +{ + btDbvtAabbMm box; + box.mi=mi;box.mx=mx; + return(box); +} + +// +inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3* pts,int n) +{ + btDbvtAabbMm box; + box.mi=box.mx=pts[0]; + for(int i=1;i0) mx.setX(mx.x()+e[0]); else mi.setX(mi.x()+e[0]); + if(e.y()>0) mx.setY(mx.y()+e[1]); else mi.setY(mi.y()+e[1]); + if(e.z()>0) mx.setZ(mx.z()+e[2]); else mi.setZ(mi.z()+e[2]); +} + +// +DBVT_INLINE bool btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const +{ + return( (mi.x()<=a.mi.x())&& + (mi.y()<=a.mi.y())&& + (mi.z()<=a.mi.z())&& + (mx.x()>=a.mx.x())&& + (mx.y()>=a.mx.y())&& + (mx.z()>=a.mx.z())); +} + +// +DBVT_INLINE int btDbvtAabbMm::Classify(const btVector3& n,btScalar o,int s) const +{ + btVector3 pi,px; + switch(s) + { + case (0+0+0): px=btVector3(mi.x(),mi.y(),mi.z()); + pi=btVector3(mx.x(),mx.y(),mx.z());break; + case (1+0+0): px=btVector3(mx.x(),mi.y(),mi.z()); + pi=btVector3(mi.x(),mx.y(),mx.z());break; + case (0+2+0): px=btVector3(mi.x(),mx.y(),mi.z()); + pi=btVector3(mx.x(),mi.y(),mx.z());break; + case (1+2+0): px=btVector3(mx.x(),mx.y(),mi.z()); + pi=btVector3(mi.x(),mi.y(),mx.z());break; + case (0+0+4): px=btVector3(mi.x(),mi.y(),mx.z()); + pi=btVector3(mx.x(),mx.y(),mi.z());break; + case (1+0+4): px=btVector3(mx.x(),mi.y(),mx.z()); + pi=btVector3(mi.x(),mx.y(),mi.z());break; + case (0+2+4): px=btVector3(mi.x(),mx.y(),mx.z()); + pi=btVector3(mx.x(),mi.y(),mi.z());break; + case (1+2+4): px=btVector3(mx.x(),mx.y(),mx.z()); + pi=btVector3(mi.x(),mi.y(),mi.z());break; + } + if((btDot(n,px)+o)<0) return(-1); + if((btDot(n,pi)+o)>=0) return(+1); + return(0); +} + +// +DBVT_INLINE btScalar btDbvtAabbMm::ProjectMinimum(const btVector3& v,unsigned signs) const +{ + const btVector3* b[]={&mx,&mi}; + const btVector3 p( b[(signs>>0)&1]->x(), + b[(signs>>1)&1]->y(), + b[(signs>>2)&1]->z()); + return(btDot(p,v)); +} + +// +DBVT_INLINE void btDbvtAabbMm::AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const +{ + for(int i=0;i<3;++i) + { + if(d[i]<0) + { smi+=mx[i]*d[i];smx+=mi[i]*d[i]; } + else + { smi+=mi[i]*d[i];smx+=mx[i]*d[i]; } + } +} + +// +DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, + const btDbvtAabbMm& b) +{ +#if DBVT_INT0_IMPL == DBVT_IMPL_SSE + const __m128 rt(_mm_or_ps( _mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)), + _mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi)))); + const __int32* pu((const __int32*)&rt); + return((pu[0]|pu[1]|pu[2])==0); +#else + return( (a.mi.x()<=b.mx.x())&& + (a.mx.x()>=b.mi.x())&& + (a.mi.y()<=b.mx.y())&& + (a.mx.y()>=b.mi.y())&& + (a.mi.z()<=b.mx.z())&& + (a.mx.z()>=b.mi.z())); +#endif +} + + + +// +DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, + const btVector3& b) +{ + return( (b.x()>=a.mi.x())&& + (b.y()>=a.mi.y())&& + (b.z()>=a.mi.z())&& + (b.x()<=a.mx.x())&& + (b.y()<=a.mx.y())&& + (b.z()<=a.mx.z())); +} + + + + + +////////////////////////////////////// + + +// +DBVT_INLINE btScalar Proximity( const btDbvtAabbMm& a, + const btDbvtAabbMm& b) +{ + const btVector3 d=(a.mi+a.mx)-(b.mi+b.mx); + return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z())); +} + + + +// +DBVT_INLINE int Select( const btDbvtAabbMm& o, + const btDbvtAabbMm& a, + const btDbvtAabbMm& b) +{ +#if DBVT_SELECT_IMPL == DBVT_IMPL_SSE + static ATTRIBUTE_ALIGNED16(const unsigned __int32) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff}; + ///@todo: the intrinsic version is 11% slower +#if DBVT_USE_INTRINSIC_SSE + + union btSSEUnion ///NOTE: if we use more intrinsics, move btSSEUnion into the LinearMath directory + { + __m128 ssereg; + float floats[4]; + int ints[4]; + }; + + __m128 omi(_mm_load_ps(o.mi)); + omi=_mm_add_ps(omi,_mm_load_ps(o.mx)); + __m128 ami(_mm_load_ps(a.mi)); + ami=_mm_add_ps(ami,_mm_load_ps(a.mx)); + ami=_mm_sub_ps(ami,omi); + ami=_mm_and_ps(ami,_mm_load_ps((const float*)mask)); + __m128 bmi(_mm_load_ps(b.mi)); + bmi=_mm_add_ps(bmi,_mm_load_ps(b.mx)); + bmi=_mm_sub_ps(bmi,omi); + bmi=_mm_and_ps(bmi,_mm_load_ps((const float*)mask)); + __m128 t0(_mm_movehl_ps(ami,ami)); + ami=_mm_add_ps(ami,t0); + ami=_mm_add_ss(ami,_mm_shuffle_ps(ami,ami,1)); + __m128 t1(_mm_movehl_ps(bmi,bmi)); + bmi=_mm_add_ps(bmi,t1); + bmi=_mm_add_ss(bmi,_mm_shuffle_ps(bmi,bmi,1)); + + btSSEUnion tmp; + tmp.ssereg = _mm_cmple_ss(bmi,ami); + return tmp.ints[0]&1; + +#else + ATTRIBUTE_ALIGNED16(__int32 r[1]); + __asm + { + mov eax,o + mov ecx,a + mov edx,b + movaps xmm0,[eax] + movaps xmm5,mask + addps xmm0,[eax+16] + movaps xmm1,[ecx] + movaps xmm2,[edx] + addps xmm1,[ecx+16] + addps xmm2,[edx+16] + subps xmm1,xmm0 + subps xmm2,xmm0 + andps xmm1,xmm5 + andps xmm2,xmm5 + movhlps xmm3,xmm1 + movhlps xmm4,xmm2 + addps xmm1,xmm3 + addps xmm2,xmm4 + pshufd xmm3,xmm1,1 + pshufd xmm4,xmm2,1 + addss xmm1,xmm3 + addss xmm2,xmm4 + cmpless xmm2,xmm1 + movss r,xmm2 + } + return(r[0]&1); +#endif +#else + return(Proximity(o,a)b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i]; + } +#endif +} + +// +DBVT_INLINE bool NotEqual( const btDbvtAabbMm& a, + const btDbvtAabbMm& b) +{ + return( (a.mi.x()!=b.mi.x())|| + (a.mi.y()!=b.mi.y())|| + (a.mi.z()!=b.mi.z())|| + (a.mx.x()!=b.mx.x())|| + (a.mx.y()!=b.mx.y())|| + (a.mx.z()!=b.mx.z())); +} + +// +// Inline's +// + +// +DBVT_PREFIX +inline void btDbvt::enumNodes( const btDbvtNode* root, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + policy.Process(root); + if(root->isinternal()) + { + enumNodes(root->childs[0],policy); + enumNodes(root->childs[1],policy); + } +} + +// +DBVT_PREFIX +inline void btDbvt::enumLeaves( const btDbvtNode* root, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + if(root->isinternal()) + { + enumLeaves(root->childs[0],policy); + enumLeaves(root->childs[1],policy); + } + else + { + policy.Process(root); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + if(root0&&root1) + { + int depth=1; + int treshold=DOUBLE_STACKSIZE-4; + btAlignedObjectArray stkStack; + stkStack.resize(DOUBLE_STACKSIZE); + stkStack[0]=sStkNN(root0,root1); + do { + sStkNN p=stkStack[--depth]; + if(depth>treshold) + { + stkStack.resize(stkStack.size()*2); + treshold=stkStack.size()-4; + } + if(p.a==p.b) + { + if(p.a->isinternal()) + { + stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]); + stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]); + stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]); + } + } + else if(Intersect(p.a->volume,p.b->volume)) + { + if(p.a->isinternal()) + { + if(p.b->isinternal()) + { + stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); + } + else + { + stkStack[depth++]=sStkNN(p.a->childs[0],p.b); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b); + } + } + else + { + if(p.b->isinternal()) + { + stkStack[depth++]=sStkNN(p.a,p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a,p.b->childs[1]); + } + else + { + policy.Process(p.a,p.b); + } + } + } + } while(depth); + } +} + + + +DBVT_PREFIX +inline void btDbvt::collideTTpersistentStack( const btDbvtNode* root0, + const btDbvtNode* root1, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + if(root0&&root1) + { + int depth=1; + int treshold=DOUBLE_STACKSIZE-4; + + m_stkStack.resize(DOUBLE_STACKSIZE); + m_stkStack[0]=sStkNN(root0,root1); + do { + sStkNN p=m_stkStack[--depth]; + if(depth>treshold) + { + m_stkStack.resize(m_stkStack.size()*2); + treshold=m_stkStack.size()-4; + } + if(p.a==p.b) + { + if(p.a->isinternal()) + { + m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]); + m_stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]); + m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]); + } + } + else if(Intersect(p.a->volume,p.b->volume)) + { + if(p.a->isinternal()) + { + if(p.b->isinternal()) + { + m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); + m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); + m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); + m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); + } + else + { + m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b); + m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b); + } + } + else + { + if(p.b->isinternal()) + { + m_stkStack[depth++]=sStkNN(p.a,p.b->childs[0]); + m_stkStack[depth++]=sStkNN(p.a,p.b->childs[1]); + } + else + { + policy.Process(p.a,p.b); + } + } + } + } while(depth); + } +} + +#if 0 +// +DBVT_PREFIX +inline void btDbvt::collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + const btTransform& xform, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + if(root0&&root1) + { + int depth=1; + int treshold=DOUBLE_STACKSIZE-4; + btAlignedObjectArray stkStack; + stkStack.resize(DOUBLE_STACKSIZE); + stkStack[0]=sStkNN(root0,root1); + do { + sStkNN p=stkStack[--depth]; + if(Intersect(p.a->volume,p.b->volume,xform)) + { + if(depth>treshold) + { + stkStack.resize(stkStack.size()*2); + treshold=stkStack.size()-4; + } + if(p.a->isinternal()) + { + if(p.b->isinternal()) + { + stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); + } + else + { + stkStack[depth++]=sStkNN(p.a->childs[0],p.b); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b); + } + } + else + { + if(p.b->isinternal()) + { + stkStack[depth++]=sStkNN(p.a,p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a,p.b->childs[1]); + } + else + { + policy.Process(p.a,p.b); + } + } + } + } while(depth); + } +} +// +DBVT_PREFIX +inline void btDbvt::collideTT( const btDbvtNode* root0, + const btTransform& xform0, + const btDbvtNode* root1, + const btTransform& xform1, + DBVT_IPOLICY) +{ + const btTransform xform=xform0.inverse()*xform1; + collideTT(root0,root1,xform,policy); +} +#endif + +// +DBVT_PREFIX +inline void btDbvt::collideTV( const btDbvtNode* root, + const btDbvtVolume& vol, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + if(root) + { + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol); + btAlignedObjectArray stack; + stack.resize(0); + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(root); + do { + const btDbvtNode* n=stack[stack.size()-1]; + stack.pop_back(); + if(Intersect(n->volume,volume)) + { + if(n->isinternal()) + { + stack.push_back(n->childs[0]); + stack.push_back(n->childs[1]); + } + else + { + policy.Process(n); + } + } + } while(stack.size()>0); + } +} + +DBVT_PREFIX +inline void btDbvt::rayTestInternal( const btDbvtNode* root, + const btVector3& rayFrom, + const btVector3& rayTo, + const btVector3& rayDirectionInverse, + unsigned int signs[3], + btScalar lambda_max, + const btVector3& aabbMin, + const btVector3& aabbMax, + DBVT_IPOLICY) const +{ + (void) rayTo; + DBVT_CHECKTYPE + if(root) + { + btVector3 resultNormal; + + int depth=1; + int treshold=DOUBLE_STACKSIZE-2; + btAlignedObjectArray& stack = m_rayTestStack; + stack.resize(DOUBLE_STACKSIZE); + stack[0]=root; + btVector3 bounds[2]; + do + { + const btDbvtNode* node=stack[--depth]; + bounds[0] = node->volume.Mins()-aabbMax; + bounds[1] = node->volume.Maxs()-aabbMin; + btScalar tmin=1.f,lambda_min=0.f; + unsigned int result1=false; + result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max); + if(result1) + { + if(node->isinternal()) + { + if(depth>treshold) + { + stack.resize(stack.size()*2); + treshold=stack.size()-2; + } + stack[depth++]=node->childs[0]; + stack[depth++]=node->childs[1]; + } + else + { + policy.Process(node); + } + } + } while(depth); + } +} + +// +DBVT_PREFIX +inline void btDbvt::rayTest( const btDbvtNode* root, + const btVector3& rayFrom, + const btVector3& rayTo, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + if(root) + { + btVector3 rayDir = (rayTo-rayFrom); + rayDir.normalize (); + + ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT + btVector3 rayDirectionInverse; + rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0]; + rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1]; + rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2]; + unsigned int signs[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0}; + + btScalar lambda_max = rayDir.dot(rayTo-rayFrom); + + btVector3 resultNormal; + + btAlignedObjectArray stack; + + int depth=1; + int treshold=DOUBLE_STACKSIZE-2; + + stack.resize(DOUBLE_STACKSIZE); + stack[0]=root; + btVector3 bounds[2]; + do { + const btDbvtNode* node=stack[--depth]; + + bounds[0] = node->volume.Mins(); + bounds[1] = node->volume.Maxs(); + + btScalar tmin=1.f,lambda_min=0.f; + unsigned int result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max); + +#ifdef COMPARE_BTRAY_AABB2 + btScalar param=1.f; + bool result2 = btRayAabb(rayFrom,rayTo,node->volume.Mins(),node->volume.Maxs(),param,resultNormal); + btAssert(result1 == result2); +#endif //TEST_BTRAY_AABB2 + + if(result1) + { + if(node->isinternal()) + { + if(depth>treshold) + { + stack.resize(stack.size()*2); + treshold=stack.size()-2; + } + stack[depth++]=node->childs[0]; + stack[depth++]=node->childs[1]; + } + else + { + policy.Process(node); + } + } + } while(depth); + + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideKDOP(const btDbvtNode* root, + const btVector3* normals, + const btScalar* offsets, + int count, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + if(root) + { + const int inside=(1< stack; + int signs[sizeof(unsigned)*8]; + btAssert(count=0)?1:0)+ + ((normals[i].y()>=0)?2:0)+ + ((normals[i].z()>=0)?4:0); + } + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(sStkNP(root,0)); + do { + sStkNP se=stack[stack.size()-1]; + bool out=false; + stack.pop_back(); + for(int i=0,j=1;(!out)&&(ivolume.Classify(normals[i],offsets[i],signs[i]); + switch(side) + { + case -1: out=true;break; + case +1: se.mask|=j;break; + } + } + } + if(!out) + { + if((se.mask!=inside)&&(se.node->isinternal())) + { + stack.push_back(sStkNP(se.node->childs[0],se.mask)); + stack.push_back(sStkNP(se.node->childs[1],se.mask)); + } + else + { + if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy); + } + } + } while(stack.size()); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideOCL( const btDbvtNode* root, + const btVector3* normals, + const btScalar* offsets, + const btVector3& sortaxis, + int count, + DBVT_IPOLICY, + bool fsort) +{ + DBVT_CHECKTYPE + if(root) + { + const unsigned srtsgns=(sortaxis[0]>=0?1:0)+ + (sortaxis[1]>=0?2:0)+ + (sortaxis[2]>=0?4:0); + const int inside=(1< stock; + btAlignedObjectArray ifree; + btAlignedObjectArray stack; + int signs[sizeof(unsigned)*8]; + btAssert(count=0)?1:0)+ + ((normals[i].y()>=0)?2:0)+ + ((normals[i].z()>=0)?4:0); + } + stock.reserve(SIMPLE_STACKSIZE); + stack.reserve(SIMPLE_STACKSIZE); + ifree.reserve(SIMPLE_STACKSIZE); + stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns)))); + do { + const int id=stack[stack.size()-1]; + sStkNPS se=stock[id]; + stack.pop_back();ifree.push_back(id); + if(se.mask!=inside) + { + bool out=false; + for(int i=0,j=1;(!out)&&(ivolume.Classify(normals[i],offsets[i],signs[i]); + switch(side) + { + case -1: out=true;break; + case +1: se.mask|=j;break; + } + } + } + if(out) continue; + } + if(policy.Descent(se.node)) + { + if(se.node->isinternal()) + { + const btDbvtNode* pns[]={ se.node->childs[0],se.node->childs[1]}; + sStkNPS nes[]={ sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)), + sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))}; + const int q=nes[0].value0)) + { + /* Insert 0 */ + j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size()); + stack.push_back(0); +#if DBVT_USE_MEMMOVE + memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1)); +#else + for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1]; +#endif + stack[j]=allocate(ifree,stock,nes[q]); + /* Insert 1 */ + j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size()); + stack.push_back(0); +#if DBVT_USE_MEMMOVE + memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1)); +#else + for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1]; +#endif + stack[j]=allocate(ifree,stock,nes[1-q]); + } + else + { + stack.push_back(allocate(ifree,stock,nes[q])); + stack.push_back(allocate(ifree,stock,nes[1-q])); + } + } + else + { + policy.Process(se.node,se.value); + } + } + } while(stack.size()); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideTU( const btDbvtNode* root, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + if(root) + { + btAlignedObjectArray stack; + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(root); + do { + const btDbvtNode* n=stack[stack.size()-1]; + stack.pop_back(); + if(policy.Descent(n)) + { + if(n->isinternal()) + { stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); } + else + { policy.Process(n); } + } + } while(stack.size()>0); + } +} + +// +// PP Cleanup +// + +#undef DBVT_USE_MEMMOVE +#undef DBVT_USE_TEMPLATE +#undef DBVT_VIRTUAL_DTOR +#undef DBVT_VIRTUAL +#undef DBVT_PREFIX +#undef DBVT_IPOLICY +#undef DBVT_CHECKTYPE +#undef DBVT_IMPL_GENERIC +#undef DBVT_IMPL_SSE +#undef DBVT_USE_INTRINSIC_SSE +#undef DBVT_SELECT_IMPL +#undef DBVT_MERGE_IMPL +#undef DBVT_INT0_IMPL + +#endif diff --git a/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp new file mode 100644 index 0000000..75cfac6 --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp @@ -0,0 +1,796 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +///btDbvtBroadphase implementation by Nathanael Presson + +#include "btDbvtBroadphase.h" + +// +// Profiling +// + +#if DBVT_BP_PROFILE||DBVT_BP_ENABLE_BENCHMARK +#include +#endif + +#if DBVT_BP_PROFILE +struct ProfileScope +{ + __forceinline ProfileScope(btClock& clock,unsigned long& value) : + m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds()) + { + } + __forceinline ~ProfileScope() + { + (*m_value)+=m_clock->getTimeMicroseconds()-m_base; + } + btClock* m_clock; + unsigned long* m_value; + unsigned long m_base; +}; +#define SPC(_value_) ProfileScope spc_scope(m_clock,_value_) +#else +#define SPC(_value_) +#endif + +// +// Helpers +// + +// +template +static inline void listappend(T* item,T*& list) +{ + item->links[0]=0; + item->links[1]=list; + if(list) list->links[0]=item; + list=item; +} + +// +template +static inline void listremove(T* item,T*& list) +{ + if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1]; + if(item->links[1]) item->links[1]->links[0]=item->links[0]; +} + +// +template +static inline int listcount(T* root) +{ + int n=0; + while(root) { ++n;root=root->links[1]; } + return(n); +} + +// +template +static inline void clear(T& value) +{ + static const struct ZeroDummy : T {} zerodummy; + value=zerodummy; +} + +// +// Colliders +// + +/* Tree collider */ +struct btDbvtTreeCollider : btDbvt::ICollide +{ + btDbvtBroadphase* pbp; + btDbvtProxy* proxy; + btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {} + void Process(const btDbvtNode* na,const btDbvtNode* nb) + { + if(na!=nb) + { + btDbvtProxy* pa=(btDbvtProxy*)na->data; + btDbvtProxy* pb=(btDbvtProxy*)nb->data; +#if DBVT_BP_SORTPAIRS + if(pa->m_uniqueId>pb->m_uniqueId) + btSwap(pa,pb); +#endif + pbp->m_paircache->addOverlappingPair(pa,pb); + ++pbp->m_newpairs; + } + } + void Process(const btDbvtNode* n) + { + Process(n,proxy->leaf); + } +}; + +// +// btDbvtBroadphase +// + +// +btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache) +{ + m_deferedcollide = false; + m_needcleanup = true; + m_releasepaircache = (paircache!=0)?false:true; + m_prediction = 0; + m_stageCurrent = 0; + m_fixedleft = 0; + m_fupdates = 1; + m_dupdates = 0; + m_cupdates = 10; + m_newpairs = 1; + m_updates_call = 0; + m_updates_done = 0; + m_updates_ratio = 0; + m_paircache = paircache? paircache : new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); + m_gid = 0; + m_pid = 0; + m_cid = 0; + for(int i=0;i<=STAGECOUNT;++i) + { + m_stageRoots[i]=0; + } +#if DBVT_BP_PROFILE + clear(m_profiling); +#endif +} + +// +btDbvtBroadphase::~btDbvtBroadphase() +{ + if(m_releasepaircache) + { + m_paircache->~btOverlappingPairCache(); + btAlignedFree(m_paircache); + } +} + +// +btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin, + const btVector3& aabbMax, + int /*shapeType*/, + void* userPtr, + short int collisionFilterGroup, + short int collisionFilterMask, + btDispatcher* /*dispatcher*/, + void* /*multiSapProxy*/) +{ + btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( aabbMin,aabbMax,userPtr, + collisionFilterGroup, + collisionFilterMask); + + btDbvtAabbMm aabb = btDbvtVolume::FromMM(aabbMin,aabbMax); + + //bproxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax); + proxy->stage = m_stageCurrent; + proxy->m_uniqueId = ++m_gid; + proxy->leaf = m_sets[0].insert(aabb,proxy); + listappend(proxy,m_stageRoots[m_stageCurrent]); + if(!m_deferedcollide) + { + btDbvtTreeCollider collider(this); + collider.proxy=proxy; + m_sets[0].collideTV(m_sets[0].m_root,aabb,collider); + m_sets[1].collideTV(m_sets[1].m_root,aabb,collider); + } + return(proxy); +} + +// +void btDbvtBroadphase::destroyProxy( btBroadphaseProxy* absproxy, + btDispatcher* dispatcher) +{ + btDbvtProxy* proxy=(btDbvtProxy*)absproxy; + if(proxy->stage==STAGECOUNT) + m_sets[1].remove(proxy->leaf); + else + m_sets[0].remove(proxy->leaf); + listremove(proxy,m_stageRoots[proxy->stage]); + m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher); + btAlignedFree(proxy); + m_needcleanup=true; +} + +void btDbvtBroadphase::getAabb(btBroadphaseProxy* absproxy,btVector3& aabbMin, btVector3& aabbMax ) const +{ + btDbvtProxy* proxy=(btDbvtProxy*)absproxy; + aabbMin = proxy->m_aabbMin; + aabbMax = proxy->m_aabbMax; +} + +struct BroadphaseRayTester : btDbvt::ICollide +{ + btBroadphaseRayCallback& m_rayCallback; + BroadphaseRayTester(btBroadphaseRayCallback& orgCallback) + :m_rayCallback(orgCallback) + { + } + void Process(const btDbvtNode* leaf) + { + btDbvtProxy* proxy=(btDbvtProxy*)leaf->data; + m_rayCallback.process(proxy); + } +}; + +void btDbvtBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax) +{ + BroadphaseRayTester callback(rayCallback); + + m_sets[0].rayTestInternal( m_sets[0].m_root, + rayFrom, + rayTo, + rayCallback.m_rayDirectionInverse, + rayCallback.m_signs, + rayCallback.m_lambda_max, + aabbMin, + aabbMax, + callback); + + m_sets[1].rayTestInternal( m_sets[1].m_root, + rayFrom, + rayTo, + rayCallback.m_rayDirectionInverse, + rayCallback.m_signs, + rayCallback.m_lambda_max, + aabbMin, + aabbMax, + callback); + +} + + +struct BroadphaseAabbTester : btDbvt::ICollide +{ + btBroadphaseAabbCallback& m_aabbCallback; + BroadphaseAabbTester(btBroadphaseAabbCallback& orgCallback) + :m_aabbCallback(orgCallback) + { + } + void Process(const btDbvtNode* leaf) + { + btDbvtProxy* proxy=(btDbvtProxy*)leaf->data; + m_aabbCallback.process(proxy); + } +}; + +void btDbvtBroadphase::aabbTest(const btVector3& aabbMin,const btVector3& aabbMax,btBroadphaseAabbCallback& aabbCallback) +{ + BroadphaseAabbTester callback(aabbCallback); + + const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(aabbMin,aabbMax); + //process all children, that overlap with the given AABB bounds + m_sets[0].collideTV(m_sets[0].m_root,bounds,callback); + m_sets[1].collideTV(m_sets[1].m_root,bounds,callback); + +} + + + +// +void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy, + const btVector3& aabbMin, + const btVector3& aabbMax, + btDispatcher* /*dispatcher*/) +{ + btDbvtProxy* proxy=(btDbvtProxy*)absproxy; + ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax); +#if DBVT_BP_PREVENTFALSEUPDATE + if(NotEqual(aabb,proxy->leaf->volume)) +#endif + { + bool docollide=false; + if(proxy->stage==STAGECOUNT) + {/* fixed -> dynamic set */ + m_sets[1].remove(proxy->leaf); + proxy->leaf=m_sets[0].insert(aabb,proxy); + docollide=true; + } + else + {/* dynamic set */ + ++m_updates_call; + if(Intersect(proxy->leaf->volume,aabb)) + {/* Moving */ + + const btVector3 delta=aabbMin-proxy->m_aabbMin; + btVector3 velocity(((proxy->m_aabbMax-proxy->m_aabbMin)/2)*m_prediction); + if(delta[0]<0) velocity[0]=-velocity[0]; + if(delta[1]<0) velocity[1]=-velocity[1]; + if(delta[2]<0) velocity[2]=-velocity[2]; + if ( +#ifdef DBVT_BP_MARGIN + m_sets[0].update(proxy->leaf,aabb,velocity,DBVT_BP_MARGIN) +#else + m_sets[0].update(proxy->leaf,aabb,velocity) +#endif + ) + { + ++m_updates_done; + docollide=true; + } + } + else + {/* Teleporting */ + m_sets[0].update(proxy->leaf,aabb); + ++m_updates_done; + docollide=true; + } + } + listremove(proxy,m_stageRoots[proxy->stage]); + proxy->m_aabbMin = aabbMin; + proxy->m_aabbMax = aabbMax; + proxy->stage = m_stageCurrent; + listappend(proxy,m_stageRoots[m_stageCurrent]); + if(docollide) + { + m_needcleanup=true; + if(!m_deferedcollide) + { + btDbvtTreeCollider collider(this); + m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider); + m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider); + } + } + } +} + + +// +void btDbvtBroadphase::setAabbForceUpdate( btBroadphaseProxy* absproxy, + const btVector3& aabbMin, + const btVector3& aabbMax, + btDispatcher* /*dispatcher*/) +{ + btDbvtProxy* proxy=(btDbvtProxy*)absproxy; + ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax); + bool docollide=false; + if(proxy->stage==STAGECOUNT) + {/* fixed -> dynamic set */ + m_sets[1].remove(proxy->leaf); + proxy->leaf=m_sets[0].insert(aabb,proxy); + docollide=true; + } + else + {/* dynamic set */ + ++m_updates_call; + /* Teleporting */ + m_sets[0].update(proxy->leaf,aabb); + ++m_updates_done; + docollide=true; + } + listremove(proxy,m_stageRoots[proxy->stage]); + proxy->m_aabbMin = aabbMin; + proxy->m_aabbMax = aabbMax; + proxy->stage = m_stageCurrent; + listappend(proxy,m_stageRoots[m_stageCurrent]); + if(docollide) + { + m_needcleanup=true; + if(!m_deferedcollide) + { + btDbvtTreeCollider collider(this); + m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider); + m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider); + } + } +} + +// +void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + collide(dispatcher); +#if DBVT_BP_PROFILE + if(0==(m_pid%DBVT_BP_PROFILING_RATE)) + { + printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs()); + unsigned int total=m_profiling.m_total; + if(total<=0) total=1; + printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE); + printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE); + printf("cleanup: %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE); + printf("total: %uus\r\n",total/DBVT_BP_PROFILING_RATE); + const unsigned long sum=m_profiling.m_ddcollide+ + m_profiling.m_fdcollide+ + m_profiling.m_cleanup; + printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE); + printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*DBVT_BP_PROFILING_RATE)); + clear(m_profiling); + m_clock.reset(); + } +#endif + + performDeferredRemoval(dispatcher); + +} + +void btDbvtBroadphase::performDeferredRemoval(btDispatcher* dispatcher) +{ + + if (m_paircache->hasDeferredRemoval()) + { + + btBroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray(); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + int invalidPair = 0; + + + int i; + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;ileaf->volume,pb->leaf->volume); + + if (hasOverlap) + { + needsRemoval = false; + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + m_paircache->cleanOverlappingPair(pair,dispatcher); + + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + invalidPair++; + } + + } + + //perform a sort, to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + overlappingPairArray.resize(overlappingPairArray.size() - invalidPair); + } +} + +// +void btDbvtBroadphase::collide(btDispatcher* dispatcher) +{ + /*printf("---------------------------------------------------------\n"); + printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves); + printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves); + printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs()); + { + int i; + for (i=0;igetNumOverlappingPairs();i++) + { + printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(), + getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid()); + } + printf("\n"); + } +*/ + + + + SPC(m_profiling.m_total); + /* optimize */ + m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100); + if(m_fixedleft) + { + const int count=1+(m_sets[1].m_leaves*m_fupdates)/100; + m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100); + m_fixedleft=btMax(0,m_fixedleft-count); + } + /* dynamic -> fixed set */ + m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT; + btDbvtProxy* current=m_stageRoots[m_stageCurrent]; + if(current) + { + btDbvtTreeCollider collider(this); + do { + btDbvtProxy* next=current->links[1]; + listremove(current,m_stageRoots[current->stage]); + listappend(current,m_stageRoots[STAGECOUNT]); +#if DBVT_BP_ACCURATESLEEPING + m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher); + collider.proxy=current; + btDbvt::collideTV(m_sets[0].m_root,current->aabb,collider); + btDbvt::collideTV(m_sets[1].m_root,current->aabb,collider); +#endif + m_sets[0].remove(current->leaf); + ATTRIBUTE_ALIGNED16(btDbvtVolume) curAabb=btDbvtVolume::FromMM(current->m_aabbMin,current->m_aabbMax); + current->leaf = m_sets[1].insert(curAabb,current); + current->stage = STAGECOUNT; + current = next; + } while(current); + m_fixedleft=m_sets[1].m_leaves; + m_needcleanup=true; + } + /* collide dynamics */ + { + btDbvtTreeCollider collider(this); + if(m_deferedcollide) + { + SPC(m_profiling.m_fdcollide); + m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[1].m_root,collider); + } + if(m_deferedcollide) + { + SPC(m_profiling.m_ddcollide); + m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[0].m_root,collider); + } + } + /* clean up */ + if(m_needcleanup) + { + SPC(m_profiling.m_cleanup); + btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray(); + if(pairs.size()>0) + { + + int ni=btMin(pairs.size(),btMax(m_newpairs,(pairs.size()*m_cupdates)/100)); + for(int i=0;ileaf->volume,pb->leaf->volume)) + { +#if DBVT_BP_SORTPAIRS + if(pa->m_uniqueId>pb->m_uniqueId) + btSwap(pa,pb); +#endif + m_paircache->removeOverlappingPair(pa,pb,dispatcher); + --ni;--i; + } + } + if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0; + } + } + ++m_pid; + m_newpairs=1; + m_needcleanup=false; + if(m_updates_call>0) + { m_updates_ratio=m_updates_done/(btScalar)m_updates_call; } + else + { m_updates_ratio=0; } + m_updates_done/=2; + m_updates_call/=2; +} + +// +void btDbvtBroadphase::optimize() +{ + m_sets[0].optimizeTopDown(); + m_sets[1].optimizeTopDown(); +} + +// +btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() +{ + return(m_paircache); +} + +// +const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const +{ + return(m_paircache); +} + +// +void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const +{ + + ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds; + + if(!m_sets[0].empty()) + if(!m_sets[1].empty()) Merge( m_sets[0].m_root->volume, + m_sets[1].m_root->volume,bounds); + else + bounds=m_sets[0].m_root->volume; + else if(!m_sets[1].empty()) bounds=m_sets[1].m_root->volume; + else + bounds=btDbvtVolume::FromCR(btVector3(0,0,0),0); + aabbMin=bounds.Mins(); + aabbMax=bounds.Maxs(); +} + +void btDbvtBroadphase::resetPool(btDispatcher* dispatcher) +{ + + int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves; + if (!totalObjects) + { + //reset internal dynamic tree data structures + m_sets[0].clear(); + m_sets[1].clear(); + + m_deferedcollide = false; + m_needcleanup = true; + m_stageCurrent = 0; + m_fixedleft = 0; + m_fupdates = 1; + m_dupdates = 0; + m_cupdates = 10; + m_newpairs = 1; + m_updates_call = 0; + m_updates_done = 0; + m_updates_ratio = 0; + + m_gid = 0; + m_pid = 0; + m_cid = 0; + for(int i=0;i<=STAGECOUNT;++i) + { + m_stageRoots[i]=0; + } + } +} + +// +void btDbvtBroadphase::printStats() +{} + +// +#if DBVT_BP_ENABLE_BENCHMARK + +struct btBroadphaseBenchmark +{ + struct Experiment + { + const char* name; + int object_count; + int update_count; + int spawn_count; + int iterations; + btScalar speed; + btScalar amplitude; + }; + struct Object + { + btVector3 center; + btVector3 extents; + btBroadphaseProxy* proxy; + btScalar time; + void update(btScalar speed,btScalar amplitude,btBroadphaseInterface* pbi) + { + time += speed; + center[0] = btCos(time*(btScalar)2.17)*amplitude+ + btSin(time)*amplitude/2; + center[1] = btCos(time*(btScalar)1.38)*amplitude+ + btSin(time)*amplitude; + center[2] = btSin(time*(btScalar)0.777)*amplitude; + pbi->setAabb(proxy,center-extents,center+extents,0); + } + }; + static int UnsignedRand(int range=RAND_MAX-1) { return(rand()%(range+1)); } + static btScalar UnitRand() { return(UnsignedRand(16384)/(btScalar)16384); } + static void OutputTime(const char* name,btClock& c,unsigned count=0) + { + const unsigned long us=c.getTimeMicroseconds(); + const unsigned long ms=(us+500)/1000; + const btScalar sec=us/(btScalar)(1000*1000); + if(count>0) + printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec); + else + printf("%s : %u us (%u ms)\r\n",name,us,ms); + } +}; + +void btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi) +{ + static const btBroadphaseBenchmark::Experiment experiments[]= + { + {"1024o.10%",1024,10,0,8192,(btScalar)0.005,(btScalar)100}, + /*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100}, + {"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/ + }; + static const int nexperiments=sizeof(experiments)/sizeof(experiments[0]); + btAlignedObjectArray objects; + btClock wallclock; + /* Begin */ + for(int iexp=0;iexpcenter[0]=btBroadphaseBenchmark::UnitRand()*50; + po->center[1]=btBroadphaseBenchmark::UnitRand()*50; + po->center[2]=btBroadphaseBenchmark::UnitRand()*50; + po->extents[0]=btBroadphaseBenchmark::UnitRand()*2+2; + po->extents[1]=btBroadphaseBenchmark::UnitRand()*2+2; + po->extents[2]=btBroadphaseBenchmark::UnitRand()*2+2; + po->time=btBroadphaseBenchmark::UnitRand()*2000; + po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0); + objects.push_back(po); + } + btBroadphaseBenchmark::OutputTime("\tInitialization",wallclock); + /* First update */ + wallclock.reset(); + for(int i=0;iupdate(speed,amplitude,pbi); + } + btBroadphaseBenchmark::OutputTime("\tFirst update",wallclock); + /* Updates */ + wallclock.reset(); + for(int i=0;iupdate(speed,amplitude,pbi); + } + pbi->calculateOverlappingPairs(0); + } + btBroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations); + /* Clean up */ + wallclock.reset(); + for(int i=0;idestroyProxy(objects[i]->proxy,0); + delete objects[i]; + } + objects.resize(0); + btBroadphaseBenchmark::OutputTime("\tRelease",wallclock); + } + +} +#else +void btDbvtBroadphase::benchmark(btBroadphaseInterface*) +{} +#endif + +#if DBVT_BP_PROFILE +#undef SPC +#endif + diff --git a/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h new file mode 100644 index 0000000..18b64ad --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h @@ -0,0 +1,146 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +///btDbvtBroadphase implementation by Nathanael Presson +#ifndef BT_DBVT_BROADPHASE_H +#define BT_DBVT_BROADPHASE_H + +#include "BulletCollision/BroadphaseCollision/btDbvt.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" + +// +// Compile time config +// + +#define DBVT_BP_PROFILE 0 +//#define DBVT_BP_SORTPAIRS 1 +#define DBVT_BP_PREVENTFALSEUPDATE 0 +#define DBVT_BP_ACCURATESLEEPING 0 +#define DBVT_BP_ENABLE_BENCHMARK 0 +#define DBVT_BP_MARGIN (btScalar)0.05 + +#if DBVT_BP_PROFILE +#define DBVT_BP_PROFILING_RATE 256 +#include "LinearMath/btQuickprof.h" +#endif + +// +// btDbvtProxy +// +struct btDbvtProxy : btBroadphaseProxy +{ + /* Fields */ + //btDbvtAabbMm aabb; + btDbvtNode* leaf; + btDbvtProxy* links[2]; + int stage; + /* ctor */ + btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) : + btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask) + { + links[0]=links[1]=0; + } +}; + +typedef btAlignedObjectArray btDbvtProxyArray; + +///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt). +///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other. +///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3. +struct btDbvtBroadphase : btBroadphaseInterface +{ + /* Config */ + enum { + DYNAMIC_SET = 0, /* Dynamic set index */ + FIXED_SET = 1, /* Fixed set index */ + STAGECOUNT = 2 /* Number of stages */ + }; + /* Fields */ + btDbvt m_sets[2]; // Dbvt sets + btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list + btOverlappingPairCache* m_paircache; // Pair cache + btScalar m_prediction; // Velocity prediction + int m_stageCurrent; // Current stage + int m_fupdates; // % of fixed updates per frame + int m_dupdates; // % of dynamic updates per frame + int m_cupdates; // % of cleanup updates per frame + int m_newpairs; // Number of pairs created + int m_fixedleft; // Fixed optimization left + unsigned m_updates_call; // Number of updates call + unsigned m_updates_done; // Number of updates done + btScalar m_updates_ratio; // m_updates_done/m_updates_call + int m_pid; // Parse id + int m_cid; // Cleanup index + int m_gid; // Gen id + bool m_releasepaircache; // Release pair cache on delete + bool m_deferedcollide; // Defere dynamic/static collision to collide call + bool m_needcleanup; // Need to run cleanup? +#if DBVT_BP_PROFILE + btClock m_clock; + struct { + unsigned long m_total; + unsigned long m_ddcollide; + unsigned long m_fdcollide; + unsigned long m_cleanup; + unsigned long m_jobcount; + } m_profiling; +#endif + /* Methods */ + btDbvtBroadphase(btOverlappingPairCache* paircache=0); + ~btDbvtBroadphase(); + void collide(btDispatcher* dispatcher); + void optimize(); + + /* btBroadphaseInterface Implementation */ + btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)); + virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback); + + virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); + virtual btOverlappingPairCache* getOverlappingPairCache(); + virtual const btOverlappingPairCache* getOverlappingPairCache() const; + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const; + virtual void printStats(); + + + ///reset broadphase internal structures, to ensure determinism/reproducability + virtual void resetPool(btDispatcher* dispatcher); + + void performDeferredRemoval(btDispatcher* dispatcher); + + void setVelocityPrediction(btScalar prediction) + { + m_prediction = prediction; + } + btScalar getVelocityPrediction() const + { + return m_prediction; + } + + ///this setAabbForceUpdate is similar to setAabb but always forces the aabb update. + ///it is not part of the btBroadphaseInterface but specific to btDbvtBroadphase. + ///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see + ///http://code.google.com/p/bullet/issues/detail?id=223 + void setAabbForceUpdate( btBroadphaseProxy* absproxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* /*dispatcher*/); + + static void benchmark(btBroadphaseInterface*); + + +}; + +#endif diff --git a/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp b/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp new file mode 100644 index 0000000..2076822 --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp @@ -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. +*/ + +#include "btDispatcher.h" + +btDispatcher::~btDispatcher() +{ + +} + diff --git a/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/src/BulletCollision/BroadphaseCollision/btDispatcher.h new file mode 100644 index 0000000..a79cf94 --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btDispatcher.h @@ -0,0 +1,110 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_DISPATCHER_H +#define BT_DISPATCHER_H +#include "LinearMath/btScalar.h" + +class btCollisionAlgorithm; +struct btBroadphaseProxy; +class btRigidBody; +class btCollisionObject; +class btOverlappingPairCache; + + +class btPersistentManifold; +class btStackAlloc; +class btPoolAllocator; + +struct btDispatcherInfo +{ + enum DispatchFunc + { + DISPATCH_DISCRETE = 1, + DISPATCH_CONTINUOUS + }; + btDispatcherInfo() + :m_timeStep(btScalar(0.)), + m_stepCount(0), + m_dispatchFunc(DISPATCH_DISCRETE), + m_timeOfImpact(btScalar(1.)), + m_useContinuous(true), + m_debugDraw(0), + m_enableSatConvex(false), + m_enableSPU(true), + m_useEpa(true), + m_allowedCcdPenetration(btScalar(0.04)), + m_useConvexConservativeDistanceUtil(false), + m_convexConservativeDistanceThreshold(0.0f), + m_stackAllocator(0) + { + + } + btScalar m_timeStep; + int m_stepCount; + int m_dispatchFunc; + mutable btScalar m_timeOfImpact; + bool m_useContinuous; + class btIDebugDraw* m_debugDraw; + bool m_enableSatConvex; + bool m_enableSPU; + bool m_useEpa; + btScalar m_allowedCcdPenetration; + bool m_useConvexConservativeDistanceUtil; + btScalar m_convexConservativeDistanceThreshold; + btStackAlloc* m_stackAllocator; +}; + +///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs. +///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic). +class btDispatcher +{ + + +public: + virtual ~btDispatcher() ; + + virtual btCollisionAlgorithm* findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold=0) = 0; + + virtual btPersistentManifold* getNewManifold(void* body0,void* body1)=0; + + virtual void releaseManifold(btPersistentManifold* manifold)=0; + + virtual void clearManifold(btPersistentManifold* manifold)=0; + + virtual bool needsCollision(btCollisionObject* body0,btCollisionObject* body1) = 0; + + virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0; + + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) =0; + + virtual int getNumManifolds() const = 0; + + virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0; + + virtual btPersistentManifold** getInternalManifoldPointer() = 0; + + virtual btPoolAllocator* getInternalManifoldPool() = 0; + + virtual const btPoolAllocator* getInternalManifoldPool() const = 0; + + virtual void* allocateCollisionAlgorithm(int size) = 0; + + virtual void freeCollisionAlgorithm(void* ptr) = 0; + +}; + + +#endif //BT_DISPATCHER_H diff --git a/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp b/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp new file mode 100644 index 0000000..81369fe --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp @@ -0,0 +1,489 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btMultiSapBroadphase.h" + +#include "btSimpleBroadphase.h" +#include "LinearMath/btAabbUtil2.h" +#include "btQuantizedBvh.h" + +/// btSapBroadphaseArray m_sapBroadphases; + +/// btOverlappingPairCache* m_overlappingPairs; +extern int gOverlappingPairs; + +/* +class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache +{ +public: + + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) + { + return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy); + } +}; + +*/ + +btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache) +:m_overlappingPairs(pairCache), +m_optimizedAabbTree(0), +m_ownsPairCache(false), +m_invalidPair(0) +{ + if (!m_overlappingPairs) + { + m_ownsPairCache = true; + void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16); + m_overlappingPairs = new (mem)btSortedOverlappingPairCache(); + } + + struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback + { + virtual ~btMultiSapOverlapFilterCallback() + {} + // return true when pairs need collision + virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const + { + btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy; + btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy; + + bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0; + collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->m_collisionFilterMask); + + return collides; + } + }; + + void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16); + m_filterCallback = new (mem)btMultiSapOverlapFilterCallback(); + + m_overlappingPairs->setOverlapFilterCallback(m_filterCallback); +// mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16); +// m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs); +} + +btMultiSapBroadphase::~btMultiSapBroadphase() +{ + if (m_ownsPairCache) + { + m_overlappingPairs->~btOverlappingPairCache(); + btAlignedFree(m_overlappingPairs); + } +} + + +void btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax) +{ + m_optimizedAabbTree = new btQuantizedBvh(); + m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax); + QuantizedNodeArray& nodes = m_optimizedAabbTree->getLeafNodeArray(); + for (int i=0;igetBroadphaseAabb(aabbMin,aabbMax); + m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0); + m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1); + int partId = 0; + node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i; + nodes.push_back(node); + } + m_optimizedAabbTree->buildInternal(); +} + +btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/) +{ + //void* ignoreMe -> we could think of recursive multi-sap, if someone is interested + + void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16); + btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask); + m_multiSapProxies.push_back(proxy); + + ///this should deal with inserting/removal into child broadphases + setAabb(proxy,aabbMin,aabbMax,dispatcher); + return proxy; +} + +void btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/) +{ + ///not yet + btAssert(0); + +} + + +void btMultiSapBroadphase::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase) +{ + void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16); + btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy; + bridgeProxyRef->m_childProxy = childProxy; + bridgeProxyRef->m_childBroadphase = childBroadphase; + parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef); +} + + +bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax); +bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax) +{ +return +amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() && +amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() && +amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ(); +} + + + + + + +void btMultiSapBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const +{ + btMultiSapProxy* multiProxy = static_cast(proxy); + aabbMin = multiProxy->m_aabbMin; + aabbMax = multiProxy->m_aabbMax; +} + +void btMultiSapBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax) +{ + for (int i=0;i + +void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher) +{ + btMultiSapProxy* multiProxy = static_cast(proxy); + multiProxy->m_aabbMin = aabbMin; + multiProxy->m_aabbMax = aabbMax; + + +// bool fullyContained = false; +// bool alreadyInSimple = false; + + + + + struct MyNodeOverlapCallback : public btNodeOverlapCallback + { + btMultiSapBroadphase* m_multiSap; + btMultiSapProxy* m_multiProxy; + btDispatcher* m_dispatcher; + + MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher) + :m_multiSap(multiSap), + m_multiProxy(multiProxy), + m_dispatcher(dispatcher) + { + + } + + virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex) + { + btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex]; + + int containingBroadphaseIndex = -1; + //already found? + for (int i=0;im_bridgeProxies.size();i++) + { + + if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase) + { + containingBroadphaseIndex = i; + break; + } + } + if (containingBroadphaseIndex<0) + { + //add it + btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy); + m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase); + + } + } + }; + + MyNodeOverlapCallback myNodeCallback(this,multiProxy,dispatcher); + + + + + if (m_optimizedAabbTree) + m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); + + int i; + + for ( i=0;im_bridgeProxies.size();i++) + { + btVector3 worldAabbMin,worldAabbMax; + multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax); + bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); + if (!overlapsBroadphase) + { + //remove it now + btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i]; + + btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy; + bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher); + + multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1); + multiProxy->m_bridgeProxies.pop_back(); + + } + } + + + /* + + if (1) + { + + //find broadphase that contain this multiProxy + int numChildBroadphases = getBroadphaseArray().size(); + for (int i=0;igetBroadphaseAabb(worldAabbMin,worldAabbMax); + bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); + + // fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); + int containingBroadphaseIndex = -1; + + //if already contains this + + for (int i=0;im_bridgeProxies.size();i++) + { + if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase) + { + containingBroadphaseIndex = i; + } + alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase); + } + + if (overlapsBroadphase) + { + if (containingBroadphaseIndex<0) + { + btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); + childProxy->m_multiSapParentProxy = multiProxy; + addToChildBroadphase(multiProxy,childProxy,childBroadphase); + } + } else + { + if (containingBroadphaseIndex>=0) + { + //remove + btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex]; + + btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy; + bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher); + + multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1); + multiProxy->m_bridgeProxies.pop_back(); + } + } + } + + + ///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force) + ///hopefully we don't end up with many entries here (can assert/provide feedback on stats) + if (0)//!multiProxy->m_bridgeProxies.size()) + { + ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision + ///this is needed to be able to calculate the aabb overlap + btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); + childProxy->m_multiSapParentProxy = multiProxy; + addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase); + } + } + + if (!multiProxy->m_bridgeProxies.size()) + { + ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision + ///this is needed to be able to calculate the aabb overlap + btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); + childProxy->m_multiSapParentProxy = multiProxy; + addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase); + } +*/ + + + //update + for ( i=0;im_bridgeProxies.size();i++) + { + btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i]; + bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher); + } + +} +bool stopUpdating=false; + + + +class btMultiSapBroadphasePairSortPredicate +{ + public: + + bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 ) const + { + btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0; + btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0; + btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0; + btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0; + + return aProxy0 > bProxy0 || + (aProxy0 == bProxy0 && aProxy1 > bProxy1) || + (aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm); + } +}; + + + ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb +void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + +// m_simpleBroadphase->calculateOverlappingPairs(dispatcher); + + if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval()) + { + + btBroadphasePairArray& overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray(); + + // quicksort(overlappingPairArray,0,overlappingPairArray.size()); + + overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate()); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + // overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + + + int i; + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;im_multiSapParentProxy : 0; + btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0; + btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0; + btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0; + + bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1); + + previousPair = pair; + + bool needsRemoval = false; + + if (!isDuplicate) + { + bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1); + + if (hasOverlap) + { + needsRemoval = false;//callback->processOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } + + ///if you don't like to skip the invalid pairs in the array, execute following code: + #define CLEAN_INVALID_PAIRS 1 + #ifdef CLEAN_INVALID_PAIRS + + //perform a sort, to sort 'invalid' pairs to the end + //overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate()); + overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + #endif//CLEAN_INVALID_PAIRS + + //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size()); + } + + +} + + +bool btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) +{ + btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy; + btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy; + + return TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax, + multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax); + +} + + +void btMultiSapBroadphase::printStats() +{ +/* printf("---------------------------------\n"); + + printf("btMultiSapBroadphase.h\n"); + printf("numHandles = %d\n",m_multiSapProxies.size()); + //find broadphase that contain this multiProxy + int numChildBroadphases = getBroadphaseArray().size(); + for (int i=0;iprintStats(); + + } + */ + +} + +void btMultiSapBroadphase::resetPool(btDispatcher* dispatcher) +{ + // not yet +} diff --git a/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h b/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h new file mode 100644 index 0000000..7bcfe6b --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h @@ -0,0 +1,151 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BT_MULTI_SAP_BROADPHASE +#define BT_MULTI_SAP_BROADPHASE + +#include "btBroadphaseInterface.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "btOverlappingPairCache.h" + + +class btBroadphaseInterface; +class btSimpleBroadphase; + + +typedef btAlignedObjectArray btSapBroadphaseArray; + +///The btMultiSapBroadphase is a research project, not recommended to use in production. Use btAxisSweep3 or btDbvtBroadphase instead. +///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases. +///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time. +///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy. +///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328 +///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329 +class btMultiSapBroadphase :public btBroadphaseInterface +{ + btSapBroadphaseArray m_sapBroadphases; + + btSimpleBroadphase* m_simpleBroadphase; + + btOverlappingPairCache* m_overlappingPairs; + + class btQuantizedBvh* m_optimizedAabbTree; + + + bool m_ownsPairCache; + + btOverlapFilterCallback* m_filterCallback; + + int m_invalidPair; + + struct btBridgeProxy + { + btBroadphaseProxy* m_childProxy; + btBroadphaseInterface* m_childBroadphase; + }; + + +public: + + struct btMultiSapProxy : public btBroadphaseProxy + { + + ///array with all the entries that this proxy belongs to + btAlignedObjectArray m_bridgeProxies; + btVector3 m_aabbMin; + btVector3 m_aabbMax; + + int m_shapeType; + +/* void* m_userPtr; + short int m_collisionFilterGroup; + short int m_collisionFilterMask; +*/ + btMultiSapProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) + :btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask), + m_aabbMin(aabbMin), + m_aabbMax(aabbMax), + m_shapeType(shapeType) + { + m_multiSapParentProxy =this; + } + + + }; + +protected: + + + btAlignedObjectArray m_multiSapProxies; + +public: + + btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0); + + + btSapBroadphaseArray& getBroadphaseArray() + { + return m_sapBroadphases; + } + + const btSapBroadphaseArray& getBroadphaseArray() const + { + return m_sapBroadphases; + } + + virtual ~btMultiSapBroadphase(); + + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); + virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; + + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0)); + + void addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase); + + ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); + + bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + virtual btOverlappingPairCache* getOverlappingPairCache() + { + return m_overlappingPairs; + } + virtual const btOverlappingPairCache* getOverlappingPairCache() const + { + return m_overlappingPairs; + } + + ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame + ///will add some transform later + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT); + aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); + } + + void buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax); + + virtual void printStats(); + + void quicksort (btBroadphasePairArray& a, int lo, int hi); + + ///reset broadphase internal structures, to ensure determinism/reproducability + virtual void resetPool(btDispatcher* dispatcher); + +}; + +#endif //BT_MULTI_SAP_BROADPHASE diff --git a/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp new file mode 100644 index 0000000..041bbe0 --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp @@ -0,0 +1,633 @@ +/* +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 "btOverlappingPairCache.h" + +#include "btDispatcher.h" +#include "btCollisionAlgorithm.h" +#include "LinearMath/btAabbUtil2.h" + +#include + +int gOverlappingPairs = 0; + +int gRemovePairs =0; +int gAddedPairs =0; +int gFindPairs =0; + + + + +btHashedOverlappingPairCache::btHashedOverlappingPairCache(): + m_overlapFilterCallback(0), + m_blockedForChanges(false), + m_ghostPairCallback(0) +{ + int initialAllocatedSize= 2; + m_overlappingPairArray.reserve(initialAllocatedSize); + growTables(); +} + + + + +btHashedOverlappingPairCache::~btHashedOverlappingPairCache() +{ +} + + + +void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) +{ + if (pair.m_algorithm) + { + { + pair.m_algorithm->~btCollisionAlgorithm(); + dispatcher->freeCollisionAlgorithm(pair.m_algorithm); + pair.m_algorithm=0; + } + } +} + + + + +void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + + class CleanPairCallback : public btOverlapCallback + { + btBroadphaseProxy* m_cleanProxy; + btOverlappingPairCache* m_pairCache; + btDispatcher* m_dispatcher; + + public: + CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) + :m_cleanProxy(cleanProxy), + m_pairCache(pairCache), + m_dispatcher(dispatcher) + { + } + virtual bool processOverlap(btBroadphasePair& pair) + { + if ((pair.m_pProxy0 == m_cleanProxy) || + (pair.m_pProxy1 == m_cleanProxy)) + { + m_pairCache->cleanOverlappingPair(pair,m_dispatcher); + } + return false; + } + + }; + + CleanPairCallback cleanPairs(proxy,this,dispatcher); + + processAllOverlappingPairs(&cleanPairs,dispatcher); + +} + + + + +void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + + class RemovePairCallback : public btOverlapCallback + { + btBroadphaseProxy* m_obsoleteProxy; + + public: + RemovePairCallback(btBroadphaseProxy* obsoleteProxy) + :m_obsoleteProxy(obsoleteProxy) + { + } + virtual bool processOverlap(btBroadphasePair& pair) + { + return ((pair.m_pProxy0 == m_obsoleteProxy) || + (pair.m_pProxy1 == m_obsoleteProxy)); + } + + }; + + + RemovePairCallback removeCallback(proxy); + + processAllOverlappingPairs(&removeCallback,dispatcher); +} + + + + + +btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) +{ + gFindPairs++; + if(proxy0->m_uniqueId>proxy1->m_uniqueId) + btSwap(proxy0,proxy1); + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + + /*if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2);*/ + + int hash = static_cast(getHash(static_cast(proxyId1), static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); + + if (hash >= m_hashTable.size()) + { + return NULL; + } + + int index = m_hashTable[hash]; + while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) + { + index = m_next[index]; + } + + if (index == BT_NULL_PAIR) + { + return NULL; + } + + btAssert(index < m_overlappingPairArray.size()); + + return &m_overlappingPairArray[index]; +} + +//#include + +void btHashedOverlappingPairCache::growTables() +{ + + int newCapacity = m_overlappingPairArray.capacity(); + + if (m_hashTable.size() < newCapacity) + { + //grow hashtable and next table + int curHashtableSize = m_hashTable.size(); + + m_hashTable.resize(newCapacity); + m_next.resize(newCapacity); + + + int i; + + for (i= 0; i < newCapacity; ++i) + { + m_hashTable[i] = BT_NULL_PAIR; + } + for (i = 0; i < newCapacity; ++i) + { + m_next[i] = BT_NULL_PAIR; + } + + for(i=0;igetUid(); + int proxyId2 = pair.m_pProxy1->getUid(); + /*if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2);*/ + int hashValue = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask + m_next[i] = m_hashTable[hashValue]; + m_hashTable[hashValue] = i; + } + + + } +} + +btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) +{ + if(proxy0->m_uniqueId>proxy1->m_uniqueId) + btSwap(proxy0,proxy1); + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + + /*if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2);*/ + + int hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask + + + btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash); + if (pair != NULL) + { + return pair; + } + /*for(int i=0;i%u\r\n",proxyId1,proxyId2); + internalFindPair(proxy0, proxy1, hash); + } + }*/ + int count = m_overlappingPairArray.size(); + int oldCapacity = m_overlappingPairArray.capacity(); + void* mem = &m_overlappingPairArray.expandNonInitializing(); + + //this is where we add an actual pair, so also call the 'ghost' + if (m_ghostPairCallback) + m_ghostPairCallback->addOverlappingPair(proxy0,proxy1); + + int newCapacity = m_overlappingPairArray.capacity(); + + if (oldCapacity < newCapacity) + { + growTables(); + //hash with new capacity + hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); + } + + pair = new (mem) btBroadphasePair(*proxy0,*proxy1); +// pair->m_pProxy0 = proxy0; +// pair->m_pProxy1 = proxy1; + pair->m_algorithm = 0; + pair->m_internalTmpValue = 0; + + + m_next[count] = m_hashTable[hash]; + m_hashTable[hash] = count; + + return pair; +} + + + +void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher) +{ + gRemovePairs++; + if(proxy0->m_uniqueId>proxy1->m_uniqueId) + btSwap(proxy0,proxy1); + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + + /*if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2);*/ + + int hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); + + btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash); + if (pair == NULL) + { + return 0; + } + + cleanOverlappingPair(*pair,dispatcher); + + void* userData = pair->m_internalInfo1; + + btAssert(pair->m_pProxy0->getUid() == proxyId1); + btAssert(pair->m_pProxy1->getUid() == proxyId2); + + int pairIndex = int(pair - &m_overlappingPairArray[0]); + btAssert(pairIndex < m_overlappingPairArray.size()); + + // Remove the pair from the hash table. + int index = m_hashTable[hash]; + btAssert(index != BT_NULL_PAIR); + + int previous = BT_NULL_PAIR; + while (index != pairIndex) + { + previous = index; + index = m_next[index]; + } + + if (previous != BT_NULL_PAIR) + { + btAssert(m_next[previous] == pairIndex); + m_next[previous] = m_next[pairIndex]; + } + else + { + m_hashTable[hash] = m_next[pairIndex]; + } + + // We now move the last pair into spot of the + // pair being removed. We need to fix the hash + // table indices to support the move. + + int lastPairIndex = m_overlappingPairArray.size() - 1; + + if (m_ghostPairCallback) + m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher); + + // If the removed pair is the last pair, we are done. + if (lastPairIndex == pairIndex) + { + m_overlappingPairArray.pop_back(); + return userData; + } + + // Remove the last pair from the hash table. + const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex]; + /* missing swap here too, Nat. */ + int lastHash = static_cast(getHash(static_cast(last->m_pProxy0->getUid()), static_cast(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity()-1)); + + index = m_hashTable[lastHash]; + btAssert(index != BT_NULL_PAIR); + + previous = BT_NULL_PAIR; + while (index != lastPairIndex) + { + previous = index; + index = m_next[index]; + } + + if (previous != BT_NULL_PAIR) + { + btAssert(m_next[previous] == lastPairIndex); + m_next[previous] = m_next[lastPairIndex]; + } + else + { + m_hashTable[lastHash] = m_next[lastPairIndex]; + } + + // Copy the last pair into the remove pair's spot. + m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex]; + + // Insert the last pair into the hash table + m_next[pairIndex] = m_hashTable[lastHash]; + m_hashTable[lastHash] = pairIndex; + + m_overlappingPairArray.pop_back(); + + return userData; +} +//#include + +void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) +{ + + int i; + +// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size()); + for (i=0;iprocessOverlap(*pair)) + { + removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher); + + gOverlappingPairs--; + } else + { + i++; + } + } +} + +void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher) +{ + ///need to keep hashmap in sync with pair address, so rebuild all + btBroadphasePairArray tmpPairs; + int i; + for (i=0;iremoveOverlappingPair(proxy0, proxy1,dispatcher); + + m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1); + m_overlappingPairArray.pop_back(); + return userData; + } + } + + return 0; +} + + + + + + + + +btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + //don't add overlap with own + btAssert(proxy0 != proxy1); + + if (!needsBroadphaseCollision(proxy0,proxy1)) + return 0; + + void* mem = &m_overlappingPairArray.expandNonInitializing(); + btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1); + + gOverlappingPairs++; + gAddedPairs++; + + if (m_ghostPairCallback) + m_ghostPairCallback->addOverlappingPair(proxy0, proxy1); + return pair; + +} + +///this findPair becomes really slow. Either sort the list to speedup the query, or +///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed. +///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address) +///Also we can use a 2D bitmap, which can be useful for a future GPU implementation + btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + if (!needsBroadphaseCollision(proxy0,proxy1)) + return 0; + + btBroadphasePair tmpPair(*proxy0,*proxy1); + int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair); + + if (findIndex < m_overlappingPairArray.size()) + { + //btAssert(it != m_overlappingPairSet.end()); + btBroadphasePair* pair = &m_overlappingPairArray[findIndex]; + return pair; + } + return 0; +} + + + + + + + + + + +//#include + +void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) +{ + + int i; + + for (i=0;iprocessOverlap(*pair)) + { + cleanOverlappingPair(*pair,dispatcher); + pair->m_pProxy0 = 0; + pair->m_pProxy1 = 0; + m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + m_overlappingPairArray.pop_back(); + gOverlappingPairs--; + } else + { + i++; + } + } +} + + + + +btSortedOverlappingPairCache::btSortedOverlappingPairCache(): + m_blockedForChanges(false), + m_hasDeferredRemoval(true), + m_overlapFilterCallback(0), + m_ghostPairCallback(0) +{ + int initialAllocatedSize= 2; + m_overlappingPairArray.reserve(initialAllocatedSize); +} + +btSortedOverlappingPairCache::~btSortedOverlappingPairCache() +{ +} + +void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) +{ + if (pair.m_algorithm) + { + { + pair.m_algorithm->~btCollisionAlgorithm(); + dispatcher->freeCollisionAlgorithm(pair.m_algorithm); + pair.m_algorithm=0; + gRemovePairs--; + } + } +} + + +void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + + class CleanPairCallback : public btOverlapCallback + { + btBroadphaseProxy* m_cleanProxy; + btOverlappingPairCache* m_pairCache; + btDispatcher* m_dispatcher; + + public: + CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) + :m_cleanProxy(cleanProxy), + m_pairCache(pairCache), + m_dispatcher(dispatcher) + { + } + virtual bool processOverlap(btBroadphasePair& pair) + { + if ((pair.m_pProxy0 == m_cleanProxy) || + (pair.m_pProxy1 == m_cleanProxy)) + { + m_pairCache->cleanOverlappingPair(pair,m_dispatcher); + } + return false; + } + + }; + + CleanPairCallback cleanPairs(proxy,this,dispatcher); + + processAllOverlappingPairs(&cleanPairs,dispatcher); + +} + + +void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + + class RemovePairCallback : public btOverlapCallback + { + btBroadphaseProxy* m_obsoleteProxy; + + public: + RemovePairCallback(btBroadphaseProxy* obsoleteProxy) + :m_obsoleteProxy(obsoleteProxy) + { + } + virtual bool processOverlap(btBroadphasePair& pair) + { + return ((pair.m_pProxy0 == m_obsoleteProxy) || + (pair.m_pProxy1 == m_obsoleteProxy)); + } + + }; + + RemovePairCallback removeCallback(proxy); + + processAllOverlappingPairs(&removeCallback,dispatcher); +} + +void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher) +{ + //should already be sorted +} + diff --git a/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h new file mode 100644 index 0000000..7a3806c --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h @@ -0,0 +1,469 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_OVERLAPPING_PAIR_CACHE_H +#define BT_OVERLAPPING_PAIR_CACHE_H + + +#include "btBroadphaseInterface.h" +#include "btBroadphaseProxy.h" +#include "btOverlappingPairCallback.h" + +#include "LinearMath/btAlignedObjectArray.h" +class btDispatcher; + +typedef btAlignedObjectArray btBroadphasePairArray; + +struct btOverlapCallback +{ + virtual ~btOverlapCallback() + {} + //return true for deletion of the pair + virtual bool processOverlap(btBroadphasePair& pair) = 0; + +}; + +struct btOverlapFilterCallback +{ + virtual ~btOverlapFilterCallback() + {} + // return true when pairs need collision + virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0; +}; + + + + + + + +extern int gRemovePairs; +extern int gAddedPairs; +extern int gFindPairs; + +const int BT_NULL_PAIR=0xffffffff; + +///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases. +///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations. +class btOverlappingPairCache : public btOverlappingPairCallback +{ +public: + virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor + + virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0; + + virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0; + + virtual btBroadphasePairArray& getOverlappingPairArray() = 0; + + virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0; + + virtual int getNumOverlappingPairs() const = 0; + + virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0; + + virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0; + + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0; + + virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0; + + virtual bool hasDeferredRemoval() = 0; + + virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0; + + virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0; + + +}; + +/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com +class btHashedOverlappingPairCache : public btOverlappingPairCache +{ + btBroadphasePairArray m_overlappingPairArray; + btOverlapFilterCallback* m_overlapFilterCallback; + bool m_blockedForChanges; + + +public: + btHashedOverlappingPairCache(); + virtual ~btHashedOverlappingPairCache(); + + + void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + + virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); + + SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const + { + if (m_overlapFilterCallback) + return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1); + + bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; + collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); + + return collides; + } + + // Add a pair and return the new pair. If the pair already exists, + // no new pair is created and the old one is returned. + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) + { + gAddedPairs++; + + if (!needsBroadphaseCollision(proxy0,proxy1)) + return 0; + + return internalAddPair(proxy0,proxy1); + } + + + + void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + + + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); + + virtual btBroadphasePair* getOverlappingPairArrayPtr() + { + return &m_overlappingPairArray[0]; + } + + const btBroadphasePair* getOverlappingPairArrayPtr() const + { + return &m_overlappingPairArray[0]; + } + + btBroadphasePairArray& getOverlappingPairArray() + { + return m_overlappingPairArray; + } + + const btBroadphasePairArray& getOverlappingPairArray() const + { + return m_overlappingPairArray; + } + + void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); + + + + btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1); + + int GetCount() const { return m_overlappingPairArray.size(); } +// btBroadphasePair* GetPairs() { return m_pairs; } + + btOverlapFilterCallback* getOverlapFilterCallback() + { + return m_overlapFilterCallback; + } + + void setOverlapFilterCallback(btOverlapFilterCallback* callback) + { + m_overlapFilterCallback = callback; + } + + int getNumOverlappingPairs() const + { + return m_overlappingPairArray.size(); + } +private: + + btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + void growTables(); + + SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2) + { + return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2; + } + + /* + // Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm + // This assumes proxyId1 and proxyId2 are 16-bit. + SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2) + { + int key = (proxyId2 << 16) | proxyId1; + key = ~key + (key << 15); + key = key ^ (key >> 12); + key = key + (key << 2); + key = key ^ (key >> 4); + key = key * 2057; + key = key ^ (key >> 16); + return key; + } + */ + + + + SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2) + { + int key = static_cast(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16)); + // Thomas Wang's hash + + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return static_cast(key); + } + + + + + + SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash) + { + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + #if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat. + if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2); + #endif + + int index = m_hashTable[hash]; + + while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) + { + index = m_next[index]; + } + + if ( index == BT_NULL_PAIR ) + { + return NULL; + } + + btAssert(index < m_overlappingPairArray.size()); + + return &m_overlappingPairArray[index]; + } + + virtual bool hasDeferredRemoval() + { + return false; + } + + virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) + { + m_ghostPairCallback = ghostPairCallback; + } + + virtual void sortOverlappingPairs(btDispatcher* dispatcher); + + +protected: + + btAlignedObjectArray m_hashTable; + btAlignedObjectArray m_next; + btOverlappingPairCallback* m_ghostPairCallback; + +}; + + + + +///btSortedOverlappingPairCache maintains the objects with overlapping AABB +///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase +class btSortedOverlappingPairCache : public btOverlappingPairCache +{ + protected: + //avoid brute-force finding all the time + btBroadphasePairArray m_overlappingPairArray; + + //during the dispatch, check that user doesn't destroy/create proxy + bool m_blockedForChanges; + + ///by default, do the removal during the pair traversal + bool m_hasDeferredRemoval; + + //if set, use the callback instead of the built in filter in needBroadphaseCollision + btOverlapFilterCallback* m_overlapFilterCallback; + + btOverlappingPairCallback* m_ghostPairCallback; + + public: + + btSortedOverlappingPairCache(); + virtual ~btSortedOverlappingPairCache(); + + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); + + void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); + + void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); + + btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + + void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + + void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + + + inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const + { + if (m_overlapFilterCallback) + return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1); + + bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; + collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); + + return collides; + } + + btBroadphasePairArray& getOverlappingPairArray() + { + return m_overlappingPairArray; + } + + const btBroadphasePairArray& getOverlappingPairArray() const + { + return m_overlappingPairArray; + } + + + + + btBroadphasePair* getOverlappingPairArrayPtr() + { + return &m_overlappingPairArray[0]; + } + + const btBroadphasePair* getOverlappingPairArrayPtr() const + { + return &m_overlappingPairArray[0]; + } + + int getNumOverlappingPairs() const + { + return m_overlappingPairArray.size(); + } + + btOverlapFilterCallback* getOverlapFilterCallback() + { + return m_overlapFilterCallback; + } + + void setOverlapFilterCallback(btOverlapFilterCallback* callback) + { + m_overlapFilterCallback = callback; + } + + virtual bool hasDeferredRemoval() + { + return m_hasDeferredRemoval; + } + + virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) + { + m_ghostPairCallback = ghostPairCallback; + } + + virtual void sortOverlappingPairs(btDispatcher* dispatcher); + + +}; + + + +///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing. +class btNullPairCache : public btOverlappingPairCache +{ + + btBroadphasePairArray m_overlappingPairArray; + +public: + + virtual btBroadphasePair* getOverlappingPairArrayPtr() + { + return &m_overlappingPairArray[0]; + } + const btBroadphasePair* getOverlappingPairArrayPtr() const + { + return &m_overlappingPairArray[0]; + } + btBroadphasePairArray& getOverlappingPairArray() + { + return m_overlappingPairArray; + } + + virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/) + { + + } + + virtual int getNumOverlappingPairs() const + { + return 0; + } + + virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/) + { + + } + + virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/) + { + } + + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/) + { + } + + virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/) + { + return 0; + } + + virtual bool hasDeferredRemoval() + { + return true; + } + + virtual void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */) + { + + } + + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/) + { + return 0; + } + + virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/) + { + return 0; + } + + virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/) + { + } + + virtual void sortOverlappingPairs(btDispatcher* dispatcher) + { + (void) dispatcher; + } + + +}; + + +#endif //BT_OVERLAPPING_PAIR_CACHE_H + + diff --git a/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h new file mode 100644 index 0000000..9c7b6f8 --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h @@ -0,0 +1,40 @@ + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef OVERLAPPING_PAIR_CALLBACK_H +#define OVERLAPPING_PAIR_CALLBACK_H + +class btDispatcher; +struct btBroadphasePair; + +///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache. +class btOverlappingPairCallback +{ +public: + virtual ~btOverlappingPairCallback() + { + + } + + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0; + + virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0; + + virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0; + +}; + +#endif //OVERLAPPING_PAIR_CALLBACK_H diff --git a/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp new file mode 100644 index 0000000..c911435 --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp @@ -0,0 +1,1375 @@ +/* +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 "btQuantizedBvh.h" + +#include "LinearMath/btAabbUtil2.h" +#include "LinearMath/btIDebugDraw.h" +#include "LinearMath/btSerializer.h" + +#define RAYAABB2 + +btQuantizedBvh::btQuantizedBvh() : + m_bulletVersion(BT_BULLET_VERSION), + m_useQuantization(false), + //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY) + m_traversalMode(TRAVERSAL_STACKLESS) + //m_traversalMode(TRAVERSAL_RECURSIVE) + ,m_subtreeHeaderCount(0) //PCK: add this line +{ + m_bvhAabbMin.setValue(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY); + m_bvhAabbMax.setValue(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY); +} + + + + + +void btQuantizedBvh::buildInternal() +{ + ///assumes that caller filled in the m_quantizedLeafNodes + m_useQuantization = true; + int numLeafNodes = 0; + + if (m_useQuantization) + { + //now we have an array of leafnodes in m_leafNodes + numLeafNodes = m_quantizedLeafNodes.size(); + + m_quantizedContiguousNodes.resize(2*numLeafNodes); + + } + + m_curNodeIndex = 0; + + buildTree(0,numLeafNodes); + + ///if the entire tree is small then subtree size, we need to create a header info for the tree + if(m_useQuantization && !m_SubtreeHeaders.size()) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]); + subtree.m_rootNodeIndex = 0; + subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex(); + } + + //PCK: update the copy of the size + m_subtreeHeaderCount = m_SubtreeHeaders.size(); + + //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary + m_quantizedLeafNodes.clear(); + m_leafNodes.clear(); +} + + + +///just for debugging, to visualize the individual patches/subtrees +#ifdef DEBUG_PATCH_COLORS +btVector3 color[4]= +{ + btVector3(1,0,0), + btVector3(0,1,0), + btVector3(0,0,1), + btVector3(0,1,1) +}; +#endif //DEBUG_PATCH_COLORS + + + +void btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin) +{ + //enlarge the AABB to avoid division by zero when initializing the quantization values + btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin); + m_bvhAabbMin = bvhAabbMin - clampValue; + m_bvhAabbMax = bvhAabbMax + clampValue; + btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin; + m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize; + m_useQuantization = true; +} + + + + +btQuantizedBvh::~btQuantizedBvh() +{ +} + +#ifdef DEBUG_TREE_BUILDING +int gStackDepth = 0; +int gMaxStackDepth = 0; +#endif //DEBUG_TREE_BUILDING + +void btQuantizedBvh::buildTree (int startIndex,int endIndex) +{ +#ifdef DEBUG_TREE_BUILDING + gStackDepth++; + if (gStackDepth > gMaxStackDepth) + gMaxStackDepth = gStackDepth; +#endif //DEBUG_TREE_BUILDING + + + int splitAxis, splitIndex, i; + int numIndices =endIndex-startIndex; + int curIndex = m_curNodeIndex; + + btAssert(numIndices>0); + + if (numIndices==1) + { +#ifdef DEBUG_TREE_BUILDING + gStackDepth--; +#endif //DEBUG_TREE_BUILDING + + assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex); + + m_curNodeIndex++; + return; + } + //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. + + splitAxis = calcSplittingAxis(startIndex,endIndex); + + splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis); + + int internalNodeIndex = m_curNodeIndex; + + //set the min aabb to 'inf' or a max value, and set the max aabb to a -inf/minimum value. + //the aabb will be expanded during buildTree/mergeInternalNodeAabb with actual node values + setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax);//can't use btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY)) because of quantization + setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin);//can't use btVector3(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY)) because of quantization + + + for (i=startIndex;im_escapeIndex; + + int leftChildNodexIndex = m_curNodeIndex; + + //build left child tree + buildTree(startIndex,splitIndex); + + int rightChildNodexIndex = m_curNodeIndex; + //build right child tree + buildTree(splitIndex,endIndex); + +#ifdef DEBUG_TREE_BUILDING + gStackDepth--; +#endif //DEBUG_TREE_BUILDING + + int escapeIndex = m_curNodeIndex - curIndex; + + if (m_useQuantization) + { + //escapeIndex is the number of nodes of this subtree + const int sizeQuantizedNode =sizeof(btQuantizedBvhNode); + const int treeSizeInBytes = escapeIndex * sizeQuantizedNode; + if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES) + { + updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex); + } + } else + { + + } + + setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex); + +} + +void btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex) +{ + btAssert(m_useQuantization); + + btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex]; + int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex(); + int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast(sizeof(btQuantizedBvhNode)); + + btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex]; + int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex(); + int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast(sizeof(btQuantizedBvhNode)); + + if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(leftChildNode); + subtree.m_rootNodeIndex = leftChildNodexIndex; + subtree.m_subtreeSize = leftSubTreeSize; + } + + if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(rightChildNode); + subtree.m_rootNodeIndex = rightChildNodexIndex; + subtree.m_subtreeSize = rightSubTreeSize; + } + + //PCK: update the copy of the size + m_subtreeHeaderCount = m_SubtreeHeaders.size(); +} + + +int btQuantizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis) +{ + int i; + int splitIndex =startIndex; + int numIndices = endIndex - startIndex; + btScalar splitValue; + + btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); + for (i=startIndex;i splitValue) + { + //swap + swapLeafNodes(i,splitIndex); + splitIndex++; + } + } + + //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex + //otherwise the tree-building might fail due to stack-overflows in certain cases. + //unbalanced1 is unsafe: it can cause stack overflows + //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); + + //unbalanced2 should work too: always use center (perfect balanced trees) + //bool unbalanced2 = true; + + //this should be safe too: + int rangeBalancedIndices = numIndices/3; + bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); + + if (unbalanced) + { + splitIndex = startIndex+ (numIndices>>1); + } + + bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); + (void)unbal; + btAssert(!unbal); + + return splitIndex; +} + + +int btQuantizedBvh::calcSplittingAxis(int startIndex,int endIndex) +{ + int i; + + btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); + btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.)); + int numIndices = endIndex-startIndex; + + for (i=startIndex;im_aabbMinOrg,rootNode->m_aabbMaxOrg); + isLeafNode = rootNode->m_escapeIndex == -1; + + //PCK: unsigned instead of bool + if (isLeafNode && (aabbOverlap != 0)) + { + nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex); + } + + //PCK: unsigned instead of bool + if ((aabbOverlap != 0) || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->m_escapeIndex; + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + +/* +///this was the original recursive traversal, before we optimized towards stackless traversal +void btQuantizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax); + if (aabbOverlap) + { + isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild); + if (isLeafNode) + { + nodeCallback->processNode(rootNode); + } else + { + walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax); + walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax); + } + } + +} +*/ + +void btQuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const +{ + btAssert(m_useQuantization); + + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned aabbOverlap; + + //PCK: unsigned instead of bool + aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax); + isLeafNode = currentNode->isLeafNode(); + + //PCK: unsigned instead of bool + if (aabbOverlap != 0) + { + if (isLeafNode) + { + nodeCallback->processNode(currentNode->getPartId(),currentNode->getTriangleIndex()); + } else + { + //process left and right children + const btQuantizedBvhNode* leftChildNode = currentNode+1; + walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); + + const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex(); + walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); + } + } +} + + + +void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const +{ + btAssert(!m_useQuantization); + + const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0]; + int escapeIndex, curIndex = 0; + int walkIterations = 0; + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned aabbOverlap=0; + unsigned rayBoxOverlap=0; + btScalar lambda_max = 1.0; + + /* Quick pruning by quantized box */ + btVector3 rayAabbMin = raySource; + btVector3 rayAabbMax = raySource; + rayAabbMin.setMin(rayTarget); + rayAabbMax.setMax(rayTarget); + + /* Add box cast extents to bounding box */ + rayAabbMin += aabbMin; + rayAabbMax += aabbMax; + +#ifdef RAYAABB2 + btVector3 rayDir = (rayTarget-raySource); + rayDir.normalize (); + lambda_max = rayDir.dot(rayTarget-raySource); + ///what about division by zero? --> just set rayDirection[i] to 1.0 + btVector3 rayDirectionInverse; + rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0]; + rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1]; + rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2]; + unsigned int sign[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0}; +#endif + + btVector3 bounds[2]; + + while (curIndex < m_curNodeIndex) + { + btScalar param = 1.0; + //catch bugs in tree data + btAssert (walkIterations < m_curNodeIndex); + + walkIterations++; + + bounds[0] = rootNode->m_aabbMinOrg; + bounds[1] = rootNode->m_aabbMaxOrg; + /* Add box cast extents */ + bounds[0] -= aabbMax; + bounds[1] -= aabbMin; + + aabbOverlap = TestAabbAgainstAabb2(rayAabbMin,rayAabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg); + //perhaps profile if it is worth doing the aabbOverlap test first + +#ifdef RAYAABB2 + ///careful with this check: need to check division by zero (above) and fix the unQuantize method + ///thanks Joerg/hiker for the reproduction case! + ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858 + rayBoxOverlap = aabbOverlap ? btRayAabb2 (raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false; + +#else + btVector3 normal; + rayBoxOverlap = btRayAabb(raySource, rayTarget,bounds[0],bounds[1],param, normal); +#endif + + isLeafNode = rootNode->m_escapeIndex == -1; + + //PCK: unsigned instead of bool + if (isLeafNode && (rayBoxOverlap != 0)) + { + nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex); + } + + //PCK: unsigned instead of bool + if ((rayBoxOverlap != 0) || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->m_escapeIndex; + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + + + +void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const +{ + btAssert(m_useQuantization); + + int curIndex = startNodeIndex; + int walkIterations = 0; + int subTreeSize = endNodeIndex - startNodeIndex; + (void)subTreeSize; + + const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex]; + int escapeIndex; + + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned boxBoxOverlap = 0; + unsigned rayBoxOverlap = 0; + + btScalar lambda_max = 1.0; + +#ifdef RAYAABB2 + btVector3 rayDirection = (rayTarget-raySource); + rayDirection.normalize (); + lambda_max = rayDirection.dot(rayTarget-raySource); + ///what about division by zero? --> just set rayDirection[i] to 1.0 + rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[0]; + rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[1]; + rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[2]; + unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0}; +#endif + + /* Quick pruning by quantized box */ + btVector3 rayAabbMin = raySource; + btVector3 rayAabbMax = raySource; + rayAabbMin.setMin(rayTarget); + rayAabbMax.setMax(rayTarget); + + /* Add box cast extents to bounding box */ + rayAabbMin += aabbMin; + rayAabbMax += aabbMax; + + unsigned short int quantizedQueryAabbMin[3]; + unsigned short int quantizedQueryAabbMax[3]; + quantizeWithClamp(quantizedQueryAabbMin,rayAabbMin,0); + quantizeWithClamp(quantizedQueryAabbMax,rayAabbMax,1); + + while (curIndex < endNodeIndex) + { + +//#define VISUALLY_ANALYZE_BVH 1 +#ifdef VISUALLY_ANALYZE_BVH + //some code snippet to debugDraw aabb, to visually analyze bvh structure + static int drawPatch = 0; + //need some global access to a debugDrawer + extern btIDebugDraw* debugDrawerPtr; + if (curIndex==drawPatch) + { + btVector3 aabbMin,aabbMax; + aabbMin = unQuantize(rootNode->m_quantizedAabbMin); + aabbMax = unQuantize(rootNode->m_quantizedAabbMax); + btVector3 color(1,0,0); + debugDrawerPtr->drawAabb(aabbMin,aabbMax,color); + } +#endif//VISUALLY_ANALYZE_BVH + + //catch bugs in tree data + btAssert (walkIterations < subTreeSize); + + walkIterations++; + //PCK: unsigned instead of bool + // only interested if this is closer than any previous hit + btScalar param = 1.0; + rayBoxOverlap = 0; + boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); + isLeafNode = rootNode->isLeafNode(); + if (boxBoxOverlap) + { + btVector3 bounds[2]; + bounds[0] = unQuantize(rootNode->m_quantizedAabbMin); + bounds[1] = unQuantize(rootNode->m_quantizedAabbMax); + /* Add box cast extents */ + bounds[0] -= aabbMax; + bounds[1] -= aabbMin; + btVector3 normal; +#if 0 + bool ra2 = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max); + bool ra = btRayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal); + if (ra2 != ra) + { + printf("functions don't match\n"); + } +#endif +#ifdef RAYAABB2 + ///careful with this check: need to check division by zero (above) and fix the unQuantize method + ///thanks Joerg/hiker for the reproduction case! + ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858 + + //BT_PROFILE("btRayAabb2"); + rayBoxOverlap = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max); + +#else + rayBoxOverlap = true;//btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal); +#endif + } + + if (isLeafNode && rayBoxOverlap) + { + nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex()); + } + + //PCK: unsigned instead of bool + if ((rayBoxOverlap != 0) || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->getEscapeIndex(); + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + +void btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const +{ + btAssert(m_useQuantization); + + int curIndex = startNodeIndex; + int walkIterations = 0; + int subTreeSize = endNodeIndex - startNodeIndex; + (void)subTreeSize; + + const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex]; + int escapeIndex; + + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned aabbOverlap; + + while (curIndex < endNodeIndex) + { + +//#define VISUALLY_ANALYZE_BVH 1 +#ifdef VISUALLY_ANALYZE_BVH + //some code snippet to debugDraw aabb, to visually analyze bvh structure + static int drawPatch = 0; + //need some global access to a debugDrawer + extern btIDebugDraw* debugDrawerPtr; + if (curIndex==drawPatch) + { + btVector3 aabbMin,aabbMax; + aabbMin = unQuantize(rootNode->m_quantizedAabbMin); + aabbMax = unQuantize(rootNode->m_quantizedAabbMax); + btVector3 color(1,0,0); + debugDrawerPtr->drawAabb(aabbMin,aabbMax,color); + } +#endif//VISUALLY_ANALYZE_BVH + + //catch bugs in tree data + btAssert (walkIterations < subTreeSize); + + walkIterations++; + //PCK: unsigned instead of bool + aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); + isLeafNode = rootNode->isLeafNode(); + + if (isLeafNode && aabbOverlap) + { + nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex()); + } + + //PCK: unsigned instead of bool + if ((aabbOverlap != 0) || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->getEscapeIndex(); + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + +//This traversal can be called from Playstation 3 SPU +void btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const +{ + btAssert(m_useQuantization); + + int i; + + + for (i=0;im_SubtreeHeaders.size();i++) + { + const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; + + //PCK: unsigned instead of bool + unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); + if (overlap != 0) + { + walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax, + subtree.m_rootNodeIndex, + subtree.m_rootNodeIndex+subtree.m_subtreeSize); + } + } +} + + +void btQuantizedBvh::reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const +{ + reportBoxCastOverlappingNodex(nodeCallback,raySource,rayTarget,btVector3(0,0,0),btVector3(0,0,0)); +} + + +void btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const +{ + //always use stackless + + if (m_useQuantization) + { + walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex); + } + else + { + walkStacklessTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex); + } + /* + { + //recursive traversal + btVector3 qaabbMin = raySource; + btVector3 qaabbMax = raySource; + qaabbMin.setMin(rayTarget); + qaabbMax.setMax(rayTarget); + qaabbMin += aabbMin; + qaabbMax += aabbMax; + reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax); + } + */ + +} + + +void btQuantizedBvh::swapLeafNodes(int i,int splitIndex) +{ + if (m_useQuantization) + { + btQuantizedBvhNode tmp = m_quantizedLeafNodes[i]; + m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex]; + m_quantizedLeafNodes[splitIndex] = tmp; + } else + { + btOptimizedBvhNode tmp = m_leafNodes[i]; + m_leafNodes[i] = m_leafNodes[splitIndex]; + m_leafNodes[splitIndex] = tmp; + } +} + +void btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex) +{ + if (m_useQuantization) + { + m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex]; + } else + { + m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex]; + } +} + +//PCK: include +#include + +#if 0 +//PCK: consts +static const unsigned BVH_ALIGNMENT = 16; +static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1; + +static const unsigned BVH_ALIGNMENT_BLOCKS = 2; +#endif + + +unsigned int btQuantizedBvh::getAlignmentSerializationPadding() +{ + // I changed this to 0 since the extra padding is not needed or used. + return 0;//BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT; +} + +unsigned btQuantizedBvh::calculateSerializeBufferSize() const +{ + unsigned baseSize = sizeof(btQuantizedBvh) + getAlignmentSerializationPadding(); + baseSize += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount; + if (m_useQuantization) + { + return baseSize + m_curNodeIndex * sizeof(btQuantizedBvhNode); + } + return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode); +} + +bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) const +{ + btAssert(m_subtreeHeaderCount == m_SubtreeHeaders.size()); + m_subtreeHeaderCount = m_SubtreeHeaders.size(); + +/* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0)) + { + ///check alignedment for buffer? + btAssert(0); + return false; + } +*/ + + btQuantizedBvh *targetBvh = (btQuantizedBvh *)o_alignedDataBuffer; + + // construct the class so the virtual function table, etc will be set up + // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor + new (targetBvh) btQuantizedBvh; + + if (i_swapEndian) + { + targetBvh->m_curNodeIndex = static_cast(btSwapEndian(m_curNodeIndex)); + + + btSwapVector3Endian(m_bvhAabbMin,targetBvh->m_bvhAabbMin); + btSwapVector3Endian(m_bvhAabbMax,targetBvh->m_bvhAabbMax); + btSwapVector3Endian(m_bvhQuantization,targetBvh->m_bvhQuantization); + + targetBvh->m_traversalMode = (btTraversalMode)btSwapEndian(m_traversalMode); + targetBvh->m_subtreeHeaderCount = static_cast(btSwapEndian(m_subtreeHeaderCount)); + } + else + { + targetBvh->m_curNodeIndex = m_curNodeIndex; + targetBvh->m_bvhAabbMin = m_bvhAabbMin; + targetBvh->m_bvhAabbMax = m_bvhAabbMax; + targetBvh->m_bvhQuantization = m_bvhQuantization; + targetBvh->m_traversalMode = m_traversalMode; + targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount; + } + + targetBvh->m_useQuantization = m_useQuantization; + + unsigned char *nodeData = (unsigned char *)targetBvh; + nodeData += sizeof(btQuantizedBvh); + + unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + int nodeCount = m_curNodeIndex; + + if (m_useQuantization) + { + targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]); + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]); + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast(btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex)); + } + } + else + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]; + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]; + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex; + + + } + } + nodeData += sizeof(btQuantizedBvhNode) * nodeCount; + + // this clears the pointer in the member variable it doesn't really do anything to the data + // it does call the destructor on the contained objects, but they are all classes with no destructor defined + // so the memory (which is not freed) is left alone + targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(NULL, 0, 0); + } + else + { + targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg); + btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg); + + targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex)); + targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_subPart)); + targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex)); + } + } + else + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg; + targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg; + + targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex; + targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart; + targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex; + } + } + nodeData += sizeof(btOptimizedBvhNode) * nodeCount; + + // this clears the pointer in the member variable it doesn't really do anything to the data + // it does call the destructor on the contained objects, but they are all classes with no destructor defined + // so the memory (which is not freed) is left alone + targetBvh->m_contiguousNodes.initializeFromBuffer(NULL, 0, 0); + } + + sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + // Now serialize the subtree headers + targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount); + if (i_swapEndian) + { + for (int i = 0; i < m_subtreeHeaderCount; i++) + { + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]); + + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]); + + targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast(btSwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex)); + targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast(btSwapEndian(m_SubtreeHeaders[i].m_subtreeSize)); + } + } + else + { + for (int i = 0; i < m_subtreeHeaderCount; i++) + { + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]); + + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]); + + targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex); + targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize); + + // need to clear padding in destination buffer + targetBvh->m_SubtreeHeaders[i].m_padding[0] = 0; + targetBvh->m_SubtreeHeaders[i].m_padding[1] = 0; + targetBvh->m_SubtreeHeaders[i].m_padding[2] = 0; + } + } + nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount; + + // this clears the pointer in the member variable it doesn't really do anything to the data + // it does call the destructor on the contained objects, but they are all classes with no destructor defined + // so the memory (which is not freed) is left alone + targetBvh->m_SubtreeHeaders.initializeFromBuffer(NULL, 0, 0); + + // this wipes the virtual function table pointer at the start of the buffer for the class + *((void**)o_alignedDataBuffer) = NULL; + + return true; +} + +btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian) +{ + + if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0)) + { + return NULL; + } + btQuantizedBvh *bvh = (btQuantizedBvh *)i_alignedDataBuffer; + + if (i_swapEndian) + { + bvh->m_curNodeIndex = static_cast(btSwapEndian(bvh->m_curNodeIndex)); + + btUnSwapVector3Endian(bvh->m_bvhAabbMin); + btUnSwapVector3Endian(bvh->m_bvhAabbMax); + btUnSwapVector3Endian(bvh->m_bvhQuantization); + + bvh->m_traversalMode = (btTraversalMode)btSwapEndian(bvh->m_traversalMode); + bvh->m_subtreeHeaderCount = static_cast(btSwapEndian(bvh->m_subtreeHeaderCount)); + } + + unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize(); + btAssert(calculatedBufSize <= i_dataBufferSize); + + if (calculatedBufSize > i_dataBufferSize) + { + return NULL; + } + + unsigned char *nodeData = (unsigned char *)bvh; + nodeData += sizeof(btQuantizedBvh); + + unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + int nodeCount = bvh->m_curNodeIndex; + + // Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor + // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor + new (bvh) btQuantizedBvh(*bvh, false); + + if (bvh->m_useQuantization) + { + bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]); + + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]); + + bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast(btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex)); + } + } + nodeData += sizeof(btQuantizedBvhNode) * nodeCount; + } + else + { + bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg); + btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg); + + bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex)); + bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart)); + bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex)); + } + } + nodeData += sizeof(btOptimizedBvhNode) * nodeCount; + } + + sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + // Now serialize the subtree headers + bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount); + if (i_swapEndian) + { + for (int i = 0; i < bvh->m_subtreeHeaderCount; i++) + { + bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]); + + bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]); + + bvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast(btSwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex)); + bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast(btSwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize)); + } + } + + return bvh; +} + +// Constructor that prevents btVector3's default constructor from being called +btQuantizedBvh::btQuantizedBvh(btQuantizedBvh &self, bool /* ownsMemory */) : +m_bvhAabbMin(self.m_bvhAabbMin), +m_bvhAabbMax(self.m_bvhAabbMax), +m_bvhQuantization(self.m_bvhQuantization), +m_bulletVersion(BT_BULLET_VERSION) +{ + +} + +void btQuantizedBvh::deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData) +{ + m_bvhAabbMax.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMax); + m_bvhAabbMin.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMin); + m_bvhQuantization.deSerializeFloat(quantizedBvhFloatData.m_bvhQuantization); + + m_curNodeIndex = quantizedBvhFloatData.m_curNodeIndex; + m_useQuantization = quantizedBvhFloatData.m_useQuantization!=0; + + { + int numElem = quantizedBvhFloatData.m_numContiguousLeafNodes; + m_contiguousNodes.resize(numElem); + + if (numElem) + { + btOptimizedBvhNodeFloatData* memPtr = quantizedBvhFloatData.m_contiguousNodesPtr; + + for (int i=0;im_aabbMaxOrg); + m_contiguousNodes[i].m_aabbMinOrg.deSerializeFloat(memPtr->m_aabbMinOrg); + m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex; + m_contiguousNodes[i].m_subPart = memPtr->m_subPart; + m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex; + } + } + } + + { + int numElem = quantizedBvhFloatData.m_numQuantizedContiguousNodes; + m_quantizedContiguousNodes.resize(numElem); + + if (numElem) + { + btQuantizedBvhNodeData* memPtr = quantizedBvhFloatData.m_quantizedContiguousNodesPtr; + for (int i=0;im_escapeIndexOrTriangleIndex; + m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0]; + m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1]; + m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2]; + m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0]; + m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1]; + m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2]; + } + } + } + + m_traversalMode = btTraversalMode(quantizedBvhFloatData.m_traversalMode); + + { + int numElem = quantizedBvhFloatData.m_numSubtreeHeaders; + m_SubtreeHeaders.resize(numElem); + if (numElem) + { + btBvhSubtreeInfoData* memPtr = quantizedBvhFloatData.m_subTreeInfoPtr; + for (int i=0;im_quantizedAabbMax[0] ; + m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1]; + m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2]; + m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0]; + m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1]; + m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2]; + m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex; + m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize; + } + } + } +} + +void btQuantizedBvh::deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData) +{ + m_bvhAabbMax.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMax); + m_bvhAabbMin.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMin); + m_bvhQuantization.deSerializeDouble(quantizedBvhDoubleData.m_bvhQuantization); + + m_curNodeIndex = quantizedBvhDoubleData.m_curNodeIndex; + m_useQuantization = quantizedBvhDoubleData.m_useQuantization!=0; + + { + int numElem = quantizedBvhDoubleData.m_numContiguousLeafNodes; + m_contiguousNodes.resize(numElem); + + if (numElem) + { + btOptimizedBvhNodeDoubleData* memPtr = quantizedBvhDoubleData.m_contiguousNodesPtr; + + for (int i=0;im_aabbMaxOrg); + m_contiguousNodes[i].m_aabbMinOrg.deSerializeDouble(memPtr->m_aabbMinOrg); + m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex; + m_contiguousNodes[i].m_subPart = memPtr->m_subPart; + m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex; + } + } + } + + { + int numElem = quantizedBvhDoubleData.m_numQuantizedContiguousNodes; + m_quantizedContiguousNodes.resize(numElem); + + if (numElem) + { + btQuantizedBvhNodeData* memPtr = quantizedBvhDoubleData.m_quantizedContiguousNodesPtr; + for (int i=0;im_escapeIndexOrTriangleIndex; + m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0]; + m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1]; + m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2]; + m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0]; + m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1]; + m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2]; + } + } + } + + m_traversalMode = btTraversalMode(quantizedBvhDoubleData.m_traversalMode); + + { + int numElem = quantizedBvhDoubleData.m_numSubtreeHeaders; + m_SubtreeHeaders.resize(numElem); + if (numElem) + { + btBvhSubtreeInfoData* memPtr = quantizedBvhDoubleData.m_subTreeInfoPtr; + for (int i=0;im_quantizedAabbMax[0] ; + m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1]; + m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2]; + m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0]; + m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1]; + m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2]; + m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex; + m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize; + } + } + } + +} + + + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btQuantizedBvh::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btQuantizedBvhData* quantizedData = (btQuantizedBvhData*)dataBuffer; + + m_bvhAabbMax.serialize(quantizedData->m_bvhAabbMax); + m_bvhAabbMin.serialize(quantizedData->m_bvhAabbMin); + m_bvhQuantization.serialize(quantizedData->m_bvhQuantization); + + quantizedData->m_curNodeIndex = m_curNodeIndex; + quantizedData->m_useQuantization = m_useQuantization; + + quantizedData->m_numContiguousLeafNodes = m_contiguousNodes.size(); + quantizedData->m_contiguousNodesPtr = (btOptimizedBvhNodeData*) (m_contiguousNodes.size() ? serializer->getUniquePointer((void*)&m_contiguousNodes[0]) : 0); + if (quantizedData->m_contiguousNodesPtr) + { + int sz = sizeof(btOptimizedBvhNodeData); + int numElem = m_contiguousNodes.size(); + btChunk* chunk = serializer->allocate(sz,numElem); + btOptimizedBvhNodeData* memPtr = (btOptimizedBvhNodeData*)chunk->m_oldPtr; + for (int i=0;im_aabbMaxOrg); + m_contiguousNodes[i].m_aabbMinOrg.serialize(memPtr->m_aabbMinOrg); + memPtr->m_escapeIndex = m_contiguousNodes[i].m_escapeIndex; + memPtr->m_subPart = m_contiguousNodes[i].m_subPart; + memPtr->m_triangleIndex = m_contiguousNodes[i].m_triangleIndex; + } + serializer->finalizeChunk(chunk,"btOptimizedBvhNodeData",BT_ARRAY_CODE,(void*)&m_contiguousNodes[0]); + } + + quantizedData->m_numQuantizedContiguousNodes = m_quantizedContiguousNodes.size(); +// printf("quantizedData->m_numQuantizedContiguousNodes=%d\n",quantizedData->m_numQuantizedContiguousNodes); + quantizedData->m_quantizedContiguousNodesPtr =(btQuantizedBvhNodeData*) (m_quantizedContiguousNodes.size() ? serializer->getUniquePointer((void*)&m_quantizedContiguousNodes[0]) : 0); + if (quantizedData->m_quantizedContiguousNodesPtr) + { + int sz = sizeof(btQuantizedBvhNodeData); + int numElem = m_quantizedContiguousNodes.size(); + btChunk* chunk = serializer->allocate(sz,numElem); + btQuantizedBvhNodeData* memPtr = (btQuantizedBvhNodeData*)chunk->m_oldPtr; + for (int i=0;im_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex; + memPtr->m_quantizedAabbMax[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[0]; + memPtr->m_quantizedAabbMax[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[1]; + memPtr->m_quantizedAabbMax[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[2]; + memPtr->m_quantizedAabbMin[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[0]; + memPtr->m_quantizedAabbMin[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[1]; + memPtr->m_quantizedAabbMin[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[2]; + } + serializer->finalizeChunk(chunk,"btQuantizedBvhNodeData",BT_ARRAY_CODE,(void*)&m_quantizedContiguousNodes[0]); + } + + quantizedData->m_traversalMode = int(m_traversalMode); + quantizedData->m_numSubtreeHeaders = m_SubtreeHeaders.size(); + + quantizedData->m_subTreeInfoPtr = (btBvhSubtreeInfoData*) (m_SubtreeHeaders.size() ? serializer->getUniquePointer((void*)&m_SubtreeHeaders[0]) : 0); + if (quantizedData->m_subTreeInfoPtr) + { + int sz = sizeof(btBvhSubtreeInfoData); + int numElem = m_SubtreeHeaders.size(); + btChunk* chunk = serializer->allocate(sz,numElem); + btBvhSubtreeInfoData* memPtr = (btBvhSubtreeInfoData*)chunk->m_oldPtr; + for (int i=0;im_quantizedAabbMax[0] = m_SubtreeHeaders[i].m_quantizedAabbMax[0]; + memPtr->m_quantizedAabbMax[1] = m_SubtreeHeaders[i].m_quantizedAabbMax[1]; + memPtr->m_quantizedAabbMax[2] = m_SubtreeHeaders[i].m_quantizedAabbMax[2]; + memPtr->m_quantizedAabbMin[0] = m_SubtreeHeaders[i].m_quantizedAabbMin[0]; + memPtr->m_quantizedAabbMin[1] = m_SubtreeHeaders[i].m_quantizedAabbMin[1]; + memPtr->m_quantizedAabbMin[2] = m_SubtreeHeaders[i].m_quantizedAabbMin[2]; + + memPtr->m_rootNodeIndex = m_SubtreeHeaders[i].m_rootNodeIndex; + memPtr->m_subtreeSize = m_SubtreeHeaders[i].m_subtreeSize; + } + serializer->finalizeChunk(chunk,"btBvhSubtreeInfoData",BT_ARRAY_CODE,(void*)&m_SubtreeHeaders[0]); + } + return btQuantizedBvhDataName; +} + + + + + diff --git a/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h new file mode 100644 index 0000000..579cc9a --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h @@ -0,0 +1,579 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_QUANTIZED_BVH_H +#define BT_QUANTIZED_BVH_H + +class btSerializer; + +//#define DEBUG_CHECK_DEQUANTIZATION 1 +#ifdef DEBUG_CHECK_DEQUANTIZATION +#ifdef __SPU__ +#define printf spu_printf +#endif //__SPU__ + +#include +#include +#endif //DEBUG_CHECK_DEQUANTIZATION + +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedAllocator.h" + +#ifdef BT_USE_DOUBLE_PRECISION +#define btQuantizedBvhData btQuantizedBvhDoubleData +#define btOptimizedBvhNodeData btOptimizedBvhNodeDoubleData +#define btQuantizedBvhDataName "btQuantizedBvhDoubleData" +#else +#define btQuantizedBvhData btQuantizedBvhFloatData +#define btOptimizedBvhNodeData btOptimizedBvhNodeFloatData +#define btQuantizedBvhDataName "btQuantizedBvhFloatData" +#endif + + + +//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp + + +//Note: currently we have 16 bytes per quantized node +#define MAX_SUBTREE_SIZE_IN_BYTES 2048 + +// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one +// actually) triangles each (since the sign bit is reserved +#define MAX_NUM_PARTS_IN_BITS 10 + +///btQuantizedBvhNode is a compressed aabb node, 16 bytes. +///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range). +ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + //12 bytes + unsigned short int m_quantizedAabbMin[3]; + unsigned short int m_quantizedAabbMax[3]; + //4 bytes + int m_escapeIndexOrTriangleIndex; + + bool isLeafNode() const + { + //skipindex is negative (internal node), triangleindex >=0 (leafnode) + return (m_escapeIndexOrTriangleIndex >= 0); + } + int getEscapeIndex() const + { + btAssert(!isLeafNode()); + return -m_escapeIndexOrTriangleIndex; + } + int getTriangleIndex() const + { + btAssert(isLeafNode()); + // Get only the lower bits where the triangle index is stored + return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS))); + } + int getPartId() const + { + btAssert(isLeafNode()); + // Get only the highest bits where the part index is stored + return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS)); + } +} +; + +/// btOptimizedBvhNode contains both internal and leaf node information. +/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes. +ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + //32 bytes + btVector3 m_aabbMinOrg; + btVector3 m_aabbMaxOrg; + + //4 + int m_escapeIndex; + + //8 + //for child nodes + int m_subPart; + int m_triangleIndex; + +//pad the size to 64 bytes + char m_padding[20]; +}; + + +///btBvhSubtreeInfo provides info to gather a subtree of limited size +ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo +{ +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + //12 bytes + unsigned short int m_quantizedAabbMin[3]; + unsigned short int m_quantizedAabbMax[3]; + //4 bytes, points to the root of the subtree + int m_rootNodeIndex; + //4 bytes + int m_subtreeSize; + int m_padding[3]; + + btBvhSubtreeInfo() + { + //memset(&m_padding[0], 0, sizeof(m_padding)); + } + + + void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode) + { + m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0]; + m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1]; + m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2]; + m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0]; + m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1]; + m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2]; + } +} +; + + +class btNodeOverlapCallback +{ +public: + virtual ~btNodeOverlapCallback() {}; + + virtual void processNode(int subPart, int triangleIndex) = 0; +}; + +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btAlignedObjectArray.h" + + + +///for code readability: +typedef btAlignedObjectArray NodeArray; +typedef btAlignedObjectArray QuantizedNodeArray; +typedef btAlignedObjectArray BvhSubtreeInfoArray; + + +///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU. +///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase. +///It is recommended to use quantization for better performance and lower memory requirements. +ATTRIBUTE_ALIGNED16(class) btQuantizedBvh +{ +public: + enum btTraversalMode + { + TRAVERSAL_STACKLESS = 0, + TRAVERSAL_STACKLESS_CACHE_FRIENDLY, + TRAVERSAL_RECURSIVE + }; + +protected: + + + btVector3 m_bvhAabbMin; + btVector3 m_bvhAabbMax; + btVector3 m_bvhQuantization; + + int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess. + + int m_curNodeIndex; + //quantization data + bool m_useQuantization; + + + + NodeArray m_leafNodes; + NodeArray m_contiguousNodes; + QuantizedNodeArray m_quantizedLeafNodes; + QuantizedNodeArray m_quantizedContiguousNodes; + + btTraversalMode m_traversalMode; + BvhSubtreeInfoArray m_SubtreeHeaders; + + //This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray + mutable int m_subtreeHeaderCount; + + + + + + ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!) + ///this might be refactored into a virtual, it is usually not calculated at run-time + void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin) + { + if (m_useQuantization) + { + quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0); + } else + { + m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin; + + } + } + void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax) + { + if (m_useQuantization) + { + quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1); + } else + { + m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax; + } + } + + btVector3 getAabbMin(int nodeIndex) const + { + if (m_useQuantization) + { + return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]); + } + //non-quantized + return m_leafNodes[nodeIndex].m_aabbMinOrg; + + } + btVector3 getAabbMax(int nodeIndex) const + { + if (m_useQuantization) + { + return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]); + } + //non-quantized + return m_leafNodes[nodeIndex].m_aabbMaxOrg; + + } + + + void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex) + { + if (m_useQuantization) + { + m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex; + } + else + { + m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex; + } + + } + + void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax) + { + if (m_useQuantization) + { + unsigned short int quantizedAabbMin[3]; + unsigned short int quantizedAabbMax[3]; + quantize(quantizedAabbMin,newAabbMin,0); + quantize(quantizedAabbMax,newAabbMax,1); + for (int i=0;i<3;i++) + { + if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i]) + m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i]; + + if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i]) + m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i]; + + } + } else + { + //non-quantized + m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin); + m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax); + } + } + + void swapLeafNodes(int firstIndex,int secondIndex); + + void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex); + +protected: + + + + void buildTree (int startIndex,int endIndex); + + int calcSplittingAxis(int startIndex,int endIndex); + + int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis); + + void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const; + void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const; + void walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const; + + ///tree traversal designed for small-memory processors like PS3 SPU + void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; + + ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal + void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; + + ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal + void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const; + + + + + void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex); + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btQuantizedBvh(); + + virtual ~btQuantizedBvh(); + + + ///***************************************** expert/internal use only ************************* + void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0)); + QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; } + ///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized + void buildInternal(); + ///***************************************** expert/internal use only ************************* + + void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; + void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const; + void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const; + + SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const + { + + btAssert(m_useQuantization); + + btAssert(point.getX() <= m_bvhAabbMax.getX()); + btAssert(point.getY() <= m_bvhAabbMax.getY()); + btAssert(point.getZ() <= m_bvhAabbMax.getZ()); + + btAssert(point.getX() >= m_bvhAabbMin.getX()); + btAssert(point.getY() >= m_bvhAabbMin.getY()); + btAssert(point.getZ() >= m_bvhAabbMin.getZ()); + + btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization; + ///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative + ///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly) + ///@todo: double-check this + if (isMax) + { + out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1)); + out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1)); + out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1)); + } else + { + out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe)); + out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe)); + out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe)); + } + + +#ifdef DEBUG_CHECK_DEQUANTIZATION + btVector3 newPoint = unQuantize(out); + if (isMax) + { + if (newPoint.getX() < point.getX()) + { + printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX()); + } + if (newPoint.getY() < point.getY()) + { + printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY()); + } + if (newPoint.getZ() < point.getZ()) + { + + printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ()); + } + } else + { + if (newPoint.getX() > point.getX()) + { + printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX()); + } + if (newPoint.getY() > point.getY()) + { + printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY()); + } + if (newPoint.getZ() > point.getZ()) + { + printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ()); + } + } +#endif //DEBUG_CHECK_DEQUANTIZATION + + } + + + SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const + { + + btAssert(m_useQuantization); + + btVector3 clampedPoint(point2); + clampedPoint.setMax(m_bvhAabbMin); + clampedPoint.setMin(m_bvhAabbMax); + + quantize(out,clampedPoint,isMax); + + } + + SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const + { + btVector3 vecOut; + vecOut.setValue( + (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()), + (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()), + (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ())); + vecOut += m_bvhAabbMin; + return vecOut; + } + + ///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees. + void setTraversalMode(btTraversalMode traversalMode) + { + m_traversalMode = traversalMode; + } + + + SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray() + { + return m_quantizedContiguousNodes; + } + + + SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray() + { + return m_SubtreeHeaders; + } + +//////////////////////////////////////////////////////////////////// + + /////Calculate space needed to store BVH for serialization + unsigned calculateSerializeBufferSize() const; + + /// Data buffer MUST be 16 byte aligned + virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const; + + ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' + static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian); + + static unsigned int getAlignmentSerializationPadding(); +////////////////////////////////////////////////////////////////////// + + + virtual int calculateSerializeBufferSizeNew() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + virtual void deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData); + + virtual void deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData); + + +//////////////////////////////////////////////////////////////////// + + SIMD_FORCE_INLINE bool isQuantized() + { + return m_useQuantization; + } + +private: + // Special "copy" constructor that allows for in-place deserialization + // Prevents btVector3's default constructor from being called, but doesn't inialize much else + // ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need) + btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory); + +} +; + + +struct btBvhSubtreeInfoData +{ + int m_rootNodeIndex; + int m_subtreeSize; + unsigned short m_quantizedAabbMin[3]; + unsigned short m_quantizedAabbMax[3]; +}; + +struct btOptimizedBvhNodeFloatData +{ + btVector3FloatData m_aabbMinOrg; + btVector3FloatData m_aabbMaxOrg; + int m_escapeIndex; + int m_subPart; + int m_triangleIndex; + char m_pad[4]; +}; + +struct btOptimizedBvhNodeDoubleData +{ + btVector3DoubleData m_aabbMinOrg; + btVector3DoubleData m_aabbMaxOrg; + int m_escapeIndex; + int m_subPart; + int m_triangleIndex; + char m_pad[4]; +}; + + +struct btQuantizedBvhNodeData +{ + unsigned short m_quantizedAabbMin[3]; + unsigned short m_quantizedAabbMax[3]; + int m_escapeIndexOrTriangleIndex; +}; + +struct btQuantizedBvhFloatData +{ + btVector3FloatData m_bvhAabbMin; + btVector3FloatData m_bvhAabbMax; + btVector3FloatData m_bvhQuantization; + int m_curNodeIndex; + int m_useQuantization; + int m_numContiguousLeafNodes; + int m_numQuantizedContiguousNodes; + btOptimizedBvhNodeFloatData *m_contiguousNodesPtr; + btQuantizedBvhNodeData *m_quantizedContiguousNodesPtr; + btBvhSubtreeInfoData *m_subTreeInfoPtr; + int m_traversalMode; + int m_numSubtreeHeaders; + +}; + +struct btQuantizedBvhDoubleData +{ + btVector3DoubleData m_bvhAabbMin; + btVector3DoubleData m_bvhAabbMax; + btVector3DoubleData m_bvhQuantization; + int m_curNodeIndex; + int m_useQuantization; + int m_numContiguousLeafNodes; + int m_numQuantizedContiguousNodes; + btOptimizedBvhNodeDoubleData *m_contiguousNodesPtr; + btQuantizedBvhNodeData *m_quantizedContiguousNodesPtr; + + int m_traversalMode; + int m_numSubtreeHeaders; + btBvhSubtreeInfoData *m_subTreeInfoPtr; +}; + + +SIMD_FORCE_INLINE int btQuantizedBvh::calculateSerializeBufferSizeNew() const +{ + return sizeof(btQuantizedBvhData); +} + + + +#endif //BT_QUANTIZED_BVH_H diff --git a/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp new file mode 100644 index 0000000..752fcd0 --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp @@ -0,0 +1,349 @@ +/* +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 "btSimpleBroadphase.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btAabbUtil2.h" + +#include + +extern int gOverlappingPairs; + +void btSimpleBroadphase::validate() +{ + for (int i=0;i~btOverlappingPairCache(); + btAlignedFree(m_pairCache); + } +} + + +btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* /*dispatcher*/,void* multiSapProxy) +{ + if (m_numHandles >= m_maxHandles) + { + btAssert(0); + return 0; //should never happen, but don't let the game crash ;-) + } + btAssert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]); + + int newHandleIndex = allocHandle(); + btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy); + + return proxy; +} + +class RemovingOverlapCallback : public btOverlapCallback +{ +protected: + virtual bool processOverlap(btBroadphasePair& pair) + { + (void)pair; + btAssert(0); + return false; + } +}; + +class RemovePairContainingProxy +{ + + btBroadphaseProxy* m_targetProxy; + public: + virtual ~RemovePairContainingProxy() + { + } +protected: + virtual bool processOverlap(btBroadphasePair& pair) + { + btSimpleBroadphaseProxy* proxy0 = static_cast(pair.m_pProxy0); + btSimpleBroadphaseProxy* proxy1 = static_cast(pair.m_pProxy1); + + return ((m_targetProxy == proxy0 || m_targetProxy == proxy1)); + }; +}; + +void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher) +{ + + btSimpleBroadphaseProxy* proxy0 = static_cast(proxyOrg); + freeHandle(proxy0); + + m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher); + + //validate(); + +} + +void btSimpleBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const +{ + const btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy); + aabbMin = sbp->m_aabbMin; + aabbMax = sbp->m_aabbMax; +} + +void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* /*dispatcher*/) +{ + btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy); + sbp->m_aabbMin = aabbMin; + sbp->m_aabbMax = aabbMax; +} + +void btSimpleBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax) +{ + for (int i=0; i <= m_LastHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy = &m_pHandles[i]; + if(!proxy->m_clientObject) + { + continue; + } + rayCallback.process(proxy); + } +} + + +void btSimpleBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) +{ + for (int i=0; i <= m_LastHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy = &m_pHandles[i]; + if(!proxy->m_clientObject) + { + continue; + } + if (TestAabbAgainstAabb2(aabbMin,aabbMax,proxy->m_aabbMin,proxy->m_aabbMax)) + { + callback.process(proxy); + } + } +} + + + + + + + +bool btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1) +{ + return proxy0->m_aabbMin[0] <= proxy1->m_aabbMax[0] && proxy1->m_aabbMin[0] <= proxy0->m_aabbMax[0] && + proxy0->m_aabbMin[1] <= proxy1->m_aabbMax[1] && proxy1->m_aabbMin[1] <= proxy0->m_aabbMax[1] && + proxy0->m_aabbMin[2] <= proxy1->m_aabbMax[2] && proxy1->m_aabbMin[2] <= proxy0->m_aabbMax[2]; + +} + + + +//then remove non-overlapping ones +class CheckOverlapCallback : public btOverlapCallback +{ +public: + virtual bool processOverlap(btBroadphasePair& pair) + { + return (!btSimpleBroadphase::aabbOverlap(static_cast(pair.m_pProxy0),static_cast(pair.m_pProxy1))); + } +}; + +void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + //first check for new overlapping pairs + int i,j; + if (m_numHandles >= 0) + { + int new_largest_index = -1; + for (i=0; i <= m_LastHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i]; + if(!proxy0->m_clientObject) + { + continue; + } + new_largest_index = i; + for (j=i+1; j <= m_LastHandleIndex; j++) + { + btSimpleBroadphaseProxy* proxy1 = &m_pHandles[j]; + btAssert(proxy0 != proxy1); + if(!proxy1->m_clientObject) + { + continue; + } + + btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); + btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); + + if (aabbOverlap(p0,p1)) + { + if ( !m_pairCache->findPair(proxy0,proxy1)) + { + m_pairCache->addOverlappingPair(proxy0,proxy1); + } + } else + { + if (!m_pairCache->hasDeferredRemoval()) + { + if ( m_pairCache->findPair(proxy0,proxy1)) + { + m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); + } + } + } + } + } + + m_LastHandleIndex = new_largest_index; + + if (m_ownsPairCache && m_pairCache->hasDeferredRemoval()) + { + + btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray(); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;iprocessOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + m_pairCache->cleanOverlappingPair(pair,dispatcher); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } + + ///if you don't like to skip the invalid pairs in the array, execute following code: +#define CLEAN_INVALID_PAIRS 1 +#ifdef CLEAN_INVALID_PAIRS + + //perform a sort, to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; +#endif//CLEAN_INVALID_PAIRS + + } + } +} + + +bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); + btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); + return aabbOverlap(p0,p1); +} + +void btSimpleBroadphase::resetPool(btDispatcher* dispatcher) +{ + //not yet +} diff --git a/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h new file mode 100644 index 0000000..7cb3c40 --- /dev/null +++ b/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h @@ -0,0 +1,171 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SIMPLE_BROADPHASE_H +#define BT_SIMPLE_BROADPHASE_H + + +#include "btOverlappingPairCache.h" + + +struct btSimpleBroadphaseProxy : public btBroadphaseProxy +{ + int m_nextFree; + +// int m_handleId; + + + btSimpleBroadphaseProxy() {}; + + btSimpleBroadphaseProxy(const btVector3& minpt,const btVector3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy) + :btBroadphaseProxy(minpt,maxpt,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy) + { + (void)shapeType; + } + + + SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;} + SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;} + + + + +}; + +///The SimpleBroadphase is just a unit-test for btAxisSweep3, bt32BitAxisSweep3, or btDbvtBroadphase, so use those classes instead. +///It is a brute force aabb culling broadphase based on O(n^2) aabb checks +class btSimpleBroadphase : public btBroadphaseInterface +{ + +protected: + + int m_numHandles; // number of active handles + int m_maxHandles; // max number of handles + int m_LastHandleIndex; + + btSimpleBroadphaseProxy* m_pHandles; // handles pool + + void* m_pHandlesRawPtr; + int m_firstFreeHandle; // free handles list + + int allocHandle() + { + btAssert(m_numHandles < m_maxHandles); + int freeHandle = m_firstFreeHandle; + m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree(); + m_numHandles++; + if(freeHandle > m_LastHandleIndex) + { + m_LastHandleIndex = freeHandle; + } + return freeHandle; + } + + void freeHandle(btSimpleBroadphaseProxy* proxy) + { + int handle = int(proxy-m_pHandles); + btAssert(handle >= 0 && handle < m_maxHandles); + if(handle == m_LastHandleIndex) + { + m_LastHandleIndex--; + } + proxy->SetNextFree(m_firstFreeHandle); + m_firstFreeHandle = handle; + + proxy->m_clientObject = 0; + + m_numHandles--; + } + + btOverlappingPairCache* m_pairCache; + bool m_ownsPairCache; + + int m_invalidPair; + + + + inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) + { + btSimpleBroadphaseProxy* proxy0 = static_cast(proxy); + return proxy0; + } + + inline const btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) const + { + const btSimpleBroadphaseProxy* proxy0 = static_cast(proxy); + return proxy0; + } + + ///reset broadphase internal structures, to ensure determinism/reproducability + virtual void resetPool(btDispatcher* dispatcher); + + + void validate(); + +protected: + + + + +public: + btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0); + virtual ~btSimpleBroadphase(); + + + static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1); + + + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); + + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); + + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); + virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; + + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0)); + virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback); + + btOverlappingPairCache* getOverlappingPairCache() + { + return m_pairCache; + } + const btOverlappingPairCache* getOverlappingPairCache() const + { + return m_pairCache; + } + + bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + + ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame + ///will add some transform later + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT); + aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); + } + + virtual void printStats() + { +// printf("btSimpleBroadphase.h\n"); +// printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles); + } +}; + + + +#endif //BT_SIMPLE_BROADPHASE_H + diff --git a/src/BulletCollision/CMakeLists.txt b/src/BulletCollision/CMakeLists.txt new file mode 100644 index 0000000..e740e98 --- /dev/null +++ b/src/BulletCollision/CMakeLists.txt @@ -0,0 +1,279 @@ +INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src ) + +SET(BulletCollision_SRCS + BroadphaseCollision/btAxisSweep3.cpp + BroadphaseCollision/btBroadphaseProxy.cpp + BroadphaseCollision/btCollisionAlgorithm.cpp + BroadphaseCollision/btDbvt.cpp + BroadphaseCollision/btDbvtBroadphase.cpp + BroadphaseCollision/btDispatcher.cpp + BroadphaseCollision/btMultiSapBroadphase.cpp + BroadphaseCollision/btOverlappingPairCache.cpp + BroadphaseCollision/btQuantizedBvh.cpp + BroadphaseCollision/btSimpleBroadphase.cpp + CollisionDispatch/btActivatingCollisionAlgorithm.cpp + CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp + CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp + CollisionDispatch/btBoxBoxDetector.cpp + CollisionDispatch/btCollisionDispatcher.cpp + CollisionDispatch/btCollisionObject.cpp + CollisionDispatch/btCollisionWorld.cpp + CollisionDispatch/btCompoundCollisionAlgorithm.cpp + CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp + CollisionDispatch/btConvexConvexAlgorithm.cpp + CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp + CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp + CollisionDispatch/btDefaultCollisionConfiguration.cpp + CollisionDispatch/btEmptyCollisionAlgorithm.cpp + CollisionDispatch/btGhostObject.cpp + CollisionDispatch/btInternalEdgeUtility.cpp + CollisionDispatch/btInternalEdgeUtility.h + CollisionDispatch/btManifoldResult.cpp + CollisionDispatch/btSimulationIslandManager.cpp + CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp + CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp + CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp + CollisionDispatch/btUnionFind.cpp + CollisionDispatch/SphereTriangleDetector.cpp + CollisionShapes/btBoxShape.cpp + CollisionShapes/btBox2dShape.cpp + CollisionShapes/btBvhTriangleMeshShape.cpp + CollisionShapes/btCapsuleShape.cpp + CollisionShapes/btCollisionShape.cpp + CollisionShapes/btCompoundShape.cpp + CollisionShapes/btConcaveShape.cpp + CollisionShapes/btConeShape.cpp + CollisionShapes/btConvexHullShape.cpp + CollisionShapes/btConvexInternalShape.cpp + CollisionShapes/btConvexPointCloudShape.cpp + CollisionShapes/btConvexPolyhedron.cpp + CollisionShapes/btConvexShape.cpp + CollisionShapes/btConvex2dShape.cpp + CollisionShapes/btConvexTriangleMeshShape.cpp + CollisionShapes/btCylinderShape.cpp + CollisionShapes/btEmptyShape.cpp + CollisionShapes/btHeightfieldTerrainShape.cpp + CollisionShapes/btMinkowskiSumShape.cpp + CollisionShapes/btMultimaterialTriangleMeshShape.cpp + CollisionShapes/btMultiSphereShape.cpp + CollisionShapes/btOptimizedBvh.cpp + CollisionShapes/btPolyhedralConvexShape.cpp + CollisionShapes/btScaledBvhTriangleMeshShape.cpp + CollisionShapes/btShapeHull.cpp + CollisionShapes/btSphereShape.cpp + CollisionShapes/btStaticPlaneShape.cpp + CollisionShapes/btStridingMeshInterface.cpp + CollisionShapes/btTetrahedronShape.cpp + CollisionShapes/btTriangleBuffer.cpp + CollisionShapes/btTriangleCallback.cpp + CollisionShapes/btTriangleIndexVertexArray.cpp + CollisionShapes/btTriangleIndexVertexMaterialArray.cpp + CollisionShapes/btTriangleMesh.cpp + CollisionShapes/btTriangleMeshShape.cpp + CollisionShapes/btUniformScalingShape.cpp + Gimpact/btContactProcessing.cpp + Gimpact/btGenericPoolAllocator.cpp + Gimpact/btGImpactBvh.cpp + Gimpact/btGImpactCollisionAlgorithm.cpp + Gimpact/btGImpactQuantizedBvh.cpp + Gimpact/btGImpactShape.cpp + Gimpact/btTriangleShapeEx.cpp + Gimpact/gim_box_set.cpp + Gimpact/gim_contact.cpp + Gimpact/gim_memory.cpp + Gimpact/gim_tri_collision.cpp + NarrowPhaseCollision/btContinuousConvexCollision.cpp + NarrowPhaseCollision/btConvexCast.cpp + NarrowPhaseCollision/btGjkConvexCast.cpp + NarrowPhaseCollision/btGjkEpa2.cpp + NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp + NarrowPhaseCollision/btGjkPairDetector.cpp + NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp + NarrowPhaseCollision/btPersistentManifold.cpp + NarrowPhaseCollision/btRaycastCallback.cpp + NarrowPhaseCollision/btSubSimplexConvexCast.cpp + NarrowPhaseCollision/btVoronoiSimplexSolver.cpp + NarrowPhaseCollision/btPolyhedralContactClipping.cpp +) + +SET(Root_HDRS + ../btBulletCollisionCommon.h +) +SET(BroadphaseCollision_HDRS + BroadphaseCollision/btAxisSweep3.h + BroadphaseCollision/btBroadphaseInterface.h + BroadphaseCollision/btBroadphaseProxy.h + BroadphaseCollision/btCollisionAlgorithm.h + BroadphaseCollision/btDbvt.h + BroadphaseCollision/btDbvtBroadphase.h + BroadphaseCollision/btDispatcher.h + BroadphaseCollision/btMultiSapBroadphase.h + BroadphaseCollision/btOverlappingPairCache.h + BroadphaseCollision/btOverlappingPairCallback.h + BroadphaseCollision/btQuantizedBvh.h + BroadphaseCollision/btSimpleBroadphase.h +) +SET(CollisionDispatch_HDRS + CollisionDispatch/btActivatingCollisionAlgorithm.h + CollisionDispatch/btBoxBoxCollisionAlgorithm.h + CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h + CollisionDispatch/btBoxBoxDetector.h + CollisionDispatch/btCollisionConfiguration.h + CollisionDispatch/btCollisionCreateFunc.h + CollisionDispatch/btCollisionDispatcher.h + CollisionDispatch/btCollisionObject.h + CollisionDispatch/btCollisionWorld.h + CollisionDispatch/btCompoundCollisionAlgorithm.h + CollisionDispatch/btConvexConcaveCollisionAlgorithm.h + CollisionDispatch/btConvexConvexAlgorithm.h + CollisionDispatch/btConvex2dConvex2dAlgorithm.h + CollisionDispatch/btConvexPlaneCollisionAlgorithm.h + CollisionDispatch/btDefaultCollisionConfiguration.h + CollisionDispatch/btEmptyCollisionAlgorithm.h + CollisionDispatch/btGhostObject.h + CollisionDispatch/btManifoldResult.h + CollisionDispatch/btSimulationIslandManager.h + CollisionDispatch/btSphereBoxCollisionAlgorithm.h + CollisionDispatch/btSphereSphereCollisionAlgorithm.h + CollisionDispatch/btSphereTriangleCollisionAlgorithm.h + CollisionDispatch/btUnionFind.h + CollisionDispatch/SphereTriangleDetector.h +) +SET(CollisionShapes_HDRS + CollisionShapes/btBoxShape.h + CollisionShapes/btBox2dShape.h + CollisionShapes/btBvhTriangleMeshShape.h + CollisionShapes/btCapsuleShape.h + CollisionShapes/btCollisionMargin.h + CollisionShapes/btCollisionShape.h + CollisionShapes/btCompoundShape.h + CollisionShapes/btConcaveShape.h + CollisionShapes/btConeShape.h + CollisionShapes/btConvexHullShape.h + CollisionShapes/btConvexInternalShape.h + CollisionShapes/btConvexPointCloudShape.h + CollisionShapes/btConvexPolyhedron.h + CollisionShapes/btConvexShape.h + CollisionShapes/btConvex2dShape.h + CollisionShapes/btConvexTriangleMeshShape.h + CollisionShapes/btCylinderShape.h + CollisionShapes/btEmptyShape.h + CollisionShapes/btHeightfieldTerrainShape.h + CollisionShapes/btMaterial.h + CollisionShapes/btMinkowskiSumShape.h + CollisionShapes/btMultimaterialTriangleMeshShape.h + CollisionShapes/btMultiSphereShape.h + CollisionShapes/btOptimizedBvh.h + CollisionShapes/btPolyhedralConvexShape.h + CollisionShapes/btScaledBvhTriangleMeshShape.h + CollisionShapes/btShapeHull.h + CollisionShapes/btSphereShape.h + CollisionShapes/btStaticPlaneShape.h + CollisionShapes/btStridingMeshInterface.h + CollisionShapes/btTetrahedronShape.h + CollisionShapes/btTriangleBuffer.h + CollisionShapes/btTriangleCallback.h + CollisionShapes/btTriangleIndexVertexArray.h + CollisionShapes/btTriangleIndexVertexMaterialArray.h + CollisionShapes/btTriangleInfoMap.h + CollisionShapes/btTriangleMesh.h + CollisionShapes/btTriangleMeshShape.h + CollisionShapes/btTriangleShape.h + CollisionShapes/btUniformScalingShape.h +) +SET(Gimpact_HDRS + Gimpact/btBoxCollision.h + Gimpact/btClipPolygon.h + Gimpact/btContactProcessing.h + Gimpact/btGenericPoolAllocator.h + Gimpact/btGeometryOperations.h + Gimpact/btGImpactBvh.h + Gimpact/btGImpactCollisionAlgorithm.h + Gimpact/btGImpactMassUtil.h + Gimpact/btGImpactQuantizedBvh.h + Gimpact/btGImpactShape.h + Gimpact/btQuantization.h + Gimpact/btTriangleShapeEx.h + Gimpact/gim_array.h + Gimpact/gim_basic_geometry_operations.h + Gimpact/gim_bitset.h + Gimpact/gim_box_collision.h + Gimpact/gim_box_set.h + Gimpact/gim_clip_polygon.h + Gimpact/gim_contact.h + Gimpact/gim_geom_types.h + Gimpact/gim_geometry.h + Gimpact/gim_hash_table.h + Gimpact/gim_linear_math.h + Gimpact/gim_math.h + Gimpact/gim_memory.h + Gimpact/gim_radixsort.h + Gimpact/gim_tri_collision.h +) +SET(NarrowPhaseCollision_HDRS + NarrowPhaseCollision/btContinuousConvexCollision.h + NarrowPhaseCollision/btConvexCast.h + NarrowPhaseCollision/btConvexPenetrationDepthSolver.h + NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h + NarrowPhaseCollision/btGjkConvexCast.h + NarrowPhaseCollision/btGjkEpa2.h + NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h + NarrowPhaseCollision/btGjkPairDetector.h + NarrowPhaseCollision/btManifoldPoint.h + NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h + NarrowPhaseCollision/btPersistentManifold.h + NarrowPhaseCollision/btPointCollector.h + NarrowPhaseCollision/btRaycastCallback.h + NarrowPhaseCollision/btSimplexSolverInterface.h + NarrowPhaseCollision/btSubSimplexConvexCast.h + NarrowPhaseCollision/btVoronoiSimplexSolver.h + NarrowPhaseCollision/btPolyhedralContactClipping.h +) + +SET(BulletCollision_HDRS + ${Root_HDRS} + ${BroadphaseCollision_HDRS} + ${CollisionDispatch_HDRS} + ${CollisionShapes_HDRS} + ${Gimpact_HDRS} + ${NarrowPhaseCollision_HDRS} +) + + +ADD_LIBRARY(BulletCollision ${BulletCollision_SRCS} ${BulletCollision_HDRS}) +SET_TARGET_PROPERTIES(BulletCollision PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletCollision PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletCollision LinearMath) +ENDIF (BUILD_SHARED_LIBS) + + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + #INSTALL of other files requires CMake 2.6 + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletCollision DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletCollision DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + INSTALL(FILES ../btBulletCollisionCommon.h +DESTINATION ${INCLUDE_INSTALL_DIR}/BulletCollision) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletCollision PROPERTIES FRAMEWORK true) + + SET_TARGET_PROPERTIES(BulletCollision PROPERTIES PUBLIC_HEADER "${Root_HDRS}") + # Have to list out sub-directories manually: + SET_PROPERTY(SOURCE ${BroadphaseCollision_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/BroadphaseCollision) + SET_PROPERTY(SOURCE ${CollisionDispatch_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/CollisionDispatch) + SET_PROPERTY(SOURCE ${CollisionShapes_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/CollisionShapes) + SET_PROPERTY(SOURCE ${Gimpact_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Gimpact) + SET_PROPERTY(SOURCE ${NarrowPhaseCollision_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/NarrowPhaseCollision) + + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp new file mode 100644 index 0000000..23a5c75 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp @@ -0,0 +1,201 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "LinearMath/btScalar.h" +#include "SphereTriangleDetector.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + + +SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle,btScalar contactBreakingThreshold) +:m_sphere(sphere), +m_triangle(triangle), +m_contactBreakingThreshold(contactBreakingThreshold) +{ + +} + +void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults) +{ + + (void)debugDraw; + const btTransform& transformA = input.m_transformA; + const btTransform& transformB = input.m_transformB; + + btVector3 point,normal; + btScalar timeOfImpact = btScalar(1.); + btScalar depth = btScalar(0.); +// output.m_distance = btScalar(BT_LARGE_FLOAT); + //move sphere into triangle space + btTransform sphereInTr = transformB.inverseTimes(transformA); + + if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact,m_contactBreakingThreshold)) + { + if (swapResults) + { + btVector3 normalOnB = transformB.getBasis()*normal; + btVector3 normalOnA = -normalOnB; + btVector3 pointOnA = transformB*point+normalOnB*depth; + output.addContactPoint(normalOnA,pointOnA,depth); + } else + { + output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth); + } + } + +} + + + +// See also geometrictools.com +// Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv +btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest); + +btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) { + btVector3 diff = p - from; + btVector3 v = to - from; + btScalar t = v.dot(diff); + + if (t > 0) { + btScalar dotVV = v.dot(v); + if (t < dotVV) { + t /= dotVV; + diff -= t*v; + } else { + t = 1; + diff -= v; + } + } else + t = 0; + + nearest = from + t*v; + return diff.dot(diff); +} + +bool SphereTriangleDetector::facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal) { + btVector3 lp(p); + btVector3 lnormal(normal); + + return pointInTriangle(vertices, lnormal, &lp); +} + +bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold) +{ + + const btVector3* vertices = &m_triangle->getVertexPtr(0); + + btScalar radius = m_sphere->getRadius(); + btScalar radiusWithThreshold = radius + contactBreakingThreshold; + + btVector3 normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]); + normal.normalize(); + btVector3 p1ToCentre = sphereCenter - vertices[0]; + btScalar distanceFromPlane = p1ToCentre.dot(normal); + + if (distanceFromPlane < btScalar(0.)) + { + //triangle facing the other way + distanceFromPlane *= btScalar(-1.); + normal *= btScalar(-1.); + } + + bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold; + + // Check for contact / intersection + bool hasContact = false; + btVector3 contactPoint; + if (isInsideContactPlane) { + if (facecontains(sphereCenter,vertices,normal)) { + // Inside the contact wedge - touches a point on the shell plane + hasContact = true; + contactPoint = sphereCenter - normal*distanceFromPlane; + } else { + // Could be inside one of the contact capsules + btScalar contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold; + btVector3 nearestOnEdge; + for (int i = 0; i < m_triangle->getNumEdges(); i++) { + + btVector3 pa; + btVector3 pb; + + m_triangle->getEdge(i,pa,pb); + + btScalar distanceSqr = SegmentSqrDistance(pa,pb,sphereCenter, nearestOnEdge); + if (distanceSqr < contactCapsuleRadiusSqr) { + // Yep, we're inside a capsule + hasContact = true; + contactPoint = nearestOnEdge; + } + + } + } + } + + if (hasContact) { + btVector3 contactToCentre = sphereCenter - contactPoint; + btScalar distanceSqr = contactToCentre.length2(); + + if (distanceSqr < radiusWithThreshold*radiusWithThreshold) + { + if (distanceSqr>SIMD_EPSILON) + { + btScalar distance = btSqrt(distanceSqr); + resultNormal = contactToCentre; + resultNormal.normalize(); + point = contactPoint; + depth = -(radius-distance); + } else + { + btScalar distance = 0.f; + resultNormal = normal; + point = contactPoint; + depth = -radius; + } + return true; + } + } + + return false; +} + + +bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p ) +{ + const btVector3* p1 = &vertices[0]; + const btVector3* p2 = &vertices[1]; + const btVector3* p3 = &vertices[2]; + + btVector3 edge1( *p2 - *p1 ); + btVector3 edge2( *p3 - *p2 ); + btVector3 edge3( *p1 - *p3 ); + + btVector3 p1_to_p( *p - *p1 ); + btVector3 p2_to_p( *p - *p2 ); + btVector3 p3_to_p( *p - *p3 ); + + btVector3 edge1_normal( edge1.cross(normal)); + btVector3 edge2_normal( edge2.cross(normal)); + btVector3 edge3_normal( edge3.cross(normal)); + + btScalar r1, r2, r3; + r1 = edge1_normal.dot( p1_to_p ); + r2 = edge2_normal.dot( p2_to_p ); + r3 = edge3_normal.dot( p3_to_p ); + if ( ( r1 > 0 && r2 > 0 && r3 > 0 ) || + ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) ) + return true; + return false; + +} diff --git a/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h new file mode 100644 index 0000000..22953af --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h @@ -0,0 +1,51 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SPHERE_TRIANGLE_DETECTOR_H +#define BT_SPHERE_TRIANGLE_DETECTOR_H + +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" + + + +class btSphereShape; +class btTriangleShape; + + + +/// sphere-triangle to match the btDiscreteCollisionDetectorInterface +struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface +{ + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false); + + SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle, btScalar contactBreakingThreshold); + + virtual ~SphereTriangleDetector() {}; + + bool collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold); + +private: + + + bool pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p ); + bool facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal); + + btSphereShape* m_sphere; + btTriangleShape* m_triangle; + btScalar m_contactBreakingThreshold; + +}; +#endif //BT_SPHERE_TRIANGLE_DETECTOR_H + diff --git a/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp b/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp new file mode 100644 index 0000000..7e5da6c --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp @@ -0,0 +1,47 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com + +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 "btActivatingCollisionAlgorithm.h" +#include "btCollisionDispatcher.h" +#include "btCollisionObject.h" + +btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci) +:btCollisionAlgorithm(ci) +//, +//m_colObj0(0), +//m_colObj1(0) +{ +} +btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* colObj0,btCollisionObject* colObj1) +:btCollisionAlgorithm(ci) +//, +//m_colObj0(0), +//m_colObj1(0) +{ +// if (ci.m_dispatcher1->needsCollision(colObj0,colObj1)) +// { +// m_colObj0 = colObj0; +// m_colObj1 = colObj1; +// +// m_colObj0->activate(); +// m_colObj1->activate(); +// } +} + +btActivatingCollisionAlgorithm::~btActivatingCollisionAlgorithm() +{ +// m_colObj0->activate(); +// m_colObj1->activate(); +} diff --git a/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h b/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h new file mode 100644 index 0000000..25fe088 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h @@ -0,0 +1,36 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef __BT_ACTIVATING_COLLISION_ALGORITHM_H +#define __BT_ACTIVATING_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" + +///This class is not enabled yet (work-in-progress) to more aggressively activate objects. +class btActivatingCollisionAlgorithm : public btCollisionAlgorithm +{ +// btCollisionObject* m_colObj0; +// btCollisionObject* m_colObj1; + +public: + + btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci); + + btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* colObj0,btCollisionObject* colObj1); + + virtual ~btActivatingCollisionAlgorithm(); + +}; +#endif //__BT_ACTIVATING_COLLISION_ALGORITHM_H diff --git a/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp b/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp new file mode 100644 index 0000000..2182d0d --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp @@ -0,0 +1,435 @@ +/* +Bullet Continuous Collision Detection and Physics Library +* The b2CollidePolygons routines are Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com + +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. +*/ + +///btBox2dBox2dCollisionAlgorithm, with modified b2CollidePolygons routines from the Box2D library. +///The modifications include: switching from b2Vec to btVector3, redefinition of b2Dot, b2Cross + +#include "btBox2dBox2dCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionDispatch/btBoxBoxDetector.h" +#include "BulletCollision/CollisionShapes/btBox2dShape.h" + +#define USE_PERSISTENT_CONTACTS 1 + +btBox2dBox2dCollisionAlgorithm::btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1) +: btActivatingCollisionAlgorithm(ci,obj0,obj1), +m_ownManifold(false), +m_manifoldPtr(mf) +{ + if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1)) + { + m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1); + m_ownManifold = true; + } +} + +btBox2dBox2dCollisionAlgorithm::~btBox2dBox2dCollisionAlgorithm() +{ + + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } + +} + + +void b2CollidePolygons(btManifoldResult* manifold, const btBox2dShape* polyA, const btTransform& xfA, const btBox2dShape* polyB, const btTransform& xfB); + +//#include +void btBox2dBox2dCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + if (!m_manifoldPtr) + return; + + btCollisionObject* col0 = body0; + btCollisionObject* col1 = body1; + btBox2dShape* box0 = (btBox2dShape*)col0->getCollisionShape(); + btBox2dShape* box1 = (btBox2dShape*)col1->getCollisionShape(); + + resultOut->setPersistentManifold(m_manifoldPtr); + + b2CollidePolygons(resultOut,box0,col0->getWorldTransform(),box1,col1->getWorldTransform()); + + // refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } + +} + +btScalar btBox2dBox2dCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) +{ + //not yet + return 1.f; +} + + +struct ClipVertex +{ + btVector3 v; + int id; + //b2ContactID id; + //b2ContactID id; +}; + +#define b2Dot(a,b) (a).dot(b) +#define b2Mul(a,b) (a)*(b) +#define b2MulT(a,b) (a).transpose()*(b) +#define b2Cross(a,b) (a).cross(b) +#define btCrossS(a,s) btVector3(s * a.getY(), -s * a.getX(),0.f) + +int b2_maxManifoldPoints =2; + +static int ClipSegmentToLine(ClipVertex vOut[2], ClipVertex vIn[2], + const btVector3& normal, btScalar offset) +{ + // Start with no output points + int numOut = 0; + + // Calculate the distance of end points to the line + btScalar distance0 = b2Dot(normal, vIn[0].v) - offset; + btScalar distance1 = b2Dot(normal, vIn[1].v) - offset; + + // If the points are behind the plane + if (distance0 <= 0.0f) vOut[numOut++] = vIn[0]; + if (distance1 <= 0.0f) vOut[numOut++] = vIn[1]; + + // If the points are on different sides of the plane + if (distance0 * distance1 < 0.0f) + { + // Find intersection point of edge and plane + btScalar interp = distance0 / (distance0 - distance1); + vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v); + if (distance0 > 0.0f) + { + vOut[numOut].id = vIn[0].id; + } + else + { + vOut[numOut].id = vIn[1].id; + } + ++numOut; + } + + return numOut; +} + +// Find the separation between poly1 and poly2 for a give edge normal on poly1. +static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1, int edge1, + const btBox2dShape* poly2, const btTransform& xf2) +{ + const btVector3* vertices1 = poly1->getVertices(); + const btVector3* normals1 = poly1->getNormals(); + + int count2 = poly2->getVertexCount(); + const btVector3* vertices2 = poly2->getVertices(); + + btAssert(0 <= edge1 && edge1 < poly1->getVertexCount()); + + // Convert normal from poly1's frame into poly2's frame. + btVector3 normal1World = b2Mul(xf1.getBasis(), normals1[edge1]); + btVector3 normal1 = b2MulT(xf2.getBasis(), normal1World); + + // Find support vertex on poly2 for -normal. + int index = 0; + btScalar minDot = BT_LARGE_FLOAT; + + for (int i = 0; i < count2; ++i) + { + btScalar dot = b2Dot(vertices2[i], normal1); + if (dot < minDot) + { + minDot = dot; + index = i; + } + } + + btVector3 v1 = b2Mul(xf1, vertices1[edge1]); + btVector3 v2 = b2Mul(xf2, vertices2[index]); + btScalar separation = b2Dot(v2 - v1, normal1World); + return separation; +} + +// Find the max separation between poly1 and poly2 using edge normals from poly1. +static btScalar FindMaxSeparation(int* edgeIndex, + const btBox2dShape* poly1, const btTransform& xf1, + const btBox2dShape* poly2, const btTransform& xf2) +{ + int count1 = poly1->getVertexCount(); + const btVector3* normals1 = poly1->getNormals(); + + // Vector pointing from the centroid of poly1 to the centroid of poly2. + btVector3 d = b2Mul(xf2, poly2->getCentroid()) - b2Mul(xf1, poly1->getCentroid()); + btVector3 dLocal1 = b2MulT(xf1.getBasis(), d); + + // Find edge normal on poly1 that has the largest projection onto d. + int edge = 0; + btScalar maxDot = -BT_LARGE_FLOAT; + for (int i = 0; i < count1; ++i) + { + btScalar dot = b2Dot(normals1[i], dLocal1); + if (dot > maxDot) + { + maxDot = dot; + edge = i; + } + } + + // Get the separation for the edge normal. + btScalar s = EdgeSeparation(poly1, xf1, edge, poly2, xf2); + if (s > 0.0f) + { + return s; + } + + // Check the separation for the previous edge normal. + int prevEdge = edge - 1 >= 0 ? edge - 1 : count1 - 1; + btScalar sPrev = EdgeSeparation(poly1, xf1, prevEdge, poly2, xf2); + if (sPrev > 0.0f) + { + return sPrev; + } + + // Check the separation for the next edge normal. + int nextEdge = edge + 1 < count1 ? edge + 1 : 0; + btScalar sNext = EdgeSeparation(poly1, xf1, nextEdge, poly2, xf2); + if (sNext > 0.0f) + { + return sNext; + } + + // Find the best edge and the search direction. + int bestEdge; + btScalar bestSeparation; + int increment; + if (sPrev > s && sPrev > sNext) + { + increment = -1; + bestEdge = prevEdge; + bestSeparation = sPrev; + } + else if (sNext > s) + { + increment = 1; + bestEdge = nextEdge; + bestSeparation = sNext; + } + else + { + *edgeIndex = edge; + return s; + } + + // Perform a local search for the best edge normal. + for ( ; ; ) + { + if (increment == -1) + edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1; + else + edge = bestEdge + 1 < count1 ? bestEdge + 1 : 0; + + s = EdgeSeparation(poly1, xf1, edge, poly2, xf2); + if (s > 0.0f) + { + return s; + } + + if (s > bestSeparation) + { + bestEdge = edge; + bestSeparation = s; + } + else + { + break; + } + } + + *edgeIndex = bestEdge; + return bestSeparation; +} + +static void FindIncidentEdge(ClipVertex c[2], + const btBox2dShape* poly1, const btTransform& xf1, int edge1, + const btBox2dShape* poly2, const btTransform& xf2) +{ + const btVector3* normals1 = poly1->getNormals(); + + int count2 = poly2->getVertexCount(); + const btVector3* vertices2 = poly2->getVertices(); + const btVector3* normals2 = poly2->getNormals(); + + btAssert(0 <= edge1 && edge1 < poly1->getVertexCount()); + + // Get the normal of the reference edge in poly2's frame. + btVector3 normal1 = b2MulT(xf2.getBasis(), b2Mul(xf1.getBasis(), normals1[edge1])); + + // Find the incident edge on poly2. + int index = 0; + btScalar minDot = BT_LARGE_FLOAT; + for (int i = 0; i < count2; ++i) + { + btScalar dot = b2Dot(normal1, normals2[i]); + if (dot < minDot) + { + minDot = dot; + index = i; + } + } + + // Build the clip vertices for the incident edge. + int i1 = index; + int i2 = i1 + 1 < count2 ? i1 + 1 : 0; + + c[0].v = b2Mul(xf2, vertices2[i1]); +// c[0].id.features.referenceEdge = (unsigned char)edge1; +// c[0].id.features.incidentEdge = (unsigned char)i1; +// c[0].id.features.incidentVertex = 0; + + c[1].v = b2Mul(xf2, vertices2[i2]); +// c[1].id.features.referenceEdge = (unsigned char)edge1; +// c[1].id.features.incidentEdge = (unsigned char)i2; +// c[1].id.features.incidentVertex = 1; +} + +// Find edge normal of max separation on A - return if separating axis is found +// Find edge normal of max separation on B - return if separation axis is found +// Choose reference edge as min(minA, minB) +// Find incident edge +// Clip + +// The normal points from 1 to 2 +void b2CollidePolygons(btManifoldResult* manifold, + const btBox2dShape* polyA, const btTransform& xfA, + const btBox2dShape* polyB, const btTransform& xfB) +{ + + int edgeA = 0; + btScalar separationA = FindMaxSeparation(&edgeA, polyA, xfA, polyB, xfB); + if (separationA > 0.0f) + return; + + int edgeB = 0; + btScalar separationB = FindMaxSeparation(&edgeB, polyB, xfB, polyA, xfA); + if (separationB > 0.0f) + return; + + const btBox2dShape* poly1; // reference poly + const btBox2dShape* poly2; // incident poly + btTransform xf1, xf2; + int edge1; // reference edge + unsigned char flip; + const btScalar k_relativeTol = 0.98f; + const btScalar k_absoluteTol = 0.001f; + + // TODO_ERIN use "radius" of poly for absolute tolerance. + if (separationB > k_relativeTol * separationA + k_absoluteTol) + { + poly1 = polyB; + poly2 = polyA; + xf1 = xfB; + xf2 = xfA; + edge1 = edgeB; + flip = 1; + } + else + { + poly1 = polyA; + poly2 = polyB; + xf1 = xfA; + xf2 = xfB; + edge1 = edgeA; + flip = 0; + } + + ClipVertex incidentEdge[2]; + FindIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2); + + int count1 = poly1->getVertexCount(); + const btVector3* vertices1 = poly1->getVertices(); + + btVector3 v11 = vertices1[edge1]; + btVector3 v12 = edge1 + 1 < count1 ? vertices1[edge1+1] : vertices1[0]; + + btVector3 dv = v12 - v11; + btVector3 sideNormal = b2Mul(xf1.getBasis(), v12 - v11); + sideNormal.normalize(); + btVector3 frontNormal = btCrossS(sideNormal, 1.0f); + + + v11 = b2Mul(xf1, v11); + v12 = b2Mul(xf1, v12); + + btScalar frontOffset = b2Dot(frontNormal, v11); + btScalar sideOffset1 = -b2Dot(sideNormal, v11); + btScalar sideOffset2 = b2Dot(sideNormal, v12); + + // Clip incident edge against extruded edge1 side edges. + ClipVertex clipPoints1[2]; + clipPoints1[0].v.setValue(0,0,0); + clipPoints1[1].v.setValue(0,0,0); + + ClipVertex clipPoints2[2]; + clipPoints2[0].v.setValue(0,0,0); + clipPoints2[1].v.setValue(0,0,0); + + + int np; + + // Clip to box side 1 + np = ClipSegmentToLine(clipPoints1, incidentEdge, -sideNormal, sideOffset1); + + if (np < 2) + return; + + // Clip to negative box side 1 + np = ClipSegmentToLine(clipPoints2, clipPoints1, sideNormal, sideOffset2); + + if (np < 2) + { + return; + } + + // Now clipPoints2 contains the clipped points. + btVector3 manifoldNormal = flip ? -frontNormal : frontNormal; + + int pointCount = 0; + for (int i = 0; i < b2_maxManifoldPoints; ++i) + { + btScalar separation = b2Dot(frontNormal, clipPoints2[i].v) - frontOffset; + + if (separation <= 0.0f) + { + + //b2ManifoldPoint* cp = manifold->points + pointCount; + //btScalar separation = separation; + //cp->localPoint1 = b2MulT(xfA, clipPoints2[i].v); + //cp->localPoint2 = b2MulT(xfB, clipPoints2[i].v); + + manifold->addContactPoint(-manifoldNormal,clipPoints2[i].v,separation); + +// cp->id = clipPoints2[i].id; +// cp->id.features.flip = flip; + ++pointCount; + } + } + +// manifold->pointCount = pointCount;} +} diff --git a/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h b/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h new file mode 100644 index 0000000..97c5be7 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h @@ -0,0 +1,66 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H +#define BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H + +#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" + +class btPersistentManifold; + +///box-box collision detection +class btBox2dBox2dCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + +public: + btBox2dBox2dCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btActivatingCollisionAlgorithm(ci) {} + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); + + virtual ~btBox2dBox2dCollisionAlgorithm(); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + int bbsize = sizeof(btBox2dBox2dCollisionAlgorithm); + void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize); + return new(ptr) btBox2dBox2dCollisionAlgorithm(0,ci,body0,body1); + } + }; + +}; + +#endif //BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H + diff --git a/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp new file mode 100644 index 0000000..4962885 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp @@ -0,0 +1,85 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btBoxBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "btBoxBoxDetector.h" + +#define USE_PERSISTENT_CONTACTS 1 + +btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1) +: btActivatingCollisionAlgorithm(ci,obj0,obj1), +m_ownManifold(false), +m_manifoldPtr(mf) +{ + if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1)) + { + m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1); + m_ownManifold = true; + } +} + +btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btBoxBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + if (!m_manifoldPtr) + return; + + btCollisionObject* col0 = body0; + btCollisionObject* col1 = body1; + btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape(); + btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape(); + + + + /// report a contact. internally this will be kept persistent, and contact reduction is done + resultOut->setPersistentManifold(m_manifoldPtr); +#ifndef USE_PERSISTENT_CONTACTS + m_manifoldPtr->clearManifold(); +#endif //USE_PERSISTENT_CONTACTS + + btDiscreteCollisionDetectorInterface::ClosestPointInput input; + input.m_maximumDistanceSquared = BT_LARGE_FLOAT; + input.m_transformA = body0->getWorldTransform(); + input.m_transformB = body1->getWorldTransform(); + + btBoxBoxDetector detector(box0,box1); + detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + +#ifdef USE_PERSISTENT_CONTACTS + // refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } +#endif //USE_PERSISTENT_CONTACTS + +} + +btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) +{ + //not yet + return 1.f; +} diff --git a/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h new file mode 100644 index 0000000..f0bbae6 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h @@ -0,0 +1,66 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_BOX_BOX__COLLISION_ALGORITHM_H +#define BT_BOX_BOX__COLLISION_ALGORITHM_H + +#include "btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" + +class btPersistentManifold; + +///box-box collision detection +class btBoxBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + +public: + btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btActivatingCollisionAlgorithm(ci) {} + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); + + virtual ~btBoxBoxCollisionAlgorithm(); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + int bbsize = sizeof(btBoxBoxCollisionAlgorithm); + void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize); + return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0,body1); + } + }; + +}; + +#endif //BT_BOX_BOX__COLLISION_ALGORITHM_H + diff --git a/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp new file mode 100644 index 0000000..a7c8cf1 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp @@ -0,0 +1,718 @@ +/* + * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith + * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. + * All rights reserved. Email: russ@q12.org Web: www.q12.org + Bullet Continuous Collision Detection and Physics Library + Bullet is Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +///ODE box-box collision detection is adapted to work with Bullet + +#include "btBoxBoxDetector.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" + +#include +#include + +btBoxBoxDetector::btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2) +: m_box1(box1), +m_box2(box2) +{ + +} + + +// given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and +// generate contact points. this returns 0 if there is no contact otherwise +// it returns the number of contacts generated. +// `normal' returns the contact normal. +// `depth' returns the maximum penetration depth along that normal. +// `return_code' returns a number indicating the type of contact that was +// detected: +// 1,2,3 = box 2 intersects with a face of box 1 +// 4,5,6 = box 1 intersects with a face of box 2 +// 7..15 = edge-edge contact +// `maxc' is the maximum number of contacts allowed to be generated, i.e. +// the size of the `contact' array. +// `contact' and `skip' are the contact array information provided to the +// collision functions. this function only fills in the position and depth +// fields. +struct dContactGeom; +#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)]) +#define dInfinity FLT_MAX + + +/*PURE_INLINE btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); } +PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); } +PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); } +PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); } +*/ +static btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); } +static btScalar dDOT44 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,4); } +static btScalar dDOT41 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,1); } +static btScalar dDOT14 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,4); } +#define dMULTIPLYOP1_331(A,op,B,C) \ +{\ + (A)[0] op dDOT41((B),(C)); \ + (A)[1] op dDOT41((B+1),(C)); \ + (A)[2] op dDOT41((B+2),(C)); \ +} + +#define dMULTIPLYOP0_331(A,op,B,C) \ +{ \ + (A)[0] op dDOT((B),(C)); \ + (A)[1] op dDOT((B+4),(C)); \ + (A)[2] op dDOT((B+8),(C)); \ +} + +#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C) +#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C) + +typedef btScalar dMatrix3[4*3]; + +void dLineClosestApproach (const btVector3& pa, const btVector3& ua, + const btVector3& pb, const btVector3& ub, + btScalar *alpha, btScalar *beta); +void dLineClosestApproach (const btVector3& pa, const btVector3& ua, + const btVector3& pb, const btVector3& ub, + btScalar *alpha, btScalar *beta) +{ + btVector3 p; + p[0] = pb[0] - pa[0]; + p[1] = pb[1] - pa[1]; + p[2] = pb[2] - pa[2]; + btScalar uaub = dDOT(ua,ub); + btScalar q1 = dDOT(ua,p); + btScalar q2 = -dDOT(ub,p); + btScalar d = 1-uaub*uaub; + if (d <= btScalar(0.0001f)) { + // @@@ this needs to be made more robust + *alpha = 0; + *beta = 0; + } + else { + d = 1.f/d; + *alpha = (q1 + uaub*q2)*d; + *beta = (uaub*q1 + q2)*d; + } +} + + + +// find all the intersection points between the 2D rectangle with vertices +// at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]), +// (p[2],p[3]),(p[4],p[5]),(p[6],p[7]). +// +// the intersection points are returned as x,y pairs in the 'ret' array. +// the number of intersection points is returned by the function (this will +// be in the range 0 to 8). + +static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16]) +{ + // q (and r) contain nq (and nr) coordinate points for the current (and + // chopped) polygons + int nq=4,nr=0; + btScalar buffer[16]; + btScalar *q = p; + btScalar *r = ret; + for (int dir=0; dir <= 1; dir++) { + // direction notation: xy[0] = x axis, xy[1] = y axis + for (int sign=-1; sign <= 1; sign += 2) { + // chop q along the line xy[dir] = sign*h[dir] + btScalar *pq = q; + btScalar *pr = r; + nr = 0; + for (int i=nq; i > 0; i--) { + // go through all points in q and all lines between adjacent points + if (sign*pq[dir] < h[dir]) { + // this point is inside the chopping line + pr[0] = pq[0]; + pr[1] = pq[1]; + pr += 2; + nr++; + if (nr & 8) { + q = r; + goto done; + } + } + btScalar *nextq = (i > 1) ? pq+2 : q; + if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) { + // this line crosses the chopping line + pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) / + (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]); + pr[dir] = sign*h[dir]; + pr += 2; + nr++; + if (nr & 8) { + q = r; + goto done; + } + } + pq += 2; + } + q = r; + r = (q==ret) ? buffer : ret; + nq = nr; + } + } + done: + if (q != ret) memcpy (ret,q,nr*2*sizeof(btScalar)); + return nr; +} + + +#define M__PI 3.14159265f + +// given n points in the plane (array p, of size 2*n), generate m points that +// best represent the whole set. the definition of 'best' here is not +// predetermined - the idea is to select points that give good box-box +// collision detection behavior. the chosen point indexes are returned in the +// array iret (of size m). 'i0' is always the first entry in the array. +// n must be in the range [1..8]. m must be in the range [1..n]. i0 must be +// in the range [0..n-1]. + +void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]); +void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]) +{ + // compute the centroid of the polygon in cx,cy + int i,j; + btScalar a,cx,cy,q; + if (n==1) { + cx = p[0]; + cy = p[1]; + } + else if (n==2) { + cx = btScalar(0.5)*(p[0] + p[2]); + cy = btScalar(0.5)*(p[1] + p[3]); + } + else { + a = 0; + cx = 0; + cy = 0; + for (i=0; i<(n-1); i++) { + q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1]; + a += q; + cx += q*(p[i*2]+p[i*2+2]); + cy += q*(p[i*2+1]+p[i*2+3]); + } + q = p[n*2-2]*p[1] - p[0]*p[n*2-1]; + if (btFabs(a+q) > SIMD_EPSILON) + { + a = 1.f/(btScalar(3.0)*(a+q)); + } else + { + a=BT_LARGE_FLOAT; + } + cx = a*(cx + q*(p[n*2-2]+p[0])); + cy = a*(cy + q*(p[n*2-1]+p[1])); + } + + // compute the angle of each point w.r.t. the centroid + btScalar A[8]; + for (i=0; i M__PI) a -= 2*M__PI; + btScalar maxdiff=1e9,diff; + + *iret = i0; // iret is not allowed to keep this value, but it sometimes does, when diff=#QNAN0 + + for (i=0; i M__PI) diff = 2*M__PI - diff; + if (diff < maxdiff) { + maxdiff = diff; + *iret = i; + } + } + } +#if defined(DEBUG) || defined (_DEBUG) + btAssert (*iret != i0); // ensure iret got set +#endif + avail[*iret] = 0; + iret++; + } +} + + + +int dBoxBox2 (const btVector3& p1, const dMatrix3 R1, + const btVector3& side1, const btVector3& p2, + const dMatrix3 R2, const btVector3& side2, + btVector3& normal, btScalar *depth, int *return_code, + int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output); +int dBoxBox2 (const btVector3& p1, const dMatrix3 R1, + const btVector3& side1, const btVector3& p2, + const dMatrix3 R2, const btVector3& side2, + btVector3& normal, btScalar *depth, int *return_code, + int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output) +{ + const btScalar fudge_factor = btScalar(1.05); + btVector3 p,pp,normalC(0.f,0.f,0.f); + const btScalar *normalR = 0; + btScalar A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33, + Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l; + int i,j,invert_normal,code; + + // get vector from centers of box 1 to box 2, relative to box 1 + p = p2 - p1; + dMULTIPLY1_331 (pp,R1,p); // get pp = p relative to body 1 + + // get side lengths / 2 + A[0] = side1[0]*btScalar(0.5); + A[1] = side1[1]*btScalar(0.5); + A[2] = side1[2]*btScalar(0.5); + B[0] = side2[0]*btScalar(0.5); + B[1] = side2[1]*btScalar(0.5); + B[2] = side2[2]*btScalar(0.5); + + // Rij is R1'*R2, i.e. the relative rotation between R1 and R2 + R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2); + R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2); + R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2); + + Q11 = btFabs(R11); Q12 = btFabs(R12); Q13 = btFabs(R13); + Q21 = btFabs(R21); Q22 = btFabs(R22); Q23 = btFabs(R23); + Q31 = btFabs(R31); Q32 = btFabs(R32); Q33 = btFabs(R33); + + // for all 15 possible separating axes: + // * see if the axis separates the boxes. if so, return 0. + // * find the depth of the penetration along the separating axis (s2) + // * if this is the largest depth so far, record it. + // the normal vector will be set to the separating axis with the smallest + // depth. note: normalR is set to point to a column of R1 or R2 if that is + // the smallest depth normal so far. otherwise normalR is 0 and normalC is + // set to a vector relative to body 1. invert_normal is 1 if the sign of + // the normal should be flipped. + +#define TST(expr1,expr2,norm,cc) \ + s2 = btFabs(expr1) - (expr2); \ + if (s2 > 0) return 0; \ + if (s2 > s) { \ + s = s2; \ + normalR = norm; \ + invert_normal = ((expr1) < 0); \ + code = (cc); \ + } + + s = -dInfinity; + invert_normal = 0; + code = 0; + + // separating axis = u1,u2,u3 + TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1); + TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2); + TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3); + + // separating axis = v1,v2,v3 + TST (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4); + TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5); + TST (dDOT41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6); + + // note: cross product axes need to be scaled when s is computed. + // normal (n1,n2,n3) is relative to box 1. +#undef TST +#define TST(expr1,expr2,n1,n2,n3,cc) \ + s2 = btFabs(expr1) - (expr2); \ + if (s2 > SIMD_EPSILON) return 0; \ + l = btSqrt((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \ + if (l > SIMD_EPSILON) { \ + s2 /= l; \ + if (s2*fudge_factor > s) { \ + s = s2; \ + normalR = 0; \ + normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \ + invert_normal = ((expr1) < 0); \ + code = (cc); \ + } \ + } + + btScalar fudge2 (1.0e-5f); + + Q11 += fudge2; + Q12 += fudge2; + Q13 += fudge2; + + Q21 += fudge2; + Q22 += fudge2; + Q23 += fudge2; + + Q31 += fudge2; + Q32 += fudge2; + Q33 += fudge2; + + // separating axis = u1 x (v1,v2,v3) + TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7); + TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8); + TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9); + + // separating axis = u2 x (v1,v2,v3) + TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10); + TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11); + TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12); + + // separating axis = u3 x (v1,v2,v3) + TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13); + TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14); + TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15); + +#undef TST + + if (!code) return 0; + + // if we get to this point, the boxes interpenetrate. compute the normal + // in global coordinates. + if (normalR) { + normal[0] = normalR[0]; + normal[1] = normalR[4]; + normal[2] = normalR[8]; + } + else { + dMULTIPLY0_331 (normal,R1,normalC); + } + if (invert_normal) { + normal[0] = -normal[0]; + normal[1] = -normal[1]; + normal[2] = -normal[2]; + } + *depth = -s; + + // compute contact point(s) + + if (code > 6) { + // an edge from box 1 touches an edge from box 2. + // find a point pa on the intersecting edge of box 1 + btVector3 pa; + btScalar sign; + for (i=0; i<3; i++) pa[i] = p1[i]; + for (j=0; j<3; j++) { + sign = (dDOT14(normal,R1+j) > 0) ? btScalar(1.0) : btScalar(-1.0); + for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j]; + } + + // find a point pb on the intersecting edge of box 2 + btVector3 pb; + for (i=0; i<3; i++) pb[i] = p2[i]; + for (j=0; j<3; j++) { + sign = (dDOT14(normal,R2+j) > 0) ? btScalar(-1.0) : btScalar(1.0); + for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j]; + } + + btScalar alpha,beta; + btVector3 ua,ub; + for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4]; + for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4]; + + dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta); + for (i=0; i<3; i++) pa[i] += ua[i]*alpha; + for (i=0; i<3; i++) pb[i] += ub[i]*beta; + + { + + //contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]); + //contact[0].depth = *depth; + btVector3 pointInWorld; + +#ifdef USE_CENTER_POINT + for (i=0; i<3; i++) + pointInWorld[i] = (pa[i]+pb[i])*btScalar(0.5); + output.addContactPoint(-normal,pointInWorld,-*depth); +#else + output.addContactPoint(-normal,pb,-*depth); + +#endif // + *return_code = code; + } + return 1; + } + + // okay, we have a face-something intersection (because the separating + // axis is perpendicular to a face). define face 'a' to be the reference + // face (i.e. the normal vector is perpendicular to this) and face 'b' to be + // the incident face (the closest face of the other box). + + const btScalar *Ra,*Rb,*pa,*pb,*Sa,*Sb; + if (code <= 3) { + Ra = R1; + Rb = R2; + pa = p1; + pb = p2; + Sa = A; + Sb = B; + } + else { + Ra = R2; + Rb = R1; + pa = p2; + pb = p1; + Sa = B; + Sb = A; + } + + // nr = normal vector of reference face dotted with axes of incident box. + // anr = absolute values of nr. + btVector3 normal2,nr,anr; + if (code <= 3) { + normal2[0] = normal[0]; + normal2[1] = normal[1]; + normal2[2] = normal[2]; + } + else { + normal2[0] = -normal[0]; + normal2[1] = -normal[1]; + normal2[2] = -normal[2]; + } + dMULTIPLY1_331 (nr,Rb,normal2); + anr[0] = btFabs (nr[0]); + anr[1] = btFabs (nr[1]); + anr[2] = btFabs (nr[2]); + + // find the largest compontent of anr: this corresponds to the normal + // for the indident face. the other axis numbers of the indicent face + // are stored in a1,a2. + int lanr,a1,a2; + if (anr[1] > anr[0]) { + if (anr[1] > anr[2]) { + a1 = 0; + lanr = 1; + a2 = 2; + } + else { + a1 = 0; + a2 = 1; + lanr = 2; + } + } + else { + if (anr[0] > anr[2]) { + lanr = 0; + a1 = 1; + a2 = 2; + } + else { + a1 = 0; + a2 = 1; + lanr = 2; + } + } + + // compute center point of incident face, in reference-face coordinates + btVector3 center; + if (nr[lanr] < 0) { + for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr]; + } + else { + for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr]; + } + + // find the normal and non-normal axis numbers of the reference box + int codeN,code1,code2; + if (code <= 3) codeN = code-1; else codeN = code-4; + if (codeN==0) { + code1 = 1; + code2 = 2; + } + else if (codeN==1) { + code1 = 0; + code2 = 2; + } + else { + code1 = 0; + code2 = 1; + } + + // find the four corners of the incident face, in reference-face coordinates + btScalar quad[8]; // 2D coordinate of incident face (x,y pairs) + btScalar c1,c2,m11,m12,m21,m22; + c1 = dDOT14 (center,Ra+code1); + c2 = dDOT14 (center,Ra+code2); + // optimize this? - we have already computed this data above, but it is not + // stored in an easy-to-index format. for now it's quicker just to recompute + // the four dot products. + m11 = dDOT44 (Ra+code1,Rb+a1); + m12 = dDOT44 (Ra+code1,Rb+a2); + m21 = dDOT44 (Ra+code2,Rb+a1); + m22 = dDOT44 (Ra+code2,Rb+a2); + { + btScalar k1 = m11*Sb[a1]; + btScalar k2 = m21*Sb[a1]; + btScalar k3 = m12*Sb[a2]; + btScalar k4 = m22*Sb[a2]; + quad[0] = c1 - k1 - k3; + quad[1] = c2 - k2 - k4; + quad[2] = c1 - k1 + k3; + quad[3] = c2 - k2 + k4; + quad[4] = c1 + k1 + k3; + quad[5] = c2 + k2 + k4; + quad[6] = c1 + k1 - k3; + quad[7] = c2 + k2 - k4; + } + + // find the size of the reference face + btScalar rect[2]; + rect[0] = Sa[code1]; + rect[1] = Sa[code2]; + + // intersect the incident and reference faces + btScalar ret[16]; + int n = intersectRectQuad2 (rect,quad,ret); + if (n < 1) return 0; // this should never happen + + // convert the intersection points into reference-face coordinates, + // and compute the contact position and depth for each point. only keep + // those points that have a positive (penetrating) depth. delete points in + // the 'ret' array as necessary so that 'point' and 'ret' correspond. + btScalar point[3*8]; // penetrating contact points + btScalar dep[8]; // depths for those points + btScalar det1 = 1.f/(m11*m22 - m12*m21); + m11 *= det1; + m12 *= det1; + m21 *= det1; + m22 *= det1; + int cnum = 0; // number of penetrating contact points found + for (j=0; j < n; j++) { + btScalar k1 = m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2); + btScalar k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2); + for (i=0; i<3; i++) point[cnum*3+i] = + center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2]; + dep[cnum] = Sa[codeN] - dDOT(normal2,point+cnum*3); + if (dep[cnum] >= 0) { + ret[cnum*2] = ret[j*2]; + ret[cnum*2+1] = ret[j*2+1]; + cnum++; + } + } + if (cnum < 1) return 0; // this should never happen + + // we can't generate more contacts than we actually have + if (maxc > cnum) maxc = cnum; + if (maxc < 1) maxc = 1; + + if (cnum <= maxc) { + + if (code<4) + { + // we have less contacts than we need, so we use them all + for (j=0; j < cnum; j++) + { + btVector3 pointInWorld; + for (i=0; i<3; i++) + pointInWorld[i] = point[j*3+i] + pa[i]; + output.addContactPoint(-normal,pointInWorld,-dep[j]); + + } + } else + { + // we have less contacts than we need, so we use them all + for (j=0; j < cnum; j++) + { + btVector3 pointInWorld; + for (i=0; i<3; i++) + pointInWorld[i] = point[j*3+i] + pa[i]-normal[i]*dep[j]; + //pointInWorld[i] = point[j*3+i] + pa[i]; + output.addContactPoint(-normal,pointInWorld,-dep[j]); + } + } + } + else { + // we have more contacts than are wanted, some of them must be culled. + // find the deepest point, it is always the first contact. + int i1 = 0; + btScalar maxdepth = dep[0]; + for (i=1; i maxdepth) { + maxdepth = dep[i]; + i1 = i; + } + } + + int iret[8]; + cullPoints2 (cnum,ret,maxc,i1,iret); + + for (j=0; j < maxc; j++) { +// dContactGeom *con = CONTACT(contact,skip*j); + // for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i]; + // con->depth = dep[iret[j]]; + + btVector3 posInWorld; + for (i=0; i<3; i++) + posInWorld[i] = point[iret[j]*3+i] + pa[i]; + if (code<4) + { + output.addContactPoint(-normal,posInWorld,-dep[iret[j]]); + } else + { + output.addContactPoint(-normal,posInWorld-normal*dep[iret[j]],-dep[iret[j]]); + } + } + cnum = maxc; + } + + *return_code = code; + return cnum; +} + +void btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* /*debugDraw*/,bool /*swapResults*/) +{ + + const btTransform& transformA = input.m_transformA; + const btTransform& transformB = input.m_transformB; + + int skip = 0; + dContactGeom *contact = 0; + + dMatrix3 R1; + dMatrix3 R2; + + for (int j=0;j<3;j++) + { + R1[0+4*j] = transformA.getBasis()[j].x(); + R2[0+4*j] = transformB.getBasis()[j].x(); + + R1[1+4*j] = transformA.getBasis()[j].y(); + R2[1+4*j] = transformB.getBasis()[j].y(); + + + R1[2+4*j] = transformA.getBasis()[j].z(); + R2[2+4*j] = transformB.getBasis()[j].z(); + + } + + + + btVector3 normal; + btScalar depth; + int return_code; + int maxc = 4; + + + dBoxBox2 (transformA.getOrigin(), + R1, + 2.f*m_box1->getHalfExtentsWithMargin(), + transformB.getOrigin(), + R2, + 2.f*m_box2->getHalfExtentsWithMargin(), + normal, &depth, &return_code, + maxc, contact, skip, + output + ); + +} diff --git a/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h new file mode 100644 index 0000000..3c941f7 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h @@ -0,0 +1,44 @@ +/* + * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith + * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. + * All rights reserved. Email: russ@q12.org Web: www.q12.org + +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BT_BOX_BOX_DETECTOR_H +#define BT_BOX_BOX_DETECTOR_H + + +class btBoxShape; +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" + + +/// btBoxBoxDetector wraps the ODE box-box collision detector +/// re-distributed under the Zlib license with permission from Russell L. Smith +struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface +{ + btBoxShape* m_box1; + btBoxShape* m_box2; + +public: + + btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2); + + virtual ~btBoxBoxDetector() {}; + + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false); + +}; + +#endif //BT_BOX_BOX_DETECTOR_H diff --git a/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h new file mode 100644 index 0000000..f63e092 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h @@ -0,0 +1,48 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COLLISION_CONFIGURATION +#define BT_COLLISION_CONFIGURATION + +struct btCollisionAlgorithmCreateFunc; + +class btStackAlloc; +class btPoolAllocator; + +///btCollisionConfiguration allows to configure Bullet collision detection +///stack allocator size, default collision algorithms and persistent manifold pool size +///@todo: describe the meaning +class btCollisionConfiguration +{ + +public: + + virtual ~btCollisionConfiguration() + { + } + + ///memory pools + virtual btPoolAllocator* getPersistentManifoldPool() = 0; + + virtual btPoolAllocator* getCollisionAlgorithmPool() = 0; + + virtual btStackAlloc* getStackAllocator() = 0; + + virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0; + +}; + +#endif //BT_COLLISION_CONFIGURATION + diff --git a/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h new file mode 100644 index 0000000..1d7e744 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h @@ -0,0 +1,45 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COLLISION_CREATE_FUNC +#define BT_COLLISION_CREATE_FUNC + +#include "LinearMath/btAlignedObjectArray.h" +class btCollisionAlgorithm; +class btCollisionObject; + +struct btCollisionAlgorithmConstructionInfo; + +///Used by the btCollisionDispatcher to register and create instances for btCollisionAlgorithm +struct btCollisionAlgorithmCreateFunc +{ + bool m_swapped; + + btCollisionAlgorithmCreateFunc() + :m_swapped(false) + { + } + virtual ~btCollisionAlgorithmCreateFunc(){}; + + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& , btCollisionObject* body0,btCollisionObject* body1) + { + + (void)body0; + (void)body1; + return 0; + } +}; +#endif //BT_COLLISION_CREATE_FUNC + diff --git a/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp new file mode 100644 index 0000000..29674f3 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp @@ -0,0 +1,310 @@ +/* +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 "btCollisionDispatcher.h" + + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" + +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "LinearMath/btPoolAllocator.h" +#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h" + +int gNumManifold = 0; + +#ifdef BT_DEBUG +#include +#endif + + +btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration): +m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD), + m_collisionConfiguration(collisionConfiguration) +{ + int i; + + setNearCallback(defaultNearCallback); + + m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool(); + + m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool(); + + for (i=0;igetCollisionAlgorithmCreateFunc(i,j); + btAssert(m_doubleDispatch[i][j]); + } + } + + +} + + +void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc) +{ + m_doubleDispatch[proxyType0][proxyType1] = createFunc; +} + +btCollisionDispatcher::~btCollisionDispatcher() +{ +} + +btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1) +{ + gNumManifold++; + + //btAssert(gNumManifold < 65535); + + + btCollisionObject* body0 = (btCollisionObject*)b0; + btCollisionObject* body1 = (btCollisionObject*)b1; + + //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 = 0; + + if (m_persistentManifoldPoolAllocator->getFreeCount()) + { + mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold)); + } else + { + //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); + manifold->m_index1a = m_manifoldsPtr.size(); + m_manifoldsPtr.push_back(manifold); + + return manifold; +} + +void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold) +{ + manifold->clearManifold(); +} + + +void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold) +{ + + gNumManifold--; + + //printf("releaseManifold: gNumManifold %d\n",gNumManifold); + clearManifold(manifold); + + int findIndex = manifold->m_index1a; + btAssert(findIndex < m_manifoldsPtr.size()); + m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1); + m_manifoldsPtr[findIndex]->m_index1a = findIndex; + m_manifoldsPtr.pop_back(); + + manifold->~btPersistentManifold(); + if (m_persistentManifoldPoolAllocator->validPtr(manifold)) + { + m_persistentManifoldPoolAllocator->freeMemory(manifold); + } else + { + btAlignedFree(manifold); + } + +} + + + +btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold) +{ + + btCollisionAlgorithmConstructionInfo ci; + + ci.m_dispatcher1 = this; + ci.m_manifold = sharedManifold; + btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1); + + return algo; +} + + + + +bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1) +{ + //here you can do filtering + bool hasResponse = + (body0->hasContactResponse() && body1->hasContactResponse()); + //no response between two static/kinematic bodies: + hasResponse = hasResponse && + ((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject())); + return hasResponse; +} + +bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionObject* body1) +{ + btAssert(body0); + btAssert(body1); + + bool needsCollision = true; + +#ifdef BT_DEBUG + if (!(m_dispatcherFlags & btCollisionDispatcher::CD_STATIC_STATIC_REPORTED)) + { + //broadphase filtering already deals with this + if (body0->isStaticOrKinematicObject() && body1->isStaticOrKinematicObject()) + { + m_dispatcherFlags |= btCollisionDispatcher::CD_STATIC_STATIC_REPORTED; + printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n"); + } + } +#endif //BT_DEBUG + + if ((!body0->isActive()) && (!body1->isActive())) + needsCollision = false; + else if (!body0->checkCollideWith(body1)) + needsCollision = false; + + return needsCollision ; + +} + + + +///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc) +///this is useful for the collision dispatcher. +class btCollisionPairCallback : public btOverlapCallback +{ + const btDispatcherInfo& m_dispatchInfo; + btCollisionDispatcher* m_dispatcher; + +public: + + btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher) + :m_dispatchInfo(dispatchInfo), + m_dispatcher(dispatcher) + { + } + + /*btCollisionPairCallback& operator=(btCollisionPairCallback& other) + { + m_dispatchInfo = other.m_dispatchInfo; + m_dispatcher = other.m_dispatcher; + return *this; + } + */ + + + virtual ~btCollisionPairCallback() {} + + + virtual bool processOverlap(btBroadphasePair& pair) + { + (*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo); + + return false; + } +}; + + + +void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) +{ + //m_blockedForChanges = true; + + btCollisionPairCallback collisionCallback(dispatchInfo,this); + + pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher); + + //m_blockedForChanges = false; + +} + + + + +//by default, Bullet will use this near callback +void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo) +{ + btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; + + if (dispatcher.needsCollision(colObj0,colObj1)) + { + //dispatcher will keep algorithms persistent in the collision pair + if (!collisionPair.m_algorithm) + { + collisionPair.m_algorithm = dispatcher.findAlgorithm(colObj0,colObj1); + } + + if (collisionPair.m_algorithm) + { + btManifoldResult contactPointResult(colObj0,colObj1); + + if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) + { + //discrete collision detection query + collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult); + } else + { + //continuous collision detection query, time of impact (toi) + btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult); + if (dispatchInfo.m_timeOfImpact > toi) + dispatchInfo.m_timeOfImpact = toi; + + } + } + } + +} + + +void* btCollisionDispatcher::allocateCollisionAlgorithm(int size) +{ + if (m_collisionAlgorithmPoolAllocator->getFreeCount()) + { + return m_collisionAlgorithmPoolAllocator->allocate(size); + } + + //warn user for overflow? + return btAlignedAlloc(static_cast(size), 16); +} + +void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr) +{ + if (m_collisionAlgorithmPoolAllocator->validPtr(ptr)) + { + m_collisionAlgorithmPoolAllocator->freeMemory(ptr); + } else + { + btAlignedFree(ptr); + } +} diff --git a/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h new file mode 100644 index 0000000..5accad9 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h @@ -0,0 +1,172 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COLLISION__DISPATCHER_H +#define BT_COLLISION__DISPATCHER_H + +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" + +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" + +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "LinearMath/btAlignedObjectArray.h" + +class btIDebugDraw; +class btOverlappingPairCache; +class btPoolAllocator; +class btCollisionConfiguration; + +#include "btCollisionCreateFunc.h" + +#define USE_DISPATCH_REGISTRY_ARRAY 1 + +class btCollisionDispatcher; +///user can override this nearcallback for collision filtering and more finegrained control over collision detection +typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo); + + +///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs. +///Time of Impact, Closest Points and Penetration Depth. +class btCollisionDispatcher : public btDispatcher +{ + +protected: + + int m_dispatcherFlags; + + btAlignedObjectArray m_manifoldsPtr; + + btManifoldResult m_defaultManifoldResult; + + btNearCallback m_nearCallback; + + btPoolAllocator* m_collisionAlgorithmPoolAllocator; + + btPoolAllocator* m_persistentManifoldPoolAllocator; + + btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES]; + + btCollisionConfiguration* m_collisionConfiguration; + + +public: + + enum DispatcherFlags + { + CD_STATIC_STATIC_REPORTED = 1, + CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD = 2, + CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION = 4 + }; + + int getDispatcherFlags() const + { + return m_dispatcherFlags; + } + + void setDispatcherFlags(int flags) + { + m_dispatcherFlags = flags; + } + + ///registerCollisionCreateFunc allows registration of custom/alternative collision create functions + void registerCollisionCreateFunc(int proxyType0,int proxyType1, btCollisionAlgorithmCreateFunc* createFunc); + + int getNumManifolds() const + { + return int( m_manifoldsPtr.size()); + } + + btPersistentManifold** getInternalManifoldPointer() + { + return m_manifoldsPtr.size()? &m_manifoldsPtr[0] : 0; + } + + btPersistentManifold* getManifoldByIndexInternal(int index) + { + return m_manifoldsPtr[index]; + } + + const btPersistentManifold* getManifoldByIndexInternal(int index) const + { + return m_manifoldsPtr[index]; + } + + btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration); + + virtual ~btCollisionDispatcher(); + + virtual btPersistentManifold* getNewManifold(void* b0,void* b1); + + virtual void releaseManifold(btPersistentManifold* manifold); + + + virtual void clearManifold(btPersistentManifold* manifold); + + + btCollisionAlgorithm* findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0); + + virtual bool needsCollision(btCollisionObject* body0,btCollisionObject* body1); + + virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1); + + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ; + + void setNearCallback(btNearCallback nearCallback) + { + m_nearCallback = nearCallback; + } + + btNearCallback getNearCallback() const + { + return m_nearCallback; + } + + //by default, Bullet will use this near callback + static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo); + + virtual void* allocateCollisionAlgorithm(int size); + + virtual void freeCollisionAlgorithm(void* ptr); + + btCollisionConfiguration* getCollisionConfiguration() + { + return m_collisionConfiguration; + } + + const btCollisionConfiguration* getCollisionConfiguration() const + { + return m_collisionConfiguration; + } + + void setCollisionConfiguration(btCollisionConfiguration* config) + { + m_collisionConfiguration = config; + } + + virtual btPoolAllocator* getInternalManifoldPool() + { + return m_persistentManifoldPoolAllocator; + } + + virtual const btPoolAllocator* getInternalManifoldPool() const + { + return m_persistentManifoldPoolAllocator; + } + +}; + +#endif //BT_COLLISION__DISPATCHER_H + diff --git a/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp new file mode 100644 index 0000000..580ea34 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp @@ -0,0 +1,116 @@ +/* +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 "btCollisionObject.h" +#include "LinearMath/btSerializer.h" + +btCollisionObject::btCollisionObject() + : m_anisotropicFriction(1.f,1.f,1.f), + m_hasAnisotropicFriction(false), + m_contactProcessingThreshold(BT_LARGE_FLOAT), + m_broadphaseHandle(0), + m_collisionShape(0), + m_extensionPointer(0), + m_rootCollisionShape(0), + m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT), + m_islandTag1(-1), + m_companionId(-1), + m_activationState1(1), + m_deactivationTime(btScalar(0.)), + m_friction(btScalar(0.5)), + m_restitution(btScalar(0.)), + m_internalType(CO_COLLISION_OBJECT), + m_userObjectPointer(0), + m_hitFraction(btScalar(1.)), + m_ccdSweptSphereRadius(btScalar(0.)), + m_ccdMotionThreshold(btScalar(0.)), + m_checkCollideWith(false) +{ + m_worldTransform.setIdentity(); +} + +btCollisionObject::~btCollisionObject() +{ +} + +void btCollisionObject::setActivationState(int newState) +{ + if ( (m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION)) + m_activationState1 = newState; +} + +void btCollisionObject::forceActivationState(int newState) +{ + m_activationState1 = newState; +} + +void btCollisionObject::activate(bool forceActivation) +{ + if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT|CF_KINEMATIC_OBJECT))) + { + setActivationState(ACTIVE_TAG); + m_deactivationTime = btScalar(0.); + } +} + +const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* serializer) const +{ + + btCollisionObjectData* dataOut = (btCollisionObjectData*)dataBuffer; + + m_worldTransform.serialize(dataOut->m_worldTransform); + m_interpolationWorldTransform.serialize(dataOut->m_interpolationWorldTransform); + m_interpolationLinearVelocity.serialize(dataOut->m_interpolationLinearVelocity); + m_interpolationAngularVelocity.serialize(dataOut->m_interpolationAngularVelocity); + m_anisotropicFriction.serialize(dataOut->m_anisotropicFriction); + dataOut->m_hasAnisotropicFriction = m_hasAnisotropicFriction; + dataOut->m_contactProcessingThreshold = m_contactProcessingThreshold; + dataOut->m_broadphaseHandle = 0; + dataOut->m_collisionShape = serializer->getUniquePointer(m_collisionShape); + dataOut->m_rootCollisionShape = 0;//@todo + dataOut->m_collisionFlags = m_collisionFlags; + dataOut->m_islandTag1 = m_islandTag1; + dataOut->m_companionId = m_companionId; + dataOut->m_activationState1 = m_activationState1; + dataOut->m_activationState1 = m_activationState1; + dataOut->m_deactivationTime = m_deactivationTime; + dataOut->m_friction = m_friction; + dataOut->m_restitution = m_restitution; + dataOut->m_internalType = m_internalType; + + char* name = (char*) serializer->findNameForPointer(this); + dataOut->m_name = (char*)serializer->getUniquePointer(name); + if (dataOut->m_name) + { + serializer->serializeName(name); + } + dataOut->m_hitFraction = m_hitFraction; + dataOut->m_ccdSweptSphereRadius = m_ccdSweptSphereRadius; + dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold; + dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold; + dataOut->m_checkCollideWith = m_checkCollideWith; + + return btCollisionObjectDataName; +} + + +void btCollisionObject::serializeSingleObject(class btSerializer* serializer) const +{ + int len = calculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(len,1); + const char* structType = serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_COLLISIONOBJECT_CODE,(void*)this); +} diff --git a/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/src/BulletCollision/CollisionDispatch/btCollisionObject.h new file mode 100644 index 0000000..3a11c96 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btCollisionObject.h @@ -0,0 +1,524 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COLLISION_OBJECT_H +#define BT_COLLISION_OBJECT_H + +#include "LinearMath/btTransform.h" + +//island management, m_activationState1 +#define ACTIVE_TAG 1 +#define ISLAND_SLEEPING 2 +#define WANTS_DEACTIVATION 3 +#define DISABLE_DEACTIVATION 4 +#define DISABLE_SIMULATION 5 + +struct btBroadphaseProxy; +class btCollisionShape; +struct btCollisionShapeData; +#include "LinearMath/btMotionState.h" +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btAlignedObjectArray.h" + +typedef btAlignedObjectArray btCollisionObjectArray; + +#ifdef BT_USE_DOUBLE_PRECISION +#define btCollisionObjectData btCollisionObjectDoubleData +#define btCollisionObjectDataName "btCollisionObjectDoubleData" +#else +#define btCollisionObjectData btCollisionObjectFloatData +#define btCollisionObjectDataName "btCollisionObjectFloatData" +#endif + + +/// btCollisionObject can be used to manage collision detection objects. +/// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy. +/// They can be added to the btCollisionWorld. +ATTRIBUTE_ALIGNED16(class) btCollisionObject +{ + +protected: + + btTransform m_worldTransform; + + ///m_interpolationWorldTransform is used for CCD and interpolation + ///it can be either previous or future (predicted) transform + btTransform m_interpolationWorldTransform; + //those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities) + //without destroying the continuous interpolated motion (which uses this interpolation velocities) + btVector3 m_interpolationLinearVelocity; + btVector3 m_interpolationAngularVelocity; + + btVector3 m_anisotropicFriction; + int m_hasAnisotropicFriction; + btScalar m_contactProcessingThreshold; + + btBroadphaseProxy* m_broadphaseHandle; + btCollisionShape* m_collisionShape; + ///m_extensionPointer is used by some internal low-level Bullet extensions. + void* m_extensionPointer; + + ///m_rootCollisionShape is temporarily used to store the original collision shape + ///The m_collisionShape might be temporarily replaced by a child collision shape during collision detection purposes + ///If it is NULL, the m_collisionShape is not temporarily replaced. + btCollisionShape* m_rootCollisionShape; + + int m_collisionFlags; + + int m_islandTag1; + int m_companionId; + + int m_activationState1; + btScalar m_deactivationTime; + + btScalar m_friction; + btScalar m_restitution; + + ///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody, btGhostObject etc. + ///do not assign your own m_internalType unless you write a new dynamics object class. + int m_internalType; + + ///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer + void* m_userObjectPointer; + + ///time of impact calculation + btScalar m_hitFraction; + + ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: + btScalar m_ccdSweptSphereRadius; + + /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold + btScalar m_ccdMotionThreshold; + + /// If some object should have elaborate collision filtering by sub-classes + int m_checkCollideWith; + + virtual bool checkCollideWithOverride(btCollisionObject* /* co */) + { + return true; + } + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + enum CollisionFlags + { + CF_STATIC_OBJECT= 1, + CF_KINEMATIC_OBJECT= 2, + CF_NO_CONTACT_RESPONSE = 4, + CF_CUSTOM_MATERIAL_CALLBACK = 8,//this allows per-triangle material (friction/restitution) + CF_CHARACTER_OBJECT = 16, + CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing + CF_DISABLE_SPU_COLLISION_PROCESSING = 64//disable parallel/SPU processing + }; + + enum CollisionObjectTypes + { + CO_COLLISION_OBJECT =1, + CO_RIGID_BODY=2, + ///CO_GHOST_OBJECT keeps track of all objects overlapping its AABB and that pass its collision filter + ///It is useful for collision sensors, explosion objects, character controller etc. + CO_GHOST_OBJECT=4, + CO_SOFT_BODY=8, + CO_HF_FLUID=16, + CO_USER_TYPE=32 + }; + + SIMD_FORCE_INLINE bool mergesSimulationIslands() const + { + ///static objects, kinematic and object without contact response don't merge islands + return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0); + } + + const btVector3& getAnisotropicFriction() const + { + return m_anisotropicFriction; + } + void setAnisotropicFriction(const btVector3& anisotropicFriction) + { + m_anisotropicFriction = anisotropicFriction; + m_hasAnisotropicFriction = (anisotropicFriction[0]!=1.f) || (anisotropicFriction[1]!=1.f) || (anisotropicFriction[2]!=1.f); + } + bool hasAnisotropicFriction() const + { + return m_hasAnisotropicFriction!=0; + } + + ///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default. + ///Note that using contacts with positive distance can improve stability. It increases, however, the chance of colliding with degerate contacts, such as 'interior' triangle edges + void setContactProcessingThreshold( btScalar contactProcessingThreshold) + { + m_contactProcessingThreshold = contactProcessingThreshold; + } + btScalar getContactProcessingThreshold() const + { + return m_contactProcessingThreshold; + } + + SIMD_FORCE_INLINE bool isStaticObject() const { + return (m_collisionFlags & CF_STATIC_OBJECT) != 0; + } + + SIMD_FORCE_INLINE bool isKinematicObject() const + { + return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0; + } + + SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const + { + return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ; + } + + SIMD_FORCE_INLINE bool hasContactResponse() const { + return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0; + } + + + btCollisionObject(); + + virtual ~btCollisionObject(); + + virtual void setCollisionShape(btCollisionShape* collisionShape) + { + m_collisionShape = collisionShape; + m_rootCollisionShape = collisionShape; + } + + SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const + { + return m_collisionShape; + } + + SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() + { + return m_collisionShape; + } + + SIMD_FORCE_INLINE const btCollisionShape* getRootCollisionShape() const + { + return m_rootCollisionShape; + } + + SIMD_FORCE_INLINE btCollisionShape* getRootCollisionShape() + { + return m_rootCollisionShape; + } + + ///Avoid using this internal API call + ///internalSetTemporaryCollisionShape is used to temporary replace the actual collision shape by a child collision shape. + void internalSetTemporaryCollisionShape(btCollisionShape* collisionShape) + { + m_collisionShape = collisionShape; + } + + ///Avoid using this internal API call, the extension pointer is used by some Bullet extensions. + ///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead. + void* internalGetExtensionPointer() const + { + return m_extensionPointer; + } + ///Avoid using this internal API call, the extension pointer is used by some Bullet extensions + ///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead. + void internalSetExtensionPointer(void* pointer) + { + m_extensionPointer = pointer; + } + + SIMD_FORCE_INLINE int getActivationState() const { return m_activationState1;} + + void setActivationState(int newState); + + void setDeactivationTime(btScalar time) + { + m_deactivationTime = time; + } + btScalar getDeactivationTime() const + { + return m_deactivationTime; + } + + void forceActivationState(int newState); + + void activate(bool forceActivation = false); + + SIMD_FORCE_INLINE bool isActive() const + { + return ((getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION)); + } + + void setRestitution(btScalar rest) + { + m_restitution = rest; + } + btScalar getRestitution() const + { + return m_restitution; + } + void setFriction(btScalar frict) + { + m_friction = frict; + } + btScalar getFriction() const + { + return m_friction; + } + + ///reserved for Bullet internal usage + int getInternalType() const + { + return m_internalType; + } + + btTransform& getWorldTransform() + { + return m_worldTransform; + } + + const btTransform& getWorldTransform() const + { + return m_worldTransform; + } + + void setWorldTransform(const btTransform& worldTrans) + { + m_worldTransform = worldTrans; + } + + + SIMD_FORCE_INLINE btBroadphaseProxy* getBroadphaseHandle() + { + return m_broadphaseHandle; + } + + SIMD_FORCE_INLINE const btBroadphaseProxy* getBroadphaseHandle() const + { + return m_broadphaseHandle; + } + + void setBroadphaseHandle(btBroadphaseProxy* handle) + { + m_broadphaseHandle = handle; + } + + + const btTransform& getInterpolationWorldTransform() const + { + return m_interpolationWorldTransform; + } + + btTransform& getInterpolationWorldTransform() + { + return m_interpolationWorldTransform; + } + + void setInterpolationWorldTransform(const btTransform& trans) + { + m_interpolationWorldTransform = trans; + } + + void setInterpolationLinearVelocity(const btVector3& linvel) + { + m_interpolationLinearVelocity = linvel; + } + + void setInterpolationAngularVelocity(const btVector3& angvel) + { + m_interpolationAngularVelocity = angvel; + } + + const btVector3& getInterpolationLinearVelocity() const + { + return m_interpolationLinearVelocity; + } + + const btVector3& getInterpolationAngularVelocity() const + { + return m_interpolationAngularVelocity; + } + + SIMD_FORCE_INLINE int getIslandTag() const + { + return m_islandTag1; + } + + void setIslandTag(int tag) + { + m_islandTag1 = tag; + } + + SIMD_FORCE_INLINE int getCompanionId() const + { + return m_companionId; + } + + void setCompanionId(int id) + { + m_companionId = id; + } + + SIMD_FORCE_INLINE btScalar getHitFraction() const + { + return m_hitFraction; + } + + void setHitFraction(btScalar hitFraction) + { + m_hitFraction = hitFraction; + } + + + SIMD_FORCE_INLINE int getCollisionFlags() const + { + return m_collisionFlags; + } + + void setCollisionFlags(int flags) + { + m_collisionFlags = flags; + } + + ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: + btScalar getCcdSweptSphereRadius() const + { + return m_ccdSweptSphereRadius; + } + + ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: + void setCcdSweptSphereRadius(btScalar radius) + { + m_ccdSweptSphereRadius = radius; + } + + btScalar getCcdMotionThreshold() const + { + return m_ccdMotionThreshold; + } + + btScalar getCcdSquareMotionThreshold() const + { + return m_ccdMotionThreshold*m_ccdMotionThreshold; + } + + + + /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold + void setCcdMotionThreshold(btScalar ccdMotionThreshold) + { + m_ccdMotionThreshold = ccdMotionThreshold; + } + + ///users can point to their objects, userPointer is not used by Bullet + void* getUserPointer() const + { + return m_userObjectPointer; + } + + ///users can point to their objects, userPointer is not used by Bullet + void setUserPointer(void* userPointer) + { + m_userObjectPointer = userPointer; + } + + + inline bool checkCollideWith(btCollisionObject* co) + { + if (m_checkCollideWith) + return checkCollideWithOverride(co); + + return true; + } + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const; + + virtual void serializeSingleObject(class btSerializer* serializer) const; + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btCollisionObjectDoubleData +{ + void *m_broadphaseHandle; + void *m_collisionShape; + btCollisionShapeData *m_rootCollisionShape; + char *m_name; + + btTransformDoubleData m_worldTransform; + btTransformDoubleData m_interpolationWorldTransform; + btVector3DoubleData m_interpolationLinearVelocity; + btVector3DoubleData m_interpolationAngularVelocity; + btVector3DoubleData m_anisotropicFriction; + double m_contactProcessingThreshold; + double m_deactivationTime; + double m_friction; + double m_restitution; + double m_hitFraction; + double m_ccdSweptSphereRadius; + double m_ccdMotionThreshold; + + int m_hasAnisotropicFriction; + int m_collisionFlags; + int m_islandTag1; + int m_companionId; + int m_activationState1; + int m_internalType; + int m_checkCollideWith; + + char m_padding[4]; +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btCollisionObjectFloatData +{ + void *m_broadphaseHandle; + void *m_collisionShape; + btCollisionShapeData *m_rootCollisionShape; + char *m_name; + + btTransformFloatData m_worldTransform; + btTransformFloatData m_interpolationWorldTransform; + btVector3FloatData m_interpolationLinearVelocity; + btVector3FloatData m_interpolationAngularVelocity; + btVector3FloatData m_anisotropicFriction; + float m_contactProcessingThreshold; + float m_deactivationTime; + float m_friction; + float m_restitution; + float m_hitFraction; + float m_ccdSweptSphereRadius; + float m_ccdMotionThreshold; + + int m_hasAnisotropicFriction; + int m_collisionFlags; + int m_islandTag1; + int m_companionId; + int m_activationState1; + int m_internalType; + int m_checkCollideWith; +}; + + + +SIMD_FORCE_INLINE int btCollisionObject::calculateSerializeBufferSize() const +{ + return sizeof(btCollisionObjectData); +} + + + +#endif //BT_COLLISION_OBJECT_H diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp new file mode 100644 index 0000000..66b93b8 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -0,0 +1,1518 @@ +/* +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 "btCollisionWorld.h" +#include "btCollisionDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting +#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/BroadphaseCollision/btDbvt.h" +#include "LinearMath/btAabbUtil2.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btStackAlloc.h" +#include "LinearMath/btSerializer.h" +#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h" + +//#define DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION + + +//#define USE_BRUTEFORCE_RAYBROADPHASE 1 +//RECALCULATE_AABB is slower, but benefit is that you don't need to call 'stepSimulation' or 'updateAabbs' before using a rayTest +//#define RECALCULATE_AABB_RAYCAST 1 + +//When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor) +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h" + + +///for debug drawing + +//for debug rendering +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/CollisionShapes/btConeShape.h" +#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btCylinderShape.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" + + + +btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration) +:m_dispatcher1(dispatcher), +m_broadphasePairCache(pairCache), +m_debugDrawer(0), +m_forceUpdateAllAabbs(true) +{ + m_stackAlloc = collisionConfiguration->getStackAllocator(); + m_dispatchInfo.m_stackAllocator = m_stackAlloc; +} + + +btCollisionWorld::~btCollisionWorld() +{ + + //clean up remaining objects + int i; + for (i=0;igetBroadphaseHandle(); + if (bp) + { + // + // only clear the cached algorithms + // + getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); + getBroadphase()->destroyProxy(bp,m_dispatcher1); + collisionObject->setBroadphaseHandle(0); + } + } + + +} + + + + + + + + + + +void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask) +{ + + btAssert(collisionObject); + + //check that the object isn't already added + btAssert( m_collisionObjects.findLinearSearch(collisionObject) == m_collisionObjects.size()); + + m_collisionObjects.push_back(collisionObject); + + //calculate new AABB + btTransform trans = collisionObject->getWorldTransform(); + + btVector3 minAabb; + btVector3 maxAabb; + collisionObject->getCollisionShape()->getAabb(trans,minAabb,maxAabb); + + int type = collisionObject->getCollisionShape()->getShapeType(); + collisionObject->setBroadphaseHandle( getBroadphase()->createProxy( + minAabb, + maxAabb, + type, + collisionObject, + collisionFilterGroup, + collisionFilterMask, + m_dispatcher1,0 + )) ; + + + + + +} + + + +void btCollisionWorld::updateSingleAabb(btCollisionObject* colObj) +{ + btVector3 minAabb,maxAabb; + colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); + //need to increase the aabb for contact thresholds + btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold); + minAabb -= contactThreshold; + maxAabb += contactThreshold; + + if(getDispatchInfo().m_useContinuous && colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject()) + { + btVector3 minAabb2,maxAabb2; + colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2); + minAabb2 -= contactThreshold; + maxAabb2 += contactThreshold; + minAabb.setMin(minAabb2); + maxAabb.setMax(maxAabb2); + } + + btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache; + + //moving objects should be moderately sized, probably something wrong if not + if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12))) + { + bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); + } else + { + //something went wrong, investigate + //this assert is unwanted in 3D modelers (danger of loosing work) + colObj->setActivationState(DISABLE_SIMULATION); + + static bool reportMe = true; + if (reportMe && m_debugDrawer) + { + reportMe = false; + m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation"); + m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n"); + m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n"); + m_debugDrawer->reportErrorWarning("Thanks.\n"); + } + } +} + +void btCollisionWorld::updateAabbs() +{ + BT_PROFILE("updateAabbs"); + + btTransform predictedTrans; + for ( int i=0;iisActive()) + { + updateSingleAabb(colObj); + } + } +} + + + +void btCollisionWorld::performDiscreteCollisionDetection() +{ + BT_PROFILE("performDiscreteCollisionDetection"); + + btDispatcherInfo& dispatchInfo = getDispatchInfo(); + + updateAabbs(); + + { + BT_PROFILE("calculateOverlappingPairs"); + m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); + } + + + btDispatcher* dispatcher = getDispatcher(); + { + BT_PROFILE("dispatchAllCollisionPairs"); + if (dispatcher) + dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); + } + +} + + + +void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject) +{ + + + //bool removeFromBroadphase = false; + + { + + btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle(); + if (bp) + { + // + // only clear the cached algorithms + // + getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); + getBroadphase()->destroyProxy(bp,m_dispatcher1); + collisionObject->setBroadphaseHandle(0); + } + } + + + //swapremove + m_collisionObjects.remove(collisionObject); + +} + + + +void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + RayResultCallback& resultCallback) +{ + btSphereShape pointShape(btScalar(0.0)); + pointShape.setMargin(0.f); + const btConvexShape* castShape = &pointShape; + + if (collisionShape->isConvex()) + { + // BT_PROFILE("rayTestConvex"); + btConvexCast::CastResult castResult; + castResult.m_fraction = resultCallback.m_closestHitFraction; + + btConvexShape* convexShape = (btConvexShape*) collisionShape; + btVoronoiSimplexSolver simplexSolver; +#define USE_SUBSIMPLEX_CONVEX_CAST 1 +#ifdef USE_SUBSIMPLEX_CONVEX_CAST + btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver); +#else + //btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver); + //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); +#endif //#USE_SUBSIMPLEX_CONVEX_CAST + + if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) + { + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) + { + if (castResult.m_fraction < resultCallback.m_closestHitFraction) + { +#ifdef USE_SUBSIMPLEX_CONVEX_CAST + //rotate normal into worldspace + castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal; +#endif //USE_SUBSIMPLEX_CONVEX_CAST + + castResult.m_normal.normalize(); + btCollisionWorld::LocalRayResult localRayResult + ( + collisionObject, + 0, + castResult.m_normal, + castResult.m_fraction + ); + + bool normalInWorldSpace = true; + resultCallback.addSingleResult(localRayResult, normalInWorldSpace); + + } + } + } + } else { + if (collisionShape->isConcave()) + { + // BT_PROFILE("rayTestConcave"); + if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + ///optimized version for btBvhTriangleMeshShape + btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); + btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); + + //ConvexCast::CastResult + struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback + { + btCollisionWorld::RayResultCallback* m_resultCallback; + btCollisionObject* m_collisionObject; + btTriangleMeshShape* m_triangleMesh; + + btTransform m_colObjWorldTransform; + + BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, + btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh,const btTransform& colObjWorldTransform): + //@BP Mod + btTriangleRaycastCallback(from,to, resultCallback->m_flags), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh), + m_colObjWorldTransform(colObjWorldTransform) + { + } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + + btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal; + + btCollisionWorld::LocalRayResult rayResult + (m_collisionObject, + &shapeInfo, + hitNormalWorld, + hitFraction); + + bool normalInWorldSpace = true; + return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace); + } + + }; + + BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh,colObjWorldTransform); + rcb.m_hitFraction = resultCallback.m_closestHitFraction; + triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal); + } else + { + //generic (slower) case + btConcaveShape* concaveShape = (btConcaveShape*)collisionShape; + + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + + btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); + btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); + + //ConvexCast::CastResult + + struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback + { + btCollisionWorld::RayResultCallback* m_resultCallback; + btCollisionObject* m_collisionObject; + btConcaveShape* m_triangleMesh; + + btTransform m_colObjWorldTransform; + + BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, + btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform): + //@BP Mod + btTriangleRaycastCallback(from,to, resultCallback->m_flags), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh), + m_colObjWorldTransform(colObjWorldTransform) + { + } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + + btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal; + + btCollisionWorld::LocalRayResult rayResult + (m_collisionObject, + &shapeInfo, + hitNormalWorld, + hitFraction); + + bool normalInWorldSpace = true; + return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace); + } + + }; + + + BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,concaveShape, colObjWorldTransform); + rcb.m_hitFraction = resultCallback.m_closestHitFraction; + + btVector3 rayAabbMinLocal = rayFromLocal; + rayAabbMinLocal.setMin(rayToLocal); + btVector3 rayAabbMaxLocal = rayFromLocal; + rayAabbMaxLocal.setMax(rayToLocal); + + concaveShape->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); + } + } else { + // BT_PROFILE("rayTestCompound"); + if (collisionShape->isCompound()) + { + struct LocalInfoAdder2 : public RayResultCallback + { + RayResultCallback* m_userCallback; + int m_i; + + LocalInfoAdder2 (int i, RayResultCallback *user) + : m_userCallback(user), m_i(i) + { + m_closestHitFraction = m_userCallback->m_closestHitFraction; + } + virtual bool needsCollision(btBroadphaseProxy* p) const + { + return m_userCallback->needsCollision(p); + } + + virtual btScalar addSingleResult (btCollisionWorld::LocalRayResult &r, bool b) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = -1; + shapeInfo.m_triangleIndex = m_i; + if (r.m_localShapeInfo == NULL) + r.m_localShapeInfo = &shapeInfo; + + const btScalar result = m_userCallback->addSingleResult(r, b); + m_closestHitFraction = m_userCallback->m_closestHitFraction; + return result; + } + }; + + struct RayTester : btDbvt::ICollide + { + btCollisionObject* m_collisionObject; + const btCompoundShape* m_compoundShape; + const btTransform& m_colObjWorldTransform; + const btTransform& m_rayFromTrans; + const btTransform& m_rayToTrans; + RayResultCallback& m_resultCallback; + + RayTester(btCollisionObject* collisionObject, + const btCompoundShape* compoundShape, + const btTransform& colObjWorldTransform, + const btTransform& rayFromTrans, + const btTransform& rayToTrans, + RayResultCallback& resultCallback): + m_collisionObject(collisionObject), + m_compoundShape(compoundShape), + m_colObjWorldTransform(colObjWorldTransform), + m_rayFromTrans(rayFromTrans), + m_rayToTrans(rayToTrans), + m_resultCallback(resultCallback) + { + + } + + void Process(int i) + { + const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(i); + const btTransform& childTrans = m_compoundShape->getChildTransform(i); + btTransform childWorldTrans = m_colObjWorldTransform * childTrans; + + // replace collision shape so that callback can determine the triangle + btCollisionShape* saveCollisionShape = m_collisionObject->getCollisionShape(); + m_collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape); + + LocalInfoAdder2 my_cb(i, &m_resultCallback); + + rayTestSingle( + m_rayFromTrans, + m_rayToTrans, + m_collisionObject, + childCollisionShape, + childWorldTrans, + my_cb); + + // restore + m_collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape); + } + + void Process(const btDbvtNode* leaf) + { + Process(leaf->dataAsInt); + } + }; + + const btCompoundShape* compoundShape = static_cast(collisionShape); + const btDbvt* dbvt = compoundShape->getDynamicAabbTree(); + + + RayTester rayCB( + collisionObject, + compoundShape, + colObjWorldTransform, + rayFromTrans, + rayToTrans, + resultCallback); +#ifndef DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION + if (dbvt) + { + btVector3 localRayFrom = colObjWorldTransform.inverseTimes(rayFromTrans).getOrigin(); + btVector3 localRayTo = colObjWorldTransform.inverseTimes(rayToTrans).getOrigin(); + btDbvt::rayTest(dbvt->m_root, localRayFrom , localRayTo, rayCB); + } + else +#endif //DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION + { + for (int i = 0, n = compoundShape->getNumChildShapes(); i < n; ++i) + { + rayCB.Process(i); + } + } + } + } + } +} + +void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + ConvexResultCallback& resultCallback, btScalar allowedPenetration) +{ + if (collisionShape->isConvex()) + { + //BT_PROFILE("convexSweepConvex"); + btConvexCast::CastResult castResult; + castResult.m_allowedPenetration = allowedPenetration; + castResult.m_fraction = resultCallback.m_closestHitFraction;//btScalar(1.);//?? + + btConvexShape* convexShape = (btConvexShape*) collisionShape; + btVoronoiSimplexSolver simplexSolver; + btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver; + + btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver); + //btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver); + //btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver); + + btConvexCast* castPtr = &convexCaster1; + + + + if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) + { + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) + { + if (castResult.m_fraction < resultCallback.m_closestHitFraction) + { + castResult.m_normal.normalize(); + btCollisionWorld::LocalConvexResult localConvexResult + ( + collisionObject, + 0, + castResult.m_normal, + castResult.m_hitPoint, + castResult.m_fraction + ); + + bool normalInWorldSpace = true; + resultCallback.addSingleResult(localConvexResult, normalInWorldSpace); + + } + } + } + } else { + if (collisionShape->isConcave()) + { + if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + //BT_PROFILE("convexSweepbtBvhTriangleMesh"); + btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin(); + btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin(); + // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation + btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); + + //ConvexCast::CastResult + struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback + { + btCollisionWorld::ConvexResultCallback* m_resultCallback; + btCollisionObject* m_collisionObject; + btTriangleMeshShape* m_triangleMesh; + + BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to, + btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld): + btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh) + { + } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + if (hitFraction <= m_resultCallback->m_closestHitFraction) + { + + btCollisionWorld::LocalConvexResult convexResult + (m_collisionObject, + &shapeInfo, + hitNormalLocal, + hitPointLocal, + hitFraction); + + bool normalInWorldSpace = true; + + + return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace); + } + return hitFraction; + } + + }; + + BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform); + tccb.m_hitFraction = resultCallback.m_closestHitFraction; + tccb.m_allowedPenetration = allowedPenetration; + btVector3 boxMinLocal, boxMaxLocal; + castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); + triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal); + } else + { + if (collisionShape->getShapeType()==STATIC_PLANE_PROXYTYPE) + { + btConvexCast::CastResult castResult; + castResult.m_allowedPenetration = allowedPenetration; + castResult.m_fraction = resultCallback.m_closestHitFraction; + btStaticPlaneShape* planeShape = (btStaticPlaneShape*) collisionShape; + btContinuousConvexCollision convexCaster1(castShape,planeShape); + btConvexCast* castPtr = &convexCaster1; + + if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) + { + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) + { + if (castResult.m_fraction < resultCallback.m_closestHitFraction) + { + castResult.m_normal.normalize(); + btCollisionWorld::LocalConvexResult localConvexResult + ( + collisionObject, + 0, + castResult.m_normal, + castResult.m_hitPoint, + castResult.m_fraction + ); + + bool normalInWorldSpace = true; + resultCallback.addSingleResult(localConvexResult, normalInWorldSpace); + } + } + } + + } else + { + //BT_PROFILE("convexSweepConcave"); + btConcaveShape* concaveShape = (btConcaveShape*)collisionShape; + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin(); + btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin(); + // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation + btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); + + //ConvexCast::CastResult + struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback + { + btCollisionWorld::ConvexResultCallback* m_resultCallback; + btCollisionObject* m_collisionObject; + btConcaveShape* m_triangleMesh; + + BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to, + btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& triangleToWorld): + btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh) + { + } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + if (hitFraction <= m_resultCallback->m_closestHitFraction) + { + + btCollisionWorld::LocalConvexResult convexResult + (m_collisionObject, + &shapeInfo, + hitNormalLocal, + hitPointLocal, + hitFraction); + + bool normalInWorldSpace = false; + + return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace); + } + return hitFraction; + } + + }; + + BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,concaveShape, colObjWorldTransform); + tccb.m_hitFraction = resultCallback.m_closestHitFraction; + tccb.m_allowedPenetration = allowedPenetration; + btVector3 boxMinLocal, boxMaxLocal; + castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); + + btVector3 rayAabbMinLocal = convexFromLocal; + rayAabbMinLocal.setMin(convexToLocal); + btVector3 rayAabbMaxLocal = convexFromLocal; + rayAabbMaxLocal.setMax(convexToLocal); + rayAabbMinLocal += boxMinLocal; + rayAabbMaxLocal += boxMaxLocal; + concaveShape->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal); + } + } + } else { + ///@todo : use AABB tree or other BVH acceleration structure! + if (collisionShape->isCompound()) + { + BT_PROFILE("convexSweepCompound"); + const btCompoundShape* compoundShape = static_cast(collisionShape); + int i=0; + for (i=0;igetNumChildShapes();i++) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); + btTransform childWorldTrans = colObjWorldTransform * childTrans; + // replace collision shape so that callback can determine the triangle + btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape(); + collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape); + struct LocalInfoAdder : public ConvexResultCallback { + ConvexResultCallback* m_userCallback; + int m_i; + + LocalInfoAdder (int i, ConvexResultCallback *user) + : m_userCallback(user), m_i(i) + { + m_closestHitFraction = m_userCallback->m_closestHitFraction; + } + virtual bool needsCollision(btBroadphaseProxy* p) const + { + return m_userCallback->needsCollision(p); + } + virtual btScalar addSingleResult (btCollisionWorld::LocalConvexResult& r, bool b) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = -1; + shapeInfo.m_triangleIndex = m_i; + if (r.m_localShapeInfo == NULL) + r.m_localShapeInfo = &shapeInfo; + const btScalar result = m_userCallback->addSingleResult(r, b); + m_closestHitFraction = m_userCallback->m_closestHitFraction; + return result; + + } + }; + + LocalInfoAdder my_cb(i, &resultCallback); + + + objectQuerySingle(castShape, convexFromTrans,convexToTrans, + collisionObject, + childCollisionShape, + childWorldTrans, + my_cb, allowedPenetration); + // restore + collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape); + } + } + } + } +} + + +struct btSingleRayCallback : public btBroadphaseRayCallback +{ + + btVector3 m_rayFromWorld; + btVector3 m_rayToWorld; + btTransform m_rayFromTrans; + btTransform m_rayToTrans; + btVector3 m_hitNormal; + + const btCollisionWorld* m_world; + btCollisionWorld::RayResultCallback& m_resultCallback; + + btSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btCollisionWorld* world,btCollisionWorld::RayResultCallback& resultCallback) + :m_rayFromWorld(rayFromWorld), + m_rayToWorld(rayToWorld), + m_world(world), + m_resultCallback(resultCallback) + { + m_rayFromTrans.setIdentity(); + m_rayFromTrans.setOrigin(m_rayFromWorld); + m_rayToTrans.setIdentity(); + m_rayToTrans.setOrigin(m_rayToWorld); + + btVector3 rayDir = (rayToWorld-rayFromWorld); + + rayDir.normalize (); + ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT + m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0]; + m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1]; + m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2]; + m_signs[0] = m_rayDirectionInverse[0] < 0.0; + m_signs[1] = m_rayDirectionInverse[1] < 0.0; + m_signs[2] = m_rayDirectionInverse[2] < 0.0; + + m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld); + + } + + + + virtual bool process(const btBroadphaseProxy* proxy) + { + ///terminate further ray tests, once the closestHitFraction reached zero + if (m_resultCallback.m_closestHitFraction == btScalar(0.f)) + return false; + + btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; + + //only perform raycast if filterMask matches + if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) + { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + //btVector3 collisionObjectAabbMin,collisionObjectAabbMax; +#if 0 +#ifdef RECALCULATE_AABB + btVector3 collisionObjectAabbMin,collisionObjectAabbMax; + collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); +#else + //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax); + const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin; + const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax; +#endif +#endif + //btScalar hitLambda = m_resultCallback.m_closestHitFraction; + //culling already done by broadphase + //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal)) + { + m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + m_resultCallback); + } + } + return true; + } +}; + +void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const +{ + //BT_PROFILE("rayTest"); + /// use the broadphase to accelerate the search for objects, based on their aabb + /// and for each object with ray-aabb overlap, perform an exact ray test + btSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback); + +#ifndef USE_BRUTEFORCE_RAYBROADPHASE + m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB); +#else + for (int i=0;igetNumCollisionObjects();i++) + { + rayCB.process(m_collisionObjects[i]->getBroadphaseHandle()); + } +#endif //USE_BRUTEFORCE_RAYBROADPHASE + +} + + +struct btSingleSweepCallback : public btBroadphaseRayCallback +{ + + btTransform m_convexFromTrans; + btTransform m_convexToTrans; + btVector3 m_hitNormal; + const btCollisionWorld* m_world; + btCollisionWorld::ConvexResultCallback& m_resultCallback; + btScalar m_allowedCcdPenetration; + const btConvexShape* m_castShape; + + + btSingleSweepCallback(const btConvexShape* castShape, const btTransform& convexFromTrans,const btTransform& convexToTrans,const btCollisionWorld* world,btCollisionWorld::ConvexResultCallback& resultCallback,btScalar allowedPenetration) + :m_convexFromTrans(convexFromTrans), + m_convexToTrans(convexToTrans), + m_world(world), + m_resultCallback(resultCallback), + m_allowedCcdPenetration(allowedPenetration), + m_castShape(castShape) + { + btVector3 unnormalizedRayDir = (m_convexToTrans.getOrigin()-m_convexFromTrans.getOrigin()); + btVector3 rayDir = unnormalizedRayDir.normalized(); + ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT + m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0]; + m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1]; + m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2]; + m_signs[0] = m_rayDirectionInverse[0] < 0.0; + m_signs[1] = m_rayDirectionInverse[1] < 0.0; + m_signs[2] = m_rayDirectionInverse[2] < 0.0; + + m_lambda_max = rayDir.dot(unnormalizedRayDir); + + } + + virtual bool process(const btBroadphaseProxy* proxy) + { + ///terminate further convex sweep tests, once the closestHitFraction reached zero + if (m_resultCallback.m_closestHitFraction == btScalar(0.f)) + return false; + + btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; + + //only perform raycast if filterMask matches + if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + m_world->objectQuerySingle(m_castShape, m_convexFromTrans,m_convexToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + m_resultCallback, + m_allowedCcdPenetration); + } + + return true; + } +}; + + + +void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const +{ + + BT_PROFILE("convexSweepTest"); + /// use the broadphase to accelerate the search for objects, based on their aabb + /// and for each object with ray-aabb overlap, perform an exact ray test + /// unfortunately the implementation for rayTest and convexSweepTest duplicated, albeit practically identical + + + + btTransform convexFromTrans,convexToTrans; + convexFromTrans = convexFromWorld; + convexToTrans = convexToWorld; + btVector3 castShapeAabbMin, castShapeAabbMax; + /* Compute AABB that encompasses angular movement */ + { + btVector3 linVel, angVel; + btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel); + btVector3 zeroLinVel; + zeroLinVel.setValue(0,0,0); + btTransform R; + R.setIdentity (); + R.setRotation (convexFromTrans.getRotation()); + castShape->calculateTemporalAabb (R, zeroLinVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax); + } + +#ifndef USE_BRUTEFORCE_RAYBROADPHASE + + btSingleSweepCallback convexCB(castShape,convexFromWorld,convexToWorld,this,resultCallback,allowedCcdPenetration); + + m_broadphasePairCache->rayTest(convexFromTrans.getOrigin(),convexToTrans.getOrigin(),convexCB,castShapeAabbMin,castShapeAabbMax); + +#else + /// go over all objects, and if the ray intersects their aabb + cast shape aabb, + // do a ray-shape query using convexCaster (CCD) + int i; + for (i=0;igetBroadphaseHandle())) { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + btVector3 collisionObjectAabbMin,collisionObjectAabbMax; + collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); + AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax); + btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing + btVector3 hitNormal; + if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) + { + objectQuerySingle(castShape, convexFromTrans,convexToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + resultCallback, + allowedCcdPenetration); + } + } + } +#endif //USE_BRUTEFORCE_RAYBROADPHASE +} + + + +struct btBridgedManifoldResult : public btManifoldResult +{ + + btCollisionWorld::ContactResultCallback& m_resultCallback; + + btBridgedManifoldResult( btCollisionObject* obj0,btCollisionObject* obj1,btCollisionWorld::ContactResultCallback& resultCallback ) + :btManifoldResult(obj0,obj1), + m_resultCallback(resultCallback) + { + } + + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) + { + bool isSwapped = m_manifoldPtr->getBody0() != m_body0; + btVector3 pointA = pointInWorld + normalOnBInWorld * depth; + btVector3 localA; + btVector3 localB; + if (isSwapped) + { + localA = m_rootTransB.invXform(pointA ); + localB = m_rootTransA.invXform(pointInWorld); + } else + { + localA = m_rootTransA.invXform(pointA ); + localB = m_rootTransB.invXform(pointInWorld); + } + + btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth); + newPt.m_positionWorldOnA = pointA; + newPt.m_positionWorldOnB = pointInWorld; + + //BP mod, store contact triangles. + if (isSwapped) + { + newPt.m_partId0 = m_partId1; + newPt.m_partId1 = m_partId0; + newPt.m_index0 = m_index1; + newPt.m_index1 = m_index0; + } else + { + newPt.m_partId0 = m_partId0; + newPt.m_partId1 = m_partId1; + newPt.m_index0 = m_index0; + newPt.m_index1 = m_index1; + } + + //experimental feature info, for per-triangle material etc. + btCollisionObject* obj0 = isSwapped? m_body1 : m_body0; + btCollisionObject* obj1 = isSwapped? m_body0 : m_body1; + m_resultCallback.addSingleResult(newPt,obj0,newPt.m_partId0,newPt.m_index0,obj1,newPt.m_partId1,newPt.m_index1); + + } + +}; + + + +struct btSingleContactCallback : public btBroadphaseAabbCallback +{ + + btCollisionObject* m_collisionObject; + btCollisionWorld* m_world; + btCollisionWorld::ContactResultCallback& m_resultCallback; + + + btSingleContactCallback(btCollisionObject* collisionObject, btCollisionWorld* world,btCollisionWorld::ContactResultCallback& resultCallback) + :m_collisionObject(collisionObject), + m_world(world), + m_resultCallback(resultCallback) + { + } + + virtual bool process(const btBroadphaseProxy* proxy) + { + btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; + if (collisionObject == m_collisionObject) + return true; + + //only perform raycast if filterMask matches + if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) + { + btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(m_collisionObject,collisionObject); + if (algorithm) + { + btBridgedManifoldResult contactPointResult(m_collisionObject,collisionObject, m_resultCallback); + //discrete collision detection query + algorithm->processCollision(m_collisionObject,collisionObject, m_world->getDispatchInfo(),&contactPointResult); + + algorithm->~btCollisionAlgorithm(); + m_world->getDispatcher()->freeCollisionAlgorithm(algorithm); + } + } + return true; + } +}; + + +///contactTest performs a discrete collision test against all objects in the btCollisionWorld, and calls the resultCallback. +///it reports one or more contact points for every overlapping object (including the one with deepest penetration) +void btCollisionWorld::contactTest( btCollisionObject* colObj, ContactResultCallback& resultCallback) +{ + btVector3 aabbMin,aabbMax; + colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(),aabbMin,aabbMax); + btSingleContactCallback contactCB(colObj,this,resultCallback); + + m_broadphasePairCache->aabbTest(aabbMin,aabbMax,contactCB); +} + + +///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected. +///it reports one or more contact points (including the one with deepest penetration) +void btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback) +{ + btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(colObjA,colObjB); + if (algorithm) + { + btBridgedManifoldResult contactPointResult(colObjA,colObjB, resultCallback); + //discrete collision detection query + algorithm->processCollision(colObjA,colObjB, getDispatchInfo(),&contactPointResult); + + algorithm->~btCollisionAlgorithm(); + getDispatcher()->freeCollisionAlgorithm(algorithm); + } + +} + + + + +class DebugDrawcallback : public btTriangleCallback, public btInternalTriangleIndexCallback +{ + btIDebugDraw* m_debugDrawer; + btVector3 m_color; + btTransform m_worldTrans; + +public: + + DebugDrawcallback(btIDebugDraw* debugDrawer,const btTransform& worldTrans,const btVector3& color) : + m_debugDrawer(debugDrawer), + m_color(color), + m_worldTrans(worldTrans) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + processTriangle(triangle,partId,triangleIndex); + } + + virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex) + { + (void)partId; + (void)triangleIndex; + + btVector3 wv0,wv1,wv2; + wv0 = m_worldTrans*triangle[0]; + wv1 = m_worldTrans*triangle[1]; + wv2 = m_worldTrans*triangle[2]; + btVector3 center = (wv0+wv1+wv2)*btScalar(1./3.); + + if (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawNormals ) + { + btVector3 normal = (wv1-wv0).cross(wv2-wv0); + normal.normalize(); + btVector3 normalColor(1,1,0); + m_debugDrawer->drawLine(center,center+normal,normalColor); + } + m_debugDrawer->drawLine(wv0,wv1,m_color); + m_debugDrawer->drawLine(wv1,wv2,m_color); + m_debugDrawer->drawLine(wv2,wv0,m_color); + } +}; + + +void btCollisionWorld::debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color) +{ + // Draw a small simplex at the center of the object + getDebugDrawer()->drawTransform(worldTransform,1); + + if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) + { + const btCompoundShape* compoundShape = static_cast(shape); + for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* colShape = compoundShape->getChildShape(i); + debugDrawObject(worldTransform*childTrans,colShape,color); + } + + } else + { + + /// for polyhedral shapes + if (shape->isPolyhedral()) + { + btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape; + + int i; + if (polyshape->getConvexPolyhedron()) + { + const btConvexPolyhedron* poly = polyshape->getConvexPolyhedron(); + for (i=0;im_faces.size();i++) + { + btVector3 centroid(0,0,0); + int numVerts = poly->m_faces[i].m_indices.size(); + if (numVerts) + { + int lastV = poly->m_faces[i].m_indices[numVerts-1]; + for (int v=0;vm_faces[i].m_indices.size();v++) + { + int curVert = poly->m_faces[i].m_indices[v]; + centroid+=poly->m_vertices[curVert]; + getDebugDrawer()->drawLine(worldTransform*poly->m_vertices[lastV],worldTransform*poly->m_vertices[curVert],color); + lastV = curVert; + } + } + centroid*= btScalar(1.f)/btScalar(numVerts); + if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawNormals) + { + btVector3 normalColor(1,1,0); + btVector3 faceNormal(poly->m_faces[i].m_plane[0],poly->m_faces[i].m_plane[1],poly->m_faces[i].m_plane[2]); + getDebugDrawer()->drawLine(worldTransform*centroid,worldTransform*(centroid+faceNormal),normalColor); + } + + } + + + } else + { + for (i=0;igetNumEdges();i++) + { + btVector3 a,b; + polyshape->getEdge(i,a,b); + btVector3 wa = worldTransform * a; + btVector3 wb = worldTransform * b; + getDebugDrawer()->drawLine(wa,wb,color); + } + } + + + } + else + { + switch (shape->getShapeType()) + { + + case BOX_SHAPE_PROXYTYPE: + { + const btBoxShape* boxShape = static_cast(shape); + btVector3 halfExtents = boxShape->getHalfExtentsWithMargin(); + getDebugDrawer()->drawBox(-halfExtents,halfExtents,worldTransform,color); + break; + } + + case SPHERE_SHAPE_PROXYTYPE: + { + const btSphereShape* sphereShape = static_cast(shape); + btScalar radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin + + getDebugDrawer()->drawSphere(radius, worldTransform, color); + break; + } + case MULTI_SPHERE_SHAPE_PROXYTYPE: + { + const btMultiSphereShape* multiSphereShape = static_cast(shape); + + btTransform childTransform; + childTransform.setIdentity(); + + for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--) + { + childTransform.setOrigin(multiSphereShape->getSpherePosition(i)); + getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform*childTransform, color); + } + + break; + } + case CAPSULE_SHAPE_PROXYTYPE: + { + const btCapsuleShape* capsuleShape = static_cast(shape); + + btScalar radius = capsuleShape->getRadius(); + btScalar halfHeight = capsuleShape->getHalfHeight(); + + int upAxis = capsuleShape->getUpAxis(); + getDebugDrawer()->drawCapsule(radius, halfHeight, upAxis, worldTransform, color); + break; + } + case CONE_SHAPE_PROXYTYPE: + { + const btConeShape* coneShape = static_cast(shape); + btScalar radius = coneShape->getRadius();//+coneShape->getMargin(); + btScalar height = coneShape->getHeight();//+coneShape->getMargin(); + + int upAxis= coneShape->getConeUpIndex(); + getDebugDrawer()->drawCone(radius, height, upAxis, worldTransform, color); + break; + + } + case CYLINDER_SHAPE_PROXYTYPE: + { + const btCylinderShape* cylinder = static_cast(shape); + int upAxis = cylinder->getUpAxis(); + btScalar radius = cylinder->getRadius(); + btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis]; + getDebugDrawer()->drawCylinder(radius, halfHeight, upAxis, worldTransform, color); + break; + } + + case STATIC_PLANE_PROXYTYPE: + { + const btStaticPlaneShape* staticPlaneShape = static_cast(shape); + btScalar planeConst = staticPlaneShape->getPlaneConstant(); + const btVector3& planeNormal = staticPlaneShape->getPlaneNormal(); + getDebugDrawer()->drawPlane(planeNormal, planeConst,worldTransform, color); + break; + + } + default: + { + + if (shape->isConcave()) + { + btConcaveShape* concaveMesh = (btConcaveShape*) shape; + + ///@todo pass camera, for some culling? no -> we are not a graphics lib + btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + + DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); + concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax); + + } + + if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE) + { + btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*) shape; + //todo: pass camera for some culling + btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + //DebugDrawcallback drawCallback; + DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); + convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); + } + + + + } + } + } + } +} + + +void btCollisionWorld::debugDrawWorld() +{ + if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints) + { + int numManifolds = getDispatcher()->getNumManifolds(); + btVector3 color(1,0.65,0); + for (int i=0;igetManifoldByIndexInternal(i); + //btCollisionObject* obA = static_cast(contactManifold->getBody0()); + //btCollisionObject* obB = static_cast(contactManifold->getBody1()); + + int numContacts = contactManifold->getNumContacts(); + for (int j=0;jgetContactPoint(j); + getDebugDrawer()->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); + } + } + } + + if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb))) + { + int i; + + for ( i=0;igetCollisionFlags() & btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT)==0) + { + if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe)) + { + btVector3 color(btScalar(1.),btScalar(1.),btScalar(1.)); + switch(colObj->getActivationState()) + { + case ACTIVE_TAG: + color = btVector3(btScalar(1.),btScalar(1.),btScalar(1.)); break; + case ISLAND_SLEEPING: + color = btVector3(btScalar(0.),btScalar(1.),btScalar(0.));break; + case WANTS_DEACTIVATION: + color = btVector3(btScalar(0.),btScalar(1.),btScalar(1.));break; + case DISABLE_DEACTIVATION: + color = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));break; + case DISABLE_SIMULATION: + color = btVector3(btScalar(1.),btScalar(1.),btScalar(0.));break; + default: + { + color = btVector3(btScalar(1),btScalar(0.),btScalar(0.)); + } + }; + + debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color); + } + if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + btVector3 minAabb,maxAabb; + btVector3 colorvec(1,0,0); + colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); + btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold); + minAabb -= contactThreshold; + maxAabb += contactThreshold; + + btVector3 minAabb2,maxAabb2; + + if(getDispatchInfo().m_useContinuous && colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject()) + { + colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2); + minAabb2 -= contactThreshold; + maxAabb2 += contactThreshold; + minAabb.setMin(minAabb2); + maxAabb.setMax(maxAabb2); + } + + m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec); + } + } + + } + } +} + + +void btCollisionWorld::serializeCollisionObjects(btSerializer* serializer) +{ + int i; + //serialize all collision objects + for (i=0;igetInternalType() == btCollisionObject::CO_COLLISION_OBJECT) + { + colObj->serializeSingleObject(serializer); + } + } + + ///keep track of shapes already serialized + btHashMap serializedShapes; + + for (i=0;igetCollisionShape(); + + if (!serializedShapes.find(shape)) + { + serializedShapes.insert(shape,shape); + shape->serializeSingleShape(serializer); + } + } + +} + + +void btCollisionWorld::serialize(btSerializer* serializer) +{ + + serializer->startSerialization(); + + serializeCollisionObjects(serializer); + + serializer->finishSerialization(); +} + diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/src/BulletCollision/CollisionDispatch/btCollisionWorld.h new file mode 100644 index 0000000..0a92d2d --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.h @@ -0,0 +1,509 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://bulletphysics.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. +*/ + + +/** + * @mainpage Bullet Documentation + * + * @section intro_sec Introduction + * Bullet Collision Detection & Physics SDK + * + * Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ). + * + * The main documentation is Bullet_User_Manual.pdf, included in the source code distribution. + * There is the Physics Forum for feedback and general Collision Detection and Physics discussions. + * Please visit http://www.bulletphysics.com + * + * @section install_sec Installation + * + * @subsection step1 Step 1: Download + * You can download the Bullet Physics Library from the Google Code repository: http://code.google.com/p/bullet/downloads/list + * + * @subsection step2 Step 2: Building + * Bullet main build system for all platforms is cmake, you can download http://www.cmake.org + * cmake can autogenerate projectfiles for Microsoft Visual Studio, Apple Xcode, KDevelop and Unix Makefiles. + * The easiest is to run the CMake cmake-gui graphical user interface and choose the options and generate projectfiles. + * You can also use cmake in the command-line. Here are some examples for various platforms: + * cmake . -G "Visual Studio 9 2008" + * cmake . -G Xcode + * cmake . -G "Unix Makefiles" + * Although cmake is recommended, you can also use autotools for UNIX: ./autogen.sh ./configure to create a Makefile and then run make. + * + * @subsection step3 Step 3: Testing demos + * Try to run and experiment with BasicDemo executable as a starting point. + * Bullet can be used in several ways, as Full Rigid Body simulation, as Collision Detector Library or Low Level / Snippets like the GJK Closest Point calculation. + * The Dependencies can be seen in this documentation under Directories + * + * @subsection step4 Step 4: Integrating in your application, full Rigid Body and Soft Body simulation + * Check out BasicDemo how to create a btDynamicsWorld, btRigidBody and btCollisionShape, Stepping the simulation and synchronizing your graphics object transform. + * Check out SoftDemo how to use soft body dynamics, using btSoftRigidDynamicsWorld. + * @subsection step5 Step 5 : Integrate the Collision Detection Library (without Dynamics and other Extras) + * Bullet Collision Detection can also be used without the Dynamics/Extras. + * Check out btCollisionWorld and btCollisionObject, and the CollisionInterfaceDemo. + * @subsection step6 Step 6 : Use Snippets like the GJK Closest Point calculation. + * Bullet has been designed in a modular way keeping dependencies to a minimum. The ConvexHullDistance demo demonstrates direct use of btGjkPairDetector. + * + * @section copyright Copyright + * For up-to-data information and copyright and contributors list check out the Bullet_User_Manual.pdf + * + */ + + + +#ifndef BT_COLLISION_WORLD_H +#define BT_COLLISION_WORLD_H + +class btStackAlloc; +class btCollisionShape; +class btConvexShape; +class btBroadphaseInterface; +class btSerializer; + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "btCollisionObject.h" +#include "btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "LinearMath/btAlignedObjectArray.h" + +///CollisionWorld is interface and container for the collision detection +class btCollisionWorld +{ + + +protected: + + btAlignedObjectArray m_collisionObjects; + + btDispatcher* m_dispatcher1; + + btDispatcherInfo m_dispatchInfo; + + btStackAlloc* m_stackAlloc; + + btBroadphaseInterface* m_broadphasePairCache; + + btIDebugDraw* m_debugDrawer; + + ///m_forceUpdateAllAabbs can be set to false as an optimization to only update active object AABBs + ///it is true by default, because it is error-prone (setting the position of static objects wouldn't update their AABB) + bool m_forceUpdateAllAabbs; + + void serializeCollisionObjects(btSerializer* serializer); + +public: + + //this constructor doesn't own the dispatcher and paircache/broadphase + btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration); + + virtual ~btCollisionWorld(); + + void setBroadphase(btBroadphaseInterface* pairCache) + { + m_broadphasePairCache = pairCache; + } + + const btBroadphaseInterface* getBroadphase() const + { + return m_broadphasePairCache; + } + + btBroadphaseInterface* getBroadphase() + { + return m_broadphasePairCache; + } + + btOverlappingPairCache* getPairCache() + { + return m_broadphasePairCache->getOverlappingPairCache(); + } + + + btDispatcher* getDispatcher() + { + return m_dispatcher1; + } + + const btDispatcher* getDispatcher() const + { + return m_dispatcher1; + } + + void updateSingleAabb(btCollisionObject* colObj); + + virtual void updateAabbs(); + + virtual void setDebugDrawer(btIDebugDraw* debugDrawer) + { + m_debugDrawer = debugDrawer; + } + + virtual btIDebugDraw* getDebugDrawer() + { + return m_debugDrawer; + } + + virtual void debugDrawWorld(); + + virtual void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color); + + + ///LocalShapeInfo gives extra information for complex shapes + ///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart + struct LocalShapeInfo + { + int m_shapePart; + int m_triangleIndex; + + //const btCollisionShape* m_shapeTemp; + //const btTransform* m_shapeLocalTransform; + }; + + struct LocalRayResult + { + LocalRayResult(btCollisionObject* collisionObject, + LocalShapeInfo* localShapeInfo, + const btVector3& hitNormalLocal, + btScalar hitFraction) + :m_collisionObject(collisionObject), + m_localShapeInfo(localShapeInfo), + m_hitNormalLocal(hitNormalLocal), + m_hitFraction(hitFraction) + { + } + + btCollisionObject* m_collisionObject; + LocalShapeInfo* m_localShapeInfo; + btVector3 m_hitNormalLocal; + btScalar m_hitFraction; + + }; + + ///RayResultCallback is used to report new raycast results + struct RayResultCallback + { + btScalar m_closestHitFraction; + btCollisionObject* m_collisionObject; + short int m_collisionFilterGroup; + short int m_collisionFilterMask; + //@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback + unsigned int m_flags; + + virtual ~RayResultCallback() + { + } + bool hasHit() const + { + return (m_collisionObject != 0); + } + + RayResultCallback() + :m_closestHitFraction(btScalar(1.)), + m_collisionObject(0), + m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), + m_collisionFilterMask(btBroadphaseProxy::AllFilter), + //@BP Mod + m_flags(0) + { + } + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0; + collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask); + return collides; + } + + + virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0; + }; + + struct ClosestRayResultCallback : public RayResultCallback + { + ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld) + :m_rayFromWorld(rayFromWorld), + m_rayToWorld(rayToWorld) + { + } + + btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction + btVector3 m_rayToWorld; + + btVector3 m_hitNormalWorld; + btVector3 m_hitPointWorld; + + virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) + { + //caller already does the filter on the m_closestHitFraction + btAssert(rayResult.m_hitFraction <= m_closestHitFraction); + + m_closestHitFraction = rayResult.m_hitFraction; + m_collisionObject = rayResult.m_collisionObject; + if (normalInWorldSpace) + { + m_hitNormalWorld = rayResult.m_hitNormalLocal; + } else + { + ///need to transform normal into worldspace + m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; + } + m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction); + return rayResult.m_hitFraction; + } + }; + + struct AllHitsRayResultCallback : public RayResultCallback + { + AllHitsRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld) + :m_rayFromWorld(rayFromWorld), + m_rayToWorld(rayToWorld) + { + } + + btAlignedObjectArray m_collisionObjects; + + btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction + btVector3 m_rayToWorld; + + btAlignedObjectArray m_hitNormalWorld; + btAlignedObjectArray m_hitPointWorld; + btAlignedObjectArray m_hitFractions; + + virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) + { + m_collisionObject = rayResult.m_collisionObject; + m_collisionObjects.push_back(rayResult.m_collisionObject); + btVector3 hitNormalWorld; + if (normalInWorldSpace) + { + hitNormalWorld = rayResult.m_hitNormalLocal; + } else + { + ///need to transform normal into worldspace + hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; + } + m_hitNormalWorld.push_back(hitNormalWorld); + btVector3 hitPointWorld; + hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction); + m_hitPointWorld.push_back(hitPointWorld); + m_hitFractions.push_back(rayResult.m_hitFraction); + return m_closestHitFraction; + } + }; + + + struct LocalConvexResult + { + LocalConvexResult(btCollisionObject* hitCollisionObject, + LocalShapeInfo* localShapeInfo, + const btVector3& hitNormalLocal, + const btVector3& hitPointLocal, + btScalar hitFraction + ) + :m_hitCollisionObject(hitCollisionObject), + m_localShapeInfo(localShapeInfo), + m_hitNormalLocal(hitNormalLocal), + m_hitPointLocal(hitPointLocal), + m_hitFraction(hitFraction) + { + } + + btCollisionObject* m_hitCollisionObject; + LocalShapeInfo* m_localShapeInfo; + btVector3 m_hitNormalLocal; + btVector3 m_hitPointLocal; + btScalar m_hitFraction; + }; + + ///RayResultCallback is used to report new raycast results + struct ConvexResultCallback + { + btScalar m_closestHitFraction; + short int m_collisionFilterGroup; + short int m_collisionFilterMask; + + ConvexResultCallback() + :m_closestHitFraction(btScalar(1.)), + m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), + m_collisionFilterMask(btBroadphaseProxy::AllFilter) + { + } + + virtual ~ConvexResultCallback() + { + } + + bool hasHit() const + { + return (m_closestHitFraction < btScalar(1.)); + } + + + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0; + collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask); + return collides; + } + + virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) = 0; + }; + + struct ClosestConvexResultCallback : public ConvexResultCallback + { + ClosestConvexResultCallback(const btVector3& convexFromWorld,const btVector3& convexToWorld) + :m_convexFromWorld(convexFromWorld), + m_convexToWorld(convexToWorld), + m_hitCollisionObject(0) + { + } + + btVector3 m_convexFromWorld;//used to calculate hitPointWorld from hitFraction + btVector3 m_convexToWorld; + + btVector3 m_hitNormalWorld; + btVector3 m_hitPointWorld; + btCollisionObject* m_hitCollisionObject; + + virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) + { +//caller already does the filter on the m_closestHitFraction + btAssert(convexResult.m_hitFraction <= m_closestHitFraction); + + m_closestHitFraction = convexResult.m_hitFraction; + m_hitCollisionObject = convexResult.m_hitCollisionObject; + if (normalInWorldSpace) + { + m_hitNormalWorld = convexResult.m_hitNormalLocal; + } else + { + ///need to transform normal into worldspace + m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal; + } + m_hitPointWorld = convexResult.m_hitPointLocal; + return convexResult.m_hitFraction; + } + }; + + ///ContactResultCallback is used to report contact points + struct ContactResultCallback + { + short int m_collisionFilterGroup; + short int m_collisionFilterMask; + + ContactResultCallback() + :m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), + m_collisionFilterMask(btBroadphaseProxy::AllFilter) + { + } + + virtual ~ContactResultCallback() + { + } + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0; + collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask); + return collides; + } + + virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1) = 0; + }; + + + + int getNumCollisionObjects() const + { + return int(m_collisionObjects.size()); + } + + /// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback + /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback. + virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const; + + /// convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback + /// This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback. + void convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = btScalar(0.)) const; + + ///contactTest performs a discrete collision test between colObj against all objects in the btCollisionWorld, and calls the resultCallback. + ///it reports one or more contact points for every overlapping object (including the one with deepest penetration) + void contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback); + + ///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected. + ///it reports one or more contact points (including the one with deepest penetration) + void contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback); + + + /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. + /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape. + /// This allows more customization. + static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + RayResultCallback& resultCallback); + + /// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest. + static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + ConvexResultCallback& resultCallback, btScalar allowedPenetration); + + virtual void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter); + + btCollisionObjectArray& getCollisionObjectArray() + { + return m_collisionObjects; + } + + const btCollisionObjectArray& getCollisionObjectArray() const + { + return m_collisionObjects; + } + + + virtual void removeCollisionObject(btCollisionObject* collisionObject); + + virtual void performDiscreteCollisionDetection(); + + btDispatcherInfo& getDispatchInfo() + { + return m_dispatchInfo; + } + + const btDispatcherInfo& getDispatchInfo() const + { + return m_dispatchInfo; + } + + bool getForceUpdateAllAabbs() const + { + return m_forceUpdateAllAabbs; + } + void setForceUpdateAllAabbs( bool forceUpdateAllAabbs) + { + m_forceUpdateAllAabbs = forceUpdateAllAabbs; + } + + ///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (Bullet/Demos/SerializeDemo) + virtual void serialize(btSerializer* serializer); + +}; + + +#endif //BT_COLLISION_WORLD_H diff --git a/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp new file mode 100644 index 0000000..54889a6 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp @@ -0,0 +1,353 @@ +/* +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 "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/BroadphaseCollision/btDbvt.h" +#include "LinearMath/btIDebugDraw.h" +#include "LinearMath/btAabbUtil2.h" +#include "btManifoldResult.h" + +btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) +:btActivatingCollisionAlgorithm(ci,body0,body1), +m_isSwapped(isSwapped), +m_sharedManifold(ci.m_manifold) +{ + m_ownsManifold = false; + + btCollisionObject* colObj = m_isSwapped? body1 : body0; + btAssert (colObj->getCollisionShape()->isCompound()); + + btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); + m_compoundShapeRevision = compoundShape->getUpdateRevision(); + + preallocateChildAlgorithms(body0,body1); +} + +void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1) +{ + btCollisionObject* colObj = m_isSwapped? body1 : body0; + btCollisionObject* otherObj = m_isSwapped? body0 : body1; + btAssert (colObj->getCollisionShape()->isCompound()); + + btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); + + int numChildren = compoundShape->getNumChildShapes(); + int i; + + m_childCollisionAlgorithms.resize(numChildren); + for (i=0;igetDynamicAabbTree()) + { + m_childCollisionAlgorithms[i] = 0; + } else + { + btCollisionShape* tmpShape = colObj->getCollisionShape(); + btCollisionShape* childShape = compoundShape->getChildShape(i); + colObj->internalSetTemporaryCollisionShape( childShape ); + m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(colObj,otherObj,m_sharedManifold); + colObj->internalSetTemporaryCollisionShape( tmpShape ); + } + } +} + +void btCompoundCollisionAlgorithm::removeChildAlgorithms() +{ + int numChildren = m_childCollisionAlgorithms.size(); + int i; + for (i=0;i~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); + } + } +} + +btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm() +{ + removeChildAlgorithms(); +} + + + + +struct btCompoundLeafCallback : btDbvt::ICollide +{ + +public: + + btCollisionObject* m_compoundColObj; + btCollisionObject* m_otherObj; + btDispatcher* m_dispatcher; + const btDispatcherInfo& m_dispatchInfo; + btManifoldResult* m_resultOut; + btCollisionAlgorithm** m_childCollisionAlgorithms; + btPersistentManifold* m_sharedManifold; + + + + + btCompoundLeafCallback (btCollisionObject* compoundObj,btCollisionObject* otherObj,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold) + :m_compoundColObj(compoundObj),m_otherObj(otherObj),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut), + m_childCollisionAlgorithms(childCollisionAlgorithms), + m_sharedManifold(sharedManifold) + { + + } + + + void ProcessChildShape(btCollisionShape* childShape,int index) + { + btAssert(index>=0); + btCompoundShape* compoundShape = static_cast(m_compoundColObj->getCollisionShape()); + btAssert(indexgetNumChildShapes()); + + + //backup + btTransform orgTrans = m_compoundColObj->getWorldTransform(); + btTransform orgInterpolationTrans = m_compoundColObj->getInterpolationWorldTransform(); + const btTransform& childTrans = compoundShape->getChildTransform(index); + btTransform newChildWorldTrans = orgTrans*childTrans ; + + //perform an AABB check first + btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; + childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0); + m_otherObj->getCollisionShape()->getAabb(m_otherObj->getWorldTransform(),aabbMin1,aabbMax1); + + if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) + { + + m_compoundColObj->setWorldTransform( newChildWorldTrans); + m_compoundColObj->setInterpolationWorldTransform(newChildWorldTrans); + + //the contactpoint is still projected back using the original inverted worldtrans + btCollisionShape* tmpShape = m_compoundColObj->getCollisionShape(); + m_compoundColObj->internalSetTemporaryCollisionShape( childShape ); + + if (!m_childCollisionAlgorithms[index]) + m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(m_compoundColObj,m_otherObj,m_sharedManifold); + + ///detect swapping case + if (m_resultOut->getBody0Internal() == m_compoundColObj) + { + m_resultOut->setShapeIdentifiersA(-1,index); + } else + { + m_resultOut->setShapeIdentifiersB(-1,index); + } + + m_childCollisionAlgorithms[index]->processCollision(m_compoundColObj,m_otherObj,m_dispatchInfo,m_resultOut); + if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + btVector3 worldAabbMin,worldAabbMax; + m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1)); + m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1)); + } + + //revert back transform + m_compoundColObj->internalSetTemporaryCollisionShape( tmpShape); + m_compoundColObj->setWorldTransform( orgTrans ); + m_compoundColObj->setInterpolationWorldTransform(orgInterpolationTrans); + } + } + void Process(const btDbvtNode* leaf) + { + int index = leaf->dataAsInt; + + btCompoundShape* compoundShape = static_cast(m_compoundColObj->getCollisionShape()); + btCollisionShape* childShape = compoundShape->getChildShape(index); + if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + btVector3 worldAabbMin,worldAabbMax; + btTransform orgTrans = m_compoundColObj->getWorldTransform(); + btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax); + m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0)); + } + ProcessChildShape(childShape,index); + + } +}; + + + + + + +void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + btCollisionObject* colObj = m_isSwapped? body1 : body0; + btCollisionObject* otherObj = m_isSwapped? body0 : body1; + + + + btAssert (colObj->getCollisionShape()->isCompound()); + btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); + + ///btCompoundShape might have changed: + ////make sure the internal child collision algorithm caches are still valid + if (compoundShape->getUpdateRevision() != m_compoundShapeRevision) + { + ///clear and update all + removeChildAlgorithms(); + + preallocateChildAlgorithms(body0,body1); + } + + + btDbvt* tree = compoundShape->getDynamicAabbTree(); + //use a dynamic aabb tree to cull potential child-overlaps + btCompoundLeafCallback callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold); + + ///we need to refresh all contact manifolds + ///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep + ///so we should add a 'refreshManifolds' in the btCollisionAlgorithm + { + int i; + btManifoldArray manifoldArray; + for (i=0;igetAllContactManifolds(manifoldArray); + for (int m=0;mgetNumContacts()) + { + resultOut->setPersistentManifold(manifoldArray[m]); + resultOut->refreshContactPoints(); + resultOut->setPersistentManifold(0);//??necessary? + } + } + manifoldArray.resize(0); + } + } + } + + if (tree) + { + + btVector3 localAabbMin,localAabbMax; + btTransform otherInCompoundSpace; + otherInCompoundSpace = colObj->getWorldTransform().inverse() * otherObj->getWorldTransform(); + otherObj->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax); + + const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); + //process all children, that overlap with the given AABB bounds + tree->collideTV(tree->m_root,bounds,callback); + + } else + { + //iterate over all children, perform an AABB check inside ProcessChildShape + int numChildren = m_childCollisionAlgorithms.size(); + int i; + for (i=0;igetChildShape(i),i); + } + } + + { + //iterate over all children, perform an AABB check inside ProcessChildShape + int numChildren = m_childCollisionAlgorithms.size(); + int i; + btManifoldArray manifoldArray; + btCollisionShape* childShape = 0; + btTransform orgTrans; + btTransform orgInterpolationTrans; + btTransform newChildWorldTrans; + btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; + + for (i=0;igetChildShape(i); + //if not longer overlapping, remove the algorithm + orgTrans = colObj->getWorldTransform(); + orgInterpolationTrans = colObj->getInterpolationWorldTransform(); + const btTransform& childTrans = compoundShape->getChildTransform(i); + newChildWorldTrans = orgTrans*childTrans ; + + //perform an AABB check first + childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0); + otherObj->getCollisionShape()->getAabb(otherObj->getWorldTransform(),aabbMin1,aabbMax1); + + if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) + { + m_childCollisionAlgorithms[i]->~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); + m_childCollisionAlgorithms[i] = 0; + } + } + } + } +} + +btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + + btCollisionObject* colObj = m_isSwapped? body1 : body0; + btCollisionObject* otherObj = m_isSwapped? body0 : body1; + + btAssert (colObj->getCollisionShape()->isCompound()); + + btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); + + //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps + //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals + //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means: + //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1 + //then use each overlapping node AABB against Tree0 + //and vise versa. + + btScalar hitFraction = btScalar(1.); + + int numChildren = m_childCollisionAlgorithms.size(); + int i; + btTransform orgTrans; + btScalar frac; + for (i=0;igetChildShape(i); + + //backup + orgTrans = colObj->getWorldTransform(); + + const btTransform& childTrans = compoundShape->getChildTransform(i); + //btTransform newChildWorldTrans = orgTrans*childTrans ; + colObj->setWorldTransform( orgTrans*childTrans ); + + btCollisionShape* tmpShape = colObj->getCollisionShape(); + colObj->internalSetTemporaryCollisionShape( childShape ); + frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut); + if (fracinternalSetTemporaryCollisionShape( tmpShape); + colObj->setWorldTransform( orgTrans); + } + return hitFraction; + +} + + + diff --git a/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h new file mode 100644 index 0000000..4045749 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h @@ -0,0 +1,86 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COMPOUND_COLLISION_ALGORITHM_H +#define BT_COMPOUND_COLLISION_ALGORITHM_H + +#include "btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" + +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +class btDispatcher; +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "btCollisionCreateFunc.h" +#include "LinearMath/btAlignedObjectArray.h" +class btDispatcher; +class btCollisionObject; + +/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes +class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ + btAlignedObjectArray m_childCollisionAlgorithms; + bool m_isSwapped; + + class btPersistentManifold* m_sharedManifold; + bool m_ownsManifold; + + int m_compoundShapeRevision;//to keep track of changes, so that childAlgorithm array can be updated + + void removeChildAlgorithms(); + + void preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1); + +public: + + btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); + + virtual ~btCompoundCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + int i; + for (i=0;igetAllContactManifolds(manifoldArray); + } + } + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm)); + return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,false); + } + }; + + struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm)); + return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,true); + } + }; + +}; + +#endif //BT_COMPOUND_COLLISION_ALGORITHM_H diff --git a/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp b/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp new file mode 100644 index 0000000..db7f884 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp @@ -0,0 +1,247 @@ +/* +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 "btConvex2dConvex2dAlgorithm.h" + +//#include +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" + + +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" + +#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" + + + +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + +#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" + +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" + + +btConvex2dConvex2dAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) +{ + m_numPerturbationIterations = 0; + m_minimumPointsPerturbationThreshold = 3; + m_simplexSolver = simplexSolver; + m_pdSolver = pdSolver; +} + +btConvex2dConvex2dAlgorithm::CreateFunc::~CreateFunc() +{ +} + +btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold) +: btActivatingCollisionAlgorithm(ci,body0,body1), +m_simplexSolver(simplexSolver), +m_pdSolver(pdSolver), +m_ownManifold (false), +m_manifoldPtr(mf), +m_lowLevelOfDetail(false), + m_numPerturbationIterations(numPerturbationIterations), +m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold) +{ + (void)body0; + (void)body1; +} + + + + +btConvex2dConvex2dAlgorithm::~btConvex2dConvex2dAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btConvex2dConvex2dAlgorithm ::setLowLevelOfDetail(bool useLowLevel) +{ + m_lowLevelOfDetail = useLowLevel; +} + + + +extern btScalar gContactBreakingThreshold; + + +// +// Convex-Convex collision algorithm +// +void btConvex2dConvex2dAlgorithm ::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + + if (!m_manifoldPtr) + { + //swapped? + m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1); + m_ownManifold = true; + } + resultOut->setPersistentManifold(m_manifoldPtr); + + //comment-out next line to test multi-contact generation + //resultOut->getPersistentManifold()->clearManifold(); + + + btConvexShape* min0 = static_cast(body0->getCollisionShape()); + btConvexShape* min1 = static_cast(body1->getCollisionShape()); + + btVector3 normalOnB; + btVector3 pointOnBWorld; + + { + + + btGjkPairDetector::ClosestPointInput input; + + btGjkPairDetector gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver); + //TODO: if (dispatchInfo.m_useContinuous) + gjkPairDetector.setMinkowskiA(min0); + gjkPairDetector.setMinkowskiB(min1); + + { + input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold(); + input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared; + } + + input.m_stackAlloc = dispatchInfo.m_stackAllocator; + input.m_transformA = body0->getWorldTransform(); + input.m_transformB = body1->getWorldTransform(); + + gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + + btVector3 v0,v1; + btVector3 sepNormalWorldSpace; + + } + + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } + +} + + + + +btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + ///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold + + ///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold + ///col0->m_worldTransform, + btScalar resultFraction = btScalar(1.); + + + btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2(); + btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2(); + + if (squareMot0 < col0->getCcdSquareMotionThreshold() && + squareMot1 < col1->getCcdSquareMotionThreshold()) + return resultFraction; + + + //An adhoc way of testing the Continuous Collision Detection algorithms + //One object is approximated as a sphere, to simplify things + //Starting in penetration should report no time of impact + //For proper CCD, better accuracy and handling of 'allowed' penetration should be added + //also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies) + + + /// Convex0 against sphere for Convex1 + { + btConvexShape* convex0 = static_cast(col0->getCollisionShape()); + + btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation + btConvexCast::CastResult result; + btVoronoiSimplexSolver voronoiSimplex; + //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex); + ///Simplification, one object is simplified as a sphere + btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex); + //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0); + if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(), + col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result)) + { + + //store result.m_fraction in both bodies + + if (col0->getHitFraction()> result.m_fraction) + col0->setHitFraction( result.m_fraction ); + + if (col1->getHitFraction() > result.m_fraction) + col1->setHitFraction( result.m_fraction); + + if (resultFraction > result.m_fraction) + resultFraction = result.m_fraction; + + } + + + + + } + + /// Sphere (for convex0) against Convex1 + { + btConvexShape* convex1 = static_cast(col1->getCollisionShape()); + + btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation + btConvexCast::CastResult result; + btVoronoiSimplexSolver voronoiSimplex; + //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex); + ///Simplification, one object is simplified as a sphere + btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex); + //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0); + if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(), + col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result)) + { + + //store result.m_fraction in both bodies + + if (col0->getHitFraction() > result.m_fraction) + col0->setHitFraction( result.m_fraction); + + if (col1->getHitFraction() > result.m_fraction) + col1->setHitFraction( result.m_fraction); + + if (resultFraction > result.m_fraction) + resultFraction = result.m_fraction; + + } + } + + return resultFraction; + +} + diff --git a/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h b/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h new file mode 100644 index 0000000..53d13b8 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h @@ -0,0 +1,95 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H +#define BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H + +#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil + +class btConvexPenetrationDepthSolver; + + +///The convex2dConvex2dAlgorithm collision algorithm support 2d collision detection for btConvex2dShape +///Currently it requires the btMinkowskiPenetrationDepthSolver, it has support for 2d penetration depth computation +class btConvex2dConvex2dAlgorithm : public btActivatingCollisionAlgorithm +{ + btSimplexSolverInterface* m_simplexSolver; + btConvexPenetrationDepthSolver* m_pdSolver; + + + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + bool m_lowLevelOfDetail; + + int m_numPerturbationIterations; + int m_minimumPointsPerturbationThreshold; + +public: + + btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold); + + + virtual ~btConvex2dConvex2dAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + ///should we use m_ownManifold to avoid adding duplicates? + if (m_manifoldPtr && m_ownManifold) + manifoldArray.push_back(m_manifoldPtr); + } + + + void setLowLevelOfDetail(bool useLowLevel); + + + const btPersistentManifold* getManifold() + { + return m_manifoldPtr; + } + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + + btConvexPenetrationDepthSolver* m_pdSolver; + btSimplexSolverInterface* m_simplexSolver; + int m_numPerturbationIterations; + int m_minimumPointsPerturbationThreshold; + + CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); + + virtual ~CreateFunc(); + + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvex2dConvex2dAlgorithm)); + return new(mem) btConvex2dConvex2dAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); + } + }; + + +}; + +#endif //BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H diff --git a/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp new file mode 100644 index 0000000..d2b2c22 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp @@ -0,0 +1,312 @@ +/* +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 "btConvexConcaveCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionShapes/btConcaveShape.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" +#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" + +btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) +: btActivatingCollisionAlgorithm(ci,body0,body1), +m_isSwapped(isSwapped), +m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped) +{ +} + +btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm() +{ +} + +void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray) +{ + if (m_btConvexTriangleCallback.m_manifoldPtr) + { + manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr); + } +} + + +btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped): + m_dispatcher(dispatcher), + m_dispatchInfoPtr(0) +{ + m_convexBody = isSwapped? body1:body0; + m_triBody = isSwapped? body0:body1; + + // + // create the manifold from the dispatcher 'manifold pool' + // + m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody); + + clearCache(); +} + +btConvexTriangleCallback::~btConvexTriangleCallback() +{ + clearCache(); + m_dispatcher->releaseManifold( m_manifoldPtr ); + +} + + +void btConvexTriangleCallback::clearCache() +{ + m_dispatcher->clearManifold(m_manifoldPtr); +} + + + +void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) +{ + + //just for debugging purposes + //printf("triangle %d",m_triangleCount++); + + + //aabb filter is already applied! + + btCollisionAlgorithmConstructionInfo ci; + ci.m_dispatcher1 = m_dispatcher; + + btCollisionObject* ob = static_cast(m_triBody); + + +#if 0 + ///debug drawing of the overlapping triangles + if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe )) + { + btVector3 color(1,1,0); + btTransform& tr = ob->getWorldTransform(); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color); + } +#endif + + if (m_convexBody->getCollisionShape()->isConvex()) + { + btTriangleShape tm(triangle[0],triangle[1],triangle[2]); + tm.setMargin(m_collisionMarginTriangle); + + btCollisionShape* tmpShape = ob->getCollisionShape(); + ob->internalSetTemporaryCollisionShape( &tm ); + + btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr); + + if (m_resultOut->getBody0Internal() == m_triBody) + { + m_resultOut->setShapeIdentifiersA(partId,triangleIndex); + } + else + { + m_resultOut->setShapeIdentifiersB(partId,triangleIndex); + } + + colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); + colAlgo->~btCollisionAlgorithm(); + ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); + ob->internalSetTemporaryCollisionShape( tmpShape); + } + + +} + + + +void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + m_dispatchInfoPtr = &dispatchInfo; + m_collisionMarginTriangle = collisionMarginTriangle; + m_resultOut = resultOut; + + //recalc aabbs + btTransform convexInTriangleSpace; + convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * m_convexBody->getWorldTransform(); + btCollisionShape* convexShape = static_cast(m_convexBody->getCollisionShape()); + //CollisionShape* triangleShape = static_cast(triBody->m_collisionShape); + convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax); + btScalar extraMargin = collisionMarginTriangle; + btVector3 extra(extraMargin,extraMargin,extraMargin); + + m_aabbMax += extra; + m_aabbMin -= extra; + +} + +void btConvexConcaveCollisionAlgorithm::clearCache() +{ + m_btConvexTriangleCallback.clearCache(); + +} + +void btConvexConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + + + btCollisionObject* convexBody = m_isSwapped ? body1 : body0; + btCollisionObject* triBody = m_isSwapped ? body0 : body1; + + if (triBody->getCollisionShape()->isConcave()) + { + + + btCollisionObject* triOb = triBody; + btConcaveShape* concaveShape = static_cast( triOb->getCollisionShape()); + + if (convexBody->getCollisionShape()->isConvex()) + { + btScalar collisionMarginTriangle = concaveShape->getMargin(); + + resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr); + m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut); + + //Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here. + //m_dispatcher->clearManifold(m_btConvexTriangleCallback.m_manifoldPtr); + + m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody); + + concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax()); + + resultOut->refreshContactPoints(); + + } + + } + +} + + +btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + btCollisionObject* convexbody = m_isSwapped ? body1 : body0; + btCollisionObject* triBody = m_isSwapped ? body0 : body1; + + + //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast) + + //only perform CCD above a certain threshold, this prevents blocking on the long run + //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame... + btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2(); + if (squareMot0 < convexbody->getCcdSquareMotionThreshold()) + { + return btScalar(1.); + } + + //const btVector3& from = convexbody->m_worldTransform.getOrigin(); + //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin(); + //todo: only do if the motion exceeds the 'radius' + + btTransform triInv = triBody->getWorldTransform().inverse(); + btTransform convexFromLocal = triInv * convexbody->getWorldTransform(); + btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform(); + + struct LocalTriangleSphereCastCallback : public btTriangleCallback + { + btTransform m_ccdSphereFromTrans; + btTransform m_ccdSphereToTrans; + btTransform m_meshTransform; + + btScalar m_ccdSphereRadius; + btScalar m_hitFraction; + + + LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction) + :m_ccdSphereFromTrans(from), + m_ccdSphereToTrans(to), + m_ccdSphereRadius(ccdSphereRadius), + m_hitFraction(hitFraction) + { + } + + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + (void)partId; + (void)triangleIndex; + //do a swept sphere for now + btTransform ident; + ident.setIdentity(); + btConvexCast::CastResult castResult; + castResult.m_fraction = m_hitFraction; + btSphereShape pointShape(m_ccdSphereRadius); + btTriangleShape triShape(triangle[0],triangle[1],triangle[2]); + btVoronoiSimplexSolver simplexSolver; + btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver); + //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); + //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0); + //local space? + + if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans, + ident,ident,castResult)) + { + if (m_hitFraction > castResult.m_fraction) + m_hitFraction = castResult.m_fraction; + } + + } + + }; + + + + + + if (triBody->getCollisionShape()->isConcave()) + { + btVector3 rayAabbMin = convexFromLocal.getOrigin(); + rayAabbMin.setMin(convexToLocal.getOrigin()); + btVector3 rayAabbMax = convexFromLocal.getOrigin(); + rayAabbMax.setMax(convexToLocal.getOrigin()); + btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius(); + rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0); + rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0); + + btScalar curHitFraction = btScalar(1.); //is this available? + LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal, + convexbody->getCcdSweptSphereRadius(),curHitFraction); + + raycastCallback.m_hitFraction = convexbody->getHitFraction(); + + btCollisionObject* concavebody = triBody; + + btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape(); + + if (triangleMesh) + { + triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax); + } + + + + if (raycastCallback.m_hitFraction < convexbody->getHitFraction()) + { + convexbody->setHitFraction( raycastCallback.m_hitFraction); + return raycastCallback.m_hitFraction; + } + } + + return btScalar(1.); + +} diff --git a/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h new file mode 100644 index 0000000..f718d1d --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h @@ -0,0 +1,116 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H +#define BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H + +#include "btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +class btDispatcher; +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "btCollisionCreateFunc.h" + +///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called. +class btConvexTriangleCallback : public btTriangleCallback +{ + btCollisionObject* m_convexBody; + btCollisionObject* m_triBody; + + btVector3 m_aabbMin; + btVector3 m_aabbMax ; + + + btManifoldResult* m_resultOut; + btDispatcher* m_dispatcher; + const btDispatcherInfo* m_dispatchInfoPtr; + btScalar m_collisionMarginTriangle; + +public: +int m_triangleCount; + + btPersistentManifold* m_manifoldPtr; + + btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); + + void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual ~btConvexTriangleCallback(); + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); + + void clearCache(); + + SIMD_FORCE_INLINE const btVector3& getAabbMin() const + { + return m_aabbMin; + } + SIMD_FORCE_INLINE const btVector3& getAabbMax() const + { + return m_aabbMax; + } + +}; + + + + +/// btConvexConcaveCollisionAlgorithm supports collision between convex shapes and (concave) trianges meshes. +class btConvexConcaveCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ + + bool m_isSwapped; + + btConvexTriangleCallback m_btConvexTriangleCallback; + + + +public: + + btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); + + virtual ~btConvexConcaveCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray); + + void clearCache(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm)); + return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); + } + }; + + struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm)); + return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); + } + }; + +}; + +#endif //BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H diff --git a/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp new file mode 100644 index 0000000..dd1f3e2 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp @@ -0,0 +1,739 @@ +/* +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. +*/ + +///Specialized capsule-capsule collision algorithm has been added for Bullet 2.75 release to increase ragdoll performance +///If you experience problems with capsule-capsule collision, try to define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER and report it in the Bullet forums +///with reproduction case +//define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER 1 +//#define ZERO_MARGIN + +#include "btConvexConvexAlgorithm.h" + +//#include +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" + + + +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" + +#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" + + + +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + +#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" + +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h" + + +/////////// + + + +static SIMD_FORCE_INLINE void segmentsClosestPoints( + btVector3& ptsVector, + btVector3& offsetA, + btVector3& offsetB, + btScalar& tA, btScalar& tB, + const btVector3& translation, + const btVector3& dirA, btScalar hlenA, + const btVector3& dirB, btScalar hlenB ) +{ + // compute the parameters of the closest points on each line segment + + btScalar dirA_dot_dirB = btDot(dirA,dirB); + btScalar dirA_dot_trans = btDot(dirA,translation); + btScalar dirB_dot_trans = btDot(dirB,translation); + + btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB; + + if ( denom == 0.0f ) { + tA = 0.0f; + } else { + tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom; + if ( tA < -hlenA ) + tA = -hlenA; + else if ( tA > hlenA ) + tA = hlenA; + } + + tB = tA * dirA_dot_dirB - dirB_dot_trans; + + if ( tB < -hlenB ) { + tB = -hlenB; + tA = tB * dirA_dot_dirB + dirA_dot_trans; + + if ( tA < -hlenA ) + tA = -hlenA; + else if ( tA > hlenA ) + tA = hlenA; + } else if ( tB > hlenB ) { + tB = hlenB; + tA = tB * dirA_dot_dirB + dirA_dot_trans; + + if ( tA < -hlenA ) + tA = -hlenA; + else if ( tA > hlenA ) + tA = hlenA; + } + + // compute the closest points relative to segment centers. + + offsetA = dirA * tA; + offsetB = dirB * tB; + + ptsVector = translation - offsetA + offsetB; +} + + +static SIMD_FORCE_INLINE btScalar capsuleCapsuleDistance( + btVector3& normalOnB, + btVector3& pointOnB, + btScalar capsuleLengthA, + btScalar capsuleRadiusA, + btScalar capsuleLengthB, + btScalar capsuleRadiusB, + int capsuleAxisA, + int capsuleAxisB, + const btTransform& transformA, + const btTransform& transformB, + btScalar distanceThreshold ) +{ + btVector3 directionA = transformA.getBasis().getColumn(capsuleAxisA); + btVector3 translationA = transformA.getOrigin(); + btVector3 directionB = transformB.getBasis().getColumn(capsuleAxisB); + btVector3 translationB = transformB.getOrigin(); + + // translation between centers + + btVector3 translation = translationB - translationA; + + // compute the closest points of the capsule line segments + + btVector3 ptsVector; // the vector between the closest points + + btVector3 offsetA, offsetB; // offsets from segment centers to their closest points + btScalar tA, tB; // parameters on line segment + + segmentsClosestPoints( ptsVector, offsetA, offsetB, tA, tB, translation, + directionA, capsuleLengthA, directionB, capsuleLengthB ); + + btScalar distance = ptsVector.length() - capsuleRadiusA - capsuleRadiusB; + + if ( distance > distanceThreshold ) + return distance; + + btScalar lenSqr = ptsVector.length2(); + if (lenSqr<= (SIMD_EPSILON*SIMD_EPSILON)) + { + //degenerate case where 2 capsules are likely at the same location: take a vector tangential to 'directionA' + btVector3 q; + btPlaneSpace1(directionA,normalOnB,q); + } else + { + // compute the contact normal + normalOnB = ptsVector*-btRecipSqrt(lenSqr); + } + pointOnB = transformB.getOrigin()+offsetB + normalOnB * capsuleRadiusB; + + return distance; +} + + + + + + + +////////// + + + + + +btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) +{ + m_numPerturbationIterations = 0; + m_minimumPointsPerturbationThreshold = 3; + m_simplexSolver = simplexSolver; + m_pdSolver = pdSolver; +} + +btConvexConvexAlgorithm::CreateFunc::~CreateFunc() +{ +} + +btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold) +: btActivatingCollisionAlgorithm(ci,body0,body1), +m_simplexSolver(simplexSolver), +m_pdSolver(pdSolver), +m_ownManifold (false), +m_manifoldPtr(mf), +m_lowLevelOfDetail(false), +#ifdef USE_SEPDISTANCE_UTIL2 +m_sepDistance((static_cast(body0->getCollisionShape()))->getAngularMotionDisc(), + (static_cast(body1->getCollisionShape()))->getAngularMotionDisc()), +#endif +m_numPerturbationIterations(numPerturbationIterations), +m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold) +{ + (void)body0; + (void)body1; +} + + + + +btConvexConvexAlgorithm::~btConvexConvexAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btConvexConvexAlgorithm ::setLowLevelOfDetail(bool useLowLevel) +{ + m_lowLevelOfDetail = useLowLevel; +} + + +struct btPerturbedContactResult : public btManifoldResult +{ + btManifoldResult* m_originalManifoldResult; + btTransform m_transformA; + btTransform m_transformB; + btTransform m_unPerturbedTransform; + bool m_perturbA; + btIDebugDraw* m_debugDrawer; + + + btPerturbedContactResult(btManifoldResult* originalResult,const btTransform& transformA,const btTransform& transformB,const btTransform& unPerturbedTransform,bool perturbA,btIDebugDraw* debugDrawer) + :m_originalManifoldResult(originalResult), + m_transformA(transformA), + m_transformB(transformB), + m_unPerturbedTransform(unPerturbedTransform), + m_perturbA(perturbA), + m_debugDrawer(debugDrawer) + { + } + virtual ~ btPerturbedContactResult() + { + } + + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar orgDepth) + { + btVector3 endPt,startPt; + btScalar newDepth; + btVector3 newNormal; + + if (m_perturbA) + { + btVector3 endPtOrg = pointInWorld + normalOnBInWorld*orgDepth; + endPt = (m_unPerturbedTransform*m_transformA.inverse())(endPtOrg); + newDepth = (endPt - pointInWorld).dot(normalOnBInWorld); + startPt = endPt+normalOnBInWorld*newDepth; + } else + { + endPt = pointInWorld + normalOnBInWorld*orgDepth; + startPt = (m_unPerturbedTransform*m_transformB.inverse())(pointInWorld); + newDepth = (endPt - startPt).dot(normalOnBInWorld); + + } + +//#define DEBUG_CONTACTS 1 +#ifdef DEBUG_CONTACTS + m_debugDrawer->drawLine(startPt,endPt,btVector3(1,0,0)); + m_debugDrawer->drawSphere(startPt,0.05,btVector3(0,1,0)); + m_debugDrawer->drawSphere(endPt,0.05,btVector3(0,0,1)); +#endif //DEBUG_CONTACTS + + + m_originalManifoldResult->addContactPoint(normalOnBInWorld,startPt,newDepth); + } + +}; + +extern btScalar gContactBreakingThreshold; + + +// +// Convex-Convex collision algorithm +// +void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + + if (!m_manifoldPtr) + { + //swapped? + m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1); + m_ownManifold = true; + } + resultOut->setPersistentManifold(m_manifoldPtr); + + //comment-out next line to test multi-contact generation + //resultOut->getPersistentManifold()->clearManifold(); + + + btConvexShape* min0 = static_cast(body0->getCollisionShape()); + btConvexShape* min1 = static_cast(body1->getCollisionShape()); + + btVector3 normalOnB; + btVector3 pointOnBWorld; +#ifndef BT_DISABLE_CAPSULE_CAPSULE_COLLIDER + if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE)) + { + btCapsuleShape* capsuleA = (btCapsuleShape*) min0; + btCapsuleShape* capsuleB = (btCapsuleShape*) min1; + btVector3 localScalingA = capsuleA->getLocalScaling(); + btVector3 localScalingB = capsuleB->getLocalScaling(); + + btScalar threshold = m_manifoldPtr->getContactBreakingThreshold(); + + btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld,capsuleA->getHalfHeight(),capsuleA->getRadius(), + capsuleB->getHalfHeight(),capsuleB->getRadius(),capsuleA->getUpAxis(),capsuleB->getUpAxis(), + body0->getWorldTransform(),body1->getWorldTransform(),threshold); + + if (dist=(SIMD_EPSILON*SIMD_EPSILON)); + resultOut->addContactPoint(normalOnB,pointOnBWorld,dist); + } + resultOut->refreshContactPoints(); + return; + } +#endif //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER + + + + +#ifdef USE_SEPDISTANCE_UTIL2 + if (dispatchInfo.m_useConvexConservativeDistanceUtil) + { + m_sepDistance.updateSeparatingDistance(body0->getWorldTransform(),body1->getWorldTransform()); + } + + if (!dispatchInfo.m_useConvexConservativeDistanceUtil || m_sepDistance.getConservativeSeparatingDistance()<=0.f) +#endif //USE_SEPDISTANCE_UTIL2 + + { + + + btGjkPairDetector::ClosestPointInput input; + + btGjkPairDetector gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver); + //TODO: if (dispatchInfo.m_useContinuous) + gjkPairDetector.setMinkowskiA(min0); + gjkPairDetector.setMinkowskiB(min1); + +#ifdef USE_SEPDISTANCE_UTIL2 + if (dispatchInfo.m_useConvexConservativeDistanceUtil) + { + input.m_maximumDistanceSquared = BT_LARGE_FLOAT; + } else +#endif //USE_SEPDISTANCE_UTIL2 + { + //if (dispatchInfo.m_convexMaxDistanceUseCPT) + //{ + // input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactProcessingThreshold(); + //} else + //{ + input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold(); +// } + + input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared; + } + + input.m_stackAlloc = dispatchInfo.m_stackAllocator; + input.m_transformA = body0->getWorldTransform(); + input.m_transformB = body1->getWorldTransform(); + + + + + +#ifdef USE_SEPDISTANCE_UTIL2 + btScalar sepDist = 0.f; + if (dispatchInfo.m_useConvexConservativeDistanceUtil) + { + sepDist = gjkPairDetector.getCachedSeparatingDistance(); + if (sepDist>SIMD_EPSILON) + { + sepDist += dispatchInfo.m_convexConservativeDistanceThreshold; + //now perturbe directions to get multiple contact points + + } + } +#endif //USE_SEPDISTANCE_UTIL2 + + if (min0->isPolyhedral() && min1->isPolyhedral()) + { + + + struct btDummyResult : public btDiscreteCollisionDetectorInterface::Result + { + virtual void setShapeIdentifiersA(int partId0,int index0){} + virtual void setShapeIdentifiersB(int partId1,int index1){} + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) + { + } + }; + + btDummyResult dummy; + + + btPolyhedralConvexShape* polyhedronA = (btPolyhedralConvexShape*) min0; + btPolyhedralConvexShape* polyhedronB = (btPolyhedralConvexShape*) min1; + if (polyhedronA->getConvexPolyhedron() && polyhedronB->getConvexPolyhedron()) + { + + + + + btScalar threshold = m_manifoldPtr->getContactBreakingThreshold(); + + btScalar minDist = -1e30f; + btVector3 sepNormalWorldSpace; + bool foundSepAxis = true; + + if (dispatchInfo.m_enableSatConvex) + { + foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis( + *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(), + body0->getWorldTransform(), + body1->getWorldTransform(), + sepNormalWorldSpace); + } else + { +#ifdef ZERO_MARGIN + gjkPairDetector.setIgnoreMargin(true); + gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); +#else + //gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw); +#endif //ZERO_MARGIN + btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2(); + if (l2>SIMD_EPSILON) + { + sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2); + //minDist = -1e30f;//gjkPairDetector.getCachedSeparatingDistance(); + minDist = gjkPairDetector.getCachedSeparatingDistance()-min0->getMargin()-min1->getMargin(); + +#ifdef ZERO_MARGIN + foundSepAxis = true;//gjkPairDetector.getCachedSeparatingDistance()<0.f; +#else + foundSepAxis = gjkPairDetector.getCachedSeparatingDistance()<(min0->getMargin()+min1->getMargin()); +#endif + } + } + if (foundSepAxis) + { +// printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ()); + + btPolyhedralContactClipping::clipHullAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(), + body0->getWorldTransform(), + body1->getWorldTransform(), minDist-threshold, threshold, *resultOut); + + } + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } + return; + + } else + { + //we can also deal with convex versus triangle (without connectivity data) + if (polyhedronA->getConvexPolyhedron() && polyhedronB->getShapeType()==TRIANGLE_SHAPE_PROXYTYPE) + { + + btVertexArray vertices; + btTriangleShape* tri = (btTriangleShape*)polyhedronB; + vertices.push_back( body1->getWorldTransform()*tri->m_vertices1[0]); + vertices.push_back( body1->getWorldTransform()*tri->m_vertices1[1]); + vertices.push_back( body1->getWorldTransform()*tri->m_vertices1[2]); + + //tri->initializePolyhedralFeatures(); + + btScalar threshold = m_manifoldPtr->getContactBreakingThreshold(); + + btVector3 sepNormalWorldSpace; + btScalar minDist =-1e30f; + btScalar maxDist = threshold; + + bool foundSepAxis = false; + if (0) + { + polyhedronB->initializePolyhedralFeatures(); + foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis( + *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(), + body0->getWorldTransform(), + body1->getWorldTransform(), + sepNormalWorldSpace); + // printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ()); + + } else + { +#ifdef ZERO_MARGIN + gjkPairDetector.setIgnoreMargin(true); + gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); +#else + gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw); +#endif//ZERO_MARGIN + + btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2(); + if (l2>SIMD_EPSILON) + { + sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2); + //minDist = gjkPairDetector.getCachedSeparatingDistance(); + //maxDist = threshold; + minDist = gjkPairDetector.getCachedSeparatingDistance()-min0->getMargin()-min1->getMargin(); + foundSepAxis = true; + } + } + + + if (foundSepAxis) + { + btPolyhedralContactClipping::clipFaceAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), + body0->getWorldTransform(), vertices, minDist-threshold, maxDist, *resultOut); + } + + + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } + + return; + } + + } + + + } + + gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + + //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects + + //perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points + if (m_numPerturbationIterations && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold) + { + + int i; + btVector3 v0,v1; + btVector3 sepNormalWorldSpace; + btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2(); + + if (l2>SIMD_EPSILON) + { + sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2); + + btPlaneSpace1(sepNormalWorldSpace,v0,v1); + + + bool perturbeA = true; + const btScalar angleLimit = 0.125f * SIMD_PI; + btScalar perturbeAngle; + btScalar radiusA = min0->getAngularMotionDisc(); + btScalar radiusB = min1->getAngularMotionDisc(); + if (radiusA < radiusB) + { + perturbeAngle = gContactBreakingThreshold /radiusA; + perturbeA = true; + } else + { + perturbeAngle = gContactBreakingThreshold / radiusB; + perturbeA = false; + } + if ( perturbeAngle > angleLimit ) + perturbeAngle = angleLimit; + + btTransform unPerturbedTransform; + if (perturbeA) + { + unPerturbedTransform = input.m_transformA; + } else + { + unPerturbedTransform = input.m_transformB; + } + + for ( i=0;iSIMD_EPSILON) + { + btQuaternion perturbeRot(v0,perturbeAngle); + btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations)); + btQuaternion rotq(sepNormalWorldSpace,iterationAngle); + + + if (perturbeA) + { + input.m_transformA.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body0->getWorldTransform().getBasis()); + input.m_transformB = body1->getWorldTransform(); + #ifdef DEBUG_CONTACTS + dispatchInfo.m_debugDraw->drawTransform(input.m_transformA,10.0); + #endif //DEBUG_CONTACTS + } else + { + input.m_transformA = body0->getWorldTransform(); + input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1->getWorldTransform().getBasis()); + #ifdef DEBUG_CONTACTS + dispatchInfo.m_debugDraw->drawTransform(input.m_transformB,10.0); + #endif + } + + btPerturbedContactResult perturbedResultOut(resultOut,input.m_transformA,input.m_transformB,unPerturbedTransform,perturbeA,dispatchInfo.m_debugDraw); + gjkPairDetector.getClosestPoints(input,perturbedResultOut,dispatchInfo.m_debugDraw); + } + } + } + } + + + +#ifdef USE_SEPDISTANCE_UTIL2 + if (dispatchInfo.m_useConvexConservativeDistanceUtil && (sepDist>SIMD_EPSILON)) + { + m_sepDistance.initSeparatingDistance(gjkPairDetector.getCachedSeparatingAxis(),sepDist,body0->getWorldTransform(),body1->getWorldTransform()); + } +#endif //USE_SEPDISTANCE_UTIL2 + + + } + + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } + +} + + + +bool disableCcd = false; +btScalar btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + ///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold + + ///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold + ///col0->m_worldTransform, + btScalar resultFraction = btScalar(1.); + + + btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2(); + btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2(); + + if (squareMot0 < col0->getCcdSquareMotionThreshold() && + squareMot1 < col1->getCcdSquareMotionThreshold()) + return resultFraction; + + if (disableCcd) + return btScalar(1.); + + + //An adhoc way of testing the Continuous Collision Detection algorithms + //One object is approximated as a sphere, to simplify things + //Starting in penetration should report no time of impact + //For proper CCD, better accuracy and handling of 'allowed' penetration should be added + //also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies) + + + /// Convex0 against sphere for Convex1 + { + btConvexShape* convex0 = static_cast(col0->getCollisionShape()); + + btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation + btConvexCast::CastResult result; + btVoronoiSimplexSolver voronoiSimplex; + //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex); + ///Simplification, one object is simplified as a sphere + btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex); + //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0); + if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(), + col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result)) + { + + //store result.m_fraction in both bodies + + if (col0->getHitFraction()> result.m_fraction) + col0->setHitFraction( result.m_fraction ); + + if (col1->getHitFraction() > result.m_fraction) + col1->setHitFraction( result.m_fraction); + + if (resultFraction > result.m_fraction) + resultFraction = result.m_fraction; + + } + + + + + } + + /// Sphere (for convex0) against Convex1 + { + btConvexShape* convex1 = static_cast(col1->getCollisionShape()); + + btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation + btConvexCast::CastResult result; + btVoronoiSimplexSolver voronoiSimplex; + //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex); + ///Simplification, one object is simplified as a sphere + btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex); + //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0); + if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(), + col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result)) + { + + //store result.m_fraction in both bodies + + if (col0->getHitFraction() > result.m_fraction) + col0->setHitFraction( result.m_fraction); + + if (col1->getHitFraction() > result.m_fraction) + col1->setHitFraction( result.m_fraction); + + if (resultFraction > result.m_fraction) + resultFraction = result.m_fraction; + + } + } + + return resultFraction; + +} + diff --git a/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h new file mode 100644 index 0000000..4380b80 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h @@ -0,0 +1,109 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_CONVEX_ALGORITHM_H +#define BT_CONVEX_CONVEX_ALGORITHM_H + +#include "btActivatingCollisionAlgorithm.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "btCollisionCreateFunc.h" +#include "btCollisionDispatcher.h" +#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil + +class btConvexPenetrationDepthSolver; + +///Enabling USE_SEPDISTANCE_UTIL2 requires 100% reliable distance computation. However, when using large size ratios GJK can be imprecise +///so the distance is not conservative. In that case, enabling this USE_SEPDISTANCE_UTIL2 would result in failing/missing collisions. +///Either improve GJK for large size ratios (testing a 100 units versus a 0.1 unit object) or only enable the util +///for certain pairs that have a small size ratio + +//#define USE_SEPDISTANCE_UTIL2 1 + +///The convexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations between two convex objects. +///Multiple contact points are calculated by perturbing the orientation of the smallest object orthogonal to the separating normal. +///This idea was described by Gino van den Bergen in this forum topic http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=4&t=288&p=888#p888 +class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm +{ +#ifdef USE_SEPDISTANCE_UTIL2 + btConvexSeparatingDistanceUtil m_sepDistance; +#endif + btSimplexSolverInterface* m_simplexSolver; + btConvexPenetrationDepthSolver* m_pdSolver; + + + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + bool m_lowLevelOfDetail; + + int m_numPerturbationIterations; + int m_minimumPointsPerturbationThreshold; + + + ///cache separating vector to speedup collision detection + + +public: + + btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold); + + + virtual ~btConvexConvexAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + ///should we use m_ownManifold to avoid adding duplicates? + if (m_manifoldPtr && m_ownManifold) + manifoldArray.push_back(m_manifoldPtr); + } + + + void setLowLevelOfDetail(bool useLowLevel); + + + const btPersistentManifold* getManifold() + { + return m_manifoldPtr; + } + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + + btConvexPenetrationDepthSolver* m_pdSolver; + btSimplexSolverInterface* m_simplexSolver; + int m_numPerturbationIterations; + int m_minimumPointsPerturbationThreshold; + + CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); + + virtual ~CreateFunc(); + + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm)); + return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); + } + }; + + +}; + +#endif //BT_CONVEX_CONVEX_ALGORITHM_H diff --git a/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp b/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp new file mode 100644 index 0000000..b2e9bfa --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp @@ -0,0 +1,173 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btConvexPlaneCollisionAlgorithm.h" + +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" + +//#include + +btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold) +: btCollisionAlgorithm(ci), +m_ownManifold(false), +m_manifoldPtr(mf), +m_isSwapped(isSwapped), +m_numPerturbationIterations(numPerturbationIterations), +m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold) +{ + btCollisionObject* convexObj = m_isSwapped? col1 : col0; + btCollisionObject* planeObj = m_isSwapped? col0 : col1; + + if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj)) + { + m_manifoldPtr = m_dispatcher->getNewManifold(convexObj,planeObj); + m_ownManifold = true; + } +} + + +btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + btCollisionObject* convexObj = m_isSwapped? body1 : body0; + btCollisionObject* planeObj = m_isSwapped? body0: body1; + + btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape(); + btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape(); + + bool hasCollision = false; + const btVector3& planeNormal = planeShape->getPlaneNormal(); + const btScalar& planeConstant = planeShape->getPlaneConstant(); + + btTransform convexWorldTransform = convexObj->getWorldTransform(); + btTransform convexInPlaneTrans; + convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexWorldTransform; + //now perturbe the convex-world transform + convexWorldTransform.getBasis()*=btMatrix3x3(perturbeRot); + btTransform planeInConvex; + planeInConvex= convexWorldTransform.inverse() * planeObj->getWorldTransform(); + + btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal); + + btVector3 vtxInPlane = convexInPlaneTrans(vtx); + btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); + + btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; + btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected; + + hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold(); + resultOut->setPersistentManifold(m_manifoldPtr); + if (hasCollision) + { + /// report a contact. internally this will be kept persistent, and contact reduction is done + btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal; + btVector3 pOnB = vtxInPlaneWorld; + resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance); + } +} + + +void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)dispatchInfo; + if (!m_manifoldPtr) + return; + + btCollisionObject* convexObj = m_isSwapped? body1 : body0; + btCollisionObject* planeObj = m_isSwapped? body0: body1; + + btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape(); + btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape(); + + bool hasCollision = false; + const btVector3& planeNormal = planeShape->getPlaneNormal(); + const btScalar& planeConstant = planeShape->getPlaneConstant(); + btTransform planeInConvex; + planeInConvex= convexObj->getWorldTransform().inverse() * planeObj->getWorldTransform(); + btTransform convexInPlaneTrans; + convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexObj->getWorldTransform(); + + btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal); + btVector3 vtxInPlane = convexInPlaneTrans(vtx); + btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); + + btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; + btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected; + + hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold(); + resultOut->setPersistentManifold(m_manifoldPtr); + if (hasCollision) + { + /// report a contact. internally this will be kept persistent, and contact reduction is done + btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal; + btVector3 pOnB = vtxInPlaneWorld; + resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance); + } + + //the perturbation algorithm doesn't work well with implicit surfaces such as spheres, cylinder and cones: + //they keep on rolling forever because of the additional off-center contact points + //so only enable the feature for polyhedral shapes (btBoxShape, btConvexHullShape etc) + if (convexShape->isPolyhedral() && resultOut->getPersistentManifold()->getNumContacts()getAngularMotionDisc(); + perturbeAngle = gContactBreakingThreshold / radius; + if ( perturbeAngle > angleLimit ) + perturbeAngle = angleLimit; + + btQuaternion perturbeRot(v0,perturbeAngle); + for (int i=0;igetNumContacts()) + { + resultOut->refreshContactPoints(); + } + } +} + +btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + (void)col0; + (void)col1; + + //not yet + return btScalar(1.); +} diff --git a/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h b/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h new file mode 100644 index 0000000..b9494f5 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h @@ -0,0 +1,84 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_PLANE_COLLISION_ALGORITHM_H +#define BT_CONVEX_PLANE_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +class btPersistentManifold; +#include "btCollisionDispatcher.h" + +#include "LinearMath/btVector3.h" + +/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection. +/// Other features are frame-coherency (persistent data) and collision response. +class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + bool m_isSwapped; + int m_numPerturbationIterations; + int m_minimumPointsPerturbationThreshold; + +public: + + btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold); + + virtual ~btConvexPlaneCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + void collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + int m_numPerturbationIterations; + int m_minimumPointsPerturbationThreshold; + + CreateFunc() + : m_numPerturbationIterations(1), + m_minimumPointsPerturbationThreshold(0) + { + } + + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm)); + if (!m_swapped) + { + return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); + } else + { + return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); + } + } + }; + +}; + +#endif //BT_CONVEX_PLANE_COLLISION_ALGORITHM_H + diff --git a/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp new file mode 100644 index 0000000..7faee6f --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp @@ -0,0 +1,309 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btDefaultCollisionConfiguration.h" + +#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM +#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM +#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" + + + +#include "LinearMath/btStackAlloc.h" +#include "LinearMath/btPoolAllocator.h" + + + + + +btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo) +//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool) +{ + + void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16); + m_simplexSolver = new (mem)btVoronoiSimplexSolver(); + + if (constructionInfo.m_useEpaPenetrationAlgorithm) + { + mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16); + m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver; + }else + { + mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16); + m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver; + } + + //default CreationFunctions, filling the m_doubleDispatch table + mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16); + m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver); + mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); + m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); + m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc; + mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16); + m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16); + m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc; + mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16); + m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16); + m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc; +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM + mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); + m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); + m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc; + m_boxSphereCF->m_swapped = true; +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + + mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); + m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); + m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; + m_triangleSphereCF->m_swapped = true; + + mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16); + m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc; + + //convex versus plane + mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16); + m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16); + m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc; + m_planeConvexCF->m_swapped = true; + + ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool + int maxSize = sizeof(btConvexConvexAlgorithm); + int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm); + int maxSize3 = sizeof(btCompoundCollisionAlgorithm); + int sl = sizeof(btConvexSeparatingDistanceUtil); + sl = sizeof(btGjkPairDetector); + int collisionAlgorithmMaxElementSize = btMax(maxSize,constructionInfo.m_customCollisionAlgorithmMaxElementSize); + collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2); + collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3); + + if (constructionInfo.m_stackAlloc) + { + m_ownsStackAllocator = false; + this->m_stackAlloc = constructionInfo.m_stackAlloc; + } else + { + m_ownsStackAllocator = true; + void* mem = btAlignedAlloc(sizeof(btStackAlloc),16); + m_stackAlloc = new(mem)btStackAlloc(constructionInfo.m_defaultStackAllocatorSize); + } + + if (constructionInfo.m_persistentManifoldPool) + { + m_ownsPersistentManifoldPool = false; + m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool; + } else + { + m_ownsPersistentManifoldPool = true; + void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); + m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize); + } + + if (constructionInfo.m_collisionAlgorithmPool) + { + m_ownsCollisionAlgorithmPool = false; + m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool; + } else + { + m_ownsCollisionAlgorithmPool = true; + void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); + m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize); + } + + +} + +btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration() +{ + if (m_ownsStackAllocator) + { + m_stackAlloc->destroy(); + m_stackAlloc->~btStackAlloc(); + btAlignedFree(m_stackAlloc); + } + if (m_ownsCollisionAlgorithmPool) + { + m_collisionAlgorithmPool->~btPoolAllocator(); + btAlignedFree(m_collisionAlgorithmPool); + } + if (m_ownsPersistentManifoldPool) + { + m_persistentManifoldPool->~btPoolAllocator(); + btAlignedFree(m_persistentManifoldPool); + } + + m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_convexConvexCreateFunc); + + m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_convexConcaveCreateFunc); + m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedConvexConcaveCreateFunc); + + m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_compoundCreateFunc); + + m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedCompoundCreateFunc); + + m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_emptyCreateFunc); + + m_sphereSphereCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_sphereSphereCF); + +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM + m_sphereBoxCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_sphereBoxCF); + m_boxSphereCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_boxSphereCF); +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + + m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_sphereTriangleCF); + m_triangleSphereCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_triangleSphereCF); + m_boxBoxCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_boxBoxCF); + + m_convexPlaneCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_convexPlaneCF); + m_planeConvexCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_planeConvexCF); + + m_simplexSolver->~btVoronoiSimplexSolver(); + btAlignedFree(m_simplexSolver); + + m_pdSolver->~btConvexPenetrationDepthSolver(); + + btAlignedFree(m_pdSolver); + + +} + + +btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) +{ + + + + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) + { + return m_sphereSphereCF; + } +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE)) + { + return m_sphereBoxCF; + } + + if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) + { + return m_boxSphereCF; + } +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + + + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE)) + { + return m_sphereTriangleCF; + } + + if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) + { + return m_triangleSphereCF; + } + + if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE)) + { + return m_boxBoxCF; + } + + if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE)) + { + return m_convexPlaneCF; + } + + if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE)) + { + return m_planeConvexCF; + } + + + + if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1)) + { + return m_convexConvexCreateFunc; + } + + if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1)) + { + return m_convexConcaveCreateFunc; + } + + if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0)) + { + return m_swappedConvexConcaveCreateFunc; + } + + if (btBroadphaseProxy::isCompound(proxyType0)) + { + return m_compoundCreateFunc; + } else + { + if (btBroadphaseProxy::isCompound(proxyType1)) + { + return m_swappedCompoundCreateFunc; + } + } + + //failed to find an algorithm + return m_emptyCreateFunc; +} + +void btDefaultCollisionConfiguration::setConvexConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold) +{ + btConvexConvexAlgorithm::CreateFunc* convexConvex = (btConvexConvexAlgorithm::CreateFunc*) m_convexConvexCreateFunc; + convexConvex->m_numPerturbationIterations = numPerturbationIterations; + convexConvex->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold; +} + +void btDefaultCollisionConfiguration::setPlaneConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold) +{ + btConvexPlaneCollisionAlgorithm::CreateFunc* cpCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_convexPlaneCF; + cpCF->m_numPerturbationIterations = numPerturbationIterations; + cpCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold; + + btConvexPlaneCollisionAlgorithm::CreateFunc* pcCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_planeConvexCF; + pcCF->m_numPerturbationIterations = numPerturbationIterations; + pcCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold; +} diff --git a/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h new file mode 100644 index 0000000..81ed424 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h @@ -0,0 +1,137 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_DEFAULT_COLLISION_CONFIGURATION +#define BT_DEFAULT_COLLISION_CONFIGURATION + +#include "btCollisionConfiguration.h" +class btVoronoiSimplexSolver; +class btConvexPenetrationDepthSolver; + +struct btDefaultCollisionConstructionInfo +{ + btStackAlloc* m_stackAlloc; + btPoolAllocator* m_persistentManifoldPool; + btPoolAllocator* m_collisionAlgorithmPool; + int m_defaultMaxPersistentManifoldPoolSize; + int m_defaultMaxCollisionAlgorithmPoolSize; + int m_customCollisionAlgorithmMaxElementSize; + int m_defaultStackAllocatorSize; + int m_useEpaPenetrationAlgorithm; + + btDefaultCollisionConstructionInfo() + :m_stackAlloc(0), + m_persistentManifoldPool(0), + m_collisionAlgorithmPool(0), + m_defaultMaxPersistentManifoldPoolSize(4096), + m_defaultMaxCollisionAlgorithmPoolSize(4096), + m_customCollisionAlgorithmMaxElementSize(0), + m_defaultStackAllocatorSize(0), + m_useEpaPenetrationAlgorithm(true) + { + } +}; + + + +///btCollisionConfiguration allows to configure Bullet collision detection +///stack allocator, pool memory allocators +///@todo: describe the meaning +class btDefaultCollisionConfiguration : public btCollisionConfiguration +{ + +protected: + + int m_persistentManifoldPoolSize; + + btStackAlloc* m_stackAlloc; + bool m_ownsStackAllocator; + + btPoolAllocator* m_persistentManifoldPool; + bool m_ownsPersistentManifoldPool; + + + btPoolAllocator* m_collisionAlgorithmPool; + bool m_ownsCollisionAlgorithmPool; + + //default simplex/penetration depth solvers + btVoronoiSimplexSolver* m_simplexSolver; + btConvexPenetrationDepthSolver* m_pdSolver; + + //default CreationFunctions, filling the m_doubleDispatch table + btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_compoundCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc; + btCollisionAlgorithmCreateFunc* m_emptyCreateFunc; + btCollisionAlgorithmCreateFunc* m_sphereSphereCF; +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM + btCollisionAlgorithmCreateFunc* m_sphereBoxCF; + btCollisionAlgorithmCreateFunc* m_boxSphereCF; +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + + btCollisionAlgorithmCreateFunc* m_boxBoxCF; + btCollisionAlgorithmCreateFunc* m_sphereTriangleCF; + btCollisionAlgorithmCreateFunc* m_triangleSphereCF; + btCollisionAlgorithmCreateFunc* m_planeConvexCF; + btCollisionAlgorithmCreateFunc* m_convexPlaneCF; + +public: + + + btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo()); + + virtual ~btDefaultCollisionConfiguration(); + + ///memory pools + virtual btPoolAllocator* getPersistentManifoldPool() + { + return m_persistentManifoldPool; + } + + virtual btPoolAllocator* getCollisionAlgorithmPool() + { + return m_collisionAlgorithmPool; + } + + virtual btStackAlloc* getStackAllocator() + { + return m_stackAlloc; + } + + virtual btVoronoiSimplexSolver* getSimplexSolver() + { + return m_simplexSolver; + } + + + virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); + + ///Use this method to allow to generate multiple contact points between at once, between two objects using the generic convex-convex algorithm. + ///By default, this feature is disabled for best performance. + ///@param numPerturbationIterations controls the number of collision queries. Set it to zero to disable the feature. + ///@param minimumPointsPerturbationThreshold is the minimum number of points in the contact cache, above which the feature is disabled + ///3 is a good value for both params, if you want to enable the feature. This is because the default contact cache contains a maximum of 4 points, and one collision query at the unperturbed orientation is performed first. + ///See Bullet/Demos/CollisionDemo for an example how this feature gathers multiple points. + ///@todo we could add a per-object setting of those parameters, for level-of-detail collision detection. + void setConvexConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3); + + void setPlaneConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3); + +}; + +#endif //BT_DEFAULT_COLLISION_CONFIGURATION + diff --git a/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp b/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp new file mode 100644 index 0000000..9360543 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp @@ -0,0 +1,34 @@ +/* +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 "btEmptyCollisionAlgorithm.h" + + + +btEmptyAlgorithm::btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btCollisionAlgorithm(ci) +{ +} + +void btEmptyAlgorithm::processCollision (btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* ) +{ +} + +btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* ) +{ + return btScalar(1.); +} + + diff --git a/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h new file mode 100644 index 0000000..f03c9dc --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h @@ -0,0 +1,54 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_EMPTY_ALGORITH +#define BT_EMPTY_ALGORITH +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "btCollisionCreateFunc.h" +#include "btCollisionDispatcher.h" + +#define ATTRIBUTE_ALIGNED(a) + +///EmptyAlgorithm is a stub for unsupported collision pairs. +///The dispatcher can dispatch a persistent btEmptyAlgorithm to avoid a search every frame. +class btEmptyAlgorithm : public btCollisionAlgorithm +{ + +public: + + btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + } + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + (void)body0; + (void)body1; + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm)); + return new(mem) btEmptyAlgorithm(ci); + } + }; + +} ATTRIBUTE_ALIGNED(16); + +#endif //BT_EMPTY_ALGORITH diff --git a/src/BulletCollision/CollisionDispatch/btGhostObject.cpp b/src/BulletCollision/CollisionDispatch/btGhostObject.cpp new file mode 100644 index 0000000..86141fa --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btGhostObject.cpp @@ -0,0 +1,171 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com + +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 "btGhostObject.h" +#include "btCollisionWorld.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "LinearMath/btAabbUtil2.h" + +btGhostObject::btGhostObject() +{ + m_internalType = CO_GHOST_OBJECT; +} + +btGhostObject::~btGhostObject() +{ + ///btGhostObject should have been removed from the world, so no overlapping objects + btAssert(!m_overlappingObjects.size()); +} + + +void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy) +{ + btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; + btAssert(otherObject); + ///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure + int index = m_overlappingObjects.findLinearSearch(otherObject); + if (index==m_overlappingObjects.size()) + { + //not found + m_overlappingObjects.push_back(otherObject); + } +} + +void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy) +{ + btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; + btAssert(otherObject); + int index = m_overlappingObjects.findLinearSearch(otherObject); + if (index~btHashedOverlappingPairCache(); + btAlignedFree( m_hashPairCache ); +} + +void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy) +{ + btBroadphaseProxy*actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle(); + btAssert(actualThisProxy); + + btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; + btAssert(otherObject); + int index = m_overlappingObjects.findLinearSearch(otherObject); + if (index==m_overlappingObjects.size()) + { + m_overlappingObjects.push_back(otherObject); + m_hashPairCache->addOverlappingPair(actualThisProxy,otherProxy); + } +} + +void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy1) +{ + btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; + btBroadphaseProxy* actualThisProxy = thisProxy1 ? thisProxy1 : getBroadphaseHandle(); + btAssert(actualThisProxy); + + btAssert(otherObject); + int index = m_overlappingObjects.findLinearSearch(otherObject); + if (indexremoveOverlappingPair(actualThisProxy,otherProxy,dispatcher); + } +} + + +void btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const +{ + btTransform convexFromTrans,convexToTrans; + convexFromTrans = convexFromWorld; + convexToTrans = convexToWorld; + btVector3 castShapeAabbMin, castShapeAabbMax; + /* Compute AABB that encompasses angular movement */ + { + btVector3 linVel, angVel; + btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel); + btTransform R; + R.setIdentity (); + R.setRotation (convexFromTrans.getRotation()); + castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax); + } + + /// go over all objects, and if the ray intersects their aabb + cast shape aabb, + // do a ray-shape query using convexCaster (CCD) + int i; + for (i=0;igetBroadphaseHandle())) { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + btVector3 collisionObjectAabbMin,collisionObjectAabbMax; + collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); + AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax); + btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing + btVector3 hitNormal; + if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) + { + btCollisionWorld::objectQuerySingle(castShape, convexFromTrans,convexToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + resultCallback, + allowedCcdPenetration); + } + } + } + +} + +void btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const +{ + btTransform rayFromTrans; + rayFromTrans.setIdentity(); + rayFromTrans.setOrigin(rayFromWorld); + btTransform rayToTrans; + rayToTrans.setIdentity(); + rayToTrans.setOrigin(rayToWorld); + + + int i; + for (i=0;igetBroadphaseHandle())) + { + btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + resultCallback); + } + } +} + diff --git a/src/BulletCollision/CollisionDispatch/btGhostObject.h b/src/BulletCollision/CollisionDispatch/btGhostObject.h new file mode 100644 index 0000000..8ec8613 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btGhostObject.h @@ -0,0 +1,175 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_GHOST_OBJECT_H +#define BT_GHOST_OBJECT_H + + +#include "btCollisionObject.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h" +#include "LinearMath/btAlignedAllocator.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "btCollisionWorld.h" + +class btConvexShape; + +class btDispatcher; + +///The btGhostObject can keep track of all objects that are overlapping +///By default, this overlap is based on the AABB +///This is useful for creating a character controller, collision sensors/triggers, explosions etc. +///We plan on adding rayTest and other queries for the btGhostObject +ATTRIBUTE_ALIGNED16(class) btGhostObject : public btCollisionObject +{ +protected: + + btAlignedObjectArray m_overlappingObjects; + +public: + + btGhostObject(); + + virtual ~btGhostObject(); + + void convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const; + + void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const; + + ///this method is mainly for expert/internal use only. + virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0); + ///this method is mainly for expert/internal use only. + virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0); + + int getNumOverlappingObjects() const + { + return m_overlappingObjects.size(); + } + + btCollisionObject* getOverlappingObject(int index) + { + return m_overlappingObjects[index]; + } + + const btCollisionObject* getOverlappingObject(int index) const + { + return m_overlappingObjects[index]; + } + + btAlignedObjectArray& getOverlappingPairs() + { + return m_overlappingObjects; + } + + const btAlignedObjectArray getOverlappingPairs() const + { + return m_overlappingObjects; + } + + // + // internal cast + // + + static const btGhostObject* upcast(const btCollisionObject* colObj) + { + if (colObj->getInternalType()==CO_GHOST_OBJECT) + return (const btGhostObject*)colObj; + return 0; + } + static btGhostObject* upcast(btCollisionObject* colObj) + { + if (colObj->getInternalType()==CO_GHOST_OBJECT) + return (btGhostObject*)colObj; + return 0; + } + +}; + +class btPairCachingGhostObject : public btGhostObject +{ + btHashedOverlappingPairCache* m_hashPairCache; + +public: + + btPairCachingGhostObject(); + + virtual ~btPairCachingGhostObject(); + + ///this method is mainly for expert/internal use only. + virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0); + + virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0); + + btHashedOverlappingPairCache* getOverlappingPairCache() + { + return m_hashPairCache; + } + +}; + + + +///The btGhostPairCallback interfaces and forwards adding and removal of overlapping pairs from the btBroadphaseInterface to btGhostObject. +class btGhostPairCallback : public btOverlappingPairCallback +{ + +public: + btGhostPairCallback() + { + } + + virtual ~btGhostPairCallback() + { + + } + + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) + { + btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject; + btGhostObject* ghost0 = btGhostObject::upcast(colObj0); + btGhostObject* ghost1 = btGhostObject::upcast(colObj1); + if (ghost0) + ghost0->addOverlappingObjectInternal(proxy1, proxy0); + if (ghost1) + ghost1->addOverlappingObjectInternal(proxy0, proxy1); + return 0; + } + + virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) + { + btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject; + btGhostObject* ghost0 = btGhostObject::upcast(colObj0); + btGhostObject* ghost1 = btGhostObject::upcast(colObj1); + if (ghost0) + ghost0->removeOverlappingObjectInternal(proxy1,dispatcher,proxy0); + if (ghost1) + ghost1->removeOverlappingObjectInternal(proxy0,dispatcher,proxy1); + return 0; + } + + virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/) + { + btAssert(0); + //need to keep track of all ghost objects and call them here + //m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher); + } + + + +}; + +#endif + diff --git a/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp b/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp new file mode 100644 index 0000000..4353cda --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp @@ -0,0 +1,842 @@ +#include "btInternalEdgeUtility.h" + +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" +#include "LinearMath/btIDebugDraw.h" + + +//#define DEBUG_INTERNAL_EDGE + +#ifdef DEBUG_INTERNAL_EDGE +#include +#endif //DEBUG_INTERNAL_EDGE + + +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW +static btIDebugDraw* gDebugDrawer = 0; + +void btSetDebugDrawer(btIDebugDraw* debugDrawer) +{ + gDebugDrawer = debugDrawer; +} + +static void btDebugDrawLine(const btVector3& from,const btVector3& to, const btVector3& color) +{ + if (gDebugDrawer) + gDebugDrawer->drawLine(from,to,color); +} +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + +static int btGetHash(int partId, int triangleIndex) +{ + int hash = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex; + return hash; +} + + + +static btScalar btGetAngle(const btVector3& edgeA, const btVector3& normalA,const btVector3& normalB) +{ + const btVector3 refAxis0 = edgeA; + const btVector3 refAxis1 = normalA; + const btVector3 swingAxis = normalB; + btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); + return angle; +} + + +struct btConnectivityProcessor : public btTriangleCallback +{ + int m_partIdA; + int m_triangleIndexA; + btVector3* m_triangleVerticesA; + btTriangleInfoMap* m_triangleInfoMap; + + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + //skip self-collisions + if ((m_partIdA == partId) && (m_triangleIndexA == triangleIndex)) + return; + + //skip duplicates (disabled for now) + //if ((m_partIdA <= partId) && (m_triangleIndexA <= triangleIndex)) + // return; + + //search for shared vertices and edges + int numshared = 0; + int sharedVertsA[3]={-1,-1,-1}; + int sharedVertsB[3]={-1,-1,-1}; + + ///skip degenerate triangles + btScalar crossBSqr = ((triangle[1]-triangle[0]).cross(triangle[2]-triangle[0])).length2(); + if (crossBSqr < m_triangleInfoMap->m_equalVertexThreshold) + return; + + + btScalar crossASqr = ((m_triangleVerticesA[1]-m_triangleVerticesA[0]).cross(m_triangleVerticesA[2]-m_triangleVerticesA[0])).length2(); + ///skip degenerate triangles + if (crossASqr< m_triangleInfoMap->m_equalVertexThreshold) + return; + +#if 0 + printf("triangle A[0] = (%f,%f,%f)\ntriangle A[1] = (%f,%f,%f)\ntriangle A[2] = (%f,%f,%f)\n", + m_triangleVerticesA[0].getX(),m_triangleVerticesA[0].getY(),m_triangleVerticesA[0].getZ(), + m_triangleVerticesA[1].getX(),m_triangleVerticesA[1].getY(),m_triangleVerticesA[1].getZ(), + m_triangleVerticesA[2].getX(),m_triangleVerticesA[2].getY(),m_triangleVerticesA[2].getZ()); + + printf("partId=%d, triangleIndex=%d\n",partId,triangleIndex); + printf("triangle B[0] = (%f,%f,%f)\ntriangle B[1] = (%f,%f,%f)\ntriangle B[2] = (%f,%f,%f)\n", + triangle[0].getX(),triangle[0].getY(),triangle[0].getZ(), + triangle[1].getX(),triangle[1].getY(),triangle[1].getZ(), + triangle[2].getX(),triangle[2].getY(),triangle[2].getZ()); +#endif + + for (int i=0;i<3;i++) + { + for (int j=0;j<3;j++) + { + if ( (m_triangleVerticesA[i]-triangle[j]).length2() < m_triangleInfoMap->m_equalVertexThreshold) + { + sharedVertsA[numshared] = i; + sharedVertsB[numshared] = j; + numshared++; + ///degenerate case + if(numshared >= 3) + return; + } + } + ///degenerate case + if(numshared >= 3) + return; + } + switch (numshared) + { + case 0: + { + break; + } + case 1: + { + //shared vertex + break; + } + case 2: + { + //shared edge + //we need to make sure the edge is in the order V2V0 and not V0V2 so that the signs are correct + if (sharedVertsA[0] == 0 && sharedVertsA[1] == 2) + { + sharedVertsA[0] = 2; + sharedVertsA[1] = 0; + int tmp = sharedVertsB[1]; + sharedVertsB[1] = sharedVertsB[0]; + sharedVertsB[0] = tmp; + } + + int hash = btGetHash(m_partIdA,m_triangleIndexA); + + btTriangleInfo* info = m_triangleInfoMap->find(hash); + if (!info) + { + btTriangleInfo tmp; + m_triangleInfoMap->insert(hash,tmp); + info = m_triangleInfoMap->find(hash); + } + + int sumvertsA = sharedVertsA[0]+sharedVertsA[1]; + int otherIndexA = 3-sumvertsA; + + + btVector3 edge(m_triangleVerticesA[sharedVertsA[1]]-m_triangleVerticesA[sharedVertsA[0]]); + + btTriangleShape tA(m_triangleVerticesA[0],m_triangleVerticesA[1],m_triangleVerticesA[2]); + int otherIndexB = 3-(sharedVertsB[0]+sharedVertsB[1]); + + btTriangleShape tB(triangle[sharedVertsB[1]],triangle[sharedVertsB[0]],triangle[otherIndexB]); + //btTriangleShape tB(triangle[0],triangle[1],triangle[2]); + + btVector3 normalA; + btVector3 normalB; + tA.calcNormal(normalA); + tB.calcNormal(normalB); + edge.normalize(); + btVector3 edgeCrossA = edge.cross(normalA).normalize(); + + { + btVector3 tmp = m_triangleVerticesA[otherIndexA]-m_triangleVerticesA[sharedVertsA[0]]; + if (edgeCrossA.dot(tmp) < 0) + { + edgeCrossA*=-1; + } + } + + btVector3 edgeCrossB = edge.cross(normalB).normalize(); + + { + btVector3 tmp = triangle[otherIndexB]-triangle[sharedVertsB[0]]; + if (edgeCrossB.dot(tmp) < 0) + { + edgeCrossB*=-1; + } + } + + btScalar angle2 = 0; + btScalar ang4 = 0.f; + + + btVector3 calculatedEdge = edgeCrossA.cross(edgeCrossB); + btScalar len2 = calculatedEdge.length2(); + + btScalar correctedAngle(0); + btVector3 calculatedNormalB = normalA; + bool isConvex = false; + + if (len2m_planarEpsilon) + { + angle2 = 0.f; + ang4 = 0.f; + } else + { + + calculatedEdge.normalize(); + btVector3 calculatedNormalA = calculatedEdge.cross(edgeCrossA); + calculatedNormalA.normalize(); + angle2 = btGetAngle(calculatedNormalA,edgeCrossA,edgeCrossB); + ang4 = SIMD_PI-angle2; + btScalar dotA = normalA.dot(edgeCrossB); + ///@todo: check if we need some epsilon, due to floating point imprecision + isConvex = (dotA<0.); + + correctedAngle = isConvex ? ang4 : -ang4; + btQuaternion orn2(calculatedEdge,-correctedAngle); + calculatedNormalB = btMatrix3x3(orn2)*normalA; + + + } + + + + + + //alternatively use + //btVector3 calculatedNormalB2 = quatRotate(orn,normalA); + + + switch (sumvertsA) + { + case 1: + { + btVector3 edge = m_triangleVerticesA[0]-m_triangleVerticesA[1]; + btQuaternion orn(edge,-correctedAngle); + btVector3 computedNormalB = quatRotate(orn,normalA); + btScalar bla = computedNormalB.dot(normalB); + if (bla<0) + { + computedNormalB*=-1; + info->m_flags |= TRI_INFO_V0V1_SWAP_NORMALB; + } +#ifdef DEBUG_INTERNAL_EDGE + if ((computedNormalB-normalB).length()>0.0001) + { + printf("warning: normals not identical\n"); + } +#endif//DEBUG_INTERNAL_EDGE + + info->m_edgeV0V1Angle = -correctedAngle; + + if (isConvex) + info->m_flags |= TRI_INFO_V0V1_CONVEX; + break; + } + case 2: + { + btVector3 edge = m_triangleVerticesA[2]-m_triangleVerticesA[0]; + btQuaternion orn(edge,-correctedAngle); + btVector3 computedNormalB = quatRotate(orn,normalA); + if (computedNormalB.dot(normalB)<0) + { + computedNormalB*=-1; + info->m_flags |= TRI_INFO_V2V0_SWAP_NORMALB; + } + +#ifdef DEBUG_INTERNAL_EDGE + if ((computedNormalB-normalB).length()>0.0001) + { + printf("warning: normals not identical\n"); + } +#endif //DEBUG_INTERNAL_EDGE + info->m_edgeV2V0Angle = -correctedAngle; + if (isConvex) + info->m_flags |= TRI_INFO_V2V0_CONVEX; + break; + } + case 3: + { + btVector3 edge = m_triangleVerticesA[1]-m_triangleVerticesA[2]; + btQuaternion orn(edge,-correctedAngle); + btVector3 computedNormalB = quatRotate(orn,normalA); + if (computedNormalB.dot(normalB)<0) + { + info->m_flags |= TRI_INFO_V1V2_SWAP_NORMALB; + computedNormalB*=-1; + } +#ifdef DEBUG_INTERNAL_EDGE + if ((computedNormalB-normalB).length()>0.0001) + { + printf("warning: normals not identical\n"); + } +#endif //DEBUG_INTERNAL_EDGE + info->m_edgeV1V2Angle = -correctedAngle; + + if (isConvex) + info->m_flags |= TRI_INFO_V1V2_CONVEX; + break; + } + } + + break; + } + default: + { + // printf("warning: duplicate triangle\n"); + } + + } + } +}; +///////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// + +void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap) +{ + //the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there! + if (trimeshShape->getTriangleInfoMap()) + return; + + trimeshShape->setTriangleInfoMap(triangleInfoMap); + + btStridingMeshInterface* meshInterface = trimeshShape->getMeshInterface(); + const btVector3& meshScaling = meshInterface->getScaling(); + + for (int partId = 0; partId< meshInterface->getNumSubParts();partId++) + { + const unsigned char *vertexbase = 0; + int numverts = 0; + PHY_ScalarType type = PHY_INTEGER; + int stride = 0; + const unsigned char *indexbase = 0; + int indexstride = 0; + int numfaces = 0; + PHY_ScalarType indicestype = PHY_INTEGER; + //PHY_ScalarType indexType=0; + + btVector3 triangleVerts[3]; + meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,partId); + btVector3 aabbMin,aabbMax; + + for (int triangleIndex = 0 ; triangleIndex < numfaces;triangleIndex++) + { + unsigned int* gfxbase = (unsigned int*)(indexbase+triangleIndex*indexstride); + + for (int j=2;j>=0;j--) + { + + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + if (type == PHY_FLOAT) + { + float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); + triangleVerts[j] = btVector3( + graphicsbase[0]*meshScaling.getX(), + graphicsbase[1]*meshScaling.getY(), + graphicsbase[2]*meshScaling.getZ()); + } + else + { + double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); + triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*meshScaling.getX()), btScalar(graphicsbase[1]*meshScaling.getY()), btScalar(graphicsbase[2]*meshScaling.getZ())); + } + } + aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + aabbMin.setMin(triangleVerts[0]); + aabbMax.setMax(triangleVerts[0]); + aabbMin.setMin(triangleVerts[1]); + aabbMax.setMax(triangleVerts[1]); + aabbMin.setMin(triangleVerts[2]); + aabbMax.setMax(triangleVerts[2]); + + btConnectivityProcessor connectivityProcessor; + connectivityProcessor.m_partIdA = partId; + connectivityProcessor.m_triangleIndexA = triangleIndex; + connectivityProcessor.m_triangleVerticesA = &triangleVerts[0]; + connectivityProcessor.m_triangleInfoMap = triangleInfoMap; + + trimeshShape->processAllTriangles(&connectivityProcessor,aabbMin,aabbMax); + } + + } + +} + + + + +// Given a point and a line segment (defined by two points), compute the closest point +// in the line. Cap the point at the endpoints of the line segment. +void btNearestPointInLineSegment(const btVector3 &point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint) +{ + btVector3 lineDelta = line1 - line0; + + // Handle degenerate lines + if ( lineDelta.fuzzyZero()) + { + nearestPoint = line0; + } + else + { + btScalar delta = (point-line0).dot(lineDelta) / (lineDelta).dot(lineDelta); + + // Clamp the point to conform to the segment's endpoints + if ( delta < 0 ) + delta = 0; + else if ( delta > 1 ) + delta = 1; + + nearestPoint = line0 + lineDelta*delta; + } +} + + + + +bool btClampNormal(const btVector3& edge,const btVector3& tri_normal_org,const btVector3& localContactNormalOnB, btScalar correctedEdgeAngle, btVector3 & clampedLocalNormal) +{ + btVector3 tri_normal = tri_normal_org; + //we only have a local triangle normal, not a local contact normal -> only normal in world space... + //either compute the current angle all in local space, or all in world space + + btVector3 edgeCross = edge.cross(tri_normal).normalize(); + btScalar curAngle = btGetAngle(edgeCross,tri_normal,localContactNormalOnB); + + if (correctedEdgeAngle<0) + { + if (curAngle < correctedEdgeAngle) + { + btScalar diffAngle = correctedEdgeAngle-curAngle; + btQuaternion rotation(edge,diffAngle ); + clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB; + return true; + } + } + + if (correctedEdgeAngle>=0) + { + if (curAngle > correctedEdgeAngle) + { + btScalar diffAngle = correctedEdgeAngle-curAngle; + btQuaternion rotation(edge,diffAngle ); + clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB; + return true; + } + } + return false; +} + + + +/// Changes a btManifoldPoint collision normal to the normal from the mesh. +void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* colObj0,const btCollisionObject* colObj1, int partId0, int index0, int normalAdjustFlags) +{ + //btAssert(colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE); + if (colObj0->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE) + return; + + btBvhTriangleMeshShape* trimesh = 0; + + if( colObj0->getRootCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE ) + trimesh = ((btScaledBvhTriangleMeshShape*)colObj0->getRootCollisionShape())->getChildShape(); + else + trimesh = (btBvhTriangleMeshShape*)colObj0->getRootCollisionShape(); + + btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*) trimesh->getTriangleInfoMap(); + if (!triangleInfoMapPtr) + return; + + int hash = btGetHash(partId0,index0); + + + btTriangleInfo* info = triangleInfoMapPtr->find(hash); + if (!info) + return; + + btScalar frontFacing = (normalAdjustFlags & BT_TRIANGLE_CONVEX_BACKFACE_MODE)==0? 1.f : -1.f; + + const btTriangleShape* tri_shape = static_cast(colObj0->getCollisionShape()); + btVector3 v0,v1,v2; + tri_shape->getVertex(0,v0); + tri_shape->getVertex(1,v1); + tri_shape->getVertex(2,v2); + + btVector3 center = (v0+v1+v2)*btScalar(1./3.); + + btVector3 red(1,0,0), green(0,1,0),blue(0,0,1),white(1,1,1),black(0,0,0); + btVector3 tri_normal; + tri_shape->calcNormal(tri_normal); + + //btScalar dot = tri_normal.dot(cp.m_normalWorldOnB); + btVector3 nearest; + btNearestPointInLineSegment(cp.m_localPointB,v0,v1,nearest); + + btVector3 contact = cp.m_localPointB; +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + const btTransform& tr = colObj0->getWorldTransform(); + btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,red); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + + + bool isNearEdge = false; + + int numConcaveEdgeHits = 0; + int numConvexEdgeHits = 0; + + btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB; + localContactNormalOnB.normalize();//is this necessary? + + // Get closest edge + int bestedge=-1; + btScalar disttobestedge=BT_LARGE_FLOAT; + // + // Edge 0 -> 1 + if (btFabs(info->m_edgeV0V1Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) + { + btVector3 nearest; + btNearestPointInLineSegment( cp.m_localPointB, v0, v1, nearest ); + btScalar len=(contact-nearest).length(); + // + if( len < disttobestedge ) + { + bestedge=0; + disttobestedge=len; + } + } + // Edge 1 -> 2 + if (btFabs(info->m_edgeV1V2Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) + { + btVector3 nearest; + btNearestPointInLineSegment( cp.m_localPointB, v1, v2, nearest ); + btScalar len=(contact-nearest).length(); + // + if( len < disttobestedge ) + { + bestedge=1; + disttobestedge=len; + } + } + // Edge 2 -> 0 + if (btFabs(info->m_edgeV2V0Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) + { + btVector3 nearest; + btNearestPointInLineSegment( cp.m_localPointB, v2, v0, nearest ); + btScalar len=(contact-nearest).length(); + // + if( len < disttobestedge ) + { + bestedge=2; + disttobestedge=len; + } + } + +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btVector3 upfix=tri_normal * btVector3(0.1f,0.1f,0.1f); + btDebugDrawLine(tr * v0 + upfix, tr * v1 + upfix, red ); +#endif + if (btFabs(info->m_edgeV0V1Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) + { +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black); +#endif + btScalar len = (contact-nearest).length(); + if(lenm_edgeDistanceThreshold) + if( bestedge==0 ) + { + btVector3 edge(v0-v1); + isNearEdge = true; + + if (info->m_edgeV0V1Angle==btScalar(0)) + { + numConcaveEdgeHits++; + } else + { + + bool isEdgeConvex = (info->m_flags & TRI_INFO_V0V1_CONVEX); + btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1); + #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white); + #endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + btVector3 nA = swapFactor * tri_normal; + + btQuaternion orn(edge,info->m_edgeV0V1Angle); + btVector3 computedNormalB = quatRotate(orn,tri_normal); + if (info->m_flags & TRI_INFO_V0V1_SWAP_NORMALB) + computedNormalB*=-1; + btVector3 nB = swapFactor*computedNormalB; + + btScalar NdotA = localContactNormalOnB.dot(nA); + btScalar NdotB = localContactNormalOnB.dot(nB); + bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotBm_convexEpsilon); + +#ifdef DEBUG_INTERNAL_EDGE + { + + btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red); + } +#endif //DEBUG_INTERNAL_EDGE + + + if (backFacingNormal) + { + numConcaveEdgeHits++; + } + else + { + numConvexEdgeHits++; + btVector3 clampedLocalNormal; + bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV0V1Angle,clampedLocalNormal); + if (isClamped) + { + if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0)) + { + btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal; + // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB); + cp.m_normalWorldOnB = newNormal; + // Reproject collision point along normal. (what about cp.m_distance1?) + cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; + cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB); + + } + } + } + } + } + } + + btNearestPointInLineSegment(contact,v1,v2,nearest); +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,green); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr * v1 + upfix, tr * v2 + upfix , green ); +#endif + + if (btFabs(info->m_edgeV1V2Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) + { +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + + + btScalar len = (contact-nearest).length(); + if(lenm_edgeDistanceThreshold) + if( bestedge==1 ) + { + isNearEdge = true; +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + btVector3 edge(v1-v2); + + isNearEdge = true; + + if (info->m_edgeV1V2Angle == btScalar(0)) + { + numConcaveEdgeHits++; + } else + { + bool isEdgeConvex = (info->m_flags & TRI_INFO_V1V2_CONVEX)!=0; + btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1); + #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white); + #endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + btVector3 nA = swapFactor * tri_normal; + + btQuaternion orn(edge,info->m_edgeV1V2Angle); + btVector3 computedNormalB = quatRotate(orn,tri_normal); + if (info->m_flags & TRI_INFO_V1V2_SWAP_NORMALB) + computedNormalB*=-1; + btVector3 nB = swapFactor*computedNormalB; + +#ifdef DEBUG_INTERNAL_EDGE + { + btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red); + } +#endif //DEBUG_INTERNAL_EDGE + + + btScalar NdotA = localContactNormalOnB.dot(nA); + btScalar NdotB = localContactNormalOnB.dot(nB); + bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotBm_convexEpsilon); + + if (backFacingNormal) + { + numConcaveEdgeHits++; + } + else + { + numConvexEdgeHits++; + btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB; + btVector3 clampedLocalNormal; + bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV1V2Angle,clampedLocalNormal); + if (isClamped) + { + if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0)) + { + btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal; + // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB); + cp.m_normalWorldOnB = newNormal; + // Reproject collision point along normal. + cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; + cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB); + } + } + } + } + } + } + + btNearestPointInLineSegment(contact,v2,v0,nearest); +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,blue); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr * v2 + upfix, tr * v0 + upfix , blue ); +#endif + + if (btFabs(info->m_edgeV2V0Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) + { + +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + btScalar len = (contact-nearest).length(); + if(lenm_edgeDistanceThreshold) + if( bestedge==2 ) + { + isNearEdge = true; +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + btVector3 edge(v2-v0); + + if (info->m_edgeV2V0Angle==btScalar(0)) + { + numConcaveEdgeHits++; + } else + { + + bool isEdgeConvex = (info->m_flags & TRI_INFO_V2V0_CONVEX)!=0; + btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1); + #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white); + #endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + btVector3 nA = swapFactor * tri_normal; + btQuaternion orn(edge,info->m_edgeV2V0Angle); + btVector3 computedNormalB = quatRotate(orn,tri_normal); + if (info->m_flags & TRI_INFO_V2V0_SWAP_NORMALB) + computedNormalB*=-1; + btVector3 nB = swapFactor*computedNormalB; + +#ifdef DEBUG_INTERNAL_EDGE + { + btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red); + } +#endif //DEBUG_INTERNAL_EDGE + + btScalar NdotA = localContactNormalOnB.dot(nA); + btScalar NdotB = localContactNormalOnB.dot(nB); + bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotBm_convexEpsilon); + + if (backFacingNormal) + { + numConcaveEdgeHits++; + } + else + { + numConvexEdgeHits++; + // printf("hitting convex edge\n"); + + + btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB; + btVector3 clampedLocalNormal; + bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB,info->m_edgeV2V0Angle,clampedLocalNormal); + if (isClamped) + { + if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0)) + { + btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal; + // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB); + cp.m_normalWorldOnB = newNormal; + // Reproject collision point along normal. + cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; + cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB); + } + } + } + } + + + } + } + +#ifdef DEBUG_INTERNAL_EDGE + { + btVector3 color(0,1,1); + btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+cp.m_normalWorldOnB*10,color); + } +#endif //DEBUG_INTERNAL_EDGE + + if (isNearEdge) + { + + if (numConcaveEdgeHits>0) + { + if ((normalAdjustFlags & BT_TRIANGLE_CONCAVE_DOUBLE_SIDED)!=0) + { + //fix tri_normal so it pointing the same direction as the current local contact normal + if (tri_normal.dot(localContactNormalOnB) < 0) + { + tri_normal *= -1; + } + cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis()*tri_normal; + } else + { + btVector3 newNormal = tri_normal *frontFacing; + //if the tri_normal is pointing opposite direction as the current local contact normal, skip it + btScalar d = newNormal.dot(localContactNormalOnB) ; + if (d< 0) + { + return; + } + //modify the normal to be the triangle normal (or backfacing normal) + cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis() *newNormal; + } + + // Reproject collision point along normal. + cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; + cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB); + } + } +} diff --git a/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h b/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h new file mode 100644 index 0000000..9efb012 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h @@ -0,0 +1,46 @@ + +#ifndef BT_INTERNAL_EDGE_UTILITY_H +#define BT_INTERNAL_EDGE_UTILITY_H + +#include "LinearMath/btHashMap.h" +#include "LinearMath/btVector3.h" + +#include "BulletCollision/CollisionShapes/btTriangleInfoMap.h" + +///The btInternalEdgeUtility helps to avoid or reduce artifacts due to wrong collision normals caused by internal edges. +///See also http://code.google.com/p/bullet/issues/detail?id=27 + +class btBvhTriangleMeshShape; +class btCollisionObject; +class btManifoldPoint; +class btIDebugDraw; + + + +enum btInternalEdgeAdjustFlags +{ + BT_TRIANGLE_CONVEX_BACKFACE_MODE = 1, + BT_TRIANGLE_CONCAVE_DOUBLE_SIDED = 2, //double sided options are experimental, single sided is recommended + BT_TRIANGLE_CONVEX_DOUBLE_SIDED = 4 +}; + + +///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo' +void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap); + + +///Call the btFixMeshNormal to adjust the collision normal, using the triangle info map (generated using btGenerateInternalEdgeInfo) +///If this info map is missing, or the triangle is not store in this map, nothing will be done +void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* trimeshColObj0,const btCollisionObject* otherColObj1, int partId0, int index0, int normalAdjustFlags = 0); + +///Enable the BT_INTERNAL_EDGE_DEBUG_DRAW define and call btSetDebugDrawer, to get visual info to see if the internal edge utility works properly. +///If the utility doesn't work properly, you might have to adjust the threshold values in btTriangleInfoMap +//#define BT_INTERNAL_EDGE_DEBUG_DRAW + +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW +void btSetDebugDrawer(btIDebugDraw* debugDrawer); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + +#endif //BT_INTERNAL_EDGE_UTILITY_H + diff --git a/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp new file mode 100644 index 0000000..bf24246 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp @@ -0,0 +1,135 @@ +/* +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 "btManifoldResult.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" + + +///This is to allow MaterialCombiner/Custom Friction/Restitution values +ContactAddedCallback gContactAddedCallback=0; + +///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; +inline btScalar calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1) +{ + btScalar friction = body0->getFriction() * body1->getFriction(); + + const btScalar MAX_FRICTION = btScalar(10.); + if (friction < -MAX_FRICTION) + friction = -MAX_FRICTION; + if (friction > MAX_FRICTION) + friction = MAX_FRICTION; + return friction; + +} + +inline btScalar calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1) +{ + return body0->getRestitution() * body1->getRestitution(); +} + + + +btManifoldResult::btManifoldResult(btCollisionObject* body0,btCollisionObject* body1) + :m_manifoldPtr(0), + m_body0(body0), + m_body1(body1) +#ifdef DEBUG_PART_INDEX + ,m_partId0(-1), + m_partId1(-1), + m_index0(-1), + m_index1(-1) +#endif //DEBUG_PART_INDEX +{ + m_rootTransA = body0->getWorldTransform(); + m_rootTransB = body1->getWorldTransform(); +} + + +void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) +{ + btAssert(m_manifoldPtr); + //order in manifold needs to match + + if (depth > m_manifoldPtr->getContactBreakingThreshold()) +// if (depth > m_manifoldPtr->getContactProcessingThreshold()) + return; + + bool isSwapped = m_manifoldPtr->getBody0() != m_body0; + + btVector3 pointA = pointInWorld + normalOnBInWorld * depth; + + btVector3 localA; + btVector3 localB; + + if (isSwapped) + { + localA = m_rootTransB.invXform(pointA ); + localB = m_rootTransA.invXform(pointInWorld); + } else + { + localA = m_rootTransA.invXform(pointA ); + localB = m_rootTransB.invXform(pointInWorld); + } + + btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth); + newPt.m_positionWorldOnA = pointA; + newPt.m_positionWorldOnB = pointInWorld; + + int insertIndex = m_manifoldPtr->getCacheEntry(newPt); + + newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1); + newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1); + + //BP mod, store contact triangles. + if (isSwapped) + { + newPt.m_partId0 = m_partId1; + newPt.m_partId1 = m_partId0; + newPt.m_index0 = m_index1; + newPt.m_index1 = m_index0; + } else + { + newPt.m_partId0 = m_partId0; + newPt.m_partId1 = m_partId1; + newPt.m_index0 = m_index0; + newPt.m_index1 = m_index1; + } + //printf("depth=%f\n",depth); + ///@todo, check this for any side effects + if (insertIndex >= 0) + { + //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex); + m_manifoldPtr->replaceContactPoint(newPt,insertIndex); + } else + { + insertIndex = m_manifoldPtr->addManifoldPoint(newPt); + } + + //User can override friction and/or restitution + if (gContactAddedCallback && + //and if either of the two bodies requires custom material + ((m_body0->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) || + (m_body1->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK))) + { + //experimental feature info, for per-triangle material etc. + btCollisionObject* obj0 = isSwapped? m_body1 : m_body0; + btCollisionObject* obj1 = isSwapped? m_body0 : m_body1; + (*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0,newPt.m_partId0,newPt.m_index0,obj1,newPt.m_partId1,newPt.m_index1); + } + +} + diff --git a/src/BulletCollision/CollisionDispatch/btManifoldResult.h b/src/BulletCollision/CollisionDispatch/btManifoldResult.h new file mode 100644 index 0000000..18199b4 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btManifoldResult.h @@ -0,0 +1,128 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_MANIFOLD_RESULT_H +#define BT_MANIFOLD_RESULT_H + +class btCollisionObject; +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +class btManifoldPoint; + +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" + +#include "LinearMath/btTransform.h" + +typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1); +extern ContactAddedCallback gContactAddedCallback; + +//#define DEBUG_PART_INDEX 1 + + +///btManifoldResult is a helper class to manage contact results. +class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result +{ +protected: + + btPersistentManifold* m_manifoldPtr; + + //we need this for compounds + btTransform m_rootTransA; + btTransform m_rootTransB; + + btCollisionObject* m_body0; + btCollisionObject* m_body1; + int m_partId0; + int m_partId1; + int m_index0; + int m_index1; + + +public: + + btManifoldResult() +#ifdef DEBUG_PART_INDEX + : + m_partId0(-1), + m_partId1(-1), + m_index0(-1), + m_index1(-1) +#endif //DEBUG_PART_INDEX + { + } + + btManifoldResult(btCollisionObject* body0,btCollisionObject* body1); + + virtual ~btManifoldResult() {}; + + void setPersistentManifold(btPersistentManifold* manifoldPtr) + { + m_manifoldPtr = manifoldPtr; + } + + const btPersistentManifold* getPersistentManifold() const + { + return m_manifoldPtr; + } + btPersistentManifold* getPersistentManifold() + { + return m_manifoldPtr; + } + + virtual void setShapeIdentifiersA(int partId0,int index0) + { + m_partId0=partId0; + m_index0=index0; + } + + virtual void setShapeIdentifiersB( int partId1,int index1) + { + m_partId1=partId1; + m_index1=index1; + } + + + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth); + + SIMD_FORCE_INLINE void refreshContactPoints() + { + btAssert(m_manifoldPtr); + if (!m_manifoldPtr->getNumContacts()) + return; + + bool isSwapped = m_manifoldPtr->getBody0() != m_body0; + + if (isSwapped) + { + m_manifoldPtr->refreshContactPoints(m_rootTransB,m_rootTransA); + } else + { + m_manifoldPtr->refreshContactPoints(m_rootTransA,m_rootTransB); + } + } + + const btCollisionObject* getBody0Internal() const + { + return m_body0; + } + + const btCollisionObject* getBody1Internal() const + { + return m_body1; + } + +}; + +#endif //BT_MANIFOLD_RESULT_H diff --git a/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp new file mode 100644 index 0000000..871c644 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp @@ -0,0 +1,450 @@ + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "LinearMath/btScalar.h" +#include "btSimulationIslandManager.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" + +//#include +#include "LinearMath/btQuickprof.h" + +btSimulationIslandManager::btSimulationIslandManager(): +m_splitIslands(true) +{ +} + +btSimulationIslandManager::~btSimulationIslandManager() +{ +} + + +void btSimulationIslandManager::initUnionFind(int n) +{ + m_unionFind.reset(n); +} + + +void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld) +{ + + { + btOverlappingPairCache* pairCachePtr = colWorld->getPairCache(); + const int numOverlappingPairs = pairCachePtr->getNumOverlappingPairs(); + if (numOverlappingPairs) + { + btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr(); + + for (int i=0;im_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; + + if (((colObj0) && ((colObj0)->mergesSimulationIslands())) && + ((colObj1) && ((colObj1)->mergesSimulationIslands()))) + { + + m_unionFind.unite((colObj0)->getIslandTag(), + (colObj1)->getIslandTag()); + } + } + } + } +} + +#ifdef STATIC_SIMULATION_ISLAND_OPTIMIZATION +void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher) +{ + + // put the index into m_controllers into m_tag + int index = 0; + { + + int i; + for (i=0;igetCollisionObjectArray().size(); i++) + { + btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; + //Adding filtering here + if (!collisionObject->isStaticOrKinematicObject()) + { + collisionObject->setIslandTag(index++); + } + collisionObject->setCompanionId(-1); + collisionObject->setHitFraction(btScalar(1.)); + } + } + // do the union find + + initUnionFind( index ); + + findUnions(dispatcher,colWorld); +} + +void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld) +{ + // put the islandId ('find' value) into m_tag + { + int index = 0; + int i; + for (i=0;igetCollisionObjectArray().size();i++) + { + btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; + if (!collisionObject->isStaticOrKinematicObject()) + { + collisionObject->setIslandTag( m_unionFind.find(index) ); + //Set the correct object offset in Collision Object Array + m_unionFind.getElement(index).m_sz = i; + collisionObject->setCompanionId(-1); + index++; + } else + { + collisionObject->setIslandTag(-1); + collisionObject->setCompanionId(-2); + } + } + } +} + + +#else //STATIC_SIMULATION_ISLAND_OPTIMIZATION +void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher) +{ + + initUnionFind( int (colWorld->getCollisionObjectArray().size())); + + // put the index into m_controllers into m_tag + { + + int index = 0; + int i; + for (i=0;igetCollisionObjectArray().size(); i++) + { + btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; + collisionObject->setIslandTag(index); + collisionObject->setCompanionId(-1); + collisionObject->setHitFraction(btScalar(1.)); + index++; + + } + } + // do the union find + + findUnions(dispatcher,colWorld); +} + +void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld) +{ + // put the islandId ('find' value) into m_tag + { + + + int index = 0; + int i; + for (i=0;igetCollisionObjectArray().size();i++) + { + btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; + if (!collisionObject->isStaticOrKinematicObject()) + { + collisionObject->setIslandTag( m_unionFind.find(index) ); + collisionObject->setCompanionId(-1); + } else + { + collisionObject->setIslandTag(-1); + collisionObject->setCompanionId(-2); + } + index++; + } + } +} + +#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION + +inline int getIslandId(const btPersistentManifold* lhs) +{ + int islandId; + const btCollisionObject* rcolObj0 = static_cast(lhs->getBody0()); + const btCollisionObject* rcolObj1 = static_cast(lhs->getBody1()); + islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag(); + return islandId; + +} + + + +/// function object that routes calls to operator< +class btPersistentManifoldSortPredicate +{ + public: + + SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs ) const + { + return getIslandId(lhs) < getIslandId(rhs); + } +}; + + +void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld) +{ + + BT_PROFILE("islandUnionFindAndQuickSort"); + + btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); + + m_islandmanifold.resize(0); + + //we are going to sort the unionfind array, and store the element id in the size + //afterwards, we clean unionfind, to make sure no-one uses it anymore + + getUnionFind().sortIslands(); + int numElem = getUnionFind().getNumElements(); + + int endIslandIndex=1; + int startIslandIndex; + + + //update the sleeping state for bodies, if all are sleeping + for ( startIslandIndex=0;startIslandIndexgetIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) + { +// printf("error in island management\n"); + } + + btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); + if (colObj0->getIslandTag() == islandId) + { + if (colObj0->getActivationState()== ACTIVE_TAG) + { + allSleeping = false; + } + if (colObj0->getActivationState()== DISABLE_DEACTIVATION) + { + allSleeping = false; + } + } + } + + + if (allSleeping) + { + int idx; + for (idx=startIslandIndex;idxgetIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) + { +// printf("error in island management\n"); + } + + btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); + + if (colObj0->getIslandTag() == islandId) + { + colObj0->setActivationState( ISLAND_SLEEPING ); + } + } + } else + { + + int idx; + for (idx=startIslandIndex;idxgetIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) + { +// printf("error in island management\n"); + } + + btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); + + if (colObj0->getIslandTag() == islandId) + { + if ( colObj0->getActivationState() == ISLAND_SLEEPING) + { + colObj0->setActivationState( WANTS_DEACTIVATION); + colObj0->setDeactivationTime(0.f); + } + } + } + } + } + + + int i; + int maxNumManifolds = dispatcher->getNumManifolds(); + +//#define SPLIT_ISLANDS 1 +//#ifdef SPLIT_ISLANDS + + +//#endif //SPLIT_ISLANDS + + + for (i=0;igetManifoldByIndexInternal(i); + + btCollisionObject* colObj0 = static_cast(manifold->getBody0()); + btCollisionObject* colObj1 = static_cast(manifold->getBody1()); + + ///@todo: check sleeping conditions! + if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) || + ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING)) + { + + //kinematic objects don't merge islands, but wake up all connected objects + if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) + { + if (colObj0->hasContactResponse()) + colObj1->activate(); + } + if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) + { + if (colObj1->hasContactResponse()) + colObj0->activate(); + } + if(m_splitIslands) + { + //filtering for response + if (dispatcher->needsResponse(colObj0,colObj1)) + m_islandmanifold.push_back(manifold); + } + } + } +} + + + +///@todo: this is random access, it can be walked 'cache friendly'! +void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback) +{ + btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); + + buildIslands(dispatcher,collisionWorld); + + int endIslandIndex=1; + int startIslandIndex; + int numElem = getUnionFind().getNumElements(); + + BT_PROFILE("processIslands"); + + if(!m_splitIslands) + { + btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer(); + int maxNumManifolds = dispatcher->getNumManifolds(); + callback->processIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1); + } + else + { + // Sort manifolds, based on islands + // Sort the vector using predicate and std::sort + //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate); + + int numManifolds = int (m_islandmanifold.size()); + + //tried a radix sort, but quicksort/heapsort seems still faster + //@todo rewrite island management + m_islandmanifold.quickSort(btPersistentManifoldSortPredicate()); + //m_islandmanifold.heapSort(btPersistentManifoldSortPredicate()); + + //now process all active islands (sets of manifolds for now) + + int startManifoldIndex = 0; + int endManifoldIndex = 1; + + //int islandId; + + + + // printf("Start Islands\n"); + + //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated + for ( startIslandIndex=0;startIslandIndexisActive()) + islandSleeping = false; + } + + + //find the accompanying contact manifold for this islandId + int numIslandManifolds = 0; + btPersistentManifold** startManifold = 0; + + if (startManifoldIndexprocessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId); + // printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds); + } + + if (numIslandManifolds) + { + startManifoldIndex = endManifoldIndex; + } + + m_islandBodies.resize(0); + } + } // else if(!splitIslands) + +} diff --git a/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h new file mode 100644 index 0000000..e24c6af --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h @@ -0,0 +1,81 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SIMULATION_ISLAND_MANAGER_H +#define BT_SIMULATION_ISLAND_MANAGER_H + +#include "BulletCollision/CollisionDispatch/btUnionFind.h" +#include "btCollisionCreateFunc.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "btCollisionObject.h" + +class btCollisionObject; +class btCollisionWorld; +class btDispatcher; +class btPersistentManifold; + + +///SimulationIslandManager creates and handles simulation islands, using btUnionFind +class btSimulationIslandManager +{ + btUnionFind m_unionFind; + + btAlignedObjectArray m_islandmanifold; + btAlignedObjectArray m_islandBodies; + + bool m_splitIslands; + +public: + btSimulationIslandManager(); + virtual ~btSimulationIslandManager(); + + + void initUnionFind(int n); + + + btUnionFind& getUnionFind() { return m_unionFind;} + + virtual void updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher); + virtual void storeIslandActivationState(btCollisionWorld* world); + + + void findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld); + + + + struct IslandCallback + { + virtual ~IslandCallback() {}; + + virtual void processIsland(btCollisionObject** bodies,int numBodies,class btPersistentManifold** manifolds,int numManifolds, int islandId) = 0; + }; + + void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback); + + void buildIslands(btDispatcher* dispatcher,btCollisionWorld* colWorld); + + bool getSplitIslands() + { + return m_splitIslands; + } + void setSplitIslands(bool doSplitIslands) + { + m_splitIslands = doSplitIslands; + } + +}; + +#endif //BT_SIMULATION_ISLAND_MANAGER_H + diff --git a/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp new file mode 100644 index 0000000..8df8769 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp @@ -0,0 +1,260 @@ +/* +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 "btSphereBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +//#include + +btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped) +: btActivatingCollisionAlgorithm(ci,col0,col1), +m_ownManifold(false), +m_manifoldPtr(mf), +m_isSwapped(isSwapped) +{ + btCollisionObject* sphereObj = m_isSwapped? col1 : col0; + btCollisionObject* boxObj = m_isSwapped? col0 : col1; + + if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObj,boxObj)) + { + m_manifoldPtr = m_dispatcher->getNewManifold(sphereObj,boxObj); + m_ownManifold = true; + } +} + + +btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + + + +void btSphereBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)dispatchInfo; + (void)resultOut; + if (!m_manifoldPtr) + return; + + btCollisionObject* sphereObj = m_isSwapped? body1 : body0; + btCollisionObject* boxObj = m_isSwapped? body0 : body1; + + + btSphereShape* sphere0 = (btSphereShape*)sphereObj->getCollisionShape(); + + btVector3 normalOnSurfaceB; + btVector3 pOnBox,pOnSphere; + btVector3 sphereCenter = sphereObj->getWorldTransform().getOrigin(); + btScalar radius = sphere0->getRadius(); + + btScalar dist = getSphereDistance(boxObj,pOnBox,pOnSphere,sphereCenter,radius); + + resultOut->setPersistentManifold(m_manifoldPtr); + + if (dist < SIMD_EPSILON) + { + btVector3 normalOnSurfaceB = (pOnBox- pOnSphere).normalize(); + + /// report a contact. internally this will be kept persistent, and contact reduction is done + + resultOut->addContactPoint(normalOnSurfaceB,pOnBox,dist); + + } + + if (m_ownManifold) + { + if (m_manifoldPtr->getNumContacts()) + { + resultOut->refreshContactPoints(); + } + } + +} + +btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + (void)col0; + (void)col1; + + //not yet + return btScalar(1.); +} + + +btScalar btSphereBoxCollisionAlgorithm::getSphereDistance(btCollisionObject* boxObj, btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius ) +{ + + btScalar margins; + btVector3 bounds[2]; + btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape(); + + bounds[0] = -boxShape->getHalfExtentsWithoutMargin(); + bounds[1] = boxShape->getHalfExtentsWithoutMargin(); + + margins = boxShape->getMargin();//also add sphereShape margin? + + const btTransform& m44T = boxObj->getWorldTransform(); + + btVector3 boundsVec[2]; + btScalar fPenetration; + + boundsVec[0] = bounds[0]; + boundsVec[1] = bounds[1]; + + btVector3 marginsVec( margins, margins, margins ); + + // add margins + bounds[0] += marginsVec; + bounds[1] -= marginsVec; + + ///////////////////////////////////////////////// + + btVector3 tmp, prel, n[6], normal, v3P; + btScalar fSep = btScalar(10000000.0), fSepThis; + + n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) ); + n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) ); + n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) ); + n[3].setValue( btScalar(1.0), btScalar(0.0), btScalar(0.0) ); + n[4].setValue( btScalar(0.0), btScalar(1.0), btScalar(0.0) ); + n[5].setValue( btScalar(0.0), btScalar(0.0), btScalar(1.0) ); + + // convert point in local space + prel = m44T.invXform( sphereCenter); + + bool bFound = false; + + v3P = prel; + + for (int i=0;i<6;i++) + { + int j = i<3? 0:1; + if ( (fSepThis = ((v3P-bounds[j]) .dot(n[i]))) > btScalar(0.0) ) + { + v3P = v3P - n[i]*fSepThis; + bFound = true; + } + } + + // + + if ( bFound ) + { + bounds[0] = boundsVec[0]; + bounds[1] = boundsVec[1]; + + normal = (prel - v3P).normalize(); + pointOnBox = v3P + normal*margins; + v3PointOnSphere = prel - normal*fRadius; + + if ( ((v3PointOnSphere - pointOnBox) .dot (normal)) > btScalar(0.0) ) + { + return btScalar(1.0); + } + + // transform back in world space + tmp = m44T( pointOnBox); + pointOnBox = tmp; + tmp = m44T( v3PointOnSphere); + v3PointOnSphere = tmp; + btScalar fSeps2 = (pointOnBox-v3PointOnSphere).length2(); + + //if this fails, fallback into deeper penetration case, below + if (fSeps2 > SIMD_EPSILON) + { + fSep = - btSqrt(fSeps2); + normal = (pointOnBox-v3PointOnSphere); + normal *= btScalar(1.)/fSep; + } + + return fSep; + } + + ////////////////////////////////////////////////// + // Deep penetration case + + fPenetration = getSpherePenetration( boxObj,pointOnBox, v3PointOnSphere, sphereCenter, fRadius,bounds[0],bounds[1] ); + + bounds[0] = boundsVec[0]; + bounds[1] = boundsVec[1]; + + if ( fPenetration <= btScalar(0.0) ) + return (fPenetration-margins); + else + return btScalar(1.0); +} + +btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btCollisionObject* boxObj,btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax) +{ + + btVector3 bounds[2]; + + bounds[0] = aabbMin; + bounds[1] = aabbMax; + + btVector3 p0, tmp, prel, n[6], normal; + btScalar fSep = btScalar(-10000000.0), fSepThis; + + // set p0 and normal to a default value to shup up GCC + p0.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); + normal.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); + + n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) ); + n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) ); + n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) ); + n[3].setValue( btScalar(1.0), btScalar(0.0), btScalar(0.0) ); + n[4].setValue( btScalar(0.0), btScalar(1.0), btScalar(0.0) ); + n[5].setValue( btScalar(0.0), btScalar(0.0), btScalar(1.0) ); + + const btTransform& m44T = boxObj->getWorldTransform(); + + // convert point in local space + prel = m44T.invXform( sphereCenter); + + /////////// + + for (int i=0;i<6;i++) + { + int j = i<3 ? 0:1; + if ( (fSepThis = ((prel-bounds[j]) .dot( n[i]))-fRadius) > btScalar(0.0) ) return btScalar(1.0); + if ( fSepThis > fSep ) + { + p0 = bounds[j]; normal = (btVector3&)n[i]; + fSep = fSepThis; + } + } + + pointOnBox = prel - normal*(normal.dot((prel-p0))); + v3PointOnSphere = pointOnBox + normal*fSep; + + // transform back in world space + tmp = m44T( pointOnBox); + pointOnBox = tmp; + tmp = m44T( v3PointOnSphere); v3PointOnSphere = tmp; + normal = (pointOnBox-v3PointOnSphere).normalize(); + + return fSep; + +} + diff --git a/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h new file mode 100644 index 0000000..60286ae --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h @@ -0,0 +1,75 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SPHERE_BOX_COLLISION_ALGORITHM_H +#define BT_SPHERE_BOX_COLLISION_ALGORITHM_H + +#include "btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +class btPersistentManifold; +#include "btCollisionDispatcher.h" + +#include "LinearMath/btVector3.h" + +/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection. +/// Other features are frame-coherency (persistent data) and collision response. +class btSphereBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + bool m_isSwapped; + +public: + + btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped); + + virtual ~btSphereBoxCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + + btScalar getSphereDistance( btCollisionObject* boxObj,btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius ); + + btScalar getSpherePenetration( btCollisionObject* boxObj, btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm)); + if (!m_swapped) + { + return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false); + } else + { + return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true); + } + } + }; + +}; + +#endif //BT_SPHERE_BOX_COLLISION_ALGORITHM_H + diff --git a/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp new file mode 100644 index 0000000..5c4e78f --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp @@ -0,0 +1,105 @@ +/* +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 "btSphereSphereCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" + +btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1) +: btActivatingCollisionAlgorithm(ci,col0,col1), +m_ownManifold(false), +m_manifoldPtr(mf) +{ + if (!m_manifoldPtr) + { + m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1); + m_ownManifold = true; + } +} + +btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)dispatchInfo; + + if (!m_manifoldPtr) + return; + + resultOut->setPersistentManifold(m_manifoldPtr); + + btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape(); + btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape(); + + btVector3 diff = col0->getWorldTransform().getOrigin()- col1->getWorldTransform().getOrigin(); + btScalar len = diff.length(); + btScalar radius0 = sphere0->getRadius(); + btScalar radius1 = sphere1->getRadius(); + +#ifdef CLEAR_MANIFOLD + m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting +#endif + + ///iff distance positive, don't generate a new contact + if ( len > (radius0+radius1)) + { +#ifndef CLEAR_MANIFOLD + resultOut->refreshContactPoints(); +#endif //CLEAR_MANIFOLD + return; + } + ///distance (negative means penetration) + btScalar dist = len - (radius0+radius1); + + btVector3 normalOnSurfaceB(1,0,0); + if (len > SIMD_EPSILON) + { + normalOnSurfaceB = diff / len; + } + + ///point on A (worldspace) + ///btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB; + ///point on B (worldspace) + btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB; + + /// report a contact. internally this will be kept persistent, and contact reduction is done + + + resultOut->addContactPoint(normalOnSurfaceB,pos1,dist); + +#ifndef CLEAR_MANIFOLD + resultOut->refreshContactPoints(); +#endif //CLEAR_MANIFOLD + +} + +btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)col0; + (void)col1; + (void)dispatchInfo; + (void)resultOut; + + //not yet + return btScalar(1.); +} diff --git a/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h new file mode 100644 index 0000000..e55acf2 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h @@ -0,0 +1,66 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H +#define BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H + +#include "btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "btCollisionDispatcher.h" + +class btPersistentManifold; + +/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. +/// Other features are frame-coherency (persistent data) and collision response. +/// Also provides the most basic sample for custom/user btCollisionAlgorithm +class btSphereSphereCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + +public: + btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); + + btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btActivatingCollisionAlgorithm(ci) {} + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + + virtual ~btSphereSphereCollisionAlgorithm(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm)); + return new(mem) btSphereSphereCollisionAlgorithm(0,ci,body0,body1); + } + }; + +}; + +#endif //BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H + diff --git a/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp new file mode 100644 index 0000000..c327c3f --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp @@ -0,0 +1,84 @@ +/* +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 "btSphereTriangleCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "SphereTriangleDetector.h" + + +btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1,bool swapped) +: btActivatingCollisionAlgorithm(ci,col0,col1), +m_ownManifold(false), +m_manifoldPtr(mf), +m_swapped(swapped) +{ + if (!m_manifoldPtr) + { + m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1); + m_ownManifold = true; + } +} + +btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + if (!m_manifoldPtr) + return; + + btCollisionObject* sphereObj = m_swapped? col1 : col0; + btCollisionObject* triObj = m_swapped? col0 : col1; + + btSphereShape* sphere = (btSphereShape*)sphereObj->getCollisionShape(); + btTriangleShape* triangle = (btTriangleShape*)triObj->getCollisionShape(); + + /// report a contact. internally this will be kept persistent, and contact reduction is done + resultOut->setPersistentManifold(m_manifoldPtr); + SphereTriangleDetector detector(sphere,triangle, m_manifoldPtr->getContactBreakingThreshold()); + + btDiscreteCollisionDetectorInterface::ClosestPointInput input; + input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);///@todo: tighter bounds + input.m_transformA = sphereObj->getWorldTransform(); + input.m_transformB = triObj->getWorldTransform(); + + bool swapResults = m_swapped; + + detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults); + + if (m_ownManifold) + resultOut->refreshContactPoints(); + +} + +btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + (void)col0; + (void)col1; + + //not yet + return btScalar(1.); +} diff --git a/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h new file mode 100644 index 0000000..7c6c4d8 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h @@ -0,0 +1,69 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H +#define BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H + +#include "btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +class btPersistentManifold; +#include "btCollisionDispatcher.h" + +/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. +/// Other features are frame-coherency (persistent data) and collision response. +/// Also provides the most basic sample for custom/user btCollisionAlgorithm +class btSphereTriangleCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + bool m_swapped; + +public: + btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool swapped); + + btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btActivatingCollisionAlgorithm(ci) {} + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + + virtual ~btSphereTriangleCollisionAlgorithm(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm)); + + return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped); + } + }; + +}; + +#endif //BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H + diff --git a/src/BulletCollision/CollisionDispatch/btUnionFind.cpp b/src/BulletCollision/CollisionDispatch/btUnionFind.cpp new file mode 100644 index 0000000..5222933 --- /dev/null +++ b/src/BulletCollision/CollisionDispatch/btUnionFind.cpp @@ -0,0 +1,82 @@ +/* +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 "btUnionFind.h" + + + +btUnionFind::~btUnionFind() +{ + Free(); + +} + +btUnionFind::btUnionFind() +{ + +} + +void btUnionFind::allocate(int N) +{ + m_elements.resize(N); +} +void btUnionFind::Free() +{ + m_elements.clear(); +} + + +void btUnionFind::reset(int N) +{ + allocate(N); + + for (int i = 0; i < N; i++) + { + m_elements[i].m_id = i; m_elements[i].m_sz = 1; + } +} + + +class btUnionFindElementSortPredicate +{ + public: + + bool operator() ( const btElement& lhs, const btElement& rhs ) const + { + return lhs.m_id < rhs.m_id; + } +}; + +///this is a special operation, destroying the content of btUnionFind. +///it sorts the elements, based on island id, in order to make it easy to iterate over islands +void btUnionFind::sortIslands() +{ + + //first store the original body index, and islandId + int numElements = m_elements.size(); + + for (int i=0;i m_elements; + + public: + + btUnionFind(); + ~btUnionFind(); + + + //this is a special operation, destroying the content of btUnionFind. + //it sorts the elements, based on island id, in order to make it easy to iterate over islands + void sortIslands(); + + void reset(int N); + + SIMD_FORCE_INLINE int getNumElements() const + { + return int(m_elements.size()); + } + SIMD_FORCE_INLINE bool isRoot(int x) const + { + return (x == m_elements[x].m_id); + } + + btElement& getElement(int index) + { + return m_elements[index]; + } + const btElement& getElement(int index) const + { + return m_elements[index]; + } + + void allocate(int N); + void Free(); + + + + + int find(int p, int q) + { + return (find(p) == find(q)); + } + + void unite(int p, int q) + { + int i = find(p), j = find(q); + if (i == j) + return; + +#ifndef USE_PATH_COMPRESSION + //weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) ) + if (m_elements[i].m_sz < m_elements[j].m_sz) + { + m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz; + } + else + { + m_elements[j].m_id = i; m_elements[i].m_sz += m_elements[j].m_sz; + } +#else + m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz; +#endif //USE_PATH_COMPRESSION + } + + int find(int x) + { + //btAssert(x < m_N); + //btAssert(x >= 0); + + while (x != m_elements[x].m_id) + { + //not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically + + #ifdef USE_PATH_COMPRESSION + const btElement* elementPtr = &m_elements[m_elements[x].m_id]; + m_elements[x].m_id = elementPtr->m_id; + x = elementPtr->m_id; + #else// + x = m_elements[x].m_id; + #endif + //btAssert(x < m_N); + //btAssert(x >= 0); + + } + return x; + } + + + }; + + +#endif //BT_UNION_FIND_H diff --git a/src/BulletCollision/CollisionShapes/btBox2dShape.cpp b/src/BulletCollision/CollisionShapes/btBox2dShape.cpp new file mode 100644 index 0000000..ecce028 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btBox2dShape.cpp @@ -0,0 +1,42 @@ +/* +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 "btBox2dShape.h" + + +//{ + + +void btBox2dShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax); +} + + +void btBox2dShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + //btScalar margin = btScalar(0.); + btVector3 halfExtents = getHalfExtentsWithMargin(); + + btScalar lx=btScalar(2.)*(halfExtents.x()); + btScalar ly=btScalar(2.)*(halfExtents.y()); + btScalar lz=btScalar(2.)*(halfExtents.z()); + + inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + ly*ly)); + +} + diff --git a/src/BulletCollision/CollisionShapes/btBox2dShape.h b/src/BulletCollision/CollisionShapes/btBox2dShape.h new file mode 100644 index 0000000..f4a9ca0 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btBox2dShape.h @@ -0,0 +1,369 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_OBB_BOX_2D_SHAPE_H +#define BT_OBB_BOX_2D_SHAPE_H + +#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btMinMax.h" + +///The btBox2dShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space. +class btBox2dShape: public btPolyhedralConvexShape +{ + + //btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead + + btVector3 m_centroid; + btVector3 m_vertices[4]; + btVector3 m_normals[4]; + +public: + + btVector3 getHalfExtentsWithMargin() const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents += margin; + return halfExtents; + } + + const btVector3& getHalfExtentsWithoutMargin() const + { + return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included + } + + + virtual btVector3 localGetSupportingVertex(const btVector3& vec) const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents += margin; + + return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), + btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), + btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); + } + + SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const + { + const btVector3& halfExtents = getHalfExtentsWithoutMargin(); + + return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), + btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), + btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); + } + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const + { + const btVector3& halfExtents = getHalfExtentsWithoutMargin(); + + for (int i=0;iboxHalfExtents.getY()) + minDimension = boxHalfExtents.getY(); + setSafeMargin(minDimension); + + m_shapeType = BOX_2D_SHAPE_PROXYTYPE; + btVector3 margin(getMargin(),getMargin(),getMargin()); + m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin; + }; + + virtual void setMargin(btScalar collisionMargin) + { + //correct the m_implicitShapeDimensions for the margin + btVector3 oldMargin(getMargin(),getMargin(),getMargin()); + btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin; + + btConvexInternalShape::setMargin(collisionMargin); + btVector3 newMargin(getMargin(),getMargin(),getMargin()); + m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin; + + } + virtual void setLocalScaling(const btVector3& scaling) + { + btVector3 oldMargin(getMargin(),getMargin(),getMargin()); + btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin; + btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling; + + btConvexInternalShape::setLocalScaling(scaling); + + m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin; + + } + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + + + + + int getVertexCount() const + { + return 4; + } + + virtual int getNumVertices()const + { + return 4; + } + + const btVector3* getVertices() const + { + return &m_vertices[0]; + } + + const btVector3* getNormals() const + { + return &m_normals[0]; + } + + + + + + + + virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const + { + //this plane might not be aligned... + btVector4 plane ; + getPlaneEquation(plane,i); + planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ()); + planeSupport = localGetSupportingVertex(-planeNormal); + } + + + const btVector3& getCentroid() const + { + return m_centroid; + } + + virtual int getNumPlanes() const + { + return 6; + } + + + + virtual int getNumEdges() const + { + return 12; + } + + + virtual void getVertex(int i,btVector3& vtx) const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + + vtx = btVector3( + halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1), + halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1), + halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2)); + } + + + virtual void getPlaneEquation(btVector4& plane,int i) const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + + switch (i) + { + case 0: + plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x()); + break; + case 1: + plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x()); + break; + case 2: + plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y()); + break; + case 3: + plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y()); + break; + case 4: + plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z()); + break; + case 5: + plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z()); + break; + default: + btAssert(0); + } + } + + + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const + //virtual void getEdge(int i,Edge& edge) const + { + int edgeVert0 = 0; + int edgeVert1 = 0; + + switch (i) + { + case 0: + edgeVert0 = 0; + edgeVert1 = 1; + break; + case 1: + edgeVert0 = 0; + edgeVert1 = 2; + break; + case 2: + edgeVert0 = 1; + edgeVert1 = 3; + + break; + case 3: + edgeVert0 = 2; + edgeVert1 = 3; + break; + case 4: + edgeVert0 = 0; + edgeVert1 = 4; + break; + case 5: + edgeVert0 = 1; + edgeVert1 = 5; + + break; + case 6: + edgeVert0 = 2; + edgeVert1 = 6; + break; + case 7: + edgeVert0 = 3; + edgeVert1 = 7; + break; + case 8: + edgeVert0 = 4; + edgeVert1 = 5; + break; + case 9: + edgeVert0 = 4; + edgeVert1 = 6; + break; + case 10: + edgeVert0 = 5; + edgeVert1 = 7; + break; + case 11: + edgeVert0 = 6; + edgeVert1 = 7; + break; + default: + btAssert(0); + + } + + getVertex(edgeVert0,pa ); + getVertex(edgeVert1,pb ); + } + + + + + + virtual bool isInside(const btVector3& pt,btScalar tolerance) const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + + //btScalar minDist = 2*tolerance; + + bool result = (pt.x() <= (halfExtents.x()+tolerance)) && + (pt.x() >= (-halfExtents.x()-tolerance)) && + (pt.y() <= (halfExtents.y()+tolerance)) && + (pt.y() >= (-halfExtents.y()-tolerance)) && + (pt.z() <= (halfExtents.z()+tolerance)) && + (pt.z() >= (-halfExtents.z()-tolerance)); + + return result; + } + + + //debugging + virtual const char* getName()const + { + return "Box2d"; + } + + virtual int getNumPreferredPenetrationDirections() const + { + return 6; + } + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const + { + switch (index) + { + case 0: + penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.)); + break; + case 1: + penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.)); + break; + case 2: + penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.)); + break; + case 3: + penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.)); + break; + case 4: + penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.)); + break; + case 5: + penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.)); + break; + default: + btAssert(0); + } + } + +}; + +#endif //BT_OBB_BOX_2D_SHAPE_H + + diff --git a/src/BulletCollision/CollisionShapes/btBoxShape.cpp b/src/BulletCollision/CollisionShapes/btBoxShape.cpp new file mode 100644 index 0000000..3859138 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btBoxShape.cpp @@ -0,0 +1,51 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btBoxShape.h" + +btBoxShape::btBoxShape( const btVector3& boxHalfExtents) +: btPolyhedralConvexShape() +{ + m_shapeType = BOX_SHAPE_PROXYTYPE; + + setSafeMargin(boxHalfExtents); + + btVector3 margin(getMargin(),getMargin(),getMargin()); + m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin; +}; + + + + +void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax); +} + + +void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + //btScalar margin = btScalar(0.); + btVector3 halfExtents = getHalfExtentsWithMargin(); + + btScalar lx=btScalar(2.)*(halfExtents.x()); + btScalar ly=btScalar(2.)*(halfExtents.y()); + btScalar lz=btScalar(2.)*(halfExtents.z()); + + inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + ly*ly)); + +} + diff --git a/src/BulletCollision/CollisionShapes/btBoxShape.h b/src/BulletCollision/CollisionShapes/btBoxShape.h new file mode 100644 index 0000000..0c5857d --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btBoxShape.h @@ -0,0 +1,312 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_OBB_BOX_MINKOWSKI_H +#define BT_OBB_BOX_MINKOWSKI_H + +#include "btPolyhedralConvexShape.h" +#include "btCollisionMargin.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btMinMax.h" + +///The btBoxShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space. +class btBoxShape: public btPolyhedralConvexShape +{ + + //btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead + + +public: + + btVector3 getHalfExtentsWithMargin() const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents += margin; + return halfExtents; + } + + const btVector3& getHalfExtentsWithoutMargin() const + { + return m_implicitShapeDimensions;//scaling is included, margin is not + } + + + virtual btVector3 localGetSupportingVertex(const btVector3& vec) const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents += margin; + + return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), + btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), + btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); + } + + SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const + { + const btVector3& halfExtents = getHalfExtentsWithoutMargin(); + + return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), + btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), + btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); + } + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const + { + const btVector3& halfExtents = getHalfExtentsWithoutMargin(); + + for (int i=0;i>1)) - halfExtents.y() * ((i&2)>>1), + halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2)); + } + + + virtual void getPlaneEquation(btVector4& plane,int i) const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + + switch (i) + { + case 0: + plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x()); + break; + case 1: + plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x()); + break; + case 2: + plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y()); + break; + case 3: + plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y()); + break; + case 4: + plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z()); + break; + case 5: + plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z()); + break; + default: + btAssert(0); + } + } + + + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const + //virtual void getEdge(int i,Edge& edge) const + { + int edgeVert0 = 0; + int edgeVert1 = 0; + + switch (i) + { + case 0: + edgeVert0 = 0; + edgeVert1 = 1; + break; + case 1: + edgeVert0 = 0; + edgeVert1 = 2; + break; + case 2: + edgeVert0 = 1; + edgeVert1 = 3; + + break; + case 3: + edgeVert0 = 2; + edgeVert1 = 3; + break; + case 4: + edgeVert0 = 0; + edgeVert1 = 4; + break; + case 5: + edgeVert0 = 1; + edgeVert1 = 5; + + break; + case 6: + edgeVert0 = 2; + edgeVert1 = 6; + break; + case 7: + edgeVert0 = 3; + edgeVert1 = 7; + break; + case 8: + edgeVert0 = 4; + edgeVert1 = 5; + break; + case 9: + edgeVert0 = 4; + edgeVert1 = 6; + break; + case 10: + edgeVert0 = 5; + edgeVert1 = 7; + break; + case 11: + edgeVert0 = 6; + edgeVert1 = 7; + break; + default: + btAssert(0); + + } + + getVertex(edgeVert0,pa ); + getVertex(edgeVert1,pb ); + } + + + + + + virtual bool isInside(const btVector3& pt,btScalar tolerance) const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + + //btScalar minDist = 2*tolerance; + + bool result = (pt.x() <= (halfExtents.x()+tolerance)) && + (pt.x() >= (-halfExtents.x()-tolerance)) && + (pt.y() <= (halfExtents.y()+tolerance)) && + (pt.y() >= (-halfExtents.y()-tolerance)) && + (pt.z() <= (halfExtents.z()+tolerance)) && + (pt.z() >= (-halfExtents.z()-tolerance)); + + return result; + } + + + //debugging + virtual const char* getName()const + { + return "Box"; + } + + virtual int getNumPreferredPenetrationDirections() const + { + return 6; + } + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const + { + switch (index) + { + case 0: + penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.)); + break; + case 1: + penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.)); + break; + case 2: + penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.)); + break; + case 3: + penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.)); + break; + case 4: + penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.)); + break; + case 5: + penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.)); + break; + default: + btAssert(0); + } + } + +}; + + +#endif //BT_OBB_BOX_MINKOWSKI_H + + diff --git a/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp b/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp new file mode 100644 index 0000000..ace4cfa --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp @@ -0,0 +1,466 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +//#define DISABLE_BVH + +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btOptimizedBvh.h" +#include "LinearMath/btSerializer.h" + +///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization. +///Uses an interface to access the triangles to allow for sharing graphics/physics triangles. +btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh) +:btTriangleMeshShape(meshInterface), +m_bvh(0), +m_triangleInfoMap(0), +m_useQuantizedAabbCompression(useQuantizedAabbCompression), +m_ownsBvh(false) +{ + m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE; + //construct bvh from meshInterface +#ifndef DISABLE_BVH + + if (buildBvh) + { + buildOptimizedBvh(); + } + +#endif //DISABLE_BVH + +} + +btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh) +:btTriangleMeshShape(meshInterface), +m_bvh(0), +m_triangleInfoMap(0), +m_useQuantizedAabbCompression(useQuantizedAabbCompression), +m_ownsBvh(false) +{ + m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE; + //construct bvh from meshInterface +#ifndef DISABLE_BVH + + if (buildBvh) + { + void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); + m_bvh = new (mem) btOptimizedBvh(); + + m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); + m_ownsBvh = true; + } + +#endif //DISABLE_BVH + +} + +void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax) +{ + m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax ); + + m_localAabbMin.setMin(aabbMin); + m_localAabbMax.setMax(aabbMax); +} + + +void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax) +{ + m_bvh->refit( m_meshInterface, aabbMin,aabbMax ); + + recalcLocalAabb(); +} + +btBvhTriangleMeshShape::~btBvhTriangleMeshShape() +{ + if (m_ownsBvh) + { + m_bvh->~btOptimizedBvh(); + btAlignedFree(m_bvh); + } +} + +void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget) +{ + struct MyNodeOverlapCallback : public btNodeOverlapCallback + { + btStridingMeshInterface* m_meshInterface; + btTriangleCallback* m_callback; + + MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) + :m_meshInterface(meshInterface), + m_callback(callback) + { + } + + virtual void processNode(int nodeSubPart, int nodeTriangleIndex) + { + btVector3 m_triangle[3]; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + nodeSubPart); + + unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); + btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); + + const btVector3& meshScaling = m_meshInterface->getScaling(); + for (int j=2;j>=0;j--) + { + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + + if (type == PHY_FLOAT) + { + float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + } + else + { + double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ()); + } + } + + /* Perform ray vs. triangle collision here */ + m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); + m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); + } + }; + + MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); + + m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget); +} + +void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax) +{ + struct MyNodeOverlapCallback : public btNodeOverlapCallback + { + btStridingMeshInterface* m_meshInterface; + btTriangleCallback* m_callback; + + MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) + :m_meshInterface(meshInterface), + m_callback(callback) + { + } + + virtual void processNode(int nodeSubPart, int nodeTriangleIndex) + { + btVector3 m_triangle[3]; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + nodeSubPart); + + unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); + btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); + + const btVector3& meshScaling = m_meshInterface->getScaling(); + for (int j=2;j>=0;j--) + { + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + + if (type == PHY_FLOAT) + { + float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + } + else + { + double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ()); + } + } + + /* Perform ray vs. triangle collision here */ + m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); + m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); + } + }; + + MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); + + m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax); +} + +//perform bvh tree traversal and report overlapping triangles to 'callback' +void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + +#ifdef DISABLE_BVH + //brute force traverse all triangles + btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax); +#else + + //first get all the nodes + + + struct MyNodeOverlapCallback : public btNodeOverlapCallback + { + btStridingMeshInterface* m_meshInterface; + btTriangleCallback* m_callback; + btVector3 m_triangle[3]; + + + MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) + :m_meshInterface(meshInterface), + m_callback(callback) + { + } + + virtual void processNode(int nodeSubPart, int nodeTriangleIndex) + { + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + nodeSubPart); + + unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); + btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT||indicestype==PHY_UCHAR); + + const btVector3& meshScaling = m_meshInterface->getScaling(); + for (int j=2;j>=0;j--) + { + + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:indicestype==PHY_INTEGER?gfxbase[j]:((unsigned char*)gfxbase)[j]; + + +#ifdef DEBUG_TRIANGLE_MESH + printf("%d ,",graphicsindex); +#endif //DEBUG_TRIANGLE_MESH + if (type == PHY_FLOAT) + { + float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3( + graphicsbase[0]*meshScaling.getX(), + graphicsbase[1]*meshScaling.getY(), + graphicsbase[2]*meshScaling.getZ()); + } + else + { + double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3( + btScalar(graphicsbase[0])*meshScaling.getX(), + btScalar(graphicsbase[1])*meshScaling.getY(), + btScalar(graphicsbase[2])*meshScaling.getZ()); + } +#ifdef DEBUG_TRIANGLE_MESH + printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z()); +#endif //DEBUG_TRIANGLE_MESH + } + + m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); + m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); + } + + }; + + MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); + + m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); + + +#endif//DISABLE_BVH + + +} + +void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) +{ + if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) + { + btTriangleMeshShape::setLocalScaling(scaling); + buildOptimizedBvh(); + } +} + +void btBvhTriangleMeshShape::buildOptimizedBvh() +{ + if (m_ownsBvh) + { + m_bvh->~btOptimizedBvh(); + btAlignedFree(m_bvh); + } + ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work + void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); + m_bvh = new(mem) btOptimizedBvh(); + //rebuild the bvh... + m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax); + m_ownsBvh = true; +} + +void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling) +{ + btAssert(!m_bvh); + btAssert(!m_ownsBvh); + + m_bvh = bvh; + m_ownsBvh = false; + // update the scaling without rebuilding the bvh + if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) + { + btTriangleMeshShape::setLocalScaling(scaling); + } +} + + + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*) dataBuffer; + + btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer); + + m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer); + + trimeshData->m_collisionMargin = float(m_collisionMargin); + + + + if (m_bvh && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_BVH)) + { + void* chunk = serializer->findPointer(m_bvh); + if (chunk) + { +#ifdef BT_USE_DOUBLE_PRECISION + trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk; + trimeshData->m_quantizedFloatBvh = 0; +#else + trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)chunk; + trimeshData->m_quantizedDoubleBvh= 0; +#endif //BT_USE_DOUBLE_PRECISION + } else + { + +#ifdef BT_USE_DOUBLE_PRECISION + trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh); + trimeshData->m_quantizedFloatBvh = 0; +#else + trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh); + trimeshData->m_quantizedDoubleBvh= 0; +#endif //BT_USE_DOUBLE_PRECISION + + int sz = m_bvh->calculateSerializeBufferSizeNew(); + btChunk* chunk = serializer->allocate(sz,1); + const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,m_bvh); + } + } else + { + trimeshData->m_quantizedFloatBvh = 0; + trimeshData->m_quantizedDoubleBvh = 0; + } + + + + if (m_triangleInfoMap && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_TRIANGLEINFOMAP)) + { + void* chunk = serializer->findPointer(m_triangleInfoMap); + if (chunk) + { + trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk; + } else + { + trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)serializer->getUniquePointer(m_triangleInfoMap); + int sz = m_triangleInfoMap->calculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(sz,1); + const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,m_triangleInfoMap); + } + } else + { + trimeshData->m_triangleInfoMap = 0; + } + + return "btTriangleMeshShapeData"; +} + +void btBvhTriangleMeshShape::serializeSingleBvh(btSerializer* serializer) const +{ + if (m_bvh) + { + int len = m_bvh->calculateSerializeBufferSizeNew(); //make sure not to use calculateSerializeBufferSize because it is used for in-place + btChunk* chunk = serializer->allocate(len,1); + const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,(void*)m_bvh); + } +} + +void btBvhTriangleMeshShape::serializeSingleTriangleInfoMap(btSerializer* serializer) const +{ + if (m_triangleInfoMap) + { + int len = m_triangleInfoMap->calculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(len,1); + const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,(void*)m_triangleInfoMap); + } +} + + + + diff --git a/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h new file mode 100644 index 0000000..d1c2162 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h @@ -0,0 +1,139 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_BVH_TRIANGLE_MESH_SHAPE_H +#define BT_BVH_TRIANGLE_MESH_SHAPE_H + +#include "btTriangleMeshShape.h" +#include "btOptimizedBvh.h" +#include "LinearMath/btAlignedAllocator.h" +#include "btTriangleInfoMap.h" + +///The btBvhTriangleMeshShape is a static-triangle mesh shape with several optimizations, such as bounding volume hierarchy and cache friendly traversal for PlayStation 3 Cell SPU. It is recommended to enable useQuantizedAabbCompression for better memory usage. +///It takes a triangle mesh as input, for example a btTriangleMesh or btTriangleIndexVertexArray. The btBvhTriangleMeshShape class allows for triangle mesh deformations by a refit or partialRefit method. +///Instead of building the bounding volume hierarchy acceleration structure, it is also possible to serialize (save) and deserialize (load) the structure from disk. +///See Demos\ConcaveDemo\ConcavePhysicsDemo.cpp for an example. +ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape +{ + + btOptimizedBvh* m_bvh; + btTriangleInfoMap* m_triangleInfoMap; + + bool m_useQuantizedAabbCompression; + bool m_ownsBvh; + bool m_pad[11];////need padding due to alignment + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + + btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true); + + ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb + btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true); + + virtual ~btBvhTriangleMeshShape(); + + bool getOwnsBvh () const + { + return m_ownsBvh; + } + + + + void performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget); + void performConvexcast (btTriangleCallback* callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax); + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + void refitTree(const btVector3& aabbMin,const btVector3& aabbMax); + + ///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks + void partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax); + + //debugging + virtual const char* getName()const {return "BVHTRIANGLEMESH";} + + + virtual void setLocalScaling(const btVector3& scaling); + + btOptimizedBvh* getOptimizedBvh() + { + return m_bvh; + } + + void setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& localScaling=btVector3(1,1,1)); + + void buildOptimizedBvh(); + + bool usesQuantizedAabbCompression() const + { + return m_useQuantizedAabbCompression; + } + + void setTriangleInfoMap(btTriangleInfoMap* triangleInfoMap) + { + m_triangleInfoMap = triangleInfoMap; + } + + const btTriangleInfoMap* getTriangleInfoMap() const + { + return m_triangleInfoMap; + } + + btTriangleInfoMap* getTriangleInfoMap() + { + return m_triangleInfoMap; + } + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + virtual void serializeSingleBvh(btSerializer* serializer) const; + + virtual void serializeSingleTriangleInfoMap(btSerializer* serializer) const; + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btTriangleMeshShapeData +{ + btCollisionShapeData m_collisionShapeData; + + btStridingMeshInterfaceData m_meshInterface; + + btQuantizedBvhFloatData *m_quantizedFloatBvh; + btQuantizedBvhDoubleData *m_quantizedDoubleBvh; + + btTriangleInfoMapData *m_triangleInfoMap; + + float m_collisionMargin; + + char m_pad3[4]; + +}; + + +SIMD_FORCE_INLINE int btBvhTriangleMeshShape::calculateSerializeBufferSize() const +{ + return sizeof(btTriangleMeshShapeData); +} + + + +#endif //BT_BVH_TRIANGLE_MESH_SHAPE_H diff --git a/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp new file mode 100644 index 0000000..864df26 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp @@ -0,0 +1,171 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btCapsuleShape.h" + +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" +#include "LinearMath/btQuaternion.h" + +btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInternalShape () +{ + m_shapeType = CAPSULE_SHAPE_PROXYTYPE; + m_upAxis = 1; + m_implicitShapeDimensions.setValue(radius,0.5f*height,radius); +} + + + btVector3 btCapsuleShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const +{ + + btVector3 supVec(0,0,0); + + btScalar maxDot(btScalar(-BT_LARGE_FLOAT)); + + btVector3 vec = vec0; + btScalar lenSqr = vec.length2(); + if (lenSqr < btScalar(0.0001)) + { + vec.setValue(1,0,0); + } else + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + vec *= rlen; + } + + btVector3 vtx; + btScalar newDot; + + btScalar radius = getRadius(); + + + { + btVector3 pos(0,0,0); + pos[getUpAxis()] = getHalfHeight(); + + vtx = pos +vec*(radius) - vec * getMargin(); + newDot = vec.dot(vtx); + if (newDot > maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + { + btVector3 pos(0,0,0); + pos[getUpAxis()] = -getHalfHeight(); + + vtx = pos +vec*(radius) - vec * getMargin(); + newDot = vec.dot(vtx); + if (newDot > maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + + return supVec; + +} + + void btCapsuleShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + + + btScalar radius = getRadius(); + + for (int j=0;j maxDot) + { + maxDot = newDot; + supportVerticesOut[j] = vtx; + } + } + { + btVector3 pos(0,0,0); + pos[getUpAxis()] = -getHalfHeight(); + vtx = pos +vec*(radius) - vec * getMargin(); + newDot = vec.dot(vtx); + if (newDot > maxDot) + { + maxDot = newDot; + supportVerticesOut[j] = vtx; + } + } + + } +} + + +void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + //as an approximation, take the inertia of the box that bounds the spheres + + btTransform ident; + ident.setIdentity(); + + + btScalar radius = getRadius(); + + btVector3 halfExtents(radius,radius,radius); + halfExtents[getUpAxis()]+=getHalfHeight(); + + btScalar margin = CONVEX_DISTANCE_MARGIN; + + btScalar lx=btScalar(2.)*(halfExtents[0]+margin); + btScalar ly=btScalar(2.)*(halfExtents[1]+margin); + btScalar lz=btScalar(2.)*(halfExtents[2]+margin); + const btScalar x2 = lx*lx; + const btScalar y2 = ly*ly; + const btScalar z2 = lz*lz; + const btScalar scaledmass = mass * btScalar(.08333333); + + inertia[0] = scaledmass * (y2+z2); + inertia[1] = scaledmass * (x2+z2); + inertia[2] = scaledmass * (x2+y2); + +} + +btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height) +{ + m_upAxis = 0; + m_implicitShapeDimensions.setValue(0.5f*height, radius,radius); +} + + + + + + +btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height) +{ + m_upAxis = 2; + m_implicitShapeDimensions.setValue(radius,radius,0.5f*height); +} + + + + diff --git a/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/src/BulletCollision/CollisionShapes/btCapsuleShape.h new file mode 100644 index 0000000..ab763ab --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btCapsuleShape.h @@ -0,0 +1,173 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CAPSULE_SHAPE_H +#define BT_CAPSULE_SHAPE_H + +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types + + +///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis. +///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. +///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres. +class btCapsuleShape : public btConvexInternalShape +{ +protected: + int m_upAxis; + +protected: + ///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses. + btCapsuleShape() : btConvexInternalShape() {m_shapeType = CAPSULE_SHAPE_PROXYTYPE;}; + +public: + btCapsuleShape(btScalar radius,btScalar height); + + ///CollisionShape Interface + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + /// btConvexShape Interface + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + virtual void setMargin(btScalar collisionMargin) + { + //correct the m_implicitShapeDimensions for the margin + btVector3 oldMargin(getMargin(),getMargin(),getMargin()); + btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin; + + btConvexInternalShape::setMargin(collisionMargin); + btVector3 newMargin(getMargin(),getMargin(),getMargin()); + m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin; + + } + + virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const + { + btVector3 halfExtents(getRadius(),getRadius(),getRadius()); + halfExtents[m_upAxis] = getRadius() + getHalfHeight(); + halfExtents += btVector3(getMargin(),getMargin(),getMargin()); + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents)); + + aabbMin = center - extent; + aabbMax = center + extent; + } + + virtual const char* getName()const + { + return "CapsuleShape"; + } + + int getUpAxis() const + { + return m_upAxis; + } + + btScalar getRadius() const + { + int radiusAxis = (m_upAxis+2)%3; + return m_implicitShapeDimensions[radiusAxis]; + } + + btScalar getHalfHeight() const + { + return m_implicitShapeDimensions[m_upAxis]; + } + + virtual void setLocalScaling(const btVector3& scaling) + { + btVector3 oldMargin(getMargin(),getMargin(),getMargin()); + btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin; + btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling; + + btConvexInternalShape::setLocalScaling(scaling); + + m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin; + + } + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + +///btCapsuleShapeX represents a capsule around the Z axis +///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. +class btCapsuleShapeX : public btCapsuleShape +{ +public: + + btCapsuleShapeX(btScalar radius,btScalar height); + + //debugging + virtual const char* getName()const + { + return "CapsuleX"; + } + + + +}; + +///btCapsuleShapeZ represents a capsule around the Z axis +///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. +class btCapsuleShapeZ : public btCapsuleShape +{ +public: + btCapsuleShapeZ(btScalar radius,btScalar height); + + //debugging + virtual const char* getName()const + { + return "CapsuleZ"; + } + + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btCapsuleShapeData +{ + btConvexInternalShapeData m_convexInternalShapeData; + + int m_upAxis; + + char m_padding[4]; +}; + +SIMD_FORCE_INLINE int btCapsuleShape::calculateSerializeBufferSize() const +{ + return sizeof(btCapsuleShapeData); +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btCapsuleShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btCapsuleShapeData* shapeData = (btCapsuleShapeData*) dataBuffer; + + btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData,serializer); + + shapeData->m_upAxis = m_upAxis; + + return "btCapsuleShapeData"; +} + +#endif //BT_CAPSULE_SHAPE_H diff --git a/src/BulletCollision/CollisionShapes/btCollisionMargin.h b/src/BulletCollision/CollisionShapes/btCollisionMargin.h new file mode 100644 index 0000000..474bf1f --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btCollisionMargin.h @@ -0,0 +1,27 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COLLISION_MARGIN_H +#define BT_COLLISION_MARGIN_H + +///The CONVEX_DISTANCE_MARGIN is a default collision margin for convex collision shapes derived from btConvexInternalShape. +///This collision margin is used by Gjk and some other algorithms +///Note that when creating small objects, you need to make sure to set a smaller collision margin, using the 'setMargin' API +#define CONVEX_DISTANCE_MARGIN btScalar(0.04)// btScalar(0.1)//;//btScalar(0.01) + + + +#endif //BT_COLLISION_MARGIN_H + diff --git a/src/BulletCollision/CollisionShapes/btCollisionShape.cpp b/src/BulletCollision/CollisionShapes/btCollisionShape.cpp new file mode 100644 index 0000000..39ee21c --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btCollisionShape.cpp @@ -0,0 +1,119 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "LinearMath/btSerializer.h" + +/* + Make sure this dummy function never changes so that it + can be used by probes that are checking whether the + library is actually installed. +*/ +extern "C" +{ +void btBulletCollisionProbe (); + +void btBulletCollisionProbe () {} +} + + + +void btCollisionShape::getBoundingSphere(btVector3& center,btScalar& radius) const +{ + btTransform tr; + tr.setIdentity(); + btVector3 aabbMin,aabbMax; + + getAabb(tr,aabbMin,aabbMax); + + radius = (aabbMax-aabbMin).length()*btScalar(0.5); + center = (aabbMin+aabbMax)*btScalar(0.5); +} + + +btScalar btCollisionShape::getContactBreakingThreshold(btScalar defaultContactThreshold) const +{ + return getAngularMotionDisc() * defaultContactThreshold; +} + +btScalar btCollisionShape::getAngularMotionDisc() const +{ + ///@todo cache this value, to improve performance + btVector3 center; + btScalar disc; + getBoundingSphere(center,disc); + disc += (center).length(); + return disc; +} + +void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const +{ + //start with static aabb + getAabb(curTrans,temporalAabbMin,temporalAabbMax); + + btScalar temporalAabbMaxx = temporalAabbMax.getX(); + btScalar temporalAabbMaxy = temporalAabbMax.getY(); + btScalar temporalAabbMaxz = temporalAabbMax.getZ(); + btScalar temporalAabbMinx = temporalAabbMin.getX(); + btScalar temporalAabbMiny = temporalAabbMin.getY(); + btScalar temporalAabbMinz = temporalAabbMin.getZ(); + + // add linear motion + btVector3 linMotion = linvel*timeStep; + ///@todo: simd would have a vector max/min operation, instead of per-element access + if (linMotion.x() > btScalar(0.)) + temporalAabbMaxx += linMotion.x(); + else + temporalAabbMinx += linMotion.x(); + if (linMotion.y() > btScalar(0.)) + temporalAabbMaxy += linMotion.y(); + else + temporalAabbMiny += linMotion.y(); + if (linMotion.z() > btScalar(0.)) + temporalAabbMaxz += linMotion.z(); + else + temporalAabbMinz += linMotion.z(); + + //add conservative angular motion + btScalar angularMotion = angvel.length() * getAngularMotionDisc() * timeStep; + btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion); + temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz); + temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz); + + temporalAabbMin -= angularMotion3d; + temporalAabbMax += angularMotion3d; +} + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btCollisionShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btCollisionShapeData* shapeData = (btCollisionShapeData*) dataBuffer; + char* name = (char*) serializer->findNameForPointer(this); + shapeData->m_name = (char*)serializer->getUniquePointer(name); + if (shapeData->m_name) + { + serializer->serializeName(name); + } + shapeData->m_shapeType = m_shapeType; + //shapeData->m_padding//?? + return "btCollisionShapeData"; +} + +void btCollisionShape::serializeSingleShape(btSerializer* serializer) const +{ + int len = calculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(len,1); + const char* structType = serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,(void*)this); +} \ No newline at end of file diff --git a/src/BulletCollision/CollisionShapes/btCollisionShape.h b/src/BulletCollision/CollisionShapes/btCollisionShape.h new file mode 100644 index 0000000..865c106 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btCollisionShape.h @@ -0,0 +1,150 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COLLISION_SHAPE_H +#define BT_COLLISION_SHAPE_H + +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types +class btSerializer; + + +///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects. +class btCollisionShape +{ +protected: + int m_shapeType; + void* m_userPointer; + +public: + + btCollisionShape() : m_shapeType (INVALID_SHAPE_PROXYTYPE), m_userPointer(0) + { + } + + virtual ~btCollisionShape() + { + } + + ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t. + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; + + virtual void getBoundingSphere(btVector3& center,btScalar& radius) const; + + ///getAngularMotionDisc returns the maximus radius needed for Conservative Advancement to handle time-of-impact with rotations. + virtual btScalar getAngularMotionDisc() const; + + virtual btScalar getContactBreakingThreshold(btScalar defaultContactThresholdFactor) const; + + + ///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep) + ///result is conservative + void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const; + + + + SIMD_FORCE_INLINE bool isPolyhedral() const + { + return btBroadphaseProxy::isPolyhedral(getShapeType()); + } + + SIMD_FORCE_INLINE bool isConvex2d() const + { + return btBroadphaseProxy::isConvex2d(getShapeType()); + } + + SIMD_FORCE_INLINE bool isConvex() const + { + return btBroadphaseProxy::isConvex(getShapeType()); + } + SIMD_FORCE_INLINE bool isNonMoving() const + { + return btBroadphaseProxy::isNonMoving(getShapeType()); + } + SIMD_FORCE_INLINE bool isConcave() const + { + return btBroadphaseProxy::isConcave(getShapeType()); + } + SIMD_FORCE_INLINE bool isCompound() const + { + return btBroadphaseProxy::isCompound(getShapeType()); + } + + SIMD_FORCE_INLINE bool isSoftBody() const + { + return btBroadphaseProxy::isSoftBody(getShapeType()); + } + + ///isInfinite is used to catch simulation error (aabb check) + SIMD_FORCE_INLINE bool isInfinite() const + { + return btBroadphaseProxy::isInfinite(getShapeType()); + } + +#ifndef __SPU__ + virtual void setLocalScaling(const btVector3& scaling) =0; + virtual const btVector3& getLocalScaling() const =0; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const = 0; + + +//debugging support + virtual const char* getName()const =0 ; +#endif //__SPU__ + + + int getShapeType() const { return m_shapeType; } + virtual void setMargin(btScalar margin) = 0; + virtual btScalar getMargin() const = 0; + + + ///optional user data pointer + void setUserPointer(void* userPtr) + { + m_userPointer = userPtr; + } + + void* getUserPointer() const + { + return m_userPointer; + } + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + virtual void serializeSingleShape(btSerializer* serializer) const; + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btCollisionShapeData +{ + char *m_name; + int m_shapeType; + char m_padding[4]; +}; + +SIMD_FORCE_INLINE int btCollisionShape::calculateSerializeBufferSize() const +{ + return sizeof(btCollisionShapeData); +} + + + +#endif //BT_COLLISION_SHAPE_H + diff --git a/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/src/BulletCollision/CollisionShapes/btCompoundShape.cpp new file mode 100644 index 0000000..4eb860c --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btCompoundShape.cpp @@ -0,0 +1,356 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btCompoundShape.h" +#include "btCollisionShape.h" +#include "BulletCollision/BroadphaseCollision/btDbvt.h" +#include "LinearMath/btSerializer.h" + +btCompoundShape::btCompoundShape(bool enableDynamicAabbTree) +: m_localAabbMin(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)), +m_localAabbMax(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)), +m_dynamicAabbTree(0), +m_updateRevision(1), +m_collisionMargin(btScalar(0.)), +m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)) +{ + m_shapeType = COMPOUND_SHAPE_PROXYTYPE; + + if (enableDynamicAabbTree) + { + void* mem = btAlignedAlloc(sizeof(btDbvt),16); + m_dynamicAabbTree = new(mem) btDbvt(); + btAssert(mem==m_dynamicAabbTree); + } +} + + +btCompoundShape::~btCompoundShape() +{ + if (m_dynamicAabbTree) + { + m_dynamicAabbTree->~btDbvt(); + btAlignedFree(m_dynamicAabbTree); + } +} + +void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape) +{ + m_updateRevision++; + //m_childTransforms.push_back(localTransform); + //m_childShapes.push_back(shape); + btCompoundShapeChild child; + child.m_node = 0; + child.m_transform = localTransform; + child.m_childShape = shape; + child.m_childShapeType = shape->getShapeType(); + child.m_childMargin = shape->getMargin(); + + + //extend the local aabbMin/aabbMax + btVector3 localAabbMin,localAabbMax; + shape->getAabb(localTransform,localAabbMin,localAabbMax); + for (int i=0;i<3;i++) + { + if (m_localAabbMin[i] > localAabbMin[i]) + { + m_localAabbMin[i] = localAabbMin[i]; + } + if (m_localAabbMax[i] < localAabbMax[i]) + { + m_localAabbMax[i] = localAabbMax[i]; + } + + } + if (m_dynamicAabbTree) + { + const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); + int index = m_children.size(); + child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index); + } + + m_children.push_back(child); + +} + +void btCompoundShape::updateChildTransform(int childIndex, const btTransform& newChildTransform,bool shouldRecalculateLocalAabb) +{ + m_children[childIndex].m_transform = newChildTransform; + + if (m_dynamicAabbTree) + { + ///update the dynamic aabb tree + btVector3 localAabbMin,localAabbMax; + m_children[childIndex].m_childShape->getAabb(newChildTransform,localAabbMin,localAabbMax); + ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); + //int index = m_children.size()-1; + m_dynamicAabbTree->update(m_children[childIndex].m_node,bounds); + } + + if (shouldRecalculateLocalAabb) + { + recalculateLocalAabb(); + } +} + +void btCompoundShape::removeChildShapeByIndex(int childShapeIndex) +{ + m_updateRevision++; + btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size()); + if (m_dynamicAabbTree) + { + m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node); + } + m_children.swap(childShapeIndex,m_children.size()-1); + if (m_dynamicAabbTree) + m_children[childShapeIndex].m_node->dataAsInt = childShapeIndex; + m_children.pop_back(); + +} + + + +void btCompoundShape::removeChildShape(btCollisionShape* shape) +{ + m_updateRevision++; + // Find the children containing the shape specified, and remove those children. + //note: there might be multiple children using the same shape! + for(int i = m_children.size()-1; i >= 0 ; i--) + { + if(m_children[i].m_childShape == shape) + { + removeChildShapeByIndex(i); + } + } + + + + recalculateLocalAabb(); +} + +void btCompoundShape::recalculateLocalAabb() +{ + // Recalculate the local aabb + // Brute force, it iterates over all the shapes left. + + m_localAabbMin = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + m_localAabbMax = btVector3(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + + //extend the local aabbMin/aabbMax + for (int j = 0; j < m_children.size(); j++) + { + btVector3 localAabbMin,localAabbMax; + m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax); + for (int i=0;i<3;i++) + { + if (m_localAabbMin[i] > localAabbMin[i]) + m_localAabbMin[i] = localAabbMin[i]; + if (m_localAabbMax[i] < localAabbMax[i]) + m_localAabbMax[i] = localAabbMax[i]; + } + } +} + +///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version +void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); + btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); + + //avoid an illegal AABB when there are no children + if (!m_children.size()) + { + localHalfExtents.setValue(0,0,0); + localCenter.setValue(0,0,0); + } + localHalfExtents += btVector3(getMargin(),getMargin(),getMargin()); + + + btMatrix3x3 abs_b = trans.getBasis().absolute(); + + btVector3 center = trans(localCenter); + + btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + aabbMin = center-extent; + aabbMax = center+extent; + +} + +void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + //approximation: take the inertia from the aabb for now + btTransform ident; + ident.setIdentity(); + btVector3 aabbMin,aabbMax; + getAabb(ident,aabbMin,aabbMax); + + btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5); + + btScalar lx=btScalar(2.)*(halfExtents.x()); + btScalar ly=btScalar(2.)*(halfExtents.y()); + btScalar lz=btScalar(2.)*(halfExtents.z()); + + inertia[0] = mass/(btScalar(12.0)) * (ly*ly + lz*lz); + inertia[1] = mass/(btScalar(12.0)) * (lx*lx + lz*lz); + inertia[2] = mass/(btScalar(12.0)) * (lx*lx + ly*ly); + +} + + + + +void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const +{ + int n = m_children.size(); + + btScalar totalMass = 0; + btVector3 center(0, 0, 0); + int k; + + for (k = 0; k < n; k++) + { + btAssert(masses[k]>0); + center += m_children[k].m_transform.getOrigin() * masses[k]; + totalMass += masses[k]; + } + + btAssert(totalMass>0); + + center /= totalMass; + principal.setOrigin(center); + + btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0); + for ( k = 0; k < n; k++) + { + btVector3 i; + m_children[k].m_childShape->calculateLocalInertia(masses[k], i); + + const btTransform& t = m_children[k].m_transform; + btVector3 o = t.getOrigin() - center; + + //compute inertia tensor in coordinate system of compound shape + btMatrix3x3 j = t.getBasis().transpose(); + j[0] *= i[0]; + j[1] *= i[1]; + j[2] *= i[2]; + j = t.getBasis() * j; + + //add inertia tensor + tensor[0] += j[0]; + tensor[1] += j[1]; + tensor[2] += j[2]; + + //compute inertia tensor of pointmass at o + btScalar o2 = o.length2(); + j[0].setValue(o2, 0, 0); + j[1].setValue(0, o2, 0); + j[2].setValue(0, 0, o2); + j[0] += o * -o.x(); + j[1] += o * -o.y(); + j[2] += o * -o.z(); + + //add inertia tensor of pointmass + tensor[0] += masses[k] * j[0]; + tensor[1] += masses[k] * j[1]; + tensor[2] += masses[k] * j[2]; + } + + tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20); + inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]); +} + + + +void btCompoundShape::setLocalScaling(const btVector3& scaling) +{ + + for(int i = 0; i < m_children.size(); i++) + { + btTransform childTrans = getChildTransform(i); + btVector3 childScale = m_children[i].m_childShape->getLocalScaling(); +// childScale = childScale * (childTrans.getBasis() * scaling); + childScale = childScale * scaling / m_localScaling; + m_children[i].m_childShape->setLocalScaling(childScale); + childTrans.setOrigin((childTrans.getOrigin())*scaling); + updateChildTransform(i, childTrans,false); + } + + m_localScaling = scaling; + recalculateLocalAabb(); + +} + + +void btCompoundShape::createAabbTreeFromChildren() +{ + if ( !m_dynamicAabbTree ) + { + void* mem = btAlignedAlloc(sizeof(btDbvt),16); + m_dynamicAabbTree = new(mem) btDbvt(); + btAssert(mem==m_dynamicAabbTree); + + for ( int index = 0; index < m_children.size(); index++ ) + { + btCompoundShapeChild &child = m_children[index]; + + //extend the local aabbMin/aabbMax + btVector3 localAabbMin,localAabbMax; + child.m_childShape->getAabb(child.m_transform,localAabbMin,localAabbMax); + + const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); + child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index); + } + } +} + + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btCompoundShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + + btCompoundShapeData* shapeData = (btCompoundShapeData*) dataBuffer; + btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer); + + shapeData->m_collisionMargin = float(m_collisionMargin); + shapeData->m_numChildShapes = m_children.size(); + shapeData->m_childShapePtr = 0; + if (shapeData->m_numChildShapes) + { + btChunk* chunk = serializer->allocate(sizeof(btCompoundShapeChildData),shapeData->m_numChildShapes); + btCompoundShapeChildData* memPtr = (btCompoundShapeChildData*)chunk->m_oldPtr; + shapeData->m_childShapePtr = (btCompoundShapeChildData*)serializer->getUniquePointer(memPtr); + + for (int i=0;im_numChildShapes;i++,memPtr++) + { + memPtr->m_childMargin = float(m_children[i].m_childMargin); + memPtr->m_childShape = (btCollisionShapeData*)serializer->getUniquePointer(m_children[i].m_childShape); + //don't serialize shapes that already have been serialized + if (!serializer->findPointer(m_children[i].m_childShape)) + { + btChunk* chunk = serializer->allocate(m_children[i].m_childShape->calculateSerializeBufferSize(),1); + const char* structType = m_children[i].m_childShape->serialize(chunk->m_oldPtr,serializer); + serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,m_children[i].m_childShape); + } + + memPtr->m_childShapeType = m_children[i].m_childShapeType; + m_children[i].m_transform.serializeFloat(memPtr->m_transform); + } + serializer->finalizeChunk(chunk,"btCompoundShapeChildData",BT_ARRAY_CODE,chunk->m_oldPtr); + } + return "btCompoundShapeData"; +} + diff --git a/src/BulletCollision/CollisionShapes/btCompoundShape.h b/src/BulletCollision/CollisionShapes/btCompoundShape.h new file mode 100644 index 0000000..141034a --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btCompoundShape.h @@ -0,0 +1,212 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COMPOUND_SHAPE_H +#define BT_COMPOUND_SHAPE_H + +#include "btCollisionShape.h" + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" +#include "btCollisionMargin.h" +#include "LinearMath/btAlignedObjectArray.h" + +//class btOptimizedBvh; +struct btDbvt; + +ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btTransform m_transform; + btCollisionShape* m_childShape; + int m_childShapeType; + btScalar m_childMargin; + struct btDbvtNode* m_node; +}; + +SIMD_FORCE_INLINE bool operator==(const btCompoundShapeChild& c1, const btCompoundShapeChild& c2) +{ + return ( c1.m_transform == c2.m_transform && + c1.m_childShape == c2.m_childShape && + c1.m_childShapeType == c2.m_childShapeType && + c1.m_childMargin == c2.m_childMargin ); +} + +/// The btCompoundShape allows to store multiple other btCollisionShapes +/// This allows for moving concave collision objects. This is more general then the static concave btBvhTriangleMeshShape. +/// It has an (optional) dynamic aabb tree to accelerate early rejection tests. +/// @todo: This aabb tree can also be use to speed up ray tests on btCompoundShape, see http://code.google.com/p/bullet/issues/detail?id=25 +/// Currently, removal of child shapes is only supported when disabling the aabb tree (pass 'false' in the constructor of btCompoundShape) +ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape +{ + btAlignedObjectArray m_children; + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + + btDbvt* m_dynamicAabbTree; + + ///increment m_updateRevision when adding/removing/replacing child shapes, so that some caches can be updated + int m_updateRevision; + + btScalar m_collisionMargin; + +protected: + btVector3 m_localScaling; + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btCompoundShape(bool enableDynamicAabbTree = true); + + virtual ~btCompoundShape(); + + void addChildShape(const btTransform& localTransform,btCollisionShape* shape); + + /// Remove all children shapes that contain the specified shape + virtual void removeChildShape(btCollisionShape* shape); + + void removeChildShapeByIndex(int childShapeindex); + + + int getNumChildShapes() const + { + return int (m_children.size()); + } + + btCollisionShape* getChildShape(int index) + { + return m_children[index].m_childShape; + } + const btCollisionShape* getChildShape(int index) const + { + return m_children[index].m_childShape; + } + + btTransform& getChildTransform(int index) + { + return m_children[index].m_transform; + } + const btTransform& getChildTransform(int index) const + { + return m_children[index].m_transform; + } + + ///set a new transform for a child, and update internal data structures (local aabb and dynamic tree) + void updateChildTransform(int childIndex, const btTransform& newChildTransform, bool shouldRecalculateLocalAabb = true); + + + btCompoundShapeChild* getChildList() + { + return &m_children[0]; + } + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + /** Re-calculate the local Aabb. Is called at the end of removeChildShapes. + Use this yourself if you modify the children or their transforms. */ + virtual void recalculateLocalAabb(); + + virtual void setLocalScaling(const btVector3& scaling); + + virtual const btVector3& getLocalScaling() const + { + return m_localScaling; + } + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual void setMargin(btScalar margin) + { + m_collisionMargin = margin; + } + virtual btScalar getMargin() const + { + return m_collisionMargin; + } + virtual const char* getName()const + { + return "Compound"; + } + + const btDbvt* getDynamicAabbTree() const + { + return m_dynamicAabbTree; + } + + btDbvt* getDynamicAabbTree() + { + return m_dynamicAabbTree; + } + + void createAabbTreeFromChildren(); + + ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia + ///and the center of mass to the current coordinate system. "masses" points to an array of masses of the children. The resulting transform + ///"principal" has to be applied inversely to all children transforms in order for the local coordinate system of the compound + ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform + ///of the collision object by the principal transform. + void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const; + + int getUpdateRevision() const + { + return m_updateRevision; + } + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btCompoundShapeChildData +{ + btTransformFloatData m_transform; + btCollisionShapeData *m_childShape; + int m_childShapeType; + float m_childMargin; +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btCompoundShapeData +{ + btCollisionShapeData m_collisionShapeData; + + btCompoundShapeChildData *m_childShapePtr; + + int m_numChildShapes; + + float m_collisionMargin; + +}; + + +SIMD_FORCE_INLINE int btCompoundShape::calculateSerializeBufferSize() const +{ + return sizeof(btCompoundShapeData); +} + + + + + + + +#endif //BT_COMPOUND_SHAPE_H diff --git a/src/BulletCollision/CollisionShapes/btConcaveShape.cpp b/src/BulletCollision/CollisionShapes/btConcaveShape.cpp new file mode 100644 index 0000000..58ff84a --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btConcaveShape.cpp @@ -0,0 +1,27 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btConcaveShape.h" + +btConcaveShape::btConcaveShape() : m_collisionMargin(btScalar(0.)) +{ + +} + +btConcaveShape::~btConcaveShape() +{ + +} diff --git a/src/BulletCollision/CollisionShapes/btConcaveShape.h b/src/BulletCollision/CollisionShapes/btConcaveShape.h new file mode 100644 index 0000000..2a03241 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btConcaveShape.h @@ -0,0 +1,60 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONCAVE_SHAPE_H +#define BT_CONCAVE_SHAPE_H + +#include "btCollisionShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btTriangleCallback.h" + +/// PHY_ScalarType enumerates possible scalar types. +/// See the btStridingMeshInterface or btHeightfieldTerrainShape for its use +typedef enum PHY_ScalarType { + PHY_FLOAT, + PHY_DOUBLE, + PHY_INTEGER, + PHY_SHORT, + PHY_FIXEDPOINT88, + PHY_UCHAR +} PHY_ScalarType; + +///The btConcaveShape class provides an interface for non-moving (static) concave shapes. +///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape. +class btConcaveShape : public btCollisionShape +{ +protected: + btScalar m_collisionMargin; + +public: + btConcaveShape(); + + virtual ~btConcaveShape(); + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const = 0; + + virtual btScalar getMargin() const { + return m_collisionMargin; + } + virtual void setMargin(btScalar collisionMargin) + { + m_collisionMargin = collisionMargin; + } + + + +}; + +#endif //BT_CONCAVE_SHAPE_H diff --git a/src/BulletCollision/CollisionShapes/btConeShape.cpp b/src/BulletCollision/CollisionShapes/btConeShape.cpp new file mode 100644 index 0000000..5e83087 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btConeShape.cpp @@ -0,0 +1,143 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btConeShape.h" + + + +btConeShape::btConeShape (btScalar radius,btScalar height): btConvexInternalShape (), +m_radius (radius), +m_height(height) +{ + m_shapeType = CONE_SHAPE_PROXYTYPE; + setConeUpIndex(1); + btVector3 halfExtents; + m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height)); +} + +btConeShapeZ::btConeShapeZ (btScalar radius,btScalar height): +btConeShape(radius,height) +{ + setConeUpIndex(2); +} + +btConeShapeX::btConeShapeX (btScalar radius,btScalar height): +btConeShape(radius,height) +{ + setConeUpIndex(0); +} + +///choose upAxis index +void btConeShape::setConeUpIndex(int upIndex) +{ + switch (upIndex) + { + case 0: + m_coneIndices[0] = 1; + m_coneIndices[1] = 0; + m_coneIndices[2] = 2; + break; + case 1: + m_coneIndices[0] = 0; + m_coneIndices[1] = 1; + m_coneIndices[2] = 2; + break; + case 2: + m_coneIndices[0] = 0; + m_coneIndices[1] = 2; + m_coneIndices[2] = 1; + break; + default: + btAssert(0); + }; +} + +btVector3 btConeShape::coneLocalSupport(const btVector3& v) const +{ + + btScalar halfHeight = m_height * btScalar(0.5); + + if (v[m_coneIndices[1]] > v.length() * m_sinAngle) + { + btVector3 tmp; + + tmp[m_coneIndices[0]] = btScalar(0.); + tmp[m_coneIndices[1]] = halfHeight; + tmp[m_coneIndices[2]] = btScalar(0.); + return tmp; + } + else { + btScalar s = btSqrt(v[m_coneIndices[0]] * v[m_coneIndices[0]] + v[m_coneIndices[2]] * v[m_coneIndices[2]]); + if (s > SIMD_EPSILON) { + btScalar d = m_radius / s; + btVector3 tmp; + tmp[m_coneIndices[0]] = v[m_coneIndices[0]] * d; + tmp[m_coneIndices[1]] = -halfHeight; + tmp[m_coneIndices[2]] = v[m_coneIndices[2]] * d; + return tmp; + } + else { + btVector3 tmp; + tmp[m_coneIndices[0]] = btScalar(0.); + tmp[m_coneIndices[1]] = -halfHeight; + tmp[m_coneIndices[2]] = btScalar(0.); + return tmp; + } + } + +} + +btVector3 btConeShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const +{ + return coneLocalSupport(vec); +} + +void btConeShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + for (int i=0;ilocalGetSupportingVertexWithoutMargin(vec); +} + +void btConvex2dShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors); +} + + +btVector3 btConvex2dShape::localGetSupportingVertex(const btVector3& vec)const +{ + return m_childConvexShape->localGetSupportingVertex(vec); +} + + +void btConvex2dShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + ///this linear upscaling is not realistic, but we don't deal with large mass ratios... + m_childConvexShape->calculateLocalInertia(mass,inertia); +} + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version +void btConvex2dShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + m_childConvexShape->getAabb(t,aabbMin,aabbMax); +} + +void btConvex2dShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + m_childConvexShape->getAabbSlow(t,aabbMin,aabbMax); +} + +void btConvex2dShape::setLocalScaling(const btVector3& scaling) +{ + m_childConvexShape->setLocalScaling(scaling); +} + +const btVector3& btConvex2dShape::getLocalScaling() const +{ + return m_childConvexShape->getLocalScaling(); +} + +void btConvex2dShape::setMargin(btScalar margin) +{ + m_childConvexShape->setMargin(margin); +} +btScalar btConvex2dShape::getMargin() const +{ + return m_childConvexShape->getMargin(); +} + +int btConvex2dShape::getNumPreferredPenetrationDirections() const +{ + return m_childConvexShape->getNumPreferredPenetrationDirections(); +} + +void btConvex2dShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const +{ + m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector); +} diff --git a/src/BulletCollision/CollisionShapes/btConvex2dShape.h b/src/BulletCollision/CollisionShapes/btConvex2dShape.h new file mode 100644 index 0000000..caf5432 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btConvex2dShape.h @@ -0,0 +1,80 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_2D_SHAPE_H +#define BT_CONVEX_2D_SHAPE_H + +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types + +///The btConvex2dShape allows to use arbitrary convex shapes as 2d convex shapes, with the Z component assumed to be 0. +///For 2d boxes, the btBox2dShape is recommended. +class btConvex2dShape : public btConvexShape +{ + btConvexShape* m_childConvexShape; + + public: + + btConvex2dShape( btConvexShape* convexChildShape); + + virtual ~btConvex2dShape(); + + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + btConvexShape* getChildShape() + { + return m_childConvexShape; + } + + const btConvexShape* getChildShape() const + { + return m_childConvexShape; + } + + virtual const char* getName()const + { + return "Convex2dShape"; + } + + + + /////////////////////////// + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void setLocalScaling(const btVector3& scaling) ; + virtual const btVector3& getLocalScaling() const ; + + virtual void setMargin(btScalar margin); + virtual btScalar getMargin() const; + + virtual int getNumPreferredPenetrationDirections() const; + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const; + + +}; + +#endif //BT_CONVEX_2D_SHAPE_H diff --git a/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp b/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp new file mode 100644 index 0000000..2262459 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp @@ -0,0 +1,255 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btConvexHullShape.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btSerializer.h" + +btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int stride) : btPolyhedralConvexAabbCachingShape () +{ + m_shapeType = CONVEX_HULL_SHAPE_PROXYTYPE; + m_unscaledPoints.resize(numPoints); + + unsigned char* pointsAddress = (unsigned char*)points; + + for (int i=0;i maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + return supVec; +} + +void btConvexHullShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + btScalar newDot; + //use 'w' component of supportVerticesOut? + { + for (int i=0;i supportVerticesOut[j][3]) + { + //WARNING: don't swap next lines, the w component would get overwritten! + supportVerticesOut[j] = vtx; + supportVerticesOut[j][3] = newDot; + } + } + } + + + +} + + + +btVector3 btConvexHullShape::localGetSupportingVertex(const btVector3& vec)const +{ + btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); + + if ( getMargin()!=btScalar(0.) ) + { + btVector3 vecnorm = vec; + if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + vecnorm.normalize(); + supVertex+= getMargin() * vecnorm; + } + return supVertex; +} + + + + + + + + + +//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection +//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo +int btConvexHullShape::getNumVertices() const +{ + return m_unscaledPoints.size(); +} + +int btConvexHullShape::getNumEdges() const +{ + return m_unscaledPoints.size(); +} + +void btConvexHullShape::getEdge(int i,btVector3& pa,btVector3& pb) const +{ + + int index0 = i%m_unscaledPoints.size(); + int index1 = (i+1)%m_unscaledPoints.size(); + pa = getScaledPoint(index0); + pb = getScaledPoint(index1); +} + +void btConvexHullShape::getVertex(int i,btVector3& vtx) const +{ + vtx = getScaledPoint(i); +} + +int btConvexHullShape::getNumPlanes() const +{ + return 0; +} + +void btConvexHullShape::getPlane(btVector3& ,btVector3& ,int ) const +{ + + btAssert(0); +} + +//not yet +bool btConvexHullShape::isInside(const btVector3& ,btScalar ) const +{ + btAssert(0); + return false; +} + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btConvexHullShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + //int szc = sizeof(btConvexHullShapeData); + btConvexHullShapeData* shapeData = (btConvexHullShapeData*) dataBuffer; + btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer); + + int numElem = m_unscaledPoints.size(); + shapeData->m_numUnscaledPoints = numElem; +#ifdef BT_USE_DOUBLE_PRECISION + shapeData->m_unscaledPointsFloatPtr = 0; + shapeData->m_unscaledPointsDoublePtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]): 0; +#else + shapeData->m_unscaledPointsFloatPtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]): 0; + shapeData->m_unscaledPointsDoublePtr = 0; +#endif + + if (numElem) + { + int sz = sizeof(btVector3Data); + // int sz2 = sizeof(btVector3DoubleData); + // int sz3 = sizeof(btVector3FloatData); + btChunk* chunk = serializer->allocate(sz,numElem); + btVector3Data* memPtr = (btVector3Data*)chunk->m_oldPtr; + for (int i=0;ifinalizeChunk(chunk,btVector3DataName,BT_ARRAY_CODE,(void*)&m_unscaledPoints[0]); + } + + return "btConvexHullShapeData"; +} + +void btConvexHullShape::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const +{ +#if 1 + min = FLT_MAX; + max = -FLT_MAX; + btVector3 witnesPtMin; + btVector3 witnesPtMax; + + int numVerts = m_unscaledPoints.size(); + for(int i=0;i max) + { + max = dp; + witnesPtMax=pt; + } + } +#else + btVector3 localAxis = dir*trans.getBasis(); + btVector3 vtx1 = trans(localGetSupportingVertex(localAxis)); + btVector3 vtx2 = trans(localGetSupportingVertex(-localAxis)); + + min = vtx1.dot(dir); + max = vtx2.dot(dir); +#endif + + if(min>max) + { + btScalar tmp = min; + min = max; + max = tmp; + } + + +} + + diff --git a/src/BulletCollision/CollisionShapes/btConvexHullShape.h b/src/BulletCollision/CollisionShapes/btConvexHullShape.h new file mode 100644 index 0000000..95a2af6 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btConvexHullShape.h @@ -0,0 +1,122 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_HULL_SHAPE_H +#define BT_CONVEX_HULL_SHAPE_H + +#include "btPolyhedralConvexShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "LinearMath/btAlignedObjectArray.h" + + +///The btConvexHullShape implements an implicit convex hull of an array of vertices. +///Bullet provides a general and fast collision detector for convex shapes based on GJK and EPA using localGetSupportingVertex. +ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexAabbCachingShape +{ + btAlignedObjectArray m_unscaledPoints; + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + + ///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory. + ///It is easier to not pass any points in the constructor, and just add one point at a time, using addPoint. + ///btConvexHullShape make an internal copy of the points. + btConvexHullShape(const btScalar* points=0,int numPoints=0, int stride=sizeof(btVector3)); + + void addPoint(const btVector3& point); + + + btVector3* getUnscaledPoints() + { + return &m_unscaledPoints[0]; + } + + const btVector3* getUnscaledPoints() const + { + return &m_unscaledPoints[0]; + } + + ///getPoints is obsolete, please use getUnscaledPoints + const btVector3* getPoints() const + { + return getUnscaledPoints(); + } + + + + + SIMD_FORCE_INLINE btVector3 getScaledPoint(int i) const + { + return m_unscaledPoints[i] * m_localScaling; + } + + SIMD_FORCE_INLINE int getNumPoints() const + { + return m_unscaledPoints.size(); + } + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + + virtual void project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const; + + + //debugging + virtual const char* getName()const {return "Convex";} + + + virtual int getNumVertices() const; + virtual int getNumEdges() const; + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const; + virtual void getVertex(int i,btVector3& vtx) const; + virtual int getNumPlanes() const; + virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const; + virtual bool isInside(const btVector3& pt,btScalar tolerance) const; + + ///in case we receive negative scaling + virtual void setLocalScaling(const btVector3& scaling); + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btConvexHullShapeData +{ + btConvexInternalShapeData m_convexInternalShapeData; + + btVector3FloatData *m_unscaledPointsFloatPtr; + btVector3DoubleData *m_unscaledPointsDoublePtr; + + int m_numUnscaledPoints; + char m_padding3[4]; + +}; + + +SIMD_FORCE_INLINE int btConvexHullShape::calculateSerializeBufferSize() const +{ + return sizeof(btConvexHullShapeData); +} + + +#endif //BT_CONVEX_HULL_SHAPE_H + diff --git a/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp new file mode 100644 index 0000000..083d60b --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp @@ -0,0 +1,151 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btConvexInternalShape.h" + + + +btConvexInternalShape::btConvexInternalShape() +: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), +m_collisionMargin(CONVEX_DISTANCE_MARGIN) +{ +} + + +void btConvexInternalShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling.absolute(); +} + + + +void btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const +{ +#ifndef __SPU__ + //use localGetSupportingVertexWithoutMargin? + btScalar margin = getMargin(); + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + + btVector3 sv = localGetSupportingVertex(vec*trans.getBasis()); + + btVector3 tmp = trans(sv); + maxAabb[i] = tmp[i]+margin; + vec[i] = btScalar(-1.); + tmp = trans(localGetSupportingVertex(vec*trans.getBasis())); + minAabb[i] = tmp[i]-margin; + } +#endif +} + + + +btVector3 btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const +{ +#ifndef __SPU__ + + btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); + + if ( getMargin()!=btScalar(0.) ) + { + btVector3 vecnorm = vec; + if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + vecnorm.normalize(); + supVertex+= getMargin() * vecnorm; + } + return supVertex; + +#else + btAssert(0); + return btVector3(0,0,0); +#endif //__SPU__ + + } + + +btConvexInternalAabbCachingShape::btConvexInternalAabbCachingShape() + : btConvexInternalShape(), +m_localAabbMin(1,1,1), +m_localAabbMax(-1,-1,-1), +m_isLocalAabbValid(false) +{ +} + + +void btConvexInternalAabbCachingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + getNonvirtualAabb(trans,aabbMin,aabbMax,getMargin()); +} + +void btConvexInternalAabbCachingShape::setLocalScaling(const btVector3& scaling) +{ + btConvexInternalShape::setLocalScaling(scaling); + recalcLocalAabb(); +} + + +void btConvexInternalAabbCachingShape::recalcLocalAabb() +{ + m_isLocalAabbValid = true; + + #if 1 + static const btVector3 _directions[] = + { + btVector3( 1., 0., 0.), + btVector3( 0., 1., 0.), + btVector3( 0., 0., 1.), + btVector3( -1., 0., 0.), + btVector3( 0., -1., 0.), + btVector3( 0., 0., -1.) + }; + + btVector3 _supporting[] = + { + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.) + }; + + batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6); + + for ( int i = 0; i < 3; ++i ) + { + m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin; + m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin; + } + + #else + + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + btVector3 tmp = localGetSupportingVertex(vec); + m_localAabbMax[i] = tmp[i]+m_collisionMargin; + vec[i] = btScalar(-1.); + tmp = localGetSupportingVertex(vec); + m_localAabbMin[i] = tmp[i]-m_collisionMargin; + } + #endif +} diff --git a/src/BulletCollision/CollisionShapes/btConvexInternalShape.h b/src/BulletCollision/CollisionShapes/btConvexInternalShape.h new file mode 100644 index 0000000..85cd9ef --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btConvexInternalShape.h @@ -0,0 +1,224 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_INTERNAL_SHAPE_H +#define BT_CONVEX_INTERNAL_SHAPE_H + +#include "btConvexShape.h" +#include "LinearMath/btAabbUtil2.h" + + +///The btConvexInternalShape is an internal base class, shared by most convex shape implementations. +///The btConvexInternalShape uses a default collision margin set to CONVEX_DISTANCE_MARGIN. +///This collision margin used by Gjk and some other algorithms, see also btCollisionMargin.h +///Note that when creating small shapes (derived from btConvexInternalShape), +///you need to make sure to set a smaller collision margin, using the 'setMargin' API +///There is a automatic mechanism 'setSafeMargin' used by btBoxShape and btCylinderShape +class btConvexInternalShape : public btConvexShape +{ + + protected: + + //local scaling. collisionMargin is not scaled ! + btVector3 m_localScaling; + + btVector3 m_implicitShapeDimensions; + + btScalar m_collisionMargin; + + btScalar m_padding; + + btConvexInternalShape(); + +public: + + + + virtual ~btConvexInternalShape() + { + + } + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + + const btVector3& getImplicitShapeDimensions() const + { + return m_implicitShapeDimensions; + } + + ///warning: use setImplicitShapeDimensions with care + ///changing a collision shape while the body is in the world is not recommended, + ///it is best to remove the body from the world, then make the change, and re-add it + ///alternatively flush the contact points, see documentation for 'cleanProxyFromPairs' + void setImplicitShapeDimensions(const btVector3& dimensions) + { + m_implicitShapeDimensions = dimensions; + } + + void setSafeMargin(btScalar minDimension, btScalar defaultMarginMultiplier = 0.1f) + { + btScalar safeMargin = defaultMarginMultiplier*minDimension; + if (safeMargin < getMargin()) + { + setMargin(safeMargin); + } + } + void setSafeMargin(const btVector3& halfExtents, btScalar defaultMarginMultiplier = 0.1f) + { + //see http://code.google.com/p/bullet/issues/detail?id=349 + //this margin check could could be added to other collision shapes too, + //or add some assert/warning somewhere + btScalar minDimension=halfExtents[halfExtents.minAxis()]; + setSafeMargin(minDimension, defaultMarginMultiplier); + } + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + getAabbSlow(t,aabbMin,aabbMax); + } + + + + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const + { + return m_localScaling; + } + + const btVector3& getLocalScalingNV() const + { + return m_localScaling; + } + + virtual void setMargin(btScalar margin) + { + m_collisionMargin = margin; + } + virtual btScalar getMargin() const + { + return m_collisionMargin; + } + + btScalar getMarginNV() const + { + return m_collisionMargin; + } + + virtual int getNumPreferredPenetrationDirections() const + { + return 0; + } + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const + { + (void)penetrationVector; + (void)index; + btAssert(0); + } + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btConvexInternalShapeData +{ + btCollisionShapeData m_collisionShapeData; + + btVector3FloatData m_localScaling; + + btVector3FloatData m_implicitShapeDimensions; + + float m_collisionMargin; + + int m_padding; + +}; + + + +SIMD_FORCE_INLINE int btConvexInternalShape::calculateSerializeBufferSize() const +{ + return sizeof(btConvexInternalShapeData); +} + +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btConvexInternalShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btConvexInternalShapeData* shapeData = (btConvexInternalShapeData*) dataBuffer; + btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer); + + m_implicitShapeDimensions.serializeFloat(shapeData->m_implicitShapeDimensions); + m_localScaling.serializeFloat(shapeData->m_localScaling); + shapeData->m_collisionMargin = float(m_collisionMargin); + + return "btConvexInternalShapeData"; +} + + + + +///btConvexInternalAabbCachingShape adds local aabb caching for convex shapes, to avoid expensive bounding box calculations +class btConvexInternalAabbCachingShape : public btConvexInternalShape +{ + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + bool m_isLocalAabbValid; + +protected: + + btConvexInternalAabbCachingShape(); + + void setCachedLocalAabb (const btVector3& aabbMin, const btVector3& aabbMax) + { + m_isLocalAabbValid = true; + m_localAabbMin = aabbMin; + m_localAabbMax = aabbMax; + } + + inline void getCachedLocalAabb (btVector3& aabbMin, btVector3& aabbMax) const + { + btAssert(m_isLocalAabbValid); + aabbMin = m_localAabbMin; + aabbMax = m_localAabbMax; + } + + inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const + { + + //lazy evaluation of local aabb + btAssert(m_isLocalAabbValid); + btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax); + } + +public: + + virtual void setLocalScaling(const btVector3& scaling); + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + void recalcLocalAabb(); + +}; + +#endif //BT_CONVEX_INTERNAL_SHAPE_H diff --git a/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp b/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp new file mode 100644 index 0000000..c1b155a --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp @@ -0,0 +1,157 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btConvexPointCloudShape.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + +#include "LinearMath/btQuaternion.h" + +void btConvexPointCloudShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; + recalcLocalAabb(); +} + +#ifndef __SPU__ +btVector3 btConvexPointCloudShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const +{ + btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.)); + btScalar newDot,maxDot = btScalar(-BT_LARGE_FLOAT); + + btVector3 vec = vec0; + btScalar lenSqr = vec.length2(); + if (lenSqr < btScalar(0.0001)) + { + vec.setValue(1,0,0); + } else + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + vec *= rlen; + } + + + for (int i=0;i maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + return supVec; +} + +void btConvexPointCloudShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + btScalar newDot; + //use 'w' component of supportVerticesOut? + { + for (int i=0;i supportVerticesOut[j][3]) + { + //WARNING: don't swap next lines, the w component would get overwritten! + supportVerticesOut[j] = vtx; + supportVerticesOut[j][3] = newDot; + } + } + } + + + +} + + + +btVector3 btConvexPointCloudShape::localGetSupportingVertex(const btVector3& vec)const +{ + btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); + + if ( getMargin()!=btScalar(0.) ) + { + btVector3 vecnorm = vec; + if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + vecnorm.normalize(); + supVertex+= getMargin() * vecnorm; + } + return supVertex; +} + + +#endif + + + + + + +//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection +//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo +int btConvexPointCloudShape::getNumVertices() const +{ + return m_numPoints; +} + +int btConvexPointCloudShape::getNumEdges() const +{ + return 0; +} + +void btConvexPointCloudShape::getEdge(int i,btVector3& pa,btVector3& pb) const +{ + btAssert (0); +} + +void btConvexPointCloudShape::getVertex(int i,btVector3& vtx) const +{ + vtx = m_unscaledPoints[i]*m_localScaling; +} + +int btConvexPointCloudShape::getNumPlanes() const +{ + return 0; +} + +void btConvexPointCloudShape::getPlane(btVector3& ,btVector3& ,int ) const +{ + + btAssert(0); +} + +//not yet +bool btConvexPointCloudShape::isInside(const btVector3& ,btScalar ) const +{ + btAssert(0); + return false; +} + diff --git a/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h b/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h new file mode 100644 index 0000000..54b5afa --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h @@ -0,0 +1,105 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_POINT_CLOUD_SHAPE_H +#define BT_CONVEX_POINT_CLOUD_SHAPE_H + +#include "btPolyhedralConvexShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "LinearMath/btAlignedObjectArray.h" + +///The btConvexPointCloudShape implements an implicit convex hull of an array of vertices. +ATTRIBUTE_ALIGNED16(class) btConvexPointCloudShape : public btPolyhedralConvexAabbCachingShape +{ + btVector3* m_unscaledPoints; + int m_numPoints; + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btConvexPointCloudShape() + { + m_localScaling.setValue(1.f,1.f,1.f); + m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE; + m_unscaledPoints = 0; + m_numPoints = 0; + } + + btConvexPointCloudShape(btVector3* points,int numPoints, const btVector3& localScaling,bool computeAabb = true) + { + m_localScaling = localScaling; + m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE; + m_unscaledPoints = points; + m_numPoints = numPoints; + + if (computeAabb) + recalcLocalAabb(); + } + + void setPoints (btVector3* points, int numPoints, bool computeAabb = true,const btVector3& localScaling=btVector3(1.f,1.f,1.f)) + { + m_unscaledPoints = points; + m_numPoints = numPoints; + m_localScaling = localScaling; + + if (computeAabb) + recalcLocalAabb(); + } + + SIMD_FORCE_INLINE btVector3* getUnscaledPoints() + { + return m_unscaledPoints; + } + + SIMD_FORCE_INLINE const btVector3* getUnscaledPoints() const + { + return m_unscaledPoints; + } + + SIMD_FORCE_INLINE int getNumPoints() const + { + return m_numPoints; + } + + SIMD_FORCE_INLINE btVector3 getScaledPoint( int index) const + { + return m_unscaledPoints[index] * m_localScaling; + } + +#ifndef __SPU__ + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; +#endif + + + //debugging + virtual const char* getName()const {return "ConvexPointCloud";} + + virtual int getNumVertices() const; + virtual int getNumEdges() const; + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const; + virtual void getVertex(int i,btVector3& vtx) const; + virtual int getNumPlanes() const; + virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const; + virtual bool isInside(const btVector3& pt,btScalar tolerance) const; + + ///in case we receive negative scaling + virtual void setLocalScaling(const btVector3& scaling); +}; + + +#endif //BT_CONVEX_POINT_CLOUD_SHAPE_H + diff --git a/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp b/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp new file mode 100644 index 0000000..c8fe949 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp @@ -0,0 +1,296 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +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. +*/ + + +///This file was written by Erwin Coumans +///Separating axis rest based on work from Pierre Terdiman, see +///And contact clipping based on work from Simon Hobbs + +#include "btConvexPolyhedron.h" +#include "LinearMath/btHashMap.h" + +btConvexPolyhedron::btConvexPolyhedron() +{ + +} +btConvexPolyhedron::~btConvexPolyhedron() +{ + +} + + +inline bool IsAlmostZero(const btVector3& v) +{ + if(fabsf(v.x())>1e-6 || fabsf(v.y())>1e-6 || fabsf(v.z())>1e-6) return false; + return true; +} + +struct btInternalVertexPair +{ + btInternalVertexPair(short int v0,short int v1) + :m_v0(v0), + m_v1(v1) + { + if (m_v1>m_v0) + btSwap(m_v0,m_v1); + } + short int m_v0; + short int m_v1; + int getHash() const + { + return m_v0+(m_v1<<16); + } + bool equals(const btInternalVertexPair& other) const + { + return m_v0==other.m_v0 && m_v1==other.m_v1; + } +}; + +struct btInternalEdge +{ + btInternalEdge() + :m_face0(-1), + m_face1(-1) + { + } + short int m_face0; + short int m_face1; +}; + +// + +#ifdef TEST_INTERNAL_OBJECTS +bool btConvexPolyhedron::testContainment() const +{ + for(int p=0;p<8;p++) + { + btVector3 LocalPt; + if(p==0) LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], m_extents[2]); + else if(p==1) LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], -m_extents[2]); + else if(p==2) LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], m_extents[2]); + else if(p==3) LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], -m_extents[2]); + else if(p==4) LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], m_extents[2]); + else if(p==5) LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], -m_extents[2]); + else if(p==6) LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], m_extents[2]); + else if(p==7) LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], -m_extents[2]); + + for(int i=0;i0.0f) + return false; + } + } + return true; +} +#endif + +void btConvexPolyhedron::initialize() +{ + + btHashMap edges; + + btScalar TotalArea = 0.0f; + + m_localCenter.setValue(0, 0, 0); + for(int i=0;im_face0>=0); + btAssert(edptr->m_face1<0); + edptr->m_face1 = i; + } else + { + btInternalEdge ed; + ed.m_face0 = i; + edges.insert(vp,ed); + } + } + } + +#ifdef USE_CONNECTED_FACES + for(int i=0;im_face0>=0); + btAssert(edptr->m_face1>=0); + + int connectedFace = (edptr->m_face0==i)?edptr->m_face1:edptr->m_face0; + m_faces[i].m_connectedFaces[j] = connectedFace; + } + } +#endif//USE_CONNECTED_FACES + + for(int i=0;iMaxX) MaxX = pt.x(); + if(pt.y()MaxY) MaxY = pt.y(); + if(pt.z()MaxZ) MaxZ = pt.z(); + } + mC.setValue(MaxX+MinX, MaxY+MinY, MaxZ+MinZ); + mE.setValue(MaxX-MinX, MaxY-MinY, MaxZ-MinZ); + + + +// const btScalar r = m_radius / sqrtf(2.0f); + const btScalar r = m_radius / sqrtf(3.0f); + const int LargestExtent = mE.maxAxis(); + const btScalar Step = (mE[LargestExtent]*0.5f - r)/1024.0f; + m_extents[0] = m_extents[1] = m_extents[2] = r; + m_extents[LargestExtent] = mE[LargestExtent]*0.5f; + bool FoundBox = false; + for(int j=0;j<1024;j++) + { + if(testContainment()) + { + FoundBox = true; + break; + } + + m_extents[LargestExtent] -= Step; + } + if(!FoundBox) + { + m_extents[0] = m_extents[1] = m_extents[2] = r; + } + else + { + // Refine the box + const btScalar Step = (m_radius - r)/1024.0f; + const int e0 = (1< max) max = dp; + } + if(min>max) + { + btScalar tmp = min; + min = max; + max = tmp; + } +} \ No newline at end of file diff --git a/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h b/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h new file mode 100644 index 0000000..4386cdd --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h @@ -0,0 +1,62 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +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. +*/ + + +///This file was written by Erwin Coumans + + +#ifndef _BT_POLYHEDRAL_FEATURES_H +#define _BT_POLYHEDRAL_FEATURES_H + +#include "LinearMath/btTransform.h" +#include "LinearMath/btAlignedObjectArray.h" + +#define TEST_INTERNAL_OBJECTS 1 + + +struct btFace +{ + btAlignedObjectArray m_indices; +// btAlignedObjectArray m_connectedFaces; + btScalar m_plane[4]; +}; + + +class btConvexPolyhedron +{ + public: + btConvexPolyhedron(); + virtual ~btConvexPolyhedron(); + + btAlignedObjectArray m_vertices; + btAlignedObjectArray m_faces; + btAlignedObjectArray m_uniqueEdges; + + btVector3 m_localCenter; + btVector3 m_extents; + btScalar m_radius; + btVector3 mC; + btVector3 mE; + + void initialize(); + bool testContainment() const; + + void project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const; +}; + + +#endif //_BT_POLYHEDRAL_FEATURES_H + + diff --git a/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/src/BulletCollision/CollisionShapes/btConvexShape.cpp new file mode 100644 index 0000000..8c67d8e --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btConvexShape.cpp @@ -0,0 +1,446 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btConvexShape.h" +#include "btTriangleShape.h" +#include "btSphereShape.h" +#include "btCylinderShape.h" +#include "btCapsuleShape.h" +#include "btConvexHullShape.h" +#include "btConvexPointCloudShape.h" + +///not supported on IBM SDK, until we fix the alignment of btVector3 +#if defined (__CELLOS_LV2__) && defined (__SPU__) +#include +static inline vec_float4 vec_dot3( vec_float4 vec0, vec_float4 vec1 ) +{ + vec_float4 result; + result = spu_mul( vec0, vec1 ); + result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result ); + return spu_madd( spu_rlqwbyte( vec0, 8 ), spu_rlqwbyte( vec1, 8 ), result ); +} +#endif //__SPU__ + +btConvexShape::btConvexShape () +{ +} + +btConvexShape::~btConvexShape() +{ + +} + + +void btConvexShape::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const +{ + btVector3 localAxis = dir*trans.getBasis(); + btVector3 vtx1 = trans(localGetSupportingVertex(localAxis)); + btVector3 vtx2 = trans(localGetSupportingVertex(-localAxis)); + + min = vtx1.dot(dir); + max = vtx2.dot(dir); + + if(min>max) + { + btScalar tmp = min; + min = max; + max = tmp; + } +} + + +static btVector3 convexHullSupport (const btVector3& localDirOrg, const btVector3* points, int numPoints, const btVector3& localScaling) +{ + + btVector3 vec = localDirOrg * localScaling; + +#if defined (__CELLOS_LV2__) && defined (__SPU__) + + btVector3 localDir = vec; + + vec_float4 v_distMax = {-FLT_MAX,0,0,0}; + vec_int4 v_idxMax = {-999,0,0,0}; + int v=0; + int numverts = numPoints; + + for(;v<(int)numverts-4;v+=4) { + vec_float4 p0 = vec_dot3(points[v ].get128(),localDir.get128()); + vec_float4 p1 = vec_dot3(points[v+1].get128(),localDir.get128()); + vec_float4 p2 = vec_dot3(points[v+2].get128(),localDir.get128()); + vec_float4 p3 = vec_dot3(points[v+3].get128(),localDir.get128()); + const vec_int4 i0 = {v ,0,0,0}; + const vec_int4 i1 = {v+1,0,0,0}; + const vec_int4 i2 = {v+2,0,0,0}; + const vec_int4 i3 = {v+3,0,0,0}; + vec_uint4 retGt01 = spu_cmpgt(p0,p1); + vec_float4 pmax01 = spu_sel(p1,p0,retGt01); + vec_int4 imax01 = spu_sel(i1,i0,retGt01); + vec_uint4 retGt23 = spu_cmpgt(p2,p3); + vec_float4 pmax23 = spu_sel(p3,p2,retGt23); + vec_int4 imax23 = spu_sel(i3,i2,retGt23); + vec_uint4 retGt0123 = spu_cmpgt(pmax01,pmax23); + vec_float4 pmax0123 = spu_sel(pmax23,pmax01,retGt0123); + vec_int4 imax0123 = spu_sel(imax23,imax01,retGt0123); + vec_uint4 retGtMax = spu_cmpgt(v_distMax,pmax0123); + v_distMax = spu_sel(pmax0123,v_distMax,retGtMax); + v_idxMax = spu_sel(imax0123,v_idxMax,retGtMax); + } + for(;v<(int)numverts;v++) { + vec_float4 p = vec_dot3(points[v].get128(),localDir.get128()); + const vec_int4 i = {v,0,0,0}; + vec_uint4 retGtMax = spu_cmpgt(v_distMax,p); + v_distMax = spu_sel(p,v_distMax,retGtMax); + v_idxMax = spu_sel(i,v_idxMax,retGtMax); + } + int ptIndex = spu_extract(v_idxMax,0); + const btVector3& supVec= points[ptIndex] * localScaling; + return supVec; +#else + + btScalar newDot,maxDot = btScalar(-BT_LARGE_FLOAT); + int ptIndex = -1; + + for (int i=0;i maxDot) + { + maxDot = newDot; + ptIndex = i; + } + } + btAssert(ptIndex >= 0); + btVector3 supVec = points[ptIndex] * localScaling; + return supVec; +#endif //__SPU__ +} + +btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btVector3& localDir) const +{ + switch (m_shapeType) + { + case SPHERE_SHAPE_PROXYTYPE: + { + return btVector3(0,0,0); + } + case BOX_SHAPE_PROXYTYPE: + { + btBoxShape* convexShape = (btBoxShape*)this; + const btVector3& halfExtents = convexShape->getImplicitShapeDimensions(); + + return btVector3(btFsels(localDir.x(), halfExtents.x(), -halfExtents.x()), + btFsels(localDir.y(), halfExtents.y(), -halfExtents.y()), + btFsels(localDir.z(), halfExtents.z(), -halfExtents.z())); + } + case TRIANGLE_SHAPE_PROXYTYPE: + { + btTriangleShape* triangleShape = (btTriangleShape*)this; + btVector3 dir(localDir.getX(),localDir.getY(),localDir.getZ()); + btVector3* vertices = &triangleShape->m_vertices1[0]; + btVector3 dots(dir.dot(vertices[0]), dir.dot(vertices[1]), dir.dot(vertices[2])); + btVector3 sup = vertices[dots.maxAxis()]; + return btVector3(sup.getX(),sup.getY(),sup.getZ()); + } + case CYLINDER_SHAPE_PROXYTYPE: + { + btCylinderShape* cylShape = (btCylinderShape*)this; + //mapping of halfextents/dimension onto radius/height depends on how cylinder local orientation is (upAxis) + + btVector3 halfExtents = cylShape->getImplicitShapeDimensions(); + btVector3 v(localDir.getX(),localDir.getY(),localDir.getZ()); + int cylinderUpAxis = cylShape->getUpAxis(); + int XX(1),YY(0),ZZ(2); + + switch (cylinderUpAxis) + { + case 0: + { + XX = 1; + YY = 0; + ZZ = 2; + } + break; + case 1: + { + XX = 0; + YY = 1; + ZZ = 2; + } + break; + case 2: + { + XX = 0; + YY = 2; + ZZ = 1; + + } + break; + default: + btAssert(0); + break; + }; + + btScalar radius = halfExtents[XX]; + btScalar halfHeight = halfExtents[cylinderUpAxis]; + + btVector3 tmp; + btScalar d ; + + btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]); + if (s != btScalar(0.0)) + { + d = radius / s; + tmp[XX] = v[XX] * d; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = v[ZZ] * d; + return btVector3(tmp.getX(),tmp.getY(),tmp.getZ()); + } else { + tmp[XX] = radius; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = btScalar(0.0); + return btVector3(tmp.getX(),tmp.getY(),tmp.getZ()); + } + } + case CAPSULE_SHAPE_PROXYTYPE: + { + btVector3 vec0(localDir.getX(),localDir.getY(),localDir.getZ()); + + btCapsuleShape* capsuleShape = (btCapsuleShape*)this; + btScalar halfHeight = capsuleShape->getHalfHeight(); + int capsuleUpAxis = capsuleShape->getUpAxis(); + + btScalar radius = capsuleShape->getRadius(); + btVector3 supVec(0,0,0); + + btScalar maxDot(btScalar(-BT_LARGE_FLOAT)); + + btVector3 vec = vec0; + btScalar lenSqr = vec.length2(); + if (lenSqr < btScalar(0.0001)) + { + vec.setValue(1,0,0); + } else + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + vec *= rlen; + } + btVector3 vtx; + btScalar newDot; + { + btVector3 pos(0,0,0); + pos[capsuleUpAxis] = halfHeight; + + //vtx = pos +vec*(radius); + vtx = pos +vec*(radius) - vec * capsuleShape->getMarginNV(); + newDot = vec.dot(vtx); + + + if (newDot > maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + { + btVector3 pos(0,0,0); + pos[capsuleUpAxis] = -halfHeight; + + //vtx = pos +vec*(radius); + vtx = pos +vec*(radius) - vec * capsuleShape->getMarginNV(); + newDot = vec.dot(vtx); + if (newDot > maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + return btVector3(supVec.getX(),supVec.getY(),supVec.getZ()); + } + case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE: + { + btConvexPointCloudShape* convexPointCloudShape = (btConvexPointCloudShape*)this; + btVector3* points = convexPointCloudShape->getUnscaledPoints (); + int numPoints = convexPointCloudShape->getNumPoints (); + return convexHullSupport (localDir, points, numPoints,convexPointCloudShape->getLocalScalingNV()); + } + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + btConvexHullShape* convexHullShape = (btConvexHullShape*)this; + btVector3* points = convexHullShape->getUnscaledPoints(); + int numPoints = convexHullShape->getNumPoints (); + return convexHullSupport (localDir, points, numPoints,convexHullShape->getLocalScalingNV()); + } + default: +#ifndef __SPU__ + return this->localGetSupportingVertexWithoutMargin (localDir); +#else + btAssert (0); +#endif + } + + // should never reach here + btAssert (0); + return btVector3 (btScalar(0.0f), btScalar(0.0f), btScalar(0.0f)); +} + +btVector3 btConvexShape::localGetSupportVertexNonVirtual (const btVector3& localDir) const +{ + btVector3 localDirNorm = localDir; + if (localDirNorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + localDirNorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + localDirNorm.normalize (); + + return localGetSupportVertexWithoutMarginNonVirtual(localDirNorm)+ getMarginNonVirtual() * localDirNorm; +} + +/* TODO: This should be bumped up to btCollisionShape () */ +btScalar btConvexShape::getMarginNonVirtual () const +{ + switch (m_shapeType) + { + case SPHERE_SHAPE_PROXYTYPE: + { + btSphereShape* sphereShape = (btSphereShape*)this; + return sphereShape->getRadius (); + } + case BOX_SHAPE_PROXYTYPE: + { + btBoxShape* convexShape = (btBoxShape*)this; + return convexShape->getMarginNV (); + } + case TRIANGLE_SHAPE_PROXYTYPE: + { + btTriangleShape* triangleShape = (btTriangleShape*)this; + return triangleShape->getMarginNV (); + } + case CYLINDER_SHAPE_PROXYTYPE: + { + btCylinderShape* cylShape = (btCylinderShape*)this; + return cylShape->getMarginNV(); + } + case CAPSULE_SHAPE_PROXYTYPE: + { + btCapsuleShape* capsuleShape = (btCapsuleShape*)this; + return capsuleShape->getMarginNV(); + } + case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE: + /* fall through */ + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + btPolyhedralConvexShape* convexHullShape = (btPolyhedralConvexShape*)this; + return convexHullShape->getMarginNV(); + } + default: +#ifndef __SPU__ + return this->getMargin (); +#else + btAssert (0); +#endif + } + + // should never reach here + btAssert (0); + return btScalar(0.0f); +} +#ifndef __SPU__ +void btConvexShape::getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const +{ + switch (m_shapeType) + { + case SPHERE_SHAPE_PROXYTYPE: + { + btSphereShape* sphereShape = (btSphereShape*)this; + btScalar radius = sphereShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX(); + btScalar margin = radius + sphereShape->getMarginNonVirtual(); + const btVector3& center = t.getOrigin(); + btVector3 extent(margin,margin,margin); + aabbMin = center - extent; + aabbMax = center + extent; + } + break; + case CYLINDER_SHAPE_PROXYTYPE: + /* fall through */ + case BOX_SHAPE_PROXYTYPE: + { + btBoxShape* convexShape = (btBoxShape*)this; + btScalar margin=convexShape->getMarginNonVirtual(); + btVector3 halfExtents = convexShape->getImplicitShapeDimensions(); + halfExtents += btVector3(margin,margin,margin); + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents)); + + aabbMin = center - extent; + aabbMax = center + extent; + break; + } + case TRIANGLE_SHAPE_PROXYTYPE: + { + btTriangleShape* triangleShape = (btTriangleShape*)this; + btScalar margin = triangleShape->getMarginNonVirtual(); + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + + btVector3 sv = localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis()); + + btVector3 tmp = t(sv); + aabbMax[i] = tmp[i]+margin; + vec[i] = btScalar(-1.); + tmp = t(localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis())); + aabbMin[i] = tmp[i]-margin; + } + } + break; + case CAPSULE_SHAPE_PROXYTYPE: + { + btCapsuleShape* capsuleShape = (btCapsuleShape*)this; + btVector3 halfExtents(capsuleShape->getRadius(),capsuleShape->getRadius(),capsuleShape->getRadius()); + int m_upAxis = capsuleShape->getUpAxis(); + halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight(); + halfExtents += btVector3(capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual()); + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents)); + aabbMin = center - extent; + aabbMax = center + extent; + } + break; + case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE: + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + btPolyhedralConvexAabbCachingShape* convexHullShape = (btPolyhedralConvexAabbCachingShape*)this; + btScalar margin = convexHullShape->getMarginNonVirtual(); + convexHullShape->getNonvirtualAabb (t, aabbMin, aabbMax, margin); + } + break; + default: +#ifndef __SPU__ + this->getAabb (t, aabbMin, aabbMax); +#else + btAssert (0); +#endif + break; + } + + // should never reach here + btAssert (0); +} + +#endif //__SPU__ diff --git a/src/BulletCollision/CollisionShapes/btConvexShape.h b/src/BulletCollision/CollisionShapes/btConvexShape.h new file mode 100644 index 0000000..290cd9f --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btConvexShape.h @@ -0,0 +1,84 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_SHAPE_INTERFACE1 +#define BT_CONVEX_SHAPE_INTERFACE1 + +#include "btCollisionShape.h" + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" +#include "btCollisionMargin.h" +#include "LinearMath/btAlignedAllocator.h" + +#define MAX_PREFERRED_PENETRATION_DIRECTIONS 10 + +/// The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape, btConvexHullShape etc. +/// It describes general convex shapes using the localGetSupportingVertex interface, used by collision detectors such as btGjkPairDetector. +ATTRIBUTE_ALIGNED16(class) btConvexShape : public btCollisionShape +{ + + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btConvexShape (); + + virtual ~btConvexShape(); + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const = 0; + + //////// + #ifndef __SPU__ + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const=0; + #endif //#ifndef __SPU__ + + btVector3 localGetSupportVertexWithoutMarginNonVirtual (const btVector3& vec) const; + btVector3 localGetSupportVertexNonVirtual (const btVector3& vec) const; + btScalar getMarginNonVirtual () const; + void getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const; + + virtual void project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const; + + + //notice that the vectors should be unit length + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0; + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; + + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; + + virtual void setLocalScaling(const btVector3& scaling) =0; + virtual const btVector3& getLocalScaling() const =0; + + virtual void setMargin(btScalar margin)=0; + + virtual btScalar getMargin() const=0; + + virtual int getNumPreferredPenetrationDirections() const=0; + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const=0; + + + + +}; + + + +#endif //BT_CONVEX_SHAPE_INTERFACE1 diff --git a/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp new file mode 100644 index 0000000..0f9ced5 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp @@ -0,0 +1,315 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btConvexTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + +#include "LinearMath/btQuaternion.h" +#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h" + + +btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb) +: btPolyhedralConvexAabbCachingShape(), m_stridingMesh(meshInterface) +{ + m_shapeType = CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE; + if ( calcAabb ) + recalcLocalAabb(); +} + + + + +///It's not nice to have all this virtual function overhead, so perhaps we can also gather the points once +///but then we are duplicating +class LocalSupportVertexCallback: public btInternalTriangleIndexCallback +{ + + btVector3 m_supportVertexLocal; +public: + + btScalar m_maxDot; + btVector3 m_supportVecLocal; + + LocalSupportVertexCallback(const btVector3& supportVecLocal) + : m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)), + m_maxDot(btScalar(-BT_LARGE_FLOAT)), + m_supportVecLocal(supportVecLocal) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + (void)triangleIndex; + (void)partId; + + for (int i=0;i<3;i++) + { + btScalar dot = m_supportVecLocal.dot(triangle[i]); + if (dot > m_maxDot) + { + m_maxDot = dot; + m_supportVertexLocal = triangle[i]; + } + } + } + + btVector3 GetSupportVertexLocal() + { + return m_supportVertexLocal; + } + +}; + + + + + +btVector3 btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const +{ + btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.)); + + btVector3 vec = vec0; + btScalar lenSqr = vec.length2(); + if (lenSqr < btScalar(0.0001)) + { + vec.setValue(1,0,0); + } else + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + vec *= rlen; + } + + LocalSupportVertexCallback supportCallback(vec); + btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax); + supVec = supportCallback.GetSupportVertexLocal(); + + return supVec; +} + +void btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + //use 'w' component of supportVerticesOut? + { + for (int i=0;iInternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax); + supportVerticesOut[j] = supportCallback.GetSupportVertexLocal(); + } + +} + + + +btVector3 btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec)const +{ + btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); + + if ( getMargin()!=btScalar(0.) ) + { + btVector3 vecnorm = vec; + if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + vecnorm.normalize(); + supVertex+= getMargin() * vecnorm; + } + return supVertex; +} + + + + + + + + + +//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection +//Please note that you can debug-draw btConvexTriangleMeshShape with the Raytracer Demo +int btConvexTriangleMeshShape::getNumVertices() const +{ + //cache this? + return 0; + +} + +int btConvexTriangleMeshShape::getNumEdges() const +{ + return 0; +} + +void btConvexTriangleMeshShape::getEdge(int ,btVector3& ,btVector3& ) const +{ + btAssert(0); +} + +void btConvexTriangleMeshShape::getVertex(int ,btVector3& ) const +{ + btAssert(0); +} + +int btConvexTriangleMeshShape::getNumPlanes() const +{ + return 0; +} + +void btConvexTriangleMeshShape::getPlane(btVector3& ,btVector3& ,int ) const +{ + btAssert(0); +} + +//not yet +bool btConvexTriangleMeshShape::isInside(const btVector3& ,btScalar ) const +{ + btAssert(0); + return false; +} + + + +void btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling) +{ + m_stridingMesh->setScaling(scaling); + + recalcLocalAabb(); + +} + + +const btVector3& btConvexTriangleMeshShape::getLocalScaling() const +{ + return m_stridingMesh->getScaling(); +} + +void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const +{ + class CenterCallback: public btInternalTriangleIndexCallback + { + bool first; + btVector3 ref; + btVector3 sum; + btScalar volume; + + public: + + CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) + { + (void) triangleIndex; + (void) partId; + if (first) + { + ref = triangle[0]; + first = false; + } + else + { + btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref)); + sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref)); + volume += vol; + } + } + + btVector3 getCenter() + { + return (volume > 0) ? sum / volume : ref; + } + + btScalar getVolume() + { + return volume * btScalar(1. / 6); + } + + }; + + class InertiaCallback: public btInternalTriangleIndexCallback + { + btMatrix3x3 sum; + btVector3 center; + + public: + + InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) + { + (void) triangleIndex; + (void) partId; + btMatrix3x3 i; + btVector3 a = triangle[0] - center; + btVector3 b = triangle[1] - center; + btVector3 c = triangle[2] - center; + btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6); + for (int j = 0; j < 3; j++) + { + for (int k = 0; k <= j; k++) + { + i[j][k] = i[k][j] = volNeg * (btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k]) + + btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j])); + } + } + btScalar i00 = -i[0][0]; + btScalar i11 = -i[1][1]; + btScalar i22 = -i[2][2]; + i[0][0] = i11 + i22; + i[1][1] = i22 + i00; + i[2][2] = i00 + i11; + sum[0] += i[0]; + sum[1] += i[1]; + sum[2] += i[2]; + } + + btMatrix3x3& getInertia() + { + return sum; + } + + }; + + CenterCallback centerCallback; + btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + m_stridingMesh->InternalProcessAllTriangles(¢erCallback, -aabbMax, aabbMax); + btVector3 center = centerCallback.getCenter(); + principal.setOrigin(center); + volume = centerCallback.getVolume(); + + InertiaCallback inertiaCallback(center); + m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax); + + btMatrix3x3& i = inertiaCallback.getInertia(); + i.diagonalize(principal.getBasis(), btScalar(0.00001), 20); + inertia.setValue(i[0][0], i[1][1], i[2][2]); + inertia /= volume; +} + diff --git a/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h new file mode 100644 index 0000000..af5d003 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h @@ -0,0 +1,75 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BT_CONVEX_TRIANGLEMESH_SHAPE_H +#define BT_CONVEX_TRIANGLEMESH_SHAPE_H + + +#include "btPolyhedralConvexShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types + + +/// The btConvexTriangleMeshShape is a convex hull of a triangle mesh, but the performance is not as good as btConvexHullShape. +/// A small benefit of this class is that it uses the btStridingMeshInterface, so you can avoid the duplication of the triangle mesh data. Nevertheless, most users should use the much better performing btConvexHullShape instead. +class btConvexTriangleMeshShape : public btPolyhedralConvexAabbCachingShape +{ + + class btStridingMeshInterface* m_stridingMesh; + +public: + btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb = true); + + class btStridingMeshInterface* getMeshInterface() + { + return m_stridingMesh; + } + const class btStridingMeshInterface* getMeshInterface() const + { + return m_stridingMesh; + } + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + //debugging + virtual const char* getName()const {return "ConvexTrimesh";} + + virtual int getNumVertices() const; + virtual int getNumEdges() const; + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const; + virtual void getVertex(int i,btVector3& vtx) const; + virtual int getNumPlanes() const; + virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const; + virtual bool isInside(const btVector3& pt,btScalar tolerance) const; + + + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const; + + ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia + ///and the center of mass to the current coordinate system. A mass of 1 is assumed, for other masses just multiply the computed "inertia" + ///by the mass. The resulting transform "principal" has to be applied inversely to the mesh in order for the local coordinate system of the + ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform + ///of the collision object by the principal transform. This method also computes the volume of the convex mesh. + void calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const; + +}; + + + +#endif //BT_CONVEX_TRIANGLEMESH_SHAPE_H + + + diff --git a/src/BulletCollision/CollisionShapes/btCylinderShape.cpp b/src/BulletCollision/CollisionShapes/btCylinderShape.cpp new file mode 100644 index 0000000..6cfe43b --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btCylinderShape.cpp @@ -0,0 +1,281 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btCylinderShape.h" + +btCylinderShape::btCylinderShape (const btVector3& halfExtents) +:btConvexInternalShape(), +m_upAxis(1) +{ + setSafeMargin(halfExtents); + + btVector3 margin(getMargin(),getMargin(),getMargin()); + m_implicitShapeDimensions = (halfExtents * m_localScaling) - margin; + m_shapeType = CYLINDER_SHAPE_PROXYTYPE; +} + + +btCylinderShapeX::btCylinderShapeX (const btVector3& halfExtents) +:btCylinderShape(halfExtents) +{ + m_upAxis = 0; + +} + + +btCylinderShapeZ::btCylinderShapeZ (const btVector3& halfExtents) +:btCylinderShape(halfExtents) +{ + m_upAxis = 2; + +} + +void btCylinderShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax); +} + +void btCylinderShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + +//Until Bullet 2.77 a box approximation was used, so uncomment this if you need backwards compatibility +//#define USE_BOX_INERTIA_APPROXIMATION 1 +#ifndef USE_BOX_INERTIA_APPROXIMATION + + /* + cylinder is defined as following: + * + * - principle axis aligned along y by default, radius in x, z-value not used + * - for btCylinderShapeX: principle axis aligned along x, radius in y direction, z-value not used + * - for btCylinderShapeZ: principle axis aligned along z, radius in x direction, y-value not used + * + */ + + btScalar radius2; // square of cylinder radius + btScalar height2; // square of cylinder height + btVector3 halfExtents = getHalfExtentsWithMargin(); // get cylinder dimension + btScalar div12 = mass / 12.f; + btScalar div4 = mass / 4.f; + btScalar div2 = mass / 2.f; + int idxRadius, idxHeight; + + switch (m_upAxis) // get indices of radius and height of cylinder + { + case 0: // cylinder is aligned along x + idxRadius = 1; + idxHeight = 0; + break; + case 2: // cylinder is aligned along z + idxRadius = 0; + idxHeight = 2; + break; + default: // cylinder is aligned along y + idxRadius = 0; + idxHeight = 1; + } + + // calculate squares + radius2 = halfExtents[idxRadius] * halfExtents[idxRadius]; + height2 = btScalar(4.) * halfExtents[idxHeight] * halfExtents[idxHeight]; + + // calculate tensor terms + btScalar t1 = div12 * height2 + div4 * radius2; + btScalar t2 = div2 * radius2; + + switch (m_upAxis) // set diagonal elements of inertia tensor + { + case 0: // cylinder is aligned along x + inertia.setValue(t2,t1,t1); + break; + case 2: // cylinder is aligned along z + inertia.setValue(t1,t1,t2); + break; + default: // cylinder is aligned along y + inertia.setValue(t1,t2,t1); + } +#else //USE_BOX_INERTIA_APPROXIMATION + //approximation of box shape + btVector3 halfExtents = getHalfExtentsWithMargin(); + + btScalar lx=btScalar(2.)*(halfExtents.x()); + btScalar ly=btScalar(2.)*(halfExtents.y()); + btScalar lz=btScalar(2.)*(halfExtents.z()); + + inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + ly*ly)); +#endif //USE_BOX_INERTIA_APPROXIMATION +} + + +SIMD_FORCE_INLINE btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v) +{ +const int cylinderUpAxis = 0; +const int XX = 1; +const int YY = 0; +const int ZZ = 2; + + //mapping depends on how cylinder local orientation is + // extents of the cylinder is: X,Y is for radius, and Z for height + + + btScalar radius = halfExtents[XX]; + btScalar halfHeight = halfExtents[cylinderUpAxis]; + + + btVector3 tmp; + btScalar d ; + + btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]); + if (s != btScalar(0.0)) + { + d = radius / s; + tmp[XX] = v[XX] * d; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = v[ZZ] * d; + return tmp; + } + else + { + tmp[XX] = radius; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = btScalar(0.0); + return tmp; + } + + +} + + + + + + +inline btVector3 CylinderLocalSupportY(const btVector3& halfExtents,const btVector3& v) +{ + +const int cylinderUpAxis = 1; +const int XX = 0; +const int YY = 1; +const int ZZ = 2; + + + btScalar radius = halfExtents[XX]; + btScalar halfHeight = halfExtents[cylinderUpAxis]; + + + btVector3 tmp; + btScalar d ; + + btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]); + if (s != btScalar(0.0)) + { + d = radius / s; + tmp[XX] = v[XX] * d; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = v[ZZ] * d; + return tmp; + } + else + { + tmp[XX] = radius; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = btScalar(0.0); + return tmp; + } + +} + +inline btVector3 CylinderLocalSupportZ(const btVector3& halfExtents,const btVector3& v) +{ +const int cylinderUpAxis = 2; +const int XX = 0; +const int YY = 2; +const int ZZ = 1; + + //mapping depends on how cylinder local orientation is + // extents of the cylinder is: X,Y is for radius, and Z for height + + + btScalar radius = halfExtents[XX]; + btScalar halfHeight = halfExtents[cylinderUpAxis]; + + + btVector3 tmp; + btScalar d ; + + btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]); + if (s != btScalar(0.0)) + { + d = radius / s; + tmp[XX] = v[XX] * d; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = v[ZZ] * d; + return tmp; + } + else + { + tmp[XX] = radius; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = btScalar(0.0); + return tmp; + } + + +} + +btVector3 btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + return CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vec); +} + + +btVector3 btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + return CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vec); +} +btVector3 btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + return CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vec); +} + +void btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + for (int i=0;im_convexInternalShapeData,serializer); + + shapeData->m_upAxis = m_upAxis; + + return "btCylinderShapeData"; +} + + + +#endif //BT_CYLINDER_MINKOWSKI_H + diff --git a/src/BulletCollision/CollisionShapes/btEmptyShape.cpp b/src/BulletCollision/CollisionShapes/btEmptyShape.cpp new file mode 100644 index 0000000..a9e6df5 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btEmptyShape.cpp @@ -0,0 +1,50 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btEmptyShape.h" + + +#include "btCollisionShape.h" + + +btEmptyShape::btEmptyShape() : btConcaveShape () +{ + m_shapeType = EMPTY_SHAPE_PROXYTYPE; +} + + +btEmptyShape::~btEmptyShape() +{ +} + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version +void btEmptyShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + btVector3 margin(getMargin(),getMargin(),getMargin()); + + aabbMin = t.getOrigin() - margin; + + aabbMax = t.getOrigin() + margin; + +} + +void btEmptyShape::calculateLocalInertia(btScalar ,btVector3& ) const +{ + btAssert(0); +} + + + diff --git a/src/BulletCollision/CollisionShapes/btEmptyShape.h b/src/BulletCollision/CollisionShapes/btEmptyShape.h new file mode 100644 index 0000000..87b7b66 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btEmptyShape.h @@ -0,0 +1,70 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_EMPTY_SHAPE_H +#define BT_EMPTY_SHAPE_H + +#include "btConcaveShape.h" + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" +#include "btCollisionMargin.h" + + + + +/// The btEmptyShape is a collision shape without actual collision detection shape, so most users should ignore this class. +/// It can be replaced by another shape during runtime, but the inertia tensor should be recomputed. +class btEmptyShape : public btConcaveShape +{ +public: + btEmptyShape(); + + virtual ~btEmptyShape(); + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + + virtual void setLocalScaling(const btVector3& scaling) + { + m_localScaling = scaling; + } + virtual const btVector3& getLocalScaling() const + { + return m_localScaling; + } + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual const char* getName()const + { + return "Empty"; + } + + virtual void processAllTriangles(btTriangleCallback* ,const btVector3& ,const btVector3& ) const + { + } + +protected: + btVector3 m_localScaling; + +}; + + + +#endif //BT_EMPTY_SHAPE_H diff --git a/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp new file mode 100644 index 0000000..95631c3 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp @@ -0,0 +1,411 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btHeightfieldTerrainShape.h" + +#include "LinearMath/btTransformUtil.h" + + + +btHeightfieldTerrainShape::btHeightfieldTerrainShape +( +int heightStickWidth, int heightStickLength, const void* heightfieldData, +btScalar heightScale, btScalar minHeight, btScalar maxHeight,int upAxis, +PHY_ScalarType hdt, bool flipQuadEdges +) +{ + initialize(heightStickWidth, heightStickLength, heightfieldData, + heightScale, minHeight, maxHeight, upAxis, hdt, + flipQuadEdges); +} + + + +btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,const void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges) +{ + // legacy constructor: support only float or unsigned char, + // and min height is zero + PHY_ScalarType hdt = (useFloatData) ? PHY_FLOAT : PHY_UCHAR; + btScalar minHeight = 0.0; + + // previously, height = uchar * maxHeight / 65535. + // So to preserve legacy behavior, heightScale = maxHeight / 65535 + btScalar heightScale = maxHeight / 65535; + + initialize(heightStickWidth, heightStickLength, heightfieldData, + heightScale, minHeight, maxHeight, upAxis, hdt, + flipQuadEdges); +} + + + +void btHeightfieldTerrainShape::initialize +( +int heightStickWidth, int heightStickLength, const void* heightfieldData, +btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis, +PHY_ScalarType hdt, bool flipQuadEdges +) +{ + // validation + btAssert(heightStickWidth > 1 && "bad width"); + btAssert(heightStickLength > 1 && "bad length"); + btAssert(heightfieldData && "null heightfield data"); + // btAssert(heightScale) -- do we care? Trust caller here + btAssert(minHeight <= maxHeight && "bad min/max height"); + btAssert(upAxis >= 0 && upAxis < 3 && + "bad upAxis--should be in range [0,2]"); + btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT && + "Bad height data type enum"); + + // initialize member variables + m_shapeType = TERRAIN_SHAPE_PROXYTYPE; + m_heightStickWidth = heightStickWidth; + m_heightStickLength = heightStickLength; + m_minHeight = minHeight; + m_maxHeight = maxHeight; + m_width = (btScalar) (heightStickWidth - 1); + m_length = (btScalar) (heightStickLength - 1); + m_heightScale = heightScale; + m_heightfieldDataUnknown = heightfieldData; + m_heightDataType = hdt; + m_flipQuadEdges = flipQuadEdges; + m_useDiamondSubdivision = false; + m_upAxis = upAxis; + m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.)); + + // determine min/max axis-aligned bounding box (aabb) values + switch (m_upAxis) + { + case 0: + { + m_localAabbMin.setValue(m_minHeight, 0, 0); + m_localAabbMax.setValue(m_maxHeight, m_width, m_length); + break; + } + case 1: + { + m_localAabbMin.setValue(0, m_minHeight, 0); + m_localAabbMax.setValue(m_width, m_maxHeight, m_length); + break; + }; + case 2: + { + m_localAabbMin.setValue(0, 0, m_minHeight); + m_localAabbMax.setValue(m_width, m_length, m_maxHeight); + break; + } + default: + { + //need to get valid m_upAxis + btAssert(0 && "Bad m_upAxis"); + } + } + + // remember origin (defined as exact middle of aabb) + m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax); +} + + + +btHeightfieldTerrainShape::~btHeightfieldTerrainShape() +{ +} + + + +void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5); + + btVector3 localOrigin(0, 0, 0); + localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5); + localOrigin *= m_localScaling; + + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = btVector3(abs_b[0].dot(halfExtents), + abs_b[1].dot(halfExtents), + abs_b[2].dot(halfExtents)); + extent += btVector3(getMargin(),getMargin(),getMargin()); + + aabbMin = center - extent; + aabbMax = center + extent; +} + + +/// This returns the "raw" (user's initial) height, not the actual height. +/// The actual height needs to be adjusted to be relative to the center +/// of the heightfield's AABB. +btScalar +btHeightfieldTerrainShape::getRawHeightFieldValue(int x,int y) const +{ + btScalar val = 0.f; + switch (m_heightDataType) + { + case PHY_FLOAT: + { + val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x]; + break; + } + + case PHY_UCHAR: + { + unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x]; + val = heightFieldValue * m_heightScale; + break; + } + + case PHY_SHORT: + { + short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x]; + val = hfValue * m_heightScale; + break; + } + + default: + { + btAssert(!"Bad m_heightDataType"); + } + } + + return val; +} + + + + +/// this returns the vertex in bullet-local coordinates +void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const +{ + btAssert(x>=0); + btAssert(y>=0); + btAssert(xstartX) + startX = quantizedAabbMin[1]; + if (quantizedAabbMax[1]startJ) + startJ = quantizedAabbMin[2]; + if (quantizedAabbMax[2]startX) + startX = quantizedAabbMin[0]; + if (quantizedAabbMax[0]startJ) + startJ = quantizedAabbMin[2]; + if (quantizedAabbMax[2]startX) + startX = quantizedAabbMin[0]; + if (quantizedAabbMax[0]startJ) + startJ = quantizedAabbMin[1]; + if (quantizedAabbMax[1]processTriangle(vertices,x,j); + //second triangle + getVertex(x,j,vertices[0]); + getVertex(x+1,j+1,vertices[1]); + getVertex(x,j+1,vertices[2]); + callback->processTriangle(vertices,x,j); + } else + { + //first triangle + getVertex(x,j,vertices[0]); + getVertex(x,j+1,vertices[1]); + getVertex(x+1,j,vertices[2]); + callback->processTriangle(vertices,x,j); + //second triangle + getVertex(x+1,j,vertices[0]); + getVertex(x,j+1,vertices[1]); + getVertex(x+1,j+1,vertices[2]); + callback->processTriangle(vertices,x,j); + } + } + } + + + +} + +void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const +{ + //moving concave objects not supported + + inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); +} + +void btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; +} +const btVector3& btHeightfieldTerrainShape::getLocalScaling() const +{ + return m_localScaling; +} diff --git a/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h new file mode 100644 index 0000000..78e231e --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h @@ -0,0 +1,161 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_HEIGHTFIELD_TERRAIN_SHAPE_H +#define BT_HEIGHTFIELD_TERRAIN_SHAPE_H + +#include "btConcaveShape.h" + +///btHeightfieldTerrainShape simulates a 2D heightfield terrain +/** + The caller is responsible for maintaining the heightfield array; this + class does not make a copy. + + The heightfield can be dynamic so long as the min/max height values + capture the extremes (heights must always be in that range). + + The local origin of the heightfield is assumed to be the exact + center (as determined by width and length and height, with each + axis multiplied by the localScaling). + + \b NOTE: be careful with coordinates. If you have a heightfield with a local + min height of -100m, and a max height of +500m, you may be tempted to place it + at the origin (0,0) and expect the heights in world coordinates to be + -100 to +500 meters. + Actually, the heights will be -300 to +300m, because bullet will re-center + the heightfield based on its AABB (which is determined by the min/max + heights). So keep in mind that once you create a btHeightfieldTerrainShape + object, the heights will be adjusted relative to the center of the AABB. This + is different to the behavior of many rendering engines, but is useful for + physics engines. + + Most (but not all) rendering and heightfield libraries assume upAxis = 1 + (that is, the y-axis is "up"). This class allows any of the 3 coordinates + to be "up". Make sure your choice of axis is consistent with your rendering + system. + + The heightfield heights are determined from the data type used for the + heightfieldData array. + + - PHY_UCHAR: height at a point is the uchar value at the + grid point, multipled by heightScale. uchar isn't recommended + because of its inability to deal with negative values, and + low resolution (8-bit). + + - PHY_SHORT: height at a point is the short int value at that grid + point, multipled by heightScale. + + - PHY_FLOAT: height at a point is the float value at that grid + point. heightScale is ignored when using the float heightfield + data type. + + Whatever the caller specifies as minHeight and maxHeight will be honored. + The class will not inspect the heightfield to discover the actual minimum + or maximum heights. These values are used to determine the heightfield's + axis-aligned bounding box, multiplied by localScaling. + + For usage and testing see the TerrainDemo. + */ +class btHeightfieldTerrainShape : public btConcaveShape +{ +protected: + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + btVector3 m_localOrigin; + + ///terrain data + int m_heightStickWidth; + int m_heightStickLength; + btScalar m_minHeight; + btScalar m_maxHeight; + btScalar m_width; + btScalar m_length; + btScalar m_heightScale; + union + { + const unsigned char* m_heightfieldDataUnsignedChar; + const short* m_heightfieldDataShort; + const btScalar* m_heightfieldDataFloat; + const void* m_heightfieldDataUnknown; + }; + + PHY_ScalarType m_heightDataType; + bool m_flipQuadEdges; + bool m_useDiamondSubdivision; + + int m_upAxis; + + btVector3 m_localScaling; + + virtual btScalar getRawHeightFieldValue(int x,int y) const; + void quantizeWithClamp(int* out, const btVector3& point,int isMax) const; + void getVertex(int x,int y,btVector3& vertex) const; + + + + /// protected initialization + /** + Handles the work of constructors so that public constructors can be + backwards-compatible without a lot of copy/paste. + */ + void initialize(int heightStickWidth, int heightStickLength, + const void* heightfieldData, btScalar heightScale, + btScalar minHeight, btScalar maxHeight, int upAxis, + PHY_ScalarType heightDataType, bool flipQuadEdges); + +public: + /// preferred constructor + /** + This constructor supports a range of heightfield + data types, and allows for a non-zero minimum height value. + heightScale is needed for any integer-based heightfield data types. + */ + btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength, + const void* heightfieldData, btScalar heightScale, + btScalar minHeight, btScalar maxHeight, + int upAxis, PHY_ScalarType heightDataType, + bool flipQuadEdges); + + /// legacy constructor + /** + The legacy constructor assumes the heightfield has a minimum height + of zero. Only unsigned char or floats are supported. For legacy + compatibility reasons, heightScale is calculated as maxHeight / 65535 + (and is only used when useFloatData = false). + */ + btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,const void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges); + + virtual ~btHeightfieldTerrainShape(); + + + void setUseDiamondSubdivision(bool useDiamondSubdivision=true) { m_useDiamondSubdivision = useDiamondSubdivision;} + + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual void setLocalScaling(const btVector3& scaling); + + virtual const btVector3& getLocalScaling() const; + + //debugging + virtual const char* getName()const {return "HEIGHTFIELD";} + +}; + +#endif //BT_HEIGHTFIELD_TERRAIN_SHAPE_H diff --git a/src/BulletCollision/CollisionShapes/btMaterial.h b/src/BulletCollision/CollisionShapes/btMaterial.h new file mode 100644 index 0000000..866f9b4 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btMaterial.h @@ -0,0 +1,35 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +/// This file was created by Alex Silverman + +#ifndef BT_MATERIAL_H +#define BT_MATERIAL_H + +// Material class to be used by btMultimaterialTriangleMeshShape to store triangle properties +class btMaterial +{ + // public members so that materials can change due to world events +public: + btScalar m_friction; + btScalar m_restitution; + int pad[2]; + + btMaterial(){} + btMaterial(btScalar fric, btScalar rest) { m_friction = fric; m_restitution = rest; } +}; + +#endif // BT_MATERIAL_H + diff --git a/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp b/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp new file mode 100644 index 0000000..06707e2 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp @@ -0,0 +1,60 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btMinkowskiSumShape.h" + + +btMinkowskiSumShape::btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB) +: btConvexInternalShape (), +m_shapeA(shapeA), +m_shapeB(shapeB) +{ + m_shapeType = MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE; + m_transA.setIdentity(); + m_transB.setIdentity(); +} + +btVector3 btMinkowskiSumShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(vec*m_transA.getBasis())); + btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(-vec*m_transB.getBasis())); + return supVertexA - supVertexB; +} + +void btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + ///@todo: could make recursive use of batching. probably this shape is not used frequently. + for (int i=0;igetMargin() + m_shapeB->getMargin(); +} + + +void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + (void)mass; + btAssert(0); + inertia.setValue(0,0,0); +} diff --git a/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h new file mode 100644 index 0000000..6c844e8 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h @@ -0,0 +1,60 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_MINKOWSKI_SUM_SHAPE_H +#define BT_MINKOWSKI_SUM_SHAPE_H + +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types + +/// The btMinkowskiSumShape is only for advanced users. This shape represents implicit based minkowski sum of two convex implicit shapes. +class btMinkowskiSumShape : public btConvexInternalShape +{ + + btTransform m_transA; + btTransform m_transB; + const btConvexShape* m_shapeA; + const btConvexShape* m_shapeB; + +public: + + btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB); + + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + void setTransformA(const btTransform& transA) { m_transA = transA;} + void setTransformB(const btTransform& transB) { m_transB = transB;} + + const btTransform& getTransformA()const { return m_transA;} + const btTransform& GetTransformB()const { return m_transB;} + + + virtual btScalar getMargin() const; + + const btConvexShape* getShapeA() const { return m_shapeA;} + const btConvexShape* getShapeB() const { return m_shapeB;} + + virtual const char* getName()const + { + return "MinkowskiSum"; + } +}; + +#endif //BT_MINKOWSKI_SUM_SHAPE_H diff --git a/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp new file mode 100644 index 0000000..c996bfc --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp @@ -0,0 +1,167 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btMultiSphereShape.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btSerializer.h" + +btMultiSphereShape::btMultiSphereShape (const btVector3* positions,const btScalar* radi,int numSpheres) +:btConvexInternalAabbCachingShape () +{ + m_shapeType = MULTI_SPHERE_SHAPE_PROXYTYPE; + //btScalar startMargin = btScalar(BT_LARGE_FLOAT); + + m_localPositionArray.resize(numSpheres); + m_radiArray.resize(numSpheres); + for (int i=0;i maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + + return supVec; + +} + + void btMultiSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + + for (int j=0;j maxDot) + { + maxDot = newDot; + supportVerticesOut[j] = vtx; + } + } + } +} + + + + + + + + +void btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + //as an approximation, take the inertia of the box that bounds the spheres + + btVector3 localAabbMin,localAabbMax; + getCachedLocalAabb(localAabbMin,localAabbMax); + btVector3 halfExtents = (localAabbMax-localAabbMin)*btScalar(0.5); + + btScalar lx=btScalar(2.)*(halfExtents.x()); + btScalar ly=btScalar(2.)*(halfExtents.y()); + btScalar lz=btScalar(2.)*(halfExtents.z()); + + inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + ly*ly)); + +} + + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btMultiSphereShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btMultiSphereShapeData* shapeData = (btMultiSphereShapeData*) dataBuffer; + btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer); + + int numElem = m_localPositionArray.size(); + shapeData->m_localPositionArrayPtr = numElem ? (btPositionAndRadius*)serializer->getUniquePointer((void*)&m_localPositionArray[0]): 0; + + shapeData->m_localPositionArraySize = numElem; + if (numElem) + { + btChunk* chunk = serializer->allocate(sizeof(btPositionAndRadius),numElem); + btPositionAndRadius* memPtr = (btPositionAndRadius*)chunk->m_oldPtr; + for (int i=0;im_pos); + memPtr->m_radius = float(m_radiArray[i]); + } + serializer->finalizeChunk(chunk,"btPositionAndRadius",BT_ARRAY_CODE,(void*)&m_localPositionArray[0]); + } + + return "btMultiSphereShapeData"; +} + + diff --git a/src/BulletCollision/CollisionShapes/btMultiSphereShape.h b/src/BulletCollision/CollisionShapes/btMultiSphereShape.h new file mode 100644 index 0000000..06c5d16 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btMultiSphereShape.h @@ -0,0 +1,99 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_MULTI_SPHERE_MINKOWSKI_H +#define BT_MULTI_SPHERE_MINKOWSKI_H + +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAabbUtil2.h" + + + +///The btMultiSphereShape represents the convex hull of a collection of spheres. You can create special capsules or other smooth volumes. +///It is possible to animate the spheres for deformation, but call 'recalcLocalAabb' after changing any sphere position/radius +class btMultiSphereShape : public btConvexInternalAabbCachingShape +{ + + btAlignedObjectArray m_localPositionArray; + btAlignedObjectArray m_radiArray; + +public: + btMultiSphereShape (const btVector3* positions,const btScalar* radi,int numSpheres); + + ///CollisionShape Interface + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + /// btConvexShape Interface + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + int getSphereCount() const + { + return m_localPositionArray.size(); + } + + const btVector3& getSpherePosition(int index) const + { + return m_localPositionArray[index]; + } + + btScalar getSphereRadius(int index) const + { + return m_radiArray[index]; + } + + + virtual const char* getName()const + { + return "MultiSphere"; + } + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + + +struct btPositionAndRadius +{ + btVector3FloatData m_pos; + float m_radius; +}; + +struct btMultiSphereShapeData +{ + btConvexInternalShapeData m_convexInternalShapeData; + + btPositionAndRadius *m_localPositionArrayPtr; + int m_localPositionArraySize; + char m_padding[4]; +}; + + + +SIMD_FORCE_INLINE int btMultiSphereShape::calculateSerializeBufferSize() const +{ + return sizeof(btMultiSphereShapeData); +} + + + +#endif //BT_MULTI_SPHERE_MINKOWSKI_H diff --git a/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp b/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp new file mode 100644 index 0000000..58799ac --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp @@ -0,0 +1,45 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +/// This file was created by Alex Silverman + +#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h" +//#include "BulletCollision/CollisionShapes/btOptimizedBvh.h" + + +///Obtains the material for a specific triangle +const btMaterial * btMultimaterialTriangleMeshShape::getMaterialProperties(int partID, int triIndex) +{ + const unsigned char * materialBase = 0; + int numMaterials; + PHY_ScalarType materialType; + int materialStride; + const unsigned char * triangleMaterialBase = 0; + int numTriangles; + int triangleMaterialStride; + PHY_ScalarType triangleType; + + ((btTriangleIndexVertexMaterialArray*)m_meshInterface)->getLockedReadOnlyMaterialBase(&materialBase, numMaterials, materialType, materialStride, + &triangleMaterialBase, numTriangles, triangleMaterialStride, triangleType, partID); + + // return the pointer to the place with the friction for the triangle + // TODO: This depends on whether it's a moving mesh or not + // BUG IN GIMPACT + //return (btScalar*)(&materialBase[triangleMaterialBase[(triIndex-1) * triangleMaterialStride] * materialStride]); + int * matInd = (int *)(&(triangleMaterialBase[(triIndex * triangleMaterialStride)])); + btMaterial *matVal = (btMaterial *)(&(materialBase[*matInd * materialStride])); + return (matVal); +} diff --git a/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h b/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h new file mode 100644 index 0000000..2b92ab7 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h @@ -0,0 +1,120 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +/// This file was created by Alex Silverman + +#ifndef BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H +#define BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H + +#include "btBvhTriangleMeshShape.h" +#include "btMaterial.h" + +///The BvhTriangleMaterialMeshShape extends the btBvhTriangleMeshShape. Its main contribution is the interface into a material array, which allows per-triangle friction and restitution. +ATTRIBUTE_ALIGNED16(class) btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape +{ + btAlignedObjectArray m_materialList; + int ** m_triangleMaterials; + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true): + btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh) + { + m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE; + + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16)); + + for(int i = 0; i < meshInterface->getNumSubParts(); i++) + { + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + i); + //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces, 16)); + } + } + + ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb + btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true): + btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh) + { + m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE; + + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16)); + + for(int i = 0; i < meshInterface->getNumSubParts(); i++) + { + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + i); + //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces * 2, 16)); + } + } + + virtual ~btMultimaterialTriangleMeshShape() + { +/* + for(int i = 0; i < m_meshInterface->getNumSubParts(); i++) + { + btAlignedFree(m_materialValues[i]); + m_materialLookup[i] = NULL; + } + btAlignedFree(m_materialValues); + m_materialLookup = NULL; +*/ + } + //debugging + virtual const char* getName()const {return "MULTIMATERIALTRIANGLEMESH";} + + ///Obtains the material for a specific triangle + const btMaterial * getMaterialProperties(int partID, int triIndex); + +} +; + +#endif //BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H diff --git a/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp new file mode 100644 index 0000000..6f36775 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp @@ -0,0 +1,391 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btOptimizedBvh.h" +#include "btStridingMeshInterface.h" +#include "LinearMath/btAabbUtil2.h" +#include "LinearMath/btIDebugDraw.h" + + +btOptimizedBvh::btOptimizedBvh() +{ +} + +btOptimizedBvh::~btOptimizedBvh() +{ +} + + +void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax) +{ + m_useQuantization = useQuantizedAabbCompression; + + + // NodeArray triangleNodes; + + struct NodeTriangleCallback : public btInternalTriangleIndexCallback + { + + NodeArray& m_triangleNodes; + + NodeTriangleCallback& operator=(NodeTriangleCallback& other) + { + m_triangleNodes.copyFromArray(other.m_triangleNodes); + return *this; + } + + NodeTriangleCallback(NodeArray& triangleNodes) + :m_triangleNodes(triangleNodes) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + btOptimizedBvhNode node; + btVector3 aabbMin,aabbMax; + aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + aabbMin.setMin(triangle[0]); + aabbMax.setMax(triangle[0]); + aabbMin.setMin(triangle[1]); + aabbMax.setMax(triangle[1]); + aabbMin.setMin(triangle[2]); + aabbMax.setMax(triangle[2]); + + //with quantization? + node.m_aabbMinOrg = aabbMin; + node.m_aabbMaxOrg = aabbMax; + + node.m_escapeIndex = -1; + + //for child nodes + node.m_subPart = partId; + node.m_triangleIndex = triangleIndex; + m_triangleNodes.push_back(node); + } + }; + struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback + { + QuantizedNodeArray& m_triangleNodes; + const btQuantizedBvh* m_optimizedTree; // for quantization + + QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other) + { + m_triangleNodes.copyFromArray(other.m_triangleNodes); + m_optimizedTree = other.m_optimizedTree; + return *this; + } + + QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btQuantizedBvh* tree) + :m_triangleNodes(triangleNodes),m_optimizedTree(tree) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + // The partId and triangle index must fit in the same (positive) integer + btAssert(partId < (1<=0); + + btQuantizedBvhNode node; + btVector3 aabbMin,aabbMax; + aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + aabbMin.setMin(triangle[0]); + aabbMax.setMax(triangle[0]); + aabbMin.setMin(triangle[1]); + aabbMax.setMax(triangle[1]); + aabbMin.setMin(triangle[2]); + aabbMax.setMax(triangle[2]); + + //PCK: add these checks for zero dimensions of aabb + const btScalar MIN_AABB_DIMENSION = btScalar(0.002); + const btScalar MIN_AABB_HALF_DIMENSION = btScalar(0.001); + if (aabbMax.x() - aabbMin.x() < MIN_AABB_DIMENSION) + { + aabbMax.setX(aabbMax.x() + MIN_AABB_HALF_DIMENSION); + aabbMin.setX(aabbMin.x() - MIN_AABB_HALF_DIMENSION); + } + if (aabbMax.y() - aabbMin.y() < MIN_AABB_DIMENSION) + { + aabbMax.setY(aabbMax.y() + MIN_AABB_HALF_DIMENSION); + aabbMin.setY(aabbMin.y() - MIN_AABB_HALF_DIMENSION); + } + if (aabbMax.z() - aabbMin.z() < MIN_AABB_DIMENSION) + { + aabbMax.setZ(aabbMax.z() + MIN_AABB_HALF_DIMENSION); + aabbMin.setZ(aabbMin.z() - MIN_AABB_HALF_DIMENSION); + } + + m_optimizedTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0); + m_optimizedTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1); + + node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex; + + m_triangleNodes.push_back(node); + } + }; + + + + int numLeafNodes = 0; + + + if (m_useQuantization) + { + + //initialize quantization values + setQuantizationValues(bvhAabbMin,bvhAabbMax); + + QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes,this); + + + triangles->InternalProcessAllTriangles(&callback,m_bvhAabbMin,m_bvhAabbMax); + + //now we have an array of leafnodes in m_leafNodes + numLeafNodes = m_quantizedLeafNodes.size(); + + + m_quantizedContiguousNodes.resize(2*numLeafNodes); + + + } else + { + NodeTriangleCallback callback(m_leafNodes); + + btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + + triangles->InternalProcessAllTriangles(&callback,aabbMin,aabbMax); + + //now we have an array of leafnodes in m_leafNodes + numLeafNodes = m_leafNodes.size(); + + m_contiguousNodes.resize(2*numLeafNodes); + } + + m_curNodeIndex = 0; + + buildTree(0,numLeafNodes); + + ///if the entire tree is small then subtree size, we need to create a header info for the tree + if(m_useQuantization && !m_SubtreeHeaders.size()) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]); + subtree.m_rootNodeIndex = 0; + subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex(); + } + + //PCK: update the copy of the size + m_subtreeHeaderCount = m_SubtreeHeaders.size(); + + //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary + m_quantizedLeafNodes.clear(); + m_leafNodes.clear(); +} + + + + +void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax) +{ + if (m_useQuantization) + { + + setQuantizationValues(aabbMin,aabbMax); + + updateBvhNodes(meshInterface,0,m_curNodeIndex,0); + + ///now update all subtree headers + + int i; + for (i=0;i m_bvhAabbMin.getX()); + btAssert(aabbMin.getY() > m_bvhAabbMin.getY()); + btAssert(aabbMin.getZ() > m_bvhAabbMin.getZ()); + + btAssert(aabbMax.getX() < m_bvhAabbMax.getX()); + btAssert(aabbMax.getY() < m_bvhAabbMax.getY()); + btAssert(aabbMax.getZ() < m_bvhAabbMax.getZ()); + + ///we should update all quantization values, using updateBvhNodes(meshInterface); + ///but we only update chunks that overlap the given aabb + + unsigned short quantizedQueryAabbMin[3]; + unsigned short quantizedQueryAabbMax[3]; + + quantize(&quantizedQueryAabbMin[0],aabbMin,0); + quantize(&quantizedQueryAabbMax[0],aabbMax,1); + + int i; + for (i=0;im_SubtreeHeaders.size();i++) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; + + //PCK: unsigned instead of bool + unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); + if (overlap != 0) + { + updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i); + + subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]); + } + } + +} + +void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index) +{ + (void)index; + + btAssert(m_useQuantization); + + int curNodeSubPart=-1; + + //get access info to trianglemesh data + const unsigned char *vertexbase = 0; + int numverts = 0; + PHY_ScalarType type = PHY_INTEGER; + int stride = 0; + const unsigned char *indexbase = 0; + int indexstride = 0; + int numfaces = 0; + PHY_ScalarType indicestype = PHY_INTEGER; + + btVector3 triangleVerts[3]; + btVector3 aabbMin,aabbMax; + const btVector3& meshScaling = meshInterface->getScaling(); + + int i; + for (i=endNode-1;i>=firstNode;i--) + { + + + btQuantizedBvhNode& curNode = m_quantizedContiguousNodes[i]; + if (curNode.isLeafNode()) + { + //recalc aabb from triangle data + int nodeSubPart = curNode.getPartId(); + int nodeTriangleIndex = curNode.getTriangleIndex(); + if (nodeSubPart != curNodeSubPart) + { + if (curNodeSubPart >= 0) + meshInterface->unLockReadOnlyVertexBase(curNodeSubPart); + meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart); + + curNodeSubPart = nodeSubPart; + btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); + } + //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts, + + unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); + + + for (int j=2;j>=0;j--) + { + + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + if (type == PHY_FLOAT) + { + float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); + triangleVerts[j] = btVector3( + graphicsbase[0]*meshScaling.getX(), + graphicsbase[1]*meshScaling.getY(), + graphicsbase[2]*meshScaling.getZ()); + } + else + { + double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); + triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*meshScaling.getX()), btScalar(graphicsbase[1]*meshScaling.getY()), btScalar(graphicsbase[2]*meshScaling.getZ())); + } + } + + + + aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + aabbMin.setMin(triangleVerts[0]); + aabbMax.setMax(triangleVerts[0]); + aabbMin.setMin(triangleVerts[1]); + aabbMax.setMax(triangleVerts[1]); + aabbMin.setMin(triangleVerts[2]); + aabbMax.setMax(triangleVerts[2]); + + quantize(&curNode.m_quantizedAabbMin[0],aabbMin,0); + quantize(&curNode.m_quantizedAabbMax[0],aabbMax,1); + + } else + { + //combine aabb from both children + + btQuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i+1]; + + btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i+2] : + &m_quantizedContiguousNodes[i+1+leftChildNode->getEscapeIndex()]; + + + { + for (int i=0;i<3;i++) + { + curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i]; + if (curNode.m_quantizedAabbMin[i]>rightChildNode->m_quantizedAabbMin[i]) + curNode.m_quantizedAabbMin[i]=rightChildNode->m_quantizedAabbMin[i]; + + curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i]; + if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i]) + curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i]; + } + } + } + + } + + if (curNodeSubPart >= 0) + meshInterface->unLockReadOnlyVertexBase(curNodeSubPart); + + +} + +///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' +btOptimizedBvh* btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian) +{ + btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer,i_dataBufferSize,i_swapEndian); + + //we don't add additional data so just do a static upcast + return static_cast(bvh); +} diff --git a/src/BulletCollision/CollisionShapes/btOptimizedBvh.h b/src/BulletCollision/CollisionShapes/btOptimizedBvh.h new file mode 100644 index 0000000..715961f --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btOptimizedBvh.h @@ -0,0 +1,65 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +///Contains contributions from Disney Studio's + +#ifndef BT_OPTIMIZED_BVH_H +#define BT_OPTIMIZED_BVH_H + +#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h" + +class btStridingMeshInterface; + + +///The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes, through the btStridingMeshInterface. +ATTRIBUTE_ALIGNED16(class) btOptimizedBvh : public btQuantizedBvh +{ + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + +protected: + +public: + + btOptimizedBvh(); + + virtual ~btOptimizedBvh(); + + void build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax); + + void refit(btStridingMeshInterface* triangles,const btVector3& aabbMin,const btVector3& aabbMax); + + void refitPartial(btStridingMeshInterface* triangles,const btVector3& aabbMin, const btVector3& aabbMax); + + void updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index); + + /// Data buffer MUST be 16 byte aligned + virtual bool serializeInPlace(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const + { + return btQuantizedBvh::serialize(o_alignedDataBuffer,i_dataBufferSize,i_swapEndian); + + } + + ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' + static btOptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian); + + +}; + + +#endif //BT_OPTIMIZED_BVH_H + + diff --git a/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp new file mode 100644 index 0000000..82def79 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp @@ -0,0 +1,475 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" +#include "btConvexPolyhedron.h" +#include "LinearMath/btConvexHullComputer.h" +#include +#include "LinearMath/btGeometryUtil.h" +#include "LinearMath/btGrahamScan2dConvexHull.h" + + +btPolyhedralConvexShape::btPolyhedralConvexShape() :btConvexInternalShape(), +m_polyhedron(0) +{ + +} + +btPolyhedralConvexShape::~btPolyhedralConvexShape() +{ + if (m_polyhedron) + { + btAlignedFree(m_polyhedron); + } +} + + +bool btPolyhedralConvexShape::initializePolyhedralFeatures() +{ + + if (m_polyhedron) + btAlignedFree(m_polyhedron); + + void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron),16); + m_polyhedron = new (mem) btConvexPolyhedron; + + btAlignedObjectArray orgVertices; + + for (int i=0;i planeEquations; + btGeometryUtil::getPlaneEquationsFromVertices(orgVertices,planeEquations); + + btAlignedObjectArray shiftedPlaneEquations; + for (int p=0;p tmpVertices; + + btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,tmpVertices); + btConvexHullComputer conv; + conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f); + +#else + btConvexHullComputer conv; + conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f); + +#endif + + + + btAlignedObjectArray faceNormals; + int numFaces = conv.faces.size(); + faceNormals.resize(numFaces); + btConvexHullComputer* convexUtil = &conv; + + + btAlignedObjectArray tmpFaces; + tmpFaces.resize(numFaces); + + int numVertices = convexUtil->vertices.size(); + m_polyhedron->m_vertices.resize(numVertices); + for (int p=0;pm_vertices[p] = convexUtil->vertices[p]; + } + + + for (int i=0;ifaces[i]; + //printf("face=%d\n",face); + const btConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face]; + const btConvexHullComputer::Edge* edge = firstEdge; + + btVector3 edges[3]; + int numEdges = 0; + //compute face normals + + btScalar maxCross2 = 0.f; + int chosenEdge = -1; + + do + { + + int src = edge->getSourceVertex(); + tmpFaces[i].m_indices.push_back(src); + int targ = edge->getTargetVertex(); + btVector3 wa = convexUtil->vertices[src]; + + btVector3 wb = convexUtil->vertices[targ]; + btVector3 newEdge = wb-wa; + newEdge.normalize(); + if (numEdges<2) + edges[numEdges++] = newEdge; + + edge = edge->getNextEdgeOfFace(); + } while (edge!=firstEdge); + + btScalar planeEq = 1e30f; + + + if (numEdges==2) + { + faceNormals[i] = edges[0].cross(edges[1]); + faceNormals[i].normalize(); + tmpFaces[i].m_plane[0] = faceNormals[i].getX(); + tmpFaces[i].m_plane[1] = faceNormals[i].getY(); + tmpFaces[i].m_plane[2] = faceNormals[i].getZ(); + tmpFaces[i].m_plane[3] = planeEq; + + } + else + { + btAssert(0);//degenerate? + faceNormals[i].setZero(); + } + + for (int v=0;vm_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]); + if (planeEq>eq) + { + planeEq=eq; + } + } + tmpFaces[i].m_plane[3] = -planeEq; + } + + //merge coplanar faces and copy them to m_polyhedron + + btScalar faceWeldThreshold= 0.999f; + btAlignedObjectArray todoFaces; + for (int i=0;i coplanarFaceGroup; + int refFace = todoFaces[todoFaces.size()-1]; + + coplanarFaceGroup.push_back(refFace); + btFace& faceA = tmpFaces[refFace]; + todoFaces.pop_back(); + + btVector3 faceNormalA(faceA.m_plane[0],faceA.m_plane[1],faceA.m_plane[2]); + for (int j=todoFaces.size()-1;j>=0;j--) + { + int i = todoFaces[j]; + btFace& faceB = tmpFaces[i]; + btVector3 faceNormalB(faceB.m_plane[0],faceB.m_plane[1],faceB.m_plane[2]); + if (faceNormalA.dot(faceNormalB)>faceWeldThreshold) + { + coplanarFaceGroup.push_back(i); + todoFaces.remove(i); + } + } + + + bool did_merge = false; + if (coplanarFaceGroup.size()>1) + { + //do the merge: use Graham Scan 2d convex hull + + btAlignedObjectArray orgpoints; + + for (int i=0;im_faces.push_back(tmpFaces[coplanarFaceGroup[i]]); + + btFace& face = tmpFaces[coplanarFaceGroup[i]]; + btVector3 faceNormal(face.m_plane[0],face.m_plane[1],face.m_plane[2]); + btVector3 xyPlaneNormal(0,0,1); + + btQuaternion rotationArc = shortestArcQuat(faceNormal,xyPlaneNormal); + + for (int f=0;fm_vertices[orgIndex]; + btVector3 rotatedPt = quatRotate(rotationArc,pt); + rotatedPt.setZ(0); + bool found = false; + + for (int i=0;i hull; + GrahamScanConvexHull2D(orgpoints,hull); + + for (int i=0;im_faces.push_back(combinedFace); + } + } + if(!did_merge) + { + for (int i=0;im_faces.push_back(tmpFaces[coplanarFaceGroup[i]]); + } + + } + + + + } + + m_polyhedron->initialize(); + + return true; +} + + +btVector3 btPolyhedralConvexShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const +{ + + + btVector3 supVec(0,0,0); +#ifndef __SPU__ + int i; + btScalar maxDot(btScalar(-BT_LARGE_FLOAT)); + + btVector3 vec = vec0; + btScalar lenSqr = vec.length2(); + if (lenSqr < btScalar(0.0001)) + { + vec.setValue(1,0,0); + } else + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + vec *= rlen; + } + + btVector3 vtx; + btScalar newDot; + + for (i=0;i maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + + +#endif //__SPU__ + return supVec; +} + + + +void btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ +#ifndef __SPU__ + int i; + + btVector3 vtx; + btScalar newDot; + + for (i=0;i supportVerticesOut[j][3]) + { + //WARNING: don't swap next lines, the w component would get overwritten! + supportVerticesOut[j] = vtx; + supportVerticesOut[j][3] = newDot; + } + } + } +#endif //__SPU__ +} + + + +void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ +#ifndef __SPU__ + //not yet, return box inertia + + btScalar margin = getMargin(); + + btTransform ident; + ident.setIdentity(); + btVector3 aabbMin,aabbMax; + getAabb(ident,aabbMin,aabbMax); + btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5); + + btScalar lx=btScalar(2.)*(halfExtents.x()+margin); + btScalar ly=btScalar(2.)*(halfExtents.y()+margin); + btScalar lz=btScalar(2.)*(halfExtents.z()+margin); + const btScalar x2 = lx*lx; + const btScalar y2 = ly*ly; + const btScalar z2 = lz*lz; + const btScalar scaledmass = mass * btScalar(0.08333333); + + inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2)); +#endif //__SPU__ +} + + + +void btPolyhedralConvexAabbCachingShape::setLocalScaling(const btVector3& scaling) +{ + btConvexInternalShape::setLocalScaling(scaling); + recalcLocalAabb(); +} + +btPolyhedralConvexAabbCachingShape::btPolyhedralConvexAabbCachingShape() +:btPolyhedralConvexShape(), +m_localAabbMin(1,1,1), +m_localAabbMax(-1,-1,-1), +m_isLocalAabbValid(false) +{ +} + +void btPolyhedralConvexAabbCachingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + getNonvirtualAabb(trans,aabbMin,aabbMax,getMargin()); +} + +void btPolyhedralConvexAabbCachingShape::recalcLocalAabb() +{ + m_isLocalAabbValid = true; + + #if 1 + static const btVector3 _directions[] = + { + btVector3( 1., 0., 0.), + btVector3( 0., 1., 0.), + btVector3( 0., 0., 1.), + btVector3( -1., 0., 0.), + btVector3( 0., -1., 0.), + btVector3( 0., 0., -1.) + }; + + btVector3 _supporting[] = + { + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.) + }; + + batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6); + + for ( int i = 0; i < 3; ++i ) + { + m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin; + m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin; + } + + #else + + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + btVector3 tmp = localGetSupportingVertex(vec); + m_localAabbMax[i] = tmp[i]; + vec[i] = btScalar(-1.); + tmp = localGetSupportingVertex(vec); + m_localAabbMin[i] = tmp[i]; + } + #endif +} + + + + diff --git a/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h new file mode 100644 index 0000000..ee2e1e2 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h @@ -0,0 +1,112 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_POLYHEDRAL_CONVEX_SHAPE_H +#define BT_POLYHEDRAL_CONVEX_SHAPE_H + +#include "LinearMath/btMatrix3x3.h" +#include "btConvexInternalShape.h" +class btConvexPolyhedron; + + +///The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes. +class btPolyhedralConvexShape : public btConvexInternalShape +{ + + +protected: + + btConvexPolyhedron* m_polyhedron; + +public: + + btPolyhedralConvexShape(); + + virtual ~btPolyhedralConvexShape(); + + ///optional method mainly used to generate multiple contact points by clipping polyhedral features (faces/edges) + virtual bool initializePolyhedralFeatures(); + + const btConvexPolyhedron* getConvexPolyhedron() const + { + return m_polyhedron; + } + + //brute force implementations + + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + + virtual int getNumVertices() const = 0 ; + virtual int getNumEdges() const = 0; + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const = 0; + virtual void getVertex(int i,btVector3& vtx) const = 0; + virtual int getNumPlanes() const = 0; + virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const = 0; +// virtual int getIndex(int i) const = 0 ; + + virtual bool isInside(const btVector3& pt,btScalar tolerance) const = 0; + +}; + + +///The btPolyhedralConvexAabbCachingShape adds aabb caching to the btPolyhedralConvexShape +class btPolyhedralConvexAabbCachingShape : public btPolyhedralConvexShape +{ + + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + bool m_isLocalAabbValid; + +protected: + + void setCachedLocalAabb (const btVector3& aabbMin, const btVector3& aabbMax) + { + m_isLocalAabbValid = true; + m_localAabbMin = aabbMin; + m_localAabbMax = aabbMax; + } + + inline void getCachedLocalAabb (btVector3& aabbMin, btVector3& aabbMax) const + { + btAssert(m_isLocalAabbValid); + aabbMin = m_localAabbMin; + aabbMax = m_localAabbMax; + } + +public: + + btPolyhedralConvexAabbCachingShape(); + + inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const + { + + //lazy evaluation of local aabb + btAssert(m_isLocalAabbValid); + btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax); + } + + virtual void setLocalScaling(const btVector3& scaling); + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + void recalcLocalAabb(); + +}; + +#endif //BT_POLYHEDRAL_CONVEX_SHAPE_H diff --git a/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp b/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp new file mode 100644 index 0000000..25d58d6 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp @@ -0,0 +1,123 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btScaledBvhTriangleMeshShape.h" + +btScaledBvhTriangleMeshShape::btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling) +:m_localScaling(localScaling),m_bvhTriMeshShape(childShape) +{ + m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE; +} + +btScaledBvhTriangleMeshShape::~btScaledBvhTriangleMeshShape() +{ +} + + +class btScaledTriangleCallback : public btTriangleCallback +{ + btTriangleCallback* m_originalCallback; + + btVector3 m_localScaling; + +public: + + btScaledTriangleCallback(btTriangleCallback* originalCallback,const btVector3& localScaling) + :m_originalCallback(originalCallback), + m_localScaling(localScaling) + { + } + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + btVector3 newTriangle[3]; + newTriangle[0] = triangle[0]*m_localScaling; + newTriangle[1] = triangle[1]*m_localScaling; + newTriangle[2] = triangle[2]*m_localScaling; + m_originalCallback->processTriangle(&newTriangle[0],partId,triangleIndex); + } +}; + +void btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + btScaledTriangleCallback scaledCallback(callback,m_localScaling); + + btVector3 invLocalScaling(1.f/m_localScaling.getX(),1.f/m_localScaling.getY(),1.f/m_localScaling.getZ()); + btVector3 scaledAabbMin,scaledAabbMax; + + ///support negative scaling + scaledAabbMin[0] = m_localScaling.getX() >= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0]; + scaledAabbMin[1] = m_localScaling.getY() >= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1]; + scaledAabbMin[2] = m_localScaling.getZ() >= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2]; + scaledAabbMin[3] = 0.f; + + scaledAabbMax[0] = m_localScaling.getX() <= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0]; + scaledAabbMax[1] = m_localScaling.getY() <= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1]; + scaledAabbMax[2] = m_localScaling.getZ() <= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2]; + scaledAabbMax[3] = 0.f; + + + m_bvhTriMeshShape->processAllTriangles(&scaledCallback,scaledAabbMin,scaledAabbMax); +} + + +void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + btVector3 localAabbMin = m_bvhTriMeshShape->getLocalAabbMin(); + btVector3 localAabbMax = m_bvhTriMeshShape->getLocalAabbMax(); + + btVector3 tmpLocalAabbMin = localAabbMin * m_localScaling; + btVector3 tmpLocalAabbMax = localAabbMax * m_localScaling; + + localAabbMin[0] = (m_localScaling.getX() >= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0]; + localAabbMin[1] = (m_localScaling.getY() >= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1]; + localAabbMin[2] = (m_localScaling.getZ() >= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2]; + localAabbMax[0] = (m_localScaling.getX() <= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0]; + localAabbMax[1] = (m_localScaling.getY() <= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1]; + localAabbMax[2] = (m_localScaling.getZ() <= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2]; + + btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin); + btScalar margin = m_bvhTriMeshShape->getMargin(); + localHalfExtents += btVector3(margin,margin,margin); + btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin); + + btMatrix3x3 abs_b = trans.getBasis().absolute(); + + btVector3 center = trans(localCenter); + + btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + aabbMin = center - extent; + aabbMax = center + extent; + +} + +void btScaledBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; +} + +const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const +{ + return m_localScaling; +} + +void btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + ///don't make this a movable object! +// btAssert(0); +} diff --git a/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h b/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h new file mode 100644 index 0000000..ff86ef3 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h @@ -0,0 +1,93 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H +#define BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H + +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" + + +///The btScaledBvhTriangleMeshShape allows to instance a scaled version of an existing btBvhTriangleMeshShape. +///Note that each btBvhTriangleMeshShape still can have its own local scaling, independent from this btScaledBvhTriangleMeshShape 'localScaling' +ATTRIBUTE_ALIGNED16(class) btScaledBvhTriangleMeshShape : public btConcaveShape +{ + + + btVector3 m_localScaling; + + btBvhTriangleMeshShape* m_bvhTriMeshShape; + +public: + + + btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling); + + virtual ~btScaledBvhTriangleMeshShape(); + + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + btBvhTriangleMeshShape* getChildShape() + { + return m_bvhTriMeshShape; + } + + const btBvhTriangleMeshShape* getChildShape() const + { + return m_bvhTriMeshShape; + } + + //debugging + virtual const char* getName()const {return "SCALEDBVHTRIANGLEMESH";} + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btScaledTriangleMeshShapeData +{ + btTriangleMeshShapeData m_trimeshShapeData; + + btVector3FloatData m_localScaling; +}; + + +SIMD_FORCE_INLINE int btScaledBvhTriangleMeshShape::calculateSerializeBufferSize() const +{ + return sizeof(btScaledTriangleMeshShapeData); +} + + +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btScaledBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btScaledTriangleMeshShapeData* scaledMeshData = (btScaledTriangleMeshShapeData*) dataBuffer; + m_bvhTriMeshShape->serialize(&scaledMeshData->m_trimeshShapeData,serializer); + scaledMeshData->m_trimeshShapeData.m_collisionShapeData.m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE; + m_localScaling.serializeFloat(scaledMeshData->m_localScaling); + return "btScaledTriangleMeshShapeData"; +} + + +#endif //BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H diff --git a/src/BulletCollision/CollisionShapes/btShapeHull.cpp b/src/BulletCollision/CollisionShapes/btShapeHull.cpp new file mode 100644 index 0000000..3beaf86 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btShapeHull.cpp @@ -0,0 +1,170 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +//btShapeHull was implemented by John McCutchan. + + +#include "btShapeHull.h" +#include "LinearMath/btConvexHull.h" + +#define NUM_UNITSPHERE_POINTS 42 + +btShapeHull::btShapeHull (const btConvexShape* shape) +{ + m_shape = shape; + m_vertices.clear (); + m_indices.clear(); + m_numIndices = 0; +} + +btShapeHull::~btShapeHull () +{ + m_indices.clear(); + m_vertices.clear (); +} + +bool +btShapeHull::buildHull (btScalar /*margin*/) +{ + int numSampleDirections = NUM_UNITSPHERE_POINTS; + { + int numPDA = m_shape->getNumPreferredPenetrationDirections(); + if (numPDA) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + getUnitSpherePoints()[numSampleDirections] = norm; + numSampleDirections++; + } + } + } + + btVector3 supportPoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + int i; + for (i = 0; i < numSampleDirections; i++) + { + supportPoints[i] = m_shape->localGetSupportingVertex(getUnitSpherePoints()[i]); + } + + HullDesc hd; + hd.mFlags = QF_TRIANGLES; + hd.mVcount = static_cast(numSampleDirections); + +#ifdef BT_USE_DOUBLE_PRECISION + hd.mVertices = &supportPoints[0]; + hd.mVertexStride = sizeof(btVector3); +#else + hd.mVertices = &supportPoints[0]; + hd.mVertexStride = sizeof (btVector3); +#endif + + HullLibrary hl; + HullResult hr; + if (hl.CreateConvexHull (hd, hr) == QE_FAIL) + { + return false; + } + + m_vertices.resize (static_cast(hr.mNumOutputVertices)); + + + for (i = 0; i < static_cast(hr.mNumOutputVertices); i++) + { + m_vertices[i] = hr.m_OutputVertices[i]; + } + m_numIndices = hr.mNumIndices; + m_indices.resize(static_cast(m_numIndices)); + for (i = 0; i < static_cast(m_numIndices); i++) + { + m_indices[i] = hr.m_Indices[i]; + } + + // free temporary hull result that we just copied + hl.ReleaseResult (hr); + + return true; +} + +int +btShapeHull::numTriangles () const +{ + return static_cast(m_numIndices / 3); +} + +int +btShapeHull::numVertices () const +{ + return m_vertices.size (); +} + +int +btShapeHull::numIndices () const +{ + return static_cast(m_numIndices); +} + + +btVector3* btShapeHull::getUnitSpherePoints() +{ + static btVector3 sUnitSpherePoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = + { + btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)), + btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)), + btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)), + btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)), + btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)), + btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)), + btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)), + btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)), + btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)), + btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)), + btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)), + btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)), + btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)), + btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)), + btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)), + btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)), + btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)), + btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)), + btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)), + btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)), + btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)), + btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)), + btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)), + btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)), + btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)), + btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)), + btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)), + btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)), + btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)), + btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)), + btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)), + btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)), + btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)), + btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)), + btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)), + btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)), + btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)), + btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)), + btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)), + btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)), + btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)), + btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654)) + }; + return sUnitSpherePoints; +} + diff --git a/src/BulletCollision/CollisionShapes/btShapeHull.h b/src/BulletCollision/CollisionShapes/btShapeHull.h new file mode 100644 index 0000000..642a288 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btShapeHull.h @@ -0,0 +1,59 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +///btShapeHull implemented by John McCutchan. + +#ifndef BT_SHAPE_HULL_H +#define BT_SHAPE_HULL_H + +#include "LinearMath/btAlignedObjectArray.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" + + +///The btShapeHull class takes a btConvexShape, builds a simplified convex hull using btConvexHull and provides triangle indices and vertices. +///It can be useful for to simplify a complex convex object and for visualization of a non-polyhedral convex object. +///It approximates the convex hull using the supporting vertex of 42 directions. +class btShapeHull +{ +protected: + + btAlignedObjectArray m_vertices; + btAlignedObjectArray m_indices; + unsigned int m_numIndices; + const btConvexShape* m_shape; + + static btVector3* getUnitSpherePoints(); + +public: + btShapeHull (const btConvexShape* shape); + ~btShapeHull (); + + bool buildHull (btScalar margin); + + int numTriangles () const; + int numVertices () const; + int numIndices () const; + + const btVector3* getVertexPointer() const + { + return &m_vertices[0]; + } + const unsigned int* getIndexPointer() const + { + return &m_indices[0]; + } +}; + +#endif //BT_SHAPE_HULL_H diff --git a/src/BulletCollision/CollisionShapes/btSphereShape.cpp b/src/BulletCollision/CollisionShapes/btSphereShape.cpp new file mode 100644 index 0000000..b9a736c --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btSphereShape.cpp @@ -0,0 +1,71 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btSphereShape.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + +#include "LinearMath/btQuaternion.h" + +btVector3 btSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + (void)vec; + return btVector3(btScalar(0.),btScalar(0.),btScalar(0.)); +} + +void btSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + (void)vectors; + + for (int i=0;iprocessTriangle(triangle,0,0); + + triangle[0] = projectedCenter - tangentDir0*radius - tangentDir1*radius; + triangle[1] = projectedCenter - tangentDir0*radius + tangentDir1*radius; + triangle[2] = projectedCenter + tangentDir0*radius + tangentDir1*radius; + + callback->processTriangle(triangle,0,1); + +} + +void btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + (void)mass; + + //moving concave objects not supported + + inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); +} + +void btStaticPlaneShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; +} +const btVector3& btStaticPlaneShape::getLocalScaling() const +{ + return m_localScaling; +} diff --git a/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h new file mode 100644 index 0000000..b13825e --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h @@ -0,0 +1,103 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_STATIC_PLANE_SHAPE_H +#define BT_STATIC_PLANE_SHAPE_H + +#include "btConcaveShape.h" + + +///The btStaticPlaneShape simulates an infinite non-moving (static) collision plane. +ATTRIBUTE_ALIGNED16(class) btStaticPlaneShape : public btConcaveShape +{ +protected: + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + + btVector3 m_planeNormal; + btScalar m_planeConstant; + btVector3 m_localScaling; + +public: + btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant); + + virtual ~btStaticPlaneShape(); + + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const; + + const btVector3& getPlaneNormal() const + { + return m_planeNormal; + } + + const btScalar& getPlaneConstant() const + { + return m_planeConstant; + } + + //debugging + virtual const char* getName()const {return "STATICPLANE";} + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btStaticPlaneShapeData +{ + btCollisionShapeData m_collisionShapeData; + + btVector3FloatData m_localScaling; + btVector3FloatData m_planeNormal; + float m_planeConstant; + char m_pad[4]; +}; + + +SIMD_FORCE_INLINE int btStaticPlaneShape::calculateSerializeBufferSize() const +{ + return sizeof(btStaticPlaneShapeData); +} + +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btStaticPlaneShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*) dataBuffer; + btCollisionShape::serialize(&planeData->m_collisionShapeData,serializer); + + m_localScaling.serializeFloat(planeData->m_localScaling); + m_planeNormal.serializeFloat(planeData->m_planeNormal); + planeData->m_planeConstant = float(m_planeConstant); + + return "btStaticPlaneShapeData"; +} + + +#endif //BT_STATIC_PLANE_SHAPE_H + + + diff --git a/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp new file mode 100644 index 0000000..dd22fc5 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp @@ -0,0 +1,381 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btStridingMeshInterface.h" +#include "LinearMath/btSerializer.h" + +btStridingMeshInterface::~btStridingMeshInterface() +{ + +} + + +void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + (void)aabbMin; + (void)aabbMax; + int numtotalphysicsverts = 0; + int part,graphicssubparts = getNumSubParts(); + const unsigned char * vertexbase; + const unsigned char * indexbase; + int indexstride; + PHY_ScalarType type; + PHY_ScalarType gfxindextype; + int stride,numverts,numtriangles; + int gfxindex; + btVector3 triangle[3]; + + btVector3 meshScaling = getScaling(); + + ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype + for (part=0;partinternalProcessTriangleIndex(triangle,part,gfxindex); + } + break; + } + case PHY_SHORT: + { + for (gfxindex=0;gfxindexinternalProcessTriangleIndex(triangle,part,gfxindex); + } + break; + } + case PHY_UCHAR: + { + for (gfxindex=0;gfxindexinternalProcessTriangleIndex(triangle,part,gfxindex); + } + break; + } + default: + btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT)); + } + break; + } + + case PHY_DOUBLE: + { + double* graphicsbase; + + switch (gfxindextype) + { + case PHY_INTEGER: + { + for (gfxindex=0;gfxindexinternalProcessTriangleIndex(triangle,part,gfxindex); + } + break; + } + case PHY_SHORT: + { + for (gfxindex=0;gfxindexinternalProcessTriangleIndex(triangle,part,gfxindex); + } + break; + } + case PHY_UCHAR: + { + for (gfxindex=0;gfxindexinternalProcessTriangleIndex(triangle,part,gfxindex); + } + break; + } + default: + btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT)); + } + break; + } + default: + btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE)); + } + + unLockReadOnlyVertexBase(part); + } +} + +void btStridingMeshInterface::calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax) +{ + + struct AabbCalculationCallback : public btInternalTriangleIndexCallback + { + btVector3 m_aabbMin; + btVector3 m_aabbMax; + + AabbCalculationCallback() + { + m_aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + m_aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + (void)partId; + (void)triangleIndex; + + m_aabbMin.setMin(triangle[0]); + m_aabbMax.setMax(triangle[0]); + m_aabbMin.setMin(triangle[1]); + m_aabbMax.setMax(triangle[1]); + m_aabbMin.setMin(triangle[2]); + m_aabbMax.setMax(triangle[2]); + } + }; + + //first calculate the total aabb for all triangles + AabbCalculationCallback aabbCallback; + aabbMin.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + aabbMax.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + InternalProcessAllTriangles(&aabbCallback,aabbMin,aabbMax); + + aabbMin = aabbCallback.m_aabbMin; + aabbMax = aabbCallback.m_aabbMax; +} + + + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btStridingMeshInterfaceData* trimeshData = (btStridingMeshInterfaceData*) dataBuffer; + + trimeshData->m_numMeshParts = getNumSubParts(); + + //void* uniquePtr = 0; + + trimeshData->m_meshPartsPtr = 0; + + if (trimeshData->m_numMeshParts) + { + btChunk* chunk = serializer->allocate(sizeof(btMeshPartData),trimeshData->m_numMeshParts); + btMeshPartData* memPtr = (btMeshPartData*)chunk->m_oldPtr; + trimeshData->m_meshPartsPtr = (btMeshPartData *)serializer->getUniquePointer(memPtr); + + + // int numtotalphysicsverts = 0; + int part,graphicssubparts = getNumSubParts(); + const unsigned char * vertexbase; + const unsigned char * indexbase; + int indexstride; + PHY_ScalarType type; + PHY_ScalarType gfxindextype; + int stride,numverts,numtriangles; + int gfxindex; + // btVector3 triangle[3]; + + btVector3 meshScaling = getScaling(); + + ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype + for (part=0;partm_numTriangles = numtriangles;//indices = 3*numtriangles + memPtr->m_numVertices = numverts; + memPtr->m_indices16 = 0; + memPtr->m_indices32 = 0; + memPtr->m_3indices16 = 0; + memPtr->m_3indices8 = 0; + memPtr->m_vertices3f = 0; + memPtr->m_vertices3d = 0; + + + switch (gfxindextype) + { + case PHY_INTEGER: + { + int numindices = numtriangles*3; + + if (numindices) + { + btChunk* chunk = serializer->allocate(sizeof(btIntIndexData),numindices); + btIntIndexData* tmpIndices = (btIntIndexData*)chunk->m_oldPtr; + memPtr->m_indices32 = (btIntIndexData*)serializer->getUniquePointer(tmpIndices); + for (gfxindex=0;gfxindexfinalizeChunk(chunk,"btIntIndexData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr); + } + break; + } + case PHY_SHORT: + { + if (numtriangles) + { + btChunk* chunk = serializer->allocate(sizeof(btShortIntIndexTripletData),numtriangles); + btShortIntIndexTripletData* tmpIndices = (btShortIntIndexTripletData*)chunk->m_oldPtr; + memPtr->m_3indices16 = (btShortIntIndexTripletData*) serializer->getUniquePointer(tmpIndices); + for (gfxindex=0;gfxindexfinalizeChunk(chunk,"btShortIntIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr); + } + break; + } + case PHY_UCHAR: + { + if (numtriangles) + { + btChunk* chunk = serializer->allocate(sizeof(btCharIndexTripletData),numtriangles); + btCharIndexTripletData* tmpIndices = (btCharIndexTripletData*)chunk->m_oldPtr; + memPtr->m_3indices8 = (btCharIndexTripletData*) serializer->getUniquePointer(tmpIndices); + for (gfxindex=0;gfxindexfinalizeChunk(chunk,"btCharIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr); + } + break; + } + default: + { + btAssert(0); + //unknown index type + } + } + + switch (type) + { + case PHY_FLOAT: + { + float* graphicsbase; + + if (numverts) + { + btChunk* chunk = serializer->allocate(sizeof(btVector3FloatData),numverts); + btVector3FloatData* tmpVertices = (btVector3FloatData*) chunk->m_oldPtr; + memPtr->m_vertices3f = (btVector3FloatData *)serializer->getUniquePointer(tmpVertices); + for (int i=0;ifinalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr); + } + break; + } + + case PHY_DOUBLE: + { + if (numverts) + { + btChunk* chunk = serializer->allocate(sizeof(btVector3DoubleData),numverts); + btVector3DoubleData* tmpVertices = (btVector3DoubleData*) chunk->m_oldPtr; + memPtr->m_vertices3d = (btVector3DoubleData *) serializer->getUniquePointer(tmpVertices); + for (int i=0;ifinalizeChunk(chunk,"btVector3DoubleData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr); + } + break; + } + + default: + btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE)); + } + + unLockReadOnlyVertexBase(part); + } + + serializer->finalizeChunk(chunk,"btMeshPartData",BT_ARRAY_CODE,chunk->m_oldPtr); + } + + + m_scaling.serializeFloat(trimeshData->m_scaling); + return "btStridingMeshInterfaceData"; +} diff --git a/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h new file mode 100644 index 0000000..f2b27ad --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h @@ -0,0 +1,162 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_STRIDING_MESHINTERFACE_H +#define BT_STRIDING_MESHINTERFACE_H + +#include "LinearMath/btVector3.h" +#include "btTriangleCallback.h" +#include "btConcaveShape.h" + + + + + +/// The btStridingMeshInterface is the interface class for high performance generic access to triangle meshes, used in combination with btBvhTriangleMeshShape and some other collision shapes. +/// Using index striding of 3*sizeof(integer) it can use triangle arrays, using index striding of 1*sizeof(integer) it can handle triangle strips. +/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory. +class btStridingMeshInterface +{ + protected: + + btVector3 m_scaling; + + public: + btStridingMeshInterface() :m_scaling(btScalar(1.),btScalar(1.),btScalar(1.)) + { + + } + + virtual ~btStridingMeshInterface(); + + + + virtual void InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + ///brute force method to calculate aabb + void calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax); + + /// get read and write access to a subpart of a triangle mesh + /// this subpart has a continuous array of vertices and indices + /// in this way the mesh can be handled as chunks of memory with striding + /// very similar to OpenGL vertexarray support + /// make a call to unLockVertexBase when the read and write access is finished + virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0)=0; + + virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const=0; + + /// unLockVertexBase finishes the access to a subpart of the triangle mesh + /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished + virtual void unLockVertexBase(int subpart)=0; + + virtual void unLockReadOnlyVertexBase(int subpart) const=0; + + + /// getNumSubParts returns the number of seperate subparts + /// each subpart has a continuous array of vertices and indices + virtual int getNumSubParts() const=0; + + virtual void preallocateVertices(int numverts)=0; + virtual void preallocateIndices(int numindices)=0; + + virtual bool hasPremadeAabb() const { return false; } + virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const + { + (void) aabbMin; + (void) aabbMax; + } + virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const + { + (void) aabbMin; + (void) aabbMax; + } + + const btVector3& getScaling() const { + return m_scaling; + } + void setScaling(const btVector3& scaling) + { + m_scaling = scaling; + } + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + +struct btIntIndexData +{ + int m_value; +}; + +struct btShortIntIndexData +{ + short m_value; + char m_pad[2]; +}; + +struct btShortIntIndexTripletData +{ + short m_values[3]; + char m_pad[2]; +}; + +struct btCharIndexTripletData +{ + unsigned char m_values[3]; + char m_pad; +}; + + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btMeshPartData +{ + btVector3FloatData *m_vertices3f; + btVector3DoubleData *m_vertices3d; + + btIntIndexData *m_indices32; + btShortIntIndexTripletData *m_3indices16; + btCharIndexTripletData *m_3indices8; + + btShortIntIndexData *m_indices16;//backwards compatibility + + int m_numTriangles;//length of m_indices = m_numTriangles + int m_numVertices; +}; + + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btStridingMeshInterfaceData +{ + btMeshPartData *m_meshPartsPtr; + btVector3FloatData m_scaling; + int m_numMeshParts; + char m_padding[4]; +}; + + + + +SIMD_FORCE_INLINE int btStridingMeshInterface::calculateSerializeBufferSize() const +{ + return sizeof(btStridingMeshInterfaceData); +} + + + +#endif //BT_STRIDING_MESHINTERFACE_H diff --git a/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp b/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp new file mode 100644 index 0000000..52f346b --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp @@ -0,0 +1,218 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btTetrahedronShape.h" +#include "LinearMath/btMatrix3x3.h" + +btBU_Simplex1to4::btBU_Simplex1to4() : btPolyhedralConvexAabbCachingShape (), +m_numVertices(0) +{ + m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE; +} + +btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0) : btPolyhedralConvexAabbCachingShape (), +m_numVertices(0) +{ + m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE; + addVertex(pt0); +} + +btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1) : btPolyhedralConvexAabbCachingShape (), +m_numVertices(0) +{ + m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE; + addVertex(pt0); + addVertex(pt1); +} + +btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2) : btPolyhedralConvexAabbCachingShape (), +m_numVertices(0) +{ + m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE; + addVertex(pt0); + addVertex(pt1); + addVertex(pt2); +} + +btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2,const btVector3& pt3) : btPolyhedralConvexAabbCachingShape (), +m_numVertices(0) +{ + m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE; + addVertex(pt0); + addVertex(pt1); + addVertex(pt2); + addVertex(pt3); +} + + +void btBU_Simplex1to4::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ +#if 1 + btPolyhedralConvexAabbCachingShape::getAabb(t,aabbMin,aabbMax); +#else + aabbMin.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); + aabbMax.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT); + + //just transform the vertices in worldspace, and take their AABB + for (int i=0;iprocessAllTriangles(&triBuf,aabbMin, aabbMax); +/// for (int i=0;i m_triangleBuffer; + +public: + + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); + + int getNumTriangles() const + { + return int(m_triangleBuffer.size()); + } + + const btTriangle& getTriangle(int index) const + { + return m_triangleBuffer[index]; + } + + void clearBuffer() + { + m_triangleBuffer.clear(); + } + +}; + + +#endif //BT_TRIANGLE_BUFFER_H + diff --git a/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp b/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp new file mode 100644 index 0000000..f558bf6 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp @@ -0,0 +1,28 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btTriangleCallback.h" + +btTriangleCallback::~btTriangleCallback() +{ + +} + + +btInternalTriangleIndexCallback::~btInternalTriangleIndexCallback() +{ + +} + diff --git a/src/BulletCollision/CollisionShapes/btTriangleCallback.h b/src/BulletCollision/CollisionShapes/btTriangleCallback.h new file mode 100644 index 0000000..461c57f --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btTriangleCallback.h @@ -0,0 +1,42 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_TRIANGLE_CALLBACK_H +#define BT_TRIANGLE_CALLBACK_H + +#include "LinearMath/btVector3.h" + + +///The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTriangles. +///This callback is called by processAllTriangles for all btConcaveShape derived class, such as btBvhTriangleMeshShape, btStaticPlaneShape and btHeightfieldTerrainShape. +class btTriangleCallback +{ +public: + + virtual ~btTriangleCallback(); + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) = 0; +}; + +class btInternalTriangleIndexCallback +{ +public: + + virtual ~btInternalTriangleIndexCallback(); + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) = 0; +}; + + + +#endif //BT_TRIANGLE_CALLBACK_H diff --git a/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp b/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp new file mode 100644 index 0000000..a665024 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp @@ -0,0 +1,95 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btTriangleIndexVertexArray.h" + +btTriangleIndexVertexArray::btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride) +: m_hasAabb(0) +{ + btIndexedMesh mesh; + + mesh.m_numTriangles = numTriangles; + mesh.m_triangleIndexBase = (const unsigned char *)triangleIndexBase; + mesh.m_triangleIndexStride = triangleIndexStride; + mesh.m_numVertices = numVertices; + mesh.m_vertexBase = (const unsigned char *)vertexBase; + mesh.m_vertexStride = vertexStride; + + addIndexedMesh(mesh); + +} + +btTriangleIndexVertexArray::~btTriangleIndexVertexArray() +{ + +} + +void btTriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) +{ + btAssert(subpart< getNumSubParts() ); + + btIndexedMesh& mesh = m_indexedMeshes[subpart]; + + numverts = mesh.m_numVertices; + (*vertexbase) = (unsigned char *) mesh.m_vertexBase; + + type = mesh.m_vertexType; + + vertexStride = mesh.m_vertexStride; + + numfaces = mesh.m_numTriangles; + + (*indexbase) = (unsigned char *)mesh.m_triangleIndexBase; + indexstride = mesh.m_triangleIndexStride; + indicestype = mesh.m_indexType; +} + +void btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const +{ + const btIndexedMesh& mesh = m_indexedMeshes[subpart]; + + numverts = mesh.m_numVertices; + (*vertexbase) = (const unsigned char *)mesh.m_vertexBase; + + type = mesh.m_vertexType; + + vertexStride = mesh.m_vertexStride; + + numfaces = mesh.m_numTriangles; + (*indexbase) = (const unsigned char *)mesh.m_triangleIndexBase; + indexstride = mesh.m_triangleIndexStride; + indicestype = mesh.m_indexType; +} + +bool btTriangleIndexVertexArray::hasPremadeAabb() const +{ + return (m_hasAabb == 1); +} + + +void btTriangleIndexVertexArray::setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const +{ + m_aabbMin = aabbMin; + m_aabbMax = aabbMax; + m_hasAabb = 1; // this is intentionally an int see notes in header +} + +void btTriangleIndexVertexArray::getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const +{ + *aabbMin = m_aabbMin; + *aabbMax = m_aabbMax; +} + + diff --git a/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h new file mode 100644 index 0000000..9e1544e --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h @@ -0,0 +1,133 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_TRIANGLE_INDEX_VERTEX_ARRAY_H +#define BT_TRIANGLE_INDEX_VERTEX_ARRAY_H + +#include "btStridingMeshInterface.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btScalar.h" + + +///The btIndexedMesh indexes a single vertex and index array. Multiple btIndexedMesh objects can be passed into a btTriangleIndexVertexArray using addIndexedMesh. +///Instead of the number of indices, we pass the number of triangles. +ATTRIBUTE_ALIGNED16( struct) btIndexedMesh +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + int m_numTriangles; + const unsigned char * m_triangleIndexBase; + // Size in byte of the indices for one triangle (3*sizeof(index_type) if the indices are tightly packed) + int m_triangleIndexStride; + int m_numVertices; + const unsigned char * m_vertexBase; + // Size of a vertex, in bytes + int m_vertexStride; + + // The index type is set when adding an indexed mesh to the + // btTriangleIndexVertexArray, do not set it manually + PHY_ScalarType m_indexType; + + // The vertex type has a default type similar to Bullet's precision mode (float or double) + // but can be set manually if you for example run Bullet with double precision but have + // mesh data in single precision.. + PHY_ScalarType m_vertexType; + + + btIndexedMesh() + :m_indexType(PHY_INTEGER), +#ifdef BT_USE_DOUBLE_PRECISION + m_vertexType(PHY_DOUBLE) +#else // BT_USE_DOUBLE_PRECISION + m_vertexType(PHY_FLOAT) +#endif // BT_USE_DOUBLE_PRECISION + { + } +} +; + + +typedef btAlignedObjectArray IndexedMeshArray; + +///The btTriangleIndexVertexArray allows to access multiple triangle meshes, by indexing into existing triangle/index arrays. +///Additional meshes can be added using addIndexedMesh +///No duplcate is made of the vertex/index data, it only indexes into external vertex/index arrays. +///So keep those arrays around during the lifetime of this btTriangleIndexVertexArray. +ATTRIBUTE_ALIGNED16( class) btTriangleIndexVertexArray : public btStridingMeshInterface +{ +protected: + IndexedMeshArray m_indexedMeshes; + int m_pad[2]; + mutable int m_hasAabb; // using int instead of bool to maintain alignment + mutable btVector3 m_aabbMin; + mutable btVector3 m_aabbMax; + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btTriangleIndexVertexArray() : m_hasAabb(0) + { + } + + virtual ~btTriangleIndexVertexArray(); + + //just to be backwards compatible + btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride); + + void addIndexedMesh(const btIndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER) + { + m_indexedMeshes.push_back(mesh); + m_indexedMeshes[m_indexedMeshes.size()-1].m_indexType = indexType; + } + + + virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0); + + virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const; + + /// unLockVertexBase finishes the access to a subpart of the triangle mesh + /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished + virtual void unLockVertexBase(int subpart) {(void)subpart;} + + virtual void unLockReadOnlyVertexBase(int subpart) const {(void)subpart;} + + /// getNumSubParts returns the number of seperate subparts + /// each subpart has a continuous array of vertices and indices + virtual int getNumSubParts() const { + return (int)m_indexedMeshes.size(); + } + + IndexedMeshArray& getIndexedMeshArray() + { + return m_indexedMeshes; + } + + const IndexedMeshArray& getIndexedMeshArray() const + { + return m_indexedMeshes; + } + + virtual void preallocateVertices(int numverts){(void) numverts;} + virtual void preallocateIndices(int numindices){(void) numindices;} + + virtual bool hasPremadeAabb() const; + virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const; + virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const; + +} +; + +#endif //BT_TRIANGLE_INDEX_VERTEX_ARRAY_H diff --git a/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp b/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp new file mode 100644 index 0000000..dc56294 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp @@ -0,0 +1,86 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +///This file was created by Alex Silverman + +#include "btTriangleIndexVertexMaterialArray.h" + +btTriangleIndexVertexMaterialArray::btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride, + int numVertices,btScalar* vertexBase,int vertexStride, + int numMaterials, unsigned char* materialBase, int materialStride, + int* triangleMaterialsBase, int materialIndexStride) : +btTriangleIndexVertexArray(numTriangles, triangleIndexBase, triangleIndexStride, numVertices, vertexBase, vertexStride) +{ + btMaterialProperties mat; + + mat.m_numMaterials = numMaterials; + mat.m_materialBase = materialBase; + mat.m_materialStride = materialStride; +#ifdef BT_USE_DOUBLE_PRECISION + mat.m_materialType = PHY_DOUBLE; +#else + mat.m_materialType = PHY_FLOAT; +#endif + + mat.m_numTriangles = numTriangles; + mat.m_triangleMaterialsBase = (unsigned char *)triangleMaterialsBase; + mat.m_triangleMaterialStride = materialIndexStride; + mat.m_triangleType = PHY_INTEGER; + + addMaterialProperties(mat); +} + + +void btTriangleIndexVertexMaterialArray::getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, + unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart) +{ + btAssert(subpart< getNumSubParts() ); + + btMaterialProperties& mats = m_materials[subpart]; + + numMaterials = mats.m_numMaterials; + (*materialBase) = (unsigned char *) mats.m_materialBase; +#ifdef BT_USE_DOUBLE_PRECISION + materialType = PHY_DOUBLE; +#else + materialType = PHY_FLOAT; +#endif + materialStride = mats.m_materialStride; + + numTriangles = mats.m_numTriangles; + (*triangleMaterialBase) = (unsigned char *)mats.m_triangleMaterialsBase; + triangleMaterialStride = mats.m_triangleMaterialStride; + triangleType = mats.m_triangleType; +} + +void btTriangleIndexVertexMaterialArray::getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, + const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart) +{ + btMaterialProperties& mats = m_materials[subpart]; + + numMaterials = mats.m_numMaterials; + (*materialBase) = (const unsigned char *) mats.m_materialBase; +#ifdef BT_USE_DOUBLE_PRECISION + materialType = PHY_DOUBLE; +#else + materialType = PHY_FLOAT; +#endif + materialStride = mats.m_materialStride; + + numTriangles = mats.m_numTriangles; + (*triangleMaterialBase) = (const unsigned char *)mats.m_triangleMaterialsBase; + triangleMaterialStride = mats.m_triangleMaterialStride; + triangleType = mats.m_triangleType; +} diff --git a/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h b/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h new file mode 100644 index 0000000..ba4f7b4 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h @@ -0,0 +1,84 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +///This file was created by Alex Silverman + +#ifndef BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H +#define BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H + +#include "btTriangleIndexVertexArray.h" + + +ATTRIBUTE_ALIGNED16( struct) btMaterialProperties +{ + ///m_materialBase ==========> 2 btScalar values make up one material, friction then restitution + int m_numMaterials; + const unsigned char * m_materialBase; + int m_materialStride; + PHY_ScalarType m_materialType; + ///m_numTriangles <=========== This exists in the btIndexedMesh object for the same subpart, but since we're + /// padding the structure, it can be reproduced at no real cost + ///m_triangleMaterials =====> 1 integer value makes up one entry + /// eg: m_triangleMaterials[1] = 5; // This will set triangle 2 to use material 5 + int m_numTriangles; + const unsigned char * m_triangleMaterialsBase; + int m_triangleMaterialStride; + ///m_triangleType <========== Automatically set in addMaterialProperties + PHY_ScalarType m_triangleType; +}; + +typedef btAlignedObjectArray MaterialArray; + +///Teh btTriangleIndexVertexMaterialArray is built on TriangleIndexVertexArray +///The addition of a material array allows for the utilization of the partID and +///triangleIndex that are returned in the ContactAddedCallback. As with +///TriangleIndexVertexArray, no duplicate is made of the material data, so it +///is the users responsibility to maintain the array during the lifetime of the +///TriangleIndexVertexMaterialArray. +ATTRIBUTE_ALIGNED16(class) btTriangleIndexVertexMaterialArray : public btTriangleIndexVertexArray +{ +protected: + MaterialArray m_materials; + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btTriangleIndexVertexMaterialArray() + { + } + + btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride, + int numVertices,btScalar* vertexBase,int vertexStride, + int numMaterials, unsigned char* materialBase, int materialStride, + int* triangleMaterialsBase, int materialIndexStride); + + virtual ~btTriangleIndexVertexMaterialArray() {} + + void addMaterialProperties(const btMaterialProperties& mat, PHY_ScalarType triangleType = PHY_INTEGER) + { + m_materials.push_back(mat); + m_materials[m_materials.size()-1].m_triangleType = triangleType; + } + + virtual void getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, + unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType ,int subpart = 0); + + virtual void getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, + const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0); + +} +; + +#endif //BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H diff --git a/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h b/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h new file mode 100644 index 0000000..1cea704 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h @@ -0,0 +1,241 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2010 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef _BT_TRIANGLE_INFO_MAP_H +#define _BT_TRIANGLE_INFO_MAP_H + + +#include "LinearMath/btHashMap.h" +#include "LinearMath/btSerializer.h" + + +///for btTriangleInfo m_flags +#define TRI_INFO_V0V1_CONVEX 1 +#define TRI_INFO_V1V2_CONVEX 2 +#define TRI_INFO_V2V0_CONVEX 4 + +#define TRI_INFO_V0V1_SWAP_NORMALB 8 +#define TRI_INFO_V1V2_SWAP_NORMALB 16 +#define TRI_INFO_V2V0_SWAP_NORMALB 32 + + +///The btTriangleInfo structure stores information to adjust collision normals to avoid collisions against internal edges +///it can be generated using +struct btTriangleInfo +{ + btTriangleInfo() + { + m_edgeV0V1Angle = SIMD_2_PI; + m_edgeV1V2Angle = SIMD_2_PI; + m_edgeV2V0Angle = SIMD_2_PI; + m_flags=0; + } + + int m_flags; + + btScalar m_edgeV0V1Angle; + btScalar m_edgeV1V2Angle; + btScalar m_edgeV2V0Angle; + +}; + +typedef btHashMap btInternalTriangleInfoMap; + + +///The btTriangleInfoMap stores edge angle information for some triangles. You can compute this information yourself or using btGenerateInternalEdgeInfo. +struct btTriangleInfoMap : public btInternalTriangleInfoMap +{ + btScalar m_convexEpsilon;///used to determine if an edge or contact normal is convex, using the dot product + btScalar m_planarEpsilon; ///used to determine if a triangle edge is planar with zero angle + btScalar m_equalVertexThreshold; ///used to compute connectivity: if the distance between two vertices is smaller than m_equalVertexThreshold, they are considered to be 'shared' + btScalar m_edgeDistanceThreshold; ///used to determine edge contacts: if the closest distance between a contact point and an edge is smaller than this distance threshold it is considered to "hit the edge" + btScalar m_maxEdgeAngleThreshold; //ignore edges that connect triangles at an angle larger than this m_maxEdgeAngleThreshold + btScalar m_zeroAreaThreshold; ///used to determine if a triangle is degenerate (length squared of cross product of 2 triangle edges < threshold) + + + btTriangleInfoMap() + { + m_convexEpsilon = 0.00f; + m_planarEpsilon = 0.0001f; + m_equalVertexThreshold = btScalar(0.0001)*btScalar(0.0001); + m_edgeDistanceThreshold = btScalar(0.1); + m_zeroAreaThreshold = btScalar(0.0001)*btScalar(0.0001); + m_maxEdgeAngleThreshold = SIMD_2_PI; + } + virtual ~btTriangleInfoMap() {} + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + void deSerialize(struct btTriangleInfoMapData& data); + +}; + +///those fields have to be float and not btScalar for the serialization to work properly +struct btTriangleInfoData +{ + int m_flags; + float m_edgeV0V1Angle; + float m_edgeV1V2Angle; + float m_edgeV2V0Angle; +}; + +struct btTriangleInfoMapData +{ + int *m_hashTablePtr; + int *m_nextPtr; + btTriangleInfoData *m_valueArrayPtr; + int *m_keyArrayPtr; + + float m_convexEpsilon; + float m_planarEpsilon; + float m_equalVertexThreshold; + float m_edgeDistanceThreshold; + float m_zeroAreaThreshold; + + int m_nextSize; + int m_hashTableSize; + int m_numValues; + int m_numKeys; + char m_padding[4]; +}; + +SIMD_FORCE_INLINE int btTriangleInfoMap::calculateSerializeBufferSize() const +{ + return sizeof(btTriangleInfoMapData); +} + +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btTriangleInfoMap::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btTriangleInfoMapData* tmapData = (btTriangleInfoMapData*) dataBuffer; + tmapData->m_convexEpsilon = m_convexEpsilon; + tmapData->m_planarEpsilon = m_planarEpsilon; + tmapData->m_equalVertexThreshold = m_equalVertexThreshold; + tmapData->m_edgeDistanceThreshold = m_edgeDistanceThreshold; + tmapData->m_zeroAreaThreshold = m_zeroAreaThreshold; + + tmapData->m_hashTableSize = m_hashTable.size(); + + tmapData->m_hashTablePtr = tmapData->m_hashTableSize ? (int*)serializer->getUniquePointer((void*)&m_hashTable[0]) : 0; + if (tmapData->m_hashTablePtr) + { + //serialize an int buffer + int sz = sizeof(int); + int numElem = tmapData->m_hashTableSize; + btChunk* chunk = serializer->allocate(sz,numElem); + int* memPtr = (int*)chunk->m_oldPtr; + for (int i=0;ifinalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_hashTable[0]); + + } + + tmapData->m_nextSize = m_next.size(); + tmapData->m_nextPtr = tmapData->m_nextSize? (int*)serializer->getUniquePointer((void*)&m_next[0]): 0; + if (tmapData->m_nextPtr) + { + int sz = sizeof(int); + int numElem = tmapData->m_nextSize; + btChunk* chunk = serializer->allocate(sz,numElem); + int* memPtr = (int*)chunk->m_oldPtr; + for (int i=0;ifinalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_next[0]); + } + + tmapData->m_numValues = m_valueArray.size(); + tmapData->m_valueArrayPtr = tmapData->m_numValues ? (btTriangleInfoData*)serializer->getUniquePointer((void*)&m_valueArray[0]): 0; + if (tmapData->m_valueArrayPtr) + { + int sz = sizeof(btTriangleInfoData); + int numElem = tmapData->m_numValues; + btChunk* chunk = serializer->allocate(sz,numElem); + btTriangleInfoData* memPtr = (btTriangleInfoData*)chunk->m_oldPtr; + for (int i=0;im_edgeV0V1Angle = m_valueArray[i].m_edgeV0V1Angle; + memPtr->m_edgeV1V2Angle = m_valueArray[i].m_edgeV1V2Angle; + memPtr->m_edgeV2V0Angle = m_valueArray[i].m_edgeV2V0Angle; + memPtr->m_flags = m_valueArray[i].m_flags; + } + serializer->finalizeChunk(chunk,"btTriangleInfoData",BT_ARRAY_CODE,(void*) &m_valueArray[0]); + } + + tmapData->m_numKeys = m_keyArray.size(); + tmapData->m_keyArrayPtr = tmapData->m_numKeys ? (int*)serializer->getUniquePointer((void*)&m_keyArray[0]) : 0; + if (tmapData->m_keyArrayPtr) + { + int sz = sizeof(int); + int numElem = tmapData->m_numValues; + btChunk* chunk = serializer->allocate(sz,numElem); + int* memPtr = (int*)chunk->m_oldPtr; + for (int i=0;ifinalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*) &m_keyArray[0]); + + } + return "btTriangleInfoMapData"; +} + + + +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE void btTriangleInfoMap::deSerialize(btTriangleInfoMapData& tmapData ) +{ + + + m_convexEpsilon = tmapData.m_convexEpsilon; + m_planarEpsilon = tmapData.m_planarEpsilon; + m_equalVertexThreshold = tmapData.m_equalVertexThreshold; + m_edgeDistanceThreshold = tmapData.m_edgeDistanceThreshold; + m_zeroAreaThreshold = tmapData.m_zeroAreaThreshold; + m_hashTable.resize(tmapData.m_hashTableSize); + int i =0; + for (i=0;i m_4componentVertices; + btAlignedObjectArray m_3componentVertices; + + btAlignedObjectArray m_32bitIndices; + btAlignedObjectArray m_16bitIndices; + bool m_use32bitIndices; + bool m_use4componentVertices; + + + public: + btScalar m_weldingThreshold; + + btTriangleMesh (bool use32bitIndices=true,bool use4componentVertices=true); + + bool getUse32bitIndices() const + { + return m_use32bitIndices; + } + + bool getUse4componentVertices() const + { + return m_use4componentVertices; + } + ///By default addTriangle won't search for duplicate vertices, because the search is very slow for large triangle meshes. + ///In general it is better to directly use btTriangleIndexVertexArray instead. + void addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2, bool removeDuplicateVertices=false); + + int getNumTriangles() const; + + virtual void preallocateVertices(int numverts){(void) numverts;} + virtual void preallocateIndices(int numindices){(void) numindices;} + + ///findOrAddVertex is an internal method, use addTriangle instead + int findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices); + ///addIndex is an internal method, use addTriangle instead + void addIndex(int index); + +}; + +#endif //BT_TRIANGLE_MESH_H + diff --git a/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp new file mode 100644 index 0000000..683684d --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp @@ -0,0 +1,211 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btTriangleMeshShape.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btQuaternion.h" +#include "btStridingMeshInterface.h" +#include "LinearMath/btAabbUtil2.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + + +btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface) +: btConcaveShape (), m_meshInterface(meshInterface) +{ + m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE; + if(meshInterface->hasPremadeAabb()) + { + meshInterface->getPremadeAabb(&m_localAabbMin, &m_localAabbMax); + } + else + { + recalcLocalAabb(); + } +} + + +btTriangleMeshShape::~btTriangleMeshShape() +{ + +} + + + + +void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + + btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); + localHalfExtents += btVector3(getMargin(),getMargin(),getMargin()); + btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); + + btMatrix3x3 abs_b = trans.getBasis().absolute(); + + btVector3 center = trans(localCenter); + + btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + aabbMin = center - extent; + aabbMax = center + extent; + + +} + +void btTriangleMeshShape::recalcLocalAabb() +{ + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + btVector3 tmp = localGetSupportingVertex(vec); + m_localAabbMax[i] = tmp[i]+m_collisionMargin; + vec[i] = btScalar(-1.); + tmp = localGetSupportingVertex(vec); + m_localAabbMin[i] = tmp[i]-m_collisionMargin; + } +} + + + +class SupportVertexCallback : public btTriangleCallback +{ + + btVector3 m_supportVertexLocal; +public: + + btTransform m_worldTrans; + btScalar m_maxDot; + btVector3 m_supportVecLocal; + + SupportVertexCallback(const btVector3& supportVecWorld,const btTransform& trans) + : m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)), m_worldTrans(trans) ,m_maxDot(btScalar(-BT_LARGE_FLOAT)) + + { + m_supportVecLocal = supportVecWorld * m_worldTrans.getBasis(); + } + + virtual void processTriangle( btVector3* triangle,int partId, int triangleIndex) + { + (void)partId; + (void)triangleIndex; + for (int i=0;i<3;i++) + { + btScalar dot = m_supportVecLocal.dot(triangle[i]); + if (dot > m_maxDot) + { + m_maxDot = dot; + m_supportVertexLocal = triangle[i]; + } + } + } + + btVector3 GetSupportVertexWorldSpace() + { + return m_worldTrans(m_supportVertexLocal); + } + + btVector3 GetSupportVertexLocal() + { + return m_supportVertexLocal; + } + +}; + + +void btTriangleMeshShape::setLocalScaling(const btVector3& scaling) +{ + m_meshInterface->setScaling(scaling); + recalcLocalAabb(); +} + +const btVector3& btTriangleMeshShape::getLocalScaling() const +{ + return m_meshInterface->getScaling(); +} + + + + + + +//#define DEBUG_TRIANGLE_MESH + + + +void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + struct FilteredCallback : public btInternalTriangleIndexCallback + { + btTriangleCallback* m_callback; + btVector3 m_aabbMin; + btVector3 m_aabbMax; + + FilteredCallback(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) + :m_callback(callback), + m_aabbMin(aabbMin), + m_aabbMax(aabbMax) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + if (TestTriangleAgainstAabb2(&triangle[0],m_aabbMin,m_aabbMax)) + { + //check aabb in triangle-space, before doing this + m_callback->processTriangle(triangle,partId,triangleIndex); + } + + } + + }; + + FilteredCallback filterCallback(callback,aabbMin,aabbMax); + + m_meshInterface->InternalProcessAllTriangles(&filterCallback,aabbMin,aabbMax); +} + + + + + +void btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + (void)mass; + //moving concave objects not supported + btAssert(0); + inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); +} + + +btVector3 btTriangleMeshShape::localGetSupportingVertex(const btVector3& vec) const +{ + btVector3 supportVertex; + + btTransform ident; + ident.setIdentity(); + + SupportVertexCallback supportCallback(vec,ident); + + btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + + processAllTriangles(&supportCallback,-aabbMax,aabbMax); + + supportVertex = supportCallback.GetSupportVertexLocal(); + + return supportVertex; +} + + diff --git a/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h new file mode 100644 index 0000000..c8caf8f --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h @@ -0,0 +1,89 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_TRIANGLE_MESH_SHAPE_H +#define BT_TRIANGLE_MESH_SHAPE_H + +#include "btConcaveShape.h" +#include "btStridingMeshInterface.h" + + +///The btTriangleMeshShape is an internal concave triangle mesh interface. Don't use this class directly, use btBvhTriangleMeshShape instead. +class btTriangleMeshShape : public btConcaveShape +{ +protected: + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + btStridingMeshInterface* m_meshInterface; + + ///btTriangleMeshShape constructor has been disabled/protected, so that users will not mistakenly use this class. + ///Don't use btTriangleMeshShape but use btBvhTriangleMeshShape instead! + btTriangleMeshShape(btStridingMeshInterface* meshInterface); + +public: + + virtual ~btTriangleMeshShape(); + + virtual btVector3 localGetSupportingVertex(const btVector3& vec) const; + + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const + { + btAssert(0); + return localGetSupportingVertex(vec); + } + + void recalcLocalAabb(); + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const; + + btStridingMeshInterface* getMeshInterface() + { + return m_meshInterface; + } + + const btStridingMeshInterface* getMeshInterface() const + { + return m_meshInterface; + } + + const btVector3& getLocalAabbMin() const + { + return m_localAabbMin; + } + const btVector3& getLocalAabbMax() const + { + return m_localAabbMax; + } + + + + //debugging + virtual const char* getName()const {return "TRIANGLEMESH";} + + + +}; + + + + +#endif //BT_TRIANGLE_MESH_SHAPE_H diff --git a/src/BulletCollision/CollisionShapes/btTriangleShape.h b/src/BulletCollision/CollisionShapes/btTriangleShape.h new file mode 100644 index 0000000..71b0557 --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btTriangleShape.h @@ -0,0 +1,182 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_OBB_TRIANGLE_MINKOWSKI_H +#define BT_OBB_TRIANGLE_MINKOWSKI_H + +#include "btConvexShape.h" +#include "btBoxShape.h" + +ATTRIBUTE_ALIGNED16(class) btTriangleShape : public btPolyhedralConvexShape +{ + + +public: + + btVector3 m_vertices1[3]; + + virtual int getNumVertices() const + { + return 3; + } + + btVector3& getVertexPtr(int index) + { + return m_vertices1[index]; + } + + const btVector3& getVertexPtr(int index) const + { + return m_vertices1[index]; + } + virtual void getVertex(int index,btVector3& vert) const + { + vert = m_vertices1[index]; + } + + virtual int getNumEdges() const + { + return 3; + } + + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const + { + getVertex(i,pa); + getVertex((i+1)%3,pb); + } + + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax)const + { +// btAssert(0); + getAabbSlow(t,aabbMin,aabbMax); + } + + btVector3 localGetSupportingVertexWithoutMargin(const btVector3& dir)const + { + btVector3 dots(dir.dot(m_vertices1[0]), dir.dot(m_vertices1[1]), dir.dot(m_vertices1[2])); + return m_vertices1[dots.maxAxis()]; + + } + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const + { + for (int i=0;i= -tolerance && dist <= tolerance) + { + //inside check on edge-planes + int i; + for (i=0;i<3;i++) + { + btVector3 pa,pb; + getEdge(i,pa,pb); + btVector3 edge = pb-pa; + btVector3 edgeNormal = edge.cross(normal); + edgeNormal.normalize(); + btScalar dist = pt.dot( edgeNormal); + btScalar edgeConst = pa.dot(edgeNormal); + dist -= edgeConst; + if (dist < -tolerance) + return false; + } + + return true; + } + + return false; + } + //debugging + virtual const char* getName()const + { + return "Triangle"; + } + + virtual int getNumPreferredPenetrationDirections() const + { + return 2; + } + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const + { + calcNormal(penetrationVector); + if (index) + penetrationVector *= btScalar(-1.); + } + + +}; + +#endif //BT_OBB_TRIANGLE_MINKOWSKI_H + diff --git a/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp b/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp new file mode 100644 index 0000000..b148bbd --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp @@ -0,0 +1,160 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btUniformScalingShape.h" + +btUniformScalingShape::btUniformScalingShape( btConvexShape* convexChildShape,btScalar uniformScalingFactor): +btConvexShape (), m_childConvexShape(convexChildShape), +m_uniformScalingFactor(uniformScalingFactor) +{ + m_shapeType = UNIFORM_SCALING_SHAPE_PROXYTYPE; +} + +btUniformScalingShape::~btUniformScalingShape() +{ +} + + +btVector3 btUniformScalingShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + btVector3 tmpVertex; + tmpVertex = m_childConvexShape->localGetSupportingVertexWithoutMargin(vec); + return tmpVertex*m_uniformScalingFactor; +} + +void btUniformScalingShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors); + int i; + for (i=0;ilocalGetSupportingVertex(vec); + return tmpVertex*m_uniformScalingFactor; +} + + +void btUniformScalingShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + + ///this linear upscaling is not realistic, but we don't deal with large mass ratios... + btVector3 tmpInertia; + m_childConvexShape->calculateLocalInertia(mass,tmpInertia); + inertia = tmpInertia * m_uniformScalingFactor; +} + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version +void btUniformScalingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + getAabbSlow(trans,aabbMin,aabbMax); + +} + +void btUniformScalingShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ +#if 1 + btVector3 _directions[] = + { + btVector3( 1., 0., 0.), + btVector3( 0., 1., 0.), + btVector3( 0., 0., 1.), + btVector3( -1., 0., 0.), + btVector3( 0., -1., 0.), + btVector3( 0., 0., -1.) + }; + + btVector3 _supporting[] = + { + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.) + }; + + for (int i=0;i<6;i++) + { + _directions[i] = _directions[i]*t.getBasis(); + } + + batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6); + + btVector3 aabbMin1(0,0,0),aabbMax1(0,0,0); + + for ( int i = 0; i < 3; ++i ) + { + aabbMax1[i] = t(_supporting[i])[i]; + aabbMin1[i] = t(_supporting[i + 3])[i]; + } + btVector3 marginVec(getMargin(),getMargin(),getMargin()); + aabbMin = aabbMin1-marginVec; + aabbMax = aabbMax1+marginVec; + +#else + + btScalar margin = getMargin(); + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + btVector3 sv = localGetSupportingVertex(vec*t.getBasis()); + btVector3 tmp = t(sv); + aabbMax[i] = tmp[i]+margin; + vec[i] = btScalar(-1.); + sv = localGetSupportingVertex(vec*t.getBasis()); + tmp = t(sv); + aabbMin[i] = tmp[i]-margin; + } + +#endif +} + +void btUniformScalingShape::setLocalScaling(const btVector3& scaling) +{ + m_childConvexShape->setLocalScaling(scaling); +} + +const btVector3& btUniformScalingShape::getLocalScaling() const +{ + return m_childConvexShape->getLocalScaling(); +} + +void btUniformScalingShape::setMargin(btScalar margin) +{ + m_childConvexShape->setMargin(margin); +} +btScalar btUniformScalingShape::getMargin() const +{ + return m_childConvexShape->getMargin() * m_uniformScalingFactor; +} + +int btUniformScalingShape::getNumPreferredPenetrationDirections() const +{ + return m_childConvexShape->getNumPreferredPenetrationDirections(); +} + +void btUniformScalingShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const +{ + m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector); +} diff --git a/src/BulletCollision/CollisionShapes/btUniformScalingShape.h b/src/BulletCollision/CollisionShapes/btUniformScalingShape.h new file mode 100644 index 0000000..cbf7e6f --- /dev/null +++ b/src/BulletCollision/CollisionShapes/btUniformScalingShape.h @@ -0,0 +1,87 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_UNIFORM_SCALING_SHAPE_H +#define BT_UNIFORM_SCALING_SHAPE_H + +#include "btConvexShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types + +///The btUniformScalingShape allows to re-use uniform scaled instances of btConvexShape in a memory efficient way. +///Istead of using btUniformScalingShape, it is better to use the non-uniform setLocalScaling method on convex shapes that implement it. +class btUniformScalingShape : public btConvexShape +{ + btConvexShape* m_childConvexShape; + + btScalar m_uniformScalingFactor; + + public: + + btUniformScalingShape( btConvexShape* convexChildShape, btScalar uniformScalingFactor); + + virtual ~btUniformScalingShape(); + + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + btScalar getUniformScalingFactor() const + { + return m_uniformScalingFactor; + } + + btConvexShape* getChildShape() + { + return m_childConvexShape; + } + + const btConvexShape* getChildShape() const + { + return m_childConvexShape; + } + + virtual const char* getName()const + { + return "UniformScalingShape"; + } + + + + /////////////////////////// + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void setLocalScaling(const btVector3& scaling) ; + virtual const btVector3& getLocalScaling() const ; + + virtual void setMargin(btScalar margin); + virtual btScalar getMargin() const; + + virtual int getNumPreferredPenetrationDirections() const; + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const; + + +}; + +#endif //BT_UNIFORM_SCALING_SHAPE_H diff --git a/src/BulletCollision/Doxyfile b/src/BulletCollision/Doxyfile new file mode 100644 index 0000000..4ecb6ac --- /dev/null +++ b/src/BulletCollision/Doxyfile @@ -0,0 +1,746 @@ +# Doxyfile 1.2.4 + +# This file describes the settings to be used by doxygen for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. +PROJECT_NAME = "Bullet Continuous Collision Detection Library" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese, +# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian, +# Polish, Portuguese and Slovene. + +OUTPUT_LANGUAGE = English + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these class will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a class diagram (in Html and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. + +CLASS_DIAGRAMS = YES + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower case letters. If set to YES upper case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are adviced to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explict @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# reimplements. + +INHERIT_DOCS = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# The ENABLE_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . + + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +FILE_PATTERNS = *.h *.cpp *.c + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse. + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript and frames is required (for instance Netscape 4.0+ +# or Internet explorer 4.0+). + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimised for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using a WORD or other. +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assigments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. Warning: This feature +# is still experimental and very incomplete. + +GENERATE_XML = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = ../../generic/extern + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tagfiles. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to +# YES then doxygen will generate a graph for each documented file showing +# the direct and indirect include dependencies of the file with other +# documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to +# YES then doxygen will generate a graph for each documented header file showing +# the documented files that directly or indirectly include this file + +INCLUDED_BY_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO + +# The CGI_NAME tag should be the name of the CGI script that +# starts the search engine (doxysearch) with the correct parameters. +# A script with this name will be generated by doxygen. + +CGI_NAME = search.cgi + +# The CGI_URL tag should be the absolute URL to the directory where the +# cgi binaries are located. See the documentation of your http daemon for +# details. + +CGI_URL = + +# The DOC_URL tag should be the absolute URL to the directory where the +# documentation is located. If left blank the absolute path to the +# documentation, with file:// prepended to it, will be used. + +DOC_URL = + +# The DOC_ABSPATH tag should be the absolute path to the directory where the +# documentation is located. If left blank the directory on the local machine +# will be used. + +DOC_ABSPATH = + +# The BIN_ABSPATH tag must point to the directory where the doxysearch binary +# is installed. + +BIN_ABSPATH = c:\program files\doxygen\bin + +# The EXT_DOC_PATHS tag can be used to specify one or more paths to +# documentation generated for other projects. This allows doxysearch to search +# the documentation for these projects as well. + +EXT_DOC_PATHS = diff --git a/src/BulletCollision/Gimpact/btBoxCollision.h b/src/BulletCollision/Gimpact/btBoxCollision.h new file mode 100644 index 0000000..d5676aa --- /dev/null +++ b/src/BulletCollision/Gimpact/btBoxCollision.h @@ -0,0 +1,647 @@ +#ifndef BT_BOX_COLLISION_H_INCLUDED +#define BT_BOX_COLLISION_H_INCLUDED + +/*! \file gim_box_collision.h +\author Francisco Leon Najera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "LinearMath/btTransform.h" + + +///Swap numbers +#define BT_SWAP_NUMBERS(a,b){ \ + a = a+b; \ + b = a-b; \ + a = a-b; \ +}\ + + +#define BT_MAX(a,b) (ab?b:a) + +#define BT_GREATER(x, y) btFabs(x) > (y) + +#define BT_MAX3(a,b,c) BT_MAX(a,BT_MAX(b,c)) +#define BT_MIN3(a,b,c) BT_MIN(a,BT_MIN(b,c)) + + + + + + +enum eBT_PLANE_INTERSECTION_TYPE +{ + BT_CONST_BACK_PLANE = 0, + BT_CONST_COLLIDE_PLANE, + BT_CONST_FRONT_PLANE +}; + +//SIMD_FORCE_INLINE bool test_cross_edge_box( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, const btVector3 & extend, +// int dir_index0, +// int dir_index1 +// int component_index0, +// int component_index1) +//{ +// // dir coords are -z and y +// +// const btScalar dir0 = -edge[dir_index0]; +// const btScalar dir1 = edge[dir_index1]; +// btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1; +// btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1; +// //find minmax +// if(pmin>pmax) +// { +// BT_SWAP_NUMBERS(pmin,pmax); +// } +// //find extends +// const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] + +// extend[component_index1] * absolute_edge[dir_index1]; +// +// if(pmin>rad || -rad>pmax) return false; +// return true; +//} +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2); +//} +// +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0); +//} +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1); +//} + + +#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\ +{\ + const btScalar dir0 = -edge[i_dir_0];\ + const btScalar dir1 = edge[i_dir_1];\ + btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\ + btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\ + if(pmin>pmax)\ + {\ + BT_SWAP_NUMBERS(pmin,pmax); \ + }\ + const btScalar abs_dir0 = absolute_edge[i_dir_0];\ + const btScalar abs_dir1 = absolute_edge[i_dir_1];\ + const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\ + if(pmin>rad || -rad>pmax) return false;\ +}\ + + +#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\ +}\ + +#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\ +}\ + +#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\ +}\ + + +//! Returns the dot product between a vec3f and the col of a matrix +SIMD_FORCE_INLINE btScalar bt_mat3_dot_col( +const btMatrix3x3 & mat, const btVector3 & vec3, int colindex) +{ + return vec3[0]*mat[0][colindex] + vec3[1]*mat[1][colindex] + vec3[2]*mat[2][colindex]; +} + + +//! Class for transforming a model1 to the space of model0 +ATTRIBUTE_ALIGNED16 (class) BT_BOX_BOX_TRANSFORM_CACHE +{ +public: + btVector3 m_T1to0;//!< Transforms translation of model1 to model 0 + btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal to R0' * R1 + btMatrix3x3 m_AR;//!< Absolute value of m_R1to0 + + SIMD_FORCE_INLINE void calc_absolute_matrix() + { +// static const btVector3 vepsi(1e-6f,1e-6f,1e-6f); +// m_AR[0] = vepsi + m_R1to0[0].absolute(); +// m_AR[1] = vepsi + m_R1to0[1].absolute(); +// m_AR[2] = vepsi + m_R1to0[2].absolute(); + + int i,j; + + for(i=0;i<3;i++) + { + for(j=0;j<3;j++ ) + { + m_AR[i][j] = 1e-6f + btFabs(m_R1to0[i][j]); + } + } + + } + + BT_BOX_BOX_TRANSFORM_CACHE() + { + } + + + + //! Calc the transformation relative 1 to 0. Inverts matrics by transposing + SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1) + { + + btTransform temp_trans = trans0.inverse(); + temp_trans = temp_trans * trans1; + + m_T1to0 = temp_trans.getOrigin(); + m_R1to0 = temp_trans.getBasis(); + + + calc_absolute_matrix(); + } + + //! Calcs the full invertion of the matrices. Useful for scaling matrices + SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1) + { + m_R1to0 = trans0.getBasis().inverse(); + m_T1to0 = m_R1to0 * (-trans0.getOrigin()); + + m_T1to0 += m_R1to0*trans1.getOrigin(); + m_R1to0 *= trans1.getBasis(); + + calc_absolute_matrix(); + } + + SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point) const + { + return btVector3(m_R1to0[0].dot(point) + m_T1to0.x(), + m_R1to0[1].dot(point) + m_T1to0.y(), + m_R1to0[2].dot(point) + m_T1to0.z()); + } +}; + + +#define BOX_PLANE_EPSILON 0.000001f + +//! Axis aligned box +ATTRIBUTE_ALIGNED16 (class) btAABB +{ +public: + btVector3 m_min; + btVector3 m_max; + + btAABB() + {} + + + btAABB(const btVector3 & V1, + const btVector3 & V2, + const btVector3 & V3) + { + m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]); + } + + btAABB(const btVector3 & V1, + const btVector3 & V2, + const btVector3 & V3, + btScalar margin) + { + m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]); + + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + btAABB(const btAABB &other): + m_min(other.m_min),m_max(other.m_max) + { + } + + btAABB(const btAABB &other,btScalar margin ): + m_min(other.m_min),m_max(other.m_max) + { + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + SIMD_FORCE_INLINE void invalidate() + { + m_min[0] = SIMD_INFINITY; + m_min[1] = SIMD_INFINITY; + m_min[2] = SIMD_INFINITY; + m_max[0] = -SIMD_INFINITY; + m_max[1] = -SIMD_INFINITY; + m_max[2] = -SIMD_INFINITY; + } + + SIMD_FORCE_INLINE void increment_margin(btScalar margin) + { + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + SIMD_FORCE_INLINE void copy_with_margin(const btAABB &other, btScalar margin) + { + m_min[0] = other.m_min[0] - margin; + m_min[1] = other.m_min[1] - margin; + m_min[2] = other.m_min[2] - margin; + + m_max[0] = other.m_max[0] + margin; + m_max[1] = other.m_max[1] + margin; + m_max[2] = other.m_max[2] + margin; + } + + template + SIMD_FORCE_INLINE void calc_from_triangle( + const CLASS_POINT & V1, + const CLASS_POINT & V2, + const CLASS_POINT & V3) + { + m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]); + } + + template + SIMD_FORCE_INLINE void calc_from_triangle_margin( + const CLASS_POINT & V1, + const CLASS_POINT & V2, + const CLASS_POINT & V3, btScalar margin) + { + m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]); + + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + //! Apply a transform to an AABB + SIMD_FORCE_INLINE void appy_transform(const btTransform & trans) + { + btVector3 center = (m_max+m_min)*0.5f; + btVector3 extends = m_max - center; + // Compute new center + center = trans(center); + + btVector3 textends(extends.dot(trans.getBasis().getRow(0).absolute()), + extends.dot(trans.getBasis().getRow(1).absolute()), + extends.dot(trans.getBasis().getRow(2).absolute())); + + m_min = center - textends; + m_max = center + textends; + } + + + //! Apply a transform to an AABB + SIMD_FORCE_INLINE void appy_transform_trans_cache(const BT_BOX_BOX_TRANSFORM_CACHE & trans) + { + btVector3 center = (m_max+m_min)*0.5f; + btVector3 extends = m_max - center; + // Compute new center + center = trans.transform(center); + + btVector3 textends(extends.dot(trans.m_R1to0.getRow(0).absolute()), + extends.dot(trans.m_R1to0.getRow(1).absolute()), + extends.dot(trans.m_R1to0.getRow(2).absolute())); + + m_min = center - textends; + m_max = center + textends; + } + + //! Merges a Box + SIMD_FORCE_INLINE void merge(const btAABB & box) + { + m_min[0] = BT_MIN(m_min[0],box.m_min[0]); + m_min[1] = BT_MIN(m_min[1],box.m_min[1]); + m_min[2] = BT_MIN(m_min[2],box.m_min[2]); + + m_max[0] = BT_MAX(m_max[0],box.m_max[0]); + m_max[1] = BT_MAX(m_max[1],box.m_max[1]); + m_max[2] = BT_MAX(m_max[2],box.m_max[2]); + } + + //! Merges a point + template + SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point) + { + m_min[0] = BT_MIN(m_min[0],point[0]); + m_min[1] = BT_MIN(m_min[1],point[1]); + m_min[2] = BT_MIN(m_min[2],point[2]); + + m_max[0] = BT_MAX(m_max[0],point[0]); + m_max[1] = BT_MAX(m_max[1],point[1]); + m_max[2] = BT_MAX(m_max[2],point[2]); + } + + //! Gets the extend and center + SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const + { + center = (m_max+m_min)*0.5f; + extend = m_max - center; + } + + //! Finds the intersecting box between this box and the other. + SIMD_FORCE_INLINE void find_intersection(const btAABB & other, btAABB & intersection) const + { + intersection.m_min[0] = BT_MAX(other.m_min[0],m_min[0]); + intersection.m_min[1] = BT_MAX(other.m_min[1],m_min[1]); + intersection.m_min[2] = BT_MAX(other.m_min[2],m_min[2]); + + intersection.m_max[0] = BT_MIN(other.m_max[0],m_max[0]); + intersection.m_max[1] = BT_MIN(other.m_max[1],m_max[1]); + intersection.m_max[2] = BT_MIN(other.m_max[2],m_max[2]); + } + + + SIMD_FORCE_INLINE bool has_collision(const btAABB & other) const + { + if(m_min[0] > other.m_max[0] || + m_max[0] < other.m_min[0] || + m_min[1] > other.m_max[1] || + m_max[1] < other.m_min[1] || + m_min[2] > other.m_max[2] || + m_max[2] < other.m_min[2]) + { + return false; + } + return true; + } + + /*! \brief Finds the Ray intersection parameter. + \param aabb Aligned box + \param vorigin A vec3f with the origin of the ray + \param vdir A vec3f with the direction of the ray + */ + SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir) const + { + btVector3 extents,center; + this->get_center_extend(center,extents);; + + btScalar Dx = vorigin[0] - center[0]; + if(BT_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false; + btScalar Dy = vorigin[1] - center[1]; + if(BT_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false; + btScalar Dz = vorigin[2] - center[2]; + if(BT_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false; + + + btScalar f = vdir[1] * Dz - vdir[2] * Dy; + if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false; + f = vdir[2] * Dx - vdir[0] * Dz; + if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false; + f = vdir[0] * Dy - vdir[1] * Dx; + if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false; + return true; + } + + + SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const + { + btVector3 center = (m_max+m_min)*0.5f; + btVector3 extend = m_max-center; + + btScalar _fOrigin = direction.dot(center); + btScalar _fMaximumExtent = extend.dot(direction.absolute()); + vmin = _fOrigin - _fMaximumExtent; + vmax = _fOrigin + _fMaximumExtent; + } + + SIMD_FORCE_INLINE eBT_PLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const + { + btScalar _fmin,_fmax; + this->projection_interval(plane,_fmin,_fmax); + + if(plane[3] > _fmax + BOX_PLANE_EPSILON) + { + return BT_CONST_BACK_PLANE; // 0 + } + + if(plane[3]+BOX_PLANE_EPSILON >=_fmin) + { + return BT_CONST_COLLIDE_PLANE; //1 + } + return BT_CONST_FRONT_PLANE;//2 + } + + SIMD_FORCE_INLINE bool overlapping_trans_conservative(const btAABB & box, btTransform & trans1_to_0) const + { + btAABB tbox = box; + tbox.appy_transform(trans1_to_0); + return has_collision(tbox); + } + + SIMD_FORCE_INLINE bool overlapping_trans_conservative2(const btAABB & box, + const BT_BOX_BOX_TRANSFORM_CACHE & trans1_to_0) const + { + btAABB tbox = box; + tbox.appy_transform_trans_cache(trans1_to_0); + return has_collision(tbox); + } + + //! transcache is the transformation cache from box to this AABB + SIMD_FORCE_INLINE bool overlapping_trans_cache( + const btAABB & box,const BT_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest) const + { + + //Taken from OPCODE + btVector3 ea,eb;//extends + btVector3 ca,cb;//extends + get_center_extend(ca,ea); + box.get_center_extend(cb,eb); + + + btVector3 T; + btScalar t,t2; + int i; + + // Class I : A's basis vectors + for(i=0;i<3;i++) + { + T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i]; + t = transcache.m_AR[i].dot(eb) + ea[i]; + if(BT_GREATER(T[i], t)) return false; + } + // Class II : B's basis vectors + for(i=0;i<3;i++) + { + t = bt_mat3_dot_col(transcache.m_R1to0,T,i); + t2 = bt_mat3_dot_col(transcache.m_AR,ea,i) + eb[i]; + if(BT_GREATER(t,t2)) return false; + } + // Class III : 9 cross products + if(fulltest) + { + int j,m,n,o,p,q,r; + for(i=0;i<3;i++) + { + m = (i+1)%3; + n = (i+2)%3; + o = i==0?1:0; + p = i==2?1:2; + for(j=0;j<3;j++) + { + q = j==2?1:2; + r = j==0?1:0; + t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j]; + t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] + + eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r]; + if(BT_GREATER(t,t2)) return false; + } + } + } + return true; + } + + //! Simple test for planes. + SIMD_FORCE_INLINE bool collide_plane( + const btVector4 & plane) const + { + eBT_PLANE_INTERSECTION_TYPE classify = plane_classify(plane); + return (classify == BT_CONST_COLLIDE_PLANE); + } + + //! test for a triangle, with edges + SIMD_FORCE_INLINE bool collide_triangle_exact( + const btVector3 & p1, + const btVector3 & p2, + const btVector3 & p3, + const btVector4 & triangle_plane) const + { + if(!collide_plane(triangle_plane)) return false; + + btVector3 center,extends; + this->get_center_extend(center,extends); + + const btVector3 v1(p1 - center); + const btVector3 v2(p2 - center); + const btVector3 v3(p3 - center); + + //First axis + btVector3 diff(v2 - v1); + btVector3 abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends); + + + diff = v3 - v2; + abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends); + + diff = v1 - v3; + abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends); + + return true; + } +}; + + +//! Compairison of transformation objects +SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2) +{ + if(!(t1.getOrigin() == t2.getOrigin()) ) return false; + + if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false; + if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false; + if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false; + return true; +} + + + +#endif // GIM_BOX_COLLISION_H_INCLUDED diff --git a/src/BulletCollision/Gimpact/btClipPolygon.h b/src/BulletCollision/Gimpact/btClipPolygon.h new file mode 100644 index 0000000..de0a523 --- /dev/null +++ b/src/BulletCollision/Gimpact/btClipPolygon.h @@ -0,0 +1,182 @@ +#ifndef BT_CLIP_POLYGON_H_INCLUDED +#define BT_CLIP_POLYGON_H_INCLUDED + +/*! \file btClipPolygon.h +\author Francisco Leon Najera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "LinearMath/btTransform.h" +#include "LinearMath/btGeometryUtil.h" + + +SIMD_FORCE_INLINE btScalar bt_distance_point_plane(const btVector4 & plane,const btVector3 &point) +{ + return point.dot(plane) - plane[3]; +} + +/*! Vector blending +Takes two vectors a, b, blends them together*/ +SIMD_FORCE_INLINE void bt_vec_blend(btVector3 &vr, const btVector3 &va,const btVector3 &vb, btScalar blend_factor) +{ + vr = (1-blend_factor)*va + blend_factor*vb; +} + +//! This function calcs the distance from a 3D plane +SIMD_FORCE_INLINE void bt_plane_clip_polygon_collect( + const btVector3 & point0, + const btVector3 & point1, + btScalar dist0, + btScalar dist1, + btVector3 * clipped, + int & clipped_count) +{ + bool _prevclassif = (dist0>SIMD_EPSILON); + bool _classif = (dist1>SIMD_EPSILON); + if(_classif!=_prevclassif) + { + btScalar blendfactor = -dist0/(dist1-dist0); + bt_vec_blend(clipped[clipped_count],point0,point1,blendfactor); + clipped_count++; + } + if(!_classif) + { + clipped[clipped_count] = point1; + clipped_count++; + } +} + + +//! Clips a polygon by a plane +/*! +*\return The count of the clipped counts +*/ +SIMD_FORCE_INLINE int bt_plane_clip_polygon( + const btVector4 & plane, + const btVector3 * polygon_points, + int polygon_point_count, + btVector3 * clipped) +{ + int clipped_count = 0; + + + //clip first point + btScalar firstdist = bt_distance_point_plane(plane,polygon_points[0]);; + if(!(firstdist>SIMD_EPSILON)) + { + clipped[clipped_count] = polygon_points[0]; + clipped_count++; + } + + btScalar olddist = firstdist; + for(int i=1;iSIMD_EPSILON)) + { + clipped[clipped_count] = point0; + clipped_count++; + } + + // point 1 + btScalar olddist = firstdist; + btScalar dist = bt_distance_point_plane(plane,point1); + + bt_plane_clip_polygon_collect( + point0,point1, + olddist, + dist, + clipped, + clipped_count); + + olddist = dist; + + + // point 2 + dist = bt_distance_point_plane(plane,point2); + + bt_plane_clip_polygon_collect( + point1,point2, + olddist, + dist, + clipped, + clipped_count); + olddist = dist; + + + + //RETURN TO FIRST point0 + bt_plane_clip_polygon_collect( + point2,point0, + olddist, + firstdist, + clipped, + clipped_count); + + return clipped_count; +} + + + + + +#endif // GIM_TRI_COLLISION_H_INCLUDED diff --git a/src/BulletCollision/Gimpact/btContactProcessing.cpp b/src/BulletCollision/Gimpact/btContactProcessing.cpp new file mode 100644 index 0000000..eed31d8 --- /dev/null +++ b/src/BulletCollision/Gimpact/btContactProcessing.cpp @@ -0,0 +1,181 @@ + +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +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 "btContactProcessing.h" + +#define MAX_COINCIDENT 8 + +struct CONTACT_KEY_TOKEN +{ + unsigned int m_key; + int m_value; + CONTACT_KEY_TOKEN() + { + } + + CONTACT_KEY_TOKEN(unsigned int key,int token) + { + m_key = key; + m_value = token; + } + + CONTACT_KEY_TOKEN(const CONTACT_KEY_TOKEN& rtoken) + { + m_key = rtoken.m_key; + m_value = rtoken.m_value; + } + + inline bool operator <(const CONTACT_KEY_TOKEN& other) const + { + return (m_key < other.m_key); + } + + inline bool operator >(const CONTACT_KEY_TOKEN& other) const + { + return (m_key > other.m_key); + } + +}; + +class CONTACT_KEY_TOKEN_COMP +{ + public: + + bool operator() ( const CONTACT_KEY_TOKEN& a, const CONTACT_KEY_TOKEN& b ) const + { + return ( a < b ); + } +}; + + +void btContactArray::merge_contacts( + const btContactArray & contacts, bool normal_contact_average) +{ + clear(); + + int i; + if(contacts.size()==0) return; + + + if(contacts.size()==1) + { + push_back(contacts[0]); + return; + } + + btAlignedObjectArray keycontacts; + + keycontacts.reserve(contacts.size()); + + //fill key contacts + + for ( i = 0;im_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//) + { + *pcontact = *scontact; + coincident_count = 0; + } + else if(normal_contact_average) + { + if(btFabs(pcontact->m_depth - scontact->m_depth)m_normal; + coincident_count++; + } + } + } + } + else + {//add new contact + + if(normal_contact_average && coincident_count>0) + { + pcontact->interpolate_normals(coincident_normals,coincident_count); + coincident_count = 0; + } + + push_back(*scontact); + pcontact = &(*this)[this->size()-1]; + } + last_key = key; + } +} + +void btContactArray::merge_contacts_unique(const btContactArray & contacts) +{ + clear(); + + if(contacts.size()==0) return; + + if(contacts.size()==1) + { + push_back(contacts[0]); + return; + } + + GIM_CONTACT average_contact = contacts[0]; + + for (int i=1;i +{ +public: + btContactArray() + { + reserve(64); + } + + SIMD_FORCE_INLINE void push_contact( + const btVector3 &point,const btVector3 & normal, + btScalar depth, int feature1, int feature2) + { + push_back( GIM_CONTACT(point,normal,depth,feature1,feature2) ); + } + + SIMD_FORCE_INLINE void push_triangle_contacts( + const GIM_TRIANGLE_CONTACT & tricontact, + int feature1,int feature2) + { + for(int i = 0;i splitValue) + { + //swap + primitive_boxes.swap(i,splitIndex); + //swapLeafNodes(i,splitIndex); + splitIndex++; + } + } + + //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex + //otherwise the tree-building might fail due to stack-overflows in certain cases. + //unbalanced1 is unsafe: it can cause stack overflows + //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); + + //unbalanced2 should work too: always use center (perfect balanced trees) + //bool unbalanced2 = true; + + //this should be safe too: + int rangeBalancedIndices = numIndices/3; + bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); + + if (unbalanced) + { + splitIndex = startIndex+ (numIndices>>1); + } + + btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex)))); + + return splitIndex; + +} + + +void btBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex) +{ + int curIndex = m_num_nodes; + m_num_nodes++; + + btAssert((endIndex-startIndex)>0); + + if ((endIndex-startIndex)==1) + { + //We have a leaf node + setNodeBound(curIndex,primitive_boxes[startIndex].m_bound); + m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data); + + return; + } + //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. + + //split axis + int splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex); + + splitIndex = _sort_and_calc_splitting_index( + primitive_boxes,startIndex,endIndex, + splitIndex//split axis + ); + + + //calc this node bounding box + + btAABB node_bound; + node_bound.invalidate(); + + for (int i=startIndex;iget_primitive_box(getNodeData(nodecount),leafbox); + setNodeBound(nodecount,leafbox); + } + else + { + //const GIM_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount); + //get left bound + btAABB bound; + bound.invalidate(); + + btAABB temp_box; + + int child_node = getLeftNode(nodecount); + if(child_node) + { + getNodeBound(child_node,temp_box); + bound.merge(temp_box); + } + + child_node = getRightNode(nodecount); + if(child_node) + { + getNodeBound(child_node,temp_box); + bound.merge(temp_box); + } + + setNodeBound(nodecount,bound); + } + } +} + +//! this rebuild the entire set +void btGImpactBvh::buildSet() +{ + //obtain primitive boxes + GIM_BVH_DATA_ARRAY primitive_boxes; + primitive_boxes.resize(m_primitive_manager->get_primitive_count()); + + for (int i = 0;iget_primitive_box(i,primitive_boxes[i].m_bound); + primitive_boxes[i].m_data = i; + } + + m_box_tree.build_tree(primitive_boxes); +} + +//! returns the indices of the primitives in the m_primitive_manager +bool btGImpactBvh::boxQuery(const btAABB & box, btAlignedObjectArray & collided_results) const +{ + int curIndex = 0; + int numNodes = getNodeCount(); + + while (curIndex < numNodes) + { + btAABB bound; + getNodeBound(curIndex,bound); + + //catch bugs in tree data + + bool aabbOverlap = bound.has_collision(box); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData(curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getEscapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; +} + + + +//! returns the indices of the primitives in the m_primitive_manager +bool btGImpactBvh::rayQuery( + const btVector3 & ray_dir,const btVector3 & ray_origin , + btAlignedObjectArray & collided_results) const +{ + int curIndex = 0; + int numNodes = getNodeCount(); + + while (curIndex < numNodes) + { + btAABB bound; + getNodeBound(curIndex,bound); + + //catch bugs in tree data + + bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData( curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getEscapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; +} + + +SIMD_FORCE_INLINE bool _node_collision( + btGImpactBvh * boxset0, btGImpactBvh * boxset1, + const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0, + int node0 ,int node1, bool complete_primitive_tests) +{ + btAABB box0; + boxset0->getNodeBound(node0,box0); + btAABB box1; + boxset1->getNodeBound(node1,box1); + + return box0.overlapping_trans_cache(box1,trans_cache_1to0,complete_primitive_tests ); +// box1.appy_transform_trans_cache(trans_cache_1to0); +// return box0.has_collision(box1); + +} + + +//stackless recursive collision routine +static void _find_collision_pairs_recursive( + btGImpactBvh * boxset0, btGImpactBvh * boxset1, + btPairSet * collision_pairs, + const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0, + int node0, int node1, bool complete_primitive_tests) +{ + + + + if( _node_collision( + boxset0,boxset1,trans_cache_1to0, + node0,node1,complete_primitive_tests) ==false) return;//avoid colliding internal nodes + + if(boxset0->isLeafNode(node0)) + { + if(boxset1->isLeafNode(node1)) + { + // collision result + collision_pairs->push_pair( + boxset0->getNodeData(node0),boxset1->getNodeData(node1)); + return; + } + else + { + + //collide left recursive + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + node0,boxset1->getLeftNode(node1),false); + + //collide right recursive + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + node0,boxset1->getRightNode(node1),false); + + + } + } + else + { + if(boxset1->isLeafNode(node1)) + { + + //collide left recursive + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),node1,false); + + + //collide right recursive + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),node1,false); + + + } + else + { + //collide left0 left1 + + + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),boxset1->getLeftNode(node1),false); + + //collide left0 right1 + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),boxset1->getRightNode(node1),false); + + + //collide right0 left1 + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),boxset1->getLeftNode(node1),false); + + //collide right0 right1 + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),boxset1->getRightNode(node1),false); + + }// else if node1 is not a leaf + }// else if node0 is not a leaf +} + + +void btGImpactBvh::find_collision(btGImpactBvh * boxset0, const btTransform & trans0, + btGImpactBvh * boxset1, const btTransform & trans1, + btPairSet & collision_pairs) +{ + + if(boxset0->getNodeCount()==0 || boxset1->getNodeCount()==0 ) return; + + BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0; + + trans_cache_1to0.calc_from_homogenic(trans0,trans1); + +#ifdef TRI_COLLISION_PROFILING + bt_begin_gim02_tree_time(); +#endif //TRI_COLLISION_PROFILING + + _find_collision_pairs_recursive( + boxset0,boxset1, + &collision_pairs,trans_cache_1to0,0,0,true); +#ifdef TRI_COLLISION_PROFILING + bt_end_gim02_tree_time(); +#endif //TRI_COLLISION_PROFILING + +} + diff --git a/src/BulletCollision/Gimpact/btGImpactBvh.h b/src/BulletCollision/Gimpact/btGImpactBvh.h new file mode 100644 index 0000000..6174ae9 --- /dev/null +++ b/src/BulletCollision/Gimpact/btGImpactBvh.h @@ -0,0 +1,396 @@ +#ifndef GIM_BOX_SET_H_INCLUDED +#define GIM_BOX_SET_H_INCLUDED + +/*! \file gim_box_set.h +\author Francisco Leon Najera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "LinearMath/btAlignedObjectArray.h" + +#include "btBoxCollision.h" +#include "btTriangleShapeEx.h" + + + + + +//! Overlapping pair +struct GIM_PAIR +{ + int m_index1; + int m_index2; + GIM_PAIR() + {} + + GIM_PAIR(const GIM_PAIR & p) + { + m_index1 = p.m_index1; + m_index2 = p.m_index2; + } + + GIM_PAIR(int index1, int index2) + { + m_index1 = index1; + m_index2 = index2; + } +}; + +//! A pairset array +class btPairSet: public btAlignedObjectArray +{ +public: + btPairSet() + { + reserve(32); + } + inline void push_pair(int index1,int index2) + { + push_back(GIM_PAIR(index1,index2)); + } + + inline void push_pair_inv(int index1,int index2) + { + push_back(GIM_PAIR(index2,index1)); + } +}; + + +///GIM_BVH_DATA is an internal GIMPACT collision structure to contain axis aligned bounding box +struct GIM_BVH_DATA +{ + btAABB m_bound; + int m_data; +}; + +//! Node Structure for trees +class GIM_BVH_TREE_NODE +{ +public: + btAABB m_bound; +protected: + int m_escapeIndexOrDataIndex; +public: + GIM_BVH_TREE_NODE() + { + m_escapeIndexOrDataIndex = 0; + } + + SIMD_FORCE_INLINE bool isLeafNode() const + { + //skipindex is negative (internal node), triangleindex >=0 (leafnode) + return (m_escapeIndexOrDataIndex>=0); + } + + SIMD_FORCE_INLINE int getEscapeIndex() const + { + //btAssert(m_escapeIndexOrDataIndex < 0); + return -m_escapeIndexOrDataIndex; + } + + SIMD_FORCE_INLINE void setEscapeIndex(int index) + { + m_escapeIndexOrDataIndex = -index; + } + + SIMD_FORCE_INLINE int getDataIndex() const + { + //btAssert(m_escapeIndexOrDataIndex >= 0); + + return m_escapeIndexOrDataIndex; + } + + SIMD_FORCE_INLINE void setDataIndex(int index) + { + m_escapeIndexOrDataIndex = index; + } + +}; + + +class GIM_BVH_DATA_ARRAY:public btAlignedObjectArray +{ +}; + + +class GIM_BVH_TREE_NODE_ARRAY:public btAlignedObjectArray +{ +}; + + + + +//! Basic Box tree structure +class btBvhTree +{ +protected: + int m_num_nodes; + GIM_BVH_TREE_NODE_ARRAY m_node_array; +protected: + int _sort_and_calc_splitting_index( + GIM_BVH_DATA_ARRAY & primitive_boxes, + int startIndex, int endIndex, int splitAxis); + + int _calc_splitting_axis(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); + + void _build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); +public: + btBvhTree() + { + m_num_nodes = 0; + } + + //! prototype functions for box tree management + //!@{ + void build_tree(GIM_BVH_DATA_ARRAY & primitive_boxes); + + SIMD_FORCE_INLINE void clearNodes() + { + m_node_array.clear(); + m_num_nodes = 0; + } + + //! node count + SIMD_FORCE_INLINE int getNodeCount() const + { + return m_num_nodes; + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const + { + return m_node_array[nodeindex].isLeafNode(); + } + + SIMD_FORCE_INLINE int getNodeData(int nodeindex) const + { + return m_node_array[nodeindex].getDataIndex(); + } + + SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const + { + bound = m_node_array[nodeindex].m_bound; + } + + SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound) + { + m_node_array[nodeindex].m_bound = bound; + } + + SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const + { + return nodeindex+1; + } + + SIMD_FORCE_INLINE int getRightNode(int nodeindex) const + { + if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2; + return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex(); + } + + SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const + { + return m_node_array[nodeindex].getEscapeIndex(); + } + + SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE * get_node_pointer(int index = 0) const + { + return &m_node_array[index]; + } + + //!@} +}; + + +//! Prototype Base class for primitive classification +/*! +This class is a wrapper for primitive collections. +This tells relevant info for the Bounding Box set classes, which take care of space classification. +This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons. +*/ +class btPrimitiveManagerBase +{ +public: + + virtual ~btPrimitiveManagerBase() {} + + //! determines if this manager consist on only triangles, which special case will be optimized + virtual bool is_trimesh() const = 0; + virtual int get_primitive_count() const = 0; + virtual void get_primitive_box(int prim_index ,btAABB & primbox) const = 0; + //! retrieves only the points of the triangle, and the collision margin + virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const= 0; +}; + + +//! Structure for containing Boxes +/*! +This class offers an structure for managing a box tree of primitives. +Requires a Primitive prototype (like btPrimitiveManagerBase ) +*/ +class btGImpactBvh +{ +protected: + btBvhTree m_box_tree; + btPrimitiveManagerBase * m_primitive_manager; + +protected: + //stackless refit + void refit(); +public: + + //! this constructor doesn't build the tree. you must call buildSet + btGImpactBvh() + { + m_primitive_manager = NULL; + } + + //! this constructor doesn't build the tree. you must call buildSet + btGImpactBvh(btPrimitiveManagerBase * primitive_manager) + { + m_primitive_manager = primitive_manager; + } + + SIMD_FORCE_INLINE btAABB getGlobalBox() const + { + btAABB totalbox; + getNodeBound(0, totalbox); + return totalbox; + } + + SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager) + { + m_primitive_manager = primitive_manager; + } + + SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const + { + return m_primitive_manager; + } + + +//! node manager prototype functions +///@{ + + //! this attemps to refit the box set. + SIMD_FORCE_INLINE void update() + { + refit(); + } + + //! this rebuild the entire set + void buildSet(); + + //! returns the indices of the primitives in the m_primitive_manager + bool boxQuery(const btAABB & box, btAlignedObjectArray & collided_results) const; + + //! returns the indices of the primitives in the m_primitive_manager + SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box, + const btTransform & transform, btAlignedObjectArray & collided_results) const + { + btAABB transbox=box; + transbox.appy_transform(transform); + return boxQuery(transbox,collided_results); + } + + //! returns the indices of the primitives in the m_primitive_manager + bool rayQuery( + const btVector3 & ray_dir,const btVector3 & ray_origin , + btAlignedObjectArray & collided_results) const; + + //! tells if this set has hierarcht + SIMD_FORCE_INLINE bool hasHierarchy() const + { + return true; + } + + //! tells if this set is a trimesh + SIMD_FORCE_INLINE bool isTrimesh() const + { + return m_primitive_manager->is_trimesh(); + } + + //! node count + SIMD_FORCE_INLINE int getNodeCount() const + { + return m_box_tree.getNodeCount(); + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const + { + return m_box_tree.isLeafNode(nodeindex); + } + + SIMD_FORCE_INLINE int getNodeData(int nodeindex) const + { + return m_box_tree.getNodeData(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const + { + m_box_tree.getNodeBound(nodeindex, bound); + } + + SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound) + { + m_box_tree.setNodeBound(nodeindex, bound); + } + + + SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const + { + return m_box_tree.getLeftNode(nodeindex); + } + + SIMD_FORCE_INLINE int getRightNode(int nodeindex) const + { + return m_box_tree.getRightNode(nodeindex); + } + + SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const + { + return m_box_tree.getEscapeNodeIndex(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const + { + m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle); + } + + + SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE * get_node_pointer(int index = 0) const + { + return m_box_tree.get_node_pointer(index); + } + +#ifdef TRI_COLLISION_PROFILING + static float getAverageTreeCollisionTime(); +#endif //TRI_COLLISION_PROFILING + + static void find_collision(btGImpactBvh * boxset1, const btTransform & trans1, + btGImpactBvh * boxset2, const btTransform & trans2, + btPairSet & collision_pairs); +}; + + +#endif // GIM_BOXPRUNING_H_INCLUDED diff --git a/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp b/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp new file mode 100644 index 0000000..2f2c09f --- /dev/null +++ b/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp @@ -0,0 +1,904 @@ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +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. +*/ +/* +Author: Francisco Len Nßjera +Concave-Concave Collision + +*/ + +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "btGImpactCollisionAlgorithm.h" +#include "btContactProcessing.h" +#include "LinearMath/btQuickprof.h" + + +//! Class for accessing the plane equation +class btPlaneShape : public btStaticPlaneShape +{ +public: + + btPlaneShape(const btVector3& v, float f) + :btStaticPlaneShape(v,f) + { + } + + void get_plane_equation(btVector4 &equation) + { + equation[0] = m_planeNormal[0]; + equation[1] = m_planeNormal[1]; + equation[2] = m_planeNormal[2]; + equation[3] = m_planeConstant; + } + + + void get_plane_equation_transformed(const btTransform & trans,btVector4 &equation) + { + equation[0] = trans.getBasis().getRow(0).dot(m_planeNormal); + equation[1] = trans.getBasis().getRow(1).dot(m_planeNormal); + equation[2] = trans.getBasis().getRow(2).dot(m_planeNormal); + equation[3] = trans.getOrigin().dot(m_planeNormal) + m_planeConstant; + } +}; + + + +////////////////////////////////////////////////////////////////////////////////////////////// +#ifdef TRI_COLLISION_PROFILING + +btClock g_triangle_clock; + +float g_accum_triangle_collision_time = 0; +int g_count_triangle_collision = 0; + +void bt_begin_gim02_tri_time() +{ + g_triangle_clock.reset(); +} + +void bt_end_gim02_tri_time() +{ + g_accum_triangle_collision_time += g_triangle_clock.getTimeMicroseconds(); + g_count_triangle_collision++; +} +#endif //TRI_COLLISION_PROFILING +//! Retrieving shapes shapes +/*! +Declared here due of insuficent space on Pool allocators +*/ +//!@{ +class GIM_ShapeRetriever +{ +public: + btGImpactShapeInterface * m_gim_shape; + btTriangleShapeEx m_trishape; + btTetrahedronShapeEx m_tetrashape; + +public: + class ChildShapeRetriever + { + public: + GIM_ShapeRetriever * m_parent; + virtual btCollisionShape * getChildShape(int index) + { + return m_parent->m_gim_shape->getChildShape(index); + } + virtual ~ChildShapeRetriever() {} + }; + + class TriangleShapeRetriever:public ChildShapeRetriever + { + public: + + virtual btCollisionShape * getChildShape(int index) + { + m_parent->m_gim_shape->getBulletTriangle(index,m_parent->m_trishape); + return &m_parent->m_trishape; + } + virtual ~TriangleShapeRetriever() {} + }; + + class TetraShapeRetriever:public ChildShapeRetriever + { + public: + + virtual btCollisionShape * getChildShape(int index) + { + m_parent->m_gim_shape->getBulletTetrahedron(index,m_parent->m_tetrashape); + return &m_parent->m_tetrashape; + } + }; +public: + ChildShapeRetriever m_child_retriever; + TriangleShapeRetriever m_tri_retriever; + TetraShapeRetriever m_tetra_retriever; + ChildShapeRetriever * m_current_retriever; + + GIM_ShapeRetriever(btGImpactShapeInterface * gim_shape) + { + m_gim_shape = gim_shape; + //select retriever + if(m_gim_shape->needsRetrieveTriangles()) + { + m_current_retriever = &m_tri_retriever; + } + else if(m_gim_shape->needsRetrieveTetrahedrons()) + { + m_current_retriever = &m_tetra_retriever; + } + else + { + m_current_retriever = &m_child_retriever; + } + + m_current_retriever->m_parent = this; + } + + btCollisionShape * getChildShape(int index) + { + return m_current_retriever->getChildShape(index); + } + + +}; + + + +//!@} + + +#ifdef TRI_COLLISION_PROFILING + +//! Gets the average time in miliseconds of tree collisions +float btGImpactCollisionAlgorithm::getAverageTreeCollisionTime() +{ + return btGImpactBoxSet::getAverageTreeCollisionTime(); + +} + +//! Gets the average time in miliseconds of triangle collisions +float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime() +{ + if(g_count_triangle_collision == 0) return 0; + + float avgtime = g_accum_triangle_collision_time; + avgtime /= (float)g_count_triangle_collision; + + g_accum_triangle_collision_time = 0; + g_count_triangle_collision = 0; + + return avgtime; +} + +#endif //TRI_COLLISION_PROFILING + + + +btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) +: btActivatingCollisionAlgorithm(ci,body0,body1) +{ + m_manifoldPtr = NULL; + m_convex_algorithm = NULL; +} + +btGImpactCollisionAlgorithm::~btGImpactCollisionAlgorithm() +{ + clearCache(); +} + + + + + +void btGImpactCollisionAlgorithm::addContactPoint(btCollisionObject * body0, + btCollisionObject * body1, + const btVector3 & point, + const btVector3 & normal, + btScalar distance) +{ + m_resultOut->setShapeIdentifiersA(m_part0,m_triface0); + m_resultOut->setShapeIdentifiersB(m_part1,m_triface1); + checkManifold(body0,body1); + m_resultOut->addContactPoint(normal,point,distance); +} + + +void btGImpactCollisionAlgorithm::shape_vs_shape_collision( + btCollisionObject * body0, + btCollisionObject * body1, + btCollisionShape * shape0, + btCollisionShape * shape1) +{ + + btCollisionShape* tmpShape0 = body0->getCollisionShape(); + btCollisionShape* tmpShape1 = body1->getCollisionShape(); + + body0->internalSetTemporaryCollisionShape(shape0); + body1->internalSetTemporaryCollisionShape(shape1); + + { + btCollisionAlgorithm* algor = newAlgorithm(body0,body1); + // post : checkManifold is called + + m_resultOut->setShapeIdentifiersA(m_part0,m_triface0); + m_resultOut->setShapeIdentifiersB(m_part1,m_triface1); + + algor->processCollision(body0,body1,*m_dispatchInfo,m_resultOut); + + algor->~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm(algor); + } + + body0->internalSetTemporaryCollisionShape(tmpShape0); + body1->internalSetTemporaryCollisionShape(tmpShape1); +} + +void btGImpactCollisionAlgorithm::convex_vs_convex_collision( + btCollisionObject * body0, + btCollisionObject * body1, + btCollisionShape * shape0, + btCollisionShape * shape1) +{ + + btCollisionShape* tmpShape0 = body0->getCollisionShape(); + btCollisionShape* tmpShape1 = body1->getCollisionShape(); + + body0->internalSetTemporaryCollisionShape(shape0); + body1->internalSetTemporaryCollisionShape(shape1); + + + m_resultOut->setShapeIdentifiersA(m_part0,m_triface0); + m_resultOut->setShapeIdentifiersB(m_part1,m_triface1); + + checkConvexAlgorithm(body0,body1); + m_convex_algorithm->processCollision(body0,body1,*m_dispatchInfo,m_resultOut); + + body0->internalSetTemporaryCollisionShape(tmpShape0); + body1->internalSetTemporaryCollisionShape(tmpShape1); + +} + + + + +void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs( + const btTransform & trans0, + const btTransform & trans1, + btGImpactShapeInterface * shape0, + btGImpactShapeInterface * shape1,btPairSet & pairset) +{ + if(shape0->hasBoxSet() && shape1->hasBoxSet()) + { + btGImpactBoxSet::find_collision(shape0->getBoxSet(),trans0,shape1->getBoxSet(),trans1,pairset); + } + else + { + btAABB boxshape0; + btAABB boxshape1; + int i = shape0->getNumChildShapes(); + + while(i--) + { + shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max); + + int j = shape1->getNumChildShapes(); + while(j--) + { + shape1->getChildAabb(i,trans1,boxshape1.m_min,boxshape1.m_max); + + if(boxshape1.has_collision(boxshape0)) + { + pairset.push_pair(i,j); + } + } + } + } + + +} + + +void btGImpactCollisionAlgorithm::gimpact_vs_shape_find_pairs( + const btTransform & trans0, + const btTransform & trans1, + btGImpactShapeInterface * shape0, + btCollisionShape * shape1, + btAlignedObjectArray & collided_primitives) +{ + + btAABB boxshape; + + + if(shape0->hasBoxSet()) + { + btTransform trans1to0 = trans0.inverse(); + trans1to0 *= trans1; + + shape1->getAabb(trans1to0,boxshape.m_min,boxshape.m_max); + + shape0->getBoxSet()->boxQuery(boxshape, collided_primitives); + } + else + { + shape1->getAabb(trans1,boxshape.m_min,boxshape.m_max); + + btAABB boxshape0; + int i = shape0->getNumChildShapes(); + + while(i--) + { + shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max); + + if(boxshape.has_collision(boxshape0)) + { + collided_primitives.push_back(i); + } + } + + } + +} + + +void btGImpactCollisionAlgorithm::collide_gjk_triangles(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactMeshShapePart * shape0, + btGImpactMeshShapePart * shape1, + const int * pairs, int pair_count) +{ + btTriangleShapeEx tri0; + btTriangleShapeEx tri1; + + shape0->lockChildShapes(); + shape1->lockChildShapes(); + + const int * pair_pointer = pairs; + + while(pair_count--) + { + + m_triface0 = *(pair_pointer); + m_triface1 = *(pair_pointer+1); + pair_pointer+=2; + + + + shape0->getBulletTriangle(m_triface0,tri0); + shape1->getBulletTriangle(m_triface1,tri1); + + + //collide two convex shapes + if(tri0.overlap_test_conservative(tri1)) + { + convex_vs_convex_collision(body0,body1,&tri0,&tri1); + } + + } + + shape0->unlockChildShapes(); + shape1->unlockChildShapes(); +} + +void btGImpactCollisionAlgorithm::collide_sat_triangles(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactMeshShapePart * shape0, + btGImpactMeshShapePart * shape1, + const int * pairs, int pair_count) +{ + btTransform orgtrans0 = body0->getWorldTransform(); + btTransform orgtrans1 = body1->getWorldTransform(); + + btPrimitiveTriangle ptri0; + btPrimitiveTriangle ptri1; + GIM_TRIANGLE_CONTACT contact_data; + + shape0->lockChildShapes(); + shape1->lockChildShapes(); + + const int * pair_pointer = pairs; + + while(pair_count--) + { + + m_triface0 = *(pair_pointer); + m_triface1 = *(pair_pointer+1); + pair_pointer+=2; + + + shape0->getPrimitiveTriangle(m_triface0,ptri0); + shape1->getPrimitiveTriangle(m_triface1,ptri1); + + #ifdef TRI_COLLISION_PROFILING + bt_begin_gim02_tri_time(); + #endif + + ptri0.applyTransform(orgtrans0); + ptri1.applyTransform(orgtrans1); + + + //build planes + ptri0.buildTriPlane(); + ptri1.buildTriPlane(); + // test conservative + + + + if(ptri0.overlap_test_conservative(ptri1)) + { + if(ptri0.find_triangle_collision_clip_method(ptri1,contact_data)) + { + + int j = contact_data.m_point_count; + while(j--) + { + + addContactPoint(body0, body1, + contact_data.m_points[j], + contact_data.m_separating_normal, + -contact_data.m_penetration_depth); + } + } + } + + #ifdef TRI_COLLISION_PROFILING + bt_end_gim02_tri_time(); + #endif + + } + + shape0->unlockChildShapes(); + shape1->unlockChildShapes(); + +} + + +void btGImpactCollisionAlgorithm::gimpact_vs_gimpact( + btCollisionObject * body0, + btCollisionObject * body1, + btGImpactShapeInterface * shape0, + btGImpactShapeInterface * shape1) +{ + + if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE) + { + btGImpactMeshShape * meshshape0 = static_cast(shape0); + m_part0 = meshshape0->getMeshPartCount(); + + while(m_part0--) + { + gimpact_vs_gimpact(body0,body1,meshshape0->getMeshPart(m_part0),shape1); + } + + return; + } + + if(shape1->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE) + { + btGImpactMeshShape * meshshape1 = static_cast(shape1); + m_part1 = meshshape1->getMeshPartCount(); + + while(m_part1--) + { + + gimpact_vs_gimpact(body0,body1,shape0,meshshape1->getMeshPart(m_part1)); + + } + + return; + } + + + btTransform orgtrans0 = body0->getWorldTransform(); + btTransform orgtrans1 = body1->getWorldTransform(); + + btPairSet pairset; + + gimpact_vs_gimpact_find_pairs(orgtrans0,orgtrans1,shape0,shape1,pairset); + + if(pairset.size()== 0) return; + + if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART && + shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART) + { + btGImpactMeshShapePart * shapepart0 = static_cast(shape0); + btGImpactMeshShapePart * shapepart1 = static_cast(shape1); + //specialized function + #ifdef BULLET_TRIANGLE_COLLISION + collide_gjk_triangles(body0,body1,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size()); + #else + collide_sat_triangles(body0,body1,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size()); + #endif + + return; + } + + //general function + + shape0->lockChildShapes(); + shape1->lockChildShapes(); + + GIM_ShapeRetriever retriever0(shape0); + GIM_ShapeRetriever retriever1(shape1); + + bool child_has_transform0 = shape0->childrenHasTransform(); + bool child_has_transform1 = shape1->childrenHasTransform(); + + int i = pairset.size(); + while(i--) + { + GIM_PAIR * pair = &pairset[i]; + m_triface0 = pair->m_index1; + m_triface1 = pair->m_index2; + btCollisionShape * colshape0 = retriever0.getChildShape(m_triface0); + btCollisionShape * colshape1 = retriever1.getChildShape(m_triface1); + + if(child_has_transform0) + { + body0->setWorldTransform(orgtrans0*shape0->getChildTransform(m_triface0)); + } + + if(child_has_transform1) + { + body1->setWorldTransform(orgtrans1*shape1->getChildTransform(m_triface1)); + } + + //collide two convex shapes + convex_vs_convex_collision(body0,body1,colshape0,colshape1); + + + if(child_has_transform0) + { + body0->setWorldTransform(orgtrans0); + } + + if(child_has_transform1) + { + body1->setWorldTransform(orgtrans1); + } + + } + + shape0->unlockChildShapes(); + shape1->unlockChildShapes(); +} + +void btGImpactCollisionAlgorithm::gimpact_vs_shape(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactShapeInterface * shape0, + btCollisionShape * shape1,bool swapped) +{ + if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE) + { + btGImpactMeshShape * meshshape0 = static_cast(shape0); + int& part = swapped ? m_part1 : m_part0; + part = meshshape0->getMeshPartCount(); + + while(part--) + { + + gimpact_vs_shape(body0, + body1, + meshshape0->getMeshPart(part), + shape1,swapped); + + } + + return; + } + + #ifdef GIMPACT_VS_PLANE_COLLISION + if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART && + shape1->getShapeType() == STATIC_PLANE_PROXYTYPE) + { + btGImpactMeshShapePart * shapepart = static_cast(shape0); + btStaticPlaneShape * planeshape = static_cast(shape1); + gimpacttrimeshpart_vs_plane_collision(body0,body1,shapepart,planeshape,swapped); + return; + } + + #endif + + + + if(shape1->isCompound()) + { + btCompoundShape * compoundshape = static_cast(shape1); + gimpact_vs_compoundshape(body0,body1,shape0,compoundshape,swapped); + return; + } + else if(shape1->isConcave()) + { + btConcaveShape * concaveshape = static_cast(shape1); + gimpact_vs_concave(body0,body1,shape0,concaveshape,swapped); + return; + } + + + btTransform orgtrans0 = body0->getWorldTransform(); + + btTransform orgtrans1 = body1->getWorldTransform(); + + btAlignedObjectArray collided_results; + + gimpact_vs_shape_find_pairs(orgtrans0,orgtrans1,shape0,shape1,collided_results); + + if(collided_results.size() == 0) return; + + + shape0->lockChildShapes(); + + GIM_ShapeRetriever retriever0(shape0); + + + bool child_has_transform0 = shape0->childrenHasTransform(); + + + int i = collided_results.size(); + + while(i--) + { + int child_index = collided_results[i]; + if(swapped) + m_triface1 = child_index; + else + m_triface0 = child_index; + + btCollisionShape * colshape0 = retriever0.getChildShape(child_index); + + if(child_has_transform0) + { + body0->setWorldTransform(orgtrans0*shape0->getChildTransform(child_index)); + } + + //collide two shapes + if(swapped) + { + shape_vs_shape_collision(body1,body0,shape1,colshape0); + } + else + { + shape_vs_shape_collision(body0,body1,colshape0,shape1); + } + + //restore transforms + if(child_has_transform0) + { + body0->setWorldTransform(orgtrans0); + } + + } + + shape0->unlockChildShapes(); + +} + +void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactShapeInterface * shape0, + btCompoundShape * shape1,bool swapped) +{ + btTransform orgtrans1 = body1->getWorldTransform(); + + int i = shape1->getNumChildShapes(); + while(i--) + { + + btCollisionShape * colshape1 = shape1->getChildShape(i); + btTransform childtrans1 = orgtrans1*shape1->getChildTransform(i); + + body1->setWorldTransform(childtrans1); + + //collide child shape + gimpact_vs_shape(body0, body1, + shape0,colshape1,swapped); + + + //restore transforms + body1->setWorldTransform(orgtrans1); + } +} + +void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision( + btCollisionObject * body0, + btCollisionObject * body1, + btGImpactMeshShapePart * shape0, + btStaticPlaneShape * shape1,bool swapped) +{ + + + btTransform orgtrans0 = body0->getWorldTransform(); + btTransform orgtrans1 = body1->getWorldTransform(); + + btPlaneShape * planeshape = static_cast(shape1); + btVector4 plane; + planeshape->get_plane_equation_transformed(orgtrans1,plane); + + //test box against plane + + btAABB tribox; + shape0->getAabb(orgtrans0,tribox.m_min,tribox.m_max); + tribox.increment_margin(planeshape->getMargin()); + + if( tribox.plane_classify(plane)!= BT_CONST_COLLIDE_PLANE) return; + + shape0->lockChildShapes(); + + btScalar margin = shape0->getMargin() + planeshape->getMargin(); + + btVector3 vertex; + int vi = shape0->getVertexCount(); + while(vi--) + { + shape0->getVertex(vi,vertex); + vertex = orgtrans0(vertex); + + btScalar distance = vertex.dot(plane) - plane[3] - margin; + + if(distance<0.0)//add contact + { + if(swapped) + { + addContactPoint(body1, body0, + vertex, + -plane, + distance); + } + else + { + addContactPoint(body0, body1, + vertex, + plane, + distance); + } + } + } + + shape0->unlockChildShapes(); +} + + + + +class btGImpactTriangleCallback: public btTriangleCallback +{ +public: + btGImpactCollisionAlgorithm * algorithm; + btCollisionObject * body0; + btCollisionObject * body1; + btGImpactShapeInterface * gimpactshape0; + bool swapped; + btScalar margin; + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + btTriangleShapeEx tri1(triangle[0],triangle[1],triangle[2]); + tri1.setMargin(margin); + if(swapped) + { + algorithm->setPart0(partId); + algorithm->setFace0(triangleIndex); + } + else + { + algorithm->setPart1(partId); + algorithm->setFace1(triangleIndex); + } + algorithm->gimpact_vs_shape( + body0,body1,gimpactshape0,&tri1,swapped); + } +}; + + + + +void btGImpactCollisionAlgorithm::gimpact_vs_concave( + btCollisionObject * body0, + btCollisionObject * body1, + btGImpactShapeInterface * shape0, + btConcaveShape * shape1,bool swapped) +{ + //create the callback + btGImpactTriangleCallback tricallback; + tricallback.algorithm = this; + tricallback.body0 = body0; + tricallback.body1 = body1; + tricallback.gimpactshape0 = shape0; + tricallback.swapped = swapped; + tricallback.margin = shape1->getMargin(); + + //getting the trimesh AABB + btTransform gimpactInConcaveSpace; + + gimpactInConcaveSpace = body1->getWorldTransform().inverse() * body0->getWorldTransform(); + + btVector3 minAABB,maxAABB; + shape0->getAabb(gimpactInConcaveSpace,minAABB,maxAABB); + + shape1->processAllTriangles(&tricallback,minAABB,maxAABB); + +} + + + +void btGImpactCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + clearCache(); + + m_resultOut = resultOut; + m_dispatchInfo = &dispatchInfo; + btGImpactShapeInterface * gimpactshape0; + btGImpactShapeInterface * gimpactshape1; + + if (body0->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE) + { + gimpactshape0 = static_cast(body0->getCollisionShape()); + + if( body1->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE ) + { + gimpactshape1 = static_cast(body1->getCollisionShape()); + + gimpact_vs_gimpact(body0,body1,gimpactshape0,gimpactshape1); + } + else + { + gimpact_vs_shape(body0,body1,gimpactshape0,body1->getCollisionShape(),false); + } + + } + else if (body1->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE ) + { + gimpactshape1 = static_cast(body1->getCollisionShape()); + + gimpact_vs_shape(body1,body0,gimpactshape1,body0->getCollisionShape(),true); + } +} + + +btScalar btGImpactCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + return 1.f; + +} + +///////////////////////////////////// REGISTERING ALGORITHM ////////////////////////////////////////////// + + + +//! Use this function for register the algorithm externally +void btGImpactCollisionAlgorithm::registerAlgorithm(btCollisionDispatcher * dispatcher) +{ + + static btGImpactCollisionAlgorithm::CreateFunc s_gimpact_cf; + + int i; + + for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ ) + { + dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE,i ,&s_gimpact_cf); + } + + for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ ) + { + dispatcher->registerCollisionCreateFunc(i,GIMPACT_SHAPE_PROXYTYPE ,&s_gimpact_cf); + } + +} diff --git a/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h b/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h new file mode 100644 index 0000000..6b6e07c --- /dev/null +++ b/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h @@ -0,0 +1,306 @@ +/*! \file btGImpactShape.h +\author Francisco Leon Najera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H +#define BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H + +#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +class btDispatcher; +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" + +#include "LinearMath/btAlignedObjectArray.h" + +#include "btGImpactShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" +#include "LinearMath/btIDebugDraw.h" + + + +//! Collision Algorithm for GImpact Shapes +/*! +For register this algorithm in Bullet, proceed as following: + \code +btCollisionDispatcher * dispatcher = static_cast(m_dynamicsWorld ->getDispatcher()); +btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher); + \endcode +*/ +class btGImpactCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ +protected: + btCollisionAlgorithm * m_convex_algorithm; + btPersistentManifold * m_manifoldPtr; + btManifoldResult* m_resultOut; + const btDispatcherInfo * m_dispatchInfo; + int m_triface0; + int m_part0; + int m_triface1; + int m_part1; + + + //! Creates a new contact point + SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(btCollisionObject* body0,btCollisionObject* body1) + { + m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1); + return m_manifoldPtr; + } + + SIMD_FORCE_INLINE void destroyConvexAlgorithm() + { + if(m_convex_algorithm) + { + m_convex_algorithm->~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm( m_convex_algorithm); + m_convex_algorithm = NULL; + } + } + + SIMD_FORCE_INLINE void destroyContactManifolds() + { + if(m_manifoldPtr == NULL) return; + m_dispatcher->releaseManifold(m_manifoldPtr); + m_manifoldPtr = NULL; + } + + SIMD_FORCE_INLINE void clearCache() + { + destroyContactManifolds(); + destroyConvexAlgorithm(); + + m_triface0 = -1; + m_part0 = -1; + m_triface1 = -1; + m_part1 = -1; + } + + SIMD_FORCE_INLINE btPersistentManifold* getLastManifold() + { + return m_manifoldPtr; + } + + + // Call before process collision + SIMD_FORCE_INLINE void checkManifold(btCollisionObject* body0,btCollisionObject* body1) + { + if(getLastManifold() == 0) + { + newContactManifold(body0,body1); + } + + m_resultOut->setPersistentManifold(getLastManifold()); + } + + // Call before process collision + SIMD_FORCE_INLINE btCollisionAlgorithm * newAlgorithm(btCollisionObject* body0,btCollisionObject* body1) + { + checkManifold(body0,body1); + + btCollisionAlgorithm * convex_algorithm = m_dispatcher->findAlgorithm( + body0,body1,getLastManifold()); + return convex_algorithm ; + } + + // Call before process collision + SIMD_FORCE_INLINE void checkConvexAlgorithm(btCollisionObject* body0,btCollisionObject* body1) + { + if(m_convex_algorithm) return; + m_convex_algorithm = newAlgorithm(body0,body1); + } + + + + + void addContactPoint(btCollisionObject * body0, + btCollisionObject * body1, + const btVector3 & point, + const btVector3 & normal, + btScalar distance); + +//! Collision routines +//!@{ + + void collide_gjk_triangles(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactMeshShapePart * shape0, + btGImpactMeshShapePart * shape1, + const int * pairs, int pair_count); + + void collide_sat_triangles(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactMeshShapePart * shape0, + btGImpactMeshShapePart * shape1, + const int * pairs, int pair_count); + + + + + void shape_vs_shape_collision( + btCollisionObject * body0, + btCollisionObject * body1, + btCollisionShape * shape0, + btCollisionShape * shape1); + + void convex_vs_convex_collision(btCollisionObject * body0, + btCollisionObject * body1, + btCollisionShape * shape0, + btCollisionShape * shape1); + + + + void gimpact_vs_gimpact_find_pairs( + const btTransform & trans0, + const btTransform & trans1, + btGImpactShapeInterface * shape0, + btGImpactShapeInterface * shape1,btPairSet & pairset); + + void gimpact_vs_shape_find_pairs( + const btTransform & trans0, + const btTransform & trans1, + btGImpactShapeInterface * shape0, + btCollisionShape * shape1, + btAlignedObjectArray & collided_primitives); + + + void gimpacttrimeshpart_vs_plane_collision( + btCollisionObject * body0, + btCollisionObject * body1, + btGImpactMeshShapePart * shape0, + btStaticPlaneShape * shape1,bool swapped); + + +public: + + btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); + + virtual ~btGImpactCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr) + manifoldArray.push_back(m_manifoldPtr); + } + + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btGImpactCollisionAlgorithm)); + return new(mem) btGImpactCollisionAlgorithm(ci,body0,body1); + } + }; + + //! Use this function for register the algorithm externally + static void registerAlgorithm(btCollisionDispatcher * dispatcher); +#ifdef TRI_COLLISION_PROFILING + //! Gets the average time in miliseconds of tree collisions + static float getAverageTreeCollisionTime(); + + //! Gets the average time in miliseconds of triangle collisions + static float getAverageTriangleCollisionTime(); +#endif //TRI_COLLISION_PROFILING + + //! Collides two gimpact shapes + /*! + \pre shape0 and shape1 couldn't be btGImpactMeshShape objects + */ + + + void gimpact_vs_gimpact(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactShapeInterface * shape0, + btGImpactShapeInterface * shape1); + + void gimpact_vs_shape(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactShapeInterface * shape0, + btCollisionShape * shape1,bool swapped); + + void gimpact_vs_compoundshape(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactShapeInterface * shape0, + btCompoundShape * shape1,bool swapped); + + void gimpact_vs_concave( + btCollisionObject * body0, + btCollisionObject * body1, + btGImpactShapeInterface * shape0, + btConcaveShape * shape1,bool swapped); + + + + + /// Accessor/Mutator pairs for Part and triangleID + void setFace0(int value) + { + m_triface0 = value; + } + int getFace0() + { + return m_triface0; + } + void setFace1(int value) + { + m_triface1 = value; + } + int getFace1() + { + return m_triface1; + } + void setPart0(int value) + { + m_part0 = value; + } + int getPart0() + { + return m_part0; + } + void setPart1(int value) + { + m_part1 = value; + } + int getPart1() + { + return m_part1; + } + +}; + + +//algorithm details +//#define BULLET_TRIANGLE_COLLISION 1 +#define GIMPACT_VS_PLANE_COLLISION 1 + + + +#endif //BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H diff --git a/src/BulletCollision/Gimpact/btGImpactMassUtil.h b/src/BulletCollision/Gimpact/btGImpactMassUtil.h new file mode 100644 index 0000000..2543aef --- /dev/null +++ b/src/BulletCollision/Gimpact/btGImpactMassUtil.h @@ -0,0 +1,60 @@ +/*! \file btGImpactMassUtil.h +\author Francisco Leon Najera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +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 GIMPACT_MASS_UTIL_H +#define GIMPACT_MASS_UTIL_H + +#include "LinearMath/btTransform.h" + + + +SIMD_FORCE_INLINE btVector3 gim_inertia_add_transformed( + const btVector3 & source_inertia, const btVector3 & added_inertia, const btTransform & transform) +{ + btMatrix3x3 rotatedTensor = transform.getBasis().scaled(added_inertia) * transform.getBasis().transpose(); + + btScalar x2 = transform.getOrigin()[0]; + x2*= x2; + btScalar y2 = transform.getOrigin()[1]; + y2*= y2; + btScalar z2 = transform.getOrigin()[2]; + z2*= z2; + + btScalar ix = rotatedTensor[0][0]*(y2+z2); + btScalar iy = rotatedTensor[1][1]*(x2+z2); + btScalar iz = rotatedTensor[2][2]*(x2+y2); + + return btVector3(source_inertia[0]+ix,source_inertia[1]+iy,source_inertia[2] + iz); +} + +SIMD_FORCE_INLINE btVector3 gim_get_point_inertia(const btVector3 & point, btScalar mass) +{ + btScalar x2 = point[0]*point[0]; + btScalar y2 = point[1]*point[1]; + btScalar z2 = point[2]*point[2]; + return btVector3(mass*(y2+z2),mass*(x2+z2),mass*(x2+y2)); +} + + +#endif //GIMPACT_MESH_SHAPE_H diff --git a/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp b/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp new file mode 100644 index 0000000..cd4dfdb --- /dev/null +++ b/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp @@ -0,0 +1,528 @@ +/*! \file gim_box_set.h +\author Francisco Leon Najera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +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 "btGImpactQuantizedBvh.h" +#include "LinearMath/btQuickprof.h" + +#ifdef TRI_COLLISION_PROFILING +btClock g_q_tree_clock; + + +float g_q_accum_tree_collision_time = 0; +int g_q_count_traversing = 0; + + +void bt_begin_gim02_q_tree_time() +{ + g_q_tree_clock.reset(); +} + +void bt_end_gim02_q_tree_time() +{ + g_q_accum_tree_collision_time += g_q_tree_clock.getTimeMicroseconds(); + g_q_count_traversing++; +} + + +//! Gets the average time in miliseconds of tree collisions +float btGImpactQuantizedBvh::getAverageTreeCollisionTime() +{ + if(g_q_count_traversing == 0) return 0; + + float avgtime = g_q_accum_tree_collision_time; + avgtime /= (float)g_q_count_traversing; + + g_q_accum_tree_collision_time = 0; + g_q_count_traversing = 0; + return avgtime; + +// float avgtime = g_q_count_traversing; +// g_q_count_traversing = 0; +// return avgtime; + +} + +#endif //TRI_COLLISION_PROFILING + +/////////////////////// btQuantizedBvhTree ///////////////////////////////// + +void btQuantizedBvhTree::calc_quantization( + GIM_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin) +{ + //calc globa box + btAABB global_bound; + global_bound.invalidate(); + + for (int i=0;i splitValue) + { + //swap + primitive_boxes.swap(i,splitIndex); + //swapLeafNodes(i,splitIndex); + splitIndex++; + } + } + + //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex + //otherwise the tree-building might fail due to stack-overflows in certain cases. + //unbalanced1 is unsafe: it can cause stack overflows + //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); + + //unbalanced2 should work too: always use center (perfect balanced trees) + //bool unbalanced2 = true; + + //this should be safe too: + int rangeBalancedIndices = numIndices/3; + bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); + + if (unbalanced) + { + splitIndex = startIndex+ (numIndices>>1); + } + + btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex)))); + + return splitIndex; + +} + + +void btQuantizedBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex) +{ + int curIndex = m_num_nodes; + m_num_nodes++; + + btAssert((endIndex-startIndex)>0); + + if ((endIndex-startIndex)==1) + { + //We have a leaf node + setNodeBound(curIndex,primitive_boxes[startIndex].m_bound); + m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data); + + return; + } + //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. + + //split axis + int splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex); + + splitIndex = _sort_and_calc_splitting_index( + primitive_boxes,startIndex,endIndex, + splitIndex//split axis + ); + + + //calc this node bounding box + + btAABB node_bound; + node_bound.invalidate(); + + for (int i=startIndex;iget_primitive_box(getNodeData(nodecount),leafbox); + setNodeBound(nodecount,leafbox); + } + else + { + //const GIM_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount); + //get left bound + btAABB bound; + bound.invalidate(); + + btAABB temp_box; + + int child_node = getLeftNode(nodecount); + if(child_node) + { + getNodeBound(child_node,temp_box); + bound.merge(temp_box); + } + + child_node = getRightNode(nodecount); + if(child_node) + { + getNodeBound(child_node,temp_box); + bound.merge(temp_box); + } + + setNodeBound(nodecount,bound); + } + } +} + +//! this rebuild the entire set +void btGImpactQuantizedBvh::buildSet() +{ + //obtain primitive boxes + GIM_BVH_DATA_ARRAY primitive_boxes; + primitive_boxes.resize(m_primitive_manager->get_primitive_count()); + + for (int i = 0;iget_primitive_box(i,primitive_boxes[i].m_bound); + primitive_boxes[i].m_data = i; + } + + m_box_tree.build_tree(primitive_boxes); +} + +//! returns the indices of the primitives in the m_primitive_manager +bool btGImpactQuantizedBvh::boxQuery(const btAABB & box, btAlignedObjectArray & collided_results) const +{ + int curIndex = 0; + int numNodes = getNodeCount(); + + //quantize box + + unsigned short quantizedMin[3]; + unsigned short quantizedMax[3]; + + m_box_tree.quantizePoint(quantizedMin,box.m_min); + m_box_tree.quantizePoint(quantizedMax,box.m_max); + + + while (curIndex < numNodes) + { + + //catch bugs in tree data + + bool aabbOverlap = m_box_tree.testQuantizedBoxOverlapp(curIndex, quantizedMin,quantizedMax); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData(curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getEscapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; +} + + + +//! returns the indices of the primitives in the m_primitive_manager +bool btGImpactQuantizedBvh::rayQuery( + const btVector3 & ray_dir,const btVector3 & ray_origin , + btAlignedObjectArray & collided_results) const +{ + int curIndex = 0; + int numNodes = getNodeCount(); + + while (curIndex < numNodes) + { + btAABB bound; + getNodeBound(curIndex,bound); + + //catch bugs in tree data + + bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData( curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getEscapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; +} + + +SIMD_FORCE_INLINE bool _quantized_node_collision( + btGImpactQuantizedBvh * boxset0, btGImpactQuantizedBvh * boxset1, + const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0, + int node0 ,int node1, bool complete_primitive_tests) +{ + btAABB box0; + boxset0->getNodeBound(node0,box0); + btAABB box1; + boxset1->getNodeBound(node1,box1); + + return box0.overlapping_trans_cache(box1,trans_cache_1to0,complete_primitive_tests ); +// box1.appy_transform_trans_cache(trans_cache_1to0); +// return box0.has_collision(box1); + +} + + +//stackless recursive collision routine +static void _find_quantized_collision_pairs_recursive( + btGImpactQuantizedBvh * boxset0, btGImpactQuantizedBvh * boxset1, + btPairSet * collision_pairs, + const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0, + int node0, int node1, bool complete_primitive_tests) +{ + + + + if( _quantized_node_collision( + boxset0,boxset1,trans_cache_1to0, + node0,node1,complete_primitive_tests) ==false) return;//avoid colliding internal nodes + + if(boxset0->isLeafNode(node0)) + { + if(boxset1->isLeafNode(node1)) + { + // collision result + collision_pairs->push_pair( + boxset0->getNodeData(node0),boxset1->getNodeData(node1)); + return; + } + else + { + + //collide left recursive + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + node0,boxset1->getLeftNode(node1),false); + + //collide right recursive + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + node0,boxset1->getRightNode(node1),false); + + + } + } + else + { + if(boxset1->isLeafNode(node1)) + { + + //collide left recursive + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),node1,false); + + + //collide right recursive + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),node1,false); + + + } + else + { + //collide left0 left1 + + + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),boxset1->getLeftNode(node1),false); + + //collide left0 right1 + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),boxset1->getRightNode(node1),false); + + + //collide right0 left1 + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),boxset1->getLeftNode(node1),false); + + //collide right0 right1 + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),boxset1->getRightNode(node1),false); + + }// else if node1 is not a leaf + }// else if node0 is not a leaf +} + + +void btGImpactQuantizedBvh::find_collision(btGImpactQuantizedBvh * boxset0, const btTransform & trans0, + btGImpactQuantizedBvh * boxset1, const btTransform & trans1, + btPairSet & collision_pairs) +{ + + if(boxset0->getNodeCount()==0 || boxset1->getNodeCount()==0 ) return; + + BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0; + + trans_cache_1to0.calc_from_homogenic(trans0,trans1); + +#ifdef TRI_COLLISION_PROFILING + bt_begin_gim02_q_tree_time(); +#endif //TRI_COLLISION_PROFILING + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + &collision_pairs,trans_cache_1to0,0,0,true); +#ifdef TRI_COLLISION_PROFILING + bt_end_gim02_q_tree_time(); +#endif //TRI_COLLISION_PROFILING + +} + + diff --git a/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h b/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h new file mode 100644 index 0000000..9c99077 --- /dev/null +++ b/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h @@ -0,0 +1,372 @@ +#ifndef GIM_QUANTIZED_SET_H_INCLUDED +#define GIM_QUANTIZED_SET_H_INCLUDED + +/*! \file btGImpactQuantizedBvh.h +\author Francisco Leon Najera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +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 "btGImpactBvh.h" +#include "btQuantization.h" + + + + + +///btQuantizedBvhNode is a compressed aabb node, 16 bytes. +///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range). +ATTRIBUTE_ALIGNED16 (struct) BT_QUANTIZED_BVH_NODE +{ + //12 bytes + unsigned short int m_quantizedAabbMin[3]; + unsigned short int m_quantizedAabbMax[3]; + //4 bytes + int m_escapeIndexOrDataIndex; + + BT_QUANTIZED_BVH_NODE() + { + m_escapeIndexOrDataIndex = 0; + } + + SIMD_FORCE_INLINE bool isLeafNode() const + { + //skipindex is negative (internal node), triangleindex >=0 (leafnode) + return (m_escapeIndexOrDataIndex>=0); + } + + SIMD_FORCE_INLINE int getEscapeIndex() const + { + //btAssert(m_escapeIndexOrDataIndex < 0); + return -m_escapeIndexOrDataIndex; + } + + SIMD_FORCE_INLINE void setEscapeIndex(int index) + { + m_escapeIndexOrDataIndex = -index; + } + + SIMD_FORCE_INLINE int getDataIndex() const + { + //btAssert(m_escapeIndexOrDataIndex >= 0); + + return m_escapeIndexOrDataIndex; + } + + SIMD_FORCE_INLINE void setDataIndex(int index) + { + m_escapeIndexOrDataIndex = index; + } + + SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp( + unsigned short * quantizedMin,unsigned short * quantizedMax) const + { + if(m_quantizedAabbMin[0] > quantizedMax[0] || + m_quantizedAabbMax[0] < quantizedMin[0] || + m_quantizedAabbMin[1] > quantizedMax[1] || + m_quantizedAabbMax[1] < quantizedMin[1] || + m_quantizedAabbMin[2] > quantizedMax[2] || + m_quantizedAabbMax[2] < quantizedMin[2]) + { + return false; + } + return true; + } + +}; + + + +class GIM_QUANTIZED_BVH_NODE_ARRAY:public btAlignedObjectArray +{ +}; + + + + +//! Basic Box tree structure +class btQuantizedBvhTree +{ +protected: + int m_num_nodes; + GIM_QUANTIZED_BVH_NODE_ARRAY m_node_array; + btAABB m_global_bound; + btVector3 m_bvhQuantization; +protected: + void calc_quantization(GIM_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin = btScalar(1.0) ); + + int _sort_and_calc_splitting_index( + GIM_BVH_DATA_ARRAY & primitive_boxes, + int startIndex, int endIndex, int splitAxis); + + int _calc_splitting_axis(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); + + void _build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); +public: + btQuantizedBvhTree() + { + m_num_nodes = 0; + } + + //! prototype functions for box tree management + //!@{ + void build_tree(GIM_BVH_DATA_ARRAY & primitive_boxes); + + SIMD_FORCE_INLINE void quantizePoint( + unsigned short * quantizedpoint, const btVector3 & point) const + { + bt_quantize_clamp(quantizedpoint,point,m_global_bound.m_min,m_global_bound.m_max,m_bvhQuantization); + } + + + SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp( + int node_index, + unsigned short * quantizedMin,unsigned short * quantizedMax) const + { + return m_node_array[node_index].testQuantizedBoxOverlapp(quantizedMin,quantizedMax); + } + + SIMD_FORCE_INLINE void clearNodes() + { + m_node_array.clear(); + m_num_nodes = 0; + } + + //! node count + SIMD_FORCE_INLINE int getNodeCount() const + { + return m_num_nodes; + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const + { + return m_node_array[nodeindex].isLeafNode(); + } + + SIMD_FORCE_INLINE int getNodeData(int nodeindex) const + { + return m_node_array[nodeindex].getDataIndex(); + } + + SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const + { + bound.m_min = bt_unquantize( + m_node_array[nodeindex].m_quantizedAabbMin, + m_global_bound.m_min,m_bvhQuantization); + + bound.m_max = bt_unquantize( + m_node_array[nodeindex].m_quantizedAabbMax, + m_global_bound.m_min,m_bvhQuantization); + } + + SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound) + { + bt_quantize_clamp( m_node_array[nodeindex].m_quantizedAabbMin, + bound.m_min, + m_global_bound.m_min, + m_global_bound.m_max, + m_bvhQuantization); + + bt_quantize_clamp( m_node_array[nodeindex].m_quantizedAabbMax, + bound.m_max, + m_global_bound.m_min, + m_global_bound.m_max, + m_bvhQuantization); + } + + SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const + { + return nodeindex+1; + } + + SIMD_FORCE_INLINE int getRightNode(int nodeindex) const + { + if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2; + return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex(); + } + + SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const + { + return m_node_array[nodeindex].getEscapeIndex(); + } + + SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const + { + return &m_node_array[index]; + } + + //!@} +}; + + + +//! Structure for containing Boxes +/*! +This class offers an structure for managing a box tree of primitives. +Requires a Primitive prototype (like btPrimitiveManagerBase ) +*/ +class btGImpactQuantizedBvh +{ +protected: + btQuantizedBvhTree m_box_tree; + btPrimitiveManagerBase * m_primitive_manager; + +protected: + //stackless refit + void refit(); +public: + + //! this constructor doesn't build the tree. you must call buildSet + btGImpactQuantizedBvh() + { + m_primitive_manager = NULL; + } + + //! this constructor doesn't build the tree. you must call buildSet + btGImpactQuantizedBvh(btPrimitiveManagerBase * primitive_manager) + { + m_primitive_manager = primitive_manager; + } + + SIMD_FORCE_INLINE btAABB getGlobalBox() const + { + btAABB totalbox; + getNodeBound(0, totalbox); + return totalbox; + } + + SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager) + { + m_primitive_manager = primitive_manager; + } + + SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const + { + return m_primitive_manager; + } + + +//! node manager prototype functions +///@{ + + //! this attemps to refit the box set. + SIMD_FORCE_INLINE void update() + { + refit(); + } + + //! this rebuild the entire set + void buildSet(); + + //! returns the indices of the primitives in the m_primitive_manager + bool boxQuery(const btAABB & box, btAlignedObjectArray & collided_results) const; + + //! returns the indices of the primitives in the m_primitive_manager + SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box, + const btTransform & transform, btAlignedObjectArray & collided_results) const + { + btAABB transbox=box; + transbox.appy_transform(transform); + return boxQuery(transbox,collided_results); + } + + //! returns the indices of the primitives in the m_primitive_manager + bool rayQuery( + const btVector3 & ray_dir,const btVector3 & ray_origin , + btAlignedObjectArray & collided_results) const; + + //! tells if this set has hierarcht + SIMD_FORCE_INLINE bool hasHierarchy() const + { + return true; + } + + //! tells if this set is a trimesh + SIMD_FORCE_INLINE bool isTrimesh() const + { + return m_primitive_manager->is_trimesh(); + } + + //! node count + SIMD_FORCE_INLINE int getNodeCount() const + { + return m_box_tree.getNodeCount(); + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const + { + return m_box_tree.isLeafNode(nodeindex); + } + + SIMD_FORCE_INLINE int getNodeData(int nodeindex) const + { + return m_box_tree.getNodeData(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const + { + m_box_tree.getNodeBound(nodeindex, bound); + } + + SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound) + { + m_box_tree.setNodeBound(nodeindex, bound); + } + + + SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const + { + return m_box_tree.getLeftNode(nodeindex); + } + + SIMD_FORCE_INLINE int getRightNode(int nodeindex) const + { + return m_box_tree.getRightNode(nodeindex); + } + + SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const + { + return m_box_tree.getEscapeNodeIndex(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const + { + m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle); + } + + + SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const + { + return m_box_tree.get_node_pointer(index); + } + +#ifdef TRI_COLLISION_PROFILING + static float getAverageTreeCollisionTime(); +#endif //TRI_COLLISION_PROFILING + + static void find_collision(btGImpactQuantizedBvh * boxset1, const btTransform & trans1, + btGImpactQuantizedBvh * boxset2, const btTransform & trans2, + btPairSet & collision_pairs); +}; + + +#endif // GIM_BOXPRUNING_H_INCLUDED diff --git a/src/BulletCollision/Gimpact/btGImpactShape.cpp b/src/BulletCollision/Gimpact/btGImpactShape.cpp new file mode 100644 index 0000000..cceace5 --- /dev/null +++ b/src/BulletCollision/Gimpact/btGImpactShape.cpp @@ -0,0 +1,203 @@ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +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 "btGImpactShape.h" +#include "btGImpactMassUtil.h" + + +#define CALC_EXACT_INERTIA 1 + +void btGImpactCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + lockChildShapes(); +#ifdef CALC_EXACT_INERTIA + inertia.setValue(0.f,0.f,0.f); + + int i = this->getNumChildShapes(); + btScalar shapemass = mass/btScalar(i); + + while(i--) + { + btVector3 temp_inertia; + m_childShapes[i]->calculateLocalInertia(shapemass,temp_inertia); + if(childrenHasTransform()) + { + inertia = gim_inertia_add_transformed( inertia,temp_inertia,m_childTransforms[i]); + } + else + { + inertia = gim_inertia_add_transformed( inertia,temp_inertia,btTransform::getIdentity()); + } + + } + +#else + + // Calc box inertia + + btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0]; + btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1]; + btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2]; + const btScalar x2 = lx*lx; + const btScalar y2 = ly*ly; + const btScalar z2 = lz*lz; + const btScalar scaledmass = mass * btScalar(0.08333333); + + inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2)); + +#endif + unlockChildShapes(); +} + + + +void btGImpactMeshShapePart::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + lockChildShapes(); + + +#ifdef CALC_EXACT_INERTIA + inertia.setValue(0.f,0.f,0.f); + + int i = this->getVertexCount(); + btScalar pointmass = mass/btScalar(i); + + while(i--) + { + btVector3 pointintertia; + this->getVertex(i,pointintertia); + pointintertia = gim_get_point_inertia(pointintertia,pointmass); + inertia+=pointintertia; + } + +#else + + // Calc box inertia + + btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0]; + btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1]; + btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2]; + const btScalar x2 = lx*lx; + const btScalar y2 = ly*ly; + const btScalar z2 = lz*lz; + const btScalar scaledmass = mass * btScalar(0.08333333); + + inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2)); + +#endif + + unlockChildShapes(); +} + +void btGImpactMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + +#ifdef CALC_EXACT_INERTIA + inertia.setValue(0.f,0.f,0.f); + + int i = this->getMeshPartCount(); + btScalar partmass = mass/btScalar(i); + + while(i--) + { + btVector3 partinertia; + getMeshPart(i)->calculateLocalInertia(partmass,partinertia); + inertia+=partinertia; + } + +#else + + // Calc box inertia + + btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0]; + btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1]; + btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2]; + const btScalar x2 = lx*lx; + const btScalar y2 = ly*ly; + const btScalar z2 = lz*lz; + const btScalar scaledmass = mass * btScalar(0.08333333); + + inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2)); + +#endif +} + +void btGImpactMeshShape::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const +{ +} + + +void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + lockChildShapes(); + btAABB box; + box.m_min = aabbMin; + box.m_max = aabbMax; + + btAlignedObjectArray collided; + m_box_set.boxQuery(box,collided); + + if(collided.size()==0) + { + unlockChildShapes(); + return; + } + + int part = (int)getPart(); + btPrimitiveTriangle triangle; + int i = collided.size(); + while(i--) + { + this->getPrimitiveTriangle(collided[i],triangle); + callback->processTriangle(triangle.m_vertices,part,collided[i]); + } + unlockChildShapes(); + +} + +void btGImpactMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + int i = m_mesh_parts.size(); + while(i--) + { + m_mesh_parts[i]->processAllTriangles(callback,aabbMin,aabbMax); + } +} + + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btGImpactMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btGImpactMeshShapeData* trimeshData = (btGImpactMeshShapeData*) dataBuffer; + + btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer); + + m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer); + + trimeshData->m_collisionMargin = float(m_collisionMargin); + + localScaling.serializeFloat(trimeshData->m_localScaling); + + trimeshData->m_gimpactSubType = int(getGImpactShapeType()); + + return "btGImpactMeshShapeData"; +} + diff --git a/src/BulletCollision/Gimpact/btGImpactShape.h b/src/BulletCollision/Gimpact/btGImpactShape.h new file mode 100644 index 0000000..90015bb --- /dev/null +++ b/src/BulletCollision/Gimpact/btGImpactShape.h @@ -0,0 +1,1171 @@ +/*! \file btGImpactShape.h +\author Francisco Len Nßjera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +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 GIMPACT_SHAPE_H +#define GIMPACT_SHAPE_H + +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "BulletCollision/CollisionShapes/btConcaveShape.h" +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btAlignedObjectArray.h" + +#include "btGImpactQuantizedBvh.h" // box tree class + + +//! declare Quantized trees, (you can change to float based trees) +typedef btGImpactQuantizedBvh btGImpactBoxSet; + +enum eGIMPACT_SHAPE_TYPE +{ + CONST_GIMPACT_COMPOUND_SHAPE = 0, + CONST_GIMPACT_TRIMESH_SHAPE_PART, + CONST_GIMPACT_TRIMESH_SHAPE +}; + + +//! Helper class for tetrahedrons +class btTetrahedronShapeEx:public btBU_Simplex1to4 +{ +public: + btTetrahedronShapeEx() + { + m_numVertices = 4; + } + + + SIMD_FORCE_INLINE void setVertices( + const btVector3 & v0,const btVector3 & v1, + const btVector3 & v2,const btVector3 & v3) + { + m_vertices[0] = v0; + m_vertices[1] = v1; + m_vertices[2] = v2; + m_vertices[3] = v3; + recalcLocalAabb(); + } +}; + + +//! Base class for gimpact shapes +class btGImpactShapeInterface : public btConcaveShape +{ +protected: + btAABB m_localAABB; + bool m_needs_update; + btVector3 localScaling; + btGImpactBoxSet m_box_set;// optionally boxset + + //! use this function for perfofm refit in bounding boxes + //! use this function for perfofm refit in bounding boxes + virtual void calcLocalAABB() + { + lockChildShapes(); + if(m_box_set.getNodeCount() == 0) + { + m_box_set.buildSet(); + } + else + { + m_box_set.update(); + } + unlockChildShapes(); + + m_localAABB = m_box_set.getGlobalBox(); + } + + +public: + btGImpactShapeInterface() + { + m_shapeType=GIMPACT_SHAPE_PROXYTYPE; + m_localAABB.invalidate(); + m_needs_update = true; + localScaling.setValue(1.f,1.f,1.f); + } + + + //! performs refit operation + /*! + Updates the entire Box set of this shape. + \pre postUpdate() must be called for attemps to calculating the box set, else this function + will does nothing. + \post if m_needs_update == true, then it calls calcLocalAABB(); + */ + SIMD_FORCE_INLINE void updateBound() + { + if(!m_needs_update) return; + calcLocalAABB(); + m_needs_update = false; + } + + //! If the Bounding box is not updated, then this class attemps to calculate it. + /*! + \post Calls updateBound() for update the box set. + */ + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + btAABB transformedbox = m_localAABB; + transformedbox.appy_transform(t); + aabbMin = transformedbox.m_min; + aabbMax = transformedbox.m_max; + } + + //! Tells to this object that is needed to refit the box set + virtual void postUpdate() + { + m_needs_update = true; + } + + //! Obtains the local box, which is the global calculated box of the total of subshapes + SIMD_FORCE_INLINE const btAABB & getLocalBox() + { + return m_localAABB; + } + + + virtual int getShapeType() const + { + return GIMPACT_SHAPE_PROXYTYPE; + } + + /*! + \post You must call updateBound() for update the box set. + */ + virtual void setLocalScaling(const btVector3& scaling) + { + localScaling = scaling; + postUpdate(); + } + + virtual const btVector3& getLocalScaling() const + { + return localScaling; + } + + + virtual void setMargin(btScalar margin) + { + m_collisionMargin = margin; + int i = getNumChildShapes(); + while(i--) + { + btCollisionShape* child = getChildShape(i); + child->setMargin(margin); + } + + m_needs_update = true; + } + + + //! Subshape member functions + //!@{ + + //! Base method for determinig which kind of GIMPACT shape we get + virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const = 0 ; + + //! gets boxset + SIMD_FORCE_INLINE btGImpactBoxSet * getBoxSet() + { + return &m_box_set; + } + + //! Determines if this class has a hierarchy structure for sorting its primitives + SIMD_FORCE_INLINE bool hasBoxSet() const + { + if(m_box_set.getNodeCount() == 0) return false; + return true; + } + + //! Obtains the primitive manager + virtual const btPrimitiveManagerBase * getPrimitiveManager() const = 0; + + + //! Gets the number of children + virtual int getNumChildShapes() const = 0; + + //! if true, then its children must get transforms. + virtual bool childrenHasTransform() const = 0; + + //! Determines if this shape has triangles + virtual bool needsRetrieveTriangles() const = 0; + + //! Determines if this shape has tetrahedrons + virtual bool needsRetrieveTetrahedrons() const = 0; + + virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const = 0; + + virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const = 0; + + + + //! call when reading child shapes + virtual void lockChildShapes() const + { + } + + virtual void unlockChildShapes() const + { + } + + //! if this trimesh + SIMD_FORCE_INLINE void getPrimitiveTriangle(int index,btPrimitiveTriangle & triangle) const + { + getPrimitiveManager()->get_primitive_triangle(index,triangle); + } + + + //! Retrieves the bound from a child + /*! + */ + virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + btAABB child_aabb; + getPrimitiveManager()->get_primitive_box(child_index,child_aabb); + child_aabb.appy_transform(t); + aabbMin = child_aabb.m_min; + aabbMax = child_aabb.m_max; + } + + //! Gets the children + virtual btCollisionShape* getChildShape(int index) = 0; + + + //! Gets the child + virtual const btCollisionShape* getChildShape(int index) const = 0; + + //! Gets the children transform + virtual btTransform getChildTransform(int index) const = 0; + + //! Sets the children transform + /*! + \post You must call updateBound() for update the box set. + */ + virtual void setChildTransform(int index, const btTransform & transform) = 0; + + //!@} + + + //! virtual method for ray collision + virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const + { + (void) rayFrom; (void) rayTo; (void) resultCallback; + } + + //! Function for retrieve triangles. + /*! + It gives the triangles in local space + */ + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const + { + (void) callback; (void) aabbMin; (void) aabbMax; + } + + //!@} + +}; + + +//! btGImpactCompoundShape allows to handle multiple btCollisionShape objects at once +/*! +This class only can manage Convex subshapes +*/ +class btGImpactCompoundShape : public btGImpactShapeInterface +{ +public: + //! compound primitive manager + class CompoundPrimitiveManager:public btPrimitiveManagerBase + { + public: + virtual ~CompoundPrimitiveManager() {} + btGImpactCompoundShape * m_compoundShape; + + + CompoundPrimitiveManager(const CompoundPrimitiveManager& compound) + : btPrimitiveManagerBase() + { + m_compoundShape = compound.m_compoundShape; + } + + CompoundPrimitiveManager(btGImpactCompoundShape * compoundShape) + { + m_compoundShape = compoundShape; + } + + CompoundPrimitiveManager() + { + m_compoundShape = NULL; + } + + virtual bool is_trimesh() const + { + return false; + } + + virtual int get_primitive_count() const + { + return (int )m_compoundShape->getNumChildShapes(); + } + + virtual void get_primitive_box(int prim_index ,btAABB & primbox) const + { + btTransform prim_trans; + if(m_compoundShape->childrenHasTransform()) + { + prim_trans = m_compoundShape->getChildTransform(prim_index); + } + else + { + prim_trans.setIdentity(); + } + const btCollisionShape* shape = m_compoundShape->getChildShape(prim_index); + shape->getAabb(prim_trans,primbox.m_min,primbox.m_max); + } + + virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const + { + btAssert(0); + (void) prim_index; (void) triangle; + } + + }; + + + +protected: + CompoundPrimitiveManager m_primitive_manager; + btAlignedObjectArray m_childTransforms; + btAlignedObjectArray m_childShapes; + + +public: + + btGImpactCompoundShape(bool children_has_transform = true) + { + (void) children_has_transform; + m_primitive_manager.m_compoundShape = this; + m_box_set.setPrimitiveManager(&m_primitive_manager); + } + + virtual ~btGImpactCompoundShape() + { + } + + + //! if true, then its children must get transforms. + virtual bool childrenHasTransform() const + { + if(m_childTransforms.size()==0) return false; + return true; + } + + + //! Obtains the primitive manager + virtual const btPrimitiveManagerBase * getPrimitiveManager() const + { + return &m_primitive_manager; + } + + //! Obtains the compopund primitive manager + SIMD_FORCE_INLINE CompoundPrimitiveManager * getCompoundPrimitiveManager() + { + return &m_primitive_manager; + } + + //! Gets the number of children + virtual int getNumChildShapes() const + { + return m_childShapes.size(); + } + + + //! Use this method for adding children. Only Convex shapes are allowed. + void addChildShape(const btTransform& localTransform,btCollisionShape* shape) + { + btAssert(shape->isConvex()); + m_childTransforms.push_back(localTransform); + m_childShapes.push_back(shape); + } + + //! Use this method for adding children. Only Convex shapes are allowed. + void addChildShape(btCollisionShape* shape) + { + btAssert(shape->isConvex()); + m_childShapes.push_back(shape); + } + + //! Gets the children + virtual btCollisionShape* getChildShape(int index) + { + return m_childShapes[index]; + } + + //! Gets the children + virtual const btCollisionShape* getChildShape(int index) const + { + return m_childShapes[index]; + } + + //! Retrieves the bound from a child + /*! + */ + virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + + if(childrenHasTransform()) + { + m_childShapes[child_index]->getAabb(t*m_childTransforms[child_index],aabbMin,aabbMax); + } + else + { + m_childShapes[child_index]->getAabb(t,aabbMin,aabbMax); + } + } + + + //! Gets the children transform + virtual btTransform getChildTransform(int index) const + { + btAssert(m_childTransforms.size() == m_childShapes.size()); + return m_childTransforms[index]; + } + + //! Sets the children transform + /*! + \post You must call updateBound() for update the box set. + */ + virtual void setChildTransform(int index, const btTransform & transform) + { + btAssert(m_childTransforms.size() == m_childShapes.size()); + m_childTransforms[index] = transform; + postUpdate(); + } + + //! Determines if this shape has triangles + virtual bool needsRetrieveTriangles() const + { + return false; + } + + //! Determines if this shape has tetrahedrons + virtual bool needsRetrieveTetrahedrons() const + { + return false; + } + + + virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const + { + (void) prim_index; (void) triangle; + btAssert(0); + } + + virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const + { + (void) prim_index; (void) tetrahedron; + btAssert(0); + } + + + //! Calculates the exact inertia tensor for this shape + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual const char* getName()const + { + return "GImpactCompound"; + } + + virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const + { + return CONST_GIMPACT_COMPOUND_SHAPE; + } + +}; + + + +//! This class manages a sub part of a mesh supplied by the btStridingMeshInterface interface. +/*! +- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShapePart, then you must call updateBound() after creating the mesh +- When making operations with this shape, you must call lock before accessing to the trimesh primitives, and then call unlock +- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices. + +*/ +class btGImpactMeshShapePart : public btGImpactShapeInterface +{ +public: + //! Trimesh primitive manager + /*! + Manages the info from btStridingMeshInterface object and controls the Lock/Unlock mechanism + */ + class TrimeshPrimitiveManager:public btPrimitiveManagerBase + { + public: + btScalar m_margin; + btStridingMeshInterface * m_meshInterface; + btVector3 m_scale; + int m_part; + int m_lock_count; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + TrimeshPrimitiveManager() + { + m_meshInterface = NULL; + m_part = 0; + m_margin = 0.01f; + m_scale = btVector3(1.f,1.f,1.f); + m_lock_count = 0; + vertexbase = 0; + numverts = 0; + stride = 0; + indexbase = 0; + indexstride = 0; + numfaces = 0; + } + + TrimeshPrimitiveManager(const TrimeshPrimitiveManager & manager) + : btPrimitiveManagerBase() + { + m_meshInterface = manager.m_meshInterface; + m_part = manager.m_part; + m_margin = manager.m_margin; + m_scale = manager.m_scale; + m_lock_count = 0; + vertexbase = 0; + numverts = 0; + stride = 0; + indexbase = 0; + indexstride = 0; + numfaces = 0; + + } + + TrimeshPrimitiveManager( + btStridingMeshInterface * meshInterface, int part) + { + m_meshInterface = meshInterface; + m_part = part; + m_scale = m_meshInterface->getScaling(); + m_margin = 0.1f; + m_lock_count = 0; + vertexbase = 0; + numverts = 0; + stride = 0; + indexbase = 0; + indexstride = 0; + numfaces = 0; + + } + + virtual ~TrimeshPrimitiveManager() {} + + void lock() + { + if(m_lock_count>0) + { + m_lock_count++; + return; + } + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase,numverts, + type, stride,&indexbase, indexstride, numfaces,indicestype,m_part); + + m_lock_count = 1; + } + + void unlock() + { + if(m_lock_count == 0) return; + if(m_lock_count>1) + { + --m_lock_count; + return; + } + m_meshInterface->unLockReadOnlyVertexBase(m_part); + vertexbase = NULL; + m_lock_count = 0; + } + + virtual bool is_trimesh() const + { + return true; + } + + virtual int get_primitive_count() const + { + return (int )numfaces; + } + + SIMD_FORCE_INLINE int get_vertex_count() const + { + return (int )numverts; + } + + SIMD_FORCE_INLINE void get_indices(int face_index,int &i0,int &i1,int &i2) const + { + if(indicestype == PHY_SHORT) + { + short * s_indices = (short *)(indexbase + face_index*indexstride); + i0 = s_indices[0]; + i1 = s_indices[1]; + i2 = s_indices[2]; + } + else + { + int * i_indices = (int *)(indexbase + face_index*indexstride); + i0 = i_indices[0]; + i1 = i_indices[1]; + i2 = i_indices[2]; + } + } + + SIMD_FORCE_INLINE void get_vertex(int vertex_index, btVector3 & vertex) const + { + if(type == PHY_DOUBLE) + { + double * dvertices = (double *)(vertexbase + vertex_index*stride); + vertex[0] = btScalar(dvertices[0]*m_scale[0]); + vertex[1] = btScalar(dvertices[1]*m_scale[1]); + vertex[2] = btScalar(dvertices[2]*m_scale[2]); + } + else + { + float * svertices = (float *)(vertexbase + vertex_index*stride); + vertex[0] = svertices[0]*m_scale[0]; + vertex[1] = svertices[1]*m_scale[1]; + vertex[2] = svertices[2]*m_scale[2]; + } + } + + virtual void get_primitive_box(int prim_index ,btAABB & primbox) const + { + btPrimitiveTriangle triangle; + get_primitive_triangle(prim_index,triangle); + primbox.calc_from_triangle_margin( + triangle.m_vertices[0], + triangle.m_vertices[1],triangle.m_vertices[2],triangle.m_margin); + } + + virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const + { + int indices[3]; + get_indices(prim_index,indices[0],indices[1],indices[2]); + get_vertex(indices[0],triangle.m_vertices[0]); + get_vertex(indices[1],triangle.m_vertices[1]); + get_vertex(indices[2],triangle.m_vertices[2]); + triangle.m_margin = m_margin; + } + + SIMD_FORCE_INLINE void get_bullet_triangle(int prim_index,btTriangleShapeEx & triangle) const + { + int indices[3]; + get_indices(prim_index,indices[0],indices[1],indices[2]); + get_vertex(indices[0],triangle.m_vertices1[0]); + get_vertex(indices[1],triangle.m_vertices1[1]); + get_vertex(indices[2],triangle.m_vertices1[2]); + triangle.setMargin(m_margin); + } + + }; + + +protected: + TrimeshPrimitiveManager m_primitive_manager; +public: + + btGImpactMeshShapePart() + { + m_box_set.setPrimitiveManager(&m_primitive_manager); + } + + + btGImpactMeshShapePart(btStridingMeshInterface * meshInterface, int part) + { + m_primitive_manager.m_meshInterface = meshInterface; + m_primitive_manager.m_part = part; + m_box_set.setPrimitiveManager(&m_primitive_manager); + } + + virtual ~btGImpactMeshShapePart() + { + } + + //! if true, then its children must get transforms. + virtual bool childrenHasTransform() const + { + return false; + } + + + //! call when reading child shapes + virtual void lockChildShapes() const + { + void * dummy = (void*)(m_box_set.getPrimitiveManager()); + TrimeshPrimitiveManager * dummymanager = static_cast(dummy); + dummymanager->lock(); + } + + virtual void unlockChildShapes() const + { + void * dummy = (void*)(m_box_set.getPrimitiveManager()); + TrimeshPrimitiveManager * dummymanager = static_cast(dummy); + dummymanager->unlock(); + } + + //! Gets the number of children + virtual int getNumChildShapes() const + { + return m_primitive_manager.get_primitive_count(); + } + + + //! Gets the children + virtual btCollisionShape* getChildShape(int index) + { + (void) index; + btAssert(0); + return NULL; + } + + + + //! Gets the child + virtual const btCollisionShape* getChildShape(int index) const + { + (void) index; + btAssert(0); + return NULL; + } + + //! Gets the children transform + virtual btTransform getChildTransform(int index) const + { + (void) index; + btAssert(0); + return btTransform(); + } + + //! Sets the children transform + /*! + \post You must call updateBound() for update the box set. + */ + virtual void setChildTransform(int index, const btTransform & transform) + { + (void) index; + (void) transform; + btAssert(0); + } + + + //! Obtains the primitive manager + virtual const btPrimitiveManagerBase * getPrimitiveManager() const + { + return &m_primitive_manager; + } + + SIMD_FORCE_INLINE TrimeshPrimitiveManager * getTrimeshPrimitiveManager() + { + return &m_primitive_manager; + } + + + + + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + + + + virtual const char* getName()const + { + return "GImpactMeshShapePart"; + } + + virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const + { + return CONST_GIMPACT_TRIMESH_SHAPE_PART; + } + + //! Determines if this shape has triangles + virtual bool needsRetrieveTriangles() const + { + return true; + } + + //! Determines if this shape has tetrahedrons + virtual bool needsRetrieveTetrahedrons() const + { + return false; + } + + virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const + { + m_primitive_manager.get_bullet_triangle(prim_index,triangle); + } + + virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const + { + (void) prim_index; + (void) tetrahedron; + btAssert(0); + } + + + + SIMD_FORCE_INLINE int getVertexCount() const + { + return m_primitive_manager.get_vertex_count(); + } + + SIMD_FORCE_INLINE void getVertex(int vertex_index, btVector3 & vertex) const + { + m_primitive_manager.get_vertex(vertex_index,vertex); + } + + SIMD_FORCE_INLINE void setMargin(btScalar margin) + { + m_primitive_manager.m_margin = margin; + postUpdate(); + } + + SIMD_FORCE_INLINE btScalar getMargin() const + { + return m_primitive_manager.m_margin; + } + + virtual void setLocalScaling(const btVector3& scaling) + { + m_primitive_manager.m_scale = scaling; + postUpdate(); + } + + virtual const btVector3& getLocalScaling() const + { + return m_primitive_manager.m_scale; + } + + SIMD_FORCE_INLINE int getPart() const + { + return (int)m_primitive_manager.m_part; + } + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; +}; + + +//! This class manages a mesh supplied by the btStridingMeshInterface interface. +/*! +Set of btGImpactMeshShapePart parts +- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShape, then you must call updateBound() after creating the mesh + +- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices. + +*/ +class btGImpactMeshShape : public btGImpactShapeInterface +{ + btStridingMeshInterface* m_meshInterface; + +protected: + btAlignedObjectArray m_mesh_parts; + void buildMeshParts(btStridingMeshInterface * meshInterface) + { + for (int i=0;igetNumSubParts() ;++i ) + { + btGImpactMeshShapePart * newpart = new btGImpactMeshShapePart(meshInterface,i); + m_mesh_parts.push_back(newpart); + } + } + + //! use this function for perfofm refit in bounding boxes + virtual void calcLocalAABB() + { + m_localAABB.invalidate(); + int i = m_mesh_parts.size(); + while(i--) + { + m_mesh_parts[i]->updateBound(); + m_localAABB.merge(m_mesh_parts[i]->getLocalBox()); + } + } + +public: + btGImpactMeshShape(btStridingMeshInterface * meshInterface) + { + m_meshInterface = meshInterface; + buildMeshParts(meshInterface); + } + + virtual ~btGImpactMeshShape() + { + int i = m_mesh_parts.size(); + while(i--) + { + btGImpactMeshShapePart * part = m_mesh_parts[i]; + delete part; + } + m_mesh_parts.clear(); + } + + + btStridingMeshInterface* getMeshInterface() + { + return m_meshInterface; + } + + const btStridingMeshInterface* getMeshInterface() const + { + return m_meshInterface; + } + + int getMeshPartCount() const + { + return m_mesh_parts.size(); + } + + btGImpactMeshShapePart * getMeshPart(int index) + { + return m_mesh_parts[index]; + } + + + + const btGImpactMeshShapePart * getMeshPart(int index) const + { + return m_mesh_parts[index]; + } + + + virtual void setLocalScaling(const btVector3& scaling) + { + localScaling = scaling; + + int i = m_mesh_parts.size(); + while(i--) + { + btGImpactMeshShapePart * part = m_mesh_parts[i]; + part->setLocalScaling(scaling); + } + + m_needs_update = true; + } + + virtual void setMargin(btScalar margin) + { + m_collisionMargin = margin; + + int i = m_mesh_parts.size(); + while(i--) + { + btGImpactMeshShapePart * part = m_mesh_parts[i]; + part->setMargin(margin); + } + + m_needs_update = true; + } + + //! Tells to this object that is needed to refit all the meshes + virtual void postUpdate() + { + int i = m_mesh_parts.size(); + while(i--) + { + btGImpactMeshShapePart * part = m_mesh_parts[i]; + part->postUpdate(); + } + + m_needs_update = true; + } + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + + //! Obtains the primitive manager + virtual const btPrimitiveManagerBase * getPrimitiveManager() const + { + btAssert(0); + return NULL; + } + + + //! Gets the number of children + virtual int getNumChildShapes() const + { + btAssert(0); + return 0; + } + + + //! if true, then its children must get transforms. + virtual bool childrenHasTransform() const + { + btAssert(0); + return false; + } + + //! Determines if this shape has triangles + virtual bool needsRetrieveTriangles() const + { + btAssert(0); + return false; + } + + //! Determines if this shape has tetrahedrons + virtual bool needsRetrieveTetrahedrons() const + { + btAssert(0); + return false; + } + + virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const + { + (void) prim_index; (void) triangle; + btAssert(0); + } + + virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const + { + (void) prim_index; (void) tetrahedron; + btAssert(0); + } + + //! call when reading child shapes + virtual void lockChildShapes() const + { + btAssert(0); + } + + virtual void unlockChildShapes() const + { + btAssert(0); + } + + + + + //! Retrieves the bound from a child + /*! + */ + virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + (void) child_index; (void) t; (void) aabbMin; (void) aabbMax; + btAssert(0); + } + + //! Gets the children + virtual btCollisionShape* getChildShape(int index) + { + (void) index; + btAssert(0); + return NULL; + } + + + //! Gets the child + virtual const btCollisionShape* getChildShape(int index) const + { + (void) index; + btAssert(0); + return NULL; + } + + //! Gets the children transform + virtual btTransform getChildTransform(int index) const + { + (void) index; + btAssert(0); + return btTransform(); + } + + //! Sets the children transform + /*! + \post You must call updateBound() for update the box set. + */ + virtual void setChildTransform(int index, const btTransform & transform) + { + (void) index; (void) transform; + btAssert(0); + } + + + virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const + { + return CONST_GIMPACT_TRIMESH_SHAPE; + } + + + virtual const char* getName()const + { + return "GImpactMesh"; + } + + virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const; + + //! Function for retrieve triangles. + /*! + It gives the triangles in local space + */ + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btGImpactMeshShapeData +{ + btCollisionShapeData m_collisionShapeData; + + btStridingMeshInterfaceData m_meshInterface; + + btVector3FloatData m_localScaling; + + float m_collisionMargin; + + int m_gimpactSubType; +}; + +SIMD_FORCE_INLINE int btGImpactMeshShape::calculateSerializeBufferSize() const +{ + return sizeof(btGImpactMeshShapeData); +} + + +#endif //GIMPACT_MESH_SHAPE_H diff --git a/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp b/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp new file mode 100644 index 0000000..5d07d1a --- /dev/null +++ b/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp @@ -0,0 +1,283 @@ +/*! \file btGenericPoolAllocator.cpp +\author Francisco Leon Najera. email projectileman@yahoo.com + +General purpose allocator class +*/ +/* +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 "btGenericPoolAllocator.h" + + + +/// *************** btGenericMemoryPool ******************/////////// + +size_t btGenericMemoryPool::allocate_from_free_nodes(size_t num_elements) +{ + size_t ptr = BT_UINT_MAX; + + if(m_free_nodes_count == 0) return BT_UINT_MAX; + // find an avaliable free node with the correct size + size_t revindex = m_free_nodes_count; + + while(revindex-- && ptr == BT_UINT_MAX) + { + if(m_allocated_sizes[m_free_nodes[revindex]]>=num_elements) + { + ptr = revindex; + } + } + if(ptr == BT_UINT_MAX) return BT_UINT_MAX; // not found + + + revindex = ptr; + ptr = m_free_nodes[revindex]; + // post: ptr contains the node index, and revindex the index in m_free_nodes + + size_t finalsize = m_allocated_sizes[ptr]; + finalsize -= num_elements; + + m_allocated_sizes[ptr] = num_elements; + + // post: finalsize>=0, m_allocated_sizes[ptr] has the requested size + + if(finalsize>0) // preserve free node, there are some free memory + { + m_free_nodes[revindex] = ptr + num_elements; + m_allocated_sizes[ptr + num_elements] = finalsize; + } + else // delete free node + { + // swap with end + m_free_nodes[revindex] = m_free_nodes[m_free_nodes_count-1]; + m_free_nodes_count--; + } + + return ptr; +} + +size_t btGenericMemoryPool::allocate_from_pool(size_t num_elements) +{ + if(m_allocated_count+num_elements>m_max_element_count) return BT_UINT_MAX; + + size_t ptr = m_allocated_count; + + m_allocated_sizes[m_allocated_count] = num_elements; + m_allocated_count+=num_elements; + + return ptr; +} + + +void btGenericMemoryPool::init_pool(size_t element_size, size_t element_count) +{ + m_allocated_count = 0; + m_free_nodes_count = 0; + + m_element_size = element_size; + m_max_element_count = element_count; + + + + + m_pool = (unsigned char *) btAlignedAlloc(m_element_size*m_max_element_count,16); + m_free_nodes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16); + m_allocated_sizes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16); + + for (size_t i = 0;i< m_max_element_count;i++ ) + { + m_allocated_sizes[i] = 0; + } +} + +void btGenericMemoryPool::end_pool() +{ + btAlignedFree(m_pool); + btAlignedFree(m_free_nodes); + btAlignedFree(m_allocated_sizes); + m_allocated_count = 0; + m_free_nodes_count = 0; +} + + +//! Allocates memory in pool +/*! +\param size_bytes size in bytes of the buffer +*/ +void * btGenericMemoryPool::allocate(size_t size_bytes) +{ + + size_t module = size_bytes%m_element_size; + size_t element_count = size_bytes/m_element_size; + if(module>0) element_count++; + + size_t alloc_pos = allocate_from_free_nodes(element_count); + // a free node is found + if(alloc_pos != BT_UINT_MAX) + { + return get_element_data(alloc_pos); + } + // allocate directly on pool + alloc_pos = allocate_from_pool(element_count); + + if(alloc_pos == BT_UINT_MAX) return NULL; // not space + return get_element_data(alloc_pos); +} + +bool btGenericMemoryPool::freeMemory(void * pointer) +{ + unsigned char * pointer_pos = (unsigned char *)pointer; + unsigned char * pool_pos = (unsigned char *)m_pool; + // calc offset + if(pointer_pos=get_pool_capacity()) return false;// far away + + // find free position + m_free_nodes[m_free_nodes_count] = offset/m_element_size; + m_free_nodes_count++; + return true; +} + + +/// *******************! btGenericPoolAllocator *******************!/// + + +btGenericPoolAllocator::~btGenericPoolAllocator() +{ + // destroy pools + size_t i; + for (i=0;iend_pool(); + btAlignedFree(m_pools[i]); + } +} + + +// creates a pool +btGenericMemoryPool * btGenericPoolAllocator::push_new_pool() +{ + if(m_pool_count >= BT_DEFAULT_MAX_POOLS) return NULL; + + btGenericMemoryPool * newptr = (btGenericMemoryPool *)btAlignedAlloc(sizeof(btGenericMemoryPool),16); + + m_pools[m_pool_count] = newptr; + + m_pools[m_pool_count]->init_pool(m_pool_element_size,m_pool_element_count); + + m_pool_count++; + return newptr; +} + +void * btGenericPoolAllocator::failback_alloc(size_t size_bytes) +{ + + btGenericMemoryPool * pool = NULL; + + + if(size_bytes<=get_pool_capacity()) + { + pool = push_new_pool(); + } + + if(pool==NULL) // failback + { + return btAlignedAlloc(size_bytes,16); + } + + return pool->allocate(size_bytes); +} + +bool btGenericPoolAllocator::failback_free(void * pointer) +{ + btAlignedFree(pointer); + return true; +} + + +//! Allocates memory in pool +/*! +\param size_bytes size in bytes of the buffer +*/ +void * btGenericPoolAllocator::allocate(size_t size_bytes) +{ + void * ptr = NULL; + + size_t i = 0; + while(iallocate(size_bytes); + ++i; + } + + if(ptr) return ptr; + + return failback_alloc(size_bytes); +} + +bool btGenericPoolAllocator::freeMemory(void * pointer) +{ + bool result = false; + + size_t i = 0; + while(ifreeMemory(pointer); + ++i; + } + + if(result) return true; + + return failback_free(pointer); +} + +/// ************** STANDARD ALLOCATOR ***************************/// + + +#define BT_DEFAULT_POOL_SIZE 32768 +#define BT_DEFAULT_POOL_ELEMENT_SIZE 8 + +// main allocator +class GIM_STANDARD_ALLOCATOR: public btGenericPoolAllocator +{ +public: + GIM_STANDARD_ALLOCATOR():btGenericPoolAllocator(BT_DEFAULT_POOL_ELEMENT_SIZE,BT_DEFAULT_POOL_SIZE) + { + } +}; + +// global allocator +GIM_STANDARD_ALLOCATOR g_main_allocator; + + +void * btPoolAlloc(size_t size) +{ + return g_main_allocator.allocate(size); +} + +void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize) +{ + void * newptr = btPoolAlloc(newsize); + size_t copysize = oldsize +#include +#include +#include "LinearMath/btAlignedAllocator.h" + +#define BT_UINT_MAX UINT_MAX +#define BT_DEFAULT_MAX_POOLS 16 + + +//! Generic Pool class +class btGenericMemoryPool +{ +public: + unsigned char * m_pool; //[m_element_size*m_max_element_count]; + size_t * m_free_nodes; //[m_max_element_count];//! free nodes + size_t * m_allocated_sizes;//[m_max_element_count];//! Number of elements allocated per node + size_t m_allocated_count; + size_t m_free_nodes_count; +protected: + size_t m_element_size; + size_t m_max_element_count; + + size_t allocate_from_free_nodes(size_t num_elements); + size_t allocate_from_pool(size_t num_elements); + +public: + + void init_pool(size_t element_size, size_t element_count); + + void end_pool(); + + + btGenericMemoryPool(size_t element_size, size_t element_count) + { + init_pool(element_size, element_count); + } + + ~btGenericMemoryPool() + { + end_pool(); + } + + + inline size_t get_pool_capacity() + { + return m_element_size*m_max_element_count; + } + + inline size_t gem_element_size() + { + return m_element_size; + } + + inline size_t get_max_element_count() + { + return m_max_element_count; + } + + inline size_t get_allocated_count() + { + return m_allocated_count; + } + + inline size_t get_free_positions_count() + { + return m_free_nodes_count; + } + + inline void * get_element_data(size_t element_index) + { + return &m_pool[element_index*m_element_size]; + } + + //! Allocates memory in pool + /*! + \param size_bytes size in bytes of the buffer + */ + void * allocate(size_t size_bytes); + + bool freeMemory(void * pointer); +}; + + + + +//! Generic Allocator with pools +/*! +General purpose Allocator which can create Memory Pools dynamiacally as needed. +*/ +class btGenericPoolAllocator +{ +protected: + size_t m_pool_element_size; + size_t m_pool_element_count; +public: + btGenericMemoryPool * m_pools[BT_DEFAULT_MAX_POOLS]; + size_t m_pool_count; + + + inline size_t get_pool_capacity() + { + return m_pool_element_size*m_pool_element_count; + } + + +protected: + // creates a pool + btGenericMemoryPool * push_new_pool(); + + void * failback_alloc(size_t size_bytes); + + bool failback_free(void * pointer); +public: + + btGenericPoolAllocator(size_t pool_element_size, size_t pool_element_count) + { + m_pool_count = 0; + m_pool_element_size = pool_element_size; + m_pool_element_count = pool_element_count; + } + + virtual ~btGenericPoolAllocator(); + + //! Allocates memory in pool + /*! + \param size_bytes size in bytes of the buffer + */ + void * allocate(size_t size_bytes); + + bool freeMemory(void * pointer); +}; + + + +void * btPoolAlloc(size_t size); +void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize); +void btPoolFree(void *ptr); + + +#endif diff --git a/src/BulletCollision/Gimpact/btGeometryOperations.h b/src/BulletCollision/Gimpact/btGeometryOperations.h new file mode 100644 index 0000000..60f0651 --- /dev/null +++ b/src/BulletCollision/Gimpact/btGeometryOperations.h @@ -0,0 +1,212 @@ +#ifndef BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED +#define BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED + +/*! \file btGeometryOperations.h +*\author Francisco Leon Najera + +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +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 "btBoxCollision.h" + + + + + +#define PLANEDIREPSILON 0.0000001f +#define PARALELENORMALS 0.000001f + + +#define BT_CLAMP(number,minval,maxval) (numbermaxval?maxval:number)) + +/// Calc a plane from a triangle edge an a normal. plane is a vec4f +SIMD_FORCE_INLINE void bt_edge_plane(const btVector3 & e1,const btVector3 & e2, const btVector3 & normal,btVector4 & plane) +{ + btVector3 planenormal = (e2-e1).cross(normal); + planenormal.normalize(); + plane.setValue(planenormal[0],planenormal[1],planenormal[2],e2.dot(planenormal)); +} + + + +//***************** SEGMENT and LINE FUNCTIONS **********************************/// + +/*! Finds the closest point(cp) to (v) on a segment (e1,e2) + */ +SIMD_FORCE_INLINE void bt_closest_point_on_segment( + btVector3 & cp, const btVector3 & v, + const btVector3 &e1,const btVector3 &e2) +{ + btVector3 n = e2-e1; + cp = v - e1; + btScalar _scalar = cp.dot(n)/n.dot(n); + if(_scalar <0.0f) + { + cp = e1; + } + else if(_scalar >1.0f) + { + cp = e2; + } + else + { + cp = _scalar*n + e1; + } +} + + +//! line plane collision +/*! +*\return + -0 if the ray never intersects + -1 if the ray collides in front + -2 if the ray collides in back +*/ + +SIMD_FORCE_INLINE int bt_line_plane_collision( + const btVector4 & plane, + const btVector3 & vDir, + const btVector3 & vPoint, + btVector3 & pout, + btScalar &tparam, + btScalar tmin, btScalar tmax) +{ + + btScalar _dotdir = vDir.dot(plane); + + if(btFabs(_dotdir)tmax) + { + returnvalue = 0; + tparam = tmax; + } + pout = tparam*vDir + vPoint; + return returnvalue; +} + + +//! Find closest points on segments +SIMD_FORCE_INLINE void bt_segment_collision( + const btVector3 & vA1, + const btVector3 & vA2, + const btVector3 & vB1, + const btVector3 & vB2, + btVector3 & vPointA, + btVector3 & vPointB) +{ + btVector3 AD = vA2 - vA1; + btVector3 BD = vB2 - vB1; + btVector3 N = AD.cross(BD); + btScalar tp = N.length2(); + + btVector4 _M;//plane + + if(tp_M[1]) + { + invert_b_order = true; + BT_SWAP_NUMBERS(_M[0],_M[1]); + } + _M[2] = vA1.dot(AD); + _M[3] = vA2.dot(AD); + //mid points + N[0] = (_M[0]+_M[1])*0.5f; + N[1] = (_M[2]+_M[3])*0.5f; + + if(N[0]=0.0f) + { + if (_dist>m_penetration_depth) + { + m_penetration_depth = _dist; + point_indices[0] = _k; + m_point_count=1; + } + else if ((_dist+SIMD_EPSILON)>=m_penetration_depth) + { + point_indices[m_point_count] = _k; + m_point_count++; + } + } + } + + for ( _k=0;_k0.0f&&dis1>0.0f&&dis2>0.0f) return false; + + // classify points on this triangle + dis0 = bt_distance_point_plane(other.m_plane,m_vertices[0]) - total_margin; + + dis1 = bt_distance_point_plane(other.m_plane,m_vertices[1]) - total_margin; + + dis2 = bt_distance_point_plane(other.m_plane,m_vertices[2]) - total_margin; + + if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false; + + return true; +} + +int btPrimitiveTriangle::clip_triangle(btPrimitiveTriangle & other, btVector3 * clipped_points ) +{ + // edge 0 + + btVector3 temp_points[MAX_TRI_CLIPPING]; + + + btVector4 edgeplane; + + get_edge_plane(0,edgeplane); + + + int clipped_count = bt_plane_clip_triangle( + edgeplane,other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],temp_points); + + if (clipped_count == 0) return 0; + + btVector3 temp_points1[MAX_TRI_CLIPPING]; + + + // edge 1 + get_edge_plane(1,edgeplane); + + + clipped_count = bt_plane_clip_polygon(edgeplane,temp_points,clipped_count,temp_points1); + + if (clipped_count == 0) return 0; + + // edge 2 + get_edge_plane(2,edgeplane); + + clipped_count = bt_plane_clip_polygon( + edgeplane,temp_points1,clipped_count,clipped_points); + + return clipped_count; +} + +bool btPrimitiveTriangle::find_triangle_collision_clip_method(btPrimitiveTriangle & other, GIM_TRIANGLE_CONTACT & contacts) +{ + btScalar margin = m_margin + other.m_margin; + + btVector3 clipped_points[MAX_TRI_CLIPPING]; + int clipped_count; + //create planes + // plane v vs U points + + GIM_TRIANGLE_CONTACT contacts1; + + contacts1.m_separating_normal = m_plane; + + + clipped_count = clip_triangle(other,clipped_points); + + if (clipped_count == 0 ) + { + return false;//Reject + } + + //find most deep interval face1 + contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count); + if (contacts1.m_point_count == 0) return false; // too far + //Normal pointing to this triangle + contacts1.m_separating_normal *= -1.f; + + + //Clip tri1 by tri2 edges + GIM_TRIANGLE_CONTACT contacts2; + contacts2.m_separating_normal = other.m_plane; + + clipped_count = other.clip_triangle(*this,clipped_points); + + if (clipped_count == 0 ) + { + return false;//Reject + } + + //find most deep interval face1 + contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count); + if (contacts2.m_point_count == 0) return false; // too far + + + + + ////check most dir for contacts + if (contacts2.m_penetration_depth0.0f&&dis1>0.0f&&dis2>0.0f) return false; + + // classify points on this triangle + dis0 = bt_distance_point_plane(plane1,m_vertices1[0]) - total_margin; + + dis1 = bt_distance_point_plane(plane1,m_vertices1[1]) - total_margin; + + dis2 = bt_distance_point_plane(plane1,m_vertices1[2]) - total_margin; + + if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false; + + return true; +} + + diff --git a/src/BulletCollision/Gimpact/btTriangleShapeEx.h b/src/BulletCollision/Gimpact/btTriangleShapeEx.h new file mode 100644 index 0000000..973c2ed --- /dev/null +++ b/src/BulletCollision/Gimpact/btTriangleShapeEx.h @@ -0,0 +1,180 @@ +/*! \file btGImpactShape.h +\author Francisco Leon Najera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +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 GIMPACT_TRIANGLE_SHAPE_EX_H +#define GIMPACT_TRIANGLE_SHAPE_EX_H + +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "btBoxCollision.h" +#include "btClipPolygon.h" +#include "btGeometryOperations.h" + + +#define MAX_TRI_CLIPPING 16 + +//! Structure for collision +struct GIM_TRIANGLE_CONTACT +{ + btScalar m_penetration_depth; + int m_point_count; + btVector4 m_separating_normal; + btVector3 m_points[MAX_TRI_CLIPPING]; + + SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT& other) + { + m_penetration_depth = other.m_penetration_depth; + m_separating_normal = other.m_separating_normal; + m_point_count = other.m_point_count; + int i = m_point_count; + while(i--) + { + m_points[i] = other.m_points[i]; + } + } + + GIM_TRIANGLE_CONTACT() + { + } + + GIM_TRIANGLE_CONTACT(const GIM_TRIANGLE_CONTACT& other) + { + copy_from(other); + } + + //! classify points that are closer + void merge_points(const btVector4 & plane, + btScalar margin, const btVector3 * points, int point_count); + +}; + + + +class btPrimitiveTriangle +{ +public: + btVector3 m_vertices[3]; + btVector4 m_plane; + btScalar m_margin; + btScalar m_dummy; + btPrimitiveTriangle():m_margin(0.01f) + { + + } + + + SIMD_FORCE_INLINE void buildTriPlane() + { + btVector3 normal = (m_vertices[1]-m_vertices[0]).cross(m_vertices[2]-m_vertices[0]); + normal.normalize(); + m_plane.setValue(normal[0],normal[1],normal[2],m_vertices[0].dot(normal)); + } + + //! Test if triangles could collide + bool overlap_test_conservative(const btPrimitiveTriangle& other); + + //! Calcs the plane which is paralele to the edge and perpendicular to the triangle plane + /*! + \pre this triangle must have its plane calculated. + */ + SIMD_FORCE_INLINE void get_edge_plane(int edge_index, btVector4 &plane) const + { + const btVector3 & e0 = m_vertices[edge_index]; + const btVector3 & e1 = m_vertices[(edge_index+1)%3]; + bt_edge_plane(e0,e1,m_plane,plane); + } + + void applyTransform(const btTransform& t) + { + m_vertices[0] = t(m_vertices[0]); + m_vertices[1] = t(m_vertices[1]); + m_vertices[2] = t(m_vertices[2]); + } + + //! Clips the triangle against this + /*! + \pre clipped_points must have MAX_TRI_CLIPPING size, and this triangle must have its plane calculated. + \return the number of clipped points + */ + int clip_triangle(btPrimitiveTriangle & other, btVector3 * clipped_points ); + + //! Find collision using the clipping method + /*! + \pre this triangle and other must have their triangles calculated + */ + bool find_triangle_collision_clip_method(btPrimitiveTriangle & other, GIM_TRIANGLE_CONTACT & contacts); +}; + + + +//! Helper class for colliding Bullet Triangle Shapes +/*! +This class implements a better getAabb method than the previous btTriangleShape class +*/ +class btTriangleShapeEx: public btTriangleShape +{ +public: + + btTriangleShapeEx():btTriangleShape(btVector3(0,0,0),btVector3(0,0,0),btVector3(0,0,0)) + { + } + + btTriangleShapeEx(const btVector3& p0,const btVector3& p1,const btVector3& p2): btTriangleShape(p0,p1,p2) + { + } + + btTriangleShapeEx(const btTriangleShapeEx & other): btTriangleShape(other.m_vertices1[0],other.m_vertices1[1],other.m_vertices1[2]) + { + } + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax)const + { + btVector3 tv0 = t(m_vertices1[0]); + btVector3 tv1 = t(m_vertices1[1]); + btVector3 tv2 = t(m_vertices1[2]); + + btAABB trianglebox(tv0,tv1,tv2,m_collisionMargin); + aabbMin = trianglebox.m_min; + aabbMax = trianglebox.m_max; + } + + void applyTransform(const btTransform& t) + { + m_vertices1[0] = t(m_vertices1[0]); + m_vertices1[1] = t(m_vertices1[1]); + m_vertices1[2] = t(m_vertices1[2]); + } + + SIMD_FORCE_INLINE void buildTriPlane(btVector4 & plane) const + { + btVector3 normal = (m_vertices1[1]-m_vertices1[0]).cross(m_vertices1[2]-m_vertices1[0]); + normal.normalize(); + plane.setValue(normal[0],normal[1],normal[2],m_vertices1[0].dot(normal)); + } + + bool overlap_test_conservative(const btTriangleShapeEx& other); +}; + + +#endif //GIMPACT_TRIANGLE_MESH_SHAPE_H diff --git a/src/BulletCollision/Gimpact/gim_array.h b/src/BulletCollision/Gimpact/gim_array.h new file mode 100644 index 0000000..cfd5da8 --- /dev/null +++ b/src/BulletCollision/Gimpact/gim_array.h @@ -0,0 +1,326 @@ +#ifndef GIM_ARRAY_H_INCLUDED +#define GIM_ARRAY_H_INCLUDED +/*! \file gim_array.h +\author Francisco Leon Najera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "gim_memory.h" + + +#define GIM_ARRAY_GROW_INCREMENT 2 +#define GIM_ARRAY_GROW_FACTOR 2 + +//! Very simple array container with fast access and simd memory +template +class gim_array +{ +public: +//! properties +//!@{ + T *m_data; + GUINT m_size; + GUINT m_allocated_size; +//!@} +//! protected operations +//!@{ + + inline void destroyData() + { + m_allocated_size = 0; + if(m_data==NULL) return; + gim_free(m_data); + m_data = NULL; + } + + inline bool resizeData(GUINT newsize) + { + if(newsize==0) + { + destroyData(); + return true; + } + + if(m_size>0) + { + m_data = (T*)gim_realloc(m_data,m_size*sizeof(T),newsize*sizeof(T)); + } + else + { + m_data = (T*)gim_alloc(newsize*sizeof(T)); + } + m_allocated_size = newsize; + return true; + } + + inline bool growingCheck() + { + if(m_allocated_size<=m_size) + { + GUINT requestsize = m_size; + m_size = m_allocated_size; + if(resizeData((requestsize+GIM_ARRAY_GROW_INCREMENT)*GIM_ARRAY_GROW_FACTOR)==false) return false; + } + return true; + } + +//!@} +//! public operations +//!@{ + inline bool reserve(GUINT size) + { + if(m_allocated_size>=size) return false; + return resizeData(size); + } + + inline void clear_range(GUINT start_range) + { + while(m_size>start_range) + { + m_data[--m_size].~T(); + } + } + + inline void clear() + { + if(m_size==0)return; + clear_range(0); + } + + inline void clear_memory() + { + clear(); + destroyData(); + } + + gim_array() + { + m_data = 0; + m_size = 0; + m_allocated_size = 0; + } + + gim_array(GUINT reservesize) + { + m_data = 0; + m_size = 0; + + m_allocated_size = 0; + reserve(reservesize); + } + + ~gim_array() + { + clear_memory(); + } + + inline GUINT size() const + { + return m_size; + } + + inline GUINT max_size() const + { + return m_allocated_size; + } + + inline T & operator[](size_t i) + { + return m_data[i]; + } + inline const T & operator[](size_t i) const + { + return m_data[i]; + } + + inline T * pointer(){ return m_data;} + inline const T * pointer() const + { return m_data;} + + + inline T * get_pointer_at(GUINT i) + { + return m_data + i; + } + + inline const T * get_pointer_at(GUINT i) const + { + return m_data + i; + } + + inline T & at(GUINT i) + { + return m_data[i]; + } + + inline const T & at(GUINT i) const + { + return m_data[i]; + } + + inline T & front() + { + return *m_data; + } + + inline const T & front() const + { + return *m_data; + } + + inline T & back() + { + return m_data[m_size-1]; + } + + inline const T & back() const + { + return m_data[m_size-1]; + } + + + inline void swap(GUINT i, GUINT j) + { + gim_swap_elements(m_data,i,j); + } + + inline void push_back(const T & obj) + { + this->growingCheck(); + m_data[m_size] = obj; + m_size++; + } + + //!Simply increase the m_size, doesn't call the new element constructor + inline void push_back_mem() + { + this->growingCheck(); + m_size++; + } + + inline void push_back_memcpy(const T & obj) + { + this->growingCheck(); + irr_simd_memcpy(&m_data[m_size],&obj,sizeof(T)); + m_size++; + } + + inline void pop_back() + { + m_size--; + m_data[m_size].~T(); + } + + //!Simply decrease the m_size, doesn't call the deleted element destructor + inline void pop_back_mem() + { + m_size--; + } + + //! fast erase + inline void erase(GUINT index) + { + if(indexgrowingCheck(); + for(GUINT i = m_size;i>index;i--) + { + gim_simd_memcpy(m_data+i,m_data+i-1,sizeof(T)); + } + m_size++; + } + + inline void insert(const T & obj,GUINT index) + { + insert_mem(index); + m_data[index] = obj; + } + + inline void resize(GUINT size, bool call_constructor = true) + { + + if(size>m_size) + { + reserve(size); + if(call_constructor) + { + T obj; + while(m_size +SIMD_FORCE_INLINE bool POINT_IN_HULL( + const CLASS_POINT& point,const CLASS_PLANE * planes,GUINT plane_count) +{ + GREAL _dis; + for (GUINT _i = 0;_i< plane_count;++_i) + { + _dis = DISTANCE_PLANE_POINT(planes[_i],point); + if(_dis>0.0f) return false; + } + return true; +} + +template +SIMD_FORCE_INLINE void PLANE_CLIP_SEGMENT( + const CLASS_POINT& s1, + const CLASS_POINT &s2,const CLASS_PLANE &plane,CLASS_POINT &clipped) +{ + GREAL _dis1,_dis2; + _dis1 = DISTANCE_PLANE_POINT(plane,s1); + VEC_DIFF(clipped,s2,s1); + _dis2 = VEC_DOT(clipped,plane); + VEC_SCALE(clipped,-_dis1/_dis2,clipped); + VEC_SUM(clipped,clipped,s1); +} + +enum ePLANE_INTERSECTION_TYPE +{ + G_BACK_PLANE = 0, + G_COLLIDE_PLANE, + G_FRONT_PLANE +}; + +enum eLINE_PLANE_INTERSECTION_TYPE +{ + G_FRONT_PLANE_S1 = 0, + G_FRONT_PLANE_S2, + G_BACK_PLANE_S1, + G_BACK_PLANE_S2, + G_COLLIDE_PLANE_S1, + G_COLLIDE_PLANE_S2 +}; + +//! Confirms if the plane intersect the edge or nor +/*! +intersection type must have the following values +
        +
      • 0 : Segment in front of plane, s1 closest +
      • 1 : Segment in front of plane, s2 closest +
      • 2 : Segment in back of plane, s1 closest +
      • 3 : Segment in back of plane, s2 closest +
      • 4 : Segment collides plane, s1 in back +
      • 5 : Segment collides plane, s2 in back +
      +*/ + +template +SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT2( + const CLASS_POINT& s1, + const CLASS_POINT &s2, + const CLASS_PLANE &plane,CLASS_POINT &clipped) +{ + GREAL _dis1 = DISTANCE_PLANE_POINT(plane,s1); + GREAL _dis2 = DISTANCE_PLANE_POINT(plane,s2); + if(_dis1 >-G_EPSILON && _dis2 >-G_EPSILON) + { + if(_dis1<_dis2) return G_FRONT_PLANE_S1; + return G_FRONT_PLANE_S2; + } + else if(_dis1 _dis2) return G_BACK_PLANE_S1; + return G_BACK_PLANE_S2; + } + + VEC_DIFF(clipped,s2,s1); + _dis2 = VEC_DOT(clipped,plane); + VEC_SCALE(clipped,-_dis1/_dis2,clipped); + VEC_SUM(clipped,clipped,s1); + if(_dis1<_dis2) return G_COLLIDE_PLANE_S1; + return G_COLLIDE_PLANE_S2; +} + +//! Confirms if the plane intersect the edge or not +/*! +clipped1 and clipped2 are the vertices behind the plane. +clipped1 is the closest + +intersection_type must have the following values +
        +
      • 0 : Segment in front of plane, s1 closest +
      • 1 : Segment in front of plane, s2 closest +
      • 2 : Segment in back of plane, s1 closest +
      • 3 : Segment in back of plane, s2 closest +
      • 4 : Segment collides plane, s1 in back +
      • 5 : Segment collides plane, s2 in back +
      +*/ +template +SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT_CLOSEST( + const CLASS_POINT& s1, + const CLASS_POINT &s2, + const CLASS_PLANE &plane, + CLASS_POINT &clipped1,CLASS_POINT &clipped2) +{ + eLINE_PLANE_INTERSECTION_TYPE intersection_type = PLANE_CLIP_SEGMENT2(s1,s2,plane,clipped1); + switch(intersection_type) + { + case G_FRONT_PLANE_S1: + VEC_COPY(clipped1,s1); + VEC_COPY(clipped2,s2); + break; + case G_FRONT_PLANE_S2: + VEC_COPY(clipped1,s2); + VEC_COPY(clipped2,s1); + break; + case G_BACK_PLANE_S1: + VEC_COPY(clipped1,s1); + VEC_COPY(clipped2,s2); + break; + case G_BACK_PLANE_S2: + VEC_COPY(clipped1,s2); + VEC_COPY(clipped2,s1); + break; + case G_COLLIDE_PLANE_S1: + VEC_COPY(clipped2,s1); + break; + case G_COLLIDE_PLANE_S2: + VEC_COPY(clipped2,s2); + break; + } + return intersection_type; +} + + +//! Finds the 2 smallest cartesian coordinates of a plane normal +#define PLANE_MINOR_AXES(plane, i0, i1) VEC_MINOR_AXES(plane, i0, i1) + +//! Ray plane collision in one way +/*! +Intersects plane in one way only. The ray must face the plane (normals must be in opossite directions).
      +It uses the PLANEDIREPSILON constant. +*/ +template +SIMD_FORCE_INLINE bool RAY_PLANE_COLLISION( + const CLASS_PLANE & plane, + const CLASS_POINT & vDir, + const CLASS_POINT & vPoint, + CLASS_POINT & pout,T &tparam) +{ + GREAL _dis,_dotdir; + _dotdir = VEC_DOT(plane,vDir); + if(_dotdir +SIMD_FORCE_INLINE GUINT LINE_PLANE_COLLISION( + const CLASS_PLANE & plane, + const CLASS_POINT & vDir, + const CLASS_POINT & vPoint, + CLASS_POINT & pout, + T &tparam, + T tmin, T tmax) +{ + GREAL _dis,_dotdir; + _dotdir = VEC_DOT(plane,vDir); + if(btFabs(_dotdir)tmax) + { + returnvalue = 0; + tparam = tmax; + } + + VEC_SCALE(pout,tparam,vDir); + VEC_SUM(pout,vPoint,pout); + return returnvalue; +} + +/*! \brief Returns the Ray on which 2 planes intersect if they do. + Written by Rodrigo Hernandez on ODE convex collision + + \param p1 Plane 1 + \param p2 Plane 2 + \param p Contains the origin of the ray upon returning if planes intersect + \param d Contains the direction of the ray upon returning if planes intersect + \return true if the planes intersect, 0 if paralell. + +*/ +template +SIMD_FORCE_INLINE bool INTERSECT_PLANES( + const CLASS_PLANE &p1, + const CLASS_PLANE &p2, + CLASS_POINT &p, + CLASS_POINT &d) +{ + VEC_CROSS(d,p1,p2); + GREAL denom = VEC_DOT(d, d); + if(GIM_IS_ZERO(denom)) return false; + vec3f _n; + _n[0]=p1[3]*p2[0] - p2[3]*p1[0]; + _n[1]=p1[3]*p2[1] - p2[3]*p1[1]; + _n[2]=p1[3]*p2[2] - p2[3]*p1[2]; + VEC_CROSS(p,_n,d); + p[0]/=denom; + p[1]/=denom; + p[2]/=denom; + return true; +} + +//***************** SEGMENT and LINE FUNCTIONS **********************************/// + +/*! Finds the closest point(cp) to (v) on a segment (e1,e2) + */ +template +SIMD_FORCE_INLINE void CLOSEST_POINT_ON_SEGMENT( + CLASS_POINT & cp, const CLASS_POINT & v, + const CLASS_POINT &e1,const CLASS_POINT &e2) +{ + vec3f _n; + VEC_DIFF(_n,e2,e1); + VEC_DIFF(cp,v,e1); + GREAL _scalar = VEC_DOT(cp, _n); + _scalar/= VEC_DOT(_n, _n); + if(_scalar <0.0f) + { + VEC_COPY(cp,e1); + } + else if(_scalar >1.0f) + { + VEC_COPY(cp,e2); + } + else + { + VEC_SCALE(cp,_scalar,_n); + VEC_SUM(cp,cp,e1); + } +} + + +/*! \brief Finds the line params where these lines intersect. + +\param dir1 Direction of line 1 +\param point1 Point of line 1 +\param dir2 Direction of line 2 +\param point2 Point of line 2 +\param t1 Result Parameter for line 1 +\param t2 Result Parameter for line 2 +\param dointersect 0 if the lines won't intersect, else 1 + +*/ +template +SIMD_FORCE_INLINE bool LINE_INTERSECTION_PARAMS( + const CLASS_POINT & dir1, + CLASS_POINT & point1, + const CLASS_POINT & dir2, + CLASS_POINT & point2, + T& t1,T& t2) +{ + GREAL det; + GREAL e1e1 = VEC_DOT(dir1,dir1); + GREAL e1e2 = VEC_DOT(dir1,dir2); + GREAL e2e2 = VEC_DOT(dir2,dir2); + vec3f p1p2; + VEC_DIFF(p1p2,point1,point2); + GREAL p1p2e1 = VEC_DOT(p1p2,dir1); + GREAL p1p2e2 = VEC_DOT(p1p2,dir2); + det = e1e2*e1e2 - e1e1*e2e2; + if(GIM_IS_ZERO(det)) return false; + t1 = (e1e2*p1p2e2 - e2e2*p1p2e1)/det; + t2 = (e1e1*p1p2e2 - e1e2*p1p2e1)/det; + return true; +} + +//! Find closest points on segments +template +SIMD_FORCE_INLINE void SEGMENT_COLLISION( + const CLASS_POINT & vA1, + const CLASS_POINT & vA2, + const CLASS_POINT & vB1, + const CLASS_POINT & vB2, + CLASS_POINT & vPointA, + CLASS_POINT & vPointB) +{ + CLASS_POINT _AD,_BD,_N; + vec4f _M;//plane + VEC_DIFF(_AD,vA2,vA1); + VEC_DIFF(_BD,vB2,vB1); + VEC_CROSS(_N,_AD,_BD); + GREAL _tp = VEC_DOT(_N,_N); + if(_tp_M[1]) + { + invert_b_order = true; + GIM_SWAP_NUMBERS(_M[0],_M[1]); + } + _M[2] = VEC_DOT(vA1,_AD); + _M[3] = VEC_DOT(vA2,_AD); + //mid points + _N[0] = (_M[0]+_M[1])*0.5f; + _N[1] = (_M[2]+_M[3])*0.5f; + + if(_N[0]<_N[1]) + { + if(_M[1]<_M[2]) + { + vPointB = invert_b_order?vB1:vB2; + vPointA = vA1; + } + else if(_M[1]<_M[3]) + { + vPointB = invert_b_order?vB1:vB2; + CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2); + } + else + { + vPointA = vA2; + CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2); + } + } + else + { + if(_M[3]<_M[0]) + { + vPointB = invert_b_order?vB2:vB1; + vPointA = vA2; + } + else if(_M[3]<_M[1]) + { + vPointA = vA2; + CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2); + } + else + { + vPointB = invert_b_order?vB1:vB2; + CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2); + } + } + return; + } + + + VEC_CROSS(_M,_N,_BD); + _M[3] = VEC_DOT(_M,vB1); + + LINE_PLANE_COLLISION(_M,_AD,vA1,vPointA,_tp,btScalar(0), btScalar(1)); + /*Closest point on segment*/ + VEC_DIFF(vPointB,vPointA,vB1); + _tp = VEC_DOT(vPointB, _BD); + _tp/= VEC_DOT(_BD, _BD); + _tp = GIM_CLAMP(_tp,0.0f,1.0f); + VEC_SCALE(vPointB,_tp,_BD); + VEC_SUM(vPointB,vPointB,vB1); +} + + + + +//! Line box intersection in one dimension +/*! + +*\param pos Position of the ray +*\param dir Projection of the Direction of the ray +*\param bmin Minimum bound of the box +*\param bmax Maximum bound of the box +*\param tfirst the minimum projection. Assign to 0 at first. +*\param tlast the maximum projection. Assign to INFINITY at first. +*\return true if there is an intersection. +*/ +template +SIMD_FORCE_INLINE bool BOX_AXIS_INTERSECT(T pos, T dir,T bmin, T bmax, T & tfirst, T & tlast) +{ + if(GIM_IS_ZERO(dir)) + { + return !(pos < bmin || pos > bmax); + } + GREAL a0 = (bmin - pos) / dir; + GREAL a1 = (bmax - pos) / dir; + if(a0 > a1) GIM_SWAP_NUMBERS(a0, a1); + tfirst = GIM_MAX(a0, tfirst); + tlast = GIM_MIN(a1, tlast); + if (tlast < tfirst) return false; + return true; +} + + +//! Sorts 3 componets +template +SIMD_FORCE_INLINE void SORT_3_INDICES( + const T * values, + GUINT * order_indices) +{ + //get minimum + order_indices[0] = values[0] < values[1] ? (values[0] < values[2] ? 0 : 2) : (values[1] < values[2] ? 1 : 2); + + //get second and third + GUINT i0 = (order_indices[0] + 1)%3; + GUINT i1 = (i0 + 1)%3; + + if(values[i0] < values[i1]) + { + order_indices[1] = i0; + order_indices[2] = i1; + } + else + { + order_indices[1] = i1; + order_indices[2] = i0; + } +} + + + + + +#endif // GIM_VECTOR_H_INCLUDED diff --git a/src/BulletCollision/Gimpact/gim_bitset.h b/src/BulletCollision/Gimpact/gim_bitset.h new file mode 100644 index 0000000..7dee48a --- /dev/null +++ b/src/BulletCollision/Gimpact/gim_bitset.h @@ -0,0 +1,123 @@ +#ifndef GIM_BITSET_H_INCLUDED +#define GIM_BITSET_H_INCLUDED +/*! \file gim_bitset.h +\author Francisco Leon Najera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "gim_array.h" + + +#define GUINT_BIT_COUNT 32 +#define GUINT_EXPONENT 5 + +class gim_bitset +{ +public: + gim_array m_container; + + gim_bitset() + { + + } + + gim_bitset(GUINT bits_count) + { + resize(bits_count); + } + + ~gim_bitset() + { + } + + inline bool resize(GUINT newsize) + { + GUINT oldsize = m_container.size(); + m_container.resize(newsize/GUINT_BIT_COUNT + 1,false); + while(oldsize=size()) + { + resize(bit_index); + } + m_container[bit_index >> GUINT_EXPONENT] |= (1 << (bit_index & (GUINT_BIT_COUNT-1))); + } + + ///Return 0 or 1 + inline char get(GUINT bit_index) + { + if(bit_index>=size()) + { + return 0; + } + char value = m_container[bit_index >> GUINT_EXPONENT] & + (1 << (bit_index & (GUINT_BIT_COUNT-1))); + return value; + } + + inline void clear(GUINT bit_index) + { + m_container[bit_index >> GUINT_EXPONENT] &= ~(1 << (bit_index & (GUINT_BIT_COUNT-1))); + } +}; + + + + + +#endif // GIM_CONTAINERS_H_INCLUDED diff --git a/src/BulletCollision/Gimpact/gim_box_collision.h b/src/BulletCollision/Gimpact/gim_box_collision.h new file mode 100644 index 0000000..b360dd4 --- /dev/null +++ b/src/BulletCollision/Gimpact/gim_box_collision.h @@ -0,0 +1,590 @@ +#ifndef GIM_BOX_COLLISION_H_INCLUDED +#define GIM_BOX_COLLISION_H_INCLUDED + +/*! \file gim_box_collision.h +\author Francisco Leon Najera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ +#include "gim_basic_geometry_operations.h" +#include "LinearMath/btTransform.h" + + + +//SIMD_FORCE_INLINE bool test_cross_edge_box( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, const btVector3 & extend, +// int dir_index0, +// int dir_index1 +// int component_index0, +// int component_index1) +//{ +// // dir coords are -z and y +// +// const btScalar dir0 = -edge[dir_index0]; +// const btScalar dir1 = edge[dir_index1]; +// btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1; +// btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1; +// //find minmax +// if(pmin>pmax) +// { +// GIM_SWAP_NUMBERS(pmin,pmax); +// } +// //find extends +// const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] + +// extend[component_index1] * absolute_edge[dir_index1]; +// +// if(pmin>rad || -rad>pmax) return false; +// return true; +//} +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2); +//} +// +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0); +//} +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1); +//} + +#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\ +{\ + const btScalar dir0 = -edge[i_dir_0];\ + const btScalar dir1 = edge[i_dir_1];\ + btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\ + btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\ + if(pmin>pmax)\ + {\ + GIM_SWAP_NUMBERS(pmin,pmax); \ + }\ + const btScalar abs_dir0 = absolute_edge[i_dir_0];\ + const btScalar abs_dir1 = absolute_edge[i_dir_1];\ + const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\ + if(pmin>rad || -rad>pmax) return false;\ +}\ + + +#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\ +}\ + +#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\ +}\ + +#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\ +}\ + + + +//! Class for transforming a model1 to the space of model0 +class GIM_BOX_BOX_TRANSFORM_CACHE +{ +public: + btVector3 m_T1to0;//!< Transforms translation of model1 to model 0 + btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal to R0' * R1 + btMatrix3x3 m_AR;//!< Absolute value of m_R1to0 + + SIMD_FORCE_INLINE void calc_absolute_matrix() + { + static const btVector3 vepsi(1e-6f,1e-6f,1e-6f); + m_AR[0] = vepsi + m_R1to0[0].absolute(); + m_AR[1] = vepsi + m_R1to0[1].absolute(); + m_AR[2] = vepsi + m_R1to0[2].absolute(); + } + + GIM_BOX_BOX_TRANSFORM_CACHE() + { + } + + + GIM_BOX_BOX_TRANSFORM_CACHE(mat4f trans1_to_0) + { + COPY_MATRIX_3X3(m_R1to0,trans1_to_0) + MAT_GET_TRANSLATION(trans1_to_0,m_T1to0) + calc_absolute_matrix(); + } + + //! Calc the transformation relative 1 to 0. Inverts matrics by transposing + SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1) + { + + m_R1to0 = trans0.getBasis().transpose(); + m_T1to0 = m_R1to0 * (-trans0.getOrigin()); + + m_T1to0 += m_R1to0*trans1.getOrigin(); + m_R1to0 *= trans1.getBasis(); + + calc_absolute_matrix(); + } + + //! Calcs the full invertion of the matrices. Useful for scaling matrices + SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1) + { + m_R1to0 = trans0.getBasis().inverse(); + m_T1to0 = m_R1to0 * (-trans0.getOrigin()); + + m_T1to0 += m_R1to0*trans1.getOrigin(); + m_R1to0 *= trans1.getBasis(); + + calc_absolute_matrix(); + } + + SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point) + { + return btVector3(m_R1to0[0].dot(point) + m_T1to0.x(), + m_R1to0[1].dot(point) + m_T1to0.y(), + m_R1to0[2].dot(point) + m_T1to0.z()); + } +}; + + +#define BOX_PLANE_EPSILON 0.000001f + +//! Axis aligned box +class GIM_AABB +{ +public: + btVector3 m_min; + btVector3 m_max; + + GIM_AABB() + {} + + + GIM_AABB(const btVector3 & V1, + const btVector3 & V2, + const btVector3 & V3) + { + m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]); + } + + GIM_AABB(const btVector3 & V1, + const btVector3 & V2, + const btVector3 & V3, + GREAL margin) + { + m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]); + + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + GIM_AABB(const GIM_AABB &other): + m_min(other.m_min),m_max(other.m_max) + { + } + + GIM_AABB(const GIM_AABB &other,btScalar margin ): + m_min(other.m_min),m_max(other.m_max) + { + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + SIMD_FORCE_INLINE void invalidate() + { + m_min[0] = G_REAL_INFINITY; + m_min[1] = G_REAL_INFINITY; + m_min[2] = G_REAL_INFINITY; + m_max[0] = -G_REAL_INFINITY; + m_max[1] = -G_REAL_INFINITY; + m_max[2] = -G_REAL_INFINITY; + } + + SIMD_FORCE_INLINE void increment_margin(btScalar margin) + { + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + SIMD_FORCE_INLINE void copy_with_margin(const GIM_AABB &other, btScalar margin) + { + m_min[0] = other.m_min[0] - margin; + m_min[1] = other.m_min[1] - margin; + m_min[2] = other.m_min[2] - margin; + + m_max[0] = other.m_max[0] + margin; + m_max[1] = other.m_max[1] + margin; + m_max[2] = other.m_max[2] + margin; + } + + template + SIMD_FORCE_INLINE void calc_from_triangle( + const CLASS_POINT & V1, + const CLASS_POINT & V2, + const CLASS_POINT & V3) + { + m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]); + } + + template + SIMD_FORCE_INLINE void calc_from_triangle_margin( + const CLASS_POINT & V1, + const CLASS_POINT & V2, + const CLASS_POINT & V3, btScalar margin) + { + m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]); + + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + //! Apply a transform to an AABB + SIMD_FORCE_INLINE void appy_transform(const btTransform & trans) + { + btVector3 center = (m_max+m_min)*0.5f; + btVector3 extends = m_max - center; + // Compute new center + center = trans(center); + + btVector3 textends(extends.dot(trans.getBasis().getRow(0).absolute()), + extends.dot(trans.getBasis().getRow(1).absolute()), + extends.dot(trans.getBasis().getRow(2).absolute())); + + m_min = center - textends; + m_max = center + textends; + } + + //! Merges a Box + SIMD_FORCE_INLINE void merge(const GIM_AABB & box) + { + m_min[0] = GIM_MIN(m_min[0],box.m_min[0]); + m_min[1] = GIM_MIN(m_min[1],box.m_min[1]); + m_min[2] = GIM_MIN(m_min[2],box.m_min[2]); + + m_max[0] = GIM_MAX(m_max[0],box.m_max[0]); + m_max[1] = GIM_MAX(m_max[1],box.m_max[1]); + m_max[2] = GIM_MAX(m_max[2],box.m_max[2]); + } + + //! Merges a point + template + SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point) + { + m_min[0] = GIM_MIN(m_min[0],point[0]); + m_min[1] = GIM_MIN(m_min[1],point[1]); + m_min[2] = GIM_MIN(m_min[2],point[2]); + + m_max[0] = GIM_MAX(m_max[0],point[0]); + m_max[1] = GIM_MAX(m_max[1],point[1]); + m_max[2] = GIM_MAX(m_max[2],point[2]); + } + + //! Gets the extend and center + SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const + { + center = (m_max+m_min)*0.5f; + extend = m_max - center; + } + + //! Finds the intersecting box between this box and the other. + SIMD_FORCE_INLINE void find_intersection(const GIM_AABB & other, GIM_AABB & intersection) const + { + intersection.m_min[0] = GIM_MAX(other.m_min[0],m_min[0]); + intersection.m_min[1] = GIM_MAX(other.m_min[1],m_min[1]); + intersection.m_min[2] = GIM_MAX(other.m_min[2],m_min[2]); + + intersection.m_max[0] = GIM_MIN(other.m_max[0],m_max[0]); + intersection.m_max[1] = GIM_MIN(other.m_max[1],m_max[1]); + intersection.m_max[2] = GIM_MIN(other.m_max[2],m_max[2]); + } + + + SIMD_FORCE_INLINE bool has_collision(const GIM_AABB & other) const + { + if(m_min[0] > other.m_max[0] || + m_max[0] < other.m_min[0] || + m_min[1] > other.m_max[1] || + m_max[1] < other.m_min[1] || + m_min[2] > other.m_max[2] || + m_max[2] < other.m_min[2]) + { + return false; + } + return true; + } + + /*! \brief Finds the Ray intersection parameter. + \param aabb Aligned box + \param vorigin A vec3f with the origin of the ray + \param vdir A vec3f with the direction of the ray + */ + SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir) + { + btVector3 extents,center; + this->get_center_extend(center,extents);; + + btScalar Dx = vorigin[0] - center[0]; + if(GIM_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false; + btScalar Dy = vorigin[1] - center[1]; + if(GIM_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false; + btScalar Dz = vorigin[2] - center[2]; + if(GIM_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false; + + + btScalar f = vdir[1] * Dz - vdir[2] * Dy; + if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false; + f = vdir[2] * Dx - vdir[0] * Dz; + if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false; + f = vdir[0] * Dy - vdir[1] * Dx; + if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false; + return true; + } + + + SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const + { + btVector3 center = (m_max+m_min)*0.5f; + btVector3 extend = m_max-center; + + btScalar _fOrigin = direction.dot(center); + btScalar _fMaximumExtent = extend.dot(direction.absolute()); + vmin = _fOrigin - _fMaximumExtent; + vmax = _fOrigin + _fMaximumExtent; + } + + SIMD_FORCE_INLINE ePLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const + { + btScalar _fmin,_fmax; + this->projection_interval(plane,_fmin,_fmax); + + if(plane[3] > _fmax + BOX_PLANE_EPSILON) + { + return G_BACK_PLANE; // 0 + } + + if(plane[3]+BOX_PLANE_EPSILON >=_fmin) + { + return G_COLLIDE_PLANE; //1 + } + return G_FRONT_PLANE;//2 + } + + SIMD_FORCE_INLINE bool overlapping_trans_conservative(const GIM_AABB & box, btTransform & trans1_to_0) + { + GIM_AABB tbox = box; + tbox.appy_transform(trans1_to_0); + return has_collision(tbox); + } + + //! transcache is the transformation cache from box to this AABB + SIMD_FORCE_INLINE bool overlapping_trans_cache( + const GIM_AABB & box,const GIM_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest) + { + + //Taken from OPCODE + btVector3 ea,eb;//extends + btVector3 ca,cb;//extends + get_center_extend(ca,ea); + box.get_center_extend(cb,eb); + + + btVector3 T; + btScalar t,t2; + int i; + + // Class I : A's basis vectors + for(i=0;i<3;i++) + { + T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i]; + t = transcache.m_AR[i].dot(eb) + ea[i]; + if(GIM_GREATER(T[i], t)) return false; + } + // Class II : B's basis vectors + for(i=0;i<3;i++) + { + t = MAT_DOT_COL(transcache.m_R1to0,T,i); + t2 = MAT_DOT_COL(transcache.m_AR,ea,i) + eb[i]; + if(GIM_GREATER(t,t2)) return false; + } + // Class III : 9 cross products + if(fulltest) + { + int j,m,n,o,p,q,r; + for(i=0;i<3;i++) + { + m = (i+1)%3; + n = (i+2)%3; + o = i==0?1:0; + p = i==2?1:2; + for(j=0;j<3;j++) + { + q = j==2?1:2; + r = j==0?1:0; + t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j]; + t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] + + eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r]; + if(GIM_GREATER(t,t2)) return false; + } + } + } + return true; + } + + //! Simple test for planes. + SIMD_FORCE_INLINE bool collide_plane( + const btVector4 & plane) + { + ePLANE_INTERSECTION_TYPE classify = plane_classify(plane); + return (classify == G_COLLIDE_PLANE); + } + + //! test for a triangle, with edges + SIMD_FORCE_INLINE bool collide_triangle_exact( + const btVector3 & p1, + const btVector3 & p2, + const btVector3 & p3, + const btVector4 & triangle_plane) + { + if(!collide_plane(triangle_plane)) return false; + + btVector3 center,extends; + this->get_center_extend(center,extends); + + const btVector3 v1(p1 - center); + const btVector3 v2(p2 - center); + const btVector3 v3(p3 - center); + + //First axis + btVector3 diff(v2 - v1); + btVector3 abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends); + + + diff = v3 - v2; + abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends); + + diff = v1 - v3; + abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends); + + return true; + } +}; + + +//! Compairison of transformation objects +SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2) +{ + if(!(t1.getOrigin() == t2.getOrigin()) ) return false; + + if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false; + if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false; + if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false; + return true; +} + + + +#endif // GIM_BOX_COLLISION_H_INCLUDED diff --git a/src/BulletCollision/Gimpact/gim_box_set.cpp b/src/BulletCollision/Gimpact/gim_box_set.cpp new file mode 100644 index 0000000..0c3d7ba --- /dev/null +++ b/src/BulletCollision/Gimpact/gim_box_set.cpp @@ -0,0 +1,182 @@ + +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + + +#include "gim_box_set.h" + + +GUINT GIM_BOX_TREE::_calc_splitting_axis( + gim_array & primitive_boxes, GUINT startIndex, GUINT endIndex) +{ + GUINT i; + + btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); + btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.)); + GUINT numIndices = endIndex-startIndex; + + for (i=startIndex;i & primitive_boxes, GUINT startIndex, + GUINT endIndex, GUINT splitAxis) +{ + GUINT i; + GUINT splitIndex =startIndex; + GUINT numIndices = endIndex - startIndex; + + // average of centers + btScalar splitValue = 0.0f; + for (i=startIndex;i splitValue) + { + //swap + primitive_boxes.swap(i,splitIndex); + splitIndex++; + } + } + + //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex + //otherwise the tree-building might fail due to stack-overflows in certain cases. + //unbalanced1 is unsafe: it can cause stack overflows + //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); + + //unbalanced2 should work too: always use center (perfect balanced trees) + //bool unbalanced2 = true; + + //this should be safe too: + GUINT rangeBalancedIndices = numIndices/3; + bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); + + if (unbalanced) + { + splitIndex = startIndex+ (numIndices>>1); + } + + btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex)))); + + return splitIndex; +} + + +void GIM_BOX_TREE::_build_sub_tree(gim_array & primitive_boxes, GUINT startIndex, GUINT endIndex) +{ + GUINT current_index = m_num_nodes++; + + btAssert((endIndex-startIndex)>0); + + if((endIndex-startIndex) == 1) //we got a leaf + { + m_node_array[current_index].m_left = 0; + m_node_array[current_index].m_right = 0; + m_node_array[current_index].m_escapeIndex = 0; + + m_node_array[current_index].m_bound = primitive_boxes[startIndex].m_bound; + m_node_array[current_index].m_data = primitive_boxes[startIndex].m_data; + return; + } + + //configure inner node + + GUINT splitIndex; + + //calc this node bounding box + m_node_array[current_index].m_bound.invalidate(); + for (splitIndex=startIndex;splitIndex & primitive_boxes) +{ + // initialize node count to 0 + m_num_nodes = 0; + // allocate nodes + m_node_array.resize(primitive_boxes.size()*2); + + _build_sub_tree(primitive_boxes, 0, primitive_boxes.size()); +} + + diff --git a/src/BulletCollision/Gimpact/gim_box_set.h b/src/BulletCollision/Gimpact/gim_box_set.h new file mode 100644 index 0000000..61d190a --- /dev/null +++ b/src/BulletCollision/Gimpact/gim_box_set.h @@ -0,0 +1,674 @@ +#ifndef GIM_BOX_SET_H_INCLUDED +#define GIM_BOX_SET_H_INCLUDED + +/*! \file gim_box_set.h +\author Francisco Leon Najera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + + +#include "gim_array.h" +#include "gim_radixsort.h" +#include "gim_box_collision.h" +#include "gim_tri_collision.h" + + + +//! Overlapping pair +struct GIM_PAIR +{ + GUINT m_index1; + GUINT m_index2; + GIM_PAIR() + {} + + GIM_PAIR(const GIM_PAIR & p) + { + m_index1 = p.m_index1; + m_index2 = p.m_index2; + } + + GIM_PAIR(GUINT index1, GUINT index2) + { + m_index1 = index1; + m_index2 = index2; + } +}; + +//! A pairset array +class gim_pair_set: public gim_array +{ +public: + gim_pair_set():gim_array(32) + { + } + inline void push_pair(GUINT index1,GUINT index2) + { + push_back(GIM_PAIR(index1,index2)); + } + + inline void push_pair_inv(GUINT index1,GUINT index2) + { + push_back(GIM_PAIR(index2,index1)); + } +}; + + +//! Prototype Base class for primitive classification +/*! +This class is a wrapper for primitive collections. +This tells relevant info for the Bounding Box set classes, which take care of space classification. +This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons. +*/ +class GIM_PRIMITIVE_MANAGER_PROTOTYPE +{ +public: + + virtual ~GIM_PRIMITIVE_MANAGER_PROTOTYPE() {} + //! determines if this manager consist on only triangles, which special case will be optimized + virtual bool is_trimesh() = 0; + virtual GUINT get_primitive_count() = 0; + virtual void get_primitive_box(GUINT prim_index ,GIM_AABB & primbox) = 0; + virtual void get_primitive_triangle(GUINT prim_index,GIM_TRIANGLE & triangle) = 0; +}; + + +struct GIM_AABB_DATA +{ + GIM_AABB m_bound; + GUINT m_data; +}; + +//! Node Structure for trees +struct GIM_BOX_TREE_NODE +{ + GIM_AABB m_bound; + GUINT m_left;//!< Left subtree + GUINT m_right;//!< Right subtree + GUINT m_escapeIndex;//!< Scape index for traversing + GUINT m_data;//!< primitive index if apply + + GIM_BOX_TREE_NODE() + { + m_left = 0; + m_right = 0; + m_escapeIndex = 0; + m_data = 0; + } + + SIMD_FORCE_INLINE bool is_leaf_node() const + { + return (!m_left && !m_right); + } +}; + +//! Basic Box tree structure +class GIM_BOX_TREE +{ +protected: + GUINT m_num_nodes; + gim_array m_node_array; +protected: + GUINT _sort_and_calc_splitting_index( + gim_array & primitive_boxes, + GUINT startIndex, GUINT endIndex, GUINT splitAxis); + + GUINT _calc_splitting_axis(gim_array & primitive_boxes, GUINT startIndex, GUINT endIndex); + + void _build_sub_tree(gim_array & primitive_boxes, GUINT startIndex, GUINT endIndex); +public: + GIM_BOX_TREE() + { + m_num_nodes = 0; + } + + //! prototype functions for box tree management + //!@{ + void build_tree(gim_array & primitive_boxes); + + SIMD_FORCE_INLINE void clearNodes() + { + m_node_array.clear(); + m_num_nodes = 0; + } + + //! node count + SIMD_FORCE_INLINE GUINT getNodeCount() const + { + return m_num_nodes; + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const + { + return m_node_array[nodeindex].is_leaf_node(); + } + + SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const + { + return m_node_array[nodeindex].m_data; + } + + SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const + { + bound = m_node_array[nodeindex].m_bound; + } + + SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound) + { + m_node_array[nodeindex].m_bound = bound; + } + + SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const + { + return m_node_array[nodeindex].m_left; + } + + SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const + { + return m_node_array[nodeindex].m_right; + } + + SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const + { + return m_node_array[nodeindex].m_escapeIndex; + } + + //!@} +}; + + +//! Generic Box Tree Template +/*! +This class offers an structure for managing a box tree of primitives. +Requires a Primitive prototype (like GIM_PRIMITIVE_MANAGER_PROTOTYPE ) and +a Box tree structure ( like GIM_BOX_TREE). +*/ +template +class GIM_BOX_TREE_TEMPLATE_SET +{ +protected: + _GIM_PRIMITIVE_MANAGER_PROTOTYPE m_primitive_manager; + _GIM_BOX_TREE_PROTOTYPE m_box_tree; +protected: + //stackless refit + SIMD_FORCE_INLINE void refit() + { + GUINT nodecount = getNodeCount(); + while(nodecount--) + { + if(isLeafNode(nodecount)) + { + GIM_AABB leafbox; + m_primitive_manager.get_primitive_box(getNodeData(nodecount),leafbox); + setNodeBound(nodecount,leafbox); + } + else + { + //get left bound + GUINT childindex = getLeftNodeIndex(nodecount); + GIM_AABB bound; + getNodeBound(childindex,bound); + //get right bound + childindex = getRightNodeIndex(nodecount); + GIM_AABB bound2; + getNodeBound(childindex,bound2); + bound.merge(bound2); + + setNodeBound(nodecount,bound); + } + } + } +public: + + GIM_BOX_TREE_TEMPLATE_SET() + { + } + + SIMD_FORCE_INLINE GIM_AABB getGlobalBox() const + { + GIM_AABB totalbox; + getNodeBound(0, totalbox); + return totalbox; + } + + SIMD_FORCE_INLINE void setPrimitiveManager(const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & primitive_manager) + { + m_primitive_manager = primitive_manager; + } + + const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager() const + { + return m_primitive_manager; + } + + _GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager() + { + return m_primitive_manager; + } + +//! node manager prototype functions +///@{ + + //! this attemps to refit the box set. + SIMD_FORCE_INLINE void update() + { + refit(); + } + + //! this rebuild the entire set + SIMD_FORCE_INLINE void buildSet() + { + //obtain primitive boxes + gim_array primitive_boxes; + primitive_boxes.resize(m_primitive_manager.get_primitive_count(),false); + + for (GUINT i = 0;i & collided_results) const + { + GUINT curIndex = 0; + GUINT numNodes = getNodeCount(); + + while (curIndex < numNodes) + { + GIM_AABB bound; + getNodeBound(curIndex,bound); + + //catch bugs in tree data + + bool aabbOverlap = bound.has_collision(box); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData(curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getScapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; + } + + //! returns the indices of the primitives in the m_primitive_manager + SIMD_FORCE_INLINE bool boxQueryTrans(const GIM_AABB & box, + const btTransform & transform, gim_array & collided_results) const + { + GIM_AABB transbox=box; + transbox.appy_transform(transform); + return boxQuery(transbox,collided_results); + } + + //! returns the indices of the primitives in the m_primitive_manager + SIMD_FORCE_INLINE bool rayQuery( + const btVector3 & ray_dir,const btVector3 & ray_origin , + gim_array & collided_results) const + { + GUINT curIndex = 0; + GUINT numNodes = getNodeCount(); + + while (curIndex < numNodes) + { + GIM_AABB bound; + getNodeBound(curIndex,bound); + + //catch bugs in tree data + + bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData( curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getScapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; + } + + //! tells if this set has hierarcht + SIMD_FORCE_INLINE bool hasHierarchy() const + { + return true; + } + + //! tells if this set is a trimesh + SIMD_FORCE_INLINE bool isTrimesh() const + { + return m_primitive_manager.is_trimesh(); + } + + //! node count + SIMD_FORCE_INLINE GUINT getNodeCount() const + { + return m_box_tree.getNodeCount(); + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const + { + return m_box_tree.isLeafNode(nodeindex); + } + + SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const + { + return m_box_tree.getNodeData(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const + { + m_box_tree.getNodeBound(nodeindex, bound); + } + + SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound) + { + m_box_tree.setNodeBound(nodeindex, bound); + } + + SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const + { + return m_box_tree.getLeftNodeIndex(nodeindex); + } + + SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const + { + return m_box_tree.getRightNodeIndex(nodeindex); + } + + SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const + { + return m_box_tree.getScapeNodeIndex(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeTriangle(GUINT nodeindex,GIM_TRIANGLE & triangle) const + { + m_primitive_manager.get_primitive_triangle(getNodeData(nodeindex),triangle); + } + +}; + +//! Class for Box Tree Sets +/*! +this has the GIM_BOX_TREE implementation for bounding boxes. +*/ +template +class GIM_BOX_TREE_SET: public GIM_BOX_TREE_TEMPLATE_SET< _GIM_PRIMITIVE_MANAGER_PROTOTYPE, GIM_BOX_TREE> +{ +public: + +}; + + + + + +/// GIM_BOX_SET collision methods +template +class GIM_TREE_TREE_COLLIDER +{ +public: + gim_pair_set * m_collision_pairs; + BOX_SET_CLASS0 * m_boxset0; + BOX_SET_CLASS1 * m_boxset1; + GUINT current_node0; + GUINT current_node1; + bool node0_is_leaf; + bool node1_is_leaf; + bool t0_is_trimesh; + bool t1_is_trimesh; + bool node0_has_triangle; + bool node1_has_triangle; + GIM_AABB m_box0; + GIM_AABB m_box1; + GIM_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0; + btTransform trans_cache_0to1; + GIM_TRIANGLE m_tri0; + btVector4 m_tri0_plane; + GIM_TRIANGLE m_tri1; + btVector4 m_tri1_plane; + + +public: + GIM_TREE_TREE_COLLIDER() + { + current_node0 = G_UINT_INFINITY; + current_node1 = G_UINT_INFINITY; + } +protected: + SIMD_FORCE_INLINE void retrieve_node0_triangle(GUINT node0) + { + if(node0_has_triangle) return; + m_boxset0->getNodeTriangle(node0,m_tri0); + //transform triangle + m_tri0.m_vertices[0] = trans_cache_0to1(m_tri0.m_vertices[0]); + m_tri0.m_vertices[1] = trans_cache_0to1(m_tri0.m_vertices[1]); + m_tri0.m_vertices[2] = trans_cache_0to1(m_tri0.m_vertices[2]); + m_tri0.get_plane(m_tri0_plane); + + node0_has_triangle = true; + } + + SIMD_FORCE_INLINE void retrieve_node1_triangle(GUINT node1) + { + if(node1_has_triangle) return; + m_boxset1->getNodeTriangle(node1,m_tri1); + //transform triangle + m_tri1.m_vertices[0] = trans_cache_1to0.transform(m_tri1.m_vertices[0]); + m_tri1.m_vertices[1] = trans_cache_1to0.transform(m_tri1.m_vertices[1]); + m_tri1.m_vertices[2] = trans_cache_1to0.transform(m_tri1.m_vertices[2]); + m_tri1.get_plane(m_tri1_plane); + + node1_has_triangle = true; + } + + SIMD_FORCE_INLINE void retrieve_node0_info(GUINT node0) + { + if(node0 == current_node0) return; + m_boxset0->getNodeBound(node0,m_box0); + node0_is_leaf = m_boxset0->isLeafNode(node0); + node0_has_triangle = false; + current_node0 = node0; + } + + SIMD_FORCE_INLINE void retrieve_node1_info(GUINT node1) + { + if(node1 == current_node1) return; + m_boxset1->getNodeBound(node1,m_box1); + node1_is_leaf = m_boxset1->isLeafNode(node1); + node1_has_triangle = false; + current_node1 = node1; + } + + SIMD_FORCE_INLINE bool node_collision(GUINT node0 ,GUINT node1) + { + retrieve_node0_info(node0); + retrieve_node1_info(node1); + bool result = m_box0.overlapping_trans_cache(m_box1,trans_cache_1to0,true); + if(!result) return false; + + if(t0_is_trimesh && node0_is_leaf) + { + //perform primitive vs box collision + retrieve_node0_triangle(node0); + //do triangle vs box collision + m_box1.increment_margin(m_tri0.m_margin); + + result = m_box1.collide_triangle_exact( + m_tri0.m_vertices[0],m_tri0.m_vertices[1],m_tri0.m_vertices[2],m_tri0_plane); + + m_box1.increment_margin(-m_tri0.m_margin); + + if(!result) return false; + return true; + } + else if(t1_is_trimesh && node1_is_leaf) + { + //perform primitive vs box collision + retrieve_node1_triangle(node1); + //do triangle vs box collision + m_box0.increment_margin(m_tri1.m_margin); + + result = m_box0.collide_triangle_exact( + m_tri1.m_vertices[0],m_tri1.m_vertices[1],m_tri1.m_vertices[2],m_tri1_plane); + + m_box0.increment_margin(-m_tri1.m_margin); + + if(!result) return false; + return true; + } + return true; + } + + //stackless collision routine + void find_collision_pairs() + { + gim_pair_set stack_collisions; + stack_collisions.reserve(32); + + //add the first pair + stack_collisions.push_pair(0,0); + + + while(stack_collisions.size()) + { + //retrieve the last pair and pop + GUINT node0 = stack_collisions.back().m_index1; + GUINT node1 = stack_collisions.back().m_index2; + stack_collisions.pop_back(); + if(node_collision(node0,node1)) // a collision is found + { + if(node0_is_leaf) + { + if(node1_is_leaf) + { + m_collision_pairs->push_pair(m_boxset0->getNodeData(node0),m_boxset1->getNodeData(node1)); + } + else + { + //collide left + stack_collisions.push_pair(node0,m_boxset1->getLeftNodeIndex(node1)); + + //collide right + stack_collisions.push_pair(node0,m_boxset1->getRightNodeIndex(node1)); + } + } + else + { + if(node1_is_leaf) + { + //collide left + stack_collisions.push_pair(m_boxset0->getLeftNodeIndex(node0),node1); + //collide right + stack_collisions.push_pair(m_boxset0->getRightNodeIndex(node0),node1); + } + else + { + GUINT left0 = m_boxset0->getLeftNodeIndex(node0); + GUINT right0 = m_boxset0->getRightNodeIndex(node0); + GUINT left1 = m_boxset1->getLeftNodeIndex(node1); + GUINT right1 = m_boxset1->getRightNodeIndex(node1); + //collide left + stack_collisions.push_pair(left0,left1); + //collide right + stack_collisions.push_pair(left0,right1); + //collide left + stack_collisions.push_pair(right0,left1); + //collide right + stack_collisions.push_pair(right0,right1); + + }// else if node1 is not a leaf + }// else if node0 is not a leaf + + }// if(node_collision(node0,node1)) + }//while(stack_collisions.size()) + } +public: + void find_collision(BOX_SET_CLASS0 * boxset1, const btTransform & trans1, + BOX_SET_CLASS1 * boxset2, const btTransform & trans2, + gim_pair_set & collision_pairs, bool complete_primitive_tests = true) + { + m_collision_pairs = &collision_pairs; + m_boxset0 = boxset1; + m_boxset1 = boxset2; + + trans_cache_1to0.calc_from_homogenic(trans1,trans2); + + trans_cache_0to1 = trans2.inverse(); + trans_cache_0to1 *= trans1; + + + if(complete_primitive_tests) + { + t0_is_trimesh = boxset1->getPrimitiveManager().is_trimesh(); + t1_is_trimesh = boxset2->getPrimitiveManager().is_trimesh(); + } + else + { + t0_is_trimesh = false; + t1_is_trimesh = false; + } + + find_collision_pairs(); + } +}; + + +#endif // GIM_BOXPRUNING_H_INCLUDED + + diff --git a/src/BulletCollision/Gimpact/gim_clip_polygon.h b/src/BulletCollision/Gimpact/gim_clip_polygon.h new file mode 100644 index 0000000..e342459 --- /dev/null +++ b/src/BulletCollision/Gimpact/gim_clip_polygon.h @@ -0,0 +1,210 @@ +#ifndef GIM_CLIP_POLYGON_H_INCLUDED +#define GIM_CLIP_POLYGON_H_INCLUDED + +/*! \file gim_tri_collision.h +\author Francisco Leon Najera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + + +//! This function calcs the distance from a 3D plane +class DISTANCE_PLANE_3D_FUNC +{ +public: + template + inline GREAL operator()(const CLASS_PLANE & plane, const CLASS_POINT & point) + { + return DISTANCE_PLANE_POINT(plane, point); + } +}; + + + +template +SIMD_FORCE_INLINE void PLANE_CLIP_POLYGON_COLLECT( + const CLASS_POINT & point0, + const CLASS_POINT & point1, + GREAL dist0, + GREAL dist1, + CLASS_POINT * clipped, + GUINT & clipped_count) +{ + GUINT _prevclassif = (dist0>G_EPSILON); + GUINT _classif = (dist1>G_EPSILON); + if(_classif!=_prevclassif) + { + GREAL blendfactor = -dist0/(dist1-dist0); + VEC_BLEND(clipped[clipped_count],point0,point1,blendfactor); + clipped_count++; + } + if(!_classif) + { + VEC_COPY(clipped[clipped_count],point1); + clipped_count++; + } +} + + +//! Clips a polygon by a plane +/*! +*\return The count of the clipped counts +*/ +template +SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON_GENERIC( + const CLASS_PLANE & plane, + const CLASS_POINT * polygon_points, + GUINT polygon_point_count, + CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func) +{ + GUINT clipped_count = 0; + + + //clip first point + GREAL firstdist = distance_func(plane,polygon_points[0]);; + if(!(firstdist>G_EPSILON)) + { + VEC_COPY(clipped[clipped_count],polygon_points[0]); + clipped_count++; + } + + GREAL olddist = firstdist; + for(GUINT _i=1;_i +SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE_GENERIC( + const CLASS_PLANE & plane, + const CLASS_POINT & point0, + const CLASS_POINT & point1, + const CLASS_POINT & point2, + CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func) +{ + GUINT clipped_count = 0; + + //clip first point + GREAL firstdist = distance_func(plane,point0);; + if(!(firstdist>G_EPSILON)) + { + VEC_COPY(clipped[clipped_count],point0); + clipped_count++; + } + + // point 1 + GREAL olddist = firstdist; + GREAL dist = distance_func(plane,point1); + + PLANE_CLIP_POLYGON_COLLECT( + point0,point1, + olddist, + dist, + clipped, + clipped_count); + + olddist = dist; + + + // point 2 + dist = distance_func(plane,point2); + + PLANE_CLIP_POLYGON_COLLECT( + point1,point2, + olddist, + dist, + clipped, + clipped_count); + olddist = dist; + + + + //RETURN TO FIRST point + PLANE_CLIP_POLYGON_COLLECT( + point2,point0, + olddist, + firstdist, + clipped, + clipped_count); + + return clipped_count; +} + + +template +SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON3D( + const CLASS_PLANE & plane, + const CLASS_POINT * polygon_points, + GUINT polygon_point_count, + CLASS_POINT * clipped) +{ + return PLANE_CLIP_POLYGON_GENERIC(plane,polygon_points,polygon_point_count,clipped,DISTANCE_PLANE_3D_FUNC()); +} + + +template +SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE3D( + const CLASS_PLANE & plane, + const CLASS_POINT & point0, + const CLASS_POINT & point1, + const CLASS_POINT & point2, + CLASS_POINT * clipped) +{ + return PLANE_CLIP_TRIANGLE_GENERIC(plane,point0,point1,point2,clipped,DISTANCE_PLANE_3D_FUNC()); +} + + + +#endif // GIM_TRI_COLLISION_H_INCLUDED diff --git a/src/BulletCollision/Gimpact/gim_contact.cpp b/src/BulletCollision/Gimpact/gim_contact.cpp new file mode 100644 index 0000000..20e41de --- /dev/null +++ b/src/BulletCollision/Gimpact/gim_contact.cpp @@ -0,0 +1,146 @@ + +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "gim_contact.h" + +#define MAX_COINCIDENT 8 + +void gim_contact_array::merge_contacts( + const gim_contact_array & contacts, bool normal_contact_average) +{ + clear(); + + if(contacts.size()==1) + { + push_back(contacts.back()); + return; + } + + gim_array keycontacts(contacts.size()); + keycontacts.resize(contacts.size(),false); + + //fill key contacts + + GUINT i; + + for (i = 0;im_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//) + { + *pcontact = *scontact; + coincident_count = 0; + } + else if(normal_contact_average) + { + if(btFabs(pcontact->m_depth - scontact->m_depth)m_normal; + coincident_count++; + } + } + } + } + else + {//add new contact + + if(normal_contact_average && coincident_count>0) + { + pcontact->interpolate_normals(coincident_normals,coincident_count); + coincident_count = 0; + } + + push_back(*scontact); + pcontact = &back(); + } + last_key = key; + } +} + +void gim_contact_array::merge_contacts_unique(const gim_contact_array & contacts) +{ + clear(); + + if(contacts.size()==1) + { + push_back(contacts.back()); + return; + } + + GIM_CONTACT average_contact = contacts.back(); + + for (GUINT i=1;i +{ +public: + gim_contact_array():gim_array(64) + { + } + + SIMD_FORCE_INLINE void push_contact(const btVector3 &point,const btVector3 & normal, + GREAL depth, GUINT feature1, GUINT feature2) + { + push_back_mem(); + GIM_CONTACT & newele = back(); + newele.m_point = point; + newele.m_normal = normal; + newele.m_depth = depth; + newele.m_feature1 = feature1; + newele.m_feature2 = feature2; + } + + SIMD_FORCE_INLINE void push_triangle_contacts( + const GIM_TRIANGLE_CONTACT_DATA & tricontact, + GUINT feature1,GUINT feature2) + { + for(GUINT i = 0;i +struct GIM_HASH_TABLE_NODE +{ + GUINT m_key; + T m_data; + GIM_HASH_TABLE_NODE() + { + } + + GIM_HASH_TABLE_NODE(const GIM_HASH_TABLE_NODE & value) + { + m_key = value.m_key; + m_data = value.m_data; + } + + GIM_HASH_TABLE_NODE(GUINT key, const T & data) + { + m_key = key; + m_data = data; + } + + bool operator <(const GIM_HASH_TABLE_NODE & other) const + { + ///inverse order, further objects are first + if(m_key < other.m_key) return true; + return false; + } + + bool operator >(const GIM_HASH_TABLE_NODE & other) const + { + ///inverse order, further objects are first + if(m_key > other.m_key) return true; + return false; + } + + bool operator ==(const GIM_HASH_TABLE_NODE & other) const + { + ///inverse order, further objects are first + if(m_key == other.m_key) return true; + return false; + } +}; + +///Macro for getting the key +class GIM_HASH_NODE_GET_KEY +{ +public: + template + inline GUINT operator()( const T& a) + { + return a.m_key; + } +}; + + + +///Macro for comparing the key and the element +class GIM_HASH_NODE_CMP_KEY_MACRO +{ +public: + template + inline int operator() ( const T& a, GUINT key) + { + return ((int)(a.m_key - key)); + } +}; + +///Macro for comparing Hash nodes +class GIM_HASH_NODE_CMP_MACRO +{ +public: + template + inline int operator() ( const T& a, const T& b ) + { + return ((int)(a.m_key - b.m_key)); + } +}; + + + + + +//! Sorting for hash table +/*! +switch automatically between quicksort and radixsort +*/ +template +void gim_sort_hash_node_array(T * array, GUINT array_count) +{ + if(array_count + +
        +
      • if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes. +When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable. +
      • If node_size != 0, then this container becomes a hash table for ever +
      + +*/ +template +class gim_hash_table +{ +protected: + typedef GIM_HASH_TABLE_NODE _node_type; + + //!The nodes + //array< _node_type, SuperAllocator<_node_type> > m_nodes; + gim_array< _node_type > m_nodes; + //SuperBufferedArray< _node_type > m_nodes; + bool m_sorted; + + ///Hash table data management. The hash table has the indices to the corresponding m_nodes array + GUINT * m_hash_table;//!< + GUINT m_table_size;//!< + GUINT m_node_size;//!< + GUINT m_min_hash_table_size; + + + + //! Returns the cell index + inline GUINT _find_cell(GUINT hashkey) + { + _node_type * nodesptr = m_nodes.pointer(); + GUINT start_index = (hashkey%m_table_size)*m_node_size; + GUINT end_index = start_index + m_node_size; + + while(start_index= m_nodes.size()) return false; + if(m_nodes[index].m_key != GIM_INVALID_HASH) + { + //Search for the avaliable cell in buffer + GUINT cell_index = _find_cell(m_nodes[index].m_key); + + btAssert(cell_index!=GIM_INVALID_HASH); + btAssert(m_hash_table[cell_index]==index); + + m_hash_table[cell_index] = GIM_INVALID_HASH; + } + + return this->_erase_unsorted(index); + } + + //! erase by key in hash table + inline bool _erase_hash_table(GUINT hashkey) + { + if(hashkey == GIM_INVALID_HASH) return false; + + //Search for the avaliable cell in buffer + GUINT cell_index = _find_cell(hashkey); + if(cell_index ==GIM_INVALID_HASH) return false; + + GUINT index = m_hash_table[cell_index]; + m_hash_table[cell_index] = GIM_INVALID_HASH; + + return this->_erase_unsorted(index); + } + + + + //! insert an element in hash table + /*! + If the element exists, this won't insert the element + \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted + If so, the element has been inserted at the last position of the array. + */ + inline GUINT _insert_hash_table(GUINT hashkey, const T & value) + { + if(hashkey==GIM_INVALID_HASH) + { + //Insert anyway + _insert_unsorted(hashkey,value); + return GIM_INVALID_HASH; + } + + GUINT cell_index = _assign_hash_table_cell(hashkey); + + GUINT value_key = m_hash_table[cell_index]; + + if(value_key!= GIM_INVALID_HASH) return value_key;// Not overrited + + m_hash_table[cell_index] = m_nodes.size(); + + _insert_unsorted(hashkey,value); + return GIM_INVALID_HASH; + } + + //! insert an element in hash table. + /*! + If the element exists, this replaces the element. + \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted + If so, the element has been inserted at the last position of the array. + */ + inline GUINT _insert_hash_table_replace(GUINT hashkey, const T & value) + { + if(hashkey==GIM_INVALID_HASH) + { + //Insert anyway + _insert_unsorted(hashkey,value); + return GIM_INVALID_HASH; + } + + GUINT cell_index = _assign_hash_table_cell(hashkey); + + GUINT value_key = m_hash_table[cell_index]; + + if(value_key!= GIM_INVALID_HASH) + {//replaces the existing + m_nodes[value_key] = _node_type(hashkey,value); + return value_key;// index of the replaced element + } + + m_hash_table[cell_index] = m_nodes.size(); + + _insert_unsorted(hashkey,value); + return GIM_INVALID_HASH; + + } + + + ///Sorted array data management. The hash table has the indices to the corresponding m_nodes array + inline bool _erase_sorted(GUINT index) + { + if(index>=(GUINT)m_nodes.size()) return false; + m_nodes.erase_sorted(index); + if(m_nodes.size()<2) m_sorted = false; + return true; + } + + //! faster, but unsorted + inline bool _erase_unsorted(GUINT index) + { + if(index>=m_nodes.size()) return false; + + GUINT lastindex = m_nodes.size()-1; + if(indexcheck_for_switching_to_hashtable(); + } + + //! Insert an element in an ordered array + inline GUINT _insert_sorted(GUINT hashkey, const T & value) + { + if(hashkey==GIM_INVALID_HASH || size()==0) + { + m_nodes.push_back(_node_type(hashkey,value)); + return GIM_INVALID_HASH; + } + //Insert at last position + //Sort element + + + GUINT result_ind=0; + GUINT last_index = m_nodes.size()-1; + _node_type * ptr = m_nodes.pointer(); + + bool found = gim_binary_search_ex( + ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO()); + + + //Insert before found index + if(found) + { + return result_ind; + } + else + { + _insert_in_pos(hashkey, value, result_ind); + } + return GIM_INVALID_HASH; + } + + inline GUINT _insert_sorted_replace(GUINT hashkey, const T & value) + { + if(hashkey==GIM_INVALID_HASH || size()==0) + { + m_nodes.push_back(_node_type(hashkey,value)); + return GIM_INVALID_HASH; + } + //Insert at last position + //Sort element + GUINT result_ind; + GUINT last_index = m_nodes.size()-1; + _node_type * ptr = m_nodes.pointer(); + + bool found = gim_binary_search_ex( + ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO()); + + //Insert before found index + if(found) + { + m_nodes[result_ind] = _node_type(hashkey,value); + } + else + { + _insert_in_pos(hashkey, value, result_ind); + } + return result_ind; + } + + //! Fast insertion in m_nodes array + inline GUINT _insert_unsorted(GUINT hashkey, const T & value) + { + m_nodes.push_back(_node_type(hashkey,value)); + m_sorted = false; + return GIM_INVALID_HASH; + } + + + +public: + + /*! +
    1. if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes. + When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable. +
    2. If node_size != 0, then this container becomes a hash table for ever + + */ + gim_hash_table(GUINT reserve_size = GIM_DEFAULT_HASH_TABLE_SIZE, + GUINT node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE, + GUINT min_hash_table_size = GIM_INVALID_HASH) + { + m_hash_table = NULL; + m_table_size = 0; + m_sorted = false; + m_node_size = node_size; + m_min_hash_table_size = min_hash_table_size; + + if(m_node_size!=0) + { + if(reserve_size!=0) + { + m_nodes.reserve(reserve_size); + _reserve_table_memory(reserve_size); + _invalidate_keys(); + } + else + { + m_nodes.reserve(GIM_DEFAULT_HASH_TABLE_SIZE); + _reserve_table_memory(GIM_DEFAULT_HASH_TABLE_SIZE); + _invalidate_keys(); + } + } + else if(reserve_size!=0) + { + m_nodes.reserve(reserve_size); + } + + } + + ~gim_hash_table() + { + _destroy(); + } + + inline bool is_hash_table() + { + if(m_hash_table) return true; + return false; + } + + inline bool is_sorted() + { + if(size()<2) return true; + return m_sorted; + } + + bool sort() + { + if(is_sorted()) return true; + if(m_nodes.size()<2) return false; + + + _node_type * ptr = m_nodes.pointer(); + GUINT siz = m_nodes.size(); + gim_sort_hash_node_array(ptr,siz); + m_sorted=true; + + + + if(m_hash_table) + { + _rehash(); + } + return true; + } + + bool switch_to_hashtable() + { + if(m_hash_table) return false; + if(m_node_size==0) m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE; + if(m_nodes.size()m_hash_table) return true; + + if(!(m_nodes.size()< m_min_hash_table_size)) + { + if(m_node_size == 0) + { + m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE; + } + + _resize_table(m_nodes.size()+1); + return true; + } + return false; + } + + inline void set_sorted(bool value) + { + m_sorted = value; + } + + //! Retrieves the amount of keys. + inline GUINT size() const + { + return m_nodes.size(); + } + + //! Retrieves the hash key. + inline GUINT get_key(GUINT index) const + { + return m_nodes[index].m_key; + } + + //! Retrieves the value by index + /*! + */ + inline T * get_value_by_index(GUINT index) + { + return &m_nodes[index].m_data; + } + + inline const T& operator[](GUINT index) const + { + return m_nodes[index].m_data; + } + + inline T& operator[](GUINT index) + { + return m_nodes[index].m_data; + } + + //! Finds the index of the element with the key + /*! + \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted + If so, the element has been inserted at the last position of the array. + */ + inline GUINT find(GUINT hashkey) + { + if(m_hash_table) + { + GUINT cell_index = _find_cell(hashkey); + if(cell_index==GIM_INVALID_HASH) return GIM_INVALID_HASH; + return m_hash_table[cell_index]; + } + GUINT last_index = m_nodes.size(); + if(last_index<2) + { + if(last_index==0) return GIM_INVALID_HASH; + if(m_nodes[0].m_key == hashkey) return 0; + return GIM_INVALID_HASH; + } + else if(m_sorted) + { + //Binary search + GUINT result_ind = 0; + last_index--; + _node_type * ptr = m_nodes.pointer(); + + bool found = gim_binary_search_ex(ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO()); + + + if(found) return result_ind; + } + return GIM_INVALID_HASH; + } + + //! Retrieves the value associated with the index + /*! + \return the found element, or null + */ + inline T * get_value(GUINT hashkey) + { + GUINT index = find(hashkey); + if(index == GIM_INVALID_HASH) return NULL; + return &m_nodes[index].m_data; + } + + + /*! + */ + inline bool erase_by_index(GUINT index) + { + if(index > m_nodes.size()) return false; + + if(m_hash_table == NULL) + { + if(is_sorted()) + { + return this->_erase_sorted(index); + } + else + { + return this->_erase_unsorted(index); + } + } + else + { + return this->_erase_by_index_hash_table(index); + } + return false; + } + + + + inline bool erase_by_index_unsorted(GUINT index) + { + if(index > m_nodes.size()) return false; + + if(m_hash_table == NULL) + { + return this->_erase_unsorted(index); + } + else + { + return this->_erase_by_index_hash_table(index); + } + return false; + } + + + + /*! + + */ + inline bool erase_by_key(GUINT hashkey) + { + if(size()==0) return false; + + if(m_hash_table) + { + return this->_erase_hash_table(hashkey); + } + //Binary search + + if(is_sorted()==false) return false; + + GUINT result_ind = find(hashkey); + if(result_ind!= GIM_INVALID_HASH) + { + return this->_erase_sorted(result_ind); + } + return false; + } + + void clear() + { + m_nodes.clear(); + + if(m_hash_table==NULL) return; + GUINT datasize = m_table_size*m_node_size; + //Initialize the hashkeys. + GUINT i; + for(i=0;i_insert_hash_table(hashkey,element); + } + if(this->is_sorted()) + { + return this->_insert_sorted(hashkey,element); + } + return this->_insert_unsorted(hashkey,element); + } + + //! Insert an element into the hash, and could overrite an existing object with the same hash. + /*! + \return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position + of the replaced element. + */ + inline GUINT insert_override(GUINT hashkey, const T & element) + { + if(m_hash_table) + { + return this->_insert_hash_table_replace(hashkey,element); + } + if(this->is_sorted()) + { + return this->_insert_sorted_replace(hashkey,element); + } + this->_insert_unsorted(hashkey,element); + return m_nodes.size(); + } + + + + //! Insert an element into the hash,But if this container is a sorted array, this inserts it unsorted + /*! + */ + inline GUINT insert_unsorted(GUINT hashkey,const T & element) + { + if(m_hash_table) + { + return this->_insert_hash_table(hashkey,element); + } + return this->_insert_unsorted(hashkey,element); + } + + +}; + + + +#endif // GIM_CONTAINERS_H_INCLUDED diff --git a/src/BulletCollision/Gimpact/gim_linear_math.h b/src/BulletCollision/Gimpact/gim_linear_math.h new file mode 100644 index 0000000..64f11b4 --- /dev/null +++ b/src/BulletCollision/Gimpact/gim_linear_math.h @@ -0,0 +1,1573 @@ +#ifndef GIM_LINEAR_H_INCLUDED +#define GIM_LINEAR_H_INCLUDED + +/*! \file gim_linear_math.h +*\author Francisco Leon Najera +Type Independant Vector and matrix operations. +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + + +#include "gim_math.h" +#include "gim_geom_types.h" + + + + +//! Zero out a 2D vector +#define VEC_ZERO_2(a) \ +{ \ + (a)[0] = (a)[1] = 0.0f; \ +}\ + + +//! Zero out a 3D vector +#define VEC_ZERO(a) \ +{ \ + (a)[0] = (a)[1] = (a)[2] = 0.0f; \ +}\ + + +/// Zero out a 4D vector +#define VEC_ZERO_4(a) \ +{ \ + (a)[0] = (a)[1] = (a)[2] = (a)[3] = 0.0f; \ +}\ + + +/// Vector copy +#define VEC_COPY_2(b,a) \ +{ \ + (b)[0] = (a)[0]; \ + (b)[1] = (a)[1]; \ +}\ + + +/// Copy 3D vector +#define VEC_COPY(b,a) \ +{ \ + (b)[0] = (a)[0]; \ + (b)[1] = (a)[1]; \ + (b)[2] = (a)[2]; \ +}\ + + +/// Copy 4D vector +#define VEC_COPY_4(b,a) \ +{ \ + (b)[0] = (a)[0]; \ + (b)[1] = (a)[1]; \ + (b)[2] = (a)[2]; \ + (b)[3] = (a)[3]; \ +}\ + +/// VECTOR SWAP +#define VEC_SWAP(b,a) \ +{ \ + GIM_SWAP_NUMBERS((b)[0],(a)[0]);\ + GIM_SWAP_NUMBERS((b)[1],(a)[1]);\ + GIM_SWAP_NUMBERS((b)[2],(a)[2]);\ +}\ + +/// Vector difference +#define VEC_DIFF_2(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] - (v1)[0]; \ + (v21)[1] = (v2)[1] - (v1)[1]; \ +}\ + + +/// Vector difference +#define VEC_DIFF(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] - (v1)[0]; \ + (v21)[1] = (v2)[1] - (v1)[1]; \ + (v21)[2] = (v2)[2] - (v1)[2]; \ +}\ + + +/// Vector difference +#define VEC_DIFF_4(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] - (v1)[0]; \ + (v21)[1] = (v2)[1] - (v1)[1]; \ + (v21)[2] = (v2)[2] - (v1)[2]; \ + (v21)[3] = (v2)[3] - (v1)[3]; \ +}\ + + +/// Vector sum +#define VEC_SUM_2(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] + (v1)[0]; \ + (v21)[1] = (v2)[1] + (v1)[1]; \ +}\ + + +/// Vector sum +#define VEC_SUM(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] + (v1)[0]; \ + (v21)[1] = (v2)[1] + (v1)[1]; \ + (v21)[2] = (v2)[2] + (v1)[2]; \ +}\ + + +/// Vector sum +#define VEC_SUM_4(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] + (v1)[0]; \ + (v21)[1] = (v2)[1] + (v1)[1]; \ + (v21)[2] = (v2)[2] + (v1)[2]; \ + (v21)[3] = (v2)[3] + (v1)[3]; \ +}\ + + +/// scalar times vector +#define VEC_SCALE_2(c,a,b) \ +{ \ + (c)[0] = (a)*(b)[0]; \ + (c)[1] = (a)*(b)[1]; \ +}\ + + +/// scalar times vector +#define VEC_SCALE(c,a,b) \ +{ \ + (c)[0] = (a)*(b)[0]; \ + (c)[1] = (a)*(b)[1]; \ + (c)[2] = (a)*(b)[2]; \ +}\ + + +/// scalar times vector +#define VEC_SCALE_4(c,a,b) \ +{ \ + (c)[0] = (a)*(b)[0]; \ + (c)[1] = (a)*(b)[1]; \ + (c)[2] = (a)*(b)[2]; \ + (c)[3] = (a)*(b)[3]; \ +}\ + + +/// accumulate scaled vector +#define VEC_ACCUM_2(c,a,b) \ +{ \ + (c)[0] += (a)*(b)[0]; \ + (c)[1] += (a)*(b)[1]; \ +}\ + + +/// accumulate scaled vector +#define VEC_ACCUM(c,a,b) \ +{ \ + (c)[0] += (a)*(b)[0]; \ + (c)[1] += (a)*(b)[1]; \ + (c)[2] += (a)*(b)[2]; \ +}\ + + +/// accumulate scaled vector +#define VEC_ACCUM_4(c,a,b) \ +{ \ + (c)[0] += (a)*(b)[0]; \ + (c)[1] += (a)*(b)[1]; \ + (c)[2] += (a)*(b)[2]; \ + (c)[3] += (a)*(b)[3]; \ +}\ + + +/// Vector dot product +#define VEC_DOT_2(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1]) + + +/// Vector dot product +#define VEC_DOT(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2]) + +/// Vector dot product +#define VEC_DOT_4(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] + (a)[3]*(b)[3]) + +/// vector impact parameter (squared) +#define VEC_IMPACT_SQ(bsq,direction,position) {\ + GREAL _llel_ = VEC_DOT(direction, position);\ + bsq = VEC_DOT(position, position) - _llel_*_llel_;\ +}\ + + +/// vector impact parameter +#define VEC_IMPACT(bsq,direction,position) {\ + VEC_IMPACT_SQ(bsq,direction,position); \ + GIM_SQRT(bsq,bsq); \ +}\ + +/// Vector length +#define VEC_LENGTH_2(a,l)\ +{\ + GREAL _pp = VEC_DOT_2(a,a);\ + GIM_SQRT(_pp,l);\ +}\ + + +/// Vector length +#define VEC_LENGTH(a,l)\ +{\ + GREAL _pp = VEC_DOT(a,a);\ + GIM_SQRT(_pp,l);\ +}\ + + +/// Vector length +#define VEC_LENGTH_4(a,l)\ +{\ + GREAL _pp = VEC_DOT_4(a,a);\ + GIM_SQRT(_pp,l);\ +}\ + +/// Vector inv length +#define VEC_INV_LENGTH_2(a,l)\ +{\ + GREAL _pp = VEC_DOT_2(a,a);\ + GIM_INV_SQRT(_pp,l);\ +}\ + + +/// Vector inv length +#define VEC_INV_LENGTH(a,l)\ +{\ + GREAL _pp = VEC_DOT(a,a);\ + GIM_INV_SQRT(_pp,l);\ +}\ + + +/// Vector inv length +#define VEC_INV_LENGTH_4(a,l)\ +{\ + GREAL _pp = VEC_DOT_4(a,a);\ + GIM_INV_SQRT(_pp,l);\ +}\ + + + +/// distance between two points +#define VEC_DISTANCE(_len,_va,_vb) {\ + vec3f _tmp_; \ + VEC_DIFF(_tmp_, _vb, _va); \ + VEC_LENGTH(_tmp_,_len); \ +}\ + + +/// Vector length +#define VEC_CONJUGATE_LENGTH(a,l)\ +{\ + GREAL _pp = 1.0 - a[0]*a[0] - a[1]*a[1] - a[2]*a[2];\ + GIM_SQRT(_pp,l);\ +}\ + + +/// Vector length +#define VEC_NORMALIZE(a) { \ + GREAL len;\ + VEC_INV_LENGTH(a,len); \ + if(lenA[1]?(A[0]>A[2]?0:2):(A[1]>A[2]?1:2);\ +}\ + +//! Finds the 2 smallest cartesian coordinates from a vector +#define VEC_MINOR_AXES(vec, i0, i1)\ +{\ + VEC_MAYOR_COORD(vec,i0);\ + i0 = (i0+1)%3;\ + i1 = (i0+1)%3;\ +}\ + + + + +#define VEC_EQUAL(v1,v2) (v1[0]==v2[0]&&v1[1]==v2[1]&&v1[2]==v2[2]) + +#define VEC_NEAR_EQUAL(v1,v2) (GIM_NEAR_EQUAL(v1[0],v2[0])&&GIM_NEAR_EQUAL(v1[1],v2[1])&&GIM_NEAR_EQUAL(v1[2],v2[2])) + + +/// Vector cross +#define X_AXIS_CROSS_VEC(dst,src)\ +{ \ + dst[0] = 0.0f; \ + dst[1] = -src[2]; \ + dst[2] = src[1]; \ +}\ + +#define Y_AXIS_CROSS_VEC(dst,src)\ +{ \ + dst[0] = src[2]; \ + dst[1] = 0.0f; \ + dst[2] = -src[0]; \ +}\ + +#define Z_AXIS_CROSS_VEC(dst,src)\ +{ \ + dst[0] = -src[1]; \ + dst[1] = src[0]; \ + dst[2] = 0.0f; \ +}\ + + + + + + +/// initialize matrix +#define IDENTIFY_MATRIX_3X3(m) \ +{ \ + m[0][0] = 1.0; \ + m[0][1] = 0.0; \ + m[0][2] = 0.0; \ + \ + m[1][0] = 0.0; \ + m[1][1] = 1.0; \ + m[1][2] = 0.0; \ + \ + m[2][0] = 0.0; \ + m[2][1] = 0.0; \ + m[2][2] = 1.0; \ +}\ + +/*! initialize matrix */ +#define IDENTIFY_MATRIX_4X4(m) \ +{ \ + m[0][0] = 1.0; \ + m[0][1] = 0.0; \ + m[0][2] = 0.0; \ + m[0][3] = 0.0; \ + \ + m[1][0] = 0.0; \ + m[1][1] = 1.0; \ + m[1][2] = 0.0; \ + m[1][3] = 0.0; \ + \ + m[2][0] = 0.0; \ + m[2][1] = 0.0; \ + m[2][2] = 1.0; \ + m[2][3] = 0.0; \ + \ + m[3][0] = 0.0; \ + m[3][1] = 0.0; \ + m[3][2] = 0.0; \ + m[3][3] = 1.0; \ +}\ + +/*! initialize matrix */ +#define ZERO_MATRIX_4X4(m) \ +{ \ + m[0][0] = 0.0; \ + m[0][1] = 0.0; \ + m[0][2] = 0.0; \ + m[0][3] = 0.0; \ + \ + m[1][0] = 0.0; \ + m[1][1] = 0.0; \ + m[1][2] = 0.0; \ + m[1][3] = 0.0; \ + \ + m[2][0] = 0.0; \ + m[2][1] = 0.0; \ + m[2][2] = 0.0; \ + m[2][3] = 0.0; \ + \ + m[3][0] = 0.0; \ + m[3][1] = 0.0; \ + m[3][2] = 0.0; \ + m[3][3] = 0.0; \ +}\ + +/*! matrix rotation X */ +#define ROTX_CS(m,cosine,sine) \ +{ \ + /* rotation about the x-axis */ \ + \ + m[0][0] = 1.0; \ + m[0][1] = 0.0; \ + m[0][2] = 0.0; \ + m[0][3] = 0.0; \ + \ + m[1][0] = 0.0; \ + m[1][1] = (cosine); \ + m[1][2] = (sine); \ + m[1][3] = 0.0; \ + \ + m[2][0] = 0.0; \ + m[2][1] = -(sine); \ + m[2][2] = (cosine); \ + m[2][3] = 0.0; \ + \ + m[3][0] = 0.0; \ + m[3][1] = 0.0; \ + m[3][2] = 0.0; \ + m[3][3] = 1.0; \ +}\ + +/*! matrix rotation Y */ +#define ROTY_CS(m,cosine,sine) \ +{ \ + /* rotation about the y-axis */ \ + \ + m[0][0] = (cosine); \ + m[0][1] = 0.0; \ + m[0][2] = -(sine); \ + m[0][3] = 0.0; \ + \ + m[1][0] = 0.0; \ + m[1][1] = 1.0; \ + m[1][2] = 0.0; \ + m[1][3] = 0.0; \ + \ + m[2][0] = (sine); \ + m[2][1] = 0.0; \ + m[2][2] = (cosine); \ + m[2][3] = 0.0; \ + \ + m[3][0] = 0.0; \ + m[3][1] = 0.0; \ + m[3][2] = 0.0; \ + m[3][3] = 1.0; \ +}\ + +/*! matrix rotation Z */ +#define ROTZ_CS(m,cosine,sine) \ +{ \ + /* rotation about the z-axis */ \ + \ + m[0][0] = (cosine); \ + m[0][1] = (sine); \ + m[0][2] = 0.0; \ + m[0][3] = 0.0; \ + \ + m[1][0] = -(sine); \ + m[1][1] = (cosine); \ + m[1][2] = 0.0; \ + m[1][3] = 0.0; \ + \ + m[2][0] = 0.0; \ + m[2][1] = 0.0; \ + m[2][2] = 1.0; \ + m[2][3] = 0.0; \ + \ + m[3][0] = 0.0; \ + m[3][1] = 0.0; \ + m[3][2] = 0.0; \ + m[3][3] = 1.0; \ +}\ + +/*! matrix copy */ +#define COPY_MATRIX_2X2(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[0][1]; \ + \ + b[1][0] = a[1][0]; \ + b[1][1] = a[1][1]; \ + \ +}\ + + +/*! matrix copy */ +#define COPY_MATRIX_2X3(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[0][1]; \ + b[0][2] = a[0][2]; \ + \ + b[1][0] = a[1][0]; \ + b[1][1] = a[1][1]; \ + b[1][2] = a[1][2]; \ +}\ + + +/*! matrix copy */ +#define COPY_MATRIX_3X3(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[0][1]; \ + b[0][2] = a[0][2]; \ + \ + b[1][0] = a[1][0]; \ + b[1][1] = a[1][1]; \ + b[1][2] = a[1][2]; \ + \ + b[2][0] = a[2][0]; \ + b[2][1] = a[2][1]; \ + b[2][2] = a[2][2]; \ +}\ + + +/*! matrix copy */ +#define COPY_MATRIX_4X4(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[0][1]; \ + b[0][2] = a[0][2]; \ + b[0][3] = a[0][3]; \ + \ + b[1][0] = a[1][0]; \ + b[1][1] = a[1][1]; \ + b[1][2] = a[1][2]; \ + b[1][3] = a[1][3]; \ + \ + b[2][0] = a[2][0]; \ + b[2][1] = a[2][1]; \ + b[2][2] = a[2][2]; \ + b[2][3] = a[2][3]; \ + \ + b[3][0] = a[3][0]; \ + b[3][1] = a[3][1]; \ + b[3][2] = a[3][2]; \ + b[3][3] = a[3][3]; \ +}\ + + +/*! matrix transpose */ +#define TRANSPOSE_MATRIX_2X2(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[1][0]; \ + \ + b[1][0] = a[0][1]; \ + b[1][1] = a[1][1]; \ +}\ + + +/*! matrix transpose */ +#define TRANSPOSE_MATRIX_3X3(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[1][0]; \ + b[0][2] = a[2][0]; \ + \ + b[1][0] = a[0][1]; \ + b[1][1] = a[1][1]; \ + b[1][2] = a[2][1]; \ + \ + b[2][0] = a[0][2]; \ + b[2][1] = a[1][2]; \ + b[2][2] = a[2][2]; \ +}\ + + +/*! matrix transpose */ +#define TRANSPOSE_MATRIX_4X4(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[1][0]; \ + b[0][2] = a[2][0]; \ + b[0][3] = a[3][0]; \ + \ + b[1][0] = a[0][1]; \ + b[1][1] = a[1][1]; \ + b[1][2] = a[2][1]; \ + b[1][3] = a[3][1]; \ + \ + b[2][0] = a[0][2]; \ + b[2][1] = a[1][2]; \ + b[2][2] = a[2][2]; \ + b[2][3] = a[3][2]; \ + \ + b[3][0] = a[0][3]; \ + b[3][1] = a[1][3]; \ + b[3][2] = a[2][3]; \ + b[3][3] = a[3][3]; \ +}\ + + +/*! multiply matrix by scalar */ +#define SCALE_MATRIX_2X2(b,s,a) \ +{ \ + b[0][0] = (s) * a[0][0]; \ + b[0][1] = (s) * a[0][1]; \ + \ + b[1][0] = (s) * a[1][0]; \ + b[1][1] = (s) * a[1][1]; \ +}\ + + +/*! multiply matrix by scalar */ +#define SCALE_MATRIX_3X3(b,s,a) \ +{ \ + b[0][0] = (s) * a[0][0]; \ + b[0][1] = (s) * a[0][1]; \ + b[0][2] = (s) * a[0][2]; \ + \ + b[1][0] = (s) * a[1][0]; \ + b[1][1] = (s) * a[1][1]; \ + b[1][2] = (s) * a[1][2]; \ + \ + b[2][0] = (s) * a[2][0]; \ + b[2][1] = (s) * a[2][1]; \ + b[2][2] = (s) * a[2][2]; \ +}\ + + +/*! multiply matrix by scalar */ +#define SCALE_MATRIX_4X4(b,s,a) \ +{ \ + b[0][0] = (s) * a[0][0]; \ + b[0][1] = (s) * a[0][1]; \ + b[0][2] = (s) * a[0][2]; \ + b[0][3] = (s) * a[0][3]; \ + \ + b[1][0] = (s) * a[1][0]; \ + b[1][1] = (s) * a[1][1]; \ + b[1][2] = (s) * a[1][2]; \ + b[1][3] = (s) * a[1][3]; \ + \ + b[2][0] = (s) * a[2][0]; \ + b[2][1] = (s) * a[2][1]; \ + b[2][2] = (s) * a[2][2]; \ + b[2][3] = (s) * a[2][3]; \ + \ + b[3][0] = s * a[3][0]; \ + b[3][1] = s * a[3][1]; \ + b[3][2] = s * a[3][2]; \ + b[3][3] = s * a[3][3]; \ +}\ + + +/*! multiply matrix by scalar */ +#define SCALE_VEC_MATRIX_2X2(b,svec,a) \ +{ \ + b[0][0] = svec[0] * a[0][0]; \ + b[1][0] = svec[0] * a[1][0]; \ + \ + b[0][1] = svec[1] * a[0][1]; \ + b[1][1] = svec[1] * a[1][1]; \ +}\ + + +/*! multiply matrix by scalar. Each columns is scaled by each scalar vector component */ +#define SCALE_VEC_MATRIX_3X3(b,svec,a) \ +{ \ + b[0][0] = svec[0] * a[0][0]; \ + b[1][0] = svec[0] * a[1][0]; \ + b[2][0] = svec[0] * a[2][0]; \ + \ + b[0][1] = svec[1] * a[0][1]; \ + b[1][1] = svec[1] * a[1][1]; \ + b[2][1] = svec[1] * a[2][1]; \ + \ + b[0][2] = svec[2] * a[0][2]; \ + b[1][2] = svec[2] * a[1][2]; \ + b[2][2] = svec[2] * a[2][2]; \ +}\ + + +/*! multiply matrix by scalar */ +#define SCALE_VEC_MATRIX_4X4(b,svec,a) \ +{ \ + b[0][0] = svec[0] * a[0][0]; \ + b[1][0] = svec[0] * a[1][0]; \ + b[2][0] = svec[0] * a[2][0]; \ + b[3][0] = svec[0] * a[3][0]; \ + \ + b[0][1] = svec[1] * a[0][1]; \ + b[1][1] = svec[1] * a[1][1]; \ + b[2][1] = svec[1] * a[2][1]; \ + b[3][1] = svec[1] * a[3][1]; \ + \ + b[0][2] = svec[2] * a[0][2]; \ + b[1][2] = svec[2] * a[1][2]; \ + b[2][2] = svec[2] * a[2][2]; \ + b[3][2] = svec[2] * a[3][2]; \ + \ + b[0][3] = svec[3] * a[0][3]; \ + b[1][3] = svec[3] * a[1][3]; \ + b[2][3] = svec[3] * a[2][3]; \ + b[3][3] = svec[3] * a[3][3]; \ +}\ + + +/*! multiply matrix by scalar */ +#define ACCUM_SCALE_MATRIX_2X2(b,s,a) \ +{ \ + b[0][0] += (s) * a[0][0]; \ + b[0][1] += (s) * a[0][1]; \ + \ + b[1][0] += (s) * a[1][0]; \ + b[1][1] += (s) * a[1][1]; \ +}\ + + +/*! multiply matrix by scalar */ +#define ACCUM_SCALE_MATRIX_3X3(b,s,a) \ +{ \ + b[0][0] += (s) * a[0][0]; \ + b[0][1] += (s) * a[0][1]; \ + b[0][2] += (s) * a[0][2]; \ + \ + b[1][0] += (s) * a[1][0]; \ + b[1][1] += (s) * a[1][1]; \ + b[1][2] += (s) * a[1][2]; \ + \ + b[2][0] += (s) * a[2][0]; \ + b[2][1] += (s) * a[2][1]; \ + b[2][2] += (s) * a[2][2]; \ +}\ + + +/*! multiply matrix by scalar */ +#define ACCUM_SCALE_MATRIX_4X4(b,s,a) \ +{ \ + b[0][0] += (s) * a[0][0]; \ + b[0][1] += (s) * a[0][1]; \ + b[0][2] += (s) * a[0][2]; \ + b[0][3] += (s) * a[0][3]; \ + \ + b[1][0] += (s) * a[1][0]; \ + b[1][1] += (s) * a[1][1]; \ + b[1][2] += (s) * a[1][2]; \ + b[1][3] += (s) * a[1][3]; \ + \ + b[2][0] += (s) * a[2][0]; \ + b[2][1] += (s) * a[2][1]; \ + b[2][2] += (s) * a[2][2]; \ + b[2][3] += (s) * a[2][3]; \ + \ + b[3][0] += (s) * a[3][0]; \ + b[3][1] += (s) * a[3][1]; \ + b[3][2] += (s) * a[3][2]; \ + b[3][3] += (s) * a[3][3]; \ +}\ + +/*! matrix product */ +/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/ +#define MATRIX_PRODUCT_2X2(c,a,b) \ +{ \ + c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]; \ + c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]; \ + \ + c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]; \ + c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]; \ + \ +}\ + +/*! matrix product */ +/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/ +#define MATRIX_PRODUCT_3X3(c,a,b) \ +{ \ + c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0]; \ + c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]+a[0][2]*b[2][1]; \ + c[0][2] = a[0][0]*b[0][2]+a[0][1]*b[1][2]+a[0][2]*b[2][2]; \ + \ + c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]+a[1][2]*b[2][0]; \ + c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]+a[1][2]*b[2][1]; \ + c[1][2] = a[1][0]*b[0][2]+a[1][1]*b[1][2]+a[1][2]*b[2][2]; \ + \ + c[2][0] = a[2][0]*b[0][0]+a[2][1]*b[1][0]+a[2][2]*b[2][0]; \ + c[2][1] = a[2][0]*b[0][1]+a[2][1]*b[1][1]+a[2][2]*b[2][1]; \ + c[2][2] = a[2][0]*b[0][2]+a[2][1]*b[1][2]+a[2][2]*b[2][2]; \ +}\ + + +/*! matrix product */ +/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/ +#define MATRIX_PRODUCT_4X4(c,a,b) \ +{ \ + c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0]+a[0][3]*b[3][0];\ + c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]+a[0][2]*b[2][1]+a[0][3]*b[3][1];\ + c[0][2] = a[0][0]*b[0][2]+a[0][1]*b[1][2]+a[0][2]*b[2][2]+a[0][3]*b[3][2];\ + c[0][3] = a[0][0]*b[0][3]+a[0][1]*b[1][3]+a[0][2]*b[2][3]+a[0][3]*b[3][3];\ + \ + c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]+a[1][2]*b[2][0]+a[1][3]*b[3][0];\ + c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]+a[1][2]*b[2][1]+a[1][3]*b[3][1];\ + c[1][2] = a[1][0]*b[0][2]+a[1][1]*b[1][2]+a[1][2]*b[2][2]+a[1][3]*b[3][2];\ + c[1][3] = a[1][0]*b[0][3]+a[1][1]*b[1][3]+a[1][2]*b[2][3]+a[1][3]*b[3][3];\ + \ + c[2][0] = a[2][0]*b[0][0]+a[2][1]*b[1][0]+a[2][2]*b[2][0]+a[2][3]*b[3][0];\ + c[2][1] = a[2][0]*b[0][1]+a[2][1]*b[1][1]+a[2][2]*b[2][1]+a[2][3]*b[3][1];\ + c[2][2] = a[2][0]*b[0][2]+a[2][1]*b[1][2]+a[2][2]*b[2][2]+a[2][3]*b[3][2];\ + c[2][3] = a[2][0]*b[0][3]+a[2][1]*b[1][3]+a[2][2]*b[2][3]+a[2][3]*b[3][3];\ + \ + c[3][0] = a[3][0]*b[0][0]+a[3][1]*b[1][0]+a[3][2]*b[2][0]+a[3][3]*b[3][0];\ + c[3][1] = a[3][0]*b[0][1]+a[3][1]*b[1][1]+a[3][2]*b[2][1]+a[3][3]*b[3][1];\ + c[3][2] = a[3][0]*b[0][2]+a[3][1]*b[1][2]+a[3][2]*b[2][2]+a[3][3]*b[3][2];\ + c[3][3] = a[3][0]*b[0][3]+a[3][1]*b[1][3]+a[3][2]*b[2][3]+a[3][3]*b[3][3];\ +}\ + + +/*! matrix times vector */ +#define MAT_DOT_VEC_2X2(p,m,v) \ +{ \ + p[0] = m[0][0]*v[0] + m[0][1]*v[1]; \ + p[1] = m[1][0]*v[0] + m[1][1]*v[1]; \ +}\ + + +/*! matrix times vector */ +#define MAT_DOT_VEC_3X3(p,m,v) \ +{ \ + p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2]; \ + p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2]; \ + p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2]; \ +}\ + + +/*! matrix times vector +v is a vec4f +*/ +#define MAT_DOT_VEC_4X4(p,m,v) \ +{ \ + p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2] + m[0][3]*v[3]; \ + p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2] + m[1][3]*v[3]; \ + p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2] + m[2][3]*v[3]; \ + p[3] = m[3][0]*v[0] + m[3][1]*v[1] + m[3][2]*v[2] + m[3][3]*v[3]; \ +}\ + +/*! matrix times vector +v is a vec3f +and m is a mat4f
      +Last column is added as the position +*/ +#define MAT_DOT_VEC_3X4(p,m,v) \ +{ \ + p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2] + m[0][3]; \ + p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2] + m[1][3]; \ + p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2] + m[2][3]; \ +}\ + + +/*! vector transpose times matrix */ +/*! p[j] = v[0]*m[0][j] + v[1]*m[1][j] + v[2]*m[2][j]; */ +#define VEC_DOT_MAT_3X3(p,v,m) \ +{ \ + p[0] = v[0]*m[0][0] + v[1]*m[1][0] + v[2]*m[2][0]; \ + p[1] = v[0]*m[0][1] + v[1]*m[1][1] + v[2]*m[2][1]; \ + p[2] = v[0]*m[0][2] + v[1]*m[1][2] + v[2]*m[2][2]; \ +}\ + + +/*! affine matrix times vector */ +/** The matrix is assumed to be an affine matrix, with last two + * entries representing a translation */ +#define MAT_DOT_VEC_2X3(p,m,v) \ +{ \ + p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]; \ + p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]; \ +}\ + +//! Transform a plane +#define MAT_TRANSFORM_PLANE_4X4(pout,m,plane)\ +{ \ + pout[0] = m[0][0]*plane[0] + m[0][1]*plane[1] + m[0][2]*plane[2];\ + pout[1] = m[1][0]*plane[0] + m[1][1]*plane[1] + m[1][2]*plane[2];\ + pout[2] = m[2][0]*plane[0] + m[2][1]*plane[1] + m[2][2]*plane[2];\ + pout[3] = m[0][3]*pout[0] + m[1][3]*pout[1] + m[2][3]*pout[2] + plane[3];\ +}\ + + + +/** inverse transpose of matrix times vector + * + * This macro computes inverse transpose of matrix m, + * and multiplies vector v into it, to yeild vector p + * + * DANGER !!! Do Not use this on normal vectors!!! + * It will leave normals the wrong length !!! + * See macro below for use on normals. + */ +#define INV_TRANSP_MAT_DOT_VEC_2X2(p,m,v) \ +{ \ + GREAL det; \ + \ + det = m[0][0]*m[1][1] - m[0][1]*m[1][0]; \ + p[0] = m[1][1]*v[0] - m[1][0]*v[1]; \ + p[1] = - m[0][1]*v[0] + m[0][0]*v[1]; \ + \ + /* if matrix not singular, and not orthonormal, then renormalize */ \ + if ((det!=1.0f) && (det != 0.0f)) { \ + det = 1.0f / det; \ + p[0] *= det; \ + p[1] *= det; \ + } \ +}\ + + +/** transform normal vector by inverse transpose of matrix + * and then renormalize the vector + * + * This macro computes inverse transpose of matrix m, + * and multiplies vector v into it, to yeild vector p + * Vector p is then normalized. + */ +#define NORM_XFORM_2X2(p,m,v) \ +{ \ + GREAL len; \ + \ + /* do nothing if off-diagonals are zero and diagonals are \ + * equal */ \ + if ((m[0][1] != 0.0) || (m[1][0] != 0.0) || (m[0][0] != m[1][1])) { \ + p[0] = m[1][1]*v[0] - m[1][0]*v[1]; \ + p[1] = - m[0][1]*v[0] + m[0][0]*v[1]; \ + \ + len = p[0]*p[0] + p[1]*p[1]; \ + GIM_INV_SQRT(len,len); \ + p[0] *= len; \ + p[1] *= len; \ + } else { \ + VEC_COPY_2 (p, v); \ + } \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define OUTER_PRODUCT_2X2(m,v,t) \ +{ \ + m[0][0] = v[0] * t[0]; \ + m[0][1] = v[0] * t[1]; \ + \ + m[1][0] = v[1] * t[0]; \ + m[1][1] = v[1] * t[1]; \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define OUTER_PRODUCT_3X3(m,v,t) \ +{ \ + m[0][0] = v[0] * t[0]; \ + m[0][1] = v[0] * t[1]; \ + m[0][2] = v[0] * t[2]; \ + \ + m[1][0] = v[1] * t[0]; \ + m[1][1] = v[1] * t[1]; \ + m[1][2] = v[1] * t[2]; \ + \ + m[2][0] = v[2] * t[0]; \ + m[2][1] = v[2] * t[1]; \ + m[2][2] = v[2] * t[2]; \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define OUTER_PRODUCT_4X4(m,v,t) \ +{ \ + m[0][0] = v[0] * t[0]; \ + m[0][1] = v[0] * t[1]; \ + m[0][2] = v[0] * t[2]; \ + m[0][3] = v[0] * t[3]; \ + \ + m[1][0] = v[1] * t[0]; \ + m[1][1] = v[1] * t[1]; \ + m[1][2] = v[1] * t[2]; \ + m[1][3] = v[1] * t[3]; \ + \ + m[2][0] = v[2] * t[0]; \ + m[2][1] = v[2] * t[1]; \ + m[2][2] = v[2] * t[2]; \ + m[2][3] = v[2] * t[3]; \ + \ + m[3][0] = v[3] * t[0]; \ + m[3][1] = v[3] * t[1]; \ + m[3][2] = v[3] * t[2]; \ + m[3][3] = v[3] * t[3]; \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define ACCUM_OUTER_PRODUCT_2X2(m,v,t) \ +{ \ + m[0][0] += v[0] * t[0]; \ + m[0][1] += v[0] * t[1]; \ + \ + m[1][0] += v[1] * t[0]; \ + m[1][1] += v[1] * t[1]; \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define ACCUM_OUTER_PRODUCT_3X3(m,v,t) \ +{ \ + m[0][0] += v[0] * t[0]; \ + m[0][1] += v[0] * t[1]; \ + m[0][2] += v[0] * t[2]; \ + \ + m[1][0] += v[1] * t[0]; \ + m[1][1] += v[1] * t[1]; \ + m[1][2] += v[1] * t[2]; \ + \ + m[2][0] += v[2] * t[0]; \ + m[2][1] += v[2] * t[1]; \ + m[2][2] += v[2] * t[2]; \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define ACCUM_OUTER_PRODUCT_4X4(m,v,t) \ +{ \ + m[0][0] += v[0] * t[0]; \ + m[0][1] += v[0] * t[1]; \ + m[0][2] += v[0] * t[2]; \ + m[0][3] += v[0] * t[3]; \ + \ + m[1][0] += v[1] * t[0]; \ + m[1][1] += v[1] * t[1]; \ + m[1][2] += v[1] * t[2]; \ + m[1][3] += v[1] * t[3]; \ + \ + m[2][0] += v[2] * t[0]; \ + m[2][1] += v[2] * t[1]; \ + m[2][2] += v[2] * t[2]; \ + m[2][3] += v[2] * t[3]; \ + \ + m[3][0] += v[3] * t[0]; \ + m[3][1] += v[3] * t[1]; \ + m[3][2] += v[3] * t[2]; \ + m[3][3] += v[3] * t[3]; \ +}\ + + +/** determinant of matrix + * + * Computes determinant of matrix m, returning d + */ +#define DETERMINANT_2X2(d,m) \ +{ \ + d = m[0][0] * m[1][1] - m[0][1] * m[1][0]; \ +}\ + + +/** determinant of matrix + * + * Computes determinant of matrix m, returning d + */ +#define DETERMINANT_3X3(d,m) \ +{ \ + d = m[0][0] * (m[1][1]*m[2][2] - m[1][2] * m[2][1]); \ + d -= m[0][1] * (m[1][0]*m[2][2] - m[1][2] * m[2][0]); \ + d += m[0][2] * (m[1][0]*m[2][1] - m[1][1] * m[2][0]); \ +}\ + + +/** i,j,th cofactor of a 4x4 matrix + * + */ +#define COFACTOR_4X4_IJ(fac,m,i,j) \ +{ \ + GUINT __ii[4], __jj[4], __k; \ + \ + for (__k=0; __k +*/ +#define INV_MAT_DOT_VEC_3X3(p,m,v) \ +{ \ + p[0] = MAT_DOT_COL(m,v,0); \ + p[1] = MAT_DOT_COL(m,v,1); \ + p[2] = MAT_DOT_COL(m,v,2); \ +}\ + + + +#endif // GIM_VECTOR_H_INCLUDED diff --git a/src/BulletCollision/Gimpact/gim_math.h b/src/BulletCollision/Gimpact/gim_math.h new file mode 100644 index 0000000..939079e --- /dev/null +++ b/src/BulletCollision/Gimpact/gim_math.h @@ -0,0 +1,157 @@ +#ifndef GIM_MATH_H_INCLUDED +#define GIM_MATH_H_INCLUDED +/*! \file gim_math.h +\author Francisco Leon Najera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "LinearMath/btScalar.h" + + + +#define GREAL btScalar +#define GREAL2 double +#define GINT int +#define GUINT unsigned int +#define GSHORT short +#define GUSHORT unsigned short +#define GINT64 long long +#define GUINT64 unsigned long long + + + +#define G_PI 3.14159265358979f +#define G_HALF_PI 1.5707963f +//267948966 +#define G_TWO_PI 6.28318530f +//71795864 +#define G_ROOT3 1.73205f +#define G_ROOT2 1.41421f +#define G_UINT_INFINITY 0xffffffff //!< A very very high value +#define G_REAL_INFINITY FLT_MAX +#define G_SIGN_BITMASK 0x80000000 +#define G_EPSILON SIMD_EPSILON + + + +enum GIM_SCALAR_TYPES +{ + G_STYPE_REAL =0, + G_STYPE_REAL2, + G_STYPE_SHORT, + G_STYPE_USHORT, + G_STYPE_INT, + G_STYPE_UINT, + G_STYPE_INT64, + G_STYPE_UINT64 +}; + + + +#define G_DEGTORAD(X) ((X)*3.1415926f/180.0f) +#define G_RADTODEG(X) ((X)*180.0f/3.1415926f) + +//! Integer representation of a floating-point value. +#define GIM_IR(x) ((GUINT&)(x)) + +//! Signed integer representation of a floating-point value. +#define GIM_SIR(x) ((GINT&)(x)) + +//! Absolute integer representation of a floating-point value +#define GIM_AIR(x) (GIM_IR(x)&0x7fffffff) + +//! Floating-point representation of an integer value. +#define GIM_FR(x) ((GREAL&)(x)) + +#define GIM_MAX(a,b) (ab?b:a) + +#define GIM_MAX3(a,b,c) GIM_MAX(a,GIM_MAX(b,c)) +#define GIM_MIN3(a,b,c) GIM_MIN(a,GIM_MIN(b,c)) + +#define GIM_IS_ZERO(value) (value < G_EPSILON && value > -G_EPSILON) + +#define GIM_IS_NEGATIVE(value) (value <= -G_EPSILON) + +#define GIM_IS_POSISITVE(value) (value >= G_EPSILON) + +#define GIM_NEAR_EQUAL(v1,v2) GIM_IS_ZERO((v1-v2)) + +///returns a clamped number +#define GIM_CLAMP(number,minval,maxval) (numbermaxval?maxval:number)) + +#define GIM_GREATER(x, y) btFabs(x) > (y) + +///Swap numbers +#define GIM_SWAP_NUMBERS(a,b){ \ + a = a+b; \ + b = a-b; \ + a = a-b; \ +}\ + +#define GIM_INV_SQRT(va,isva)\ +{\ + if(va<=0.0000001f)\ + {\ + isva = G_REAL_INFINITY;\ + }\ + else\ + {\ + GREAL _x = va * 0.5f;\ + GUINT _y = 0x5f3759df - ( GIM_IR(va) >> 1);\ + isva = GIM_FR(_y);\ + isva = isva * ( 1.5f - ( _x * isva * isva ) );\ + }\ +}\ + +#define GIM_SQRT(va,sva)\ +{\ + GIM_INV_SQRT(va,sva);\ + sva = 1.0f/sva;\ +}\ + +//! Computes 1.0f / sqrtf(x). Comes from Quake3. See http://www.magic-software.com/3DGEDInvSqrt.html +inline GREAL gim_inv_sqrt(GREAL f) +{ + GREAL r; + GIM_INV_SQRT(f,r); + return r; +} + +inline GREAL gim_sqrt(GREAL f) +{ + GREAL r; + GIM_SQRT(f,r); + return r; +} + + + +#endif // GIM_MATH_H_INCLUDED diff --git a/src/BulletCollision/Gimpact/gim_memory.cpp b/src/BulletCollision/Gimpact/gim_memory.cpp new file mode 100644 index 0000000..1636eb7 --- /dev/null +++ b/src/BulletCollision/Gimpact/gim_memory.cpp @@ -0,0 +1,135 @@ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + + +#include "gim_memory.h" +#include "stdlib.h" + +#ifdef GIM_SIMD_MEMORY +#include "LinearMath/btAlignedAllocator.h" +#endif + +static gim_alloc_function *g_allocfn = 0; +static gim_alloca_function *g_allocafn = 0; +static gim_realloc_function *g_reallocfn = 0; +static gim_free_function *g_freefn = 0; + +void gim_set_alloc_handler (gim_alloc_function *fn) +{ + g_allocfn = fn; +} + +void gim_set_alloca_handler (gim_alloca_function *fn) +{ + g_allocafn = fn; +} + +void gim_set_realloc_handler (gim_realloc_function *fn) +{ + g_reallocfn = fn; +} + +void gim_set_free_handler (gim_free_function *fn) +{ + g_freefn = fn; +} + +gim_alloc_function *gim_get_alloc_handler() +{ + return g_allocfn; +} + +gim_alloca_function *gim_get_alloca_handler() +{ + return g_allocafn; +} + + +gim_realloc_function *gim_get_realloc_handler () +{ + return g_reallocfn; +} + + +gim_free_function *gim_get_free_handler () +{ + return g_freefn; +} + + +void * gim_alloc(size_t size) +{ + void * ptr; + if (g_allocfn) + { + ptr = g_allocfn(size); + } + else + { +#ifdef GIM_SIMD_MEMORY + ptr = btAlignedAlloc(size,16); +#else + ptr = malloc(size); +#endif + } + return ptr; +} + +void * gim_alloca(size_t size) +{ + if (g_allocafn) return g_allocafn(size); else return gim_alloc(size); +} + + +void * gim_realloc(void *ptr, size_t oldsize, size_t newsize) +{ + void * newptr = gim_alloc(newsize); + size_t copysize = oldsize + +#ifdef PREFETCH +#include // for prefetch +#define pfval 64 +#define pfval2 128 +//! Prefetch 64 +#define pf(_x,_i) _mm_prefetch((void *)(_x + _i + pfval), 0) +//! Prefetch 128 +#define pf2(_x,_i) _mm_prefetch((void *)(_x + _i + pfval2), 0) +#else +//! Prefetch 64 +#define pf(_x,_i) +//! Prefetch 128 +#define pf2(_x,_i) +#endif + + +///Functions for manip packed arrays of numbers +#define GIM_COPY_ARRAYS(dest_array,source_array,element_count)\ +{\ + for (GUINT _i_=0;_i_=SIMD_T_SIZE) + { + *(ui_dst_ptr++) = *(ui_src_ptr++); + copysize-=SIMD_T_SIZE; + } + if(copysize==0) return; +*/ + + char * c_src_ptr = (char *)src; + char * c_dst_ptr = (char *)dst; + while(copysize>0) + { + *(c_dst_ptr++) = *(c_src_ptr++); + copysize--; + } + return; +#else + memcpy(dst,src,copysize); +#endif +} + + + +template +inline void gim_swap_elements(T* _array,size_t _i,size_t _j) +{ + T _e_tmp_ = _array[_i]; + _array[_i] = _array[_j]; + _array[_j] = _e_tmp_; +} + + +template +inline void gim_swap_elements_memcpy(T* _array,size_t _i,size_t _j) +{ + char _e_tmp_[sizeof(T)]; + gim_simd_memcpy(_e_tmp_,&_array[_i],sizeof(T)); + gim_simd_memcpy(&_array[_i],&_array[_j],sizeof(T)); + gim_simd_memcpy(&_array[_j],_e_tmp_,sizeof(T)); +} + +template +inline void gim_swap_elements_ptr(char * _array,size_t _i,size_t _j) +{ + char _e_tmp_[SIZE]; + _i*=SIZE; + _j*=SIZE; + gim_simd_memcpy(_e_tmp_,_array+_i,SIZE); + gim_simd_memcpy(_array+_i,_array+_j,SIZE); + gim_simd_memcpy(_array+_j,_e_tmp_,SIZE); +} + +#endif // GIM_MEMORY_H_INCLUDED diff --git a/src/BulletCollision/Gimpact/gim_radixsort.h b/src/BulletCollision/Gimpact/gim_radixsort.h new file mode 100644 index 0000000..c246ef1 --- /dev/null +++ b/src/BulletCollision/Gimpact/gim_radixsort.h @@ -0,0 +1,406 @@ +#ifndef GIM_RADIXSORT_H_INCLUDED +#define GIM_RADIXSORT_H_INCLUDED +/*! \file gim_radixsort.h +\author Francisco Leon Najera. +Based on the work of Michael Herf : "fast floating-point radix sort" +Avaliable on http://www.stereopsis.com/radix.html +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "gim_memory.h" + +///Macros for sorting. +//! Prototype for comparators +class less_comparator +{ + public: + + template + inline int operator() ( const T& a, const Z& b ) + { + return ( ab?1:0)); + } +}; + +//! Prototype for comparators +class integer_comparator +{ + public: + + template + inline int operator() ( const T& a, const T& b ) + { + return (int)(a-b); + } +}; + +//!Prototype for getting the integer representation of an object +class uint_key_func +{ +public: + template + inline GUINT operator()( const T& a) + { + return (GUINT)a; + } +}; + + +//!Prototype for copying elements +class copy_elements_func +{ +public: + template + inline void operator()(T& a,T& b) + { + a = b; + } +}; + +//!Prototype for copying elements +class memcopy_elements_func +{ +public: + template + inline void operator()(T& a,T& b) + { + gim_simd_memcpy(&a,&b,sizeof(T)); + } +}; + + +//! @{ +struct GIM_RSORT_TOKEN +{ + GUINT m_key; + GUINT m_value; + GIM_RSORT_TOKEN() + { + } + GIM_RSORT_TOKEN(const GIM_RSORT_TOKEN& rtoken) + { + m_key = rtoken.m_key; + m_value = rtoken.m_value; + } + + inline bool operator <(const GIM_RSORT_TOKEN& other) const + { + return (m_key < other.m_key); + } + + inline bool operator >(const GIM_RSORT_TOKEN& other) const + { + return (m_key > other.m_key); + } +}; + +//! Prototype for comparators +class GIM_RSORT_TOKEN_COMPARATOR +{ + public: + + inline int operator()( const GIM_RSORT_TOKEN& a, const GIM_RSORT_TOKEN& b ) + { + return (int)((a.m_key) - (b.m_key)); + } +}; + + + +#define kHist 2048 +// ---- utils for accessing 11-bit quantities +#define D11_0(x) (x & 0x7FF) +#define D11_1(x) (x >> 11 & 0x7FF) +#define D11_2(x) (x >> 22 ) + + + +///Radix sort for unsigned integer keys +inline void gim_radix_sort_rtokens( + GIM_RSORT_TOKEN * array, + GIM_RSORT_TOKEN * sorted, GUINT element_count) +{ + GUINT i; + GUINT b0[kHist * 3]; + GUINT *b1 = b0 + kHist; + GUINT *b2 = b1 + kHist; + for (i = 0; i < kHist * 3; ++i) + { + b0[i] = 0; + } + GUINT fi; + GUINT pos; + for (i = 0; i < element_count; ++i) + { + fi = array[i].m_key; + b0[D11_0(fi)] ++; + b1[D11_1(fi)] ++; + b2[D11_2(fi)] ++; + } + { + GUINT sum0 = 0, sum1 = 0, sum2 = 0; + GUINT tsum; + for (i = 0; i < kHist; ++i) + { + tsum = b0[i] + sum0; + b0[i] = sum0 - 1; + sum0 = tsum; + tsum = b1[i] + sum1; + b1[i] = sum1 - 1; + sum1 = tsum; + tsum = b2[i] + sum2; + b2[i] = sum2 - 1; + sum2 = tsum; + } + } + for (i = 0; i < element_count; ++i) + { + fi = array[i].m_key; + pos = D11_0(fi); + pos = ++b0[pos]; + sorted[pos].m_key = array[i].m_key; + sorted[pos].m_value = array[i].m_value; + } + for (i = 0; i < element_count; ++i) + { + fi = sorted[i].m_key; + pos = D11_1(fi); + pos = ++b1[pos]; + array[pos].m_key = sorted[i].m_key; + array[pos].m_value = sorted[i].m_value; + } + for (i = 0; i < element_count; ++i) + { + fi = array[i].m_key; + pos = D11_2(fi); + pos = ++b2[pos]; + sorted[pos].m_key = array[i].m_key; + sorted[pos].m_value = array[i].m_value; + } +} + + + + +/// Get the sorted tokens from an array. For generic use. Tokens are IRR_RSORT_TOKEN +/*! +*\param array Array of elements to sort +*\param sorted_tokens Tokens of sorted elements +*\param element_count element count +*\param uintkey_macro Functor which retrieves the integer representation of an array element +*/ +template +void gim_radix_sort_array_tokens( + T* array , + GIM_RSORT_TOKEN * sorted_tokens, + GUINT element_count,GETKEY_CLASS uintkey_macro) +{ + GIM_RSORT_TOKEN * _unsorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count); + for (GUINT _i=0;_i +void gim_radix_sort( + T * array, GUINT element_count, + GETKEY_CLASS get_uintkey_macro, COPY_CLASS copy_elements_macro) +{ + GIM_RSORT_TOKEN * _sorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count); + gim_radix_sort_array_tokens(array,_sorted,element_count,get_uintkey_macro); + T * _original_array = (T *) gim_alloc(sizeof(T)*element_count); + gim_simd_memcpy(_original_array,array,sizeof(T)*element_count); + for (GUINT _i=0;_i +bool gim_binary_search_ex( + const T* _array, GUINT _start_i, + GUINT _end_i,GUINT & _result_index, + const KEYCLASS & _search_key, + COMP_CLASS _comp_macro) +{ + GUINT _k; + int _comp_result; + GUINT _i = _start_i; + GUINT _j = _end_i+1; + while (_i < _j) + { + _k = (_j+_i-1)/2; + _comp_result = _comp_macro(_array[_k], _search_key); + if (_comp_result == 0) + { + _result_index = _k; + return true; + } + else if (_comp_result < 0) + { + _i = _k+1; + } + else + { + _j = _k; + } + } + _result_index = _i; + return false; +} + + + +//! Failsafe Iterative binary search,Template version +/*! +If the element is not found, it returns the nearest upper element position, may be the further position after the last element. +\param _array +\param _start_i the beginning of the array +\param _end_i the ending index of the array +\param _search_key Value to find +\param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value +\return true if found, else false +*/ +template +bool gim_binary_search( + const T*_array,GUINT _start_i, + GUINT _end_i,const T & _search_key, + GUINT & _result_index) +{ + GUINT _i = _start_i; + GUINT _j = _end_i+1; + GUINT _k; + while(_i < _j) + { + _k = (_j+_i-1)/2; + if(_array[_k]==_search_key) + { + _result_index = _k; + return true; + } + else if (_array[_k]<_search_key) + { + _i = _k+1; + } + else + { + _j = _k; + } + } + _result_index = _i; + return false; +} + + + +///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/ +template +void gim_down_heap(T *pArr, GUINT k, GUINT n,COMP_CLASS CompareFunc) +{ + /* PRE: a[k+1..N] is a heap */ + /* POST: a[k..N] is a heap */ + + T temp = pArr[k - 1]; + /* k has child(s) */ + while (k <= n/2) + { + int child = 2*k; + + if ((child < (int)n) && CompareFunc(pArr[child - 1] , pArr[child])<0) + { + child++; + } + /* pick larger child */ + if (CompareFunc(temp , pArr[child - 1])<0) + { + /* move child up */ + pArr[k - 1] = pArr[child - 1]; + k = child; + } + else + { + break; + } + } + pArr[k - 1] = temp; +} /*downHeap*/ + + +template +void gim_heap_sort(T *pArr, GUINT element_count, COMP_CLASS CompareFunc) +{ + /* sort a[0..N-1], N.B. 0 to N-1 */ + GUINT k; + GUINT n = element_count; + for (k = n/2; k > 0; k--) + { + gim_down_heap(pArr, k, n, CompareFunc); + } + + /* a[1..N] is now a heap */ + while ( n>=2 ) + { + gim_swap_elements(pArr,0,n-1); /* largest of a[0..n-1] */ + --n; + /* restore a[1..i-1] heap */ + gim_down_heap(pArr, 1, n, CompareFunc); + } +} + + + + +#endif // GIM_RADIXSORT_H_INCLUDED diff --git a/src/BulletCollision/Gimpact/gim_tri_collision.cpp b/src/BulletCollision/Gimpact/gim_tri_collision.cpp new file mode 100644 index 0000000..f9727e1 --- /dev/null +++ b/src/BulletCollision/Gimpact/gim_tri_collision.cpp @@ -0,0 +1,640 @@ + +/*! \file gim_tri_collision.h +\author Francisco Leon Najera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "gim_tri_collision.h" + + +#define TRI_LOCAL_EPSILON 0.000001f +#define MIN_EDGE_EDGE_DIS 0.00001f + + +class GIM_TRIANGLE_CALCULATION_CACHE +{ +public: + GREAL margin; + btVector3 tu_vertices[3]; + btVector3 tv_vertices[3]; + btVector4 tu_plane; + btVector4 tv_plane; + btVector3 closest_point_u; + btVector3 closest_point_v; + btVector3 edge_edge_dir; + btVector3 distances; + GREAL du[4]; + GREAL du0du1; + GREAL du0du2; + GREAL dv[4]; + GREAL dv0dv1; + GREAL dv0dv2; + btVector3 temp_points[MAX_TRI_CLIPPING]; + btVector3 temp_points1[MAX_TRI_CLIPPING]; + btVector3 contact_points[MAX_TRI_CLIPPING]; + + + + //! if returns false, the faces are paralele + SIMD_FORCE_INLINE bool compute_intervals( + const GREAL &D0, + const GREAL &D1, + const GREAL &D2, + const GREAL &D0D1, + const GREAL &D0D2, + GREAL & scale_edge0, + GREAL & scale_edge1, + GUINT &edge_index0, + GUINT &edge_index1) + { + if(D0D1>0.0f) + { + /* here we know that D0D2<=0.0 */ + /* that is D0, D1 are on the same side, D2 on the other or on the plane */ + scale_edge0 = -D2/(D0-D2); + scale_edge1 = -D1/(D2-D1); + edge_index0 = 2;edge_index1 = 1; + } + else if(D0D2>0.0f) + { + /* here we know that d0d1<=0.0 */ + scale_edge0 = -D0/(D1-D0); + scale_edge1 = -D1/(D2-D1); + edge_index0 = 0;edge_index1 = 1; + } + else if(D1*D2>0.0f || D0!=0.0f) + { + /* here we know that d0d1<=0.0 or that D0!=0.0 */ + scale_edge0 = -D0/(D1-D0); + scale_edge1 = -D2/(D0-D2); + edge_index0 = 0 ;edge_index1 = 2; + } + else + { + return false; + } + return true; + } + + + //! clip triangle + /*! + */ + SIMD_FORCE_INLINE GUINT clip_triangle( + const btVector4 & tri_plane, + const btVector3 * tripoints, + const btVector3 * srcpoints, + btVector3 * clip_points) + { + // edge 0 + + btVector4 edgeplane; + + EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane); + + GUINT clipped_count = PLANE_CLIP_TRIANGLE3D( + edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points); + + if(clipped_count == 0) return 0; + + // edge 1 + + EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane); + + clipped_count = PLANE_CLIP_POLYGON3D( + edgeplane,temp_points,clipped_count,temp_points1); + + if(clipped_count == 0) return 0; + + // edge 2 + + EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane); + + clipped_count = PLANE_CLIP_POLYGON3D( + edgeplane,temp_points1,clipped_count,clip_points); + + return clipped_count; + + + /*GUINT i0 = (tri_plane.closestAxis()+1)%3; + GUINT i1 = (i0+1)%3; + // edge 0 + btVector3 temp_points[MAX_TRI_CLIPPING]; + btVector3 temp_points1[MAX_TRI_CLIPPING]; + + GUINT clipped_count= PLANE_CLIP_TRIANGLE_GENERIC( + 0,srcpoints[0],srcpoints[1],srcpoints[2],temp_points, + DISTANCE_EDGE(tripoints[0],tripoints[1],i0,i1)); + + + if(clipped_count == 0) return 0; + + // edge 1 + clipped_count = PLANE_CLIP_POLYGON_GENERIC( + 0,temp_points,clipped_count,temp_points1, + DISTANCE_EDGE(tripoints[1],tripoints[2],i0,i1)); + + if(clipped_count == 0) return 0; + + // edge 2 + clipped_count = PLANE_CLIP_POLYGON_GENERIC( + 0,temp_points1,clipped_count,clipped_points, + DISTANCE_EDGE(tripoints[2],tripoints[0],i0,i1)); + + return clipped_count;*/ + } + + SIMD_FORCE_INLINE void sort_isect( + GREAL & isect0,GREAL & isect1,GUINT &e0,GUINT &e1,btVector3 & vec0,btVector3 & vec1) + { + if(isect1=isect_v[1]) // face U casts face V + { + return 1; + } + else if(isect_v[0]<=isect_u[0]) // face V casts face U + { + return 2; + } + // closest points + closest_point_u = up_e1; + closest_point_v = vp_e0; + // calc edges and separation + + if(isect_u[1]+ MIN_EDGE_EDGE_DIS=isect_u[1]) // face V casts face U + { + return 2; + } + else if(isect_u[0]<=isect_v[0]) // face U casts face V + { + return 1; + } + // closest points + closest_point_u = up_e0; + closest_point_v = vp_e1; + // calc edges and separation + + if(isect_v[1]+MIN_EDGE_EDGE_DIS0.0f && du0du2>0.0f) // same sign on all of them + not equal 0 ? + { + if(du[0]<0) //we need test behind the triangle plane + { + distances[0] = GIM_MAX3(du[0],du[1],du[2]); + distances[0] = -distances[0]; + if(distances[0]>margin) return false; //never intersect + + //reorder triangle v + VEC_SWAP(tv_vertices[0],tv_vertices[1]); + VEC_SCALE_4(tv_plane,-1.0f,tv_plane); + } + else + { + distances[0] = GIM_MIN3(du[0],du[1],du[2]); + if(distances[0]>margin) return false; //never intersect + } + } + else + { + //Look if we need to invert the triangle + distances[0] = (du[0]+du[1]+du[2])/3.0f; //centroid + + if(distances[0]<0.0f) + { + //reorder triangle v + VEC_SWAP(tv_vertices[0],tv_vertices[1]); + VEC_SCALE_4(tv_plane,-1.0f,tv_plane); + + distances[0] = GIM_MAX3(du[0],du[1],du[2]); + distances[0] = -distances[0]; + } + else + { + distances[0] = GIM_MIN3(du[0],du[1],du[2]); + } + } + + + // plane U vs V points + + TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],tu_plane); + + dv[0] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[0]); + dv[1] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[1]); + dv[2] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[2]); + + dv0dv1 = dv[0] * dv[1]; + dv0dv2 = dv[0] * dv[2]; + + + if(dv0dv1>0.0f && dv0dv2>0.0f) // same sign on all of them + not equal 0 ? + { + if(dv[0]<0) //we need test behind the triangle plane + { + distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]); + distances[1] = -distances[1]; + if(distances[1]>margin) return false; //never intersect + + //reorder triangle u + VEC_SWAP(tu_vertices[0],tu_vertices[1]); + VEC_SCALE_4(tu_plane,-1.0f,tu_plane); + } + else + { + distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]); + if(distances[1]>margin) return false; //never intersect + } + } + else + { + //Look if we need to invert the triangle + distances[1] = (dv[0]+dv[1]+dv[2])/3.0f; //centroid + + if(distances[1]<0.0f) + { + //reorder triangle v + VEC_SWAP(tu_vertices[0],tu_vertices[1]); + VEC_SCALE_4(tu_plane,-1.0f,tu_plane); + + distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]); + distances[1] = -distances[1]; + } + else + { + distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]); + } + } + + GUINT bl; + /* bl = cross_line_intersection_test(); + if(bl==3) + { + //take edge direction too + bl = distances.maxAxis(); + } + else + {*/ + bl = 0; + if(distances[0]margin) return false; + + contacts.m_penetration_depth = -distances[2] + margin; + contacts.m_points[0] = closest_point_v; + contacts.m_point_count = 1; + VEC_COPY(contacts.m_separating_normal,edge_edge_dir); + + return true; + } + + //clip face against other + + + GUINT point_count; + //TODO + if(bl == 0) //clip U points against V + { + point_count = clip_triangle(tv_plane,tv_vertices,tu_vertices,contact_points); + if(point_count == 0) return false; + contacts.merge_points(tv_plane,margin,contact_points,point_count); + } + else //clip V points against U + { + point_count = clip_triangle(tu_plane,tu_vertices,tv_vertices,contact_points); + if(point_count == 0) return false; + contacts.merge_points(tu_plane,margin,contact_points,point_count); + contacts.m_separating_normal *= -1.f; + } + if(contacts.m_point_count == 0) return false; + return true; + } + +}; + + +/*class GIM_TRIANGLE_CALCULATION_CACHE +{ +public: + GREAL margin; + GUINT clipped_count; + btVector3 tu_vertices[3]; + btVector3 tv_vertices[3]; + btVector3 temp_points[MAX_TRI_CLIPPING]; + btVector3 temp_points1[MAX_TRI_CLIPPING]; + btVector3 clipped_points[MAX_TRI_CLIPPING]; + GIM_TRIANGLE_CONTACT_DATA contacts1; + GIM_TRIANGLE_CONTACT_DATA contacts2; + + + //! clip triangle + GUINT clip_triangle( + const btVector4 & tri_plane, + const btVector3 * tripoints, + const btVector3 * srcpoints, + btVector3 * clipped_points) + { + // edge 0 + + btVector4 edgeplane; + + EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane); + + GUINT clipped_count = PLANE_CLIP_TRIANGLE3D( + edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points); + + if(clipped_count == 0) return 0; + + // edge 1 + + EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane); + + clipped_count = PLANE_CLIP_POLYGON3D( + edgeplane,temp_points,clipped_count,temp_points1); + + if(clipped_count == 0) return 0; + + // edge 2 + + EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane); + + clipped_count = PLANE_CLIP_POLYGON3D( + edgeplane,temp_points1,clipped_count,clipped_points); + + return clipped_count; + } + + + + + //! collides only on one side + bool triangle_collision( + const btVector3 & u0, + const btVector3 & u1, + const btVector3 & u2, + GREAL margin_u, + const btVector3 & v0, + const btVector3 & v1, + const btVector3 & v2, + GREAL margin_v, + GIM_TRIANGLE_CONTACT_DATA & contacts) + { + + margin = margin_u + margin_v; + + + tu_vertices[0] = u0; + tu_vertices[1] = u1; + tu_vertices[2] = u2; + + tv_vertices[0] = v0; + tv_vertices[1] = v1; + tv_vertices[2] = v2; + + //create planes + // plane v vs U points + + + TRIANGLE_PLANE(tv_vertices[0],tv_vertices[1],tv_vertices[2],contacts1.m_separating_normal); + + clipped_count = clip_triangle( + contacts1.m_separating_normal,tv_vertices,tu_vertices,clipped_points); + + if(clipped_count == 0 ) + { + return false;//Reject + } + + //find most deep interval face1 + contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count); + if(contacts1.m_point_count == 0) return false; // too far + + //Normal pointing to triangle1 + //contacts1.m_separating_normal *= -1.f; + + //Clip tri1 by tri2 edges + + TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],contacts2.m_separating_normal); + + clipped_count = clip_triangle( + contacts2.m_separating_normal,tu_vertices,tv_vertices,clipped_points); + + if(clipped_count == 0 ) + { + return false;//Reject + } + + //find most deep interval face1 + contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count); + if(contacts2.m_point_count == 0) return false; // too far + + contacts2.m_separating_normal *= -1.f; + + ////check most dir for contacts + if(contacts2.m_penetration_depth + SIMD_FORCE_INLINE void mergepoints_generic(const CLASS_PLANE & plane, + GREAL margin, const btVector3 * points, GUINT point_count, DISTANCE_FUNC distance_func) + { + m_point_count = 0; + m_penetration_depth= -1000.0f; + + GUINT point_indices[MAX_TRI_CLIPPING]; + + GUINT _k; + + for(_k=0;_k=0.0f) + { + if(_dist>m_penetration_depth) + { + m_penetration_depth = _dist; + point_indices[0] = _k; + m_point_count=1; + } + else if((_dist+G_EPSILON)>=m_penetration_depth) + { + point_indices[m_point_count] = _k; + m_point_count++; + } + } + } + + for( _k=0;_k u*axe1[i1] + ((vecproj[i2] - u*axe1[i2])/axe2[i2])*axe2[i1] = vecproj[i1] + + --> u*axe1[i1] + vecproj[i2]*axe2[i1]/axe2[i2] - u*axe1[i2]*axe2[i1]/axe2[i2] = vecproj[i1] + + --> u*(axe1[i1] - axe1[i2]*axe2[i1]/axe2[i2]) = vecproj[i1] - vecproj[i2]*axe2[i1]/axe2[i2] + + --> u*((axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1])/axe2[i2]) = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1])/axe2[i2] + + --> u*(axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1]) = vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1] + + --> u = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]) /(axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1]) + +if 0.0<= u+v <=1.0 then they are inside of triangle + + \return false if the point is outside of triangle.This function doesn't take the margin + */ + SIMD_FORCE_INLINE bool get_uv_parameters( + const btVector3 & point, + const btVector3 & tri_plane, + GREAL & u, GREAL & v) const + { + btVector3 _axe1 = m_vertices[1]-m_vertices[0]; + btVector3 _axe2 = m_vertices[2]-m_vertices[0]; + btVector3 _vecproj = point - m_vertices[0]; + GUINT _i1 = (tri_plane.closestAxis()+1)%3; + GUINT _i2 = (_i1+1)%3; + if(btFabs(_axe2[_i2])G_EPSILON) + { + return false; + } + } + return true; + } + + //! is point in triangle beam? + /*! + Test if point is in triangle, with m_margin tolerance + */ + SIMD_FORCE_INLINE bool is_point_inside(const btVector3 & point, const btVector3 & tri_normal) const + { + //Test with edge 0 + btVector4 edge_plane; + this->get_edge_plane(0,tri_normal,edge_plane); + GREAL dist = DISTANCE_PLANE_POINT(edge_plane,point); + if(dist-m_margin>0.0f) return false; // outside plane + + this->get_edge_plane(1,tri_normal,edge_plane); + dist = DISTANCE_PLANE_POINT(edge_plane,point); + if(dist-m_margin>0.0f) return false; // outside plane + + this->get_edge_plane(2,tri_normal,edge_plane); + dist = DISTANCE_PLANE_POINT(edge_plane,point); + if(dist-m_margin>0.0f) return false; // outside plane + return true; + } + + + //! Bidireccional ray collision + SIMD_FORCE_INLINE bool ray_collision( + const btVector3 & vPoint, + const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal, + GREAL & tparam, GREAL tmax = G_REAL_INFINITY) + { + btVector4 faceplane; + { + btVector3 dif1 = m_vertices[1] - m_vertices[0]; + btVector3 dif2 = m_vertices[2] - m_vertices[0]; + VEC_CROSS(faceplane,dif1,dif2); + faceplane[3] = m_vertices[0].dot(faceplane); + } + + GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax); + if(res == 0) return false; + if(! is_point_inside(pout,faceplane)) return false; + + if(res==2) //invert normal + { + triangle_normal.setValue(-faceplane[0],-faceplane[1],-faceplane[2]); + } + else + { + triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]); + } + + VEC_NORMALIZE(triangle_normal); + + return true; + } + + + //! one direccion ray collision + SIMD_FORCE_INLINE bool ray_collision_front_side( + const btVector3 & vPoint, + const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal, + GREAL & tparam, GREAL tmax = G_REAL_INFINITY) + { + btVector4 faceplane; + { + btVector3 dif1 = m_vertices[1] - m_vertices[0]; + btVector3 dif2 = m_vertices[2] - m_vertices[0]; + VEC_CROSS(faceplane,dif1,dif2); + faceplane[3] = m_vertices[0].dot(faceplane); + } + + GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax); + if(res != 1) return false; + + if(!is_point_inside(pout,faceplane)) return false; + + triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]); + + VEC_NORMALIZE(triangle_normal); + + return true; + } + +}; + + + + +#endif // GIM_TRI_COLLISION_H_INCLUDED diff --git a/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp new file mode 100644 index 0000000..91fcea5 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp @@ -0,0 +1,243 @@ +/* +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 "btContinuousConvexCollision.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" +#include "LinearMath/btTransformUtil.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + +#include "btGjkPairDetector.h" +#include "btPointCollector.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" + + + +btContinuousConvexCollision::btContinuousConvexCollision ( const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver) +:m_simplexSolver(simplexSolver), +m_penetrationDepthSolver(penetrationDepthSolver), +m_convexA(convexA),m_convexB1(convexB),m_planeShape(0) +{ +} + + +btContinuousConvexCollision::btContinuousConvexCollision( const btConvexShape* convexA,const btStaticPlaneShape* plane) +:m_simplexSolver(0), +m_penetrationDepthSolver(0), +m_convexA(convexA),m_convexB1(0),m_planeShape(plane) +{ +} + + +/// This maximum should not be necessary. It allows for untested/degenerate cases in production code. +/// You don't want your game ever to lock-up. +#define MAX_ITERATIONS 64 + +void btContinuousConvexCollision::computeClosestPoints( const btTransform& transA, const btTransform& transB,btPointCollector& pointCollector) +{ + if (m_convexB1) + { + m_simplexSolver->reset(); + btGjkPairDetector gjk(m_convexA,m_convexB1,m_convexA->getShapeType(),m_convexB1->getShapeType(),m_convexA->getMargin(),m_convexB1->getMargin(),m_simplexSolver,m_penetrationDepthSolver); + btGjkPairDetector::ClosestPointInput input; + input.m_transformA = transA; + input.m_transformB = transB; + gjk.getClosestPoints(input,pointCollector,0); + } else + { + //convex versus plane + const btConvexShape* convexShape = m_convexA; + const btStaticPlaneShape* planeShape = m_planeShape; + + bool hasCollision = false; + const btVector3& planeNormal = planeShape->getPlaneNormal(); + const btScalar& planeConstant = planeShape->getPlaneConstant(); + + btTransform convexWorldTransform = transA; + btTransform convexInPlaneTrans; + convexInPlaneTrans= transB.inverse() * convexWorldTransform; + btTransform planeInConvex; + planeInConvex= convexWorldTransform.inverse() * transB; + + btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal); + + btVector3 vtxInPlane = convexInPlaneTrans(vtx); + btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); + + btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; + btVector3 vtxInPlaneWorld = transB * vtxInPlaneProjected; + btVector3 normalOnSurfaceB = transB.getBasis() * planeNormal; + + pointCollector.addContactPoint( + normalOnSurfaceB, + vtxInPlaneWorld, + distance); + } +} + +bool btContinuousConvexCollision::calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result) +{ + + + /// compute linear and angular velocity for this interval, to interpolate + btVector3 linVelA,angVelA,linVelB,angVelB; + btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA); + btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB); + + + btScalar boundingRadiusA = m_convexA->getAngularMotionDisc(); + btScalar boundingRadiusB = m_convexB1?m_convexB1->getAngularMotionDisc():0.f; + + btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB; + btVector3 relLinVel = (linVelB-linVelA); + + btScalar relLinVelocLength = (linVelB-linVelA).length(); + + if ((relLinVelocLength+maxAngularProjectedVelocity) == 0.f) + return false; + + + + btScalar lambda = btScalar(0.); + btVector3 v(1,0,0); + + int maxIter = MAX_ITERATIONS; + + btVector3 n; + n.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + bool hasResult = false; + btVector3 c; + + btScalar lastLambda = lambda; + //btScalar epsilon = btScalar(0.001); + + int numIter = 0; + //first solution, using GJK + + + btScalar radius = 0.001f; +// result.drawCoordSystem(sphereTr); + + btPointCollector pointCollector1; + + { + + computeClosestPoints(fromA,fromB,pointCollector1); + + hasResult = pointCollector1.m_hasResult; + c = pointCollector1.m_pointInWorld; + } + + if (hasResult) + { + btScalar dist; + dist = pointCollector1.m_distance + result.m_allowedPenetration; + n = pointCollector1.m_normalOnBInWorld; + btScalar projectedLinearVelocity = relLinVel.dot(n); + if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON) + return false; + + //not close enough + while (dist > radius) + { + if (result.m_debugDrawer) + { + result.m_debugDrawer->drawSphere(c,0.2f,btVector3(1,1,1)); + } + btScalar dLambda = btScalar(0.); + + projectedLinearVelocity = relLinVel.dot(n); + + + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON) + return false; + + dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity); + + + + lambda = lambda + dLambda; + + if (lambda > btScalar(1.)) + return false; + + if (lambda < btScalar(0.)) + return false; + + + //todo: next check with relative epsilon + if (lambda <= lastLambda) + { + return false; + //n.setValue(0,0,0); + break; + } + lastLambda = lambda; + + + + //interpolate to next lambda + btTransform interpolatedTransA,interpolatedTransB,relativeTrans; + + btTransformUtil::integrateTransform(fromA,linVelA,angVelA,lambda,interpolatedTransA); + btTransformUtil::integrateTransform(fromB,linVelB,angVelB,lambda,interpolatedTransB); + relativeTrans = interpolatedTransB.inverseTimes(interpolatedTransA); + + if (result.m_debugDrawer) + { + result.m_debugDrawer->drawSphere(interpolatedTransA.getOrigin(),0.2f,btVector3(1,0,0)); + } + + result.DebugDraw( lambda ); + + btPointCollector pointCollector; + computeClosestPoints(interpolatedTransA,interpolatedTransB,pointCollector); + + if (pointCollector.m_hasResult) + { + dist = pointCollector.m_distance+result.m_allowedPenetration; + c = pointCollector.m_pointInWorld; + n = pointCollector.m_normalOnBInWorld; + } else + { + result.reportFailure(-1, numIter); + return false; + } + + numIter++; + if (numIter > maxIter) + { + result.reportFailure(-2, numIter); + return false; + } + } + + result.m_fraction = lambda; + result.m_normal = n; + result.m_hitPoint = c; + return true; + } + + return false; + +} + diff --git a/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h b/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h new file mode 100644 index 0000000..bdc0572 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h @@ -0,0 +1,59 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_CONTINUOUS_COLLISION_CONVEX_CAST_H +#define BT_CONTINUOUS_COLLISION_CONVEX_CAST_H + +#include "btConvexCast.h" +#include "btSimplexSolverInterface.h" +class btConvexPenetrationDepthSolver; +class btConvexShape; +class btStaticPlaneShape; + +/// btContinuousConvexCollision implements angular and linear time of impact for convex objects. +/// Based on Brian Mirtich's Conservative Advancement idea (PhD thesis). +/// Algorithm operates in worldspace, in order to keep inbetween motion globally consistent. +/// It uses GJK at the moment. Future improvement would use minkowski sum / supporting vertex, merging innerloops +class btContinuousConvexCollision : public btConvexCast +{ + btSimplexSolverInterface* m_simplexSolver; + btConvexPenetrationDepthSolver* m_penetrationDepthSolver; + const btConvexShape* m_convexA; + //second object is either a convex or a plane (code sharing) + const btConvexShape* m_convexB1; + const btStaticPlaneShape* m_planeShape; + + void computeClosestPoints( const btTransform& transA, const btTransform& transB,struct btPointCollector& pointCollector); + +public: + + btContinuousConvexCollision (const btConvexShape* shapeA,const btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); + + btContinuousConvexCollision(const btConvexShape* shapeA,const btStaticPlaneShape* plane ); + + virtual bool calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result); + + +}; + + +#endif //BT_CONTINUOUS_COLLISION_CONVEX_CAST_H + diff --git a/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp b/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp new file mode 100644 index 0000000..d2a1310 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp @@ -0,0 +1,20 @@ +/* +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 "btConvexCast.h" + +btConvexCast::~btConvexCast() +{ +} diff --git a/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h new file mode 100644 index 0000000..bfd79d0 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h @@ -0,0 +1,73 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_CONVEX_CAST_H +#define BT_CONVEX_CAST_H + +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btScalar.h" +class btMinkowskiSumShape; +#include "LinearMath/btIDebugDraw.h" + +/// btConvexCast is an interface for Casting +class btConvexCast +{ +public: + + + virtual ~btConvexCast(); + + ///RayResult stores the closest result + /// alternatively, add a callback method to decide about closest/all results + struct CastResult + { + //virtual bool addRayResult(const btVector3& normal,btScalar fraction) = 0; + + virtual void DebugDraw(btScalar fraction) {(void)fraction;} + virtual void drawCoordSystem(const btTransform& trans) {(void)trans;} + virtual void reportFailure(int errNo, int numIterations) {(void)errNo;(void)numIterations;} + CastResult() + :m_fraction(btScalar(BT_LARGE_FLOAT)), + m_debugDrawer(0), + m_allowedPenetration(btScalar(0)) + { + } + + + virtual ~CastResult() {}; + + btTransform m_hitTransformA; + btTransform m_hitTransformB; + btVector3 m_normal; + btVector3 m_hitPoint; + btScalar m_fraction; //input and output + btIDebugDraw* m_debugDrawer; + btScalar m_allowedPenetration; + + }; + + + /// cast a convex against another convex object + virtual bool calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result) = 0; +}; + +#endif //BT_CONVEX_CAST_H diff --git a/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h b/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h new file mode 100644 index 0000000..72eb5ae --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h @@ -0,0 +1,42 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_CONVEX_PENETRATION_DEPTH_H +#define BT_CONVEX_PENETRATION_DEPTH_H + +class btStackAlloc; +class btVector3; +#include "btSimplexSolverInterface.h" +class btConvexShape; +class btTransform; + +///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation. +class btConvexPenetrationDepthSolver +{ +public: + + virtual ~btConvexPenetrationDepthSolver() {}; + virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, + const btConvexShape* convexA,const btConvexShape* convexB, + const btTransform& transA,const btTransform& transB, + btVector3& v, btVector3& pa, btVector3& pb, + class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc + ) = 0; + + +}; +#endif //BT_CONVEX_PENETRATION_DEPTH_H + diff --git a/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h b/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h new file mode 100644 index 0000000..f958cc5 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h @@ -0,0 +1,91 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H +#define BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H + +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +class btStackAlloc; + +/// This interface is made to be used by an iterative approach to do TimeOfImpact calculations +/// This interface allows to query for closest points and penetration depth between two (convex) objects +/// the closest point is on the second object (B), and the normal points from the surface on B towards A. +/// distance is between closest points on B and closest point on A. So you can calculate closest point on A +/// by taking closestPointInA = closestPointInB + m_distance * m_normalOnSurfaceB +struct btDiscreteCollisionDetectorInterface +{ + + struct Result + { + + virtual ~Result(){} + + ///setShapeIdentifiersA/B provides experimental support for per-triangle material / custom material combiner + virtual void setShapeIdentifiersA(int partId0,int index0)=0; + virtual void setShapeIdentifiersB(int partId1,int index1)=0; + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)=0; + }; + + struct ClosestPointInput + { + ClosestPointInput() + :m_maximumDistanceSquared(btScalar(BT_LARGE_FLOAT)), + m_stackAlloc(0) + { + } + + btTransform m_transformA; + btTransform m_transformB; + btScalar m_maximumDistanceSquared; + btStackAlloc* m_stackAlloc; + }; + + virtual ~btDiscreteCollisionDetectorInterface() {}; + + // + // give either closest points (distance > 0) or penetration (distance) + // the normal always points from B towards A + // + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false) = 0; + +}; + +struct btStorageResult : public btDiscreteCollisionDetectorInterface::Result +{ + btVector3 m_normalOnSurfaceB; + btVector3 m_closestPointInB; + btScalar m_distance; //negative means penetration ! + + btStorageResult() : m_distance(btScalar(BT_LARGE_FLOAT)) + { + + } + virtual ~btStorageResult() {}; + + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) + { + if (depth < m_distance) + { + m_normalOnSurfaceB = normalOnBInWorld; + m_closestPointInB = pointInWorld; + m_distance = depth; + } + } +}; + +#endif //BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H + diff --git a/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp new file mode 100644 index 0000000..bef697a --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp @@ -0,0 +1,176 @@ +/* +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 "btGjkConvexCast.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "btGjkPairDetector.h" +#include "btPointCollector.h" +#include "LinearMath/btTransformUtil.h" + +#ifdef BT_USE_DOUBLE_PRECISION +#define MAX_ITERATIONS 64 +#else +#define MAX_ITERATIONS 32 +#endif + +btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) +:m_simplexSolver(simplexSolver), +m_convexA(convexA), +m_convexB(convexB) +{ +} + +bool btGjkConvexCast::calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result) +{ + + + m_simplexSolver->reset(); + + /// compute linear velocity for this interval, to interpolate + //assume no rotation/angular velocity, assert here? + btVector3 linVelA,linVelB; + linVelA = toA.getOrigin()-fromA.getOrigin(); + linVelB = toB.getOrigin()-fromB.getOrigin(); + + btScalar radius = btScalar(0.001); + btScalar lambda = btScalar(0.); + btVector3 v(1,0,0); + + int maxIter = MAX_ITERATIONS; + + btVector3 n; + n.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + bool hasResult = false; + btVector3 c; + btVector3 r = (linVelA-linVelB); + + btScalar lastLambda = lambda; + //btScalar epsilon = btScalar(0.001); + + int numIter = 0; + //first solution, using GJK + + + btTransform identityTrans; + identityTrans.setIdentity(); + + +// result.drawCoordSystem(sphereTr); + + btPointCollector pointCollector; + + + btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,0);//m_penetrationDepthSolver); + btGjkPairDetector::ClosestPointInput input; + + //we don't use margins during CCD + // gjk.setIgnoreMargin(true); + + input.m_transformA = fromA; + input.m_transformB = fromB; + gjk.getClosestPoints(input,pointCollector,0); + + hasResult = pointCollector.m_hasResult; + c = pointCollector.m_pointInWorld; + + if (hasResult) + { + btScalar dist; + dist = pointCollector.m_distance; + n = pointCollector.m_normalOnBInWorld; + + + + //not close enough + while (dist > radius) + { + numIter++; + if (numIter > maxIter) + { + return false; //todo: report a failure + } + btScalar dLambda = btScalar(0.); + + btScalar projectedLinearVelocity = r.dot(n); + + dLambda = dist / (projectedLinearVelocity); + + lambda = lambda - dLambda; + + if (lambda > btScalar(1.)) + return false; + + if (lambda < btScalar(0.)) + return false; + + //todo: next check with relative epsilon + if (lambda <= lastLambda) + { + return false; + //n.setValue(0,0,0); + break; + } + lastLambda = lambda; + + //interpolate to next lambda + result.DebugDraw( lambda ); + input.m_transformA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda); + input.m_transformB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda); + + gjk.getClosestPoints(input,pointCollector,0); + if (pointCollector.m_hasResult) + { + if (pointCollector.m_distance < btScalar(0.)) + { + result.m_fraction = lastLambda; + n = pointCollector.m_normalOnBInWorld; + result.m_normal=n; + result.m_hitPoint = pointCollector.m_pointInWorld; + return true; + } + c = pointCollector.m_pointInWorld; + n = pointCollector.m_normalOnBInWorld; + dist = pointCollector.m_distance; + } else + { + //?? + return false; + } + + } + + //is n normalized? + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if (n.dot(r)>=-result.m_allowedPenetration) + return false; + + result.m_fraction = lambda; + result.m_normal = n; + result.m_hitPoint = c; + return true; + } + + return false; + + +} + diff --git a/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h b/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h new file mode 100644 index 0000000..6a42ee6 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h @@ -0,0 +1,50 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_GJK_CONVEX_CAST_H +#define BT_GJK_CONVEX_CAST_H + +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + +#include "LinearMath/btVector3.h" +#include "btConvexCast.h" +class btConvexShape; +class btMinkowskiSumShape; +#include "btSimplexSolverInterface.h" + +///GjkConvexCast performs a raycast on a convex object using support mapping. +class btGjkConvexCast : public btConvexCast +{ + btSimplexSolverInterface* m_simplexSolver; + const btConvexShape* m_convexA; + const btConvexShape* m_convexB; + +public: + + btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver); + + /// cast a convex against another convex object + virtual bool calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result); + +}; + +#endif //BT_GJK_CONVEX_CAST_H diff --git a/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp b/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp new file mode 100644 index 0000000..f74261d --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp @@ -0,0 +1,989 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 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. +*/ + +/* +GJK-EPA collision solver by Nathanael Presson, 2008 +*/ +#include "BulletCollision/CollisionShapes/btConvexInternalShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "btGjkEpa2.h" + +#if defined(DEBUG) || defined (_DEBUG) +#include //for debug printf +#ifdef __SPU__ +#include +#define printf spu_printf +#endif //__SPU__ +#endif + +namespace gjkepa2_impl +{ + + // Config + + /* GJK */ +#define GJK_MAX_ITERATIONS 128 +#define GJK_ACCURARY ((btScalar)0.0001) +#define GJK_MIN_DISTANCE ((btScalar)0.0001) +#define GJK_DUPLICATED_EPS ((btScalar)0.0001) +#define GJK_SIMPLEX2_EPS ((btScalar)0.0) +#define GJK_SIMPLEX3_EPS ((btScalar)0.0) +#define GJK_SIMPLEX4_EPS ((btScalar)0.0) + + /* EPA */ +#define EPA_MAX_VERTICES 64 +#define EPA_MAX_FACES (EPA_MAX_VERTICES*2) +#define EPA_MAX_ITERATIONS 255 +#define EPA_ACCURACY ((btScalar)0.0001) +#define EPA_FALLBACK (10*EPA_ACCURACY) +#define EPA_PLANE_EPS ((btScalar)0.00001) +#define EPA_INSIDE_EPS ((btScalar)0.01) + + + // Shorthands + typedef unsigned int U; + typedef unsigned char U1; + + // MinkowskiDiff + struct MinkowskiDiff + { + const btConvexShape* m_shapes[2]; + btMatrix3x3 m_toshape1; + btTransform m_toshape0; +#ifdef __SPU__ + bool m_enableMargin; +#else + btVector3 (btConvexShape::*Ls)(const btVector3&) const; +#endif//__SPU__ + + + MinkowskiDiff() + { + + } +#ifdef __SPU__ + void EnableMargin(bool enable) + { + m_enableMargin = enable; + } + inline btVector3 Support0(const btVector3& d) const + { + if (m_enableMargin) + { + return m_shapes[0]->localGetSupportVertexNonVirtual(d); + } else + { + return m_shapes[0]->localGetSupportVertexWithoutMarginNonVirtual(d); + } + } + inline btVector3 Support1(const btVector3& d) const + { + if (m_enableMargin) + { + return m_toshape0*(m_shapes[1]->localGetSupportVertexNonVirtual(m_toshape1*d)); + } else + { + return m_toshape0*(m_shapes[1]->localGetSupportVertexWithoutMarginNonVirtual(m_toshape1*d)); + } + } +#else + void EnableMargin(bool enable) + { + if(enable) + Ls=&btConvexShape::localGetSupportVertexNonVirtual; + else + Ls=&btConvexShape::localGetSupportVertexWithoutMarginNonVirtual; + } + inline btVector3 Support0(const btVector3& d) const + { + return(((m_shapes[0])->*(Ls))(d)); + } + inline btVector3 Support1(const btVector3& d) const + { + return(m_toshape0*((m_shapes[1])->*(Ls))(m_toshape1*d)); + } +#endif //__SPU__ + + inline btVector3 Support(const btVector3& d) const + { + return(Support0(d)-Support1(-d)); + } + btVector3 Support(const btVector3& d,U index) const + { + if(index) + return(Support1(d)); + else + return(Support0(d)); + } + }; + + typedef MinkowskiDiff tShape; + + + // GJK + struct GJK + { + /* Types */ + struct sSV + { + btVector3 d,w; + }; + struct sSimplex + { + sSV* c[4]; + btScalar p[4]; + U rank; + }; + struct eStatus { enum _ { + Valid, + Inside, + Failed };}; + /* Fields */ + tShape m_shape; + btVector3 m_ray; + btScalar m_distance; + sSimplex m_simplices[2]; + sSV m_store[4]; + sSV* m_free[4]; + U m_nfree; + U m_current; + sSimplex* m_simplex; + eStatus::_ m_status; + /* Methods */ + GJK() + { + Initialize(); + } + void Initialize() + { + m_ray = btVector3(0,0,0); + m_nfree = 0; + m_status = eStatus::Failed; + m_current = 0; + m_distance = 0; + } + eStatus::_ Evaluate(const tShape& shapearg,const btVector3& guess) + { + U iterations=0; + btScalar sqdist=0; + btScalar alpha=0; + btVector3 lastw[4]; + U clastw=0; + /* Initialize solver */ + m_free[0] = &m_store[0]; + m_free[1] = &m_store[1]; + m_free[2] = &m_store[2]; + m_free[3] = &m_store[3]; + m_nfree = 4; + m_current = 0; + m_status = eStatus::Valid; + m_shape = shapearg; + m_distance = 0; + /* Initialize simplex */ + m_simplices[0].rank = 0; + m_ray = guess; + const btScalar sqrl= m_ray.length2(); + appendvertice(m_simplices[0],sqrl>0?-m_ray:btVector3(1,0,0)); + m_simplices[0].p[0] = 1; + m_ray = m_simplices[0].c[0]->w; + sqdist = sqrl; + lastw[0] = + lastw[1] = + lastw[2] = + lastw[3] = m_ray; + /* Loop */ + do { + const U next=1-m_current; + sSimplex& cs=m_simplices[m_current]; + sSimplex& ns=m_simplices[next]; + /* Check zero */ + const btScalar rl=m_ray.length(); + if(rlw; + bool found=false; + for(U i=0;i<4;++i) + { + if((w-lastw[i]).length2()w, + cs.c[1]->w, + weights,mask);break; + case 3: sqdist=projectorigin( cs.c[0]->w, + cs.c[1]->w, + cs.c[2]->w, + weights,mask);break; + case 4: sqdist=projectorigin( cs.c[0]->w, + cs.c[1]->w, + cs.c[2]->w, + cs.c[3]->w, + weights,mask);break; + } + if(sqdist>=0) + {/* Valid */ + ns.rank = 0; + m_ray = btVector3(0,0,0); + m_current = next; + for(U i=0,ni=cs.rank;iw*weights[i]; + } + else + { + m_free[m_nfree++] = cs.c[i]; + } + } + if(mask==15) m_status=eStatus::Inside; + } + else + {/* Return old simplex */ + removevertice(m_simplices[m_current]); + break; + } + m_status=((++iterations)rank) + { + case 1: + { + for(U i=0;i<3;++i) + { + btVector3 axis=btVector3(0,0,0); + axis[i]=1; + appendvertice(*m_simplex, axis); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + appendvertice(*m_simplex,-axis); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + } + } + break; + case 2: + { + const btVector3 d=m_simplex->c[1]->w-m_simplex->c[0]->w; + for(U i=0;i<3;++i) + { + btVector3 axis=btVector3(0,0,0); + axis[i]=1; + const btVector3 p=btCross(d,axis); + if(p.length2()>0) + { + appendvertice(*m_simplex, p); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + appendvertice(*m_simplex,-p); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + } + } + } + break; + case 3: + { + const btVector3 n=btCross(m_simplex->c[1]->w-m_simplex->c[0]->w, + m_simplex->c[2]->w-m_simplex->c[0]->w); + if(n.length2()>0) + { + appendvertice(*m_simplex,n); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + appendvertice(*m_simplex,-n); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + } + } + break; + case 4: + { + if(btFabs(det( m_simplex->c[0]->w-m_simplex->c[3]->w, + m_simplex->c[1]->w-m_simplex->c[3]->w, + m_simplex->c[2]->w-m_simplex->c[3]->w))>0) + return(true); + } + break; + } + return(false); + } + /* Internals */ + void getsupport(const btVector3& d,sSV& sv) const + { + sv.d = d/d.length(); + sv.w = m_shape.Support(sv.d); + } + void removevertice(sSimplex& simplex) + { + m_free[m_nfree++]=simplex.c[--simplex.rank]; + } + void appendvertice(sSimplex& simplex,const btVector3& v) + { + simplex.p[simplex.rank]=0; + simplex.c[simplex.rank]=m_free[--m_nfree]; + getsupport(v,*simplex.c[simplex.rank++]); + } + static btScalar det(const btVector3& a,const btVector3& b,const btVector3& c) + { + return( a.y()*b.z()*c.x()+a.z()*b.x()*c.y()- + a.x()*b.z()*c.y()-a.y()*b.x()*c.z()+ + a.x()*b.y()*c.z()-a.z()*b.y()*c.x()); + } + static btScalar projectorigin( const btVector3& a, + const btVector3& b, + btScalar* w,U& m) + { + const btVector3 d=b-a; + const btScalar l=d.length2(); + if(l>GJK_SIMPLEX2_EPS) + { + const btScalar t(l>0?-btDot(a,d)/l:0); + if(t>=1) { w[0]=0;w[1]=1;m=2;return(b.length2()); } + else if(t<=0) { w[0]=1;w[1]=0;m=1;return(a.length2()); } + else { w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); } + } + return(-1); + } + static btScalar projectorigin( const btVector3& a, + const btVector3& b, + const btVector3& c, + btScalar* w,U& m) + { + static const U imd3[]={1,2,0}; + const btVector3* vt[]={&a,&b,&c}; + const btVector3 dl[]={a-b,b-c,c-a}; + const btVector3 n=btCross(dl[0],dl[1]); + const btScalar l=n.length2(); + if(l>GJK_SIMPLEX3_EPS) + { + btScalar mindist=-1; + btScalar subw[2]={0.f,0.f}; + U subm(0); + for(U i=0;i<3;++i) + { + if(btDot(*vt[i],btCross(dl[i],n))>0) + { + const U j=imd3[i]; + const btScalar subd(projectorigin(*vt[i],*vt[j],subw,subm)); + if((mindist<0)||(subd(((subm&1)?1<GJK_SIMPLEX4_EPS)) + { + btScalar mindist=-1; + btScalar subw[3]={0.f,0.f,0.f}; + U subm(0); + for(U i=0;i<3;++i) + { + const U j=imd3[i]; + const btScalar s=vl*btDot(d,btCross(dl[i],dl[j])); + if(s>0) + { + const btScalar subd=projectorigin(*vt[i],*vt[j],d,subw,subm); + if((mindist<0)||(subd((subm&1?1<e[ea]=(U1)eb;fa->f[ea]=fb; + fb->e[eb]=(U1)ea;fb->f[eb]=fa; + } + static inline void append(sList& list,sFace* face) + { + face->l[0] = 0; + face->l[1] = list.root; + if(list.root) list.root->l[0]=face; + list.root = face; + ++list.count; + } + static inline void remove(sList& list,sFace* face) + { + if(face->l[1]) face->l[1]->l[0]=face->l[0]; + if(face->l[0]) face->l[0]->l[1]=face->l[1]; + if(face==list.root) list.root=face->l[1]; + --list.count; + } + + + void Initialize() + { + m_status = eStatus::Failed; + m_normal = btVector3(0,0,0); + m_depth = 0; + m_nextsv = 0; + for(U i=0;i1)&&gjk.EncloseOrigin()) + { + + /* Clean up */ + while(m_hull.root) + { + sFace* f = m_hull.root; + remove(m_hull,f); + append(m_stock,f); + } + m_status = eStatus::Valid; + m_nextsv = 0; + /* Orient simplex */ + if(gjk.det( simplex.c[0]->w-simplex.c[3]->w, + simplex.c[1]->w-simplex.c[3]->w, + simplex.c[2]->w-simplex.c[3]->w)<0) + { + btSwap(simplex.c[0],simplex.c[1]); + btSwap(simplex.p[0],simplex.p[1]); + } + /* Build initial hull */ + sFace* tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true), + newface(simplex.c[1],simplex.c[0],simplex.c[3],true), + newface(simplex.c[2],simplex.c[1],simplex.c[3],true), + newface(simplex.c[0],simplex.c[2],simplex.c[3],true)}; + if(m_hull.count==4) + { + sFace* best=findbest(); + sFace outer=*best; + U pass=0; + U iterations=0; + bind(tetra[0],0,tetra[1],0); + bind(tetra[0],1,tetra[2],0); + bind(tetra[0],2,tetra[3],0); + bind(tetra[1],1,tetra[3],2); + bind(tetra[1],2,tetra[2],1); + bind(tetra[2],2,tetra[3],1); + m_status=eStatus::Valid; + for(;iterationspass = (U1)(++pass); + gjk.getsupport(best->n,*w); + const btScalar wdist=btDot(best->n,w->w)-best->d; + if(wdist>EPA_ACCURACY) + { + for(U j=0;(j<3)&&valid;++j) + { + valid&=expand( pass,w, + best->f[j],best->e[j], + horizon); + } + if(valid&&(horizon.nf>=3)) + { + bind(horizon.cf,1,horizon.ff,2); + remove(m_hull,best); + append(m_stock,best); + best=findbest(); + if(best->p>=outer.p) outer=*best; + } else { m_status=eStatus::InvalidHull;break; } + } else { m_status=eStatus::AccuraryReached;break; } + } else { m_status=eStatus::OutOfVertices;break; } + } + const btVector3 projection=outer.n*outer.d; + m_normal = outer.n; + m_depth = outer.d; + m_result.rank = 3; + m_result.c[0] = outer.c[0]; + m_result.c[1] = outer.c[1]; + m_result.c[2] = outer.c[2]; + m_result.p[0] = btCross( outer.c[1]->w-projection, + outer.c[2]->w-projection).length(); + m_result.p[1] = btCross( outer.c[2]->w-projection, + outer.c[0]->w-projection).length(); + m_result.p[2] = btCross( outer.c[0]->w-projection, + outer.c[1]->w-projection).length(); + const btScalar sum=m_result.p[0]+m_result.p[1]+m_result.p[2]; + m_result.p[0] /= sum; + m_result.p[1] /= sum; + m_result.p[2] /= sum; + return(m_status); + } + } + /* Fallback */ + m_status = eStatus::FallBack; + m_normal = -guess; + const btScalar nl=m_normal.length(); + if(nl>0) + m_normal = m_normal/nl; + else + m_normal = btVector3(1,0,0); + m_depth = 0; + m_result.rank=1; + m_result.c[0]=simplex.c[0]; + m_result.p[0]=1; + return(m_status); + } + sFace* newface(sSV* a,sSV* b,sSV* c,bool forced) + { + if(m_stock.root) + { + sFace* face=m_stock.root; + remove(m_stock,face); + append(m_hull,face); + face->pass = 0; + face->c[0] = a; + face->c[1] = b; + face->c[2] = c; + face->n = btCross(b->w-a->w,c->w-a->w); + const btScalar l=face->n.length(); + const bool v=l>EPA_ACCURACY; + face->p = btMin(btMin( + btDot(a->w,btCross(face->n,a->w-b->w)), + btDot(b->w,btCross(face->n,b->w-c->w))), + btDot(c->w,btCross(face->n,c->w-a->w))) / + (v?l:1); + face->p = face->p>=-EPA_INSIDE_EPS?0:face->p; + if(v) + { + face->d = btDot(a->w,face->n)/l; + face->n /= l; + if(forced||(face->d>=-EPA_PLANE_EPS)) + { + return(face); + } else m_status=eStatus::NonConvex; + } else m_status=eStatus::Degenerated; + remove(m_hull,face); + append(m_stock,face); + return(0); + } + m_status=m_stock.root?eStatus::OutOfVertices:eStatus::OutOfFaces; + return(0); + } + sFace* findbest() + { + sFace* minf=m_hull.root; + btScalar mind=minf->d*minf->d; + btScalar maxp=minf->p; + for(sFace* f=minf->l[1];f;f=f->l[1]) + { + const btScalar sqd=f->d*f->d; + if((f->p>=maxp)&&(sqdp; + } + } + return(minf); + } + bool expand(U pass,sSV* w,sFace* f,U e,sHorizon& horizon) + { + static const U i1m3[]={1,2,0}; + static const U i2m3[]={2,0,1}; + if(f->pass!=pass) + { + const U e1=i1m3[e]; + if((btDot(f->n,w->w)-f->d)<-EPA_PLANE_EPS) + { + sFace* nf=newface(f->c[e1],f->c[e],w,false); + if(nf) + { + bind(nf,0,f,e); + if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf; + horizon.cf=nf; + ++horizon.nf; + return(true); + } + } + else + { + const U e2=i2m3[e]; + f->pass = (U1)pass; + if( expand(pass,w,f->f[e1],f->e[e1],horizon)&& + expand(pass,w,f->f[e2],f->e[e2],horizon)) + { + remove(m_hull,f); + append(m_stock,f); + return(true); + } + } + } + return(false); + } + + }; + + // + static void Initialize( const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + btGjkEpaSolver2::sResults& results, + tShape& shape, + bool withmargins) + { + /* Results */ + results.witnesses[0] = + results.witnesses[1] = btVector3(0,0,0); + results.status = btGjkEpaSolver2::sResults::Separated; + /* Shape */ + shape.m_shapes[0] = shape0; + shape.m_shapes[1] = shape1; + shape.m_toshape1 = wtrs1.getBasis().transposeTimes(wtrs0.getBasis()); + shape.m_toshape0 = wtrs0.inverseTimes(wtrs1); + shape.EnableMargin(withmargins); + } + +} + +// +// Api +// + +using namespace gjkepa2_impl; + +// +int btGjkEpaSolver2::StackSizeRequirement() +{ + return(sizeof(GJK)+sizeof(EPA)); +} + +// +bool btGjkEpaSolver2::Distance( const btConvexShape* shape0, + const btTransform& wtrs0, + const btConvexShape* shape1, + const btTransform& wtrs1, + const btVector3& guess, + sResults& results) +{ + tShape shape; + Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false); + GJK gjk; + GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess); + if(gjk_status==GJK::eStatus::Valid) + { + btVector3 w0=btVector3(0,0,0); + btVector3 w1=btVector3(0,0,0); + for(U i=0;irank;++i) + { + const btScalar p=gjk.m_simplex->p[i]; + w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p; + w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p; + } + results.witnesses[0] = wtrs0*w0; + results.witnesses[1] = wtrs0*w1; + results.normal = w0-w1; + results.distance = results.normal.length(); + results.normal /= results.distance>GJK_MIN_DISTANCE?results.distance:1; + return(true); + } + else + { + results.status = gjk_status==GJK::eStatus::Inside? + sResults::Penetrating : + sResults::GJK_Failed ; + return(false); + } +} + +// +bool btGjkEpaSolver2::Penetration( const btConvexShape* shape0, + const btTransform& wtrs0, + const btConvexShape* shape1, + const btTransform& wtrs1, + const btVector3& guess, + sResults& results, + bool usemargins) +{ + tShape shape; + Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,usemargins); + GJK gjk; + GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,-guess); + switch(gjk_status) + { + case GJK::eStatus::Inside: + { + EPA epa; + EPA::eStatus::_ epa_status=epa.Evaluate(gjk,-guess); + if(epa_status!=EPA::eStatus::Failed) + { + btVector3 w0=btVector3(0,0,0); + for(U i=0;id,0)*epa.m_result.p[i]; + } + results.status = sResults::Penetrating; + results.witnesses[0] = wtrs0*w0; + results.witnesses[1] = wtrs0*(w0-epa.m_normal*epa.m_depth); + results.normal = -epa.m_normal; + results.distance = -epa.m_depth; + return(true); + } else results.status=sResults::EPA_Failed; + } + break; + case GJK::eStatus::Failed: + results.status=sResults::GJK_Failed; + break; + default: + { + } + } + return(false); +} + +#ifndef __SPU__ +// +btScalar btGjkEpaSolver2::SignedDistance(const btVector3& position, + btScalar margin, + const btConvexShape* shape0, + const btTransform& wtrs0, + sResults& results) +{ + tShape shape; + btSphereShape shape1(margin); + btTransform wtrs1(btQuaternion(0,0,0,1),position); + Initialize(shape0,wtrs0,&shape1,wtrs1,results,shape,false); + GJK gjk; + GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,btVector3(1,1,1)); + if(gjk_status==GJK::eStatus::Valid) + { + btVector3 w0=btVector3(0,0,0); + btVector3 w1=btVector3(0,0,0); + for(U i=0;irank;++i) + { + const btScalar p=gjk.m_simplex->p[i]; + w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p; + w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p; + } + results.witnesses[0] = wtrs0*w0; + results.witnesses[1] = wtrs0*w1; + const btVector3 delta= results.witnesses[1]- + results.witnesses[0]; + const btScalar margin= shape0->getMarginNonVirtual()+ + shape1.getMarginNonVirtual(); + const btScalar length= delta.length(); + results.normal = delta/length; + results.witnesses[0] += results.normal*margin; + return(length-margin); + } + else + { + if(gjk_status==GJK::eStatus::Inside) + { + if(Penetration(shape0,wtrs0,&shape1,wtrs1,gjk.m_ray,results)) + { + const btVector3 delta= results.witnesses[0]- + results.witnesses[1]; + const btScalar length= delta.length(); + if (length >= SIMD_EPSILON) + results.normal = delta/length; + return(-length); + } + } + } + return(SIMD_INFINITY); +} + +// +bool btGjkEpaSolver2::SignedDistance(const btConvexShape* shape0, + const btTransform& wtrs0, + const btConvexShape* shape1, + const btTransform& wtrs1, + const btVector3& guess, + sResults& results) +{ + if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results)) + return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false)); + else + return(true); +} +#endif //__SPU__ + +/* Symbols cleanup */ + +#undef GJK_MAX_ITERATIONS +#undef GJK_ACCURARY +#undef GJK_MIN_DISTANCE +#undef GJK_DUPLICATED_EPS +#undef GJK_SIMPLEX2_EPS +#undef GJK_SIMPLEX3_EPS +#undef GJK_SIMPLEX4_EPS + +#undef EPA_MAX_VERTICES +#undef EPA_MAX_FACES +#undef EPA_MAX_ITERATIONS +#undef EPA_ACCURACY +#undef EPA_FALLBACK +#undef EPA_PLANE_EPS +#undef EPA_INSIDE_EPS diff --git a/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h b/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h new file mode 100644 index 0000000..ac501d5 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h @@ -0,0 +1,75 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 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. +*/ + +/* +GJK-EPA collision solver by Nathanael Presson, 2008 +*/ +#ifndef BT_GJK_EPA2_H +#define BT_GJK_EPA2_H + +#include "BulletCollision/CollisionShapes/btConvexShape.h" + +///btGjkEpaSolver contributed under zlib by Nathanael Presson +struct btGjkEpaSolver2 +{ +struct sResults + { + enum eStatus + { + Separated, /* Shapes doesnt penetrate */ + Penetrating, /* Shapes are penetrating */ + GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */ + EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */ + } status; + btVector3 witnesses[2]; + btVector3 normal; + btScalar distance; + }; + +static int StackSizeRequirement(); + +static bool Distance( const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + const btVector3& guess, + sResults& results); + +static bool Penetration(const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + const btVector3& guess, + sResults& results, + bool usemargins=true); +#ifndef __SPU__ +static btScalar SignedDistance( const btVector3& position, + btScalar margin, + const btConvexShape* shape, + const btTransform& wtrs, + sResults& results); + +static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + const btVector3& guess, + sResults& results); +#endif //__SPU__ + +}; + +#endif //BT_GJK_EPA2_H + diff --git a/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp new file mode 100644 index 0000000..c6dc3f3 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp @@ -0,0 +1,66 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +EPA Copyright (c) Ricardo Padrela 2006 + +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 "BulletCollision/CollisionShapes/btConvexShape.h" +#include "btGjkEpaPenetrationDepthSolver.h" + + +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" + +bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver, + const btConvexShape* pConvexA, const btConvexShape* pConvexB, + const btTransform& transformA, const btTransform& transformB, + btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB, + class btIDebugDraw* debugDraw, btStackAlloc* stackAlloc ) +{ + + (void)debugDraw; + (void)v; + (void)simplexSolver; + +// const btScalar radialmargin(btScalar(0.)); + + btVector3 guessVector(transformA.getOrigin()-transformB.getOrigin()); + btGjkEpaSolver2::sResults results; + + + if(btGjkEpaSolver2::Penetration(pConvexA,transformA, + pConvexB,transformB, + guessVector,results)) + + { + // debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0)); + //resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth); + wWitnessOnA = results.witnesses[0]; + wWitnessOnB = results.witnesses[1]; + v = results.normal; + return true; + } else + { + if(btGjkEpaSolver2::Distance(pConvexA,transformA,pConvexB,transformB,guessVector,results)) + { + wWitnessOnA = results.witnesses[0]; + wWitnessOnB = results.witnesses[1]; + v = results.normal; + return false; + } + } + + return false; +} + + diff --git a/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h b/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h new file mode 100644 index 0000000..a49689a --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h @@ -0,0 +1,43 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +EPA Copyright (c) Ricardo Padrela 2006 + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BT_GJP_EPA_PENETRATION_DEPTH_H +#define BT_GJP_EPA_PENETRATION_DEPTH_H + +#include "btConvexPenetrationDepthSolver.h" + +///EpaPenetrationDepthSolver uses the Expanding Polytope Algorithm to +///calculate the penetration depth between two convex shapes. +class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver +{ + public : + + btGjkEpaPenetrationDepthSolver() + { + } + + bool calcPenDepth( btSimplexSolverInterface& simplexSolver, + const btConvexShape* pConvexA, const btConvexShape* pConvexB, + const btTransform& transformA, const btTransform& transformB, + btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB, + class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc ); + + private : + +}; + +#endif // BT_GJP_EPA_PENETRATION_DEPTH_H + diff --git a/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp new file mode 100644 index 0000000..8af16b9 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp @@ -0,0 +1,457 @@ +/* +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 "btGjkPairDetector.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" +#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" + + + +#if defined(DEBUG) || defined (_DEBUG) +//#define TEST_NON_VIRTUAL 1 +#include //for debug printf +#ifdef __SPU__ +#include +#define printf spu_printf +//#define DEBUG_SPU_COLLISION_DETECTION 1 +#endif //__SPU__ +#endif + +//must be above the machine epsilon +#define REL_ERROR2 btScalar(1.0e-6) + +//temp globals, to improve GJK/EPA/penetration calculations +int gNumDeepPenetrationChecks = 0; +int gNumGjkChecks = 0; + + +btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver) +:m_cachedSeparatingAxis(btScalar(0.),btScalar(1.),btScalar(0.)), +m_penetrationDepthSolver(penetrationDepthSolver), +m_simplexSolver(simplexSolver), +m_minkowskiA(objectA), +m_minkowskiB(objectB), +m_shapeTypeA(objectA->getShapeType()), +m_shapeTypeB(objectB->getShapeType()), +m_marginA(objectA->getMargin()), +m_marginB(objectB->getMargin()), +m_ignoreMargin(false), +m_lastUsedMethod(-1), +m_catchDegeneracies(1) +{ +} +btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,int shapeTypeA,int shapeTypeB,btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver) +:m_cachedSeparatingAxis(btScalar(0.),btScalar(1.),btScalar(0.)), +m_penetrationDepthSolver(penetrationDepthSolver), +m_simplexSolver(simplexSolver), +m_minkowskiA(objectA), +m_minkowskiB(objectB), +m_shapeTypeA(shapeTypeA), +m_shapeTypeB(shapeTypeB), +m_marginA(marginA), +m_marginB(marginB), +m_ignoreMargin(false), +m_lastUsedMethod(-1), +m_catchDegeneracies(1) +{ +} + +void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults) +{ + (void)swapResults; + + getClosestPointsNonVirtual(input,output,debugDraw); +} + +#ifdef __SPU__ +void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) +#else +void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) +#endif +{ + m_cachedSeparatingDistance = 0.f; + + btScalar distance=btScalar(0.); + btVector3 normalInB(btScalar(0.),btScalar(0.),btScalar(0.)); + btVector3 pointOnA,pointOnB; + btTransform localTransA = input.m_transformA; + btTransform localTransB = input.m_transformB; + btVector3 positionOffset = (localTransA.getOrigin() + localTransB.getOrigin()) * btScalar(0.5); + localTransA.getOrigin() -= positionOffset; + localTransB.getOrigin() -= positionOffset; + + bool check2d = m_minkowskiA->isConvex2d() && m_minkowskiB->isConvex2d(); + + btScalar marginA = m_marginA; + btScalar marginB = m_marginB; + + gNumGjkChecks++; + +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("inside gjk\n"); +#endif + //for CCD we don't use margins + if (m_ignoreMargin) + { + marginA = btScalar(0.); + marginB = btScalar(0.); +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("ignoring margin\n"); +#endif + } + + m_curIter = 0; + int gGjkMaxIter = 1000;//this is to catch invalid input, perhaps check for #NaN? + m_cachedSeparatingAxis.setValue(0,1,0); + + bool isValid = false; + bool checkSimplex = false; + bool checkPenetration = true; + m_degenerateSimplex = 0; + + m_lastUsedMethod = -1; + + { + btScalar squaredDistance = BT_LARGE_FLOAT; + btScalar delta = btScalar(0.); + + btScalar margin = marginA + marginB; + + + + m_simplexSolver->reset(); + + for ( ; ; ) + //while (true) + { + + btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis)* input.m_transformA.getBasis(); + btVector3 seperatingAxisInB = m_cachedSeparatingAxis* input.m_transformB.getBasis(); + +#if 1 + + btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA); + btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB); + +// btVector3 pInA = localGetSupportingVertexWithoutMargin(m_shapeTypeA, m_minkowskiA, seperatingAxisInA,input.m_convexVertexData[0]);//, &featureIndexA); +// btVector3 qInB = localGetSupportingVertexWithoutMargin(m_shapeTypeB, m_minkowskiB, seperatingAxisInB,input.m_convexVertexData[1]);//, &featureIndexB); + +#else +#ifdef __SPU__ + btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA); + btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB); +#else + btVector3 pInA = m_minkowskiA->localGetSupportingVertexWithoutMargin(seperatingAxisInA); + btVector3 qInB = m_minkowskiB->localGetSupportingVertexWithoutMargin(seperatingAxisInB); +#ifdef TEST_NON_VIRTUAL + btVector3 pInAv = m_minkowskiA->localGetSupportingVertexWithoutMargin(seperatingAxisInA); + btVector3 qInBv = m_minkowskiB->localGetSupportingVertexWithoutMargin(seperatingAxisInB); + btAssert((pInAv-pInA).length() < 0.0001); + btAssert((qInBv-qInB).length() < 0.0001); +#endif // +#endif //__SPU__ +#endif + + + btVector3 pWorld = localTransA(pInA); + btVector3 qWorld = localTransB(qInB); + +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("got local supporting vertices\n"); +#endif + + if (check2d) + { + pWorld[2] = 0.f; + qWorld[2] = 0.f; + } + + btVector3 w = pWorld - qWorld; + delta = m_cachedSeparatingAxis.dot(w); + + // potential exit, they don't overlap + if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * input.m_maximumDistanceSquared)) + { + m_degenerateSimplex = 10; + checkSimplex=true; + //checkPenetration = false; + break; + } + + //exit 0: the new point is already in the simplex, or we didn't come any closer + if (m_simplexSolver->inSimplex(w)) + { + m_degenerateSimplex = 1; + checkSimplex = true; + break; + } + // are we getting any closer ? + btScalar f0 = squaredDistance - delta; + btScalar f1 = squaredDistance * REL_ERROR2; + + if (f0 <= f1) + { + if (f0 <= btScalar(0.)) + { + m_degenerateSimplex = 2; + } else + { + m_degenerateSimplex = 11; + } + checkSimplex = true; + break; + } + +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("addVertex 1\n"); +#endif + //add current vertex to simplex + m_simplexSolver->addVertex(w, pWorld, qWorld); +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("addVertex 2\n"); +#endif + btVector3 newCachedSeparatingAxis; + + //calculate the closest point to the origin (update vector v) + if (!m_simplexSolver->closest(newCachedSeparatingAxis)) + { + m_degenerateSimplex = 3; + checkSimplex = true; + break; + } + + if(newCachedSeparatingAxis.length2()previousSquaredDistance) + { + m_degenerateSimplex = 7; + squaredDistance = previousSquaredDistance; + checkSimplex = false; + break; + } +#endif // + + + //redundant m_simplexSolver->compute_points(pointOnA, pointOnB); + + //are we getting any closer ? + if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance) + { +// m_simplexSolver->backup_closest(m_cachedSeparatingAxis); + checkSimplex = true; + m_degenerateSimplex = 12; + + break; + } + + m_cachedSeparatingAxis = newCachedSeparatingAxis; + + //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject + if (m_curIter++ > gGjkMaxIter) + { + #if defined(DEBUG) || defined (_DEBUG) || defined (DEBUG_SPU_COLLISION_DETECTION) + + printf("btGjkPairDetector maxIter exceeded:%i\n",m_curIter); + printf("sepAxis=(%f,%f,%f), squaredDistance = %f, shapeTypeA=%i,shapeTypeB=%i\n", + m_cachedSeparatingAxis.getX(), + m_cachedSeparatingAxis.getY(), + m_cachedSeparatingAxis.getZ(), + squaredDistance, + m_minkowskiA->getShapeType(), + m_minkowskiB->getShapeType()); + + #endif + break; + + } + + + bool check = (!m_simplexSolver->fullSimplex()); + //bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex()); + + if (!check) + { + //do we need this backup_closest here ? +// m_simplexSolver->backup_closest(m_cachedSeparatingAxis); + m_degenerateSimplex = 13; + break; + } + } + + if (checkSimplex) + { + m_simplexSolver->compute_points(pointOnA, pointOnB); + normalInB = m_cachedSeparatingAxis; + btScalar lenSqr =m_cachedSeparatingAxis.length2(); + + //valid normal + if (lenSqr < 0.0001) + { + m_degenerateSimplex = 5; + } + if (lenSqr > SIMD_EPSILON*SIMD_EPSILON) + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + normalInB *= rlen; //normalize + btScalar s = btSqrt(squaredDistance); + + btAssert(s > btScalar(0.0)); + pointOnA -= m_cachedSeparatingAxis * (marginA / s); + pointOnB += m_cachedSeparatingAxis * (marginB / s); + distance = ((btScalar(1.)/rlen) - margin); + isValid = true; + + m_lastUsedMethod = 1; + } else + { + m_lastUsedMethod = 2; + } + } + + bool catchDegeneratePenetrationCase = + (m_catchDegeneracies && m_penetrationDepthSolver && m_degenerateSimplex && ((distance+margin) < 0.01)); + + //if (checkPenetration && !isValid) + if (checkPenetration && (!isValid || catchDegeneratePenetrationCase )) + { + //penetration case + + //if there is no way to handle penetrations, bail out + if (m_penetrationDepthSolver) + { + // Penetration depth case. + btVector3 tmpPointOnA,tmpPointOnB; + + gNumDeepPenetrationChecks++; + m_cachedSeparatingAxis.setZero(); + + bool isValid2 = m_penetrationDepthSolver->calcPenDepth( + *m_simplexSolver, + m_minkowskiA,m_minkowskiB, + localTransA,localTransB, + m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB, + debugDraw,input.m_stackAlloc + ); + + + if (isValid2) + { + btVector3 tmpNormalInB = tmpPointOnB-tmpPointOnA; + btScalar lenSqr = tmpNormalInB.length2(); + if (lenSqr <= (SIMD_EPSILON*SIMD_EPSILON)) + { + tmpNormalInB = m_cachedSeparatingAxis; + lenSqr = m_cachedSeparatingAxis.length2(); + } + + if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON)) + { + tmpNormalInB /= btSqrt(lenSqr); + btScalar distance2 = -(tmpPointOnA-tmpPointOnB).length(); + //only replace valid penetrations when the result is deeper (check) + if (!isValid || (distance2 < distance)) + { + distance = distance2; + pointOnA = tmpPointOnA; + pointOnB = tmpPointOnB; + normalInB = tmpNormalInB; + isValid = true; + m_lastUsedMethod = 3; + } else + { + m_lastUsedMethod = 8; + } + } else + { + m_lastUsedMethod = 9; + } + } else + + { + ///this is another degenerate case, where the initial GJK calculation reports a degenerate case + ///EPA reports no penetration, and the second GJK (using the supporting vector without margin) + ///reports a valid positive distance. Use the results of the second GJK instead of failing. + ///thanks to Jacob.Langford for the reproduction case + ///http://code.google.com/p/bullet/issues/detail?id=250 + + + if (m_cachedSeparatingAxis.length2() > btScalar(0.)) + { + btScalar distance2 = (tmpPointOnA-tmpPointOnB).length()-margin; + //only replace valid distances when the distance is less + if (!isValid || (distance2 < distance)) + { + distance = distance2; + pointOnA = tmpPointOnA; + pointOnB = tmpPointOnB; + pointOnA -= m_cachedSeparatingAxis * marginA ; + pointOnB += m_cachedSeparatingAxis * marginB ; + normalInB = m_cachedSeparatingAxis; + normalInB.normalize(); + isValid = true; + m_lastUsedMethod = 6; + } else + { + m_lastUsedMethod = 5; + } + } + } + + } + + } + } + + + + if (isValid && ((distance < 0) || (distance*distance < input.m_maximumDistanceSquared))) + { +#if 0 +///some debugging +// if (check2d) + { + printf("n = %2.3f,%2.3f,%2.3f. ",normalInB[0],normalInB[1],normalInB[2]); + printf("distance = %2.3f exit=%d deg=%d\n",distance,m_lastUsedMethod,m_degenerateSimplex); + } +#endif + + m_cachedSeparatingAxis = normalInB; + m_cachedSeparatingDistance = distance; + + output.addContactPoint( + normalInB, + pointOnB+positionOffset, + distance); + + } + + +} + + + + + diff --git a/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h new file mode 100644 index 0000000..2277a19 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h @@ -0,0 +1,103 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + + +#ifndef BT_GJK_PAIR_DETECTOR_H +#define BT_GJK_PAIR_DETECTOR_H + +#include "btDiscreteCollisionDetectorInterface.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + +class btConvexShape; +#include "btSimplexSolverInterface.h" +class btConvexPenetrationDepthSolver; + +/// btGjkPairDetector uses GJK to implement the btDiscreteCollisionDetectorInterface +class btGjkPairDetector : public btDiscreteCollisionDetectorInterface +{ + + + btVector3 m_cachedSeparatingAxis; + btConvexPenetrationDepthSolver* m_penetrationDepthSolver; + btSimplexSolverInterface* m_simplexSolver; + const btConvexShape* m_minkowskiA; + const btConvexShape* m_minkowskiB; + int m_shapeTypeA; + int m_shapeTypeB; + btScalar m_marginA; + btScalar m_marginB; + + bool m_ignoreMargin; + btScalar m_cachedSeparatingDistance; + + +public: + + //some debugging to fix degeneracy problems + int m_lastUsedMethod; + int m_curIter; + int m_degenerateSimplex; + int m_catchDegeneracies; + + + btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); + btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,int shapeTypeA,int shapeTypeB,btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); + virtual ~btGjkPairDetector() {}; + + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false); + + void getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw); + + + void setMinkowskiA(btConvexShape* minkA) + { + m_minkowskiA = minkA; + } + + void setMinkowskiB(btConvexShape* minkB) + { + m_minkowskiB = minkB; + } + void setCachedSeperatingAxis(const btVector3& seperatingAxis) + { + m_cachedSeparatingAxis = seperatingAxis; + } + + const btVector3& getCachedSeparatingAxis() const + { + return m_cachedSeparatingAxis; + } + btScalar getCachedSeparatingDistance() const + { + return m_cachedSeparatingDistance; + } + + void setPenetrationDepthSolver(btConvexPenetrationDepthSolver* penetrationDepthSolver) + { + m_penetrationDepthSolver = penetrationDepthSolver; + } + + ///don't use setIgnoreMargin, it's for Bullet's internal use + void setIgnoreMargin(bool ignoreMargin) + { + m_ignoreMargin = ignoreMargin; + } + + +}; + +#endif //BT_GJK_PAIR_DETECTOR_H diff --git a/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h new file mode 100644 index 0000000..0ce9dd2 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h @@ -0,0 +1,158 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_MANIFOLD_CONTACT_POINT_H +#define BT_MANIFOLD_CONTACT_POINT_H + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransformUtil.h" + +#ifdef PFX_USE_FREE_VECTORMATH + #include "physics_effects/base_level/solver/pfx_constraint_row.h" +typedef sce::PhysicsEffects::PfxConstraintRow btConstraintRow; +#else + // Don't change following order of parameters + ATTRIBUTE_ALIGNED16(struct) btConstraintRow { + btScalar m_normal[3]; + btScalar m_rhs; + btScalar m_jacDiagInv; + btScalar m_lowerLimit; + btScalar m_upperLimit; + btScalar m_accumImpulse; + }; + typedef btConstraintRow PfxConstraintRow; +#endif //PFX_USE_FREE_VECTORMATH + + + +/// ManifoldContactPoint collects and maintains persistent contactpoints. +/// used to improve stability and performance of rigidbody dynamics response. +class btManifoldPoint + { + public: + btManifoldPoint() + :m_userPersistentData(0), + m_appliedImpulse(0.f), + m_lateralFrictionInitialized(false), + m_appliedImpulseLateral1(0.f), + m_appliedImpulseLateral2(0.f), + m_contactMotion1(0.f), + m_contactMotion2(0.f), + m_contactCFM1(0.f), + m_contactCFM2(0.f), + m_lifeTime(0) + { + } + + btManifoldPoint( const btVector3 &pointA, const btVector3 &pointB, + const btVector3 &normal, + btScalar distance ) : + m_localPointA( pointA ), + m_localPointB( pointB ), + m_normalWorldOnB( normal ), + m_distance1( distance ), + m_combinedFriction(btScalar(0.)), + m_combinedRestitution(btScalar(0.)), + m_userPersistentData(0), + m_appliedImpulse(0.f), + m_lateralFrictionInitialized(false), + m_appliedImpulseLateral1(0.f), + m_appliedImpulseLateral2(0.f), + m_contactMotion1(0.f), + m_contactMotion2(0.f), + m_contactCFM1(0.f), + m_contactCFM2(0.f), + m_lifeTime(0) + { + mConstraintRow[0].m_accumImpulse = 0.f; + mConstraintRow[1].m_accumImpulse = 0.f; + mConstraintRow[2].m_accumImpulse = 0.f; + } + + + + btVector3 m_localPointA; + btVector3 m_localPointB; + btVector3 m_positionWorldOnB; + ///m_positionWorldOnA is redundant information, see getPositionWorldOnA(), but for clarity + btVector3 m_positionWorldOnA; + btVector3 m_normalWorldOnB; + + btScalar m_distance1; + btScalar m_combinedFriction; + btScalar m_combinedRestitution; + + //BP mod, store contact triangles. + int m_partId0; + int m_partId1; + int m_index0; + int m_index1; + + mutable void* m_userPersistentData; + btScalar m_appliedImpulse; + + bool m_lateralFrictionInitialized; + btScalar m_appliedImpulseLateral1; + btScalar m_appliedImpulseLateral2; + btScalar m_contactMotion1; + btScalar m_contactMotion2; + btScalar m_contactCFM1; + btScalar m_contactCFM2; + + int m_lifeTime;//lifetime of the contactpoint in frames + + btVector3 m_lateralFrictionDir1; + btVector3 m_lateralFrictionDir2; + + + + btConstraintRow mConstraintRow[3]; + + + btScalar getDistance() const + { + return m_distance1; + } + int getLifeTime() const + { + return m_lifeTime; + } + + const btVector3& getPositionWorldOnA() const { + return m_positionWorldOnA; +// return m_positionWorldOnB + m_normalWorldOnB * m_distance1; + } + + const btVector3& getPositionWorldOnB() const + { + return m_positionWorldOnB; + } + + void setDistance(btScalar dist) + { + m_distance1 = dist; + } + + ///this returns the most recent applied impulse, to satisfy contact constraints by the constraint solver + btScalar getAppliedImpulse() const + { + return m_appliedImpulse; + } + + + + }; + +#endif //BT_MANIFOLD_CONTACT_POINT_H diff --git a/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp b/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp new file mode 100644 index 0000000..fe31f08 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp @@ -0,0 +1,362 @@ +/* +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 "btMinkowskiPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" + +#define NUM_UNITSPHERE_POINTS 42 + + +bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver, + const btConvexShape* convexA,const btConvexShape* convexB, + const btTransform& transA,const btTransform& transB, + btVector3& v, btVector3& pa, btVector3& pb, + class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc + ) +{ + + (void)stackAlloc; + (void)v; + + bool check2d= convexA->isConvex2d() && convexB->isConvex2d(); + + struct btIntermediateResult : public btDiscreteCollisionDetectorInterface::Result + { + + btIntermediateResult():m_hasResult(false) + { + } + + btVector3 m_normalOnBInWorld; + btVector3 m_pointInWorld; + btScalar m_depth; + bool m_hasResult; + + virtual void setShapeIdentifiersA(int partId0,int index0) + { + (void)partId0; + (void)index0; + } + virtual void setShapeIdentifiersB(int partId1,int index1) + { + (void)partId1; + (void)index1; + } + void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) + { + m_normalOnBInWorld = normalOnBInWorld; + m_pointInWorld = pointInWorld; + m_depth = depth; + m_hasResult = true; + } + }; + + //just take fixed number of orientation, and sample the penetration depth in that direction + btScalar minProj = btScalar(BT_LARGE_FLOAT); + btVector3 minNorm(btScalar(0.), btScalar(0.), btScalar(0.)); + btVector3 minA,minB; + btVector3 seperatingAxisInA,seperatingAxisInB; + btVector3 pInA,qInB,pWorld,qWorld,w; + +#ifndef __SPU__ +#define USE_BATCHED_SUPPORT 1 +#endif +#ifdef USE_BATCHED_SUPPORT + + btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + btVector3 seperatingAxisInABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + btVector3 seperatingAxisInBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + int i; + + int numSampleDirections = NUM_UNITSPHERE_POINTS; + + for (i=0;igetNumPreferredPenetrationDirections(); + if (numPDA) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + norm = transA.getBasis() * norm; + getPenetrationDirections()[numSampleDirections] = norm; + seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis(); + seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis(); + numSampleDirections++; + } + } + } + + { + int numPDB = convexB->getNumPreferredPenetrationDirections(); + if (numPDB) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + norm = transB.getBasis() * norm; + getPenetrationDirections()[numSampleDirections] = norm; + seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis(); + seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis(); + numSampleDirections++; + } + } + } + + + + + convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch,supportVerticesABatch,numSampleDirections); + convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch,supportVerticesBBatch,numSampleDirections); + + for (i=0;i0.01) + { + + seperatingAxisInA = seperatingAxisInABatch[i]; + seperatingAxisInB = seperatingAxisInBBatch[i]; + + pInA = supportVerticesABatch[i]; + qInB = supportVerticesBBatch[i]; + + pWorld = transA(pInA); + qWorld = transB(qInB); + if (check2d) + { + pWorld[2] = 0.f; + qWorld[2] = 0.f; + } + + w = qWorld - pWorld; + btScalar delta = norm.dot(w); + //find smallest delta + if (delta < minProj) + { + minProj = delta; + minNorm = norm; + minA = pWorld; + minB = qWorld; + } + } + } +#else + + int numSampleDirections = NUM_UNITSPHERE_POINTS; + +#ifndef __SPU__ + { + int numPDA = convexA->getNumPreferredPenetrationDirections(); + if (numPDA) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + norm = transA.getBasis() * norm; + getPenetrationDirections()[numSampleDirections] = norm; + numSampleDirections++; + } + } + } + + { + int numPDB = convexB->getNumPreferredPenetrationDirections(); + if (numPDB) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + norm = transB.getBasis() * norm; + getPenetrationDirections()[numSampleDirections] = norm; + numSampleDirections++; + } + } + } +#endif // __SPU__ + + for (int i=0;ilocalGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA); + qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB); + pWorld = transA(pInA); + qWorld = transB(qInB); + w = qWorld - pWorld; + btScalar delta = norm.dot(w); + //find smallest delta + if (delta < minProj) + { + minProj = delta; + minNorm = norm; + minA = pWorld; + minB = qWorld; + } + } +#endif //USE_BATCHED_SUPPORT + + //add the margins + + minA += minNorm*convexA->getMarginNonVirtual(); + minB -= minNorm*convexB->getMarginNonVirtual(); + //no penetration + if (minProj < btScalar(0.)) + return false; + + btScalar extraSeparation = 0.5f;///scale dependent + minProj += extraSeparation+(convexA->getMarginNonVirtual() + convexB->getMarginNonVirtual()); + + + + + +//#define DEBUG_DRAW 1 +#ifdef DEBUG_DRAW + if (debugDraw) + { + btVector3 color(0,1,0); + debugDraw->drawLine(minA,minB,color); + color = btVector3 (1,1,1); + btVector3 vec = minB-minA; + btScalar prj2 = minNorm.dot(vec); + debugDraw->drawLine(minA,minA+(minNorm*minProj),color); + + } +#endif //DEBUG_DRAW + + + + btGjkPairDetector gjkdet(convexA,convexB,&simplexSolver,0); + + btScalar offsetDist = minProj; + btVector3 offset = minNorm * offsetDist; + + + + btGjkPairDetector::ClosestPointInput input; + + btVector3 newOrg = transA.getOrigin() + offset; + + btTransform displacedTrans = transA; + displacedTrans.setOrigin(newOrg); + + input.m_transformA = displacedTrans; + input.m_transformB = transB; + input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);//minProj; + + btIntermediateResult res; + gjkdet.setCachedSeperatingAxis(-minNorm); + gjkdet.getClosestPoints(input,res,debugDraw); + + btScalar correctedMinNorm = minProj - res.m_depth; + + + //the penetration depth is over-estimated, relax it + btScalar penetration_relaxation= btScalar(1.); + minNorm*=penetration_relaxation; + + + if (res.m_hasResult) + { + + pa = res.m_pointInWorld - minNorm * correctedMinNorm; + pb = res.m_pointInWorld; + v = minNorm; + +#ifdef DEBUG_DRAW + if (debugDraw) + { + btVector3 color(1,0,0); + debugDraw->drawLine(pa,pb,color); + } +#endif//DEBUG_DRAW + + + } + return res.m_hasResult; +} + +btVector3* btMinkowskiPenetrationDepthSolver::getPenetrationDirections() +{ + static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = + { + btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)), + btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)), + btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)), + btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)), + btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)), + btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)), + btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)), + btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)), + btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)), + btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)), + btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)), + btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)), + btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)), + btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)), + btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)), + btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)), + btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)), + btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)), + btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)), + btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)), + btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)), + btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)), + btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)), + btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)), + btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)), + btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)), + btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)), + btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)), + btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)), + btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)), + btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)), + btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)), + btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)), + btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)), + btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)), + btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)), + btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)), + btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)), + btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)), + btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)), + btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)), + btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654)) + }; + + return sPenetrationDirections; +} + + diff --git a/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h b/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h new file mode 100644 index 0000000..6a8fe52 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h @@ -0,0 +1,40 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H +#define BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H + +#include "btConvexPenetrationDepthSolver.h" + +///MinkowskiPenetrationDepthSolver implements bruteforce penetration depth estimation. +///Implementation is based on sampling the depth using support mapping, and using GJK step to get the witness points. +class btMinkowskiPenetrationDepthSolver : public btConvexPenetrationDepthSolver +{ +protected: + + static btVector3* getPenetrationDirections(); + +public: + + virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, + const btConvexShape* convexA,const btConvexShape* convexB, + const btTransform& transA,const btTransform& transB, + btVector3& v, btVector3& pa, btVector3& pb, + class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc + ); +}; + +#endif //BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H + diff --git a/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp new file mode 100644 index 0000000..954b839 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp @@ -0,0 +1,302 @@ +/* +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 "btPersistentManifold.h" +#include "LinearMath/btTransform.h" + + +btScalar gContactBreakingThreshold = btScalar(0.02); +ContactDestroyedCallback gContactDestroyedCallback = 0; +ContactProcessedCallback gContactProcessedCallback = 0; +///gContactCalcArea3Points will approximate the convex hull area using 3 points +///when setting it to false, it will use 4 points to compute the area: it is more accurate but slower +bool gContactCalcArea3Points = true; + + +btPersistentManifold::btPersistentManifold() +:btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE), +m_body0(0), +m_body1(0), +m_cachedPoints (0), +m_index1a(0) +{ +} + + + + +#ifdef DEBUG_PERSISTENCY +#include +void btPersistentManifold::DebugPersistency() +{ + int i; + printf("DebugPersistency : numPoints %d\n",m_cachedPoints); + for (i=0;i1) + printf("error in clearUserCache\n"); + } + } + btAssert(occurance<=0); +#endif //DEBUG_PERSISTENCY + + if (pt.m_userPersistentData && gContactDestroyedCallback) + { + (*gContactDestroyedCallback)(pt.m_userPersistentData); + pt.m_userPersistentData = 0; + } + +#ifdef DEBUG_PERSISTENCY + DebugPersistency(); +#endif + } + + +} + +static inline btScalar calcArea4Points(const btVector3 &p0,const btVector3 &p1,const btVector3 &p2,const btVector3 &p3) +{ + // It calculates possible 3 area constructed from random 4 points and returns the biggest one. + + btVector3 a[3],b[3]; + a[0] = p0 - p1; + a[1] = p0 - p2; + a[2] = p0 - p3; + b[0] = p2 - p3; + b[1] = p1 - p3; + b[2] = p1 - p2; + + //todo: Following 3 cross production can be easily optimized by SIMD. + btVector3 tmp0 = a[0].cross(b[0]); + btVector3 tmp1 = a[1].cross(b[1]); + btVector3 tmp2 = a[2].cross(b[2]); + + return btMax(btMax(tmp0.length2(),tmp1.length2()),tmp2.length2()); +} + +int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt) +{ + //calculate 4 possible cases areas, and take biggest area + //also need to keep 'deepest' + + int maxPenetrationIndex = -1; +#define KEEP_DEEPEST_POINT 1 +#ifdef KEEP_DEEPEST_POINT + btScalar maxPenetration = pt.getDistance(); + for (int i=0;i<4;i++) + { + if (m_pointCache[i].getDistance() < maxPenetration) + { + maxPenetrationIndex = i; + maxPenetration = m_pointCache[i].getDistance(); + } + } +#endif //KEEP_DEEPEST_POINT + + btScalar res0(btScalar(0.)),res1(btScalar(0.)),res2(btScalar(0.)),res3(btScalar(0.)); + + if (gContactCalcArea3Points) + { + if (maxPenetrationIndex != 0) + { + btVector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA; + btVector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA; + btVector3 cross = a0.cross(b0); + res0 = cross.length2(); + } + if (maxPenetrationIndex != 1) + { + btVector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA; + btVector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA; + btVector3 cross = a1.cross(b1); + res1 = cross.length2(); + } + + if (maxPenetrationIndex != 2) + { + btVector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA; + btVector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA; + btVector3 cross = a2.cross(b2); + res2 = cross.length2(); + } + + if (maxPenetrationIndex != 3) + { + btVector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA; + btVector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA; + btVector3 cross = a3.cross(b3); + res3 = cross.length2(); + } + } + else + { + if(maxPenetrationIndex != 0) { + res0 = calcArea4Points(pt.m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA); + } + + if(maxPenetrationIndex != 1) { + res1 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA); + } + + if(maxPenetrationIndex != 2) { + res2 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[3].m_localPointA); + } + + if(maxPenetrationIndex != 3) { + res3 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA); + } + } + btVector4 maxvec(res0,res1,res2,res3); + int biggestarea = maxvec.closestAxis4(); + return biggestarea; + +} + + +int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const +{ + btScalar shortestDist = getContactBreakingThreshold() * getContactBreakingThreshold(); + int size = getNumContacts(); + int nearestPoint = -1; + for( int i = 0; i < size; i++ ) + { + const btManifoldPoint &mp = m_pointCache[i]; + + btVector3 diffA = mp.m_localPointA- newPoint.m_localPointA; + const btScalar distToManiPoint = diffA.dot(diffA); + if( distToManiPoint < shortestDist ) + { + shortestDist = distToManiPoint; + nearestPoint = i; + } + } + return nearestPoint; +} + +int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint) +{ + btAssert(validContactDistance(newPoint)); + + int insertIndex = getNumContacts(); + if (insertIndex == MANIFOLD_CACHE_SIZE) + { +#if MANIFOLD_CACHE_SIZE >= 4 + //sort cache so best points come first, based on area + insertIndex = sortCachedPoints(newPoint); +#else + insertIndex = 0; +#endif + clearUserCache(m_pointCache[insertIndex]); + + } else + { + m_cachedPoints++; + + + } + if (insertIndex<0) + insertIndex=0; + + btAssert(m_pointCache[insertIndex].m_userPersistentData==0); + m_pointCache[insertIndex] = newPoint; + return insertIndex; +} + +btScalar btPersistentManifold::getContactBreakingThreshold() const +{ + return m_contactBreakingThreshold; +} + + + +void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB) +{ + int i; +#ifdef DEBUG_PERSISTENCY + printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n", + trA.getOrigin().getX(), + trA.getOrigin().getY(), + trA.getOrigin().getZ(), + trB.getOrigin().getX(), + trB.getOrigin().getY(), + trB.getOrigin().getZ()); +#endif //DEBUG_PERSISTENCY + /// first refresh worldspace positions and distance + for (i=getNumContacts()-1;i>=0;i--) + { + btManifoldPoint &manifoldPoint = m_pointCache[i]; + manifoldPoint.m_positionWorldOnA = trA( manifoldPoint.m_localPointA ); + manifoldPoint.m_positionWorldOnB = trB( manifoldPoint.m_localPointB ); + manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB); + manifoldPoint.m_lifeTime++; + } + + /// then + btScalar distance2d; + btVector3 projectedDifference,projectedPoint; + for (i=getNumContacts()-1;i>=0;i--) + { + + btManifoldPoint &manifoldPoint = m_pointCache[i]; + //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction) + if (!validContactDistance(manifoldPoint)) + { + removeContactPoint(i); + } else + { + //contact also becomes invalid when relative movement orthogonal to normal exceeds margin + projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1; + projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint; + distance2d = projectedDifference.dot(projectedDifference); + if (distance2d > getContactBreakingThreshold()*getContactBreakingThreshold() ) + { + removeContactPoint(i); + } else + { + //contact point processed callback + if (gContactProcessedCallback) + (*gContactProcessedCallback)(manifoldPoint,m_body0,m_body1); + } + } + } +#ifdef DEBUG_PERSISTENCY + DebugPersistency(); +#endif // +} + + + + + diff --git a/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h new file mode 100644 index 0000000..d877f09 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h @@ -0,0 +1,228 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_PERSISTENT_MANIFOLD_H +#define BT_PERSISTENT_MANIFOLD_H + + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "btManifoldPoint.h" +#include "LinearMath/btAlignedAllocator.h" + +struct btCollisionResult; + +///maximum contact breaking and merging threshold +extern btScalar gContactBreakingThreshold; + +typedef bool (*ContactDestroyedCallback)(void* userPersistentData); +typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp,void* body0,void* body1); +extern ContactDestroyedCallback gContactDestroyedCallback; +extern ContactProcessedCallback gContactProcessedCallback; + +//the enum starts at 1024 to avoid type conflicts with btTypedConstraint +enum btContactManifoldTypes +{ + MIN_CONTACT_MANIFOLD_TYPE = 1024, + BT_PERSISTENT_MANIFOLD_TYPE +}; + +#define MANIFOLD_CACHE_SIZE 4 + +///btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase. +///Those contact points are created by the collision narrow phase. +///The cache can be empty, or hold 1,2,3 or 4 points. Some collision algorithms (GJK) might only add one point at a time. +///updates/refreshes old contact points, and throw them away if necessary (distance becomes too large) +///reduces the cache to 4 points, when more then 4 points are added, using following rules: +///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points +///note that some pairs of objects might have more then one contact manifold. + + +ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject +//ATTRIBUTE_ALIGNED16( class) btPersistentManifold : public btTypedObject +{ + + btManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE]; + + /// this two body pointers can point to the physics rigidbody class. + /// void* will allow any rigidbody class + void* m_body0; + void* m_body1; + + int m_cachedPoints; + + btScalar m_contactBreakingThreshold; + btScalar m_contactProcessingThreshold; + + + /// sort cached points so most isolated points come first + int sortCachedPoints(const btManifoldPoint& pt); + + int findContactPoint(const btManifoldPoint* unUsed, int numUnused,const btManifoldPoint& pt); + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + int m_companionIdA; + int m_companionIdB; + + int m_index1a; + + btPersistentManifold(); + + btPersistentManifold(void* body0,void* body1,int , btScalar contactBreakingThreshold,btScalar contactProcessingThreshold) + : btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE), + m_body0(body0),m_body1(body1),m_cachedPoints(0), + m_contactBreakingThreshold(contactBreakingThreshold), + m_contactProcessingThreshold(contactProcessingThreshold) + { + } + + SIMD_FORCE_INLINE void* getBody0() { return m_body0;} + SIMD_FORCE_INLINE void* getBody1() { return m_body1;} + + SIMD_FORCE_INLINE const void* getBody0() const { return m_body0;} + SIMD_FORCE_INLINE const void* getBody1() const { return m_body1;} + + void setBodies(void* body0,void* body1) + { + m_body0 = body0; + m_body1 = body1; + } + + void clearUserCache(btManifoldPoint& pt); + +#ifdef DEBUG_PERSISTENCY + void DebugPersistency(); +#endif // + + SIMD_FORCE_INLINE int getNumContacts() const { return m_cachedPoints;} + + SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const + { + btAssert(index < m_cachedPoints); + return m_pointCache[index]; + } + + SIMD_FORCE_INLINE btManifoldPoint& getContactPoint(int index) + { + btAssert(index < m_cachedPoints); + return m_pointCache[index]; + } + + ///@todo: get this margin from the current physics / collision environment + btScalar getContactBreakingThreshold() const; + + btScalar getContactProcessingThreshold() const + { + return m_contactProcessingThreshold; + } + + int getCacheEntry(const btManifoldPoint& newPoint) const; + + int addManifoldPoint( const btManifoldPoint& newPoint); + + void removeContactPoint (int index) + { + clearUserCache(m_pointCache[index]); + + int lastUsedIndex = getNumContacts() - 1; +// m_pointCache[index] = m_pointCache[lastUsedIndex]; + if(index != lastUsedIndex) + { + m_pointCache[index] = m_pointCache[lastUsedIndex]; + //get rid of duplicated userPersistentData pointer + m_pointCache[lastUsedIndex].m_userPersistentData = 0; + m_pointCache[lastUsedIndex].mConstraintRow[0].m_accumImpulse = 0.f; + m_pointCache[lastUsedIndex].mConstraintRow[1].m_accumImpulse = 0.f; + m_pointCache[lastUsedIndex].mConstraintRow[2].m_accumImpulse = 0.f; + + m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f; + m_pointCache[lastUsedIndex].m_lateralFrictionInitialized = false; + m_pointCache[lastUsedIndex].m_appliedImpulseLateral1 = 0.f; + m_pointCache[lastUsedIndex].m_appliedImpulseLateral2 = 0.f; + m_pointCache[lastUsedIndex].m_lifeTime = 0; + } + + btAssert(m_pointCache[lastUsedIndex].m_userPersistentData==0); + m_cachedPoints--; + } + void replaceContactPoint(const btManifoldPoint& newPoint,int insertIndex) + { + btAssert(validContactDistance(newPoint)); + +#define MAINTAIN_PERSISTENCY 1 +#ifdef MAINTAIN_PERSISTENCY + int lifeTime = m_pointCache[insertIndex].getLifeTime(); + btScalar appliedImpulse = m_pointCache[insertIndex].mConstraintRow[0].m_accumImpulse; + btScalar appliedLateralImpulse1 = m_pointCache[insertIndex].mConstraintRow[1].m_accumImpulse; + btScalar appliedLateralImpulse2 = m_pointCache[insertIndex].mConstraintRow[2].m_accumImpulse; +// bool isLateralFrictionInitialized = m_pointCache[insertIndex].m_lateralFrictionInitialized; + + + + btAssert(lifeTime>=0); + void* cache = m_pointCache[insertIndex].m_userPersistentData; + + m_pointCache[insertIndex] = newPoint; + + m_pointCache[insertIndex].m_userPersistentData = cache; + m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse; + m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1; + m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2; + + m_pointCache[insertIndex].mConstraintRow[0].m_accumImpulse = appliedImpulse; + m_pointCache[insertIndex].mConstraintRow[1].m_accumImpulse = appliedLateralImpulse1; + m_pointCache[insertIndex].mConstraintRow[2].m_accumImpulse = appliedLateralImpulse2; + + + m_pointCache[insertIndex].m_lifeTime = lifeTime; +#else + clearUserCache(m_pointCache[insertIndex]); + m_pointCache[insertIndex] = newPoint; + +#endif + } + + + bool validContactDistance(const btManifoldPoint& pt) const + { + return pt.m_distance1 <= getContactBreakingThreshold(); + } + /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin + void refreshContactPoints( const btTransform& trA,const btTransform& trB); + + + SIMD_FORCE_INLINE void clearManifold() + { + int i; + for (i=0;i //for FLT_MAX + +int gExpectedNbTests=0; +int gActualNbTests = 0; +bool gUseInternalObject = true; + +// Clips a face to the back of a plane +void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS,btScalar planeEqWS) +{ + + int ve; + btScalar ds, de; + int numVerts = pVtxIn.size(); + if (numVerts < 2) + return; + + btVector3 firstVertex=pVtxIn[pVtxIn.size()-1]; + btVector3 endVertex = pVtxIn[0]; + + ds = planeNormalWS.dot(firstVertex)+planeEqWS; + + for (ve = 0; ve < numVerts; ve++) + { + endVertex=pVtxIn[ve]; + + de = planeNormalWS.dot(endVertex)+planeEqWS; + + if (ds<0) + { + if (de<0) + { + // Start < 0, end < 0, so output endVertex + ppVtxOut.push_back(endVertex); + } + else + { + // Start < 0, end >= 0, so output intersection + ppVtxOut.push_back( firstVertex.lerp(endVertex,btScalar(ds * 1.f/(ds - de)))); + } + } + else + { + if (de<0) + { + // Start >= 0, end < 0 so output intersection and end + ppVtxOut.push_back(firstVertex.lerp(endVertex,btScalar(ds * 1.f/(ds - de)))); + ppVtxOut.push_back(endVertex); + } + } + firstVertex = endVertex; + ds = de; + } +} + + +static bool TestSepAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btVector3& sep_axis, btScalar& depth) +{ + btScalar Min0,Max0; + btScalar Min1,Max1; + hullA.project(transA,sep_axis, Min0, Max0); + hullB.project(transB, sep_axis, Min1, Max1); + + if(Max0=0.0f); + btScalar d1 = Max1 - Min0; + assert(d1>=0.0f); + depth = d01e-6 || fabsf(v.y())>1e-6 || fabsf(v.z())>1e-6) return false; + return true; +} + +#ifdef TEST_INTERNAL_OBJECTS + +inline void BoxSupport(const btScalar extents[3], const btScalar sv[3], btScalar p[3]) +{ + // This version is ~11.000 cycles (4%) faster overall in one of the tests. +// IR(p[0]) = IR(extents[0])|(IR(sv[0])&SIGN_BITMASK); +// IR(p[1]) = IR(extents[1])|(IR(sv[1])&SIGN_BITMASK); +// IR(p[2]) = IR(extents[2])|(IR(sv[2])&SIGN_BITMASK); + p[0] = sv[0] < 0.0f ? -extents[0] : extents[0]; + p[1] = sv[1] < 0.0f ? -extents[1] : extents[1]; + p[2] = sv[2] < 0.0f ? -extents[2] : extents[2]; +} + +void InverseTransformPoint3x3(btVector3& out, const btVector3& in, const btTransform& tr) +{ + const btMatrix3x3& rot = tr.getBasis(); + const btVector3& r0 = rot[0]; + const btVector3& r1 = rot[1]; + const btVector3& r2 = rot[2]; + + const btScalar x = r0.x()*in.x() + r1.x()*in.y() + r2.x()*in.z(); + const btScalar y = r0.y()*in.x() + r1.y()*in.y() + r2.y()*in.z(); + const btScalar z = r0.z()*in.x() + r1.z()*in.y() + r2.z()*in.z(); + + out.setValue(x, y, z); +} + + bool TestInternalObjects( const btTransform& trans0, const btTransform& trans1, const btVector3& delta_c, const btVector3& axis, const btConvexPolyhedron& convex0, const btConvexPolyhedron& convex1, btScalar dmin) +{ + const btScalar dp = delta_c.dot(axis); + + btVector3 localAxis0; + InverseTransformPoint3x3(localAxis0, axis,trans0); + btVector3 localAxis1; + InverseTransformPoint3x3(localAxis1, axis,trans1); + + btScalar p0[3]; + BoxSupport(convex0.m_extents, localAxis0, p0); + btScalar p1[3]; + BoxSupport(convex1.m_extents, localAxis1, p1); + + const btScalar Radius0 = p0[0]*localAxis0.x() + p0[1]*localAxis0.y() + p0[2]*localAxis0.z(); + const btScalar Radius1 = p1[0]*localAxis1.x() + p1[1]*localAxis1.y() + p1[2]*localAxis1.z(); + + const btScalar MinRadius = Radius0>convex0.m_radius ? Radius0 : convex0.m_radius; + const btScalar MaxRadius = Radius1>convex1.m_radius ? Radius1 : convex1.m_radius; + + const btScalar MinMaxRadius = MaxRadius + MinRadius; + const btScalar d0 = MinMaxRadius + dp; + const btScalar d1 = MinMaxRadius - dp; + + const btScalar depth = d0dmin) + return false; + return true; +} +#endif //TEST_INTERNAL_OBJECTS + + +bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep) +{ + gActualSATPairTests++; + +//#ifdef TEST_INTERNAL_OBJECTS + const btVector3 c0 = transA * hullA.m_localCenter; + const btVector3 c1 = transB * hullB.m_localCenter; + const btVector3 DeltaC2 = c0 - c1; +//#endif + + btScalar dmin = FLT_MAX; + int curPlaneTests=0; + + int numFacesA = hullA.m_faces.size(); + // Test normals from hullA + for(int i=0;i0.0f) + sep = -sep; + + return true; +} + +void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut) +{ + btVertexArray worldVertsB2; + btVertexArray* pVtxIn = &worldVertsB1; + btVertexArray* pVtxOut = &worldVertsB2; + pVtxOut->reserve(pVtxIn->size()); + + int closestFaceA=-1; + { + btScalar dmin = FLT_MAX; + for(int face=0;facesize(); + int numVerticesA = polyA.m_indices.size(); + for(int e0=0;e0resize(0); + } + + + +//#define ONLY_REPORT_DEEPEST_POINT + + btVector3 point; + + + // only keep points that are behind the witness face + { + btVector3 localPlaneNormal (polyA.m_plane[0],polyA.m_plane[1],polyA.m_plane[2]); + btScalar localPlaneEq = polyA.m_plane[3]; + btVector3 planeNormalWS = transA.getBasis()*localPlaneNormal; + btScalar planeEqWS=localPlaneEq-planeNormalWS.dot(transA.getOrigin()); + for (int i=0;isize();i++) + { + + btScalar depth = planeNormalWS.dot(pVtxIn->at(i))+planeEqWS; + if (depth <=minDist) + { +// printf("clamped: depth=%f to minDist=%f\n",depth,minDist); + depth = minDist; + } + + if (depth <=maxDist) + { + btVector3 point = pVtxIn->at(i); +#ifdef ONLY_REPORT_DEEPEST_POINT + curMaxDist = depth; +#else +#if 0 + if (depth<-3) + { + printf("error in btPolyhedralContactClipping depth = %f\n", depth); + printf("likely wrong separatingNormal passed in\n"); + } +#endif + resultOut.addContactPoint(separatingNormal,point,depth); +#endif + } + } + } +#ifdef ONLY_REPORT_DEEPEST_POINT + if (curMaxDist dmax) + { + dmax = d; + closestFaceB = face; + } + } + } + btVertexArray worldVertsB1; + { + const btFace& polyB = hullB.m_faces[closestFaceB]; + const int numVertices = polyB.m_indices.size(); + for(int e0=0;e0=0) + clipFaceAgainstHull(separatingNormal, hullA, transA,worldVertsB1, minDist, maxDist,resultOut); + +} diff --git a/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h b/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h new file mode 100644 index 0000000..7ab9c1e --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h @@ -0,0 +1,46 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +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. +*/ + + +///This file was written by Erwin Coumans + + +#ifndef BT_POLYHEDRAL_CONTACT_CLIPPING_H +#define BT_POLYHEDRAL_CONTACT_CLIPPING_H + + +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btTransform.h" +#include "btDiscreteCollisionDetectorInterface.h" + +class btConvexPolyhedron; + +typedef btAlignedObjectArray btVertexArray; + +// Clips a face to the back of a plane +struct btPolyhedralContactClipping +{ + static void clipHullAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist, btDiscreteCollisionDetectorInterface::Result& resultOut); + static void clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut); + + static bool findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep); + + ///the clipFace method is used internally + static void clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS,btScalar planeEqWS); + +}; + +#endif // BT_POLYHEDRAL_CONTACT_CLIPPING_H + diff --git a/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp b/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp new file mode 100644 index 0000000..fbe579c --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp @@ -0,0 +1,177 @@ +/* +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 + +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "btRaycastCallback.h" + +btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags) + : + m_from(from), + m_to(to), + //@BP Mod + m_flags(flags), + m_hitFraction(btScalar(1.)) +{ + +} + + + +void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) +{ + const btVector3 &vert0=triangle[0]; + const btVector3 &vert1=triangle[1]; + const btVector3 &vert2=triangle[2]; + + btVector3 v10; v10 = vert1 - vert0 ; + btVector3 v20; v20 = vert2 - vert0 ; + + btVector3 triangleNormal; triangleNormal = v10.cross( v20 ); + + const btScalar dist = vert0.dot(triangleNormal); + btScalar dist_a = triangleNormal.dot(m_from) ; + dist_a-= dist; + btScalar dist_b = triangleNormal.dot(m_to); + dist_b -= dist; + + if ( dist_a * dist_b >= btScalar(0.0) ) + { + return ; // same sign + } + //@BP Mod - Backface filtering + if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a > btScalar(0.0))) + { + // Backface, skip check + return; + } + + const btScalar proj_length=dist_a-dist_b; + const btScalar distance = (dist_a)/(proj_length); + // Now we have the intersection point on the plane, we'll see if it's inside the triangle + // Add an epsilon as a tolerance for the raycast, + // in case the ray hits exacly on the edge of the triangle. + // It must be scaled for the triangle size. + + if(distance < m_hitFraction) + { + + + btScalar edge_tolerance =triangleNormal.length2(); + edge_tolerance *= btScalar(-0.0001); + btVector3 point; point.setInterpolate3( m_from, m_to, distance); + { + btVector3 v0p; v0p = vert0 - point; + btVector3 v1p; v1p = vert1 - point; + btVector3 cp0; cp0 = v0p.cross( v1p ); + + if ( (btScalar)(cp0.dot(triangleNormal)) >=edge_tolerance) + { + + + btVector3 v2p; v2p = vert2 - point; + btVector3 cp1; + cp1 = v1p.cross( v2p); + if ( (btScalar)(cp1.dot(triangleNormal)) >=edge_tolerance) + { + btVector3 cp2; + cp2 = v2p.cross(v0p); + + if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance) + { + //@BP Mod + // Triangle normal isn't normalized + triangleNormal.normalize(); + + //@BP Mod - Allow for unflipped normal when raycasting against backfaces + if (((m_flags & kF_KeepUnflippedNormal) != 0) || (dist_a <= btScalar(0.0))) + { + m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex); + } + else + { + m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex); + } + } + } + } + } + } +} + + +btTriangleConvexcastCallback::btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin) +{ + m_convexShape = convexShape; + m_convexShapeFrom = convexShapeFrom; + m_convexShapeTo = convexShapeTo; + m_triangleToWorld = triangleToWorld; + m_hitFraction = 1.0f; + m_triangleCollisionMargin = triangleCollisionMargin; + m_allowedPenetration = 0.f; +} + +void +btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId, int triangleIndex) +{ + btTriangleShape triangleShape (triangle[0], triangle[1], triangle[2]); + triangleShape.setMargin(m_triangleCollisionMargin); + + btVoronoiSimplexSolver simplexSolver; + btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver; + +//#define USE_SUBSIMPLEX_CONVEX_CAST 1 +//if you reenable USE_SUBSIMPLEX_CONVEX_CAST see commented out code below +#ifdef USE_SUBSIMPLEX_CONVEX_CAST + btSubsimplexConvexCast convexCaster(m_convexShape, &triangleShape, &simplexSolver); +#else + //btGjkConvexCast convexCaster(m_convexShape,&triangleShape,&simplexSolver); + btContinuousConvexCollision convexCaster(m_convexShape,&triangleShape,&simplexSolver,&gjkEpaPenetrationSolver); +#endif //#USE_SUBSIMPLEX_CONVEX_CAST + + btConvexCast::CastResult castResult; + castResult.m_fraction = btScalar(1.); + castResult.m_allowedPenetration = m_allowedPenetration; + if (convexCaster.calcTimeOfImpact(m_convexShapeFrom,m_convexShapeTo,m_triangleToWorld, m_triangleToWorld, castResult)) + { + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) + { + if (castResult.m_fraction < m_hitFraction) + { +/* btContinuousConvexCast's normal is already in world space */ +/* +#ifdef USE_SUBSIMPLEX_CONVEX_CAST + //rotate normal into worldspace + castResult.m_normal = m_convexShapeFrom.getBasis() * castResult.m_normal; +#endif //USE_SUBSIMPLEX_CONVEX_CAST +*/ + castResult.m_normal.normalize(); + + reportHit (castResult.m_normal, + castResult.m_hitPoint, + castResult.m_fraction, + partId, + triangleIndex); + } + } + } +} diff --git a/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h new file mode 100644 index 0000000..f012889 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h @@ -0,0 +1,72 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_RAYCAST_TRI_CALLBACK_H +#define BT_RAYCAST_TRI_CALLBACK_H + +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "LinearMath/btTransform.h" +struct btBroadphaseProxy; +class btConvexShape; + +class btTriangleRaycastCallback: public btTriangleCallback +{ +public: + + //input + btVector3 m_from; + btVector3 m_to; + + //@BP Mod - allow backface filtering and unflipped normals + enum EFlags + { + kF_None = 0, + kF_FilterBackfaces = 1 << 0, + kF_KeepUnflippedNormal = 1 << 1, // Prevents returned face normal getting flipped when a ray hits a back-facing triangle + + kF_Terminator = 0xFFFFFFFF + }; + unsigned int m_flags; + + btScalar m_hitFraction; + + btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags=0); + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); + + virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) = 0; + +}; + +class btTriangleConvexcastCallback : public btTriangleCallback +{ +public: + const btConvexShape* m_convexShape; + btTransform m_convexShapeFrom; + btTransform m_convexShapeTo; + btTransform m_triangleToWorld; + btScalar m_hitFraction; + btScalar m_triangleCollisionMargin; + btScalar m_allowedPenetration; + + btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin); + + virtual void processTriangle (btVector3* triangle, int partId, int triangleIndex); + + virtual btScalar reportHit (const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex) = 0; +}; + +#endif //BT_RAYCAST_TRI_CALLBACK_H + diff --git a/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h b/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h new file mode 100644 index 0000000..da8a139 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h @@ -0,0 +1,63 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_SIMPLEX_SOLVER_INTERFACE_H +#define BT_SIMPLEX_SOLVER_INTERFACE_H + +#include "LinearMath/btVector3.h" + +#define NO_VIRTUAL_INTERFACE 1 +#ifdef NO_VIRTUAL_INTERFACE +#include "btVoronoiSimplexSolver.h" +#define btSimplexSolverInterface btVoronoiSimplexSolver +#else + +/// btSimplexSolverInterface can incrementally calculate distance between origin and up to 4 vertices +/// Used by GJK or Linear Casting. Can be implemented by the Johnson-algorithm or alternative approaches based on +/// voronoi regions or barycentric coordinates +class btSimplexSolverInterface +{ + public: + virtual ~btSimplexSolverInterface() {}; + + virtual void reset() = 0; + + virtual void addVertex(const btVector3& w, const btVector3& p, const btVector3& q) = 0; + + virtual bool closest(btVector3& v) = 0; + + virtual btScalar maxVertex() = 0; + + virtual bool fullSimplex() const = 0; + + virtual int getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const = 0; + + virtual bool inSimplex(const btVector3& w) = 0; + + virtual void backup_closest(btVector3& v) = 0; + + virtual bool emptySimplex() const = 0; + + virtual void compute_points(btVector3& p1, btVector3& p2) = 0; + + virtual int numVertices() const =0; + + +}; +#endif +#endif //BT_SIMPLEX_SOLVER_INTERFACE_H + diff --git a/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp b/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp new file mode 100644 index 0000000..18eb662 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp @@ -0,0 +1,160 @@ +/* +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 "btSubSimplexConvexCast.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" + +#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" +#include "btPointCollector.h" +#include "LinearMath/btTransformUtil.h" + +btSubsimplexConvexCast::btSubsimplexConvexCast (const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) +:m_simplexSolver(simplexSolver), +m_convexA(convexA),m_convexB(convexB) +{ +} + +///Typically the conservative advancement reaches solution in a few iterations, clip it to 32 for degenerate cases. +///See discussion about this here http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=565 +#ifdef BT_USE_DOUBLE_PRECISION +#define MAX_ITERATIONS 64 +#else +#define MAX_ITERATIONS 32 +#endif +bool btSubsimplexConvexCast::calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result) +{ + + m_simplexSolver->reset(); + + btVector3 linVelA,linVelB; + linVelA = toA.getOrigin()-fromA.getOrigin(); + linVelB = toB.getOrigin()-fromB.getOrigin(); + + btScalar lambda = btScalar(0.); + + btTransform interpolatedTransA = fromA; + btTransform interpolatedTransB = fromB; + + ///take relative motion + btVector3 r = (linVelA-linVelB); + btVector3 v; + + btVector3 supVertexA = fromA(m_convexA->localGetSupportingVertex(-r*fromA.getBasis())); + btVector3 supVertexB = fromB(m_convexB->localGetSupportingVertex(r*fromB.getBasis())); + v = supVertexA-supVertexB; + int maxIter = MAX_ITERATIONS; + + btVector3 n; + n.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + bool hasResult = false; + btVector3 c; + + btScalar lastLambda = lambda; + + + btScalar dist2 = v.length2(); +#ifdef BT_USE_DOUBLE_PRECISION + btScalar epsilon = btScalar(0.0001); +#else + btScalar epsilon = btScalar(0.0001); +#endif //BT_USE_DOUBLE_PRECISION + btVector3 w,p; + btScalar VdotR; + + while ( (dist2 > epsilon) && maxIter--) + { + supVertexA = interpolatedTransA(m_convexA->localGetSupportingVertex(-v*interpolatedTransA.getBasis())); + supVertexB = interpolatedTransB(m_convexB->localGetSupportingVertex(v*interpolatedTransB.getBasis())); + w = supVertexA-supVertexB; + + btScalar VdotW = v.dot(w); + + if (lambda > btScalar(1.0)) + { + return false; + } + + if ( VdotW > btScalar(0.)) + { + VdotR = v.dot(r); + + if (VdotR >= -(SIMD_EPSILON*SIMD_EPSILON)) + return false; + else + { + lambda = lambda - VdotW / VdotR; + //interpolate to next lambda + // x = s + lambda * r; + interpolatedTransA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda); + interpolatedTransB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda); + //m_simplexSolver->reset(); + //check next line + w = supVertexA-supVertexB; + lastLambda = lambda; + n = v; + hasResult = true; + } + } + ///Just like regular GJK only add the vertex if it isn't already (close) to current vertex, it would lead to divisions by zero and NaN etc. + if (!m_simplexSolver->inSimplex(w)) + m_simplexSolver->addVertex( w, supVertexA , supVertexB); + + if (m_simplexSolver->closest(v)) + { + dist2 = v.length2(); + hasResult = true; + //todo: check this normal for validity + //n=v; + //printf("V=%f , %f, %f\n",v[0],v[1],v[2]); + //printf("DIST2=%f\n",dist2); + //printf("numverts = %i\n",m_simplexSolver->numVertices()); + } else + { + dist2 = btScalar(0.); + } + } + + //int numiter = MAX_ITERATIONS - maxIter; +// printf("number of iterations: %d", numiter); + + //don't report a time of impact when moving 'away' from the hitnormal + + + result.m_fraction = lambda; + if (n.length2() >= (SIMD_EPSILON*SIMD_EPSILON)) + result.m_normal = n.normalized(); + else + result.m_normal = btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if (result.m_normal.dot(r)>=-result.m_allowedPenetration) + return false; + + btVector3 hitA,hitB; + m_simplexSolver->compute_points(hitA,hitB); + result.m_hitPoint=hitB; + return true; +} + + + + diff --git a/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h b/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h new file mode 100644 index 0000000..6c81279 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h @@ -0,0 +1,50 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_SUBSIMPLEX_CONVEX_CAST_H +#define BT_SUBSIMPLEX_CONVEX_CAST_H + +#include "btConvexCast.h" +#include "btSimplexSolverInterface.h" +class btConvexShape; + +/// btSubsimplexConvexCast implements Gino van den Bergens' paper +///"Ray Casting against bteral Convex Objects with Application to Continuous Collision Detection" +/// GJK based Ray Cast, optimized version +/// Objects should not start in overlap, otherwise results are not defined. +class btSubsimplexConvexCast : public btConvexCast +{ + btSimplexSolverInterface* m_simplexSolver; + const btConvexShape* m_convexA; + const btConvexShape* m_convexB; + +public: + + btSubsimplexConvexCast (const btConvexShape* shapeA,const btConvexShape* shapeB,btSimplexSolverInterface* simplexSolver); + + //virtual ~btSubsimplexConvexCast(); + ///SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (sweep) between two moving objects. + ///Precondition is that objects should not penetration/overlap at the start from the interval. Overlap can be tested using btGjkPairDetector. + virtual bool calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result); + +}; + +#endif //BT_SUBSIMPLEX_CONVEX_CAST_H diff --git a/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp new file mode 100644 index 0000000..a775198 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp @@ -0,0 +1,609 @@ + +/* +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. + + Elsevier CDROM license agreements grants nonexclusive license to use the software + for any purpose, commercial or non-commercial as long as the following credit is included + identifying the original source of the software: + + Parts of the source are "from the book Real-Time Collision Detection by + Christer Ericson, published by Morgan Kaufmann Publishers, + (c) 2005 Elsevier Inc." + +*/ + + +#include "btVoronoiSimplexSolver.h" + +#define VERTA 0 +#define VERTB 1 +#define VERTC 2 +#define VERTD 3 + +#define CATCH_DEGENERATE_TETRAHEDRON 1 +void btVoronoiSimplexSolver::removeVertex(int index) +{ + + btAssert(m_numVertices>0); + m_numVertices--; + m_simplexVectorW[index] = m_simplexVectorW[m_numVertices]; + m_simplexPointsP[index] = m_simplexPointsP[m_numVertices]; + m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices]; +} + +void btVoronoiSimplexSolver::reduceVertices (const btUsageBitfield& usedVerts) +{ + if ((numVertices() >= 4) && (!usedVerts.usedVertexD)) + removeVertex(3); + + if ((numVertices() >= 3) && (!usedVerts.usedVertexC)) + removeVertex(2); + + if ((numVertices() >= 2) && (!usedVerts.usedVertexB)) + removeVertex(1); + + if ((numVertices() >= 1) && (!usedVerts.usedVertexA)) + removeVertex(0); + +} + + + + + +//clear the simplex, remove all the vertices +void btVoronoiSimplexSolver::reset() +{ + m_cachedValidClosest = false; + m_numVertices = 0; + m_needsUpdate = true; + m_lastW = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + m_cachedBC.reset(); +} + + + + //add a vertex +void btVoronoiSimplexSolver::addVertex(const btVector3& w, const btVector3& p, const btVector3& q) +{ + m_lastW = w; + m_needsUpdate = true; + + m_simplexVectorW[m_numVertices] = w; + m_simplexPointsP[m_numVertices] = p; + m_simplexPointsQ[m_numVertices] = q; + + m_numVertices++; +} + +bool btVoronoiSimplexSolver::updateClosestVectorAndPoints() +{ + + if (m_needsUpdate) + { + m_cachedBC.reset(); + + m_needsUpdate = false; + + switch (numVertices()) + { + case 0: + m_cachedValidClosest = false; + break; + case 1: + { + m_cachedP1 = m_simplexPointsP[0]; + m_cachedP2 = m_simplexPointsQ[0]; + m_cachedV = m_cachedP1-m_cachedP2; //== m_simplexVectorW[0] + m_cachedBC.reset(); + m_cachedBC.setBarycentricCoordinates(btScalar(1.),btScalar(0.),btScalar(0.),btScalar(0.)); + m_cachedValidClosest = m_cachedBC.isValid(); + break; + }; + case 2: + { + //closest point origin from line segment + const btVector3& from = m_simplexVectorW[0]; + const btVector3& to = m_simplexVectorW[1]; + btVector3 nearest; + + btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.)); + btVector3 diff = p - from; + btVector3 v = to - from; + btScalar t = v.dot(diff); + + if (t > 0) { + btScalar dotVV = v.dot(v); + if (t < dotVV) { + t /= dotVV; + diff -= t*v; + m_cachedBC.m_usedVertices.usedVertexA = true; + m_cachedBC.m_usedVertices.usedVertexB = true; + } else { + t = 1; + diff -= v; + //reduce to 1 point + m_cachedBC.m_usedVertices.usedVertexB = true; + } + } else + { + t = 0; + //reduce to 1 point + m_cachedBC.m_usedVertices.usedVertexA = true; + } + m_cachedBC.setBarycentricCoordinates(1-t,t); + nearest = from + t*v; + + m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]); + m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]); + m_cachedV = m_cachedP1 - m_cachedP2; + + reduceVertices(m_cachedBC.m_usedVertices); + + m_cachedValidClosest = m_cachedBC.isValid(); + break; + } + case 3: + { + //closest point origin from triangle + btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.)); + + const btVector3& a = m_simplexVectorW[0]; + const btVector3& b = m_simplexVectorW[1]; + const btVector3& c = m_simplexVectorW[2]; + + closestPtPointTriangle(p,a,b,c,m_cachedBC); + m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] + + m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] + + m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2]; + + m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] + + m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] + + m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2]; + + m_cachedV = m_cachedP1-m_cachedP2; + + reduceVertices (m_cachedBC.m_usedVertices); + m_cachedValidClosest = m_cachedBC.isValid(); + + break; + } + case 4: + { + + + btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.)); + + const btVector3& a = m_simplexVectorW[0]; + const btVector3& b = m_simplexVectorW[1]; + const btVector3& c = m_simplexVectorW[2]; + const btVector3& d = m_simplexVectorW[3]; + + bool hasSeperation = closestPtPointTetrahedron(p,a,b,c,d,m_cachedBC); + + if (hasSeperation) + { + + m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] + + m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] + + m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] + + m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3]; + + m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] + + m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] + + m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] + + m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3]; + + m_cachedV = m_cachedP1-m_cachedP2; + reduceVertices (m_cachedBC.m_usedVertices); + } else + { +// printf("sub distance got penetration\n"); + + if (m_cachedBC.m_degenerate) + { + m_cachedValidClosest = false; + } else + { + m_cachedValidClosest = true; + //degenerate case == false, penetration = true + zero + m_cachedV.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + break; + } + + m_cachedValidClosest = m_cachedBC.isValid(); + + //closest point origin from tetrahedron + break; + } + default: + { + m_cachedValidClosest = false; + } + }; + } + + return m_cachedValidClosest; + +} + +//return/calculate the closest vertex +bool btVoronoiSimplexSolver::closest(btVector3& v) +{ + bool succes = updateClosestVectorAndPoints(); + v = m_cachedV; + return succes; +} + + + +btScalar btVoronoiSimplexSolver::maxVertex() +{ + int i, numverts = numVertices(); + btScalar maxV = btScalar(0.); + for (i=0;i= btScalar(0.0) && d4 <= d3) + { + result.m_closestPointOnSimplex = b; + result.m_usedVertices.usedVertexB = true; + result.setBarycentricCoordinates(0,1,0); + + return true; // b; // barycentric coordinates (0,1,0) + } + // Check if P in edge region of AB, if so return projection of P onto AB + btScalar vc = d1*d4 - d3*d2; + if (vc <= btScalar(0.0) && d1 >= btScalar(0.0) && d3 <= btScalar(0.0)) { + btScalar v = d1 / (d1 - d3); + result.m_closestPointOnSimplex = a + v * ab; + result.m_usedVertices.usedVertexA = true; + result.m_usedVertices.usedVertexB = true; + result.setBarycentricCoordinates(1-v,v,0); + return true; + //return a + v * ab; // barycentric coordinates (1-v,v,0) + } + + // Check if P in vertex region outside C + btVector3 cp = p - c; + btScalar d5 = ab.dot(cp); + btScalar d6 = ac.dot(cp); + if (d6 >= btScalar(0.0) && d5 <= d6) + { + result.m_closestPointOnSimplex = c; + result.m_usedVertices.usedVertexC = true; + result.setBarycentricCoordinates(0,0,1); + return true;//c; // barycentric coordinates (0,0,1) + } + + // Check if P in edge region of AC, if so return projection of P onto AC + btScalar vb = d5*d2 - d1*d6; + if (vb <= btScalar(0.0) && d2 >= btScalar(0.0) && d6 <= btScalar(0.0)) { + btScalar w = d2 / (d2 - d6); + result.m_closestPointOnSimplex = a + w * ac; + result.m_usedVertices.usedVertexA = true; + result.m_usedVertices.usedVertexC = true; + result.setBarycentricCoordinates(1-w,0,w); + return true; + //return a + w * ac; // barycentric coordinates (1-w,0,w) + } + + // Check if P in edge region of BC, if so return projection of P onto BC + btScalar va = d3*d6 - d5*d4; + if (va <= btScalar(0.0) && (d4 - d3) >= btScalar(0.0) && (d5 - d6) >= btScalar(0.0)) { + btScalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); + + result.m_closestPointOnSimplex = b + w * (c - b); + result.m_usedVertices.usedVertexB = true; + result.m_usedVertices.usedVertexC = true; + result.setBarycentricCoordinates(0,1-w,w); + return true; + // return b + w * (c - b); // barycentric coordinates (0,1-w,w) + } + + // P inside face region. Compute Q through its barycentric coordinates (u,v,w) + btScalar denom = btScalar(1.0) / (va + vb + vc); + btScalar v = vb * denom; + btScalar w = vc * denom; + + result.m_closestPointOnSimplex = a + ab * v + ac * w; + result.m_usedVertices.usedVertexA = true; + result.m_usedVertices.usedVertexB = true; + result.m_usedVertices.usedVertexC = true; + result.setBarycentricCoordinates(1-v-w,v,w); + + return true; +// return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = btScalar(1.0) - v - w + +} + + + + + +/// Test if point p and d lie on opposite sides of plane through abc +int btVoronoiSimplexSolver::pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d) +{ + btVector3 normal = (b-a).cross(c-a); + + btScalar signp = (p - a).dot(normal); // [AP AB AC] + btScalar signd = (d - a).dot( normal); // [AD AB AC] + +#ifdef CATCH_DEGENERATE_TETRAHEDRON +#ifdef BT_USE_DOUBLE_PRECISION +if (signd * signd < (btScalar(1e-8) * btScalar(1e-8))) + { + return -1; + } +#else + if (signd * signd < (btScalar(1e-4) * btScalar(1e-4))) + { +// printf("affine dependent/degenerate\n");// + return -1; + } +#endif + +#endif + // Points on opposite sides if expression signs are opposite + return signp * signd < btScalar(0.); +} + + +bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult) +{ + btSubSimplexClosestResult tempResult; + + // Start out assuming point inside all halfspaces, so closest to itself + finalResult.m_closestPointOnSimplex = p; + finalResult.m_usedVertices.reset(); + finalResult.m_usedVertices.usedVertexA = true; + finalResult.m_usedVertices.usedVertexB = true; + finalResult.m_usedVertices.usedVertexC = true; + finalResult.m_usedVertices.usedVertexD = true; + + int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d); + int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b); + int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c); + int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a); + + if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0) + { + finalResult.m_degenerate = true; + return false; + } + + if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC) + { + return false; + } + + + btScalar bestSqDist = FLT_MAX; + // If point outside face abc then compute closest point on abc + if (pointOutsideABC) + { + closestPtPointTriangle(p, a, b, c,tempResult); + btVector3 q = tempResult.m_closestPointOnSimplex; + + btScalar sqDist = (q - p).dot( q - p); + // Update best closest point if (squared) distance is less than current best + if (sqDist < bestSqDist) { + bestSqDist = sqDist; + finalResult.m_closestPointOnSimplex = q; + //convert result bitmask! + finalResult.m_usedVertices.reset(); + finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA; + finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB; + finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC; + finalResult.setBarycentricCoordinates( + tempResult.m_barycentricCoords[VERTA], + tempResult.m_barycentricCoords[VERTB], + tempResult.m_barycentricCoords[VERTC], + 0 + ); + + } + } + + + // Repeat test for face acd + if (pointOutsideACD) + { + closestPtPointTriangle(p, a, c, d,tempResult); + btVector3 q = tempResult.m_closestPointOnSimplex; + //convert result bitmask! + + btScalar sqDist = (q - p).dot( q - p); + if (sqDist < bestSqDist) + { + bestSqDist = sqDist; + finalResult.m_closestPointOnSimplex = q; + finalResult.m_usedVertices.reset(); + finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA; + + finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB; + finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC; + finalResult.setBarycentricCoordinates( + tempResult.m_barycentricCoords[VERTA], + 0, + tempResult.m_barycentricCoords[VERTB], + tempResult.m_barycentricCoords[VERTC] + ); + + } + } + // Repeat test for face adb + + + if (pointOutsideADB) + { + closestPtPointTriangle(p, a, d, b,tempResult); + btVector3 q = tempResult.m_closestPointOnSimplex; + //convert result bitmask! + + btScalar sqDist = (q - p).dot( q - p); + if (sqDist < bestSqDist) + { + bestSqDist = sqDist; + finalResult.m_closestPointOnSimplex = q; + finalResult.m_usedVertices.reset(); + finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA; + finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC; + + finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB; + finalResult.setBarycentricCoordinates( + tempResult.m_barycentricCoords[VERTA], + tempResult.m_barycentricCoords[VERTC], + 0, + tempResult.m_barycentricCoords[VERTB] + ); + + } + } + // Repeat test for face bdc + + + if (pointOutsideBDC) + { + closestPtPointTriangle(p, b, d, c,tempResult); + btVector3 q = tempResult.m_closestPointOnSimplex; + //convert result bitmask! + btScalar sqDist = (q - p).dot( q - p); + if (sqDist < bestSqDist) + { + bestSqDist = sqDist; + finalResult.m_closestPointOnSimplex = q; + finalResult.m_usedVertices.reset(); + // + finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexA; + finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC; + finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB; + + finalResult.setBarycentricCoordinates( + 0, + tempResult.m_barycentricCoords[VERTA], + tempResult.m_barycentricCoords[VERTC], + tempResult.m_barycentricCoords[VERTB] + ); + + } + } + + //help! we ended up full ! + + if (finalResult.m_usedVertices.usedVertexA && + finalResult.m_usedVertices.usedVertexB && + finalResult.m_usedVertices.usedVertexC && + finalResult.m_usedVertices.usedVertexD) + { + return true; + } + + return true; +} + diff --git a/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h b/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h new file mode 100644 index 0000000..f1c7613 --- /dev/null +++ b/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h @@ -0,0 +1,179 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_VORONOI_SIMPLEX_SOLVER_H +#define BT_VORONOI_SIMPLEX_SOLVER_H + +#include "btSimplexSolverInterface.h" + + + +#define VORONOI_SIMPLEX_MAX_VERTS 5 + +///disable next define, or use defaultCollisionConfiguration->getSimplexSolver()->setEqualVertexThreshold(0.f) to disable/configure +#define BT_USE_EQUAL_VERTEX_THRESHOLD +#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 0.0001f + + +struct btUsageBitfield{ + btUsageBitfield() + { + reset(); + } + + void reset() + { + usedVertexA = false; + usedVertexB = false; + usedVertexC = false; + usedVertexD = false; + } + unsigned short usedVertexA : 1; + unsigned short usedVertexB : 1; + unsigned short usedVertexC : 1; + unsigned short usedVertexD : 1; + unsigned short unused1 : 1; + unsigned short unused2 : 1; + unsigned short unused3 : 1; + unsigned short unused4 : 1; +}; + + +struct btSubSimplexClosestResult +{ + btVector3 m_closestPointOnSimplex; + //MASK for m_usedVertices + //stores the simplex vertex-usage, using the MASK, + // if m_usedVertices & MASK then the related vertex is used + btUsageBitfield m_usedVertices; + btScalar m_barycentricCoords[4]; + bool m_degenerate; + + void reset() + { + m_degenerate = false; + setBarycentricCoordinates(); + m_usedVertices.reset(); + } + bool isValid() + { + bool valid = (m_barycentricCoords[0] >= btScalar(0.)) && + (m_barycentricCoords[1] >= btScalar(0.)) && + (m_barycentricCoords[2] >= btScalar(0.)) && + (m_barycentricCoords[3] >= btScalar(0.)); + + + return valid; + } + void setBarycentricCoordinates(btScalar a=btScalar(0.),btScalar b=btScalar(0.),btScalar c=btScalar(0.),btScalar d=btScalar(0.)) + { + m_barycentricCoords[0] = a; + m_barycentricCoords[1] = b; + m_barycentricCoords[2] = c; + m_barycentricCoords[3] = d; + } + +}; + +/// btVoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin. +/// Can be used with GJK, as an alternative to Johnson distance algorithm. +#ifdef NO_VIRTUAL_INTERFACE +class btVoronoiSimplexSolver +#else +class btVoronoiSimplexSolver : public btSimplexSolverInterface +#endif +{ +public: + + int m_numVertices; + + btVector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS]; + btVector3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS]; + btVector3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS]; + + + + btVector3 m_cachedP1; + btVector3 m_cachedP2; + btVector3 m_cachedV; + btVector3 m_lastW; + + btScalar m_equalVertexThreshold; + bool m_cachedValidClosest; + + + btSubSimplexClosestResult m_cachedBC; + + bool m_needsUpdate; + + void removeVertex(int index); + void reduceVertices (const btUsageBitfield& usedVerts); + bool updateClosestVectorAndPoints(); + + bool closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult); + int pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d); + bool closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c,btSubSimplexClosestResult& result); + +public: + + btVoronoiSimplexSolver() + : m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD) + { + } + void reset(); + + void addVertex(const btVector3& w, const btVector3& p, const btVector3& q); + + void setEqualVertexThreshold(btScalar threshold) + { + m_equalVertexThreshold = threshold; + } + + btScalar getEqualVertexThreshold() const + { + return m_equalVertexThreshold; + } + + bool closest(btVector3& v); + + btScalar maxVertex(); + + bool fullSimplex() const + { + return (m_numVertices == 4); + } + + int getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const; + + bool inSimplex(const btVector3& w); + + void backup_closest(btVector3& v) ; + + bool emptySimplex() const ; + + void compute_points(btVector3& p1, btVector3& p2) ; + + int numVertices() const + { + return m_numVertices; + } + + +}; + +#endif //BT_VORONOI_SIMPLEX_SOLVER_H + diff --git a/src/BulletCollision/ibmsdk/Makefile b/src/BulletCollision/ibmsdk/Makefile new file mode 100644 index 0000000..8a78783 --- /dev/null +++ b/src/BulletCollision/ibmsdk/Makefile @@ -0,0 +1,112 @@ +#### Source code Dirs +VPATH = \ +../BroadphaseCollision \ +../CollisionDispatch \ +../NarrowPhaseCollision \ +../CollisionShapes + +ROOT = ../../.. + +#### Library +LIBRARY_ppu = bulletcollision.a + +#### Compiler flags +CPPFLAGS = \ +-DUSE_LIBSPE2 \ +-I../BroadphaseCollision \ +-I../CollisionDispath \ +-I../NarrowPhaseCollision \ +-I../CollisionShapes \ +-I$(ROOT)/src/ \ +-I$(SDKINC) + +#### Optimization level flags +#CC_OPT_LEVEL = $(CC_OPT_LEVEL_DEBUG) +CC_OPT_LEVEL = -O3 + +##### Objects to be archived in lib + +OBJS = \ +btAxisSweep3.o \ +btQuantizedBvh.o \ +btBroadphaseProxy.o \ +btCollisionAlgorithm.o \ +btDispatcher.o \ +btDbvtBroadphase.o \ +btDbvt.o \ +btOverlappingPairCache.o \ +btSimpleBroadphase.o \ +btContinuousConvexCollision.o \ +btConvexCast.o \ +btGjkConvexCast.o \ +btGjkEpa2.o \ +btGjkEpaPenetrationDepthSolver.o \ +btGjkPairDetector.o \ +btDefaultCollisionConfiguration.o \ +btMinkowskiPenetrationDepthSolver.o \ +btPersistentManifold.o \ +btRaycastCallback.o \ +btSubSimplexConvexCast.o \ +btVoronoiSimplexSolver.o \ +btCollisionDispatcher.o \ +btCollisionObject.o \ +btCollisionWorld.o \ +btCompoundCollisionAlgorithm.o \ +btBoxBoxCollisionAlgorithm.o \ +btBoxBoxDetector.o \ +btConvexPlaneCollisionAlgorithm.o \ +btConvexConcaveCollisionAlgorithm.o \ +btConvexConvexAlgorithm.o \ +btDefaultCollisionConfiguration.o \ +btEmptyCollisionAlgorithm.o \ +btManifoldResult.o \ +btSimulationIslandManager.o \ +btSphereBoxCollisionAlgorithm.o \ +btSphereSphereCollisionAlgorithm.o \ +btSphereTriangleCollisionAlgorithm.o \ +btActivatingCollisionAlgorithm.o \ +btUnionFind.o \ +SphereTriangleDetector.o \ +btBoxShape.o \ +btBvhTriangleMeshShape.o \ +btCapsuleShape.o \ +btCollisionShape.o \ +btCompoundShape.o \ +btConcaveShape.o \ +btConeShape.o \ +btConvexHullShape.o \ +btConvexShape.o \ +btConvexInternalShape.o \ +btConvexTriangleMeshShape.o \ +btCylinderShape.o \ +btEmptyShape.o \ +btHeightfieldTerrainShape.o \ +btMinkowskiSumShape.o \ +btMultiSphereShape.o \ +btOptimizedBvh.o \ +btPolyhedralConvexShape.o \ +btSphereShape.o \ +btStaticPlaneShape.o \ +btStridingMeshInterface.o \ +btTetrahedronShape.o \ +btTriangleBuffer.o \ +btTriangleCallback.o \ +btTriangleIndexVertexArray.o \ +btTriangleMesh.o \ +btTriangleMeshShape.o \ +btUniformScalingShape.o + +#### Install directories +INSTALL_DIR = $(ROOT)/lib/ibmsdk +INSTALL_FILES = $(LIBRARY_ppu) + +IBM_CELLSDK_VERSION := $(shell if [ -d /opt/cell ]; then echo "3.0"; fi) + +ifeq ("$(IBM_CELLSDK_VERSION)","3.0") + CELL_TOP ?= /opt/cell/sdk + include $(CELL_TOP)/buildutils/make.footer +else + CELL_TOP ?= /opt/ibm/cell-sdk/prototype + include $(CELL_TOP)/make.footer +endif + diff --git a/src/BulletCollision/premake4.lua b/src/BulletCollision/premake4.lua new file mode 100644 index 0000000..094b306 --- /dev/null +++ b/src/BulletCollision/premake4.lua @@ -0,0 +1,11 @@ + project "BulletCollision" + + kind "StaticLib" + targetdir "../../lib" + includedirs { + "..", + } + files { + "**.cpp", + "**.h" + } \ No newline at end of file diff --git a/src/BulletDynamics/CMakeLists.txt b/src/BulletDynamics/CMakeLists.txt new file mode 100644 index 0000000..3a88e35 --- /dev/null +++ b/src/BulletDynamics/CMakeLists.txt @@ -0,0 +1,112 @@ +INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src ) + + + +SET(BulletDynamics_SRCS + Character/btKinematicCharacterController.cpp + ConstraintSolver/btConeTwistConstraint.cpp + ConstraintSolver/btContactConstraint.cpp + ConstraintSolver/btGeneric6DofConstraint.cpp + ConstraintSolver/btGeneric6DofSpringConstraint.cpp + ConstraintSolver/btHinge2Constraint.cpp + ConstraintSolver/btHingeConstraint.cpp + ConstraintSolver/btPoint2PointConstraint.cpp + ConstraintSolver/btSequentialImpulseConstraintSolver.cpp + ConstraintSolver/btSliderConstraint.cpp + ConstraintSolver/btSolve2LinearConstraint.cpp + ConstraintSolver/btTypedConstraint.cpp + ConstraintSolver/btUniversalConstraint.cpp + Dynamics/btDiscreteDynamicsWorld.cpp + Dynamics/btRigidBody.cpp + Dynamics/btSimpleDynamicsWorld.cpp + Dynamics/Bullet-C-API.cpp + Vehicle/btRaycastVehicle.cpp + Vehicle/btWheelInfo.cpp +) + +SET(Root_HDRS + ../btBulletDynamicsCommon.h + ../btBulletCollisionCommon.h +) +SET(ConstraintSolver_HDRS + ConstraintSolver/btConeTwistConstraint.h + ConstraintSolver/btConstraintSolver.h + ConstraintSolver/btContactConstraint.h + ConstraintSolver/btContactSolverInfo.h + ConstraintSolver/btGeneric6DofConstraint.h + ConstraintSolver/btGeneric6DofSpringConstraint.h + ConstraintSolver/btHinge2Constraint.h + ConstraintSolver/btHingeConstraint.h + ConstraintSolver/btJacobianEntry.h + ConstraintSolver/btPoint2PointConstraint.h + ConstraintSolver/btSequentialImpulseConstraintSolver.h + ConstraintSolver/btSliderConstraint.h + ConstraintSolver/btSolve2LinearConstraint.h + ConstraintSolver/btSolverBody.h + ConstraintSolver/btSolverConstraint.h + ConstraintSolver/btTypedConstraint.h + ConstraintSolver/btUniversalConstraint.h +) +SET(Dynamics_HDRS + Dynamics/btActionInterface.h + Dynamics/btDiscreteDynamicsWorld.h + Dynamics/btDynamicsWorld.h + Dynamics/btSimpleDynamicsWorld.h + Dynamics/btRigidBody.h +) +SET(Vehicle_HDRS + Vehicle/btRaycastVehicle.h + Vehicle/btVehicleRaycaster.h + Vehicle/btWheelInfo.h +) + +SET(Character_HDRS + Character/btCharacterControllerInterface.h + Character/btKinematicCharacterController.h +) + + + +SET(BulletDynamics_HDRS + ${Root_HDRS} + ${ConstraintSolver_HDRS} + ${Dynamics_HDRS} + ${Vehicle_HDRS} + ${Character_HDRS} +) + + +ADD_LIBRARY(BulletDynamics ${BulletDynamics_SRCS} ${BulletDynamics_HDRS}) +SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletDynamics BulletCollision LinearMath) +ENDIF (BUILD_SHARED_LIBS) + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletDynamics DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletDynamics DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN +".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + INSTALL(FILES ../btBulletDynamicsCommon.h +DESTINATION ${INCLUDE_INSTALL_DIR}/BulletDynamics) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES PUBLIC_HEADER "${Root_HDRS}") + # Have to list out sub-directories manually: + SET_PROPERTY(SOURCE ${ConstraintSolver_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/ConstraintSolver) + SET_PROPERTY(SOURCE ${Dynamics_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Dynamics) + SET_PROPERTY(SOURCE ${Vehicle_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Vehicle) + SET_PROPERTY(SOURCE ${Character_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Character) + + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/src/BulletDynamics/Character/btCharacterControllerInterface.h b/src/BulletDynamics/Character/btCharacterControllerInterface.h new file mode 100644 index 0000000..c81813c --- /dev/null +++ b/src/BulletDynamics/Character/btCharacterControllerInterface.h @@ -0,0 +1,46 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CHARACTER_CONTROLLER_INTERFACE_H +#define BT_CHARACTER_CONTROLLER_INTERFACE_H + +#include "LinearMath/btVector3.h" +#include "BulletDynamics/Dynamics/btActionInterface.h" + +class btCollisionShape; +class btRigidBody; +class btCollisionWorld; + +class btCharacterControllerInterface : public btActionInterface +{ +public: + btCharacterControllerInterface () {}; + virtual ~btCharacterControllerInterface () {}; + + virtual void setWalkDirection(const btVector3& walkDirection) = 0; + virtual void setVelocityForTimeInterval(const btVector3& velocity, btScalar timeInterval) = 0; + virtual void reset () = 0; + virtual void warp (const btVector3& origin) = 0; + + virtual void preStep ( btCollisionWorld* collisionWorld) = 0; + virtual void playerStep (btCollisionWorld* collisionWorld, btScalar dt) = 0; + virtual bool canJump () const = 0; + virtual void jump () = 0; + + virtual bool onGround () const = 0; +}; + +#endif //BT_CHARACTER_CONTROLLER_INTERFACE_H + diff --git a/src/BulletDynamics/Character/btKinematicCharacterController.cpp b/src/BulletDynamics/Character/btKinematicCharacterController.cpp new file mode 100644 index 0000000..f733dc0 --- /dev/null +++ b/src/BulletDynamics/Character/btKinematicCharacterController.cpp @@ -0,0 +1,641 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/CollisionDispatch/btGhostObject.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "LinearMath/btDefaultMotionState.h" +#include "btKinematicCharacterController.h" + + +// static helper method +static btVector3 +getNormalizedVector(const btVector3& v) +{ + btVector3 n = v.normalized(); + if (n.length() < SIMD_EPSILON) { + n.setValue(0, 0, 0); + } + return n; +} + + +///@todo Interact with dynamic objects, +///Ride kinematicly animated platforms properly +///More realistic (or maybe just a config option) falling +/// -> Should integrate falling velocity manually and use that in stepDown() +///Support jumping +///Support ducking +class btKinematicClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback +{ +public: + btKinematicClosestNotMeRayResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)) + { + m_me = me; + } + + virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) + { + if (rayResult.m_collisionObject == m_me) + return 1.0; + + return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace); + } +protected: + btCollisionObject* m_me; +}; + +class btKinematicClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback +{ +public: + btKinematicClosestNotMeConvexResultCallback (btCollisionObject* me, const btVector3& up, btScalar minSlopeDot) + : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)) + , m_me(me) + , m_up(up) + , m_minSlopeDot(minSlopeDot) + { + } + + virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace) + { + if (convexResult.m_hitCollisionObject == m_me) + return btScalar(1.0); + + btVector3 hitNormalWorld; + if (normalInWorldSpace) + { + hitNormalWorld = convexResult.m_hitNormalLocal; + } else + { + ///need to transform normal into worldspace + hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal; + } + + btScalar dotUp = m_up.dot(hitNormalWorld); + if (dotUp < m_minSlopeDot) { + return btScalar(1.0); + } + + return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace); + } +protected: + btCollisionObject* m_me; + const btVector3 m_up; + btScalar m_minSlopeDot; +}; + +/* + * Returns the reflection direction of a ray going 'direction' hitting a surface with normal 'normal' + * + * from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html + */ +btVector3 btKinematicCharacterController::computeReflectionDirection (const btVector3& direction, const btVector3& normal) +{ + return direction - (btScalar(2.0) * direction.dot(normal)) * normal; +} + +/* + * Returns the portion of 'direction' that is parallel to 'normal' + */ +btVector3 btKinematicCharacterController::parallelComponent (const btVector3& direction, const btVector3& normal) +{ + btScalar magnitude = direction.dot(normal); + return normal * magnitude; +} + +/* + * Returns the portion of 'direction' that is perpindicular to 'normal' + */ +btVector3 btKinematicCharacterController::perpindicularComponent (const btVector3& direction, const btVector3& normal) +{ + return direction - parallelComponent(direction, normal); +} + +btKinematicCharacterController::btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis) +{ + m_upAxis = upAxis; + m_addedMargin = 0.02; + m_walkDirection.setValue(0,0,0); + m_useGhostObjectSweepTest = true; + m_ghostObject = ghostObject; + m_stepHeight = stepHeight; + m_turnAngle = btScalar(0.0); + m_convexShape=convexShape; + m_useWalkDirection = true; // use walk direction by default, legacy behavior + m_velocityTimeInterval = 0.0; + m_verticalVelocity = 0.0; + m_verticalOffset = 0.0; + m_gravity = 9.8 * 3 ; // 3G acceleration. + m_fallSpeed = 55.0; // Terminal velocity of a sky diver in m/s. + m_jumpSpeed = 10.0; // ? + m_wasOnGround = false; + m_wasJumping = false; + setMaxSlope(btRadians(45.0)); +} + +btKinematicCharacterController::~btKinematicCharacterController () +{ +} + +btPairCachingGhostObject* btKinematicCharacterController::getGhostObject() +{ + return m_ghostObject; +} + +bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld* collisionWorld) +{ + + bool penetration = false; + + collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher()); + + m_currentPosition = m_ghostObject->getWorldTransform().getOrigin(); + + btScalar maxPen = btScalar(0.0); + for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++) + { + m_manifoldArray.resize(0); + + btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i]; + + if (collisionPair->m_algorithm) + collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray); + + + for (int j=0;jgetBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0); + for (int p=0;pgetNumContacts();p++) + { + const btManifoldPoint&pt = manifold->getContactPoint(p); + + btScalar dist = pt.getDistance(); + + if (dist < 0.0) + { + if (dist < maxPen) + { + maxPen = dist; + m_touchingNormal = pt.m_normalWorldOnB * directionSign;//?? + + } + m_currentPosition += pt.m_normalWorldOnB * directionSign * dist * btScalar(0.2); + penetration = true; + } else { + //printf("touching %f\n", dist); + } + } + + //manifold->clearManifold(); + } + } + btTransform newTrans = m_ghostObject->getWorldTransform(); + newTrans.setOrigin(m_currentPosition); + m_ghostObject->setWorldTransform(newTrans); +// printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]); + return penetration; +} + +void btKinematicCharacterController::stepUp ( btCollisionWorld* world) +{ + // phase 1: up + btTransform start, end; + m_targetPosition = m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_stepHeight + (m_verticalOffset > 0.f?m_verticalOffset:0.f)); + + start.setIdentity (); + end.setIdentity (); + + /* FIXME: Handle penetration properly */ + start.setOrigin (m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_convexShape->getMargin() + m_addedMargin)); + end.setOrigin (m_targetPosition); + + btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, -getUpAxisDirections()[m_upAxis], btScalar(0.7071)); + callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; + callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; + + if (m_useGhostObjectSweepTest) + { + m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration); + } + else + { + world->convexSweepTest (m_convexShape, start, end, callback); + } + + if (callback.hasHit()) + { + // Only modify the position if the hit was a slope and not a wall or ceiling. + if(callback.m_hitNormalWorld.dot(getUpAxisDirections()[m_upAxis]) > 0.0) + { + // we moved up only a fraction of the step height + m_currentStepOffset = m_stepHeight * callback.m_closestHitFraction; + m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); + } + m_verticalVelocity = 0.0; + m_verticalOffset = 0.0; + } else { + m_currentStepOffset = m_stepHeight; + m_currentPosition = m_targetPosition; + } +} + +void btKinematicCharacterController::updateTargetPositionBasedOnCollision (const btVector3& hitNormal, btScalar tangentMag, btScalar normalMag) +{ + btVector3 movementDirection = m_targetPosition - m_currentPosition; + btScalar movementLength = movementDirection.length(); + if (movementLength>SIMD_EPSILON) + { + movementDirection.normalize(); + + btVector3 reflectDir = computeReflectionDirection (movementDirection, hitNormal); + reflectDir.normalize(); + + btVector3 parallelDir, perpindicularDir; + + parallelDir = parallelComponent (reflectDir, hitNormal); + perpindicularDir = perpindicularComponent (reflectDir, hitNormal); + + m_targetPosition = m_currentPosition; + if (0)//tangentMag != 0.0) + { + btVector3 parComponent = parallelDir * btScalar (tangentMag*movementLength); +// printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]); + m_targetPosition += parComponent; + } + + if (normalMag != 0.0) + { + btVector3 perpComponent = perpindicularDir * btScalar (normalMag*movementLength); +// printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]); + m_targetPosition += perpComponent; + } + } else + { +// printf("movementLength don't normalize a zero vector\n"); + } +} + +void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* collisionWorld, const btVector3& walkMove) +{ + // printf("m_normalizedDirection=%f,%f,%f\n", + // m_normalizedDirection[0],m_normalizedDirection[1],m_normalizedDirection[2]); + // phase 2: forward and strafe + btTransform start, end; + m_targetPosition = m_currentPosition + walkMove; + + start.setIdentity (); + end.setIdentity (); + + btScalar fraction = 1.0; + btScalar distance2 = (m_currentPosition-m_targetPosition).length2(); +// printf("distance2=%f\n",distance2); + + if (m_touchingContact) + { + if (m_normalizedDirection.dot(m_touchingNormal) > btScalar(0.0)) + { + updateTargetPositionBasedOnCollision (m_touchingNormal); + } + } + + int maxIter = 10; + + while (fraction > btScalar(0.01) && maxIter-- > 0) + { + start.setOrigin (m_currentPosition); + end.setOrigin (m_targetPosition); + btVector3 sweepDirNegative(m_currentPosition - m_targetPosition); + + btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, sweepDirNegative, btScalar(0.0)); + callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; + callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; + + + btScalar margin = m_convexShape->getMargin(); + m_convexShape->setMargin(margin + m_addedMargin); + + + if (m_useGhostObjectSweepTest) + { + m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); + } else + { + collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); + } + + m_convexShape->setMargin(margin); + + + fraction -= callback.m_closestHitFraction; + + if (callback.hasHit()) + { + // we moved only a fraction + btScalar hitDistance; + hitDistance = (callback.m_hitPointWorld - m_currentPosition).length(); + +// m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); + + updateTargetPositionBasedOnCollision (callback.m_hitNormalWorld); + btVector3 currentDir = m_targetPosition - m_currentPosition; + distance2 = currentDir.length2(); + if (distance2 > SIMD_EPSILON) + { + currentDir.normalize(); + /* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */ + if (currentDir.dot(m_normalizedDirection) <= btScalar(0.0)) + { + break; + } + } else + { +// printf("currentDir: don't normalize a zero vector\n"); + break; + } + + } else { + // we moved whole way + m_currentPosition = m_targetPosition; + } + + // if (callback.m_closestHitFraction == 0.f) + // break; + + } +} + +void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld, btScalar dt) +{ + btTransform start, end; + + // phase 3: down + /*btScalar additionalDownStep = (m_wasOnGround && !onGround()) ? m_stepHeight : 0.0; + btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + additionalDownStep); + btScalar downVelocity = (additionalDownStep == 0.0 && m_verticalVelocity<0.0?-m_verticalVelocity:0.0) * dt; + btVector3 gravity_drop = getUpAxisDirections()[m_upAxis] * downVelocity; + m_targetPosition -= (step_drop + gravity_drop);*/ + + btScalar downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt; + if(downVelocity > 0.0 && downVelocity < m_stepHeight + && (m_wasOnGround || !m_wasJumping)) + { + downVelocity = m_stepHeight; + } + + btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity); + m_targetPosition -= step_drop; + + start.setIdentity (); + end.setIdentity (); + + start.setOrigin (m_currentPosition); + end.setOrigin (m_targetPosition); + + btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, getUpAxisDirections()[m_upAxis], m_maxSlopeCosine); + callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; + callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; + + if (m_useGhostObjectSweepTest) + { + m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); + } else + { + collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); + } + + if (callback.hasHit()) + { + // we dropped a fraction of the height -> hit floor + m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); + m_verticalVelocity = 0.0; + m_verticalOffset = 0.0; + m_wasJumping = false; + } else { + // we dropped the full height + + m_currentPosition = m_targetPosition; + } +} + + + +void btKinematicCharacterController::setWalkDirection +( +const btVector3& walkDirection +) +{ + m_useWalkDirection = true; + m_walkDirection = walkDirection; + m_normalizedDirection = getNormalizedVector(m_walkDirection); +} + + + +void btKinematicCharacterController::setVelocityForTimeInterval +( +const btVector3& velocity, +btScalar timeInterval +) +{ +// printf("setVelocity!\n"); +// printf(" interval: %f\n", timeInterval); +// printf(" velocity: (%f, %f, %f)\n", +// velocity.x(), velocity.y(), velocity.z()); + + m_useWalkDirection = false; + m_walkDirection = velocity; + m_normalizedDirection = getNormalizedVector(m_walkDirection); + m_velocityTimeInterval = timeInterval; +} + + + +void btKinematicCharacterController::reset () +{ +} + +void btKinematicCharacterController::warp (const btVector3& origin) +{ + btTransform xform; + xform.setIdentity(); + xform.setOrigin (origin); + m_ghostObject->setWorldTransform (xform); +} + + +void btKinematicCharacterController::preStep ( btCollisionWorld* collisionWorld) +{ + + int numPenetrationLoops = 0; + m_touchingContact = false; + while (recoverFromPenetration (collisionWorld)) + { + numPenetrationLoops++; + m_touchingContact = true; + if (numPenetrationLoops > 4) + { + //printf("character could not recover from penetration = %d\n", numPenetrationLoops); + break; + } + } + + m_currentPosition = m_ghostObject->getWorldTransform().getOrigin(); + m_targetPosition = m_currentPosition; +// printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]); + + +} + +#include + +void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWorld, btScalar dt) +{ +// printf("playerStep(): "); +// printf(" dt = %f", dt); + + // quick check... + if (!m_useWalkDirection && m_velocityTimeInterval <= 0.0) { +// printf("\n"); + return; // no motion + } + + m_wasOnGround = onGround(); + + // Update fall velocity. + m_verticalVelocity -= m_gravity * dt; + if(m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed) + { + m_verticalVelocity = m_jumpSpeed; + } + if(m_verticalVelocity < 0.0 && btFabs(m_verticalVelocity) > btFabs(m_fallSpeed)) + { + m_verticalVelocity = -btFabs(m_fallSpeed); + } + m_verticalOffset = m_verticalVelocity * dt; + + + btTransform xform; + xform = m_ghostObject->getWorldTransform (); + +// printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]); +// printf("walkSpeed=%f\n",walkSpeed); + + stepUp (collisionWorld); + if (m_useWalkDirection) { + stepForwardAndStrafe (collisionWorld, m_walkDirection); + } else { + //printf(" time: %f", m_velocityTimeInterval); + // still have some time left for moving! + btScalar dtMoving = + (dt < m_velocityTimeInterval) ? dt : m_velocityTimeInterval; + m_velocityTimeInterval -= dt; + + // how far will we move while we are moving? + btVector3 move = m_walkDirection * dtMoving; + + //printf(" dtMoving: %f", dtMoving); + + // okay, step + stepForwardAndStrafe(collisionWorld, move); + } + stepDown (collisionWorld, dt); + + // printf("\n"); + + xform.setOrigin (m_currentPosition); + m_ghostObject->setWorldTransform (xform); +} + +void btKinematicCharacterController::setFallSpeed (btScalar fallSpeed) +{ + m_fallSpeed = fallSpeed; +} + +void btKinematicCharacterController::setJumpSpeed (btScalar jumpSpeed) +{ + m_jumpSpeed = jumpSpeed; +} + +void btKinematicCharacterController::setMaxJumpHeight (btScalar maxJumpHeight) +{ + m_maxJumpHeight = maxJumpHeight; +} + +bool btKinematicCharacterController::canJump () const +{ + return onGround(); +} + +void btKinematicCharacterController::jump () +{ + if (!canJump()) + return; + + m_verticalVelocity = m_jumpSpeed; + m_wasJumping = true; + +#if 0 + currently no jumping. + btTransform xform; + m_rigidBody->getMotionState()->getWorldTransform (xform); + btVector3 up = xform.getBasis()[1]; + up.normalize (); + btScalar magnitude = (btScalar(1.0)/m_rigidBody->getInvMass()) * btScalar(8.0); + m_rigidBody->applyCentralImpulse (up * magnitude); +#endif +} + +void btKinematicCharacterController::setGravity(btScalar gravity) +{ + m_gravity = gravity; +} + +btScalar btKinematicCharacterController::getGravity() const +{ + return m_gravity; +} + +void btKinematicCharacterController::setMaxSlope(btScalar slopeRadians) +{ + m_maxSlopeRadians = slopeRadians; + m_maxSlopeCosine = btCos(slopeRadians); +} + +btScalar btKinematicCharacterController::getMaxSlope() const +{ + return m_maxSlopeRadians; +} + +bool btKinematicCharacterController::onGround () const +{ + return m_verticalVelocity == 0.0 && m_verticalOffset == 0.0; +} + + +btVector3* btKinematicCharacterController::getUpAxisDirections() +{ + static btVector3 sUpAxisDirection[3] = { btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f) }; + + return sUpAxisDirection; +} + +void btKinematicCharacterController::debugDraw(btIDebugDraw* debugDrawer) +{ +} diff --git a/src/BulletDynamics/Character/btKinematicCharacterController.h b/src/BulletDynamics/Character/btKinematicCharacterController.h new file mode 100644 index 0000000..ef01f8a --- /dev/null +++ b/src/BulletDynamics/Character/btKinematicCharacterController.h @@ -0,0 +1,163 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_KINEMATIC_CHARACTER_CONTROLLER_H +#define BT_KINEMATIC_CHARACTER_CONTROLLER_H + +#include "LinearMath/btVector3.h" + +#include "btCharacterControllerInterface.h" + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" + + +class btCollisionShape; +class btConvexShape; +class btRigidBody; +class btCollisionWorld; +class btCollisionDispatcher; +class btPairCachingGhostObject; + +///btKinematicCharacterController is an object that supports a sliding motion in a world. +///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations. +///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user. +class btKinematicCharacterController : public btCharacterControllerInterface +{ +protected: + + btScalar m_halfHeight; + + btPairCachingGhostObject* m_ghostObject; + btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast + + btScalar m_verticalVelocity; + btScalar m_verticalOffset; + btScalar m_fallSpeed; + btScalar m_jumpSpeed; + btScalar m_maxJumpHeight; + btScalar m_maxSlopeRadians; // Slope angle that is set (used for returning the exact value) + btScalar m_maxSlopeCosine; // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization) + btScalar m_gravity; + + btScalar m_turnAngle; + + btScalar m_stepHeight; + + btScalar m_addedMargin;//@todo: remove this and fix the code + + ///this is the desired walk direction, set by the user + btVector3 m_walkDirection; + btVector3 m_normalizedDirection; + + //some internal variables + btVector3 m_currentPosition; + btScalar m_currentStepOffset; + btVector3 m_targetPosition; + + ///keep track of the contact manifolds + btManifoldArray m_manifoldArray; + + bool m_touchingContact; + btVector3 m_touchingNormal; + + bool m_wasOnGround; + bool m_wasJumping; + bool m_useGhostObjectSweepTest; + bool m_useWalkDirection; + btScalar m_velocityTimeInterval; + int m_upAxis; + + static btVector3* getUpAxisDirections(); + + btVector3 computeReflectionDirection (const btVector3& direction, const btVector3& normal); + btVector3 parallelComponent (const btVector3& direction, const btVector3& normal); + btVector3 perpindicularComponent (const btVector3& direction, const btVector3& normal); + + bool recoverFromPenetration ( btCollisionWorld* collisionWorld); + void stepUp (btCollisionWorld* collisionWorld); + void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0)); + void stepForwardAndStrafe (btCollisionWorld* collisionWorld, const btVector3& walkMove); + void stepDown (btCollisionWorld* collisionWorld, btScalar dt); +public: + btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis = 1); + ~btKinematicCharacterController (); + + + ///btActionInterface interface + virtual void updateAction( btCollisionWorld* collisionWorld,btScalar deltaTime) + { + preStep ( collisionWorld); + playerStep (collisionWorld, deltaTime); + } + + ///btActionInterface interface + void debugDraw(btIDebugDraw* debugDrawer); + + void setUpAxis (int axis) + { + if (axis < 0) + axis = 0; + if (axis > 2) + axis = 2; + m_upAxis = axis; + } + + /// This should probably be called setPositionIncrementPerSimulatorStep. + /// This is neither a direction nor a velocity, but the amount to + /// increment the position each simulation iteration, regardless + /// of dt. + /// This call will reset any velocity set by setVelocityForTimeInterval(). + virtual void setWalkDirection(const btVector3& walkDirection); + + /// Caller provides a velocity with which the character should move for + /// the given time period. After the time period, velocity is reset + /// to zero. + /// This call will reset any walk direction set by setWalkDirection(). + /// Negative time intervals will result in no motion. + virtual void setVelocityForTimeInterval(const btVector3& velocity, + btScalar timeInterval); + + void reset (); + void warp (const btVector3& origin); + + void preStep ( btCollisionWorld* collisionWorld); + void playerStep ( btCollisionWorld* collisionWorld, btScalar dt); + + void setFallSpeed (btScalar fallSpeed); + void setJumpSpeed (btScalar jumpSpeed); + void setMaxJumpHeight (btScalar maxJumpHeight); + bool canJump () const; + + void jump (); + + void setGravity(btScalar gravity); + btScalar getGravity() const; + + /// The max slope determines the maximum angle that the controller can walk up. + /// The slope angle is measured in radians. + void setMaxSlope(btScalar slopeRadians); + btScalar getMaxSlope() const; + + btPairCachingGhostObject* getGhostObject(); + void setUseGhostSweepTest(bool useGhostObjectSweepTest) + { + m_useGhostObjectSweepTest = useGhostObjectSweepTest; + } + + bool onGround () const; +}; + +#endif // BT_KINEMATIC_CHARACTER_CONTROLLER_H diff --git a/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp new file mode 100644 index 0000000..755544f --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp @@ -0,0 +1,1132 @@ +/* +Bullet Continuous Collision Detection and Physics Library +btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios + +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. + +Written by: Marcus Hennix +*/ + + +#include "btConeTwistConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" +#include "LinearMath/btMinMax.h" +#include + + + +//#define CONETWIST_USE_OBSOLETE_SOLVER true +#define CONETWIST_USE_OBSOLETE_SOLVER false +#define CONETWIST_DEF_FIX_THRESH btScalar(.05f) + + +SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis, const btMatrix3x3& invInertiaWorld) +{ + btVector3 vec = axis * invInertiaWorld; + return axis.dot(vec); +} + + + + +btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB, + const btTransform& rbAFrame,const btTransform& rbBFrame) + :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), + m_angularOnly(false), + m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER) +{ + init(); +} + +btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame) + :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE,rbA),m_rbAFrame(rbAFrame), + m_angularOnly(false), + m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER) +{ + m_rbBFrame = m_rbAFrame; + init(); +} + + +void btConeTwistConstraint::init() +{ + m_angularOnly = false; + m_solveTwistLimit = false; + m_solveSwingLimit = false; + m_bMotorEnabled = false; + m_maxMotorImpulse = btScalar(-1); + + setLimit(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT)); + m_damping = btScalar(0.01); + m_fixThresh = CONETWIST_DEF_FIX_THRESH; + m_flags = 0; + m_linCFM = btScalar(0.f); + m_linERP = btScalar(0.7f); + m_angCFM = btScalar(0.f); +} + + +void btConeTwistConstraint::getInfo1 (btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } + else + { + info->m_numConstraintRows = 3; + info->nub = 3; + calcAngleInfo2(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld()); + if(m_solveSwingLimit) + { + info->m_numConstraintRows++; + info->nub--; + if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) + { + info->m_numConstraintRows++; + info->nub--; + } + } + if(m_solveTwistLimit) + { + info->m_numConstraintRows++; + info->nub--; + } + } +} + +void btConeTwistConstraint::getInfo1NonVirtual (btConstraintInfo1* info) +{ + //always reserve 6 rows: object transform is not available on SPU + info->m_numConstraintRows = 6; + info->nub = 0; + +} + + +void btConeTwistConstraint::getInfo2 (btConstraintInfo2* info) +{ + getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld()); +} + +void btConeTwistConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB) +{ + calcAngleInfo2(transA,transB,invInertiaWorldA,invInertiaWorldB); + + btAssert(!m_useSolveConstraintObsolete); + // set jacobian + info->m_J1linearAxis[0] = 1; + info->m_J1linearAxis[info->rowskip+1] = 1; + info->m_J1linearAxis[2*info->rowskip+2] = 1; + btVector3 a1 = transA.getBasis() * m_rbAFrame.getOrigin(); + { + btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip); + btVector3 a1neg = -a1; + a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + btVector3 a2 = transB.getBasis() * m_rbBFrame.getOrigin(); + { + btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip); + a2.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + // set right hand side + btScalar linERP = (m_flags & BT_CONETWIST_FLAGS_LIN_ERP) ? m_linERP : info->erp; + btScalar k = info->fps * linERP; + int j; + for (j=0; j<3; j++) + { + info->m_constraintError[j*info->rowskip] = k * (a2[j] + transB.getOrigin()[j] - a1[j] - transA.getOrigin()[j]); + info->m_lowerLimit[j*info->rowskip] = -SIMD_INFINITY; + info->m_upperLimit[j*info->rowskip] = SIMD_INFINITY; + if(m_flags & BT_CONETWIST_FLAGS_LIN_CFM) + { + info->cfm[j*info->rowskip] = m_linCFM; + } + } + int row = 3; + int srow = row * info->rowskip; + btVector3 ax1; + // angular limits + if(m_solveSwingLimit) + { + btScalar *J1 = info->m_J1angularAxis; + btScalar *J2 = info->m_J2angularAxis; + if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) + { + btTransform trA = transA*m_rbAFrame; + btVector3 p = trA.getBasis().getColumn(1); + btVector3 q = trA.getBasis().getColumn(2); + int srow1 = srow + info->rowskip; + J1[srow+0] = p[0]; + J1[srow+1] = p[1]; + J1[srow+2] = p[2]; + J1[srow1+0] = q[0]; + J1[srow1+1] = q[1]; + J1[srow1+2] = q[2]; + J2[srow+0] = -p[0]; + J2[srow+1] = -p[1]; + J2[srow+2] = -p[2]; + J2[srow1+0] = -q[0]; + J2[srow1+1] = -q[1]; + J2[srow1+2] = -q[2]; + btScalar fact = info->fps * m_relaxationFactor; + info->m_constraintError[srow] = fact * m_swingAxis.dot(p); + info->m_constraintError[srow1] = fact * m_swingAxis.dot(q); + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + info->m_lowerLimit[srow1] = -SIMD_INFINITY; + info->m_upperLimit[srow1] = SIMD_INFINITY; + srow = srow1 + info->rowskip; + } + else + { + ax1 = m_swingAxis * m_relaxationFactor * m_relaxationFactor; + J1[srow+0] = ax1[0]; + J1[srow+1] = ax1[1]; + J1[srow+2] = ax1[2]; + J2[srow+0] = -ax1[0]; + J2[srow+1] = -ax1[1]; + J2[srow+2] = -ax1[2]; + btScalar k = info->fps * m_biasFactor; + + info->m_constraintError[srow] = k * m_swingCorrection; + if(m_flags & BT_CONETWIST_FLAGS_ANG_CFM) + { + info->cfm[srow] = m_angCFM; + } + // m_swingCorrection is always positive or 0 + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + srow += info->rowskip; + } + } + if(m_solveTwistLimit) + { + ax1 = m_twistAxis * m_relaxationFactor * m_relaxationFactor; + btScalar *J1 = info->m_J1angularAxis; + btScalar *J2 = info->m_J2angularAxis; + J1[srow+0] = ax1[0]; + J1[srow+1] = ax1[1]; + J1[srow+2] = ax1[2]; + J2[srow+0] = -ax1[0]; + J2[srow+1] = -ax1[1]; + J2[srow+2] = -ax1[2]; + btScalar k = info->fps * m_biasFactor; + info->m_constraintError[srow] = k * m_twistCorrection; + if(m_flags & BT_CONETWIST_FLAGS_ANG_CFM) + { + info->cfm[srow] = m_angCFM; + } + if(m_twistSpan > 0.0f) + { + + if(m_twistCorrection > 0.0f) + { + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + } + else + { + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + srow += info->rowskip; + } +} + + + +void btConeTwistConstraint::buildJacobian() +{ + if (m_useSolveConstraintObsolete) + { + m_appliedImpulse = btScalar(0.); + m_accTwistLimitImpulse = btScalar(0.); + m_accSwingLimitImpulse = btScalar(0.); + m_accMotorImpulse = btVector3(0.,0.,0.); + + if (!m_angularOnly) + { + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + btVector3 relPos = pivotBInW - pivotAInW; + + btVector3 normal[3]; + if (relPos.length2() > SIMD_EPSILON) + { + normal[0] = relPos.normalized(); + } + else + { + normal[0].setValue(btScalar(1.0),0,0); + } + + btPlaneSpace1(normal[0], normal[1], normal[2]); + + for (int i=0;i<3;i++) + { + new (&m_jac[i]) btJacobianEntry( + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + pivotAInW - m_rbA.getCenterOfMassPosition(), + pivotBInW - m_rbB.getCenterOfMassPosition(), + normal[i], + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); + } + } + + calcAngleInfo2(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld()); + } +} + + + +void btConeTwistConstraint::solveConstraintObsolete(btRigidBody& bodyA,btRigidBody& bodyB,btScalar timeStep) +{ + #ifndef __SPU__ + if (m_useSolveConstraintObsolete) + { + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + + btScalar tau = btScalar(0.3); + + //linear part + if (!m_angularOnly) + { + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + btVector3 vel1; + bodyA.internalGetVelocityInLocalPointObsolete(rel_pos1,vel1); + btVector3 vel2; + bodyB.internalGetVelocityInLocalPointObsolete(rel_pos2,vel2); + btVector3 vel = vel1 - vel2; + + for (int i=0;i<3;i++) + { + const btVector3& normal = m_jac[i].m_linearJointAxis; + btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); + + btScalar rel_vel; + rel_vel = normal.dot(vel); + //positional error (zeroth order error) + btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal + btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv; + m_appliedImpulse += impulse; + + btVector3 ftorqueAxis1 = rel_pos1.cross(normal); + btVector3 ftorqueAxis2 = rel_pos2.cross(normal); + bodyA.internalApplyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,impulse); + bodyB.internalApplyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-impulse); + + } + } + + // apply motor + if (m_bMotorEnabled) + { + // compute current and predicted transforms + btTransform trACur = m_rbA.getCenterOfMassTransform(); + btTransform trBCur = m_rbB.getCenterOfMassTransform(); + btVector3 omegaA; bodyA.internalGetAngularVelocity(omegaA); + btVector3 omegaB; bodyB.internalGetAngularVelocity(omegaB); + btTransform trAPred; trAPred.setIdentity(); + btVector3 zerovec(0,0,0); + btTransformUtil::integrateTransform( + trACur, zerovec, omegaA, timeStep, trAPred); + btTransform trBPred; trBPred.setIdentity(); + btTransformUtil::integrateTransform( + trBCur, zerovec, omegaB, timeStep, trBPred); + + // compute desired transforms in world + btTransform trPose(m_qTarget); + btTransform trABDes = m_rbBFrame * trPose * m_rbAFrame.inverse(); + btTransform trADes = trBPred * trABDes; + btTransform trBDes = trAPred * trABDes.inverse(); + + // compute desired omegas in world + btVector3 omegaADes, omegaBDes; + + btTransformUtil::calculateVelocity(trACur, trADes, timeStep, zerovec, omegaADes); + btTransformUtil::calculateVelocity(trBCur, trBDes, timeStep, zerovec, omegaBDes); + + // compute delta omegas + btVector3 dOmegaA = omegaADes - omegaA; + btVector3 dOmegaB = omegaBDes - omegaB; + + // compute weighted avg axis of dOmega (weighting based on inertias) + btVector3 axisA, axisB; + btScalar kAxisAInv = 0, kAxisBInv = 0; + + if (dOmegaA.length2() > SIMD_EPSILON) + { + axisA = dOmegaA.normalized(); + kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(axisA); + } + + if (dOmegaB.length2() > SIMD_EPSILON) + { + axisB = dOmegaB.normalized(); + kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(axisB); + } + + btVector3 avgAxis = kAxisAInv * axisA + kAxisBInv * axisB; + + static bool bDoTorque = true; + if (bDoTorque && avgAxis.length2() > SIMD_EPSILON) + { + avgAxis.normalize(); + kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(avgAxis); + kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(avgAxis); + btScalar kInvCombined = kAxisAInv + kAxisBInv; + + btVector3 impulse = (kAxisAInv * dOmegaA - kAxisBInv * dOmegaB) / + (kInvCombined * kInvCombined); + + if (m_maxMotorImpulse >= 0) + { + btScalar fMaxImpulse = m_maxMotorImpulse; + if (m_bNormalizedMotorStrength) + fMaxImpulse = fMaxImpulse/kAxisAInv; + + btVector3 newUnclampedAccImpulse = m_accMotorImpulse + impulse; + btScalar newUnclampedMag = newUnclampedAccImpulse.length(); + if (newUnclampedMag > fMaxImpulse) + { + newUnclampedAccImpulse.normalize(); + newUnclampedAccImpulse *= fMaxImpulse; + impulse = newUnclampedAccImpulse - m_accMotorImpulse; + } + m_accMotorImpulse += impulse; + } + + btScalar impulseMag = impulse.length(); + btVector3 impulseAxis = impulse / impulseMag; + + bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*impulseAxis, impulseMag); + bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*impulseAxis, -impulseMag); + + } + } + else if (m_damping > SIMD_EPSILON) // no motor: do a little damping + { + btVector3 angVelA; bodyA.internalGetAngularVelocity(angVelA); + btVector3 angVelB; bodyB.internalGetAngularVelocity(angVelB); + btVector3 relVel = angVelB - angVelA; + if (relVel.length2() > SIMD_EPSILON) + { + btVector3 relVelAxis = relVel.normalized(); + btScalar m_kDamping = btScalar(1.) / + (getRigidBodyA().computeAngularImpulseDenominator(relVelAxis) + + getRigidBodyB().computeAngularImpulseDenominator(relVelAxis)); + btVector3 impulse = m_damping * m_kDamping * relVel; + + btScalar impulseMag = impulse.length(); + btVector3 impulseAxis = impulse / impulseMag; + bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*impulseAxis, impulseMag); + bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*impulseAxis, -impulseMag); + } + } + + // joint limits + { + ///solve angular part + btVector3 angVelA; + bodyA.internalGetAngularVelocity(angVelA); + btVector3 angVelB; + bodyB.internalGetAngularVelocity(angVelB); + + // solve swing limit + if (m_solveSwingLimit) + { + btScalar amplitude = m_swingLimitRatio * m_swingCorrection*m_biasFactor/timeStep; + btScalar relSwingVel = (angVelB - angVelA).dot(m_swingAxis); + if (relSwingVel > 0) + amplitude += m_swingLimitRatio * relSwingVel * m_relaxationFactor; + btScalar impulseMag = amplitude * m_kSwing; + + // Clamp the accumulated impulse + btScalar temp = m_accSwingLimitImpulse; + m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0) ); + impulseMag = m_accSwingLimitImpulse - temp; + + btVector3 impulse = m_swingAxis * impulseMag; + + // don't let cone response affect twist + // (this can happen since body A's twist doesn't match body B's AND we use an elliptical cone limit) + { + btVector3 impulseTwistCouple = impulse.dot(m_twistAxisA) * m_twistAxisA; + btVector3 impulseNoTwistCouple = impulse - impulseTwistCouple; + impulse = impulseNoTwistCouple; + } + + impulseMag = impulse.length(); + btVector3 noTwistSwingAxis = impulse / impulseMag; + + bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*noTwistSwingAxis, impulseMag); + bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*noTwistSwingAxis, -impulseMag); + } + + + // solve twist limit + if (m_solveTwistLimit) + { + btScalar amplitude = m_twistLimitRatio * m_twistCorrection*m_biasFactor/timeStep; + btScalar relTwistVel = (angVelB - angVelA).dot( m_twistAxis ); + if (relTwistVel > 0) // only damp when moving towards limit (m_twistAxis flipping is important) + amplitude += m_twistLimitRatio * relTwistVel * m_relaxationFactor; + btScalar impulseMag = amplitude * m_kTwist; + + // Clamp the accumulated impulse + btScalar temp = m_accTwistLimitImpulse; + m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0) ); + impulseMag = m_accTwistLimitImpulse - temp; + + btVector3 impulse = m_twistAxis * impulseMag; + + bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*m_twistAxis,impulseMag); + bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*m_twistAxis,-impulseMag); + } + } + } +#else +btAssert(0); +#endif //__SPU__ +} + + + + +void btConeTwistConstraint::updateRHS(btScalar timeStep) +{ + (void)timeStep; + +} + + +#ifndef __SPU__ +void btConeTwistConstraint::calcAngleInfo() +{ + m_swingCorrection = btScalar(0.); + m_twistLimitSign = btScalar(0.); + m_solveTwistLimit = false; + m_solveSwingLimit = false; + + btVector3 b1Axis1,b1Axis2,b1Axis3; + btVector3 b2Axis1,b2Axis2; + + b1Axis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(0); + b2Axis1 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(0); + + btScalar swing1=btScalar(0.),swing2 = btScalar(0.); + + btScalar swx=btScalar(0.),swy = btScalar(0.); + btScalar thresh = btScalar(10.); + btScalar fact; + + // Get Frame into world space + if (m_swingSpan1 >= btScalar(0.05f)) + { + b1Axis2 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(1); + swx = b2Axis1.dot(b1Axis1); + swy = b2Axis1.dot(b1Axis2); + swing1 = btAtan2Fast(swy, swx); + fact = (swy*swy + swx*swx) * thresh * thresh; + fact = fact / (fact + btScalar(1.0)); + swing1 *= fact; + } + + if (m_swingSpan2 >= btScalar(0.05f)) + { + b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2); + swx = b2Axis1.dot(b1Axis1); + swy = b2Axis1.dot(b1Axis3); + swing2 = btAtan2Fast(swy, swx); + fact = (swy*swy + swx*swx) * thresh * thresh; + fact = fact / (fact + btScalar(1.0)); + swing2 *= fact; + } + + btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1*m_swingSpan1); + btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2*m_swingSpan2); + btScalar EllipseAngle = btFabs(swing1*swing1)* RMaxAngle1Sq + btFabs(swing2*swing2) * RMaxAngle2Sq; + + if (EllipseAngle > 1.0f) + { + m_swingCorrection = EllipseAngle-1.0f; + m_solveSwingLimit = true; + // Calculate necessary axis & factors + m_swingAxis = b2Axis1.cross(b1Axis2* b2Axis1.dot(b1Axis2) + b1Axis3* b2Axis1.dot(b1Axis3)); + m_swingAxis.normalize(); + btScalar swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f; + m_swingAxis *= swingAxisSign; + } + + // Twist limits + if (m_twistSpan >= btScalar(0.)) + { + btVector3 b2Axis2 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(1); + btQuaternion rotationArc = shortestArcQuat(b2Axis1,b1Axis1); + btVector3 TwistRef = quatRotate(rotationArc,b2Axis2); + btScalar twist = btAtan2Fast( TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2) ); + m_twistAngle = twist; + +// btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.); + btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? btScalar(1.0f) : btScalar(0.); + if (twist <= -m_twistSpan*lockedFreeFactor) + { + m_twistCorrection = -(twist + m_twistSpan); + m_solveTwistLimit = true; + m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; + m_twistAxis.normalize(); + m_twistAxis *= -1.0f; + } + else if (twist > m_twistSpan*lockedFreeFactor) + { + m_twistCorrection = (twist - m_twistSpan); + m_solveTwistLimit = true; + m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; + m_twistAxis.normalize(); + } + } +} +#endif //__SPU__ + +static btVector3 vTwist(1,0,0); // twist axis in constraint's space + + + +void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB) +{ + m_swingCorrection = btScalar(0.); + m_twistLimitSign = btScalar(0.); + m_solveTwistLimit = false; + m_solveSwingLimit = false; + // compute rotation of A wrt B (in constraint space) + if (m_bMotorEnabled && (!m_useSolveConstraintObsolete)) + { // it is assumed that setMotorTarget() was alredy called + // and motor target m_qTarget is within constraint limits + // TODO : split rotation to pure swing and pure twist + // compute desired transforms in world + btTransform trPose(m_qTarget); + btTransform trA = transA * m_rbAFrame; + btTransform trB = transB * m_rbBFrame; + btTransform trDeltaAB = trB * trPose * trA.inverse(); + btQuaternion qDeltaAB = trDeltaAB.getRotation(); + btVector3 swingAxis = btVector3(qDeltaAB.x(), qDeltaAB.y(), qDeltaAB.z()); + float swingAxisLen2 = swingAxis.length2(); + if(btFuzzyZero(swingAxisLen2)) + { + return; + } + m_swingAxis = swingAxis; + m_swingAxis.normalize(); + m_swingCorrection = qDeltaAB.getAngle(); + if(!btFuzzyZero(m_swingCorrection)) + { + m_solveSwingLimit = true; + } + return; + } + + + { + // compute rotation of A wrt B (in constraint space) + btQuaternion qA = transA.getRotation() * m_rbAFrame.getRotation(); + btQuaternion qB = transB.getRotation() * m_rbBFrame.getRotation(); + btQuaternion qAB = qB.inverse() * qA; + // split rotation into cone and twist + // (all this is done from B's perspective. Maybe I should be averaging axes...) + btVector3 vConeNoTwist = quatRotate(qAB, vTwist); vConeNoTwist.normalize(); + btQuaternion qABCone = shortestArcQuat(vTwist, vConeNoTwist); qABCone.normalize(); + btQuaternion qABTwist = qABCone.inverse() * qAB; qABTwist.normalize(); + + if (m_swingSpan1 >= m_fixThresh && m_swingSpan2 >= m_fixThresh) + { + btScalar swingAngle, swingLimit = 0; btVector3 swingAxis; + computeConeLimitInfo(qABCone, swingAngle, swingAxis, swingLimit); + + if (swingAngle > swingLimit * m_limitSoftness) + { + m_solveSwingLimit = true; + + // compute limit ratio: 0->1, where + // 0 == beginning of soft limit + // 1 == hard/real limit + m_swingLimitRatio = 1.f; + if (swingAngle < swingLimit && m_limitSoftness < 1.f - SIMD_EPSILON) + { + m_swingLimitRatio = (swingAngle - swingLimit * m_limitSoftness)/ + (swingLimit - swingLimit * m_limitSoftness); + } + + // swing correction tries to get back to soft limit + m_swingCorrection = swingAngle - (swingLimit * m_limitSoftness); + + // adjustment of swing axis (based on ellipse normal) + adjustSwingAxisToUseEllipseNormal(swingAxis); + + // Calculate necessary axis & factors + m_swingAxis = quatRotate(qB, -swingAxis); + + m_twistAxisA.setValue(0,0,0); + + m_kSwing = btScalar(1.) / + (computeAngularImpulseDenominator(m_swingAxis,invInertiaWorldA) + + computeAngularImpulseDenominator(m_swingAxis,invInertiaWorldB)); + } + } + else + { + // you haven't set any limits; + // or you're trying to set at least one of the swing limits too small. (if so, do you really want a conetwist constraint?) + // anyway, we have either hinge or fixed joint + btVector3 ivA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0); + btVector3 jvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1); + btVector3 kvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(2); + btVector3 ivB = transB.getBasis() * m_rbBFrame.getBasis().getColumn(0); + btVector3 target; + btScalar x = ivB.dot(ivA); + btScalar y = ivB.dot(jvA); + btScalar z = ivB.dot(kvA); + if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) + { // fixed. We'll need to add one more row to constraint + if((!btFuzzyZero(y)) || (!(btFuzzyZero(z)))) + { + m_solveSwingLimit = true; + m_swingAxis = -ivB.cross(ivA); + } + } + else + { + if(m_swingSpan1 < m_fixThresh) + { // hinge around Y axis + if(!(btFuzzyZero(y))) + { + m_solveSwingLimit = true; + if(m_swingSpan2 >= m_fixThresh) + { + y = btScalar(0.f); + btScalar span2 = btAtan2(z, x); + if(span2 > m_swingSpan2) + { + x = btCos(m_swingSpan2); + z = btSin(m_swingSpan2); + } + else if(span2 < -m_swingSpan2) + { + x = btCos(m_swingSpan2); + z = -btSin(m_swingSpan2); + } + } + } + } + else + { // hinge around Z axis + if(!btFuzzyZero(z)) + { + m_solveSwingLimit = true; + if(m_swingSpan1 >= m_fixThresh) + { + z = btScalar(0.f); + btScalar span1 = btAtan2(y, x); + if(span1 > m_swingSpan1) + { + x = btCos(m_swingSpan1); + y = btSin(m_swingSpan1); + } + else if(span1 < -m_swingSpan1) + { + x = btCos(m_swingSpan1); + y = -btSin(m_swingSpan1); + } + } + } + } + target[0] = x * ivA[0] + y * jvA[0] + z * kvA[0]; + target[1] = x * ivA[1] + y * jvA[1] + z * kvA[1]; + target[2] = x * ivA[2] + y * jvA[2] + z * kvA[2]; + target.normalize(); + m_swingAxis = -ivB.cross(target); + m_swingCorrection = m_swingAxis.length(); + m_swingAxis.normalize(); + } + } + + if (m_twistSpan >= btScalar(0.f)) + { + btVector3 twistAxis; + computeTwistLimitInfo(qABTwist, m_twistAngle, twistAxis); + + if (m_twistAngle > m_twistSpan*m_limitSoftness) + { + m_solveTwistLimit = true; + + m_twistLimitRatio = 1.f; + if (m_twistAngle < m_twistSpan && m_limitSoftness < 1.f - SIMD_EPSILON) + { + m_twistLimitRatio = (m_twistAngle - m_twistSpan * m_limitSoftness)/ + (m_twistSpan - m_twistSpan * m_limitSoftness); + } + + // twist correction tries to get back to soft limit + m_twistCorrection = m_twistAngle - (m_twistSpan * m_limitSoftness); + + m_twistAxis = quatRotate(qB, -twistAxis); + + m_kTwist = btScalar(1.) / + (computeAngularImpulseDenominator(m_twistAxis,invInertiaWorldA) + + computeAngularImpulseDenominator(m_twistAxis,invInertiaWorldB)); + } + + if (m_solveSwingLimit) + m_twistAxisA = quatRotate(qA, -twistAxis); + } + else + { + m_twistAngle = btScalar(0.f); + } + } +} + + + +// given a cone rotation in constraint space, (pre: twist must already be removed) +// this method computes its corresponding swing angle and axis. +// more interestingly, it computes the cone/swing limit (angle) for this cone "pose". +void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone, + btScalar& swingAngle, // out + btVector3& vSwingAxis, // out + btScalar& swingLimit) // out +{ + swingAngle = qCone.getAngle(); + if (swingAngle > SIMD_EPSILON) + { + vSwingAxis = btVector3(qCone.x(), qCone.y(), qCone.z()); + vSwingAxis.normalize(); + if (fabs(vSwingAxis.x()) > SIMD_EPSILON) + { + // non-zero twist?! this should never happen. + int wtf = 0; wtf = wtf; + } + + // Compute limit for given swing. tricky: + // Given a swing axis, we're looking for the intersection with the bounding cone ellipse. + // (Since we're dealing with angles, this ellipse is embedded on the surface of a sphere.) + + // For starters, compute the direction from center to surface of ellipse. + // This is just the perpendicular (ie. rotate 2D vector by PI/2) of the swing axis. + // (vSwingAxis is the cone rotation (in z,y); change vars and rotate to (x,y) coords.) + btScalar xEllipse = vSwingAxis.y(); + btScalar yEllipse = -vSwingAxis.z(); + + // Now, we use the slope of the vector (using x/yEllipse) and find the length + // of the line that intersects the ellipse: + // x^2 y^2 + // --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits) + // a^2 b^2 + // Do the math and it should be clear. + + swingLimit = m_swingSpan1; // if xEllipse == 0, we have a pure vSwingAxis.z rotation: just use swingspan1 + if (fabs(xEllipse) > SIMD_EPSILON) + { + btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse); + btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2); + norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1); + btScalar swingLimit2 = (1 + surfaceSlope2) / norm; + swingLimit = sqrt(swingLimit2); + } + + // test! + /*swingLimit = m_swingSpan2; + if (fabs(vSwingAxis.z()) > SIMD_EPSILON) + { + btScalar mag_2 = m_swingSpan1*m_swingSpan1 + m_swingSpan2*m_swingSpan2; + btScalar sinphi = m_swingSpan2 / sqrt(mag_2); + btScalar phi = asin(sinphi); + btScalar theta = atan2(fabs(vSwingAxis.y()),fabs(vSwingAxis.z())); + btScalar alpha = 3.14159f - theta - phi; + btScalar sinalpha = sin(alpha); + swingLimit = m_swingSpan1 * sinphi/sinalpha; + }*/ + } + else if (swingAngle < 0) + { + // this should never happen! + int wtf = 0; wtf = wtf; + } +} + +btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const +{ + // compute x/y in ellipse using cone angle (0 -> 2*PI along surface of cone) + btScalar xEllipse = btCos(fAngleInRadians); + btScalar yEllipse = btSin(fAngleInRadians); + + // Use the slope of the vector (using x/yEllipse) and find the length + // of the line that intersects the ellipse: + // x^2 y^2 + // --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits) + // a^2 b^2 + // Do the math and it should be clear. + + float swingLimit = m_swingSpan1; // if xEllipse == 0, just use axis b (1) + if (fabs(xEllipse) > SIMD_EPSILON) + { + btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse); + btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2); + norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1); + btScalar swingLimit2 = (1 + surfaceSlope2) / norm; + swingLimit = sqrt(swingLimit2); + } + + // convert into point in constraint space: + // note: twist is x-axis, swing 1 and 2 are along the z and y axes respectively + btVector3 vSwingAxis(0, xEllipse, -yEllipse); + btQuaternion qSwing(vSwingAxis, swingLimit); + btVector3 vPointInConstraintSpace(fLength,0,0); + return quatRotate(qSwing, vPointInConstraintSpace); +} + +// given a twist rotation in constraint space, (pre: cone must already be removed) +// this method computes its corresponding angle and axis. +void btConeTwistConstraint::computeTwistLimitInfo(const btQuaternion& qTwist, + btScalar& twistAngle, // out + btVector3& vTwistAxis) // out +{ + btQuaternion qMinTwist = qTwist; + twistAngle = qTwist.getAngle(); + + if (twistAngle > SIMD_PI) // long way around. flip quat and recalculate. + { + qMinTwist = -(qTwist); + twistAngle = qMinTwist.getAngle(); + } + if (twistAngle < 0) + { + // this should never happen + int wtf = 0; wtf = wtf; + } + + vTwistAxis = btVector3(qMinTwist.x(), qMinTwist.y(), qMinTwist.z()); + if (twistAngle > SIMD_EPSILON) + vTwistAxis.normalize(); +} + + +void btConeTwistConstraint::adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const +{ + // the swing axis is computed as the "twist-free" cone rotation, + // but the cone limit is not circular, but elliptical (if swingspan1 != swingspan2). + // so, if we're outside the limits, the closest way back inside the cone isn't + // along the vector back to the center. better (and more stable) to use the ellipse normal. + + // convert swing axis to direction from center to surface of ellipse + // (ie. rotate 2D vector by PI/2) + btScalar y = -vSwingAxis.z(); + btScalar z = vSwingAxis.y(); + + // do the math... + if (fabs(z) > SIMD_EPSILON) // avoid division by 0. and we don't need an update if z == 0. + { + // compute gradient/normal of ellipse surface at current "point" + btScalar grad = y/z; + grad *= m_swingSpan2 / m_swingSpan1; + + // adjust y/z to represent normal at point (instead of vector to point) + if (y > 0) + y = fabs(grad * z); + else + y = -fabs(grad * z); + + // convert ellipse direction back to swing axis + vSwingAxis.setZ(-y); + vSwingAxis.setY( z); + vSwingAxis.normalize(); + } +} + + + +void btConeTwistConstraint::setMotorTarget(const btQuaternion &q) +{ + btTransform trACur = m_rbA.getCenterOfMassTransform(); + btTransform trBCur = m_rbB.getCenterOfMassTransform(); + btTransform trABCur = trBCur.inverse() * trACur; + btQuaternion qABCur = trABCur.getRotation(); + btTransform trConstraintCur = (trBCur * m_rbBFrame).inverse() * (trACur * m_rbAFrame); + btQuaternion qConstraintCur = trConstraintCur.getRotation(); + + btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * q * m_rbAFrame.getRotation(); + setMotorTargetInConstraintSpace(qConstraint); +} + + +void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion &q) +{ + m_qTarget = q; + + // clamp motor target to within limits + { + btScalar softness = 1.f;//m_limitSoftness; + + // split into twist and cone + btVector3 vTwisted = quatRotate(m_qTarget, vTwist); + btQuaternion qTargetCone = shortestArcQuat(vTwist, vTwisted); qTargetCone.normalize(); + btQuaternion qTargetTwist = qTargetCone.inverse() * m_qTarget; qTargetTwist.normalize(); + + // clamp cone + if (m_swingSpan1 >= btScalar(0.05f) && m_swingSpan2 >= btScalar(0.05f)) + { + btScalar swingAngle, swingLimit; btVector3 swingAxis; + computeConeLimitInfo(qTargetCone, swingAngle, swingAxis, swingLimit); + + if (fabs(swingAngle) > SIMD_EPSILON) + { + if (swingAngle > swingLimit*softness) + swingAngle = swingLimit*softness; + else if (swingAngle < -swingLimit*softness) + swingAngle = -swingLimit*softness; + qTargetCone = btQuaternion(swingAxis, swingAngle); + } + } + + // clamp twist + if (m_twistSpan >= btScalar(0.05f)) + { + btScalar twistAngle; btVector3 twistAxis; + computeTwistLimitInfo(qTargetTwist, twistAngle, twistAxis); + + if (fabs(twistAngle) > SIMD_EPSILON) + { + // eddy todo: limitSoftness used here??? + if (twistAngle > m_twistSpan*softness) + twistAngle = m_twistSpan*softness; + else if (twistAngle < -m_twistSpan*softness) + twistAngle = -m_twistSpan*softness; + qTargetTwist = btQuaternion(twistAxis, twistAngle); + } + } + + m_qTarget = qTargetCone * qTargetTwist; + } +} + +///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). +///If no axis is provided, it uses the default axis for this constraint. +void btConeTwistConstraint::setParam(int num, btScalar value, int axis) +{ + switch(num) + { + case BT_CONSTRAINT_ERP : + case BT_CONSTRAINT_STOP_ERP : + if((axis >= 0) && (axis < 3)) + { + m_linERP = value; + m_flags |= BT_CONETWIST_FLAGS_LIN_ERP; + } + else + { + m_biasFactor = value; + } + break; + case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_STOP_CFM : + if((axis >= 0) && (axis < 3)) + { + m_linCFM = value; + m_flags |= BT_CONETWIST_FLAGS_LIN_CFM; + } + else + { + m_angCFM = value; + m_flags |= BT_CONETWIST_FLAGS_ANG_CFM; + } + break; + default: + btAssertConstrParams(0); + break; + } +} + +///return the local value of parameter +btScalar btConeTwistConstraint::getParam(int num, int axis) const +{ + btScalar retVal = 0; + switch(num) + { + case BT_CONSTRAINT_ERP : + case BT_CONSTRAINT_STOP_ERP : + if((axis >= 0) && (axis < 3)) + { + btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_ERP); + retVal = m_linERP; + } + else if((axis >= 3) && (axis < 6)) + { + retVal = m_biasFactor; + } + else + { + btAssertConstrParams(0); + } + break; + case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_STOP_CFM : + if((axis >= 0) && (axis < 3)) + { + btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_CFM); + retVal = m_linCFM; + } + else if((axis >= 3) && (axis < 6)) + { + btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_ANG_CFM); + retVal = m_angCFM; + } + else + { + btAssertConstrParams(0); + } + break; + default : + btAssertConstrParams(0); + } + return retVal; +} + + +void btConeTwistConstraint::setFrames(const btTransform & frameA, const btTransform & frameB) +{ + m_rbAFrame = frameA; + m_rbBFrame = frameB; + buildJacobian(); + //calculateTransforms(); +} + + + + diff --git a/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h new file mode 100644 index 0000000..868e62f --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h @@ -0,0 +1,346 @@ +/* +Bullet Continuous Collision Detection and Physics Library +btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios + +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. + +Written by: Marcus Hennix +*/ + + + +/* +Overview: + +btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc). +It is a fixed translation, 3 degree-of-freedom (DOF) rotational "joint". +It divides the 3 rotational DOFs into swing (movement within a cone) and twist. +Swing is divided into swing1 and swing2 which can have different limits, giving an elliptical shape. +(Note: the cone's base isn't flat, so this ellipse is "embedded" on the surface of a sphere.) + +In the contraint's frame of reference: +twist is along the x-axis, +and swing 1 and 2 are along the z and y axes respectively. +*/ + + + +#ifndef BT_CONETWISTCONSTRAINT_H +#define BT_CONETWISTCONSTRAINT_H + +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" + +class btRigidBody; + +enum btConeTwistFlags +{ + BT_CONETWIST_FLAGS_LIN_CFM = 1, + BT_CONETWIST_FLAGS_LIN_ERP = 2, + BT_CONETWIST_FLAGS_ANG_CFM = 4 +}; + +///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc) +class btConeTwistConstraint : public btTypedConstraint +{ +#ifdef IN_PARALLELL_SOLVER +public: +#endif + btJacobianEntry m_jac[3]; //3 orthogonal linear constraints + + btTransform m_rbAFrame; + btTransform m_rbBFrame; + + btScalar m_limitSoftness; + btScalar m_biasFactor; + btScalar m_relaxationFactor; + + btScalar m_damping; + + btScalar m_swingSpan1; + btScalar m_swingSpan2; + btScalar m_twistSpan; + + btScalar m_fixThresh; + + btVector3 m_swingAxis; + btVector3 m_twistAxis; + + btScalar m_kSwing; + btScalar m_kTwist; + + btScalar m_twistLimitSign; + btScalar m_swingCorrection; + btScalar m_twistCorrection; + + btScalar m_twistAngle; + + btScalar m_accSwingLimitImpulse; + btScalar m_accTwistLimitImpulse; + + bool m_angularOnly; + bool m_solveTwistLimit; + bool m_solveSwingLimit; + + bool m_useSolveConstraintObsolete; + + // not yet used... + btScalar m_swingLimitRatio; + btScalar m_twistLimitRatio; + btVector3 m_twistAxisA; + + // motor + bool m_bMotorEnabled; + bool m_bNormalizedMotorStrength; + btQuaternion m_qTarget; + btScalar m_maxMotorImpulse; + btVector3 m_accMotorImpulse; + + // parameters + int m_flags; + btScalar m_linCFM; + btScalar m_linERP; + btScalar m_angCFM; + +protected: + + void init(); + + void computeConeLimitInfo(const btQuaternion& qCone, // in + btScalar& swingAngle, btVector3& vSwingAxis, btScalar& swingLimit); // all outs + + void computeTwistLimitInfo(const btQuaternion& qTwist, // in + btScalar& twistAngle, btVector3& vTwistAxis); // all outs + + void adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const; + + +public: + + btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,const btTransform& rbAFrame, const btTransform& rbBFrame); + + btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame); + + virtual void buildJacobian(); + + virtual void getInfo1 (btConstraintInfo1* info); + + void getInfo1NonVirtual(btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB); + + virtual void solveConstraintObsolete(btRigidBody& bodyA,btRigidBody& bodyB,btScalar timeStep); + + void updateRHS(btScalar timeStep); + + + const btRigidBody& getRigidBodyA() const + { + return m_rbA; + } + const btRigidBody& getRigidBodyB() const + { + return m_rbB; + } + + void setAngularOnly(bool angularOnly) + { + m_angularOnly = angularOnly; + } + + void setLimit(int limitIndex,btScalar limitValue) + { + switch (limitIndex) + { + case 3: + { + m_twistSpan = limitValue; + break; + } + case 4: + { + m_swingSpan2 = limitValue; + break; + } + case 5: + { + m_swingSpan1 = limitValue; + break; + } + default: + { + } + }; + } + + // setLimit(), a few notes: + // _softness: + // 0->1, recommend ~0.8->1. + // describes % of limits where movement is free. + // beyond this softness %, the limit is gradually enforced until the "hard" (1.0) limit is reached. + // _biasFactor: + // 0->1?, recommend 0.3 +/-0.3 or so. + // strength with which constraint resists zeroth order (angular, not angular velocity) limit violation. + // __relaxationFactor: + // 0->1, recommend to stay near 1. + // the lower the value, the less the constraint will fight velocities which violate the angular limits. + void setLimit(btScalar _swingSpan1,btScalar _swingSpan2,btScalar _twistSpan, btScalar _softness = 1.f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) + { + m_swingSpan1 = _swingSpan1; + m_swingSpan2 = _swingSpan2; + m_twistSpan = _twistSpan; + + m_limitSoftness = _softness; + m_biasFactor = _biasFactor; + m_relaxationFactor = _relaxationFactor; + } + + const btTransform& getAFrame() { return m_rbAFrame; }; + const btTransform& getBFrame() { return m_rbBFrame; }; + + inline int getSolveTwistLimit() + { + return m_solveTwistLimit; + } + + inline int getSolveSwingLimit() + { + return m_solveTwistLimit; + } + + inline btScalar getTwistLimitSign() + { + return m_twistLimitSign; + } + + void calcAngleInfo(); + void calcAngleInfo2(const btTransform& transA, const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB); + + inline btScalar getSwingSpan1() + { + return m_swingSpan1; + } + inline btScalar getSwingSpan2() + { + return m_swingSpan2; + } + inline btScalar getTwistSpan() + { + return m_twistSpan; + } + inline btScalar getTwistAngle() + { + return m_twistAngle; + } + bool isPastSwingLimit() { return m_solveSwingLimit; } + + void setDamping(btScalar damping) { m_damping = damping; } + + void enableMotor(bool b) { m_bMotorEnabled = b; } + void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = false; } + void setMaxMotorImpulseNormalized(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = true; } + + btScalar getFixThresh() { return m_fixThresh; } + void setFixThresh(btScalar fixThresh) { m_fixThresh = fixThresh; } + + // setMotorTarget: + // q: the desired rotation of bodyA wrt bodyB. + // note: if q violates the joint limits, the internal target is clamped to avoid conflicting impulses (very bad for stability) + // note: don't forget to enableMotor() + void setMotorTarget(const btQuaternion &q); + + // same as above, but q is the desired rotation of frameA wrt frameB in constraint space + void setMotorTargetInConstraintSpace(const btQuaternion &q); + + btVector3 GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const; + + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///If no axis is provided, it uses the default axis for this constraint. + virtual void setParam(int num, btScalar value, int axis = -1); + + virtual void setFrames(const btTransform& frameA, const btTransform& frameB); + + const btTransform& getFrameOffsetA() const + { + return m_rbAFrame; + } + + const btTransform& getFrameOffsetB() const + { + return m_rbBFrame; + } + + + ///return the local value of parameter + virtual btScalar getParam(int num, int axis = -1) const; + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btConeTwistConstraintData +{ + btTypedConstraintData m_typeConstraintData; + btTransformFloatData m_rbAFrame; + btTransformFloatData m_rbBFrame; + + //limits + float m_swingSpan1; + float m_swingSpan2; + float m_twistSpan; + float m_limitSoftness; + float m_biasFactor; + float m_relaxationFactor; + + float m_damping; + + char m_pad[4]; + +}; + + + +SIMD_FORCE_INLINE int btConeTwistConstraint::calculateSerializeBufferSize() const +{ + return sizeof(btConeTwistConstraintData); + +} + + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btConeTwistConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btConeTwistConstraintData* cone = (btConeTwistConstraintData*) dataBuffer; + btTypedConstraint::serialize(&cone->m_typeConstraintData,serializer); + + m_rbAFrame.serializeFloat(cone->m_rbAFrame); + m_rbBFrame.serializeFloat(cone->m_rbBFrame); + + cone->m_swingSpan1 = float(m_swingSpan1); + cone->m_swingSpan2 = float(m_swingSpan2); + cone->m_twistSpan = float(m_twistSpan); + cone->m_limitSoftness = float(m_limitSoftness); + cone->m_biasFactor = float(m_biasFactor); + cone->m_relaxationFactor = float(m_relaxationFactor); + cone->m_damping = float(m_damping); + + return "btConeTwistConstraintData"; +} + + +#endif //BT_CONETWISTCONSTRAINT_H diff --git a/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h new file mode 100644 index 0000000..6f67310 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h @@ -0,0 +1,52 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONSTRAINT_SOLVER_H +#define BT_CONSTRAINT_SOLVER_H + +#include "LinearMath/btScalar.h" + +class btPersistentManifold; +class btRigidBody; +class btCollisionObject; +class btTypedConstraint; +struct btContactSolverInfo; +struct btBroadphaseProxy; +class btIDebugDraw; +class btStackAlloc; +class btDispatcher; +/// btConstraintSolver provides solver interface +class btConstraintSolver +{ + +public: + + virtual ~btConstraintSolver() {} + + virtual void prepareSolve (int /* numBodies */, int /* numManifolds */) {;} + + ///solve a group of constraints + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher) = 0; + + virtual void allSolved (const btContactSolverInfo& /* info */,class btIDebugDraw* /* debugDrawer */, btStackAlloc* /* stackAlloc */) {;} + + ///clear internal cached data and reset random seed + virtual void reset() = 0; +}; + + + + +#endif //BT_CONSTRAINT_SOLVER_H diff --git a/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp new file mode 100644 index 0000000..8885918 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp @@ -0,0 +1,178 @@ +/* +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 "btContactConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btContactSolverInfo.h" +#include "LinearMath/btMinMax.h" +#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" + + + +btContactConstraint::btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB) +:btTypedConstraint(CONTACT_CONSTRAINT_TYPE,rbA,rbB), + m_contactManifold(*contactManifold) +{ + +} + +btContactConstraint::~btContactConstraint() +{ + +} + +void btContactConstraint::setContactManifold(btPersistentManifold* contactManifold) +{ + m_contactManifold = *contactManifold; +} + +void btContactConstraint::getInfo1 (btConstraintInfo1* info) +{ + +} + +void btContactConstraint::getInfo2 (btConstraintInfo2* info) +{ + +} + +void btContactConstraint::buildJacobian() +{ + +} + + + + + +#include "btContactConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btContactSolverInfo.h" +#include "LinearMath/btMinMax.h" +#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" + + + +//response between two dynamic objects without friction, assuming 0 penetration depth +btScalar resolveSingleCollision( + btRigidBody* body1, + btCollisionObject* colObj2, + const btVector3& contactPositionWorld, + const btVector3& contactNormalOnB, + const btContactSolverInfo& solverInfo, + btScalar distance) +{ + btRigidBody* body2 = btRigidBody::upcast(colObj2); + + + const btVector3& normal = contactNormalOnB; + + btVector3 rel_pos1 = contactPositionWorld - body1->getWorldTransform().getOrigin(); + btVector3 rel_pos2 = contactPositionWorld - colObj2->getWorldTransform().getOrigin(); + + btVector3 vel1 = body1->getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2? body2->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); + btVector3 vel = vel1 - vel2; + btScalar rel_vel; + rel_vel = normal.dot(vel); + + btScalar combinedRestitution = body1->getRestitution() * colObj2->getRestitution(); + btScalar restitution = combinedRestitution* -rel_vel; + + btScalar positionalError = solverInfo.m_erp *-distance /solverInfo.m_timeStep ; + btScalar velocityError = -(1.0f + restitution) * rel_vel;// * damping; + btScalar denom0 = body1->computeImpulseDenominator(contactPositionWorld,normal); + btScalar denom1 = body2? body2->computeImpulseDenominator(contactPositionWorld,normal) : 0.f; + btScalar relaxation = 1.f; + btScalar jacDiagABInv = relaxation/(denom0+denom1); + + btScalar penetrationImpulse = positionalError * jacDiagABInv; + btScalar velocityImpulse = velocityError * jacDiagABInv; + + btScalar normalImpulse = penetrationImpulse+velocityImpulse; + normalImpulse = 0.f > normalImpulse ? 0.f: normalImpulse; + + body1->applyImpulse(normal*(normalImpulse), rel_pos1); + if (body2) + body2->applyImpulse(-normal*(normalImpulse), rel_pos2); + + return normalImpulse; +} + + +//bilateral constraint between two dynamic objects +void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, + btRigidBody& body2, const btVector3& pos2, + btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep) +{ + (void)timeStep; + (void)distance; + + + btScalar normalLenSqr = normal.length2(); + btAssert(btFabs(normalLenSqr) < btScalar(1.1)); + if (normalLenSqr > btScalar(1.1)) + { + impulse = btScalar(0.); + return; + } + btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition(); + btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition(); + //this jacobian entry could be re-used for all iterations + + btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + + btJacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(), + body2.getCenterOfMassTransform().getBasis().transpose(), + rel_pos1,rel_pos2,normal,body1.getInvInertiaDiagLocal(),body1.getInvMass(), + body2.getInvInertiaDiagLocal(),body2.getInvMass()); + + btScalar jacDiagAB = jac.getDiagonal(); + btScalar jacDiagABInv = btScalar(1.) / jacDiagAB; + + btScalar rel_vel = jac.getRelativeVelocity( + body1.getLinearVelocity(), + body1.getCenterOfMassTransform().getBasis().transpose() * body1.getAngularVelocity(), + body2.getLinearVelocity(), + body2.getCenterOfMassTransform().getBasis().transpose() * body2.getAngularVelocity()); + btScalar a; + a=jacDiagABInv; + + + rel_vel = normal.dot(vel); + + //todo: move this into proper structure + btScalar contactDamping = btScalar(0.2); + +#ifdef ONLY_USE_LINEAR_MASS + btScalar massTerm = btScalar(1.) / (body1.getInvMass() + body2.getInvMass()); + impulse = - contactDamping * rel_vel * massTerm; +#else + btScalar velocityImpulse = -contactDamping * rel_vel * jacDiagABInv; + impulse = velocityImpulse; +#endif +} + + + + diff --git a/src/BulletDynamics/ConstraintSolver/btContactConstraint.h b/src/BulletDynamics/ConstraintSolver/btContactConstraint.h new file mode 100644 index 0000000..477c79d --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btContactConstraint.h @@ -0,0 +1,71 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONTACT_CONSTRAINT_H +#define BT_CONTACT_CONSTRAINT_H + +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" + +///btContactConstraint can be automatically created to solve contact constraints using the unified btTypedConstraint interface +ATTRIBUTE_ALIGNED16(class) btContactConstraint : public btTypedConstraint +{ +protected: + + btPersistentManifold m_contactManifold; + +public: + + + btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB); + + void setContactManifold(btPersistentManifold* contactManifold); + + btPersistentManifold* getContactManifold() + { + return &m_contactManifold; + } + + const btPersistentManifold* getContactManifold() const + { + return &m_contactManifold; + } + + virtual ~btContactConstraint(); + + virtual void getInfo1 (btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + ///obsolete methods + virtual void buildJacobian(); + + +}; + +///very basic collision resolution without friction +btScalar resolveSingleCollision(btRigidBody* body1, class btCollisionObject* colObj2, const btVector3& contactPositionWorld,const btVector3& contactNormalOnB, const struct btContactSolverInfo& solverInfo,btScalar distance); + + +///resolveSingleBilateral is an obsolete methods used for vehicle friction between two dynamic objects +void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, + btRigidBody& body2, const btVector3& pos2, + btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep); + + + +#endif //BT_CONTACT_CONSTRAINT_H diff --git a/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h new file mode 100644 index 0000000..6204cb3 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h @@ -0,0 +1,87 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONTACT_SOLVER_INFO +#define BT_CONTACT_SOLVER_INFO + +enum btSolverMode +{ + SOLVER_RANDMIZE_ORDER = 1, + SOLVER_FRICTION_SEPARATE = 2, + SOLVER_USE_WARMSTARTING = 4, + SOLVER_USE_FRICTION_WARMSTARTING = 8, + SOLVER_USE_2_FRICTION_DIRECTIONS = 16, + SOLVER_ENABLE_FRICTION_DIRECTION_CACHING = 32, + SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION = 64, + SOLVER_CACHE_FRIENDLY = 128, + SOLVER_SIMD = 256, //enabled for Windows, the solver innerloop is branchless SIMD, 40% faster than FPU/scalar version + SOLVER_CUDA = 512 //will be open sourced during Game Developers Conference 2009. Much faster. +}; + +struct btContactSolverInfoData +{ + + + btScalar m_tau; + btScalar m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'. + btScalar m_friction; + btScalar m_timeStep; + btScalar m_restitution; + int m_numIterations; + btScalar m_maxErrorReduction; + btScalar m_sor; + btScalar m_erp;//used as Baumgarte factor + btScalar m_erp2;//used in Split Impulse + btScalar m_globalCfm;//constraint force mixing + int m_splitImpulse; + btScalar m_splitImpulsePenetrationThreshold; + btScalar m_linearSlop; + btScalar m_warmstartingFactor; + + int m_solverMode; + int m_restingContactRestitutionThreshold; + int m_minimumSolverBatchSize; + + +}; + +struct btContactSolverInfo : public btContactSolverInfoData +{ + + + + inline btContactSolverInfo() + { + m_tau = btScalar(0.6); + m_damping = btScalar(1.0); + m_friction = btScalar(0.3); + m_restitution = btScalar(0.); + m_maxErrorReduction = btScalar(20.); + m_numIterations = 10; + m_erp = btScalar(0.2); + m_erp2 = btScalar(0.1); + m_globalCfm = btScalar(0.); + m_sor = btScalar(1.); + m_splitImpulse = false; + m_splitImpulsePenetrationThreshold = -0.02f; + m_linearSlop = btScalar(0.0); + m_warmstartingFactor=btScalar(0.85); + m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD;// | SOLVER_RANDMIZE_ORDER; + m_restingContactRestitutionThreshold = 2;//resting contact lifetime threshold to disable restitution + m_minimumSolverBatchSize = 128; //try to combine islands until the amount of constraints reaches this limit + } +}; + +#endif //BT_CONTACT_SOLVER_INFO diff --git a/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp new file mode 100644 index 0000000..8ff9940 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp @@ -0,0 +1,1078 @@ +/* +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. +*/ +/* +2007-09-09 +Refactored by Francisco Le?n +email: projectileman@yahoo.com +http://gimpact.sf.net +*/ + +#include "btGeneric6DofConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" +#include "LinearMath/btTransformUtil.h" +#include + + + +#define D6_USE_OBSOLETE_METHOD false +#define D6_USE_FRAME_OFFSET true + + + + + + +btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) +: btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB) +, m_frameInA(frameInA) +, m_frameInB(frameInB), +m_useLinearReferenceFrameA(useLinearReferenceFrameA), +m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET), +m_flags(0), +m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD) +{ + calculateTransforms(); +} + + + +btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB) + : btTypedConstraint(D6_CONSTRAINT_TYPE, getFixedBody(), rbB), + m_frameInB(frameInB), + m_useLinearReferenceFrameA(useLinearReferenceFrameB), + m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET), + m_flags(0), + m_useSolveConstraintObsolete(false) +{ + ///not providing rigidbody A means implicitly using worldspace for body A + m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB; + calculateTransforms(); +} + + + + +#define GENERIC_D6_DISABLE_WARMSTARTING 1 + + + +btScalar btGetMatrixElem(const btMatrix3x3& mat, int index); +btScalar btGetMatrixElem(const btMatrix3x3& mat, int index) +{ + int i = index%3; + int j = index/3; + return mat[i][j]; +} + + + +///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html +bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz); +bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) +{ + // // rot = cy*cz -cy*sz sy + // // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx + // // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy + // + + btScalar fi = btGetMatrixElem(mat,2); + if (fi < btScalar(1.0f)) + { + if (fi > btScalar(-1.0f)) + { + xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8)); + xyz[1] = btAsin(btGetMatrixElem(mat,2)); + xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0)); + return true; + } + else + { + // WARNING. Not unique. XA - ZA = -atan2(r10,r11) + xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); + xyz[1] = -SIMD_HALF_PI; + xyz[2] = btScalar(0.0); + return false; + } + } + else + { + // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) + xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); + xyz[1] = SIMD_HALF_PI; + xyz[2] = 0.0; + } + return false; +} + +//////////////////////////// btRotationalLimitMotor //////////////////////////////////// + +int btRotationalLimitMotor::testLimitValue(btScalar test_value) +{ + if(m_loLimit>m_hiLimit) + { + m_currentLimit = 0;//Free from violation + return 0; + } + if (test_value < m_loLimit) + { + m_currentLimit = 1;//low limit violation + m_currentLimitError = test_value - m_loLimit; + if(m_currentLimitError>SIMD_PI) + m_currentLimitError-=SIMD_2_PI; + else if(m_currentLimitError<-SIMD_PI) + m_currentLimitError+=SIMD_2_PI; + return 1; + } + else if (test_value> m_hiLimit) + { + m_currentLimit = 2;//High limit violation + m_currentLimitError = test_value - m_hiLimit; + if(m_currentLimitError>SIMD_PI) + m_currentLimitError-=SIMD_2_PI; + else if(m_currentLimitError<-SIMD_PI) + m_currentLimitError+=SIMD_2_PI; + return 2; + }; + + m_currentLimit = 0;//Free from violation + return 0; + +} + + + +btScalar btRotationalLimitMotor::solveAngularLimits( + btScalar timeStep,btVector3& axis,btScalar jacDiagABInv, + btRigidBody * body0, btRigidBody * body1 ) +{ + if (needApplyTorques()==false) return 0.0f; + + btScalar target_velocity = m_targetVelocity; + btScalar maxMotorForce = m_maxMotorForce; + + //current error correction + if (m_currentLimit!=0) + { + target_velocity = -m_stopERP*m_currentLimitError/(timeStep); + maxMotorForce = m_maxLimitForce; + } + + maxMotorForce *= timeStep; + + // current velocity difference + + btVector3 angVelA; + body0->internalGetAngularVelocity(angVelA); + btVector3 angVelB; + body1->internalGetAngularVelocity(angVelB); + + btVector3 vel_diff; + vel_diff = angVelA-angVelB; + + + + btScalar rel_vel = axis.dot(vel_diff); + + // correction velocity + btScalar motor_relvel = m_limitSoftness*(target_velocity - m_damping*rel_vel); + + + if ( motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON ) + { + return 0.0f;//no need for applying force + } + + + // correction impulse + btScalar unclippedMotorImpulse = (1+m_bounce)*motor_relvel*jacDiagABInv; + + // clip correction impulse + btScalar clippedMotorImpulse; + + ///@todo: should clip against accumulated impulse + if (unclippedMotorImpulse>0.0f) + { + clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce? maxMotorForce: unclippedMotorImpulse; + } + else + { + clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce: unclippedMotorImpulse; + } + + + // sort with accumulated impulses + btScalar lo = btScalar(-BT_LARGE_FLOAT); + btScalar hi = btScalar(BT_LARGE_FLOAT); + + btScalar oldaccumImpulse = m_accumulatedImpulse; + btScalar sum = oldaccumImpulse + clippedMotorImpulse; + m_accumulatedImpulse = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; + + clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse; + + btVector3 motorImp = clippedMotorImpulse * axis; + + //body0->applyTorqueImpulse(motorImp); + //body1->applyTorqueImpulse(-motorImp); + + body0->internalApplyImpulse(btVector3(0,0,0), body0->getInvInertiaTensorWorld()*axis,clippedMotorImpulse); + body1->internalApplyImpulse(btVector3(0,0,0), body1->getInvInertiaTensorWorld()*axis,-clippedMotorImpulse); + + + return clippedMotorImpulse; + + +} + +//////////////////////////// End btRotationalLimitMotor //////////////////////////////////// + + + + +//////////////////////////// btTranslationalLimitMotor //////////////////////////////////// + + +int btTranslationalLimitMotor::testLimitValue(int limitIndex, btScalar test_value) +{ + btScalar loLimit = m_lowerLimit[limitIndex]; + btScalar hiLimit = m_upperLimit[limitIndex]; + if(loLimit > hiLimit) + { + m_currentLimit[limitIndex] = 0;//Free from violation + m_currentLimitError[limitIndex] = btScalar(0.f); + return 0; + } + + if (test_value < loLimit) + { + m_currentLimit[limitIndex] = 2;//low limit violation + m_currentLimitError[limitIndex] = test_value - loLimit; + return 2; + } + else if (test_value> hiLimit) + { + m_currentLimit[limitIndex] = 1;//High limit violation + m_currentLimitError[limitIndex] = test_value - hiLimit; + return 1; + }; + + m_currentLimit[limitIndex] = 0;//Free from violation + m_currentLimitError[limitIndex] = btScalar(0.f); + return 0; +} + + + +btScalar btTranslationalLimitMotor::solveLinearAxis( + btScalar timeStep, + btScalar jacDiagABInv, + btRigidBody& body1,const btVector3 &pointInA, + btRigidBody& body2,const btVector3 &pointInB, + int limit_index, + const btVector3 & axis_normal_on_a, + const btVector3 & anchorPos) +{ + + ///find relative velocity + // btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition(); + // btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition(); + btVector3 rel_pos1 = anchorPos - body1.getCenterOfMassPosition(); + btVector3 rel_pos2 = anchorPos - body2.getCenterOfMassPosition(); + + btVector3 vel1; + body1.internalGetVelocityInLocalPointObsolete(rel_pos1,vel1); + btVector3 vel2; + body2.internalGetVelocityInLocalPointObsolete(rel_pos2,vel2); + btVector3 vel = vel1 - vel2; + + btScalar rel_vel = axis_normal_on_a.dot(vel); + + + + /// apply displacement correction + + //positional error (zeroth order error) + btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a); + btScalar lo = btScalar(-BT_LARGE_FLOAT); + btScalar hi = btScalar(BT_LARGE_FLOAT); + + btScalar minLimit = m_lowerLimit[limit_index]; + btScalar maxLimit = m_upperLimit[limit_index]; + + //handle the limits + if (minLimit < maxLimit) + { + { + if (depth > maxLimit) + { + depth -= maxLimit; + lo = btScalar(0.); + + } + else + { + if (depth < minLimit) + { + depth -= minLimit; + hi = btScalar(0.); + } + else + { + return 0.0f; + } + } + } + } + + btScalar normalImpulse= m_limitSoftness*(m_restitution*depth/timeStep - m_damping*rel_vel) * jacDiagABInv; + + + + + btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index]; + btScalar sum = oldNormalImpulse + normalImpulse; + m_accumulatedImpulse[limit_index] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; + normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse; + + btVector3 impulse_vector = axis_normal_on_a * normalImpulse; + //body1.applyImpulse( impulse_vector, rel_pos1); + //body2.applyImpulse(-impulse_vector, rel_pos2); + + btVector3 ftorqueAxis1 = rel_pos1.cross(axis_normal_on_a); + btVector3 ftorqueAxis2 = rel_pos2.cross(axis_normal_on_a); + body1.internalApplyImpulse(axis_normal_on_a*body1.getInvMass(), body1.getInvInertiaTensorWorld()*ftorqueAxis1,normalImpulse); + body2.internalApplyImpulse(axis_normal_on_a*body2.getInvMass(), body2.getInvInertiaTensorWorld()*ftorqueAxis2,-normalImpulse); + + + + + return normalImpulse; +} + +//////////////////////////// btTranslationalLimitMotor //////////////////////////////////// + +void btGeneric6DofConstraint::calculateAngleInfo() +{ + btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis(); + matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff); + // in euler angle mode we do not actually constrain the angular velocity + // along the axes axis[0] and axis[2] (although we do use axis[1]) : + // + // to get constrain w2-w1 along ...not + // ------ --------------------- ------ + // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0] + // d(angle[1])/dt = 0 ax[1] + // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2] + // + // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0. + // to prove the result for angle[0], write the expression for angle[0] from + // GetInfo1 then take the derivative. to prove this for angle[2] it is + // easier to take the euler rate expression for d(angle[2])/dt with respect + // to the components of w and set that to 0. + btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0); + btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2); + + m_calculatedAxis[1] = axis2.cross(axis0); + m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2); + m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]); + + m_calculatedAxis[0].normalize(); + m_calculatedAxis[1].normalize(); + m_calculatedAxis[2].normalize(); + +} + +void btGeneric6DofConstraint::calculateTransforms() +{ + calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); +} + +void btGeneric6DofConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB) +{ + m_calculatedTransformA = transA * m_frameInA; + m_calculatedTransformB = transB * m_frameInB; + calculateLinearInfo(); + calculateAngleInfo(); + if(m_useOffsetForConstraintFrame) + { // get weight factors depending on masses + btScalar miA = getRigidBodyA().getInvMass(); + btScalar miB = getRigidBodyB().getInvMass(); + m_hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON); + btScalar miS = miA + miB; + if(miS > btScalar(0.f)) + { + m_factA = miB / miS; + } + else + { + m_factA = btScalar(0.5f); + } + m_factB = btScalar(1.0f) - m_factA; + } +} + + + +void btGeneric6DofConstraint::buildLinearJacobian( + btJacobianEntry & jacLinear,const btVector3 & normalWorld, + const btVector3 & pivotAInW,const btVector3 & pivotBInW) +{ + new (&jacLinear) btJacobianEntry( + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + pivotAInW - m_rbA.getCenterOfMassPosition(), + pivotBInW - m_rbB.getCenterOfMassPosition(), + normalWorld, + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); +} + + + +void btGeneric6DofConstraint::buildAngularJacobian( + btJacobianEntry & jacAngular,const btVector3 & jointAxisW) +{ + new (&jacAngular) btJacobianEntry(jointAxisW, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + +} + + + +bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index) +{ + btScalar angle = m_calculatedAxisAngleDiff[axis_index]; + angle = btAdjustAngleToLimits(angle, m_angularLimits[axis_index].m_loLimit, m_angularLimits[axis_index].m_hiLimit); + m_angularLimits[axis_index].m_currentPosition = angle; + //test limits + m_angularLimits[axis_index].testLimitValue(angle); + return m_angularLimits[axis_index].needApplyTorques(); +} + + + +void btGeneric6DofConstraint::buildJacobian() +{ +#ifndef __SPU__ + if (m_useSolveConstraintObsolete) + { + + // Clear accumulated impulses for the next simulation step + m_linearLimits.m_accumulatedImpulse.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); + int i; + for(i = 0; i < 3; i++) + { + m_angularLimits[i].m_accumulatedImpulse = btScalar(0.); + } + //calculates transform + calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + + // const btVector3& pivotAInW = m_calculatedTransformA.getOrigin(); + // const btVector3& pivotBInW = m_calculatedTransformB.getOrigin(); + calcAnchorPos(); + btVector3 pivotAInW = m_AnchorPos; + btVector3 pivotBInW = m_AnchorPos; + + // not used here + // btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + // btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + btVector3 normalWorld; + //linear part + for (i=0;i<3;i++) + { + if (m_linearLimits.isLimited(i)) + { + if (m_useLinearReferenceFrameA) + normalWorld = m_calculatedTransformA.getBasis().getColumn(i); + else + normalWorld = m_calculatedTransformB.getBasis().getColumn(i); + + buildLinearJacobian( + m_jacLinear[i],normalWorld , + pivotAInW,pivotBInW); + + } + } + + // angular part + for (i=0;i<3;i++) + { + //calculates error angle + if (testAngularLimitMotor(i)) + { + normalWorld = this->getAxis(i); + // Create angular atom + buildAngularJacobian(m_jacAng[i],normalWorld); + } + } + + } +#endif //__SPU__ + +} + + +void btGeneric6DofConstraint::getInfo1 (btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } else + { + //prepare constraint + calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + info->m_numConstraintRows = 0; + info->nub = 6; + int i; + //test linear limits + for(i = 0; i < 3; i++) + { + if(m_linearLimits.needApplyForce(i)) + { + info->m_numConstraintRows++; + info->nub--; + } + } + //test angular limits + for (i=0;i<3 ;i++ ) + { + if(testAngularLimitMotor(i)) + { + info->m_numConstraintRows++; + info->nub--; + } + } + } +} + +void btGeneric6DofConstraint::getInfo1NonVirtual (btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } else + { + //pre-allocate all 6 + info->m_numConstraintRows = 6; + info->nub = 0; + } +} + + +void btGeneric6DofConstraint::getInfo2 (btConstraintInfo2* info) +{ + btAssert(!m_useSolveConstraintObsolete); + + const btTransform& transA = m_rbA.getCenterOfMassTransform(); + const btTransform& transB = m_rbB.getCenterOfMassTransform(); + const btVector3& linVelA = m_rbA.getLinearVelocity(); + const btVector3& linVelB = m_rbB.getLinearVelocity(); + const btVector3& angVelA = m_rbA.getAngularVelocity(); + const btVector3& angVelB = m_rbB.getAngularVelocity(); + + if(m_useOffsetForConstraintFrame) + { // for stability better to solve angular limits first + int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB); + setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB); + } + else + { // leave old version for compatibility + int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB); + setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB); + } + +} + + +void btGeneric6DofConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB) +{ + + btAssert(!m_useSolveConstraintObsolete); + //prepare constraint + calculateTransforms(transA,transB); + + int i; + for (i=0;i<3 ;i++ ) + { + testAngularLimitMotor(i); + } + + if(m_useOffsetForConstraintFrame) + { // for stability better to solve angular limits first + int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB); + setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB); + } + else + { // leave old version for compatibility + int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB); + setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB); + } +} + + + +int btGeneric6DofConstraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB) +{ +// int row = 0; + //solve linear limits + btRotationalLimitMotor limot; + for (int i=0;i<3 ;i++ ) + { + if(m_linearLimits.needApplyForce(i)) + { // re-use rotational motor code + limot.m_bounce = btScalar(0.f); + limot.m_currentLimit = m_linearLimits.m_currentLimit[i]; + limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i]; + limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i]; + limot.m_damping = m_linearLimits.m_damping; + limot.m_enableMotor = m_linearLimits.m_enableMotor[i]; + limot.m_hiLimit = m_linearLimits.m_upperLimit[i]; + limot.m_limitSoftness = m_linearLimits.m_limitSoftness; + limot.m_loLimit = m_linearLimits.m_lowerLimit[i]; + limot.m_maxLimitForce = btScalar(0.f); + limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i]; + limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i]; + btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i); + int flags = m_flags >> (i * BT_6DOF_FLAGS_AXIS_SHIFT); + limot.m_normalCFM = (flags & BT_6DOF_FLAGS_CFM_NORM) ? m_linearLimits.m_normalCFM[i] : info->cfm[0]; + limot.m_stopCFM = (flags & BT_6DOF_FLAGS_CFM_STOP) ? m_linearLimits.m_stopCFM[i] : info->cfm[0]; + limot.m_stopERP = (flags & BT_6DOF_FLAGS_ERP_STOP) ? m_linearLimits.m_stopERP[i] : info->erp; + if(m_useOffsetForConstraintFrame) + { + int indx1 = (i + 1) % 3; + int indx2 = (i + 2) % 3; + int rotAllowed = 1; // rotations around orthos to current axis + if(m_angularLimits[indx1].m_currentLimit && m_angularLimits[indx2].m_currentLimit) + { + rotAllowed = 0; + } + row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0, rotAllowed); + } + else + { + row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0); + } + } + } + return row; +} + + + +int btGeneric6DofConstraint::setAngularLimits(btConstraintInfo2 *info, int row_offset, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB) +{ + btGeneric6DofConstraint * d6constraint = this; + int row = row_offset; + //solve angular limits + for (int i=0;i<3 ;i++ ) + { + if(d6constraint->getRotationalLimitMotor(i)->needApplyTorques()) + { + btVector3 axis = d6constraint->getAxis(i); + int flags = m_flags >> ((i + 3) * BT_6DOF_FLAGS_AXIS_SHIFT); + if(!(flags & BT_6DOF_FLAGS_CFM_NORM)) + { + m_angularLimits[i].m_normalCFM = info->cfm[0]; + } + if(!(flags & BT_6DOF_FLAGS_CFM_STOP)) + { + m_angularLimits[i].m_stopCFM = info->cfm[0]; + } + if(!(flags & BT_6DOF_FLAGS_ERP_STOP)) + { + m_angularLimits[i].m_stopERP = info->erp; + } + row += get_limit_motor_info2(d6constraint->getRotationalLimitMotor(i), + transA,transB,linVelA,linVelB,angVelA,angVelB, info,row,axis,1); + } + } + + return row; +} + + + + +void btGeneric6DofConstraint::updateRHS(btScalar timeStep) +{ + (void)timeStep; + +} + + +void btGeneric6DofConstraint::setFrames(const btTransform& frameA, const btTransform& frameB) +{ + m_frameInA = frameA; + m_frameInB = frameB; + buildJacobian(); + calculateTransforms(); +} + + + +btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const +{ + return m_calculatedAxis[axis_index]; +} + + +btScalar btGeneric6DofConstraint::getRelativePivotPosition(int axisIndex) const +{ + return m_calculatedLinearDiff[axisIndex]; +} + + +btScalar btGeneric6DofConstraint::getAngle(int axisIndex) const +{ + return m_calculatedAxisAngleDiff[axisIndex]; +} + + + +void btGeneric6DofConstraint::calcAnchorPos(void) +{ + btScalar imA = m_rbA.getInvMass(); + btScalar imB = m_rbB.getInvMass(); + btScalar weight; + if(imB == btScalar(0.0)) + { + weight = btScalar(1.0); + } + else + { + weight = imA / (imA + imB); + } + const btVector3& pA = m_calculatedTransformA.getOrigin(); + const btVector3& pB = m_calculatedTransformB.getOrigin(); + m_AnchorPos = pA * weight + pB * (btScalar(1.0) - weight); + return; +} + + + +void btGeneric6DofConstraint::calculateLinearInfo() +{ + m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin(); + m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff; + for(int i = 0; i < 3; i++) + { + m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i]; + m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]); + } +} + + + +int btGeneric6DofConstraint::get_limit_motor_info2( + btRotationalLimitMotor * limot, + const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB, + btConstraintInfo2 *info, int row, btVector3& ax1, int rotational,int rotAllowed) +{ + int srow = row * info->rowskip; + int powered = limot->m_enableMotor; + int limit = limot->m_currentLimit; + if (powered || limit) + { // if the joint is powered, or has joint limits, add in the extra row + btScalar *J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis; + btScalar *J2 = rotational ? info->m_J2angularAxis : 0; + J1[srow+0] = ax1[0]; + J1[srow+1] = ax1[1]; + J1[srow+2] = ax1[2]; + if(rotational) + { + J2[srow+0] = -ax1[0]; + J2[srow+1] = -ax1[1]; + J2[srow+2] = -ax1[2]; + } + if((!rotational)) + { + if (m_useOffsetForConstraintFrame) + { + btVector3 tmpA, tmpB, relA, relB; + // get vector from bodyB to frameB in WCS + relB = m_calculatedTransformB.getOrigin() - transB.getOrigin(); + // get its projection to constraint axis + btVector3 projB = ax1 * relB.dot(ax1); + // get vector directed from bodyB to constraint axis (and orthogonal to it) + btVector3 orthoB = relB - projB; + // same for bodyA + relA = m_calculatedTransformA.getOrigin() - transA.getOrigin(); + btVector3 projA = ax1 * relA.dot(ax1); + btVector3 orthoA = relA - projA; + // get desired offset between frames A and B along constraint axis + btScalar desiredOffs = limot->m_currentPosition - limot->m_currentLimitError; + // desired vector from projection of center of bodyA to projection of center of bodyB to constraint axis + btVector3 totalDist = projA + ax1 * desiredOffs - projB; + // get offset vectors relA and relB + relA = orthoA + totalDist * m_factA; + relB = orthoB - totalDist * m_factB; + tmpA = relA.cross(ax1); + tmpB = relB.cross(ax1); + if(m_hasStaticBody && (!rotAllowed)) + { + tmpA *= m_factA; + tmpB *= m_factB; + } + int i; + for (i=0; i<3; i++) info->m_J1angularAxis[srow+i] = tmpA[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[srow+i] = -tmpB[i]; + } else + { + btVector3 ltd; // Linear Torque Decoupling vector + btVector3 c = m_calculatedTransformB.getOrigin() - transA.getOrigin(); + ltd = c.cross(ax1); + info->m_J1angularAxis[srow+0] = ltd[0]; + info->m_J1angularAxis[srow+1] = ltd[1]; + info->m_J1angularAxis[srow+2] = ltd[2]; + + c = m_calculatedTransformB.getOrigin() - transB.getOrigin(); + ltd = -c.cross(ax1); + info->m_J2angularAxis[srow+0] = ltd[0]; + info->m_J2angularAxis[srow+1] = ltd[1]; + info->m_J2angularAxis[srow+2] = ltd[2]; + } + } + // if we're limited low and high simultaneously, the joint motor is + // ineffective + if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = 0; + info->m_constraintError[srow] = btScalar(0.f); + if (powered) + { + info->cfm[srow] = limot->m_normalCFM; + if(!limit) + { + btScalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity; + + btScalar mot_fact = getMotorFactor( limot->m_currentPosition, + limot->m_loLimit, + limot->m_hiLimit, + tag_vel, + info->fps * limot->m_stopERP); + info->m_constraintError[srow] += mot_fact * limot->m_targetVelocity; + info->m_lowerLimit[srow] = -limot->m_maxMotorForce; + info->m_upperLimit[srow] = limot->m_maxMotorForce; + } + } + if(limit) + { + btScalar k = info->fps * limot->m_stopERP; + if(!rotational) + { + info->m_constraintError[srow] += k * limot->m_currentLimitError; + } + else + { + info->m_constraintError[srow] += -k * limot->m_currentLimitError; + } + info->cfm[srow] = limot->m_stopCFM; + if (limot->m_loLimit == limot->m_hiLimit) + { // limited low and high simultaneously + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { + if (limit == 1) + { + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + // deal with bounce + if (limot->m_bounce > 0) + { + // calculate joint velocity + btScalar vel; + if (rotational) + { + vel = angVelA.dot(ax1); +//make sure that if no body -> angVelB == zero vec +// if (body1) + vel -= angVelB.dot(ax1); + } + else + { + vel = linVelA.dot(ax1); +//make sure that if no body -> angVelB == zero vec +// if (body1) + vel -= linVelB.dot(ax1); + } + // only apply bounce if the velocity is incoming, and if the + // resulting c[] exceeds what we already have. + if (limit == 1) + { + if (vel < 0) + { + btScalar newc = -limot->m_bounce* vel; + if (newc > info->m_constraintError[srow]) + info->m_constraintError[srow] = newc; + } + } + else + { + if (vel > 0) + { + btScalar newc = -limot->m_bounce * vel; + if (newc < info->m_constraintError[srow]) + info->m_constraintError[srow] = newc; + } + } + } + } + } + return 1; + } + else return 0; +} + + + + + + + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///If no axis is provided, it uses the default axis for this constraint. +void btGeneric6DofConstraint::setParam(int num, btScalar value, int axis) +{ + if((axis >= 0) && (axis < 3)) + { + switch(num) + { + case BT_CONSTRAINT_STOP_ERP : + m_linearLimits.m_stopERP[axis] = value; + m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); + break; + case BT_CONSTRAINT_STOP_CFM : + m_linearLimits.m_stopCFM[axis] = value; + m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); + break; + case BT_CONSTRAINT_CFM : + m_linearLimits.m_normalCFM[axis] = value; + m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); + break; + default : + btAssertConstrParams(0); + } + } + else if((axis >=3) && (axis < 6)) + { + switch(num) + { + case BT_CONSTRAINT_STOP_ERP : + m_angularLimits[axis - 3].m_stopERP = value; + m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); + break; + case BT_CONSTRAINT_STOP_CFM : + m_angularLimits[axis - 3].m_stopCFM = value; + m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); + break; + case BT_CONSTRAINT_CFM : + m_angularLimits[axis - 3].m_normalCFM = value; + m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); + break; + default : + btAssertConstrParams(0); + } + } + else + { + btAssertConstrParams(0); + } +} + + ///return the local value of parameter +btScalar btGeneric6DofConstraint::getParam(int num, int axis) const +{ + btScalar retVal = 0; + if((axis >= 0) && (axis < 3)) + { + switch(num) + { + case BT_CONSTRAINT_STOP_ERP : + btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); + retVal = m_linearLimits.m_stopERP[axis]; + break; + case BT_CONSTRAINT_STOP_CFM : + btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); + retVal = m_linearLimits.m_stopCFM[axis]; + break; + case BT_CONSTRAINT_CFM : + btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); + retVal = m_linearLimits.m_normalCFM[axis]; + break; + default : + btAssertConstrParams(0); + } + } + else if((axis >=3) && (axis < 6)) + { + switch(num) + { + case BT_CONSTRAINT_STOP_ERP : + btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); + retVal = m_angularLimits[axis - 3].m_stopERP; + break; + case BT_CONSTRAINT_STOP_CFM : + btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); + retVal = m_angularLimits[axis - 3].m_stopCFM; + break; + case BT_CONSTRAINT_CFM : + btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); + retVal = m_angularLimits[axis - 3].m_normalCFM; + break; + default : + btAssertConstrParams(0); + } + } + else + { + btAssertConstrParams(0); + } + return retVal; +} + + + +void btGeneric6DofConstraint::setAxis(const btVector3& axis1,const btVector3& axis2) +{ + btVector3 zAxis = axis1.normalized(); + btVector3 yAxis = axis2.normalized(); + btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system + + btTransform frameInW; + frameInW.setIdentity(); + frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0], + xAxis[1], yAxis[1], zAxis[1], + xAxis[2], yAxis[2], zAxis[2]); + + // now get constraint frame in local coordinate systems + m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW; + m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW; + + calculateTransforms(); +} diff --git a/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h new file mode 100644 index 0000000..b441081 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h @@ -0,0 +1,614 @@ +/* +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. +*/ + +/// 2009 March: btGeneric6DofConstraint refactored by Roman Ponomarev +/// Added support for generic constraint solver through getInfo1/getInfo2 methods + +/* +2007-09-09 +btGeneric6DofConstraint Refactored by Francisco Le?n +email: projectileman@yahoo.com +http://gimpact.sf.net +*/ + + +#ifndef BT_GENERIC_6DOF_CONSTRAINT_H +#define BT_GENERIC_6DOF_CONSTRAINT_H + +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" + +class btRigidBody; + + + + +//! Rotation Limit structure for generic joints +class btRotationalLimitMotor +{ +public: + //! limit_parameters + //!@{ + btScalar m_loLimit;//!< joint limit + btScalar m_hiLimit;//!< joint limit + btScalar m_targetVelocity;//!< target motor velocity + btScalar m_maxMotorForce;//!< max force on motor + btScalar m_maxLimitForce;//!< max force on limit + btScalar m_damping;//!< Damping. + btScalar m_limitSoftness;//! Relaxation factor + btScalar m_normalCFM;//!< Constraint force mixing factor + btScalar m_stopERP;//!< Error tolerance factor when joint is at limit + btScalar m_stopCFM;//!< Constraint force mixing factor when joint is at limit + btScalar m_bounce;//!< restitution factor + bool m_enableMotor; + + //!@} + + //! temp_variables + //!@{ + btScalar m_currentLimitError;//! How much is violated this limit + btScalar m_currentPosition; //! current value of angle + int m_currentLimit;//!< 0=free, 1=at lo limit, 2=at hi limit + btScalar m_accumulatedImpulse; + //!@} + + btRotationalLimitMotor() + { + m_accumulatedImpulse = 0.f; + m_targetVelocity = 0; + m_maxMotorForce = 0.1f; + m_maxLimitForce = 300.0f; + m_loLimit = 1.0f; + m_hiLimit = -1.0f; + m_normalCFM = 0.f; + m_stopERP = 0.2f; + m_stopCFM = 0.f; + m_bounce = 0.0f; + m_damping = 1.0f; + m_limitSoftness = 0.5f; + m_currentLimit = 0; + m_currentLimitError = 0; + m_enableMotor = false; + } + + btRotationalLimitMotor(const btRotationalLimitMotor & limot) + { + m_targetVelocity = limot.m_targetVelocity; + m_maxMotorForce = limot.m_maxMotorForce; + m_limitSoftness = limot.m_limitSoftness; + m_loLimit = limot.m_loLimit; + m_hiLimit = limot.m_hiLimit; + m_normalCFM = limot.m_normalCFM; + m_stopERP = limot.m_stopERP; + m_stopCFM = limot.m_stopCFM; + m_bounce = limot.m_bounce; + m_currentLimit = limot.m_currentLimit; + m_currentLimitError = limot.m_currentLimitError; + m_enableMotor = limot.m_enableMotor; + } + + + + //! Is limited + bool isLimited() + { + if(m_loLimit > m_hiLimit) return false; + return true; + } + + //! Need apply correction + bool needApplyTorques() + { + if(m_currentLimit == 0 && m_enableMotor == false) return false; + return true; + } + + //! calculates error + /*! + calculates m_currentLimit and m_currentLimitError. + */ + int testLimitValue(btScalar test_value); + + //! apply the correction impulses for two bodies + btScalar solveAngularLimits(btScalar timeStep,btVector3& axis, btScalar jacDiagABInv,btRigidBody * body0, btRigidBody * body1); + +}; + + + +class btTranslationalLimitMotor +{ +public: + btVector3 m_lowerLimit;//!< the constraint lower limits + btVector3 m_upperLimit;//!< the constraint upper limits + btVector3 m_accumulatedImpulse; + //! Linear_Limit_parameters + //!@{ + btScalar m_limitSoftness;//!< Softness for linear limit + btScalar m_damping;//!< Damping for linear limit + btScalar m_restitution;//! Bounce parameter for linear limit + btVector3 m_normalCFM;//!< Constraint force mixing factor + btVector3 m_stopERP;//!< Error tolerance factor when joint is at limit + btVector3 m_stopCFM;//!< Constraint force mixing factor when joint is at limit + //!@} + bool m_enableMotor[3]; + btVector3 m_targetVelocity;//!< target motor velocity + btVector3 m_maxMotorForce;//!< max force on motor + btVector3 m_currentLimitError;//! How much is violated this limit + btVector3 m_currentLinearDiff;//! Current relative offset of constraint frames + int m_currentLimit[3];//!< 0=free, 1=at lower limit, 2=at upper limit + + btTranslationalLimitMotor() + { + m_lowerLimit.setValue(0.f,0.f,0.f); + m_upperLimit.setValue(0.f,0.f,0.f); + m_accumulatedImpulse.setValue(0.f,0.f,0.f); + m_normalCFM.setValue(0.f, 0.f, 0.f); + m_stopERP.setValue(0.2f, 0.2f, 0.2f); + m_stopCFM.setValue(0.f, 0.f, 0.f); + + m_limitSoftness = 0.7f; + m_damping = btScalar(1.0f); + m_restitution = btScalar(0.5f); + for(int i=0; i < 3; i++) + { + m_enableMotor[i] = false; + m_targetVelocity[i] = btScalar(0.f); + m_maxMotorForce[i] = btScalar(0.f); + } + } + + btTranslationalLimitMotor(const btTranslationalLimitMotor & other ) + { + m_lowerLimit = other.m_lowerLimit; + m_upperLimit = other.m_upperLimit; + m_accumulatedImpulse = other.m_accumulatedImpulse; + + m_limitSoftness = other.m_limitSoftness ; + m_damping = other.m_damping; + m_restitution = other.m_restitution; + m_normalCFM = other.m_normalCFM; + m_stopERP = other.m_stopERP; + m_stopCFM = other.m_stopCFM; + + for(int i=0; i < 3; i++) + { + m_enableMotor[i] = other.m_enableMotor[i]; + m_targetVelocity[i] = other.m_targetVelocity[i]; + m_maxMotorForce[i] = other.m_maxMotorForce[i]; + } + } + + //! Test limit + /*! + - free means upper < lower, + - locked means upper == lower + - limited means upper > lower + - limitIndex: first 3 are linear, next 3 are angular + */ + inline bool isLimited(int limitIndex) + { + return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); + } + inline bool needApplyForce(int limitIndex) + { + if(m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false; + return true; + } + int testLimitValue(int limitIndex, btScalar test_value); + + + btScalar solveLinearAxis( + btScalar timeStep, + btScalar jacDiagABInv, + btRigidBody& body1,const btVector3 &pointInA, + btRigidBody& body2,const btVector3 &pointInB, + int limit_index, + const btVector3 & axis_normal_on_a, + const btVector3 & anchorPos); + + +}; + +enum bt6DofFlags +{ + BT_6DOF_FLAGS_CFM_NORM = 1, + BT_6DOF_FLAGS_CFM_STOP = 2, + BT_6DOF_FLAGS_ERP_STOP = 4 +}; +#define BT_6DOF_FLAGS_AXIS_SHIFT 3 // bits per axis + + +/// btGeneric6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space +/*! +btGeneric6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked'. +currently this limit supports rotational motors
      +
        +
      • For Linear limits, use btGeneric6DofConstraint.setLinearUpperLimit, btGeneric6DofConstraint.setLinearLowerLimit. You can set the parameters with the btTranslationalLimitMotor structure accsesible through the btGeneric6DofConstraint.getTranslationalLimitMotor method. +At this moment translational motors are not supported. May be in the future.
      • + +
      • For Angular limits, use the btRotationalLimitMotor structure for configuring the limit. +This is accessible through btGeneric6DofConstraint.getLimitMotor method, +This brings support for limit parameters and motors.
      • + +
      • Angulars limits have these possible ranges: + + + + + + + + + + + + + + + + + + +
        AXISMIN ANGLEMAX ANGLE
        X-PIPI
        Y-PI/2PI/2
        Z-PIPI
        +
      • +
      + +*/ +class btGeneric6DofConstraint : public btTypedConstraint +{ +protected: + + //! relative_frames + //!@{ + btTransform m_frameInA;//!< the constraint space w.r.t body A + btTransform m_frameInB;//!< the constraint space w.r.t body B + //!@} + + //! Jacobians + //!@{ + btJacobianEntry m_jacLinear[3];//!< 3 orthogonal linear constraints + btJacobianEntry m_jacAng[3];//!< 3 orthogonal angular constraints + //!@} + + //! Linear_Limit_parameters + //!@{ + btTranslationalLimitMotor m_linearLimits; + //!@} + + + //! hinge_parameters + //!@{ + btRotationalLimitMotor m_angularLimits[3]; + //!@} + + +protected: + //! temporal variables + //!@{ + btScalar m_timeStep; + btTransform m_calculatedTransformA; + btTransform m_calculatedTransformB; + btVector3 m_calculatedAxisAngleDiff; + btVector3 m_calculatedAxis[3]; + btVector3 m_calculatedLinearDiff; + btScalar m_factA; + btScalar m_factB; + bool m_hasStaticBody; + + btVector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes + + bool m_useLinearReferenceFrameA; + bool m_useOffsetForConstraintFrame; + + int m_flags; + + //!@} + + btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other) + { + btAssert(0); + (void) other; + return *this; + } + + + int setAngularLimits(btConstraintInfo2 *info, int row_offset,const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB); + + int setLinearLimits(btConstraintInfo2 *info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB); + + void buildLinearJacobian( + btJacobianEntry & jacLinear,const btVector3 & normalWorld, + const btVector3 & pivotAInW,const btVector3 & pivotBInW); + + void buildAngularJacobian(btJacobianEntry & jacAngular,const btVector3 & jointAxisW); + + // tests linear limits + void calculateLinearInfo(); + + //! calcs the euler angles between the two bodies. + void calculateAngleInfo(); + + + +public: + + ///for backwards compatibility during the transition to 'getInfo/getInfo2' + bool m_useSolveConstraintObsolete; + + btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); + btGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB); + + //! Calcs global transform of the offsets + /*! + Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies. + \sa btGeneric6DofConstraint.getCalculatedTransformA , btGeneric6DofConstraint.getCalculatedTransformB, btGeneric6DofConstraint.calculateAngleInfo + */ + void calculateTransforms(const btTransform& transA,const btTransform& transB); + + void calculateTransforms(); + + //! Gets the global transform of the offset for body A + /*! + \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo. + */ + const btTransform & getCalculatedTransformA() const + { + return m_calculatedTransformA; + } + + //! Gets the global transform of the offset for body B + /*! + \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo. + */ + const btTransform & getCalculatedTransformB() const + { + return m_calculatedTransformB; + } + + const btTransform & getFrameOffsetA() const + { + return m_frameInA; + } + + const btTransform & getFrameOffsetB() const + { + return m_frameInB; + } + + + btTransform & getFrameOffsetA() + { + return m_frameInA; + } + + btTransform & getFrameOffsetB() + { + return m_frameInB; + } + + + //! performs Jacobian calculation, and also calculates angle differences and axis + virtual void buildJacobian(); + + virtual void getInfo1 (btConstraintInfo1* info); + + void getInfo1NonVirtual (btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + void getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB); + + + void updateRHS(btScalar timeStep); + + //! Get the rotation axis in global coordinates + /*! + \pre btGeneric6DofConstraint.buildJacobian must be called previously. + */ + btVector3 getAxis(int axis_index) const; + + //! Get the relative Euler angle + /*! + \pre btGeneric6DofConstraint::calculateTransforms() must be called previously. + */ + btScalar getAngle(int axis_index) const; + + //! Get the relative position of the constraint pivot + /*! + \pre btGeneric6DofConstraint::calculateTransforms() must be called previously. + */ + btScalar getRelativePivotPosition(int axis_index) const; + + void setFrames(const btTransform & frameA, const btTransform & frameB); + + //! Test angular limit. + /*! + Calculates angular correction and returns true if limit needs to be corrected. + \pre btGeneric6DofConstraint::calculateTransforms() must be called previously. + */ + bool testAngularLimitMotor(int axis_index); + + void setLinearLowerLimit(const btVector3& linearLower) + { + m_linearLimits.m_lowerLimit = linearLower; + } + + void getLinearLowerLimit(btVector3& linearLower) + { + linearLower = m_linearLimits.m_lowerLimit; + } + + void setLinearUpperLimit(const btVector3& linearUpper) + { + m_linearLimits.m_upperLimit = linearUpper; + } + + void getLinearUpperLimit(btVector3& linearUpper) + { + linearUpper = m_linearLimits.m_upperLimit; + } + + void setAngularLowerLimit(const btVector3& angularLower) + { + for(int i = 0; i < 3; i++) + m_angularLimits[i].m_loLimit = btNormalizeAngle(angularLower[i]); + } + + void getAngularLowerLimit(btVector3& angularLower) + { + for(int i = 0; i < 3; i++) + angularLower[i] = m_angularLimits[i].m_loLimit; + } + + void setAngularUpperLimit(const btVector3& angularUpper) + { + for(int i = 0; i < 3; i++) + m_angularLimits[i].m_hiLimit = btNormalizeAngle(angularUpper[i]); + } + + void getAngularUpperLimit(btVector3& angularUpper) + { + for(int i = 0; i < 3; i++) + angularUpper[i] = m_angularLimits[i].m_hiLimit; + } + + //! Retrieves the angular limit informacion + btRotationalLimitMotor * getRotationalLimitMotor(int index) + { + return &m_angularLimits[index]; + } + + //! Retrieves the limit informacion + btTranslationalLimitMotor * getTranslationalLimitMotor() + { + return &m_linearLimits; + } + + //first 3 are linear, next 3 are angular + void setLimit(int axis, btScalar lo, btScalar hi) + { + if(axis<3) + { + m_linearLimits.m_lowerLimit[axis] = lo; + m_linearLimits.m_upperLimit[axis] = hi; + } + else + { + lo = btNormalizeAngle(lo); + hi = btNormalizeAngle(hi); + m_angularLimits[axis-3].m_loLimit = lo; + m_angularLimits[axis-3].m_hiLimit = hi; + } + } + + //! Test limit + /*! + - free means upper < lower, + - locked means upper == lower + - limited means upper > lower + - limitIndex: first 3 are linear, next 3 are angular + */ + bool isLimited(int limitIndex) + { + if(limitIndex<3) + { + return m_linearLimits.isLimited(limitIndex); + + } + return m_angularLimits[limitIndex-3].isLimited(); + } + + virtual void calcAnchorPos(void); // overridable + + int get_limit_motor_info2( btRotationalLimitMotor * limot, + const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB, + btConstraintInfo2 *info, int row, btVector3& ax1, int rotational, int rotAllowed = false); + + // access for UseFrameOffset + bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; } + void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; } + + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///If no axis is provided, it uses the default axis for this constraint. + virtual void setParam(int num, btScalar value, int axis = -1); + ///return the local value of parameter + virtual btScalar getParam(int num, int axis = -1) const; + + void setAxis( const btVector3& axis1, const btVector3& axis2); + + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btGeneric6DofConstraintData +{ + btTypedConstraintData m_typeConstraintData; + btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransformFloatData m_rbBFrame; + + btVector3FloatData m_linearUpperLimit; + btVector3FloatData m_linearLowerLimit; + + btVector3FloatData m_angularUpperLimit; + btVector3FloatData m_angularLowerLimit; + + int m_useLinearReferenceFrameA; + int m_useOffsetForConstraintFrame; +}; + +SIMD_FORCE_INLINE int btGeneric6DofConstraint::calculateSerializeBufferSize() const +{ + return sizeof(btGeneric6DofConstraintData); +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btGeneric6DofConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +{ + + btGeneric6DofConstraintData* dof = (btGeneric6DofConstraintData*)dataBuffer; + btTypedConstraint::serialize(&dof->m_typeConstraintData,serializer); + + m_frameInA.serializeFloat(dof->m_rbAFrame); + m_frameInB.serializeFloat(dof->m_rbBFrame); + + + int i; + for (i=0;i<3;i++) + { + dof->m_angularLowerLimit.m_floats[i] = float(m_angularLimits[i].m_loLimit); + dof->m_angularUpperLimit.m_floats[i] = float(m_angularLimits[i].m_hiLimit); + dof->m_linearLowerLimit.m_floats[i] = float(m_linearLimits.m_lowerLimit[i]); + dof->m_linearUpperLimit.m_floats[i] = float(m_linearLimits.m_upperLimit[i]); + } + + dof->m_useLinearReferenceFrameA = m_useLinearReferenceFrameA? 1 : 0; + dof->m_useOffsetForConstraintFrame = m_useOffsetForConstraintFrame ? 1 : 0; + + return "btGeneric6DofConstraintData"; +} + + + + + +#endif //BT_GENERIC_6DOF_CONSTRAINT_H diff --git a/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp b/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp new file mode 100644 index 0000000..2b38714 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp @@ -0,0 +1,185 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +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 "btGeneric6DofSpringConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" + + +btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA) + : btGeneric6DofConstraint(rbA, rbB, frameInA, frameInB, useLinearReferenceFrameA) +{ + init(); +} + + +btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB) + : btGeneric6DofConstraint(rbB, frameInB, useLinearReferenceFrameB) +{ + init(); +} + + +void btGeneric6DofSpringConstraint::init() +{ + m_objectType = D6_SPRING_CONSTRAINT_TYPE; + + for(int i = 0; i < 6; i++) + { + m_springEnabled[i] = false; + m_equilibriumPoint[i] = btScalar(0.f); + m_springStiffness[i] = btScalar(0.f); + m_springDamping[i] = btScalar(1.f); + } +} + + +void btGeneric6DofSpringConstraint::enableSpring(int index, bool onOff) +{ + btAssert((index >= 0) && (index < 6)); + m_springEnabled[index] = onOff; + if(index < 3) + { + m_linearLimits.m_enableMotor[index] = onOff; + } + else + { + m_angularLimits[index - 3].m_enableMotor = onOff; + } +} + + + +void btGeneric6DofSpringConstraint::setStiffness(int index, btScalar stiffness) +{ + btAssert((index >= 0) && (index < 6)); + m_springStiffness[index] = stiffness; +} + + +void btGeneric6DofSpringConstraint::setDamping(int index, btScalar damping) +{ + btAssert((index >= 0) && (index < 6)); + m_springDamping[index] = damping; +} + + +void btGeneric6DofSpringConstraint::setEquilibriumPoint() +{ + calculateTransforms(); + int i; + + for( i = 0; i < 3; i++) + { + m_equilibriumPoint[i] = m_calculatedLinearDiff[i]; + } + for(i = 0; i < 3; i++) + { + m_equilibriumPoint[i + 3] = m_calculatedAxisAngleDiff[i]; + } +} + + + +void btGeneric6DofSpringConstraint::setEquilibriumPoint(int index) +{ + btAssert((index >= 0) && (index < 6)); + calculateTransforms(); + if(index < 3) + { + m_equilibriumPoint[index] = m_calculatedLinearDiff[index]; + } + else + { + m_equilibriumPoint[index] = m_calculatedAxisAngleDiff[index - 3]; + } +} + +void btGeneric6DofSpringConstraint::setEquilibriumPoint(int index, btScalar val) +{ + btAssert((index >= 0) && (index < 6)); + m_equilibriumPoint[index] = val; +} + + +void btGeneric6DofSpringConstraint::internalUpdateSprings(btConstraintInfo2* info) +{ + // it is assumed that calculateTransforms() have been called before this call + int i; + btVector3 relVel = m_rbB.getLinearVelocity() - m_rbA.getLinearVelocity(); + for(i = 0; i < 3; i++) + { + if(m_springEnabled[i]) + { + // get current position of constraint + btScalar currPos = m_calculatedLinearDiff[i]; + // calculate difference + btScalar delta = currPos - m_equilibriumPoint[i]; + // spring force is (delta * m_stiffness) according to Hooke's Law + btScalar force = delta * m_springStiffness[i]; + btScalar velFactor = info->fps * m_springDamping[i] / btScalar(info->m_numIterations); + m_linearLimits.m_targetVelocity[i] = velFactor * force; + m_linearLimits.m_maxMotorForce[i] = btFabs(force) / info->fps; + } + } + for(i = 0; i < 3; i++) + { + if(m_springEnabled[i + 3]) + { + // get current position of constraint + btScalar currPos = m_calculatedAxisAngleDiff[i]; + // calculate difference + btScalar delta = currPos - m_equilibriumPoint[i+3]; + // spring force is (-delta * m_stiffness) according to Hooke's Law + btScalar force = -delta * m_springStiffness[i+3]; + btScalar velFactor = info->fps * m_springDamping[i+3] / btScalar(info->m_numIterations); + m_angularLimits[i].m_targetVelocity = velFactor * force; + m_angularLimits[i].m_maxMotorForce = btFabs(force) / info->fps; + } + } +} + + +void btGeneric6DofSpringConstraint::getInfo2(btConstraintInfo2* info) +{ + // this will be called by constraint solver at the constraint setup stage + // set current motor parameters + internalUpdateSprings(info); + // do the rest of job for constraint setup + btGeneric6DofConstraint::getInfo2(info); +} + + +void btGeneric6DofSpringConstraint::setAxis(const btVector3& axis1,const btVector3& axis2) +{ + btVector3 zAxis = axis1.normalized(); + btVector3 yAxis = axis2.normalized(); + btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system + + btTransform frameInW; + frameInW.setIdentity(); + frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0], + xAxis[1], yAxis[1], zAxis[1], + xAxis[2], yAxis[2], zAxis[2]); + + // now get constraint frame in local coordinate systems + m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW; + m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW; + + calculateTransforms(); +} + + + diff --git a/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h b/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h new file mode 100644 index 0000000..31e0cd5 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h @@ -0,0 +1,99 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_GENERIC_6DOF_SPRING_CONSTRAINT_H +#define BT_GENERIC_6DOF_SPRING_CONSTRAINT_H + + +#include "LinearMath/btVector3.h" +#include "btTypedConstraint.h" +#include "btGeneric6DofConstraint.h" + + +/// Generic 6 DOF constraint that allows to set spring motors to any translational and rotational DOF + +/// DOF index used in enableSpring() and setStiffness() means: +/// 0 : translation X +/// 1 : translation Y +/// 2 : translation Z +/// 3 : rotation X (3rd Euler rotational around new position of X axis, range [-PI+epsilon, PI-epsilon] ) +/// 4 : rotation Y (2nd Euler rotational around new position of Y axis, range [-PI/2+epsilon, PI/2-epsilon] ) +/// 5 : rotation Z (1st Euler rotational around Z axis, range [-PI+epsilon, PI-epsilon] ) + +class btGeneric6DofSpringConstraint : public btGeneric6DofConstraint +{ +protected: + bool m_springEnabled[6]; + btScalar m_equilibriumPoint[6]; + btScalar m_springStiffness[6]; + btScalar m_springDamping[6]; // between 0 and 1 (1 == no damping) + void init(); + void internalUpdateSprings(btConstraintInfo2* info); +public: + btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); + btGeneric6DofSpringConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB); + void enableSpring(int index, bool onOff); + void setStiffness(int index, btScalar stiffness); + void setDamping(int index, btScalar damping); + void setEquilibriumPoint(); // set the current constraint position/orientation as an equilibrium point for all DOF + void setEquilibriumPoint(int index); // set the current constraint position/orientation as an equilibrium point for given DOF + void setEquilibriumPoint(int index, btScalar val); + + virtual void setAxis( const btVector3& axis1, const btVector3& axis2); + + virtual void getInfo2 (btConstraintInfo2* info); + + virtual int calculateSerializeBufferSize() const; + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + +}; + + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btGeneric6DofSpringConstraintData +{ + btGeneric6DofConstraintData m_6dofData; + + int m_springEnabled[6]; + float m_equilibriumPoint[6]; + float m_springStiffness[6]; + float m_springDamping[6]; +}; + +SIMD_FORCE_INLINE int btGeneric6DofSpringConstraint::calculateSerializeBufferSize() const +{ + return sizeof(btGeneric6DofSpringConstraintData); +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btGeneric6DofSpringConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btGeneric6DofSpringConstraintData* dof = (btGeneric6DofSpringConstraintData*)dataBuffer; + btGeneric6DofConstraint::serialize(&dof->m_6dofData,serializer); + + int i; + for (i=0;i<6;i++) + { + dof->m_equilibriumPoint[i] = m_equilibriumPoint[i]; + dof->m_springDamping[i] = m_springDamping[i]; + dof->m_springEnabled[i] = m_springEnabled[i]? 1 : 0; + dof->m_springStiffness[i] = m_springStiffness[i]; + } + return "btGeneric6DofConstraintData"; +} + +#endif // BT_GENERIC_6DOF_SPRING_CONSTRAINT_H + diff --git a/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp b/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp new file mode 100644 index 0000000..29123d5 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp @@ -0,0 +1,66 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +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 "btHinge2Constraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" + + + +// constructor +// anchor, axis1 and axis2 are in world coordinate system +// axis1 must be orthogonal to axis2 +btHinge2Constraint::btHinge2Constraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2) +: btGeneric6DofSpringConstraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), true), + m_anchor(anchor), + m_axis1(axis1), + m_axis2(axis2) +{ + // build frame basis + // 6DOF constraint uses Euler angles and to define limits + // it is assumed that rotational order is : + // Z - first, allowed limits are (-PI,PI); + // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number + // used to prevent constraint from instability on poles; + // new position of X, allowed limits are (-PI,PI); + // So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs + // Build the frame in world coordinate system first + btVector3 zAxis = axis1.normalize(); + btVector3 xAxis = axis2.normalize(); + btVector3 yAxis = zAxis.cross(xAxis); // we want right coordinate system + btTransform frameInW; + frameInW.setIdentity(); + frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0], + xAxis[1], yAxis[1], zAxis[1], + xAxis[2], yAxis[2], zAxis[2]); + frameInW.setOrigin(anchor); + // now get constraint frame in local coordinate systems + m_frameInA = rbA.getCenterOfMassTransform().inverse() * frameInW; + m_frameInB = rbB.getCenterOfMassTransform().inverse() * frameInW; + // sei limits + setLinearLowerLimit(btVector3(0.f, 0.f, -1.f)); + setLinearUpperLimit(btVector3(0.f, 0.f, 1.f)); + // like front wheels of a car + setAngularLowerLimit(btVector3(1.f, 0.f, -SIMD_HALF_PI * 0.5f)); + setAngularUpperLimit(btVector3(-1.f, 0.f, SIMD_HALF_PI * 0.5f)); + // enable suspension + enableSpring(2, true); + setStiffness(2, SIMD_PI * SIMD_PI * 4.f); // period 1 sec for 1 kilogramm weel :-) + setDamping(2, 0.01f); + setEquilibriumPoint(); +} + diff --git a/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h b/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h new file mode 100644 index 0000000..a76452d --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h @@ -0,0 +1,58 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_HINGE2_CONSTRAINT_H +#define BT_HINGE2_CONSTRAINT_H + + + +#include "LinearMath/btVector3.h" +#include "btTypedConstraint.h" +#include "btGeneric6DofSpringConstraint.h" + + + +// Constraint similar to ODE Hinge2 Joint +// has 3 degrees of frredom: +// 2 rotational degrees of freedom, similar to Euler rotations around Z (axis 1) and X (axis 2) +// 1 translational (along axis Z) with suspension spring + +class btHinge2Constraint : public btGeneric6DofSpringConstraint +{ +protected: + btVector3 m_anchor; + btVector3 m_axis1; + btVector3 m_axis2; +public: + // constructor + // anchor, axis1 and axis2 are in world coordinate system + // axis1 must be orthogonal to axis2 + btHinge2Constraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2); + // access + const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); } + const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); } + const btVector3& getAxis1() { return m_axis1; } + const btVector3& getAxis2() { return m_axis2; } + btScalar getAngle1() { return getAngle(2); } + btScalar getAngle2() { return getAngle(0); } + // limits + void setUpperLimit(btScalar ang1max) { setAngularUpperLimit(btVector3(-1.f, 0.f, ang1max)); } + void setLowerLimit(btScalar ang1min) { setAngularLowerLimit(btVector3( 1.f, 0.f, ang1min)); } +}; + + + +#endif // BT_HINGE2_CONSTRAINT_H + diff --git a/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp new file mode 100644 index 0000000..9e3a2ba --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp @@ -0,0 +1,1034 @@ +/* +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 "btHingeConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" +#include "LinearMath/btMinMax.h" +#include +#include "btSolverBody.h" + + + +//#define HINGE_USE_OBSOLETE_SOLVER false +#define HINGE_USE_OBSOLETE_SOLVER false + +#define HINGE_USE_FRAME_OFFSET true + +#ifndef __SPU__ + + + + + +btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, + const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA) + :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB), +#ifdef _BT_USE_CENTER_LIMIT_ + m_limit(), +#endif + m_angularOnly(false), + m_enableAngularMotor(false), + m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), + m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), + m_useReferenceFrameA(useReferenceFrameA), + m_flags(0) +{ + m_rbAFrame.getOrigin() = pivotInA; + + // since no frame is given, assume this to be zero angle and just pick rb transform axis + btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0); + + btVector3 rbAxisA2; + btScalar projection = axisInA.dot(rbAxisA1); + if (projection >= 1.0f - SIMD_EPSILON) { + rbAxisA1 = -rbA.getCenterOfMassTransform().getBasis().getColumn(2); + rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); + } else if (projection <= -1.0f + SIMD_EPSILON) { + rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(2); + rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); + } else { + rbAxisA2 = axisInA.cross(rbAxisA1); + rbAxisA1 = rbAxisA2.cross(axisInA); + } + + m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), + rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), + rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); + + btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); + btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); + btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); + + m_rbBFrame.getOrigin() = pivotInB; + m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(), + rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(), + rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() ); + +#ifndef _BT_USE_CENTER_LIMIT_ + //start with free + m_lowerLimit = btScalar(1.0f); + m_upperLimit = btScalar(-1.0f); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; +#endif + m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); +} + + + +btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA) +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), +#ifdef _BT_USE_CENTER_LIMIT_ +m_limit(), +#endif +m_angularOnly(false), m_enableAngularMotor(false), +m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), +m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), +m_useReferenceFrameA(useReferenceFrameA), +m_flags(0) +{ + + // since no frame is given, assume this to be zero angle and just pick rb transform axis + // fixed axis in worldspace + btVector3 rbAxisA1, rbAxisA2; + btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2); + + m_rbAFrame.getOrigin() = pivotInA; + m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), + rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), + rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); + + btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * axisInA; + + btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); + btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); + btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); + + + m_rbBFrame.getOrigin() = rbA.getCenterOfMassTransform()(pivotInA); + m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(), + rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(), + rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() ); + +#ifndef _BT_USE_CENTER_LIMIT_ + //start with free + m_lowerLimit = btScalar(1.0f); + m_upperLimit = btScalar(-1.0f); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; +#endif + m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); +} + + + +btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, + const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA) +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), +#ifdef _BT_USE_CENTER_LIMIT_ +m_limit(), +#endif +m_angularOnly(false), +m_enableAngularMotor(false), +m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), +m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), +m_useReferenceFrameA(useReferenceFrameA), +m_flags(0) +{ +#ifndef _BT_USE_CENTER_LIMIT_ + //start with free + m_lowerLimit = btScalar(1.0f); + m_upperLimit = btScalar(-1.0f); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; +#endif + m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); +} + + + +btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA) +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame), +#ifdef _BT_USE_CENTER_LIMIT_ +m_limit(), +#endif +m_angularOnly(false), +m_enableAngularMotor(false), +m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), +m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), +m_useReferenceFrameA(useReferenceFrameA), +m_flags(0) +{ + ///not providing rigidbody B means implicitly using worldspace for body B + + m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin()); +#ifndef _BT_USE_CENTER_LIMIT_ + //start with free + m_lowerLimit = btScalar(1.0f); + m_upperLimit = btScalar(-1.0f); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; +#endif + m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); +} + + + +void btHingeConstraint::buildJacobian() +{ + if (m_useSolveConstraintObsolete) + { + m_appliedImpulse = btScalar(0.); + m_accMotorImpulse = btScalar(0.); + + if (!m_angularOnly) + { + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + btVector3 relPos = pivotBInW - pivotAInW; + + btVector3 normal[3]; + if (relPos.length2() > SIMD_EPSILON) + { + normal[0] = relPos.normalized(); + } + else + { + normal[0].setValue(btScalar(1.0),0,0); + } + + btPlaneSpace1(normal[0], normal[1], normal[2]); + + for (int i=0;i<3;i++) + { + new (&m_jac[i]) btJacobianEntry( + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + pivotAInW - m_rbA.getCenterOfMassPosition(), + pivotBInW - m_rbB.getCenterOfMassPosition(), + normal[i], + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); + } + } + + //calculate two perpendicular jointAxis, orthogonal to hingeAxis + //these two jointAxis require equal angular velocities for both bodies + + //this is unused for now, it's a todo + btVector3 jointAxis0local; + btVector3 jointAxis1local; + + btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local); + + btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local; + btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local; + btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); + + new (&m_jacAng[0]) btJacobianEntry(jointAxis0, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + + new (&m_jacAng[1]) btJacobianEntry(jointAxis1, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + + new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + + // clear accumulator + m_accLimitImpulse = btScalar(0.); + + // test angular limit + testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + + //Compute K = J*W*J' for hinge axis + btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); + m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) + + getRigidBodyB().computeAngularImpulseDenominator(axisA)); + + } +} + + +#endif //__SPU__ + + +void btHingeConstraint::getInfo1(btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } + else + { + info->m_numConstraintRows = 5; // Fixed 3 linear + 2 angular + info->nub = 1; + //always add the row, to avoid computation (data is not available yet) + //prepare constraint + testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + if(getSolveLimit() || getEnableAngularMotor()) + { + info->m_numConstraintRows++; // limit 3rd anguar as well + info->nub--; + } + + } +} + +void btHingeConstraint::getInfo1NonVirtual(btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } + else + { + //always add the 'limit' row, to avoid computation (data is not available yet) + info->m_numConstraintRows = 6; // Fixed 3 linear + 2 angular + info->nub = 0; + } +} + +void btHingeConstraint::getInfo2 (btConstraintInfo2* info) +{ + if(m_useOffsetForConstraintFrame) + { + getInfo2InternalUsingFrameOffset(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getAngularVelocity(),m_rbB.getAngularVelocity()); + } + else + { + getInfo2Internal(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getAngularVelocity(),m_rbB.getAngularVelocity()); + } +} + + +void btHingeConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB) +{ + ///the regular (virtual) implementation getInfo2 already performs 'testLimit' during getInfo1, so we need to do it now + testLimit(transA,transB); + + getInfo2Internal(info,transA,transB,angVelA,angVelB); +} + + +void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB) +{ + + btAssert(!m_useSolveConstraintObsolete); + int i, skip = info->rowskip; + // transforms in world space + btTransform trA = transA*m_rbAFrame; + btTransform trB = transB*m_rbBFrame; + // pivot point + btVector3 pivotAInW = trA.getOrigin(); + btVector3 pivotBInW = trB.getOrigin(); +#if 0 + if (0) + { + for (i=0;i<6;i++) + { + info->m_J1linearAxis[i*skip]=0; + info->m_J1linearAxis[i*skip+1]=0; + info->m_J1linearAxis[i*skip+2]=0; + + info->m_J1angularAxis[i*skip]=0; + info->m_J1angularAxis[i*skip+1]=0; + info->m_J1angularAxis[i*skip+2]=0; + + info->m_J2angularAxis[i*skip]=0; + info->m_J2angularAxis[i*skip+1]=0; + info->m_J2angularAxis[i*skip+2]=0; + + info->m_constraintError[i*skip]=0.f; + } + } +#endif //#if 0 + // linear (all fixed) + + if (!m_angularOnly) + { + info->m_J1linearAxis[0] = 1; + info->m_J1linearAxis[skip + 1] = 1; + info->m_J1linearAxis[2 * skip + 2] = 1; + } + + + + + btVector3 a1 = pivotAInW - transA.getOrigin(); + { + btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + skip); + btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * skip); + btVector3 a1neg = -a1; + a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + btVector3 a2 = pivotBInW - transB.getOrigin(); + { + btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + skip); + btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * skip); + a2.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + // linear RHS + btScalar k = info->fps * info->erp; + if (!m_angularOnly) + { + for(i = 0; i < 3; i++) + { + info->m_constraintError[i * skip] = k * (pivotBInW[i] - pivotAInW[i]); + } + } + // make rotations around X and Y equal + // the hinge axis should be the only unconstrained + // rotational axis, the angular velocity of the two bodies perpendicular to + // the hinge axis should be equal. thus the constraint equations are + // p*w1 - p*w2 = 0 + // q*w1 - q*w2 = 0 + // where p and q are unit vectors normal to the hinge axis, and w1 and w2 + // are the angular velocity vectors of the two bodies. + // get hinge axis (Z) + btVector3 ax1 = trA.getBasis().getColumn(2); + // get 2 orthos to hinge axis (X, Y) + btVector3 p = trA.getBasis().getColumn(0); + btVector3 q = trA.getBasis().getColumn(1); + // set the two hinge angular rows + int s3 = 3 * info->rowskip; + int s4 = 4 * info->rowskip; + + info->m_J1angularAxis[s3 + 0] = p[0]; + info->m_J1angularAxis[s3 + 1] = p[1]; + info->m_J1angularAxis[s3 + 2] = p[2]; + info->m_J1angularAxis[s4 + 0] = q[0]; + info->m_J1angularAxis[s4 + 1] = q[1]; + info->m_J1angularAxis[s4 + 2] = q[2]; + + info->m_J2angularAxis[s3 + 0] = -p[0]; + info->m_J2angularAxis[s3 + 1] = -p[1]; + info->m_J2angularAxis[s3 + 2] = -p[2]; + info->m_J2angularAxis[s4 + 0] = -q[0]; + info->m_J2angularAxis[s4 + 1] = -q[1]; + info->m_J2angularAxis[s4 + 2] = -q[2]; + // compute the right hand side of the constraint equation. set relative + // body velocities along p and q to bring the hinge back into alignment. + // if ax1,ax2 are the unit length hinge axes as computed from body1 and + // body2, we need to rotate both bodies along the axis u = (ax1 x ax2). + // if `theta' is the angle between ax1 and ax2, we need an angular velocity + // along u to cover angle erp*theta in one step : + // |angular_velocity| = angle/time = erp*theta / stepsize + // = (erp*fps) * theta + // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| + // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) + // ...as ax1 and ax2 are unit length. if theta is smallish, + // theta ~= sin(theta), so + // angular_velocity = (erp*fps) * (ax1 x ax2) + // ax1 x ax2 is in the plane space of ax1, so we project the angular + // velocity to p and q to find the right hand side. + btVector3 ax2 = trB.getBasis().getColumn(2); + btVector3 u = ax1.cross(ax2); + info->m_constraintError[s3] = k * u.dot(p); + info->m_constraintError[s4] = k * u.dot(q); + // check angular limits + int nrow = 4; // last filled row + int srow; + btScalar limit_err = btScalar(0.0); + int limit = 0; + if(getSolveLimit()) + { +#ifdef _BT_USE_CENTER_LIMIT_ + limit_err = m_limit.getCorrection() * m_referenceSign; +#else + limit_err = m_correction * m_referenceSign; +#endif + limit = (limit_err > btScalar(0.0)) ? 1 : 2; + + } + // if the hinge has joint limits or motor, add in the extra row + int powered = 0; + if(getEnableAngularMotor()) + { + powered = 1; + } + if(limit || powered) + { + nrow++; + srow = nrow * info->rowskip; + info->m_J1angularAxis[srow+0] = ax1[0]; + info->m_J1angularAxis[srow+1] = ax1[1]; + info->m_J1angularAxis[srow+2] = ax1[2]; + + info->m_J2angularAxis[srow+0] = -ax1[0]; + info->m_J2angularAxis[srow+1] = -ax1[1]; + info->m_J2angularAxis[srow+2] = -ax1[2]; + + btScalar lostop = getLowerLimit(); + btScalar histop = getUpperLimit(); + if(limit && (lostop == histop)) + { // the joint motor is ineffective + powered = 0; + } + info->m_constraintError[srow] = btScalar(0.0f); + btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : info->erp; + if(powered) + { + if(m_flags & BT_HINGE_FLAGS_CFM_NORM) + { + info->cfm[srow] = m_normalCFM; + } + btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP); + info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign; + info->m_lowerLimit[srow] = - m_maxMotorImpulse; + info->m_upperLimit[srow] = m_maxMotorImpulse; + } + if(limit) + { + k = info->fps * currERP; + info->m_constraintError[srow] += k * limit_err; + if(m_flags & BT_HINGE_FLAGS_CFM_STOP) + { + info->cfm[srow] = m_stopCFM; + } + if(lostop == histop) + { + // limited low and high simultaneously + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else if(limit == 1) + { // low limit + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { // high limit + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that) +#ifdef _BT_USE_CENTER_LIMIT_ + btScalar bounce = m_limit.getRelaxationFactor(); +#else + btScalar bounce = m_relaxationFactor; +#endif + if(bounce > btScalar(0.0)) + { + btScalar vel = angVelA.dot(ax1); + vel -= angVelB.dot(ax1); + // only apply bounce if the velocity is incoming, and if the + // resulting c[] exceeds what we already have. + if(limit == 1) + { // low limit + if(vel < 0) + { + btScalar newc = -bounce * vel; + if(newc > info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + else + { // high limit - all those computations are reversed + if(vel > 0) + { + btScalar newc = -bounce * vel; + if(newc < info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + } +#ifdef _BT_USE_CENTER_LIMIT_ + info->m_constraintError[srow] *= m_limit.getBiasFactor(); +#else + info->m_constraintError[srow] *= m_biasFactor; +#endif + } // if(limit) + } // if angular limit or powered +} + + +void btHingeConstraint::setFrames(const btTransform & frameA, const btTransform & frameB) +{ + m_rbAFrame = frameA; + m_rbBFrame = frameB; + buildJacobian(); +} + + +void btHingeConstraint::updateRHS(btScalar timeStep) +{ + (void)timeStep; + +} + + +btScalar btHingeConstraint::getHingeAngle() +{ + return getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); +} + +btScalar btHingeConstraint::getHingeAngle(const btTransform& transA,const btTransform& transB) +{ + const btVector3 refAxis0 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0); + const btVector3 refAxis1 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1); + const btVector3 swingAxis = transB.getBasis() * m_rbBFrame.getBasis().getColumn(1); +// btScalar angle = btAtan2Fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); + btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); + return m_referenceSign * angle; +} + + + +void btHingeConstraint::testLimit(const btTransform& transA,const btTransform& transB) +{ + // Compute limit information + m_hingeAngle = getHingeAngle(transA,transB); +#ifdef _BT_USE_CENTER_LIMIT_ + m_limit.test(m_hingeAngle); +#else + m_correction = btScalar(0.); + m_limitSign = btScalar(0.); + m_solveLimit = false; + if (m_lowerLimit <= m_upperLimit) + { + m_hingeAngle = btAdjustAngleToLimits(m_hingeAngle, m_lowerLimit, m_upperLimit); + if (m_hingeAngle <= m_lowerLimit) + { + m_correction = (m_lowerLimit - m_hingeAngle); + m_limitSign = 1.0f; + m_solveLimit = true; + } + else if (m_hingeAngle >= m_upperLimit) + { + m_correction = m_upperLimit - m_hingeAngle; + m_limitSign = -1.0f; + m_solveLimit = true; + } + } +#endif + return; +} + + +static btVector3 vHinge(0, 0, btScalar(1)); + +void btHingeConstraint::setMotorTarget(const btQuaternion& qAinB, btScalar dt) +{ + // convert target from body to constraint space + btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * qAinB * m_rbAFrame.getRotation(); + qConstraint.normalize(); + + // extract "pure" hinge component + btVector3 vNoHinge = quatRotate(qConstraint, vHinge); vNoHinge.normalize(); + btQuaternion qNoHinge = shortestArcQuat(vHinge, vNoHinge); + btQuaternion qHinge = qNoHinge.inverse() * qConstraint; + qHinge.normalize(); + + // compute angular target, clamped to limits + btScalar targetAngle = qHinge.getAngle(); + if (targetAngle > SIMD_PI) // long way around. flip quat and recalculate. + { + qHinge = -(qHinge); + targetAngle = qHinge.getAngle(); + } + if (qHinge.getZ() < 0) + targetAngle = -targetAngle; + + setMotorTarget(targetAngle, dt); +} + +void btHingeConstraint::setMotorTarget(btScalar targetAngle, btScalar dt) +{ +#ifdef _BT_USE_CENTER_LIMIT_ + m_limit.fit(targetAngle); +#else + if (m_lowerLimit < m_upperLimit) + { + if (targetAngle < m_lowerLimit) + targetAngle = m_lowerLimit; + else if (targetAngle > m_upperLimit) + targetAngle = m_upperLimit; + } +#endif + // compute angular velocity + btScalar curAngle = getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + btScalar dAngle = targetAngle - curAngle; + m_motorTargetVelocity = dAngle / dt; +} + + + +void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB) +{ + btAssert(!m_useSolveConstraintObsolete); + int i, s = info->rowskip; + // transforms in world space + btTransform trA = transA*m_rbAFrame; + btTransform trB = transB*m_rbBFrame; + // pivot point + btVector3 pivotAInW = trA.getOrigin(); + btVector3 pivotBInW = trB.getOrigin(); +#if 1 + // difference between frames in WCS + btVector3 ofs = trB.getOrigin() - trA.getOrigin(); + // now get weight factors depending on masses + btScalar miA = getRigidBodyA().getInvMass(); + btScalar miB = getRigidBodyB().getInvMass(); + bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON); + btScalar miS = miA + miB; + btScalar factA, factB; + if(miS > btScalar(0.f)) + { + factA = miB / miS; + } + else + { + factA = btScalar(0.5f); + } + factB = btScalar(1.0f) - factA; + // get the desired direction of hinge axis + // as weighted sum of Z-orthos of frameA and frameB in WCS + btVector3 ax1A = trA.getBasis().getColumn(2); + btVector3 ax1B = trB.getBasis().getColumn(2); + btVector3 ax1 = ax1A * factA + ax1B * factB; + ax1.normalize(); + // fill first 3 rows + // we want: velA + wA x relA == velB + wB x relB + btTransform bodyA_trans = transA; + btTransform bodyB_trans = transB; + int s0 = 0; + int s1 = s; + int s2 = s * 2; + int nrow = 2; // last filled row + btVector3 tmpA, tmpB, relA, relB, p, q; + // get vector from bodyB to frameB in WCS + relB = trB.getOrigin() - bodyB_trans.getOrigin(); + // get its projection to hinge axis + btVector3 projB = ax1 * relB.dot(ax1); + // get vector directed from bodyB to hinge axis (and orthogonal to it) + btVector3 orthoB = relB - projB; + // same for bodyA + relA = trA.getOrigin() - bodyA_trans.getOrigin(); + btVector3 projA = ax1 * relA.dot(ax1); + btVector3 orthoA = relA - projA; + btVector3 totalDist = projA - projB; + // get offset vectors relA and relB + relA = orthoA + totalDist * factA; + relB = orthoB - totalDist * factB; + // now choose average ortho to hinge axis + p = orthoB * factA + orthoA * factB; + btScalar len2 = p.length2(); + if(len2 > SIMD_EPSILON) + { + p /= btSqrt(len2); + } + else + { + p = trA.getBasis().getColumn(1); + } + // make one more ortho + q = ax1.cross(p); + // fill three rows + tmpA = relA.cross(p); + tmpB = relB.cross(p); + for (i=0; i<3; i++) info->m_J1angularAxis[s0+i] = tmpA[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[s0+i] = -tmpB[i]; + tmpA = relA.cross(q); + tmpB = relB.cross(q); + if(hasStaticBody && getSolveLimit()) + { // to make constraint between static and dynamic objects more rigid + // remove wA (or wB) from equation if angular limit is hit + tmpB *= factB; + tmpA *= factA; + } + for (i=0; i<3; i++) info->m_J1angularAxis[s1+i] = tmpA[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[s1+i] = -tmpB[i]; + tmpA = relA.cross(ax1); + tmpB = relB.cross(ax1); + if(hasStaticBody) + { // to make constraint between static and dynamic objects more rigid + // remove wA (or wB) from equation + tmpB *= factB; + tmpA *= factA; + } + for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i]; + + btScalar k = info->fps * info->erp; + + if (!m_angularOnly) + { + for (i=0; i<3; i++) info->m_J1linearAxis[s0+i] = p[i]; + for (i=0; i<3; i++) info->m_J1linearAxis[s1+i] = q[i]; + for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = ax1[i]; + + // compute three elements of right hand side + + btScalar rhs = k * p.dot(ofs); + info->m_constraintError[s0] = rhs; + rhs = k * q.dot(ofs); + info->m_constraintError[s1] = rhs; + rhs = k * ax1.dot(ofs); + info->m_constraintError[s2] = rhs; + } + // the hinge axis should be the only unconstrained + // rotational axis, the angular velocity of the two bodies perpendicular to + // the hinge axis should be equal. thus the constraint equations are + // p*w1 - p*w2 = 0 + // q*w1 - q*w2 = 0 + // where p and q are unit vectors normal to the hinge axis, and w1 and w2 + // are the angular velocity vectors of the two bodies. + int s3 = 3 * s; + int s4 = 4 * s; + info->m_J1angularAxis[s3 + 0] = p[0]; + info->m_J1angularAxis[s3 + 1] = p[1]; + info->m_J1angularAxis[s3 + 2] = p[2]; + info->m_J1angularAxis[s4 + 0] = q[0]; + info->m_J1angularAxis[s4 + 1] = q[1]; + info->m_J1angularAxis[s4 + 2] = q[2]; + + info->m_J2angularAxis[s3 + 0] = -p[0]; + info->m_J2angularAxis[s3 + 1] = -p[1]; + info->m_J2angularAxis[s3 + 2] = -p[2]; + info->m_J2angularAxis[s4 + 0] = -q[0]; + info->m_J2angularAxis[s4 + 1] = -q[1]; + info->m_J2angularAxis[s4 + 2] = -q[2]; + // compute the right hand side of the constraint equation. set relative + // body velocities along p and q to bring the hinge back into alignment. + // if ax1A,ax1B are the unit length hinge axes as computed from bodyA and + // bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2). + // if "theta" is the angle between ax1 and ax2, we need an angular velocity + // along u to cover angle erp*theta in one step : + // |angular_velocity| = angle/time = erp*theta / stepsize + // = (erp*fps) * theta + // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| + // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) + // ...as ax1 and ax2 are unit length. if theta is smallish, + // theta ~= sin(theta), so + // angular_velocity = (erp*fps) * (ax1 x ax2) + // ax1 x ax2 is in the plane space of ax1, so we project the angular + // velocity to p and q to find the right hand side. + k = info->fps * info->erp; + btVector3 u = ax1A.cross(ax1B); + info->m_constraintError[s3] = k * u.dot(p); + info->m_constraintError[s4] = k * u.dot(q); +#endif + // check angular limits + nrow = 4; // last filled row + int srow; + btScalar limit_err = btScalar(0.0); + int limit = 0; + if(getSolveLimit()) + { +#ifdef _BT_USE_CENTER_LIMIT_ + limit_err = m_limit.getCorrection() * m_referenceSign; +#else + limit_err = m_correction * m_referenceSign; +#endif + limit = (limit_err > btScalar(0.0)) ? 1 : 2; + + } + // if the hinge has joint limits or motor, add in the extra row + int powered = 0; + if(getEnableAngularMotor()) + { + powered = 1; + } + if(limit || powered) + { + nrow++; + srow = nrow * info->rowskip; + info->m_J1angularAxis[srow+0] = ax1[0]; + info->m_J1angularAxis[srow+1] = ax1[1]; + info->m_J1angularAxis[srow+2] = ax1[2]; + + info->m_J2angularAxis[srow+0] = -ax1[0]; + info->m_J2angularAxis[srow+1] = -ax1[1]; + info->m_J2angularAxis[srow+2] = -ax1[2]; + + btScalar lostop = getLowerLimit(); + btScalar histop = getUpperLimit(); + if(limit && (lostop == histop)) + { // the joint motor is ineffective + powered = 0; + } + info->m_constraintError[srow] = btScalar(0.0f); + btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : info->erp; + if(powered) + { + if(m_flags & BT_HINGE_FLAGS_CFM_NORM) + { + info->cfm[srow] = m_normalCFM; + } + btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP); + info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign; + info->m_lowerLimit[srow] = - m_maxMotorImpulse; + info->m_upperLimit[srow] = m_maxMotorImpulse; + } + if(limit) + { + k = info->fps * currERP; + info->m_constraintError[srow] += k * limit_err; + if(m_flags & BT_HINGE_FLAGS_CFM_STOP) + { + info->cfm[srow] = m_stopCFM; + } + if(lostop == histop) + { + // limited low and high simultaneously + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else if(limit == 1) + { // low limit + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { // high limit + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that) +#ifdef _BT_USE_CENTER_LIMIT_ + btScalar bounce = m_limit.getRelaxationFactor(); +#else + btScalar bounce = m_relaxationFactor; +#endif + if(bounce > btScalar(0.0)) + { + btScalar vel = angVelA.dot(ax1); + vel -= angVelB.dot(ax1); + // only apply bounce if the velocity is incoming, and if the + // resulting c[] exceeds what we already have. + if(limit == 1) + { // low limit + if(vel < 0) + { + btScalar newc = -bounce * vel; + if(newc > info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + else + { // high limit - all those computations are reversed + if(vel > 0) + { + btScalar newc = -bounce * vel; + if(newc < info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + } +#ifdef _BT_USE_CENTER_LIMIT_ + info->m_constraintError[srow] *= m_limit.getBiasFactor(); +#else + info->m_constraintError[srow] *= m_biasFactor; +#endif + } // if(limit) + } // if angular limit or powered +} + + +///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). +///If no axis is provided, it uses the default axis for this constraint. +void btHingeConstraint::setParam(int num, btScalar value, int axis) +{ + if((axis == -1) || (axis == 5)) + { + switch(num) + { + case BT_CONSTRAINT_STOP_ERP : + m_stopERP = value; + m_flags |= BT_HINGE_FLAGS_ERP_STOP; + break; + case BT_CONSTRAINT_STOP_CFM : + m_stopCFM = value; + m_flags |= BT_HINGE_FLAGS_CFM_STOP; + break; + case BT_CONSTRAINT_CFM : + m_normalCFM = value; + m_flags |= BT_HINGE_FLAGS_CFM_NORM; + break; + default : + btAssertConstrParams(0); + } + } + else + { + btAssertConstrParams(0); + } +} + +///return the local value of parameter +btScalar btHingeConstraint::getParam(int num, int axis) const +{ + btScalar retVal = 0; + if((axis == -1) || (axis == 5)) + { + switch(num) + { + case BT_CONSTRAINT_STOP_ERP : + btAssertConstrParams(m_flags & BT_HINGE_FLAGS_ERP_STOP); + retVal = m_stopERP; + break; + case BT_CONSTRAINT_STOP_CFM : + btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_STOP); + retVal = m_stopCFM; + break; + case BT_CONSTRAINT_CFM : + btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_NORM); + retVal = m_normalCFM; + break; + default : + btAssertConstrParams(0); + } + } + else + { + btAssertConstrParams(0); + } + return retVal; +} + + diff --git a/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h new file mode 100644 index 0000000..cb2973e --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h @@ -0,0 +1,381 @@ +/* +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. +*/ + +/* Hinge Constraint by Dirk Gregorius. Limits added by Marcus Hennix at Starbreeze Studios */ + +#ifndef BT_HINGECONSTRAINT_H +#define BT_HINGECONSTRAINT_H + +#define _BT_USE_CENTER_LIMIT_ 1 + + +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" + +class btRigidBody; + +#ifdef BT_USE_DOUBLE_PRECISION +#define btHingeConstraintData btHingeConstraintDoubleData +#define btHingeConstraintDataName "btHingeConstraintDoubleData" +#else +#define btHingeConstraintData btHingeConstraintFloatData +#define btHingeConstraintDataName "btHingeConstraintFloatData" +#endif //BT_USE_DOUBLE_PRECISION + + + +enum btHingeFlags +{ + BT_HINGE_FLAGS_CFM_STOP = 1, + BT_HINGE_FLAGS_ERP_STOP = 2, + BT_HINGE_FLAGS_CFM_NORM = 4 +}; + + +/// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space +/// axis defines the orientation of the hinge axis +ATTRIBUTE_ALIGNED16(class) btHingeConstraint : public btTypedConstraint +{ +#ifdef IN_PARALLELL_SOLVER +public: +#endif + btJacobianEntry m_jac[3]; //3 orthogonal linear constraints + btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor + + btTransform m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransform m_rbBFrame; + + btScalar m_motorTargetVelocity; + btScalar m_maxMotorImpulse; + + +#ifdef _BT_USE_CENTER_LIMIT_ + btAngularLimit m_limit; +#else + btScalar m_lowerLimit; + btScalar m_upperLimit; + btScalar m_limitSign; + btScalar m_correction; + + btScalar m_limitSoftness; + btScalar m_biasFactor; + btScalar m_relaxationFactor; + + bool m_solveLimit; +#endif + + btScalar m_kHinge; + + + btScalar m_accLimitImpulse; + btScalar m_hingeAngle; + btScalar m_referenceSign; + + bool m_angularOnly; + bool m_enableAngularMotor; + bool m_useSolveConstraintObsolete; + bool m_useOffsetForConstraintFrame; + bool m_useReferenceFrameA; + + btScalar m_accMotorImpulse; + + int m_flags; + btScalar m_normalCFM; + btScalar m_stopCFM; + btScalar m_stopERP; + + +public: + + btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA = false); + + btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA = false); + + btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false); + + btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA = false); + + + virtual void buildJacobian(); + + virtual void getInfo1 (btConstraintInfo1* info); + + void getInfo1NonVirtual(btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB); + + void getInfo2Internal(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB); + void getInfo2InternalUsingFrameOffset(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB); + + + void updateRHS(btScalar timeStep); + + const btRigidBody& getRigidBodyA() const + { + return m_rbA; + } + const btRigidBody& getRigidBodyB() const + { + return m_rbB; + } + + btRigidBody& getRigidBodyA() + { + return m_rbA; + } + + btRigidBody& getRigidBodyB() + { + return m_rbB; + } + + btTransform& getFrameOffsetA() + { + return m_rbAFrame; + } + + btTransform& getFrameOffsetB() + { + return m_rbBFrame; + } + + void setFrames(const btTransform& frameA, const btTransform& frameB); + + void setAngularOnly(bool angularOnly) + { + m_angularOnly = angularOnly; + } + + void enableAngularMotor(bool enableMotor,btScalar targetVelocity,btScalar maxMotorImpulse) + { + m_enableAngularMotor = enableMotor; + m_motorTargetVelocity = targetVelocity; + m_maxMotorImpulse = maxMotorImpulse; + } + + // extra motor API, including ability to set a target rotation (as opposed to angular velocity) + // note: setMotorTarget sets angular velocity under the hood, so you must call it every tick to + // maintain a given angular target. + void enableMotor(bool enableMotor) { m_enableAngularMotor = enableMotor; } + void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; } + void setMotorTarget(const btQuaternion& qAinB, btScalar dt); // qAinB is rotation of body A wrt body B. + void setMotorTarget(btScalar targetAngle, btScalar dt); + + + void setLimit(btScalar low,btScalar high,btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) + { +#ifdef _BT_USE_CENTER_LIMIT_ + m_limit.set(low, high, _softness, _biasFactor, _relaxationFactor); +#else + m_lowerLimit = btNormalizeAngle(low); + m_upperLimit = btNormalizeAngle(high); + m_limitSoftness = _softness; + m_biasFactor = _biasFactor; + m_relaxationFactor = _relaxationFactor; +#endif + } + + void setAxis(btVector3& axisInA) + { + btVector3 rbAxisA1, rbAxisA2; + btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2); + btVector3 pivotInA = m_rbAFrame.getOrigin(); +// m_rbAFrame.getOrigin() = pivotInA; + m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), + rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), + rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); + + btVector3 axisInB = m_rbA.getCenterOfMassTransform().getBasis() * axisInA; + + btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); + btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); + btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); + + m_rbBFrame.getOrigin() = m_rbB.getCenterOfMassTransform().inverse()(m_rbA.getCenterOfMassTransform()(pivotInA)); + + m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(), + rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(), + rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() ); + m_rbBFrame.getBasis() = m_rbB.getCenterOfMassTransform().getBasis().inverse() * m_rbBFrame.getBasis(); + + } + + btScalar getLowerLimit() const + { +#ifdef _BT_USE_CENTER_LIMIT_ + return m_limit.getLow(); +#else + return m_lowerLimit; +#endif + } + + btScalar getUpperLimit() const + { +#ifdef _BT_USE_CENTER_LIMIT_ + return m_limit.getHigh(); +#else + return m_upperLimit; +#endif + } + + + btScalar getHingeAngle(); + + btScalar getHingeAngle(const btTransform& transA,const btTransform& transB); + + void testLimit(const btTransform& transA,const btTransform& transB); + + + const btTransform& getAFrame() const { return m_rbAFrame; }; + const btTransform& getBFrame() const { return m_rbBFrame; }; + + btTransform& getAFrame() { return m_rbAFrame; }; + btTransform& getBFrame() { return m_rbBFrame; }; + + inline int getSolveLimit() + { +#ifdef _BT_USE_CENTER_LIMIT_ + return m_limit.isLimit(); +#else + return m_solveLimit; +#endif + } + + inline btScalar getLimitSign() + { +#ifdef _BT_USE_CENTER_LIMIT_ + return m_limit.getSign(); +#else + return m_limitSign; +#endif + } + + inline bool getAngularOnly() + { + return m_angularOnly; + } + inline bool getEnableAngularMotor() + { + return m_enableAngularMotor; + } + inline btScalar getMotorTargetVelosity() + { + return m_motorTargetVelocity; + } + inline btScalar getMaxMotorImpulse() + { + return m_maxMotorImpulse; + } + // access for UseFrameOffset + bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; } + void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; } + + + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///If no axis is provided, it uses the default axis for this constraint. + virtual void setParam(int num, btScalar value, int axis = -1); + ///return the local value of parameter + virtual btScalar getParam(int num, int axis = -1) const; + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btHingeConstraintDoubleData +{ + btTypedConstraintData m_typeConstraintData; + btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransformDoubleData m_rbBFrame; + int m_useReferenceFrameA; + int m_angularOnly; + int m_enableAngularMotor; + float m_motorTargetVelocity; + float m_maxMotorImpulse; + + float m_lowerLimit; + float m_upperLimit; + float m_limitSoftness; + float m_biasFactor; + float m_relaxationFactor; + +}; +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btHingeConstraintFloatData +{ + btTypedConstraintData m_typeConstraintData; + btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransformFloatData m_rbBFrame; + int m_useReferenceFrameA; + int m_angularOnly; + + int m_enableAngularMotor; + float m_motorTargetVelocity; + float m_maxMotorImpulse; + + float m_lowerLimit; + float m_upperLimit; + float m_limitSoftness; + float m_biasFactor; + float m_relaxationFactor; + +}; + + + +SIMD_FORCE_INLINE int btHingeConstraint::calculateSerializeBufferSize() const +{ + return sizeof(btHingeConstraintData); +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btHingeConstraintData* hingeData = (btHingeConstraintData*)dataBuffer; + btTypedConstraint::serialize(&hingeData->m_typeConstraintData,serializer); + + m_rbAFrame.serialize(hingeData->m_rbAFrame); + m_rbBFrame.serialize(hingeData->m_rbBFrame); + + hingeData->m_angularOnly = m_angularOnly; + hingeData->m_enableAngularMotor = m_enableAngularMotor; + hingeData->m_maxMotorImpulse = float(m_maxMotorImpulse); + hingeData->m_motorTargetVelocity = float(m_motorTargetVelocity); + hingeData->m_useReferenceFrameA = m_useReferenceFrameA; +#ifdef _BT_USE_CENTER_LIMIT_ + hingeData->m_lowerLimit = float(m_limit.getLow()); + hingeData->m_upperLimit = float(m_limit.getHigh()); + hingeData->m_limitSoftness = float(m_limit.getSoftness()); + hingeData->m_biasFactor = float(m_limit.getBiasFactor()); + hingeData->m_relaxationFactor = float(m_limit.getRelaxationFactor()); +#else + hingeData->m_lowerLimit = float(m_lowerLimit); + hingeData->m_upperLimit = float(m_upperLimit); + hingeData->m_limitSoftness = float(m_limitSoftness); + hingeData->m_biasFactor = float(m_biasFactor); + hingeData->m_relaxationFactor = float(m_relaxationFactor); +#endif + + return btHingeConstraintDataName; +} + +#endif //BT_HINGECONSTRAINT_H diff --git a/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h new file mode 100644 index 0000000..f1994a2 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h @@ -0,0 +1,156 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_JACOBIAN_ENTRY_H +#define BT_JACOBIAN_ENTRY_H + +#include "LinearMath/btVector3.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" + + +//notes: +// Another memory optimization would be to store m_1MinvJt in the remaining 3 w components +// which makes the btJacobianEntry memory layout 16 bytes +// if you only are interested in angular part, just feed massInvA and massInvB zero + +/// Jacobian entry is an abstraction that allows to describe constraints +/// it can be used in combination with a constraint solver +/// Can be used to relate the effect of an impulse to the constraint error +ATTRIBUTE_ALIGNED16(class) btJacobianEntry +{ +public: + btJacobianEntry() {}; + //constraint between two different rigidbodies + btJacobianEntry( + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + const btVector3& rel_pos1,const btVector3& rel_pos2, + const btVector3& jointAxis, + const btVector3& inertiaInvA, + const btScalar massInvA, + const btVector3& inertiaInvB, + const btScalar massInvB) + :m_linearJointAxis(jointAxis) + { + m_aJ = world2A*(rel_pos1.cross(m_linearJointAxis)); + m_bJ = world2B*(rel_pos2.cross(-m_linearJointAxis)); + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = inertiaInvB * m_bJ; + m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ); + + btAssert(m_Adiag > btScalar(0.0)); + } + + //angular constraint between two different rigidbodies + btJacobianEntry(const btVector3& jointAxis, + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + const btVector3& inertiaInvA, + const btVector3& inertiaInvB) + :m_linearJointAxis(btVector3(btScalar(0.),btScalar(0.),btScalar(0.))) + { + m_aJ= world2A*jointAxis; + m_bJ = world2B*-jointAxis; + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = inertiaInvB * m_bJ; + m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ); + + btAssert(m_Adiag > btScalar(0.0)); + } + + //angular constraint between two different rigidbodies + btJacobianEntry(const btVector3& axisInA, + const btVector3& axisInB, + const btVector3& inertiaInvA, + const btVector3& inertiaInvB) + : m_linearJointAxis(btVector3(btScalar(0.),btScalar(0.),btScalar(0.))) + , m_aJ(axisInA) + , m_bJ(-axisInB) + { + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = inertiaInvB * m_bJ; + m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ); + + btAssert(m_Adiag > btScalar(0.0)); + } + + //constraint on one rigidbody + btJacobianEntry( + const btMatrix3x3& world2A, + const btVector3& rel_pos1,const btVector3& rel_pos2, + const btVector3& jointAxis, + const btVector3& inertiaInvA, + const btScalar massInvA) + :m_linearJointAxis(jointAxis) + { + m_aJ= world2A*(rel_pos1.cross(jointAxis)); + m_bJ = world2A*(rel_pos2.cross(-jointAxis)); + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = btVector3(btScalar(0.),btScalar(0.),btScalar(0.)); + m_Adiag = massInvA + m_0MinvJt.dot(m_aJ); + + btAssert(m_Adiag > btScalar(0.0)); + } + + btScalar getDiagonal() const { return m_Adiag; } + + // for two constraints on the same rigidbody (for example vehicle friction) + btScalar getNonDiagonal(const btJacobianEntry& jacB, const btScalar massInvA) const + { + const btJacobianEntry& jacA = *this; + btScalar lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis); + btScalar ang = jacA.m_0MinvJt.dot(jacB.m_aJ); + return lin + ang; + } + + + + // for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies) + btScalar getNonDiagonal(const btJacobianEntry& jacB,const btScalar massInvA,const btScalar massInvB) const + { + const btJacobianEntry& jacA = *this; + btVector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis; + btVector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ; + btVector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ; + btVector3 lin0 = massInvA * lin ; + btVector3 lin1 = massInvB * lin; + btVector3 sum = ang0+ang1+lin0+lin1; + return sum[0]+sum[1]+sum[2]; + } + + btScalar getRelativeVelocity(const btVector3& linvelA,const btVector3& angvelA,const btVector3& linvelB,const btVector3& angvelB) + { + btVector3 linrel = linvelA - linvelB; + btVector3 angvela = angvelA * m_aJ; + btVector3 angvelb = angvelB * m_bJ; + linrel *= m_linearJointAxis; + angvela += angvelb; + angvela += linrel; + btScalar rel_vel2 = angvela[0]+angvela[1]+angvela[2]; + return rel_vel2 + SIMD_EPSILON; + } +//private: + + btVector3 m_linearJointAxis; + btVector3 m_aJ; + btVector3 m_bJ; + btVector3 m_0MinvJt; + btVector3 m_1MinvJt; + //Optimization: can be stored in the w/last component of one of the vectors + btScalar m_Adiag; + +}; + +#endif //BT_JACOBIAN_ENTRY_H diff --git a/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp new file mode 100644 index 0000000..7e0d93b --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp @@ -0,0 +1,230 @@ +/* +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 "btPoint2PointConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include + + + + + +btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB) +:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB), +m_flags(0), +m_useSolveConstraintObsolete(false) +{ + +} + + +btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA) +:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)), +m_flags(0), +m_useSolveConstraintObsolete(false) +{ + +} + +void btPoint2PointConstraint::buildJacobian() +{ + + ///we need it for both methods + { + m_appliedImpulse = btScalar(0.); + + btVector3 normal(0,0,0); + + for (int i=0;i<3;i++) + { + normal[i] = 1; + new (&m_jac[i]) btJacobianEntry( + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getCenterOfMassTransform()*m_pivotInA - m_rbA.getCenterOfMassPosition(), + m_rbB.getCenterOfMassTransform()*m_pivotInB - m_rbB.getCenterOfMassPosition(), + normal, + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); + normal[i] = 0; + } + } + + +} + +void btPoint2PointConstraint::getInfo1 (btConstraintInfo1* info) +{ + getInfo1NonVirtual(info); +} + +void btPoint2PointConstraint::getInfo1NonVirtual (btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } else + { + info->m_numConstraintRows = 3; + info->nub = 3; + } +} + + + + +void btPoint2PointConstraint::getInfo2 (btConstraintInfo2* info) +{ + getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); +} + +void btPoint2PointConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans) +{ + btAssert(!m_useSolveConstraintObsolete); + + //retrieve matrices + + // anchor points in global coordinates with respect to body PORs. + + // set jacobian + info->m_J1linearAxis[0] = 1; + info->m_J1linearAxis[info->rowskip+1] = 1; + info->m_J1linearAxis[2*info->rowskip+2] = 1; + + btVector3 a1 = body0_trans.getBasis()*getPivotInA(); + { + btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip); + btVector3 a1neg = -a1; + a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + + /*info->m_J2linearAxis[0] = -1; + info->m_J2linearAxis[s+1] = -1; + info->m_J2linearAxis[2*s+2] = -1; + */ + + btVector3 a2 = body1_trans.getBasis()*getPivotInB(); + + { + btVector3 a2n = -a2; + btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip); + a2.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + + + + // set right hand side + btScalar currERP = (m_flags & BT_P2P_FLAGS_ERP) ? m_erp : info->erp; + btScalar k = info->fps * currERP; + int j; + for (j=0; j<3; j++) + { + info->m_constraintError[j*info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]); + //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]); + } + if(m_flags & BT_P2P_FLAGS_CFM) + { + for (j=0; j<3; j++) + { + info->cfm[j*info->rowskip] = m_cfm; + } + } + + btScalar impulseClamp = m_setting.m_impulseClamp;// + for (j=0; j<3; j++) + { + if (m_setting.m_impulseClamp > 0) + { + info->m_lowerLimit[j*info->rowskip] = -impulseClamp; + info->m_upperLimit[j*info->rowskip] = impulseClamp; + } + } + info->m_damping = m_setting.m_damping; + +} + + + +void btPoint2PointConstraint::updateRHS(btScalar timeStep) +{ + (void)timeStep; + +} + +///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). +///If no axis is provided, it uses the default axis for this constraint. +void btPoint2PointConstraint::setParam(int num, btScalar value, int axis) +{ + if(axis != -1) + { + btAssertConstrParams(0); + } + else + { + switch(num) + { + case BT_CONSTRAINT_ERP : + case BT_CONSTRAINT_STOP_ERP : + m_erp = value; + m_flags |= BT_P2P_FLAGS_ERP; + break; + case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_STOP_CFM : + m_cfm = value; + m_flags |= BT_P2P_FLAGS_CFM; + break; + default: + btAssertConstrParams(0); + } + } +} + +///return the local value of parameter +btScalar btPoint2PointConstraint::getParam(int num, int axis) const +{ + btScalar retVal(SIMD_INFINITY); + if(axis != -1) + { + btAssertConstrParams(0); + } + else + { + switch(num) + { + case BT_CONSTRAINT_ERP : + case BT_CONSTRAINT_STOP_ERP : + btAssertConstrParams(m_flags & BT_P2P_FLAGS_ERP); + retVal = m_erp; + break; + case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_STOP_CFM : + btAssertConstrParams(m_flags & BT_P2P_FLAGS_CFM); + retVal = m_cfm; + break; + default: + btAssertConstrParams(0); + } + } + return retVal; +} + diff --git a/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h new file mode 100644 index 0000000..b3bda03 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h @@ -0,0 +1,161 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_POINT2POINTCONSTRAINT_H +#define BT_POINT2POINTCONSTRAINT_H + +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" + +class btRigidBody; + + +#ifdef BT_USE_DOUBLE_PRECISION +#define btPoint2PointConstraintData btPoint2PointConstraintDoubleData +#define btPoint2PointConstraintDataName "btPoint2PointConstraintDoubleData" +#else +#define btPoint2PointConstraintData btPoint2PointConstraintFloatData +#define btPoint2PointConstraintDataName "btPoint2PointConstraintFloatData" +#endif //BT_USE_DOUBLE_PRECISION + +struct btConstraintSetting +{ + btConstraintSetting() : + m_tau(btScalar(0.3)), + m_damping(btScalar(1.)), + m_impulseClamp(btScalar(0.)) + { + } + btScalar m_tau; + btScalar m_damping; + btScalar m_impulseClamp; +}; + +enum btPoint2PointFlags +{ + BT_P2P_FLAGS_ERP = 1, + BT_P2P_FLAGS_CFM = 2 +}; + +/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space +ATTRIBUTE_ALIGNED16(class) btPoint2PointConstraint : public btTypedConstraint +{ +#ifdef IN_PARALLELL_SOLVER +public: +#endif + btJacobianEntry m_jac[3]; //3 orthogonal linear constraints + + btVector3 m_pivotInA; + btVector3 m_pivotInB; + + int m_flags; + btScalar m_erp; + btScalar m_cfm; + +public: + + ///for backwards compatibility during the transition to 'getInfo/getInfo2' + bool m_useSolveConstraintObsolete; + + btConstraintSetting m_setting; + + btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB); + + btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA); + + + virtual void buildJacobian(); + + virtual void getInfo1 (btConstraintInfo1* info); + + void getInfo1NonVirtual (btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + void getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans); + + void updateRHS(btScalar timeStep); + + void setPivotA(const btVector3& pivotA) + { + m_pivotInA = pivotA; + } + + void setPivotB(const btVector3& pivotB) + { + m_pivotInB = pivotB; + } + + const btVector3& getPivotInA() const + { + return m_pivotInA; + } + + const btVector3& getPivotInB() const + { + return m_pivotInB; + } + + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///If no axis is provided, it uses the default axis for this constraint. + virtual void setParam(int num, btScalar value, int axis = -1); + ///return the local value of parameter + virtual btScalar getParam(int num, int axis = -1) const; + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btPoint2PointConstraintFloatData +{ + btTypedConstraintData m_typeConstraintData; + btVector3FloatData m_pivotInA; + btVector3FloatData m_pivotInB; +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btPoint2PointConstraintDoubleData +{ + btTypedConstraintData m_typeConstraintData; + btVector3DoubleData m_pivotInA; + btVector3DoubleData m_pivotInB; +}; + + +SIMD_FORCE_INLINE int btPoint2PointConstraint::calculateSerializeBufferSize() const +{ + return sizeof(btPoint2PointConstraintData); + +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btPoint2PointConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btPoint2PointConstraintData* p2pData = (btPoint2PointConstraintData*)dataBuffer; + + btTypedConstraint::serialize(&p2pData->m_typeConstraintData,serializer); + m_pivotInA.serialize(p2pData->m_pivotInA); + m_pivotInB.serialize(p2pData->m_pivotInB); + + return btPoint2PointConstraintDataName; +} + +#endif //BT_POINT2POINTCONSTRAINT_H diff --git a/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp new file mode 100644 index 0000000..ab07422 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp @@ -0,0 +1,1269 @@ +/* +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. +*/ + +//#define COMPUTE_IMPULSE_DENOM 1 +//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms. + +#include "btSequentialImpulseConstraintSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "btContactConstraint.h" +#include "btSolve2LinearConstraint.h" +#include "btContactSolverInfo.h" +#include "LinearMath/btIDebugDraw.h" +#include "btJacobianEntry.h" +#include "LinearMath/btMinMax.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include +#include "LinearMath/btStackAlloc.h" +#include "LinearMath/btQuickprof.h" +#include "btSolverBody.h" +#include "btSolverConstraint.h" +#include "LinearMath/btAlignedObjectArray.h" +#include //for memset + +int gNumSplitImpulseRecoveries = 0; + +btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver() +:m_btSeed2(0) +{ + +} + +btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver() +{ +} + +#ifdef USE_SIMD +#include +#define btVecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e)) +static inline __m128 btSimdDot3( __m128 vec0, __m128 vec1 ) +{ + __m128 result = _mm_mul_ps( vec0, vec1); + return _mm_add_ps( btVecSplat( result, 0 ), _mm_add_ps( btVecSplat( result, 1 ), btVecSplat( result, 2 ) ) ); +} +#endif//USE_SIMD + +// Project Gauss Seidel or the equivalent Sequential Impulse +void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c) +{ +#ifdef USE_SIMD + __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse); + __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit); + __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit); + __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm))); + __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal.mVec128,body1.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetDeltaAngularVelocity().mVec128)); + __m128 deltaVel2Dotn = _mm_sub_ps(btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetDeltaAngularVelocity().mVec128),btSimdDot3((c.m_contactNormal).mVec128,body2.internalGetDeltaLinearVelocity().mVec128)); + deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv))); + deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv))); + btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse); + btSimdScalar resultLowerLess,resultUpperLess; + resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1); + resultUpperLess = _mm_cmplt_ps(sum,upperLimit1); + __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp); + deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) ); + c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) ); + __m128 upperMinApplied = _mm_sub_ps(upperLimit1,cpAppliedImp); + deltaImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied) ); + c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1) ); + __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128); + __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128); + __m128 impulseMagnitude = deltaImpulse; + body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude)); + body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude)); + body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude)); + body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude)); +#else + resolveSingleConstraintRowGeneric(body1,body2,c); +#endif +} + +// Project Gauss Seidel or the equivalent Sequential Impulse + void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c) +{ + btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm; + const btScalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity()); + const btScalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity()); + +// const btScalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn; + deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv; + deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv; + + const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse; + if (sum < c.m_lowerLimit) + { + deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_lowerLimit; + } + else if (sum > c.m_upperLimit) + { + deltaImpulse = c.m_upperLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_upperLimit; + } + else + { + c.m_appliedImpulse = sum; + } + body1.internalApplyImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse); + body2.internalApplyImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse); +} + + void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c) +{ +#ifdef USE_SIMD + __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse); + __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit); + __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit); + __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm))); + __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal.mVec128,body1.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetDeltaAngularVelocity().mVec128)); + __m128 deltaVel2Dotn = _mm_sub_ps(btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetDeltaAngularVelocity().mVec128),btSimdDot3((c.m_contactNormal).mVec128,body2.internalGetDeltaLinearVelocity().mVec128)); + deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv))); + deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv))); + btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse); + btSimdScalar resultLowerLess,resultUpperLess; + resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1); + resultUpperLess = _mm_cmplt_ps(sum,upperLimit1); + __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp); + deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) ); + c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) ); + __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128); + __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128); + __m128 impulseMagnitude = deltaImpulse; + body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude)); + body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude)); + body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude)); + body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude)); +#else + resolveSingleConstraintRowLowerLimit(body1,body2,c); +#endif +} + +// Project Gauss Seidel or the equivalent Sequential Impulse + void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c) +{ + btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm; + const btScalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity()); + const btScalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity()); + + deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv; + deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv; + const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse; + if (sum < c.m_lowerLimit) + { + deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_lowerLimit; + } + else + { + c.m_appliedImpulse = sum; + } + body1.internalApplyImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse); + body2.internalApplyImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse); +} + + +void btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFriendly( + btRigidBody& body1, + btRigidBody& body2, + const btSolverConstraint& c) +{ + if (c.m_rhsPenetration) + { + gNumSplitImpulseRecoveries++; + btScalar deltaImpulse = c.m_rhsPenetration-btScalar(c.m_appliedPushImpulse)*c.m_cfm; + const btScalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetTurnVelocity()); + const btScalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetTurnVelocity()); + + deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv; + deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv; + const btScalar sum = btScalar(c.m_appliedPushImpulse) + deltaImpulse; + if (sum < c.m_lowerLimit) + { + deltaImpulse = c.m_lowerLimit-c.m_appliedPushImpulse; + c.m_appliedPushImpulse = c.m_lowerLimit; + } + else + { + c.m_appliedPushImpulse = sum; + } + body1.internalApplyPushImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse); + body2.internalApplyPushImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse); + } +} + + void btSequentialImpulseConstraintSolver::resolveSplitPenetrationSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c) +{ +#ifdef USE_SIMD + if (!c.m_rhsPenetration) + return; + + gNumSplitImpulseRecoveries++; + + __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedPushImpulse); + __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit); + __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit); + __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse),_mm_set1_ps(c.m_cfm))); + __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal.mVec128,body1.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetTurnVelocity().mVec128)); + __m128 deltaVel2Dotn = _mm_sub_ps(btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetTurnVelocity().mVec128),btSimdDot3((c.m_contactNormal).mVec128,body2.internalGetPushVelocity().mVec128)); + deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv))); + deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv))); + btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse); + btSimdScalar resultLowerLess,resultUpperLess; + resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1); + resultUpperLess = _mm_cmplt_ps(sum,upperLimit1); + __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp); + deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) ); + c.m_appliedPushImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) ); + __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128); + __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128); + __m128 impulseMagnitude = deltaImpulse; + body1.internalGetPushVelocity().mVec128 = _mm_add_ps(body1.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude)); + body1.internalGetTurnVelocity().mVec128 = _mm_add_ps(body1.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude)); + body2.internalGetPushVelocity().mVec128 = _mm_sub_ps(body2.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude)); + body2.internalGetTurnVelocity().mVec128 = _mm_add_ps(body2.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude)); +#else + resolveSplitPenetrationImpulseCacheFriendly(body1,body2,c); +#endif +} + + + +unsigned long btSequentialImpulseConstraintSolver::btRand2() +{ + m_btSeed2 = (1664525L*m_btSeed2 + 1013904223L) & 0xffffffff; + return m_btSeed2; +} + + + +//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1) +int btSequentialImpulseConstraintSolver::btRandInt2 (int n) +{ + // seems good; xor-fold and modulus + const unsigned long un = static_cast(n); + unsigned long r = btRand2(); + + // note: probably more aggressive than it needs to be -- might be + // able to get away without one or two of the innermost branches. + if (un <= 0x00010000UL) { + r ^= (r >> 16); + if (un <= 0x00000100UL) { + r ^= (r >> 8); + if (un <= 0x00000010UL) { + r ^= (r >> 4); + if (un <= 0x00000004UL) { + r ^= (r >> 2); + if (un <= 0x00000002UL) { + r ^= (r >> 1); + } + } + } + } + } + + return (int) (r % un); +} + + +#if 0 +void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject) +{ + btRigidBody* rb = collisionObject? btRigidBody::upcast(collisionObject) : 0; + + solverBody->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f); + solverBody->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f); + solverBody->internalGetPushVelocity().setValue(0.f,0.f,0.f); + solverBody->internalGetTurnVelocity().setValue(0.f,0.f,0.f); + + if (rb) + { + solverBody->internalGetInvMass() = btVector3(rb->getInvMass(),rb->getInvMass(),rb->getInvMass())*rb->getLinearFactor(); + solverBody->m_originalBody = rb; + solverBody->m_angularFactor = rb->getAngularFactor(); + } else + { + solverBody->internalGetInvMass().setValue(0,0,0); + solverBody->m_originalBody = 0; + solverBody->m_angularFactor.setValue(1,1,1); + } +} +#endif + + + + + +btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution) +{ + btScalar rest = restitution * -rel_vel; + return rest; +} + + + +void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection); +void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection) +{ + if (colObj && colObj->hasAnisotropicFriction()) + { + // transform to local coordinates + btVector3 loc_lateral = frictionDirection * colObj->getWorldTransform().getBasis(); + const btVector3& friction_scaling = colObj->getAnisotropicFriction(); + //apply anisotropic friction + loc_lateral *= friction_scaling; + // ... and transform it back to global coordinates + frictionDirection = colObj->getWorldTransform().getBasis() * loc_lateral; + } +} + + +void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis,btRigidBody* solverBodyA,btRigidBody* solverBodyB,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip) +{ + + + btRigidBody* body0=btRigidBody::upcast(colObj0); + btRigidBody* body1=btRigidBody::upcast(colObj1); + + solverConstraint.m_contactNormal = normalAxis; + + solverConstraint.m_solverBodyA = body0 ? body0 : &getFixedBody(); + solverConstraint.m_solverBodyB = body1 ? body1 : &getFixedBody(); + + solverConstraint.m_friction = cp.m_combinedFriction; + solverConstraint.m_originalContactPoint = 0; + + solverConstraint.m_appliedImpulse = 0.f; + solverConstraint.m_appliedPushImpulse = 0.f; + + { + btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal); + solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor() : btVector3(0,0,0); + } + { + btVector3 ftorqueAxis1 = rel_pos2.cross(-solverConstraint.m_contactNormal); + solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentB = body1 ? body1->getInvInertiaTensorWorld()*ftorqueAxis1*body1->getAngularFactor() : btVector3(0,0,0); + } + +#ifdef COMPUTE_IMPULSE_DENOM + btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal); + btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal); +#else + btVector3 vec; + btScalar denom0 = 0.f; + btScalar denom1 = 0.f; + if (body0) + { + vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); + denom0 = body0->getInvMass() + normalAxis.dot(vec); + } + if (body1) + { + vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2); + denom1 = body1->getInvMass() + normalAxis.dot(vec); + } + + +#endif //COMPUTE_IMPULSE_DENOM + btScalar denom = relaxation/(denom0+denom1); + solverConstraint.m_jacDiagABInv = denom; + +#ifdef _USE_JACOBIAN + solverConstraint.m_jac = btJacobianEntry ( + rel_pos1,rel_pos2,solverConstraint.m_contactNormal, + body0->getInvInertiaDiagLocal(), + body0->getInvMass(), + body1->getInvInertiaDiagLocal(), + body1->getInvMass()); +#endif //_USE_JACOBIAN + + + { + btScalar rel_vel; + btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(body0?body0->getLinearVelocity():btVector3(0,0,0)) + + solverConstraint.m_relpos1CrossNormal.dot(body0?body0->getAngularVelocity():btVector3(0,0,0)); + btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(body1?body1->getLinearVelocity():btVector3(0,0,0)) + + solverConstraint.m_relpos2CrossNormal.dot(body1?body1->getAngularVelocity():btVector3(0,0,0)); + + rel_vel = vel1Dotn+vel2Dotn; + +// btScalar positionalError = 0.f; + + btSimdScalar velocityError = desiredVelocity - rel_vel; + btSimdScalar velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv); + solverConstraint.m_rhs = velocityImpulse; + solverConstraint.m_cfm = cfmSlip; + solverConstraint.m_lowerLimit = 0; + solverConstraint.m_upperLimit = 1e10f; + } +} + + + +btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,btRigidBody* solverBodyA,btRigidBody* solverBodyB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip) +{ + btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing(); + solverConstraint.m_frictionIndex = frictionIndex; + setupFrictionConstraint(solverConstraint, normalAxis, solverBodyA, solverBodyB, cp, rel_pos1, rel_pos2, + colObj0, colObj1, relaxation, desiredVelocity, cfmSlip); + return solverConstraint; +} + +int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body) +{ +#if 0 + int solverBodyIdA = -1; + + if (body.getCompanionId() >= 0) + { + //body has already been converted + solverBodyIdA = body.getCompanionId(); + } else + { + btRigidBody* rb = btRigidBody::upcast(&body); + if (rb && rb->getInvMass()) + { + solverBodyIdA = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,&body); + body.setCompanionId(solverBodyIdA); + } else + { + return 0;//assume first one is a fixed solver body + } + } + return solverBodyIdA; +#endif + return 0; +} +#include + + +void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint, + btCollisionObject* colObj0, btCollisionObject* colObj1, + btManifoldPoint& cp, const btContactSolverInfo& infoGlobal, + btVector3& vel, btScalar& rel_vel, btScalar& relaxation, + btVector3& rel_pos1, btVector3& rel_pos2) +{ + btRigidBody* rb0 = btRigidBody::upcast(colObj0); + btRigidBody* rb1 = btRigidBody::upcast(colObj1); + + const btVector3& pos1 = cp.getPositionWorldOnA(); + const btVector3& pos2 = cp.getPositionWorldOnB(); + +// btVector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin(); +// btVector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin(); + rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin(); + rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin(); + + relaxation = 1.f; + + btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0); + btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0); + + { +#ifdef COMPUTE_IMPULSE_DENOM + btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB); + btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB); +#else + btVector3 vec; + btScalar denom0 = 0.f; + btScalar denom1 = 0.f; + if (rb0) + { + vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); + denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec); + } + if (rb1) + { + vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2); + denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec); + } +#endif //COMPUTE_IMPULSE_DENOM + + btScalar denom = relaxation/(denom0+denom1); + solverConstraint.m_jacDiagABInv = denom; + } + + solverConstraint.m_contactNormal = cp.m_normalWorldOnB; + solverConstraint.m_relpos1CrossNormal = rel_pos1.cross(cp.m_normalWorldOnB); + solverConstraint.m_relpos2CrossNormal = rel_pos2.cross(-cp.m_normalWorldOnB); + + + + + btVector3 vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0); + btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); + vel = vel1 - vel2; + rel_vel = cp.m_normalWorldOnB.dot(vel); + + btScalar penetration = cp.getDistance()+infoGlobal.m_linearSlop; + + + solverConstraint.m_friction = cp.m_combinedFriction; + + btScalar restitution = 0.f; + + if (cp.m_lifeTime>infoGlobal.m_restingContactRestitutionThreshold) + { + restitution = 0.f; + } else + { + restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution); + if (restitution <= btScalar(0.)) + { + restitution = 0.f; + }; + } + + + ///warm starting (or zero if disabled) + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) + { + solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor; + if (rb0) + rb0->internalApplyImpulse(solverConstraint.m_contactNormal*rb0->getInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse); + if (rb1) + rb1->internalApplyImpulse(solverConstraint.m_contactNormal*rb1->getInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-(btScalar)solverConstraint.m_appliedImpulse); + } else + { + solverConstraint.m_appliedImpulse = 0.f; + } + + solverConstraint.m_appliedPushImpulse = 0.f; + + { + btScalar rel_vel; + btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(rb0?rb0->getLinearVelocity():btVector3(0,0,0)) + + solverConstraint.m_relpos1CrossNormal.dot(rb0?rb0->getAngularVelocity():btVector3(0,0,0)); + btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rb1?rb1->getLinearVelocity():btVector3(0,0,0)) + + solverConstraint.m_relpos2CrossNormal.dot(rb1?rb1->getAngularVelocity():btVector3(0,0,0)); + + rel_vel = vel1Dotn+vel2Dotn; + + btScalar positionalError = 0.f; + btScalar velocityError = restitution - rel_vel;// * damping; + + if (penetration>0) + { + positionalError = 0; + velocityError -= penetration / infoGlobal.m_timeStep; + } else + { + positionalError = -penetration * infoGlobal.m_erp/infoGlobal.m_timeStep; + } + + btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; + if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) + { + //combine position and velocity into rhs + solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; + solverConstraint.m_rhsPenetration = 0.f; + } else + { + //split position and velocity into rhs and m_rhsPenetration + solverConstraint.m_rhs = velocityImpulse; + solverConstraint.m_rhsPenetration = penetrationImpulse; + } + solverConstraint.m_cfm = 0.f; + solverConstraint.m_lowerLimit = 0; + solverConstraint.m_upperLimit = 1e10f; + } + + + + +} + + + +void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse( btSolverConstraint& solverConstraint, + btRigidBody* rb0, btRigidBody* rb1, + btManifoldPoint& cp, const btContactSolverInfo& infoGlobal) +{ + if (infoGlobal.m_solverMode & SOLVER_USE_FRICTION_WARMSTARTING) + { + { + btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex]; + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) + { + frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor; + if (rb0) + rb0->internalApplyImpulse(frictionConstraint1.m_contactNormal*rb0->getInvMass()*rb0->getLinearFactor(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse); + if (rb1) + rb1->internalApplyImpulse(frictionConstraint1.m_contactNormal*rb1->getInvMass()*rb1->getLinearFactor(),-frictionConstraint1.m_angularComponentB,-(btScalar)frictionConstraint1.m_appliedImpulse); + } else + { + frictionConstraint1.m_appliedImpulse = 0.f; + } + } + + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + { + btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1]; + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) + { + frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor; + if (rb0) + rb0->internalApplyImpulse(frictionConstraint2.m_contactNormal*rb0->getInvMass(),frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse); + if (rb1) + rb1->internalApplyImpulse(frictionConstraint2.m_contactNormal*rb1->getInvMass(),-frictionConstraint2.m_angularComponentB,-(btScalar)frictionConstraint2.m_appliedImpulse); + } else + { + frictionConstraint2.m_appliedImpulse = 0.f; + } + } + } else + { + btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex]; + frictionConstraint1.m_appliedImpulse = 0.f; + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + { + btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1]; + frictionConstraint2.m_appliedImpulse = 0.f; + } + } +} + + + + +void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal) +{ + btCollisionObject* colObj0=0,*colObj1=0; + + colObj0 = (btCollisionObject*)manifold->getBody0(); + colObj1 = (btCollisionObject*)manifold->getBody1(); + + + btRigidBody* solverBodyA = btRigidBody::upcast(colObj0); + btRigidBody* solverBodyB = btRigidBody::upcast(colObj1); + + ///avoid collision response between two static objects + if ((!solverBodyA || !solverBodyA->getInvMass()) && (!solverBodyB || !solverBodyB->getInvMass())) + return; + + for (int j=0;jgetNumContacts();j++) + { + + btManifoldPoint& cp = manifold->getContactPoint(j); + + if (cp.getDistance() <= manifold->getContactProcessingThreshold()) + { + btVector3 rel_pos1; + btVector3 rel_pos2; + btScalar relaxation; + btScalar rel_vel; + btVector3 vel; + + int frictionIndex = m_tmpSolverContactConstraintPool.size(); + btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing(); + btRigidBody* rb0 = btRigidBody::upcast(colObj0); + btRigidBody* rb1 = btRigidBody::upcast(colObj1); + solverConstraint.m_solverBodyA = rb0? rb0 : &getFixedBody(); + solverConstraint.m_solverBodyB = rb1? rb1 : &getFixedBody(); + solverConstraint.m_originalContactPoint = &cp; + + setupContactConstraint(solverConstraint, colObj0, colObj1, cp, infoGlobal, vel, rel_vel, relaxation, rel_pos1, rel_pos2); + +// const btVector3& pos1 = cp.getPositionWorldOnA(); +// const btVector3& pos2 = cp.getPositionWorldOnB(); + + /////setup the friction constraints + + solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size(); + + if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !cp.m_lateralFrictionInitialized) + { + cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; + btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2(); + if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON) + { + cp.m_lateralFrictionDir1 /= btSqrt(lat_rel_vel); + if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + { + cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB); + cp.m_lateralFrictionDir2.normalize();//?? + applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2); + applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2); + addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + } + + applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1); + applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1); + addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + cp.m_lateralFrictionInitialized = true; + } else + { + //re-calculate friction direction every frame, todo: check if this is really needed + btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2); + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + { + applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2); + applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2); + addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + } + + applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1); + applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1); + addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + + cp.m_lateralFrictionInitialized = true; + } + + } else + { + addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation,cp.m_contactMotion1, cp.m_contactCFM1); + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, cp.m_contactMotion2, cp.m_contactCFM2); + } + + setFrictionConstraintImpulse( solverConstraint, rb0, rb1, cp, infoGlobal); + + } + } +} + +btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) +{ + BT_PROFILE("solveGroupCacheFriendlySetup"); + (void)stackAlloc; + (void)debugDrawer; + + m_maxOverrideNumSolverIterations = 0; + + if (!(numConstraints + numManifolds)) + { + // printf("empty\n"); + return 0.f; + } + + if (infoGlobal.m_splitImpulse) + { + for (int i = 0; i < numBodies; i++) + { + btRigidBody* body = btRigidBody::upcast(bodies[i]); + if (body) + { + body->internalGetDeltaLinearVelocity().setZero(); + body->internalGetDeltaAngularVelocity().setZero(); + body->internalGetPushVelocity().setZero(); + body->internalGetTurnVelocity().setZero(); + } + } + } + else + { + for (int i = 0; i < numBodies; i++) + { + btRigidBody* body = btRigidBody::upcast(bodies[i]); + if (body) + { + body->internalGetDeltaLinearVelocity().setZero(); + body->internalGetDeltaAngularVelocity().setZero(); + } + } + } + + if (1) + { + int j; + for (j=0;jbuildJacobian(); + constraint->internalSetAppliedImpulse(0.0f); + } + } + //btRigidBody* rb0=0,*rb1=0; + + //if (1) + { + { + + int totalNumRows = 0; + int i; + + m_tmpConstraintSizesPool.resize(numConstraints); + //calculate the total number of contraint rows + for (i=0;iisEnabled()) + { + constraints[i]->getInfo1(&info1); + } else + { + info1.m_numConstraintRows = 0; + info1.nub = 0; + } + totalNumRows += info1.m_numConstraintRows; + } + m_tmpSolverNonContactConstraintPool.resize(totalNumRows); + + + ///setup the btSolverConstraints + int currentRow = 0; + + for (i=0;igetRigidBodyA(); + btRigidBody& rbB = constraint->getRigidBodyB(); + + + int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations; + if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations) + m_maxOverrideNumSolverIterations = overrideNumSolverIterations; + + + int j; + for ( j=0;jm_contactNormal; + info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal; + info2.m_J2linearAxis = 0; + info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal; + info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this + ///the size of btSolverConstraint needs be a multiple of btScalar + btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint)); + info2.m_constraintError = ¤tConstraintRow->m_rhs; + currentConstraintRow->m_cfm = infoGlobal.m_globalCfm; + info2.m_damping = infoGlobal.m_damping; + info2.cfm = ¤tConstraintRow->m_cfm; + info2.m_lowerLimit = ¤tConstraintRow->m_lowerLimit; + info2.m_upperLimit = ¤tConstraintRow->m_upperLimit; + info2.m_numIterations = infoGlobal.m_numIterations; + constraints[i]->getInfo2(&info2); + + ///finalize the constraint setup + for ( j=0;j=constraints[i]->getBreakingImpulseThreshold()) + { + solverConstraint.m_upperLimit = constraints[i]->getBreakingImpulseThreshold(); + } + + if (solverConstraint.m_lowerLimit<=-constraints[i]->getBreakingImpulseThreshold()) + { + solverConstraint.m_lowerLimit = -constraints[i]->getBreakingImpulseThreshold(); + } + + solverConstraint.m_originalContactPoint = constraint; + + { + const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal; + solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor(); + } + { + const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal; + solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor(); + } + + { + btVector3 iMJlA = solverConstraint.m_contactNormal*rbA.getInvMass(); + btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal; + btVector3 iMJlB = solverConstraint.m_contactNormal*rbB.getInvMass();//sign of normal? + btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal; + + btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal); + sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal); + sum += iMJlB.dot(solverConstraint.m_contactNormal); + sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal); + + solverConstraint.m_jacDiagABInv = btScalar(1.)/sum; + } + + + ///fix rhs + ///todo: add force/torque accelerators + { + btScalar rel_vel; + btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.getLinearVelocity()) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity()); + btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.getLinearVelocity()) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity()); + + rel_vel = vel1Dotn+vel2Dotn; + + btScalar restitution = 0.f; + btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2 + btScalar velocityError = restitution - rel_vel * info2.m_damping; + btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; + solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; + solverConstraint.m_appliedImpulse = 0.f; + + } + } + } + currentRow+=m_tmpConstraintSizesPool[i].m_numConstraintRows; + } + } + + { + int i; + btPersistentManifold* manifold = 0; +// btCollisionObject* colObj0=0,*colObj1=0; + + + for (i=0;isolveConstraintObsolete(constraints[j]->getRigidBodyA(),constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep); + } + + ///solve all contact constraints using SIMD, if available + int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); + for (j=0;jbtScalar(0)) + { + solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; + + resolveSingleConstraintRowGenericSIMD(*solveManifold.m_solverBodyA, *solveManifold.m_solverBodyB,solveManifold); + } + } + } + } else + { + + ///solve all joint constraints + for (j=0;jsolveConstraintObsolete(constraints[j]->getRigidBodyA(),constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep); + } + ///solve all contact constraints + int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); + for (j=0;jbtScalar(0)) + { + solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; + + resolveSingleConstraintRowGeneric(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold); + } + } + } + } + return 0.f; +} + + +void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) +{ + int iteration; + if (infoGlobal.m_splitImpulse) + { + if (infoGlobal.m_solverMode & SOLVER_SIMD) + { + for ( iteration = 0;iteration infoGlobal.m_numIterations? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations; + + for ( int iteration = 0 ; iteration< maxIterations ; iteration++) + //for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--) + { + solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer,stackAlloc); + } + + } + return 0.f; +} + +btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies ,int numBodies,btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/,btTypedConstraint** /*constraints*/,int /* numConstraints*/,const btContactSolverInfo& infoGlobal,btIDebugDraw* /*debugDrawer*/,btStackAlloc* /*stackAlloc*/) +{ + int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); + int i,j; + + for (j=0;jm_appliedImpulse = solveManifold.m_appliedImpulse; + if (infoGlobal.m_solverMode & SOLVER_USE_FRICTION_WARMSTARTING) + { + pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; + pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse; + } + + //do a callback here? + } + + numPoolConstraints = m_tmpSolverNonContactConstraintPool.size(); + for (j=0;jinternalSetAppliedImpulse(solverConstr.m_appliedImpulse); + if (btFabs(solverConstr.m_appliedImpulse)>=constr->getBreakingImpulseThreshold()) + { + constr->setEnabled(false); + } + } + + + if (infoGlobal.m_splitImpulse) + { + for ( i=0;iinternalWritebackVelocity(infoGlobal.m_timeStep); + } + } else + { + for ( i=0;iinternalWritebackVelocity(); + } + } + + + m_tmpSolverContactConstraintPool.resize(0); + m_tmpSolverNonContactConstraintPool.resize(0); + m_tmpSolverContactFrictionConstraintPool.resize(0); + + return 0.f; +} + + + +/// btSequentialImpulseConstraintSolver Sequentially applies impulses +btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc,btDispatcher* /*dispatcher*/) +{ + + BT_PROFILE("solveGroup"); + //you need to provide at least some bodies + btAssert(bodies); + btAssert(numBodies); + + solveGroupCacheFriendlySetup( bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc); + + solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc); + + solveGroupCacheFriendlyFinish(bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc); + + return 0.f; +} + +void btSequentialImpulseConstraintSolver::reset() +{ + m_btSeed2 = 0; +} + +btRigidBody& btSequentialImpulseConstraintSolver::getFixedBody() +{ + static btRigidBody s_fixed(0, 0,0); + s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); + return s_fixed; +} + diff --git a/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h new file mode 100644 index 0000000..bb377db --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h @@ -0,0 +1,130 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H +#define BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H + +#include "btConstraintSolver.h" +class btIDebugDraw; +#include "btContactConstraint.h" +#include "btSolverBody.h" +#include "btSolverConstraint.h" +#include "btTypedConstraint.h" +#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" + +///The btSequentialImpulseConstraintSolver is a fast SIMD implementation of the Projected Gauss Seidel (iterative LCP) method. +class btSequentialImpulseConstraintSolver : public btConstraintSolver +{ +protected: + + btConstraintArray m_tmpSolverContactConstraintPool; + btConstraintArray m_tmpSolverNonContactConstraintPool; + btConstraintArray m_tmpSolverContactFrictionConstraintPool; + btAlignedObjectArray m_orderTmpConstraintPool; + btAlignedObjectArray m_orderNonContactConstraintPool; + btAlignedObjectArray m_orderFrictionConstraintPool; + btAlignedObjectArray m_tmpConstraintSizesPool; + int m_maxOverrideNumSolverIterations; + + void setupFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,btRigidBody* solverBodyA,btRigidBody* solverBodyIdB, + btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2, + btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, + btScalar desiredVelocity=0., btScalar cfmSlip=0.); + + btSolverConstraint& addFrictionConstraint(const btVector3& normalAxis,btRigidBody* solverBodyA,btRigidBody* solverBodyB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0., btScalar cfmSlip=0.); + + void setupContactConstraint(btSolverConstraint& solverConstraint, btCollisionObject* colObj0, btCollisionObject* colObj1, btManifoldPoint& cp, + const btContactSolverInfo& infoGlobal, btVector3& vel, btScalar& rel_vel, btScalar& relaxation, + btVector3& rel_pos1, btVector3& rel_pos2); + + void setFrictionConstraintImpulse( btSolverConstraint& solverConstraint, btRigidBody* rb0, btRigidBody* rb1, + btManifoldPoint& cp, const btContactSolverInfo& infoGlobal); + + ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction + unsigned long m_btSeed2; + +// void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject); + btScalar restitutionCurve(btScalar rel_vel, btScalar restitution); + + void convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal); + + + void resolveSplitPenetrationSIMD( + btRigidBody& body1, + btRigidBody& body2, + const btSolverConstraint& contactConstraint); + + void resolveSplitPenetrationImpulseCacheFriendly( + btRigidBody& body1, + btRigidBody& body2, + const btSolverConstraint& contactConstraint); + + //internal method + int getOrInitSolverBody(btCollisionObject& body); + + void resolveSingleConstraintRowGeneric(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& contactConstraint); + + void resolveSingleConstraintRowGenericSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& contactConstraint); + + void resolveSingleConstraintRowLowerLimit(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& contactConstraint); + + void resolveSingleConstraintRowLowerLimitSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& contactConstraint); + +protected: + static btRigidBody& getFixedBody(); + + virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); + virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); + btScalar solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); + + virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); + virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); + + +public: + + + btSequentialImpulseConstraintSolver(); + virtual ~btSequentialImpulseConstraintSolver(); + + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher); + + + + ///clear internal cached data and reset random seed + virtual void reset(); + + unsigned long btRand2(); + + int btRandInt2 (int n); + + void setRandSeed(unsigned long seed) + { + m_btSeed2 = seed; + } + unsigned long getRandSeed() const + { + return m_btSeed2; + } + +}; + +#ifndef BT_PREFER_SIMD +typedef btSequentialImpulseConstraintSolver btSequentialImpulseConstraintSolverPrefered; +#endif + + +#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H + diff --git a/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp new file mode 100755 index 0000000..b69f46d --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp @@ -0,0 +1,857 @@ +/* +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. +*/ + +/* +Added by Roman Ponomarev (rponom@gmail.com) +April 04, 2008 +*/ + + + +#include "btSliderConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" +#include + +#define USE_OFFSET_FOR_CONSTANT_FRAME true + +void btSliderConstraint::initParams() +{ + m_lowerLinLimit = btScalar(1.0); + m_upperLinLimit = btScalar(-1.0); + m_lowerAngLimit = btScalar(0.); + m_upperAngLimit = btScalar(0.); + m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingDirLin = btScalar(0.); + m_cfmDirLin = SLIDER_CONSTRAINT_DEF_CFM; + m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingDirAng = btScalar(0.); + m_cfmDirAng = SLIDER_CONSTRAINT_DEF_CFM; + m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING; + m_cfmOrthoLin = SLIDER_CONSTRAINT_DEF_CFM; + m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING; + m_cfmOrthoAng = SLIDER_CONSTRAINT_DEF_CFM; + m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING; + m_cfmLimLin = SLIDER_CONSTRAINT_DEF_CFM; + m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING; + m_cfmLimAng = SLIDER_CONSTRAINT_DEF_CFM; + + m_poweredLinMotor = false; + m_targetLinMotorVelocity = btScalar(0.); + m_maxLinMotorForce = btScalar(0.); + m_accumulatedLinMotorImpulse = btScalar(0.0); + + m_poweredAngMotor = false; + m_targetAngMotorVelocity = btScalar(0.); + m_maxAngMotorForce = btScalar(0.); + m_accumulatedAngMotorImpulse = btScalar(0.0); + + m_flags = 0; + m_flags = 0; + + m_useOffsetForConstraintFrame = USE_OFFSET_FOR_CONSTANT_FRAME; + + calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); +} + + + + + +btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) + : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB), + m_useSolveConstraintObsolete(false), + m_frameInA(frameInA), + m_frameInB(frameInB), + m_useLinearReferenceFrameA(useLinearReferenceFrameA) +{ + initParams(); +} + + + +btSliderConstraint::btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA) + : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, getFixedBody(), rbB), + m_useSolveConstraintObsolete(false), + m_frameInB(frameInB), + m_useLinearReferenceFrameA(useLinearReferenceFrameA) +{ + ///not providing rigidbody A means implicitly using worldspace for body A + m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB; +// m_frameInA.getOrigin() = m_rbA.getCenterOfMassTransform()(m_frameInA.getOrigin()); + + initParams(); +} + + + + + + +void btSliderConstraint::getInfo1(btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } + else + { + info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular + info->nub = 2; + //prepare constraint + calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + testAngLimits(); + testLinLimits(); + if(getSolveLinLimit() || getPoweredLinMotor()) + { + info->m_numConstraintRows++; // limit 3rd linear as well + info->nub--; + } + if(getSolveAngLimit() || getPoweredAngMotor()) + { + info->m_numConstraintRows++; // limit 3rd angular as well + info->nub--; + } + } +} + +void btSliderConstraint::getInfo1NonVirtual(btConstraintInfo1* info) +{ + + info->m_numConstraintRows = 6; // Fixed 2 linear + 2 angular + 1 limit (even if not used) + info->nub = 0; +} + +void btSliderConstraint::getInfo2(btConstraintInfo2* info) +{ + getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(), m_rbA.getLinearVelocity(),m_rbB.getLinearVelocity(), m_rbA.getInvMass(),m_rbB.getInvMass()); +} + + + + + + + +void btSliderConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB) +{ + if(m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete)) + { + m_calculatedTransformA = transA * m_frameInA; + m_calculatedTransformB = transB * m_frameInB; + } + else + { + m_calculatedTransformA = transB * m_frameInB; + m_calculatedTransformB = transA * m_frameInA; + } + m_realPivotAInW = m_calculatedTransformA.getOrigin(); + m_realPivotBInW = m_calculatedTransformB.getOrigin(); + m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X + if(m_useLinearReferenceFrameA || m_useSolveConstraintObsolete) + { + m_delta = m_realPivotBInW - m_realPivotAInW; + } + else + { + m_delta = m_realPivotAInW - m_realPivotBInW; + } + m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis; + btVector3 normalWorld; + int i; + //linear part + for(i = 0; i < 3; i++) + { + normalWorld = m_calculatedTransformA.getBasis().getColumn(i); + m_depth[i] = m_delta.dot(normalWorld); + } +} + + + +void btSliderConstraint::testLinLimits(void) +{ + m_solveLinLim = false; + m_linPos = m_depth[0]; + if(m_lowerLinLimit <= m_upperLinLimit) + { + if(m_depth[0] > m_upperLinLimit) + { + m_depth[0] -= m_upperLinLimit; + m_solveLinLim = true; + } + else if(m_depth[0] < m_lowerLinLimit) + { + m_depth[0] -= m_lowerLinLimit; + m_solveLinLim = true; + } + else + { + m_depth[0] = btScalar(0.); + } + } + else + { + m_depth[0] = btScalar(0.); + } +} + + + +void btSliderConstraint::testAngLimits(void) +{ + m_angDepth = btScalar(0.); + m_solveAngLim = false; + if(m_lowerAngLimit <= m_upperAngLimit) + { + const btVector3 axisA0 = m_calculatedTransformA.getBasis().getColumn(1); + const btVector3 axisA1 = m_calculatedTransformA.getBasis().getColumn(2); + const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1); +// btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0)); + btScalar rot = btAtan2(axisB0.dot(axisA1), axisB0.dot(axisA0)); + rot = btAdjustAngleToLimits(rot, m_lowerAngLimit, m_upperAngLimit); + m_angPos = rot; + if(rot < m_lowerAngLimit) + { + m_angDepth = rot - m_lowerAngLimit; + m_solveAngLim = true; + } + else if(rot > m_upperAngLimit) + { + m_angDepth = rot - m_upperAngLimit; + m_solveAngLim = true; + } + } +} + +btVector3 btSliderConstraint::getAncorInA(void) +{ + btVector3 ancorInA; + ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * btScalar(0.5) * m_sliderAxis; + ancorInA = m_rbA.getCenterOfMassTransform().inverse() * ancorInA; + return ancorInA; +} + + + +btVector3 btSliderConstraint::getAncorInB(void) +{ + btVector3 ancorInB; + ancorInB = m_frameInB.getOrigin(); + return ancorInB; +} + + +void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB, const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass ) +{ + const btTransform& trA = getCalculatedTransformA(); + const btTransform& trB = getCalculatedTransformB(); + + btAssert(!m_useSolveConstraintObsolete); + int i, s = info->rowskip; + + btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f); + + // difference between frames in WCS + btVector3 ofs = trB.getOrigin() - trA.getOrigin(); + // now get weight factors depending on masses + btScalar miA = rbAinvMass; + btScalar miB = rbBinvMass; + bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON); + btScalar miS = miA + miB; + btScalar factA, factB; + if(miS > btScalar(0.f)) + { + factA = miB / miS; + } + else + { + factA = btScalar(0.5f); + } + factB = btScalar(1.0f) - factA; + btVector3 ax1, p, q; + btVector3 ax1A = trA.getBasis().getColumn(0); + btVector3 ax1B = trB.getBasis().getColumn(0); + if(m_useOffsetForConstraintFrame) + { + // get the desired direction of slider axis + // as weighted sum of X-orthos of frameA and frameB in WCS + ax1 = ax1A * factA + ax1B * factB; + ax1.normalize(); + // construct two orthos to slider axis + btPlaneSpace1 (ax1, p, q); + } + else + { // old way - use frameA + ax1 = trA.getBasis().getColumn(0); + // get 2 orthos to slider axis (Y, Z) + p = trA.getBasis().getColumn(1); + q = trA.getBasis().getColumn(2); + } + // make rotations around these orthos equal + // the slider axis should be the only unconstrained + // rotational axis, the angular velocity of the two bodies perpendicular to + // the slider axis should be equal. thus the constraint equations are + // p*w1 - p*w2 = 0 + // q*w1 - q*w2 = 0 + // where p and q are unit vectors normal to the slider axis, and w1 and w2 + // are the angular velocity vectors of the two bodies. + info->m_J1angularAxis[0] = p[0]; + info->m_J1angularAxis[1] = p[1]; + info->m_J1angularAxis[2] = p[2]; + info->m_J1angularAxis[s+0] = q[0]; + info->m_J1angularAxis[s+1] = q[1]; + info->m_J1angularAxis[s+2] = q[2]; + + info->m_J2angularAxis[0] = -p[0]; + info->m_J2angularAxis[1] = -p[1]; + info->m_J2angularAxis[2] = -p[2]; + info->m_J2angularAxis[s+0] = -q[0]; + info->m_J2angularAxis[s+1] = -q[1]; + info->m_J2angularAxis[s+2] = -q[2]; + // compute the right hand side of the constraint equation. set relative + // body velocities along p and q to bring the slider back into alignment. + // if ax1A,ax1B are the unit length slider axes as computed from bodyA and + // bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2). + // if "theta" is the angle between ax1 and ax2, we need an angular velocity + // along u to cover angle erp*theta in one step : + // |angular_velocity| = angle/time = erp*theta / stepsize + // = (erp*fps) * theta + // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| + // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) + // ...as ax1 and ax2 are unit length. if theta is smallish, + // theta ~= sin(theta), so + // angular_velocity = (erp*fps) * (ax1 x ax2) + // ax1 x ax2 is in the plane space of ax1, so we project the angular + // velocity to p and q to find the right hand side. +// btScalar k = info->fps * info->erp * getSoftnessOrthoAng(); + btScalar currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTANG) ? m_softnessOrthoAng : m_softnessOrthoAng * info->erp; + btScalar k = info->fps * currERP; + + btVector3 u = ax1A.cross(ax1B); + info->m_constraintError[0] = k * u.dot(p); + info->m_constraintError[s] = k * u.dot(q); + if(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG) + { + info->cfm[0] = m_cfmOrthoAng; + info->cfm[s] = m_cfmOrthoAng; + } + + int nrow = 1; // last filled row + int srow; + btScalar limit_err; + int limit; + int powered; + + // next two rows. + // we want: velA + wA x relA == velB + wB x relB ... but this would + // result in three equations, so we project along two orthos to the slider axis + + btTransform bodyA_trans = transA; + btTransform bodyB_trans = transB; + nrow++; + int s2 = nrow * s; + nrow++; + int s3 = nrow * s; + btVector3 tmpA(0,0,0), tmpB(0,0,0), relA(0,0,0), relB(0,0,0), c(0,0,0); + if(m_useOffsetForConstraintFrame) + { + // get vector from bodyB to frameB in WCS + relB = trB.getOrigin() - bodyB_trans.getOrigin(); + // get its projection to slider axis + btVector3 projB = ax1 * relB.dot(ax1); + // get vector directed from bodyB to slider axis (and orthogonal to it) + btVector3 orthoB = relB - projB; + // same for bodyA + relA = trA.getOrigin() - bodyA_trans.getOrigin(); + btVector3 projA = ax1 * relA.dot(ax1); + btVector3 orthoA = relA - projA; + // get desired offset between frames A and B along slider axis + btScalar sliderOffs = m_linPos - m_depth[0]; + // desired vector from projection of center of bodyA to projection of center of bodyB to slider axis + btVector3 totalDist = projA + ax1 * sliderOffs - projB; + // get offset vectors relA and relB + relA = orthoA + totalDist * factA; + relB = orthoB - totalDist * factB; + // now choose average ortho to slider axis + p = orthoB * factA + orthoA * factB; + btScalar len2 = p.length2(); + if(len2 > SIMD_EPSILON) + { + p /= btSqrt(len2); + } + else + { + p = trA.getBasis().getColumn(1); + } + // make one more ortho + q = ax1.cross(p); + // fill two rows + tmpA = relA.cross(p); + tmpB = relB.cross(p); + for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i]; + tmpA = relA.cross(q); + tmpB = relB.cross(q); + if(hasStaticBody && getSolveAngLimit()) + { // to make constraint between static and dynamic objects more rigid + // remove wA (or wB) from equation if angular limit is hit + tmpB *= factB; + tmpA *= factA; + } + for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = tmpA[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = -tmpB[i]; + for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i]; + for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i]; + } + else + { // old way - maybe incorrect if bodies are not on the slider axis + // see discussion "Bug in slider constraint" http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4024&start=0 + c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin(); + btVector3 tmp = c.cross(p); + for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = factA*tmp[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = factB*tmp[i]; + tmp = c.cross(q); + for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = factA*tmp[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = factB*tmp[i]; + + for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i]; + for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i]; + } + // compute two elements of right hand side + + // k = info->fps * info->erp * getSoftnessOrthoLin(); + currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN) ? m_softnessOrthoLin : m_softnessOrthoLin * info->erp; + k = info->fps * currERP; + + btScalar rhs = k * p.dot(ofs); + info->m_constraintError[s2] = rhs; + rhs = k * q.dot(ofs); + info->m_constraintError[s3] = rhs; + if(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN) + { + info->cfm[s2] = m_cfmOrthoLin; + info->cfm[s3] = m_cfmOrthoLin; + } + + + // check linear limits + limit_err = btScalar(0.0); + limit = 0; + if(getSolveLinLimit()) + { + limit_err = getLinDepth() * signFact; + limit = (limit_err > btScalar(0.0)) ? 2 : 1; + } + powered = 0; + if(getPoweredLinMotor()) + { + powered = 1; + } + // if the slider has joint limits or motor, add in the extra row + if (limit || powered) + { + nrow++; + srow = nrow * info->rowskip; + info->m_J1linearAxis[srow+0] = ax1[0]; + info->m_J1linearAxis[srow+1] = ax1[1]; + info->m_J1linearAxis[srow+2] = ax1[2]; + // linear torque decoupling step: + // + // we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies + // do not create a torque couple. in other words, the points that the + // constraint force is applied at must lie along the same ax1 axis. + // a torque couple will result in limited slider-jointed free + // bodies from gaining angular momentum. + if(m_useOffsetForConstraintFrame) + { + // this is needed only when bodyA and bodyB are both dynamic. + if(!hasStaticBody) + { + tmpA = relA.cross(ax1); + tmpB = relB.cross(ax1); + info->m_J1angularAxis[srow+0] = tmpA[0]; + info->m_J1angularAxis[srow+1] = tmpA[1]; + info->m_J1angularAxis[srow+2] = tmpA[2]; + info->m_J2angularAxis[srow+0] = -tmpB[0]; + info->m_J2angularAxis[srow+1] = -tmpB[1]; + info->m_J2angularAxis[srow+2] = -tmpB[2]; + } + } + else + { // The old way. May be incorrect if bodies are not on the slider axis + btVector3 ltd; // Linear Torque Decoupling vector (a torque) + ltd = c.cross(ax1); + info->m_J1angularAxis[srow+0] = factA*ltd[0]; + info->m_J1angularAxis[srow+1] = factA*ltd[1]; + info->m_J1angularAxis[srow+2] = factA*ltd[2]; + info->m_J2angularAxis[srow+0] = factB*ltd[0]; + info->m_J2angularAxis[srow+1] = factB*ltd[1]; + info->m_J2angularAxis[srow+2] = factB*ltd[2]; + } + // right-hand part + btScalar lostop = getLowerLinLimit(); + btScalar histop = getUpperLinLimit(); + if(limit && (lostop == histop)) + { // the joint motor is ineffective + powered = 0; + } + info->m_constraintError[srow] = 0.; + info->m_lowerLimit[srow] = 0.; + info->m_upperLimit[srow] = 0.; + currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN) ? m_softnessLimLin : info->erp; + if(powered) + { + if(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN) + { + info->cfm[srow] = m_cfmDirLin; + } + btScalar tag_vel = getTargetLinMotorVelocity(); + btScalar mot_fact = getMotorFactor(m_linPos, m_lowerLinLimit, m_upperLinLimit, tag_vel, info->fps * currERP); + info->m_constraintError[srow] -= signFact * mot_fact * getTargetLinMotorVelocity(); + info->m_lowerLimit[srow] += -getMaxLinMotorForce() * info->fps; + info->m_upperLimit[srow] += getMaxLinMotorForce() * info->fps; + } + if(limit) + { + k = info->fps * currERP; + info->m_constraintError[srow] += k * limit_err; + if(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN) + { + info->cfm[srow] = m_cfmLimLin; + } + if(lostop == histop) + { // limited low and high simultaneously + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else if(limit == 1) + { // low limit + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + else + { // high limit + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + // bounce (we'll use slider parameter abs(1.0 - m_dampingLimLin) for that) + btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin()); + if(bounce > btScalar(0.0)) + { + btScalar vel = linVelA.dot(ax1); + vel -= linVelB.dot(ax1); + vel *= signFact; + // only apply bounce if the velocity is incoming, and if the + // resulting c[] exceeds what we already have. + if(limit == 1) + { // low limit + if(vel < 0) + { + btScalar newc = -bounce * vel; + if (newc > info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + else + { // high limit - all those computations are reversed + if(vel > 0) + { + btScalar newc = -bounce * vel; + if(newc < info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + } + info->m_constraintError[srow] *= getSoftnessLimLin(); + } // if(limit) + } // if linear limit + // check angular limits + limit_err = btScalar(0.0); + limit = 0; + if(getSolveAngLimit()) + { + limit_err = getAngDepth(); + limit = (limit_err > btScalar(0.0)) ? 1 : 2; + } + // if the slider has joint limits, add in the extra row + powered = 0; + if(getPoweredAngMotor()) + { + powered = 1; + } + if(limit || powered) + { + nrow++; + srow = nrow * info->rowskip; + info->m_J1angularAxis[srow+0] = ax1[0]; + info->m_J1angularAxis[srow+1] = ax1[1]; + info->m_J1angularAxis[srow+2] = ax1[2]; + + info->m_J2angularAxis[srow+0] = -ax1[0]; + info->m_J2angularAxis[srow+1] = -ax1[1]; + info->m_J2angularAxis[srow+2] = -ax1[2]; + + btScalar lostop = getLowerAngLimit(); + btScalar histop = getUpperAngLimit(); + if(limit && (lostop == histop)) + { // the joint motor is ineffective + powered = 0; + } + currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMANG) ? m_softnessLimAng : info->erp; + if(powered) + { + if(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG) + { + info->cfm[srow] = m_cfmDirAng; + } + btScalar mot_fact = getMotorFactor(m_angPos, m_lowerAngLimit, m_upperAngLimit, getTargetAngMotorVelocity(), info->fps * currERP); + info->m_constraintError[srow] = mot_fact * getTargetAngMotorVelocity(); + info->m_lowerLimit[srow] = -getMaxAngMotorForce() * info->fps; + info->m_upperLimit[srow] = getMaxAngMotorForce() * info->fps; + } + if(limit) + { + k = info->fps * currERP; + info->m_constraintError[srow] += k * limit_err; + if(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG) + { + info->cfm[srow] = m_cfmLimAng; + } + if(lostop == histop) + { + // limited low and high simultaneously + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else if(limit == 1) + { // low limit + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { // high limit + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that) + btScalar bounce = btFabs(btScalar(1.0) - getDampingLimAng()); + if(bounce > btScalar(0.0)) + { + btScalar vel = m_rbA.getAngularVelocity().dot(ax1); + vel -= m_rbB.getAngularVelocity().dot(ax1); + // only apply bounce if the velocity is incoming, and if the + // resulting c[] exceeds what we already have. + if(limit == 1) + { // low limit + if(vel < 0) + { + btScalar newc = -bounce * vel; + if(newc > info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + else + { // high limit - all those computations are reversed + if(vel > 0) + { + btScalar newc = -bounce * vel; + if(newc < info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + } + info->m_constraintError[srow] *= getSoftnessLimAng(); + } // if(limit) + } // if angular limit or powered +} + + +///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). +///If no axis is provided, it uses the default axis for this constraint. +void btSliderConstraint::setParam(int num, btScalar value, int axis) +{ + switch(num) + { + case BT_CONSTRAINT_STOP_ERP : + if(axis < 1) + { + m_softnessLimLin = value; + m_flags |= BT_SLIDER_FLAGS_ERP_LIMLIN; + } + else if(axis < 3) + { + m_softnessOrthoLin = value; + m_flags |= BT_SLIDER_FLAGS_ERP_ORTLIN; + } + else if(axis == 3) + { + m_softnessLimAng = value; + m_flags |= BT_SLIDER_FLAGS_ERP_LIMANG; + } + else if(axis < 6) + { + m_softnessOrthoAng = value; + m_flags |= BT_SLIDER_FLAGS_ERP_ORTANG; + } + else + { + btAssertConstrParams(0); + } + break; + case BT_CONSTRAINT_CFM : + if(axis < 1) + { + m_cfmDirLin = value; + m_flags |= BT_SLIDER_FLAGS_CFM_DIRLIN; + } + else if(axis == 3) + { + m_cfmDirAng = value; + m_flags |= BT_SLIDER_FLAGS_CFM_DIRANG; + } + else + { + btAssertConstrParams(0); + } + break; + case BT_CONSTRAINT_STOP_CFM : + if(axis < 1) + { + m_cfmLimLin = value; + m_flags |= BT_SLIDER_FLAGS_CFM_LIMLIN; + } + else if(axis < 3) + { + m_cfmOrthoLin = value; + m_flags |= BT_SLIDER_FLAGS_CFM_ORTLIN; + } + else if(axis == 3) + { + m_cfmLimAng = value; + m_flags |= BT_SLIDER_FLAGS_CFM_LIMANG; + } + else if(axis < 6) + { + m_cfmOrthoAng = value; + m_flags |= BT_SLIDER_FLAGS_CFM_ORTANG; + } + else + { + btAssertConstrParams(0); + } + break; + } +} + +///return the local value of parameter +btScalar btSliderConstraint::getParam(int num, int axis) const +{ + btScalar retVal(SIMD_INFINITY); + switch(num) + { + case BT_CONSTRAINT_STOP_ERP : + if(axis < 1) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN); + retVal = m_softnessLimLin; + } + else if(axis < 3) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN); + retVal = m_softnessOrthoLin; + } + else if(axis == 3) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMANG); + retVal = m_softnessLimAng; + } + else if(axis < 6) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTANG); + retVal = m_softnessOrthoAng; + } + else + { + btAssertConstrParams(0); + } + break; + case BT_CONSTRAINT_CFM : + if(axis < 1) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN); + retVal = m_cfmDirLin; + } + else if(axis == 3) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG); + retVal = m_cfmDirAng; + } + else + { + btAssertConstrParams(0); + } + break; + case BT_CONSTRAINT_STOP_CFM : + if(axis < 1) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN); + retVal = m_cfmLimLin; + } + else if(axis < 3) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN); + retVal = m_cfmOrthoLin; + } + else if(axis == 3) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG); + retVal = m_cfmLimAng; + } + else if(axis < 6) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG); + retVal = m_cfmOrthoAng; + } + else + { + btAssertConstrParams(0); + } + break; + } + return retVal; +} + + + diff --git a/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h new file mode 100755 index 0000000..2edc8d2 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h @@ -0,0 +1,333 @@ +/* +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. +*/ + +/* +Added by Roman Ponomarev (rponom@gmail.com) +April 04, 2008 + +TODO: + - add clamping od accumulated impulse to improve stability + - add conversion for ODE constraint solver +*/ + +#ifndef BT_SLIDER_CONSTRAINT_H +#define BT_SLIDER_CONSTRAINT_H + + + +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" + + + +class btRigidBody; + + + +#define SLIDER_CONSTRAINT_DEF_SOFTNESS (btScalar(1.0)) +#define SLIDER_CONSTRAINT_DEF_DAMPING (btScalar(1.0)) +#define SLIDER_CONSTRAINT_DEF_RESTITUTION (btScalar(0.7)) +#define SLIDER_CONSTRAINT_DEF_CFM (btScalar(0.f)) + + +enum btSliderFlags +{ + BT_SLIDER_FLAGS_CFM_DIRLIN = (1 << 0), + BT_SLIDER_FLAGS_ERP_DIRLIN = (1 << 1), + BT_SLIDER_FLAGS_CFM_DIRANG = (1 << 2), + BT_SLIDER_FLAGS_ERP_DIRANG = (1 << 3), + BT_SLIDER_FLAGS_CFM_ORTLIN = (1 << 4), + BT_SLIDER_FLAGS_ERP_ORTLIN = (1 << 5), + BT_SLIDER_FLAGS_CFM_ORTANG = (1 << 6), + BT_SLIDER_FLAGS_ERP_ORTANG = (1 << 7), + BT_SLIDER_FLAGS_CFM_LIMLIN = (1 << 8), + BT_SLIDER_FLAGS_ERP_LIMLIN = (1 << 9), + BT_SLIDER_FLAGS_CFM_LIMANG = (1 << 10), + BT_SLIDER_FLAGS_ERP_LIMANG = (1 << 11) +}; + + +class btSliderConstraint : public btTypedConstraint +{ +protected: + ///for backwards compatibility during the transition to 'getInfo/getInfo2' + bool m_useSolveConstraintObsolete; + bool m_useOffsetForConstraintFrame; + btTransform m_frameInA; + btTransform m_frameInB; + // use frameA fo define limits, if true + bool m_useLinearReferenceFrameA; + // linear limits + btScalar m_lowerLinLimit; + btScalar m_upperLinLimit; + // angular limits + btScalar m_lowerAngLimit; + btScalar m_upperAngLimit; + // softness, restitution and damping for different cases + // DirLin - moving inside linear limits + // LimLin - hitting linear limit + // DirAng - moving inside angular limits + // LimAng - hitting angular limit + // OrthoLin, OrthoAng - against constraint axis + btScalar m_softnessDirLin; + btScalar m_restitutionDirLin; + btScalar m_dampingDirLin; + btScalar m_cfmDirLin; + + btScalar m_softnessDirAng; + btScalar m_restitutionDirAng; + btScalar m_dampingDirAng; + btScalar m_cfmDirAng; + + btScalar m_softnessLimLin; + btScalar m_restitutionLimLin; + btScalar m_dampingLimLin; + btScalar m_cfmLimLin; + + btScalar m_softnessLimAng; + btScalar m_restitutionLimAng; + btScalar m_dampingLimAng; + btScalar m_cfmLimAng; + + btScalar m_softnessOrthoLin; + btScalar m_restitutionOrthoLin; + btScalar m_dampingOrthoLin; + btScalar m_cfmOrthoLin; + + btScalar m_softnessOrthoAng; + btScalar m_restitutionOrthoAng; + btScalar m_dampingOrthoAng; + btScalar m_cfmOrthoAng; + + // for interlal use + bool m_solveLinLim; + bool m_solveAngLim; + + int m_flags; + + btJacobianEntry m_jacLin[3]; + btScalar m_jacLinDiagABInv[3]; + + btJacobianEntry m_jacAng[3]; + + btScalar m_timeStep; + btTransform m_calculatedTransformA; + btTransform m_calculatedTransformB; + + btVector3 m_sliderAxis; + btVector3 m_realPivotAInW; + btVector3 m_realPivotBInW; + btVector3 m_projPivotInW; + btVector3 m_delta; + btVector3 m_depth; + btVector3 m_relPosA; + btVector3 m_relPosB; + + btScalar m_linPos; + btScalar m_angPos; + + btScalar m_angDepth; + btScalar m_kAngle; + + bool m_poweredLinMotor; + btScalar m_targetLinMotorVelocity; + btScalar m_maxLinMotorForce; + btScalar m_accumulatedLinMotorImpulse; + + bool m_poweredAngMotor; + btScalar m_targetAngMotorVelocity; + btScalar m_maxAngMotorForce; + btScalar m_accumulatedAngMotorImpulse; + + //------------------------ + void initParams(); +public: + // constructors + btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); + btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA); + + // overrides + + virtual void getInfo1 (btConstraintInfo1* info); + + void getInfo1NonVirtual(btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + void getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass); + + + // access + const btRigidBody& getRigidBodyA() const { return m_rbA; } + const btRigidBody& getRigidBodyB() const { return m_rbB; } + const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; } + const btTransform & getCalculatedTransformB() const { return m_calculatedTransformB; } + const btTransform & getFrameOffsetA() const { return m_frameInA; } + const btTransform & getFrameOffsetB() const { return m_frameInB; } + btTransform & getFrameOffsetA() { return m_frameInA; } + btTransform & getFrameOffsetB() { return m_frameInB; } + btScalar getLowerLinLimit() { return m_lowerLinLimit; } + void setLowerLinLimit(btScalar lowerLimit) { m_lowerLinLimit = lowerLimit; } + btScalar getUpperLinLimit() { return m_upperLinLimit; } + void setUpperLinLimit(btScalar upperLimit) { m_upperLinLimit = upperLimit; } + btScalar getLowerAngLimit() { return m_lowerAngLimit; } + void setLowerAngLimit(btScalar lowerLimit) { m_lowerAngLimit = btNormalizeAngle(lowerLimit); } + btScalar getUpperAngLimit() { return m_upperAngLimit; } + void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = btNormalizeAngle(upperLimit); } + bool getUseLinearReferenceFrameA() { return m_useLinearReferenceFrameA; } + btScalar getSoftnessDirLin() { return m_softnessDirLin; } + btScalar getRestitutionDirLin() { return m_restitutionDirLin; } + btScalar getDampingDirLin() { return m_dampingDirLin ; } + btScalar getSoftnessDirAng() { return m_softnessDirAng; } + btScalar getRestitutionDirAng() { return m_restitutionDirAng; } + btScalar getDampingDirAng() { return m_dampingDirAng; } + btScalar getSoftnessLimLin() { return m_softnessLimLin; } + btScalar getRestitutionLimLin() { return m_restitutionLimLin; } + btScalar getDampingLimLin() { return m_dampingLimLin; } + btScalar getSoftnessLimAng() { return m_softnessLimAng; } + btScalar getRestitutionLimAng() { return m_restitutionLimAng; } + btScalar getDampingLimAng() { return m_dampingLimAng; } + btScalar getSoftnessOrthoLin() { return m_softnessOrthoLin; } + btScalar getRestitutionOrthoLin() { return m_restitutionOrthoLin; } + btScalar getDampingOrthoLin() { return m_dampingOrthoLin; } + btScalar getSoftnessOrthoAng() { return m_softnessOrthoAng; } + btScalar getRestitutionOrthoAng() { return m_restitutionOrthoAng; } + btScalar getDampingOrthoAng() { return m_dampingOrthoAng; } + void setSoftnessDirLin(btScalar softnessDirLin) { m_softnessDirLin = softnessDirLin; } + void setRestitutionDirLin(btScalar restitutionDirLin) { m_restitutionDirLin = restitutionDirLin; } + void setDampingDirLin(btScalar dampingDirLin) { m_dampingDirLin = dampingDirLin; } + void setSoftnessDirAng(btScalar softnessDirAng) { m_softnessDirAng = softnessDirAng; } + void setRestitutionDirAng(btScalar restitutionDirAng) { m_restitutionDirAng = restitutionDirAng; } + void setDampingDirAng(btScalar dampingDirAng) { m_dampingDirAng = dampingDirAng; } + void setSoftnessLimLin(btScalar softnessLimLin) { m_softnessLimLin = softnessLimLin; } + void setRestitutionLimLin(btScalar restitutionLimLin) { m_restitutionLimLin = restitutionLimLin; } + void setDampingLimLin(btScalar dampingLimLin) { m_dampingLimLin = dampingLimLin; } + void setSoftnessLimAng(btScalar softnessLimAng) { m_softnessLimAng = softnessLimAng; } + void setRestitutionLimAng(btScalar restitutionLimAng) { m_restitutionLimAng = restitutionLimAng; } + void setDampingLimAng(btScalar dampingLimAng) { m_dampingLimAng = dampingLimAng; } + void setSoftnessOrthoLin(btScalar softnessOrthoLin) { m_softnessOrthoLin = softnessOrthoLin; } + void setRestitutionOrthoLin(btScalar restitutionOrthoLin) { m_restitutionOrthoLin = restitutionOrthoLin; } + void setDampingOrthoLin(btScalar dampingOrthoLin) { m_dampingOrthoLin = dampingOrthoLin; } + void setSoftnessOrthoAng(btScalar softnessOrthoAng) { m_softnessOrthoAng = softnessOrthoAng; } + void setRestitutionOrthoAng(btScalar restitutionOrthoAng) { m_restitutionOrthoAng = restitutionOrthoAng; } + void setDampingOrthoAng(btScalar dampingOrthoAng) { m_dampingOrthoAng = dampingOrthoAng; } + void setPoweredLinMotor(bool onOff) { m_poweredLinMotor = onOff; } + bool getPoweredLinMotor() { return m_poweredLinMotor; } + void setTargetLinMotorVelocity(btScalar targetLinMotorVelocity) { m_targetLinMotorVelocity = targetLinMotorVelocity; } + btScalar getTargetLinMotorVelocity() { return m_targetLinMotorVelocity; } + void setMaxLinMotorForce(btScalar maxLinMotorForce) { m_maxLinMotorForce = maxLinMotorForce; } + btScalar getMaxLinMotorForce() { return m_maxLinMotorForce; } + void setPoweredAngMotor(bool onOff) { m_poweredAngMotor = onOff; } + bool getPoweredAngMotor() { return m_poweredAngMotor; } + void setTargetAngMotorVelocity(btScalar targetAngMotorVelocity) { m_targetAngMotorVelocity = targetAngMotorVelocity; } + btScalar getTargetAngMotorVelocity() { return m_targetAngMotorVelocity; } + void setMaxAngMotorForce(btScalar maxAngMotorForce) { m_maxAngMotorForce = maxAngMotorForce; } + btScalar getMaxAngMotorForce() { return m_maxAngMotorForce; } + + btScalar getLinearPos() const { return m_linPos; } + btScalar getAngularPos() const { return m_angPos; } + + + + // access for ODE solver + bool getSolveLinLimit() { return m_solveLinLim; } + btScalar getLinDepth() { return m_depth[0]; } + bool getSolveAngLimit() { return m_solveAngLim; } + btScalar getAngDepth() { return m_angDepth; } + // shared code used by ODE solver + void calculateTransforms(const btTransform& transA,const btTransform& transB); + void testLinLimits(); + void testAngLimits(); + // access for PE Solver + btVector3 getAncorInA(); + btVector3 getAncorInB(); + // access for UseFrameOffset + bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; } + void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; } + + void setFrames(const btTransform& frameA, const btTransform& frameB) + { + m_frameInA=frameA; + m_frameInB=frameB; + calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + buildJacobian(); + } + + + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///If no axis is provided, it uses the default axis for this constraint. + virtual void setParam(int num, btScalar value, int axis = -1); + ///return the local value of parameter + virtual btScalar getParam(int num, int axis = -1) const; + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btSliderConstraintData +{ + btTypedConstraintData m_typeConstraintData; + btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransformFloatData m_rbBFrame; + + float m_linearUpperLimit; + float m_linearLowerLimit; + + float m_angularUpperLimit; + float m_angularLowerLimit; + + int m_useLinearReferenceFrameA; + int m_useOffsetForConstraintFrame; + +}; + + +SIMD_FORCE_INLINE int btSliderConstraint::calculateSerializeBufferSize() const +{ + return sizeof(btSliderConstraintData); +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btSliderConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +{ + + btSliderConstraintData* sliderData = (btSliderConstraintData*) dataBuffer; + btTypedConstraint::serialize(&sliderData->m_typeConstraintData,serializer); + + m_frameInA.serializeFloat(sliderData->m_rbAFrame); + m_frameInB.serializeFloat(sliderData->m_rbBFrame); + + sliderData->m_linearUpperLimit = float(m_upperLinLimit); + sliderData->m_linearLowerLimit = float(m_lowerLinLimit); + + sliderData->m_angularUpperLimit = float(m_upperAngLimit); + sliderData->m_angularLowerLimit = float(m_lowerAngLimit); + + sliderData->m_useLinearReferenceFrameA = m_useLinearReferenceFrameA; + sliderData->m_useOffsetForConstraintFrame = m_useOffsetForConstraintFrame; + + return "btSliderConstraintData"; +} + + + +#endif //BT_SLIDER_CONSTRAINT_H + diff --git a/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp b/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp new file mode 100644 index 0000000..0c7dbd6 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp @@ -0,0 +1,255 @@ +/* +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 "btSolve2LinearConstraint.h" + +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" + + +void btSolve2LinearConstraint::resolveUnilateralPairConstraint( + btRigidBody* body1, + btRigidBody* body2, + + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + + const btVector3& invInertiaADiag, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btVector3& invInertiaBDiag, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1) +{ + (void)linvelA; + (void)linvelB; + (void)angvelB; + (void)angvelA; + + + + imp0 = btScalar(0.); + imp1 = btScalar(0.); + + btScalar len = btFabs(normalA.length()) - btScalar(1.); + if (btFabs(len) >= SIMD_EPSILON) + return; + + btAssert(len < SIMD_EPSILON); + + + //this jacobian entry could be re-used for all iterations + btJacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA, + invInertiaBDiag,invMassB); + btJacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA, + invInertiaBDiag,invMassB); + + //const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); + //const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); + + const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1)); + const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1)); + +// btScalar penetrationImpulse = (depth*contactTau*timeCorrection) * massTerm;//jacDiagABInv + btScalar massTerm = btScalar(1.) / (invMassA + invMassB); + + + // calculate rhs (or error) terms + const btScalar dv0 = depthA * m_tau * massTerm - vel0 * m_damping; + const btScalar dv1 = depthB * m_tau * massTerm - vel1 * m_damping; + + + // dC/dv * dv = -C + + // jacobian * impulse = -error + // + + //impulse = jacobianInverse * -error + + // inverting 2x2 symmetric system (offdiagonal are equal!) + // + + + btScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB); + btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag ); + + //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; + //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; + + imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; + imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; + + //[a b] [d -c] + //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc) + + //[jA nD] * [imp0] = [dv0] + //[nD jB] [imp1] [dv1] + +} + + + +void btSolve2LinearConstraint::resolveBilateralPairConstraint( + btRigidBody* body1, + btRigidBody* body2, + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + + const btVector3& invInertiaADiag, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btVector3& invInertiaBDiag, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1) +{ + + (void)linvelA; + (void)linvelB; + (void)angvelA; + (void)angvelB; + + + + imp0 = btScalar(0.); + imp1 = btScalar(0.); + + btScalar len = btFabs(normalA.length()) - btScalar(1.); + if (btFabs(len) >= SIMD_EPSILON) + return; + + btAssert(len < SIMD_EPSILON); + + + //this jacobian entry could be re-used for all iterations + btJacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA, + invInertiaBDiag,invMassB); + btJacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA, + invInertiaBDiag,invMassB); + + //const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); + //const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); + + const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1)); + const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1)); + + // calculate rhs (or error) terms + const btScalar dv0 = depthA * m_tau - vel0 * m_damping; + const btScalar dv1 = depthB * m_tau - vel1 * m_damping; + + // dC/dv * dv = -C + + // jacobian * impulse = -error + // + + //impulse = jacobianInverse * -error + + // inverting 2x2 symmetric system (offdiagonal are equal!) + // + + + btScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB); + btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag ); + + //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; + //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; + + imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; + imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; + + //[a b] [d -c] + //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc) + + //[jA nD] * [imp0] = [dv0] + //[nD jB] [imp1] [dv1] + + if ( imp0 > btScalar(0.0)) + { + if ( imp1 > btScalar(0.0) ) + { + //both positive + } + else + { + imp1 = btScalar(0.); + + // now imp0>0 imp1<0 + imp0 = dv0 / jacA.getDiagonal(); + if ( imp0 > btScalar(0.0) ) + { + } else + { + imp0 = btScalar(0.); + } + } + } + else + { + imp0 = btScalar(0.); + + imp1 = dv1 / jacB.getDiagonal(); + if ( imp1 <= btScalar(0.0) ) + { + imp1 = btScalar(0.); + // now imp0>0 imp1<0 + imp0 = dv0 / jacA.getDiagonal(); + if ( imp0 > btScalar(0.0) ) + { + } else + { + imp0 = btScalar(0.); + } + } else + { + } + } +} + + +/* +void btSolve2LinearConstraint::resolveAngularConstraint( const btMatrix3x3& invInertiaAWS, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btMatrix3x3& invInertiaBWS, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1) +{ + +} +*/ + diff --git a/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h b/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h new file mode 100644 index 0000000..e8bfabf --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h @@ -0,0 +1,107 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOLVE_2LINEAR_CONSTRAINT_H +#define BT_SOLVE_2LINEAR_CONSTRAINT_H + +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btVector3.h" + + +class btRigidBody; + + + +/// constraint class used for lateral tyre friction. +class btSolve2LinearConstraint +{ + btScalar m_tau; + btScalar m_damping; + +public: + + btSolve2LinearConstraint(btScalar tau,btScalar damping) + { + m_tau = tau; + m_damping = damping; + } + // + // solve unilateral constraint (equality, direct method) + // + void resolveUnilateralPairConstraint( + btRigidBody* body0, + btRigidBody* body1, + + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + + const btVector3& invInertiaADiag, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btVector3& invInertiaBDiag, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1); + + + // + // solving 2x2 lcp problem (inequality, direct solution ) + // + void resolveBilateralPairConstraint( + btRigidBody* body0, + btRigidBody* body1, + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + + const btVector3& invInertiaADiag, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btVector3& invInertiaBDiag, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1); + +/* + void resolveAngularConstraint( const btMatrix3x3& invInertiaAWS, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btMatrix3x3& invInertiaBWS, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1); + +*/ + +}; + +#endif //BT_SOLVE_2LINEAR_CONSTRAINT_H diff --git a/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/src/BulletDynamics/ConstraintSolver/btSolverBody.h new file mode 100644 index 0000000..8de5158 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btSolverBody.h @@ -0,0 +1,191 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOLVER_BODY_H +#define BT_SOLVER_BODY_H + +class btRigidBody; +#include "LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btTransformUtil.h" + +///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision +#ifdef BT_USE_SSE +#define USE_SIMD 1 +#endif // + + +#ifdef USE_SIMD + +struct btSimdScalar +{ + SIMD_FORCE_INLINE btSimdScalar() + { + + } + + SIMD_FORCE_INLINE btSimdScalar(float fl) + :m_vec128 (_mm_set1_ps(fl)) + { + } + + SIMD_FORCE_INLINE btSimdScalar(__m128 v128) + :m_vec128(v128) + { + } + union + { + __m128 m_vec128; + float m_floats[4]; + int m_ints[4]; + btScalar m_unusedPadding; + }; + SIMD_FORCE_INLINE __m128 get128() + { + return m_vec128; + } + + SIMD_FORCE_INLINE const __m128 get128() const + { + return m_vec128; + } + + SIMD_FORCE_INLINE void set128(__m128 v128) + { + m_vec128 = v128; + } + + SIMD_FORCE_INLINE operator __m128() + { + return m_vec128; + } + SIMD_FORCE_INLINE operator const __m128() const + { + return m_vec128; + } + + SIMD_FORCE_INLINE operator float() const + { + return m_floats[0]; + } + +}; + +///@brief Return the elementwise product of two btSimdScalar +SIMD_FORCE_INLINE btSimdScalar +operator*(const btSimdScalar& v1, const btSimdScalar& v2) +{ + return btSimdScalar(_mm_mul_ps(v1.get128(),v2.get128())); +} + +///@brief Return the elementwise product of two btSimdScalar +SIMD_FORCE_INLINE btSimdScalar +operator+(const btSimdScalar& v1, const btSimdScalar& v2) +{ + return btSimdScalar(_mm_add_ps(v1.get128(),v2.get128())); +} + + +#else +#define btSimdScalar btScalar +#endif + +///The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance. +ATTRIBUTE_ALIGNED64 (struct) btSolverBodyObsolete +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + btVector3 m_deltaLinearVelocity; + btVector3 m_deltaAngularVelocity; + btVector3 m_angularFactor; + btVector3 m_invMass; + btRigidBody* m_originalBody; + btVector3 m_pushVelocity; + btVector3 m_turnVelocity; + + + SIMD_FORCE_INLINE void getVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const + { + if (m_originalBody) + velocity = m_originalBody->getLinearVelocity()+m_deltaLinearVelocity + (m_originalBody->getAngularVelocity()+m_deltaAngularVelocity).cross(rel_pos); + else + velocity.setValue(0,0,0); + } + + SIMD_FORCE_INLINE void getAngularVelocity(btVector3& angVel) const + { + if (m_originalBody) + angVel = m_originalBody->getAngularVelocity()+m_deltaAngularVelocity; + else + angVel.setValue(0,0,0); + } + + + //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position + SIMD_FORCE_INLINE void applyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude) + { + //if (m_invMass) + { + m_deltaLinearVelocity += linearComponent*impulseMagnitude; + m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor); + } + } + + SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) + { + if (m_originalBody) + { + m_pushVelocity += linearComponent*impulseMagnitude; + m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor); + } + } + + void writebackVelocity() + { + if (m_originalBody) + { + m_originalBody->setLinearVelocity(m_originalBody->getLinearVelocity()+ m_deltaLinearVelocity); + m_originalBody->setAngularVelocity(m_originalBody->getAngularVelocity()+m_deltaAngularVelocity); + + //m_originalBody->setCompanionId(-1); + } + } + + + void writebackVelocity(btScalar timeStep) + { + (void) timeStep; + if (m_originalBody) + { + m_originalBody->setLinearVelocity(m_originalBody->getLinearVelocity()+ m_deltaLinearVelocity); + m_originalBody->setAngularVelocity(m_originalBody->getAngularVelocity()+m_deltaAngularVelocity); + + //correct the position/orientation based on push/turn recovery + btTransform newTransform; + btTransformUtil::integrateTransform(m_originalBody->getWorldTransform(),m_pushVelocity,m_turnVelocity,timeStep,newTransform); + m_originalBody->setWorldTransform(newTransform); + + //m_originalBody->setCompanionId(-1); + } + } + + + +}; + +#endif //BT_SOLVER_BODY_H + + diff --git a/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h new file mode 100644 index 0000000..179e79d --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h @@ -0,0 +1,98 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOLVER_CONSTRAINT_H +#define BT_SOLVER_CONSTRAINT_H + +class btRigidBody; +#include "LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" +#include "btJacobianEntry.h" + +//#define NO_FRICTION_TANGENTIALS 1 +#include "btSolverBody.h" + + +///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints. +ATTRIBUTE_ALIGNED64 (struct) btSolverConstraint +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btVector3 m_relpos1CrossNormal; + btVector3 m_contactNormal; + + btVector3 m_relpos2CrossNormal; + //btVector3 m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal + + btVector3 m_angularComponentA; + btVector3 m_angularComponentB; + + mutable btSimdScalar m_appliedPushImpulse; + mutable btSimdScalar m_appliedImpulse; + + + btScalar m_friction; + btScalar m_jacDiagABInv; + union + { + int m_numConsecutiveRowsPerKernel; + btScalar m_unusedPadding0; + }; + + int m_overrideNumSolverIterations; + + union + { + int m_frictionIndex; + btScalar m_unusedPadding1; + }; + union + { + btRigidBody* m_solverBodyA; + int m_companionIdA; + }; + union + { + btRigidBody* m_solverBodyB; + int m_companionIdB; + }; + + union + { + void* m_originalContactPoint; + btScalar m_unusedPadding4; + }; + + btScalar m_rhs; + btScalar m_cfm; + btScalar m_lowerLimit; + btScalar m_upperLimit; + + btScalar m_rhsPenetration; + + enum btSolverConstraintType + { + BT_SOLVER_CONTACT_1D = 0, + BT_SOLVER_FRICTION_1D + }; +}; + +typedef btAlignedObjectArray btConstraintArray; + + +#endif //BT_SOLVER_CONSTRAINT_H + + + diff --git a/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp new file mode 100644 index 0000000..06bde5e --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp @@ -0,0 +1,220 @@ +/* +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 "btTypedConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btSerializer.h" + + +#define DEFAULT_DEBUGDRAW_SIZE btScalar(0.3f) + +btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA) +:btTypedObject(type), +m_userConstraintType(-1), +m_userConstraintId(-1), +m_breakingImpulseThreshold(SIMD_INFINITY), +m_isEnabled(true), +m_needsFeedback(false), +m_overrideNumSolverIterations(-1), +m_rbA(rbA), +m_rbB(getFixedBody()), +m_appliedImpulse(btScalar(0.)), +m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE) +{ +} + + +btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB) +:btTypedObject(type), +m_userConstraintType(-1), +m_userConstraintId(-1), +m_breakingImpulseThreshold(SIMD_INFINITY), +m_isEnabled(true), +m_needsFeedback(false), +m_overrideNumSolverIterations(-1), +m_rbA(rbA), +m_rbB(rbB), +m_appliedImpulse(btScalar(0.)), +m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE) +{ +} + + + + +btScalar btTypedConstraint::getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact) +{ + if(lowLim > uppLim) + { + return btScalar(1.0f); + } + else if(lowLim == uppLim) + { + return btScalar(0.0f); + } + btScalar lim_fact = btScalar(1.0f); + btScalar delta_max = vel / timeFact; + if(delta_max < btScalar(0.0f)) + { + if((pos >= lowLim) && (pos < (lowLim - delta_max))) + { + lim_fact = (lowLim - pos) / delta_max; + } + else if(pos < lowLim) + { + lim_fact = btScalar(0.0f); + } + else + { + lim_fact = btScalar(1.0f); + } + } + else if(delta_max > btScalar(0.0f)) + { + if((pos <= uppLim) && (pos > (uppLim - delta_max))) + { + lim_fact = (uppLim - pos) / delta_max; + } + else if(pos > uppLim) + { + lim_fact = btScalar(0.0f); + } + else + { + lim_fact = btScalar(1.0f); + } + } + else + { + lim_fact = btScalar(0.0f); + } + return lim_fact; +} + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btTypedConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btTypedConstraintData* tcd = (btTypedConstraintData*) dataBuffer; + + tcd->m_rbA = (btRigidBodyData*)serializer->getUniquePointer(&m_rbA); + tcd->m_rbB = (btRigidBodyData*)serializer->getUniquePointer(&m_rbB); + char* name = (char*) serializer->findNameForPointer(this); + tcd->m_name = (char*)serializer->getUniquePointer(name); + if (tcd->m_name) + { + serializer->serializeName(name); + } + + tcd->m_objectType = m_objectType; + tcd->m_needsFeedback = m_needsFeedback; + tcd->m_overrideNumSolverIterations = m_overrideNumSolverIterations; + tcd->m_breakingImpulseThreshold = float(m_breakingImpulseThreshold); + tcd->m_isEnabled = m_isEnabled? 1: 0; + + tcd->m_userConstraintId =m_userConstraintId; + tcd->m_userConstraintType =m_userConstraintType; + + tcd->m_appliedImpulse = float(m_appliedImpulse); + tcd->m_dbgDrawSize = float(m_dbgDrawSize ); + + tcd->m_disableCollisionsBetweenLinkedBodies = false; + + int i; + for (i=0;im_disableCollisionsBetweenLinkedBodies = true; + for (i=0;im_disableCollisionsBetweenLinkedBodies = true; + + return "btTypedConstraintData"; +} + +btRigidBody& btTypedConstraint::getFixedBody() +{ + static btRigidBody s_fixed(0, 0,0); + s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); + return s_fixed; +} + + +void btAngularLimit::set(btScalar low, btScalar high, btScalar _softness, btScalar _biasFactor, btScalar _relaxationFactor) +{ + m_halfRange = (high - low) / 2.0f; + m_center = btNormalizeAngle(low + m_halfRange); + m_softness = _softness; + m_biasFactor = _biasFactor; + m_relaxationFactor = _relaxationFactor; +} + +void btAngularLimit::test(const btScalar angle) +{ + m_correction = 0.0f; + m_sign = 0.0f; + m_solveLimit = false; + + if (m_halfRange >= 0.0f) + { + btScalar deviation = btNormalizeAngle(angle - m_center); + if (deviation < -m_halfRange) + { + m_solveLimit = true; + m_correction = - (deviation + m_halfRange); + m_sign = +1.0f; + } + else if (deviation > m_halfRange) + { + m_solveLimit = true; + m_correction = m_halfRange - deviation; + m_sign = -1.0f; + } + } +} + + +btScalar btAngularLimit::getError() const +{ + return m_correction * m_sign; +} + +void btAngularLimit::fit(btScalar& angle) const +{ + if (m_halfRange > 0.0f) + { + btScalar relativeAngle = btNormalizeAngle(angle - m_center); + if (!btEqual(relativeAngle, m_halfRange)) + { + if (relativeAngle > 0.0f) + { + angle = getHigh(); + } + else + { + angle = getLow(); + } + } + } +} + +btScalar btAngularLimit::getLow() const +{ + return btNormalizeAngle(m_center - m_halfRange); +} + +btScalar btAngularLimit::getHigh() const +{ + return btNormalizeAngle(m_center + m_halfRange); +} diff --git a/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h new file mode 100644 index 0000000..a16e869 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h @@ -0,0 +1,452 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2010 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_TYPED_CONSTRAINT_H +#define BT_TYPED_CONSTRAINT_H + +class btRigidBody; +#include "LinearMath/btScalar.h" +#include "btSolverConstraint.h" + +class btSerializer; + +//Don't change any of the existing enum values, so add enum types at the end for serialization compatibility +enum btTypedConstraintType +{ + POINT2POINT_CONSTRAINT_TYPE=3, + HINGE_CONSTRAINT_TYPE, + CONETWIST_CONSTRAINT_TYPE, + D6_CONSTRAINT_TYPE, + SLIDER_CONSTRAINT_TYPE, + CONTACT_CONSTRAINT_TYPE, + D6_SPRING_CONSTRAINT_TYPE, + MAX_CONSTRAINT_TYPE +}; + + +enum btConstraintParams +{ + BT_CONSTRAINT_ERP=1, + BT_CONSTRAINT_STOP_ERP, + BT_CONSTRAINT_CFM, + BT_CONSTRAINT_STOP_CFM +}; + +#if 1 + #define btAssertConstrParams(_par) btAssert(_par) +#else + #define btAssertConstrParams(_par) +#endif + + +///TypedConstraint is the baseclass for Bullet constraints and vehicles +class btTypedConstraint : public btTypedObject +{ + int m_userConstraintType; + + union + { + int m_userConstraintId; + void* m_userConstraintPtr; + }; + + btScalar m_breakingImpulseThreshold; + bool m_isEnabled; + bool m_needsFeedback; + int m_overrideNumSolverIterations; + + + btTypedConstraint& operator=(btTypedConstraint& other) + { + btAssert(0); + (void) other; + return *this; + } + +protected: + btRigidBody& m_rbA; + btRigidBody& m_rbB; + btScalar m_appliedImpulse; + btScalar m_dbgDrawSize; + + ///internal method used by the constraint solver, don't use them directly + btScalar getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact); + + +public: + + virtual ~btTypedConstraint() {}; + btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA); + btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB); + + struct btConstraintInfo1 { + int m_numConstraintRows,nub; + }; + + static btRigidBody& getFixedBody(); + + struct btConstraintInfo2 { + // integrator parameters: frames per second (1/stepsize), default error + // reduction parameter (0..1). + btScalar fps,erp; + + // for the first and second body, pointers to two (linear and angular) + // n*3 jacobian sub matrices, stored by rows. these matrices will have + // been initialized to 0 on entry. if the second body is zero then the + // J2xx pointers may be 0. + btScalar *m_J1linearAxis,*m_J1angularAxis,*m_J2linearAxis,*m_J2angularAxis; + + // elements to jump from one row to the next in J's + int rowskip; + + // right hand sides of the equation J*v = c + cfm * lambda. cfm is the + // "constraint force mixing" vector. c is set to zero on entry, cfm is + // set to a constant value (typically very small or zero) value on entry. + btScalar *m_constraintError,*cfm; + + // lo and hi limits for variables (set to -/+ infinity on entry). + btScalar *m_lowerLimit,*m_upperLimit; + + // findex vector for variables. see the LCP solver interface for a + // description of what this does. this is set to -1 on entry. + // note that the returned indexes are relative to the first index of + // the constraint. + int *findex; + // number of solver iterations + int m_numIterations; + + //damping of the velocity + btScalar m_damping; + }; + + int getOverrideNumSolverIterations() const + { + return m_overrideNumSolverIterations; + } + + ///override the number of constraint solver iterations used to solve this constraint + ///-1 will use the default number of iterations, as specified in SolverInfo.m_numIterations + void setOverrideNumSolverIterations(int overideNumIterations) + { + m_overrideNumSolverIterations = overideNumIterations; + } + + ///internal method used by the constraint solver, don't use them directly + virtual void buildJacobian() {}; + + ///internal method used by the constraint solver, don't use them directly + virtual void setupSolverConstraint(btConstraintArray& ca, int solverBodyA,int solverBodyB, btScalar timeStep) + { + (void)ca; + (void)solverBodyA; + (void)solverBodyB; + (void)timeStep; + } + + ///internal method used by the constraint solver, don't use them directly + virtual void getInfo1 (btConstraintInfo1* info)=0; + + ///internal method used by the constraint solver, don't use them directly + virtual void getInfo2 (btConstraintInfo2* info)=0; + + ///internal method used by the constraint solver, don't use them directly + void internalSetAppliedImpulse(btScalar appliedImpulse) + { + m_appliedImpulse = appliedImpulse; + } + ///internal method used by the constraint solver, don't use them directly + btScalar internalGetAppliedImpulse() + { + return m_appliedImpulse; + } + + + btScalar getBreakingImpulseThreshold() const + { + return m_breakingImpulseThreshold; + } + + void setBreakingImpulseThreshold(btScalar threshold) + { + m_breakingImpulseThreshold = threshold; + } + + bool isEnabled() const + { + return m_isEnabled; + } + + void setEnabled(bool enabled) + { + m_isEnabled=enabled; + } + + + ///internal method used by the constraint solver, don't use them directly + virtual void solveConstraintObsolete(btRigidBody& /*bodyA*/,btRigidBody& /*bodyB*/,btScalar /*timeStep*/) {}; + + + const btRigidBody& getRigidBodyA() const + { + return m_rbA; + } + const btRigidBody& getRigidBodyB() const + { + return m_rbB; + } + + btRigidBody& getRigidBodyA() + { + return m_rbA; + } + btRigidBody& getRigidBodyB() + { + return m_rbB; + } + + int getUserConstraintType() const + { + return m_userConstraintType ; + } + + void setUserConstraintType(int userConstraintType) + { + m_userConstraintType = userConstraintType; + }; + + void setUserConstraintId(int uid) + { + m_userConstraintId = uid; + } + + int getUserConstraintId() const + { + return m_userConstraintId; + } + + void setUserConstraintPtr(void* ptr) + { + m_userConstraintPtr = ptr; + } + + void* getUserConstraintPtr() + { + return m_userConstraintPtr; + } + + int getUid() const + { + return m_userConstraintId; + } + + bool needsFeedback() const + { + return m_needsFeedback; + } + + ///enableFeedback will allow to read the applied linear and angular impulse + ///use getAppliedImpulse, getAppliedLinearImpulse and getAppliedAngularImpulse to read feedback information + void enableFeedback(bool needsFeedback) + { + m_needsFeedback = needsFeedback; + } + + ///getAppliedImpulse is an estimated total applied impulse. + ///This feedback could be used to determine breaking constraints or playing sounds. + btScalar getAppliedImpulse() const + { + btAssert(m_needsFeedback); + return m_appliedImpulse; + } + + btTypedConstraintType getConstraintType () const + { + return btTypedConstraintType(m_objectType); + } + + void setDbgDrawSize(btScalar dbgDrawSize) + { + m_dbgDrawSize = dbgDrawSize; + } + btScalar getDbgDrawSize() + { + return m_dbgDrawSize; + } + + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///If no axis is provided, it uses the default axis for this constraint. + virtual void setParam(int num, btScalar value, int axis = -1) = 0; + + ///return the local value of parameter + virtual btScalar getParam(int num, int axis = -1) const = 0; + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + +}; + +// returns angle in range [-SIMD_2_PI, SIMD_2_PI], closest to one of the limits +// all arguments should be normalized angles (i.e. in range [-SIMD_PI, SIMD_PI]) +SIMD_FORCE_INLINE btScalar btAdjustAngleToLimits(btScalar angleInRadians, btScalar angleLowerLimitInRadians, btScalar angleUpperLimitInRadians) +{ + if(angleLowerLimitInRadians >= angleUpperLimitInRadians) + { + return angleInRadians; + } + else if(angleInRadians < angleLowerLimitInRadians) + { + btScalar diffLo = btFabs(btNormalizeAngle(angleLowerLimitInRadians - angleInRadians)); + btScalar diffHi = btFabs(btNormalizeAngle(angleUpperLimitInRadians - angleInRadians)); + return (diffLo < diffHi) ? angleInRadians : (angleInRadians + SIMD_2_PI); + } + else if(angleInRadians > angleUpperLimitInRadians) + { + btScalar diffHi = btFabs(btNormalizeAngle(angleInRadians - angleUpperLimitInRadians)); + btScalar diffLo = btFabs(btNormalizeAngle(angleInRadians - angleLowerLimitInRadians)); + return (diffLo < diffHi) ? (angleInRadians - SIMD_2_PI) : angleInRadians; + } + else + { + return angleInRadians; + } +} + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btTypedConstraintData +{ + btRigidBodyData *m_rbA; + btRigidBodyData *m_rbB; + char *m_name; + + int m_objectType; + int m_userConstraintType; + int m_userConstraintId; + int m_needsFeedback; + + float m_appliedImpulse; + float m_dbgDrawSize; + + int m_disableCollisionsBetweenLinkedBodies; + int m_overrideNumSolverIterations; + + float m_breakingImpulseThreshold; + int m_isEnabled; + +}; + +SIMD_FORCE_INLINE int btTypedConstraint::calculateSerializeBufferSize() const +{ + return sizeof(btTypedConstraintData); +} + + + +class btAngularLimit +{ +private: + btScalar + m_center, + m_halfRange, + m_softness, + m_biasFactor, + m_relaxationFactor, + m_correction, + m_sign; + + bool + m_solveLimit; + +public: + /// Default constructor initializes limit as inactive, allowing free constraint movement + btAngularLimit() + :m_center(0.0f), + m_halfRange(-1.0f), + m_softness(0.9f), + m_biasFactor(0.3f), + m_relaxationFactor(1.0f), + m_correction(0.0f), + m_sign(0.0f), + m_solveLimit(false) + {} + + /// Sets all limit's parameters. + /// When low > high limit becomes inactive. + /// When high - low > 2PI limit is ineffective too becouse no angle can exceed the limit + void set(btScalar low, btScalar high, btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f); + + /// Checks conastaint angle against limit. If limit is active and the angle violates the limit + /// correction is calculated. + void test(const btScalar angle); + + /// Returns limit's softness + inline btScalar getSoftness() const + { + return m_softness; + } + + /// Returns limit's bias factor + inline btScalar getBiasFactor() const + { + return m_biasFactor; + } + + /// Returns limit's relaxation factor + inline btScalar getRelaxationFactor() const + { + return m_relaxationFactor; + } + + /// Returns correction value evaluated when test() was invoked + inline btScalar getCorrection() const + { + return m_correction; + } + + /// Returns sign value evaluated when test() was invoked + inline btScalar getSign() const + { + return m_sign; + } + + /// Gives half of the distance between min and max limit angle + inline btScalar getHalfRange() const + { + return m_halfRange; + } + + /// Returns true when the last test() invocation recognized limit violation + inline bool isLimit() const + { + return m_solveLimit; + } + + /// Checks given angle against limit. If limit is active and angle doesn't fit it, the angle + /// returned is modified so it equals to the limit closest to given angle. + void fit(btScalar& angle) const; + + /// Returns correction value multiplied by sign value + btScalar getError() const; + + btScalar getLow() const; + + btScalar getHigh() const; + +}; + + + +#endif //BT_TYPED_CONSTRAINT_H diff --git a/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp b/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp new file mode 100644 index 0000000..b009f41 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp @@ -0,0 +1,87 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +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 "btUniversalConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" + + + +#define UNIV_EPS btScalar(0.01f) + + +// constructor +// anchor, axis1 and axis2 are in world coordinate system +// axis1 must be orthogonal to axis2 +btUniversalConstraint::btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2) +: btGeneric6DofConstraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), true), + m_anchor(anchor), + m_axis1(axis1), + m_axis2(axis2) +{ + // build frame basis + // 6DOF constraint uses Euler angles and to define limits + // it is assumed that rotational order is : + // Z - first, allowed limits are (-PI,PI); + // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number + // used to prevent constraint from instability on poles; + // new position of X, allowed limits are (-PI,PI); + // So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs + // Build the frame in world coordinate system first + btVector3 zAxis = m_axis1.normalize(); + btVector3 yAxis = m_axis2.normalize(); + btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system + btTransform frameInW; + frameInW.setIdentity(); + frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0], + xAxis[1], yAxis[1], zAxis[1], + xAxis[2], yAxis[2], zAxis[2]); + frameInW.setOrigin(anchor); + // now get constraint frame in local coordinate systems + m_frameInA = rbA.getCenterOfMassTransform().inverse() * frameInW; + m_frameInB = rbB.getCenterOfMassTransform().inverse() * frameInW; + // sei limits + setLinearLowerLimit(btVector3(0., 0., 0.)); + setLinearUpperLimit(btVector3(0., 0., 0.)); + setAngularLowerLimit(btVector3(0.f, -SIMD_HALF_PI + UNIV_EPS, -SIMD_PI + UNIV_EPS)); + setAngularUpperLimit(btVector3(0.f, SIMD_HALF_PI - UNIV_EPS, SIMD_PI - UNIV_EPS)); +} + +void btUniversalConstraint::setAxis(const btVector3& axis1,const btVector3& axis2) +{ + m_axis1 = axis1; + m_axis2 = axis2; + + btVector3 zAxis = axis1.normalized(); + btVector3 yAxis = axis2.normalized(); + btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system + + btTransform frameInW; + frameInW.setIdentity(); + frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0], + xAxis[1], yAxis[1], zAxis[1], + xAxis[2], yAxis[2], zAxis[2]); + frameInW.setOrigin(m_anchor); + + // now get constraint frame in local coordinate systems + m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW; + m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW; + + calculateTransforms(); +} + + diff --git a/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h b/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h new file mode 100644 index 0000000..a869391 --- /dev/null +++ b/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h @@ -0,0 +1,62 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_UNIVERSAL_CONSTRAINT_H +#define BT_UNIVERSAL_CONSTRAINT_H + + + +#include "LinearMath/btVector3.h" +#include "btTypedConstraint.h" +#include "btGeneric6DofConstraint.h" + + + +/// Constraint similar to ODE Universal Joint +/// has 2 rotatioonal degrees of freedom, similar to Euler rotations around Z (axis 1) +/// and Y (axis 2) +/// Description from ODE manual : +/// "Given axis 1 on body 1, and axis 2 on body 2 that is perpendicular to axis 1, it keeps them perpendicular. +/// In other words, rotation of the two bodies about the direction perpendicular to the two axes will be equal." + +class btUniversalConstraint : public btGeneric6DofConstraint +{ +protected: + btVector3 m_anchor; + btVector3 m_axis1; + btVector3 m_axis2; +public: + // constructor + // anchor, axis1 and axis2 are in world coordinate system + // axis1 must be orthogonal to axis2 + btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2); + // access + const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); } + const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); } + const btVector3& getAxis1() { return m_axis1; } + const btVector3& getAxis2() { return m_axis2; } + btScalar getAngle1() { return getAngle(2); } + btScalar getAngle2() { return getAngle(1); } + // limits + void setUpperLimit(btScalar ang1max, btScalar ang2max) { setAngularUpperLimit(btVector3(0.f, ang1max, ang2max)); } + void setLowerLimit(btScalar ang1min, btScalar ang2min) { setAngularLowerLimit(btVector3(0.f, ang1min, ang2min)); } + + void setAxis( const btVector3& axis1, const btVector3& axis2); +}; + + + +#endif // BT_UNIVERSAL_CONSTRAINT_H + diff --git a/src/BulletDynamics/Dynamics/Bullet-C-API.cpp b/src/BulletDynamics/Dynamics/Bullet-C-API.cpp new file mode 100644 index 0000000..bd8e274 --- /dev/null +++ b/src/BulletDynamics/Dynamics/Bullet-C-API.cpp @@ -0,0 +1,405 @@ +/* +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. +*/ + +/* + Draft high-level generic physics C-API. For low-level access, use the physics SDK native API's. + Work in progress, functionality will be added on demand. + + If possible, use the richer Bullet C++ API, by including +*/ + +#include "Bullet-C-Api.h" +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btAlignedAllocator.h" + + + +#include "LinearMath/btVector3.h" +#include "LinearMath/btScalar.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btTransform.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" + +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btPointCollector.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" +#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" +#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" +#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" + + +/* + Create and Delete a Physics SDK +*/ + +struct btPhysicsSdk +{ + +// btDispatcher* m_dispatcher; +// btOverlappingPairCache* m_pairCache; +// btConstraintSolver* m_constraintSolver + + btVector3 m_worldAabbMin; + btVector3 m_worldAabbMax; + + + //todo: version, hardware/optimization settings etc? + btPhysicsSdk() + :m_worldAabbMin(-1000,-1000,-1000), + m_worldAabbMax(1000,1000,1000) + { + + } + + +}; + +plPhysicsSdkHandle plNewBulletSdk() +{ + void* mem = btAlignedAlloc(sizeof(btPhysicsSdk),16); + return (plPhysicsSdkHandle)new (mem)btPhysicsSdk; +} + +void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk) +{ + btPhysicsSdk* phys = reinterpret_cast(physicsSdk); + btAlignedFree(phys); +} + + +/* Dynamics World */ +plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdkHandle) +{ + btPhysicsSdk* physicsSdk = reinterpret_cast(physicsSdkHandle); + void* mem = btAlignedAlloc(sizeof(btDefaultCollisionConfiguration),16); + btDefaultCollisionConfiguration* collisionConfiguration = new (mem)btDefaultCollisionConfiguration(); + mem = btAlignedAlloc(sizeof(btCollisionDispatcher),16); + btDispatcher* dispatcher = new (mem)btCollisionDispatcher(collisionConfiguration); + mem = btAlignedAlloc(sizeof(btAxisSweep3),16); + btBroadphaseInterface* pairCache = new (mem)btAxisSweep3(physicsSdk->m_worldAabbMin,physicsSdk->m_worldAabbMax); + mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16); + btConstraintSolver* constraintSolver = new(mem) btSequentialImpulseConstraintSolver(); + + mem = btAlignedAlloc(sizeof(btDiscreteDynamicsWorld),16); + return (plDynamicsWorldHandle) new (mem)btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration); +} +void plDeleteDynamicsWorld(plDynamicsWorldHandle world) +{ + //todo: also clean up the other allocations, axisSweep, pairCache,dispatcher,constraintSolver,collisionConfiguration + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + btAlignedFree(dynamicsWorld); +} + +void plStepSimulation(plDynamicsWorldHandle world, plReal timeStep) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + btAssert(dynamicsWorld); + dynamicsWorld->stepSimulation(timeStep); +} + +void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + btAssert(dynamicsWorld); + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + + dynamicsWorld->addRigidBody(body); +} + +void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + btAssert(dynamicsWorld); + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + + dynamicsWorld->removeRigidBody(body); +} + +/* Rigid Body */ + +plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape ) +{ + btTransform trans; + trans.setIdentity(); + btVector3 localInertia(0,0,0); + btCollisionShape* shape = reinterpret_cast( cshape); + btAssert(shape); + if (mass) + { + shape->calculateLocalInertia(mass,localInertia); + } + void* mem = btAlignedAlloc(sizeof(btRigidBody),16); + btRigidBody::btRigidBodyConstructionInfo rbci(mass, 0,shape,localInertia); + btRigidBody* body = new (mem)btRigidBody(rbci); + body->setWorldTransform(trans); + body->setUserPointer(user_data); + return (plRigidBodyHandle) body; +} + +void plDeleteRigidBody(plRigidBodyHandle cbody) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(cbody); + btAssert(body); + btAlignedFree( body); +} + + +/* Collision Shape definition */ + +plCollisionShapeHandle plNewSphereShape(plReal radius) +{ + void* mem = btAlignedAlloc(sizeof(btSphereShape),16); + return (plCollisionShapeHandle) new (mem)btSphereShape(radius); + +} + +plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z) +{ + void* mem = btAlignedAlloc(sizeof(btBoxShape),16); + return (plCollisionShapeHandle) new (mem)btBoxShape(btVector3(x,y,z)); +} + +plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height) +{ + //capsule is convex hull of 2 spheres, so use btMultiSphereShape + + const int numSpheres = 2; + btVector3 positions[numSpheres] = {btVector3(0,height,0),btVector3(0,-height,0)}; + btScalar radi[numSpheres] = {radius,radius}; + void* mem = btAlignedAlloc(sizeof(btMultiSphereShape),16); + return (plCollisionShapeHandle) new (mem)btMultiSphereShape(positions,radi,numSpheres); +} +plCollisionShapeHandle plNewConeShape(plReal radius, plReal height) +{ + void* mem = btAlignedAlloc(sizeof(btConeShape),16); + return (plCollisionShapeHandle) new (mem)btConeShape(radius,height); +} + +plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height) +{ + void* mem = btAlignedAlloc(sizeof(btCylinderShape),16); + return (plCollisionShapeHandle) new (mem)btCylinderShape(btVector3(radius,height,radius)); +} + +/* Convex Meshes */ +plCollisionShapeHandle plNewConvexHullShape() +{ + void* mem = btAlignedAlloc(sizeof(btConvexHullShape),16); + return (plCollisionShapeHandle) new (mem)btConvexHullShape(); +} + + +/* Concave static triangle meshes */ +plMeshInterfaceHandle plNewMeshInterface() +{ + return 0; +} + +plCollisionShapeHandle plNewCompoundShape() +{ + void* mem = btAlignedAlloc(sizeof(btCompoundShape),16); + return (plCollisionShapeHandle) new (mem)btCompoundShape(); +} + +void plAddChildShape(plCollisionShapeHandle compoundShapeHandle,plCollisionShapeHandle childShapeHandle, plVector3 childPos,plQuaternion childOrn) +{ + btCollisionShape* colShape = reinterpret_cast(compoundShapeHandle); + btAssert(colShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE); + btCompoundShape* compoundShape = reinterpret_cast(colShape); + btCollisionShape* childShape = reinterpret_cast(childShapeHandle); + btTransform localTrans; + localTrans.setIdentity(); + localTrans.setOrigin(btVector3(childPos[0],childPos[1],childPos[2])); + localTrans.setRotation(btQuaternion(childOrn[0],childOrn[1],childOrn[2],childOrn[3])); + compoundShape->addChildShape(localTrans,childShape); +} + +void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient) +{ + btQuaternion orn; + orn.setEuler(yaw,pitch,roll); + orient[0] = orn.getX(); + orient[1] = orn.getY(); + orient[2] = orn.getZ(); + orient[3] = orn.getW(); + +} + + +// extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2); +// extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle); + + +void plAddVertex(plCollisionShapeHandle cshape, plReal x,plReal y,plReal z) +{ + btCollisionShape* colShape = reinterpret_cast( cshape); + (void)colShape; + btAssert(colShape->getShapeType()==CONVEX_HULL_SHAPE_PROXYTYPE); + btConvexHullShape* convexHullShape = reinterpret_cast( cshape); + convexHullShape->addPoint(btVector3(x,y,z)); + +} + +void plDeleteShape(plCollisionShapeHandle cshape) +{ + btCollisionShape* shape = reinterpret_cast( cshape); + btAssert(shape); + btAlignedFree(shape); +} +void plSetScaling(plCollisionShapeHandle cshape, plVector3 cscaling) +{ + btCollisionShape* shape = reinterpret_cast( cshape); + btAssert(shape); + btVector3 scaling(cscaling[0],cscaling[1],cscaling[2]); + shape->setLocalScaling(scaling); +} + + + +void plSetPosition(plRigidBodyHandle object, const plVector3 position) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + btVector3 pos(position[0],position[1],position[2]); + btTransform worldTrans = body->getWorldTransform(); + worldTrans.setOrigin(pos); + body->setWorldTransform(worldTrans); +} + +void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + btQuaternion orn(orientation[0],orientation[1],orientation[2],orientation[3]); + btTransform worldTrans = body->getWorldTransform(); + worldTrans.setRotation(orn); + body->setWorldTransform(worldTrans); +} + +void plSetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + btTransform& worldTrans = body->getWorldTransform(); + worldTrans.setFromOpenGLMatrix(matrix); +} + +void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + body->getWorldTransform().getOpenGLMatrix(matrix); + +} + +void plGetPosition(plRigidBodyHandle object,plVector3 position) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + const btVector3& pos = body->getWorldTransform().getOrigin(); + position[0] = pos.getX(); + position[1] = pos.getY(); + position[2] = pos.getZ(); +} + +void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + const btQuaternion& orn = body->getWorldTransform().getRotation(); + orientation[0] = orn.getX(); + orientation[1] = orn.getY(); + orientation[2] = orn.getZ(); + orientation[3] = orn.getW(); +} + + + +//plRigidBodyHandle plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); + +// extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); + +double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]) +{ + btVector3 vp(p1[0], p1[1], p1[2]); + btTriangleShape trishapeA(vp, + btVector3(p2[0], p2[1], p2[2]), + btVector3(p3[0], p3[1], p3[2])); + trishapeA.setMargin(0.000001f); + btVector3 vq(q1[0], q1[1], q1[2]); + btTriangleShape trishapeB(vq, + btVector3(q2[0], q2[1], q2[2]), + btVector3(q3[0], q3[1], q3[2])); + trishapeB.setMargin(0.000001f); + + // btVoronoiSimplexSolver sGjkSimplexSolver; + // btGjkEpaPenetrationDepthSolver penSolverPtr; + + static btSimplexSolverInterface sGjkSimplexSolver; + sGjkSimplexSolver.reset(); + + static btGjkEpaPenetrationDepthSolver Solver0; + static btMinkowskiPenetrationDepthSolver Solver1; + + btConvexPenetrationDepthSolver* Solver = NULL; + + Solver = &Solver1; + + btGjkPairDetector convexConvex(&trishapeA ,&trishapeB,&sGjkSimplexSolver,Solver); + + convexConvex.m_catchDegeneracies = 1; + + // btGjkPairDetector convexConvex(&trishapeA ,&trishapeB,&sGjkSimplexSolver,0); + + btPointCollector gjkOutput; + btGjkPairDetector::ClosestPointInput input; + + + btTransform tr; + tr.setIdentity(); + + input.m_transformA = tr; + input.m_transformB = tr; + + convexConvex.getClosestPoints(input, gjkOutput, 0); + + + if (gjkOutput.m_hasResult) + { + + pb[0] = pa[0] = gjkOutput.m_pointInWorld[0]; + pb[1] = pa[1] = gjkOutput.m_pointInWorld[1]; + pb[2] = pa[2] = gjkOutput.m_pointInWorld[2]; + + pb[0]+= gjkOutput.m_normalOnBInWorld[0] * gjkOutput.m_distance; + pb[1]+= gjkOutput.m_normalOnBInWorld[1] * gjkOutput.m_distance; + pb[2]+= gjkOutput.m_normalOnBInWorld[2] * gjkOutput.m_distance; + + normal[0] = gjkOutput.m_normalOnBInWorld[0]; + normal[1] = gjkOutput.m_normalOnBInWorld[1]; + normal[2] = gjkOutput.m_normalOnBInWorld[2]; + + return gjkOutput.m_distance; + } + return -1.0f; +} + diff --git a/src/BulletDynamics/Dynamics/btActionInterface.h b/src/BulletDynamics/Dynamics/btActionInterface.h new file mode 100644 index 0000000..e1fea3a --- /dev/null +++ b/src/BulletDynamics/Dynamics/btActionInterface.h @@ -0,0 +1,46 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef _BT_ACTION_INTERFACE_H +#define _BT_ACTION_INTERFACE_H + +class btIDebugDraw; +class btCollisionWorld; + +#include "LinearMath/btScalar.h" +#include "btRigidBody.h" + +///Basic interface to allow actions such as vehicles and characters to be updated inside a btDynamicsWorld +class btActionInterface +{ +protected: + + static btRigidBody& getFixedBody(); + + +public: + + virtual ~btActionInterface() + { + } + + virtual void updateAction( btCollisionWorld* collisionWorld, btScalar deltaTimeStep)=0; + + virtual void debugDraw(btIDebugDraw* debugDrawer) = 0; + +}; + +#endif //_BT_ACTION_INTERFACE_H + diff --git a/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp new file mode 100644 index 0000000..954ef24 --- /dev/null +++ b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -0,0 +1,1257 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btDiscreteDynamicsWorld.h" + +//collision detection +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" +#include "LinearMath/btTransformUtil.h" +#include "LinearMath/btQuickprof.h" + +//rigidbody & constraints +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h" +#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h" +#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h" +#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h" +#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h" +#include "BulletDynamics/ConstraintSolver/btContactConstraint.h" + + +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + + +#include "BulletDynamics/Dynamics/btActionInterface.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btMotionState.h" + +#include "LinearMath/btSerializer.h" + +#if 0 +btAlignedObjectArray debugContacts; +btAlignedObjectArray debugNormals; +int startHit=2; +int firstHit=startHit; +#endif + +SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs) +{ + int islandId; + + const btCollisionObject& rcolObj0 = lhs->getRigidBodyA(); + const btCollisionObject& rcolObj1 = lhs->getRigidBodyB(); + islandId= rcolObj0.getIslandTag()>=0?rcolObj0.getIslandTag():rcolObj1.getIslandTag(); + return islandId; + +} + + +class btSortConstraintOnIslandPredicate +{ + public: + + bool operator() ( const btTypedConstraint* lhs, const btTypedConstraint* rhs ) const + { + int rIslandId0,lIslandId0; + rIslandId0 = btGetConstraintIslandId(rhs); + lIslandId0 = btGetConstraintIslandId(lhs); + return lIslandId0 < rIslandId0; + } +}; + +struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback +{ + btContactSolverInfo* m_solverInfo; + btConstraintSolver* m_solver; + btTypedConstraint** m_sortedConstraints; + int m_numConstraints; + btIDebugDraw* m_debugDrawer; + btStackAlloc* m_stackAlloc; + btDispatcher* m_dispatcher; + + btAlignedObjectArray m_bodies; + btAlignedObjectArray m_manifolds; + btAlignedObjectArray m_constraints; + + + InplaceSolverIslandCallback( + btConstraintSolver* solver, + btStackAlloc* stackAlloc, + btDispatcher* dispatcher) + :m_solverInfo(NULL), + m_solver(solver), + m_sortedConstraints(NULL), + m_numConstraints(0), + m_debugDrawer(NULL), + m_stackAlloc(stackAlloc), + m_dispatcher(dispatcher) + { + + } + + InplaceSolverIslandCallback& operator=(InplaceSolverIslandCallback& other) + { + btAssert(0); + (void)other; + return *this; + } + + SIMD_FORCE_INLINE void setup ( btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btIDebugDraw* debugDrawer) + { + btAssert(solverInfo); + m_solverInfo = solverInfo; + m_sortedConstraints = sortedConstraints; + m_numConstraints = numConstraints; + m_debugDrawer = debugDrawer; + m_bodies.resize (0); + m_manifolds.resize (0); + m_constraints.resize (0); + } + + + virtual void processIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId) + { + if (islandId<0) + { + if (numManifolds + m_numConstraints) + { + ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id + m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,*m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); + } + } else + { + //also add all non-contact constraints/joints for this island + btTypedConstraint** startConstraint = 0; + int numCurConstraints = 0; + int i; + + //find the first constraint for this island + for (i=0;im_minimumSolverBatchSize<=1) + { + ///only call solveGroup if there is some work: avoid virtual function call, its overhead can be excessive + if (numManifolds + numCurConstraints) + { + m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); + } + } else + { + + for (i=0;im_solverInfo->m_minimumSolverBatchSize) + { + processConstraints(); + } else + { + //printf("deferred\n"); + } + } + } + } + void processConstraints() + { + if (m_manifolds.size() + m_constraints.size()>0) + { + + btCollisionObject** bodies = m_bodies.size()? &m_bodies[0]:0; + btPersistentManifold** manifold = m_manifolds.size()?&m_manifolds[0]:0; + btTypedConstraint** constraints = m_constraints.size()?&m_constraints[0]:0; + + m_solver->solveGroup( bodies,m_bodies.size(),manifold, m_manifolds.size(),constraints, m_constraints.size() ,*m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); + } + m_bodies.resize(0); + m_manifolds.resize(0); + m_constraints.resize(0); + + } + +}; + + + +btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration) +:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration), +m_constraintSolver(constraintSolver), +m_gravity(0,-10,0), +m_localTime(0), +m_synchronizeAllMotionStates(false), +m_profileTimings(0), +m_sortedConstraints (), +m_solverIslandCallback ( NULL ) +{ + if (!m_constraintSolver) + { + void* mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16); + m_constraintSolver = new (mem) btSequentialImpulseConstraintSolver; + m_ownsConstraintSolver = true; + } else + { + m_ownsConstraintSolver = false; + } + + { + void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager),16); + m_islandManager = new (mem) btSimulationIslandManager(); + } + + m_ownsIslandManager = true; + + { + void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallback),16); + m_solverIslandCallback = new (mem) InplaceSolverIslandCallback (constraintSolver, m_stackAlloc, dispatcher); + } +} + + +btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld() +{ + //only delete it when we created it + if (m_ownsIslandManager) + { + m_islandManager->~btSimulationIslandManager(); + btAlignedFree( m_islandManager); + } + if (m_solverIslandCallback) + { + m_solverIslandCallback->~InplaceSolverIslandCallback(); + btAlignedFree(m_solverIslandCallback); + } + if (m_ownsConstraintSolver) + { + + m_constraintSolver->~btConstraintSolver(); + btAlignedFree(m_constraintSolver); + } +} + +void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep) +{ +///would like to iterate over m_nonStaticRigidBodies, but unfortunately old API allows +///to switch status _after_ adding kinematic objects to the world +///fix it for Bullet 3.x release + for (int i=0;igetActivationState() != ISLAND_SLEEPING) + { + if (body->isKinematicObject()) + { + //to calculate velocities next frame + body->saveKinematicState(timeStep); + } + } + } + +} + +void btDiscreteDynamicsWorld::debugDrawWorld() +{ + BT_PROFILE("debugDrawWorld"); + + btCollisionWorld::debugDrawWorld(); + + bool drawConstraints = false; + if (getDebugDrawer()) + { + int mode = getDebugDrawer()->getDebugMode(); + if(mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits)) + { + drawConstraints = true; + } + } + if(drawConstraints) + { + for(int i = getNumConstraints()-1; i>=0 ;i--) + { + btTypedConstraint* constraint = getConstraint(i); + debugDrawConstraint(constraint); + } + } + + + + if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb | btIDebugDraw::DBG_DrawNormals))) + { + int i; + + if (getDebugDrawer() && getDebugDrawer()->getDebugMode()) + { + for (i=0;idebugDraw(m_debugDrawer); + } + } + } +} + +void btDiscreteDynamicsWorld::clearForces() +{ + ///@todo: iterate over awake simulation islands! + for ( int i=0;iclearForces(); + } +} + +///apply gravity, call this once per timestep +void btDiscreteDynamicsWorld::applyGravity() +{ + ///@todo: iterate over awake simulation islands! + for ( int i=0;iisActive()) + { + body->applyGravity(); + } + } +} + + +void btDiscreteDynamicsWorld::synchronizeSingleMotionState(btRigidBody* body) +{ + btAssert(body); + + if (body->getMotionState() && !body->isStaticOrKinematicObject()) + { + //we need to call the update at least once, even for sleeping objects + //otherwise the 'graphics' transform never updates properly + ///@todo: add 'dirty' flag + //if (body->getActivationState() != ISLAND_SLEEPING) + { + btTransform interpolatedTransform; + btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), + body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),m_localTime*body->getHitFraction(),interpolatedTransform); + body->getMotionState()->setWorldTransform(interpolatedTransform); + } + } +} + + +void btDiscreteDynamicsWorld::synchronizeMotionStates() +{ + BT_PROFILE("synchronizeMotionStates"); + if (m_synchronizeAllMotionStates) + { + //iterate over all collision objects + for ( int i=0;iisActive()) + synchronizeSingleMotionState(body); + } + } +} + + +int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) +{ + startProfiling(timeStep); + + BT_PROFILE("stepSimulation"); + + int numSimulationSubSteps = 0; + + if (maxSubSteps) + { + //fixed timestep with interpolation + m_localTime += timeStep; + if (m_localTime >= fixedTimeStep) + { + numSimulationSubSteps = int( m_localTime / fixedTimeStep); + m_localTime -= numSimulationSubSteps * fixedTimeStep; + } + } else + { + //variable timestep + fixedTimeStep = timeStep; + m_localTime = timeStep; + if (btFuzzyZero(timeStep)) + { + numSimulationSubSteps = 0; + maxSubSteps = 0; + } else + { + numSimulationSubSteps = 1; + maxSubSteps = 1; + } + } + + //process some debugging flags + if (getDebugDrawer()) + { + btIDebugDraw* debugDrawer = getDebugDrawer (); + gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0; + } + if (numSimulationSubSteps) + { + + //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt + int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps; + + saveKinematicState(fixedTimeStep*clampedSimulationSteps); + + applyGravity(); + + + + for (int i=0;iisActive() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY)) + { + body->setGravity(gravity); + } + } +} + +btVector3 btDiscreteDynamicsWorld::getGravity () const +{ + return m_gravity; +} + +void btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask) +{ + btCollisionWorld::addCollisionObject(collisionObject,collisionFilterGroup,collisionFilterMask); +} + +void btDiscreteDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject) +{ + btRigidBody* body = btRigidBody::upcast(collisionObject); + if (body) + removeRigidBody(body); + else + btCollisionWorld::removeCollisionObject(collisionObject); +} + +void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body) +{ + m_nonStaticRigidBodies.remove(body); + btCollisionWorld::removeCollisionObject(body); +} + + +void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body) +{ + if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY)) + { + body->setGravity(m_gravity); + } + + if (body->getCollisionShape()) + { + if (!body->isStaticObject()) + { + m_nonStaticRigidBodies.push_back(body); + } else + { + body->setActivationState(ISLAND_SLEEPING); + } + + bool isDynamic = !(body->isStaticObject() || body->isKinematicObject()); + short collisionFilterGroup = isDynamic? short(btBroadphaseProxy::DefaultFilter) : short(btBroadphaseProxy::StaticFilter); + short collisionFilterMask = isDynamic? short(btBroadphaseProxy::AllFilter) : short(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter); + + addCollisionObject(body,collisionFilterGroup,collisionFilterMask); + } +} + +void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short mask) +{ + if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY)) + { + body->setGravity(m_gravity); + } + + if (body->getCollisionShape()) + { + if (!body->isStaticObject()) + { + m_nonStaticRigidBodies.push_back(body); + } + else + { + body->setActivationState(ISLAND_SLEEPING); + } + addCollisionObject(body,group,mask); + } +} + + +void btDiscreteDynamicsWorld::updateActions(btScalar timeStep) +{ + BT_PROFILE("updateActions"); + + for ( int i=0;iupdateAction( this, timeStep); + } +} + + +void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep) +{ + BT_PROFILE("updateActivationState"); + + for ( int i=0;iupdateDeactivation(timeStep); + + if (body->wantsSleeping()) + { + if (body->isStaticOrKinematicObject()) + { + body->setActivationState(ISLAND_SLEEPING); + } else + { + if (body->getActivationState() == ACTIVE_TAG) + body->setActivationState( WANTS_DEACTIVATION ); + if (body->getActivationState() == ISLAND_SLEEPING) + { + body->setAngularVelocity(btVector3(0,0,0)); + body->setLinearVelocity(btVector3(0,0,0)); + } + + } + } else + { + if (body->getActivationState() != DISABLE_DEACTIVATION) + body->setActivationState( ACTIVE_TAG ); + } + } + } +} + +void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies) +{ + m_constraints.push_back(constraint); + if (disableCollisionsBetweenLinkedBodies) + { + constraint->getRigidBodyA().addConstraintRef(constraint); + constraint->getRigidBodyB().addConstraintRef(constraint); + } +} + +void btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint) +{ + m_constraints.remove(constraint); + constraint->getRigidBodyA().removeConstraintRef(constraint); + constraint->getRigidBodyB().removeConstraintRef(constraint); +} + +void btDiscreteDynamicsWorld::addAction(btActionInterface* action) +{ + m_actions.push_back(action); +} + +void btDiscreteDynamicsWorld::removeAction(btActionInterface* action) +{ + m_actions.remove(action); +} + + +void btDiscreteDynamicsWorld::addVehicle(btActionInterface* vehicle) +{ + addAction(vehicle); +} + +void btDiscreteDynamicsWorld::removeVehicle(btActionInterface* vehicle) +{ + removeAction(vehicle); +} + +void btDiscreteDynamicsWorld::addCharacter(btActionInterface* character) +{ + addAction(character); +} + +void btDiscreteDynamicsWorld::removeCharacter(btActionInterface* character) +{ + removeAction(character); +} + + + + +void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) +{ + BT_PROFILE("solveConstraints"); + + m_sortedConstraints.resize( m_constraints.size()); + int i; + for (i=0;isetup(&solverInfo,constraintsPtr,m_sortedConstraints.size(),getDebugDrawer()); + m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds()); + + /// solve all the constraints for this island + m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld(),m_solverIslandCallback); + + m_solverIslandCallback->processConstraints(); + + m_constraintSolver->allSolved(solverInfo, m_debugDrawer, m_stackAlloc); +} + + +void btDiscreteDynamicsWorld::calculateSimulationIslands() +{ + BT_PROFILE("calculateSimulationIslands"); + + getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher()); + + { + int i; + int numConstraints = int(m_constraints.size()); + for (i=0;i< numConstraints ; i++ ) + { + btTypedConstraint* constraint = m_constraints[i]; + if (constraint->isEnabled()) + { + const btRigidBody* colObj0 = &constraint->getRigidBodyA(); + const btRigidBody* colObj1 = &constraint->getRigidBodyB(); + + if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) && + ((colObj1) && (!(colObj1)->isStaticOrKinematicObject()))) + { + if (colObj0->isActive() || colObj1->isActive()) + { + + getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), + (colObj1)->getIslandTag()); + } + } + } + } + } + + //Store the island id in each body + getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld()); + + +} + + + + +class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback +{ +public: + + btCollisionObject* m_me; + btScalar m_allowedPenetration; + btOverlappingPairCache* m_pairCache; + btDispatcher* m_dispatcher; + +public: + btClosestNotMeConvexResultCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) : + btCollisionWorld::ClosestConvexResultCallback(fromA,toA), + m_me(me), + m_allowedPenetration(0.0f), + m_pairCache(pairCache), + m_dispatcher(dispatcher) + { + } + + virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace) + { + if (convexResult.m_hitCollisionObject == m_me) + return 1.0f; + + //ignore result if there is no contact response + if(!convexResult.m_hitCollisionObject->hasContactResponse()) + return 1.0f; + + btVector3 linVelA,linVelB; + linVelA = m_convexToWorld-m_convexFromWorld; + linVelB = btVector3(0,0,0);//toB.getOrigin()-fromB.getOrigin(); + + btVector3 relativeVelocity = (linVelA-linVelB); + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if (convexResult.m_hitNormalLocal.dot(relativeVelocity)>=-m_allowedPenetration) + return 1.f; + + return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace); + } + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + //don't collide with itself + if (proxy0->m_clientObject == m_me) + return false; + + ///don't do CCD when the collision filters are not matching + if (!ClosestConvexResultCallback::needsCollision(proxy0)) + return false; + + btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject; + + //call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179 + if (m_dispatcher->needsResponse(m_me,otherObj)) + { +#if 0 + ///don't do CCD when there are already contact points (touching contact/penetration) + btAlignedObjectArray manifoldArray; + btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0); + if (collisionPair) + { + if (collisionPair->m_algorithm) + { + manifoldArray.resize(0); + collisionPair->m_algorithm->getAllContactManifolds(manifoldArray); + for (int j=0;jgetNumContacts()>0) + return false; + } + } + } +#endif + return true; + } + + return false; + } + + +}; + +///internal debugging variable. this value shouldn't be too high +int gNumClampedCcdMotions=0; + +void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) +{ + BT_PROFILE("integrateTransforms"); + btTransform predictedTrans; + for ( int i=0;isetHitFraction(1.f); + + if (body->isActive() && (!body->isStaticOrKinematicObject())) + { + + body->predictIntegratedTransform(timeStep, predictedTrans); + + btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2(); + + + + if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion) + { + BT_PROFILE("CCD motion clamping"); + if (body->getCollisionShape()->isConvex()) + { + gNumClampedCcdMotions++; +#ifdef USE_STATIC_ONLY + class StaticOnlyCallback : public btClosestNotMeConvexResultCallback + { + public: + + StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) : + btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher) + { + } + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject; + if (!otherObj->isStaticOrKinematicObject()) + return false; + return btClosestNotMeConvexResultCallback::needsCollision(proxy0); + } + }; + + StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher()); +#else + btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher()); +#endif + //btConvexShape* convexShape = static_cast(body->getCollisionShape()); + btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast(body->getCollisionShape()); + sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration; + + sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup; + sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask; + btTransform modifiedPredictedTrans = predictedTrans; + modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis()); + + convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults); + if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f)) + { + + //printf("clamped integration to hit fraction = %f\n",fraction); + body->setHitFraction(sweepResults.m_closestHitFraction); + body->predictIntegratedTransform(timeStep*body->getHitFraction(), predictedTrans); + body->setHitFraction(0.f); + body->proceedToTransform( predictedTrans); + +#if 0 + btVector3 linVel = body->getLinearVelocity(); + + btScalar maxSpeed = body->getCcdMotionThreshold()/getSolverInfo().m_timeStep; + btScalar maxSpeedSqr = maxSpeed*maxSpeed; + if (linVel.length2()>maxSpeedSqr) + { + linVel.normalize(); + linVel*= maxSpeed; + body->setLinearVelocity(linVel); + btScalar ms2 = body->getLinearVelocity().length2(); + body->predictIntegratedTransform(timeStep, predictedTrans); + + btScalar sm2 = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2(); + btScalar smt = body->getCcdSquareMotionThreshold(); + printf("sm2=%f\n",sm2); + } +#else + //response between two dynamic objects without friction, assuming 0 penetration depth + btScalar appliedImpulse = 0.f; + btScalar depth = 0.f; + appliedImpulse = resolveSingleCollision(body,sweepResults.m_hitCollisionObject,sweepResults.m_hitPointWorld,sweepResults.m_hitNormalWorld,getSolverInfo(), depth); + + +#endif + + continue; + } + } + } + + + body->proceedToTransform( predictedTrans); + } + } +} + + + + + + +void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) +{ + BT_PROFILE("predictUnconstraintMotion"); + for ( int i=0;iisStaticOrKinematicObject()) + { + body->integrateVelocities( timeStep); + //damping + body->applyDamping(timeStep); + + body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); + } + } +} + + +void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep) +{ + (void)timeStep; + +#ifndef BT_NO_PROFILE + CProfileManager::Reset(); +#endif //BT_NO_PROFILE + +} + + + + + + +void btDiscreteDynamicsWorld::debugDrawConstraint(btTypedConstraint* constraint) +{ + bool drawFrames = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraints) != 0; + bool drawLimits = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraintLimits) != 0; + btScalar dbgDrawSize = constraint->getDbgDrawSize(); + if(dbgDrawSize <= btScalar(0.f)) + { + return; + } + + switch(constraint->getConstraintType()) + { + case POINT2POINT_CONSTRAINT_TYPE: + { + btPoint2PointConstraint* p2pC = (btPoint2PointConstraint*)constraint; + btTransform tr; + tr.setIdentity(); + btVector3 pivot = p2pC->getPivotInA(); + pivot = p2pC->getRigidBodyA().getCenterOfMassTransform() * pivot; + tr.setOrigin(pivot); + getDebugDrawer()->drawTransform(tr, dbgDrawSize); + // that ideally should draw the same frame + pivot = p2pC->getPivotInB(); + pivot = p2pC->getRigidBodyB().getCenterOfMassTransform() * pivot; + tr.setOrigin(pivot); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + } + break; + case HINGE_CONSTRAINT_TYPE: + { + btHingeConstraint* pHinge = (btHingeConstraint*)constraint; + btTransform tr = pHinge->getRigidBodyA().getCenterOfMassTransform() * pHinge->getAFrame(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + tr = pHinge->getRigidBodyB().getCenterOfMassTransform() * pHinge->getBFrame(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + btScalar minAng = pHinge->getLowerLimit(); + btScalar maxAng = pHinge->getUpperLimit(); + if(minAng == maxAng) + { + break; + } + bool drawSect = true; + if(minAng > maxAng) + { + minAng = btScalar(0.f); + maxAng = SIMD_2_PI; + drawSect = false; + } + if(drawLimits) + { + btVector3& center = tr.getOrigin(); + btVector3 normal = tr.getBasis().getColumn(2); + btVector3 axis = tr.getBasis().getColumn(0); + getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, minAng, maxAng, btVector3(0,0,0), drawSect); + } + } + break; + case CONETWIST_CONSTRAINT_TYPE: + { + btConeTwistConstraint* pCT = (btConeTwistConstraint*)constraint; + btTransform tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + if(drawLimits) + { + //const btScalar length = btScalar(5); + const btScalar length = dbgDrawSize; + static int nSegments = 8*4; + btScalar fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)(nSegments-1)/btScalar(nSegments); + btVector3 pPrev = pCT->GetPointForAngle(fAngleInRadians, length); + pPrev = tr * pPrev; + for (int i=0; iGetPointForAngle(fAngleInRadians, length); + pCur = tr * pCur; + getDebugDrawer()->drawLine(pPrev, pCur, btVector3(0,0,0)); + + if (i%(nSegments/8) == 0) + getDebugDrawer()->drawLine(tr.getOrigin(), pCur, btVector3(0,0,0)); + + pPrev = pCur; + } + btScalar tws = pCT->getTwistSpan(); + btScalar twa = pCT->getTwistAngle(); + bool useFrameB = (pCT->getRigidBodyB().getInvMass() > btScalar(0.f)); + if(useFrameB) + { + tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame(); + } + else + { + tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame(); + } + btVector3 pivot = tr.getOrigin(); + btVector3 normal = tr.getBasis().getColumn(0); + btVector3 axis1 = tr.getBasis().getColumn(1); + getDebugDrawer()->drawArc(pivot, normal, axis1, dbgDrawSize, dbgDrawSize, -twa-tws, -twa+tws, btVector3(0,0,0), true); + + } + } + break; + case D6_SPRING_CONSTRAINT_TYPE: + case D6_CONSTRAINT_TYPE: + { + btGeneric6DofConstraint* p6DOF = (btGeneric6DofConstraint*)constraint; + btTransform tr = p6DOF->getCalculatedTransformA(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + tr = p6DOF->getCalculatedTransformB(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + if(drawLimits) + { + tr = p6DOF->getCalculatedTransformA(); + const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin(); + btVector3 up = tr.getBasis().getColumn(2); + btVector3 axis = tr.getBasis().getColumn(0); + btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit; + btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit; + btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit; + btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit; + getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0,0,0)); + axis = tr.getBasis().getColumn(1); + btScalar ay = p6DOF->getAngle(1); + btScalar az = p6DOF->getAngle(2); + btScalar cy = btCos(ay); + btScalar sy = btSin(ay); + btScalar cz = btCos(az); + btScalar sz = btSin(az); + btVector3 ref; + ref[0] = cy*cz*axis[0] + cy*sz*axis[1] - sy*axis[2]; + ref[1] = -sz*axis[0] + cz*axis[1]; + ref[2] = cz*sy*axis[0] + sz*sy*axis[1] + cy*axis[2]; + tr = p6DOF->getCalculatedTransformB(); + btVector3 normal = -tr.getBasis().getColumn(0); + btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit; + btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit; + if(minFi > maxFi) + { + getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0,0,0), false); + } + else if(minFi < maxFi) + { + getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0,0,0), true); + } + tr = p6DOF->getCalculatedTransformA(); + btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit; + btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit; + getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0,0,0)); + } + } + break; + case SLIDER_CONSTRAINT_TYPE: + { + btSliderConstraint* pSlider = (btSliderConstraint*)constraint; + btTransform tr = pSlider->getCalculatedTransformA(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + tr = pSlider->getCalculatedTransformB(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + if(drawLimits) + { + btTransform tr = pSlider->getUseLinearReferenceFrameA() ? pSlider->getCalculatedTransformA() : pSlider->getCalculatedTransformB(); + btVector3 li_min = tr * btVector3(pSlider->getLowerLinLimit(), 0.f, 0.f); + btVector3 li_max = tr * btVector3(pSlider->getUpperLinLimit(), 0.f, 0.f); + getDebugDrawer()->drawLine(li_min, li_max, btVector3(0, 0, 0)); + btVector3 normal = tr.getBasis().getColumn(0); + btVector3 axis = tr.getBasis().getColumn(1); + btScalar a_min = pSlider->getLowerAngLimit(); + btScalar a_max = pSlider->getUpperAngLimit(); + const btVector3& center = pSlider->getCalculatedTransformB().getOrigin(); + getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, a_min, a_max, btVector3(0,0,0), true); + } + } + break; + default : + break; + } + return; +} + + + + + +void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) +{ + if (m_ownsConstraintSolver) + { + btAlignedFree( m_constraintSolver); + } + m_ownsConstraintSolver = false; + m_constraintSolver = solver; +} + +btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver() +{ + return m_constraintSolver; +} + + +int btDiscreteDynamicsWorld::getNumConstraints() const +{ + return int(m_constraints.size()); +} +btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) +{ + return m_constraints[index]; +} +const btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) const +{ + return m_constraints[index]; +} + + + +void btDiscreteDynamicsWorld::serializeRigidBodies(btSerializer* serializer) +{ + int i; + //serialize all collision objects + for (i=0;igetInternalType() & btCollisionObject::CO_RIGID_BODY) + { + int len = colObj->calculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(len,1); + const char* structType = colObj->serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_RIGIDBODY_CODE,colObj); + } + } + + for (i=0;icalculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(size,1); + const char* structType = constraint->serialize(chunk->m_oldPtr,serializer); + serializer->finalizeChunk(chunk,structType,BT_CONSTRAINT_CODE,constraint); + } +} + + +void btDiscreteDynamicsWorld::serialize(btSerializer* serializer) +{ + + serializer->startSerialization(); + + serializeRigidBodies(serializer); + + serializeCollisionObjects(serializer); + + serializer->finishSerialization(); +} + diff --git a/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h new file mode 100644 index 0000000..23a38dd --- /dev/null +++ b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h @@ -0,0 +1,203 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_DISCRETE_DYNAMICS_WORLD_H +#define BT_DISCRETE_DYNAMICS_WORLD_H + +#include "btDynamicsWorld.h" + +class btDispatcher; +class btOverlappingPairCache; +class btConstraintSolver; +class btSimulationIslandManager; +class btTypedConstraint; +class btActionInterface; + +class btIDebugDraw; +struct InplaceSolverIslandCallback; + +#include "LinearMath/btAlignedObjectArray.h" + + +///btDiscreteDynamicsWorld provides discrete rigid body simulation +///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController +class btDiscreteDynamicsWorld : public btDynamicsWorld +{ +protected: + + btAlignedObjectArray m_sortedConstraints; + InplaceSolverIslandCallback* m_solverIslandCallback; + + btConstraintSolver* m_constraintSolver; + + btSimulationIslandManager* m_islandManager; + + btAlignedObjectArray m_constraints; + + btAlignedObjectArray m_nonStaticRigidBodies; + + btVector3 m_gravity; + + //for variable timesteps + btScalar m_localTime; + //for variable timesteps + + bool m_ownsIslandManager; + bool m_ownsConstraintSolver; + bool m_synchronizeAllMotionStates; + + btAlignedObjectArray m_actions; + + int m_profileTimings; + + virtual void predictUnconstraintMotion(btScalar timeStep); + + virtual void integrateTransforms(btScalar timeStep); + + virtual void calculateSimulationIslands(); + + virtual void solveConstraints(btContactSolverInfo& solverInfo); + + void updateActivationState(btScalar timeStep); + + void updateActions(btScalar timeStep); + + void startProfiling(btScalar timeStep); + + virtual void internalSingleStepSimulation( btScalar timeStep); + + + virtual void saveKinematicState(btScalar timeStep); + + void serializeRigidBodies(btSerializer* serializer); + +public: + + + ///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those + btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); + + virtual ~btDiscreteDynamicsWorld(); + + ///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's + virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); + + + virtual void synchronizeMotionStates(); + + ///this can be useful to synchronize a single rigid body -> graphics object + void synchronizeSingleMotionState(btRigidBody* body); + + virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false); + + virtual void removeConstraint(btTypedConstraint* constraint); + + virtual void addAction(btActionInterface*); + + virtual void removeAction(btActionInterface*); + + btSimulationIslandManager* getSimulationIslandManager() + { + return m_islandManager; + } + + const btSimulationIslandManager* getSimulationIslandManager() const + { + return m_islandManager; + } + + btCollisionWorld* getCollisionWorld() + { + return this; + } + + virtual void setGravity(const btVector3& gravity); + + virtual btVector3 getGravity () const; + + virtual void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::StaticFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter); + + virtual void addRigidBody(btRigidBody* body); + + virtual void addRigidBody(btRigidBody* body, short group, short mask); + + virtual void removeRigidBody(btRigidBody* body); + + ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject + virtual void removeCollisionObject(btCollisionObject* collisionObject); + + + void debugDrawConstraint(btTypedConstraint* constraint); + + virtual void debugDrawWorld(); + + virtual void setConstraintSolver(btConstraintSolver* solver); + + virtual btConstraintSolver* getConstraintSolver(); + + virtual int getNumConstraints() const; + + virtual btTypedConstraint* getConstraint(int index) ; + + virtual const btTypedConstraint* getConstraint(int index) const; + + + virtual btDynamicsWorldType getWorldType() const + { + return BT_DISCRETE_DYNAMICS_WORLD; + } + + ///the forces on each rigidbody is accumulating together with gravity. clear this after each timestep. + virtual void clearForces(); + + ///apply gravity, call this once per timestep + virtual void applyGravity(); + + virtual void setNumTasks(int numTasks) + { + (void) numTasks; + } + + ///obsolete, use updateActions instead + virtual void updateVehicles(btScalar timeStep) + { + updateActions(timeStep); + } + + ///obsolete, use addAction instead + virtual void addVehicle(btActionInterface* vehicle); + ///obsolete, use removeAction instead + virtual void removeVehicle(btActionInterface* vehicle); + ///obsolete, use addAction instead + virtual void addCharacter(btActionInterface* character); + ///obsolete, use removeAction instead + virtual void removeCharacter(btActionInterface* character); + + void setSynchronizeAllMotionStates(bool synchronizeAll) + { + m_synchronizeAllMotionStates = synchronizeAll; + } + bool getSynchronizeAllMotionStates() const + { + return m_synchronizeAllMotionStates; + } + + ///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (see Bullet/Demos/SerializeDemo) + virtual void serialize(btSerializer* serializer); + +}; + +#endif //BT_DISCRETE_DYNAMICS_WORLD_H diff --git a/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/src/BulletDynamics/Dynamics/btDynamicsWorld.h new file mode 100644 index 0000000..6b00933 --- /dev/null +++ b/src/BulletDynamics/Dynamics/btDynamicsWorld.h @@ -0,0 +1,151 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_DYNAMICS_WORLD_H +#define BT_DYNAMICS_WORLD_H + +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" + +class btTypedConstraint; +class btActionInterface; +class btConstraintSolver; +class btDynamicsWorld; + + +/// Type for the callback for each tick +typedef void (*btInternalTickCallback)(btDynamicsWorld *world, btScalar timeStep); + +enum btDynamicsWorldType +{ + BT_SIMPLE_DYNAMICS_WORLD=1, + BT_DISCRETE_DYNAMICS_WORLD=2, + BT_CONTINUOUS_DYNAMICS_WORLD=3, + BT_SOFT_RIGID_DYNAMICS_WORLD=4 +}; + +///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc. +class btDynamicsWorld : public btCollisionWorld +{ + +protected: + btInternalTickCallback m_internalTickCallback; + btInternalTickCallback m_internalPreTickCallback; + void* m_worldUserInfo; + + btContactSolverInfo m_solverInfo; + +public: + + + btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration) + :btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0),m_internalPreTickCallback(0), m_worldUserInfo(0) + { + } + + virtual ~btDynamicsWorld() + { + } + + ///stepSimulation proceeds the simulation over 'timeStep', units in preferably in seconds. + ///By default, Bullet will subdivide the timestep in constant substeps of each 'fixedTimeStep'. + ///in order to keep the simulation real-time, the maximum number of substeps can be clamped to 'maxSubSteps'. + ///You can disable subdividing the timestep/substepping by passing maxSubSteps=0 as second argument to stepSimulation, but in that case you have to keep the timeStep constant. + virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0; + + virtual void debugDrawWorld() = 0; + + virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false) + { + (void)constraint; (void)disableCollisionsBetweenLinkedBodies; + } + + virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;} + + virtual void addAction(btActionInterface* action) = 0; + + virtual void removeAction(btActionInterface* action) = 0; + + //once a rigidbody is added to the dynamics world, it will get this gravity assigned + //existing rigidbodies in the world get gravity assigned too, during this method + virtual void setGravity(const btVector3& gravity) = 0; + virtual btVector3 getGravity () const = 0; + + virtual void synchronizeMotionStates() = 0; + + virtual void addRigidBody(btRigidBody* body) = 0; + + virtual void addRigidBody(btRigidBody* body, short group, short mask) = 0; + + virtual void removeRigidBody(btRigidBody* body) = 0; + + virtual void setConstraintSolver(btConstraintSolver* solver) = 0; + + virtual btConstraintSolver* getConstraintSolver() = 0; + + virtual int getNumConstraints() const { return 0; } + + virtual btTypedConstraint* getConstraint(int index) { (void)index; return 0; } + + virtual const btTypedConstraint* getConstraint(int index) const { (void)index; return 0; } + + virtual btDynamicsWorldType getWorldType() const=0; + + virtual void clearForces() = 0; + + /// Set the callback for when an internal tick (simulation substep) happens, optional user info + void setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo=0,bool isPreTick=false) + { + if (isPreTick) + { + m_internalPreTickCallback = cb; + } else + { + m_internalTickCallback = cb; + } + m_worldUserInfo = worldUserInfo; + } + + void setWorldUserInfo(void* worldUserInfo) + { + m_worldUserInfo = worldUserInfo; + } + + void* getWorldUserInfo() const + { + return m_worldUserInfo; + } + + btContactSolverInfo& getSolverInfo() + { + return m_solverInfo; + } + + + ///obsolete, use addAction instead. + virtual void addVehicle(btActionInterface* vehicle) {(void)vehicle;} + ///obsolete, use removeAction instead + virtual void removeVehicle(btActionInterface* vehicle) {(void)vehicle;} + ///obsolete, use addAction instead. + virtual void addCharacter(btActionInterface* character) {(void)character;} + ///obsolete, use removeAction instead + virtual void removeCharacter(btActionInterface* character) {(void)character;} + + +}; + +#endif //BT_DYNAMICS_WORLD_H + + diff --git a/src/BulletDynamics/Dynamics/btRigidBody.cpp b/src/BulletDynamics/Dynamics/btRigidBody.cpp new file mode 100644 index 0000000..911b507 --- /dev/null +++ b/src/BulletDynamics/Dynamics/btRigidBody.cpp @@ -0,0 +1,403 @@ +/* +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 "btRigidBody.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "LinearMath/btMinMax.h" +#include "LinearMath/btTransformUtil.h" +#include "LinearMath/btMotionState.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "LinearMath/btSerializer.h" + +//'temporarily' global variables +btScalar gDeactivationTime = btScalar(2.); +bool gDisableDeactivation = false; +static int uniqueId = 0; + + +btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo) +{ + setupRigidBody(constructionInfo); +} + +btRigidBody::btRigidBody(btScalar mass, btMotionState *motionState, btCollisionShape *collisionShape, const btVector3 &localInertia) +{ + btRigidBodyConstructionInfo cinfo(mass,motionState,collisionShape,localInertia); + setupRigidBody(cinfo); +} + +void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo) +{ + + m_internalType=CO_RIGID_BODY; + + m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + m_angularFactor.setValue(1,1,1); + m_linearFactor.setValue(1,1,1); + m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_gravity_acceleration.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping); + + m_linearSleepingThreshold = constructionInfo.m_linearSleepingThreshold; + m_angularSleepingThreshold = constructionInfo.m_angularSleepingThreshold; + m_optionalMotionState = constructionInfo.m_motionState; + m_contactSolverType = 0; + m_frictionSolverType = 0; + m_additionalDamping = constructionInfo.m_additionalDamping; + m_additionalDampingFactor = constructionInfo.m_additionalDampingFactor; + m_additionalLinearDampingThresholdSqr = constructionInfo.m_additionalLinearDampingThresholdSqr; + m_additionalAngularDampingThresholdSqr = constructionInfo.m_additionalAngularDampingThresholdSqr; + m_additionalAngularDampingFactor = constructionInfo.m_additionalAngularDampingFactor; + + if (m_optionalMotionState) + { + m_optionalMotionState->getWorldTransform(m_worldTransform); + } else + { + m_worldTransform = constructionInfo.m_startWorldTransform; + } + + m_interpolationWorldTransform = m_worldTransform; + m_interpolationLinearVelocity.setValue(0,0,0); + m_interpolationAngularVelocity.setValue(0,0,0); + + //moved to btCollisionObject + m_friction = constructionInfo.m_friction; + m_restitution = constructionInfo.m_restitution; + + setCollisionShape( constructionInfo.m_collisionShape ); + m_debugBodyId = uniqueId++; + + setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia); + updateInertiaTensor(); + + m_rigidbodyFlags = 0; + + + m_deltaLinearVelocity.setZero(); + m_deltaAngularVelocity.setZero(); + m_invMass = m_inverseMass*m_linearFactor; + m_pushVelocity.setZero(); + m_turnVelocity.setZero(); + + + +} + + +void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform) +{ + btTransformUtil::integrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform); +} + +void btRigidBody::saveKinematicState(btScalar timeStep) +{ + //todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities + if (timeStep != btScalar(0.)) + { + //if we use motionstate to synchronize world transforms, get the new kinematic/animated world transform + if (getMotionState()) + getMotionState()->getWorldTransform(m_worldTransform); + btVector3 linVel,angVel; + + btTransformUtil::calculateVelocity(m_interpolationWorldTransform,m_worldTransform,timeStep,m_linearVelocity,m_angularVelocity); + m_interpolationLinearVelocity = m_linearVelocity; + m_interpolationAngularVelocity = m_angularVelocity; + m_interpolationWorldTransform = m_worldTransform; + //printf("angular = %f %f %f\n",m_angularVelocity.getX(),m_angularVelocity.getY(),m_angularVelocity.getZ()); + } +} + +void btRigidBody::getAabb(btVector3& aabbMin,btVector3& aabbMax) const +{ + getCollisionShape()->getAabb(m_worldTransform,aabbMin,aabbMax); +} + + + + +void btRigidBody::setGravity(const btVector3& acceleration) +{ + if (m_inverseMass != btScalar(0.0)) + { + m_gravity = acceleration * (btScalar(1.0) / m_inverseMass); + } + m_gravity_acceleration = acceleration; +} + + + + + + +void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping) +{ + m_linearDamping = btClamped(lin_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); + m_angularDamping = btClamped(ang_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); +} + + + + +///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping +void btRigidBody::applyDamping(btScalar timeStep) +{ + //On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74 + //todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway + +//#define USE_OLD_DAMPING_METHOD 1 +#ifdef USE_OLD_DAMPING_METHOD + m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); + m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); +#else + m_linearVelocity *= btPow(btScalar(1)-m_linearDamping, timeStep); + m_angularVelocity *= btPow(btScalar(1)-m_angularDamping, timeStep); +#endif + + if (m_additionalDamping) + { + //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc. + //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete + if ((m_angularVelocity.length2() < m_additionalAngularDampingThresholdSqr) && + (m_linearVelocity.length2() < m_additionalLinearDampingThresholdSqr)) + { + m_angularVelocity *= m_additionalDampingFactor; + m_linearVelocity *= m_additionalDampingFactor; + } + + + btScalar speed = m_linearVelocity.length(); + if (speed < m_linearDamping) + { + btScalar dampVel = btScalar(0.005); + if (speed > dampVel) + { + btVector3 dir = m_linearVelocity.normalized(); + m_linearVelocity -= dir * dampVel; + } else + { + m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + } + + btScalar angSpeed = m_angularVelocity.length(); + if (angSpeed < m_angularDamping) + { + btScalar angDampVel = btScalar(0.005); + if (angSpeed > angDampVel) + { + btVector3 dir = m_angularVelocity.normalized(); + m_angularVelocity -= dir * angDampVel; + } else + { + m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + } + } +} + + +void btRigidBody::applyGravity() +{ + if (isStaticOrKinematicObject()) + return; + + applyCentralForce(m_gravity); + +} + +void btRigidBody::proceedToTransform(const btTransform& newTrans) +{ + setCenterOfMassTransform( newTrans ); +} + + +void btRigidBody::setMassProps(btScalar mass, const btVector3& inertia) +{ + if (mass == btScalar(0.)) + { + m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT; + m_inverseMass = btScalar(0.); + } else + { + m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT); + m_inverseMass = btScalar(1.0) / mass; + } + + //Fg = m * a + m_gravity = mass * m_gravity_acceleration; + + m_invInertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x(): btScalar(0.0), + inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y(): btScalar(0.0), + inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z(): btScalar(0.0)); + + m_invMass = m_linearFactor*m_inverseMass; +} + + + +void btRigidBody::updateInertiaTensor() +{ + m_invInertiaTensorWorld = m_worldTransform.getBasis().scaled(m_invInertiaLocal) * m_worldTransform.getBasis().transpose(); +} + + +void btRigidBody::integrateVelocities(btScalar step) +{ + if (isStaticOrKinematicObject()) + return; + + m_linearVelocity += m_totalForce * (m_inverseMass * step); + m_angularVelocity += m_invInertiaTensorWorld * m_totalTorque * step; + +#define MAX_ANGVEL SIMD_HALF_PI + /// clamp angular velocity. collision calculations will fail on higher angular velocities + btScalar angvel = m_angularVelocity.length(); + if (angvel*step > MAX_ANGVEL) + { + m_angularVelocity *= (MAX_ANGVEL/step) /angvel; + } + +} + +btQuaternion btRigidBody::getOrientation() const +{ + btQuaternion orn; + m_worldTransform.getBasis().getRotation(orn); + return orn; +} + + +void btRigidBody::setCenterOfMassTransform(const btTransform& xform) +{ + + if (isKinematicObject()) + { + m_interpolationWorldTransform = m_worldTransform; + } else + { + m_interpolationWorldTransform = xform; + } + m_interpolationLinearVelocity = getLinearVelocity(); + m_interpolationAngularVelocity = getAngularVelocity(); + m_worldTransform = xform; + updateInertiaTensor(); +} + + +bool btRigidBody::checkCollideWithOverride(btCollisionObject* co) +{ + btRigidBody* otherRb = btRigidBody::upcast(co); + if (!otherRb) + return true; + + for (int i = 0; i < m_constraintRefs.size(); ++i) + { + btTypedConstraint* c = m_constraintRefs[i]; + if (c->isEnabled()) + if (&c->getRigidBodyA() == otherRb || &c->getRigidBodyB() == otherRb) + return false; + } + + return true; +} + +void btRigidBody::internalWritebackVelocity(btScalar timeStep) +{ + (void) timeStep; + if (m_inverseMass) + { + setLinearVelocity(getLinearVelocity()+ m_deltaLinearVelocity); + setAngularVelocity(getAngularVelocity()+m_deltaAngularVelocity); + + //correct the position/orientation based on push/turn recovery + btTransform newTransform; + btTransformUtil::integrateTransform(getWorldTransform(),m_pushVelocity,m_turnVelocity,timeStep,newTransform); + setWorldTransform(newTransform); + //m_originalBody->setCompanionId(-1); + } +// m_deltaLinearVelocity.setZero(); +// m_deltaAngularVelocity .setZero(); +// m_pushVelocity.setZero(); +// m_turnVelocity.setZero(); +} + + + +void btRigidBody::addConstraintRef(btTypedConstraint* c) +{ + int index = m_constraintRefs.findLinearSearch(c); + if (index == m_constraintRefs.size()) + m_constraintRefs.push_back(c); + + m_checkCollideWith = true; +} + +void btRigidBody::removeConstraintRef(btTypedConstraint* c) +{ + m_constraintRefs.remove(c); + m_checkCollideWith = m_constraintRefs.size() > 0; +} + +int btRigidBody::calculateSerializeBufferSize() const +{ + int sz = sizeof(btRigidBodyData); + return sz; +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btRigidBody::serialize(void* dataBuffer, class btSerializer* serializer) const +{ + btRigidBodyData* rbd = (btRigidBodyData*) dataBuffer; + + btCollisionObject::serialize(&rbd->m_collisionObjectData, serializer); + + m_invInertiaTensorWorld.serialize(rbd->m_invInertiaTensorWorld); + m_linearVelocity.serialize(rbd->m_linearVelocity); + m_angularVelocity.serialize(rbd->m_angularVelocity); + rbd->m_inverseMass = m_inverseMass; + m_angularFactor.serialize(rbd->m_angularFactor); + m_linearFactor.serialize(rbd->m_linearFactor); + m_gravity.serialize(rbd->m_gravity); + m_gravity_acceleration.serialize(rbd->m_gravity_acceleration); + m_invInertiaLocal.serialize(rbd->m_invInertiaLocal); + m_totalForce.serialize(rbd->m_totalForce); + m_totalTorque.serialize(rbd->m_totalTorque); + rbd->m_linearDamping = m_linearDamping; + rbd->m_angularDamping = m_angularDamping; + rbd->m_additionalDamping = m_additionalDamping; + rbd->m_additionalDampingFactor = m_additionalDampingFactor; + rbd->m_additionalLinearDampingThresholdSqr = m_additionalLinearDampingThresholdSqr; + rbd->m_additionalAngularDampingThresholdSqr = m_additionalAngularDampingThresholdSqr; + rbd->m_additionalAngularDampingFactor = m_additionalAngularDampingFactor; + rbd->m_linearSleepingThreshold=m_linearSleepingThreshold; + rbd->m_angularSleepingThreshold = m_angularSleepingThreshold; + + return btRigidBodyDataName; +} + + + +void btRigidBody::serializeSingleObject(class btSerializer* serializer) const +{ + btChunk* chunk = serializer->allocate(calculateSerializeBufferSize(),1); + const char* structType = serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_RIGIDBODY_CODE,(void*)this); +} + + diff --git a/src/BulletDynamics/Dynamics/btRigidBody.h b/src/BulletDynamics/Dynamics/btRigidBody.h new file mode 100644 index 0000000..7c121e6 --- /dev/null +++ b/src/BulletDynamics/Dynamics/btRigidBody.h @@ -0,0 +1,691 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_RIGIDBODY_H +#define BT_RIGIDBODY_H + +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btTransform.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" + +class btCollisionShape; +class btMotionState; +class btTypedConstraint; + + +extern btScalar gDeactivationTime; +extern bool gDisableDeactivation; + +#ifdef BT_USE_DOUBLE_PRECISION +#define btRigidBodyData btRigidBodyDoubleData +#define btRigidBodyDataName "btRigidBodyDoubleData" +#else +#define btRigidBodyData btRigidBodyFloatData +#define btRigidBodyDataName "btRigidBodyFloatData" +#endif //BT_USE_DOUBLE_PRECISION + + +enum btRigidBodyFlags +{ + BT_DISABLE_WORLD_GRAVITY = 1 +}; + + +///The btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape. +///It is recommended for performance and memory use to share btCollisionShape objects whenever possible. +///There are 3 types of rigid bodies: +///- A) Dynamic rigid bodies, with positive mass. Motion is controlled by rigid body dynamics. +///- B) Fixed objects with zero mass. They are not moving (basically collision objects) +///- C) Kinematic objects, which are objects without mass, but the user can move them. There is on-way interaction, and Bullet calculates a velocity based on the timestep and previous and current world transform. +///Bullet automatically deactivates dynamic rigid bodies, when the velocity is below a threshold for a given time. +///Deactivated (sleeping) rigid bodies don't take any processing time, except a minor broadphase collision detection impact (to allow active objects to activate/wake up sleeping objects) +class btRigidBody : public btCollisionObject +{ + + btMatrix3x3 m_invInertiaTensorWorld; + btVector3 m_linearVelocity; + btVector3 m_angularVelocity; + btScalar m_inverseMass; + btVector3 m_linearFactor; + + btVector3 m_gravity; + btVector3 m_gravity_acceleration; + btVector3 m_invInertiaLocal; + btVector3 m_totalForce; + btVector3 m_totalTorque; + + btScalar m_linearDamping; + btScalar m_angularDamping; + + bool m_additionalDamping; + btScalar m_additionalDampingFactor; + btScalar m_additionalLinearDampingThresholdSqr; + btScalar m_additionalAngularDampingThresholdSqr; + btScalar m_additionalAngularDampingFactor; + + + btScalar m_linearSleepingThreshold; + btScalar m_angularSleepingThreshold; + + //m_optionalMotionState allows to automatic synchronize the world transform for active objects + btMotionState* m_optionalMotionState; + + //keep track of typed constraints referencing this rigid body + btAlignedObjectArray m_constraintRefs; + + int m_rigidbodyFlags; + + int m_debugBodyId; + + +protected: + + ATTRIBUTE_ALIGNED64(btVector3 m_deltaLinearVelocity); + btVector3 m_deltaAngularVelocity; + btVector3 m_angularFactor; + btVector3 m_invMass; + btVector3 m_pushVelocity; + btVector3 m_turnVelocity; + + +public: + + + ///The btRigidBodyConstructionInfo structure provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body. + ///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument) + ///You can use the motion state to synchronize the world transform between physics and graphics objects. + ///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state, + ///m_startWorldTransform is only used when you don't provide a motion state. + struct btRigidBodyConstructionInfo + { + btScalar m_mass; + + ///When a motionState is provided, the rigid body will initialize its world transform from the motion state + ///In this case, m_startWorldTransform is ignored. + btMotionState* m_motionState; + btTransform m_startWorldTransform; + + btCollisionShape* m_collisionShape; + btVector3 m_localInertia; + btScalar m_linearDamping; + btScalar m_angularDamping; + + ///best simulation results when friction is non-zero + btScalar m_friction; + ///best simulation results using zero restitution. + btScalar m_restitution; + + btScalar m_linearSleepingThreshold; + btScalar m_angularSleepingThreshold; + + //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc. + //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete + bool m_additionalDamping; + btScalar m_additionalDampingFactor; + btScalar m_additionalLinearDampingThresholdSqr; + btScalar m_additionalAngularDampingThresholdSqr; + btScalar m_additionalAngularDampingFactor; + + btRigidBodyConstructionInfo( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)): + m_mass(mass), + m_motionState(motionState), + m_collisionShape(collisionShape), + m_localInertia(localInertia), + m_linearDamping(btScalar(0.)), + m_angularDamping(btScalar(0.)), + m_friction(btScalar(0.5)), + m_restitution(btScalar(0.)), + m_linearSleepingThreshold(btScalar(0.8)), + m_angularSleepingThreshold(btScalar(1.f)), + m_additionalDamping(false), + m_additionalDampingFactor(btScalar(0.005)), + m_additionalLinearDampingThresholdSqr(btScalar(0.01)), + m_additionalAngularDampingThresholdSqr(btScalar(0.01)), + m_additionalAngularDampingFactor(btScalar(0.01)) + { + m_startWorldTransform.setIdentity(); + } + }; + + ///btRigidBody constructor using construction info + btRigidBody( const btRigidBodyConstructionInfo& constructionInfo); + + ///btRigidBody constructor for backwards compatibility. + ///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo) + btRigidBody( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)); + + + virtual ~btRigidBody() + { + //No constraints should point to this rigidbody + //Remove constraints from the dynamics world before you delete the related rigidbodies. + btAssert(m_constraintRefs.size()==0); + } + +protected: + + ///setupRigidBody is only used internally by the constructor + void setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo); + +public: + + void proceedToTransform(const btTransform& newTrans); + + ///to keep collision detection and dynamics separate we don't store a rigidbody pointer + ///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast + static const btRigidBody* upcast(const btCollisionObject* colObj) + { + if (colObj->getInternalType()&btCollisionObject::CO_RIGID_BODY) + return (const btRigidBody*)colObj; + return 0; + } + static btRigidBody* upcast(btCollisionObject* colObj) + { + if (colObj->getInternalType()&btCollisionObject::CO_RIGID_BODY) + return (btRigidBody*)colObj; + return 0; + } + + /// continuous collision detection needs prediction + void predictIntegratedTransform(btScalar step, btTransform& predictedTransform) ; + + void saveKinematicState(btScalar step); + + void applyGravity(); + + void setGravity(const btVector3& acceleration); + + const btVector3& getGravity() const + { + return m_gravity_acceleration; + } + + void setDamping(btScalar lin_damping, btScalar ang_damping); + + btScalar getLinearDamping() const + { + return m_linearDamping; + } + + btScalar getAngularDamping() const + { + return m_angularDamping; + } + + btScalar getLinearSleepingThreshold() const + { + return m_linearSleepingThreshold; + } + + btScalar getAngularSleepingThreshold() const + { + return m_angularSleepingThreshold; + } + + void applyDamping(btScalar timeStep); + + SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { + return m_collisionShape; + } + + SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() { + return m_collisionShape; + } + + void setMassProps(btScalar mass, const btVector3& inertia); + + const btVector3& getLinearFactor() const + { + return m_linearFactor; + } + void setLinearFactor(const btVector3& linearFactor) + { + m_linearFactor = linearFactor; + m_invMass = m_linearFactor*m_inverseMass; + } + btScalar getInvMass() const { return m_inverseMass; } + const btMatrix3x3& getInvInertiaTensorWorld() const { + return m_invInertiaTensorWorld; + } + + void integrateVelocities(btScalar step); + + void setCenterOfMassTransform(const btTransform& xform); + + void applyCentralForce(const btVector3& force) + { + m_totalForce += force*m_linearFactor; + } + + const btVector3& getTotalForce() const + { + return m_totalForce; + }; + + const btVector3& getTotalTorque() const + { + return m_totalTorque; + }; + + const btVector3& getInvInertiaDiagLocal() const + { + return m_invInertiaLocal; + }; + + void setInvInertiaDiagLocal(const btVector3& diagInvInertia) + { + m_invInertiaLocal = diagInvInertia; + } + + void setSleepingThresholds(btScalar linear,btScalar angular) + { + m_linearSleepingThreshold = linear; + m_angularSleepingThreshold = angular; + } + + void applyTorque(const btVector3& torque) + { + m_totalTorque += torque*m_angularFactor; + } + + void applyForce(const btVector3& force, const btVector3& rel_pos) + { + applyCentralForce(force); + applyTorque(rel_pos.cross(force*m_linearFactor)); + } + + void applyCentralImpulse(const btVector3& impulse) + { + m_linearVelocity += impulse *m_linearFactor * m_inverseMass; + } + + void applyTorqueImpulse(const btVector3& torque) + { + m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor; + } + + void applyImpulse(const btVector3& impulse, const btVector3& rel_pos) + { + if (m_inverseMass != btScalar(0.)) + { + applyCentralImpulse(impulse); + if (m_angularFactor) + { + applyTorqueImpulse(rel_pos.cross(impulse*m_linearFactor)); + } + } + } + + void clearForces() + { + m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + } + + void updateInertiaTensor(); + + const btVector3& getCenterOfMassPosition() const { + return m_worldTransform.getOrigin(); + } + btQuaternion getOrientation() const; + + const btTransform& getCenterOfMassTransform() const { + return m_worldTransform; + } + const btVector3& getLinearVelocity() const { + return m_linearVelocity; + } + const btVector3& getAngularVelocity() const { + return m_angularVelocity; + } + + + inline void setLinearVelocity(const btVector3& lin_vel) + { + m_linearVelocity = lin_vel; + } + + inline void setAngularVelocity(const btVector3& ang_vel) + { + m_angularVelocity = ang_vel; + } + + btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const + { + //we also calculate lin/ang velocity for kinematic objects + return m_linearVelocity + m_angularVelocity.cross(rel_pos); + + //for kinematic objects, we could also use use: + // return (m_worldTransform(rel_pos) - m_interpolationWorldTransform(rel_pos)) / m_kinematicTimeStep; + } + + void translate(const btVector3& v) + { + m_worldTransform.getOrigin() += v; + } + + + void getAabb(btVector3& aabbMin,btVector3& aabbMax) const; + + + + + + SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btVector3& pos, const btVector3& normal) const + { + btVector3 r0 = pos - getCenterOfMassPosition(); + + btVector3 c0 = (r0).cross(normal); + + btVector3 vec = (c0 * getInvInertiaTensorWorld()).cross(r0); + + return m_inverseMass + normal.dot(vec); + + } + + SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const + { + btVector3 vec = axis * getInvInertiaTensorWorld(); + return axis.dot(vec); + } + + SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep) + { + if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION)) + return; + + if ((getLinearVelocity().length2() < m_linearSleepingThreshold*m_linearSleepingThreshold) && + (getAngularVelocity().length2() < m_angularSleepingThreshold*m_angularSleepingThreshold)) + { + m_deactivationTime += timeStep; + } else + { + m_deactivationTime=btScalar(0.); + setActivationState(0); + } + + } + + SIMD_FORCE_INLINE bool wantsSleeping() + { + + if (getActivationState() == DISABLE_DEACTIVATION) + return false; + + //disable deactivation + if (gDisableDeactivation || (gDeactivationTime == btScalar(0.))) + return false; + + if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION)) + return true; + + if (m_deactivationTime> gDeactivationTime) + { + return true; + } + return false; + } + + + + const btBroadphaseProxy* getBroadphaseProxy() const + { + return m_broadphaseHandle; + } + btBroadphaseProxy* getBroadphaseProxy() + { + return m_broadphaseHandle; + } + void setNewBroadphaseProxy(btBroadphaseProxy* broadphaseProxy) + { + m_broadphaseHandle = broadphaseProxy; + } + + //btMotionState allows to automatic synchronize the world transform for active objects + btMotionState* getMotionState() + { + return m_optionalMotionState; + } + const btMotionState* getMotionState() const + { + return m_optionalMotionState; + } + void setMotionState(btMotionState* motionState) + { + m_optionalMotionState = motionState; + if (m_optionalMotionState) + motionState->getWorldTransform(m_worldTransform); + } + + //for experimental overriding of friction/contact solver func + int m_contactSolverType; + int m_frictionSolverType; + + void setAngularFactor(const btVector3& angFac) + { + m_angularFactor = angFac; + } + + void setAngularFactor(btScalar angFac) + { + m_angularFactor.setValue(angFac,angFac,angFac); + } + const btVector3& getAngularFactor() const + { + return m_angularFactor; + } + + //is this rigidbody added to a btCollisionWorld/btDynamicsWorld/btBroadphase? + bool isInWorld() const + { + return (getBroadphaseProxy() != 0); + } + + virtual bool checkCollideWithOverride(btCollisionObject* co); + + void addConstraintRef(btTypedConstraint* c); + void removeConstraintRef(btTypedConstraint* c); + + btTypedConstraint* getConstraintRef(int index) + { + return m_constraintRefs[index]; + } + + int getNumConstraintRefs() const + { + return m_constraintRefs.size(); + } + + void setFlags(int flags) + { + m_rigidbodyFlags = flags; + } + + int getFlags() const + { + return m_rigidbodyFlags; + } + + const btVector3& getDeltaLinearVelocity() const + { + return m_deltaLinearVelocity; + } + + const btVector3& getDeltaAngularVelocity() const + { + return m_deltaAngularVelocity; + } + + const btVector3& getPushVelocity() const + { + return m_pushVelocity; + } + + const btVector3& getTurnVelocity() const + { + return m_turnVelocity; + } + + + //////////////////////////////////////////////// + ///some internal methods, don't use them + + btVector3& internalGetDeltaLinearVelocity() + { + return m_deltaLinearVelocity; + } + + btVector3& internalGetDeltaAngularVelocity() + { + return m_deltaAngularVelocity; + } + + const btVector3& internalGetAngularFactor() const + { + return m_angularFactor; + } + + const btVector3& internalGetInvMass() const + { + return m_invMass; + } + + btVector3& internalGetPushVelocity() + { + return m_pushVelocity; + } + + btVector3& internalGetTurnVelocity() + { + return m_turnVelocity; + } + + SIMD_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const + { + velocity = getLinearVelocity()+m_deltaLinearVelocity + (getAngularVelocity()+m_deltaAngularVelocity).cross(rel_pos); + } + + SIMD_FORCE_INLINE void internalGetAngularVelocity(btVector3& angVel) const + { + angVel = getAngularVelocity()+m_deltaAngularVelocity; + } + + + //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position + SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude) + { + if (m_inverseMass) + { + m_deltaLinearVelocity += linearComponent*impulseMagnitude; + m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor); + } + } + + SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) + { + if (m_inverseMass) + { + m_pushVelocity += linearComponent*impulseMagnitude; + m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor); + } + } + + void internalWritebackVelocity() + { + if (m_inverseMass) + { + setLinearVelocity(getLinearVelocity()+ m_deltaLinearVelocity); + setAngularVelocity(getAngularVelocity()+m_deltaAngularVelocity); + //m_deltaLinearVelocity.setZero(); + //m_deltaAngularVelocity .setZero(); + //m_originalBody->setCompanionId(-1); + } + } + + + void internalWritebackVelocity(btScalar timeStep); + + + + /////////////////////////////////////////////// + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const; + + virtual void serializeSingleObject(class btSerializer* serializer) const; + +}; + +//@todo add m_optionalMotionState and m_constraintRefs to btRigidBodyData +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btRigidBodyFloatData +{ + btCollisionObjectFloatData m_collisionObjectData; + btMatrix3x3FloatData m_invInertiaTensorWorld; + btVector3FloatData m_linearVelocity; + btVector3FloatData m_angularVelocity; + btVector3FloatData m_angularFactor; + btVector3FloatData m_linearFactor; + btVector3FloatData m_gravity; + btVector3FloatData m_gravity_acceleration; + btVector3FloatData m_invInertiaLocal; + btVector3FloatData m_totalForce; + btVector3FloatData m_totalTorque; + float m_inverseMass; + float m_linearDamping; + float m_angularDamping; + float m_additionalDampingFactor; + float m_additionalLinearDampingThresholdSqr; + float m_additionalAngularDampingThresholdSqr; + float m_additionalAngularDampingFactor; + float m_linearSleepingThreshold; + float m_angularSleepingThreshold; + int m_additionalDamping; +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btRigidBodyDoubleData +{ + btCollisionObjectDoubleData m_collisionObjectData; + btMatrix3x3DoubleData m_invInertiaTensorWorld; + btVector3DoubleData m_linearVelocity; + btVector3DoubleData m_angularVelocity; + btVector3DoubleData m_angularFactor; + btVector3DoubleData m_linearFactor; + btVector3DoubleData m_gravity; + btVector3DoubleData m_gravity_acceleration; + btVector3DoubleData m_invInertiaLocal; + btVector3DoubleData m_totalForce; + btVector3DoubleData m_totalTorque; + double m_inverseMass; + double m_linearDamping; + double m_angularDamping; + double m_additionalDampingFactor; + double m_additionalLinearDampingThresholdSqr; + double m_additionalAngularDampingThresholdSqr; + double m_additionalAngularDampingFactor; + double m_linearSleepingThreshold; + double m_angularSleepingThreshold; + int m_additionalDamping; + char m_padding[4]; +}; + + + +#endif //BT_RIGIDBODY_H + diff --git a/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp new file mode 100644 index 0000000..5fc2f3c --- /dev/null +++ b/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp @@ -0,0 +1,280 @@ +/* +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 "btSimpleDynamicsWorld.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" + + +/* + Make sure this dummy function never changes so that it + can be used by probes that are checking whether the + library is actually installed. +*/ +extern "C" +{ + void btBulletDynamicsProbe (); + void btBulletDynamicsProbe () {} +} + + + + +btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) +:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration), +m_constraintSolver(constraintSolver), +m_ownsConstraintSolver(false), +m_gravity(0,0,-10) +{ + +} + + +btSimpleDynamicsWorld::~btSimpleDynamicsWorld() +{ + if (m_ownsConstraintSolver) + btAlignedFree( m_constraintSolver); +} + +int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) +{ + (void)fixedTimeStep; + (void)maxSubSteps; + + + ///apply gravity, predict motion + predictUnconstraintMotion(timeStep); + + btDispatcherInfo& dispatchInfo = getDispatchInfo(); + dispatchInfo.m_timeStep = timeStep; + dispatchInfo.m_stepCount = 0; + dispatchInfo.m_debugDraw = getDebugDrawer(); + + ///perform collision detection + performDiscreteCollisionDetection(); + + ///solve contact constraints + int numManifolds = m_dispatcher1->getNumManifolds(); + if (numManifolds) + { + btPersistentManifold** manifoldPtr = ((btCollisionDispatcher*)m_dispatcher1)->getInternalManifoldPointer(); + + btContactSolverInfo infoGlobal; + infoGlobal.m_timeStep = timeStep; + m_constraintSolver->prepareSolve(0,numManifolds); + m_constraintSolver->solveGroup(&getCollisionObjectArray()[0],getNumCollisionObjects(),manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc,m_dispatcher1); + m_constraintSolver->allSolved(infoGlobal,m_debugDrawer, m_stackAlloc); + } + + ///integrate transforms + integrateTransforms(timeStep); + + updateAabbs(); + + synchronizeMotionStates(); + + clearForces(); + + return 1; + +} + +void btSimpleDynamicsWorld::clearForces() +{ + ///@todo: iterate over awake simulation islands! + for ( int i=0;iclearForces(); + } + } +} + + +void btSimpleDynamicsWorld::setGravity(const btVector3& gravity) +{ + m_gravity = gravity; + for ( int i=0;isetGravity(gravity); + } + } +} + +btVector3 btSimpleDynamicsWorld::getGravity () const +{ + return m_gravity; +} + +void btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body) +{ + btCollisionWorld::removeCollisionObject(body); +} + +void btSimpleDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject) +{ + btRigidBody* body = btRigidBody::upcast(collisionObject); + if (body) + removeRigidBody(body); + else + btCollisionWorld::removeCollisionObject(collisionObject); +} + + +void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body) +{ + body->setGravity(m_gravity); + + if (body->getCollisionShape()) + { + addCollisionObject(body); + } +} + +void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body, short group, short mask) +{ + body->setGravity(m_gravity); + + if (body->getCollisionShape()) + { + addCollisionObject(body,group,mask); + } +} + + +void btSimpleDynamicsWorld::debugDrawWorld() +{ + +} + +void btSimpleDynamicsWorld::addAction(btActionInterface* action) +{ + +} + +void btSimpleDynamicsWorld::removeAction(btActionInterface* action) +{ + +} + + +void btSimpleDynamicsWorld::updateAabbs() +{ + btTransform predictedTrans; + for ( int i=0;iisActive() && (!body->isStaticObject())) + { + btVector3 minAabb,maxAabb; + colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); + btBroadphaseInterface* bp = getBroadphase(); + bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); + } + } + } +} + +void btSimpleDynamicsWorld::integrateTransforms(btScalar timeStep) +{ + btTransform predictedTrans; + for ( int i=0;iisActive() && (!body->isStaticObject())) + { + body->predictIntegratedTransform(timeStep, predictedTrans); + body->proceedToTransform( predictedTrans); + } + } + } +} + + + +void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) +{ + for ( int i=0;iisStaticObject()) + { + if (body->isActive()) + { + body->applyGravity(); + body->integrateVelocities( timeStep); + body->applyDamping(timeStep); + body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); + } + } + } + } +} + + +void btSimpleDynamicsWorld::synchronizeMotionStates() +{ + ///@todo: iterate over awake simulation islands! + for ( int i=0;igetMotionState()) + { + if (body->getActivationState() != ISLAND_SLEEPING) + { + body->getMotionState()->setWorldTransform(body->getWorldTransform()); + } + } + } + +} + + +void btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) +{ + if (m_ownsConstraintSolver) + { + btAlignedFree(m_constraintSolver); + } + m_ownsConstraintSolver = false; + m_constraintSolver = solver; +} + +btConstraintSolver* btSimpleDynamicsWorld::getConstraintSolver() +{ + return m_constraintSolver; +} diff --git a/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h new file mode 100644 index 0000000..d48d2e3 --- /dev/null +++ b/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h @@ -0,0 +1,89 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SIMPLE_DYNAMICS_WORLD_H +#define BT_SIMPLE_DYNAMICS_WORLD_H + +#include "btDynamicsWorld.h" + +class btDispatcher; +class btOverlappingPairCache; +class btConstraintSolver; + +///The btSimpleDynamicsWorld serves as unit-test and to verify more complicated and optimized dynamics worlds. +///Please use btDiscreteDynamicsWorld instead +class btSimpleDynamicsWorld : public btDynamicsWorld +{ +protected: + + btConstraintSolver* m_constraintSolver; + + bool m_ownsConstraintSolver; + + void predictUnconstraintMotion(btScalar timeStep); + + void integrateTransforms(btScalar timeStep); + + btVector3 m_gravity; + +public: + + + + ///this btSimpleDynamicsWorld constructor creates dispatcher, broadphase pairCache and constraintSolver + btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); + + virtual ~btSimpleDynamicsWorld(); + + ///maxSubSteps/fixedTimeStep for interpolation is currently ignored for btSimpleDynamicsWorld, use btDiscreteDynamicsWorld instead + virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); + + virtual void setGravity(const btVector3& gravity); + + virtual btVector3 getGravity () const; + + virtual void addRigidBody(btRigidBody* body); + + virtual void addRigidBody(btRigidBody* body, short group, short mask); + + virtual void removeRigidBody(btRigidBody* body); + + virtual void debugDrawWorld(); + + virtual void addAction(btActionInterface* action); + + virtual void removeAction(btActionInterface* action); + + ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject + virtual void removeCollisionObject(btCollisionObject* collisionObject); + + virtual void updateAabbs(); + + virtual void synchronizeMotionStates(); + + virtual void setConstraintSolver(btConstraintSolver* solver); + + virtual btConstraintSolver* getConstraintSolver(); + + virtual btDynamicsWorldType getWorldType() const + { + return BT_SIMPLE_DYNAMICS_WORLD; + } + + virtual void clearForces(); + +}; + +#endif //BT_SIMPLE_DYNAMICS_WORLD_H diff --git a/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp new file mode 100644 index 0000000..5b46788 --- /dev/null +++ b/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp @@ -0,0 +1,771 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. +*/ + +#include "LinearMath/btVector3.h" +#include "btRaycastVehicle.h" + +#include "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h" +#include "BulletDynamics/ConstraintSolver/btJacobianEntry.h" +#include "LinearMath/btQuaternion.h" +#include "BulletDynamics/Dynamics/btDynamicsWorld.h" +#include "btVehicleRaycaster.h" +#include "btWheelInfo.h" +#include "LinearMath/btMinMax.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletDynamics/ConstraintSolver/btContactConstraint.h" + +#define ROLLING_INFLUENCE_FIX + + +btRigidBody& btActionInterface::getFixedBody() +{ + static btRigidBody s_fixed(0, 0,0); + s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); + return s_fixed; +} + +btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster ) +:m_vehicleRaycaster(raycaster), +m_pitchControl(btScalar(0.)) +{ + m_chassisBody = chassis; + m_indexRightAxis = 0; + m_indexUpAxis = 2; + m_indexForwardAxis = 1; + defaultInit(tuning); +} + + +void btRaycastVehicle::defaultInit(const btVehicleTuning& tuning) +{ + (void)tuning; + m_currentVehicleSpeedKmHour = btScalar(0.); + m_steeringValue = btScalar(0.); + +} + + + +btRaycastVehicle::~btRaycastVehicle() +{ +} + + +// +// basically most of the code is general for 2 or 4 wheel vehicles, but some of it needs to be reviewed +// +btWheelInfo& btRaycastVehicle::addWheel( const btVector3& connectionPointCS, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel) +{ + + btWheelInfoConstructionInfo ci; + + ci.m_chassisConnectionCS = connectionPointCS; + ci.m_wheelDirectionCS = wheelDirectionCS0; + ci.m_wheelAxleCS = wheelAxleCS; + ci.m_suspensionRestLength = suspensionRestLength; + ci.m_wheelRadius = wheelRadius; + ci.m_suspensionStiffness = tuning.m_suspensionStiffness; + ci.m_wheelsDampingCompression = tuning.m_suspensionCompression; + ci.m_wheelsDampingRelaxation = tuning.m_suspensionDamping; + ci.m_frictionSlip = tuning.m_frictionSlip; + ci.m_bIsFrontWheel = isFrontWheel; + ci.m_maxSuspensionTravelCm = tuning.m_maxSuspensionTravelCm; + ci.m_maxSuspensionForce = tuning.m_maxSuspensionForce; + + m_wheelInfo.push_back( btWheelInfo(ci)); + + btWheelInfo& wheel = m_wheelInfo[getNumWheels()-1]; + + updateWheelTransformsWS( wheel , false ); + updateWheelTransform(getNumWheels()-1,false); + return wheel; +} + + + + +const btTransform& btRaycastVehicle::getWheelTransformWS( int wheelIndex ) const +{ + btAssert(wheelIndex < getNumWheels()); + const btWheelInfo& wheel = m_wheelInfo[wheelIndex]; + return wheel.m_worldTransform; + +} + +void btRaycastVehicle::updateWheelTransform( int wheelIndex , bool interpolatedTransform) +{ + + btWheelInfo& wheel = m_wheelInfo[ wheelIndex ]; + updateWheelTransformsWS(wheel,interpolatedTransform); + btVector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS; + const btVector3& right = wheel.m_raycastInfo.m_wheelAxleWS; + btVector3 fwd = up.cross(right); + fwd = fwd.normalize(); +// up = right.cross(fwd); +// up.normalize(); + + //rotate around steering over de wheelAxleWS + btScalar steering = wheel.m_steering; + + btQuaternion steeringOrn(up,steering);//wheel.m_steering); + btMatrix3x3 steeringMat(steeringOrn); + + btQuaternion rotatingOrn(right,-wheel.m_rotation); + btMatrix3x3 rotatingMat(rotatingOrn); + + btMatrix3x3 basis2( + right[0],fwd[0],up[0], + right[1],fwd[1],up[1], + right[2],fwd[2],up[2] + ); + + wheel.m_worldTransform.setBasis(steeringMat * rotatingMat * basis2); + wheel.m_worldTransform.setOrigin( + wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength + ); +} + +void btRaycastVehicle::resetSuspension() +{ + + int i; + for (i=0;igetMotionState())) + { + getRigidBody()->getMotionState()->getWorldTransform(chassisTrans); + } + + wheel.m_raycastInfo.m_hardPointWS = chassisTrans( wheel.m_chassisConnectionPointCS ); + wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.getBasis() * wheel.m_wheelDirectionCS ; + wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.getBasis() * wheel.m_wheelAxleCS; +} + +btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel) +{ + updateWheelTransformsWS( wheel,false); + + + btScalar depth = -1; + + btScalar raylen = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius; + + btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen); + const btVector3& source = wheel.m_raycastInfo.m_hardPointWS; + wheel.m_raycastInfo.m_contactPointWS = source + rayvector; + const btVector3& target = wheel.m_raycastInfo.m_contactPointWS; + + btScalar param = btScalar(0.); + + btVehicleRaycaster::btVehicleRaycasterResult rayResults; + + btAssert(m_vehicleRaycaster); + + void* object = m_vehicleRaycaster->castRay(source,target,rayResults); + + wheel.m_raycastInfo.m_groundObject = 0; + + if (object) + { + param = rayResults.m_distFraction; + depth = raylen * rayResults.m_distFraction; + wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld; + wheel.m_raycastInfo.m_isInContact = true; + + wheel.m_raycastInfo.m_groundObject = &getFixedBody();///@todo for driving on dynamic/movable objects!; + //wheel.m_raycastInfo.m_groundObject = object; + + + btScalar hitDistance = param*raylen; + wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius; + //clamp on max suspension travel + + btScalar minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravelCm*btScalar(0.01); + btScalar maxSuspensionLength = wheel.getSuspensionRestLength()+ wheel.m_maxSuspensionTravelCm*btScalar(0.01); + if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength) + { + wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength; + } + if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength) + { + wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength; + } + + wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld; + + btScalar denominator= wheel.m_raycastInfo.m_contactNormalWS.dot( wheel.m_raycastInfo.m_wheelDirectionWS ); + + btVector3 chassis_velocity_at_contactPoint; + btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition(); + + chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos); + + btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint ); + + if ( denominator >= btScalar(-0.1)) + { + wheel.m_suspensionRelativeVelocity = btScalar(0.0); + wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1); + } + else + { + btScalar inv = btScalar(-1.) / denominator; + wheel.m_suspensionRelativeVelocity = projVel * inv; + wheel.m_clippedInvContactDotSuspension = inv; + } + + } else + { + //put wheel info as in rest position + wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength(); + wheel.m_suspensionRelativeVelocity = btScalar(0.0); + wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS; + wheel.m_clippedInvContactDotSuspension = btScalar(1.0); + } + + return depth; +} + + +const btTransform& btRaycastVehicle::getChassisWorldTransform() const +{ + /*if (getRigidBody()->getMotionState()) + { + btTransform chassisWorldTrans; + getRigidBody()->getMotionState()->getWorldTransform(chassisWorldTrans); + return chassisWorldTrans; + } + */ + + + return getRigidBody()->getCenterOfMassTransform(); +} + + +void btRaycastVehicle::updateVehicle( btScalar step ) +{ + { + for (int i=0;igetLinearVelocity().length(); + + const btTransform& chassisTrans = getChassisWorldTransform(); + + btVector3 forwardW ( + chassisTrans.getBasis()[0][m_indexForwardAxis], + chassisTrans.getBasis()[1][m_indexForwardAxis], + chassisTrans.getBasis()[2][m_indexForwardAxis]); + + if (forwardW.dot(getRigidBody()->getLinearVelocity()) < btScalar(0.)) + { + m_currentVehicleSpeedKmHour *= btScalar(-1.); + } + + // + // simulate suspension + // + + int i=0; + for (i=0;i wheel.m_maxSuspensionForce) + { + suspensionForce = wheel.m_maxSuspensionForce; + } + btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step; + btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition(); + + getRigidBody()->applyImpulse(impulse, relpos); + + } + + + + updateFriction( step); + + + for (i=0;igetCenterOfMassPosition(); + btVector3 vel = getRigidBody()->getVelocityInLocalPoint( relpos ); + + if (wheel.m_raycastInfo.m_isInContact) + { + const btTransform& chassisWorldTransform = getChassisWorldTransform(); + + btVector3 fwd ( + chassisWorldTransform.getBasis()[0][m_indexForwardAxis], + chassisWorldTransform.getBasis()[1][m_indexForwardAxis], + chassisWorldTransform.getBasis()[2][m_indexForwardAxis]); + + btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS); + fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj; + + btScalar proj2 = fwd.dot(vel); + + wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius); + wheel.m_rotation += wheel.m_deltaRotation; + + } else + { + wheel.m_rotation += wheel.m_deltaRotation; + } + + wheel.m_deltaRotation *= btScalar(0.99);//damping of rotation when not in contact + + } + + + +} + + +void btRaycastVehicle::setSteeringValue(btScalar steering,int wheel) +{ + btAssert(wheel>=0 && wheel < getNumWheels()); + + btWheelInfo& wheelInfo = getWheelInfo(wheel); + wheelInfo.m_steering = steering; +} + + + +btScalar btRaycastVehicle::getSteeringValue(int wheel) const +{ + return getWheelInfo(wheel).m_steering; +} + + +void btRaycastVehicle::applyEngineForce(btScalar force, int wheel) +{ + btAssert(wheel>=0 && wheel < getNumWheels()); + btWheelInfo& wheelInfo = getWheelInfo(wheel); + wheelInfo.m_engineForce = force; +} + + +const btWheelInfo& btRaycastVehicle::getWheelInfo(int index) const +{ + btAssert((index >= 0) && (index < getNumWheels())); + + return m_wheelInfo[index]; +} + +btWheelInfo& btRaycastVehicle::getWheelInfo(int index) +{ + btAssert((index >= 0) && (index < getNumWheels())); + + return m_wheelInfo[index]; +} + +void btRaycastVehicle::setBrake(btScalar brake,int wheelIndex) +{ + btAssert((wheelIndex >= 0) && (wheelIndex < getNumWheels())); + getWheelInfo(wheelIndex).m_brake = brake; +} + + +void btRaycastVehicle::updateSuspension(btScalar deltaTime) +{ + (void)deltaTime; + + btScalar chassisMass = btScalar(1.) / m_chassisBody->getInvMass(); + + for (int w_it=0; w_itcomputeImpulseDenominator(frictionPosWorld,frictionDirectionWorld); + btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld); + btScalar relaxation = 1.f; + m_jacDiagABInv = relaxation/(denom0+denom1); + } + + + +}; + +btScalar calcRollingFriction(btWheelContactPoint& contactPoint); +btScalar calcRollingFriction(btWheelContactPoint& contactPoint) +{ + + btScalar j1=0.f; + + const btVector3& contactPosWorld = contactPoint.m_frictionPositionWorld; + + btVector3 rel_pos1 = contactPosWorld - contactPoint.m_body0->getCenterOfMassPosition(); + btVector3 rel_pos2 = contactPosWorld - contactPoint.m_body1->getCenterOfMassPosition(); + + btScalar maxImpulse = contactPoint.m_maxImpulse; + + btVector3 vel1 = contactPoint.m_body0->getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = contactPoint.m_body1->getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + btScalar vrel = contactPoint.m_frictionDirectionWorld.dot(vel); + + // calculate j that moves us to zero relative velocity + j1 = -vrel * contactPoint.m_jacDiagABInv; + btSetMin(j1, maxImpulse); + btSetMax(j1, -maxImpulse); + + return j1; +} + + + + +btScalar sideFrictionStiffness2 = btScalar(1.0); +void btRaycastVehicle::updateFriction(btScalar timeStep) +{ + + //calculate the impulse, so that the wheels don't move sidewards + int numWheel = getNumWheels(); + if (!numWheel) + return; + + m_forwardWS.resize(numWheel); + m_axle.resize(numWheel); + m_forwardImpulse.resize(numWheel); + m_sideImpulse.resize(numWheel); + + int numWheelsOnGround = 0; + + + //collapse all those loops into one! + for (int i=0;i maximpSquared) + { + sliding = true; + + btScalar factor = maximp / btSqrt(impulseSquared); + + m_wheelInfo[wheel].m_skidInfo *= factor; + } + } + + } + } + + + + + if (sliding) + { + for (int wheel = 0;wheel < getNumWheels(); wheel++) + { + if (m_sideImpulse[wheel] != btScalar(0.)) + { + if (m_wheelInfo[wheel].m_skidInfo< btScalar(1.)) + { + m_forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; + m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; + } + } + } + } + + // apply the impulses + { + for (int wheel = 0;wheelgetCenterOfMassPosition(); + + if (m_forwardImpulse[wheel] != btScalar(0.)) + { + m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]),rel_pos); + } + if (m_sideImpulse[wheel] != btScalar(0.)) + { + class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject; + + btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS - + groundObject->getCenterOfMassPosition(); + + + btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel]; + +#if defined ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT. + btVector3 vChassisWorldUp = getRigidBody()->getCenterOfMassTransform().getBasis().getColumn(m_indexUpAxis); + rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) * (1.f-wheelInfo.m_rollInfluence)); +#else + rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence; +#endif + m_chassisBody->applyImpulse(sideImp,rel_pos); + + //apply friction impulse on the ground + groundObject->applyImpulse(-sideImp,rel_pos2); + } + } + } + + +} + + + +void btRaycastVehicle::debugDraw(btIDebugDraw* debugDrawer) +{ + + for (int v=0;vgetNumWheels();v++) + { + btVector3 wheelColor(0,1,1); + if (getWheelInfo(v).m_raycastInfo.m_isInContact) + { + wheelColor.setValue(0,0,1); + } else + { + wheelColor.setValue(1,0,1); + } + + btVector3 wheelPosWS = getWheelInfo(v).m_worldTransform.getOrigin(); + + btVector3 axle = btVector3( + getWheelInfo(v).m_worldTransform.getBasis()[0][getRightAxis()], + getWheelInfo(v).m_worldTransform.getBasis()[1][getRightAxis()], + getWheelInfo(v).m_worldTransform.getBasis()[2][getRightAxis()]); + + //debug wheels (cylinders) + debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor); + debugDrawer->drawLine(wheelPosWS,getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor); + + } +} + + +void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result) +{ +// RayResultCallback& resultCallback; + + btCollisionWorld::ClosestRayResultCallback rayCallback(from,to); + + m_dynamicsWorld->rayTest(from, to, rayCallback); + + if (rayCallback.hasHit()) + { + + btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject); + if (body && body->hasContactResponse()) + { + result.m_hitPointInWorld = rayCallback.m_hitPointWorld; + result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld; + result.m_hitNormalInWorld.normalize(); + result.m_distFraction = rayCallback.m_closestHitFraction; + return body; + } + } + return 0; +} + diff --git a/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/src/BulletDynamics/Vehicle/btRaycastVehicle.h new file mode 100644 index 0000000..f59555f --- /dev/null +++ b/src/BulletDynamics/Vehicle/btRaycastVehicle.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. +*/ +#ifndef BT_RAYCASTVEHICLE_H +#define BT_RAYCASTVEHICLE_H + +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "btVehicleRaycaster.h" +class btDynamicsWorld; +#include "LinearMath/btAlignedObjectArray.h" +#include "btWheelInfo.h" +#include "BulletDynamics/Dynamics/btActionInterface.h" + +class btVehicleTuning; + +///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle. +class btRaycastVehicle : public btActionInterface +{ + + btAlignedObjectArray m_forwardWS; + btAlignedObjectArray m_axle; + btAlignedObjectArray m_forwardImpulse; + btAlignedObjectArray m_sideImpulse; + + ///backwards compatibility + int m_userConstraintType; + int m_userConstraintId; + +public: + class btVehicleTuning + { + public: + + btVehicleTuning() + :m_suspensionStiffness(btScalar(5.88)), + m_suspensionCompression(btScalar(0.83)), + m_suspensionDamping(btScalar(0.88)), + m_maxSuspensionTravelCm(btScalar(500.)), + m_frictionSlip(btScalar(10.5)), + m_maxSuspensionForce(btScalar(6000.)) + { + } + btScalar m_suspensionStiffness; + btScalar m_suspensionCompression; + btScalar m_suspensionDamping; + btScalar m_maxSuspensionTravelCm; + btScalar m_frictionSlip; + btScalar m_maxSuspensionForce; + + }; +private: + + btScalar m_tau; + btScalar m_damping; + btVehicleRaycaster* m_vehicleRaycaster; + btScalar m_pitchControl; + btScalar m_steeringValue; + btScalar m_currentVehicleSpeedKmHour; + + btRigidBody* m_chassisBody; + + int m_indexRightAxis; + int m_indexUpAxis; + int m_indexForwardAxis; + + void defaultInit(const btVehicleTuning& tuning); + +public: + + //constructor to create a car from an existing rigidbody + btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster ); + + virtual ~btRaycastVehicle() ; + + + ///btActionInterface interface + virtual void updateAction( btCollisionWorld* collisionWorld, btScalar step) + { + (void) collisionWorld; + updateVehicle(step); + } + + + ///btActionInterface interface + void debugDraw(btIDebugDraw* debugDrawer); + + const btTransform& getChassisWorldTransform() const; + + btScalar rayCast(btWheelInfo& wheel); + + virtual void updateVehicle(btScalar step); + + + void resetSuspension(); + + btScalar getSteeringValue(int wheel) const; + + void setSteeringValue(btScalar steering,int wheel); + + + void applyEngineForce(btScalar force, int wheel); + + const btTransform& getWheelTransformWS( int wheelIndex ) const; + + void updateWheelTransform( int wheelIndex, bool interpolatedTransform = true ); + +// void setRaycastWheelInfo( int wheelIndex , bool isInContact, const btVector3& hitPoint, const btVector3& hitNormal,btScalar depth); + + btWheelInfo& addWheel( const btVector3& connectionPointCS0, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS,btScalar suspensionRestLength,btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel); + + inline int getNumWheels() const { + return int (m_wheelInfo.size()); + } + + btAlignedObjectArray m_wheelInfo; + + + const btWheelInfo& getWheelInfo(int index) const; + + btWheelInfo& getWheelInfo(int index); + + void updateWheelTransformsWS(btWheelInfo& wheel , bool interpolatedTransform = true); + + + void setBrake(btScalar brake,int wheelIndex); + + void setPitchControl(btScalar pitch) + { + m_pitchControl = pitch; + } + + void updateSuspension(btScalar deltaTime); + + virtual void updateFriction(btScalar timeStep); + + + + inline btRigidBody* getRigidBody() + { + return m_chassisBody; + } + + const btRigidBody* getRigidBody() const + { + return m_chassisBody; + } + + inline int getRightAxis() const + { + return m_indexRightAxis; + } + inline int getUpAxis() const + { + return m_indexUpAxis; + } + + inline int getForwardAxis() const + { + return m_indexForwardAxis; + } + + + ///Worldspace forward vector + btVector3 getForwardVector() const + { + const btTransform& chassisTrans = getChassisWorldTransform(); + + btVector3 forwardW ( + chassisTrans.getBasis()[0][m_indexForwardAxis], + chassisTrans.getBasis()[1][m_indexForwardAxis], + chassisTrans.getBasis()[2][m_indexForwardAxis]); + + return forwardW; + } + + ///Velocity of vehicle (positive if velocity vector has same direction as foward vector) + btScalar getCurrentSpeedKmHour() const + { + return m_currentVehicleSpeedKmHour; + } + + virtual void setCoordinateSystem(int rightIndex,int upIndex,int forwardIndex) + { + m_indexRightAxis = rightIndex; + m_indexUpAxis = upIndex; + m_indexForwardAxis = forwardIndex; + } + + + ///backwards compatibility + int getUserConstraintType() const + { + return m_userConstraintType ; + } + + void setUserConstraintType(int userConstraintType) + { + m_userConstraintType = userConstraintType; + }; + + void setUserConstraintId(int uid) + { + m_userConstraintId = uid; + } + + int getUserConstraintId() const + { + return m_userConstraintId; + } + +}; + +class btDefaultVehicleRaycaster : public btVehicleRaycaster +{ + btDynamicsWorld* m_dynamicsWorld; +public: + btDefaultVehicleRaycaster(btDynamicsWorld* world) + :m_dynamicsWorld(world) + { + } + + virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result); + +}; + + +#endif //BT_RAYCASTVEHICLE_H + diff --git a/src/BulletDynamics/Vehicle/btVehicleRaycaster.h b/src/BulletDynamics/Vehicle/btVehicleRaycaster.h new file mode 100644 index 0000000..3cc909c --- /dev/null +++ b/src/BulletDynamics/Vehicle/btVehicleRaycaster.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://bulletphysics.org + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. +*/ +#ifndef BT_VEHICLE_RAYCASTER_H +#define BT_VEHICLE_RAYCASTER_H + +#include "LinearMath/btVector3.h" + +/// btVehicleRaycaster is provides interface for between vehicle simulation and raycasting +struct btVehicleRaycaster +{ +virtual ~btVehicleRaycaster() +{ +} + struct btVehicleRaycasterResult + { + btVehicleRaycasterResult() :m_distFraction(btScalar(-1.)){}; + btVector3 m_hitPointInWorld; + btVector3 m_hitNormalInWorld; + btScalar m_distFraction; + }; + + virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result) = 0; + +}; + +#endif //BT_VEHICLE_RAYCASTER_H + diff --git a/src/BulletDynamics/Vehicle/btWheelInfo.cpp b/src/BulletDynamics/Vehicle/btWheelInfo.cpp new file mode 100644 index 0000000..ef93c16 --- /dev/null +++ b/src/BulletDynamics/Vehicle/btWheelInfo.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. +*/ +#include "btWheelInfo.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" // for pointvelocity + + +btScalar btWheelInfo::getSuspensionRestLength() const +{ + + return m_suspensionRestLength1; + +} + +void btWheelInfo::updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo) +{ + (void)raycastInfo; + + + if (m_raycastInfo.m_isInContact) + + { + btScalar project= m_raycastInfo.m_contactNormalWS.dot( m_raycastInfo.m_wheelDirectionWS ); + btVector3 chassis_velocity_at_contactPoint; + btVector3 relpos = m_raycastInfo.m_contactPointWS - chassis.getCenterOfMassPosition(); + chassis_velocity_at_contactPoint = chassis.getVelocityInLocalPoint( relpos ); + btScalar projVel = m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint ); + if ( project >= btScalar(-0.1)) + { + m_suspensionRelativeVelocity = btScalar(0.0); + m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1); + } + else + { + btScalar inv = btScalar(-1.) / project; + m_suspensionRelativeVelocity = projVel * inv; + m_clippedInvContactDotSuspension = inv; + } + + } + + else // Not in contact : position wheel in a nice (rest length) position + { + m_raycastInfo.m_suspensionLength = this->getSuspensionRestLength(); + m_suspensionRelativeVelocity = btScalar(0.0); + m_raycastInfo.m_contactNormalWS = -m_raycastInfo.m_wheelDirectionWS; + m_clippedInvContactDotSuspension = btScalar(1.0); + } +} diff --git a/src/BulletDynamics/Vehicle/btWheelInfo.h b/src/BulletDynamics/Vehicle/btWheelInfo.h new file mode 100644 index 0000000..f916053 --- /dev/null +++ b/src/BulletDynamics/Vehicle/btWheelInfo.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. +*/ +#ifndef BT_WHEEL_INFO_H +#define BT_WHEEL_INFO_H + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" + +class btRigidBody; + +struct btWheelInfoConstructionInfo +{ + btVector3 m_chassisConnectionCS; + btVector3 m_wheelDirectionCS; + btVector3 m_wheelAxleCS; + btScalar m_suspensionRestLength; + btScalar m_maxSuspensionTravelCm; + btScalar m_wheelRadius; + + btScalar m_suspensionStiffness; + btScalar m_wheelsDampingCompression; + btScalar m_wheelsDampingRelaxation; + btScalar m_frictionSlip; + btScalar m_maxSuspensionForce; + bool m_bIsFrontWheel; + +}; + +/// btWheelInfo contains information per wheel about friction and suspension. +struct btWheelInfo +{ + struct RaycastInfo + { + //set by raycaster + btVector3 m_contactNormalWS;//contactnormal + btVector3 m_contactPointWS;//raycast hitpoint + btScalar m_suspensionLength; + btVector3 m_hardPointWS;//raycast starting point + btVector3 m_wheelDirectionWS; //direction in worldspace + btVector3 m_wheelAxleWS; // axle in worldspace + bool m_isInContact; + void* m_groundObject; //could be general void* ptr + }; + + RaycastInfo m_raycastInfo; + + btTransform m_worldTransform; + + btVector3 m_chassisConnectionPointCS; //const + btVector3 m_wheelDirectionCS;//const + btVector3 m_wheelAxleCS; // const or modified by steering + btScalar m_suspensionRestLength1;//const + btScalar m_maxSuspensionTravelCm; + btScalar getSuspensionRestLength() const; + btScalar m_wheelsRadius;//const + btScalar m_suspensionStiffness;//const + btScalar m_wheelsDampingCompression;//const + btScalar m_wheelsDampingRelaxation;//const + btScalar m_frictionSlip; + btScalar m_steering; + btScalar m_rotation; + btScalar m_deltaRotation; + btScalar m_rollInfluence; + btScalar m_maxSuspensionForce; + + btScalar m_engineForce; + + btScalar m_brake; + + bool m_bIsFrontWheel; + + void* m_clientInfo;//can be used to store pointer to sync transforms... + + btWheelInfo(btWheelInfoConstructionInfo& ci) + + { + + m_suspensionRestLength1 = ci.m_suspensionRestLength; + m_maxSuspensionTravelCm = ci.m_maxSuspensionTravelCm; + + m_wheelsRadius = ci.m_wheelRadius; + m_suspensionStiffness = ci.m_suspensionStiffness; + m_wheelsDampingCompression = ci.m_wheelsDampingCompression; + m_wheelsDampingRelaxation = ci.m_wheelsDampingRelaxation; + m_chassisConnectionPointCS = ci.m_chassisConnectionCS; + m_wheelDirectionCS = ci.m_wheelDirectionCS; + m_wheelAxleCS = ci.m_wheelAxleCS; + m_frictionSlip = ci.m_frictionSlip; + m_steering = btScalar(0.); + m_engineForce = btScalar(0.); + m_rotation = btScalar(0.); + m_deltaRotation = btScalar(0.); + m_brake = btScalar(0.); + m_rollInfluence = btScalar(0.1); + m_bIsFrontWheel = ci.m_bIsFrontWheel; + m_maxSuspensionForce = ci.m_maxSuspensionForce; + + } + + void updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo); + + btScalar m_clippedInvContactDotSuspension; + btScalar m_suspensionRelativeVelocity; + //calculated by suspension + btScalar m_wheelsSuspensionForce; + btScalar m_skidInfo; + +}; + +#endif //BT_WHEEL_INFO_H + diff --git a/src/BulletDynamics/ibmsdk/Makefile b/src/BulletDynamics/ibmsdk/Makefile new file mode 100644 index 0000000..57505d8 --- /dev/null +++ b/src/BulletDynamics/ibmsdk/Makefile @@ -0,0 +1,53 @@ +#### Source code Dirs +VPATH = \ +../ConstraintSolver \ +../Dynamics \ +../Vehicle + +ROOT = ../../.. + +#### Library +LIBRARY_ppu = bulletdynamics.a + +#### Compiler flags +CPPFLAGS = \ +-DUSE_LIBSPE2 \ +-I../ConstraintSolver \ +-I../Dynamics \ +-I../Vehicle \ +-I$(ROOT)/src \ +-I$(SDKINC) + +#### Optimization level flags +#CC_OPT_LEVEL = $(CC_OPT_LEVEL_DEBUG) +CC_OPT_LEVEL = -O3 + +##### Objects to be archived in lib + +OBJS = \ +btContactConstraint.o \ +btGeneric6DofConstraint.o \ +btHingeConstraint.o \ +btPoint2PointConstraint.o \ +btSequentialImpulseConstraintSolver.o \ +btSolve2LinearConstraint.o \ +btTypedConstraint.o \ +btDiscreteDynamicsWorld.o \ +btRigidBody.o \ +btSimpleDynamicsWorld.o \ +btRaycastVehicle.o \ +btWheelInfo.o +#### Install directories +INSTALL_DIR = $(ROOT)/lib/ibmsdk +INSTALL_FILES = $(LIBRARY_ppu) + +IBM_CELLSDK_VERSION := $(shell if [ -d /opt/cell ]; then echo "3.0"; fi) + +ifeq ("$(IBM_CELLSDK_VERSION)","3.0") + CELL_TOP ?= /opt/cell/sdk + include $(CELL_TOP)/buildutils/make.footer +else + CELL_TOP ?= /opt/ibm/cell-sdk/prototype + include $(CELL_TOP)/make.footer +endif + diff --git a/src/BulletDynamics/premake4.lua b/src/BulletDynamics/premake4.lua new file mode 100644 index 0000000..9af6d3a --- /dev/null +++ b/src/BulletDynamics/premake4.lua @@ -0,0 +1,11 @@ + project "BulletDynamics" + + kind "StaticLib" + targetdir "../../lib" + includedirs { + "..", + } + files { + "**.cpp", + "**.h" + } \ No newline at end of file diff --git a/src/BulletMultiThreaded/CMakeLists.txt b/src/BulletMultiThreaded/CMakeLists.txt new file mode 100644 index 0000000..6eeeb6d --- /dev/null +++ b/src/BulletMultiThreaded/CMakeLists.txt @@ -0,0 +1,123 @@ +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${VECTOR_MATH_INCLUDE} +) + +SET(BulletMultiThreaded_SRCS + SpuFakeDma.cpp + SpuLibspe2Support.cpp + btThreadSupportInterface.cpp + Win32ThreadSupport.cpp + PosixThreadSupport.cpp + SequentialThreadSupport.cpp + SpuSampleTaskProcess.cpp + SpuCollisionObjectWrapper.cpp + SpuCollisionTaskProcess.cpp + SpuGatheringCollisionDispatcher.cpp + SpuContactManifoldCollisionAlgorithm.cpp + btParallelConstraintSolver.cpp + + #SPURS_PEGatherScatterTask/SpuPEGatherScatterTask.cpp + #SpuPEGatherScatterTaskProcess.cpp + + SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp + SpuNarrowPhaseCollisionTask/SpuContactResult.cpp + SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp + SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp + SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp + + #Some GPU related stuff, mainly CUDA and perhaps OpenCL + btGpu3DGridBroadphase.cpp +) + +SET(Root_HDRS + PlatformDefinitions.h + PpuAddressSpace.h + SpuFakeDma.h + SpuDoubleBuffer.h + SpuLibspe2Support.h + btThreadSupportInterface.h + Win32ThreadSupport.h + PosixThreadSupport.h + SequentialThreadSupport.h + SpuSampleTaskProcess.h + SpuCollisionObjectWrapper.cpp + SpuCollisionObjectWrapper.h + SpuCollisionTaskProcess.h + SpuGatheringCollisionDispatcher.h + SpuContactManifoldCollisionAlgorithm.h + btParallelConstraintSolver.h + + #SPURS_PEGatherScatterTask/SpuPEGatherScatterTask.h + #SpuPEGatherScatterTaskProcess.h + + #Some GPU related stuff, mainly CUDA and perhaps OpenCL + btGpu3DGridBroadphase.h + btGpu3DGridBroadphaseSharedCode.h + btGpu3DGridBroadphaseSharedDefs.h + btGpu3DGridBroadphaseSharedTypes.h + btGpuDefines.h + btGpuUtilsSharedCode.h + btGpuUtilsSharedDefs.h +) + +SET(SpuNarrowPhaseCollisionTask_HDRS + SpuNarrowPhaseCollisionTask/Box.h + SpuNarrowPhaseCollisionTask/boxBoxDistance.h + SpuNarrowPhaseCollisionTask/SpuContactResult.h + SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h + SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h + SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h + SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h + SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h +) + +SET(BulletMultiThreaded_HDRS + ${Root_HDRS} + ${SpuNarrowPhaseCollisionTask_HDRS} +) + +ADD_LIBRARY(BulletMultiThreaded ${BulletMultiThreaded_SRCS} ${BulletMultiThreaded_HDRS}) +SET_TARGET_PROPERTIES(BulletMultiThreaded PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletMultiThreaded PROPERTIES SOVERSION ${BULLET_VERSION}) + + +SUBDIRS(GpuSoftBodySolvers) + + +IF (BUILD_SHARED_LIBS) + IF (UNIX) + TARGET_LINK_LIBRARIES(BulletMultiThreaded BulletDynamics BulletCollision pthread) + ELSE() + TARGET_LINK_LIBRARIES(BulletMultiThreaded BulletDynamics BulletCollision) + ENDIF() +ENDIF (BUILD_SHARED_LIBS) + + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + #INSTALL of other files requires CMake 2.6 + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) +# IF(INSTALL_EXTRA_LIBS) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletMultiThreaded DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletMultiThreaded DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY +${CMAKE_CURRENT_SOURCE_DIR} DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING +PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) +# ENDIF (INSTALL_EXTRA_LIBS) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletMultiThreaded PROPERTIES FRAMEWORK true) + + SET_TARGET_PROPERTIES(BulletMultiThreaded PROPERTIES PUBLIC_HEADER "${Root_HDRS}") + # Have to list out sub-directories manually: + SET_PROPERTY(SOURCE ${SpuNarrowPhaseCollisionTask_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/SpuNarrowPhaseCollisionTask) + + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) + diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt b/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt new file mode 100644 index 0000000..d895176 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt @@ -0,0 +1,13 @@ + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +) + + +SUBDIRS ( + OpenCL +) + +IF( USE_DX11 ) + SUBDIRS( DX11 ) +ENDIF( USE_DX11 ) diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt new file mode 100644 index 0000000..e488771 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt @@ -0,0 +1,83 @@ + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +) + +SET(DXSDK_DIR $ENV{DXSDK_DIR}) +SET(DX11_INCLUDE_PATH "${DIRECTX_SDK_BASE_DIR}/Include" CACHE DOCSTRING "Microsoft directX SDK include path") + + +INCLUDE_DIRECTORIES( +${DX11_INCLUDE_PATH} "../Shared/" +${VECTOR_MATH_INCLUDE} +) + +SET(BulletSoftBodyDX11Solvers_SRCS + btSoftBodySolver_DX11.cpp + btSoftBodySolver_DX11SIMDAware.cpp +) + +SET(BulletSoftBodyDX11Solvers_HDRS + btSoftBodySolver_DX11.h + btSoftBodySolver_DX11SIMDAware.h + ../Shared/btSoftBodySolverData.h + btSoftBodySolverVertexData_DX11.h + btSoftBodySolverTriangleData_DX11.h + btSoftBodySolverLinkData_DX11.h + btSoftBodySolverLinkData_DX11SIMDAware.h + btSoftBodySolverBuffer_DX11.h + btSoftBodySolverVertexBuffer_DX11.h + +) + +# OpenCL and HLSL Shaders. +# Build rules generated to stringify these into headers +# which are needed by some of the sources +SET(BulletSoftBodyDX11Solvers_Shaders + OutputToVertexArray + UpdateNormals + Integrate + UpdatePositions + UpdateNodes + ComputeBounds + SolvePositions + SolvePositionsSIMDBatched + SolveCollisionsAndUpdateVelocities + SolveCollisionsAndUpdateVelocitiesSIMDBatched + UpdatePositionsFromVelocities + ApplyForces + PrepareLinks + VSolveLinks +) + +foreach(f ${BulletSoftBodyDX11Solvers_Shaders}) + LIST(APPEND BulletSoftBodyDX11Solvers_HLSL "HLSL/${f}.hlsl") +endforeach(f) + + + +ADD_LIBRARY(BulletSoftBodySolvers_DX11 ${BulletSoftBodyDX11Solvers_SRCS} ${BulletSoftBodyDX11Solvers_HDRS} ${BulletSoftBodyDX11Solvers_HLSL}) +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_DX11 BulletSoftBody BulletDynamics) +ENDIF (BUILD_SHARED_LIBS) + + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_DX11 DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_DX11 DESTINATION lib${LIB_SUFFIX}) +#headers are already installed by BulletMultiThreaded library + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES PUBLIC_HEADER "${BulletSoftBodyDX11Solvers_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl new file mode 100644 index 0000000..9f9ac07 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl @@ -0,0 +1,95 @@ +MSTRINGIFY( + +cbuffer ApplyForcesCB : register( b0 ) +{ + unsigned int numNodes; + float solverdt; + float epsilon; + int padding3; +}; + + +StructuredBuffer g_vertexClothIdentifier : register( t0 ); +StructuredBuffer g_vertexNormal : register( t1 ); +StructuredBuffer g_vertexArea : register( t2 ); +StructuredBuffer g_vertexInverseMass : register( t3 ); +// TODO: These could be combined into a lift/drag factor array along with medium density +StructuredBuffer g_clothLiftFactor : register( t4 ); +StructuredBuffer g_clothDragFactor : register( t5 ); +StructuredBuffer g_clothWindVelocity : register( t6 ); +StructuredBuffer g_clothAcceleration : register( t7 ); +StructuredBuffer g_clothMediumDensity : register( t8 ); + +RWStructuredBuffer g_vertexForceAccumulator : register( u0 ); +RWStructuredBuffer g_vertexVelocity : register( u1 ); + +float3 projectOnAxis( float3 v, float3 a ) +{ + return (a*dot(v, a)); +} + +[numthreads(128, 1, 1)] +void +ApplyForcesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + unsigned int nodeID = DTid.x; + if( nodeID < numNodes ) + { + int clothId = g_vertexClothIdentifier[nodeID]; + float nodeIM = g_vertexInverseMass[nodeID]; + + if( nodeIM > 0.0f ) + { + float3 nodeV = g_vertexVelocity[nodeID].xyz; + float3 normal = g_vertexNormal[nodeID].xyz; + float area = g_vertexArea[nodeID]; + float3 nodeF = g_vertexForceAccumulator[nodeID].xyz; + + // Read per-cloth values + float3 clothAcceleration = g_clothAcceleration[clothId].xyz; + float3 clothWindVelocity = g_clothWindVelocity[clothId].xyz; + float liftFactor = g_clothLiftFactor[clothId]; + float dragFactor = g_clothDragFactor[clothId]; + float mediumDensity = g_clothMediumDensity[clothId]; + + // Apply the acceleration to the cloth rather than do this via a force + nodeV += (clothAcceleration*solverdt); + + g_vertexVelocity[nodeID] = float4(nodeV, 0.f); + + float3 relativeWindVelocity = nodeV - clothWindVelocity; + float relativeSpeedSquared = dot(relativeWindVelocity, relativeWindVelocity); + + if( relativeSpeedSquared > epsilon ) + { + // Correct direction of normal relative to wind direction and get dot product + normal = normal * (dot(normal, relativeWindVelocity) < 0 ? -1.f : 1.f); + float dvNormal = dot(normal, relativeWindVelocity); + if( dvNormal > 0 ) + { + float3 force = float3(0.f, 0.f, 0.f); + float c0 = area * dvNormal * relativeSpeedSquared / 2.f; + float c1 = c0 * mediumDensity; + force += normal * (-c1 * liftFactor); + force += normalize(relativeWindVelocity)*(-c1 * dragFactor); + + float dtim = solverdt * nodeIM; + float3 forceDTIM = force * dtim; + + float3 nodeFPlusForce = nodeF + force; + + // m_nodesf[i] -= ProjectOnAxis(m_nodesv[i], force.normalized())/dtim; + float3 nodeFMinus = nodeF - (projectOnAxis(nodeV, normalize(force))/dtim); + + nodeF = nodeFPlusForce; + if( dot(forceDTIM, forceDTIM) > dot(nodeV, nodeV) ) + nodeF = nodeFMinus; + + g_vertexForceAccumulator[nodeID] = float4(nodeF, 0.0f); + } + } + } + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl new file mode 100644 index 0000000..e21f959 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl @@ -0,0 +1,83 @@ +MSTRINGIFY( + +cbuffer ComputeBoundsCB : register( b0 ) +{ + int numNodes; + int numSoftBodies; + int padding1; + int padding2; +}; + +// Node indices for each link +StructuredBuffer g_vertexClothIdentifier : register( t0 ); +StructuredBuffer g_vertexPositions : register( t1 ); + +RWStructuredBuffer g_clothMinBounds : register( u0 ); +RWStructuredBuffer g_clothMaxBounds : register( u1 ); + +groupshared uint4 clothMinBounds[256]; +groupshared uint4 clothMaxBounds[256]; + +[numthreads(128, 1, 1)] +void +ComputeBoundsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + const unsigned int UINT_MAX = 0xffffffff; + + // Init min and max bounds arrays + if( GTid.x < numSoftBodies ) + { + clothMinBounds[GTid.x] = uint4(UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX); + clothMaxBounds[GTid.x] = uint4(0,0,0,0); + } + + AllMemoryBarrierWithGroupSync(); + + int nodeID = DTid.x; + if( nodeID < numNodes ) + { + int clothIdentifier = g_vertexClothIdentifier[nodeID]; + if( clothIdentifier >= 0 ) + { + float3 position = g_vertexPositions[nodeID].xyz; + + // Reinterpret position as uint + uint3 positionUInt = uint3(asuint(position.x), asuint(position.y), asuint(position.z)); + + // Invert sign bit of positives and whole of negatives to allow comparison as unsigned ints + //positionUInt.x ^= uint((-int(positionUInt.x >> 31) | 0x80000000)); + //positionUInt.y ^= uint((-int(positionUInt.y >> 31) | 0x80000000)); + //positionUInt.z ^= uint((-int(positionUInt.z >> 31) | 0x80000000)); + positionUInt.x ^= (1+~(positionUInt.x >> 31) | 0x80000000); + positionUInt.y ^= (1+~(positionUInt.y >> 31) | 0x80000000); + positionUInt.z ^= (1+~(positionUInt.z >> 31) | 0x80000000); + + // Min/max with the LDS values + InterlockedMin(clothMinBounds[clothIdentifier].x, positionUInt.x); + InterlockedMin(clothMinBounds[clothIdentifier].y, positionUInt.y); + InterlockedMin(clothMinBounds[clothIdentifier].z, positionUInt.z); + + InterlockedMax(clothMaxBounds[clothIdentifier].x, positionUInt.x); + InterlockedMax(clothMaxBounds[clothIdentifier].y, positionUInt.y); + InterlockedMax(clothMaxBounds[clothIdentifier].z, positionUInt.z); + } + } + + AllMemoryBarrierWithGroupSync(); + + + // Use global atomics to update the global versions of the data + if( GTid.x < numSoftBodies ) + { + InterlockedMin(g_clothMinBounds[GTid.x].x, clothMinBounds[GTid.x].x); + InterlockedMin(g_clothMinBounds[GTid.x].y, clothMinBounds[GTid.x].y); + InterlockedMin(g_clothMinBounds[GTid.x].z, clothMinBounds[GTid.x].z); + + InterlockedMax(g_clothMaxBounds[GTid.x].x, clothMaxBounds[GTid.x].x); + InterlockedMax(g_clothMaxBounds[GTid.x].y, clothMaxBounds[GTid.x].y); + InterlockedMax(g_clothMaxBounds[GTid.x].z, clothMaxBounds[GTid.x].z); + } +} + + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl new file mode 100644 index 0000000..e43870b --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl @@ -0,0 +1,41 @@ +MSTRINGIFY( + +cbuffer IntegrateCB : register( b0 ) +{ + int numNodes; + float solverdt; + int padding1; + int padding2; +}; + +// Node indices for each link +StructuredBuffer g_vertexInverseMasses : register( t0 ); + +RWStructuredBuffer g_vertexPositions : register( u0 ); +RWStructuredBuffer g_vertexVelocity : register( u1 ); +RWStructuredBuffer g_vertexPreviousPositions : register( u2 ); +RWStructuredBuffer g_vertexForceAccumulator : register( u3 ); + +[numthreads(128, 1, 1)] +void +IntegrateKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int nodeID = DTid.x; + if( nodeID < numNodes ) + { + float3 position = g_vertexPositions[nodeID].xyz; + float3 velocity = g_vertexVelocity[nodeID].xyz; + float3 force = g_vertexForceAccumulator[nodeID].xyz; + float inverseMass = g_vertexInverseMasses[nodeID]; + + g_vertexPreviousPositions[nodeID] = float4(position, 0.f); + velocity += force * inverseMass * solverdt; + position += velocity * solverdt; + + g_vertexForceAccumulator[nodeID] = float4(0.f, 0.f, 0.f, 0.0f); + g_vertexPositions[nodeID] = float4(position, 0.f); + g_vertexVelocity[nodeID] = float4(velocity, 0.f); + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl new file mode 100644 index 0000000..cd2924d --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl @@ -0,0 +1,63 @@ +MSTRINGIFY( + +cbuffer OutputToVertexArrayCB : register( b0 ) +{ + int startNode; + int numNodes; + int positionOffset; + int positionStride; + + int normalOffset; + int normalStride; + int padding1; + int padding2; +}; + + +StructuredBuffer g_vertexPositions : register( t0 ); +StructuredBuffer g_vertexNormals : register( t1 ); + +RWBuffer g_vertexBuffer : register( u0 ); + + +[numthreads(128, 1, 1)] +void +OutputToVertexArrayWithNormalsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int nodeID = DTid.x; + if( nodeID < numNodes ) + { + float4 position = g_vertexPositions[nodeID + startNode]; + float4 normal = g_vertexNormals[nodeID + startNode]; + + // Stride should account for the float->float4 conversion + int positionDestination = nodeID * positionStride + positionOffset; + g_vertexBuffer[positionDestination] = position.x; + g_vertexBuffer[positionDestination+1] = position.y; + g_vertexBuffer[positionDestination+2] = position.z; + + int normalDestination = nodeID * normalStride + normalOffset; + g_vertexBuffer[normalDestination] = normal.x; + g_vertexBuffer[normalDestination+1] = normal.y; + g_vertexBuffer[normalDestination+2] = normal.z; + } +} + +[numthreads(128, 1, 1)] +void +OutputToVertexArrayWithoutNormalsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int nodeID = DTid.x; + if( nodeID < numNodes ) + { + float4 position = g_vertexPositions[nodeID + startNode]; + float4 normal = g_vertexNormals[nodeID + startNode]; + + // Stride should account for the float->float4 conversion + int positionDestination = nodeID * positionStride + positionOffset; + g_vertexBuffer[positionDestination] = position.x; + g_vertexBuffer[positionDestination+1] = position.y; + g_vertexBuffer[positionDestination+2] = position.z; + } +} +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl new file mode 100644 index 0000000..269e65c --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl @@ -0,0 +1,44 @@ +MSTRINGIFY( + +cbuffer PrepareLinksCB : register( b0 ) +{ + int numLinks; + int padding0; + int padding1; + int padding2; +}; + +// Node indices for each link +StructuredBuffer g_linksVertexIndices : register( t0 ); +StructuredBuffer g_linksMassLSC : register( t1 ); +StructuredBuffer g_nodesPreviousPosition : register( t2 ); + +RWStructuredBuffer g_linksLengthRatio : register( u0 ); +RWStructuredBuffer g_linksCurrentLength : register( u1 ); + +[numthreads(128, 1, 1)] +void +PrepareLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int linkID = DTid.x; + if( linkID < numLinks ) + { + int2 nodeIndices = g_linksVertexIndices[linkID]; + int node0 = nodeIndices.x; + int node1 = nodeIndices.y; + + float4 nodePreviousPosition0 = g_nodesPreviousPosition[node0]; + float4 nodePreviousPosition1 = g_nodesPreviousPosition[node1]; + + float massLSC = g_linksMassLSC[linkID]; + + float4 linkCurrentLength = nodePreviousPosition1 - nodePreviousPosition0; + + float linkLengthRatio = dot(linkCurrentLength, linkCurrentLength)*massLSC; + linkLengthRatio = 1./linkLengthRatio; + + g_linksCurrentLength[linkID] = linkCurrentLength; + g_linksLengthRatio[linkID] = linkLengthRatio; + } +} +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl new file mode 100644 index 0000000..0eacaf1 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl @@ -0,0 +1,55 @@ +MSTRINGIFY( + +cbuffer SolvePositionsFromLinksKernelCB : register( b0 ) +{ + int startLink; + int numLinks; + float kst; + float ti; +}; + +// Node indices for each link +StructuredBuffer g_linksVertexIndices : register( t0 ); + +StructuredBuffer g_linksMassLSC : register( t1 ); +StructuredBuffer g_linksRestLengthSquared : register( t2 ); +StructuredBuffer g_verticesInverseMass : register( t3 ); + +RWStructuredBuffer g_vertexPositions : register( u0 ); + +[numthreads(128, 1, 1)] +void +SolvePositionsFromLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int linkID = DTid.x + startLink; + if( DTid.x < numLinks ) + { + float massLSC = g_linksMassLSC[linkID]; + float restLengthSquared = g_linksRestLengthSquared[linkID]; + + if( massLSC > 0.0f ) + { + int2 nodeIndices = g_linksVertexIndices[linkID]; + int node0 = nodeIndices.x; + int node1 = nodeIndices.y; + + float3 position0 = g_vertexPositions[node0].xyz; + float3 position1 = g_vertexPositions[node1].xyz; + + float inverseMass0 = g_verticesInverseMass[node0]; + float inverseMass1 = g_verticesInverseMass[node1]; + + float3 del = position1 - position0; + float len = dot(del, del); + float k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst; + position0 = position0 - del*(k*inverseMass0); + position1 = position1 + del*(k*inverseMass1); + + g_vertexPositions[node0] = float4(position0, 0.f); + g_vertexPositions[node1] = float4(position1, 0.f); + + } + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl new file mode 100644 index 0000000..4834dc1 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl @@ -0,0 +1,147 @@ +MSTRINGIFY( + + + +cbuffer SolvePositionsFromLinksKernelCB : register( b0 ) +{ + int startWaveInBatch; + int numWaves; + float kst; + float ti; +}; + + +// Number of batches per wavefront stored one element per logical wavefront +StructuredBuffer g_wavefrontBatchCountsVertexCounts : register( t0 ); +// Set of up to maxNumVertices vertex addresses per wavefront +StructuredBuffer g_vertexAddressesPerWavefront : register( t1 ); + +StructuredBuffer g_verticesInverseMass : register( t2 ); + +// Per-link data layed out structured in terms of sub batches within wavefronts +StructuredBuffer g_linksVertexIndices : register( t3 ); +StructuredBuffer g_linksMassLSC : register( t4 ); +StructuredBuffer g_linksRestLengthSquared : register( t5 ); + +RWStructuredBuffer g_vertexPositions : register( u0 ); + +// Data loaded on a per-wave basis +groupshared int2 wavefrontBatchCountsVertexCounts[WAVEFRONT_BLOCK_MULTIPLIER]; +groupshared float4 vertexPositionSharedData[MAX_NUM_VERTICES_PER_WAVE*WAVEFRONT_BLOCK_MULTIPLIER]; +groupshared float vertexInverseMassSharedData[MAX_NUM_VERTICES_PER_WAVE*WAVEFRONT_BLOCK_MULTIPLIER]; + +// Storing the vertex addresses actually slowed things down a little +//groupshared int vertexAddressSharedData[MAX_NUM_VERTICES_PER_WAVE*WAVEFRONT_BLOCK_MULTIPLIER]; + + +[numthreads(BLOCK_SIZE, 1, 1)] +void +SolvePositionsFromLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + const int laneInWavefront = (DTid.x & (WAVEFRONT_SIZE-1)); + const int wavefront = startWaveInBatch + (DTid.x / WAVEFRONT_SIZE); + const int firstWavefrontInBlock = startWaveInBatch + Gid.x * WAVEFRONT_BLOCK_MULTIPLIER; + const int localWavefront = wavefront - firstWavefrontInBlock; + + int batchesWithinWavefront = 0; + int verticesUsedByWave = 0; + int cond = wavefront < (startWaveInBatch + numWaves); + + // Mask out in case there's a stray "wavefront" at the end that's been forced in through the multiplier + if( cond) + { + + // Load the batch counts for the wavefronts + + int2 batchesAndVerticesWithinWavefront = g_wavefrontBatchCountsVertexCounts[wavefront]; + + batchesWithinWavefront = batchesAndVerticesWithinWavefront.x; + verticesUsedByWave = batchesAndVerticesWithinWavefront.y; + + // Load the vertices for the wavefronts + for( int vertex = laneInWavefront; vertex < verticesUsedByWave; vertex+=WAVEFRONT_SIZE ) + { + int vertexAddress = g_vertexAddressesPerWavefront[wavefront*MAX_NUM_VERTICES_PER_WAVE + vertex]; + + //vertexAddressSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = vertexAddress; + vertexPositionSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = g_vertexPositions[vertexAddress]; + vertexInverseMassSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = g_verticesInverseMass[vertexAddress]; + } + + } + // Ensure compiler does not re-order memory operations + //AllMemoryBarrier(); + AllMemoryBarrierWithGroupSync (); + + if( cond) + { + // Loop through the batches performing the solve on each in LDS + int baseDataLocationForWave = WAVEFRONT_SIZE * wavefront * MAX_BATCHES_PER_WAVE; + + //for( int batch = 0; batch < batchesWithinWavefront; ++batch ) + + int batch = 0; + do + { + int baseDataLocation = baseDataLocationForWave + WAVEFRONT_SIZE * batch; + int locationOfValue = baseDataLocation + laneInWavefront; + + + // These loads should all be perfectly linear across the WF + int2 localVertexIndices = g_linksVertexIndices[locationOfValue]; + float massLSC = g_linksMassLSC[locationOfValue]; + float restLengthSquared = g_linksRestLengthSquared[locationOfValue]; + + + // LDS vertex addresses based on logical wavefront number in block and loaded index + int vertexAddress0 = MAX_NUM_VERTICES_PER_WAVE * localWavefront + localVertexIndices.x; + int vertexAddress1 = MAX_NUM_VERTICES_PER_WAVE * localWavefront + localVertexIndices.y; + + float3 position0 = vertexPositionSharedData[vertexAddress0].xyz; + float3 position1 = vertexPositionSharedData[vertexAddress1].xyz; + + float inverseMass0 = vertexInverseMassSharedData[vertexAddress0]; + float inverseMass1 = vertexInverseMassSharedData[vertexAddress1]; + + float3 del = position1 - position0; + float len = dot(del, del); + + float k = 0; + if( massLSC > 0.0f ) + { + k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst; + } + + position0 = position0 - del*(k*inverseMass0); + position1 = position1 + del*(k*inverseMass1); + + // Ensure compiler does not re-order memory operations + AllMemoryBarrier(); + + vertexPositionSharedData[vertexAddress0] = float4(position0, 0.f); + vertexPositionSharedData[vertexAddress1] = float4(position1, 0.f); + + // Ensure compiler does not re-order memory operations + AllMemoryBarrier(); + + + ++batch; + } while( batch < batchesWithinWavefront ); + + // Update the global memory vertices for the wavefronts + for( int vertex = laneInWavefront; vertex < verticesUsedByWave; vertex+=WAVEFRONT_SIZE ) + { + int vertexAddress = g_vertexAddressesPerWavefront[wavefront*MAX_NUM_VERTICES_PER_WAVE + vertex]; + + g_vertexPositions[vertexAddress] = vertexPositionSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex]; + } + } + + +} + + + + +); + diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl new file mode 100644 index 0000000..0b8031b --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl @@ -0,0 +1,48 @@ +MSTRINGIFY( + +cbuffer UpdateConstantsCB : register( b0 ) +{ + int numLinks; + int padding0; + int padding1; + int padding2; +}; + +// Node indices for each link +StructuredBuffer g_linksVertexIndices : register( t0 ); +StructuredBuffer g_vertexPositions : register( t1 ); +StructuredBuffer g_vertexInverseMasses : register( t2 ); +StructuredBuffer g_linksMaterialLSC : register( t3 ); + +RWStructuredBuffer g_linksMassLSC : register( u0 ); +RWStructuredBuffer g_linksRestLengthSquared : register( u1 ); +RWStructuredBuffer g_linksRestLengths : register( u2 ); + +[numthreads(128, 1, 1)] +void +UpdateConstantsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int linkID = DTid.x; + if( linkID < numLinks ) + { + int2 nodeIndices = g_linksVertexIndices[linkID]; + int node0 = nodeIndices.x; + int node1 = nodeIndices.y; + float linearStiffnessCoefficient = g_linksMaterialLSC[ linkID ]; + + float3 position0 = g_vertexPositions[node0].xyz; + float3 position1 = g_vertexPositions[node1].xyz; + float inverseMass0 = g_vertexInverseMasses[node0]; + float inverseMass1 = g_vertexInverseMasses[node1]; + + float3 difference = position0 - position1; + float length2 = dot(difference, difference); + float length = sqrt(length2); + + g_linksRestLengths[linkID] = length; + g_linksMassLSC[linkID] = (inverseMass0 + inverseMass1)/linearStiffnessCoefficient; + g_linksRestLengthSquared[linkID] = length*length; + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl new file mode 100644 index 0000000..538cc22 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl @@ -0,0 +1,49 @@ +MSTRINGIFY( + +cbuffer UpdateVelocitiesFromPositionsWithVelocitiesCB : register( b0 ) +{ + int numNodes; + float isolverdt; + int padding1; + int padding2; +}; + + +StructuredBuffer g_vertexPositions : register( t0 ); +StructuredBuffer g_vertexPreviousPositions : register( t1 ); +StructuredBuffer g_vertexClothIndices : register( t2 ); +StructuredBuffer g_clothVelocityCorrectionCoefficients : register( t3 ); +StructuredBuffer g_clothDampingFactor : register( t4 ); + +RWStructuredBuffer g_vertexVelocities : register( u0 ); +RWStructuredBuffer g_vertexForces : register( u1 ); + + +[numthreads(128, 1, 1)] +void +updateVelocitiesFromPositionsWithVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int nodeID = DTid.x; + if( nodeID < numNodes ) + { + float3 position = g_vertexPositions[nodeID].xyz; + float3 previousPosition = g_vertexPreviousPositions[nodeID].xyz; + float3 velocity = g_vertexVelocities[nodeID].xyz; + int clothIndex = g_vertexClothIndices[nodeID]; + float velocityCorrectionCoefficient = g_clothVelocityCorrectionCoefficients[clothIndex]; + float dampingFactor = g_clothDampingFactor[clothIndex]; + float velocityCoefficient = (1.f - dampingFactor); + + float3 difference = position - previousPosition; + + velocity += difference*velocityCorrectionCoefficient*isolverdt; + + // Damp the velocity + velocity *= velocityCoefficient; + + g_vertexVelocities[nodeID] = float4(velocity, 0.f); + g_vertexForces[nodeID] = float4(0.f, 0.f, 0.f, 0.f); + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl new file mode 100644 index 0000000..edfd321 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl @@ -0,0 +1,98 @@ +MSTRINGIFY( + +cbuffer UpdateSoftBodiesCB : register( b0 ) +{ + unsigned int numNodes; + unsigned int startFace; + unsigned int numFaces; + float epsilon; +}; + + +// Node indices for each link +StructuredBuffer g_triangleVertexIndexSet : register( t0 ); +StructuredBuffer g_vertexPositions : register( t1 ); +StructuredBuffer g_vertexTriangleCount : register( t2 ); + +RWStructuredBuffer g_vertexNormals : register( u0 ); +RWStructuredBuffer g_vertexArea : register( u1 ); +RWStructuredBuffer g_triangleNormals : register( u2 ); +RWStructuredBuffer g_triangleArea : register( u3 ); + + +[numthreads(128, 1, 1)] +void +ResetNormalsAndAreasKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + if( DTid.x < numNodes ) + { + g_vertexNormals[DTid.x] = float4(0.0f, 0.0f, 0.0f, 0.0f); + g_vertexArea[DTid.x] = 0.0f; + } +} + + +[numthreads(128, 1, 1)] +void +UpdateSoftBodiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int faceID = DTid.x + startFace; + if( DTid.x < numFaces ) + { + int4 triangleIndexSet = g_triangleVertexIndexSet[ faceID ]; + int nodeIndex0 = triangleIndexSet.x; + int nodeIndex1 = triangleIndexSet.y; + int nodeIndex2 = triangleIndexSet.z; + + float3 node0 = g_vertexPositions[nodeIndex0].xyz; + float3 node1 = g_vertexPositions[nodeIndex1].xyz; + float3 node2 = g_vertexPositions[nodeIndex2].xyz; + float3 nodeNormal0 = g_vertexNormals[nodeIndex0].xyz; + float3 nodeNormal1 = g_vertexNormals[nodeIndex1].xyz; + float3 nodeNormal2 = g_vertexNormals[nodeIndex2].xyz; + float vertexArea0 = g_vertexArea[nodeIndex0]; + float vertexArea1 = g_vertexArea[nodeIndex1]; + float vertexArea2 = g_vertexArea[nodeIndex2]; + + float3 vector0 = node1 - node0; + float3 vector1 = node2 - node0; + + float3 faceNormal = cross(vector0.xyz, vector1.xyz); + float triangleArea = length(faceNormal); + + nodeNormal0 = nodeNormal0 + faceNormal; + nodeNormal1 = nodeNormal1 + faceNormal; + nodeNormal2 = nodeNormal2 + faceNormal; + vertexArea0 = vertexArea0 + triangleArea; + vertexArea1 = vertexArea1 + triangleArea; + vertexArea2 = vertexArea2 + triangleArea; + + g_triangleNormals[faceID] = float4(normalize(faceNormal), 0.f); + g_vertexNormals[nodeIndex0] = float4(nodeNormal0, 0.f); + g_vertexNormals[nodeIndex1] = float4(nodeNormal1, 0.f); + g_vertexNormals[nodeIndex2] = float4(nodeNormal2, 0.f); + g_triangleArea[faceID] = triangleArea; + g_vertexArea[nodeIndex0] = vertexArea0; + g_vertexArea[nodeIndex1] = vertexArea1; + g_vertexArea[nodeIndex2] = vertexArea2; + } +} + +[numthreads(128, 1, 1)] +void +NormalizeNormalsAndAreasKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + if( DTid.x < numNodes ) + { + float4 normal = g_vertexNormals[DTid.x]; + float area = g_vertexArea[DTid.x]; + int numTriangles = g_vertexTriangleCount[DTid.x]; + + float vectorLength = length(normal); + + g_vertexNormals[DTid.x] = normalize(normal); + g_vertexArea[DTid.x] = area/float(numTriangles); + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl new file mode 100644 index 0000000..3547a74 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl @@ -0,0 +1,44 @@ +MSTRINGIFY( + +cbuffer UpdateVelocitiesFromPositionsWithoutVelocitiesCB : register( b0 ) +{ + int numNodes; + float isolverdt; + int padding1; + int padding2; +}; + + +StructuredBuffer g_vertexPositions : register( t0 ); +StructuredBuffer g_vertexPreviousPositions : register( t1 ); +StructuredBuffer g_vertexClothIndices : register( t2 ); +StructuredBuffer g_clothDampingFactor : register( t3 ); + +RWStructuredBuffer g_vertexVelocities : register( u0 ); +RWStructuredBuffer g_vertexForces : register( u1 ); + + +[numthreads(128, 1, 1)] +void +updateVelocitiesFromPositionsWithoutVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int nodeID = DTid.x; + if( nodeID < numNodes ) + { + float3 position = g_vertexPositions[nodeID].xyz; + float3 previousPosition = g_vertexPreviousPositions[nodeID].xyz; + float3 velocity = g_vertexVelocities[nodeID].xyz; + int clothIndex = g_vertexClothIndices[nodeID]; + float dampingFactor = g_clothDampingFactor[clothIndex]; + float velocityCoefficient = (1.f - dampingFactor); + + float3 difference = position - previousPosition; + + velocity = difference*velocityCoefficient*isolverdt; + + g_vertexVelocities[nodeID] = float4(velocity, 0.f); + g_vertexForces[nodeID] = float4(0.f, 0.f, 0.f, 0.f); + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl new file mode 100644 index 0000000..5c94bd0 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl @@ -0,0 +1,35 @@ +MSTRINGIFY( + +cbuffer UpdatePositionsFromVelocitiesCB : register( b0 ) +{ + int numNodes; + float solverSDT; + int padding1; + int padding2; +}; + + +StructuredBuffer g_vertexVelocities : register( t0 ); + +RWStructuredBuffer g_vertexPreviousPositions : register( u0 ); +RWStructuredBuffer g_vertexCurrentPosition : register( u1 ); + + +[numthreads(128, 1, 1)] +void +UpdatePositionsFromVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int vertexID = DTid.x; + if( vertexID < numNodes ) + { + float3 previousPosition = g_vertexPreviousPositions[vertexID].xyz; + float3 velocity = g_vertexVelocities[vertexID].xyz; + + float3 newPosition = previousPosition + velocity*solverSDT; + + g_vertexCurrentPosition[vertexID] = float4(newPosition, 0.f); + g_vertexPreviousPositions[vertexID] = float4(newPosition, 0.f); + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl new file mode 100644 index 0000000..fc39195 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl @@ -0,0 +1,55 @@ +MSTRINGIFY( + +cbuffer VSolveLinksCB : register( b0 ) +{ + int startLink; + int numLinks; + float kst; + int padding; +}; + +// Node indices for each link +StructuredBuffer g_linksVertexIndices : register( t0 ); + +StructuredBuffer g_linksLengthRatio : register( t1 ); +StructuredBuffer g_linksCurrentLength : register( t2 ); +StructuredBuffer g_vertexInverseMass : register( t3 ); + +RWStructuredBuffer g_vertexVelocity : register( u0 ); + +[numthreads(128, 1, 1)] +void +VSolveLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int linkID = DTid.x + startLink; + if( DTid.x < numLinks ) + { + int2 nodeIndices = g_linksVertexIndices[linkID]; + int node0 = nodeIndices.x; + int node1 = nodeIndices.y; + + float linkLengthRatio = g_linksLengthRatio[linkID]; + float3 linkCurrentLength = g_linksCurrentLength[linkID].xyz; + + float3 vertexVelocity0 = g_vertexVelocity[node0].xyz; + float3 vertexVelocity1 = g_vertexVelocity[node1].xyz; + + float vertexInverseMass0 = g_vertexInverseMass[node0]; + float vertexInverseMass1 = g_vertexInverseMass[node1]; + + float3 nodeDifference = vertexVelocity0 - vertexVelocity1; + float dotResult = dot(linkCurrentLength, nodeDifference); + float j = -dotResult*linkLengthRatio*kst; + + float3 velocityChange0 = linkCurrentLength*(j*vertexInverseMass0); + float3 velocityChange1 = linkCurrentLength*(j*vertexInverseMass1); + + vertexVelocity0 += velocityChange0; + vertexVelocity1 -= velocityChange1; + + g_vertexVelocity[node0] = float4(vertexVelocity0, 0.f); + g_vertexVelocity[node1] = float4(vertexVelocity1, 0.f); + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl new file mode 100644 index 0000000..399912f --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl @@ -0,0 +1,170 @@ +MSTRINGIFY( + +cbuffer SolvePositionsFromLinksKernelCB : register( b0 ) +{ + unsigned int numNodes; + float isolverdt; + int padding0; + int padding1; +}; + +struct CollisionObjectIndices +{ + int firstObject; + int endObject; +}; + +struct CollisionShapeDescription +{ + float4x4 shapeTransform; + float4 linearVelocity; + float4 angularVelocity; + + int softBodyIdentifier; + int collisionShapeType; + + + // Shape information + // Compressed from the union + float radius; + float halfHeight; + + float margin; + float friction; + + int padding0; + int padding1; + +}; + +// From btBroadphaseProxy.h +static const int CAPSULE_SHAPE_PROXYTYPE = 10; + +// Node indices for each link +StructuredBuffer g_vertexClothIdentifier : register( t0 ); +StructuredBuffer g_vertexPreviousPositions : register( t1 ); +StructuredBuffer g_perClothFriction : register( t2 ); +StructuredBuffer g_clothDampingFactor : register( t3 ); +StructuredBuffer g_perClothCollisionObjectIndices : register( t4 ); +StructuredBuffer g_collisionObjectDetails : register( t5 ); + +RWStructuredBuffer g_vertexForces : register( u0 ); +RWStructuredBuffer g_vertexVelocities : register( u1 ); +RWStructuredBuffer g_vertexPositions : register( u2 ); + +[numthreads(128, 1, 1)] +void +SolveCollisionsAndUpdateVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int nodeID = DTid.x; + float3 forceOnVertex = float3(0.f, 0.f, 0.f); + if( DTid.x < numNodes ) + { + int clothIdentifier = g_vertexClothIdentifier[nodeID]; + float4 position = float4(g_vertexPositions[nodeID].xyz, 1.f); + float4 previousPosition = float4(g_vertexPreviousPositions[nodeID].xyz, 1.f); + float3 velocity; + float clothFriction = g_perClothFriction[clothIdentifier]; + float dampingFactor = g_clothDampingFactor[clothIdentifier]; + float velocityCoefficient = (1.f - dampingFactor); + CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier]; + + if( collisionObjectIndices.firstObject != collisionObjectIndices.endObject ) + { + velocity = float3(15, 0, 0); + + // We have some possible collisions to deal with + for( int collision = collisionObjectIndices.firstObject; collision < collisionObjectIndices.endObject; ++collision ) + { + CollisionShapeDescription shapeDescription = g_collisionObjectDetails[collision]; + float colliderFriction = shapeDescription.friction; + + if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE ) + { + // Colliding with a capsule + + float capsuleHalfHeight = shapeDescription.halfHeight; + float capsuleRadius = shapeDescription.radius; + float capsuleMargin = shapeDescription.margin; + float4x4 worldTransform = shapeDescription.shapeTransform; + + float4 c1 = float4(0.f, -capsuleHalfHeight, 0.f, 1.f); + float4 c2 = float4(0.f, +capsuleHalfHeight, 0.f, 1.f); + float4 worldC1 = mul(worldTransform, c1); + float4 worldC2 = mul(worldTransform, c2); + float3 segment = (worldC2 - worldC1).xyz; + + // compute distance of tangent to vertex along line segment in capsule + float distanceAlongSegment = -( dot( (worldC1 - position).xyz, segment ) / dot(segment, segment) ); + + float4 closestPoint = (worldC1 + float4(segment * distanceAlongSegment, 0.f)); + float distanceFromLine = length(position - closestPoint); + float distanceFromC1 = length(worldC1 - position); + float distanceFromC2 = length(worldC2 - position); + + // Final distance from collision, point to push from, direction to push in + // for impulse force + float dist; + float3 normalVector; + if( distanceAlongSegment < 0 ) + { + dist = distanceFromC1; + normalVector = normalize(position - worldC1).xyz; + } else if( distanceAlongSegment > 1.f ) { + dist = distanceFromC2; + normalVector = normalize(position - worldC2).xyz; + } else { + dist = distanceFromLine; + normalVector = normalize(position - closestPoint).xyz; + } + + float3 colliderLinearVelocity = shapeDescription.linearVelocity.xyz; + float3 colliderAngularVelocity = shapeDescription.angularVelocity.xyz; + float3 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position.xyz - worldTransform._m03_m13_m23); + + float minDistance = capsuleRadius + capsuleMargin; + + // In case of no collision, this is the value of velocity + velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt; + + + // Check for a collision + if( dist < minDistance ) + { + // Project back to surface along normal + position = position + float4((minDistance - dist)*normalVector*0.9, 0.f); + velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt; + float3 relativeVelocity = velocity - velocityOfSurfacePoint; + + float3 p1 = normalize(cross(normalVector, segment)); + float3 p2 = normalize(cross(p1, normalVector)); + // Full friction is sum of velocities in each direction of plane + float3 frictionVector = p1*dot(relativeVelocity, p1) + p2*dot(relativeVelocity, p2); + + // Real friction is peak friction corrected by friction coefficients + frictionVector = frictionVector * (colliderFriction*clothFriction); + + float approachSpeed = dot(relativeVelocity, normalVector); + + if( approachSpeed <= 0.0 ) + forceOnVertex -= frictionVector; + } + + } + } + } else { + // Update velocity + float3 difference = position.xyz - previousPosition.xyz; + velocity = difference*velocityCoefficient*isolverdt; + } + + g_vertexVelocities[nodeID] = float4(velocity, 0.f); + + // Update external force + g_vertexForces[nodeID] = float4(forceOnVertex, 0.f); + + g_vertexPositions[nodeID] = float4(position.xyz, 0.f); + } +} + +); diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl new file mode 100644 index 0000000..9bb7e4d --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl @@ -0,0 +1,191 @@ +MSTRINGIFY( + +cbuffer SolvePositionsFromLinksKernelCB : register( b0 ) +{ + unsigned int numNodes; + float isolverdt; + int padding0; + int padding1; +}; + +struct CollisionObjectIndices +{ + int firstObject; + int endObject; +}; + +struct CollisionShapeDescription +{ + float4x4 shapeTransform; + float4 linearVelocity; + float4 angularVelocity; + + int softBodyIdentifier; + int collisionShapeType; + + + // Shape information + // Compressed from the union + float radius; + float halfHeight; + + float margin; + float friction; + + int padding0; + int padding1; + +}; + +// From btBroadphaseProxy.h +static const int CAPSULE_SHAPE_PROXYTYPE = 10; + +// Node indices for each link +StructuredBuffer g_vertexClothIdentifier : register( t0 ); +StructuredBuffer g_vertexPreviousPositions : register( t1 ); +StructuredBuffer g_perClothFriction : register( t2 ); +StructuredBuffer g_clothDampingFactor : register( t3 ); +StructuredBuffer g_perClothCollisionObjectIndices : register( t4 ); +StructuredBuffer g_collisionObjectDetails : register( t5 ); + +RWStructuredBuffer g_vertexForces : register( u0 ); +RWStructuredBuffer g_vertexVelocities : register( u1 ); +RWStructuredBuffer g_vertexPositions : register( u2 ); + +// A buffer of local collision shapes +// TODO: Iterate to support more than 16 +groupshared CollisionShapeDescription localCollisionShapes[16]; + +[numthreads(128, 1, 1)] +void +SolveCollisionsAndUpdateVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int nodeID = DTid.x; + float3 forceOnVertex = float3(0.f, 0.f, 0.f); + + int clothIdentifier = g_vertexClothIdentifier[nodeID]; + float4 position = float4(g_vertexPositions[nodeID].xyz, 1.f); + float4 previousPosition = float4(g_vertexPreviousPositions[nodeID].xyz, 1.f); + float3 velocity; + float clothFriction = g_perClothFriction[clothIdentifier]; + float dampingFactor = g_clothDampingFactor[clothIdentifier]; + float velocityCoefficient = (1.f - dampingFactor); + CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier]; + + int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; + if( numObjects > 0 ) + { + // We have some possible collisions to deal with + + // First load all of the collision objects into LDS + int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; + if( GTid.x < numObjects ) + { + localCollisionShapes[GTid.x] = g_collisionObjectDetails[ collisionObjectIndices.firstObject + GTid.x ]; + } + } + + // Safe as the vertices are padded so that not more than one soft body is in a group + AllMemoryBarrierWithGroupSync(); + + // Annoyingly, even though I know the flow control is not varying, the compiler will not let me skip this + if( numObjects > 0 ) + { + velocity = float3(0, 0, 0); + + + // We have some possible collisions to deal with + for( int collision = 0; collision < numObjects; ++collision ) + { + CollisionShapeDescription shapeDescription = localCollisionShapes[collision]; + float colliderFriction = shapeDescription.friction; + + if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE ) + { + // Colliding with a capsule + + float capsuleHalfHeight = localCollisionShapes[collision].halfHeight; + float capsuleRadius = localCollisionShapes[collision].radius; + float capsuleMargin = localCollisionShapes[collision].margin; + + float4x4 worldTransform = localCollisionShapes[collision].shapeTransform; + + float4 c1 = float4(0.f, -capsuleHalfHeight, 0.f, 1.f); + float4 c2 = float4(0.f, +capsuleHalfHeight, 0.f, 1.f); + float4 worldC1 = mul(worldTransform, c1); + float4 worldC2 = mul(worldTransform, c2); + float3 segment = (worldC2 - worldC1).xyz; + + // compute distance of tangent to vertex along line segment in capsule + float distanceAlongSegment = -( dot( (worldC1 - position).xyz, segment ) / dot(segment, segment) ); + + float4 closestPoint = (worldC1 + float4(segment * distanceAlongSegment, 0.f)); + float distanceFromLine = length(position - closestPoint); + float distanceFromC1 = length(worldC1 - position); + float distanceFromC2 = length(worldC2 - position); + + // Final distance from collision, point to push from, direction to push in + // for impulse force + float dist; + float3 normalVector; + if( distanceAlongSegment < 0 ) + { + dist = distanceFromC1; + normalVector = normalize(position - worldC1).xyz; + } else if( distanceAlongSegment > 1.f ) { + dist = distanceFromC2; + normalVector = normalize(position - worldC2).xyz; + } else { + dist = distanceFromLine; + normalVector = normalize(position - closestPoint).xyz; + } + + float3 colliderLinearVelocity = localCollisionShapes[collision].linearVelocity.xyz; + float3 colliderAngularVelocity = localCollisionShapes[collision].angularVelocity.xyz; + float3 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position.xyz - worldTransform._m03_m13_m23); + + float minDistance = capsuleRadius + capsuleMargin; + + // In case of no collision, this is the value of velocity + velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt; + + + // Check for a collision + if( dist < minDistance ) + { + // Project back to surface along normal + position = position + float4((minDistance - dist)*normalVector*0.9, 0.f); + velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt; + float3 relativeVelocity = velocity - velocityOfSurfacePoint; + + float3 p1 = normalize(cross(normalVector, segment)); + float3 p2 = normalize(cross(p1, normalVector)); + // Full friction is sum of velocities in each direction of plane + float3 frictionVector = p1*dot(relativeVelocity, p1) + p2*dot(relativeVelocity, p2); + + // Real friction is peak friction corrected by friction coefficients + frictionVector = frictionVector * (colliderFriction*clothFriction); + + float approachSpeed = dot(relativeVelocity, normalVector); + + if( approachSpeed <= 0.0 ) + forceOnVertex -= frictionVector; + } + + } + } + } else { + // Update velocity + float3 difference = position.xyz - previousPosition.xyz; + velocity = difference*velocityCoefficient*isolverdt; + } + + g_vertexVelocities[nodeID] = float4(velocity, 0.f); + + // Update external force + g_vertexForces[nodeID] = float4(forceOnVertex, 0.f); + + g_vertexPositions[nodeID] = float4(position.xyz, 0.f); +} + +); diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h new file mode 100644 index 0000000..daf1ef8 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h @@ -0,0 +1,323 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BT_SOFT_BODY_SOLVER_BUFFER_DX11_H +#define BT_SOFT_BODY_SOLVER_BUFFER_DX11_H + +// DX11 support +#include +#include +#include +#include +#include + +#ifndef SAFE_RELEASE +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } +#endif + +/** + * DX11 Buffer that tracks a host buffer on use to ensure size-correctness. + */ +template class btDX11Buffer +{ +protected: + ID3D11Device* m_d3dDevice; + ID3D11DeviceContext* m_d3dDeviceContext; + + ID3D11Buffer* m_Buffer; + ID3D11ShaderResourceView* m_SRV; + ID3D11UnorderedAccessView* m_UAV; + btAlignedObjectArray< ElementType >* m_CPUBuffer; + + // TODO: Separate this from the main class + // as read back buffers can be shared between buffers + ID3D11Buffer* m_readBackBuffer; + + int m_gpuSize; + bool m_onGPU; + + bool m_readOnlyOnGPU; + + bool createBuffer( ID3D11Buffer *preexistingBuffer = 0) + { + HRESULT hr = S_OK; + + // Create all CS buffers + if( preexistingBuffer ) + { + m_Buffer = preexistingBuffer; + } else { + D3D11_BUFFER_DESC buffer_desc; + ZeroMemory(&buffer_desc, sizeof(buffer_desc)); + buffer_desc.Usage = D3D11_USAGE_DEFAULT; + if( m_readOnlyOnGPU ) + buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + else + buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS; + buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + + buffer_desc.ByteWidth = m_CPUBuffer->size() * sizeof(ElementType); + // At a minimum the buffer must exist + if( buffer_desc.ByteWidth == 0 ) + buffer_desc.ByteWidth = sizeof(ElementType); + buffer_desc.StructureByteStride = sizeof(ElementType); + hr = m_d3dDevice->CreateBuffer(&buffer_desc, NULL, &m_Buffer); + if( FAILED( hr ) ) + return (hr==S_OK); + } + + if( m_readOnlyOnGPU ) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc; + ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc)); + srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN; + srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + + srvbuffer_desc.Buffer.ElementWidth = m_CPUBuffer->size(); + if( srvbuffer_desc.Buffer.ElementWidth == 0 ) + srvbuffer_desc.Buffer.ElementWidth = 1; + hr = m_d3dDevice->CreateShaderResourceView(m_Buffer, &srvbuffer_desc, &m_SRV); + if( FAILED( hr ) ) + return (hr==S_OK); + } else { + // Create SRV + D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc; + ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc)); + srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN; + srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + + srvbuffer_desc.Buffer.ElementWidth = m_CPUBuffer->size(); + if( srvbuffer_desc.Buffer.ElementWidth == 0 ) + srvbuffer_desc.Buffer.ElementWidth = 1; + hr = m_d3dDevice->CreateShaderResourceView(m_Buffer, &srvbuffer_desc, &m_SRV); + if( FAILED( hr ) ) + return (hr==S_OK); + + // Create UAV + D3D11_UNORDERED_ACCESS_VIEW_DESC uavbuffer_desc; + ZeroMemory(&uavbuffer_desc, sizeof(uavbuffer_desc)); + uavbuffer_desc.Format = DXGI_FORMAT_UNKNOWN; + uavbuffer_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + + uavbuffer_desc.Buffer.NumElements = m_CPUBuffer->size(); + if( uavbuffer_desc.Buffer.NumElements == 0 ) + uavbuffer_desc.Buffer.NumElements = 1; + hr = m_d3dDevice->CreateUnorderedAccessView(m_Buffer, &uavbuffer_desc, &m_UAV); + if( FAILED( hr ) ) + return (hr==S_OK); + + // Create read back buffer + D3D11_BUFFER_DESC readback_buffer_desc; + ZeroMemory(&readback_buffer_desc, sizeof(readback_buffer_desc)); + + readback_buffer_desc.ByteWidth = m_CPUBuffer->size() * sizeof(ElementType); + readback_buffer_desc.Usage = D3D11_USAGE_STAGING; + readback_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + readback_buffer_desc.StructureByteStride = sizeof(ElementType); + hr = m_d3dDevice->CreateBuffer(&readback_buffer_desc, NULL, &m_readBackBuffer); + if( FAILED( hr ) ) + return (hr==S_OK); + } + + m_gpuSize = m_CPUBuffer->size(); + return true; + } + + + +public: + btDX11Buffer( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext, btAlignedObjectArray< ElementType > *CPUBuffer, bool readOnly ) + { + m_d3dDevice = d3dDevice; + m_d3dDeviceContext = d3dDeviceContext; + m_Buffer = 0; + m_SRV = 0; + m_UAV = 0; + m_readBackBuffer = 0; + + m_CPUBuffer = CPUBuffer; + + m_gpuSize = 0; + m_onGPU = false; + + m_readOnlyOnGPU = readOnly; + } + + virtual ~btDX11Buffer() + { + SAFE_RELEASE(m_Buffer); + SAFE_RELEASE(m_SRV); + SAFE_RELEASE(m_UAV); + SAFE_RELEASE(m_readBackBuffer); + } + + ID3D11ShaderResourceView* &getSRV() + { + return m_SRV; + } + + ID3D11UnorderedAccessView* &getUAV() + { + return m_UAV; + } + + ID3D11Buffer* &getBuffer() + { + return m_Buffer; + } + + /** + * Move the data to the GPU if it is not there already. + */ + bool moveToGPU() + { + // Reallocate if GPU size is too small + if( (m_CPUBuffer->size() > m_gpuSize ) ) + m_onGPU = false; + if( !m_onGPU && m_CPUBuffer->size() > 0 ) + { + // If the buffer doesn't exist or the CPU-side buffer has changed size, create + // We should really delete the old one, too, but let's leave that for later + if( !m_Buffer || (m_CPUBuffer->size() != m_gpuSize) ) + { + SAFE_RELEASE(m_Buffer); + SAFE_RELEASE(m_SRV); + SAFE_RELEASE(m_UAV); + SAFE_RELEASE(m_readBackBuffer); + if( !createBuffer() ) + { + btAssert("Buffer creation failed."); + return false; + } + } + + if( m_gpuSize > 0 ) + { + D3D11_BOX destRegion; + destRegion.left = 0; + destRegion.front = 0; + destRegion.top = 0; + destRegion.bottom = 1; + destRegion.back = 1; + destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType); + m_d3dDeviceContext->UpdateSubresource(m_Buffer, 0, &destRegion, &((*m_CPUBuffer)[0]), 0, 0); + + m_onGPU = true; + } + + } + + return true; + } + + /** + * Move the data back from the GPU if it is on there and isn't read only. + */ + bool moveFromGPU() + { + if( m_CPUBuffer->size() > 0 ) + { + if( m_onGPU && !m_readOnlyOnGPU ) + { + // Copy back + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + //m_pd3dImmediateContext->CopyResource(m_phAngVelReadBackBuffer, m_phAngVel); + + D3D11_BOX destRegion; + destRegion.left = 0; + destRegion.front = 0; + destRegion.top = 0; + destRegion.bottom = 1; + destRegion.back = 1; + + destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType); + m_d3dDeviceContext->CopySubresourceRegion( + m_readBackBuffer, + 0, + 0, + 0, + 0 , + m_Buffer, + 0, + &destRegion + ); + + m_d3dDeviceContext->Map(m_readBackBuffer, 0, D3D11_MAP_READ, 0, &MappedResource); + //memcpy(m_hAngVel, MappedResource.pData, (m_maxObjs * sizeof(float) )); + memcpy(&((*m_CPUBuffer)[0]), MappedResource.pData, ((m_CPUBuffer->size()) * sizeof(ElementType) )); + m_d3dDeviceContext->Unmap(m_readBackBuffer, 0); + + m_onGPU = false; + } + } + + return true; + } + + + /** + * Copy the data back from the GPU without changing its state to be CPU-side. + * Useful if we just want to view it on the host for visualization. + */ + bool copyFromGPU() + { + if( m_CPUBuffer->size() > 0 ) + { + if( m_onGPU && !m_readOnlyOnGPU ) + { + // Copy back + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + + D3D11_BOX destRegion; + destRegion.left = 0; + destRegion.front = 0; + destRegion.top = 0; + destRegion.bottom = 1; + destRegion.back = 1; + + destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType); + m_d3dDeviceContext->CopySubresourceRegion( + m_readBackBuffer, + 0, + 0, + 0, + 0 , + m_Buffer, + 0, + &destRegion + ); + + m_d3dDeviceContext->Map(m_readBackBuffer, 0, D3D11_MAP_READ, 0, &MappedResource); + //memcpy(m_hAngVel, MappedResource.pData, (m_maxObjs * sizeof(float) )); + memcpy(&((*m_CPUBuffer)[0]), MappedResource.pData, ((m_CPUBuffer->size()) * sizeof(ElementType) )); + m_d3dDeviceContext->Unmap(m_readBackBuffer, 0); + } + } + + return true; + } + + /** + * Call if data has changed on the CPU. + * Can then trigger a move to the GPU as necessary. + */ + virtual void changedOnCPU() + { + m_onGPU = false; + } +}; // class btDX11Buffer + + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_BUFFER_DX11_H \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h new file mode 100644 index 0000000..0f753ce --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h @@ -0,0 +1,103 @@ +/* +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 "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" +#include "btSoftBodySolverBuffer_DX11.h" + + +#ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_DX11_H +#define BT_SOFT_BODY_SOLVER_LINK_DATA_DX11_H + +struct ID3D11Device; +struct ID3D11DeviceContext; + + +class btSoftBodyLinkDataDX11 : public btSoftBodyLinkData +{ +public: + bool m_onGPU; + ID3D11Device *m_d3dDevice; + ID3D11DeviceContext *m_d3dDeviceContext; + + + btDX11Buffer m_dx11Links; + btDX11Buffer m_dx11LinkStrength; + btDX11Buffer m_dx11LinksMassLSC; + btDX11Buffer m_dx11LinksRestLengthSquared; + btDX11Buffer m_dx11LinksCLength; + btDX11Buffer m_dx11LinksLengthRatio; + btDX11Buffer m_dx11LinksRestLength; + btDX11Buffer m_dx11LinksMaterialLinearStiffnessCoefficient; + + struct BatchPair + { + int start; + int length; + + BatchPair() : + start(0), + length(0) + { + } + + BatchPair( int s, int l ) : + start( s ), + length( l ) + { + } + }; + + /** + * Link addressing information for each cloth. + * Allows link locations to be computed independently of data batching. + */ + btAlignedObjectArray< int > m_linkAddresses; + + /** + * Start and length values for computation batches over link data. + */ + btAlignedObjectArray< BatchPair > m_batchStartLengths; + + + //ID3D11Buffer* readBackBuffer; + + btSoftBodyLinkDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ); + + virtual ~btSoftBodyLinkDataDX11(); + + /** Allocate enough space in all link-related arrays to fit numLinks links */ + virtual void createLinks( int numLinks ); + + /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ + virtual void setLinkAt( const LinkDescription &link, int linkIndex ); + + virtual bool onAccelerator(); + + virtual bool moveToAccelerator(); + + virtual bool moveFromAccelerator(); + + /** + * Generate (and later update) the batching for the entire link set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ + void generateBatches(); +}; + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_DX11_H diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h new file mode 100644 index 0000000..82ce46a --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h @@ -0,0 +1,173 @@ +/* +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 "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" +#include "btSoftBodySolverBuffer_DX11.h" + +#ifndef BT_ACCELERATED_SOFT_BODY_LINK_DATA_DX11_SIMDAWARE_H +#define BT_ACCELERATED_SOFT_BODY_LINK_DATA_DX11_SIMDAWARE_H + +struct ID3D11Device; +struct ID3D11DeviceContext; + + +class btSoftBodyLinkDataDX11SIMDAware : public btSoftBodyLinkData +{ +public: + bool m_onGPU; + ID3D11Device *m_d3dDevice; + ID3D11DeviceContext *m_d3dDeviceContext; + + const int m_wavefrontSize; + const int m_linksPerWorkItem; + const int m_maxLinksPerWavefront; + int m_maxBatchesWithinWave; + int m_maxVerticesWithinWave; + int m_numWavefronts; + + int m_maxVertex; + + struct NumBatchesVerticesPair + { + int numBatches; + int numVertices; + }; + + // Array storing number of links in each wavefront + btAlignedObjectArray m_linksPerWavefront; + btAlignedObjectArray m_numBatchesAndVerticesWithinWaves; + btDX11Buffer< NumBatchesVerticesPair > m_dx11NumBatchesAndVerticesWithinWaves; + + // All arrays here will contain batches of m_maxLinksPerWavefront links + // ordered by wavefront. + // with either global vertex pairs or local vertex pairs + btAlignedObjectArray< int > m_wavefrontVerticesGlobalAddresses; // List of global vertices per wavefront + btDX11Buffer m_dx11WavefrontVerticesGlobalAddresses; + btAlignedObjectArray< LinkNodePair > m_linkVerticesLocalAddresses; // Vertex pair for the link + btDX11Buffer m_dx11LinkVerticesLocalAddresses; + btDX11Buffer m_dx11LinkStrength; + btDX11Buffer m_dx11LinksMassLSC; + btDX11Buffer m_dx11LinksRestLengthSquared; + btDX11Buffer m_dx11LinksRestLength; + btDX11Buffer m_dx11LinksMaterialLinearStiffnessCoefficient; + + struct BatchPair + { + int start; + int length; + + BatchPair() : + start(0), + length(0) + { + } + + BatchPair( int s, int l ) : + start( s ), + length( l ) + { + } + }; + + /** + * Link addressing information for each cloth. + * Allows link locations to be computed independently of data batching. + */ + btAlignedObjectArray< int > m_linkAddresses; + + /** + * Start and length values for computation batches over link data. + */ + btAlignedObjectArray< BatchPair > m_wavefrontBatchStartLengths; + + + //ID3D11Buffer* readBackBuffer; + + btSoftBodyLinkDataDX11SIMDAware( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ); + + virtual ~btSoftBodyLinkDataDX11SIMDAware(); + + /** Allocate enough space in all link-related arrays to fit numLinks links */ + virtual void createLinks( int numLinks ); + + /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ + virtual void setLinkAt( const LinkDescription &link, int linkIndex ); + + virtual bool onAccelerator(); + + virtual bool moveToAccelerator(); + + virtual bool moveFromAccelerator(); + + /** + * Generate (and later update) the batching for the entire link set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ + void generateBatches(); + + int getMaxVerticesPerWavefront() + { + return m_maxVerticesWithinWave; + } + + int getWavefrontSize() + { + return m_wavefrontSize; + } + + int getLinksPerWorkItem() + { + return m_linksPerWorkItem; + } + + int getMaxLinksPerWavefront() + { + return m_maxLinksPerWavefront; + } + + int getMaxBatchesPerWavefront() + { + return m_maxBatchesWithinWave; + } + + int getNumWavefronts() + { + return m_numWavefronts; + } + + NumBatchesVerticesPair getNumBatchesAndVerticesWithinWavefront( int wavefront ) + { + return m_numBatchesAndVerticesWithinWaves[wavefront]; + } + + int getVertexGlobalAddresses( int vertexIndex ) + { + return m_wavefrontVerticesGlobalAddresses[vertexIndex]; + } + + /** + * Get post-batching local addresses of the vertex pair for a link assuming all vertices used by a wavefront are loaded locally. + */ + LinkNodePair getVertexPairLocalAddresses( int linkIndex ) + { + return m_linkVerticesLocalAddresses[linkIndex]; + } + +}; + + +#endif // #ifndef BT_ACCELERATED_SOFT_BODY_LINK_DATA_DX11_SIMDAWARE_H diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h new file mode 100644 index 0000000..fc06a27 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h @@ -0,0 +1,96 @@ +/* +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 "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" +#include "btSoftBodySolverBuffer_DX11.h" + + +#ifndef BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_DX11_H +#define BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_DX11_H + +struct ID3D11Device; +struct ID3D11DeviceContext; + +class btSoftBodyTriangleDataDX11 : public btSoftBodyTriangleData +{ +public: + bool m_onGPU; + ID3D11Device *m_d3dDevice; + ID3D11DeviceContext *m_d3dDeviceContext; + + btDX11Buffer m_dx11VertexIndices; + btDX11Buffer m_dx11Area; + btDX11Buffer m_dx11Normal; + + struct BatchPair + { + int start; + int length; + + BatchPair() : + start(0), + length(0) + { + } + + BatchPair( int s, int l ) : + start( s ), + length( l ) + { + } + }; + + + /** + * Link addressing information for each cloth. + * Allows link locations to be computed independently of data batching. + */ + btAlignedObjectArray< int > m_triangleAddresses; + + /** + * Start and length values for computation batches over link data. + */ + btAlignedObjectArray< BatchPair > m_batchStartLengths; + + //ID3D11Buffer* readBackBuffer; + +public: + btSoftBodyTriangleDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ); + + virtual ~btSoftBodyTriangleDataDX11(); + + + /** Allocate enough space in all link-related arrays to fit numLinks links */ + virtual void createTriangles( int numTriangles ); + + /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ + virtual void setTriangleAt( const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex ); + + virtual bool onAccelerator(); + virtual bool moveToAccelerator(); + + virtual bool moveFromAccelerator(); + /** + * Generate (and later update) the batching for the entire triangle set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ + void generateBatches(); +}; + + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_DX11_H diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h new file mode 100644 index 0000000..49d1d0f --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h @@ -0,0 +1,107 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_DX11_H +#define BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_DX11_H + + +#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h" + +#include +#include +#include +#include +#include + +class btDX11VertexBufferDescriptor : public btVertexBufferDescriptor +{ +protected: + /** Context of the DX11 device on which the vertex buffer is stored. */ + ID3D11DeviceContext* m_context; + /** DX11 vertex buffer */ + ID3D11Buffer* m_vertexBuffer; + /** UAV for DX11 buffer */ + ID3D11UnorderedAccessView* m_vertexBufferUAV; + + +public: + /** + * buffer is a pointer to the DX11 buffer to place the vertex data in. + * UAV is a pointer to the UAV representation of the buffer laid out in floats. + * vertexOffset is the offset in floats to the first vertex. + * vertexStride is the stride in floats between vertices. + */ + btDX11VertexBufferDescriptor( ID3D11DeviceContext* context, ID3D11Buffer* buffer, ID3D11UnorderedAccessView *UAV, int vertexOffset, int vertexStride ) + { + m_context = context; + m_vertexBuffer = buffer; + m_vertexBufferUAV = UAV; + m_vertexOffset = vertexOffset; + m_vertexStride = vertexStride; + m_hasVertexPositions = true; + } + + /** + * buffer is a pointer to the DX11 buffer to place the vertex data in. + * UAV is a pointer to the UAV representation of the buffer laid out in floats. + * vertexOffset is the offset in floats to the first vertex. + * vertexStride is the stride in floats between vertices. + * normalOffset is the offset in floats to the first normal. + * normalStride is the stride in floats between normals. + */ + btDX11VertexBufferDescriptor( ID3D11DeviceContext* context, ID3D11Buffer* buffer, ID3D11UnorderedAccessView *UAV, int vertexOffset, int vertexStride, int normalOffset, int normalStride ) + { + m_context = context; + m_vertexBuffer = buffer; + m_vertexBufferUAV = UAV; + m_vertexOffset = vertexOffset; + m_vertexStride = vertexStride; + m_hasVertexPositions = true; + + m_normalOffset = normalOffset; + m_normalStride = normalStride; + m_hasNormals = true; + } + + virtual ~btDX11VertexBufferDescriptor() + { + + } + + /** + * Return the type of the vertex buffer descriptor. + */ + virtual BufferTypes getBufferType() const + { + return DX11_BUFFER; + } + + virtual ID3D11DeviceContext* getContext() const + { + return m_context; + } + + virtual ID3D11Buffer* getbtDX11Buffer() const + { + return m_vertexBuffer; + } + + virtual ID3D11UnorderedAccessView* getDX11UAV() const + { + return m_vertexBufferUAV; + } +}; + +#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_DX11_H \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h new file mode 100644 index 0000000..1374f3a --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h @@ -0,0 +1,63 @@ +/* +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 "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" +#include "btSoftBodySolverBuffer_DX11.h" + + +#ifndef BT_SOFT_BHODY_SOLVER_VERTEX_DATA_DX11_H +#define BT_SOFT_BHODY_SOLVER_VERTEX_DATA_DX11_H + +class btSoftBodyLinkData; +class btSoftBodyLinkData::LinkDescription; + +struct ID3D11Device; +struct ID3D11DeviceContext; + +class btSoftBodyVertexDataDX11 : public btSoftBodyVertexData +{ +protected: + bool m_onGPU; + ID3D11Device *m_d3dDevice; + ID3D11DeviceContext *m_d3dDeviceContext; + +public: + btDX11Buffer m_dx11ClothIdentifier; + btDX11Buffer m_dx11VertexPosition; + btDX11Buffer m_dx11VertexPreviousPosition; + btDX11Buffer m_dx11VertexVelocity; + btDX11Buffer m_dx11VertexForceAccumulator; + btDX11Buffer m_dx11VertexNormal; + btDX11Buffer m_dx11VertexInverseMass; + btDX11Buffer m_dx11VertexArea; + btDX11Buffer m_dx11VertexTriangleCount; + + + //ID3D11Buffer* readBackBuffer; + +public: + btSoftBodyVertexDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ); + virtual ~btSoftBodyVertexDataDX11(); + + virtual bool onAccelerator(); + virtual bool moveToAccelerator(); + + virtual bool moveFromAccelerator(bool bCopy = false, bool bCopyMinimum = true); +}; + + +#endif // #ifndef BT_SOFT_BHODY_SOLVER_VERTEX_DATA_DX11_H + diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp new file mode 100644 index 0000000..b66722b --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp @@ -0,0 +1,2236 @@ +/* +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 "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "vectormath/vmInclude.h" + +#include "btSoftBodySolver_DX11.h" +#include "btSoftBodySolverVertexBuffer_DX11.h" +#include "BulletSoftBody/btSoftBody.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include //printf +#define MSTRINGIFY(A) #A +static char* PrepareLinksHLSLString = +#include "HLSL/PrepareLinks.hlsl" +static char* UpdatePositionsFromVelocitiesHLSLString = +#include "HLSL/UpdatePositionsFromVelocities.hlsl" +static char* SolvePositionsHLSLString = +#include "HLSL/SolvePositions.hlsl" +static char* UpdateNodesHLSLString = +#include "HLSL/UpdateNodes.hlsl" +static char* UpdatePositionsHLSLString = +#include "HLSL/UpdatePositions.hlsl" +static char* UpdateConstantsHLSLString = +#include "HLSL/UpdateConstants.hlsl" +static char* IntegrateHLSLString = +#include "HLSL/Integrate.hlsl" +static char* ApplyForcesHLSLString = +#include "HLSL/ApplyForces.hlsl" +static char* UpdateNormalsHLSLString = +#include "HLSL/UpdateNormals.hlsl" +static char* OutputToVertexArrayHLSLString = +#include "HLSL/OutputToVertexArray.hlsl" +static char* VSolveLinksHLSLString = +#include "HLSL/VSolveLinks.hlsl" +static char* ComputeBoundsHLSLString = +#include "HLSL/ComputeBounds.hlsl" +static char* SolveCollisionsAndUpdateVelocitiesHLSLString = +#include "HLSL/SolveCollisionsAndUpdateVelocities.hlsl" + + +btSoftBodyLinkDataDX11::btSoftBodyLinkDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) : + m_dx11Links( d3dDevice, d3dDeviceContext, &m_links, false ), + m_dx11LinkStrength( d3dDevice, d3dDeviceContext, &m_linkStrength, false ), + m_dx11LinksMassLSC( d3dDevice, d3dDeviceContext, &m_linksMassLSC, false ), + m_dx11LinksRestLengthSquared( d3dDevice, d3dDeviceContext, &m_linksRestLengthSquared, false ), + m_dx11LinksCLength( d3dDevice, d3dDeviceContext, &m_linksCLength, false ), + m_dx11LinksLengthRatio( d3dDevice, d3dDeviceContext, &m_linksLengthRatio, false ), + m_dx11LinksRestLength( d3dDevice, d3dDeviceContext, &m_linksRestLength, false ), + m_dx11LinksMaterialLinearStiffnessCoefficient( d3dDevice, d3dDeviceContext, &m_linksMaterialLinearStiffnessCoefficient, false ) +{ + m_d3dDevice = d3dDevice; + m_d3dDeviceContext = d3dDeviceContext; +} + +btSoftBodyLinkDataDX11::~btSoftBodyLinkDataDX11() +{ +} + +static Vectormath::Aos::Vector3 toVector3( const btVector3 &vec ) +{ + Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() ); + return outVec; +} + +void btSoftBodyLinkDataDX11::createLinks( int numLinks ) +{ + int previousSize = m_links.size(); + int newSize = previousSize + numLinks; + + btSoftBodyLinkData::createLinks( numLinks ); + + // Resize the link addresses array as well + m_linkAddresses.resize( newSize ); +} + +void btSoftBodyLinkDataDX11::setLinkAt( const btSoftBodyLinkData::LinkDescription &link, int linkIndex ) +{ + btSoftBodyLinkData::setLinkAt( link, linkIndex ); + + // Set the link index correctly for initialisation + m_linkAddresses[linkIndex] = linkIndex; +} + +bool btSoftBodyLinkDataDX11::onAccelerator() +{ + return m_onGPU; +} + +bool btSoftBodyLinkDataDX11::moveToAccelerator() +{ + bool success = true; + success = success && m_dx11Links.moveToGPU(); + success = success && m_dx11LinkStrength.moveToGPU(); + success = success && m_dx11LinksMassLSC.moveToGPU(); + success = success && m_dx11LinksRestLengthSquared.moveToGPU(); + success = success && m_dx11LinksCLength.moveToGPU(); + success = success && m_dx11LinksLengthRatio.moveToGPU(); + success = success && m_dx11LinksRestLength.moveToGPU(); + success = success && m_dx11LinksMaterialLinearStiffnessCoefficient.moveToGPU(); + + if( success ) + m_onGPU = true; + + return success; +} + +bool btSoftBodyLinkDataDX11::moveFromAccelerator() +{ + bool success = true; + success = success && m_dx11Links.moveFromGPU(); + success = success && m_dx11LinkStrength.moveFromGPU(); + success = success && m_dx11LinksMassLSC.moveFromGPU(); + success = success && m_dx11LinksRestLengthSquared.moveFromGPU(); + success = success && m_dx11LinksCLength.moveFromGPU(); + success = success && m_dx11LinksLengthRatio.moveFromGPU(); + success = success && m_dx11LinksRestLength.moveFromGPU(); + success = success && m_dx11LinksMaterialLinearStiffnessCoefficient.moveFromGPU(); + + if( success ) + m_onGPU = false; + + return success; +} + +void btSoftBodyLinkDataDX11::generateBatches() +{ + int numLinks = getNumLinks(); + + // Do the graph colouring here temporarily + btAlignedObjectArray< int > batchValues; + batchValues.resize( numLinks, 0 ); + + // Find the maximum vertex value internally for now + int maxVertex = 0; + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + int vertex0 = getVertexPair(linkIndex).vertex0; + int vertex1 = getVertexPair(linkIndex).vertex1; + if( vertex0 > maxVertex ) + maxVertex = vertex0; + if( vertex1 > maxVertex ) + maxVertex = vertex1; + } + int numVertices = maxVertex + 1; + + // Set of lists, one for each node, specifying which colours are connected + // to that node. + // No two edges into a node can share a colour. + btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists; + vertexConnectedColourLists.resize(numVertices); + + + + // Simple algorithm that chooses the lowest batch number + // that none of the links attached to either of the connected + // nodes is in + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + int linkLocation = m_linkAddresses[linkIndex]; + + int vertex0 = getVertexPair(linkLocation).vertex0; + int vertex1 = getVertexPair(linkLocation).vertex1; + + // Get the two node colour lists + btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] ); + btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] ); + + // Choose the minimum colour that is in neither list + int colour = 0; + while( colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() ) + ++colour; + // i should now be the minimum colour in neither list + // Add to the two lists so that future edges don't share + // And store the colour against this edge + + colourListVertex0.push_back(colour); + colourListVertex1.push_back(colour); + batchValues[linkIndex] = colour; + } + + // Check the colour counts + btAlignedObjectArray< int > batchCounts; + for( int i = 0; i < numLinks; ++i ) + { + int batch = batchValues[i]; + if( batch >= batchCounts.size() ) + batchCounts.push_back(1); + else + ++(batchCounts[batch]); + } + + m_batchStartLengths.resize(batchCounts.size()); + if( m_batchStartLengths.size() > 0 ) + { + m_batchStartLengths[0] = BatchPair( 0, 0 ); + + int sum = 0; + for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex ) + { + m_batchStartLengths[batchIndex].start = sum; + m_batchStartLengths[batchIndex].length = batchCounts[batchIndex]; + sum += batchCounts[batchIndex]; + } + } + + ///////////////////////////// + // Sort data based on batches + + // Create source arrays by copying originals + btAlignedObjectArray m_links_Backup(m_links); + btAlignedObjectArray m_linkStrength_Backup(m_linkStrength); + btAlignedObjectArray m_linksMassLSC_Backup(m_linksMassLSC); + btAlignedObjectArray m_linksRestLengthSquared_Backup(m_linksRestLengthSquared); + btAlignedObjectArray m_linksCLength_Backup(m_linksCLength); + btAlignedObjectArray m_linksLengthRatio_Backup(m_linksLengthRatio); + btAlignedObjectArray m_linksRestLength_Backup(m_linksRestLength); + btAlignedObjectArray m_linksMaterialLinearStiffnessCoefficient_Backup(m_linksMaterialLinearStiffnessCoefficient); + + + for( int batch = 0; batch < batchCounts.size(); ++batch ) + batchCounts[batch] = 0; + + // Do sort as single pass into destination arrays + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + // To maintain locations run off the original link locations rather than the current position. + // It's not cache efficient, but as we run this rarely that should not matter. + // It's faster than searching the link location array for the current location and then updating it. + // The other alternative would be to unsort before resorting, but this is equivalent to doing that. + int linkLocation = m_linkAddresses[linkIndex]; + + // Obtain batch and calculate target location for the + // next element in that batch, incrementing the batch counter + // afterwards + int batch = batchValues[linkIndex]; + int newLocation = m_batchStartLengths[batch].start + batchCounts[batch]; + + batchCounts[batch] = batchCounts[batch] + 1; + m_links[newLocation] = m_links_Backup[linkLocation]; +#if 1 + m_linkStrength[newLocation] = m_linkStrength_Backup[linkLocation]; + m_linksMassLSC[newLocation] = m_linksMassLSC_Backup[linkLocation]; + m_linksRestLengthSquared[newLocation] = m_linksRestLengthSquared_Backup[linkLocation]; + m_linksLengthRatio[newLocation] = m_linksLengthRatio_Backup[linkLocation]; + m_linksRestLength[newLocation] = m_linksRestLength_Backup[linkLocation]; + m_linksMaterialLinearStiffnessCoefficient[newLocation] = m_linksMaterialLinearStiffnessCoefficient_Backup[linkLocation]; +#endif + // Update the locations array to account for the moved entry + m_linkAddresses[linkIndex] = newLocation; + } +} // void btSoftBodyLinkDataDX11::generateBatches() + + + +btSoftBodyVertexDataDX11::btSoftBodyVertexDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) : + m_dx11ClothIdentifier( d3dDevice, d3dDeviceContext, &m_clothIdentifier, false ), + m_dx11VertexPosition( d3dDevice, d3dDeviceContext, &m_vertexPosition, false ), + m_dx11VertexPreviousPosition( d3dDevice, d3dDeviceContext, &m_vertexPreviousPosition, false ), + m_dx11VertexVelocity( d3dDevice, d3dDeviceContext, &m_vertexVelocity, false ), + m_dx11VertexForceAccumulator( d3dDevice, d3dDeviceContext, &m_vertexForceAccumulator, false ), + m_dx11VertexNormal( d3dDevice, d3dDeviceContext, &m_vertexNormal, false ), + m_dx11VertexInverseMass( d3dDevice, d3dDeviceContext, &m_vertexInverseMass, false ), + m_dx11VertexArea( d3dDevice, d3dDeviceContext, &m_vertexArea, false ), + m_dx11VertexTriangleCount( d3dDevice, d3dDeviceContext, &m_vertexTriangleCount, false ) +{ + m_d3dDevice = d3dDevice; + m_d3dDeviceContext = d3dDeviceContext; +} + +btSoftBodyVertexDataDX11::~btSoftBodyVertexDataDX11() +{ + +} + +bool btSoftBodyVertexDataDX11::onAccelerator() +{ + return m_onGPU; +} + +bool btSoftBodyVertexDataDX11::moveToAccelerator() +{ + bool success = true; + success = success && m_dx11ClothIdentifier.moveToGPU(); + success = success && m_dx11VertexPosition.moveToGPU(); + success = success && m_dx11VertexPreviousPosition.moveToGPU(); + success = success && m_dx11VertexVelocity.moveToGPU(); + success = success && m_dx11VertexForceAccumulator.moveToGPU(); + success = success && m_dx11VertexNormal.moveToGPU(); + success = success && m_dx11VertexInverseMass.moveToGPU(); + success = success && m_dx11VertexArea.moveToGPU(); + success = success && m_dx11VertexTriangleCount.moveToGPU(); + + if( success ) + m_onGPU = true; + + return success; +} + +bool btSoftBodyVertexDataDX11::moveFromAccelerator(bool bCopy, bool bCopyMinimum) +{ + bool success = true; + + if (!bCopy) + { + success = success && m_dx11ClothIdentifier.moveFromGPU(); + success = success && m_dx11VertexPosition.moveFromGPU(); + success = success && m_dx11VertexPreviousPosition.moveFromGPU(); + success = success && m_dx11VertexVelocity.moveFromGPU(); + success = success && m_dx11VertexForceAccumulator.moveFromGPU(); + success = success && m_dx11VertexNormal.moveFromGPU(); + success = success && m_dx11VertexInverseMass.moveFromGPU(); + success = success && m_dx11VertexArea.moveFromGPU(); + success = success && m_dx11VertexTriangleCount.moveFromGPU(); + } + else + { + if (bCopyMinimum) + { + success = success && m_dx11VertexPosition.copyFromGPU(); + success = success && m_dx11VertexNormal.copyFromGPU(); + } + else + { + success = success && m_dx11ClothIdentifier.copyFromGPU(); + success = success && m_dx11VertexPosition.copyFromGPU(); + success = success && m_dx11VertexPreviousPosition.copyFromGPU(); + success = success && m_dx11VertexVelocity.copyFromGPU(); + success = success && m_dx11VertexForceAccumulator.copyFromGPU(); + success = success && m_dx11VertexNormal.copyFromGPU(); + success = success && m_dx11VertexInverseMass.copyFromGPU(); + success = success && m_dx11VertexArea.copyFromGPU(); + success = success && m_dx11VertexTriangleCount.copyFromGPU(); + } + } + + if( success ) + m_onGPU = true; + + return success; +} + + +btSoftBodyTriangleDataDX11::btSoftBodyTriangleDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) : + m_dx11VertexIndices( d3dDevice, d3dDeviceContext, &m_vertexIndices, false ), + m_dx11Area( d3dDevice, d3dDeviceContext, &m_area, false ), + m_dx11Normal( d3dDevice, d3dDeviceContext, &m_normal, false ) +{ + m_d3dDevice = d3dDevice; + m_d3dDeviceContext = d3dDeviceContext; +} + +btSoftBodyTriangleDataDX11::~btSoftBodyTriangleDataDX11() +{ + +} + + +/** Allocate enough space in all link-related arrays to fit numLinks links */ +void btSoftBodyTriangleDataDX11::createTriangles( int numTriangles ) +{ + int previousSize = getNumTriangles(); + int newSize = previousSize + numTriangles; + + btSoftBodyTriangleData::createTriangles( numTriangles ); + + // Resize the link addresses array as well + m_triangleAddresses.resize( newSize ); +} + +/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ +void btSoftBodyTriangleDataDX11::setTriangleAt( const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex ) +{ + btSoftBodyTriangleData::setTriangleAt( triangle, triangleIndex ); + + m_triangleAddresses[triangleIndex] = triangleIndex; +} + +bool btSoftBodyTriangleDataDX11::onAccelerator() +{ + return m_onGPU; +} + +bool btSoftBodyTriangleDataDX11::moveToAccelerator() +{ + bool success = true; + success = success && m_dx11VertexIndices.moveToGPU(); + success = success && m_dx11Area.moveToGPU(); + success = success && m_dx11Normal.moveToGPU(); + + if( success ) + m_onGPU = true; + + return success; +} + +bool btSoftBodyTriangleDataDX11::moveFromAccelerator() +{ + bool success = true; + success = success && m_dx11VertexIndices.moveFromGPU(); + success = success && m_dx11Area.moveFromGPU(); + success = success && m_dx11Normal.moveFromGPU(); + + if( success ) + m_onGPU = true; + + return success; +} + +/** + * Generate (and later update) the batching for the entire triangle set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ +void btSoftBodyTriangleDataDX11::generateBatches() +{ + int numTriangles = getNumTriangles(); + if( numTriangles == 0 ) + return; + + // Do the graph colouring here temporarily + btAlignedObjectArray< int > batchValues; + batchValues.resize( numTriangles ); + + // Find the maximum vertex value internally for now + int maxVertex = 0; + for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) + { + int vertex0 = getVertexSet(triangleIndex).vertex0; + int vertex1 = getVertexSet(triangleIndex).vertex1; + int vertex2 = getVertexSet(triangleIndex).vertex2; + + if( vertex0 > maxVertex ) + maxVertex = vertex0; + if( vertex1 > maxVertex ) + maxVertex = vertex1; + if( vertex2 > maxVertex ) + maxVertex = vertex2; + } + int numVertices = maxVertex + 1; + + // Set of lists, one for each node, specifying which colours are connected + // to that node. + // No two edges into a node can share a colour. + btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists; + vertexConnectedColourLists.resize(numVertices); + + + //std::cout << "\n"; + // Simple algorithm that chooses the lowest batch number + // that none of the faces attached to either of the connected + // nodes is in + for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) + { + // To maintain locations run off the original link locations rather than the current position. + // It's not cache efficient, but as we run this rarely that should not matter. + // It's faster than searching the link location array for the current location and then updating it. + // The other alternative would be to unsort before resorting, but this is equivalent to doing that. + int triangleLocation = m_triangleAddresses[triangleIndex]; + + int vertex0 = getVertexSet(triangleLocation).vertex0; + int vertex1 = getVertexSet(triangleLocation).vertex1; + int vertex2 = getVertexSet(triangleLocation).vertex2; + + // Get the three node colour lists + btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] ); + btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] ); + btAlignedObjectArray< int > &colourListVertex2( vertexConnectedColourLists[vertex2] ); + + // Choose the minimum colour that is in none of the lists + int colour = 0; + while( + colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || + colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() || + colourListVertex2.findLinearSearch(colour) != colourListVertex2.size() ) + { + ++colour; + } + // i should now be the minimum colour in neither list + // Add to the three lists so that future edges don't share + // And store the colour against this face + colourListVertex0.push_back(colour); + colourListVertex1.push_back(colour); + colourListVertex2.push_back(colour); + + batchValues[triangleIndex] = colour; + } + + + // Check the colour counts + btAlignedObjectArray< int > batchCounts; + for( int i = 0; i < numTriangles; ++i ) + { + int batch = batchValues[i]; + if( batch >= batchCounts.size() ) + batchCounts.push_back(1); + else + ++(batchCounts[batch]); + } + + + m_batchStartLengths.resize(batchCounts.size()); + m_batchStartLengths[0] = BatchPair( 0, 0 ); + + + int sum = 0; + for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex ) + { + m_batchStartLengths[batchIndex].start = sum; + m_batchStartLengths[batchIndex].length = batchCounts[batchIndex]; + sum += batchCounts[batchIndex]; + } + + ///////////////////////////// + // Sort data based on batches + + // Create source arrays by copying originals + btAlignedObjectArray m_vertexIndices_Backup(m_vertexIndices); + btAlignedObjectArray m_area_Backup(m_area); + btAlignedObjectArray m_normal_Backup(m_normal); + + + for( int batch = 0; batch < batchCounts.size(); ++batch ) + batchCounts[batch] = 0; + + // Do sort as single pass into destination arrays + for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) + { + // To maintain locations run off the original link locations rather than the current position. + // It's not cache efficient, but as we run this rarely that should not matter. + // It's faster than searching the link location array for the current location and then updating it. + // The other alternative would be to unsort before resorting, but this is equivalent to doing that. + int triangleLocation = m_triangleAddresses[triangleIndex]; + + // Obtain batch and calculate target location for the + // next element in that batch, incrementing the batch counter + // afterwards + int batch = batchValues[triangleIndex]; + int newLocation = m_batchStartLengths[batch].start + batchCounts[batch]; + + batchCounts[batch] = batchCounts[batch] + 1; + m_vertexIndices[newLocation] = m_vertexIndices_Backup[triangleLocation]; + m_area[newLocation] = m_area_Backup[triangleLocation]; + m_normal[newLocation] = m_normal_Backup[triangleLocation]; + + // Update the locations array to account for the moved entry + m_triangleAddresses[triangleIndex] = newLocation; + } +} // btSoftBodyTriangleDataDX11::generateBatches + + + + + + + + + + + + +btDX11SoftBodySolver::btDX11SoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory) : + m_dx11Device( dx11Device ), + m_dx11Context( dx11Context ), + dxFunctions( m_dx11Device, m_dx11Context, dx11CompileFromMemory ), + m_linkData(m_dx11Device, m_dx11Context), + m_vertexData(m_dx11Device, m_dx11Context), + m_triangleData(m_dx11Device, m_dx11Context), + m_dx11PerClothAcceleration( m_dx11Device, m_dx11Context, &m_perClothAcceleration, true ), + m_dx11PerClothWindVelocity( m_dx11Device, m_dx11Context, &m_perClothWindVelocity, true ), + m_dx11PerClothDampingFactor( m_dx11Device, m_dx11Context, &m_perClothDampingFactor, true ), + m_dx11PerClothVelocityCorrectionCoefficient( m_dx11Device, m_dx11Context, &m_perClothVelocityCorrectionCoefficient, true ), + m_dx11PerClothLiftFactor( m_dx11Device, m_dx11Context, &m_perClothLiftFactor, true ), + m_dx11PerClothDragFactor( m_dx11Device, m_dx11Context, &m_perClothDragFactor, true ), + m_dx11PerClothMediumDensity( m_dx11Device, m_dx11Context, &m_perClothMediumDensity, true ), + m_dx11PerClothCollisionObjects( m_dx11Device, m_dx11Context, &m_perClothCollisionObjects, true ), + m_dx11CollisionObjectDetails( m_dx11Device, m_dx11Context, &m_collisionObjectDetails, true ), + m_dx11PerClothMinBounds( m_dx11Device, m_dx11Context, &m_perClothMinBounds, false ), + m_dx11PerClothMaxBounds( m_dx11Device, m_dx11Context, &m_perClothMaxBounds, false ), + m_dx11PerClothFriction( m_dx11Device, m_dx11Context, &m_perClothFriction, false ), + m_enableUpdateBounds(false) +{ + // Initial we will clearly need to update solver constants + // For now this is global for the cloths linked with this solver - we should probably make this body specific + // for performance in future once we understand more clearly when constants need to be updated + m_updateSolverConstants = true; + + m_shadersInitialized = false; +} + +btDX11SoftBodySolver::~btDX11SoftBodySolver() +{ + releaseKernels(); +} + +void btDX11SoftBodySolver::releaseKernels() +{ + + SAFE_RELEASE( prepareLinksKernel.kernel ); + SAFE_RELEASE( prepareLinksKernel.constBuffer ); + SAFE_RELEASE( integrateKernel.kernel ); + SAFE_RELEASE( integrateKernel.constBuffer ); + SAFE_RELEASE( integrateKernel.kernel ); + SAFE_RELEASE( solvePositionsFromLinksKernel.constBuffer ); + SAFE_RELEASE( solvePositionsFromLinksKernel.kernel ); + SAFE_RELEASE( updatePositionsFromVelocitiesKernel.constBuffer ); + SAFE_RELEASE( updatePositionsFromVelocitiesKernel.kernel ); + SAFE_RELEASE( updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer ); + SAFE_RELEASE( updateVelocitiesFromPositionsWithoutVelocitiesKernel.kernel ); + SAFE_RELEASE( updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer ); + SAFE_RELEASE( updateVelocitiesFromPositionsWithVelocitiesKernel.kernel ); + SAFE_RELEASE( resetNormalsAndAreasKernel.constBuffer ); + SAFE_RELEASE( resetNormalsAndAreasKernel.kernel ); + SAFE_RELEASE( normalizeNormalsAndAreasKernel.constBuffer ); + SAFE_RELEASE( normalizeNormalsAndAreasKernel.kernel ); + SAFE_RELEASE( updateSoftBodiesKernel.constBuffer ); + SAFE_RELEASE( updateSoftBodiesKernel.kernel ); + SAFE_RELEASE( solveCollisionsAndUpdateVelocitiesKernel.kernel ); + SAFE_RELEASE( solveCollisionsAndUpdateVelocitiesKernel.constBuffer ); + SAFE_RELEASE( computeBoundsKernel.kernel ); + SAFE_RELEASE( computeBoundsKernel.constBuffer ); + SAFE_RELEASE( vSolveLinksKernel.kernel ); + SAFE_RELEASE( vSolveLinksKernel.constBuffer ); + + SAFE_RELEASE( addVelocityKernel.constBuffer ); + SAFE_RELEASE( addVelocityKernel.kernel ); + SAFE_RELEASE( applyForcesKernel.constBuffer ); + SAFE_RELEASE( applyForcesKernel.kernel ); + + m_shadersInitialized = false; +} + + +void btDX11SoftBodySolver::copyBackToSoftBodies(bool bMove) +{ + // Move the vertex data back to the host first + m_vertexData.moveFromAccelerator(!bMove); + + // Loop over soft bodies, copying all the vertex positions back for each body in turn + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[ softBodyIndex ]; + btSoftBody *softBody = softBodyInterface->getSoftBody(); + + int firstVertex = softBodyInterface->getFirstVertex(); + int numVertices = softBodyInterface->getNumVertices(); + + // Copy vertices from solver back into the softbody + for( int vertex = 0; vertex < numVertices; ++vertex ) + { + using Vectormath::Aos::Point3; + Point3 vertexPosition( getVertexData().getVertexPositions()[firstVertex + vertex] ); + + softBody->m_nodes[vertex].m_x.setX( vertexPosition.getX() ); + softBody->m_nodes[vertex].m_x.setY( vertexPosition.getY() ); + softBody->m_nodes[vertex].m_x.setZ( vertexPosition.getZ() ); + + softBody->m_nodes[vertex].m_n.setX( vertexPosition.getX() ); + softBody->m_nodes[vertex].m_n.setY( vertexPosition.getY() ); + softBody->m_nodes[vertex].m_n.setZ( vertexPosition.getZ() ); + } + } +} // btDX11SoftBodySolver::copyBackToSoftBodies + + +void btDX11SoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies, bool forceUpdate ) +{ + if( forceUpdate || m_softBodySet.size() != softBodies.size() ) + { + // Have a change in the soft body set so update, reloading all the data + getVertexData().clear(); + getTriangleData().clear(); + getLinkData().clear(); + m_softBodySet.resize(0); + + + for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex ) + { + btSoftBody *softBody = softBodies[ softBodyIndex ]; + using Vectormath::Aos::Matrix3; + using Vectormath::Aos::Point3; + + // Create SoftBody that will store the information within the solver + btAcceleratedSoftBodyInterface *newSoftBody = new btAcceleratedSoftBodyInterface( softBody ); + m_softBodySet.push_back( newSoftBody ); + + m_perClothAcceleration.push_back( toVector3(softBody->getWorldInfo()->m_gravity) ); + m_perClothDampingFactor.push_back(softBody->m_cfg.kDP); + m_perClothVelocityCorrectionCoefficient.push_back( softBody->m_cfg.kVCF ); + m_perClothLiftFactor.push_back( softBody->m_cfg.kLF ); + m_perClothDragFactor.push_back( softBody->m_cfg.kDG ); + m_perClothMediumDensity.push_back(softBody->getWorldInfo()->air_density); + // Simple init values. Actually we'll put 0 and -1 into them at the appropriate time + m_perClothMinBounds.push_back( UIntVector3( 0, 0, 0 ) ); + m_perClothMaxBounds.push_back( UIntVector3( UINT_MAX, UINT_MAX, UINT_MAX ) ); + m_perClothFriction.push_back( softBody->getFriction() ); + m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) ); + + // Add space for new vertices and triangles in the default solver for now + // TODO: Include space here for tearing too later + int firstVertex = getVertexData().getNumVertices(); + int numVertices = softBody->m_nodes.size(); + int maxVertices = numVertices; + // Allocate space for new vertices in all the vertex arrays + getVertexData().createVertices( maxVertices, softBodyIndex ); + + int firstTriangle = getTriangleData().getNumTriangles(); + int numTriangles = softBody->m_faces.size(); + int maxTriangles = numTriangles; + getTriangleData().createTriangles( maxTriangles ); + + // Copy vertices from softbody into the solver + for( int vertex = 0; vertex < numVertices; ++vertex ) + { + Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ()); + btSoftBodyVertexData::VertexDescription desc; + + // TODO: Position in the softbody might be pre-transformed + // or we may need to adapt for the pose. + //desc.setPosition( cloth.getMeshTransform()*multPoint ); + desc.setPosition( multPoint ); + + float vertexInverseMass = softBody->m_nodes[vertex].m_im; + desc.setInverseMass(vertexInverseMass); + getVertexData().setVertexAt( desc, firstVertex + vertex ); + } + + // Copy triangles similarly + // We're assuming here that vertex indices are based on the firstVertex rather than the entire scene + for( int triangle = 0; triangle < numTriangles; ++triangle ) + { + // Note that large array storage is relative to the array not to the cloth + // So we need to add firstVertex to each value + int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0])); + int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0])); + int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0])); + btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex); + getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle ); + + // Increase vertex triangle counts for this triangle + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex0)++; + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex1)++; + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex2)++; + } + + int firstLink = getLinkData().getNumLinks(); + int numLinks = softBody->m_links.size(); + int maxLinks = numLinks; + + // Allocate space for the links + getLinkData().createLinks( numLinks ); + + // Add the links + for( int link = 0; link < numLinks; ++link ) + { + int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]); + int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]); + + btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST); + newLink.setLinkStrength(1.f); + getLinkData().setLinkAt(newLink, firstLink + link); + } + + newSoftBody->setFirstVertex( firstVertex ); + newSoftBody->setFirstTriangle( firstTriangle ); + newSoftBody->setNumVertices( numVertices ); + newSoftBody->setMaxVertices( maxVertices ); + newSoftBody->setNumTriangles( numTriangles ); + newSoftBody->setMaxTriangles( maxTriangles ); + newSoftBody->setFirstLink( firstLink ); + newSoftBody->setNumLinks( numLinks ); + } + + + + updateConstants(0.f); + + + m_linkData.generateBatches(); + m_triangleData.generateBatches(); + } +} + + +btSoftBodyLinkData &btDX11SoftBodySolver::getLinkData() +{ + // TODO: Consider setting link data to "changed" here + return m_linkData; +} + +btSoftBodyVertexData &btDX11SoftBodySolver::getVertexData() +{ + // TODO: Consider setting vertex data to "changed" here + return m_vertexData; +} + +btSoftBodyTriangleData &btDX11SoftBodySolver::getTriangleData() +{ + // TODO: Consider setting triangle data to "changed" here + return m_triangleData; +} + +bool btDX11SoftBodySolver::checkInitialized() +{ + if( !m_shadersInitialized ) + if( buildShaders() ) + m_shadersInitialized = true; + + return m_shadersInitialized; +} + +void btDX11SoftBodySolver::resetNormalsAndAreas( int numVertices ) +{ + // No need to batch link solver, it is entirely parallel + // Copy kernel parameters to GPU + UpdateSoftBodiesCB constBuffer; + + constBuffer.numNodes = numVertices; + constBuffer.epsilon = FLT_EPSILON; + + // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateSoftBodiesCB) ); + m_dx11Context->Unmap( integrateKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexNormal.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexArea.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( resetNormalsAndAreasKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks, 1, 1 ); + + { + // Tidy up + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SoftBodySolver::resetNormalsAndAreas + +void btDX11SoftBodySolver::normalizeNormalsAndAreas( int numVertices ) +{ + // No need to batch link solver, it is entirely parallel + // Copy kernel parameters to GPU + UpdateSoftBodiesCB constBuffer; + + constBuffer.numNodes = numVertices; + constBuffer.epsilon = FLT_EPSILON; + + // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateSoftBodiesCB) ); + m_dx11Context->Unmap( integrateKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexTriangleCount.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexNormal.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexArea.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( normalizeNormalsAndAreasKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks, 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SoftBodySolver::normalizeNormalsAndAreas + +void btDX11SoftBodySolver::executeUpdateSoftBodies( int firstTriangle, int numTriangles ) +{ + // No need to batch link solver, it is entirely parallel + // Copy kernel parameters to GPU + UpdateSoftBodiesCB constBuffer; + + constBuffer.startFace = firstTriangle; + constBuffer.numFaces = numTriangles; + + // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( updateSoftBodiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateSoftBodiesCB) ); + m_dx11Context->Unmap( updateSoftBodiesKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &updateSoftBodiesKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_triangleData.m_dx11VertexIndices.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexNormal.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexArea.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &(m_triangleData.m_dx11Normal.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 3, 1, &(m_triangleData.m_dx11Area.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( updateSoftBodiesKernel.kernel, NULL, 0 ); + + int numBlocks = (numTriangles + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks, 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SoftBodySolver::executeUpdateSoftBodies + +void btDX11SoftBodySolver::updateSoftBodies() +{ + using namespace Vectormath::Aos; + + + int numVertices = m_vertexData.getNumVertices(); + int numTriangles = m_triangleData.getNumTriangles(); + + // Ensure data is on accelerator + m_vertexData.moveToAccelerator(); + m_triangleData.moveToAccelerator(); + + resetNormalsAndAreas( numVertices ); + + + // Go through triangle batches so updates occur correctly + for( int batchIndex = 0; batchIndex < m_triangleData.m_batchStartLengths.size(); ++batchIndex ) + { + + int startTriangle = m_triangleData.m_batchStartLengths[batchIndex].start; + int numTriangles = m_triangleData.m_batchStartLengths[batchIndex].length; + + executeUpdateSoftBodies( startTriangle, numTriangles ); + } + + + normalizeNormalsAndAreas( numVertices ); + + +} // btDX11SoftBodySolver::updateSoftBodies + + +Vectormath::Aos::Vector3 btDX11SoftBodySolver::ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a ) +{ + return a*Vectormath::Aos::dot(v, a); +} + +void btDX11SoftBodySolver::ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce ) +{ + float dtInverseMass = solverdt*inverseMass; + if( Vectormath::Aos::lengthSqr(force * dtInverseMass) > Vectormath::Aos::lengthSqr(vertexVelocity) ) + { + vertexForce -= ProjectOnAxis( vertexVelocity, normalize( force ) )/dtInverseMass; + } else { + vertexForce += force; + } +} + +void btDX11SoftBodySolver::applyForces( float solverdt ) +{ + using namespace Vectormath::Aos; + + + // Ensure data is on accelerator + m_vertexData.moveToAccelerator(); + m_dx11PerClothAcceleration.moveToGPU(); + m_dx11PerClothLiftFactor.moveToGPU(); + m_dx11PerClothDragFactor.moveToGPU(); + m_dx11PerClothMediumDensity.moveToGPU(); + m_dx11PerClothWindVelocity.moveToGPU(); + + // No need to batch link solver, it is entirely parallel + // Copy kernel parameters to GPU + ApplyForcesCB constBuffer; + + constBuffer.numNodes = m_vertexData.getNumVertices(); + constBuffer.solverdt = solverdt; + constBuffer.epsilon = FLT_EPSILON; + + // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(ApplyForcesCB) ); + m_dx11Context->Unmap( integrateKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexNormal.getSRV()) ); + m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexArea.getSRV()) ); + m_dx11Context->CSSetShaderResources( 3, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) ); + m_dx11Context->CSSetShaderResources( 4, 1, &(m_dx11PerClothLiftFactor.getSRV()) ); + m_dx11Context->CSSetShaderResources( 5, 1, &(m_dx11PerClothDragFactor.getSRV()) ); + m_dx11Context->CSSetShaderResources( 6, 1, &(m_dx11PerClothWindVelocity.getSRV()) ); + m_dx11Context->CSSetShaderResources( 7, 1, &(m_dx11PerClothAcceleration.getSRV()) ); + m_dx11Context->CSSetShaderResources( 8, 1, &(m_dx11PerClothMediumDensity.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( applyForcesKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks, 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 5, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 6, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 7, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 8, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SoftBodySolver::applyForces + +/** + * Integrate motion on the solver. + */ +void btDX11SoftBodySolver::integrate( float solverdt ) +{ + // TEMPORARY COPIES + m_vertexData.moveToAccelerator(); + + // No need to batch link solver, it is entirely parallel + // Copy kernel parameters to GPU + IntegrateCB constBuffer; + + constBuffer.numNodes = m_vertexData.getNumVertices(); + constBuffer.solverdt = solverdt; + + // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(IntegrateCB) ); + m_dx11Context->Unmap( integrateKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 3, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( integrateKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks, 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 3, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SoftBodySolver::integrate + +float btDX11SoftBodySolver::computeTriangleArea( + const Vectormath::Aos::Point3 &vertex0, + const Vectormath::Aos::Point3 &vertex1, + const Vectormath::Aos::Point3 &vertex2 ) +{ + Vectormath::Aos::Vector3 a = vertex1 - vertex0; + Vectormath::Aos::Vector3 b = vertex2 - vertex0; + Vectormath::Aos::Vector3 crossProduct = cross(a, b); + float area = length( crossProduct ); + return area; +} // btDX11SoftBodySolver::computeTriangleArea + + +void btDX11SoftBodySolver::updateBounds() +{ + using Vectormath::Aos::Point3; + // Interpretation structure for float and int + + struct FPRep { + unsigned int mantissa : 23; + unsigned int exponent : 8; + unsigned int sign : 1; + }; + union FloatAsInt + { + float floatValue; + int intValue; + unsigned int uintValue; + FPRep fpRep; + }; + + + // Update bounds array to min and max int values to allow easy atomics + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + m_perClothMinBounds[softBodyIndex] = UIntVector3( UINT_MAX, UINT_MAX, UINT_MAX ); + m_perClothMaxBounds[softBodyIndex] = UIntVector3( 0, 0, 0 ); + } + + m_dx11PerClothMinBounds.moveToGPU(); + m_dx11PerClothMaxBounds.moveToGPU(); + + + computeBounds( ); + + + m_dx11PerClothMinBounds.moveFromGPU(); + m_dx11PerClothMaxBounds.moveFromGPU(); + + + + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + UIntVector3 minBoundUInt = m_perClothMinBounds[softBodyIndex]; + UIntVector3 maxBoundUInt = m_perClothMaxBounds[softBodyIndex]; + + // Convert back to float + FloatAsInt fai; + + btVector3 minBound; + fai.uintValue = minBoundUInt.x; + fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); + minBound.setX( fai.floatValue ); + fai.uintValue = minBoundUInt.y; + fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); + minBound.setY( fai.floatValue ); + fai.uintValue = minBoundUInt.z; + fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); + minBound.setZ( fai.floatValue ); + + btVector3 maxBound; + fai.uintValue = maxBoundUInt.x; + fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); + maxBound.setX( fai.floatValue ); + fai.uintValue = maxBoundUInt.y; + fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); + maxBound.setY( fai.floatValue ); + fai.uintValue = maxBoundUInt.z; + fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); + maxBound.setZ( fai.floatValue ); + + // And finally assign to the soft body + m_softBodySet[softBodyIndex]->updateBounds( minBound, maxBound ); + } +} + +void btDX11SoftBodySolver::updateConstants( float timeStep ) +{ + using namespace Vectormath::Aos; + + if( m_updateSolverConstants ) + { + m_updateSolverConstants = false; + + // Will have to redo this if we change the structure (tear, maybe) or various other possible changes + + // Initialise link constants + const int numLinks = m_linkData.getNumLinks(); + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair &vertices( m_linkData.getVertexPair(linkIndex) ); + m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 ))); + float invMass0 = m_vertexData.getInverseMass(vertices.vertex0); + float invMass1 = m_vertexData.getInverseMass(vertices.vertex1); + float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex); + float massLSC = (invMass0 + invMass1)/linearStiffness; + m_linkData.getMassLSC(linkIndex) = massLSC; + float restLength = m_linkData.getRestLength(linkIndex); + float restLengthSquared = restLength*restLength; + m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared; + } + } +} // btDX11SoftBodySolver::updateConstants + +/** + * Sort the collision object details array and generate indexing into it for the per-cloth collision object array. + */ +void btDX11SoftBodySolver::prepareCollisionConstraints() +{ + // First do a simple sort on the collision objects + btAlignedObjectArray numObjectsPerClothPrefixSum; + btAlignedObjectArray numObjectsPerCloth; + numObjectsPerCloth.resize( m_softBodySet.size(), 0 ); + numObjectsPerClothPrefixSum.resize( m_softBodySet.size(), 0 ); + + + class QuickSortCompare + { + public: + + bool operator() ( const CollisionShapeDescription& a, const CollisionShapeDescription& b ) const + { + return ( a.softBodyIdentifier < b.softBodyIdentifier ); + } + }; + + QuickSortCompare comparator; + m_collisionObjectDetails.quickSort( comparator ); + + // Generating indexing for perClothCollisionObjects + // First clear the previous values with the "no collision object for cloth" constant + for( int clothIndex = 0; clothIndex < m_perClothCollisionObjects.size(); ++clothIndex ) + { + m_perClothCollisionObjects[clothIndex].firstObject = -1; + m_perClothCollisionObjects[clothIndex].endObject = -1; + } + int currentCloth = 0; + int startIndex = 0; + for( int collisionObject = 0; collisionObject < m_collisionObjectDetails.size(); ++collisionObject ) + { + int nextCloth = m_collisionObjectDetails[collisionObject].softBodyIdentifier; + if( nextCloth != currentCloth ) + { + // Changed cloth in the array + // Set the end index and the range is what we need for currentCloth + m_perClothCollisionObjects[currentCloth].firstObject = startIndex; + m_perClothCollisionObjects[currentCloth].endObject = collisionObject; + currentCloth = nextCloth; + startIndex = collisionObject; + } + } + + // And update last cloth + m_perClothCollisionObjects[currentCloth].firstObject = startIndex; + m_perClothCollisionObjects[currentCloth].endObject = m_collisionObjectDetails.size(); + +} // btDX11SoftBodySolver::prepareCollisionConstraints + + +void btDX11SoftBodySolver::solveConstraints( float solverdt ) +{ + + //std::cerr << "'GPU' solve constraints\n"; + using Vectormath::Aos::Vector3; + using Vectormath::Aos::Point3; + using Vectormath::Aos::lengthSqr; + using Vectormath::Aos::dot; + + // Prepare links + int numLinks = m_linkData.getNumLinks(); + int numVertices = m_vertexData.getNumVertices(); + + float kst = 1.f; + float ti = 0.f; + + + m_dx11PerClothDampingFactor.moveToGPU(); + m_dx11PerClothVelocityCorrectionCoefficient.moveToGPU(); + + + // Ensure data is on accelerator + m_linkData.moveToAccelerator(); + m_vertexData.moveToAccelerator(); + + + prepareLinks(); + + for( int iteration = 0; iteration < m_numberOfVelocityIterations ; ++iteration ) + { + for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i ) + { + int startLink = m_linkData.m_batchStartLengths[i].start; + int numLinks = m_linkData.m_batchStartLengths[i].length; + + solveLinksForVelocity( startLink, numLinks, kst ); + } + } + + + prepareCollisionConstraints(); + + // Compute new positions from velocity + // Also update the previous position so that our position computation is now based on the new position from the velocity solution + // rather than based directly on the original positions + if( m_numberOfVelocityIterations > 0 ) + { + updateVelocitiesFromPositionsWithVelocities( 1.f/solverdt ); + } else { + updateVelocitiesFromPositionsWithoutVelocities( 1.f/solverdt ); + } + + + // Solve drift + for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) + { + for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i ) + { + int startLink = m_linkData.m_batchStartLengths[i].start; + int numLinks = m_linkData.m_batchStartLengths[i].length; + + solveLinksForPosition( startLink, numLinks, kst, ti ); + } + + } // for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) + + // At this point assume that the force array is blank - we will overwrite it + solveCollisionsAndUpdateVelocities( 1.f/solverdt ); +} // btDX11SoftBodySolver::solveConstraints + + + + +////////////////////////////////////// +// Kernel dispatches +void btDX11SoftBodySolver::prepareLinks() +{ + // No need to batch link solver, it is entirely parallel + // Copy kernel parameters to GPU + PrepareLinksCB constBuffer; + + constBuffer.numLinks = m_linkData.getNumLinks(); + + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( prepareLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(PrepareLinksCB) ); + m_dx11Context->Unmap( prepareLinksKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &prepareLinksKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11Links.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11LinksMassLSC.getSRV()) ); + m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_linkData.m_dx11LinksLengthRatio.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_linkData.m_dx11LinksCLength.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( prepareLinksKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numLinks + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks , 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SoftBodySolver::prepareLinks + + +void btDX11SoftBodySolver::updatePositionsFromVelocities( float solverdt ) +{ + // No need to batch link solver, it is entirely parallel + // Copy kernel parameters to GPU + UpdatePositionsFromVelocitiesCB constBuffer; + + constBuffer.numNodes = m_vertexData.getNumVertices(); + constBuffer.solverSDT = solverdt; + + // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( updatePositionsFromVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(UpdatePositionsFromVelocitiesCB) ); + m_dx11Context->Unmap( updatePositionsFromVelocitiesKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &updatePositionsFromVelocitiesKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( updatePositionsFromVelocitiesKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks, 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SoftBodySolver::updatePositionsFromVelocities + +void btDX11SoftBodySolver::solveLinksForPosition( int startLink, int numLinks, float kst, float ti ) +{ + // Copy kernel parameters to GPU + SolvePositionsFromLinksKernelCB constBuffer; + + // Set the first link of the batch + // and the batch size + constBuffer.startLink = startLink; + constBuffer.numLinks = numLinks; + + constBuffer.kst = kst; + constBuffer.ti = ti; + + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( solvePositionsFromLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(SolvePositionsFromLinksKernelCB) ); + m_dx11Context->Unmap( solvePositionsFromLinksKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &solvePositionsFromLinksKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11Links.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11LinksMassLSC.getSRV()) ); + m_dx11Context->CSSetShaderResources( 2, 1, &(m_linkData.m_dx11LinksRestLengthSquared.getSRV()) ); + m_dx11Context->CSSetShaderResources( 3, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( solvePositionsFromLinksKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numLinks + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks , 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } + +} // btDX11SoftBodySolver::solveLinksForPosition + +void btDX11SoftBodySolver::solveLinksForVelocity( int startLink, int numLinks, float kst ) +{ + // Copy kernel parameters to GPU + VSolveLinksCB constBuffer; + + // Set the first link of the batch + // and the batch size + + constBuffer.startLink = startLink; + constBuffer.numLinks = numLinks; + constBuffer.kst = kst; + + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( vSolveLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(VSolveLinksCB) ); + m_dx11Context->Unmap( vSolveLinksKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &vSolveLinksKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11Links.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11LinksLengthRatio.getSRV()) ); + m_dx11Context->CSSetShaderResources( 2, 1, &(m_linkData.m_dx11LinksCLength.getSRV()) ); + m_dx11Context->CSSetShaderResources( 3, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( vSolveLinksKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numLinks + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks , 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SoftBodySolver::solveLinksForVelocity + + +void btDX11SoftBodySolver::updateVelocitiesFromPositionsWithVelocities( float isolverdt ) +{ + // Copy kernel parameters to GPU + UpdateVelocitiesFromPositionsWithVelocitiesCB constBuffer; + + // Set the first link of the batch + // and the batch size + constBuffer.numNodes = m_vertexData.getNumVertices(); + constBuffer.isolverdt = isolverdt; + + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateVelocitiesFromPositionsWithVelocitiesCB) ); + m_dx11Context->Unmap( updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) ); + m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) ); + m_dx11Context->CSSetShaderResources( 3, 1, &(m_dx11PerClothVelocityCorrectionCoefficient.getSRV()) ); + m_dx11Context->CSSetShaderResources( 4, 1, &(m_dx11PerClothDampingFactor.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL ); + + + // Execute the kernel + m_dx11Context->CSSetShader( updateVelocitiesFromPositionsWithVelocitiesKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks , 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } + +} // btDX11SoftBodySolver::updateVelocitiesFromPositionsWithVelocities + +void btDX11SoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities( float isolverdt ) +{ + // Copy kernel parameters to GPU + UpdateVelocitiesFromPositionsWithoutVelocitiesCB constBuffer; + + // Set the first link of the batch + // and the batch size + constBuffer.numNodes = m_vertexData.getNumVertices(); + constBuffer.isolverdt = isolverdt; + + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateVelocitiesFromPositionsWithoutVelocitiesCB) ); + m_dx11Context->Unmap( updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) ); + m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) ); + m_dx11Context->CSSetShaderResources( 3, 1, &(m_dx11PerClothDampingFactor.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL ); + + + // Execute the kernel + m_dx11Context->CSSetShader( updateVelocitiesFromPositionsWithoutVelocitiesKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks , 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } + +} // btDX11SoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities + + +void btDX11SoftBodySolver::computeBounds( ) +{ + ComputeBoundsCB constBuffer; + m_vertexData.moveToAccelerator(); + + // Set the first link of the batch + // and the batch size + constBuffer.numNodes = m_vertexData.getNumVertices(); + constBuffer.numSoftBodies = m_softBodySet.size(); + + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( computeBoundsKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(ComputeBoundsCB) ); + m_dx11Context->Unmap( computeBoundsKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &computeBoundsKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_dx11PerClothMinBounds.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_dx11PerClothMaxBounds.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( computeBoundsKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks , 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} + +void btDX11SoftBodySolver::solveCollisionsAndUpdateVelocities( float isolverdt ) +{ + + // Copy kernel parameters to GPU + m_vertexData.moveToAccelerator(); + m_dx11PerClothFriction.moveToGPU(); + m_dx11PerClothDampingFactor.moveToGPU(); + m_dx11PerClothCollisionObjects.moveToGPU(); + m_dx11CollisionObjectDetails.moveToGPU(); + + SolveCollisionsAndUpdateVelocitiesCB constBuffer; + + // Set the first link of the batch + // and the batch size + constBuffer.numNodes = m_vertexData.getNumVertices(); + constBuffer.isolverdt = isolverdt; + + + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( solveCollisionsAndUpdateVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(SolveCollisionsAndUpdateVelocitiesCB) ); + m_dx11Context->Unmap( solveCollisionsAndUpdateVelocitiesKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &solveCollisionsAndUpdateVelocitiesKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) ); + m_dx11Context->CSSetShaderResources( 2, 1, &(m_dx11PerClothFriction.getSRV()) ); + m_dx11Context->CSSetShaderResources( 3, 1, &(m_dx11PerClothDampingFactor.getSRV()) ); + m_dx11Context->CSSetShaderResources( 4, 1, &(m_dx11PerClothCollisionObjects.getSRV()) ); + m_dx11Context->CSSetShaderResources( 5, 1, &(m_dx11CollisionObjectDetails.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( solveCollisionsAndUpdateVelocitiesKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks , 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 5, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } + +} // btDX11SoftBodySolver::solveCollisionsAndUpdateVelocities + +// End kernel dispatches +///////////////////////////////////// + + + + + + + + + + + + + + +btDX11SoftBodySolver::btAcceleratedSoftBodyInterface *btDX11SoftBodySolver::findSoftBodyInterface( const btSoftBody* const softBody ) +{ + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex]; + if( softBodyInterface->getSoftBody() == softBody ) + return softBodyInterface; + } + return 0; +} + +const btDX11SoftBodySolver::btAcceleratedSoftBodyInterface * const btDX11SoftBodySolver::findSoftBodyInterface( const btSoftBody* const softBody ) const +{ + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex]; + if( softBodyInterface->getSoftBody() == softBody ) + return softBodyInterface; + } + return 0; +} + +int btDX11SoftBodySolver::findSoftBodyIndex( const btSoftBody* const softBody ) +{ + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex]; + if( softBodyInterface->getSoftBody() == softBody ) + return softBodyIndex; + } + return 1; +} + + +void btSoftBodySolverOutputDXtoCPU::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) +{ + + + btSoftBodySolver *solver = softBody->getSoftBodySolver(); + btAssert( solver->getSolverType() == btSoftBodySolver::DX_SOLVER || solver->getSolverType() == btSoftBodySolver::DX_SIMD_SOLVER ); + btDX11SoftBodySolver *dxSolver = static_cast< btDX11SoftBodySolver * >( solver ); + + btDX11SoftBodySolver::btAcceleratedSoftBodyInterface * currentCloth = dxSolver->findSoftBodyInterface( softBody ); + btSoftBodyVertexDataDX11 &vertexData( dxSolver->m_vertexData ); + + + const int firstVertex = currentCloth->getFirstVertex(); + const int lastVertex = firstVertex + currentCloth->getNumVertices(); + + if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER ) + { + // If we're doing a CPU-buffer copy must copy the data back to the host first + vertexData.m_dx11VertexPosition.copyFromGPU(); + vertexData.m_dx11VertexNormal.copyFromGPU(); + + const int firstVertex = currentCloth->getFirstVertex(); + const int lastVertex = firstVertex + currentCloth->getNumVertices(); + const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast< btCPUVertexBufferDescriptor* >(vertexBuffer); + float *basePointer = cpuVertexBuffer->getBasePointer(); + + if( vertexBuffer->hasVertexPositions() ) + { + const int vertexOffset = cpuVertexBuffer->getVertexOffset(); + const int vertexStride = cpuVertexBuffer->getVertexStride(); + float *vertexPointer = basePointer + vertexOffset; + + for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex ) + { + Vectormath::Aos::Point3 position = vertexData.getPosition(vertexIndex); + *(vertexPointer + 0) = position.getX(); + *(vertexPointer + 1) = position.getY(); + *(vertexPointer + 2) = position.getZ(); + vertexPointer += vertexStride; + } + } + if( vertexBuffer->hasNormals() ) + { + const int normalOffset = cpuVertexBuffer->getNormalOffset(); + const int normalStride = cpuVertexBuffer->getNormalStride(); + float *normalPointer = basePointer + normalOffset; + + for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex ) + { + Vectormath::Aos::Vector3 normal = vertexData.getNormal(vertexIndex); + *(normalPointer + 0) = normal.getX(); + *(normalPointer + 1) = normal.getY(); + *(normalPointer + 2) = normal.getZ(); + normalPointer += normalStride; + } + } + } +} // btDX11SoftBodySolver::outputToVertexBuffers + + + +bool btSoftBodySolverOutputDXtoDX::checkInitialized() +{ + if( !m_shadersInitialized ) + if( buildShaders() ) + m_shadersInitialized = true; + + return m_shadersInitialized; +} + +void btSoftBodySolverOutputDXtoDX::releaseKernels() +{ + SAFE_RELEASE( outputToVertexArrayWithNormalsKernel.constBuffer ); + SAFE_RELEASE( outputToVertexArrayWithNormalsKernel.kernel ); + SAFE_RELEASE( outputToVertexArrayWithoutNormalsKernel.constBuffer ); + SAFE_RELEASE( outputToVertexArrayWithoutNormalsKernel.kernel ); + + m_shadersInitialized = false; +} + + +bool btSoftBodySolverOutputDXtoDX::buildShaders() +{ + // Ensure current kernels are released first + releaseKernels(); + + bool returnVal = true; + + if( m_shadersInitialized ) + return true; + + + outputToVertexArrayWithNormalsKernel = dxFunctions.compileComputeShaderFromString( OutputToVertexArrayHLSLString, "OutputToVertexArrayWithNormalsKernel", sizeof(OutputToVertexArrayCB) ); + if( !outputToVertexArrayWithNormalsKernel.constBuffer) + returnVal = false; + outputToVertexArrayWithoutNormalsKernel = dxFunctions.compileComputeShaderFromString( OutputToVertexArrayHLSLString, "OutputToVertexArrayWithoutNormalsKernel", sizeof(OutputToVertexArrayCB) ); + if( !outputToVertexArrayWithoutNormalsKernel.constBuffer ) + returnVal = false; + + + if( returnVal ) + m_shadersInitialized = true; + + return returnVal; +} + + +void btSoftBodySolverOutputDXtoDX::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) +{ + + + btSoftBodySolver *solver = softBody->getSoftBodySolver(); + btAssert( solver->getSolverType() == btSoftBodySolver::DX_SOLVER || solver->getSolverType() == btSoftBodySolver::DX_SIMD_SOLVER ); + btDX11SoftBodySolver *dxSolver = static_cast< btDX11SoftBodySolver * >( solver ); + checkInitialized(); + btDX11SoftBodySolver::btAcceleratedSoftBodyInterface * currentCloth = dxSolver->findSoftBodyInterface( softBody ); + btSoftBodyVertexDataDX11 &vertexData( dxSolver->m_vertexData ); + + + const int firstVertex = currentCloth->getFirstVertex(); + const int lastVertex = firstVertex + currentCloth->getNumVertices(); + + if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER ) + { + btSoftBodySolverOutputDXtoDX::copySoftBodyToVertexBuffer( softBody, vertexBuffer ); + } else if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::DX11_BUFFER ) + { + // Do a DX11 copy shader DX to DX copy + + const btDX11VertexBufferDescriptor *dx11VertexBuffer = static_cast< btDX11VertexBufferDescriptor* >(vertexBuffer); + + // No need to batch link solver, it is entirely parallel + // Copy kernel parameters to GPU + OutputToVertexArrayCB constBuffer; + ID3D11ComputeShader* outputToVertexArrayShader = outputToVertexArrayWithoutNormalsKernel.kernel; + ID3D11Buffer* outputToVertexArrayConstBuffer = outputToVertexArrayWithoutNormalsKernel.constBuffer; + + constBuffer.startNode = firstVertex; + constBuffer.numNodes = currentCloth->getNumVertices(); + constBuffer.positionOffset = vertexBuffer->getVertexOffset(); + constBuffer.positionStride = vertexBuffer->getVertexStride(); + if( vertexBuffer->hasNormals() ) + { + constBuffer.normalOffset = vertexBuffer->getNormalOffset(); + constBuffer.normalStride = vertexBuffer->getNormalStride(); + outputToVertexArrayShader = outputToVertexArrayWithNormalsKernel.kernel; + outputToVertexArrayConstBuffer = outputToVertexArrayWithNormalsKernel.constBuffer; + } + + // TODO: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + dxFunctions.m_dx11Context->Map( outputToVertexArrayConstBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(OutputToVertexArrayCB) ); + dxFunctions.m_dx11Context->Unmap( outputToVertexArrayConstBuffer, 0 ); + dxFunctions.m_dx11Context->CSSetConstantBuffers( 0, 1, &outputToVertexArrayConstBuffer ); + + // Set resources and dispatch + dxFunctions.m_dx11Context->CSSetShaderResources( 0, 1, &(vertexData.m_dx11VertexPosition.getSRV()) ); + dxFunctions.m_dx11Context->CSSetShaderResources( 1, 1, &(vertexData.m_dx11VertexNormal.getSRV()) ); + + ID3D11UnorderedAccessView* dx11UAV = dx11VertexBuffer->getDX11UAV(); + dxFunctions.m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(dx11UAV), NULL ); + + // Execute the kernel + dxFunctions.m_dx11Context->CSSetShader( outputToVertexArrayShader, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + dxFunctions.m_dx11Context->Dispatch(numBlocks, 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + dxFunctions.m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + dxFunctions.m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + dxFunctions.m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + dxFunctions.m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } + } +} // btDX11SoftBodySolver::outputToVertexBuffers + + + + +DXFunctions::KernelDesc DXFunctions::compileComputeShaderFromString( const char* shaderString, const char* shaderName, int constBufferSize, D3D10_SHADER_MACRO *compileMacros ) +{ + const char *cs5String = "cs_5_0"; + + HRESULT hr = S_OK; + ID3DBlob* pErrorBlob = NULL; + ID3DBlob* pBlob = NULL; + ID3D11ComputeShader* kernelPointer = 0; + + hr = m_dx11CompileFromMemory( + shaderString, + strlen(shaderString), + shaderName, + compileMacros, + NULL, + shaderName, + cs5String, + D3D10_SHADER_ENABLE_STRICTNESS, + NULL, + NULL, + &pBlob, + &pErrorBlob, + NULL + ); + + if( FAILED(hr) ) + { + if( pErrorBlob ) { + btAssert( "Compilation of compute shader failed\n" ); + char *debugString = (char*)pErrorBlob->GetBufferPointer(); + OutputDebugStringA( debugString ); + } + + SAFE_RELEASE( pErrorBlob ); + SAFE_RELEASE( pBlob ); + + DXFunctions::KernelDesc descriptor; + descriptor.kernel = 0; + descriptor.constBuffer = 0; + return descriptor; + } + + // Create the Compute Shader + hr = m_dx11Device->CreateComputeShader( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), NULL, &kernelPointer ); + if( FAILED( hr ) ) + { + DXFunctions::KernelDesc descriptor; + descriptor.kernel = 0; + descriptor.constBuffer = 0; + return descriptor; + } + + ID3D11Buffer* constBuffer = 0; + if( constBufferSize > 0 ) + { + // Create the constant buffer + D3D11_BUFFER_DESC constant_buffer_desc; + ZeroMemory(&constant_buffer_desc, sizeof(constant_buffer_desc)); + constant_buffer_desc.ByteWidth = constBufferSize; + constant_buffer_desc.Usage = D3D11_USAGE_DYNAMIC; + constant_buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constant_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + m_dx11Device->CreateBuffer(&constant_buffer_desc, NULL, &constBuffer); + if( FAILED( hr ) ) + { + KernelDesc descriptor; + descriptor.kernel = 0; + descriptor.constBuffer = 0; + return descriptor; + } + } + + SAFE_RELEASE( pErrorBlob ); + SAFE_RELEASE( pBlob ); + + DXFunctions::KernelDesc descriptor; + descriptor.kernel = kernelPointer; + descriptor.constBuffer = constBuffer; + return descriptor; +} // compileComputeShader + + + +bool btDX11SoftBodySolver::buildShaders() +{ + // Ensure current kernels are released first + releaseKernels(); + + bool returnVal = true; + + if( m_shadersInitialized ) + return true; + + prepareLinksKernel = dxFunctions.compileComputeShaderFromString( PrepareLinksHLSLString, "PrepareLinksKernel", sizeof(PrepareLinksCB) ); + if( !prepareLinksKernel.constBuffer ) + returnVal = false; + updatePositionsFromVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdatePositionsFromVelocitiesHLSLString, "UpdatePositionsFromVelocitiesKernel", sizeof(UpdatePositionsFromVelocitiesCB) ); + if( !updatePositionsFromVelocitiesKernel.constBuffer ) + returnVal = false; + solvePositionsFromLinksKernel = dxFunctions.compileComputeShaderFromString( SolvePositionsHLSLString, "SolvePositionsFromLinksKernel", sizeof(SolvePositionsFromLinksKernelCB) ); + if( !updatePositionsFromVelocitiesKernel.constBuffer ) + returnVal = false; + vSolveLinksKernel = dxFunctions.compileComputeShaderFromString( VSolveLinksHLSLString, "VSolveLinksKernel", sizeof(VSolveLinksCB) ); + if( !vSolveLinksKernel.constBuffer ) + returnVal = false; + updateVelocitiesFromPositionsWithVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdateNodesHLSLString, "updateVelocitiesFromPositionsWithVelocitiesKernel", sizeof(UpdateVelocitiesFromPositionsWithVelocitiesCB) ); + if( !updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer ) + returnVal = false; + updateVelocitiesFromPositionsWithoutVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdatePositionsHLSLString, "updateVelocitiesFromPositionsWithoutVelocitiesKernel", sizeof(UpdateVelocitiesFromPositionsWithoutVelocitiesCB) ); + if( !updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer ) + returnVal = false; + integrateKernel = dxFunctions.compileComputeShaderFromString( IntegrateHLSLString, "IntegrateKernel", sizeof(IntegrateCB) ); + if( !integrateKernel.constBuffer ) + returnVal = false; + applyForcesKernel = dxFunctions.compileComputeShaderFromString( ApplyForcesHLSLString, "ApplyForcesKernel", sizeof(ApplyForcesCB) ); + if( !applyForcesKernel.constBuffer ) + returnVal = false; + solveCollisionsAndUpdateVelocitiesKernel = dxFunctions.compileComputeShaderFromString( SolveCollisionsAndUpdateVelocitiesHLSLString, "SolveCollisionsAndUpdateVelocitiesKernel", sizeof(SolveCollisionsAndUpdateVelocitiesCB) ); + if( !solveCollisionsAndUpdateVelocitiesKernel.constBuffer ) + returnVal = false; + + // TODO: Rename to UpdateSoftBodies + resetNormalsAndAreasKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "ResetNormalsAndAreasKernel", sizeof(UpdateSoftBodiesCB) ); + if( !resetNormalsAndAreasKernel.constBuffer ) + returnVal = false; + normalizeNormalsAndAreasKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "NormalizeNormalsAndAreasKernel", sizeof(UpdateSoftBodiesCB) ); + if( !normalizeNormalsAndAreasKernel.constBuffer ) + returnVal = false; + updateSoftBodiesKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "UpdateSoftBodiesKernel", sizeof(UpdateSoftBodiesCB) ); + if( !updateSoftBodiesKernel.constBuffer ) + returnVal = false; + + computeBoundsKernel = dxFunctions.compileComputeShaderFromString( ComputeBoundsHLSLString, "ComputeBoundsKernel", sizeof(ComputeBoundsCB) ); + if( !computeBoundsKernel.constBuffer ) + returnVal = false; + + + + if( returnVal ) + m_shadersInitialized = true; + + return returnVal; +} + + +static Vectormath::Aos::Transform3 toTransform3( const btTransform &transform ) +{ + Vectormath::Aos::Transform3 outTransform; + outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0))); + outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1))); + outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2))); + outTransform.setCol(3, toVector3(transform.getOrigin())); + return outTransform; +} + + +void btDX11SoftBodySolver::btAcceleratedSoftBodyInterface::updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound ) +{ + float scalarMargin = this->getSoftBody()->getCollisionShape()->getMargin(); + btVector3 vectorMargin( scalarMargin, scalarMargin, scalarMargin ); + m_softBody->m_bounds[0] = lowerBound - vectorMargin; + m_softBody->m_bounds[1] = upperBound + vectorMargin; +} + +void btDX11SoftBodySolver::processCollision( btSoftBody*, btSoftBody* ) +{ + +} + +// Add the collision object to the set to deal with for a particular soft body +void btDX11SoftBodySolver::processCollision( btSoftBody *softBody, btCollisionObject* collisionObject ) +{ + int softBodyIndex = findSoftBodyIndex( softBody ); + + if( softBodyIndex >= 0 ) + { + btCollisionShape *collisionShape = collisionObject->getCollisionShape(); + float friction = collisionObject->getFriction(); + int shapeType = collisionShape->getShapeType(); + if( shapeType == CAPSULE_SHAPE_PROXYTYPE ) + { + // Add to the list of expected collision objects + CollisionShapeDescription newCollisionShapeDescription; + newCollisionShapeDescription.softBodyIdentifier = softBodyIndex; + newCollisionShapeDescription.collisionShapeType = shapeType; + // TODO: May need to transpose this matrix either here or in HLSL + newCollisionShapeDescription.shapeTransform = toTransform3(collisionObject->getWorldTransform()); + btCapsuleShape *capsule = static_cast( collisionShape ); + newCollisionShapeDescription.radius = capsule->getRadius(); + newCollisionShapeDescription.halfHeight = capsule->getHalfHeight(); + newCollisionShapeDescription.margin = capsule->getMargin(); + newCollisionShapeDescription.friction = friction; + btRigidBody* body = static_cast< btRigidBody* >( collisionObject ); + newCollisionShapeDescription.linearVelocity = toVector3(body->getLinearVelocity()); + newCollisionShapeDescription.angularVelocity = toVector3(body->getAngularVelocity()); + m_collisionObjectDetails.push_back( newCollisionShapeDescription ); + + } else { +#ifdef _DEBUG + printf("Unsupported collision shape type\n"); +#endif + } + } else { + btAssert("Unknown soft body"); + } +} // btDX11SoftBodySolver::processCollision + + + +void btDX11SoftBodySolver::predictMotion( float timeStep ) +{ + // Clear the collision shape array for the next frame + // Ensure that the DX11 ones are moved off the device so they will be updated correctly + m_dx11CollisionObjectDetails.changedOnCPU(); + m_dx11PerClothCollisionObjects.changedOnCPU(); + m_collisionObjectDetails.clear(); + + // Fill the force arrays with current acceleration data etc + m_perClothWindVelocity.resize( m_softBodySet.size() ); + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btSoftBody *softBody = m_softBodySet[softBodyIndex]->getSoftBody(); + + m_perClothWindVelocity[softBodyIndex] = toVector3(softBody->getWindVelocity()); + } + m_dx11PerClothWindVelocity.changedOnCPU(); + + // Apply forces that we know about to the cloths + applyForces( timeStep * getTimeScale() ); + + // Itegrate motion for all soft bodies dealt with by the solver + integrate( timeStep * getTimeScale() ); + + // Update bounds + // Will update the bounds for all softBodies being dealt with by the solver and + // set the values in the btSoftBody object + if (m_enableUpdateBounds) + updateBounds(); + + // End prediction work for solvers +} + diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h new file mode 100644 index 0000000..62e629b --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h @@ -0,0 +1,691 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H +#define BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H + + +#include "vectormath/vmInclude.h" +#include "BulletSoftBody/btSoftBodySolvers.h" +#include "btSoftBodySolverVertexBuffer_DX11.h" +#include "btSoftBodySolverLinkData_DX11.h" +#include "btSoftBodySolverVertexData_DX11.h" +#include "btSoftBodySolverTriangleData_DX11.h" + + + +class DXFunctions +{ +public: + + typedef HRESULT (WINAPI * CompileFromMemoryFunc)(LPCSTR,SIZE_T,LPCSTR,const D3D10_SHADER_MACRO*,LPD3D10INCLUDE,LPCSTR,LPCSTR,UINT,UINT,ID3DX11ThreadPump*,ID3D10Blob**,ID3D10Blob**,HRESULT*); + + ID3D11Device * m_dx11Device; + ID3D11DeviceContext* m_dx11Context; + CompileFromMemoryFunc m_dx11CompileFromMemory; + + DXFunctions(ID3D11Device *dx11Device, ID3D11DeviceContext* dx11Context, CompileFromMemoryFunc dx11CompileFromMemory) : + m_dx11Device( dx11Device ), + m_dx11Context( dx11Context ), + m_dx11CompileFromMemory( dx11CompileFromMemory ) + { + + } + + class KernelDesc + { + protected: + + + public: + ID3D11ComputeShader* kernel; + ID3D11Buffer* constBuffer; + + KernelDesc() + { + kernel = 0; + constBuffer = 0; + } + + virtual ~KernelDesc() + { + // TODO: this should probably destroy its kernel but we need to be careful + // in case KernelDescs are copied + } + }; + + /** + * Compile a compute shader kernel from a string and return the appropriate KernelDesc object. + */ + KernelDesc compileComputeShaderFromString( const char* shaderString, const char* shaderName, int constBufferSize, D3D10_SHADER_MACRO *compileMacros = 0 ); + +}; + +class btDX11SoftBodySolver : public btSoftBodySolver +{ +protected: + /** + * Entry in the collision shape array. + * Specifies the shape type, the transform matrix and the necessary details of the collisionShape. + */ + struct CollisionShapeDescription + { + Vectormath::Aos::Transform3 shapeTransform; + Vectormath::Aos::Vector3 linearVelocity; + Vectormath::Aos::Vector3 angularVelocity; + + int softBodyIdentifier; + int collisionShapeType; + + // Both needed for capsule + float radius; + float halfHeight; + + float margin; + float friction; + + CollisionShapeDescription() + { + collisionShapeType = 0; + margin = 0; + friction = 0; + } + }; + + struct UIntVector3 + { + UIntVector3() + { + x = 0; + y = 0; + z = 0; + _padding = 0; + } + + UIntVector3( unsigned int x_, unsigned int y_, unsigned int z_ ) + { + x = x_; + y = y_; + z = z_; + _padding = 0; + } + + unsigned int x; + unsigned int y; + unsigned int z; + unsigned int _padding; + }; + + + +public: + /** + * SoftBody class to maintain information about a soft body instance + * within a solver. + * This data addresses the main solver arrays. + */ + class btAcceleratedSoftBodyInterface + { + protected: + /** Current number of vertices that are part of this cloth */ + int m_numVertices; + /** Maximum number of vertices allocated to be part of this cloth */ + int m_maxVertices; + /** Current number of triangles that are part of this cloth */ + int m_numTriangles; + /** Maximum number of triangles allocated to be part of this cloth */ + int m_maxTriangles; + /** Index of first vertex in the world allocated to this cloth */ + int m_firstVertex; + /** Index of first triangle in the world allocated to this cloth */ + int m_firstTriangle; + /** Index of first link in the world allocated to this cloth */ + int m_firstLink; + /** Maximum number of links allocated to this cloth */ + int m_maxLinks; + /** Current number of links allocated to this cloth */ + int m_numLinks; + + /** The actual soft body this data represents */ + btSoftBody *m_softBody; + + + public: + btAcceleratedSoftBodyInterface( btSoftBody *softBody ) : + m_softBody( softBody ) + { + m_numVertices = 0; + m_maxVertices = 0; + m_numTriangles = 0; + m_maxTriangles = 0; + m_firstVertex = 0; + m_firstTriangle = 0; + m_firstLink = 0; + m_maxLinks = 0; + m_numLinks = 0; + } + int getNumVertices() const + { + return m_numVertices; + } + + int getNumTriangles() const + { + return m_numTriangles; + } + + int getMaxVertices() const + { + return m_maxVertices; + } + + int getMaxTriangles() const + { + return m_maxTriangles; + } + + int getFirstVertex() const + { + return m_firstVertex; + } + + int getFirstTriangle() const + { + return m_firstTriangle; + } + + + /** + * Update the bounds in the btSoftBody object + */ + void updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound ); + + + // TODO: All of these set functions will have to do checks and + // update the world because restructuring of the arrays will be necessary + // Reasonable use of "friend"? + void setNumVertices( int numVertices ) + { + m_numVertices = numVertices; + } + + void setNumTriangles( int numTriangles ) + { + m_numTriangles = numTriangles; + } + + void setMaxVertices( int maxVertices ) + { + m_maxVertices = maxVertices; + } + + void setMaxTriangles( int maxTriangles ) + { + m_maxTriangles = maxTriangles; + } + + void setFirstVertex( int firstVertex ) + { + m_firstVertex = firstVertex; + } + + void setFirstTriangle( int firstTriangle ) + { + m_firstTriangle = firstTriangle; + } + + void setMaxLinks( int maxLinks ) + { + m_maxLinks = maxLinks; + } + + void setNumLinks( int numLinks ) + { + m_numLinks = numLinks; + } + + void setFirstLink( int firstLink ) + { + m_firstLink = firstLink; + } + + int getMaxLinks() + { + return m_maxLinks; + } + + int getNumLinks() + { + return m_numLinks; + } + + int getFirstLink() + { + return m_firstLink; + } + + btSoftBody* getSoftBody() + { + return m_softBody; + } + + }; + + + struct CollisionObjectIndices + { + CollisionObjectIndices( int f, int e ) + { + firstObject = f; + endObject = e; + } + + int firstObject; + int endObject; + }; + + + + + + struct PrepareLinksCB + { + int numLinks; + int padding0; + int padding1; + int padding2; + }; + + struct SolvePositionsFromLinksKernelCB + { + int startLink; + int numLinks; + float kst; + float ti; + }; + + struct IntegrateCB + { + int numNodes; + float solverdt; + int padding1; + int padding2; + }; + + struct UpdatePositionsFromVelocitiesCB + { + int numNodes; + float solverSDT; + int padding1; + int padding2; + }; + + struct UpdateVelocitiesFromPositionsWithoutVelocitiesCB + { + int numNodes; + float isolverdt; + int padding1; + int padding2; + }; + + struct UpdateVelocitiesFromPositionsWithVelocitiesCB + { + int numNodes; + float isolverdt; + int padding1; + int padding2; + }; + + struct UpdateSoftBodiesCB + { + int numNodes; + int startFace; + int numFaces; + float epsilon; + }; + + + struct ApplyForcesCB + { + unsigned int numNodes; + float solverdt; + float epsilon; + int padding3; + }; + + struct AddVelocityCB + { + int startNode; + int lastNode; + float velocityX; + float velocityY; + float velocityZ; + int padding1; + int padding2; + int padding3; + }; + + struct VSolveLinksCB + { + int startLink; + int numLinks; + float kst; + int padding; + }; + + struct ComputeBoundsCB + { + int numNodes; + int numSoftBodies; + int padding1; + int padding2; + }; + + struct SolveCollisionsAndUpdateVelocitiesCB + { + unsigned int numNodes; + float isolverdt; + int padding0; + int padding1; + }; + + + + +protected: + ID3D11Device * m_dx11Device; + ID3D11DeviceContext* m_dx11Context; + + DXFunctions dxFunctions; +public: + /** Link data for all cloths. Note that this will be sorted batch-wise for efficient computation and m_linkAddresses will maintain the addressing. */ + btSoftBodyLinkDataDX11 m_linkData; + btSoftBodyVertexDataDX11 m_vertexData; + btSoftBodyTriangleDataDX11 m_triangleData; + +protected: + + /** Variable to define whether we need to update solver constants on the next iteration */ + bool m_updateSolverConstants; + + bool m_shadersInitialized; + + /** + * Cloths owned by this solver. + * Only our cloths are in this array. + */ + btAlignedObjectArray< btAcceleratedSoftBodyInterface * > m_softBodySet; + + /** Acceleration value to be applied to all non-static vertices in the solver. + * Index n is cloth n, array sized by number of cloths in the world not the solver. + */ + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothAcceleration; + btDX11Buffer m_dx11PerClothAcceleration; + + /** Wind velocity to be applied normal to all non-static vertices in the solver. + * Index n is cloth n, array sized by number of cloths in the world not the solver. + */ + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothWindVelocity; + btDX11Buffer m_dx11PerClothWindVelocity; + + /** Velocity damping factor */ + btAlignedObjectArray< float > m_perClothDampingFactor; + btDX11Buffer m_dx11PerClothDampingFactor; + + /** Velocity correction coefficient */ + btAlignedObjectArray< float > m_perClothVelocityCorrectionCoefficient; + btDX11Buffer m_dx11PerClothVelocityCorrectionCoefficient; + + /** Lift parameter for wind effect on cloth. */ + btAlignedObjectArray< float > m_perClothLiftFactor; + btDX11Buffer m_dx11PerClothLiftFactor; + + /** Drag parameter for wind effect on cloth. */ + btAlignedObjectArray< float > m_perClothDragFactor; + btDX11Buffer m_dx11PerClothDragFactor; + + /** Density of the medium in which each cloth sits */ + btAlignedObjectArray< float > m_perClothMediumDensity; + btDX11Buffer m_dx11PerClothMediumDensity; + + + /** + * Collision shape details: pair of index of first collision shape for the cloth and number of collision objects. + */ + btAlignedObjectArray< CollisionObjectIndices > m_perClothCollisionObjects; + btDX11Buffer m_dx11PerClothCollisionObjects; + + /** + * Collision shapes being passed across to the cloths in this solver. + */ + btAlignedObjectArray< CollisionShapeDescription > m_collisionObjectDetails; + btDX11Buffer< CollisionShapeDescription > m_dx11CollisionObjectDetails; + + /** + * Minimum bounds for each cloth. + * Updated by GPU and returned for use by broad phase. + * These are int vectors as a reminder that they store the int representation of a float, not a float. + * Bit 31 is inverted - is floats are stored with int-sortable values. + */ + btAlignedObjectArray< UIntVector3 > m_perClothMinBounds; + btDX11Buffer< UIntVector3 > m_dx11PerClothMinBounds; + + /** + * Maximum bounds for each cloth. + * Updated by GPU and returned for use by broad phase. + * These are int vectors as a reminder that they store the int representation of a float, not a float. + * Bit 31 is inverted - is floats are stored with int-sortable values. + */ + btAlignedObjectArray< UIntVector3 > m_perClothMaxBounds; + btDX11Buffer< UIntVector3 > m_dx11PerClothMaxBounds; + + + /** + * Friction coefficient for each cloth + */ + btAlignedObjectArray< float > m_perClothFriction; + btDX11Buffer< float > m_dx11PerClothFriction; + + DXFunctions::KernelDesc prepareLinksKernel; + DXFunctions::KernelDesc solvePositionsFromLinksKernel; + DXFunctions::KernelDesc vSolveLinksKernel; + DXFunctions::KernelDesc integrateKernel; + DXFunctions::KernelDesc addVelocityKernel; + DXFunctions::KernelDesc updatePositionsFromVelocitiesKernel; + DXFunctions::KernelDesc updateVelocitiesFromPositionsWithoutVelocitiesKernel; + DXFunctions::KernelDesc updateVelocitiesFromPositionsWithVelocitiesKernel; + DXFunctions::KernelDesc solveCollisionsAndUpdateVelocitiesKernel; + DXFunctions::KernelDesc resetNormalsAndAreasKernel; + DXFunctions::KernelDesc normalizeNormalsAndAreasKernel; + DXFunctions::KernelDesc computeBoundsKernel; + DXFunctions::KernelDesc updateSoftBodiesKernel; + + DXFunctions::KernelDesc applyForcesKernel; + + bool m_enableUpdateBounds; + + /** + * Integrate motion on the solver. + */ + virtual void integrate( float solverdt ); + float computeTriangleArea( + const Vectormath::Aos::Point3 &vertex0, + const Vectormath::Aos::Point3 &vertex1, + const Vectormath::Aos::Point3 &vertex2 ); + + + virtual bool buildShaders(); + + void resetNormalsAndAreas( int numVertices ); + + void normalizeNormalsAndAreas( int numVertices ); + + void executeUpdateSoftBodies( int firstTriangle, int numTriangles ); + + void prepareCollisionConstraints(); + + Vectormath::Aos::Vector3 ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a ); + + void ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce ); + + virtual void applyForces( float solverdt ); + + virtual void updateConstants( float timeStep ); + int findSoftBodyIndex( const btSoftBody* const softBody ); + + ////////////////////////////////////// + // Kernel dispatches + virtual void prepareLinks(); + + void updatePositionsFromVelocities( float solverdt ); + void solveLinksForPosition( int startLink, int numLinks, float kst, float ti ); + void solveLinksForVelocity( int startLink, int numLinks, float kst ); + + void updateVelocitiesFromPositionsWithVelocities( float isolverdt ); + void updateVelocitiesFromPositionsWithoutVelocities( float isolverdt ); + void computeBounds( ); + void solveCollisionsAndUpdateVelocities( float isolverdt ); + + // End kernel dispatches + ///////////////////////////////////// + + void updateBounds(); + + + void releaseKernels(); + +public: + btDX11SoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory = &D3DX11CompileFromMemory); + + virtual ~btDX11SoftBodySolver(); + + + virtual SolverTypes getSolverType() const + { + return DX_SOLVER; + } + + void setEnableUpdateBounds(bool enableBounds) + { + m_enableUpdateBounds = enableBounds; + } + bool getEnableUpdateBounds() const + { + return m_enableUpdateBounds; + } + + + + virtual btSoftBodyLinkData &getLinkData(); + + virtual btSoftBodyVertexData &getVertexData(); + + virtual btSoftBodyTriangleData &getTriangleData(); + + + + + + btAcceleratedSoftBodyInterface *findSoftBodyInterface( const btSoftBody* const softBody ); + const btAcceleratedSoftBodyInterface * const findSoftBodyInterface( const btSoftBody* const softBody ) const; + + virtual bool checkInitialized(); + + virtual void updateSoftBodies( ); + + virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false); + + virtual void copyBackToSoftBodies(bool bMove = true); + + virtual void solveConstraints( float solverdt ); + + virtual void predictMotion( float solverdt ); + + + virtual void processCollision( btSoftBody *, btCollisionObject* ); + + virtual void processCollision( btSoftBody*, btSoftBody* ); + +}; + + + +/** + * Class to manage movement of data from a solver to a given target. + * This version is the DX to CPU version. + */ +class btSoftBodySolverOutputDXtoCPU : public btSoftBodySolverOutput +{ +protected: + +public: + btSoftBodySolverOutputDXtoCPU() + { + } + + /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */ + virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ); +}; + +/** + * Class to manage movement of data from a solver to a given target. + * This version is the DX to DX version and subclasses DX to CPU so that it works for that too. + */ +class btSoftBodySolverOutputDXtoDX : public btSoftBodySolverOutputDXtoCPU +{ +protected: + struct OutputToVertexArrayCB + { + int startNode; + int numNodes; + int positionOffset; + int positionStride; + + int normalOffset; + int normalStride; + int padding1; + int padding2; + }; + + DXFunctions dxFunctions; + DXFunctions::KernelDesc outputToVertexArrayWithNormalsKernel; + DXFunctions::KernelDesc outputToVertexArrayWithoutNormalsKernel; + + + bool m_shadersInitialized; + + bool checkInitialized(); + bool buildShaders(); + void releaseKernels(); + +public: + btSoftBodySolverOutputDXtoDX(ID3D11Device *dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory = &D3DX11CompileFromMemory) : + dxFunctions( dx11Device, dx11Context, dx11CompileFromMemory ) + { + m_shadersInitialized = false; + } + + ~btSoftBodySolverOutputDXtoDX() + { + releaseKernels(); + } + + /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */ + virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ); +}; + +#endif // #ifndef BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H + + diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp new file mode 100644 index 0000000..b74c8d2 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp @@ -0,0 +1,1051 @@ +/* +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 + + +#define WAVEFRONT_SIZE 32 +#define WAVEFRONT_BLOCK_MULTIPLIER 2 +#define GROUP_SIZE (WAVEFRONT_SIZE*WAVEFRONT_BLOCK_MULTIPLIER) +#define LINKS_PER_SIMD_LANE 16 + +#define STRINGIFY( S ) STRINGIFY2( S ) +#define STRINGIFY2( S ) #S + +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "vectormath/vmInclude.h" + +#include "btSoftBodySolverLinkData_DX11SIMDAware.h" +#include "btSoftBodySolver_DX11SIMDAware.h" +#include "btSoftBodySolverVertexBuffer_DX11.h" +#include "BulletSoftBody/btSoftBody.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" + +#define MSTRINGIFY(A) #A +static char* UpdatePositionsFromVelocitiesHLSLString = +#include "HLSL/UpdatePositionsFromVelocities.hlsl" +static char* SolvePositionsSIMDBatchedHLSLString = +#include "HLSL/SolvePositionsSIMDBatched.hlsl" +static char* UpdateNodesHLSLString = +#include "HLSL/UpdateNodes.hlsl" +static char* UpdatePositionsHLSLString = +#include "HLSL/UpdatePositions.hlsl" +static char* UpdateConstantsHLSLString = +#include "HLSL/UpdateConstants.hlsl" +static char* IntegrateHLSLString = +#include "HLSL/Integrate.hlsl" +static char* ApplyForcesHLSLString = +#include "HLSL/ApplyForces.hlsl" +static char* UpdateNormalsHLSLString = +#include "HLSL/UpdateNormals.hlsl" +static char* OutputToVertexArrayHLSLString = +#include "HLSL/OutputToVertexArray.hlsl" +static char* VSolveLinksHLSLString = +#include "HLSL/VSolveLinks.hlsl" +static char* ComputeBoundsHLSLString = +#include "HLSL/ComputeBounds.hlsl" +static char* SolveCollisionsAndUpdateVelocitiesHLSLString = +#include "HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl" + + + +btSoftBodyLinkDataDX11SIMDAware::btSoftBodyLinkDataDX11SIMDAware( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) : + m_d3dDevice( d3dDevice ), + m_d3dDeviceContext( d3dDeviceContext ), + m_wavefrontSize( WAVEFRONT_SIZE ), + m_linksPerWorkItem( LINKS_PER_SIMD_LANE ), + m_maxBatchesWithinWave( 0 ), + m_maxLinksPerWavefront( m_wavefrontSize * m_linksPerWorkItem ), + m_numWavefronts( 0 ), + m_maxVertex( 0 ), + m_dx11NumBatchesAndVerticesWithinWaves( d3dDevice, d3dDeviceContext, &m_numBatchesAndVerticesWithinWaves, true ), + m_dx11WavefrontVerticesGlobalAddresses( d3dDevice, d3dDeviceContext, &m_wavefrontVerticesGlobalAddresses, true ), + m_dx11LinkVerticesLocalAddresses( d3dDevice, d3dDeviceContext, &m_linkVerticesLocalAddresses, true ), + m_dx11LinkStrength( d3dDevice, d3dDeviceContext, &m_linkStrength, true ), + m_dx11LinksMassLSC( d3dDevice, d3dDeviceContext, &m_linksMassLSC, true ), + m_dx11LinksRestLengthSquared( d3dDevice, d3dDeviceContext, &m_linksRestLengthSquared, true ), + m_dx11LinksRestLength( d3dDevice, d3dDeviceContext, &m_linksRestLength, true ), + m_dx11LinksMaterialLinearStiffnessCoefficient( d3dDevice, d3dDeviceContext, &m_linksMaterialLinearStiffnessCoefficient, true ) +{ + m_d3dDevice = d3dDevice; + m_d3dDeviceContext = d3dDeviceContext; +} + +btSoftBodyLinkDataDX11SIMDAware::~btSoftBodyLinkDataDX11SIMDAware() +{ +} + +static Vectormath::Aos::Vector3 toVector3( const btVector3 &vec ) +{ + Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() ); + return outVec; +} + +void btSoftBodyLinkDataDX11SIMDAware::createLinks( int numLinks ) +{ + int previousSize = m_links.size(); + int newSize = previousSize + numLinks; + + btSoftBodyLinkData::createLinks( numLinks ); + + // Resize the link addresses array as well + m_linkAddresses.resize( newSize ); +} + +void btSoftBodyLinkDataDX11SIMDAware::setLinkAt( const btSoftBodyLinkData::LinkDescription &link, int linkIndex ) +{ + btSoftBodyLinkData::setLinkAt( link, linkIndex ); + + if( link.getVertex0() > m_maxVertex ) + m_maxVertex = link.getVertex0(); + if( link.getVertex1() > m_maxVertex ) + m_maxVertex = link.getVertex1(); + + // Set the link index correctly for initialisation + m_linkAddresses[linkIndex] = linkIndex; +} + +bool btSoftBodyLinkDataDX11SIMDAware::onAccelerator() +{ + return m_onGPU; +} + +bool btSoftBodyLinkDataDX11SIMDAware::moveToAccelerator() +{ + bool success = true; + + success = success && m_dx11NumBatchesAndVerticesWithinWaves.moveToGPU(); + success = success && m_dx11WavefrontVerticesGlobalAddresses.moveToGPU(); + success = success && m_dx11LinkVerticesLocalAddresses.moveToGPU(); + success = success && m_dx11LinkStrength.moveToGPU(); + success = success && m_dx11LinksMassLSC.moveToGPU(); + success = success && m_dx11LinksRestLengthSquared.moveToGPU(); + success = success && m_dx11LinksRestLength.moveToGPU(); + success = success && m_dx11LinksMaterialLinearStiffnessCoefficient.moveToGPU(); + + if( success ) + m_onGPU = true; + + return success; +} + +bool btSoftBodyLinkDataDX11SIMDAware::moveFromAccelerator() +{ + bool success = true; + success = success && m_dx11NumBatchesAndVerticesWithinWaves.moveFromGPU(); + success = success && m_dx11WavefrontVerticesGlobalAddresses.moveFromGPU(); + success = success && m_dx11LinkVerticesLocalAddresses.moveFromGPU(); + success = success && m_dx11LinkStrength.moveFromGPU(); + success = success && m_dx11LinksMassLSC.moveFromGPU(); + success = success && m_dx11LinksRestLengthSquared.moveFromGPU(); + success = success && m_dx11LinksRestLength.moveFromGPU(); + success = success && m_dx11LinksMaterialLinearStiffnessCoefficient.moveFromGPU(); + + if( success ) + m_onGPU = false; + + return success; +} + + + + + + + + + + + + + + + +btDX11SIMDAwareSoftBodySolver::btDX11SIMDAwareSoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory) : + btDX11SoftBodySolver( dx11Device, dx11Context, dx11CompileFromMemory ), + m_linkData(m_dx11Device, m_dx11Context) +{ + // Initial we will clearly need to update solver constants + // For now this is global for the cloths linked with this solver - we should probably make this body specific + // for performance in future once we understand more clearly when constants need to be updated + m_updateSolverConstants = true; + + m_shadersInitialized = false; +} + +btDX11SIMDAwareSoftBodySolver::~btDX11SIMDAwareSoftBodySolver() +{ + releaseKernels(); +} + + +btSoftBodyLinkData &btDX11SIMDAwareSoftBodySolver::getLinkData() +{ + // TODO: Consider setting link data to "changed" here + return m_linkData; +} + + + +void btDX11SIMDAwareSoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate) +{ + if(forceUpdate || m_softBodySet.size() != softBodies.size() ) + { + // Have a change in the soft body set so update, reloading all the data + getVertexData().clear(); + getTriangleData().clear(); + getLinkData().clear(); + m_softBodySet.resize(0); + + + for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex ) + { + btSoftBody *softBody = softBodies[ softBodyIndex ]; + using Vectormath::Aos::Matrix3; + using Vectormath::Aos::Point3; + + // Create SoftBody that will store the information within the solver + btAcceleratedSoftBodyInterface *newSoftBody = new btAcceleratedSoftBodyInterface( softBody ); + m_softBodySet.push_back( newSoftBody ); + + m_perClothAcceleration.push_back( toVector3(softBody->getWorldInfo()->m_gravity) ); + m_perClothDampingFactor.push_back(softBody->m_cfg.kDP); + m_perClothVelocityCorrectionCoefficient.push_back( softBody->m_cfg.kVCF ); + m_perClothLiftFactor.push_back( softBody->m_cfg.kLF ); + m_perClothDragFactor.push_back( softBody->m_cfg.kDG ); + m_perClothMediumDensity.push_back(softBody->getWorldInfo()->air_density); + // Simple init values. Actually we'll put 0 and -1 into them at the appropriate time + m_perClothMinBounds.push_back( UIntVector3( 0, 0, 0 ) ); + m_perClothMaxBounds.push_back( UIntVector3( UINT_MAX, UINT_MAX, UINT_MAX ) ); + m_perClothFriction.push_back( softBody->getFriction() ); + m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) ); + + // Add space for new vertices and triangles in the default solver for now + // TODO: Include space here for tearing too later + int firstVertex = getVertexData().getNumVertices(); + int numVertices = softBody->m_nodes.size(); + // Round maxVertices to a multiple of the workgroup size so we know we're safe to run over in a given group + // maxVertices can be increased to allow tearing, but should be used sparingly because these extra verts will always be processed + int maxVertices = GROUP_SIZE*((numVertices+GROUP_SIZE)/GROUP_SIZE); + // Allocate space for new vertices in all the vertex arrays + getVertexData().createVertices( numVertices, softBodyIndex, maxVertices ); + + int firstTriangle = getTriangleData().getNumTriangles(); + int numTriangles = softBody->m_faces.size(); + int maxTriangles = numTriangles; + getTriangleData().createTriangles( maxTriangles ); + + // Copy vertices from softbody into the solver + for( int vertex = 0; vertex < numVertices; ++vertex ) + { + Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ()); + btSoftBodyVertexData::VertexDescription desc; + + // TODO: Position in the softbody might be pre-transformed + // or we may need to adapt for the pose. + //desc.setPosition( cloth.getMeshTransform()*multPoint ); + desc.setPosition( multPoint ); + + float vertexInverseMass = softBody->m_nodes[vertex].m_im; + desc.setInverseMass(vertexInverseMass); + getVertexData().setVertexAt( desc, firstVertex + vertex ); + } + + // Copy triangles similarly + // We're assuming here that vertex indices are based on the firstVertex rather than the entire scene + for( int triangle = 0; triangle < numTriangles; ++triangle ) + { + // Note that large array storage is relative to the array not to the cloth + // So we need to add firstVertex to each value + int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0])); + int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0])); + int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0])); + btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex); + getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle ); + + // Increase vertex triangle counts for this triangle + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex0)++; + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex1)++; + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex2)++; + } + + int firstLink = getLinkData().getNumLinks(); + int numLinks = softBody->m_links.size(); + int maxLinks = numLinks; + + // Allocate space for the links + getLinkData().createLinks( numLinks ); + + // Add the links + for( int link = 0; link < numLinks; ++link ) + { + int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]); + int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]); + + btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST); + newLink.setLinkStrength(1.f); + getLinkData().setLinkAt(newLink, firstLink + link); + } + + newSoftBody->setFirstVertex( firstVertex ); + newSoftBody->setFirstTriangle( firstTriangle ); + newSoftBody->setNumVertices( numVertices ); + newSoftBody->setMaxVertices( maxVertices ); + newSoftBody->setNumTriangles( numTriangles ); + newSoftBody->setMaxTriangles( maxTriangles ); + newSoftBody->setFirstLink( firstLink ); + newSoftBody->setNumLinks( numLinks ); + } + + + + updateConstants(0.f); + + + m_linkData.generateBatches(); + m_triangleData.generateBatches(); + + + // Build the shaders to match the batching parameters + buildShaders(); + } + +} + + + +void btDX11SIMDAwareSoftBodySolver::solveConstraints( float solverdt ) +{ + + //std::cerr << "'GPU' solve constraints\n"; + using Vectormath::Aos::Vector3; + using Vectormath::Aos::Point3; + using Vectormath::Aos::lengthSqr; + using Vectormath::Aos::dot; + + // Prepare links + int numLinks = m_linkData.getNumLinks(); + int numVertices = m_vertexData.getNumVertices(); + + float kst = 1.f; + float ti = 0.f; + + + m_dx11PerClothDampingFactor.moveToGPU(); + m_dx11PerClothVelocityCorrectionCoefficient.moveToGPU(); + + + + // Ensure data is on accelerator + m_linkData.moveToAccelerator(); + m_vertexData.moveToAccelerator(); + + + + prepareCollisionConstraints(); + + + // Solve drift + for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) + { + + for( int i = 0; i < m_linkData.m_wavefrontBatchStartLengths.size(); ++i ) + { + int startWave = m_linkData.m_wavefrontBatchStartLengths[i].start; + int numWaves = m_linkData.m_wavefrontBatchStartLengths[i].length; + + solveLinksForPosition( startWave, numWaves, kst, ti ); + } + + } // for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) + + + + + // At this point assume that the force array is blank - we will overwrite it + solveCollisionsAndUpdateVelocities( 1.f/solverdt ); + +} // btDX11SIMDAwareSoftBodySolver::solveConstraints + + +void btDX11SIMDAwareSoftBodySolver::updateConstants( float timeStep ) +{ + using namespace Vectormath::Aos; + + if( m_updateSolverConstants ) + { + m_updateSolverConstants = false; + + // Will have to redo this if we change the structure (tear, maybe) or various other possible changes + + // Initialise link constants + const int numLinks = m_linkData.getNumLinks(); + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair &vertices( m_linkData.getVertexPair(linkIndex) ); + m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 ))); + float invMass0 = m_vertexData.getInverseMass(vertices.vertex0); + float invMass1 = m_vertexData.getInverseMass(vertices.vertex1); + float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex); + float massLSC = (invMass0 + invMass1)/linearStiffness; + m_linkData.getMassLSC(linkIndex) = massLSC; + float restLength = m_linkData.getRestLength(linkIndex); + float restLengthSquared = restLength*restLength; + m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared; + } + } +} // btDX11SIMDAwareSoftBodySolver::updateConstants + +////////////////////////////////////// +// Kernel dispatches + + +void btDX11SIMDAwareSoftBodySolver::solveLinksForPosition( int startWave, int numWaves, float kst, float ti ) +{ + + + m_vertexData.moveToAccelerator(); + m_linkData.moveToAccelerator(); + + // Copy kernel parameters to GPU + SolvePositionsFromLinksKernelCB constBuffer; + + // Set the first wave of the batch and the number of waves + constBuffer.startWave = startWave; + constBuffer.numWaves = numWaves; + + constBuffer.kst = kst; + constBuffer.ti = ti; + + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( solvePositionsFromLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(SolvePositionsFromLinksKernelCB) ); + m_dx11Context->Unmap( solvePositionsFromLinksKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &solvePositionsFromLinksKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11NumBatchesAndVerticesWithinWaves.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11WavefrontVerticesGlobalAddresses.getSRV()) ); + m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) ); + m_dx11Context->CSSetShaderResources( 3, 1, &(m_linkData.m_dx11LinkVerticesLocalAddresses.getSRV()) ); + m_dx11Context->CSSetShaderResources( 4, 1, &(m_linkData.m_dx11LinksMassLSC.getSRV()) ); + m_dx11Context->CSSetShaderResources( 5, 1, &(m_linkData.m_dx11LinksRestLengthSquared.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( solvePositionsFromLinksKernel.kernel, NULL, 0 ); + + int numBlocks = ((constBuffer.numWaves + WAVEFRONT_BLOCK_MULTIPLIER - 1) / WAVEFRONT_BLOCK_MULTIPLIER ); + m_dx11Context->Dispatch(numBlocks , 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 5, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SIMDAwareSoftBodySolver::solveLinksForPosition + + + +// End kernel dispatches +///////////////////////////////////// + + + + + + + + + +bool btDX11SIMDAwareSoftBodySolver::buildShaders() +{ + // Ensure current kernels are released first + releaseKernels(); + + bool returnVal = true; + + + if( m_shadersInitialized ) + return true; + + + updatePositionsFromVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdatePositionsFromVelocitiesHLSLString, "UpdatePositionsFromVelocitiesKernel", sizeof(UpdatePositionsFromVelocitiesCB) ); + if( !updatePositionsFromVelocitiesKernel.constBuffer ) + returnVal = false; + + char maxVerticesPerWavefront[20]; + char maxBatchesPerWavefront[20]; + char waveFrontSize[20]; + char waveFrontBlockMultiplier[20]; + char blockSize[20]; + + sprintf(maxVerticesPerWavefront, "%d", m_linkData.getMaxVerticesPerWavefront()); + sprintf(maxBatchesPerWavefront, "%d", m_linkData.getMaxBatchesPerWavefront()); + sprintf(waveFrontSize, "%d", m_linkData.getWavefrontSize()); + sprintf(waveFrontBlockMultiplier, "%d", WAVEFRONT_BLOCK_MULTIPLIER); + sprintf(blockSize, "%d", WAVEFRONT_BLOCK_MULTIPLIER*m_linkData.getWavefrontSize()); + + D3D10_SHADER_MACRO solvePositionsMacros[6] = { "MAX_NUM_VERTICES_PER_WAVE", maxVerticesPerWavefront, "MAX_BATCHES_PER_WAVE", maxBatchesPerWavefront, "WAVEFRONT_SIZE", waveFrontSize, "WAVEFRONT_BLOCK_MULTIPLIER", waveFrontBlockMultiplier, "BLOCK_SIZE", blockSize, 0, 0 }; + + solvePositionsFromLinksKernel = dxFunctions.compileComputeShaderFromString( SolvePositionsSIMDBatchedHLSLString, "SolvePositionsFromLinksKernel", sizeof(SolvePositionsFromLinksKernelCB), solvePositionsMacros ); + if( !solvePositionsFromLinksKernel.constBuffer ) + returnVal = false; + + updateVelocitiesFromPositionsWithVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdateNodesHLSLString, "updateVelocitiesFromPositionsWithVelocitiesKernel", sizeof(UpdateVelocitiesFromPositionsWithVelocitiesCB) ); + if( !updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer ) + returnVal = false; + updateVelocitiesFromPositionsWithoutVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdatePositionsHLSLString, "updateVelocitiesFromPositionsWithoutVelocitiesKernel", sizeof(UpdateVelocitiesFromPositionsWithoutVelocitiesCB)); + if( !updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer ) + returnVal = false; + integrateKernel = dxFunctions.compileComputeShaderFromString( IntegrateHLSLString, "IntegrateKernel", sizeof(IntegrateCB) ); + if( !integrateKernel.constBuffer ) + returnVal = false; + applyForcesKernel = dxFunctions.compileComputeShaderFromString( ApplyForcesHLSLString, "ApplyForcesKernel", sizeof(ApplyForcesCB) ); + if( !applyForcesKernel.constBuffer ) + returnVal = false; + solveCollisionsAndUpdateVelocitiesKernel = dxFunctions.compileComputeShaderFromString( SolveCollisionsAndUpdateVelocitiesHLSLString, "SolveCollisionsAndUpdateVelocitiesKernel", sizeof(SolveCollisionsAndUpdateVelocitiesCB) ); + if( !solveCollisionsAndUpdateVelocitiesKernel.constBuffer ) + returnVal = false; + resetNormalsAndAreasKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "ResetNormalsAndAreasKernel", sizeof(UpdateSoftBodiesCB) ); + if( !resetNormalsAndAreasKernel.constBuffer ) + returnVal = false; + normalizeNormalsAndAreasKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "NormalizeNormalsAndAreasKernel", sizeof(UpdateSoftBodiesCB) ); + if( !normalizeNormalsAndAreasKernel.constBuffer ) + returnVal = false; + updateSoftBodiesKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "UpdateSoftBodiesKernel", sizeof(UpdateSoftBodiesCB) ); + if( !updateSoftBodiesKernel.constBuffer ) + returnVal = false; + + computeBoundsKernel = dxFunctions.compileComputeShaderFromString( ComputeBoundsHLSLString, "ComputeBoundsKernel", sizeof(ComputeBoundsCB) ); + if( !computeBoundsKernel.constBuffer ) + returnVal = false; + + if( returnVal ) + m_shadersInitialized = true; + + return returnVal; +} // btDX11SIMDAwareSoftBodySolver::buildShaders + +static Vectormath::Aos::Transform3 toTransform3( const btTransform &transform ) +{ + Vectormath::Aos::Transform3 outTransform; + outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0))); + outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1))); + outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2))); + outTransform.setCol(3, toVector3(transform.getOrigin())); + return outTransform; +} + + + + + + + + + + + + +static void generateBatchesOfWavefronts( btAlignedObjectArray < btAlignedObjectArray > &linksForWavefronts, btSoftBodyLinkData &linkData, int numVertices, btAlignedObjectArray < btAlignedObjectArray > &wavefrontBatches ) +{ + // A per-batch map of truth values stating whether a given vertex is in that batch + // This allows us to significantly optimize the batching + btAlignedObjectArray > mapOfVerticesInBatches; + + for( int waveIndex = 0; waveIndex < linksForWavefronts.size(); ++waveIndex ) + { + btAlignedObjectArray &wavefront( linksForWavefronts[waveIndex] ); + + int batch = 0; + bool placed = false; + while( batch < wavefrontBatches.size() && !placed ) + { + // Test the current batch, see if this wave shares any vertex with the waves in the batch + bool foundSharedVertex = false; + for( int link = 0; link < wavefront.size(); ++link ) + { + btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); + if( (mapOfVerticesInBatches[batch])[vertices.vertex0] || (mapOfVerticesInBatches[batch])[vertices.vertex1] ) + { + foundSharedVertex = true; + } + } + + if( !foundSharedVertex ) + { + wavefrontBatches[batch].push_back( waveIndex ); + // Insert vertices into this batch too + for( int link = 0; link < wavefront.size(); ++link ) + { + btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); + (mapOfVerticesInBatches[batch])[vertices.vertex0] = true; + (mapOfVerticesInBatches[batch])[vertices.vertex1] = true; + } + placed = true; + } + batch++; + } + if( batch == wavefrontBatches.size() && !placed ) + { + wavefrontBatches.resize( batch + 1 ); + wavefrontBatches[batch].push_back( waveIndex ); + + // And resize map as well + mapOfVerticesInBatches.resize( batch + 1 ); + + // Resize maps with total number of vertices + mapOfVerticesInBatches[batch].resize( numVertices+1, false ); + + // Insert vertices into this batch too + for( int link = 0; link < wavefront.size(); ++link ) + { + btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); + (mapOfVerticesInBatches[batch])[vertices.vertex0] = true; + (mapOfVerticesInBatches[batch])[vertices.vertex1] = true; + } + } + } + mapOfVerticesInBatches.clear(); +} + +// Function to remove an object from a vector maintaining correct ordering of the vector +template< typename T > static void removeFromVector( btAlignedObjectArray< T > &vectorToUpdate, int indexToRemove ) +{ + int currentSize = vectorToUpdate.size(); + for( int i = indexToRemove; i < (currentSize-1); ++i ) + { + vectorToUpdate[i] = vectorToUpdate[i+1]; + } + if( currentSize > 0 ) + vectorToUpdate.resize( currentSize - 1 ); +} + +/** + * Insert element into vectorToUpdate at index index. + */ +template< typename T > static void insertAtIndex( btAlignedObjectArray< T > &vectorToUpdate, int index, T element ) +{ + vectorToUpdate.resize( vectorToUpdate.size() + 1 ); + for( int i = (vectorToUpdate.size() - 1); i > index; --i ) + { + vectorToUpdate[i] = vectorToUpdate[i-1]; + } + vectorToUpdate[index] = element; +} + +/** + * Insert into btAlignedObjectArray assuming the array is ordered and maintaining both ordering and uniqueness. + * ie it treats vectorToUpdate as an ordered set. + */ +template< typename T > static void insertUniqueAndOrderedIntoVector( btAlignedObjectArray &vectorToUpdate, T element ) +{ + int index = 0; + while( index < vectorToUpdate.size() && vectorToUpdate[index] < element ) + { + index++; + } + if( index == vectorToUpdate.size() || vectorToUpdate[index] != element ) + insertAtIndex( vectorToUpdate, index, element ); +} + +static void generateLinksPerVertex( int numVertices, btSoftBodyLinkData &linkData, btAlignedObjectArray< int > &listOfLinksPerVertex, btAlignedObjectArray &numLinksPerVertex, int &maxLinks ) +{ + for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); + numLinksPerVertex[nodes.vertex0]++; + numLinksPerVertex[nodes.vertex1]++; + } + int maxLinksPerVertex = 0; + for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex ) + { + maxLinksPerVertex = btMax(numLinksPerVertex[vertexIndex], maxLinksPerVertex); + } + maxLinks = maxLinksPerVertex; + + btAlignedObjectArray< int > linksFoundPerVertex; + linksFoundPerVertex.resize( numVertices, 0 ); + + listOfLinksPerVertex.resize( maxLinksPerVertex * numVertices ); + + for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); + { + // Do vertex 0 + int vertexIndex = nodes.vertex0; + int linkForVertex = linksFoundPerVertex[nodes.vertex0]; + int linkAddress = vertexIndex * maxLinksPerVertex + linkForVertex; + + listOfLinksPerVertex[linkAddress] = linkIndex; + + linksFoundPerVertex[nodes.vertex0] = linkForVertex + 1; + } + { + // Do vertex 1 + int vertexIndex = nodes.vertex1; + int linkForVertex = linksFoundPerVertex[nodes.vertex1]; + int linkAddress = vertexIndex * maxLinksPerVertex + linkForVertex; + + listOfLinksPerVertex[linkAddress] = linkIndex; + + linksFoundPerVertex[nodes.vertex1] = linkForVertex + 1; + } + } +} + +static void computeBatchingIntoWavefronts( + btSoftBodyLinkData &linkData, + int wavefrontSize, + int linksPerWorkItem, + int maxLinksPerWavefront, + btAlignedObjectArray < btAlignedObjectArray > &linksForWavefronts, + btAlignedObjectArray< btAlignedObjectArray < btAlignedObjectArray > > &batchesWithinWaves, /* wave, batch, links in batch */ + btAlignedObjectArray< btAlignedObjectArray< int > > &verticesForWavefronts /* wavefront, vertex */ + ) +{ + + + // Attempt generation of larger batches of links. + btAlignedObjectArray< bool > processedLink; + processedLink.resize( linkData.getNumLinks() ); + btAlignedObjectArray< int > listOfLinksPerVertex; + int maxLinksPerVertex = 0; + + // Count num vertices + int numVertices = 0; + for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); + numVertices = btMax( numVertices, nodes.vertex0 + 1 ); + numVertices = btMax( numVertices, nodes.vertex1 + 1 ); + } + + // Need list of links per vertex + // Compute valence of each vertex + btAlignedObjectArray numLinksPerVertex; + numLinksPerVertex.resize(0); + numLinksPerVertex.resize( numVertices, 0 ); + + generateLinksPerVertex( numVertices, linkData, listOfLinksPerVertex, numLinksPerVertex, maxLinksPerVertex ); + + + // At this point we know what links we have for each vertex so we can start batching + + // We want a vertex to start with, let's go with 0 + int currentVertex = 0; + int linksProcessed = 0; + + btAlignedObjectArray verticesToProcess; + + while( linksProcessed < linkData.getNumLinks() ) + { + // Next wavefront + int nextWavefront = linksForWavefronts.size(); + linksForWavefronts.resize( nextWavefront + 1 ); + btAlignedObjectArray &linksForWavefront(linksForWavefronts[nextWavefront]); + verticesForWavefronts.resize( nextWavefront + 1 ); + btAlignedObjectArray &vertexSet( verticesForWavefronts[nextWavefront] ); + + linksForWavefront.resize(0); + + // Loop to find enough links to fill the wavefront + // Stopping if we either run out of links, or fill it + while( linksProcessed < linkData.getNumLinks() && linksForWavefront.size() < maxLinksPerWavefront ) + { + // Go through the links for the current vertex + for( int link = 0; link < numLinksPerVertex[currentVertex] && linksForWavefront.size() < maxLinksPerWavefront; ++link ) + { + int linkAddress = currentVertex * maxLinksPerVertex + link; + int linkIndex = listOfLinksPerVertex[linkAddress]; + + // If we have not already processed this link, add it to the wavefront + // Claim it as another processed link + // Add the vertex at the far end to the list of vertices to process. + if( !processedLink[linkIndex] ) + { + linksForWavefront.push_back( linkIndex ); + linksProcessed++; + processedLink[linkIndex] = true; + int v0 = linkData.getVertexPair(linkIndex).vertex0; + int v1 = linkData.getVertexPair(linkIndex).vertex1; + if( v0 == currentVertex ) + verticesToProcess.push_back( v1 ); + else + verticesToProcess.push_back( v0 ); + } + } + if( verticesToProcess.size() > 0 ) + { + // Get the element on the front of the queue and remove it + currentVertex = verticesToProcess[0]; + removeFromVector( verticesToProcess, 0 ); + } else { + // If we've not yet processed all the links, find the first unprocessed one + // and select one of its vertices as the current vertex + if( linksProcessed < linkData.getNumLinks() ) + { + int searchLink = 0; + while( processedLink[searchLink] ) + searchLink++; + currentVertex = linkData.getVertexPair(searchLink).vertex0; + } + } + } + + // We have either finished or filled a wavefront + for( int link = 0; link < linksForWavefront.size(); ++link ) + { + int v0 = linkData.getVertexPair( linksForWavefront[link] ).vertex0; + int v1 = linkData.getVertexPair( linksForWavefront[link] ).vertex1; + insertUniqueAndOrderedIntoVector( vertexSet, v0 ); + insertUniqueAndOrderedIntoVector( vertexSet, v1 ); + } + // Iterate over links mapped to the wave and batch those + // We can run a batch on each cycle trivially + + batchesWithinWaves.resize( batchesWithinWaves.size() + 1 ); + btAlignedObjectArray < btAlignedObjectArray > &batchesWithinWave( batchesWithinWaves[batchesWithinWaves.size()-1] ); + + + for( int link = 0; link < linksForWavefront.size(); ++link ) + { + int linkIndex = linksForWavefront[link]; + btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( linkIndex ); + + int batch = 0; + bool placed = false; + while( batch < batchesWithinWave.size() && !placed ) + { + bool foundSharedVertex = false; + if( batchesWithinWave[batch].size() >= wavefrontSize ) + { + // If we have already filled this batch, move on to another + foundSharedVertex = true; + } else { + for( int link2 = 0; link2 < batchesWithinWave[batch].size(); ++link2 ) + { + btSoftBodyLinkData::LinkNodePair vertices2 = linkData.getVertexPair( (batchesWithinWave[batch])[link2] ); + + if( vertices.vertex0 == vertices2.vertex0 || + vertices.vertex1 == vertices2.vertex0 || + vertices.vertex0 == vertices2.vertex1 || + vertices.vertex1 == vertices2.vertex1 ) + { + foundSharedVertex = true; + break; + } + } + } + if( !foundSharedVertex ) + { + batchesWithinWave[batch].push_back( linkIndex ); + placed = true; + } else { + ++batch; + } + } + if( batch == batchesWithinWave.size() && !placed ) + { + batchesWithinWave.resize( batch + 1 ); + batchesWithinWave[batch].push_back( linkIndex ); + } + } + + } + +} + +void btSoftBodyLinkDataDX11SIMDAware::generateBatches() +{ + btAlignedObjectArray < btAlignedObjectArray > linksForWavefronts; + btAlignedObjectArray < btAlignedObjectArray > wavefrontBatches; + btAlignedObjectArray< btAlignedObjectArray < btAlignedObjectArray > > batchesWithinWaves; + btAlignedObjectArray< btAlignedObjectArray< int > > verticesForWavefronts; // wavefronts, vertices in wavefront as an ordered set + + // Group the links into wavefronts + computeBatchingIntoWavefronts( *this, m_wavefrontSize, m_linksPerWorkItem, m_maxLinksPerWavefront, linksForWavefronts, batchesWithinWaves, verticesForWavefronts ); + + + // Batch the wavefronts + generateBatchesOfWavefronts( linksForWavefronts, *this, m_maxVertex, wavefrontBatches ); + + m_numWavefronts = linksForWavefronts.size(); + + // At this point we have a description of which links we need to process in each wavefront + + // First correctly fill the batch ranges vector + int numBatches = wavefrontBatches.size(); + m_wavefrontBatchStartLengths.resize(0); + int prefixSum = 0; + for( int batchIndex = 0; batchIndex < numBatches; ++batchIndex ) + { + int wavesInBatch = wavefrontBatches[batchIndex].size(); + int nextPrefixSum = prefixSum + wavesInBatch; + m_wavefrontBatchStartLengths.push_back( BatchPair( prefixSum, nextPrefixSum - prefixSum ) ); + + prefixSum += wavesInBatch; + } + + // Also find max number of batches within a wave + m_maxBatchesWithinWave = 0; + m_maxVerticesWithinWave = 0; + m_numBatchesAndVerticesWithinWaves.resize( m_numWavefronts ); + for( int waveIndex = 0; waveIndex < m_numWavefronts; ++waveIndex ) + { + // See if the number of batches in this wave is greater than the current maxium + int batchesInCurrentWave = batchesWithinWaves[waveIndex].size(); + int verticesInCurrentWave = verticesForWavefronts[waveIndex].size(); + m_maxBatchesWithinWave = btMax( batchesInCurrentWave, m_maxBatchesWithinWave ); + m_maxVerticesWithinWave = btMax( verticesInCurrentWave, m_maxVerticesWithinWave ); + } + + // Add padding values both for alignment and as dudd addresses within LDS to compute junk rather than branch around + m_maxVerticesWithinWave = 16*((m_maxVerticesWithinWave/16)+2); + + // Now we know the maximum number of vertices per-wave we can resize the global vertices array + m_wavefrontVerticesGlobalAddresses.resize( m_maxVerticesWithinWave * m_numWavefronts ); + + // Grab backup copies of all the link data arrays for the sorting process + btAlignedObjectArray m_links_Backup(m_links); + btAlignedObjectArray m_linkStrength_Backup(m_linkStrength); + btAlignedObjectArray m_linksMassLSC_Backup(m_linksMassLSC); + btAlignedObjectArray m_linksRestLengthSquared_Backup(m_linksRestLengthSquared); + //btAlignedObjectArray m_linksCLength_Backup(m_linksCLength); + //btAlignedObjectArray m_linksLengthRatio_Backup(m_linksLengthRatio); + btAlignedObjectArray m_linksRestLength_Backup(m_linksRestLength); + btAlignedObjectArray m_linksMaterialLinearStiffnessCoefficient_Backup(m_linksMaterialLinearStiffnessCoefficient); + + // Resize to a wavefront sized batch per batch per wave so we get perfectly coherent memory accesses. + m_links.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linkVerticesLocalAddresses.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linkStrength.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linksMassLSC.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linksRestLengthSquared.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linksRestLength.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linksMaterialLinearStiffnessCoefficient.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + + // Then re-order links into wavefront blocks + + // Total number of wavefronts moved. This will decide the ordering of sorted wavefronts. + int wavefrontCount = 0; + + // Iterate over batches of wavefronts, then wavefronts in the batch + for( int batchIndex = 0; batchIndex < numBatches; ++batchIndex ) + { + btAlignedObjectArray &batch( wavefrontBatches[batchIndex] ); + int wavefrontsInBatch = batch.size(); + + + for( int wavefrontIndex = 0; wavefrontIndex < wavefrontsInBatch; ++wavefrontIndex ) + { + + int originalWavefrontIndex = batch[wavefrontIndex]; + btAlignedObjectArray< int > &wavefrontVertices( verticesForWavefronts[originalWavefrontIndex] ); + int verticesUsedByWavefront = wavefrontVertices.size(); + + // Copy the set of vertices into the correctly structured array for use on the device + // Fill the non-vertices with -1s + // so we can mask out those reads + for( int vertex = 0; vertex < verticesUsedByWavefront; ++vertex ) + { + m_wavefrontVerticesGlobalAddresses[m_maxVerticesWithinWave * wavefrontCount + vertex] = wavefrontVertices[vertex]; + } + for( int vertex = verticesUsedByWavefront; vertex < m_maxVerticesWithinWave; ++vertex ) + { + m_wavefrontVerticesGlobalAddresses[m_maxVerticesWithinWave * wavefrontCount + vertex] = -1; + } + + // Obtain the set of batches within the current wavefront + btAlignedObjectArray < btAlignedObjectArray > &batchesWithinWavefront( batchesWithinWaves[originalWavefrontIndex] ); + // Set the size of the batches for use in the solver, correctly ordered + NumBatchesVerticesPair batchesAndVertices; + batchesAndVertices.numBatches = batchesWithinWavefront.size(); + batchesAndVertices.numVertices = verticesUsedByWavefront; + m_numBatchesAndVerticesWithinWaves[wavefrontCount] = batchesAndVertices; + + + // Now iterate over batches within the wavefront to structure the links correctly + for( int wavefrontBatch = 0; wavefrontBatch < batchesWithinWavefront.size(); ++wavefrontBatch ) + { + btAlignedObjectArray &linksInBatch( batchesWithinWavefront[wavefrontBatch] ); + int wavefrontBatchSize = linksInBatch.size(); + + int batchAddressInTarget = m_maxBatchesWithinWave * m_wavefrontSize * wavefrontCount + m_wavefrontSize * wavefrontBatch; + + for( int linkIndex = 0; linkIndex < wavefrontBatchSize; ++linkIndex ) + { + int originalLinkAddress = linksInBatch[linkIndex]; + // Reorder simple arrays trivially + m_links[batchAddressInTarget + linkIndex] = m_links_Backup[originalLinkAddress]; + m_linkStrength[batchAddressInTarget + linkIndex] = m_linkStrength_Backup[originalLinkAddress]; + m_linksMassLSC[batchAddressInTarget + linkIndex] = m_linksMassLSC_Backup[originalLinkAddress]; + m_linksRestLengthSquared[batchAddressInTarget + linkIndex] = m_linksRestLengthSquared_Backup[originalLinkAddress]; + m_linksRestLength[batchAddressInTarget + linkIndex] = m_linksRestLength_Backup[originalLinkAddress]; + m_linksMaterialLinearStiffnessCoefficient[batchAddressInTarget + linkIndex] = m_linksMaterialLinearStiffnessCoefficient_Backup[originalLinkAddress]; + + // The local address is more complicated. We need to work out where a given vertex will end up + // by searching the set of vertices for this link and using the index as the local address + btSoftBodyLinkData::LinkNodePair localPair; + btSoftBodyLinkData::LinkNodePair globalPair = m_links[batchAddressInTarget + linkIndex]; + localPair.vertex0 = wavefrontVertices.findLinearSearch( globalPair.vertex0 ); + localPair.vertex1 = wavefrontVertices.findLinearSearch( globalPair.vertex1 ); + m_linkVerticesLocalAddresses[batchAddressInTarget + linkIndex] = localPair; + } + for( int linkIndex = wavefrontBatchSize; linkIndex < m_wavefrontSize; ++linkIndex ) + { + // Put 0s into these arrays for padding for cleanliness + m_links[batchAddressInTarget + linkIndex] = btSoftBodyLinkData::LinkNodePair(0, 0); + m_linkStrength[batchAddressInTarget + linkIndex] = 0.f; + m_linksMassLSC[batchAddressInTarget + linkIndex] = 0.f; + m_linksRestLengthSquared[batchAddressInTarget + linkIndex] = 0.f; + m_linksRestLength[batchAddressInTarget + linkIndex] = 0.f; + m_linksMaterialLinearStiffnessCoefficient[batchAddressInTarget + linkIndex] = 0.f; + + + // For local addresses of junk data choose a set of addresses just above the range of valid ones + // and cycling tyhrough % 16 so that we don't have bank conficts between all dud addresses + // The valid addresses will do scatter and gather in the valid range, the junk ones should happily work + // off the end of that range so we need no control + btSoftBodyLinkData::LinkNodePair localPair; + localPair.vertex0 = verticesUsedByWavefront + (linkIndex % 16); + localPair.vertex1 = verticesUsedByWavefront + (linkIndex % 16); + m_linkVerticesLocalAddresses[batchAddressInTarget + linkIndex] = localPair; + } + + } + + + wavefrontCount++; + } + + + } + +} // void btSoftBodyLinkDataDX11SIMDAware::generateBatches() diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h new file mode 100644 index 0000000..554e40c --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h @@ -0,0 +1,81 @@ +/* +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 "vectormath/vmInclude.h" +#include "btSoftBodySolver_DX11.h" +#include "btSoftBodySolverVertexBuffer_DX11.h" +#include "btSoftBodySolverLinkData_DX11SIMDAware.h" +#include "btSoftBodySolverVertexData_DX11.h" +#include "btSoftBodySolverTriangleData_DX11.h" + + +#ifndef BT_SOFT_BODY_DX11_SOLVER_SIMDAWARE_H +#define BT_SOFT_BODY_DX11_SOLVER_SIMDAWARE_H + +class btDX11SIMDAwareSoftBodySolver : public btDX11SoftBodySolver +{ +protected: + struct SolvePositionsFromLinksKernelCB + { + int startWave; + int numWaves; + float kst; + float ti; + }; + + + /** Link data for all cloths. Note that this will be sorted batch-wise for efficient computation and m_linkAddresses will maintain the addressing. */ + btSoftBodyLinkDataDX11SIMDAware m_linkData; + + /** Variable to define whether we need to update solver constants on the next iteration */ + bool m_updateSolverConstants; + + + virtual bool buildShaders(); + + void updateConstants( float timeStep ); + + + ////////////////////////////////////// + // Kernel dispatches + + + void solveLinksForPosition( int startLink, int numLinks, float kst, float ti ); + + // End kernel dispatches + ///////////////////////////////////// + + + +public: + btDX11SIMDAwareSoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory = &D3DX11CompileFromMemory); + + virtual ~btDX11SIMDAwareSoftBodySolver(); + + virtual btSoftBodyLinkData &getLinkData(); + + virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false); + + virtual void solveConstraints( float solverdt ); + + virtual SolverTypes getSolverType() const + { + return DX_SIMD_SOLVER; + } + +}; + +#endif // #ifndef BT_SOFT_BODY_DX11_SOLVER_SIMDAWARE_H + diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua new file mode 100644 index 0000000..8f95f62 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua @@ -0,0 +1,23 @@ + +hasDX11 = findDirectX11() + +if (hasDX11) then + + project "BulletSoftBodyDX11Solvers" + + initDirectX11() + + kind "StaticLib" + + targetdir "../../../../lib" + + includedirs { + ".", + "../../.." + } + files { + "**.cpp", + "**.h" + } + +end diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt new file mode 100644 index 0000000..d2a56ba --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt @@ -0,0 +1,62 @@ + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${AMD_OPENCL_INCLUDES} +) + +ADD_DEFINITIONS(-DUSE_AMD_OPENCL) +ADD_DEFINITIONS(-DCL_PLATFORM_AMD) + + + +SET(BulletSoftBodyOpenCLSolvers_SRCS + ../btSoftBodySolver_OpenCL.cpp + ../btSoftBodySolver_OpenCLSIMDAware.cpp + ../btSoftBodySolverOutputCLtoGL.cpp +) + +SET(BulletSoftBodyOpenCLSolvers_HDRS + ../btSoftBodySolver_OpenCL.h + ../btSoftBodySolver_OpenCLSIMDAware.h + ../../Shared/btSoftBodySolverData.h + ../btSoftBodySolverVertexData_OpenCL.h + ../btSoftBodySolverTriangleData_OpenCL.h + ../btSoftBodySolverLinkData_OpenCL.h + ../btSoftBodySolverLinkData_OpenCLSIMDAware.h + ../btSoftBodySolverBuffer_OpenCL.h + ../btSoftBodySolverVertexBuffer_OpenGL.h + ../btSoftBodySolverOutputCLtoGL.h +) + + + + +ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_AMD + ${BulletSoftBodyOpenCLSolvers_SRCS} + ${BulletSoftBodyOpenCLSolvers_HDRS} +) + +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_AMD PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_AMD PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_AMD BulletSoftBody) +ENDIF (BUILD_SHARED_LIBS) + + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_AMD DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_AMD DESTINATION lib${LIB_SUFFIX}) +#headers are already installed by BulletMultiThreaded library + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_AMD PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_AMD PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua new file mode 100644 index 0000000..05a9290 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua @@ -0,0 +1,27 @@ + +hasCL = findOpenCL_AMD() + +if (hasCL) then + + project "BulletSoftBodySolvers_OpenCL_AMD" + + defines { "USE_AMD_OPENCL","CL_PLATFORM_AMD"} + + initOpenCL_AMD() + + kind "StaticLib" + + targetdir "../../../../../lib" + + includedirs { + ".", + "../../../..", + "../../../../../Glut" + } + files { + "../btSoftBodySolver_OpenCL.cpp", + "../btSoftBodySolver_OpenCLSIMDAware.cpp", + "../btSoftBodySolverOutputCLtoGL.cpp" + } + +end diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt new file mode 100644 index 0000000..3db66c9 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt @@ -0,0 +1,77 @@ + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +) + + + + +SET(BulletSoftBodyOpenCLSolvers_SRCS + ../btSoftBodySolver_OpenCL.cpp + ../btSoftBodySolver_OpenCLSIMDAware.cpp +) + +SET(BulletSoftBodyOpenCLSolvers_HDRS + ../btSoftBodySolver_OpenCL.h + ../../Shared/btSoftBodySolverData.h + ../btSoftBodySolverVertexData_OpenCL.h + ../btSoftBodySolverTriangleData_OpenCL.h + ../btSoftBodySolverLinkData_OpenCL.h + ../btSoftBodySolverBuffer_OpenCL.h +) + +# OpenCL and HLSL Shaders. +# Build rules generated to stringify these into headers +# which are needed by some of the sources +SET(BulletSoftBodyOpenCLSolvers_Shaders +# OutputToVertexArray + UpdateNormals + Integrate + UpdatePositions + UpdateNodes + SolvePositions + UpdatePositionsFromVelocities + ApplyForces + PrepareLinks + VSolveLinks +) + +foreach(f ${BulletSoftBodyOpenCLSolvers_Shaders}) + LIST(APPEND BulletSoftBodyOpenCLSolvers_OpenCLC "../OpenCLC10/${f}.cl") +endforeach(f) + + + +ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_Apple + ${BulletSoftBodyOpenCLSolvers_SRCS} + ${BulletSoftBodyOpenCLSolvers_HDRS} + ${BulletSoftBodyOpenCLSolvers_OpenCLC} +) + +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + IF (APPLE AND (BUILD_SHARED_LIBS OR FRAMEWORK) ) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES LINK_FLAGS "-framework OpenCL") + ENDIF (APPLE AND (BUILD_SHARED_LIBS OR FRAMEWORK) ) + TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_Apple BulletSoftBody) +ENDIF (BUILD_SHARED_LIBS) + + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Apple DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Apple DESTINATION lib${LIB_SUFFIX}) +#headers are already installed by BulletMultiThreaded library + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt new file mode 100644 index 0000000..64b029f --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt @@ -0,0 +1,17 @@ + SUBDIRS( MiniCL ) + +IF(BUILD_INTEL_OPENCL_DEMOS) + SUBDIRS(Intel) +ENDIF() + +IF(BUILD_AMD_OPENCL_DEMOS) + SUBDIRS(AMD) +ENDIF() + +IF(BUILD_NVIDIA_OPENCL_DEMOS) + SUBDIRS(NVidia) +ENDIF() + +IF(APPLE AND OPENCL_LIBRARY) + SUBDIRS(Apple) +ENDIF() diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt new file mode 100644 index 0000000..27d57f7 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt @@ -0,0 +1,82 @@ + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${INTEL_OPENCL_INCLUDES} +) + +ADD_DEFINITIONS(-DUSE_INTEL_OPENCL) +ADD_DEFINITIONS(-DCL_PLATFORM_INTEL) + + + +SET(BulletSoftBodyOpenCLSolvers_SRCS + ../btSoftBodySolver_OpenCL.cpp + ../btSoftBodySolver_OpenCLSIMDAware.cpp + ../btSoftBodySolverOutputCLtoGL.cpp +) + +SET(BulletSoftBodyOpenCLSolvers_HDRS + ../btSoftBodySolver_OpenCL.h + ../btSoftBodySolver_OpenCLSIMDAware.h + ../../Shared/btSoftBodySolverData.h + ../btSoftBodySolverVertexData_OpenCL.h + ../btSoftBodySolverTriangleData_OpenCL.h + ../btSoftBodySolverLinkData_OpenCL.h + ../btSoftBodySolverLinkData_OpenCLSIMDAware.h + ../btSoftBodySolverBuffer_OpenCL.h + ../btSoftBodySolverVertexBuffer_OpenGL.h + ../btSoftBodySolverOutputCLtoGL.h +) + +# OpenCL and HLSL Shaders. +# Build rules generated to stringify these into headers +# which are needed by some of the sources +SET(BulletSoftBodyOpenCLSolvers_Shaders +# OutputToVertexArray + UpdateNormals + Integrate + UpdatePositions + UpdateNodes + SolvePositions + UpdatePositionsFromVelocities + ApplyForces + PrepareLinks + VSolveLinks +) + +foreach(f ${BulletSoftBodyOpenCLSolvers_Shaders}) + LIST(APPEND BulletSoftBodyOpenCLSolvers_OpenCLC "../OpenCLC10/${f}.cl") +endforeach(f) + + + +ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_Intel + ${BulletSoftBodyOpenCLSolvers_SRCS} + ${BulletSoftBodyOpenCLSolvers_HDRS} + ${BulletSoftBodyOpenCLSolvers_OpenCLC} +) + +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Intel PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Intel PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_Intel BulletSoftBody) +ENDIF (BUILD_SHARED_LIBS) + + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Intel DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Intel DESTINATION lib${LIB_SUFFIX}) +#headers are already installed by BulletMultiThreaded library + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Intel PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Intel PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua new file mode 100644 index 0000000..7d88776 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua @@ -0,0 +1,27 @@ + +hasCL = findOpenCL_Intel() + +if (hasCL) then + + project "BulletSoftBodySolvers_OpenCL_Intel" + + defines { "USE_INTEL_OPENCL","CL_PLATFORM_INTEL"} + + initOpenCL_Intel() + + kind "StaticLib" + + targetdir "../../../../../lib" + + includedirs { + ".", + "../../../..", + "../../../../../Glut" + } + files { + "../btSoftBodySolver_OpenCL.cpp", + "../btSoftBodySolver_OpenCLSIMDAware.cpp", + "../btSoftBodySolverOutputCLtoGL.cpp" + } + +end diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt new file mode 100644 index 0000000..72d0a73 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt @@ -0,0 +1,75 @@ + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +) + +ADD_DEFINITIONS(-DUSE_MINICL) + + + + +SET(BulletSoftBodyOpenCLSolvers_SRCS + ../btSoftBodySolver_OpenCL.cpp +) + +SET(BulletSoftBodyOpenCLSolvers_HDRS + ../btSoftBodySolver_OpenCL.h + ../../Shared/btSoftBodySolverData.h + ../btSoftBodySolverVertexData_OpenCL.h + ../btSoftBodySolverTriangleData_OpenCL.h + ../btSoftBodySolverLinkData_OpenCL.h + ../btSoftBodySolverBuffer_OpenCL.h +) + +# OpenCL and HLSL Shaders. +# Build rules generated to stringify these into headers +# which are needed by some of the sources +SET(BulletSoftBodyOpenCLSolvers_Shaders +# OutputToVertexArray + UpdateNormals + Integrate + UpdatePositions + UpdateNodes + SolvePositions + UpdatePositionsFromVelocities + ApplyForces + PrepareLinks + VSolveLinks +) + +foreach(f ${BulletSoftBodyOpenCLSolvers_Shaders}) + LIST(APPEND BulletSoftBodyOpenCLSolvers_OpenCLC "../OpenCLC10/${f}.cl") +endforeach(f) + + + +ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_Mini + ${BulletSoftBodyOpenCLSolvers_SRCS} + ${BulletSoftBodyOpenCLSolvers_HDRS} + ${BulletSoftBodyOpenCLSolvers_OpenCLC} +) + +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Mini PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Mini PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_Mini MiniCL BulletMultiThreaded BulletSoftBody) +ENDIF (BUILD_SHARED_LIBS) + + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Mini DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Mini DESTINATION lib${LIB_SUFFIX}) +#headers are already installed by BulletMultiThreaded library + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Mini PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Mini PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp new file mode 100644 index 0000000..49ca12d --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp @@ -0,0 +1,249 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +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 + +#define MSTRINGIFY(A) A +#include "../OpenCLC10/ApplyForces.cl" +#include "../OpenCLC10/Integrate.cl" +#include "../OpenCLC10/PrepareLinks.cl" +#include "../OpenCLC10/SolvePositions.cl" +#include "../OpenCLC10/UpdateNodes.cl" +#include "../OpenCLC10/UpdateNormals.cl" +#include "../OpenCLC10/UpdatePositions.cl" +#include "../OpenCLC10/UpdatePositionsFromVelocities.cl" +#include "../OpenCLC10/VSolveLinks.cl" +#include "../OpenCLC10/UpdateFixedVertexPositions.cl" +//#include "../OpenCLC10/SolveCollisionsAndUpdateVelocities.cl" + + +MINICL_REGISTER(PrepareLinksKernel) +MINICL_REGISTER(VSolveLinksKernel) +MINICL_REGISTER(UpdatePositionsFromVelocitiesKernel) +MINICL_REGISTER(SolvePositionsFromLinksKernel) +MINICL_REGISTER(updateVelocitiesFromPositionsWithVelocitiesKernel) +MINICL_REGISTER(updateVelocitiesFromPositionsWithoutVelocitiesKernel) +MINICL_REGISTER(IntegrateKernel) +MINICL_REGISTER(ApplyForcesKernel) +MINICL_REGISTER(ResetNormalsAndAreasKernel) +MINICL_REGISTER(NormalizeNormalsAndAreasKernel) +MINICL_REGISTER(UpdateSoftBodiesKernel) +MINICL_REGISTER(UpdateFixedVertexPositions) + +float mydot3a(float4 a, float4 b) +{ + return a.x*b.x + a.y*b.y + a.z*b.z; +} + + +typedef struct +{ + int firstObject; + int endObject; +} CollisionObjectIndices; + +typedef struct +{ + float4 shapeTransform[4]; // column major 4x4 matrix + float4 linearVelocity; + float4 angularVelocity; + + int softBodyIdentifier; + int collisionShapeType; + + + // Shape information + // Compressed from the union + float radius; + float halfHeight; + int upAxis; + + float margin; + float friction; + + int padding0; + +} CollisionShapeDescription; + +// From btBroadphaseProxy.h +__constant int CAPSULE_SHAPE_PROXYTYPE = 10; + +// Multiply column-major matrix against vector +float4 matrixVectorMul( float4 matrix[4], float4 vector ) +{ + float4 returnVector; + float4 row0 = float4(matrix[0].x, matrix[1].x, matrix[2].x, matrix[3].x); + float4 row1 = float4(matrix[0].y, matrix[1].y, matrix[2].y, matrix[3].y); + float4 row2 = float4(matrix[0].z, matrix[1].z, matrix[2].z, matrix[3].z); + float4 row3 = float4(matrix[0].w, matrix[1].w, matrix[2].w, matrix[3].w); + returnVector.x = dot(row0, vector); + returnVector.y = dot(row1, vector); + returnVector.z = dot(row2, vector); + returnVector.w = dot(row3, vector); + return returnVector; +} + +__kernel void +SolveCollisionsAndUpdateVelocitiesKernel( + const int numNodes, + const float isolverdt, + __global int *g_vertexClothIdentifier, + __global float4 *g_vertexPreviousPositions, + __global float * g_perClothFriction, + __global float * g_clothDampingFactor, + __global CollisionObjectIndices * g_perClothCollisionObjectIndices, + __global CollisionShapeDescription * g_collisionObjectDetails, + __global float4 * g_vertexForces, + __global float4 *g_vertexVelocities, + __global float4 *g_vertexPositions GUID_ARG) +{ + int nodeID = get_global_id(0); + float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f); + + if( get_global_id(0) < numNodes ) + { + int clothIdentifier = g_vertexClothIdentifier[nodeID]; + + // Abort if this is not a valid cloth + if( clothIdentifier < 0 ) + return; + + + float4 position (g_vertexPositions[nodeID].xyz, 1.f); + float4 previousPosition (g_vertexPreviousPositions[nodeID].xyz, 1.f); + + float clothFriction = g_perClothFriction[clothIdentifier]; + float dampingFactor = g_clothDampingFactor[clothIdentifier]; + float velocityCoefficient = (1.f - dampingFactor); + float4 difference = position - previousPosition; + float4 velocity = difference*velocityCoefficient*isolverdt; + + CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier]; + + int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; + + if( numObjects > 0 ) + { + // We have some possible collisions to deal with + for( int collision = collisionObjectIndices.firstObject; collision < collisionObjectIndices.endObject; ++collision ) + { + CollisionShapeDescription shapeDescription = g_collisionObjectDetails[collision]; + float colliderFriction = shapeDescription.friction; + + if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE ) + { + // Colliding with a capsule + + float capsuleHalfHeight = shapeDescription.halfHeight; + float capsuleRadius = shapeDescription.radius; + float capsuleMargin = shapeDescription.margin; + int capsuleupAxis = shapeDescription.upAxis; + + // Four columns of worldTransform matrix + float4 worldTransform[4]; + worldTransform[0] = shapeDescription.shapeTransform[0]; + worldTransform[1] = shapeDescription.shapeTransform[1]; + worldTransform[2] = shapeDescription.shapeTransform[2]; + worldTransform[3] = shapeDescription.shapeTransform[3]; + + // Correctly define capsule centerline vector + float4 c1 (0.f, 0.f, 0.f, 1.f); + float4 c2 (0.f, 0.f, 0.f, 1.f); + c1.x = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 0 ); + c1.y = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 1 ); + c1.z = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 2 ); + c2.x = -c1.x; + c2.y = -c1.y; + c2.z = -c1.z; + + + float4 worldC1 = matrixVectorMul(worldTransform, c1); + float4 worldC2 = matrixVectorMul(worldTransform, c2); + float4 segment = (worldC2 - worldC1); + + // compute distance of tangent to vertex along line segment in capsule + float distanceAlongSegment = -( mydot3a( (worldC1 - position), segment ) / mydot3a(segment, segment) ); + + float4 closestPoint = (worldC1 + (segment * distanceAlongSegment)); + float distanceFromLine = length(position - closestPoint); + float distanceFromC1 = length(worldC1 - position); + float distanceFromC2 = length(worldC2 - position); + + // Final distance from collision, point to push from, direction to push in + // for impulse force + float dist; + float4 normalVector; + if( distanceAlongSegment < 0 ) + { + dist = distanceFromC1; + normalVector = float4(normalize(position - worldC1).xyz, 0.f); + } else if( distanceAlongSegment > 1.f ) { + dist = distanceFromC2; + normalVector = float4(normalize(position - worldC2).xyz, 0.f); + } else { + dist = distanceFromLine; + normalVector = float4(normalize(position - closestPoint).xyz, 0.f); + } + + float4 colliderLinearVelocity = shapeDescription.linearVelocity; + float4 colliderAngularVelocity = shapeDescription.angularVelocity; + float4 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position - float4(worldTransform[0].w, worldTransform[1].w, worldTransform[2].w, 0.f)); + + float minDistance = capsuleRadius + capsuleMargin; + + // In case of no collision, this is the value of velocity + velocity = (position - previousPosition) * velocityCoefficient * isolverdt; + + + // Check for a collision + if( dist < minDistance ) + { + // Project back to surface along normal + position = position + float4(normalVector*(minDistance - dist)*0.9f); + velocity = (position - previousPosition) * velocityCoefficient * isolverdt; + float4 relativeVelocity = velocity - velocityOfSurfacePoint; + + float4 p1 = normalize(cross(normalVector, segment)); + float4 p2 = normalize(cross(p1, normalVector)); + // Full friction is sum of velocities in each direction of plane + float4 frictionVector = p1*mydot3a(relativeVelocity, p1) + p2*mydot3a(relativeVelocity, p2); + + // Real friction is peak friction corrected by friction coefficients + frictionVector = frictionVector * (colliderFriction*clothFriction); + + float approachSpeed = dot(relativeVelocity, normalVector); + + if( approachSpeed <= 0.0f ) + forceOnVertex -= frictionVector; + } + } + } + } + + g_vertexVelocities[nodeID] = float4(velocity.xyz, 0.f); + + // Update external force + g_vertexForces[nodeID] = float4(forceOnVertex.xyz, 0.f); + + g_vertexPositions[nodeID] = float4(position.xyz, 0.f); + } +} + + +MINICL_REGISTER(SolveCollisionsAndUpdateVelocitiesKernel); + + + + diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt new file mode 100644 index 0000000..10ed90f --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt @@ -0,0 +1,81 @@ + +ADD_DEFINITIONS(-DUSE_NVIDIA_OPENCL) +ADD_DEFINITIONS(-DCL_PLATFORM_NVIDIA) + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${NVIDIA_OPENCL_INCLUDES} +) + + + +SET(BulletSoftBodyOpenCLSolvers_SRCS + ../btSoftBodySolver_OpenCL.cpp + ../btSoftBodySolver_OpenCLSIMDAware.cpp + ../btSoftBodySolverOutputCLtoGL.cpp +) + +SET(BulletSoftBodyOpenCLSolvers_HDRS + ../btSoftBodySolver_OpenCL.h + ../../Shared/btSoftBodySolverData.h + ../btSoftBodySolverVertexData_OpenCL.h + ../btSoftBodySolverTriangleData_OpenCL.h + ../btSoftBodySolverLinkData_OpenCL.h + ../btSoftBodySolverLinkData_OpenCLSIMDAware.h + ../btSoftBodySolverBuffer_OpenCL.h + ../btSoftBodySolverVertexBuffer_OpenGL.h + ../btSoftBodySolverOutputCLtoGL.h +) + +# OpenCL and HLSL Shaders. +# Build rules generated to stringify these into headers +# which are needed by some of the sources +SET(BulletSoftBodyOpenCLSolvers_Shaders +# OutputToVertexArray + UpdateNormals + Integrate + UpdatePositions + UpdateNodes + SolvePositions + UpdatePositionsFromVelocities + ApplyForces + PrepareLinks + VSolveLinks +) + +foreach(f ${BulletSoftBodyOpenCLSolvers_Shaders}) + LIST(APPEND BulletSoftBodyOpenCLSolvers_OpenCLC "../OpenCLC10/${f}.cl") +endforeach(f) + + + +ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_NVidia + ${BulletSoftBodyOpenCLSolvers_SRCS} + ${BulletSoftBodyOpenCLSolvers_HDRS} + ${BulletSoftBodyOpenCLSolvers_OpenCLC} +) + +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_NVidia PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_NVidia PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_NVidia BulletSoftBody BulletDynamics) +ENDIF (BUILD_SHARED_LIBS) + + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_NVidia DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_NVidia DESTINATION lib${LIB_SUFFIX}) +#headers are already installed by BulletMultiThreaded library + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_NVidia PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_NVidia PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua new file mode 100644 index 0000000..6e64547 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua @@ -0,0 +1,27 @@ + +hasCL = findOpenCL_NVIDIA() + +if (hasCL) then + + project "BulletSoftBodySolvers_OpenCL_NVIDIA" + + defines { "USE_NVIDIA_OPENCL","CL_PLATFORM_NVIDIA"} + + initOpenCL_NVIDIA() + + kind "StaticLib" + + targetdir "../../../../../lib" + + includedirs { + ".", + "../../../..", + "../../../../../Glut" + } + files { + "../btSoftBodySolver_OpenCL.cpp", + "../btSoftBodySolver_OpenCLSIMDAware.cpp", + "../btSoftBodySolverOutputCLtoGL.cpp" + } + +end diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl new file mode 100644 index 0000000..3d4d610 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl @@ -0,0 +1,102 @@ +MSTRINGIFY( + + +float adot3(float4 a, float4 b) +{ + return a.x*b.x + a.y*b.y + a.z*b.z; +} + +float alength3(float4 a) +{ + a.w = 0; + return length(a); +} + +float4 anormalize3(float4 a) +{ + a.w = 0; + return normalize(a); +} + +float4 projectOnAxis( float4 v, float4 a ) +{ + return (a*adot3(v, a)); +} + +__kernel void +ApplyForcesKernel( + const uint numNodes, + const float solverdt, + const float epsilon, + __global int * g_vertexClothIdentifier, + __global float4 * g_vertexNormal, + __global float * g_vertexArea, + __global float * g_vertexInverseMass, + __global float * g_clothLiftFactor, + __global float * g_clothDragFactor, + __global float4 * g_clothWindVelocity, + __global float4 * g_clothAcceleration, + __global float * g_clothMediumDensity, + __global float4 * g_vertexForceAccumulator, + __global float4 * g_vertexVelocity GUID_ARG) +{ + unsigned int nodeID = get_global_id(0); + if( nodeID < numNodes ) + { + int clothId = g_vertexClothIdentifier[nodeID]; + float nodeIM = g_vertexInverseMass[nodeID]; + + if( nodeIM > 0.0f ) + { + float4 nodeV = g_vertexVelocity[nodeID]; + float4 normal = g_vertexNormal[nodeID]; + float area = g_vertexArea[nodeID]; + float4 nodeF = g_vertexForceAccumulator[nodeID]; + + // Read per-cloth values + float4 clothAcceleration = g_clothAcceleration[clothId]; + float4 clothWindVelocity = g_clothWindVelocity[clothId]; + float liftFactor = g_clothLiftFactor[clothId]; + float dragFactor = g_clothDragFactor[clothId]; + float mediumDensity = g_clothMediumDensity[clothId]; + + // Apply the acceleration to the cloth rather than do this via a force + nodeV += (clothAcceleration*solverdt); + + g_vertexVelocity[nodeID] = nodeV; + + // Aerodynamics + float4 rel_v = nodeV - clothWindVelocity; + float rel_v_len = alength3(rel_v); + float rel_v2 = dot(rel_v, rel_v); + + if( rel_v2 > epsilon ) + { + float4 rel_v_nrm = anormalize3(rel_v); + float4 nrm = normal; + + nrm = nrm * (dot(nrm, rel_v) < 0 ? -1.f : 1.f); + + float4 fDrag = (float4)(0.f, 0.f, 0.f, 0.f); + float4 fLift = (float4)(0.f, 0.f, 0.f, 0.f); + + float n_dot_v = dot(nrm, rel_v_nrm); + + // drag force + if ( dragFactor > 0.f ) + fDrag = 0.5f * dragFactor * mediumDensity * rel_v2 * area * n_dot_v * (-1.0f) * rel_v_nrm; + + // lift force + // Check angle of attack + // cos(10º) = 0.98480 + if ( 0 < n_dot_v && n_dot_v < 0.98480f) + fLift = 0.5f * liftFactor * mediumDensity * rel_v_len * area * sqrt(1.0f-n_dot_v*n_dot_v) * (cross(cross(nrm, rel_v_nrm), rel_v_nrm)); + + nodeF += fDrag + fLift; + g_vertexForceAccumulator[nodeID] = nodeF; + } + } + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl new file mode 100644 index 0000000..f18eada --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl @@ -0,0 +1,82 @@ +MSTRINGIFY( +#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n +#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n + +__kernel void +ComputeBoundsKernel( + const int numNodes, + const int numSoftBodies, + __global int * g_vertexClothIdentifier, + __global float4 * g_vertexPositions, + /* Unfortunately, to get the atomics below to work these arrays cannot be */ + /* uint4, though that is the layout of the data */ + /* Therefore this is little-endian-only code */ + volatile __global uint * g_clothMinBounds, + volatile __global uint * g_clothMaxBounds, + volatile __local uint * clothMinBounds, + volatile __local uint * clothMaxBounds) +{ + // Init min and max bounds arrays + if( get_local_id(0) < numSoftBodies ) + { + + clothMinBounds[get_local_id(0)*4] = UINT_MAX; + clothMinBounds[get_local_id(0)*4+1] = UINT_MAX; + clothMinBounds[get_local_id(0)*4+2] = UINT_MAX; + clothMinBounds[get_local_id(0)*4+3] = UINT_MAX; + clothMaxBounds[get_local_id(0)*4] = 0; + clothMaxBounds[get_local_id(0)*4+1] = 0; + clothMaxBounds[get_local_id(0)*4+2] = 0; + clothMaxBounds[get_local_id(0)*4+3] = 0; + + } + + barrier(CLK_LOCAL_MEM_FENCE); + + int nodeID = get_global_id(0); + if( nodeID < numNodes ) + { + int clothIdentifier = g_vertexClothIdentifier[nodeID]; + if( clothIdentifier >= 0 ) + { + + float4 position = (float4)(g_vertexPositions[nodeID].xyz, 0.f); + + /* Reinterpret position as uint */ + uint4 positionUInt = (uint4)(as_uint(position.x), as_uint(position.y), as_uint(position.z), 0); + + /* Invert sign bit of positives and whole of negatives to allow comparison as unsigned ints */ + positionUInt.x ^= (1+~(positionUInt.x >> 31) | 0x80000000); + positionUInt.y ^= (1+~(positionUInt.y >> 31) | 0x80000000); + positionUInt.z ^= (1+~(positionUInt.z >> 31) | 0x80000000); + + // Min/max with the LDS values + atom_min(&(clothMinBounds[clothIdentifier*4]), positionUInt.x); + atom_min(&(clothMinBounds[clothIdentifier*4+1]), positionUInt.y); + atom_min(&(clothMinBounds[clothIdentifier*4+2]), positionUInt.z); + + atom_max(&(clothMaxBounds[clothIdentifier*4]), positionUInt.x); + atom_max(&(clothMaxBounds[clothIdentifier*4+1]), positionUInt.y); + atom_max(&(clothMaxBounds[clothIdentifier*4+2]), positionUInt.z); + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + + + /* Use global atomics to update the global versions of the data */ + if( get_local_id(0) < numSoftBodies ) + { + /*atom_min(&(g_clothMinBounds[get_local_id(0)].x), clothMinBounds[get_local_id(0)].x);*/ + atom_min(&(g_clothMinBounds[get_local_id(0)*4]), clothMinBounds[get_local_id(0)*4]); + atom_min(&(g_clothMinBounds[get_local_id(0)*4+1]), clothMinBounds[get_local_id(0)*4+1]); + atom_min(&(g_clothMinBounds[get_local_id(0)*4+2]), clothMinBounds[get_local_id(0)*4+2]); + + atom_max(&(g_clothMaxBounds[get_local_id(0)*4]), clothMaxBounds[get_local_id(0)*4]); + atom_max(&(g_clothMaxBounds[get_local_id(0)*4+1]), clothMaxBounds[get_local_id(0)*4+1]); + atom_max(&(g_clothMaxBounds[get_local_id(0)*4+2]), clothMaxBounds[get_local_id(0)*4+2]); + } +} + + +); diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl new file mode 100644 index 0000000..fb65330 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl @@ -0,0 +1,35 @@ +MSTRINGIFY( + +// Node indices for each link + + + +__kernel void +IntegrateKernel( + const int numNodes, + const float solverdt, + __global float * g_vertexInverseMasses, + __global float4 * g_vertexPositions, + __global float4 * g_vertexVelocity, + __global float4 * g_vertexPreviousPositions, + __global float4 * g_vertexForceAccumulator GUID_ARG) +{ + int nodeID = get_global_id(0); + if( nodeID < numNodes ) + { + float4 position = g_vertexPositions[nodeID]; + float4 velocity = g_vertexVelocity[nodeID]; + float4 force = g_vertexForceAccumulator[nodeID]; + float inverseMass = g_vertexInverseMasses[nodeID]; + + g_vertexPreviousPositions[nodeID] = position; + velocity += force * inverseMass * solverdt; + position += velocity * solverdt; + + g_vertexForceAccumulator[nodeID] = (float4)(0.f, 0.f, 0.f, 0.0f); + g_vertexPositions[nodeID] = position; + g_vertexVelocity[nodeID] = velocity; + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl new file mode 100644 index 0000000..f04e092 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl @@ -0,0 +1,46 @@ +MSTRINGIFY( + +__kernel void +OutputToVertexArrayWithNormalsKernel( + const int startNode, const int numNodes, __global float *g_vertexBuffer, + const int positionOffset, const int positionStride, const __global float4* g_vertexPositions, + const int normalOffset, const int normalStride, const __global float4* g_vertexNormals ) +{ + int nodeID = get_global_id(0); + if( nodeID < numNodes ) + { + float4 position = g_vertexPositions[nodeID + startNode]; + float4 normal = g_vertexNormals[nodeID + startNode]; + + // Stride should account for the float->float4 conversion + int positionDestination = nodeID * positionStride + positionOffset; + g_vertexBuffer[positionDestination] = position.x; + g_vertexBuffer[positionDestination+1] = position.y; + g_vertexBuffer[positionDestination+2] = position.z; + + int normalDestination = nodeID * normalStride + normalOffset; + g_vertexBuffer[normalDestination] = normal.x; + g_vertexBuffer[normalDestination+1] = normal.y; + g_vertexBuffer[normalDestination+2] = normal.z; + } +} + +__kernel void +OutputToVertexArrayWithoutNormalsKernel( + const int startNode, const int numNodes, __global float *g_vertexBuffer, + const int positionOffset, const int positionStride, const __global float4* g_vertexPositions ) +{ + int nodeID = get_global_id(0); + if( nodeID < numNodes ) + { + float4 position = g_vertexPositions[nodeID + startNode]; + + // Stride should account for the float->float4 conversion + int positionDestination = nodeID * positionStride + positionOffset; + g_vertexBuffer[positionDestination] = position.x; + g_vertexBuffer[positionDestination+1] = position.y; + g_vertexBuffer[positionDestination+2] = position.z; + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl new file mode 100644 index 0000000..72d46cc --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl @@ -0,0 +1,38 @@ +MSTRINGIFY( + + + +__kernel void +PrepareLinksKernel( + const int numLinks, + __global int2 * g_linksVertexIndices, + __global float * g_linksMassLSC, + __global float4 * g_nodesPreviousPosition, + __global float * g_linksLengthRatio, + __global float4 * g_linksCurrentLength GUID_ARG) +{ + int linkID = get_global_id(0); + if( linkID < numLinks ) + { + + int2 nodeIndices = g_linksVertexIndices[linkID]; + int node0 = nodeIndices.x; + int node1 = nodeIndices.y; + + float4 nodePreviousPosition0 = g_nodesPreviousPosition[node0]; + float4 nodePreviousPosition1 = g_nodesPreviousPosition[node1]; + + float massLSC = g_linksMassLSC[linkID]; + + float4 linkCurrentLength = nodePreviousPosition1 - nodePreviousPosition0; + linkCurrentLength.w = 0.f; + + float linkLengthRatio = dot(linkCurrentLength, linkCurrentLength)*massLSC; + linkLengthRatio = 1.0f/linkLengthRatio; + + g_linksCurrentLength[linkID] = linkCurrentLength; + g_linksLengthRatio[linkID] = linkLengthRatio; + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl new file mode 100644 index 0000000..099042f --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl @@ -0,0 +1,204 @@ +MSTRINGIFY( + + + +float mydot3a(float4 a, float4 b) +{ + return a.x*b.x + a.y*b.y + a.z*b.z; +} + + +typedef struct +{ + int firstObject; + int endObject; +} CollisionObjectIndices; + +typedef struct +{ + float4 shapeTransform[4]; // column major 4x4 matrix + float4 linearVelocity; + float4 angularVelocity; + + int softBodyIdentifier; + int collisionShapeType; + + + // Shape information + // Compressed from the union + float radius; + float halfHeight; + int upAxis; + + float margin; + float friction; + + int padding0; + +} CollisionShapeDescription; + +// From btBroadphaseProxy.h +__constant int CAPSULE_SHAPE_PROXYTYPE = 10; + +// Multiply column-major matrix against vector +float4 matrixVectorMul( float4 matrix[4], float4 vector ) +{ + float4 returnVector; + float4 row0 = (float4)(matrix[0].x, matrix[1].x, matrix[2].x, matrix[3].x); + float4 row1 = (float4)(matrix[0].y, matrix[1].y, matrix[2].y, matrix[3].y); + float4 row2 = (float4)(matrix[0].z, matrix[1].z, matrix[2].z, matrix[3].z); + float4 row3 = (float4)(matrix[0].w, matrix[1].w, matrix[2].w, matrix[3].w); + returnVector.x = dot(row0, vector); + returnVector.y = dot(row1, vector); + returnVector.z = dot(row2, vector); + returnVector.w = dot(row3, vector); + return returnVector; +} + +__kernel void +SolveCollisionsAndUpdateVelocitiesKernel( + const int numNodes, + const float isolverdt, + __global int *g_vertexClothIdentifier, + __global float4 *g_vertexPreviousPositions, + __global float * g_perClothFriction, + __global float * g_clothDampingFactor, + __global CollisionObjectIndices * g_perClothCollisionObjectIndices, + __global CollisionShapeDescription * g_collisionObjectDetails, + __global float4 * g_vertexForces, + __global float4 *g_vertexVelocities, + __global float4 *g_vertexPositions GUID_ARG) +{ + int nodeID = get_global_id(0); + float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f); + + if( get_global_id(0) < numNodes ) + { + int clothIdentifier = g_vertexClothIdentifier[nodeID]; + + // Abort if this is not a valid cloth + if( clothIdentifier < 0 ) + return; + + + float4 position = (float4)(g_vertexPositions[nodeID].xyz, 1.f); + float4 previousPosition = (float4)(g_vertexPreviousPositions[nodeID].xyz, 1.f); + + float clothFriction = g_perClothFriction[clothIdentifier]; + float dampingFactor = g_clothDampingFactor[clothIdentifier]; + float velocityCoefficient = (1.f - dampingFactor); + float4 difference = position - previousPosition; + float4 velocity = difference*velocityCoefficient*isolverdt; + + CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier]; + + int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; + + if( numObjects > 0 ) + { + // We have some possible collisions to deal with + for( int collision = collisionObjectIndices.firstObject; collision < collisionObjectIndices.endObject; ++collision ) + { + CollisionShapeDescription shapeDescription = g_collisionObjectDetails[collision]; + float colliderFriction = shapeDescription.friction; + + if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE ) + { + // Colliding with a capsule + + float capsuleHalfHeight = shapeDescription.halfHeight; + float capsuleRadius = shapeDescription.radius; + float capsuleMargin = shapeDescription.margin; + int capsuleupAxis = shapeDescription.upAxis; + + // Four columns of worldTransform matrix + float4 worldTransform[4]; + worldTransform[0] = shapeDescription.shapeTransform[0]; + worldTransform[1] = shapeDescription.shapeTransform[1]; + worldTransform[2] = shapeDescription.shapeTransform[2]; + worldTransform[3] = shapeDescription.shapeTransform[3]; + + // Correctly define capsule centerline vector + float4 c1 = (float4)(0.f, 0.f, 0.f, 1.f); + float4 c2 = (float4)(0.f, 0.f, 0.f, 1.f); + c1.x = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 0 ); + c1.y = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 1 ); + c1.z = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 2 ); + c2.x = -c1.x; + c2.y = -c1.y; + c2.z = -c1.z; + + + float4 worldC1 = matrixVectorMul(worldTransform, c1); + float4 worldC2 = matrixVectorMul(worldTransform, c2); + float4 segment = (worldC2 - worldC1); + + // compute distance of tangent to vertex along line segment in capsule + float distanceAlongSegment = -( mydot3a( (worldC1 - position), segment ) / mydot3a(segment, segment) ); + + float4 closestPoint = (worldC1 + (float4)(segment * distanceAlongSegment)); + float distanceFromLine = length(position - closestPoint); + float distanceFromC1 = length(worldC1 - position); + float distanceFromC2 = length(worldC2 - position); + + // Final distance from collision, point to push from, direction to push in + // for impulse force + float dist; + float4 normalVector; + if( distanceAlongSegment < 0 ) + { + dist = distanceFromC1; + normalVector = (float4)(normalize(position - worldC1).xyz, 0.f); + } else if( distanceAlongSegment > 1.f ) { + dist = distanceFromC2; + normalVector = (float4)(normalize(position - worldC2).xyz, 0.f); + } else { + dist = distanceFromLine; + normalVector = (float4)(normalize(position - closestPoint).xyz, 0.f); + } + + float4 colliderLinearVelocity = shapeDescription.linearVelocity; + float4 colliderAngularVelocity = shapeDescription.angularVelocity; + float4 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position - (float4)(worldTransform[0].w, worldTransform[1].w, worldTransform[2].w, 0.f)); + + float minDistance = capsuleRadius + capsuleMargin; + + // In case of no collision, this is the value of velocity + velocity = (position - previousPosition) * velocityCoefficient * isolverdt; + + + // Check for a collision + if( dist < minDistance ) + { + // Project back to surface along normal + position = position + (float4)((minDistance - dist)*normalVector*0.9f); + velocity = (position - previousPosition) * velocityCoefficient * isolverdt; + float4 relativeVelocity = velocity - velocityOfSurfacePoint; + + float4 p1 = normalize(cross(normalVector, segment)); + float4 p2 = normalize(cross(p1, normalVector)); + // Full friction is sum of velocities in each direction of plane + float4 frictionVector = p1*mydot3a(relativeVelocity, p1) + p2*mydot3a(relativeVelocity, p2); + + // Real friction is peak friction corrected by friction coefficients + frictionVector = frictionVector * (colliderFriction*clothFriction); + + float approachSpeed = dot(relativeVelocity, normalVector); + + if( approachSpeed <= 0.0f ) + forceOnVertex -= frictionVector; + } + } + } + } + + g_vertexVelocities[nodeID] = (float4)(velocity.xyz, 0.f); + + // Update external force + g_vertexForces[nodeID] = (float4)(forceOnVertex.xyz, 0.f); + + g_vertexPositions[nodeID] = (float4)(position.xyz, 0.f); + } +} + +); diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl new file mode 100644 index 0000000..8709022 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl @@ -0,0 +1,242 @@ +MSTRINGIFY( + +//#pragma OPENCL EXTENSION cl_amd_printf:enable\n + +float mydot3a(float4 a, float4 b) +{ + return a.x*b.x + a.y*b.y + a.z*b.z; +} + +float mylength3(float4 a) +{ + a.w = 0; + return length(a); +} + +float4 mynormalize3(float4 a) +{ + a.w = 0; + return normalize(a); +} + +typedef struct +{ + int firstObject; + int endObject; +} CollisionObjectIndices; + +typedef struct +{ + float4 shapeTransform[4]; // column major 4x4 matrix + float4 linearVelocity; + float4 angularVelocity; + + int softBodyIdentifier; + int collisionShapeType; + + + // Shape information + // Compressed from the union + float radius; + float halfHeight; + int upAxis; + + float margin; + float friction; + + int padding0; + +} CollisionShapeDescription; + +// From btBroadphaseProxy.h +__constant int CAPSULE_SHAPE_PROXYTYPE = 10; + +// Multiply column-major matrix against vector +float4 matrixVectorMul( float4 matrix[4], float4 vector ) +{ + float4 returnVector; + float4 row0 = (float4)(matrix[0].x, matrix[1].x, matrix[2].x, matrix[3].x); + float4 row1 = (float4)(matrix[0].y, matrix[1].y, matrix[2].y, matrix[3].y); + float4 row2 = (float4)(matrix[0].z, matrix[1].z, matrix[2].z, matrix[3].z); + float4 row3 = (float4)(matrix[0].w, matrix[1].w, matrix[2].w, matrix[3].w); + returnVector.x = dot(row0, vector); + returnVector.y = dot(row1, vector); + returnVector.z = dot(row2, vector); + returnVector.w = dot(row3, vector); + return returnVector; +} + +__kernel void +SolveCollisionsAndUpdateVelocitiesKernel( + const int numNodes, + const float isolverdt, + __global int *g_vertexClothIdentifier, + __global float4 *g_vertexPreviousPositions, + __global float * g_perClothFriction, + __global float * g_clothDampingFactor, + __global CollisionObjectIndices * g_perClothCollisionObjectIndices, + __global CollisionShapeDescription * g_collisionObjectDetails, + __global float4 * g_vertexForces, + __global float4 *g_vertexVelocities, + __global float4 *g_vertexPositions, + __local CollisionShapeDescription *localCollisionShapes, + __global float * g_vertexInverseMasses) +{ + int nodeID = get_global_id(0); + float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f); + + int clothIdentifier = g_vertexClothIdentifier[nodeID]; + + // Abort if this is not a valid cloth + if( clothIdentifier < 0 ) + return; + + + float4 position = (float4)(g_vertexPositions[nodeID].xyz, 0.f); + float4 previousPosition = (float4)(g_vertexPreviousPositions[nodeID].xyz, 0.f); + + float clothFriction = g_perClothFriction[clothIdentifier]; + float dampingFactor = g_clothDampingFactor[clothIdentifier]; + float velocityCoefficient = (1.f - dampingFactor); + float4 difference = position - previousPosition; + float4 velocity = difference*velocityCoefficient*isolverdt; + float inverseMass = g_vertexInverseMasses[nodeID]; + + CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier]; + + int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; + + if( numObjects > 0 ) + { + // We have some possible collisions to deal with + + // First load all of the collision objects into LDS + int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; + if( get_local_id(0) < numObjects ) + { + localCollisionShapes[get_local_id(0)] = g_collisionObjectDetails[ collisionObjectIndices.firstObject + get_local_id(0) ]; + } + } + + // Safe as the vertices are padded so that not more than one soft body is in a group + barrier(CLK_LOCAL_MEM_FENCE); + + // Annoyingly, even though I know the flow control is not varying, the compiler will not let me skip this + if( numObjects > 0 ) + { + + + // We have some possible collisions to deal with + for( int collision = 0; collision < numObjects; ++collision ) + { + CollisionShapeDescription shapeDescription = localCollisionShapes[collision]; + float colliderFriction = localCollisionShapes[collision].friction; + + if( localCollisionShapes[collision].collisionShapeType == CAPSULE_SHAPE_PROXYTYPE ) + { + // Colliding with a capsule + + float capsuleHalfHeight = localCollisionShapes[collision].halfHeight; + float capsuleRadius = localCollisionShapes[collision].radius; + float capsuleMargin = localCollisionShapes[collision].margin; + int capsuleupAxis = localCollisionShapes[collision].upAxis; + + if ( capsuleHalfHeight <= 0 ) + capsuleHalfHeight = 0.0001f; + float4 worldTransform[4]; + worldTransform[0] = localCollisionShapes[collision].shapeTransform[0]; + worldTransform[1] = localCollisionShapes[collision].shapeTransform[1]; + worldTransform[2] = localCollisionShapes[collision].shapeTransform[2]; + worldTransform[3] = localCollisionShapes[collision].shapeTransform[3]; + + // Correctly define capsule centerline vector + float4 c1 = (float4)(0.f, 0.f, 0.f, 1.f); + float4 c2 = (float4)(0.f, 0.f, 0.f, 1.f); + c1.x = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 0 ); + c1.y = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 1 ); + c1.z = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 2 ); + c2.x = -c1.x; + c2.y = -c1.y; + c2.z = -c1.z; + + float4 worldC1 = matrixVectorMul(worldTransform, c1); + float4 worldC2 = matrixVectorMul(worldTransform, c2); + float4 segment = (float4)((worldC2 - worldC1).xyz, 0.f); + + float4 segmentNormalized = mynormalize3(segment); + float distanceAlongSegment =mydot3a( (position - worldC1), segmentNormalized ); + + float4 closestPointOnSegment = (worldC1 + (float4)(segmentNormalized * distanceAlongSegment)); + float distanceFromLine = mylength3(position - closestPointOnSegment); + float distanceFromC1 = mylength3(worldC1 - position); + float distanceFromC2 = mylength3(worldC2 - position); + + // Final distance from collision, point to push from, direction to push in + // for impulse force + float dist; + float4 normalVector; + + if( distanceAlongSegment < 0 ) + { + dist = distanceFromC1; + normalVector = (float4)(normalize(position - worldC1).xyz, 0.f); + } else if( distanceAlongSegment > length(segment) ) { + dist = distanceFromC2; + normalVector = (float4)(normalize(position - worldC2).xyz, 0.f); + } else { + dist = distanceFromLine; + normalVector = (float4)(normalize(position - closestPointOnSegment).xyz, 0.f); + } + + float minDistance = capsuleRadius + capsuleMargin; + float4 closestPointOnSurface = (float4)((position + (minDistance - dist) * normalVector).xyz, 0.f); + + float4 colliderLinearVelocity = shapeDescription.linearVelocity; + float4 colliderAngularVelocity = shapeDescription.angularVelocity; + float4 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, closestPointOnSurface - (float4)(worldTransform[0].w, worldTransform[1].w, worldTransform[2].w, 0.f)); + + + // Check for a collision + if( dist < minDistance ) + { + // Project back to surface along normal + position = closestPointOnSurface; + velocity = (position - previousPosition) * velocityCoefficient * isolverdt; + float4 relativeVelocity = velocity - velocityOfSurfacePoint; + + float4 p1 = mynormalize3(cross(normalVector, segment)); + float4 p2 = mynormalize3(cross(p1, normalVector)); + + float4 tangentialVel = p1*mydot3a(relativeVelocity, p1) + p2*mydot3a(relativeVelocity, p2); + float frictionCoef = (colliderFriction * clothFriction); + if (frictionCoef>1.f) + frictionCoef = 1.f; + + //only apply friction if objects are not moving apart + float projVel = mydot3a(relativeVelocity,normalVector); + if ( projVel >= -0.001f) + { + if ( inverseMass > 0 ) + { + //float4 myforceOnVertex = -tangentialVel * frictionCoef * isolverdt * (1.0f / inverseMass); + position += (-tangentialVel * frictionCoef) / (isolverdt); + } + } + + // In case of no collision, this is the value of velocity + velocity = (position - previousPosition) * velocityCoefficient * isolverdt; + + } + } + } + } + + g_vertexVelocities[nodeID] = (float4)(velocity.xyz, 0.f); + + // Update external force + g_vertexForces[nodeID] = (float4)(forceOnVertex.xyz, 0.f); + + g_vertexPositions[nodeID] = (float4)(position.xyz, 0.f); +} + +); diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl new file mode 100644 index 0000000..fe7aec6 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl @@ -0,0 +1,57 @@ + + + +MSTRINGIFY( + + +float mydot3(float4 a, float4 b) +{ + return a.x*b.x + a.y*b.y + a.z*b.z; +} + + +__kernel void +SolvePositionsFromLinksKernel( + const int startLink, + const int numLinks, + const float kst, + const float ti, + __global int2 * g_linksVertexIndices, + __global float * g_linksMassLSC, + __global float * g_linksRestLengthSquared, + __global float * g_verticesInverseMass, + __global float4 * g_vertexPositions GUID_ARG) + +{ + int linkID = get_global_id(0) + startLink; + if( get_global_id(0) < numLinks ) + { + float massLSC = g_linksMassLSC[linkID]; + float restLengthSquared = g_linksRestLengthSquared[linkID]; + + if( massLSC > 0.0f ) + { + int2 nodeIndices = g_linksVertexIndices[linkID]; + int node0 = nodeIndices.x; + int node1 = nodeIndices.y; + + float4 position0 = g_vertexPositions[node0]; + float4 position1 = g_vertexPositions[node1]; + + float inverseMass0 = g_verticesInverseMass[node0]; + float inverseMass1 = g_verticesInverseMass[node1]; + + float4 del = position1 - position0; + float len = mydot3(del, del); + float k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst; + position0 = position0 - del*(k*inverseMass0); + position1 = position1 + del*(k*inverseMass1); + + g_vertexPositions[node0] = position0; + g_vertexPositions[node1] = position1; + + } + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl new file mode 100644 index 0000000..3316342 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl @@ -0,0 +1,130 @@ +/* +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. +*/ + +MSTRINGIFY( + +float mydot3(float4 a, float4 b) +{ + return a.x*b.x + a.y*b.y + a.z*b.z; +} + +__kernel __attribute__((reqd_work_group_size(WAVEFRONT_BLOCK_MULTIPLIER*WAVEFRONT_SIZE, 1, 1))) +void +SolvePositionsFromLinksKernel( + const int startWaveInBatch, + const int numWaves, + const float kst, + const float ti, + __global int2 *g_wavefrontBatchCountsVertexCounts, + __global int *g_vertexAddressesPerWavefront, + __global int2 * g_linksVertexIndices, + __global float * g_linksMassLSC, + __global float * g_linksRestLengthSquared, + __global float * g_verticesInverseMass, + __global float4 * g_vertexPositions, + __local int2 *wavefrontBatchCountsVertexCounts, + __local float4 *vertexPositionSharedData, + __local float *vertexInverseMassSharedData) +{ + const int laneInWavefront = (get_global_id(0) & (WAVEFRONT_SIZE-1)); + const int wavefront = startWaveInBatch + (get_global_id(0) / WAVEFRONT_SIZE); + const int firstWavefrontInBlock = startWaveInBatch + get_group_id(0) * WAVEFRONT_BLOCK_MULTIPLIER; + const int localWavefront = wavefront - firstWavefrontInBlock; + + // Mask out in case there's a stray "wavefront" at the end that's been forced in through the multiplier + if( wavefront < (startWaveInBatch + numWaves) ) + { + // Load the batch counts for the wavefronts + + int2 batchesAndVerticesWithinWavefront = g_wavefrontBatchCountsVertexCounts[wavefront]; + int batchesWithinWavefront = batchesAndVerticesWithinWavefront.x; + int verticesUsedByWave = batchesAndVerticesWithinWavefront.y; + + // Load the vertices for the wavefronts + for( int vertex = laneInWavefront; vertex < verticesUsedByWave; vertex+=WAVEFRONT_SIZE ) + { + int vertexAddress = g_vertexAddressesPerWavefront[wavefront*MAX_NUM_VERTICES_PER_WAVE + vertex]; + + vertexPositionSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = g_vertexPositions[vertexAddress]; + vertexInverseMassSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = g_verticesInverseMass[vertexAddress]; + } + + barrier(CLK_LOCAL_MEM_FENCE); + + // Loop through the batches performing the solve on each in LDS + int baseDataLocationForWave = WAVEFRONT_SIZE * wavefront * MAX_BATCHES_PER_WAVE; + + //for( int batch = 0; batch < batchesWithinWavefront; ++batch ) + + int batch = 0; + do + { + int baseDataLocation = baseDataLocationForWave + WAVEFRONT_SIZE * batch; + int locationOfValue = baseDataLocation + laneInWavefront; + + + // These loads should all be perfectly linear across the WF + int2 localVertexIndices = g_linksVertexIndices[locationOfValue]; + float massLSC = g_linksMassLSC[locationOfValue]; + float restLengthSquared = g_linksRestLengthSquared[locationOfValue]; + + // LDS vertex addresses based on logical wavefront number in block and loaded index + int vertexAddress0 = MAX_NUM_VERTICES_PER_WAVE * localWavefront + localVertexIndices.x; + int vertexAddress1 = MAX_NUM_VERTICES_PER_WAVE * localWavefront + localVertexIndices.y; + + float4 position0 = vertexPositionSharedData[vertexAddress0]; + float4 position1 = vertexPositionSharedData[vertexAddress1]; + + float inverseMass0 = vertexInverseMassSharedData[vertexAddress0]; + float inverseMass1 = vertexInverseMassSharedData[vertexAddress1]; + + float4 del = position1 - position0; + float len = mydot3(del, del); + + float k = 0; + if( massLSC > 0.0f ) + { + k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst; + } + + position0 = position0 - del*(k*inverseMass0); + position1 = position1 + del*(k*inverseMass1); + + // Ensure compiler does not re-order memory operations + barrier(CLK_LOCAL_MEM_FENCE); + + vertexPositionSharedData[vertexAddress0] = position0; + vertexPositionSharedData[vertexAddress1] = position1; + + // Ensure compiler does not re-order memory operations + barrier(CLK_LOCAL_MEM_FENCE); + + + ++batch; + } while( batch < batchesWithinWavefront ); + + // Update the global memory vertices for the wavefronts + for( int vertex = laneInWavefront; vertex < verticesUsedByWave; vertex+=WAVEFRONT_SIZE ) + { + int vertexAddress = g_vertexAddressesPerWavefront[wavefront*MAX_NUM_VERTICES_PER_WAVE + vertex]; + + g_vertexPositions[vertexAddress] = (float4)(vertexPositionSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex].xyz, 0.f); + } + + } + +} + +); diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl new file mode 100644 index 0000000..488a584 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl @@ -0,0 +1,44 @@ +MSTRINGIFY( + +/*#define float3 float4 + +float dot3(float3 a, float3 b) +{ + return a.x*b.x + a.y*b.y + a.z*b.z; +}*/ + +__kernel void +UpdateConstantsKernel( + const int numLinks, + __global int2 * g_linksVertexIndices, + __global float4 * g_vertexPositions, + __global float * g_vertexInverseMasses, + __global float * g_linksMaterialLSC, + __global float * g_linksMassLSC, + __global float * g_linksRestLengthSquared, + __global float * g_linksRestLengths) +{ + int linkID = get_global_id(0); + if( linkID < numLinks ) + { + int2 nodeIndices = g_linksVertexIndices[linkID]; + int node0 = nodeIndices.x; + int node1 = nodeIndices.y; + float linearStiffnessCoefficient = g_linksMaterialLSC[ linkID ]; + + float3 position0 = g_vertexPositions[node0].xyz; + float3 position1 = g_vertexPositions[node1].xyz; + float inverseMass0 = g_vertexInverseMasses[node0]; + float inverseMass1 = g_vertexInverseMasses[node1]; + + float3 difference = position0 - position1; + float length2 = dot(difference, difference); + float length = sqrt(length2); + + g_linksRestLengths[linkID] = length; + g_linksMassLSC[linkID] = (inverseMass0 + inverseMass1)/linearStiffnessCoefficient; + g_linksRestLengthSquared[linkID] = length*length; + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl new file mode 100644 index 0000000..c631f16 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl @@ -0,0 +1,25 @@ +MSTRINGIFY( + +__kernel void +UpdateFixedVertexPositions( + const uint numNodes, + __global int * g_anchorIndex, + __global float4 * g_vertexPositions, + __global float4 * g_anchorPositions GUID_ARG) +{ + unsigned int nodeID = get_global_id(0); + + if( nodeID < numNodes ) + { + int anchorIndex = g_anchorIndex[nodeID]; + float4 position = g_vertexPositions[nodeID]; + + if ( anchorIndex >= 0 ) + { + float4 anchorPosition = g_anchorPositions[anchorIndex]; + g_vertexPositions[nodeID] = anchorPosition; + } + } +} + +); diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl new file mode 100644 index 0000000..9ad227b --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl @@ -0,0 +1,39 @@ +MSTRINGIFY( + + +__kernel void +updateVelocitiesFromPositionsWithVelocitiesKernel( + int numNodes, + float isolverdt, + __global float4 * g_vertexPositions, + __global float4 * g_vertexPreviousPositions, + __global int * g_vertexClothIndices, + __global float *g_clothVelocityCorrectionCoefficients, + __global float * g_clothDampingFactor, + __global float4 * g_vertexVelocities, + __global float4 * g_vertexForces GUID_ARG) +{ + int nodeID = get_global_id(0); + if( nodeID < numNodes ) + { + float4 position = g_vertexPositions[nodeID]; + float4 previousPosition = g_vertexPreviousPositions[nodeID]; + float4 velocity = g_vertexVelocities[nodeID]; + int clothIndex = g_vertexClothIndices[nodeID]; + float velocityCorrectionCoefficient = g_clothVelocityCorrectionCoefficients[clothIndex]; + float dampingFactor = g_clothDampingFactor[clothIndex]; + float velocityCoefficient = (1.f - dampingFactor); + + float4 difference = position - previousPosition; + + velocity += difference*velocityCorrectionCoefficient*isolverdt; + + // Damp the velocity + velocity *= velocityCoefficient; + + g_vertexVelocities[nodeID] = velocity; + g_vertexForces[nodeID] = (float4)(0.f, 0.f, 0.f, 0.f); + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl new file mode 100644 index 0000000..7bb2334 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl @@ -0,0 +1,102 @@ +MSTRINGIFY( + +float length3(float4 a) +{ + a.w = 0; + return length(a); +} + +float4 normalize3(float4 a) +{ + a.w = 0; + return normalize(a); +} + +__kernel void +ResetNormalsAndAreasKernel( + const unsigned int numNodes, + __global float4 * g_vertexNormals, + __global float * g_vertexArea GUID_ARG) +{ + if( get_global_id(0) < numNodes ) + { + g_vertexNormals[get_global_id(0)] = (float4)(0.0f, 0.0f, 0.0f, 0.0f); + g_vertexArea[get_global_id(0)] = 0.0f; + } +} + + +__kernel void +UpdateSoftBodiesKernel( + const unsigned int startFace, + const unsigned int numFaces, + __global int4 * g_triangleVertexIndexSet, + __global float4 * g_vertexPositions, + __global float4 * g_vertexNormals, + __global float * g_vertexArea, + __global float4 * g_triangleNormals, + __global float * g_triangleArea GUID_ARG) +{ + int faceID = get_global_id(0) + startFace; + if( get_global_id(0) < numFaces ) + { + int4 triangleIndexSet = g_triangleVertexIndexSet[ faceID ]; + int nodeIndex0 = triangleIndexSet.x; + int nodeIndex1 = triangleIndexSet.y; + int nodeIndex2 = triangleIndexSet.z; + + float4 node0 = g_vertexPositions[nodeIndex0]; + float4 node1 = g_vertexPositions[nodeIndex1]; + float4 node2 = g_vertexPositions[nodeIndex2]; + float4 nodeNormal0 = g_vertexNormals[nodeIndex0]; + float4 nodeNormal1 = g_vertexNormals[nodeIndex1]; + float4 nodeNormal2 = g_vertexNormals[nodeIndex2]; + float vertexArea0 = g_vertexArea[nodeIndex0]; + float vertexArea1 = g_vertexArea[nodeIndex1]; + float vertexArea2 = g_vertexArea[nodeIndex2]; + + float4 vector0 = node1 - node0; + float4 vector1 = node2 - node0; + + float4 faceNormal = cross(vector0, vector1); + float triangleArea = length(faceNormal); + + nodeNormal0 = nodeNormal0 + faceNormal; + nodeNormal1 = nodeNormal1 + faceNormal; + nodeNormal2 = nodeNormal2 + faceNormal; + vertexArea0 = vertexArea0 + triangleArea; + vertexArea1 = vertexArea1 + triangleArea; + vertexArea2 = vertexArea2 + triangleArea; + + g_triangleNormals[faceID] = normalize3(faceNormal); + g_vertexNormals[nodeIndex0] = nodeNormal0; + g_vertexNormals[nodeIndex1] = nodeNormal1; + g_vertexNormals[nodeIndex2] = nodeNormal2; + g_triangleArea[faceID] = triangleArea; + g_vertexArea[nodeIndex0] = vertexArea0; + g_vertexArea[nodeIndex1] = vertexArea1; + g_vertexArea[nodeIndex2] = vertexArea2; + } +} + +__kernel void +NormalizeNormalsAndAreasKernel( + const unsigned int numNodes, + __global int * g_vertexTriangleCount, + __global float4 * g_vertexNormals, + __global float * g_vertexArea GUID_ARG) +{ + if( get_global_id(0) < numNodes ) + { + float4 normal = g_vertexNormals[get_global_id(0)]; + float area = g_vertexArea[get_global_id(0)]; + int numTriangles = g_vertexTriangleCount[get_global_id(0)]; + + float vectorLength = length3(normal); + + g_vertexNormals[get_global_id(0)] = normalize3(normal); + g_vertexArea[get_global_id(0)] = area/(float)(numTriangles); + } +} + +); diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl new file mode 100644 index 0000000..3155a04 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl @@ -0,0 +1,34 @@ +MSTRINGIFY( + +__kernel void +updateVelocitiesFromPositionsWithoutVelocitiesKernel( + const int numNodes, + const float isolverdt, + __global float4 * g_vertexPositions, + __global float4 * g_vertexPreviousPositions, + __global int * g_vertexClothIndices, + __global float * g_clothDampingFactor, + __global float4 * g_vertexVelocities, + __global float4 * g_vertexForces GUID_ARG) + +{ + int nodeID = get_global_id(0); + if( nodeID < numNodes ) + { + float4 position = g_vertexPositions[nodeID]; + float4 previousPosition = g_vertexPreviousPositions[nodeID]; + float4 velocity = g_vertexVelocities[nodeID]; + int clothIndex = g_vertexClothIndices[nodeID]; + float dampingFactor = g_clothDampingFactor[clothIndex]; + float velocityCoefficient = (1.f - dampingFactor); + + float4 difference = position - previousPosition; + + velocity = difference*velocityCoefficient*isolverdt; + + g_vertexVelocities[nodeID] = velocity; + g_vertexForces[nodeID] = (float4)(0.f, 0.f, 0.f, 0.f); + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl new file mode 100644 index 0000000..97e708b --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl @@ -0,0 +1,28 @@ + +MSTRINGIFY( + + + + +__kernel void +UpdatePositionsFromVelocitiesKernel( + const int numNodes, + const float solverSDT, + __global float4 * g_vertexVelocities, + __global float4 * g_vertexPreviousPositions, + __global float4 * g_vertexCurrentPosition GUID_ARG) +{ + int vertexID = get_global_id(0); + if( vertexID < numNodes ) + { + float4 previousPosition = g_vertexPreviousPositions[vertexID]; + float4 velocity = g_vertexVelocities[vertexID]; + + float4 newPosition = previousPosition + velocity*solverSDT; + + g_vertexCurrentPosition[vertexID] = newPosition; + g_vertexPreviousPositions[vertexID] = newPosition; + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl new file mode 100644 index 0000000..a618d69 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl @@ -0,0 +1,45 @@ +MSTRINGIFY( + +__kernel void +VSolveLinksKernel( + int startLink, + int numLinks, + float kst, + __global int2 * g_linksVertexIndices, + __global float * g_linksLengthRatio, + __global float4 * g_linksCurrentLength, + __global float * g_vertexInverseMass, + __global float4 * g_vertexVelocity GUID_ARG) +{ + int linkID = get_global_id(0) + startLink; + if( get_global_id(0) < numLinks ) + { + int2 nodeIndices = g_linksVertexIndices[linkID]; + int node0 = nodeIndices.x; + int node1 = nodeIndices.y; + + float linkLengthRatio = g_linksLengthRatio[linkID]; + float3 linkCurrentLength = g_linksCurrentLength[linkID].xyz; + + float3 vertexVelocity0 = g_vertexVelocity[node0].xyz; + float3 vertexVelocity1 = g_vertexVelocity[node1].xyz; + + float vertexInverseMass0 = g_vertexInverseMass[node0]; + float vertexInverseMass1 = g_vertexInverseMass[node1]; + + float3 nodeDifference = vertexVelocity0 - vertexVelocity1; + float dotResult = dot(linkCurrentLength, nodeDifference); + float j = -dotResult*linkLengthRatio*kst; + + float3 velocityChange0 = linkCurrentLength*(j*vertexInverseMass0); + float3 velocityChange1 = linkCurrentLength*(j*vertexInverseMass1); + + vertexVelocity0 += velocityChange0; + vertexVelocity1 -= velocityChange1; + + g_vertexVelocity[node0] = (float4)(vertexVelocity0, 0.f); + g_vertexVelocity[node1] = (float4)(vertexVelocity1, 0.f); + } +} + +); \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h new file mode 100644 index 0000000..61d474a --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h @@ -0,0 +1,209 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVER_BUFFER_OPENCL_H +#define BT_SOFT_BODY_SOLVER_BUFFER_OPENCL_H + +// OpenCL support + +#ifdef USE_MINICL + #include "MiniCL/cl.h" +#else //USE_MINICL + #ifdef __APPLE__ + #include + #else + #include + #endif //__APPLE__ +#endif//USE_MINICL + +#ifndef SAFE_RELEASE +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } +#endif + +template class btOpenCLBuffer +{ +public: + + cl_command_queue m_cqCommandQue; + cl_context m_clContext; + cl_mem m_buffer; + + + + btAlignedObjectArray< ElementType > * m_CPUBuffer; + + int m_gpuSize; + bool m_onGPU; + bool m_readOnlyOnGPU; + bool m_allocated; + + + bool createBuffer( cl_mem* preexistingBuffer = 0) + { + + cl_int err; + + + if( preexistingBuffer ) + { + m_buffer = *preexistingBuffer; + } + else { + + cl_mem_flags flags= m_readOnlyOnGPU ? CL_MEM_READ_ONLY : CL_MEM_READ_WRITE; + + size_t size = m_CPUBuffer->size() * sizeof(ElementType); + // At a minimum the buffer must exist + if( size == 0 ) + size = sizeof(ElementType); + m_buffer = clCreateBuffer(m_clContext, flags, size, 0, &err); + if( err != CL_SUCCESS ) + { + btAssert( "Buffer::Buffer(m_buffer)"); + } + } + + m_gpuSize = m_CPUBuffer->size(); + + return true; + } + +public: + btOpenCLBuffer( cl_command_queue commandQue,cl_context ctx, btAlignedObjectArray< ElementType >* CPUBuffer, bool readOnly) + :m_cqCommandQue(commandQue), + m_clContext(ctx), + m_buffer(0), + m_CPUBuffer(CPUBuffer), + m_gpuSize(0), + m_onGPU(false), + m_readOnlyOnGPU(readOnly), + m_allocated(false) + { + } + + ~btOpenCLBuffer() + { + clReleaseMemObject(m_buffer); + } + + + bool moveToGPU() + { + + + cl_int err; + + if( (m_CPUBuffer->size() != m_gpuSize) ) + { + m_onGPU = false; + } + + if( !m_allocated && m_CPUBuffer->size() == 0 ) + { + // If it isn't on the GPU and yet there is no data on the CPU side this may cause a problem with some kernels. + // We should create *something* on the device side + if (!createBuffer()) { + return false; + } + m_allocated = true; + } + + if( !m_onGPU && m_CPUBuffer->size() > 0 ) + { + if (!m_allocated || (m_CPUBuffer->size() != m_gpuSize)) { + if (!createBuffer()) { + return false; + } + m_allocated = true; + } + + size_t size = m_CPUBuffer->size() * sizeof(ElementType); + err = clEnqueueWriteBuffer(m_cqCommandQue,m_buffer, + CL_FALSE, + 0, + size, + &((*m_CPUBuffer)[0]),0,0,0); + if( err != CL_SUCCESS ) + { + btAssert( "CommandQueue::enqueueWriteBuffer(m_buffer)" ); + } + + m_onGPU = true; + } + + return true; + + } + + bool moveFromGPU() + { + + cl_int err; + + if (m_CPUBuffer->size() > 0) { + if (m_onGPU && !m_readOnlyOnGPU) { + size_t size = m_CPUBuffer->size() * sizeof(ElementType); + err = clEnqueueReadBuffer(m_cqCommandQue, + m_buffer, + CL_TRUE, + 0, + size, + &((*m_CPUBuffer)[0]),0,0,0); + + if( err != CL_SUCCESS ) + { + btAssert( "CommandQueue::enqueueReadBuffer(m_buffer)" ); + } + + m_onGPU = false; + } + } + + return true; + } + + bool copyFromGPU() + { + + cl_int err; + size_t size = m_CPUBuffer->size() * sizeof(ElementType); + + if (m_CPUBuffer->size() > 0) { + if (m_onGPU && !m_readOnlyOnGPU) { + err = clEnqueueReadBuffer(m_cqCommandQue, + m_buffer, + CL_TRUE, + 0,size, + &((*m_CPUBuffer)[0]),0,0,0); + + if( err != CL_SUCCESS ) + { + btAssert( "CommandQueue::enqueueReadBuffer(m_buffer)"); + } + + } + } + + return true; + } + + virtual void changedOnCPU() + { + m_onGPU = false; + } +}; // class btOpenCLBuffer + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_BUFFER_OPENCL_H \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h new file mode 100644 index 0000000..0092c8f --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h @@ -0,0 +1,99 @@ +/* +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 "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" +#include "btSoftBodySolverBuffer_OpenCL.h" + + +#ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_H +#define BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_H + + +class btSoftBodyLinkDataOpenCL : public btSoftBodyLinkData +{ +public: + bool m_onGPU; + + cl_command_queue m_cqCommandQue; + + + btOpenCLBuffer m_clLinks; + btOpenCLBuffer m_clLinkStrength; + btOpenCLBuffer m_clLinksMassLSC; + btOpenCLBuffer m_clLinksRestLengthSquared; + btOpenCLBuffer m_clLinksCLength; + btOpenCLBuffer m_clLinksLengthRatio; + btOpenCLBuffer m_clLinksRestLength; + btOpenCLBuffer m_clLinksMaterialLinearStiffnessCoefficient; + + struct BatchPair + { + int start; + int length; + + BatchPair() : + start(0), + length(0) + { + } + + BatchPair( int s, int l ) : + start( s ), + length( l ) + { + } + }; + + /** + * Link addressing information for each cloth. + * Allows link locations to be computed independently of data batching. + */ + btAlignedObjectArray< int > m_linkAddresses; + + /** + * Start and length values for computation batches over link data. + */ + btAlignedObjectArray< BatchPair > m_batchStartLengths; + + btSoftBodyLinkDataOpenCL(cl_command_queue queue, cl_context ctx); + + virtual ~btSoftBodyLinkDataOpenCL(); + + /** Allocate enough space in all link-related arrays to fit numLinks links */ + virtual void createLinks( int numLinks ); + + /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ + virtual void setLinkAt( + const LinkDescription &link, + int linkIndex ); + + virtual bool onAccelerator(); + + virtual bool moveToAccelerator(); + + virtual bool moveFromAccelerator(); + + /** + * Generate (and later update) the batching for the entire link set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ + void generateBatches(); +}; + + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_H diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h new file mode 100644 index 0000000..7a6e726 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h @@ -0,0 +1,169 @@ +/* +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 "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" +#include "btSoftBodySolverBuffer_OpenCL.h" + + +#ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_SIMDAWARE_H +#define BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_SIMDAWARE_H + + +class btSoftBodyLinkDataOpenCLSIMDAware : public btSoftBodyLinkData +{ +public: + bool m_onGPU; + + cl_command_queue m_cqCommandQue; + + const int m_wavefrontSize; + const int m_linksPerWorkItem; + const int m_maxLinksPerWavefront; + int m_maxBatchesWithinWave; + int m_maxVerticesWithinWave; + int m_numWavefronts; + + int m_maxVertex; + + struct NumBatchesVerticesPair + { + int numBatches; + int numVertices; + }; + + btAlignedObjectArray m_linksPerWavefront; + btAlignedObjectArray m_numBatchesAndVerticesWithinWaves; + btOpenCLBuffer< NumBatchesVerticesPair > m_clNumBatchesAndVerticesWithinWaves; + + // All arrays here will contain batches of m_maxLinksPerWavefront links + // ordered by wavefront. + // with either global vertex pairs or local vertex pairs + btAlignedObjectArray< int > m_wavefrontVerticesGlobalAddresses; // List of global vertices per wavefront + btOpenCLBuffer m_clWavefrontVerticesGlobalAddresses; + btAlignedObjectArray< LinkNodePair > m_linkVerticesLocalAddresses; // Vertex pair for the link + btOpenCLBuffer m_clLinkVerticesLocalAddresses; + btOpenCLBuffer m_clLinkStrength; + btOpenCLBuffer m_clLinksMassLSC; + btOpenCLBuffer m_clLinksRestLengthSquared; + btOpenCLBuffer m_clLinksRestLength; + btOpenCLBuffer m_clLinksMaterialLinearStiffnessCoefficient; + + struct BatchPair + { + int start; + int length; + + BatchPair() : + start(0), + length(0) + { + } + + BatchPair( int s, int l ) : + start( s ), + length( l ) + { + } + }; + + /** + * Link addressing information for each cloth. + * Allows link locations to be computed independently of data batching. + */ + btAlignedObjectArray< int > m_linkAddresses; + + /** + * Start and length values for computation batches over link data. + */ + btAlignedObjectArray< BatchPair > m_wavefrontBatchStartLengths; + + btSoftBodyLinkDataOpenCLSIMDAware(cl_command_queue queue, cl_context ctx); + + virtual ~btSoftBodyLinkDataOpenCLSIMDAware(); + + /** Allocate enough space in all link-related arrays to fit numLinks links */ + virtual void createLinks( int numLinks ); + + /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ + virtual void setLinkAt( + const LinkDescription &link, + int linkIndex ); + + virtual bool onAccelerator(); + + virtual bool moveToAccelerator(); + + virtual bool moveFromAccelerator(); + + /** + * Generate (and later update) the batching for the entire link set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ + void generateBatches(); + + int getMaxVerticesPerWavefront() + { + return m_maxVerticesWithinWave; + } + + int getWavefrontSize() + { + return m_wavefrontSize; + } + + int getLinksPerWorkItem() + { + return m_linksPerWorkItem; + } + + int getMaxLinksPerWavefront() + { + return m_maxLinksPerWavefront; + } + + int getMaxBatchesPerWavefront() + { + return m_maxBatchesWithinWave; + } + + int getNumWavefronts() + { + return m_numWavefronts; + } + + NumBatchesVerticesPair getNumBatchesAndVerticesWithinWavefront( int wavefront ) + { + return m_numBatchesAndVerticesWithinWaves[wavefront]; + } + + int getVertexGlobalAddresses( int vertexIndex ) + { + return m_wavefrontVerticesGlobalAddresses[vertexIndex]; + } + + /** + * Get post-batching local addresses of the vertex pair for a link assuming all vertices used by a wavefront are loaded locally. + */ + LinkNodePair getVertexPairLocalAddresses( int linkIndex ) + { + return m_linkVerticesLocalAddresses[linkIndex]; + } +}; + + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_SIMDAWARE_H diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp new file mode 100644 index 0000000..e18b575 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp @@ -0,0 +1,126 @@ +#include "btSoftBodySolverOutputCLtoGL.h" +#include //@todo: remove the debugging printf at some stage +#include "btSoftBodySolver_OpenCL.h" +#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h" +#include "btSoftBodySolverVertexBuffer_OpenGL.h" +#include "BulletSoftBody/btSoftBody.h" + +////OpenCL 1.0 kernels don't use float3 +#define MSTRINGIFY(A) #A +static char* OutputToVertexArrayCLString = +#include "OpenCLC10/OutputToVertexArray.cl" + + +#define RELEASE_CL_KERNEL(kernelName) {if( kernelName ){ clReleaseKernel( kernelName ); kernelName = 0; }} + +static const size_t workGroupSize = 128; + +void btSoftBodySolverOutputCLtoGL::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) +{ + + btSoftBodySolver *solver = softBody->getSoftBodySolver(); + btAssert( solver->getSolverType() == btSoftBodySolver::CL_SOLVER || solver->getSolverType() == btSoftBodySolver::CL_SIMD_SOLVER ); + btOpenCLSoftBodySolver *dxSolver = static_cast< btOpenCLSoftBodySolver * >( solver ); + checkInitialized(); + btOpenCLAcceleratedSoftBodyInterface* currentCloth = dxSolver->findSoftBodyInterface( softBody ); + btSoftBodyVertexDataOpenCL &vertexData( dxSolver->m_vertexData ); + + const int firstVertex = currentCloth->getFirstVertex(); + const int lastVertex = firstVertex + currentCloth->getNumVertices(); + + if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::OPENGL_BUFFER ) { + + const btOpenGLInteropVertexBufferDescriptor *openGLVertexBuffer = static_cast< btOpenGLInteropVertexBufferDescriptor* >(vertexBuffer); + cl_int ciErrNum = CL_SUCCESS; + + cl_mem clBuffer = openGLVertexBuffer->getBuffer(); + cl_kernel outputKernel = outputToVertexArrayWithNormalsKernel; + if( !vertexBuffer->hasNormals() ) + outputKernel = outputToVertexArrayWithoutNormalsKernel; + + ciErrNum = clEnqueueAcquireGLObjects(m_cqCommandQue, 1, &clBuffer, 0, 0, NULL); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "clEnqueueAcquireGLObjects(copySoftBodyToVertexBuffer)"); + } + + int numVertices = currentCloth->getNumVertices(); + + ciErrNum = clSetKernelArg(outputKernel, 0, sizeof(int), &firstVertex ); + ciErrNum = clSetKernelArg(outputKernel, 1, sizeof(int), &numVertices ); + ciErrNum = clSetKernelArg(outputKernel, 2, sizeof(cl_mem), (void*)&clBuffer ); + if( vertexBuffer->hasVertexPositions() ) + { + int vertexOffset = vertexBuffer->getVertexOffset(); + int vertexStride = vertexBuffer->getVertexStride(); + ciErrNum = clSetKernelArg(outputKernel, 3, sizeof(int), &vertexOffset ); + ciErrNum = clSetKernelArg(outputKernel, 4, sizeof(int), &vertexStride ); + ciErrNum = clSetKernelArg(outputKernel, 5, sizeof(cl_mem), (void*)&vertexData.m_clVertexPosition.m_buffer ); + + } + if( vertexBuffer->hasNormals() ) + { + int normalOffset = vertexBuffer->getNormalOffset(); + int normalStride = vertexBuffer->getNormalStride(); + ciErrNum = clSetKernelArg(outputKernel, 6, sizeof(int), &normalOffset ); + ciErrNum = clSetKernelArg(outputKernel, 7, sizeof(int), &normalStride ); + ciErrNum = clSetKernelArg(outputKernel, 8, sizeof(cl_mem), (void*)&vertexData.m_clVertexNormal.m_buffer ); + + } + size_t numWorkItems = workGroupSize*((vertexData.getNumVertices() + (workGroupSize-1)) / workGroupSize); + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, outputKernel, 1, NULL, &numWorkItems, &workGroupSize,0 ,0 ,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(copySoftBodyToVertexBuffer)"); + } + + ciErrNum = clEnqueueReleaseGLObjects(m_cqCommandQue, 1, &clBuffer, 0, 0, 0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "clEnqueueReleaseGLObjects(copySoftBodyToVertexBuffer)"); + } + } else { + btAssert( "Undefined output for this solver output" == false ); + } + + // clFinish in here may not be the best thing. It's possible that we should have a waitForFrameComplete function. + clFinish(m_cqCommandQue); + +} // btSoftBodySolverOutputCLtoGL::outputToVertexBuffers + +bool btSoftBodySolverOutputCLtoGL::buildShaders() +{ + // Ensure current kernels are released first + releaseKernels(); + + bool returnVal = true; + + if( m_shadersInitialized ) + return true; + + outputToVertexArrayWithNormalsKernel = clFunctions.compileCLKernelFromString( OutputToVertexArrayCLString, "OutputToVertexArrayWithNormalsKernel" ,"","OpenCLC10/OutputToVertexArray.cl"); + outputToVertexArrayWithoutNormalsKernel = clFunctions.compileCLKernelFromString( OutputToVertexArrayCLString, "OutputToVertexArrayWithoutNormalsKernel" ,"","OpenCLC10/OutputToVertexArray.cl"); + + + if( returnVal ) + m_shadersInitialized = true; + + return returnVal; +} // btSoftBodySolverOutputCLtoGL::buildShaders + +void btSoftBodySolverOutputCLtoGL::releaseKernels() +{ + RELEASE_CL_KERNEL( outputToVertexArrayWithNormalsKernel ); + RELEASE_CL_KERNEL( outputToVertexArrayWithoutNormalsKernel ); + + m_shadersInitialized = false; +} // btSoftBodySolverOutputCLtoGL::releaseKernels + +bool btSoftBodySolverOutputCLtoGL::checkInitialized() +{ + if( !m_shadersInitialized ) + if( buildShaders() ) + m_shadersInitialized = true; + + return m_shadersInitialized; +} \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h new file mode 100644 index 0000000..45279b0 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h @@ -0,0 +1,62 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVER_OUTPUT_CL_TO_GL_H +#define BT_SOFT_BODY_SOLVER_OUTPUT_CL_TO_GL_H + +#include "btSoftBodySolver_OpenCL.h" + +/** + * Class to manage movement of data from a solver to a given target. + * This version is the CL to GL interop version. + */ +class btSoftBodySolverOutputCLtoGL : public btSoftBodySolverOutput +{ +protected: + cl_command_queue m_cqCommandQue; + cl_context m_cxMainContext; + CLFunctions clFunctions; + + cl_kernel outputToVertexArrayWithNormalsKernel; + cl_kernel outputToVertexArrayWithoutNormalsKernel; + + bool m_shadersInitialized; + + virtual bool checkInitialized(); + virtual bool buildShaders(); + void releaseKernels(); +public: + btSoftBodySolverOutputCLtoGL(cl_command_queue cqCommandQue, cl_context cxMainContext) : + m_cqCommandQue( cqCommandQue ), + m_cxMainContext( cxMainContext ), + clFunctions(cqCommandQue, cxMainContext), + outputToVertexArrayWithNormalsKernel( 0 ), + outputToVertexArrayWithoutNormalsKernel( 0 ), + m_shadersInitialized( false ) + { + } + + virtual ~btSoftBodySolverOutputCLtoGL() + { + releaseKernels(); + } + + /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */ + virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ); +}; + + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_OUTPUT_CL_TO_GL_H \ No newline at end of file diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h new file mode 100644 index 0000000..9cafe83 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h @@ -0,0 +1,84 @@ +/* +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 "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" +#include "btSoftBodySolverBuffer_OpenCL.h" + + +#ifndef BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_OPENCL_H +#define BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_OPENCL_H + + +class btSoftBodyTriangleDataOpenCL : public btSoftBodyTriangleData +{ +public: + bool m_onGPU; + cl_command_queue m_queue; + + btOpenCLBuffer m_clVertexIndices; + btOpenCLBuffer m_clArea; + btOpenCLBuffer m_clNormal; + + /** + * Link addressing information for each cloth. + * Allows link locations to be computed independently of data batching. + */ + btAlignedObjectArray< int > m_triangleAddresses; + + /** + * Start and length values for computation batches over link data. + */ + struct btSomePair + { + btSomePair() {} + btSomePair(int f,int s) + :first(f),second(s) + { + } + int first; + int second; + }; + btAlignedObjectArray< btSomePair > m_batchStartLengths; + +public: + btSoftBodyTriangleDataOpenCL( cl_command_queue queue, cl_context ctx ); + + virtual ~btSoftBodyTriangleDataOpenCL(); + + /** Allocate enough space in all link-related arrays to fit numLinks links */ + virtual void createTriangles( int numTriangles ); + + /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ + virtual void setTriangleAt( const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex ); + + virtual bool onAccelerator(); + + virtual bool moveToAccelerator(); + + virtual bool moveFromAccelerator(); + + /** + * Generate (and later update) the batching for the entire triangle set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ + void generateBatches(); +}; // class btSoftBodyTriangleDataOpenCL + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_OPENCL_H + diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h new file mode 100644 index 0000000..3a30b0e --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h @@ -0,0 +1,166 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_OPENGL_H +#define BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_OPENGL_H + + +#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h" +#ifdef USE_MINICL + #include "MiniCL/cl.h" +#else //USE_MINICL + #ifdef __APPLE__ + #include + #else + #include + #include + #endif //__APPLE__ +#endif//USE_MINICL + + +#ifdef _WIN32//for glut.h +#include +#endif + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#include +#else + + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#endif //_WINDOWS +#endif //APPLE + + + +class btOpenGLInteropVertexBufferDescriptor : public btVertexBufferDescriptor +{ +protected: + /** OpenCL context */ + cl_context m_context; + + /** OpenCL command queue */ + cl_command_queue m_commandQueue; + + /** OpenCL interop buffer */ + cl_mem m_buffer; + + /** VBO in GL that is the basis of the interop buffer */ + GLuint m_openGLVBO; + + +public: + /** + * context is the OpenCL context this interop buffer will work in. + * queue is the command queue that kernels and data movement will be enqueued into. + * openGLVBO is the OpenGL vertex buffer data will be copied into. + * vertexOffset is the offset in floats to the first vertex. + * vertexStride is the stride in floats between vertices. + */ + btOpenGLInteropVertexBufferDescriptor( cl_command_queue cqCommandQue, cl_context context, GLuint openGLVBO, int vertexOffset, int vertexStride ) + { +#ifndef USE_MINICL + cl_int ciErrNum = CL_SUCCESS; + m_context = context; + m_commandQueue = cqCommandQue; + + m_vertexOffset = vertexOffset; + m_vertexStride = vertexStride; + + m_openGLVBO = openGLVBO; + + m_buffer = clCreateFromGLBuffer(m_context, CL_MEM_WRITE_ONLY, openGLVBO, &ciErrNum); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "clEnqueueAcquireGLObjects(copySoftBodyToVertexBuffer)"); + } + + m_hasVertexPositions = true; +#else + btAssert(0);//MiniCL shouldn't get here +#endif + } + + /** + * context is the OpenCL context this interop buffer will work in. + * queue is the command queue that kernels and data movement will be enqueued into. + * openGLVBO is the OpenGL vertex buffer data will be copied into. + * vertexOffset is the offset in floats to the first vertex. + * vertexStride is the stride in floats between vertices. + * normalOffset is the offset in floats to the first normal. + * normalStride is the stride in floats between normals. + */ + btOpenGLInteropVertexBufferDescriptor( cl_command_queue cqCommandQue, cl_context context, GLuint openGLVBO, int vertexOffset, int vertexStride, int normalOffset, int normalStride ) + { +#ifndef USE_MINICL + cl_int ciErrNum = CL_SUCCESS; + m_context = context; + m_commandQueue = cqCommandQue; + + m_openGLVBO = openGLVBO; + + m_buffer = clCreateFromGLBuffer(m_context, CL_MEM_WRITE_ONLY, openGLVBO, &ciErrNum); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "clEnqueueAcquireGLObjects(copySoftBodyToVertexBuffer)"); + } + + m_vertexOffset = vertexOffset; + m_vertexStride = vertexStride; + m_hasVertexPositions = true; + + m_normalOffset = normalOffset; + m_normalStride = normalStride; + m_hasNormals = true; +#else + btAssert(0); +#endif //USE_MINICL + + } + + virtual ~btOpenGLInteropVertexBufferDescriptor() + { + clReleaseMemObject( m_buffer ); + } + + /** + * Return the type of the vertex buffer descriptor. + */ + virtual BufferTypes getBufferType() const + { + return OPENGL_BUFFER; + } + + virtual cl_context getContext() const + { + return m_context; + } + + virtual cl_mem getBuffer() const + { + return m_buffer; + } +}; + +#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_OPENGL_H diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h new file mode 100644 index 0000000..3420c3f --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h @@ -0,0 +1,52 @@ +/* +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 "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" +#include "btSoftBodySolverBuffer_OpenCL.h" + +#ifndef BT_SOFT_BODY_SOLVER_VERTEX_DATA_OPENCL_H +#define BT_SOFT_BODY_SOLVER_VERTEX_DATA_OPENCL_H + + +class btSoftBodyVertexDataOpenCL : public btSoftBodyVertexData +{ +protected: + bool m_onGPU; + cl_command_queue m_queue; + +public: + btOpenCLBuffer m_clClothIdentifier; + btOpenCLBuffer m_clVertexPosition; + btOpenCLBuffer m_clVertexPreviousPosition; + btOpenCLBuffer m_clVertexVelocity; + btOpenCLBuffer m_clVertexForceAccumulator; + btOpenCLBuffer m_clVertexNormal; + btOpenCLBuffer m_clVertexInverseMass; + btOpenCLBuffer m_clVertexArea; + btOpenCLBuffer m_clVertexTriangleCount; +public: + btSoftBodyVertexDataOpenCL( cl_command_queue queue, cl_context ctx); + + virtual ~btSoftBodyVertexDataOpenCL(); + + virtual bool onAccelerator(); + + virtual bool moveToAccelerator(); + + virtual bool moveFromAccelerator(bool bCopy = false, bool bCopyMinimum = true); +}; + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_DATA_OPENCL_H diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp new file mode 100644 index 0000000..0a5ca00 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp @@ -0,0 +1,1820 @@ +/* +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 "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "vectormath/vmInclude.h" +#include //@todo: remove the debugging printf at some stage +#include "btSoftBodySolver_OpenCL.h" +#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h" +#include "BulletSoftBody/btSoftBody.h" +#include "BulletSoftBody/btSoftBodyInternals.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "LinearMath/btQuickprof.h" +#include + + +#define BT_SUPPRESS_OPENCL_ASSERTS + +#ifdef USE_MINICL + #include "MiniCL/cl.h" +#else //USE_MINICL + #ifdef __APPLE__ + #include + #else + #include + #endif //__APPLE__ +#endif//USE_MINICL + +#define BT_DEFAULT_WORKGROUPSIZE 64 + + +#define RELEASE_CL_KERNEL(kernelName) {if( kernelName ){ clReleaseKernel( kernelName ); kernelName = 0; }} + + +//CL_VERSION_1_1 seems broken on NVidia SDK so just disable it + +////OpenCL 1.0 kernels don't use float3 +#define MSTRINGIFY(A) #A +static const char* PrepareLinksCLString = +#include "OpenCLC10/PrepareLinks.cl" +static const char* UpdatePositionsFromVelocitiesCLString = +#include "OpenCLC10/UpdatePositionsFromVelocities.cl" +static const char* SolvePositionsCLString = +#include "OpenCLC10/SolvePositions.cl" +static const char* UpdateNodesCLString = +#include "OpenCLC10/UpdateNodes.cl" +static const char* UpdatePositionsCLString = +#include "OpenCLC10/UpdatePositions.cl" +static const char* UpdateConstantsCLString = +#include "OpenCLC10/UpdateConstants.cl" +static const char* IntegrateCLString = +#include "OpenCLC10/Integrate.cl" +static const char* ApplyForcesCLString = +#include "OpenCLC10/ApplyForces.cl" +static const char* UpdateFixedVertexPositionsCLString = +#include "OpenCLC10/UpdateFixedVertexPositions.cl" +static const char* UpdateNormalsCLString = +#include "OpenCLC10/UpdateNormals.cl" +static const char* VSolveLinksCLString = +#include "OpenCLC10/VSolveLinks.cl" +static const char* SolveCollisionsAndUpdateVelocitiesCLString = +#include "OpenCLC10/SolveCollisionsAndUpdateVelocities.cl" + + +btSoftBodyVertexDataOpenCL::btSoftBodyVertexDataOpenCL( cl_command_queue queue, cl_context ctx) : + m_queue(queue), + m_clClothIdentifier( queue, ctx, &m_clothIdentifier, false ), + m_clVertexPosition( queue, ctx, &m_vertexPosition, false ), + m_clVertexPreviousPosition( queue, ctx, &m_vertexPreviousPosition, false ), + m_clVertexVelocity( queue, ctx, &m_vertexVelocity, false ), + m_clVertexForceAccumulator( queue, ctx, &m_vertexForceAccumulator, false ), + m_clVertexNormal( queue, ctx, &m_vertexNormal, false ), + m_clVertexInverseMass( queue, ctx, &m_vertexInverseMass, false ), + m_clVertexArea( queue, ctx, &m_vertexArea, false ), + m_clVertexTriangleCount( queue, ctx, &m_vertexTriangleCount, false ) +{ +} + +btSoftBodyVertexDataOpenCL::~btSoftBodyVertexDataOpenCL() +{ + +} + +bool btSoftBodyVertexDataOpenCL::onAccelerator() +{ + return m_onGPU; +} + +bool btSoftBodyVertexDataOpenCL::moveToAccelerator() +{ + bool success = true; + success = success && m_clClothIdentifier.moveToGPU(); + success = success && m_clVertexPosition.moveToGPU(); + success = success && m_clVertexPreviousPosition.moveToGPU(); + success = success && m_clVertexVelocity.moveToGPU(); + success = success && m_clVertexForceAccumulator.moveToGPU(); + success = success && m_clVertexNormal.moveToGPU(); + success = success && m_clVertexInverseMass.moveToGPU(); + success = success && m_clVertexArea.moveToGPU(); + success = success && m_clVertexTriangleCount.moveToGPU(); + + if( success ) + m_onGPU = true; + + return success; +} + +bool btSoftBodyVertexDataOpenCL::moveFromAccelerator(bool bCopy, bool bCopyMinimum) +{ + bool success = true; + + if (!bCopy) + { + success = success && m_clClothIdentifier.moveFromGPU(); + success = success && m_clVertexPosition.moveFromGPU(); + success = success && m_clVertexPreviousPosition.moveFromGPU(); + success = success && m_clVertexVelocity.moveFromGPU(); + success = success && m_clVertexForceAccumulator.moveFromGPU(); + success = success && m_clVertexNormal.moveFromGPU(); + success = success && m_clVertexInverseMass.moveFromGPU(); + success = success && m_clVertexArea.moveFromGPU(); + success = success && m_clVertexTriangleCount.moveFromGPU(); + } + else + { + if (bCopyMinimum) + { + success = success && m_clVertexPosition.copyFromGPU(); + success = success && m_clVertexNormal.copyFromGPU(); + } + else + { + success = success && m_clClothIdentifier.copyFromGPU(); + success = success && m_clVertexPosition.copyFromGPU(); + success = success && m_clVertexPreviousPosition.copyFromGPU(); + success = success && m_clVertexVelocity.copyFromGPU(); + success = success && m_clVertexForceAccumulator.copyFromGPU(); + success = success && m_clVertexNormal.copyFromGPU(); + success = success && m_clVertexInverseMass.copyFromGPU(); + success = success && m_clVertexArea.copyFromGPU(); + success = success && m_clVertexTriangleCount.copyFromGPU(); + } + } + + if( success ) + m_onGPU = true; + + return success; +} + +btSoftBodyLinkDataOpenCL::btSoftBodyLinkDataOpenCL(cl_command_queue queue, cl_context ctx) +:m_cqCommandQue(queue), + m_clLinks( queue, ctx, &m_links, false ), + m_clLinkStrength( queue, ctx, &m_linkStrength, false ), + m_clLinksMassLSC( queue, ctx, &m_linksMassLSC, false ), + m_clLinksRestLengthSquared( queue, ctx, &m_linksRestLengthSquared, false ), + m_clLinksCLength( queue, ctx, &m_linksCLength, false ), + m_clLinksLengthRatio( queue, ctx, &m_linksLengthRatio, false ), + m_clLinksRestLength( queue, ctx, &m_linksRestLength, false ), + m_clLinksMaterialLinearStiffnessCoefficient( queue, ctx, &m_linksMaterialLinearStiffnessCoefficient, false ) +{ +} + +btSoftBodyLinkDataOpenCL::~btSoftBodyLinkDataOpenCL() +{ +} + +static Vectormath::Aos::Vector3 toVector3( const btVector3 &vec ) +{ + Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() ); + return outVec; +} + +/** Allocate enough space in all link-related arrays to fit numLinks links */ +void btSoftBodyLinkDataOpenCL::createLinks( int numLinks ) +{ + int previousSize = m_links.size(); + int newSize = previousSize + numLinks; + + btSoftBodyLinkData::createLinks( numLinks ); + + // Resize the link addresses array as well + m_linkAddresses.resize( newSize ); +} + +/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ +void btSoftBodyLinkDataOpenCL::setLinkAt( + const LinkDescription &link, + int linkIndex ) +{ + btSoftBodyLinkData::setLinkAt( link, linkIndex ); + + // Set the link index correctly for initialisation + m_linkAddresses[linkIndex] = linkIndex; +} + +bool btSoftBodyLinkDataOpenCL::onAccelerator() +{ + return m_onGPU; +} + +bool btSoftBodyLinkDataOpenCL::moveToAccelerator() +{ + bool success = true; + success = success && m_clLinks.moveToGPU(); + success = success && m_clLinkStrength.moveToGPU(); + success = success && m_clLinksMassLSC.moveToGPU(); + success = success && m_clLinksRestLengthSquared.moveToGPU(); + success = success && m_clLinksCLength.moveToGPU(); + success = success && m_clLinksLengthRatio.moveToGPU(); + success = success && m_clLinksRestLength.moveToGPU(); + success = success && m_clLinksMaterialLinearStiffnessCoefficient.moveToGPU(); + + if( success ) { + m_onGPU = true; + } + + return success; +} + +bool btSoftBodyLinkDataOpenCL::moveFromAccelerator() +{ + bool success = true; + success = success && m_clLinks.moveFromGPU(); + success = success && m_clLinkStrength.moveFromGPU(); + success = success && m_clLinksMassLSC.moveFromGPU(); + success = success && m_clLinksRestLengthSquared.moveFromGPU(); + success = success && m_clLinksCLength.moveFromGPU(); + success = success && m_clLinksLengthRatio.moveFromGPU(); + success = success && m_clLinksRestLength.moveFromGPU(); + success = success && m_clLinksMaterialLinearStiffnessCoefficient.moveFromGPU(); + + if( success ) { + m_onGPU = false; + } + + return success; +} + +/** + * Generate (and later update) the batching for the entire link set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ +void btSoftBodyLinkDataOpenCL::generateBatches() +{ + int numLinks = getNumLinks(); + + // Do the graph colouring here temporarily + btAlignedObjectArray< int > batchValues; + batchValues.resize( numLinks, 0 ); + + // Find the maximum vertex value internally for now + int maxVertex = 0; + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + int vertex0 = getVertexPair(linkIndex).vertex0; + int vertex1 = getVertexPair(linkIndex).vertex1; + if( vertex0 > maxVertex ) + maxVertex = vertex0; + if( vertex1 > maxVertex ) + maxVertex = vertex1; + } + int numVertices = maxVertex + 1; + + // Set of lists, one for each node, specifying which colours are connected + // to that node. + // No two edges into a node can share a colour. + btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists; + vertexConnectedColourLists.resize(numVertices); + + // Simple algorithm that chooses the lowest batch number + // that none of the links attached to either of the connected + // nodes is in + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + int linkLocation = m_linkAddresses[linkIndex]; + + int vertex0 = getVertexPair(linkLocation).vertex0; + int vertex1 = getVertexPair(linkLocation).vertex1; + + // Get the two node colour lists + btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] ); + btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] ); + + // Choose the minimum colour that is in neither list + int colour = 0; + while( colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() ) + ++colour; + // i should now be the minimum colour in neither list + // Add to the two lists so that future edges don't share + // And store the colour against this edge + + colourListVertex0.push_back(colour); + colourListVertex1.push_back(colour); + batchValues[linkIndex] = colour; + } + + // Check the colour counts + btAlignedObjectArray< int > batchCounts; + for( int i = 0; i < numLinks; ++i ) + { + int batch = batchValues[i]; + if( batch >= batchCounts.size() ) + batchCounts.push_back(1); + else + ++(batchCounts[batch]); + } + + m_batchStartLengths.resize(batchCounts.size()); + if( m_batchStartLengths.size() > 0 ) + { + m_batchStartLengths.resize(batchCounts.size()); + m_batchStartLengths[0] = BatchPair(0, 0); + + int sum = 0; + for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex ) + { + m_batchStartLengths[batchIndex].start = sum; + m_batchStartLengths[batchIndex].length = batchCounts[batchIndex]; + sum += batchCounts[batchIndex]; + } + } + + ///////////////////////////// + // Sort data based on batches + + // Create source arrays by copying originals + btAlignedObjectArray m_links_Backup(m_links); + btAlignedObjectArray m_linkStrength_Backup(m_linkStrength); + btAlignedObjectArray m_linksMassLSC_Backup(m_linksMassLSC); + btAlignedObjectArray m_linksRestLengthSquared_Backup(m_linksRestLengthSquared); + btAlignedObjectArray m_linksCLength_Backup(m_linksCLength); + btAlignedObjectArray m_linksLengthRatio_Backup(m_linksLengthRatio); + btAlignedObjectArray m_linksRestLength_Backup(m_linksRestLength); + btAlignedObjectArray m_linksMaterialLinearStiffnessCoefficient_Backup(m_linksMaterialLinearStiffnessCoefficient); + + + for( int batch = 0; batch < batchCounts.size(); ++batch ) + batchCounts[batch] = 0; + + // Do sort as single pass into destination arrays + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + // To maintain locations run off the original link locations rather than the current position. + // It's not cache efficient, but as we run this rarely that should not matter. + // It's faster than searching the link location array for the current location and then updating it. + // The other alternative would be to unsort before resorting, but this is equivalent to doing that. + int linkLocation = m_linkAddresses[linkIndex]; + + // Obtain batch and calculate target location for the + // next element in that batch, incrementing the batch counter + // afterwards + int batch = batchValues[linkIndex]; + int newLocation = m_batchStartLengths[batch].start + batchCounts[batch]; + + batchCounts[batch] = batchCounts[batch] + 1; + m_links[newLocation] = m_links_Backup[linkLocation]; +#if 1 + m_linkStrength[newLocation] = m_linkStrength_Backup[linkLocation]; + m_linksMassLSC[newLocation] = m_linksMassLSC_Backup[linkLocation]; + m_linksRestLengthSquared[newLocation] = m_linksRestLengthSquared_Backup[linkLocation]; + m_linksLengthRatio[newLocation] = m_linksLengthRatio_Backup[linkLocation]; + m_linksRestLength[newLocation] = m_linksRestLength_Backup[linkLocation]; + m_linksMaterialLinearStiffnessCoefficient[newLocation] = m_linksMaterialLinearStiffnessCoefficient_Backup[linkLocation]; +#endif + // Update the locations array to account for the moved entry + m_linkAddresses[linkIndex] = newLocation; + } + + +} // void generateBatches() + + + + + +btSoftBodyTriangleDataOpenCL::btSoftBodyTriangleDataOpenCL( cl_command_queue queue , cl_context ctx) : + m_queue( queue ), + m_clVertexIndices( queue, ctx, &m_vertexIndices, false ), + m_clArea( queue, ctx, &m_area, false ), + m_clNormal( queue, ctx, &m_normal, false ) +{ +} + +btSoftBodyTriangleDataOpenCL::~btSoftBodyTriangleDataOpenCL() +{ +} + +/** Allocate enough space in all link-related arrays to fit numLinks links */ +void btSoftBodyTriangleDataOpenCL::createTriangles( int numTriangles ) +{ + int previousSize = getNumTriangles(); + int newSize = previousSize + numTriangles; + + btSoftBodyTriangleData::createTriangles( numTriangles ); + + // Resize the link addresses array as well + m_triangleAddresses.resize( newSize ); +} + +/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ +void btSoftBodyTriangleDataOpenCL::setTriangleAt( const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex ) +{ + btSoftBodyTriangleData::setTriangleAt( triangle, triangleIndex ); + + m_triangleAddresses[triangleIndex] = triangleIndex; +} + +bool btSoftBodyTriangleDataOpenCL::onAccelerator() +{ + return m_onGPU; +} + +bool btSoftBodyTriangleDataOpenCL::moveToAccelerator() +{ + bool success = true; + success = success && m_clVertexIndices.moveToGPU(); + success = success && m_clArea.moveToGPU(); + success = success && m_clNormal.moveToGPU(); + + if( success ) + m_onGPU = true; + + return success; +} + +bool btSoftBodyTriangleDataOpenCL::moveFromAccelerator() +{ + bool success = true; + success = success && m_clVertexIndices.moveFromGPU(); + success = success && m_clArea.moveFromGPU(); + success = success && m_clNormal.moveFromGPU(); + + if( success ) + m_onGPU = true; + + return success; +} + +/** + * Generate (and later update) the batching for the entire triangle set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ +void btSoftBodyTriangleDataOpenCL::generateBatches() +{ + int numTriangles = getNumTriangles(); + if( numTriangles == 0 ) + return; + + // Do the graph colouring here temporarily + btAlignedObjectArray< int > batchValues; + batchValues.resize( numTriangles ); + + // Find the maximum vertex value internally for now + int maxVertex = 0; + for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) + { + int vertex0 = getVertexSet(triangleIndex).vertex0; + int vertex1 = getVertexSet(triangleIndex).vertex1; + int vertex2 = getVertexSet(triangleIndex).vertex2; + + if( vertex0 > maxVertex ) + maxVertex = vertex0; + if( vertex1 > maxVertex ) + maxVertex = vertex1; + if( vertex2 > maxVertex ) + maxVertex = vertex2; + } + int numVertices = maxVertex + 1; + + // Set of lists, one for each node, specifying which colours are connected + // to that node. + // No two edges into a node can share a colour. + btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists; + vertexConnectedColourLists.resize(numVertices); + + + //std::cout << "\n"; + // Simple algorithm that chooses the lowest batch number + // that none of the faces attached to either of the connected + // nodes is in + for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) + { + // To maintain locations run off the original link locations rather than the current position. + // It's not cache efficient, but as we run this rarely that should not matter. + // It's faster than searching the link location array for the current location and then updating it. + // The other alternative would be to unsort before resorting, but this is equivalent to doing that. + int triangleLocation = m_triangleAddresses[triangleIndex]; + + int vertex0 = getVertexSet(triangleLocation).vertex0; + int vertex1 = getVertexSet(triangleLocation).vertex1; + int vertex2 = getVertexSet(triangleLocation).vertex2; + + // Get the three node colour lists + btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] ); + btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] ); + btAlignedObjectArray< int > &colourListVertex2( vertexConnectedColourLists[vertex2] ); + + // Choose the minimum colour that is in none of the lists + int colour = 0; + while( + colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || + colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() || + colourListVertex2.findLinearSearch(colour) != colourListVertex2.size() ) + { + ++colour; + } + // i should now be the minimum colour in neither list + // Add to the three lists so that future edges don't share + // And store the colour against this face + colourListVertex0.push_back(colour); + colourListVertex1.push_back(colour); + colourListVertex2.push_back(colour); + + batchValues[triangleIndex] = colour; + } + + + // Check the colour counts + btAlignedObjectArray< int > batchCounts; + for( int i = 0; i < numTriangles; ++i ) + { + int batch = batchValues[i]; + if( batch >= batchCounts.size() ) + batchCounts.push_back(1); + else + ++(batchCounts[batch]); + } + + + m_batchStartLengths.resize(batchCounts.size()); + m_batchStartLengths[0] = btSomePair(0,0); + + + int sum = 0; + for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex ) + { + m_batchStartLengths[batchIndex].first = sum; + m_batchStartLengths[batchIndex].second = batchCounts[batchIndex]; + sum += batchCounts[batchIndex]; + } + + ///////////////////////////// + // Sort data based on batches + + // Create source arrays by copying originals + btAlignedObjectArray m_vertexIndices_Backup(m_vertexIndices); + btAlignedObjectArray m_area_Backup(m_area); + btAlignedObjectArray m_normal_Backup(m_normal); + + + for( int batch = 0; batch < batchCounts.size(); ++batch ) + batchCounts[batch] = 0; + + // Do sort as single pass into destination arrays + for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) + { + // To maintain locations run off the original link locations rather than the current position. + // It's not cache efficient, but as we run this rarely that should not matter. + // It's faster than searching the link location array for the current location and then updating it. + // The other alternative would be to unsort before resorting, but this is equivalent to doing that. + int triangleLocation = m_triangleAddresses[triangleIndex]; + + // Obtain batch and calculate target location for the + // next element in that batch, incrementing the batch counter + // afterwards + int batch = batchValues[triangleIndex]; + int newLocation = m_batchStartLengths[batch].first + batchCounts[batch]; + + batchCounts[batch] = batchCounts[batch] + 1; + m_vertexIndices[newLocation] = m_vertexIndices_Backup[triangleLocation]; + m_area[newLocation] = m_area_Backup[triangleLocation]; + m_normal[newLocation] = m_normal_Backup[triangleLocation]; + + // Update the locations array to account for the moved entry + m_triangleAddresses[triangleIndex] = newLocation; + } +} // btSoftBodyTriangleDataOpenCL::generateBatches + + + + + + + +btOpenCLSoftBodySolver::btOpenCLSoftBodySolver(cl_command_queue queue, cl_context ctx, bool bUpdateAchchoredNodePos) : + m_linkData(queue, ctx), + m_vertexData(queue, ctx), + m_triangleData(queue, ctx), + m_defaultCLFunctions(queue, ctx), + m_currentCLFunctions(&m_defaultCLFunctions), + m_clPerClothAcceleration(queue, ctx, &m_perClothAcceleration, true ), + m_clPerClothWindVelocity(queue, ctx, &m_perClothWindVelocity, true ), + m_clPerClothDampingFactor(queue,ctx, &m_perClothDampingFactor, true ), + m_clPerClothVelocityCorrectionCoefficient(queue, ctx,&m_perClothVelocityCorrectionCoefficient, true ), + m_clPerClothLiftFactor(queue, ctx,&m_perClothLiftFactor, true ), + m_clPerClothDragFactor(queue, ctx,&m_perClothDragFactor, true ), + m_clPerClothMediumDensity(queue, ctx,&m_perClothMediumDensity, true ), + m_clPerClothCollisionObjects( queue, ctx, &m_perClothCollisionObjects, true ), + m_clCollisionObjectDetails( queue, ctx, &m_collisionObjectDetails, true ), + m_clPerClothFriction( queue, ctx, &m_perClothFriction, false ), + m_clAnchorPosition( queue, ctx, &m_anchorPosition, true ), + m_clAnchorIndex( queue, ctx, &m_anchorIndex, true), + m_cqCommandQue( queue ), + m_cxMainContext(ctx), + m_defaultWorkGroupSize(BT_DEFAULT_WORKGROUPSIZE), + m_bUpdateAnchoredNodePos(bUpdateAchchoredNodePos) +{ + + // Initial we will clearly need to update solver constants + // For now this is global for the cloths linked with this solver - we should probably make this body specific + // for performance in future once we understand more clearly when constants need to be updated + m_updateSolverConstants = true; + + m_shadersInitialized = false; + + m_prepareLinksKernel = 0; + m_solvePositionsFromLinksKernel = 0; + m_updateConstantsKernel = 0; + m_integrateKernel = 0; + m_addVelocityKernel = 0; + m_updatePositionsFromVelocitiesKernel = 0; + m_updateVelocitiesFromPositionsWithoutVelocitiesKernel = 0; + m_updateVelocitiesFromPositionsWithVelocitiesKernel = 0; + m_vSolveLinksKernel = 0; + m_solveCollisionsAndUpdateVelocitiesKernel = 0; + m_resetNormalsAndAreasKernel = 0; + m_updateSoftBodiesKernel = 0; + m_normalizeNormalsAndAreasKernel = 0; + m_outputToVertexArrayKernel = 0; + m_applyForcesKernel = 0; + m_updateFixedVertexPositionsKernel = 0; +} + +btOpenCLSoftBodySolver::~btOpenCLSoftBodySolver() +{ + releaseKernels(); +} + +void btOpenCLSoftBodySolver::releaseKernels() +{ + RELEASE_CL_KERNEL( m_prepareLinksKernel ); + RELEASE_CL_KERNEL( m_solvePositionsFromLinksKernel ); + RELEASE_CL_KERNEL( m_updateConstantsKernel ); + RELEASE_CL_KERNEL( m_integrateKernel ); + RELEASE_CL_KERNEL( m_addVelocityKernel ); + RELEASE_CL_KERNEL( m_updatePositionsFromVelocitiesKernel ); + RELEASE_CL_KERNEL( m_updateVelocitiesFromPositionsWithoutVelocitiesKernel ); + RELEASE_CL_KERNEL( m_updateVelocitiesFromPositionsWithVelocitiesKernel ); + RELEASE_CL_KERNEL( m_vSolveLinksKernel ); + RELEASE_CL_KERNEL( m_solveCollisionsAndUpdateVelocitiesKernel ); + RELEASE_CL_KERNEL( m_resetNormalsAndAreasKernel ); + RELEASE_CL_KERNEL( m_normalizeNormalsAndAreasKernel ); + RELEASE_CL_KERNEL( m_outputToVertexArrayKernel ); + RELEASE_CL_KERNEL( m_applyForcesKernel ); + RELEASE_CL_KERNEL( m_updateFixedVertexPositionsKernel ); + + m_shadersInitialized = false; +} + +void btOpenCLSoftBodySolver::copyBackToSoftBodies(bool bMove) +{ + + // Move the vertex data back to the host first + m_vertexData.moveFromAccelerator(!bMove); + + // Loop over soft bodies, copying all the vertex positions back for each body in turn + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btOpenCLAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[ softBodyIndex ]; + btSoftBody *softBody = softBodyInterface->getSoftBody(); + + int firstVertex = softBodyInterface->getFirstVertex(); + int numVertices = softBodyInterface->getNumVertices(); + + // Copy vertices from solver back into the softbody + for( int vertex = 0; vertex < numVertices; ++vertex ) + { + using Vectormath::Aos::Point3; + Point3 vertexPosition( m_vertexData.getVertexPositions()[firstVertex + vertex] ); + Point3 normal(m_vertexData.getNormal(firstVertex + vertex)); + + softBody->m_nodes[vertex].m_x.setX( vertexPosition.getX() ); + softBody->m_nodes[vertex].m_x.setY( vertexPosition.getY() ); + softBody->m_nodes[vertex].m_x.setZ( vertexPosition.getZ() ); + + softBody->m_nodes[vertex].m_n.setX( normal.getX() ); + softBody->m_nodes[vertex].m_n.setY( normal.getY() ); + softBody->m_nodes[vertex].m_n.setZ( normal.getZ() ); + } + } +} // btOpenCLSoftBodySolver::copyBackToSoftBodies + +void btOpenCLSoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies, bool forceUpdate ) +{ + if( forceUpdate || m_softBodySet.size() != softBodies.size() ) + { + // Have a change in the soft body set so update, reloading all the data + getVertexData().clear(); + getTriangleData().clear(); + getLinkData().clear(); + m_softBodySet.resize(0); + m_anchorIndex.clear(); + + int maxPiterations = 0; + int maxViterations = 0; + + for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex ) + { + btSoftBody *softBody = softBodies[ softBodyIndex ]; + using Vectormath::Aos::Matrix3; + using Vectormath::Aos::Point3; + + // Create SoftBody that will store the information within the solver + btOpenCLAcceleratedSoftBodyInterface *newSoftBody = new btOpenCLAcceleratedSoftBodyInterface( softBody ); + m_softBodySet.push_back( newSoftBody ); + + m_perClothAcceleration.push_back( toVector3(softBody->getWorldInfo()->m_gravity) ); + m_perClothDampingFactor.push_back(softBody->m_cfg.kDP); + m_perClothVelocityCorrectionCoefficient.push_back( softBody->m_cfg.kVCF ); + m_perClothLiftFactor.push_back( softBody->m_cfg.kLF ); + m_perClothDragFactor.push_back( softBody->m_cfg.kDG ); + m_perClothMediumDensity.push_back(softBody->getWorldInfo()->air_density); + // Simple init values. Actually we'll put 0 and -1 into them at the appropriate time + m_perClothFriction.push_back(softBody->m_cfg.kDF); + m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) ); + + // Add space for new vertices and triangles in the default solver for now + // TODO: Include space here for tearing too later + int firstVertex = getVertexData().getNumVertices(); + int numVertices = softBody->m_nodes.size(); + int maxVertices = numVertices; + // Allocate space for new vertices in all the vertex arrays + getVertexData().createVertices( maxVertices, softBodyIndex ); + + int firstTriangle = getTriangleData().getNumTriangles(); + int numTriangles = softBody->m_faces.size(); + int maxTriangles = numTriangles; + getTriangleData().createTriangles( maxTriangles ); + + // Copy vertices from softbody into the solver + for( int vertex = 0; vertex < numVertices; ++vertex ) + { + Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ()); + btSoftBodyVertexData::VertexDescription desc; + + // TODO: Position in the softbody might be pre-transformed + // or we may need to adapt for the pose. + //desc.setPosition( cloth.getMeshTransform()*multPoint ); + desc.setPosition( multPoint ); + + float vertexInverseMass = softBody->m_nodes[vertex].m_im; + desc.setInverseMass(vertexInverseMass); + getVertexData().setVertexAt( desc, firstVertex + vertex ); + + m_anchorIndex.push_back(-1.0); + } + + // Copy triangles similarly + // We're assuming here that vertex indices are based on the firstVertex rather than the entire scene + for( int triangle = 0; triangle < numTriangles; ++triangle ) + { + // Note that large array storage is relative to the array not to the cloth + // So we need to add firstVertex to each value + int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0])); + int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0])); + int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0])); + btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex); + getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle ); + + // Increase vertex triangle counts for this triangle + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex0)++; + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex1)++; + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex2)++; + } + + int firstLink = getLinkData().getNumLinks(); + int numLinks = softBody->m_links.size(); + int maxLinks = numLinks; + + // Allocate space for the links + getLinkData().createLinks( numLinks ); + + // Add the links + for( int link = 0; link < numLinks; ++link ) + { + int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]); + int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]); + + btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST); + newLink.setLinkStrength(1.f); + getLinkData().setLinkAt(newLink, firstLink + link); + } + + newSoftBody->setFirstVertex( firstVertex ); + newSoftBody->setFirstTriangle( firstTriangle ); + newSoftBody->setNumVertices( numVertices ); + newSoftBody->setMaxVertices( maxVertices ); + newSoftBody->setNumTriangles( numTriangles ); + newSoftBody->setMaxTriangles( maxTriangles ); + newSoftBody->setFirstLink( firstLink ); + newSoftBody->setNumLinks( numLinks ); + + // Find maximum piterations and viterations + int piterations = softBody->m_cfg.piterations; + + if ( piterations > maxPiterations ) + maxPiterations = piterations; + + int viterations = softBody->m_cfg.viterations; + + if ( viterations > maxViterations ) + maxViterations = viterations; + + // zero mass + for( int vertex = 0; vertex < numVertices; ++vertex ) + { + if ( softBody->m_nodes[vertex].m_im == 0 ) + { + AnchorNodeInfoCL nodeInfo; + nodeInfo.clVertexIndex = firstVertex + vertex; + nodeInfo.pNode = &softBody->m_nodes[vertex]; + + m_anchorNodeInfoArray.push_back(nodeInfo); + } + } + + // anchor position + if ( numVertices > 0 ) + { + for ( int anchorIndex = 0; anchorIndex < softBody->m_anchors.size(); anchorIndex++ ) + { + btSoftBody::Node* anchorNode = softBody->m_anchors[anchorIndex].m_node; + btSoftBody::Node* firstNode = &softBody->m_nodes[0]; + + AnchorNodeInfoCL nodeInfo; + nodeInfo.clVertexIndex = firstVertex + (int)(anchorNode - firstNode); + nodeInfo.pNode = anchorNode; + + m_anchorNodeInfoArray.push_back(nodeInfo); + } + } + } + + + m_anchorPosition.clear(); + m_anchorPosition.resize(m_anchorNodeInfoArray.size()); + + for ( int anchorNode = 0; anchorNode < m_anchorNodeInfoArray.size(); anchorNode++ ) + { + const AnchorNodeInfoCL& anchorNodeInfo = m_anchorNodeInfoArray[anchorNode]; + m_anchorIndex[anchorNodeInfo.clVertexIndex] = anchorNode; + getVertexData().getInverseMass(anchorNodeInfo.clVertexIndex) = 0.0f; + } + + updateConstants(0.f); + + // set position and velocity iterations + setNumberOfPositionIterations(maxPiterations); + setNumberOfVelocityIterations(maxViterations); + + // set wind velocity + m_perClothWindVelocity.resize( m_softBodySet.size() ); + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btSoftBody *softBody = m_softBodySet[softBodyIndex]->getSoftBody(); + m_perClothWindVelocity[softBodyIndex] = toVector3(softBody->getWindVelocity()); + } + + m_clPerClothWindVelocity.changedOnCPU(); + + // generate batches + m_linkData.generateBatches(); + m_triangleData.generateBatches(); + + // Build the shaders to match the batching parameters + buildShaders(); + } +} + + +btSoftBodyLinkData &btOpenCLSoftBodySolver::getLinkData() +{ + // TODO: Consider setting link data to "changed" here + return m_linkData; +} + +btSoftBodyVertexData &btOpenCLSoftBodySolver::getVertexData() +{ + // TODO: Consider setting vertex data to "changed" here + return m_vertexData; +} + +btSoftBodyTriangleData &btOpenCLSoftBodySolver::getTriangleData() +{ + // TODO: Consider setting triangle data to "changed" here + return m_triangleData; +} + +void btOpenCLSoftBodySolver::resetNormalsAndAreas( int numVertices ) +{ + cl_int ciErrNum; + ciErrNum = clSetKernelArg(m_resetNormalsAndAreasKernel, 0, sizeof(numVertices), (void*)&numVertices); //oclCHECKERROR(ciErrNum, CL_SUCCESS); + ciErrNum = clSetKernelArg(m_resetNormalsAndAreasKernel, 1, sizeof(cl_mem), (void*)&m_vertexData.m_clVertexNormal.m_buffer);//oclCHECKERROR(ciErrNum, CL_SUCCESS); + ciErrNum = clSetKernelArg(m_resetNormalsAndAreasKernel, 2, sizeof(cl_mem), (void*)&m_vertexData.m_clVertexArea.m_buffer); //oclCHECKERROR(ciErrNum, CL_SUCCESS); + size_t numWorkItems = m_defaultWorkGroupSize*((numVertices + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + + if (numWorkItems) + { + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, m_resetNormalsAndAreasKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize, 0,0,0 ); + + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_resetNormalsAndAreasKernel)" ); + } + } + +} + +void btOpenCLSoftBodySolver::normalizeNormalsAndAreas( int numVertices ) +{ + cl_int ciErrNum; + + ciErrNum = clSetKernelArg(m_normalizeNormalsAndAreasKernel, 0, sizeof(int),(void*) &numVertices); + ciErrNum = clSetKernelArg(m_normalizeNormalsAndAreasKernel, 1, sizeof(cl_mem), &m_vertexData.m_clVertexTriangleCount.m_buffer); + ciErrNum = clSetKernelArg(m_normalizeNormalsAndAreasKernel, 2, sizeof(cl_mem), &m_vertexData.m_clVertexNormal.m_buffer); + ciErrNum = clSetKernelArg(m_normalizeNormalsAndAreasKernel, 3, sizeof(cl_mem), &m_vertexData.m_clVertexArea.m_buffer); + size_t numWorkItems = m_defaultWorkGroupSize*((numVertices + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + if (numWorkItems) + { + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, m_normalizeNormalsAndAreasKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize, 0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_normalizeNormalsAndAreasKernel)"); + } + } + +} + +void btOpenCLSoftBodySolver::executeUpdateSoftBodies( int firstTriangle, int numTriangles ) +{ + cl_int ciErrNum; + ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 0, sizeof(int), (void*) &firstTriangle); + ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 1, sizeof(int), &numTriangles); + ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 2, sizeof(cl_mem), &m_triangleData.m_clVertexIndices.m_buffer); + ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 3, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); + ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 4, sizeof(cl_mem), &m_vertexData.m_clVertexNormal.m_buffer); + ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 5, sizeof(cl_mem), &m_vertexData.m_clVertexArea.m_buffer); + ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 6, sizeof(cl_mem), &m_triangleData.m_clNormal.m_buffer); + ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 7, sizeof(cl_mem), &m_triangleData.m_clArea.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((numTriangles + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, m_updateSoftBodiesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_normalizeNormalsAndAreasKernel)"); + } + +} + +void btOpenCLSoftBodySolver::updateSoftBodies() +{ + using namespace Vectormath::Aos; + + + int numVertices = m_vertexData.getNumVertices(); + int numTriangles = m_triangleData.getNumTriangles(); + + // Ensure data is on accelerator + m_vertexData.moveToAccelerator(); + m_triangleData.moveToAccelerator(); + + resetNormalsAndAreas( numVertices ); + + + // Go through triangle batches so updates occur correctly + for( int batchIndex = 0; batchIndex < m_triangleData.m_batchStartLengths.size(); ++batchIndex ) + { + + int startTriangle = m_triangleData.m_batchStartLengths[batchIndex].first; + int numTriangles = m_triangleData.m_batchStartLengths[batchIndex].second; + + executeUpdateSoftBodies( startTriangle, numTriangles ); + } + + + normalizeNormalsAndAreas( numVertices ); +} // updateSoftBodies + + +Vectormath::Aos::Vector3 btOpenCLSoftBodySolver::ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a ) +{ + return a*Vectormath::Aos::dot(v, a); +} + +void btOpenCLSoftBodySolver::ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce ) +{ + float dtInverseMass = solverdt*inverseMass; + if( Vectormath::Aos::lengthSqr(force * dtInverseMass) > Vectormath::Aos::lengthSqr(vertexVelocity) ) + { + vertexForce -= ProjectOnAxis( vertexVelocity, normalize( force ) )/dtInverseMass; + } else { + vertexForce += force; + } +} + +void btOpenCLSoftBodySolver::updateFixedVertexPositions() +{ + // Ensure data is on accelerator + m_vertexData.moveToAccelerator(); + m_clAnchorPosition.moveToGPU(); + m_clAnchorIndex.moveToGPU(); + + cl_int ciErrNum ; + int numVerts = m_vertexData.getNumVertices(); + ciErrNum = clSetKernelArg(m_updateFixedVertexPositionsKernel, 0, sizeof(int), &numVerts); + ciErrNum = clSetKernelArg(m_updateFixedVertexPositionsKernel,1, sizeof(cl_mem), &m_clAnchorIndex.m_buffer); + ciErrNum = clSetKernelArg(m_updateFixedVertexPositionsKernel,2, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); + ciErrNum = clSetKernelArg(m_updateFixedVertexPositionsKernel,3, sizeof(cl_mem), &m_clAnchorPosition.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + if (numWorkItems) + { + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_updateFixedVertexPositionsKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize, 0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_updateFixedVertexPositionsKernel)"); + } + } + +} + +void btOpenCLSoftBodySolver::applyForces( float solverdt ) +{ + // Ensure data is on accelerator + m_vertexData.moveToAccelerator(); + m_clPerClothAcceleration.moveToGPU(); + m_clPerClothLiftFactor.moveToGPU(); + m_clPerClothDragFactor.moveToGPU(); + m_clPerClothMediumDensity.moveToGPU(); + m_clPerClothWindVelocity.moveToGPU(); + + cl_int ciErrNum ; + int numVerts = m_vertexData.getNumVertices(); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 0, sizeof(int), &numVerts); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 1, sizeof(float), &solverdt); + float fl = FLT_EPSILON; + ciErrNum = clSetKernelArg(m_applyForcesKernel, 2, sizeof(float), &fl); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 3, sizeof(cl_mem), &m_vertexData.m_clClothIdentifier.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 4, sizeof(cl_mem), &m_vertexData.m_clVertexNormal.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 5, sizeof(cl_mem), &m_vertexData.m_clVertexArea.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 6, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 7, sizeof(cl_mem), &m_clPerClothLiftFactor.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 8 ,sizeof(cl_mem), &m_clPerClothDragFactor.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 9, sizeof(cl_mem), &m_clPerClothWindVelocity.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel,10, sizeof(cl_mem), &m_clPerClothAcceleration.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel,11, sizeof(cl_mem), &m_clPerClothMediumDensity.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel,12, sizeof(cl_mem), &m_vertexData.m_clVertexForceAccumulator.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel,13, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + if (numWorkItems) + { + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_applyForcesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize, 0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_applyForcesKernel)"); + } + } + +} + +/** + * Integrate motion on the solver. + */ +void btOpenCLSoftBodySolver::integrate( float solverdt ) +{ + // Ensure data is on accelerator + m_vertexData.moveToAccelerator(); + + cl_int ciErrNum; + int numVerts = m_vertexData.getNumVertices(); + ciErrNum = clSetKernelArg(m_integrateKernel, 0, sizeof(int), &numVerts); + ciErrNum = clSetKernelArg(m_integrateKernel, 1, sizeof(float), &solverdt); + ciErrNum = clSetKernelArg(m_integrateKernel, 2, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer); + ciErrNum = clSetKernelArg(m_integrateKernel, 3, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); + ciErrNum = clSetKernelArg(m_integrateKernel, 4, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer); + ciErrNum = clSetKernelArg(m_integrateKernel, 5, sizeof(cl_mem), &m_vertexData.m_clVertexPreviousPosition.m_buffer); + ciErrNum = clSetKernelArg(m_integrateKernel, 6, sizeof(cl_mem), &m_vertexData.m_clVertexForceAccumulator.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + if (numWorkItems) + { + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_integrateKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_integrateKernel)"); + } + } + +} + +float btOpenCLSoftBodySolver::computeTriangleArea( + const Vectormath::Aos::Point3 &vertex0, + const Vectormath::Aos::Point3 &vertex1, + const Vectormath::Aos::Point3 &vertex2 ) +{ + Vectormath::Aos::Vector3 a = vertex1 - vertex0; + Vectormath::Aos::Vector3 b = vertex2 - vertex0; + Vectormath::Aos::Vector3 crossProduct = cross(a, b); + float area = length( crossProduct ); + return area; +} + + +void btOpenCLSoftBodySolver::updateBounds() +{ + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btVector3 minBound(-1e30,-1e30,-1e30), maxBound(1e30,1e30,1e30); + m_softBodySet[softBodyIndex]->updateBounds( minBound, maxBound ); + } + +} // btOpenCLSoftBodySolver::updateBounds + + +void btOpenCLSoftBodySolver::updateConstants( float timeStep ) +{ + + using namespace Vectormath::Aos; + + if( m_updateSolverConstants ) + { + m_updateSolverConstants = false; + + // Will have to redo this if we change the structure (tear, maybe) or various other possible changes + + // Initialise link constants + const int numLinks = m_linkData.getNumLinks(); + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair &vertices( m_linkData.getVertexPair(linkIndex) ); + m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 ))); + float invMass0 = m_vertexData.getInverseMass(vertices.vertex0); + float invMass1 = m_vertexData.getInverseMass(vertices.vertex1); + float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex); + float massLSC = (invMass0 + invMass1)/linearStiffness; + m_linkData.getMassLSC(linkIndex) = massLSC; + float restLength = m_linkData.getRestLength(linkIndex); + float restLengthSquared = restLength*restLength; + m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared; + } + } + +} + +class QuickSortCompare +{ + public: + + bool operator() ( const CollisionShapeDescription& a, const CollisionShapeDescription& b ) const + { + return ( a.softBodyIdentifier < b.softBodyIdentifier ); + } +}; + + +/** + * Sort the collision object details array and generate indexing into it for the per-cloth collision object array. + */ +void btOpenCLSoftBodySolver::prepareCollisionConstraints() +{ + // First do a simple sort on the collision objects + btAlignedObjectArray numObjectsPerClothPrefixSum; + btAlignedObjectArray numObjectsPerCloth; + numObjectsPerCloth.resize( m_softBodySet.size(), 0 ); + numObjectsPerClothPrefixSum.resize( m_softBodySet.size(), 0 ); + + + + m_collisionObjectDetails.quickSort( QuickSortCompare() ); + + if (!m_perClothCollisionObjects.size()) + return; + + // Generating indexing for perClothCollisionObjects + // First clear the previous values with the "no collision object for cloth" constant + for( int clothIndex = 0; clothIndex < m_perClothCollisionObjects.size(); ++clothIndex ) + { + m_perClothCollisionObjects[clothIndex].firstObject = -1; + m_perClothCollisionObjects[clothIndex].endObject = -1; + } + int currentCloth = 0; + int startIndex = 0; + for( int collisionObject = 0; collisionObject < m_collisionObjectDetails.size(); ++collisionObject ) + { + int nextCloth = m_collisionObjectDetails[collisionObject].softBodyIdentifier; + if( nextCloth != currentCloth ) + { + // Changed cloth in the array + // Set the end index and the range is what we need for currentCloth + m_perClothCollisionObjects[currentCloth].firstObject = startIndex; + m_perClothCollisionObjects[currentCloth].endObject = collisionObject; + currentCloth = nextCloth; + startIndex = collisionObject; + } + } + + // And update last cloth + m_perClothCollisionObjects[currentCloth].firstObject = startIndex; + m_perClothCollisionObjects[currentCloth].endObject = m_collisionObjectDetails.size(); + +} // btOpenCLSoftBodySolver::prepareCollisionConstraints + + + +void btOpenCLSoftBodySolver::solveConstraints( float solverdt ) +{ + + using Vectormath::Aos::Vector3; + using Vectormath::Aos::Point3; + using Vectormath::Aos::lengthSqr; + using Vectormath::Aos::dot; + + // Prepare links + int numLinks = m_linkData.getNumLinks(); + int numVertices = m_vertexData.getNumVertices(); + + float kst = 1.f; + float ti = 0.f; + + + m_clPerClothDampingFactor.moveToGPU(); + m_clPerClothVelocityCorrectionCoefficient.moveToGPU(); + + + // Ensure data is on accelerator + m_linkData.moveToAccelerator(); + m_vertexData.moveToAccelerator(); + + prepareLinks(); + + + + for( int iteration = 0; iteration < m_numberOfVelocityIterations ; ++iteration ) + { + for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i ) + { + int startLink = m_linkData.m_batchStartLengths[i].start; + int numLinks = m_linkData.m_batchStartLengths[i].length; + + solveLinksForVelocity( startLink, numLinks, kst ); + } + } + + + prepareCollisionConstraints(); + + // Compute new positions from velocity + // Also update the previous position so that our position computation is now based on the new position from the velocity solution + // rather than based directly on the original positions + if( m_numberOfVelocityIterations > 0 ) + { + updateVelocitiesFromPositionsWithVelocities( 1.f/solverdt ); + } else { + updateVelocitiesFromPositionsWithoutVelocities( 1.f/solverdt ); + } + + // Solve position + for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) + { + for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i ) + { + int startLink = m_linkData.m_batchStartLengths[i].start; + int numLinks = m_linkData.m_batchStartLengths[i].length; + + solveLinksForPosition( startLink, numLinks, kst, ti ); + } + + } // for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) + + + // At this point assume that the force array is blank - we will overwrite it + solveCollisionsAndUpdateVelocities( 1.f/solverdt ); + +} + + +////////////////////////////////////// +// Kernel dispatches +void btOpenCLSoftBodySolver::prepareLinks() +{ + cl_int ciErrNum; + int numLinks = m_linkData.getNumLinks(); + ciErrNum = clSetKernelArg(m_prepareLinksKernel,0, sizeof(int), &numLinks); + ciErrNum = clSetKernelArg(m_prepareLinksKernel,1, sizeof(cl_mem), &m_linkData.m_clLinks.m_buffer); + ciErrNum = clSetKernelArg(m_prepareLinksKernel,2, sizeof(cl_mem), &m_linkData.m_clLinksMassLSC.m_buffer); + ciErrNum = clSetKernelArg(m_prepareLinksKernel,3, sizeof(cl_mem), &m_vertexData.m_clVertexPreviousPosition.m_buffer); + ciErrNum = clSetKernelArg(m_prepareLinksKernel,4, sizeof(cl_mem), &m_linkData.m_clLinksLengthRatio.m_buffer); + ciErrNum = clSetKernelArg(m_prepareLinksKernel,5, sizeof(cl_mem), &m_linkData.m_clLinksCLength.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((m_linkData.getNumLinks() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_prepareLinksKernel, 1 , NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_prepareLinksKernel)"); + } + +} + +void btOpenCLSoftBodySolver::updatePositionsFromVelocities( float solverdt ) +{ + cl_int ciErrNum; + int numVerts = m_vertexData.getNumVertices(); + ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,0, sizeof(int), &numVerts); + ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,1, sizeof(float), &solverdt); + ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,2, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer); + ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,3, sizeof(cl_mem), &m_vertexData.m_clVertexPreviousPosition.m_buffer); + ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,4, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_updatePositionsFromVelocitiesKernel, 1, NULL, &numWorkItems,&m_defaultWorkGroupSize,0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_updatePositionsFromVelocitiesKernel)"); + } + +} + +void btOpenCLSoftBodySolver::solveLinksForPosition( int startLink, int numLinks, float kst, float ti ) +{ + cl_int ciErrNum; + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,0, sizeof(int), &startLink); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,1, sizeof(int), &numLinks); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,2, sizeof(float), &kst); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,3, sizeof(float), &ti); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,4, sizeof(cl_mem), &m_linkData.m_clLinks.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,5, sizeof(cl_mem), &m_linkData.m_clLinksMassLSC.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,6, sizeof(cl_mem), &m_linkData.m_clLinksRestLengthSquared.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,7, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,8, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((numLinks + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_solvePositionsFromLinksKernel,1,NULL,&numWorkItems,&m_defaultWorkGroupSize,0,0,0); + if( ciErrNum!= CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_solvePositionsFromLinksKernel)"); + } + +} // solveLinksForPosition + + +void btOpenCLSoftBodySolver::solveLinksForVelocity( int startLink, int numLinks, float kst ) +{ + cl_int ciErrNum; + ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 0, sizeof(int), &startLink); + ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 1, sizeof(int), &numLinks); + ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 2, sizeof(float), &kst); + ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 3, sizeof(cl_mem), &m_linkData.m_clLinks.m_buffer); + ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 4, sizeof(cl_mem), &m_linkData.m_clLinksLengthRatio.m_buffer); + ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 5, sizeof(cl_mem), &m_linkData.m_clLinksCLength.m_buffer); + ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 6, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer); + ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 7, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((numLinks + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_vSolveLinksKernel,1,NULL,&numWorkItems, &m_defaultWorkGroupSize,0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_vSolveLinksKernel)"); + } + +} + +void btOpenCLSoftBodySolver::updateVelocitiesFromPositionsWithVelocities( float isolverdt ) +{ + cl_int ciErrNum; + int numVerts = m_vertexData.getNumVertices(); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel,0, sizeof(int), &numVerts); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 1, sizeof(float), &isolverdt); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 2, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 3, sizeof(cl_mem), &m_vertexData.m_clVertexPreviousPosition.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 4, sizeof(cl_mem), &m_vertexData.m_clClothIdentifier.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 5, sizeof(cl_mem), &m_clPerClothVelocityCorrectionCoefficient.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 6, sizeof(cl_mem), &m_clPerClothDampingFactor.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 7, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 8, sizeof(cl_mem), &m_vertexData.m_clVertexForceAccumulator.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_updateVelocitiesFromPositionsWithVelocitiesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_updateVelocitiesFromPositionsWithVelocitiesKernel)"); + } + + +} // updateVelocitiesFromPositionsWithVelocities + +void btOpenCLSoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities( float isolverdt ) +{ + cl_int ciErrNum; + int numVerts = m_vertexData.getNumVertices(); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 0, sizeof(int), &numVerts); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 1, sizeof(float), &isolverdt); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 2, sizeof(cl_mem),&m_vertexData.m_clVertexPosition.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 3, sizeof(cl_mem),&m_vertexData.m_clVertexPreviousPosition.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 4, sizeof(cl_mem),&m_vertexData.m_clClothIdentifier.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 5, sizeof(cl_mem),&m_clPerClothDampingFactor.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 6, sizeof(cl_mem),&m_vertexData.m_clVertexVelocity.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 7, sizeof(cl_mem),&m_vertexData.m_clVertexForceAccumulator.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel)"); + } + +} // updateVelocitiesFromPositionsWithoutVelocities + + + +void btOpenCLSoftBodySolver::solveCollisionsAndUpdateVelocities( float isolverdt ) +{ + // Copy kernel parameters to GPU + m_vertexData.moveToAccelerator(); + m_clPerClothFriction.moveToGPU(); + m_clPerClothDampingFactor.moveToGPU(); + m_clPerClothCollisionObjects.moveToGPU(); + m_clCollisionObjectDetails.moveToGPU(); + + cl_int ciErrNum; + int numVerts = m_vertexData.getNumVertices(); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 0, sizeof(int), &numVerts); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 1, sizeof(int), &isolverdt); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 2, sizeof(cl_mem),&m_vertexData.m_clClothIdentifier.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 3, sizeof(cl_mem),&m_vertexData.m_clVertexPreviousPosition.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 4, sizeof(cl_mem),&m_clPerClothFriction.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 5, sizeof(cl_mem),&m_clPerClothDampingFactor.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 6, sizeof(cl_mem),&m_clPerClothCollisionObjects.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 7, sizeof(cl_mem),&m_clCollisionObjectDetails.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 8, sizeof(cl_mem),&m_vertexData.m_clVertexForceAccumulator.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 9, sizeof(cl_mem),&m_vertexData.m_clVertexVelocity.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 10, sizeof(cl_mem),&m_vertexData.m_clVertexPosition.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + if (numWorkItems) + { + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_solveCollisionsAndUpdateVelocitiesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel)"); + } + } + +} // btOpenCLSoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities + + + +// End kernel dispatches +///////////////////////////////////// + + +void btSoftBodySolverOutputCLtoCPU::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) +{ + + btSoftBodySolver *solver = softBody->getSoftBodySolver(); + btAssert( solver->getSolverType() == btSoftBodySolver::CL_SOLVER || solver->getSolverType() == btSoftBodySolver::CL_SIMD_SOLVER ); + btOpenCLSoftBodySolver *dxSolver = static_cast< btOpenCLSoftBodySolver * >( solver ); + + btOpenCLAcceleratedSoftBodyInterface* currentCloth = dxSolver->findSoftBodyInterface( softBody ); + btSoftBodyVertexDataOpenCL &vertexData( dxSolver->m_vertexData ); + + + const int firstVertex = currentCloth->getFirstVertex(); + const int lastVertex = firstVertex + currentCloth->getNumVertices(); + + if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER ) + { + const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast< btCPUVertexBufferDescriptor* >(vertexBuffer); + float *basePointer = cpuVertexBuffer->getBasePointer(); + + vertexData.m_clVertexPosition.copyFromGPU(); + vertexData.m_clVertexNormal.copyFromGPU(); + + if( vertexBuffer->hasVertexPositions() ) + { + const int vertexOffset = cpuVertexBuffer->getVertexOffset(); + const int vertexStride = cpuVertexBuffer->getVertexStride(); + float *vertexPointer = basePointer + vertexOffset; + + for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex ) + { + Vectormath::Aos::Point3 position = vertexData.getPosition(vertexIndex); + *(vertexPointer + 0) = position.getX(); + *(vertexPointer + 1) = position.getY(); + *(vertexPointer + 2) = position.getZ(); + vertexPointer += vertexStride; + } + } + if( vertexBuffer->hasNormals() ) + { + const int normalOffset = cpuVertexBuffer->getNormalOffset(); + const int normalStride = cpuVertexBuffer->getNormalStride(); + float *normalPointer = basePointer + normalOffset; + + for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex ) + { + Vectormath::Aos::Vector3 normal = vertexData.getNormal(vertexIndex); + *(normalPointer + 0) = normal.getX(); + *(normalPointer + 1) = normal.getY(); + *(normalPointer + 2) = normal.getZ(); + normalPointer += normalStride; + } + } + } + +} // btSoftBodySolverOutputCLtoCPU::outputToVertexBuffers + + + +cl_kernel CLFunctions::compileCLKernelFromString( const char* kernelSource, const char* kernelName, const char* additionalMacros ,const char* orgSrcFileNameForCaching) +{ + printf("compiling kernelName: %s ",kernelName); + cl_kernel kernel=0; + cl_int ciErrNum; + size_t program_length = strlen(kernelSource); + + cl_program m_cpProgram = clCreateProgramWithSource(m_cxMainContext, 1, (const char**)&kernelSource, &program_length, &ciErrNum); +// oclCHECKERROR(ciErrNum, CL_SUCCESS); + + // Build the program with 'mad' Optimization option + + +#ifdef MAC + char* flags = "-cl-mad-enable -DMAC -DGUID_ARG"; +#else + //const char* flags = "-DGUID_ARG= -fno-alias"; + const char* flags = "-DGUID_ARG= "; +#endif + + char* compileFlags = new char[strlen(additionalMacros) + strlen(flags) + 5]; + sprintf(compileFlags, "%s %s", flags, additionalMacros); + ciErrNum = clBuildProgram(m_cpProgram, 0, NULL, compileFlags, NULL, NULL); + if (ciErrNum != CL_SUCCESS) + { + size_t numDevices; + clGetProgramInfo( m_cpProgram, CL_PROGRAM_DEVICES, 0, 0, &numDevices ); + cl_device_id *devices = new cl_device_id[numDevices]; + clGetProgramInfo( m_cpProgram, CL_PROGRAM_DEVICES, numDevices, devices, &numDevices ); + for( int i = 0; i < 2; ++i ) + { + char *build_log; + size_t ret_val_size; + clGetProgramBuildInfo(m_cpProgram, devices[i], CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size); + build_log = new char[ret_val_size+1]; + clGetProgramBuildInfo(m_cpProgram, devices[i], CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL); + + // to be carefully, terminate with \0 + // there's no information in the reference whether the string is 0 terminated or not + build_log[ret_val_size] = '\0'; + + + printf("Error in clBuildProgram, Line %u in file %s, Log: \n%s\n !!!\n\n", __LINE__, __FILE__, build_log); + delete[] build_log; + } +#ifndef BT_SUPPRESS_OPENCL_ASSERTS + btAssert(0); +#endif //BT_SUPPRESS_OPENCL_ASSERTS + m_kernelCompilationFailures++; + return 0; + } + + + // Create the kernel + kernel = clCreateKernel(m_cpProgram, kernelName, &ciErrNum); + if (ciErrNum != CL_SUCCESS) + { + const char* msg = ""; + switch(ciErrNum) + { + case CL_INVALID_PROGRAM: + msg = "Program is not a valid program object."; + break; + case CL_INVALID_PROGRAM_EXECUTABLE: + msg = "There is no successfully built executable for program."; + break; + case CL_INVALID_KERNEL_NAME: + msg = "kernel_name is not found in program."; + break; + case CL_INVALID_KERNEL_DEFINITION: + msg = "the function definition for __kernel function given by kernel_name such as the number of arguments, the argument types are not the same for all devices for which the program executable has been built."; + break; + case CL_INVALID_VALUE: + msg = "kernel_name is NULL."; + break; + case CL_OUT_OF_HOST_MEMORY: + msg = "Failure to allocate resources required by the OpenCL implementation on the host."; + break; + default: + { + } + } + + printf("Error in clCreateKernel for kernel '%s', error is \"%s\", Line %u in file %s !!!\n\n", kernelName, msg, __LINE__, __FILE__); + +#ifndef BT_SUPPRESS_OPENCL_ASSERTS + btAssert(0); +#endif //BT_SUPPRESS_OPENCL_ASSERTS + m_kernelCompilationFailures++; + return 0; + } + + printf("ready. \n"); + delete [] compileFlags; + if (!kernel) + m_kernelCompilationFailures++; + return kernel; + +} + +void btOpenCLSoftBodySolver::predictMotion( float timeStep ) +{ + // Clear the collision shape array for the next frame + // Ensure that the DX11 ones are moved off the device so they will be updated correctly + m_clCollisionObjectDetails.changedOnCPU(); + m_clPerClothCollisionObjects.changedOnCPU(); + m_collisionObjectDetails.clear(); + + if ( m_bUpdateAnchoredNodePos ) + { + // In OpenCL cloth solver, if softbody node has zero inverse mass(infinite mass) or anchor attached, + // we need to update the node position in case the node or anchor is animated externally. + // If there is no such node, we can eliminate the unnecessary CPU-to-GPU data trasferring. + for ( int i = 0; i < m_anchorNodeInfoArray.size(); i++ ) + { + const AnchorNodeInfoCL& anchorNodeInfo = m_anchorNodeInfoArray[i]; + btSoftBody::Node* node = anchorNodeInfo.pNode; + + using Vectormath::Aos::Point3; + Point3 pos((float)node->m_x.getX(), (float)node->m_x.getY(), (float)node->m_x.getZ()); + m_anchorPosition[i] = pos; + } + + if ( m_anchorNodeInfoArray.size() > 0 ) + m_clAnchorPosition.changedOnCPU(); + + updateFixedVertexPositions(); + } + + { + BT_PROFILE("applyForces"); + // Apply forces that we know about to the cloths + applyForces( timeStep * getTimeScale() ); + } + + { + BT_PROFILE("integrate"); + // Itegrate motion for all soft bodies dealt with by the solver + integrate( timeStep * getTimeScale() ); + } + + { + BT_PROFILE("updateBounds"); + updateBounds(); + } + // End prediction work for solvers +} + +static Vectormath::Aos::Transform3 toTransform3( const btTransform &transform ) +{ + Vectormath::Aos::Transform3 outTransform; + outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0))); + outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1))); + outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2))); + outTransform.setCol(3, toVector3(transform.getOrigin())); + return outTransform; +} + +void btOpenCLAcceleratedSoftBodyInterface::updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound ) +{ + float scalarMargin = (float)getSoftBody()->getCollisionShape()->getMargin(); + btVector3 vectorMargin( scalarMargin, scalarMargin, scalarMargin ); + m_softBody->m_bounds[0] = lowerBound - vectorMargin; + m_softBody->m_bounds[1] = upperBound + vectorMargin; +} // btOpenCLSoftBodySolver::btDX11AcceleratedSoftBodyInterface::updateBounds + +void btOpenCLSoftBodySolver::processCollision( btSoftBody*, btSoftBody* ) +{ + +} + +// Add the collision object to the set to deal with for a particular soft body +void btOpenCLSoftBodySolver::processCollision( btSoftBody *softBody, btCollisionObject* collisionObject ) +{ + int softBodyIndex = findSoftBodyIndex( softBody ); + + if( softBodyIndex >= 0 ) + { + btCollisionShape *collisionShape = collisionObject->getCollisionShape(); + float friction = collisionObject->getFriction(); + int shapeType = collisionShape->getShapeType(); + if( shapeType == CAPSULE_SHAPE_PROXYTYPE ) + { + // Add to the list of expected collision objects + CollisionShapeDescription newCollisionShapeDescription; + newCollisionShapeDescription.softBodyIdentifier = softBodyIndex; + newCollisionShapeDescription.collisionShapeType = shapeType; + // TODO: May need to transpose this matrix either here or in HLSL + newCollisionShapeDescription.shapeTransform = toTransform3(collisionObject->getWorldTransform()); + btCapsuleShape *capsule = static_cast( collisionShape ); + newCollisionShapeDescription.radius = capsule->getRadius(); + newCollisionShapeDescription.halfHeight = capsule->getHalfHeight(); + newCollisionShapeDescription.margin = capsule->getMargin(); + newCollisionShapeDescription.upAxis = capsule->getUpAxis(); + newCollisionShapeDescription.friction = friction; + btRigidBody* body = static_cast< btRigidBody* >( collisionObject ); + newCollisionShapeDescription.linearVelocity = toVector3(body->getLinearVelocity()); + newCollisionShapeDescription.angularVelocity = toVector3(body->getAngularVelocity()); + m_collisionObjectDetails.push_back( newCollisionShapeDescription ); + + } + else { +#ifdef _DEBUG + printf("Unsupported collision shape type\n"); +#endif + //btAssert(0 && "Unsupported collision shape type\n"); + } + } else { + btAssert(0 && "Unknown soft body"); + } +} // btOpenCLSoftBodySolver::processCollision + + + + + +btOpenCLAcceleratedSoftBodyInterface* btOpenCLSoftBodySolver::findSoftBodyInterface( const btSoftBody* const softBody ) +{ + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btOpenCLAcceleratedSoftBodyInterface* softBodyInterface = m_softBodySet[softBodyIndex]; + if( softBodyInterface->getSoftBody() == softBody ) + return softBodyInterface; + } + return 0; +} + + +int btOpenCLSoftBodySolver::findSoftBodyIndex( const btSoftBody* const softBody ) +{ + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btOpenCLAcceleratedSoftBodyInterface* softBodyInterface = m_softBodySet[softBodyIndex]; + if( softBodyInterface->getSoftBody() == softBody ) + return softBodyIndex; + } + return 1; +} + +bool btOpenCLSoftBodySolver::checkInitialized() +{ + if( !m_shadersInitialized ) + if( buildShaders() ) + m_shadersInitialized = true; + + return m_shadersInitialized; +} + +bool btOpenCLSoftBodySolver::buildShaders() +{ + if( m_shadersInitialized ) + return true; + + const char* additionalMacros=""; + + // Ensure current kernels are released first + releaseKernels(); + + m_currentCLFunctions->clearKernelCompilationFailures(); + + m_prepareLinksKernel = m_currentCLFunctions->compileCLKernelFromString( PrepareLinksCLString, "PrepareLinksKernel",additionalMacros,"OpenCLC10/PrepareLinks.cl" ); + m_updatePositionsFromVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdatePositionsFromVelocitiesCLString, "UpdatePositionsFromVelocitiesKernel" ,additionalMacros,"OpenCLC10/UpdatePositionsFromVelocities.cl"); + m_solvePositionsFromLinksKernel = m_currentCLFunctions->compileCLKernelFromString( SolvePositionsCLString, "SolvePositionsFromLinksKernel",additionalMacros,"OpenCLC10/SolvePositions.cl" ); + m_vSolveLinksKernel = m_currentCLFunctions->compileCLKernelFromString( VSolveLinksCLString, "VSolveLinksKernel" ,additionalMacros,"OpenCLC10/VSolveLinks.cl"); + m_updateVelocitiesFromPositionsWithVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNodesCLString, "updateVelocitiesFromPositionsWithVelocitiesKernel" ,additionalMacros,"OpenCLC10/UpdateNodes.cl"); + m_updateVelocitiesFromPositionsWithoutVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdatePositionsCLString, "updateVelocitiesFromPositionsWithoutVelocitiesKernel" ,additionalMacros,"OpenCLC10/UpdatePositions.cl"); + m_solveCollisionsAndUpdateVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( SolveCollisionsAndUpdateVelocitiesCLString, "SolveCollisionsAndUpdateVelocitiesKernel" ,additionalMacros,"OpenCLC10/SolveCollisionsAndUpdateVelocities.cl"); + m_integrateKernel = m_currentCLFunctions->compileCLKernelFromString( IntegrateCLString, "IntegrateKernel" ,additionalMacros,"OpenCLC10/Integrate.cl"); + m_applyForcesKernel = m_currentCLFunctions->compileCLKernelFromString( ApplyForcesCLString, "ApplyForcesKernel" ,additionalMacros,"OpenCLC10/ApplyForces.cl"); + m_updateFixedVertexPositionsKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateFixedVertexPositionsCLString, "UpdateFixedVertexPositions" , additionalMacros, "OpenCLC10/UpdateFixedVertexPositions.cl"); + + // TODO: Rename to UpdateSoftBodies + m_resetNormalsAndAreasKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "ResetNormalsAndAreasKernel" ,additionalMacros,"OpenCLC10/UpdateNormals.cl"); + m_normalizeNormalsAndAreasKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "NormalizeNormalsAndAreasKernel" ,additionalMacros,"OpenCLC10/UpdateNormals.cl"); + m_updateSoftBodiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "UpdateSoftBodiesKernel" ,additionalMacros,"OpenCLC10/UpdateNormals.cl"); + + + if( m_currentCLFunctions->getKernelCompilationFailures()==0 ) + m_shadersInitialized = true; + + return m_shadersInitialized; +} + diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h new file mode 100644 index 0000000..4c9c8e9 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h @@ -0,0 +1,527 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVER_OPENCL_H +#define BT_SOFT_BODY_SOLVER_OPENCL_H + +#include "stddef.h" //for size_t +#include "vectormath/vmInclude.h" + +#include "BulletSoftBody/btSoftBodySolvers.h" +#include "BulletSoftBody/btSoftBody.h" +#include "btSoftBodySolverBuffer_OpenCL.h" +#include "btSoftBodySolverLinkData_OpenCL.h" +#include "btSoftBodySolverVertexData_OpenCL.h" +#include "btSoftBodySolverTriangleData_OpenCL.h" + +class CLFunctions +{ +protected: + cl_command_queue m_cqCommandQue; + cl_context m_cxMainContext; + + int m_kernelCompilationFailures; + + +public: + CLFunctions(cl_command_queue cqCommandQue, cl_context cxMainContext) : + m_cqCommandQue( cqCommandQue ), + m_cxMainContext( cxMainContext ), + m_kernelCompilationFailures(0) + { + } + + int getKernelCompilationFailures() const + { + return m_kernelCompilationFailures; + } + + /** + * Compile a compute shader kernel from a string and return the appropriate cl_kernel object. + */ + virtual cl_kernel compileCLKernelFromString( const char* kernelSource, const char* kernelName, const char* additionalMacros, const char* srcFileNameForCaching); + + void clearKernelCompilationFailures() + { + m_kernelCompilationFailures=0; + } +}; + +/** + * Entry in the collision shape array. + * Specifies the shape type, the transform matrix and the necessary details of the collisionShape. + */ +struct CollisionShapeDescription +{ + Vectormath::Aos::Transform3 shapeTransform; + Vectormath::Aos::Vector3 linearVelocity; + Vectormath::Aos::Vector3 angularVelocity; + + int softBodyIdentifier; + int collisionShapeType; + + // Both needed for capsule + float radius; + float halfHeight; + int upAxis; + + float margin; + float friction; + + CollisionShapeDescription() + { + collisionShapeType = 0; + margin = 0; + friction = 0; + } +}; + +/** + * SoftBody class to maintain information about a soft body instance + * within a solver. + * This data addresses the main solver arrays. + */ +class btOpenCLAcceleratedSoftBodyInterface +{ +protected: + /** Current number of vertices that are part of this cloth */ + int m_numVertices; + /** Maximum number of vertices allocated to be part of this cloth */ + int m_maxVertices; + /** Current number of triangles that are part of this cloth */ + int m_numTriangles; + /** Maximum number of triangles allocated to be part of this cloth */ + int m_maxTriangles; + /** Index of first vertex in the world allocated to this cloth */ + int m_firstVertex; + /** Index of first triangle in the world allocated to this cloth */ + int m_firstTriangle; + /** Index of first link in the world allocated to this cloth */ + int m_firstLink; + /** Maximum number of links allocated to this cloth */ + int m_maxLinks; + /** Current number of links allocated to this cloth */ + int m_numLinks; + + /** The actual soft body this data represents */ + btSoftBody *m_softBody; + + +public: + btOpenCLAcceleratedSoftBodyInterface( btSoftBody *softBody ) : + m_softBody( softBody ) + { + m_numVertices = 0; + m_maxVertices = 0; + m_numTriangles = 0; + m_maxTriangles = 0; + m_firstVertex = 0; + m_firstTriangle = 0; + m_firstLink = 0; + m_maxLinks = 0; + m_numLinks = 0; + } + int getNumVertices() + { + return m_numVertices; + } + + int getNumTriangles() + { + return m_numTriangles; + } + + int getMaxVertices() + { + return m_maxVertices; + } + + int getMaxTriangles() + { + return m_maxTriangles; + } + + int getFirstVertex() + { + return m_firstVertex; + } + + int getFirstTriangle() + { + return m_firstTriangle; + } + + /** + * Update the bounds in the btSoftBody object + */ + void updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound ); + + // TODO: All of these set functions will have to do checks and + // update the world because restructuring of the arrays will be necessary + // Reasonable use of "friend"? + void setNumVertices( int numVertices ) + { + m_numVertices = numVertices; + } + + void setNumTriangles( int numTriangles ) + { + m_numTriangles = numTriangles; + } + + void setMaxVertices( int maxVertices ) + { + m_maxVertices = maxVertices; + } + + void setMaxTriangles( int maxTriangles ) + { + m_maxTriangles = maxTriangles; + } + + void setFirstVertex( int firstVertex ) + { + m_firstVertex = firstVertex; + } + + void setFirstTriangle( int firstTriangle ) + { + m_firstTriangle = firstTriangle; + } + + void setMaxLinks( int maxLinks ) + { + m_maxLinks = maxLinks; + } + + void setNumLinks( int numLinks ) + { + m_numLinks = numLinks; + } + + void setFirstLink( int firstLink ) + { + m_firstLink = firstLink; + } + + int getMaxLinks() + { + return m_maxLinks; + } + + int getNumLinks() + { + return m_numLinks; + } + + int getFirstLink() + { + return m_firstLink; + } + + btSoftBody* getSoftBody() + { + return m_softBody; + } + +}; + + + +class btOpenCLSoftBodySolver : public btSoftBodySolver +{ +public: + + + struct UIntVector3 + { + UIntVector3() + { + x = 0; + y = 0; + z = 0; + _padding = 0; + } + + UIntVector3( unsigned int x_, unsigned int y_, unsigned int z_ ) + { + x = x_; + y = y_; + z = z_; + _padding = 0; + } + + unsigned int x; + unsigned int y; + unsigned int z; + unsigned int _padding; + }; + + struct CollisionObjectIndices + { + CollisionObjectIndices( int f, int e ) + { + firstObject = f; + endObject = e; + } + + int firstObject; + int endObject; + }; + + btSoftBodyLinkDataOpenCL m_linkData; + btSoftBodyVertexDataOpenCL m_vertexData; + btSoftBodyTriangleDataOpenCL m_triangleData; + +protected: + + CLFunctions m_defaultCLFunctions; + CLFunctions* m_currentCLFunctions; + + /** Variable to define whether we need to update solver constants on the next iteration */ + bool m_updateSolverConstants; + + bool m_shadersInitialized; + + /** + * Cloths owned by this solver. + * Only our cloths are in this array. + */ + btAlignedObjectArray< btOpenCLAcceleratedSoftBodyInterface * > m_softBodySet; + + /** Acceleration value to be applied to all non-static vertices in the solver. + * Index n is cloth n, array sized by number of cloths in the world not the solver. + */ + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothAcceleration; + btOpenCLBuffer m_clPerClothAcceleration; + + /** Wind velocity to be applied normal to all non-static vertices in the solver. + * Index n is cloth n, array sized by number of cloths in the world not the solver. + */ + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothWindVelocity; + btOpenCLBuffer m_clPerClothWindVelocity; + + /** Velocity damping factor */ + btAlignedObjectArray< float > m_perClothDampingFactor; + btOpenCLBuffer m_clPerClothDampingFactor; + + /** Velocity correction coefficient */ + btAlignedObjectArray< float > m_perClothVelocityCorrectionCoefficient; + btOpenCLBuffer m_clPerClothVelocityCorrectionCoefficient; + + /** Lift parameter for wind effect on cloth. */ + btAlignedObjectArray< float > m_perClothLiftFactor; + btOpenCLBuffer m_clPerClothLiftFactor; + + /** Drag parameter for wind effect on cloth. */ + btAlignedObjectArray< float > m_perClothDragFactor; + btOpenCLBuffer m_clPerClothDragFactor; + + /** Density of the medium in which each cloth sits */ + btAlignedObjectArray< float > m_perClothMediumDensity; + btOpenCLBuffer m_clPerClothMediumDensity; + + /** + * Collision shape details: pair of index of first collision shape for the cloth and number of collision objects. + */ + btAlignedObjectArray< CollisionObjectIndices > m_perClothCollisionObjects; + btOpenCLBuffer m_clPerClothCollisionObjects; + + /** + * Collision shapes being passed across to the cloths in this solver. + */ + btAlignedObjectArray< CollisionShapeDescription > m_collisionObjectDetails; + btOpenCLBuffer< CollisionShapeDescription > m_clCollisionObjectDetails; + + + + /** + * Friction coefficient for each cloth + */ + btAlignedObjectArray< float > m_perClothFriction; + btOpenCLBuffer< float > m_clPerClothFriction; + + // anchor node info + struct AnchorNodeInfoCL + { + int clVertexIndex; + btSoftBody::Node* pNode; + }; + + btAlignedObjectArray m_anchorNodeInfoArray; + btAlignedObjectArray m_anchorPosition; + btOpenCLBuffer m_clAnchorPosition; + btAlignedObjectArray m_anchorIndex; + btOpenCLBuffer m_clAnchorIndex; + + bool m_bUpdateAnchoredNodePos; + + cl_kernel m_prepareLinksKernel; + cl_kernel m_solvePositionsFromLinksKernel; + cl_kernel m_updateConstantsKernel; + cl_kernel m_integrateKernel; + cl_kernel m_addVelocityKernel; + cl_kernel m_updatePositionsFromVelocitiesKernel; + cl_kernel m_updateVelocitiesFromPositionsWithoutVelocitiesKernel; + cl_kernel m_updateVelocitiesFromPositionsWithVelocitiesKernel; + cl_kernel m_vSolveLinksKernel; + cl_kernel m_solveCollisionsAndUpdateVelocitiesKernel; + cl_kernel m_resetNormalsAndAreasKernel; + cl_kernel m_normalizeNormalsAndAreasKernel; + cl_kernel m_updateSoftBodiesKernel; + + cl_kernel m_outputToVertexArrayKernel; + cl_kernel m_applyForcesKernel; + cl_kernel m_updateFixedVertexPositionsKernel; + + cl_command_queue m_cqCommandQue; + cl_context m_cxMainContext; + + size_t m_defaultWorkGroupSize; + + + virtual bool buildShaders(); + + void resetNormalsAndAreas( int numVertices ); + + void normalizeNormalsAndAreas( int numVertices ); + + void executeUpdateSoftBodies( int firstTriangle, int numTriangles ); + + void prepareCollisionConstraints(); + + Vectormath::Aos::Vector3 ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a ); + + void ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce ); + + + int findSoftBodyIndex( const btSoftBody* const softBody ); + + virtual void applyForces( float solverdt ); + + void updateFixedVertexPositions(); + + /** + * Integrate motion on the solver. + */ + virtual void integrate( float solverdt ); + + virtual void updateConstants( float timeStep ); + + float computeTriangleArea( + const Vectormath::Aos::Point3 &vertex0, + const Vectormath::Aos::Point3 &vertex1, + const Vectormath::Aos::Point3 &vertex2 ); + + + ////////////////////////////////////// + // Kernel dispatches + void prepareLinks(); + + void solveLinksForVelocity( int startLink, int numLinks, float kst ); + + void updatePositionsFromVelocities( float solverdt ); + + virtual void solveLinksForPosition( int startLink, int numLinks, float kst, float ti ); + + void updateVelocitiesFromPositionsWithVelocities( float isolverdt ); + + void updateVelocitiesFromPositionsWithoutVelocities( float isolverdt ); + virtual void solveCollisionsAndUpdateVelocities( float isolverdt ); + + // End kernel dispatches + ///////////////////////////////////// + + void updateBounds(); + + void releaseKernels(); + +public: + btOpenCLSoftBodySolver(cl_command_queue queue,cl_context ctx, bool bUpdateAchchoredNodePos = false); + + virtual ~btOpenCLSoftBodySolver(); + + + + btOpenCLAcceleratedSoftBodyInterface *findSoftBodyInterface( const btSoftBody* const softBody ); + + virtual btSoftBodyLinkData &getLinkData(); + + virtual btSoftBodyVertexData &getVertexData(); + + virtual btSoftBodyTriangleData &getTriangleData(); + + virtual SolverTypes getSolverType() const + { + return CL_SOLVER; + } + + + virtual bool checkInitialized(); + + virtual void updateSoftBodies( ); + + virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false); + + virtual void copyBackToSoftBodies(bool bMove = true); + + virtual void solveConstraints( float solverdt ); + + virtual void predictMotion( float solverdt ); + + virtual void processCollision( btSoftBody *, btCollisionObject* ); + + virtual void processCollision( btSoftBody*, btSoftBody* ); + + virtual void setDefaultWorkgroupSize(size_t workGroupSize) + { + m_defaultWorkGroupSize = workGroupSize; + } + virtual size_t getDefaultWorkGroupSize() const + { + return m_defaultWorkGroupSize; + } + + void setCLFunctions(CLFunctions* funcs) + { + if (funcs) + m_currentCLFunctions = funcs; + else + m_currentCLFunctions = &m_defaultCLFunctions; + } + +}; // btOpenCLSoftBodySolver + + +/** + * Class to manage movement of data from a solver to a given target. + * This version is the CL to CPU version. + */ +class btSoftBodySolverOutputCLtoCPU : public btSoftBodySolverOutput +{ +protected: + +public: + btSoftBodySolverOutputCLtoCPU() + { + } + + /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */ + virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ); +}; + + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_OPENCL_H diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp new file mode 100644 index 0000000..2216768 --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp @@ -0,0 +1,1101 @@ +/* +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 "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "vectormath/vmInclude.h" +#include //@todo: remove the debugging printf at some stage +#include "btSoftBodySolver_OpenCLSIMDAware.h" +#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h" +#include "BulletSoftBody/btSoftBody.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include + +#define WAVEFRONT_SIZE 32 +#define WAVEFRONT_BLOCK_MULTIPLIER 2 +#define GROUP_SIZE (WAVEFRONT_SIZE*WAVEFRONT_BLOCK_MULTIPLIER) +#define LINKS_PER_SIMD_LANE 16 + +static const size_t workGroupSize = GROUP_SIZE; + + +//CL_VERSION_1_1 seems broken on NVidia SDK so just disable it + +////OpenCL 1.0 kernels don't use float3 +#define MSTRINGIFY(A) #A +static const char* UpdatePositionsFromVelocitiesCLString = +#include "OpenCLC10/UpdatePositionsFromVelocities.cl" +static const char* SolvePositionsCLString = +#include "OpenCLC10/SolvePositionsSIMDBatched.cl" +static const char* UpdateNodesCLString = +#include "OpenCLC10/UpdateNodes.cl" +static const char* UpdatePositionsCLString = +#include "OpenCLC10/UpdatePositions.cl" +static const char* UpdateConstantsCLString = +#include "OpenCLC10/UpdateConstants.cl" +static const char* IntegrateCLString = +#include "OpenCLC10/Integrate.cl" +static const char* ApplyForcesCLString = +#include "OpenCLC10/ApplyForces.cl" +static const char* UpdateFixedVertexPositionsCLString = +#include "OpenCLC10/UpdateFixedVertexPositions.cl" +static const char* UpdateNormalsCLString = +#include "OpenCLC10/UpdateNormals.cl" +static const char* VSolveLinksCLString = +#include "OpenCLC10/VSolveLinks.cl" +static const char* SolveCollisionsAndUpdateVelocitiesCLString = +#include "OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl" +static const char* OutputToVertexArrayCLString = +#include "OpenCLC10/OutputToVertexArray.cl" + + + +btSoftBodyLinkDataOpenCLSIMDAware::btSoftBodyLinkDataOpenCLSIMDAware(cl_command_queue queue, cl_context ctx) : + m_cqCommandQue(queue), + m_wavefrontSize( WAVEFRONT_SIZE ), + m_linksPerWorkItem( LINKS_PER_SIMD_LANE ), + m_maxBatchesWithinWave( 0 ), + m_maxLinksPerWavefront( m_wavefrontSize * m_linksPerWorkItem ), + m_numWavefronts( 0 ), + m_maxVertex( 0 ), + m_clNumBatchesAndVerticesWithinWaves( queue, ctx, &m_numBatchesAndVerticesWithinWaves, true ), + m_clWavefrontVerticesGlobalAddresses( queue, ctx, &m_wavefrontVerticesGlobalAddresses, true ), + m_clLinkVerticesLocalAddresses( queue, ctx, &m_linkVerticesLocalAddresses, true ), + m_clLinkStrength( queue, ctx, &m_linkStrength, false ), + m_clLinksMassLSC( queue, ctx, &m_linksMassLSC, false ), + m_clLinksRestLengthSquared( queue, ctx, &m_linksRestLengthSquared, false ), + m_clLinksRestLength( queue, ctx, &m_linksRestLength, false ), + m_clLinksMaterialLinearStiffnessCoefficient( queue, ctx, &m_linksMaterialLinearStiffnessCoefficient, false ) +{ +} + +btSoftBodyLinkDataOpenCLSIMDAware::~btSoftBodyLinkDataOpenCLSIMDAware() +{ +} + +static Vectormath::Aos::Vector3 toVector3( const btVector3 &vec ) +{ + Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() ); + return outVec; +} + +/** Allocate enough space in all link-related arrays to fit numLinks links */ +void btSoftBodyLinkDataOpenCLSIMDAware::createLinks( int numLinks ) +{ + int previousSize = m_links.size(); + int newSize = previousSize + numLinks; + + btSoftBodyLinkData::createLinks( numLinks ); + + // Resize the link addresses array as well + m_linkAddresses.resize( newSize ); +} + +/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ +void btSoftBodyLinkDataOpenCLSIMDAware::setLinkAt( + const LinkDescription &link, + int linkIndex ) +{ + btSoftBodyLinkData::setLinkAt( link, linkIndex ); + + if( link.getVertex0() > m_maxVertex ) + m_maxVertex = link.getVertex0(); + if( link.getVertex1() > m_maxVertex ) + m_maxVertex = link.getVertex1(); + + // Set the link index correctly for initialisation + m_linkAddresses[linkIndex] = linkIndex; +} + +bool btSoftBodyLinkDataOpenCLSIMDAware::onAccelerator() +{ + return m_onGPU; +} + +bool btSoftBodyLinkDataOpenCLSIMDAware::moveToAccelerator() +{ + bool success = true; + success = success && m_clNumBatchesAndVerticesWithinWaves.moveToGPU(); + success = success && m_clWavefrontVerticesGlobalAddresses.moveToGPU(); + success = success && m_clLinkVerticesLocalAddresses.moveToGPU(); + success = success && m_clLinkStrength.moveToGPU(); + success = success && m_clLinksMassLSC.moveToGPU(); + success = success && m_clLinksRestLengthSquared.moveToGPU(); + success = success && m_clLinksRestLength.moveToGPU(); + success = success && m_clLinksMaterialLinearStiffnessCoefficient.moveToGPU(); + + if( success ) { + m_onGPU = true; + } + + return success; +} + +bool btSoftBodyLinkDataOpenCLSIMDAware::moveFromAccelerator() +{ + bool success = true; + success = success && m_clNumBatchesAndVerticesWithinWaves.moveToGPU(); + success = success && m_clWavefrontVerticesGlobalAddresses.moveToGPU(); + success = success && m_clLinkVerticesLocalAddresses.moveToGPU(); + success = success && m_clLinkStrength.moveFromGPU(); + success = success && m_clLinksMassLSC.moveFromGPU(); + success = success && m_clLinksRestLengthSquared.moveFromGPU(); + success = success && m_clLinksRestLength.moveFromGPU(); + success = success && m_clLinksMaterialLinearStiffnessCoefficient.moveFromGPU(); + + if( success ) { + m_onGPU = false; + } + + return success; +} + + + + + + + + +btOpenCLSoftBodySolverSIMDAware::btOpenCLSoftBodySolverSIMDAware(cl_command_queue queue, cl_context ctx, bool bUpdateAchchoredNodePos) : + btOpenCLSoftBodySolver( queue, ctx, bUpdateAchchoredNodePos ), + m_linkData(queue, ctx) +{ + // Initial we will clearly need to update solver constants + // For now this is global for the cloths linked with this solver - we should probably make this body specific + // for performance in future once we understand more clearly when constants need to be updated + m_updateSolverConstants = true; + + m_shadersInitialized = false; +} + +btOpenCLSoftBodySolverSIMDAware::~btOpenCLSoftBodySolverSIMDAware() +{ + releaseKernels(); +} + +void btOpenCLSoftBodySolverSIMDAware::optimize( btAlignedObjectArray< btSoftBody * > &softBodies ,bool forceUpdate) +{ + if( forceUpdate || m_softBodySet.size() != softBodies.size() ) + { + // Have a change in the soft body set so update, reloading all the data + getVertexData().clear(); + getTriangleData().clear(); + getLinkData().clear(); + m_softBodySet.resize(0); + m_anchorIndex.clear(); + + int maxPiterations = 0; + int maxViterations = 0; + + for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex ) + { + btSoftBody *softBody = softBodies[ softBodyIndex ]; + using Vectormath::Aos::Matrix3; + using Vectormath::Aos::Point3; + + // Create SoftBody that will store the information within the solver + btOpenCLAcceleratedSoftBodyInterface* newSoftBody = new btOpenCLAcceleratedSoftBodyInterface( softBody ); + m_softBodySet.push_back( newSoftBody ); + + m_perClothAcceleration.push_back( toVector3(softBody->getWorldInfo()->m_gravity) ); + m_perClothDampingFactor.push_back(softBody->m_cfg.kDP); + m_perClothVelocityCorrectionCoefficient.push_back( softBody->m_cfg.kVCF ); + m_perClothLiftFactor.push_back( softBody->m_cfg.kLF ); + m_perClothDragFactor.push_back( softBody->m_cfg.kDG ); + m_perClothMediumDensity.push_back(softBody->getWorldInfo()->air_density); + // Simple init values. Actually we'll put 0 and -1 into them at the appropriate time + m_perClothFriction.push_back(softBody->m_cfg.kDF); + m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) ); + + // Add space for new vertices and triangles in the default solver for now + // TODO: Include space here for tearing too later + int firstVertex = getVertexData().getNumVertices(); + int numVertices = softBody->m_nodes.size(); + // Round maxVertices to a multiple of the workgroup size so we know we're safe to run over in a given group + // maxVertices can be increased to allow tearing, but should be used sparingly because these extra verts will always be processed + int maxVertices = GROUP_SIZE*((numVertices+GROUP_SIZE)/GROUP_SIZE); + // Allocate space for new vertices in all the vertex arrays + getVertexData().createVertices( numVertices, softBodyIndex, maxVertices ); + + + int firstTriangle = getTriangleData().getNumTriangles(); + int numTriangles = softBody->m_faces.size(); + int maxTriangles = numTriangles; + getTriangleData().createTriangles( maxTriangles ); + + // Copy vertices from softbody into the solver + for( int vertex = 0; vertex < numVertices; ++vertex ) + { + Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ()); + btSoftBodyVertexData::VertexDescription desc; + + // TODO: Position in the softbody might be pre-transformed + // or we may need to adapt for the pose. + //desc.setPosition( cloth.getMeshTransform()*multPoint ); + desc.setPosition( multPoint ); + + float vertexInverseMass = softBody->m_nodes[vertex].m_im; + desc.setInverseMass(vertexInverseMass); + getVertexData().setVertexAt( desc, firstVertex + vertex ); + + m_anchorIndex.push_back(-1.0); + } + for( int vertex = numVertices; vertex < maxVertices; ++vertex ) + { + m_anchorIndex.push_back(-1.0); + } + + // Copy triangles similarly + // We're assuming here that vertex indices are based on the firstVertex rather than the entire scene + for( int triangle = 0; triangle < numTriangles; ++triangle ) + { + // Note that large array storage is relative to the array not to the cloth + // So we need to add firstVertex to each value + int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0])); + int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0])); + int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0])); + btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex); + getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle ); + + // Increase vertex triangle counts for this triangle + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex0)++; + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex1)++; + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex2)++; + } + + int firstLink = getLinkData().getNumLinks(); + int numLinks = softBody->m_links.size(); + int maxLinks = numLinks; + + // Allocate space for the links + getLinkData().createLinks( numLinks ); + + // Add the links + for( int link = 0; link < numLinks; ++link ) + { + int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]); + int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]); + + btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST); + newLink.setLinkStrength(1.f); + getLinkData().setLinkAt(newLink, firstLink + link); + } + + newSoftBody->setFirstVertex( firstVertex ); + newSoftBody->setFirstTriangle( firstTriangle ); + newSoftBody->setNumVertices( numVertices ); + newSoftBody->setMaxVertices( maxVertices ); + newSoftBody->setNumTriangles( numTriangles ); + newSoftBody->setMaxTriangles( maxTriangles ); + newSoftBody->setFirstLink( firstLink ); + newSoftBody->setNumLinks( numLinks ); + + // Find maximum piterations and viterations + int piterations = softBody->m_cfg.piterations; + + if ( piterations > maxPiterations ) + maxPiterations = piterations; + + int viterations = softBody->m_cfg.viterations; + + if ( viterations > maxViterations ) + maxViterations = viterations; + + // zero mass + for( int vertex = 0; vertex < numVertices; ++vertex ) + { + if ( softBody->m_nodes[vertex].m_im == 0 ) + { + AnchorNodeInfoCL nodeInfo; + nodeInfo.clVertexIndex = firstVertex + vertex; + nodeInfo.pNode = &softBody->m_nodes[vertex]; + + m_anchorNodeInfoArray.push_back(nodeInfo); + } + } + + // anchor position + if ( numVertices > 0 ) + { + for ( int anchorIndex = 0; anchorIndex < softBody->m_anchors.size(); anchorIndex++ ) + { + btSoftBody::Node* anchorNode = softBody->m_anchors[anchorIndex].m_node; + btSoftBody::Node* firstNode = &softBody->m_nodes[0]; + + AnchorNodeInfoCL nodeInfo; + nodeInfo.clVertexIndex = firstVertex + (int)(anchorNode - firstNode); + nodeInfo.pNode = anchorNode; + + m_anchorNodeInfoArray.push_back(nodeInfo); + } + } + } + + m_anchorPosition.clear(); + m_anchorPosition.resize(m_anchorNodeInfoArray.size()); + + for ( int anchorNode = 0; anchorNode < m_anchorNodeInfoArray.size(); anchorNode++ ) + { + const AnchorNodeInfoCL& anchorNodeInfo = m_anchorNodeInfoArray[anchorNode]; + m_anchorIndex[anchorNodeInfo.clVertexIndex] = anchorNode; + getVertexData().getInverseMass(anchorNodeInfo.clVertexIndex) = 0.0f; + } + + updateConstants(0.f); + + // set position and velocity iterations + setNumberOfPositionIterations(maxPiterations); + setNumberOfVelocityIterations(maxViterations); + + // set wind velocity + m_perClothWindVelocity.resize( m_softBodySet.size() ); + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btSoftBody *softBody = m_softBodySet[softBodyIndex]->getSoftBody(); + m_perClothWindVelocity[softBodyIndex] = toVector3(softBody->getWindVelocity()); + } + + m_clPerClothWindVelocity.changedOnCPU(); + + // generate batches + m_linkData.generateBatches(); + m_triangleData.generateBatches(); + + // Build the shaders to match the batching parameters + buildShaders(); + } +} + + +btSoftBodyLinkData &btOpenCLSoftBodySolverSIMDAware::getLinkData() +{ + // TODO: Consider setting link data to "changed" here + return m_linkData; +} + + + + +void btOpenCLSoftBodySolverSIMDAware::updateConstants( float timeStep ) +{ + + using namespace Vectormath::Aos; + + if( m_updateSolverConstants ) + { + m_updateSolverConstants = false; + + // Will have to redo this if we change the structure (tear, maybe) or various other possible changes + + // Initialise link constants + const int numLinks = m_linkData.getNumLinks(); + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair &vertices( m_linkData.getVertexPair(linkIndex) ); + m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 ))); + float invMass0 = m_vertexData.getInverseMass(vertices.vertex0); + float invMass1 = m_vertexData.getInverseMass(vertices.vertex1); + float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex); + float massLSC = (invMass0 + invMass1)/linearStiffness; + m_linkData.getMassLSC(linkIndex) = massLSC; + float restLength = m_linkData.getRestLength(linkIndex); + float restLengthSquared = restLength*restLength; + m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared; + } + } + +} + + + +void btOpenCLSoftBodySolverSIMDAware::solveConstraints( float solverdt ) +{ + + using Vectormath::Aos::Vector3; + using Vectormath::Aos::Point3; + using Vectormath::Aos::lengthSqr; + using Vectormath::Aos::dot; + + // Prepare links + int numLinks = m_linkData.getNumLinks(); + int numVertices = m_vertexData.getNumVertices(); + + float kst = 1.f; + float ti = 0.f; + + + m_clPerClothDampingFactor.moveToGPU(); + m_clPerClothVelocityCorrectionCoefficient.moveToGPU(); + + + // Ensure data is on accelerator + m_linkData.moveToAccelerator(); + m_vertexData.moveToAccelerator(); + + + //prepareLinks(); + + prepareCollisionConstraints(); + + // Solve drift + for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) + { + + for( int i = 0; i < m_linkData.m_wavefrontBatchStartLengths.size(); ++i ) + { + int startWave = m_linkData.m_wavefrontBatchStartLengths[i].start; + int numWaves = m_linkData.m_wavefrontBatchStartLengths[i].length; + solveLinksForPosition( startWave, numWaves, kst, ti ); + } + } // for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) + + + // At this point assume that the force array is blank - we will overwrite it + solveCollisionsAndUpdateVelocities( 1.f/solverdt ); +} + + +////////////////////////////////////// +// Kernel dispatches + + +void btOpenCLSoftBodySolverSIMDAware::solveLinksForPosition( int startWave, int numWaves, float kst, float ti ) +{ + cl_int ciErrNum; + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,0, sizeof(int), &startWave); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,1, sizeof(int), &numWaves); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,2, sizeof(float), &kst); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,3, sizeof(float), &ti); + + + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,4, sizeof(cl_mem), &m_linkData.m_clNumBatchesAndVerticesWithinWaves.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,5, sizeof(cl_mem), &m_linkData.m_clWavefrontVerticesGlobalAddresses.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,6, sizeof(cl_mem), &m_linkData.m_clLinkVerticesLocalAddresses.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,7, sizeof(cl_mem), &m_linkData.m_clLinksMassLSC.m_buffer); + + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,8, sizeof(cl_mem), &m_linkData.m_clLinksRestLengthSquared.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,9, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,10, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); + + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,11, WAVEFRONT_BLOCK_MULTIPLIER*sizeof(cl_int2), 0); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,12, m_linkData.getMaxVerticesPerWavefront()*WAVEFRONT_BLOCK_MULTIPLIER*sizeof(cl_float4), 0); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,13, m_linkData.getMaxVerticesPerWavefront()*WAVEFRONT_BLOCK_MULTIPLIER*sizeof(cl_float), 0); + + size_t numWorkItems = workGroupSize*((numWaves*WAVEFRONT_SIZE + (workGroupSize-1)) / workGroupSize); + + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_solvePositionsFromLinksKernel,1,NULL,&numWorkItems,&workGroupSize,0,0,0); + + if( ciErrNum!= CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_solvePositionsFromLinksKernel)"); + } + +} // solveLinksForPosition + +void btOpenCLSoftBodySolverSIMDAware::solveCollisionsAndUpdateVelocities( float isolverdt ) +{ + // Copy kernel parameters to GPU + m_vertexData.moveToAccelerator(); + m_clPerClothFriction.moveToGPU(); + m_clPerClothDampingFactor.moveToGPU(); + m_clPerClothCollisionObjects.moveToGPU(); + m_clCollisionObjectDetails.moveToGPU(); + + cl_int ciErrNum; + int numVerts = m_vertexData.getNumVertices(); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 0, sizeof(int), &numVerts); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 1, sizeof(int), &isolverdt); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 2, sizeof(cl_mem),&m_vertexData.m_clClothIdentifier.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 3, sizeof(cl_mem),&m_vertexData.m_clVertexPreviousPosition.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 4, sizeof(cl_mem),&m_clPerClothFriction.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 5, sizeof(cl_mem),&m_clPerClothDampingFactor.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 6, sizeof(cl_mem),&m_clPerClothCollisionObjects.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 7, sizeof(cl_mem),&m_clCollisionObjectDetails.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 8, sizeof(cl_mem),&m_vertexData.m_clVertexForceAccumulator.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 9, sizeof(cl_mem),&m_vertexData.m_clVertexVelocity.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 10, sizeof(cl_mem),&m_vertexData.m_clVertexPosition.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 11, sizeof(CollisionShapeDescription)*16,0); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 12, sizeof(cl_mem),&m_vertexData.m_clVertexInverseMass.m_buffer); + size_t numWorkItems = workGroupSize*((m_vertexData.getNumVertices() + (workGroupSize-1)) / workGroupSize); + + if (numWorkItems) + { + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_solveCollisionsAndUpdateVelocitiesKernel, 1, NULL, &numWorkItems, &workGroupSize,0,0,0); + + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_solveCollisionsAndUpdateVelocitiesKernel)"); + } + } + +} // btOpenCLSoftBodySolverSIMDAware::updateVelocitiesFromPositionsWithoutVelocities + +// End kernel dispatches +///////////////////////////////////// + + + +bool btOpenCLSoftBodySolverSIMDAware::buildShaders() +{ + releaseKernels(); + + if( m_shadersInitialized ) + return true; + + const char* additionalMacros=""; + + m_currentCLFunctions->clearKernelCompilationFailures(); + + char *wavefrontMacros = new char[256]; + + sprintf( + wavefrontMacros, + "-DMAX_NUM_VERTICES_PER_WAVE=%d -DMAX_BATCHES_PER_WAVE=%d -DWAVEFRONT_SIZE=%d -DWAVEFRONT_BLOCK_MULTIPLIER=%d -DBLOCK_SIZE=%d", + m_linkData.getMaxVerticesPerWavefront(), + m_linkData.getMaxBatchesPerWavefront(), + m_linkData.getWavefrontSize(), + WAVEFRONT_BLOCK_MULTIPLIER, + WAVEFRONT_BLOCK_MULTIPLIER*m_linkData.getWavefrontSize()); + + m_updatePositionsFromVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdatePositionsFromVelocitiesCLString, "UpdatePositionsFromVelocitiesKernel", additionalMacros,"OpenCLC10/UpdatePositionsFromVelocities.cl"); + m_solvePositionsFromLinksKernel = m_currentCLFunctions->compileCLKernelFromString( SolvePositionsCLString, "SolvePositionsFromLinksKernel", wavefrontMacros ,"OpenCLC10/SolvePositionsSIMDBatched.cl"); + m_updateVelocitiesFromPositionsWithVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNodesCLString, "updateVelocitiesFromPositionsWithVelocitiesKernel", additionalMacros ,"OpenCLC10/UpdateNodes.cl"); + m_updateVelocitiesFromPositionsWithoutVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdatePositionsCLString, "updateVelocitiesFromPositionsWithoutVelocitiesKernel", additionalMacros,"OpenCLC10/UpdatePositions.cl"); + m_integrateKernel = m_currentCLFunctions->compileCLKernelFromString( IntegrateCLString, "IntegrateKernel", additionalMacros ,"OpenCLC10/Integrate.cl"); + m_applyForcesKernel = m_currentCLFunctions->compileCLKernelFromString( ApplyForcesCLString, "ApplyForcesKernel", additionalMacros,"OpenCLC10/ApplyForces.cl" ); + m_updateFixedVertexPositionsKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateFixedVertexPositionsCLString, "UpdateFixedVertexPositions" ,additionalMacros,"OpenCLC10/UpdateFixedVertexPositions.cl"); + m_solveCollisionsAndUpdateVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( SolveCollisionsAndUpdateVelocitiesCLString, "SolveCollisionsAndUpdateVelocitiesKernel", additionalMacros ,"OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl"); + + // TODO: Rename to UpdateSoftBodies + m_resetNormalsAndAreasKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "ResetNormalsAndAreasKernel", additionalMacros ,"OpenCLC10/UpdateNormals.cl"); + m_normalizeNormalsAndAreasKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "NormalizeNormalsAndAreasKernel", additionalMacros ,"OpenCLC10/UpdateNormals.cl"); + m_updateSoftBodiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "UpdateSoftBodiesKernel", additionalMacros ,"OpenCLC10/UpdateNormals.cl"); + + delete [] wavefrontMacros; + + if( m_currentCLFunctions->getKernelCompilationFailures()==0) + { + m_shadersInitialized = true; + } + + return m_shadersInitialized; +} + + + + +static Vectormath::Aos::Transform3 toTransform3( const btTransform &transform ) +{ + Vectormath::Aos::Transform3 outTransform; + outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0))); + outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1))); + outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2))); + outTransform.setCol(3, toVector3(transform.getOrigin())); + return outTransform; +} + + +static void generateBatchesOfWavefronts( btAlignedObjectArray < btAlignedObjectArray > &linksForWavefronts, btSoftBodyLinkData &linkData, int numVertices, btAlignedObjectArray < btAlignedObjectArray > &wavefrontBatches ) +{ + // A per-batch map of truth values stating whether a given vertex is in that batch + // This allows us to significantly optimize the batching + btAlignedObjectArray > mapOfVerticesInBatches; + + for( int waveIndex = 0; waveIndex < linksForWavefronts.size(); ++waveIndex ) + { + btAlignedObjectArray &wavefront( linksForWavefronts[waveIndex] ); + + int batch = 0; + bool placed = false; + while( batch < wavefrontBatches.size() && !placed ) + { + // Test the current batch, see if this wave shares any vertex with the waves in the batch + bool foundSharedVertex = false; + for( int link = 0; link < wavefront.size(); ++link ) + { + btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); + if( (mapOfVerticesInBatches[batch])[vertices.vertex0] || (mapOfVerticesInBatches[batch])[vertices.vertex1] ) + { + foundSharedVertex = true; + } + } + + if( !foundSharedVertex ) + { + wavefrontBatches[batch].push_back( waveIndex ); + // Insert vertices into this batch too + for( int link = 0; link < wavefront.size(); ++link ) + { + btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); + (mapOfVerticesInBatches[batch])[vertices.vertex0] = true; + (mapOfVerticesInBatches[batch])[vertices.vertex1] = true; + } + placed = true; + } + batch++; + } + if( batch == wavefrontBatches.size() && !placed ) + { + wavefrontBatches.resize( batch + 1 ); + wavefrontBatches[batch].push_back( waveIndex ); + + // And resize map as well + mapOfVerticesInBatches.resize( batch + 1 ); + + // Resize maps with total number of vertices + mapOfVerticesInBatches[batch].resize( numVertices+1, false ); + + // Insert vertices into this batch too + for( int link = 0; link < wavefront.size(); ++link ) + { + btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); + (mapOfVerticesInBatches[batch])[vertices.vertex0] = true; + (mapOfVerticesInBatches[batch])[vertices.vertex1] = true; + } + } + } + mapOfVerticesInBatches.clear(); +} + +// Function to remove an object from a vector maintaining correct ordering of the vector +template< typename T > static void removeFromVector( btAlignedObjectArray< T > &vectorToUpdate, int indexToRemove ) +{ + int currentSize = vectorToUpdate.size(); + for( int i = indexToRemove; i < (currentSize-1); ++i ) + { + vectorToUpdate[i] = vectorToUpdate[i+1]; + } + if( currentSize > 0 ) + vectorToUpdate.resize( currentSize - 1 ); +} + +/** + * Insert element into vectorToUpdate at index index. + */ +template< typename T > static void insertAtIndex( btAlignedObjectArray< T > &vectorToUpdate, int index, T element ) +{ + vectorToUpdate.resize( vectorToUpdate.size() + 1 ); + for( int i = (vectorToUpdate.size() - 1); i > index; --i ) + { + vectorToUpdate[i] = vectorToUpdate[i-1]; + } + vectorToUpdate[index] = element; +} + +/** + * Insert into btAlignedObjectArray assuming the array is ordered and maintaining both ordering and uniqueness. + * ie it treats vectorToUpdate as an ordered set. + */ +template< typename T > static void insertUniqueAndOrderedIntoVector( btAlignedObjectArray &vectorToUpdate, T element ) +{ + int index = 0; + while( index < vectorToUpdate.size() && vectorToUpdate[index] < element ) + { + index++; + } + if( index == vectorToUpdate.size() || vectorToUpdate[index] != element ) + insertAtIndex( vectorToUpdate, index, element ); +} + +static void generateLinksPerVertex( int numVertices, btSoftBodyLinkData &linkData, btAlignedObjectArray< int > &listOfLinksPerVertex, btAlignedObjectArray &numLinksPerVertex, int &maxLinks ) +{ + for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); + numLinksPerVertex[nodes.vertex0]++; + numLinksPerVertex[nodes.vertex1]++; + } + int maxLinksPerVertex = 0; + for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex ) + { + maxLinksPerVertex = btMax(numLinksPerVertex[vertexIndex], maxLinksPerVertex); + } + maxLinks = maxLinksPerVertex; + + btAlignedObjectArray< int > linksFoundPerVertex; + linksFoundPerVertex.resize( numVertices, 0 ); + + listOfLinksPerVertex.resize( maxLinksPerVertex * numVertices ); + + for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); + { + // Do vertex 0 + int vertexIndex = nodes.vertex0; + int linkForVertex = linksFoundPerVertex[nodes.vertex0]; + int linkAddress = vertexIndex * maxLinksPerVertex + linkForVertex; + + listOfLinksPerVertex[linkAddress] = linkIndex; + + linksFoundPerVertex[nodes.vertex0] = linkForVertex + 1; + } + { + // Do vertex 1 + int vertexIndex = nodes.vertex1; + int linkForVertex = linksFoundPerVertex[nodes.vertex1]; + int linkAddress = vertexIndex * maxLinksPerVertex + linkForVertex; + + listOfLinksPerVertex[linkAddress] = linkIndex; + + linksFoundPerVertex[nodes.vertex1] = linkForVertex + 1; + } + } +} + +static void computeBatchingIntoWavefronts( + btSoftBodyLinkData &linkData, + int wavefrontSize, + int linksPerWorkItem, + int maxLinksPerWavefront, + btAlignedObjectArray < btAlignedObjectArray > &linksForWavefronts, + btAlignedObjectArray< btAlignedObjectArray < btAlignedObjectArray > > &batchesWithinWaves, /* wave, batch, links in batch */ + btAlignedObjectArray< btAlignedObjectArray< int > > &verticesForWavefronts /* wavefront, vertex */ + ) +{ + + + // Attempt generation of larger batches of links. + btAlignedObjectArray< bool > processedLink; + processedLink.resize( linkData.getNumLinks() ); + btAlignedObjectArray< int > listOfLinksPerVertex; + int maxLinksPerVertex = 0; + + // Count num vertices + int numVertices = 0; + for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); + numVertices = btMax( numVertices, nodes.vertex0 + 1 ); + numVertices = btMax( numVertices, nodes.vertex1 + 1 ); + } + + // Need list of links per vertex + // Compute valence of each vertex + btAlignedObjectArray numLinksPerVertex; + numLinksPerVertex.resize(0); + numLinksPerVertex.resize( numVertices, 0 ); + + generateLinksPerVertex( numVertices, linkData, listOfLinksPerVertex, numLinksPerVertex, maxLinksPerVertex ); + + if (!numVertices) + return; + + for( int vertex = 0; vertex < 10; ++vertex ) + { + for( int link = 0; link < numLinksPerVertex[vertex]; ++link ) + { + int linkAddress = vertex * maxLinksPerVertex + link; + } + } + + + // At this point we know what links we have for each vertex so we can start batching + + // We want a vertex to start with, let's go with 0 + int currentVertex = 0; + int linksProcessed = 0; + + btAlignedObjectArray verticesToProcess; + + while( linksProcessed < linkData.getNumLinks() ) + { + // Next wavefront + int nextWavefront = linksForWavefronts.size(); + linksForWavefronts.resize( nextWavefront + 1 ); + btAlignedObjectArray &linksForWavefront(linksForWavefronts[nextWavefront]); + verticesForWavefronts.resize( nextWavefront + 1 ); + btAlignedObjectArray &vertexSet( verticesForWavefronts[nextWavefront] ); + + linksForWavefront.resize(0); + + // Loop to find enough links to fill the wavefront + // Stopping if we either run out of links, or fill it + while( linksProcessed < linkData.getNumLinks() && linksForWavefront.size() < maxLinksPerWavefront ) + { + // Go through the links for the current vertex + for( int link = 0; link < numLinksPerVertex[currentVertex] && linksForWavefront.size() < maxLinksPerWavefront; ++link ) + { + int linkAddress = currentVertex * maxLinksPerVertex + link; + int linkIndex = listOfLinksPerVertex[linkAddress]; + + // If we have not already processed this link, add it to the wavefront + // Claim it as another processed link + // Add the vertex at the far end to the list of vertices to process. + if( !processedLink[linkIndex] ) + { + linksForWavefront.push_back( linkIndex ); + linksProcessed++; + processedLink[linkIndex] = true; + int v0 = linkData.getVertexPair(linkIndex).vertex0; + int v1 = linkData.getVertexPair(linkIndex).vertex1; + if( v0 == currentVertex ) + verticesToProcess.push_back( v1 ); + else + verticesToProcess.push_back( v0 ); + } + } + if( verticesToProcess.size() > 0 ) + { + // Get the element on the front of the queue and remove it + currentVertex = verticesToProcess[0]; + removeFromVector( verticesToProcess, 0 ); + } else { + // If we've not yet processed all the links, find the first unprocessed one + // and select one of its vertices as the current vertex + if( linksProcessed < linkData.getNumLinks() ) + { + int searchLink = 0; + while( processedLink[searchLink] ) + searchLink++; + currentVertex = linkData.getVertexPair(searchLink).vertex0; + } + } + } + + // We have either finished or filled a wavefront + for( int link = 0; link < linksForWavefront.size(); ++link ) + { + int v0 = linkData.getVertexPair( linksForWavefront[link] ).vertex0; + int v1 = linkData.getVertexPair( linksForWavefront[link] ).vertex1; + insertUniqueAndOrderedIntoVector( vertexSet, v0 ); + insertUniqueAndOrderedIntoVector( vertexSet, v1 ); + } + // Iterate over links mapped to the wave and batch those + // We can run a batch on each cycle trivially + + batchesWithinWaves.resize( batchesWithinWaves.size() + 1 ); + btAlignedObjectArray < btAlignedObjectArray > &batchesWithinWave( batchesWithinWaves[batchesWithinWaves.size()-1] ); + + + for( int link = 0; link < linksForWavefront.size(); ++link ) + { + int linkIndex = linksForWavefront[link]; + btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( linkIndex ); + + int batch = 0; + bool placed = false; + while( batch < batchesWithinWave.size() && !placed ) + { + bool foundSharedVertex = false; + if( batchesWithinWave[batch].size() >= wavefrontSize ) + { + // If we have already filled this batch, move on to another + foundSharedVertex = true; + } else { + for( int link2 = 0; link2 < batchesWithinWave[batch].size(); ++link2 ) + { + btSoftBodyLinkData::LinkNodePair vertices2 = linkData.getVertexPair( (batchesWithinWave[batch])[link2] ); + + if( vertices.vertex0 == vertices2.vertex0 || + vertices.vertex1 == vertices2.vertex0 || + vertices.vertex0 == vertices2.vertex1 || + vertices.vertex1 == vertices2.vertex1 ) + { + foundSharedVertex = true; + break; + } + } + } + if( !foundSharedVertex ) + { + batchesWithinWave[batch].push_back( linkIndex ); + placed = true; + } else { + ++batch; + } + } + if( batch == batchesWithinWave.size() && !placed ) + { + batchesWithinWave.resize( batch + 1 ); + batchesWithinWave[batch].push_back( linkIndex ); + } + } + + } + +} + +void btSoftBodyLinkDataOpenCLSIMDAware::generateBatches() +{ + btAlignedObjectArray < btAlignedObjectArray > linksForWavefronts; + btAlignedObjectArray < btAlignedObjectArray > wavefrontBatches; + btAlignedObjectArray< btAlignedObjectArray < btAlignedObjectArray > > batchesWithinWaves; + btAlignedObjectArray< btAlignedObjectArray< int > > verticesForWavefronts; // wavefronts, vertices in wavefront as an ordered set + + // Group the links into wavefronts + computeBatchingIntoWavefronts( *this, m_wavefrontSize, m_linksPerWorkItem, m_maxLinksPerWavefront, linksForWavefronts, batchesWithinWaves, verticesForWavefronts ); + + + // Batch the wavefronts + generateBatchesOfWavefronts( linksForWavefronts, *this, m_maxVertex, wavefrontBatches ); + + m_numWavefronts = linksForWavefronts.size(); + + // At this point we have a description of which links we need to process in each wavefront + + // First correctly fill the batch ranges vector + int numBatches = wavefrontBatches.size(); + m_wavefrontBatchStartLengths.resize(0); + int prefixSum = 0; + for( int batchIndex = 0; batchIndex < numBatches; ++batchIndex ) + { + int wavesInBatch = wavefrontBatches[batchIndex].size(); + int nextPrefixSum = prefixSum + wavesInBatch; + m_wavefrontBatchStartLengths.push_back( BatchPair( prefixSum, nextPrefixSum - prefixSum ) ); + + prefixSum += wavesInBatch; + } + + // Also find max number of batches within a wave + m_maxBatchesWithinWave = 0; + m_maxVerticesWithinWave = 0; + m_numBatchesAndVerticesWithinWaves.resize( m_numWavefronts ); + for( int waveIndex = 0; waveIndex < m_numWavefronts; ++waveIndex ) + { + // See if the number of batches in this wave is greater than the current maxium + int batchesInCurrentWave = batchesWithinWaves[waveIndex].size(); + int verticesInCurrentWave = verticesForWavefronts[waveIndex].size(); + m_maxBatchesWithinWave = btMax( batchesInCurrentWave, m_maxBatchesWithinWave ); + m_maxVerticesWithinWave = btMax( verticesInCurrentWave, m_maxVerticesWithinWave ); + } + + // Add padding values both for alignment and as dudd addresses within LDS to compute junk rather than branch around + m_maxVerticesWithinWave = 16*((m_maxVerticesWithinWave/16)+2); + + // Now we know the maximum number of vertices per-wave we can resize the global vertices array + m_wavefrontVerticesGlobalAddresses.resize( m_maxVerticesWithinWave * m_numWavefronts ); + + // Grab backup copies of all the link data arrays for the sorting process + btAlignedObjectArray m_links_Backup(m_links); + btAlignedObjectArray m_linkStrength_Backup(m_linkStrength); + btAlignedObjectArray m_linksMassLSC_Backup(m_linksMassLSC); + btAlignedObjectArray m_linksRestLengthSquared_Backup(m_linksRestLengthSquared); + //btAlignedObjectArray m_linksCLength_Backup(m_linksCLength); + //btAlignedObjectArray m_linksLengthRatio_Backup(m_linksLengthRatio); + btAlignedObjectArray m_linksRestLength_Backup(m_linksRestLength); + btAlignedObjectArray m_linksMaterialLinearStiffnessCoefficient_Backup(m_linksMaterialLinearStiffnessCoefficient); + + // Resize to a wavefront sized batch per batch per wave so we get perfectly coherent memory accesses. + m_links.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linkVerticesLocalAddresses.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linkStrength.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linksMassLSC.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linksRestLengthSquared.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linksRestLength.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linksMaterialLinearStiffnessCoefficient.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + + // Then re-order links into wavefront blocks + + // Total number of wavefronts moved. This will decide the ordering of sorted wavefronts. + int wavefrontCount = 0; + + // Iterate over batches of wavefronts, then wavefronts in the batch + for( int batchIndex = 0; batchIndex < numBatches; ++batchIndex ) + { + btAlignedObjectArray &batch( wavefrontBatches[batchIndex] ); + int wavefrontsInBatch = batch.size(); + + + for( int wavefrontIndex = 0; wavefrontIndex < wavefrontsInBatch; ++wavefrontIndex ) + { + + int originalWavefrontIndex = batch[wavefrontIndex]; + btAlignedObjectArray< int > &wavefrontVertices( verticesForWavefronts[originalWavefrontIndex] ); + int verticesUsedByWavefront = wavefrontVertices.size(); + + // Copy the set of vertices into the correctly structured array for use on the device + // Fill the non-vertices with -1s + // so we can mask out those reads + for( int vertex = 0; vertex < verticesUsedByWavefront; ++vertex ) + { + m_wavefrontVerticesGlobalAddresses[m_maxVerticesWithinWave * wavefrontCount + vertex] = wavefrontVertices[vertex]; + } + for( int vertex = verticesUsedByWavefront; vertex < m_maxVerticesWithinWave; ++vertex ) + { + m_wavefrontVerticesGlobalAddresses[m_maxVerticesWithinWave * wavefrontCount + vertex] = -1; + } + + // Obtain the set of batches within the current wavefront + btAlignedObjectArray < btAlignedObjectArray > &batchesWithinWavefront( batchesWithinWaves[originalWavefrontIndex] ); + // Set the size of the batches for use in the solver, correctly ordered + NumBatchesVerticesPair batchesAndVertices; + batchesAndVertices.numBatches = batchesWithinWavefront.size(); + batchesAndVertices.numVertices = verticesUsedByWavefront; + m_numBatchesAndVerticesWithinWaves[wavefrontCount] = batchesAndVertices; + + + // Now iterate over batches within the wavefront to structure the links correctly + for( int wavefrontBatch = 0; wavefrontBatch < batchesWithinWavefront.size(); ++wavefrontBatch ) + { + btAlignedObjectArray &linksInBatch( batchesWithinWavefront[wavefrontBatch] ); + int wavefrontBatchSize = linksInBatch.size(); + + int batchAddressInTarget = m_maxBatchesWithinWave * m_wavefrontSize * wavefrontCount + m_wavefrontSize * wavefrontBatch; + + for( int linkIndex = 0; linkIndex < wavefrontBatchSize; ++linkIndex ) + { + int originalLinkAddress = linksInBatch[linkIndex]; + // Reorder simple arrays trivially + m_links[batchAddressInTarget + linkIndex] = m_links_Backup[originalLinkAddress]; + m_linkStrength[batchAddressInTarget + linkIndex] = m_linkStrength_Backup[originalLinkAddress]; + m_linksMassLSC[batchAddressInTarget + linkIndex] = m_linksMassLSC_Backup[originalLinkAddress]; + m_linksRestLengthSquared[batchAddressInTarget + linkIndex] = m_linksRestLengthSquared_Backup[originalLinkAddress]; + m_linksRestLength[batchAddressInTarget + linkIndex] = m_linksRestLength_Backup[originalLinkAddress]; + m_linksMaterialLinearStiffnessCoefficient[batchAddressInTarget + linkIndex] = m_linksMaterialLinearStiffnessCoefficient_Backup[originalLinkAddress]; + + // The local address is more complicated. We need to work out where a given vertex will end up + // by searching the set of vertices for this link and using the index as the local address + btSoftBodyLinkData::LinkNodePair localPair; + btSoftBodyLinkData::LinkNodePair globalPair = m_links[batchAddressInTarget + linkIndex]; + localPair.vertex0 = wavefrontVertices.findLinearSearch( globalPair.vertex0 ); + localPair.vertex1 = wavefrontVertices.findLinearSearch( globalPair.vertex1 ); + m_linkVerticesLocalAddresses[batchAddressInTarget + linkIndex] = localPair; + } + for( int linkIndex = wavefrontBatchSize; linkIndex < m_wavefrontSize; ++linkIndex ) + { + // Put 0s into these arrays for padding for cleanliness + m_links[batchAddressInTarget + linkIndex] = btSoftBodyLinkData::LinkNodePair(0, 0); + m_linkStrength[batchAddressInTarget + linkIndex] = 0.f; + m_linksMassLSC[batchAddressInTarget + linkIndex] = 0.f; + m_linksRestLengthSquared[batchAddressInTarget + linkIndex] = 0.f; + m_linksRestLength[batchAddressInTarget + linkIndex] = 0.f; + m_linksMaterialLinearStiffnessCoefficient[batchAddressInTarget + linkIndex] = 0.f; + + + // For local addresses of junk data choose a set of addresses just above the range of valid ones + // and cycling tyhrough % 16 so that we don't have bank conficts between all dud addresses + // The valid addresses will do scatter and gather in the valid range, the junk ones should happily work + // off the end of that range so we need no control + btSoftBodyLinkData::LinkNodePair localPair; + localPair.vertex0 = verticesUsedByWavefront + (linkIndex % 16); + localPair.vertex1 = verticesUsedByWavefront + (linkIndex % 16); + m_linkVerticesLocalAddresses[batchAddressInTarget + linkIndex] = localPair; + } + + } + + + wavefrontCount++; + } + + + } + +} // void btSoftBodyLinkDataDX11SIMDAware::generateBatches() + + + diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h new file mode 100644 index 0000000..9dda3ed --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h @@ -0,0 +1,81 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVER_OPENCL_SIMDAWARE_H +#define BT_SOFT_BODY_SOLVER_OPENCL_SIMDAWARE_H + +#include "stddef.h" //for size_t +#include "vectormath/vmInclude.h" + +#include "btSoftBodySolver_OpenCL.h" +#include "btSoftBodySolverBuffer_OpenCL.h" +#include "btSoftBodySolverLinkData_OpenCLSIMDAware.h" +#include "btSoftBodySolverVertexData_OpenCL.h" +#include "btSoftBodySolverTriangleData_OpenCL.h" + + + + + +class btOpenCLSoftBodySolverSIMDAware : public btOpenCLSoftBodySolver +{ +protected: + + + btSoftBodyLinkDataOpenCLSIMDAware m_linkData; + + + + + virtual bool buildShaders(); + + + void updateConstants( float timeStep ); + + float computeTriangleArea( + const Vectormath::Aos::Point3 &vertex0, + const Vectormath::Aos::Point3 &vertex1, + const Vectormath::Aos::Point3 &vertex2 ); + + + ////////////////////////////////////// + // Kernel dispatches + void solveLinksForPosition( int startLink, int numLinks, float kst, float ti ); + + void solveCollisionsAndUpdateVelocities( float isolverdt ); + // End kernel dispatches + ///////////////////////////////////// + +public: + btOpenCLSoftBodySolverSIMDAware(cl_command_queue queue,cl_context ctx, bool bUpdateAchchoredNodePos = false); + + virtual ~btOpenCLSoftBodySolverSIMDAware(); + + virtual SolverTypes getSolverType() const + { + return CL_SIMD_SOLVER; + } + + + virtual btSoftBodyLinkData &getLinkData(); + + + virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false); + + virtual void solveConstraints( float solverdt ); + +}; // btOpenCLSoftBodySolverSIMDAware + +#endif // #ifndef BT_SOFT_BODY_SOLVER_OPENCL_SIMDAWARE_H diff --git a/src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h b/src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h new file mode 100644 index 0000000..e7d715b --- /dev/null +++ b/src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h @@ -0,0 +1,748 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVER_DATA_H +#define BT_SOFT_BODY_SOLVER_DATA_H + +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "vectormath/vmInclude.h" + + +class btSoftBodyLinkData +{ +public: + /** + * Class representing a link as a set of three indices into the vertex array. + */ + class LinkNodePair + { + public: + int vertex0; + int vertex1; + + LinkNodePair() + { + vertex0 = 0; + vertex1 = 0; + } + + LinkNodePair( int v0, int v1 ) + { + vertex0 = v0; + vertex1 = v1; + } + }; + + /** + * Class describing a link for input into the system. + */ + class LinkDescription + { + protected: + int m_vertex0; + int m_vertex1; + float m_linkLinearStiffness; + float m_linkStrength; + + public: + + LinkDescription() + { + m_vertex0 = 0; + m_vertex1 = 0; + m_linkLinearStiffness = 1.0; + m_linkStrength = 1.0; + } + + LinkDescription( int newVertex0, int newVertex1, float linkLinearStiffness ) + { + m_vertex0 = newVertex0; + m_vertex1 = newVertex1; + m_linkLinearStiffness = linkLinearStiffness; + m_linkStrength = 1.0; + } + + LinkNodePair getVertexPair() const + { + LinkNodePair nodes; + nodes.vertex0 = m_vertex0; + nodes.vertex1 = m_vertex1; + return nodes; + } + + void setVertex0( int vertex ) + { + m_vertex0 = vertex; + } + + void setVertex1( int vertex ) + { + m_vertex1 = vertex; + } + + void setLinkLinearStiffness( float linearStiffness ) + { + m_linkLinearStiffness = linearStiffness; + } + + void setLinkStrength( float strength ) + { + m_linkStrength = strength; + } + + int getVertex0() const + { + return m_vertex0; + } + + int getVertex1() const + { + return m_vertex1; + } + + float getLinkStrength() const + { + return m_linkStrength; + } + + float getLinkLinearStiffness() const + { + return m_linkLinearStiffness; + } + }; + + +protected: + // NOTE: + // Vertex reference data is stored relative to global array, not relative to individual cloth. + // Values must be correct if being passed into single-cloth VBOs or when migrating from one solver + // to another. + + btAlignedObjectArray< LinkNodePair > m_links; // Vertex pair for the link + btAlignedObjectArray< float > m_linkStrength; // Strength of each link + // (inverseMassA + inverseMassB)/ linear stiffness coefficient + btAlignedObjectArray< float > m_linksMassLSC; + btAlignedObjectArray< float > m_linksRestLengthSquared; + // Current vector length of link + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_linksCLength; + // 1/(current length * current length * massLSC) + btAlignedObjectArray< float > m_linksLengthRatio; + btAlignedObjectArray< float > m_linksRestLength; + btAlignedObjectArray< float > m_linksMaterialLinearStiffnessCoefficient; + +public: + btSoftBodyLinkData() + { + } + + virtual ~btSoftBodyLinkData() + { + } + + virtual void clear() + { + m_links.resize(0); + m_linkStrength.resize(0); + m_linksMassLSC.resize(0); + m_linksRestLengthSquared.resize(0); + m_linksLengthRatio.resize(0); + m_linksRestLength.resize(0); + m_linksMaterialLinearStiffnessCoefficient.resize(0); + } + + int getNumLinks() + { + return m_links.size(); + } + + /** Allocate enough space in all link-related arrays to fit numLinks links */ + virtual void createLinks( int numLinks ) + { + int previousSize = m_links.size(); + int newSize = previousSize + numLinks; + + // Resize all the arrays that store link data + m_links.resize( newSize ); + m_linkStrength.resize( newSize ); + m_linksMassLSC.resize( newSize ); + m_linksRestLengthSquared.resize( newSize ); + m_linksCLength.resize( newSize ); + m_linksLengthRatio.resize( newSize ); + m_linksRestLength.resize( newSize ); + m_linksMaterialLinearStiffnessCoefficient.resize( newSize ); + } + + /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ + virtual void setLinkAt( const LinkDescription &link, int linkIndex ) + { + m_links[linkIndex] = link.getVertexPair(); + m_linkStrength[linkIndex] = link.getLinkStrength(); + m_linksMassLSC[linkIndex] = 0.f; + m_linksRestLengthSquared[linkIndex] = 0.f; + m_linksCLength[linkIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f); + m_linksLengthRatio[linkIndex] = 0.f; + m_linksRestLength[linkIndex] = 0.f; + m_linksMaterialLinearStiffnessCoefficient[linkIndex] = link.getLinkLinearStiffness(); + } + + + /** + * Return true if data is on the accelerator. + * The CPU version of this class will return true here because + * the CPU is the same as the accelerator. + */ + virtual bool onAccelerator() + { + return true; + } + + /** + * Move data from host memory to the accelerator. + * The CPU version will always return that it has moved it. + */ + virtual bool moveToAccelerator() + { + return true; + } + + /** + * Move data from host memory from the accelerator. + * The CPU version will always return that it has moved it. + */ + virtual bool moveFromAccelerator() + { + return true; + } + + + + /** + * Return reference to the vertex index pair for link linkIndex as stored on the host. + */ + LinkNodePair &getVertexPair( int linkIndex ) + { + return m_links[linkIndex]; + } + + /** + * Return reference to strength of link linkIndex as stored on the host. + */ + float &getStrength( int linkIndex ) + { + return m_linkStrength[linkIndex]; + } + + /** + * Return a reference to the strength of the link corrected for link sorting. + * This is important if we are using data on an accelerator which has the data sorted in some fashion. + */ + virtual float &getStrengthCorrected( int linkIndex ) + { + return getStrength( linkIndex ); + } + + /** + * Return reference to the rest length of link linkIndex as stored on the host. + */ + float &getRestLength( int linkIndex ) + { + return m_linksRestLength[linkIndex]; + } + + /** + * Return reference to linear stiffness coefficient for link linkIndex as stored on the host. + */ + float &getLinearStiffnessCoefficient( int linkIndex ) + { + return m_linksMaterialLinearStiffnessCoefficient[linkIndex]; + } + + /** + * Return reference to the MassLSC value for link linkIndex as stored on the host. + */ + float &getMassLSC( int linkIndex ) + { + return m_linksMassLSC[linkIndex]; + } + + /** + * Return reference to rest length squared for link linkIndex as stored on the host. + */ + float &getRestLengthSquared( int linkIndex ) + { + return m_linksRestLengthSquared[linkIndex]; + } + + /** + * Return reference to current length of link linkIndex as stored on the host. + */ + Vectormath::Aos::Vector3 &getCurrentLength( int linkIndex ) + { + return m_linksCLength[linkIndex]; + } + + /** + * Return the link length ratio from for link linkIndex as stored on the host. + */ + float &getLinkLengthRatio( int linkIndex ) + { + return m_linksLengthRatio[linkIndex]; + } +}; + + + +/** + * Wrapper for vertex data information. + * By wrapping it like this we stand a good chance of being able to optimise for storage format easily. + * It should also help us make sure all the data structures remain consistent. + */ +class btSoftBodyVertexData +{ +public: + /** + * Class describing a vertex for input into the system. + */ + class VertexDescription + { + private: + Vectormath::Aos::Point3 m_position; + /** Inverse mass. If this is 0f then the mass was 0 because that simplifies calculations. */ + float m_inverseMass; + + public: + VertexDescription() + { + m_position = Vectormath::Aos::Point3( 0.f, 0.f, 0.f ); + m_inverseMass = 0.f; + } + + VertexDescription( const Vectormath::Aos::Point3 &position, float mass ) + { + m_position = position; + if( mass > 0.f ) + m_inverseMass = 1.0f/mass; + else + m_inverseMass = 0.f; + } + + void setPosition( const Vectormath::Aos::Point3 &position ) + { + m_position = position; + } + + void setInverseMass( float inverseMass ) + { + m_inverseMass = inverseMass; + } + + void setMass( float mass ) + { + if( mass > 0.f ) + m_inverseMass = 1.0f/mass; + else + m_inverseMass = 0.f; + } + + Vectormath::Aos::Point3 getPosition() const + { + return m_position; + } + + float getInverseMass() const + { + return m_inverseMass; + } + + float getMass() const + { + if( m_inverseMass == 0.f ) + return 0.f; + else + return 1.0f/m_inverseMass; + } + }; +protected: + + // identifier for the individual cloth + // For the CPU we don't really need this as we can grab the cloths and iterate over only their vertices + // For a parallel accelerator knowing on a per-vertex basis which cloth we're part of will help for obtaining + // per-cloth data + // For sorting etc it might also be helpful to be able to use in-array data such as this. + btAlignedObjectArray< int > m_clothIdentifier; + btAlignedObjectArray< Vectormath::Aos::Point3 > m_vertexPosition; // vertex positions + btAlignedObjectArray< Vectormath::Aos::Point3 > m_vertexPreviousPosition; // vertex positions + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_vertexVelocity; // Velocity + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_vertexForceAccumulator; // Force accumulator + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_vertexNormal; // Normals + btAlignedObjectArray< float > m_vertexInverseMass; // Inverse mass + btAlignedObjectArray< float > m_vertexArea; // Area controlled by the vertex + btAlignedObjectArray< int > m_vertexTriangleCount; // Number of triangles touching this vertex + +public: + btSoftBodyVertexData() + { + } + + virtual ~btSoftBodyVertexData() + { + } + + virtual void clear() + { + m_clothIdentifier.resize(0); + m_vertexPosition.resize(0); + m_vertexPreviousPosition.resize(0); + m_vertexVelocity.resize(0); + m_vertexForceAccumulator.resize(0); + m_vertexNormal.resize(0); + m_vertexInverseMass.resize(0); + m_vertexArea.resize(0); + m_vertexTriangleCount.resize(0); + } + + int getNumVertices() + { + return m_vertexPosition.size(); + } + + int getClothIdentifier( int vertexIndex ) + { + return m_clothIdentifier[vertexIndex]; + } + + void setVertexAt( const VertexDescription &vertex, int vertexIndex ) + { + m_vertexPosition[vertexIndex] = vertex.getPosition(); + m_vertexPreviousPosition[vertexIndex] = vertex.getPosition(); + m_vertexVelocity[vertexIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f); + m_vertexForceAccumulator[vertexIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f); + m_vertexNormal[vertexIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f); + m_vertexInverseMass[vertexIndex] = vertex.getInverseMass(); + m_vertexArea[vertexIndex] = 0.f; + m_vertexTriangleCount[vertexIndex] = 0; + } + + /** + * Create numVertices new vertices for cloth clothIdentifier + * maxVertices allows a buffer zone of extra vertices for alignment or tearing reasons. + */ + void createVertices( int numVertices, int clothIdentifier, int maxVertices = 0 ) + { + int previousSize = m_vertexPosition.size(); + if( maxVertices == 0 ) + maxVertices = numVertices; + int newSize = previousSize + maxVertices; + + // Resize all the arrays that store vertex data + m_clothIdentifier.resize( newSize ); + m_vertexPosition.resize( newSize ); + m_vertexPreviousPosition.resize( newSize ); + m_vertexVelocity.resize( newSize ); + m_vertexForceAccumulator.resize( newSize ); + m_vertexNormal.resize( newSize ); + m_vertexInverseMass.resize( newSize ); + m_vertexArea.resize( newSize ); + m_vertexTriangleCount.resize( newSize ); + + for( int vertexIndex = previousSize; vertexIndex < newSize; ++vertexIndex ) + m_clothIdentifier[vertexIndex] = clothIdentifier; + for( int vertexIndex = (previousSize + numVertices); vertexIndex < newSize; ++vertexIndex ) + m_clothIdentifier[vertexIndex] = -1; + } + + // Get and set methods in header so they can be inlined + + /** + * Return a reference to the position of vertex vertexIndex as stored on the host. + */ + Vectormath::Aos::Point3 &getPosition( int vertexIndex ) + { + return m_vertexPosition[vertexIndex]; + } + + Vectormath::Aos::Point3 getPosition( int vertexIndex ) const + { + return m_vertexPosition[vertexIndex]; + } + + /** + * Return a reference to the previous position of vertex vertexIndex as stored on the host. + */ + Vectormath::Aos::Point3 &getPreviousPosition( int vertexIndex ) + { + return m_vertexPreviousPosition[vertexIndex]; + } + + /** + * Return a reference to the velocity of vertex vertexIndex as stored on the host. + */ + Vectormath::Aos::Vector3 &getVelocity( int vertexIndex ) + { + return m_vertexVelocity[vertexIndex]; + } + + /** + * Return a reference to the force accumulator of vertex vertexIndex as stored on the host. + */ + Vectormath::Aos::Vector3 &getForceAccumulator( int vertexIndex ) + { + return m_vertexForceAccumulator[vertexIndex]; + } + + /** + * Return a reference to the normal of vertex vertexIndex as stored on the host. + */ + Vectormath::Aos::Vector3 &getNormal( int vertexIndex ) + { + return m_vertexNormal[vertexIndex]; + } + + Vectormath::Aos::Vector3 getNormal( int vertexIndex ) const + { + return m_vertexNormal[vertexIndex]; + } + + /** + * Return a reference to the inverse mass of vertex vertexIndex as stored on the host. + */ + float &getInverseMass( int vertexIndex ) + { + return m_vertexInverseMass[vertexIndex]; + } + + /** + * Get access to the area controlled by this vertex. + */ + float &getArea( int vertexIndex ) + { + return m_vertexArea[vertexIndex]; + } + + /** + * Get access to the array of how many triangles touch each vertex. + */ + int &getTriangleCount( int vertexIndex ) + { + return m_vertexTriangleCount[vertexIndex]; + } + + + + /** + * Return true if data is on the accelerator. + * The CPU version of this class will return true here because + * the CPU is the same as the accelerator. + */ + virtual bool onAccelerator() + { + return true; + } + + /** + * Move data from host memory to the accelerator. + * The CPU version will always return that it has moved it. + */ + virtual bool moveToAccelerator() + { + return true; + } + + /** + * Move data to host memory from the accelerator if bCopy is false. + * If bCopy is true, copy data to host memory from the accelerator so that data + * won't be moved to accelerator when moveToAccelerator() is called next time. + * If bCopyMinimum is true, only vertex position and normal are copied. + * bCopyMinimum will be meaningful only if bCopy is true. + * The CPU version will always return that it has moved it. + */ + virtual bool moveFromAccelerator(bool bCopy = false, bool bCopyMinimum = true) + { + return true; + } + + btAlignedObjectArray< Vectormath::Aos::Point3 > &getVertexPositions() + { + return m_vertexPosition; + } +}; + + +class btSoftBodyTriangleData +{ +public: + /** + * Class representing a triangle as a set of three indices into the + * vertex array. + */ + class TriangleNodeSet + { + public: + int vertex0; + int vertex1; + int vertex2; + int _padding; + + TriangleNodeSet( ) + { + vertex0 = 0; + vertex1 = 0; + vertex2 = 0; + _padding = -1; + } + + TriangleNodeSet( int newVertex0, int newVertex1, int newVertex2 ) + { + vertex0 = newVertex0; + vertex1 = newVertex1; + vertex2 = newVertex2; + } + }; + + class TriangleDescription + { + protected: + int m_vertex0; + int m_vertex1; + int m_vertex2; + + public: + TriangleDescription() + { + m_vertex0 = 0; + m_vertex1 = 0; + m_vertex2 = 0; + } + + TriangleDescription( int newVertex0, int newVertex1, int newVertex2 ) + { + m_vertex0 = newVertex0; + m_vertex1 = newVertex1; + m_vertex2 = newVertex2; + } + + TriangleNodeSet getVertexSet() const + { + btSoftBodyTriangleData::TriangleNodeSet nodes; + nodes.vertex0 = m_vertex0; + nodes.vertex1 = m_vertex1; + nodes.vertex2 = m_vertex2; + return nodes; + } + }; + +protected: + // NOTE: + // Vertex reference data is stored relative to global array, not relative to individual cloth. + // Values must be correct if being passed into single-cloth VBOs or when migrating from one solver + // to another. + btAlignedObjectArray< TriangleNodeSet > m_vertexIndices; + btAlignedObjectArray< float > m_area; + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_normal; + +public: + btSoftBodyTriangleData() + { + } + + virtual ~btSoftBodyTriangleData() + { + + } + + virtual void clear() + { + m_vertexIndices.resize(0); + m_area.resize(0); + m_normal.resize(0); + } + + int getNumTriangles() + { + return m_vertexIndices.size(); + } + + virtual void setTriangleAt( const TriangleDescription &triangle, int triangleIndex ) + { + m_vertexIndices[triangleIndex] = triangle.getVertexSet(); + } + + virtual void createTriangles( int numTriangles ) + { + int previousSize = m_vertexIndices.size(); + int newSize = previousSize + numTriangles; + + // Resize all the arrays that store triangle data + m_vertexIndices.resize( newSize ); + m_area.resize( newSize ); + m_normal.resize( newSize ); + } + + /** + * Return the vertex index set for triangle triangleIndex as stored on the host. + */ + const TriangleNodeSet &getVertexSet( int triangleIndex ) + { + return m_vertexIndices[triangleIndex]; + } + + /** + * Get access to the triangle area. + */ + float &getTriangleArea( int triangleIndex ) + { + return m_area[triangleIndex]; + } + + /** + * Get access to the normal vector for this triangle. + */ + Vectormath::Aos::Vector3 &getNormal( int triangleIndex ) + { + return m_normal[triangleIndex]; + } + + /** + * Return true if data is on the accelerator. + * The CPU version of this class will return true here because + * the CPU is the same as the accelerator. + */ + virtual bool onAccelerator() + { + return true; + } + + /** + * Move data from host memory to the accelerator. + * The CPU version will always return that it has moved it. + */ + virtual bool moveToAccelerator() + { + return true; + } + + /** + * Move data from host memory from the accelerator. + * The CPU version will always return that it has moved it. + */ + virtual bool moveFromAccelerator() + { + return true; + } +}; + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_DATA_H + diff --git a/src/BulletMultiThreaded/HeapManager.h b/src/BulletMultiThreaded/HeapManager.h new file mode 100644 index 0000000..b2da4ef --- /dev/null +++ b/src/BulletMultiThreaded/HeapManager.h @@ -0,0 +1,117 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + +#ifndef BT_HEAP_MANAGER_H__ +#define BT_HEAP_MANAGER_H__ + +#ifdef __SPU__ + #define HEAP_STACK_SIZE 32 +#else + #define HEAP_STACK_SIZE 64 +#endif + +#define MIN_ALLOC_SIZE 16 + + +class HeapManager +{ +private: + ATTRIBUTE_ALIGNED16(unsigned char *mHeap); + ATTRIBUTE_ALIGNED16(unsigned int mHeapBytes); + ATTRIBUTE_ALIGNED16(unsigned char *mPoolStack[HEAP_STACK_SIZE]); + ATTRIBUTE_ALIGNED16(unsigned int mCurStack); + +public: + enum {ALIGN16,ALIGN128}; + + HeapManager(unsigned char *buf,int bytes) + { + mHeap = buf; + mHeapBytes = bytes; + clear(); + } + + ~HeapManager() + { + } + + int getAllocated() + { + return (int)(mPoolStack[mCurStack]-mHeap); + } + + int getRest() + { + return mHeapBytes-getAllocated(); + } + + void *allocate(size_t bytes,int alignment = ALIGN16) + { + if(bytes <= 0) bytes = MIN_ALLOC_SIZE; + btAssert(mCurStack < (HEAP_STACK_SIZE-1)); + + +#if defined(_WIN64) || defined(__LP64__) || defined(__x86_64__) + unsigned long long p = (unsigned long long )mPoolStack[mCurStack]; + if(alignment == ALIGN128) { + p = ((p+127) & 0xffffffffffffff80); + bytes = (bytes+127) & 0xffffffffffffff80; + } + else { + bytes = (bytes+15) & 0xfffffffffffffff0; + } + + btAssert(bytes <=(mHeapBytes-(p-(unsigned long long )mHeap)) ); + +#else + unsigned long p = (unsigned long )mPoolStack[mCurStack]; + if(alignment == ALIGN128) { + p = ((p+127) & 0xffffff80); + bytes = (bytes+127) & 0xffffff80; + } + else { + bytes = (bytes+15) & 0xfffffff0; + } + btAssert(bytes <=(mHeapBytes-(p-(unsigned long)mHeap)) ); +#endif + unsigned char * bla = (unsigned char *)(p + bytes); + mPoolStack[++mCurStack] = bla; + return (void*)p; + } + + void deallocate(void *p) + { + (void) p; + mCurStack--; + } + + void clear() + { + mPoolStack[0] = mHeap; + mCurStack = 0; + } + +// void printStack() +// { +// for(unsigned int i=0;i<=mCurStack;i++) { +// PRINTF("memStack %2d 0x%x\n",i,(uint32_t)mPoolStack[i]); +// } +// } + +}; + +#endif //BT_HEAP_MANAGER_H__ + diff --git a/src/BulletMultiThreaded/Makefile.original b/src/BulletMultiThreaded/Makefile.original new file mode 100644 index 0000000..d0a8318 --- /dev/null +++ b/src/BulletMultiThreaded/Makefile.original @@ -0,0 +1,187 @@ +__ARCH_BITS__ := 32 + +# define macros +NARROWPHASEDIR=./SpuNarrowPhaseCollisionTask +SPU_TASKFILE=$(NARROWPHASEDIR)/SpuGatheringCollisionTask + +IBM_CELLSDK_VERSION := $(shell if [ -d /opt/cell ]; then echo "3.0"; fi) + +ifeq ("$(IBM_CELLSDK_VERSION)","3.0") + CELL_TOP ?= /opt/cell/sdk + CELL_SYSROOT := /opt/cell/sysroot +else + CELL_TOP ?= /opt/ibm/cell-sdk/prototype + CELL_SYSROOT := $(CELL_TOP)/sysroot +endif + + +USE_CCACHE=ccache +RM=rm -f +OUTDIR=./out +DEBUGFLAG=-DNDEBUG +LIBOUTDIR=../../lib/ibmsdk +COLLISIONDIR=../../src/BulletCollision +MATHDIR=../../src/LinearMath +ARCHITECTUREFLAG=-m$(__ARCH_BITS__) +ifeq "$(__ARCH_BITS__)" "64" + SPU_DEFFLAGS= -DUSE_LIBSPE2 -D__SPU__ -DUSE_ADDR64 +else + SPU_DEFFLAGS= -DUSE_LIBSPE2 -D__SPU__ +endif + +SPU_DEFFLAGS+=-DUSE_PE_BOX_BOX + +SPU_GCC=$(USE_CCACHE) /usr/bin/spu-gcc +SPU_INCLUDEDIR= -Ivectormath/scalar/cpp -I. -I$(CELL_SYSROOT)/usr/spu/include -I../../src -I$(NARROWPHASEDIR) +#SPU_CFLAGS= $(DEBUGFLAG) -W -Wall -Winline -Os -c -include spu_intrinsics.h -include stdbool.h +SPU_CFLAGS= $(DEBUGFLAG) -W -Wall -Winline -O3 -mbranch-hints -fomit-frame-pointer -ftree-vectorize -finline-functions -ftree-vect-loop-version -ftree-loop-optimize -ffast-math -fno-rtti -fno-exceptions -c -include spu_intrinsics.h -include stdbool.h + +SPU_LFLAGS= -Wl,-N +SPU_LIBRARIES=-lstdc++ +SPU_EMBED=/usr/bin/ppu-embedspu +SPU_AR=/usr/bin/ar +SYMBOLNAME=spu_program + +ifeq "$(__ARCH_BITS__)" "64" + PPU_DEFFLAGS= -DUSE_LIBSPE2 -DUSE_ADDR64 + PPU_GCC=$(USE_CCACHE) /usr/bin/ppu-gcc +else + PPU_DEFFLAGS= -DUSE_LIBSPE2 + PPU_GCC=$(USE_CCACHE) /usr/bin/ppu32-gcc +endif + +PPU_CFLAGS= $(ARCHITECTUREFLAG) $(DEBUGFLAG) -W -Wall -Winline -O3 -c -mabi=altivec -maltivec -include altivec.h -include stdbool.h +PPU_INCLUDEDIR= -I. -I$(CELL_SYSROOT)/usr/include -I../../src -I$(NARROWPHASEDIR) +PPU_LFLAGS= $(ARCHITECTUREFLAG) -Wl,-m,elf$(__ARCH_BITS__)ppc +PPU_LIBRARIES= -lstdc++ -lsupc++ -lgcc -lgcov -lspe2 -lpthread -L../../lib/ibmsdk -lbulletcollision -lbulletdynamics -lbulletmath -L$(CELL_SYSROOT)/usr/lib$(__ARCH_BITS__) -R$(CELL_SYSROOT)/usr/lib +PPU_AR=/usr/bin/ar + +MakeOut : +# rm -f -R $(OUTDIR) ; mkdir $(OUTDIR) + @echo "usage: make spu, make ppu, make all, or make clean" +# SPU +SpuTaskFile : MakeOut + $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/SpuTaskFile.o $(SPU_TASKFILE).cpp + +boxBoxDistance : MakeOut + $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $(NARROWPHASEDIR)/$@.cpp + +SpuFakeDma : MakeOut + $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $@.cpp + +SpuContactManifoldCollisionAlgorithm_spu : MakeOut + $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o SpuContactManifoldCollisionAlgorithm.cpp + +SpuCollisionShapes : MakeOut + $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $(NARROWPHASEDIR)/$@.cpp + +SpuContactResult : MakeOut + $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $(NARROWPHASEDIR)/$@.cpp + +#SpuGatheringCollisionTask : MakeOut +# $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $(NARROWPHASEDIR)/$@.cpp + +SpuGjkPairDetector: MakeOut + $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $(NARROWPHASEDIR)/$@.cpp + +SpuMinkowskiPenetrationDepthSolver : MakeOut + $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $(NARROWPHASEDIR)/$@.cpp + +SpuVoronoiSimplexSolver : MakeOut + $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $(NARROWPHASEDIR)/$@.cpp + +#SpuLibspe2Support_spu : MakeOut +# $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o SpuLibspe2Support.cpp + +## SPU-Bullet +btPersistentManifold : MakeOut + $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $(COLLISIONDIR)/NarrowPhaseCollision/$@.cpp + +btOptimizedBvh : MakeOut + $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $(COLLISIONDIR)/CollisionShapes/$@.cpp + +btCollisionObject : MakeOut + $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $(COLLISIONDIR)/CollisionDispatch/$@.cpp + +btTriangleCallback : MakeOut + $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $(COLLISIONDIR)/CollisionShapes/$@.cpp + +btTriangleIndexVertexArray : MakeOut + $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $(COLLISIONDIR)/CollisionShapes/$@.cpp + +btStridingMeshInterface : MakeOut + $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $(COLLISIONDIR)/CollisionShapes/$@.cpp + +btAlignedAllocator : MakeOut + $(SPU_GCC) $(SPU_DEFFLAGS) $(SPU_CFLAGS) $(SPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $(MATHDIR)/$@.cpp + + +# PPU +SpuGatheringCollisionDispatcher : MakeOut + $(PPU_GCC) $(PPU_DEFFLAGS) $(PPU_CFLAGS) $(PPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $@.cpp + +SequentialThreadSupport: MakeOut + $(PPU_GCC) $(PPU_DEFFLAGS) $(PPU_CFLAGS) $(PPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $@.cpp + +SpuLibspe2Support: MakeOut + $(PPU_GCC) $(PPU_DEFFLAGS) $(PPU_CFLAGS) $(PPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $@.cpp + +btThreadSupportInterface: MakeOut + $(PPU_GCC) $(PPU_DEFFLAGS) $(PPU_CFLAGS) $(PPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $@.cpp + +SpuCollisionTaskProcess : MakeOut + $(PPU_GCC) $(PPU_DEFFLAGS) $(PPU_CFLAGS) $(PPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $@.cpp + +SpuContactManifoldCollisionAlgorithm : MakeOut + $(PPU_GCC) $(PPU_DEFFLAGS) $(PPU_CFLAGS) $(PPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $@.cpp + +SpuSampleTaskProcess : MakeOut + $(PPU_GCC) $(PPU_DEFFLAGS) $(PPU_CFLAGS) $(PPU_INCLUDEDIR) -o $(OUTDIR)/$@.o $@.cpp + + + +spu : boxBoxDistance SpuFakeDma SpuContactManifoldCollisionAlgorithm_spu SpuContactResult SpuTaskFile \ + SpuGjkPairDetector SpuMinkowskiPenetrationDepthSolver SpuVoronoiSimplexSolver SpuCollisionShapes \ + btPersistentManifold btOptimizedBvh btCollisionObject btTriangleCallback btTriangleIndexVertexArray \ + btStridingMeshInterface btAlignedAllocator + $(SPU_GCC) -o $(OUTDIR)/spuCollision.elf \ + $(OUTDIR)/SpuTaskFile.o \ + $(OUTDIR)/SpuFakeDma.o \ + $(OUTDIR)/boxBoxDistance.o \ + $(OUTDIR)/SpuContactManifoldCollisionAlgorithm_spu.o \ + $(OUTDIR)/SpuContactResult.o \ + $(OUTDIR)/SpuCollisionShapes.o \ + $(OUTDIR)/SpuGjkPairDetector.o \ + $(OUTDIR)/SpuMinkowskiPenetrationDepthSolver.o \ + $(OUTDIR)/SpuVoronoiSimplexSolver.o \ + $(OUTDIR)/btPersistentManifold.o \ + $(OUTDIR)/btTriangleCallback.o \ + $(OUTDIR)/btTriangleIndexVertexArray.o \ + $(OUTDIR)/btStridingMeshInterface.o \ + $(OUTDIR)/btAlignedAllocator.o \ + $(SPU_LFLAGS) $(SPU_LIBRARIES) + +spu-embed : spu + $(SPU_EMBED) $(ARCHITECTUREFLAG) $(SYMBOLNAME) $(OUTDIR)/spuCollision.elf $(OUTDIR)/$@.o + $(SPU_AR) -qcs $(LIBOUTDIR)/libspu.a $(OUTDIR)/$@.o + + + +ppu : SpuGatheringCollisionDispatcher SpuCollisionTaskProcess btThreadSupportInterface \ + SpuLibspe2Support SpuContactManifoldCollisionAlgorithm SpuSampleTaskProcess + $(PPU_AR) -qcs $(LIBOUTDIR)/bulletmultithreaded.a \ + $(OUTDIR)/SpuCollisionTaskProcess.o \ + $(OUTDIR)/SpuSampleTaskProcess.o \ + $(OUTDIR)/SpuGatheringCollisionDispatcher.o \ + $(OUTDIR)/SpuLibspe2Support.o \ + $(OUTDIR)/btThreadSupportInterface.o \ + $(OUTDIR)/SpuContactManifoldCollisionAlgorithm.o + +all : spu-embed ppu + +clean: + $(RM) $(OUTDIR)/* ; $(RM) $(LIBOUTDIR)/libspu.a ; $(RM) $(LIBOUTDIR)/bulletmultithreaded.a + + + + diff --git a/src/BulletMultiThreaded/PlatformDefinitions.h b/src/BulletMultiThreaded/PlatformDefinitions.h new file mode 100644 index 0000000..142103a --- /dev/null +++ b/src/BulletMultiThreaded/PlatformDefinitions.h @@ -0,0 +1,99 @@ +#ifndef BT_TYPE_DEFINITIONS_H +#define BT_TYPE_DEFINITIONS_H + +///This file provides some platform/compiler checks for common definitions +#include "LinearMath/btScalar.h" +#include "LinearMath/btMinMax.h" + +#ifdef PFX_USE_FREE_VECTORMATH +#include "physics_effects/base_level/base/pfx_vectormath_include.win32.h" +typedef Vectormath::Aos::Vector3 vmVector3; +typedef Vectormath::Aos::Quat vmQuat; +typedef Vectormath::Aos::Matrix3 vmMatrix3; +typedef Vectormath::Aos::Transform3 vmTransform3; +typedef Vectormath::Aos::Point3 vmPoint3; +#else +#include "vectormath/vmInclude.h" +#endif//PFX_USE_FREE_VECTORMATH + + + + + +#ifdef _WIN32 + +typedef union +{ + unsigned int u; + void *p; +} addr64; + +#define USE_WIN32_THREADING 1 + + #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) + #else + #endif //__MINGW32__ + + typedef unsigned char uint8_t; +#ifndef __PHYSICS_COMMON_H__ +#ifndef PFX_USE_FREE_VECTORMATH +#ifndef __BT_SKIP_UINT64_H + typedef unsigned long int uint64_t; +#endif //__BT_SKIP_UINT64_H +#endif //PFX_USE_FREE_VECTORMATH + typedef unsigned int uint32_t; +#endif //__PHYSICS_COMMON_H__ + typedef unsigned short uint16_t; + + #include + #define memalign(alignment, size) malloc(size); + +#include //memcpy + + + + #include + #define spu_printf printf + +#else + #include + #include + #include //for memcpy + +#if defined (__CELLOS_LV2__) + // Playstation 3 Cell SDK +#include + +#else + // posix system + +#define USE_PTHREADS (1) + +#ifdef USE_LIBSPE2 +#include +#define spu_printf printf +#define DWORD unsigned int + typedef union + { + unsigned long long ull; + unsigned int ui[2]; + void *p; + } addr64; +#endif // USE_LIBSPE2 + +#endif //__CELLOS_LV2__ + +#endif + +#ifdef __SPU__ +#include +#define printf spu_printf +#endif + +/* Included here because we need uint*_t typedefs */ +#include "PpuAddressSpace.h" + +#endif //BT_TYPE_DEFINITIONS_H + + + diff --git a/src/BulletMultiThreaded/PosixThreadSupport.cpp b/src/BulletMultiThreaded/PosixThreadSupport.cpp new file mode 100644 index 0000000..c8b49ee --- /dev/null +++ b/src/BulletMultiThreaded/PosixThreadSupport.cpp @@ -0,0 +1,399 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +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 +#include "PosixThreadSupport.h" +#ifdef USE_PTHREADS +#include +#include + +#include "SpuCollisionTaskProcess.h" +#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" + +#define checkPThreadFunction(returnValue) \ + if(0 != returnValue) { \ + printf("PThread problem at line %i in file %s: %i %d\n", __LINE__, __FILE__, returnValue, errno); \ + } + +// The number of threads should be equal to the number of available cores +// Todo: each worker should be linked to a single core, using SetThreadIdealProcessor. + +// PosixThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication +// Setup and initialize SPU/CELL/Libspe2 +PosixThreadSupport::PosixThreadSupport(ThreadConstructionInfo& threadConstructionInfo) +{ + startThreads(threadConstructionInfo); +} + +// cleanup/shutdown Libspe2 +PosixThreadSupport::~PosixThreadSupport() +{ + stopSPU(); +} + +#if (defined (__APPLE__)) +#define NAMED_SEMAPHORES +#endif + +// this semaphore will signal, if and how many threads are finished with their work +static sem_t* mainSemaphore=0; + +static sem_t* createSem(const char* baseName) +{ + static int semCount = 0; +#ifdef NAMED_SEMAPHORES + /// Named semaphore begin + char name[32]; + snprintf(name, 32, "/%s-%d-%4.4d", baseName, getpid(), semCount++); + sem_t* tempSem = sem_open(name, O_CREAT, 0600, 0); + + if (tempSem != reinterpret_cast(SEM_FAILED)) + { +// printf("Created \"%s\" Semaphore %p\n", name, tempSem); + } + else + { + //printf("Error creating Semaphore %d\n", errno); + exit(-1); + } + /// Named semaphore end +#else + sem_t* tempSem = new sem_t; + checkPThreadFunction(sem_init(tempSem, 0, 0)); +#endif + return tempSem; +} + +static void destroySem(sem_t* semaphore) +{ +#ifdef NAMED_SEMAPHORES + checkPThreadFunction(sem_close(semaphore)); +#else + checkPThreadFunction(sem_destroy(semaphore)); + delete semaphore; +#endif +} + +static void *threadFunction(void *argument) +{ + + PosixThreadSupport::btSpuStatus* status = (PosixThreadSupport::btSpuStatus*)argument; + + + while (1) + { + checkPThreadFunction(sem_wait(status->startSemaphore)); + + void* userPtr = status->m_userPtr; + + if (userPtr) + { + btAssert(status->m_status); + status->m_userThreadFunc(userPtr,status->m_lsMemory); + status->m_status = 2; + checkPThreadFunction(sem_post(mainSemaphore)); + status->threadUsed++; + } else { + //exit Thread + status->m_status = 3; + checkPThreadFunction(sem_post(mainSemaphore)); + printf("Thread with taskId %i exiting\n",status->m_taskId); + break; + } + + } + + printf("Thread TERMINATED\n"); + return 0; + +} + +///send messages to SPUs +void PosixThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId) +{ + /// gMidphaseSPU.sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (uint32_t) &taskDesc); + + ///we should spawn an SPU task here, and in 'waitForResponse' it should wait for response of the (one of) the first tasks that finished + + + + switch (uiCommand) + { + case CMD_GATHER_AND_PROCESS_PAIRLIST: + { + btSpuStatus& spuStatus = m_activeSpuStatus[taskId]; + btAssert(taskId >= 0); + btAssert(taskId < m_activeSpuStatus.size()); + + spuStatus.m_commandId = uiCommand; + spuStatus.m_status = 1; + spuStatus.m_userPtr = (void*)uiArgument0; + + // fire event to start new task + checkPThreadFunction(sem_post(spuStatus.startSemaphore)); + break; + } + default: + { + ///not implemented + btAssert(0); + } + + }; + + +} + + +///check for messages from SPUs +void PosixThreadSupport::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) +{ + ///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response + + ///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback' + + + btAssert(m_activeSpuStatus.size()); + + // wait for any of the threads to finish + checkPThreadFunction(sem_wait(mainSemaphore)); + + // get at least one thread which has finished + size_t last = -1; + + for(size_t t=0; t < size_t(m_activeSpuStatus.size()); ++t) { + if(2 == m_activeSpuStatus[t].m_status) { + last = t; + break; + } + } + + btSpuStatus& spuStatus = m_activeSpuStatus[last]; + + btAssert(spuStatus.m_status > 1); + spuStatus.m_status = 0; + + // need to find an active spu + btAssert(last >= 0); + + *puiArgument0 = spuStatus.m_taskId; + *puiArgument1 = spuStatus.m_status; +} + + + +void PosixThreadSupport::startThreads(ThreadConstructionInfo& threadConstructionInfo) +{ + printf("%s creating %i threads.\n", __FUNCTION__, threadConstructionInfo.m_numThreads); + m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads); + + mainSemaphore = createSem("main"); + //checkPThreadFunction(sem_wait(mainSemaphore)); + + for (int i=0;i < threadConstructionInfo.m_numThreads;i++) + { + printf("starting thread %d\n",i); + + btSpuStatus& spuStatus = m_activeSpuStatus[i]; + + spuStatus.startSemaphore = createSem("threadLocal"); + + checkPThreadFunction(pthread_create(&spuStatus.thread, NULL, &threadFunction, (void*)&spuStatus)); + + spuStatus.m_userPtr=0; + + spuStatus.m_taskId = i; + spuStatus.m_commandId = 0; + spuStatus.m_status = 0; + spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc(); + spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc; + spuStatus.threadUsed = 0; + + printf("started thread %d \n",i); + + } + +} + +void PosixThreadSupport::startSPU() +{ +} + + +///tell the task scheduler we are done with the SPU tasks +void PosixThreadSupport::stopSPU() +{ + for(size_t t=0; t < size_t(m_activeSpuStatus.size()); ++t) + { + btSpuStatus& spuStatus = m_activeSpuStatus[t]; + printf("%s: Thread %i used: %ld\n", __FUNCTION__, int(t), spuStatus.threadUsed); + + spuStatus.m_userPtr = 0; + checkPThreadFunction(sem_post(spuStatus.startSemaphore)); + checkPThreadFunction(sem_wait(mainSemaphore)); + + printf("destroy semaphore\n"); + destroySem(spuStatus.startSemaphore); + printf("semaphore destroyed\n"); + checkPThreadFunction(pthread_join(spuStatus.thread,0)); + } + printf("destroy main semaphore\n"); + destroySem(mainSemaphore); + printf("main semaphore destroyed\n"); + m_activeSpuStatus.clear(); +} + +class PosixCriticalSection : public btCriticalSection +{ + pthread_mutex_t m_mutex; + +public: + PosixCriticalSection() + { + pthread_mutex_init(&m_mutex, NULL); + } + virtual ~PosixCriticalSection() + { + pthread_mutex_destroy(&m_mutex); + } + + ATTRIBUTE_ALIGNED16(unsigned int mCommonBuff[32]); + + virtual unsigned int getSharedParam(int i) + { + return mCommonBuff[i]; + } + virtual void setSharedParam(int i,unsigned int p) + { + mCommonBuff[i] = p; + } + + virtual void lock() + { + pthread_mutex_lock(&m_mutex); + } + virtual void unlock() + { + pthread_mutex_unlock(&m_mutex); + } +}; + + +#if defined(_POSIX_BARRIERS) && (_POSIX_BARRIERS - 20012L) >= 0 +/* OK to use barriers on this platform */ +class PosixBarrier : public btBarrier +{ + pthread_barrier_t m_barr; + int m_numThreads; +public: + PosixBarrier() + :m_numThreads(0) { } + virtual ~PosixBarrier() { + pthread_barrier_destroy(&m_barr); + } + + virtual void sync() + { + int rc = pthread_barrier_wait(&m_barr); + if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf("Could not wait on barrier\n"); + exit(-1); + } + } + virtual void setMaxCount(int numThreads) + { + int result = pthread_barrier_init(&m_barr, NULL, numThreads); + m_numThreads = numThreads; + btAssert(result==0); + } + virtual int getMaxCount() + { + return m_numThreads; + } +}; +#else +/* Not OK to use barriers on this platform - insert alternate code here */ +class PosixBarrier : public btBarrier +{ + pthread_mutex_t m_mutex; + pthread_cond_t m_cond; + + int m_numThreads; + int m_called; + +public: + PosixBarrier() + :m_numThreads(0) + { + } + virtual ~PosixBarrier() + { + if (m_numThreads>0) + { + pthread_mutex_destroy(&m_mutex); + pthread_cond_destroy(&m_cond); + } + } + + virtual void sync() + { + pthread_mutex_lock(&m_mutex); + m_called++; + if (m_called == m_numThreads) { + m_called = 0; + pthread_cond_broadcast(&m_cond); + } else { + pthread_cond_wait(&m_cond,&m_mutex); + } + pthread_mutex_unlock(&m_mutex); + + } + virtual void setMaxCount(int numThreads) + { + if (m_numThreads>0) + { + pthread_mutex_destroy(&m_mutex); + pthread_cond_destroy(&m_cond); + } + m_called = 0; + pthread_mutex_init(&m_mutex,NULL); + pthread_cond_init(&m_cond,NULL); + m_numThreads = numThreads; + } + virtual int getMaxCount() + { + return m_numThreads; + } +}; + +#endif//_POSIX_BARRIERS + + + +btBarrier* PosixThreadSupport::createBarrier() +{ + PosixBarrier* barrier = new PosixBarrier(); + barrier->setMaxCount(getNumTasks()); + return barrier; +} + +btCriticalSection* PosixThreadSupport::createCriticalSection() +{ + return new PosixCriticalSection(); +} + +#endif // USE_PTHREADS + diff --git a/src/BulletMultiThreaded/PosixThreadSupport.h b/src/BulletMultiThreaded/PosixThreadSupport.h new file mode 100644 index 0000000..ca47e45 --- /dev/null +++ b/src/BulletMultiThreaded/PosixThreadSupport.h @@ -0,0 +1,142 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_POSIX_THREAD_SUPPORT_H +#define BT_POSIX_THREAD_SUPPORT_H + + +#include "LinearMath/btScalar.h" +#include "PlatformDefinitions.h" + +#ifdef USE_PTHREADS //platform specifc defines are defined in PlatformDefinitions.h + +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 600 //for definition of pthread_barrier_t, see http://pages.cs.wisc.edu/~travitch/pthreads_primer.html +#endif //_XOPEN_SOURCE +#include +#include + + + +#include "LinearMath/btAlignedObjectArray.h" + +#include "btThreadSupportInterface.h" + + +typedef void (*PosixThreadFunc)(void* userPtr,void* lsMemory); +typedef void* (*PosixlsMemorySetupFunc)(); + +// PosixThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication +class PosixThreadSupport : public btThreadSupportInterface +{ +public: + typedef enum sStatus { + STATUS_BUSY, + STATUS_READY, + STATUS_FINISHED + } Status; + + // placeholder, until libspe2 support is there + struct btSpuStatus + { + uint32_t m_taskId; + uint32_t m_commandId; + uint32_t m_status; + + PosixThreadFunc m_userThreadFunc; + void* m_userPtr; //for taskDesc etc + void* m_lsMemory; //initialized using PosixLocalStoreMemorySetupFunc + + pthread_t thread; + sem_t* startSemaphore; + + unsigned long threadUsed; + }; +private: + + btAlignedObjectArray m_activeSpuStatus; +public: + ///Setup and initialize SPU/CELL/Libspe2 + + + + struct ThreadConstructionInfo + { + ThreadConstructionInfo(const char* uniqueName, + PosixThreadFunc userThreadFunc, + PosixlsMemorySetupFunc lsMemoryFunc, + int numThreads=1, + int threadStackSize=65535 + ) + :m_uniqueName(uniqueName), + m_userThreadFunc(userThreadFunc), + m_lsMemoryFunc(lsMemoryFunc), + m_numThreads(numThreads), + m_threadStackSize(threadStackSize) + { + + } + + const char* m_uniqueName; + PosixThreadFunc m_userThreadFunc; + PosixlsMemorySetupFunc m_lsMemoryFunc; + int m_numThreads; + int m_threadStackSize; + + }; + + PosixThreadSupport(ThreadConstructionInfo& threadConstructionInfo); + +///cleanup/shutdown Libspe2 + virtual ~PosixThreadSupport(); + + void startThreads(ThreadConstructionInfo& threadInfo); + + +///send messages to SPUs + virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1); + +///check for messages from SPUs + virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1); + +///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) + virtual void startSPU(); + +///tell the task scheduler we are done with the SPU tasks + virtual void stopSPU(); + + virtual void setNumTasks(int numTasks) {} + + virtual int getNumTasks() const + { + return m_activeSpuStatus.size(); + } + + virtual btBarrier* createBarrier(); + + virtual btCriticalSection* createCriticalSection(); + + virtual void* getThreadLocalMemory(int taskId) + { + return m_activeSpuStatus[taskId].m_lsMemory; + } + +}; + +#endif // USE_PTHREADS + +#endif // BT_POSIX_THREAD_SUPPORT_H + + diff --git a/src/BulletMultiThreaded/PpuAddressSpace.h b/src/BulletMultiThreaded/PpuAddressSpace.h new file mode 100644 index 0000000..6f22827 --- /dev/null +++ b/src/BulletMultiThreaded/PpuAddressSpace.h @@ -0,0 +1,37 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2010 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_PPU_ADDRESS_SPACE_H +#define BT_PPU_ADDRESS_SPACE_H + + +#ifdef _WIN32 +//stop those casting warnings until we have a better solution for ppu_address_t / void* / uint64 conversions +#pragma warning (disable: 4311) +#pragma warning (disable: 4312) +#endif //_WIN32 + + +#if defined(_WIN64) + typedef unsigned __int64 ppu_address_t; +#elif defined(__LP64__) || defined(__x86_64__) + typedef uint64_t ppu_address_t; +#else + typedef uint32_t ppu_address_t; +#endif //defined(_WIN64) + +#endif //BT_PPU_ADDRESS_SPACE_H + diff --git a/src/BulletMultiThreaded/SequentialThreadSupport.cpp b/src/BulletMultiThreaded/SequentialThreadSupport.cpp new file mode 100644 index 0000000..8cc7241 --- /dev/null +++ b/src/BulletMultiThreaded/SequentialThreadSupport.cpp @@ -0,0 +1,169 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +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 "SequentialThreadSupport.h" + + +#include "SpuCollisionTaskProcess.h" +#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" + +SequentialThreadSupport::SequentialThreadSupport(SequentialThreadConstructionInfo& threadConstructionInfo) +{ + startThreads(threadConstructionInfo); +} + +///cleanup/shutdown Libspe2 +SequentialThreadSupport::~SequentialThreadSupport() +{ + stopSPU(); +} + +#include + +///send messages to SPUs +void SequentialThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId) +{ + switch (uiCommand) + { + case CMD_GATHER_AND_PROCESS_PAIRLIST: + { + btSpuStatus& spuStatus = m_activeSpuStatus[0]; + spuStatus.m_userPtr=(void*)uiArgument0; + spuStatus.m_userThreadFunc(spuStatus.m_userPtr,spuStatus.m_lsMemory); + } + break; + default: + { + ///not implemented + btAssert(0 && "Not implemented"); + } + + }; + + +} + +///check for messages from SPUs +void SequentialThreadSupport::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) +{ + btAssert(m_activeSpuStatus.size()); + btSpuStatus& spuStatus = m_activeSpuStatus[0]; + *puiArgument0 = spuStatus.m_taskId; + *puiArgument1 = spuStatus.m_status; +} + +void SequentialThreadSupport::startThreads(SequentialThreadConstructionInfo& threadConstructionInfo) +{ + m_activeSpuStatus.resize(1); + printf("STS: Not starting any threads\n"); + btSpuStatus& spuStatus = m_activeSpuStatus[0]; + spuStatus.m_userPtr = 0; + spuStatus.m_taskId = 0; + spuStatus.m_commandId = 0; + spuStatus.m_status = 0; + spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc(); + spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc; + printf("STS: Created local store at %p for task %s\n", spuStatus.m_lsMemory, threadConstructionInfo.m_uniqueName); +} + +void SequentialThreadSupport::startSPU() +{ +} + +void SequentialThreadSupport::stopSPU() +{ + m_activeSpuStatus.clear(); +} + +void SequentialThreadSupport::setNumTasks(int numTasks) +{ + printf("SequentialThreadSupport::setNumTasks(%d) is not implemented and has no effect\n",numTasks); +} + + + + +class btDummyBarrier : public btBarrier +{ +private: + +public: + btDummyBarrier() + { + } + + virtual ~btDummyBarrier() + { + } + + void sync() + { + } + + virtual void setMaxCount(int n) {} + virtual int getMaxCount() {return 1;} +}; + +class btDummyCriticalSection : public btCriticalSection +{ + +public: + btDummyCriticalSection() + { + } + + virtual ~btDummyCriticalSection() + { + } + + unsigned int getSharedParam(int i) + { + btAssert(i>=0&&i<31); + return mCommonBuff[i+1]; + } + + void setSharedParam(int i,unsigned int p) + { + btAssert(i>=0&&i<31); + mCommonBuff[i+1] = p; + } + + void lock() + { + mCommonBuff[0] = 1; + } + + void unlock() + { + mCommonBuff[0] = 0; + } +}; + + + + +btBarrier* SequentialThreadSupport::createBarrier() +{ + return new btDummyBarrier(); +} + +btCriticalSection* SequentialThreadSupport::createCriticalSection() +{ + return new btDummyCriticalSection(); + +} + + + diff --git a/src/BulletMultiThreaded/SequentialThreadSupport.h b/src/BulletMultiThreaded/SequentialThreadSupport.h new file mode 100644 index 0000000..2b9ade8 --- /dev/null +++ b/src/BulletMultiThreaded/SequentialThreadSupport.h @@ -0,0 +1,96 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "LinearMath/btScalar.h" +#include "PlatformDefinitions.h" + + +#ifndef BT_SEQUENTIAL_THREAD_SUPPORT_H +#define BT_SEQUENTIAL_THREAD_SUPPORT_H + +#include "LinearMath/btAlignedObjectArray.h" + +#include "btThreadSupportInterface.h" + +typedef void (*SequentialThreadFunc)(void* userPtr,void* lsMemory); +typedef void* (*SequentiallsMemorySetupFunc)(); + + + +///The SequentialThreadSupport is a portable non-parallel implementation of the btThreadSupportInterface +///This is useful for debugging and porting SPU Tasks to other platforms. +class SequentialThreadSupport : public btThreadSupportInterface +{ +public: + struct btSpuStatus + { + uint32_t m_taskId; + uint32_t m_commandId; + uint32_t m_status; + + SequentialThreadFunc m_userThreadFunc; + + void* m_userPtr; //for taskDesc etc + void* m_lsMemory; //initialized using SequentiallsMemorySetupFunc + }; +private: + btAlignedObjectArray m_activeSpuStatus; + btAlignedObjectArray m_completeHandles; +public: + struct SequentialThreadConstructionInfo + { + SequentialThreadConstructionInfo (const char* uniqueName, + SequentialThreadFunc userThreadFunc, + SequentiallsMemorySetupFunc lsMemoryFunc + ) + :m_uniqueName(uniqueName), + m_userThreadFunc(userThreadFunc), + m_lsMemoryFunc(lsMemoryFunc) + { + + } + + const char* m_uniqueName; + SequentialThreadFunc m_userThreadFunc; + SequentiallsMemorySetupFunc m_lsMemoryFunc; + }; + + SequentialThreadSupport(SequentialThreadConstructionInfo& threadConstructionInfo); + virtual ~SequentialThreadSupport(); + void startThreads(SequentialThreadConstructionInfo& threadInfo); +///send messages to SPUs + virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1); +///check for messages from SPUs + virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1); +///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) + virtual void startSPU(); +///tell the task scheduler we are done with the SPU tasks + virtual void stopSPU(); + + virtual void setNumTasks(int numTasks); + + virtual int getNumTasks() const + { + return 1; + } + virtual btBarrier* createBarrier(); + + virtual btCriticalSection* createCriticalSection(); + + +}; + +#endif //BT_SEQUENTIAL_THREAD_SUPPORT_H + diff --git a/src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp b/src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp new file mode 100644 index 0000000..182aa26 --- /dev/null +++ b/src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp @@ -0,0 +1,48 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +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 "SpuCollisionObjectWrapper.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" + +SpuCollisionObjectWrapper::SpuCollisionObjectWrapper () +{ +} + +#ifndef __SPU__ +SpuCollisionObjectWrapper::SpuCollisionObjectWrapper (const btCollisionObject* collisionObject) +{ + m_shapeType = collisionObject->getCollisionShape()->getShapeType (); + m_collisionObjectPtr = (ppu_address_t)collisionObject; + m_margin = collisionObject->getCollisionShape()->getMargin (); +} +#endif + +int +SpuCollisionObjectWrapper::getShapeType () const +{ + return m_shapeType; +} + +float +SpuCollisionObjectWrapper::getCollisionMargin () const +{ + return m_margin; +} + +ppu_address_t +SpuCollisionObjectWrapper::getCollisionObjectPtr () const +{ + return m_collisionObjectPtr; +} diff --git a/src/BulletMultiThreaded/SpuCollisionObjectWrapper.h b/src/BulletMultiThreaded/SpuCollisionObjectWrapper.h new file mode 100644 index 0000000..f90da27 --- /dev/null +++ b/src/BulletMultiThreaded/SpuCollisionObjectWrapper.h @@ -0,0 +1,40 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SPU_COLLISION_OBJECT_WRAPPER_H +#define BT_SPU_COLLISION_OBJECT_WRAPPER_H + +#include "PlatformDefinitions.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" + +ATTRIBUTE_ALIGNED16(class) SpuCollisionObjectWrapper +{ +protected: + int m_shapeType; + float m_margin; + ppu_address_t m_collisionObjectPtr; + +public: + SpuCollisionObjectWrapper (); + + SpuCollisionObjectWrapper (const btCollisionObject* collisionObject); + + int getShapeType () const; + float getCollisionMargin () const; + ppu_address_t getCollisionObjectPtr () const; +}; + + +#endif //BT_SPU_COLLISION_OBJECT_WRAPPER_H diff --git a/src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp b/src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp new file mode 100644 index 0000000..f606d13 --- /dev/null +++ b/src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp @@ -0,0 +1,317 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +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. +*/ + + +//#define DEBUG_SPU_TASK_SCHEDULING 1 + + +//class OptimizedBvhNode; + +#include "SpuCollisionTaskProcess.h" + + + + +void SpuCollisionTaskProcess::setNumTasks(int maxNumTasks) +{ + if (int(m_maxNumOutstandingTasks) != maxNumTasks) + { + m_maxNumOutstandingTasks = maxNumTasks; + m_taskBusy.resize(m_maxNumOutstandingTasks); + m_spuGatherTaskDesc.resize(m_maxNumOutstandingTasks); + + for (int i = 0; i < m_taskBusy.size(); i++) + { + m_taskBusy[i] = false; + } + + ///re-allocate task memory buffers + if (m_workUnitTaskBuffers != 0) + { + btAlignedFree(m_workUnitTaskBuffers); + } + + m_workUnitTaskBuffers = (unsigned char *)btAlignedAlloc(MIDPHASE_WORKUNIT_TASK_SIZE*m_maxNumOutstandingTasks, 128); + } + +} + + + +SpuCollisionTaskProcess::SpuCollisionTaskProcess(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks) +:m_threadInterface(threadInterface), +m_maxNumOutstandingTasks(0) +{ + m_workUnitTaskBuffers = (unsigned char *)0; + setNumTasks(maxNumOutstandingTasks); + m_numBusyTasks = 0; + m_currentTask = 0; + m_currentPage = 0; + m_currentPageEntry = 0; + +#ifdef DEBUG_SpuCollisionTaskProcess + m_initialized = false; +#endif + + m_threadInterface->startSPU(); + + //printf("sizeof vec_float4: %d\n", sizeof(vec_float4)); + printf("sizeof SpuGatherAndProcessWorkUnitInput: %d\n", int(sizeof(SpuGatherAndProcessWorkUnitInput))); + +} + +SpuCollisionTaskProcess::~SpuCollisionTaskProcess() +{ + + if (m_workUnitTaskBuffers != 0) + { + btAlignedFree(m_workUnitTaskBuffers); + m_workUnitTaskBuffers = 0; + } + + + + m_threadInterface->stopSPU(); + +} + + + +void SpuCollisionTaskProcess::initialize2(bool useEpa) +{ + +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("SpuCollisionTaskProcess::initialize()\n"); +#endif //DEBUG_SPU_TASK_SCHEDULING + + for (int i = 0; i < int (m_maxNumOutstandingTasks); i++) + { + m_taskBusy[i] = false; + } + m_numBusyTasks = 0; + m_currentTask = 0; + m_currentPage = 0; + m_currentPageEntry = 0; + m_useEpa = useEpa; + +#ifdef DEBUG_SpuCollisionTaskProcess + m_initialized = true; + btAssert(MIDPHASE_NUM_WORKUNITS_PER_TASK*sizeof(SpuGatherAndProcessWorkUnitInput) <= MIDPHASE_WORKUNIT_TASK_SIZE); +#endif +} + + +void SpuCollisionTaskProcess::issueTask2() +{ + +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("SpuCollisionTaskProcess::issueTask (m_currentTask= %d\n)", m_currentTask); +#endif //DEBUG_SPU_TASK_SCHEDULING + + m_taskBusy[m_currentTask] = true; + m_numBusyTasks++; + + + SpuGatherAndProcessPairsTaskDesc& taskDesc = m_spuGatherTaskDesc[m_currentTask]; + taskDesc.m_useEpa = m_useEpa; + + { + // send task description in event message + // no error checking here... + // but, currently, event queue can be no larger than NUM_WORKUNIT_TASKS. + + taskDesc.m_inPairPtr = reinterpret_cast(MIDPHASE_TASK_PTR(m_currentTask)); + + taskDesc.taskId = m_currentTask; + taskDesc.numPages = m_currentPage+1; + taskDesc.numOnLastPage = m_currentPageEntry; + } + + + + m_threadInterface->sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (ppu_address_t) &taskDesc,m_currentTask); + + // if all tasks busy, wait for spu event to clear the task. + + + if (m_numBusyTasks >= m_maxNumOutstandingTasks) + { + unsigned int taskId; + unsigned int outputSize; + + + for (int i=0;i=0); + + + m_threadInterface->waitForResponse(&taskId, &outputSize); + +// printf("issueTask taskId %d completed, numBusy=%d\n",taskId,m_numBusyTasks); + + //printf("PPU: after issue, received event: %u %d\n", taskId, outputSize); + + //postProcess(taskId, outputSize); + + m_taskBusy[taskId] = false; + + m_numBusyTasks--; + } + +} + +void SpuCollisionTaskProcess::addWorkToTask(void* pairArrayPtr,int startIndex,int endIndex) +{ +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("#"); +#endif //DEBUG_SPU_TASK_SCHEDULING + +#ifdef DEBUG_SpuCollisionTaskProcess + btAssert(m_initialized); + btAssert(m_workUnitTaskBuffers); + +#endif + + bool batch = true; + + if (batch) + { + if (m_currentPageEntry == MIDPHASE_NUM_WORKUNITS_PER_PAGE) + { + if (m_currentPage == MIDPHASE_NUM_WORKUNIT_PAGES-1) + { + // task buffer is full, issue current task. + // if all task buffers busy, this waits until SPU is done. + issueTask2(); + + // find new task buffer + for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++) + { + if (!m_taskBusy[i]) + { + m_currentTask = i; + //init the task data + + break; + } + } + + m_currentPage = 0; + } + else + { + m_currentPage++; + } + + m_currentPageEntry = 0; + } + } + + { + + + + SpuGatherAndProcessWorkUnitInput &wuInput = + *(reinterpret_cast + (MIDPHASE_ENTRY_PTR(m_currentTask, m_currentPage, m_currentPageEntry))); + + wuInput.m_pairArrayPtr = reinterpret_cast(pairArrayPtr); + wuInput.m_startIndex = startIndex; + wuInput.m_endIndex = endIndex; + + + + m_currentPageEntry++; + + if (!batch) + { + issueTask2(); + + // find new task buffer + for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++) + { + if (!m_taskBusy[i]) + { + m_currentTask = i; + //init the task data + + break; + } + } + + m_currentPage = 0; + m_currentPageEntry =0; + } + } +} + + +void +SpuCollisionTaskProcess::flush2() +{ +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("\nSpuCollisionTaskProcess::flush()\n"); +#endif //DEBUG_SPU_TASK_SCHEDULING + + // if there's a partially filled task buffer, submit that task + if (m_currentPage > 0 || m_currentPageEntry > 0) + { + issueTask2(); + } + + + // all tasks are issued, wait for all tasks to be complete + while(m_numBusyTasks > 0) + { + // Consolidating SPU code + unsigned int taskId=-1; + unsigned int outputSize; + + for (int i=0;i=0); + + + { + + // SPURS support. + m_threadInterface->waitForResponse(&taskId, &outputSize); + } +// printf("flush2 taskId %d completed, numBusy =%d \n",taskId,m_numBusyTasks); + //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize); + + //postProcess(taskId, outputSize); + + m_taskBusy[taskId] = false; + + m_numBusyTasks--; + } + + +} diff --git a/src/BulletMultiThreaded/SpuCollisionTaskProcess.h b/src/BulletMultiThreaded/SpuCollisionTaskProcess.h new file mode 100644 index 0000000..23b5b05 --- /dev/null +++ b/src/BulletMultiThreaded/SpuCollisionTaskProcess.h @@ -0,0 +1,163 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SPU_COLLISION_TASK_PROCESS_H +#define BT_SPU_COLLISION_TASK_PROCESS_H + +#include + +#include "LinearMath/btScalar.h" + +#include "PlatformDefinitions.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" // for definitions processCollisionTask and createCollisionLocalStoreMemory + +#include "btThreadSupportInterface.h" + + +//#include "SPUAssert.h" +#include + + +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" + +#include "LinearMath/btAlignedAllocator.h" + +#include + + +#define DEBUG_SpuCollisionTaskProcess 1 + + +#define CMD_GATHER_AND_PROCESS_PAIRLIST 1 + +class btCollisionObject; +class btPersistentManifold; +class btDispatcher; + + +/////Task Description for SPU collision detection +//struct SpuGatherAndProcessPairsTaskDesc +//{ +// uint64_t inPtr;//m_pairArrayPtr; +// //mutex variable +// uint32_t m_someMutexVariableInMainMemory; +// +// uint64_t m_dispatcher; +// +// uint32_t numOnLastPage; +// +// uint16_t numPages; +// uint16_t taskId; +// +// struct CollisionTask_LocalStoreMemory* m_lsMemory; +//} +// +//#if defined(__CELLOS_LV2__) || defined(USE_LIBSPE2) +//__attribute__ ((aligned (16))) +//#endif +//; + + +///MidphaseWorkUnitInput stores individual primitive versus mesh collision detection input, to be processed by the SPU. +ATTRIBUTE_ALIGNED16(struct) SpuGatherAndProcessWorkUnitInput +{ + uint64_t m_pairArrayPtr; + int m_startIndex; + int m_endIndex; +}; + + + + +/// SpuCollisionTaskProcess handles SPU processing of collision pairs. +/// Maintains a set of task buffers. +/// When the task is full, the task is issued for SPUs to process. Contact output goes into btPersistentManifold +/// associated with each task. +/// When PPU issues a task, it will look for completed task buffers +/// PPU will do postprocessing, dependent on workunit output (not likely) +class SpuCollisionTaskProcess +{ + + unsigned char *m_workUnitTaskBuffers; + + + // track task buffers that are being used, and total busy tasks + btAlignedObjectArray m_taskBusy; + btAlignedObjectArray m_spuGatherTaskDesc; + + class btThreadSupportInterface* m_threadInterface; + + unsigned int m_maxNumOutstandingTasks; + + unsigned int m_numBusyTasks; + + // the current task and the current entry to insert a new work unit + unsigned int m_currentTask; + unsigned int m_currentPage; + unsigned int m_currentPageEntry; + + bool m_useEpa; + +#ifdef DEBUG_SpuCollisionTaskProcess + bool m_initialized; +#endif + void issueTask2(); + //void postProcess(unsigned int taskId, int outputSize); + +public: + SpuCollisionTaskProcess(btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks); + + ~SpuCollisionTaskProcess(); + + ///call initialize in the beginning of the frame, before addCollisionPairToTask + void initialize2(bool useEpa = false); + + ///batch up additional work to a current task for SPU processing. When batch is full, it issues the task. + void addWorkToTask(void* pairArrayPtr,int startIndex,int endIndex); + + ///call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished + void flush2(); + + /// set the maximum number of SPU tasks allocated + void setNumTasks(int maxNumTasks); + + int getNumTasks() const + { + return m_maxNumOutstandingTasks; + } +}; + + + +#define MIDPHASE_TASK_PTR(task) (&m_workUnitTaskBuffers[0] + MIDPHASE_WORKUNIT_TASK_SIZE*task) +#define MIDPHASE_ENTRY_PTR(task,page,entry) (MIDPHASE_TASK_PTR(task) + MIDPHASE_WORKUNIT_PAGE_SIZE*page + sizeof(SpuGatherAndProcessWorkUnitInput)*entry) +#define MIDPHASE_OUTPUT_PTR(task) (&m_contactOutputBuffers[0] + MIDPHASE_MAX_CONTACT_BUFFER_SIZE*task) +#define MIDPHASE_TREENODES_PTR(task) (&m_complexShapeBuffers[0] + MIDPHASE_COMPLEX_SHAPE_BUFFER_SIZE*task) + + +#define MIDPHASE_WORKUNIT_PAGE_SIZE (16) +//#define MIDPHASE_WORKUNIT_PAGE_SIZE (128) + +#define MIDPHASE_NUM_WORKUNIT_PAGES 1 +#define MIDPHASE_WORKUNIT_TASK_SIZE (MIDPHASE_WORKUNIT_PAGE_SIZE*MIDPHASE_NUM_WORKUNIT_PAGES) +#define MIDPHASE_NUM_WORKUNITS_PER_PAGE (MIDPHASE_WORKUNIT_PAGE_SIZE / sizeof(SpuGatherAndProcessWorkUnitInput)) +#define MIDPHASE_NUM_WORKUNITS_PER_TASK (MIDPHASE_NUM_WORKUNITS_PER_PAGE*MIDPHASE_NUM_WORKUNIT_PAGES) + + +#endif // BT_SPU_COLLISION_TASK_PROCESS_H + diff --git a/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp b/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp new file mode 100644 index 0000000..286b631 --- /dev/null +++ b/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp @@ -0,0 +1,69 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +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 "SpuContactManifoldCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" + + + + +void SpuContactManifoldCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + btAssert(0); +} + +btScalar SpuContactManifoldCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + btAssert(0); + return 1.f; +} + +#ifndef __SPU__ +SpuContactManifoldCollisionAlgorithm::SpuContactManifoldCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1) +:btCollisionAlgorithm(ci) +#ifdef USE_SEPDISTANCE_UTIL +,m_sepDistance(body0->getCollisionShape()->getAngularMotionDisc(),body1->getCollisionShape()->getAngularMotionDisc()) +#endif //USE_SEPDISTANCE_UTIL +{ + m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1); + m_shapeType0 = body0->getCollisionShape()->getShapeType(); + m_shapeType1 = body1->getCollisionShape()->getShapeType(); + m_collisionMargin0 = body0->getCollisionShape()->getMargin(); + m_collisionMargin1 = body1->getCollisionShape()->getMargin(); + m_collisionObject0 = body0; + m_collisionObject1 = body1; + + if (body0->getCollisionShape()->isPolyhedral()) + { + btPolyhedralConvexShape* convex0 = (btPolyhedralConvexShape*)body0->getCollisionShape(); + m_shapeDimensions0 = convex0->getImplicitShapeDimensions(); + } + if (body1->getCollisionShape()->isPolyhedral()) + { + btPolyhedralConvexShape* convex1 = (btPolyhedralConvexShape*)body1->getCollisionShape(); + m_shapeDimensions1 = convex1->getImplicitShapeDimensions(); + } +} +#endif //__SPU__ + + +SpuContactManifoldCollisionAlgorithm::~SpuContactManifoldCollisionAlgorithm() +{ + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); +} diff --git a/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h b/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h new file mode 100644 index 0000000..d28d4db --- /dev/null +++ b/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h @@ -0,0 +1,120 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H +#define BT_SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "LinearMath/btTransformUtil.h" + +class btPersistentManifold; + +//#define USE_SEPDISTANCE_UTIL 1 + +/// SpuContactManifoldCollisionAlgorithm provides contact manifold and should be processed on SPU. +ATTRIBUTE_ALIGNED16(class) SpuContactManifoldCollisionAlgorithm : public btCollisionAlgorithm +{ + btVector3 m_shapeDimensions0; + btVector3 m_shapeDimensions1; + btPersistentManifold* m_manifoldPtr; + int m_shapeType0; + int m_shapeType1; + float m_collisionMargin0; + float m_collisionMargin1; + + btCollisionObject* m_collisionObject0; + btCollisionObject* m_collisionObject1; + + + + +public: + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + + SpuContactManifoldCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); +#ifdef USE_SEPDISTANCE_UTIL + btConvexSeparatingDistanceUtil m_sepDistance; +#endif //USE_SEPDISTANCE_UTIL + + virtual ~SpuContactManifoldCollisionAlgorithm(); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr) + manifoldArray.push_back(m_manifoldPtr); + } + + btPersistentManifold* getContactManifoldPtr() + { + return m_manifoldPtr; + } + + btCollisionObject* getCollisionObject0() + { + return m_collisionObject0; + } + + btCollisionObject* getCollisionObject1() + { + return m_collisionObject1; + } + + int getShapeType0() const + { + return m_shapeType0; + } + + int getShapeType1() const + { + return m_shapeType1; + } + float getCollisionMargin0() const + { + return m_collisionMargin0; + } + float getCollisionMargin1() const + { + return m_collisionMargin1; + } + + const btVector3& getShapeDimensions0() const + { + return m_shapeDimensions0; + } + + const btVector3& getShapeDimensions1() const + { + return m_shapeDimensions1; + } + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(SpuContactManifoldCollisionAlgorithm)); + return new(mem) SpuContactManifoldCollisionAlgorithm(ci,body0,body1); + } + }; + +}; + +#endif //BT_SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H diff --git a/src/BulletMultiThreaded/SpuDoubleBuffer.h b/src/BulletMultiThreaded/SpuDoubleBuffer.h new file mode 100644 index 0000000..558d615 --- /dev/null +++ b/src/BulletMultiThreaded/SpuDoubleBuffer.h @@ -0,0 +1,126 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_DOUBLE_BUFFER_H +#define BT_DOUBLE_BUFFER_H + +#include "SpuFakeDma.h" +#include "LinearMath/btScalar.h" + + +///DoubleBuffer +template +class DoubleBuffer +{ +#if defined(__SPU__) || defined(USE_LIBSPE2) + ATTRIBUTE_ALIGNED128( T m_buffer0[size] ) ; + ATTRIBUTE_ALIGNED128( T m_buffer1[size] ) ; +#else + T m_buffer0[size]; + T m_buffer1[size]; +#endif + + T *m_frontBuffer; + T *m_backBuffer; + + unsigned int m_dmaTag; + bool m_dmaPending; +public: + bool isPending() const { return m_dmaPending;} + DoubleBuffer(); + + void init (); + + // dma get and put commands + void backBufferDmaGet(uint64_t ea, unsigned int numBytes, unsigned int tag); + void backBufferDmaPut(uint64_t ea, unsigned int numBytes, unsigned int tag); + + // gets pointer to a buffer + T *getFront(); + T *getBack(); + + // if back buffer dma was started, wait for it to complete + // then move back to front and vice versa + T *swapBuffers(); +}; + +template +DoubleBuffer::DoubleBuffer() +{ + init (); +} + +template +void DoubleBuffer::init() +{ + this->m_dmaPending = false; + this->m_frontBuffer = &this->m_buffer0[0]; + this->m_backBuffer = &this->m_buffer1[0]; +} + +template +void +DoubleBuffer::backBufferDmaGet(uint64_t ea, unsigned int numBytes, unsigned int tag) +{ + m_dmaPending = true; + m_dmaTag = tag; + if (numBytes) + { + m_backBuffer = (T*)cellDmaLargeGetReadOnly(m_backBuffer, ea, numBytes, tag, 0, 0); + } +} + +template +void +DoubleBuffer::backBufferDmaPut(uint64_t ea, unsigned int numBytes, unsigned int tag) +{ + m_dmaPending = true; + m_dmaTag = tag; + cellDmaLargePut(m_backBuffer, ea, numBytes, tag, 0, 0); +} + +template +T * +DoubleBuffer::getFront() +{ + return m_frontBuffer; +} + +template +T * +DoubleBuffer::getBack() +{ + return m_backBuffer; +} + +template +T * +DoubleBuffer::swapBuffers() +{ + if (m_dmaPending) + { + cellDmaWaitTagStatusAll(1< //for btAssert +//Disabling memcpy sometimes helps debugging DMA + +#define USE_MEMCPY 1 +#ifdef USE_MEMCPY + +#endif + + +void* cellDmaLargeGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid) +{ + +#if defined (__SPU__) || defined (USE_LIBSPE2) + cellDmaLargeGet(ls,ea,size,tag,tid,rid); + return ls; +#else + return (void*)(ppu_address_t)ea; +#endif +} + +void* cellDmaSmallGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid) +{ +#if defined (__SPU__) || defined (USE_LIBSPE2) + mfc_get(ls,ea,size,tag,0,0); + return ls; +#else + return (void*)(ppu_address_t)ea; +#endif +} + + + + +void* cellDmaGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid) +{ +#if defined (__SPU__) || defined (USE_LIBSPE2) + cellDmaGet(ls,ea,size,tag,tid,rid); + return ls; +#else + return (void*)(ppu_address_t)ea; +#endif +} + + +///this unalignedDma should not be frequently used, only for small data. It handles alignment and performs check on size (<16 bytes) +int stallingUnalignedDmaSmallGet(void *ls, uint64_t ea, uint32_t size) +{ + + btAssert(size<32); + + ATTRIBUTE_ALIGNED16(char tmpBuffer[32]); + + + char* localStore = (char*)ls; + uint32_t i; + + + ///make sure last 4 bits are the same, for cellDmaSmallGet + uint32_t last4BitsOffset = ea & 0x0f; + char* tmpTarget = tmpBuffer + last4BitsOffset; + +#if defined (__SPU__) || defined (USE_LIBSPE2) + + int remainingSize = size; + +//#define FORCE_cellDmaUnalignedGet 1 +#ifdef FORCE_cellDmaUnalignedGet + cellDmaUnalignedGet(tmpTarget,ea,size,DMA_TAG(1),0,0); +#else + char* remainingTmpTarget = tmpTarget; + uint64_t remainingEa = ea; + + while (remainingSize) + { + switch (remainingSize) + { + case 1: + case 2: + case 4: + case 8: + case 16: + { + mfc_get(remainingTmpTarget,remainingEa,remainingSize,DMA_TAG(1),0,0); + remainingSize=0; + break; + } + default: + { + //spu_printf("unaligned DMA with non-natural size:%d\n",remainingSize); + int actualSize = 0; + + if (remainingSize > 16) + actualSize = 16; + else + if (remainingSize >8) + actualSize=8; + else + if (remainingSize >4) + actualSize=4; + else + if (remainingSize >2) + actualSize=2; + mfc_get(remainingTmpTarget,remainingEa,actualSize,DMA_TAG(1),0,0); + remainingSize-=actualSize; + remainingTmpTarget+=actualSize; + remainingEa += actualSize; + } + } + } +#endif//FORCE_cellDmaUnalignedGet + +#else + char* mainMem = (char*)ea; + //copy into final destination +#ifdef USE_MEMCPY + + memcpy(tmpTarget,mainMem,size); +#else + for ( i=0;i +#include + +#define DMA_TAG(xfer) (xfer + 1) +#define DMA_MASK(xfer) (1 << DMA_TAG(xfer)) + +#else // !USE_LIBSPE2 + +#define DMA_TAG(xfer) (xfer + 1) +#define DMA_MASK(xfer) (1 << DMA_TAG(xfer)) + +#include + +#define DEBUG_DMA +#ifdef DEBUG_DMA +#define dUASSERT(a,b) if (!(a)) { printf(b);} +#define uintsize ppu_address_t + +#define cellDmaLargeGet(ls, ea, size, tag, tid, rid) if ( (((uintsize)ls%16) != ((uintsize)ea%16)) || ((((uintsize)ea%16) || ((uintsize)ls%16)) && (( ((uintsize)ls%16) != ((uintsize)size%16) ) || ( ((uintsize)ea%16) != ((uintsize)size%16) ) ) ) || ( ((uintsize)size%16) && ((uintsize)size!=1) && ((uintsize)size!=2) && ((uintsize)size!=4) && ((uintsize)size!=8) ) || (size >= 16384) || !(uintsize)ls || !(uintsize)ea) { \ + dUASSERT( (((uintsize)ea % 16) == 0) || (size < 16), "XDR Address not aligned: "); \ + dUASSERT( (((uintsize)ls % 16) == 0) || (size < 16), "LS Address not aligned: "); \ + dUASSERT( ((((uintsize)ls % size) == 0) && (((uintsize)ea % size) == 0)) || (size > 16), "Not naturally aligned: "); \ + dUASSERT((size == 1) || (size == 2) || (size == 4) || (size == 8) || ((size % 16) == 0), "size not a multiple of 16byte: "); \ + dUASSERT(size < 16384, "size too big: "); \ + dUASSERT( ((uintsize)ea%16)==((uintsize)ls%16), "wrong Quadword alignment of LS and EA: "); \ + dUASSERT(ea != 0, "Nullpointer EA: "); dUASSERT(ls != 0, "Nullpointer LS: ");\ + printf("GET %s:%d from: 0x%x, to: 0x%x - %d bytes\n", __FILE__, __LINE__, (unsigned int)ea,(unsigned int)ls,(unsigned int)size);\ + } \ + mfc_get(ls, ea, size, tag, tid, rid) +#define cellDmaGet(ls, ea, size, tag, tid, rid) if ( (((uintsize)ls%16) != ((uintsize)ea%16)) || ((((uintsize)ea%16) || ((uintsize)ls%16)) && (( ((uintsize)ls%16) != ((uintsize)size%16) ) || ( ((uintsize)ea%16) != ((uintsize)size%16) ) ) ) || ( ((uintsize)size%16) && ((uintsize)size!=1) && ((uintsize)size!=2) && ((uintsize)size!=4) && ((uintsize)size!=8) ) || (size >= 16384) || !(uintsize)ls || !(uintsize)ea) { \ + dUASSERT( (((uintsize)ea % 16) == 0) || (size < 16), "XDR Address not aligned: "); \ + dUASSERT( (((uintsize)ls % 16) == 0) || (size < 16), "LS Address not aligned: "); \ + dUASSERT( ((((uintsize)ls % size) == 0) && (((uintsize)ea % size) == 0)) || (size > 16), "Not naturally aligned: "); \ + dUASSERT((size == 1) || (size == 2) || (size == 4) || (size == 8) || ((size % 16) == 0), "size not a multiple of 16byte: "); \ + dUASSERT(size < 16384, "size too big: "); \ + dUASSERT( ((uintsize)ea%16)==((uintsize)ls%16), "wrong Quadword alignment of LS and EA: "); \ + dUASSERT(ea != 0, "Nullpointer EA: "); dUASSERT(ls != 0, "Nullpointer LS: ");\ + printf("GET %s:%d from: 0x%x, to: 0x%x - %d bytes\n", __FILE__, __LINE__, (unsigned int)ea,(unsigned int)ls,(unsigned int)size);\ + } \ + mfc_get(ls, ea, size, tag, tid, rid) +#define cellDmaLargePut(ls, ea, size, tag, tid, rid) if ( (((uintsize)ls%16) != ((uintsize)ea%16)) || ((((uintsize)ea%16) || ((uintsize)ls%16)) && (( ((uintsize)ls%16) != ((uintsize)size%16) ) || ( ((uintsize)ea%16) != ((uintsize)size%16) ) ) ) || ( ((uintsize)size%16) && ((uintsize)size!=1) && ((uintsize)size!=2) && ((uintsize)size!=4) && ((uintsize)size!=8) ) || (size >= 16384) || !(uintsize)ls || !(uintsize)ea) { \ + dUASSERT( (((uintsize)ea % 16) == 0) || (size < 16), "XDR Address not aligned: "); \ + dUASSERT( (((uintsize)ls % 16) == 0) || (size < 16), "LS Address not aligned: "); \ + dUASSERT( ((((uintsize)ls % size) == 0) && (((uintsize)ea % size) == 0)) || (size > 16), "Not naturally aligned: "); \ + dUASSERT((size == 1) || (size == 2) || (size == 4) || (size == 8) || ((size % 16) == 0), "size not a multiple of 16byte: "); \ + dUASSERT(size < 16384, "size too big: "); \ + dUASSERT( ((uintsize)ea%16)==((uintsize)ls%16), "wrong Quadword alignment of LS and EA: "); \ + dUASSERT(ea != 0, "Nullpointer EA: "); dUASSERT(ls != 0, "Nullpointer LS: ");\ + printf("PUT %s:%d from: 0x%x, to: 0x%x - %d bytes\n", __FILE__, __LINE__, (unsigned int)ls,(unsigned int)ea,(unsigned int)size); \ + } \ + mfc_put(ls, ea, size, tag, tid, rid) +#define cellDmaSmallGet(ls, ea, size, tag, tid, rid) if ( (((uintsize)ls%16) != ((uintsize)ea%16)) || ((((uintsize)ea%16) || ((uintsize)ls%16)) && (( ((uintsize)ls%16) != ((uintsize)size%16) ) || ( ((uintsize)ea%16) != ((uintsize)size%16) ) ) ) || ( ((uintsize)size%16) && ((uintsize)size!=1) && ((uintsize)size!=2) && ((uintsize)size!=4) && ((uintsize)size!=8) ) || (size >= 16384) || !(uintsize)ls || !(uintsize)ea) { \ + dUASSERT( (((uintsize)ea % 16) == 0) || (size < 16), "XDR Address not aligned: "); \ + dUASSERT( (((uintsize)ls % 16) == 0) || (size < 16), "LS Address not aligned: "); \ + dUASSERT( ((((uintsize)ls % size) == 0) && (((uintsize)ea % size) == 0)) || (size > 16), "Not naturally aligned: "); \ + dUASSERT((size == 1) || (size == 2) || (size == 4) || (size == 8) || ((size % 16) == 0), "size not a multiple of 16byte: "); \ + dUASSERT(size < 16384, "size too big: "); \ + dUASSERT( ((uintsize)ea%16)==((uintsize)ls%16), "wrong Quadword alignment of LS and EA: "); \ + dUASSERT(ea != 0, "Nullpointer EA: "); dUASSERT(ls != 0, "Nullpointer LS: ");\ + printf("GET %s:%d from: 0x%x, to: 0x%x - %d bytes\n", __FILE__, __LINE__, (unsigned int)ea,(unsigned int)ls,(unsigned int)size);\ + } \ + mfc_get(ls, ea, size, tag, tid, rid) +#define cellDmaWaitTagStatusAll(ignore) mfc_write_tag_mask(ignore) ; mfc_read_tag_status_all() + +#else +#define cellDmaLargeGet(ls, ea, size, tag, tid, rid) mfc_get(ls, ea, size, tag, tid, rid) +#define cellDmaGet(ls, ea, size, tag, tid, rid) mfc_get(ls, ea, size, tag, tid, rid) +#define cellDmaLargePut(ls, ea, size, tag, tid, rid) mfc_put(ls, ea, size, tag, tid, rid) +#define cellDmaSmallGet(ls, ea, size, tag, tid, rid) mfc_get(ls, ea, size, tag, tid, rid) +#define cellDmaWaitTagStatusAll(ignore) mfc_write_tag_mask(ignore) ; mfc_read_tag_status_all() +#endif // DEBUG_DMA + + + + + + + + +#endif // USE_LIBSPE2 +#else // !__SPU__ +//Simulate DMA using memcpy or direct access on non-CELL platforms that don't have DMAs and SPUs (Win32, Mac, Linux etc) +//Potential to add networked simulation using this interface + +#define DMA_TAG(a) (a) +#define DMA_MASK(a) (a) + + /// cellDmaLargeGet Win32 replacements for Cell DMA to allow simulating most of the SPU code (just memcpy) + int cellDmaLargeGet(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); + int cellDmaGet(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); + /// cellDmaLargePut Win32 replacements for Cell DMA to allow simulating most of the SPU code (just memcpy) + int cellDmaLargePut(const void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); + /// cellDmaWaitTagStatusAll Win32 replacements for Cell DMA to allow simulating most of the SPU code (just memcpy) + void cellDmaWaitTagStatusAll(int ignore); + + +#endif //__CELLOS_LV2__ + +///stallingUnalignedDmaSmallGet internally uses DMA_TAG(1) +int stallingUnalignedDmaSmallGet(void *ls, uint64_t ea, uint32_t size); + + +void* cellDmaLargeGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); +void* cellDmaGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); +void* cellDmaSmallGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); + + +#endif //BT_FAKE_DMA_H diff --git a/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp b/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp new file mode 100644 index 0000000..1a76be0 --- /dev/null +++ b/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp @@ -0,0 +1,276 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +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 "SpuGatheringCollisionDispatcher.h" +#include "SpuCollisionTaskProcess.h" + + +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" +#include "SpuContactManifoldCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "LinearMath/btQuickprof.h" +#include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h" + + + + + +SpuGatheringCollisionDispatcher::SpuGatheringCollisionDispatcher(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks,btCollisionConfiguration* collisionConfiguration) +:btCollisionDispatcher(collisionConfiguration), +m_spuCollisionTaskProcess(0), +m_threadInterface(threadInterface), +m_maxNumOutstandingTasks(maxNumOutstandingTasks) +{ + +} + + +bool SpuGatheringCollisionDispatcher::supportsDispatchPairOnSpu(int proxyType0,int proxyType1) +{ + bool supported0 = ( + (proxyType0 == BOX_SHAPE_PROXYTYPE) || + (proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) || + (proxyType0 == SPHERE_SHAPE_PROXYTYPE) || + (proxyType0 == CAPSULE_SHAPE_PROXYTYPE) || + (proxyType0 == CYLINDER_SHAPE_PROXYTYPE) || +// (proxyType0 == CONE_SHAPE_PROXYTYPE) || + (proxyType0 == TRIANGLE_MESH_SHAPE_PROXYTYPE) || + (proxyType0 == CONVEX_HULL_SHAPE_PROXYTYPE)|| + (proxyType0 == STATIC_PLANE_PROXYTYPE)|| + (proxyType0 == COMPOUND_SHAPE_PROXYTYPE) + ); + + bool supported1 = ( + (proxyType1 == BOX_SHAPE_PROXYTYPE) || + (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE) || + (proxyType1 == SPHERE_SHAPE_PROXYTYPE) || + (proxyType1 == CAPSULE_SHAPE_PROXYTYPE) || + (proxyType1 == CYLINDER_SHAPE_PROXYTYPE) || +// (proxyType1 == CONE_SHAPE_PROXYTYPE) || + (proxyType1 == TRIANGLE_MESH_SHAPE_PROXYTYPE) || + (proxyType1 == CONVEX_HULL_SHAPE_PROXYTYPE) || + (proxyType1 == STATIC_PLANE_PROXYTYPE) || + (proxyType1 == COMPOUND_SHAPE_PROXYTYPE) + ); + + + return supported0 && supported1; +} + + + +SpuGatheringCollisionDispatcher::~SpuGatheringCollisionDispatcher() +{ + if (m_spuCollisionTaskProcess) + delete m_spuCollisionTaskProcess; + +} + +#include "stdio.h" + + + +///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc) +///this is useful for the collision dispatcher. +class btSpuCollisionPairCallback : public btOverlapCallback +{ + const btDispatcherInfo& m_dispatchInfo; + SpuGatheringCollisionDispatcher* m_dispatcher; + +public: + + btSpuCollisionPairCallback(const btDispatcherInfo& dispatchInfo, SpuGatheringCollisionDispatcher* dispatcher) + :m_dispatchInfo(dispatchInfo), + m_dispatcher(dispatcher) + { + } + + virtual bool processOverlap(btBroadphasePair& collisionPair) + { + + + //PPU version + //(*m_dispatcher->getNearCallback())(collisionPair,*m_dispatcher,m_dispatchInfo); + + //only support discrete collision detection for now, we could fallback on PPU/unoptimized version for TOI/CCD + btAssert(m_dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE); + + //by default, Bullet will use this near callback + { + ///userInfo is used to determine if the SPU has to handle this case or not (skip PPU tasks) + if (!collisionPair.m_internalTmpValue) + { + collisionPair.m_internalTmpValue = 1; + } + if (!collisionPair.m_algorithm) + { + btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; + + btCollisionAlgorithmConstructionInfo ci; + ci.m_dispatcher1 = m_dispatcher; + ci.m_manifold = 0; + + if (m_dispatcher->needsCollision(colObj0,colObj1)) + { + int proxyType0 = colObj0->getCollisionShape()->getShapeType(); + int proxyType1 = colObj1->getCollisionShape()->getShapeType(); + bool supportsSpuDispatch = m_dispatcher->supportsDispatchPairOnSpu(proxyType0,proxyType1) + && ((colObj0->getCollisionFlags() & btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) == 0) + && ((colObj1->getCollisionFlags() & btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) == 0); + + if (proxyType0 == COMPOUND_SHAPE_PROXYTYPE) + { + btCompoundShape* compound = (btCompoundShape*)colObj0->getCollisionShape(); + if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES) + { + //printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES); + supportsSpuDispatch = false; + } + } + + if (proxyType1 == COMPOUND_SHAPE_PROXYTYPE) + { + btCompoundShape* compound = (btCompoundShape*)colObj1->getCollisionShape(); + if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES) + { + //printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES); + supportsSpuDispatch = false; + } + } + + if (supportsSpuDispatch) + { + + int so = sizeof(SpuContactManifoldCollisionAlgorithm); +#ifdef ALLOCATE_SEPARATELY + void* mem = btAlignedAlloc(so,16);//m_dispatcher->allocateCollisionAlgorithm(so); +#else + void* mem = m_dispatcher->allocateCollisionAlgorithm(so); +#endif + collisionPair.m_algorithm = new(mem) SpuContactManifoldCollisionAlgorithm(ci,colObj0,colObj1); + collisionPair.m_internalTmpValue = 2; + } else + { + collisionPair.m_algorithm = m_dispatcher->findAlgorithm(colObj0,colObj1); + collisionPair.m_internalTmpValue = 3; + } + } + } + } + return false; + } +}; + +void SpuGatheringCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher) +{ + + if (dispatchInfo.m_enableSPU) + { + m_maxNumOutstandingTasks = m_threadInterface->getNumTasks(); + + { + BT_PROFILE("processAllOverlappingPairs"); + + if (!m_spuCollisionTaskProcess) + m_spuCollisionTaskProcess = new SpuCollisionTaskProcess(m_threadInterface,m_maxNumOutstandingTasks); + + m_spuCollisionTaskProcess->setNumTasks(m_maxNumOutstandingTasks); + // printf("m_maxNumOutstandingTasks =%d\n",m_maxNumOutstandingTasks); + + m_spuCollisionTaskProcess->initialize2(dispatchInfo.m_useEpa); + + + ///modified version of btCollisionDispatcher::dispatchAllCollisionPairs: + { + btSpuCollisionPairCallback collisionCallback(dispatchInfo,this); + + pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher); + } + } + + //send one big batch + int numTotalPairs = pairCache->getNumOverlappingPairs(); + if (numTotalPairs) + { + btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr(); + int i; + { + int pairRange = SPU_BATCHSIZE_BROADPHASE_PAIRS; + if (numTotalPairs < (m_spuCollisionTaskProcess->getNumTasks()*SPU_BATCHSIZE_BROADPHASE_PAIRS)) + { + pairRange = (numTotalPairs/m_spuCollisionTaskProcess->getNumTasks())+1; + } + + BT_PROFILE("addWorkToTask"); + for (i=0;iaddWorkToTask(pairPtr,i,endIndex); + i = endIndex; + } + } + { + BT_PROFILE("PPU fallback"); + //handle PPU fallback pairs + for (i=0;im_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; + + if (dispatcher->needsCollision(colObj0,colObj1)) + { + btManifoldResult contactPointResult(colObj0,colObj1); + + if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) + { + //discrete collision detection query + collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult); + } else + { + //continuous collision detection query, time of impact (toi) + btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult); + if (dispatchInfo.m_timeOfImpact > toi) + dispatchInfo.m_timeOfImpact = toi; + + } + } + } + } + } + } + } + { + BT_PROFILE("flush2"); + //make sure all SPU work is done + m_spuCollisionTaskProcess->flush2(); + } + + } else + { + ///PPU fallback + ///!Need to make sure to clear all 'algorithms' when switching between SPU and PPU + btCollisionDispatcher::dispatchAllCollisionPairs(pairCache,dispatchInfo,dispatcher); + } +} diff --git a/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h b/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h new file mode 100644 index 0000000..f8bc7da --- /dev/null +++ b/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h @@ -0,0 +1,72 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BT_SPU_GATHERING_COLLISION__DISPATCHER_H +#define BT_SPU_GATHERING_COLLISION__DISPATCHER_H + +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" + + +///Tuning value to optimized SPU utilization +///Too small value means Task overhead is large compared to computation (too fine granularity) +///Too big value might render some SPUs are idle, while a few other SPUs are doing all work. +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 8 +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 16 +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 64 +#define SPU_BATCHSIZE_BROADPHASE_PAIRS 128 +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 256 +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 512 +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 1024 + + + +class SpuCollisionTaskProcess; + +///SpuGatheringCollisionDispatcher can use SPU to gather and calculate collision detection +///Time of Impact, Closest Points and Penetration Depth. +class SpuGatheringCollisionDispatcher : public btCollisionDispatcher +{ + + SpuCollisionTaskProcess* m_spuCollisionTaskProcess; + +protected: + + class btThreadSupportInterface* m_threadInterface; + + unsigned int m_maxNumOutstandingTasks; + + +public: + + //can be used by SPU collision algorithms + SpuCollisionTaskProcess* getSpuCollisionTaskProcess() + { + return m_spuCollisionTaskProcess; + } + + SpuGatheringCollisionDispatcher (class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks,btCollisionConfiguration* collisionConfiguration); + + virtual ~SpuGatheringCollisionDispatcher(); + + bool supportsDispatchPairOnSpu(int proxyType0,int proxyType1); + + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ; + +}; + + + +#endif //BT_SPU_GATHERING_COLLISION__DISPATCHER_H + + diff --git a/src/BulletMultiThreaded/SpuLibspe2Support.cpp b/src/BulletMultiThreaded/SpuLibspe2Support.cpp new file mode 100644 index 0000000..a312450 --- /dev/null +++ b/src/BulletMultiThreaded/SpuLibspe2Support.cpp @@ -0,0 +1,257 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +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. +*/ + +#ifdef USE_LIBSPE2 + +#include "SpuLibspe2Support.h" + + + + +//SpuLibspe2Support helps to initialize/shutdown libspe2, start/stop SPU tasks and communication +///Setup and initialize SPU/CELL/Libspe2 +SpuLibspe2Support::SpuLibspe2Support(spe_program_handle_t *speprog, int numThreads) +{ + this->program = speprog; + this->numThreads = ((numThreads <= spe_cpu_info_get(SPE_COUNT_PHYSICAL_SPES, -1)) ? numThreads : spe_cpu_info_get(SPE_COUNT_PHYSICAL_SPES, -1)); +} + +///cleanup/shutdown Libspe2 +SpuLibspe2Support::~SpuLibspe2Support() +{ + + stopSPU(); +} + + + +///send messages to SPUs +void SpuLibspe2Support::sendRequest(uint32_t uiCommand, uint32_t uiArgument0, uint32_t uiArgument1) +{ + spe_context_ptr_t context; + + switch (uiCommand) + { + case CMD_SAMPLE_TASK_COMMAND: + { + //get taskdescription + SpuSampleTaskDesc* taskDesc = (SpuSampleTaskDesc*) uiArgument0; + + btAssert(taskDesc->m_taskIdm_taskId]; + + //set data for spuStatus + spuStatus.m_commandId = uiCommand; + spuStatus.m_status = Spu_Status_Occupied; //set SPU as "occupied" + spuStatus.m_taskDesc.p = taskDesc; + + //get context + context = data[taskDesc->m_taskId].context; + + + taskDesc->m_mainMemoryPtr = reinterpret_cast (spuStatus.m_lsMemory.p); + + + break; + } + case CMD_GATHER_AND_PROCESS_PAIRLIST: + { + //get taskdescription + SpuGatherAndProcessPairsTaskDesc* taskDesc = (SpuGatherAndProcessPairsTaskDesc*) uiArgument0; + + btAssert(taskDesc->taskIdtaskId]; + + //set data for spuStatus + spuStatus.m_commandId = uiCommand; + spuStatus.m_status = Spu_Status_Occupied; //set SPU as "occupied" + spuStatus.m_taskDesc.p = taskDesc; + + //get context + context = data[taskDesc->taskId].context; + + + taskDesc->m_lsMemory = (CollisionTask_LocalStoreMemory*)spuStatus.m_lsMemory.p; + + break; + } + default: + { + ///not implemented + btAssert(0); + } + + }; + + + //write taskdescription in mailbox + unsigned int event = Spu_Mailbox_Event_Task; + spe_in_mbox_write(context, &event, 1, SPE_MBOX_ANY_NONBLOCKING); + +} + +///check for messages from SPUs +void SpuLibspe2Support::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) +{ + ///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response + + ///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback' + + btAssert(m_activeSpuStatus.size()); + + + int last = -1; + + //find an active spu/thread + while(last < 0) + { + for (int i=0;i=0); + + + + *puiArgument0 = spuStatus.m_taskId; + *puiArgument1 = spuStatus.m_status; + + +} + + +void SpuLibspe2Support::startSPU() +{ + this->internal_startSPU(); +} + + + +///start the spus group (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) +void SpuLibspe2Support::internal_startSPU() +{ + m_activeSpuStatus.resize(numThreads); + + + for (int i=0; i < numThreads; i++) + { + + if(data[i].context == NULL) + { + + /* Create context */ + if ((data[i].context = spe_context_create(0, NULL)) == NULL) + { + perror ("Failed creating context"); + exit(1); + } + + /* Load program into context */ + if(spe_program_load(data[i].context, this->program)) + { + perror ("Failed loading program"); + exit(1); + } + + m_activeSpuStatus[i].m_status = Spu_Status_Startup; + m_activeSpuStatus[i].m_taskId = i; + m_activeSpuStatus[i].m_commandId = 0; + m_activeSpuStatus[i].m_lsMemory.p = NULL; + + + data[i].entry = SPE_DEFAULT_ENTRY; + data[i].flags = 0; + data[i].argp.p = &m_activeSpuStatus[i]; + data[i].envp.p = NULL; + + /* Create thread for each SPE context */ + if (pthread_create(&data[i].pthread, NULL, &ppu_pthread_function, &(data[i]) )) + { + perror ("Failed creating thread"); + exit(1); + } + /* + else + { + printf("started thread %d\n",i); + }*/ + } + } + + + for (int i=0; i < numThreads; i++) + { + if(data[i].context != NULL) + { + while( m_activeSpuStatus[i].m_status == Spu_Status_Startup) + { + // wait for spu to set up + sched_yield(); + } + printf("Spu %d is ready\n", i); + } + } +} + +///tell the task scheduler we are done with the SPU tasks +void SpuLibspe2Support::stopSPU() +{ + // wait for all threads to finish + int i; + for ( i = 0; i < this->numThreads; i++ ) + { + + unsigned int event = Spu_Mailbox_Event_Shutdown; + spe_context_ptr_t context = data[i].context; + spe_in_mbox_write(context, &event, 1, SPE_MBOX_ALL_BLOCKING); + pthread_join (data[i].pthread, NULL); + + } + // close SPE program + spe_image_close(program); + // destroy SPE contexts + for ( i = 0; i < this->numThreads; i++ ) + { + if(data[i].context != NULL) + { + spe_context_destroy (data[i].context); + } + } + + m_activeSpuStatus.clear(); + +} + + + +#endif //USE_LIBSPE2 + diff --git a/src/BulletMultiThreaded/SpuLibspe2Support.h b/src/BulletMultiThreaded/SpuLibspe2Support.h new file mode 100644 index 0000000..37a5e79 --- /dev/null +++ b/src/BulletMultiThreaded/SpuLibspe2Support.h @@ -0,0 +1,180 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_SPU_LIBSPE2_SUPPORT_H +#define BT_SPU_LIBSPE2_SUPPORT_H + +#include //for uint32_t etc. + +#ifdef USE_LIBSPE2 + +#include +#include +//#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" +#include "PlatformDefinitions.h" + + +//extern struct SpuGatherAndProcessPairsTaskDesc; + +enum +{ + Spu_Mailbox_Event_Nothing = 0, + Spu_Mailbox_Event_Task = 1, + Spu_Mailbox_Event_Shutdown = 2, + + Spu_Mailbox_Event_ForceDword = 0xFFFFFFFF + +}; + +enum +{ + Spu_Status_Free = 0, + Spu_Status_Occupied = 1, + Spu_Status_Startup = 2, + + Spu_Status_ForceDword = 0xFFFFFFFF + +}; + + +struct btSpuStatus +{ + uint32_t m_taskId; + uint32_t m_commandId; + uint32_t m_status; + + addr64 m_taskDesc; + addr64 m_lsMemory; + +} +__attribute__ ((aligned (128))) +; + + + +#ifndef __SPU__ + +#include "LinearMath/btAlignedObjectArray.h" +#include "SpuCollisionTaskProcess.h" +#include "SpuSampleTaskProcess.h" +#include "btThreadSupportInterface.h" +#include +#include +#include + +#define MAX_SPUS 4 + +typedef struct ppu_pthread_data +{ + spe_context_ptr_t context; + pthread_t pthread; + unsigned int entry; + unsigned int flags; + addr64 argp; + addr64 envp; + spe_stop_info_t stopinfo; +} ppu_pthread_data_t; + + +static void *ppu_pthread_function(void *arg) +{ + ppu_pthread_data_t * datap = (ppu_pthread_data_t *)arg; + /* + int rc; + do + {*/ + spe_context_run(datap->context, &datap->entry, datap->flags, datap->argp.p, datap->envp.p, &datap->stopinfo); + if (datap->stopinfo.stop_reason == SPE_EXIT) + { + if (datap->stopinfo.result.spe_exit_code != 0) + { + perror("FAILED: SPE returned a non-zero exit status: \n"); + exit(1); + } + } + else + { + perror("FAILED: SPE abnormally terminated\n"); + exit(1); + } + + + //} while (rc > 0); // loop until exit or error, and while any stop & signal + pthread_exit(NULL); +} + + + + + + +///SpuLibspe2Support helps to initialize/shutdown libspe2, start/stop SPU tasks and communication +class SpuLibspe2Support : public btThreadSupportInterface +{ + + btAlignedObjectArray m_activeSpuStatus; + +public: + //Setup and initialize SPU/CELL/Libspe2 + SpuLibspe2Support(spe_program_handle_t *speprog,int numThreads); + + // SPE program handle ptr. + spe_program_handle_t *program; + + // SPE program data + ppu_pthread_data_t data[MAX_SPUS]; + + //cleanup/shutdown Libspe2 + ~SpuLibspe2Support(); + + ///send messages to SPUs + void sendRequest(uint32_t uiCommand, uint32_t uiArgument0, uint32_t uiArgument1=0); + + //check for messages from SPUs + void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1); + + //start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) + virtual void startSPU(); + + //tell the task scheduler we are done with the SPU tasks + virtual void stopSPU(); + + virtual void setNumTasks(int numTasks) + { + //changing the number of tasks after initialization is not implemented (yet) + } + +private: + + ///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) + void internal_startSPU(); + + + + + int numThreads; + +}; + +#endif // NOT __SPU__ + +#endif //USE_LIBSPE2 + +#endif //BT_SPU_LIBSPE2_SUPPORT_H + + + + diff --git a/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h new file mode 100644 index 0000000..e517961 --- /dev/null +++ b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h @@ -0,0 +1,167 @@ +/* + Copyright (C) 2006, 2008 Sony Computer Entertainment Inc. + All rights reserved. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + +#ifndef __BOX_H__ +#define __BOX_H__ + + +#ifndef PE_REF +#define PE_REF(a) a& +#endif + +#include + + +#include "../PlatformDefinitions.h" + + + + +enum FeatureType { F, E, V }; + +//---------------------------------------------------------------------------- +// Box +//---------------------------------------------------------------------------- +///The Box is an internal class used by the boxBoxDistance calculation. +class Box +{ +public: + vmVector3 mHalf; + + inline Box() + {} + inline Box(PE_REF(vmVector3) half_); + inline Box(float hx, float hy, float hz); + + inline void Set(PE_REF(vmVector3) half_); + inline void Set(float hx, float hy, float hz); + + inline vmVector3 GetAABB(const vmMatrix3& rotation) const; +}; + +inline +Box::Box(PE_REF(vmVector3) half_) +{ + Set(half_); +} + +inline +Box::Box(float hx, float hy, float hz) +{ + Set(hx, hy, hz); +} + +inline +void +Box::Set(PE_REF(vmVector3) half_) +{ + mHalf = half_; +} + +inline +void +Box::Set(float hx, float hy, float hz) +{ + mHalf = vmVector3(hx, hy, hz); +} + +inline +vmVector3 +Box::GetAABB(const vmMatrix3& rotation) const +{ + return absPerElem(rotation) * mHalf; +} + +//------------------------------------------------------------------------------------------------- +// BoxPoint +//------------------------------------------------------------------------------------------------- + +///The BoxPoint class is an internally used class to contain feature information for boxBoxDistance calculation. +class BoxPoint +{ +public: + BoxPoint() : localPoint(0.0f) {} + + vmPoint3 localPoint; + FeatureType featureType; + int featureIdx; + + inline void setVertexFeature(int plusX, int plusY, int plusZ); + inline void setEdgeFeature(int dim0, int plus0, int dim1, int plus1); + inline void setFaceFeature(int dim, int plus); + + inline void getVertexFeature(int & plusX, int & plusY, int & plusZ) const; + inline void getEdgeFeature(int & dim0, int & plus0, int & dim1, int & plus1) const; + inline void getFaceFeature(int & dim, int & plus) const; +}; + +inline +void +BoxPoint::setVertexFeature(int plusX, int plusY, int plusZ) +{ + featureType = V; + featureIdx = plusX << 2 | plusY << 1 | plusZ; +} + +inline +void +BoxPoint::setEdgeFeature(int dim0, int plus0, int dim1, int plus1) +{ + featureType = E; + + if (dim0 > dim1) { + featureIdx = plus1 << 5 | dim1 << 3 | plus0 << 2 | dim0; + } else { + featureIdx = plus0 << 5 | dim0 << 3 | plus1 << 2 | dim1; + } +} + +inline +void +BoxPoint::setFaceFeature(int dim, int plus) +{ + featureType = F; + featureIdx = plus << 2 | dim; +} + +inline +void +BoxPoint::getVertexFeature(int & plusX, int & plusY, int & plusZ) const +{ + plusX = featureIdx >> 2; + plusY = featureIdx >> 1 & 1; + plusZ = featureIdx & 1; +} + +inline +void +BoxPoint::getEdgeFeature(int & dim0, int & plus0, int & dim1, int & plus1) const +{ + plus0 = featureIdx >> 5; + dim0 = featureIdx >> 3 & 3; + plus1 = featureIdx >> 2 & 1; + dim1 = featureIdx & 3; +} + +inline +void +BoxPoint::getFaceFeature(int & dim, int & plus) const +{ + plus = featureIdx >> 2; + dim = featureIdx & 3; +} + +#endif /* __BOX_H__ */ diff --git a/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp new file mode 100644 index 0000000..dfcd842 --- /dev/null +++ b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp @@ -0,0 +1,302 @@ +/* +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 "SpuCollisionShapes.h" + +///not supported on IBM SDK, until we fix the alignment of btVector3 +#if defined (__CELLOS_LV2__) && defined (__SPU__) +#include +static inline vec_float4 vec_dot3( vec_float4 vec0, vec_float4 vec1 ) +{ + vec_float4 result; + result = spu_mul( vec0, vec1 ); + result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result ); + return spu_madd( spu_rlqwbyte( vec0, 8 ), spu_rlqwbyte( vec1, 8 ), result ); +} +#endif //__SPU__ + + +void computeAabb (btVector3& aabbMin, btVector3& aabbMax, btConvexInternalShape* convexShape, ppu_address_t convexShapePtr, int shapeType, const btTransform& xform) +{ + //calculate the aabb, given the types... + switch (shapeType) + { + case CYLINDER_SHAPE_PROXYTYPE: + /* fall through */ + case BOX_SHAPE_PROXYTYPE: + { + btScalar margin=convexShape->getMarginNV(); + btVector3 halfExtents = convexShape->getImplicitShapeDimensions(); + halfExtents += btVector3(margin,margin,margin); + const btTransform& t = xform; + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents)); + + aabbMin = center - extent; + aabbMax = center + extent; + break; + } + case CAPSULE_SHAPE_PROXYTYPE: + { + btScalar margin=convexShape->getMarginNV(); + btVector3 halfExtents = convexShape->getImplicitShapeDimensions(); + //add the radius to y-axis to get full height + btScalar radius = halfExtents[0]; + halfExtents[1] += radius; + halfExtents += btVector3(margin,margin,margin); +#if 0 + int capsuleUpAxis = convexShape->getUpAxis(); + btScalar halfHeight = convexShape->getHalfHeight(); + btScalar radius = convexShape->getRadius(); + halfExtents[capsuleUpAxis] = radius + halfHeight; +#endif + const btTransform& t = xform; + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents)); + + aabbMin = center - extent; + aabbMax = center + extent; + break; + } + case SPHERE_SHAPE_PROXYTYPE: + { + btScalar radius = convexShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX(); + btScalar margin = radius + convexShape->getMarginNV(); + const btTransform& t = xform; + const btVector3& center = t.getOrigin(); + btVector3 extent(margin,margin,margin); + aabbMin = center - extent; + aabbMax = center + extent; + break; + } + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]); + cellDmaGet(&convexHullShape0, convexShapePtr , sizeof(btConvexHullShape), DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + btConvexHullShape* localPtr = (btConvexHullShape*)&convexHullShape0; + const btTransform& t = xform; + btScalar margin = convexShape->getMarginNV(); + localPtr->getNonvirtualAabb(t,aabbMin,aabbMax,margin); + //spu_printf("SPU convex aabbMin=%f,%f,%f=\n",aabbMin.getX(),aabbMin.getY(),aabbMin.getZ()); + //spu_printf("SPU convex aabbMax=%f,%f,%f=\n",aabbMax.getX(),aabbMax.getY(),aabbMax.getZ()); + break; + } + default: + { + // spu_printf("SPU: unsupported shapetype %d in AABB calculation\n"); + } + }; +} + +void dmaBvhShapeData (bvhMeshShape_LocalStoreMemory* bvhMeshShape, btBvhTriangleMeshShape* triMeshShape) +{ + register int dmaSize; + register ppu_address_t dmaPpuAddress2; + + dmaSize = sizeof(btTriangleIndexVertexArray); + dmaPpuAddress2 = reinterpret_cast(triMeshShape->getMeshInterface()); + // spu_printf("trimeshShape->getMeshInterface() == %llx\n",dmaPpuAddress2); +#ifdef __SPU__ + cellDmaGet(&bvhMeshShape->gTriangleMeshInterfaceStorage, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + bvhMeshShape->gTriangleMeshInterfacePtr = &bvhMeshShape->gTriangleMeshInterfaceStorage; +#else + bvhMeshShape->gTriangleMeshInterfacePtr = (btTriangleIndexVertexArray*)cellDmaGetReadOnly(&bvhMeshShape->gTriangleMeshInterfaceStorage, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); +#endif + + //cellDmaWaitTagStatusAll(DMA_MASK(1)); + + ///now DMA over the BVH + + dmaSize = sizeof(btOptimizedBvh); + dmaPpuAddress2 = reinterpret_cast(triMeshShape->getOptimizedBvh()); + //spu_printf("trimeshShape->getOptimizedBvh() == %llx\n",dmaPpuAddress2); + cellDmaGet(&bvhMeshShape->gOptimizedBvh, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0); + //cellDmaWaitTagStatusAll(DMA_MASK(2)); + cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); +} + +void dmaBvhIndexedMesh (btIndexedMesh* IndexMesh, IndexedMeshArray& indexArray, int index, uint32_t dmaTag) +{ + cellDmaGet(IndexMesh, (ppu_address_t)&indexArray[index] , sizeof(btIndexedMesh), DMA_TAG(dmaTag), 0, 0); + +} + +void dmaBvhSubTreeHeaders (btBvhSubtreeInfo* subTreeHeaders, ppu_address_t subTreePtr, int batchSize, uint32_t dmaTag) +{ + cellDmaGet(subTreeHeaders, subTreePtr, batchSize * sizeof(btBvhSubtreeInfo), DMA_TAG(dmaTag), 0, 0); +} + +void dmaBvhSubTreeNodes (btQuantizedBvhNode* nodes, const btBvhSubtreeInfo& subtree, QuantizedNodeArray& nodeArray, int dmaTag) +{ + cellDmaGet(nodes, reinterpret_cast(&nodeArray[subtree.m_rootNodeIndex]) , subtree.m_subtreeSize* sizeof(btQuantizedBvhNode), DMA_TAG(2), 0, 0); +} + +///getShapeTypeSize could easily be optimized, but it is not likely a bottleneck +int getShapeTypeSize(int shapeType) +{ + + + switch (shapeType) + { + case CYLINDER_SHAPE_PROXYTYPE: + { + int shapeSize = sizeof(btCylinderShape); + btAssert(shapeSize < MAX_SHAPE_SIZE); + return shapeSize; + } + case BOX_SHAPE_PROXYTYPE: + { + int shapeSize = sizeof(btBoxShape); + btAssert(shapeSize < MAX_SHAPE_SIZE); + return shapeSize; + } + case SPHERE_SHAPE_PROXYTYPE: + { + int shapeSize = sizeof(btSphereShape); + btAssert(shapeSize < MAX_SHAPE_SIZE); + return shapeSize; + } + case TRIANGLE_MESH_SHAPE_PROXYTYPE: + { + int shapeSize = sizeof(btBvhTriangleMeshShape); + btAssert(shapeSize < MAX_SHAPE_SIZE); + return shapeSize; + } + case CAPSULE_SHAPE_PROXYTYPE: + { + int shapeSize = sizeof(btCapsuleShape); + btAssert(shapeSize < MAX_SHAPE_SIZE); + return shapeSize; + } + + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + int shapeSize = sizeof(btConvexHullShape); + btAssert(shapeSize < MAX_SHAPE_SIZE); + return shapeSize; + } + + case COMPOUND_SHAPE_PROXYTYPE: + { + int shapeSize = sizeof(btCompoundShape); + btAssert(shapeSize < MAX_SHAPE_SIZE); + return shapeSize; + } + case STATIC_PLANE_PROXYTYPE: + { + int shapeSize = sizeof(btStaticPlaneShape); + btAssert(shapeSize < MAX_SHAPE_SIZE); + return shapeSize; + } + + default: + btAssert(0); + //unsupported shapetype, please add here + return 0; + } +} + +void dmaConvexVertexData (SpuConvexPolyhedronVertexData* convexVertexData, btConvexHullShape* convexShapeSPU) +{ + convexVertexData->gNumConvexPoints = convexShapeSPU->getNumPoints(); + if (convexVertexData->gNumConvexPoints>MAX_NUM_SPU_CONVEX_POINTS) + { + btAssert(0); + // spu_printf("SPU: Error: MAX_NUM_SPU_CONVEX_POINTS(%d) exceeded: %d\n",MAX_NUM_SPU_CONVEX_POINTS,convexVertexData->gNumConvexPoints); + return; + } + + register int dmaSize = convexVertexData->gNumConvexPoints*sizeof(btVector3); + ppu_address_t pointsPPU = (ppu_address_t) convexShapeSPU->getUnscaledPoints(); + cellDmaGet(&convexVertexData->g_convexPointBuffer[0], pointsPPU , dmaSize, DMA_TAG(2), 0, 0); +} + +void dmaCollisionShape (void* collisionShapeLocation, ppu_address_t collisionShapePtr, uint32_t dmaTag, int shapeType) +{ + register int dmaSize = getShapeTypeSize(shapeType); + cellDmaGet(collisionShapeLocation, collisionShapePtr , dmaSize, DMA_TAG(dmaTag), 0, 0); + //cellDmaGetReadOnly(collisionShapeLocation, collisionShapePtr , dmaSize, DMA_TAG(dmaTag), 0, 0); + //cellDmaWaitTagStatusAll(DMA_MASK(dmaTag)); +} + +void dmaCompoundShapeInfo (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag) +{ + register int dmaSize; + register ppu_address_t dmaPpuAddress2; + int childShapeCount = spuCompoundShape->getNumChildShapes(); + dmaSize = childShapeCount * sizeof(btCompoundShapeChild); + dmaPpuAddress2 = (ppu_address_t)spuCompoundShape->getChildList(); + cellDmaGet(&compoundShapeLocation->gSubshapes[0], dmaPpuAddress2, dmaSize, DMA_TAG(dmaTag), 0, 0); +} + +void dmaCompoundSubShapes (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag) +{ + int childShapeCount = spuCompoundShape->getNumChildShapes(); + int i; + // DMA all the subshapes + for ( i = 0; i < childShapeCount; ++i) + { + btCompoundShapeChild& childShape = compoundShapeLocation->gSubshapes[i]; + dmaCollisionShape (&compoundShapeLocation->gSubshapeShape[i],(ppu_address_t)childShape.m_childShape, dmaTag, childShape.m_childShapeType); + } +} + + +void spuWalkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,const btQuantizedBvhNode* rootNode,int startNodeIndex,int endNodeIndex) +{ + + int curIndex = startNodeIndex; + int walkIterations = 0; +#ifdef BT_DEBUG + int subTreeSize = endNodeIndex - startNodeIndex; +#endif + + int escapeIndex; + + unsigned int aabbOverlap, isLeafNode; + + while (curIndex < endNodeIndex) + { + //catch bugs in tree data + btAssert (walkIterations < subTreeSize); + + walkIterations++; + aabbOverlap = spuTestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); + isLeafNode = rootNode->isLeafNode(); + + if (isLeafNode && aabbOverlap) + { + //printf("overlap with node %d\n",rootNode->getTriangleIndex()); + nodeCallback->processNode(0,rootNode->getTriangleIndex()); + // spu_printf("SPU: overlap detected with triangleIndex:%d\n",rootNode->getTriangleIndex()); + } + + if (aabbOverlap || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->getEscapeIndex(); + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + +} diff --git a/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h new file mode 100644 index 0000000..aa8a291 --- /dev/null +++ b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h @@ -0,0 +1,128 @@ +/* +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 __SPU_COLLISION_SHAPES_H +#define __SPU_COLLISION_SHAPES_H + +#include "../SpuDoubleBuffer.h" + +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionShapes/btConvexInternalShape.h" +#include "BulletCollision/CollisionShapes/btCylinderShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" + +#include "BulletCollision/CollisionShapes/btOptimizedBvh.h" +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" + +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btConvexHullShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" + +#define MAX_NUM_SPU_CONVEX_POINTS 128 //@fallback to PPU if a btConvexHullShape has more than MAX_NUM_SPU_CONVEX_POINTS points +#define MAX_SPU_COMPOUND_SUBSHAPES 16 //@fallback on PPU if compound has more than MAX_SPU_COMPOUND_SUBSHAPES child shapes +#define MAX_SHAPE_SIZE 256 //@todo: assert on this + +ATTRIBUTE_ALIGNED16(struct) SpuConvexPolyhedronVertexData +{ + void* gSpuConvexShapePtr; + btVector3* gConvexPoints; + int gNumConvexPoints; + int unused; + ATTRIBUTE_ALIGNED16(btVector3 g_convexPointBuffer[MAX_NUM_SPU_CONVEX_POINTS]); +}; + + + +ATTRIBUTE_ALIGNED16(struct) CollisionShape_LocalStoreMemory +{ + ATTRIBUTE_ALIGNED16(char collisionShape[MAX_SHAPE_SIZE]); +}; + +ATTRIBUTE_ALIGNED16(struct) CompoundShape_LocalStoreMemory +{ + // Compound data + + ATTRIBUTE_ALIGNED16(btCompoundShapeChild gSubshapes[MAX_SPU_COMPOUND_SUBSHAPES]); + ATTRIBUTE_ALIGNED16(char gSubshapeShape[MAX_SPU_COMPOUND_SUBSHAPES][MAX_SHAPE_SIZE]); +}; + +ATTRIBUTE_ALIGNED16(struct) bvhMeshShape_LocalStoreMemory +{ + //ATTRIBUTE_ALIGNED16(btOptimizedBvh gOptimizedBvh); + ATTRIBUTE_ALIGNED16(char gOptimizedBvh[sizeof(btOptimizedBvh)+16]); + btOptimizedBvh* getOptimizedBvh() + { + return (btOptimizedBvh*) gOptimizedBvh; + } + + ATTRIBUTE_ALIGNED16(btTriangleIndexVertexArray gTriangleMeshInterfaceStorage); + btTriangleIndexVertexArray* gTriangleMeshInterfacePtr; + ///only a single mesh part for now, we can add support for multiple parts, but quantized trees don't support this at the moment + ATTRIBUTE_ALIGNED16(btIndexedMesh gIndexMesh); + #define MAX_SPU_SUBTREE_HEADERS 32 + //1024 + ATTRIBUTE_ALIGNED16(btBvhSubtreeInfo gSubtreeHeaders[MAX_SPU_SUBTREE_HEADERS]); + ATTRIBUTE_ALIGNED16(btQuantizedBvhNode gSubtreeNodes[MAX_SUBTREE_SIZE_IN_BYTES/sizeof(btQuantizedBvhNode)]); +}; + + +void computeAabb (btVector3& aabbMin, btVector3& aabbMax, btConvexInternalShape* convexShape, ppu_address_t convexShapePtr, int shapeType, const btTransform& xform); +void dmaBvhShapeData (bvhMeshShape_LocalStoreMemory* bvhMeshShape, btBvhTriangleMeshShape* triMeshShape); +void dmaBvhIndexedMesh (btIndexedMesh* IndexMesh, IndexedMeshArray& indexArray, int index, uint32_t dmaTag); +void dmaBvhSubTreeHeaders (btBvhSubtreeInfo* subTreeHeaders, ppu_address_t subTreePtr, int batchSize, uint32_t dmaTag); +void dmaBvhSubTreeNodes (btQuantizedBvhNode* nodes, const btBvhSubtreeInfo& subtree, QuantizedNodeArray& nodeArray, int dmaTag); + +int getShapeTypeSize(int shapeType); +void dmaConvexVertexData (SpuConvexPolyhedronVertexData* convexVertexData, btConvexHullShape* convexShapeSPU); +void dmaCollisionShape (void* collisionShapeLocation, ppu_address_t collisionShapePtr, uint32_t dmaTag, int shapeType); +void dmaCompoundShapeInfo (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag); +void dmaCompoundSubShapes (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag); + + +#define USE_BRANCHFREE_TEST 1 +#ifdef USE_BRANCHFREE_TEST +SIMD_FORCE_INLINE unsigned int spuTestQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) +{ +#if defined(__CELLOS_LV2__) && defined (__SPU__) + vec_ushort8 vecMin = {aabbMin1[0],aabbMin2[0],aabbMin1[2],aabbMin2[2],aabbMin1[1],aabbMin2[1],0,0}; + vec_ushort8 vecMax = {aabbMax2[0],aabbMax1[0],aabbMax2[2],aabbMax1[2],aabbMax2[1],aabbMax1[1],0,0}; + vec_ushort8 isGt = spu_cmpgt(vecMin,vecMax); + return spu_extract(spu_gather(isGt),0)==0; + +#else + return btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0]) + & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2]) + & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])), + 1, 0); +#endif +} +#else + +SIMD_FORCE_INLINE unsigned int spuTestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) +{ + unsigned int overlap = 1; + overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? 0 : overlap; + overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? 0 : overlap; + overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? 0 : overlap; + return overlap; +} +#endif + +void spuWalkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,const btQuantizedBvhNode* rootNode,int startNodeIndex,int endNodeIndex); + +#endif diff --git a/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp new file mode 100644 index 0000000..8584e74 --- /dev/null +++ b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp @@ -0,0 +1,248 @@ +/* +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 "SpuContactResult.h" + +//#define DEBUG_SPU_COLLISION_DETECTION 1 + +#ifdef DEBUG_SPU_COLLISION_DETECTION +#ifndef __SPU__ +#include +#define spu_printf printf +#endif +#endif //DEBUG_SPU_COLLISION_DETECTION + +SpuContactResult::SpuContactResult() +{ + m_manifoldAddress = 0; + m_spuManifold = NULL; + m_RequiresWriteBack = false; +} + + SpuContactResult::~SpuContactResult() +{ + g_manifoldDmaExport.swapBuffers(); +} + + ///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; +inline btScalar calculateCombinedFriction(btScalar friction0,btScalar friction1) +{ + btScalar friction = friction0*friction1; + + const btScalar MAX_FRICTION = btScalar(10.); + + if (friction < -MAX_FRICTION) + friction = -MAX_FRICTION; + if (friction > MAX_FRICTION) + friction = MAX_FRICTION; + return friction; + +} + +inline btScalar calculateCombinedRestitution(btScalar restitution0,btScalar restitution1) +{ + return restitution0*restitution1; +} + + + + void SpuContactResult::setContactInfo(btPersistentManifold* spuManifold, ppu_address_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1, btScalar restitution0,btScalar restitution1, btScalar friction0,btScalar friction1, bool isSwapped) + { + //spu_printf("SpuContactResult::setContactInfo ManifoldAddress: %lu\n", manifoldAddress); + m_rootWorldTransform0 = worldTrans0; + m_rootWorldTransform1 = worldTrans1; + m_manifoldAddress = manifoldAddress; + m_spuManifold = spuManifold; + + m_combinedFriction = calculateCombinedFriction(friction0,friction1); + m_combinedRestitution = calculateCombinedRestitution(restitution0,restitution1); + m_isSwapped = isSwapped; + } + + void SpuContactResult::setShapeIdentifiersA(int partId0,int index0) + { + + } + + void SpuContactResult::setShapeIdentifiersB(int partId1,int index1) + { + + } + + + + ///return true if it requires a dma transfer back +bool ManifoldResultAddContactPoint(const btVector3& normalOnBInWorld, + const btVector3& pointInWorld, + float depth, + btPersistentManifold* manifoldPtr, + btTransform& transA, + btTransform& transB, + btScalar combinedFriction, + btScalar combinedRestitution, + bool isSwapped) +{ + +// float contactTreshold = manifoldPtr->getContactBreakingThreshold(); + + //spu_printf("SPU: add contactpoint, depth:%f, contactTreshold %f, manifoldPtr %llx\n",depth,contactTreshold,manifoldPtr); + +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("SPU: contactTreshold %f\n",contactTreshold); +#endif //DEBUG_SPU_COLLISION_DETECTION + if (depth > manifoldPtr->getContactBreakingThreshold()) + return false; + + //if (depth > manifoldPtr->getContactProcessingThreshold()) + // return false; + + + + btVector3 pointA; + btVector3 localA; + btVector3 localB; + btVector3 normal; + + + if (isSwapped) + { + normal = normalOnBInWorld * -1; + pointA = pointInWorld + normal * depth; + localA = transA.invXform(pointA ); + localB = transB.invXform(pointInWorld); + } + else + { + normal = normalOnBInWorld; + pointA = pointInWorld + normal * depth; + localA = transA.invXform(pointA ); + localB = transB.invXform(pointInWorld); + } + + btManifoldPoint newPt(localA,localB,normal,depth); + newPt.m_positionWorldOnA = pointA; + newPt.m_positionWorldOnB = pointInWorld; + + newPt.m_combinedFriction = combinedFriction; + newPt.m_combinedRestitution = combinedRestitution; + + + int insertIndex = manifoldPtr->getCacheEntry(newPt); + if (insertIndex >= 0) + { + // we need to replace the current contact point, otherwise small errors will accumulate (spheres start rolling etc) + manifoldPtr->replaceContactPoint(newPt,insertIndex); + return true; + + } else + { + + /* + ///@todo: SPU callbacks, either immediate (local on the SPU), or deferred + //User can override friction and/or restitution + if (gContactAddedCallback && + //and if either of the two bodies requires custom material + ((m_body0->m_collisionFlags & btCollisionObject::customMaterialCallback) || + (m_body1->m_collisionFlags & btCollisionObject::customMaterialCallback))) + { + //experimental feature info, for per-triangle material etc. + (*gContactAddedCallback)(newPt,m_body0,m_partId0,m_index0,m_body1,m_partId1,m_index1); + } + */ + + manifoldPtr->addManifoldPoint(newPt); + return true; + + } + return false; + +} + + +void SpuContactResult::writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold) +{ + ///only write back the contact information on SPU. Other platforms avoid copying, and use the data in-place + ///see SpuFakeDma.cpp 'cellDmaLargeGetReadOnly' +#if defined (__SPU__) || defined (USE_LIBSPE2) + memcpy(g_manifoldDmaExport.getFront(),lsManifold,sizeof(btPersistentManifold)); + + g_manifoldDmaExport.swapBuffers(); + ppu_address_t mmAddr = (ppu_address_t)mmManifold; + g_manifoldDmaExport.backBufferDmaPut(mmAddr, sizeof(btPersistentManifold), DMA_TAG(9)); + // Should there be any kind of wait here? What if somebody tries to use this tag again? What if we call this function again really soon? + //no, the swapBuffers does the wait +#endif +} + +void SpuContactResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) +{ +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("*** SpuContactResult::addContactPoint: depth = %f\n",depth); + spu_printf("*** normal = %f,%f,%f\n",normalOnBInWorld.getX(),normalOnBInWorld.getY(),normalOnBInWorld.getZ()); + spu_printf("*** position = %f,%f,%f\n",pointInWorld.getX(),pointInWorld.getY(),pointInWorld.getZ()); +#endif //DEBUG_SPU_COLLISION_DETECTION + + +#ifdef DEBUG_SPU_COLLISION_DETECTION + // int sman = sizeof(rage::phManifold); +// spu_printf("sizeof_manifold = %i\n",sman); +#endif //DEBUG_SPU_COLLISION_DETECTION + + btPersistentManifold* localManifold = m_spuManifold; + + btVector3 normalB(normalOnBInWorld.getX(),normalOnBInWorld.getY(),normalOnBInWorld.getZ()); + btVector3 pointWrld(pointInWorld.getX(),pointInWorld.getY(),pointInWorld.getZ()); + + //process the contact point + const bool retVal = ManifoldResultAddContactPoint(normalB, + pointWrld, + depth, + localManifold, + m_rootWorldTransform0, + m_rootWorldTransform1, + m_combinedFriction, + m_combinedRestitution, + m_isSwapped); + m_RequiresWriteBack = m_RequiresWriteBack || retVal; +} + +void SpuContactResult::flush() +{ + + if (m_spuManifold && m_spuManifold->getNumContacts()) + { + m_spuManifold->refreshContactPoints(m_rootWorldTransform0,m_rootWorldTransform1); + m_RequiresWriteBack = true; + } + + + if (m_RequiresWriteBack) + { +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("SPU: Start SpuContactResult::flush (Put) DMA\n"); + spu_printf("Num contacts:%d\n", m_spuManifold->getNumContacts()); + spu_printf("Manifold address: %llu\n", m_manifoldAddress); +#endif //DEBUG_SPU_COLLISION_DETECTION + // spu_printf("writeDoubleBufferedManifold\n"); + writeDoubleBufferedManifold(m_spuManifold, (btPersistentManifold*)m_manifoldAddress); +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("SPU: Finished (Put) DMA\n"); +#endif //DEBUG_SPU_COLLISION_DETECTION + } + m_spuManifold = NULL; + m_RequiresWriteBack = false; +} + + diff --git a/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h new file mode 100644 index 0000000..394f56d --- /dev/null +++ b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h @@ -0,0 +1,106 @@ +/* +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 SPU_CONTACT_RESULT2_H +#define SPU_CONTACT_RESULT2_H + + +#ifndef _WIN32 +#include +#endif + + + +#include "../SpuDoubleBuffer.h" + + +#include "LinearMath/btTransform.h" + + +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" + +class btCollisionShape; + + +struct SpuCollisionPairInput +{ + ppu_address_t m_collisionShapes[2]; + btCollisionShape* m_spuCollisionShapes[2]; + + ppu_address_t m_persistentManifoldPtr; + btVector3 m_primitiveDimensions0; + btVector3 m_primitiveDimensions1; + int m_shapeType0; + int m_shapeType1; + float m_collisionMargin0; + float m_collisionMargin1; + + btTransform m_worldTransform0; + btTransform m_worldTransform1; + + bool m_isSwapped; + bool m_useEpa; +}; + + +struct SpuClosestPointInput : public btDiscreteCollisionDetectorInterface::ClosestPointInput +{ + struct SpuConvexPolyhedronVertexData* m_convexVertexData[2]; +}; + +///SpuContactResult exports the contact points using double-buffered DMA transfers, only when needed +///So when an existing contact point is duplicated, no transfer/refresh is performed. +class SpuContactResult : public btDiscreteCollisionDetectorInterface::Result +{ + btTransform m_rootWorldTransform0; + btTransform m_rootWorldTransform1; + ppu_address_t m_manifoldAddress; + + btPersistentManifold* m_spuManifold; + bool m_RequiresWriteBack; + btScalar m_combinedFriction; + btScalar m_combinedRestitution; + + bool m_isSwapped; + + DoubleBuffer g_manifoldDmaExport; + + public: + SpuContactResult(); + virtual ~SpuContactResult(); + + btPersistentManifold* GetSpuManifold() const + { + return m_spuManifold; + } + + virtual void setShapeIdentifiersA(int partId0,int index0); + virtual void setShapeIdentifiersB(int partId1,int index1); + + void setContactInfo(btPersistentManifold* spuManifold, ppu_address_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1, btScalar restitution0,btScalar restitution1, btScalar friction0,btScalar friction01, bool isSwapped); + + + void writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold); + + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth); + + void flush(); +}; + + + +#endif //SPU_CONTACT_RESULT2_H + diff --git a/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h new file mode 100644 index 0000000..449f192 --- /dev/null +++ b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h @@ -0,0 +1,51 @@ + +/* +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 SPU_CONVEX_PENETRATION_DEPTH_H +#define SPU_CONVEX_PENETRATION_DEPTH_H + + + +class btStackAlloc; +class btIDebugDraw; +#include "BulletCollision/NarrowphaseCollision/btConvexPenetrationDepthSolver.h" + +#include "LinearMath/btTransform.h" + + +///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation. +class SpuConvexPenetrationDepthSolver : public btConvexPenetrationDepthSolver +{ +public: + + virtual ~SpuConvexPenetrationDepthSolver() {}; + virtual bool calcPenDepth( SpuVoronoiSimplexSolver& simplexSolver, + void* convexA,void* convexB,int shapeTypeA, int shapeTypeB, float marginA, float marginB, + btTransform& transA,const btTransform& transB, + btVector3& v, btVector3& pa, btVector3& pb, + class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc, + struct SpuConvexPolyhedronVertexData* convexVertexDataA, + struct SpuConvexPolyhedronVertexData* convexVertexDataB + ) const = 0; + + +}; + + + +#endif //SPU_CONVEX_PENETRATION_DEPTH_H + diff --git a/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp new file mode 100644 index 0000000..42f5f45 --- /dev/null +++ b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp @@ -0,0 +1,1415 @@ +/* +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 "SpuGatheringCollisionTask.h" + +//#define DEBUG_SPU_COLLISION_DETECTION 1 +#include "../SpuDoubleBuffer.h" + +#include "../SpuCollisionTaskProcess.h" +#include "../SpuGatheringCollisionDispatcher.h" //for SPU_BATCHSIZE_BROADPHASE_PAIRS + +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "../SpuContactManifoldCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "SpuContactResult.h" +#include "BulletCollision/CollisionShapes/btOptimizedBvh.h" +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btConvexPointCloudShape.h" + +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" + +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btConvexHullShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" + +#include "SpuMinkowskiPenetrationDepthSolver.h" +//#include "SpuEpaPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" + + +#include "boxBoxDistance.h" +#include "BulletMultiThreaded/vectormath2bullet.h" +#include "SpuCollisionShapes.h" //definition of SpuConvexPolyhedronVertexData +#include "BulletCollision/CollisionDispatch/btBoxBoxDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" + +#ifdef __SPU__ +///Software caching from the IBM Cell SDK, it reduces 25% SPU time for our test cases +#ifndef USE_LIBSPE2 +//#define USE_SOFTWARE_CACHE 1 +#endif +#endif //__SPU__ + +int gSkippedCol = 0; +int gProcessedCol = 0; + +//////////////////////////////////////////////// +/// software caching +#if USE_SOFTWARE_CACHE +#include +#include +#include +#include +#define SPE_CACHE_NWAY 4 +//#define SPE_CACHE_NSETS 32, 16 +#define SPE_CACHE_NSETS 8 +//#define SPE_CACHELINE_SIZE 512 +#define SPE_CACHELINE_SIZE 128 +#define SPE_CACHE_SET_TAGID(set) 15 +///make sure that spe_cache.h is below those defines! +#include "../Extras/software_cache/cache/include/spe_cache.h" + + +int g_CacheMisses=0; +int g_CacheHits=0; + +#if 0 // Added to allow cache misses and hits to be tracked, change this to 1 to restore unmodified version +#define spe_cache_read(ea) _spe_cache_lookup_xfer_wait_(ea, 0, 1) +#else +#define spe_cache_read(ea) \ +({ \ + int set, idx, line, byte; \ + _spe_cache_nway_lookup_(ea, set, idx); \ + \ + if (btUnlikely(idx < 0)) { \ + ++g_CacheMisses; \ + idx = _spe_cache_miss_(ea, set, -1); \ + spu_writech(22, SPE_CACHE_SET_TAGMASK(set)); \ + spu_mfcstat(MFC_TAG_UPDATE_ALL); \ + } \ + else \ + { \ + ++g_CacheHits; \ + } \ + line = _spe_cacheline_num_(set, idx); \ + byte = _spe_cacheline_byte_offset_(ea); \ + (void *) &spe_cache_mem[line + byte]; \ +}) + +#endif + +#endif // USE_SOFTWARE_CACHE + +bool gUseEpa = false; + +#ifdef USE_SN_TUNER +#include +#endif //USE_SN_TUNER + +#if defined (__SPU__) && !defined (USE_LIBSPE2) +#include +#elif defined (USE_LIBSPE2) +#define spu_printf(a) +#else +#define IGNORE_ALIGNMENT 1 +#include +#include +#define spu_printf printf + +#endif + +//int gNumConvexPoints0=0; + +///Make sure no destructors are called on this memory +struct CollisionTask_LocalStoreMemory +{ + ///This CollisionTask_LocalStoreMemory is mainly used for the SPU version, using explicit DMA + ///Other platforms can use other memory programming models. + + ATTRIBUTE_ALIGNED16(btBroadphasePair gBroadphasePairsBuffer[SPU_BATCHSIZE_BROADPHASE_PAIRS]); + DoubleBuffer g_workUnitTaskBuffers; + ATTRIBUTE_ALIGNED16(char gSpuContactManifoldAlgoBuffer [sizeof(SpuContactManifoldCollisionAlgorithm)+16]); + ATTRIBUTE_ALIGNED16(char gColObj0Buffer [sizeof(btCollisionObject)+16]); + ATTRIBUTE_ALIGNED16(char gColObj1Buffer [sizeof(btCollisionObject)+16]); + ///we reserve 32bit integer indices, even though they might be 16bit + ATTRIBUTE_ALIGNED16(int spuIndices[16]); + btPersistentManifold gPersistentManifoldBuffer; + CollisionShape_LocalStoreMemory gCollisionShapes[2]; + bvhMeshShape_LocalStoreMemory bvhShapeData; + SpuConvexPolyhedronVertexData convexVertexData[2]; + CompoundShape_LocalStoreMemory compoundShapeData[2]; + + ///The following pointers might either point into this local store memory, or to the original/other memory locations. + ///See SpuFakeDma for implementation of cellDmaSmallGetReadOnly. + btCollisionObject* m_lsColObj0Ptr; + btCollisionObject* m_lsColObj1Ptr; + btBroadphasePair* m_pairsPointer; + btPersistentManifold* m_lsManifoldPtr; + SpuContactManifoldCollisionAlgorithm* m_lsCollisionAlgorithmPtr; + + bool needsDmaPutContactManifoldAlgo; + + btCollisionObject* getColObj0() + { + return m_lsColObj0Ptr; + } + btCollisionObject* getColObj1() + { + return m_lsColObj1Ptr; + } + + + btBroadphasePair* getBroadphasePairPtr() + { + return m_pairsPointer; + } + + SpuContactManifoldCollisionAlgorithm* getlocalCollisionAlgorithm() + { + return m_lsCollisionAlgorithmPtr; + } + + btPersistentManifold* getContactManifoldPtr() + { + return m_lsManifoldPtr; + } +}; + + +#if defined(__CELLOS_LV2__) || defined(USE_LIBSPE2) + +ATTRIBUTE_ALIGNED16(CollisionTask_LocalStoreMemory gLocalStoreMemory); + +void* createCollisionLocalStoreMemory() +{ + return &gLocalStoreMemory; +} +#else +void* createCollisionLocalStoreMemory() +{ + return new CollisionTask_LocalStoreMemory; +} + +#endif + +void ProcessSpuConvexConvexCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts); + + +SIMD_FORCE_INLINE void small_cache_read(void* buffer, ppu_address_t ea, size_t size) +{ +#if USE_SOFTWARE_CACHE + // Check for alignment requirements. We need to make sure the entire request fits within one cache line, + // so the first and last bytes should fall on the same cache line + btAssert((ea & ~SPE_CACHELINE_MASK) == ((ea + size - 1) & ~SPE_CACHELINE_MASK)); + + void* ls = spe_cache_read(ea); + memcpy(buffer, ls, size); +#else + stallingUnalignedDmaSmallGet(buffer,ea,size); +#endif +} + +SIMD_FORCE_INLINE void small_cache_read_triple( void* ls0, ppu_address_t ea0, + void* ls1, ppu_address_t ea1, + void* ls2, ppu_address_t ea2, + size_t size) +{ + btAssert(size<16); + ATTRIBUTE_ALIGNED16(char tmpBuffer0[32]); + ATTRIBUTE_ALIGNED16(char tmpBuffer1[32]); + ATTRIBUTE_ALIGNED16(char tmpBuffer2[32]); + + uint32_t i; + + + ///make sure last 4 bits are the same, for cellDmaSmallGet + char* localStore0 = (char*)ls0; + uint32_t last4BitsOffset = ea0 & 0x0f; + char* tmpTarget0 = tmpBuffer0 + last4BitsOffset; +#ifdef __SPU__ + cellDmaSmallGet(tmpTarget0,ea0,size,DMA_TAG(1),0,0); +#else + tmpTarget0 = (char*)cellDmaSmallGetReadOnly(tmpTarget0,ea0,size,DMA_TAG(1),0,0); +#endif + + + char* localStore1 = (char*)ls1; + last4BitsOffset = ea1 & 0x0f; + char* tmpTarget1 = tmpBuffer1 + last4BitsOffset; +#ifdef __SPU__ + cellDmaSmallGet(tmpTarget1,ea1,size,DMA_TAG(1),0,0); +#else + tmpTarget1 = (char*)cellDmaSmallGetReadOnly(tmpTarget1,ea1,size,DMA_TAG(1),0,0); +#endif + + char* localStore2 = (char*)ls2; + last4BitsOffset = ea2 & 0x0f; + char* tmpTarget2 = tmpBuffer2 + last4BitsOffset; +#ifdef __SPU__ + cellDmaSmallGet(tmpTarget2,ea2,size,DMA_TAG(1),0,0); +#else + tmpTarget2 = (char*)cellDmaSmallGetReadOnly(tmpTarget2,ea2,size,DMA_TAG(1),0,0); +#endif + + + cellDmaWaitTagStatusAll( DMA_MASK(1) ); + + //this is slowish, perhaps memcpy on SPU is smarter? + for (i=0; btLikely( ibvhShapeData.gIndexMesh.m_indexType == PHY_SHORT) + { + unsigned short int* indexBasePtr = (unsigned short int*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexBase+triangleIndex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexStride); + ATTRIBUTE_ALIGNED16(unsigned short int tmpIndices[3]); + + small_cache_read_triple(&tmpIndices[0],(ppu_address_t)&indexBasePtr[0], + &tmpIndices[1],(ppu_address_t)&indexBasePtr[1], + &tmpIndices[2],(ppu_address_t)&indexBasePtr[2], + sizeof(unsigned short int)); + + m_lsMemPtr->spuIndices[0] = int(tmpIndices[0]); + m_lsMemPtr->spuIndices[1] = int(tmpIndices[1]); + m_lsMemPtr->spuIndices[2] = int(tmpIndices[2]); + } else + { + unsigned int* indexBasePtr = (unsigned int*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexBase+triangleIndex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexStride); + + small_cache_read_triple(&m_lsMemPtr->spuIndices[0],(ppu_address_t)&indexBasePtr[0], + &m_lsMemPtr->spuIndices[1],(ppu_address_t)&indexBasePtr[1], + &m_lsMemPtr->spuIndices[2],(ppu_address_t)&indexBasePtr[2], + sizeof(int)); + } + + // spu_printf("SPU index0=%d ,",spuIndices[0]); + // spu_printf("SPU index1=%d ,",spuIndices[1]); + // spu_printf("SPU index2=%d ,",spuIndices[2]); + // spu_printf("SPU: indexBasePtr=%llx\n",indexBasePtr); + + const btVector3& meshScaling = m_lsMemPtr->bvhShapeData.gTriangleMeshInterfacePtr->getScaling(); + for (int j=2;btLikely( j>=0 );j--) + { + int graphicsindex = m_lsMemPtr->spuIndices[j]; + + // spu_printf("SPU index=%d ,",graphicsindex); + btScalar* graphicsbasePtr = (btScalar*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_vertexBase+graphicsindex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_vertexStride); + // spu_printf("SPU graphicsbasePtr=%llx\n",graphicsbasePtr); + + + ///handle un-aligned vertices... + + //another DMA for each vertex + small_cache_read_triple(&spuUnscaledVertex[0],(ppu_address_t)&graphicsbasePtr[0], + &spuUnscaledVertex[1],(ppu_address_t)&graphicsbasePtr[1], + &spuUnscaledVertex[2],(ppu_address_t)&graphicsbasePtr[2], + sizeof(btScalar)); + + m_tmpTriangleShape.getVertexPtr(j).setValue(spuUnscaledVertex[0]*meshScaling.getX(), + spuUnscaledVertex[1]*meshScaling.getY(), + spuUnscaledVertex[2]*meshScaling.getZ()); + + // spu_printf("SPU:triangle vertices:%f,%f,%f\n",spuTriangleVertices[j].x(),spuTriangleVertices[j].y(),spuTriangleVertices[j].z()); + } + + + SpuCollisionPairInput triangleConcaveInput(*m_wuInput); +// triangleConcaveInput.m_spuCollisionShapes[1] = &spuTriangleVertices[0]; + triangleConcaveInput.m_spuCollisionShapes[1] = &m_tmpTriangleShape; + triangleConcaveInput.m_shapeType1 = TRIANGLE_SHAPE_PROXYTYPE; + + m_spuContacts.setShapeIdentifiersB(subPart,triangleIndex); + + // m_spuContacts.flush(); + + ProcessSpuConvexConvexCollision(&triangleConcaveInput, m_lsMemPtr,m_spuContacts); + ///this flush should be automatic + // m_spuContacts.flush(); + } + +}; + + + +void btConvexPlaneCollideSingleContact (SpuCollisionPairInput* wuInput,CollisionTask_LocalStoreMemory* lsMemPtr,SpuContactResult& spuContacts) +{ + + btConvexShape* convexShape = (btConvexShape*) wuInput->m_spuCollisionShapes[0]; + btStaticPlaneShape* planeShape = (btStaticPlaneShape*) wuInput->m_spuCollisionShapes[1]; + + bool hasCollision = false; + const btVector3& planeNormal = planeShape->getPlaneNormal(); + const btScalar& planeConstant = planeShape->getPlaneConstant(); + + + btTransform convexWorldTransform = wuInput->m_worldTransform0; + btTransform convexInPlaneTrans; + convexInPlaneTrans= wuInput->m_worldTransform1.inverse() * convexWorldTransform; + btTransform planeInConvex; + planeInConvex= convexWorldTransform.inverse() * wuInput->m_worldTransform1; + + //btVector3 vtx = convexShape->localGetSupportVertexWithoutMarginNonVirtual(planeInConvex.getBasis()*-planeNormal); + btVector3 vtx = convexShape->localGetSupportVertexNonVirtual(planeInConvex.getBasis()*-planeNormal); + + btVector3 vtxInPlane = convexInPlaneTrans(vtx); + btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); + + btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; + btVector3 vtxInPlaneWorld = wuInput->m_worldTransform1 * vtxInPlaneProjected; + + hasCollision = distance < lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold(); + //resultOut->setPersistentManifold(m_manifoldPtr); + if (hasCollision) + { + /// report a contact. internally this will be kept persistent, and contact reduction is done + btVector3 normalOnSurfaceB =wuInput->m_worldTransform1.getBasis() * planeNormal; + btVector3 pOnB = vtxInPlaneWorld; + spuContacts.addContactPoint(normalOnSurfaceB,pOnB,distance); + } +} + +void ProcessConvexPlaneSpuCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts) +{ + + register int dmaSize = 0; + register ppu_address_t dmaPpuAddress2; + btPersistentManifold* manifold = (btPersistentManifold*)wuInput->m_persistentManifoldPtr; + + ///DMA in the vertices for convex shapes + ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]); + ATTRIBUTE_ALIGNED16(char convexHullShape1[sizeof(btConvexHullShape)]); + + if ( btLikely( wuInput->m_shapeType0== CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + // spu_printf("SPU: DMA btConvexHullShape\n"); + + dmaSize = sizeof(btConvexHullShape); + dmaPpuAddress2 = wuInput->m_collisionShapes[0]; + + cellDmaGet(&convexHullShape0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + //cellDmaWaitTagStatusAll(DMA_MASK(1)); + } + + if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + // spu_printf("SPU: DMA btConvexHullShape\n"); + dmaSize = sizeof(btConvexHullShape); + dmaPpuAddress2 = wuInput->m_collisionShapes[1]; + cellDmaGet(&convexHullShape1, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + //cellDmaWaitTagStatusAll(DMA_MASK(1)); + } + + if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + cellDmaWaitTagStatusAll(DMA_MASK(1)); + dmaConvexVertexData (&lsMemPtr->convexVertexData[0], (btConvexHullShape*)&convexHullShape0); + lsMemPtr->convexVertexData[0].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[0]; + } + + + if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + cellDmaWaitTagStatusAll(DMA_MASK(1)); + dmaConvexVertexData (&lsMemPtr->convexVertexData[1], (btConvexHullShape*)&convexHullShape1); + lsMemPtr->convexVertexData[1].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[1]; + } + + + btConvexPointCloudShape cpc0,cpc1; + + if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + cellDmaWaitTagStatusAll(DMA_MASK(2)); + lsMemPtr->convexVertexData[0].gConvexPoints = &lsMemPtr->convexVertexData[0].g_convexPointBuffer[0]; + btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[0]; + const btVector3& localScaling = ch->getLocalScalingNV(); + cpc0.setPoints(lsMemPtr->convexVertexData[0].gConvexPoints,lsMemPtr->convexVertexData[0].gNumConvexPoints,false,localScaling); + wuInput->m_spuCollisionShapes[0] = &cpc0; + } + + if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + cellDmaWaitTagStatusAll(DMA_MASK(2)); + lsMemPtr->convexVertexData[1].gConvexPoints = &lsMemPtr->convexVertexData[1].g_convexPointBuffer[0]; + btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[1]; + const btVector3& localScaling = ch->getLocalScalingNV(); + cpc1.setPoints(lsMemPtr->convexVertexData[1].gConvexPoints,lsMemPtr->convexVertexData[1].gNumConvexPoints,false,localScaling); + wuInput->m_spuCollisionShapes[1] = &cpc1; + + } + + +// const btConvexShape* shape0Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[0]; +// const btConvexShape* shape1Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[1]; +// int shapeType0 = wuInput->m_shapeType0; +// int shapeType1 = wuInput->m_shapeType1; + float marginA = wuInput->m_collisionMargin0; + float marginB = wuInput->m_collisionMargin1; + + SpuClosestPointInput cpInput; + cpInput.m_convexVertexData[0] = &lsMemPtr->convexVertexData[0]; + cpInput.m_convexVertexData[1] = &lsMemPtr->convexVertexData[1]; + cpInput.m_transformA = wuInput->m_worldTransform0; + cpInput.m_transformB = wuInput->m_worldTransform1; + float sumMargin = (marginA+marginB+lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold()); + cpInput.m_maximumDistanceSquared = sumMargin * sumMargin; + + ppu_address_t manifoldAddress = (ppu_address_t)manifold; + + btPersistentManifold* spuManifold=lsMemPtr->getContactManifoldPtr(); + //spuContacts.setContactInfo(spuManifold,manifoldAddress,wuInput->m_worldTransform0,wuInput->m_worldTransform1,wuInput->m_isSwapped); + spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMemPtr->getColObj0()->getWorldTransform(), + lsMemPtr->getColObj1()->getWorldTransform(), + lsMemPtr->getColObj0()->getRestitution(),lsMemPtr->getColObj1()->getRestitution(), + lsMemPtr->getColObj0()->getFriction(),lsMemPtr->getColObj1()->getFriction(), + wuInput->m_isSwapped); + + + btConvexPlaneCollideSingleContact(wuInput,lsMemPtr,spuContacts); + + + + +} + + + + +//////////////////////// +/// Convex versus Concave triangle mesh collision detection (handles concave triangle mesh versus sphere, box, cylinder, triangle, cone, convex polyhedron etc) +/////////////////// +void ProcessConvexConcaveSpuCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts) +{ + //order: first collision shape is convex, second concave. m_isSwapped is true, if the original order was opposite + + btBvhTriangleMeshShape* trimeshShape = (btBvhTriangleMeshShape*)wuInput->m_spuCollisionShapes[1]; + //need the mesh interface, for access to triangle vertices + dmaBvhShapeData (&lsMemPtr->bvhShapeData, trimeshShape); + + btVector3 aabbMin(-1,-400,-1); + btVector3 aabbMax(1,400,1); + + + //recalc aabbs + btTransform convexInTriangleSpace; + convexInTriangleSpace = wuInput->m_worldTransform1.inverse() * wuInput->m_worldTransform0; + btConvexInternalShape* convexShape = (btConvexInternalShape*)wuInput->m_spuCollisionShapes[0]; + + computeAabb (aabbMin, aabbMax, convexShape, wuInput->m_collisionShapes[0], wuInput->m_shapeType0, convexInTriangleSpace); + + + //CollisionShape* triangleShape = static_cast(triBody->m_collisionShape); + //convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax); + + // btScalar extraMargin = collisionMarginTriangle; + // btVector3 extra(extraMargin,extraMargin,extraMargin); + // aabbMax += extra; + // aabbMin -= extra; + + ///quantize query AABB + unsigned short int quantizedQueryAabbMin[3]; + unsigned short int quantizedQueryAabbMax[3]; + lsMemPtr->bvhShapeData.getOptimizedBvh()->quantizeWithClamp(quantizedQueryAabbMin,aabbMin,0); + lsMemPtr->bvhShapeData.getOptimizedBvh()->quantizeWithClamp(quantizedQueryAabbMax,aabbMax,1); + + QuantizedNodeArray& nodeArray = lsMemPtr->bvhShapeData.getOptimizedBvh()->getQuantizedNodeArray(); + //spu_printf("SPU: numNodes = %d\n",nodeArray.size()); + + BvhSubtreeInfoArray& subTrees = lsMemPtr->bvhShapeData.getOptimizedBvh()->getSubtreeInfoArray(); + + + spuNodeCallback nodeCallback(wuInput,lsMemPtr,spuContacts); + IndexedMeshArray& indexArray = lsMemPtr->bvhShapeData.gTriangleMeshInterfacePtr->getIndexedMeshArray(); + //spu_printf("SPU:indexArray.size() = %d\n",indexArray.size()); + + // spu_printf("SPU: numSubTrees = %d\n",subTrees.size()); + //not likely to happen + if (subTrees.size() && indexArray.size() == 1) + { + ///DMA in the index info + dmaBvhIndexedMesh (&lsMemPtr->bvhShapeData.gIndexMesh, indexArray, 0 /* index into indexArray */, 1 /* dmaTag */); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + //display the headers + int numBatch = subTrees.size(); + for (int i=0;ibvhShapeData.gSubtreeHeaders[0], (ppu_address_t)(&subTrees[i]), nextBatch, 1); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + + // spu_printf("nextBatch = %d\n",nextBatch); + + for (int j=0;jbvhShapeData.gSubtreeHeaders[j]; + + unsigned int overlap = spuTestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); + if (overlap) + { + btAssert(subtree.m_subtreeSize); + + //dma the actual nodes of this subtree + dmaBvhSubTreeNodes (&lsMemPtr->bvhShapeData.gSubtreeNodes[0], subtree, nodeArray, 2); + cellDmaWaitTagStatusAll(DMA_MASK(2)); + + /* Walk this subtree */ + spuWalkStacklessQuantizedTree(&nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax, + &lsMemPtr->bvhShapeData.gSubtreeNodes[0], + 0, + subtree.m_subtreeSize); + } + // spu_printf("subtreeSize = %d\n",gSubtreeHeaders[j].m_subtreeSize); + } + + // unsigned short int m_quantizedAabbMin[3]; + // unsigned short int m_quantizedAabbMax[3]; + // int m_rootNodeIndex; + // int m_subtreeSize; + i+=nextBatch; + } + + //pre-fetch first tree, then loop and double buffer + } + +} + + +#define MAX_DEGENERATE_STATS 15 +int stats[MAX_DEGENERATE_STATS]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +int degenerateStats[MAX_DEGENERATE_STATS]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + +//////////////////////// +/// Convex versus Convex collision detection (handles collision between sphere, box, cylinder, triangle, cone, convex polyhedron etc) +/////////////////// +void ProcessSpuConvexConvexCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts) +{ + register int dmaSize; + register ppu_address_t dmaPpuAddress2; + +#ifdef DEBUG_SPU_COLLISION_DETECTION + //spu_printf("SPU: ProcessSpuConvexConvexCollision\n"); +#endif //DEBUG_SPU_COLLISION_DETECTION + //CollisionShape* shape0 = (CollisionShape*)wuInput->m_collisionShapes[0]; + //CollisionShape* shape1 = (CollisionShape*)wuInput->m_collisionShapes[1]; + btPersistentManifold* manifold = (btPersistentManifold*)wuInput->m_persistentManifoldPtr; + + bool genericGjk = true; + + if (genericGjk) + { + //try generic GJK + + + + //SpuConvexPenetrationDepthSolver* penetrationSolver=0; + btVoronoiSimplexSolver simplexSolver; + btGjkEpaPenetrationDepthSolver epaPenetrationSolver2; + + btConvexPenetrationDepthSolver* penetrationSolver = &epaPenetrationSolver2; + + //SpuMinkowskiPenetrationDepthSolver minkowskiPenetrationSolver; +#ifdef ENABLE_EPA + if (gUseEpa) + { + penetrationSolver = &epaPenetrationSolver2; + } else +#endif + { + //penetrationSolver = &minkowskiPenetrationSolver; + } + + + ///DMA in the vertices for convex shapes + ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]); + ATTRIBUTE_ALIGNED16(char convexHullShape1[sizeof(btConvexHullShape)]); + + if ( btLikely( wuInput->m_shapeType0== CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + // spu_printf("SPU: DMA btConvexHullShape\n"); + + dmaSize = sizeof(btConvexHullShape); + dmaPpuAddress2 = wuInput->m_collisionShapes[0]; + + cellDmaGet(&convexHullShape0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + //cellDmaWaitTagStatusAll(DMA_MASK(1)); + } + + if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + // spu_printf("SPU: DMA btConvexHullShape\n"); + dmaSize = sizeof(btConvexHullShape); + dmaPpuAddress2 = wuInput->m_collisionShapes[1]; + cellDmaGet(&convexHullShape1, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + //cellDmaWaitTagStatusAll(DMA_MASK(1)); + } + + if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + cellDmaWaitTagStatusAll(DMA_MASK(1)); + dmaConvexVertexData (&lsMemPtr->convexVertexData[0], (btConvexHullShape*)&convexHullShape0); + lsMemPtr->convexVertexData[0].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[0]; + } + + + if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + cellDmaWaitTagStatusAll(DMA_MASK(1)); + dmaConvexVertexData (&lsMemPtr->convexVertexData[1], (btConvexHullShape*)&convexHullShape1); + lsMemPtr->convexVertexData[1].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[1]; + } + + + btConvexPointCloudShape cpc0,cpc1; + + if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + cellDmaWaitTagStatusAll(DMA_MASK(2)); + lsMemPtr->convexVertexData[0].gConvexPoints = &lsMemPtr->convexVertexData[0].g_convexPointBuffer[0]; + btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[0]; + const btVector3& localScaling = ch->getLocalScalingNV(); + cpc0.setPoints(lsMemPtr->convexVertexData[0].gConvexPoints,lsMemPtr->convexVertexData[0].gNumConvexPoints,false,localScaling); + wuInput->m_spuCollisionShapes[0] = &cpc0; + } + + if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + cellDmaWaitTagStatusAll(DMA_MASK(2)); + lsMemPtr->convexVertexData[1].gConvexPoints = &lsMemPtr->convexVertexData[1].g_convexPointBuffer[0]; + btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[1]; + const btVector3& localScaling = ch->getLocalScalingNV(); + cpc1.setPoints(lsMemPtr->convexVertexData[1].gConvexPoints,lsMemPtr->convexVertexData[1].gNumConvexPoints,false,localScaling); + wuInput->m_spuCollisionShapes[1] = &cpc1; + + } + + + const btConvexShape* shape0Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[0]; + const btConvexShape* shape1Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[1]; + int shapeType0 = wuInput->m_shapeType0; + int shapeType1 = wuInput->m_shapeType1; + float marginA = wuInput->m_collisionMargin0; + float marginB = wuInput->m_collisionMargin1; + + SpuClosestPointInput cpInput; + cpInput.m_convexVertexData[0] = &lsMemPtr->convexVertexData[0]; + cpInput.m_convexVertexData[1] = &lsMemPtr->convexVertexData[1]; + cpInput.m_transformA = wuInput->m_worldTransform0; + cpInput.m_transformB = wuInput->m_worldTransform1; + float sumMargin = (marginA+marginB+lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold()); + cpInput.m_maximumDistanceSquared = sumMargin * sumMargin; + + ppu_address_t manifoldAddress = (ppu_address_t)manifold; + + btPersistentManifold* spuManifold=lsMemPtr->getContactManifoldPtr(); + //spuContacts.setContactInfo(spuManifold,manifoldAddress,wuInput->m_worldTransform0,wuInput->m_worldTransform1,wuInput->m_isSwapped); + spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMemPtr->getColObj0()->getWorldTransform(), + lsMemPtr->getColObj1()->getWorldTransform(), + lsMemPtr->getColObj0()->getRestitution(),lsMemPtr->getColObj1()->getRestitution(), + lsMemPtr->getColObj0()->getFriction(),lsMemPtr->getColObj1()->getFriction(), + wuInput->m_isSwapped); + + { + btGjkPairDetector gjk(shape0Ptr,shape1Ptr,shapeType0,shapeType1,marginA,marginB,&simplexSolver,penetrationSolver);//&vsSolver,penetrationSolver); + gjk.getClosestPoints(cpInput,spuContacts,0);//,debugDraw); + + btAssert(gjk.m_lastUsedMethod getContactBreakingThreshold(); + lsMemPtr->getlocalCollisionAlgorithm()->m_sepDistance.initSeparatingDistance(gjk.getCachedSeparatingAxis(),sepDist,wuInput->m_worldTransform0,wuInput->m_worldTransform1); + lsMemPtr->needsDmaPutContactManifoldAlgo = true; +#endif //USE_SEPDISTANCE_UTIL + + } + + } + + +} + + +template void DoSwap(T& a, T& b) +{ + char tmp[sizeof(T)]; + memcpy(tmp, &a, sizeof(T)); + memcpy(&a, &b, sizeof(T)); + memcpy(&b, tmp, sizeof(T)); +} + +SIMD_FORCE_INLINE void dmaAndSetupCollisionObjects(SpuCollisionPairInput& collisionPairInput, CollisionTask_LocalStoreMemory& lsMem) +{ + register int dmaSize; + register ppu_address_t dmaPpuAddress2; + + dmaSize = sizeof(btCollisionObject);//btTransform); + dmaPpuAddress2 = /*collisionPairInput.m_isSwapped ? (ppu_address_t)lsMem.gProxyPtr1->m_clientObject :*/ (ppu_address_t)lsMem.getlocalCollisionAlgorithm()->getCollisionObject0(); + lsMem.m_lsColObj0Ptr = (btCollisionObject*)cellDmaGetReadOnly(&lsMem.gColObj0Buffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + + dmaSize = sizeof(btCollisionObject);//btTransform); + dmaPpuAddress2 = /*collisionPairInput.m_isSwapped ? (ppu_address_t)lsMem.gProxyPtr0->m_clientObject :*/ (ppu_address_t)lsMem.getlocalCollisionAlgorithm()->getCollisionObject1(); + lsMem.m_lsColObj1Ptr = (btCollisionObject*)cellDmaGetReadOnly(&lsMem.gColObj1Buffer, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0); + + cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); + + btCollisionObject* ob0 = lsMem.getColObj0(); + btCollisionObject* ob1 = lsMem.getColObj1(); + + collisionPairInput.m_worldTransform0 = ob0->getWorldTransform(); + collisionPairInput.m_worldTransform1 = ob1->getWorldTransform(); +} + + + +void handleCollisionPair(SpuCollisionPairInput& collisionPairInput, CollisionTask_LocalStoreMemory& lsMem, + SpuContactResult &spuContacts, + ppu_address_t collisionShape0Ptr, void* collisionShape0Loc, + ppu_address_t collisionShape1Ptr, void* collisionShape1Loc, bool dmaShapes = true) +{ + + if (btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType0) + && btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType1)) + { + if (dmaShapes) + { + dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0); + dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1); + cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); + } + + btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc; + btConvexInternalShape* spuConvexShape1 = (btConvexInternalShape*)collisionShape1Loc; + + btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions(); + btVector3 dim1 = spuConvexShape1->getImplicitShapeDimensions(); + + collisionPairInput.m_primitiveDimensions0 = dim0; + collisionPairInput.m_primitiveDimensions1 = dim1; + collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr; + collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr; + collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0; + collisionPairInput.m_spuCollisionShapes[1] = spuConvexShape1; + ProcessSpuConvexConvexCollision(&collisionPairInput,&lsMem,spuContacts); + } + else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType0) && + btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType1)) + { + //snPause(); + + dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0); + dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1); + cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); + + // Both are compounds, do N^2 CD for now + ///@todo: add some AABB-based pruning (probably not -> slower) + + btCompoundShape* spuCompoundShape0 = (btCompoundShape*)collisionShape0Loc; + btCompoundShape* spuCompoundShape1 = (btCompoundShape*)collisionShape1Loc; + + dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape0, 1); + dmaCompoundShapeInfo (&lsMem.compoundShapeData[1], spuCompoundShape1, 2); + cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); + + + dmaCompoundSubShapes (&lsMem.compoundShapeData[0], spuCompoundShape0, 1); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + dmaCompoundSubShapes (&lsMem.compoundShapeData[1], spuCompoundShape1, 1); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + int childShapeCount0 = spuCompoundShape0->getNumChildShapes(); + btAssert(childShapeCount0< MAX_SPU_COMPOUND_SUBSHAPES); + int childShapeCount1 = spuCompoundShape1->getNumChildShapes(); + btAssert(childShapeCount1< MAX_SPU_COMPOUND_SUBSHAPES); + + // Start the N^2 + for (int i = 0; i < childShapeCount0; ++i) + { + btCompoundShapeChild& childShape0 = lsMem.compoundShapeData[0].gSubshapes[i]; + btAssert(!btBroadphaseProxy::isCompound(childShape0.m_childShapeType)); + + for (int j = 0; j < childShapeCount1; ++j) + { + btCompoundShapeChild& childShape1 = lsMem.compoundShapeData[1].gSubshapes[j]; + btAssert(!btBroadphaseProxy::isCompound(childShape1.m_childShapeType)); + + + /* Create a new collision pair input struct using the two child shapes */ + SpuCollisionPairInput cinput (collisionPairInput); + + cinput.m_worldTransform0 = collisionPairInput.m_worldTransform0 * childShape0.m_transform; + cinput.m_shapeType0 = childShape0.m_childShapeType; + cinput.m_collisionMargin0 = childShape0.m_childMargin; + + cinput.m_worldTransform1 = collisionPairInput.m_worldTransform1 * childShape1.m_transform; + cinput.m_shapeType1 = childShape1.m_childShapeType; + cinput.m_collisionMargin1 = childShape1.m_childMargin; + /* Recursively call handleCollisionPair () with new collision pair input */ + + handleCollisionPair(cinput, lsMem, spuContacts, + (ppu_address_t)childShape0.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i], + (ppu_address_t)childShape1.m_childShape, lsMem.compoundShapeData[1].gSubshapeShape[j], false); + } + } + } + else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType0) ) + { + //snPause(); + + dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0); + dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1); + cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); + + // object 0 compound, object 1 non-compound + btCompoundShape* spuCompoundShape = (btCompoundShape*)collisionShape0Loc; + dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape, 1); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + int childShapeCount = spuCompoundShape->getNumChildShapes(); + btAssert(childShapeCount< MAX_SPU_COMPOUND_SUBSHAPES); + + for (int i = 0; i < childShapeCount; ++i) + { + btCompoundShapeChild& childShape = lsMem.compoundShapeData[0].gSubshapes[i]; + btAssert(!btBroadphaseProxy::isCompound(childShape.m_childShapeType)); + // Dma the child shape + dmaCollisionShape (&lsMem.compoundShapeData[0].gSubshapeShape[i], (ppu_address_t)childShape.m_childShape, 1, childShape.m_childShapeType); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + SpuCollisionPairInput cinput (collisionPairInput); + cinput.m_worldTransform0 = collisionPairInput.m_worldTransform0 * childShape.m_transform; + cinput.m_shapeType0 = childShape.m_childShapeType; + cinput.m_collisionMargin0 = childShape.m_childMargin; + + handleCollisionPair(cinput, lsMem, spuContacts, + (ppu_address_t)childShape.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i], + collisionShape1Ptr, collisionShape1Loc, false); + } + } + else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType1) ) + { + //snPause(); + + dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0); + dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1); + cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); + // object 0 non-compound, object 1 compound + btCompoundShape* spuCompoundShape = (btCompoundShape*)collisionShape1Loc; + dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape, 1); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + int childShapeCount = spuCompoundShape->getNumChildShapes(); + btAssert(childShapeCount< MAX_SPU_COMPOUND_SUBSHAPES); + + + for (int i = 0; i < childShapeCount; ++i) + { + btCompoundShapeChild& childShape = lsMem.compoundShapeData[0].gSubshapes[i]; + btAssert(!btBroadphaseProxy::isCompound(childShape.m_childShapeType)); + // Dma the child shape + dmaCollisionShape (&lsMem.compoundShapeData[0].gSubshapeShape[i], (ppu_address_t)childShape.m_childShape, 1, childShape.m_childShapeType); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + SpuCollisionPairInput cinput (collisionPairInput); + cinput.m_worldTransform1 = collisionPairInput.m_worldTransform1 * childShape.m_transform; + cinput.m_shapeType1 = childShape.m_childShapeType; + cinput.m_collisionMargin1 = childShape.m_childMargin; + handleCollisionPair(cinput, lsMem, spuContacts, + collisionShape0Ptr, collisionShape0Loc, + (ppu_address_t)childShape.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i], false); + } + + } + else + { + //a non-convex shape is involved + bool handleConvexConcave = false; + + //snPause(); + + if (btBroadphaseProxy::isConcave(collisionPairInput.m_shapeType0) && + btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType1)) + { + // Swap stuff + DoSwap(collisionShape0Ptr, collisionShape1Ptr); + DoSwap(collisionShape0Loc, collisionShape1Loc); + DoSwap(collisionPairInput.m_shapeType0, collisionPairInput.m_shapeType1); + DoSwap(collisionPairInput.m_worldTransform0, collisionPairInput.m_worldTransform1); + DoSwap(collisionPairInput.m_collisionMargin0, collisionPairInput.m_collisionMargin1); + + collisionPairInput.m_isSwapped = true; + } + + if (btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType0)&& + btBroadphaseProxy::isConcave(collisionPairInput.m_shapeType1)) + { + handleConvexConcave = true; + } + if (handleConvexConcave) + { + if (dmaShapes) + { + dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0); + dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1); + cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); + } + + if (collisionPairInput.m_shapeType1 == STATIC_PLANE_PROXYTYPE) + { + btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc; + btStaticPlaneShape* planeShape= (btStaticPlaneShape*)collisionShape1Loc; + + btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions(); + collisionPairInput.m_primitiveDimensions0 = dim0; + collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr; + collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr; + collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0; + collisionPairInput.m_spuCollisionShapes[1] = planeShape; + + ProcessConvexPlaneSpuCollision(&collisionPairInput,&lsMem,spuContacts); + } else + { + btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc; + btBvhTriangleMeshShape* trimeshShape = (btBvhTriangleMeshShape*)collisionShape1Loc; + + btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions(); + collisionPairInput.m_primitiveDimensions0 = dim0; + collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr; + collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr; + collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0; + collisionPairInput.m_spuCollisionShapes[1] = trimeshShape; + + ProcessConvexConcaveSpuCollision(&collisionPairInput,&lsMem,spuContacts); + } + } + + } + + spuContacts.flush(); + +} + + +void processCollisionTask(void* userPtr, void* lsMemPtr) +{ + + SpuGatherAndProcessPairsTaskDesc* taskDescPtr = (SpuGatherAndProcessPairsTaskDesc*)userPtr; + SpuGatherAndProcessPairsTaskDesc& taskDesc = *taskDescPtr; + CollisionTask_LocalStoreMemory* colMemPtr = (CollisionTask_LocalStoreMemory*)lsMemPtr; + CollisionTask_LocalStoreMemory& lsMem = *(colMemPtr); + + gUseEpa = taskDesc.m_useEpa; + + // spu_printf("taskDescPtr=%llx\n",taskDescPtr); + + SpuContactResult spuContacts; + + //////////////////// + + ppu_address_t dmaInPtr = taskDesc.m_inPairPtr; + unsigned int numPages = taskDesc.numPages; + unsigned int numOnLastPage = taskDesc.numOnLastPage; + + // prefetch first set of inputs and wait + lsMem.g_workUnitTaskBuffers.init(); + + unsigned int nextNumOnPage = (numPages > 1)? MIDPHASE_NUM_WORKUNITS_PER_PAGE : numOnLastPage; + lsMem.g_workUnitTaskBuffers.backBufferDmaGet(dmaInPtr, nextNumOnPage*sizeof(SpuGatherAndProcessWorkUnitInput), DMA_TAG(3)); + dmaInPtr += MIDPHASE_WORKUNIT_PAGE_SIZE; + + + register unsigned char *inputPtr; + register unsigned int numOnPage; + register unsigned int j; + SpuGatherAndProcessWorkUnitInput* wuInputs; + register int dmaSize; + register ppu_address_t dmaPpuAddress; + register ppu_address_t dmaPpuAddress2; + + int numPairs; + register int p; + SpuCollisionPairInput collisionPairInput; + + for (unsigned int i = 0; btLikely(i < numPages); i++) + { + + // wait for back buffer dma and swap buffers + inputPtr = lsMem.g_workUnitTaskBuffers.swapBuffers(); + + // number on current page is number prefetched last iteration + numOnPage = nextNumOnPage; + + + // prefetch next set of inputs +#if MIDPHASE_NUM_WORKUNIT_PAGES > 2 + if ( btLikely( i < numPages-1 ) ) +#else + if ( btUnlikely( i < numPages-1 ) ) +#endif + { + nextNumOnPage = (i == numPages-2)? numOnLastPage : MIDPHASE_NUM_WORKUNITS_PER_PAGE; + lsMem.g_workUnitTaskBuffers.backBufferDmaGet(dmaInPtr, nextNumOnPage*sizeof(SpuGatherAndProcessWorkUnitInput), DMA_TAG(3)); + dmaInPtr += MIDPHASE_WORKUNIT_PAGE_SIZE; + } + + wuInputs = reinterpret_cast(inputPtr); + + + for (j = 0; btLikely( j < numOnPage ); j++) + { +#ifdef DEBUG_SPU_COLLISION_DETECTION + // printMidphaseInput(&wuInputs[j]); +#endif //DEBUG_SPU_COLLISION_DETECTION + + + numPairs = wuInputs[j].m_endIndex - wuInputs[j].m_startIndex; + + if ( btLikely( numPairs ) ) + { + dmaSize = numPairs*sizeof(btBroadphasePair); + dmaPpuAddress = wuInputs[j].m_pairArrayPtr+wuInputs[j].m_startIndex * sizeof(btBroadphasePair); + lsMem.m_pairsPointer = (btBroadphasePair*)cellDmaGetReadOnly(&lsMem.gBroadphasePairsBuffer, dmaPpuAddress , dmaSize, DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + + for (p=0;pm_userInfo = %d\n",pair.m_userInfo); + spu_printf("pair->m_algorithm = %d\n",pair.m_algorithm); + spu_printf("pair->m_pProxy0 = %d\n",pair.m_pProxy0); + spu_printf("pair->m_pProxy1 = %d\n",pair.m_pProxy1); +#endif //DEBUG_SPU_COLLISION_DETECTION + + if (pair.m_internalTmpValue == 2 && pair.m_algorithm && pair.m_pProxy0 && pair.m_pProxy1) + { + dmaSize = sizeof(SpuContactManifoldCollisionAlgorithm); + dmaPpuAddress2 = (ppu_address_t)pair.m_algorithm; + lsMem.m_lsCollisionAlgorithmPtr = (SpuContactManifoldCollisionAlgorithm*)cellDmaGetReadOnly(&lsMem.gSpuContactManifoldAlgoBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + lsMem.needsDmaPutContactManifoldAlgo = false; + + collisionPairInput.m_persistentManifoldPtr = (ppu_address_t) lsMem.getlocalCollisionAlgorithm()->getContactManifoldPtr(); + collisionPairInput.m_isSwapped = false; + + if (1) + { + + ///can wait on the combined DMA_MASK, or dma on the same tag + + +#ifdef DEBUG_SPU_COLLISION_DETECTION + // spu_printf("SPU collisionPairInput->m_shapeType0 = %d\n",collisionPairInput->m_shapeType0); + // spu_printf("SPU collisionPairInput->m_shapeType1 = %d\n",collisionPairInput->m_shapeType1); +#endif //DEBUG_SPU_COLLISION_DETECTION + + + dmaSize = sizeof(btPersistentManifold); + + dmaPpuAddress2 = collisionPairInput.m_persistentManifoldPtr; + lsMem.m_lsManifoldPtr = (btPersistentManifold*)cellDmaGetReadOnly(&lsMem.gPersistentManifoldBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + + collisionPairInput.m_shapeType0 = lsMem.getlocalCollisionAlgorithm()->getShapeType0(); + collisionPairInput.m_shapeType1 = lsMem.getlocalCollisionAlgorithm()->getShapeType1(); + collisionPairInput.m_collisionMargin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0(); + collisionPairInput.m_collisionMargin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1(); + + + + //??cellDmaWaitTagStatusAll(DMA_MASK(1)); + + + if (1) + { + //snPause(); + + // Get the collision objects + dmaAndSetupCollisionObjects(collisionPairInput, lsMem); + + if (lsMem.getColObj0()->isActive() || lsMem.getColObj1()->isActive()) + { + + lsMem.needsDmaPutContactManifoldAlgo = true; +#ifdef USE_SEPDISTANCE_UTIL + lsMem.getlocalCollisionAlgorithm()->m_sepDistance.updateSeparatingDistance(collisionPairInput.m_worldTransform0,collisionPairInput.m_worldTransform1); +#endif //USE_SEPDISTANCE_UTIL + +#define USE_DEDICATED_BOX_BOX 1 +#ifdef USE_DEDICATED_BOX_BOX + bool boxbox = ((lsMem.getlocalCollisionAlgorithm()->getShapeType0()==BOX_SHAPE_PROXYTYPE)&& + (lsMem.getlocalCollisionAlgorithm()->getShapeType1()==BOX_SHAPE_PROXYTYPE)); + if (boxbox) + { + //spu_printf("boxbox dist = %f\n",distance); + btPersistentManifold* spuManifold=lsMem.getContactManifoldPtr(); + btPersistentManifold* manifold = (btPersistentManifold*)collisionPairInput.m_persistentManifoldPtr; + ppu_address_t manifoldAddress = (ppu_address_t)manifold; + + spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMem.getColObj0()->getWorldTransform(), + lsMem.getColObj1()->getWorldTransform(), + lsMem.getColObj0()->getRestitution(),lsMem.getColObj1()->getRestitution(), + lsMem.getColObj0()->getFriction(),lsMem.getColObj1()->getFriction(), + collisionPairInput.m_isSwapped); + + + //float distance=0.f; + btVector3 normalInB; + + + if (//!gUseEpa && +#ifdef USE_SEPDISTANCE_UTIL + lsMem.getlocalCollisionAlgorithm()->m_sepDistance.getConservativeSeparatingDistance()<=0.f +#else + 1 +#endif + ) + { +//#define USE_PE_BOX_BOX 1 +#ifdef USE_PE_BOX_BOX + { + + //getCollisionMargin0 + btScalar margin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0(); + btScalar margin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1(); + btVector3 shapeDim0 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions0()+btVector3(margin0,margin0,margin0); + btVector3 shapeDim1 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions1()+btVector3(margin1,margin1,margin1); +/* + //Box boxA(shapeDim0.getX(),shapeDim0.getY(),shapeDim0.getZ()); + vmVector3 vmPos0 = getVmVector3(collisionPairInput.m_worldTransform0.getOrigin()); + vmVector3 vmPos1 = getVmVector3(collisionPairInput.m_worldTransform1.getOrigin()); + vmMatrix3 vmMatrix0 = getVmMatrix3(collisionPairInput.m_worldTransform0.getBasis()); + vmMatrix3 vmMatrix1 = getVmMatrix3(collisionPairInput.m_worldTransform1.getBasis()); + + vmTransform3 transformA(vmMatrix0,vmPos0); + Box boxB(shapeDim1.getX(),shapeDim1.getY(),shapeDim1.getZ()); + vmTransform3 transformB(vmMatrix1,vmPos1); + BoxPoint resultClosestBoxPointA; + BoxPoint resultClosestBoxPointB; + vmVector3 resultNormal; + */ + +#ifdef USE_SEPDISTANCE_UTIL + float distanceThreshold = FLT_MAX +#else + //float distanceThreshold = 0.f; +#endif + + + vmVector3 n; + Box boxA; + vmVector3 hA(shapeDim0.getX(),shapeDim0.getY(),shapeDim0.getZ()); + vmVector3 hB(shapeDim1.getX(),shapeDim1.getY(),shapeDim1.getZ()); + boxA.mHalf= hA; + vmTransform3 trA; + trA.setTranslation(getVmVector3(collisionPairInput.m_worldTransform0.getOrigin())); + trA.setUpper3x3(getVmMatrix3(collisionPairInput.m_worldTransform0.getBasis())); + Box boxB; + boxB.mHalf = hB; + vmTransform3 trB; + trB.setTranslation(getVmVector3(collisionPairInput.m_worldTransform1.getOrigin())); + trB.setUpper3x3(getVmMatrix3(collisionPairInput.m_worldTransform1.getBasis())); + + float distanceThreshold = spuManifold->getContactBreakingThreshold();//0.001f; + + + BoxPoint ptA,ptB; + float dist = boxBoxDistance(n, ptA, ptB, + boxA, trA, boxB, trB, + distanceThreshold ); + + +// float distance = boxBoxDistance(resultNormal,resultClosestBoxPointA,resultClosestBoxPointB, boxA, transformA, boxB,transformB,distanceThreshold); + + normalInB = -getBtVector3(n);//resultNormal); + + //if(dist < distanceThreshold)//spuManifold->getContactBreakingThreshold()) + if(dist < spuManifold->getContactBreakingThreshold()) + { + btVector3 pointOnB = collisionPairInput.m_worldTransform1(getBtVector3(ptB.localPoint)); + + spuContacts.addContactPoint( + normalInB, + pointOnB, + dist); + } + } +#else + { + + btScalar margin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0(); + btScalar margin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1(); + btVector3 shapeDim0 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions0()+btVector3(margin0,margin0,margin0); + btVector3 shapeDim1 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions1()+btVector3(margin1,margin1,margin1); + + + btBoxShape box0(shapeDim0); + btBoxShape box1(shapeDim1); + + struct SpuBridgeContactCollector : public btDiscreteCollisionDetectorInterface::Result + { + SpuContactResult& m_spuContacts; + + virtual void setShapeIdentifiersA(int partId0,int index0) + { + m_spuContacts.setShapeIdentifiersA(partId0,index0); + } + virtual void setShapeIdentifiersB(int partId1,int index1) + { + m_spuContacts.setShapeIdentifiersB(partId1,index1); + } + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) + { + m_spuContacts.addContactPoint(normalOnBInWorld,pointInWorld,depth); + } + + SpuBridgeContactCollector(SpuContactResult& spuContacts) + :m_spuContacts(spuContacts) + { + + } + }; + + SpuBridgeContactCollector bridgeOutput(spuContacts); + + btDiscreteCollisionDetectorInterface::ClosestPointInput input; + input.m_maximumDistanceSquared = BT_LARGE_FLOAT; + input.m_transformA = collisionPairInput.m_worldTransform0; + input.m_transformB = collisionPairInput.m_worldTransform1; + + btBoxBoxDetector detector(&box0,&box1); + + detector.getClosestPoints(input,bridgeOutput,0); + + } +#endif //USE_PE_BOX_BOX + + lsMem.needsDmaPutContactManifoldAlgo = true; +#ifdef USE_SEPDISTANCE_UTIL + btScalar sepDist2 = distance+spuManifold->getContactBreakingThreshold(); + lsMem.getlocalCollisionAlgorithm()->m_sepDistance.initSeparatingDistance(normalInB,sepDist2,collisionPairInput.m_worldTransform0,collisionPairInput.m_worldTransform1); +#endif //USE_SEPDISTANCE_UTIL + gProcessedCol++; + } else + { + gSkippedCol++; + } + + spuContacts.flush(); + + + } else +#endif //USE_DEDICATED_BOX_BOX + { + if ( +#ifdef USE_SEPDISTANCE_UTIL + lsMem.getlocalCollisionAlgorithm()->m_sepDistance.getConservativeSeparatingDistance()<=0.f +#else + 1 +#endif //USE_SEPDISTANCE_UTIL + ) + { + handleCollisionPair(collisionPairInput, lsMem, spuContacts, + (ppu_address_t)lsMem.getColObj0()->getRootCollisionShape(), &lsMem.gCollisionShapes[0].collisionShape, + (ppu_address_t)lsMem.getColObj1()->getRootCollisionShape(), &lsMem.gCollisionShapes[1].collisionShape); + } else + { + //spu_printf("boxbox dist = %f\n",distance); + btPersistentManifold* spuManifold=lsMem.getContactManifoldPtr(); + btPersistentManifold* manifold = (btPersistentManifold*)collisionPairInput.m_persistentManifoldPtr; + ppu_address_t manifoldAddress = (ppu_address_t)manifold; + + spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMem.getColObj0()->getWorldTransform(), + lsMem.getColObj1()->getWorldTransform(), + lsMem.getColObj0()->getRestitution(),lsMem.getColObj1()->getRestitution(), + lsMem.getColObj0()->getFriction(),lsMem.getColObj1()->getFriction(), + collisionPairInput.m_isSwapped); + + spuContacts.flush(); + } + } + + } + + } + } + +#ifdef USE_SEPDISTANCE_UTIL +#if defined (__SPU__) || defined (USE_LIBSPE2) + if (lsMem.needsDmaPutContactManifoldAlgo) + { + dmaSize = sizeof(SpuContactManifoldCollisionAlgorithm); + dmaPpuAddress2 = (ppu_address_t)pair.m_algorithm; + cellDmaLargePut(&lsMem.gSpuContactManifoldAlgoBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + } +#endif +#endif //#ifdef USE_SEPDISTANCE_UTIL + + } + } + } + } //end for (j = 0; j < numOnPage; j++) + + }// for + + + + return; +} + + diff --git a/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h new file mode 100644 index 0000000..bbaa555 --- /dev/null +++ b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h @@ -0,0 +1,140 @@ +/* +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 SPU_GATHERING_COLLISION_TASK_H +#define SPU_GATHERING_COLLISION_TASK_H + +#include "../PlatformDefinitions.h" +//#define DEBUG_SPU_COLLISION_DETECTION 1 + + +///Task Description for SPU collision detection +struct SpuGatherAndProcessPairsTaskDesc +{ + ppu_address_t m_inPairPtr;//m_pairArrayPtr; + //mutex variable + uint32_t m_someMutexVariableInMainMemory; + + ppu_address_t m_dispatcher; + + uint32_t numOnLastPage; + + uint16_t numPages; + uint16_t taskId; + bool m_useEpa; + + struct CollisionTask_LocalStoreMemory* m_lsMemory; +} + +#if defined(__CELLOS_LV2__) || defined(USE_LIBSPE2) +__attribute__ ((aligned (128))) +#endif +; + + +void processCollisionTask(void* userPtr, void* lsMemory); + +void* createCollisionLocalStoreMemory(); + + +#if defined(USE_LIBSPE2) && defined(__SPU__) +#include "../SpuLibspe2Support.h" +#include +#include +#include + +//#define DEBUG_LIBSPE2_SPU_TASK + + + +int main(unsigned long long speid, addr64 argp, addr64 envp) +{ + printf("SPU: hello \n"); + + ATTRIBUTE_ALIGNED128(btSpuStatus status); + ATTRIBUTE_ALIGNED16( SpuGatherAndProcessPairsTaskDesc taskDesc ) ; + unsigned int received_message = Spu_Mailbox_Event_Nothing; + bool shutdown = false; + + cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + status.m_status = Spu_Status_Free; + status.m_lsMemory.p = createCollisionLocalStoreMemory(); + + cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + + while ( btLikely( !shutdown ) ) + { + + received_message = spu_read_in_mbox(); + + if( btLikely( received_message == Spu_Mailbox_Event_Task )) + { +#ifdef DEBUG_LIBSPE2_SPU_TASK + printf("SPU: received Spu_Mailbox_Event_Task\n"); +#endif //DEBUG_LIBSPE2_SPU_TASK + + // refresh the status + cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + btAssert(status.m_status==Spu_Status_Occupied); + + cellDmaGet(&taskDesc, status.m_taskDesc.p, sizeof(SpuGatherAndProcessPairsTaskDesc), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); +#ifdef DEBUG_LIBSPE2_SPU_TASK + printf("SPU:processCollisionTask\n"); +#endif //DEBUG_LIBSPE2_SPU_TASK + processCollisionTask((void*)&taskDesc, taskDesc.m_lsMemory); + +#ifdef DEBUG_LIBSPE2_SPU_TASK + printf("SPU:finished processCollisionTask\n"); +#endif //DEBUG_LIBSPE2_SPU_TASK + } + else + { +#ifdef DEBUG_LIBSPE2_SPU_TASK + printf("SPU: received ShutDown\n"); +#endif //DEBUG_LIBSPE2_SPU_TASK + if( btLikely( received_message == Spu_Mailbox_Event_Shutdown ) ) + { + shutdown = true; + } + else + { + //printf("SPU - Sth. recieved\n"); + } + } + + // set to status free and wait for next task + status.m_status = Spu_Status_Free; + cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + + } + + printf("SPU: shutdown\n"); + return 0; +} +#endif // USE_LIBSPE2 + + +#endif //SPU_GATHERING_COLLISION_TASK_H + + diff --git a/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h new file mode 100644 index 0000000..8b89de0 --- /dev/null +++ b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h @@ -0,0 +1,19 @@ +/* +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. +*/ + + + + + diff --git a/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp new file mode 100644 index 0000000..9f7e64d --- /dev/null +++ b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp @@ -0,0 +1,348 @@ +/* +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 "SpuMinkowskiPenetrationDepthSolver.h" +#include "SpuContactResult.h" +#include "SpuPreferredPenetrationDirections.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "SpuCollisionShapes.h" + +#define NUM_UNITSPHERE_POINTS 42 +static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = +{ +btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)), +btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)), +btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)), +btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)), +btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)), +btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)), +btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)), +btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)), +btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)), +btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)), +btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)), +btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)), +btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)), +btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)), +btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)), +btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)), +btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)), +btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)), +btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)), +btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)), +btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)), +btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)), +btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)), +btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)), +btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)), +btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)), +btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)), +btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)), +btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)), +btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)), +btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)), +btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)), +btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)), +btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)), +btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)), +btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)), +btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)), +btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)), +btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)), +btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)), +btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)), +btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654)) +}; + + +bool SpuMinkowskiPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver, + const btConvexShape* convexA,const btConvexShape* convexB, + const btTransform& transA,const btTransform& transB, + btVector3& v, btVector3& pa, btVector3& pb, + class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc) +{ +#if 0 + (void)stackAlloc; + (void)v; + + + struct btIntermediateResult : public SpuContactResult + { + + btIntermediateResult():m_hasResult(false) + { + } + + btVector3 m_normalOnBInWorld; + btVector3 m_pointInWorld; + btScalar m_depth; + bool m_hasResult; + + virtual void setShapeIdentifiersA(int partId0,int index0) + { + (void)partId0; + (void)index0; + } + + virtual void setShapeIdentifiersB(int partId1,int index1) + { + (void)partId1; + (void)index1; + } + void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) + { + m_normalOnBInWorld = normalOnBInWorld; + m_pointInWorld = pointInWorld; + m_depth = depth; + m_hasResult = true; + } + }; + + //just take fixed number of orientation, and sample the penetration depth in that direction + btScalar minProj = btScalar(BT_LARGE_FLOAT); + btVector3 minNorm(0.f,0.f,0.f); + btVector3 minVertex; + btVector3 minA,minB; + btVector3 seperatingAxisInA,seperatingAxisInB; + btVector3 pInA,qInB,pWorld,qWorld,w; + +//#define USE_BATCHED_SUPPORT 1 +#ifdef USE_BATCHED_SUPPORT + + btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + btVector3 seperatingAxisInABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + btVector3 seperatingAxisInBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + int i; + + int numSampleDirections = NUM_UNITSPHERE_POINTS; + + for (i=0;igetNumPreferredPenetrationDirections(); + if (numPDA) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + norm = transA.getBasis() * norm; + sPenetrationDirections[numSampleDirections] = norm; + seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis(); + seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis(); + numSampleDirections++; + } + } + } + + { + int numPDB = convexB->getNumPreferredPenetrationDirections(); + if (numPDB) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + norm = transB.getBasis() * norm; + sPenetrationDirections[numSampleDirections] = norm; + seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis(); + seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis(); + numSampleDirections++; + } + } + } + + + + convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch,supportVerticesABatch,numSampleDirections); + convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch,supportVerticesBBatch,numSampleDirections); + + for (i=0;ilocalGetSupportVertexWithoutMarginNonVirtual( seperatingAxisInA);//, NULL); + qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);//, NULL); + + // pInA = convexA->localGetSupportingVertexWithoutMargin(seperatingAxisInA); + // qInB = convexB->localGetSupportingVertexWithoutMargin(seperatingAxisInB); + + pWorld = transA(pInA); + qWorld = transB(qInB); + w = qWorld - pWorld; + btScalar delta = norm.dot(w); + //find smallest delta + if (delta < minProj) + { + minProj = delta; + minNorm = norm; + minA = pWorld; + minB = qWorld; + } + } +#endif //USE_BATCHED_SUPPORT + + //add the margins + + minA += minNorm*marginA; + minB -= minNorm*marginB; + //no penetration + if (minProj < btScalar(0.)) + return false; + + minProj += (marginA + marginB) + btScalar(1.00); + + + + + +//#define DEBUG_DRAW 1 +#ifdef DEBUG_DRAW + if (debugDraw) + { + btVector3 color(0,1,0); + debugDraw->drawLine(minA,minB,color); + color = btVector3 (1,1,1); + btVector3 vec = minB-minA; + btScalar prj2 = minNorm.dot(vec); + debugDraw->drawLine(minA,minA+(minNorm*minProj),color); + + } +#endif //DEBUG_DRAW + + + btGjkPairDetector gjkdet(convexA,convexB,&simplexSolver,0); + + btScalar offsetDist = minProj; + btVector3 offset = minNorm * offsetDist; + + + SpuClosestPointInput input; + input.m_convexVertexData[0] = convexVertexDataA; + input.m_convexVertexData[1] = convexVertexDataB; + btVector3 newOrg = transA.getOrigin() + offset; + + btTransform displacedTrans = transA; + displacedTrans.setOrigin(newOrg); + + input.m_transformA = displacedTrans; + input.m_transformB = transB; + input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);//minProj; + + btIntermediateResult res; + gjkdet.getClosestPoints(input,res,0); + + btScalar correctedMinNorm = minProj - res.m_depth; + + + //the penetration depth is over-estimated, relax it + btScalar penetration_relaxation= btScalar(1.); + minNorm*=penetration_relaxation; + + if (res.m_hasResult) + { + + pa = res.m_pointInWorld - minNorm * correctedMinNorm; + pb = res.m_pointInWorld; + +#ifdef DEBUG_DRAW + if (debugDraw) + { + btVector3 color(1,0,0); + debugDraw->drawLine(pa,pb,color); + } +#endif//DEBUG_DRAW + + + } else { + // could not seperate shapes + //btAssert (false); + } + return res.m_hasResult; +#endif + return false; +} + + + diff --git a/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h new file mode 100644 index 0000000..18ad223 --- /dev/null +++ b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h @@ -0,0 +1,48 @@ + +/* +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 MINKOWSKI_PENETRATION_DEPTH_SOLVER_H +#define MINKOWSKI_PENETRATION_DEPTH_SOLVER_H + + +#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" + +class btStackAlloc; +class btIDebugDraw; +class btVoronoiSimplexSolver; +class btConvexShape; + +///MinkowskiPenetrationDepthSolver implements bruteforce penetration depth estimation. +///Implementation is based on sampling the depth using support mapping, and using GJK step to get the witness points. +class SpuMinkowskiPenetrationDepthSolver : public btConvexPenetrationDepthSolver +{ +public: + SpuMinkowskiPenetrationDepthSolver() {} + virtual ~SpuMinkowskiPenetrationDepthSolver() {}; + + virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, + const btConvexShape* convexA,const btConvexShape* convexB, + const btTransform& transA,const btTransform& transB, + btVector3& v, btVector3& pa, btVector3& pb, + class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc + ); + + +}; + + +#endif //MINKOWSKI_PENETRATION_DEPTH_SOLVER_H + diff --git a/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h new file mode 100644 index 0000000..774a0cb --- /dev/null +++ b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h @@ -0,0 +1,70 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef _SPU_PREFERRED_PENETRATION_DIRECTIONS_H +#define _SPU_PREFERRED_PENETRATION_DIRECTIONS_H + + +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" + +int spuGetNumPreferredPenetrationDirections(int shapeType, void* shape) +{ + switch (shapeType) + { + case TRIANGLE_SHAPE_PROXYTYPE: + { + return 2; + //spu_printf("2\n"); + break; + } + default: + { +#if __ASSERT + spu_printf("spuGetNumPreferredPenetrationDirections() - Unsupported bound type: %d.\n", shapeType); +#endif // __ASSERT + } + } + + return 0; +} + +void spuGetPreferredPenetrationDirection(int shapeType, void* shape, int index, btVector3& penetrationVector) +{ + + + switch (shapeType) + { + case TRIANGLE_SHAPE_PROXYTYPE: + { + btVector3* vertices = (btVector3*)shape; + ///calcNormal + penetrationVector = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]); + penetrationVector.normalize(); + if (index) + penetrationVector *= btScalar(-1.); + break; + } + default: + { + +#if __ASSERT + spu_printf("spuGetNumPreferredPenetrationDirections() - Unsupported bound type: %d.\n", shapeType); +#endif // __ASSERT + } + } + +} + +#endif //_SPU_PREFERRED_PENETRATION_DIRECTIONS_H diff --git a/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp new file mode 100644 index 0000000..5e1202c --- /dev/null +++ b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp @@ -0,0 +1,1160 @@ +/* + Copyright (C) 2006, 2008 Sony Computer Entertainment Inc. + All rights reserved. + +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 "PfxContactBoxBox.h" + +#include +#include "../PlatformDefinitions.h" +#include "boxBoxDistance.h" + +static inline float sqr( float a ) +{ + return (a * a); +} + +enum BoxSepAxisType +{ + A_AXIS, B_AXIS, CROSS_AXIS +}; + +//------------------------------------------------------------------------------------------------- +// voronoiTol: bevels Voronoi planes slightly which helps when features are parallel. +//------------------------------------------------------------------------------------------------- + +static const float voronoiTol = -1.0e-5f; + +//------------------------------------------------------------------------------------------------- +// separating axis tests: gaps along each axis are computed, and the axis with the maximum +// gap is stored. cross product axes are normalized. +//------------------------------------------------------------------------------------------------- + +#define AaxisTest( dim, letter, first ) \ +{ \ + if ( first ) \ + { \ + maxGap = gap = gapsA.get##letter(); \ + if ( gap > distanceThreshold ) return gap; \ + axisType = A_AXIS; \ + faceDimA = dim; \ + axisA = identity.getCol##dim(); \ + } \ + else \ + { \ + gap = gapsA.get##letter(); \ + if ( gap > distanceThreshold ) return gap; \ + else if ( gap > maxGap ) \ + { \ + maxGap = gap; \ + axisType = A_AXIS; \ + faceDimA = dim; \ + axisA = identity.getCol##dim(); \ + } \ + } \ +} + + +#define BaxisTest( dim, letter ) \ +{ \ + gap = gapsB.get##letter(); \ + if ( gap > distanceThreshold ) return gap; \ + else if ( gap > maxGap ) \ + { \ + maxGap = gap; \ + axisType = B_AXIS; \ + faceDimB = dim; \ + axisB = identity.getCol##dim(); \ + } \ +} + +#define CrossAxisTest( dima, dimb, letterb ) \ +{ \ + const float lsqr_tolerance = 1.0e-30f; \ + float lsqr; \ + \ + lsqr = lsqrs.getCol##dima().get##letterb(); \ + \ + if ( lsqr > lsqr_tolerance ) \ + { \ + float l_recip = 1.0f / sqrtf( lsqr ); \ + gap = float(gapsAxB.getCol##dima().get##letterb()) * l_recip; \ + \ + if ( gap > distanceThreshold ) \ + { \ + return gap; \ + } \ + \ + if ( gap > maxGap ) \ + { \ + maxGap = gap; \ + axisType = CROSS_AXIS; \ + edgeDimA = dima; \ + edgeDimB = dimb; \ + axisA = cross(identity.getCol##dima(),matrixAB.getCol##dimb()) * l_recip; \ + } \ + } \ +} + +//------------------------------------------------------------------------------------------------- +// tests whether a vertex of box B and a face of box A are the closest features +//------------------------------------------------------------------------------------------------- + +inline +float +VertexBFaceATest( + bool & inVoronoi, + float & t0, + float & t1, + const vmVector3 & hA, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsB, + PE_REF(vmVector3) scalesB ) +{ + // compute a corner of box B in A's coordinate system + + vmVector3 corner = + vmVector3( faceOffsetAB + matrixAB.getCol0() * scalesB.getX() + matrixAB.getCol1() * scalesB.getY() ); + + // compute the parameters of the point on A, closest to this corner + + t0 = corner[0]; + t1 = corner[1]; + + if ( t0 > hA[0] ) + t0 = hA[0]; + else if ( t0 < -hA[0] ) + t0 = -hA[0]; + if ( t1 > hA[1] ) + t1 = hA[1]; + else if ( t1 < -hA[1] ) + t1 = -hA[1]; + + // do the Voronoi test: already know the point on B is in the Voronoi region of the + // point on A, check the reverse. + + vmVector3 facePointB = + vmVector3( mulPerElem( faceOffsetBA + matrixBA.getCol0() * t0 + matrixBA.getCol1() * t1 - scalesB, signsB ) ); + + inVoronoi = ( ( facePointB[0] >= voronoiTol * facePointB[2] ) && + ( facePointB[1] >= voronoiTol * facePointB[0] ) && + ( facePointB[2] >= voronoiTol * facePointB[1] ) ); + + return (sqr( corner[0] - t0 ) + sqr( corner[1] - t1 ) + sqr( corner[2] )); +} + +#define VertexBFaceA_SetNewMin() \ +{ \ + minDistSqr = distSqr; \ + localPointA.setX(t0); \ + localPointA.setY(t1); \ + localPointB.setX( scalesB.getX() ); \ + localPointB.setY( scalesB.getY() ); \ + featureA = F; \ + featureB = V; \ +} + +void +VertexBFaceATests( + bool & done, + float & minDistSqr, + vmPoint3 & localPointA, + vmPoint3 & localPointB, + FeatureType & featureA, + FeatureType & featureB, + const vmVector3 & hA, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsB, + PE_REF(vmVector3) scalesB, + bool first ) +{ + + float t0, t1; + float distSqr; + + distSqr = VertexBFaceATest( done, t0, t1, hA, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsB, scalesB ); + + if ( first ) { + VertexBFaceA_SetNewMin(); + } else { + if ( distSqr < minDistSqr ) { + VertexBFaceA_SetNewMin(); + } + } + + if ( done ) + return; + + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = VertexBFaceATest( done, t0, t1, hA, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsB, scalesB ); + + if ( distSqr < minDistSqr ) { + VertexBFaceA_SetNewMin(); + } + + if ( done ) + return; + + signsB.setY( -signsB.getY() ); + scalesB.setY( -scalesB.getY() ); + + distSqr = VertexBFaceATest( done, t0, t1, hA, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsB, scalesB ); + + if ( distSqr < minDistSqr ) { + VertexBFaceA_SetNewMin(); + } + + if ( done ) + return; + + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = VertexBFaceATest( done, t0, t1, hA, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsB, scalesB ); + + if ( distSqr < minDistSqr ) { + VertexBFaceA_SetNewMin(); + } +} + +//------------------------------------------------------------------------------------------------- +// VertexAFaceBTest: tests whether a vertex of box A and a face of box B are the closest features +//------------------------------------------------------------------------------------------------- + +inline +float +VertexAFaceBTest( + bool & inVoronoi, + float & t0, + float & t1, + const vmVector3 & hB, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsA, + PE_REF(vmVector3) scalesA ) +{ + vmVector3 corner = + vmVector3( faceOffsetBA + matrixBA.getCol0() * scalesA.getX() + matrixBA.getCol1() * scalesA.getY() ); + + t0 = corner[0]; + t1 = corner[1]; + + if ( t0 > hB[0] ) + t0 = hB[0]; + else if ( t0 < -hB[0] ) + t0 = -hB[0]; + if ( t1 > hB[1] ) + t1 = hB[1]; + else if ( t1 < -hB[1] ) + t1 = -hB[1]; + + vmVector3 facePointA = + vmVector3( mulPerElem( faceOffsetAB + matrixAB.getCol0() * t0 + matrixAB.getCol1() * t1 - scalesA, signsA ) ); + + inVoronoi = ( ( facePointA[0] >= voronoiTol * facePointA[2] ) && + ( facePointA[1] >= voronoiTol * facePointA[0] ) && + ( facePointA[2] >= voronoiTol * facePointA[1] ) ); + + return (sqr( corner[0] - t0 ) + sqr( corner[1] - t1 ) + sqr( corner[2] )); +} + +#define VertexAFaceB_SetNewMin() \ +{ \ + minDistSqr = distSqr; \ + localPointB.setX(t0); \ + localPointB.setY(t1); \ + localPointA.setX( scalesA.getX() ); \ + localPointA.setY( scalesA.getY() ); \ + featureA = V; \ + featureB = F; \ +} + +void +VertexAFaceBTests( + bool & done, + float & minDistSqr, + vmPoint3 & localPointA, + vmPoint3 & localPointB, + FeatureType & featureA, + FeatureType & featureB, + const vmVector3 & hB, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsA, + PE_REF(vmVector3) scalesA, + bool first ) +{ + float t0, t1; + float distSqr; + + distSqr = VertexAFaceBTest( done, t0, t1, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, scalesA ); + + if ( first ) { + VertexAFaceB_SetNewMin(); + } else { + if ( distSqr < minDistSqr ) { + VertexAFaceB_SetNewMin(); + } + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = VertexAFaceBTest( done, t0, t1, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, scalesA ); + + if ( distSqr < minDistSqr ) { + VertexAFaceB_SetNewMin(); + } + + if ( done ) + return; + + signsA.setY( -signsA.getY() ); + scalesA.setY( -scalesA.getY() ); + + distSqr = VertexAFaceBTest( done, t0, t1, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, scalesA ); + + if ( distSqr < minDistSqr ) { + VertexAFaceB_SetNewMin(); + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = VertexAFaceBTest( done, t0, t1, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, scalesA ); + + if ( distSqr < minDistSqr ) { + VertexAFaceB_SetNewMin(); + } +} + +//------------------------------------------------------------------------------------------------- +// CustomEdgeEdgeTest: +// +// tests whether a pair of edges are the closest features +// +// note on the shorthand: +// 'a' & 'b' refer to the edges. +// 'c' is the dimension of the axis that points from the face center to the edge Center +// 'd' is the dimension of the edge Direction +// the dimension of the face normal is 2 +//------------------------------------------------------------------------------------------------- + +#define CustomEdgeEdgeTest( ac, ac_letter, ad, ad_letter, bc, bc_letter, bd, bd_letter ) \ +{ \ + vmVector3 edgeOffsetAB; \ + vmVector3 edgeOffsetBA; \ + \ + edgeOffsetAB = faceOffsetAB + matrixAB.getCol##bc() * scalesB.get##bc_letter(); \ + edgeOffsetAB.set##ac_letter( edgeOffsetAB.get##ac_letter() - scalesA.get##ac_letter() ); \ + \ + edgeOffsetBA = faceOffsetBA + matrixBA.getCol##ac() * scalesA.get##ac_letter(); \ + edgeOffsetBA.set##bc_letter( edgeOffsetBA.get##bc_letter() - scalesB.get##bc_letter() ); \ + \ + float dirDot = matrixAB.getCol##bd().get##ad_letter(); \ + float denom = 1.0f - dirDot*dirDot; \ + float edgeOffsetAB_ad = edgeOffsetAB.get##ad_letter(); \ + float edgeOffsetBA_bd = edgeOffsetBA.get##bd_letter(); \ + \ + if ( denom == 0.0f ) \ + { \ + tA = 0.0f; \ + } \ + else \ + { \ + tA = ( edgeOffsetAB_ad + edgeOffsetBA_bd * dirDot ) / denom; \ + } \ + \ + if ( tA < -hA[ad] ) tA = -hA[ad]; \ + else if ( tA > hA[ad] ) tA = hA[ad]; \ + \ + tB = tA * dirDot + edgeOffsetBA_bd; \ + \ + if ( tB < -hB[bd] ) \ + { \ + tB = -hB[bd]; \ + tA = tB * dirDot + edgeOffsetAB_ad; \ + \ + if ( tA < -hA[ad] ) tA = -hA[ad]; \ + else if ( tA > hA[ad] ) tA = hA[ad]; \ + } \ + else if ( tB > hB[bd] ) \ + { \ + tB = hB[bd]; \ + tA = tB * dirDot + edgeOffsetAB_ad; \ + \ + if ( tA < -hA[ad] ) tA = -hA[ad]; \ + else if ( tA > hA[ad] ) tA = hA[ad]; \ + } \ + \ + vmVector3 edgeOffAB = vmVector3( mulPerElem( edgeOffsetAB + matrixAB.getCol##bd() * tB, signsA ) );\ + vmVector3 edgeOffBA = vmVector3( mulPerElem( edgeOffsetBA + matrixBA.getCol##ad() * tA, signsB ) );\ + \ + inVoronoi = ( edgeOffAB[ac] >= voronoiTol * edgeOffAB[2] ) && \ + ( edgeOffAB[2] >= voronoiTol * edgeOffAB[ac] ) && \ + ( edgeOffBA[bc] >= voronoiTol * edgeOffBA[2] ) && \ + ( edgeOffBA[2] >= voronoiTol * edgeOffBA[bc] ); \ + \ + edgeOffAB[ad] -= tA; \ + edgeOffBA[bd] -= tB; \ + \ + return dot(edgeOffAB,edgeOffAB); \ +} + +float +CustomEdgeEdgeTest_0101( + bool & inVoronoi, + float & tA, + float & tB, + const vmVector3 & hA, + const vmVector3 & hB, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsA, + PE_REF(vmVector3) signsB, + PE_REF(vmVector3) scalesA, + PE_REF(vmVector3) scalesB ) +{ + CustomEdgeEdgeTest( 0, X, 1, Y, 0, X, 1, Y ); +} + +float +CustomEdgeEdgeTest_0110( + bool & inVoronoi, + float & tA, + float & tB, + const vmVector3 & hA, + const vmVector3 & hB, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsA, + PE_REF(vmVector3) signsB, + PE_REF(vmVector3) scalesA, + PE_REF(vmVector3) scalesB ) +{ + CustomEdgeEdgeTest( 0, X, 1, Y, 1, Y, 0, X ); +} + +float +CustomEdgeEdgeTest_1001( + bool & inVoronoi, + float & tA, + float & tB, + const vmVector3 & hA, + const vmVector3 & hB, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsA, + PE_REF(vmVector3) signsB, + PE_REF(vmVector3) scalesA, + PE_REF(vmVector3) scalesB ) +{ + CustomEdgeEdgeTest( 1, Y, 0, X, 0, X, 1, Y ); +} + +float +CustomEdgeEdgeTest_1010( + bool & inVoronoi, + float & tA, + float & tB, + const vmVector3 & hA, + const vmVector3 & hB, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsA, + PE_REF(vmVector3) signsB, + PE_REF(vmVector3) scalesA, + PE_REF(vmVector3) scalesB ) +{ + CustomEdgeEdgeTest( 1, Y, 0, X, 1, Y, 0, X ); +} + +#define EdgeEdge_SetNewMin( ac_letter, ad_letter, bc_letter, bd_letter ) \ +{ \ + minDistSqr = distSqr; \ + localPointA.set##ac_letter(scalesA.get##ac_letter()); \ + localPointA.set##ad_letter(tA); \ + localPointB.set##bc_letter(scalesB.get##bc_letter()); \ + localPointB.set##bd_letter(tB); \ + otherFaceDimA = testOtherFaceDimA; \ + otherFaceDimB = testOtherFaceDimB; \ + featureA = E; \ + featureB = E; \ +} + +void +EdgeEdgeTests( + bool & done, + float & minDistSqr, + vmPoint3 & localPointA, + vmPoint3 & localPointB, + int & otherFaceDimA, + int & otherFaceDimB, + FeatureType & featureA, + FeatureType & featureB, + const vmVector3 & hA, + const vmVector3 & hB, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsA, + PE_REF(vmVector3) signsB, + PE_REF(vmVector3) scalesA, + PE_REF(vmVector3) scalesB, + bool first ) +{ + + float distSqr; + float tA, tB; + + int testOtherFaceDimA, testOtherFaceDimB; + + testOtherFaceDimA = 0; + testOtherFaceDimB = 0; + + distSqr = CustomEdgeEdgeTest_0101( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( first ) { + EdgeEdge_SetNewMin( X, Y, X, Y ); + } else { + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, X, Y ); + } + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = CustomEdgeEdgeTest_0101( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, X, Y ); + } + + if ( done ) + return; + + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = CustomEdgeEdgeTest_0101( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, X, Y ); + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = CustomEdgeEdgeTest_0101( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, X, Y ); + } + + if ( done ) + return; + + testOtherFaceDimA = 1; + testOtherFaceDimB = 0; + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = CustomEdgeEdgeTest_1001( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, X, Y ); + } + + if ( done ) + return; + + signsA.setY( -signsA.getY() ); + scalesA.setY( -scalesA.getY() ); + + distSqr = CustomEdgeEdgeTest_1001( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, X, Y ); + } + + if ( done ) + return; + + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = CustomEdgeEdgeTest_1001( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, X, Y ); + } + + if ( done ) + return; + + signsA.setY( -signsA.getY() ); + scalesA.setY( -scalesA.getY() ); + + distSqr = CustomEdgeEdgeTest_1001( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, X, Y ); + } + + if ( done ) + return; + + testOtherFaceDimA = 0; + testOtherFaceDimB = 1; + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = CustomEdgeEdgeTest_0110( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, Y, X ); + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = CustomEdgeEdgeTest_0110( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, Y, X ); + } + + if ( done ) + return; + + signsB.setY( -signsB.getY() ); + scalesB.setY( -scalesB.getY() ); + + distSqr = CustomEdgeEdgeTest_0110( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, Y, X ); + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = CustomEdgeEdgeTest_0110( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, Y, X ); + } + + if ( done ) + return; + + testOtherFaceDimA = 1; + testOtherFaceDimB = 1; + signsB.setY( -signsB.getY() ); + scalesB.setY( -scalesB.getY() ); + + distSqr = CustomEdgeEdgeTest_1010( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, Y, X ); + } + + if ( done ) + return; + + signsA.setY( -signsA.getY() ); + scalesA.setY( -scalesA.getY() ); + + distSqr = CustomEdgeEdgeTest_1010( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, Y, X ); + } + + if ( done ) + return; + + signsB.setY( -signsB.getY() ); + scalesB.setY( -scalesB.getY() ); + + distSqr = CustomEdgeEdgeTest_1010( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, Y, X ); + } + + if ( done ) + return; + + signsA.setY( -signsA.getY() ); + scalesA.setY( -scalesA.getY() ); + + distSqr = CustomEdgeEdgeTest_1010( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, Y, X ); + } +} + + +float +boxBoxDistance(vmVector3& normal, BoxPoint& boxPointA, BoxPoint& boxPointB, + PE_REF(Box) boxA, const vmTransform3 & transformA, PE_REF(Box) boxB, + const vmTransform3 & transformB, + float distanceThreshold) +{ + vmMatrix3 identity; + identity = vmMatrix3::identity(); + vmVector3 ident[3]; + ident[0] = identity.getCol0(); + ident[1] = identity.getCol1(); + ident[2] = identity.getCol2(); + + // get relative transformations + + vmTransform3 transformAB, transformBA; + vmMatrix3 matrixAB, matrixBA; + vmVector3 offsetAB, offsetBA; + + transformAB = orthoInverse(transformA) * transformB; + transformBA = orthoInverse(transformAB); + + matrixAB = transformAB.getUpper3x3(); + offsetAB = transformAB.getTranslation(); + matrixBA = transformBA.getUpper3x3(); + offsetBA = transformBA.getTranslation(); + + vmMatrix3 absMatrixAB = absPerElem(matrixAB); + vmMatrix3 absMatrixBA = absPerElem(matrixBA); + + // find separating axis with largest gap between projections + + BoxSepAxisType axisType; + vmVector3 axisA(0.0f), axisB(0.0f); + float gap, maxGap; + int faceDimA = 0, faceDimB = 0, edgeDimA = 0, edgeDimB = 0; + + // face axes + + vmVector3 gapsA = absPerElem(offsetAB) - boxA.mHalf - absMatrixAB * boxB.mHalf; + + AaxisTest(0,X,true); + AaxisTest(1,Y,false); + AaxisTest(2,Z,false); + + vmVector3 gapsB = absPerElem(offsetBA) - boxB.mHalf - absMatrixBA * boxA.mHalf; + + BaxisTest(0,X); + BaxisTest(1,Y); + BaxisTest(2,Z); + + // cross product axes + + // ŠOÏ‚ª‚O‚Ì‚Æ‚«‚̑΍ô + absMatrixAB += vmMatrix3(1.0e-5f); + absMatrixBA += vmMatrix3(1.0e-5f); + + vmMatrix3 lsqrs, projOffset, projAhalf, projBhalf; + + lsqrs.setCol0( mulPerElem( matrixBA.getCol2(), matrixBA.getCol2() ) + + mulPerElem( matrixBA.getCol1(), matrixBA.getCol1() ) ); + lsqrs.setCol1( mulPerElem( matrixBA.getCol2(), matrixBA.getCol2() ) + + mulPerElem( matrixBA.getCol0(), matrixBA.getCol0() ) ); + lsqrs.setCol2( mulPerElem( matrixBA.getCol1(), matrixBA.getCol1() ) + + mulPerElem( matrixBA.getCol0(), matrixBA.getCol0() ) ); + + projOffset.setCol0(matrixBA.getCol1() * offsetAB.getZ() - matrixBA.getCol2() * offsetAB.getY()); + projOffset.setCol1(matrixBA.getCol2() * offsetAB.getX() - matrixBA.getCol0() * offsetAB.getZ()); + projOffset.setCol2(matrixBA.getCol0() * offsetAB.getY() - matrixBA.getCol1() * offsetAB.getX()); + + projAhalf.setCol0(absMatrixBA.getCol1() * boxA.mHalf.getZ() + absMatrixBA.getCol2() * boxA.mHalf.getY()); + projAhalf.setCol1(absMatrixBA.getCol2() * boxA.mHalf.getX() + absMatrixBA.getCol0() * boxA.mHalf.getZ()); + projAhalf.setCol2(absMatrixBA.getCol0() * boxA.mHalf.getY() + absMatrixBA.getCol1() * boxA.mHalf.getX()); + + projBhalf.setCol0(absMatrixAB.getCol1() * boxB.mHalf.getZ() + absMatrixAB.getCol2() * boxB.mHalf.getY()); + projBhalf.setCol1(absMatrixAB.getCol2() * boxB.mHalf.getX() + absMatrixAB.getCol0() * boxB.mHalf.getZ()); + projBhalf.setCol2(absMatrixAB.getCol0() * boxB.mHalf.getY() + absMatrixAB.getCol1() * boxB.mHalf.getX()); + + vmMatrix3 gapsAxB = absPerElem(projOffset) - projAhalf - transpose(projBhalf); + + CrossAxisTest(0,0,X); + CrossAxisTest(0,1,Y); + CrossAxisTest(0,2,Z); + CrossAxisTest(1,0,X); + CrossAxisTest(1,1,Y); + CrossAxisTest(1,2,Z); + CrossAxisTest(2,0,X); + CrossAxisTest(2,1,Y); + CrossAxisTest(2,2,Z); + + // need to pick the face on each box whose normal best matches the separating axis. + // will transform vectors to be in the coordinate system of this face to simplify things later. + // for this, a permutation matrix can be used, which the next section computes. + + int dimA[3], dimB[3]; + + if ( axisType == A_AXIS ) { + if ( dot(axisA,offsetAB) < 0.0f ) + axisA = -axisA; + axisB = matrixBA * -axisA; + + vmVector3 absAxisB = vmVector3(absPerElem(axisB)); + + if ( ( absAxisB[0] > absAxisB[1] ) && ( absAxisB[0] > absAxisB[2] ) ) + faceDimB = 0; + else if ( absAxisB[1] > absAxisB[2] ) + faceDimB = 1; + else + faceDimB = 2; + } else if ( axisType == B_AXIS ) { + if ( dot(axisB,offsetBA) < 0.0f ) + axisB = -axisB; + axisA = matrixAB * -axisB; + + vmVector3 absAxisA = vmVector3(absPerElem(axisA)); + + if ( ( absAxisA[0] > absAxisA[1] ) && ( absAxisA[0] > absAxisA[2] ) ) + faceDimA = 0; + else if ( absAxisA[1] > absAxisA[2] ) + faceDimA = 1; + else + faceDimA = 2; + } + + if ( axisType == CROSS_AXIS ) { + if ( dot(axisA,offsetAB) < 0.0f ) + axisA = -axisA; + axisB = matrixBA * -axisA; + + vmVector3 absAxisA = vmVector3(absPerElem(axisA)); + vmVector3 absAxisB = vmVector3(absPerElem(axisB)); + + dimA[1] = edgeDimA; + dimB[1] = edgeDimB; + + if ( edgeDimA == 0 ) { + if ( absAxisA[1] > absAxisA[2] ) { + dimA[0] = 2; + dimA[2] = 1; + } else { + dimA[0] = 1; + dimA[2] = 2; + } + } else if ( edgeDimA == 1 ) { + if ( absAxisA[2] > absAxisA[0] ) { + dimA[0] = 0; + dimA[2] = 2; + } else { + dimA[0] = 2; + dimA[2] = 0; + } + } else { + if ( absAxisA[0] > absAxisA[1] ) { + dimA[0] = 1; + dimA[2] = 0; + } else { + dimA[0] = 0; + dimA[2] = 1; + } + } + + if ( edgeDimB == 0 ) { + if ( absAxisB[1] > absAxisB[2] ) { + dimB[0] = 2; + dimB[2] = 1; + } else { + dimB[0] = 1; + dimB[2] = 2; + } + } else if ( edgeDimB == 1 ) { + if ( absAxisB[2] > absAxisB[0] ) { + dimB[0] = 0; + dimB[2] = 2; + } else { + dimB[0] = 2; + dimB[2] = 0; + } + } else { + if ( absAxisB[0] > absAxisB[1] ) { + dimB[0] = 1; + dimB[2] = 0; + } else { + dimB[0] = 0; + dimB[2] = 1; + } + } + } else { + dimA[2] = faceDimA; + dimA[0] = (faceDimA+1)%3; + dimA[1] = (faceDimA+2)%3; + dimB[2] = faceDimB; + dimB[0] = (faceDimB+1)%3; + dimB[1] = (faceDimB+2)%3; + } + + vmMatrix3 aperm_col, bperm_col; + + aperm_col.setCol0(ident[dimA[0]]); + aperm_col.setCol1(ident[dimA[1]]); + aperm_col.setCol2(ident[dimA[2]]); + + bperm_col.setCol0(ident[dimB[0]]); + bperm_col.setCol1(ident[dimB[1]]); + bperm_col.setCol2(ident[dimB[2]]); + + vmMatrix3 aperm_row, bperm_row; + + aperm_row = transpose(aperm_col); + bperm_row = transpose(bperm_col); + + // permute all box parameters to be in the face coordinate systems + + vmMatrix3 matrixAB_perm = aperm_row * matrixAB * bperm_col; + vmMatrix3 matrixBA_perm = transpose(matrixAB_perm); + + vmVector3 offsetAB_perm, offsetBA_perm; + + offsetAB_perm = aperm_row * offsetAB; + offsetBA_perm = bperm_row * offsetBA; + + vmVector3 halfA_perm, halfB_perm; + + halfA_perm = aperm_row * boxA.mHalf; + halfB_perm = bperm_row * boxB.mHalf; + + // compute the vector between the centers of each face, in each face's coordinate frame + + vmVector3 signsA_perm, signsB_perm, scalesA_perm, scalesB_perm, faceOffsetAB_perm, faceOffsetBA_perm; + + signsA_perm = copySignPerElem(vmVector3(1.0f),aperm_row * axisA); + signsB_perm = copySignPerElem(vmVector3(1.0f),bperm_row * axisB); + scalesA_perm = mulPerElem( signsA_perm, halfA_perm ); + scalesB_perm = mulPerElem( signsB_perm, halfB_perm ); + + faceOffsetAB_perm = offsetAB_perm + matrixAB_perm.getCol2() * scalesB_perm.getZ(); + faceOffsetAB_perm.setZ( faceOffsetAB_perm.getZ() - scalesA_perm.getZ() ); + + faceOffsetBA_perm = offsetBA_perm + matrixBA_perm.getCol2() * scalesA_perm.getZ(); + faceOffsetBA_perm.setZ( faceOffsetBA_perm.getZ() - scalesB_perm.getZ() ); + + if ( maxGap < 0.0f ) { + // if boxes overlap, this will separate the faces for finding points of penetration. + + faceOffsetAB_perm -= aperm_row * axisA * maxGap * 1.01f; + faceOffsetBA_perm -= bperm_row * axisB * maxGap * 1.01f; + } + + // for each vertex/face or edge/edge pair of the two faces, find the closest points. + // + // these points each have an associated box feature (vertex, edge, or face). if each + // point is in the external Voronoi region of the other's feature, they are the + // closest points of the boxes, and the algorithm can exit. + // + // the feature pairs are arranged so that in the general case, the first test will + // succeed. degenerate cases (parallel faces) may require up to all tests in the + // worst case. + // + // if for some reason no case passes the Voronoi test, the features with the minimum + // distance are returned. + + vmPoint3 localPointA_perm, localPointB_perm; + float minDistSqr; + bool done; + + vmVector3 hA_perm( halfA_perm ), hB_perm( halfB_perm ); + + localPointA_perm.setZ( scalesA_perm.getZ() ); + localPointB_perm.setZ( scalesB_perm.getZ() ); + scalesA_perm.setZ(0.0f); + scalesB_perm.setZ(0.0f); + + int otherFaceDimA, otherFaceDimB; + FeatureType featureA, featureB; + + if ( axisType == CROSS_AXIS ) { + EdgeEdgeTests( done, minDistSqr, localPointA_perm, localPointB_perm, + otherFaceDimA, otherFaceDimB, featureA, featureB, + hA_perm, hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, signsB_perm, + scalesA_perm, scalesB_perm, true ); + + if ( !done ) { + VertexBFaceATests( done, minDistSqr, localPointA_perm, localPointB_perm, + featureA, featureB, + hA_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsB_perm, scalesB_perm, false ); + + if ( !done ) { + VertexAFaceBTests( done, minDistSqr, localPointA_perm, localPointB_perm, + featureA, featureB, + hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, scalesA_perm, false ); + } + } + } else if ( axisType == B_AXIS ) { + VertexAFaceBTests( done, minDistSqr, localPointA_perm, localPointB_perm, + featureA, featureB, + hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, scalesA_perm, true ); + + if ( !done ) { + VertexBFaceATests( done, minDistSqr, localPointA_perm, localPointB_perm, + featureA, featureB, + hA_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsB_perm, scalesB_perm, false ); + + if ( !done ) { + EdgeEdgeTests( done, minDistSqr, localPointA_perm, localPointB_perm, + otherFaceDimA, otherFaceDimB, featureA, featureB, + hA_perm, hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, signsB_perm, + scalesA_perm, scalesB_perm, false ); + } + } + } else { + VertexBFaceATests( done, minDistSqr, localPointA_perm, localPointB_perm, + featureA, featureB, + hA_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsB_perm, scalesB_perm, true ); + + if ( !done ) { + VertexAFaceBTests( done, minDistSqr, localPointA_perm, localPointB_perm, + featureA, featureB, + hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, scalesA_perm, false ); + + if ( !done ) { + EdgeEdgeTests( done, minDistSqr, localPointA_perm, localPointB_perm, + otherFaceDimA, otherFaceDimB, featureA, featureB, + hA_perm, hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, signsB_perm, + scalesA_perm, scalesB_perm, false ); + } + } + } + + // convert local points from face-local to box-local coordinate system + + + boxPointA.localPoint = vmPoint3( aperm_col * vmVector3( localPointA_perm )) ; + boxPointB.localPoint = vmPoint3( bperm_col * vmVector3( localPointB_perm )) ; + +#if 0 + // find which features of the boxes are involved. + // the only feature pairs which occur in this function are VF, FV, and EE, even though the + // closest points might actually lie on sub-features, as in a VF contact might be used for + // what's actually a VV contact. this means some feature pairs could possibly seem distinct + // from others, although their contact positions are the same. don't know yet whether this + // matters. + + int sA[3], sB[3]; + + sA[0] = boxPointA.localPoint.getX() > 0.0f; + sA[1] = boxPointA.localPoint.getY() > 0.0f; + sA[2] = boxPointA.localPoint.getZ() > 0.0f; + + sB[0] = boxPointB.localPoint.getX() > 0.0f; + sB[1] = boxPointB.localPoint.getY() > 0.0f; + sB[2] = boxPointB.localPoint.getZ() > 0.0f; + + if ( featureA == F ) { + boxPointA.setFaceFeature( dimA[2], sA[dimA[2]] ); + } else if ( featureA == E ) { + boxPointA.setEdgeFeature( dimA[2], sA[dimA[2]], dimA[otherFaceDimA], sA[dimA[otherFaceDimA]] ); + } else { + boxPointA.setVertexFeature( sA[0], sA[1], sA[2] ); + } + + if ( featureB == F ) { + boxPointB.setFaceFeature( dimB[2], sB[dimB[2]] ); + } else if ( featureB == E ) { + boxPointB.setEdgeFeature( dimB[2], sB[dimB[2]], dimB[otherFaceDimB], sB[dimB[otherFaceDimB]] ); + } else { + boxPointB.setVertexFeature( sB[0], sB[1], sB[2] ); + } +#endif + + normal = transformA * axisA; + + if ( maxGap < 0.0f ) { + return (maxGap); + } else { + return (sqrtf( minDistSqr )); + } +} diff --git a/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h new file mode 100644 index 0000000..0d4957d --- /dev/null +++ b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 2006, 2008 Sony Computer Entertainment Inc. + All rights reserved. + +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 __BOXBOXDISTANCE_H__ +#define __BOXBOXDISTANCE_H__ + + +#include "Box.h" + + +//--------------------------------------------------------------------------- +// boxBoxDistance: +// +// description: +// this computes info that can be used for the collision response of two boxes. when the boxes +// do not overlap, the points are set to the closest points of the boxes, and a positive +// distance between them is returned. if the boxes do overlap, a negative distance is returned +// and the points are set to two points that would touch after the boxes are translated apart. +// the contact normal gives the direction to repel or separate the boxes when they touch or +// overlap (it's being approximated here as one of the 15 "separating axis" directions). +// +// returns: +// positive or negative distance between two boxes. +// +// args: +// vmVector3& normal: set to a unit contact normal pointing from box A to box B. +// +// BoxPoint& boxPointA, BoxPoint& boxPointB: +// set to a closest point or point of penetration on each box. +// +// Box boxA, Box boxB: +// boxes, represented as 3 half-widths +// +// const vmTransform3& transformA, const vmTransform3& transformB: +// box transformations, in world coordinates +// +// float distanceThreshold: +// the algorithm will exit early if it finds that the boxes are more distant than this +// threshold, and not compute a contact normal or points. if this distance returned +// exceeds the threshold, all the other output data may not have been computed. by +// default, this is set to MAX_FLOAT so it will have no effect. +// +//--------------------------------------------------------------------------- + +float +boxBoxDistance(vmVector3& normal, BoxPoint& boxPointA, BoxPoint& boxPointB, + PE_REF(Box) boxA, const vmTransform3 & transformA, PE_REF(Box) boxB, + const vmTransform3 & transformB, + float distanceThreshold = FLT_MAX ); + +#endif /* __BOXBOXDISTANCE_H__ */ diff --git a/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt new file mode 100644 index 0000000..5b4a907 --- /dev/null +++ b/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt @@ -0,0 +1 @@ +Empty placeholder for future Libspe2 SPU task diff --git a/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp b/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp new file mode 100644 index 0000000..fe61955 --- /dev/null +++ b/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp @@ -0,0 +1,214 @@ +/* +Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans + +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 "SpuSampleTask.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "../PlatformDefinitions.h" +#include "../SpuFakeDma.h" +#include "LinearMath/btMinMax.h" + +#ifdef __SPU__ +#include +#else +#include +#define spu_printf printf +#endif + +#define MAX_NUM_BODIES 8192 + +struct SampleTask_LocalStoreMemory +{ + ATTRIBUTE_ALIGNED16(char gLocalRigidBody [sizeof(btRigidBody)+16]); + ATTRIBUTE_ALIGNED16(void* gPointerArray[MAX_NUM_BODIES]); + +}; + + + + +//-- MAIN METHOD +void processSampleTask(void* userPtr, void* lsMemory) +{ + // BT_PROFILE("processSampleTask"); + + SampleTask_LocalStoreMemory* localMemory = (SampleTask_LocalStoreMemory*)lsMemory; + + SpuSampleTaskDesc* taskDescPtr = (SpuSampleTaskDesc*)userPtr; + SpuSampleTaskDesc& taskDesc = *taskDescPtr; + + switch (taskDesc.m_sampleCommand) + { + case CMD_SAMPLE_INTEGRATE_BODIES: + { + btTransform predictedTrans; + btCollisionObject** eaPtr = (btCollisionObject**)taskDesc.m_mainMemoryPtr; + + int batchSize = taskDesc.m_sampleValue; + if (batchSize>MAX_NUM_BODIES) + { + spu_printf("SPU Error: exceed number of bodies, see MAX_NUM_BODIES in SpuSampleTask.cpp\n"); + break; + } + int dmaArraySize = batchSize*sizeof(void*); + + uint64_t ppuArrayAddress = reinterpret_cast(eaPtr); + + // spu_printf("array location is at %llx, batchSize = %d, DMA size = %d\n",ppuArrayAddress,batchSize,dmaArraySize); + + if (dmaArraySize>=16) + { + cellDmaLargeGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize, DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + } else + { + stallingUnalignedDmaSmallGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize); + } + + + for ( int i=0;igLocalRigidBody[0]; + void* shortAdd = localMemory->gPointerArray[i]; + uint64_t ppuRigidBodyAddress = reinterpret_cast(shortAdd); + + // spu_printf("cellDmaGet at CMD_SAMPLE_INTEGRATE_BODIES from %llx to %llx\n",ppuRigidBodyAddress,localPtr); + + int dmaBodySize = sizeof(btRigidBody); + + cellDmaGet((void*)localPtr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + + float timeStep = 1.f/60.f; + + btRigidBody* body = (btRigidBody*) localPtr;//btRigidBody::upcast(colObj); + if (body) + { + if (body->isActive() && (!body->isStaticOrKinematicObject())) + { + body->predictIntegratedTransform(timeStep, predictedTrans); + body->proceedToTransform( predictedTrans); + void* ptr = (void*)localPtr; + // spu_printf("cellDmaLargePut from %llx to LS %llx\n",ptr,ppuRigidBodyAddress); + + cellDmaLargePut(ptr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + } + } + + } + break; + } + + + case CMD_SAMPLE_PREDICT_MOTION_BODIES: + { + btTransform predictedTrans; + btCollisionObject** eaPtr = (btCollisionObject**)taskDesc.m_mainMemoryPtr; + + int batchSize = taskDesc.m_sampleValue; + int dmaArraySize = batchSize*sizeof(void*); + + if (batchSize>MAX_NUM_BODIES) + { + spu_printf("SPU Error: exceed number of bodies, see MAX_NUM_BODIES in SpuSampleTask.cpp\n"); + break; + } + + uint64_t ppuArrayAddress = reinterpret_cast(eaPtr); + + // spu_printf("array location is at %llx, batchSize = %d, DMA size = %d\n",ppuArrayAddress,batchSize,dmaArraySize); + + if (dmaArraySize>=16) + { + cellDmaLargeGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize, DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + } else + { + stallingUnalignedDmaSmallGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize); + } + + + for ( int i=0;igLocalRigidBody[0]; + void* shortAdd = localMemory->gPointerArray[i]; + uint64_t ppuRigidBodyAddress = reinterpret_cast(shortAdd); + + // spu_printf("cellDmaGet at CMD_SAMPLE_INTEGRATE_BODIES from %llx to %llx\n",ppuRigidBodyAddress,localPtr); + + int dmaBodySize = sizeof(btRigidBody); + + cellDmaGet((void*)localPtr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + + float timeStep = 1.f/60.f; + + btRigidBody* body = (btRigidBody*) localPtr;//btRigidBody::upcast(colObj); + if (body) + { + if (!body->isStaticOrKinematicObject()) + { + if (body->isActive()) + { + body->integrateVelocities( timeStep); + //damping + body->applyDamping(timeStep); + + body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); + + void* ptr = (void*)localPtr; + cellDmaLargePut(ptr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + } + } + } + + } + break; + } + + + + default: + { + + } + }; +} + + +#if defined(__CELLOS_LV2__) || defined (LIBSPE2) + +ATTRIBUTE_ALIGNED16(SampleTask_LocalStoreMemory gLocalStoreMemory); + +void* createSampleLocalStoreMemory() +{ + return &gLocalStoreMemory; +} +#else +void* createSampleLocalStoreMemory() +{ + return new SampleTask_LocalStoreMemory; +}; + +#endif diff --git a/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h b/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h new file mode 100644 index 0000000..c8ebdfd --- /dev/null +++ b/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h @@ -0,0 +1,54 @@ +/* +Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans + +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 SPU_SAMPLE_TASK_H +#define SPU_SAMPLE_TASK_H + +#include "../PlatformDefinitions.h" +#include "LinearMath/btScalar.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" + +#include "LinearMath/btAlignedAllocator.h" + + +enum +{ + CMD_SAMPLE_INTEGRATE_BODIES = 1, + CMD_SAMPLE_PREDICT_MOTION_BODIES +}; + + + +ATTRIBUTE_ALIGNED16(struct) SpuSampleTaskDesc +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + uint32_t m_sampleCommand; + uint32_t m_taskId; + + uint64_t m_mainMemoryPtr; + int m_sampleValue; + + +}; + + +void processSampleTask(void* userPtr, void* lsMemory); +void* createSampleLocalStoreMemory(); + + +#endif //SPU_SAMPLE_TASK_H + diff --git a/src/BulletMultiThreaded/SpuSampleTask/readme.txt b/src/BulletMultiThreaded/SpuSampleTask/readme.txt new file mode 100644 index 0000000..5b4a907 --- /dev/null +++ b/src/BulletMultiThreaded/SpuSampleTask/readme.txt @@ -0,0 +1 @@ +Empty placeholder for future Libspe2 SPU task diff --git a/src/BulletMultiThreaded/SpuSampleTaskProcess.cpp b/src/BulletMultiThreaded/SpuSampleTaskProcess.cpp new file mode 100644 index 0000000..11cb9e7 --- /dev/null +++ b/src/BulletMultiThreaded/SpuSampleTaskProcess.cpp @@ -0,0 +1,222 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +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. +*/ + +//#define __CELLOS_LV2__ 1 + +#define USE_SAMPLE_PROCESS 1 +#ifdef USE_SAMPLE_PROCESS + + +#include "SpuSampleTaskProcess.h" +#include + +#ifdef __SPU__ + + + +void SampleThreadFunc(void* userPtr,void* lsMemory) +{ + //do nothing + printf("hello world\n"); +} + + +void* SamplelsMemoryFunc() +{ + //don't create local store memory, just return 0 + return 0; +} + + +#else + + +#include "btThreadSupportInterface.h" + +//# include "SPUAssert.h" +#include + + + +extern "C" { + extern char SPU_SAMPLE_ELF_SYMBOL[]; +} + + + + + +SpuSampleTaskProcess::SpuSampleTaskProcess(btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks) +:m_threadInterface(threadInterface), +m_maxNumOutstandingTasks(maxNumOutstandingTasks) +{ + + m_taskBusy.resize(m_maxNumOutstandingTasks); + m_spuSampleTaskDesc.resize(m_maxNumOutstandingTasks); + + for (int i = 0; i < m_maxNumOutstandingTasks; i++) + { + m_taskBusy[i] = false; + } + m_numBusyTasks = 0; + m_currentTask = 0; + + m_initialized = false; + + m_threadInterface->startSPU(); + + +} + +SpuSampleTaskProcess::~SpuSampleTaskProcess() +{ + m_threadInterface->stopSPU(); + +} + + + +void SpuSampleTaskProcess::initialize() +{ +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("SpuSampleTaskProcess::initialize()\n"); +#endif //DEBUG_SPU_TASK_SCHEDULING + + for (int i = 0; i < m_maxNumOutstandingTasks; i++) + { + m_taskBusy[i] = false; + } + m_numBusyTasks = 0; + m_currentTask = 0; + m_initialized = true; + +} + + +void SpuSampleTaskProcess::issueTask(void* sampleMainMemPtr,int sampleValue,int sampleCommand) +{ + +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("SpuSampleTaskProcess::issueTask (m_currentTask= %d\)n", m_currentTask); +#endif //DEBUG_SPU_TASK_SCHEDULING + + m_taskBusy[m_currentTask] = true; + m_numBusyTasks++; + + SpuSampleTaskDesc& taskDesc = m_spuSampleTaskDesc[m_currentTask]; + { + // send task description in event message + // no error checking here... + // but, currently, event queue can be no larger than NUM_WORKUNIT_TASKS. + + taskDesc.m_mainMemoryPtr = reinterpret_cast(sampleMainMemPtr); + taskDesc.m_sampleValue = sampleValue; + taskDesc.m_sampleCommand = sampleCommand; + + //some bookkeeping to recognize finished tasks + taskDesc.m_taskId = m_currentTask; + } + + + m_threadInterface->sendRequest(1, (ppu_address_t) &taskDesc, m_currentTask); + + // if all tasks busy, wait for spu event to clear the task. + + if (m_numBusyTasks >= m_maxNumOutstandingTasks) + { + unsigned int taskId; + unsigned int outputSize; + + for (int i=0;iwaitForResponse(&taskId, &outputSize); + + //printf("PPU: after issue, received event: %u %d\n", taskId, outputSize); + + postProcess(taskId, outputSize); + + m_taskBusy[taskId] = false; + + m_numBusyTasks--; + } + + // find new task buffer + for (int i = 0; i < m_maxNumOutstandingTasks; i++) + { + if (!m_taskBusy[i]) + { + m_currentTask = i; + break; + } + } +} + + +///Optional PPU-size post processing for each task +void SpuSampleTaskProcess::postProcess(int taskId, int outputSize) +{ + +} + + +void SpuSampleTaskProcess::flush() +{ +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("\nSpuCollisionTaskProcess::flush()\n"); +#endif //DEBUG_SPU_TASK_SCHEDULING + + + // all tasks are issued, wait for all tasks to be complete + while(m_numBusyTasks > 0) + { +// Consolidating SPU code + unsigned int taskId; + unsigned int outputSize; + + for (int i=0;iwaitForResponse(&taskId, &outputSize); + } + + //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize); + + postProcess(taskId, outputSize); + + m_taskBusy[taskId] = false; + + m_numBusyTasks--; + } + + +} + +#endif + + +#endif //USE_SAMPLE_PROCESS diff --git a/src/BulletMultiThreaded/SpuSampleTaskProcess.h b/src/BulletMultiThreaded/SpuSampleTaskProcess.h new file mode 100644 index 0000000..6173225 --- /dev/null +++ b/src/BulletMultiThreaded/SpuSampleTaskProcess.h @@ -0,0 +1,153 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SPU_SAMPLE_TASK_PROCESS_H +#define BT_SPU_SAMPLE_TASK_PROCESS_H + +#include + + +#include "PlatformDefinitions.h" + +#include + +#include "LinearMath/btAlignedObjectArray.h" + + +#include "SpuSampleTask/SpuSampleTask.h" + + +//just add your commands here, try to keep them globally unique for debugging purposes +#define CMD_SAMPLE_TASK_COMMAND 10 + + + +/// SpuSampleTaskProcess handles SPU processing of collision pairs. +/// When PPU issues a task, it will look for completed task buffers +/// PPU will do postprocessing, dependent on workunit output (not likely) +class SpuSampleTaskProcess +{ + // track task buffers that are being used, and total busy tasks + btAlignedObjectArray m_taskBusy; + btAlignedObjectArraym_spuSampleTaskDesc; + + int m_numBusyTasks; + + // the current task and the current entry to insert a new work unit + int m_currentTask; + + bool m_initialized; + + void postProcess(int taskId, int outputSize); + + class btThreadSupportInterface* m_threadInterface; + + int m_maxNumOutstandingTasks; + + + +public: + SpuSampleTaskProcess(btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks); + + ~SpuSampleTaskProcess(); + + ///call initialize in the beginning of the frame, before addCollisionPairToTask + void initialize(); + + void issueTask(void* sampleMainMemPtr,int sampleValue,int sampleCommand); + + ///call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished + void flush(); +}; + + +#if defined(USE_LIBSPE2) && defined(__SPU__) +////////////////////MAIN///////////////////////////// +#include "../SpuLibspe2Support.h" +#include +#include +#include + +void * SamplelsMemoryFunc(); +void SampleThreadFunc(void* userPtr,void* lsMemory); + +//#define DEBUG_LIBSPE2_MAINLOOP + +int main(unsigned long long speid, addr64 argp, addr64 envp) +{ + printf("SPU is up \n"); + + ATTRIBUTE_ALIGNED128(btSpuStatus status); + ATTRIBUTE_ALIGNED16( SpuSampleTaskDesc taskDesc ) ; + unsigned int received_message = Spu_Mailbox_Event_Nothing; + bool shutdown = false; + + cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + status.m_status = Spu_Status_Free; + status.m_lsMemory.p = SamplelsMemoryFunc(); + + cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + + while (!shutdown) + { + received_message = spu_read_in_mbox(); + + + + switch(received_message) + { + case Spu_Mailbox_Event_Shutdown: + shutdown = true; + break; + case Spu_Mailbox_Event_Task: + // refresh the status +#ifdef DEBUG_LIBSPE2_MAINLOOP + printf("SPU recieved Task \n"); +#endif //DEBUG_LIBSPE2_MAINLOOP + cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + btAssert(status.m_status==Spu_Status_Occupied); + + cellDmaGet(&taskDesc, status.m_taskDesc.p, sizeof(SpuSampleTaskDesc), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + SampleThreadFunc((void*)&taskDesc, reinterpret_cast (taskDesc.m_mainMemoryPtr) ); + break; + case Spu_Mailbox_Event_Nothing: + default: + break; + } + + // set to status free and wait for next task + status.m_status = Spu_Status_Free; + cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + + } + return 0; +} +////////////////////////////////////////////////////// +#endif + + + +#endif // BT_SPU_SAMPLE_TASK_PROCESS_H + diff --git a/src/BulletMultiThreaded/SpuSync.h b/src/BulletMultiThreaded/SpuSync.h new file mode 100644 index 0000000..4157b8f --- /dev/null +++ b/src/BulletMultiThreaded/SpuSync.h @@ -0,0 +1,149 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2007 Starbreeze Studios + +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. + +Written by: Marten Svanfeldt +*/ + +#ifndef BT_SPU_SYNC_H +#define BT_SPU_SYNC_H + + +#include "PlatformDefinitions.h" + + +#if defined(WIN32) + +#define WIN32_LEAN_AND_MEAN +#ifdef _XBOX +#include +#else +#include +#endif + +///The btSpinlock is a structure to allow multi-platform synchronization. This allows to port the SPU tasks to other platforms. +class btSpinlock +{ +public: + //typedef volatile LONG SpinVariable; + typedef CRITICAL_SECTION SpinVariable; + + btSpinlock (SpinVariable* var) + : spinVariable (var) + {} + + void Init () + { + //*spinVariable = 0; + InitializeCriticalSection(spinVariable); + } + + void Lock () + { + EnterCriticalSection(spinVariable); + } + + void Unlock () + { + LeaveCriticalSection(spinVariable); + } + +private: + SpinVariable* spinVariable; +}; + + +#elif defined (__CELLOS_LV2__) + +//#include +#include + +///The btSpinlock is a structure to allow multi-platform synchronization. This allows to port the SPU tasks to other platforms. +class btSpinlock +{ +public: + typedef CellSyncMutex SpinVariable; + + btSpinlock (SpinVariable* var) + : spinVariable (var) + {} + + void Init () + { +#ifndef __SPU__ + //*spinVariable = 1; + cellSyncMutexInitialize(spinVariable); +#endif + } + + + + void Lock () + { +#ifdef __SPU__ + // lock semaphore + /*while (cellAtomicTestAndDecr32(atomic_buf, (uint64_t)spinVariable) == 0) + { + + };*/ + cellSyncMutexLock((uint64_t)spinVariable); +#endif + } + + void Unlock () + { +#ifdef __SPU__ + //cellAtomicIncr32(atomic_buf, (uint64_t)spinVariable); + cellSyncMutexUnlock((uint64_t)spinVariable); +#endif + } + + +private: + SpinVariable* spinVariable; + ATTRIBUTE_ALIGNED128(uint32_t atomic_buf[32]); +}; + +#else +//create a dummy implementation (without any locking) useful for serial processing +class btSpinlock +{ +public: + typedef int SpinVariable; + + btSpinlock (SpinVariable* var) + : spinVariable (var) + {} + + void Init () + { + } + + void Lock () + { + } + + void Unlock () + { + } + +private: + SpinVariable* spinVariable; +}; + + +#endif + + +#endif //BT_SPU_SYNC_H + diff --git a/src/BulletMultiThreaded/TrbDynBody.h b/src/BulletMultiThreaded/TrbDynBody.h new file mode 100644 index 0000000..4d14212 --- /dev/null +++ b/src/BulletMultiThreaded/TrbDynBody.h @@ -0,0 +1,79 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + +#ifndef BT_RB_DYN_BODY_H__ +#define BT_RB_DYN_BODY_H__ + +#include "vectormath/vmInclude.h" +using namespace Vectormath::Aos; + +#include "TrbStateVec.h" + +class CollObject; + +class TrbDynBody +{ +public: + TrbDynBody() + { + fMass = 0.0f; + fCollObject = NULL; + fElasticity = 0.2f; + fFriction = 0.8f; + } + + // Get methods + float getMass() const {return fMass;}; + float getElasticity() const {return fElasticity;} + float getFriction() const {return fFriction;} + CollObject* getCollObject() const {return fCollObject;} + const Matrix3 &getBodyInertia() const {return fIBody;} + const Matrix3 &getBodyInertiaInv() const {return fIBodyInv;} + float getMassInv() const {return fMassInv;} + + // Set methods + void setMass(float mass) {fMass=mass;fMassInv=mass>0.0f?1.0f/mass:0.0f;} + void setBodyInertia(const Matrix3 bodyInertia) {fIBody = bodyInertia;fIBodyInv = inverse(bodyInertia);} + void setElasticity(float elasticity) {fElasticity = elasticity;} + void setFriction(float friction) {fFriction = friction;} + void setCollObject(CollObject *collObj) {fCollObject = collObj;} + + void setBodyInertiaInv(const Matrix3 bodyInertiaInv) + { + fIBody = inverse(bodyInertiaInv); + fIBodyInv = bodyInertiaInv; + } + void setMassInv(float invMass) { + fMass= invMass>0.0f ? 1.0f/invMass :0.0f; + fMassInv=invMass; + } + + +private: + // Rigid Body constants + float fMass; // Rigid Body mass + float fMassInv; // Inverse of mass + Matrix3 fIBody; // Inertia matrix in body's coords + Matrix3 fIBodyInv; // Inertia matrix inverse in body's coords + float fElasticity; // Coefficient of restitution + float fFriction; // Coefficient of friction + +public: + CollObject* fCollObject; // Collision object corresponding the RB +} __attribute__ ((aligned(16))); + +#endif //BT_RB_DYN_BODY_H__ + diff --git a/src/BulletMultiThreaded/TrbStateVec.h b/src/BulletMultiThreaded/TrbStateVec.h new file mode 100644 index 0000000..46d1904 --- /dev/null +++ b/src/BulletMultiThreaded/TrbStateVec.h @@ -0,0 +1,339 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + +#ifndef BT_TRBSTATEVEC_H__ +#define BT_TRBSTATEVEC_H__ + +#include +#ifdef PFX_USE_FREE_VECTORMATH +#include "vecmath/vmInclude.h" +#else +#include "vectormath/vmInclude.h" +#endif //PFX_USE_FREE_VECTORMATH + + +#include "PlatformDefinitions.h" + + +static inline vmVector3 read_Vector3(const float* p) +{ + vmVector3 v; + loadXYZ(v, p); + return v; +} + +static inline vmQuat read_Quat(const float* p) +{ + vmQuat vq; + loadXYZW(vq, p); + return vq; +} + +static inline void store_Vector3(const vmVector3 &src, float* p) +{ + vmVector3 v = src; + storeXYZ(v, p); +} + +static inline void store_Quat(const vmQuat &src, float* p) +{ + vmQuat vq = src; + storeXYZW(vq, p); +} + +// Motion Type +enum { + PfxMotionTypeFixed = 0, + PfxMotionTypeActive, + PfxMotionTypeKeyframe, + PfxMotionTypeOneWay, + PfxMotionTypeTrigger, + PfxMotionTypeCount +}; + +#define PFX_MOTION_MASK_DYNAMIC 0x0a // Active,OneWay +#define PFX_MOTION_MASK_STATIC 0x95 // Fixed,Keyframe,Trigger,Sleeping +#define PFX_MOTION_MASK_SLEEP 0x0e // Can sleep +#define PFX_MOTION_MASK_TYPE 0x7f + +// +// Rigid Body state +// + +#ifdef __CELLOS_LV2__ +ATTRIBUTE_ALIGNED128(class) TrbState +#else +ATTRIBUTE_ALIGNED16(class) TrbState +#endif + +{ +public: + TrbState() + { + setMotionType(PfxMotionTypeActive); + contactFilterSelf=contactFilterTarget=0xffffffff; + deleted = 0; + mSleeping = 0; + useSleep = 1; + trbBodyIdx=0; + mSleepCount=0; + useCcd = 0; + useContactCallback = 0; + useSleepCallback = 0; + linearDamping = 1.0f; + angularDamping = 0.99f; + } + + TrbState(const uint8_t m, const vmVector3& x, const vmQuat& q, const vmVector3& v, const vmVector3& omega ); + + uint16_t mSleepCount; + uint8_t mMotionType; + uint8_t deleted : 1; + uint8_t mSleeping : 1; + uint8_t useSleep : 1; + uint8_t useCcd : 1; + uint8_t useContactCallback : 1; + uint8_t useSleepCallback : 1; + + uint16_t trbBodyIdx; + uint32_t contactFilterSelf; + uint32_t contactFilterTarget; + + float center[3]; // AABB center(World) + float half[3]; // AABB half(World) + + float linearDamping; + float angularDamping; + + float deltaLinearVelocity[3]; + float deltaAngularVelocity[3]; + + float fX[3]; // position + float fQ[4]; // orientation + float fV[3]; // velocity + float fOmega[3]; // angular velocity + + inline void setZero(); // Zeroes out the elements + inline void setIdentity(); // Sets the rotation to identity and zeroes out the other elements + + bool isDeleted() const {return deleted==1;} + + uint16_t getRigidBodyId() const {return trbBodyIdx;} + void setRigidBodyId(uint16_t i) {trbBodyIdx = i;} + + + uint32_t getContactFilterSelf() const {return contactFilterSelf;} + void setContactFilterSelf(uint32_t filter) {contactFilterSelf = filter;} + + uint32_t getContactFilterTarget() const {return contactFilterTarget;} + void setContactFilterTarget(uint32_t filter) {contactFilterTarget = filter;} + + float getLinearDamping() const {return linearDamping;} + float getAngularDamping() const {return angularDamping;} + + void setLinearDamping(float damping) {linearDamping=damping;} + void setAngularDamping(float damping) {angularDamping=damping;} + + + uint8_t getMotionType() const {return mMotionType;} + void setMotionType(uint8_t t) {mMotionType = t;mSleeping=0;mSleepCount=0;} + + uint8_t getMotionMask() const {return (1< + +#include "SpuCollisionTaskProcess.h" + +#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" + + + +///The number of threads should be equal to the number of available cores +///@todo: each worker should be linked to a single core, using SetThreadIdealProcessor. + +///Win32ThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication +///Setup and initialize SPU/CELL/Libspe2 +Win32ThreadSupport::Win32ThreadSupport(const Win32ThreadConstructionInfo & threadConstructionInfo) +{ + m_maxNumTasks = threadConstructionInfo.m_numThreads; + startThreads(threadConstructionInfo); +} + +///cleanup/shutdown Libspe2 +Win32ThreadSupport::~Win32ThreadSupport() +{ + stopSPU(); +} + + + + +#include + +DWORD WINAPI Thread_no_1( LPVOID lpParam ) +{ + + Win32ThreadSupport::btSpuStatus* status = (Win32ThreadSupport::btSpuStatus*)lpParam; + + + while (1) + { + WaitForSingleObject(status->m_eventStartHandle,INFINITE); + + void* userPtr = status->m_userPtr; + + if (userPtr) + { + btAssert(status->m_status); + status->m_userThreadFunc(userPtr,status->m_lsMemory); + status->m_status = 2; + SetEvent(status->m_eventCompletetHandle); + } else + { + //exit Thread + status->m_status = 3; + printf("Thread with taskId %i with handle %p exiting\n",status->m_taskId, status->m_threadHandle); + SetEvent(status->m_eventCompletetHandle); + break; + } + + } + + printf("Thread TERMINATED\n"); + return 0; + +} + +///send messages to SPUs +void Win32ThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId) +{ + /// gMidphaseSPU.sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (ppu_address_t) &taskDesc); + + ///we should spawn an SPU task here, and in 'waitForResponse' it should wait for response of the (one of) the first tasks that finished + + + + switch (uiCommand) + { + case CMD_GATHER_AND_PROCESS_PAIRLIST: + { + + +//#define SINGLE_THREADED 1 +#ifdef SINGLE_THREADED + + btSpuStatus& spuStatus = m_activeSpuStatus[0]; + spuStatus.m_userPtr=(void*)uiArgument0; + spuStatus.m_userThreadFunc(spuStatus.m_userPtr,spuStatus.m_lsMemory); + HANDLE handle =0; +#else + + + btSpuStatus& spuStatus = m_activeSpuStatus[taskId]; + btAssert(taskId>=0); + btAssert(int(taskId) 1); + spuStatus.m_status = 0; + + ///need to find an active spu + btAssert(last>=0); + +#else + last=0; + btSpuStatus& spuStatus = m_activeSpuStatus[last]; +#endif //SINGLE_THREADED + + + + *puiArgument0 = spuStatus.m_taskId; + *puiArgument1 = spuStatus.m_status; + + +} + + +///check for messages from SPUs +bool Win32ThreadSupport::isTaskCompleted(unsigned int *puiArgument0, unsigned int *puiArgument1, int timeOutInMilliseconds) +{ + ///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response + + ///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback' + + + btAssert(m_activeSpuStatus.size()); + + int last = -1; +#ifndef SINGLE_THREADED + DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, timeOutInMilliseconds); + + if ((res != STATUS_TIMEOUT) && (res != WAIT_FAILED)) + { + + btAssert(res != WAIT_FAILED); + last = res - WAIT_OBJECT_0; + + btSpuStatus& spuStatus = m_activeSpuStatus[last]; + btAssert(spuStatus.m_threadHandle); + btAssert(spuStatus.m_eventCompletetHandle); + + //WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE); + btAssert(spuStatus.m_status > 1); + spuStatus.m_status = 0; + + ///need to find an active spu + btAssert(last>=0); + + #else + last=0; + btSpuStatus& spuStatus = m_activeSpuStatus[last]; + #endif //SINGLE_THREADED + + + + *puiArgument0 = spuStatus.m_taskId; + *puiArgument1 = spuStatus.m_status; + + return true; + } + + return false; +} + + +void Win32ThreadSupport::startThreads(const Win32ThreadConstructionInfo& threadConstructionInfo) +{ + + m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads); + m_completeHandles.resize(threadConstructionInfo.m_numThreads); + + m_maxNumTasks = threadConstructionInfo.m_numThreads; + + for (int i=0;i0) + { + WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE); + } + + + spuStatus.m_userPtr = 0; + SetEvent(spuStatus.m_eventStartHandle); + WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE); + + CloseHandle(spuStatus.m_eventCompletetHandle); + CloseHandle(spuStatus.m_eventStartHandle); + CloseHandle(spuStatus.m_threadHandle); + } + + m_activeSpuStatus.clear(); + m_completeHandles.clear(); + +} + + + +class btWin32Barrier : public btBarrier +{ +private: + CRITICAL_SECTION mExternalCriticalSection; + CRITICAL_SECTION mLocalCriticalSection; + HANDLE mRunEvent,mNotifyEvent; + int mCounter,mEnableCounter; + int mMaxCount; + +public: + btWin32Barrier() + { + mCounter = 0; + mMaxCount = 1; + mEnableCounter = 0; + InitializeCriticalSection(&mExternalCriticalSection); + InitializeCriticalSection(&mLocalCriticalSection); + mRunEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + mNotifyEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + } + + virtual ~btWin32Barrier() + { + DeleteCriticalSection(&mExternalCriticalSection); + DeleteCriticalSection(&mLocalCriticalSection); + CloseHandle(mRunEvent); + CloseHandle(mNotifyEvent); + } + + void sync() + { + int eventId; + + EnterCriticalSection(&mExternalCriticalSection); + + //PFX_PRINTF("enter taskId %d count %d stage %d phase %d mEnableCounter %d\n",taskId,mCounter,debug&0xff,debug>>16,mEnableCounter); + + if(mEnableCounter > 0) { + ResetEvent(mNotifyEvent); + LeaveCriticalSection(&mExternalCriticalSection); + WaitForSingleObject(mNotifyEvent,INFINITE); + EnterCriticalSection(&mExternalCriticalSection); + } + + eventId = mCounter; + mCounter++; + + if(eventId == mMaxCount-1) { + SetEvent(mRunEvent); + + mEnableCounter = mCounter-1; + mCounter = 0; + } + else { + ResetEvent(mRunEvent); + LeaveCriticalSection(&mExternalCriticalSection); + WaitForSingleObject(mRunEvent,INFINITE); + EnterCriticalSection(&mExternalCriticalSection); + mEnableCounter--; + } + + if(mEnableCounter == 0) { + SetEvent(mNotifyEvent); + } + + //PFX_PRINTF("leave taskId %d count %d stage %d phase %d mEnableCounter %d\n",taskId,mCounter,debug&0xff,debug>>16,mEnableCounter); + + LeaveCriticalSection(&mExternalCriticalSection); + } + + virtual void setMaxCount(int n) {mMaxCount = n;} + virtual int getMaxCount() {return mMaxCount;} +}; + +class btWin32CriticalSection : public btCriticalSection +{ +private: + CRITICAL_SECTION mCriticalSection; + +public: + btWin32CriticalSection() + { + InitializeCriticalSection(&mCriticalSection); + } + + ~btWin32CriticalSection() + { + DeleteCriticalSection(&mCriticalSection); + } + + unsigned int getSharedParam(int i) + { + btAssert(i>=0&&i<31); + return mCommonBuff[i+1]; + } + + void setSharedParam(int i,unsigned int p) + { + btAssert(i>=0&&i<31); + mCommonBuff[i+1] = p; + } + + void lock() + { + EnterCriticalSection(&mCriticalSection); + mCommonBuff[0] = 1; + } + + void unlock() + { + mCommonBuff[0] = 0; + LeaveCriticalSection(&mCriticalSection); + } +}; + + +btBarrier* Win32ThreadSupport::createBarrier() +{ + unsigned char* mem = (unsigned char*)btAlignedAlloc(sizeof(btWin32Barrier),16); + btWin32Barrier* barrier = new(mem) btWin32Barrier(); + barrier->setMaxCount(getNumTasks()); + return barrier; +} + +btCriticalSection* Win32ThreadSupport::createCriticalSection() +{ + unsigned char* mem = (unsigned char*) btAlignedAlloc(sizeof(btWin32CriticalSection),16); + btWin32CriticalSection* cs = new(mem) btWin32CriticalSection(); + return cs; +} + + + +#endif //USE_WIN32_THREADING + + diff --git a/src/BulletMultiThreaded/Win32ThreadSupport.h b/src/BulletMultiThreaded/Win32ThreadSupport.h new file mode 100644 index 0000000..abf5d21 --- /dev/null +++ b/src/BulletMultiThreaded/Win32ThreadSupport.h @@ -0,0 +1,138 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "LinearMath/btScalar.h" +#include "PlatformDefinitions.h" + +#ifdef USE_WIN32_THREADING //platform specific defines are defined in PlatformDefinitions.h + +#ifndef BT_WIN32_THREAD_SUPPORT_H +#define BT_WIN32_THREAD_SUPPORT_H + +#include "LinearMath/btAlignedObjectArray.h" + +#include "btThreadSupportInterface.h" + + +typedef void (*Win32ThreadFunc)(void* userPtr,void* lsMemory); +typedef void* (*Win32lsMemorySetupFunc)(); + + +///Win32ThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication +class Win32ThreadSupport : public btThreadSupportInterface +{ +public: + ///placeholder, until libspe2 support is there + struct btSpuStatus + { + uint32_t m_taskId; + uint32_t m_commandId; + uint32_t m_status; + + Win32ThreadFunc m_userThreadFunc; + void* m_userPtr; //for taskDesc etc + void* m_lsMemory; //initialized using Win32LocalStoreMemorySetupFunc + + void* m_threadHandle; //this one is calling 'Win32ThreadFunc' + + void* m_eventStartHandle; + char m_eventStartHandleName[32]; + + void* m_eventCompletetHandle; + char m_eventCompletetHandleName[32]; + + + }; +private: + + btAlignedObjectArray m_activeSpuStatus; + btAlignedObjectArray m_completeHandles; + + int m_maxNumTasks; +public: + ///Setup and initialize SPU/CELL/Libspe2 + + struct Win32ThreadConstructionInfo + { + Win32ThreadConstructionInfo(const char* uniqueName, + Win32ThreadFunc userThreadFunc, + Win32lsMemorySetupFunc lsMemoryFunc, + int numThreads=1, + int threadStackSize=65535 + ) + :m_uniqueName(uniqueName), + m_userThreadFunc(userThreadFunc), + m_lsMemoryFunc(lsMemoryFunc), + m_numThreads(numThreads), + m_threadStackSize(threadStackSize) + { + + } + + const char* m_uniqueName; + Win32ThreadFunc m_userThreadFunc; + Win32lsMemorySetupFunc m_lsMemoryFunc; + int m_numThreads; + int m_threadStackSize; + + }; + + + + Win32ThreadSupport(const Win32ThreadConstructionInfo& threadConstructionInfo); + +///cleanup/shutdown Libspe2 + virtual ~Win32ThreadSupport(); + + void startThreads(const Win32ThreadConstructionInfo& threadInfo); + + +///send messages to SPUs + virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1); + +///check for messages from SPUs + virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1); + + virtual bool isTaskCompleted(unsigned int *puiArgument0, unsigned int *puiArgument1, int timeOutInMilliseconds); + +///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) + virtual void startSPU(); + +///tell the task scheduler we are done with the SPU tasks + virtual void stopSPU(); + + virtual void setNumTasks(int numTasks) + { + m_maxNumTasks = numTasks; + } + + virtual int getNumTasks() const + { + return m_maxNumTasks; + } + + virtual void* getThreadLocalMemory(int taskId) + { + return m_activeSpuStatus[taskId].m_lsMemory; + } + virtual btBarrier* createBarrier(); + + virtual btCriticalSection* createCriticalSection(); + +}; + +#endif //BT_WIN32_THREAD_SUPPORT_H + +#endif //USE_WIN32_THREADING diff --git a/src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp b/src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp new file mode 100644 index 0000000..84a5e59 --- /dev/null +++ b/src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp @@ -0,0 +1,590 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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. +*/ + +///The 3 following lines include the CPU implementation of the kernels, keep them in this order. +#include "BulletMultiThreaded/btGpuDefines.h" +#include "BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#include "BulletMultiThreaded/btGpuUtilsSharedCode.h" + + + +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btQuickprof.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" + + + +#include "btGpuDefines.h" +#include "btGpuUtilsSharedDefs.h" + +#include "btGpu3DGridBroadphaseSharedDefs.h" + +#include "btGpu3DGridBroadphase.h" +#include //for memset + + +#include + + + +static bt3DGridBroadphaseParams s3DGridBroadphaseParams; + + + +btGpu3DGridBroadphase::btGpu3DGridBroadphase( const btVector3& worldAabbMin,const btVector3& worldAabbMax, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + int maxBodiesPerCell, + btScalar cellFactorAABB) : + btSimpleBroadphase(maxSmallProxies, +// new (btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16)) btSortedOverlappingPairCache), + new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache), + m_bInitialized(false), + m_numBodies(0) +{ + _initialize(worldAabbMin, worldAabbMax, gridSizeX, gridSizeY, gridSizeZ, + maxSmallProxies, maxLargeProxies, maxPairsPerBody, + maxBodiesPerCell, cellFactorAABB); +} + + + +btGpu3DGridBroadphase::btGpu3DGridBroadphase( btOverlappingPairCache* overlappingPairCache, + const btVector3& worldAabbMin,const btVector3& worldAabbMax, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + int maxBodiesPerCell, + btScalar cellFactorAABB) : + btSimpleBroadphase(maxSmallProxies, overlappingPairCache), + m_bInitialized(false), + m_numBodies(0) +{ + _initialize(worldAabbMin, worldAabbMax, gridSizeX, gridSizeY, gridSizeZ, + maxSmallProxies, maxLargeProxies, maxPairsPerBody, + maxBodiesPerCell, cellFactorAABB); +} + + + +btGpu3DGridBroadphase::~btGpu3DGridBroadphase() +{ + //btSimpleBroadphase will free memory of btSortedOverlappingPairCache, because m_ownsPairCache + assert(m_bInitialized); + _finalize(); +} + + + +void btGpu3DGridBroadphase::_initialize( const btVector3& worldAabbMin,const btVector3& worldAabbMax, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + int maxBodiesPerCell, + btScalar cellFactorAABB) +{ + // set various paramerers + m_ownsPairCache = true; + m_params.m_gridSizeX = gridSizeX; + m_params.m_gridSizeY = gridSizeY; + m_params.m_gridSizeZ = gridSizeZ; + m_params.m_numCells = m_params.m_gridSizeX * m_params.m_gridSizeY * m_params.m_gridSizeZ; + btVector3 w_org = worldAabbMin; + m_params.m_worldOriginX = w_org.getX(); + m_params.m_worldOriginY = w_org.getY(); + m_params.m_worldOriginZ = w_org.getZ(); + btVector3 w_size = worldAabbMax - worldAabbMin; + m_params.m_cellSizeX = w_size.getX() / m_params.m_gridSizeX; + m_params.m_cellSizeY = w_size.getY() / m_params.m_gridSizeY; + m_params.m_cellSizeZ = w_size.getZ() / m_params.m_gridSizeZ; + m_maxRadius = btMin(btMin(m_params.m_cellSizeX, m_params.m_cellSizeY), m_params.m_cellSizeZ); + m_maxRadius *= btScalar(0.5f); + m_params.m_numBodies = m_numBodies; + m_params.m_maxBodiesPerCell = maxBodiesPerCell; + + m_numLargeHandles = 0; + m_maxLargeHandles = maxLargeProxies; + + m_maxPairsPerBody = maxPairsPerBody; + + m_cellFactorAABB = cellFactorAABB; + + m_LastLargeHandleIndex = -1; + + assert(!m_bInitialized); + // allocate host storage + m_hBodiesHash = new unsigned int[m_maxHandles * 2]; + memset(m_hBodiesHash, 0x00, m_maxHandles*2*sizeof(unsigned int)); + + m_hCellStart = new unsigned int[m_params.m_numCells]; + memset(m_hCellStart, 0x00, m_params.m_numCells * sizeof(unsigned int)); + + m_hPairBuffStartCurr = new unsigned int[m_maxHandles * 2 + 2]; + // --------------- for now, init with m_maxPairsPerBody for each body + m_hPairBuffStartCurr[0] = 0; + m_hPairBuffStartCurr[1] = 0; + for(int i = 1; i <= m_maxHandles; i++) + { + m_hPairBuffStartCurr[i * 2] = m_hPairBuffStartCurr[(i-1) * 2] + m_maxPairsPerBody; + m_hPairBuffStartCurr[i * 2 + 1] = 0; + } + //---------------- + unsigned int numAABB = m_maxHandles + m_maxLargeHandles; + m_hAABB = new bt3DGrid3F1U[numAABB * 2]; // AABB Min & Max + + m_hPairBuff = new unsigned int[m_maxHandles * m_maxPairsPerBody]; + memset(m_hPairBuff, 0x00, m_maxHandles * m_maxPairsPerBody * sizeof(unsigned int)); // needed? + + m_hPairScan = new unsigned int[m_maxHandles + 1]; + + m_hPairOut = new unsigned int[m_maxHandles * m_maxPairsPerBody]; + +// large proxies + + // allocate handles buffer and put all handles on free list + m_pLargeHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy) * m_maxLargeHandles, 16); + m_pLargeHandles = new(m_pLargeHandlesRawPtr) btSimpleBroadphaseProxy[m_maxLargeHandles]; + m_firstFreeLargeHandle = 0; + { + for (int i = m_firstFreeLargeHandle; i < m_maxLargeHandles; i++) + { + m_pLargeHandles[i].SetNextFree(i + 1); + m_pLargeHandles[i].m_uniqueId = m_maxHandles+2+i; + } + m_pLargeHandles[m_maxLargeHandles - 1].SetNextFree(0); + } + +// debug data + m_numPairsAdded = 0; + m_numOverflows = 0; + + m_bInitialized = true; +} + + + +void btGpu3DGridBroadphase::_finalize() +{ + assert(m_bInitialized); + delete [] m_hBodiesHash; + delete [] m_hCellStart; + delete [] m_hPairBuffStartCurr; + delete [] m_hAABB; + delete [] m_hPairBuff; + delete [] m_hPairScan; + delete [] m_hPairOut; + btAlignedFree(m_pLargeHandlesRawPtr); + m_bInitialized = false; +} + + + +void btGpu3DGridBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + if(m_numHandles <= 0) + { + BT_PROFILE("addLarge2LargePairsToCache"); + addLarge2LargePairsToCache(dispatcher); + return; + } + // update constants + setParameters(&m_params); + // prepare AABB array + prepareAABB(); + // calculate hash + calcHashAABB(); + // sort bodies based on hash + sortHash(); + // find start of each cell + findCellStart(); + // findOverlappingPairs (small/small) + findOverlappingPairs(); + // findOverlappingPairs (small/large) + findPairsLarge(); + // add pairs to CPU cache + computePairCacheChanges(); + scanOverlappingPairBuff(); + squeezeOverlappingPairBuff(); + addPairsToCache(dispatcher); + // find and add large/large pairs to CPU cache + addLarge2LargePairsToCache(dispatcher); + return; +} + + + +void btGpu3DGridBroadphase::addPairsToCache(btDispatcher* dispatcher) +{ + m_numPairsAdded = 0; + m_numPairsRemoved = 0; + for(int i = 0; i < m_numHandles; i++) + { + unsigned int num = m_hPairScan[i+1] - m_hPairScan[i]; + if(!num) + { + continue; + } + unsigned int* pInp = m_hPairOut + m_hPairScan[i]; + unsigned int index0 = m_hAABB[i * 2].uw; + btSimpleBroadphaseProxy* proxy0 = &m_pHandles[index0]; + for(unsigned int j = 0; j < num; j++) + { + unsigned int indx1_s = pInp[j]; + unsigned int index1 = indx1_s & (~BT_3DGRID_PAIR_ANY_FLG); + btSimpleBroadphaseProxy* proxy1; + if(index1 < (unsigned int)m_maxHandles) + { + proxy1 = &m_pHandles[index1]; + } + else + { + index1 -= m_maxHandles; + btAssert((index1 >= 0) && (index1 < (unsigned int)m_maxLargeHandles)); + proxy1 = &m_pLargeHandles[index1]; + } + if(indx1_s & BT_3DGRID_PAIR_NEW_FLG) + { + m_pairCache->addOverlappingPair(proxy0,proxy1); + m_numPairsAdded++; + } + else + { + m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); + m_numPairsRemoved++; + } + } + } +} + + + +btBroadphaseProxy* btGpu3DGridBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) +{ + btBroadphaseProxy* proxy; + bool bIsLarge = isLargeProxy(aabbMin, aabbMax); + if(bIsLarge) + { + if (m_numLargeHandles >= m_maxLargeHandles) + { + ///you have to increase the cell size, so 'large' proxies become 'small' proxies (fitting a cell) + btAssert(0); + return 0; //should never happen, but don't let the game crash ;-) + } + btAssert((aabbMin[0]<= aabbMax[0]) && (aabbMin[1]<= aabbMax[1]) && (aabbMin[2]<= aabbMax[2])); + int newHandleIndex = allocLargeHandle(); + proxy = new (&m_pLargeHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy); + } + else + { + proxy = btSimpleBroadphase::createProxy(aabbMin, aabbMax, shapeType, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher, multiSapProxy); + } + return proxy; +} + + + +void btGpu3DGridBroadphase::destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher) +{ + bool bIsLarge = isLargeProxy(proxy); + if(bIsLarge) + { + + btSimpleBroadphaseProxy* proxy0 = static_cast(proxy); + freeLargeHandle(proxy0); + m_pairCache->removeOverlappingPairsContainingProxy(proxy,dispatcher); + } + else + { + btSimpleBroadphase::destroyProxy(proxy, dispatcher); + } + return; +} + + + +void btGpu3DGridBroadphase::resetPool(btDispatcher* dispatcher) +{ + m_hPairBuffStartCurr[0] = 0; + m_hPairBuffStartCurr[1] = 0; + for(int i = 1; i <= m_maxHandles; i++) + { + m_hPairBuffStartCurr[i * 2] = m_hPairBuffStartCurr[(i-1) * 2] + m_maxPairsPerBody; + m_hPairBuffStartCurr[i * 2 + 1] = 0; + } +} + + + +bool btGpu3DGridBroadphase::isLargeProxy(const btVector3& aabbMin, const btVector3& aabbMax) +{ + btVector3 diag = aabbMax - aabbMin; + + ///use the bounding sphere radius of this bounding box, to include rotation + btScalar radius = diag.length() * btScalar(0.5f); + radius *= m_cellFactorAABB; // user-defined factor + + return (radius > m_maxRadius); +} + + + +bool btGpu3DGridBroadphase::isLargeProxy(btBroadphaseProxy* proxy) +{ + return (proxy->getUid() >= (m_maxHandles+2)); +} + + + +void btGpu3DGridBroadphase::addLarge2LargePairsToCache(btDispatcher* dispatcher) +{ + int i,j; + if (m_numLargeHandles <= 0) + { + return; + } + int new_largest_index = -1; + for(i = 0; i <= m_LastLargeHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy0 = &m_pLargeHandles[i]; + if(!proxy0->m_clientObject) + { + continue; + } + new_largest_index = i; + for(j = i + 1; j <= m_LastLargeHandleIndex; j++) + { + btSimpleBroadphaseProxy* proxy1 = &m_pLargeHandles[j]; + if(!proxy1->m_clientObject) + { + continue; + } + btAssert(proxy0 != proxy1); + btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); + btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); + if(aabbOverlap(p0,p1)) + { + if (!m_pairCache->findPair(proxy0,proxy1)) + { + m_pairCache->addOverlappingPair(proxy0,proxy1); + } + } + else + { + if(m_pairCache->findPair(proxy0,proxy1)) + { + m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); + } + } + } + } + m_LastLargeHandleIndex = new_largest_index; + return; +} + + + +void btGpu3DGridBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback) +{ + btSimpleBroadphase::rayTest(rayFrom, rayTo, rayCallback); + for (int i=0; i <= m_LastLargeHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy = &m_pLargeHandles[i]; + if(!proxy->m_clientObject) + { + continue; + } + rayCallback.process(proxy); + } +} + + + +// +// overrides for CPU version +// + + + +void btGpu3DGridBroadphase::prepareAABB() +{ + BT_PROFILE("prepareAABB"); + bt3DGrid3F1U* pBB = m_hAABB; + int i; + int new_largest_index = -1; + unsigned int num_small = 0; + for(i = 0; i <= m_LastHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i]; + if(!proxy0->m_clientObject) + { + continue; + } + new_largest_index = i; + pBB->fx = proxy0->m_aabbMin.getX(); + pBB->fy = proxy0->m_aabbMin.getY(); + pBB->fz = proxy0->m_aabbMin.getZ(); + pBB->uw = i; + pBB++; + pBB->fx = proxy0->m_aabbMax.getX(); + pBB->fy = proxy0->m_aabbMax.getY(); + pBB->fz = proxy0->m_aabbMax.getZ(); + pBB->uw = num_small; + pBB++; + num_small++; + } + m_LastHandleIndex = new_largest_index; + new_largest_index = -1; + unsigned int num_large = 0; + for(i = 0; i <= m_LastLargeHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy0 = &m_pLargeHandles[i]; + if(!proxy0->m_clientObject) + { + continue; + } + new_largest_index = i; + pBB->fx = proxy0->m_aabbMin.getX(); + pBB->fy = proxy0->m_aabbMin.getY(); + pBB->fz = proxy0->m_aabbMin.getZ(); + pBB->uw = i + m_maxHandles; + pBB++; + pBB->fx = proxy0->m_aabbMax.getX(); + pBB->fy = proxy0->m_aabbMax.getY(); + pBB->fz = proxy0->m_aabbMax.getZ(); + pBB->uw = num_large + m_maxHandles; + pBB++; + num_large++; + } + m_LastLargeHandleIndex = new_largest_index; + // paranoid checks + btAssert(num_small == m_numHandles); + btAssert(num_large == m_numLargeHandles); + return; +} + + + +void btGpu3DGridBroadphase::setParameters(bt3DGridBroadphaseParams* hostParams) +{ + s3DGridBroadphaseParams = *hostParams; + return; +} + + + +void btGpu3DGridBroadphase::calcHashAABB() +{ + BT_PROFILE("bt3DGrid_calcHashAABB"); + btGpu_calcHashAABB(m_hAABB, m_hBodiesHash, m_numHandles); + return; +} + + + +void btGpu3DGridBroadphase::sortHash() +{ + class bt3DGridHashKey + { + public: + unsigned int hash; + unsigned int index; + void quickSort(bt3DGridHashKey* pData, int lo, int hi) + { + int i=lo, j=hi; + bt3DGridHashKey x = pData[(lo+hi)/2]; + do + { + while(pData[i].hash > x.hash) i++; + while(x.hash > pData[j].hash) j--; + if(i <= j) + { + bt3DGridHashKey t = pData[i]; + pData[i] = pData[j]; + pData[j] = t; + i++; j--; + } + } while(i <= j); + if(lo < j) pData->quickSort(pData, lo, j); + if(i < hi) pData->quickSort(pData, i, hi); + } + }; + BT_PROFILE("bt3DGrid_sortHash"); + bt3DGridHashKey* pHash = (bt3DGridHashKey*)m_hBodiesHash; + pHash->quickSort(pHash, 0, m_numHandles - 1); + return; +} + + + +void btGpu3DGridBroadphase::findCellStart() +{ + BT_PROFILE("bt3DGrid_findCellStart"); + btGpu_findCellStart(m_hBodiesHash, m_hCellStart, m_numHandles, m_params.m_numCells); + return; +} + + + +void btGpu3DGridBroadphase::findOverlappingPairs() +{ + BT_PROFILE("bt3DGrid_findOverlappingPairs"); + btGpu_findOverlappingPairs(m_hAABB, m_hBodiesHash, m_hCellStart, m_hPairBuff, m_hPairBuffStartCurr, m_numHandles); + return; +} + + + +void btGpu3DGridBroadphase::findPairsLarge() +{ + BT_PROFILE("bt3DGrid_findPairsLarge"); + btGpu_findPairsLarge(m_hAABB, m_hBodiesHash, m_hCellStart, m_hPairBuff, m_hPairBuffStartCurr, m_numHandles, m_numLargeHandles); + return; +} + + + +void btGpu3DGridBroadphase::computePairCacheChanges() +{ + BT_PROFILE("bt3DGrid_computePairCacheChanges"); + btGpu_computePairCacheChanges(m_hPairBuff, m_hPairBuffStartCurr, m_hPairScan, m_hAABB, m_numHandles); + return; +} + + + +void btGpu3DGridBroadphase::scanOverlappingPairBuff() +{ + BT_PROFILE("bt3DGrid_scanOverlappingPairBuff"); + m_hPairScan[0] = 0; + for(int i = 1; i <= m_numHandles; i++) + { + unsigned int delta = m_hPairScan[i]; + m_hPairScan[i] = m_hPairScan[i-1] + delta; + } + return; +} + + + +void btGpu3DGridBroadphase::squeezeOverlappingPairBuff() +{ + BT_PROFILE("bt3DGrid_squeezeOverlappingPairBuff"); + btGpu_squeezeOverlappingPairBuff(m_hPairBuff, m_hPairBuffStartCurr, m_hPairScan, m_hPairOut, m_hAABB, m_numHandles); + return; +} + + + +#include "btGpu3DGridBroadphaseSharedCode.h" + + diff --git a/src/BulletMultiThreaded/btGpu3DGridBroadphase.h b/src/BulletMultiThreaded/btGpu3DGridBroadphase.h new file mode 100644 index 0000000..1d49a05 --- /dev/null +++ b/src/BulletMultiThreaded/btGpu3DGridBroadphase.h @@ -0,0 +1,138 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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 BTGPU3DGRIDBROADPHASE_H +#define BTGPU3DGRIDBROADPHASE_H + +//---------------------------------------------------------------------------------------- + +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" + +#include "btGpu3DGridBroadphaseSharedTypes.h" + +//---------------------------------------------------------------------------------------- + +///The btGpu3DGridBroadphase uses GPU-style code compiled for CPU to compute overlapping pairs + +class btGpu3DGridBroadphase : public btSimpleBroadphase +{ +protected: + bool m_bInitialized; + unsigned int m_numBodies; + unsigned int m_numCells; + unsigned int m_maxPairsPerBody; + btScalar m_cellFactorAABB; + unsigned int m_maxBodiesPerCell; + bt3DGridBroadphaseParams m_params; + btScalar m_maxRadius; + // CPU data + unsigned int* m_hBodiesHash; + unsigned int* m_hCellStart; + unsigned int* m_hPairBuffStartCurr; + bt3DGrid3F1U* m_hAABB; + unsigned int* m_hPairBuff; + unsigned int* m_hPairScan; + unsigned int* m_hPairOut; +// large proxies + int m_numLargeHandles; + int m_maxLargeHandles; + int m_LastLargeHandleIndex; + btSimpleBroadphaseProxy* m_pLargeHandles; + void* m_pLargeHandlesRawPtr; + int m_firstFreeLargeHandle; + int allocLargeHandle() + { + btAssert(m_numLargeHandles < m_maxLargeHandles); + int freeLargeHandle = m_firstFreeLargeHandle; + m_firstFreeLargeHandle = m_pLargeHandles[freeLargeHandle].GetNextFree(); + m_numLargeHandles++; + if(freeLargeHandle > m_LastLargeHandleIndex) + { + m_LastLargeHandleIndex = freeLargeHandle; + } + return freeLargeHandle; + } + void freeLargeHandle(btSimpleBroadphaseProxy* proxy) + { + int handle = int(proxy - m_pLargeHandles); + btAssert((handle >= 0) && (handle < m_maxHandles)); + if(handle == m_LastLargeHandleIndex) + { + m_LastLargeHandleIndex--; + } + proxy->SetNextFree(m_firstFreeLargeHandle); + m_firstFreeLargeHandle = handle; + proxy->m_clientObject = 0; + m_numLargeHandles--; + } + bool isLargeProxy(const btVector3& aabbMin, const btVector3& aabbMax); + bool isLargeProxy(btBroadphaseProxy* proxy); +// debug + unsigned int m_numPairsAdded; + unsigned int m_numPairsRemoved; + unsigned int m_numOverflows; +// +public: + btGpu3DGridBroadphase(const btVector3& worldAabbMin,const btVector3& worldAabbMax, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + int maxBodiesPerCell = 8, + btScalar cellFactorAABB = btScalar(1.0f)); + btGpu3DGridBroadphase( btOverlappingPairCache* overlappingPairCache, + const btVector3& worldAabbMin,const btVector3& worldAabbMax, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + int maxBodiesPerCell = 8, + btScalar cellFactorAABB = btScalar(1.0f)); + virtual ~btGpu3DGridBroadphase(); + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); + + virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback); + virtual void resetPool(btDispatcher* dispatcher); + +protected: + void _initialize( const btVector3& worldAabbMin,const btVector3& worldAabbMax, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + int maxBodiesPerCell = 8, + btScalar cellFactorAABB = btScalar(1.0f)); + void _finalize(); + void addPairsToCache(btDispatcher* dispatcher); + void addLarge2LargePairsToCache(btDispatcher* dispatcher); + +// overrides for CPU version + virtual void setParameters(bt3DGridBroadphaseParams* hostParams); + virtual void prepareAABB(); + virtual void calcHashAABB(); + virtual void sortHash(); + virtual void findCellStart(); + virtual void findOverlappingPairs(); + virtual void findPairsLarge(); + virtual void computePairCacheChanges(); + virtual void scanOverlappingPairBuff(); + virtual void squeezeOverlappingPairBuff(); +}; + +//---------------------------------------------------------------------------------------- + +#endif //BTGPU3DGRIDBROADPHASE_H + +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- diff --git a/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h b/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h new file mode 100644 index 0000000..e0afb87 --- /dev/null +++ b/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h @@ -0,0 +1,430 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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. +*/ + +//---------------------------------------------------------------------------------------- + +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +// K E R N E L F U N C T I O N S +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- + +// calculate position in uniform grid +BT_GPU___device__ int3 bt3DGrid_calcGridPos(float4 p) +{ + int3 gridPos; + gridPos.x = (int)floor((p.x - BT_GPU_params.m_worldOriginX) / BT_GPU_params.m_cellSizeX); + gridPos.y = (int)floor((p.y - BT_GPU_params.m_worldOriginY) / BT_GPU_params.m_cellSizeY); + gridPos.z = (int)floor((p.z - BT_GPU_params.m_worldOriginZ) / BT_GPU_params.m_cellSizeZ); + return gridPos; +} // bt3DGrid_calcGridPos() + +//---------------------------------------------------------------------------------------- + +// calculate address in grid from position (clamping to edges) +BT_GPU___device__ uint bt3DGrid_calcGridHash(int3 gridPos) +{ + gridPos.x = BT_GPU_max(0, BT_GPU_min(gridPos.x, (int)BT_GPU_params.m_gridSizeX - 1)); + gridPos.y = BT_GPU_max(0, BT_GPU_min(gridPos.y, (int)BT_GPU_params.m_gridSizeY - 1)); + gridPos.z = BT_GPU_max(0, BT_GPU_min(gridPos.z, (int)BT_GPU_params.m_gridSizeZ - 1)); + return BT_GPU___mul24(BT_GPU___mul24(gridPos.z, BT_GPU_params.m_gridSizeY), BT_GPU_params.m_gridSizeX) + BT_GPU___mul24(gridPos.y, BT_GPU_params.m_gridSizeX) + gridPos.x; +} // bt3DGrid_calcGridHash() + +//---------------------------------------------------------------------------------------- + +// calculate grid hash value for each body using its AABB +BT_GPU___global__ void calcHashAABBD(bt3DGrid3F1U* pAABB, uint2* pHash, uint numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + bt3DGrid3F1U bbMin = pAABB[index*2]; + bt3DGrid3F1U bbMax = pAABB[index*2 + 1]; + float4 pos; + pos.x = (bbMin.fx + bbMax.fx) * 0.5f; + pos.y = (bbMin.fy + bbMax.fy) * 0.5f; + pos.z = (bbMin.fz + bbMax.fz) * 0.5f; + // get address in grid + int3 gridPos = bt3DGrid_calcGridPos(pos); + uint gridHash = bt3DGrid_calcGridHash(gridPos); + // store grid hash and body index + pHash[index] = BT_GPU_make_uint2(gridHash, index); +} // calcHashAABBD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void findCellStartD(uint2* pHash, uint* cellStart, uint numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + uint2 sortedData = pHash[index]; + // Load hash data into shared memory so that we can look + // at neighboring body's hash value without loading + // two hash values per thread + BT_GPU___shared__ uint sharedHash[257]; + sharedHash[BT_GPU_threadIdx.x+1] = sortedData.x; + if((index > 0) && (BT_GPU_threadIdx.x == 0)) + { + // first thread in block must load neighbor body hash + volatile uint2 prevData = pHash[index-1]; + sharedHash[0] = prevData.x; + } + BT_GPU___syncthreads(); + if((index == 0) || (sortedData.x != sharedHash[BT_GPU_threadIdx.x])) + { + cellStart[sortedData.x] = index; + } +} // findCellStartD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___device__ uint cudaTestAABBOverlap(bt3DGrid3F1U min0, bt3DGrid3F1U max0, bt3DGrid3F1U min1, bt3DGrid3F1U max1) +{ + return (min0.fx <= max1.fx)&& (min1.fx <= max0.fx) && + (min0.fy <= max1.fy)&& (min1.fy <= max0.fy) && + (min0.fz <= max1.fz)&& (min1.fz <= max0.fz); +} // cudaTestAABBOverlap() + +//---------------------------------------------------------------------------------------- + +BT_GPU___device__ void findPairsInCell( int3 gridPos, + uint index, + uint2* pHash, + uint* pCellStart, + bt3DGrid3F1U* pAABB, + uint* pPairBuff, + uint2* pPairBuffStartCurr, + uint numBodies) +{ + if ( (gridPos.x < 0) || (gridPos.x > (int)BT_GPU_params.m_gridSizeX - 1) + || (gridPos.y < 0) || (gridPos.y > (int)BT_GPU_params.m_gridSizeY - 1) + || (gridPos.z < 0) || (gridPos.z > (int)BT_GPU_params.m_gridSizeZ - 1)) + { + return; + } + uint gridHash = bt3DGrid_calcGridHash(gridPos); + // get start of bucket for this cell + uint bucketStart = pCellStart[gridHash]; + if (bucketStart == 0xffffffff) + { + return; // cell empty + } + // iterate over bodies in this cell + uint2 sortedData = pHash[index]; + uint unsorted_indx = sortedData.y; + bt3DGrid3F1U min0 = BT_GPU_FETCH(pAABB, unsorted_indx*2); + bt3DGrid3F1U max0 = BT_GPU_FETCH(pAABB, unsorted_indx*2 + 1); + uint handleIndex = min0.uw; + uint2 start_curr = pPairBuffStartCurr[handleIndex]; + uint start = start_curr.x; + uint curr = start_curr.y; + uint2 start_curr_next = pPairBuffStartCurr[handleIndex+1]; + uint curr_max = start_curr_next.x - start - 1; + uint bucketEnd = bucketStart + BT_GPU_params.m_maxBodiesPerCell; + bucketEnd = (bucketEnd > numBodies) ? numBodies : bucketEnd; + for(uint index2 = bucketStart; index2 < bucketEnd; index2++) + { + uint2 cellData = pHash[index2]; + if (cellData.x != gridHash) + { + break; // no longer in same bucket + } + uint unsorted_indx2 = cellData.y; + if (unsorted_indx2 < unsorted_indx) // check not colliding with self + { + bt3DGrid3F1U min1 = BT_GPU_FETCH(pAABB, unsorted_indx2*2); + bt3DGrid3F1U max1 = BT_GPU_FETCH(pAABB, unsorted_indx2*2 + 1); + if(cudaTestAABBOverlap(min0, max0, min1, max1)) + { + uint handleIndex2 = min1.uw; + uint k; + for(k = 0; k < curr; k++) + { + uint old_pair = pPairBuff[start+k] & (~BT_3DGRID_PAIR_ANY_FLG); + if(old_pair == handleIndex2) + { + pPairBuff[start+k] |= BT_3DGRID_PAIR_FOUND_FLG; + break; + } + } + if(k == curr) + { + if(curr >= curr_max) + { // not a good solution, but let's avoid crash + break; + } + pPairBuff[start+curr] = handleIndex2 | BT_3DGRID_PAIR_NEW_FLG; + curr++; + } + } + } + } + pPairBuffStartCurr[handleIndex] = BT_GPU_make_uint2(start, curr); + return; +} // findPairsInCell() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void findOverlappingPairsD( bt3DGrid3F1U* pAABB, uint2* pHash, uint* pCellStart, + uint* pPairBuff, uint2* pPairBuffStartCurr, uint numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + uint2 sortedData = pHash[index]; + uint unsorted_indx = sortedData.y; + bt3DGrid3F1U bbMin = BT_GPU_FETCH(pAABB, unsorted_indx*2); + bt3DGrid3F1U bbMax = BT_GPU_FETCH(pAABB, unsorted_indx*2 + 1); + float4 pos; + pos.x = (bbMin.fx + bbMax.fx) * 0.5f; + pos.y = (bbMin.fy + bbMax.fy) * 0.5f; + pos.z = (bbMin.fz + bbMax.fz) * 0.5f; + // get address in grid + int3 gridPos = bt3DGrid_calcGridPos(pos); + // examine only neighbouring cells + for(int z=-1; z<=1; z++) { + for(int y=-1; y<=1; y++) { + for(int x=-1; x<=1; x++) { + findPairsInCell(gridPos + BT_GPU_make_int3(x, y, z), index, pHash, pCellStart, pAABB, pPairBuff, pPairBuffStartCurr, numBodies); + } + } + } +} // findOverlappingPairsD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void findPairsLargeD( bt3DGrid3F1U* pAABB, uint2* pHash, uint* pCellStart, uint* pPairBuff, + uint2* pPairBuffStartCurr, uint numBodies, uint numLarge) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + uint2 sortedData = pHash[index]; + uint unsorted_indx = sortedData.y; + bt3DGrid3F1U min0 = BT_GPU_FETCH(pAABB, unsorted_indx*2); + bt3DGrid3F1U max0 = BT_GPU_FETCH(pAABB, unsorted_indx*2 + 1); + uint handleIndex = min0.uw; + uint2 start_curr = pPairBuffStartCurr[handleIndex]; + uint start = start_curr.x; + uint curr = start_curr.y; + uint2 start_curr_next = pPairBuffStartCurr[handleIndex+1]; + uint curr_max = start_curr_next.x - start - 1; + for(uint i = 0; i < numLarge; i++) + { + uint indx2 = numBodies + i; + bt3DGrid3F1U min1 = BT_GPU_FETCH(pAABB, indx2*2); + bt3DGrid3F1U max1 = BT_GPU_FETCH(pAABB, indx2*2 + 1); + if(cudaTestAABBOverlap(min0, max0, min1, max1)) + { + uint k; + uint handleIndex2 = min1.uw; + for(k = 0; k < curr; k++) + { + uint old_pair = pPairBuff[start+k] & (~BT_3DGRID_PAIR_ANY_FLG); + if(old_pair == handleIndex2) + { + pPairBuff[start+k] |= BT_3DGRID_PAIR_FOUND_FLG; + break; + } + } + if(k == curr) + { + pPairBuff[start+curr] = handleIndex2 | BT_3DGRID_PAIR_NEW_FLG; + if(curr >= curr_max) + { // not a good solution, but let's avoid crash + break; + } + curr++; + } + } + } + pPairBuffStartCurr[handleIndex] = BT_GPU_make_uint2(start, curr); + return; +} // findPairsLargeD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void computePairCacheChangesD(uint* pPairBuff, uint2* pPairBuffStartCurr, + uint* pPairScan, bt3DGrid3F1U* pAABB, uint numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + bt3DGrid3F1U bbMin = pAABB[index * 2]; + uint handleIndex = bbMin.uw; + uint2 start_curr = pPairBuffStartCurr[handleIndex]; + uint start = start_curr.x; + uint curr = start_curr.y; + uint *pInp = pPairBuff + start; + uint num_changes = 0; + for(uint k = 0; k < curr; k++, pInp++) + { + if(!((*pInp) & BT_3DGRID_PAIR_FOUND_FLG)) + { + num_changes++; + } + } + pPairScan[index+1] = num_changes; +} // computePairCacheChangesD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void squeezeOverlappingPairBuffD(uint* pPairBuff, uint2* pPairBuffStartCurr, uint* pPairScan, + uint* pPairOut, bt3DGrid3F1U* pAABB, uint numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + bt3DGrid3F1U bbMin = pAABB[index * 2]; + uint handleIndex = bbMin.uw; + uint2 start_curr = pPairBuffStartCurr[handleIndex]; + uint start = start_curr.x; + uint curr = start_curr.y; + uint* pInp = pPairBuff + start; + uint* pOut = pPairOut + pPairScan[index]; + uint* pOut2 = pInp; + uint num = 0; + for(uint k = 0; k < curr; k++, pInp++) + { + if(!((*pInp) & BT_3DGRID_PAIR_FOUND_FLG)) + { + *pOut = *pInp; + pOut++; + } + if((*pInp) & BT_3DGRID_PAIR_ANY_FLG) + { + *pOut2 = (*pInp) & (~BT_3DGRID_PAIR_ANY_FLG); + pOut2++; + num++; + } + } + pPairBuffStartCurr[handleIndex] = BT_GPU_make_uint2(start, num); +} // squeezeOverlappingPairBuffD() + + +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +// E N D O F K E R N E L F U N C T I O N S +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- + +extern "C" +{ + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(calcHashAABB)(bt3DGrid3F1U* pAABB, unsigned int* hash, unsigned int numBodies) +{ + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); + // execute the kernel + BT_GPU_EXECKERNEL(numBlocks, numThreads, calcHashAABBD, (pAABB, (uint2*)hash, numBodies)); + // check if kernel invocation generated an error + BT_GPU_CHECK_ERROR("calcHashAABBD kernel execution failed"); +} // calcHashAABB() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(findCellStart(unsigned int* hash, unsigned int* cellStart, unsigned int numBodies, unsigned int numCells)) +{ + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); + BT_GPU_SAFE_CALL(BT_GPU_Memset(cellStart, 0xffffffff, numCells*sizeof(uint))); + BT_GPU_EXECKERNEL(numBlocks, numThreads, findCellStartD, ((uint2*)hash, (uint*)cellStart, numBodies)); + BT_GPU_CHECK_ERROR("Kernel execution failed: findCellStartD"); +} // findCellStart() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(findOverlappingPairs(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies)) +{ +#if B_CUDA_USE_TEX + BT_GPU_SAFE_CALL(cudaBindTexture(0, pAABBTex, pAABB, numBodies * 2 * sizeof(bt3DGrid3F1U))); +#endif + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 64, numBlocks, numThreads); + BT_GPU_EXECKERNEL(numBlocks, numThreads, findOverlappingPairsD, (pAABB,(uint2*)pHash,(uint*)pCellStart,(uint*)pPairBuff,(uint2*)pPairBuffStartCurr,numBodies)); + BT_GPU_CHECK_ERROR("Kernel execution failed: bt_CudaFindOverlappingPairsD"); +#if B_CUDA_USE_TEX + BT_GPU_SAFE_CALL(cudaUnbindTexture(pAABBTex)); +#endif +} // findOverlappingPairs() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(findPairsLarge(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies, unsigned int numLarge)) +{ +#if B_CUDA_USE_TEX + BT_GPU_SAFE_CALL(cudaBindTexture(0, pAABBTex, pAABB, (numBodies+numLarge) * 2 * sizeof(bt3DGrid3F1U))); +#endif + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 64, numBlocks, numThreads); + BT_GPU_EXECKERNEL(numBlocks, numThreads, findPairsLargeD, (pAABB,(uint2*)pHash,(uint*)pCellStart,(uint*)pPairBuff,(uint2*)pPairBuffStartCurr,numBodies,numLarge)); + BT_GPU_CHECK_ERROR("Kernel execution failed: btCuda_findPairsLargeD"); +#if B_CUDA_USE_TEX + BT_GPU_SAFE_CALL(cudaUnbindTexture(pAABBTex)); +#endif +} // findPairsLarge() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(computePairCacheChanges(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, bt3DGrid3F1U* pAABB, unsigned int numBodies)) +{ + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); + BT_GPU_EXECKERNEL(numBlocks, numThreads, computePairCacheChangesD, ((uint*)pPairBuff,(uint2*)pPairBuffStartCurr,(uint*)pPairScan,pAABB,numBodies)); + BT_GPU_CHECK_ERROR("Kernel execution failed: btCudaComputePairCacheChangesD"); +} // computePairCacheChanges() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(squeezeOverlappingPairBuff(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, unsigned int* pPairOut, bt3DGrid3F1U* pAABB, unsigned int numBodies)) +{ + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); + BT_GPU_EXECKERNEL(numBlocks, numThreads, squeezeOverlappingPairBuffD, ((uint*)pPairBuff,(uint2*)pPairBuffStartCurr,(uint*)pPairScan,(uint*)pPairOut,pAABB,numBodies)); + BT_GPU_CHECK_ERROR("Kernel execution failed: btCudaSqueezeOverlappingPairBuffD"); +} // btCuda_squeezeOverlappingPairBuff() + +//------------------------------------------------------------------------------------------------ + +} // extern "C" + +//------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------ diff --git a/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h b/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h new file mode 100644 index 0000000..607bda7 --- /dev/null +++ b/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h @@ -0,0 +1,61 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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. +*/ + +//---------------------------------------------------------------------------------------- + +// Shared definitions for GPU-based 3D Grid collision detection broadphase + +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// Keep this file free from Bullet headers +// it is included into both CUDA and CPU code +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +//---------------------------------------------------------------------------------------- + +#ifndef BTGPU3DGRIDBROADPHASESHAREDDEFS_H +#define BTGPU3DGRIDBROADPHASESHAREDDEFS_H + +//---------------------------------------------------------------------------------------- + +#include "btGpu3DGridBroadphaseSharedTypes.h" + +//---------------------------------------------------------------------------------------- + +extern "C" +{ + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(calcHashAABB)(bt3DGrid3F1U* pAABB, unsigned int* hash, unsigned int numBodies); + +void BT_GPU_PREF(findCellStart)(unsigned int* hash, unsigned int* cellStart, unsigned int numBodies, unsigned int numCells); + +void BT_GPU_PREF(findOverlappingPairs)(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies); + +void BT_GPU_PREF(findPairsLarge)(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies, unsigned int numLarge); + +void BT_GPU_PREF(computePairCacheChanges)(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, bt3DGrid3F1U* pAABB, unsigned int numBodies); + +void BT_GPU_PREF(squeezeOverlappingPairBuff)(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, unsigned int* pPairOut, bt3DGrid3F1U* pAABB, unsigned int numBodies); + + +//---------------------------------------------------------------------------------------- + +} // extern "C" + +//---------------------------------------------------------------------------------------- + +#endif // BTGPU3DGRIDBROADPHASESHAREDDEFS_H + diff --git a/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h b/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h new file mode 100644 index 0000000..616a400 --- /dev/null +++ b/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h @@ -0,0 +1,67 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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. +*/ + +//---------------------------------------------------------------------------------------- + +// Shared definitions for GPU-based 3D Grid collision detection broadphase + +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// Keep this file free from Bullet headers +// it is included into both CUDA and CPU code +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +//---------------------------------------------------------------------------------------- + +#ifndef BTGPU3DGRIDBROADPHASESHAREDTYPES_H +#define BTGPU3DGRIDBROADPHASESHAREDTYPES_H + +//---------------------------------------------------------------------------------------- + +#define BT_3DGRID_PAIR_FOUND_FLG (0x40000000) +#define BT_3DGRID_PAIR_NEW_FLG (0x20000000) +#define BT_3DGRID_PAIR_ANY_FLG (BT_3DGRID_PAIR_FOUND_FLG | BT_3DGRID_PAIR_NEW_FLG) + +//---------------------------------------------------------------------------------------- + +struct bt3DGridBroadphaseParams +{ + unsigned int m_gridSizeX; + unsigned int m_gridSizeY; + unsigned int m_gridSizeZ; + unsigned int m_numCells; + float m_worldOriginX; + float m_worldOriginY; + float m_worldOriginZ; + float m_cellSizeX; + float m_cellSizeY; + float m_cellSizeZ; + unsigned int m_numBodies; + unsigned int m_maxBodiesPerCell; +}; + +//---------------------------------------------------------------------------------------- + +struct bt3DGrid3F1U +{ + float fx; + float fy; + float fz; + unsigned int uw; +}; + +//---------------------------------------------------------------------------------------- + +#endif // BTGPU3DGRIDBROADPHASESHAREDTYPES_H + diff --git a/src/BulletMultiThreaded/btGpuDefines.h b/src/BulletMultiThreaded/btGpuDefines.h new file mode 100644 index 0000000..f9315ab --- /dev/null +++ b/src/BulletMultiThreaded/btGpuDefines.h @@ -0,0 +1,211 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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. +*/ + + + +// definitions for "GPU on CPU" code + + +#ifndef BT_GPU_DEFINES_H +#define BT_GPU_DEFINES_H + +typedef unsigned int uint; + +struct int2 +{ + int x, y; +}; + +struct uint2 +{ + unsigned int x, y; +}; + +struct int3 +{ + int x, y, z; +}; + +struct uint3 +{ + unsigned int x, y, z; +}; + +struct float4 +{ + float x, y, z, w; +}; + +struct float3 +{ + float x, y, z; +}; + + +#define BT_GPU___device__ inline +#define BT_GPU___devdata__ +#define BT_GPU___constant__ +#define BT_GPU_max(a, b) ((a) > (b) ? (a) : (b)) +#define BT_GPU_min(a, b) ((a) < (b) ? (a) : (b)) +#define BT_GPU_params s3DGridBroadphaseParams +#define BT_GPU___mul24(a, b) ((a)*(b)) +#define BT_GPU___global__ inline +#define BT_GPU___shared__ static +#define BT_GPU___syncthreads() +#define CUDART_PI_F SIMD_PI + +static inline uint2 bt3dGrid_make_uint2(unsigned int x, unsigned int y) +{ + uint2 t; t.x = x; t.y = y; return t; +} +#define BT_GPU_make_uint2(x, y) bt3dGrid_make_uint2(x, y) + +static inline int3 bt3dGrid_make_int3(int x, int y, int z) +{ + int3 t; t.x = x; t.y = y; t.z = z; return t; +} +#define BT_GPU_make_int3(x, y, z) bt3dGrid_make_int3(x, y, z) + +static inline float3 bt3dGrid_make_float3(float x, float y, float z) +{ + float3 t; t.x = x; t.y = y; t.z = z; return t; +} +#define BT_GPU_make_float3(x, y, z) bt3dGrid_make_float3(x, y, z) + +static inline float3 bt3dGrid_make_float34(float4 f) +{ + float3 t; t.x = f.x; t.y = f.y; t.z = f.z; return t; +} +#define BT_GPU_make_float34(f) bt3dGrid_make_float34(f) + +static inline float3 bt3dGrid_make_float31(float f) +{ + float3 t; t.x = t.y = t.z = f; return t; +} +#define BT_GPU_make_float31(x) bt3dGrid_make_float31(x) + +static inline float4 bt3dGrid_make_float42(float3 v, float f) +{ + float4 t; t.x = v.x; t.y = v.y; t.z = v.z; t.w = f; return t; +} +#define BT_GPU_make_float42(a, b) bt3dGrid_make_float42(a, b) + +static inline float4 bt3dGrid_make_float44(float a, float b, float c, float d) +{ + float4 t; t.x = a; t.y = b; t.z = c; t.w = d; return t; +} +#define BT_GPU_make_float44(a, b, c, d) bt3dGrid_make_float44(a, b, c, d) + +inline int3 operator+(int3 a, int3 b) +{ + return bt3dGrid_make_int3(a.x + b.x, a.y + b.y, a.z + b.z); +} + +inline float4 operator+(const float4& a, const float4& b) +{ + float4 r; r.x = a.x+b.x; r.y = a.y+b.y; r.z = a.z+b.z; r.w = a.w+b.w; return r; +} +inline float4 operator*(const float4& a, float fact) +{ + float4 r; r.x = a.x*fact; r.y = a.y*fact; r.z = a.z*fact; r.w = a.w*fact; return r; +} +inline float4 operator*(float fact, float4& a) +{ + return (a * fact); +} +inline float4& operator*=(float4& a, float fact) +{ + a = fact * a; + return a; +} +inline float4& operator+=(float4& a, const float4& b) +{ + a = a + b; + return a; +} + +inline float3 operator+(const float3& a, const float3& b) +{ + float3 r; r.x = a.x+b.x; r.y = a.y+b.y; r.z = a.z+b.z; return r; +} +inline float3 operator-(const float3& a, const float3& b) +{ + float3 r; r.x = a.x-b.x; r.y = a.y-b.y; r.z = a.z-b.z; return r; +} +static inline float bt3dGrid_dot(float3& a, float3& b) +{ + return a.x*b.x+a.y*b.y+a.z*b.z; +} +#define BT_GPU_dot(a,b) bt3dGrid_dot(a,b) + +static inline float bt3dGrid_dot4(float4& a, float4& b) +{ + return a.x*b.x+a.y*b.y+a.z*b.z+a.w*b.w; +} +#define BT_GPU_dot4(a,b) bt3dGrid_dot4(a,b) + +static inline float3 bt3dGrid_cross(const float3& a, const float3& b) +{ + float3 r; r.x = a.y*b.z-a.z*b.y; r.y = -a.x*b.z+a.z*b.x; r.z = a.x*b.y-a.y*b.x; return r; +} +#define BT_GPU_cross(a,b) bt3dGrid_cross(a,b) + + +inline float3 operator*(const float3& a, float fact) +{ + float3 r; r.x = a.x*fact; r.y = a.y*fact; r.z = a.z*fact; return r; +} + + +inline float3& operator+=(float3& a, const float3& b) +{ + a = a + b; + return a; +} +inline float3& operator-=(float3& a, const float3& b) +{ + a = a - b; + return a; +} +inline float3& operator*=(float3& a, float fact) +{ + a = a * fact; + return a; +} +inline float3 operator-(const float3& v) +{ + float3 r; r.x = -v.x; r.y = -v.y; r.z = -v.z; return r; +} + + +#define BT_GPU_FETCH(a, b) a[b] +#define BT_GPU_FETCH4(a, b) a[b] +#define BT_GPU_PREF(func) btGpu_##func +#define BT_GPU_SAFE_CALL(func) func +#define BT_GPU_Memset memset +#define BT_GPU_MemcpyToSymbol(a, b, c) memcpy(&a, b, c) +#define BT_GPU_BindTexture(a, b, c, d) +#define BT_GPU_UnbindTexture(a) + +static uint2 s_blockIdx, s_blockDim, s_threadIdx; +#define BT_GPU_blockIdx s_blockIdx +#define BT_GPU_blockDim s_blockDim +#define BT_GPU_threadIdx s_threadIdx +#define BT_GPU_EXECKERNEL(numb, numt, kfunc, args) {s_blockDim.x=numt;for(int nb=0;nb c.m_upperLimit) + { + deltaImpulse = c.m_upperLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_upperLimit; + } + else + { + c.m_appliedImpulse = sum; + } + + + if (body1.mMassInv) + { + btVector3 linearComponent = c.m_contactNormal*body1.mMassInv; + body1.mDeltaLinearVelocity += vmVector3(linearComponent.getX()*deltaImpulse,linearComponent.getY()*deltaImpulse,linearComponent.getZ()*deltaImpulse); + btVector3 tmp=c.m_angularComponentA*(btVector3(deltaImpulse,deltaImpulse,deltaImpulse)); + body1.mDeltaAngularVelocity += vmVector3(tmp.getX(),tmp.getY(),tmp.getZ()); + } + + if (body2.mMassInv) + { + btVector3 linearComponent = -c.m_contactNormal*body2.mMassInv; + body2.mDeltaLinearVelocity += vmVector3(linearComponent.getX()*deltaImpulse,linearComponent.getY()*deltaImpulse,linearComponent.getZ()*deltaImpulse); + btVector3 tmp = c.m_angularComponentB*((btVector3(deltaImpulse,deltaImpulse,deltaImpulse)));//*m_angularFactor); + body2.mDeltaAngularVelocity += vmVector3(tmp.getX(),tmp.getY(),tmp.getZ()); + } + + //body1.internalApplyImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse); + //body2.internalApplyImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse); + +} + + +static SIMD_FORCE_INLINE +void pfxSolveLinearConstraintRow(btConstraintRow &constraint, + vmVector3 &deltaLinearVelocityA,vmVector3 &deltaAngularVelocityA, + float massInvA,const vmMatrix3 &inertiaInvA,const vmVector3 &rA, + vmVector3 &deltaLinearVelocityB,vmVector3 &deltaAngularVelocityB, + float massInvB,const vmMatrix3 &inertiaInvB,const vmVector3 &rB) +{ + const vmVector3 normal(btReadVector3(constraint.m_normal)); + btScalar deltaImpulse = constraint.m_rhs; + vmVector3 dVA = deltaLinearVelocityA + cross(deltaAngularVelocityA,rA); + vmVector3 dVB = deltaLinearVelocityB + cross(deltaAngularVelocityB,rB); + deltaImpulse -= constraint.m_jacDiagInv * dot(normal,dVA-dVB); + btScalar oldImpulse = constraint.m_accumImpulse; + constraint.m_accumImpulse = btClamped(oldImpulse + deltaImpulse,constraint.m_lowerLimit,constraint.m_upperLimit); + deltaImpulse = constraint.m_accumImpulse - oldImpulse; + deltaLinearVelocityA += deltaImpulse * massInvA * normal; + deltaAngularVelocityA += deltaImpulse * inertiaInvA * cross(rA,normal); + deltaLinearVelocityB -= deltaImpulse * massInvB * normal; + deltaAngularVelocityB -= deltaImpulse * inertiaInvB * cross(rB,normal); + +} + +void btSolveContactConstraint( + btConstraintRow &constraintResponse, + btConstraintRow &constraintFriction1, + btConstraintRow &constraintFriction2, + const vmVector3 &contactPointA, + const vmVector3 &contactPointB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + float friction + ) +{ + vmVector3 rA = rotate(solverBodyA.mOrientation,contactPointA); + vmVector3 rB = rotate(solverBodyB.mOrientation,contactPointB); + + pfxSolveLinearConstraintRow(constraintResponse, + solverBodyA.mDeltaLinearVelocity,solverBodyA.mDeltaAngularVelocity,solverBodyA.mMassInv,solverBodyA.mInertiaInv,rA, + solverBodyB.mDeltaLinearVelocity,solverBodyB.mDeltaAngularVelocity,solverBodyB.mMassInv,solverBodyB.mInertiaInv,rB); + + float mf = friction*fabsf(constraintResponse.m_accumImpulse); + constraintFriction1.m_lowerLimit = -mf; + constraintFriction1.m_upperLimit = mf; + constraintFriction2.m_lowerLimit = -mf; + constraintFriction2.m_upperLimit = mf; + + pfxSolveLinearConstraintRow(constraintFriction1, + solverBodyA.mDeltaLinearVelocity,solverBodyA.mDeltaAngularVelocity,solverBodyA.mMassInv,solverBodyA.mInertiaInv,rA, + solverBodyB.mDeltaLinearVelocity,solverBodyB.mDeltaAngularVelocity,solverBodyB.mMassInv,solverBodyB.mInertiaInv,rB); + + pfxSolveLinearConstraintRow(constraintFriction2, + solverBodyA.mDeltaLinearVelocity,solverBodyA.mDeltaAngularVelocity,solverBodyA.mMassInv,solverBodyA.mInertiaInv,rA, + solverBodyB.mDeltaLinearVelocity,solverBodyB.mDeltaAngularVelocity,solverBodyB.mMassInv,solverBodyB.mInertiaInv,rB); +} + + +void CustomSolveConstraintsTaskParallel( + const PfxParallelGroup *contactParallelGroup,const PfxParallelBatch *contactParallelBatches, + PfxConstraintPair *contactPairs,uint32_t numContactPairs, + btPersistentManifold* offsetContactManifolds, + const PfxParallelGroup *jointParallelGroup,const PfxParallelBatch *jointParallelBatches, + PfxConstraintPair *jointPairs,uint32_t numJointPairs, + btSolverConstraint* offsetSolverConstraints, + TrbState *offsetRigStates, + PfxSolverBody *offsetSolverBodies, + uint32_t numRigidBodies, + int iteration,unsigned int taskId,unsigned int numTasks,btBarrier *barrier) +{ + + PfxSolverBody staticBody; + staticBody.mMassInv = 0.f; + staticBody.mDeltaAngularVelocity=vmVector3(0,0,0); + staticBody.mDeltaLinearVelocity =vmVector3(0,0,0); + + + for(int k=0;knumPhases;phaseId++) { + for(uint32_t batchId=0;batchIdnumBatches[phaseId];batchId++) { + uint32_t numPairs = jointParallelGroup->numPairs[phaseId*PFX_MAX_SOLVER_BATCHES+batchId]; + if(batchId%numTasks == taskId && numPairs > 0) { + const PfxParallelBatch &batch = jointParallelBatches[phaseId*PFX_MAX_SOLVER_BATCHES+batchId]; + for(uint32_t i=0;isync(); + } + + // Contact + for(uint32_t phaseId=0;phaseIdnumPhases;phaseId++) { + for(uint32_t batchId=0;batchIdnumBatches[phaseId];batchId++) { + uint32_t numPairs = contactParallelGroup->numPairs[phaseId*PFX_MAX_SOLVER_BATCHES+batchId]; + if(batchId%numTasks == taskId && numPairs > 0) { + const PfxParallelBatch &batch = contactParallelBatches[phaseId*PFX_MAX_SOLVER_BATCHES+batchId]; + for(uint32_t i=0;isync(); + } + } +} + +void CustomPostSolverTask( + TrbState *states, + PfxSolverBody *solverBodies, + uint32_t numRigidBodies) +{ + for(uint32_t i=0;i 0.707f) { + // choose p in y-z plane + float a = n[1]*n[1] + n[2]*n[2]; + float k = 1.0f/sqrtf(a); + p[0] = 0; + p[1] = -n[2]*k; + p[2] = n[1]*k; + // set q = n x p + q[0] = a*k; + q[1] = -n[0]*p[2]; + q[2] = n[0]*p[1]; + } + else { + // choose p in x-y plane + float a = n[0]*n[0] + n[1]*n[1]; + float k = 1.0f/sqrtf(a); + p[0] = -n[1]*k; + p[1] = n[0]*k; + p[2] = 0; + // set q = n x p + q[0] = -n[2]*p[1]; + q[1] = n[2]*p[0]; + q[2] = a*k; + } +} + + + +#define PFX_CONTACT_SLOP 0.001f + +void btSetupContactConstraint( + btConstraintRow &constraintResponse, + btConstraintRow &constraintFriction1, + btConstraintRow &constraintFriction2, + float penetrationDepth, + float restitution, + float friction, + const vmVector3 &contactNormal, + const vmVector3 &contactPointA, + const vmVector3 &contactPointB, + const TrbState &stateA, + const TrbState &stateB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + float separateBias, + float timeStep + ) +{ + vmVector3 rA = rotate(solverBodyA.mOrientation,contactPointA); + vmVector3 rB = rotate(solverBodyB.mOrientation,contactPointB); + + vmMatrix3 K = vmMatrix3::scale(vmVector3(solverBodyA.mMassInv + solverBodyB.mMassInv)) - + crossMatrix(rA) * solverBodyA.mInertiaInv * crossMatrix(rA) - + crossMatrix(rB) * solverBodyB.mInertiaInv * crossMatrix(rB); + + vmVector3 vA = stateA.getLinearVelocity() + cross(stateA.getAngularVelocity(),rA); + vmVector3 vB = stateB.getLinearVelocity() + cross(stateB.getAngularVelocity(),rB); + vmVector3 vAB = vA-vB; + + vmVector3 tangent1,tangent2; + btPlaneSpace1(contactNormal,tangent1,tangent2); + +// constraintResponse.m_accumImpulse = 0.f; +// constraintFriction1.m_accumImpulse = 0.f; +// constraintFriction2.m_accumImpulse = 0.f; + + // Contact Constraint + { + vmVector3 normal = contactNormal; + + float denom = dot(K*normal,normal); + + constraintResponse.m_rhs = -(1.0f+restitution)*dot(vAB,normal); // velocity error + constraintResponse.m_rhs -= (separateBias * btMin(0.0f,penetrationDepth+PFX_CONTACT_SLOP)) / timeStep; // position error + constraintResponse.m_rhs /= denom; + constraintResponse.m_jacDiagInv = 1.0f/denom; + constraintResponse.m_lowerLimit = 0.0f; + constraintResponse.m_upperLimit = SIMD_INFINITY; + btStoreVector3(normal,constraintResponse.m_normal); + } + + // Friction Constraint 1 + { + vmVector3 normal = tangent1; + + float denom = dot(K*normal,normal); + + constraintFriction1.m_jacDiagInv = 1.0f/denom; + constraintFriction1.m_rhs = -dot(vAB,normal); + constraintFriction1.m_rhs *= constraintFriction1.m_jacDiagInv; + constraintFriction1.m_lowerLimit = 0.0f; + constraintFriction1.m_upperLimit = SIMD_INFINITY; + btStoreVector3(normal,constraintFriction1.m_normal); + } + + // Friction Constraint 2 + { + vmVector3 normal = tangent2; + + float denom = dot(K*normal,normal); + + constraintFriction2.m_jacDiagInv = 1.0f/denom; + constraintFriction2.m_rhs = -dot(vAB,normal); + constraintFriction2.m_rhs *= constraintFriction2.m_jacDiagInv; + constraintFriction2.m_lowerLimit = 0.0f; + constraintFriction2.m_upperLimit = SIMD_INFINITY; + btStoreVector3(normal,constraintFriction2.m_normal); + } +} + + +void CustomSetupContactConstraintsTask( + PfxConstraintPair *contactPairs,uint32_t numContactPairs, + btPersistentManifold* offsetContactManifolds, + TrbState *offsetRigStates, + PfxSolverBody *offsetSolverBodies, + uint32_t numRigidBodies, + float separateBias, + float timeStep) +{ + for(uint32_t i=0;i 1) restitution = 0.0f; + + float friction = sqrtf(solverBodyA.friction * solverBodyB.friction); + + for(int j=0;jio); + btCriticalSection* criticalsection = io->setupContactConstraints.criticalSection; + + + //CustomCriticalSection *criticalsection = &io->m_cs; + switch(io->cmd) { + + case PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS: + CustomSolveConstraintsTaskParallel( + io->solveConstraints.contactParallelGroup, + io->solveConstraints.contactParallelBatches, + io->solveConstraints.contactPairs, + io->solveConstraints.numContactPairs, + io->solveConstraints.offsetContactManifolds, + + io->solveConstraints.jointParallelGroup, + io->solveConstraints.jointParallelBatches, + io->solveConstraints.jointPairs, + io->solveConstraints.numJointPairs, + io->solveConstraints.offsetSolverConstraints, + io->solveConstraints.offsetRigStates1, + io->solveConstraints.offsetSolverBodies, + io->solveConstraints.numRigidBodies, + io->solveConstraints.iteration, + + io->solveConstraints.taskId, + io->maxTasks1, + io->solveConstraints.barrier + ); + break; + + case PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER: + CustomPostSolverTask( io->postSolver.states,io->postSolver.solverBodies, io->postSolver.numRigidBodies); + break; + + + case PFX_CONSTRAINT_SOLVER_CMD_SETUP_CONTACT_CONSTRAINTS: + { + bool empty = false; + while(!empty) { + int start,batch; + + criticalsection->lock(); + + start = (int)criticalsection->getSharedParam(0); + batch = (int)criticalsection->getSharedParam(1); + + //PFX_PRINTF("taskId %d start %d num %d\n",arg->taskId,start,batch); + + // ŽŸ‚̃oƒbƒtƒ@‚ðƒZƒbƒg + int nextStart = start + batch; + int rest = btMax((int)io->setupContactConstraints.numContactPairs1 - nextStart,0); + int nextBatch = (rest > batch)?batch:rest; + + criticalsection->setSharedParam(0,nextStart); + criticalsection->setSharedParam(1,nextBatch); + + criticalsection->unlock(); + + if(batch > 0) { + CustomSetupContactConstraintsTask( + io->setupContactConstraints.offsetContactPairs+start,batch, + io->setupContactConstraints.offsetContactManifolds, + io->setupContactConstraints.offsetRigStates, +// io->setupContactConstraints.offsetRigBodies, + io->setupContactConstraints.offsetSolverBodies, + io->setupContactConstraints.numRigidBodies, + io->setupContactConstraints.separateBias, + io->setupContactConstraints.timeStep); + } + else { + empty = true; + } + } + } + break; + + default: + { + btAssert(0); + } + } + +} + + +void CustomSetupContactConstraintsNew( + PfxConstraintPair *contactPairs1,uint32_t numContactPairs, + btPersistentManifold *offsetContactManifolds, + TrbState *offsetRigStates, + PfxSolverBody *offsetSolverBodies, + uint32_t numRigidBodies, + float separationBias, + float timeStep, + class btThreadSupportInterface* threadSupport, + btCriticalSection* criticalSection, + btConstraintSolverIO *io + ) +{ + int maxTasks = threadSupport->getNumTasks(); + + int div = (int)maxTasks * 4; + int batch = ((int)numContactPairs + div - 1) / div; +#ifdef __PPU__ + BulletPE2ConstraintSolverSpursSupport* spursThread = (BulletPE2ConstraintSolverSpursSupport*) threadSupport; +#endif + if (criticalSection) + { + criticalSection->setSharedParam(0,0); + criticalSection->setSharedParam(1,btMin(batch,64)); // batched number + } else + { +#ifdef __PPU__ + spursThread->setSharedParam(0,0); + spursThread->setSharedParam(1,btMin(batch,64)); // batched number +#endif //__PPU__ + } + + for(int t=0;tgetBarrierAddress(); + io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress(); +#endif + + +//#define SEQUENTIAL_SETUP +#ifdef SEQUENTIAL_SETUP + CustomSetupContactConstraintsTask(contactPairs1,numContactPairs,offsetContactManifolds,offsetRigStates,offsetSolverBodies,numRigidBodies,separationBias,timeStep); +#else + threadSupport->sendRequest(1,(ppu_address_t)&io[t],t); +#endif + + } +#ifndef SEQUENTIAL_SETUP + unsigned int arg0,arg1; + for(int t=0;twaitForResponse(&arg0,&arg1); + } +#endif //SEQUENTIAL_SETUP + +} + + +void CustomSplitConstraints( + PfxConstraintPair *pairs,uint32_t numPairs, + PfxParallelGroup &group,PfxParallelBatch *batches, + uint32_t numTasks, + uint32_t numRigidBodies, + void *poolBuff, + uint32_t poolBytes + ) +{ + HeapManager pool((unsigned char*)poolBuff,poolBytes); + + // ƒXƒe[ƒgƒ`ƒFƒbƒN—pƒrƒbƒgƒtƒ‰ƒOƒe[ƒuƒ‹ + int bufSize = sizeof(uint8_t)*numRigidBodies; + bufSize = ((bufSize+127)>>7)<<7; // 128 bytes alignment + uint8_t *bodyTable = (uint8_t*)pool.allocate(bufSize,HeapManager::ALIGN128); + + // ƒyƒAƒ`ƒFƒbƒN—pƒrƒbƒgƒtƒ‰ƒOƒe[ƒuƒ‹ + uint32_t *pairTable; + size_t allocSize = sizeof(uint32_t)*((numPairs+31)/32); + pairTable = (uint32_t*)pool.allocate(allocSize); + memset(pairTable,0,allocSize); + + // –Ú•W‚Æ‚·‚镪Š„” + uint32_t targetCount = btMax(uint32_t(PFX_MIN_SOLVER_PAIRS),btMin(numPairs / (numTasks*2),uint32_t(PFX_MAX_SOLVER_PAIRS))); + uint32_t startIndex = 0; + + uint32_t phaseId; + uint32_t batchId; + uint32_t totalCount=0; + + uint32_t maxBatches = btMin(numTasks,uint32_t(PFX_MAX_SOLVER_BATCHES)); + + for(phaseId=0;phaseId>5; + uint32_t maskP = 1L << (i & 31); + + //pair is already assigned to a phase/batch + if(pairTable[idxP] & maskP) { + continue; + } + + uint32_t idxA = pfxGetRigidBodyIdA(pairs[i]); + uint32_t idxB = pfxGetRigidBodyIdB(pairs[i]); + + // —¼•û‚Æ‚àƒAƒNƒeƒBƒu‚Å‚È‚¢A‚Ü‚½‚͏Փ˓_‚ª‚O‚̃yƒA‚Í“o˜^‘Ώۂ©‚ç‚Í‚¸‚· + if(!pfxGetActive(pairs[i]) || pfxGetNumConstraints(pairs[i]) == 0 || + ((pfxGetMotionMaskA(pairs[i])&PFX_MOTION_MASK_STATIC) && (pfxGetMotionMaskB(pairs[i])&PFX_MOTION_MASK_STATIC)) ) { + if(startIndexCheck) + startIndex++; + //assign pair -> skip it because it has no constraints + pairTable[idxP] |= maskP; + totalCount++; + continue; + } + + // ˆË‘¶«‚̃`ƒFƒbƒN + if( (bodyTable[idxA] != batchId && bodyTable[idxA] != 0xff) || + (bodyTable[idxB] != batchId && bodyTable[idxB] != 0xff) ) { + startIndexCheck = false; + //bodies of the pair are already assigned to another batch within this phase + continue; + } + + // ˆË‘¶«”»’èƒe[ƒuƒ‹‚É“o˜^ + if(pfxGetMotionMaskA(pairs[i])&PFX_MOTION_MASK_DYNAMIC) + bodyTable[idxA] = batchId; + if(pfxGetMotionMaskB(pairs[i])&PFX_MOTION_MASK_DYNAMIC) + bodyTable[idxB] = batchId; + + if(startIndexCheck) + startIndex++; + + pairTable[idxP] |= maskP; + //add the pair 'i' to the current batch + batch.pairIndices[pairId++] = i; + pairCount++; + } + + group.numPairs[phaseId*PFX_MAX_SOLVER_BATCHES+batchId] = (uint16_t)pairId; + totalCount += pairCount; + } + + group.numBatches[phaseId] = batchId; + } + + group.numPhases = phaseId; + + pool.clear(); +} + + + +void CustomSolveConstraintsParallel( + PfxConstraintPair *contactPairs,uint32_t numContactPairs, + + PfxConstraintPair *jointPairs,uint32_t numJointPairs, + btPersistentManifold* offsetContactManifolds, + btSolverConstraint* offsetSolverConstraints, + TrbState *offsetRigStates, + PfxSolverBody *offsetSolverBodies, + uint32_t numRigidBodies, + struct btConstraintSolverIO* io, + class btThreadSupportInterface* threadSupport, + int iteration, + void* poolBuf, + int poolBytes, + class btBarrier* barrier) + { + + int maxTasks = threadSupport->getNumTasks(); +// config.taskManager->setTaskEntry(PFX_SOLVER_ENTRY); + + HeapManager pool((unsigned char*)poolBuf,poolBytes); + + { + PfxParallelGroup *cgroup = (PfxParallelGroup*)pool.allocate(sizeof(PfxParallelGroup)); + PfxParallelBatch *cbatches = (PfxParallelBatch*)pool.allocate(sizeof(PfxParallelBatch)*(PFX_MAX_SOLVER_PHASES*PFX_MAX_SOLVER_BATCHES),128); + PfxParallelGroup *jgroup = (PfxParallelGroup*)pool.allocate(sizeof(PfxParallelGroup)); + PfxParallelBatch *jbatches = (PfxParallelBatch*)pool.allocate(sizeof(PfxParallelBatch)*(PFX_MAX_SOLVER_PHASES*PFX_MAX_SOLVER_BATCHES),128); + + uint32_t tmpBytes = poolBytes - 2 * (sizeof(PfxParallelGroup) + sizeof(PfxParallelBatch)*(PFX_MAX_SOLVER_PHASES*PFX_MAX_SOLVER_BATCHES) + 128); + void *tmpBuff = pool.allocate(tmpBytes); + + { + BT_PROFILE("CustomSplitConstraints"); + CustomSplitConstraints(contactPairs,numContactPairs,*cgroup,cbatches,maxTasks,numRigidBodies,tmpBuff,tmpBytes); + CustomSplitConstraints(jointPairs,numJointPairs,*jgroup,jbatches,maxTasks,numRigidBodies,tmpBuff,tmpBytes); + } + + { + BT_PROFILE("PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS"); +//#define SOLVE_SEQUENTIAL +#ifdef SOLVE_SEQUENTIAL + CustomSolveConstraintsTask( + io->solveConstraints.contactParallelGroup, + io->solveConstraints.contactParallelBatches, + io->solveConstraints.contactPairs, + io->solveConstraints.numContactPairs, + io->solveConstraints.offsetContactManifolds, + + io->solveConstraints.jointParallelGroup, + io->solveConstraints.jointParallelBatches, + io->solveConstraints.jointPairs, + io->solveConstraints.numJointPairs, + io->solveConstraints.offsetJoints, + + io->solveConstraints.offsetRigStates, + io->solveConstraints.offsetSolverBodies, + io->solveConstraints.numRigidBodies, + io->solveConstraints.iteration,0,1,0);//arg->taskId,1,0);//,arg->maxTasks,arg->barrier); +#else + for(int t=0;tgetBarrierAddress(); + io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress(); +#endif + + threadSupport->sendRequest(1,(ppu_address_t)&io[t],t); + } + + unsigned int arg0,arg1; + for(int t=0;twaitForResponse(&arg0,&arg1); + } +#endif + } + pool.clear(); + } + + { + BT_PROFILE("PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER"); + int batch = ((int)numRigidBodies + maxTasks - 1) / maxTasks; + int rest = (int)numRigidBodies; + int start = 0; + + for(int t=0;t 0 ? batch : rest; + io[t].cmd = PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER; + io[t].postSolver.states = offsetRigStates + start; + io[t].postSolver.solverBodies = offsetSolverBodies + start; + io[t].postSolver.numRigidBodies = (uint32_t)num; + io[t].maxTasks1 = maxTasks; +#ifdef __PPU__ + BulletPE2ConstraintSolverSpursSupport* spursThread = (BulletPE2ConstraintSolverSpursSupport*) threadSupport; + io[t].barrierAddr2 = (unsigned int)spursThread->getBarrierAddress(); + io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress(); +#endif + +#ifdef SOLVE_SEQUENTIAL + CustomPostSolverTask( io[t].postSolver.states,io[t].postSolver.solverBodies, io[t].postSolver.numRigidBodies); +#else + threadSupport->sendRequest(1,(ppu_address_t)&io[t],t); +#endif + rest -= num; + start += num; + } + + unsigned int arg0,arg1; + for(int t=0;twaitForResponse(&arg0,&arg1); +#endif + } + } + +} + + + +void BPE_customConstraintSolverSequentialNew(unsigned int new_num, PfxBroadphasePair *new_pairs1 , + btPersistentManifold* offsetContactManifolds, + TrbState* states,int numRigidBodies, + struct PfxSolverBody* solverBodies, + PfxConstraintPair* jointPairs, unsigned int numJoints, + btSolverConstraint* offsetSolverConstraints, + float separateBias, + float timeStep, + int iteration, + btThreadSupportInterface* solverThreadSupport, + btCriticalSection* criticalSection, + struct btConstraintSolverIO* solverIO, + btBarrier* barrier + ) +{ + + { + BT_PROFILE("pfxSetupConstraints"); + + for(uint32_t i=0;i m_mystates; + btAlignedObjectArray m_mysolverbodies; + btAlignedObjectArray m_mypairs; + btAlignedObjectArray m_jointPairs; + +}; + + +btConstraintSolverIO* createSolverIO(int numThreads) +{ + return new btConstraintSolverIO[numThreads]; +} + +btParallelConstraintSolver::btParallelConstraintSolver(btThreadSupportInterface* solverThreadSupport) +{ + + m_solverThreadSupport = solverThreadSupport;//createSolverThreadSupport(maxNumThreads); + m_solverIO = createSolverIO(m_solverThreadSupport->getNumTasks()); + + m_barrier = m_solverThreadSupport->createBarrier(); + m_criticalSection = m_solverThreadSupport->createCriticalSection(); + + m_memoryCache = new btParallelSolverMemoryCache(); +} + +btParallelConstraintSolver::~btParallelConstraintSolver() +{ + delete m_memoryCache; + delete m_solverIO; +} + + + +btScalar btParallelConstraintSolver::solveGroup(btCollisionObject** bodies1,int numRigidBodies,btPersistentManifold** manifoldPtr,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher) +{ + +/* int sz = sizeof(PfxSolverBody); + int sz2 = sizeof(vmVector3); + int sz3 = sizeof(vmMatrix3); + int sz4 = sizeof(vmQuat); + int sz5 = sizeof(btConstraintRow); + int sz6 = sizeof(btSolverConstraint); + int sz7 = sizeof(TrbState); +*/ + + btPersistentManifold* offsetContactManifolds= (btPersistentManifold*) dispatcher->getInternalManifoldPool()->getPoolAddress(); + + + m_memoryCache->m_mysolverbodies.resize(numRigidBodies); + m_memoryCache->m_mystates.resize(numRigidBodies); + + { + BT_PROFILE("create states and solver bodies"); + for (int i=0;isetCompanionId(i); + + PfxSolverBody& solverBody = m_memoryCache->m_mysolverbodies[i]; + btRigidBody* rb = btRigidBody::upcast(obj); + TrbState& state = m_memoryCache->m_mystates[i]; + + state.reset(); + const btQuaternion& orgOri = obj->getWorldTransform().getRotation(); + vmQuat orn(orgOri.getX(),orgOri.getY(),orgOri.getZ(),orgOri.getW()); + state.setPosition(getVmVector3(obj->getWorldTransform().getOrigin())); + state.setOrientation(orn); + state.setPosition(state.getPosition()); + state.setRigidBodyId(i); + state.setAngularDamping(0); + state.setLinearDamping(0); + + + solverBody.mOrientation = state.getOrientation(); + solverBody.mDeltaLinearVelocity = vmVector3(0.0f); + solverBody.mDeltaAngularVelocity = vmVector3(0.0f); + solverBody.friction = obj->getFriction(); + solverBody.restitution = obj->getRestitution(); + + state.resetSleepCount(); + + //if(state.getMotionMask()&PFX_MOTION_MASK_DYNAMIC) { + if (rb && (rb->getInvMass()>0.f)) + { + state.setAngularVelocity(vmVector3(rb->getAngularVelocity().getX(),rb->getAngularVelocity().getY(),rb->getAngularVelocity().getZ())); + state.setLinearVelocity(vmVector3(rb->getLinearVelocity().getX(),rb->getLinearVelocity().getY(),rb->getLinearVelocity().getZ())); + + state.setMotionType(PfxMotionTypeActive); + vmMatrix3 ori(solverBody.mOrientation); + vmMatrix3 localInvInertia = vmMatrix3::identity(); + localInvInertia.setCol(0,vmVector3(rb->getInvInertiaDiagLocal().getX(),0,0)); + localInvInertia.setCol(1,vmVector3(0, rb->getInvInertiaDiagLocal().getY(),0)); + localInvInertia.setCol(2,vmVector3(0,0, rb->getInvInertiaDiagLocal().getZ())); + + solverBody.mMassInv = rb->getInvMass(); + solverBody.mInertiaInv = ori * localInvInertia * transpose(ori); + } else + { + state.setAngularVelocity(vmVector3(0)); + state.setLinearVelocity(vmVector3(0)); + + state.setMotionType(PfxMotionTypeFixed); + m_memoryCache->m_mysolverbodies[i].mMassInv = 0.f; + m_memoryCache->m_mysolverbodies[i].mInertiaInv = vmMatrix3(0.0f); + } + + } + } + + + + int totalPoints = 0; +#ifndef USE_C_ARRAYS + m_memoryCache->m_mypairs.resize(numManifolds); + m_memoryCache->m_jointPairs.resize(numConstraints); +#endif//USE_C_ARRAYS + + int actualNumManifolds= 0; + { + BT_PROFILE("convert manifolds"); + for (int i1=0;i1getNumContacts()>0) + { + btPersistentManifold* m = manifoldPtr[i1]; + btCollisionObject* obA = (btCollisionObject*)m->getBody0(); + btCollisionObject* obB = (btCollisionObject*)m->getBody1(); + bool obAisActive = !obA->isStaticOrKinematicObject() && obA->isActive(); + bool obBisActive = !obB->isStaticOrKinematicObject() && obB->isActive(); + + if (!obAisActive && !obBisActive) + continue; + + + //int contactId = i1;//actualNumManifolds; + + PfxBroadphasePair& pair = m_memoryCache->m_mypairs[actualNumManifolds]; + //init those + float compFric = obA->getFriction()*obB->getFriction();//@todo + int idA = obA->getCompanionId(); + int idB = obB->getCompanionId(); + + m->m_companionIdA = idA; + m->m_companionIdB = idB; + + + // if ((mysolverbodies[idA].mMassInv!=0)&&(mysolverbodies[idB].mMassInv!=0)) + // continue; + int numPosPoints=0; + for (int p=0;pgetNumContacts();p++) + { + //btManifoldPoint& pt = m->getContactPoint(p); + //float dist = pt.getDistance(); + //if (dist<0.001) + numPosPoints++; + } + + + numPosPoints = numPosPoints; + totalPoints+=numPosPoints; + pfxSetRigidBodyIdA(pair,idA); + pfxSetRigidBodyIdB(pair,idB); + pfxSetMotionMaskA(pair,m_memoryCache->m_mystates[idA].getMotionMask()); + pfxSetMotionMaskB(pair,m_memoryCache->m_mystates[idB].getMotionMask()); + pfxSetActive(pair,numPosPoints>0); + + pfxSetBroadphaseFlag(pair,0); + int contactId = m-offsetContactManifolds; + //likely the contact pool is not contiguous, make sure to allocate large enough contact pool + btAssert(contactId>=0); + btAssert(contactIdgetInternalManifoldPool()->getMaxCount()); + + pfxSetContactId(pair,contactId); + pfxSetNumConstraints(pair,numPosPoints);//manifoldPtr[i]->getNumContacts()); + actualNumManifolds++; + } + + } + } + + PfxConstraintPair* jointPairs=0; + jointPairs = numConstraints? &m_memoryCache->m_jointPairs[0]:0; + int actualNumJoints=0; + + + btSolverConstraint* offsetSolverConstraints = 0; + + //if (1) + { + + { + BT_PROFILE("convert constraints"); + + int totalNumRows = 0; + int i; + + m_tmpConstraintSizesPool.resize(numConstraints); + //calculate the total number of contraint rows + for (i=0;igetInfo1(&info1); + totalNumRows += info1.m_numConstraintRows; + } + m_tmpSolverNonContactConstraintPool.resize(totalNumRows); + offsetSolverConstraints =totalNumRows? &m_tmpSolverNonContactConstraintPool[0]:0; + + + ///setup the btSolverConstraints + int currentRow = 0; + + for (i=0;igetRigidBodyA(); + btRigidBody& rbB = constraint->getRigidBodyB(); + + + int j; + for ( j=0;jm_contactNormal; + info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal; + info2.m_J2linearAxis = 0; + info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal; + info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this + ///the size of btSolverConstraint needs be a multiple of btScalar + btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint)); + info2.m_constraintError = ¤tConstraintRow->m_rhs; + currentConstraintRow->m_cfm = infoGlobal.m_globalCfm; + info2.cfm = ¤tConstraintRow->m_cfm; + info2.m_lowerLimit = ¤tConstraintRow->m_lowerLimit; + info2.m_upperLimit = ¤tConstraintRow->m_upperLimit; + info2.m_numIterations = infoGlobal.m_numIterations; + constraints[i]->getInfo2(&info2); + + + int idA = constraint->getRigidBodyA().getCompanionId(); + int idB = constraint->getRigidBodyB().getCompanionId(); + + + ///finalize the constraint setup + for ( j=0;jgetRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor(); + } + { + const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal; + solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor(); + } + + { + btVector3 iMJlA = solverConstraint.m_contactNormal*rbA.getInvMass(); + btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal; + btVector3 iMJlB = solverConstraint.m_contactNormal*rbB.getInvMass();//sign of normal? + btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal; + + btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal); + sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal); + sum += iMJlB.dot(solverConstraint.m_contactNormal); + sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal); + + solverConstraint.m_jacDiagABInv = btScalar(1.)/sum; + } + + + ///fix rhs + ///todo: add force/torque accelerators + { + btScalar rel_vel; + btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.getLinearVelocity()) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity()); + btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.getLinearVelocity()) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity()); + + rel_vel = vel1Dotn+vel2Dotn; + + btScalar restitution = 0.f; + btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2 + btScalar velocityError = restitution - rel_vel;// * damping; + btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; + solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; + solverConstraint.m_appliedImpulse = 0.f; + + } + } + + PfxConstraintPair& pair = jointPairs[actualNumJoints]; + + int numConstraintRows= info1.m_numConstraintRows; + pfxSetNumConstraints(pair,numConstraintRows); + + + + pfxSetRigidBodyIdA(pair,idA); + pfxSetRigidBodyIdB(pair,idB); + //is this needed? + if (idA>=0) + pfxSetMotionMaskA(pair,m_memoryCache->m_mystates[idA].getMotionMask()); + if (idB>=0) + pfxSetMotionMaskB(pair,m_memoryCache->m_mystates[idB].getMotionMask()); + + pfxSetActive(pair,true); + int id = currentConstraintRow-offsetSolverConstraints; + pfxSetContactId(pair,id); + actualNumJoints++; + + + } + currentRow+=m_tmpConstraintSizesPool[i].m_numConstraintRows; + } + } + } + + + + float separateBias=0.1;//info.m_erp;//or m_erp2? + float timeStep=infoGlobal.m_timeStep; + int iteration=infoGlobal.m_numIterations; + + //create a pair for each constraints, copy over info etc + + + + + + { + BT_PROFILE("compute num contacts"); + int totalContacts =0; + + for (int i=0;im_mypairs[i]; + totalContacts += pfxGetNumConstraints(*pair); + } + //printf("numManifolds = %d\n",numManifolds); + //printf("totalContacts=%d\n",totalContacts); + } + + + +// printf("actualNumManifolds=%d\n",actualNumManifolds); + { + BT_PROFILE("BPE_customConstraintSolverSequentialNew"); + if (numRigidBodies>0 && (actualNumManifolds+actualNumJoints)>0) + { +// PFX_PRINTF("num points = %d\n",totalPoints); +// PFX_PRINTF("num points PFX = %d\n",total); + + + + BPE_customConstraintSolverSequentialNew( + actualNumManifolds, + &m_memoryCache->m_mypairs[0], + offsetContactManifolds, + &m_memoryCache->m_mystates[0],numRigidBodies, + &m_memoryCache->m_mysolverbodies[0], + jointPairs,actualNumJoints, + offsetSolverConstraints, + separateBias,timeStep,iteration, + m_solverThreadSupport,m_criticalSection,m_solverIO,m_barrier); + } + } + + //copy results back to bodies + { + BT_PROFILE("copy back"); + for (int i=0;im_mystates[i]; + if (rb && (rb->getInvMass()>0.f)) + { + rb->setLinearVelocity(btVector3(state.getLinearVelocity().getX(),state.getLinearVelocity().getY(),state.getLinearVelocity().getZ())); + rb->setAngularVelocity(btVector3(state.getAngularVelocity().getX(),state.getAngularVelocity().getY(),state.getAngularVelocity().getZ())); + } + } + } + + + return 0.f; +} diff --git a/src/BulletMultiThreaded/btParallelConstraintSolver.h b/src/BulletMultiThreaded/btParallelConstraintSolver.h new file mode 100644 index 0000000..7c0268e --- /dev/null +++ b/src/BulletMultiThreaded/btParallelConstraintSolver.h @@ -0,0 +1,285 @@ +/* + Copyright (C) 2010 Sony Computer Entertainment Inc. + All rights reserved. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + +#ifndef __BT_PARALLEL_CONSTRAINT_SOLVER_H +#define __BT_PARALLEL_CONSTRAINT_SOLVER_H + +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" + + + + +#include "LinearMath/btScalar.h" +#include "PlatformDefinitions.h" + + +#define PFX_MAX_SOLVER_PHASES 64 +#define PFX_MAX_SOLVER_BATCHES 16 +#define PFX_MAX_SOLVER_PAIRS 128 +#define PFX_MIN_SOLVER_PAIRS 16 + +#ifdef __CELLOS_LV2__ +ATTRIBUTE_ALIGNED128(struct) PfxParallelBatch { +#else +ATTRIBUTE_ALIGNED16(struct) PfxParallelBatch { +#endif + uint16_t pairIndices[PFX_MAX_SOLVER_PAIRS]; +}; + +#ifdef __CELLOS_LV2__ +ATTRIBUTE_ALIGNED128(struct) PfxParallelGroup { +#else +ATTRIBUTE_ALIGNED16(struct) PfxParallelGroup { +#endif + uint16_t numPhases; + uint16_t numBatches[PFX_MAX_SOLVER_PHASES]; + uint16_t numPairs[PFX_MAX_SOLVER_PHASES*PFX_MAX_SOLVER_BATCHES]; +}; + + + +ATTRIBUTE_ALIGNED16(struct) PfxSortData16 { + union { + uint8_t i8data[16]; + uint16_t i16data[8]; + uint32_t i32data[4]; +#ifdef __SPU__ + vec_uint4 vdata; +#endif + }; + +#ifdef __SPU__ + void set8(int elem,uint8_t data) {vdata=(vec_uint4)spu_insert(data,(vec_uchar16)vdata,elem);} + void set16(int elem,uint16_t data) {vdata=(vec_uint4)spu_insert(data,(vec_ushort8)vdata,elem);} + void set32(int elem,uint32_t data) {vdata=(vec_uint4)spu_insert(data,(vec_uint4)vdata,elem);} + uint8_t get8(int elem) const {return spu_extract((vec_uchar16)vdata,elem);} + uint16_t get16(int elem) const {return spu_extract((vec_ushort8)vdata,elem);} + uint32_t get32(int elem) const {return spu_extract((vec_uint4)vdata,elem);} +#else + void set8(int elem,uint8_t data) {i8data[elem] = data;} + void set16(int elem,uint16_t data) {i16data[elem] = data;} + void set32(int elem,uint32_t data) {i32data[elem] = data;} + uint8_t get8(int elem) const {return i8data[elem];} + uint16_t get16(int elem) const {return i16data[elem];} + uint32_t get32(int elem) const {return i32data[elem];} +#endif +}; + +typedef PfxSortData16 PfxConstraintPair; + + +//J PfxBroadphasePair‚Æ‹¤’Ê + +SIMD_FORCE_INLINE void pfxSetConstraintId(PfxConstraintPair &pair,uint32_t i) {pair.set32(2,i);} +SIMD_FORCE_INLINE void pfxSetNumConstraints(PfxConstraintPair &pair,uint8_t n) {pair.set8(7,n);} + +SIMD_FORCE_INLINE uint32_t pfxGetConstraintId1(const PfxConstraintPair &pair) {return pair.get32(2);} +SIMD_FORCE_INLINE uint8_t pfxGetNumConstraints(const PfxConstraintPair &pair) {return pair.get8(7);} + +typedef PfxSortData16 PfxBroadphasePair; + +SIMD_FORCE_INLINE void pfxSetRigidBodyIdA(PfxBroadphasePair &pair,uint16_t i) {pair.set16(0,i);} +SIMD_FORCE_INLINE void pfxSetRigidBodyIdB(PfxBroadphasePair &pair,uint16_t i) {pair.set16(1,i);} +SIMD_FORCE_INLINE void pfxSetMotionMaskA(PfxBroadphasePair &pair,uint8_t i) {pair.set8(4,i);} +SIMD_FORCE_INLINE void pfxSetMotionMaskB(PfxBroadphasePair &pair,uint8_t i) {pair.set8(5,i);} +SIMD_FORCE_INLINE void pfxSetBroadphaseFlag(PfxBroadphasePair &pair,uint8_t f) {pair.set8(6,(pair.get8(6)&0xf0)|(f&0x0f));} +SIMD_FORCE_INLINE void pfxSetActive(PfxBroadphasePair &pair,bool b) {pair.set8(6,(pair.get8(6)&0x0f)|((b?1:0)<<4));} +SIMD_FORCE_INLINE void pfxSetContactId(PfxBroadphasePair &pair,uint32_t i) {pair.set32(2,i);} + +SIMD_FORCE_INLINE uint16_t pfxGetRigidBodyIdA(const PfxBroadphasePair &pair) {return pair.get16(0);} +SIMD_FORCE_INLINE uint16_t pfxGetRigidBodyIdB(const PfxBroadphasePair &pair) {return pair.get16(1);} +SIMD_FORCE_INLINE uint8_t pfxGetMotionMaskA(const PfxBroadphasePair &pair) {return pair.get8(4);} +SIMD_FORCE_INLINE uint8_t pfxGetMotionMaskB(const PfxBroadphasePair &pair) {return pair.get8(5);} +SIMD_FORCE_INLINE uint8_t pfxGetBroadphaseFlag(const PfxBroadphasePair &pair) {return pair.get8(6)&0x0f;} +SIMD_FORCE_INLINE bool pfxGetActive(const PfxBroadphasePair &pair) {return (pair.get8(6)>>4)!=0;} +SIMD_FORCE_INLINE uint32_t pfxGetContactId1(const PfxBroadphasePair &pair) {return pair.get32(2);} + + + +#if defined(__PPU__) || defined (__SPU__) +ATTRIBUTE_ALIGNED128(struct) PfxSolverBody { +#else +ATTRIBUTE_ALIGNED16(struct) PfxSolverBody { +#endif + vmVector3 mDeltaLinearVelocity; + vmVector3 mDeltaAngularVelocity; + vmMatrix3 mInertiaInv; + vmQuat mOrientation; + float mMassInv; + float friction; + float restitution; + float unused; + float unused2; + float unused3; + float unused4; + float unused5; +}; + + +#ifdef __PPU__ +#include "SpuDispatch/BulletPE2ConstraintSolverSpursSupport.h" +#endif + +static SIMD_FORCE_INLINE vmVector3 btReadVector3(const double* p) +{ + float tmp[3] = {float(p[0]),float(p[1]),float(p[2])}; + vmVector3 v; + loadXYZ(v, tmp); + return v; +} + +static SIMD_FORCE_INLINE vmQuat btReadQuat(const double* p) +{ + float tmp[4] = {float(p[0]),float(p[1]),float(p[2]),float(p[4])}; + vmQuat vq; + loadXYZW(vq, tmp); + return vq; +} + +static SIMD_FORCE_INLINE void btStoreVector3(const vmVector3 &src, double* p) +{ + float tmp[3]; + vmVector3 v = src; + storeXYZ(v, tmp); + p[0] = tmp[0]; + p[1] = tmp[1]; + p[2] = tmp[2]; +} + + +static SIMD_FORCE_INLINE vmVector3 btReadVector3(const float* p) +{ + vmVector3 v; + loadXYZ(v, p); + return v; +} + +static SIMD_FORCE_INLINE vmQuat btReadQuat(const float* p) +{ + vmQuat vq; + loadXYZW(vq, p); + return vq; +} + +static SIMD_FORCE_INLINE void btStoreVector3(const vmVector3 &src, float* p) +{ + vmVector3 v = src; + storeXYZ(v, p); +} + + + + +class btPersistentManifold; + +enum { + PFX_CONSTRAINT_SOLVER_CMD_SETUP_SOLVER_BODIES, + PFX_CONSTRAINT_SOLVER_CMD_SETUP_CONTACT_CONSTRAINTS, + PFX_CONSTRAINT_SOLVER_CMD_SETUP_JOINT_CONSTRAINTS, + PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS, + PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER +}; + + +struct PfxSetupContactConstraintsIO { + PfxConstraintPair *offsetContactPairs; + uint32_t numContactPairs1; + btPersistentManifold* offsetContactManifolds; + class TrbState *offsetRigStates; + struct PfxSolverBody *offsetSolverBodies; + uint32_t numRigidBodies; + float separateBias; + float timeStep; + class btCriticalSection* criticalSection; +}; + + + +struct PfxSolveConstraintsIO { + PfxParallelGroup *contactParallelGroup; + PfxParallelBatch *contactParallelBatches; + PfxConstraintPair *contactPairs; + uint32_t numContactPairs; + btPersistentManifold *offsetContactManifolds; + PfxParallelGroup *jointParallelGroup; + PfxParallelBatch *jointParallelBatches; + PfxConstraintPair *jointPairs; + uint32_t numJointPairs; + struct btSolverConstraint* offsetSolverConstraints; + TrbState *offsetRigStates1; + PfxSolverBody *offsetSolverBodies; + uint32_t numRigidBodies; + uint32_t iteration; + + uint32_t taskId; + + class btBarrier* barrier; + +}; + +struct PfxPostSolverIO { + TrbState *states; + PfxSolverBody *solverBodies; + uint32_t numRigidBodies; +}; + +ATTRIBUTE_ALIGNED16(struct) btConstraintSolverIO { + uint8_t cmd; + union { + PfxSetupContactConstraintsIO setupContactConstraints; + PfxSolveConstraintsIO solveConstraints; + PfxPostSolverIO postSolver; + }; + + //SPU only + uint32_t barrierAddr2; + uint32_t criticalsectionAddr2; + uint32_t maxTasks1; +}; + + + + +void SolverThreadFunc(void* userPtr,void* lsMemory); +void* SolverlsMemoryFunc(); +///The btParallelConstraintSolver performs computations on constraint rows in parallel +///Using the cross-platform threading it supports Windows, Linux, Mac OSX and PlayStation 3 Cell SPUs +class btParallelConstraintSolver : public btSequentialImpulseConstraintSolver +{ + +protected: + struct btParallelSolverMemoryCache* m_memoryCache; + + class btThreadSupportInterface* m_solverThreadSupport; + + struct btConstraintSolverIO* m_solverIO; + class btBarrier* m_barrier; + class btCriticalSection* m_criticalSection; + + +public: + + btParallelConstraintSolver(class btThreadSupportInterface* solverThreadSupport); + + virtual ~btParallelConstraintSolver(); + + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher); + +}; + + + +#endif //__BT_PARALLEL_CONSTRAINT_SOLVER_H \ No newline at end of file diff --git a/src/BulletMultiThreaded/btThreadSupportInterface.cpp b/src/BulletMultiThreaded/btThreadSupportInterface.cpp new file mode 100644 index 0000000..8192aa4 --- /dev/null +++ b/src/BulletMultiThreaded/btThreadSupportInterface.cpp @@ -0,0 +1,22 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +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 "btThreadSupportInterface.h" + +btThreadSupportInterface::~btThreadSupportInterface() +{ + +} + diff --git a/src/BulletMultiThreaded/btThreadSupportInterface.h b/src/BulletMultiThreaded/btThreadSupportInterface.h new file mode 100644 index 0000000..16850e2 --- /dev/null +++ b/src/BulletMultiThreaded/btThreadSupportInterface.h @@ -0,0 +1,85 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_THREAD_SUPPORT_INTERFACE_H +#define BT_THREAD_SUPPORT_INTERFACE_H + + +#include //for ATTRIBUTE_ALIGNED16 +#include "PlatformDefinitions.h" +#include "PpuAddressSpace.h" + +class btBarrier { +public: + btBarrier() {} + virtual ~btBarrier() {} + + virtual void sync() = 0; + virtual void setMaxCount(int n) = 0; + virtual int getMaxCount() = 0; +}; + +class btCriticalSection { +public: + btCriticalSection() {} + virtual ~btCriticalSection() {} + + ATTRIBUTE_ALIGNED16(unsigned int mCommonBuff[32]); + + virtual unsigned int getSharedParam(int i) = 0; + virtual void setSharedParam(int i,unsigned int p) = 0; + + virtual void lock() = 0; + virtual void unlock() = 0; +}; + + +class btThreadSupportInterface +{ +public: + + virtual ~btThreadSupportInterface(); + +///send messages to SPUs + virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1) =0; + +///check for messages from SPUs + virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) =0; + + + ///non-blocking test if a task is completed. First implement all versions, and then enable this API + ///virtual bool isTaskCompleted(unsigned int *puiArgument0, unsigned int *puiArgument1, int timeOutInMilliseconds)=0; + +///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) + virtual void startSPU() =0; + +///tell the task scheduler we are done with the SPU tasks + virtual void stopSPU()=0; + + ///tell the task scheduler to use no more than numTasks tasks + virtual void setNumTasks(int numTasks)=0; + + virtual int getNumTasks() const = 0; + + virtual btBarrier* createBarrier() = 0; + + virtual btCriticalSection* createCriticalSection() = 0; + + virtual void* getThreadLocalMemory(int taskId) { return 0; } + +}; + +#endif //BT_THREAD_SUPPORT_INTERFACE_H + diff --git a/src/BulletMultiThreaded/vectormath2bullet.h b/src/BulletMultiThreaded/vectormath2bullet.h new file mode 100644 index 0000000..11ee33a --- /dev/null +++ b/src/BulletMultiThreaded/vectormath2bullet.h @@ -0,0 +1,73 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef BT_AOS_VECTORMATH_BULLET_CONVERT_H +#define BT_AOS_VECTORMATH_BULLET_CONVERT_H + +#include "PlatformDefinitions.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btMatrix3x3.h" + +inline Vectormath::Aos::Vector3 getVmVector3(const btVector3& bulletVec) +{ + return Vectormath::Aos::Vector3(bulletVec.getX(),bulletVec.getY(),bulletVec.getZ()); +} + +inline btVector3 getBtVector3(const Vectormath::Aos::Vector3& vmVec) +{ + return btVector3(vmVec.getX(),vmVec.getY(),vmVec.getZ()); +} +inline btVector3 getBtVector3(const Vectormath::Aos::Point3& vmVec) +{ + return btVector3(vmVec.getX(),vmVec.getY(),vmVec.getZ()); +} + +inline Vectormath::Aos::Quat getVmQuat(const btQuaternion& bulletQuat) +{ + Vectormath::Aos::Quat vmQuat(bulletQuat.getX(),bulletQuat.getY(),bulletQuat.getZ(),bulletQuat.getW()); + return vmQuat; +} + +inline btQuaternion getBtQuat(const Vectormath::Aos::Quat& vmQuat) +{ + return btQuaternion (vmQuat.getX(),vmQuat.getY(),vmQuat.getZ(),vmQuat.getW()); +} + +inline Vectormath::Aos::Matrix3 getVmMatrix3(const btMatrix3x3& btMat) +{ + Vectormath::Aos::Matrix3 mat( + getVmVector3(btMat.getColumn(0)), + getVmVector3(btMat.getColumn(1)), + getVmVector3(btMat.getColumn(2))); + return mat; +} + + +#endif //BT_AOS_VECTORMATH_BULLET_CONVERT_H diff --git a/src/BulletSoftBody/CMakeLists.txt b/src/BulletSoftBody/CMakeLists.txt new file mode 100644 index 0000000..1053795 --- /dev/null +++ b/src/BulletSoftBody/CMakeLists.txt @@ -0,0 +1,65 @@ + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src + +) + +#SUBDIRS( Solvers ) + +SET(BulletSoftBody_SRCS + btSoftBody.cpp + btSoftBodyConcaveCollisionAlgorithm.cpp + btSoftBodyHelpers.cpp + btSoftBodyRigidBodyCollisionConfiguration.cpp + btSoftRigidCollisionAlgorithm.cpp + btSoftRigidDynamicsWorld.cpp + btSoftSoftCollisionAlgorithm.cpp + btDefaultSoftBodySolver.cpp + +) + +SET(BulletSoftBody_HDRS + btSoftBody.h + btSoftBodyData.h + btSoftBodyConcaveCollisionAlgorithm.h + btSoftBodyHelpers.h + btSoftBodyRigidBodyCollisionConfiguration.h + btSoftRigidCollisionAlgorithm.h + btSoftRigidDynamicsWorld.h + btSoftSoftCollisionAlgorithm.h + btSparseSDF.h + + btSoftBodySolvers.h + btDefaultSoftBodySolver.h + + btSoftBodySolverVertexBuffer.h +) + + + +ADD_LIBRARY(BulletSoftBody ${BulletSoftBody_SRCS} ${BulletSoftBody_HDRS}) +SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletSoftBody BulletDynamics) +ENDIF (BUILD_SHARED_LIBS) + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBody DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBody DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN +".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES PUBLIC_HEADER "${BulletSoftBody_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/src/BulletSoftBody/btDefaultSoftBodySolver.cpp b/src/BulletSoftBody/btDefaultSoftBodySolver.cpp new file mode 100644 index 0000000..d1435b6 --- /dev/null +++ b/src/BulletSoftBody/btDefaultSoftBodySolver.cpp @@ -0,0 +1,151 @@ +/* +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 "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" + +#include "btDefaultSoftBodySolver.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletSoftBody/btSoftBody.h" + + +btDefaultSoftBodySolver::btDefaultSoftBodySolver() +{ + // Initial we will clearly need to update solver constants + // For now this is global for the cloths linked with this solver - we should probably make this body specific + // for performance in future once we understand more clearly when constants need to be updated + m_updateSolverConstants = true; +} + +btDefaultSoftBodySolver::~btDefaultSoftBodySolver() +{ +} + +// In this case the data is already in the soft bodies so there is no need for us to do anything +void btDefaultSoftBodySolver::copyBackToSoftBodies(bool bMove) +{ + +} + +void btDefaultSoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate) +{ + m_softBodySet.copyFromArray( softBodies ); +} + +void btDefaultSoftBodySolver::updateSoftBodies( ) +{ + for ( int i=0; i < m_softBodySet.size(); i++) + { + btSoftBody* psb=(btSoftBody*)m_softBodySet[i]; + if (psb->isActive()) + { + psb->integrateMotion(); + } + } +} // updateSoftBodies + +bool btDefaultSoftBodySolver::checkInitialized() +{ + return true; +} + +void btDefaultSoftBodySolver::solveConstraints( float solverdt ) +{ + // Solve constraints for non-solver softbodies + for(int i=0; i < m_softBodySet.size(); ++i) + { + btSoftBody* psb = static_cast(m_softBodySet[i]); + if (psb->isActive()) + { + psb->solveConstraints(); + } + } +} // btDefaultSoftBodySolver::solveConstraints + + +void btDefaultSoftBodySolver::copySoftBodyToVertexBuffer( const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer ) +{ + // Currently only support CPU output buffers + // TODO: check for DX11 buffers. Take all offsets into the same DX11 buffer + // and use them together on a single kernel call if possible by setting up a + // per-cloth target buffer array for the copy kernel. + + if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER ) + { + const btAlignedObjectArray &clothVertices( softBody->m_nodes ); + int numVertices = clothVertices.size(); + + const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast< btCPUVertexBufferDescriptor* >(vertexBuffer); + float *basePointer = cpuVertexBuffer->getBasePointer(); + + if( vertexBuffer->hasVertexPositions() ) + { + const int vertexOffset = cpuVertexBuffer->getVertexOffset(); + const int vertexStride = cpuVertexBuffer->getVertexStride(); + float *vertexPointer = basePointer + vertexOffset; + + for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex ) + { + btVector3 position = clothVertices[vertexIndex].m_x; + *(vertexPointer + 0) = position.getX(); + *(vertexPointer + 1) = position.getY(); + *(vertexPointer + 2) = position.getZ(); + vertexPointer += vertexStride; + } + } + if( vertexBuffer->hasNormals() ) + { + const int normalOffset = cpuVertexBuffer->getNormalOffset(); + const int normalStride = cpuVertexBuffer->getNormalStride(); + float *normalPointer = basePointer + normalOffset; + + for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex ) + { + btVector3 normal = clothVertices[vertexIndex].m_n; + *(normalPointer + 0) = normal.getX(); + *(normalPointer + 1) = normal.getY(); + *(normalPointer + 2) = normal.getZ(); + normalPointer += normalStride; + } + } + } +} // btDefaultSoftBodySolver::copySoftBodyToVertexBuffer + +void btDefaultSoftBodySolver::processCollision( btSoftBody* softBody, btSoftBody* otherSoftBody) +{ + softBody->defaultCollisionHandler( otherSoftBody); +} + +// For the default solver just leave the soft body to do its collision processing +void btDefaultSoftBodySolver::processCollision( btSoftBody *softBody, btCollisionObject* collisionObject ) +{ + softBody->defaultCollisionHandler( collisionObject ); +} // btDefaultSoftBodySolver::processCollision + + +void btDefaultSoftBodySolver::predictMotion( float timeStep ) +{ + for ( int i=0; i < m_softBodySet.size(); ++i) + { + btSoftBody* psb = m_softBodySet[i]; + + if (psb->isActive()) + { + psb->predictMotion(timeStep); + } + } +} + diff --git a/src/BulletSoftBody/btDefaultSoftBodySolver.h b/src/BulletSoftBody/btDefaultSoftBodySolver.h new file mode 100644 index 0000000..7d9092c --- /dev/null +++ b/src/BulletSoftBody/btDefaultSoftBodySolver.h @@ -0,0 +1,63 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_DEFAULT_SOLVER_H +#define BT_SOFT_BODY_DEFAULT_SOLVER_H + + +#include "BulletSoftBody/btSoftBodySolvers.h" +#include "btSoftBodySolverVertexBuffer.h" + + +class btDefaultSoftBodySolver : public btSoftBodySolver +{ +protected: + /** Variable to define whether we need to update solver constants on the next iteration */ + bool m_updateSolverConstants; + + btAlignedObjectArray< btSoftBody * > m_softBodySet; + + +public: + btDefaultSoftBodySolver(); + + virtual ~btDefaultSoftBodySolver(); + + virtual SolverTypes getSolverType() const + { + return DEFAULT_SOLVER; + } + + virtual bool checkInitialized(); + + virtual void updateSoftBodies( ); + + virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies,bool forceUpdate=false ); + + virtual void copyBackToSoftBodies(bool bMove = true); + + virtual void solveConstraints( float solverdt ); + + virtual void predictMotion( float solverdt ); + + virtual void copySoftBodyToVertexBuffer( const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer ); + + virtual void processCollision( btSoftBody *, btCollisionObject* ); + + virtual void processCollision( btSoftBody*, btSoftBody* ); + +}; + +#endif // #ifndef BT_ACCELERATED_SOFT_BODY_CPU_SOLVER_H diff --git a/src/BulletSoftBody/btSoftBody.cpp b/src/BulletSoftBody/btSoftBody.cpp new file mode 100644 index 0000000..d1b5eb4 --- /dev/null +++ b/src/BulletSoftBody/btSoftBody.cpp @@ -0,0 +1,3538 @@ +/* +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. +*/ +///btSoftBody implementation by Nathanael Presson + +#include "btSoftBodyInternals.h" +#include "BulletSoftBody/btSoftBodySolvers.h" +#include "btSoftBodyData.h" +#include "LinearMath/btSerializer.h" + + +// +btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m) +:m_softBodySolver(0),m_worldInfo(worldInfo) +{ + /* Init */ + initDefaults(); + + /* Default material */ + Material* pm=appendMaterial(); + pm->m_kLST = 1; + pm->m_kAST = 1; + pm->m_kVST = 1; + pm->m_flags = fMaterial::Default; + + /* Nodes */ + const btScalar margin=getCollisionShape()->getMargin(); + m_nodes.resize(node_count); + for(int i=0,ni=node_count;i0?1/n.m_im:0; + n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n); + n.m_material= pm; + } + updateBounds(); + +} + +btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo) +:m_worldInfo(worldInfo) +{ + initDefaults(); +} + + +void btSoftBody::initDefaults() +{ + m_internalType = CO_SOFT_BODY; + m_cfg.aeromodel = eAeroModel::V_Point; + m_cfg.kVCF = 1; + m_cfg.kDG = 0; + m_cfg.kLF = 0; + m_cfg.kDP = 0; + m_cfg.kPR = 0; + m_cfg.kVC = 0; + m_cfg.kDF = (btScalar)0.2; + m_cfg.kMT = 0; + m_cfg.kCHR = (btScalar)1.0; + m_cfg.kKHR = (btScalar)0.1; + m_cfg.kSHR = (btScalar)1.0; + m_cfg.kAHR = (btScalar)0.7; + m_cfg.kSRHR_CL = (btScalar)0.1; + m_cfg.kSKHR_CL = (btScalar)1; + m_cfg.kSSHR_CL = (btScalar)0.5; + m_cfg.kSR_SPLT_CL = (btScalar)0.5; + m_cfg.kSK_SPLT_CL = (btScalar)0.5; + m_cfg.kSS_SPLT_CL = (btScalar)0.5; + m_cfg.maxvolume = (btScalar)1; + m_cfg.timescale = 1; + m_cfg.viterations = 0; + m_cfg.piterations = 1; + m_cfg.diterations = 0; + m_cfg.citerations = 4; + m_cfg.collisions = fCollision::Default; + m_pose.m_bvolume = false; + m_pose.m_bframe = false; + m_pose.m_volume = 0; + m_pose.m_com = btVector3(0,0,0); + m_pose.m_rot.setIdentity(); + m_pose.m_scl.setIdentity(); + m_tag = 0; + m_timeacc = 0; + m_bUpdateRtCst = true; + m_bounds[0] = btVector3(0,0,0); + m_bounds[1] = btVector3(0,0,0); + m_worldTransform.setIdentity(); + setSolver(eSolverPresets::Positions); + + /* Collision shape */ + ///for now, create a collision shape internally + m_collisionShape = new btSoftBodyCollisionShape(this); + m_collisionShape->setMargin(0.25); + + m_initialWorldTransform.setIdentity(); + + m_windVelocity = btVector3(0,0,0); + +} + +// +btSoftBody::~btSoftBody() +{ + //for now, delete the internal shape + delete m_collisionShape; + int i; + + releaseClusters(); + for(i=0;i0) + *pm=*m_materials[0]; + else + ZeroInitialize(*pm); + m_materials.push_back(pm); + return(pm); +} + +// +void btSoftBody::appendNote( const char* text, + const btVector3& o, + const btVector4& c, + Node* n0, + Node* n1, + Node* n2, + Node* n3) +{ + Note n; + ZeroInitialize(n); + n.m_rank = 0; + n.m_text = text; + n.m_offset = o; + n.m_coords[0] = c.x(); + n.m_coords[1] = c.y(); + n.m_coords[2] = c.z(); + n.m_coords[3] = c.w(); + n.m_nodes[0] = n0;n.m_rank+=n0?1:0; + n.m_nodes[1] = n1;n.m_rank+=n1?1:0; + n.m_nodes[2] = n2;n.m_rank+=n2?1:0; + n.m_nodes[3] = n3;n.m_rank+=n3?1:0; + m_notes.push_back(n); +} + +// +void btSoftBody::appendNote( const char* text, + const btVector3& o, + Node* feature) +{ + appendNote(text,o,btVector4(1,0,0,0),feature); +} + +// +void btSoftBody::appendNote( const char* text, + const btVector3& o, + Link* feature) +{ + static const btScalar w=1/(btScalar)2; + appendNote(text,o,btVector4(w,w,0,0), feature->m_n[0], + feature->m_n[1]); +} + +// +void btSoftBody::appendNote( const char* text, + const btVector3& o, + Face* feature) +{ + static const btScalar w=1/(btScalar)3; + appendNote(text,o,btVector4(w,w,w,0), feature->m_n[0], + feature->m_n[1], + feature->m_n[2]); +} + +// +void btSoftBody::appendNode( const btVector3& x,btScalar m) +{ + if(m_nodes.capacity()==m_nodes.size()) + { + pointersToIndices(); + m_nodes.reserve(m_nodes.size()*2+1); + indicesToPointers(); + } + const btScalar margin=getCollisionShape()->getMargin(); + m_nodes.push_back(Node()); + Node& n=m_nodes[m_nodes.size()-1]; + ZeroInitialize(n); + n.m_x = x; + n.m_q = n.m_x; + n.m_im = m>0?1/m:0; + n.m_material = m_materials[0]; + n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n); +} + +// +void btSoftBody::appendLink(int model,Material* mat) +{ + Link l; + if(model>=0) + l=m_links[model]; + else + { ZeroInitialize(l);l.m_material=mat?mat:m_materials[0]; } + m_links.push_back(l); +} + +// +void btSoftBody::appendLink( int node0, + int node1, + Material* mat, + bool bcheckexist) +{ + appendLink(&m_nodes[node0],&m_nodes[node1],mat,bcheckexist); +} + +// +void btSoftBody::appendLink( Node* node0, + Node* node1, + Material* mat, + bool bcheckexist) +{ + if((!bcheckexist)||(!checkLink(node0,node1))) + { + appendLink(-1,mat); + Link& l=m_links[m_links.size()-1]; + l.m_n[0] = node0; + l.m_n[1] = node1; + l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length(); + m_bUpdateRtCst=true; + } +} + +// +void btSoftBody::appendFace(int model,Material* mat) +{ + Face f; + if(model>=0) + { f=m_faces[model]; } + else + { ZeroInitialize(f);f.m_material=mat?mat:m_materials[0]; } + m_faces.push_back(f); +} + +// +void btSoftBody::appendFace(int node0,int node1,int node2,Material* mat) +{ + if (node0==node1) + return; + if (node1==node2) + return; + if (node2==node0) + return; + + appendFace(-1,mat); + Face& f=m_faces[m_faces.size()-1]; + btAssert(node0!=node1); + btAssert(node1!=node2); + btAssert(node2!=node0); + f.m_n[0] = &m_nodes[node0]; + f.m_n[1] = &m_nodes[node1]; + f.m_n[2] = &m_nodes[node2]; + f.m_ra = AreaOf( f.m_n[0]->m_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x); + m_bUpdateRtCst=true; +} + +// +void btSoftBody::appendTetra(int model,Material* mat) +{ +Tetra t; +if(model>=0) + t=m_tetras[model]; + else + { ZeroInitialize(t);t.m_material=mat?mat:m_materials[0]; } +m_tetras.push_back(t); +} + +// +void btSoftBody::appendTetra(int node0, + int node1, + int node2, + int node3, + Material* mat) +{ + appendTetra(-1,mat); + Tetra& t=m_tetras[m_tetras.size()-1]; + t.m_n[0] = &m_nodes[node0]; + t.m_n[1] = &m_nodes[node1]; + t.m_n[2] = &m_nodes[node2]; + t.m_n[3] = &m_nodes[node3]; + t.m_rv = VolumeOf(t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x); + m_bUpdateRtCst=true; +} + +// + +void btSoftBody::appendAnchor(int node,btRigidBody* body, bool disableCollisionBetweenLinkedBodies,btScalar influence) +{ + btVector3 local = body->getWorldTransform().inverse()*m_nodes[node].m_x; + appendAnchor(node,body,local,disableCollisionBetweenLinkedBodies,influence); +} + +// +void btSoftBody::appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies,btScalar influence) +{ + if (disableCollisionBetweenLinkedBodies) + { + if (m_collisionDisabledObjects.findLinearSearch(body)==m_collisionDisabledObjects.size()) + { + m_collisionDisabledObjects.push_back(body); + } + } + + Anchor a; + a.m_node = &m_nodes[node]; + a.m_body = body; + a.m_local = localPivot; + a.m_node->m_battach = 1; + a.m_influence = influence; + m_anchors.push_back(a); +} + +// +void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1) +{ + LJoint* pj = new(btAlignedAlloc(sizeof(LJoint),16)) LJoint(); + pj->m_bodies[0] = body0; + pj->m_bodies[1] = body1; + pj->m_refs[0] = pj->m_bodies[0].xform().inverse()*specs.position; + pj->m_refs[1] = pj->m_bodies[1].xform().inverse()*specs.position; + pj->m_cfm = specs.cfm; + pj->m_erp = specs.erp; + pj->m_split = specs.split; + m_joints.push_back(pj); +} + +// +void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Body body) +{ + appendLinearJoint(specs,m_clusters[0],body); +} + +// +void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body) +{ + appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]); +} + +// +void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1) +{ + AJoint* pj = new(btAlignedAlloc(sizeof(AJoint),16)) AJoint(); + pj->m_bodies[0] = body0; + pj->m_bodies[1] = body1; + pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis()*specs.axis; + pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis()*specs.axis; + pj->m_cfm = specs.cfm; + pj->m_erp = specs.erp; + pj->m_split = specs.split; + pj->m_icontrol = specs.icontrol; + m_joints.push_back(pj); +} + +// +void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Body body) +{ + appendAngularJoint(specs,m_clusters[0],body); +} + +// +void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body) +{ + appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]); +} + +// +void btSoftBody::addForce(const btVector3& force) +{ + for(int i=0,ni=m_nodes.size();i0) + { + n.m_f += force; + } +} + +void btSoftBody::addAeroForceToNode(const btVector3& windVelocity,int nodeIndex) +{ + btAssert(nodeIndex >= 0 && nodeIndex < m_nodes.size()); + + const btScalar dt = m_sst.sdt; + const btScalar kLF = m_cfg.kLF; + const btScalar kDG = m_cfg.kDG; + const btScalar kPR = m_cfg.kPR; + const btScalar kVC = m_cfg.kVC; + const bool as_lift = kLF>0; + const bool as_drag = kDG>0; + const bool as_aero = as_lift || as_drag; + const bool as_vaero = as_aero && (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided); + + Node& n = m_nodes[nodeIndex]; + + if( n.m_im>0 ) + { + btSoftBody::sMedium medium; + + EvaluateMedium(m_worldInfo, n.m_x, medium); + medium.m_velocity = windVelocity; + medium.m_density = m_worldInfo->air_density; + + /* Aerodynamics */ + if(as_vaero) + { + const btVector3 rel_v = n.m_v - medium.m_velocity; + const btScalar rel_v_len = rel_v.length(); + const btScalar rel_v2 = rel_v.length2(); + + if(rel_v2>SIMD_EPSILON) + { + const btVector3 rel_v_nrm = rel_v.normalized(); + btVector3 nrm = n.m_n; + + if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSidedLiftDrag) + { + nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); + btVector3 fDrag(0, 0, 0); + btVector3 fLift(0, 0, 0); + + btScalar n_dot_v = nrm.dot(rel_v_nrm); + btScalar tri_area = 0.5f * n.m_area; + + fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm); + + // Check angle of attack + // cos(10º) = 0.98480 + if ( 0 < n_dot_v && n_dot_v < 0.98480f) + fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f-n_dot_v*n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm)); + + n.m_f += fDrag; + n.m_f += fLift; + } + else if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_Point || m_cfg.aeromodel == btSoftBody::eAeroModel::V_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided) + { + if (btSoftBody::eAeroModel::V_TwoSided) + nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); + + const btScalar dvn = btDot(rel_v,nrm); + /* Compute forces */ + if(dvn>0) + { + btVector3 force(0,0,0); + const btScalar c0 = n.m_area * dvn * rel_v2/2; + const btScalar c1 = c0 * medium.m_density; + force += nrm*(-c1*kLF); + force += rel_v.normalized() * (-c1 * kDG); + ApplyClampedForce(n, force, dt); + } + } + } + } + } +} + +void btSoftBody::addAeroForceToFace(const btVector3& windVelocity,int faceIndex) +{ + const btScalar dt = m_sst.sdt; + const btScalar kLF = m_cfg.kLF; + const btScalar kDG = m_cfg.kDG; + const btScalar kPR = m_cfg.kPR; + const btScalar kVC = m_cfg.kVC; + const bool as_lift = kLF>0; + const bool as_drag = kDG>0; + const bool as_aero = as_lift || as_drag; + const bool as_faero = as_aero && (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided); + + if(as_faero) + { + btSoftBody::Face& f=m_faces[faceIndex]; + + btSoftBody::sMedium medium; + + const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3; + const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3; + EvaluateMedium(m_worldInfo,x,medium); + medium.m_velocity = windVelocity; + medium.m_density = m_worldInfo->air_density; + const btVector3 rel_v=v-medium.m_velocity; + const btScalar rel_v_len = rel_v.length(); + const btScalar rel_v2=rel_v.length2(); + + if(rel_v2>SIMD_EPSILON) + { + const btVector3 rel_v_nrm = rel_v.normalized(); + btVector3 nrm = f.m_normal; + + if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSidedLiftDrag) + { + nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); + + btVector3 fDrag(0, 0, 0); + btVector3 fLift(0, 0, 0); + + btScalar n_dot_v = nrm.dot(rel_v_nrm); + btScalar tri_area = 0.5f * f.m_ra; + + fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm); + + // Check angle of attack + // cos(10º) = 0.98480 + if ( 0 < n_dot_v && n_dot_v < 0.98480f) + fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f-n_dot_v*n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm)); + + fDrag /= 3; + fLift /= 3; + + for(int j=0;j<3;++j) + { + if (f.m_n[j]->m_im>0) + { + f.m_n[j]->m_f += fDrag; + f.m_n[j]->m_f += fLift; + } + } + } + else if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided) + { + if (btSoftBody::eAeroModel::F_TwoSided) + nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); + + const btScalar dvn=btDot(rel_v,nrm); + /* Compute forces */ + if(dvn>0) + { + btVector3 force(0,0,0); + const btScalar c0 = f.m_ra*dvn*rel_v2; + const btScalar c1 = c0*medium.m_density; + force += nrm*(-c1*kLF); + force += rel_v.normalized()*(-c1*kDG); + force /= 3; + for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt); + } + } + } + } + +} + +// +void btSoftBody::addVelocity(const btVector3& velocity) +{ + for(int i=0,ni=m_nodes.size();i0) + { + n.m_v = velocity; + } + } +} + + +// +void btSoftBody::addVelocity(const btVector3& velocity,int node) +{ + Node& n=m_nodes[node]; + if(n.m_im>0) + { + n.m_v += velocity; + } +} + +// +void btSoftBody::setMass(int node,btScalar mass) +{ + m_nodes[node].m_im=mass>0?1/mass:0; + m_bUpdateRtCst=true; +} + +// +btScalar btSoftBody::getMass(int node) const +{ + return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0); +} + +// +btScalar btSoftBody::getTotalMass() const +{ + btScalar mass=0; + for(int i=0;im_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x); + for(int j=0;j<3;++j) + { + f.m_n[j]->m_im+=twicearea; + } + } + for( i=0;i ranks; +ranks.resize(m_nodes.size(),0); +int i; + +for(i=0;im_im+=btFabs(t.m_rv); + ranks[int(t.m_n[j]-&m_nodes[0])]+=1; + } + } +for( i=0;i0) + { + m_nodes[i].m_im=ranks[i]/m_nodes[i].m_im; + } + } +setTotalMass(mass,false); +} + +// +void btSoftBody::setVolumeDensity(btScalar density) +{ +btScalar volume=0; +for(int i=0;igetMargin(); + ATTRIBUTE_ALIGNED16(btDbvtVolume) vol; + + for(int i=0,ni=m_nodes.size();igetMargin(); + ATTRIBUTE_ALIGNED16(btDbvtVolume) vol; + + for(int i=0,ni=m_nodes.size();i0 ? + 1/(m_nodes[i].m_im*tmass) : + kmass/tmass; + } + /* Pos */ + const btVector3 com=evaluateCom(); + m_pose.m_pos.resize(m_nodes.size()); + for( i=0,ni=m_nodes.size();i0) + { + int i,ni; + + const btVector3 org=m_nodes[0].m_x; + for(i=0,ni=m_faces.size();im_x-org,btCross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org)); + } + vol/=(btScalar)6; + } + return(vol); +} + +// +int btSoftBody::clusterCount() const +{ + return(m_clusters.size()); +} + +// +btVector3 btSoftBody::clusterCom(const Cluster* cluster) +{ + btVector3 com(0,0,0); + for(int i=0,ni=cluster->m_nodes.size();im_nodes[i]->m_x*cluster->m_masses[i]; + } + return(com*cluster->m_imass); +} + +// +btVector3 btSoftBody::clusterCom(int cluster) const +{ + return(clusterCom(m_clusters[cluster])); +} + +// +btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos) +{ + return(cluster->m_lv+btCross(cluster->m_av,rpos)); +} + +// +void btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse) +{ + const btVector3 li=cluster->m_imass*impulse; + const btVector3 ai=cluster->m_invwi*btCross(rpos,impulse); + cluster->m_vimpulses[0]+=li;cluster->m_lv+=li; + cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai; + cluster->m_nvimpulses++; +} + +// +void btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse) +{ + const btVector3 li=cluster->m_imass*impulse; + const btVector3 ai=cluster->m_invwi*btCross(rpos,impulse); + cluster->m_dimpulses[0]+=li; + cluster->m_dimpulses[1]+=ai; + cluster->m_ndimpulses++; +} + +// +void btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse) +{ + if(impulse.m_asVelocity) clusterVImpulse(cluster,rpos,impulse.m_velocity); + if(impulse.m_asDrift) clusterDImpulse(cluster,rpos,impulse.m_drift); +} + +// +void btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse) +{ + const btVector3 ai=cluster->m_invwi*impulse; + cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai; + cluster->m_nvimpulses++; +} + +// +void btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse) +{ + const btVector3 ai=cluster->m_invwi*impulse; + cluster->m_dimpulses[1]+=ai; + cluster->m_ndimpulses++; +} + +// +void btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse) +{ + if(impulse.m_asVelocity) clusterVAImpulse(cluster,impulse.m_velocity); + if(impulse.m_asDrift) clusterDAImpulse(cluster,impulse.m_drift); +} + +// +void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse) +{ + cluster->m_dimpulses[0]+=impulse*cluster->m_imass; + cluster->m_ndimpulses++; +} + +struct NodeLinks +{ + btAlignedObjectArray m_links; +}; + + + +// +int btSoftBody::generateBendingConstraints(int distance,Material* mat) +{ + int i,j; + + if(distance>1) + { + /* Build graph */ + const int n=m_nodes.size(); + const unsigned inf=(~(unsigned)0)>>1; + unsigned* adj=new unsigned[n*n]; + + +#define IDX(_x_,_y_) ((_y_)*n+(_x_)) + for(j=0;j nodeLinks; + + + /* Build node links */ + nodeLinks.resize(m_nodes.size()); + + for( i=0;isum) + { + adj[IDX(i,j)]=adj[IDX(j,i)]=sum; + } + } + + } + } + } + } else + { + ///generic Floyd's algorithm + for(int k=0;ksum) + { + adj[IDX(i,j)]=adj[IDX(j,i)]=sum; + } + } + } + } + } + + + /* Build links */ + int nlinks=0; + for(j=0;jm_leaf) m_cdbvt.remove(c->m_leaf); + c->~Cluster(); + btAlignedFree(c); + m_clusters.remove(c); +} + +// +void btSoftBody::releaseClusters() +{ + while(m_clusters.size()>0) releaseCluster(0); +} + +// +int btSoftBody::generateClusters(int k,int maxiterations) +{ + int i; + releaseClusters(); + m_clusters.resize(btMin(k,m_nodes.size())); + for(i=0;im_collide= true; + } + k=m_clusters.size(); + if(k>0) + { + /* Initialize */ + btAlignedObjectArray centers; + btVector3 cog(0,0,0); + int i; + for(i=0;im_nodes.push_back(&m_nodes[i]); + } + cog/=(btScalar)m_nodes.size(); + centers.resize(k,cog); + /* Iterate */ + const btScalar slope=16; + bool changed; + int iterations=0; + do { + const btScalar w=2-btMin(1,iterations/slope); + changed=false; + iterations++; + int i; + + for(i=0;im_nodes.size();++j) + { + c+=m_clusters[i]->m_nodes[j]->m_x; + } + if(m_clusters[i]->m_nodes.size()) + { + c /= (btScalar)m_clusters[i]->m_nodes.size(); + c = centers[i]+(c-centers[i])*w; + changed |= ((c-centers[i]).length2()>SIMD_EPSILON); + centers[i] = c; + m_clusters[i]->m_nodes.resize(0); + } + } + for(i=0;im_nodes.push_back(&m_nodes[i]); + } + } while(changed&&(iterations cids; + cids.resize(m_nodes.size(),-1); + for(i=0;im_nodes.size();++j) + { + cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i; + } + } + for(i=0;im_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size()) + { + m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]); + } + } + } + } + } + /* Master */ + if(m_clusters.size()>1) + { + Cluster* pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster(); + pmaster->m_collide = false; + pmaster->m_nodes.reserve(m_nodes.size()); + for(int i=0;im_nodes.push_back(&m_nodes[i]); + m_clusters.push_back(pmaster); + btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]); + } + /* Terminate */ + for(i=0;im_nodes.size()==0) + { + releaseCluster(i--); + } + } + } else + { + //create a cluster for each tetrahedron (if tetrahedra exist) or each face + if (m_tetras.size()) + { + m_clusters.resize(m_tetras.size()); + for(i=0;im_collide= true; + } + for (i=0;im_nodes.push_back(m_tetras[i].m_n[j]); + } + } + + } else + { + m_clusters.resize(m_faces.size()); + for(i=0;im_collide= true; + } + + for(i=0;im_nodes.push_back(m_faces[i].m_n[j]); + } + } + } + } + + if (m_clusters.size()) + { + initializeClusters(); + updateClusters(); + + + //for self-collision + m_clusterConnectivity.resize(m_clusters.size()*m_clusters.size()); + { + for (int c0=0;c0m_clusterIndex=c0; + for (int c1=0;c1m_nodes.size();i++) + { + for (int j=0;jm_nodes.size();j++) + { + if (cla->m_nodes[i] == clb->m_nodes[j]) + { + connected=true; + break; + } + } + } + m_clusterConnectivity[c0+c1*m_clusters.size()]=connected; + } + } + } + } + + return(m_clusters.size()); +} + +// +void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut) +{ + const Node* nbase = &m_nodes[0]; + int ncount = m_nodes.size(); + btSymMatrix edges(ncount,-2); + int newnodes=0; + int i,j,k,ni; + + /* Filter out */ + for(i=0;iEval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x))) + { + btSwap(m_links[i],m_links[m_links.size()-1]); + m_links.pop_back();--i; + } + } + } + /* Fill edges */ + for(i=0;i0) + { + const btVector3 x=Lerp(a.m_x,b.m_x,t); + const btVector3 v=Lerp(a.m_v,b.m_v,t); + btScalar m=0; + if(a.m_im>0) + { + if(b.m_im>0) + { + const btScalar ma=1/a.m_im; + const btScalar mb=1/b.m_im; + const btScalar mc=Lerp(ma,mb,t); + const btScalar f=(ma+mb)/(ma+mb+mc); + a.m_im=1/(ma*f); + b.m_im=1/(mb*f); + m=mc*f; + } + else + { a.m_im/=0.5;m=1/a.m_im; } + } + else + { + if(b.m_im>0) + { b.m_im/=0.5;m=1/b.m_im; } + else + m=0; + } + appendNode(x,m); + edges(i,j)=m_nodes.size()-1; + m_nodes[edges(i,j)].m_v=v; + ++newnodes; + } + } + } + } + nbase=&m_nodes[0]; + /* Refine links */ + for(i=0,ni=m_links.size();i0) + { + appendLink(i); + Link* pft[]={ &m_links[i], + &m_links[m_links.size()-1]}; + pft[0]->m_n[0]=&m_nodes[idx[0]]; + pft[0]->m_n[1]=&m_nodes[ni]; + pft[1]->m_n[0]=&m_nodes[ni]; + pft[1]->m_n[1]=&m_nodes[idx[1]]; + } + } + } + /* Refine faces */ + for(i=0;i0) + { + appendFace(i); + const int l=(k+1)%3; + Face* pft[]={ &m_faces[i], + &m_faces[m_faces.size()-1]}; + pft[0]->m_n[0]=&m_nodes[idx[l]]; + pft[0]->m_n[1]=&m_nodes[idx[j]]; + pft[0]->m_n[2]=&m_nodes[ni]; + pft[1]->m_n[0]=&m_nodes[ni]; + pft[1]->m_n[1]=&m_nodes[idx[k]]; + pft[1]->m_n[2]=&m_nodes[idx[l]]; + appendLink(ni,idx[l],pft[0]->m_material); + --i;break; + } + } + } + } + /* Cut */ + if(cut) + { + btAlignedObjectArray cnodes; + const int pcount=ncount; + int i; + ncount=m_nodes.size(); + cnodes.resize(ncount,0); + /* Nodes */ + for(i=0;i=pcount)||(btFabs(ifn->Eval(x))0) { m*=0.5;m_nodes[i].m_im/=0.5; } + appendNode(x,m); + cnodes[i]=m_nodes.size()-1; + m_nodes[cnodes[i]].m_v=v; + } + } + nbase=&m_nodes[0]; + /* Links */ + for(i=0,ni=m_links.size();iEval(m_nodes[id[0]].m_x)Eval(m_nodes[id[1]].m_x)Eval(n[0]->m_x)Eval(n[1]->m_x)Eval(n[2]->m_x) ranks; + btAlignedObjectArray todelete; + ranks.resize(nnodes,0); + for(i=0,ni=m_links.size();i=0;--i) + { + if(!ranks[i]) todelete.push_back(i); + } + if(todelete.size()) + { + btAlignedObjectArray& map=ranks; + for(int i=0;im_v=v; + pn[1]->m_v=v; + for(i=0,ni=m_links.size();im_n[1]=pn[mtch]; + pft[1]->m_n[0]=pn[1-mtch]; + done=true; + } + } + for(i=0,ni=m_faces.size();im_n[l]=pn[mtch]; + pft[1]->m_n[k]=pn[1-mtch]; + appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true); + appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true); + } + } + } + if(!done) + { + m_ndbvt.remove(pn[0]->m_leaf); + m_ndbvt.remove(pn[1]->m_leaf); + m_nodes.pop_back(); + m_nodes.pop_back(); + } + return(done); +} + +// +bool btSoftBody::rayTest(const btVector3& rayFrom, + const btVector3& rayTo, + sRayCast& results) +{ + if(m_faces.size()&&m_fdbvt.empty()) + initializeFaceTree(); + + results.body = this; + results.fraction = 1.f; + results.feature = eFeature::None; + results.index = -1; + + return(rayTest(rayFrom,rayTo,results.fraction,results.feature,results.index,false)!=0); +} + +// +void btSoftBody::setSolver(eSolverPresets::_ preset) +{ + m_cfg.m_vsequence.clear(); + m_cfg.m_psequence.clear(); + m_cfg.m_dsequence.clear(); + switch(preset) + { + case eSolverPresets::Positions: + m_cfg.m_psequence.push_back(ePSolver::Anchors); + m_cfg.m_psequence.push_back(ePSolver::RContacts); + m_cfg.m_psequence.push_back(ePSolver::SContacts); + m_cfg.m_psequence.push_back(ePSolver::Linear); + break; + case eSolverPresets::Velocities: + m_cfg.m_vsequence.push_back(eVSolver::Linear); + + m_cfg.m_psequence.push_back(ePSolver::Anchors); + m_cfg.m_psequence.push_back(ePSolver::RContacts); + m_cfg.m_psequence.push_back(ePSolver::SContacts); + + m_cfg.m_dsequence.push_back(ePSolver::Linear); + break; + } +} + +// +void btSoftBody::predictMotion(btScalar dt) +{ + + int i,ni; + + /* Update */ + if(m_bUpdateRtCst) + { + m_bUpdateRtCst=false; + updateConstants(); + m_fdbvt.clear(); + if(m_cfg.collisions&fCollision::VF_SS) + { + initializeFaceTree(); + } + } + + /* Prepare */ + m_sst.sdt = dt*m_cfg.timescale; + m_sst.isdt = 1/m_sst.sdt; + m_sst.velmrg = m_sst.sdt*3; + m_sst.radmrg = getCollisionShape()->getMargin(); + m_sst.updmrg = m_sst.radmrg*(btScalar)0.25; + /* Forces */ + addVelocity(m_worldInfo->m_gravity*m_sst.sdt); + applyForces(); + /* Integrate */ + for(i=0,ni=m_nodes.size();im_v+ + f.m_n[1]->m_v+ + f.m_n[2]->m_v)/3; + vol = VolumeOf(f,m_sst.radmrg); + m_fdbvt.update( f.m_leaf, + vol, + v*m_sst.velmrg, + m_sst.updmrg); + } + } + /* Pose */ + updatePose(); + /* Match */ + if(m_pose.m_bframe&&(m_cfg.kMT>0)) + { + const btMatrix3x3 posetrs=m_pose.m_rot; + for(int i=0,ni=m_nodes.size();i0) + { + const btVector3 x=posetrs*m_pose.m_pos[i]+m_pose.m_com; + n.m_x=Lerp(n.m_x,x,m_cfg.kMT); + } + } + } + /* Clear contacts */ + m_rcontacts.resize(0); + m_scontacts.resize(0); + /* Optimize dbvt's */ + m_ndbvt.optimizeIncremental(1); + m_fdbvt.optimizeIncremental(1); + m_cdbvt.optimizeIncremental(1); +} + +// +void btSoftBody::solveConstraints() +{ + + /* Apply clusters */ + applyClusters(false); + /* Prepare links */ + + int i,ni; + + for(i=0,ni=m_links.size();im_q-l.m_n[0]->m_q; + l.m_c2 = 1/(l.m_c3.length2()*l.m_c0); + } + /* Prepare anchors */ + for(i=0,ni=m_anchors.size();igetWorldTransform().getBasis()*a.m_local; + a.m_c0 = ImpulseMatrix( m_sst.sdt, + a.m_node->m_im, + a.m_body->getInvMass(), + a.m_body->getInvInertiaTensorWorld(), + ra); + a.m_c1 = ra; + a.m_c2 = m_sst.sdt*a.m_node->m_im; + a.m_body->activate(); + } + /* Solve velocities */ + if(m_cfg.viterations>0) + { + /* Solve */ + for(int isolve=0;isolve0) + { + for(int isolve=0;isolve0) + { + const btScalar vcf=m_cfg.kVCF*m_sst.isdt; + for(i=0,ni=m_nodes.size();i& bodies) +{ + const int nb=bodies.size(); + int iterations=0; + int i; + + for(i=0;im_cfg.citerations); + } + for(i=0;iprepareClusters(iterations); + } + for(i=0;isolveClusters(sor); + } + } + for(i=0;icleanupClusters(); + } +} + +// +void btSoftBody::integrateMotion() +{ + /* Update */ + updateNormals(); +} + +// +btSoftBody::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt) +{ + m_rayFrom = rayFrom; + m_rayNormalizedDirection = (rayTo-rayFrom); + m_rayTo = rayTo; + m_mint = mxt; + m_face = 0; + m_tests = 0; +} + +// +void btSoftBody::RayFromToCaster::Process(const btDbvtNode* leaf) +{ + btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data; + const btScalar t=rayFromToTriangle( m_rayFrom,m_rayTo,m_rayNormalizedDirection, + f.m_n[0]->m_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x, + m_mint); + if((t>0)&&(tteps)&&(tceps) && + (btDot(n,btCross(b-hit,c-hit))>ceps) && + (btDot(n,btCross(c-hit,a-hit))>ceps)) + { + return(t); + } + } + } + return(-1); +} + +// +void btSoftBody::pointersToIndices() +{ +#define PTR2IDX(_p_,_b_) reinterpret_cast((_p_)-(_b_)) + btSoftBody::Node* base=m_nodes.size() ? &m_nodes[0] : 0; + int i,ni; + + for(i=0,ni=m_nodes.size();idata=*(void**)&i; + } + } + for(i=0,ni=m_links.size();idata=*(void**)&i; + } + } + for(i=0,ni=m_anchors.size();idata=&m_nodes[i]; + } + } + for(i=0,ni=m_links.size();idata=&m_faces[i]; + } + } + for(i=0,ni=m_anchors.size();im_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x, + mint); + if(t>0) + { + ++cnt; + if(!bcountonly) + { + feature=btSoftBody::eFeature::Face; + index=i; + mint=t; + } + } + } + } + else + {/* Use dbvt */ + RayFromToCaster collider(rayFrom,rayTo,mint); + + btDbvt::rayTest(m_fdbvt.m_root,rayFrom,rayTo,collider); + if(collider.m_face) + { + mint=collider.m_mint; + feature=btSoftBody::eFeature::Face; + index=(int)(collider.m_face-&m_faces[0]); + cnt=1; + } + } + + for (int i=0;im_x; + btVector3 v1=tet.m_n[index1]->m_x; + btVector3 v2=tet.m_n[index2]->m_x; + + + const btScalar t=RayFromToCaster::rayFromToTriangle( rayFrom,rayTo,dir, + v0,v1,v2, + mint); + if(t>0) + { + ++cnt; + if(!bcountonly) + { + feature=btSoftBody::eFeature::Tetra; + index=i; + mint=t; + } + } + } + } + return(cnt); +} + +// +void btSoftBody::initializeFaceTree() +{ + m_fdbvt.clear(); + for(int i=0;igetCollisionShape(); + btRigidBody *tmpRigid = btRigidBody::upcast(colObj); + const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObj->getWorldTransform(); + btScalar dst = + m_worldInfo->m_sparsesdf.Evaluate( + wtr.invXform(x), + shp, + nrm, + margin); + if(dst<0) + { + cti.m_colObj = colObj; + cti.m_normal = wtr.getBasis()*nrm; + cti.m_offset = -btDot( cti.m_normal, x - cti.m_normal * dst ); + return(true); + } + return(false); +} + +// +void btSoftBody::updateNormals() +{ + + const btVector3 zv(0,0,0); + int i,ni; + + for(i=0,ni=m_nodes.size();im_x-f.m_n[0]->m_x, + f.m_n[2]->m_x-f.m_n[0]->m_x); + f.m_normal=n.normalized(); + f.m_n[0]->m_n+=n; + f.m_n[1]->m_n+=n; + f.m_n[2]->m_n+=n; + } + for(i=0,ni=m_nodes.size();iSIMD_EPSILON) + m_nodes[i].m_n /= len; + } +} + +// +void btSoftBody::updateBounds() +{ + /*if( m_acceleratedSoftBody ) + { + // If we have an accelerated softbody we need to obtain the bounds correctly + // For now (slightly hackily) just have a very large AABB + // TODO: Write get bounds kernel + // If that is updating in place, atomic collisions might be low (when the cloth isn't perfectly aligned to an axis) and we could + // probably do a test and exchange reasonably efficiently. + + m_bounds[0] = btVector3(-1000, -1000, -1000); + m_bounds[1] = btVector3(1000, 1000, 1000); + + } else {*/ + if(m_ndbvt.m_root) + { + const btVector3& mins=m_ndbvt.m_root->volume.Mins(); + const btVector3& maxs=m_ndbvt.m_root->volume.Maxs(); + const btScalar csm=getCollisionShape()->getMargin(); + const btVector3 mrg=btVector3( csm, + csm, + csm)*1; // ??? to investigate... + m_bounds[0]=mins-mrg; + m_bounds[1]=maxs+mrg; + if(0!=getBroadphaseHandle()) + { + m_worldInfo->m_broadphase->setAabb( getBroadphaseHandle(), + m_bounds[0], + m_bounds[1], + m_worldInfo->m_dispatcher); + } + } + else + { + m_bounds[0]= + m_bounds[1]=btVector3(0,0,0); + } + //} +} + + +// +void btSoftBody::updatePose() +{ + if(m_pose.m_bframe) + { + btSoftBody::Pose& pose=m_pose; + const btVector3 com=evaluateCom(); + /* Com */ + pose.m_com = com; + /* Rotation */ + btMatrix3x3 Apq; + const btScalar eps=SIMD_EPSILON; + Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0); + Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3); + for(int i=0,ni=m_nodes.size();i1) + { + const btScalar idet=Clamp( 1/pose.m_scl.determinant(), + 1,m_cfg.maxvolume); + pose.m_scl=Mul(pose.m_scl,idet); + } + + } +} + +// +void btSoftBody::updateConstants() +{ + int i,ni; + + /* Links */ + for(i=0,ni=m_links.size();im_x-l.m_n[1]->m_x).length(); + l.m_c0 = (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST; + l.m_c1 = l.m_rl*l.m_rl; + } + /* Faces */ + for(i=0,ni=m_faces.size();im_x,f.m_n[1]->m_x,f.m_n[2]->m_x); + } + /* Area's */ + btAlignedObjectArray counts; + counts.resize(m_nodes.size(),0); + for(i=0,ni=m_nodes.size();im_area+=btFabs(f.m_ra); + } + } + for(i=0,ni=m_nodes.size();i0) + m_nodes[i].m_area/=(btScalar)counts[i]; + else + m_nodes[i].m_area=0; + } +} + +// +void btSoftBody::initializeClusters() +{ + int i; + + for( i=0;im_im==0) + { + c.m_containsAnchor = true; + c.m_masses[j] = BT_LARGE_FLOAT; + } else + { + c.m_masses[j] = btScalar(1.)/c.m_nodes[j]->m_im; + } + c.m_imass += c.m_masses[j]; + } + c.m_imass = btScalar(1.)/c.m_imass; + c.m_com = btSoftBody::clusterCom(&c); + c.m_lv = btVector3(0,0,0); + c.m_av = btVector3(0,0,0); + c.m_leaf = 0; + /* Inertia */ + btMatrix3x3& ii=c.m_locii; + ii[0]=ii[1]=ii[2]=btVector3(0,0,0); + { + int i,ni; + + for(i=0,ni=c.m_nodes.size();im_x-c.m_com; + const btVector3 q=k*k; + const btScalar m=c.m_masses[i]; + ii[0][0] += m*(q[1]+q[2]); + ii[1][1] += m*(q[0]+q[2]); + ii[2][2] += m*(q[0]+q[1]); + ii[0][1] -= m*k[0]*k[1]; + ii[0][2] -= m*k[0]*k[2]; + ii[1][2] -= m*k[1]*k[2]; + } + } + ii[1][0]=ii[0][1]; + ii[2][0]=ii[0][2]; + ii[2][1]=ii[1][2]; + + ii = ii.inverse(); + + /* Frame */ + c.m_framexform.setIdentity(); + c.m_framexform.setOrigin(c.m_com); + c.m_framerefs.resize(c.m_nodes.size()); + { + int i; + for(i=0;im_x-c.m_com; + } + } + } +} + +// +void btSoftBody::updateClusters() +{ + BT_PROFILE("UpdateClusters"); + int i; + + for(i=0;im_x-c.m_com; + const btVector3& b=c.m_framerefs[i]; + m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b; + } + PolarDecompose(m,r,s); + c.m_framexform.setOrigin(c.m_com); + c.m_framexform.setBasis(r); + /* Inertia */ +#if 1/* Constant */ + c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose(); +#else +#if 0/* Sphere */ + const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass); + const btVector3 inertia(rk,rk,rk); + const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0, + btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0, + btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0); + + c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose(); +#else/* Actual */ + c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0); + for(int i=0;im_x-c.m_com; + const btVector3 q=k*k; + const btScalar m=1/c.m_nodes[i]->m_im; + c.m_invwi[0][0] += m*(q[1]+q[2]); + c.m_invwi[1][1] += m*(q[0]+q[2]); + c.m_invwi[2][2] += m*(q[0]+q[1]); + c.m_invwi[0][1] -= m*k[0]*k[1]; + c.m_invwi[0][2] -= m*k[0]*k[2]; + c.m_invwi[1][2] -= m*k[1]*k[2]; + } + c.m_invwi[1][0]=c.m_invwi[0][1]; + c.m_invwi[2][0]=c.m_invwi[0][2]; + c.m_invwi[2][1]=c.m_invwi[1][2]; + c.m_invwi=c.m_invwi.inverse(); +#endif +#endif + /* Velocities */ + c.m_lv=btVector3(0,0,0); + c.m_av=btVector3(0,0,0); + { + int i; + + for(i=0;im_v*c.m_masses[i]; + c.m_lv += v; + c.m_av += btCross(c.m_nodes[i]->m_x-c.m_com,v); + } + } + c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping); + c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping); + c.m_vimpulses[0] = + c.m_vimpulses[1] = btVector3(0,0,0); + c.m_dimpulses[0] = + c.m_dimpulses[1] = btVector3(0,0,0); + c.m_nvimpulses = 0; + c.m_ndimpulses = 0; + /* Matching */ + if(c.m_matching>0) + { + for(int j=0;jm_x; + btVector3 mx=mi; + for(int j=1;jm_x); + mx.setMax(c.m_nodes[j]->m_x); + } + ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(mi,mx); + if(c.m_leaf) + m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg); + else + c.m_leaf=m_cdbvt.insert(bounds,&c); + } + } + } + + +} + + + + +// +void btSoftBody::cleanupClusters() +{ + for(int i=0;iTerminate(m_sst.sdt); + if(m_joints[i]->m_delete) + { + btAlignedFree(m_joints[i]); + m_joints.remove(m_joints[i--]); + } + } +} + +// +void btSoftBody::prepareClusters(int iterations) +{ + for(int i=0;iPrepare(m_sst.sdt,iterations); + } +} + + +// +void btSoftBody::solveClusters(btScalar sor) +{ + for(int i=0,ni=m_joints.size();iSolve(m_sst.sdt,sor); + } +} + +// +void btSoftBody::applyClusters(bool drift) +{ + BT_PROFILE("ApplyClusters"); +// const btScalar f0=m_sst.sdt; + //const btScalar f1=f0/2; + btAlignedObjectArray deltas; + btAlignedObjectArray weights; + deltas.resize(m_nodes.size(),btVector3(0,0,0)); + weights.resize(m_nodes.size(),0); + int i; + + if(drift) + { + for(i=0;im_x; + const btScalar q=c.m_masses[j]; + deltas[idx] += (v+btCross(w,x-c.m_com))*q; + weights[idx] += q; + } + } + } + for(i=0;i0) + { + m_nodes[i].m_x+=deltas[i]/weights[i]; + } + } +} + +// +void btSoftBody::dampClusters() +{ + int i; + + for(i=0;i0) + { + for(int j=0;j0) + { + const btVector3 vx=c.m_lv+btCross(c.m_av,c.m_nodes[j]->m_q-c.m_com); + if(vx.length2()<=n.m_v.length2()) + { + n.m_v += c.m_ndamping*(vx-n.m_v); + } + } + } + } + } +} + +// +void btSoftBody::Joint::Prepare(btScalar dt,int) +{ + m_bodies[0].activate(); + m_bodies[1].activate(); +} + +// +void btSoftBody::LJoint::Prepare(btScalar dt,int iterations) +{ + static const btScalar maxdrift=4; + Joint::Prepare(dt,iterations); + m_rpos[0] = m_bodies[0].xform()*m_refs[0]; + m_rpos[1] = m_bodies[1].xform()*m_refs[1]; + m_drift = Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt; + m_rpos[0] -= m_bodies[0].xform().getOrigin(); + m_rpos[1] -= m_bodies[1].xform().getOrigin(); + m_massmatrix = ImpulseMatrix( m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0], + m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]); + if(m_split>0) + { + m_sdrift = m_massmatrix*(m_drift*m_split); + m_drift *= 1-m_split; + } + m_drift /=(btScalar)iterations; +} + +// +void btSoftBody::LJoint::Solve(btScalar dt,btScalar sor) +{ + const btVector3 va=m_bodies[0].velocity(m_rpos[0]); + const btVector3 vb=m_bodies[1].velocity(m_rpos[1]); + const btVector3 vr=va-vb; + btSoftBody::Impulse impulse; + impulse.m_asVelocity = 1; + impulse.m_velocity = m_massmatrix*(m_drift+vr*m_cfm)*sor; + m_bodies[0].applyImpulse(-impulse,m_rpos[0]); + m_bodies[1].applyImpulse( impulse,m_rpos[1]); +} + +// +void btSoftBody::LJoint::Terminate(btScalar dt) +{ + if(m_split>0) + { + m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]); + m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]); + } +} + +// +void btSoftBody::AJoint::Prepare(btScalar dt,int iterations) +{ + static const btScalar maxdrift=SIMD_PI/16; + m_icontrol->Prepare(this); + Joint::Prepare(dt,iterations); + m_axis[0] = m_bodies[0].xform().getBasis()*m_refs[0]; + m_axis[1] = m_bodies[1].xform().getBasis()*m_refs[1]; + m_drift = NormalizeAny(btCross(m_axis[1],m_axis[0])); + m_drift *= btMin(maxdrift,btAcos(Clamp(btDot(m_axis[0],m_axis[1]),-1,+1))); + m_drift *= m_erp/dt; + m_massmatrix= AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia()); + if(m_split>0) + { + m_sdrift = m_massmatrix*(m_drift*m_split); + m_drift *= 1-m_split; + } + m_drift /=(btScalar)iterations; +} + +// +void btSoftBody::AJoint::Solve(btScalar dt,btScalar sor) +{ + const btVector3 va=m_bodies[0].angularVelocity(); + const btVector3 vb=m_bodies[1].angularVelocity(); + const btVector3 vr=va-vb; + const btScalar sp=btDot(vr,m_axis[0]); + const btVector3 vc=vr-m_axis[0]*m_icontrol->Speed(this,sp); + btSoftBody::Impulse impulse; + impulse.m_asVelocity = 1; + impulse.m_velocity = m_massmatrix*(m_drift+vc*m_cfm)*sor; + m_bodies[0].applyAImpulse(-impulse); + m_bodies[1].applyAImpulse( impulse); +} + +// +void btSoftBody::AJoint::Terminate(btScalar dt) +{ + if(m_split>0) + { + m_bodies[0].applyDAImpulse(-m_sdrift); + m_bodies[1].applyDAImpulse( m_sdrift); + } +} + +// +void btSoftBody::CJoint::Prepare(btScalar dt,int iterations) +{ + Joint::Prepare(dt,iterations); + const bool dodrift=(m_life==0); + m_delete=(++m_life)>m_maxlife; + if(dodrift) + { + m_drift=m_drift*m_erp/dt; + if(m_split>0) + { + m_sdrift = m_massmatrix*(m_drift*m_split); + m_drift *= 1-m_split; + } + m_drift/=(btScalar)iterations; + } + else + { + m_drift=m_sdrift=btVector3(0,0,0); + } +} + +// +void btSoftBody::CJoint::Solve(btScalar dt,btScalar sor) +{ + const btVector3 va=m_bodies[0].velocity(m_rpos[0]); + const btVector3 vb=m_bodies[1].velocity(m_rpos[1]); + const btVector3 vrel=va-vb; + const btScalar rvac=btDot(vrel,m_normal); + btSoftBody::Impulse impulse; + impulse.m_asVelocity = 1; + impulse.m_velocity = m_drift; + if(rvac<0) + { + const btVector3 iv=m_normal*rvac; + const btVector3 fv=vrel-iv; + impulse.m_velocity += iv+fv*m_friction; + } + impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor; + + if (m_bodies[0].m_soft==m_bodies[1].m_soft) + { + if ((impulse.m_velocity.getX() ==impulse.m_velocity.getX())&&(impulse.m_velocity.getY() ==impulse.m_velocity.getY())&& + (impulse.m_velocity.getZ() ==impulse.m_velocity.getZ())) + { + if (impulse.m_asVelocity) + { + if (impulse.m_velocity.length() m_maxSelfCollisionImpulse) + { + + } else + { + m_bodies[0].applyImpulse(-impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[0]); + m_bodies[1].applyImpulse( impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[1]); + } + } + } + } else + { + m_bodies[0].applyImpulse(-impulse,m_rpos[0]); + m_bodies[1].applyImpulse( impulse,m_rpos[1]); + } +} + +// +void btSoftBody::CJoint::Terminate(btScalar dt) +{ + if(m_split>0) + { + m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]); + m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]); + } +} + +// +void btSoftBody::applyForces() +{ + + BT_PROFILE("SoftBody applyForces"); + const btScalar dt = m_sst.sdt; + const btScalar kLF = m_cfg.kLF; + const btScalar kDG = m_cfg.kDG; + const btScalar kPR = m_cfg.kPR; + const btScalar kVC = m_cfg.kVC; + const bool as_lift = kLF>0; + const bool as_drag = kDG>0; + const bool as_pressure = kPR!=0; + const bool as_volume = kVC>0; + const bool as_aero = as_lift || + as_drag ; + const bool as_vaero = as_aero && + (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided); + const bool as_faero = as_aero && + (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided); + const bool use_medium = as_aero; + const bool use_volume = as_pressure || + as_volume ; + btScalar volume = 0; + btScalar ivolumetp = 0; + btScalar dvolumetv = 0; + btSoftBody::sMedium medium; + if(use_volume) + { + volume = getVolume(); + ivolumetp = 1/btFabs(volume)*kPR; + dvolumetv = (m_pose.m_volume-volume)*kVC; + } + /* Per vertex forces */ + int i,ni; + + for(i=0,ni=m_nodes.size();i0) + { + if(use_medium) + { + /* Aerodynamics */ + addAeroForceToNode(m_windVelocity, i); + } + /* Pressure */ + if(as_pressure) + { + n.m_f += n.m_n*(n.m_area*ivolumetp); + } + /* Volume */ + if(as_volume) + { + n.m_f += n.m_n*(n.m_area*dvolumetv); + } + } + } + + /* Per face forces */ + for(i=0,ni=m_faces.size();im_cfg.kAHR*kst; + const btScalar dt=psb->m_sst.sdt; + for(int i=0,ni=psb->m_anchors.size();im_anchors[i]; + const btTransform& t=a.m_body->getWorldTransform(); + Node& n=*a.m_node; + const btVector3 wa=t*a.m_local; + const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt; + const btVector3 vb=n.m_x-n.m_q; + const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR; + const btVector3 impulse=a.m_c0*vr*a.m_influence; + n.m_x+=impulse*a.m_c2; + a.m_body->applyImpulse(-impulse,a.m_c1); + } +} + +// +void btSoftBody::PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti) +{ + const btScalar dt = psb->m_sst.sdt; + const btScalar mrg = psb->getCollisionShape()->getMargin(); + for(int i=0,ni=psb->m_rcontacts.size();im_rcontacts[i]; + const sCti& cti = c.m_cti; + btRigidBody* tmpRigid = btRigidBody::upcast(cti.m_colObj); + + const btVector3 va = tmpRigid ? tmpRigid->getVelocityInLocalPoint(c.m_c1)*dt : btVector3(0,0,0); + const btVector3 vb = c.m_node->m_x-c.m_node->m_q; + const btVector3 vr = vb-va; + const btScalar dn = btDot(vr, cti.m_normal); + if(dn<=SIMD_EPSILON) + { + const btScalar dp = btMin( (btDot(c.m_node->m_x, cti.m_normal) + cti.m_offset), mrg ); + const btVector3 fv = vr - (cti.m_normal * dn); + // c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient + const btVector3 impulse = c.m_c0 * ( (vr - (fv * c.m_c3) + (cti.m_normal * (dp * c.m_c4))) * kst ); + c.m_node->m_x -= impulse * c.m_c2; + if (tmpRigid) + tmpRigid->applyImpulse(impulse,c.m_c1); + } + } +} + +// +void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti) +{ + for(int i=0,ni=psb->m_scontacts.size();im_scontacts[i]; + const btVector3& nr=c.m_normal; + Node& n=*c.m_node; + Face& f=*c.m_face; + const btVector3 p=BaryEval( f.m_n[0]->m_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x, + c.m_weights); + const btVector3 q=BaryEval( f.m_n[0]->m_q, + f.m_n[1]->m_q, + f.m_n[2]->m_q, + c.m_weights); + const btVector3 vr=(n.m_x-n.m_q)-(p-q); + btVector3 corr(0,0,0); + btScalar dot = btDot(vr,nr); + if(dot<0) + { + const btScalar j=c.m_margin-(btDot(nr,n.m_x)-btDot(nr,p)); + corr+=c.m_normal*j; + } + corr -= ProjectOnPlane(vr,nr)*c.m_friction; + n.m_x += corr*c.m_cfm[0]; + f.m_n[0]->m_x -= corr*(c.m_cfm[1]*c.m_weights.x()); + f.m_n[1]->m_x -= corr*(c.m_cfm[1]*c.m_weights.y()); + f.m_n[2]->m_x -= corr*(c.m_cfm[1]*c.m_weights.z()); + } +} + +// +void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti) +{ + for(int i=0,ni=psb->m_links.size();im_links[i]; + if(l.m_c0>0) + { + Node& a=*l.m_n[0]; + Node& b=*l.m_n[1]; + const btVector3 del=b.m_x-a.m_x; + const btScalar len=del.length2(); + if (l.m_c1+len > SIMD_EPSILON) + { + const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst; + a.m_x-=del*(k*a.m_im); + b.m_x+=del*(k*b.m_im); + } + } + } +} + +// +void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst) +{ + for(int i=0,ni=psb->m_links.size();im_links[i]; + Node** n=l.m_n; + const btScalar j=-btDot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst; + n[0]->m_v+= l.m_c3*(j*n[0]->m_im); + n[1]->m_v-= l.m_c3*(j*n[1]->m_im); + } +} + +// +btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver) +{ + switch(solver) + { + case ePSolver::Anchors: + return(&btSoftBody::PSolve_Anchors); + case ePSolver::Linear: + return(&btSoftBody::PSolve_Links); + case ePSolver::RContacts: + return(&btSoftBody::PSolve_RContacts); + case ePSolver::SContacts: + return(&btSoftBody::PSolve_SContacts); + default: + { + } + } + return(0); +} + +// +btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver) +{ + switch(solver) + { + case eVSolver::Linear: return(&btSoftBody::VSolve_Links); + default: + { + } + } + return(0); +} + +// +void btSoftBody::defaultCollisionHandler(btCollisionObject* pco) +{ + + switch(m_cfg.collisions&fCollision::RVSmask) + { + case fCollision::SDF_RS: + { + btSoftColliders::CollideSDF_RS docollide; + btRigidBody* prb1=btRigidBody::upcast(pco); + btTransform wtr=pco->getWorldTransform(); + + const btTransform ctr=pco->getWorldTransform(); + const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length(); + const btScalar basemargin=getCollisionShape()->getMargin(); + btVector3 mins; + btVector3 maxs; + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume; + pco->getCollisionShape()->getAabb( pco->getWorldTransform(), + mins, + maxs); + volume=btDbvtVolume::FromMM(mins,maxs); + volume.Expand(btVector3(basemargin,basemargin,basemargin)); + docollide.psb = this; + docollide.m_colObj1 = pco; + docollide.m_rigidBody = prb1; + + docollide.dynmargin = basemargin+timemargin; + docollide.stamargin = basemargin; + m_ndbvt.collideTV(m_ndbvt.m_root,volume,docollide); + } + break; + case fCollision::CL_RS: + { + btSoftColliders::CollideCL_RS collider; + collider.Process(this,pco); + } + break; + } +} + +// +void btSoftBody::defaultCollisionHandler(btSoftBody* psb) +{ + const int cf=m_cfg.collisions&psb->m_cfg.collisions; + switch(cf&fCollision::SVSmask) + { + case fCollision::CL_SS: + { + + //support self-collision if CL_SELF flag set + if (this!=psb || psb->m_cfg.collisions&fCollision::CL_SELF) + { + btSoftColliders::CollideCL_SS docollide; + docollide.Process(this,psb); + } + + } + break; + case fCollision::VF_SS: + { + //only self-collision for Cluster, not Vertex-Face yet + if (this!=psb) + { + btSoftColliders::CollideVF_SS docollide; + /* common */ + docollide.mrg= getCollisionShape()->getMargin()+ + psb->getCollisionShape()->getMargin(); + /* psb0 nodes vs psb1 faces */ + docollide.psb[0]=this; + docollide.psb[1]=psb; + docollide.psb[0]->m_ndbvt.collideTT( docollide.psb[0]->m_ndbvt.m_root, + docollide.psb[1]->m_fdbvt.m_root, + docollide); + /* psb1 nodes vs psb0 faces */ + docollide.psb[0]=psb; + docollide.psb[1]=this; + docollide.psb[0]->m_ndbvt.collideTT( docollide.psb[0]->m_ndbvt.m_root, + docollide.psb[1]->m_fdbvt.m_root, + docollide); + } + } + break; + default: + { + + } + } +} + + + +void btSoftBody::setWindVelocity( const btVector3 &velocity ) +{ + m_windVelocity = velocity; +} + + +const btVector3& btSoftBody::getWindVelocity() +{ + return m_windVelocity; +} + + + +int btSoftBody::calculateSerializeBufferSize() const +{ + int sz = sizeof(btSoftBodyData); + return sz; +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializer) const +{ + btSoftBodyData* sbd = (btSoftBodyData*) dataBuffer; + + btCollisionObject::serialize(&sbd->m_collisionObjectData, serializer); + + btHashMap m_nodeIndexMap; + + sbd->m_numMaterials = m_materials.size(); + sbd->m_materials = sbd->m_numMaterials? (SoftBodyMaterialData**) serializer->getUniquePointer((void*)&m_materials): 0; + + if (sbd->m_materials) + { + int sz = sizeof(SoftBodyMaterialData*); + int numElem = sbd->m_numMaterials; + btChunk* chunk = serializer->allocate(sz,numElem); + //SoftBodyMaterialData** memPtr = chunk->m_oldPtr; + SoftBodyMaterialData** memPtr = (SoftBodyMaterialData**)chunk->m_oldPtr; + for (int i=0;igetUniquePointer((void*)mat) : 0; + if (!serializer->findPointer(mat)) + { + //serialize it here + btChunk* chunk = serializer->allocate(sizeof(SoftBodyMaterialData),1); + SoftBodyMaterialData* memPtr = (SoftBodyMaterialData*)chunk->m_oldPtr; + memPtr->m_flags = mat->m_flags; + memPtr->m_angularStiffness = mat->m_kAST; + memPtr->m_linearStiffness = mat->m_kLST; + memPtr->m_volumeStiffness = mat->m_kVST; + serializer->finalizeChunk(chunk,"SoftBodyMaterialData",BT_SBMATERIAL_CODE,mat); + } + } + serializer->finalizeChunk(chunk,"SoftBodyMaterialData",BT_ARRAY_CODE,(void*) &m_materials); + } + + + + + sbd->m_numNodes = m_nodes.size(); + sbd->m_nodes = sbd->m_numNodes ? (SoftBodyNodeData*)serializer->getUniquePointer((void*)&m_nodes): 0; + if (sbd->m_nodes) + { + int sz = sizeof(SoftBodyNodeData); + int numElem = sbd->m_numNodes; + btChunk* chunk = serializer->allocate(sz,numElem); + SoftBodyNodeData* memPtr = (SoftBodyNodeData*)chunk->m_oldPtr; + for (int i=0;im_accumulatedForce); + memPtr->m_area = m_nodes[i].m_area; + memPtr->m_attach = m_nodes[i].m_battach; + memPtr->m_inverseMass = m_nodes[i].m_im; + memPtr->m_material = m_nodes[i].m_material? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_nodes[i].m_material):0; + m_nodes[i].m_n.serializeFloat(memPtr->m_normal); + m_nodes[i].m_x.serializeFloat(memPtr->m_position); + m_nodes[i].m_q.serializeFloat(memPtr->m_previousPosition); + m_nodes[i].m_v.serializeFloat(memPtr->m_velocity); + m_nodeIndexMap.insert(&m_nodes[i],i); + } + serializer->finalizeChunk(chunk,"SoftBodyNodeData",BT_SBNODE_CODE,(void*) &m_nodes); + } + + sbd->m_numLinks = m_links.size(); + sbd->m_links = sbd->m_numLinks? (SoftBodyLinkData*) serializer->getUniquePointer((void*)&m_links[0]):0; + if (sbd->m_links) + { + int sz = sizeof(SoftBodyLinkData); + int numElem = sbd->m_numLinks; + btChunk* chunk = serializer->allocate(sz,numElem); + SoftBodyLinkData* memPtr = (SoftBodyLinkData*)chunk->m_oldPtr; + for (int i=0;im_bbending = m_links[i].m_bbending; + memPtr->m_material = m_links[i].m_material? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_links[i].m_material):0; + memPtr->m_nodeIndices[0] = m_links[i].m_n[0] ? m_links[i].m_n[0] - &m_nodes[0]: -1; + memPtr->m_nodeIndices[1] = m_links[i].m_n[1] ? m_links[i].m_n[1] - &m_nodes[0]: -1; + btAssert(memPtr->m_nodeIndices[0]m_nodeIndices[1]m_restLength = m_links[i].m_rl; + } + serializer->finalizeChunk(chunk,"SoftBodyLinkData",BT_ARRAY_CODE,(void*) &m_links[0]); + + } + + + sbd->m_numFaces = m_faces.size(); + sbd->m_faces = sbd->m_numFaces? (SoftBodyFaceData*) serializer->getUniquePointer((void*)&m_faces[0]):0; + if (sbd->m_faces) + { + int sz = sizeof(SoftBodyFaceData); + int numElem = sbd->m_numFaces; + btChunk* chunk = serializer->allocate(sz,numElem); + SoftBodyFaceData* memPtr = (SoftBodyFaceData*)chunk->m_oldPtr; + for (int i=0;im_material = m_faces[i].m_material ? (SoftBodyMaterialData*) serializer->getUniquePointer((void*)m_faces[i].m_material): 0; + m_faces[i].m_normal.serializeFloat( memPtr->m_normal); + for (int j=0;j<3;j++) + { + memPtr->m_nodeIndices[j] = m_faces[i].m_n[j]? m_faces[i].m_n[j] - &m_nodes[0]: -1; + } + memPtr->m_restArea = m_faces[i].m_ra; + } + serializer->finalizeChunk(chunk,"SoftBodyFaceData",BT_ARRAY_CODE,(void*) &m_faces[0]); + } + + + sbd->m_numTetrahedra = m_tetras.size(); + sbd->m_tetrahedra = sbd->m_numTetrahedra ? (SoftBodyTetraData*) serializer->getUniquePointer((void*)&m_tetras[0]):0; + if (sbd->m_tetrahedra) + { + int sz = sizeof(SoftBodyTetraData); + int numElem = sbd->m_numTetrahedra; + btChunk* chunk = serializer->allocate(sz,numElem); + SoftBodyTetraData* memPtr = (SoftBodyTetraData*)chunk->m_oldPtr; + for (int i=0;im_c0[j] ); + memPtr->m_nodeIndices[j] = m_tetras[j].m_n[j]? m_tetras[j].m_n[j]-&m_nodes[0] : -1; + } + memPtr->m_c1 = m_tetras[i].m_c1; + memPtr->m_c2 = m_tetras[i].m_c2; + memPtr->m_material = m_tetras[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_tetras[i].m_material): 0; + memPtr->m_restVolume = m_tetras[i].m_rv; + } + serializer->finalizeChunk(chunk,"SoftBodyTetraData",BT_ARRAY_CODE,(void*) &m_tetras[0]); + } + + sbd->m_numAnchors = m_anchors.size(); + sbd->m_anchors = sbd->m_numAnchors ? (SoftRigidAnchorData*) serializer->getUniquePointer((void*)&m_anchors[0]):0; + if (sbd->m_anchors) + { + int sz = sizeof(SoftRigidAnchorData); + int numElem = sbd->m_numAnchors; + btChunk* chunk = serializer->allocate(sz,numElem); + SoftRigidAnchorData* memPtr = (SoftRigidAnchorData*)chunk->m_oldPtr; + for (int i=0;im_c0); + m_anchors[i].m_c1.serializeFloat(memPtr->m_c1); + memPtr->m_c2 = m_anchors[i].m_c2; + m_anchors[i].m_local.serializeFloat(memPtr->m_localFrame); + memPtr->m_nodeIndex = m_anchors[i].m_node? m_anchors[i].m_node-&m_nodes[0]: -1; + + memPtr->m_rigidBody = m_anchors[i].m_body? (btRigidBodyData*) serializer->getUniquePointer((void*)m_anchors[i].m_body): 0; + btAssert(memPtr->m_nodeIndex < m_nodes.size()); + } + serializer->finalizeChunk(chunk,"SoftRigidAnchorData",BT_ARRAY_CODE,(void*) &m_anchors[0]); + } + + + sbd->m_config.m_dynamicFriction = m_cfg.kDF; + sbd->m_config.m_baumgarte = m_cfg.kVCF; + sbd->m_config.m_pressure = m_cfg.kPR; + sbd->m_config.m_aeroModel = this->m_cfg.aeromodel; + sbd->m_config.m_lift = m_cfg.kLF; + sbd->m_config.m_drag = m_cfg.kDG; + sbd->m_config.m_positionIterations = m_cfg.piterations; + sbd->m_config.m_driftIterations = m_cfg.diterations; + sbd->m_config.m_clusterIterations = m_cfg.citerations; + sbd->m_config.m_velocityIterations = m_cfg.viterations; + sbd->m_config.m_maxVolume = m_cfg.maxvolume; + sbd->m_config.m_damping = m_cfg.kDP; + sbd->m_config.m_poseMatch = m_cfg.kMT; + sbd->m_config.m_collisionFlags = m_cfg.collisions; + sbd->m_config.m_volume = m_cfg.kVC; + sbd->m_config.m_rigidContactHardness = m_cfg.kCHR; + sbd->m_config.m_kineticContactHardness = m_cfg.kKHR; + sbd->m_config.m_softContactHardness = m_cfg.kSHR; + sbd->m_config.m_anchorHardness = m_cfg.kAHR; + sbd->m_config.m_timeScale = m_cfg.timescale; + sbd->m_config.m_maxVolume = m_cfg.maxvolume; + sbd->m_config.m_softRigidClusterHardness = m_cfg.kSRHR_CL; + sbd->m_config.m_softKineticClusterHardness = m_cfg.kSKHR_CL; + sbd->m_config.m_softSoftClusterHardness = m_cfg.kSSHR_CL; + sbd->m_config.m_softRigidClusterImpulseSplit = m_cfg.kSR_SPLT_CL; + sbd->m_config.m_softKineticClusterImpulseSplit = m_cfg.kSK_SPLT_CL; + sbd->m_config.m_softSoftClusterImpulseSplit = m_cfg.kSS_SPLT_CL; + + //pose for shape matching + { + sbd->m_pose = (SoftBodyPoseData*)serializer->getUniquePointer((void*)&m_pose); + + int sz = sizeof(SoftBodyPoseData); + btChunk* chunk = serializer->allocate(sz,1); + SoftBodyPoseData* memPtr = (SoftBodyPoseData*)chunk->m_oldPtr; + + m_pose.m_aqq.serializeFloat(memPtr->m_aqq); + memPtr->m_bframe = m_pose.m_bframe; + memPtr->m_bvolume = m_pose.m_bvolume; + m_pose.m_com.serializeFloat(memPtr->m_com); + + memPtr->m_numPositions = m_pose.m_pos.size(); + memPtr->m_positions = memPtr->m_numPositions ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_pose.m_pos[0]): 0; + if (memPtr->m_numPositions) + { + int numElem = memPtr->m_numPositions; + int sz = sizeof(btVector3Data); + btChunk* chunk = serializer->allocate(sz,numElem); + btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr; + for (int i=0;ifinalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)&m_pose.m_pos[0]); + } + memPtr->m_restVolume = m_pose.m_volume; + m_pose.m_rot.serializeFloat(memPtr->m_rot); + m_pose.m_scl.serializeFloat(memPtr->m_scale); + + memPtr->m_numWeigts = m_pose.m_wgh.size(); + memPtr->m_weights = memPtr->m_numWeigts? (float*) serializer->getUniquePointer((void*) &m_pose.m_wgh[0]) : 0; + if (memPtr->m_numWeigts) + { + + int numElem = memPtr->m_numWeigts; + int sz = sizeof(float); + btChunk* chunk = serializer->allocate(sz,numElem); + float* memPtr = (float*) chunk->m_oldPtr; + for (int i=0;ifinalizeChunk(chunk,"float",BT_ARRAY_CODE,(void*)&m_pose.m_wgh[0]); + } + + serializer->finalizeChunk(chunk,"SoftBodyPoseData",BT_ARRAY_CODE,(void*)&m_pose); + } + + //clusters for convex-cluster collision detection + + sbd->m_numClusters = m_clusters.size(); + sbd->m_clusters = sbd->m_numClusters? (SoftBodyClusterData*) serializer->getUniquePointer((void*)m_clusters[0]) : 0; + if (sbd->m_numClusters) + { + int numElem = sbd->m_numClusters; + int sz = sizeof(SoftBodyClusterData); + btChunk* chunk = serializer->allocate(sz,numElem); + SoftBodyClusterData* memPtr = (SoftBodyClusterData*) chunk->m_oldPtr; + for (int i=0;im_adamping= m_clusters[i]->m_adamping; + m_clusters[i]->m_av.serializeFloat(memPtr->m_av); + memPtr->m_clusterIndex = m_clusters[i]->m_clusterIndex; + memPtr->m_collide = m_clusters[i]->m_collide; + m_clusters[i]->m_com.serializeFloat(memPtr->m_com); + memPtr->m_containsAnchor = m_clusters[i]->m_containsAnchor; + m_clusters[i]->m_dimpulses[0].serializeFloat(memPtr->m_dimpulses[0]); + m_clusters[i]->m_dimpulses[1].serializeFloat(memPtr->m_dimpulses[1]); + m_clusters[i]->m_framexform.serializeFloat(memPtr->m_framexform); + memPtr->m_idmass = m_clusters[i]->m_idmass; + memPtr->m_imass = m_clusters[i]->m_imass; + m_clusters[i]->m_invwi.serializeFloat(memPtr->m_invwi); + memPtr->m_ldamping = m_clusters[i]->m_ldamping; + m_clusters[i]->m_locii.serializeFloat(memPtr->m_locii); + m_clusters[i]->m_lv.serializeFloat(memPtr->m_lv); + memPtr->m_matching = m_clusters[i]->m_matching; + memPtr->m_maxSelfCollisionImpulse = m_clusters[i]->m_maxSelfCollisionImpulse; + memPtr->m_ndamping = m_clusters[i]->m_ndamping; + memPtr->m_ldamping = m_clusters[i]->m_ldamping; + memPtr->m_adamping = m_clusters[i]->m_adamping; + memPtr->m_selfCollisionImpulseFactor = m_clusters[i]->m_selfCollisionImpulseFactor; + + memPtr->m_numFrameRefs = m_clusters[i]->m_framerefs.size(); + memPtr->m_numMasses = m_clusters[i]->m_masses.size(); + memPtr->m_numNodes = m_clusters[i]->m_nodes.size(); + + memPtr->m_nvimpulses = m_clusters[i]->m_nvimpulses; + m_clusters[i]->m_vimpulses[0].serializeFloat(memPtr->m_vimpulses[0]); + m_clusters[i]->m_vimpulses[1].serializeFloat(memPtr->m_vimpulses[1]); + memPtr->m_ndimpulses = m_clusters[i]->m_ndimpulses; + + + + memPtr->m_framerefs = memPtr->m_numFrameRefs? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_clusters[i]->m_framerefs[0]) : 0; + if (memPtr->m_framerefs) + { + int numElem = memPtr->m_numFrameRefs; + int sz = sizeof(btVector3FloatData); + btChunk* chunk = serializer->allocate(sz,numElem); + btVector3FloatData* memPtr = (btVector3FloatData*) chunk->m_oldPtr; + for (int j=0;jm_framerefs[j].serializeFloat(*memPtr); + } + serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_framerefs[0]); + } + + memPtr->m_masses = memPtr->m_numMasses ? (float*) serializer->getUniquePointer((void*)&m_clusters[i]->m_masses[0]): 0; + if (memPtr->m_masses) + { + int numElem = memPtr->m_numMasses; + int sz = sizeof(float); + btChunk* chunk = serializer->allocate(sz,numElem); + float* memPtr = (float*) chunk->m_oldPtr; + for (int j=0;jm_masses[j]; + } + serializer->finalizeChunk(chunk,"float",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_masses[0]); + } + + memPtr->m_nodeIndices = memPtr->m_numNodes ? (int*) serializer->getUniquePointer((void*) &m_clusters[i]->m_nodes) : 0; + if (memPtr->m_nodeIndices ) + { + int numElem = memPtr->m_numMasses; + int sz = sizeof(int); + btChunk* chunk = serializer->allocate(sz,numElem); + int* memPtr = (int*) chunk->m_oldPtr; + for (int j=0;jm_nodes[j]); + btAssert(indexPtr); + *memPtr = *indexPtr; + } + serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_nodes); + } + } + serializer->finalizeChunk(chunk,"SoftBodyClusterData",BT_ARRAY_CODE,(void*)m_clusters[0]); + + } + + + + sbd->m_numJoints = m_joints.size(); + sbd->m_joints = m_joints.size()? (btSoftBodyJointData*) serializer->getUniquePointer((void*)&m_joints[0]) : 0; + + if (sbd->m_joints) + { + int sz = sizeof(btSoftBodyJointData); + int numElem = m_joints.size(); + btChunk* chunk = serializer->allocate(sz,numElem); + btSoftBodyJointData* memPtr = (btSoftBodyJointData*)chunk->m_oldPtr; + + for (int i=0;im_jointType = (int)m_joints[i]->Type(); + m_joints[i]->m_refs[0].serializeFloat(memPtr->m_refs[0]); + m_joints[i]->m_refs[1].serializeFloat(memPtr->m_refs[1]); + memPtr->m_cfm = m_joints[i]->m_cfm; + memPtr->m_erp = m_joints[i]->m_erp; + memPtr->m_split = m_joints[i]->m_split; + memPtr->m_delete = m_joints[i]->m_delete; + + for (int j=0;j<4;j++) + { + memPtr->m_relPosition[0].m_floats[j] = 0.f; + memPtr->m_relPosition[1].m_floats[j] = 0.f; + } + memPtr->m_bodyA = 0; + memPtr->m_bodyB = 0; + if (m_joints[i]->m_bodies[0].m_soft) + { + memPtr->m_bodyAtype = BT_JOINT_SOFT_BODY_CLUSTER; + memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_soft); + } + if (m_joints[i]->m_bodies[0].m_collisionObject) + { + memPtr->m_bodyAtype = BT_JOINT_COLLISION_OBJECT; + memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_collisionObject); + } + if (m_joints[i]->m_bodies[0].m_rigid) + { + memPtr->m_bodyAtype = BT_JOINT_RIGID_BODY; + memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_rigid); + } + + if (m_joints[i]->m_bodies[1].m_soft) + { + memPtr->m_bodyBtype = BT_JOINT_SOFT_BODY_CLUSTER; + memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_soft); + } + if (m_joints[i]->m_bodies[1].m_collisionObject) + { + memPtr->m_bodyBtype = BT_JOINT_COLLISION_OBJECT; + memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_collisionObject); + } + if (m_joints[i]->m_bodies[1].m_rigid) + { + memPtr->m_bodyBtype = BT_JOINT_RIGID_BODY; + memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_rigid); + } + } + serializer->finalizeChunk(chunk,"btSoftBodyJointData",BT_ARRAY_CODE,(void*) &m_joints[0]); + } + + + return btSoftBodyDataName; +} + diff --git a/src/BulletSoftBody/btSoftBody.h b/src/BulletSoftBody/btSoftBody.h new file mode 100644 index 0000000..ba58948 --- /dev/null +++ b/src/BulletSoftBody/btSoftBody.h @@ -0,0 +1,987 @@ +/* +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. +*/ +///btSoftBody implementation by Nathanael Presson + +#ifndef _BT_SOFT_BODY_H +#define _BT_SOFT_BODY_H + +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" + +#include "BulletCollision/CollisionShapes/btConcaveShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "btSparseSDF.h" +#include "BulletCollision/BroadphaseCollision/btDbvt.h" + +//#ifdef BT_USE_DOUBLE_PRECISION +//#define btRigidBodyData btRigidBodyDoubleData +//#define btRigidBodyDataName "btRigidBodyDoubleData" +//#else +#define btSoftBodyData btSoftBodyFloatData +#define btSoftBodyDataName "btSoftBodyFloatData" +//#endif //BT_USE_DOUBLE_PRECISION + +class btBroadphaseInterface; +class btDispatcher; +class btSoftBodySolver; + +/* btSoftBodyWorldInfo */ +struct btSoftBodyWorldInfo +{ + btScalar air_density; + btScalar water_density; + btScalar water_offset; + btVector3 water_normal; + btBroadphaseInterface* m_broadphase; + btDispatcher* m_dispatcher; + btVector3 m_gravity; + btSparseSdf<3> m_sparsesdf; + + btSoftBodyWorldInfo() + :air_density((btScalar)1.2), + water_density(0), + water_offset(0), + water_normal(0,0,0), + m_broadphase(0), + m_dispatcher(0), + m_gravity(0,-10,0) + { + } +}; + + +///The btSoftBody is an class to simulate cloth and volumetric soft bodies. +///There is two-way interaction between btSoftBody and btRigidBody/btCollisionObject. +class btSoftBody : public btCollisionObject +{ +public: + btAlignedObjectArray m_collisionDisabledObjects; + + // The solver object that handles this soft body + btSoftBodySolver *m_softBodySolver; + + // + // Enumerations + // + + ///eAeroModel + struct eAeroModel { enum _ { + V_Point, ///Vertex normals are oriented toward velocity + V_TwoSided, ///Vertex normals are flipped to match velocity + V_TwoSidedLiftDrag, ///Vertex normals are flipped to match velocity and lift and drag forces are applied + V_OneSided, ///Vertex normals are taken as it is + F_TwoSided, ///Face normals are flipped to match velocity + F_TwoSidedLiftDrag, ///Face normals are flipped to match velocity and lift and drag forces are applied + F_OneSided, ///Face normals are taken as it is + END + };}; + + ///eVSolver : velocities solvers + struct eVSolver { enum _ { + Linear, ///Linear solver + END + };}; + + ///ePSolver : positions solvers + struct ePSolver { enum _ { + Linear, ///Linear solver + Anchors, ///Anchor solver + RContacts, ///Rigid contacts solver + SContacts, ///Soft contacts solver + END + };}; + + ///eSolverPresets + struct eSolverPresets { enum _ { + Positions, + Velocities, + Default = Positions, + END + };}; + + ///eFeature + struct eFeature { enum _ { + None, + Node, + Link, + Face, + Tetra, + END + };}; + + typedef btAlignedObjectArray tVSolverArray; + typedef btAlignedObjectArray tPSolverArray; + + // + // Flags + // + + ///fCollision + struct fCollision { enum _ { + RVSmask = 0x000f, ///Rigid versus soft mask + SDF_RS = 0x0001, ///SDF based rigid vs soft + CL_RS = 0x0002, ///Cluster vs convex rigid vs soft + + SVSmask = 0x0030, ///Rigid versus soft mask + VF_SS = 0x0010, ///Vertex vs face soft vs soft handling + CL_SS = 0x0020, ///Cluster vs cluster soft vs soft handling + CL_SELF = 0x0040, ///Cluster soft body self collision + /* presets */ + Default = SDF_RS, + END + };}; + + ///fMaterial + struct fMaterial { enum _ { + DebugDraw = 0x0001, /// Enable debug draw + /* presets */ + Default = DebugDraw, + END + };}; + + // + // API Types + // + + /* sRayCast */ + struct sRayCast + { + btSoftBody* body; /// soft body + eFeature::_ feature; /// feature type + int index; /// feature index + btScalar fraction; /// time of impact fraction (rayorg+(rayto-rayfrom)*fraction) + }; + + /* ImplicitFn */ + struct ImplicitFn + { + virtual btScalar Eval(const btVector3& x)=0; + }; + + // + // Internal types + // + + typedef btAlignedObjectArray tScalarArray; + typedef btAlignedObjectArray tVector3Array; + + /* sCti is Softbody contact info */ + struct sCti + { + btCollisionObject* m_colObj; /* Rigid body */ + btVector3 m_normal; /* Outward normal */ + btScalar m_offset; /* Offset from origin */ + }; + + /* sMedium */ + struct sMedium + { + btVector3 m_velocity; /* Velocity */ + btScalar m_pressure; /* Pressure */ + btScalar m_density; /* Density */ + }; + + /* Base type */ + struct Element + { + void* m_tag; // User data + Element() : m_tag(0) {} + }; + /* Material */ + struct Material : Element + { + btScalar m_kLST; // Linear stiffness coefficient [0,1] + btScalar m_kAST; // Area/Angular stiffness coefficient [0,1] + btScalar m_kVST; // Volume stiffness coefficient [0,1] + int m_flags; // Flags + }; + + /* Feature */ + struct Feature : Element + { + Material* m_material; // Material + }; + /* Node */ + struct Node : Feature + { + btVector3 m_x; // Position + btVector3 m_q; // Previous step position + btVector3 m_v; // Velocity + btVector3 m_f; // Force accumulator + btVector3 m_n; // Normal + btScalar m_im; // 1/mass + btScalar m_area; // Area + btDbvtNode* m_leaf; // Leaf data + int m_battach:1; // Attached + }; + /* Link */ + struct Link : Feature + { + Node* m_n[2]; // Node pointers + btScalar m_rl; // Rest length + int m_bbending:1; // Bending link + btScalar m_c0; // (ima+imb)*kLST + btScalar m_c1; // rl^2 + btScalar m_c2; // |gradient|^2/c0 + btVector3 m_c3; // gradient + }; + /* Face */ + struct Face : Feature + { + Node* m_n[3]; // Node pointers + btVector3 m_normal; // Normal + btScalar m_ra; // Rest area + btDbvtNode* m_leaf; // Leaf data + }; + /* Tetra */ + struct Tetra : Feature + { + Node* m_n[4]; // Node pointers + btScalar m_rv; // Rest volume + btDbvtNode* m_leaf; // Leaf data + btVector3 m_c0[4]; // gradients + btScalar m_c1; // (4*kVST)/(im0+im1+im2+im3) + btScalar m_c2; // m_c1/sum(|g0..3|^2) + }; + /* RContact */ + struct RContact + { + sCti m_cti; // Contact infos + Node* m_node; // Owner node + btMatrix3x3 m_c0; // Impulse matrix + btVector3 m_c1; // Relative anchor + btScalar m_c2; // ima*dt + btScalar m_c3; // Friction + btScalar m_c4; // Hardness + }; + /* SContact */ + struct SContact + { + Node* m_node; // Node + Face* m_face; // Face + btVector3 m_weights; // Weigths + btVector3 m_normal; // Normal + btScalar m_margin; // Margin + btScalar m_friction; // Friction + btScalar m_cfm[2]; // Constraint force mixing + }; + /* Anchor */ + struct Anchor + { + Node* m_node; // Node pointer + btVector3 m_local; // Anchor position in body space + btRigidBody* m_body; // Body + btScalar m_influence; + btMatrix3x3 m_c0; // Impulse matrix + btVector3 m_c1; // Relative anchor + btScalar m_c2; // ima*dt + }; + /* Note */ + struct Note : Element + { + const char* m_text; // Text + btVector3 m_offset; // Offset + int m_rank; // Rank + Node* m_nodes[4]; // Nodes + btScalar m_coords[4]; // Coordinates + }; + /* Pose */ + struct Pose + { + bool m_bvolume; // Is valid + bool m_bframe; // Is frame + btScalar m_volume; // Rest volume + tVector3Array m_pos; // Reference positions + tScalarArray m_wgh; // Weights + btVector3 m_com; // COM + btMatrix3x3 m_rot; // Rotation + btMatrix3x3 m_scl; // Scale + btMatrix3x3 m_aqq; // Base scaling + }; + /* Cluster */ + struct Cluster + { + tScalarArray m_masses; + btAlignedObjectArray m_nodes; + tVector3Array m_framerefs; + btTransform m_framexform; + btScalar m_idmass; + btScalar m_imass; + btMatrix3x3 m_locii; + btMatrix3x3 m_invwi; + btVector3 m_com; + btVector3 m_vimpulses[2]; + btVector3 m_dimpulses[2]; + int m_nvimpulses; + int m_ndimpulses; + btVector3 m_lv; + btVector3 m_av; + btDbvtNode* m_leaf; + btScalar m_ndamping; /* Node damping */ + btScalar m_ldamping; /* Linear damping */ + btScalar m_adamping; /* Angular damping */ + btScalar m_matching; + btScalar m_maxSelfCollisionImpulse; + btScalar m_selfCollisionImpulseFactor; + bool m_containsAnchor; + bool m_collide; + int m_clusterIndex; + Cluster() : m_leaf(0),m_ndamping(0),m_ldamping(0),m_adamping(0),m_matching(0) + ,m_maxSelfCollisionImpulse(100.f), + m_selfCollisionImpulseFactor(0.01f), + m_containsAnchor(false) + {} + }; + /* Impulse */ + struct Impulse + { + btVector3 m_velocity; + btVector3 m_drift; + int m_asVelocity:1; + int m_asDrift:1; + Impulse() : m_velocity(0,0,0),m_drift(0,0,0),m_asVelocity(0),m_asDrift(0) {} + Impulse operator -() const + { + Impulse i=*this; + i.m_velocity=-i.m_velocity; + i.m_drift=-i.m_drift; + return(i); + } + Impulse operator*(btScalar x) const + { + Impulse i=*this; + i.m_velocity*=x; + i.m_drift*=x; + return(i); + } + }; + /* Body */ + struct Body + { + Cluster* m_soft; + btRigidBody* m_rigid; + btCollisionObject* m_collisionObject; + + Body() : m_soft(0),m_rigid(0),m_collisionObject(0) {} + Body(Cluster* p) : m_soft(p),m_rigid(0),m_collisionObject(0) {} + Body(btCollisionObject* colObj) : m_soft(0),m_collisionObject(colObj) + { + m_rigid = btRigidBody::upcast(m_collisionObject); + } + + void activate() const + { + if(m_rigid) + m_rigid->activate(); + if (m_collisionObject) + m_collisionObject->activate(); + + } + const btMatrix3x3& invWorldInertia() const + { + static const btMatrix3x3 iwi(0,0,0,0,0,0,0,0,0); + if(m_rigid) return(m_rigid->getInvInertiaTensorWorld()); + if(m_soft) return(m_soft->m_invwi); + return(iwi); + } + btScalar invMass() const + { + if(m_rigid) return(m_rigid->getInvMass()); + if(m_soft) return(m_soft->m_imass); + return(0); + } + const btTransform& xform() const + { + static const btTransform identity=btTransform::getIdentity(); + if(m_collisionObject) return(m_collisionObject->getWorldTransform()); + if(m_soft) return(m_soft->m_framexform); + return(identity); + } + btVector3 linearVelocity() const + { + if(m_rigid) return(m_rigid->getLinearVelocity()); + if(m_soft) return(m_soft->m_lv); + return(btVector3(0,0,0)); + } + btVector3 angularVelocity(const btVector3& rpos) const + { + if(m_rigid) return(btCross(m_rigid->getAngularVelocity(),rpos)); + if(m_soft) return(btCross(m_soft->m_av,rpos)); + return(btVector3(0,0,0)); + } + btVector3 angularVelocity() const + { + if(m_rigid) return(m_rigid->getAngularVelocity()); + if(m_soft) return(m_soft->m_av); + return(btVector3(0,0,0)); + } + btVector3 velocity(const btVector3& rpos) const + { + return(linearVelocity()+angularVelocity(rpos)); + } + void applyVImpulse(const btVector3& impulse,const btVector3& rpos) const + { + if(m_rigid) m_rigid->applyImpulse(impulse,rpos); + if(m_soft) btSoftBody::clusterVImpulse(m_soft,rpos,impulse); + } + void applyDImpulse(const btVector3& impulse,const btVector3& rpos) const + { + if(m_rigid) m_rigid->applyImpulse(impulse,rpos); + if(m_soft) btSoftBody::clusterDImpulse(m_soft,rpos,impulse); + } + void applyImpulse(const Impulse& impulse,const btVector3& rpos) const + { + if(impulse.m_asVelocity) + { +// printf("impulse.m_velocity = %f,%f,%f\n",impulse.m_velocity.getX(),impulse.m_velocity.getY(),impulse.m_velocity.getZ()); + applyVImpulse(impulse.m_velocity,rpos); + } + if(impulse.m_asDrift) + { +// printf("impulse.m_drift = %f,%f,%f\n",impulse.m_drift.getX(),impulse.m_drift.getY(),impulse.m_drift.getZ()); + applyDImpulse(impulse.m_drift,rpos); + } + } + void applyVAImpulse(const btVector3& impulse) const + { + if(m_rigid) m_rigid->applyTorqueImpulse(impulse); + if(m_soft) btSoftBody::clusterVAImpulse(m_soft,impulse); + } + void applyDAImpulse(const btVector3& impulse) const + { + if(m_rigid) m_rigid->applyTorqueImpulse(impulse); + if(m_soft) btSoftBody::clusterDAImpulse(m_soft,impulse); + } + void applyAImpulse(const Impulse& impulse) const + { + if(impulse.m_asVelocity) applyVAImpulse(impulse.m_velocity); + if(impulse.m_asDrift) applyDAImpulse(impulse.m_drift); + } + void applyDCImpulse(const btVector3& impulse) const + { + if(m_rigid) m_rigid->applyCentralImpulse(impulse); + if(m_soft) btSoftBody::clusterDCImpulse(m_soft,impulse); + } + }; + /* Joint */ + struct Joint + { + struct eType { enum _ { + Linear=0, + Angular, + Contact + };}; + struct Specs + { + Specs() : erp(1),cfm(1),split(1) {} + btScalar erp; + btScalar cfm; + btScalar split; + }; + Body m_bodies[2]; + btVector3 m_refs[2]; + btScalar m_cfm; + btScalar m_erp; + btScalar m_split; + btVector3 m_drift; + btVector3 m_sdrift; + btMatrix3x3 m_massmatrix; + bool m_delete; + virtual ~Joint() {} + Joint() : m_delete(false) {} + virtual void Prepare(btScalar dt,int iterations); + virtual void Solve(btScalar dt,btScalar sor)=0; + virtual void Terminate(btScalar dt)=0; + virtual eType::_ Type() const=0; + }; + /* LJoint */ + struct LJoint : Joint + { + struct Specs : Joint::Specs + { + btVector3 position; + }; + btVector3 m_rpos[2]; + void Prepare(btScalar dt,int iterations); + void Solve(btScalar dt,btScalar sor); + void Terminate(btScalar dt); + eType::_ Type() const { return(eType::Linear); } + }; + /* AJoint */ + struct AJoint : Joint + { + struct IControl + { + virtual void Prepare(AJoint*) {} + virtual btScalar Speed(AJoint*,btScalar current) { return(current); } + static IControl* Default() { static IControl def;return(&def); } + }; + struct Specs : Joint::Specs + { + Specs() : icontrol(IControl::Default()) {} + btVector3 axis; + IControl* icontrol; + }; + btVector3 m_axis[2]; + IControl* m_icontrol; + void Prepare(btScalar dt,int iterations); + void Solve(btScalar dt,btScalar sor); + void Terminate(btScalar dt); + eType::_ Type() const { return(eType::Angular); } + }; + /* CJoint */ + struct CJoint : Joint + { + int m_life; + int m_maxlife; + btVector3 m_rpos[2]; + btVector3 m_normal; + btScalar m_friction; + void Prepare(btScalar dt,int iterations); + void Solve(btScalar dt,btScalar sor); + void Terminate(btScalar dt); + eType::_ Type() const { return(eType::Contact); } + }; + /* Config */ + struct Config + { + eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point) + btScalar kVCF; // Velocities correction factor (Baumgarte) + btScalar kDP; // Damping coefficient [0,1] + btScalar kDG; // Drag coefficient [0,+inf] + btScalar kLF; // Lift coefficient [0,+inf] + btScalar kPR; // Pressure coefficient [-inf,+inf] + btScalar kVC; // Volume conversation coefficient [0,+inf] + btScalar kDF; // Dynamic friction coefficient [0,1] + btScalar kMT; // Pose matching coefficient [0,1] + btScalar kCHR; // Rigid contacts hardness [0,1] + btScalar kKHR; // Kinetic contacts hardness [0,1] + btScalar kSHR; // Soft contacts hardness [0,1] + btScalar kAHR; // Anchors hardness [0,1] + btScalar kSRHR_CL; // Soft vs rigid hardness [0,1] (cluster only) + btScalar kSKHR_CL; // Soft vs kinetic hardness [0,1] (cluster only) + btScalar kSSHR_CL; // Soft vs soft hardness [0,1] (cluster only) + btScalar kSR_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) + btScalar kSK_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) + btScalar kSS_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) + btScalar maxvolume; // Maximum volume ratio for pose + btScalar timescale; // Time scale + int viterations; // Velocities solver iterations + int piterations; // Positions solver iterations + int diterations; // Drift solver iterations + int citerations; // Cluster solver iterations + int collisions; // Collisions flags + tVSolverArray m_vsequence; // Velocity solvers sequence + tPSolverArray m_psequence; // Position solvers sequence + tPSolverArray m_dsequence; // Drift solvers sequence + }; + /* SolverState */ + struct SolverState + { + btScalar sdt; // dt*timescale + btScalar isdt; // 1/sdt + btScalar velmrg; // velocity margin + btScalar radmrg; // radial margin + btScalar updmrg; // Update margin + }; + /// RayFromToCaster takes a ray from, ray to (instead of direction!) + struct RayFromToCaster : btDbvt::ICollide + { + btVector3 m_rayFrom; + btVector3 m_rayTo; + btVector3 m_rayNormalizedDirection; + btScalar m_mint; + Face* m_face; + int m_tests; + RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt); + void Process(const btDbvtNode* leaf); + + static inline btScalar rayFromToTriangle(const btVector3& rayFrom, + const btVector3& rayTo, + const btVector3& rayNormalizedDirection, + const btVector3& a, + const btVector3& b, + const btVector3& c, + btScalar maxt=SIMD_INFINITY); + }; + + // + // Typedefs + // + + typedef void (*psolver_t)(btSoftBody*,btScalar,btScalar); + typedef void (*vsolver_t)(btSoftBody*,btScalar); + typedef btAlignedObjectArray tClusterArray; + typedef btAlignedObjectArray tNoteArray; + typedef btAlignedObjectArray tNodeArray; + typedef btAlignedObjectArray tLeafArray; + typedef btAlignedObjectArray tLinkArray; + typedef btAlignedObjectArray tFaceArray; + typedef btAlignedObjectArray tTetraArray; + typedef btAlignedObjectArray tAnchorArray; + typedef btAlignedObjectArray tRContactArray; + typedef btAlignedObjectArray tSContactArray; + typedef btAlignedObjectArray tMaterialArray; + typedef btAlignedObjectArray tJointArray; + typedef btAlignedObjectArray tSoftBodyArray; + + // + // Fields + // + + Config m_cfg; // Configuration + SolverState m_sst; // Solver state + Pose m_pose; // Pose + void* m_tag; // User data + btSoftBodyWorldInfo* m_worldInfo; // World info + tNoteArray m_notes; // Notes + tNodeArray m_nodes; // Nodes + tLinkArray m_links; // Links + tFaceArray m_faces; // Faces + tTetraArray m_tetras; // Tetras + tAnchorArray m_anchors; // Anchors + tRContactArray m_rcontacts; // Rigid contacts + tSContactArray m_scontacts; // Soft contacts + tJointArray m_joints; // Joints + tMaterialArray m_materials; // Materials + btScalar m_timeacc; // Time accumulator + btVector3 m_bounds[2]; // Spatial bounds + bool m_bUpdateRtCst; // Update runtime constants + btDbvt m_ndbvt; // Nodes tree + btDbvt m_fdbvt; // Faces tree + btDbvt m_cdbvt; // Clusters tree + tClusterArray m_clusters; // Clusters + + btAlignedObjectArraym_clusterConnectivity;//cluster connectivity, for self-collision + + btTransform m_initialWorldTransform; + + btVector3 m_windVelocity; + // + // Api + // + + /* ctor */ + btSoftBody( btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m); + + /* ctor */ + btSoftBody( btSoftBodyWorldInfo* worldInfo); + + void initDefaults(); + + /* dtor */ + virtual ~btSoftBody(); + /* Check for existing link */ + + btAlignedObjectArray m_userIndexMapping; + + btSoftBodyWorldInfo* getWorldInfo() + { + return m_worldInfo; + } + + ///@todo: avoid internal softbody shape hack and move collision code to collision library + virtual void setCollisionShape(btCollisionShape* collisionShape) + { + + } + + bool checkLink( int node0, + int node1) const; + bool checkLink( const Node* node0, + const Node* node1) const; + /* Check for existring face */ + bool checkFace( int node0, + int node1, + int node2) const; + /* Append material */ + Material* appendMaterial(); + /* Append note */ + void appendNote( const char* text, + const btVector3& o, + const btVector4& c=btVector4(1,0,0,0), + Node* n0=0, + Node* n1=0, + Node* n2=0, + Node* n3=0); + void appendNote( const char* text, + const btVector3& o, + Node* feature); + void appendNote( const char* text, + const btVector3& o, + Link* feature); + void appendNote( const char* text, + const btVector3& o, + Face* feature); + /* Append node */ + void appendNode( const btVector3& x,btScalar m); + /* Append link */ + void appendLink(int model=-1,Material* mat=0); + void appendLink( int node0, + int node1, + Material* mat=0, + bool bcheckexist=false); + void appendLink( Node* node0, + Node* node1, + Material* mat=0, + bool bcheckexist=false); + /* Append face */ + void appendFace(int model=-1,Material* mat=0); + void appendFace( int node0, + int node1, + int node2, + Material* mat=0); + void appendTetra(int model,Material* mat); + // + void appendTetra(int node0, + int node1, + int node2, + int node3, + Material* mat=0); + + + /* Append anchor */ + void appendAnchor( int node, + btRigidBody* body, bool disableCollisionBetweenLinkedBodies=false,btScalar influence = 1); + void appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies=false,btScalar influence = 1); + /* Append linear joint */ + void appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1); + void appendLinearJoint(const LJoint::Specs& specs,Body body=Body()); + void appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body); + /* Append linear joint */ + void appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1); + void appendAngularJoint(const AJoint::Specs& specs,Body body=Body()); + void appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body); + /* Add force (or gravity) to the entire body */ + void addForce( const btVector3& force); + /* Add force (or gravity) to a node of the body */ + void addForce( const btVector3& force, + int node); + /* Add aero force to a node of the body */ + void addAeroForceToNode(const btVector3& windVelocity,int nodeIndex); + + /* Add aero force to a face of the body */ + void addAeroForceToFace(const btVector3& windVelocity,int faceIndex); + + /* Add velocity to the entire body */ + void addVelocity( const btVector3& velocity); + + /* Set velocity for the entire body */ + void setVelocity( const btVector3& velocity); + + /* Add velocity to a node of the body */ + void addVelocity( const btVector3& velocity, + int node); + /* Set mass */ + void setMass( int node, + btScalar mass); + /* Get mass */ + btScalar getMass( int node) const; + /* Get total mass */ + btScalar getTotalMass() const; + /* Set total mass (weighted by previous masses) */ + void setTotalMass( btScalar mass, + bool fromfaces=false); + /* Set total density */ + void setTotalDensity(btScalar density); + /* Set volume mass (using tetrahedrons) */ + void setVolumeMass( btScalar mass); + /* Set volume density (using tetrahedrons) */ + void setVolumeDensity( btScalar density); + /* Transform */ + void transform( const btTransform& trs); + /* Translate */ + void translate( const btVector3& trs); + /* Rotate */ + void rotate( const btQuaternion& rot); + /* Scale */ + void scale( const btVector3& scl); + /* Set current state as pose */ + void setPose( bool bvolume, + bool bframe); + /* Return the volume */ + btScalar getVolume() const; + /* Cluster count */ + int clusterCount() const; + /* Cluster center of mass */ + static btVector3 clusterCom(const Cluster* cluster); + btVector3 clusterCom(int cluster) const; + /* Cluster velocity at rpos */ + static btVector3 clusterVelocity(const Cluster* cluster,const btVector3& rpos); + /* Cluster impulse */ + static void clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse); + static void clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse); + static void clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse); + static void clusterVAImpulse(Cluster* cluster,const btVector3& impulse); + static void clusterDAImpulse(Cluster* cluster,const btVector3& impulse); + static void clusterAImpulse(Cluster* cluster,const Impulse& impulse); + static void clusterDCImpulse(Cluster* cluster,const btVector3& impulse); + /* Generate bending constraints based on distance in the adjency graph */ + int generateBendingConstraints( int distance, + Material* mat=0); + /* Randomize constraints to reduce solver bias */ + void randomizeConstraints(); + /* Release clusters */ + void releaseCluster(int index); + void releaseClusters(); + /* Generate clusters (K-mean) */ + ///generateClusters with k=0 will create a convex cluster for each tetrahedron or triangle + ///otherwise an approximation will be used (better performance) + int generateClusters(int k,int maxiterations=8192); + /* Refine */ + void refine(ImplicitFn* ifn,btScalar accurary,bool cut); + /* CutLink */ + bool cutLink(int node0,int node1,btScalar position); + bool cutLink(const Node* node0,const Node* node1,btScalar position); + + ///Ray casting using rayFrom and rayTo in worldspace, (not direction!) + bool rayTest(const btVector3& rayFrom, + const btVector3& rayTo, + sRayCast& results); + /* Solver presets */ + void setSolver(eSolverPresets::_ preset); + /* predictMotion */ + void predictMotion(btScalar dt); + /* solveConstraints */ + void solveConstraints(); + /* staticSolve */ + void staticSolve(int iterations); + /* solveCommonConstraints */ + static void solveCommonConstraints(btSoftBody** bodies,int count,int iterations); + /* solveClusters */ + static void solveClusters(const btAlignedObjectArray& bodies); + /* integrateMotion */ + void integrateMotion(); + /* defaultCollisionHandlers */ + void defaultCollisionHandler(btCollisionObject* pco); + void defaultCollisionHandler(btSoftBody* psb); + + + + // + // Functionality to deal with new accelerated solvers. + // + + /** + * Set a wind velocity for interaction with the air. + */ + void setWindVelocity( const btVector3 &velocity ); + + + /** + * Return the wind velocity for interaction with the air. + */ + const btVector3& getWindVelocity(); + + // + // Set the solver that handles this soft body + // Should not be allowed to get out of sync with reality + // Currently called internally on addition to the world + void setSoftBodySolver( btSoftBodySolver *softBodySolver ) + { + m_softBodySolver = softBodySolver; + } + + // + // Return the solver that handles this soft body + // + btSoftBodySolver *getSoftBodySolver() + { + return m_softBodySolver; + } + + // + // Return the solver that handles this soft body + // + btSoftBodySolver *getSoftBodySolver() const + { + return m_softBodySolver; + } + + + // + // Cast + // + + static const btSoftBody* upcast(const btCollisionObject* colObj) + { + if (colObj->getInternalType()==CO_SOFT_BODY) + return (const btSoftBody*)colObj; + return 0; + } + static btSoftBody* upcast(btCollisionObject* colObj) + { + if (colObj->getInternalType()==CO_SOFT_BODY) + return (btSoftBody*)colObj; + return 0; + } + + // + // ::btCollisionObject + // + + virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin = m_bounds[0]; + aabbMax = m_bounds[1]; + } + // + // Private + // + void pointersToIndices(); + void indicesToPointers(const int* map=0); + + int rayTest(const btVector3& rayFrom,const btVector3& rayTo, + btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const; + void initializeFaceTree(); + btVector3 evaluateCom() const; + bool checkContact(btCollisionObject* colObj,const btVector3& x,btScalar margin,btSoftBody::sCti& cti) const; + void updateNormals(); + void updateBounds(); + void updatePose(); + void updateConstants(); + void initializeClusters(); + void updateClusters(); + void cleanupClusters(); + void prepareClusters(int iterations); + void solveClusters(btScalar sor); + void applyClusters(bool drift); + void dampClusters(); + void applyForces(); + static void PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti); + static void PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti); + static void PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti); + static void PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti); + static void VSolve_Links(btSoftBody* psb,btScalar kst); + static psolver_t getSolver(ePSolver::_ solver); + static vsolver_t getSolver(eVSolver::_ solver); + + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const; + + //virtual void serializeSingleObject(class btSerializer* serializer) const; + + +}; + + + + +#endif //_BT_SOFT_BODY_H diff --git a/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp b/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp new file mode 100644 index 0000000..d99be3b --- /dev/null +++ b/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp @@ -0,0 +1,368 @@ +/* +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 "btSoftBodyConcaveCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionShapes/btConcaveShape.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" +#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" +#include "BulletCollision/CollisionShapes/btConvexHullShape.h" + + + +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletSoftBody/btSoftBody.h" + +#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.06)//make this configurable + +btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) +: btCollisionAlgorithm(ci), +m_isSwapped(isSwapped), +m_btSoftBodyTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped) +{ +} + + + +btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm() +{ +} + + + +btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped): +m_dispatcher(dispatcher), +m_dispatchInfoPtr(0) +{ + m_softBody = (btSoftBody*) (isSwapped? body1:body0); + m_triBody = isSwapped? body0:body1; + + // + // create the manifold from the dispatcher 'manifold pool' + // + // m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody); + + clearCache(); +} + +btSoftBodyTriangleCallback::~btSoftBodyTriangleCallback() +{ + clearCache(); + // m_dispatcher->releaseManifold( m_manifoldPtr ); + +} + + +void btSoftBodyTriangleCallback::clearCache() +{ + for (int i=0;im_childShape); + m_softBody->getWorldInfo()->m_sparsesdf.RemoveReferences(tmp->m_childShape);//necessary? + delete tmp->m_childShape; + } + m_shapeCache.clear(); +} + + +void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) +{ + //just for debugging purposes + //printf("triangle %d",m_triangleCount++); + btCollisionObject* ob = static_cast(m_triBody); + btCollisionAlgorithmConstructionInfo ci; + ci.m_dispatcher1 = m_dispatcher; + + ///debug drawing of the overlapping triangles + if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe)) + { + btVector3 color(1,1,0); + btTransform& tr = ob->getWorldTransform(); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color); + } + + btTriIndex triIndex(partId,triangleIndex,0); + btHashKey triKey(triIndex.getUid()); + + + btTriIndex* shapeIndex = m_shapeCache[triKey]; + if (shapeIndex) + { + btCollisionShape* tm = shapeIndex->m_childShape; + btAssert(tm); + + //copy over user pointers to temporary shape + tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer()); + + btCollisionShape* tmpShape = ob->getCollisionShape(); + ob->internalSetTemporaryCollisionShape( tm ); + + + btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr); + + colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); + colAlgo->~btCollisionAlgorithm(); + ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); + ob->internalSetTemporaryCollisionShape( tmpShape); + return; + } + + //aabb filter is already applied! + + //btCollisionObject* colObj = static_cast(m_convexProxy->m_clientObject); + + // if (m_softBody->getCollisionShape()->getShapeType()== + { + // btVector3 other; + btVector3 normal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]); + normal.normalize(); + normal*= BT_SOFTBODY_TRIANGLE_EXTRUSION; + // other=(triangle[0]+triangle[1]+triangle[2])*0.333333f; + // other+=normal*22.f; + btVector3 pts[6] = {triangle[0]+normal, + triangle[1]+normal, + triangle[2]+normal, + triangle[0]-normal, + triangle[1]-normal, + triangle[2]-normal}; + + btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(),6); + + + // btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other); + + //btTriangleShape tm(triangle[0],triangle[1],triangle[2]); + // tm.setMargin(m_collisionMarginTriangle); + + //copy over user pointers to temporary shape + tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer()); + + btCollisionShape* tmpShape = ob->getCollisionShape(); + ob->internalSetTemporaryCollisionShape( tm ); + + + btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr); + ///this should use the btDispatcher, so the actual registered algorithm is used + // btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody); + + //m_resultOut->setShapeIdentifiersB(partId,triangleIndex); + // cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); + colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); + colAlgo->~btCollisionAlgorithm(); + ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); + + + ob->internalSetTemporaryCollisionShape( tmpShape ); + triIndex.m_childShape = tm; + m_shapeCache.insert(triKey,triIndex); + + } + + + +} + + + +void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + m_dispatchInfoPtr = &dispatchInfo; + m_collisionMarginTriangle = collisionMarginTriangle+btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION); + m_resultOut = resultOut; + + + btVector3 aabbWorldSpaceMin,aabbWorldSpaceMax; + m_softBody->getAabb(aabbWorldSpaceMin,aabbWorldSpaceMax); + btVector3 halfExtents = (aabbWorldSpaceMax-aabbWorldSpaceMin)*btScalar(0.5); + btVector3 softBodyCenter = (aabbWorldSpaceMax+aabbWorldSpaceMin)*btScalar(0.5); + + btTransform softTransform; + softTransform.setIdentity(); + softTransform.setOrigin(softBodyCenter); + + btTransform convexInTriangleSpace; + convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * softTransform; + btTransformAabb(halfExtents,m_collisionMarginTriangle,convexInTriangleSpace,m_aabbMin,m_aabbMax); +} + +void btSoftBodyConcaveCollisionAlgorithm::clearCache() +{ + m_btSoftBodyTriangleCallback.clearCache(); + +} + +void btSoftBodyConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + + + //btCollisionObject* convexBody = m_isSwapped ? body1 : body0; + btCollisionObject* triBody = m_isSwapped ? body0 : body1; + + if (triBody->getCollisionShape()->isConcave()) + { + + + btCollisionObject* triOb = triBody; + btConcaveShape* concaveShape = static_cast( triOb->getCollisionShape()); + + // if (convexBody->getCollisionShape()->isConvex()) + { + btScalar collisionMarginTriangle = concaveShape->getMargin(); + + // resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr); + m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut); + + //Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here. + //m_dispatcher->clearManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr); + + // m_btSoftBodyTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody); + + + concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax()); + + // resultOut->refreshContactPoints(); + + } + + } + +} + + +btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + btCollisionObject* convexbody = m_isSwapped ? body1 : body0; + btCollisionObject* triBody = m_isSwapped ? body0 : body1; + + + //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast) + + //only perform CCD above a certain threshold, this prevents blocking on the long run + //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame... + btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2(); + if (squareMot0 < convexbody->getCcdSquareMotionThreshold()) + { + return btScalar(1.); + } + + //const btVector3& from = convexbody->m_worldTransform.getOrigin(); + //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin(); + //todo: only do if the motion exceeds the 'radius' + + btTransform triInv = triBody->getWorldTransform().inverse(); + btTransform convexFromLocal = triInv * convexbody->getWorldTransform(); + btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform(); + + struct LocalTriangleSphereCastCallback : public btTriangleCallback + { + btTransform m_ccdSphereFromTrans; + btTransform m_ccdSphereToTrans; + btTransform m_meshTransform; + + btScalar m_ccdSphereRadius; + btScalar m_hitFraction; + + + LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction) + :m_ccdSphereFromTrans(from), + m_ccdSphereToTrans(to), + m_ccdSphereRadius(ccdSphereRadius), + m_hitFraction(hitFraction) + { + } + + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + (void)partId; + (void)triangleIndex; + //do a swept sphere for now + btTransform ident; + ident.setIdentity(); + btConvexCast::CastResult castResult; + castResult.m_fraction = m_hitFraction; + btSphereShape pointShape(m_ccdSphereRadius); + btTriangleShape triShape(triangle[0],triangle[1],triangle[2]); + btVoronoiSimplexSolver simplexSolver; + btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver); + //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); + //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0); + //local space? + + if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans, + ident,ident,castResult)) + { + if (m_hitFraction > castResult.m_fraction) + m_hitFraction = castResult.m_fraction; + } + + } + + }; + + + + + + if (triBody->getCollisionShape()->isConcave()) + { + btVector3 rayAabbMin = convexFromLocal.getOrigin(); + rayAabbMin.setMin(convexToLocal.getOrigin()); + btVector3 rayAabbMax = convexFromLocal.getOrigin(); + rayAabbMax.setMax(convexToLocal.getOrigin()); + btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius(); + rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0); + rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0); + + btScalar curHitFraction = btScalar(1.); //is this available? + LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal, + convexbody->getCcdSweptSphereRadius(),curHitFraction); + + raycastCallback.m_hitFraction = convexbody->getHitFraction(); + + btCollisionObject* concavebody = triBody; + + btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape(); + + if (triangleMesh) + { + triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax); + } + + + + if (raycastCallback.m_hitFraction < convexbody->getHitFraction()) + { + convexbody->setHitFraction( raycastCallback.m_hitFraction); + return raycastCallback.m_hitFraction; + } + } + + return btScalar(1.); + +} diff --git a/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h b/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h new file mode 100644 index 0000000..11ec5b3 --- /dev/null +++ b/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h @@ -0,0 +1,153 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H +#define BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +class btDispatcher; +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +class btSoftBody; +class btCollisionShape; + +#include "LinearMath/btHashMap.h" + +#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h" //for definition of MAX_NUM_PARTS_IN_BITS + +struct btTriIndex +{ + int m_PartIdTriangleIndex; + class btCollisionShape* m_childShape; + + btTriIndex(int partId,int triangleIndex,btCollisionShape* shape) + { + m_PartIdTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex; + m_childShape = shape; + } + + int getTriangleIndex() const + { + // Get only the lower bits where the triangle index is stored + return (m_PartIdTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS))); + } + int getPartId() const + { + // Get only the highest bits where the part index is stored + return (m_PartIdTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS)); + } + int getUid() const + { + return m_PartIdTriangleIndex; + } +}; + + +///For each triangle in the concave mesh that overlaps with the AABB of a soft body (m_softBody), processTriangle is called. +class btSoftBodyTriangleCallback : public btTriangleCallback +{ + btSoftBody* m_softBody; + btCollisionObject* m_triBody; + + btVector3 m_aabbMin; + btVector3 m_aabbMax ; + + btManifoldResult* m_resultOut; + + btDispatcher* m_dispatcher; + const btDispatcherInfo* m_dispatchInfoPtr; + btScalar m_collisionMarginTriangle; + + btHashMap,btTriIndex> m_shapeCache; + +public: + int m_triangleCount; + + // btPersistentManifold* m_manifoldPtr; + + btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); + + void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual ~btSoftBodyTriangleCallback(); + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); + + void clearCache(); + + SIMD_FORCE_INLINE const btVector3& getAabbMin() const + { + return m_aabbMin; + } + SIMD_FORCE_INLINE const btVector3& getAabbMax() const + { + return m_aabbMax; + } + +}; + + + + +/// btSoftBodyConcaveCollisionAlgorithm supports collision between soft body shapes and (concave) trianges meshes. +class btSoftBodyConcaveCollisionAlgorithm : public btCollisionAlgorithm +{ + + bool m_isSwapped; + + btSoftBodyTriangleCallback m_btSoftBodyTriangleCallback; + +public: + + btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); + + virtual ~btSoftBodyConcaveCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + //we don't add any manifolds + } + + void clearCache(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm)); + return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0,body1,false); + } + }; + + struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm)); + return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0,body1,true); + } + }; + +}; + +#endif //BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H diff --git a/src/BulletSoftBody/btSoftBodyData.h b/src/BulletSoftBody/btSoftBodyData.h new file mode 100644 index 0000000..a2fde77 --- /dev/null +++ b/src/BulletSoftBody/btSoftBodyData.h @@ -0,0 +1,217 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFTBODY_FLOAT_DATA +#define BT_SOFTBODY_FLOAT_DATA + +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" + + + +struct SoftBodyMaterialData +{ + float m_linearStiffness; + float m_angularStiffness; + float m_volumeStiffness; + int m_flags; +}; + +struct SoftBodyNodeData +{ + SoftBodyMaterialData *m_material; + btVector3FloatData m_position; + btVector3FloatData m_previousPosition; + btVector3FloatData m_velocity; + btVector3FloatData m_accumulatedForce; + btVector3FloatData m_normal; + float m_inverseMass; + float m_area; + int m_attach; + int m_pad; +}; + +struct SoftBodyLinkData +{ + SoftBodyMaterialData *m_material; + int m_nodeIndices[2]; // Node pointers + float m_restLength; // Rest length + int m_bbending; // Bending link +}; + +struct SoftBodyFaceData +{ + btVector3FloatData m_normal; // Normal + SoftBodyMaterialData *m_material; + int m_nodeIndices[3]; // Node pointers + float m_restArea; // Rest area +}; + +struct SoftBodyTetraData +{ + btVector3FloatData m_c0[4]; // gradients + SoftBodyMaterialData *m_material; + int m_nodeIndices[4]; // Node pointers + float m_restVolume; // Rest volume + float m_c1; // (4*kVST)/(im0+im1+im2+im3) + float m_c2; // m_c1/sum(|g0..3|^2) + int m_pad; +}; + +struct SoftRigidAnchorData +{ + btMatrix3x3FloatData m_c0; // Impulse matrix + btVector3FloatData m_c1; // Relative anchor + btVector3FloatData m_localFrame; // Anchor position in body space + btRigidBodyData *m_rigidBody; + int m_nodeIndex; // Node pointer + float m_c2; // ima*dt +}; + + + +struct SoftBodyConfigData +{ + int m_aeroModel; // Aerodynamic model (default: V_Point) + float m_baumgarte; // Velocities correction factor (Baumgarte) + float m_damping; // Damping coefficient [0,1] + float m_drag; // Drag coefficient [0,+inf] + float m_lift; // Lift coefficient [0,+inf] + float m_pressure; // Pressure coefficient [-inf,+inf] + float m_volume; // Volume conversation coefficient [0,+inf] + float m_dynamicFriction; // Dynamic friction coefficient [0,1] + float m_poseMatch; // Pose matching coefficient [0,1] + float m_rigidContactHardness; // Rigid contacts hardness [0,1] + float m_kineticContactHardness; // Kinetic contacts hardness [0,1] + float m_softContactHardness; // Soft contacts hardness [0,1] + float m_anchorHardness; // Anchors hardness [0,1] + float m_softRigidClusterHardness; // Soft vs rigid hardness [0,1] (cluster only) + float m_softKineticClusterHardness; // Soft vs kinetic hardness [0,1] (cluster only) + float m_softSoftClusterHardness; // Soft vs soft hardness [0,1] (cluster only) + float m_softRigidClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only) + float m_softKineticClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only) + float m_softSoftClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only) + float m_maxVolume; // Maximum volume ratio for pose + float m_timeScale; // Time scale + int m_velocityIterations; // Velocities solver iterations + int m_positionIterations; // Positions solver iterations + int m_driftIterations; // Drift solver iterations + int m_clusterIterations; // Cluster solver iterations + int m_collisionFlags; // Collisions flags +}; + +struct SoftBodyPoseData +{ + btMatrix3x3FloatData m_rot; // Rotation + btMatrix3x3FloatData m_scale; // Scale + btMatrix3x3FloatData m_aqq; // Base scaling + btVector3FloatData m_com; // COM + + btVector3FloatData *m_positions; // Reference positions + float *m_weights; // Weights + int m_numPositions; + int m_numWeigts; + + int m_bvolume; // Is valid + int m_bframe; // Is frame + float m_restVolume; // Rest volume + int m_pad; +}; + +struct SoftBodyClusterData +{ + btTransformFloatData m_framexform; + btMatrix3x3FloatData m_locii; + btMatrix3x3FloatData m_invwi; + btVector3FloatData m_com; + btVector3FloatData m_vimpulses[2]; + btVector3FloatData m_dimpulses[2]; + btVector3FloatData m_lv; + btVector3FloatData m_av; + + btVector3FloatData *m_framerefs; + int *m_nodeIndices; + float *m_masses; + + int m_numFrameRefs; + int m_numNodes; + int m_numMasses; + + float m_idmass; + float m_imass; + int m_nvimpulses; + int m_ndimpulses; + float m_ndamping; + float m_ldamping; + float m_adamping; + float m_matching; + float m_maxSelfCollisionImpulse; + float m_selfCollisionImpulseFactor; + int m_containsAnchor; + int m_collide; + int m_clusterIndex; +}; + + +enum btSoftJointBodyType +{ + BT_JOINT_SOFT_BODY_CLUSTER=1, + BT_JOINT_RIGID_BODY, + BT_JOINT_COLLISION_OBJECT +}; + +struct btSoftBodyJointData +{ + void *m_bodyA; + void *m_bodyB; + btVector3FloatData m_refs[2]; + float m_cfm; + float m_erp; + float m_split; + int m_delete; + btVector3FloatData m_relPosition[2];//linear + int m_bodyAtype; + int m_bodyBtype; + int m_jointType; + int m_pad; +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btSoftBodyFloatData +{ + btCollisionObjectFloatData m_collisionObjectData; + + SoftBodyPoseData *m_pose; + SoftBodyMaterialData **m_materials; + SoftBodyNodeData *m_nodes; + SoftBodyLinkData *m_links; + SoftBodyFaceData *m_faces; + SoftBodyTetraData *m_tetrahedra; + SoftRigidAnchorData *m_anchors; + SoftBodyClusterData *m_clusters; + btSoftBodyJointData *m_joints; + + int m_numMaterials; + int m_numNodes; + int m_numLinks; + int m_numFaces; + int m_numTetrahedra; + int m_numAnchors; + int m_numClusters; + int m_numJoints; + SoftBodyConfigData m_config; +}; + +#endif //BT_SOFTBODY_FLOAT_DATA + diff --git a/src/BulletSoftBody/btSoftBodyHelpers.cpp b/src/BulletSoftBody/btSoftBodyHelpers.cpp new file mode 100644 index 0000000..0fb3560 --- /dev/null +++ b/src/BulletSoftBody/btSoftBodyHelpers.cpp @@ -0,0 +1,1055 @@ +/* +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. +*/ +///btSoftBodyHelpers.cpp by Nathanael Presson + +#include "btSoftBodyInternals.h" +#include +#include +#include "btSoftBodyHelpers.h" +#include "LinearMath/btConvexHull.h" +#include "LinearMath/btConvexHullComputer.h" + + +// +static void drawVertex( btIDebugDraw* idraw, + const btVector3& x,btScalar s,const btVector3& c) +{ + idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c); + idraw->drawLine(x-btVector3(0,s,0),x+btVector3(0,s,0),c); + idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c); +} + +// +static void drawBox( btIDebugDraw* idraw, + const btVector3& mins, + const btVector3& maxs, + const btVector3& color) +{ + const btVector3 c[]={ btVector3(mins.x(),mins.y(),mins.z()), + btVector3(maxs.x(),mins.y(),mins.z()), + btVector3(maxs.x(),maxs.y(),mins.z()), + btVector3(mins.x(),maxs.y(),mins.z()), + btVector3(mins.x(),mins.y(),maxs.z()), + btVector3(maxs.x(),mins.y(),maxs.z()), + btVector3(maxs.x(),maxs.y(),maxs.z()), + btVector3(mins.x(),maxs.y(),maxs.z())}; + idraw->drawLine(c[0],c[1],color);idraw->drawLine(c[1],c[2],color); + idraw->drawLine(c[2],c[3],color);idraw->drawLine(c[3],c[0],color); + idraw->drawLine(c[4],c[5],color);idraw->drawLine(c[5],c[6],color); + idraw->drawLine(c[6],c[7],color);idraw->drawLine(c[7],c[4],color); + idraw->drawLine(c[0],c[4],color);idraw->drawLine(c[1],c[5],color); + idraw->drawLine(c[2],c[6],color);idraw->drawLine(c[3],c[7],color); +} + +// +static void drawTree( btIDebugDraw* idraw, + const btDbvtNode* node, + int depth, + const btVector3& ncolor, + const btVector3& lcolor, + int mindepth, + int maxdepth) +{ + if(node) + { + if(node->isinternal()&&((depthchilds[0],depth+1,ncolor,lcolor,mindepth,maxdepth); + drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth); + } + if(depth>=mindepth) + { + const btScalar scl=(btScalar)(node->isinternal()?1:1); + const btVector3 mi=node->volume.Center()-node->volume.Extents()*scl; + const btVector3 mx=node->volume.Center()+node->volume.Extents()*scl; + drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor); + } + } +} + +// +template +static inline T sum(const btAlignedObjectArray& items) +{ + T v; + if(items.size()) + { + v=items[0]; + for(int i=1,ni=items.size();i +static inline void add(btAlignedObjectArray& items,const Q& value) +{ + for(int i=0,ni=items.size();i +static inline void mul(btAlignedObjectArray& items,const Q& value) +{ + for(int i=0,ni=items.size();i +static inline T average(const btAlignedObjectArray& items) +{ + const btScalar n=(btScalar)(items.size()>0?items.size():1); + return(sum(items)/n); +} + +// +static inline btScalar tetravolume(const btVector3& x0, + const btVector3& x1, + const btVector3& x2, + const btVector3& x3) +{ + const btVector3 a=x1-x0; + const btVector3 b=x2-x0; + const btVector3 c=x3-x0; + return(btDot(a,btCross(b,c))); +} + +// +#if 0 +static btVector3 stresscolor(btScalar stress) +{ + static const btVector3 spectrum[]= { btVector3(1,0,1), + btVector3(0,0,1), + btVector3(0,1,1), + btVector3(0,1,0), + btVector3(1,1,0), + btVector3(1,0,0), + btVector3(1,0,0)}; + static const int ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1; + static const btScalar one=1; + stress=btMax(0,btMin(1,stress))*ncolors; + const int sel=(int)stress; + const btScalar frc=stress-sel; + return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc); +} +#endif + +// +void btSoftBodyHelpers::Draw( btSoftBody* psb, + btIDebugDraw* idraw, + int drawflags) +{ + const btScalar scl=(btScalar)0.1; + const btScalar nscl=scl*5; + const btVector3 lcolor=btVector3(0,0,0); + const btVector3 ncolor=btVector3(1,1,1); + const btVector3 ccolor=btVector3(1,0,0); + int i,j,nj; + + /* Clusters */ + if(0!=(drawflags&fDrawFlags::Clusters)) + { + srand(1806); + for(i=0;im_clusters.size();++i) + { + if(psb->m_clusters[i]->m_collide) + { + btVector3 color( rand()/(btScalar)RAND_MAX, + rand()/(btScalar)RAND_MAX, + rand()/(btScalar)RAND_MAX); + color=color.normalized()*0.75; + btAlignedObjectArray vertices; + vertices.resize(psb->m_clusters[i]->m_nodes.size()); + for(j=0,nj=vertices.size();jm_clusters[i]->m_nodes[j]->m_x; + } +#define USE_NEW_CONVEX_HULL_COMPUTER +#ifdef USE_NEW_CONVEX_HULL_COMPUTER + btConvexHullComputer computer; + int stride = sizeof(btVector3); + int count = vertices.size(); + btScalar shrink=0.f; + btScalar shrinkClamp=0.f; + computer.compute(&vertices[0].getX(),stride,count,shrink,shrinkClamp); + for (int i=0;igetNextEdgeOfFace(); + + int v0 = firstEdge->getSourceVertex(); + int v1 = firstEdge->getTargetVertex(); + while (edge!=firstEdge) + { + int v2 = edge->getTargetVertex(); + idraw->drawTriangle(computer.vertices[v0],computer.vertices[v1],computer.vertices[v2],color,1); + edge = edge->getNextEdgeOfFace(); + v0=v1; + v1=v2; + }; + } +#else + + HullDesc hdsc(QF_TRIANGLES,vertices.size(),&vertices[0]); + HullResult hres; + HullLibrary hlib; + hdsc.mMaxVertices=vertices.size(); + hlib.CreateConvexHull(hdsc,hres); + const btVector3 center=average(hres.m_OutputVertices); + add(hres.m_OutputVertices,-center); + mul(hres.m_OutputVertices,(btScalar)1); + add(hres.m_OutputVertices,center); + for(j=0;j<(int)hres.mNumFaces;++j) + { + const int idx[]={hres.m_Indices[j*3+0],hres.m_Indices[j*3+1],hres.m_Indices[j*3+2]}; + idraw->drawTriangle(hres.m_OutputVertices[idx[0]], + hres.m_OutputVertices[idx[1]], + hres.m_OutputVertices[idx[2]], + color,1); + } + hlib.ReleaseResult(hres); +#endif + + } + /* Velocities */ +#if 0 + for(int j=0;jm_clusters[i].m_nodes.size();++j) + { + const btSoftBody::Cluster& c=psb->m_clusters[i]; + const btVector3 r=c.m_nodes[j]->m_x-c.m_com; + const btVector3 v=c.m_lv+btCross(c.m_av,r); + idraw->drawLine(c.m_nodes[j]->m_x,c.m_nodes[j]->m_x+v,btVector3(1,0,0)); + } +#endif + /* Frame */ + // btSoftBody::Cluster& c=*psb->m_clusters[i]; + // idraw->drawLine(c.m_com,c.m_framexform*btVector3(10,0,0),btVector3(1,0,0)); + // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,10,0),btVector3(0,1,0)); + // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1)); + } + } + else + { + /* Nodes */ + if(0!=(drawflags&fDrawFlags::Nodes)) + { + for(i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0)); + idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0)); + idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1)); + } + } + /* Links */ + if(0!=(drawflags&fDrawFlags::Links)) + { + for(i=0;im_links.size();++i) + { + const btSoftBody::Link& l=psb->m_links[i]; + if(0==(l.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,lcolor); + } + } + /* Normals */ + if(0!=(drawflags&fDrawFlags::Normals)) + { + for(i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + const btVector3 d=n.m_n*nscl; + idraw->drawLine(n.m_x,n.m_x+d,ncolor); + idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5); + } + } + /* Contacts */ + if(0!=(drawflags&fDrawFlags::Contacts)) + { + static const btVector3 axis[]={btVector3(1,0,0), + btVector3(0,1,0), + btVector3(0,0,1)}; + for(i=0;im_rcontacts.size();++i) + { + const btSoftBody::RContact& c=psb->m_rcontacts[i]; + const btVector3 o= c.m_node->m_x-c.m_cti.m_normal* + (btDot(c.m_node->m_x,c.m_cti.m_normal)+c.m_cti.m_offset); + const btVector3 x=btCross(c.m_cti.m_normal,axis[c.m_cti.m_normal.minAxis()]).normalized(); + const btVector3 y=btCross(x,c.m_cti.m_normal).normalized(); + idraw->drawLine(o-x*nscl,o+x*nscl,ccolor); + idraw->drawLine(o-y*nscl,o+y*nscl,ccolor); + idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0)); + } + } + /* Faces */ + if(0!=(drawflags&fDrawFlags::Faces)) + { + const btScalar scl=(btScalar)0.8; + const btScalar alp=(btScalar)1; + const btVector3 col(0,(btScalar)0.7,0); + for(i=0;im_faces.size();++i) + { + const btSoftBody::Face& f=psb->m_faces[i]; + if(0==(f.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x}; + const btVector3 c=(x[0]+x[1]+x[2])/3; + idraw->drawTriangle((x[0]-c)*scl+c, + (x[1]-c)*scl+c, + (x[2]-c)*scl+c, + col,alp); + } + } + /* Tetras */ + if(0!=(drawflags&fDrawFlags::Tetras)) + { + const btScalar scl=(btScalar)0.8; + const btScalar alp=(btScalar)1; + const btVector3 col((btScalar)0.3,(btScalar)0.3,(btScalar)0.7); + for(int i=0;im_tetras.size();++i) + { + const btSoftBody::Tetra& t=psb->m_tetras[i]; + if(0==(t.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + const btVector3 x[]={t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x}; + const btVector3 c=(x[0]+x[1]+x[2]+x[3])/4; + idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[2]-c)*scl+c,col,alp); + idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[3]-c)*scl+c,col,alp); + idraw->drawTriangle((x[1]-c)*scl+c,(x[2]-c)*scl+c,(x[3]-c)*scl+c,col,alp); + idraw->drawTriangle((x[2]-c)*scl+c,(x[0]-c)*scl+c,(x[3]-c)*scl+c,col,alp); + } + } + } + /* Anchors */ + if(0!=(drawflags&fDrawFlags::Anchors)) + { + for(i=0;im_anchors.size();++i) + { + const btSoftBody::Anchor& a=psb->m_anchors[i]; + const btVector3 q=a.m_body->getWorldTransform()*a.m_local; + drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0)); + drawVertex(idraw,q,0.25,btVector3(0,1,0)); + idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1)); + } + for(i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + if(n.m_im<=0) + { + drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0)); + } + } + } + + + /* Notes */ + if(0!=(drawflags&fDrawFlags::Notes)) + { + for(i=0;im_notes.size();++i) + { + const btSoftBody::Note& n=psb->m_notes[i]; + btVector3 p=n.m_offset; + for(int j=0;jm_x*n.m_coords[j]; + } + idraw->draw3dText(p,n.m_text); + } + } + /* Node tree */ + if(0!=(drawflags&fDrawFlags::NodeTree)) DrawNodeTree(psb,idraw); + /* Face tree */ + if(0!=(drawflags&fDrawFlags::FaceTree)) DrawFaceTree(psb,idraw); + /* Cluster tree */ + if(0!=(drawflags&fDrawFlags::ClusterTree)) DrawClusterTree(psb,idraw); + /* Joints */ + if(0!=(drawflags&fDrawFlags::Joints)) + { + for(i=0;im_joints.size();++i) + { + const btSoftBody::Joint* pj=psb->m_joints[i]; + switch(pj->Type()) + { + case btSoftBody::Joint::eType::Linear: + { + const btSoftBody::LJoint* pjl=(const btSoftBody::LJoint*)pj; + const btVector3 a0=pj->m_bodies[0].xform()*pjl->m_refs[0]; + const btVector3 a1=pj->m_bodies[1].xform()*pjl->m_refs[1]; + idraw->drawLine(pj->m_bodies[0].xform().getOrigin(),a0,btVector3(1,1,0)); + idraw->drawLine(pj->m_bodies[1].xform().getOrigin(),a1,btVector3(0,1,1)); + drawVertex(idraw,a0,0.25,btVector3(1,1,0)); + drawVertex(idraw,a1,0.25,btVector3(0,1,1)); + } + break; + case btSoftBody::Joint::eType::Angular: + { + //const btSoftBody::AJoint* pja=(const btSoftBody::AJoint*)pj; + const btVector3 o0=pj->m_bodies[0].xform().getOrigin(); + const btVector3 o1=pj->m_bodies[1].xform().getOrigin(); + const btVector3 a0=pj->m_bodies[0].xform().getBasis()*pj->m_refs[0]; + const btVector3 a1=pj->m_bodies[1].xform().getBasis()*pj->m_refs[1]; + idraw->drawLine(o0,o0+a0*10,btVector3(1,1,0)); + idraw->drawLine(o0,o0+a1*10,btVector3(1,1,0)); + idraw->drawLine(o1,o1+a0*10,btVector3(0,1,1)); + idraw->drawLine(o1,o1+a1*10,btVector3(0,1,1)); + break; + } + default: + { + } + + } + } + } +} + +// +void btSoftBodyHelpers::DrawInfos( btSoftBody* psb, + btIDebugDraw* idraw, + bool masses, + bool areas, + bool /*stress*/) +{ + for(int i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + char text[2048]={0}; + char buff[1024]; + if(masses) + { + sprintf(buff," M(%.2f)",1/n.m_im); + strcat(text,buff); + } + if(areas) + { + sprintf(buff," A(%.2f)",n.m_area); + strcat(text,buff); + } + if(text[0]) idraw->draw3dText(n.m_x,text); + } +} + +// +void btSoftBodyHelpers::DrawNodeTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth, + int maxdepth) +{ + drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,maxdepth); +} + +// +void btSoftBodyHelpers::DrawFaceTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth, + int maxdepth) +{ + drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,maxdepth); +} + +// +void btSoftBodyHelpers::DrawClusterTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth, + int maxdepth) +{ + drawTree(idraw,psb->m_cdbvt.m_root,0,btVector3(0,1,1),btVector3(1,0,0),mindepth,maxdepth); +} + +// +void btSoftBodyHelpers::DrawFrame( btSoftBody* psb, + btIDebugDraw* idraw) +{ + if(psb->m_pose.m_bframe) + { + static const btScalar ascl=10; + static const btScalar nscl=(btScalar)0.1; + const btVector3 com=psb->m_pose.m_com; + const btMatrix3x3 trs=psb->m_pose.m_rot*psb->m_pose.m_scl; + const btVector3 Xaxis=(trs*btVector3(1,0,0)).normalized(); + const btVector3 Yaxis=(trs*btVector3(0,1,0)).normalized(); + const btVector3 Zaxis=(trs*btVector3(0,0,1)).normalized(); + idraw->drawLine(com,com+Xaxis*ascl,btVector3(1,0,0)); + idraw->drawLine(com,com+Yaxis*ascl,btVector3(0,1,0)); + idraw->drawLine(com,com+Zaxis*ascl,btVector3(0,0,1)); + for(int i=0;im_pose.m_pos.size();++i) + { + const btVector3 x=com+trs*psb->m_pose.m_pos[i]; + drawVertex(idraw,x,nscl,btVector3(1,0,1)); + } + } +} + +// +btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBodyWorldInfo& worldInfo, const btVector3& from, + const btVector3& to, + int res, + int fixeds) +{ + /* Create nodes */ + const int r=res+2; + btVector3* x=new btVector3[r]; + btScalar* m=new btScalar[r]; + int i; + + for(i=0;isetMass(0,0); + if(fixeds&2) psb->setMass(r-1,0); + delete[] x; + delete[] m; + /* Create links */ + for(i=1;iappendLink(i-1,i); + } + /* Finished */ + return(psb); +} + +// +btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo,const btVector3& corner00, + const btVector3& corner10, + const btVector3& corner01, + const btVector3& corner11, + int resx, + int resy, + int fixeds, + bool gendiags) +{ +#define IDX(_x_,_y_) ((_y_)*rx+(_x_)) + /* Create nodes */ + if((resx<2)||(resy<2)) return(0); + const int rx=resx; + const int ry=resy; + const int tot=rx*ry; + btVector3* x=new btVector3[tot]; + btScalar* m=new btScalar[tot]; + int iy; + + for(iy=0;iysetMass(IDX(0,0),0); + if(fixeds&2) psb->setMass(IDX(rx-1,0),0); + if(fixeds&4) psb->setMass(IDX(0,ry-1),0); + if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0); + delete[] x; + delete[] m; + /* Create links and faces */ + for(iy=0;iyappendLink(idx,IDX(ix+1,iy)); + if(mdy) psb->appendLink(idx,IDX(ix,iy+1)); + if(mdx&&mdy) + { + if((ix+iy)&1) + { + psb->appendFace(IDX(ix,iy),IDX(ix+1,iy),IDX(ix+1,iy+1)); + psb->appendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1)); + if(gendiags) + { + psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1)); + } + } + else + { + psb->appendFace(IDX(ix,iy+1),IDX(ix,iy),IDX(ix+1,iy)); + psb->appendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1)); + if(gendiags) + { + psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1)); + } + } + } + } + } + /* Finished */ +#undef IDX + return(psb); +} + +// +btSoftBody* btSoftBodyHelpers::CreatePatchUV(btSoftBodyWorldInfo& worldInfo, + const btVector3& corner00, + const btVector3& corner10, + const btVector3& corner01, + const btVector3& corner11, + int resx, + int resy, + int fixeds, + bool gendiags, + float* tex_coords) +{ + + /* + * + * corners: + * + * [0][0] corner00 ------- corner01 [resx][0] + * | | + * | | + * [0][resy] corner10 -------- corner11 [resx][resy] + * + * + * + * + * + * + * "fixedgs" map: + * + * corner00 --> +1 + * corner01 --> +2 + * corner10 --> +4 + * corner11 --> +8 + * upper middle --> +16 + * left middle --> +32 + * right middle --> +64 + * lower middle --> +128 + * center --> +256 + * + * + * tex_coords size (resx-1)*(resy-1)*12 + * + * + * + * SINGLE QUAD INTERNALS + * + * 1) btSoftBody's nodes and links, + * diagonal link is optional ("gendiags") + * + * + * node00 ------ node01 + * | . + * | . + * | . + * | . + * | . + * node10 node11 + * + * + * + * 2) Faces: + * two triangles, + * UV Coordinates (hier example for single quad) + * + * (0,1) (0,1) (1,1) + * 1 |\ 3 \-----| 2 + * | \ \ | + * | \ \ | + * | \ \ | + * | \ \ | + * 2 |-----\ 3 \| 1 + * (0,0) (1,0) (1,0) + * + * + * + * + * + * + */ + +#define IDX(_x_,_y_) ((_y_)*rx+(_x_)) + /* Create nodes */ + if((resx<2)||(resy<2)) return(0); + const int rx=resx; + const int ry=resy; + const int tot=rx*ry; + btVector3* x=new btVector3[tot]; + btScalar* m=new btScalar[tot]; + + int iy; + + for(iy=0;iysetMass(IDX(0,0),0); + if(fixeds&2) psb->setMass(IDX(rx-1,0),0); + if(fixeds&4) psb->setMass(IDX(0,ry-1),0); + if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0); + if(fixeds&16) psb->setMass(IDX((rx-1)/2,0),0); + if(fixeds&32) psb->setMass(IDX(0,(ry-1)/2),0); + if(fixeds&64) psb->setMass(IDX(rx-1,(ry-1)/2),0); + if(fixeds&128) psb->setMass(IDX((rx-1)/2,ry-1),0); + if(fixeds&256) psb->setMass(IDX((rx-1)/2,(ry-1)/2),0); + delete[] x; + delete[] m; + + + int z = 0; + /* Create links and faces */ + for(iy=0;iyappendLink(node00,node01); + if(mdy) psb->appendLink(node00,node10); + if(mdx&&mdy) + { + psb->appendFace(node00,node10,node11); + if (tex_coords) { + tex_coords[z+0]=CalculateUV(resx,resy,ix,iy,0); + tex_coords[z+1]=CalculateUV(resx,resy,ix,iy,1); + tex_coords[z+2]=CalculateUV(resx,resy,ix,iy,0); + tex_coords[z+3]=CalculateUV(resx,resy,ix,iy,2); + tex_coords[z+4]=CalculateUV(resx,resy,ix,iy,3); + tex_coords[z+5]=CalculateUV(resx,resy,ix,iy,2); + } + psb->appendFace(node11,node01,node00); + if (tex_coords) { + tex_coords[z+6 ]=CalculateUV(resx,resy,ix,iy,3); + tex_coords[z+7 ]=CalculateUV(resx,resy,ix,iy,2); + tex_coords[z+8 ]=CalculateUV(resx,resy,ix,iy,3); + tex_coords[z+9 ]=CalculateUV(resx,resy,ix,iy,1); + tex_coords[z+10]=CalculateUV(resx,resy,ix,iy,0); + tex_coords[z+11]=CalculateUV(resx,resy,ix,iy,1); + } + if (gendiags) psb->appendLink(node00,node11); + z += 12; + } + } + } + /* Finished */ +#undef IDX + return(psb); +} + +float btSoftBodyHelpers::CalculateUV(int resx,int resy,int ix,int iy,int id) +{ + + /* + * + * + * node00 --- node01 + * | | + * node10 --- node11 + * + * + * ID map: + * + * node00 s --> 0 + * node00 t --> 1 + * + * node01 s --> 3 + * node01 t --> 1 + * + * node10 s --> 0 + * node10 t --> 2 + * + * node11 s --> 3 + * node11 t --> 2 + * + * + */ + + float tc=0.0f; + if (id == 0) { + tc = (1.0f/((resx-1))*ix); + } + else if (id==1) { + tc = (1.0f/((resy-1))*(resy-1-iy)); + } + else if (id==2) { + tc = (1.0f/((resy-1))*(resy-1-iy-1)); + } + else if (id==3) { + tc = (1.0f/((resx-1))*(ix+1)); + } + return tc; +} +// +btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,const btVector3& center, + const btVector3& radius, + int res) +{ + struct Hammersley + { + static void Generate(btVector3* x,int n) + { + for(int i=0;i>=1) if(j&1) t+=p; + btScalar w=2*t-1; + btScalar a=(SIMD_PI+2*i*SIMD_PI)/n; + btScalar s=btSqrt(1-w*w); + *x++=btVector3(s*btCos(a),s*btSin(a),w); + } + } + }; + btAlignedObjectArray vtx; + vtx.resize(3+res); + Hammersley::Generate(&vtx[0],vtx.size()); + for(int i=0;i chks; + btAlignedObjectArray vtx; + chks.resize(maxidx*maxidx,false); + vtx.resize(maxidx); + for(i=0,j=0,ni=maxidx*3;iappendLink(idx[j],idx[k]); + } + } +#undef IDX + psb->appendFace(idx[0],idx[1],idx[2]); + } + + if (randomizeConstraints) + { + psb->randomizeConstraints(); + } + + return(psb); +} + +// +btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices, + int nvertices, bool randomizeConstraints) +{ + HullDesc hdsc(QF_TRIANGLES,nvertices,vertices); + HullResult hres; + HullLibrary hlib;/*??*/ + hdsc.mMaxVertices=nvertices; + hlib.CreateConvexHull(hdsc,hres); + btSoftBody* psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices, + &hres.m_OutputVertices[0],0); + for(int i=0;i<(int)hres.mNumFaces;++i) + { + const int idx[]={ hres.m_Indices[i*3+0], + hres.m_Indices[i*3+1], + hres.m_Indices[i*3+2]}; + if(idx[0]appendLink( idx[0],idx[1]); + if(idx[1]appendLink( idx[1],idx[2]); + if(idx[2]appendLink( idx[2],idx[0]); + psb->appendFace(idx[0],idx[1],idx[2]); + } + hlib.ReleaseResult(hres); + if (randomizeConstraints) + { + psb->randomizeConstraints(); + } + return(psb); +} + + + + +static int nextLine(const char* buffer) +{ + int numBytesRead=0; + + while (*buffer != '\n') + { + buffer++; + numBytesRead++; + } + + + if (buffer[0]==0x0a) + { + buffer++; + numBytesRead++; + } + return numBytesRead; +} + +/* Create from TetGen .ele, .face, .node data */ +btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(btSoftBodyWorldInfo& worldInfo, + const char* ele, + const char* face, + const char* node, + bool bfacelinks, + bool btetralinks, + bool bfacesfromtetras) +{ +btAlignedObjectArray pos; +int nnode=0; +int ndims=0; +int nattrb=0; +int hasbounds=0; +int result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds); +result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds); +node += nextLine(node); + +pos.resize(nnode); +for(int i=0;i>index; +// sn>>x;sn>>y;sn>>z; + node += nextLine(node); + + //for(int j=0;j>a; + + //if(hasbounds) + // sn>>bound; + + pos[index].setX(btScalar(x)); + pos[index].setY(btScalar(y)); + pos[index].setZ(btScalar(z)); + } +btSoftBody* psb=new btSoftBody(&worldInfo,nnode,&pos[0],0); +#if 0 +if(face&&face[0]) + { + int nface=0; + sf>>nface;sf>>hasbounds; + for(int i=0;i>index; + sf>>ni[0];sf>>ni[1];sf>>ni[2]; + sf>>bound; + psb->appendFace(ni[0],ni[1],ni[2]); + if(btetralinks) + { + psb->appendLink(ni[0],ni[1],0,true); + psb->appendLink(ni[1],ni[2],0,true); + psb->appendLink(ni[2],ni[0],0,true); + } + } + } +#endif + +if(ele&&ele[0]) + { + int ntetra=0; + int ncorner=0; + int neattrb=0; + sscanf(ele,"%d %d %d",&ntetra,&ncorner,&neattrb); + ele += nextLine(ele); + + //se>>ntetra;se>>ncorner;se>>neattrb; + for(int i=0;i>index; + //se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3]; + sscanf(ele,"%d %d %d %d %d",&index,&ni[0],&ni[1],&ni[2],&ni[3]); + ele+=nextLine(ele); + //for(int j=0;j>a; + psb->appendTetra(ni[0],ni[1],ni[2],ni[3]); + if(btetralinks) + { + psb->appendLink(ni[0],ni[1],0,true); + psb->appendLink(ni[1],ni[2],0,true); + psb->appendLink(ni[2],ni[0],0,true); + psb->appendLink(ni[0],ni[3],0,true); + psb->appendLink(ni[1],ni[3],0,true); + psb->appendLink(ni[2],ni[3],0,true); + } + } + } +printf("Nodes: %u\r\n",psb->m_nodes.size()); +printf("Links: %u\r\n",psb->m_links.size()); +printf("Faces: %u\r\n",psb->m_faces.size()); +printf("Tetras: %u\r\n",psb->m_tetras.size()); +return(psb); +} + diff --git a/src/BulletSoftBody/btSoftBodyHelpers.h b/src/BulletSoftBody/btSoftBodyHelpers.h new file mode 100644 index 0000000..620a52f --- /dev/null +++ b/src/BulletSoftBody/btSoftBodyHelpers.h @@ -0,0 +1,143 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_HELPERS_H +#define BT_SOFT_BODY_HELPERS_H + +#include "btSoftBody.h" + +// +// Helpers +// + +/* fDrawFlags */ +struct fDrawFlags { enum _ { + Nodes = 0x0001, + Links = 0x0002, + Faces = 0x0004, + Tetras = 0x0008, + Normals = 0x0010, + Contacts = 0x0020, + Anchors = 0x0040, + Notes = 0x0080, + Clusters = 0x0100, + NodeTree = 0x0200, + FaceTree = 0x0400, + ClusterTree = 0x0800, + Joints = 0x1000, + /* presets */ + Std = Links+Faces+Tetras+Anchors+Notes+Joints, + StdTetra = Std-Faces+Tetras +};}; + +struct btSoftBodyHelpers +{ + /* Draw body */ + static void Draw( btSoftBody* psb, + btIDebugDraw* idraw, + int drawflags=fDrawFlags::Std); + /* Draw body infos */ + static void DrawInfos( btSoftBody* psb, + btIDebugDraw* idraw, + bool masses, + bool areas, + bool stress); + /* Draw node tree */ + static void DrawNodeTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth=0, + int maxdepth=-1); + /* Draw face tree */ + static void DrawFaceTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth=0, + int maxdepth=-1); + /* Draw cluster tree */ + static void DrawClusterTree(btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth=0, + int maxdepth=-1); + /* Draw rigid frame */ + static void DrawFrame( btSoftBody* psb, + btIDebugDraw* idraw); + /* Create a rope */ + static btSoftBody* CreateRope( btSoftBodyWorldInfo& worldInfo, + const btVector3& from, + const btVector3& to, + int res, + int fixeds); + /* Create a patch */ + static btSoftBody* CreatePatch(btSoftBodyWorldInfo& worldInfo, + const btVector3& corner00, + const btVector3& corner10, + const btVector3& corner01, + const btVector3& corner11, + int resx, + int resy, + int fixeds, + bool gendiags); + /* Create a patch with UV Texture Coordinates */ + static btSoftBody* CreatePatchUV(btSoftBodyWorldInfo& worldInfo, + const btVector3& corner00, + const btVector3& corner10, + const btVector3& corner01, + const btVector3& corner11, + int resx, + int resy, + int fixeds, + bool gendiags, + float* tex_coords=0); + static float CalculateUV(int resx,int resy,int ix,int iy,int id); + /* Create an ellipsoid */ + static btSoftBody* CreateEllipsoid(btSoftBodyWorldInfo& worldInfo, + const btVector3& center, + const btVector3& radius, + int res); + /* Create from trimesh */ + static btSoftBody* CreateFromTriMesh( btSoftBodyWorldInfo& worldInfo, + const btScalar* vertices, + const int* triangles, + int ntriangles, + bool randomizeConstraints = true); + /* Create from convex-hull */ + static btSoftBody* CreateFromConvexHull( btSoftBodyWorldInfo& worldInfo, + const btVector3* vertices, + int nvertices, + bool randomizeConstraints = true); + + + /* Export TetGen compatible .smesh file */ +// static void ExportAsSMeshFile( btSoftBody* psb, +// const char* filename); + /* Create from TetGen .ele, .face, .node files */ +// static btSoftBody* CreateFromTetGenFile( btSoftBodyWorldInfo& worldInfo, +// const char* ele, +// const char* face, +// const char* node, +// bool bfacelinks, +// bool btetralinks, +// bool bfacesfromtetras); + /* Create from TetGen .ele, .face, .node data */ + static btSoftBody* CreateFromTetGenData( btSoftBodyWorldInfo& worldInfo, + const char* ele, + const char* face, + const char* node, + bool bfacelinks, + bool btetralinks, + bool bfacesfromtetras); + +}; + +#endif //BT_SOFT_BODY_HELPERS_H diff --git a/src/BulletSoftBody/btSoftBodyInternals.h b/src/BulletSoftBody/btSoftBodyInternals.h new file mode 100644 index 0000000..5ef8db1 --- /dev/null +++ b/src/BulletSoftBody/btSoftBodyInternals.h @@ -0,0 +1,930 @@ +/* +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. +*/ +///btSoftBody implementation by Nathanael Presson + +#ifndef _BT_SOFT_BODY_INTERNALS_H +#define _BT_SOFT_BODY_INTERNALS_H + +#include "btSoftBody.h" + + +#include "LinearMath/btQuickprof.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btConvexInternalShape.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" +#include //for memset +// +// btSymMatrix +// +template +struct btSymMatrix +{ + btSymMatrix() : dim(0) {} + btSymMatrix(int n,const T& init=T()) { resize(n,init); } + void resize(int n,const T& init=T()) { dim=n;store.resize((n*(n+1))/2,init); } + int index(int c,int r) const { if(c>r) btSwap(c,r);btAssert(r store; + int dim; +}; + +// +// btSoftBodyCollisionShape +// +class btSoftBodyCollisionShape : public btConcaveShape +{ +public: + btSoftBody* m_body; + + btSoftBodyCollisionShape(btSoftBody* backptr) + { + m_shapeType = SOFTBODY_SHAPE_PROXYTYPE; + m_body=backptr; + } + + virtual ~btSoftBodyCollisionShape() + { + + } + + void processAllTriangles(btTriangleCallback* /*callback*/,const btVector3& /*aabbMin*/,const btVector3& /*aabbMax*/) const + { + //not yet + btAssert(0); + } + + ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t. + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + /* t is usually identity, except when colliding against btCompoundShape. See Issue 512 */ + const btVector3 mins=m_body->m_bounds[0]; + const btVector3 maxs=m_body->m_bounds[1]; + const btVector3 crns[]={t*btVector3(mins.x(),mins.y(),mins.z()), + t*btVector3(maxs.x(),mins.y(),mins.z()), + t*btVector3(maxs.x(),maxs.y(),mins.z()), + t*btVector3(mins.x(),maxs.y(),mins.z()), + t*btVector3(mins.x(),mins.y(),maxs.z()), + t*btVector3(maxs.x(),mins.y(),maxs.z()), + t*btVector3(maxs.x(),maxs.y(),maxs.z()), + t*btVector3(mins.x(),maxs.y(),maxs.z())}; + aabbMin=aabbMax=crns[0]; + for(int i=1;i<8;++i) + { + aabbMin.setMin(crns[i]); + aabbMax.setMax(crns[i]); + } + } + + + virtual void setLocalScaling(const btVector3& /*scaling*/) + { + ///na + } + virtual const btVector3& getLocalScaling() const + { + static const btVector3 dummy(1,1,1); + return dummy; + } + virtual void calculateLocalInertia(btScalar /*mass*/,btVector3& /*inertia*/) const + { + ///not yet + btAssert(0); + } + virtual const char* getName()const + { + return "SoftBody"; + } + +}; + +// +// btSoftClusterCollisionShape +// +class btSoftClusterCollisionShape : public btConvexInternalShape +{ +public: + const btSoftBody::Cluster* m_cluster; + + btSoftClusterCollisionShape (const btSoftBody::Cluster* cluster) : m_cluster(cluster) { setMargin(0); } + + + virtual btVector3 localGetSupportingVertex(const btVector3& vec) const + { + btSoftBody::Node* const * n=&m_cluster->m_nodes[0]; + btScalar d=btDot(vec,n[0]->m_x); + int j=0; + for(int i=1,ni=m_cluster->m_nodes.size();im_x); + if(k>d) { d=k;j=i; } + } + return(n[j]->m_x); + } + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const + { + return(localGetSupportingVertex(vec)); + } + //notice that the vectors should be unit length + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const + {} + + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const + {} + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + {} + + virtual int getShapeType() const { return SOFTBODY_SHAPE_PROXYTYPE; } + + //debugging + virtual const char* getName()const {return "SOFTCLUSTER";} + + virtual void setMargin(btScalar margin) + { + btConvexInternalShape::setMargin(margin); + } + virtual btScalar getMargin() const + { + return getMargin(); + } +}; + +// +// Inline's +// + +// +template +static inline void ZeroInitialize(T& value) +{ + memset(&value,0,sizeof(T)); +} +// +template +static inline bool CompLess(const T& a,const T& b) +{ return(a +static inline bool CompGreater(const T& a,const T& b) +{ return(a>b); } +// +template +static inline T Lerp(const T& a,const T& b,btScalar t) +{ return(a+(b-a)*t); } +// +template +static inline T InvLerp(const T& a,const T& b,btScalar t) +{ return((b+a*t-b*t)/(a*b)); } +// +static inline btMatrix3x3 Lerp( const btMatrix3x3& a, + const btMatrix3x3& b, + btScalar t) +{ + btMatrix3x3 r; + r[0]=Lerp(a[0],b[0],t); + r[1]=Lerp(a[1],b[1],t); + r[2]=Lerp(a[2],b[2],t); + return(r); +} +// +static inline btVector3 Clamp(const btVector3& v,btScalar maxlength) +{ + const btScalar sql=v.length2(); + if(sql>(maxlength*maxlength)) + return((v*maxlength)/btSqrt(sql)); + else + return(v); +} +// +template +static inline T Clamp(const T& x,const T& l,const T& h) +{ return(xh?h:x); } +// +template +static inline T Sq(const T& x) +{ return(x*x); } +// +template +static inline T Cube(const T& x) +{ return(x*x*x); } +// +template +static inline T Sign(const T& x) +{ return((T)(x<0?-1:+1)); } +// +template +static inline bool SameSign(const T& x,const T& y) +{ return((x*y)>0); } +// +static inline btScalar ClusterMetric(const btVector3& x,const btVector3& y) +{ + const btVector3 d=x-y; + return(btFabs(d[0])+btFabs(d[1])+btFabs(d[2])); +} +// +static inline btMatrix3x3 ScaleAlongAxis(const btVector3& a,btScalar s) +{ + const btScalar xx=a.x()*a.x(); + const btScalar yy=a.y()*a.y(); + const btScalar zz=a.z()*a.z(); + const btScalar xy=a.x()*a.y(); + const btScalar yz=a.y()*a.z(); + const btScalar zx=a.z()*a.x(); + btMatrix3x3 m; + m[0]=btVector3(1-xx+xx*s,xy*s-xy,zx*s-zx); + m[1]=btVector3(xy*s-xy,1-yy+yy*s,yz*s-yz); + m[2]=btVector3(zx*s-zx,yz*s-yz,1-zz+zz*s); + return(m); +} +// +static inline btMatrix3x3 Cross(const btVector3& v) +{ + btMatrix3x3 m; + m[0]=btVector3(0,-v.z(),+v.y()); + m[1]=btVector3(+v.z(),0,-v.x()); + m[2]=btVector3(-v.y(),+v.x(),0); + return(m); +} +// +static inline btMatrix3x3 Diagonal(btScalar x) +{ + btMatrix3x3 m; + m[0]=btVector3(x,0,0); + m[1]=btVector3(0,x,0); + m[2]=btVector3(0,0,x); + return(m); +} +// +static inline btMatrix3x3 Add(const btMatrix3x3& a, + const btMatrix3x3& b) +{ + btMatrix3x3 r; + for(int i=0;i<3;++i) r[i]=a[i]+b[i]; + return(r); +} +// +static inline btMatrix3x3 Sub(const btMatrix3x3& a, + const btMatrix3x3& b) +{ + btMatrix3x3 r; + for(int i=0;i<3;++i) r[i]=a[i]-b[i]; + return(r); +} +// +static inline btMatrix3x3 Mul(const btMatrix3x3& a, + btScalar b) +{ + btMatrix3x3 r; + for(int i=0;i<3;++i) r[i]=a[i]*b; + return(r); +} +// +static inline void Orthogonalize(btMatrix3x3& m) +{ + m[2]=btCross(m[0],m[1]).normalized(); + m[1]=btCross(m[2],m[0]).normalized(); + m[0]=btCross(m[1],m[2]).normalized(); +} +// +static inline btMatrix3x3 MassMatrix(btScalar im,const btMatrix3x3& iwi,const btVector3& r) +{ + const btMatrix3x3 cr=Cross(r); + return(Sub(Diagonal(im),cr*iwi*cr)); +} + +// +static inline btMatrix3x3 ImpulseMatrix( btScalar dt, + btScalar ima, + btScalar imb, + const btMatrix3x3& iwi, + const btVector3& r) +{ + return(Diagonal(1/dt)*Add(Diagonal(ima),MassMatrix(imb,iwi,r)).inverse()); +} + +// +static inline btMatrix3x3 ImpulseMatrix( btScalar ima,const btMatrix3x3& iia,const btVector3& ra, + btScalar imb,const btMatrix3x3& iib,const btVector3& rb) +{ + return(Add(MassMatrix(ima,iia,ra),MassMatrix(imb,iib,rb)).inverse()); +} + +// +static inline btMatrix3x3 AngularImpulseMatrix( const btMatrix3x3& iia, + const btMatrix3x3& iib) +{ + return(Add(iia,iib).inverse()); +} + +// +static inline btVector3 ProjectOnAxis( const btVector3& v, + const btVector3& a) +{ + return(a*btDot(v,a)); +} +// +static inline btVector3 ProjectOnPlane( const btVector3& v, + const btVector3& a) +{ + return(v-ProjectOnAxis(v,a)); +} + +// +static inline void ProjectOrigin( const btVector3& a, + const btVector3& b, + btVector3& prj, + btScalar& sqd) +{ + const btVector3 d=b-a; + const btScalar m2=d.length2(); + if(m2>SIMD_EPSILON) + { + const btScalar t=Clamp(-btDot(a,d)/m2,0,1); + const btVector3 p=a+d*t; + const btScalar l2=p.length2(); + if(l2SIMD_EPSILON) + { + const btVector3 n=q/btSqrt(m2); + const btScalar k=btDot(a,n); + const btScalar k2=k*k; + if(k20)&& + (btDot(btCross(b-p,c-p),q)>0)&& + (btDot(btCross(c-p,a-p),q)>0)) + { + prj=p; + sqd=k2; + } + else + { + ProjectOrigin(a,b,prj,sqd); + ProjectOrigin(b,c,prj,sqd); + ProjectOrigin(c,a,prj,sqd); + } + } + } +} + +// +template +static inline T BaryEval( const T& a, + const T& b, + const T& c, + const btVector3& coord) +{ + return(a*coord.x()+b*coord.y()+c*coord.z()); +} +// +static inline btVector3 BaryCoord( const btVector3& a, + const btVector3& b, + const btVector3& c, + const btVector3& p) +{ + const btScalar w[]={ btCross(a-p,b-p).length(), + btCross(b-p,c-p).length(), + btCross(c-p,a-p).length()}; + const btScalar isum=1/(w[0]+w[1]+w[2]); + return(btVector3(w[1]*isum,w[2]*isum,w[0]*isum)); +} + +// +static btScalar ImplicitSolve( btSoftBody::ImplicitFn* fn, + const btVector3& a, + const btVector3& b, + const btScalar accuracy, + const int maxiterations=256) +{ + btScalar span[2]={0,1}; + btScalar values[2]={fn->Eval(a),fn->Eval(b)}; + if(values[0]>values[1]) + { + btSwap(span[0],span[1]); + btSwap(values[0],values[1]); + } + if(values[0]>-accuracy) return(-1); + if(values[1]<+accuracy) return(-1); + for(int i=0;iEval(Lerp(a,b,t)); + if((t<=0)||(t>=1)) break; + if(btFabs(v)SIMD_EPSILON) + return(v/l); + else + return(btVector3(0,0,0)); +} + +// +static inline btDbvtVolume VolumeOf( const btSoftBody::Face& f, + btScalar margin) +{ + const btVector3* pts[]={ &f.m_n[0]->m_x, + &f.m_n[1]->m_x, + &f.m_n[2]->m_x}; + btDbvtVolume vol=btDbvtVolume::FromPoints(pts,3); + vol.Expand(btVector3(margin,margin,margin)); + return(vol); +} + +// +static inline btVector3 CenterOf( const btSoftBody::Face& f) +{ + return((f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3); +} + +// +static inline btScalar AreaOf( const btVector3& x0, + const btVector3& x1, + const btVector3& x2) +{ + const btVector3 a=x1-x0; + const btVector3 b=x2-x0; + const btVector3 cr=btCross(a,b); + const btScalar area=cr.length(); + return(area); +} + +// +static inline btScalar VolumeOf( const btVector3& x0, + const btVector3& x1, + const btVector3& x2, + const btVector3& x3) +{ + const btVector3 a=x1-x0; + const btVector3 b=x2-x0; + const btVector3 c=x3-x0; + return(btDot(a,btCross(b,c))); +} + +// +static void EvaluateMedium( const btSoftBodyWorldInfo* wfi, + const btVector3& x, + btSoftBody::sMedium& medium) +{ + medium.m_velocity = btVector3(0,0,0); + medium.m_pressure = 0; + medium.m_density = wfi->air_density; + if(wfi->water_density>0) + { + const btScalar depth=-(btDot(x,wfi->water_normal)+wfi->water_offset); + if(depth>0) + { + medium.m_density = wfi->water_density; + medium.m_pressure = depth*wfi->water_density*wfi->m_gravity.length(); + } + } +} + +// +static inline void ApplyClampedForce( btSoftBody::Node& n, + const btVector3& f, + btScalar dt) +{ + const btScalar dtim=dt*n.m_im; + if((f*dtim).length2()>n.m_v.length2()) + {/* Clamp */ + n.m_f-=ProjectOnAxis(n.m_v,f.normalized())/dtim; + } + else + {/* Apply */ + n.m_f+=f; + } +} + +// +static inline int MatchEdge( const btSoftBody::Node* a, + const btSoftBody::Node* b, + const btSoftBody::Node* ma, + const btSoftBody::Node* mb) +{ + if((a==ma)&&(b==mb)) return(0); + if((a==mb)&&(b==ma)) return(1); + return(-1); +} + +// +// btEigen : Extract eigen system, +// straitforward implementation of http://math.fullerton.edu/mathews/n2003/JacobiMethodMod.html +// outputs are NOT sorted. +// +struct btEigen +{ + static int system(btMatrix3x3& a,btMatrix3x3* vectors,btVector3* values=0) + { + static const int maxiterations=16; + static const btScalar accuracy=(btScalar)0.0001; + btMatrix3x3& v=*vectors; + int iterations=0; + vectors->setIdentity(); + do { + int p=0,q=1; + if(btFabs(a[p][q])accuracy) + { + const btScalar w=(a[q][q]-a[p][p])/(2*a[p][q]); + const btScalar z=btFabs(w); + const btScalar t=w/(z*(btSqrt(1+w*w)+z)); + if(t==t)/* [WARNING] let hope that one does not get thrown aways by some compilers... */ + { + const btScalar c=1/btSqrt(t*t+1); + const btScalar s=c*t; + mulPQ(a,c,s,p,q); + mulTPQ(a,c,s,p,q); + mulPQ(v,c,s,p,q); + } else break; + } else break; + } while((++iterations)accuracy) det=ndet; else break; + } + /* Final orthogonalization */ + Orthogonalize(q); + /* Compute 'S' */ + s=q.transpose()*m; + } + else + { + q.setIdentity(); + s.setIdentity(); + } + return(i); +} + +// +// btSoftColliders +// +struct btSoftColliders +{ + // + // ClusterBase + // + struct ClusterBase : btDbvt::ICollide + { + btScalar erp; + btScalar idt; + btScalar m_margin; + btScalar friction; + btScalar threshold; + ClusterBase() + { + erp =(btScalar)1; + idt =0; + m_margin =0; + friction =0; + threshold =(btScalar)0; + } + bool SolveContact( const btGjkEpaSolver2::sResults& res, + btSoftBody::Body ba,btSoftBody::Body bb, + btSoftBody::CJoint& joint) + { + if(res.distancedata; + btSoftClusterCollisionShape cshape(cluster); + + const btConvexShape* rshape=(const btConvexShape*)m_colObj->getCollisionShape(); + + ///don't collide an anchored cluster with a static/kinematic object + if(m_colObj->isStaticOrKinematicObject() && cluster->m_containsAnchor) + return; + + btGjkEpaSolver2::sResults res; + if(btGjkEpaSolver2::SignedDistance( &cshape,btTransform::getIdentity(), + rshape,m_colObj->getWorldTransform(), + btVector3(1,0,0),res)) + { + btSoftBody::CJoint joint; + if(SolveContact(res,cluster,m_colObj,joint))//prb,joint)) + { + btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint(); + *pj=joint;psb->m_joints.push_back(pj); + if(m_colObj->isStaticOrKinematicObject()) + { + pj->m_erp *= psb->m_cfg.kSKHR_CL; + pj->m_split *= psb->m_cfg.kSK_SPLT_CL; + } + else + { + pj->m_erp *= psb->m_cfg.kSRHR_CL; + pj->m_split *= psb->m_cfg.kSR_SPLT_CL; + } + } + } + } + void Process(btSoftBody* ps,btCollisionObject* colOb) + { + psb = ps; + m_colObj = colOb; + idt = ps->m_sst.isdt; + m_margin = m_colObj->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin(); + ///Bullet rigid body uses multiply instead of minimum to determine combined friction. Some customization would be useful. + friction = btMin(psb->m_cfg.kDF,m_colObj->getFriction()); + btVector3 mins; + btVector3 maxs; + + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume; + colOb->getCollisionShape()->getAabb(colOb->getWorldTransform(),mins,maxs); + volume=btDbvtVolume::FromMM(mins,maxs); + volume.Expand(btVector3(1,1,1)*m_margin); + ps->m_cdbvt.collideTV(ps->m_cdbvt.m_root,volume,*this); + } + }; + // + // CollideCL_SS + // + struct CollideCL_SS : ClusterBase + { + btSoftBody* bodies[2]; + void Process(const btDbvtNode* la,const btDbvtNode* lb) + { + btSoftBody::Cluster* cla=(btSoftBody::Cluster*)la->data; + btSoftBody::Cluster* clb=(btSoftBody::Cluster*)lb->data; + + + bool connected=false; + if ((bodies[0]==bodies[1])&&(bodies[0]->m_clusterConnectivity.size())) + { + connected = bodies[0]->m_clusterConnectivity[cla->m_clusterIndex+bodies[0]->m_clusters.size()*clb->m_clusterIndex]; + } + + if (!connected) + { + btSoftClusterCollisionShape csa(cla); + btSoftClusterCollisionShape csb(clb); + btGjkEpaSolver2::sResults res; + if(btGjkEpaSolver2::SignedDistance( &csa,btTransform::getIdentity(), + &csb,btTransform::getIdentity(), + cla->m_com-clb->m_com,res)) + { + btSoftBody::CJoint joint; + if(SolveContact(res,cla,clb,joint)) + { + btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint(); + *pj=joint;bodies[0]->m_joints.push_back(pj); + pj->m_erp *= btMax(bodies[0]->m_cfg.kSSHR_CL,bodies[1]->m_cfg.kSSHR_CL); + pj->m_split *= (bodies[0]->m_cfg.kSS_SPLT_CL+bodies[1]->m_cfg.kSS_SPLT_CL)/2; + } + } + } else + { + static int count=0; + count++; + //printf("count=%d\n",count); + + } + } + void Process(btSoftBody* psa,btSoftBody* psb) + { + idt = psa->m_sst.isdt; + //m_margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin())/2; + m_margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin()); + friction = btMin(psa->m_cfg.kDF,psb->m_cfg.kDF); + bodies[0] = psa; + bodies[1] = psb; + psa->m_cdbvt.collideTT(psa->m_cdbvt.m_root,psb->m_cdbvt.m_root,*this); + } + }; + // + // CollideSDF_RS + // + struct CollideSDF_RS : btDbvt::ICollide + { + void Process(const btDbvtNode* leaf) + { + btSoftBody::Node* node=(btSoftBody::Node*)leaf->data; + DoNode(*node); + } + void DoNode(btSoftBody::Node& n) const + { + const btScalar m=n.m_im>0?dynmargin:stamargin; + btSoftBody::RContact c; + if( (!n.m_battach)&& + psb->checkContact(m_colObj1,n.m_x,m,c.m_cti)) + { + const btScalar ima=n.m_im; + const btScalar imb= m_rigidBody? m_rigidBody->getInvMass() : 0.f; + const btScalar ms=ima+imb; + if(ms>0) + { + const btTransform& wtr=m_rigidBody?m_rigidBody->getWorldTransform() : m_colObj1->getWorldTransform(); + static const btMatrix3x3 iwiStatic(0,0,0,0,0,0,0,0,0); + const btMatrix3x3& iwi=m_rigidBody?m_rigidBody->getInvInertiaTensorWorld() : iwiStatic; + const btVector3 ra=n.m_x-wtr.getOrigin(); + const btVector3 va=m_rigidBody ? m_rigidBody->getVelocityInLocalPoint(ra)*psb->m_sst.sdt : btVector3(0,0,0); + const btVector3 vb=n.m_x-n.m_q; + const btVector3 vr=vb-va; + const btScalar dn=btDot(vr,c.m_cti.m_normal); + const btVector3 fv=vr-c.m_cti.m_normal*dn; + const btScalar fc=psb->m_cfg.kDF*m_colObj1->getFriction(); + c.m_node = &n; + c.m_c0 = ImpulseMatrix(psb->m_sst.sdt,ima,imb,iwi,ra); + c.m_c1 = ra; + c.m_c2 = ima*psb->m_sst.sdt; + c.m_c3 = fv.length2()<(btFabs(dn)*fc)?0:1-fc; + c.m_c4 = m_colObj1->isStaticOrKinematicObject()?psb->m_cfg.kKHR:psb->m_cfg.kCHR; + psb->m_rcontacts.push_back(c); + if (m_rigidBody) + m_rigidBody->activate(); + } + } + } + btSoftBody* psb; + btCollisionObject* m_colObj1; + btRigidBody* m_rigidBody; + btScalar dynmargin; + btScalar stamargin; + }; + // + // CollideVF_SS + // + struct CollideVF_SS : btDbvt::ICollide + { + void Process(const btDbvtNode* lnode, + const btDbvtNode* lface) + { + btSoftBody::Node* node=(btSoftBody::Node*)lnode->data; + btSoftBody::Face* face=(btSoftBody::Face*)lface->data; + btVector3 o=node->m_x; + btVector3 p; + btScalar d=SIMD_INFINITY; + ProjectOrigin( face->m_n[0]->m_x-o, + face->m_n[1]->m_x-o, + face->m_n[2]->m_x-o, + p,d); + const btScalar m=mrg+(o-node->m_q).length()*2; + if(d<(m*m)) + { + const btSoftBody::Node* n[]={face->m_n[0],face->m_n[1],face->m_n[2]}; + const btVector3 w=BaryCoord(n[0]->m_x,n[1]->m_x,n[2]->m_x,p+o); + const btScalar ma=node->m_im; + btScalar mb=BaryEval(n[0]->m_im,n[1]->m_im,n[2]->m_im,w); + if( (n[0]->m_im<=0)|| + (n[1]->m_im<=0)|| + (n[2]->m_im<=0)) + { + mb=0; + } + const btScalar ms=ma+mb; + if(ms>0) + { + btSoftBody::SContact c; + c.m_normal = p/-btSqrt(d); + c.m_margin = m; + c.m_node = node; + c.m_face = face; + c.m_weights = w; + c.m_friction = btMax(psb[0]->m_cfg.kDF,psb[1]->m_cfg.kDF); + c.m_cfm[0] = ma/ms*psb[0]->m_cfg.kSHR; + c.m_cfm[1] = mb/ms*psb[1]->m_cfg.kSHR; + psb[0]->m_scontacts.push_back(c); + } + } + } + btSoftBody* psb[2]; + btScalar mrg; + }; +}; + +#endif //_BT_SOFT_BODY_INTERNALS_H diff --git a/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp b/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp new file mode 100644 index 0000000..f5a67f6 --- /dev/null +++ b/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp @@ -0,0 +1,134 @@ +/* +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 "btSoftBodyRigidBodyCollisionConfiguration.h" +#include "btSoftRigidCollisionAlgorithm.h" +#include "btSoftBodyConcaveCollisionAlgorithm.h" +#include "btSoftSoftCollisionAlgorithm.h" + +#include "LinearMath/btPoolAllocator.h" + +#define ENABLE_SOFTBODY_CONCAVE_COLLISIONS 1 + +btSoftBodyRigidBodyCollisionConfiguration::btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo) +:btDefaultCollisionConfiguration(constructionInfo) +{ + void* mem; + + mem = btAlignedAlloc(sizeof(btSoftSoftCollisionAlgorithm::CreateFunc),16); + m_softSoftCreateFunc = new(mem) btSoftSoftCollisionAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16); + m_softRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16); + m_swappedSoftRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc; + m_swappedSoftRigidConvexCreateFunc->m_swapped=true; + +#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS + mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16); + m_softRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16); + m_swappedSoftRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::SwappedCreateFunc; + m_swappedSoftRigidConcaveCreateFunc->m_swapped=true; +#endif + + //replace pool by a new one, with potential larger size + + if (m_ownsCollisionAlgorithmPool && m_collisionAlgorithmPool) + { + int curElemSize = m_collisionAlgorithmPool->getElementSize(); + ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool + + + int maxSize0 = sizeof(btSoftSoftCollisionAlgorithm); + int maxSize1 = sizeof(btSoftRigidCollisionAlgorithm); + int maxSize2 = sizeof(btSoftBodyConcaveCollisionAlgorithm); + + int collisionAlgorithmMaxElementSize = btMax(maxSize0,maxSize1); + collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2); + + if (collisionAlgorithmMaxElementSize > curElemSize) + { + m_collisionAlgorithmPool->~btPoolAllocator(); + btAlignedFree(m_collisionAlgorithmPool); + void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); + m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize); + } + } + +} + +btSoftBodyRigidBodyCollisionConfiguration::~btSoftBodyRigidBodyCollisionConfiguration() +{ + m_softSoftCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_softSoftCreateFunc); + + m_softRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_softRigidConvexCreateFunc); + + m_swappedSoftRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedSoftRigidConvexCreateFunc); + +#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS + m_softRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_softRigidConcaveCreateFunc); + + m_swappedSoftRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedSoftRigidConcaveCreateFunc); +#endif +} + +///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation +btCollisionAlgorithmCreateFunc* btSoftBodyRigidBodyCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) +{ + + ///try to handle the softbody interactions first + + if ((proxyType0 == SOFTBODY_SHAPE_PROXYTYPE ) && (proxyType1==SOFTBODY_SHAPE_PROXYTYPE)) + { + return m_softSoftCreateFunc; + } + + ///softbody versus convex + if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConvex(proxyType1)) + { + return m_softRigidConvexCreateFunc; + } + + ///convex versus soft body + if (btBroadphaseProxy::isConvex(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE ) + { + return m_swappedSoftRigidConvexCreateFunc; + } + +#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS + ///softbody versus convex + if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConcave(proxyType1)) + { + return m_softRigidConcaveCreateFunc; + } + + ///convex versus soft body + if (btBroadphaseProxy::isConcave(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE ) + { + return m_swappedSoftRigidConcaveCreateFunc; + } +#endif + + ///fallback to the regular rigid collision shape + return btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0,proxyType1); +} diff --git a/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h b/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h new file mode 100644 index 0000000..21addcf --- /dev/null +++ b/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h @@ -0,0 +1,48 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION +#define BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION + +#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h" + +class btVoronoiSimplexSolver; +class btGjkEpaPenetrationDepthSolver; + + +///btSoftBodyRigidBodyCollisionConfiguration add softbody interaction on top of btDefaultCollisionConfiguration +class btSoftBodyRigidBodyCollisionConfiguration : public btDefaultCollisionConfiguration +{ + + //default CreationFunctions, filling the m_doubleDispatch table + btCollisionAlgorithmCreateFunc* m_softSoftCreateFunc; + btCollisionAlgorithmCreateFunc* m_softRigidConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_softRigidConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConcaveCreateFunc; + +public: + + btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo()); + + virtual ~btSoftBodyRigidBodyCollisionConfiguration(); + + ///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation + virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); + +}; + +#endif //BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION + diff --git a/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h b/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h new file mode 100644 index 0000000..c4733d6 --- /dev/null +++ b/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h @@ -0,0 +1,165 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H +#define BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H + + +class btVertexBufferDescriptor +{ +public: + enum BufferTypes + { + CPU_BUFFER, + DX11_BUFFER, + OPENGL_BUFFER + }; + +protected: + + bool m_hasVertexPositions; + bool m_hasNormals; + + int m_vertexOffset; + int m_vertexStride; + + int m_normalOffset; + int m_normalStride; + +public: + btVertexBufferDescriptor() + { + m_hasVertexPositions = false; + m_hasNormals = false; + m_vertexOffset = 0; + m_vertexStride = 0; + m_normalOffset = 0; + m_normalStride = 0; + } + + virtual ~btVertexBufferDescriptor() + { + + } + + virtual bool hasVertexPositions() const + { + return m_hasVertexPositions; + } + + virtual bool hasNormals() const + { + return m_hasNormals; + } + + /** + * Return the type of the vertex buffer descriptor. + */ + virtual BufferTypes getBufferType() const = 0; + + /** + * Return the vertex offset in floats from the base pointer. + */ + virtual int getVertexOffset() const + { + return m_vertexOffset; + } + + /** + * Return the vertex stride in number of floats between vertices. + */ + virtual int getVertexStride() const + { + return m_vertexStride; + } + + /** + * Return the vertex offset in floats from the base pointer. + */ + virtual int getNormalOffset() const + { + return m_normalOffset; + } + + /** + * Return the vertex stride in number of floats between vertices. + */ + virtual int getNormalStride() const + { + return m_normalStride; + } +}; + + +class btCPUVertexBufferDescriptor : public btVertexBufferDescriptor +{ +protected: + float *m_basePointer; + +public: + /** + * vertexBasePointer is pointer to beginning of the buffer. + * vertexOffset is the offset in floats to the first vertex. + * vertexStride is the stride in floats between vertices. + */ + btCPUVertexBufferDescriptor( float *basePointer, int vertexOffset, int vertexStride ) + { + m_basePointer = basePointer; + m_vertexOffset = vertexOffset; + m_vertexStride = vertexStride; + m_hasVertexPositions = true; + } + + /** + * vertexBasePointer is pointer to beginning of the buffer. + * vertexOffset is the offset in floats to the first vertex. + * vertexStride is the stride in floats between vertices. + */ + btCPUVertexBufferDescriptor( float *basePointer, int vertexOffset, int vertexStride, int normalOffset, int normalStride ) + { + m_basePointer = basePointer; + + m_vertexOffset = vertexOffset; + m_vertexStride = vertexStride; + m_hasVertexPositions = true; + + m_normalOffset = normalOffset; + m_normalStride = normalStride; + m_hasNormals = true; + } + + virtual ~btCPUVertexBufferDescriptor() + { + + } + + /** + * Return the type of the vertex buffer descriptor. + */ + virtual BufferTypes getBufferType() const + { + return CPU_BUFFER; + } + + /** + * Return the base pointer in memory to the first vertex. + */ + virtual float *getBasePointer() const + { + return m_basePointer; + } +}; + +#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H diff --git a/src/BulletSoftBody/btSoftBodySolvers.h b/src/BulletSoftBody/btSoftBodySolvers.h new file mode 100644 index 0000000..824b7e9 --- /dev/null +++ b/src/BulletSoftBody/btSoftBodySolvers.h @@ -0,0 +1,154 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVERS_H +#define BT_SOFT_BODY_SOLVERS_H + +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" + + +class btSoftBodyTriangleData; +class btSoftBodyLinkData; +class btSoftBodyVertexData; +class btVertexBufferDescriptor; +class btCollisionObject; +class btSoftBody; + + +class btSoftBodySolver +{ +public: + enum SolverTypes + { + DEFAULT_SOLVER, + CPU_SOLVER, + CL_SOLVER, + CL_SIMD_SOLVER, + DX_SOLVER, + DX_SIMD_SOLVER + }; + + +protected: + int m_numberOfPositionIterations; + int m_numberOfVelocityIterations; + // Simulation timescale + float m_timeScale; + +public: + btSoftBodySolver() : + m_numberOfPositionIterations( 10 ), + m_timeScale( 1 ) + { + m_numberOfVelocityIterations = 0; + m_numberOfPositionIterations = 5; + } + + virtual ~btSoftBodySolver() + { + } + + /** + * Return the type of the solver. + */ + virtual SolverTypes getSolverType() const = 0; + + + /** Ensure that this solver is initialized. */ + virtual bool checkInitialized() = 0; + + /** Optimize soft bodies in this solver. */ + virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false) = 0; + + /** Copy necessary data back to the original soft body source objects. */ + virtual void copyBackToSoftBodies(bool bMove = true) = 0; + + /** Predict motion of soft bodies into next timestep */ + virtual void predictMotion( float solverdt ) = 0; + + /** Solve constraints for a set of soft bodies */ + virtual void solveConstraints( float solverdt ) = 0; + + /** Perform necessary per-step updates of soft bodies such as recomputing normals and bounding boxes */ + virtual void updateSoftBodies() = 0; + + /** Process a collision between one of the world's soft bodies and another collision object */ + virtual void processCollision( btSoftBody *, btCollisionObject* ) = 0; + + /** Process a collision between two soft bodies */ + virtual void processCollision( btSoftBody*, btSoftBody* ) = 0; + + /** Set the number of velocity constraint solver iterations this solver uses. */ + virtual void setNumberOfPositionIterations( int iterations ) + { + m_numberOfPositionIterations = iterations; + } + + /** Get the number of velocity constraint solver iterations this solver uses. */ + virtual int getNumberOfPositionIterations() + { + return m_numberOfPositionIterations; + } + + /** Set the number of velocity constraint solver iterations this solver uses. */ + virtual void setNumberOfVelocityIterations( int iterations ) + { + m_numberOfVelocityIterations = iterations; + } + + /** Get the number of velocity constraint solver iterations this solver uses. */ + virtual int getNumberOfVelocityIterations() + { + return m_numberOfVelocityIterations; + } + + /** Return the timescale that the simulation is using */ + float getTimeScale() + { + return m_timeScale; + } + +#if 0 + /** + * Add a collision object to be used by the indicated softbody. + */ + virtual void addCollisionObjectForSoftBody( int clothIdentifier, btCollisionObject *collisionObject ) = 0; +#endif +}; + +/** + * Class to manage movement of data from a solver to a given target. + * This version is abstract. Subclasses will have custom pairings for different combinations. + */ +class btSoftBodySolverOutput +{ +protected: + +public: + btSoftBodySolverOutput() + { + } + + virtual ~btSoftBodySolverOutput() + { + } + + + /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */ + virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) = 0; +}; + + +#endif // #ifndef BT_SOFT_BODY_SOLVERS_H diff --git a/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp b/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp new file mode 100644 index 0000000..bc374c8 --- /dev/null +++ b/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp @@ -0,0 +1,84 @@ +/* +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 "btSoftRigidCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "btSoftBody.h" +#include "BulletSoftBody/btSoftBodySolvers.h" + +///TODO: include all the shapes that the softbody can collide with +///alternatively, implement special case collision algorithms (just like for rigid collision shapes) + +//#include + +btSoftRigidCollisionAlgorithm::btSoftRigidCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* /*col0*/,btCollisionObject* /*col1*/, bool isSwapped) +: btCollisionAlgorithm(ci), +//m_ownManifold(false), +//m_manifoldPtr(mf), +m_isSwapped(isSwapped) +{ +} + + +btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm() +{ + + //m_softBody->m_overlappingRigidBodies.remove(m_rigidCollisionObject); + + /*if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } + */ + +} + + +#include + +void btSoftRigidCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)dispatchInfo; + (void)resultOut; + //printf("btSoftRigidCollisionAlgorithm\n"); + + btSoftBody* softBody = m_isSwapped? (btSoftBody*)body1 : (btSoftBody*)body0; + btCollisionObject* rigidCollisionObject = m_isSwapped? body0 : body1; + + if (softBody->m_collisionDisabledObjects.findLinearSearch(rigidCollisionObject)==softBody->m_collisionDisabledObjects.size()) + { + softBody->getSoftBodySolver()->processCollision(softBody, rigidCollisionObject); + } + + +} + +btScalar btSoftRigidCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + (void)col0; + (void)col1; + + //not yet + return btScalar(1.); +} + + + diff --git a/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h b/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h new file mode 100644 index 0000000..7658e3c --- /dev/null +++ b/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h @@ -0,0 +1,75 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_RIGID_COLLISION_ALGORITHM_H +#define BT_SOFT_RIGID_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +class btPersistentManifold; +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" + +#include "LinearMath/btVector3.h" +class btSoftBody; + +/// btSoftRigidCollisionAlgorithm provides collision detection between btSoftBody and btRigidBody +class btSoftRigidCollisionAlgorithm : public btCollisionAlgorithm +{ + // bool m_ownManifold; + // btPersistentManifold* m_manifoldPtr; + + btSoftBody* m_softBody; + btCollisionObject* m_rigidCollisionObject; + + ///for rigid versus soft (instead of soft versus rigid), we use this swapped boolean + bool m_isSwapped; + +public: + + btSoftRigidCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped); + + virtual ~btSoftRigidCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + //we don't add any manifolds + } + + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftRigidCollisionAlgorithm)); + if (!m_swapped) + { + return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0,body1,false); + } else + { + return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0,body1,true); + } + } + }; + +}; + +#endif //BT_SOFT_RIGID_COLLISION_ALGORITHM_H + + diff --git a/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp new file mode 100644 index 0000000..8f4be23 --- /dev/null +++ b/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp @@ -0,0 +1,365 @@ +/* +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 "btSoftRigidDynamicsWorld.h" +#include "LinearMath/btQuickprof.h" + +//softbody & helpers +#include "btSoftBody.h" +#include "btSoftBodyHelpers.h" +#include "btSoftBodySolvers.h" +#include "btDefaultSoftBodySolver.h" +#include "LinearMath/btSerializer.h" + + +btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld( + btDispatcher* dispatcher, + btBroadphaseInterface* pairCache, + btConstraintSolver* constraintSolver, + btCollisionConfiguration* collisionConfiguration, + btSoftBodySolver *softBodySolver ) : + btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration), + m_softBodySolver( softBodySolver ), + m_ownsSolver(false) +{ + if( !m_softBodySolver ) + { + void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver),16); + m_softBodySolver = new(ptr) btDefaultSoftBodySolver(); + m_ownsSolver = true; + } + + m_drawFlags = fDrawFlags::Std; + m_drawNodeTree = true; + m_drawFaceTree = false; + m_drawClusterTree = false; + m_sbi.m_broadphase = pairCache; + m_sbi.m_dispatcher = dispatcher; + m_sbi.m_sparsesdf.Initialize(); + m_sbi.m_sparsesdf.Reset(); + + m_sbi.air_density = (btScalar)1.2; + m_sbi.water_density = 0; + m_sbi.water_offset = 0; + m_sbi.water_normal = btVector3(0,0,0); + m_sbi.m_gravity.setValue(0,-10,0); + + m_sbi.m_sparsesdf.Initialize(); + + +} + +btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld() +{ + if (m_ownsSolver) + { + m_softBodySolver->~btSoftBodySolver(); + btAlignedFree(m_softBodySolver); + } +} + +void btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) +{ + btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep ); + { + BT_PROFILE("predictUnconstraintMotionSoftBody"); + m_softBodySolver->predictMotion( timeStep ); + } +} + +void btSoftRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep ) +{ + + // Let the solver grab the soft bodies and if necessary optimize for it + m_softBodySolver->optimize( getSoftBodyArray() ); + + if( !m_softBodySolver->checkInitialized() ) + { + btAssert( "Solver initialization failed\n" ); + } + + btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep ); + + ///solve soft bodies constraints + solveSoftBodiesConstraints( timeStep ); + + //self collisions + for ( int i=0;idefaultCollisionHandler(psb); + } + + ///update soft bodies + m_softBodySolver->updateSoftBodies( ); + + // End solver-wise simulation step + // /////////////////////////////// + +} + +void btSoftRigidDynamicsWorld::solveSoftBodiesConstraints( btScalar timeStep ) +{ + BT_PROFILE("solveSoftConstraints"); + + if(m_softBodies.size()) + { + btSoftBody::solveClusters(m_softBodies); + } + + // Solve constraints solver-wise + m_softBodySolver->solveConstraints( timeStep * m_softBodySolver->getTimeScale() ); + +} + +void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body,short int collisionFilterGroup,short int collisionFilterMask) +{ + m_softBodies.push_back(body); + + // Set the soft body solver that will deal with this body + // to be the world's solver + body->setSoftBodySolver( m_softBodySolver ); + + btCollisionWorld::addCollisionObject(body, + collisionFilterGroup, + collisionFilterMask); + +} + +void btSoftRigidDynamicsWorld::removeSoftBody(btSoftBody* body) +{ + m_softBodies.remove(body); + + btCollisionWorld::removeCollisionObject(body); +} + +void btSoftRigidDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject) +{ + btSoftBody* body = btSoftBody::upcast(collisionObject); + if (body) + removeSoftBody(body); + else + btDiscreteDynamicsWorld::removeCollisionObject(collisionObject); +} + +void btSoftRigidDynamicsWorld::debugDrawWorld() +{ + btDiscreteDynamicsWorld::debugDrawWorld(); + + if (getDebugDrawer()) + { + int i; + for ( i=0;im_softBodies.size();i++) + { + btSoftBody* psb=(btSoftBody*)this->m_softBodies[i]; + if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe))) + { + btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer); + btSoftBodyHelpers::Draw(psb,m_debugDrawer,m_drawFlags); + } + + if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + if(m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer); + if(m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb,m_debugDrawer); + if(m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb,m_debugDrawer); + } + } + } +} + + + + +struct btSoftSingleRayCallback : public btBroadphaseRayCallback +{ + btVector3 m_rayFromWorld; + btVector3 m_rayToWorld; + btTransform m_rayFromTrans; + btTransform m_rayToTrans; + btVector3 m_hitNormal; + + const btSoftRigidDynamicsWorld* m_world; + btCollisionWorld::RayResultCallback& m_resultCallback; + + btSoftSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btSoftRigidDynamicsWorld* world,btCollisionWorld::RayResultCallback& resultCallback) + :m_rayFromWorld(rayFromWorld), + m_rayToWorld(rayToWorld), + m_world(world), + m_resultCallback(resultCallback) + { + m_rayFromTrans.setIdentity(); + m_rayFromTrans.setOrigin(m_rayFromWorld); + m_rayToTrans.setIdentity(); + m_rayToTrans.setOrigin(m_rayToWorld); + + btVector3 rayDir = (rayToWorld-rayFromWorld); + + rayDir.normalize (); + ///what about division by zero? --> just set rayDirection[i] to INF/1e30 + m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0]; + m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1]; + m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2]; + m_signs[0] = m_rayDirectionInverse[0] < 0.0; + m_signs[1] = m_rayDirectionInverse[1] < 0.0; + m_signs[2] = m_rayDirectionInverse[2] < 0.0; + + m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld); + + } + + + + virtual bool process(const btBroadphaseProxy* proxy) + { + ///terminate further ray tests, once the closestHitFraction reached zero + if (m_resultCallback.m_closestHitFraction == btScalar(0.f)) + return false; + + btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; + + //only perform raycast if filterMask matches + if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) + { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + //btVector3 collisionObjectAabbMin,collisionObjectAabbMax; +#if 0 +#ifdef RECALCULATE_AABB + btVector3 collisionObjectAabbMin,collisionObjectAabbMax; + collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); +#else + //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax); + const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin; + const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax; +#endif +#endif + //btScalar hitLambda = m_resultCallback.m_closestHitFraction; + //culling already done by broadphase + //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal)) + { + m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + m_resultCallback); + } + } + return true; + } +}; + +void btSoftRigidDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const +{ + BT_PROFILE("rayTest"); + /// use the broadphase to accelerate the search for objects, based on their aabb + /// and for each object with ray-aabb overlap, perform an exact ray test + btSoftSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback); + +#ifndef USE_BRUTEFORCE_RAYBROADPHASE + m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB); +#else + for (int i=0;igetNumCollisionObjects();i++) + { + rayCB.process(m_collisionObjects[i]->getBroadphaseHandle()); + } +#endif //USE_BRUTEFORCE_RAYBROADPHASE + +} + + +void btSoftRigidDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + RayResultCallback& resultCallback) +{ + if (collisionShape->isSoftBody()) { + btSoftBody* softBody = btSoftBody::upcast(collisionObject); + if (softBody) { + btSoftBody::sRayCast softResult; + if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult)) + { + + if (softResult.fraction<= resultCallback.m_closestHitFraction) + { + + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = 0; + shapeInfo.m_triangleIndex = softResult.index; + // get the normal + btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin(); + btVector3 normal=-rayDir; + normal.normalize(); + + if (softResult.feature == btSoftBody::eFeature::Face) + { + normal = softBody->m_faces[softResult.index].m_normal; + if (normal.dot(rayDir) > 0) { + // normal always point toward origin of the ray + normal = -normal; + } + } + + btCollisionWorld::LocalRayResult rayResult + (collisionObject, + &shapeInfo, + normal, + softResult.fraction); + bool normalInWorldSpace = true; + resultCallback.addSingleResult(rayResult,normalInWorldSpace); + } + } + } + } + else { + btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,collisionObject,collisionShape,colObjWorldTransform,resultCallback); + } +} + + +void btSoftRigidDynamicsWorld::serializeSoftBodies(btSerializer* serializer) +{ + int i; + //serialize all collision objects + for (i=0;igetInternalType() & btCollisionObject::CO_SOFT_BODY) + { + int len = colObj->calculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(len,1); + const char* structType = colObj->serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_SOFTBODY_CODE,colObj); + } + } + +} + +void btSoftRigidDynamicsWorld::serialize(btSerializer* serializer) +{ + + serializer->startSerialization(); + + serializeSoftBodies(serializer); + + serializeRigidBodies(serializer); + + serializeCollisionObjects(serializer); + + serializer->finishSerialization(); +} + + diff --git a/src/BulletSoftBody/btSoftRigidDynamicsWorld.h b/src/BulletSoftBody/btSoftRigidDynamicsWorld.h new file mode 100644 index 0000000..3e0efaf --- /dev/null +++ b/src/BulletSoftBody/btSoftRigidDynamicsWorld.h @@ -0,0 +1,107 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_RIGID_DYNAMICS_WORLD_H +#define BT_SOFT_RIGID_DYNAMICS_WORLD_H + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +#include "btSoftBody.h" + +typedef btAlignedObjectArray btSoftBodyArray; + +class btSoftBodySolver; + +class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld +{ + + btSoftBodyArray m_softBodies; + int m_drawFlags; + bool m_drawNodeTree; + bool m_drawFaceTree; + bool m_drawClusterTree; + btSoftBodyWorldInfo m_sbi; + ///Solver classes that encapsulate multiple soft bodies for solving + btSoftBodySolver *m_softBodySolver; + bool m_ownsSolver; + +protected: + + virtual void predictUnconstraintMotion(btScalar timeStep); + + virtual void internalSingleStepSimulation( btScalar timeStep); + + void solveSoftBodiesConstraints( btScalar timeStep ); + + void serializeSoftBodies(btSerializer* serializer); + +public: + + btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btSoftBodySolver *softBodySolver = 0 ); + + virtual ~btSoftRigidDynamicsWorld(); + + virtual void debugDrawWorld(); + + void addSoftBody(btSoftBody* body,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter); + + void removeSoftBody(btSoftBody* body); + + ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btDiscreteDynamicsWorld::removeCollisionObject + virtual void removeCollisionObject(btCollisionObject* collisionObject); + + int getDrawFlags() const { return(m_drawFlags); } + void setDrawFlags(int f) { m_drawFlags=f; } + + btSoftBodyWorldInfo& getWorldInfo() + { + return m_sbi; + } + const btSoftBodyWorldInfo& getWorldInfo() const + { + return m_sbi; + } + + virtual btDynamicsWorldType getWorldType() const + { + return BT_SOFT_RIGID_DYNAMICS_WORLD; + } + + btSoftBodyArray& getSoftBodyArray() + { + return m_softBodies; + } + + const btSoftBodyArray& getSoftBodyArray() const + { + return m_softBodies; + } + + + virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const; + + /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. + /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape. + /// This allows more customization. + static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + RayResultCallback& resultCallback); + + virtual void serialize(btSerializer* serializer); + +}; + +#endif //BT_SOFT_RIGID_DYNAMICS_WORLD_H diff --git a/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp b/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp new file mode 100644 index 0000000..1b8cfa7 --- /dev/null +++ b/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp @@ -0,0 +1,47 @@ +/* +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 "btSoftSoftCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletSoftBody/btSoftBodySolvers.h" +#include "btSoftBody.h" + +#define USE_PERSISTENT_CONTACTS 1 + +btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* /*obj0*/,btCollisionObject* /*obj1*/) +: btCollisionAlgorithm(ci) +//m_ownManifold(false), +//m_manifoldPtr(mf) +{ +} + +btSoftSoftCollisionAlgorithm::~btSoftSoftCollisionAlgorithm() +{ +} + +void btSoftSoftCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) +{ + btSoftBody* soft0 = (btSoftBody*)body0; + btSoftBody* soft1 = (btSoftBody*)body1; + soft0->getSoftBodySolver()->processCollision(soft0, soft1); +} + +btScalar btSoftSoftCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) +{ + //not yet + return 1.f; +} diff --git a/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h b/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h new file mode 100644 index 0000000..92d683c --- /dev/null +++ b/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h @@ -0,0 +1,69 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_SOFT_COLLISION_ALGORITHM_H +#define BT_SOFT_SOFT_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" + +class btPersistentManifold; +class btSoftBody; + +///collision detection between two btSoftBody shapes +class btSoftSoftCollisionAlgorithm : public btCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + + btSoftBody* m_softBody0; + btSoftBody* m_softBody1; + + +public: + btSoftSoftCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btCollisionAlgorithm(ci) {} + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + manifoldArray.push_back(m_manifoldPtr); + } + + btSoftSoftCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); + + virtual ~btSoftSoftCollisionAlgorithm(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + int bbsize = sizeof(btSoftSoftCollisionAlgorithm); + void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize); + return new(ptr) btSoftSoftCollisionAlgorithm(0,ci,body0,body1); + } + }; + +}; + +#endif //BT_SOFT_SOFT_COLLISION_ALGORITHM_H + + diff --git a/src/BulletSoftBody/btSparseSDF.h b/src/BulletSoftBody/btSparseSDF.h new file mode 100644 index 0000000..90a26cd --- /dev/null +++ b/src/BulletSoftBody/btSparseSDF.h @@ -0,0 +1,306 @@ +/* +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. +*/ +///btSparseSdf implementation by Nathanael Presson + +#ifndef BT_SPARSE_SDF_H +#define BT_SPARSE_SDF_H + +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" + +// Modified Paul Hsieh hash +template +unsigned int HsiehHash(const void* pdata) +{ + const unsigned short* data=(const unsigned short*)pdata; + unsigned hash=DWORDLEN<<2,tmp; + for(int i=0;i>11; + } + hash^=hash<<3;hash+=hash>>5; + hash^=hash<<4;hash+=hash>>17; + hash^=hash<<25;hash+=hash>>6; + return(hash); +} + +template +struct btSparseSdf +{ + // + // Inner types + // + struct IntFrac + { + int b; + int i; + btScalar f; + }; + struct Cell + { + btScalar d[CELLSIZE+1][CELLSIZE+1][CELLSIZE+1]; + int c[3]; + int puid; + unsigned hash; + btCollisionShape* pclient; + Cell* next; + }; + // + // Fields + // + + btAlignedObjectArray cells; + btScalar voxelsz; + int puid; + int ncells; + int nprobes; + int nqueries; + + // + // Methods + // + + // + void Initialize(int hashsize=2383) + { + cells.resize(hashsize,0); + Reset(); + } + // + void Reset() + { + for(int i=0,ni=cells.size();inext; + delete pc; + pc=pn; + } + } + voxelsz =0.25; + puid =0; + ncells =0; + nprobes =1; + nqueries =1; + } + // + void GarbageCollect(int lifetime=256) + { + const int life=puid-lifetime; + for(int i=0;inext; + if(pc->puidnext=pn; else root=pn; + delete pc;pc=pp;--ncells; + } + pp=pc;pc=pn; + } + } + //printf("GC[%d]: %d cells, PpQ: %f\r\n",puid,ncells,nprobes/(btScalar)nqueries); + nqueries=1; + nprobes=1; + ++puid; ///@todo: Reset puid's when int range limit is reached */ + /* else setup a priority list... */ + } + // + int RemoveReferences(btCollisionShape* pcs) + { + int refcount=0; + for(int i=0;inext; + if(pc->pclient==pcs) + { + if(pp) pp->next=pn; else root=pn; + delete pc;pc=pp;++refcount; + } + pp=pc;pc=pn; + } + } + return(refcount); + } + // + btScalar Evaluate( const btVector3& x, + btCollisionShape* shape, + btVector3& normal, + btScalar margin) + { + /* Lookup cell */ + const btVector3 scx=x/voxelsz; + const IntFrac ix=Decompose(scx.x()); + const IntFrac iy=Decompose(scx.y()); + const IntFrac iz=Decompose(scx.z()); + const unsigned h=Hash(ix.b,iy.b,iz.b,shape); + Cell*& root=cells[static_cast(h%cells.size())]; + Cell* c=root; + ++nqueries; + while(c) + { + ++nprobes; + if( (c->hash==h) && + (c->c[0]==ix.b) && + (c->c[1]==iy.b) && + (c->c[2]==iz.b) && + (c->pclient==shape)) + { break; } + else + { c=c->next; } + } + if(!c) + { + ++nprobes; + ++ncells; + c=new Cell(); + c->next=root;root=c; + c->pclient=shape; + c->hash=h; + c->c[0]=ix.b;c->c[1]=iy.b;c->c[2]=iz.b; + BuildCell(*c); + } + c->puid=puid; + /* Extract infos */ + const int o[]={ ix.i,iy.i,iz.i}; + const btScalar d[]={ c->d[o[0]+0][o[1]+0][o[2]+0], + c->d[o[0]+1][o[1]+0][o[2]+0], + c->d[o[0]+1][o[1]+1][o[2]+0], + c->d[o[0]+0][o[1]+1][o[2]+0], + c->d[o[0]+0][o[1]+0][o[2]+1], + c->d[o[0]+1][o[1]+0][o[2]+1], + c->d[o[0]+1][o[1]+1][o[2]+1], + c->d[o[0]+0][o[1]+1][o[2]+1]}; + /* Normal */ +#if 1 + const btScalar gx[]={ d[1]-d[0],d[2]-d[3], + d[5]-d[4],d[6]-d[7]}; + const btScalar gy[]={ d[3]-d[0],d[2]-d[1], + d[7]-d[4],d[6]-d[5]}; + const btScalar gz[]={ d[4]-d[0],d[5]-d[1], + d[7]-d[3],d[6]-d[2]}; + normal.setX(Lerp( Lerp(gx[0],gx[1],iy.f), + Lerp(gx[2],gx[3],iy.f),iz.f)); + normal.setY(Lerp( Lerp(gy[0],gy[1],ix.f), + Lerp(gy[2],gy[3],ix.f),iz.f)); + normal.setZ(Lerp( Lerp(gz[0],gz[1],ix.f), + Lerp(gz[2],gz[3],ix.f),iy.f)); + normal = normal.normalized(); +#else + normal = btVector3(d[1]-d[0],d[3]-d[0],d[4]-d[0]).normalized(); +#endif + /* Distance */ + const btScalar d0=Lerp(Lerp(d[0],d[1],ix.f), + Lerp(d[3],d[2],ix.f),iy.f); + const btScalar d1=Lerp(Lerp(d[4],d[5],ix.f), + Lerp(d[7],d[6],ix.f),iy.f); + return(Lerp(d0,d1,iz.f)-margin); + } + // + void BuildCell(Cell& c) + { + const btVector3 org=btVector3( (btScalar)c.c[0], + (btScalar)c.c[1], + (btScalar)c.c[2]) * + CELLSIZE*voxelsz; + for(int k=0;k<=CELLSIZE;++k) + { + const btScalar z=voxelsz*k+org.z(); + for(int j=0;j<=CELLSIZE;++j) + { + const btScalar y=voxelsz*j+org.y(); + for(int i=0;i<=CELLSIZE;++i) + { + const btScalar x=voxelsz*i+org.x(); + c.d[i][j][k]=DistanceToShape( btVector3(x,y,z), + c.pclient); + } + } + } + } + // + static inline btScalar DistanceToShape(const btVector3& x, + btCollisionShape* shape) + { + btTransform unit; + unit.setIdentity(); + if(shape->isConvex()) + { + btGjkEpaSolver2::sResults res; + btConvexShape* csh=static_cast(shape); + return(btGjkEpaSolver2::SignedDistance(x,0,csh,unit,res)); + } + return(0); + } + // + static inline IntFrac Decompose(btScalar x) + { + /* That one need a lot of improvements... */ + /* Remove test, faster floor... */ + IntFrac r; + x/=CELLSIZE; + const int o=x<0?(int)(-x+1):0; + x+=o;r.b=(int)x; + const btScalar k=(x-r.b)*CELLSIZE; + r.i=(int)k;r.f=k-r.i;r.b-=o; + return(r); + } + // + static inline btScalar Lerp(btScalar a,btScalar b,btScalar t) + { + return(a+(b-a)*t); + } + + + + // + static inline unsigned int Hash(int x,int y,int z,btCollisionShape* shape) + { + struct btS + { + int x,y,z; + void* p; + }; + + btS myset; + + myset.x=x;myset.y=y;myset.z=z;myset.p=shape; + const void* ptr = &myset; + + unsigned int result = HsiehHash (ptr); + + + return result; + } +}; + + +#endif //BT_SPARSE_SDF_H diff --git a/src/BulletSoftBody/premake4.lua b/src/BulletSoftBody/premake4.lua new file mode 100644 index 0000000..2c78bbb --- /dev/null +++ b/src/BulletSoftBody/premake4.lua @@ -0,0 +1,11 @@ + project "BulletSoftBody" + + kind "StaticLib" + targetdir "../../lib" + includedirs { + "..", + } + files { + "**.cpp", + "**.h" + } \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..b522b68 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,28 @@ +SUBDIRS( MiniCL BulletMultiThreaded BulletSoftBody BulletCollision BulletDynamics LinearMath ) + +IF(INSTALL_LIBS) + #INSTALL of other files requires CMake 2.6 + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + # Don't actually need to install any common files, the frameworks include everything + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(FILES btBulletCollisionCommon.h btBulletDynamicsCommon.h Bullet-C-Api.h DESTINATION ${INCLUDE_INSTALL_DIR}) + INSTALL(FILES vectormath/vmInclude.h DESTINATION ${INCLUDE_INSTALL_DIR}/vectormath) + INSTALL(FILES vectormath/scalar/boolInVec.h + vectormath/scalar/floatInVec.h + vectormath/scalar/mat_aos.h + vectormath/scalar/quat_aos.h + vectormath/scalar/vec_aos.h + vectormath/scalar/vectormath_aos.h + DESTINATION ${INCLUDE_INSTALL_DIR}/vectormath/scalar) + INSTALL(FILES vectormath/sse/boolInVec.h + vectormath/sse/floatInVec.h + vectormath/sse/mat_aos.h + vectormath/sse/quat_aos.h + vectormath/sse/vec_aos.h + vectormath/sse/vecidx_aos.h + vectormath/sse/vectormath_aos.h + DESTINATION ${INCLUDE_INSTALL_DIR}/vectormath/sse) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) +ENDIF(INSTALL_LIBS) diff --git a/src/LinearMath/CMakeLists.txt b/src/LinearMath/CMakeLists.txt new file mode 100644 index 0000000..4cbefc8 --- /dev/null +++ b/src/LinearMath/CMakeLists.txt @@ -0,0 +1,66 @@ + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src +) + +SET(LinearMath_SRCS + btAlignedAllocator.cpp + btConvexHull.cpp + btConvexHullComputer.cpp + btGeometryUtil.cpp + btQuickprof.cpp + btSerializer.cpp +) + +SET(LinearMath_HDRS + btAabbUtil2.h + btAlignedAllocator.h + btAlignedObjectArray.h + btConvexHull.h + btConvexHullComputer.h + btDefaultMotionState.h + btGeometryUtil.h + btGrahamScan2dConvexHull.h + btHashMap.h + btIDebugDraw.h + btList.h + btMatrix3x3.h + btMinMax.h + btMotionState.h + btPoolAllocator.h + btQuadWord.h + btQuaternion.h + btQuickprof.h + btRandom.h + btScalar.h + btSerializer.h + btStackAlloc.h + btTransform.h + btTransformUtil.h + btVector3.h +) + +ADD_LIBRARY(LinearMath ${LinearMath_SRCS} ${LinearMath_HDRS}) +SET_TARGET_PROPERTIES(LinearMath PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(LinearMath PROPERTIES SOVERSION ${BULLET_VERSION}) + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + #FILES_MATCHING requires CMake 2.6 + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS LinearMath DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS LinearMath DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN +".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(LinearMath PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(LinearMath PROPERTIES PUBLIC_HEADER "${LinearMath_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/src/LinearMath/btAabbUtil2.h b/src/LinearMath/btAabbUtil2.h new file mode 100644 index 0000000..42b721d --- /dev/null +++ b/src/LinearMath/btAabbUtil2.h @@ -0,0 +1,236 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_AABB_UTIL2 +#define BT_AABB_UTIL2 + +#include "btTransform.h" +#include "btVector3.h" +#include "btMinMax.h" + + + +SIMD_FORCE_INLINE void AabbExpand (btVector3& aabbMin, + btVector3& aabbMax, + const btVector3& expansionMin, + const btVector3& expansionMax) +{ + aabbMin = aabbMin + expansionMin; + aabbMax = aabbMax + expansionMax; +} + +/// conservative test for overlap between two aabbs +SIMD_FORCE_INLINE bool TestPointAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1, + const btVector3 &point) +{ + bool overlap = true; + overlap = (aabbMin1.getX() > point.getX() || aabbMax1.getX() < point.getX()) ? false : overlap; + overlap = (aabbMin1.getZ() > point.getZ() || aabbMax1.getZ() < point.getZ()) ? false : overlap; + overlap = (aabbMin1.getY() > point.getY() || aabbMax1.getY() < point.getY()) ? false : overlap; + return overlap; +} + + +/// conservative test for overlap between two aabbs +SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1, + const btVector3 &aabbMin2, const btVector3 &aabbMax2) +{ + bool overlap = true; + overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap; + overlap = (aabbMin1.getZ() > aabbMax2.getZ() || aabbMax1.getZ() < aabbMin2.getZ()) ? false : overlap; + overlap = (aabbMin1.getY() > aabbMax2.getY() || aabbMax1.getY() < aabbMin2.getY()) ? false : overlap; + return overlap; +} + +/// conservative test for overlap between triangle and aabb +SIMD_FORCE_INLINE bool TestTriangleAgainstAabb2(const btVector3 *vertices, + const btVector3 &aabbMin, const btVector3 &aabbMax) +{ + const btVector3 &p1 = vertices[0]; + const btVector3 &p2 = vertices[1]; + const btVector3 &p3 = vertices[2]; + + if (btMin(btMin(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false; + if (btMax(btMax(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false; + + if (btMin(btMin(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false; + if (btMax(btMax(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false; + + if (btMin(btMin(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false; + if (btMax(btMax(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false; + return true; +} + + +SIMD_FORCE_INLINE int btOutcode(const btVector3& p,const btVector3& halfExtent) +{ + return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) | + (p.getX() > halfExtent.getX() ? 0x08 : 0x0) | + (p.getY() < -halfExtent.getY() ? 0x02 : 0x0) | + (p.getY() > halfExtent.getY() ? 0x10 : 0x0) | + (p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) | + (p.getZ() > halfExtent.getZ() ? 0x20 : 0x0); +} + + + +SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom, + const btVector3& rayInvDirection, + const unsigned int raySign[3], + const btVector3 bounds[2], + btScalar& tmin, + btScalar lambda_min, + btScalar lambda_max) +{ + btScalar tmax, tymin, tymax, tzmin, tzmax; + tmin = (bounds[raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX(); + tmax = (bounds[1-raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX(); + tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY(); + tymax = (bounds[1-raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY(); + + if ( (tmin > tymax) || (tymin > tmax) ) + return false; + + if (tymin > tmin) + tmin = tymin; + + if (tymax < tmax) + tmax = tymax; + + tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ(); + tzmax = (bounds[1-raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ(); + + if ( (tmin > tzmax) || (tzmin > tmax) ) + return false; + if (tzmin > tmin) + tmin = tzmin; + if (tzmax < tmax) + tmax = tzmax; + return ( (tmin < lambda_max) && (tmax > lambda_min) ); +} + +SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom, + const btVector3& rayTo, + const btVector3& aabbMin, + const btVector3& aabbMax, + btScalar& param, btVector3& normal) +{ + btVector3 aabbHalfExtent = (aabbMax-aabbMin)* btScalar(0.5); + btVector3 aabbCenter = (aabbMax+aabbMin)* btScalar(0.5); + btVector3 source = rayFrom - aabbCenter; + btVector3 target = rayTo - aabbCenter; + int sourceOutcode = btOutcode(source,aabbHalfExtent); + int targetOutcode = btOutcode(target,aabbHalfExtent); + if ((sourceOutcode & targetOutcode) == 0x0) + { + btScalar lambda_enter = btScalar(0.0); + btScalar lambda_exit = param; + btVector3 r = target - source; + int i; + btScalar normSign = 1; + btVector3 hitNormal(0,0,0); + int bit=1; + + for (int j=0;j<2;j++) + { + for (i = 0; i != 3; ++i) + { + if (sourceOutcode & bit) + { + btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i]; + if (lambda_enter <= lambda) + { + lambda_enter = lambda; + hitNormal.setValue(0,0,0); + hitNormal[i] = normSign; + } + } + else if (targetOutcode & bit) + { + btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i]; + btSetMin(lambda_exit, lambda); + } + bit<<=1; + } + normSign = btScalar(-1.); + } + if (lambda_enter <= lambda_exit) + { + param = lambda_enter; + normal = hitNormal; + return true; + } + } + return false; +} + + + +SIMD_FORCE_INLINE void btTransformAabb(const btVector3& halfExtents, btScalar margin,const btTransform& t,btVector3& aabbMinOut,btVector3& aabbMaxOut) +{ + btVector3 halfExtentsWithMargin = halfExtents+btVector3(margin,margin,margin); + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = btVector3(abs_b[0].dot(halfExtentsWithMargin), + abs_b[1].dot(halfExtentsWithMargin), + abs_b[2].dot(halfExtentsWithMargin)); + aabbMinOut = center - extent; + aabbMaxOut = center + extent; +} + + +SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin,const btVector3& localAabbMax, btScalar margin,const btTransform& trans,btVector3& aabbMinOut,btVector3& aabbMaxOut) +{ + btAssert(localAabbMin.getX() <= localAabbMax.getX()); + btAssert(localAabbMin.getY() <= localAabbMax.getY()); + btAssert(localAabbMin.getZ() <= localAabbMax.getZ()); + btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin); + localHalfExtents+=btVector3(margin,margin,margin); + + btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin); + btMatrix3x3 abs_b = trans.getBasis().absolute(); + btVector3 center = trans(localCenter); + btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + aabbMinOut = center-extent; + aabbMaxOut = center+extent; +} + +#define USE_BANCHLESS 1 +#ifdef USE_BANCHLESS + //This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360) + SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) + { + return static_cast(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0]) + & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2]) + & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])), + 1, 0)); + } +#else + SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) + { + bool overlap = true; + overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap; + overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap; + overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap; + return overlap; + } +#endif //USE_BANCHLESS + +#endif //BT_AABB_UTIL2 + + diff --git a/src/LinearMath/btAlignedAllocator.cpp b/src/LinearMath/btAlignedAllocator.cpp new file mode 100644 index 0000000..c4c0ceb --- /dev/null +++ b/src/LinearMath/btAlignedAllocator.cpp @@ -0,0 +1,181 @@ +/* +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 "btAlignedAllocator.h" + +int gNumAlignedAllocs = 0; +int gNumAlignedFree = 0; +int gTotalBytesAlignedAllocs = 0;//detect memory leaks + +static void *btAllocDefault(size_t size) +{ + return malloc(size); +} + +static void btFreeDefault(void *ptr) +{ + free(ptr); +} + +static btAllocFunc *sAllocFunc = btAllocDefault; +static btFreeFunc *sFreeFunc = btFreeDefault; + + + +#if defined (BT_HAS_ALIGNED_ALLOCATOR) +#include +static void *btAlignedAllocDefault(size_t size, int alignment) +{ + return _aligned_malloc(size, (size_t)alignment); +} + +static void btAlignedFreeDefault(void *ptr) +{ + _aligned_free(ptr); +} +#elif defined(__CELLOS_LV2__) +#include + +static inline void *btAlignedAllocDefault(size_t size, int alignment) +{ + return memalign(alignment, size); +} + +static inline void btAlignedFreeDefault(void *ptr) +{ + free(ptr); +} +#else + + + + + +static inline void *btAlignedAllocDefault(size_t size, int alignment) +{ + void *ret; + char *real; + real = (char *)sAllocFunc(size + sizeof(void *) + (alignment-1)); + if (real) { + ret = btAlignPointer(real + sizeof(void *),alignment); + *((void **)(ret)-1) = (void *)(real); + } else { + ret = (void *)(real); + } + return (ret); +} + +static inline void btAlignedFreeDefault(void *ptr) +{ + void* real; + + if (ptr) { + real = *((void **)(ptr)-1); + sFreeFunc(real); + } +} +#endif + + +static btAlignedAllocFunc *sAlignedAllocFunc = btAlignedAllocDefault; +static btAlignedFreeFunc *sAlignedFreeFunc = btAlignedFreeDefault; + +void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc) +{ + sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault; + sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault; +} + +void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc) +{ + sAllocFunc = allocFunc ? allocFunc : btAllocDefault; + sFreeFunc = freeFunc ? freeFunc : btFreeDefault; +} + +#ifdef BT_DEBUG_MEMORY_ALLOCATIONS +//this generic allocator provides the total allocated number of bytes +#include + +void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename) +{ + void *ret; + char *real; + + gTotalBytesAlignedAllocs += size; + gNumAlignedAllocs++; + + + real = (char *)sAllocFunc(size + 2*sizeof(void *) + (alignment-1)); + if (real) { + ret = (void*) btAlignPointer((real + 2*sizeof(void *), alignment); + *((void **)(ret)-1) = (void *)(real); + *((int*)(ret)-2) = size; + + } else { + ret = (void *)(real);//?? + } + + printf("allocation#%d at address %x, from %s,line %d, size %d\n",gNumAlignedAllocs,real, filename,line,size); + + int* ptr = (int*)ret; + *ptr = 12; + return (ret); +} + +void btAlignedFreeInternal (void* ptr,int line,char* filename) +{ + + void* real; + gNumAlignedFree++; + + if (ptr) { + real = *((void **)(ptr)-1); + int size = *((int*)(ptr)-2); + gTotalBytesAlignedAllocs -= size; + + printf("free #%d at address %x, from %s,line %d, size %d\n",gNumAlignedFree,real, filename,line,size); + + sFreeFunc(real); + } else + { + printf("NULL ptr\n"); + } +} + +#else //BT_DEBUG_MEMORY_ALLOCATIONS + +void* btAlignedAllocInternal (size_t size, int alignment) +{ + gNumAlignedAllocs++; + void* ptr; + ptr = sAlignedAllocFunc(size, alignment); +// printf("btAlignedAllocInternal %d, %x\n",size,ptr); + return ptr; +} + +void btAlignedFreeInternal (void* ptr) +{ + if (!ptr) + { + return; + } + + gNumAlignedFree++; +// printf("btAlignedFreeInternal %x\n",ptr); + sAlignedFreeFunc(ptr); +} + +#endif //BT_DEBUG_MEMORY_ALLOCATIONS + diff --git a/src/LinearMath/btAlignedAllocator.h b/src/LinearMath/btAlignedAllocator.h new file mode 100644 index 0000000..f168f3c --- /dev/null +++ b/src/LinearMath/btAlignedAllocator.h @@ -0,0 +1,107 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_ALIGNED_ALLOCATOR +#define BT_ALIGNED_ALLOCATOR + +///we probably replace this with our own aligned memory allocator +///so we replace _aligned_malloc and _aligned_free with our own +///that is better portable and more predictable + +#include "btScalar.h" +//#define BT_DEBUG_MEMORY_ALLOCATIONS 1 +#ifdef BT_DEBUG_MEMORY_ALLOCATIONS + +#define btAlignedAlloc(a,b) \ + btAlignedAllocInternal(a,b,__LINE__,__FILE__) + +#define btAlignedFree(ptr) \ + btAlignedFreeInternal(ptr,__LINE__,__FILE__) + +void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename); + +void btAlignedFreeInternal (void* ptr,int line,char* filename); + +#else + void* btAlignedAllocInternal (size_t size, int alignment); + void btAlignedFreeInternal (void* ptr); + + #define btAlignedAlloc(size,alignment) btAlignedAllocInternal(size,alignment) + #define btAlignedFree(ptr) btAlignedFreeInternal(ptr) + +#endif +typedef int size_type; + +typedef void *(btAlignedAllocFunc)(size_t size, int alignment); +typedef void (btAlignedFreeFunc)(void *memblock); +typedef void *(btAllocFunc)(size_t size); +typedef void (btFreeFunc)(void *memblock); + +///The developer can let all Bullet memory allocations go through a custom memory allocator, using btAlignedAllocSetCustom +void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc); +///If the developer has already an custom aligned allocator, then btAlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it. +void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc); + + +///The btAlignedAllocator is a portable class for aligned memory allocations. +///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using btAlignedAllocSetCustom and btAlignedAllocSetCustomAligned. +template < typename T , unsigned Alignment > +class btAlignedAllocator { + + typedef btAlignedAllocator< T , Alignment > self_type; + +public: + + //just going down a list: + btAlignedAllocator() {} + /* + btAlignedAllocator( const self_type & ) {} + */ + + template < typename Other > + btAlignedAllocator( const btAlignedAllocator< Other , Alignment > & ) {} + + typedef const T* const_pointer; + typedef const T& const_reference; + typedef T* pointer; + typedef T& reference; + typedef T value_type; + + pointer address ( reference ref ) const { return &ref; } + const_pointer address ( const_reference ref ) const { return &ref; } + pointer allocate ( size_type n , const_pointer * hint = 0 ) { + (void)hint; + return reinterpret_cast< pointer >(btAlignedAlloc( sizeof(value_type) * n , Alignment )); + } + void construct ( pointer ptr , const value_type & value ) { new (ptr) value_type( value ); } + void deallocate( pointer ptr ) { + btAlignedFree( reinterpret_cast< void * >( ptr ) ); + } + void destroy ( pointer ptr ) { ptr->~value_type(); } + + + template < typename O > struct rebind { + typedef btAlignedAllocator< O , Alignment > other; + }; + template < typename O > + self_type & operator=( const btAlignedAllocator< O , Alignment > & ) { return *this; } + + friend bool operator==( const self_type & , const self_type & ) { return true; } +}; + + + +#endif //BT_ALIGNED_ALLOCATOR + diff --git a/src/LinearMath/btAlignedObjectArray.h b/src/LinearMath/btAlignedObjectArray.h new file mode 100644 index 0000000..36090e1 --- /dev/null +++ b/src/LinearMath/btAlignedObjectArray.h @@ -0,0 +1,494 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_OBJECT_ARRAY__ +#define BT_OBJECT_ARRAY__ + +#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE +#include "btAlignedAllocator.h" + +///If the platform doesn't support placement new, you can disable BT_USE_PLACEMENT_NEW +///then the btAlignedObjectArray doesn't support objects with virtual methods, and non-trivial constructors/destructors +///You can enable BT_USE_MEMCPY, then swapping elements in the array will use memcpy instead of operator= +///see discussion here: http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1231 and +///http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1240 + +#define BT_USE_PLACEMENT_NEW 1 +//#define BT_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in or or otherwise... +#define BT_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful + +#ifdef BT_USE_MEMCPY +#include +#include +#endif //BT_USE_MEMCPY + +#ifdef BT_USE_PLACEMENT_NEW +#include //for placement new +#endif //BT_USE_PLACEMENT_NEW + + +///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods +///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data +template +//template +class btAlignedObjectArray +{ + btAlignedAllocator m_allocator; + + int m_size; + int m_capacity; + T* m_data; + //PCK: added this line + bool m_ownsMemory; + +#ifdef BT_ALLOW_ARRAY_COPY_OPERATOR +public: + SIMD_FORCE_INLINE btAlignedObjectArray& operator=(const btAlignedObjectArray &other) + { + copyFromArray(other); + return *this; + } +#else//BT_ALLOW_ARRAY_COPY_OPERATOR +private: + SIMD_FORCE_INLINE btAlignedObjectArray& operator=(const btAlignedObjectArray &other); +#endif//BT_ALLOW_ARRAY_COPY_OPERATOR + +protected: + SIMD_FORCE_INLINE int allocSize(int size) + { + return (size ? size*2 : 1); + } + SIMD_FORCE_INLINE void copy(int start,int end, T* dest) const + { + int i; + for (i=start;i=0); + btAssert(n=0); + btAssert(n=0); + btAssert(n=0); + btAssert(n0); + m_size--; + m_data[m_size].~T(); + } + + ///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument. + ///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations. + SIMD_FORCE_INLINE void resize(int newsize, const T& fillData=T()) + { + int curSize = size(); + + if (newsize < curSize) + { + for(int i = newsize; i < curSize; i++) + { + m_data[i].~T(); + } + } else + { + if (newsize > size()) + { + reserve(newsize); + } +#ifdef BT_USE_PLACEMENT_NEW + for (int i=curSize;i + void quickSortInternal(const L& CompareFunc,int lo, int hi) + { + // lo is the lower index, hi is the upper index + // of the region of array a that is to be sorted + int i=lo, j=hi; + T x=m_data[(lo+hi)/2]; + + // partition + do + { + while (CompareFunc(m_data[i],x)) + i++; + while (CompareFunc(x,m_data[j])) + j--; + if (i<=j) + { + swap(i,j); + i++; j--; + } + } while (i<=j); + + // recursion + if (lo + void quickSort(const L& CompareFunc) + { + //don't sort 0 or 1 elements + if (size()>1) + { + quickSortInternal(CompareFunc,0,size()-1); + } + } + + + ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/ + template + void downHeap(T *pArr, int k, int n, const L& CompareFunc) + { + /* PRE: a[k+1..N] is a heap */ + /* POST: a[k..N] is a heap */ + + T temp = pArr[k - 1]; + /* k has child(s) */ + while (k <= n/2) + { + int child = 2*k; + + if ((child < n) && CompareFunc(pArr[child - 1] , pArr[child])) + { + child++; + } + /* pick larger child */ + if (CompareFunc(temp , pArr[child - 1])) + { + /* move child up */ + pArr[k - 1] = pArr[child - 1]; + k = child; + } + else + { + break; + } + } + pArr[k - 1] = temp; + } /*downHeap*/ + + void swap(int index0,int index1) + { +#ifdef BT_USE_MEMCPY + char temp[sizeof(T)]; + memcpy(temp,&m_data[index0],sizeof(T)); + memcpy(&m_data[index0],&m_data[index1],sizeof(T)); + memcpy(&m_data[index1],temp,sizeof(T)); +#else + T temp = m_data[index0]; + m_data[index0] = m_data[index1]; + m_data[index1] = temp; +#endif //BT_USE_PLACEMENT_NEW + + } + + template + void heapSort(const L& CompareFunc) + { + /* sort a[0..N-1], N.B. 0 to N-1 */ + int k; + int n = m_size; + for (k = n/2; k > 0; k--) + { + downHeap(m_data, k, n, CompareFunc); + } + + /* a[1..N] is now a heap */ + while ( n>=1 ) + { + swap(0,n-1); /* largest of a[0..n-1] */ + + + n = n - 1; + /* restore a[1..i-1] heap */ + downHeap(m_data, 1, n, CompareFunc); + } + } + + ///non-recursive binary search, assumes sorted array + int findBinarySearch(const T& key) const + { + int first = 0; + int last = size()-1; + + //assume sorted array + while (first <= last) { + int mid = (first + last) / 2; // compute mid point. + if (key > m_data[mid]) + first = mid + 1; // repeat search in top half. + else if (key < m_data[mid]) + last = mid - 1; // repeat search in bottom half. + else + return mid; // found it. return position ///// + } + return size(); // failed to find key + } + + + int findLinearSearch(const T& key) const + { + int index=size(); + int i; + + for (i=0;i + +#include "btConvexHull.h" +#include "btAlignedObjectArray.h" +#include "btMinMax.h" +#include "btVector3.h" + + + +template +void Swap(T &a,T &b) +{ + T tmp = a; + a=b; + b=tmp; +} + + +//---------------------------------- + +class int3 +{ +public: + int x,y,z; + int3(){}; + int3(int _x,int _y, int _z){x=_x;y=_y;z=_z;} + const int& operator[](int i) const {return (&x)[i];} + int& operator[](int i) {return (&x)[i];} +}; + + +//------- btPlane ---------- + + +inline btPlane PlaneFlip(const btPlane &plane){return btPlane(-plane.normal,-plane.dist);} +inline int operator==( const btPlane &a, const btPlane &b ) { return (a.normal==b.normal && a.dist==b.dist); } +inline int coplanar( const btPlane &a, const btPlane &b ) { return (a==b || a==PlaneFlip(b)); } + + +//--------- Utility Functions ------ + +btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1); +btVector3 PlaneProject(const btPlane &plane, const btVector3 &point); + +btVector3 ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2); +btVector3 ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2) +{ + btVector3 N1 = p0.normal; + btVector3 N2 = p1.normal; + btVector3 N3 = p2.normal; + + btVector3 n2n3; n2n3 = N2.cross(N3); + btVector3 n3n1; n3n1 = N3.cross(N1); + btVector3 n1n2; n1n2 = N1.cross(N2); + + btScalar quotient = (N1.dot(n2n3)); + + btAssert(btFabs(quotient) > btScalar(0.000001)); + + quotient = btScalar(-1.) / quotient; + n2n3 *= p0.dist; + n3n1 *= p1.dist; + n1n2 *= p2.dist; + btVector3 potentialVertex = n2n3; + potentialVertex += n3n1; + potentialVertex += n1n2; + potentialVertex *= quotient; + + btVector3 result(potentialVertex.getX(),potentialVertex.getY(),potentialVertex.getZ()); + return result; + +} + +btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint=NULL, btVector3 *vpoint=NULL); +btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2); +btVector3 NormalOf(const btVector3 *vert, const int n); + + +btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1) +{ + // returns the point where the line p0-p1 intersects the plane n&d + static btVector3 dif; + dif = p1-p0; + btScalar dn= btDot(plane.normal,dif); + btScalar t = -(plane.dist+btDot(plane.normal,p0) )/dn; + return p0 + (dif*t); +} + +btVector3 PlaneProject(const btPlane &plane, const btVector3 &point) +{ + return point - plane.normal * (btDot(point,plane.normal)+plane.dist); +} + +btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2) +{ + // return the normal of the triangle + // inscribed by v0, v1, and v2 + btVector3 cp=btCross(v1-v0,v2-v1); + btScalar m=cp.length(); + if(m==0) return btVector3(1,0,0); + return cp*(btScalar(1.0)/m); +} + + +btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint, btVector3 *vpoint) +{ + static btVector3 cp; + cp = btCross(udir,vdir).normalized(); + + btScalar distu = -btDot(cp,ustart); + btScalar distv = -btDot(cp,vstart); + btScalar dist = (btScalar)fabs(distu-distv); + if(upoint) + { + btPlane plane; + plane.normal = btCross(vdir,cp).normalized(); + plane.dist = -btDot(plane.normal,vstart); + *upoint = PlaneLineIntersection(plane,ustart,ustart+udir); + } + if(vpoint) + { + btPlane plane; + plane.normal = btCross(udir,cp).normalized(); + plane.dist = -btDot(plane.normal,ustart); + *vpoint = PlaneLineIntersection(plane,vstart,vstart+vdir); + } + return dist; +} + + + + + + + +#define COPLANAR (0) +#define UNDER (1) +#define OVER (2) +#define SPLIT (OVER|UNDER) +#define PAPERWIDTH (btScalar(0.001)) + +btScalar planetestepsilon = PAPERWIDTH; + + + +typedef ConvexH::HalfEdge HalfEdge; + +ConvexH::ConvexH(int vertices_size,int edges_size,int facets_size) +{ + vertices.resize(vertices_size); + edges.resize(edges_size); + facets.resize(facets_size); +} + + +int PlaneTest(const btPlane &p, const btVector3 &v); +int PlaneTest(const btPlane &p, const btVector3 &v) { + btScalar a = btDot(v,p.normal)+p.dist; + int flag = (a>planetestepsilon)?OVER:((a<-planetestepsilon)?UNDER:COPLANAR); + return flag; +} + +int SplitTest(ConvexH &convex,const btPlane &plane); +int SplitTest(ConvexH &convex,const btPlane &plane) { + int flag=0; + for(int i=0;i +int maxdirfiltered(const T *p,int count,const T &dir,btAlignedObjectArray &allow) +{ + btAssert(count); + int m=-1; + for(int i=0;ibtDot(p[m],dir)) + m=i; + } + btAssert(m!=-1); + return m; +} + +btVector3 orth(const btVector3 &v); +btVector3 orth(const btVector3 &v) +{ + btVector3 a=btCross(v,btVector3(0,0,1)); + btVector3 b=btCross(v,btVector3(0,1,0)); + if (a.length() > b.length()) + { + return a.normalized(); + } else { + return b.normalized(); + } +} + + +template +int maxdirsterid(const T *p,int count,const T &dir,btAlignedObjectArray &allow) +{ + int m=-1; + while(m==-1) + { + m = maxdirfiltered(p,count,dir,allow); + if(allow[m]==3) return m; + T u = orth(dir); + T v = btCross(u,dir); + int ma=-1; + for(btScalar x = btScalar(0.0) ; x<= btScalar(360.0) ; x+= btScalar(45.0)) + { + btScalar s = btSin(SIMD_RADS_PER_DEG*(x)); + btScalar c = btCos(SIMD_RADS_PER_DEG*(x)); + int mb = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow); + if(ma==m && mb==m) + { + allow[m]=3; + return m; + } + if(ma!=-1 && ma!=mb) // Yuck - this is really ugly + { + int mc = ma; + for(btScalar xx = x-btScalar(40.0) ; xx <= x ; xx+= btScalar(5.0)) + { + btScalar s = btSin(SIMD_RADS_PER_DEG*(xx)); + btScalar c = btCos(SIMD_RADS_PER_DEG*(xx)); + int md = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow); + if(mc==m && md==m) + { + allow[m]=3; + return m; + } + mc=md; + } + } + ma=mb; + } + allow[m]=0; + m=-1; + } + btAssert(0); + return m; +} + + + + +int operator ==(const int3 &a,const int3 &b); +int operator ==(const int3 &a,const int3 &b) +{ + for(int i=0;i<3;i++) + { + if(a[i]!=b[i]) return 0; + } + return 1; +} + + +int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon); +int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon) +{ + btVector3 n=TriNormal(vertices[t[0]],vertices[t[1]],vertices[t[2]]); + return (btDot(n,p-vertices[t[0]]) > epsilon); // EPSILON??? +} +int hasedge(const int3 &t, int a,int b); +int hasedge(const int3 &t, int a,int b) +{ + for(int i=0;i<3;i++) + { + int i1= (i+1)%3; + if(t[i]==a && t[i1]==b) return 1; + } + return 0; +} +int hasvert(const int3 &t, int v); +int hasvert(const int3 &t, int v) +{ + return (t[0]==v || t[1]==v || t[2]==v) ; +} +int shareedge(const int3 &a,const int3 &b); +int shareedge(const int3 &a,const int3 &b) +{ + int i; + for(i=0;i<3;i++) + { + int i1= (i+1)%3; + if(hasedge(a,b[i1],b[i])) return 1; + } + return 0; +} + +class btHullTriangle; + + + +class btHullTriangle : public int3 +{ +public: + int3 n; + int id; + int vmax; + btScalar rise; + btHullTriangle(int a,int b,int c):int3(a,b,c),n(-1,-1,-1) + { + vmax=-1; + rise = btScalar(0.0); + } + ~btHullTriangle() + { + } + int &neib(int a,int b); +}; + + +int &btHullTriangle::neib(int a,int b) +{ + static int er=-1; + int i; + for(i=0;i<3;i++) + { + int i1=(i+1)%3; + int i2=(i+2)%3; + if((*this)[i]==a && (*this)[i1]==b) return n[i2]; + if((*this)[i]==b && (*this)[i1]==a) return n[i2]; + } + btAssert(0); + return er; +} +void HullLibrary::b2bfix(btHullTriangle* s,btHullTriangle*t) +{ + int i; + for(i=0;i<3;i++) + { + int i1=(i+1)%3; + int i2=(i+2)%3; + int a = (*s)[i1]; + int b = (*s)[i2]; + btAssert(m_tris[s->neib(a,b)]->neib(b,a) == s->id); + btAssert(m_tris[t->neib(a,b)]->neib(b,a) == t->id); + m_tris[s->neib(a,b)]->neib(b,a) = t->neib(b,a); + m_tris[t->neib(b,a)]->neib(a,b) = s->neib(a,b); + } +} + +void HullLibrary::removeb2b(btHullTriangle* s,btHullTriangle*t) +{ + b2bfix(s,t); + deAllocateTriangle(s); + + deAllocateTriangle(t); +} + +void HullLibrary::checkit(btHullTriangle *t) +{ + (void)t; + + int i; + btAssert(m_tris[t->id]==t); + for(i=0;i<3;i++) + { + int i1=(i+1)%3; + int i2=(i+2)%3; + int a = (*t)[i1]; + int b = (*t)[i2]; + + // release compile fix + (void)i1; + (void)i2; + (void)a; + (void)b; + + btAssert(a!=b); + btAssert( m_tris[t->n[i]]->neib(b,a) == t->id); + } +} + +btHullTriangle* HullLibrary::allocateTriangle(int a,int b,int c) +{ + void* mem = btAlignedAlloc(sizeof(btHullTriangle),16); + btHullTriangle* tr = new (mem)btHullTriangle(a,b,c); + tr->id = m_tris.size(); + m_tris.push_back(tr); + + return tr; +} + +void HullLibrary::deAllocateTriangle(btHullTriangle* tri) +{ + btAssert(m_tris[tri->id]==tri); + m_tris[tri->id]=NULL; + tri->~btHullTriangle(); + btAlignedFree(tri); +} + + +void HullLibrary::extrude(btHullTriangle *t0,int v) +{ + int3 t= *t0; + int n = m_tris.size(); + btHullTriangle* ta = allocateTriangle(v,t[1],t[2]); + ta->n = int3(t0->n[0],n+1,n+2); + m_tris[t0->n[0]]->neib(t[1],t[2]) = n+0; + btHullTriangle* tb = allocateTriangle(v,t[2],t[0]); + tb->n = int3(t0->n[1],n+2,n+0); + m_tris[t0->n[1]]->neib(t[2],t[0]) = n+1; + btHullTriangle* tc = allocateTriangle(v,t[0],t[1]); + tc->n = int3(t0->n[2],n+0,n+1); + m_tris[t0->n[2]]->neib(t[0],t[1]) = n+2; + checkit(ta); + checkit(tb); + checkit(tc); + if(hasvert(*m_tris[ta->n[0]],v)) removeb2b(ta,m_tris[ta->n[0]]); + if(hasvert(*m_tris[tb->n[0]],v)) removeb2b(tb,m_tris[tb->n[0]]); + if(hasvert(*m_tris[tc->n[0]],v)) removeb2b(tc,m_tris[tc->n[0]]); + deAllocateTriangle(t0); + +} + +btHullTriangle* HullLibrary::extrudable(btScalar epsilon) +{ + int i; + btHullTriangle *t=NULL; + for(i=0;iriserise)) + { + t = m_tris[i]; + } + } + return (t->rise >epsilon)?t:NULL ; +} + + + + +int4 HullLibrary::FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray &allow) +{ + btVector3 basis[3]; + basis[0] = btVector3( btScalar(0.01), btScalar(0.02), btScalar(1.0) ); + int p0 = maxdirsterid(verts,verts_count, basis[0],allow); + int p1 = maxdirsterid(verts,verts_count,-basis[0],allow); + basis[0] = verts[p0]-verts[p1]; + if(p0==p1 || basis[0]==btVector3(0,0,0)) + return int4(-1,-1,-1,-1); + basis[1] = btCross(btVector3( btScalar(1),btScalar(0.02), btScalar(0)),basis[0]); + basis[2] = btCross(btVector3(btScalar(-0.02), btScalar(1), btScalar(0)),basis[0]); + if (basis[1].length() > basis[2].length()) + { + basis[1].normalize(); + } else { + basis[1] = basis[2]; + basis[1].normalize (); + } + int p2 = maxdirsterid(verts,verts_count,basis[1],allow); + if(p2 == p0 || p2 == p1) + { + p2 = maxdirsterid(verts,verts_count,-basis[1],allow); + } + if(p2 == p0 || p2 == p1) + return int4(-1,-1,-1,-1); + basis[1] = verts[p2] - verts[p0]; + basis[2] = btCross(basis[1],basis[0]).normalized(); + int p3 = maxdirsterid(verts,verts_count,basis[2],allow); + if(p3==p0||p3==p1||p3==p2) p3 = maxdirsterid(verts,verts_count,-basis[2],allow); + if(p3==p0||p3==p1||p3==p2) + return int4(-1,-1,-1,-1); + btAssert(!(p0==p1||p0==p2||p0==p3||p1==p2||p1==p3||p2==p3)); + if(btDot(verts[p3]-verts[p0],btCross(verts[p1]-verts[p0],verts[p2]-verts[p0])) <0) {Swap(p2,p3);} + return int4(p0,p1,p2,p3); +} + +int HullLibrary::calchullgen(btVector3 *verts,int verts_count, int vlimit) +{ + if(verts_count <4) return 0; + if(vlimit==0) vlimit=1000000000; + int j; + btVector3 bmin(*verts),bmax(*verts); + btAlignedObjectArray isextreme; + isextreme.reserve(verts_count); + btAlignedObjectArray allow; + allow.reserve(verts_count); + + for(j=0;jn=int3(2,3,1); + btHullTriangle *t1 = allocateTriangle(p[3],p[2],p[0]); t1->n=int3(3,2,0); + btHullTriangle *t2 = allocateTriangle(p[0],p[1],p[3]); t2->n=int3(0,1,3); + btHullTriangle *t3 = allocateTriangle(p[1],p[0],p[2]); t3->n=int3(1,0,2); + isextreme[p[0]]=isextreme[p[1]]=isextreme[p[2]]=isextreme[p[3]]=1; + checkit(t0);checkit(t1);checkit(t2);checkit(t3); + + for(j=0;jvmax<0); + btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]); + t->vmax = maxdirsterid(verts,verts_count,n,allow); + t->rise = btDot(n,verts[t->vmax]-verts[(*t)[0]]); + } + btHullTriangle *te; + vlimit-=4; + while(vlimit >0 && ((te=extrudable(epsilon)) != 0)) + { + int3 ti=*te; + int v=te->vmax; + btAssert(v != -1); + btAssert(!isextreme[v]); // wtf we've already done this vertex + isextreme[v]=1; + //if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already + j=m_tris.size(); + while(j--) { + if(!m_tris[j]) continue; + int3 t=*m_tris[j]; + if(above(verts,t,verts[v],btScalar(0.01)*epsilon)) + { + extrude(m_tris[j],v); + } + } + // now check for those degenerate cases where we have a flipped triangle or a really skinny triangle + j=m_tris.size(); + while(j--) + { + if(!m_tris[j]) continue; + if(!hasvert(*m_tris[j],v)) break; + int3 nt=*m_tris[j]; + if(above(verts,nt,center,btScalar(0.01)*epsilon) || btCross(verts[nt[1]]-verts[nt[0]],verts[nt[2]]-verts[nt[1]]).length()< epsilon*epsilon*btScalar(0.1) ) + { + btHullTriangle *nb = m_tris[m_tris[j]->n[0]]; + btAssert(nb);btAssert(!hasvert(*nb,v));btAssert(nb->idvmax>=0) break; + btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]); + t->vmax = maxdirsterid(verts,verts_count,n,allow); + if(isextreme[t->vmax]) + { + t->vmax=-1; // already done that vertex - algorithm needs to be able to terminate. + } + else + { + t->rise = btDot(n,verts[t->vmax]-verts[(*t)[0]]); + } + } + vlimit --; + } + return 1; +} + +int HullLibrary::calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit) +{ + int rc=calchullgen(verts,verts_count, vlimit) ; + if(!rc) return 0; + btAlignedObjectArray ts; + int i; + + for(i=0;i(ts[i]); + } + m_tris.resize(0); + + return 1; +} + + + + + +bool HullLibrary::ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit) +{ + + int tris_count; + int ret = calchull( (btVector3 *) vertices, (int) vcount, result.m_Indices, tris_count, static_cast(vlimit) ); + if(!ret) return false; + result.mIndexCount = (unsigned int) (tris_count*3); + result.mFaceCount = (unsigned int) tris_count; + result.mVertices = (btVector3*) vertices; + result.mVcount = (unsigned int) vcount; + return true; + +} + + +void ReleaseHull(PHullResult &result); +void ReleaseHull(PHullResult &result) +{ + if ( result.m_Indices.size() ) + { + result.m_Indices.clear(); + } + + result.mVcount = 0; + result.mIndexCount = 0; + result.mVertices = 0; +} + + +//********************************************************************* +//********************************************************************* +//******** HullLib header +//********************************************************************* +//********************************************************************* + +//********************************************************************* +//********************************************************************* +//******** HullLib implementation +//********************************************************************* +//********************************************************************* + +HullError HullLibrary::CreateConvexHull(const HullDesc &desc, // describes the input request + HullResult &result) // contains the resulst +{ + HullError ret = QE_FAIL; + + + PHullResult hr; + + unsigned int vcount = desc.mVcount; + if ( vcount < 8 ) vcount = 8; + + btAlignedObjectArray vertexSource; + vertexSource.resize(static_cast(vcount)); + + btVector3 scale; + + unsigned int ovcount; + + bool ok = CleanupVertices(desc.mVcount,desc.mVertices, desc.mVertexStride, ovcount, &vertexSource[0], desc.mNormalEpsilon, scale ); // normalize point cloud, remove duplicates! + + if ( ok ) + { + + +// if ( 1 ) // scale vertices back to their original size. + { + for (unsigned int i=0; i(i)]; + v[0]*=scale[0]; + v[1]*=scale[1]; + v[2]*=scale[2]; + } + } + + ok = ComputeHull(ovcount,&vertexSource[0],hr,desc.mMaxVertices); + + if ( ok ) + { + + // re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table. + btAlignedObjectArray vertexScratch; + vertexScratch.resize(static_cast(hr.mVcount)); + + BringOutYourDead(hr.mVertices,hr.mVcount, &vertexScratch[0], ovcount, &hr.m_Indices[0], hr.mIndexCount ); + + ret = QE_OK; + + if ( desc.HasHullFlag(QF_TRIANGLES) ) // if he wants the results as triangle! + { + result.mPolygons = false; + result.mNumOutputVertices = ovcount; + result.m_OutputVertices.resize(static_cast(ovcount)); + result.mNumFaces = hr.mFaceCount; + result.mNumIndices = hr.mIndexCount; + + result.m_Indices.resize(static_cast(hr.mIndexCount)); + + memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount ); + + if ( desc.HasHullFlag(QF_REVERSE_ORDER) ) + { + + const unsigned int *source = &hr.m_Indices[0]; + unsigned int *dest = &result.m_Indices[0]; + + for (unsigned int i=0; i(ovcount)); + result.mNumFaces = hr.mFaceCount; + result.mNumIndices = hr.mIndexCount+hr.mFaceCount; + result.m_Indices.resize(static_cast(result.mNumIndices)); + memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount ); + +// if ( 1 ) + { + const unsigned int *source = &hr.m_Indices[0]; + unsigned int *dest = &result.m_Indices[0]; + for (unsigned int i=0; i bmax[j] ) bmax[j] = p[j]; + } + } + } + + btScalar dx = bmax[0] - bmin[0]; + btScalar dy = bmax[1] - bmin[1]; + btScalar dz = bmax[2] - bmin[2]; + + btVector3 center; + + center[0] = dx*btScalar(0.5) + bmin[0]; + center[1] = dy*btScalar(0.5) + bmin[1]; + center[2] = dz*btScalar(0.5) + bmin[2]; + + if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || svcount < 3 ) + { + + btScalar len = FLT_MAX; + + if ( dx > EPSILON && dx < len ) len = dx; + if ( dy > EPSILON && dy < len ) len = dy; + if ( dz > EPSILON && dz < len ) len = dz; + + if ( len == FLT_MAX ) + { + dx = dy = dz = btScalar(0.01); // one centimeter + } + else + { + if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge. + if ( dy < EPSILON ) dy = len * btScalar(0.05); + if ( dz < EPSILON ) dz = len * btScalar(0.05); + } + + btScalar x1 = center[0] - dx; + btScalar x2 = center[0] + dx; + + btScalar y1 = center[1] - dy; + btScalar y2 = center[1] + dy; + + btScalar z1 = center[2] - dz; + btScalar z2 = center[2] + dz; + + addPoint(vcount,vertices,x1,y1,z1); + addPoint(vcount,vertices,x2,y1,z1); + addPoint(vcount,vertices,x2,y2,z1); + addPoint(vcount,vertices,x1,y2,z1); + addPoint(vcount,vertices,x1,y1,z2); + addPoint(vcount,vertices,x2,y1,z2); + addPoint(vcount,vertices,x2,y2,z2); + addPoint(vcount,vertices,x1,y2,z2); + + return true; // return cube + + + } + else + { + if ( scale ) + { + scale[0] = dx; + scale[1] = dy; + scale[2] = dz; + + recip[0] = 1 / dx; + recip[1] = 1 / dy; + recip[2] = 1 / dz; + + center[0]*=recip[0]; + center[1]*=recip[1]; + center[2]*=recip[2]; + + } + + } + + + + vtx = (const char *) svertices; + + for (unsigned int i=0; igetX(); + btScalar py = p->getY(); + btScalar pz = p->getZ(); + + if ( scale ) + { + px = px*recip[0]; // normalize + py = py*recip[1]; // normalize + pz = pz*recip[2]; // normalize + } + +// if ( 1 ) + { + unsigned int j; + + for (j=0; j dist2 ) + { + v[0] = px; + v[1] = py; + v[2] = pz; + + } + + break; + } + } + + if ( j == vcount ) + { + btVector3& dest = vertices[vcount]; + dest[0] = px; + dest[1] = py; + dest[2] = pz; + vcount++; + } + m_vertexIndexMapping.push_back(j); + } + } + + // ok..now make sure we didn't prune so many vertices it is now invalid. +// if ( 1 ) + { + btScalar bmin[3] = { FLT_MAX, FLT_MAX, FLT_MAX }; + btScalar bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX }; + + for (unsigned int i=0; i bmax[j] ) bmax[j] = p[j]; + } + } + + btScalar dx = bmax[0] - bmin[0]; + btScalar dy = bmax[1] - bmin[1]; + btScalar dz = bmax[2] - bmin[2]; + + if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || vcount < 3) + { + btScalar cx = dx*btScalar(0.5) + bmin[0]; + btScalar cy = dy*btScalar(0.5) + bmin[1]; + btScalar cz = dz*btScalar(0.5) + bmin[2]; + + btScalar len = FLT_MAX; + + if ( dx >= EPSILON && dx < len ) len = dx; + if ( dy >= EPSILON && dy < len ) len = dy; + if ( dz >= EPSILON && dz < len ) len = dz; + + if ( len == FLT_MAX ) + { + dx = dy = dz = btScalar(0.01); // one centimeter + } + else + { + if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge. + if ( dy < EPSILON ) dy = len * btScalar(0.05); + if ( dz < EPSILON ) dz = len * btScalar(0.05); + } + + btScalar x1 = cx - dx; + btScalar x2 = cx + dx; + + btScalar y1 = cy - dy; + btScalar y2 = cy + dy; + + btScalar z1 = cz - dz; + btScalar z2 = cz + dz; + + vcount = 0; // add box + + addPoint(vcount,vertices,x1,y1,z1); + addPoint(vcount,vertices,x2,y1,z1); + addPoint(vcount,vertices,x2,y2,z1); + addPoint(vcount,vertices,x1,y2,z1); + addPoint(vcount,vertices,x1,y1,z2); + addPoint(vcount,vertices,x2,y1,z2); + addPoint(vcount,vertices,x2,y2,z2); + addPoint(vcount,vertices,x1,y2,z2); + + return true; + } + } + + return true; +} + +void HullLibrary::BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount) +{ + btAlignedObjectArraytmpIndices; + tmpIndices.resize(m_vertexIndexMapping.size()); + int i; + + for (i=0;i(vcount)); + memset(&usedIndices[0],0,sizeof(unsigned int)*vcount); + + ocount = 0; + + for (i=0; i= 0 && v < vcount ); + + if ( usedIndices[static_cast(v)] ) // if already remapped + { + indices[i] = usedIndices[static_cast(v)]-1; // index to new array + } + else + { + + indices[i] = ocount; // new index mapping + + overts[ocount][0] = verts[v][0]; // copy old vert to new vert array + overts[ocount][1] = verts[v][1]; + overts[ocount][2] = verts[v][2]; + + for (int k=0;k=0 && ocount <= vcount ); + + usedIndices[static_cast(v)] = ocount; // assign new index remapping + + + } + } + + +} diff --git a/src/LinearMath/btConvexHull.h b/src/LinearMath/btConvexHull.h new file mode 100644 index 0000000..69c52bc --- /dev/null +++ b/src/LinearMath/btConvexHull.h @@ -0,0 +1,241 @@ + +/* +Stan Melax Convex Hull Computation +Copyright (c) 2008 Stan Melax http://www.melax.com/ + +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. +*/ + +///includes modifications/improvements by John Ratcliff, see BringOutYourDead below. + +#ifndef BT_CD_HULL_H +#define BT_CD_HULL_H + +#include "btVector3.h" +#include "btAlignedObjectArray.h" + +typedef btAlignedObjectArray TUIntArray; + +class HullResult +{ +public: + HullResult(void) + { + mPolygons = true; + mNumOutputVertices = 0; + mNumFaces = 0; + mNumIndices = 0; + } + bool mPolygons; // true if indices represents polygons, false indices are triangles + unsigned int mNumOutputVertices; // number of vertices in the output hull + btAlignedObjectArray m_OutputVertices; // array of vertices + unsigned int mNumFaces; // the number of faces produced + unsigned int mNumIndices; // the total number of indices + btAlignedObjectArray m_Indices; // pointer to indices. + +// If triangles, then indices are array indexes into the vertex list. +// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc.. +}; + +enum HullFlag +{ + QF_TRIANGLES = (1<<0), // report results as triangles, not polygons. + QF_REVERSE_ORDER = (1<<1), // reverse order of the triangle indices. + QF_DEFAULT = QF_TRIANGLES +}; + + +class HullDesc +{ +public: + HullDesc(void) + { + mFlags = QF_DEFAULT; + mVcount = 0; + mVertices = 0; + mVertexStride = sizeof(btVector3); + mNormalEpsilon = 0.001f; + mMaxVertices = 4096; // maximum number of points to be considered for a convex hull. + mMaxFaces = 4096; + }; + + HullDesc(HullFlag flag, + unsigned int vcount, + const btVector3 *vertices, + unsigned int stride = sizeof(btVector3)) + { + mFlags = flag; + mVcount = vcount; + mVertices = vertices; + mVertexStride = stride; + mNormalEpsilon = btScalar(0.001); + mMaxVertices = 4096; + } + + bool HasHullFlag(HullFlag flag) const + { + if ( mFlags & flag ) return true; + return false; + } + + void SetHullFlag(HullFlag flag) + { + mFlags|=flag; + } + + void ClearHullFlag(HullFlag flag) + { + mFlags&=~flag; + } + + unsigned int mFlags; // flags to use when generating the convex hull. + unsigned int mVcount; // number of vertices in the input point cloud + const btVector3 *mVertices; // the array of vertices. + unsigned int mVertexStride; // the stride of each vertex, in bytes. + btScalar mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on. + unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull! + unsigned int mMaxFaces; +}; + +enum HullError +{ + QE_OK, // success! + QE_FAIL // failed. +}; + +class btPlane +{ + public: + btVector3 normal; + btScalar dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0 + btPlane(const btVector3 &n,btScalar d):normal(n),dist(d){} + btPlane():normal(),dist(0){} + +}; + + + +class ConvexH +{ + public: + class HalfEdge + { + public: + short ea; // the other half of the edge (index into edges list) + unsigned char v; // the vertex at the start of this edge (index into vertices list) + unsigned char p; // the facet on which this edge lies (index into facets list) + HalfEdge(){} + HalfEdge(short _ea,unsigned char _v, unsigned char _p):ea(_ea),v(_v),p(_p){} + }; + ConvexH() + { + } + ~ConvexH() + { + } + btAlignedObjectArray vertices; + btAlignedObjectArray edges; + btAlignedObjectArray facets; + ConvexH(int vertices_size,int edges_size,int facets_size); +}; + + +class int4 +{ +public: + int x,y,z,w; + int4(){}; + int4(int _x,int _y, int _z,int _w){x=_x;y=_y;z=_z;w=_w;} + const int& operator[](int i) const {return (&x)[i];} + int& operator[](int i) {return (&x)[i];} +}; + +class PHullResult +{ +public: + + PHullResult(void) + { + mVcount = 0; + mIndexCount = 0; + mFaceCount = 0; + mVertices = 0; + } + + unsigned int mVcount; + unsigned int mIndexCount; + unsigned int mFaceCount; + btVector3* mVertices; + TUIntArray m_Indices; +}; + + + +///The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull method. +///The btShapeHull class uses this HullLibrary to create a approximate convex mesh given a general (non-polyhedral) convex shape. +class HullLibrary +{ + + btAlignedObjectArray m_tris; + +public: + + btAlignedObjectArray m_vertexIndexMapping; + + + HullError CreateConvexHull(const HullDesc& desc, // describes the input request + HullResult& result); // contains the resulst + HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it. + +private: + + bool ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit); + + class btHullTriangle* allocateTriangle(int a,int b,int c); + void deAllocateTriangle(btHullTriangle*); + void b2bfix(btHullTriangle* s,btHullTriangle*t); + + void removeb2b(btHullTriangle* s,btHullTriangle*t); + + void checkit(btHullTriangle *t); + + btHullTriangle* extrudable(btScalar epsilon); + + int calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit); + + int calchullgen(btVector3 *verts,int verts_count, int vlimit); + + int4 FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray &allow); + + class ConvexH* ConvexHCrop(ConvexH& convex,const btPlane& slice); + + void extrude(class btHullTriangle* t0,int v); + + ConvexH* test_cube(); + + //BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'. + //After the hull is generated it give you back a set of polygon faces which index the *original* point cloud. + //The thing is, often times, there are many 'dead vertices' in the point cloud that are on longer referenced by the hull. + //The routine 'BringOutYourDead' find only the referenced vertices, copies them to an new buffer, and re-indexes the hull so that it is a minimal representation. + void BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int* indices,unsigned indexcount); + + bool CleanupVertices(unsigned int svcount, + const btVector3* svertices, + unsigned int stride, + unsigned int &vcount, // output number of vertices + btVector3* vertices, // location to store the results. + btScalar normalepsilon, + btVector3& scale); +}; + + +#endif //BT_CD_HULL_H + diff --git a/src/LinearMath/btConvexHullComputer.cpp b/src/LinearMath/btConvexHullComputer.cpp new file mode 100644 index 0000000..b47cb81 --- /dev/null +++ b/src/LinearMath/btConvexHullComputer.cpp @@ -0,0 +1,2751 @@ +/* +Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net + +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 + +#include "btConvexHullComputer.h" +#include "btAlignedObjectArray.h" +#include "btMinMax.h" +#include "btVector3.h" + +#ifdef __GNUC__ + #include +#elif defined(_MSC_VER) + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; +#else + typedef int int32_t; + typedef long long int int64_t; + typedef unsigned int uint32_t; + typedef unsigned long long int uint64_t; +#endif + + +//The definition of USE_X86_64_ASM is moved into the build system. You can enable it manually by commenting out the following lines +//#if (defined(__GNUC__) && defined(__x86_64__) && !defined(__ICL)) // || (defined(__ICL) && defined(_M_X64)) bug in Intel compiler, disable inline assembly +// #define USE_X86_64_ASM +//#endif + + +//#define DEBUG_CONVEX_HULL +//#define SHOW_ITERATIONS + +#if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS) + #include +#endif + +// Convex hull implementation based on Preparata and Hong +// Ole Kniemeyer, MAXON Computer GmbH +class btConvexHullInternal +{ + public: + + class Point64 + { + public: + int64_t x; + int64_t y; + int64_t z; + + Point64(int64_t x, int64_t y, int64_t z): x(x), y(y), z(z) + { + } + + bool isZero() + { + return (x == 0) && (y == 0) && (z == 0); + } + + int64_t dot(const Point64& b) const + { + return x * b.x + y * b.y + z * b.z; + } + }; + + class Point32 + { + public: + int32_t x; + int32_t y; + int32_t z; + int index; + + Point32() + { + } + + Point32(int32_t x, int32_t y, int32_t z): x(x), y(y), z(z), index(-1) + { + } + + bool operator==(const Point32& b) const + { + return (x == b.x) && (y == b.y) && (z == b.z); + } + + bool operator!=(const Point32& b) const + { + return (x != b.x) || (y != b.y) || (z != b.z); + } + + bool isZero() + { + return (x == 0) && (y == 0) && (z == 0); + } + + Point64 cross(const Point32& b) const + { + return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x); + } + + Point64 cross(const Point64& b) const + { + return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x); + } + + int64_t dot(const Point32& b) const + { + return x * b.x + y * b.y + z * b.z; + } + + int64_t dot(const Point64& b) const + { + return x * b.x + y * b.y + z * b.z; + } + + Point32 operator+(const Point32& b) const + { + return Point32(x + b.x, y + b.y, z + b.z); + } + + Point32 operator-(const Point32& b) const + { + return Point32(x - b.x, y - b.y, z - b.z); + } + }; + + class Int128 + { + public: + uint64_t low; + uint64_t high; + + Int128() + { + } + + Int128(uint64_t low, uint64_t high): low(low), high(high) + { + } + + Int128(uint64_t low): low(low), high(0) + { + } + + Int128(int64_t value): low(value), high((value >= 0) ? 0 : (uint64_t) -1LL) + { + } + + static Int128 mul(int64_t a, int64_t b); + + static Int128 mul(uint64_t a, uint64_t b); + + Int128 operator-() const + { + return Int128((uint64_t) -(int64_t)low, ~high + (low == 0)); + } + + Int128 operator+(const Int128& b) const + { +#ifdef USE_X86_64_ASM + Int128 result; + __asm__ ("addq %[bl], %[rl]\n\t" + "adcq %[bh], %[rh]\n\t" + : [rl] "=r" (result.low), [rh] "=r" (result.high) + : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high) + : "cc" ); + return result; +#else + uint64_t lo = low + b.low; + return Int128(lo, high + b.high + (lo < low)); +#endif + } + + Int128 operator-(const Int128& b) const + { +#ifdef USE_X86_64_ASM + Int128 result; + __asm__ ("subq %[bl], %[rl]\n\t" + "sbbq %[bh], %[rh]\n\t" + : [rl] "=r" (result.low), [rh] "=r" (result.high) + : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high) + : "cc" ); + return result; +#else + return *this + -b; +#endif + } + + Int128& operator+=(const Int128& b) + { +#ifdef USE_X86_64_ASM + __asm__ ("addq %[bl], %[rl]\n\t" + "adcq %[bh], %[rh]\n\t" + : [rl] "=r" (low), [rh] "=r" (high) + : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high) + : "cc" ); +#else + uint64_t lo = low + b.low; + if (lo < low) + { + ++high; + } + low = lo; + high += b.high; +#endif + return *this; + } + + Int128& operator++() + { + if (++low == 0) + { + ++high; + } + return *this; + } + + Int128 operator*(int64_t b) const; + + btScalar toScalar() const + { + return ((int64_t) high >= 0) ? btScalar(high) * (btScalar(0x100000000LL) * btScalar(0x100000000LL)) + btScalar(low) + : -(-*this).toScalar(); + } + + int getSign() const + { + return ((int64_t) high < 0) ? -1 : (high || low) ? 1 : 0; + } + + bool operator<(const Int128& b) const + { + return (high < b.high) || ((high == b.high) && (low < b.low)); + } + + int ucmp(const Int128&b) const + { + if (high < b.high) + { + return -1; + } + if (high > b.high) + { + return 1; + } + if (low < b.low) + { + return -1; + } + if (low > b.low) + { + return 1; + } + return 0; + } + }; + + + class Rational64 + { + private: + uint64_t m_numerator; + uint64_t m_denominator; + int sign; + + public: + Rational64(int64_t numerator, int64_t denominator) + { + if (numerator > 0) + { + sign = 1; + m_numerator = (uint64_t) numerator; + } + else if (numerator < 0) + { + sign = -1; + m_numerator = (uint64_t) -numerator; + } + else + { + sign = 0; + m_numerator = 0; + } + if (denominator > 0) + { + m_denominator = (uint64_t) denominator; + } + else if (denominator < 0) + { + sign = -sign; + m_denominator = (uint64_t) -denominator; + } + else + { + m_denominator = 0; + } + } + + bool isNegativeInfinity() const + { + return (sign < 0) && (m_denominator == 0); + } + + bool isNaN() const + { + return (sign == 0) && (m_denominator == 0); + } + + int compare(const Rational64& b) const; + + btScalar toScalar() const + { + return sign * ((m_denominator == 0) ? SIMD_INFINITY : (btScalar) m_numerator / m_denominator); + } + }; + + + class Rational128 + { + private: + Int128 numerator; + Int128 denominator; + int sign; + bool isInt64; + + public: + Rational128(int64_t value) + { + if (value > 0) + { + sign = 1; + this->numerator = value; + } + else if (value < 0) + { + sign = -1; + this->numerator = -value; + } + else + { + sign = 0; + this->numerator = (uint64_t) 0; + } + this->denominator = (uint64_t) 1; + isInt64 = true; + } + + Rational128(const Int128& numerator, const Int128& denominator) + { + sign = numerator.getSign(); + if (sign >= 0) + { + this->numerator = numerator; + } + else + { + this->numerator = -numerator; + } + int dsign = denominator.getSign(); + if (dsign >= 0) + { + this->denominator = denominator; + } + else + { + sign = -sign; + this->denominator = -denominator; + } + isInt64 = false; + } + + int compare(const Rational128& b) const; + + int compare(int64_t b) const; + + btScalar toScalar() const + { + return sign * ((denominator.getSign() == 0) ? SIMD_INFINITY : numerator.toScalar() / denominator.toScalar()); + } + }; + + class PointR128 + { + public: + Int128 x; + Int128 y; + Int128 z; + Int128 denominator; + + PointR128() + { + } + + PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator): x(x), y(y), z(z), denominator(denominator) + { + } + + btScalar xvalue() const + { + return x.toScalar() / denominator.toScalar(); + } + + btScalar yvalue() const + { + return y.toScalar() / denominator.toScalar(); + } + + btScalar zvalue() const + { + return z.toScalar() / denominator.toScalar(); + } + }; + + + class Edge; + class Face; + + class Vertex + { + public: + Vertex* next; + Vertex* prev; + Edge* edges; + Face* firstNearbyFace; + Face* lastNearbyFace; + PointR128 point128; + Point32 point; + int copy; + + Vertex(): next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1) + { + } + +#ifdef DEBUG_CONVEX_HULL + void print() + { + printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z); + } + + void printGraph(); +#endif + + Point32 operator-(const Vertex& b) const + { + return point - b.point; + } + + Rational128 dot(const Point64& b) const + { + return (point.index >= 0) ? Rational128(point.dot(b)) + : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator); + } + + btScalar xvalue() const + { + return (point.index >= 0) ? btScalar(point.x) : point128.xvalue(); + } + + btScalar yvalue() const + { + return (point.index >= 0) ? btScalar(point.y) : point128.yvalue(); + } + + btScalar zvalue() const + { + return (point.index >= 0) ? btScalar(point.z) : point128.zvalue(); + } + + void receiveNearbyFaces(Vertex* src) + { + if (lastNearbyFace) + { + lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace; + } + else + { + firstNearbyFace = src->firstNearbyFace; + } + if (src->lastNearbyFace) + { + lastNearbyFace = src->lastNearbyFace; + } + for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex) + { + btAssert(f->nearbyVertex == src); + f->nearbyVertex = this; + } + src->firstNearbyFace = NULL; + src->lastNearbyFace = NULL; + } + }; + + + class Edge + { + public: + Edge* next; + Edge* prev; + Edge* reverse; + Vertex* target; + Face* face; + int copy; + + ~Edge() + { + next = NULL; + prev = NULL; + reverse = NULL; + target = NULL; + face = NULL; + } + + void link(Edge* n) + { + btAssert(reverse->target == n->reverse->target); + next = n; + n->prev = this; + } + +#ifdef DEBUG_CONVEX_HULL + void print() + { + printf("E%p : %d -> %d, n=%p p=%p (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev, + reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z); + } +#endif + }; + + class Face + { + public: + Face* next; + Vertex* nearbyVertex; + Face* nextWithSameNearbyVertex; + Point32 origin; + Point32 dir0; + Point32 dir1; + + Face(): next(NULL), nearbyVertex(NULL), nextWithSameNearbyVertex(NULL) + { + } + + void init(Vertex* a, Vertex* b, Vertex* c) + { + nearbyVertex = a; + origin = a->point; + dir0 = *b - *a; + dir1 = *c - *a; + if (a->lastNearbyFace) + { + a->lastNearbyFace->nextWithSameNearbyVertex = this; + } + else + { + a->firstNearbyFace = this; + } + a->lastNearbyFace = this; + } + + Point64 getNormal() + { + return dir0.cross(dir1); + } + }; + + template class DMul + { + private: + static uint32_t high(uint64_t value) + { + return (uint32_t) (value >> 32); + } + + static uint32_t low(uint64_t value) + { + return (uint32_t) value; + } + + static uint64_t mul(uint32_t a, uint32_t b) + { + return (uint64_t) a * (uint64_t) b; + } + + static void shlHalf(uint64_t& value) + { + value <<= 32; + } + + static uint64_t high(Int128 value) + { + return value.high; + } + + static uint64_t low(Int128 value) + { + return value.low; + } + + static Int128 mul(uint64_t a, uint64_t b) + { + return Int128::mul(a, b); + } + + static void shlHalf(Int128& value) + { + value.high = value.low; + value.low = 0; + } + + public: + + static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh) + { + UWord p00 = mul(low(a), low(b)); + UWord p01 = mul(low(a), high(b)); + UWord p10 = mul(high(a), low(b)); + UWord p11 = mul(high(a), high(b)); + UWord p0110 = UWord(low(p01)) + UWord(low(p10)); + p11 += high(p01); + p11 += high(p10); + p11 += high(p0110); + shlHalf(p0110); + p00 += p0110; + if (p00 < p0110) + { + ++p11; + } + resLow = p00; + resHigh = p11; + } + }; + + private: + + class IntermediateHull + { + public: + Vertex* minXy; + Vertex* maxXy; + Vertex* minYx; + Vertex* maxYx; + + IntermediateHull(): minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL) + { + } + + void print(); + }; + + enum Orientation {NONE, CLOCKWISE, COUNTER_CLOCKWISE}; + + template class PoolArray + { + private: + T* array; + int size; + + public: + PoolArray* next; + + PoolArray(int size): size(size), next(NULL) + { + array = (T*) btAlignedAlloc(sizeof(T) * size, 16); + } + + ~PoolArray() + { + btAlignedFree(array); + } + + T* init() + { + T* o = array; + for (int i = 0; i < size; i++, o++) + { + o->next = (i+1 < size) ? o + 1 : NULL; + } + return array; + } + }; + + template class Pool + { + private: + PoolArray* arrays; + PoolArray* nextArray; + T* freeObjects; + int arraySize; + + public: + Pool(): arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256) + { + } + + ~Pool() + { + while (arrays) + { + PoolArray* p = arrays; + arrays = p->next; + p->~PoolArray(); + btAlignedFree(p); + } + } + + void reset() + { + nextArray = arrays; + freeObjects = NULL; + } + + void setArraySize(int arraySize) + { + this->arraySize = arraySize; + } + + T* newObject() + { + T* o = freeObjects; + if (!o) + { + PoolArray* p = nextArray; + if (p) + { + nextArray = p->next; + } + else + { + p = new(btAlignedAlloc(sizeof(PoolArray), 16)) PoolArray(arraySize); + p->next = arrays; + arrays = p; + } + o = p->init(); + } + freeObjects = o->next; + return new(o) T(); + }; + + void freeObject(T* object) + { + object->~T(); + object->next = freeObjects; + freeObjects = object; + } + }; + + btVector3 scaling; + btVector3 center; + Pool vertexPool; + Pool edgePool; + Pool facePool; + btAlignedObjectArray originalVertices; + int mergeStamp; + int minAxis; + int medAxis; + int maxAxis; + int usedEdgePairs; + int maxUsedEdgePairs; + + static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t); + Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot); + void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1); + + Edge* newEdgePair(Vertex* from, Vertex* to); + + void removeEdgePair(Edge* edge) + { + Edge* n = edge->next; + Edge* r = edge->reverse; + + btAssert(edge->target && r->target); + + if (n != edge) + { + n->prev = edge->prev; + edge->prev->next = n; + r->target->edges = n; + } + else + { + r->target->edges = NULL; + } + + n = r->next; + + if (n != r) + { + n->prev = r->prev; + r->prev->next = n; + edge->target->edges = n; + } + else + { + edge->target->edges = NULL; + } + + edgePool.freeObject(edge); + edgePool.freeObject(r); + usedEdgePairs--; + } + + void computeInternal(int start, int end, IntermediateHull& result); + + bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1); + + void merge(IntermediateHull& h0, IntermediateHull& h1); + + btVector3 toBtVector(const Point32& v); + + btVector3 getBtNormal(Face* face); + + bool shiftFace(Face* face, btScalar amount, btAlignedObjectArray stack); + + public: + Vertex* vertexList; + + void compute(const void* coords, bool doubleCoords, int stride, int count); + + btVector3 getCoordinates(const Vertex* v); + + btScalar shrink(btScalar amount, btScalar clampAmount); +}; + + +btConvexHullInternal::Int128 btConvexHullInternal::Int128::operator*(int64_t b) const +{ + bool negative = (int64_t) high < 0; + Int128 a = negative ? -*this : *this; + if (b < 0) + { + negative = !negative; + b = -b; + } + Int128 result = mul(a.low, (uint64_t) b); + result.high += a.high * (uint64_t) b; + return negative ? -result : result; +} + +btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(int64_t a, int64_t b) +{ + Int128 result; + +#ifdef USE_X86_64_ASM + __asm__ ("imulq %[b]" + : "=a" (result.low), "=d" (result.high) + : "0"(a), [b] "r"(b) + : "cc" ); + return result; + +#else + bool negative = a < 0; + if (negative) + { + a = -a; + } + if (b < 0) + { + negative = !negative; + b = -b; + } + DMul::mul((uint64_t) a, (uint64_t) b, result.low, result.high); + return negative ? -result : result; +#endif +} + +btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(uint64_t a, uint64_t b) +{ + Int128 result; + +#ifdef USE_X86_64_ASM + __asm__ ("mulq %[b]" + : "=a" (result.low), "=d" (result.high) + : "0"(a), [b] "r"(b) + : "cc" ); + +#else + DMul::mul(a, b, result.low, result.high); +#endif + + return result; +} + +int btConvexHullInternal::Rational64::compare(const Rational64& b) const +{ + if (sign != b.sign) + { + return sign - b.sign; + } + else if (sign == 0) + { + return 0; + } + + // return (numerator * b.denominator > b.numerator * denominator) ? sign : (numerator * b.denominator < b.numerator * denominator) ? -sign : 0; + +#ifdef USE_X86_64_ASM + + int result; + int64_t tmp; + int64_t dummy; + __asm__ ("mulq %[bn]\n\t" + "movq %%rax, %[tmp]\n\t" + "movq %%rdx, %%rbx\n\t" + "movq %[tn], %%rax\n\t" + "mulq %[bd]\n\t" + "subq %[tmp], %%rax\n\t" + "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator" + "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise + "orq %%rdx, %%rax\n\t" + "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero + "decb %%bh\n\t" // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference) + "shll $16, %%ebx\n\t" // ebx has same sign as difference + : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy) + : "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator) + : "%rdx", "cc" ); + return result ? result ^ sign // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero) + // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero) + : 0; + +#else + + return sign * Int128::mul(m_numerator, b.m_denominator).ucmp(Int128::mul(m_denominator, b.m_numerator)); + +#endif +} + +int btConvexHullInternal::Rational128::compare(const Rational128& b) const +{ + if (sign != b.sign) + { + return sign - b.sign; + } + else if (sign == 0) + { + return 0; + } + if (isInt64) + { + return -b.compare(sign * (int64_t) numerator.low); + } + + Int128 nbdLow, nbdHigh, dbnLow, dbnHigh; + DMul::mul(numerator, b.denominator, nbdLow, nbdHigh); + DMul::mul(denominator, b.numerator, dbnLow, dbnHigh); + + int cmp = nbdHigh.ucmp(dbnHigh); + if (cmp) + { + return cmp * sign; + } + return nbdLow.ucmp(dbnLow) * sign; +} + +int btConvexHullInternal::Rational128::compare(int64_t b) const +{ + if (isInt64) + { + int64_t a = sign * (int64_t) numerator.low; + return (a > b) ? 1 : (a < b) ? -1 : 0; + } + if (b > 0) + { + if (sign <= 0) + { + return -1; + } + } + else if (b < 0) + { + if (sign >= 0) + { + return 1; + } + b = -b; + } + else + { + return sign; + } + + return numerator.ucmp(denominator * b) * sign; +} + + +btConvexHullInternal::Edge* btConvexHullInternal::newEdgePair(Vertex* from, Vertex* to) +{ + btAssert(from && to); + Edge* e = edgePool.newObject(); + Edge* r = edgePool.newObject(); + e->reverse = r; + r->reverse = e; + e->copy = mergeStamp; + r->copy = mergeStamp; + e->target = to; + r->target = from; + e->face = NULL; + r->face = NULL; + usedEdgePairs++; + if (usedEdgePairs > maxUsedEdgePairs) + { + maxUsedEdgePairs = usedEdgePairs; + } + return e; +} + +bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1) +{ + Vertex* v0 = h0.maxYx; + Vertex* v1 = h1.minYx; + if ((v0->point.x == v1->point.x) && (v0->point.y == v1->point.y)) + { + btAssert(v0->point.z < v1->point.z); + Vertex* v1p = v1->prev; + if (v1p == v1) + { + c0 = v0; + if (v1->edges) + { + btAssert(v1->edges->next == v1->edges); + v1 = v1->edges->target; + btAssert(v1->edges->next == v1->edges); + } + c1 = v1; + return false; + } + Vertex* v1n = v1->next; + v1p->next = v1n; + v1n->prev = v1p; + if (v1 == h1.minXy) + { + if ((v1n->point.x < v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y < v1p->point.y))) + { + h1.minXy = v1n; + } + else + { + h1.minXy = v1p; + } + } + if (v1 == h1.maxXy) + { + if ((v1n->point.x > v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y > v1p->point.y))) + { + h1.maxXy = v1n; + } + else + { + h1.maxXy = v1p; + } + } + } + + v0 = h0.maxXy; + v1 = h1.maxXy; + Vertex* v00 = NULL; + Vertex* v10 = NULL; + int32_t sign = 1; + + for (int side = 0; side <= 1; side++) + { + int32_t dx = (v1->point.x - v0->point.x) * sign; + if (dx > 0) + { + while (true) + { + int32_t dy = v1->point.y - v0->point.y; + + Vertex* w0 = side ? v0->next : v0->prev; + if (w0 != v0) + { + int32_t dx0 = (w0->point.x - v0->point.x) * sign; + int32_t dy0 = w0->point.y - v0->point.y; + if ((dy0 <= 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx <= dy * dx0)))) + { + v0 = w0; + dx = (v1->point.x - v0->point.x) * sign; + continue; + } + } + + Vertex* w1 = side ? v1->next : v1->prev; + if (w1 != v1) + { + int32_t dx1 = (w1->point.x - v1->point.x) * sign; + int32_t dy1 = w1->point.y - v1->point.y; + int32_t dxn = (w1->point.x - v0->point.x) * sign; + if ((dxn > 0) && (dy1 < 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx < dy * dx1)))) + { + v1 = w1; + dx = dxn; + continue; + } + } + + break; + } + } + else if (dx < 0) + { + while (true) + { + int32_t dy = v1->point.y - v0->point.y; + + Vertex* w1 = side ? v1->prev : v1->next; + if (w1 != v1) + { + int32_t dx1 = (w1->point.x - v1->point.x) * sign; + int32_t dy1 = w1->point.y - v1->point.y; + if ((dy1 >= 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx <= dy * dx1)))) + { + v1 = w1; + dx = (v1->point.x - v0->point.x) * sign; + continue; + } + } + + Vertex* w0 = side ? v0->prev : v0->next; + if (w0 != v0) + { + int32_t dx0 = (w0->point.x - v0->point.x) * sign; + int32_t dy0 = w0->point.y - v0->point.y; + int32_t dxn = (v1->point.x - w0->point.x) * sign; + if ((dxn < 0) && (dy0 > 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx < dy * dx0)))) + { + v0 = w0; + dx = dxn; + continue; + } + } + + break; + } + } + else + { + int32_t x = v0->point.x; + int32_t y0 = v0->point.y; + Vertex* w0 = v0; + Vertex* t; + while (((t = side ? w0->next : w0->prev) != v0) && (t->point.x == x) && (t->point.y <= y0)) + { + w0 = t; + y0 = t->point.y; + } + v0 = w0; + + int32_t y1 = v1->point.y; + Vertex* w1 = v1; + while (((t = side ? w1->prev : w1->next) != v1) && (t->point.x == x) && (t->point.y >= y1)) + { + w1 = t; + y1 = t->point.y; + } + v1 = w1; + } + + if (side == 0) + { + v00 = v0; + v10 = v1; + + v0 = h0.minXy; + v1 = h1.minXy; + sign = -1; + } + } + + v0->prev = v1; + v1->next = v0; + + v00->next = v10; + v10->prev = v00; + + if (h1.minXy->point.x < h0.minXy->point.x) + { + h0.minXy = h1.minXy; + } + if (h1.maxXy->point.x >= h0.maxXy->point.x) + { + h0.maxXy = h1.maxXy; + } + + h0.maxYx = h1.maxYx; + + c0 = v00; + c1 = v10; + + return true; +} + +void btConvexHullInternal::computeInternal(int start, int end, IntermediateHull& result) +{ + int n = end - start; + switch (n) + { + case 0: + result.minXy = NULL; + result.maxXy = NULL; + result.minYx = NULL; + result.maxYx = NULL; + return; + case 2: + { + Vertex* v = originalVertices[start]; + Vertex* w = v + 1; + if (v->point != w->point) + { + int32_t dx = v->point.x - w->point.x; + int32_t dy = v->point.y - w->point.y; + + if ((dx == 0) && (dy == 0)) + { + if (v->point.z > w->point.z) + { + Vertex* t = w; + w = v; + v = t; + } + btAssert(v->point.z < w->point.z); + v->next = v; + v->prev = v; + result.minXy = v; + result.maxXy = v; + result.minYx = v; + result.maxYx = v; + } + else + { + v->next = w; + v->prev = w; + w->next = v; + w->prev = v; + + if ((dx < 0) || ((dx == 0) && (dy < 0))) + { + result.minXy = v; + result.maxXy = w; + } + else + { + result.minXy = w; + result.maxXy = v; + } + + if ((dy < 0) || ((dy == 0) && (dx < 0))) + { + result.minYx = v; + result.maxYx = w; + } + else + { + result.minYx = w; + result.maxYx = v; + } + } + + Edge* e = newEdgePair(v, w); + e->link(e); + v->edges = e; + + e = e->reverse; + e->link(e); + w->edges = e; + + return; + } + } + // lint -fallthrough + case 1: + { + Vertex* v = originalVertices[start]; + v->edges = NULL; + v->next = v; + v->prev = v; + + result.minXy = v; + result.maxXy = v; + result.minYx = v; + result.maxYx = v; + + return; + } + } + + int split0 = start + n / 2; + Point32 p = originalVertices[split0-1]->point; + int split1 = split0; + while ((split1 < end) && (originalVertices[split1]->point == p)) + { + split1++; + } + computeInternal(start, split0, result); + IntermediateHull hull1; + computeInternal(split1, end, hull1); +#ifdef DEBUG_CONVEX_HULL + printf("\n\nMerge\n"); + result.print(); + hull1.print(); +#endif + merge(result, hull1); +#ifdef DEBUG_CONVEX_HULL + printf("\n Result\n"); + result.print(); +#endif +} + +#ifdef DEBUG_CONVEX_HULL +void btConvexHullInternal::IntermediateHull::print() +{ + printf(" Hull\n"); + for (Vertex* v = minXy; v; ) + { + printf(" "); + v->print(); + if (v == maxXy) + { + printf(" maxXy"); + } + if (v == minYx) + { + printf(" minYx"); + } + if (v == maxYx) + { + printf(" maxYx"); + } + if (v->next->prev != v) + { + printf(" Inconsistency"); + } + printf("\n"); + v = v->next; + if (v == minXy) + { + break; + } + } + if (minXy) + { + minXy->copy = (minXy->copy == -1) ? -2 : -1; + minXy->printGraph(); + } +} + +void btConvexHullInternal::Vertex::printGraph() +{ + print(); + printf("\nEdges\n"); + Edge* e = edges; + if (e) + { + do + { + e->print(); + printf("\n"); + e = e->next; + } while (e != edges); + do + { + Vertex* v = e->target; + if (v->copy != copy) + { + v->copy = copy; + v->printGraph(); + } + e = e->next; + } while (e != edges); + } +} +#endif + +btConvexHullInternal::Orientation btConvexHullInternal::getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t) +{ + btAssert(prev->reverse->target == next->reverse->target); + if (prev->next == next) + { + if (prev->prev == next) + { + Point64 n = t.cross(s); + Point64 m = (*prev->target - *next->reverse->target).cross(*next->target - *next->reverse->target); + btAssert(!m.isZero()); + int64_t dot = n.dot(m); + btAssert(dot != 0); + return (dot > 0) ? COUNTER_CLOCKWISE : CLOCKWISE; + } + return COUNTER_CLOCKWISE; + } + else if (prev->prev == next) + { + return CLOCKWISE; + } + else + { + return NONE; + } +} + +btConvexHullInternal::Edge* btConvexHullInternal::findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot) +{ + Edge* minEdge = NULL; + +#ifdef DEBUG_CONVEX_HULL + printf("find max edge for %d\n", start->point.index); +#endif + Edge* e = start->edges; + if (e) + { + do + { + if (e->copy > mergeStamp) + { + Point32 t = *e->target - *start; + Rational64 cot(t.dot(sxrxs), t.dot(rxs)); +#ifdef DEBUG_CONVEX_HULL + printf(" Angle is %f (%d) for ", (float) btAtan(cot.toScalar()), (int) cot.isNaN()); + e->print(); +#endif + if (cot.isNaN()) + { + btAssert(ccw ? (t.dot(s) < 0) : (t.dot(s) > 0)); + } + else + { + int cmp; + if (minEdge == NULL) + { + minCot = cot; + minEdge = e; + } + else if ((cmp = cot.compare(minCot)) < 0) + { + minCot = cot; + minEdge = e; + } + else if ((cmp == 0) && (ccw == (getOrientation(minEdge, e, s, t) == COUNTER_CLOCKWISE))) + { + minEdge = e; + } + } +#ifdef DEBUG_CONVEX_HULL + printf("\n"); +#endif + } + e = e->next; + } while (e != start->edges); + } + return minEdge; +} + +void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1) +{ + Edge* start0 = e0; + Edge* start1 = e1; + Point32 et0 = start0 ? start0->target->point : c0->point; + Point32 et1 = start1 ? start1->target->point : c1->point; + Point32 s = c1->point - c0->point; + Point64 normal = ((start0 ? start0 : start1)->target->point - c0->point).cross(s); + int64_t dist = c0->point.dot(normal); + btAssert(!start1 || (start1->target->point.dot(normal) == dist)); + Point64 perp = s.cross(normal); + btAssert(!perp.isZero()); + +#ifdef DEBUG_CONVEX_HULL + printf(" Advancing %d %d (%p %p, %d %d)\n", c0->point.index, c1->point.index, start0, start1, start0 ? start0->target->point.index : -1, start1 ? start1->target->point.index : -1); +#endif + + int64_t maxDot0 = et0.dot(perp); + if (e0) + { + while (e0->target != stop0) + { + Edge* e = e0->reverse->prev; + if (e->target->point.dot(normal) < dist) + { + break; + } + btAssert(e->target->point.dot(normal) == dist); + if (e->copy == mergeStamp) + { + break; + } + int64_t dot = e->target->point.dot(perp); + if (dot <= maxDot0) + { + break; + } + maxDot0 = dot; + e0 = e; + et0 = e->target->point; + } + } + + int64_t maxDot1 = et1.dot(perp); + if (e1) + { + while (e1->target != stop1) + { + Edge* e = e1->reverse->next; + if (e->target->point.dot(normal) < dist) + { + break; + } + btAssert(e->target->point.dot(normal) == dist); + if (e->copy == mergeStamp) + { + break; + } + int64_t dot = e->target->point.dot(perp); + if (dot <= maxDot1) + { + break; + } + maxDot1 = dot; + e1 = e; + et1 = e->target->point; + } + } + +#ifdef DEBUG_CONVEX_HULL + printf(" Starting at %d %d\n", et0.index, et1.index); +#endif + + int64_t dx = maxDot1 - maxDot0; + if (dx > 0) + { + while (true) + { + int64_t dy = (et1 - et0).dot(s); + + if (e0 && (e0->target != stop0)) + { + Edge* f0 = e0->next->reverse; + if (f0->copy > mergeStamp) + { + int64_t dx0 = (f0->target->point - et0).dot(perp); + int64_t dy0 = (f0->target->point - et0).dot(s); + if ((dx0 == 0) ? (dy0 < 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) >= 0))) + { + et0 = f0->target->point; + dx = (et1 - et0).dot(perp); + e0 = (e0 == start0) ? NULL : f0; + continue; + } + } + } + + if (e1 && (e1->target != stop1)) + { + Edge* f1 = e1->reverse->next; + if (f1->copy > mergeStamp) + { + Point32 d1 = f1->target->point - et1; + if (d1.dot(normal) == 0) + { + int64_t dx1 = d1.dot(perp); + int64_t dy1 = d1.dot(s); + int64_t dxn = (f1->target->point - et0).dot(perp); + if ((dxn > 0) && ((dx1 == 0) ? (dy1 < 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) > 0)))) + { + e1 = f1; + et1 = e1->target->point; + dx = dxn; + continue; + } + } + else + { + btAssert((e1 == start1) && (d1.dot(normal) < 0)); + } + } + } + + break; + } + } + else if (dx < 0) + { + while (true) + { + int64_t dy = (et1 - et0).dot(s); + + if (e1 && (e1->target != stop1)) + { + Edge* f1 = e1->prev->reverse; + if (f1->copy > mergeStamp) + { + int64_t dx1 = (f1->target->point - et1).dot(perp); + int64_t dy1 = (f1->target->point - et1).dot(s); + if ((dx1 == 0) ? (dy1 > 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) <= 0))) + { + et1 = f1->target->point; + dx = (et1 - et0).dot(perp); + e1 = (e1 == start1) ? NULL : f1; + continue; + } + } + } + + if (e0 && (e0->target != stop0)) + { + Edge* f0 = e0->reverse->prev; + if (f0->copy > mergeStamp) + { + Point32 d0 = f0->target->point - et0; + if (d0.dot(normal) == 0) + { + int64_t dx0 = d0.dot(perp); + int64_t dy0 = d0.dot(s); + int64_t dxn = (et1 - f0->target->point).dot(perp); + if ((dxn < 0) && ((dx0 == 0) ? (dy0 > 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) < 0)))) + { + e0 = f0; + et0 = e0->target->point; + dx = dxn; + continue; + } + } + else + { + btAssert((e0 == start0) && (d0.dot(normal) < 0)); + } + } + } + + break; + } + } +#ifdef DEBUG_CONVEX_HULL + printf(" Advanced edges to %d %d\n", et0.index, et1.index); +#endif +} + + +void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1) +{ + if (!h1.maxXy) + { + return; + } + if (!h0.maxXy) + { + h0 = h1; + return; + } + + mergeStamp--; + + Vertex* c0 = NULL; + Edge* toPrev0 = NULL; + Edge* firstNew0 = NULL; + Edge* pendingHead0 = NULL; + Edge* pendingTail0 = NULL; + Vertex* c1 = NULL; + Edge* toPrev1 = NULL; + Edge* firstNew1 = NULL; + Edge* pendingHead1 = NULL; + Edge* pendingTail1 = NULL; + Point32 prevPoint; + + if (mergeProjection(h0, h1, c0, c1)) + { + Point32 s = *c1 - *c0; + Point64 normal = Point32(0, 0, -1).cross(s); + Point64 t = s.cross(normal); + btAssert(!t.isZero()); + + Edge* e = c0->edges; + Edge* start0 = NULL; + if (e) + { + do + { + int64_t dot = (*e->target - *c0).dot(normal); + btAssert(dot <= 0); + if ((dot == 0) && ((*e->target - *c0).dot(t) > 0)) + { + if (!start0 || (getOrientation(start0, e, s, Point32(0, 0, -1)) == CLOCKWISE)) + { + start0 = e; + } + } + e = e->next; + } while (e != c0->edges); + } + + e = c1->edges; + Edge* start1 = NULL; + if (e) + { + do + { + int64_t dot = (*e->target - *c1).dot(normal); + btAssert(dot <= 0); + if ((dot == 0) && ((*e->target - *c1).dot(t) > 0)) + { + if (!start1 || (getOrientation(start1, e, s, Point32(0, 0, -1)) == COUNTER_CLOCKWISE)) + { + start1 = e; + } + } + e = e->next; + } while (e != c1->edges); + } + + if (start0 || start1) + { + findEdgeForCoplanarFaces(c0, c1, start0, start1, NULL, NULL); + if (start0) + { + c0 = start0->target; + } + if (start1) + { + c1 = start1->target; + } + } + + prevPoint = c1->point; + prevPoint.z++; + } + else + { + prevPoint = c1->point; + prevPoint.x++; + } + + Vertex* first0 = c0; + Vertex* first1 = c1; + bool firstRun = true; + + while (true) + { + Point32 s = *c1 - *c0; + Point32 r = prevPoint - c0->point; + Point64 rxs = r.cross(s); + Point64 sxrxs = s.cross(rxs); + +#ifdef DEBUG_CONVEX_HULL + printf("\n Checking %d %d\n", c0->point.index, c1->point.index); +#endif + Rational64 minCot0(0, 0); + Edge* min0 = findMaxAngle(false, c0, s, rxs, sxrxs, minCot0); + Rational64 minCot1(0, 0); + Edge* min1 = findMaxAngle(true, c1, s, rxs, sxrxs, minCot1); + if (!min0 && !min1) + { + Edge* e = newEdgePair(c0, c1); + e->link(e); + c0->edges = e; + + e = e->reverse; + e->link(e); + c1->edges = e; + return; + } + else + { + int cmp = !min0 ? 1 : !min1 ? -1 : minCot0.compare(minCot1); +#ifdef DEBUG_CONVEX_HULL + printf(" -> Result %d\n", cmp); +#endif + if (firstRun || ((cmp >= 0) ? !minCot1.isNegativeInfinity() : !minCot0.isNegativeInfinity())) + { + Edge* e = newEdgePair(c0, c1); + if (pendingTail0) + { + pendingTail0->prev = e; + } + else + { + pendingHead0 = e; + } + e->next = pendingTail0; + pendingTail0 = e; + + e = e->reverse; + if (pendingTail1) + { + pendingTail1->next = e; + } + else + { + pendingHead1 = e; + } + e->prev = pendingTail1; + pendingTail1 = e; + } + + Edge* e0 = min0; + Edge* e1 = min1; + +#ifdef DEBUG_CONVEX_HULL + printf(" Found min edges to %d %d\n", e0 ? e0->target->point.index : -1, e1 ? e1->target->point.index : -1); +#endif + + if (cmp == 0) + { + findEdgeForCoplanarFaces(c0, c1, e0, e1, NULL, NULL); + } + + if ((cmp >= 0) && e1) + { + if (toPrev1) + { + for (Edge* e = toPrev1->next, *n = NULL; e != min1; e = n) + { + n = e->next; + removeEdgePair(e); + } + } + + if (pendingTail1) + { + if (toPrev1) + { + toPrev1->link(pendingHead1); + } + else + { + min1->prev->link(pendingHead1); + firstNew1 = pendingHead1; + } + pendingTail1->link(min1); + pendingHead1 = NULL; + pendingTail1 = NULL; + } + else if (!toPrev1) + { + firstNew1 = min1; + } + + prevPoint = c1->point; + c1 = e1->target; + toPrev1 = e1->reverse; + } + + if ((cmp <= 0) && e0) + { + if (toPrev0) + { + for (Edge* e = toPrev0->prev, *n = NULL; e != min0; e = n) + { + n = e->prev; + removeEdgePair(e); + } + } + + if (pendingTail0) + { + if (toPrev0) + { + pendingHead0->link(toPrev0); + } + else + { + pendingHead0->link(min0->next); + firstNew0 = pendingHead0; + } + min0->link(pendingTail0); + pendingHead0 = NULL; + pendingTail0 = NULL; + } + else if (!toPrev0) + { + firstNew0 = min0; + } + + prevPoint = c0->point; + c0 = e0->target; + toPrev0 = e0->reverse; + } + } + + if ((c0 == first0) && (c1 == first1)) + { + if (toPrev0 == NULL) + { + pendingHead0->link(pendingTail0); + c0->edges = pendingTail0; + } + else + { + for (Edge* e = toPrev0->prev, *n = NULL; e != firstNew0; e = n) + { + n = e->prev; + removeEdgePair(e); + } + if (pendingTail0) + { + pendingHead0->link(toPrev0); + firstNew0->link(pendingTail0); + } + } + + if (toPrev1 == NULL) + { + pendingTail1->link(pendingHead1); + c1->edges = pendingTail1; + } + else + { + for (Edge* e = toPrev1->next, *n = NULL; e != firstNew1; e = n) + { + n = e->next; + removeEdgePair(e); + } + if (pendingTail1) + { + toPrev1->link(pendingHead1); + pendingTail1->link(firstNew1); + } + } + + return; + } + + firstRun = false; + } +} + + +static bool pointCmp(const btConvexHullInternal::Point32& p, const btConvexHullInternal::Point32& q) +{ + return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z)))); +} + +void btConvexHullInternal::compute(const void* coords, bool doubleCoords, int stride, int count) +{ + btVector3 min(btScalar(1e30), btScalar(1e30), btScalar(1e30)), max(btScalar(-1e30), btScalar(-1e30), btScalar(-1e30)); + const char* ptr = (const char*) coords; + if (doubleCoords) + { + for (int i = 0; i < count; i++) + { + const double* v = (const double*) ptr; + btVector3 p((btScalar) v[0], (btScalar) v[1], (btScalar) v[2]); + ptr += stride; + min.setMin(p); + max.setMax(p); + } + } + else + { + for (int i = 0; i < count; i++) + { + const float* v = (const float*) ptr; + btVector3 p(v[0], v[1], v[2]); + ptr += stride; + min.setMin(p); + max.setMax(p); + } + } + + btVector3 s = max - min; + maxAxis = s.maxAxis(); + minAxis = s.minAxis(); + if (minAxis == maxAxis) + { + minAxis = (maxAxis + 1) % 3; + } + medAxis = 3 - maxAxis - minAxis; + + s /= btScalar(10216); + if (((medAxis + 1) % 3) != maxAxis) + { + s *= -1; + } + scaling = s; + + if (s[0] != 0) + { + s[0] = btScalar(1) / s[0]; + } + if (s[1] != 0) + { + s[1] = btScalar(1) / s[1]; + } + if (s[2] != 0) + { + s[2] = btScalar(1) / s[2]; + } + + center = (min + max) * btScalar(0.5); + + btAlignedObjectArray points; + points.resize(count); + ptr = (const char*) coords; + if (doubleCoords) + { + for (int i = 0; i < count; i++) + { + const double* v = (const double*) ptr; + btVector3 p((btScalar) v[0], (btScalar) v[1], (btScalar) v[2]); + ptr += stride; + p = (p - center) * s; + points[i].x = (int32_t) p[medAxis]; + points[i].y = (int32_t) p[maxAxis]; + points[i].z = (int32_t) p[minAxis]; + points[i].index = i; + } + } + else + { + for (int i = 0; i < count; i++) + { + const float* v = (const float*) ptr; + btVector3 p(v[0], v[1], v[2]); + ptr += stride; + p = (p - center) * s; + points[i].x = (int32_t) p[medAxis]; + points[i].y = (int32_t) p[maxAxis]; + points[i].z = (int32_t) p[minAxis]; + points[i].index = i; + } + } + points.quickSort(pointCmp); + + vertexPool.reset(); + vertexPool.setArraySize(count); + originalVertices.resize(count); + for (int i = 0; i < count; i++) + { + Vertex* v = vertexPool.newObject(); + v->edges = NULL; + v->point = points[i]; + v->copy = -1; + originalVertices[i] = v; + } + + points.clear(); + + edgePool.reset(); + edgePool.setArraySize(6 * count); + + usedEdgePairs = 0; + maxUsedEdgePairs = 0; + + mergeStamp = -3; + + IntermediateHull hull; + computeInternal(0, count, hull); + vertexList = hull.minXy; +#ifdef DEBUG_CONVEX_HULL + printf("max. edges %d (3v = %d)", maxUsedEdgePairs, 3 * count); +#endif +} + +btVector3 btConvexHullInternal::toBtVector(const Point32& v) +{ + btVector3 p; + p[medAxis] = btScalar(v.x); + p[maxAxis] = btScalar(v.y); + p[minAxis] = btScalar(v.z); + return p * scaling; +} + +btVector3 btConvexHullInternal::getBtNormal(Face* face) +{ + return toBtVector(face->dir0).cross(toBtVector(face->dir1)).normalized(); +} + +btVector3 btConvexHullInternal::getCoordinates(const Vertex* v) +{ + btVector3 p; + p[medAxis] = v->xvalue(); + p[maxAxis] = v->yvalue(); + p[minAxis] = v->zvalue(); + return p * scaling + center; +} + +btScalar btConvexHullInternal::shrink(btScalar amount, btScalar clampAmount) +{ + if (!vertexList) + { + return 0; + } + int stamp = --mergeStamp; + btAlignedObjectArray stack; + vertexList->copy = stamp; + stack.push_back(vertexList); + btAlignedObjectArray faces; + + Point32 ref = vertexList->point; + Int128 hullCenterX(0, 0); + Int128 hullCenterY(0, 0); + Int128 hullCenterZ(0, 0); + Int128 volume(0, 0); + + while (stack.size() > 0) + { + Vertex* v = stack[stack.size() - 1]; + stack.pop_back(); + Edge* e = v->edges; + if (e) + { + do + { + if (e->target->copy != stamp) + { + e->target->copy = stamp; + stack.push_back(e->target); + } + if (e->copy != stamp) + { + Face* face = facePool.newObject(); + face->init(e->target, e->reverse->prev->target, v); + faces.push_back(face); + Edge* f = e; + + Vertex* a = NULL; + Vertex* b = NULL; + do + { + if (a && b) + { + int64_t vol = (v->point - ref).dot((a->point - ref).cross(b->point - ref)); + btAssert(vol >= 0); + Point32 c = v->point + a->point + b->point + ref; + hullCenterX += vol * c.x; + hullCenterY += vol * c.y; + hullCenterZ += vol * c.z; + volume += vol; + } + + btAssert(f->copy != stamp); + f->copy = stamp; + f->face = face; + + a = b; + b = f->target; + + f = f->reverse->prev; + } while (f != e); + } + e = e->next; + } while (e != v->edges); + } + } + + if (volume.getSign() <= 0) + { + return 0; + } + + btVector3 hullCenter; + hullCenter[medAxis] = hullCenterX.toScalar(); + hullCenter[maxAxis] = hullCenterY.toScalar(); + hullCenter[minAxis] = hullCenterZ.toScalar(); + hullCenter /= 4 * volume.toScalar(); + hullCenter *= scaling; + + int faceCount = faces.size(); + + if (clampAmount > 0) + { + btScalar minDist = SIMD_INFINITY; + for (int i = 0; i < faceCount; i++) + { + btVector3 normal = getBtNormal(faces[i]); + btScalar dist = normal.dot(toBtVector(faces[i]->origin) - hullCenter); + if (dist < minDist) + { + minDist = dist; + } + } + + if (minDist <= 0) + { + return 0; + } + + amount = btMin(amount, minDist * clampAmount); + } + + unsigned int seed = 243703; + for (int i = 0; i < faceCount; i++, seed = 1664525 * seed + 1013904223) + { + btSwap(faces[i], faces[seed % faceCount]); + } + + for (int i = 0; i < faceCount; i++) + { + if (!shiftFace(faces[i], amount, stack)) + { + return -amount; + } + } + + return amount; +} + +bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjectArray stack) +{ + btVector3 origShift = getBtNormal(face) * -amount; + if (scaling[0] != 0) + { + origShift[0] /= scaling[0]; + } + if (scaling[1] != 0) + { + origShift[1] /= scaling[1]; + } + if (scaling[2] != 0) + { + origShift[2] /= scaling[2]; + } + Point32 shift((int32_t) origShift[medAxis], (int32_t) origShift[maxAxis], (int32_t) origShift[minAxis]); + if (shift.isZero()) + { + return true; + } + Point64 normal = face->getNormal(); +#ifdef DEBUG_CONVEX_HULL + printf("\nShrinking face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n", + face->origin.x, face->origin.y, face->origin.z, face->dir0.x, face->dir0.y, face->dir0.z, face->dir1.x, face->dir1.y, face->dir1.z, shift.x, shift.y, shift.z); +#endif + int64_t origDot = face->origin.dot(normal); + Point32 shiftedOrigin = face->origin + shift; + int64_t shiftedDot = shiftedOrigin.dot(normal); + btAssert(shiftedDot <= origDot); + if (shiftedDot >= origDot) + { + return false; + } + + Edge* intersection = NULL; + + Edge* startEdge = face->nearbyVertex->edges; +#ifdef DEBUG_CONVEX_HULL + printf("Start edge is "); + startEdge->print(); + printf(", normal is (%lld %lld %lld), shifted dot is %lld\n", normal.x, normal.y, normal.z, shiftedDot); +#endif + Rational128 optDot = face->nearbyVertex->dot(normal); + int cmp = optDot.compare(shiftedDot); +#ifdef SHOW_ITERATIONS + int n = 0; +#endif + if (cmp >= 0) + { + Edge* e = startEdge; + do + { +#ifdef SHOW_ITERATIONS + n++; +#endif + Rational128 dot = e->target->dot(normal); + btAssert(dot.compare(origDot) <= 0); +#ifdef DEBUG_CONVEX_HULL + printf("Moving downwards, edge is "); + e->print(); + printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot); +#endif + if (dot.compare(optDot) < 0) + { + int c = dot.compare(shiftedDot); + optDot = dot; + e = e->reverse; + startEdge = e; + if (c < 0) + { + intersection = e; + break; + } + cmp = c; + } + e = e->prev; + } while (e != startEdge); + + if (!intersection) + { + return false; + } + } + else + { + Edge* e = startEdge; + do + { +#ifdef SHOW_ITERATIONS + n++; +#endif + Rational128 dot = e->target->dot(normal); + btAssert(dot.compare(origDot) <= 0); +#ifdef DEBUG_CONVEX_HULL + printf("Moving upwards, edge is "); + e->print(); + printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot); +#endif + if (dot.compare(optDot) > 0) + { + cmp = dot.compare(shiftedDot); + if (cmp >= 0) + { + intersection = e; + break; + } + optDot = dot; + e = e->reverse; + startEdge = e; + } + e = e->prev; + } while (e != startEdge); + + if (!intersection) + { + return true; + } + } + +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to find initial intersection\n", n); +#endif + + if (cmp == 0) + { + Edge* e = intersection->reverse->next; +#ifdef SHOW_ITERATIONS + n = 0; +#endif + while (e->target->dot(normal).compare(shiftedDot) <= 0) + { +#ifdef SHOW_ITERATIONS + n++; +#endif + e = e->next; + if (e == intersection->reverse) + { + return true; + } +#ifdef DEBUG_CONVEX_HULL + printf("Checking for outwards edge, current edge is "); + e->print(); + printf("\n"); +#endif + } +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to check for complete containment\n", n); +#endif + } + + Edge* firstIntersection = NULL; + Edge* faceEdge = NULL; + Edge* firstFaceEdge = NULL; + +#ifdef SHOW_ITERATIONS + int m = 0; +#endif + while (true) + { +#ifdef SHOW_ITERATIONS + m++; +#endif +#ifdef DEBUG_CONVEX_HULL + printf("Intersecting edge is "); + intersection->print(); + printf("\n"); +#endif + if (cmp == 0) + { + Edge* e = intersection->reverse->next; + startEdge = e; +#ifdef SHOW_ITERATIONS + n = 0; +#endif + while (true) + { +#ifdef SHOW_ITERATIONS + n++; +#endif + if (e->target->dot(normal).compare(shiftedDot) >= 0) + { + break; + } + intersection = e->reverse; + e = e->next; + if (e == startEdge) + { + return true; + } + } +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to advance intersection\n", n); +#endif + } + +#ifdef DEBUG_CONVEX_HULL + printf("Advanced intersecting edge to "); + intersection->print(); + printf(", cmp = %d\n", cmp); +#endif + + if (!firstIntersection) + { + firstIntersection = intersection; + } + else if (intersection == firstIntersection) + { + break; + } + + int prevCmp = cmp; + Edge* prevIntersection = intersection; + Edge* prevFaceEdge = faceEdge; + + Edge* e = intersection->reverse; +#ifdef SHOW_ITERATIONS + n = 0; +#endif + while (true) + { +#ifdef SHOW_ITERATIONS + n++; +#endif + e = e->reverse->prev; + btAssert(e != intersection->reverse); + cmp = e->target->dot(normal).compare(shiftedDot); +#ifdef DEBUG_CONVEX_HULL + printf("Testing edge "); + e->print(); + printf(" -> cmp = %d\n", cmp); +#endif + if (cmp >= 0) + { + intersection = e; + break; + } + } +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to find other intersection of face\n", n); +#endif + + if (cmp > 0) + { + Vertex* removed = intersection->target; + e = intersection->reverse; + if (e->prev == e) + { + removed->edges = NULL; + } + else + { + removed->edges = e->prev; + e->prev->link(e->next); + e->link(e); + } +#ifdef DEBUG_CONVEX_HULL + printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z); +#endif + + Point64 n0 = intersection->face->getNormal(); + Point64 n1 = intersection->reverse->face->getNormal(); + int64_t m00 = face->dir0.dot(n0); + int64_t m01 = face->dir1.dot(n0); + int64_t m10 = face->dir0.dot(n1); + int64_t m11 = face->dir1.dot(n1); + int64_t r0 = (intersection->face->origin - shiftedOrigin).dot(n0); + int64_t r1 = (intersection->reverse->face->origin - shiftedOrigin).dot(n1); + Int128 det = Int128::mul(m00, m11) - Int128::mul(m01, m10); + btAssert(det.getSign() != 0); + Vertex* v = vertexPool.newObject(); + v->point.index = -1; + v->copy = -1; + v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01) + + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x, + Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01) + + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y, + Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01) + + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z, + det); + v->point.x = (int32_t) v->point128.xvalue(); + v->point.y = (int32_t) v->point128.yvalue(); + v->point.z = (int32_t) v->point128.zvalue(); + intersection->target = v; + v->edges = e; + + stack.push_back(v); + stack.push_back(removed); + stack.push_back(NULL); + } + + if (cmp || prevCmp || (prevIntersection->reverse->next->target != intersection->target)) + { + faceEdge = newEdgePair(prevIntersection->target, intersection->target); + if (prevCmp == 0) + { + faceEdge->link(prevIntersection->reverse->next); + } + if ((prevCmp == 0) || prevFaceEdge) + { + prevIntersection->reverse->link(faceEdge); + } + if (cmp == 0) + { + intersection->reverse->prev->link(faceEdge->reverse); + } + faceEdge->reverse->link(intersection->reverse); + } + else + { + faceEdge = prevIntersection->reverse->next; + } + + if (prevFaceEdge) + { + if (prevCmp > 0) + { + faceEdge->link(prevFaceEdge->reverse); + } + else if (faceEdge != prevFaceEdge->reverse) + { + stack.push_back(prevFaceEdge->target); + while (faceEdge->next != prevFaceEdge->reverse) + { + Vertex* removed = faceEdge->next->target; + removeEdgePair(faceEdge->next); + stack.push_back(removed); +#ifdef DEBUG_CONVEX_HULL + printf("2: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z); +#endif + } + stack.push_back(NULL); + } + } + faceEdge->face = face; + faceEdge->reverse->face = intersection->face; + + if (!firstFaceEdge) + { + firstFaceEdge = faceEdge; + } + } +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to process all intersections\n", m); +#endif + + if (cmp > 0) + { + firstFaceEdge->reverse->target = faceEdge->target; + firstIntersection->reverse->link(firstFaceEdge); + firstFaceEdge->link(faceEdge->reverse); + } + else if (firstFaceEdge != faceEdge->reverse) + { + stack.push_back(faceEdge->target); + while (firstFaceEdge->next != faceEdge->reverse) + { + Vertex* removed = firstFaceEdge->next->target; + removeEdgePair(firstFaceEdge->next); + stack.push_back(removed); +#ifdef DEBUG_CONVEX_HULL + printf("3: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z); +#endif + } + stack.push_back(NULL); + } + + btAssert(stack.size() > 0); + vertexList = stack[0]; + +#ifdef DEBUG_CONVEX_HULL + printf("Removing part\n"); +#endif +#ifdef SHOW_ITERATIONS + n = 0; +#endif + int pos = 0; + while (pos < stack.size()) + { + int end = stack.size(); + while (pos < end) + { + Vertex* kept = stack[pos++]; +#ifdef DEBUG_CONVEX_HULL + kept->print(); +#endif + bool deeper = false; + Vertex* removed; + while ((removed = stack[pos++]) != NULL) + { +#ifdef SHOW_ITERATIONS + n++; +#endif + kept->receiveNearbyFaces(removed); + while (removed->edges) + { + if (!deeper) + { + deeper = true; + stack.push_back(kept); + } + stack.push_back(removed->edges->target); + removeEdgePair(removed->edges); + } + } + if (deeper) + { + stack.push_back(NULL); + } + } + } +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to remove part\n", n); +#endif + + stack.resize(0); + face->origin = shiftedOrigin; + + return true; +} + + +static int getVertexCopy(btConvexHullInternal::Vertex* vertex, btAlignedObjectArray& vertices) +{ + int index = vertex->copy; + if (index < 0) + { + index = vertices.size(); + vertex->copy = index; + vertices.push_back(vertex); +#ifdef DEBUG_CONVEX_HULL + printf("Vertex %d gets index *%d\n", vertex->point.index, index); +#endif + } + return index; +} + +btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp) +{ + if (count <= 0) + { + vertices.clear(); + edges.clear(); + faces.clear(); + return 0; + } + + btConvexHullInternal hull; + hull.compute(coords, doubleCoords, stride, count); + + btScalar shift = 0; + if ((shrink > 0) && ((shift = hull.shrink(shrink, shrinkClamp)) < 0)) + { + vertices.clear(); + edges.clear(); + faces.clear(); + return shift; + } + + vertices.resize(0); + edges.resize(0); + faces.resize(0); + + btAlignedObjectArray oldVertices; + getVertexCopy(hull.vertexList, oldVertices); + int copied = 0; + while (copied < oldVertices.size()) + { + btConvexHullInternal::Vertex* v = oldVertices[copied]; + vertices.push_back(hull.getCoordinates(v)); + btConvexHullInternal::Edge* firstEdge = v->edges; + if (firstEdge) + { + int firstCopy = -1; + int prevCopy = -1; + btConvexHullInternal::Edge* e = firstEdge; + do + { + if (e->copy < 0) + { + int s = edges.size(); + edges.push_back(Edge()); + edges.push_back(Edge()); + Edge* c = &edges[s]; + Edge* r = &edges[s + 1]; + e->copy = s; + e->reverse->copy = s + 1; + c->reverse = 1; + r->reverse = -1; + c->targetVertex = getVertexCopy(e->target, oldVertices); + r->targetVertex = copied; +#ifdef DEBUG_CONVEX_HULL + printf(" CREATE: Vertex *%d has edge to *%d\n", copied, c->getTargetVertex()); +#endif + } + if (prevCopy >= 0) + { + edges[e->copy].next = prevCopy - e->copy; + } + else + { + firstCopy = e->copy; + } + prevCopy = e->copy; + e = e->next; + } while (e != firstEdge); + edges[firstCopy].next = prevCopy - firstCopy; + } + copied++; + } + + for (int i = 0; i < copied; i++) + { + btConvexHullInternal::Vertex* v = oldVertices[i]; + btConvexHullInternal::Edge* firstEdge = v->edges; + if (firstEdge) + { + btConvexHullInternal::Edge* e = firstEdge; + do + { + if (e->copy >= 0) + { +#ifdef DEBUG_CONVEX_HULL + printf("Vertex *%d has edge to *%d\n", i, edges[e->copy].getTargetVertex()); +#endif + faces.push_back(e->copy); + btConvexHullInternal::Edge* f = e; + do + { +#ifdef DEBUG_CONVEX_HULL + printf(" Face *%d\n", edges[f->copy].getTargetVertex()); +#endif + f->copy = -1; + f = f->reverse->prev; + } while (f != e); + } + e = e->next; + } while (e != firstEdge); + } + } + + return shift; +} + + + + + diff --git a/src/LinearMath/btConvexHullComputer.h b/src/LinearMath/btConvexHullComputer.h new file mode 100644 index 0000000..da96a49 --- /dev/null +++ b/src/LinearMath/btConvexHullComputer.h @@ -0,0 +1,103 @@ +/* +Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_HULL_COMPUTER_H +#define BT_CONVEX_HULL_COMPUTER_H + +#include "btVector3.h" +#include "btAlignedObjectArray.h" + +/// Convex hull implementation based on Preparata and Hong +/// See http://code.google.com/p/bullet/issues/detail?id=275 +/// Ole Kniemeyer, MAXON Computer GmbH +class btConvexHullComputer +{ + private: + btScalar compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp); + + public: + + class Edge + { + private: + int next; + int reverse; + int targetVertex; + + friend class btConvexHullComputer; + + public: + int getSourceVertex() const + { + return (this + reverse)->targetVertex; + } + + int getTargetVertex() const + { + return targetVertex; + } + + const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex + { + return this + next; + } + + const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face + { + return (this + reverse)->getNextEdgeOfVertex(); + } + + const Edge* getReverseEdge() const + { + return this + reverse; + } + }; + + + // Vertices of the output hull + btAlignedObjectArray vertices; + + // Edges of the output hull + btAlignedObjectArray edges; + + // Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons + btAlignedObjectArray faces; + + /* + Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes + between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken + by that amount (each face is moved by "shrink" length units towards the center along its normal). + If "shrinkClamp" is positive, "shrink" is clamped to not exceed "shrinkClamp * innerRadius", where "innerRadius" + is the minimum distance of a face to the center of the convex hull. + + The returned value is the amount by which the hull has been shrunken. If it is negative, the amount was so large + that the resulting convex hull is empty. + + The output convex hull can be found in the member variables "vertices", "edges", "faces". + */ + btScalar compute(const float* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp) + { + return compute(coords, false, stride, count, shrink, shrinkClamp); + } + + // same as above, but double precision + btScalar compute(const double* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp) + { + return compute(coords, true, stride, count, shrink, shrinkClamp); + } +}; + + +#endif //BT_CONVEX_HULL_COMPUTER_H + diff --git a/src/LinearMath/btDefaultMotionState.h b/src/LinearMath/btDefaultMotionState.h new file mode 100644 index 0000000..a6b7ef1 --- /dev/null +++ b/src/LinearMath/btDefaultMotionState.h @@ -0,0 +1,40 @@ +#ifndef BT_DEFAULT_MOTION_STATE_H +#define BT_DEFAULT_MOTION_STATE_H + +#include "btMotionState.h" + +///The btDefaultMotionState provides a common implementation to synchronize world transforms with offsets. +struct btDefaultMotionState : public btMotionState +{ + btTransform m_graphicsWorldTrans; + btTransform m_centerOfMassOffset; + btTransform m_startWorldTrans; + void* m_userPointer; + + btDefaultMotionState(const btTransform& startTrans = btTransform::getIdentity(),const btTransform& centerOfMassOffset = btTransform::getIdentity()) + : m_graphicsWorldTrans(startTrans), + m_centerOfMassOffset(centerOfMassOffset), + m_startWorldTrans(startTrans), + m_userPointer(0) + + { + } + + ///synchronizes world transform from user to physics + virtual void getWorldTransform(btTransform& centerOfMassWorldTrans ) const + { + centerOfMassWorldTrans = m_centerOfMassOffset.inverse() * m_graphicsWorldTrans ; + } + + ///synchronizes world transform from physics to user + ///Bullet only calls the update of worldtransform for active objects + virtual void setWorldTransform(const btTransform& centerOfMassWorldTrans) + { + m_graphicsWorldTrans = centerOfMassWorldTrans * m_centerOfMassOffset ; + } + + + +}; + +#endif //BT_DEFAULT_MOTION_STATE_H diff --git a/src/LinearMath/btGeometryUtil.cpp b/src/LinearMath/btGeometryUtil.cpp new file mode 100644 index 0000000..5ac230f --- /dev/null +++ b/src/LinearMath/btGeometryUtil.cpp @@ -0,0 +1,185 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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 "btGeometryUtil.h" + + +/* + Make sure this dummy function never changes so that it + can be used by probes that are checking whether the + library is actually installed. +*/ +extern "C" +{ + void btBulletMathProbe (); + + void btBulletMathProbe () {} +} + + +bool btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray& planeEquations, const btVector3& point, btScalar margin) +{ + int numbrushes = planeEquations.size(); + for (int i=0;ibtScalar(0.)) + { + return false; + } + } + return true; + +} + + +bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray& vertices, btScalar margin) +{ + int numvertices = vertices.size(); + for (int i=0;ibtScalar(0.)) + { + return false; + } + } + return true; +} + +bool notExist(const btVector3& planeEquation,const btAlignedObjectArray& planeEquations); + +bool notExist(const btVector3& planeEquation,const btAlignedObjectArray& planeEquations) +{ + int numbrushes = planeEquations.size(); + for (int i=0;i btScalar(0.999)) + { + return false; + } + } + return true; +} + +void btGeometryUtil::getPlaneEquationsFromVertices(btAlignedObjectArray& vertices, btAlignedObjectArray& planeEquationsOut ) +{ + const int numvertices = vertices.size(); + // brute force: + for (int i=0;i btScalar(0.0001)) + { + planeEquation.normalize(); + if (notExist(planeEquation,planeEquationsOut)) + { + planeEquation[3] = -planeEquation.dot(N1); + + //check if inside, and replace supportingVertexOut if needed + if (areVerticesBehindPlane(planeEquation,vertices,btScalar(0.01))) + { + planeEquationsOut.push_back(planeEquation); + } + } + } + normalSign = btScalar(-1.); + } + + } + } + } + +} + +void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray& planeEquations , btAlignedObjectArray& verticesOut ) +{ + const int numbrushes = planeEquations.size(); + // brute force: + for (int i=0;i btScalar(0.0001) ) && + ( n3n1.length2() > btScalar(0.0001) ) && + ( n1n2.length2() > btScalar(0.0001) ) ) + { + //point P out of 3 plane equations: + + // d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 ) + //P = ------------------------------------------------------------------------- + // N1 . ( N2 * N3 ) + + + btScalar quotient = (N1.dot(n2n3)); + if (btFabs(quotient) > btScalar(0.000001)) + { + quotient = btScalar(-1.) / quotient; + n2n3 *= N1[3]; + n3n1 *= N2[3]; + n1n2 *= N3[3]; + btVector3 potentialVertex = n2n3; + potentialVertex += n3n1; + potentialVertex += n1n2; + potentialVertex *= quotient; + + //check if inside, and replace supportingVertexOut if needed + if (isPointInsidePlanes(planeEquations,potentialVertex,btScalar(0.01))) + { + verticesOut.push_back(potentialVertex); + } + } + } + } + } + } +} + diff --git a/src/LinearMath/btGeometryUtil.h b/src/LinearMath/btGeometryUtil.h new file mode 100644 index 0000000..a4b13b4 --- /dev/null +++ b/src/LinearMath/btGeometryUtil.h @@ -0,0 +1,42 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_GEOMETRY_UTIL_H +#define BT_GEOMETRY_UTIL_H + +#include "btVector3.h" +#include "btAlignedObjectArray.h" + +///The btGeometryUtil helper class provides a few methods to convert between plane equations and vertices. +class btGeometryUtil +{ + public: + + + static void getPlaneEquationsFromVertices(btAlignedObjectArray& vertices, btAlignedObjectArray& planeEquationsOut ); + + static void getVerticesFromPlaneEquations(const btAlignedObjectArray& planeEquations , btAlignedObjectArray& verticesOut ); + + static bool isInside(const btAlignedObjectArray& vertices, const btVector3& planeNormal, btScalar margin); + + static bool isPointInsidePlanes(const btAlignedObjectArray& planeEquations, const btVector3& point, btScalar margin); + + static bool areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray& vertices, btScalar margin); + +}; + + +#endif //BT_GEOMETRY_UTIL_H + diff --git a/src/LinearMath/btGrahamScan2dConvexHull.h b/src/LinearMath/btGrahamScan2dConvexHull.h new file mode 100644 index 0000000..aa933c1 --- /dev/null +++ b/src/LinearMath/btGrahamScan2dConvexHull.h @@ -0,0 +1,110 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +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 GRAHAM_SCAN_2D_CONVEX_HULL_H +#define GRAHAM_SCAN_2D_CONVEX_HULL_H + + +#include "btVector3.h" +#include "btAlignedObjectArray.h" + +struct GrahamVector2 : public btVector3 +{ + GrahamVector2(const btVector3& org, int orgIndex) + :btVector3(org), + m_orgIndex(orgIndex) + { + } + btScalar m_angle; + int m_orgIndex; +}; + + +struct btAngleCompareFunc { + btVector3 m_anchor; + btAngleCompareFunc(const btVector3& anchor) + : m_anchor(anchor) + { + } + bool operator()(const GrahamVector2& a, const GrahamVector2& b) const { + if (a.m_angle != b.m_angle) + return a.m_angle < b.m_angle; + else + { + btScalar al = (a-m_anchor).length2(); + btScalar bl = (b-m_anchor).length2(); + if (al != bl) + return al < bl; + else + { + return a.m_orgIndex < b.m_orgIndex; + } + } + } +}; + +inline void GrahamScanConvexHull2D(btAlignedObjectArray& originalPoints, btAlignedObjectArray& hull) +{ + if (originalPoints.size()<=1) + { + for (int i=0;i1) { + btVector3& a = hull[hull.size()-2]; + btVector3& b = hull[hull.size()-1]; + isConvex = btCross(a-b,a-originalPoints[i]).dot(btVector3(0,0,1))> 0; + if (!isConvex) + hull.pop_back(); + else + hull.push_back(originalPoints[i]); + } + } +} + +#endif //GRAHAM_SCAN_2D_CONVEX_HULL_H diff --git a/src/LinearMath/btHashMap.h b/src/LinearMath/btHashMap.h new file mode 100644 index 0000000..ce07db3 --- /dev/null +++ b/src/LinearMath/btHashMap.h @@ -0,0 +1,450 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_HASH_MAP_H +#define BT_HASH_MAP_H + +#include "btAlignedObjectArray.h" + +///very basic hashable string implementation, compatible with btHashMap +struct btHashString +{ + const char* m_string; + unsigned int m_hash; + + SIMD_FORCE_INLINE unsigned int getHash()const + { + return m_hash; + } + + btHashString(const char* name) + :m_string(name) + { + /* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */ + static const unsigned int InitialFNV = 2166136261u; + static const unsigned int FNVMultiple = 16777619u; + + /* Fowler / Noll / Vo (FNV) Hash */ + unsigned int hash = InitialFNV; + + for(int i = 0; m_string[i]; i++) + { + hash = hash ^ (m_string[i]); /* xor the low 8 bits */ + hash = hash * FNVMultiple; /* multiply by the magic number */ + } + m_hash = hash; + } + + int portableStringCompare(const char* src, const char* dst) const + { + int ret = 0 ; + + while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst) + ++src, ++dst; + + if ( ret < 0 ) + ret = -1 ; + else if ( ret > 0 ) + ret = 1 ; + + return( ret ); + } + + bool equals(const btHashString& other) const + { + return (m_string == other.m_string) || + (0==portableStringCompare(m_string,other.m_string)); + + } + +}; + +const int BT_HASH_NULL=0xffffffff; + + +class btHashInt +{ + int m_uid; +public: + btHashInt(int uid) :m_uid(uid) + { + } + + int getUid1() const + { + return m_uid; + } + + void setUid1(int uid) + { + m_uid = uid; + } + + bool equals(const btHashInt& other) const + { + return getUid1() == other.getUid1(); + } + //to our success + SIMD_FORCE_INLINE unsigned int getHash()const + { + int key = m_uid; + // Thomas Wang's hash + key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16); + return key; + } +}; + + + +class btHashPtr +{ + + union + { + const void* m_pointer; + int m_hashValues[2]; + }; + +public: + + btHashPtr(const void* ptr) + :m_pointer(ptr) + { + } + + const void* getPointer() const + { + return m_pointer; + } + + bool equals(const btHashPtr& other) const + { + return getPointer() == other.getPointer(); + } + + //to our success + SIMD_FORCE_INLINE unsigned int getHash()const + { + const bool VOID_IS_8 = ((sizeof(void*)==8)); + + int key = VOID_IS_8? m_hashValues[0]+m_hashValues[1] : m_hashValues[0]; + + // Thomas Wang's hash + key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16); + return key; + } + + +}; + + +template +class btHashKeyPtr +{ + int m_uid; +public: + + btHashKeyPtr(int uid) :m_uid(uid) + { + } + + int getUid1() const + { + return m_uid; + } + + bool equals(const btHashKeyPtr& other) const + { + return getUid1() == other.getUid1(); + } + + //to our success + SIMD_FORCE_INLINE unsigned int getHash()const + { + int key = m_uid; + // Thomas Wang's hash + key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16); + return key; + } + + +}; + + +template +class btHashKey +{ + int m_uid; +public: + + btHashKey(int uid) :m_uid(uid) + { + } + + int getUid1() const + { + return m_uid; + } + + bool equals(const btHashKey& other) const + { + return getUid1() == other.getUid1(); + } + //to our success + SIMD_FORCE_INLINE unsigned int getHash()const + { + int key = m_uid; + // Thomas Wang's hash + key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16); + return key; + } +}; + + +///The btHashMap template class implements a generic and lightweight hashmap. +///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp +template +class btHashMap +{ + +protected: + btAlignedObjectArray m_hashTable; + btAlignedObjectArray m_next; + + btAlignedObjectArray m_valueArray; + btAlignedObjectArray m_keyArray; + + void growTables(const Key& /*key*/) + { + int newCapacity = m_valueArray.capacity(); + + if (m_hashTable.size() < newCapacity) + { + //grow hashtable and next table + int curHashtableSize = m_hashTable.size(); + + m_hashTable.resize(newCapacity); + m_next.resize(newCapacity); + + int i; + + for (i= 0; i < newCapacity; ++i) + { + m_hashTable[i] = BT_HASH_NULL; + } + for (i = 0; i < newCapacity; ++i) + { + m_next[i] = BT_HASH_NULL; + } + + for(i=0;i= (unsigned int)m_hashTable.size()) + { + return BT_HASH_NULL; + } + + int index = m_hashTable[hash]; + while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false) + { + index = m_next[index]; + } + return index; + } + + void clear() + { + m_hashTable.clear(); + m_next.clear(); + m_valueArray.clear(); + m_keyArray.clear(); + } + +}; + +#endif //BT_HASH_MAP_H diff --git a/src/LinearMath/btIDebugDraw.h b/src/LinearMath/btIDebugDraw.h new file mode 100644 index 0000000..935502f --- /dev/null +++ b/src/LinearMath/btIDebugDraw.h @@ -0,0 +1,418 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_IDEBUG_DRAW__H +#define BT_IDEBUG_DRAW__H + +#include "btVector3.h" +#include "btTransform.h" + + +///The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations. +///Typical use case: create a debug drawer object, and assign it to a btCollisionWorld or btDynamicsWorld using setDebugDrawer and call debugDrawWorld. +///A class that implements the btIDebugDraw interface has to implement the drawLine method at a minimum. +///For color arguments the X,Y,Z components refer to Red, Green and Blue each in the range [0..1] +class btIDebugDraw +{ + public: + + enum DebugDrawModes + { + DBG_NoDebug=0, + DBG_DrawWireframe = 1, + DBG_DrawAabb=2, + DBG_DrawFeaturesText=4, + DBG_DrawContactPoints=8, + DBG_NoDeactivation=16, + DBG_NoHelpText = 32, + DBG_DrawText=64, + DBG_ProfileTimings = 128, + DBG_EnableSatComparison = 256, + DBG_DisableBulletLCP = 512, + DBG_EnableCCD = 1024, + DBG_DrawConstraints = (1 << 11), + DBG_DrawConstraintLimits = (1 << 12), + DBG_FastWireframe = (1<<13), + DBG_DrawNormals = (1<<14), + DBG_MAX_DEBUG_DRAW_MODE + }; + + virtual ~btIDebugDraw() {}; + + virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color)=0; + + virtual void drawLine(const btVector3& from,const btVector3& to, const btVector3& fromColor, const btVector3& toColor) + { + (void) toColor; + drawLine (from, to, fromColor); + } + + virtual void drawSphere(btScalar radius, const btTransform& transform, const btVector3& color) + { + btVector3 start = transform.getOrigin(); + + const btVector3 xoffs = transform.getBasis() * btVector3(radius,0,0); + const btVector3 yoffs = transform.getBasis() * btVector3(0,radius,0); + const btVector3 zoffs = transform.getBasis() * btVector3(0,0,radius); + + // XY + drawLine(start-xoffs, start+yoffs, color); + drawLine(start+yoffs, start+xoffs, color); + drawLine(start+xoffs, start-yoffs, color); + drawLine(start-yoffs, start-xoffs, color); + + // XZ + drawLine(start-xoffs, start+zoffs, color); + drawLine(start+zoffs, start+xoffs, color); + drawLine(start+xoffs, start-zoffs, color); + drawLine(start-zoffs, start-xoffs, color); + + // YZ + drawLine(start-yoffs, start+zoffs, color); + drawLine(start+zoffs, start+yoffs, color); + drawLine(start+yoffs, start-zoffs, color); + drawLine(start-zoffs, start-yoffs, color); + } + + virtual void drawSphere (const btVector3& p, btScalar radius, const btVector3& color) + { + btTransform tr; + tr.setIdentity(); + tr.setOrigin(p); + drawSphere(radius,tr,color); + } + + virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& /*n0*/,const btVector3& /*n1*/,const btVector3& /*n2*/,const btVector3& color, btScalar alpha) + { + drawTriangle(v0,v1,v2,color,alpha); + } + virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& color, btScalar /*alpha*/) + { + drawLine(v0,v1,color); + drawLine(v1,v2,color); + drawLine(v2,v0,color); + } + + virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)=0; + + virtual void reportErrorWarning(const char* warningString) = 0; + + virtual void draw3dText(const btVector3& location,const char* textString) = 0; + + virtual void setDebugMode(int debugMode) =0; + + virtual int getDebugMode() const = 0; + + virtual void drawAabb(const btVector3& from,const btVector3& to,const btVector3& color) + { + + btVector3 halfExtents = (to-from)* 0.5f; + btVector3 center = (to+from) *0.5f; + int i,j; + + btVector3 edgecoord(1.f,1.f,1.f),pa,pb; + for (i=0;i<4;i++) + { + for (j=0;j<3;j++) + { + pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1], + edgecoord[2]*halfExtents[2]); + pa+=center; + + int othercoord = j%3; + edgecoord[othercoord]*=-1.f; + pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1], + edgecoord[2]*halfExtents[2]); + pb+=center; + + drawLine(pa,pb,color); + } + edgecoord = btVector3(-1.f,-1.f,-1.f); + if (i<3) + edgecoord[i]*=-1.f; + } + } + virtual void drawTransform(const btTransform& transform, btScalar orthoLen) + { + btVector3 start = transform.getOrigin(); + drawLine(start, start+transform.getBasis() * btVector3(orthoLen, 0, 0), btVector3(0.7f,0,0)); + drawLine(start, start+transform.getBasis() * btVector3(0, orthoLen, 0), btVector3(0,0.7f,0)); + drawLine(start, start+transform.getBasis() * btVector3(0, 0, orthoLen), btVector3(0,0,0.7f)); + } + + virtual void drawArc(const btVector3& center, const btVector3& normal, const btVector3& axis, btScalar radiusA, btScalar radiusB, btScalar minAngle, btScalar maxAngle, + const btVector3& color, bool drawSect, btScalar stepDegrees = btScalar(10.f)) + { + const btVector3& vx = axis; + btVector3 vy = normal.cross(axis); + btScalar step = stepDegrees * SIMD_RADS_PER_DEG; + int nSteps = (int)((maxAngle - minAngle) / step); + if(!nSteps) nSteps = 1; + btVector3 prev = center + radiusA * vx * btCos(minAngle) + radiusB * vy * btSin(minAngle); + if(drawSect) + { + drawLine(center, prev, color); + } + for(int i = 1; i <= nSteps; i++) + { + btScalar angle = minAngle + (maxAngle - minAngle) * btScalar(i) / btScalar(nSteps); + btVector3 next = center + radiusA * vx * btCos(angle) + radiusB * vy * btSin(angle); + drawLine(prev, next, color); + prev = next; + } + if(drawSect) + { + drawLine(center, prev, color); + } + } + virtual void drawSpherePatch(const btVector3& center, const btVector3& up, const btVector3& axis, btScalar radius, + btScalar minTh, btScalar maxTh, btScalar minPs, btScalar maxPs, const btVector3& color, btScalar stepDegrees = btScalar(10.f)) + { + btVector3 vA[74]; + btVector3 vB[74]; + btVector3 *pvA = vA, *pvB = vB, *pT; + btVector3 npole = center + up * radius; + btVector3 spole = center - up * radius; + btVector3 arcStart; + btScalar step = stepDegrees * SIMD_RADS_PER_DEG; + const btVector3& kv = up; + const btVector3& iv = axis; + btVector3 jv = kv.cross(iv); + bool drawN = false; + bool drawS = false; + if(minTh <= -SIMD_HALF_PI) + { + minTh = -SIMD_HALF_PI + step; + drawN = true; + } + if(maxTh >= SIMD_HALF_PI) + { + maxTh = SIMD_HALF_PI - step; + drawS = true; + } + if(minTh > maxTh) + { + minTh = -SIMD_HALF_PI + step; + maxTh = SIMD_HALF_PI - step; + drawN = drawS = true; + } + int n_hor = (int)((maxTh - minTh) / step) + 1; + if(n_hor < 2) n_hor = 2; + btScalar step_h = (maxTh - minTh) / btScalar(n_hor - 1); + bool isClosed = false; + if(minPs > maxPs) + { + minPs = -SIMD_PI + step; + maxPs = SIMD_PI; + isClosed = true; + } + else if((maxPs - minPs) >= SIMD_PI * btScalar(2.f)) + { + isClosed = true; + } + else + { + isClosed = false; + } + int n_vert = (int)((maxPs - minPs) / step) + 1; + if(n_vert < 2) n_vert = 2; + btScalar step_v = (maxPs - minPs) / btScalar(n_vert - 1); + for(int i = 0; i < n_hor; i++) + { + btScalar th = minTh + btScalar(i) * step_h; + btScalar sth = radius * btSin(th); + btScalar cth = radius * btCos(th); + for(int j = 0; j < n_vert; j++) + { + btScalar psi = minPs + btScalar(j) * step_v; + btScalar sps = btSin(psi); + btScalar cps = btCos(psi); + pvB[j] = center + cth * cps * iv + cth * sps * jv + sth * kv; + if(i) + { + drawLine(pvA[j], pvB[j], color); + } + else if(drawS) + { + drawLine(spole, pvB[j], color); + } + if(j) + { + drawLine(pvB[j-1], pvB[j], color); + } + else + { + arcStart = pvB[j]; + } + if((i == (n_hor - 1)) && drawN) + { + drawLine(npole, pvB[j], color); + } + if(isClosed) + { + if(j == (n_vert-1)) + { + drawLine(arcStart, pvB[j], color); + } + } + else + { + if(((!i) || (i == (n_hor-1))) && ((!j) || (j == (n_vert-1)))) + { + drawLine(center, pvB[j], color); + } + } + } + pT = pvA; pvA = pvB; pvB = pT; + } + } + + virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btVector3& color) + { + drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMin[2]), color); + drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMin[2]), color); + drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMin[2]), color); + drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMin[2]), color); + drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color); + drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color); + drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color); + drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color); + drawLine(btVector3(bbMin[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color); + drawLine(btVector3(bbMax[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color); + drawLine(btVector3(bbMax[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color); + drawLine(btVector3(bbMin[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color); + } + virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btTransform& trans, const btVector3& color) + { + drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), color); + drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), color); + drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color); + } + + virtual void drawCapsule(btScalar radius, btScalar halfHeight, int upAxis, const btTransform& transform, const btVector3& color) + { + btVector3 capStart(0.f,0.f,0.f); + capStart[upAxis] = -halfHeight; + + btVector3 capEnd(0.f,0.f,0.f); + capEnd[upAxis] = halfHeight; + + // Draw the ends + { + + btTransform childTransform = transform; + childTransform.getOrigin() = transform * capStart; + drawSphere(radius, childTransform, color); + } + + { + btTransform childTransform = transform; + childTransform.getOrigin() = transform * capEnd; + drawSphere(radius, childTransform, color); + } + + // Draw some additional lines + btVector3 start = transform.getOrigin(); + + capStart[(upAxis+1)%3] = radius; + capEnd[(upAxis+1)%3] = radius; + drawLine(start+transform.getBasis() * capStart,start+transform.getBasis() * capEnd, color); + capStart[(upAxis+1)%3] = -radius; + capEnd[(upAxis+1)%3] = -radius; + drawLine(start+transform.getBasis() * capStart,start+transform.getBasis() * capEnd, color); + + capStart[(upAxis+1)%3] = 0.f; + capEnd[(upAxis+1)%3] = 0.f; + + capStart[(upAxis+2)%3] = radius; + capEnd[(upAxis+2)%3] = radius; + drawLine(start+transform.getBasis() * capStart,start+transform.getBasis() * capEnd, color); + capStart[(upAxis+2)%3] = -radius; + capEnd[(upAxis+2)%3] = -radius; + drawLine(start+transform.getBasis() * capStart,start+transform.getBasis() * capEnd, color); + } + + virtual void drawCylinder(btScalar radius, btScalar halfHeight, int upAxis, const btTransform& transform, const btVector3& color) + { + btVector3 start = transform.getOrigin(); + btVector3 offsetHeight(0,0,0); + offsetHeight[upAxis] = halfHeight; + btVector3 offsetRadius(0,0,0); + offsetRadius[(upAxis+1)%3] = radius; + drawLine(start+transform.getBasis() * (offsetHeight+offsetRadius),start+transform.getBasis() * (-offsetHeight+offsetRadius),color); + drawLine(start+transform.getBasis() * (offsetHeight-offsetRadius),start+transform.getBasis() * (-offsetHeight-offsetRadius),color); + + // Drawing top and bottom caps of the cylinder + btVector3 yaxis(0,0,0); + yaxis[upAxis] = btScalar(1.0); + btVector3 xaxis(0,0,0); + xaxis[(upAxis+1)%3] = btScalar(1.0); + drawArc(start-transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,btScalar(10.0)); + drawArc(start+transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,btScalar(10.0)); + } + + virtual void drawCone(btScalar radius, btScalar height, int upAxis, const btTransform& transform, const btVector3& color) + { + + btVector3 start = transform.getOrigin(); + + btVector3 offsetHeight(0,0,0); + offsetHeight[upAxis] = height * btScalar(0.5); + btVector3 offsetRadius(0,0,0); + offsetRadius[(upAxis+1)%3] = radius; + btVector3 offset2Radius(0,0,0); + offset2Radius[(upAxis+2)%3] = radius; + + drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight+offsetRadius),color); + drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight-offsetRadius),color); + drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight+offset2Radius),color); + drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight-offset2Radius),color); + + // Drawing the base of the cone + btVector3 yaxis(0,0,0); + yaxis[upAxis] = btScalar(1.0); + btVector3 xaxis(0,0,0); + xaxis[(upAxis+1)%3] = btScalar(1.0); + drawArc(start-transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,10.0); + } + + virtual void drawPlane(const btVector3& planeNormal, btScalar planeConst, const btTransform& transform, const btVector3& color) + { + btVector3 planeOrigin = planeNormal * planeConst; + btVector3 vec0,vec1; + btPlaneSpace1(planeNormal,vec0,vec1); + btScalar vecLen = 100.f; + btVector3 pt0 = planeOrigin + vec0*vecLen; + btVector3 pt1 = planeOrigin - vec0*vecLen; + btVector3 pt2 = planeOrigin + vec1*vecLen; + btVector3 pt3 = planeOrigin - vec1*vecLen; + drawLine(transform*pt0,transform*pt1,color); + drawLine(transform*pt2,transform*pt3,color); + } +}; + + +#endif //BT_IDEBUG_DRAW__H + diff --git a/src/LinearMath/btList.h b/src/LinearMath/btList.h new file mode 100644 index 0000000..eec80a7 --- /dev/null +++ b/src/LinearMath/btList.h @@ -0,0 +1,73 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_GEN_LIST_H +#define BT_GEN_LIST_H + +class btGEN_Link { +public: + btGEN_Link() : m_next(0), m_prev(0) {} + btGEN_Link(btGEN_Link *next, btGEN_Link *prev) : m_next(next), m_prev(prev) {} + + btGEN_Link *getNext() const { return m_next; } + btGEN_Link *getPrev() const { return m_prev; } + + bool isHead() const { return m_prev == 0; } + bool isTail() const { return m_next == 0; } + + void insertBefore(btGEN_Link *link) { + m_next = link; + m_prev = link->m_prev; + m_next->m_prev = this; + m_prev->m_next = this; + } + + void insertAfter(btGEN_Link *link) { + m_next = link->m_next; + m_prev = link; + m_next->m_prev = this; + m_prev->m_next = this; + } + + void remove() { + m_next->m_prev = m_prev; + m_prev->m_next = m_next; + } + +private: + btGEN_Link *m_next; + btGEN_Link *m_prev; +}; + +class btGEN_List { +public: + btGEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {} + + btGEN_Link *getHead() const { return m_head.getNext(); } + btGEN_Link *getTail() const { return m_tail.getPrev(); } + + void addHead(btGEN_Link *link) { link->insertAfter(&m_head); } + void addTail(btGEN_Link *link) { link->insertBefore(&m_tail); } + +private: + btGEN_Link m_head; + btGEN_Link m_tail; +}; + +#endif //BT_GEN_LIST_H + + + diff --git a/src/LinearMath/btMatrix3x3.h b/src/LinearMath/btMatrix3x3.h new file mode 100644 index 0000000..d0234a0 --- /dev/null +++ b/src/LinearMath/btMatrix3x3.h @@ -0,0 +1,771 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_MATRIX3x3_H +#define BT_MATRIX3x3_H + +#include "btVector3.h" +#include "btQuaternion.h" + +#ifdef BT_USE_DOUBLE_PRECISION +#define btMatrix3x3Data btMatrix3x3DoubleData +#else +#define btMatrix3x3Data btMatrix3x3FloatData +#endif //BT_USE_DOUBLE_PRECISION + + +/**@brief The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with btQuaternion, btTransform and btVector3. +* Make sure to only include a pure orthogonal matrix without scaling. */ +class btMatrix3x3 { + + ///Data storage for the matrix, each vector is a row of the matrix + btVector3 m_el[3]; + +public: + /** @brief No initializaion constructor */ + btMatrix3x3 () {} + + // explicit btMatrix3x3(const btScalar *m) { setFromOpenGLSubMatrix(m); } + + /**@brief Constructor from Quaternion */ + explicit btMatrix3x3(const btQuaternion& q) { setRotation(q); } + /* + template + Matrix3x3(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) + { + setEulerYPR(yaw, pitch, roll); + } + */ + /** @brief Constructor with row major formatting */ + btMatrix3x3(const btScalar& xx, const btScalar& xy, const btScalar& xz, + const btScalar& yx, const btScalar& yy, const btScalar& yz, + const btScalar& zx, const btScalar& zy, const btScalar& zz) + { + setValue(xx, xy, xz, + yx, yy, yz, + zx, zy, zz); + } + /** @brief Copy constructor */ + SIMD_FORCE_INLINE btMatrix3x3 (const btMatrix3x3& other) + { + m_el[0] = other.m_el[0]; + m_el[1] = other.m_el[1]; + m_el[2] = other.m_el[2]; + } + /** @brief Assignment Operator */ + SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& other) + { + m_el[0] = other.m_el[0]; + m_el[1] = other.m_el[1]; + m_el[2] = other.m_el[2]; + return *this; + } + + /** @brief Get a column of the matrix as a vector + * @param i Column number 0 indexed */ + SIMD_FORCE_INLINE btVector3 getColumn(int i) const + { + return btVector3(m_el[0][i],m_el[1][i],m_el[2][i]); + } + + + /** @brief Get a row of the matrix as a vector + * @param i Row number 0 indexed */ + SIMD_FORCE_INLINE const btVector3& getRow(int i) const + { + btFullAssert(0 <= i && i < 3); + return m_el[i]; + } + + /** @brief Get a mutable reference to a row of the matrix as a vector + * @param i Row number 0 indexed */ + SIMD_FORCE_INLINE btVector3& operator[](int i) + { + btFullAssert(0 <= i && i < 3); + return m_el[i]; + } + + /** @brief Get a const reference to a row of the matrix as a vector + * @param i Row number 0 indexed */ + SIMD_FORCE_INLINE const btVector3& operator[](int i) const + { + btFullAssert(0 <= i && i < 3); + return m_el[i]; + } + + /** @brief Multiply by the target matrix on the right + * @param m Rotation matrix to be applied + * Equivilant to this = this * m */ + btMatrix3x3& operator*=(const btMatrix3x3& m); + + /** @brief Adds by the target matrix on the right + * @param m matrix to be applied + * Equivilant to this = this + m */ + btMatrix3x3& operator+=(const btMatrix3x3& m); + + /** @brief Substractss by the target matrix on the right + * @param m matrix to be applied + * Equivilant to this = this - m */ + btMatrix3x3& operator-=(const btMatrix3x3& m); + + /** @brief Set from the rotational part of a 4x4 OpenGL matrix + * @param m A pointer to the beginning of the array of scalars*/ + void setFromOpenGLSubMatrix(const btScalar *m) + { + m_el[0].setValue(m[0],m[4],m[8]); + m_el[1].setValue(m[1],m[5],m[9]); + m_el[2].setValue(m[2],m[6],m[10]); + + } + /** @brief Set the values of the matrix explicitly (row major) + * @param xx Top left + * @param xy Top Middle + * @param xz Top Right + * @param yx Middle Left + * @param yy Middle Middle + * @param yz Middle Right + * @param zx Bottom Left + * @param zy Bottom Middle + * @param zz Bottom Right*/ + void setValue(const btScalar& xx, const btScalar& xy, const btScalar& xz, + const btScalar& yx, const btScalar& yy, const btScalar& yz, + const btScalar& zx, const btScalar& zy, const btScalar& zz) + { + m_el[0].setValue(xx,xy,xz); + m_el[1].setValue(yx,yy,yz); + m_el[2].setValue(zx,zy,zz); + } + + /** @brief Set the matrix from a quaternion + * @param q The Quaternion to match */ + void setRotation(const btQuaternion& q) + { + btScalar d = q.length2(); + btFullAssert(d != btScalar(0.0)); + btScalar s = btScalar(2.0) / d; + btScalar xs = q.x() * s, ys = q.y() * s, zs = q.z() * s; + btScalar wx = q.w() * xs, wy = q.w() * ys, wz = q.w() * zs; + btScalar xx = q.x() * xs, xy = q.x() * ys, xz = q.x() * zs; + btScalar yy = q.y() * ys, yz = q.y() * zs, zz = q.z() * zs; + setValue(btScalar(1.0) - (yy + zz), xy - wz, xz + wy, + xy + wz, btScalar(1.0) - (xx + zz), yz - wx, + xz - wy, yz + wx, btScalar(1.0) - (xx + yy)); + } + + + /** @brief Set the matrix from euler angles using YPR around YXZ respectively + * @param yaw Yaw about Y axis + * @param pitch Pitch about X axis + * @param roll Roll about Z axis + */ + void setEulerYPR(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) + { + setEulerZYX(roll, pitch, yaw); + } + + /** @brief Set the matrix from euler angles YPR around ZYX axes + * @param eulerX Roll about X axis + * @param eulerY Pitch around Y axis + * @param eulerZ Yaw aboud Z axis + * + * These angles are used to produce a rotation matrix. The euler + * angles are applied in ZYX order. I.e a vector is first rotated + * about X then Y and then Z + **/ + void setEulerZYX(btScalar eulerX,btScalar eulerY,btScalar eulerZ) { + ///@todo proposed to reverse this since it's labeled zyx but takes arguments xyz and it will match all other parts of the code + btScalar ci ( btCos(eulerX)); + btScalar cj ( btCos(eulerY)); + btScalar ch ( btCos(eulerZ)); + btScalar si ( btSin(eulerX)); + btScalar sj ( btSin(eulerY)); + btScalar sh ( btSin(eulerZ)); + btScalar cc = ci * ch; + btScalar cs = ci * sh; + btScalar sc = si * ch; + btScalar ss = si * sh; + + setValue(cj * ch, sj * sc - cs, sj * cc + ss, + cj * sh, sj * ss + cc, sj * cs - sc, + -sj, cj * si, cj * ci); + } + + /**@brief Set the matrix to the identity */ + void setIdentity() + { + setValue(btScalar(1.0), btScalar(0.0), btScalar(0.0), + btScalar(0.0), btScalar(1.0), btScalar(0.0), + btScalar(0.0), btScalar(0.0), btScalar(1.0)); + } + + static const btMatrix3x3& getIdentity() + { + static const btMatrix3x3 identityMatrix(btScalar(1.0), btScalar(0.0), btScalar(0.0), + btScalar(0.0), btScalar(1.0), btScalar(0.0), + btScalar(0.0), btScalar(0.0), btScalar(1.0)); + return identityMatrix; + } + + /**@brief Fill the rotational part of an OpenGL matrix and clear the shear/perspective + * @param m The array to be filled */ + void getOpenGLSubMatrix(btScalar *m) const + { + m[0] = btScalar(m_el[0].x()); + m[1] = btScalar(m_el[1].x()); + m[2] = btScalar(m_el[2].x()); + m[3] = btScalar(0.0); + m[4] = btScalar(m_el[0].y()); + m[5] = btScalar(m_el[1].y()); + m[6] = btScalar(m_el[2].y()); + m[7] = btScalar(0.0); + m[8] = btScalar(m_el[0].z()); + m[9] = btScalar(m_el[1].z()); + m[10] = btScalar(m_el[2].z()); + m[11] = btScalar(0.0); + } + + /**@brief Get the matrix represented as a quaternion + * @param q The quaternion which will be set */ + void getRotation(btQuaternion& q) const + { + btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z(); + btScalar temp[4]; + + if (trace > btScalar(0.0)) + { + btScalar s = btSqrt(trace + btScalar(1.0)); + temp[3]=(s * btScalar(0.5)); + s = btScalar(0.5) / s; + + temp[0]=((m_el[2].y() - m_el[1].z()) * s); + temp[1]=((m_el[0].z() - m_el[2].x()) * s); + temp[2]=((m_el[1].x() - m_el[0].y()) * s); + } + else + { + int i = m_el[0].x() < m_el[1].y() ? + (m_el[1].y() < m_el[2].z() ? 2 : 1) : + (m_el[0].x() < m_el[2].z() ? 2 : 0); + int j = (i + 1) % 3; + int k = (i + 2) % 3; + + btScalar s = btSqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0)); + temp[i] = s * btScalar(0.5); + s = btScalar(0.5) / s; + + temp[3] = (m_el[k][j] - m_el[j][k]) * s; + temp[j] = (m_el[j][i] + m_el[i][j]) * s; + temp[k] = (m_el[k][i] + m_el[i][k]) * s; + } + q.setValue(temp[0],temp[1],temp[2],temp[3]); + } + + /**@brief Get the matrix represented as euler angles around YXZ, roundtrip with setEulerYPR + * @param yaw Yaw around Y axis + * @param pitch Pitch around X axis + * @param roll around Z axis */ + void getEulerYPR(btScalar& yaw, btScalar& pitch, btScalar& roll) const + { + + // first use the normal calculus + yaw = btScalar(btAtan2(m_el[1].x(), m_el[0].x())); + pitch = btScalar(btAsin(-m_el[2].x())); + roll = btScalar(btAtan2(m_el[2].y(), m_el[2].z())); + + // on pitch = +/-HalfPI + if (btFabs(pitch)==SIMD_HALF_PI) + { + if (yaw>0) + yaw-=SIMD_PI; + else + yaw+=SIMD_PI; + + if (roll>0) + roll-=SIMD_PI; + else + roll+=SIMD_PI; + } + }; + + + /**@brief Get the matrix represented as euler angles around ZYX + * @param yaw Yaw around X axis + * @param pitch Pitch around Y axis + * @param roll around X axis + * @param solution_number Which solution of two possible solutions ( 1 or 2) are possible values*/ + void getEulerZYX(btScalar& yaw, btScalar& pitch, btScalar& roll, unsigned int solution_number = 1) const + { + struct Euler + { + btScalar yaw; + btScalar pitch; + btScalar roll; + }; + + Euler euler_out; + Euler euler_out2; //second solution + //get the pointer to the raw data + + // Check that pitch is not at a singularity + if (btFabs(m_el[2].x()) >= 1) + { + euler_out.yaw = 0; + euler_out2.yaw = 0; + + // From difference of angles formula + btScalar delta = btAtan2(m_el[0].x(),m_el[0].z()); + if (m_el[2].x() > 0) //gimbal locked up + { + euler_out.pitch = SIMD_PI / btScalar(2.0); + euler_out2.pitch = SIMD_PI / btScalar(2.0); + euler_out.roll = euler_out.pitch + delta; + euler_out2.roll = euler_out.pitch + delta; + } + else // gimbal locked down + { + euler_out.pitch = -SIMD_PI / btScalar(2.0); + euler_out2.pitch = -SIMD_PI / btScalar(2.0); + euler_out.roll = -euler_out.pitch + delta; + euler_out2.roll = -euler_out.pitch + delta; + } + } + else + { + euler_out.pitch = - btAsin(m_el[2].x()); + euler_out2.pitch = SIMD_PI - euler_out.pitch; + + euler_out.roll = btAtan2(m_el[2].y()/btCos(euler_out.pitch), + m_el[2].z()/btCos(euler_out.pitch)); + euler_out2.roll = btAtan2(m_el[2].y()/btCos(euler_out2.pitch), + m_el[2].z()/btCos(euler_out2.pitch)); + + euler_out.yaw = btAtan2(m_el[1].x()/btCos(euler_out.pitch), + m_el[0].x()/btCos(euler_out.pitch)); + euler_out2.yaw = btAtan2(m_el[1].x()/btCos(euler_out2.pitch), + m_el[0].x()/btCos(euler_out2.pitch)); + } + + if (solution_number == 1) + { + yaw = euler_out.yaw; + pitch = euler_out.pitch; + roll = euler_out.roll; + } + else + { + yaw = euler_out2.yaw; + pitch = euler_out2.pitch; + roll = euler_out2.roll; + } + } + + /**@brief Create a scaled copy of the matrix + * @param s Scaling vector The elements of the vector will scale each column */ + + btMatrix3x3 scaled(const btVector3& s) const + { + return btMatrix3x3(m_el[0].x() * s.x(), m_el[0].y() * s.y(), m_el[0].z() * s.z(), + m_el[1].x() * s.x(), m_el[1].y() * s.y(), m_el[1].z() * s.z(), + m_el[2].x() * s.x(), m_el[2].y() * s.y(), m_el[2].z() * s.z()); + } + + /**@brief Return the determinant of the matrix */ + btScalar determinant() const; + /**@brief Return the adjoint of the matrix */ + btMatrix3x3 adjoint() const; + /**@brief Return the matrix with all values non negative */ + btMatrix3x3 absolute() const; + /**@brief Return the transpose of the matrix */ + btMatrix3x3 transpose() const; + /**@brief Return the inverse of the matrix */ + btMatrix3x3 inverse() const; + + btMatrix3x3 transposeTimes(const btMatrix3x3& m) const; + btMatrix3x3 timesTranspose(const btMatrix3x3& m) const; + + SIMD_FORCE_INLINE btScalar tdotx(const btVector3& v) const + { + return m_el[0].x() * v.x() + m_el[1].x() * v.y() + m_el[2].x() * v.z(); + } + SIMD_FORCE_INLINE btScalar tdoty(const btVector3& v) const + { + return m_el[0].y() * v.x() + m_el[1].y() * v.y() + m_el[2].y() * v.z(); + } + SIMD_FORCE_INLINE btScalar tdotz(const btVector3& v) const + { + return m_el[0].z() * v.x() + m_el[1].z() * v.y() + m_el[2].z() * v.z(); + } + + + /**@brief diagonalizes this matrix by the Jacobi method. + * @param rot stores the rotation from the coordinate system in which the matrix is diagonal to the original + * coordinate system, i.e., old_this = rot * new_this * rot^T. + * @param threshold See iteration + * @param iteration The iteration stops when all off-diagonal elements are less than the threshold multiplied + * by the sum of the absolute values of the diagonal, or when maxSteps have been executed. + * + * Note that this matrix is assumed to be symmetric. + */ + void diagonalize(btMatrix3x3& rot, btScalar threshold, int maxSteps) + { + rot.setIdentity(); + for (int step = maxSteps; step > 0; step--) + { + // find off-diagonal element [p][q] with largest magnitude + int p = 0; + int q = 1; + int r = 2; + btScalar max = btFabs(m_el[0][1]); + btScalar v = btFabs(m_el[0][2]); + if (v > max) + { + q = 2; + r = 1; + max = v; + } + v = btFabs(m_el[1][2]); + if (v > max) + { + p = 1; + q = 2; + r = 0; + max = v; + } + + btScalar t = threshold * (btFabs(m_el[0][0]) + btFabs(m_el[1][1]) + btFabs(m_el[2][2])); + if (max <= t) + { + if (max <= SIMD_EPSILON * t) + { + return; + } + step = 1; + } + + // compute Jacobi rotation J which leads to a zero for element [p][q] + btScalar mpq = m_el[p][q]; + btScalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq); + btScalar theta2 = theta * theta; + btScalar cos; + btScalar sin; + if (theta2 * theta2 < btScalar(10 / SIMD_EPSILON)) + { + t = (theta >= 0) ? 1 / (theta + btSqrt(1 + theta2)) + : 1 / (theta - btSqrt(1 + theta2)); + cos = 1 / btSqrt(1 + t * t); + sin = cos * t; + } + else + { + // approximation for large theta-value, i.e., a nearly diagonal matrix + t = 1 / (theta * (2 + btScalar(0.5) / theta2)); + cos = 1 - btScalar(0.5) * t * t; + sin = cos * t; + } + + // apply rotation to matrix (this = J^T * this * J) + m_el[p][q] = m_el[q][p] = 0; + m_el[p][p] -= t * mpq; + m_el[q][q] += t * mpq; + btScalar mrp = m_el[r][p]; + btScalar mrq = m_el[r][q]; + m_el[r][p] = m_el[p][r] = cos * mrp - sin * mrq; + m_el[r][q] = m_el[q][r] = cos * mrq + sin * mrp; + + // apply rotation to rot (rot = rot * J) + for (int i = 0; i < 3; i++) + { + btVector3& row = rot[i]; + mrp = row[p]; + mrq = row[q]; + row[p] = cos * mrp - sin * mrq; + row[q] = cos * mrq + sin * mrp; + } + } + } + + + + + /**@brief Calculate the matrix cofactor + * @param r1 The first row to use for calculating the cofactor + * @param c1 The first column to use for calculating the cofactor + * @param r1 The second row to use for calculating the cofactor + * @param c1 The second column to use for calculating the cofactor + * See http://en.wikipedia.org/wiki/Cofactor_(linear_algebra) for more details + */ + btScalar cofac(int r1, int c1, int r2, int c2) const + { + return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1]; + } + + void serialize(struct btMatrix3x3Data& dataOut) const; + + void serializeFloat(struct btMatrix3x3FloatData& dataOut) const; + + void deSerialize(const struct btMatrix3x3Data& dataIn); + + void deSerializeFloat(const struct btMatrix3x3FloatData& dataIn); + + void deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn); + +}; + + +SIMD_FORCE_INLINE btMatrix3x3& +btMatrix3x3::operator*=(const btMatrix3x3& m) +{ + setValue(m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]), + m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]), + m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2])); + return *this; +} + +SIMD_FORCE_INLINE btMatrix3x3& +btMatrix3x3::operator+=(const btMatrix3x3& m) +{ + setValue( + m_el[0][0]+m.m_el[0][0], + m_el[0][1]+m.m_el[0][1], + m_el[0][2]+m.m_el[0][2], + m_el[1][0]+m.m_el[1][0], + m_el[1][1]+m.m_el[1][1], + m_el[1][2]+m.m_el[1][2], + m_el[2][0]+m.m_el[2][0], + m_el[2][1]+m.m_el[2][1], + m_el[2][2]+m.m_el[2][2]); + return *this; +} + +SIMD_FORCE_INLINE btMatrix3x3 +operator*(const btMatrix3x3& m, const btScalar & k) +{ + return btMatrix3x3( + m[0].x()*k,m[0].y()*k,m[0].z()*k, + m[1].x()*k,m[1].y()*k,m[1].z()*k, + m[2].x()*k,m[2].y()*k,m[2].z()*k); +} + + SIMD_FORCE_INLINE btMatrix3x3 +operator+(const btMatrix3x3& m1, const btMatrix3x3& m2) +{ + return btMatrix3x3( + m1[0][0]+m2[0][0], + m1[0][1]+m2[0][1], + m1[0][2]+m2[0][2], + m1[1][0]+m2[1][0], + m1[1][1]+m2[1][1], + m1[1][2]+m2[1][2], + m1[2][0]+m2[2][0], + m1[2][1]+m2[2][1], + m1[2][2]+m2[2][2]); +} + +SIMD_FORCE_INLINE btMatrix3x3 +operator-(const btMatrix3x3& m1, const btMatrix3x3& m2) +{ + return btMatrix3x3( + m1[0][0]-m2[0][0], + m1[0][1]-m2[0][1], + m1[0][2]-m2[0][2], + m1[1][0]-m2[1][0], + m1[1][1]-m2[1][1], + m1[1][2]-m2[1][2], + m1[2][0]-m2[2][0], + m1[2][1]-m2[2][1], + m1[2][2]-m2[2][2]); +} + + +SIMD_FORCE_INLINE btMatrix3x3& +btMatrix3x3::operator-=(const btMatrix3x3& m) +{ + setValue( + m_el[0][0]-m.m_el[0][0], + m_el[0][1]-m.m_el[0][1], + m_el[0][2]-m.m_el[0][2], + m_el[1][0]-m.m_el[1][0], + m_el[1][1]-m.m_el[1][1], + m_el[1][2]-m.m_el[1][2], + m_el[2][0]-m.m_el[2][0], + m_el[2][1]-m.m_el[2][1], + m_el[2][2]-m.m_el[2][2]); + return *this; +} + + +SIMD_FORCE_INLINE btScalar +btMatrix3x3::determinant() const +{ + return btTriple((*this)[0], (*this)[1], (*this)[2]); +} + + +SIMD_FORCE_INLINE btMatrix3x3 +btMatrix3x3::absolute() const +{ + return btMatrix3x3( + btFabs(m_el[0].x()), btFabs(m_el[0].y()), btFabs(m_el[0].z()), + btFabs(m_el[1].x()), btFabs(m_el[1].y()), btFabs(m_el[1].z()), + btFabs(m_el[2].x()), btFabs(m_el[2].y()), btFabs(m_el[2].z())); +} + +SIMD_FORCE_INLINE btMatrix3x3 +btMatrix3x3::transpose() const +{ + return btMatrix3x3(m_el[0].x(), m_el[1].x(), m_el[2].x(), + m_el[0].y(), m_el[1].y(), m_el[2].y(), + m_el[0].z(), m_el[1].z(), m_el[2].z()); +} + +SIMD_FORCE_INLINE btMatrix3x3 +btMatrix3x3::adjoint() const +{ + return btMatrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2), + cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0), + cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1)); +} + +SIMD_FORCE_INLINE btMatrix3x3 +btMatrix3x3::inverse() const +{ + btVector3 co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1)); + btScalar det = (*this)[0].dot(co); + btFullAssert(det != btScalar(0.0)); + btScalar s = btScalar(1.0) / det; + return btMatrix3x3(co.x() * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s, + co.y() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s, + co.z() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s); +} + +SIMD_FORCE_INLINE btMatrix3x3 +btMatrix3x3::transposeTimes(const btMatrix3x3& m) const +{ + return btMatrix3x3( + m_el[0].x() * m[0].x() + m_el[1].x() * m[1].x() + m_el[2].x() * m[2].x(), + m_el[0].x() * m[0].y() + m_el[1].x() * m[1].y() + m_el[2].x() * m[2].y(), + m_el[0].x() * m[0].z() + m_el[1].x() * m[1].z() + m_el[2].x() * m[2].z(), + m_el[0].y() * m[0].x() + m_el[1].y() * m[1].x() + m_el[2].y() * m[2].x(), + m_el[0].y() * m[0].y() + m_el[1].y() * m[1].y() + m_el[2].y() * m[2].y(), + m_el[0].y() * m[0].z() + m_el[1].y() * m[1].z() + m_el[2].y() * m[2].z(), + m_el[0].z() * m[0].x() + m_el[1].z() * m[1].x() + m_el[2].z() * m[2].x(), + m_el[0].z() * m[0].y() + m_el[1].z() * m[1].y() + m_el[2].z() * m[2].y(), + m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].z()); +} + +SIMD_FORCE_INLINE btMatrix3x3 +btMatrix3x3::timesTranspose(const btMatrix3x3& m) const +{ + return btMatrix3x3( + m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]), + m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]), + m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2])); + +} + +SIMD_FORCE_INLINE btVector3 +operator*(const btMatrix3x3& m, const btVector3& v) +{ + return btVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v)); +} + + +SIMD_FORCE_INLINE btVector3 +operator*(const btVector3& v, const btMatrix3x3& m) +{ + return btVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v)); +} + +SIMD_FORCE_INLINE btMatrix3x3 +operator*(const btMatrix3x3& m1, const btMatrix3x3& m2) +{ + return btMatrix3x3( + m2.tdotx( m1[0]), m2.tdoty( m1[0]), m2.tdotz( m1[0]), + m2.tdotx( m1[1]), m2.tdoty( m1[1]), m2.tdotz( m1[1]), + m2.tdotx( m1[2]), m2.tdoty( m1[2]), m2.tdotz( m1[2])); +} + +/* +SIMD_FORCE_INLINE btMatrix3x3 btMultTransposeLeft(const btMatrix3x3& m1, const btMatrix3x3& m2) { +return btMatrix3x3( +m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0], +m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1], +m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2], +m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0], +m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1], +m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2], +m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0], +m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1], +m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]); +} +*/ + +/**@brief Equality operator between two matrices +* It will test all elements are equal. */ +SIMD_FORCE_INLINE bool operator==(const btMatrix3x3& m1, const btMatrix3x3& m2) +{ + return ( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] && + m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] && + m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2] ); +} + +///for serialization +struct btMatrix3x3FloatData +{ + btVector3FloatData m_el[3]; +}; + +///for serialization +struct btMatrix3x3DoubleData +{ + btVector3DoubleData m_el[3]; +}; + + + + +SIMD_FORCE_INLINE void btMatrix3x3::serialize(struct btMatrix3x3Data& dataOut) const +{ + for (int i=0;i<3;i++) + m_el[i].serialize(dataOut.m_el[i]); +} + +SIMD_FORCE_INLINE void btMatrix3x3::serializeFloat(struct btMatrix3x3FloatData& dataOut) const +{ + for (int i=0;i<3;i++) + m_el[i].serializeFloat(dataOut.m_el[i]); +} + + +SIMD_FORCE_INLINE void btMatrix3x3::deSerialize(const struct btMatrix3x3Data& dataIn) +{ + for (int i=0;i<3;i++) + m_el[i].deSerialize(dataIn.m_el[i]); +} + +SIMD_FORCE_INLINE void btMatrix3x3::deSerializeFloat(const struct btMatrix3x3FloatData& dataIn) +{ + for (int i=0;i<3;i++) + m_el[i].deSerializeFloat(dataIn.m_el[i]); +} + +SIMD_FORCE_INLINE void btMatrix3x3::deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn) +{ + for (int i=0;i<3;i++) + m_el[i].deSerializeDouble(dataIn.m_el[i]); +} + +#endif //BT_MATRIX3x3_H + diff --git a/src/LinearMath/btMinMax.h b/src/LinearMath/btMinMax.h new file mode 100644 index 0000000..5b436e9 --- /dev/null +++ b/src/LinearMath/btMinMax.h @@ -0,0 +1,71 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_GEN_MINMAX_H +#define BT_GEN_MINMAX_H + +#include "btScalar.h" + +template +SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b) +{ + return a < b ? a : b ; +} + +template +SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b) +{ + return a > b ? a : b; +} + +template +SIMD_FORCE_INLINE const T& btClamped(const T& a, const T& lb, const T& ub) +{ + return a < lb ? lb : (ub < a ? ub : a); +} + +template +SIMD_FORCE_INLINE void btSetMin(T& a, const T& b) +{ + if (b < a) + { + a = b; + } +} + +template +SIMD_FORCE_INLINE void btSetMax(T& a, const T& b) +{ + if (a < b) + { + a = b; + } +} + +template +SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub) +{ + if (a < lb) + { + a = lb; + } + else if (ub < a) + { + a = ub; + } +} + +#endif //BT_GEN_MINMAX_H diff --git a/src/LinearMath/btMotionState.h b/src/LinearMath/btMotionState.h new file mode 100644 index 0000000..9431814 --- /dev/null +++ b/src/LinearMath/btMotionState.h @@ -0,0 +1,40 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_MOTIONSTATE_H +#define BT_MOTIONSTATE_H + +#include "btTransform.h" + +///The btMotionState interface class allows the dynamics world to synchronize and interpolate the updated world transforms with graphics +///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation) +class btMotionState +{ + public: + + virtual ~btMotionState() + { + + } + + virtual void getWorldTransform(btTransform& worldTrans ) const =0; + + //Bullet only calls the update of worldtransform for active objects + virtual void setWorldTransform(const btTransform& worldTrans)=0; + + +}; + +#endif //BT_MOTIONSTATE_H diff --git a/src/LinearMath/btPoolAllocator.h b/src/LinearMath/btPoolAllocator.h new file mode 100755 index 0000000..ef20845 --- /dev/null +++ b/src/LinearMath/btPoolAllocator.h @@ -0,0 +1,121 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef _BT_POOL_ALLOCATOR_H +#define _BT_POOL_ALLOCATOR_H + +#include "btScalar.h" +#include "btAlignedAllocator.h" + +///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately. +class btPoolAllocator +{ + int m_elemSize; + int m_maxElements; + int m_freeCount; + void* m_firstFree; + unsigned char* m_pool; + +public: + + btPoolAllocator(int elemSize, int maxElements) + :m_elemSize(elemSize), + m_maxElements(maxElements) + { + m_pool = (unsigned char*) btAlignedAlloc( static_cast(m_elemSize*m_maxElements),16); + + unsigned char* p = m_pool; + m_firstFree = p; + m_freeCount = m_maxElements; + int count = m_maxElements; + while (--count) { + *(void**)p = (p + m_elemSize); + p += m_elemSize; + } + *(void**)p = 0; + } + + ~btPoolAllocator() + { + btAlignedFree( m_pool); + } + + int getFreeCount() const + { + return m_freeCount; + } + + int getUsedCount() const + { + return m_maxElements - m_freeCount; + } + + int getMaxCount() const + { + return m_maxElements; + } + + void* allocate(int size) + { + // release mode fix + (void)size; + btAssert(!size || size<=m_elemSize); + btAssert(m_freeCount>0); + void* result = m_firstFree; + m_firstFree = *(void**)m_firstFree; + --m_freeCount; + return result; + } + + bool validPtr(void* ptr) + { + if (ptr) { + if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize)) + { + return true; + } + } + return false; + } + + void freeMemory(void* ptr) + { + if (ptr) { + btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize); + + *(void**)ptr = m_firstFree; + m_firstFree = ptr; + ++m_freeCount; + } + } + + int getElementSize() const + { + return m_elemSize; + } + + unsigned char* getPoolAddress() + { + return m_pool; + } + + const unsigned char* getPoolAddress() const + { + return m_pool; + } + +}; + +#endif //_BT_POOL_ALLOCATOR_H diff --git a/src/LinearMath/btQuadWord.h b/src/LinearMath/btQuadWord.h new file mode 100644 index 0000000..d5e9daa --- /dev/null +++ b/src/LinearMath/btQuadWord.h @@ -0,0 +1,180 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_SIMD_QUADWORD_H +#define BT_SIMD_QUADWORD_H + +#include "btScalar.h" +#include "btMinMax.h" + + +#if defined (__CELLOS_LV2) && defined (__SPU__) +#include +#endif + +/**@brief The btQuadWord class is base class for btVector3 and btQuaternion. + * Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword. + */ +#ifndef USE_LIBSPE2 +ATTRIBUTE_ALIGNED16(class) btQuadWord +#else +class btQuadWord +#endif +{ +protected: + +#if defined (__SPU__) && defined (__CELLOS_LV2__) + union { + vec_float4 mVec128; + btScalar m_floats[4]; + }; +public: + vec_float4 get128() const + { + return mVec128; + } +protected: +#else //__CELLOS_LV2__ __SPU__ + btScalar m_floats[4]; +#endif //__CELLOS_LV2__ __SPU__ + + public: + + + /**@brief Return the x value */ + SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; } + /**@brief Return the y value */ + SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; } + /**@brief Return the z value */ + SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; } + /**@brief Set the x value */ + SIMD_FORCE_INLINE void setX(btScalar x) { m_floats[0] = x;}; + /**@brief Set the y value */ + SIMD_FORCE_INLINE void setY(btScalar y) { m_floats[1] = y;}; + /**@brief Set the z value */ + SIMD_FORCE_INLINE void setZ(btScalar z) { m_floats[2] = z;}; + /**@brief Set the w value */ + SIMD_FORCE_INLINE void setW(btScalar w) { m_floats[3] = w;}; + /**@brief Return the x value */ + SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; } + /**@brief Return the y value */ + SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; } + /**@brief Return the z value */ + SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; } + /**@brief Return the w value */ + SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; } + + //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; } + //SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; } + ///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons. + SIMD_FORCE_INLINE operator btScalar *() { return &m_floats[0]; } + SIMD_FORCE_INLINE operator const btScalar *() const { return &m_floats[0]; } + + SIMD_FORCE_INLINE bool operator==(const btQuadWord& other) const + { + return ((m_floats[3]==other.m_floats[3]) && (m_floats[2]==other.m_floats[2]) && (m_floats[1]==other.m_floats[1]) && (m_floats[0]==other.m_floats[0])); + } + + SIMD_FORCE_INLINE bool operator!=(const btQuadWord& other) const + { + return !(*this == other); + } + + /**@brief Set x,y,z and zero w + * @param x Value of x + * @param y Value of y + * @param z Value of z + */ + SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z) + { + m_floats[0]=x; + m_floats[1]=y; + m_floats[2]=z; + m_floats[3] = 0.f; + } + +/* void getValue(btScalar *m) const + { + m[0] = m_floats[0]; + m[1] = m_floats[1]; + m[2] = m_floats[2]; + } +*/ +/**@brief Set the values + * @param x Value of x + * @param y Value of y + * @param z Value of z + * @param w Value of w + */ + SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) + { + m_floats[0]=x; + m_floats[1]=y; + m_floats[2]=z; + m_floats[3]=w; + } + /**@brief No initialization constructor */ + SIMD_FORCE_INLINE btQuadWord() + // :m_floats[0](btScalar(0.)),m_floats[1](btScalar(0.)),m_floats[2](btScalar(0.)),m_floats[3](btScalar(0.)) + { + } + + /**@brief Three argument constructor (zeros w) + * @param x Value of x + * @param y Value of y + * @param z Value of z + */ + SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z) + { + m_floats[0] = x, m_floats[1] = y, m_floats[2] = z, m_floats[3] = 0.0f; + } + +/**@brief Initializing constructor + * @param x Value of x + * @param y Value of y + * @param z Value of z + * @param w Value of w + */ + SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) + { + m_floats[0] = x, m_floats[1] = y, m_floats[2] = z, m_floats[3] = w; + } + + /**@brief Set each element to the max of the current values and the values of another btQuadWord + * @param other The other btQuadWord to compare with + */ + SIMD_FORCE_INLINE void setMax(const btQuadWord& other) + { + btSetMax(m_floats[0], other.m_floats[0]); + btSetMax(m_floats[1], other.m_floats[1]); + btSetMax(m_floats[2], other.m_floats[2]); + btSetMax(m_floats[3], other.m_floats[3]); + } + /**@brief Set each element to the min of the current values and the values of another btQuadWord + * @param other The other btQuadWord to compare with + */ + SIMD_FORCE_INLINE void setMin(const btQuadWord& other) + { + btSetMin(m_floats[0], other.m_floats[0]); + btSetMin(m_floats[1], other.m_floats[1]); + btSetMin(m_floats[2], other.m_floats[2]); + btSetMin(m_floats[3], other.m_floats[3]); + } + + + +}; + +#endif //BT_SIMD_QUADWORD_H diff --git a/src/LinearMath/btQuaternion.h b/src/LinearMath/btQuaternion.h new file mode 100644 index 0000000..ee79f6e --- /dev/null +++ b/src/LinearMath/btQuaternion.h @@ -0,0 +1,430 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_SIMD__QUATERNION_H_ +#define BT_SIMD__QUATERNION_H_ + + +#include "btVector3.h" +#include "btQuadWord.h" + +/**@brief The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. */ +class btQuaternion : public btQuadWord { +public: + /**@brief No initialization constructor */ + btQuaternion() {} + + // template + // explicit Quaternion(const btScalar *v) : Tuple4(v) {} + /**@brief Constructor from scalars */ + btQuaternion(const btScalar& x, const btScalar& y, const btScalar& z, const btScalar& w) + : btQuadWord(x, y, z, w) + {} + /**@brief Axis angle Constructor + * @param axis The axis which the rotation is around + * @param angle The magnitude of the rotation around the angle (Radians) */ + btQuaternion(const btVector3& axis, const btScalar& angle) + { + setRotation(axis, angle); + } + /**@brief Constructor from Euler angles + * @param yaw Angle around Y unless BT_EULER_DEFAULT_ZYX defined then Z + * @param pitch Angle around X unless BT_EULER_DEFAULT_ZYX defined then Y + * @param roll Angle around Z unless BT_EULER_DEFAULT_ZYX defined then X */ + btQuaternion(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) + { +#ifndef BT_EULER_DEFAULT_ZYX + setEuler(yaw, pitch, roll); +#else + setEulerZYX(yaw, pitch, roll); +#endif + } + /**@brief Set the rotation using axis angle notation + * @param axis The axis around which to rotate + * @param angle The magnitude of the rotation in Radians */ + void setRotation(const btVector3& axis, const btScalar& angle) + { + btScalar d = axis.length(); + btAssert(d != btScalar(0.0)); + btScalar s = btSin(angle * btScalar(0.5)) / d; + setValue(axis.x() * s, axis.y() * s, axis.z() * s, + btCos(angle * btScalar(0.5))); + } + /**@brief Set the quaternion using Euler angles + * @param yaw Angle around Y + * @param pitch Angle around X + * @param roll Angle around Z */ + void setEuler(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) + { + btScalar halfYaw = btScalar(yaw) * btScalar(0.5); + btScalar halfPitch = btScalar(pitch) * btScalar(0.5); + btScalar halfRoll = btScalar(roll) * btScalar(0.5); + btScalar cosYaw = btCos(halfYaw); + btScalar sinYaw = btSin(halfYaw); + btScalar cosPitch = btCos(halfPitch); + btScalar sinPitch = btSin(halfPitch); + btScalar cosRoll = btCos(halfRoll); + btScalar sinRoll = btSin(halfRoll); + setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, + cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, + sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, + cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); + } + /**@brief Set the quaternion using euler angles + * @param yaw Angle around Z + * @param pitch Angle around Y + * @param roll Angle around X */ + void setEulerZYX(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) + { + btScalar halfYaw = btScalar(yaw) * btScalar(0.5); + btScalar halfPitch = btScalar(pitch) * btScalar(0.5); + btScalar halfRoll = btScalar(roll) * btScalar(0.5); + btScalar cosYaw = btCos(halfYaw); + btScalar sinYaw = btSin(halfYaw); + btScalar cosPitch = btCos(halfPitch); + btScalar sinPitch = btSin(halfPitch); + btScalar cosRoll = btCos(halfRoll); + btScalar sinRoll = btSin(halfRoll); + setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x + cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y + cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z + cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx + } + /**@brief Add two quaternions + * @param q The quaternion to add to this one */ + SIMD_FORCE_INLINE btQuaternion& operator+=(const btQuaternion& q) + { + m_floats[0] += q.x(); m_floats[1] += q.y(); m_floats[2] += q.z(); m_floats[3] += q.m_floats[3]; + return *this; + } + + /**@brief Subtract out a quaternion + * @param q The quaternion to subtract from this one */ + btQuaternion& operator-=(const btQuaternion& q) + { + m_floats[0] -= q.x(); m_floats[1] -= q.y(); m_floats[2] -= q.z(); m_floats[3] -= q.m_floats[3]; + return *this; + } + + /**@brief Scale this quaternion + * @param s The scalar to scale by */ + btQuaternion& operator*=(const btScalar& s) + { + m_floats[0] *= s; m_floats[1] *= s; m_floats[2] *= s; m_floats[3] *= s; + return *this; + } + + /**@brief Multiply this quaternion by q on the right + * @param q The other quaternion + * Equivilant to this = this * q */ + btQuaternion& operator*=(const btQuaternion& q) + { + setValue(m_floats[3] * q.x() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.z() - m_floats[2] * q.y(), + m_floats[3] * q.y() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.x() - m_floats[0] * q.z(), + m_floats[3] * q.z() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.y() - m_floats[1] * q.x(), + m_floats[3] * q.m_floats[3] - m_floats[0] * q.x() - m_floats[1] * q.y() - m_floats[2] * q.z()); + return *this; + } + /**@brief Return the dot product between this quaternion and another + * @param q The other quaternion */ + btScalar dot(const btQuaternion& q) const + { + return m_floats[0] * q.x() + m_floats[1] * q.y() + m_floats[2] * q.z() + m_floats[3] * q.m_floats[3]; + } + + /**@brief Return the length squared of the quaternion */ + btScalar length2() const + { + return dot(*this); + } + + /**@brief Return the length of the quaternion */ + btScalar length() const + { + return btSqrt(length2()); + } + + /**@brief Normalize the quaternion + * Such that x^2 + y^2 + z^2 +w^2 = 1 */ + btQuaternion& normalize() + { + return *this /= length(); + } + + /**@brief Return a scaled version of this quaternion + * @param s The scale factor */ + SIMD_FORCE_INLINE btQuaternion + operator*(const btScalar& s) const + { + return btQuaternion(x() * s, y() * s, z() * s, m_floats[3] * s); + } + + + /**@brief Return an inversely scaled versionof this quaternion + * @param s The inverse scale factor */ + btQuaternion operator/(const btScalar& s) const + { + btAssert(s != btScalar(0.0)); + return *this * (btScalar(1.0) / s); + } + + /**@brief Inversely scale this quaternion + * @param s The scale factor */ + btQuaternion& operator/=(const btScalar& s) + { + btAssert(s != btScalar(0.0)); + return *this *= btScalar(1.0) / s; + } + + /**@brief Return a normalized version of this quaternion */ + btQuaternion normalized() const + { + return *this / length(); + } + /**@brief Return the angle between this quaternion and the other + * @param q The other quaternion */ + btScalar angle(const btQuaternion& q) const + { + btScalar s = btSqrt(length2() * q.length2()); + btAssert(s != btScalar(0.0)); + return btAcos(dot(q) / s); + } + /**@brief Return the angle of rotation represented by this quaternion */ + btScalar getAngle() const + { + btScalar s = btScalar(2.) * btAcos(m_floats[3]); + return s; + } + + /**@brief Return the axis of the rotation represented by this quaternion */ + btVector3 getAxis() const + { + btScalar s_squared = 1.f-m_floats[3]*m_floats[3]; + + if (s_squared < btScalar(10.) * SIMD_EPSILON) //Check for divide by zero + return btVector3(1.0, 0.0, 0.0); // Arbitrary + btScalar s = 1.f/btSqrt(s_squared); + return btVector3(m_floats[0] * s, m_floats[1] * s, m_floats[2] * s); + } + + /**@brief Return the inverse of this quaternion */ + btQuaternion inverse() const + { + return btQuaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]); + } + + /**@brief Return the sum of this quaternion and the other + * @param q2 The other quaternion */ + SIMD_FORCE_INLINE btQuaternion + operator+(const btQuaternion& q2) const + { + const btQuaternion& q1 = *this; + return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_floats[3] + q2.m_floats[3]); + } + + /**@brief Return the difference between this quaternion and the other + * @param q2 The other quaternion */ + SIMD_FORCE_INLINE btQuaternion + operator-(const btQuaternion& q2) const + { + const btQuaternion& q1 = *this; + return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_floats[3] - q2.m_floats[3]); + } + + /**@brief Return the negative of this quaternion + * This simply negates each element */ + SIMD_FORCE_INLINE btQuaternion operator-() const + { + const btQuaternion& q2 = *this; + return btQuaternion( - q2.x(), - q2.y(), - q2.z(), - q2.m_floats[3]); + } + /**@todo document this and it's use */ + SIMD_FORCE_INLINE btQuaternion farthest( const btQuaternion& qd) const + { + btQuaternion diff,sum; + diff = *this - qd; + sum = *this + qd; + if( diff.dot(diff) > sum.dot(sum) ) + return qd; + return (-qd); + } + + /**@todo document this and it's use */ + SIMD_FORCE_INLINE btQuaternion nearest( const btQuaternion& qd) const + { + btQuaternion diff,sum; + diff = *this - qd; + sum = *this + qd; + if( diff.dot(diff) < sum.dot(sum) ) + return qd; + return (-qd); + } + + + /**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion + * @param q The other quaternion to interpolate with + * @param t The ratio between this and q to interpolate. If t = 0 the result is this, if t=1 the result is q. + * Slerp interpolates assuming constant velocity. */ + btQuaternion slerp(const btQuaternion& q, const btScalar& t) const + { + btScalar magnitude = btSqrt(length2() * q.length2()); + btAssert(magnitude > btScalar(0)); + + btScalar product = dot(q) / magnitude; + if (btFabs(product) != btScalar(1)) + { + // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp + const btScalar sign = (product < 0) ? btScalar(-1) : btScalar(1); + + const btScalar theta = btAcos(sign * product); + const btScalar s1 = btSin(sign * t * theta); + const btScalar d = btScalar(1.0) / btSin(theta); + const btScalar s0 = btSin((btScalar(1.0) - t) * theta); + + return btQuaternion( + (m_floats[0] * s0 + q.x() * s1) * d, + (m_floats[1] * s0 + q.y() * s1) * d, + (m_floats[2] * s0 + q.z() * s1) * d, + (m_floats[3] * s0 + q.m_floats[3] * s1) * d); + } + else + { + return *this; + } + } + + static const btQuaternion& getIdentity() + { + static const btQuaternion identityQuat(btScalar(0.),btScalar(0.),btScalar(0.),btScalar(1.)); + return identityQuat; + } + + SIMD_FORCE_INLINE const btScalar& getW() const { return m_floats[3]; } + + +}; + + + + + +/**@brief Return the product of two quaternions */ +SIMD_FORCE_INLINE btQuaternion +operator*(const btQuaternion& q1, const btQuaternion& q2) { + return btQuaternion(q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(), + q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(), + q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(), + q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z()); +} + +SIMD_FORCE_INLINE btQuaternion +operator*(const btQuaternion& q, const btVector3& w) +{ + return btQuaternion( q.w() * w.x() + q.y() * w.z() - q.z() * w.y(), + q.w() * w.y() + q.z() * w.x() - q.x() * w.z(), + q.w() * w.z() + q.x() * w.y() - q.y() * w.x(), + -q.x() * w.x() - q.y() * w.y() - q.z() * w.z()); +} + +SIMD_FORCE_INLINE btQuaternion +operator*(const btVector3& w, const btQuaternion& q) +{ + return btQuaternion( w.x() * q.w() + w.y() * q.z() - w.z() * q.y(), + w.y() * q.w() + w.z() * q.x() - w.x() * q.z(), + w.z() * q.w() + w.x() * q.y() - w.y() * q.x(), + -w.x() * q.x() - w.y() * q.y() - w.z() * q.z()); +} + +/**@brief Calculate the dot product between two quaternions */ +SIMD_FORCE_INLINE btScalar +dot(const btQuaternion& q1, const btQuaternion& q2) +{ + return q1.dot(q2); +} + + +/**@brief Return the length of a quaternion */ +SIMD_FORCE_INLINE btScalar +length(const btQuaternion& q) +{ + return q.length(); +} + +/**@brief Return the angle between two quaternions*/ +SIMD_FORCE_INLINE btScalar +angle(const btQuaternion& q1, const btQuaternion& q2) +{ + return q1.angle(q2); +} + +/**@brief Return the inverse of a quaternion*/ +SIMD_FORCE_INLINE btQuaternion +inverse(const btQuaternion& q) +{ + return q.inverse(); +} + +/**@brief Return the result of spherical linear interpolation betwen two quaternions + * @param q1 The first quaternion + * @param q2 The second quaternion + * @param t The ration between q1 and q2. t = 0 return q1, t=1 returns q2 + * Slerp assumes constant velocity between positions. */ +SIMD_FORCE_INLINE btQuaternion +slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t) +{ + return q1.slerp(q2, t); +} + +SIMD_FORCE_INLINE btVector3 +quatRotate(const btQuaternion& rotation, const btVector3& v) +{ + btQuaternion q = rotation * v; + q *= rotation.inverse(); + return btVector3(q.getX(),q.getY(),q.getZ()); +} + +SIMD_FORCE_INLINE btQuaternion +shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized +{ + btVector3 c = v0.cross(v1); + btScalar d = v0.dot(v1); + + if (d < -1.0 + SIMD_EPSILON) + { + btVector3 n,unused; + btPlaneSpace1(v0,n,unused); + return btQuaternion(n.x(),n.y(),n.z(),0.0f); // just pick any vector that is orthogonal to v0 + } + + btScalar s = btSqrt((1.0f + d) * 2.0f); + btScalar rs = 1.0f / s; + + return btQuaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f); +} + +SIMD_FORCE_INLINE btQuaternion +shortestArcQuatNormalize2(btVector3& v0,btVector3& v1) +{ + v0.normalize(); + v1.normalize(); + return shortestArcQuat(v0,v1); +} + +#endif //BT_SIMD__QUATERNION_H_ + + + + diff --git a/src/LinearMath/btQuickprof.cpp b/src/LinearMath/btQuickprof.cpp new file mode 100644 index 0000000..544aee8 --- /dev/null +++ b/src/LinearMath/btQuickprof.cpp @@ -0,0 +1,566 @@ +/* + +*************************************************************************************************** +** +** profile.cpp +** +** Real-Time Hierarchical Profiling for Game Programming Gems 3 +** +** by Greg Hjelstrom & Byon Garrabrant +** +***************************************************************************************************/ + +// Credits: The Clock class was inspired by the Timer classes in +// Ogre (www.ogre3d.org). + +#include "btQuickprof.h" + +#ifndef BT_NO_PROFILE + + +static btClock gProfileClock; + + +#ifdef __CELLOS_LV2__ +#include +#include +#include +#endif + +#if defined (SUNOS) || defined (__SUNOS__) +#include +#endif + +#if defined(WIN32) || defined(_WIN32) + +#define BT_USE_WINDOWS_TIMERS +#define WIN32_LEAN_AND_MEAN +#define NOWINRES +#define NOMCX +#define NOIME + +#ifdef _XBOX + #include +#else //_XBOX + #include +#endif //_XBOX + +#include + + +#else //_WIN32 +#include +#endif //_WIN32 + +#define mymin(a,b) (a > b ? a : b) + +struct btClockData +{ + +#ifdef BT_USE_WINDOWS_TIMERS + LARGE_INTEGER mClockFrequency; + DWORD mStartTick; + LONGLONG mPrevElapsedTime; + LARGE_INTEGER mStartTime; +#else +#ifdef __CELLOS_LV2__ + uint64_t mStartTime; +#else + struct timeval mStartTime; +#endif +#endif //__CELLOS_LV2__ + +}; + +///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling. +btClock::btClock() +{ + m_data = new btClockData; +#ifdef BT_USE_WINDOWS_TIMERS + QueryPerformanceFrequency(&m_data->mClockFrequency); +#endif + reset(); +} + +btClock::~btClock() +{ + delete m_data; +} + +btClock::btClock(const btClock& other) +{ + m_data = new btClockData; + *m_data = *other.m_data; +} + +btClock& btClock::operator=(const btClock& other) +{ + *m_data = *other.m_data; + return *this; +} + + + /// Resets the initial reference time. +void btClock::reset() +{ +#ifdef BT_USE_WINDOWS_TIMERS + QueryPerformanceCounter(&m_data->mStartTime); + m_data->mStartTick = GetTickCount(); + m_data->mPrevElapsedTime = 0; +#else +#ifdef __CELLOS_LV2__ + + typedef uint64_t ClockSize; + ClockSize newTime; + //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + SYS_TIMEBASE_GET( newTime ); + m_data->mStartTime = newTime; +#else + gettimeofday(&m_data->mStartTime, 0); +#endif +#endif +} + +/// Returns the time in ms since the last call to reset or since +/// the btClock was created. +unsigned long int btClock::getTimeMilliseconds() +{ +#ifdef BT_USE_WINDOWS_TIMERS + LARGE_INTEGER currentTime; + QueryPerformanceCounter(¤tTime); + LONGLONG elapsedTime = currentTime.QuadPart - + m_data->mStartTime.QuadPart; + // Compute the number of millisecond ticks elapsed. + unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / + m_data->mClockFrequency.QuadPart); + // Check for unexpected leaps in the Win32 performance counter. + // (This is caused by unexpected data across the PCI to ISA + // bridge, aka south bridge. See Microsoft KB274323.) + unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick; + signed long msecOff = (signed long)(msecTicks - elapsedTicks); + if (msecOff < -100 || msecOff > 100) + { + // Adjust the starting time forwards. + LONGLONG msecAdjustment = mymin(msecOff * + m_data->mClockFrequency.QuadPart / 1000, elapsedTime - + m_data->mPrevElapsedTime); + m_data->mStartTime.QuadPart += msecAdjustment; + elapsedTime -= msecAdjustment; + + // Recompute the number of millisecond ticks elapsed. + msecTicks = (unsigned long)(1000 * elapsedTime / + m_data->mClockFrequency.QuadPart); + } + + // Store the current elapsed time for adjustments next time. + m_data->mPrevElapsedTime = elapsedTime; + + return msecTicks; +#else + +#ifdef __CELLOS_LV2__ + uint64_t freq=sys_time_get_timebase_frequency(); + double dFreq=((double) freq) / 1000.0; + typedef uint64_t ClockSize; + ClockSize newTime; + SYS_TIMEBASE_GET( newTime ); + //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + + return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq); +#else + + struct timeval currentTime; + gettimeofday(¤tTime, 0); + return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 + + (currentTime.tv_usec - m_data->mStartTime.tv_usec) / 1000; +#endif //__CELLOS_LV2__ +#endif +} + + /// Returns the time in us since the last call to reset or since + /// the Clock was created. +unsigned long int btClock::getTimeMicroseconds() +{ +#ifdef BT_USE_WINDOWS_TIMERS + LARGE_INTEGER currentTime; + QueryPerformanceCounter(¤tTime); + LONGLONG elapsedTime = currentTime.QuadPart - + m_data->mStartTime.QuadPart; + + // Compute the number of millisecond ticks elapsed. + unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / + m_data->mClockFrequency.QuadPart); + + // Check for unexpected leaps in the Win32 performance counter. + // (This is caused by unexpected data across the PCI to ISA + // bridge, aka south bridge. See Microsoft KB274323.) + unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick; + signed long msecOff = (signed long)(msecTicks - elapsedTicks); + if (msecOff < -100 || msecOff > 100) + { + // Adjust the starting time forwards. + LONGLONG msecAdjustment = mymin(msecOff * + m_data->mClockFrequency.QuadPart / 1000, elapsedTime - + m_data->mPrevElapsedTime); + m_data->mStartTime.QuadPart += msecAdjustment; + elapsedTime -= msecAdjustment; + } + + // Store the current elapsed time for adjustments next time. + m_data->mPrevElapsedTime = elapsedTime; + + // Convert to microseconds. + unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / + m_data->mClockFrequency.QuadPart); + + return usecTicks; +#else + +#ifdef __CELLOS_LV2__ + uint64_t freq=sys_time_get_timebase_frequency(); + double dFreq=((double) freq)/ 1000000.0; + typedef uint64_t ClockSize; + ClockSize newTime; + //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + SYS_TIMEBASE_GET( newTime ); + + return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq); +#else + + struct timeval currentTime; + gettimeofday(¤tTime, 0); + return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 + + (currentTime.tv_usec - m_data->mStartTime.tv_usec); +#endif//__CELLOS_LV2__ +#endif +} + + + + + +inline void Profile_Get_Ticks(unsigned long int * ticks) +{ + *ticks = gProfileClock.getTimeMicroseconds(); +} + +inline float Profile_Get_Tick_Rate(void) +{ +// return 1000000.f; + return 1000.f; + +} + + + +/*************************************************************************************************** +** +** CProfileNode +** +***************************************************************************************************/ + +/*********************************************************************************************** + * INPUT: * + * name - pointer to a static string which is the name of this profile node * + * parent - parent pointer * + * * + * WARNINGS: * + * The name is assumed to be a static pointer, only the pointer is stored and compared for * + * efficiency reasons. * + *=============================================================================================*/ +CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) : + Name( name ), + TotalCalls( 0 ), + TotalTime( 0 ), + StartTime( 0 ), + RecursionCounter( 0 ), + Parent( parent ), + Child( NULL ), + Sibling( NULL ), + m_userPtr(0) +{ + Reset(); +} + + +void CProfileNode::CleanupMemory() +{ + delete ( Child); + Child = NULL; + delete ( Sibling); + Sibling = NULL; +} + +CProfileNode::~CProfileNode( void ) +{ + delete ( Child); + delete ( Sibling); +} + + +/*********************************************************************************************** + * INPUT: * + * name - static string pointer to the name of the node we are searching for * + * * + * WARNINGS: * + * All profile names are assumed to be static strings so this function uses pointer compares * + * to find the named node. * + *=============================================================================================*/ +CProfileNode * CProfileNode::Get_Sub_Node( const char * name ) +{ + // Try to find this sub node + CProfileNode * child = Child; + while ( child ) { + if ( child->Name == name ) { + return child; + } + child = child->Sibling; + } + + // We didn't find it, so add it + + CProfileNode * node = new CProfileNode( name, this ); + node->Sibling = Child; + Child = node; + return node; +} + + +void CProfileNode::Reset( void ) +{ + TotalCalls = 0; + TotalTime = 0.0f; + + + if ( Child ) { + Child->Reset(); + } + if ( Sibling ) { + Sibling->Reset(); + } +} + + +void CProfileNode::Call( void ) +{ + TotalCalls++; + if (RecursionCounter++ == 0) { + Profile_Get_Ticks(&StartTime); + } +} + + +bool CProfileNode::Return( void ) +{ + if ( --RecursionCounter == 0 && TotalCalls != 0 ) { + unsigned long int time; + Profile_Get_Ticks(&time); + time-=StartTime; + TotalTime += (float)time / Profile_Get_Tick_Rate(); + } + return ( RecursionCounter == 0 ); +} + + +/*************************************************************************************************** +** +** CProfileIterator +** +***************************************************************************************************/ +CProfileIterator::CProfileIterator( CProfileNode * start ) +{ + CurrentParent = start; + CurrentChild = CurrentParent->Get_Child(); +} + + +void CProfileIterator::First(void) +{ + CurrentChild = CurrentParent->Get_Child(); +} + + +void CProfileIterator::Next(void) +{ + CurrentChild = CurrentChild->Get_Sibling(); +} + + +bool CProfileIterator::Is_Done(void) +{ + return CurrentChild == NULL; +} + + +void CProfileIterator::Enter_Child( int index ) +{ + CurrentChild = CurrentParent->Get_Child(); + while ( (CurrentChild != NULL) && (index != 0) ) { + index--; + CurrentChild = CurrentChild->Get_Sibling(); + } + + if ( CurrentChild != NULL ) { + CurrentParent = CurrentChild; + CurrentChild = CurrentParent->Get_Child(); + } +} + + +void CProfileIterator::Enter_Parent( void ) +{ + if ( CurrentParent->Get_Parent() != NULL ) { + CurrentParent = CurrentParent->Get_Parent(); + } + CurrentChild = CurrentParent->Get_Child(); +} + + +/*************************************************************************************************** +** +** CProfileManager +** +***************************************************************************************************/ + +CProfileNode CProfileManager::Root( "Root", NULL ); +CProfileNode * CProfileManager::CurrentNode = &CProfileManager::Root; +int CProfileManager::FrameCounter = 0; +unsigned long int CProfileManager::ResetTime = 0; + + +/*********************************************************************************************** + * CProfileManager::Start_Profile -- Begin a named profile * + * * + * Steps one level deeper into the tree, if a child already exists with the specified name * + * then it accumulates the profiling; otherwise a new child node is added to the profile tree. * + * * + * INPUT: * + * name - name of this profiling record * + * * + * WARNINGS: * + * The string used is assumed to be a static string; pointer compares are used throughout * + * the profiling code for efficiency. * + *=============================================================================================*/ +void CProfileManager::Start_Profile( const char * name ) +{ + if (name != CurrentNode->Get_Name()) { + CurrentNode = CurrentNode->Get_Sub_Node( name ); + } + + CurrentNode->Call(); +} + + +/*********************************************************************************************** + * CProfileManager::Stop_Profile -- Stop timing and record the results. * + *=============================================================================================*/ +void CProfileManager::Stop_Profile( void ) +{ + // Return will indicate whether we should back up to our parent (we may + // be profiling a recursive function) + if (CurrentNode->Return()) { + CurrentNode = CurrentNode->Get_Parent(); + } +} + + +/*********************************************************************************************** + * CProfileManager::Reset -- Reset the contents of the profiling system * + * * + * This resets everything except for the tree structure. All of the timing data is reset. * + *=============================================================================================*/ +void CProfileManager::Reset( void ) +{ + gProfileClock.reset(); + Root.Reset(); + Root.Call(); + FrameCounter = 0; + Profile_Get_Ticks(&ResetTime); +} + + +/*********************************************************************************************** + * CProfileManager::Increment_Frame_Counter -- Increment the frame counter * + *=============================================================================================*/ +void CProfileManager::Increment_Frame_Counter( void ) +{ + FrameCounter++; +} + + +/*********************************************************************************************** + * CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset * + *=============================================================================================*/ +float CProfileManager::Get_Time_Since_Reset( void ) +{ + unsigned long int time; + Profile_Get_Ticks(&time); + time -= ResetTime; + return (float)time / Profile_Get_Tick_Rate(); +} + +#include + +void CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spacing) +{ + profileIterator->First(); + if (profileIterator->Is_Done()) + return; + + float accumulated_time=0,parent_time = profileIterator->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time(); + int i; + int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset(); + for (i=0;iGet_Current_Parent_Name(), parent_time ); + float totalTime = 0.f; + + + int numChildren = 0; + + for (i = 0; !profileIterator->Is_Done(); i++,profileIterator->Next()) + { + numChildren++; + float current_total_time = profileIterator->Get_Current_Total_Time(); + accumulated_time += current_total_time; + float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f; + { + int i; for (i=0;iGet_Current_Name(), fraction,(current_total_time / (double)frames_since_reset),profileIterator->Get_Current_Total_Calls()); + totalTime += current_total_time; + //recurse into children + } + + if (parent_time < accumulated_time) + { + printf("what's wrong\n"); + } + for (i=0;i SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time); + + for (i=0;iEnter_Child(i); + dumpRecursive(profileIterator,spacing+3); + profileIterator->Enter_Parent(); + } +} + + + +void CProfileManager::dumpAll() +{ + CProfileIterator* profileIterator = 0; + profileIterator = CProfileManager::Get_Iterator(); + + dumpRecursive(profileIterator,0); + + CProfileManager::Release_Iterator(profileIterator); +} + + + + +#endif //BT_NO_PROFILE diff --git a/src/LinearMath/btQuickprof.h b/src/LinearMath/btQuickprof.h new file mode 100644 index 0000000..93f3f4a --- /dev/null +++ b/src/LinearMath/btQuickprof.h @@ -0,0 +1,203 @@ + +/*************************************************************************************************** +** +** Real-Time Hierarchical Profiling for Game Programming Gems 3 +** +** by Greg Hjelstrom & Byon Garrabrant +** +***************************************************************************************************/ + +// Credits: The Clock class was inspired by the Timer classes in +// Ogre (www.ogre3d.org). + + + +#ifndef BT_QUICK_PROF_H +#define BT_QUICK_PROF_H + +//To disable built-in profiling, please comment out next line +//#define BT_NO_PROFILE 1 +#ifndef BT_NO_PROFILE +#include //@todo remove this, backwards compatibility +#include "btScalar.h" +#include "btAlignedAllocator.h" +#include + + + + + +#define USE_BT_CLOCK 1 + +#ifdef USE_BT_CLOCK + +///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling. +class btClock +{ +public: + btClock(); + + btClock(const btClock& other); + btClock& operator=(const btClock& other); + + ~btClock(); + + /// Resets the initial reference time. + void reset(); + + /// Returns the time in ms since the last call to reset or since + /// the btClock was created. + unsigned long int getTimeMilliseconds(); + + /// Returns the time in us since the last call to reset or since + /// the Clock was created. + unsigned long int getTimeMicroseconds(); +private: + struct btClockData* m_data; +}; + +#endif //USE_BT_CLOCK + + + + +///A node in the Profile Hierarchy Tree +class CProfileNode { + +public: + CProfileNode( const char * name, CProfileNode * parent ); + ~CProfileNode( void ); + + CProfileNode * Get_Sub_Node( const char * name ); + + CProfileNode * Get_Parent( void ) { return Parent; } + CProfileNode * Get_Sibling( void ) { return Sibling; } + CProfileNode * Get_Child( void ) { return Child; } + + void CleanupMemory(); + void Reset( void ); + void Call( void ); + bool Return( void ); + + const char * Get_Name( void ) { return Name; } + int Get_Total_Calls( void ) { return TotalCalls; } + float Get_Total_Time( void ) { return TotalTime; } + void* GetUserPointer() const {return m_userPtr;} + void SetUserPointer(void* ptr) { m_userPtr = ptr;} +protected: + + const char * Name; + int TotalCalls; + float TotalTime; + unsigned long int StartTime; + int RecursionCounter; + + CProfileNode * Parent; + CProfileNode * Child; + CProfileNode * Sibling; + void* m_userPtr; +}; + +///An iterator to navigate through the tree +class CProfileIterator +{ +public: + // Access all the children of the current parent + void First(void); + void Next(void); + bool Is_Done(void); + bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); } + + void Enter_Child( int index ); // Make the given child the new parent + void Enter_Largest_Child( void ); // Make the largest child the new parent + void Enter_Parent( void ); // Make the current parent's parent the new parent + + // Access the current child + const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); } + int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); } + float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); } + + void* Get_Current_UserPointer( void ) { return CurrentChild->GetUserPointer(); } + void Set_Current_UserPointer(void* ptr) {CurrentChild->SetUserPointer(ptr);} + // Access the current parent + const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); } + int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); } + float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); } + + + +protected: + + CProfileNode * CurrentParent; + CProfileNode * CurrentChild; + + + CProfileIterator( CProfileNode * start ); + friend class CProfileManager; +}; + + +///The Manager for the Profile system +class CProfileManager { +public: + static void Start_Profile( const char * name ); + static void Stop_Profile( void ); + + static void CleanupMemory(void) + { + Root.CleanupMemory(); + } + + static void Reset( void ); + static void Increment_Frame_Counter( void ); + static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; } + static float Get_Time_Since_Reset( void ); + + static CProfileIterator * Get_Iterator( void ) + { + + return new CProfileIterator( &Root ); + } + static void Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); } + + static void dumpRecursive(CProfileIterator* profileIterator, int spacing); + + static void dumpAll(); + +private: + static CProfileNode Root; + static CProfileNode * CurrentNode; + static int FrameCounter; + static unsigned long int ResetTime; +}; + + +///ProfileSampleClass is a simple way to profile a function's scope +///Use the BT_PROFILE macro at the start of scope to time +class CProfileSample { +public: + CProfileSample( const char * name ) + { + CProfileManager::Start_Profile( name ); + } + + ~CProfileSample( void ) + { + CProfileManager::Stop_Profile(); + } +}; + + +#define BT_PROFILE( name ) CProfileSample __profile( name ) + +#else + +#define BT_PROFILE( name ) + +#endif //#ifndef BT_NO_PROFILE + + + +#endif //BT_QUICK_PROF_H + + diff --git a/src/LinearMath/btRandom.h b/src/LinearMath/btRandom.h new file mode 100644 index 0000000..4cbfc6b --- /dev/null +++ b/src/LinearMath/btRandom.h @@ -0,0 +1,42 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_GEN_RANDOM_H +#define BT_GEN_RANDOM_H + +#ifdef MT19937 + +#include +#include + +#define GEN_RAND_MAX UINT_MAX + +SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { init_genrand(seed); } +SIMD_FORCE_INLINE unsigned int GEN_rand() { return genrand_int32(); } + +#else + +#include + +#define GEN_RAND_MAX RAND_MAX + +SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { srand(seed); } +SIMD_FORCE_INLINE unsigned int GEN_rand() { return rand(); } + +#endif + +#endif //BT_GEN_RANDOM_H + diff --git a/src/LinearMath/btScalar.h b/src/LinearMath/btScalar.h new file mode 100644 index 0000000..e3bd37a --- /dev/null +++ b/src/LinearMath/btScalar.h @@ -0,0 +1,539 @@ +/* +Copyright (c) 2003-2009 Erwin Coumans http://bullet.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_SCALAR_H +#define BT_SCALAR_H + +#ifdef BT_MANAGED_CODE +//Aligned data types not supported in managed code +#pragma unmanaged +#endif + + +#include +#include //size_t for MSVC 6.0 +#include + +/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/ +#define BT_BULLET_VERSION 280 + +inline int btGetVersion() +{ + return BT_BULLET_VERSION; +} + +#if defined(DEBUG) || defined (_DEBUG) +#define BT_DEBUG +#endif + + +#ifdef _WIN32 + + #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) + + #define SIMD_FORCE_INLINE inline + #define ATTRIBUTE_ALIGNED16(a) a + #define ATTRIBUTE_ALIGNED64(a) a + #define ATTRIBUTE_ALIGNED128(a) a + #else + //#define BT_HAS_ALIGNED_ALLOCATOR + #pragma warning(disable : 4324) // disable padding warning +// #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning. +// #pragma warning(disable:4996) //Turn off warnings about deprecated C routines +// #pragma warning(disable:4786) // Disable the "debug name too long" warning + + #define SIMD_FORCE_INLINE __forceinline + #define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a + #define ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a + #define ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a + #ifdef _XBOX + #define BT_USE_VMX128 + + #include + #define BT_HAVE_NATIVE_FSEL + #define btFsel(a,b,c) __fsel((a),(b),(c)) + #else + +#if (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION)) + #define BT_USE_SSE + #include +#endif + + #endif//_XBOX + + #endif //__MINGW32__ + + #include +#ifdef BT_DEBUG + #define btAssert assert +#else + #define btAssert(x) +#endif + //btFullAssert is optional, slows down a lot + #define btFullAssert(x) + + #define btLikely(_c) _c + #define btUnlikely(_c) _c + +#else + +#if defined (__CELLOS_LV2__) + #define SIMD_FORCE_INLINE inline __attribute__((always_inline)) + #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) + #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) + #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) + #ifndef assert + #include + #endif +#ifdef BT_DEBUG +#ifdef __SPU__ +#include +#define printf spu_printf + #define btAssert(x) {if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);spu_hcmpeq(0,0);}} +#else + #define btAssert assert +#endif + +#else + #define btAssert(x) +#endif + //btFullAssert is optional, slows down a lot + #define btFullAssert(x) + + #define btLikely(_c) _c + #define btUnlikely(_c) _c + +#else + +#ifdef USE_LIBSPE2 + + #define SIMD_FORCE_INLINE __inline + #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) + #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) + #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) + #ifndef assert + #include + #endif +#ifdef BT_DEBUG + #define btAssert assert +#else + #define btAssert(x) +#endif + //btFullAssert is optional, slows down a lot + #define btFullAssert(x) + + + #define btLikely(_c) __builtin_expect((_c), 1) + #define btUnlikely(_c) __builtin_expect((_c), 0) + + +#else + //non-windows systems + +#if (defined (__APPLE__) && defined (__i386__) && (!defined (BT_USE_DOUBLE_PRECISION))) + #define BT_USE_SSE + #include + + #define SIMD_FORCE_INLINE inline +///@todo: check out alignment methods for other platforms/compilers + #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) + #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) + #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) + #ifndef assert + #include + #endif + + #if defined(DEBUG) || defined (_DEBUG) + #define btAssert assert + #else + #define btAssert(x) + #endif + + //btFullAssert is optional, slows down a lot + #define btFullAssert(x) + #define btLikely(_c) _c + #define btUnlikely(_c) _c + +#else + + #define SIMD_FORCE_INLINE inline + ///@todo: check out alignment methods for other platforms/compilers + ///#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) + ///#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) + ///#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) + #define ATTRIBUTE_ALIGNED16(a) a + #define ATTRIBUTE_ALIGNED64(a) a + #define ATTRIBUTE_ALIGNED128(a) a + #ifndef assert + #include + #endif + +#if defined(DEBUG) || defined (_DEBUG) + #define btAssert assert +#else + #define btAssert(x) +#endif + + //btFullAssert is optional, slows down a lot + #define btFullAssert(x) + #define btLikely(_c) _c + #define btUnlikely(_c) _c +#endif //__APPLE__ + +#endif // LIBSPE2 + +#endif //__CELLOS_LV2__ +#endif + + +///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision. +#if defined(BT_USE_DOUBLE_PRECISION) +typedef double btScalar; +//this number could be bigger in double precision +#define BT_LARGE_FLOAT 1e30 +#else +typedef float btScalar; +//keep BT_LARGE_FLOAT*BT_LARGE_FLOAT < FLT_MAX +#define BT_LARGE_FLOAT 1e18f +#endif + + + +#define BT_DECLARE_ALIGNED_ALLOCATOR() \ + SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ + SIMD_FORCE_INLINE void operator delete(void* ptr) { btAlignedFree(ptr); } \ + SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \ + SIMD_FORCE_INLINE void operator delete(void*, void*) { } \ + SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ + SIMD_FORCE_INLINE void operator delete[](void* ptr) { btAlignedFree(ptr); } \ + SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr) { return ptr; } \ + SIMD_FORCE_INLINE void operator delete[](void*, void*) { } \ + + + +#if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS) + +SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); } +SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); } +SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); } +SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); } +SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); } +SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { if (xbtScalar(1)) x=btScalar(1); return acos(x); } +SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { if (xbtScalar(1)) x=btScalar(1); return asin(x); } +SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); } +SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); } +SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); } +SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); } +SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); } +SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmod(x,y); } + +#else + +SIMD_FORCE_INLINE btScalar btSqrt(btScalar y) +{ +#ifdef USE_APPROXIMATION + double x, z, tempf; + unsigned long *tfptr = ((unsigned long *)&tempf) + 1; + + tempf = y; + *tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */ + x = tempf; + z = y*btScalar(0.5); + x = (btScalar(1.5)*x)-(x*x)*(x*z); /* iteration formula */ + x = (btScalar(1.5)*x)-(x*x)*(x*z); + x = (btScalar(1.5)*x)-(x*x)*(x*z); + x = (btScalar(1.5)*x)-(x*x)*(x*z); + x = (btScalar(1.5)*x)-(x*x)*(x*z); + return x*y; +#else + return sqrtf(y); +#endif +} +SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); } +SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); } +SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); } +SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); } +SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { + if (xbtScalar(1)) + x=btScalar(1); + return acosf(x); +} +SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { + if (xbtScalar(1)) + x=btScalar(1); + return asinf(x); +} +SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); } +SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); } +SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); } +SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); } +SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return powf(x,y); } +SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmodf(x,y); } + +#endif + +#define SIMD_2_PI btScalar(6.283185307179586232) +#define SIMD_PI (SIMD_2_PI * btScalar(0.5)) +#define SIMD_HALF_PI (SIMD_2_PI * btScalar(0.25)) +#define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0)) +#define SIMD_DEGS_PER_RAD (btScalar(360.0) / SIMD_2_PI) +#define SIMDSQRT12 btScalar(0.7071067811865475244008443621048490) + +#define btRecipSqrt(x) ((btScalar)(btScalar(1.0)/btSqrt(btScalar(x)))) /* reciprocal square root */ + + +#ifdef BT_USE_DOUBLE_PRECISION +#define SIMD_EPSILON DBL_EPSILON +#define SIMD_INFINITY DBL_MAX +#else +#define SIMD_EPSILON FLT_EPSILON +#define SIMD_INFINITY FLT_MAX +#endif + +SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x) +{ + btScalar coeff_1 = SIMD_PI / 4.0f; + btScalar coeff_2 = 3.0f * coeff_1; + btScalar abs_y = btFabs(y); + btScalar angle; + if (x >= 0.0f) { + btScalar r = (x - abs_y) / (x + abs_y); + angle = coeff_1 - coeff_1 * r; + } else { + btScalar r = (x + abs_y) / (abs_y - x); + angle = coeff_2 - coeff_1 * r; + } + return (y < 0.0f) ? -angle : angle; +} + +SIMD_FORCE_INLINE bool btFuzzyZero(btScalar x) { return btFabs(x) < SIMD_EPSILON; } + +SIMD_FORCE_INLINE bool btEqual(btScalar a, btScalar eps) { + return (((a) <= eps) && !((a) < -eps)); +} +SIMD_FORCE_INLINE bool btGreaterEqual (btScalar a, btScalar eps) { + return (!((a) <= eps)); +} + + +SIMD_FORCE_INLINE int btIsNegative(btScalar x) { + return x < btScalar(0.0) ? 1 : 0; +} + +SIMD_FORCE_INLINE btScalar btRadians(btScalar x) { return x * SIMD_RADS_PER_DEG; } +SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; } + +#define BT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name + +#ifndef btFsel +SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c) +{ + return a >= 0 ? b : c; +} +#endif +#define btFsels(a,b,c) (btScalar)btFsel(a,b,c) + + +SIMD_FORCE_INLINE bool btMachineIsLittleEndian() +{ + long int i = 1; + const char *p = (const char *) &i; + if (p[0] == 1) // Lowest address contains the least significant byte + return true; + else + return false; +} + + + +///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360 +///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html +SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero) +{ + // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero + // Rely on positive value or'ed with its negative having sign bit on + // and zero value or'ed with its negative (which is still zero) having sign bit off + // Use arithmetic shift right, shifting the sign bit through all 32 bits + unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); + unsigned testEqz = ~testNz; + return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); +} +SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero) +{ + unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); + unsigned testEqz = ~testNz; + return static_cast((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); +} +SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero) +{ +#ifdef BT_HAVE_NATIVE_FSEL + return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero); +#else + return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero; +#endif +} + +template SIMD_FORCE_INLINE void btSwap(T& a, T& b) +{ + T tmp = a; + a = b; + b = tmp; +} + + +//PCK: endian swapping functions +SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val) +{ + return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); +} + +SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val) +{ + return static_cast(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)); +} + +SIMD_FORCE_INLINE unsigned btSwapEndian(int val) +{ + return btSwapEndian((unsigned)val); +} + +SIMD_FORCE_INLINE unsigned short btSwapEndian(short val) +{ + return btSwapEndian((unsigned short) val); +} + +///btSwapFloat uses using char pointers to swap the endianness +////btSwapFloat/btSwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values +///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754. +///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception. +///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you. +///so instead of returning a float/double, we return integer/long long integer +SIMD_FORCE_INLINE unsigned int btSwapEndianFloat(float d) +{ + unsigned int a = 0; + unsigned char *dst = (unsigned char *)&a; + unsigned char *src = (unsigned char *)&d; + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; + return a; +} + +// unswap using char pointers +SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a) +{ + float d = 0.0f; + unsigned char *src = (unsigned char *)&a; + unsigned char *dst = (unsigned char *)&d; + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; + + return d; +} + + +// swap using char pointers +SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char* dst) +{ + unsigned char *src = (unsigned char *)&d; + + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; + +} + +// unswap using char pointers +SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src) +{ + double d = 0.0; + unsigned char *dst = (unsigned char *)&d; + + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; + + return d; +} + +// returns normalized value in range [-SIMD_PI, SIMD_PI] +SIMD_FORCE_INLINE btScalar btNormalizeAngle(btScalar angleInRadians) +{ + angleInRadians = btFmod(angleInRadians, SIMD_2_PI); + if(angleInRadians < -SIMD_PI) + { + return angleInRadians + SIMD_2_PI; + } + else if(angleInRadians > SIMD_PI) + { + return angleInRadians - SIMD_2_PI; + } + else + { + return angleInRadians; + } +} + +///rudimentary class to provide type info +struct btTypedObject +{ + btTypedObject(int objectType) + :m_objectType(objectType) + { + } + int m_objectType; + inline int getObjectType() const + { + return m_objectType; + } +}; + + +///align a pointer to the provided alignment, upwards +template T* btAlignPointer(T* unalignedPtr, size_t alignment) +{ + union + { + T* ptr; + size_t integer; + }; + const size_t bit_mask = ~(alignment - 1); + ptr = unalignedPtr; + integer += alignment-1; + integer &= bit_mask; + return ptr; +} + +#endif //BT_SCALAR_H diff --git a/src/LinearMath/btSerializer.cpp b/src/LinearMath/btSerializer.cpp new file mode 100644 index 0000000..49c25b7 --- /dev/null +++ b/src/LinearMath/btSerializer.cpp @@ -0,0 +1,841 @@ +char sBulletDNAstr[]= { +83,68,78,65,78,65,77,69,44,1,0,0,109,95,115,105,122,101,0,109, +95,99,97,112,97,99,105,116,121,0,42,109,95,100,97,116,97,0,109,95, +99,111,108,108,105,115,105,111,110,83,104,97,112,101,115,0,109,95,99,111, +108,108,105,115,105,111,110,79,98,106,101,99,116,115,0,109,95,99,111,110, +115,116,114,97,105,110,116,115,0,42,102,105,114,115,116,0,42,108,97,115, +116,0,109,95,102,108,111,97,116,115,91,52,93,0,109,95,101,108,91,51, +93,0,109,95,98,97,115,105,115,0,109,95,111,114,105,103,105,110,0,109, +95,114,111,111,116,78,111,100,101,73,110,100,101,120,0,109,95,115,117,98, +116,114,101,101,83,105,122,101,0,109,95,113,117,97,110,116,105,122,101,100, +65,97,98,98,77,105,110,91,51,93,0,109,95,113,117,97,110,116,105,122, +101,100,65,97,98,98,77,97,120,91,51,93,0,109,95,97,97,98,98,77, +105,110,79,114,103,0,109,95,97,97,98,98,77,97,120,79,114,103,0,109, +95,101,115,99,97,112,101,73,110,100,101,120,0,109,95,115,117,98,80,97, +114,116,0,109,95,116,114,105,97,110,103,108,101,73,110,100,101,120,0,109, +95,112,97,100,91,52,93,0,109,95,101,115,99,97,112,101,73,110,100,101, +120,79,114,84,114,105,97,110,103,108,101,73,110,100,101,120,0,109,95,98, +118,104,65,97,98,98,77,105,110,0,109,95,98,118,104,65,97,98,98,77, +97,120,0,109,95,98,118,104,81,117,97,110,116,105,122,97,116,105,111,110, +0,109,95,99,117,114,78,111,100,101,73,110,100,101,120,0,109,95,117,115, +101,81,117,97,110,116,105,122,97,116,105,111,110,0,109,95,110,117,109,67, +111,110,116,105,103,117,111,117,115,76,101,97,102,78,111,100,101,115,0,109, +95,110,117,109,81,117,97,110,116,105,122,101,100,67,111,110,116,105,103,117, +111,117,115,78,111,100,101,115,0,42,109,95,99,111,110,116,105,103,117,111, +117,115,78,111,100,101,115,80,116,114,0,42,109,95,113,117,97,110,116,105, +122,101,100,67,111,110,116,105,103,117,111,117,115,78,111,100,101,115,80,116, +114,0,42,109,95,115,117,98,84,114,101,101,73,110,102,111,80,116,114,0, +109,95,116,114,97,118,101,114,115,97,108,77,111,100,101,0,109,95,110,117, +109,83,117,98,116,114,101,101,72,101,97,100,101,114,115,0,42,109,95,110, +97,109,101,0,109,95,115,104,97,112,101,84,121,112,101,0,109,95,112,97, +100,100,105,110,103,91,52,93,0,109,95,99,111,108,108,105,115,105,111,110, +83,104,97,112,101,68,97,116,97,0,109,95,108,111,99,97,108,83,99,97, +108,105,110,103,0,109,95,112,108,97,110,101,78,111,114,109,97,108,0,109, +95,112,108,97,110,101,67,111,110,115,116,97,110,116,0,109,95,105,109,112, +108,105,99,105,116,83,104,97,112,101,68,105,109,101,110,115,105,111,110,115, +0,109,95,99,111,108,108,105,115,105,111,110,77,97,114,103,105,110,0,109, +95,112,97,100,100,105,110,103,0,109,95,112,111,115,0,109,95,114,97,100, +105,117,115,0,109,95,99,111,110,118,101,120,73,110,116,101,114,110,97,108, +83,104,97,112,101,68,97,116,97,0,42,109,95,108,111,99,97,108,80,111, +115,105,116,105,111,110,65,114,114,97,121,80,116,114,0,109,95,108,111,99, +97,108,80,111,115,105,116,105,111,110,65,114,114,97,121,83,105,122,101,0, +109,95,118,97,108,117,101,0,109,95,112,97,100,91,50,93,0,109,95,118, +97,108,117,101,115,91,51,93,0,109,95,112,97,100,0,42,109,95,118,101, +114,116,105,99,101,115,51,102,0,42,109,95,118,101,114,116,105,99,101,115, +51,100,0,42,109,95,105,110,100,105,99,101,115,51,50,0,42,109,95,51, +105,110,100,105,99,101,115,49,54,0,42,109,95,51,105,110,100,105,99,101, +115,56,0,42,109,95,105,110,100,105,99,101,115,49,54,0,109,95,110,117, +109,84,114,105,97,110,103,108,101,115,0,109,95,110,117,109,86,101,114,116, +105,99,101,115,0,42,109,95,109,101,115,104,80,97,114,116,115,80,116,114, +0,109,95,115,99,97,108,105,110,103,0,109,95,110,117,109,77,101,115,104, +80,97,114,116,115,0,109,95,109,101,115,104,73,110,116,101,114,102,97,99, +101,0,42,109,95,113,117,97,110,116,105,122,101,100,70,108,111,97,116,66, +118,104,0,42,109,95,113,117,97,110,116,105,122,101,100,68,111,117,98,108, +101,66,118,104,0,42,109,95,116,114,105,97,110,103,108,101,73,110,102,111, +77,97,112,0,109,95,112,97,100,51,91,52,93,0,109,95,116,114,105,109, +101,115,104,83,104,97,112,101,68,97,116,97,0,109,95,116,114,97,110,115, +102,111,114,109,0,42,109,95,99,104,105,108,100,83,104,97,112,101,0,109, +95,99,104,105,108,100,83,104,97,112,101,84,121,112,101,0,109,95,99,104, +105,108,100,77,97,114,103,105,110,0,42,109,95,99,104,105,108,100,83,104, +97,112,101,80,116,114,0,109,95,110,117,109,67,104,105,108,100,83,104,97, +112,101,115,0,109,95,117,112,65,120,105,115,0,109,95,102,108,97,103,115, +0,109,95,101,100,103,101,86,48,86,49,65,110,103,108,101,0,109,95,101, +100,103,101,86,49,86,50,65,110,103,108,101,0,109,95,101,100,103,101,86, +50,86,48,65,110,103,108,101,0,42,109,95,104,97,115,104,84,97,98,108, +101,80,116,114,0,42,109,95,110,101,120,116,80,116,114,0,42,109,95,118, +97,108,117,101,65,114,114,97,121,80,116,114,0,42,109,95,107,101,121,65, +114,114,97,121,80,116,114,0,109,95,99,111,110,118,101,120,69,112,115,105, +108,111,110,0,109,95,112,108,97,110,97,114,69,112,115,105,108,111,110,0, +109,95,101,113,117,97,108,86,101,114,116,101,120,84,104,114,101,115,104,111, +108,100,0,109,95,101,100,103,101,68,105,115,116,97,110,99,101,84,104,114, +101,115,104,111,108,100,0,109,95,122,101,114,111,65,114,101,97,84,104,114, +101,115,104,111,108,100,0,109,95,110,101,120,116,83,105,122,101,0,109,95, +104,97,115,104,84,97,98,108,101,83,105,122,101,0,109,95,110,117,109,86, +97,108,117,101,115,0,109,95,110,117,109,75,101,121,115,0,109,95,103,105, +109,112,97,99,116,83,117,98,84,121,112,101,0,42,109,95,117,110,115,99, +97,108,101,100,80,111,105,110,116,115,70,108,111,97,116,80,116,114,0,42, +109,95,117,110,115,99,97,108,101,100,80,111,105,110,116,115,68,111,117,98, +108,101,80,116,114,0,109,95,110,117,109,85,110,115,99,97,108,101,100,80, +111,105,110,116,115,0,109,95,112,97,100,100,105,110,103,51,91,52,93,0, +42,109,95,98,114,111,97,100,112,104,97,115,101,72,97,110,100,108,101,0, +42,109,95,99,111,108,108,105,115,105,111,110,83,104,97,112,101,0,42,109, +95,114,111,111,116,67,111,108,108,105,115,105,111,110,83,104,97,112,101,0, +109,95,119,111,114,108,100,84,114,97,110,115,102,111,114,109,0,109,95,105, +110,116,101,114,112,111,108,97,116,105,111,110,87,111,114,108,100,84,114,97, +110,115,102,111,114,109,0,109,95,105,110,116,101,114,112,111,108,97,116,105, +111,110,76,105,110,101,97,114,86,101,108,111,99,105,116,121,0,109,95,105, +110,116,101,114,112,111,108,97,116,105,111,110,65,110,103,117,108,97,114,86, +101,108,111,99,105,116,121,0,109,95,97,110,105,115,111,116,114,111,112,105, +99,70,114,105,99,116,105,111,110,0,109,95,99,111,110,116,97,99,116,80, +114,111,99,101,115,115,105,110,103,84,104,114,101,115,104,111,108,100,0,109, +95,100,101,97,99,116,105,118,97,116,105,111,110,84,105,109,101,0,109,95, +102,114,105,99,116,105,111,110,0,109,95,114,101,115,116,105,116,117,116,105, +111,110,0,109,95,104,105,116,70,114,97,99,116,105,111,110,0,109,95,99, +99,100,83,119,101,112,116,83,112,104,101,114,101,82,97,100,105,117,115,0, +109,95,99,99,100,77,111,116,105,111,110,84,104,114,101,115,104,111,108,100, +0,109,95,104,97,115,65,110,105,115,111,116,114,111,112,105,99,70,114,105, +99,116,105,111,110,0,109,95,99,111,108,108,105,115,105,111,110,70,108,97, +103,115,0,109,95,105,115,108,97,110,100,84,97,103,49,0,109,95,99,111, +109,112,97,110,105,111,110,73,100,0,109,95,97,99,116,105,118,97,116,105, +111,110,83,116,97,116,101,49,0,109,95,105,110,116,101,114,110,97,108,84, +121,112,101,0,109,95,99,104,101,99,107,67,111,108,108,105,100,101,87,105, +116,104,0,109,95,99,111,108,108,105,115,105,111,110,79,98,106,101,99,116, +68,97,116,97,0,109,95,105,110,118,73,110,101,114,116,105,97,84,101,110, +115,111,114,87,111,114,108,100,0,109,95,108,105,110,101,97,114,86,101,108, +111,99,105,116,121,0,109,95,97,110,103,117,108,97,114,86,101,108,111,99, +105,116,121,0,109,95,97,110,103,117,108,97,114,70,97,99,116,111,114,0, +109,95,108,105,110,101,97,114,70,97,99,116,111,114,0,109,95,103,114,97, +118,105,116,121,0,109,95,103,114,97,118,105,116,121,95,97,99,99,101,108, +101,114,97,116,105,111,110,0,109,95,105,110,118,73,110,101,114,116,105,97, +76,111,99,97,108,0,109,95,116,111,116,97,108,70,111,114,99,101,0,109, +95,116,111,116,97,108,84,111,114,113,117,101,0,109,95,105,110,118,101,114, +115,101,77,97,115,115,0,109,95,108,105,110,101,97,114,68,97,109,112,105, +110,103,0,109,95,97,110,103,117,108,97,114,68,97,109,112,105,110,103,0, +109,95,97,100,100,105,116,105,111,110,97,108,68,97,109,112,105,110,103,70, +97,99,116,111,114,0,109,95,97,100,100,105,116,105,111,110,97,108,76,105, +110,101,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,108,100, +83,113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,103,117, +108,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,108,100,83, +113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,103,117,108, +97,114,68,97,109,112,105,110,103,70,97,99,116,111,114,0,109,95,108,105, +110,101,97,114,83,108,101,101,112,105,110,103,84,104,114,101,115,104,111,108, +100,0,109,95,97,110,103,117,108,97,114,83,108,101,101,112,105,110,103,84, +104,114,101,115,104,111,108,100,0,109,95,97,100,100,105,116,105,111,110,97, +108,68,97,109,112,105,110,103,0,109,95,110,117,109,67,111,110,115,116,114, +97,105,110,116,82,111,119,115,0,110,117,98,0,42,109,95,114,98,65,0, +42,109,95,114,98,66,0,109,95,111,98,106,101,99,116,84,121,112,101,0, +109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,84,121,112,101, +0,109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,73,100,0, +109,95,110,101,101,100,115,70,101,101,100,98,97,99,107,0,109,95,97,112, +112,108,105,101,100,73,109,112,117,108,115,101,0,109,95,100,98,103,68,114, +97,119,83,105,122,101,0,109,95,100,105,115,97,98,108,101,67,111,108,108, +105,115,105,111,110,115,66,101,116,119,101,101,110,76,105,110,107,101,100,66, +111,100,105,101,115,0,109,95,111,118,101,114,114,105,100,101,78,117,109,83, +111,108,118,101,114,73,116,101,114,97,116,105,111,110,115,0,109,95,98,114, +101,97,107,105,110,103,73,109,112,117,108,115,101,84,104,114,101,115,104,111, +108,100,0,109,95,105,115,69,110,97,98,108,101,100,0,109,95,116,121,112, +101,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,109,95,112,105, +118,111,116,73,110,65,0,109,95,112,105,118,111,116,73,110,66,0,109,95, +114,98,65,70,114,97,109,101,0,109,95,114,98,66,70,114,97,109,101,0, +109,95,117,115,101,82,101,102,101,114,101,110,99,101,70,114,97,109,101,65, +0,109,95,97,110,103,117,108,97,114,79,110,108,121,0,109,95,101,110,97, +98,108,101,65,110,103,117,108,97,114,77,111,116,111,114,0,109,95,109,111, +116,111,114,84,97,114,103,101,116,86,101,108,111,99,105,116,121,0,109,95, +109,97,120,77,111,116,111,114,73,109,112,117,108,115,101,0,109,95,108,111, +119,101,114,76,105,109,105,116,0,109,95,117,112,112,101,114,76,105,109,105, +116,0,109,95,108,105,109,105,116,83,111,102,116,110,101,115,115,0,109,95, +98,105,97,115,70,97,99,116,111,114,0,109,95,114,101,108,97,120,97,116, +105,111,110,70,97,99,116,111,114,0,109,95,115,119,105,110,103,83,112,97, +110,49,0,109,95,115,119,105,110,103,83,112,97,110,50,0,109,95,116,119, +105,115,116,83,112,97,110,0,109,95,100,97,109,112,105,110,103,0,109,95, +108,105,110,101,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,108, +105,110,101,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,97,110, +103,117,108,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,97,110, +103,117,108,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,117,115, +101,76,105,110,101,97,114,82,101,102,101,114,101,110,99,101,70,114,97,109, +101,65,0,109,95,117,115,101,79,102,102,115,101,116,70,111,114,67,111,110, +115,116,114,97,105,110,116,70,114,97,109,101,0,109,95,54,100,111,102,68, +97,116,97,0,109,95,115,112,114,105,110,103,69,110,97,98,108,101,100,91, +54,93,0,109,95,101,113,117,105,108,105,98,114,105,117,109,80,111,105,110, +116,91,54,93,0,109,95,115,112,114,105,110,103,83,116,105,102,102,110,101, +115,115,91,54,93,0,109,95,115,112,114,105,110,103,68,97,109,112,105,110, +103,91,54,93,0,109,95,108,105,110,101,97,114,83,116,105,102,102,110,101, +115,115,0,109,95,97,110,103,117,108,97,114,83,116,105,102,102,110,101,115, +115,0,109,95,118,111,108,117,109,101,83,116,105,102,102,110,101,115,115,0, +42,109,95,109,97,116,101,114,105,97,108,0,109,95,112,111,115,105,116,105, +111,110,0,109,95,112,114,101,118,105,111,117,115,80,111,115,105,116,105,111, +110,0,109,95,118,101,108,111,99,105,116,121,0,109,95,97,99,99,117,109, +117,108,97,116,101,100,70,111,114,99,101,0,109,95,110,111,114,109,97,108, +0,109,95,97,114,101,97,0,109,95,97,116,116,97,99,104,0,109,95,110, +111,100,101,73,110,100,105,99,101,115,91,50,93,0,109,95,114,101,115,116, +76,101,110,103,116,104,0,109,95,98,98,101,110,100,105,110,103,0,109,95, +110,111,100,101,73,110,100,105,99,101,115,91,51,93,0,109,95,114,101,115, +116,65,114,101,97,0,109,95,99,48,91,52,93,0,109,95,110,111,100,101, +73,110,100,105,99,101,115,91,52,93,0,109,95,114,101,115,116,86,111,108, +117,109,101,0,109,95,99,49,0,109,95,99,50,0,109,95,99,48,0,109, +95,108,111,99,97,108,70,114,97,109,101,0,42,109,95,114,105,103,105,100, +66,111,100,121,0,109,95,110,111,100,101,73,110,100,101,120,0,109,95,97, +101,114,111,77,111,100,101,108,0,109,95,98,97,117,109,103,97,114,116,101, +0,109,95,100,114,97,103,0,109,95,108,105,102,116,0,109,95,112,114,101, +115,115,117,114,101,0,109,95,118,111,108,117,109,101,0,109,95,100,121,110, +97,109,105,99,70,114,105,99,116,105,111,110,0,109,95,112,111,115,101,77, +97,116,99,104,0,109,95,114,105,103,105,100,67,111,110,116,97,99,116,72, +97,114,100,110,101,115,115,0,109,95,107,105,110,101,116,105,99,67,111,110, +116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,67, +111,110,116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,97,110,99, +104,111,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,82,105, +103,105,100,67,108,117,115,116,101,114,72,97,114,100,110,101,115,115,0,109, +95,115,111,102,116,75,105,110,101,116,105,99,67,108,117,115,116,101,114,72, +97,114,100,110,101,115,115,0,109,95,115,111,102,116,83,111,102,116,67,108, +117,115,116,101,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116, +82,105,103,105,100,67,108,117,115,116,101,114,73,109,112,117,108,115,101,83, +112,108,105,116,0,109,95,115,111,102,116,75,105,110,101,116,105,99,67,108, +117,115,116,101,114,73,109,112,117,108,115,101,83,112,108,105,116,0,109,95, +115,111,102,116,83,111,102,116,67,108,117,115,116,101,114,73,109,112,117,108, +115,101,83,112,108,105,116,0,109,95,109,97,120,86,111,108,117,109,101,0, +109,95,116,105,109,101,83,99,97,108,101,0,109,95,118,101,108,111,99,105, +116,121,73,116,101,114,97,116,105,111,110,115,0,109,95,112,111,115,105,116, +105,111,110,73,116,101,114,97,116,105,111,110,115,0,109,95,100,114,105,102, +116,73,116,101,114,97,116,105,111,110,115,0,109,95,99,108,117,115,116,101, +114,73,116,101,114,97,116,105,111,110,115,0,109,95,114,111,116,0,109,95, +115,99,97,108,101,0,109,95,97,113,113,0,109,95,99,111,109,0,42,109, +95,112,111,115,105,116,105,111,110,115,0,42,109,95,119,101,105,103,104,116, +115,0,109,95,110,117,109,80,111,115,105,116,105,111,110,115,0,109,95,110, +117,109,87,101,105,103,116,115,0,109,95,98,118,111,108,117,109,101,0,109, +95,98,102,114,97,109,101,0,109,95,102,114,97,109,101,120,102,111,114,109, +0,109,95,108,111,99,105,105,0,109,95,105,110,118,119,105,0,109,95,118, +105,109,112,117,108,115,101,115,91,50,93,0,109,95,100,105,109,112,117,108, +115,101,115,91,50,93,0,109,95,108,118,0,109,95,97,118,0,42,109,95, +102,114,97,109,101,114,101,102,115,0,42,109,95,110,111,100,101,73,110,100, +105,99,101,115,0,42,109,95,109,97,115,115,101,115,0,109,95,110,117,109, +70,114,97,109,101,82,101,102,115,0,109,95,110,117,109,78,111,100,101,115, +0,109,95,110,117,109,77,97,115,115,101,115,0,109,95,105,100,109,97,115, +115,0,109,95,105,109,97,115,115,0,109,95,110,118,105,109,112,117,108,115, +101,115,0,109,95,110,100,105,109,112,117,108,115,101,115,0,109,95,110,100, +97,109,112,105,110,103,0,109,95,108,100,97,109,112,105,110,103,0,109,95, +97,100,97,109,112,105,110,103,0,109,95,109,97,116,99,104,105,110,103,0, +109,95,109,97,120,83,101,108,102,67,111,108,108,105,115,105,111,110,73,109, +112,117,108,115,101,0,109,95,115,101,108,102,67,111,108,108,105,115,105,111, +110,73,109,112,117,108,115,101,70,97,99,116,111,114,0,109,95,99,111,110, +116,97,105,110,115,65,110,99,104,111,114,0,109,95,99,111,108,108,105,100, +101,0,109,95,99,108,117,115,116,101,114,73,110,100,101,120,0,42,109,95, +98,111,100,121,65,0,42,109,95,98,111,100,121,66,0,109,95,114,101,102, +115,91,50,93,0,109,95,99,102,109,0,109,95,101,114,112,0,109,95,115, +112,108,105,116,0,109,95,100,101,108,101,116,101,0,109,95,114,101,108,80, +111,115,105,116,105,111,110,91,50,93,0,109,95,98,111,100,121,65,116,121, +112,101,0,109,95,98,111,100,121,66,116,121,112,101,0,109,95,106,111,105, +110,116,84,121,112,101,0,42,109,95,112,111,115,101,0,42,42,109,95,109, +97,116,101,114,105,97,108,115,0,42,109,95,110,111,100,101,115,0,42,109, +95,108,105,110,107,115,0,42,109,95,102,97,99,101,115,0,42,109,95,116, +101,116,114,97,104,101,100,114,97,0,42,109,95,97,110,99,104,111,114,115, +0,42,109,95,99,108,117,115,116,101,114,115,0,42,109,95,106,111,105,110, +116,115,0,109,95,110,117,109,77,97,116,101,114,105,97,108,115,0,109,95, +110,117,109,76,105,110,107,115,0,109,95,110,117,109,70,97,99,101,115,0, +109,95,110,117,109,84,101,116,114,97,104,101,100,114,97,0,109,95,110,117, +109,65,110,99,104,111,114,115,0,109,95,110,117,109,67,108,117,115,116,101, +114,115,0,109,95,110,117,109,74,111,105,110,116,115,0,109,95,99,111,110, +102,105,103,0,84,89,80,69,72,0,0,0,99,104,97,114,0,117,99,104, +97,114,0,115,104,111,114,116,0,117,115,104,111,114,116,0,105,110,116,0, +108,111,110,103,0,117,108,111,110,103,0,102,108,111,97,116,0,100,111,117, +98,108,101,0,118,111,105,100,0,80,111,105,110,116,101,114,65,114,114,97, +121,0,98,116,80,104,121,115,105,99,115,83,121,115,116,101,109,0,76,105, +115,116,66,97,115,101,0,98,116,86,101,99,116,111,114,51,70,108,111,97, +116,68,97,116,97,0,98,116,86,101,99,116,111,114,51,68,111,117,98,108, +101,68,97,116,97,0,98,116,77,97,116,114,105,120,51,120,51,70,108,111, +97,116,68,97,116,97,0,98,116,77,97,116,114,105,120,51,120,51,68,111, +117,98,108,101,68,97,116,97,0,98,116,84,114,97,110,115,102,111,114,109, +70,108,111,97,116,68,97,116,97,0,98,116,84,114,97,110,115,102,111,114, +109,68,111,117,98,108,101,68,97,116,97,0,98,116,66,118,104,83,117,98, +116,114,101,101,73,110,102,111,68,97,116,97,0,98,116,79,112,116,105,109, +105,122,101,100,66,118,104,78,111,100,101,70,108,111,97,116,68,97,116,97, +0,98,116,79,112,116,105,109,105,122,101,100,66,118,104,78,111,100,101,68, +111,117,98,108,101,68,97,116,97,0,98,116,81,117,97,110,116,105,122,101, +100,66,118,104,78,111,100,101,68,97,116,97,0,98,116,81,117,97,110,116, +105,122,101,100,66,118,104,70,108,111,97,116,68,97,116,97,0,98,116,81, +117,97,110,116,105,122,101,100,66,118,104,68,111,117,98,108,101,68,97,116, +97,0,98,116,67,111,108,108,105,115,105,111,110,83,104,97,112,101,68,97, +116,97,0,98,116,83,116,97,116,105,99,80,108,97,110,101,83,104,97,112, +101,68,97,116,97,0,98,116,67,111,110,118,101,120,73,110,116,101,114,110, +97,108,83,104,97,112,101,68,97,116,97,0,98,116,80,111,115,105,116,105, +111,110,65,110,100,82,97,100,105,117,115,0,98,116,77,117,108,116,105,83, +112,104,101,114,101,83,104,97,112,101,68,97,116,97,0,98,116,73,110,116, +73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114,116,73,110,116, +73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114,116,73,110,116, +73,110,100,101,120,84,114,105,112,108,101,116,68,97,116,97,0,98,116,67, +104,97,114,73,110,100,101,120,84,114,105,112,108,101,116,68,97,116,97,0, +98,116,77,101,115,104,80,97,114,116,68,97,116,97,0,98,116,83,116,114, +105,100,105,110,103,77,101,115,104,73,110,116,101,114,102,97,99,101,68,97, +116,97,0,98,116,84,114,105,97,110,103,108,101,77,101,115,104,83,104,97, +112,101,68,97,116,97,0,98,116,84,114,105,97,110,103,108,101,73,110,102, +111,77,97,112,68,97,116,97,0,98,116,83,99,97,108,101,100,84,114,105, +97,110,103,108,101,77,101,115,104,83,104,97,112,101,68,97,116,97,0,98, +116,67,111,109,112,111,117,110,100,83,104,97,112,101,67,104,105,108,100,68, +97,116,97,0,98,116,67,111,109,112,111,117,110,100,83,104,97,112,101,68, +97,116,97,0,98,116,67,121,108,105,110,100,101,114,83,104,97,112,101,68, +97,116,97,0,98,116,67,97,112,115,117,108,101,83,104,97,112,101,68,97, +116,97,0,98,116,84,114,105,97,110,103,108,101,73,110,102,111,68,97,116, +97,0,98,116,71,73,109,112,97,99,116,77,101,115,104,83,104,97,112,101, +68,97,116,97,0,98,116,67,111,110,118,101,120,72,117,108,108,83,104,97, +112,101,68,97,116,97,0,98,116,67,111,108,108,105,115,105,111,110,79,98, +106,101,99,116,68,111,117,98,108,101,68,97,116,97,0,98,116,67,111,108, +108,105,115,105,111,110,79,98,106,101,99,116,70,108,111,97,116,68,97,116, +97,0,98,116,82,105,103,105,100,66,111,100,121,70,108,111,97,116,68,97, +116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,111,117,98,108,101, +68,97,116,97,0,98,116,67,111,110,115,116,114,97,105,110,116,73,110,102, +111,49,0,98,116,84,121,112,101,100,67,111,110,115,116,114,97,105,110,116, +68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,97,116,97, +0,98,116,80,111,105,110,116,50,80,111,105,110,116,67,111,110,115,116,114, +97,105,110,116,70,108,111,97,116,68,97,116,97,0,98,116,80,111,105,110, +116,50,80,111,105,110,116,67,111,110,115,116,114,97,105,110,116,68,111,117, +98,108,101,68,97,116,97,0,98,116,72,105,110,103,101,67,111,110,115,116, +114,97,105,110,116,68,111,117,98,108,101,68,97,116,97,0,98,116,72,105, +110,103,101,67,111,110,115,116,114,97,105,110,116,70,108,111,97,116,68,97, +116,97,0,98,116,67,111,110,101,84,119,105,115,116,67,111,110,115,116,114, +97,105,110,116,68,97,116,97,0,98,116,71,101,110,101,114,105,99,54,68, +111,102,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,71, +101,110,101,114,105,99,54,68,111,102,83,112,114,105,110,103,67,111,110,115, +116,114,97,105,110,116,68,97,116,97,0,98,116,83,108,105,100,101,114,67, +111,110,115,116,114,97,105,110,116,68,97,116,97,0,83,111,102,116,66,111, +100,121,77,97,116,101,114,105,97,108,68,97,116,97,0,83,111,102,116,66, +111,100,121,78,111,100,101,68,97,116,97,0,83,111,102,116,66,111,100,121, +76,105,110,107,68,97,116,97,0,83,111,102,116,66,111,100,121,70,97,99, +101,68,97,116,97,0,83,111,102,116,66,111,100,121,84,101,116,114,97,68, +97,116,97,0,83,111,102,116,82,105,103,105,100,65,110,99,104,111,114,68, +97,116,97,0,83,111,102,116,66,111,100,121,67,111,110,102,105,103,68,97, +116,97,0,83,111,102,116,66,111,100,121,80,111,115,101,68,97,116,97,0, +83,111,102,116,66,111,100,121,67,108,117,115,116,101,114,68,97,116,97,0, +98,116,83,111,102,116,66,111,100,121,74,111,105,110,116,68,97,116,97,0, +98,116,83,111,102,116,66,111,100,121,70,108,111,97,116,68,97,116,97,0, +84,76,69,78,1,0,1,0,2,0,2,0,4,0,4,0,4,0,4,0, +8,0,0,0,12,0,36,0,8,0,16,0,32,0,48,0,96,0,64,0, +-128,0,20,0,48,0,80,0,16,0,84,0,-124,0,12,0,52,0,52,0, +20,0,64,0,4,0,4,0,8,0,4,0,32,0,28,0,60,0,56,0, +76,0,76,0,24,0,60,0,60,0,16,0,64,0,68,0,-56,1,-8,0, +-32,1,-104,3,8,0,52,0,0,0,84,0,116,0,92,1,-36,0,-44,0, +-4,0,92,1,-52,0,16,0,100,0,20,0,36,0,100,0,92,0,104,0, +-64,0,92,1,104,0,-92,1,83,84,82,67,61,0,0,0,10,0,3,0, +4,0,0,0,4,0,1,0,9,0,2,0,11,0,3,0,10,0,3,0, +10,0,4,0,10,0,5,0,12,0,2,0,9,0,6,0,9,0,7,0, +13,0,1,0,7,0,8,0,14,0,1,0,8,0,8,0,15,0,1,0, +13,0,9,0,16,0,1,0,14,0,9,0,17,0,2,0,15,0,10,0, +13,0,11,0,18,0,2,0,16,0,10,0,14,0,11,0,19,0,4,0, +4,0,12,0,4,0,13,0,2,0,14,0,2,0,15,0,20,0,6,0, +13,0,16,0,13,0,17,0,4,0,18,0,4,0,19,0,4,0,20,0, +0,0,21,0,21,0,6,0,14,0,16,0,14,0,17,0,4,0,18,0, +4,0,19,0,4,0,20,0,0,0,21,0,22,0,3,0,2,0,14,0, +2,0,15,0,4,0,22,0,23,0,12,0,13,0,23,0,13,0,24,0, +13,0,25,0,4,0,26,0,4,0,27,0,4,0,28,0,4,0,29,0, +20,0,30,0,22,0,31,0,19,0,32,0,4,0,33,0,4,0,34,0, +24,0,12,0,14,0,23,0,14,0,24,0,14,0,25,0,4,0,26,0, +4,0,27,0,4,0,28,0,4,0,29,0,21,0,30,0,22,0,31,0, +4,0,33,0,4,0,34,0,19,0,32,0,25,0,3,0,0,0,35,0, +4,0,36,0,0,0,37,0,26,0,5,0,25,0,38,0,13,0,39,0, +13,0,40,0,7,0,41,0,0,0,21,0,27,0,5,0,25,0,38,0, +13,0,39,0,13,0,42,0,7,0,43,0,4,0,44,0,28,0,2,0, +13,0,45,0,7,0,46,0,29,0,4,0,27,0,47,0,28,0,48,0, +4,0,49,0,0,0,37,0,30,0,1,0,4,0,50,0,31,0,2,0, +2,0,50,0,0,0,51,0,32,0,2,0,2,0,52,0,0,0,51,0, +33,0,2,0,0,0,52,0,0,0,53,0,34,0,8,0,13,0,54,0, +14,0,55,0,30,0,56,0,32,0,57,0,33,0,58,0,31,0,59,0, +4,0,60,0,4,0,61,0,35,0,4,0,34,0,62,0,13,0,63,0, +4,0,64,0,0,0,37,0,36,0,7,0,25,0,38,0,35,0,65,0, +23,0,66,0,24,0,67,0,37,0,68,0,7,0,43,0,0,0,69,0, +38,0,2,0,36,0,70,0,13,0,39,0,39,0,4,0,17,0,71,0, +25,0,72,0,4,0,73,0,7,0,74,0,40,0,4,0,25,0,38,0, +39,0,75,0,4,0,76,0,7,0,43,0,41,0,3,0,27,0,47,0, +4,0,77,0,0,0,37,0,42,0,3,0,27,0,47,0,4,0,77,0, +0,0,37,0,43,0,4,0,4,0,78,0,7,0,79,0,7,0,80,0, +7,0,81,0,37,0,14,0,4,0,82,0,4,0,83,0,43,0,84,0, +4,0,85,0,7,0,86,0,7,0,87,0,7,0,88,0,7,0,89,0, +7,0,90,0,4,0,91,0,4,0,92,0,4,0,93,0,4,0,94,0, +0,0,37,0,44,0,5,0,25,0,38,0,35,0,65,0,13,0,39,0, +7,0,43,0,4,0,95,0,45,0,5,0,27,0,47,0,13,0,96,0, +14,0,97,0,4,0,98,0,0,0,99,0,46,0,24,0,9,0,100,0, +9,0,101,0,25,0,102,0,0,0,35,0,18,0,103,0,18,0,104,0, +14,0,105,0,14,0,106,0,14,0,107,0,8,0,108,0,8,0,109,0, +8,0,110,0,8,0,111,0,8,0,112,0,8,0,113,0,8,0,114,0, +4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0,4,0,119,0, +4,0,120,0,4,0,121,0,0,0,37,0,47,0,23,0,9,0,100,0, +9,0,101,0,25,0,102,0,0,0,35,0,17,0,103,0,17,0,104,0, +13,0,105,0,13,0,106,0,13,0,107,0,7,0,108,0,7,0,109,0, +7,0,110,0,7,0,111,0,7,0,112,0,7,0,113,0,7,0,114,0, +4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0,4,0,119,0, +4,0,120,0,4,0,121,0,48,0,21,0,47,0,122,0,15,0,123,0, +13,0,124,0,13,0,125,0,13,0,126,0,13,0,127,0,13,0,-128,0, +13,0,-127,0,13,0,-126,0,13,0,-125,0,13,0,-124,0,7,0,-123,0, +7,0,-122,0,7,0,-121,0,7,0,-120,0,7,0,-119,0,7,0,-118,0, +7,0,-117,0,7,0,-116,0,7,0,-115,0,4,0,-114,0,49,0,22,0, +46,0,122,0,16,0,123,0,14,0,124,0,14,0,125,0,14,0,126,0, +14,0,127,0,14,0,-128,0,14,0,-127,0,14,0,-126,0,14,0,-125,0, +14,0,-124,0,8,0,-123,0,8,0,-122,0,8,0,-121,0,8,0,-120,0, +8,0,-119,0,8,0,-118,0,8,0,-117,0,8,0,-116,0,8,0,-115,0, +4,0,-114,0,0,0,37,0,50,0,2,0,4,0,-113,0,4,0,-112,0, +51,0,13,0,52,0,-111,0,52,0,-110,0,0,0,35,0,4,0,-109,0, +4,0,-108,0,4,0,-107,0,4,0,-106,0,7,0,-105,0,7,0,-104,0, +4,0,-103,0,4,0,-102,0,7,0,-101,0,4,0,-100,0,53,0,3,0, +51,0,-99,0,13,0,-98,0,13,0,-97,0,54,0,3,0,51,0,-99,0, +14,0,-98,0,14,0,-97,0,55,0,13,0,51,0,-99,0,18,0,-96,0, +18,0,-95,0,4,0,-94,0,4,0,-93,0,4,0,-92,0,7,0,-91,0, +7,0,-90,0,7,0,-89,0,7,0,-88,0,7,0,-87,0,7,0,-86,0, +7,0,-85,0,56,0,13,0,51,0,-99,0,17,0,-96,0,17,0,-95,0, +4,0,-94,0,4,0,-93,0,4,0,-92,0,7,0,-91,0,7,0,-90,0, +7,0,-89,0,7,0,-88,0,7,0,-87,0,7,0,-86,0,7,0,-85,0, +57,0,11,0,51,0,-99,0,17,0,-96,0,17,0,-95,0,7,0,-84,0, +7,0,-83,0,7,0,-82,0,7,0,-87,0,7,0,-86,0,7,0,-85,0, +7,0,-81,0,0,0,21,0,58,0,9,0,51,0,-99,0,17,0,-96,0, +17,0,-95,0,13,0,-80,0,13,0,-79,0,13,0,-78,0,13,0,-77,0, +4,0,-76,0,4,0,-75,0,59,0,5,0,58,0,-74,0,4,0,-73,0, +7,0,-72,0,7,0,-71,0,7,0,-70,0,60,0,9,0,51,0,-99,0, +17,0,-96,0,17,0,-95,0,7,0,-80,0,7,0,-79,0,7,0,-78,0, +7,0,-77,0,4,0,-76,0,4,0,-75,0,61,0,4,0,7,0,-69,0, +7,0,-68,0,7,0,-67,0,4,0,78,0,62,0,10,0,61,0,-66,0, +13,0,-65,0,13,0,-64,0,13,0,-63,0,13,0,-62,0,13,0,-61,0, +7,0,-123,0,7,0,-60,0,4,0,-59,0,4,0,53,0,63,0,4,0, +61,0,-66,0,4,0,-58,0,7,0,-57,0,4,0,-56,0,64,0,4,0, +13,0,-61,0,61,0,-66,0,4,0,-55,0,7,0,-54,0,65,0,7,0, +13,0,-53,0,61,0,-66,0,4,0,-52,0,7,0,-51,0,7,0,-50,0, +7,0,-49,0,4,0,53,0,66,0,6,0,15,0,-48,0,13,0,-50,0, +13,0,-47,0,52,0,-46,0,4,0,-45,0,7,0,-49,0,67,0,26,0, +4,0,-44,0,7,0,-43,0,7,0,-81,0,7,0,-42,0,7,0,-41,0, +7,0,-40,0,7,0,-39,0,7,0,-38,0,7,0,-37,0,7,0,-36,0, +7,0,-35,0,7,0,-34,0,7,0,-33,0,7,0,-32,0,7,0,-31,0, +7,0,-30,0,7,0,-29,0,7,0,-28,0,7,0,-27,0,7,0,-26,0, +7,0,-25,0,4,0,-24,0,4,0,-23,0,4,0,-22,0,4,0,-21,0, +4,0,116,0,68,0,12,0,15,0,-20,0,15,0,-19,0,15,0,-18,0, +13,0,-17,0,13,0,-16,0,7,0,-15,0,4,0,-14,0,4,0,-13,0, +4,0,-12,0,4,0,-11,0,7,0,-51,0,4,0,53,0,69,0,27,0, +17,0,-10,0,15,0,-9,0,15,0,-8,0,13,0,-17,0,13,0,-7,0, +13,0,-6,0,13,0,-5,0,13,0,-4,0,13,0,-3,0,4,0,-2,0, +7,0,-1,0,4,0,0,1,4,0,1,1,4,0,2,1,7,0,3,1, +7,0,4,1,4,0,5,1,4,0,6,1,7,0,7,1,7,0,8,1, +7,0,9,1,7,0,10,1,7,0,11,1,7,0,12,1,4,0,13,1, +4,0,14,1,4,0,15,1,70,0,12,0,9,0,16,1,9,0,17,1, +13,0,18,1,7,0,19,1,7,0,20,1,7,0,21,1,4,0,22,1, +13,0,23,1,4,0,24,1,4,0,25,1,4,0,26,1,4,0,53,0, +71,0,19,0,47,0,122,0,68,0,27,1,61,0,28,1,62,0,29,1, +63,0,30,1,64,0,31,1,65,0,32,1,66,0,33,1,69,0,34,1, +70,0,35,1,4,0,36,1,4,0,1,1,4,0,37,1,4,0,38,1, +4,0,39,1,4,0,40,1,4,0,41,1,4,0,42,1,67,0,43,1, +}; +int sBulletDNAlen= sizeof(sBulletDNAstr); + + char sBulletDNAstr64[]= { +83,68,78,65,78,65,77,69,44,1,0,0,109,95,115,105,122,101,0,109, +95,99,97,112,97,99,105,116,121,0,42,109,95,100,97,116,97,0,109,95, +99,111,108,108,105,115,105,111,110,83,104,97,112,101,115,0,109,95,99,111, +108,108,105,115,105,111,110,79,98,106,101,99,116,115,0,109,95,99,111,110, +115,116,114,97,105,110,116,115,0,42,102,105,114,115,116,0,42,108,97,115, +116,0,109,95,102,108,111,97,116,115,91,52,93,0,109,95,101,108,91,51, +93,0,109,95,98,97,115,105,115,0,109,95,111,114,105,103,105,110,0,109, +95,114,111,111,116,78,111,100,101,73,110,100,101,120,0,109,95,115,117,98, +116,114,101,101,83,105,122,101,0,109,95,113,117,97,110,116,105,122,101,100, +65,97,98,98,77,105,110,91,51,93,0,109,95,113,117,97,110,116,105,122, +101,100,65,97,98,98,77,97,120,91,51,93,0,109,95,97,97,98,98,77, +105,110,79,114,103,0,109,95,97,97,98,98,77,97,120,79,114,103,0,109, +95,101,115,99,97,112,101,73,110,100,101,120,0,109,95,115,117,98,80,97, +114,116,0,109,95,116,114,105,97,110,103,108,101,73,110,100,101,120,0,109, +95,112,97,100,91,52,93,0,109,95,101,115,99,97,112,101,73,110,100,101, +120,79,114,84,114,105,97,110,103,108,101,73,110,100,101,120,0,109,95,98, +118,104,65,97,98,98,77,105,110,0,109,95,98,118,104,65,97,98,98,77, +97,120,0,109,95,98,118,104,81,117,97,110,116,105,122,97,116,105,111,110, +0,109,95,99,117,114,78,111,100,101,73,110,100,101,120,0,109,95,117,115, +101,81,117,97,110,116,105,122,97,116,105,111,110,0,109,95,110,117,109,67, +111,110,116,105,103,117,111,117,115,76,101,97,102,78,111,100,101,115,0,109, +95,110,117,109,81,117,97,110,116,105,122,101,100,67,111,110,116,105,103,117, +111,117,115,78,111,100,101,115,0,42,109,95,99,111,110,116,105,103,117,111, +117,115,78,111,100,101,115,80,116,114,0,42,109,95,113,117,97,110,116,105, +122,101,100,67,111,110,116,105,103,117,111,117,115,78,111,100,101,115,80,116, +114,0,42,109,95,115,117,98,84,114,101,101,73,110,102,111,80,116,114,0, +109,95,116,114,97,118,101,114,115,97,108,77,111,100,101,0,109,95,110,117, +109,83,117,98,116,114,101,101,72,101,97,100,101,114,115,0,42,109,95,110, +97,109,101,0,109,95,115,104,97,112,101,84,121,112,101,0,109,95,112,97, +100,100,105,110,103,91,52,93,0,109,95,99,111,108,108,105,115,105,111,110, +83,104,97,112,101,68,97,116,97,0,109,95,108,111,99,97,108,83,99,97, +108,105,110,103,0,109,95,112,108,97,110,101,78,111,114,109,97,108,0,109, +95,112,108,97,110,101,67,111,110,115,116,97,110,116,0,109,95,105,109,112, +108,105,99,105,116,83,104,97,112,101,68,105,109,101,110,115,105,111,110,115, +0,109,95,99,111,108,108,105,115,105,111,110,77,97,114,103,105,110,0,109, +95,112,97,100,100,105,110,103,0,109,95,112,111,115,0,109,95,114,97,100, +105,117,115,0,109,95,99,111,110,118,101,120,73,110,116,101,114,110,97,108, +83,104,97,112,101,68,97,116,97,0,42,109,95,108,111,99,97,108,80,111, +115,105,116,105,111,110,65,114,114,97,121,80,116,114,0,109,95,108,111,99, +97,108,80,111,115,105,116,105,111,110,65,114,114,97,121,83,105,122,101,0, +109,95,118,97,108,117,101,0,109,95,112,97,100,91,50,93,0,109,95,118, +97,108,117,101,115,91,51,93,0,109,95,112,97,100,0,42,109,95,118,101, +114,116,105,99,101,115,51,102,0,42,109,95,118,101,114,116,105,99,101,115, +51,100,0,42,109,95,105,110,100,105,99,101,115,51,50,0,42,109,95,51, +105,110,100,105,99,101,115,49,54,0,42,109,95,51,105,110,100,105,99,101, +115,56,0,42,109,95,105,110,100,105,99,101,115,49,54,0,109,95,110,117, +109,84,114,105,97,110,103,108,101,115,0,109,95,110,117,109,86,101,114,116, +105,99,101,115,0,42,109,95,109,101,115,104,80,97,114,116,115,80,116,114, +0,109,95,115,99,97,108,105,110,103,0,109,95,110,117,109,77,101,115,104, +80,97,114,116,115,0,109,95,109,101,115,104,73,110,116,101,114,102,97,99, +101,0,42,109,95,113,117,97,110,116,105,122,101,100,70,108,111,97,116,66, +118,104,0,42,109,95,113,117,97,110,116,105,122,101,100,68,111,117,98,108, +101,66,118,104,0,42,109,95,116,114,105,97,110,103,108,101,73,110,102,111, +77,97,112,0,109,95,112,97,100,51,91,52,93,0,109,95,116,114,105,109, +101,115,104,83,104,97,112,101,68,97,116,97,0,109,95,116,114,97,110,115, +102,111,114,109,0,42,109,95,99,104,105,108,100,83,104,97,112,101,0,109, +95,99,104,105,108,100,83,104,97,112,101,84,121,112,101,0,109,95,99,104, +105,108,100,77,97,114,103,105,110,0,42,109,95,99,104,105,108,100,83,104, +97,112,101,80,116,114,0,109,95,110,117,109,67,104,105,108,100,83,104,97, +112,101,115,0,109,95,117,112,65,120,105,115,0,109,95,102,108,97,103,115, +0,109,95,101,100,103,101,86,48,86,49,65,110,103,108,101,0,109,95,101, +100,103,101,86,49,86,50,65,110,103,108,101,0,109,95,101,100,103,101,86, +50,86,48,65,110,103,108,101,0,42,109,95,104,97,115,104,84,97,98,108, +101,80,116,114,0,42,109,95,110,101,120,116,80,116,114,0,42,109,95,118, +97,108,117,101,65,114,114,97,121,80,116,114,0,42,109,95,107,101,121,65, +114,114,97,121,80,116,114,0,109,95,99,111,110,118,101,120,69,112,115,105, +108,111,110,0,109,95,112,108,97,110,97,114,69,112,115,105,108,111,110,0, +109,95,101,113,117,97,108,86,101,114,116,101,120,84,104,114,101,115,104,111, +108,100,0,109,95,101,100,103,101,68,105,115,116,97,110,99,101,84,104,114, +101,115,104,111,108,100,0,109,95,122,101,114,111,65,114,101,97,84,104,114, +101,115,104,111,108,100,0,109,95,110,101,120,116,83,105,122,101,0,109,95, +104,97,115,104,84,97,98,108,101,83,105,122,101,0,109,95,110,117,109,86, +97,108,117,101,115,0,109,95,110,117,109,75,101,121,115,0,109,95,103,105, +109,112,97,99,116,83,117,98,84,121,112,101,0,42,109,95,117,110,115,99, +97,108,101,100,80,111,105,110,116,115,70,108,111,97,116,80,116,114,0,42, +109,95,117,110,115,99,97,108,101,100,80,111,105,110,116,115,68,111,117,98, +108,101,80,116,114,0,109,95,110,117,109,85,110,115,99,97,108,101,100,80, +111,105,110,116,115,0,109,95,112,97,100,100,105,110,103,51,91,52,93,0, +42,109,95,98,114,111,97,100,112,104,97,115,101,72,97,110,100,108,101,0, +42,109,95,99,111,108,108,105,115,105,111,110,83,104,97,112,101,0,42,109, +95,114,111,111,116,67,111,108,108,105,115,105,111,110,83,104,97,112,101,0, +109,95,119,111,114,108,100,84,114,97,110,115,102,111,114,109,0,109,95,105, +110,116,101,114,112,111,108,97,116,105,111,110,87,111,114,108,100,84,114,97, +110,115,102,111,114,109,0,109,95,105,110,116,101,114,112,111,108,97,116,105, +111,110,76,105,110,101,97,114,86,101,108,111,99,105,116,121,0,109,95,105, +110,116,101,114,112,111,108,97,116,105,111,110,65,110,103,117,108,97,114,86, +101,108,111,99,105,116,121,0,109,95,97,110,105,115,111,116,114,111,112,105, +99,70,114,105,99,116,105,111,110,0,109,95,99,111,110,116,97,99,116,80, +114,111,99,101,115,115,105,110,103,84,104,114,101,115,104,111,108,100,0,109, +95,100,101,97,99,116,105,118,97,116,105,111,110,84,105,109,101,0,109,95, +102,114,105,99,116,105,111,110,0,109,95,114,101,115,116,105,116,117,116,105, +111,110,0,109,95,104,105,116,70,114,97,99,116,105,111,110,0,109,95,99, +99,100,83,119,101,112,116,83,112,104,101,114,101,82,97,100,105,117,115,0, +109,95,99,99,100,77,111,116,105,111,110,84,104,114,101,115,104,111,108,100, +0,109,95,104,97,115,65,110,105,115,111,116,114,111,112,105,99,70,114,105, +99,116,105,111,110,0,109,95,99,111,108,108,105,115,105,111,110,70,108,97, +103,115,0,109,95,105,115,108,97,110,100,84,97,103,49,0,109,95,99,111, +109,112,97,110,105,111,110,73,100,0,109,95,97,99,116,105,118,97,116,105, +111,110,83,116,97,116,101,49,0,109,95,105,110,116,101,114,110,97,108,84, +121,112,101,0,109,95,99,104,101,99,107,67,111,108,108,105,100,101,87,105, +116,104,0,109,95,99,111,108,108,105,115,105,111,110,79,98,106,101,99,116, +68,97,116,97,0,109,95,105,110,118,73,110,101,114,116,105,97,84,101,110, +115,111,114,87,111,114,108,100,0,109,95,108,105,110,101,97,114,86,101,108, +111,99,105,116,121,0,109,95,97,110,103,117,108,97,114,86,101,108,111,99, +105,116,121,0,109,95,97,110,103,117,108,97,114,70,97,99,116,111,114,0, +109,95,108,105,110,101,97,114,70,97,99,116,111,114,0,109,95,103,114,97, +118,105,116,121,0,109,95,103,114,97,118,105,116,121,95,97,99,99,101,108, +101,114,97,116,105,111,110,0,109,95,105,110,118,73,110,101,114,116,105,97, +76,111,99,97,108,0,109,95,116,111,116,97,108,70,111,114,99,101,0,109, +95,116,111,116,97,108,84,111,114,113,117,101,0,109,95,105,110,118,101,114, +115,101,77,97,115,115,0,109,95,108,105,110,101,97,114,68,97,109,112,105, +110,103,0,109,95,97,110,103,117,108,97,114,68,97,109,112,105,110,103,0, +109,95,97,100,100,105,116,105,111,110,97,108,68,97,109,112,105,110,103,70, +97,99,116,111,114,0,109,95,97,100,100,105,116,105,111,110,97,108,76,105, +110,101,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,108,100, +83,113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,103,117, +108,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,108,100,83, +113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,103,117,108, +97,114,68,97,109,112,105,110,103,70,97,99,116,111,114,0,109,95,108,105, +110,101,97,114,83,108,101,101,112,105,110,103,84,104,114,101,115,104,111,108, +100,0,109,95,97,110,103,117,108,97,114,83,108,101,101,112,105,110,103,84, +104,114,101,115,104,111,108,100,0,109,95,97,100,100,105,116,105,111,110,97, +108,68,97,109,112,105,110,103,0,109,95,110,117,109,67,111,110,115,116,114, +97,105,110,116,82,111,119,115,0,110,117,98,0,42,109,95,114,98,65,0, +42,109,95,114,98,66,0,109,95,111,98,106,101,99,116,84,121,112,101,0, +109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,84,121,112,101, +0,109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,73,100,0, +109,95,110,101,101,100,115,70,101,101,100,98,97,99,107,0,109,95,97,112, +112,108,105,101,100,73,109,112,117,108,115,101,0,109,95,100,98,103,68,114, +97,119,83,105,122,101,0,109,95,100,105,115,97,98,108,101,67,111,108,108, +105,115,105,111,110,115,66,101,116,119,101,101,110,76,105,110,107,101,100,66, +111,100,105,101,115,0,109,95,111,118,101,114,114,105,100,101,78,117,109,83, +111,108,118,101,114,73,116,101,114,97,116,105,111,110,115,0,109,95,98,114, +101,97,107,105,110,103,73,109,112,117,108,115,101,84,104,114,101,115,104,111, +108,100,0,109,95,105,115,69,110,97,98,108,101,100,0,109,95,116,121,112, +101,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,109,95,112,105, +118,111,116,73,110,65,0,109,95,112,105,118,111,116,73,110,66,0,109,95, +114,98,65,70,114,97,109,101,0,109,95,114,98,66,70,114,97,109,101,0, +109,95,117,115,101,82,101,102,101,114,101,110,99,101,70,114,97,109,101,65, +0,109,95,97,110,103,117,108,97,114,79,110,108,121,0,109,95,101,110,97, +98,108,101,65,110,103,117,108,97,114,77,111,116,111,114,0,109,95,109,111, +116,111,114,84,97,114,103,101,116,86,101,108,111,99,105,116,121,0,109,95, +109,97,120,77,111,116,111,114,73,109,112,117,108,115,101,0,109,95,108,111, +119,101,114,76,105,109,105,116,0,109,95,117,112,112,101,114,76,105,109,105, +116,0,109,95,108,105,109,105,116,83,111,102,116,110,101,115,115,0,109,95, +98,105,97,115,70,97,99,116,111,114,0,109,95,114,101,108,97,120,97,116, +105,111,110,70,97,99,116,111,114,0,109,95,115,119,105,110,103,83,112,97, +110,49,0,109,95,115,119,105,110,103,83,112,97,110,50,0,109,95,116,119, +105,115,116,83,112,97,110,0,109,95,100,97,109,112,105,110,103,0,109,95, +108,105,110,101,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,108, +105,110,101,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,97,110, +103,117,108,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,97,110, +103,117,108,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,117,115, +101,76,105,110,101,97,114,82,101,102,101,114,101,110,99,101,70,114,97,109, +101,65,0,109,95,117,115,101,79,102,102,115,101,116,70,111,114,67,111,110, +115,116,114,97,105,110,116,70,114,97,109,101,0,109,95,54,100,111,102,68, +97,116,97,0,109,95,115,112,114,105,110,103,69,110,97,98,108,101,100,91, +54,93,0,109,95,101,113,117,105,108,105,98,114,105,117,109,80,111,105,110, +116,91,54,93,0,109,95,115,112,114,105,110,103,83,116,105,102,102,110,101, +115,115,91,54,93,0,109,95,115,112,114,105,110,103,68,97,109,112,105,110, +103,91,54,93,0,109,95,108,105,110,101,97,114,83,116,105,102,102,110,101, +115,115,0,109,95,97,110,103,117,108,97,114,83,116,105,102,102,110,101,115, +115,0,109,95,118,111,108,117,109,101,83,116,105,102,102,110,101,115,115,0, +42,109,95,109,97,116,101,114,105,97,108,0,109,95,112,111,115,105,116,105, +111,110,0,109,95,112,114,101,118,105,111,117,115,80,111,115,105,116,105,111, +110,0,109,95,118,101,108,111,99,105,116,121,0,109,95,97,99,99,117,109, +117,108,97,116,101,100,70,111,114,99,101,0,109,95,110,111,114,109,97,108, +0,109,95,97,114,101,97,0,109,95,97,116,116,97,99,104,0,109,95,110, +111,100,101,73,110,100,105,99,101,115,91,50,93,0,109,95,114,101,115,116, +76,101,110,103,116,104,0,109,95,98,98,101,110,100,105,110,103,0,109,95, +110,111,100,101,73,110,100,105,99,101,115,91,51,93,0,109,95,114,101,115, +116,65,114,101,97,0,109,95,99,48,91,52,93,0,109,95,110,111,100,101, +73,110,100,105,99,101,115,91,52,93,0,109,95,114,101,115,116,86,111,108, +117,109,101,0,109,95,99,49,0,109,95,99,50,0,109,95,99,48,0,109, +95,108,111,99,97,108,70,114,97,109,101,0,42,109,95,114,105,103,105,100, +66,111,100,121,0,109,95,110,111,100,101,73,110,100,101,120,0,109,95,97, +101,114,111,77,111,100,101,108,0,109,95,98,97,117,109,103,97,114,116,101, +0,109,95,100,114,97,103,0,109,95,108,105,102,116,0,109,95,112,114,101, +115,115,117,114,101,0,109,95,118,111,108,117,109,101,0,109,95,100,121,110, +97,109,105,99,70,114,105,99,116,105,111,110,0,109,95,112,111,115,101,77, +97,116,99,104,0,109,95,114,105,103,105,100,67,111,110,116,97,99,116,72, +97,114,100,110,101,115,115,0,109,95,107,105,110,101,116,105,99,67,111,110, +116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,67, +111,110,116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,97,110,99, +104,111,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,82,105, +103,105,100,67,108,117,115,116,101,114,72,97,114,100,110,101,115,115,0,109, +95,115,111,102,116,75,105,110,101,116,105,99,67,108,117,115,116,101,114,72, +97,114,100,110,101,115,115,0,109,95,115,111,102,116,83,111,102,116,67,108, +117,115,116,101,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116, +82,105,103,105,100,67,108,117,115,116,101,114,73,109,112,117,108,115,101,83, +112,108,105,116,0,109,95,115,111,102,116,75,105,110,101,116,105,99,67,108, +117,115,116,101,114,73,109,112,117,108,115,101,83,112,108,105,116,0,109,95, +115,111,102,116,83,111,102,116,67,108,117,115,116,101,114,73,109,112,117,108, +115,101,83,112,108,105,116,0,109,95,109,97,120,86,111,108,117,109,101,0, +109,95,116,105,109,101,83,99,97,108,101,0,109,95,118,101,108,111,99,105, +116,121,73,116,101,114,97,116,105,111,110,115,0,109,95,112,111,115,105,116, +105,111,110,73,116,101,114,97,116,105,111,110,115,0,109,95,100,114,105,102, +116,73,116,101,114,97,116,105,111,110,115,0,109,95,99,108,117,115,116,101, +114,73,116,101,114,97,116,105,111,110,115,0,109,95,114,111,116,0,109,95, +115,99,97,108,101,0,109,95,97,113,113,0,109,95,99,111,109,0,42,109, +95,112,111,115,105,116,105,111,110,115,0,42,109,95,119,101,105,103,104,116, +115,0,109,95,110,117,109,80,111,115,105,116,105,111,110,115,0,109,95,110, +117,109,87,101,105,103,116,115,0,109,95,98,118,111,108,117,109,101,0,109, +95,98,102,114,97,109,101,0,109,95,102,114,97,109,101,120,102,111,114,109, +0,109,95,108,111,99,105,105,0,109,95,105,110,118,119,105,0,109,95,118, +105,109,112,117,108,115,101,115,91,50,93,0,109,95,100,105,109,112,117,108, +115,101,115,91,50,93,0,109,95,108,118,0,109,95,97,118,0,42,109,95, +102,114,97,109,101,114,101,102,115,0,42,109,95,110,111,100,101,73,110,100, +105,99,101,115,0,42,109,95,109,97,115,115,101,115,0,109,95,110,117,109, +70,114,97,109,101,82,101,102,115,0,109,95,110,117,109,78,111,100,101,115, +0,109,95,110,117,109,77,97,115,115,101,115,0,109,95,105,100,109,97,115, +115,0,109,95,105,109,97,115,115,0,109,95,110,118,105,109,112,117,108,115, +101,115,0,109,95,110,100,105,109,112,117,108,115,101,115,0,109,95,110,100, +97,109,112,105,110,103,0,109,95,108,100,97,109,112,105,110,103,0,109,95, +97,100,97,109,112,105,110,103,0,109,95,109,97,116,99,104,105,110,103,0, +109,95,109,97,120,83,101,108,102,67,111,108,108,105,115,105,111,110,73,109, +112,117,108,115,101,0,109,95,115,101,108,102,67,111,108,108,105,115,105,111, +110,73,109,112,117,108,115,101,70,97,99,116,111,114,0,109,95,99,111,110, +116,97,105,110,115,65,110,99,104,111,114,0,109,95,99,111,108,108,105,100, +101,0,109,95,99,108,117,115,116,101,114,73,110,100,101,120,0,42,109,95, +98,111,100,121,65,0,42,109,95,98,111,100,121,66,0,109,95,114,101,102, +115,91,50,93,0,109,95,99,102,109,0,109,95,101,114,112,0,109,95,115, +112,108,105,116,0,109,95,100,101,108,101,116,101,0,109,95,114,101,108,80, +111,115,105,116,105,111,110,91,50,93,0,109,95,98,111,100,121,65,116,121, +112,101,0,109,95,98,111,100,121,66,116,121,112,101,0,109,95,106,111,105, +110,116,84,121,112,101,0,42,109,95,112,111,115,101,0,42,42,109,95,109, +97,116,101,114,105,97,108,115,0,42,109,95,110,111,100,101,115,0,42,109, +95,108,105,110,107,115,0,42,109,95,102,97,99,101,115,0,42,109,95,116, +101,116,114,97,104,101,100,114,97,0,42,109,95,97,110,99,104,111,114,115, +0,42,109,95,99,108,117,115,116,101,114,115,0,42,109,95,106,111,105,110, +116,115,0,109,95,110,117,109,77,97,116,101,114,105,97,108,115,0,109,95, +110,117,109,76,105,110,107,115,0,109,95,110,117,109,70,97,99,101,115,0, +109,95,110,117,109,84,101,116,114,97,104,101,100,114,97,0,109,95,110,117, +109,65,110,99,104,111,114,115,0,109,95,110,117,109,67,108,117,115,116,101, +114,115,0,109,95,110,117,109,74,111,105,110,116,115,0,109,95,99,111,110, +102,105,103,0,84,89,80,69,72,0,0,0,99,104,97,114,0,117,99,104, +97,114,0,115,104,111,114,116,0,117,115,104,111,114,116,0,105,110,116,0, +108,111,110,103,0,117,108,111,110,103,0,102,108,111,97,116,0,100,111,117, +98,108,101,0,118,111,105,100,0,80,111,105,110,116,101,114,65,114,114,97, +121,0,98,116,80,104,121,115,105,99,115,83,121,115,116,101,109,0,76,105, +115,116,66,97,115,101,0,98,116,86,101,99,116,111,114,51,70,108,111,97, +116,68,97,116,97,0,98,116,86,101,99,116,111,114,51,68,111,117,98,108, +101,68,97,116,97,0,98,116,77,97,116,114,105,120,51,120,51,70,108,111, +97,116,68,97,116,97,0,98,116,77,97,116,114,105,120,51,120,51,68,111, +117,98,108,101,68,97,116,97,0,98,116,84,114,97,110,115,102,111,114,109, +70,108,111,97,116,68,97,116,97,0,98,116,84,114,97,110,115,102,111,114, +109,68,111,117,98,108,101,68,97,116,97,0,98,116,66,118,104,83,117,98, +116,114,101,101,73,110,102,111,68,97,116,97,0,98,116,79,112,116,105,109, +105,122,101,100,66,118,104,78,111,100,101,70,108,111,97,116,68,97,116,97, +0,98,116,79,112,116,105,109,105,122,101,100,66,118,104,78,111,100,101,68, +111,117,98,108,101,68,97,116,97,0,98,116,81,117,97,110,116,105,122,101, +100,66,118,104,78,111,100,101,68,97,116,97,0,98,116,81,117,97,110,116, +105,122,101,100,66,118,104,70,108,111,97,116,68,97,116,97,0,98,116,81, +117,97,110,116,105,122,101,100,66,118,104,68,111,117,98,108,101,68,97,116, +97,0,98,116,67,111,108,108,105,115,105,111,110,83,104,97,112,101,68,97, +116,97,0,98,116,83,116,97,116,105,99,80,108,97,110,101,83,104,97,112, +101,68,97,116,97,0,98,116,67,111,110,118,101,120,73,110,116,101,114,110, +97,108,83,104,97,112,101,68,97,116,97,0,98,116,80,111,115,105,116,105, +111,110,65,110,100,82,97,100,105,117,115,0,98,116,77,117,108,116,105,83, +112,104,101,114,101,83,104,97,112,101,68,97,116,97,0,98,116,73,110,116, +73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114,116,73,110,116, +73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114,116,73,110,116, +73,110,100,101,120,84,114,105,112,108,101,116,68,97,116,97,0,98,116,67, +104,97,114,73,110,100,101,120,84,114,105,112,108,101,116,68,97,116,97,0, +98,116,77,101,115,104,80,97,114,116,68,97,116,97,0,98,116,83,116,114, +105,100,105,110,103,77,101,115,104,73,110,116,101,114,102,97,99,101,68,97, +116,97,0,98,116,84,114,105,97,110,103,108,101,77,101,115,104,83,104,97, +112,101,68,97,116,97,0,98,116,84,114,105,97,110,103,108,101,73,110,102, +111,77,97,112,68,97,116,97,0,98,116,83,99,97,108,101,100,84,114,105, +97,110,103,108,101,77,101,115,104,83,104,97,112,101,68,97,116,97,0,98, +116,67,111,109,112,111,117,110,100,83,104,97,112,101,67,104,105,108,100,68, +97,116,97,0,98,116,67,111,109,112,111,117,110,100,83,104,97,112,101,68, +97,116,97,0,98,116,67,121,108,105,110,100,101,114,83,104,97,112,101,68, +97,116,97,0,98,116,67,97,112,115,117,108,101,83,104,97,112,101,68,97, +116,97,0,98,116,84,114,105,97,110,103,108,101,73,110,102,111,68,97,116, +97,0,98,116,71,73,109,112,97,99,116,77,101,115,104,83,104,97,112,101, +68,97,116,97,0,98,116,67,111,110,118,101,120,72,117,108,108,83,104,97, +112,101,68,97,116,97,0,98,116,67,111,108,108,105,115,105,111,110,79,98, +106,101,99,116,68,111,117,98,108,101,68,97,116,97,0,98,116,67,111,108, +108,105,115,105,111,110,79,98,106,101,99,116,70,108,111,97,116,68,97,116, +97,0,98,116,82,105,103,105,100,66,111,100,121,70,108,111,97,116,68,97, +116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,111,117,98,108,101, +68,97,116,97,0,98,116,67,111,110,115,116,114,97,105,110,116,73,110,102, +111,49,0,98,116,84,121,112,101,100,67,111,110,115,116,114,97,105,110,116, +68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,97,116,97, +0,98,116,80,111,105,110,116,50,80,111,105,110,116,67,111,110,115,116,114, +97,105,110,116,70,108,111,97,116,68,97,116,97,0,98,116,80,111,105,110, +116,50,80,111,105,110,116,67,111,110,115,116,114,97,105,110,116,68,111,117, +98,108,101,68,97,116,97,0,98,116,72,105,110,103,101,67,111,110,115,116, +114,97,105,110,116,68,111,117,98,108,101,68,97,116,97,0,98,116,72,105, +110,103,101,67,111,110,115,116,114,97,105,110,116,70,108,111,97,116,68,97, +116,97,0,98,116,67,111,110,101,84,119,105,115,116,67,111,110,115,116,114, +97,105,110,116,68,97,116,97,0,98,116,71,101,110,101,114,105,99,54,68, +111,102,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,71, +101,110,101,114,105,99,54,68,111,102,83,112,114,105,110,103,67,111,110,115, +116,114,97,105,110,116,68,97,116,97,0,98,116,83,108,105,100,101,114,67, +111,110,115,116,114,97,105,110,116,68,97,116,97,0,83,111,102,116,66,111, +100,121,77,97,116,101,114,105,97,108,68,97,116,97,0,83,111,102,116,66, +111,100,121,78,111,100,101,68,97,116,97,0,83,111,102,116,66,111,100,121, +76,105,110,107,68,97,116,97,0,83,111,102,116,66,111,100,121,70,97,99, +101,68,97,116,97,0,83,111,102,116,66,111,100,121,84,101,116,114,97,68, +97,116,97,0,83,111,102,116,82,105,103,105,100,65,110,99,104,111,114,68, +97,116,97,0,83,111,102,116,66,111,100,121,67,111,110,102,105,103,68,97, +116,97,0,83,111,102,116,66,111,100,121,80,111,115,101,68,97,116,97,0, +83,111,102,116,66,111,100,121,67,108,117,115,116,101,114,68,97,116,97,0, +98,116,83,111,102,116,66,111,100,121,74,111,105,110,116,68,97,116,97,0, +98,116,83,111,102,116,66,111,100,121,70,108,111,97,116,68,97,116,97,0, +84,76,69,78,1,0,1,0,2,0,2,0,4,0,4,0,4,0,4,0, +8,0,0,0,16,0,48,0,16,0,16,0,32,0,48,0,96,0,64,0, +-128,0,20,0,48,0,80,0,16,0,96,0,-112,0,16,0,56,0,56,0, +20,0,72,0,4,0,4,0,8,0,4,0,56,0,32,0,80,0,72,0, +96,0,80,0,32,0,64,0,64,0,16,0,72,0,80,0,-40,1,8,1, +-16,1,-88,3,8,0,64,0,0,0,96,0,-128,0,104,1,-24,0,-32,0, +8,1,104,1,-40,0,16,0,104,0,24,0,40,0,104,0,96,0,104,0, +-56,0,104,1,112,0,-40,1,83,84,82,67,61,0,0,0,10,0,3,0, +4,0,0,0,4,0,1,0,9,0,2,0,11,0,3,0,10,0,3,0, +10,0,4,0,10,0,5,0,12,0,2,0,9,0,6,0,9,0,7,0, +13,0,1,0,7,0,8,0,14,0,1,0,8,0,8,0,15,0,1,0, +13,0,9,0,16,0,1,0,14,0,9,0,17,0,2,0,15,0,10,0, +13,0,11,0,18,0,2,0,16,0,10,0,14,0,11,0,19,0,4,0, +4,0,12,0,4,0,13,0,2,0,14,0,2,0,15,0,20,0,6,0, +13,0,16,0,13,0,17,0,4,0,18,0,4,0,19,0,4,0,20,0, +0,0,21,0,21,0,6,0,14,0,16,0,14,0,17,0,4,0,18,0, +4,0,19,0,4,0,20,0,0,0,21,0,22,0,3,0,2,0,14,0, +2,0,15,0,4,0,22,0,23,0,12,0,13,0,23,0,13,0,24,0, +13,0,25,0,4,0,26,0,4,0,27,0,4,0,28,0,4,0,29,0, +20,0,30,0,22,0,31,0,19,0,32,0,4,0,33,0,4,0,34,0, +24,0,12,0,14,0,23,0,14,0,24,0,14,0,25,0,4,0,26,0, +4,0,27,0,4,0,28,0,4,0,29,0,21,0,30,0,22,0,31,0, +4,0,33,0,4,0,34,0,19,0,32,0,25,0,3,0,0,0,35,0, +4,0,36,0,0,0,37,0,26,0,5,0,25,0,38,0,13,0,39,0, +13,0,40,0,7,0,41,0,0,0,21,0,27,0,5,0,25,0,38,0, +13,0,39,0,13,0,42,0,7,0,43,0,4,0,44,0,28,0,2,0, +13,0,45,0,7,0,46,0,29,0,4,0,27,0,47,0,28,0,48,0, +4,0,49,0,0,0,37,0,30,0,1,0,4,0,50,0,31,0,2,0, +2,0,50,0,0,0,51,0,32,0,2,0,2,0,52,0,0,0,51,0, +33,0,2,0,0,0,52,0,0,0,53,0,34,0,8,0,13,0,54,0, +14,0,55,0,30,0,56,0,32,0,57,0,33,0,58,0,31,0,59,0, +4,0,60,0,4,0,61,0,35,0,4,0,34,0,62,0,13,0,63,0, +4,0,64,0,0,0,37,0,36,0,7,0,25,0,38,0,35,0,65,0, +23,0,66,0,24,0,67,0,37,0,68,0,7,0,43,0,0,0,69,0, +38,0,2,0,36,0,70,0,13,0,39,0,39,0,4,0,17,0,71,0, +25,0,72,0,4,0,73,0,7,0,74,0,40,0,4,0,25,0,38,0, +39,0,75,0,4,0,76,0,7,0,43,0,41,0,3,0,27,0,47,0, +4,0,77,0,0,0,37,0,42,0,3,0,27,0,47,0,4,0,77,0, +0,0,37,0,43,0,4,0,4,0,78,0,7,0,79,0,7,0,80,0, +7,0,81,0,37,0,14,0,4,0,82,0,4,0,83,0,43,0,84,0, +4,0,85,0,7,0,86,0,7,0,87,0,7,0,88,0,7,0,89,0, +7,0,90,0,4,0,91,0,4,0,92,0,4,0,93,0,4,0,94,0, +0,0,37,0,44,0,5,0,25,0,38,0,35,0,65,0,13,0,39,0, +7,0,43,0,4,0,95,0,45,0,5,0,27,0,47,0,13,0,96,0, +14,0,97,0,4,0,98,0,0,0,99,0,46,0,24,0,9,0,100,0, +9,0,101,0,25,0,102,0,0,0,35,0,18,0,103,0,18,0,104,0, +14,0,105,0,14,0,106,0,14,0,107,0,8,0,108,0,8,0,109,0, +8,0,110,0,8,0,111,0,8,0,112,0,8,0,113,0,8,0,114,0, +4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0,4,0,119,0, +4,0,120,0,4,0,121,0,0,0,37,0,47,0,23,0,9,0,100,0, +9,0,101,0,25,0,102,0,0,0,35,0,17,0,103,0,17,0,104,0, +13,0,105,0,13,0,106,0,13,0,107,0,7,0,108,0,7,0,109,0, +7,0,110,0,7,0,111,0,7,0,112,0,7,0,113,0,7,0,114,0, +4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0,4,0,119,0, +4,0,120,0,4,0,121,0,48,0,21,0,47,0,122,0,15,0,123,0, +13,0,124,0,13,0,125,0,13,0,126,0,13,0,127,0,13,0,-128,0, +13,0,-127,0,13,0,-126,0,13,0,-125,0,13,0,-124,0,7,0,-123,0, +7,0,-122,0,7,0,-121,0,7,0,-120,0,7,0,-119,0,7,0,-118,0, +7,0,-117,0,7,0,-116,0,7,0,-115,0,4,0,-114,0,49,0,22,0, +46,0,122,0,16,0,123,0,14,0,124,0,14,0,125,0,14,0,126,0, +14,0,127,0,14,0,-128,0,14,0,-127,0,14,0,-126,0,14,0,-125,0, +14,0,-124,0,8,0,-123,0,8,0,-122,0,8,0,-121,0,8,0,-120,0, +8,0,-119,0,8,0,-118,0,8,0,-117,0,8,0,-116,0,8,0,-115,0, +4,0,-114,0,0,0,37,0,50,0,2,0,4,0,-113,0,4,0,-112,0, +51,0,13,0,52,0,-111,0,52,0,-110,0,0,0,35,0,4,0,-109,0, +4,0,-108,0,4,0,-107,0,4,0,-106,0,7,0,-105,0,7,0,-104,0, +4,0,-103,0,4,0,-102,0,7,0,-101,0,4,0,-100,0,53,0,3,0, +51,0,-99,0,13,0,-98,0,13,0,-97,0,54,0,3,0,51,0,-99,0, +14,0,-98,0,14,0,-97,0,55,0,13,0,51,0,-99,0,18,0,-96,0, +18,0,-95,0,4,0,-94,0,4,0,-93,0,4,0,-92,0,7,0,-91,0, +7,0,-90,0,7,0,-89,0,7,0,-88,0,7,0,-87,0,7,0,-86,0, +7,0,-85,0,56,0,13,0,51,0,-99,0,17,0,-96,0,17,0,-95,0, +4,0,-94,0,4,0,-93,0,4,0,-92,0,7,0,-91,0,7,0,-90,0, +7,0,-89,0,7,0,-88,0,7,0,-87,0,7,0,-86,0,7,0,-85,0, +57,0,11,0,51,0,-99,0,17,0,-96,0,17,0,-95,0,7,0,-84,0, +7,0,-83,0,7,0,-82,0,7,0,-87,0,7,0,-86,0,7,0,-85,0, +7,0,-81,0,0,0,21,0,58,0,9,0,51,0,-99,0,17,0,-96,0, +17,0,-95,0,13,0,-80,0,13,0,-79,0,13,0,-78,0,13,0,-77,0, +4,0,-76,0,4,0,-75,0,59,0,5,0,58,0,-74,0,4,0,-73,0, +7,0,-72,0,7,0,-71,0,7,0,-70,0,60,0,9,0,51,0,-99,0, +17,0,-96,0,17,0,-95,0,7,0,-80,0,7,0,-79,0,7,0,-78,0, +7,0,-77,0,4,0,-76,0,4,0,-75,0,61,0,4,0,7,0,-69,0, +7,0,-68,0,7,0,-67,0,4,0,78,0,62,0,10,0,61,0,-66,0, +13,0,-65,0,13,0,-64,0,13,0,-63,0,13,0,-62,0,13,0,-61,0, +7,0,-123,0,7,0,-60,0,4,0,-59,0,4,0,53,0,63,0,4,0, +61,0,-66,0,4,0,-58,0,7,0,-57,0,4,0,-56,0,64,0,4,0, +13,0,-61,0,61,0,-66,0,4,0,-55,0,7,0,-54,0,65,0,7,0, +13,0,-53,0,61,0,-66,0,4,0,-52,0,7,0,-51,0,7,0,-50,0, +7,0,-49,0,4,0,53,0,66,0,6,0,15,0,-48,0,13,0,-50,0, +13,0,-47,0,52,0,-46,0,4,0,-45,0,7,0,-49,0,67,0,26,0, +4,0,-44,0,7,0,-43,0,7,0,-81,0,7,0,-42,0,7,0,-41,0, +7,0,-40,0,7,0,-39,0,7,0,-38,0,7,0,-37,0,7,0,-36,0, +7,0,-35,0,7,0,-34,0,7,0,-33,0,7,0,-32,0,7,0,-31,0, +7,0,-30,0,7,0,-29,0,7,0,-28,0,7,0,-27,0,7,0,-26,0, +7,0,-25,0,4,0,-24,0,4,0,-23,0,4,0,-22,0,4,0,-21,0, +4,0,116,0,68,0,12,0,15,0,-20,0,15,0,-19,0,15,0,-18,0, +13,0,-17,0,13,0,-16,0,7,0,-15,0,4,0,-14,0,4,0,-13,0, +4,0,-12,0,4,0,-11,0,7,0,-51,0,4,0,53,0,69,0,27,0, +17,0,-10,0,15,0,-9,0,15,0,-8,0,13,0,-17,0,13,0,-7,0, +13,0,-6,0,13,0,-5,0,13,0,-4,0,13,0,-3,0,4,0,-2,0, +7,0,-1,0,4,0,0,1,4,0,1,1,4,0,2,1,7,0,3,1, +7,0,4,1,4,0,5,1,4,0,6,1,7,0,7,1,7,0,8,1, +7,0,9,1,7,0,10,1,7,0,11,1,7,0,12,1,4,0,13,1, +4,0,14,1,4,0,15,1,70,0,12,0,9,0,16,1,9,0,17,1, +13,0,18,1,7,0,19,1,7,0,20,1,7,0,21,1,4,0,22,1, +13,0,23,1,4,0,24,1,4,0,25,1,4,0,26,1,4,0,53,0, +71,0,19,0,47,0,122,0,68,0,27,1,61,0,28,1,62,0,29,1, +63,0,30,1,64,0,31,1,65,0,32,1,66,0,33,1,69,0,34,1, +70,0,35,1,4,0,36,1,4,0,1,1,4,0,37,1,4,0,38,1, +4,0,39,1,4,0,40,1,4,0,41,1,4,0,42,1,67,0,43,1, +}; +int sBulletDNAlen64= sizeof(sBulletDNAstr64); diff --git a/src/LinearMath/btSerializer.h b/src/LinearMath/btSerializer.h new file mode 100644 index 0000000..7d90ad2 --- /dev/null +++ b/src/LinearMath/btSerializer.h @@ -0,0 +1,639 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SERIALIZER_H +#define BT_SERIALIZER_H + +#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE +#include "btStackAlloc.h" +#include "btHashMap.h" + +#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__) +#include +#endif +#include + + + +///only the 32bit versions for now +extern char sBulletDNAstr[]; +extern int sBulletDNAlen; +extern char sBulletDNAstr64[]; +extern int sBulletDNAlen64; + +SIMD_FORCE_INLINE int btStrLen(const char* str) +{ + if (!str) + return(0); + int len = 0; + + while (*str != 0) + { + str++; + len++; + } + + return len; +} + + +class btChunk +{ +public: + int m_chunkCode; + int m_length; + void *m_oldPtr; + int m_dna_nr; + int m_number; +}; + +enum btSerializationFlags +{ + BT_SERIALIZE_NO_BVH = 1, + BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2, + BT_SERIALIZE_NO_DUPLICATE_ASSERT = 4 +}; + +class btSerializer +{ + +public: + + virtual ~btSerializer() {} + + virtual const unsigned char* getBufferPointer() const = 0; + + virtual int getCurrentBufferSize() const = 0; + + virtual btChunk* allocate(size_t size, int numElements) = 0; + + virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0; + + virtual void* findPointer(void* oldPtr) = 0; + + virtual void* getUniquePointer(void*oldPtr) = 0; + + virtual void startSerialization() = 0; + + virtual void finishSerialization() = 0; + + virtual const char* findNameForPointer(const void* ptr) const = 0; + + virtual void registerNameForPointer(const void* ptr, const char* name) = 0; + + virtual void serializeName(const char* ptr) = 0; + + virtual int getSerializationFlags() const = 0; + + virtual void setSerializationFlags(int flags) = 0; + + +}; + + + +#define BT_HEADER_LENGTH 12 +#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) +# define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) ) +#else +# define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) ) +#endif + +#define BT_SOFTBODY_CODE MAKE_ID('S','B','D','Y') +#define BT_COLLISIONOBJECT_CODE MAKE_ID('C','O','B','J') +#define BT_RIGIDBODY_CODE MAKE_ID('R','B','D','Y') +#define BT_CONSTRAINT_CODE MAKE_ID('C','O','N','S') +#define BT_BOXSHAPE_CODE MAKE_ID('B','O','X','S') +#define BT_QUANTIZED_BVH_CODE MAKE_ID('Q','B','V','H') +#define BT_TRIANLGE_INFO_MAP MAKE_ID('T','M','A','P') +#define BT_SHAPE_CODE MAKE_ID('S','H','A','P') +#define BT_ARRAY_CODE MAKE_ID('A','R','A','Y') +#define BT_SBMATERIAL_CODE MAKE_ID('S','B','M','T') +#define BT_SBNODE_CODE MAKE_ID('S','B','N','D') +#define BT_DNA_CODE MAKE_ID('D','N','A','1') + + +struct btPointerUid +{ + union + { + void* m_ptr; + int m_uniqueIds[2]; + }; +}; + +///The btDefaultSerializer is the main Bullet serialization class. +///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero. +class btDefaultSerializer : public btSerializer +{ + + + btAlignedObjectArray mTypes; + btAlignedObjectArray mStructs; + btAlignedObjectArray mTlens; + btHashMap mStructReverse; + btHashMap mTypeLookup; + + + btHashMap m_chunkP; + + btHashMap m_nameMap; + + btHashMap m_uniquePointers; + int m_uniqueIdGenerator; + + int m_totalSize; + unsigned char* m_buffer; + int m_currentSize; + void* m_dna; + int m_dnaLength; + + int m_serializationFlags; + + + btAlignedObjectArray m_chunkPtrs; + +protected: + + virtual void* findPointer(void* oldPtr) + { + void** ptr = m_chunkP.find(oldPtr); + if (ptr && *ptr) + return *ptr; + return 0; + } + + + + + + void writeDNA() + { + btChunk* dnaChunk = allocate(m_dnaLength,1); + memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength); + finalizeChunk(dnaChunk,"DNA1",BT_DNA_CODE, m_dna); + } + + int getReverseType(const char *type) const + { + + btHashString key(type); + const int* valuePtr = mTypeLookup.find(key); + if (valuePtr) + return *valuePtr; + + return -1; + } + + void initDNA(const char* bdnaOrg,int dnalen) + { + ///was already initialized + if (m_dna) + return; + + int littleEndian= 1; + littleEndian= ((char*)&littleEndian)[0]; + + + m_dna = btAlignedAlloc(dnalen,16); + memcpy(m_dna,bdnaOrg,dnalen); + m_dnaLength = dnalen; + + int *intPtr=0; + short *shtPtr=0; + char *cp = 0;int dataLen =0; + intPtr = (int*)m_dna; + + /* + SDNA (4 bytes) (magic number) + NAME (4 bytes) + (4 bytes) amount of names (int) + + + */ + + if (strncmp((const char*)m_dna, "SDNA", 4)==0) + { + // skip ++ NAME + intPtr++; intPtr++; + } + + // Parse names + if (!littleEndian) + *intPtr = btSwapEndian(*intPtr); + + dataLen = *intPtr; + + intPtr++; + + cp = (char*)intPtr; + int i; + for ( i=0; i amount of types (int) + + + */ + + intPtr = (int*)cp; + assert(strncmp(cp, "TYPE", 4)==0); intPtr++; + + if (!littleEndian) + *intPtr = btSwapEndian(*intPtr); + + dataLen = *intPtr; + intPtr++; + + + cp = (char*)intPtr; + for (i=0; i (short) the lengths of types + + */ + + // Parse type lens + intPtr = (int*)cp; + assert(strncmp(cp, "TLEN", 4)==0); intPtr++; + + dataLen = (int)mTypes.size(); + + shtPtr = (short*)intPtr; + for (i=0; i amount of structs (int) + + + + + + + */ + + intPtr = (int*)shtPtr; + cp = (char*)intPtr; + assert(strncmp(cp, "STRC", 4)==0); intPtr++; + + if (!littleEndian) + *intPtr = btSwapEndian(*intPtr); + dataLen = *intPtr ; + intPtr++; + + + shtPtr = (short*)intPtr; + for (i=0; im_length; + memcpy(currentPtr,m_chunkPtrs[i], curLength); + btAlignedFree(m_chunkPtrs[i]); + currentPtr+=curLength; + mysize+=curLength; + } + } + + mTypes.clear(); + mStructs.clear(); + mTlens.clear(); + mStructReverse.clear(); + mTypeLookup.clear(); + m_chunkP.clear(); + m_nameMap.clear(); + m_uniquePointers.clear(); + m_chunkPtrs.clear(); + } + + virtual void* getUniquePointer(void*oldPtr) + { + if (!oldPtr) + return 0; + + btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr); + if (uptr) + { + return uptr->m_ptr; + } + m_uniqueIdGenerator++; + + btPointerUid uid; + uid.m_uniqueIds[0] = m_uniqueIdGenerator; + uid.m_uniqueIds[1] = m_uniqueIdGenerator; + m_uniquePointers.insert(oldPtr,uid); + return uid.m_ptr; + + } + + virtual const unsigned char* getBufferPointer() const + { + return m_buffer; + } + + virtual int getCurrentBufferSize() const + { + return m_currentSize; + } + + virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr) + { + if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT)) + { + btAssert(!findPointer(oldPtr)); + } + + chunk->m_dna_nr = getReverseType(structType); + + chunk->m_chunkCode = chunkCode; + + void* uniquePtr = getUniquePointer(oldPtr); + + m_chunkP.insert(oldPtr,uniquePtr);//chunk->m_oldPtr); + chunk->m_oldPtr = uniquePtr;//oldPtr; + + } + + + virtual unsigned char* internalAlloc(size_t size) + { + unsigned char* ptr = 0; + + if (m_totalSize) + { + ptr = m_buffer+m_currentSize; + m_currentSize += int(size); + btAssert(m_currentSizem_chunkCode = 0; + chunk->m_oldPtr = data; + chunk->m_length = int(size)*numElements; + chunk->m_number = numElements; + + m_chunkPtrs.push_back(chunk); + + + return chunk; + } + + virtual const char* findNameForPointer(const void* ptr) const + { + const char*const * namePtr = m_nameMap.find(ptr); + if (namePtr && *namePtr) + return *namePtr; + return 0; + + } + + virtual void registerNameForPointer(const void* ptr, const char* name) + { + m_nameMap.insert(ptr,name); + } + + virtual void serializeName(const char* name) + { + if (name) + { + //don't serialize name twice + if (findPointer((void*)name)) + return; + + int len = btStrLen(name); + if (len) + { + + int newLen = len+1; + int padding = ((newLen+3)&~3)-newLen; + newLen += padding; + + //serialize name string now + btChunk* chunk = allocate(sizeof(char),newLen); + char* destinationName = (char*)chunk->m_oldPtr; + for (int i=0;i(totalsize - usedsize); + } + + unsigned char* allocate(unsigned int size) + { + const unsigned int nus(usedsize+size); + if(nusprevious = current; + pb->address = data+usedsize; + current = pb; + return(pb); + } + SIMD_FORCE_INLINE void endBlock(btBlock* block) + { + btAssert(block==current); + //Raise(L"Unmatched blocks"); + if(block==current) + { + current = block->previous; + usedsize = (unsigned int)((block->address-data)-sizeof(btBlock)); + } + } + +private: + void ctor() + { + data = 0; + totalsize = 0; + usedsize = 0; + current = 0; + ischild = false; + } + unsigned char* data; + unsigned int totalsize; + unsigned int usedsize; + btBlock* current; + bool ischild; +}; + +#endif //BT_STACK_ALLOC diff --git a/src/LinearMath/btTransform.h b/src/LinearMath/btTransform.h new file mode 100644 index 0000000..5e52d18 --- /dev/null +++ b/src/LinearMath/btTransform.h @@ -0,0 +1,307 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_TRANSFORM_H +#define BT_TRANSFORM_H + + +#include "btMatrix3x3.h" + +#ifdef BT_USE_DOUBLE_PRECISION +#define btTransformData btTransformDoubleData +#else +#define btTransformData btTransformFloatData +#endif + + + + +/**@brief The btTransform class supports rigid transforms with only translation and rotation and no scaling/shear. + *It can be used in combination with btVector3, btQuaternion and btMatrix3x3 linear algebra classes. */ +class btTransform { + + ///Storage for the rotation + btMatrix3x3 m_basis; + ///Storage for the translation + btVector3 m_origin; + +public: + + /**@brief No initialization constructor */ + btTransform() {} + /**@brief Constructor from btQuaternion (optional btVector3 ) + * @param q Rotation from quaternion + * @param c Translation from Vector (default 0,0,0) */ + explicit SIMD_FORCE_INLINE btTransform(const btQuaternion& q, + const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0))) + : m_basis(q), + m_origin(c) + {} + + /**@brief Constructor from btMatrix3x3 (optional btVector3) + * @param b Rotation from Matrix + * @param c Translation from Vector default (0,0,0)*/ + explicit SIMD_FORCE_INLINE btTransform(const btMatrix3x3& b, + const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0))) + : m_basis(b), + m_origin(c) + {} + /**@brief Copy constructor */ + SIMD_FORCE_INLINE btTransform (const btTransform& other) + : m_basis(other.m_basis), + m_origin(other.m_origin) + { + } + /**@brief Assignment Operator */ + SIMD_FORCE_INLINE btTransform& operator=(const btTransform& other) + { + m_basis = other.m_basis; + m_origin = other.m_origin; + return *this; + } + + + /**@brief Set the current transform as the value of the product of two transforms + * @param t1 Transform 1 + * @param t2 Transform 2 + * This = Transform1 * Transform2 */ + SIMD_FORCE_INLINE void mult(const btTransform& t1, const btTransform& t2) { + m_basis = t1.m_basis * t2.m_basis; + m_origin = t1(t2.m_origin); + } + +/* void multInverseLeft(const btTransform& t1, const btTransform& t2) { + btVector3 v = t2.m_origin - t1.m_origin; + m_basis = btMultTransposeLeft(t1.m_basis, t2.m_basis); + m_origin = v * t1.m_basis; + } + */ + +/**@brief Return the transform of the vector */ + SIMD_FORCE_INLINE btVector3 operator()(const btVector3& x) const + { + return btVector3(m_basis[0].dot(x) + m_origin.x(), + m_basis[1].dot(x) + m_origin.y(), + m_basis[2].dot(x) + m_origin.z()); + } + + /**@brief Return the transform of the vector */ + SIMD_FORCE_INLINE btVector3 operator*(const btVector3& x) const + { + return (*this)(x); + } + + /**@brief Return the transform of the btQuaternion */ + SIMD_FORCE_INLINE btQuaternion operator*(const btQuaternion& q) const + { + return getRotation() * q; + } + + /**@brief Return the basis matrix for the rotation */ + SIMD_FORCE_INLINE btMatrix3x3& getBasis() { return m_basis; } + /**@brief Return the basis matrix for the rotation */ + SIMD_FORCE_INLINE const btMatrix3x3& getBasis() const { return m_basis; } + + /**@brief Return the origin vector translation */ + SIMD_FORCE_INLINE btVector3& getOrigin() { return m_origin; } + /**@brief Return the origin vector translation */ + SIMD_FORCE_INLINE const btVector3& getOrigin() const { return m_origin; } + + /**@brief Return a quaternion representing the rotation */ + btQuaternion getRotation() const { + btQuaternion q; + m_basis.getRotation(q); + return q; + } + + + /**@brief Set from an array + * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */ + void setFromOpenGLMatrix(const btScalar *m) + { + m_basis.setFromOpenGLSubMatrix(m); + m_origin.setValue(m[12],m[13],m[14]); + } + + /**@brief Fill an array representation + * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */ + void getOpenGLMatrix(btScalar *m) const + { + m_basis.getOpenGLSubMatrix(m); + m[12] = m_origin.x(); + m[13] = m_origin.y(); + m[14] = m_origin.z(); + m[15] = btScalar(1.0); + } + + /**@brief Set the translational element + * @param origin The vector to set the translation to */ + SIMD_FORCE_INLINE void setOrigin(const btVector3& origin) + { + m_origin = origin; + } + + SIMD_FORCE_INLINE btVector3 invXform(const btVector3& inVec) const; + + + /**@brief Set the rotational element by btMatrix3x3 */ + SIMD_FORCE_INLINE void setBasis(const btMatrix3x3& basis) + { + m_basis = basis; + } + + /**@brief Set the rotational element by btQuaternion */ + SIMD_FORCE_INLINE void setRotation(const btQuaternion& q) + { + m_basis.setRotation(q); + } + + + /**@brief Set this transformation to the identity */ + void setIdentity() + { + m_basis.setIdentity(); + m_origin.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + } + + /**@brief Multiply this Transform by another(this = this * another) + * @param t The other transform */ + btTransform& operator*=(const btTransform& t) + { + m_origin += m_basis * t.m_origin; + m_basis *= t.m_basis; + return *this; + } + + /**@brief Return the inverse of this transform */ + btTransform inverse() const + { + btMatrix3x3 inv = m_basis.transpose(); + return btTransform(inv, inv * -m_origin); + } + + /**@brief Return the inverse of this transform times the other transform + * @param t The other transform + * return this.inverse() * the other */ + btTransform inverseTimes(const btTransform& t) const; + + /**@brief Return the product of this transform and the other */ + btTransform operator*(const btTransform& t) const; + + /**@brief Return an identity transform */ + static const btTransform& getIdentity() + { + static const btTransform identityTransform(btMatrix3x3::getIdentity()); + return identityTransform; + } + + void serialize(struct btTransformData& dataOut) const; + + void serializeFloat(struct btTransformFloatData& dataOut) const; + + void deSerialize(const struct btTransformData& dataIn); + + void deSerializeDouble(const struct btTransformDoubleData& dataIn); + + void deSerializeFloat(const struct btTransformFloatData& dataIn); + +}; + + +SIMD_FORCE_INLINE btVector3 +btTransform::invXform(const btVector3& inVec) const +{ + btVector3 v = inVec - m_origin; + return (m_basis.transpose() * v); +} + +SIMD_FORCE_INLINE btTransform +btTransform::inverseTimes(const btTransform& t) const +{ + btVector3 v = t.getOrigin() - m_origin; + return btTransform(m_basis.transposeTimes(t.m_basis), + v * m_basis); +} + +SIMD_FORCE_INLINE btTransform +btTransform::operator*(const btTransform& t) const +{ + return btTransform(m_basis * t.m_basis, + (*this)(t.m_origin)); +} + +/**@brief Test if two transforms have all elements equal */ +SIMD_FORCE_INLINE bool operator==(const btTransform& t1, const btTransform& t2) +{ + return ( t1.getBasis() == t2.getBasis() && + t1.getOrigin() == t2.getOrigin() ); +} + + +///for serialization +struct btTransformFloatData +{ + btMatrix3x3FloatData m_basis; + btVector3FloatData m_origin; +}; + +struct btTransformDoubleData +{ + btMatrix3x3DoubleData m_basis; + btVector3DoubleData m_origin; +}; + + + +SIMD_FORCE_INLINE void btTransform::serialize(btTransformData& dataOut) const +{ + m_basis.serialize(dataOut.m_basis); + m_origin.serialize(dataOut.m_origin); +} + +SIMD_FORCE_INLINE void btTransform::serializeFloat(btTransformFloatData& dataOut) const +{ + m_basis.serializeFloat(dataOut.m_basis); + m_origin.serializeFloat(dataOut.m_origin); +} + + +SIMD_FORCE_INLINE void btTransform::deSerialize(const btTransformData& dataIn) +{ + m_basis.deSerialize(dataIn.m_basis); + m_origin.deSerialize(dataIn.m_origin); +} + +SIMD_FORCE_INLINE void btTransform::deSerializeFloat(const btTransformFloatData& dataIn) +{ + m_basis.deSerializeFloat(dataIn.m_basis); + m_origin.deSerializeFloat(dataIn.m_origin); +} + +SIMD_FORCE_INLINE void btTransform::deSerializeDouble(const btTransformDoubleData& dataIn) +{ + m_basis.deSerializeDouble(dataIn.m_basis); + m_origin.deSerializeDouble(dataIn.m_origin); +} + + +#endif //BT_TRANSFORM_H + + + + + + diff --git a/src/LinearMath/btTransformUtil.h b/src/LinearMath/btTransformUtil.h new file mode 100644 index 0000000..2303c27 --- /dev/null +++ b/src/LinearMath/btTransformUtil.h @@ -0,0 +1,228 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_TRANSFORM_UTIL_H +#define BT_TRANSFORM_UTIL_H + +#include "btTransform.h" +#define ANGULAR_MOTION_THRESHOLD btScalar(0.5)*SIMD_HALF_PI + + + + +SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir) +{ + return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), + supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), + supportDir.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); +} + + + + + + +/// Utils related to temporal transforms +class btTransformUtil +{ + +public: + + static void integrateTransform(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep,btTransform& predictedTransform) + { + predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep); +// #define QUATERNION_DERIVATIVE + #ifdef QUATERNION_DERIVATIVE + btQuaternion predictedOrn = curTrans.getRotation(); + predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5)); + predictedOrn.normalize(); + #else + //Exponential map + //google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia + + btVector3 axis; + btScalar fAngle = angvel.length(); + //limit the angular motion + if (fAngle*timeStep > ANGULAR_MOTION_THRESHOLD) + { + fAngle = ANGULAR_MOTION_THRESHOLD / timeStep; + } + + if ( fAngle < btScalar(0.001) ) + { + // use Taylor's expansions of sync function + axis = angvel*( btScalar(0.5)*timeStep-(timeStep*timeStep*timeStep)*(btScalar(0.020833333333))*fAngle*fAngle ); + } + else + { + // sync(fAngle) = sin(c*fAngle)/t + axis = angvel*( btSin(btScalar(0.5)*fAngle*timeStep)/fAngle ); + } + btQuaternion dorn (axis.x(),axis.y(),axis.z(),btCos( fAngle*timeStep*btScalar(0.5) )); + btQuaternion orn0 = curTrans.getRotation(); + + btQuaternion predictedOrn = dorn * orn0; + predictedOrn.normalize(); + #endif + predictedTransform.setRotation(predictedOrn); + } + + static void calculateVelocityQuaternion(const btVector3& pos0,const btVector3& pos1,const btQuaternion& orn0,const btQuaternion& orn1,btScalar timeStep,btVector3& linVel,btVector3& angVel) + { + linVel = (pos1 - pos0) / timeStep; + btVector3 axis; + btScalar angle; + if (orn0 != orn1) + { + calculateDiffAxisAngleQuaternion(orn0,orn1,axis,angle); + angVel = axis * angle / timeStep; + } else + { + angVel.setValue(0,0,0); + } + } + + static void calculateDiffAxisAngleQuaternion(const btQuaternion& orn0,const btQuaternion& orn1a,btVector3& axis,btScalar& angle) + { + btQuaternion orn1 = orn0.nearest(orn1a); + btQuaternion dorn = orn1 * orn0.inverse(); + angle = dorn.getAngle(); + axis = btVector3(dorn.x(),dorn.y(),dorn.z()); + axis[3] = btScalar(0.); + //check for axis length + btScalar len = axis.length2(); + if (len < SIMD_EPSILON*SIMD_EPSILON) + axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.)); + else + axis /= btSqrt(len); + } + + static void calculateVelocity(const btTransform& transform0,const btTransform& transform1,btScalar timeStep,btVector3& linVel,btVector3& angVel) + { + linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep; + btVector3 axis; + btScalar angle; + calculateDiffAxisAngle(transform0,transform1,axis,angle); + angVel = axis * angle / timeStep; + } + + static void calculateDiffAxisAngle(const btTransform& transform0,const btTransform& transform1,btVector3& axis,btScalar& angle) + { + btMatrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse(); + btQuaternion dorn; + dmat.getRotation(dorn); + + ///floating point inaccuracy can lead to w component > 1..., which breaks + dorn.normalize(); + + angle = dorn.getAngle(); + axis = btVector3(dorn.x(),dorn.y(),dorn.z()); + axis[3] = btScalar(0.); + //check for axis length + btScalar len = axis.length2(); + if (len < SIMD_EPSILON*SIMD_EPSILON) + axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.)); + else + axis /= btSqrt(len); + } + +}; + + +///The btConvexSeparatingDistanceUtil can help speed up convex collision detection +///by conservatively updating a cached separating distance/vector instead of re-calculating the closest distance +class btConvexSeparatingDistanceUtil +{ + btQuaternion m_ornA; + btQuaternion m_ornB; + btVector3 m_posA; + btVector3 m_posB; + + btVector3 m_separatingNormal; + + btScalar m_boundingRadiusA; + btScalar m_boundingRadiusB; + btScalar m_separatingDistance; + +public: + + btConvexSeparatingDistanceUtil(btScalar boundingRadiusA,btScalar boundingRadiusB) + :m_boundingRadiusA(boundingRadiusA), + m_boundingRadiusB(boundingRadiusB), + m_separatingDistance(0.f) + { + } + + btScalar getConservativeSeparatingDistance() + { + return m_separatingDistance; + } + + void updateSeparatingDistance(const btTransform& transA,const btTransform& transB) + { + const btVector3& toPosA = transA.getOrigin(); + const btVector3& toPosB = transB.getOrigin(); + btQuaternion toOrnA = transA.getRotation(); + btQuaternion toOrnB = transB.getRotation(); + + if (m_separatingDistance>0.f) + { + + + btVector3 linVelA,angVelA,linVelB,angVelB; + btTransformUtil::calculateVelocityQuaternion(m_posA,toPosA,m_ornA,toOrnA,btScalar(1.),linVelA,angVelA); + btTransformUtil::calculateVelocityQuaternion(m_posB,toPosB,m_ornB,toOrnB,btScalar(1.),linVelB,angVelB); + btScalar maxAngularProjectedVelocity = angVelA.length() * m_boundingRadiusA + angVelB.length() * m_boundingRadiusB; + btVector3 relLinVel = (linVelB-linVelA); + btScalar relLinVelocLength = relLinVel.dot(m_separatingNormal); + if (relLinVelocLength<0.f) + { + relLinVelocLength = 0.f; + } + + btScalar projectedMotion = maxAngularProjectedVelocity +relLinVelocLength; + m_separatingDistance -= projectedMotion; + } + + m_posA = toPosA; + m_posB = toPosB; + m_ornA = toOrnA; + m_ornB = toOrnB; + } + + void initSeparatingDistance(const btVector3& separatingVector,btScalar separatingDistance,const btTransform& transA,const btTransform& transB) + { + m_separatingDistance = separatingDistance; + + if (m_separatingDistance>0.f) + { + m_separatingNormal = separatingVector; + + const btVector3& toPosA = transA.getOrigin(); + const btVector3& toPosB = transB.getOrigin(); + btQuaternion toOrnA = transA.getRotation(); + btQuaternion toOrnB = transB.getRotation(); + m_posA = toPosA; + m_posB = toPosB; + m_ornA = toOrnA; + m_ornB = toOrnB; + } + } + +}; + + +#endif //BT_TRANSFORM_UTIL_H + diff --git a/src/LinearMath/btVector3.h b/src/LinearMath/btVector3.h new file mode 100644 index 0000000..d99b7c8 --- /dev/null +++ b/src/LinearMath/btVector3.h @@ -0,0 +1,766 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_VECTOR3_H +#define BT_VECTOR3_H + + +#include "btScalar.h" +#include "btMinMax.h" + +#ifdef BT_USE_DOUBLE_PRECISION +#define btVector3Data btVector3DoubleData +#define btVector3DataName "btVector3DoubleData" +#else +#define btVector3Data btVector3FloatData +#define btVector3DataName "btVector3FloatData" +#endif //BT_USE_DOUBLE_PRECISION + + + + +/**@brief btVector3 can be used to represent 3D points and vectors. + * It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user + * Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers + */ +ATTRIBUTE_ALIGNED16(class) btVector3 +{ +public: + +#if defined (__SPU__) && defined (__CELLOS_LV2__) + btScalar m_floats[4]; +public: + SIMD_FORCE_INLINE const vec_float4& get128() const + { + return *((const vec_float4*)&m_floats[0]); + } +public: +#else //__CELLOS_LV2__ __SPU__ +#ifdef BT_USE_SSE // _WIN32 + union { + __m128 mVec128; + btScalar m_floats[4]; + }; + SIMD_FORCE_INLINE __m128 get128() const + { + return mVec128; + } + SIMD_FORCE_INLINE void set128(__m128 v128) + { + mVec128 = v128; + } +#else + btScalar m_floats[4]; +#endif +#endif //__CELLOS_LV2__ __SPU__ + + public: + + /**@brief No initialization constructor */ + SIMD_FORCE_INLINE btVector3() {} + + + + /**@brief Constructor from scalars + * @param x X value + * @param y Y value + * @param z Z value + */ + SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z) + { + m_floats[0] = x; + m_floats[1] = y; + m_floats[2] = z; + m_floats[3] = btScalar(0.); + } + + +/**@brief Add a vector to this one + * @param The vector to add to this one */ + SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v) + { + + m_floats[0] += v.m_floats[0]; m_floats[1] += v.m_floats[1];m_floats[2] += v.m_floats[2]; + return *this; + } + + + /**@brief Subtract a vector from this one + * @param The vector to subtract */ + SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v) + { + m_floats[0] -= v.m_floats[0]; m_floats[1] -= v.m_floats[1];m_floats[2] -= v.m_floats[2]; + return *this; + } + /**@brief Scale the vector + * @param s Scale factor */ + SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s) + { + m_floats[0] *= s; m_floats[1] *= s;m_floats[2] *= s; + return *this; + } + + /**@brief Inversely scale the vector + * @param s Scale factor to divide by */ + SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s) + { + btFullAssert(s != btScalar(0.0)); + return *this *= btScalar(1.0) / s; + } + + /**@brief Return the dot product + * @param v The other vector in the dot product */ + SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const + { + return m_floats[0] * v.m_floats[0] + m_floats[1] * v.m_floats[1] +m_floats[2] * v.m_floats[2]; + } + + /**@brief Return the length of the vector squared */ + SIMD_FORCE_INLINE btScalar length2() const + { + return dot(*this); + } + + /**@brief Return the length of the vector */ + SIMD_FORCE_INLINE btScalar length() const + { + return btSqrt(length2()); + } + + /**@brief Return the distance squared between the ends of this and another vector + * This is symantically treating the vector like a point */ + SIMD_FORCE_INLINE btScalar distance2(const btVector3& v) const; + + /**@brief Return the distance between the ends of this and another vector + * This is symantically treating the vector like a point */ + SIMD_FORCE_INLINE btScalar distance(const btVector3& v) const; + + SIMD_FORCE_INLINE btVector3& safeNormalize() + { + btVector3 absVec = this->absolute(); + int maxIndex = absVec.maxAxis(); + if (absVec[maxIndex]>0) + { + *this /= absVec[maxIndex]; + return *this /= length(); + } + setValue(1,0,0); + return *this; + } + + /**@brief Normalize this vector + * x^2 + y^2 + z^2 = 1 */ + SIMD_FORCE_INLINE btVector3& normalize() + { + return *this /= length(); + } + + /**@brief Return a normalized version of this vector */ + SIMD_FORCE_INLINE btVector3 normalized() const; + + /**@brief Return a rotated version of this vector + * @param wAxis The axis to rotate about + * @param angle The angle to rotate by */ + SIMD_FORCE_INLINE btVector3 rotate( const btVector3& wAxis, const btScalar angle ) const; + + /**@brief Return the angle between this and another vector + * @param v The other vector */ + SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const + { + btScalar s = btSqrt(length2() * v.length2()); + btFullAssert(s != btScalar(0.0)); + return btAcos(dot(v) / s); + } + /**@brief Return a vector will the absolute values of each element */ + SIMD_FORCE_INLINE btVector3 absolute() const + { + return btVector3( + btFabs(m_floats[0]), + btFabs(m_floats[1]), + btFabs(m_floats[2])); + } + /**@brief Return the cross product between this and another vector + * @param v The other vector */ + SIMD_FORCE_INLINE btVector3 cross(const btVector3& v) const + { + return btVector3( + m_floats[1] * v.m_floats[2] -m_floats[2] * v.m_floats[1], + m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2], + m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]); + } + + SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const + { + return m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) + + m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) + + m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]); + } + + /**@brief Return the axis with the smallest value + * Note return values are 0,1,2 for x, y, or z */ + SIMD_FORCE_INLINE int minAxis() const + { + return m_floats[0] < m_floats[1] ? (m_floats[0] return this, t=1 => return other) */ + SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const + { + return btVector3(m_floats[0] + (v.m_floats[0] - m_floats[0]) * t, + m_floats[1] + (v.m_floats[1] - m_floats[1]) * t, + m_floats[2] + (v.m_floats[2] -m_floats[2]) * t); + } + + /**@brief Elementwise multiply this vector by the other + * @param v The other vector */ + SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v) + { + m_floats[0] *= v.m_floats[0]; m_floats[1] *= v.m_floats[1];m_floats[2] *= v.m_floats[2]; + return *this; + } + + /**@brief Return the x value */ + SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; } + /**@brief Return the y value */ + SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; } + /**@brief Return the z value */ + SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; } + /**@brief Set the x value */ + SIMD_FORCE_INLINE void setX(btScalar x) { m_floats[0] = x;}; + /**@brief Set the y value */ + SIMD_FORCE_INLINE void setY(btScalar y) { m_floats[1] = y;}; + /**@brief Set the z value */ + SIMD_FORCE_INLINE void setZ(btScalar z) {m_floats[2] = z;}; + /**@brief Set the w value */ + SIMD_FORCE_INLINE void setW(btScalar w) { m_floats[3] = w;}; + /**@brief Return the x value */ + SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; } + /**@brief Return the y value */ + SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; } + /**@brief Return the z value */ + SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; } + /**@brief Return the w value */ + SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; } + + //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; } + //SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; } + ///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons. + SIMD_FORCE_INLINE operator btScalar *() { return &m_floats[0]; } + SIMD_FORCE_INLINE operator const btScalar *() const { return &m_floats[0]; } + + SIMD_FORCE_INLINE bool operator==(const btVector3& other) const + { + return ((m_floats[3]==other.m_floats[3]) && (m_floats[2]==other.m_floats[2]) && (m_floats[1]==other.m_floats[1]) && (m_floats[0]==other.m_floats[0])); + } + + SIMD_FORCE_INLINE bool operator!=(const btVector3& other) const + { + return !(*this == other); + } + + /**@brief Set each element to the max of the current values and the values of another btVector3 + * @param other The other btVector3 to compare with + */ + SIMD_FORCE_INLINE void setMax(const btVector3& other) + { + btSetMax(m_floats[0], other.m_floats[0]); + btSetMax(m_floats[1], other.m_floats[1]); + btSetMax(m_floats[2], other.m_floats[2]); + btSetMax(m_floats[3], other.w()); + } + /**@brief Set each element to the min of the current values and the values of another btVector3 + * @param other The other btVector3 to compare with + */ + SIMD_FORCE_INLINE void setMin(const btVector3& other) + { + btSetMin(m_floats[0], other.m_floats[0]); + btSetMin(m_floats[1], other.m_floats[1]); + btSetMin(m_floats[2], other.m_floats[2]); + btSetMin(m_floats[3], other.w()); + } + + SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z) + { + m_floats[0]=x; + m_floats[1]=y; + m_floats[2]=z; + m_floats[3] = btScalar(0.); + } + + void getSkewSymmetricMatrix(btVector3* v0,btVector3* v1,btVector3* v2) const + { + v0->setValue(0. ,-z() ,y()); + v1->setValue(z() ,0. ,-x()); + v2->setValue(-y() ,x() ,0.); + } + + void setZero() + { + setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + + SIMD_FORCE_INLINE bool isZero() const + { + return m_floats[0] == btScalar(0) && m_floats[1] == btScalar(0) && m_floats[2] == btScalar(0); + } + + SIMD_FORCE_INLINE bool fuzzyZero() const + { + return length2() < SIMD_EPSILON; + } + + SIMD_FORCE_INLINE void serialize(struct btVector3Data& dataOut) const; + + SIMD_FORCE_INLINE void deSerialize(const struct btVector3Data& dataIn); + + SIMD_FORCE_INLINE void serializeFloat(struct btVector3FloatData& dataOut) const; + + SIMD_FORCE_INLINE void deSerializeFloat(const struct btVector3FloatData& dataIn); + + SIMD_FORCE_INLINE void serializeDouble(struct btVector3DoubleData& dataOut) const; + + SIMD_FORCE_INLINE void deSerializeDouble(const struct btVector3DoubleData& dataIn); + +}; + +/**@brief Return the sum of two vectors (Point symantics)*/ +SIMD_FORCE_INLINE btVector3 +operator+(const btVector3& v1, const btVector3& v2) +{ + return btVector3(v1.m_floats[0] + v2.m_floats[0], v1.m_floats[1] + v2.m_floats[1], v1.m_floats[2] + v2.m_floats[2]); +} + +/**@brief Return the elementwise product of two vectors */ +SIMD_FORCE_INLINE btVector3 +operator*(const btVector3& v1, const btVector3& v2) +{ + return btVector3(v1.m_floats[0] * v2.m_floats[0], v1.m_floats[1] * v2.m_floats[1], v1.m_floats[2] * v2.m_floats[2]); +} + +/**@brief Return the difference between two vectors */ +SIMD_FORCE_INLINE btVector3 +operator-(const btVector3& v1, const btVector3& v2) +{ + return btVector3(v1.m_floats[0] - v2.m_floats[0], v1.m_floats[1] - v2.m_floats[1], v1.m_floats[2] - v2.m_floats[2]); +} +/**@brief Return the negative of the vector */ +SIMD_FORCE_INLINE btVector3 +operator-(const btVector3& v) +{ + return btVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]); +} + +/**@brief Return the vector scaled by s */ +SIMD_FORCE_INLINE btVector3 +operator*(const btVector3& v, const btScalar& s) +{ + return btVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s); +} + +/**@brief Return the vector scaled by s */ +SIMD_FORCE_INLINE btVector3 +operator*(const btScalar& s, const btVector3& v) +{ + return v * s; +} + +/**@brief Return the vector inversely scaled by s */ +SIMD_FORCE_INLINE btVector3 +operator/(const btVector3& v, const btScalar& s) +{ + btFullAssert(s != btScalar(0.0)); + return v * (btScalar(1.0) / s); +} + +/**@brief Return the vector inversely scaled by s */ +SIMD_FORCE_INLINE btVector3 +operator/(const btVector3& v1, const btVector3& v2) +{ + return btVector3(v1.m_floats[0] / v2.m_floats[0],v1.m_floats[1] / v2.m_floats[1],v1.m_floats[2] / v2.m_floats[2]); +} + +/**@brief Return the dot product between two vectors */ +SIMD_FORCE_INLINE btScalar +btDot(const btVector3& v1, const btVector3& v2) +{ + return v1.dot(v2); +} + + +/**@brief Return the distance squared between two vectors */ +SIMD_FORCE_INLINE btScalar +btDistance2(const btVector3& v1, const btVector3& v2) +{ + return v1.distance2(v2); +} + + +/**@brief Return the distance between two vectors */ +SIMD_FORCE_INLINE btScalar +btDistance(const btVector3& v1, const btVector3& v2) +{ + return v1.distance(v2); +} + +/**@brief Return the angle between two vectors */ +SIMD_FORCE_INLINE btScalar +btAngle(const btVector3& v1, const btVector3& v2) +{ + return v1.angle(v2); +} + +/**@brief Return the cross product of two vectors */ +SIMD_FORCE_INLINE btVector3 +btCross(const btVector3& v1, const btVector3& v2) +{ + return v1.cross(v2); +} + +SIMD_FORCE_INLINE btScalar +btTriple(const btVector3& v1, const btVector3& v2, const btVector3& v3) +{ + return v1.triple(v2, v3); +} + +/**@brief Return the linear interpolation between two vectors + * @param v1 One vector + * @param v2 The other vector + * @param t The ration of this to v (t = 0 => return v1, t=1 => return v2) */ +SIMD_FORCE_INLINE btVector3 +lerp(const btVector3& v1, const btVector3& v2, const btScalar& t) +{ + return v1.lerp(v2, t); +} + + + +SIMD_FORCE_INLINE btScalar btVector3::distance2(const btVector3& v) const +{ + return (v - *this).length2(); +} + +SIMD_FORCE_INLINE btScalar btVector3::distance(const btVector3& v) const +{ + return (v - *this).length(); +} + +SIMD_FORCE_INLINE btVector3 btVector3::normalized() const +{ + return *this / length(); +} + +SIMD_FORCE_INLINE btVector3 btVector3::rotate( const btVector3& wAxis, const btScalar angle ) const +{ + // wAxis must be a unit lenght vector + + btVector3 o = wAxis * wAxis.dot( *this ); + btVector3 x = *this - o; + btVector3 y; + + y = wAxis.cross( *this ); + + return ( o + x * btCos( angle ) + y * btSin( angle ) ); +} + +class btVector4 : public btVector3 +{ +public: + + SIMD_FORCE_INLINE btVector4() {} + + + SIMD_FORCE_INLINE btVector4(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) + : btVector3(x,y,z) + { + m_floats[3] = w; + } + + + SIMD_FORCE_INLINE btVector4 absolute4() const + { + return btVector4( + btFabs(m_floats[0]), + btFabs(m_floats[1]), + btFabs(m_floats[2]), + btFabs(m_floats[3])); + } + + + + btScalar getW() const { return m_floats[3];} + + + SIMD_FORCE_INLINE int maxAxis4() const + { + int maxIndex = -1; + btScalar maxVal = btScalar(-BT_LARGE_FLOAT); + if (m_floats[0] > maxVal) + { + maxIndex = 0; + maxVal = m_floats[0]; + } + if (m_floats[1] > maxVal) + { + maxIndex = 1; + maxVal = m_floats[1]; + } + if (m_floats[2] > maxVal) + { + maxIndex = 2; + maxVal =m_floats[2]; + } + if (m_floats[3] > maxVal) + { + maxIndex = 3; + maxVal = m_floats[3]; + } + + + + + return maxIndex; + + } + + + SIMD_FORCE_INLINE int minAxis4() const + { + int minIndex = -1; + btScalar minVal = btScalar(BT_LARGE_FLOAT); + if (m_floats[0] < minVal) + { + minIndex = 0; + minVal = m_floats[0]; + } + if (m_floats[1] < minVal) + { + minIndex = 1; + minVal = m_floats[1]; + } + if (m_floats[2] < minVal) + { + minIndex = 2; + minVal =m_floats[2]; + } + if (m_floats[3] < minVal) + { + minIndex = 3; + minVal = m_floats[3]; + } + + return minIndex; + + } + + + SIMD_FORCE_INLINE int closestAxis4() const + { + return absolute4().maxAxis4(); + } + + + + + /**@brief Set x,y,z and zero w + * @param x Value of x + * @param y Value of y + * @param z Value of z + */ + + +/* void getValue(btScalar *m) const + { + m[0] = m_floats[0]; + m[1] = m_floats[1]; + m[2] =m_floats[2]; + } +*/ +/**@brief Set the values + * @param x Value of x + * @param y Value of y + * @param z Value of z + * @param w Value of w + */ + SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) + { + m_floats[0]=x; + m_floats[1]=y; + m_floats[2]=z; + m_floats[3]=w; + } + + +}; + + +///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization +SIMD_FORCE_INLINE void btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal) +{ + #ifdef BT_USE_DOUBLE_PRECISION + unsigned char* dest = (unsigned char*) &destVal; + unsigned char* src = (unsigned char*) &sourceVal; + dest[0] = src[7]; + dest[1] = src[6]; + dest[2] = src[5]; + dest[3] = src[4]; + dest[4] = src[3]; + dest[5] = src[2]; + dest[6] = src[1]; + dest[7] = src[0]; +#else + unsigned char* dest = (unsigned char*) &destVal; + unsigned char* src = (unsigned char*) &sourceVal; + dest[0] = src[3]; + dest[1] = src[2]; + dest[2] = src[1]; + dest[3] = src[0]; +#endif //BT_USE_DOUBLE_PRECISION +} +///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization +SIMD_FORCE_INLINE void btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec) +{ + for (int i=0;i<4;i++) + { + btSwapScalarEndian(sourceVec[i],destVec[i]); + } + +} + +///btUnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization +SIMD_FORCE_INLINE void btUnSwapVector3Endian(btVector3& vector) +{ + + btVector3 swappedVec; + for (int i=0;i<4;i++) + { + btSwapScalarEndian(vector[i],swappedVec[i]); + } + vector = swappedVec; +} + +template +SIMD_FORCE_INLINE void btPlaneSpace1 (const T& n, T& p, T& q) +{ + if (btFabs(n[2]) > SIMDSQRT12) { + // choose p in y-z plane + btScalar a = n[1]*n[1] + n[2]*n[2]; + btScalar k = btRecipSqrt (a); + p[0] = 0; + p[1] = -n[2]*k; + p[2] = n[1]*k; + // set q = n x p + q[0] = a*k; + q[1] = -n[0]*p[2]; + q[2] = n[0]*p[1]; + } + else { + // choose p in x-y plane + btScalar a = n[0]*n[0] + n[1]*n[1]; + btScalar k = btRecipSqrt (a); + p[0] = -n[1]*k; + p[1] = n[0]*k; + p[2] = 0; + // set q = n x p + q[0] = -n[2]*p[1]; + q[1] = n[2]*p[0]; + q[2] = a*k; + } +} + + +struct btVector3FloatData +{ + float m_floats[4]; +}; + +struct btVector3DoubleData +{ + double m_floats[4]; + +}; + +SIMD_FORCE_INLINE void btVector3::serializeFloat(struct btVector3FloatData& dataOut) const +{ + ///could also do a memcpy, check if it is worth it + for (int i=0;i<4;i++) + dataOut.m_floats[i] = float(m_floats[i]); +} + +SIMD_FORCE_INLINE void btVector3::deSerializeFloat(const struct btVector3FloatData& dataIn) +{ + for (int i=0;i<4;i++) + m_floats[i] = btScalar(dataIn.m_floats[i]); +} + + +SIMD_FORCE_INLINE void btVector3::serializeDouble(struct btVector3DoubleData& dataOut) const +{ + ///could also do a memcpy, check if it is worth it + for (int i=0;i<4;i++) + dataOut.m_floats[i] = double(m_floats[i]); +} + +SIMD_FORCE_INLINE void btVector3::deSerializeDouble(const struct btVector3DoubleData& dataIn) +{ + for (int i=0;i<4;i++) + m_floats[i] = btScalar(dataIn.m_floats[i]); +} + + +SIMD_FORCE_INLINE void btVector3::serialize(struct btVector3Data& dataOut) const +{ + ///could also do a memcpy, check if it is worth it + for (int i=0;i<4;i++) + dataOut.m_floats[i] = m_floats[i]; +} + +SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3Data& dataIn) +{ + for (int i=0;i<4;i++) + m_floats[i] = dataIn.m_floats[i]; +} + + +#endif //BT_VECTOR3_H diff --git a/src/LinearMath/ibmsdk/Makefile b/src/LinearMath/ibmsdk/Makefile new file mode 100644 index 0000000..0414873 --- /dev/null +++ b/src/LinearMath/ibmsdk/Makefile @@ -0,0 +1,39 @@ +#### Source code Dirs +VPATH = ../ + +ROOT = ../../.. + +#### Library +LIBRARY_ppu = bulletmath.a + +#### Compiler flags +CPPFLAGS = \ +-DUSE_LIBSPE2 \ +-I$(ROOT)/src \ +-I$(SDKINC) + +#### Optimization level flags +#CC_OPT_LEVEL = $(CC_OPT_LEVEL_DEBUG) +CC_OPT_LEVEL = -O3 + +##### Objects to be archived in lib + +OBJS = \ +btAlignedAllocator.o \ +btGeometryUtil.o \ +btQuickprof.o + +#### Install directories +INSTALL_DIR = $(ROOT)/lib/ibmsdk +INSTALL_FILES = $(LIBRARY_ppu) + +IBM_CELLSDK_VERSION := $(shell if [ -d /opt/cell ]; then echo "3.0"; fi) + +ifeq ("$(IBM_CELLSDK_VERSION)","3.0") + CELL_TOP ?= /opt/cell/sdk + include $(CELL_TOP)/buildutils/make.footer +else + CELL_TOP ?= /opt/ibm/cell-sdk/prototype + include $(CELL_TOP)/make.footer +endif + diff --git a/src/LinearMath/premake4.lua b/src/LinearMath/premake4.lua new file mode 100644 index 0000000..b698bed --- /dev/null +++ b/src/LinearMath/premake4.lua @@ -0,0 +1,11 @@ + project "LinearMath" + + kind "StaticLib" + targetdir "../../lib" + includedirs { + "..", + } + files { + "**.cpp", + "**.h" + } \ No newline at end of file diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..1042202 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,554 @@ +bullet_includedir = $(includedir)/bullet +nobase_bullet_include_HEADERS = \ + btBulletDynamicsCommon.h \ + Bullet-C-Api.h \ + btBulletCollisionCommon.h + +if CONDITIONAL_BUILD_MULTITHREADED +nobase_bullet_include_HEADERS += \ + BulletMultiThreaded/PosixThreadSupport.h \ + BulletMultiThreaded/vectormath/scalar/cpp/mat_aos.h \ + BulletMultiThreaded/vectormath/scalar/cpp/vec_aos.h \ + BulletMultiThreaded/vectormath/scalar/cpp/quat_aos.h \ + BulletMultiThreaded/vectormath/scalar/cpp/vectormath_aos.h \ + BulletMultiThreaded/PpuAddressSpace.h \ + BulletMultiThreaded/SpuCollisionTaskProcess.h \ + BulletMultiThreaded/PlatformDefinitions.h \ + BulletMultiThreaded/vectormath2bullet.h \ + BulletMultiThreaded/SpuGatheringCollisionDispatcher.h \ + BulletMultiThreaded/SpuCollisionObjectWrapper.h \ + BulletMultiThreaded/SpuSampleTaskProcess.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h \ + BulletMultiThreaded/SpuSync.h \ + BulletMultiThreaded/btThreadSupportInterface.h \ + BulletMultiThreaded/SpuLibspe2Support.h \ + BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h \ + BulletMultiThreaded/SpuFakeDma.h \ + BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h \ + BulletMultiThreaded/SpuDoubleBuffer.h \ + BulletMultiThreaded/Win32ThreadSupport.h \ + BulletMultiThreaded/SequentialThreadSupport.h + +lib_LTLIBRARIES = libLinearMath.la libBulletCollision.la libBulletDynamics.la libBulletSoftBody.la libBulletMultiThreaded.la + +libBulletMultiThreaded_la_CXXFLAGS = ${CXXFLAGS} -I./BulletMultiThreaded/vectormath/scalar/cpp +libBulletMultiThreaded_la_SOURCES =\ + BulletMultiThreaded/SpuCollisionObjectWrapper.cpp \ + BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp \ + BulletMultiThreaded/SpuLibspe2Support.cpp \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp \ + BulletMultiThreaded/btThreadSupportInterface.cpp \ + BulletMultiThreaded/SequentialThreadSupport.cpp \ + BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp \ + BulletMultiThreaded/Win32ThreadSupport.cpp \ + BulletMultiThreaded/SpuFakeDma.cpp \ + BulletMultiThreaded/PosixThreadSupport.cpp \ + BulletMultiThreaded/SpuCollisionTaskProcess.cpp \ + BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp \ + BulletMultiThreaded/SpuSampleTaskProcess.cpp \ + BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h \ + BulletMultiThreaded/PpuAddressSpace.h \ + BulletMultiThreaded/SpuSampleTaskProcess.h \ + BulletMultiThreaded/SequentialThreadSupport.h \ + BulletMultiThreaded/PlatformDefinitions.h \ + BulletMultiThreaded/Win32ThreadSupport.h \ + BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h \ + BulletMultiThreaded/btThreadSupportInterface.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h \ + BulletMultiThreaded/SpuGatheringCollisionDispatcher.h \ + BulletMultiThreaded/SpuFakeDma.h \ + BulletMultiThreaded/SpuSync.h \ + BulletMultiThreaded/SpuCollisionObjectWrapper.h \ + BulletMultiThreaded/SpuDoubleBuffer.h \ + BulletMultiThreaded/SpuCollisionTaskProcess.h \ + BulletMultiThreaded/PosixThreadSupport.h \ + BulletMultiThreaded/SpuLibspe2Support.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h + +else +lib_LTLIBRARIES = libLinearMath.la libBulletCollision.la libBulletDynamics.la libBulletSoftBody.la +endif + + +libLinearMath_la_SOURCES = \ + LinearMath/btQuickprof.cpp \ + LinearMath/btGeometryUtil.cpp \ + LinearMath/btAlignedAllocator.cpp \ + LinearMath/btSerializer.cpp \ + LinearMath/btConvexHull.cpp \ + LinearMath/btConvexHullComputer.cpp \ + LinearMath/btHashMap.h \ + LinearMath/btConvexHull.h \ + LinearMath/btAabbUtil2.h \ + LinearMath/btGeometryUtil.h \ + LinearMath/btQuadWord.h \ + LinearMath/btPoolAllocator.h \ + LinearMath/btScalar.h \ + LinearMath/btMinMax.h \ + LinearMath/btVector3.h \ + LinearMath/btList.h \ + LinearMath/btStackAlloc.h \ + LinearMath/btMatrix3x3.h \ + LinearMath/btMotionState.h \ + LinearMath/btAlignedAllocator.h \ + LinearMath/btQuaternion.h \ + LinearMath/btAlignedObjectArray.h \ + LinearMath/btQuickprof.h \ + LinearMath/btSerializer.h \ + LinearMath/btTransformUtil.h \ + LinearMath/btTransform.h \ + LinearMath/btDefaultMotionState.h \ + LinearMath/btIDebugDraw.h \ + LinearMath/btRandom.h + + +libBulletCollision_la_SOURCES = \ + BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp \ + BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp \ + BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp \ + BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp \ + BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp \ + BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp \ + BulletCollision/NarrowPhaseCollision/btConvexCast.cpp \ + BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp \ + BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp \ + BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp \ + BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp \ + BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp \ + BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btCollisionObject.cpp \ + BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btGhostObject.cpp \ + BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp \ + BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp \ + BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp \ + BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp \ + BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp \ + BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp \ + BulletCollision/CollisionDispatch/btManifoldResult.cpp \ + BulletCollision/CollisionDispatch/btCollisionWorld.cpp \ + BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btUnionFind.cpp \ + BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp \ + BulletCollision/CollisionShapes/btTetrahedronShape.cpp \ + BulletCollision/CollisionShapes/btShapeHull.cpp \ + BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp \ + BulletCollision/CollisionShapes/btCompoundShape.cpp \ + BulletCollision/CollisionShapes/btConeShape.cpp \ + BulletCollision/CollisionShapes/btConvexPolyhedron.cpp \ + BulletCollision/CollisionShapes/btMultiSphereShape.cpp \ + BulletCollision/CollisionShapes/btUniformScalingShape.cpp \ + BulletCollision/CollisionShapes/btSphereShape.cpp \ + BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp \ + BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp \ + BulletCollision/CollisionShapes/btTriangleMeshShape.cpp \ + BulletCollision/CollisionShapes/btTriangleBuffer.cpp \ + BulletCollision/CollisionShapes/btStaticPlaneShape.cpp \ + BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp \ + BulletCollision/CollisionShapes/btEmptyShape.cpp \ + BulletCollision/CollisionShapes/btCollisionShape.cpp \ + BulletCollision/CollisionShapes/btConvexShape.cpp \ + BulletCollision/CollisionShapes/btConvex2dShape.cpp \ + BulletCollision/CollisionShapes/btConvexInternalShape.cpp \ + BulletCollision/CollisionShapes/btConvexHullShape.cpp \ + BulletCollision/CollisionShapes/btTriangleCallback.cpp \ + BulletCollision/CollisionShapes/btCapsuleShape.cpp \ + BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp \ + BulletCollision/CollisionShapes/btConcaveShape.cpp \ + BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp \ + BulletCollision/CollisionShapes/btBoxShape.cpp \ + BulletCollision/CollisionShapes/btBox2dShape.cpp \ + BulletCollision/CollisionShapes/btOptimizedBvh.cpp \ + BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp \ + BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp \ + BulletCollision/CollisionShapes/btCylinderShape.cpp \ + BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp \ + BulletCollision/CollisionShapes/btStridingMeshInterface.cpp \ + BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp \ + BulletCollision/CollisionShapes/btTriangleMesh.cpp \ + BulletCollision/BroadphaseCollision/btAxisSweep3.cpp \ + BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp \ + BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp \ + BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp \ + BulletCollision/BroadphaseCollision/btDispatcher.cpp \ + BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp \ + BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp \ + BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp \ + BulletCollision/BroadphaseCollision/btDbvt.cpp \ + BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp \ + BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h \ + BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h \ + BulletCollision/NarrowPhaseCollision/btConvexCast.h \ + BulletCollision/NarrowPhaseCollision/btGjkEpa2.h \ + BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h \ + BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h \ + BulletCollision/NarrowPhaseCollision/btPointCollector.h \ + BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h \ + BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h \ + BulletCollision/NarrowPhaseCollision/btRaycastCallback.h \ + BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h \ + BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h \ + BulletCollision/NarrowPhaseCollision/btPersistentManifold.h \ + BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h \ + BulletCollision/NarrowPhaseCollision/btManifoldPoint.h \ + BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h \ + BulletCollision/CollisionDispatch/btCollisionObject.h \ + BulletCollision/CollisionDispatch/btGhostObject.h \ + BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btCollisionCreateFunc.h \ + BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h \ + BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h \ + BulletCollision/CollisionDispatch/btBoxBoxDetector.h \ + BulletCollision/CollisionDispatch/btCollisionDispatcher.h \ + BulletCollision/CollisionDispatch/SphereTriangleDetector.h \ + BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btUnionFind.h \ + BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btSimulationIslandManager.h \ + BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h \ + BulletCollision/CollisionDispatch/btCollisionWorld.h \ + BulletCollision/CollisionDispatch/btInternalEdgeUtility.h \ + BulletCollision/CollisionDispatch/btManifoldResult.h \ + BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btCollisionConfiguration.h \ + BulletCollision/CollisionShapes/btConvexShape.h \ + BulletCollision/CollisionShapes/btConvex2dShape.h \ + BulletCollision/CollisionShapes/btTriangleCallback.h \ + BulletCollision/CollisionShapes/btPolyhedralConvexShape.h \ + BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btCompoundShape.h \ + BulletCollision/CollisionShapes/btBoxShape.h \ + BulletCollision/CollisionShapes/btBox2dShape.h \ + BulletCollision/CollisionShapes/btMultiSphereShape.h \ + BulletCollision/CollisionShapes/btCollisionMargin.h \ + BulletCollision/CollisionShapes/btConcaveShape.h \ + BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btEmptyShape.h \ + BulletCollision/CollisionShapes/btUniformScalingShape.h \ + BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btMaterial.h \ + BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h \ + BulletCollision/CollisionShapes/btTriangleInfoMap.h \ + BulletCollision/CollisionShapes/btSphereShape.h \ + BulletCollision/CollisionShapes/btConvexPointCloudShape.h \ + BulletCollision/CollisionShapes/btCapsuleShape.h \ + BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h \ + BulletCollision/CollisionShapes/btCollisionShape.h \ + BulletCollision/CollisionShapes/btStaticPlaneShape.h \ + BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btStridingMeshInterface.h \ + BulletCollision/CollisionShapes/btTriangleMesh.h \ + BulletCollision/CollisionShapes/btTriangleBuffer.h \ + BulletCollision/CollisionShapes/btShapeHull.h \ + BulletCollision/CollisionShapes/btMinkowskiSumShape.h \ + BulletCollision/CollisionShapes/btOptimizedBvh.h \ + BulletCollision/CollisionShapes/btTriangleShape.h \ + BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h \ + BulletCollision/CollisionShapes/btCylinderShape.h \ + BulletCollision/CollisionShapes/btTetrahedronShape.h \ + BulletCollision/CollisionShapes/btConvexInternalShape.h \ + BulletCollision/CollisionShapes/btConeShape.h \ + BulletCollision/CollisionShapes/btConvexHullShape.h \ + BulletCollision/BroadphaseCollision/btAxisSweep3.h \ + BulletCollision/BroadphaseCollision/btDbvtBroadphase.h \ + BulletCollision/BroadphaseCollision/btSimpleBroadphase.h \ + BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h \ + BulletCollision/BroadphaseCollision/btDbvt.h \ + BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h \ + BulletCollision/BroadphaseCollision/btDispatcher.h \ + BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h \ + BulletCollision/BroadphaseCollision/btBroadphaseProxy.h \ + BulletCollision/BroadphaseCollision/btOverlappingPairCache.h \ + BulletCollision/BroadphaseCollision/btBroadphaseInterface.h \ + BulletCollision/BroadphaseCollision/btQuantizedBvh.h \ + BulletCollision/Gimpact/btGImpactBvh.cpp\ + BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp\ + BulletCollision/Gimpact/btTriangleShapeEx.cpp\ + BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp\ + BulletCollision/Gimpact/btGImpactShape.cpp\ + BulletCollision/Gimpact/gim_box_set.cpp\ + BulletCollision/Gimpact/gim_contact.cpp\ + BulletCollision/Gimpact/gim_memory.cpp\ + BulletCollision/Gimpact/gim_tri_collision.cpp + +libBulletDynamics_la_SOURCES = \ + BulletDynamics/Dynamics/btRigidBody.cpp \ + BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp \ + BulletDynamics/Dynamics/Bullet-C-API.cpp \ + BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp \ + BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp \ + BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp \ + BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp \ + BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp \ + BulletDynamics/ConstraintSolver/btTypedConstraint.cpp \ + BulletDynamics/ConstraintSolver/btContactConstraint.cpp \ + BulletDynamics/ConstraintSolver/btSliderConstraint.cpp \ + BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp \ + BulletDynamics/ConstraintSolver/btHingeConstraint.cpp \ + BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp \ + BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp \ + BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp \ + BulletDynamics/Vehicle/btWheelInfo.cpp \ + BulletDynamics/Vehicle/btRaycastVehicle.cpp \ + BulletDynamics/Character/btKinematicCharacterController.cpp \ + BulletDynamics/Character/btKinematicCharacterController.h \ + BulletDynamics/Character/btCharacterControllerInterface.h \ + BulletDynamics/Dynamics/btActionInterface.h \ + BulletDynamics/Dynamics/btSimpleDynamicsWorld.h \ + BulletDynamics/Dynamics/btRigidBody.h \ + BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h \ + BulletDynamics/Dynamics/btDynamicsWorld.h \ + BulletDynamics/ConstraintSolver/btSolverBody.h \ + BulletDynamics/ConstraintSolver/btConstraintSolver.h \ + BulletDynamics/ConstraintSolver/btConeTwistConstraint.h \ + BulletDynamics/ConstraintSolver/btTypedConstraint.h \ + BulletDynamics/ConstraintSolver/btContactSolverInfo.h \ + BulletDynamics/ConstraintSolver/btContactConstraint.h \ + BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h \ + BulletDynamics/ConstraintSolver/btJacobianEntry.h \ + BulletDynamics/ConstraintSolver/btSolverConstraint.h \ + BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h \ + BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h \ + BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h \ + BulletDynamics/ConstraintSolver/btSliderConstraint.h \ + BulletDynamics/ConstraintSolver/btHingeConstraint.h \ + BulletDynamics/ConstraintSolver/btHinge2Constraint.h \ + BulletDynamics/ConstraintSolver/btUniversalConstraint.h \ + BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h \ + BulletDynamics/Vehicle/btVehicleRaycaster.h \ + BulletDynamics/Vehicle/btRaycastVehicle.h \ + BulletDynamics/Vehicle/btWheelInfo.h + +libBulletSoftBody_la_SOURCES = \ + BulletSoftBody/btDefaultSoftBodySolver.cpp \ + BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp \ + BulletSoftBody/btSoftBody.cpp \ + BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp \ + BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp \ + BulletSoftBody/btSoftRigidDynamicsWorld.cpp \ + BulletSoftBody/btSoftBodyHelpers.cpp \ + BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp \ + BulletSoftBody/btSparseSDF.h \ + BulletSoftBody/btSoftRigidCollisionAlgorithm.h \ + BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h \ + BulletSoftBody/btSoftBody.h \ + BulletSoftBody/btSoftSoftCollisionAlgorithm.h \ + BulletSoftBody/btSoftBodyInternals.h \ + BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h \ + BulletSoftBody/btSoftRigidDynamicsWorld.h \ + BulletSoftBody/btSoftBodyHelpers.h + + + +nobase_bullet_include_HEADERS += \ + BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h \ + BulletSoftBody/btSoftBodyInternals.h \ + BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h \ + BulletSoftBody/btSoftSoftCollisionAlgorithm.h \ + BulletSoftBody/btSoftBody.h \ + BulletSoftBody/btSoftBodyHelpers.h \ + BulletSoftBody/btSparseSDF.h \ + BulletSoftBody/btSoftRigidCollisionAlgorithm.h \ + BulletSoftBody/btSoftRigidDynamicsWorld.h \ + BulletDynamics/Vehicle/btRaycastVehicle.h \ + BulletDynamics/Vehicle/btWheelInfo.h \ + BulletDynamics/Vehicle/btVehicleRaycaster.h \ + BulletDynamics/Dynamics/btActionInterface.h \ + BulletDynamics/Dynamics/btRigidBody.h \ + BulletDynamics/Dynamics/btDynamicsWorld.h \ + BulletDynamics/Dynamics/btSimpleDynamicsWorld.h \ + BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h \ + BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h \ + BulletDynamics/ConstraintSolver/btSolverConstraint.h \ + BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h \ + BulletDynamics/ConstraintSolver/btTypedConstraint.h \ + BulletDynamics/ConstraintSolver/btSliderConstraint.h \ + BulletDynamics/ConstraintSolver/btConstraintSolver.h \ + BulletDynamics/ConstraintSolver/btContactConstraint.h \ + BulletDynamics/ConstraintSolver/btContactSolverInfo.h \ + BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h \ + BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h \ + BulletDynamics/ConstraintSolver/btJacobianEntry.h \ + BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h \ + BulletDynamics/ConstraintSolver/btConeTwistConstraint.h \ + BulletDynamics/ConstraintSolver/btHingeConstraint.h \ + BulletDynamics/ConstraintSolver/btHinge2Constraint.h \ + BulletDynamics/ConstraintSolver/btUniversalConstraint.h \ + BulletDynamics/ConstraintSolver/btSolverBody.h \ + BulletDynamics/Character/btCharacterControllerInterface.h \ + BulletDynamics/Character/btKinematicCharacterController.h \ + BulletCollision/CollisionShapes/btShapeHull.h \ + BulletCollision/CollisionShapes/btConcaveShape.h \ + BulletCollision/CollisionShapes/btCollisionMargin.h \ + BulletCollision/CollisionShapes/btCompoundShape.h \ + BulletCollision/CollisionShapes/btConvexHullShape.h \ + BulletCollision/CollisionShapes/btCylinderShape.h \ + BulletCollision/CollisionShapes/btTriangleMesh.h \ + BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h \ + BulletCollision/CollisionShapes/btUniformScalingShape.h \ + BulletCollision/CollisionShapes/btConvexPointCloudShape.h \ + BulletCollision/CollisionShapes/btTetrahedronShape.h \ + BulletCollision/CollisionShapes/btCapsuleShape.h \ + BulletCollision/CollisionShapes/btSphereShape.h \ + BulletCollision/CollisionShapes/btMultiSphereShape.h \ + BulletCollision/CollisionShapes/btConvexInternalShape.h \ + BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btStridingMeshInterface.h \ + BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btEmptyShape.h \ + BulletCollision/CollisionShapes/btOptimizedBvh.h \ + BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btTriangleCallback.h \ + BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h \ + BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h \ + BulletCollision/CollisionShapes/btTriangleInfoMap.h \ + BulletCollision/CollisionShapes/btTriangleBuffer.h \ + BulletCollision/CollisionShapes/btConvexShape.h \ + BulletCollision/CollisionShapes/btConvex2dShape.h \ + BulletCollision/CollisionShapes/btStaticPlaneShape.h \ + BulletCollision/CollisionShapes/btConeShape.h \ + BulletCollision/CollisionShapes/btCollisionShape.h \ + BulletCollision/CollisionShapes/btTriangleShape.h \ + BulletCollision/CollisionShapes/btBoxShape.h \ + BulletCollision/CollisionShapes/btBox2dShape.h \ + BulletCollision/CollisionShapes/btMinkowskiSumShape.h \ + BulletCollision/CollisionShapes/btTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btMaterial.h \ + BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btPolyhedralConvexShape.h \ + BulletCollision/NarrowPhaseCollision/btConvexCast.h \ + BulletCollision/NarrowPhaseCollision/btGjkEpa2.h \ + BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h \ + BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h \ + BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h \ + BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h \ + BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h \ + BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h \ + BulletCollision/NarrowPhaseCollision/btPersistentManifold.h \ + BulletCollision/NarrowPhaseCollision/btManifoldPoint.h \ + BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h \ + BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h \ + BulletCollision/NarrowPhaseCollision/btRaycastCallback.h \ + BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h \ + BulletCollision/NarrowPhaseCollision/btPointCollector.h \ + BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h \ + BulletCollision/BroadphaseCollision/btDbvt.h \ + BulletCollision/BroadphaseCollision/btDispatcher.h \ + BulletCollision/BroadphaseCollision/btDbvtBroadphase.h \ + BulletCollision/BroadphaseCollision/btSimpleBroadphase.h \ + BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h \ + BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h \ + BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h \ + BulletCollision/BroadphaseCollision/btQuantizedBvh.h \ + BulletCollision/BroadphaseCollision/btAxisSweep3.h \ + BulletCollision/BroadphaseCollision/btBroadphaseInterface.h \ + BulletCollision/BroadphaseCollision/btOverlappingPairCache.h \ + BulletCollision/BroadphaseCollision/btBroadphaseProxy.h \ + BulletCollision/CollisionDispatch/btUnionFind.h \ + BulletCollision/CollisionDispatch/btCollisionConfiguration.h \ + BulletCollision/CollisionDispatch/btCollisionDispatcher.h \ + BulletCollision/CollisionDispatch/SphereTriangleDetector.h \ + BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btCollisionWorld.h \ + BulletCollision/CollisionDispatch/btCollisionCreateFunc.h \ + BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h \ + BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h \ + BulletCollision/CollisionDispatch/btCollisionObject.h \ + BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h \ + BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btGhostObject.h \ + BulletCollision/CollisionDispatch/btSimulationIslandManager.h \ + BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btBoxBoxDetector.h \ + BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btInternalEdgeUtility.h \ + BulletCollision/CollisionDispatch/btManifoldResult.h \ + BulletCollision/Gimpact/gim_memory.h \ + BulletCollision/Gimpact/gim_clip_polygon.h \ + BulletCollision/Gimpact/gim_bitset.h \ + BulletCollision/Gimpact/gim_linear_math.h \ + BulletCollision/Gimpact/btGeometryOperations.h \ + BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h \ + BulletCollision/Gimpact/btGImpactBvh.h \ + BulletCollision/Gimpact/gim_box_set.h \ + BulletCollision/Gimpact/gim_array.h \ + BulletCollision/Gimpact/btGImpactShape.h \ + BulletCollision/Gimpact/btTriangleShapeEx.h \ + BulletCollision/Gimpact/btClipPolygon.h \ + BulletCollision/Gimpact/gim_box_collision.h \ + BulletCollision/Gimpact/gim_tri_collision.h \ + BulletCollision/Gimpact/gim_geometry.h \ + BulletCollision/Gimpact/gim_math.h \ + BulletCollision/Gimpact/btQuantization.h \ + BulletCollision/Gimpact/btGImpactQuantizedBvh.h \ + BulletCollision/Gimpact/gim_geom_types.h \ + BulletCollision/Gimpact/gim_basic_geometry_operations.h \ + BulletCollision/Gimpact/gim_contact.h \ + BulletCollision/Gimpact/gim_hash_table.h \ + BulletCollision/Gimpact/gim_radixsort.h \ + BulletCollision/Gimpact/btGImpactMassUtil.h \ + BulletCollision/Gimpact/btGenericPoolAllocator.h \ + BulletCollision/Gimpact/btBoxCollision.h \ + BulletCollision/Gimpact/btContactProcessing.h \ + LinearMath/btGeometryUtil.h \ + LinearMath/btConvexHull.h \ + LinearMath/btList.h \ + LinearMath/btMatrix3x3.h \ + LinearMath/btVector3.h \ + LinearMath/btPoolAllocator.h \ + LinearMath/btScalar.h \ + LinearMath/btDefaultMotionState.h \ + LinearMath/btTransform.h \ + LinearMath/btQuadWord.h \ + LinearMath/btAabbUtil2.h \ + LinearMath/btTransformUtil.h \ + LinearMath/btRandom.h \ + LinearMath/btQuaternion.h \ + LinearMath/btMinMax.h \ + LinearMath/btMotionState.h \ + LinearMath/btIDebugDraw.h \ + LinearMath/btAlignedAllocator.h \ + LinearMath/btStackAlloc.h \ + LinearMath/btAlignedObjectArray.h \ + LinearMath/btHashMap.h \ + LinearMath/btQuickprof.h\ + LinearMath/btSerializer.h diff --git a/src/MiniCL/CMakeLists.txt b/src/MiniCL/CMakeLists.txt new file mode 100644 index 0000000..9fe5753 --- /dev/null +++ b/src/MiniCL/CMakeLists.txt @@ -0,0 +1,66 @@ +#MiniCL provides a small subset of OpenCL + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${VECTOR_MATH_INCLUDE} +) + +SET(MiniCL_SRCS + MiniCL.cpp + MiniCLTaskScheduler.cpp + MiniCLTask/MiniCLTask.cpp +) + +SET(Root_HDRS + MiniCLTaskScheduler.h + cl.h + cl_gl.h + cl_platform.h + cl_MiniCL_Defs.h +) + +SET(MiniCLTask_HDRS + MiniCLTask/MiniCLTask.h +) + +SET(MiniCL_HDRS + ${Root_HDRS} + ${MiniCLTask_HDRS} +) + +ADD_LIBRARY(MiniCL ${MiniCL_SRCS} ${MiniCL_HDRS} ) +SET_TARGET_PROPERTIES(MiniCL PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(MiniCL PROPERTIES SOVERSION ${BULLET_VERSION}) + + +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(MiniCL BulletMultiThreaded BulletDynamics BulletCollision) +ENDIF (BUILD_SHARED_LIBS) + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + #INSTALL of other files requires CMake 2.6 + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) +# IF(INSTALL_EXTRA_LIBS) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS MiniCL DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS MiniCL DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY +${CMAKE_CURRENT_SOURCE_DIR} DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING +PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) +# ENDIF (INSTALL_EXTRA_LIBS) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(MiniCL PROPERTIES FRAMEWORK true) + + SET_TARGET_PROPERTIES(MiniCL PROPERTIES PUBLIC_HEADER "${Root_HDRS}") + # Have to list out sub-directories manually: + SET_PROPERTY(SOURCE ${MiniCLTask_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/MiniCLTask) + + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) + diff --git a/src/MiniCL/MiniCL.cpp b/src/MiniCL/MiniCL.cpp new file mode 100644 index 0000000..24f6751 --- /dev/null +++ b/src/MiniCL/MiniCL.cpp @@ -0,0 +1,784 @@ +/* + Copyright (C) 2010 Sony Computer Entertainment Inc. + All rights reserved. + +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 "MiniCL/cl.h" +#define __PHYSICS_COMMON_H__ 1 +#ifdef _WIN32 +#include "BulletMultiThreaded/Win32ThreadSupport.h" +#endif + +#include "BulletMultiThreaded/PlatformDefinitions.h" +#ifdef USE_PTHREADS +#include "BulletMultiThreaded/PosixThreadSupport.h" +#endif + + +#include "BulletMultiThreaded/SequentialThreadSupport.h" +#include "MiniCLTaskScheduler.h" +#include "MiniCLTask/MiniCLTask.h" +#include "LinearMath/btMinMax.h" +#include + +//#define DEBUG_MINICL_KERNELS 1 + +static const char* spPlatformID = "MiniCL, SCEA"; +static const char* spDriverVersion= "1.0"; + +CL_API_ENTRY cl_int CL_API_CALL clGetPlatformIDs( + cl_uint num_entries, + cl_platform_id * platforms, + cl_uint * num_platforms ) CL_API_SUFFIX__VERSION_1_0 +{ + if(platforms != NULL) + { + if(num_entries <= 0) + { + return CL_INVALID_VALUE; + } + *((const char**)platforms) = spPlatformID; + } + if(num_platforms != NULL) + { + *num_platforms = 1; + } + return CL_SUCCESS; +} + + +CL_API_ENTRY cl_int CL_API_CALL clGetPlatformInfo( + cl_platform_id platform, + cl_platform_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 +{ + char* pId = (char*)platform; + if(strcmp(pId, spPlatformID)) + { + return CL_INVALID_PLATFORM; + } + switch(param_name) + { + case CL_PLATFORM_VERSION: + { + if(param_value_size < (strlen(spDriverVersion) + 1)) + { + return CL_INVALID_VALUE; + } + strcpy((char*)param_value, spDriverVersion); + if(param_value_size_ret != NULL) + { + *param_value_size_ret = strlen(spDriverVersion) + 1; + } + break; + } + case CL_PLATFORM_NAME: + case CL_PLATFORM_VENDOR : + if(param_value_size < (strlen(spPlatformID) + 1)) + { + return CL_INVALID_VALUE; + } + strcpy((char*)param_value, spPlatformID); + if(param_value_size_ret != NULL) + { + *param_value_size_ret = strlen(spPlatformID) + 1; + } + break; + default : + return CL_INVALID_VALUE; + } + return CL_SUCCESS; +} + + + + +CL_API_ENTRY cl_int CL_API_CALL clGetDeviceInfo( + cl_device_id device , + cl_device_info param_name , + size_t param_value_size , + void * param_value , + size_t * param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 +{ + + switch (param_name) + { + case CL_DEVICE_NAME: + { + char deviceName[] = "MiniCL CPU"; + unsigned int nameLen = (unsigned int)strlen(deviceName)+1; + btAssert(param_value_size>strlen(deviceName)); + if (nameLen < param_value_size) + { + const char* cpuName = "MiniCL CPU"; + sprintf((char*)param_value,"%s",cpuName); + } else + { + printf("error: param_value_size should be at least %d, but it is %d\n",nameLen,param_value_size); + return CL_INVALID_VALUE; + } + break; + } + case CL_DEVICE_TYPE: + { + if (param_value_size>=sizeof(cl_device_type)) + { + cl_device_type* deviceType = (cl_device_type*)param_value; + *deviceType = CL_DEVICE_TYPE_CPU; + } else + { + printf("error: param_value_size should be at least %d\n",sizeof(cl_device_type)); + return CL_INVALID_VALUE; + } + break; + } + case CL_DEVICE_MAX_COMPUTE_UNITS: + { + if (param_value_size>=sizeof(cl_uint)) + { + cl_uint* numUnits = (cl_uint*)param_value; + *numUnits= 4; + } else + { + printf("error: param_value_size should be at least %d\n",sizeof(cl_uint)); + return CL_INVALID_VALUE; + } + + break; + } + case CL_DEVICE_MAX_WORK_ITEM_SIZES: + { + size_t workitem_size[3]; + + if (param_value_size>=sizeof(workitem_size)) + { + size_t* workItemSize = (size_t*)param_value; + workItemSize[0] = 64; + workItemSize[1] = 24; + workItemSize[2] = 16; + } else + { + printf("error: param_value_size should be at least %d\n",sizeof(cl_uint)); + return CL_INVALID_VALUE; + } + break; + } + case CL_DEVICE_MAX_CLOCK_FREQUENCY: + { + cl_uint* clock_frequency = (cl_uint*)param_value; + *clock_frequency = 3*1024; + break; + } + + case CL_DEVICE_VENDOR : + { + if(param_value_size < (strlen(spPlatformID) + 1)) + { + return CL_INVALID_VALUE; + } + strcpy((char*)param_value, spPlatformID); + if(param_value_size_ret != NULL) + { + *param_value_size_ret = strlen(spPlatformID) + 1; + } + break; + } + case CL_DRIVER_VERSION: + { + if(param_value_size < (strlen(spDriverVersion) + 1)) + { + return CL_INVALID_VALUE; + } + strcpy((char*)param_value, spDriverVersion); + if(param_value_size_ret != NULL) + { + *param_value_size_ret = strlen(spDriverVersion) + 1; + } + + break; + } + case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: + { + cl_uint* maxDimensions = (cl_uint*)param_value; + *maxDimensions = 1; + break; + } + case CL_DEVICE_MAX_WORK_GROUP_SIZE: + { + cl_uint* maxWorkGroupSize = (cl_uint*)param_value; + *maxWorkGroupSize = 128;//1; + break; + } + case CL_DEVICE_ADDRESS_BITS: + { + cl_uint* addressBits = (cl_uint*)param_value; + *addressBits= 32; //@todo: should this be 64 for 64bit builds? + break; + } + case CL_DEVICE_MAX_MEM_ALLOC_SIZE: + { + cl_ulong* maxMemAlloc = (cl_ulong*)param_value; + *maxMemAlloc= 512*1024*1024; //this "should be enough for everyone" ? + break; + } + case CL_DEVICE_GLOBAL_MEM_SIZE: + { + cl_ulong* maxMemAlloc = (cl_ulong*)param_value; + *maxMemAlloc= 1024*1024*1024; //this "should be enough for everyone" ? + break; + } + + case CL_DEVICE_ERROR_CORRECTION_SUPPORT: + { + cl_bool* error_correction_support = (cl_bool*)param_value; + *error_correction_support = CL_FALSE; + break; + } + + case CL_DEVICE_LOCAL_MEM_TYPE: + { + cl_device_local_mem_type* local_mem_type = (cl_device_local_mem_type*)param_value; + *local_mem_type = CL_GLOBAL; + break; + } + case CL_DEVICE_LOCAL_MEM_SIZE: + { + cl_ulong* localmem = (cl_ulong*) param_value; + *localmem = 32*1024; + break; + } + + case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: + { + cl_ulong* localmem = (cl_ulong*) param_value; + *localmem = 64*1024; + break; + } + case CL_DEVICE_QUEUE_PROPERTIES: + { + cl_command_queue_properties* queueProp = (cl_command_queue_properties*) param_value; + memset(queueProp,0,param_value_size); + + break; + } + case CL_DEVICE_IMAGE_SUPPORT: + { + cl_bool* imageSupport = (cl_bool*) param_value; + *imageSupport = CL_FALSE; + break; + } + + case CL_DEVICE_MAX_WRITE_IMAGE_ARGS: + case CL_DEVICE_MAX_READ_IMAGE_ARGS: + { + cl_uint* imageArgs = (cl_uint*) param_value; + *imageArgs = 0; + break; + } + case CL_DEVICE_IMAGE3D_MAX_DEPTH: + case CL_DEVICE_IMAGE3D_MAX_HEIGHT: + case CL_DEVICE_IMAGE2D_MAX_HEIGHT: + case CL_DEVICE_IMAGE3D_MAX_WIDTH: + case CL_DEVICE_IMAGE2D_MAX_WIDTH: + { + size_t* maxSize = (size_t*) param_value; + *maxSize = 0; + break; + } + + case CL_DEVICE_EXTENSIONS: + { + char* extensions = (char*) param_value; + *extensions = 0; + break; + } + + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: + { + cl_uint* width = (cl_uint*) param_value; + *width = 1; + break; + } + + default: + { + printf("error: unsupported param_name:%d\n",param_name); + } + } + + + return 0; +} + +CL_API_ENTRY cl_int CL_API_CALL clReleaseMemObject(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0 +{ + return 0; +} + + + +CL_API_ENTRY cl_int CL_API_CALL clReleaseCommandQueue(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0 +{ + return 0; +} + +CL_API_ENTRY cl_int CL_API_CALL clReleaseProgram(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0 +{ + return 0; +} + +CL_API_ENTRY cl_int CL_API_CALL clReleaseKernel(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0 +{ + return 0; +} + + +// Enqueued Commands APIs +CL_API_ENTRY cl_int CL_API_CALL clEnqueueReadBuffer(cl_command_queue command_queue , + cl_mem buffer , + cl_bool /* blocking_read */, + size_t offset , + size_t cb , + void * ptr , + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0 +{ + MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue; + + ///wait for all work items to be completed + scheduler->flush(); + + memcpy(ptr,(char*)buffer + offset,cb); + return 0; +} + + +CL_API_ENTRY cl_int clGetProgramBuildInfo(cl_program /* program */, + cl_device_id /* device */, + cl_program_build_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0 +{ + + return 0; +} + + +// Program Object APIs +CL_API_ENTRY cl_program +clCreateProgramWithSource(cl_context context , + cl_uint /* count */, + const char ** /* strings */, + const size_t * /* lengths */, + cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 +{ + *errcode_ret = CL_SUCCESS; + return (cl_program)context; +} + +CL_API_ENTRY cl_int CL_API_CALL clEnqueueWriteBuffer(cl_command_queue command_queue , + cl_mem buffer , + cl_bool /* blocking_read */, + size_t offset, + size_t cb , + const void * ptr , + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0 +{ + MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue; + + ///wait for all work items to be completed + scheduler->flush(); + + memcpy((char*)buffer + offset, ptr,cb); + return 0; +} + +CL_API_ENTRY cl_int CL_API_CALL clFlush(cl_command_queue command_queue) +{ + MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue; + ///wait for all work items to be completed + scheduler->flush(); + return 0; +} + + +CL_API_ENTRY cl_int CL_API_CALL clEnqueueNDRangeKernel(cl_command_queue /* command_queue */, + cl_kernel clKernel , + cl_uint work_dim , + const size_t * /* global_work_offset */, + const size_t * global_work_size , + const size_t * /* local_work_size */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0 +{ + + + MiniCLKernel* kernel = (MiniCLKernel*) clKernel; + for (unsigned int ii=0;iim_scheduler->getMaxNumOutstandingTasks(); + int numWorkItems = global_work_size[ii]; + +// //at minimum 64 work items per task +// int numWorkItemsPerTask = btMax(64,numWorkItems / maxTask); + int numWorkItemsPerTask = numWorkItems / maxTask; + if (!numWorkItemsPerTask) numWorkItemsPerTask = 1; + + for (int t=0;tm_scheduler->issueTask(t, endIndex, kernel); + t = endIndex; + } + } +/* + + void* bla = 0; + + scheduler->issueTask(bla,2,3); + scheduler->flush(); + + */ + + return 0; +} + +#define LOCAL_BUF_SIZE 32768 +static int sLocalMemBuf[LOCAL_BUF_SIZE * 4 + 16]; +static int* spLocalBufCurr = NULL; +static int sLocalBufUsed = LOCAL_BUF_SIZE; // so it will be reset at the first call +static void* localBufMalloc(int size) +{ + int size16 = (size + 15) >> 4; // in 16-byte units + if((sLocalBufUsed + size16) > LOCAL_BUF_SIZE) + { // reset + spLocalBufCurr = sLocalMemBuf; + while((unsigned long)spLocalBufCurr & 0x0F) spLocalBufCurr++; // align to 16 bytes + sLocalBufUsed = 0; + } + void* ret = spLocalBufCurr; + spLocalBufCurr += size16 * 4; + sLocalBufUsed += size; + return ret; +} + + + +CL_API_ENTRY cl_int CL_API_CALL clSetKernelArg(cl_kernel clKernel , + cl_uint arg_index , + size_t arg_size , + const void * arg_value ) CL_API_SUFFIX__VERSION_1_0 +{ + MiniCLKernel* kernel = (MiniCLKernel* ) clKernel; + btAssert(arg_size <= MINICL_MAX_ARGLENGTH); + if (arg_index>MINI_CL_MAX_ARG) + { + printf("error: clSetKernelArg arg_index (%u) exceeds %u\n",arg_index,MINI_CL_MAX_ARG); + } else + { + if (arg_size>MINICL_MAX_ARGLENGTH) + //if (arg_size != MINICL_MAX_ARGLENGTH) + { + printf("error: clSetKernelArg argdata too large: %zu (maximum is %zu)\n",arg_size,MINICL_MAX_ARGLENGTH); + } + else + { + if(arg_value == NULL) + { // this is only for __local memory qualifier + void* ptr = localBufMalloc(arg_size); + kernel->m_argData[arg_index] = ptr; + } + else + { + memcpy(&(kernel->m_argData[arg_index]), arg_value, arg_size); + } + kernel->m_argSizes[arg_index] = arg_size; + if(arg_index >= kernel->m_numArgs) + { + kernel->m_numArgs = arg_index + 1; + kernel->updateLauncher(); + } + } + } + return 0; +} + +// Kernel Object APIs +CL_API_ENTRY cl_kernel CL_API_CALL clCreateKernel(cl_program program , + const char * kernel_name , + cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 +{ + MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) program; + MiniCLKernel* kernel = new MiniCLKernel(); + int nameLen = strlen(kernel_name); + if(nameLen >= MINI_CL_MAX_KERNEL_NAME) + { + *errcode_ret = CL_INVALID_KERNEL_NAME; + return NULL; + } + strcpy(kernel->m_name, kernel_name); + kernel->m_numArgs = 0; + + //kernel->m_kernelProgramCommandId = scheduler->findProgramCommandIdByName(kernel_name); + //if (kernel->m_kernelProgramCommandId>=0) + //{ + // *errcode_ret = CL_SUCCESS; + //} else + //{ + // *errcode_ret = CL_INVALID_KERNEL_NAME; + //} + kernel->m_scheduler = scheduler; + if(kernel->registerSelf() == NULL) + { + *errcode_ret = CL_INVALID_KERNEL_NAME; + return NULL; + } + else + { + *errcode_ret = CL_SUCCESS; + } + + return (cl_kernel)kernel; + +} + + +CL_API_ENTRY cl_int CL_API_CALL clBuildProgram(cl_program /* program */, + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const char * /* options */, + void (*pfn_notify)(cl_program /* program */, void * /* user_data */), + void * /* user_data */) CL_API_SUFFIX__VERSION_1_0 +{ + return CL_SUCCESS; +} + +CL_API_ENTRY cl_program CL_API_CALL clCreateProgramWithBinary(cl_context context , + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const size_t * /* lengths */, + const unsigned char ** /* binaries */, + cl_int * /* binary_status */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0 +{ + return (cl_program)context; +} + + +// Memory Object APIs +CL_API_ENTRY cl_mem CL_API_CALL clCreateBuffer(cl_context /* context */, + cl_mem_flags flags , + size_t size, + void * host_ptr , + cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 +{ + cl_mem buf = (cl_mem)malloc(size); + if ((flags&CL_MEM_COPY_HOST_PTR) && host_ptr) + { + memcpy(buf,host_ptr,size); + } + *errcode_ret = 0; + return buf; +} + +// Command Queue APIs +CL_API_ENTRY cl_command_queue CL_API_CALL clCreateCommandQueue(cl_context context , + cl_device_id /* device */, + cl_command_queue_properties /* properties */, + cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 +{ + *errcode_ret = 0; + return (cl_command_queue) context; +} + +extern CL_API_ENTRY cl_int CL_API_CALL clGetContextInfo(cl_context /* context */, + cl_context_info param_name , + size_t param_value_size , + void * param_value, + size_t * param_value_size_ret ) CL_API_SUFFIX__VERSION_1_0 +{ + + switch (param_name) + { + case CL_CONTEXT_DEVICES: + { + if (!param_value_size) + { + *param_value_size_ret = 13; + } else + { + const char* testName = "MiniCL_Test."; + sprintf((char*)param_value,"%s",testName); + } + break; + }; + default: + { + printf("unsupported\n"); + } + } + + return 0; +} + + + +CL_API_ENTRY cl_context CL_API_CALL clCreateContextFromType(const cl_context_properties * /* properties */, + cl_device_type device_type , + void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */, + void * /* user_data */, + cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 +{ + int maxNumOutstandingTasks = 4; +// int maxNumOutstandingTasks = 2; +// int maxNumOutstandingTasks = 1; + gMiniCLNumOutstandingTasks = maxNumOutstandingTasks; + const int maxNumOfThreadSupports = 8; + static int sUniqueThreadSupportIndex = 0; + static const char* sUniqueThreadSupportName[maxNumOfThreadSupports] = + { + "MiniCL_0", "MiniCL_1", "MiniCL_2", "MiniCL_3", "MiniCL_4", "MiniCL_5", "MiniCL_6", "MiniCL_7" + }; + + btThreadSupportInterface* threadSupport = 0; + + if (device_type==CL_DEVICE_TYPE_DEBUG) + { + SequentialThreadSupport::SequentialThreadConstructionInfo stc("MiniCL",processMiniCLTask,createMiniCLLocalStoreMemory); + threadSupport = new SequentialThreadSupport(stc); + } else + { + +#if _WIN32 + btAssert(sUniqueThreadSupportIndex < maxNumOfThreadSupports); + const char* bla = "MiniCL"; + threadSupport = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo( +// bla, + sUniqueThreadSupportName[sUniqueThreadSupportIndex++], + processMiniCLTask, //processCollisionTask, + createMiniCLLocalStoreMemory,//createCollisionLocalStoreMemory, + maxNumOutstandingTasks)); +#else + +#ifdef USE_PTHREADS + PosixThreadSupport::ThreadConstructionInfo constructionInfo("PosixThreads", + processMiniCLTask, + createMiniCLLocalStoreMemory, + maxNumOutstandingTasks); + threadSupport = new PosixThreadSupport(constructionInfo); + +#else + ///todo: add posix thread support for other platforms + SequentialThreadSupport::SequentialThreadConstructionInfo stc("MiniCL",processMiniCLTask,createMiniCLLocalStoreMemory); + threadSupport = new SequentialThreadSupport(stc); +#endif //USE_PTHREADS +#endif + + } + + + MiniCLTaskScheduler* scheduler = new MiniCLTaskScheduler(threadSupport,maxNumOutstandingTasks); + + *errcode_ret = 0; + return (cl_context)scheduler; +} + +CL_API_ENTRY cl_int CL_API_CALL +clGetDeviceIDs(cl_platform_id /* platform */, + cl_device_type /* device_type */, + cl_uint /* num_entries */, + cl_device_id * /* devices */, + cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0 +{ + return 0; +} + +CL_API_ENTRY cl_context CL_API_CALL +clCreateContext(const cl_context_properties * properties , + cl_uint num_devices , + const cl_device_id * devices , + void (*pfn_notify)(const char *, const void *, size_t, void *), + void * user_data , + cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 +{ + + return clCreateContextFromType(properties,CL_DEVICE_TYPE_ALL,pfn_notify,user_data,errcode_ret); +} + +CL_API_ENTRY cl_int CL_API_CALL clReleaseContext(cl_context context ) CL_API_SUFFIX__VERSION_1_0 +{ + + MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) context; + + btThreadSupportInterface* threadSupport = scheduler->getThreadSupportInterface(); + delete scheduler; + delete threadSupport; + + return 0; +} +extern CL_API_ENTRY cl_int CL_API_CALL +clFinish(cl_command_queue command_queue ) CL_API_SUFFIX__VERSION_1_0 +{ + MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue; + ///wait for all work items to be completed + scheduler->flush(); + return CL_SUCCESS; +} + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetProgramInfo(cl_program /* program */, + cl_program_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0 +{ + return 0; +} + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetKernelWorkGroupInfo(cl_kernel kernel , + cl_device_id /* device */, + cl_kernel_work_group_info wgi/* param_name */, + size_t sz /* param_value_size */, + void * ptr /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0 +{ + if((wgi == CL_KERNEL_WORK_GROUP_SIZE) + &&(sz == sizeof(size_t)) + &&(ptr != NULL)) + { + MiniCLKernel* miniCLKernel = (MiniCLKernel*)kernel; + MiniCLTaskScheduler* scheduler = miniCLKernel->m_scheduler; + *((size_t*)ptr) = scheduler->getMaxNumOutstandingTasks(); + return CL_SUCCESS; + } + else + { + return CL_INVALID_VALUE; + } +} diff --git a/src/MiniCL/MiniCLTask/MiniCLTask.cpp b/src/MiniCL/MiniCLTask/MiniCLTask.cpp new file mode 100644 index 0000000..a56e96a --- /dev/null +++ b/src/MiniCL/MiniCLTask/MiniCLTask.cpp @@ -0,0 +1,74 @@ +/* +Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans + +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 "MiniCLTask.h" +#include "BulletMultiThreaded/PlatformDefinitions.h" +#include "BulletMultiThreaded/SpuFakeDma.h" +#include "LinearMath/btMinMax.h" +#include "MiniCLTask.h" +#include "MiniCL/MiniCLTaskScheduler.h" + + +#ifdef __SPU__ +#include +#else +#include +#define spu_printf printf +#endif + +int gMiniCLNumOutstandingTasks = 0; + +struct MiniCLTask_LocalStoreMemory +{ + +}; + + +//-- MAIN METHOD +void processMiniCLTask(void* userPtr, void* lsMemory) +{ + // BT_PROFILE("processSampleTask"); + + MiniCLTask_LocalStoreMemory* localMemory = (MiniCLTask_LocalStoreMemory*)lsMemory; + + MiniCLTaskDesc* taskDescPtr = (MiniCLTaskDesc*)userPtr; + MiniCLTaskDesc& taskDesc = *taskDescPtr; + + for (unsigned int i=taskDesc.m_firstWorkUnit;im_launcher(&taskDesc, i); + } + +// printf("Compute Unit[%d] executed kernel %d work items [%d..%d)\n",taskDesc.m_taskId,taskDesc.m_kernelProgramId,taskDesc.m_firstWorkUnit,taskDesc.m_lastWorkUnit); + +} + + +#if defined(__CELLOS_LV2__) || defined (LIBSPE2) + +ATTRIBUTE_ALIGNED16(MiniCLTask_LocalStoreMemory gLocalStoreMemory); + +void* createMiniCLLocalStoreMemory() +{ + return &gLocalStoreMemory; +} +#else +void* createMiniCLLocalStoreMemory() +{ + return new MiniCLTask_LocalStoreMemory; +}; + +#endif diff --git a/src/MiniCL/MiniCLTask/MiniCLTask.h b/src/MiniCL/MiniCLTask/MiniCLTask.h new file mode 100644 index 0000000..7e78be0 --- /dev/null +++ b/src/MiniCL/MiniCLTask/MiniCLTask.h @@ -0,0 +1,62 @@ +/* +Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans + +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 MINICL__TASK_H +#define MINICL__TASK_H + +#include "BulletMultiThreaded/PlatformDefinitions.h" +#include "LinearMath/btScalar.h" + +#include "LinearMath/btAlignedAllocator.h" + + +#define MINICL_MAX_ARGLENGTH (sizeof(void*)) +#define MINI_CL_MAX_ARG 16 +#define MINI_CL_MAX_KERNEL_NAME 256 + +struct MiniCLKernel; + +ATTRIBUTE_ALIGNED16(struct) MiniCLTaskDesc +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + MiniCLTaskDesc() + { + for (int i=0;i + +#ifdef __SPU__ + + + +void SampleThreadFunc(void* userPtr,void* lsMemory) +{ + //do nothing + printf("hello world\n"); +} + + +void* SamplelsMemoryFunc() +{ + //don't create local store memory, just return 0 + return 0; +} + + +#else + + +#include "BulletMultiThreaded/btThreadSupportInterface.h" + +//# include "SPUAssert.h" +#include + +#include "MiniCL/cl_platform.h" + +extern "C" { + extern char SPU_SAMPLE_ELF_SYMBOL[]; +} + + +MiniCLTaskScheduler::MiniCLTaskScheduler(btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks) +:m_threadInterface(threadInterface), +m_maxNumOutstandingTasks(maxNumOutstandingTasks) +{ + + m_taskBusy.resize(m_maxNumOutstandingTasks); + m_spuSampleTaskDesc.resize(m_maxNumOutstandingTasks); + + m_kernels.resize(0); + + for (int i = 0; i < m_maxNumOutstandingTasks; i++) + { + m_taskBusy[i] = false; + } + m_numBusyTasks = 0; + m_currentTask = 0; + + m_initialized = false; + + m_threadInterface->startSPU(); + + +} + +MiniCLTaskScheduler::~MiniCLTaskScheduler() +{ + m_threadInterface->stopSPU(); + +} + + + +void MiniCLTaskScheduler::initialize() +{ +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("MiniCLTaskScheduler::initialize()\n"); +#endif //DEBUG_SPU_TASK_SCHEDULING + + for (int i = 0; i < m_maxNumOutstandingTasks; i++) + { + m_taskBusy[i] = false; + } + m_numBusyTasks = 0; + m_currentTask = 0; + m_initialized = true; + +} + + +void MiniCLTaskScheduler::issueTask(int firstWorkUnit, int lastWorkUnit, MiniCLKernel* kernel) +{ + +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("MiniCLTaskScheduler::issueTask (m_currentTask= %d\)n", m_currentTask); +#endif //DEBUG_SPU_TASK_SCHEDULING + + m_taskBusy[m_currentTask] = true; + m_numBusyTasks++; + + MiniCLTaskDesc& taskDesc = m_spuSampleTaskDesc[m_currentTask]; + { + // send task description in event message + taskDesc.m_firstWorkUnit = firstWorkUnit; + taskDesc.m_lastWorkUnit = lastWorkUnit; + taskDesc.m_kernel = kernel; + //some bookkeeping to recognize finished tasks + taskDesc.m_taskId = m_currentTask; + +// for (int i=0;im_numArgs; i++) + { + taskDesc.m_argSizes[i] = kernel->m_argSizes[i]; + if (taskDesc.m_argSizes[i]) + { + taskDesc.m_argData[i] = kernel->m_argData[i]; +// memcpy(&taskDesc.m_argData[i],&argData[MINICL_MAX_ARGLENGTH*i],taskDesc.m_argSizes[i]); + } + } + } + + + m_threadInterface->sendRequest(1, (ppu_address_t) &taskDesc, m_currentTask); + + // if all tasks busy, wait for spu event to clear the task. + + if (m_numBusyTasks >= m_maxNumOutstandingTasks) + { + unsigned int taskId; + unsigned int outputSize; + + for (int i=0;iwaitForResponse(&taskId, &outputSize); + + //printf("PPU: after issue, received event: %u %d\n", taskId, outputSize); + + postProcess(taskId, outputSize); + + m_taskBusy[taskId] = false; + + m_numBusyTasks--; + } + + // find new task buffer + for (int i = 0; i < m_maxNumOutstandingTasks; i++) + { + if (!m_taskBusy[i]) + { + m_currentTask = i; + break; + } + } +} + + +///Optional PPU-size post processing for each task +void MiniCLTaskScheduler::postProcess(int taskId, int outputSize) +{ + +} + + +void MiniCLTaskScheduler::flush() +{ +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("\nSpuCollisionTaskProcess::flush()\n"); +#endif //DEBUG_SPU_TASK_SCHEDULING + + + // all tasks are issued, wait for all tasks to be complete + while(m_numBusyTasks > 0) + { +// Consolidating SPU code + unsigned int taskId; + unsigned int outputSize; + + for (int i=0;iwaitForResponse(&taskId, &outputSize); + } + + //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize); + + postProcess(taskId, outputSize); + + m_taskBusy[taskId] = false; + + m_numBusyTasks--; + } + + +} + + + +typedef void (*MiniCLKernelLauncher0)(int); +typedef void (*MiniCLKernelLauncher1)(void*, int); +typedef void (*MiniCLKernelLauncher2)(void*, void*, int); +typedef void (*MiniCLKernelLauncher3)(void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher4)(void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher5)(void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher6)(void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher7)(void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher8)(void*, void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher9)(void*, void*, void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher10)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher11)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher12)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher13)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher14)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher15)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher16)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); + + +static void kernelLauncher0(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher0)(taskDesc->m_kernel->m_launcher))(guid); +} +static void kernelLauncher1(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher1)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + guid); +} +static void kernelLauncher2(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher2)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + taskDesc->m_argData[1], + guid); +} +static void kernelLauncher3(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher3)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + guid); +} +static void kernelLauncher4(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher4)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + guid); +} +static void kernelLauncher5(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher5)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + guid); +} +static void kernelLauncher6(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher6)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + guid); +} +static void kernelLauncher7(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher7)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + guid); +} +static void kernelLauncher8(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher8)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + guid); +} +static void kernelLauncher9(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher9)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + taskDesc->m_argData[8], + guid); +} +static void kernelLauncher10(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher10)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + taskDesc->m_argData[8], + taskDesc->m_argData[9], + guid); +} +static void kernelLauncher11(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher11)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + taskDesc->m_argData[8], + taskDesc->m_argData[9], + taskDesc->m_argData[10], + guid); +} +static void kernelLauncher12(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher12)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + taskDesc->m_argData[8], + taskDesc->m_argData[9], + taskDesc->m_argData[10], + taskDesc->m_argData[11], + guid); +} +static void kernelLauncher13(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher13)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + taskDesc->m_argData[8], + taskDesc->m_argData[9], + taskDesc->m_argData[10], + taskDesc->m_argData[11], + taskDesc->m_argData[12], + guid); +} +static void kernelLauncher14(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher14)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + taskDesc->m_argData[8], + taskDesc->m_argData[9], + taskDesc->m_argData[10], + taskDesc->m_argData[11], + taskDesc->m_argData[12], + taskDesc->m_argData[13], + guid); +} +static void kernelLauncher15(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher15)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + taskDesc->m_argData[8], + taskDesc->m_argData[9], + taskDesc->m_argData[10], + taskDesc->m_argData[11], + taskDesc->m_argData[12], + taskDesc->m_argData[13], + taskDesc->m_argData[14], + guid); +} +static void kernelLauncher16(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher16)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + taskDesc->m_argData[8], + taskDesc->m_argData[9], + taskDesc->m_argData[10], + taskDesc->m_argData[11], + taskDesc->m_argData[12], + taskDesc->m_argData[13], + taskDesc->m_argData[14], + taskDesc->m_argData[15], + guid); +} + +static kernelLauncherCB spLauncherList[MINI_CL_MAX_ARG+1] = +{ + kernelLauncher0, + kernelLauncher1, + kernelLauncher2, + kernelLauncher3, + kernelLauncher4, + kernelLauncher5, + kernelLauncher6, + kernelLauncher7, + kernelLauncher8, + kernelLauncher9, + kernelLauncher10, + kernelLauncher11, + kernelLauncher12, + kernelLauncher13, + kernelLauncher14, + kernelLauncher15, + kernelLauncher16 +}; + +void MiniCLKernel::updateLauncher() +{ + m_launcher = spLauncherList[m_numArgs]; +} + +struct MiniCLKernelDescEntry +{ + void* pCode; + const char* pName; +}; +static MiniCLKernelDescEntry spKernelDesc[256]; +static int sNumKernelDesc = 0; + +MiniCLKernelDesc::MiniCLKernelDesc(void* pCode, const char* pName) +{ + for(int i = 0; i < sNumKernelDesc; i++) + { + if(!strcmp(pName, spKernelDesc[i].pName)) + { // already registered + btAssert(spKernelDesc[i].pCode == pCode); + return; + } + } + spKernelDesc[sNumKernelDesc].pCode = pCode; + spKernelDesc[sNumKernelDesc].pName = pName; + sNumKernelDesc++; +} + + +MiniCLKernel* MiniCLKernel::registerSelf() +{ + m_scheduler->registerKernel(this); + for(int i = 0; i < sNumKernelDesc; i++) + { + if(!strcmp(m_name, spKernelDesc[i].pName)) + { + m_pCode = spKernelDesc[i].pCode; + return this; + } + } + return NULL; +} + +#endif + + +#endif //USE_SAMPLE_PROCESS diff --git a/src/MiniCL/MiniCLTaskScheduler.h b/src/MiniCL/MiniCLTaskScheduler.h new file mode 100644 index 0000000..3061a71 --- /dev/null +++ b/src/MiniCL/MiniCLTaskScheduler.h @@ -0,0 +1,194 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + +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 MINICL_TASK_SCHEDULER_H +#define MINICL_TASK_SCHEDULER_H + +#include + + +#include "BulletMultiThreaded/PlatformDefinitions.h" + +#include + +#include "LinearMath/btAlignedObjectArray.h" + + +#include "MiniCLTask/MiniCLTask.h" + +//just add your commands here, try to keep them globally unique for debugging purposes +#define CMD_SAMPLE_TASK_COMMAND 10 + +struct MiniCLKernel; + +/// MiniCLTaskScheduler handles SPU processing of collision pairs. +/// When PPU issues a task, it will look for completed task buffers +/// PPU will do postprocessing, dependent on workunit output (not likely) +class MiniCLTaskScheduler +{ + // track task buffers that are being used, and total busy tasks + btAlignedObjectArray m_taskBusy; + btAlignedObjectArray m_spuSampleTaskDesc; + + + btAlignedObjectArray m_kernels; + + + int m_numBusyTasks; + + // the current task and the current entry to insert a new work unit + int m_currentTask; + + bool m_initialized; + + void postProcess(int taskId, int outputSize); + + class btThreadSupportInterface* m_threadInterface; + + int m_maxNumOutstandingTasks; + + + +public: + MiniCLTaskScheduler(btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks); + + ~MiniCLTaskScheduler(); + + ///call initialize in the beginning of the frame, before addCollisionPairToTask + void initialize(); + + void issueTask(int firstWorkUnit, int lastWorkUnit, MiniCLKernel* kernel); + + ///call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished + void flush(); + + class btThreadSupportInterface* getThreadSupportInterface() + { + return m_threadInterface; + } + + int findProgramCommandIdByName(const char* programName) const; + + int getMaxNumOutstandingTasks() const + { + return m_maxNumOutstandingTasks; + } + + void registerKernel(MiniCLKernel* kernel) + { + m_kernels.push_back(kernel); + } +}; + +typedef void (*kernelLauncherCB)(MiniCLTaskDesc* taskDesc, int guid); + +struct MiniCLKernel +{ + MiniCLTaskScheduler* m_scheduler; + +// int m_kernelProgramCommandId; + + char m_name[MINI_CL_MAX_KERNEL_NAME]; + unsigned int m_numArgs; + kernelLauncherCB m_launcher; + void* m_pCode; + void updateLauncher(); + MiniCLKernel* registerSelf(); + + void* m_argData[MINI_CL_MAX_ARG]; + int m_argSizes[MINI_CL_MAX_ARG]; +}; + + +#if defined(USE_LIBSPE2) && defined(__SPU__) +////////////////////MAIN///////////////////////////// +#include "../SpuLibspe2Support.h" +#include +#include +#include + +void * SamplelsMemoryFunc(); +void SampleThreadFunc(void* userPtr,void* lsMemory); + +//#define DEBUG_LIBSPE2_MAINLOOP + +int main(unsigned long long speid, addr64 argp, addr64 envp) +{ + printf("SPU is up \n"); + + ATTRIBUTE_ALIGNED128(btSpuStatus status); + ATTRIBUTE_ALIGNED16( SpuSampleTaskDesc taskDesc ) ; + unsigned int received_message = Spu_Mailbox_Event_Nothing; + bool shutdown = false; + + cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + status.m_status = Spu_Status_Free; + status.m_lsMemory.p = SamplelsMemoryFunc(); + + cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + + while (!shutdown) + { + received_message = spu_read_in_mbox(); + + + + switch(received_message) + { + case Spu_Mailbox_Event_Shutdown: + shutdown = true; + break; + case Spu_Mailbox_Event_Task: + // refresh the status +#ifdef DEBUG_LIBSPE2_MAINLOOP + printf("SPU recieved Task \n"); +#endif //DEBUG_LIBSPE2_MAINLOOP + cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + btAssert(status.m_status==Spu_Status_Occupied); + + cellDmaGet(&taskDesc, status.m_taskDesc.p, sizeof(SpuSampleTaskDesc), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + SampleThreadFunc((void*)&taskDesc, reinterpret_cast (taskDesc.m_mainMemoryPtr) ); + break; + case Spu_Mailbox_Event_Nothing: + default: + break; + } + + // set to status free and wait for next task + status.m_status = Spu_Status_Free; + cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + + } + return 0; +} +////////////////////////////////////////////////////// +#endif + + + +#endif // MINICL_TASK_SCHEDULER_H + diff --git a/src/MiniCL/cl.h b/src/MiniCL/cl.h new file mode 100644 index 0000000..3528298 --- /dev/null +++ b/src/MiniCL/cl.h @@ -0,0 +1,867 @@ +/******************************************************************************* + * Copyright (c) 2008-2009 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are 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 Materials. + * + * THE MATERIALS ARE 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 + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + ******************************************************************************/ + +#ifndef __OPENCL_CL_H +#define __OPENCL_CL_H + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************/ + +typedef struct _cl_platform_id * cl_platform_id; +typedef struct _cl_device_id * cl_device_id; +typedef struct _cl_context * cl_context; +typedef struct _cl_command_queue * cl_command_queue; +typedef struct _cl_mem * cl_mem; +typedef struct _cl_program * cl_program; +typedef struct _cl_kernel * cl_kernel; +typedef struct _cl_event * cl_event; +typedef struct _cl_sampler * cl_sampler; + +typedef cl_uint cl_bool; /* WARNING! Unlike cl_ types in cl_platform.h, cl_bool is not guaranteed to be the same size as the bool in kernels. */ +typedef cl_ulong cl_bitfield; +typedef cl_bitfield cl_device_type; +typedef cl_uint cl_platform_info; +typedef cl_uint cl_device_info; +typedef cl_bitfield cl_device_address_info; +typedef cl_bitfield cl_device_fp_config; +typedef cl_uint cl_device_mem_cache_type; +typedef cl_uint cl_device_local_mem_type; +typedef cl_bitfield cl_device_exec_capabilities; +typedef cl_bitfield cl_command_queue_properties; + +typedef intptr_t cl_context_properties; +typedef cl_uint cl_context_info; +typedef cl_uint cl_command_queue_info; +typedef cl_uint cl_channel_order; +typedef cl_uint cl_channel_type; +typedef cl_bitfield cl_mem_flags; +typedef cl_uint cl_mem_object_type; +typedef cl_uint cl_mem_info; +typedef cl_uint cl_image_info; +typedef cl_uint cl_addressing_mode; +typedef cl_uint cl_filter_mode; +typedef cl_uint cl_sampler_info; +typedef cl_bitfield cl_map_flags; +typedef cl_uint cl_program_info; +typedef cl_uint cl_program_build_info; +typedef cl_int cl_build_status; +typedef cl_uint cl_kernel_info; +typedef cl_uint cl_kernel_work_group_info; +typedef cl_uint cl_event_info; +typedef cl_uint cl_command_type; +typedef cl_uint cl_profiling_info; + +typedef struct _cl_image_format { + cl_channel_order image_channel_order; + cl_channel_type image_channel_data_type; +} cl_image_format; + +/******************************************************************************/ + +// Error Codes +#define CL_SUCCESS 0 +#define CL_DEVICE_NOT_FOUND -1 +#define CL_DEVICE_NOT_AVAILABLE -2 +#define CL_DEVICE_COMPILER_NOT_AVAILABLE -3 +#define CL_MEM_OBJECT_ALLOCATION_FAILURE -4 +#define CL_OUT_OF_RESOURCES -5 +#define CL_OUT_OF_HOST_MEMORY -6 +#define CL_PROFILING_INFO_NOT_AVAILABLE -7 +#define CL_MEM_COPY_OVERLAP -8 +#define CL_IMAGE_FORMAT_MISMATCH -9 +#define CL_IMAGE_FORMAT_NOT_SUPPORTED -10 +#define CL_BUILD_PROGRAM_FAILURE -11 +#define CL_MAP_FAILURE -12 + +#define CL_INVALID_VALUE -30 +#define CL_INVALID_DEVICE_TYPE -31 +#define CL_INVALID_PLATFORM -32 +#define CL_INVALID_DEVICE -33 +#define CL_INVALID_CONTEXT -34 +#define CL_INVALID_QUEUE_PROPERTIES -35 +#define CL_INVALID_COMMAND_QUEUE -36 +#define CL_INVALID_HOST_PTR -37 +#define CL_INVALID_MEM_OBJECT -38 +#define CL_INVALID_IMAGE_FORMAT_DESCRIPTOR -39 +#define CL_INVALID_IMAGE_SIZE -40 +#define CL_INVALID_SAMPLER -41 +#define CL_INVALID_BINARY -42 +#define CL_INVALID_BUILD_OPTIONS -43 +#define CL_INVALID_PROGRAM -44 +#define CL_INVALID_PROGRAM_EXECUTABLE -45 +#define CL_INVALID_KERNEL_NAME -46 +#define CL_INVALID_KERNEL_DEFINITION -47 +#define CL_INVALID_KERNEL -48 +#define CL_INVALID_ARG_INDEX -49 +#define CL_INVALID_ARG_VALUE -50 +#define CL_INVALID_ARG_SIZE -51 +#define CL_INVALID_KERNEL_ARGS -52 +#define CL_INVALID_WORK_DIMENSION -53 +#define CL_INVALID_WORK_GROUP_SIZE -54 +#define CL_INVALID_WORK_ITEM_SIZE -55 +#define CL_INVALID_GLOBAL_OFFSET -56 +#define CL_INVALID_EVENT_WAIT_LIST -57 +#define CL_INVALID_EVENT -58 +#define CL_INVALID_OPERATION -59 +#define CL_INVALID_GL_OBJECT -60 +#define CL_INVALID_BUFFER_SIZE -61 +#define CL_INVALID_MIP_LEVEL -62 + +// OpenCL Version +#define CL_VERSION_1_0 1 + +// cl_bool +#define CL_FALSE 0 +#define CL_TRUE 1 + +// cl_platform_info +#define CL_PLATFORM_PROFILE 0x0900 +#define CL_PLATFORM_VERSION 0x0901 +#define CL_PLATFORM_NAME 0x0902 +#define CL_PLATFORM_VENDOR 0x0903 +#define CL_PLATFORM_EXTENSIONS 0x0904 + +// cl_device_type - bitfield +#define CL_DEVICE_TYPE_DEFAULT (1 << 0) +#define CL_DEVICE_TYPE_CPU (1 << 1) +#define CL_DEVICE_TYPE_GPU (1 << 2) +#define CL_DEVICE_TYPE_ACCELERATOR (1 << 3) +#define CL_DEVICE_TYPE_DEBUG (1 << 4) +#define CL_DEVICE_TYPE_ALL 0xFFFFFFFF + + +// cl_device_info +#define CL_DEVICE_TYPE 0x1000 +#define CL_DEVICE_VENDOR_ID 0x1001 +#define CL_DEVICE_MAX_COMPUTE_UNITS 0x1002 +#define CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS 0x1003 +#define CL_DEVICE_MAX_WORK_GROUP_SIZE 0x1004 +#define CL_DEVICE_MAX_WORK_ITEM_SIZES 0x1005 +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR 0x1006 +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT 0x1007 +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT 0x1008 +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG 0x1009 +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT 0x100A +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE 0x100B +#define CL_DEVICE_MAX_CLOCK_FREQUENCY 0x100C +#define CL_DEVICE_ADDRESS_BITS 0x100D +#define CL_DEVICE_MAX_READ_IMAGE_ARGS 0x100E +#define CL_DEVICE_MAX_WRITE_IMAGE_ARGS 0x100F +#define CL_DEVICE_MAX_MEM_ALLOC_SIZE 0x1010 +#define CL_DEVICE_IMAGE2D_MAX_WIDTH 0x1011 +#define CL_DEVICE_IMAGE2D_MAX_HEIGHT 0x1012 +#define CL_DEVICE_IMAGE3D_MAX_WIDTH 0x1013 +#define CL_DEVICE_IMAGE3D_MAX_HEIGHT 0x1014 +#define CL_DEVICE_IMAGE3D_MAX_DEPTH 0x1015 +#define CL_DEVICE_IMAGE_SUPPORT 0x1016 +#define CL_DEVICE_MAX_PARAMETER_SIZE 0x1017 +#define CL_DEVICE_MAX_SAMPLERS 0x1018 +#define CL_DEVICE_MEM_BASE_ADDR_ALIGN 0x1019 +#define CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE 0x101A +#define CL_DEVICE_SINGLE_FP_CONFIG 0x101B +#define CL_DEVICE_GLOBAL_MEM_CACHE_TYPE 0x101C +#define CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE 0x101D +#define CL_DEVICE_GLOBAL_MEM_CACHE_SIZE 0x101E +#define CL_DEVICE_GLOBAL_MEM_SIZE 0x101F +#define CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE 0x1020 +#define CL_DEVICE_MAX_CONSTANT_ARGS 0x1021 +#define CL_DEVICE_LOCAL_MEM_TYPE 0x1022 +#define CL_DEVICE_LOCAL_MEM_SIZE 0x1023 +#define CL_DEVICE_ERROR_CORRECTION_SUPPORT 0x1024 +#define CL_DEVICE_PROFILING_TIMER_RESOLUTION 0x1025 +#define CL_DEVICE_ENDIAN_LITTLE 0x1026 +#define CL_DEVICE_AVAILABLE 0x1027 +#define CL_DEVICE_COMPILER_AVAILABLE 0x1028 +#define CL_DEVICE_EXECUTION_CAPABILITIES 0x1029 +#define CL_DEVICE_QUEUE_PROPERTIES 0x102A +#define CL_DEVICE_NAME 0x102B +#define CL_DEVICE_VENDOR 0x102C +#define CL_DRIVER_VERSION 0x102D +#define CL_DEVICE_PROFILE 0x102E +#define CL_DEVICE_VERSION 0x102F +#define CL_DEVICE_EXTENSIONS 0x1030 +#define CL_DEVICE_PLATFORM 0x1031 + +// cl_device_address_info - bitfield +#define CL_DEVICE_ADDRESS_32_BITS (1 << 0) +#define CL_DEVICE_ADDRESS_64_BITS (1 << 1) + +// cl_device_fp_config - bitfield +#define CL_FP_DENORM (1 << 0) +#define CL_FP_INF_NAN (1 << 1) +#define CL_FP_ROUND_TO_NEAREST (1 << 2) +#define CL_FP_ROUND_TO_ZERO (1 << 3) +#define CL_FP_ROUND_TO_INF (1 << 4) +#define CL_FP_FMA (1 << 5) + +// cl_device_mem_cache_type +#define CL_NONE 0x0 +#define CL_READ_ONLY_CACHE 0x1 +#define CL_READ_WRITE_CACHE 0x2 + +// cl_device_local_mem_type +#define CL_LOCAL 0x1 +#define CL_GLOBAL 0x2 + +// cl_device_exec_capabilities - bitfield +#define CL_EXEC_KERNEL (1 << 0) +#define CL_EXEC_NATIVE_KERNEL (1 << 1) + +// cl_command_queue_properties - bitfield +#define CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE (1 << 0) +#define CL_QUEUE_PROFILING_ENABLE (1 << 1) + +// cl_context_info +#define CL_CONTEXT_REFERENCE_COUNT 0x1080 +#define CL_CONTEXT_NUM_DEVICES 0x1081 +#define CL_CONTEXT_DEVICES 0x1082 +#define CL_CONTEXT_PROPERTIES 0x1083 +#define CL_CONTEXT_PLATFORM 0x1084 + +// cl_command_queue_info +#define CL_QUEUE_CONTEXT 0x1090 +#define CL_QUEUE_DEVICE 0x1091 +#define CL_QUEUE_REFERENCE_COUNT 0x1092 +#define CL_QUEUE_PROPERTIES 0x1093 + +// cl_mem_flags - bitfield +#define CL_MEM_READ_WRITE (1 << 0) +#define CL_MEM_WRITE_ONLY (1 << 1) +#define CL_MEM_READ_ONLY (1 << 2) +#define CL_MEM_USE_HOST_PTR (1 << 3) +#define CL_MEM_ALLOC_HOST_PTR (1 << 4) +#define CL_MEM_COPY_HOST_PTR (1 << 5) + +// cl_channel_order +#define CL_R 0x10B0 +#define CL_A 0x10B1 +#define CL_RG 0x10B2 +#define CL_RA 0x10B3 +#define CL_RGB 0x10B4 +#define CL_RGBA 0x10B5 +#define CL_BGRA 0x10B6 +#define CL_ARGB 0x10B7 +#define CL_INTENSITY 0x10B8 +#define CL_LUMINANCE 0x10B9 + +// cl_channel_type +#define CL_SNORM_INT8 0x10D0 +#define CL_SNORM_INT16 0x10D1 +#define CL_UNORM_INT8 0x10D2 +#define CL_UNORM_INT16 0x10D3 +#define CL_UNORM_SHORT_565 0x10D4 +#define CL_UNORM_SHORT_555 0x10D5 +#define CL_UNORM_INT_101010 0x10D6 +#define CL_SIGNED_INT8 0x10D7 +#define CL_SIGNED_INT16 0x10D8 +#define CL_SIGNED_INT32 0x10D9 +#define CL_UNSIGNED_INT8 0x10DA +#define CL_UNSIGNED_INT16 0x10DB +#define CL_UNSIGNED_INT32 0x10DC +#define CL_HALF_FLOAT 0x10DD +#define CL_FLOAT 0x10DE + +// cl_mem_object_type +#define CL_MEM_OBJECT_BUFFER 0x10F0 +#define CL_MEM_OBJECT_IMAGE2D 0x10F1 +#define CL_MEM_OBJECT_IMAGE3D 0x10F2 + +// cl_mem_info +#define CL_MEM_TYPE 0x1100 +#define CL_MEM_FLAGS 0x1101 +#define CL_MEM_SIZE 0x1102 +#define CL_MEM_HOST_PTR 0x1103 +#define CL_MEM_MAP_COUNT 0x1104 +#define CL_MEM_REFERENCE_COUNT 0x1105 +#define CL_MEM_CONTEXT 0x1106 + +// cl_image_info +#define CL_IMAGE_FORMAT 0x1110 +#define CL_IMAGE_ELEMENT_SIZE 0x1111 +#define CL_IMAGE_ROW_PITCH 0x1112 +#define CL_IMAGE_SLICE_PITCH 0x1113 +#define CL_IMAGE_WIDTH 0x1114 +#define CL_IMAGE_HEIGHT 0x1115 +#define CL_IMAGE_DEPTH 0x1116 + +// cl_addressing_mode +#define CL_ADDRESS_NONE 0x1130 +#define CL_ADDRESS_CLAMP_TO_EDGE 0x1131 +#define CL_ADDRESS_CLAMP 0x1132 +#define CL_ADDRESS_REPEAT 0x1133 + +// cl_filter_mode +#define CL_FILTER_NEAREST 0x1140 +#define CL_FILTER_LINEAR 0x1141 + +// cl_sampler_info +#define CL_SAMPLER_REFERENCE_COUNT 0x1150 +#define CL_SAMPLER_CONTEXT 0x1151 +#define CL_SAMPLER_NORMALIZED_COORDS 0x1152 +#define CL_SAMPLER_ADDRESSING_MODE 0x1153 +#define CL_SAMPLER_FILTER_MODE 0x1154 + +// cl_map_flags - bitfield +#define CL_MAP_READ (1 << 0) +#define CL_MAP_WRITE (1 << 1) + +// cl_program_info +#define CL_PROGRAM_REFERENCE_COUNT 0x1160 +#define CL_PROGRAM_CONTEXT 0x1161 +#define CL_PROGRAM_NUM_DEVICES 0x1162 +#define CL_PROGRAM_DEVICES 0x1163 +#define CL_PROGRAM_SOURCE 0x1164 +#define CL_PROGRAM_BINARY_SIZES 0x1165 +#define CL_PROGRAM_BINARIES 0x1166 + +// cl_program_build_info +#define CL_PROGRAM_BUILD_STATUS 0x1181 +#define CL_PROGRAM_BUILD_OPTIONS 0x1182 +#define CL_PROGRAM_BUILD_LOG 0x1183 + +// cl_build_status +#define CL_BUILD_SUCCESS 0 +#define CL_BUILD_NONE -1 +#define CL_BUILD_ERROR -2 +#define CL_BUILD_IN_PROGRESS -3 + +// cl_kernel_info +#define CL_KERNEL_FUNCTION_NAME 0x1190 +#define CL_KERNEL_NUM_ARGS 0x1191 +#define CL_KERNEL_REFERENCE_COUNT 0x1192 +#define CL_KERNEL_CONTEXT 0x1193 +#define CL_KERNEL_PROGRAM 0x1194 + +// cl_kernel_work_group_info +#define CL_KERNEL_WORK_GROUP_SIZE 0x11B0 +#define CL_KERNEL_COMPILE_WORK_GROUP_SIZE 0x11B1 +#define CL_KERNEL_LOCAL_MEM_SIZE 0x11B2 + +// cl_event_info +#define CL_EVENT_COMMAND_QUEUE 0x11D0 +#define CL_EVENT_COMMAND_TYPE 0x11D1 +#define CL_EVENT_REFERENCE_COUNT 0x11D2 +#define CL_EVENT_COMMAND_EXECUTION_STATUS 0x11D3 + +// cl_command_type +#define CL_COMMAND_NDRANGE_KERNEL 0x11F0 +#define CL_COMMAND_TASK 0x11F1 +#define CL_COMMAND_NATIVE_KERNEL 0x11F2 +#define CL_COMMAND_READ_BUFFER 0x11F3 +#define CL_COMMAND_WRITE_BUFFER 0x11F4 +#define CL_COMMAND_COPY_BUFFER 0x11F5 +#define CL_COMMAND_READ_IMAGE 0x11F6 +#define CL_COMMAND_WRITE_IMAGE 0x11F7 +#define CL_COMMAND_COPY_IMAGE 0x11F8 +#define CL_COMMAND_COPY_IMAGE_TO_BUFFER 0x11F9 +#define CL_COMMAND_COPY_BUFFER_TO_IMAGE 0x11FA +#define CL_COMMAND_MAP_BUFFER 0x11FB +#define CL_COMMAND_MAP_IMAGE 0x11FC +#define CL_COMMAND_UNMAP_MEM_OBJECT 0x11FD +#define CL_COMMAND_MARKER 0x11FE +#define CL_COMMAND_WAIT_FOR_EVENTS 0x11FF +#define CL_COMMAND_BARRIER 0x1200 +#define CL_COMMAND_ACQUIRE_GL_OBJECTS 0x1201 +#define CL_COMMAND_RELEASE_GL_OBJECTS 0x1202 + +// command execution status +#define CL_COMPLETE 0x0 +#define CL_RUNNING 0x1 +#define CL_SUBMITTED 0x2 +#define CL_QUEUED 0x3 + +// cl_profiling_info +#define CL_PROFILING_COMMAND_QUEUED 0x1280 +#define CL_PROFILING_COMMAND_SUBMIT 0x1281 +#define CL_PROFILING_COMMAND_START 0x1282 +#define CL_PROFILING_COMMAND_END 0x1283 + +/********************************************************************************************************/ + +// Platform API +extern CL_API_ENTRY cl_int CL_API_CALL +clGetPlatformIDs(cl_uint /* num_entries */, + cl_platform_id * /* platforms */, + cl_uint * /* num_platforms */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetPlatformInfo(cl_platform_id /* platform */, + cl_platform_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Device APIs +extern CL_API_ENTRY cl_int CL_API_CALL +clGetDeviceIDs(cl_platform_id /* platform */, + cl_device_type /* device_type */, + cl_uint /* num_entries */, + cl_device_id * /* devices */, + cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetDeviceInfo(cl_device_id /* device */, + cl_device_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Context APIs +extern CL_API_ENTRY cl_context CL_API_CALL +clCreateContext(const cl_context_properties * /* properties */, + cl_uint /* num_devices */, + const cl_device_id * /* devices */, + void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */, + void * /* user_data */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_context CL_API_CALL +clCreateContextFromType(const cl_context_properties * /* properties */, + cl_device_type /* device_type */, + void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */, + void * /* user_data */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainContext(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseContext(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetContextInfo(cl_context /* context */, + cl_context_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Command Queue APIs +extern CL_API_ENTRY cl_command_queue CL_API_CALL +clCreateCommandQueue(cl_context /* context */, + cl_device_id /* device */, + cl_command_queue_properties /* properties */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainCommandQueue(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseCommandQueue(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetCommandQueueInfo(cl_command_queue /* command_queue */, + cl_command_queue_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clSetCommandQueueProperty(cl_command_queue /* command_queue */, + cl_command_queue_properties /* properties */, + cl_bool /* enable */, + cl_command_queue_properties * /* old_properties */) CL_API_SUFFIX__VERSION_1_0; + +// Memory Object APIs +extern CL_API_ENTRY cl_mem CL_API_CALL +clCreateBuffer(cl_context /* context */, + cl_mem_flags /* flags */, + size_t /* size */, + void * /* host_ptr */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_mem CL_API_CALL +clCreateImage2D(cl_context /* context */, + cl_mem_flags /* flags */, + const cl_image_format * /* image_format */, + size_t /* image_width */, + size_t /* image_height */, + size_t /* image_row_pitch */, + void * /* host_ptr */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_mem CL_API_CALL +clCreateImage3D(cl_context /* context */, + cl_mem_flags /* flags */, + const cl_image_format * /* image_format */, + size_t /* image_width */, + size_t /* image_height */, + size_t /* image_depth */, + size_t /* image_row_pitch */, + size_t /* image_slice_pitch */, + void * /* host_ptr */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainMemObject(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseMemObject(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetSupportedImageFormats(cl_context /* context */, + cl_mem_flags /* flags */, + cl_mem_object_type /* image_type */, + cl_uint /* num_entries */, + cl_image_format * /* image_formats */, + cl_uint * /* num_image_formats */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetMemObjectInfo(cl_mem /* memobj */, + cl_mem_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetImageInfo(cl_mem /* image */, + cl_image_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Sampler APIs +extern CL_API_ENTRY cl_sampler CL_API_CALL +clCreateSampler(cl_context /* context */, + cl_bool /* normalized_coords */, + cl_addressing_mode /* addressing_mode */, + cl_filter_mode /* filter_mode */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainSampler(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseSampler(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetSamplerInfo(cl_sampler /* sampler */, + cl_sampler_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Program Object APIs +extern CL_API_ENTRY cl_program CL_API_CALL +clCreateProgramWithSource(cl_context /* context */, + cl_uint /* count */, + const char ** /* strings */, + const size_t * /* lengths */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_program CL_API_CALL +clCreateProgramWithBinary(cl_context /* context */, + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const size_t * /* lengths */, + const unsigned char ** /* binaries */, + cl_int * /* binary_status */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainProgram(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseProgram(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clBuildProgram(cl_program /* program */, + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const char * /* options */, + void (*pfn_notify)(cl_program /* program */, void * /* user_data */), + void * /* user_data */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clUnloadCompiler(void) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetProgramInfo(cl_program /* program */, + cl_program_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetProgramBuildInfo(cl_program /* program */, + cl_device_id /* device */, + cl_program_build_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Kernel Object APIs +extern CL_API_ENTRY cl_kernel CL_API_CALL +clCreateKernel(cl_program /* program */, + const char * /* kernel_name */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clCreateKernelsInProgram(cl_program /* program */, + cl_uint /* num_kernels */, + cl_kernel * /* kernels */, + cl_uint * /* num_kernels_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainKernel(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseKernel(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clSetKernelArg(cl_kernel /* kernel */, + cl_uint /* arg_index */, + size_t /* arg_size */, + const void * /* arg_value */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetKernelInfo(cl_kernel /* kernel */, + cl_kernel_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetKernelWorkGroupInfo(cl_kernel /* kernel */, + cl_device_id /* device */, + cl_kernel_work_group_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Event Object APIs +extern CL_API_ENTRY cl_int CL_API_CALL +clWaitForEvents(cl_uint /* num_events */, + const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetEventInfo(cl_event /* event */, + cl_event_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainEvent(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseEvent(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0; + +// Profiling APIs +extern CL_API_ENTRY cl_int CL_API_CALL +clGetEventProfilingInfo(cl_event /* event */, + cl_profiling_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Flush and Finish APIs +extern CL_API_ENTRY cl_int CL_API_CALL +clFlush(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clFinish(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + +// Enqueued Commands APIs +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueReadBuffer(cl_command_queue /* command_queue */, + cl_mem /* buffer */, + cl_bool /* blocking_read */, + size_t /* offset */, + size_t /* cb */, + void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueWriteBuffer(cl_command_queue /* command_queue */, + cl_mem /* buffer */, + cl_bool /* blocking_write */, + size_t /* offset */, + size_t /* cb */, + const void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueCopyBuffer(cl_command_queue /* command_queue */, + cl_mem /* src_buffer */, + cl_mem /* dst_buffer */, + size_t /* src_offset */, + size_t /* dst_offset */, + size_t /* cb */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueReadImage(cl_command_queue /* command_queue */, + cl_mem /* image */, + cl_bool /* blocking_read */, + const size_t * /* origin[3] */, + const size_t * /* region[3] */, + size_t /* row_pitch */, + size_t /* slice_pitch */, + void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueWriteImage(cl_command_queue /* command_queue */, + cl_mem /* image */, + cl_bool /* blocking_write */, + const size_t * /* origin[3] */, + const size_t * /* region[3] */, + size_t /* input_row_pitch */, + size_t /* input_slice_pitch */, + const void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueCopyImage(cl_command_queue /* command_queue */, + cl_mem /* src_image */, + cl_mem /* dst_image */, + const size_t * /* src_origin[3] */, + const size_t * /* dst_origin[3] */, + const size_t * /* region[3] */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueCopyImageToBuffer(cl_command_queue /* command_queue */, + cl_mem /* src_image */, + cl_mem /* dst_buffer */, + const size_t * /* src_origin[3] */, + const size_t * /* region[3] */, + size_t /* dst_offset */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueCopyBufferToImage(cl_command_queue /* command_queue */, + cl_mem /* src_buffer */, + cl_mem /* dst_image */, + size_t /* src_offset */, + const size_t * /* dst_origin[3] */, + const size_t * /* region[3] */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY void * CL_API_CALL +clEnqueueMapBuffer(cl_command_queue /* command_queue */, + cl_mem /* buffer */, + cl_bool /* blocking_map */, + cl_map_flags /* map_flags */, + size_t /* offset */, + size_t /* cb */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY void * CL_API_CALL +clEnqueueMapImage(cl_command_queue /* command_queue */, + cl_mem /* image */, + cl_bool /* blocking_map */, + cl_map_flags /* map_flags */, + const size_t * /* origin[3] */, + const size_t * /* region[3] */, + size_t * /* image_row_pitch */, + size_t * /* image_slice_pitch */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueUnmapMemObject(cl_command_queue /* command_queue */, + cl_mem /* memobj */, + void * /* mapped_ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueNDRangeKernel(cl_command_queue /* command_queue */, + cl_kernel /* kernel */, + cl_uint /* work_dim */, + const size_t * /* global_work_offset */, + const size_t * /* global_work_size */, + const size_t * /* local_work_size */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueTask(cl_command_queue /* command_queue */, + cl_kernel /* kernel */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueNativeKernel(cl_command_queue /* command_queue */, + void (*user_func)(void *), + void * /* args */, + size_t /* cb_args */, + cl_uint /* num_mem_objects */, + const cl_mem * /* mem_list */, + const void ** /* args_mem_loc */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueMarker(cl_command_queue /* command_queue */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueWaitForEvents(cl_command_queue /* command_queue */, + cl_uint /* num_events */, + const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueBarrier(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + +#ifdef __cplusplus +} +#endif + +#endif // __OPENCL_CL_H + diff --git a/src/MiniCL/cl_MiniCL_Defs.h b/src/MiniCL/cl_MiniCL_Defs.h new file mode 100644 index 0000000..73fd3c7 --- /dev/null +++ b/src/MiniCL/cl_MiniCL_Defs.h @@ -0,0 +1,439 @@ +/* +Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans + +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 +#include +#include "LinearMath/btScalar.h" + +#include "MiniCL/cl.h" + + +#define __kernel +#define __global +#define __local +#define get_global_id(a) __guid_arg +#define get_local_id(a) ((__guid_arg) % gMiniCLNumOutstandingTasks) +#define get_local_size(a) (gMiniCLNumOutstandingTasks) +#define get_group_id(a) ((__guid_arg) / gMiniCLNumOutstandingTasks) + +static unsigned int as_uint(float val) { return *((unsigned int*)&val); } + + +#define CLK_LOCAL_MEM_FENCE 0x01 +#define CLK_GLOBAL_MEM_FENCE 0x02 + +static void barrier(unsigned int a) +{ + // TODO : implement +} + +//ATTRIBUTE_ALIGNED16(struct) float8 +struct float8 +{ + float s0; + float s1; + float s2; + float s3; + float s4; + float s5; + float s6; + float s7; + + float8(float scalar) + { + s0=s1=s2=s3=s4=s5=s6=s7=scalar; + } +}; + + +float select( float arg0, float arg1, bool select) +{ + if (select) + return arg0; + return arg1; +} + +#define __constant + + +struct float3 +{ + float x,y,z; + + float3& operator+=(const float3& other) + { + x += other.x; + y += other.y; + z += other.z; + return *this; + } + + float3& operator-=(const float3& other) + { + x -= other.x; + y -= other.y; + z -= other.z; + return *this; + } + +}; + +static float dot(const float3&a ,const float3& b) +{ + float3 tmp; + tmp.x = a.x*b.x; + tmp.y = a.y*b.y; + tmp.z = a.z*b.z; + return tmp.x+tmp.y+tmp.z; +} + +static float3 operator-(const float3& a,const float3& b) +{ + float3 tmp; + tmp.x = a.x - b.x; + tmp.y = a.y - b.y; + tmp.z = a.z - b.z; + return tmp; +} + +static float3 operator*(const float& scalar,const float3& b) +{ + float3 tmp; + tmp.x = scalar * b.x; + tmp.y = scalar * b.y; + tmp.z = scalar * b.z; + return tmp; +} + +static float3 operator*(const float3& a,const float& scalar) +{ + float3 tmp; + tmp.x = a.x * scalar; + tmp.y = a.y * scalar; + tmp.z = a.z * scalar; + return tmp; +} + + +static float3 operator*(const float3& a,const float3& b) +{ + float3 tmp; + tmp.x = a.x * b.x; + tmp.y = a.y * b.y; + tmp.z = a.z * b.z; + return tmp; +} + + +//ATTRIBUTE_ALIGNED16(struct) float4 +struct float4 +{ + union + { + struct { + float x; + float y; + float z; + }; + float3 xyz; + }; + float w; + + float4() {} + + float4(float v0, float v1, float v2, float v3) + { + x=v0; + y=v1; + z=v2; + w=v3; + + } + float4(float3 xyz, float scalarW) + { + x = xyz.x; + y = xyz.y; + z = xyz.z; + w = scalarW; + } + + float4(float v) + { + x = y = z = w = v; + } + float4 operator*(const float4& other) + { + float4 tmp; + tmp.x = x*other.x; + tmp.y = y*other.y; + tmp.z = z*other.z; + tmp.w = w*other.w; + return tmp; + } + + + + float4 operator*(const float& other) + { + float4 tmp; + tmp.x = x*other; + tmp.y = y*other; + tmp.z = z*other; + tmp.w = w*other; + return tmp; + } + + + + float4& operator+=(const float4& other) + { + x += other.x; + y += other.y; + z += other.z; + w += other.w; + return *this; + } + + float4& operator-=(const float4& other) + { + x -= other.x; + y -= other.y; + z -= other.z; + w -= other.w; + return *this; + } + + float4& operator *=(float scalar) + { + x *= scalar; + y *= scalar; + z *= scalar; + w *= scalar; + return (*this); + } + + + + + +}; + +static float4 fabs(const float4& a) +{ + float4 tmp; + tmp.x = a.x < 0.f ? 0.f : a.x; + tmp.y = a.y < 0.f ? 0.f : a.y; + tmp.z = a.z < 0.f ? 0.f : a.z; + tmp.w = a.w < 0.f ? 0.f : a.w; + return tmp; +} +static float4 operator+(const float4& a,const float4& b) +{ + float4 tmp; + tmp.x = a.x + b.x; + tmp.y = a.y + b.y; + tmp.z = a.z + b.z; + tmp.w = a.w + b.w; + return tmp; +} + + +static float8 operator+(const float8& a,const float8& b) +{ + float8 tmp(0); + tmp.s0 = a.s0 + b.s0; + tmp.s1 = a.s1 + b.s1; + tmp.s2 = a.s2 + b.s2; + tmp.s3 = a.s3 + b.s3; + tmp.s4 = a.s4 + b.s4; + tmp.s5 = a.s5 + b.s5; + tmp.s6 = a.s6 + b.s6; + tmp.s7 = a.s7 + b.s7; + return tmp; +} + + +static float4 operator-(const float4& a,const float4& b) +{ + float4 tmp; + tmp.x = a.x - b.x; + tmp.y = a.y - b.y; + tmp.z = a.z - b.z; + tmp.w = a.w - b.w; + return tmp; +} + +static float8 operator-(const float8& a,const float8& b) +{ + float8 tmp(0); + tmp.s0 = a.s0 - b.s0; + tmp.s1 = a.s1 - b.s1; + tmp.s2 = a.s2 - b.s2; + tmp.s3 = a.s3 - b.s3; + tmp.s4 = a.s4 - b.s4; + tmp.s5 = a.s5 - b.s5; + tmp.s6 = a.s6 - b.s6; + tmp.s7 = a.s7 - b.s7; + return tmp; +} + +static float4 operator*(float a,const float4& b) +{ + float4 tmp; + tmp.x = a * b.x; + tmp.y = a * b.y; + tmp.z = a * b.z; + tmp.w = a * b.w; + return tmp; +} + +static float4 operator/(const float4& b,float a) +{ + float4 tmp; + tmp.x = b.x/a; + tmp.y = b.y/a; + tmp.z = b.z/a; + tmp.w = b.w/a; + return tmp; +} + + + + + +static float dot(const float4&a ,const float4& b) +{ + float4 tmp; + tmp.x = a.x*b.x; + tmp.y = a.y*b.y; + tmp.z = a.z*b.z; + tmp.w = a.w*b.w; + return tmp.x+tmp.y+tmp.z+tmp.w; +} + +static float length(const float4&a) +{ + float l = sqrtf(a.x*a.x+a.y*a.y+a.z*a.z); + return l; +} + +static float4 normalize(const float4&a) +{ + float4 tmp; + float l = length(a); + tmp = 1.f/l*a; + return tmp; +} + + + +static float4 cross(const float4&a ,const float4& b) +{ + float4 tmp; + tmp.x = a.y*b.z - a.z*b.y; + tmp.y = -a.x*b.z + a.z*b.x; + tmp.z = a.x*b.y - a.y*b.x; + tmp.w = 0.f; + return tmp; +} + +static float max(float a, float b) +{ + return (a >= b) ? a : b; +} + + +static float min(float a, float b) +{ + return (a <= b) ? a : b; +} + +static float fmax(float a, float b) +{ + return (a >= b) ? a : b; +} + +static float fmin(float a, float b) +{ + return (a <= b) ? a : b; +} + +struct int2 +{ + int x,y; +}; + +struct uint2 +{ + unsigned int x,y; +}; + +//typedef int2 uint2; + +typedef unsigned int uint; + +struct int4 +{ + int x,y,z,w; +}; + +struct uint4 +{ + unsigned int x,y,z,w; + uint4() {} + uint4(uint val) { x = y = z = w = val; } + uint4& operator+=(const uint4& other) + { + x += other.x; + y += other.y; + z += other.z; + w += other.w; + return *this; + } +}; +static uint4 operator+(const uint4& a,const uint4& b) +{ + uint4 tmp; + tmp.x = a.x + b.x; + tmp.y = a.y + b.y; + tmp.z = a.z + b.z; + tmp.w = a.w + b.w; + return tmp; +} +static uint4 operator-(const uint4& a,const uint4& b) +{ + uint4 tmp; + tmp.x = a.x - b.x; + tmp.y = a.y - b.y; + tmp.z = a.z - b.z; + tmp.w = a.w - b.w; + return tmp; +} + +#define native_sqrt sqrtf +#define native_sin sinf +#define native_cos cosf +#define native_powr powf + +#define GUID_ARG ,int __guid_arg +#define GUID_ARG_VAL ,__guid_arg + + +#define as_int(a) (*((int*)&(a))) + +extern "C" int gMiniCLNumOutstandingTasks; +// extern "C" void __kernel_func(); + + diff --git a/src/MiniCL/cl_gl.h b/src/MiniCL/cl_gl.h new file mode 100644 index 0000000..0a69d6e --- /dev/null +++ b/src/MiniCL/cl_gl.h @@ -0,0 +1,113 @@ +/********************************************************************************** + * Copyright (c) 2008-2009 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are 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 Materials. + * + * THE MATERIALS ARE 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 + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + **********************************************************************************/ + +#ifndef __OPENCL_CL_GL_H +#define __OPENCL_CL_GL_H + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// NOTE: Make sure that appropriate GL header file is included separately + +typedef cl_uint cl_gl_object_type; +typedef cl_uint cl_gl_texture_info; +typedef cl_uint cl_gl_platform_info; + +// cl_gl_object_type +#define CL_GL_OBJECT_BUFFER 0x2000 +#define CL_GL_OBJECT_TEXTURE2D 0x2001 +#define CL_GL_OBJECT_TEXTURE3D 0x2002 +#define CL_GL_OBJECT_RENDERBUFFER 0x2003 + +// cl_gl_texture_info +#define CL_GL_TEXTURE_TARGET 0x2004 +#define CL_GL_MIPMAP_LEVEL 0x2005 + +extern CL_API_ENTRY cl_mem CL_API_CALL +clCreateFromGLBuffer(cl_context /* context */, + cl_mem_flags /* flags */, + GLuint /* bufobj */, + int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_mem CL_API_CALL +clCreateFromGLTexture2D(cl_context /* context */, + cl_mem_flags /* flags */, + GLenum /* target */, + GLint /* miplevel */, + GLuint /* texture */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_mem CL_API_CALL +clCreateFromGLTexture3D(cl_context /* context */, + cl_mem_flags /* flags */, + GLenum /* target */, + GLint /* miplevel */, + GLuint /* texture */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_mem CL_API_CALL +clCreateFromGLRenderbuffer(cl_context /* context */, + cl_mem_flags /* flags */, + GLuint /* renderbuffer */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetGLObjectInfo(cl_mem /* memobj */, + cl_gl_object_type * /* gl_object_type */, + GLuint * /* gl_object_name */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetGLTextureInfo(cl_mem /* memobj */, + cl_gl_texture_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueAcquireGLObjects(cl_command_queue /* command_queue */, + cl_uint /* num_objects */, + const cl_mem * /* mem_objects */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueReleaseGLObjects(cl_command_queue /* command_queue */, + cl_uint /* num_objects */, + const cl_mem * /* mem_objects */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +#ifdef __cplusplus +} +#endif + +#endif // __OPENCL_CL_GL_H diff --git a/src/MiniCL/cl_platform.h b/src/MiniCL/cl_platform.h new file mode 100644 index 0000000..43219e1 --- /dev/null +++ b/src/MiniCL/cl_platform.h @@ -0,0 +1,254 @@ +/********************************************************************************** + * Copyright (c) 2008-2009 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are 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 Materials. + * + * THE MATERIALS ARE 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 + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + **********************************************************************************/ + +#ifndef __CL_PLATFORM_H +#define __CL_PLATFORM_H + +#define CL_PLATFORM_MINI_CL 0x12345 + +struct MiniCLKernelDesc +{ + MiniCLKernelDesc(void* pCode, const char* pName); +}; + +#define MINICL_REGISTER(__kernel_func) static MiniCLKernelDesc __kernel_func##Desc((void*)__kernel_func, #__kernel_func); + + +#ifdef __APPLE__ + /* Contains #defines for AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER below */ + #include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define CL_API_ENTRY +#define CL_API_CALL +#ifdef __APPLE__ +#define CL_API_SUFFIX__VERSION_1_0 // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER +#define CL_EXTENSION_WEAK_LINK __attribute__((weak_import)) +#else +#define CL_API_SUFFIX__VERSION_1_0 +#define CL_EXTENSION_WEAK_LINK +#endif + +#if defined (_WIN32) && ! defined (__MINGW32__) +typedef signed __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef signed __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef signed __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + +typedef int8_t cl_char; +typedef uint8_t cl_uchar; +typedef int16_t cl_short ; +typedef uint16_t cl_ushort ; +typedef int32_t cl_int ; +typedef uint32_t cl_uint ; +typedef int64_t cl_long ; +typedef uint64_t cl_ulong ; + +typedef uint16_t cl_half ; +typedef float cl_float ; +typedef double cl_double ; + + +typedef int8_t cl_char2[2] ; +typedef int8_t cl_char4[4] ; +typedef int8_t cl_char8[8] ; +typedef int8_t cl_char16[16] ; +typedef uint8_t cl_uchar2[2] ; +typedef uint8_t cl_uchar4[4] ; +typedef uint8_t cl_uchar8[8] ; +typedef uint8_t cl_uchar16[16] ; + +typedef int16_t cl_short2[2] ; +typedef int16_t cl_short4[4] ; +typedef int16_t cl_short8[8] ; +typedef int16_t cl_short16[16] ; +typedef uint16_t cl_ushort2[2] ; +typedef uint16_t cl_ushort4[4] ; +typedef uint16_t cl_ushort8[8] ; +typedef uint16_t cl_ushort16[16] ; + +typedef int32_t cl_int2[2] ; +typedef int32_t cl_int4[4] ; +typedef int32_t cl_int8[8] ; +typedef int32_t cl_int16[16] ; +typedef uint32_t cl_uint2[2] ; +typedef uint32_t cl_uint4[4] ; +typedef uint32_t cl_uint8[8] ; +typedef uint32_t cl_uint16[16] ; + +typedef int64_t cl_long2[2] ; +typedef int64_t cl_long4[4] ; +typedef int64_t cl_long8[8] ; +typedef int64_t cl_long16[16] ; +typedef uint64_t cl_ulong2[2] ; +typedef uint64_t cl_ulong4[4] ; +typedef uint64_t cl_ulong8[8] ; +typedef uint64_t cl_ulong16[16] ; + +typedef float cl_float2[2] ; +typedef float cl_float4[4] ; +typedef float cl_float8[8] ; +typedef float cl_float16[16] ; + +typedef double cl_double2[2] ; +typedef double cl_double4[4] ; +typedef double cl_double8[8] ; +typedef double cl_double16[16] ; + + +#else +#include + +/* scalar types */ +typedef int8_t cl_char; +typedef uint8_t cl_uchar; +typedef int16_t cl_short __attribute__((aligned(2))); +typedef uint16_t cl_ushort __attribute__((aligned(2))); +typedef int32_t cl_int __attribute__((aligned(4))); +typedef uint32_t cl_uint __attribute__((aligned(4))); +typedef int64_t cl_long __attribute__((aligned(8))); +typedef uint64_t cl_ulong __attribute__((aligned(8))); + +typedef uint16_t cl_half __attribute__((aligned(2))); +typedef float cl_float __attribute__((aligned(4))); +typedef double cl_double __attribute__((aligned(8))); + + +/* + * Vector types + * + * Note: OpenCL requires that all types be naturally aligned. + * This means that vector types must be naturally aligned. + * For example, a vector of four floats must be aligned to + * a 16 byte boundary (calculated as 4 * the natural 4-byte + * alignment of the float). The alignment qualifiers here + * will only function properly if your compiler supports them + * and if you don't actively work to defeat them. For example, + * in order for a cl_float4 to be 16 byte aligned in a struct, + * the start of the struct must itself be 16-byte aligned. + * + * Maintaining proper alignment is the user's responsibility. + */ +typedef int8_t cl_char2[2] __attribute__((aligned(2))); +typedef int8_t cl_char4[4] __attribute__((aligned(4))); +typedef int8_t cl_char8[8] __attribute__((aligned(8))); +typedef int8_t cl_char16[16] __attribute__((aligned(16))); +typedef uint8_t cl_uchar2[2] __attribute__((aligned(2))); +typedef uint8_t cl_uchar4[4] __attribute__((aligned(4))); +typedef uint8_t cl_uchar8[8] __attribute__((aligned(8))); +typedef uint8_t cl_uchar16[16] __attribute__((aligned(16))); + +typedef int16_t cl_short2[2] __attribute__((aligned(4))); +typedef int16_t cl_short4[4] __attribute__((aligned(8))); +typedef int16_t cl_short8[8] __attribute__((aligned(16))); +typedef int16_t cl_short16[16] __attribute__((aligned(32))); +typedef uint16_t cl_ushort2[2] __attribute__((aligned(4))); +typedef uint16_t cl_ushort4[4] __attribute__((aligned(8))); +typedef uint16_t cl_ushort8[8] __attribute__((aligned(16))); +typedef uint16_t cl_ushort16[16] __attribute__((aligned(32))); + +typedef int32_t cl_int2[2] __attribute__((aligned(8))); +typedef int32_t cl_int4[4] __attribute__((aligned(16))); +typedef int32_t cl_int8[8] __attribute__((aligned(32))); +typedef int32_t cl_int16[16] __attribute__((aligned(64))); +typedef uint32_t cl_uint2[2] __attribute__((aligned(8))); +typedef uint32_t cl_uint4[4] __attribute__((aligned(16))); +typedef uint32_t cl_uint8[8] __attribute__((aligned(32))); +typedef uint32_t cl_uint16[16] __attribute__((aligned(64))); + +typedef int64_t cl_long2[2] __attribute__((aligned(16))); +typedef int64_t cl_long4[4] __attribute__((aligned(32))); +typedef int64_t cl_long8[8] __attribute__((aligned(64))); +typedef int64_t cl_long16[16] __attribute__((aligned(128))); +typedef uint64_t cl_ulong2[2] __attribute__((aligned(16))); +typedef uint64_t cl_ulong4[4] __attribute__((aligned(32))); +typedef uint64_t cl_ulong8[8] __attribute__((aligned(64))); +typedef uint64_t cl_ulong16[16] __attribute__((aligned(128))); + +typedef float cl_float2[2] __attribute__((aligned(8))); +typedef float cl_float4[4] __attribute__((aligned(16))); +typedef float cl_float8[8] __attribute__((aligned(32))); +typedef float cl_float16[16] __attribute__((aligned(64))); + +typedef double cl_double2[2] __attribute__((aligned(16))); +typedef double cl_double4[4] __attribute__((aligned(32))); +typedef double cl_double8[8] __attribute__((aligned(64))); +typedef double cl_double16[16] __attribute__((aligned(128))); +#endif + +#include + +/* and a few goodies to go with them */ +#define CL_CHAR_BIT 8 +#define CL_SCHAR_MAX 127 +#define CL_SCHAR_MIN (-127-1) +#define CL_CHAR_MAX CL_SCHAR_MAX +#define CL_CHAR_MIN CL_SCHAR_MIN +#define CL_UCHAR_MAX 255 +#define CL_SHRT_MAX 32767 +#define CL_SHRT_MIN (-32767-1) +#define CL_USHRT_MAX 65535 +#define CL_INT_MAX 2147483647 +#define CL_INT_MIN (-2147483647-1) +#define CL_UINT_MAX 0xffffffffU +#define CL_LONG_MAX ((cl_long) 0x7FFFFFFFFFFFFFFFLL) +#define CL_LONG_MIN ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL) +#define CL_ULONG_MAX ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL) + +#define CL_FLT_DIG 6 +#define CL_FLT_MANT_DIG 24 +#define CL_FLT_MAX_10_EXP +38 +#define CL_FLT_MAX_EXP +128 +#define CL_FLT_MIN_10_EXP -37 +#define CL_FLT_MIN_EXP -125 +#define CL_FLT_RADIX 2 +#define CL_FLT_MAX 0x1.fffffep127f +#define CL_FLT_MIN 0x1.0p-126f +#define CL_FLT_EPSILON 0x1.0p-23f + +#define CL_DBL_DIG 15 +#define CL_DBL_MANT_DIG 53 +#define CL_DBL_MAX_10_EXP +308 +#define CL_DBL_MAX_EXP +1024 +#define CL_DBL_MIN_10_EXP -307 +#define CL_DBL_MIN_EXP -1021 +#define CL_DBL_RADIX 2 +#define CL_DBL_MAX 0x1.fffffffffffffp1023 +#define CL_DBL_MIN 0x1.0p-1022 +#define CL_DBL_EPSILON 0x1.0p-52 + +/* There are no vector types for half */ + +#ifdef __cplusplus +} +#endif + +#endif // __CL_PLATFORM_H diff --git a/src/btBulletCollisionCommon.h b/src/btBulletCollisionCommon.h new file mode 100644 index 0000000..472690c --- /dev/null +++ b/src/btBulletCollisionCommon.h @@ -0,0 +1,69 @@ +/* +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 BULLET_COLLISION_COMMON_H +#define BULLET_COLLISION_COMMON_H + +///Common headerfile includes for Bullet Collision Detection + +///Bullet's btCollisionWorld and btCollisionObject definitions +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" + +///Collision Shapes +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletCollision/CollisionShapes/btCylinderShape.h" +#include "BulletCollision/CollisionShapes/btConeShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" +#include "BulletCollision/CollisionShapes/btConvexHullShape.h" +#include "BulletCollision/CollisionShapes/btTriangleMesh.h" +#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" +#include "BulletCollision/CollisionShapes/btEmptyShape.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/CollisionShapes/btUniformScalingShape.h" + +///Narrowphase Collision Detector +#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" + +//btSphereBoxCollisionAlgorithm is broken, use gjk for now +//#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h" + +///Dispatching and generation of collision pairs (broadphase) +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/BroadphaseCollision/btAxisSweep3.h" +#include "BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h" +#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h" + +///Math library & Utils +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btDefaultMotionState.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btIDebugDraw.h" +#include "LinearMath/btSerializer.h" + + +#endif //BULLET_COLLISION_COMMON_H + diff --git a/src/btBulletDynamicsCommon.h b/src/btBulletDynamicsCommon.h new file mode 100644 index 0000000..ccfad19 --- /dev/null +++ b/src/btBulletDynamicsCommon.h @@ -0,0 +1,48 @@ +/* +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 BULLET_DYNAMICS_COMMON_H +#define BULLET_DYNAMICS_COMMON_H + +///Common headerfile includes for Bullet Dynamics, including Collision Detection +#include "btBulletCollisionCommon.h" + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" + +#include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" + +#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h" +#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h" +#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h" +#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h" +#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h" +#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h" +#include "BulletDynamics/ConstraintSolver/btUniversalConstraint.h" +#include "BulletDynamics/ConstraintSolver/btHinge2Constraint.h" + +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" + + +///Vehicle simulation, with wheel contact simulated by raycasts +#include "BulletDynamics/Vehicle/btRaycastVehicle.h" + + + + + + +#endif //BULLET_DYNAMICS_COMMON_H + diff --git a/src/ibmsdk/Makefile b/src/ibmsdk/Makefile new file mode 100644 index 0000000..1a0453e --- /dev/null +++ b/src/ibmsdk/Makefile @@ -0,0 +1,16 @@ +#### Visit Bullet library ibmsdk dirs and build code + +DIRS := \ +../BulletCollision/ibmsdk \ +../BulletDynamics/ibmsdk \ +../LinearMath/ibmsdk + +IBM_CELLSDK_VERSION := $(shell if [ -d /opt/cell ]; then echo "3.0"; fi) + +ifeq ("$(IBM_CELLSDK_VERSION)","3.0") + CELL_TOP ?= /opt/cell/sdk + include $(CELL_TOP)/buildutils/make.footer +else + CELL_TOP ?= /opt/ibm/cell-sdk/prototype + include $(CELL_TOP)/make.footer +endif diff --git a/src/vectormath/scalar/boolInVec.h b/src/vectormath/scalar/boolInVec.h new file mode 100644 index 0000000..c5eeeeb --- /dev/null +++ b/src/vectormath/scalar/boolInVec.h @@ -0,0 +1,225 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _BOOLINVEC_H +#define _BOOLINVEC_H + +#include +namespace Vectormath { + +class floatInVec; + +//-------------------------------------------------------------------------------------------------- +// boolInVec class +// + +class boolInVec +{ +private: + unsigned int mData; + +public: + // Default constructor; does no initialization + // + inline boolInVec( ) { }; + + // Construct from a value converted from float + // + inline boolInVec(floatInVec vec); + + // Explicit cast from bool + // + explicit inline boolInVec(bool scalar); + + // Explicit cast to bool + // + inline bool getAsBool() const; + +#ifndef _VECTORMATH_NO_SCALAR_CAST + // Implicit cast to bool + // + inline operator bool() const; +#endif + + // Boolean negation operator + // + inline const boolInVec operator ! () const; + + // Assignment operator + // + inline boolInVec& operator = (boolInVec vec); + + // Boolean and assignment operator + // + inline boolInVec& operator &= (boolInVec vec); + + // Boolean exclusive or assignment operator + // + inline boolInVec& operator ^= (boolInVec vec); + + // Boolean or assignment operator + // + inline boolInVec& operator |= (boolInVec vec); + +}; + +// Equal operator +// +inline const boolInVec operator == (boolInVec vec0, boolInVec vec1); + +// Not equal operator +// +inline const boolInVec operator != (boolInVec vec0, boolInVec vec1); + +// And operator +// +inline const boolInVec operator & (boolInVec vec0, boolInVec vec1); + +// Exclusive or operator +// +inline const boolInVec operator ^ (boolInVec vec0, boolInVec vec1); + +// Or operator +// +inline const boolInVec operator | (boolInVec vec0, boolInVec vec1); + +// Conditionally select between two values +// +inline const boolInVec select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1); + + +} // namespace Vectormath + + +//-------------------------------------------------------------------------------------------------- +// boolInVec implementation +// + +#include "floatInVec.h" + +namespace Vectormath { + +inline +boolInVec::boolInVec(floatInVec vec) +{ + *this = (vec != floatInVec(0.0f)); +} + +inline +boolInVec::boolInVec(bool scalar) +{ + mData = -(int)scalar; +} + +inline +bool +boolInVec::getAsBool() const +{ + return (mData > 0); +} + +#ifndef _VECTORMATH_NO_SCALAR_CAST +inline +boolInVec::operator bool() const +{ + return getAsBool(); +} +#endif + +inline +const boolInVec +boolInVec::operator ! () const +{ + return boolInVec(!mData); +} + +inline +boolInVec& +boolInVec::operator = (boolInVec vec) +{ + mData = vec.mData; + return *this; +} + +inline +boolInVec& +boolInVec::operator &= (boolInVec vec) +{ + *this = *this & vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator ^= (boolInVec vec) +{ + *this = *this ^ vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator |= (boolInVec vec) +{ + *this = *this | vec; + return *this; +} + +inline +const boolInVec +operator == (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() == vec1.getAsBool()); +} + +inline +const boolInVec +operator != (boolInVec vec0, boolInVec vec1) +{ + return !(vec0 == vec1); +} + +inline +const boolInVec +operator & (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() & vec1.getAsBool()); +} + +inline +const boolInVec +operator | (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() | vec1.getAsBool()); +} + +inline +const boolInVec +operator ^ (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() ^ vec1.getAsBool()); +} + +inline +const boolInVec +select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1) +{ + return (select_vec1.getAsBool() == 0) ? vec0 : vec1; +} + +} // namespace Vectormath + +#endif // boolInVec_h diff --git a/src/vectormath/scalar/floatInVec.h b/src/vectormath/scalar/floatInVec.h new file mode 100644 index 0000000..12d89e4 --- /dev/null +++ b/src/vectormath/scalar/floatInVec.h @@ -0,0 +1,343 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _FLOATINVEC_H +#define _FLOATINVEC_H + +#include +namespace Vectormath { + +class boolInVec; + +//-------------------------------------------------------------------------------------------------- +// floatInVec class +// + +// A class representing a scalar float value contained in a vector register +// This class does not support fastmath +class floatInVec +{ +private: + float mData; + +public: + // Default constructor; does no initialization + // + inline floatInVec( ) { }; + + // Construct from a value converted from bool + // + inline floatInVec(boolInVec vec); + + // Explicit cast from float + // + explicit inline floatInVec(float scalar); + + // Explicit cast to float + // + inline float getAsFloat() const; + +#ifndef _VECTORMATH_NO_SCALAR_CAST + // Implicit cast to float + // + inline operator float() const; +#endif + + // Post increment (add 1.0f) + // + inline const floatInVec operator ++ (int); + + // Post decrement (subtract 1.0f) + // + inline const floatInVec operator -- (int); + + // Pre increment (add 1.0f) + // + inline floatInVec& operator ++ (); + + // Pre decrement (subtract 1.0f) + // + inline floatInVec& operator -- (); + + // Negation operator + // + inline const floatInVec operator - () const; + + // Assignment operator + // + inline floatInVec& operator = (floatInVec vec); + + // Multiplication assignment operator + // + inline floatInVec& operator *= (floatInVec vec); + + // Division assignment operator + // + inline floatInVec& operator /= (floatInVec vec); + + // Addition assignment operator + // + inline floatInVec& operator += (floatInVec vec); + + // Subtraction assignment operator + // + inline floatInVec& operator -= (floatInVec vec); + +}; + +// Multiplication operator +// +inline const floatInVec operator * (floatInVec vec0, floatInVec vec1); + +// Division operator +// +inline const floatInVec operator / (floatInVec vec0, floatInVec vec1); + +// Addition operator +// +inline const floatInVec operator + (floatInVec vec0, floatInVec vec1); + +// Subtraction operator +// +inline const floatInVec operator - (floatInVec vec0, floatInVec vec1); + +// Less than operator +// +inline const boolInVec operator < (floatInVec vec0, floatInVec vec1); + +// Less than or equal operator +// +inline const boolInVec operator <= (floatInVec vec0, floatInVec vec1); + +// Greater than operator +// +inline const boolInVec operator > (floatInVec vec0, floatInVec vec1); + +// Greater than or equal operator +// +inline const boolInVec operator >= (floatInVec vec0, floatInVec vec1); + +// Equal operator +// +inline const boolInVec operator == (floatInVec vec0, floatInVec vec1); + +// Not equal operator +// +inline const boolInVec operator != (floatInVec vec0, floatInVec vec1); + +// Conditionally select between two values +// +inline const floatInVec select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1); + + +} // namespace Vectormath + + +//-------------------------------------------------------------------------------------------------- +// floatInVec implementation +// + +#include "boolInVec.h" + +namespace Vectormath { + +inline +floatInVec::floatInVec(boolInVec vec) +{ + mData = float(vec.getAsBool()); +} + +inline +floatInVec::floatInVec(float scalar) +{ + mData = scalar; +} + +inline +float +floatInVec::getAsFloat() const +{ + return mData; +} + +#ifndef _VECTORMATH_NO_SCALAR_CAST +inline +floatInVec::operator float() const +{ + return getAsFloat(); +} +#endif + +inline +const floatInVec +floatInVec::operator ++ (int) +{ + float olddata = mData; + operator ++(); + return floatInVec(olddata); +} + +inline +const floatInVec +floatInVec::operator -- (int) +{ + float olddata = mData; + operator --(); + return floatInVec(olddata); +} + +inline +floatInVec& +floatInVec::operator ++ () +{ + *this += floatInVec(1.0f); + return *this; +} + +inline +floatInVec& +floatInVec::operator -- () +{ + *this -= floatInVec(1.0f); + return *this; +} + +inline +const floatInVec +floatInVec::operator - () const +{ + return floatInVec(-mData); +} + +inline +floatInVec& +floatInVec::operator = (floatInVec vec) +{ + mData = vec.mData; + return *this; +} + +inline +floatInVec& +floatInVec::operator *= (floatInVec vec) +{ + *this = *this * vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator /= (floatInVec vec) +{ + *this = *this / vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator += (floatInVec vec) +{ + *this = *this + vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator -= (floatInVec vec) +{ + *this = *this - vec; + return *this; +} + +inline +const floatInVec +operator * (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() * vec1.getAsFloat()); +} + +inline +const floatInVec +operator / (floatInVec num, floatInVec den) +{ + return floatInVec(num.getAsFloat() / den.getAsFloat()); +} + +inline +const floatInVec +operator + (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() + vec1.getAsFloat()); +} + +inline +const floatInVec +operator - (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() - vec1.getAsFloat()); +} + +inline +const boolInVec +operator < (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() < vec1.getAsFloat()); +} + +inline +const boolInVec +operator <= (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 > vec1); +} + +inline +const boolInVec +operator > (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() > vec1.getAsFloat()); +} + +inline +const boolInVec +operator >= (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 < vec1); +} + +inline +const boolInVec +operator == (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() == vec1.getAsFloat()); +} + +inline +const boolInVec +operator != (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 == vec1); +} + +inline +const floatInVec +select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1) +{ + return (select_vec1.getAsBool() == 0) ? vec0 : vec1; +} + +} // namespace Vectormath + +#endif // floatInVec_h diff --git a/src/vectormath/scalar/mat_aos.h b/src/vectormath/scalar/mat_aos.h new file mode 100644 index 0000000..e103243 --- /dev/null +++ b/src/vectormath/scalar/mat_aos.h @@ -0,0 +1,1630 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _VECTORMATH_MAT_AOS_CPP_H +#define _VECTORMATH_MAT_AOS_CPP_H + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// Constants + +#define _VECTORMATH_PI_OVER_2 1.570796327f + +//----------------------------------------------------------------------------- +// Definitions + +inline Matrix3::Matrix3( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; +} + +inline Matrix3::Matrix3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +inline Matrix3::Matrix3( const Quat & unitQuat ) +{ + float qx, qy, qz, qw, qx2, qy2, qz2, qxqx2, qyqy2, qzqz2, qxqy2, qyqz2, qzqw2, qxqz2, qyqw2, qxqw2; + qx = unitQuat.getX(); + qy = unitQuat.getY(); + qz = unitQuat.getZ(); + qw = unitQuat.getW(); + qx2 = ( qx + qx ); + qy2 = ( qy + qy ); + qz2 = ( qz + qz ); + qxqx2 = ( qx * qx2 ); + qxqy2 = ( qx * qy2 ); + qxqz2 = ( qx * qz2 ); + qxqw2 = ( qw * qx2 ); + qyqy2 = ( qy * qy2 ); + qyqz2 = ( qy * qz2 ); + qyqw2 = ( qw * qy2 ); + qzqz2 = ( qz * qz2 ); + qzqw2 = ( qw * qz2 ); + mCol0 = Vector3( ( ( 1.0f - qyqy2 ) - qzqz2 ), ( qxqy2 + qzqw2 ), ( qxqz2 - qyqw2 ) ); + mCol1 = Vector3( ( qxqy2 - qzqw2 ), ( ( 1.0f - qxqx2 ) - qzqz2 ), ( qyqz2 + qxqw2 ) ); + mCol2 = Vector3( ( qxqz2 + qyqw2 ), ( qyqz2 - qxqw2 ), ( ( 1.0f - qxqx2 ) - qyqy2 ) ); +} + +inline Matrix3::Matrix3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; +} + +inline Matrix3 & Matrix3::setCol0( const Vector3 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix3 & Matrix3::setCol1( const Vector3 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix3 & Matrix3::setCol2( const Vector3 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix3 & Matrix3::setCol( int col, const Vector3 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix3 & Matrix3::setRow( int row, const Vector3 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + return *this; +} + +inline Matrix3 & Matrix3::setElem( int col, int row, float val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Matrix3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Matrix3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Matrix3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Matrix3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Matrix3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::getRow( int row ) const +{ + return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); +} + +inline Vector3 & Matrix3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix3 & Matrix3::operator =( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + return *this; +} + +inline const Matrix3 transpose( const Matrix3 & mat ) +{ + return Matrix3( + Vector3( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX() ), + Vector3( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY() ), + Vector3( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ() ) + ); +} + +inline const Matrix3 inverse( const Matrix3 & mat ) +{ + Vector3 tmp0, tmp1, tmp2; + float detinv; + tmp0 = cross( mat.getCol1(), mat.getCol2() ); + tmp1 = cross( mat.getCol2(), mat.getCol0() ); + tmp2 = cross( mat.getCol0(), mat.getCol1() ); + detinv = ( 1.0f / dot( mat.getCol2(), tmp2 ) ); + return Matrix3( + Vector3( ( tmp0.getX() * detinv ), ( tmp1.getX() * detinv ), ( tmp2.getX() * detinv ) ), + Vector3( ( tmp0.getY() * detinv ), ( tmp1.getY() * detinv ), ( tmp2.getY() * detinv ) ), + Vector3( ( tmp0.getZ() * detinv ), ( tmp1.getZ() * detinv ), ( tmp2.getZ() * detinv ) ) + ); +} + +inline float determinant( const Matrix3 & mat ) +{ + return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); +} + +inline const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ) + ); +} + +inline const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix3 Matrix3::operator -( ) const +{ + return Matrix3( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ) + ); +} + +inline const Matrix3 absPerElem( const Matrix3 & mat ) +{ + return Matrix3( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::operator *( float scalar ) const +{ + return Matrix3( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ) + ); +} + +inline Matrix3 & Matrix3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix3 operator *( float scalar, const Matrix3 & mat ) +{ + return mat * scalar; +} + +inline const Vector3 Matrix3::operator *( const Vector3 & vec ) const +{ + return Vector3( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ); +} + +inline const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const +{ + return Matrix3( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) +{ + return Matrix3( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::identity( ) +{ + return Matrix3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3::xAxis( ), + Vector3( 0.0f, c, s ), + Vector3( 0.0f, -s, c ) + ); +} + +inline const Matrix3 Matrix3::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3( c, 0.0f, -s ), + Vector3::yAxis( ), + Vector3( s, 0.0f, c ) + ); +} + +inline const Matrix3 Matrix3::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3( c, s, 0.0f ), + Vector3( -s, c, 0.0f ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Matrix3( + Vector3( ( cZ * cY ), ( sZ * cY ), -sY ), + Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ), + Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( float radians, const Vector3 & unitVec ) +{ + float x, y, z, s, c, oneMinusC, xy, yz, zx; + s = sinf( radians ); + c = cosf( radians ); + x = unitVec.getX(); + y = unitVec.getY(); + z = unitVec.getZ(); + xy = ( x * y ); + yz = ( y * z ); + zx = ( z * x ); + oneMinusC = ( 1.0f - c ); + return Matrix3( + Vector3( ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ) ), + Vector3( ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ) ), + Vector3( ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( const Quat & unitQuat ) +{ + return Matrix3( unitQuat ); +} + +inline const Matrix3 Matrix3::scale( const Vector3 & scaleVec ) +{ + return Matrix3( + Vector3( scaleVec.getX(), 0.0f, 0.0f ), + Vector3( 0.0f, scaleVec.getY(), 0.0f ), + Vector3( 0.0f, 0.0f, scaleVec.getZ() ) + ); +} + +inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ) +{ + return Matrix3( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ) + ); +} + +inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ) +{ + return Matrix3( + mulPerElem( mat.getCol0(), scaleVec ), + mulPerElem( mat.getCol1(), scaleVec ), + mulPerElem( mat.getCol2(), scaleVec ) + ); +} + +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix3 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); +} + +inline void print( const Matrix3 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Matrix4::Matrix4( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; +} + +inline Matrix4::Matrix4( float scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +inline Matrix4::Matrix4( const Transform3 & mat ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( mat.getCol3(), 1.0f ); +} + +inline Matrix4::Matrix4( const Vector4 & _col0, const Vector4 & _col1, const Vector4 & _col2, const Vector4 & _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Matrix4::Matrix4( const Matrix3 & mat, const Vector3 & translateVec ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +inline Matrix4::Matrix4( const Quat & unitQuat, const Vector3 & translateVec ) +{ + Matrix3 mat; + mat = Matrix3( unitQuat ); + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +inline Matrix4 & Matrix4::setCol0( const Vector4 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix4 & Matrix4::setCol1( const Vector4 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix4 & Matrix4::setCol2( const Vector4 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix4 & Matrix4::setCol3( const Vector4 & _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Matrix4 & Matrix4::setCol( int col, const Vector4 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix4 & Matrix4::setRow( int row, const Vector4 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Matrix4 & Matrix4::setElem( int col, int row, float val ) +{ + Vector4 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Matrix4::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector4 Matrix4::getCol0( ) const +{ + return mCol0; +} + +inline const Vector4 Matrix4::getCol1( ) const +{ + return mCol1; +} + +inline const Vector4 Matrix4::getCol2( ) const +{ + return mCol2; +} + +inline const Vector4 Matrix4::getCol3( ) const +{ + return mCol3; +} + +inline const Vector4 Matrix4::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector4 & Matrix4::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix4 & Matrix4::operator =( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; + return *this; +} + +inline const Matrix4 transpose( const Matrix4 & mat ) +{ + return Matrix4( + Vector4( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX(), mat.getCol3().getX() ), + Vector4( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY(), mat.getCol3().getY() ), + Vector4( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ(), mat.getCol3().getZ() ), + Vector4( mat.getCol0().getW(), mat.getCol1().getW(), mat.getCol2().getW(), mat.getCol3().getW() ) + ); +} + +inline const Matrix4 inverse( const Matrix4 & mat ) +{ + Vector4 res0, res1, res2, res3; + float mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, detInv; + mA = mat.getCol0().getX(); + mB = mat.getCol0().getY(); + mC = mat.getCol0().getZ(); + mD = mat.getCol0().getW(); + mE = mat.getCol1().getX(); + mF = mat.getCol1().getY(); + mG = mat.getCol1().getZ(); + mH = mat.getCol1().getW(); + mI = mat.getCol2().getX(); + mJ = mat.getCol2().getY(); + mK = mat.getCol2().getZ(); + mL = mat.getCol2().getW(); + mM = mat.getCol3().getX(); + mN = mat.getCol3().getY(); + mO = mat.getCol3().getZ(); + mP = mat.getCol3().getW(); + tmp0 = ( ( mK * mD ) - ( mC * mL ) ); + tmp1 = ( ( mO * mH ) - ( mG * mP ) ); + tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); + tmp3 = ( ( mF * mO ) - ( mN * mG ) ); + tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); + tmp5 = ( ( mN * mH ) - ( mF * mP ) ); + res0.setX( ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ) ); + res0.setY( ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ) ); + res0.setZ( ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ) ); + res0.setW( ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ) ); + detInv = ( 1.0f / ( ( ( ( mA * res0.getX() ) + ( mE * res0.getY() ) ) + ( mI * res0.getZ() ) ) + ( mM * res0.getW() ) ) ); + res1.setX( ( mI * tmp1 ) ); + res1.setY( ( mM * tmp0 ) ); + res1.setZ( ( mA * tmp1 ) ); + res1.setW( ( mE * tmp0 ) ); + res3.setX( ( mI * tmp3 ) ); + res3.setY( ( mM * tmp2 ) ); + res3.setZ( ( mA * tmp3 ) ); + res3.setW( ( mE * tmp2 ) ); + res2.setX( ( mI * tmp5 ) ); + res2.setY( ( mM * tmp4 ) ); + res2.setZ( ( mA * tmp5 ) ); + res2.setW( ( mE * tmp4 ) ); + tmp0 = ( ( mI * mB ) - ( mA * mJ ) ); + tmp1 = ( ( mM * mF ) - ( mE * mN ) ); + tmp2 = ( ( mI * mD ) - ( mA * mL ) ); + tmp3 = ( ( mM * mH ) - ( mE * mP ) ); + tmp4 = ( ( mI * mC ) - ( mA * mK ) ); + tmp5 = ( ( mM * mG ) - ( mE * mO ) ); + res2.setX( ( ( ( mL * tmp1 ) - ( mJ * tmp3 ) ) + res2.getX() ) ); + res2.setY( ( ( ( mP * tmp0 ) - ( mN * tmp2 ) ) + res2.getY() ) ); + res2.setZ( ( ( ( mB * tmp3 ) - ( mD * tmp1 ) ) - res2.getZ() ) ); + res2.setW( ( ( ( mF * tmp2 ) - ( mH * tmp0 ) ) - res2.getW() ) ); + res3.setX( ( ( ( mJ * tmp5 ) - ( mK * tmp1 ) ) + res3.getX() ) ); + res3.setY( ( ( ( mN * tmp4 ) - ( mO * tmp0 ) ) + res3.getY() ) ); + res3.setZ( ( ( ( mC * tmp1 ) - ( mB * tmp5 ) ) - res3.getZ() ) ); + res3.setW( ( ( ( mG * tmp0 ) - ( mF * tmp4 ) ) - res3.getW() ) ); + res1.setX( ( ( ( mK * tmp3 ) - ( mL * tmp5 ) ) - res1.getX() ) ); + res1.setY( ( ( ( mO * tmp2 ) - ( mP * tmp4 ) ) - res1.getY() ) ); + res1.setZ( ( ( ( mD * tmp5 ) - ( mC * tmp3 ) ) + res1.getZ() ) ); + res1.setW( ( ( ( mH * tmp4 ) - ( mG * tmp2 ) ) + res1.getW() ) ); + return Matrix4( + ( res0 * detInv ), + ( res1 * detInv ), + ( res2 * detInv ), + ( res3 * detInv ) + ); +} + +inline const Matrix4 affineInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( inverse( affineMat ) ); +} + +inline const Matrix4 orthoInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( orthoInverse( affineMat ) ); +} + +inline float determinant( const Matrix4 & mat ) +{ + float dx, dy, dz, dw, mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + mA = mat.getCol0().getX(); + mB = mat.getCol0().getY(); + mC = mat.getCol0().getZ(); + mD = mat.getCol0().getW(); + mE = mat.getCol1().getX(); + mF = mat.getCol1().getY(); + mG = mat.getCol1().getZ(); + mH = mat.getCol1().getW(); + mI = mat.getCol2().getX(); + mJ = mat.getCol2().getY(); + mK = mat.getCol2().getZ(); + mL = mat.getCol2().getW(); + mM = mat.getCol3().getX(); + mN = mat.getCol3().getY(); + mO = mat.getCol3().getZ(); + mP = mat.getCol3().getW(); + tmp0 = ( ( mK * mD ) - ( mC * mL ) ); + tmp1 = ( ( mO * mH ) - ( mG * mP ) ); + tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); + tmp3 = ( ( mF * mO ) - ( mN * mG ) ); + tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); + tmp5 = ( ( mN * mH ) - ( mF * mP ) ); + dx = ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ); + dy = ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ); + dz = ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ); + dw = ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ); + return ( ( ( ( mA * dx ) + ( mE * dy ) ) + ( mI * dz ) ) + ( mM * dw ) ); +} + +inline const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ), + ( mCol3 + mat.mCol3 ) + ); +} + +inline const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ), + ( mCol3 - mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix4 Matrix4::operator -( ) const +{ + return Matrix4( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ), + ( -mCol3 ) + ); +} + +inline const Matrix4 absPerElem( const Matrix4 & mat ) +{ + return Matrix4( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ), + absPerElem( mat.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::operator *( float scalar ) const +{ + return Matrix4( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ), + ( mCol3 * scalar ) + ); +} + +inline Matrix4 & Matrix4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix4 operator *( float scalar, const Matrix4 & mat ) +{ + return mat * scalar; +} + +inline const Vector4 Matrix4::operator *( const Vector4 & vec ) const +{ + return Vector4( + ( ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ) + ( mCol3.getX() * vec.getW() ) ), + ( ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ) + ( mCol3.getY() * vec.getW() ) ), + ( ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ( mCol3.getZ() * vec.getW() ) ), + ( ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) + ( mCol3.getW() * vec.getW() ) ) + ); +} + +inline const Vector4 Matrix4::operator *( const Vector3 & vec ) const +{ + return Vector4( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ), + ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) + ); +} + +inline const Vector4 Matrix4::operator *( const Point3 & pnt ) const +{ + return Vector4( + ( ( ( ( mCol0.getX() * pnt.getX() ) + ( mCol1.getX() * pnt.getY() ) ) + ( mCol2.getX() * pnt.getZ() ) ) + mCol3.getX() ), + ( ( ( ( mCol0.getY() * pnt.getX() ) + ( mCol1.getY() * pnt.getY() ) ) + ( mCol2.getY() * pnt.getZ() ) ) + mCol3.getY() ), + ( ( ( ( mCol0.getZ() * pnt.getX() ) + ( mCol1.getZ() * pnt.getY() ) ) + ( mCol2.getZ() * pnt.getZ() ) ) + mCol3.getZ() ), + ( ( ( ( mCol0.getW() * pnt.getX() ) + ( mCol1.getW() * pnt.getY() ) ) + ( mCol2.getW() * pnt.getZ() ) ) + mCol3.getW() ) + ); +} + +inline const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const +{ + return Matrix4( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ), + ( *this * mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const +{ + return Matrix4( + ( *this * tfrm.getCol0() ), + ( *this * tfrm.getCol1() ), + ( *this * tfrm.getCol2() ), + ( *this * Point3( tfrm.getCol3() ) ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) +{ + return Matrix4( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ), + mulPerElem( mat0.getCol3(), mat1.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::identity( ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) +{ + mCol0.setXYZ( mat3.getCol0() ); + mCol1.setXYZ( mat3.getCol1() ); + mCol2.setXYZ( mat3.getCol2() ); + return *this; +} + +inline const Matrix3 Matrix4::getUpper3x3( ) const +{ + return Matrix3( + mCol0.getXYZ( ), + mCol1.getXYZ( ), + mCol2.getXYZ( ) + ); +} + +inline Matrix4 & Matrix4::setTranslation( const Vector3 & translateVec ) +{ + mCol3.setXYZ( translateVec ); + return *this; +} + +inline const Vector3 Matrix4::getTranslation( ) const +{ + return mCol3.getXYZ( ); +} + +inline const Matrix4 Matrix4::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4::xAxis( ), + Vector4( 0.0f, c, s, 0.0f ), + Vector4( 0.0f, -s, c, 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4( c, 0.0f, -s, 0.0f ), + Vector4::yAxis( ), + Vector4( s, 0.0f, c, 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4( c, s, 0.0f, 0.0f ), + Vector4( -s, c, 0.0f, 0.0f ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Matrix4( + Vector4( ( cZ * cY ), ( sZ * cY ), -sY, 0.0f ), + Vector4( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ), 0.0f ), + Vector4( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( float radians, const Vector3 & unitVec ) +{ + float x, y, z, s, c, oneMinusC, xy, yz, zx; + s = sinf( radians ); + c = cosf( radians ); + x = unitVec.getX(); + y = unitVec.getY(); + z = unitVec.getZ(); + xy = ( x * y ); + yz = ( y * z ); + zx = ( z * x ); + oneMinusC = ( 1.0f - c ); + return Matrix4( + Vector4( ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ), 0.0f ), + Vector4( ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ), 0.0f ), + Vector4( ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( const Quat & unitQuat ) +{ + return Matrix4( Transform3::rotation( unitQuat ) ); +} + +inline const Matrix4 Matrix4::scale( const Vector3 & scaleVec ) +{ + return Matrix4( + Vector4( scaleVec.getX(), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, scaleVec.getY(), 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, scaleVec.getZ(), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ) +{ + return Matrix4( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ), + mat.getCol3() + ); +} + +inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ) +{ + Vector4 scale4; + scale4 = Vector4( scaleVec, 1.0f ); + return Matrix4( + mulPerElem( mat.getCol0(), scale4 ), + mulPerElem( mat.getCol1(), scale4 ), + mulPerElem( mat.getCol2(), scale4 ), + mulPerElem( mat.getCol3(), scale4 ) + ); +} + +inline const Matrix4 Matrix4::translation( const Vector3 & translateVec ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4( translateVec, 1.0f ) + ); +} + +inline const Matrix4 Matrix4::lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ) +{ + Matrix4 m4EyeFrame; + Vector3 v3X, v3Y, v3Z; + v3Y = normalize( upVec ); + v3Z = normalize( ( eyePos - lookAtPos ) ); + v3X = normalize( cross( v3Y, v3Z ) ); + v3Y = cross( v3Z, v3X ); + m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); + return orthoInverse( m4EyeFrame ); +} + +inline const Matrix4 Matrix4::perspective( float fovyRadians, float aspect, float zNear, float zFar ) +{ + float f, rangeInv; + f = tanf( ( (float)( _VECTORMATH_PI_OVER_2 ) - ( 0.5f * fovyRadians ) ) ); + rangeInv = ( 1.0f / ( zNear - zFar ) ); + return Matrix4( + Vector4( ( f / aspect ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, f, 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, ( ( zNear + zFar ) * rangeInv ), -1.0f ), + Vector4( 0.0f, 0.0f, ( ( ( zNear * zFar ) * rangeInv ) * 2.0f ), 0.0f ) + ); +} + +inline const Matrix4 Matrix4::frustum( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf, n2; + sum_rl = ( right + left ); + sum_tb = ( top + bottom ); + sum_nf = ( zNear + zFar ); + inv_rl = ( 1.0f / ( right - left ) ); + inv_tb = ( 1.0f / ( top - bottom ) ); + inv_nf = ( 1.0f / ( zNear - zFar ) ); + n2 = ( zNear + zNear ); + return Matrix4( + Vector4( ( n2 * inv_rl ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, ( n2 * inv_tb ), 0.0f, 0.0f ), + Vector4( ( sum_rl * inv_rl ), ( sum_tb * inv_tb ), ( sum_nf * inv_nf ), -1.0f ), + Vector4( 0.0f, 0.0f, ( ( n2 * inv_nf ) * zFar ), 0.0f ) + ); +} + +inline const Matrix4 Matrix4::orthographic( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf; + sum_rl = ( right + left ); + sum_tb = ( top + bottom ); + sum_nf = ( zNear + zFar ); + inv_rl = ( 1.0f / ( right - left ) ); + inv_tb = ( 1.0f / ( top - bottom ) ); + inv_nf = ( 1.0f / ( zNear - zFar ) ); + return Matrix4( + Vector4( ( inv_rl + inv_rl ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, ( inv_tb + inv_tb ), 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, ( inv_nf + inv_nf ), 0.0f ), + Vector4( ( -sum_rl * inv_rl ), ( -sum_tb * inv_tb ), ( sum_nf * inv_nf ), 1.0f ) + ); +} + +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix4 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); + print( mat.getRow( 3 ) ); +} + +inline void print( const Matrix4 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Transform3::Transform3( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; +} + +inline Transform3::Transform3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +inline Transform3::Transform3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2, const Vector3 & _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Transform3::Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ) +{ + this->setUpper3x3( tfrm ); + this->setTranslation( translateVec ); +} + +inline Transform3::Transform3( const Quat & unitQuat, const Vector3 & translateVec ) +{ + this->setUpper3x3( Matrix3( unitQuat ) ); + this->setTranslation( translateVec ); +} + +inline Transform3 & Transform3::setCol0( const Vector3 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Transform3 & Transform3::setCol1( const Vector3 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Transform3 & Transform3::setCol2( const Vector3 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Transform3 & Transform3::setCol3( const Vector3 & _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Transform3 & Transform3::setCol( int col, const Vector3 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Transform3 & Transform3::setRow( int row, const Vector4 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Transform3 & Transform3::setElem( int col, int row, float val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Transform3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Transform3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Transform3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Transform3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Transform3::getCol3( ) const +{ + return mCol3; +} + +inline const Vector3 Transform3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Transform3::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector3 & Transform3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Transform3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Transform3 & Transform3::operator =( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; + return *this; +} + +inline const Transform3 inverse( const Transform3 & tfrm ) +{ + Vector3 tmp0, tmp1, tmp2, inv0, inv1, inv2; + float detinv; + tmp0 = cross( tfrm.getCol1(), tfrm.getCol2() ); + tmp1 = cross( tfrm.getCol2(), tfrm.getCol0() ); + tmp2 = cross( tfrm.getCol0(), tfrm.getCol1() ); + detinv = ( 1.0f / dot( tfrm.getCol2(), tmp2 ) ); + inv0 = Vector3( ( tmp0.getX() * detinv ), ( tmp1.getX() * detinv ), ( tmp2.getX() * detinv ) ); + inv1 = Vector3( ( tmp0.getY() * detinv ), ( tmp1.getY() * detinv ), ( tmp2.getY() * detinv ) ); + inv2 = Vector3( ( tmp0.getZ() * detinv ), ( tmp1.getZ() * detinv ), ( tmp2.getZ() * detinv ) ); + return Transform3( + inv0, + inv1, + inv2, + Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) + ); +} + +inline const Transform3 orthoInverse( const Transform3 & tfrm ) +{ + Vector3 inv0, inv1, inv2; + inv0 = Vector3( tfrm.getCol0().getX(), tfrm.getCol1().getX(), tfrm.getCol2().getX() ); + inv1 = Vector3( tfrm.getCol0().getY(), tfrm.getCol1().getY(), tfrm.getCol2().getY() ); + inv2 = Vector3( tfrm.getCol0().getZ(), tfrm.getCol1().getZ(), tfrm.getCol2().getZ() ); + return Transform3( + inv0, + inv1, + inv2, + Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) + ); +} + +inline const Transform3 absPerElem( const Transform3 & tfrm ) +{ + return Transform3( + absPerElem( tfrm.getCol0() ), + absPerElem( tfrm.getCol1() ), + absPerElem( tfrm.getCol2() ), + absPerElem( tfrm.getCol3() ) + ); +} + +inline const Vector3 Transform3::operator *( const Vector3 & vec ) const +{ + return Vector3( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ); +} + +inline const Point3 Transform3::operator *( const Point3 & pnt ) const +{ + return Point3( + ( ( ( ( mCol0.getX() * pnt.getX() ) + ( mCol1.getX() * pnt.getY() ) ) + ( mCol2.getX() * pnt.getZ() ) ) + mCol3.getX() ), + ( ( ( ( mCol0.getY() * pnt.getX() ) + ( mCol1.getY() * pnt.getY() ) ) + ( mCol2.getY() * pnt.getZ() ) ) + mCol3.getY() ), + ( ( ( ( mCol0.getZ() * pnt.getX() ) + ( mCol1.getZ() * pnt.getY() ) ) + ( mCol2.getZ() * pnt.getZ() ) ) + mCol3.getZ() ) + ); +} + +inline const Transform3 Transform3::operator *( const Transform3 & tfrm ) const +{ + return Transform3( + ( *this * tfrm.mCol0 ), + ( *this * tfrm.mCol1 ), + ( *this * tfrm.mCol2 ), + Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) + ); +} + +inline Transform3 & Transform3::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) +{ + return Transform3( + mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), + mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), + mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), + mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) + ); +} + +inline const Transform3 Transform3::identity( ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +inline Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) +{ + mCol0 = tfrm.getCol0(); + mCol1 = tfrm.getCol1(); + mCol2 = tfrm.getCol2(); + return *this; +} + +inline const Matrix3 Transform3::getUpper3x3( ) const +{ + return Matrix3( mCol0, mCol1, mCol2 ); +} + +inline Transform3 & Transform3::setTranslation( const Vector3 & translateVec ) +{ + mCol3 = translateVec; + return *this; +} + +inline const Vector3 Transform3::getTranslation( ) const +{ + return mCol3; +} + +inline const Transform3 Transform3::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3::xAxis( ), + Vector3( 0.0f, c, s ), + Vector3( 0.0f, -s, c ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3( c, 0.0f, -s ), + Vector3::yAxis( ), + Vector3( s, 0.0f, c ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3( c, s, 0.0f ), + Vector3( -s, c, 0.0f ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Transform3( + Vector3( ( cZ * cY ), ( sZ * cY ), -sY ), + Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ), + Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotation( float radians, const Vector3 & unitVec ) +{ + return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( 0.0f ) ); +} + +inline const Transform3 Transform3::rotation( const Quat & unitQuat ) +{ + return Transform3( Matrix3( unitQuat ), Vector3( 0.0f ) ); +} + +inline const Transform3 Transform3::scale( const Vector3 & scaleVec ) +{ + return Transform3( + Vector3( scaleVec.getX(), 0.0f, 0.0f ), + Vector3( 0.0f, scaleVec.getY(), 0.0f ), + Vector3( 0.0f, 0.0f, scaleVec.getZ() ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ) +{ + return Transform3( + ( tfrm.getCol0() * scaleVec.getX( ) ), + ( tfrm.getCol1() * scaleVec.getY( ) ), + ( tfrm.getCol2() * scaleVec.getZ( ) ), + tfrm.getCol3() + ); +} + +inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ) +{ + return Transform3( + mulPerElem( tfrm.getCol0(), scaleVec ), + mulPerElem( tfrm.getCol1(), scaleVec ), + mulPerElem( tfrm.getCol2(), scaleVec ), + mulPerElem( tfrm.getCol3(), scaleVec ) + ); +} + +inline const Transform3 Transform3::translation( const Vector3 & translateVec ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + translateVec + ); +} + +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Transform3 & tfrm ) +{ + print( tfrm.getRow( 0 ) ); + print( tfrm.getRow( 1 ) ); + print( tfrm.getRow( 2 ) ); +} + +inline void print( const Transform3 & tfrm, const char * name ) +{ + printf("%s:\n", name); + print( tfrm ); +} + +#endif + +inline Quat::Quat( const Matrix3 & tfrm ) +{ + float trace, radicand, scale, xx, yx, zx, xy, yy, zy, xz, yz, zz, tmpx, tmpy, tmpz, tmpw, qx, qy, qz, qw; + int negTrace, ZgtX, ZgtY, YgtX; + int largestXorY, largestYorZ, largestZorX; + + xx = tfrm.getCol0().getX(); + yx = tfrm.getCol0().getY(); + zx = tfrm.getCol0().getZ(); + xy = tfrm.getCol1().getX(); + yy = tfrm.getCol1().getY(); + zy = tfrm.getCol1().getZ(); + xz = tfrm.getCol2().getX(); + yz = tfrm.getCol2().getY(); + zz = tfrm.getCol2().getZ(); + + trace = ( ( xx + yy ) + zz ); + + negTrace = ( trace < 0.0f ); + ZgtX = zz > xx; + ZgtY = zz > yy; + YgtX = yy > xx; + largestXorY = ( !ZgtX || !ZgtY ) && negTrace; + largestYorZ = ( YgtX || ZgtX ) && negTrace; + largestZorX = ( ZgtY || !YgtX ) && negTrace; + + if ( largestXorY ) + { + zz = -zz; + xy = -xy; + } + if ( largestYorZ ) + { + xx = -xx; + yz = -yz; + } + if ( largestZorX ) + { + yy = -yy; + zx = -zx; + } + + radicand = ( ( ( xx + yy ) + zz ) + 1.0f ); + scale = ( 0.5f * ( 1.0f / sqrtf( radicand ) ) ); + + tmpx = ( ( zy - yz ) * scale ); + tmpy = ( ( xz - zx ) * scale ); + tmpz = ( ( yx - xy ) * scale ); + tmpw = ( radicand * scale ); + qx = tmpx; + qy = tmpy; + qz = tmpz; + qw = tmpw; + + if ( largestXorY ) + { + qx = tmpw; + qy = tmpz; + qz = tmpy; + qw = tmpx; + } + if ( largestYorZ ) + { + tmpx = qx; + tmpz = qz; + qx = qy; + qy = tmpx; + qz = qw; + qw = tmpz; + } + + mX = qx; + mY = qy; + mZ = qz; + mW = qw; +} + +inline const Matrix3 outer( const Vector3 & tfrm0, const Vector3 & tfrm1 ) +{ + return Matrix3( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ) + ); +} + +inline const Matrix4 outer( const Vector4 & tfrm0, const Vector4 & tfrm1 ) +{ + return Matrix4( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ), + ( tfrm0 * tfrm1.getW( ) ) + ); +} + +inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ) +{ + return Vector3( + ( ( ( vec.getX() * mat.getCol0().getX() ) + ( vec.getY() * mat.getCol0().getY() ) ) + ( vec.getZ() * mat.getCol0().getZ() ) ), + ( ( ( vec.getX() * mat.getCol1().getX() ) + ( vec.getY() * mat.getCol1().getY() ) ) + ( vec.getZ() * mat.getCol1().getZ() ) ), + ( ( ( vec.getX() * mat.getCol2().getX() ) + ( vec.getY() * mat.getCol2().getY() ) ) + ( vec.getZ() * mat.getCol2().getZ() ) ) + ); +} + +inline const Matrix3 crossMatrix( const Vector3 & vec ) +{ + return Matrix3( + Vector3( 0.0f, vec.getZ(), -vec.getY() ), + Vector3( -vec.getZ(), 0.0f, vec.getX() ), + Vector3( vec.getY(), -vec.getX(), 0.0f ) + ); +} + +inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ) +{ + return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); +} + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/src/vectormath/scalar/quat_aos.h b/src/vectormath/scalar/quat_aos.h new file mode 100644 index 0000000..764e017 --- /dev/null +++ b/src/vectormath/scalar/quat_aos.h @@ -0,0 +1,433 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _VECTORMATH_QUAT_AOS_CPP_H +#define _VECTORMATH_QUAT_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +inline Quat::Quat( const Quat & quat ) +{ + mX = quat.mX; + mY = quat.mY; + mZ = quat.mZ; + mW = quat.mW; +} + +inline Quat::Quat( float _x, float _y, float _z, float _w ) +{ + mX = _x; + mY = _y; + mZ = _z; + mW = _w; +} + +inline Quat::Quat( const Vector3 & xyz, float _w ) +{ + this->setXYZ( xyz ); + this->setW( _w ); +} + +inline Quat::Quat( const Vector4 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + mW = vec.getW(); +} + +inline Quat::Quat( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; + mW = scalar; +} + +inline const Quat Quat::identity( ) +{ + return Quat( 0.0f, 0.0f, 0.0f, 1.0f ); +} + +inline const Quat lerp( float t, const Quat & quat0, const Quat & quat1 ) +{ + return ( quat0 + ( ( quat1 - quat0 ) * t ) ); +} + +inline const Quat slerp( float t, const Quat & unitQuat0, const Quat & unitQuat1 ) +{ + Quat start; + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitQuat0, unitQuat1 ); + if ( cosAngle < 0.0f ) { + cosAngle = -cosAngle; + start = ( -unitQuat0 ); + } else { + start = unitQuat0; + } + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( start * scale0 ) + ( unitQuat1 * scale1 ) ); +} + +inline const Quat squad( float t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ) +{ + Quat tmp0, tmp1; + tmp0 = slerp( t, unitQuat0, unitQuat3 ); + tmp1 = slerp( t, unitQuat1, unitQuat2 ); + return slerp( ( ( 2.0f * t ) * ( 1.0f - t ) ), tmp0, tmp1 ); +} + +inline void loadXYZW( Quat & quat, const float * fptr ) +{ + quat = Quat( fptr[0], fptr[1], fptr[2], fptr[3] ); +} + +inline void storeXYZW( const Quat & quat, float * fptr ) +{ + fptr[0] = quat.getX(); + fptr[1] = quat.getY(); + fptr[2] = quat.getZ(); + fptr[3] = quat.getW(); +} + +inline Quat & Quat::operator =( const Quat & quat ) +{ + mX = quat.mX; + mY = quat.mY; + mZ = quat.mZ; + mW = quat.mW; + return *this; +} + +inline Quat & Quat::setXYZ( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + return *this; +} + +inline const Vector3 Quat::getXYZ( ) const +{ + return Vector3( mX, mY, mZ ); +} + +inline Quat & Quat::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Quat::getX( ) const +{ + return mX; +} + +inline Quat & Quat::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Quat::getY( ) const +{ + return mY; +} + +inline Quat & Quat::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Quat::getZ( ) const +{ + return mZ; +} + +inline Quat & Quat::setW( float _w ) +{ + mW = _w; + return *this; +} + +inline float Quat::getW( ) const +{ + return mW; +} + +inline Quat & Quat::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Quat::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Quat::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Quat::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Quat Quat::operator +( const Quat & quat ) const +{ + return Quat( + ( mX + quat.mX ), + ( mY + quat.mY ), + ( mZ + quat.mZ ), + ( mW + quat.mW ) + ); +} + +inline const Quat Quat::operator -( const Quat & quat ) const +{ + return Quat( + ( mX - quat.mX ), + ( mY - quat.mY ), + ( mZ - quat.mZ ), + ( mW - quat.mW ) + ); +} + +inline const Quat Quat::operator *( float scalar ) const +{ + return Quat( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ), + ( mW * scalar ) + ); +} + +inline Quat & Quat::operator +=( const Quat & quat ) +{ + *this = *this + quat; + return *this; +} + +inline Quat & Quat::operator -=( const Quat & quat ) +{ + *this = *this - quat; + return *this; +} + +inline Quat & Quat::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Quat Quat::operator /( float scalar ) const +{ + return Quat( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ), + ( mW / scalar ) + ); +} + +inline Quat & Quat::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Quat Quat::operator -( ) const +{ + return Quat( + -mX, + -mY, + -mZ, + -mW + ); +} + +inline const Quat operator *( float scalar, const Quat & quat ) +{ + return quat * scalar; +} + +inline float dot( const Quat & quat0, const Quat & quat1 ) +{ + float result; + result = ( quat0.getX() * quat1.getX() ); + result = ( result + ( quat0.getY() * quat1.getY() ) ); + result = ( result + ( quat0.getZ() * quat1.getZ() ) ); + result = ( result + ( quat0.getW() * quat1.getW() ) ); + return result; +} + +inline float norm( const Quat & quat ) +{ + float result; + result = ( quat.getX() * quat.getX() ); + result = ( result + ( quat.getY() * quat.getY() ) ); + result = ( result + ( quat.getZ() * quat.getZ() ) ); + result = ( result + ( quat.getW() * quat.getW() ) ); + return result; +} + +inline float length( const Quat & quat ) +{ + return ::sqrtf( norm( quat ) ); +} + +inline const Quat normalize( const Quat & quat ) +{ + float lenSqr, lenInv; + lenSqr = norm( quat ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Quat( + ( quat.getX() * lenInv ), + ( quat.getY() * lenInv ), + ( quat.getZ() * lenInv ), + ( quat.getW() * lenInv ) + ); +} + +inline const Quat Quat::rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ) +{ + float cosHalfAngleX2, recipCosHalfAngleX2; + cosHalfAngleX2 = sqrtf( ( 2.0f * ( 1.0f + dot( unitVec0, unitVec1 ) ) ) ); + recipCosHalfAngleX2 = ( 1.0f / cosHalfAngleX2 ); + return Quat( ( cross( unitVec0, unitVec1 ) * recipCosHalfAngleX2 ), ( cosHalfAngleX2 * 0.5f ) ); +} + +inline const Quat Quat::rotation( float radians, const Vector3 & unitVec ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( ( unitVec * s ), c ); +} + +inline const Quat Quat::rotationX( float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( s, 0.0f, 0.0f, c ); +} + +inline const Quat Quat::rotationY( float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( 0.0f, s, 0.0f, c ); +} + +inline const Quat Quat::rotationZ( float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( 0.0f, 0.0f, s, c ); +} + +inline const Quat Quat::operator *( const Quat & quat ) const +{ + return Quat( + ( ( ( ( mW * quat.mX ) + ( mX * quat.mW ) ) + ( mY * quat.mZ ) ) - ( mZ * quat.mY ) ), + ( ( ( ( mW * quat.mY ) + ( mY * quat.mW ) ) + ( mZ * quat.mX ) ) - ( mX * quat.mZ ) ), + ( ( ( ( mW * quat.mZ ) + ( mZ * quat.mW ) ) + ( mX * quat.mY ) ) - ( mY * quat.mX ) ), + ( ( ( ( mW * quat.mW ) - ( mX * quat.mX ) ) - ( mY * quat.mY ) ) - ( mZ * quat.mZ ) ) + ); +} + +inline Quat & Quat::operator *=( const Quat & quat ) +{ + *this = *this * quat; + return *this; +} + +inline const Vector3 rotate( const Quat & quat, const Vector3 & vec ) +{ + float tmpX, tmpY, tmpZ, tmpW; + tmpX = ( ( ( quat.getW() * vec.getX() ) + ( quat.getY() * vec.getZ() ) ) - ( quat.getZ() * vec.getY() ) ); + tmpY = ( ( ( quat.getW() * vec.getY() ) + ( quat.getZ() * vec.getX() ) ) - ( quat.getX() * vec.getZ() ) ); + tmpZ = ( ( ( quat.getW() * vec.getZ() ) + ( quat.getX() * vec.getY() ) ) - ( quat.getY() * vec.getX() ) ); + tmpW = ( ( ( quat.getX() * vec.getX() ) + ( quat.getY() * vec.getY() ) ) + ( quat.getZ() * vec.getZ() ) ); + return Vector3( + ( ( ( ( tmpW * quat.getX() ) + ( tmpX * quat.getW() ) ) - ( tmpY * quat.getZ() ) ) + ( tmpZ * quat.getY() ) ), + ( ( ( ( tmpW * quat.getY() ) + ( tmpY * quat.getW() ) ) - ( tmpZ * quat.getX() ) ) + ( tmpX * quat.getZ() ) ), + ( ( ( ( tmpW * quat.getZ() ) + ( tmpZ * quat.getW() ) ) - ( tmpX * quat.getY() ) ) + ( tmpY * quat.getX() ) ) + ); +} + +inline const Quat conj( const Quat & quat ) +{ + return Quat( -quat.getX(), -quat.getY(), -quat.getZ(), quat.getW() ); +} + +inline const Quat select( const Quat & quat0, const Quat & quat1, bool select1 ) +{ + return Quat( + ( select1 )? quat1.getX() : quat0.getX(), + ( select1 )? quat1.getY() : quat0.getY(), + ( select1 )? quat1.getZ() : quat0.getZ(), + ( select1 )? quat1.getW() : quat0.getW() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Quat & quat ) +{ + printf( "( %f %f %f %f )\n", quat.getX(), quat.getY(), quat.getZ(), quat.getW() ); +} + +inline void print( const Quat & quat, const char * name ) +{ + printf( "%s: ( %f %f %f %f )\n", name, quat.getX(), quat.getY(), quat.getZ(), quat.getW() ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/src/vectormath/scalar/vec_aos.h b/src/vectormath/scalar/vec_aos.h new file mode 100644 index 0000000..46d4d6b --- /dev/null +++ b/src/vectormath/scalar/vec_aos.h @@ -0,0 +1,1426 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _VECTORMATH_VEC_AOS_CPP_H +#define _VECTORMATH_VEC_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Constants + +#define _VECTORMATH_SLERP_TOL 0.999f + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +inline Vector3::Vector3( const Vector3 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; +} + +inline Vector3::Vector3( float _x, float _y, float _z ) +{ + mX = _x; + mY = _y; + mZ = _z; +} + +inline Vector3::Vector3( const Point3 & pnt ) +{ + mX = pnt.getX(); + mY = pnt.getY(); + mZ = pnt.getZ(); +} + +inline Vector3::Vector3( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; +} + +inline const Vector3 Vector3::xAxis( ) +{ + return Vector3( 1.0f, 0.0f, 0.0f ); +} + +inline const Vector3 Vector3::yAxis( ) +{ + return Vector3( 0.0f, 1.0f, 0.0f ); +} + +inline const Vector3 Vector3::zAxis( ) +{ + return Vector3( 0.0f, 0.0f, 1.0f ); +} + +inline const Vector3 lerp( float t, const Vector3 & vec0, const Vector3 & vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector3 slerp( float t, const Vector3 & unitVec0, const Vector3 & unitVec1 ) +{ + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitVec0, unitVec1 ); + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); +} + +inline void loadXYZ( Vector3 & vec, const float * fptr ) +{ + vec = Vector3( fptr[0], fptr[1], fptr[2] ); +} + +inline void storeXYZ( const Vector3 & vec, float * fptr ) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); +} + +inline void loadHalfFloats( Vector3 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Vector3 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Vector3 & Vector3::operator =( const Vector3 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + return *this; +} + +inline Vector3 & Vector3::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Vector3::getX( ) const +{ + return mX; +} + +inline Vector3 & Vector3::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Vector3::getY( ) const +{ + return mY; +} + +inline Vector3 & Vector3::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Vector3::getZ( ) const +{ + return mZ; +} + +inline Vector3 & Vector3::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Vector3::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Vector3::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Vector3::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector3 Vector3::operator +( const Vector3 & vec ) const +{ + return Vector3( + ( mX + vec.mX ), + ( mY + vec.mY ), + ( mZ + vec.mZ ) + ); +} + +inline const Vector3 Vector3::operator -( const Vector3 & vec ) const +{ + return Vector3( + ( mX - vec.mX ), + ( mY - vec.mY ), + ( mZ - vec.mZ ) + ); +} + +inline const Point3 Vector3::operator +( const Point3 & pnt ) const +{ + return Point3( + ( mX + pnt.getX() ), + ( mY + pnt.getY() ), + ( mZ + pnt.getZ() ) + ); +} + +inline const Vector3 Vector3::operator *( float scalar ) const +{ + return Vector3( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ) + ); +} + +inline Vector3 & Vector3::operator +=( const Vector3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector3 & Vector3::operator -=( const Vector3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector3 & Vector3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector3 Vector3::operator /( float scalar ) const +{ + return Vector3( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ) + ); +} + +inline Vector3 & Vector3::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector3 Vector3::operator -( ) const +{ + return Vector3( + -mX, + -mY, + -mZ + ); +} + +inline const Vector3 operator *( float scalar, const Vector3 & vec ) +{ + return vec * scalar; +} + +inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec0.getX() * vec1.getX() ), + ( vec0.getY() * vec1.getY() ), + ( vec0.getZ() * vec1.getZ() ) + ); +} + +inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec0.getX() / vec1.getX() ), + ( vec0.getY() / vec1.getY() ), + ( vec0.getZ() / vec1.getZ() ) + ); +} + +inline const Vector3 recipPerElem( const Vector3 & vec ) +{ + return Vector3( + ( 1.0f / vec.getX() ), + ( 1.0f / vec.getY() ), + ( 1.0f / vec.getZ() ) + ); +} + +inline const Vector3 sqrtPerElem( const Vector3 & vec ) +{ + return Vector3( + sqrtf( vec.getX() ), + sqrtf( vec.getY() ), + sqrtf( vec.getZ() ) + ); +} + +inline const Vector3 rsqrtPerElem( const Vector3 & vec ) +{ + return Vector3( + ( 1.0f / sqrtf( vec.getX() ) ), + ( 1.0f / sqrtf( vec.getY() ) ), + ( 1.0f / sqrtf( vec.getZ() ) ) + ); +} + +inline const Vector3 absPerElem( const Vector3 & vec ) +{ + return Vector3( + fabsf( vec.getX() ), + fabsf( vec.getY() ), + fabsf( vec.getZ() ) + ); +} + +inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec1.getX() < 0.0f )? -fabsf( vec0.getX() ) : fabsf( vec0.getX() ), + ( vec1.getY() < 0.0f )? -fabsf( vec0.getY() ) : fabsf( vec0.getY() ), + ( vec1.getZ() < 0.0f )? -fabsf( vec0.getZ() ) : fabsf( vec0.getZ() ) + ); +} + +inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ() + ); +} + +inline float maxElem( const Vector3 & vec ) +{ + float result; + result = (vec.getX() > vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() > result)? vec.getZ() : result; + return result; +} + +inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ() + ); +} + +inline float minElem( const Vector3 & vec ) +{ + float result; + result = (vec.getX() < vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() < result)? vec.getZ() : result; + return result; +} + +inline float sum( const Vector3 & vec ) +{ + float result; + result = ( vec.getX() + vec.getY() ); + result = ( result + vec.getZ() ); + return result; +} + +inline float dot( const Vector3 & vec0, const Vector3 & vec1 ) +{ + float result; + result = ( vec0.getX() * vec1.getX() ); + result = ( result + ( vec0.getY() * vec1.getY() ) ); + result = ( result + ( vec0.getZ() * vec1.getZ() ) ); + return result; +} + +inline float lengthSqr( const Vector3 & vec ) +{ + float result; + result = ( vec.getX() * vec.getX() ); + result = ( result + ( vec.getY() * vec.getY() ) ); + result = ( result + ( vec.getZ() * vec.getZ() ) ); + return result; +} + +inline float length( const Vector3 & vec ) +{ + return ::sqrtf( lengthSqr( vec ) ); +} + +inline const Vector3 normalize( const Vector3 & vec ) +{ + float lenSqr, lenInv; + lenSqr = lengthSqr( vec ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Vector3( + ( vec.getX() * lenInv ), + ( vec.getY() * lenInv ), + ( vec.getZ() * lenInv ) + ); +} + +inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( ( vec0.getY() * vec1.getZ() ) - ( vec0.getZ() * vec1.getY() ) ), + ( ( vec0.getZ() * vec1.getX() ) - ( vec0.getX() * vec1.getZ() ) ), + ( ( vec0.getX() * vec1.getY() ) - ( vec0.getY() * vec1.getX() ) ) + ); +} + +inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, bool select1 ) +{ + return Vector3( + ( select1 )? vec1.getX() : vec0.getX(), + ( select1 )? vec1.getY() : vec0.getY(), + ( select1 )? vec1.getZ() : vec0.getZ() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Vector3 & vec ) +{ + printf( "( %f %f %f )\n", vec.getX(), vec.getY(), vec.getZ() ); +} + +inline void print( const Vector3 & vec, const char * name ) +{ + printf( "%s: ( %f %f %f )\n", name, vec.getX(), vec.getY(), vec.getZ() ); +} + +#endif + +inline Vector4::Vector4( const Vector4 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + mW = vec.mW; +} + +inline Vector4::Vector4( float _x, float _y, float _z, float _w ) +{ + mX = _x; + mY = _y; + mZ = _z; + mW = _w; +} + +inline Vector4::Vector4( const Vector3 & xyz, float _w ) +{ + this->setXYZ( xyz ); + this->setW( _w ); +} + +inline Vector4::Vector4( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + mW = 0.0f; +} + +inline Vector4::Vector4( const Point3 & pnt ) +{ + mX = pnt.getX(); + mY = pnt.getY(); + mZ = pnt.getZ(); + mW = 1.0f; +} + +inline Vector4::Vector4( const Quat & quat ) +{ + mX = quat.getX(); + mY = quat.getY(); + mZ = quat.getZ(); + mW = quat.getW(); +} + +inline Vector4::Vector4( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; + mW = scalar; +} + +inline const Vector4 Vector4::xAxis( ) +{ + return Vector4( 1.0f, 0.0f, 0.0f, 0.0f ); +} + +inline const Vector4 Vector4::yAxis( ) +{ + return Vector4( 0.0f, 1.0f, 0.0f, 0.0f ); +} + +inline const Vector4 Vector4::zAxis( ) +{ + return Vector4( 0.0f, 0.0f, 1.0f, 0.0f ); +} + +inline const Vector4 Vector4::wAxis( ) +{ + return Vector4( 0.0f, 0.0f, 0.0f, 1.0f ); +} + +inline const Vector4 lerp( float t, const Vector4 & vec0, const Vector4 & vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector4 slerp( float t, const Vector4 & unitVec0, const Vector4 & unitVec1 ) +{ + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitVec0, unitVec1 ); + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); +} + +inline void loadXYZW( Vector4 & vec, const float * fptr ) +{ + vec = Vector4( fptr[0], fptr[1], fptr[2], fptr[3] ); +} + +inline void storeXYZW( const Vector4 & vec, float * fptr ) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); + fptr[3] = vec.getW(); +} + +inline void loadHalfFloats( Vector4 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 4; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Vector4 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 4; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Vector4 & Vector4::operator =( const Vector4 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + mW = vec.mW; + return *this; +} + +inline Vector4 & Vector4::setXYZ( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + return *this; +} + +inline const Vector3 Vector4::getXYZ( ) const +{ + return Vector3( mX, mY, mZ ); +} + +inline Vector4 & Vector4::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Vector4::getX( ) const +{ + return mX; +} + +inline Vector4 & Vector4::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Vector4::getY( ) const +{ + return mY; +} + +inline Vector4 & Vector4::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Vector4::getZ( ) const +{ + return mZ; +} + +inline Vector4 & Vector4::setW( float _w ) +{ + mW = _w; + return *this; +} + +inline float Vector4::getW( ) const +{ + return mW; +} + +inline Vector4 & Vector4::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Vector4::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Vector4::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Vector4::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector4 Vector4::operator +( const Vector4 & vec ) const +{ + return Vector4( + ( mX + vec.mX ), + ( mY + vec.mY ), + ( mZ + vec.mZ ), + ( mW + vec.mW ) + ); +} + +inline const Vector4 Vector4::operator -( const Vector4 & vec ) const +{ + return Vector4( + ( mX - vec.mX ), + ( mY - vec.mY ), + ( mZ - vec.mZ ), + ( mW - vec.mW ) + ); +} + +inline const Vector4 Vector4::operator *( float scalar ) const +{ + return Vector4( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ), + ( mW * scalar ) + ); +} + +inline Vector4 & Vector4::operator +=( const Vector4 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector4 & Vector4::operator -=( const Vector4 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector4 & Vector4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector4 Vector4::operator /( float scalar ) const +{ + return Vector4( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ), + ( mW / scalar ) + ); +} + +inline Vector4 & Vector4::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector4 Vector4::operator -( ) const +{ + return Vector4( + -mX, + -mY, + -mZ, + -mW + ); +} + +inline const Vector4 operator *( float scalar, const Vector4 & vec ) +{ + return vec * scalar; +} + +inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec0.getX() * vec1.getX() ), + ( vec0.getY() * vec1.getY() ), + ( vec0.getZ() * vec1.getZ() ), + ( vec0.getW() * vec1.getW() ) + ); +} + +inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec0.getX() / vec1.getX() ), + ( vec0.getY() / vec1.getY() ), + ( vec0.getZ() / vec1.getZ() ), + ( vec0.getW() / vec1.getW() ) + ); +} + +inline const Vector4 recipPerElem( const Vector4 & vec ) +{ + return Vector4( + ( 1.0f / vec.getX() ), + ( 1.0f / vec.getY() ), + ( 1.0f / vec.getZ() ), + ( 1.0f / vec.getW() ) + ); +} + +inline const Vector4 sqrtPerElem( const Vector4 & vec ) +{ + return Vector4( + sqrtf( vec.getX() ), + sqrtf( vec.getY() ), + sqrtf( vec.getZ() ), + sqrtf( vec.getW() ) + ); +} + +inline const Vector4 rsqrtPerElem( const Vector4 & vec ) +{ + return Vector4( + ( 1.0f / sqrtf( vec.getX() ) ), + ( 1.0f / sqrtf( vec.getY() ) ), + ( 1.0f / sqrtf( vec.getZ() ) ), + ( 1.0f / sqrtf( vec.getW() ) ) + ); +} + +inline const Vector4 absPerElem( const Vector4 & vec ) +{ + return Vector4( + fabsf( vec.getX() ), + fabsf( vec.getY() ), + fabsf( vec.getZ() ), + fabsf( vec.getW() ) + ); +} + +inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec1.getX() < 0.0f )? -fabsf( vec0.getX() ) : fabsf( vec0.getX() ), + ( vec1.getY() < 0.0f )? -fabsf( vec0.getY() ) : fabsf( vec0.getY() ), + ( vec1.getZ() < 0.0f )? -fabsf( vec0.getZ() ) : fabsf( vec0.getZ() ), + ( vec1.getW() < 0.0f )? -fabsf( vec0.getW() ) : fabsf( vec0.getW() ) + ); +} + +inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ(), + (vec0.getW() > vec1.getW())? vec0.getW() : vec1.getW() + ); +} + +inline float maxElem( const Vector4 & vec ) +{ + float result; + result = (vec.getX() > vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() > result)? vec.getZ() : result; + result = (vec.getW() > result)? vec.getW() : result; + return result; +} + +inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ(), + (vec0.getW() < vec1.getW())? vec0.getW() : vec1.getW() + ); +} + +inline float minElem( const Vector4 & vec ) +{ + float result; + result = (vec.getX() < vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() < result)? vec.getZ() : result; + result = (vec.getW() < result)? vec.getW() : result; + return result; +} + +inline float sum( const Vector4 & vec ) +{ + float result; + result = ( vec.getX() + vec.getY() ); + result = ( result + vec.getZ() ); + result = ( result + vec.getW() ); + return result; +} + +inline float dot( const Vector4 & vec0, const Vector4 & vec1 ) +{ + float result; + result = ( vec0.getX() * vec1.getX() ); + result = ( result + ( vec0.getY() * vec1.getY() ) ); + result = ( result + ( vec0.getZ() * vec1.getZ() ) ); + result = ( result + ( vec0.getW() * vec1.getW() ) ); + return result; +} + +inline float lengthSqr( const Vector4 & vec ) +{ + float result; + result = ( vec.getX() * vec.getX() ); + result = ( result + ( vec.getY() * vec.getY() ) ); + result = ( result + ( vec.getZ() * vec.getZ() ) ); + result = ( result + ( vec.getW() * vec.getW() ) ); + return result; +} + +inline float length( const Vector4 & vec ) +{ + return ::sqrtf( lengthSqr( vec ) ); +} + +inline const Vector4 normalize( const Vector4 & vec ) +{ + float lenSqr, lenInv; + lenSqr = lengthSqr( vec ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Vector4( + ( vec.getX() * lenInv ), + ( vec.getY() * lenInv ), + ( vec.getZ() * lenInv ), + ( vec.getW() * lenInv ) + ); +} + +inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, bool select1 ) +{ + return Vector4( + ( select1 )? vec1.getX() : vec0.getX(), + ( select1 )? vec1.getY() : vec0.getY(), + ( select1 )? vec1.getZ() : vec0.getZ(), + ( select1 )? vec1.getW() : vec0.getW() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Vector4 & vec ) +{ + printf( "( %f %f %f %f )\n", vec.getX(), vec.getY(), vec.getZ(), vec.getW() ); +} + +inline void print( const Vector4 & vec, const char * name ) +{ + printf( "%s: ( %f %f %f %f )\n", name, vec.getX(), vec.getY(), vec.getZ(), vec.getW() ); +} + +#endif + +inline Point3::Point3( const Point3 & pnt ) +{ + mX = pnt.mX; + mY = pnt.mY; + mZ = pnt.mZ; +} + +inline Point3::Point3( float _x, float _y, float _z ) +{ + mX = _x; + mY = _y; + mZ = _z; +} + +inline Point3::Point3( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); +} + +inline Point3::Point3( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; +} + +inline const Point3 lerp( float t, const Point3 & pnt0, const Point3 & pnt1 ) +{ + return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); +} + +inline void loadXYZ( Point3 & pnt, const float * fptr ) +{ + pnt = Point3( fptr[0], fptr[1], fptr[2] ); +} + +inline void storeXYZ( const Point3 & pnt, float * fptr ) +{ + fptr[0] = pnt.getX(); + fptr[1] = pnt.getY(); + fptr[2] = pnt.getZ(); +} + +inline void loadHalfFloats( Point3 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Point3 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Point3 & Point3::operator =( const Point3 & pnt ) +{ + mX = pnt.mX; + mY = pnt.mY; + mZ = pnt.mZ; + return *this; +} + +inline Point3 & Point3::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Point3::getX( ) const +{ + return mX; +} + +inline Point3 & Point3::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Point3::getY( ) const +{ + return mY; +} + +inline Point3 & Point3::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Point3::getZ( ) const +{ + return mZ; +} + +inline Point3 & Point3::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Point3::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Point3::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Point3::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector3 Point3::operator -( const Point3 & pnt ) const +{ + return Vector3( + ( mX - pnt.mX ), + ( mY - pnt.mY ), + ( mZ - pnt.mZ ) + ); +} + +inline const Point3 Point3::operator +( const Vector3 & vec ) const +{ + return Point3( + ( mX + vec.getX() ), + ( mY + vec.getY() ), + ( mZ + vec.getZ() ) + ); +} + +inline const Point3 Point3::operator -( const Vector3 & vec ) const +{ + return Point3( + ( mX - vec.getX() ), + ( mY - vec.getY() ), + ( mZ - vec.getZ() ) + ); +} + +inline Point3 & Point3::operator +=( const Vector3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Point3 & Point3::operator -=( const Vector3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt0.getX() * pnt1.getX() ), + ( pnt0.getY() * pnt1.getY() ), + ( pnt0.getZ() * pnt1.getZ() ) + ); +} + +inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt0.getX() / pnt1.getX() ), + ( pnt0.getY() / pnt1.getY() ), + ( pnt0.getZ() / pnt1.getZ() ) + ); +} + +inline const Point3 recipPerElem( const Point3 & pnt ) +{ + return Point3( + ( 1.0f / pnt.getX() ), + ( 1.0f / pnt.getY() ), + ( 1.0f / pnt.getZ() ) + ); +} + +inline const Point3 sqrtPerElem( const Point3 & pnt ) +{ + return Point3( + sqrtf( pnt.getX() ), + sqrtf( pnt.getY() ), + sqrtf( pnt.getZ() ) + ); +} + +inline const Point3 rsqrtPerElem( const Point3 & pnt ) +{ + return Point3( + ( 1.0f / sqrtf( pnt.getX() ) ), + ( 1.0f / sqrtf( pnt.getY() ) ), + ( 1.0f / sqrtf( pnt.getZ() ) ) + ); +} + +inline const Point3 absPerElem( const Point3 & pnt ) +{ + return Point3( + fabsf( pnt.getX() ), + fabsf( pnt.getY() ), + fabsf( pnt.getZ() ) + ); +} + +inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt1.getX() < 0.0f )? -fabsf( pnt0.getX() ) : fabsf( pnt0.getX() ), + ( pnt1.getY() < 0.0f )? -fabsf( pnt0.getY() ) : fabsf( pnt0.getY() ), + ( pnt1.getZ() < 0.0f )? -fabsf( pnt0.getZ() ) : fabsf( pnt0.getZ() ) + ); +} + +inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + (pnt0.getX() > pnt1.getX())? pnt0.getX() : pnt1.getX(), + (pnt0.getY() > pnt1.getY())? pnt0.getY() : pnt1.getY(), + (pnt0.getZ() > pnt1.getZ())? pnt0.getZ() : pnt1.getZ() + ); +} + +inline float maxElem( const Point3 & pnt ) +{ + float result; + result = (pnt.getX() > pnt.getY())? pnt.getX() : pnt.getY(); + result = (pnt.getZ() > result)? pnt.getZ() : result; + return result; +} + +inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + (pnt0.getX() < pnt1.getX())? pnt0.getX() : pnt1.getX(), + (pnt0.getY() < pnt1.getY())? pnt0.getY() : pnt1.getY(), + (pnt0.getZ() < pnt1.getZ())? pnt0.getZ() : pnt1.getZ() + ); +} + +inline float minElem( const Point3 & pnt ) +{ + float result; + result = (pnt.getX() < pnt.getY())? pnt.getX() : pnt.getY(); + result = (pnt.getZ() < result)? pnt.getZ() : result; + return result; +} + +inline float sum( const Point3 & pnt ) +{ + float result; + result = ( pnt.getX() + pnt.getY() ); + result = ( result + pnt.getZ() ); + return result; +} + +inline const Point3 scale( const Point3 & pnt, float scaleVal ) +{ + return mulPerElem( pnt, Point3( scaleVal ) ); +} + +inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ) +{ + return mulPerElem( pnt, Point3( scaleVec ) ); +} + +inline float projection( const Point3 & pnt, const Vector3 & unitVec ) +{ + float result; + result = ( pnt.getX() * unitVec.getX() ); + result = ( result + ( pnt.getY() * unitVec.getY() ) ); + result = ( result + ( pnt.getZ() * unitVec.getZ() ) ); + return result; +} + +inline float distSqrFromOrigin( const Point3 & pnt ) +{ + return lengthSqr( Vector3( pnt ) ); +} + +inline float distFromOrigin( const Point3 & pnt ) +{ + return length( Vector3( pnt ) ); +} + +inline float distSqr( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return lengthSqr( ( pnt1 - pnt0 ) ); +} + +inline float dist( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return length( ( pnt1 - pnt0 ) ); +} + +inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, bool select1 ) +{ + return Point3( + ( select1 )? pnt1.getX() : pnt0.getX(), + ( select1 )? pnt1.getY() : pnt0.getY(), + ( select1 )? pnt1.getZ() : pnt0.getZ() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Point3 & pnt ) +{ + printf( "( %f %f %f )\n", pnt.getX(), pnt.getY(), pnt.getZ() ); +} + +inline void print( const Point3 & pnt, const char * name ) +{ + printf( "%s: ( %f %f %f )\n", name, pnt.getX(), pnt.getY(), pnt.getZ() ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/src/vectormath/scalar/vectormath_aos.h b/src/vectormath/scalar/vectormath_aos.h new file mode 100644 index 0000000..d00456d --- /dev/null +++ b/src/vectormath/scalar/vectormath_aos.h @@ -0,0 +1,1872 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _VECTORMATH_AOS_CPP_H +#define _VECTORMATH_AOS_CPP_H + +#include + +#ifdef _VECTORMATH_DEBUG +#include +#endif + +namespace Vectormath { + +namespace Aos { + +//----------------------------------------------------------------------------- +// Forward Declarations +// + +class Vector3; +class Vector4; +class Point3; +class Quat; +class Matrix3; +class Matrix4; +class Transform3; + +// A 3-D vector in array-of-structures format +// +class Vector3 +{ + float mX; + float mY; + float mZ; +#ifndef __GNUC__ + float d; +#endif + +public: + // Default constructor; does no initialization + // + inline Vector3( ) { }; + + // Copy a 3-D vector + // + inline Vector3( const Vector3 & vec ); + + // Construct a 3-D vector from x, y, and z elements + // + inline Vector3( float x, float y, float z ); + + // Copy elements from a 3-D point into a 3-D vector + // + explicit inline Vector3( const Point3 & pnt ); + + // Set all elements of a 3-D vector to the same scalar value + // + explicit inline Vector3( float scalar ); + + // Assign one 3-D vector to another + // + inline Vector3 & operator =( const Vector3 & vec ); + + // Set the x element of a 3-D vector + // + inline Vector3 & setX( float x ); + + // Set the y element of a 3-D vector + // + inline Vector3 & setY( float y ); + + // Set the z element of a 3-D vector + // + inline Vector3 & setZ( float z ); + + // Get the x element of a 3-D vector + // + inline float getX( ) const; + + // Get the y element of a 3-D vector + // + inline float getY( ) const; + + // Get the z element of a 3-D vector + // + inline float getZ( ) const; + + // Set an x, y, or z element of a 3-D vector by index + // + inline Vector3 & setElem( int idx, float value ); + + // Get an x, y, or z element of a 3-D vector by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two 3-D vectors + // + inline const Vector3 operator +( const Vector3 & vec ) const; + + // Subtract a 3-D vector from another 3-D vector + // + inline const Vector3 operator -( const Vector3 & vec ) const; + + // Add a 3-D vector to a 3-D point + // + inline const Point3 operator +( const Point3 & pnt ) const; + + // Multiply a 3-D vector by a scalar + // + inline const Vector3 operator *( float scalar ) const; + + // Divide a 3-D vector by a scalar + // + inline const Vector3 operator /( float scalar ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Vector3 & operator +=( const Vector3 & vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Vector3 & operator -=( const Vector3 & vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector3 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector3 & operator /=( float scalar ); + + // Negate all elements of a 3-D vector + // + inline const Vector3 operator -( ) const; + + // Construct x axis + // + static inline const Vector3 xAxis( ); + + // Construct y axis + // + static inline const Vector3 yAxis( ); + + // Construct z axis + // + static inline const Vector3 zAxis( ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a 3-D vector by a scalar +// +inline const Vector3 operator *( float scalar, const Vector3 & vec ); + +// Multiply two 3-D vectors per element +// +inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Divide two 3-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Compute the reciprocal of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector3 recipPerElem( const Vector3 & vec ); + +// Compute the square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector3 sqrtPerElem( const Vector3 & vec ); + +// Compute the reciprocal square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector3 rsqrtPerElem( const Vector3 & vec ); + +// Compute the absolute value of a 3-D vector per element +// +inline const Vector3 absPerElem( const Vector3 & vec ); + +// Copy sign from one 3-D vector to another, per element +// +inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Maximum of two 3-D vectors per element +// +inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Minimum of two 3-D vectors per element +// +inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Maximum element of a 3-D vector +// +inline float maxElem( const Vector3 & vec ); + +// Minimum element of a 3-D vector +// +inline float minElem( const Vector3 & vec ); + +// Compute the sum of all elements of a 3-D vector +// +inline float sum( const Vector3 & vec ); + +// Compute the dot product of two 3-D vectors +// +inline float dot( const Vector3 & vec0, const Vector3 & vec1 ); + +// Compute the square of the length of a 3-D vector +// +inline float lengthSqr( const Vector3 & vec ); + +// Compute the length of a 3-D vector +// +inline float length( const Vector3 & vec ); + +// Normalize a 3-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector3 normalize( const Vector3 & vec ); + +// Compute cross product of two 3-D vectors +// +inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ); + +// Outer product of two 3-D vectors +// +inline const Matrix3 outer( const Vector3 & vec0, const Vector3 & vec1 ); + +// Pre-multiply a row vector by a 3x3 matrix +// +inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ); + +// Cross-product matrix of a 3-D vector +// +inline const Matrix3 crossMatrix( const Vector3 & vec ); + +// Create cross-product matrix and multiply +// NOTE: +// Faster than separately creating a cross-product matrix and multiplying. +// +inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ); + +// Linear interpolation between two 3-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector3 lerp( float t, const Vector3 & vec0, const Vector3 & vec1 ); + +// Spherical linear interpolation between two 3-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector3 slerp( float t, const Vector3 & unitVec0, const Vector3 & unitVec1 ); + +// Conditionally select between two 3-D vectors +// +inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, bool select1 ); + +// Load x, y, and z elements from the first three words of a float array. +// +// +inline void loadXYZ( Vector3 & vec, const float * fptr ); + +// Store x, y, and z elements of a 3-D vector in the first three words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZ( const Vector3 & vec, float * fptr ); + +// Load three-half-floats as a 3-D vector +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Vector3 & vec, const unsigned short * hfptr ); + +// Store a 3-D vector as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Vector3 & vec, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector3 & vec ); + +// Print a 3-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector3 & vec, const char * name ); + +#endif + +// A 4-D vector in array-of-structures format +// +class Vector4 +{ + float mX; + float mY; + float mZ; + float mW; + +public: + // Default constructor; does no initialization + // + inline Vector4( ) { }; + + // Copy a 4-D vector + // + inline Vector4( const Vector4 & vec ); + + // Construct a 4-D vector from x, y, z, and w elements + // + inline Vector4( float x, float y, float z, float w ); + + // Construct a 4-D vector from a 3-D vector and a scalar + // + inline Vector4( const Vector3 & xyz, float w ); + + // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + // + explicit inline Vector4( const Vector3 & vec ); + + // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + // + explicit inline Vector4( const Point3 & pnt ); + + // Copy elements from a quaternion into a 4-D vector + // + explicit inline Vector4( const Quat & quat ); + + // Set all elements of a 4-D vector to the same scalar value + // + explicit inline Vector4( float scalar ); + + // Assign one 4-D vector to another + // + inline Vector4 & operator =( const Vector4 & vec ); + + // Set the x, y, and z elements of a 4-D vector + // NOTE: + // This function does not change the w element. + // + inline Vector4 & setXYZ( const Vector3 & vec ); + + // Get the x, y, and z elements of a 4-D vector + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a 4-D vector + // + inline Vector4 & setX( float x ); + + // Set the y element of a 4-D vector + // + inline Vector4 & setY( float y ); + + // Set the z element of a 4-D vector + // + inline Vector4 & setZ( float z ); + + // Set the w element of a 4-D vector + // + inline Vector4 & setW( float w ); + + // Get the x element of a 4-D vector + // + inline float getX( ) const; + + // Get the y element of a 4-D vector + // + inline float getY( ) const; + + // Get the z element of a 4-D vector + // + inline float getZ( ) const; + + // Get the w element of a 4-D vector + // + inline float getW( ) const; + + // Set an x, y, z, or w element of a 4-D vector by index + // + inline Vector4 & setElem( int idx, float value ); + + // Get an x, y, z, or w element of a 4-D vector by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two 4-D vectors + // + inline const Vector4 operator +( const Vector4 & vec ) const; + + // Subtract a 4-D vector from another 4-D vector + // + inline const Vector4 operator -( const Vector4 & vec ) const; + + // Multiply a 4-D vector by a scalar + // + inline const Vector4 operator *( float scalar ) const; + + // Divide a 4-D vector by a scalar + // + inline const Vector4 operator /( float scalar ) const; + + // Perform compound assignment and addition with a 4-D vector + // + inline Vector4 & operator +=( const Vector4 & vec ); + + // Perform compound assignment and subtraction by a 4-D vector + // + inline Vector4 & operator -=( const Vector4 & vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector4 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector4 & operator /=( float scalar ); + + // Negate all elements of a 4-D vector + // + inline const Vector4 operator -( ) const; + + // Construct x axis + // + static inline const Vector4 xAxis( ); + + // Construct y axis + // + static inline const Vector4 yAxis( ); + + // Construct z axis + // + static inline const Vector4 zAxis( ); + + // Construct w axis + // + static inline const Vector4 wAxis( ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a 4-D vector by a scalar +// +inline const Vector4 operator *( float scalar, const Vector4 & vec ); + +// Multiply two 4-D vectors per element +// +inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Divide two 4-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Compute the reciprocal of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector4 recipPerElem( const Vector4 & vec ); + +// Compute the square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector4 sqrtPerElem( const Vector4 & vec ); + +// Compute the reciprocal square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector4 rsqrtPerElem( const Vector4 & vec ); + +// Compute the absolute value of a 4-D vector per element +// +inline const Vector4 absPerElem( const Vector4 & vec ); + +// Copy sign from one 4-D vector to another, per element +// +inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Maximum of two 4-D vectors per element +// +inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Minimum of two 4-D vectors per element +// +inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Maximum element of a 4-D vector +// +inline float maxElem( const Vector4 & vec ); + +// Minimum element of a 4-D vector +// +inline float minElem( const Vector4 & vec ); + +// Compute the sum of all elements of a 4-D vector +// +inline float sum( const Vector4 & vec ); + +// Compute the dot product of two 4-D vectors +// +inline float dot( const Vector4 & vec0, const Vector4 & vec1 ); + +// Compute the square of the length of a 4-D vector +// +inline float lengthSqr( const Vector4 & vec ); + +// Compute the length of a 4-D vector +// +inline float length( const Vector4 & vec ); + +// Normalize a 4-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector4 normalize( const Vector4 & vec ); + +// Outer product of two 4-D vectors +// +inline const Matrix4 outer( const Vector4 & vec0, const Vector4 & vec1 ); + +// Linear interpolation between two 4-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector4 lerp( float t, const Vector4 & vec0, const Vector4 & vec1 ); + +// Spherical linear interpolation between two 4-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector4 slerp( float t, const Vector4 & unitVec0, const Vector4 & unitVec1 ); + +// Conditionally select between two 4-D vectors +// +inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, bool select1 ); + +// Load x, y, z, and w elements from the first four words of a float array. +// +// +inline void loadXYZW( Vector4 & vec, const float * fptr ); + +// Store x, y, z, and w elements of a 4-D vector in the first four words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZW( const Vector4 & vec, float * fptr ); + +// Load four-half-floats as a 4-D vector +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Vector4 & vec, const unsigned short * hfptr ); + +// Store a 4-D vector as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Vector4 & vec, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector4 & vec ); + +// Print a 4-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector4 & vec, const char * name ); + +#endif + +// A 3-D point in array-of-structures format +// +class Point3 +{ + float mX; + float mY; + float mZ; +#ifndef __GNUC__ + float d; +#endif + +public: + // Default constructor; does no initialization + // + inline Point3( ) { }; + + // Copy a 3-D point + // + inline Point3( const Point3 & pnt ); + + // Construct a 3-D point from x, y, and z elements + // + inline Point3( float x, float y, float z ); + + // Copy elements from a 3-D vector into a 3-D point + // + explicit inline Point3( const Vector3 & vec ); + + // Set all elements of a 3-D point to the same scalar value + // + explicit inline Point3( float scalar ); + + // Assign one 3-D point to another + // + inline Point3 & operator =( const Point3 & pnt ); + + // Set the x element of a 3-D point + // + inline Point3 & setX( float x ); + + // Set the y element of a 3-D point + // + inline Point3 & setY( float y ); + + // Set the z element of a 3-D point + // + inline Point3 & setZ( float z ); + + // Get the x element of a 3-D point + // + inline float getX( ) const; + + // Get the y element of a 3-D point + // + inline float getY( ) const; + + // Get the z element of a 3-D point + // + inline float getZ( ) const; + + // Set an x, y, or z element of a 3-D point by index + // + inline Point3 & setElem( int idx, float value ); + + // Get an x, y, or z element of a 3-D point by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Subtract a 3-D point from another 3-D point + // + inline const Vector3 operator -( const Point3 & pnt ) const; + + // Add a 3-D point to a 3-D vector + // + inline const Point3 operator +( const Vector3 & vec ) const; + + // Subtract a 3-D vector from a 3-D point + // + inline const Point3 operator -( const Vector3 & vec ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Point3 & operator +=( const Vector3 & vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Point3 & operator -=( const Vector3 & vec ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply two 3-D points per element +// +inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Divide two 3-D points per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Compute the reciprocal of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Point3 recipPerElem( const Point3 & pnt ); + +// Compute the square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Point3 sqrtPerElem( const Point3 & pnt ); + +// Compute the reciprocal square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Point3 rsqrtPerElem( const Point3 & pnt ); + +// Compute the absolute value of a 3-D point per element +// +inline const Point3 absPerElem( const Point3 & pnt ); + +// Copy sign from one 3-D point to another, per element +// +inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Maximum of two 3-D points per element +// +inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Minimum of two 3-D points per element +// +inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Maximum element of a 3-D point +// +inline float maxElem( const Point3 & pnt ); + +// Minimum element of a 3-D point +// +inline float minElem( const Point3 & pnt ); + +// Compute the sum of all elements of a 3-D point +// +inline float sum( const Point3 & pnt ); + +// Apply uniform scale to a 3-D point +// +inline const Point3 scale( const Point3 & pnt, float scaleVal ); + +// Apply non-uniform scale to a 3-D point +// +inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ); + +// Scalar projection of a 3-D point on a unit-length 3-D vector +// +inline float projection( const Point3 & pnt, const Vector3 & unitVec ); + +// Compute the square of the distance of a 3-D point from the coordinate-system origin +// +inline float distSqrFromOrigin( const Point3 & pnt ); + +// Compute the distance of a 3-D point from the coordinate-system origin +// +inline float distFromOrigin( const Point3 & pnt ); + +// Compute the square of the distance between two 3-D points +// +inline float distSqr( const Point3 & pnt0, const Point3 & pnt1 ); + +// Compute the distance between two 3-D points +// +inline float dist( const Point3 & pnt0, const Point3 & pnt1 ); + +// Linear interpolation between two 3-D points +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Point3 lerp( float t, const Point3 & pnt0, const Point3 & pnt1 ); + +// Conditionally select between two 3-D points +// +inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, bool select1 ); + +// Load x, y, and z elements from the first three words of a float array. +// +// +inline void loadXYZ( Point3 & pnt, const float * fptr ); + +// Store x, y, and z elements of a 3-D point in the first three words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZ( const Point3 & pnt, float * fptr ); + +// Load three-half-floats as a 3-D point +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Point3 & pnt, const unsigned short * hfptr ); + +// Store a 3-D point as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Point3 & pnt, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D point +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Point3 & pnt ); + +// Print a 3-D point and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Point3 & pnt, const char * name ); + +#endif + +// A quaternion in array-of-structures format +// +class Quat +{ + float mX; + float mY; + float mZ; + float mW; + +public: + // Default constructor; does no initialization + // + inline Quat( ) { }; + + // Copy a quaternion + // + inline Quat( const Quat & quat ); + + // Construct a quaternion from x, y, z, and w elements + // + inline Quat( float x, float y, float z, float w ); + + // Construct a quaternion from a 3-D vector and a scalar + // + inline Quat( const Vector3 & xyz, float w ); + + // Copy elements from a 4-D vector into a quaternion + // + explicit inline Quat( const Vector4 & vec ); + + // Convert a rotation matrix to a unit-length quaternion + // + explicit inline Quat( const Matrix3 & rotMat ); + + // Set all elements of a quaternion to the same scalar value + // + explicit inline Quat( float scalar ); + + // Assign one quaternion to another + // + inline Quat & operator =( const Quat & quat ); + + // Set the x, y, and z elements of a quaternion + // NOTE: + // This function does not change the w element. + // + inline Quat & setXYZ( const Vector3 & vec ); + + // Get the x, y, and z elements of a quaternion + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a quaternion + // + inline Quat & setX( float x ); + + // Set the y element of a quaternion + // + inline Quat & setY( float y ); + + // Set the z element of a quaternion + // + inline Quat & setZ( float z ); + + // Set the w element of a quaternion + // + inline Quat & setW( float w ); + + // Get the x element of a quaternion + // + inline float getX( ) const; + + // Get the y element of a quaternion + // + inline float getY( ) const; + + // Get the z element of a quaternion + // + inline float getZ( ) const; + + // Get the w element of a quaternion + // + inline float getW( ) const; + + // Set an x, y, z, or w element of a quaternion by index + // + inline Quat & setElem( int idx, float value ); + + // Get an x, y, z, or w element of a quaternion by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two quaternions + // + inline const Quat operator +( const Quat & quat ) const; + + // Subtract a quaternion from another quaternion + // + inline const Quat operator -( const Quat & quat ) const; + + // Multiply two quaternions + // + inline const Quat operator *( const Quat & quat ) const; + + // Multiply a quaternion by a scalar + // + inline const Quat operator *( float scalar ) const; + + // Divide a quaternion by a scalar + // + inline const Quat operator /( float scalar ) const; + + // Perform compound assignment and addition with a quaternion + // + inline Quat & operator +=( const Quat & quat ); + + // Perform compound assignment and subtraction by a quaternion + // + inline Quat & operator -=( const Quat & quat ); + + // Perform compound assignment and multiplication by a quaternion + // + inline Quat & operator *=( const Quat & quat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Quat & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Quat & operator /=( float scalar ); + + // Negate all elements of a quaternion + // + inline const Quat operator -( ) const; + + // Construct an identity quaternion + // + static inline const Quat identity( ); + + // Construct a quaternion to rotate between two unit-length 3-D vectors + // NOTE: + // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + // + static inline const Quat rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ); + + // Construct a quaternion to rotate around a unit-length 3-D vector + // + static inline const Quat rotation( float radians, const Vector3 & unitVec ); + + // Construct a quaternion to rotate around the x axis + // + static inline const Quat rotationX( float radians ); + + // Construct a quaternion to rotate around the y axis + // + static inline const Quat rotationY( float radians ); + + // Construct a quaternion to rotate around the z axis + // + static inline const Quat rotationZ( float radians ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a quaternion by a scalar +// +inline const Quat operator *( float scalar, const Quat & quat ); + +// Compute the conjugate of a quaternion +// +inline const Quat conj( const Quat & quat ); + +// Use a unit-length quaternion to rotate a 3-D vector +// +inline const Vector3 rotate( const Quat & unitQuat, const Vector3 & vec ); + +// Compute the dot product of two quaternions +// +inline float dot( const Quat & quat0, const Quat & quat1 ); + +// Compute the norm of a quaternion +// +inline float norm( const Quat & quat ); + +// Compute the length of a quaternion +// +inline float length( const Quat & quat ); + +// Normalize a quaternion +// NOTE: +// The result is unpredictable when all elements of quat are at or near zero. +// +inline const Quat normalize( const Quat & quat ); + +// Linear interpolation between two quaternions +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Quat lerp( float t, const Quat & quat0, const Quat & quat1 ); + +// Spherical linear interpolation between two quaternions +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +inline const Quat slerp( float t, const Quat & unitQuat0, const Quat & unitQuat1 ); + +// Spherical quadrangle interpolation +// +inline const Quat squad( float t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ); + +// Conditionally select between two quaternions +// +inline const Quat select( const Quat & quat0, const Quat & quat1, bool select1 ); + +// Load x, y, z, and w elements from the first four words of a float array. +// +// +inline void loadXYZW( Quat & quat, const float * fptr ); + +// Store x, y, z, and w elements of a quaternion in the first four words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZW( const Quat & quat, float * fptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a quaternion +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Quat & quat ); + +// Print a quaternion and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Quat & quat, const char * name ); + +#endif + +// A 3x3 matrix in array-of-structures format +// +class Matrix3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + +public: + // Default constructor; does no initialization + // + inline Matrix3( ) { }; + + // Copy a 3x3 matrix + // + inline Matrix3( const Matrix3 & mat ); + + // Construct a 3x3 matrix containing the specified columns + // + inline Matrix3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2 ); + + // Construct a 3x3 rotation matrix from a unit-length quaternion + // + explicit inline Matrix3( const Quat & unitQuat ); + + // Set all elements of a 3x3 matrix to the same scalar value + // + explicit inline Matrix3( float scalar ); + + // Assign one 3x3 matrix to another + // + inline Matrix3 & operator =( const Matrix3 & mat ); + + // Set column 0 of a 3x3 matrix + // + inline Matrix3 & setCol0( const Vector3 & col0 ); + + // Set column 1 of a 3x3 matrix + // + inline Matrix3 & setCol1( const Vector3 & col1 ); + + // Set column 2 of a 3x3 matrix + // + inline Matrix3 & setCol2( const Vector3 & col2 ); + + // Get column 0 of a 3x3 matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x3 matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x3 matrix + // + inline const Vector3 getCol2( ) const; + + // Set the column of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setCol( int col, const Vector3 & vec ); + + // Set the row of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setRow( int row, const Vector3 & vec ); + + // Get the column of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x3 matrix referred to by column and row indices + // + inline Matrix3 & setElem( int col, int row, float val ); + + // Get the element of a 3x3 matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Add two 3x3 matrices + // + inline const Matrix3 operator +( const Matrix3 & mat ) const; + + // Subtract a 3x3 matrix from another 3x3 matrix + // + inline const Matrix3 operator -( const Matrix3 & mat ) const; + + // Negate all elements of a 3x3 matrix + // + inline const Matrix3 operator -( ) const; + + // Multiply a 3x3 matrix by a scalar + // + inline const Matrix3 operator *( float scalar ) const; + + // Multiply a 3x3 matrix by a 3-D vector + // + inline const Vector3 operator *( const Vector3 & vec ) const; + + // Multiply two 3x3 matrices + // + inline const Matrix3 operator *( const Matrix3 & mat ) const; + + // Perform compound assignment and addition with a 3x3 matrix + // + inline Matrix3 & operator +=( const Matrix3 & mat ); + + // Perform compound assignment and subtraction by a 3x3 matrix + // + inline Matrix3 & operator -=( const Matrix3 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix3 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a 3x3 matrix + // + inline Matrix3 & operator *=( const Matrix3 & mat ); + + // Construct an identity 3x3 matrix + // + static inline const Matrix3 identity( ); + + // Construct a 3x3 matrix to rotate around the x axis + // + static inline const Matrix3 rotationX( float radians ); + + // Construct a 3x3 matrix to rotate around the y axis + // + static inline const Matrix3 rotationY( float radians ); + + // Construct a 3x3 matrix to rotate around the z axis + // + static inline const Matrix3 rotationZ( float radians ); + + // Construct a 3x3 matrix to rotate around the x, y, and z axes + // + static inline const Matrix3 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix3 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix3 rotation( const Quat & unitQuat ); + + // Construct a 3x3 matrix to perform scaling + // + static inline const Matrix3 scale( const Vector3 & scaleVec ); + +}; +// Multiply a 3x3 matrix by a scalar +// +inline const Matrix3 operator *( float scalar, const Matrix3 & mat ); + +// Append (post-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ); + +// Multiply two 3x3 matrices per element +// +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); + +// Compute the absolute value of a 3x3 matrix per element +// +inline const Matrix3 absPerElem( const Matrix3 & mat ); + +// Transpose of a 3x3 matrix +// +inline const Matrix3 transpose( const Matrix3 & mat ); + +// Compute the inverse of a 3x3 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix3 inverse( const Matrix3 & mat ); + +// Determinant of a 3x3 matrix +// +inline float determinant( const Matrix3 & mat ); + +// Conditionally select between two 3x3 matrices +// +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x3 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat ); + +// Print a 3x3 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat, const char * name ); + +#endif + +// A 4x4 matrix in array-of-structures format +// +class Matrix4 +{ + Vector4 mCol0; + Vector4 mCol1; + Vector4 mCol2; + Vector4 mCol3; + +public: + // Default constructor; does no initialization + // + inline Matrix4( ) { }; + + // Copy a 4x4 matrix + // + inline Matrix4( const Matrix4 & mat ); + + // Construct a 4x4 matrix containing the specified columns + // + inline Matrix4( const Vector4 & col0, const Vector4 & col1, const Vector4 & col2, const Vector4 & col3 ); + + // Construct a 4x4 matrix from a 3x4 transformation matrix + // + explicit inline Matrix4( const Transform3 & mat ); + + // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + // + inline Matrix4( const Matrix3 & mat, const Vector3 & translateVec ); + + // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + // + inline Matrix4( const Quat & unitQuat, const Vector3 & translateVec ); + + // Set all elements of a 4x4 matrix to the same scalar value + // + explicit inline Matrix4( float scalar ); + + // Assign one 4x4 matrix to another + // + inline Matrix4 & operator =( const Matrix4 & mat ); + + // Set the upper-left 3x3 submatrix + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 4x4 matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setTranslation( const Vector3 & translateVec ); + + // Get the translation component of a 4x4 matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 4x4 matrix + // + inline Matrix4 & setCol0( const Vector4 & col0 ); + + // Set column 1 of a 4x4 matrix + // + inline Matrix4 & setCol1( const Vector4 & col1 ); + + // Set column 2 of a 4x4 matrix + // + inline Matrix4 & setCol2( const Vector4 & col2 ); + + // Set column 3 of a 4x4 matrix + // + inline Matrix4 & setCol3( const Vector4 & col3 ); + + // Get column 0 of a 4x4 matrix + // + inline const Vector4 getCol0( ) const; + + // Get column 1 of a 4x4 matrix + // + inline const Vector4 getCol1( ) const; + + // Get column 2 of a 4x4 matrix + // + inline const Vector4 getCol2( ) const; + + // Get column 3 of a 4x4 matrix + // + inline const Vector4 getCol3( ) const; + + // Set the column of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setCol( int col, const Vector4 & vec ); + + // Set the row of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setRow( int row, const Vector4 & vec ); + + // Get the column of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getCol( int col ) const; + + // Get the row of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector4 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector4 operator []( int col ) const; + + // Set the element of a 4x4 matrix referred to by column and row indices + // + inline Matrix4 & setElem( int col, int row, float val ); + + // Get the element of a 4x4 matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Add two 4x4 matrices + // + inline const Matrix4 operator +( const Matrix4 & mat ) const; + + // Subtract a 4x4 matrix from another 4x4 matrix + // + inline const Matrix4 operator -( const Matrix4 & mat ) const; + + // Negate all elements of a 4x4 matrix + // + inline const Matrix4 operator -( ) const; + + // Multiply a 4x4 matrix by a scalar + // + inline const Matrix4 operator *( float scalar ) const; + + // Multiply a 4x4 matrix by a 4-D vector + // + inline const Vector4 operator *( const Vector4 & vec ) const; + + // Multiply a 4x4 matrix by a 3-D vector + // + inline const Vector4 operator *( const Vector3 & vec ) const; + + // Multiply a 4x4 matrix by a 3-D point + // + inline const Vector4 operator *( const Point3 & pnt ) const; + + // Multiply two 4x4 matrices + // + inline const Matrix4 operator *( const Matrix4 & mat ) const; + + // Multiply a 4x4 matrix by a 3x4 transformation matrix + // + inline const Matrix4 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and addition with a 4x4 matrix + // + inline Matrix4 & operator +=( const Matrix4 & mat ); + + // Perform compound assignment and subtraction by a 4x4 matrix + // + inline Matrix4 & operator -=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix4 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a 4x4 matrix + // + inline Matrix4 & operator *=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Matrix4 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 4x4 matrix + // + static inline const Matrix4 identity( ); + + // Construct a 4x4 matrix to rotate around the x axis + // + static inline const Matrix4 rotationX( float radians ); + + // Construct a 4x4 matrix to rotate around the y axis + // + static inline const Matrix4 rotationY( float radians ); + + // Construct a 4x4 matrix to rotate around the z axis + // + static inline const Matrix4 rotationZ( float radians ); + + // Construct a 4x4 matrix to rotate around the x, y, and z axes + // + static inline const Matrix4 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix4 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix4 rotation( const Quat & unitQuat ); + + // Construct a 4x4 matrix to perform scaling + // + static inline const Matrix4 scale( const Vector3 & scaleVec ); + + // Construct a 4x4 matrix to perform translation + // + static inline const Matrix4 translation( const Vector3 & translateVec ); + + // Construct viewing matrix based on eye position, position looked at, and up direction + // + static inline const Matrix4 lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ); + + // Construct a perspective projection matrix + // + static inline const Matrix4 perspective( float fovyRadians, float aspect, float zNear, float zFar ); + + // Construct a perspective projection matrix based on frustum + // + static inline const Matrix4 frustum( float left, float right, float bottom, float top, float zNear, float zFar ); + + // Construct an orthographic projection matrix + // + static inline const Matrix4 orthographic( float left, float right, float bottom, float top, float zNear, float zFar ); + +}; +// Multiply a 4x4 matrix by a scalar +// +inline const Matrix4 operator *( float scalar, const Matrix4 & mat ); + +// Append (post-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ); + +// Multiply two 4x4 matrices per element +// +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); + +// Compute the absolute value of a 4x4 matrix per element +// +inline const Matrix4 absPerElem( const Matrix4 & mat ); + +// Transpose of a 4x4 matrix +// +inline const Matrix4 transpose( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 inverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 affineInverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. +// +inline const Matrix4 orthoInverse( const Matrix4 & mat ); + +// Determinant of a 4x4 matrix +// +inline float determinant( const Matrix4 & mat ); + +// Conditionally select between two 4x4 matrices +// +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4x4 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat ); + +// Print a 4x4 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat, const char * name ); + +#endif + +// A 3x4 transformation matrix in array-of-structures format +// +class Transform3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + Vector3 mCol3; + +public: + // Default constructor; does no initialization + // + inline Transform3( ) { }; + + // Copy a 3x4 transformation matrix + // + inline Transform3( const Transform3 & tfrm ); + + // Construct a 3x4 transformation matrix containing the specified columns + // + inline Transform3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2, const Vector3 & col3 ); + + // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + // + inline Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ); + + // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + // + inline Transform3( const Quat & unitQuat, const Vector3 & translateVec ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value + // + explicit inline Transform3( float scalar ); + + // Assign one 3x4 transformation matrix to another + // + inline Transform3 & operator =( const Transform3 & tfrm ); + + // Set the upper-left 3x3 submatrix + // + inline Transform3 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // + inline Transform3 & setTranslation( const Vector3 & translateVec ); + + // Get the translation component of a 3x4 transformation matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 3x4 transformation matrix + // + inline Transform3 & setCol0( const Vector3 & col0 ); + + // Set column 1 of a 3x4 transformation matrix + // + inline Transform3 & setCol1( const Vector3 & col1 ); + + // Set column 2 of a 3x4 transformation matrix + // + inline Transform3 & setCol2( const Vector3 & col2 ); + + // Set column 3 of a 3x4 transformation matrix + // + inline Transform3 & setCol3( const Vector3 & col3 ); + + // Get column 0 of a 3x4 transformation matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x4 transformation matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x4 transformation matrix + // + inline const Vector3 getCol2( ) const; + + // Get column 3 of a 3x4 transformation matrix + // + inline const Vector3 getCol3( ) const; + + // Set the column of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setCol( int col, const Vector3 & vec ); + + // Set the row of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setRow( int row, const Vector4 & vec ); + + // Get the column of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x4 transformation matrix referred to by column and row indices + // + inline Transform3 & setElem( int col, int row, float val ); + + // Get the element of a 3x4 transformation matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Multiply a 3x4 transformation matrix by a 3-D vector + // + inline const Vector3 operator *( const Vector3 & vec ) const; + + // Multiply a 3x4 transformation matrix by a 3-D point + // + inline const Point3 operator *( const Point3 & pnt ) const; + + // Multiply two 3x4 transformation matrices + // + inline const Transform3 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Transform3 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 3x4 transformation matrix + // + static inline const Transform3 identity( ); + + // Construct a 3x4 transformation matrix to rotate around the x axis + // + static inline const Transform3 rotationX( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis + // + static inline const Transform3 rotationY( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis + // + static inline const Transform3 rotationZ( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + // + static inline const Transform3 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + // + static inline const Transform3 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Transform3 rotation( const Quat & unitQuat ); + + // Construct a 3x4 transformation matrix to perform scaling + // + static inline const Transform3 scale( const Vector3 & scaleVec ); + + // Construct a 3x4 transformation matrix to perform translation + // + static inline const Transform3 translation( const Vector3 & translateVec ); + +}; +// Append (post-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ); + +// Multiply two 3x4 transformation matrices per element +// +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); + +// Compute the absolute value of a 3x4 transformation matrix per element +// +inline const Transform3 absPerElem( const Transform3 & tfrm ); + +// Inverse of a 3x4 transformation matrix +// NOTE: +// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. +// +inline const Transform3 inverse( const Transform3 & tfrm ); + +// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. +// +inline const Transform3 orthoInverse( const Transform3 & tfrm ); + +// Conditionally select between two 3x4 transformation matrices +// +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x4 transformation matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm ); + +// Print a 3x4 transformation matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm, const char * name ); + +#endif + +} // namespace Aos +} // namespace Vectormath + +#include "vec_aos.h" +#include "quat_aos.h" +#include "mat_aos.h" + +#endif diff --git a/src/vectormath/sse/boolInVec.h b/src/vectormath/sse/boolInVec.h new file mode 100644 index 0000000..d18cb15 --- /dev/null +++ b/src/vectormath/sse/boolInVec.h @@ -0,0 +1,247 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _BOOLINVEC_H +#define _BOOLINVEC_H + +#include + +namespace Vectormath { + +class floatInVec; + +//-------------------------------------------------------------------------------------------------- +// boolInVec class +// + +class boolInVec +{ + private: + __m128 mData; + + inline boolInVec(__m128 vec); + public: + inline boolInVec() {} + + // matches standard type conversions + // + inline boolInVec(const floatInVec &vec); + + // explicit cast from bool + // + explicit inline boolInVec(bool scalar); + +#ifdef _VECTORMATH_NO_SCALAR_CAST + // explicit cast to bool + // + inline bool getAsBool() const; +#else + // implicit cast to bool + // + inline operator bool() const; +#endif + + // get vector data + // bool value is splatted across all word slots of vector as 0 (false) or -1 (true) + // + inline __m128 get128() const; + + // operators + // + inline const boolInVec operator ! () const; + inline boolInVec& operator = (const boolInVec &vec); + inline boolInVec& operator &= (const boolInVec &vec); + inline boolInVec& operator ^= (const boolInVec &vec); + inline boolInVec& operator |= (const boolInVec &vec); + + // friend functions + // + friend inline const boolInVec operator == (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec operator != (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec operator < (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator <= (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator > (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator >= (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator == (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator != (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator & (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec operator ^ (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec operator | (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec select(const boolInVec &vec0, const boolInVec &vec1, const boolInVec &select_vec1); +}; + +//-------------------------------------------------------------------------------------------------- +// boolInVec functions +// + +// operators +// +inline const boolInVec operator == (const boolInVec &vec0, const boolInVec &vec1); +inline const boolInVec operator != (const boolInVec &vec0, const boolInVec &vec1); +inline const boolInVec operator & (const boolInVec &vec0, const boolInVec &vec1); +inline const boolInVec operator ^ (const boolInVec &vec0, const boolInVec &vec1); +inline const boolInVec operator | (const boolInVec &vec0, const boolInVec &vec1); + +// select between vec0 and vec1 using boolInVec. +// false selects vec0, true selects vec1 +// +inline const boolInVec select(const boolInVec &vec0, const boolInVec &vec1, const boolInVec &select_vec1); + +} // namespace Vectormath + +//-------------------------------------------------------------------------------------------------- +// boolInVec implementation +// + +#include "floatInVec.h" + +namespace Vectormath { + +inline +boolInVec::boolInVec(__m128 vec) +{ + mData = vec; +} + +inline +boolInVec::boolInVec(const floatInVec &vec) +{ + *this = (vec != floatInVec(0.0f)); +} + +inline +boolInVec::boolInVec(bool scalar) +{ + unsigned int mask = -(int)scalar; + mData = _mm_set1_ps(*(float *)&mask); // TODO: Union +} + +#ifdef _VECTORMATH_NO_SCALAR_CAST +inline +bool +boolInVec::getAsBool() const +#else +inline +boolInVec::operator bool() const +#endif +{ + return *(bool *)&mData; +} + +inline +__m128 +boolInVec::get128() const +{ + return mData; +} + +inline +const boolInVec +boolInVec::operator ! () const +{ + return boolInVec(_mm_andnot_ps(mData, _mm_cmpneq_ps(_mm_setzero_ps(),_mm_setzero_ps()))); +} + +inline +boolInVec& +boolInVec::operator = (const boolInVec &vec) +{ + mData = vec.mData; + return *this; +} + +inline +boolInVec& +boolInVec::operator &= (const boolInVec &vec) +{ + *this = *this & vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator ^= (const boolInVec &vec) +{ + *this = *this ^ vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator |= (const boolInVec &vec) +{ + *this = *this | vec; + return *this; +} + +inline +const boolInVec +operator == (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_cmpeq_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator != (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_cmpneq_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator & (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_and_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator | (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_or_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator ^ (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_xor_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +select(const boolInVec &vec0, const boolInVec &vec1, const boolInVec &select_vec1) +{ + return boolInVec(vec_sel(vec0.get128(), vec1.get128(), select_vec1.get128())); +} + +} // namespace Vectormath + +#endif // boolInVec_h diff --git a/src/vectormath/sse/floatInVec.h b/src/vectormath/sse/floatInVec.h new file mode 100644 index 0000000..6443865 --- /dev/null +++ b/src/vectormath/sse/floatInVec.h @@ -0,0 +1,340 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _FLOATINVEC_H +#define _FLOATINVEC_H + +#include +#include + +namespace Vectormath { + +class boolInVec; + +//-------------------------------------------------------------------------------------------------- +// floatInVec class +// + +class floatInVec +{ + private: + __m128 mData; + + public: + inline floatInVec(__m128 vec); + + inline floatInVec() {} + + // matches standard type conversions + // + inline floatInVec(const boolInVec &vec); + + // construct from a slot of __m128 + // + inline floatInVec(__m128 vec, int slot); + + // explicit cast from float + // + explicit inline floatInVec(float scalar); + +#ifdef _VECTORMATH_NO_SCALAR_CAST + // explicit cast to float + // + inline float getAsFloat() const; +#else + // implicit cast to float + // + inline operator float() const; +#endif + + // get vector data + // float value is splatted across all word slots of vector + // + inline __m128 get128() const; + + // operators + // + inline const floatInVec operator ++ (int); + inline const floatInVec operator -- (int); + inline floatInVec& operator ++ (); + inline floatInVec& operator -- (); + inline const floatInVec operator - () const; + inline floatInVec& operator = (const floatInVec &vec); + inline floatInVec& operator *= (const floatInVec &vec); + inline floatInVec& operator /= (const floatInVec &vec); + inline floatInVec& operator += (const floatInVec &vec); + inline floatInVec& operator -= (const floatInVec &vec); + + // friend functions + // + friend inline const floatInVec operator * (const floatInVec &vec0, const floatInVec &vec1); + friend inline const floatInVec operator / (const floatInVec &vec0, const floatInVec &vec1); + friend inline const floatInVec operator + (const floatInVec &vec0, const floatInVec &vec1); + friend inline const floatInVec operator - (const floatInVec &vec0, const floatInVec &vec1); + friend inline const floatInVec select(const floatInVec &vec0, const floatInVec &vec1, boolInVec select_vec1); +}; + +//-------------------------------------------------------------------------------------------------- +// floatInVec functions +// + +// operators +// +inline const floatInVec operator * (const floatInVec &vec0, const floatInVec &vec1); +inline const floatInVec operator / (const floatInVec &vec0, const floatInVec &vec1); +inline const floatInVec operator + (const floatInVec &vec0, const floatInVec &vec1); +inline const floatInVec operator - (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator < (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator <= (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator > (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator >= (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator == (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator != (const floatInVec &vec0, const floatInVec &vec1); + +// select between vec0 and vec1 using boolInVec. +// false selects vec0, true selects vec1 +// +inline const floatInVec select(const floatInVec &vec0, const floatInVec &vec1, const boolInVec &select_vec1); + +} // namespace Vectormath + +//-------------------------------------------------------------------------------------------------- +// floatInVec implementation +// + +#include "boolInVec.h" + +namespace Vectormath { + +inline +floatInVec::floatInVec(__m128 vec) +{ + mData = vec; +} + +inline +floatInVec::floatInVec(const boolInVec &vec) +{ + mData = vec_sel(_mm_setzero_ps(), _mm_set1_ps(1.0f), vec.get128()); +} + +inline +floatInVec::floatInVec(__m128 vec, int slot) +{ + SSEFloat v; + v.m128 = vec; + mData = _mm_set1_ps(v.f[slot]); +} + +inline +floatInVec::floatInVec(float scalar) +{ + mData = _mm_set1_ps(scalar); +} + +#ifdef _VECTORMATH_NO_SCALAR_CAST +inline +float +floatInVec::getAsFloat() const +#else +inline +floatInVec::operator float() const +#endif +{ + return *((float *)&mData); +} + +inline +__m128 +floatInVec::get128() const +{ + return mData; +} + +inline +const floatInVec +floatInVec::operator ++ (int) +{ + __m128 olddata = mData; + operator ++(); + return floatInVec(olddata); +} + +inline +const floatInVec +floatInVec::operator -- (int) +{ + __m128 olddata = mData; + operator --(); + return floatInVec(olddata); +} + +inline +floatInVec& +floatInVec::operator ++ () +{ + *this += floatInVec(_mm_set1_ps(1.0f)); + return *this; +} + +inline +floatInVec& +floatInVec::operator -- () +{ + *this -= floatInVec(_mm_set1_ps(1.0f)); + return *this; +} + +inline +const floatInVec +floatInVec::operator - () const +{ + return floatInVec(_mm_sub_ps(_mm_setzero_ps(), mData)); +} + +inline +floatInVec& +floatInVec::operator = (const floatInVec &vec) +{ + mData = vec.mData; + return *this; +} + +inline +floatInVec& +floatInVec::operator *= (const floatInVec &vec) +{ + *this = *this * vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator /= (const floatInVec &vec) +{ + *this = *this / vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator += (const floatInVec &vec) +{ + *this = *this + vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator -= (const floatInVec &vec) +{ + *this = *this - vec; + return *this; +} + +inline +const floatInVec +operator * (const floatInVec &vec0, const floatInVec &vec1) +{ + return floatInVec(_mm_mul_ps(vec0.get128(), vec1.get128())); +} + +inline +const floatInVec +operator / (const floatInVec &num, const floatInVec &den) +{ + return floatInVec(_mm_div_ps(num.get128(), den.get128())); +} + +inline +const floatInVec +operator + (const floatInVec &vec0, const floatInVec &vec1) +{ + return floatInVec(_mm_add_ps(vec0.get128(), vec1.get128())); +} + +inline +const floatInVec +operator - (const floatInVec &vec0, const floatInVec &vec1) +{ + return floatInVec(_mm_sub_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator < (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpgt_ps(vec1.get128(), vec0.get128())); +} + +inline +const boolInVec +operator <= (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpge_ps(vec1.get128(), vec0.get128())); +} + +inline +const boolInVec +operator > (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpgt_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator >= (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpge_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator == (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpeq_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator != (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpneq_ps(vec0.get128(), vec1.get128())); +} + +inline +const floatInVec +select(const floatInVec &vec0, const floatInVec &vec1, const boolInVec &select_vec1) +{ + return floatInVec(vec_sel(vec0.get128(), vec1.get128(), select_vec1.get128())); +} + +} // namespace Vectormath + +#endif // floatInVec_h diff --git a/src/vectormath/sse/mat_aos.h b/src/vectormath/sse/mat_aos.h new file mode 100644 index 0000000..fe6aa62 --- /dev/null +++ b/src/vectormath/sse/mat_aos.h @@ -0,0 +1,2190 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _VECTORMATH_MAT_AOS_CPP_H +#define _VECTORMATH_MAT_AOS_CPP_H + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// Constants +// for shuffles, words are labeled [x,y,z,w] [a,b,c,d] + +#define _VECTORMATH_PERM_ZBWX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XCYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_C, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XYAB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_ZWCD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W, _VECTORMATH_PERM_C, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_XZBX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_CXXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_YAXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XAZC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_YXWZ ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W, _VECTORMATH_PERM_Z }) +#define _VECTORMATH_PERM_YBWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_XYCX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_YCXY ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y }) +#define _VECTORMATH_PERM_CXYC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_ZAYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_BZXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_B, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XZYA ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A }) +#define _VECTORMATH_PERM_ZXXB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_YXXC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_BBYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_B, _VECTORMATH_PERM_B, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PI_OVER_2 1.570796327f + +//----------------------------------------------------------------------------- +// Definitions + +VECTORMATH_FORCE_INLINE Matrix3::Matrix3( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; +} + +VECTORMATH_FORCE_INLINE Matrix3::Matrix3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +VECTORMATH_FORCE_INLINE Matrix3::Matrix3( const floatInVec &scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +VECTORMATH_FORCE_INLINE Matrix3::Matrix3( const Quat &unitQuat ) +{ + __m128 xyzw_2, wwww, yzxw, zxyw, yzxw_2, zxyw_2; + __m128 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + VM_ATTRIBUTE_ALIGN16 unsigned int sx[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int sz[4] = {0, 0, 0xffffffff, 0}; + __m128 select_x = _mm_load_ps((float *)sx); + __m128 select_z = _mm_load_ps((float *)sz); + + xyzw_2 = _mm_add_ps( unitQuat.get128(), unitQuat.get128() ); + wwww = _mm_shuffle_ps( unitQuat.get128(), unitQuat.get128(), _MM_SHUFFLE(3,3,3,3) ); + yzxw = _mm_shuffle_ps( unitQuat.get128(), unitQuat.get128(), _MM_SHUFFLE(3,0,2,1) ); + zxyw = _mm_shuffle_ps( unitQuat.get128(), unitQuat.get128(), _MM_SHUFFLE(3,1,0,2) ); + yzxw_2 = _mm_shuffle_ps( xyzw_2, xyzw_2, _MM_SHUFFLE(3,0,2,1) ); + zxyw_2 = _mm_shuffle_ps( xyzw_2, xyzw_2, _MM_SHUFFLE(3,1,0,2) ); + + tmp0 = _mm_mul_ps( yzxw_2, wwww ); // tmp0 = 2yw, 2zw, 2xw, 2w2 + tmp1 = _mm_sub_ps( _mm_set1_ps(1.0f), _mm_mul_ps(yzxw, yzxw_2) ); // tmp1 = 1 - 2y2, 1 - 2z2, 1 - 2x2, 1 - 2w2 + tmp2 = _mm_mul_ps( yzxw, xyzw_2 ); // tmp2 = 2xy, 2yz, 2xz, 2w2 + tmp0 = _mm_add_ps( _mm_mul_ps(zxyw, xyzw_2), tmp0 ); // tmp0 = 2yw + 2zx, 2zw + 2xy, 2xw + 2yz, 2w2 + 2w2 + tmp1 = _mm_sub_ps( tmp1, _mm_mul_ps(zxyw, zxyw_2) ); // tmp1 = 1 - 2y2 - 2z2, 1 - 2z2 - 2x2, 1 - 2x2 - 2y2, 1 - 2w2 - 2w2 + tmp2 = _mm_sub_ps( tmp2, _mm_mul_ps(zxyw_2, wwww) ); // tmp2 = 2xy - 2zw, 2yz - 2xw, 2xz - 2yw, 2w2 -2w2 + + tmp3 = vec_sel( tmp0, tmp1, select_x ); + tmp4 = vec_sel( tmp1, tmp2, select_x ); + tmp5 = vec_sel( tmp2, tmp0, select_x ); + mCol0 = Vector3( vec_sel( tmp3, tmp2, select_z ) ); + mCol1 = Vector3( vec_sel( tmp4, tmp0, select_z ) ); + mCol2 = Vector3( vec_sel( tmp5, tmp1, select_z ) ); +} + +VECTORMATH_FORCE_INLINE Matrix3::Matrix3( const Vector3 &_col0, const Vector3 &_col1, const Vector3 &_col2 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setCol0( const Vector3 &_col0 ) +{ + mCol0 = _col0; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setCol1( const Vector3 &_col1 ) +{ + mCol1 = _col1; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setCol2( const Vector3 &_col2 ) +{ + mCol2 = _col2; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setCol( int col, const Vector3 &vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setRow( int row, const Vector3 &vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setElem( int col, int row, const floatInVec &val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Matrix3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getCol0( ) const +{ + return mCol0; +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getCol1( ) const +{ + return mCol1; +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getCol2( ) const +{ + return mCol2; +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getRow( int row ) const +{ + return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Matrix3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator =( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 transpose( const Matrix3 & mat ) +{ + __m128 tmp0, tmp1, res0, res1, res2; + tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp1 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); + res0 = vec_mergeh( tmp0, mat.getCol1().get128() ); + //res1 = vec_perm( tmp0, mat.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + res1 = _mm_shuffle_ps( tmp0, tmp0, _MM_SHUFFLE(0,3,2,2)); + res1 = vec_sel(res1, mat.getCol1().get128(), select_y); + //res2 = vec_perm( tmp1, mat.getCol1().get128(), _VECTORMATH_PERM_XCYX ); + res2 = _mm_shuffle_ps( tmp1, tmp1, _MM_SHUFFLE(0,1,1,0)); + res2 = vec_sel(res2, vec_splat(mat.getCol1().get128(), 2), select_y); + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 inverse( const Matrix3 & mat ) +{ + __m128 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet, inv0, inv1, inv2; + tmp2 = _vmathVfCross( mat.getCol0().get128(), mat.getCol1().get128() ); + tmp0 = _vmathVfCross( mat.getCol1().get128(), mat.getCol2().get128() ); + tmp1 = _vmathVfCross( mat.getCol2().get128(), mat.getCol0().get128() ); + dot = _vmathVfDot3( tmp2, mat.getCol2().get128() ); + dot = vec_splat( dot, 0 ); + invdet = recipf4( dot ); + tmp3 = vec_mergeh( tmp0, tmp2 ); + tmp4 = vec_mergel( tmp0, tmp2 ); + inv0 = vec_mergeh( tmp3, tmp1 ); + //inv1 = vec_perm( tmp3, tmp1, _VECTORMATH_PERM_ZBWX ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + inv1 = _mm_shuffle_ps( tmp3, tmp3, _MM_SHUFFLE(0,3,2,2)); + inv1 = vec_sel(inv1, tmp1, select_y); + //inv2 = vec_perm( tmp4, tmp1, _VECTORMATH_PERM_XCYX ); + inv2 = _mm_shuffle_ps( tmp4, tmp4, _MM_SHUFFLE(0,1,1,0)); + inv2 = vec_sel(inv2, vec_splat(tmp1, 2), select_y); + inv0 = vec_mul( inv0, invdet ); + inv1 = vec_mul( inv1, invdet ); + inv2 = vec_mul( inv2, invdet ); + return Matrix3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ) + ); +} + +VECTORMATH_FORCE_INLINE const floatInVec determinant( const Matrix3 & mat ) +{ + return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) +{ + *this = *this + mat; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) +{ + *this = *this - mat; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator -( ) const +{ + return Matrix3( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 absPerElem( const Matrix3 & mat ) +{ + return Matrix3( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator *( const floatInVec &scalar ) const +{ + return Matrix3( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator *=( float scalar ) +{ + return *this *= floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 operator *( float scalar, const Matrix3 & mat ) +{ + return floatInVec(scalar) * mat; +} + +VECTORMATH_FORCE_INLINE const Matrix3 operator *( const floatInVec &scalar, const Matrix3 & mat ) +{ + return mat * scalar; +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::operator *( const Vector3 &vec ) const +{ + __m128 res; + __m128 xxxx, yyyy, zzzz; + xxxx = vec_splat( vec.get128(), 0 ); + yyyy = vec_splat( vec.get128(), 1 ); + zzzz = vec_splat( vec.get128(), 2 ); + res = vec_mul( mCol0.get128(), xxxx ); + res = vec_madd( mCol1.get128(), yyyy, res ); + res = vec_madd( mCol2.get128(), zzzz, res ); + return Vector3( res ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const +{ + return Matrix3( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) +{ + *this = *this * mat; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) +{ + return Matrix3( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::identity( ) +{ + return Matrix3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationX( const floatInVec &radians ) +{ + __m128 s, c, res1, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + return Matrix3( + Vector3::xAxis( ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationY( const floatInVec &radians ) +{ + __m128 s, c, res0, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + return Matrix3( + Vector3( res0 ), + Vector3::yAxis( ), + Vector3( res2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationZ( const floatInVec &radians ) +{ + __m128 s, c, res0, res1; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3::zAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationZYX( const Vector3 &radiansXYZ ) +{ + __m128 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + angles = Vector4( radiansXYZ, 0.0f ).get128(); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; + Z1 = vec_and( Z1, _mm_load_ps( (float *)select_xyz ) ); + Y0 = _mm_shuffle_ps( c, negS, _MM_SHUFFLE(0,1,1,1) ); + Y1 = _mm_shuffle_ps( s, c, _MM_SHUFFLE(0,1,1,1) ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_mul( Z0, Y1 ); + return Matrix3( + Vector3( vec_mul( Z0, Y0 ) ), + Vector3( vec_madd( Z1, X1, vec_mul( tmp, X0 ) ) ), + Vector3( vec_nmsub( Z1, X0, vec_mul( tmp, X1 ) ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotation( float radians, const Vector3 &unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotation( const floatInVec &radians, const Vector3 &unitVec ) +{ + __m128 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2; + axis = unitVec.get128(); + sincosf4( radians.get128(), &s, &c ); + xxxx = vec_splat( axis, 0 ); + yyyy = vec_splat( axis, 1 ); + zzzz = vec_splat( axis, 2 ); + oneMinusC = vec_sub( _mm_set1_ps(1.0f), c ); + axisS = vec_mul( axis, s ); + negAxisS = negatef4( axisS ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + //tmp0 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_XZBX ); + tmp0 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,2,0) ); + tmp0 = vec_sel(tmp0, vec_splat(negAxisS, 1), select_z); + //tmp1 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_CXXX ); + tmp1 = vec_sel( vec_splat(axisS, 0), vec_splat(negAxisS, 2), select_x ); + //tmp2 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_YAXX ); + tmp2 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,0,1) ); + tmp2 = vec_sel(tmp2, vec_splat(negAxisS, 0), select_y); + tmp0 = vec_sel( tmp0, c, select_x ); + tmp1 = vec_sel( tmp1, c, select_y ); + tmp2 = vec_sel( tmp2, c, select_z ); + return Matrix3( + Vector3( vec_madd( vec_mul( axis, xxxx ), oneMinusC, tmp0 ) ), + Vector3( vec_madd( vec_mul( axis, yyyy ), oneMinusC, tmp1 ) ), + Vector3( vec_madd( vec_mul( axis, zzzz ), oneMinusC, tmp2 ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotation( const Quat &unitQuat ) +{ + return Matrix3( unitQuat ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::scale( const Vector3 &scaleVec ) +{ + __m128 zero = _mm_setzero_ps(); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + return Matrix3( + Vector3( vec_sel( zero, scaleVec.get128(), select_x ) ), + Vector3( vec_sel( zero, scaleVec.get128(), select_y ) ), + Vector3( vec_sel( zero, scaleVec.get128(), select_z ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 appendScale( const Matrix3 & mat, const Vector3 &scaleVec ) +{ + return Matrix3( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 prependScale( const Vector3 &scaleVec, const Matrix3 & mat ) +{ + return Matrix3( + mulPerElem( mat.getCol0(), scaleVec ), + mulPerElem( mat.getCol1(), scaleVec ), + mulPerElem( mat.getCol2(), scaleVec ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, const boolInVec &select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Matrix3 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); +} + +VECTORMATH_FORCE_INLINE void print( const Matrix3 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( float scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const floatInVec &scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Transform3 & mat ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( mat.getCol3(), 1.0f ); +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Vector4 &_col0, const Vector4 &_col1, const Vector4 &_col2, const Vector4 &_col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Matrix3 & mat, const Vector3 &translateVec ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Quat &unitQuat, const Vector3 &translateVec ) +{ + Matrix3 mat; + mat = Matrix3( unitQuat ); + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol0( const Vector4 &_col0 ) +{ + mCol0 = _col0; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol1( const Vector4 &_col1 ) +{ + mCol1 = _col1; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol2( const Vector4 &_col2 ) +{ + mCol2 = _col2; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol3( const Vector4 &_col3 ) +{ + mCol3 = _col3; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol( int col, const Vector4 &vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setRow( int row, const Vector4 &vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setElem( int col, int row, const floatInVec &val ) +{ + Vector4 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Matrix4::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol0( ) const +{ + return mCol0; +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol1( ) const +{ + return mCol1; +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol2( ) const +{ + return mCol2; +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol3( ) const +{ + return mCol3; +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Matrix4::operator []( int col ) +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator =( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix4 transpose( const Matrix4 & mat ) +{ + __m128 tmp0, tmp1, tmp2, tmp3, res0, res1, res2, res3; + tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp1 = vec_mergeh( mat.getCol1().get128(), mat.getCol3().get128() ); + tmp2 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp3 = vec_mergel( mat.getCol1().get128(), mat.getCol3().get128() ); + res0 = vec_mergeh( tmp0, tmp1 ); + res1 = vec_mergel( tmp0, tmp1 ); + res2 = vec_mergeh( tmp2, tmp3 ); + res3 = vec_mergel( tmp2, tmp3 ); + return Matrix4( + Vector4( res0 ), + Vector4( res1 ), + Vector4( res2 ), + Vector4( res3 ) + ); +} + +// TODO: Tidy +static VM_ATTRIBUTE_ALIGN16 const unsigned int _vmathPNPN[4] = {0x00000000, 0x80000000, 0x00000000, 0x80000000}; +static VM_ATTRIBUTE_ALIGN16 const unsigned int _vmathNPNP[4] = {0x80000000, 0x00000000, 0x80000000, 0x00000000}; +static VM_ATTRIBUTE_ALIGN16 const float _vmathZERONE[4] = {1.0f, 0.0f, 0.0f, 1.0f}; + +VECTORMATH_FORCE_INLINE const Matrix4 inverse( const Matrix4 & mat ) +{ + __m128 Va,Vb,Vc; + __m128 r1,r2,r3,tt,tt2; + __m128 sum,Det,RDet; + __m128 trns0,trns1,trns2,trns3; + + __m128 _L1 = mat.getCol0().get128(); + __m128 _L2 = mat.getCol1().get128(); + __m128 _L3 = mat.getCol2().get128(); + __m128 _L4 = mat.getCol3().get128(); + // Calculating the minterms for the first line. + + // _mm_ror_ps is just a macro using _mm_shuffle_ps(). + tt = _L4; tt2 = _mm_ror_ps(_L3,1); + Vc = _mm_mul_ps(tt2,_mm_ror_ps(tt,0)); // V3'dot V4 + Va = _mm_mul_ps(tt2,_mm_ror_ps(tt,2)); // V3'dot V4" + Vb = _mm_mul_ps(tt2,_mm_ror_ps(tt,3)); // V3' dot V4^ + + r1 = _mm_sub_ps(_mm_ror_ps(Va,1),_mm_ror_ps(Vc,2)); // V3" dot V4^ - V3^ dot V4" + r2 = _mm_sub_ps(_mm_ror_ps(Vb,2),_mm_ror_ps(Vb,0)); // V3^ dot V4' - V3' dot V4^ + r3 = _mm_sub_ps(_mm_ror_ps(Va,0),_mm_ror_ps(Vc,1)); // V3' dot V4" - V3" dot V4' + + tt = _L2; + Va = _mm_ror_ps(tt,1); sum = _mm_mul_ps(Va,r1); + Vb = _mm_ror_ps(tt,2); sum = _mm_add_ps(sum,_mm_mul_ps(Vb,r2)); + Vc = _mm_ror_ps(tt,3); sum = _mm_add_ps(sum,_mm_mul_ps(Vc,r3)); + + // Calculating the determinant. + Det = _mm_mul_ps(sum,_L1); + Det = _mm_add_ps(Det,_mm_movehl_ps(Det,Det)); + + const __m128 Sign_PNPN = _mm_load_ps((float *)_vmathPNPN); + const __m128 Sign_NPNP = _mm_load_ps((float *)_vmathNPNP); + + __m128 mtL1 = _mm_xor_ps(sum,Sign_PNPN); + + // Calculating the minterms of the second line (using previous results). + tt = _mm_ror_ps(_L1,1); sum = _mm_mul_ps(tt,r1); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); + __m128 mtL2 = _mm_xor_ps(sum,Sign_NPNP); + + // Testing the determinant. + Det = _mm_sub_ss(Det,_mm_shuffle_ps(Det,Det,1)); + + // Calculating the minterms of the third line. + tt = _mm_ror_ps(_L1,1); + Va = _mm_mul_ps(tt,Vb); // V1' dot V2" + Vb = _mm_mul_ps(tt,Vc); // V1' dot V2^ + Vc = _mm_mul_ps(tt,_L2); // V1' dot V2 + + r1 = _mm_sub_ps(_mm_ror_ps(Va,1),_mm_ror_ps(Vc,2)); // V1" dot V2^ - V1^ dot V2" + r2 = _mm_sub_ps(_mm_ror_ps(Vb,2),_mm_ror_ps(Vb,0)); // V1^ dot V2' - V1' dot V2^ + r3 = _mm_sub_ps(_mm_ror_ps(Va,0),_mm_ror_ps(Vc,1)); // V1' dot V2" - V1" dot V2' + + tt = _mm_ror_ps(_L4,1); sum = _mm_mul_ps(tt,r1); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); + __m128 mtL3 = _mm_xor_ps(sum,Sign_PNPN); + + // Dividing is FASTER than rcp_nr! (Because rcp_nr causes many register-memory RWs). + RDet = _mm_div_ss(_mm_load_ss((float *)&_vmathZERONE), Det); // TODO: just 1.0f? + RDet = _mm_shuffle_ps(RDet,RDet,0x00); + + // Devide the first 12 minterms with the determinant. + mtL1 = _mm_mul_ps(mtL1, RDet); + mtL2 = _mm_mul_ps(mtL2, RDet); + mtL3 = _mm_mul_ps(mtL3, RDet); + + // Calculate the minterms of the forth line and devide by the determinant. + tt = _mm_ror_ps(_L3,1); sum = _mm_mul_ps(tt,r1); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); + __m128 mtL4 = _mm_xor_ps(sum,Sign_NPNP); + mtL4 = _mm_mul_ps(mtL4, RDet); + + // Now we just have to transpose the minterms matrix. + trns0 = _mm_unpacklo_ps(mtL1,mtL2); + trns1 = _mm_unpacklo_ps(mtL3,mtL4); + trns2 = _mm_unpackhi_ps(mtL1,mtL2); + trns3 = _mm_unpackhi_ps(mtL3,mtL4); + _L1 = _mm_movelh_ps(trns0,trns1); + _L2 = _mm_movehl_ps(trns1,trns0); + _L3 = _mm_movelh_ps(trns2,trns3); + _L4 = _mm_movehl_ps(trns3,trns2); + + return Matrix4( + Vector4( _L1 ), + Vector4( _L2 ), + Vector4( _L3 ), + Vector4( _L4 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 affineInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( inverse( affineMat ) ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 orthoInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( orthoInverse( affineMat ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec determinant( const Matrix4 & mat ) +{ + __m128 Va,Vb,Vc; + __m128 r1,r2,r3,tt,tt2; + __m128 sum,Det; + + __m128 _L1 = mat.getCol0().get128(); + __m128 _L2 = mat.getCol1().get128(); + __m128 _L3 = mat.getCol2().get128(); + __m128 _L4 = mat.getCol3().get128(); + // Calculating the minterms for the first line. + + // _mm_ror_ps is just a macro using _mm_shuffle_ps(). + tt = _L4; tt2 = _mm_ror_ps(_L3,1); + Vc = _mm_mul_ps(tt2,_mm_ror_ps(tt,0)); // V3' dot V4 + Va = _mm_mul_ps(tt2,_mm_ror_ps(tt,2)); // V3' dot V4" + Vb = _mm_mul_ps(tt2,_mm_ror_ps(tt,3)); // V3' dot V4^ + + r1 = _mm_sub_ps(_mm_ror_ps(Va,1),_mm_ror_ps(Vc,2)); // V3" dot V4^ - V3^ dot V4" + r2 = _mm_sub_ps(_mm_ror_ps(Vb,2),_mm_ror_ps(Vb,0)); // V3^ dot V4' - V3' dot V4^ + r3 = _mm_sub_ps(_mm_ror_ps(Va,0),_mm_ror_ps(Vc,1)); // V3' dot V4" - V3" dot V4' + + tt = _L2; + Va = _mm_ror_ps(tt,1); sum = _mm_mul_ps(Va,r1); + Vb = _mm_ror_ps(tt,2); sum = _mm_add_ps(sum,_mm_mul_ps(Vb,r2)); + Vc = _mm_ror_ps(tt,3); sum = _mm_add_ps(sum,_mm_mul_ps(Vc,r3)); + + // Calculating the determinant. + Det = _mm_mul_ps(sum,_L1); + Det = _mm_add_ps(Det,_mm_movehl_ps(Det,Det)); + + // Calculating the minterms of the second line (using previous results). + tt = _mm_ror_ps(_L1,1); sum = _mm_mul_ps(tt,r1); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); + + // Testing the determinant. + Det = _mm_sub_ss(Det,_mm_shuffle_ps(Det,Det,1)); + return floatInVec(Det, 0); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ), + ( mCol3 + mat.mCol3 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ), + ( mCol3 - mat.mCol3 ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) +{ + *this = *this + mat; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) +{ + *this = *this - mat; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator -( ) const +{ + return Matrix4( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ), + ( -mCol3 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 absPerElem( const Matrix4 & mat ) +{ + return Matrix4( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ), + absPerElem( mat.getCol3() ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator *( const floatInVec &scalar ) const +{ + return Matrix4( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ), + ( mCol3 * scalar ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator *=( float scalar ) +{ + return *this *= floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix4 operator *( float scalar, const Matrix4 & mat ) +{ + return floatInVec(scalar) * mat; +} + +VECTORMATH_FORCE_INLINE const Matrix4 operator *( const floatInVec &scalar, const Matrix4 & mat ) +{ + return mat * scalar; +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::operator *( const Vector4 &vec ) const +{ + return Vector4( + _mm_add_ps( + _mm_add_ps(_mm_mul_ps(mCol0.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(0,0,0,0))), _mm_mul_ps(mCol1.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(1,1,1,1)))), + _mm_add_ps(_mm_mul_ps(mCol2.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(2,2,2,2))), _mm_mul_ps(mCol3.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(3,3,3,3))))) + ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::operator *( const Vector3 &vec ) const +{ + return Vector4( + _mm_add_ps( + _mm_add_ps(_mm_mul_ps(mCol0.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(0,0,0,0))), _mm_mul_ps(mCol1.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(1,1,1,1)))), + _mm_mul_ps(mCol2.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(2,2,2,2)))) + ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::operator *( const Point3 &pnt ) const +{ + return Vector4( + _mm_add_ps( + _mm_add_ps(_mm_mul_ps(mCol0.get128(), _mm_shuffle_ps(pnt.get128(), pnt.get128(), _MM_SHUFFLE(0,0,0,0))), _mm_mul_ps(mCol1.get128(), _mm_shuffle_ps(pnt.get128(), pnt.get128(), _MM_SHUFFLE(1,1,1,1)))), + _mm_add_ps(_mm_mul_ps(mCol2.get128(), _mm_shuffle_ps(pnt.get128(), pnt.get128(), _MM_SHUFFLE(2,2,2,2))), mCol3.get128())) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const +{ + return Matrix4( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ), + ( *this * mat.mCol3 ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) +{ + *this = *this * mat; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const +{ + return Matrix4( + ( *this * tfrm.getCol0() ), + ( *this * tfrm.getCol1() ), + ( *this * tfrm.getCol2() ), + ( *this * Point3( tfrm.getCol3() ) ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) +{ + return Matrix4( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ), + mulPerElem( mat0.getCol3(), mat1.getCol3() ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::identity( ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) +{ + mCol0.setXYZ( mat3.getCol0() ); + mCol1.setXYZ( mat3.getCol1() ); + mCol2.setXYZ( mat3.getCol2() ); + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix4::getUpper3x3( ) const +{ + return Matrix3( + mCol0.getXYZ( ), + mCol1.getXYZ( ), + mCol2.getXYZ( ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setTranslation( const Vector3 &translateVec ) +{ + mCol3.setXYZ( translateVec ); + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix4::getTranslation( ) const +{ + return mCol3.getXYZ( ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationX( const floatInVec &radians ) +{ + __m128 s, c, res1, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + return Matrix4( + Vector4::xAxis( ), + Vector4( res1 ), + Vector4( res2 ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationY( const floatInVec &radians ) +{ + __m128 s, c, res0, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + return Matrix4( + Vector4( res0 ), + Vector4::yAxis( ), + Vector4( res2 ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationZ( const floatInVec &radians ) +{ + __m128 s, c, res0, res1; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + return Matrix4( + Vector4( res0 ), + Vector4( res1 ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationZYX( const Vector3 &radiansXYZ ) +{ + __m128 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + angles = Vector4( radiansXYZ, 0.0f ).get128(); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; + Z1 = vec_and( Z1, _mm_load_ps( (float *)select_xyz ) ); + Y0 = _mm_shuffle_ps( c, negS, _MM_SHUFFLE(0,1,1,1) ); + Y1 = _mm_shuffle_ps( s, c, _MM_SHUFFLE(0,1,1,1) ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_mul( Z0, Y1 ); + return Matrix4( + Vector4( vec_mul( Z0, Y0 ) ), + Vector4( vec_madd( Z1, X1, vec_mul( tmp, X0 ) ) ), + Vector4( vec_nmsub( Z1, X0, vec_mul( tmp, X1 ) ) ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotation( float radians, const Vector3 &unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotation( const floatInVec &radians, const Vector3 &unitVec ) +{ + __m128 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2; + axis = unitVec.get128(); + sincosf4( radians.get128(), &s, &c ); + xxxx = vec_splat( axis, 0 ); + yyyy = vec_splat( axis, 1 ); + zzzz = vec_splat( axis, 2 ); + oneMinusC = vec_sub( _mm_set1_ps(1.0f), c ); + axisS = vec_mul( axis, s ); + negAxisS = negatef4( axisS ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + //tmp0 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_XZBX ); + tmp0 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,2,0) ); + tmp0 = vec_sel(tmp0, vec_splat(negAxisS, 1), select_z); + //tmp1 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_CXXX ); + tmp1 = vec_sel( vec_splat(axisS, 0), vec_splat(negAxisS, 2), select_x ); + //tmp2 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_YAXX ); + tmp2 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,0,1) ); + tmp2 = vec_sel(tmp2, vec_splat(negAxisS, 0), select_y); + tmp0 = vec_sel( tmp0, c, select_x ); + tmp1 = vec_sel( tmp1, c, select_y ); + tmp2 = vec_sel( tmp2, c, select_z ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; + axis = vec_and( axis, _mm_load_ps( (float *)select_xyz ) ); + tmp0 = vec_and( tmp0, _mm_load_ps( (float *)select_xyz ) ); + tmp1 = vec_and( tmp1, _mm_load_ps( (float *)select_xyz ) ); + tmp2 = vec_and( tmp2, _mm_load_ps( (float *)select_xyz ) ); + return Matrix4( + Vector4( vec_madd( vec_mul( axis, xxxx ), oneMinusC, tmp0 ) ), + Vector4( vec_madd( vec_mul( axis, yyyy ), oneMinusC, tmp1 ) ), + Vector4( vec_madd( vec_mul( axis, zzzz ), oneMinusC, tmp2 ) ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotation( const Quat &unitQuat ) +{ + return Matrix4( Transform3::rotation( unitQuat ) ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::scale( const Vector3 &scaleVec ) +{ + __m128 zero = _mm_setzero_ps(); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + return Matrix4( + Vector4( vec_sel( zero, scaleVec.get128(), select_x ) ), + Vector4( vec_sel( zero, scaleVec.get128(), select_y ) ), + Vector4( vec_sel( zero, scaleVec.get128(), select_z ) ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 appendScale( const Matrix4 & mat, const Vector3 &scaleVec ) +{ + return Matrix4( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ), + mat.getCol3() + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 prependScale( const Vector3 &scaleVec, const Matrix4 & mat ) +{ + Vector4 scale4; + scale4 = Vector4( scaleVec, 1.0f ); + return Matrix4( + mulPerElem( mat.getCol0(), scale4 ), + mulPerElem( mat.getCol1(), scale4 ), + mulPerElem( mat.getCol2(), scale4 ), + mulPerElem( mat.getCol3(), scale4 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::translation( const Vector3 &translateVec ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4( translateVec, 1.0f ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::lookAt( const Point3 &eyePos, const Point3 &lookAtPos, const Vector3 &upVec ) +{ + Matrix4 m4EyeFrame; + Vector3 v3X, v3Y, v3Z; + v3Y = normalize( upVec ); + v3Z = normalize( ( eyePos - lookAtPos ) ); + v3X = normalize( cross( v3Y, v3Z ) ); + v3Y = cross( v3Z, v3X ); + m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); + return orthoInverse( m4EyeFrame ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::perspective( float fovyRadians, float aspect, float zNear, float zFar ) +{ + float f, rangeInv; + __m128 zero, col0, col1, col2, col3; + union { __m128 v; float s[4]; } tmp; + f = tanf( _VECTORMATH_PI_OVER_2 - fovyRadians * 0.5f ); + rangeInv = 1.0f / ( zNear - zFar ); + zero = _mm_setzero_ps(); + tmp.v = zero; + tmp.s[0] = f / aspect; + col0 = tmp.v; + tmp.v = zero; + tmp.s[1] = f; + col1 = tmp.v; + tmp.v = zero; + tmp.s[2] = ( zNear + zFar ) * rangeInv; + tmp.s[3] = -1.0f; + col2 = tmp.v; + tmp.v = zero; + tmp.s[2] = zNear * zFar * rangeInv * 2.0f; + col3 = tmp.v; + return Matrix4( + Vector4( col0 ), + Vector4( col1 ), + Vector4( col2 ), + Vector4( col3 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::frustum( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + __m128 lbf, rtn; + __m128 diff, sum, inv_diff; + __m128 diagonal, column, near2; + __m128 zero = _mm_setzero_ps(); + union { __m128 v; float s[4]; } l, f, r, n, b, t; // TODO: Union? + l.s[0] = left; + f.s[0] = zFar; + r.s[0] = right; + n.s[0] = zNear; + b.s[0] = bottom; + t.s[0] = top; + lbf = vec_mergeh( l.v, f.v ); + rtn = vec_mergeh( r.v, n.v ); + lbf = vec_mergeh( lbf, b.v ); + rtn = vec_mergeh( rtn, t.v ); + diff = vec_sub( rtn, lbf ); + sum = vec_add( rtn, lbf ); + inv_diff = recipf4( diff ); + near2 = vec_splat( n.v, 0 ); + near2 = vec_add( near2, near2 ); + diagonal = vec_mul( near2, inv_diff ); + column = vec_mul( sum, inv_diff ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_w[4] = {0, 0, 0, 0xffffffff}; + return Matrix4( + Vector4( vec_sel( zero, diagonal, select_x ) ), + Vector4( vec_sel( zero, diagonal, select_y ) ), + Vector4( vec_sel( column, _mm_set1_ps(-1.0f), select_w ) ), + Vector4( vec_sel( zero, vec_mul( diagonal, vec_splat( f.v, 0 ) ), select_z ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::orthographic( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + __m128 lbf, rtn; + __m128 diff, sum, inv_diff, neg_inv_diff; + __m128 diagonal, column; + __m128 zero = _mm_setzero_ps(); + union { __m128 v; float s[4]; } l, f, r, n, b, t; + l.s[0] = left; + f.s[0] = zFar; + r.s[0] = right; + n.s[0] = zNear; + b.s[0] = bottom; + t.s[0] = top; + lbf = vec_mergeh( l.v, f.v ); + rtn = vec_mergeh( r.v, n.v ); + lbf = vec_mergeh( lbf, b.v ); + rtn = vec_mergeh( rtn, t.v ); + diff = vec_sub( rtn, lbf ); + sum = vec_add( rtn, lbf ); + inv_diff = recipf4( diff ); + neg_inv_diff = negatef4( inv_diff ); + diagonal = vec_add( inv_diff, inv_diff ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_w[4] = {0, 0, 0, 0xffffffff}; + column = vec_mul( sum, vec_sel( neg_inv_diff, inv_diff, select_z ) ); // TODO: no madds with zero + return Matrix4( + Vector4( vec_sel( zero, diagonal, select_x ) ), + Vector4( vec_sel( zero, diagonal, select_y ) ), + Vector4( vec_sel( zero, diagonal, select_z ) ), + Vector4( vec_sel( column, _mm_set1_ps(1.0f), select_w ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, const boolInVec &select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Matrix4 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); + print( mat.getRow( 3 ) ); +} + +VECTORMATH_FORCE_INLINE void print( const Matrix4 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +VECTORMATH_FORCE_INLINE Transform3::Transform3( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; +} + +VECTORMATH_FORCE_INLINE Transform3::Transform3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +VECTORMATH_FORCE_INLINE Transform3::Transform3( const floatInVec &scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +VECTORMATH_FORCE_INLINE Transform3::Transform3( const Vector3 &_col0, const Vector3 &_col1, const Vector3 &_col2, const Vector3 &_col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +VECTORMATH_FORCE_INLINE Transform3::Transform3( const Matrix3 & tfrm, const Vector3 &translateVec ) +{ + this->setUpper3x3( tfrm ); + this->setTranslation( translateVec ); +} + +VECTORMATH_FORCE_INLINE Transform3::Transform3( const Quat &unitQuat, const Vector3 &translateVec ) +{ + this->setUpper3x3( Matrix3( unitQuat ) ); + this->setTranslation( translateVec ); +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol0( const Vector3 &_col0 ) +{ + mCol0 = _col0; + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol1( const Vector3 &_col1 ) +{ + mCol1 = _col1; + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol2( const Vector3 &_col2 ) +{ + mCol2 = _col2; + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol3( const Vector3 &_col3 ) +{ + mCol3 = _col3; + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol( int col, const Vector3 &vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setRow( int row, const Vector4 &vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setElem( int col, int row, const floatInVec &val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Transform3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol0( ) const +{ + return mCol0; +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol1( ) const +{ + return mCol1; +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol2( ) const +{ + return mCol2; +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol3( ) const +{ + return mCol3; +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector4 Transform3::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Transform3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::operator =( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; + return *this; +} + +VECTORMATH_FORCE_INLINE const Transform3 inverse( const Transform3 & tfrm ) +{ + __m128 inv0, inv1, inv2, inv3; + __m128 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet; + __m128 xxxx, yyyy, zzzz; + tmp2 = _vmathVfCross( tfrm.getCol0().get128(), tfrm.getCol1().get128() ); + tmp0 = _vmathVfCross( tfrm.getCol1().get128(), tfrm.getCol2().get128() ); + tmp1 = _vmathVfCross( tfrm.getCol2().get128(), tfrm.getCol0().get128() ); + inv3 = negatef4( tfrm.getCol3().get128() ); + dot = _vmathVfDot3( tmp2, tfrm.getCol2().get128() ); + dot = vec_splat( dot, 0 ); + invdet = recipf4( dot ); + tmp3 = vec_mergeh( tmp0, tmp2 ); + tmp4 = vec_mergel( tmp0, tmp2 ); + inv0 = vec_mergeh( tmp3, tmp1 ); + xxxx = vec_splat( inv3, 0 ); + //inv1 = vec_perm( tmp3, tmp1, _VECTORMATH_PERM_ZBWX ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + inv1 = _mm_shuffle_ps( tmp3, tmp3, _MM_SHUFFLE(0,3,2,2)); + inv1 = vec_sel(inv1, tmp1, select_y); + //inv2 = vec_perm( tmp4, tmp1, _VECTORMATH_PERM_XCYX ); + inv2 = _mm_shuffle_ps( tmp4, tmp4, _MM_SHUFFLE(0,1,1,0)); + inv2 = vec_sel(inv2, vec_splat(tmp1, 2), select_y); + yyyy = vec_splat( inv3, 1 ); + zzzz = vec_splat( inv3, 2 ); + inv3 = vec_mul( inv0, xxxx ); + inv3 = vec_madd( inv1, yyyy, inv3 ); + inv3 = vec_madd( inv2, zzzz, inv3 ); + inv0 = vec_mul( inv0, invdet ); + inv1 = vec_mul( inv1, invdet ); + inv2 = vec_mul( inv2, invdet ); + inv3 = vec_mul( inv3, invdet ); + return Transform3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ), + Vector3( inv3 ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 orthoInverse( const Transform3 & tfrm ) +{ + __m128 inv0, inv1, inv2, inv3; + __m128 tmp0, tmp1; + __m128 xxxx, yyyy, zzzz; + tmp0 = vec_mergeh( tfrm.getCol0().get128(), tfrm.getCol2().get128() ); + tmp1 = vec_mergel( tfrm.getCol0().get128(), tfrm.getCol2().get128() ); + inv3 = negatef4( tfrm.getCol3().get128() ); + inv0 = vec_mergeh( tmp0, tfrm.getCol1().get128() ); + xxxx = vec_splat( inv3, 0 ); + //inv1 = vec_perm( tmp0, tfrm.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + inv1 = _mm_shuffle_ps( tmp0, tmp0, _MM_SHUFFLE(0,3,2,2)); + inv1 = vec_sel(inv1, tfrm.getCol1().get128(), select_y); + //inv2 = vec_perm( tmp1, tfrm.getCol1().get128(), _VECTORMATH_PERM_XCYX ); + inv2 = _mm_shuffle_ps( tmp1, tmp1, _MM_SHUFFLE(0,1,1,0)); + inv2 = vec_sel(inv2, vec_splat(tfrm.getCol1().get128(), 2), select_y); + yyyy = vec_splat( inv3, 1 ); + zzzz = vec_splat( inv3, 2 ); + inv3 = vec_mul( inv0, xxxx ); + inv3 = vec_madd( inv1, yyyy, inv3 ); + inv3 = vec_madd( inv2, zzzz, inv3 ); + return Transform3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ), + Vector3( inv3 ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 absPerElem( const Transform3 & tfrm ) +{ + return Transform3( + absPerElem( tfrm.getCol0() ), + absPerElem( tfrm.getCol1() ), + absPerElem( tfrm.getCol2() ), + absPerElem( tfrm.getCol3() ) + ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::operator *( const Vector3 &vec ) const +{ + __m128 res; + __m128 xxxx, yyyy, zzzz; + xxxx = vec_splat( vec.get128(), 0 ); + yyyy = vec_splat( vec.get128(), 1 ); + zzzz = vec_splat( vec.get128(), 2 ); + res = vec_mul( mCol0.get128(), xxxx ); + res = vec_madd( mCol1.get128(), yyyy, res ); + res = vec_madd( mCol2.get128(), zzzz, res ); + return Vector3( res ); +} + +VECTORMATH_FORCE_INLINE const Point3 Transform3::operator *( const Point3 &pnt ) const +{ + __m128 tmp0, tmp1, res; + __m128 xxxx, yyyy, zzzz; + xxxx = vec_splat( pnt.get128(), 0 ); + yyyy = vec_splat( pnt.get128(), 1 ); + zzzz = vec_splat( pnt.get128(), 2 ); + tmp0 = vec_mul( mCol0.get128(), xxxx ); + tmp1 = vec_mul( mCol1.get128(), yyyy ); + tmp0 = vec_madd( mCol2.get128(), zzzz, tmp0 ); + tmp1 = vec_add( mCol3.get128(), tmp1 ); + res = vec_add( tmp0, tmp1 ); + return Point3( res ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::operator *( const Transform3 & tfrm ) const +{ + return Transform3( + ( *this * tfrm.mCol0 ), + ( *this * tfrm.mCol1 ), + ( *this * tfrm.mCol2 ), + Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) + ); +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +VECTORMATH_FORCE_INLINE const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) +{ + return Transform3( + mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), + mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), + mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), + mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::identity( ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) +{ + mCol0 = tfrm.getCol0(); + mCol1 = tfrm.getCol1(); + mCol2 = tfrm.getCol2(); + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 Transform3::getUpper3x3( ) const +{ + return Matrix3( mCol0, mCol1, mCol2 ); +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setTranslation( const Vector3 &translateVec ) +{ + mCol3 = translateVec; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getTranslation( ) const +{ + return mCol3; +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationX( const floatInVec &radians ) +{ + __m128 s, c, res1, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + return Transform3( + Vector3::xAxis( ), + Vector3( res1 ), + Vector3( res2 ), + Vector3( _mm_setzero_ps() ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationY( const floatInVec &radians ) +{ + __m128 s, c, res0, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + return Transform3( + Vector3( res0 ), + Vector3::yAxis( ), + Vector3( res2 ), + Vector3( 0.0f ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationZ( const floatInVec &radians ) +{ + __m128 s, c, res0, res1; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + __m128 zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + return Transform3( + Vector3( res0 ), + Vector3( res1 ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationZYX( const Vector3 &radiansXYZ ) +{ + __m128 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + angles = Vector4( radiansXYZ, 0.0f ).get128(); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; + Z1 = vec_and( Z1, _mm_load_ps( (float *)select_xyz ) ); + Y0 = _mm_shuffle_ps( c, negS, _MM_SHUFFLE(0,1,1,1) ); + Y1 = _mm_shuffle_ps( s, c, _MM_SHUFFLE(0,1,1,1) ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_mul( Z0, Y1 ); + return Transform3( + Vector3( vec_mul( Z0, Y0 ) ), + Vector3( vec_madd( Z1, X1, vec_mul( tmp, X0 ) ) ), + Vector3( vec_nmsub( Z1, X0, vec_mul( tmp, X1 ) ) ), + Vector3( 0.0f ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotation( float radians, const Vector3 &unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotation( const floatInVec &radians, const Vector3 &unitVec ) +{ + return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( 0.0f ) ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotation( const Quat &unitQuat ) +{ + return Transform3( Matrix3( unitQuat ), Vector3( 0.0f ) ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::scale( const Vector3 &scaleVec ) +{ + __m128 zero = _mm_setzero_ps(); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + return Transform3( + Vector3( vec_sel( zero, scaleVec.get128(), select_x ) ), + Vector3( vec_sel( zero, scaleVec.get128(), select_y ) ), + Vector3( vec_sel( zero, scaleVec.get128(), select_z ) ), + Vector3( 0.0f ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 appendScale( const Transform3 & tfrm, const Vector3 &scaleVec ) +{ + return Transform3( + ( tfrm.getCol0() * scaleVec.getX( ) ), + ( tfrm.getCol1() * scaleVec.getY( ) ), + ( tfrm.getCol2() * scaleVec.getZ( ) ), + tfrm.getCol3() + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 prependScale( const Vector3 &scaleVec, const Transform3 & tfrm ) +{ + return Transform3( + mulPerElem( tfrm.getCol0(), scaleVec ), + mulPerElem( tfrm.getCol1(), scaleVec ), + mulPerElem( tfrm.getCol2(), scaleVec ), + mulPerElem( tfrm.getCol3(), scaleVec ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::translation( const Vector3 &translateVec ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + translateVec + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, const boolInVec &select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Transform3 & tfrm ) +{ + print( tfrm.getRow( 0 ) ); + print( tfrm.getRow( 1 ) ); + print( tfrm.getRow( 2 ) ); +} + +VECTORMATH_FORCE_INLINE void print( const Transform3 & tfrm, const char * name ) +{ + printf("%s:\n", name); + print( tfrm ); +} + +#endif + +VECTORMATH_FORCE_INLINE Quat::Quat( const Matrix3 & tfrm ) +{ + __m128 res; + __m128 col0, col1, col2; + __m128 xx_yy, xx_yy_zz_xx, yy_zz_xx_yy, zz_xx_yy_zz, diagSum, diagDiff; + __m128 zy_xz_yx, yz_zx_xy, sum, diff; + __m128 radicand, invSqrt, scale; + __m128 res0, res1, res2, res3; + __m128 xx, yy, zz; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_w[4] = {0, 0, 0, 0xffffffff}; + + col0 = tfrm.getCol0().get128(); + col1 = tfrm.getCol1().get128(); + col2 = tfrm.getCol2().get128(); + + /* four cases: */ + /* trace > 0 */ + /* else */ + /* xx largest diagonal element */ + /* yy largest diagonal element */ + /* zz largest diagonal element */ + + /* compute quaternion for each case */ + + xx_yy = vec_sel( col0, col1, select_y ); + //xx_yy_zz_xx = vec_perm( xx_yy, col2, _VECTORMATH_PERM_XYCX ); + //yy_zz_xx_yy = vec_perm( xx_yy, col2, _VECTORMATH_PERM_YCXY ); + //zz_xx_yy_zz = vec_perm( xx_yy, col2, _VECTORMATH_PERM_CXYC ); + xx_yy_zz_xx = _mm_shuffle_ps( xx_yy, xx_yy, _MM_SHUFFLE(0,0,1,0) ); + xx_yy_zz_xx = vec_sel( xx_yy_zz_xx, col2, select_z ); // TODO: Ck + yy_zz_xx_yy = _mm_shuffle_ps( xx_yy_zz_xx, xx_yy_zz_xx, _MM_SHUFFLE(1,0,2,1) ); + zz_xx_yy_zz = _mm_shuffle_ps( xx_yy_zz_xx, xx_yy_zz_xx, _MM_SHUFFLE(2,1,0,2) ); + + diagSum = vec_add( vec_add( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); + diagDiff = vec_sub( vec_sub( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); + radicand = vec_add( vec_sel( diagDiff, diagSum, select_w ), _mm_set1_ps(1.0f) ); + // invSqrt = rsqrtf4( radicand ); + invSqrt = newtonrapson_rsqrt4( radicand ); + + + + zy_xz_yx = vec_sel( col0, col1, select_z ); // zy_xz_yx = 00 01 12 03 + //zy_xz_yx = vec_perm( zy_xz_yx, col2, _VECTORMATH_PERM_ZAYX ); + zy_xz_yx = _mm_shuffle_ps( zy_xz_yx, zy_xz_yx, _MM_SHUFFLE(0,1,2,2) ); // zy_xz_yx = 12 12 01 00 + zy_xz_yx = vec_sel( zy_xz_yx, vec_splat(col2, 0), select_y ); // zy_xz_yx = 12 20 01 00 + yz_zx_xy = vec_sel( col0, col1, select_x ); // yz_zx_xy = 10 01 02 03 + //yz_zx_xy = vec_perm( yz_zx_xy, col2, _VECTORMATH_PERM_BZXX ); + yz_zx_xy = _mm_shuffle_ps( yz_zx_xy, yz_zx_xy, _MM_SHUFFLE(0,0,2,0) ); // yz_zx_xy = 10 02 10 10 + yz_zx_xy = vec_sel( yz_zx_xy, vec_splat(col2, 1), select_x ); // yz_zx_xy = 21 02 10 10 + + sum = vec_add( zy_xz_yx, yz_zx_xy ); + diff = vec_sub( zy_xz_yx, yz_zx_xy ); + + scale = vec_mul( invSqrt, _mm_set1_ps(0.5f) ); + + //res0 = vec_perm( sum, diff, _VECTORMATH_PERM_XZYA ); + res0 = _mm_shuffle_ps( sum, sum, _MM_SHUFFLE(0,1,2,0) ); + res0 = vec_sel( res0, vec_splat(diff, 0), select_w ); // TODO: Ck + //res1 = vec_perm( sum, diff, _VECTORMATH_PERM_ZXXB ); + res1 = _mm_shuffle_ps( sum, sum, _MM_SHUFFLE(0,0,0,2) ); + res1 = vec_sel( res1, vec_splat(diff, 1), select_w ); // TODO: Ck + //res2 = vec_perm( sum, diff, _VECTORMATH_PERM_YXXC ); + res2 = _mm_shuffle_ps( sum, sum, _MM_SHUFFLE(0,0,0,1) ); + res2 = vec_sel( res2, vec_splat(diff, 2), select_w ); // TODO: Ck + res3 = diff; + res0 = vec_sel( res0, radicand, select_x ); + res1 = vec_sel( res1, radicand, select_y ); + res2 = vec_sel( res2, radicand, select_z ); + res3 = vec_sel( res3, radicand, select_w ); + res0 = vec_mul( res0, vec_splat( scale, 0 ) ); + res1 = vec_mul( res1, vec_splat( scale, 1 ) ); + res2 = vec_mul( res2, vec_splat( scale, 2 ) ); + res3 = vec_mul( res3, vec_splat( scale, 3 ) ); + + /* determine case and select answer */ + + xx = vec_splat( col0, 0 ); + yy = vec_splat( col1, 1 ); + zz = vec_splat( col2, 2 ); + res = vec_sel( res0, res1, vec_cmpgt( yy, xx ) ); + res = vec_sel( res, res2, vec_and( vec_cmpgt( zz, xx ), vec_cmpgt( zz, yy ) ) ); + res = vec_sel( res, res3, vec_cmpgt( vec_splat( diagSum, 0 ), _mm_setzero_ps() ) ); + mVec128 = res; +} + +VECTORMATH_FORCE_INLINE const Matrix3 outer( const Vector3 &tfrm0, const Vector3 &tfrm1 ) +{ + return Matrix3( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 outer( const Vector4 &tfrm0, const Vector4 &tfrm1 ) +{ + return Matrix4( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ), + ( tfrm0 * tfrm1.getW( ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Vector3 rowMul( const Vector3 &vec, const Matrix3 & mat ) +{ + __m128 tmp0, tmp1, mcol0, mcol1, mcol2, res; + __m128 xxxx, yyyy, zzzz; + tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp1 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); + xxxx = vec_splat( vec.get128(), 0 ); + mcol0 = vec_mergeh( tmp0, mat.getCol1().get128() ); + //mcol1 = vec_perm( tmp0, mat.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + mcol1 = _mm_shuffle_ps( tmp0, tmp0, _MM_SHUFFLE(0,3,2,2)); + mcol1 = vec_sel(mcol1, mat.getCol1().get128(), select_y); + //mcol2 = vec_perm( tmp1, mat.getCol1().get128(), _VECTORMATH_PERM_XCYX ); + mcol2 = _mm_shuffle_ps( tmp1, tmp1, _MM_SHUFFLE(0,1,1,0)); + mcol2 = vec_sel(mcol2, vec_splat(mat.getCol1().get128(), 2), select_y); + yyyy = vec_splat( vec.get128(), 1 ); + res = vec_mul( mcol0, xxxx ); + zzzz = vec_splat( vec.get128(), 2 ); + res = vec_madd( mcol1, yyyy, res ); + res = vec_madd( mcol2, zzzz, res ); + return Vector3( res ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 crossMatrix( const Vector3 &vec ) +{ + __m128 neg, res0, res1, res2; + neg = negatef4( vec.get128() ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + //res0 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_XZBX ); + res0 = _mm_shuffle_ps( vec.get128(), vec.get128(), _MM_SHUFFLE(0,2,2,0) ); + res0 = vec_sel(res0, vec_splat(neg, 1), select_z); + //res1 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_CXXX ); + res1 = vec_sel(vec_splat(vec.get128(), 0), vec_splat(neg, 2), select_x); + //res2 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_YAXX ); + res2 = _mm_shuffle_ps( vec.get128(), vec.get128(), _MM_SHUFFLE(0,0,1,1) ); + res2 = vec_sel(res2, vec_splat(neg, 0), select_y); + VM_ATTRIBUTE_ALIGN16 unsigned int filter_x[4] = {0, 0xffffffff, 0xffffffff, 0xffffffff}; + VM_ATTRIBUTE_ALIGN16 unsigned int filter_y[4] = {0xffffffff, 0, 0xffffffff, 0xffffffff}; + VM_ATTRIBUTE_ALIGN16 unsigned int filter_z[4] = {0xffffffff, 0xffffffff, 0, 0xffffffff}; + res0 = vec_and( res0, _mm_load_ps((float *)filter_x ) ); + res1 = vec_and( res1, _mm_load_ps((float *)filter_y ) ); + res2 = vec_and( res2, _mm_load_ps((float *)filter_z ) ); // TODO: Use selects? + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 crossMatrixMul( const Vector3 &vec, const Matrix3 & mat ) +{ + return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); +} + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/src/vectormath/sse/quat_aos.h b/src/vectormath/sse/quat_aos.h new file mode 100644 index 0000000..d7091ec --- /dev/null +++ b/src/vectormath/sse/quat_aos.h @@ -0,0 +1,579 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _VECTORMATH_QUAT_AOS_CPP_H +#define _VECTORMATH_QUAT_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +VECTORMATH_FORCE_INLINE void Quat::set128(vec_float4 vec) +{ + mVec128 = vec; +} + +VECTORMATH_FORCE_INLINE Quat::Quat( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z, const floatInVec &_w ) +{ + mVec128 = _mm_unpacklo_ps( + _mm_unpacklo_ps( _x.get128(), _z.get128() ), + _mm_unpacklo_ps( _y.get128(), _w.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( const Vector3 &xyz, float _w ) +{ + mVec128 = xyz.get128(); + _vmathVfSetElement(mVec128, _w, 3); +} + + + +VECTORMATH_FORCE_INLINE Quat::Quat(const Quat& quat) +{ + mVec128 = quat.get128(); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( float _x, float _y, float _z, float _w ) +{ + mVec128 = _mm_setr_ps(_x, _y, _z, _w); +} + + + + + +VECTORMATH_FORCE_INLINE Quat::Quat( const Vector3 &xyz, const floatInVec &_w ) +{ + mVec128 = xyz.get128(); + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( const Vector4 &vec ) +{ + mVec128 = vec.get128(); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( const floatInVec &scalar ) +{ + mVec128 = scalar.get128(); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( __m128 vf4 ) +{ + mVec128 = vf4; +} + +VECTORMATH_FORCE_INLINE const Quat Quat::identity( ) +{ + return Quat( _VECTORMATH_UNIT_0001 ); +} + +VECTORMATH_FORCE_INLINE const Quat lerp( float t, const Quat &quat0, const Quat &quat1 ) +{ + return lerp( floatInVec(t), quat0, quat1 ); +} + +VECTORMATH_FORCE_INLINE const Quat lerp( const floatInVec &t, const Quat &quat0, const Quat &quat1 ) +{ + return ( quat0 + ( ( quat1 - quat0 ) * t ) ); +} + +VECTORMATH_FORCE_INLINE const Quat slerp( float t, const Quat &unitQuat0, const Quat &unitQuat1 ) +{ + return slerp( floatInVec(t), unitQuat0, unitQuat1 ); +} + +VECTORMATH_FORCE_INLINE const Quat slerp( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1 ) +{ + Quat start; + vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + __m128 selectMask; + cosAngle = _vmathVfDot4( unitQuat0.get128(), unitQuat1.get128() ); + selectMask = (__m128)vec_cmpgt( _mm_setzero_ps(), cosAngle ); + cosAngle = vec_sel( cosAngle, negatef4( cosAngle ), selectMask ); + start = Quat( vec_sel( unitQuat0.get128(), negatef4( unitQuat0.get128() ), selectMask ) ); + selectMask = (__m128)vec_cmpgt( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = t.get128(); + oneMinusT = vec_sub( _mm_set1_ps(1.0f), tttt ); + angles = vec_mergeh( _mm_set1_ps(1.0f), tttt ); + angles = vec_mergeh( angles, oneMinusT ); + angles = vec_madd( angles, angle, _mm_setzero_ps() ); + sines = sinf4( angles ); + scales = _mm_div_ps( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + return Quat( vec_madd( start.get128(), scale0, vec_mul( unitQuat1.get128(), scale1 ) ) ); +} + +VECTORMATH_FORCE_INLINE const Quat squad( float t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ) +{ + return squad( floatInVec(t), unitQuat0, unitQuat1, unitQuat2, unitQuat3 ); +} + +VECTORMATH_FORCE_INLINE const Quat squad( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ) +{ + return slerp( ( ( floatInVec(2.0f) * t ) * ( floatInVec(1.0f) - t ) ), slerp( t, unitQuat0, unitQuat3 ), slerp( t, unitQuat1, unitQuat2 ) ); +} + +VECTORMATH_FORCE_INLINE __m128 Quat::get128( ) const +{ + return mVec128; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator =( const Quat &quat ) +{ + mVec128 = quat.mVec128; + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setXYZ( const Vector3 &vec ) +{ + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + mVec128 = vec_sel( vec.get128(), mVec128, sw ); + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Quat::getXYZ( ) const +{ + return Vector3( mVec128 ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setX( const floatInVec &_x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setY( const floatInVec &_y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setZ( const floatInVec &_z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setW( float _w ) +{ + _vmathVfSetElement(mVec128, _w, 3); + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setW( const floatInVec &_w ) +{ + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::getW( ) const +{ + return floatInVec( mVec128, 3 ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setElem( int idx, const floatInVec &value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE VecIdx Quat::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator +( const Quat &quat ) const +{ + return Quat( _mm_add_ps( mVec128, quat.mVec128 ) ); +} + + +VECTORMATH_FORCE_INLINE const Quat Quat::operator -( const Quat &quat ) const +{ + return Quat( _mm_sub_ps( mVec128, quat.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator *( const floatInVec &scalar ) const +{ + return Quat( _mm_mul_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator +=( const Quat &quat ) +{ + *this = *this + quat; + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator -=( const Quat &quat ) +{ + *this = *this - quat; + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator /( float scalar ) const +{ + return *this / floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator /( const floatInVec &scalar ) const +{ + return Quat( _mm_div_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator /=( const floatInVec &scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator -( ) const +{ + return Quat(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Quat operator *( float scalar, const Quat &quat ) +{ + return floatInVec(scalar) * quat; +} + +VECTORMATH_FORCE_INLINE const Quat operator *( const floatInVec &scalar, const Quat &quat ) +{ + return quat * scalar; +} + +VECTORMATH_FORCE_INLINE const floatInVec dot( const Quat &quat0, const Quat &quat1 ) +{ + return floatInVec( _vmathVfDot4( quat0.get128(), quat1.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec norm( const Quat &quat ) +{ + return floatInVec( _vmathVfDot4( quat.get128(), quat.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec length( const Quat &quat ) +{ + return floatInVec( _mm_sqrt_ps(_vmathVfDot4( quat.get128(), quat.get128() )), 0 ); +} + +VECTORMATH_FORCE_INLINE const Quat normalize( const Quat &quat ) +{ + vec_float4 dot =_vmathVfDot4( quat.get128(), quat.get128()); + return Quat( _mm_mul_ps( quat.get128(), newtonrapson_rsqrt4( dot ) ) ); +} + + +VECTORMATH_FORCE_INLINE const Quat Quat::rotation( const Vector3 &unitVec0, const Vector3 &unitVec1 ) +{ + Vector3 crossVec; + __m128 cosAngle, cosAngleX2Plus2, recipCosHalfAngleX2, cosHalfAngleX2, res; + cosAngle = _vmathVfDot3( unitVec0.get128(), unitVec1.get128() ); + cosAngleX2Plus2 = vec_madd( cosAngle, _mm_set1_ps(2.0f), _mm_set1_ps(2.0f) ); + recipCosHalfAngleX2 = _mm_rsqrt_ps( cosAngleX2Plus2 ); + cosHalfAngleX2 = vec_mul( recipCosHalfAngleX2, cosAngleX2Plus2 ); + crossVec = cross( unitVec0, unitVec1 ); + res = vec_mul( crossVec.get128(), recipCosHalfAngleX2 ); + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( res, vec_mul( cosHalfAngleX2, _mm_set1_ps(0.5f) ), sw ); + return Quat( res ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotation( float radians, const Vector3 &unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotation( const floatInVec &radians, const Vector3 &unitVec ) +{ + __m128 s, c, angle, res; + angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); + sincosf4( angle, &s, &c ); + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( vec_mul( unitVec.get128(), s ), c, sw ); + return Quat( res ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationX( const floatInVec &radians ) +{ + __m128 s, c, angle, res; + angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); + sincosf4( angle, &s, &c ); + VM_ATTRIBUTE_ALIGN16 unsigned int xsw[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int wsw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( _mm_setzero_ps(), s, xsw ); + res = vec_sel( res, c, wsw ); + return Quat( res ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationY( const floatInVec &radians ) +{ + __m128 s, c, angle, res; + angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); + sincosf4( angle, &s, &c ); + VM_ATTRIBUTE_ALIGN16 unsigned int ysw[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int wsw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( _mm_setzero_ps(), s, ysw ); + res = vec_sel( res, c, wsw ); + return Quat( res ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationZ( const floatInVec &radians ) +{ + __m128 s, c, angle, res; + angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); + sincosf4( angle, &s, &c ); + VM_ATTRIBUTE_ALIGN16 unsigned int zsw[4] = {0, 0, 0xffffffff, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int wsw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( _mm_setzero_ps(), s, zsw ); + res = vec_sel( res, c, wsw ); + return Quat( res ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator *( const Quat &quat ) const +{ + __m128 ldata, rdata, qv, tmp0, tmp1, tmp2, tmp3; + __m128 product, l_wxyz, r_wxyz, xy, qw; + ldata = mVec128; + rdata = quat.mVec128; + tmp0 = _mm_shuffle_ps( ldata, ldata, _MM_SHUFFLE(3,0,2,1) ); + tmp1 = _mm_shuffle_ps( rdata, rdata, _MM_SHUFFLE(3,1,0,2) ); + tmp2 = _mm_shuffle_ps( ldata, ldata, _MM_SHUFFLE(3,1,0,2) ); + tmp3 = _mm_shuffle_ps( rdata, rdata, _MM_SHUFFLE(3,0,2,1) ); + qv = vec_mul( vec_splat( ldata, 3 ), rdata ); + qv = vec_madd( vec_splat( rdata, 3 ), ldata, qv ); + qv = vec_madd( tmp0, tmp1, qv ); + qv = vec_nmsub( tmp2, tmp3, qv ); + product = vec_mul( ldata, rdata ); + l_wxyz = vec_sld( ldata, ldata, 12 ); + r_wxyz = vec_sld( rdata, rdata, 12 ); + qw = vec_nmsub( l_wxyz, r_wxyz, product ); + xy = vec_madd( l_wxyz, r_wxyz, product ); + qw = vec_sub( qw, vec_sld( xy, xy, 8 ) ); + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + return Quat( vec_sel( qv, qw, sw ) ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator *=( const Quat &quat ) +{ + *this = *this * quat; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 rotate( const Quat &quat, const Vector3 &vec ) +{ __m128 qdata, vdata, product, tmp0, tmp1, tmp2, tmp3, wwww, qv, qw, res; + qdata = quat.get128(); + vdata = vec.get128(); + tmp0 = _mm_shuffle_ps( qdata, qdata, _MM_SHUFFLE(3,0,2,1) ); + tmp1 = _mm_shuffle_ps( vdata, vdata, _MM_SHUFFLE(3,1,0,2) ); + tmp2 = _mm_shuffle_ps( qdata, qdata, _MM_SHUFFLE(3,1,0,2) ); + tmp3 = _mm_shuffle_ps( vdata, vdata, _MM_SHUFFLE(3,0,2,1) ); + wwww = vec_splat( qdata, 3 ); + qv = vec_mul( wwww, vdata ); + qv = vec_madd( tmp0, tmp1, qv ); + qv = vec_nmsub( tmp2, tmp3, qv ); + product = vec_mul( qdata, vdata ); + qw = vec_madd( vec_sld( qdata, qdata, 4 ), vec_sld( vdata, vdata, 4 ), product ); + qw = vec_add( vec_sld( product, product, 8 ), qw ); + tmp1 = _mm_shuffle_ps( qv, qv, _MM_SHUFFLE(3,1,0,2) ); + tmp3 = _mm_shuffle_ps( qv, qv, _MM_SHUFFLE(3,0,2,1) ); + res = vec_mul( vec_splat( qw, 0 ), qdata ); + res = vec_madd( wwww, qv, res ); + res = vec_madd( tmp0, tmp1, res ); + res = vec_nmsub( tmp2, tmp3, res ); + return Vector3( res ); +} + +VECTORMATH_FORCE_INLINE const Quat conj( const Quat &quat ) +{ + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0x80000000,0x80000000,0x80000000,0}; + return Quat( vec_xor( quat.get128(), _mm_load_ps((float *)sw) ) ); +} + +VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, bool select1 ) +{ + return select( quat0, quat1, boolInVec(select1) ); +} + +//VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, const boolInVec &select1 ) +//{ +// return Quat( vec_sel( quat0.get128(), quat1.get128(), select1.get128() ) ); +//} + +VECTORMATH_FORCE_INLINE void loadXYZW(Quat& quat, const float* fptr) +{ +#ifdef USE_SSE3_LDDQU + quat = Quat( SSEFloat(_mm_lddqu_si128((const __m128i*)((float*)(fptr)))).m128 ); +#else + SSEFloat fl; + fl.f[0] = fptr[0]; + fl.f[1] = fptr[1]; + fl.f[2] = fptr[2]; + fl.f[3] = fptr[3]; + quat = Quat( fl.m128); +#endif + + +} + +VECTORMATH_FORCE_INLINE void storeXYZW(const Quat& quat, float* fptr) +{ + fptr[0] = quat.getX(); + fptr[1] = quat.getY(); + fptr[2] = quat.getZ(); + fptr[3] = quat.getW(); +// _mm_storeu_ps((float*)quat.get128(),fptr); +} + + + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Quat &quat ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = quat.get128(); + printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +VECTORMATH_FORCE_INLINE void print( const Quat &quat, const char * name ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = quat.get128(); + printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/src/vectormath/sse/vec_aos.h b/src/vectormath/sse/vec_aos.h new file mode 100644 index 0000000..05ebac5 --- /dev/null +++ b/src/vectormath/sse/vec_aos.h @@ -0,0 +1,1455 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_AOS_CPP_H +#define _VECTORMATH_VEC_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Constants +// for permutes words are labeled [x,y,z,w] [a,b,c,d] + +#define _VECTORMATH_PERM_X 0x00010203 +#define _VECTORMATH_PERM_Y 0x04050607 +#define _VECTORMATH_PERM_Z 0x08090a0b +#define _VECTORMATH_PERM_W 0x0c0d0e0f +#define _VECTORMATH_PERM_A 0x10111213 +#define _VECTORMATH_PERM_B 0x14151617 +#define _VECTORMATH_PERM_C 0x18191a1b +#define _VECTORMATH_PERM_D 0x1c1d1e1f +#define _VECTORMATH_PERM_XYZA (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A } +#define _VECTORMATH_PERM_ZXYW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_YZXW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_YZAB (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B } +#define _VECTORMATH_PERM_ZABC (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B, _VECTORMATH_PERM_C } +#define _VECTORMATH_PERM_XYAW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_XAZW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W } +#define _VECTORMATH_MASK_0xF000 (vec_uint4){ 0xffffffff, 0, 0, 0 } +#define _VECTORMATH_MASK_0x0F00 (vec_uint4){ 0, 0xffffffff, 0, 0 } +#define _VECTORMATH_MASK_0x00F0 (vec_uint4){ 0, 0, 0xffffffff, 0 } +#define _VECTORMATH_MASK_0x000F (vec_uint4){ 0, 0, 0, 0xffffffff } +#define _VECTORMATH_UNIT_1000 _mm_setr_ps(1.0f,0.0f,0.0f,0.0f) // (__m128){ 1.0f, 0.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0100 _mm_setr_ps(0.0f,1.0f,0.0f,0.0f) // (__m128){ 0.0f, 1.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0010 _mm_setr_ps(0.0f,0.0f,1.0f,0.0f) // (__m128){ 0.0f, 0.0f, 1.0f, 0.0f } +#define _VECTORMATH_UNIT_0001 _mm_setr_ps(0.0f,0.0f,0.0f,1.0f) // (__m128){ 0.0f, 0.0f, 0.0f, 1.0f } +#define _VECTORMATH_SLERP_TOL 0.999f +//_VECTORMATH_SLERP_TOLF + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#define _vmath_shufps(a, b, immx, immy, immz, immw) _mm_shuffle_ps(a, b, _MM_SHUFFLE(immw, immz, immy, immx)) +static VECTORMATH_FORCE_INLINE __m128 _vmathVfDot3( __m128 vec0, __m128 vec1 ) +{ + __m128 result = _mm_mul_ps( vec0, vec1); + return _mm_add_ps( vec_splat( result, 0 ), _mm_add_ps( vec_splat( result, 1 ), vec_splat( result, 2 ) ) ); +} + +static VECTORMATH_FORCE_INLINE __m128 _vmathVfDot4( __m128 vec0, __m128 vec1 ) +{ + __m128 result = _mm_mul_ps(vec0, vec1); + return _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(0,0,0,0)), + _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(1,1,1,1)), + _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(2,2,2,2)), _mm_shuffle_ps(result, result, _MM_SHUFFLE(3,3,3,3))))); +} + +static VECTORMATH_FORCE_INLINE __m128 _vmathVfCross( __m128 vec0, __m128 vec1 ) +{ + __m128 tmp0, tmp1, tmp2, tmp3, result; + tmp0 = _mm_shuffle_ps( vec0, vec0, _MM_SHUFFLE(3,0,2,1) ); + tmp1 = _mm_shuffle_ps( vec1, vec1, _MM_SHUFFLE(3,1,0,2) ); + tmp2 = _mm_shuffle_ps( vec0, vec0, _MM_SHUFFLE(3,1,0,2) ); + tmp3 = _mm_shuffle_ps( vec1, vec1, _MM_SHUFFLE(3,0,2,1) ); + result = vec_mul( tmp0, tmp1 ); + result = vec_nmsub( tmp2, tmp3, result ); + return result; +} +/* +static VECTORMATH_FORCE_INLINE vec_uint4 _vmathVfToHalfFloatsUnpacked(__m128 v) +{ +#if 0 + vec_int4 bexp; + vec_uint4 mant, sign, hfloat; + vec_uint4 notZero, isInf; + const vec_uint4 hfloatInf = (vec_uint4)(0x00007c00u); + const vec_uint4 mergeMant = (vec_uint4)(0x000003ffu); + const vec_uint4 mergeSign = (vec_uint4)(0x00008000u); + + sign = vec_sr((vec_uint4)v, (vec_uint4)16); + mant = vec_sr((vec_uint4)v, (vec_uint4)13); + bexp = vec_and(vec_sr((vec_int4)v, (vec_uint4)23), (vec_int4)0xff); + + notZero = (vec_uint4)vec_cmpgt(bexp, (vec_int4)112); + isInf = (vec_uint4)vec_cmpgt(bexp, (vec_int4)142); + + bexp = _mm_add_ps(bexp, (vec_int4)-112); + bexp = vec_sl(bexp, (vec_uint4)10); + + hfloat = vec_sel((vec_uint4)bexp, mant, mergeMant); + hfloat = vec_sel((vec_uint4)(0), hfloat, notZero); + hfloat = vec_sel(hfloat, hfloatInf, isInf); + hfloat = vec_sel(hfloat, sign, mergeSign); + + return hfloat; +#else + assert(0); + return _mm_setzero_ps(); +#endif +} + +static VECTORMATH_FORCE_INLINE vec_ushort8 _vmath2VfToHalfFloats(__m128 u, __m128 v) +{ +#if 0 + vec_uint4 hfloat_u, hfloat_v; + const vec_uchar16 pack = (vec_uchar16){2,3,6,7,10,11,14,15,18,19,22,23,26,27,30,31}; + hfloat_u = _vmathVfToHalfFloatsUnpacked(u); + hfloat_v = _vmathVfToHalfFloatsUnpacked(v); + return (vec_ushort8)vec_perm(hfloat_u, hfloat_v, pack); +#else + assert(0); + return _mm_setzero_si128(); +#endif +} +*/ + +static VECTORMATH_FORCE_INLINE __m128 _vmathVfInsert(__m128 dst, __m128 src, int slot) +{ + SSEFloat s; + s.m128 = src; + SSEFloat d; + d.m128 = dst; + d.f[slot] = s.f[slot]; + return d.m128; +} + +#define _vmathVfSetElement(vec, scalar, slot) ((float *)&(vec))[slot] = scalar + +static VECTORMATH_FORCE_INLINE __m128 _vmathVfSplatScalar(float scalar) +{ + return _mm_set1_ps(scalar); +} + +#endif + +namespace Vectormath { +namespace Aos { + + +#ifdef _VECTORMATH_NO_SCALAR_CAST +VECTORMATH_FORCE_INLINE VecIdx::operator floatInVec() const +{ + return floatInVec(ref, i); +} + +VECTORMATH_FORCE_INLINE float VecIdx::getAsFloat() const +#else +VECTORMATH_FORCE_INLINE VecIdx::operator float() const +#endif +{ + return ((float *)&ref)[i]; +} + +VECTORMATH_FORCE_INLINE float VecIdx::operator =( float scalar ) +{ + _vmathVfSetElement(ref, scalar, i); + return scalar; +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator =( const floatInVec &scalar ) +{ + ref = _vmathVfInsert(ref, scalar.get128(), i); + return scalar; +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator =( const VecIdx& scalar ) +{ + return *this = floatInVec(scalar.ref, scalar.i); +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator *=( float scalar ) +{ + return *this *= floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator *=( const floatInVec &scalar ) +{ + return *this = floatInVec(ref, i) * scalar; +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator /=( float scalar ) +{ + return *this /= floatInVec(scalar); +} + +inline floatInVec VecIdx::operator /=( const floatInVec &scalar ) +{ + return *this = floatInVec(ref, i) / scalar; +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator +=( float scalar ) +{ + return *this += floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator +=( const floatInVec &scalar ) +{ + return *this = floatInVec(ref, i) + scalar; +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator -=( float scalar ) +{ + return *this -= floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator -=( const floatInVec &scalar ) +{ + return *this = floatInVec(ref, i) - scalar; +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3(const Vector3& vec) +{ + set128(vec.get128()); +} + +VECTORMATH_FORCE_INLINE void Vector3::set128(vec_float4 vec) +{ + mVec128 = vec; +} + + +VECTORMATH_FORCE_INLINE Vector3::Vector3( float _x, float _y, float _z ) +{ + mVec128 = _mm_setr_ps(_x, _y, _z, 0.0f); +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z ) +{ + __m128 xz = _mm_unpacklo_ps( _x.get128(), _z.get128() ); + mVec128 = _mm_unpacklo_ps( xz, _y.get128() ); +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3( const Point3 &pnt ) +{ + mVec128 = pnt.get128(); +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3( const floatInVec &scalar ) +{ + mVec128 = scalar.get128(); +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3( __m128 vf4 ) +{ + mVec128 = vf4; +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::xAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_1000 ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::yAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_0100 ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::zAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_0010 ); +} + +VECTORMATH_FORCE_INLINE const Vector3 lerp( float t, const Vector3 &vec0, const Vector3 &vec1 ) +{ + return lerp( floatInVec(t), vec0, vec1 ); +} + +VECTORMATH_FORCE_INLINE const Vector3 lerp( const floatInVec &t, const Vector3 &vec0, const Vector3 &vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 slerp( float t, const Vector3 &unitVec0, const Vector3 &unitVec1 ) +{ + return slerp( floatInVec(t), unitVec0, unitVec1 ); +} + +VECTORMATH_FORCE_INLINE const Vector3 slerp( const floatInVec &t, const Vector3 &unitVec0, const Vector3 &unitVec1 ) +{ + __m128 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + cosAngle = _vmathVfDot3( unitVec0.get128(), unitVec1.get128() ); + __m128 selectMask = _mm_cmpgt_ps( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = t.get128(); + oneMinusT = _mm_sub_ps( _mm_set1_ps(1.0f), tttt ); + angles = _mm_unpacklo_ps( _mm_set1_ps(1.0f), tttt ); // angles = 1, t, 1, t + angles = _mm_unpacklo_ps( angles, oneMinusT ); // angles = 1, 1-t, t, 1-t + angles = _mm_mul_ps( angles, angle ); + sines = sinf4( angles ); + scales = _mm_div_ps( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + return Vector3( vec_madd( unitVec0.get128(), scale0, _mm_mul_ps( unitVec1.get128(), scale1 ) ) ); +} + +VECTORMATH_FORCE_INLINE __m128 Vector3::get128( ) const +{ + return mVec128; +} + +VECTORMATH_FORCE_INLINE void loadXYZ(Point3& vec, const float* fptr) +{ +#ifdef USE_SSE3_LDDQU + vec = Point3( SSEFloat(_mm_lddqu_si128((const __m128i*)((float*)(fptr)))).m128 ); +#else + SSEFloat fl; + fl.f[0] = fptr[0]; + fl.f[1] = fptr[1]; + fl.f[2] = fptr[2]; + fl.f[3] = fptr[3]; + vec = Point3( fl.m128); +#endif //USE_SSE3_LDDQU + +} + + + +VECTORMATH_FORCE_INLINE void loadXYZ(Vector3& vec, const float* fptr) +{ +#ifdef USE_SSE3_LDDQU + vec = Vector3( SSEFloat(_mm_lddqu_si128((const __m128i*)((float*)(fptr)))).m128 ); +#else + SSEFloat fl; + fl.f[0] = fptr[0]; + fl.f[1] = fptr[1]; + fl.f[2] = fptr[2]; + fl.f[3] = fptr[3]; + vec = Vector3( fl.m128); +#endif //USE_SSE3_LDDQU + +} + +VECTORMATH_FORCE_INLINE void storeXYZ( const Vector3 &vec, __m128 * quad ) +{ + __m128 dstVec = *quad; + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; // TODO: Centralize + dstVec = vec_sel(vec.get128(), dstVec, sw); + *quad = dstVec; +} + +VECTORMATH_FORCE_INLINE void storeXYZ(const Point3& vec, float* fptr) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); +} + +VECTORMATH_FORCE_INLINE void storeXYZ(const Vector3& vec, float* fptr) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); +} + + +VECTORMATH_FORCE_INLINE void loadXYZArray( Vector3 & vec0, Vector3 & vec1, Vector3 & vec2, Vector3 & vec3, const __m128 * threeQuads ) +{ + const float *quads = (float *)threeQuads; + vec0 = Vector3( _mm_load_ps(quads) ); + vec1 = Vector3( _mm_loadu_ps(quads + 3) ); + vec2 = Vector3( _mm_loadu_ps(quads + 6) ); + vec3 = Vector3( _mm_loadu_ps(quads + 9) ); +} + +VECTORMATH_FORCE_INLINE void storeXYZArray( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, __m128 * threeQuads ) +{ + __m128 xxxx = _mm_shuffle_ps( vec1.get128(), vec1.get128(), _MM_SHUFFLE(0, 0, 0, 0) ); + __m128 zzzz = _mm_shuffle_ps( vec2.get128(), vec2.get128(), _MM_SHUFFLE(2, 2, 2, 2) ); + VM_ATTRIBUTE_ALIGN16 unsigned int xsw[4] = {0, 0, 0, 0xffffffff}; + VM_ATTRIBUTE_ALIGN16 unsigned int zsw[4] = {0xffffffff, 0, 0, 0}; + threeQuads[0] = vec_sel( vec0.get128(), xxxx, xsw ); + threeQuads[1] = _mm_shuffle_ps( vec1.get128(), vec2.get128(), _MM_SHUFFLE(1, 0, 2, 1) ); + threeQuads[2] = vec_sel( _mm_shuffle_ps( vec3.get128(), vec3.get128(), _MM_SHUFFLE(2, 1, 0, 3) ), zzzz, zsw ); +} +/* +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, const Vector3 &vec4, const Vector3 &vec5, const Vector3 &vec6, const Vector3 &vec7, vec_ushort8 * threeQuads ) +{ + assert(0); +#if 0 + __m128 xyz0[3]; + __m128 xyz1[3]; + storeXYZArray( vec0, vec1, vec2, vec3, xyz0 ); + storeXYZArray( vec4, vec5, vec6, vec7, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +#endif +} +*/ +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator =( const Vector3 &vec ) +{ + mVec128 = vec.mVec128; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setX( const floatInVec &_x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector3::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setY( const floatInVec &_y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector3::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setZ( const floatInVec &_z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector3::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setElem( int idx, const floatInVec &value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector3::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE VecIdx Vector3::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector3::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator +( const Vector3 &vec ) const +{ + return Vector3( _mm_add_ps( mVec128, vec.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator -( const Vector3 &vec ) const +{ + return Vector3( _mm_sub_ps( mVec128, vec.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 Vector3::operator +( const Point3 &pnt ) const +{ + return Point3( _mm_add_ps( mVec128, pnt.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator *( const floatInVec &scalar ) const +{ + return Vector3( _mm_mul_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator +=( const Vector3 &vec ) +{ + *this = *this + vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator -=( const Vector3 &vec ) +{ + *this = *this - vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator /( float scalar ) const +{ + return *this / floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator /( const floatInVec &scalar ) const +{ + return Vector3( _mm_div_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator /=( const floatInVec &scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator -( ) const +{ + //return Vector3(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) ); + + VM_ATTRIBUTE_ALIGN16 static const int array[] = {0x80000000, 0x80000000, 0x80000000, 0x80000000}; + __m128 NEG_MASK = SSEFloat(*(const vec_float4*)array).vf; + return Vector3(_mm_xor_ps(get128(),NEG_MASK)); +} + +VECTORMATH_FORCE_INLINE const Vector3 operator *( float scalar, const Vector3 &vec ) +{ + return floatInVec(scalar) * vec; +} + +VECTORMATH_FORCE_INLINE const Vector3 operator *( const floatInVec &scalar, const Vector3 &vec ) +{ + return vec * scalar; +} + +VECTORMATH_FORCE_INLINE const Vector3 mulPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _mm_mul_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 divPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _mm_div_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 recipPerElem( const Vector3 &vec ) +{ + return Vector3( _mm_rcp_ps( vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 absPerElem( const Vector3 &vec ) +{ + return Vector3( fabsf4( vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 copySignPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + __m128 vmask = toM128(0x7fffffff); + return Vector3( _mm_or_ps( + _mm_and_ps ( vmask, vec0.get128() ), // Value + _mm_andnot_ps( vmask, vec1.get128() ) ) ); // Signs +} + +VECTORMATH_FORCE_INLINE const Vector3 maxPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _mm_max_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Vector3 &vec ) +{ + return floatInVec( _mm_max_ps( _mm_max_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 minPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _mm_min_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Vector3 &vec ) +{ + return floatInVec( _mm_min_ps( _mm_min_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec sum( const Vector3 &vec ) +{ + return floatInVec( _mm_add_ps( _mm_add_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec dot( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return floatInVec( _vmathVfDot3( vec0.get128(), vec1.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec lengthSqr( const Vector3 &vec ) +{ + return floatInVec( _vmathVfDot3( vec.get128(), vec.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec length( const Vector3 &vec ) +{ + return floatInVec( _mm_sqrt_ps(_vmathVfDot3( vec.get128(), vec.get128() )), 0 ); +} + + +VECTORMATH_FORCE_INLINE const Vector3 normalizeApprox( const Vector3 &vec ) +{ + return Vector3( _mm_mul_ps( vec.get128(), _mm_rsqrt_ps( _vmathVfDot3( vec.get128(), vec.get128() ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 normalize( const Vector3 &vec ) +{ + return Vector3( _mm_mul_ps( vec.get128(), newtonrapson_rsqrt4( _vmathVfDot3( vec.get128(), vec.get128() ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 cross( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _vmathVfCross( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 select( const Vector3 &vec0, const Vector3 &vec1, bool select1 ) +{ + return select( vec0, vec1, boolInVec(select1) ); +} + + +VECTORMATH_FORCE_INLINE const Vector4 select(const Vector4& vec0, const Vector4& vec1, const boolInVec& select1) +{ + return Vector4(vec_sel(vec0.get128(), vec1.get128(), select1.get128())); +} + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Vector3 &vec ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +VECTORMATH_FORCE_INLINE void print( const Vector3 &vec, const char * name ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +#endif + +VECTORMATH_FORCE_INLINE Vector4::Vector4( float _x, float _y, float _z, float _w ) +{ + mVec128 = _mm_setr_ps(_x, _y, _z, _w); + } + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z, const floatInVec &_w ) +{ + mVec128 = _mm_unpacklo_ps( + _mm_unpacklo_ps( _x.get128(), _z.get128() ), + _mm_unpacklo_ps( _y.get128(), _w.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const Vector3 &xyz, float _w ) +{ + mVec128 = xyz.get128(); + _vmathVfSetElement(mVec128, _w, 3); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const Vector3 &xyz, const floatInVec &_w ) +{ + mVec128 = xyz.get128(); + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const Vector3 &vec ) +{ + mVec128 = vec.get128(); + mVec128 = _vmathVfInsert(mVec128, _mm_setzero_ps(), 3); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const Point3 &pnt ) +{ + mVec128 = pnt.get128(); + mVec128 = _vmathVfInsert(mVec128, _mm_set1_ps(1.0f), 3); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const Quat &quat ) +{ + mVec128 = quat.get128(); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const floatInVec &scalar ) +{ + mVec128 = scalar.get128(); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( __m128 vf4 ) +{ + mVec128 = vf4; +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::xAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_1000 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::yAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0100 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::zAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0010 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::wAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0001 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 lerp( float t, const Vector4 &vec0, const Vector4 &vec1 ) +{ + return lerp( floatInVec(t), vec0, vec1 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 lerp( const floatInVec &t, const Vector4 &vec0, const Vector4 &vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 slerp( float t, const Vector4 &unitVec0, const Vector4 &unitVec1 ) +{ + return slerp( floatInVec(t), unitVec0, unitVec1 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 slerp( const floatInVec &t, const Vector4 &unitVec0, const Vector4 &unitVec1 ) +{ + __m128 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + cosAngle = _vmathVfDot4( unitVec0.get128(), unitVec1.get128() ); + __m128 selectMask = _mm_cmpgt_ps( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = t.get128(); + oneMinusT = _mm_sub_ps( _mm_set1_ps(1.0f), tttt ); + angles = _mm_unpacklo_ps( _mm_set1_ps(1.0f), tttt ); // angles = 1, t, 1, t + angles = _mm_unpacklo_ps( angles, oneMinusT ); // angles = 1, 1-t, t, 1-t + angles = _mm_mul_ps( angles, angle ); + sines = sinf4( angles ); + scales = _mm_div_ps( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + return Vector4( vec_madd( unitVec0.get128(), scale0, _mm_mul_ps( unitVec1.get128(), scale1 ) ) ); +} + +VECTORMATH_FORCE_INLINE __m128 Vector4::get128( ) const +{ + return mVec128; +} +/* +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Vector4 &vec0, const Vector4 &vec1, const Vector4 &vec2, const Vector4 &vec3, vec_ushort8 * twoQuads ) +{ + twoQuads[0] = _vmath2VfToHalfFloats(vec0.get128(), vec1.get128()); + twoQuads[1] = _vmath2VfToHalfFloats(vec2.get128(), vec3.get128()); +} +*/ +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator =( const Vector4 &vec ) +{ + mVec128 = vec.mVec128; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setXYZ( const Vector3 &vec ) +{ + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + mVec128 = vec_sel( vec.get128(), mVec128, sw ); + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector4::getXYZ( ) const +{ + return Vector3( mVec128 ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setX( const floatInVec &_x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setY( const floatInVec &_y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setZ( const floatInVec &_z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setW( float _w ) +{ + _vmathVfSetElement(mVec128, _w, 3); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setW( const floatInVec &_w ) +{ + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::getW( ) const +{ + return floatInVec( mVec128, 3 ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setElem( int idx, const floatInVec &value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE VecIdx Vector4::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator +( const Vector4 &vec ) const +{ + return Vector4( _mm_add_ps( mVec128, vec.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator -( const Vector4 &vec ) const +{ + return Vector4( _mm_sub_ps( mVec128, vec.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator *( const floatInVec &scalar ) const +{ + return Vector4( _mm_mul_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator +=( const Vector4 &vec ) +{ + *this = *this + vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator -=( const Vector4 &vec ) +{ + *this = *this - vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator /( float scalar ) const +{ + return *this / floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator /( const floatInVec &scalar ) const +{ + return Vector4( _mm_div_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator /=( const floatInVec &scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator -( ) const +{ + return Vector4(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 operator *( float scalar, const Vector4 &vec ) +{ + return floatInVec(scalar) * vec; +} + +VECTORMATH_FORCE_INLINE const Vector4 operator *( const floatInVec &scalar, const Vector4 &vec ) +{ + return vec * scalar; +} + +VECTORMATH_FORCE_INLINE const Vector4 mulPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return Vector4( _mm_mul_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 divPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return Vector4( _mm_div_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 recipPerElem( const Vector4 &vec ) +{ + return Vector4( _mm_rcp_ps( vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 absPerElem( const Vector4 &vec ) +{ + return Vector4( fabsf4( vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 copySignPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + __m128 vmask = toM128(0x7fffffff); + return Vector4( _mm_or_ps( + _mm_and_ps ( vmask, vec0.get128() ), // Value + _mm_andnot_ps( vmask, vec1.get128() ) ) ); // Signs +} + +VECTORMATH_FORCE_INLINE const Vector4 maxPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return Vector4( _mm_max_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Vector4 &vec ) +{ + return floatInVec( _mm_max_ps( + _mm_max_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), + _mm_max_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 minPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return Vector4( _mm_min_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Vector4 &vec ) +{ + return floatInVec( _mm_min_ps( + _mm_min_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), + _mm_min_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec sum( const Vector4 &vec ) +{ + return floatInVec( _mm_add_ps( + _mm_add_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), + _mm_add_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec dot( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return floatInVec( _vmathVfDot4( vec0.get128(), vec1.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec lengthSqr( const Vector4 &vec ) +{ + return floatInVec( _vmathVfDot4( vec.get128(), vec.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec length( const Vector4 &vec ) +{ + return floatInVec( _mm_sqrt_ps(_vmathVfDot4( vec.get128(), vec.get128() )), 0 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 normalizeApprox( const Vector4 &vec ) +{ + return Vector4( _mm_mul_ps( vec.get128(), _mm_rsqrt_ps( _vmathVfDot4( vec.get128(), vec.get128() ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 normalize( const Vector4 &vec ) +{ + return Vector4( _mm_mul_ps( vec.get128(), newtonrapson_rsqrt4( _vmathVfDot4( vec.get128(), vec.get128() ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 select( const Vector4 &vec0, const Vector4 &vec1, bool select1 ) +{ + return select( vec0, vec1, boolInVec(select1) ); +} + + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Vector4 &vec ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +VECTORMATH_FORCE_INLINE void print( const Vector4 &vec, const char * name ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +#endif + +VECTORMATH_FORCE_INLINE Point3::Point3( float _x, float _y, float _z ) +{ + mVec128 = _mm_setr_ps(_x, _y, _z, 0.0f); +} + +VECTORMATH_FORCE_INLINE Point3::Point3( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z ) +{ + mVec128 = _mm_unpacklo_ps( _mm_unpacklo_ps( _x.get128(), _z.get128() ), _y.get128() ); +} + +VECTORMATH_FORCE_INLINE Point3::Point3( const Vector3 &vec ) +{ + mVec128 = vec.get128(); +} + +VECTORMATH_FORCE_INLINE Point3::Point3( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +VECTORMATH_FORCE_INLINE Point3::Point3( const floatInVec &scalar ) +{ + mVec128 = scalar.get128(); +} + +VECTORMATH_FORCE_INLINE Point3::Point3( __m128 vf4 ) +{ + mVec128 = vf4; +} + +VECTORMATH_FORCE_INLINE const Point3 lerp( float t, const Point3 &pnt0, const Point3 &pnt1 ) +{ + return lerp( floatInVec(t), pnt0, pnt1 ); +} + +VECTORMATH_FORCE_INLINE const Point3 lerp( const floatInVec &t, const Point3 &pnt0, const Point3 &pnt1 ) +{ + return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); +} + +VECTORMATH_FORCE_INLINE __m128 Point3::get128( ) const +{ + return mVec128; +} + +VECTORMATH_FORCE_INLINE void storeXYZ( const Point3 &pnt, __m128 * quad ) +{ + __m128 dstVec = *quad; + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; // TODO: Centralize + dstVec = vec_sel(pnt.get128(), dstVec, sw); + *quad = dstVec; +} + +VECTORMATH_FORCE_INLINE void loadXYZArray( Point3 & pnt0, Point3 & pnt1, Point3 & pnt2, Point3 & pnt3, const __m128 * threeQuads ) +{ + const float *quads = (float *)threeQuads; + pnt0 = Point3( _mm_load_ps(quads) ); + pnt1 = Point3( _mm_loadu_ps(quads + 3) ); + pnt2 = Point3( _mm_loadu_ps(quads + 6) ); + pnt3 = Point3( _mm_loadu_ps(quads + 9) ); +} + +VECTORMATH_FORCE_INLINE void storeXYZArray( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, __m128 * threeQuads ) +{ + __m128 xxxx = _mm_shuffle_ps( pnt1.get128(), pnt1.get128(), _MM_SHUFFLE(0, 0, 0, 0) ); + __m128 zzzz = _mm_shuffle_ps( pnt2.get128(), pnt2.get128(), _MM_SHUFFLE(2, 2, 2, 2) ); + VM_ATTRIBUTE_ALIGN16 unsigned int xsw[4] = {0, 0, 0, 0xffffffff}; + VM_ATTRIBUTE_ALIGN16 unsigned int zsw[4] = {0xffffffff, 0, 0, 0}; + threeQuads[0] = vec_sel( pnt0.get128(), xxxx, xsw ); + threeQuads[1] = _mm_shuffle_ps( pnt1.get128(), pnt2.get128(), _MM_SHUFFLE(1, 0, 2, 1) ); + threeQuads[2] = vec_sel( _mm_shuffle_ps( pnt3.get128(), pnt3.get128(), _MM_SHUFFLE(2, 1, 0, 3) ), zzzz, zsw ); +} +/* +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, const Point3 &pnt4, const Point3 &pnt5, const Point3 &pnt6, const Point3 &pnt7, vec_ushort8 * threeQuads ) +{ +#if 0 + __m128 xyz0[3]; + __m128 xyz1[3]; + storeXYZArray( pnt0, pnt1, pnt2, pnt3, xyz0 ); + storeXYZArray( pnt4, pnt5, pnt6, pnt7, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +#else + assert(0); +#endif +} +*/ +VECTORMATH_FORCE_INLINE Point3 & Point3::operator =( const Point3 &pnt ) +{ + mVec128 = pnt.mVec128; + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setX( const floatInVec &_x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Point3::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setY( const floatInVec &_y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Point3::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setZ( const floatInVec &_z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Point3::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setElem( int idx, const floatInVec &value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Point3::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE VecIdx Point3::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const floatInVec Point3::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Point3::operator -( const Point3 &pnt ) const +{ + return Vector3( _mm_sub_ps( mVec128, pnt.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 Point3::operator +( const Vector3 &vec ) const +{ + return Point3( _mm_add_ps( mVec128, vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 Point3::operator -( const Vector3 &vec ) const +{ + return Point3( _mm_sub_ps( mVec128, vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::operator +=( const Vector3 &vec ) +{ + *this = *this + vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::operator -=( const Vector3 &vec ) +{ + *this = *this - vec; + return *this; +} + +VECTORMATH_FORCE_INLINE const Point3 mulPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return Point3( _mm_mul_ps( pnt0.get128(), pnt1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 divPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return Point3( _mm_div_ps( pnt0.get128(), pnt1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 recipPerElem( const Point3 &pnt ) +{ + return Point3( _mm_rcp_ps( pnt.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 absPerElem( const Point3 &pnt ) +{ + return Point3( fabsf4( pnt.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 copySignPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + __m128 vmask = toM128(0x7fffffff); + return Point3( _mm_or_ps( + _mm_and_ps ( vmask, pnt0.get128() ), // Value + _mm_andnot_ps( vmask, pnt1.get128() ) ) ); // Signs +} + +VECTORMATH_FORCE_INLINE const Point3 maxPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return Point3( _mm_max_ps( pnt0.get128(), pnt1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Point3 &pnt ) +{ + return floatInVec( _mm_max_ps( _mm_max_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 minPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return Point3( _mm_min_ps( pnt0.get128(), pnt1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Point3 &pnt ) +{ + return floatInVec( _mm_min_ps( _mm_min_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec sum( const Point3 &pnt ) +{ + return floatInVec( _mm_add_ps( _mm_add_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, float scaleVal ) +{ + return scale( pnt, floatInVec( scaleVal ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, const floatInVec &scaleVal ) +{ + return mulPerElem( pnt, Point3( scaleVal ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, const Vector3 &scaleVec ) +{ + return mulPerElem( pnt, Point3( scaleVec ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec projection( const Point3 &pnt, const Vector3 &unitVec ) +{ + return floatInVec( _vmathVfDot3( pnt.get128(), unitVec.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec distSqrFromOrigin( const Point3 &pnt ) +{ + return lengthSqr( Vector3( pnt ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec distFromOrigin( const Point3 &pnt ) +{ + return length( Vector3( pnt ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec distSqr( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return lengthSqr( ( pnt1 - pnt0 ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec dist( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return length( ( pnt1 - pnt0 ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 select( const Point3 &pnt0, const Point3 &pnt1, bool select1 ) +{ + return select( pnt0, pnt1, boolInVec(select1) ); +} + +VECTORMATH_FORCE_INLINE const Point3 select( const Point3 &pnt0, const Point3 &pnt1, const boolInVec &select1 ) +{ + return Point3( vec_sel( pnt0.get128(), pnt1.get128(), select1.get128() ) ); +} + + + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Point3 &pnt ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = pnt.get128(); + printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +VECTORMATH_FORCE_INLINE void print( const Point3 &pnt, const char * name ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = pnt.get128(); + printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/src/vectormath/sse/vecidx_aos.h b/src/vectormath/sse/vecidx_aos.h new file mode 100644 index 0000000..32e837a --- /dev/null +++ b/src/vectormath/sse/vecidx_aos.h @@ -0,0 +1,80 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VECIDX_AOS_H +#define _VECTORMATH_VECIDX_AOS_H + + +#include "floatInVec.h" + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// VecIdx +// Used in setting elements of Vector3, Vector4, Point3, or Quat with the +// subscripting operator. +// + +VM_ATTRIBUTE_ALIGNED_CLASS16 (class) VecIdx +{ +private: + __m128 &ref; + int i; +public: + inline VecIdx( __m128& vec, int idx ): ref(vec) { i = idx; } + + // implicitly casts to float unless _VECTORMATH_NO_SCALAR_CAST defined + // in which case, implicitly casts to floatInVec, and one must call + // getAsFloat to convert to float. + // +#ifdef _VECTORMATH_NO_SCALAR_CAST + inline operator floatInVec() const; + inline float getAsFloat() const; +#else + inline operator float() const; +#endif + + inline float operator =( float scalar ); + inline floatInVec operator =( const floatInVec &scalar ); + inline floatInVec operator =( const VecIdx& scalar ); + inline floatInVec operator *=( float scalar ); + inline floatInVec operator *=( const floatInVec &scalar ); + inline floatInVec operator /=( float scalar ); + inline floatInVec operator /=( const floatInVec &scalar ); + inline floatInVec operator +=( float scalar ); + inline floatInVec operator +=( const floatInVec &scalar ); + inline floatInVec operator -=( float scalar ); + inline floatInVec operator -=( const floatInVec &scalar ); +}; + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/src/vectormath/sse/vectormath_aos.h b/src/vectormath/sse/vectormath_aos.h new file mode 100644 index 0000000..b802810 --- /dev/null +++ b/src/vectormath/sse/vectormath_aos.h @@ -0,0 +1,2547 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _VECTORMATH_AOS_CPP_SSE_H +#define _VECTORMATH_AOS_CPP_SSE_H + +#include +#include +#include +#include + +#define Vector3Ref Vector3& +#define QuatRef Quat& +#define Matrix3Ref Matrix3& + +#if (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) + #define USE_SSE3_LDDQU + + #define VM_ATTRIBUTE_ALIGNED_CLASS16(a) __declspec(align(16)) a + #define VM_ATTRIBUTE_ALIGN16 __declspec(align(16)) + #define VECTORMATH_FORCE_INLINE __forceinline +#else + #define VM_ATTRIBUTE_ALIGNED_CLASS16(a) a __attribute__ ((aligned (16))) + #define VM_ATTRIBUTE_ALIGN16 __attribute__ ((aligned (16))) + #define VECTORMATH_FORCE_INLINE inline + #ifdef __SSE3__ + #define USE_SSE3_LDDQU + #endif //__SSE3__ +#endif//_WIN32 + + +#ifdef USE_SSE3_LDDQU +#include //_mm_lddqu_si128 +#endif //USE_SSE3_LDDQU + + +// TODO: Tidy +typedef __m128 vec_float4; +typedef __m128 vec_uint4; +typedef __m128 vec_int4; +typedef __m128i vec_uchar16; +typedef __m128i vec_ushort8; + +#define vec_splat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e)) + +#define _mm_ror_ps(vec,i) \ + (((i)%4) ? (_mm_shuffle_ps(vec,vec, _MM_SHUFFLE((unsigned char)(i+3)%4,(unsigned char)(i+2)%4,(unsigned char)(i+1)%4,(unsigned char)(i+0)%4))) : (vec)) +#define _mm_rol_ps(vec,i) \ + (((i)%4) ? (_mm_shuffle_ps(vec,vec, _MM_SHUFFLE((unsigned char)(7-i)%4,(unsigned char)(6-i)%4,(unsigned char)(5-i)%4,(unsigned char)(4-i)%4))) : (vec)) + +#define vec_sld(vec,vec2,x) _mm_ror_ps(vec, ((x)/4)) + +#define _mm_abs_ps(vec) _mm_andnot_ps(_MASKSIGN_,vec) +#define _mm_neg_ps(vec) _mm_xor_ps(_MASKSIGN_,vec) + +#define vec_madd(a, b, c) _mm_add_ps(c, _mm_mul_ps(a, b) ) + +union SSEFloat +{ + __m128i vi; + __m128 m128; + __m128 vf; + unsigned int ui[4]; + unsigned short s[8]; + float f[4]; + SSEFloat(__m128 v) : m128(v) {} + SSEFloat(__m128i v) : vi(v) {} + SSEFloat() {}//uninitialized +}; + +static VECTORMATH_FORCE_INLINE __m128 vec_sel(__m128 a, __m128 b, __m128 mask) +{ + return _mm_or_ps(_mm_and_ps(mask, b), _mm_andnot_ps(mask, a)); +} +static VECTORMATH_FORCE_INLINE __m128 vec_sel(__m128 a, __m128 b, const unsigned int *_mask) +{ + return vec_sel(a, b, _mm_load_ps((float *)_mask)); +} +static VECTORMATH_FORCE_INLINE __m128 vec_sel(__m128 a, __m128 b, unsigned int _mask) +{ + return vec_sel(a, b, _mm_set1_ps(*(float *)&_mask)); +} + +static VECTORMATH_FORCE_INLINE __m128 toM128(unsigned int x) +{ + return _mm_set1_ps( *(float *)&x ); +} + +static VECTORMATH_FORCE_INLINE __m128 fabsf4(__m128 x) +{ + return _mm_and_ps( x, toM128( 0x7fffffff ) ); +} +/* +union SSE64 +{ + __m128 m128; + struct + { + __m64 m01; + __m64 m23; + } m64; +}; + +static VECTORMATH_FORCE_INLINE __m128 vec_cts(__m128 x, int a) +{ + assert(a == 0); // Only 2^0 supported + (void)a; + SSE64 sse64; + sse64.m64.m01 = _mm_cvttps_pi32(x); + sse64.m64.m23 = _mm_cvttps_pi32(_mm_ror_ps(x,2)); + _mm_empty(); + return sse64.m128; +} + +static VECTORMATH_FORCE_INLINE __m128 vec_ctf(__m128 x, int a) +{ + assert(a == 0); // Only 2^0 supported + (void)a; + SSE64 sse64; + sse64.m128 = x; + __m128 result =_mm_movelh_ps( + _mm_cvt_pi2ps(_mm_setzero_ps(), sse64.m64.m01), + _mm_cvt_pi2ps(_mm_setzero_ps(), sse64.m64.m23)); + _mm_empty(); + return result; +} +*/ +static VECTORMATH_FORCE_INLINE __m128 vec_cts(__m128 x, int a) +{ + assert(a == 0); // Only 2^0 supported + (void)a; + __m128i result = _mm_cvtps_epi32(x); + return (__m128 &)result; +} + +static VECTORMATH_FORCE_INLINE __m128 vec_ctf(__m128 x, int a) +{ + assert(a == 0); // Only 2^0 supported + (void)a; + return _mm_cvtepi32_ps((__m128i &)x); +} + +#define vec_nmsub(a,b,c) _mm_sub_ps( c, _mm_mul_ps( a, b ) ) +#define vec_sub(a,b) _mm_sub_ps( a, b ) +#define vec_add(a,b) _mm_add_ps( a, b ) +#define vec_mul(a,b) _mm_mul_ps( a, b ) +#define vec_xor(a,b) _mm_xor_ps( a, b ) +#define vec_and(a,b) _mm_and_ps( a, b ) +#define vec_cmpeq(a,b) _mm_cmpeq_ps( a, b ) +#define vec_cmpgt(a,b) _mm_cmpgt_ps( a, b ) + +#define vec_mergeh(a,b) _mm_unpacklo_ps( a, b ) +#define vec_mergel(a,b) _mm_unpackhi_ps( a, b ) + +#define vec_andc(a,b) _mm_andnot_ps( b, a ) + +#define sqrtf4(x) _mm_sqrt_ps( x ) +#define rsqrtf4(x) _mm_rsqrt_ps( x ) +#define recipf4(x) _mm_rcp_ps( x ) +#define negatef4(x) _mm_sub_ps( _mm_setzero_ps(), x ) + +static VECTORMATH_FORCE_INLINE __m128 newtonrapson_rsqrt4( const __m128 v ) +{ +#define _half4 _mm_setr_ps(.5f,.5f,.5f,.5f) +#define _three _mm_setr_ps(3.f,3.f,3.f,3.f) +const __m128 approx = _mm_rsqrt_ps( v ); +const __m128 muls = _mm_mul_ps(_mm_mul_ps(v, approx), approx); +return _mm_mul_ps(_mm_mul_ps(_half4, approx), _mm_sub_ps(_three, muls) ); +} + +static VECTORMATH_FORCE_INLINE __m128 acosf4(__m128 x) +{ + __m128 xabs = fabsf4(x); + __m128 select = _mm_cmplt_ps( x, _mm_setzero_ps() ); + __m128 t1 = sqrtf4(vec_sub(_mm_set1_ps(1.0f), xabs)); + + /* Instruction counts can be reduced if the polynomial was + * computed entirely from nested (dependent) fma's. However, + * to reduce the number of pipeline stalls, the polygon is evaluated + * in two halves (hi amd lo). + */ + __m128 xabs2 = _mm_mul_ps(xabs, xabs); + __m128 xabs4 = _mm_mul_ps(xabs2, xabs2); + __m128 hi = vec_madd(vec_madd(vec_madd(_mm_set1_ps(-0.0012624911f), + xabs, _mm_set1_ps(0.0066700901f)), + xabs, _mm_set1_ps(-0.0170881256f)), + xabs, _mm_set1_ps( 0.0308918810f)); + __m128 lo = vec_madd(vec_madd(vec_madd(_mm_set1_ps(-0.0501743046f), + xabs, _mm_set1_ps(0.0889789874f)), + xabs, _mm_set1_ps(-0.2145988016f)), + xabs, _mm_set1_ps( 1.5707963050f)); + + __m128 result = vec_madd(hi, xabs4, lo); + + // Adjust the result if x is negactive. + return vec_sel( + vec_mul(t1, result), // Positive + vec_nmsub(t1, result, _mm_set1_ps(3.1415926535898f)), // Negative + select); +} + +static VECTORMATH_FORCE_INLINE __m128 sinf4(vec_float4 x) +{ + +// +// Common constants used to evaluate sinf4/cosf4/tanf4 +// +#define _SINCOS_CC0 -0.0013602249f +#define _SINCOS_CC1 0.0416566950f +#define _SINCOS_CC2 -0.4999990225f +#define _SINCOS_SC0 -0.0001950727f +#define _SINCOS_SC1 0.0083320758f +#define _SINCOS_SC2 -0.1666665247f + +#define _SINCOS_KC1 1.57079625129f +#define _SINCOS_KC2 7.54978995489e-8f + + vec_float4 xl,xl2,xl3,res; + + // Range reduction using : xl = angle * TwoOverPi; + // + xl = vec_mul(x, _mm_set1_ps(0.63661977236f)); + + // Find the quadrant the angle falls in + // using: q = (int) (ceil(abs(xl))*sign(xl)) + // + vec_int4 q = vec_cts(xl,0); + + // Compute an offset based on the quadrant that the angle falls in + // + vec_int4 offset = _mm_and_ps(q,toM128(0x3)); + + // Remainder in range [-pi/4..pi/4] + // + vec_float4 qf = vec_ctf(q,0); + xl = vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC2),vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC1),x)); + + // Compute x^2 and x^3 + // + xl2 = vec_mul(xl,xl); + xl3 = vec_mul(xl2,xl); + + // Compute both the sin and cos of the angles + // using a polynomial expression: + // cx = 1.0f + xl2 * ((C0 * xl2 + C1) * xl2 + C2), and + // sx = xl + xl3 * ((S0 * xl2 + S1) * xl2 + S2) + // + + vec_float4 cx = + vec_madd( + vec_madd( + vec_madd(_mm_set1_ps(_SINCOS_CC0),xl2,_mm_set1_ps(_SINCOS_CC1)),xl2,_mm_set1_ps(_SINCOS_CC2)),xl2,_mm_set1_ps(1.0f)); + vec_float4 sx = + vec_madd( + vec_madd( + vec_madd(_mm_set1_ps(_SINCOS_SC0),xl2,_mm_set1_ps(_SINCOS_SC1)),xl2,_mm_set1_ps(_SINCOS_SC2)),xl3,xl); + + // Use the cosine when the offset is odd and the sin + // when the offset is even + // + res = vec_sel(cx,sx,vec_cmpeq(vec_and(offset, + toM128(0x1)), + _mm_setzero_ps())); + + // Flip the sign of the result when (offset mod 4) = 1 or 2 + // + return vec_sel( + vec_xor(toM128(0x80000000U), res), // Negative + res, // Positive + vec_cmpeq(vec_and(offset,toM128(0x2)),_mm_setzero_ps())); +} + +static VECTORMATH_FORCE_INLINE void sincosf4(vec_float4 x, vec_float4* s, vec_float4* c) +{ + vec_float4 xl,xl2,xl3; + vec_int4 offsetSin, offsetCos; + + // Range reduction using : xl = angle * TwoOverPi; + // + xl = vec_mul(x, _mm_set1_ps(0.63661977236f)); + + // Find the quadrant the angle falls in + // using: q = (int) (ceil(abs(xl))*sign(xl)) + // + //vec_int4 q = vec_cts(vec_add(xl,vec_sel(_mm_set1_ps(0.5f),xl,(0x80000000))),0); + vec_int4 q = vec_cts(xl,0); + + // Compute the offset based on the quadrant that the angle falls in. + // Add 1 to the offset for the cosine. + // + offsetSin = vec_and(q,toM128((int)0x3)); + __m128i temp = _mm_add_epi32(_mm_set1_epi32(1),(__m128i &)offsetSin); + offsetCos = (__m128 &)temp; + + // Remainder in range [-pi/4..pi/4] + // + vec_float4 qf = vec_ctf(q,0); + xl = vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC2),vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC1),x)); + + // Compute x^2 and x^3 + // + xl2 = vec_mul(xl,xl); + xl3 = vec_mul(xl2,xl); + + // Compute both the sin and cos of the angles + // using a polynomial expression: + // cx = 1.0f + xl2 * ((C0 * xl2 + C1) * xl2 + C2), and + // sx = xl + xl3 * ((S0 * xl2 + S1) * xl2 + S2) + // + vec_float4 cx = + vec_madd( + vec_madd( + vec_madd(_mm_set1_ps(_SINCOS_CC0),xl2,_mm_set1_ps(_SINCOS_CC1)),xl2,_mm_set1_ps(_SINCOS_CC2)),xl2,_mm_set1_ps(1.0f)); + vec_float4 sx = + vec_madd( + vec_madd( + vec_madd(_mm_set1_ps(_SINCOS_SC0),xl2,_mm_set1_ps(_SINCOS_SC1)),xl2,_mm_set1_ps(_SINCOS_SC2)),xl3,xl); + + // Use the cosine when the offset is odd and the sin + // when the offset is even + // + vec_uint4 sinMask = (vec_uint4)vec_cmpeq(vec_and(offsetSin,toM128(0x1)),_mm_setzero_ps()); + vec_uint4 cosMask = (vec_uint4)vec_cmpeq(vec_and(offsetCos,toM128(0x1)),_mm_setzero_ps()); + *s = vec_sel(cx,sx,sinMask); + *c = vec_sel(cx,sx,cosMask); + + // Flip the sign of the result when (offset mod 4) = 1 or 2 + // + sinMask = vec_cmpeq(vec_and(offsetSin,toM128(0x2)),_mm_setzero_ps()); + cosMask = vec_cmpeq(vec_and(offsetCos,toM128(0x2)),_mm_setzero_ps()); + + *s = vec_sel((vec_float4)vec_xor(toM128(0x80000000),(vec_uint4)*s),*s,sinMask); + *c = vec_sel((vec_float4)vec_xor(toM128(0x80000000),(vec_uint4)*c),*c,cosMask); +} + +#include "vecidx_aos.h" +#include "floatInVec.h" +#include "boolInVec.h" + +#ifdef _VECTORMATH_DEBUG +#include +#endif +namespace Vectormath { + +namespace Aos { + +//----------------------------------------------------------------------------- +// Forward Declarations +// + +class Vector3; +class Vector4; +class Point3; +class Quat; +class Matrix3; +class Matrix4; +class Transform3; + +// A 3-D vector in array-of-structures format +// +class Vector3 +{ + __m128 mVec128; + + VECTORMATH_FORCE_INLINE void set128(vec_float4 vec); + + VECTORMATH_FORCE_INLINE vec_float4& get128Ref(); + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Vector3( ) { }; + + // Default copy constructor + // + VECTORMATH_FORCE_INLINE Vector3(const Vector3& vec); + + // Construct a 3-D vector from x, y, and z elements + // + VECTORMATH_FORCE_INLINE Vector3( float x, float y, float z ); + + // Construct a 3-D vector from x, y, and z elements (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3( const floatInVec &x, const floatInVec &y, const floatInVec &z ); + + // Copy elements from a 3-D point into a 3-D vector + // + explicit VECTORMATH_FORCE_INLINE Vector3( const Point3 &pnt ); + + // Set all elements of a 3-D vector to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Vector3( float scalar ); + + // Set all elements of a 3-D vector to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Vector3( const floatInVec &scalar ); + + // Set vector float data in a 3-D vector + // + explicit VECTORMATH_FORCE_INLINE Vector3( __m128 vf4 ); + + // Get vector float data from a 3-D vector + // + VECTORMATH_FORCE_INLINE __m128 get128( ) const; + + // Assign one 3-D vector to another + // + VECTORMATH_FORCE_INLINE Vector3 & operator =( const Vector3 &vec ); + + // Set the x element of a 3-D vector + // + VECTORMATH_FORCE_INLINE Vector3 & setX( float x ); + + // Set the y element of a 3-D vector + // + VECTORMATH_FORCE_INLINE Vector3 & setY( float y ); + + // Set the z element of a 3-D vector + // + VECTORMATH_FORCE_INLINE Vector3 & setZ( float z ); + + // Set the x element of a 3-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & setX( const floatInVec &x ); + + // Set the y element of a 3-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & setY( const floatInVec &y ); + + // Set the z element of a 3-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & setZ( const floatInVec &z ); + + // Get the x element of a 3-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getX( ) const; + + // Get the y element of a 3-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getY( ) const; + + // Get the z element of a 3-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getZ( ) const; + + // Set an x, y, or z element of a 3-D vector by index + // + VECTORMATH_FORCE_INLINE Vector3 & setElem( int idx, float value ); + + // Set an x, y, or z element of a 3-D vector by index (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & setElem( int idx, const floatInVec &value ); + + // Get an x, y, or z element of a 3-D vector by index + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + VECTORMATH_FORCE_INLINE VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + VECTORMATH_FORCE_INLINE const floatInVec operator []( int idx ) const; + + // Add two 3-D vectors + // + VECTORMATH_FORCE_INLINE const Vector3 operator +( const Vector3 &vec ) const; + + // Subtract a 3-D vector from another 3-D vector + // + VECTORMATH_FORCE_INLINE const Vector3 operator -( const Vector3 &vec ) const; + + // Add a 3-D vector to a 3-D point + // + VECTORMATH_FORCE_INLINE const Point3 operator +( const Point3 &pnt ) const; + + // Multiply a 3-D vector by a scalar + // + VECTORMATH_FORCE_INLINE const Vector3 operator *( float scalar ) const; + + // Divide a 3-D vector by a scalar + // + VECTORMATH_FORCE_INLINE const Vector3 operator /( float scalar ) const; + + // Multiply a 3-D vector by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Vector3 operator *( const floatInVec &scalar ) const; + + // Divide a 3-D vector by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Vector3 operator /( const floatInVec &scalar ) const; + + // Perform compound assignment and addition with a 3-D vector + // + VECTORMATH_FORCE_INLINE Vector3 & operator +=( const Vector3 &vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + VECTORMATH_FORCE_INLINE Vector3 & operator -=( const Vector3 &vec ); + + // Perform compound assignment and multiplication by a scalar + // + VECTORMATH_FORCE_INLINE Vector3 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + VECTORMATH_FORCE_INLINE Vector3 & operator /=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and division by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & operator /=( const floatInVec &scalar ); + + // Negate all elements of a 3-D vector + // + VECTORMATH_FORCE_INLINE const Vector3 operator -( ) const; + + // Construct x axis + // + static VECTORMATH_FORCE_INLINE const Vector3 xAxis( ); + + // Construct y axis + // + static VECTORMATH_FORCE_INLINE const Vector3 yAxis( ); + + // Construct z axis + // + static VECTORMATH_FORCE_INLINE const Vector3 zAxis( ); + +}; + +// Multiply a 3-D vector by a scalar +// +VECTORMATH_FORCE_INLINE const Vector3 operator *( float scalar, const Vector3 &vec ); + +// Multiply a 3-D vector by a scalar (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Vector3 operator *( const floatInVec &scalar, const Vector3 &vec ); + +// Multiply two 3-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector3 mulPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Divide two 3-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +VECTORMATH_FORCE_INLINE const Vector3 divPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Compute the reciprocal of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +VECTORMATH_FORCE_INLINE const Vector3 recipPerElem( const Vector3 &vec ); + +// Compute the absolute value of a 3-D vector per element +// +VECTORMATH_FORCE_INLINE const Vector3 absPerElem( const Vector3 &vec ); + +// Copy sign from one 3-D vector to another, per element +// +VECTORMATH_FORCE_INLINE const Vector3 copySignPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Maximum of two 3-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector3 maxPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Minimum of two 3-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector3 minPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Maximum element of a 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Vector3 &vec ); + +// Minimum element of a 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Vector3 &vec ); + +// Compute the sum of all elements of a 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec sum( const Vector3 &vec ); + +// Compute the dot product of two 3-D vectors +// +VECTORMATH_FORCE_INLINE const floatInVec dot( const Vector3 &vec0, const Vector3 &vec1 ); + +// Compute the square of the length of a 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec lengthSqr( const Vector3 &vec ); + +// Compute the length of a 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec length( const Vector3 &vec ); + +// Normalize a 3-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +VECTORMATH_FORCE_INLINE const Vector3 normalize( const Vector3 &vec ); + +// Compute cross product of two 3-D vectors +// +VECTORMATH_FORCE_INLINE const Vector3 cross( const Vector3 &vec0, const Vector3 &vec1 ); + +// Outer product of two 3-D vectors +// +VECTORMATH_FORCE_INLINE const Matrix3 outer( const Vector3 &vec0, const Vector3 &vec1 ); + +// Pre-multiply a row vector by a 3x3 matrix +// NOTE: +// Slower than column post-multiply. +// +VECTORMATH_FORCE_INLINE const Vector3 rowMul( const Vector3 &vec, const Matrix3 & mat ); + +// Cross-product matrix of a 3-D vector +// +VECTORMATH_FORCE_INLINE const Matrix3 crossMatrix( const Vector3 &vec ); + +// Create cross-product matrix and multiply +// NOTE: +// Faster than separately creating a cross-product matrix and multiplying. +// +VECTORMATH_FORCE_INLINE const Matrix3 crossMatrixMul( const Vector3 &vec, const Matrix3 & mat ); + +// Linear interpolation between two 3-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector3 lerp( float t, const Vector3 &vec0, const Vector3 &vec1 ); + +// Linear interpolation between two 3-D vectors (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector3 lerp( const floatInVec &t, const Vector3 &vec0, const Vector3 &vec1 ); + +// Spherical linear interpolation between two 3-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector3 slerp( float t, const Vector3 &unitVec0, const Vector3 &unitVec1 ); + +// Spherical linear interpolation between two 3-D vectors (scalar data contained in vector data type) +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector3 slerp( const floatInVec &t, const Vector3 &unitVec0, const Vector3 &unitVec1 ); + +// Conditionally select between two 3-D vectors +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Vector3 select( const Vector3 &vec0, const Vector3 &vec1, bool select1 ); + +// Conditionally select between two 3-D vectors (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Vector3 select( const Vector3 &vec0, const Vector3 &vec1, const boolInVec &select1 ); + +// Store x, y, and z elements of 3-D vector in first three words of a quadword, preserving fourth word +// +VECTORMATH_FORCE_INLINE void storeXYZ( const Vector3 &vec, __m128 * quad ); + +// Load four three-float 3-D vectors, stored in three quadwords +// +VECTORMATH_FORCE_INLINE void loadXYZArray( Vector3 & vec0, Vector3 & vec1, Vector3 & vec2, Vector3 & vec3, const __m128 * threeQuads ); + +// Store four 3-D vectors in three quadwords +// +VECTORMATH_FORCE_INLINE void storeXYZArray( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, __m128 * threeQuads ); + +// Store eight 3-D vectors as half-floats +// +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, const Vector3 &vec4, const Vector3 &vec5, const Vector3 &vec6, const Vector3 &vec7, vec_ushort8 * threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Vector3 &vec ); + +// Print a 3-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Vector3 &vec, const char * name ); + +#endif + +// A 4-D vector in array-of-structures format +// +class Vector4 +{ + __m128 mVec128; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Vector4( ) { }; + + // Construct a 4-D vector from x, y, z, and w elements + // + VECTORMATH_FORCE_INLINE Vector4( float x, float y, float z, float w ); + + // Construct a 4-D vector from x, y, z, and w elements (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4( const floatInVec &x, const floatInVec &y, const floatInVec &z, const floatInVec &w ); + + // Construct a 4-D vector from a 3-D vector and a scalar + // + VECTORMATH_FORCE_INLINE Vector4( const Vector3 &xyz, float w ); + + // Construct a 4-D vector from a 3-D vector and a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4( const Vector3 &xyz, const floatInVec &w ); + + // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + // + explicit VECTORMATH_FORCE_INLINE Vector4( const Vector3 &vec ); + + // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + // + explicit VECTORMATH_FORCE_INLINE Vector4( const Point3 &pnt ); + + // Copy elements from a quaternion into a 4-D vector + // + explicit VECTORMATH_FORCE_INLINE Vector4( const Quat &quat ); + + // Set all elements of a 4-D vector to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Vector4( float scalar ); + + // Set all elements of a 4-D vector to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Vector4( const floatInVec &scalar ); + + // Set vector float data in a 4-D vector + // + explicit VECTORMATH_FORCE_INLINE Vector4( __m128 vf4 ); + + // Get vector float data from a 4-D vector + // + VECTORMATH_FORCE_INLINE __m128 get128( ) const; + + // Assign one 4-D vector to another + // + VECTORMATH_FORCE_INLINE Vector4 & operator =( const Vector4 &vec ); + + // Set the x, y, and z elements of a 4-D vector + // NOTE: + // This function does not change the w element. + // + VECTORMATH_FORCE_INLINE Vector4 & setXYZ( const Vector3 &vec ); + + // Get the x, y, and z elements of a 4-D vector + // + VECTORMATH_FORCE_INLINE const Vector3 getXYZ( ) const; + + // Set the x element of a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & setX( float x ); + + // Set the y element of a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & setY( float y ); + + // Set the z element of a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & setZ( float z ); + + // Set the w element of a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & setW( float w ); + + // Set the x element of a 4-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & setX( const floatInVec &x ); + + // Set the y element of a 4-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & setY( const floatInVec &y ); + + // Set the z element of a 4-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & setZ( const floatInVec &z ); + + // Set the w element of a 4-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & setW( const floatInVec &w ); + + // Get the x element of a 4-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getX( ) const; + + // Get the y element of a 4-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getY( ) const; + + // Get the z element of a 4-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getZ( ) const; + + // Get the w element of a 4-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getW( ) const; + + // Set an x, y, z, or w element of a 4-D vector by index + // + VECTORMATH_FORCE_INLINE Vector4 & setElem( int idx, float value ); + + // Set an x, y, z, or w element of a 4-D vector by index (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & setElem( int idx, const floatInVec &value ); + + // Get an x, y, z, or w element of a 4-D vector by index + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + VECTORMATH_FORCE_INLINE VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + VECTORMATH_FORCE_INLINE const floatInVec operator []( int idx ) const; + + // Add two 4-D vectors + // + VECTORMATH_FORCE_INLINE const Vector4 operator +( const Vector4 &vec ) const; + + // Subtract a 4-D vector from another 4-D vector + // + VECTORMATH_FORCE_INLINE const Vector4 operator -( const Vector4 &vec ) const; + + // Multiply a 4-D vector by a scalar + // + VECTORMATH_FORCE_INLINE const Vector4 operator *( float scalar ) const; + + // Divide a 4-D vector by a scalar + // + VECTORMATH_FORCE_INLINE const Vector4 operator /( float scalar ) const; + + // Multiply a 4-D vector by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Vector4 operator *( const floatInVec &scalar ) const; + + // Divide a 4-D vector by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Vector4 operator /( const floatInVec &scalar ) const; + + // Perform compound assignment and addition with a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & operator +=( const Vector4 &vec ); + + // Perform compound assignment and subtraction by a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & operator -=( const Vector4 &vec ); + + // Perform compound assignment and multiplication by a scalar + // + VECTORMATH_FORCE_INLINE Vector4 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + VECTORMATH_FORCE_INLINE Vector4 & operator /=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and division by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & operator /=( const floatInVec &scalar ); + + // Negate all elements of a 4-D vector + // + VECTORMATH_FORCE_INLINE const Vector4 operator -( ) const; + + // Construct x axis + // + static VECTORMATH_FORCE_INLINE const Vector4 xAxis( ); + + // Construct y axis + // + static VECTORMATH_FORCE_INLINE const Vector4 yAxis( ); + + // Construct z axis + // + static VECTORMATH_FORCE_INLINE const Vector4 zAxis( ); + + // Construct w axis + // + static VECTORMATH_FORCE_INLINE const Vector4 wAxis( ); + +}; + +// Multiply a 4-D vector by a scalar +// +VECTORMATH_FORCE_INLINE const Vector4 operator *( float scalar, const Vector4 &vec ); + +// Multiply a 4-D vector by a scalar (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Vector4 operator *( const floatInVec &scalar, const Vector4 &vec ); + +// Multiply two 4-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector4 mulPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Divide two 4-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +VECTORMATH_FORCE_INLINE const Vector4 divPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Compute the reciprocal of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +VECTORMATH_FORCE_INLINE const Vector4 recipPerElem( const Vector4 &vec ); + +// Compute the absolute value of a 4-D vector per element +// +VECTORMATH_FORCE_INLINE const Vector4 absPerElem( const Vector4 &vec ); + +// Copy sign from one 4-D vector to another, per element +// +VECTORMATH_FORCE_INLINE const Vector4 copySignPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Maximum of two 4-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector4 maxPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Minimum of two 4-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector4 minPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Maximum element of a 4-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Vector4 &vec ); + +// Minimum element of a 4-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Vector4 &vec ); + +// Compute the sum of all elements of a 4-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec sum( const Vector4 &vec ); + +// Compute the dot product of two 4-D vectors +// +VECTORMATH_FORCE_INLINE const floatInVec dot( const Vector4 &vec0, const Vector4 &vec1 ); + +// Compute the square of the length of a 4-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec lengthSqr( const Vector4 &vec ); + +// Compute the length of a 4-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec length( const Vector4 &vec ); + +// Normalize a 4-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +VECTORMATH_FORCE_INLINE const Vector4 normalize( const Vector4 &vec ); + +// Outer product of two 4-D vectors +// +VECTORMATH_FORCE_INLINE const Matrix4 outer( const Vector4 &vec0, const Vector4 &vec1 ); + +// Linear interpolation between two 4-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector4 lerp( float t, const Vector4 &vec0, const Vector4 &vec1 ); + +// Linear interpolation between two 4-D vectors (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector4 lerp( const floatInVec &t, const Vector4 &vec0, const Vector4 &vec1 ); + +// Spherical linear interpolation between two 4-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector4 slerp( float t, const Vector4 &unitVec0, const Vector4 &unitVec1 ); + +// Spherical linear interpolation between two 4-D vectors (scalar data contained in vector data type) +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector4 slerp( const floatInVec &t, const Vector4 &unitVec0, const Vector4 &unitVec1 ); + +// Conditionally select between two 4-D vectors +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Vector4 select( const Vector4 &vec0, const Vector4 &vec1, bool select1 ); + +// Conditionally select between two 4-D vectors (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Vector4 select( const Vector4 &vec0, const Vector4 &vec1, const boolInVec &select1 ); + +// Store four 4-D vectors as half-floats +// +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Vector4 &vec0, const Vector4 &vec1, const Vector4 &vec2, const Vector4 &vec3, vec_ushort8 * twoQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Vector4 &vec ); + +// Print a 4-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Vector4 &vec, const char * name ); + +#endif + +// A 3-D point in array-of-structures format +// +class Point3 +{ + __m128 mVec128; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Point3( ) { }; + + // Construct a 3-D point from x, y, and z elements + // + VECTORMATH_FORCE_INLINE Point3( float x, float y, float z ); + + // Construct a 3-D point from x, y, and z elements (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Point3( const floatInVec &x, const floatInVec &y, const floatInVec &z ); + + // Copy elements from a 3-D vector into a 3-D point + // + explicit VECTORMATH_FORCE_INLINE Point3( const Vector3 &vec ); + + // Set all elements of a 3-D point to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Point3( float scalar ); + + // Set all elements of a 3-D point to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Point3( const floatInVec &scalar ); + + // Set vector float data in a 3-D point + // + explicit VECTORMATH_FORCE_INLINE Point3( __m128 vf4 ); + + // Get vector float data from a 3-D point + // + VECTORMATH_FORCE_INLINE __m128 get128( ) const; + + // Assign one 3-D point to another + // + VECTORMATH_FORCE_INLINE Point3 & operator =( const Point3 &pnt ); + + // Set the x element of a 3-D point + // + VECTORMATH_FORCE_INLINE Point3 & setX( float x ); + + // Set the y element of a 3-D point + // + VECTORMATH_FORCE_INLINE Point3 & setY( float y ); + + // Set the z element of a 3-D point + // + VECTORMATH_FORCE_INLINE Point3 & setZ( float z ); + + // Set the x element of a 3-D point (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Point3 & setX( const floatInVec &x ); + + // Set the y element of a 3-D point (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Point3 & setY( const floatInVec &y ); + + // Set the z element of a 3-D point (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Point3 & setZ( const floatInVec &z ); + + // Get the x element of a 3-D point + // + VECTORMATH_FORCE_INLINE const floatInVec getX( ) const; + + // Get the y element of a 3-D point + // + VECTORMATH_FORCE_INLINE const floatInVec getY( ) const; + + // Get the z element of a 3-D point + // + VECTORMATH_FORCE_INLINE const floatInVec getZ( ) const; + + // Set an x, y, or z element of a 3-D point by index + // + VECTORMATH_FORCE_INLINE Point3 & setElem( int idx, float value ); + + // Set an x, y, or z element of a 3-D point by index (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Point3 & setElem( int idx, const floatInVec &value ); + + // Get an x, y, or z element of a 3-D point by index + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + VECTORMATH_FORCE_INLINE VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + VECTORMATH_FORCE_INLINE const floatInVec operator []( int idx ) const; + + // Subtract a 3-D point from another 3-D point + // + VECTORMATH_FORCE_INLINE const Vector3 operator -( const Point3 &pnt ) const; + + // Add a 3-D point to a 3-D vector + // + VECTORMATH_FORCE_INLINE const Point3 operator +( const Vector3 &vec ) const; + + // Subtract a 3-D vector from a 3-D point + // + VECTORMATH_FORCE_INLINE const Point3 operator -( const Vector3 &vec ) const; + + // Perform compound assignment and addition with a 3-D vector + // + VECTORMATH_FORCE_INLINE Point3 & operator +=( const Vector3 &vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + VECTORMATH_FORCE_INLINE Point3 & operator -=( const Vector3 &vec ); + +}; + +// Multiply two 3-D points per element +// +VECTORMATH_FORCE_INLINE const Point3 mulPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Divide two 3-D points per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +VECTORMATH_FORCE_INLINE const Point3 divPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Compute the reciprocal of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +VECTORMATH_FORCE_INLINE const Point3 recipPerElem( const Point3 &pnt ); + +// Compute the absolute value of a 3-D point per element +// +VECTORMATH_FORCE_INLINE const Point3 absPerElem( const Point3 &pnt ); + +// Copy sign from one 3-D point to another, per element +// +VECTORMATH_FORCE_INLINE const Point3 copySignPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Maximum of two 3-D points per element +// +VECTORMATH_FORCE_INLINE const Point3 maxPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Minimum of two 3-D points per element +// +VECTORMATH_FORCE_INLINE const Point3 minPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Maximum element of a 3-D point +// +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Point3 &pnt ); + +// Minimum element of a 3-D point +// +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Point3 &pnt ); + +// Compute the sum of all elements of a 3-D point +// +VECTORMATH_FORCE_INLINE const floatInVec sum( const Point3 &pnt ); + +// Apply uniform scale to a 3-D point +// +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, float scaleVal ); + +// Apply uniform scale to a 3-D point (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, const floatInVec &scaleVal ); + +// Apply non-uniform scale to a 3-D point +// +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, const Vector3 &scaleVec ); + +// Scalar projection of a 3-D point on a unit-length 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec projection( const Point3 &pnt, const Vector3 &unitVec ); + +// Compute the square of the distance of a 3-D point from the coordinate-system origin +// +VECTORMATH_FORCE_INLINE const floatInVec distSqrFromOrigin( const Point3 &pnt ); + +// Compute the distance of a 3-D point from the coordinate-system origin +// +VECTORMATH_FORCE_INLINE const floatInVec distFromOrigin( const Point3 &pnt ); + +// Compute the square of the distance between two 3-D points +// +VECTORMATH_FORCE_INLINE const floatInVec distSqr( const Point3 &pnt0, const Point3 &pnt1 ); + +// Compute the distance between two 3-D points +// +VECTORMATH_FORCE_INLINE const floatInVec dist( const Point3 &pnt0, const Point3 &pnt1 ); + +// Linear interpolation between two 3-D points +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Point3 lerp( float t, const Point3 &pnt0, const Point3 &pnt1 ); + +// Linear interpolation between two 3-D points (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Point3 lerp( const floatInVec &t, const Point3 &pnt0, const Point3 &pnt1 ); + +// Conditionally select between two 3-D points +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Point3 select( const Point3 &pnt0, const Point3 &pnt1, bool select1 ); + +// Conditionally select between two 3-D points (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Point3 select( const Point3 &pnt0, const Point3 &pnt1, const boolInVec &select1 ); + +// Store x, y, and z elements of 3-D point in first three words of a quadword, preserving fourth word +// +VECTORMATH_FORCE_INLINE void storeXYZ( const Point3 &pnt, __m128 * quad ); + +// Load four three-float 3-D points, stored in three quadwords +// +VECTORMATH_FORCE_INLINE void loadXYZArray( Point3 & pnt0, Point3 & pnt1, Point3 & pnt2, Point3 & pnt3, const __m128 * threeQuads ); + +// Store four 3-D points in three quadwords +// +VECTORMATH_FORCE_INLINE void storeXYZArray( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, __m128 * threeQuads ); + +// Store eight 3-D points as half-floats +// +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, const Point3 &pnt4, const Point3 &pnt5, const Point3 &pnt6, const Point3 &pnt7, vec_ushort8 * threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D point +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Point3 &pnt ); + +// Print a 3-D point and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Point3 &pnt, const char * name ); + +#endif + +// A quaternion in array-of-structures format +// +class Quat +{ + __m128 mVec128; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Quat( ) { }; + + VECTORMATH_FORCE_INLINE Quat(const Quat& quat); + + // Construct a quaternion from x, y, z, and w elements + // + VECTORMATH_FORCE_INLINE Quat( float x, float y, float z, float w ); + + // Construct a quaternion from x, y, z, and w elements (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat( const floatInVec &x, const floatInVec &y, const floatInVec &z, const floatInVec &w ); + + // Construct a quaternion from a 3-D vector and a scalar + // + VECTORMATH_FORCE_INLINE Quat( const Vector3 &xyz, float w ); + + // Construct a quaternion from a 3-D vector and a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat( const Vector3 &xyz, const floatInVec &w ); + + // Copy elements from a 4-D vector into a quaternion + // + explicit VECTORMATH_FORCE_INLINE Quat( const Vector4 &vec ); + + // Convert a rotation matrix to a unit-length quaternion + // + explicit VECTORMATH_FORCE_INLINE Quat( const Matrix3 & rotMat ); + + // Set all elements of a quaternion to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Quat( float scalar ); + + // Set all elements of a quaternion to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Quat( const floatInVec &scalar ); + + // Set vector float data in a quaternion + // + explicit VECTORMATH_FORCE_INLINE Quat( __m128 vf4 ); + + // Get vector float data from a quaternion + // + VECTORMATH_FORCE_INLINE __m128 get128( ) const; + + // Set a quaterion from vector float data + // + VECTORMATH_FORCE_INLINE void set128(vec_float4 vec); + + // Assign one quaternion to another + // + VECTORMATH_FORCE_INLINE Quat & operator =( const Quat &quat ); + + // Set the x, y, and z elements of a quaternion + // NOTE: + // This function does not change the w element. + // + VECTORMATH_FORCE_INLINE Quat & setXYZ( const Vector3 &vec ); + + // Get the x, y, and z elements of a quaternion + // + VECTORMATH_FORCE_INLINE const Vector3 getXYZ( ) const; + + // Set the x element of a quaternion + // + VECTORMATH_FORCE_INLINE Quat & setX( float x ); + + // Set the y element of a quaternion + // + VECTORMATH_FORCE_INLINE Quat & setY( float y ); + + // Set the z element of a quaternion + // + VECTORMATH_FORCE_INLINE Quat & setZ( float z ); + + // Set the w element of a quaternion + // + VECTORMATH_FORCE_INLINE Quat & setW( float w ); + + // Set the x element of a quaternion (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & setX( const floatInVec &x ); + + // Set the y element of a quaternion (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & setY( const floatInVec &y ); + + // Set the z element of a quaternion (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & setZ( const floatInVec &z ); + + // Set the w element of a quaternion (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & setW( const floatInVec &w ); + + // Get the x element of a quaternion + // + VECTORMATH_FORCE_INLINE const floatInVec getX( ) const; + + // Get the y element of a quaternion + // + VECTORMATH_FORCE_INLINE const floatInVec getY( ) const; + + // Get the z element of a quaternion + // + VECTORMATH_FORCE_INLINE const floatInVec getZ( ) const; + + // Get the w element of a quaternion + // + VECTORMATH_FORCE_INLINE const floatInVec getW( ) const; + + // Set an x, y, z, or w element of a quaternion by index + // + VECTORMATH_FORCE_INLINE Quat & setElem( int idx, float value ); + + // Set an x, y, z, or w element of a quaternion by index (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & setElem( int idx, const floatInVec &value ); + + // Get an x, y, z, or w element of a quaternion by index + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + VECTORMATH_FORCE_INLINE VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + VECTORMATH_FORCE_INLINE const floatInVec operator []( int idx ) const; + + // Add two quaternions + // + VECTORMATH_FORCE_INLINE const Quat operator +( const Quat &quat ) const; + + // Subtract a quaternion from another quaternion + // + VECTORMATH_FORCE_INLINE const Quat operator -( const Quat &quat ) const; + + // Multiply two quaternions + // + VECTORMATH_FORCE_INLINE const Quat operator *( const Quat &quat ) const; + + // Multiply a quaternion by a scalar + // + VECTORMATH_FORCE_INLINE const Quat operator *( float scalar ) const; + + // Divide a quaternion by a scalar + // + VECTORMATH_FORCE_INLINE const Quat operator /( float scalar ) const; + + // Multiply a quaternion by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Quat operator *( const floatInVec &scalar ) const; + + // Divide a quaternion by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Quat operator /( const floatInVec &scalar ) const; + + // Perform compound assignment and addition with a quaternion + // + VECTORMATH_FORCE_INLINE Quat & operator +=( const Quat &quat ); + + // Perform compound assignment and subtraction by a quaternion + // + VECTORMATH_FORCE_INLINE Quat & operator -=( const Quat &quat ); + + // Perform compound assignment and multiplication by a quaternion + // + VECTORMATH_FORCE_INLINE Quat & operator *=( const Quat &quat ); + + // Perform compound assignment and multiplication by a scalar + // + VECTORMATH_FORCE_INLINE Quat & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + VECTORMATH_FORCE_INLINE Quat & operator /=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and division by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & operator /=( const floatInVec &scalar ); + + // Negate all elements of a quaternion + // + VECTORMATH_FORCE_INLINE const Quat operator -( ) const; + + // Construct an identity quaternion + // + static VECTORMATH_FORCE_INLINE const Quat identity( ); + + // Construct a quaternion to rotate between two unit-length 3-D vectors + // NOTE: + // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + // + static VECTORMATH_FORCE_INLINE const Quat rotation( const Vector3 &unitVec0, const Vector3 &unitVec1 ); + + // Construct a quaternion to rotate around a unit-length 3-D vector + // + static VECTORMATH_FORCE_INLINE const Quat rotation( float radians, const Vector3 &unitVec ); + + // Construct a quaternion to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Quat rotation( const floatInVec &radians, const Vector3 &unitVec ); + + // Construct a quaternion to rotate around the x axis + // + static VECTORMATH_FORCE_INLINE const Quat rotationX( float radians ); + + // Construct a quaternion to rotate around the y axis + // + static VECTORMATH_FORCE_INLINE const Quat rotationY( float radians ); + + // Construct a quaternion to rotate around the z axis + // + static VECTORMATH_FORCE_INLINE const Quat rotationZ( float radians ); + + // Construct a quaternion to rotate around the x axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Quat rotationX( const floatInVec &radians ); + + // Construct a quaternion to rotate around the y axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Quat rotationY( const floatInVec &radians ); + + // Construct a quaternion to rotate around the z axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Quat rotationZ( const floatInVec &radians ); + +}; + +// Multiply a quaternion by a scalar +// +VECTORMATH_FORCE_INLINE const Quat operator *( float scalar, const Quat &quat ); + +// Multiply a quaternion by a scalar (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Quat operator *( const floatInVec &scalar, const Quat &quat ); + +// Compute the conjugate of a quaternion +// +VECTORMATH_FORCE_INLINE const Quat conj( const Quat &quat ); + +// Use a unit-length quaternion to rotate a 3-D vector +// +VECTORMATH_FORCE_INLINE const Vector3 rotate( const Quat &unitQuat, const Vector3 &vec ); + +// Compute the dot product of two quaternions +// +VECTORMATH_FORCE_INLINE const floatInVec dot( const Quat &quat0, const Quat &quat1 ); + +// Compute the norm of a quaternion +// +VECTORMATH_FORCE_INLINE const floatInVec norm( const Quat &quat ); + +// Compute the length of a quaternion +// +VECTORMATH_FORCE_INLINE const floatInVec length( const Quat &quat ); + +// Normalize a quaternion +// NOTE: +// The result is unpredictable when all elements of quat are at or near zero. +// +VECTORMATH_FORCE_INLINE const Quat normalize( const Quat &quat ); + +// Linear interpolation between two quaternions +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Quat lerp( float t, const Quat &quat0, const Quat &quat1 ); + +// Linear interpolation between two quaternions (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Quat lerp( const floatInVec &t, const Quat &quat0, const Quat &quat1 ); + +// Spherical linear interpolation between two quaternions +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Quat slerp( float t, const Quat &unitQuat0, const Quat &unitQuat1 ); + +// Spherical linear interpolation between two quaternions (scalar data contained in vector data type) +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Quat slerp( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1 ); + +// Spherical quadrangle interpolation +// +VECTORMATH_FORCE_INLINE const Quat squad( float t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ); + +// Spherical quadrangle interpolation (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Quat squad( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ); + +// Conditionally select between two quaternions +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, bool select1 ); + +// Conditionally select between two quaternions (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, const boolInVec &select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a quaternion +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Quat &quat ); + +// Print a quaternion and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Quat &quat, const char * name ); + +#endif + +// A 3x3 matrix in array-of-structures format +// +class Matrix3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Matrix3( ) { }; + + // Copy a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3( const Matrix3 & mat ); + + // Construct a 3x3 matrix containing the specified columns + // + VECTORMATH_FORCE_INLINE Matrix3( const Vector3 &col0, const Vector3 &col1, const Vector3 &col2 ); + + // Construct a 3x3 rotation matrix from a unit-length quaternion + // + explicit VECTORMATH_FORCE_INLINE Matrix3( const Quat &unitQuat ); + + // Set all elements of a 3x3 matrix to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Matrix3( float scalar ); + + // Set all elements of a 3x3 matrix to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Matrix3( const floatInVec &scalar ); + + // Assign one 3x3 matrix to another + // + VECTORMATH_FORCE_INLINE Matrix3 & operator =( const Matrix3 & mat ); + + // Set column 0 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & setCol0( const Vector3 &col0 ); + + // Set column 1 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & setCol1( const Vector3 &col1 ); + + // Set column 2 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & setCol2( const Vector3 &col2 ); + + // Get column 0 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol0( ) const; + + // Get column 1 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol1( ) const; + + // Get column 2 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol2( ) const; + + // Set the column of a 3x3 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Matrix3 & setCol( int col, const Vector3 &vec ); + + // Set the row of a 3x3 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Matrix3 & setRow( int row, const Vector3 &vec ); + + // Get the column of a 3x3 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector3 getCol( int col ) const; + + // Get the row of a 3x3 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector3 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + VECTORMATH_FORCE_INLINE Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + VECTORMATH_FORCE_INLINE const Vector3 operator []( int col ) const; + + // Set the element of a 3x3 matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE Matrix3 & setElem( int col, int row, float val ); + + // Set the element of a 3x3 matrix referred to by column and row indices (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Matrix3 & setElem( int col, int row, const floatInVec &val ); + + // Get the element of a 3x3 matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int col, int row ) const; + + // Add two 3x3 matrices + // + VECTORMATH_FORCE_INLINE const Matrix3 operator +( const Matrix3 & mat ) const; + + // Subtract a 3x3 matrix from another 3x3 matrix + // + VECTORMATH_FORCE_INLINE const Matrix3 operator -( const Matrix3 & mat ) const; + + // Negate all elements of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE const Matrix3 operator -( ) const; + + // Multiply a 3x3 matrix by a scalar + // + VECTORMATH_FORCE_INLINE const Matrix3 operator *( float scalar ) const; + + // Multiply a 3x3 matrix by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Matrix3 operator *( const floatInVec &scalar ) const; + + // Multiply a 3x3 matrix by a 3-D vector + // + VECTORMATH_FORCE_INLINE const Vector3 operator *( const Vector3 &vec ) const; + + // Multiply two 3x3 matrices + // + VECTORMATH_FORCE_INLINE const Matrix3 operator *( const Matrix3 & mat ) const; + + // Perform compound assignment and addition with a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & operator +=( const Matrix3 & mat ); + + // Perform compound assignment and subtraction by a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & operator -=( const Matrix3 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + VECTORMATH_FORCE_INLINE Matrix3 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Matrix3 & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and multiplication by a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & operator *=( const Matrix3 & mat ); + + // Construct an identity 3x3 matrix + // + static VECTORMATH_FORCE_INLINE const Matrix3 identity( ); + + // Construct a 3x3 matrix to rotate around the x axis + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationX( float radians ); + + // Construct a 3x3 matrix to rotate around the y axis + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationY( float radians ); + + // Construct a 3x3 matrix to rotate around the z axis + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationZ( float radians ); + + // Construct a 3x3 matrix to rotate around the x axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationX( const floatInVec &radians ); + + // Construct a 3x3 matrix to rotate around the y axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationY( const floatInVec &radians ); + + // Construct a 3x3 matrix to rotate around the z axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationZ( const floatInVec &radians ); + + // Construct a 3x3 matrix to rotate around the x, y, and z axes + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationZYX( const Vector3 &radiansXYZ ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotation( float radians, const Vector3 &unitVec ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotation( const floatInVec &radians, const Vector3 &unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotation( const Quat &unitQuat ); + + // Construct a 3x3 matrix to perform scaling + // + static VECTORMATH_FORCE_INLINE const Matrix3 scale( const Vector3 &scaleVec ); + +}; +// Multiply a 3x3 matrix by a scalar +// +VECTORMATH_FORCE_INLINE const Matrix3 operator *( float scalar, const Matrix3 & mat ); + +// Multiply a 3x3 matrix by a scalar (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Matrix3 operator *( const floatInVec &scalar, const Matrix3 & mat ); + +// Append (post-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Matrix3 appendScale( const Matrix3 & mat, const Vector3 &scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Matrix3 prependScale( const Vector3 &scaleVec, const Matrix3 & mat ); + +// Multiply two 3x3 matrices per element +// +VECTORMATH_FORCE_INLINE const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); + +// Compute the absolute value of a 3x3 matrix per element +// +VECTORMATH_FORCE_INLINE const Matrix3 absPerElem( const Matrix3 & mat ); + +// Transpose of a 3x3 matrix +// +VECTORMATH_FORCE_INLINE const Matrix3 transpose( const Matrix3 & mat ); + +// Compute the inverse of a 3x3 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +VECTORMATH_FORCE_INLINE const Matrix3 inverse( const Matrix3 & mat ); + +// Determinant of a 3x3 matrix +// +VECTORMATH_FORCE_INLINE const floatInVec determinant( const Matrix3 & mat ); + +// Conditionally select between two 3x3 matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ); + +// Conditionally select between two 3x3 matrices (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, const boolInVec &select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x3 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Matrix3 & mat ); + +// Print a 3x3 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Matrix3 & mat, const char * name ); + +#endif + +// A 4x4 matrix in array-of-structures format +// +class Matrix4 +{ + Vector4 mCol0; + Vector4 mCol1; + Vector4 mCol2; + Vector4 mCol3; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Matrix4( ) { }; + + // Copy a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4( const Matrix4 & mat ); + + // Construct a 4x4 matrix containing the specified columns + // + VECTORMATH_FORCE_INLINE Matrix4( const Vector4 &col0, const Vector4 &col1, const Vector4 &col2, const Vector4 &col3 ); + + // Construct a 4x4 matrix from a 3x4 transformation matrix + // + explicit VECTORMATH_FORCE_INLINE Matrix4( const Transform3 & mat ); + + // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + // + VECTORMATH_FORCE_INLINE Matrix4( const Matrix3 & mat, const Vector3 &translateVec ); + + // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + // + VECTORMATH_FORCE_INLINE Matrix4( const Quat &unitQuat, const Vector3 &translateVec ); + + // Set all elements of a 4x4 matrix to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Matrix4( float scalar ); + + // Set all elements of a 4x4 matrix to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Matrix4( const floatInVec &scalar ); + + // Assign one 4x4 matrix to another + // + VECTORMATH_FORCE_INLINE Matrix4 & operator =( const Matrix4 & mat ); + + // Set the upper-left 3x3 submatrix + // NOTE: + // This function does not change the bottom row elements. + // + VECTORMATH_FORCE_INLINE Matrix4 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Matrix3 getUpper3x3( ) const; + + // Set translation component + // NOTE: + // This function does not change the bottom row elements. + // + VECTORMATH_FORCE_INLINE Matrix4 & setTranslation( const Vector3 &translateVec ); + + // Get the translation component of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getTranslation( ) const; + + // Set column 0 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & setCol0( const Vector4 &col0 ); + + // Set column 1 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & setCol1( const Vector4 &col1 ); + + // Set column 2 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & setCol2( const Vector4 &col2 ); + + // Set column 3 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & setCol3( const Vector4 &col3 ); + + // Get column 0 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Vector4 getCol0( ) const; + + // Get column 1 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Vector4 getCol1( ) const; + + // Get column 2 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Vector4 getCol2( ) const; + + // Get column 3 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Vector4 getCol3( ) const; + + // Set the column of a 4x4 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Matrix4 & setCol( int col, const Vector4 &vec ); + + // Set the row of a 4x4 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Matrix4 & setRow( int row, const Vector4 &vec ); + + // Get the column of a 4x4 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector4 getCol( int col ) const; + + // Get the row of a 4x4 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + VECTORMATH_FORCE_INLINE Vector4 & operator []( int col ); + + // Subscripting operator to get a column + // + VECTORMATH_FORCE_INLINE const Vector4 operator []( int col ) const; + + // Set the element of a 4x4 matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE Matrix4 & setElem( int col, int row, float val ); + + // Set the element of a 4x4 matrix referred to by column and row indices (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Matrix4 & setElem( int col, int row, const floatInVec &val ); + + // Get the element of a 4x4 matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int col, int row ) const; + + // Add two 4x4 matrices + // + VECTORMATH_FORCE_INLINE const Matrix4 operator +( const Matrix4 & mat ) const; + + // Subtract a 4x4 matrix from another 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Matrix4 operator -( const Matrix4 & mat ) const; + + // Negate all elements of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Matrix4 operator -( ) const; + + // Multiply a 4x4 matrix by a scalar + // + VECTORMATH_FORCE_INLINE const Matrix4 operator *( float scalar ) const; + + // Multiply a 4x4 matrix by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Matrix4 operator *( const floatInVec &scalar ) const; + + // Multiply a 4x4 matrix by a 4-D vector + // + VECTORMATH_FORCE_INLINE const Vector4 operator *( const Vector4 &vec ) const; + + // Multiply a 4x4 matrix by a 3-D vector + // + VECTORMATH_FORCE_INLINE const Vector4 operator *( const Vector3 &vec ) const; + + // Multiply a 4x4 matrix by a 3-D point + // + VECTORMATH_FORCE_INLINE const Vector4 operator *( const Point3 &pnt ) const; + + // Multiply two 4x4 matrices + // + VECTORMATH_FORCE_INLINE const Matrix4 operator *( const Matrix4 & mat ) const; + + // Multiply a 4x4 matrix by a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Matrix4 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and addition with a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & operator +=( const Matrix4 & mat ); + + // Perform compound assignment and subtraction by a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & operator -=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + VECTORMATH_FORCE_INLINE Matrix4 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Matrix4 & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and multiplication by a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & operator *=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 4x4 matrix + // + static VECTORMATH_FORCE_INLINE const Matrix4 identity( ); + + // Construct a 4x4 matrix to rotate around the x axis + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationX( float radians ); + + // Construct a 4x4 matrix to rotate around the y axis + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationY( float radians ); + + // Construct a 4x4 matrix to rotate around the z axis + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationZ( float radians ); + + // Construct a 4x4 matrix to rotate around the x axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationX( const floatInVec &radians ); + + // Construct a 4x4 matrix to rotate around the y axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationY( const floatInVec &radians ); + + // Construct a 4x4 matrix to rotate around the z axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationZ( const floatInVec &radians ); + + // Construct a 4x4 matrix to rotate around the x, y, and z axes + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationZYX( const Vector3 &radiansXYZ ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotation( float radians, const Vector3 &unitVec ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotation( const floatInVec &radians, const Vector3 &unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotation( const Quat &unitQuat ); + + // Construct a 4x4 matrix to perform scaling + // + static VECTORMATH_FORCE_INLINE const Matrix4 scale( const Vector3 &scaleVec ); + + // Construct a 4x4 matrix to perform translation + // + static VECTORMATH_FORCE_INLINE const Matrix4 translation( const Vector3 &translateVec ); + + // Construct viewing matrix based on eye, position looked at, and up direction + // + static VECTORMATH_FORCE_INLINE const Matrix4 lookAt( const Point3 &eyePos, const Point3 &lookAtPos, const Vector3 &upVec ); + + // Construct a perspective projection matrix + // + static VECTORMATH_FORCE_INLINE const Matrix4 perspective( float fovyRadians, float aspect, float zNear, float zFar ); + + // Construct a perspective projection matrix based on frustum + // + static VECTORMATH_FORCE_INLINE const Matrix4 frustum( float left, float right, float bottom, float top, float zNear, float zFar ); + + // Construct an orthographic projection matrix + // + static VECTORMATH_FORCE_INLINE const Matrix4 orthographic( float left, float right, float bottom, float top, float zNear, float zFar ); + +}; +// Multiply a 4x4 matrix by a scalar +// +VECTORMATH_FORCE_INLINE const Matrix4 operator *( float scalar, const Matrix4 & mat ); + +// Multiply a 4x4 matrix by a scalar (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Matrix4 operator *( const floatInVec &scalar, const Matrix4 & mat ); + +// Append (post-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Matrix4 appendScale( const Matrix4 & mat, const Vector3 &scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Matrix4 prependScale( const Vector3 &scaleVec, const Matrix4 & mat ); + +// Multiply two 4x4 matrices per element +// +VECTORMATH_FORCE_INLINE const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); + +// Compute the absolute value of a 4x4 matrix per element +// +VECTORMATH_FORCE_INLINE const Matrix4 absPerElem( const Matrix4 & mat ); + +// Transpose of a 4x4 matrix +// +VECTORMATH_FORCE_INLINE const Matrix4 transpose( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +VECTORMATH_FORCE_INLINE const Matrix4 inverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. +// +VECTORMATH_FORCE_INLINE const Matrix4 affineInverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. +// +VECTORMATH_FORCE_INLINE const Matrix4 orthoInverse( const Matrix4 & mat ); + +// Determinant of a 4x4 matrix +// +VECTORMATH_FORCE_INLINE const floatInVec determinant( const Matrix4 & mat ); + +// Conditionally select between two 4x4 matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ); + +// Conditionally select between two 4x4 matrices (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, const boolInVec &select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4x4 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Matrix4 & mat ); + +// Print a 4x4 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Matrix4 & mat, const char * name ); + +#endif + +// A 3x4 transformation matrix in array-of-structures format +// +class Transform3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + Vector3 mCol3; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Transform3( ) { }; + + // Copy a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3( const Transform3 & tfrm ); + + // Construct a 3x4 transformation matrix containing the specified columns + // + VECTORMATH_FORCE_INLINE Transform3( const Vector3 &col0, const Vector3 &col1, const Vector3 &col2, const Vector3 &col3 ); + + // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + // + VECTORMATH_FORCE_INLINE Transform3( const Matrix3 & tfrm, const Vector3 &translateVec ); + + // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + // + VECTORMATH_FORCE_INLINE Transform3( const Quat &unitQuat, const Vector3 &translateVec ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Transform3( float scalar ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Transform3( const floatInVec &scalar ); + + // Assign one 3x4 transformation matrix to another + // + VECTORMATH_FORCE_INLINE Transform3 & operator =( const Transform3 & tfrm ); + + // Set the upper-left 3x3 submatrix + // + VECTORMATH_FORCE_INLINE Transform3 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Matrix3 getUpper3x3( ) const; + + // Set translation component + // + VECTORMATH_FORCE_INLINE Transform3 & setTranslation( const Vector3 &translateVec ); + + // Get the translation component of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getTranslation( ) const; + + // Set column 0 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3 & setCol0( const Vector3 &col0 ); + + // Set column 1 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3 & setCol1( const Vector3 &col1 ); + + // Set column 2 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3 & setCol2( const Vector3 &col2 ); + + // Set column 3 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3 & setCol3( const Vector3 &col3 ); + + // Get column 0 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol0( ) const; + + // Get column 1 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol1( ) const; + + // Get column 2 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol2( ) const; + + // Get column 3 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol3( ) const; + + // Set the column of a 3x4 transformation matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Transform3 & setCol( int col, const Vector3 &vec ); + + // Set the row of a 3x4 transformation matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Transform3 & setRow( int row, const Vector4 &vec ); + + // Get the column of a 3x4 transformation matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector3 getCol( int col ) const; + + // Get the row of a 3x4 transformation matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + VECTORMATH_FORCE_INLINE Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + VECTORMATH_FORCE_INLINE const Vector3 operator []( int col ) const; + + // Set the element of a 3x4 transformation matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE Transform3 & setElem( int col, int row, float val ); + + // Set the element of a 3x4 transformation matrix referred to by column and row indices (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Transform3 & setElem( int col, int row, const floatInVec &val ); + + // Get the element of a 3x4 transformation matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int col, int row ) const; + + // Multiply a 3x4 transformation matrix by a 3-D vector + // + VECTORMATH_FORCE_INLINE const Vector3 operator *( const Vector3 &vec ) const; + + // Multiply a 3x4 transformation matrix by a 3-D point + // + VECTORMATH_FORCE_INLINE const Point3 operator *( const Point3 &pnt ) const; + + // Multiply two 3x4 transformation matrices + // + VECTORMATH_FORCE_INLINE const Transform3 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 3x4 transformation matrix + // + static VECTORMATH_FORCE_INLINE const Transform3 identity( ); + + // Construct a 3x4 transformation matrix to rotate around the x axis + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationX( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationY( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationZ( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the x axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationX( const floatInVec &radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationY( const floatInVec &radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationZ( const floatInVec &radians ); + + // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationZYX( const Vector3 &radiansXYZ ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + // + static VECTORMATH_FORCE_INLINE const Transform3 rotation( float radians, const Vector3 &unitVec ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Transform3 rotation( const floatInVec &radians, const Vector3 &unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static VECTORMATH_FORCE_INLINE const Transform3 rotation( const Quat &unitQuat ); + + // Construct a 3x4 transformation matrix to perform scaling + // + static VECTORMATH_FORCE_INLINE const Transform3 scale( const Vector3 &scaleVec ); + + // Construct a 3x4 transformation matrix to perform translation + // + static VECTORMATH_FORCE_INLINE const Transform3 translation( const Vector3 &translateVec ); + +}; +// Append (post-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Transform3 appendScale( const Transform3 & tfrm, const Vector3 &scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Transform3 prependScale( const Vector3 &scaleVec, const Transform3 & tfrm ); + +// Multiply two 3x4 transformation matrices per element +// +VECTORMATH_FORCE_INLINE const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); + +// Compute the absolute value of a 3x4 transformation matrix per element +// +VECTORMATH_FORCE_INLINE const Transform3 absPerElem( const Transform3 & tfrm ); + +// Inverse of a 3x4 transformation matrix +// NOTE: +// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. +// +VECTORMATH_FORCE_INLINE const Transform3 inverse( const Transform3 & tfrm ); + +// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. +// +VECTORMATH_FORCE_INLINE const Transform3 orthoInverse( const Transform3 & tfrm ); + +// Conditionally select between two 3x4 transformation matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ); + +// Conditionally select between two 3x4 transformation matrices (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, const boolInVec &select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x4 transformation matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Transform3 & tfrm ); + +// Print a 3x4 transformation matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Transform3 & tfrm, const char * name ); + +#endif + +} // namespace Aos +} // namespace Vectormath + +#include "vec_aos.h" +#include "quat_aos.h" +#include "mat_aos.h" + +#endif diff --git a/src/vectormath/vmInclude.h b/src/vectormath/vmInclude.h new file mode 100644 index 0000000..63a8499 --- /dev/null +++ b/src/vectormath/vmInclude.h @@ -0,0 +1,27 @@ + +#ifndef __VM_INCLUDE_H +#define __VM_INCLUDE_H + +#include "LinearMath/btScalar.h" + +#if defined (USE_SYSTEM_VECTORMATH) || defined (__CELLOS_LV2__) + #include +#else //(USE_SYSTEM_VECTORMATH) + #if defined (BT_USE_SSE) && defined (_WIN32) + #include "sse/vectormath_aos.h" + #else //all other platforms + #include "scalar/vectormath_aos.h" + #endif //(BT_USE_SSE) && defined (_WIN32) +#endif //(USE_SYSTEM_VECTORMATH) + + + +typedef Vectormath::Aos::Vector3 vmVector3; +typedef Vectormath::Aos::Quat vmQuat; +typedef Vectormath::Aos::Matrix3 vmMatrix3; +typedef Vectormath::Aos::Transform3 vmTransform3; +typedef Vectormath::Aos::Point3 vmPoint3; + +#endif //__VM_INCLUDE_H + + diff --git a/test1.oec b/test1.oec new file mode 100644 index 0000000..7fac1d1 --- /dev/null +++ b/test1.oec @@ -0,0 +1,227 @@ +# OctaveEngine Casual (Jul 14 2008) +version 2 +p 22000 1 ff 7fff66ff 13 79 0 0 13 79 0 0 0 +p 22000 1 ff 7fff66ff 12.25 77.5 0 0 12.25 77.5 0 0 0 +p 22000 1 ff 7fff66ff 12.25 78.25 0 0 12.25 78.25 0 0 0 +p 22000 1 ff 7fff66ff 13 77.5 0 0 13 77.5 0 0 0 +p 22000 1 ff 7fff66ff 13 78.25 0 0 13 78.25 0 0 0 +p 22000 1 ff 7fff66ff 13.75 77.5 0 0 13.75 77.5 0 0 0 +p 22000 1 ff 7fff66ff 13.75 78.25 0 0 13.75 78.25 0 0 0 +p 22000 2 ff 7fff66ff 14.75 73.625 0 0 14.75 73.625 0 0 0 +p 22000 2 ff 7fff66ff 15.5 73.625 0 0 15.5 73.625 0 0 0 +p 22000 2 ff 7fff66ff 16.25 73.625 0 0 16.25 73.625 0 0 0 +p 22000 2 ff 7fff66ff 17 73.625 0 0 17 73.625 0 0 0 +p 22000 2 ff 7fff66ff 17.75 73.625 0 0 17.75 73.625 0 0 0 +p 22000 2 ff 7fff66ff 18.5 73.625 0 0 18.5 73.625 0 0 0 +p 22000 3 ff 7fff66ff 26 79 0 0 26 79 0 0 0 +p 22000 3 ff 7fff66ff 26.2372 78.2885 0 0 26.2372 78.2885 0 0 0 +p 22000 3 ff 7fff66ff 26.9705 78.1313 0 0 26.9705 78.1313 0 0 0 +p 22000 3 ff 7fff66ff 27.2344 78.8334 0 0 27.2344 78.8334 0 0 0 +p 22000 3 ff 7fff66ff 27.0215 79.5525 0 0 27.0215 79.5525 0 0 0 +p 22000 3 ff 7fff66ff 26.5164 80.107 0 0 26.5164 80.107 0 0 0 +p 22000 4 ff 7fff66ff 42 73.875 0 0 42 73.875 0 0 0 +p 22000 4 ff 7fff66ff 42.5857 73.4065 0 0 42.5857 73.4065 0 0 0 +p 22000 4 ff 7fff66ff 41.8884 73.1303 0 0 41.8884 73.1303 0 0 0 +p 22000 4 ff 7fff66ff 41.3003 72.6648 0 0 41.3003 72.6648 0 0 0 +p 22000 4 ff 7fff66ff 40.6805 73.0872 0 0 40.6805 73.0872 0 0 0 +p 22000 5 ff 7fff66ff 57.125 74 0 0 57.125 74 0 0 0 +p 22000 5 ff 7fff66ff 57.7958 73.6646 0 0 57.7958 73.6646 0 0 0 +p 22000 5 ff 7fff66ff 58.1111 74.3451 0 0 58.1111 74.3451 0 0 0 +p 22000 5 ff 7fff66ff 57.5445 74.8364 0 0 57.5445 74.8364 0 0 0 +p 822000 12 ff 99cc7fff 41.875 70 0 0 41.875 70 0 0 0 +p 822000 12 ff 99cc7fff 41.125 70 0 0 41.125 70 0 0 0 +p 822000 12 ff 99cc7fff 40.3852 70.1233 0 0 40.3852 70.1233 0 0 0 +p 822000 12 ff 99cc7fff 39.6352 70.125 0 0 39.6352 70.125 0 0 0 +p 822000 12 ff 99cc7fff 38.8926 70.2299 0 0 38.8926 70.2299 0 0 0 +p 822000 12 ff 99cc7fff 38.1428 70.2495 0 0 38.1428 70.2495 0 0 0 +p 822000 12 ff 99cc7fff 37.3928 70.25 0 0 37.3928 70.25 0 0 0 +p 22000 15 ff 7fff66ff 62.25 57.625 0 0 62.25 57.625 0 0 0 +p 22000 15 ff 7fff66ff 62.9615 57.3878 0 0 62.9615 57.3878 0 0 0 +p 22000 15 ff 7fff66ff 62.8866 58.1341 0 0 62.8866 58.1341 0 0 0 +p 22000 15 ff 7fff66ff 62.2927 58.5921 0 0 62.2927 58.5921 0 0 0 +p 22000 14 ff 7fff66ff 46.875 59 0 0 46.875 59 0 0 0 +p 22000 14 ff 7fff66ff 47.3435 58.4143 0 0 47.3435 58.4143 0 0 0 +p 22000 14 ff 7fff66ff 48.0775 58.26 0 0 48.0775 58.26 0 0 0 +p 22000 14 ff 7fff66ff 48.4494 58.9113 0 0 48.4494 58.9113 0 0 0 +p 22000 14 ff 7fff66ff 48.2759 59.641 0 0 48.2759 59.641 0 0 0 +p 22000 17 ff 7fff66ff 32.625 58.625 0 0 32.625 58.625 0 0 0 +p 22000 17 ff 7fff66ff 33.2958 58.2896 0 0 33.2958 58.2896 0 0 0 +p 22000 17 ff 7fff66ff 34.045 58.2538 0 0 34.045 58.2538 0 0 0 +p 22000 17 ff 7fff66ff 34.3483 58.9397 0 0 34.3483 58.9397 0 0 0 +p 22000 16 ff 7fff66ff 23 50 0 0 23 50 0 0 0 +p 22000 16 ff 7fff66ff 23.6512 49.6279 0 0 23.6512 49.6279 0 0 0 +p 22000 16 ff 7fff66ff 24.3928 49.5162 0 0 24.3928 49.5162 0 0 0 +p 22000 16 ff 7fff66ff 24.1695 50.2321 0 0 24.1695 50.2321 0 0 0 +p 22000 18 ff 7fff66ff 18.375 59.25 0 0 18.375 59.25 0 0 0 +p 22000 18 ff 7fff66ff 18.9053 58.7197 0 0 18.9053 58.7197 0 0 0 +p 22000 18 ff 7fff66ff 19.4651 59.2189 0 0 19.4651 59.2189 0 0 0 +p 22000 18 ff 7fff66ff 19.3792 59.9639 0 0 19.3792 59.9639 0 0 0 +p 22000 7 ff 7fff66ff 44.125 51.75 0 0 44.125 51.75 0 0 0 +p 22000 7 ff 7fff66ff 44.0017 51.0102 0 0 44.0017 51.0102 0 0 0 +p 22000 7 ff 7fff66ff 44.743 51.1239 0 0 44.743 51.1239 0 0 0 +p 22000 7 ff 7fff66ff 45.0428 51.8114 0 0 45.0428 51.8114 0 0 0 +p 22000 8 ff 7fff66ff 59.125 49.375 0 0 59.125 49.375 0 0 0 +p 22000 8 ff 7fff66ff 59.125 48.625 0 0 59.125 48.625 0 0 0 +p 22000 8 ff 7fff66ff 59.7958 48.2896 0 0 59.7958 48.2896 0 0 0 +p 22000 8 ff 7fff66ff 59.9739 49.0181 0 0 59.9739 49.0181 0 0 0 +p 22000 9 ff 7fff66ff 42.5 41.625 0 0 42.5 41.625 0 0 0 +p 22000 9 ff 7fff66ff 43.0303 41.0947 0 0 43.0303 41.0947 0 0 0 +p 22000 9 ff 7fff66ff 43.7798 41.1216 0 0 43.7798 41.1216 0 0 0 +p 22000 9 ff 7fff66ff 44.3525 41.6059 0 0 44.3525 41.6059 0 0 0 +p 22000 9 ff 7fff66ff 43.9569 42.2431 0 0 43.9569 42.2431 0 0 0 +p 22000 a ff 7fff66ff 70.375 63.125 0 0 70.375 63.125 0 0 0 +p 22000 a ff 7fff66ff 70.375 62.375 0 0 70.375 62.375 0 0 0 +p 22000 a ff 7fff66ff 71.1148 62.4983 0 0 71.1148 62.4983 0 0 0 +p 22000 a ff 7fff66ff 71.2476 63.2365 0 0 71.2476 63.2365 0 0 0 +p 22000 b ff 7fff66ff 15.5 40.375 0 0 15.5 40.375 0 0 0 +p 22000 b ff 7fff66ff 16.124 39.959 0 0 16.124 39.959 0 0 0 +p 22000 b ff 7fff66ff 16.8729 39.9999 0 0 16.8729 39.9999 0 0 0 +p 22000 b ff 7fff66ff 17.2098 40.67 0 0 17.2098 40.67 0 0 0 +p 22000 c ff 7fff66ff 29.375 37.875 0 0 29.375 37.875 0 0 0 +p 22000 c ff 7fff66ff 29.791 37.251 0 0 29.791 37.251 0 0 0 +p 22000 c ff 7fff66ff 30.5326 37.139 0 0 30.5326 37.139 0 0 0 +p 22000 c ff 7fff66ff 30.6126 37.8847 0 0 30.6126 37.8847 0 0 0 +p 22000 d ff 7fff66ff 69.75 49 0 0 69.75 49 0 0 0 +p 22000 d ff 7fff66ff 69.8733 48.2602 0 0 69.8733 48.2602 0 0 0 +p 22000 d ff 7fff66ff 69.875 47.5102 0 0 69.875 47.5102 0 0 0 +p 22000 d ff 7fff66ff 69.875 46.7602 0 0 69.875 46.7602 0 0 0 +p 22000 d ff 7fff66ff 69.875 46.0102 0 0 69.875 46.0102 0 0 0 +p 22000 e ff 7fff66ff 61.625 38 0 0 61.625 38 0 0 0 +p 22000 e ff 7fff66ff 61.625 37.25 0 0 61.625 37.25 0 0 0 +p 22000 e ff 7fff66ff 61.625 36.5 0 0 61.625 36.5 0 0 0 +p 22000 e ff 7fff66ff 61.625 35.75 0 0 61.625 35.75 0 0 0 +p 22000 e ff 7fff66ff 61.625 35 0 0 61.625 35 0 0 0 +p 22000 11 ff 7fff66ff 7.25 54 0 0 7.25 54 0 0 0 +p 22000 11 ff 7fff66ff 7.25 53.25 0 0 7.25 53.25 0 0 0 +p 22000 11 ff 7fff66ff 7.25 52.5 0 0 7.25 52.5 0 0 0 +p 22000 11 ff 7fff66ff 7.25 51.75 0 0 7.25 51.75 0 0 0 +p 402000 0 ff b26666ff 55.75 70.75 0 0 55.75 70.75 0 0 0 +p 402000 0 ff b26666ff 55.75 70 0 0 55.75 70 0 0 0 +p 402000 0 ff b26666ff 56.5 70 0 0 56.5 70 0 0 0 +p 402000 0 ff b26666ff 56.5 70.75 0 0 56.5 70.75 0 0 0 +p 402000 0 ff b26666ff 57.25 70.75 0 0 57.25 70.75 0 0 0 +p 402000 0 ff b26666ff 57.25 70 0 0 57.25 70 0 0 0 +p 402000 0 ff b26666ff 58 70 0 0 58 70 0 0 0 +p 402000 0 ff b26666ff 58 70.75 0 0 58 70.75 0 0 0 +p 402000 0 ff b26666ff 58.75 70 0 0 58.75 70 0 0 0 +p 402000 0 ff b26666ff 58.75 70.75 0 0 58.75 70.75 0 0 0 +p 402000 0 ff b26666ff 59.5 70.75 0 0 59.5 70.75 0 0 0 +p 402000 0 ff b26666ff 59.5 70 0 0 59.5 70 0 0 0 +p 402000 0 ff b26666ff 60.25 70 0 0 60.25 70 0 0 0 +p 402000 0 ff b26666ff 60.25 70.75 0 0 60.25 70.75 0 0 0 +p 402000 0 ff b26666ff 61 70 0 0 61 70 0 0 0 +p 402000 0 ff b26666ff 61 70.75 0 0 61 70.75 0 0 0 +p 402000 0 ff b26666ff 43 35.5 0 0 43 35.5 0 0 0 +p 402000 0 ff b26666ff 43 34 0 0 43 34 0 0 0 +p 402000 0 ff b26666ff 43 34.75 0 0 43 34.75 0 0 0 +p 402000 0 ff b26666ff 43.75 35.5 0 0 43.75 35.5 0 0 0 +p 402000 0 ff b26666ff 43.75 34 0 0 43.75 34 0 0 0 +p 402000 0 ff b26666ff 43.75 34.75 0 0 43.75 34.75 0 0 0 +p 402000 0 ff b26666ff 44.5 34.75 0 0 44.5 34.75 0 0 0 +p 402000 0 ff b26666ff 44.5 34 0 0 44.5 34 0 0 0 +p 402000 0 ff b26666ff 45.25 34 0 0 45.25 34 0 0 0 +p 402000 0 ff b26666ff 45.25 34.75 0 0 45.25 34.75 0 0 0 +p 402000 0 ff b26666ff 46 34 0 0 46 34 0 0 0 +p 402000 0 ff b26666ff 46 34.75 0 0 46 34.75 0 0 0 +@ time 7.52012 +@ timeStep 1504 +@ scale 8 +@ timeStepsPerFrame 8 +@ framesPerSecond 25 +@ pauseFlag 1 +@ randSeed 0 +@ gravityFlag 1 +@ gravityAcceleration 0.001 +@ gravityAmplification 1 +@ gravityAngle 0 +@ boundsFlag 1 +@ boundsThickness 0.25 +@ boundsLeft 0 +@ boundsRight 94.75 +@ boundsBottom 0 +@ boundsTop 89.25 +@ boundsRadius 1 +@ standardDistance 0.75 +@ standardDensity 1.0025 +@ maxSpeed 0.5 +@ pressureCoefficient 0.05 +@ repulsionCoefficient 0.05 +@ dampingFlag 1 +@ dampingCoefficient 0.05 +@ staticPressureFlag 0 +@ staticPressureCoefficient 0.5 +@ staticPressureIteration 1 +@ staticMaxPressure 0.5 +@ springCoefficient 0.05 +@ springIteration 5 +@ elasticCoefficient 0.5 +@ elasticIteration 5 +@ mochiElasticityCoefficient 0.1 +@ mochiSpringCoefficient 0.1 +@ mochiIteration 3 +@ viscosityCoefficient 0.4 +@ viscosityIteration 5 +@ surfaceTensionCoefficient 0.1 +@ surfacePressureCoefficient 0.05 +@ surfaceTensionIteration 5 +@ powderSpringCoefficient 0.5 +@ powderDampingCoefficient 0.3 +@ powderFrictionCoefficient 0.05 +@ powderLightProbability 0.5 +@ powderExtinguishProbability 0.05 +@ powderExplosionCoefficient 1 +@ brittlenessCoefficient 0.5 +@ jetCoefficient 0.5 +@ fuelLightProbability 0.01 +@ fuelExtinguishProbability 0.0005 +@ upCoefficient 10 +@ downCoefficient 10 +@ yukiSpringCoefficient 0.02 +@ yukiMeltingProbability 0.0001 +@ resistanceFlag 0 +@ resistanceCoefficient 0.02 +@ fireFlag 1 +@ fireProbability 0.005 +@ fireLife 1000 +@ fireBuoyancyCoefficient 10 +@ splashFlag 0 +@ splashProbability 0.05 +@ splashExpansion 1e-005 +@ splashMinLife 50 +@ bubbleFlag 0 +@ bubbleProbability 0.05 +@ bubbleLife 10000 +@ bubbleBuoyancyCoefficient 20 +@ pouringFlag 0 +@ pouringRainFlag 0 +@ pouringLocation 10 +@ pouringThickness 2 +@ pouringVelocity 0.1 +@ pouringTimer 0 +@ pouringMaterial 113 +@ pouringLayer -1 +@ clearFlag 1 +@ clearColorRed 0.2 +@ clearColorBlue 0.2 +@ clearColorGreen 0.2 +@ clearColorAlpha 1 +@ mouseRadius 1 +@ mouseDelay 10 +@ mouseForce 1 +@ lineWidth 1 +@ usersCharge 0 +@ usersMaxCharge 15 +@ usersSpeedX 0.05 +@ usersSpeedY 0.15 +@ usersForceX 0.05 +@ usersForceY 0.5 +@ usersX 0 +@ usersY 0 +@ viewWidth 0 +@ viewHeight 0 +@ scrollFlag 0 +@ scrollX 0 +@ scrollY 0 +@ scrollAngle 0 +@ colorFlag 1 +@ renderMode 2 -- 2.7.4

    +9Db?8JaB_ye$I4iz?xbUE{A$ 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 OYE=hXTT9XO#{UPJClP1> literal 0 HcmV?d00001 diff --git a/Extras/khx2dae/SimpleLoadDemo.patch b/Extras/khx2dae/SimpleLoadDemo.patch new file mode 100644 index 0000000..1969348 --- /dev/null +++ b/Extras/khx2dae/SimpleLoadDemo.patch @@ -0,0 +1,428 @@ +Index: SimpleLoadDemo.cpp +=================================================================== +--- SimpleLoadDemo.cpp (revision 37) ++++ SimpleLoadDemo.cpp (working copy) +@@ -9,6 +9,9 @@ + #include + #include + ++#include "btBulletDynamicsCommon.h" ++#include "ColladaConverter.h" ++ColladaConverter* converter=0; + + // Serialize includes + #include +@@ -20,6 +23,16 @@ + #include + #include + ++#include ++#include ++#include ++ ++#include ++#include ++ ++ ++ ++ + // We can optionally version the packfile contents on load + // This requires linking with hkcompat + #define SIMPLE_LOAD_WITH_VERSIONING +@@ -59,7 +72,167 @@ + hkStructureLayout::HostLayoutRules.m_emptyBaseClassOptimization? 1 : 0); + } + ++btTransform getBulletFromHavokTransform(const hkTransform& trans) ++{ + ++ btVector3 bulletStartPos(trans.getTranslation()(0), ++ trans.getTranslation()(1), ++ trans.getTranslation()(2)); ++ ++ //todo: check matrix storage ++ btMatrix3x3 bulletMatrix( ++ trans.getRotation()(0,0), ++ trans.getRotation()(0,1), ++ trans.getRotation()(0,2), ++ trans.getRotation()(1,0), ++ trans.getRotation()(1,1), ++ trans.getRotation()(1,2), ++ trans.getRotation()(2,0), ++ trans.getRotation()(2,1), ++ trans.getRotation()(2,2)); ++ ++ btTransform bulletTrans(bulletMatrix,bulletStartPos); ++ return bulletTrans; ++} ++ ++btCollisionShape* createBulletFromHavokShape(const hkpShape* havokShape) ++{ ++ btCollisionShape* bulletShape = 0; ++ ++ switch (havokShape->getType()) ++ { ++ case HK_SHAPE_SPHERE: ++ { ++ hkpSphereShape* havokSphere = (hkpSphereShape*)havokShape; ++ bulletShape = new btSphereShape(havokSphere->getRadius()); ++ break; ++ } ++ case HK_SHAPE_CYLINDER: ++ { ++ hkpCylinderShape* havokCylinder = (hkpCylinderShape*)havokShape; ++ hkVector4 vec = havokCylinder->getVertex(0); ++ vec.sub4(havokCylinder->getVertex(1)); ++ hkReal len = vec.length3(); ++ hkReal radius = havokCylinder->getRadius(); ++ ///todo: convert cylinder, or create new Bullet shape ++ btVector3 halfExtents(radius,len,radius); ++ bulletShape = new btCylinderShape(halfExtents); ++ break; ++ } ++ case HK_SHAPE_BOX: ++ { ++ hkpBoxShape* havokBox = (hkpBoxShape*)havokShape; ++ bulletShape = new btBoxShape(btVector3(havokBox->getHalfExtents()(0),havokBox->getHalfExtents()(1),havokBox->getHalfExtents()(2))); ++ break; ++ } ++ case HK_SHAPE_CAPSULE: ++ { ++ hkpCapsuleShape* havokCapsule = (hkpCapsuleShape*)havokShape; ++ hkVector4 vec = havokCapsule->getVertex(0); ++ vec.sub4(havokCapsule->getVertex(1)); ++ hkReal len = vec.length3(); ++ hkReal radius = havokCapsule->getRadius(); ++ ///todo: convert capsule, or create new Bullet shape ++ bulletShape = new btCapsuleShape(radius,len); ++ break; ++ } ++ case HK_SHAPE_CONVEX_TRANSFORM: ++ { ++ hkpConvexTransformShape* convexTransform = (hkpConvexTransformShape*)havokShape; ++ btTransform localTrans = getBulletFromHavokTransform(convexTransform->getTransform()); ++ btCompoundShape* bulletCompound = new btCompoundShape(); ++ bulletCompound->addChildShape(localTrans,createBulletFromHavokShape(convexTransform->getChildShape())); ++ break; ++ } ++ case HK_SHAPE_CONVEX_TRANSLATE: ++ { ++ hkpConvexTranslateShape* convexTranslate = (hkpConvexTranslateShape*)havokShape; ++ btTransform localTrans; ++ localTrans.setIdentity(); ++ localTrans.setOrigin(btVector3(convexTranslate->getTranslation()(0),convexTranslate->getTranslation()(1),convexTranslate->getTranslation()(2))); ++ btCompoundShape* bulletCompound = new btCompoundShape(); ++ bulletCompound->addChildShape(localTrans,createBulletFromHavokShape(convexTranslate->getChildShape())); ++ ++ break; ++ } ++ case HK_SHAPE_CONVEX_VERTICES: ++ { ++ hkpConvexVerticesShape* havokConvex = (hkpConvexVerticesShape*)havokShape; ++ hkArray vertices; ++ havokConvex->getOriginalVertices(vertices); ++ bulletShape = new btConvexHullShape(&vertices[0](0),vertices.getSize(),sizeof(hkVector4)); ++ break; ++ }; ++ case HK_SHAPE_MOPP: ++ { ++ hkpMoppBvTreeShape* moppShape = (hkpMoppBvTreeShape*)havokShape; ++ switch (moppShape->getShapeCollection()->getType()) ++ { ++ case HK_SHAPE_TRIANGLE_COLLECTION: ++ { ++ int numChildren = moppShape->getShapeCollection()->getNumChildShapes(); ++ printf("found HK_SHAPE_TRIANGLE_COLLECTION with numChildren=%d\n",numChildren); ++ ++ if (numChildren) ++ { ++ ++ btTriangleMesh* meshInterface = new btTriangleMesh(); ++ ++ hkpShapeKey key = moppShape->getShapeCollection()->getFirstKey(); ++ for (int i=0;igetShapeCollection()->getChildShape(key,buffer); ++ btVector3 vtx0(child->getVertex(0)(0),child->getVertex(0)(1),child->getVertex(0)(2)); ++ btVector3 vtx1(child->getVertex(1)(0),child->getVertex(1)(1),child->getVertex(1)(2)); ++ btVector3 vtx2(child->getVertex(2)(0),child->getVertex(2)(1),child->getVertex(2)(2)); ++ ++ meshInterface->addTriangle(vtx0,vtx1,vtx2); ++ ++ key = moppShape->getShapeCollection()->getNextKey(key); ++ } ++ bulletShape = new btBvhTriangleMeshShape(meshInterface,true); ++ } ++ break; ++ } ++ default: ++ { ++ printf("Unrecognized MOPP getShapeCollection\n"); ++ } ++ ++ } ++ break; ++ } ++ ++ //HK_SHAPE_MOPP ++ //HK_SHAPE_TRIANGLE_COLLECTION ++ ++ ++ //HK_SHAPE_HEIGHT_FIELD ++ //btHeightField ++ ++ ++ //For those, create a btCompoundShape ++ //HK_SHAPE_CONVEX_TRANSFORM ++ // ++ //HK_SHAPE_LIST ++ //HK_SHAPE_MULTI_SPHERE ++ //HK_SHAPE_BV_TREE ++ ++ ++ ++ ++ default: ++ { ++ printf("unknown shape type=%d\n",havokShape->getType()); ++ } ++ }; ++ ++ return bulletShape; ++ ++ ++} ++ + SimpleLoadDemo::SimpleLoadDemo( hkDemoEnvironment* env) + : hkDefaultPhysicsDemo(env) + { +@@ -74,7 +247,9 @@ + setupDefaultCameras( env, from, to, up ); + } + +- hkString path("Common/Api/Serialize/SimpleLoad"); ++ //hkString path("Common/Api/Serialize/SimpleLoad"); ++ hkString path("."); ++ + hkPackfileReader* reader = HK_NULL; + { + hkString fileName; +@@ -83,7 +258,8 @@ + { + case hkPackfileReader::FORMAT_BINARY: + { +- SimpleLoadDemo_getBinaryFileName(fileName); ++ //SimpleLoadDemo_getBinaryFileName(fileName); ++ fileName = "inputfile.hkx"; + reader = new hkBinaryPackfileReader(); + break; + } +@@ -141,17 +317,206 @@ + + // Create a world and add the physics systems to it + m_world = new hkpWorld( *m_physicsData->getWorldCinfo() ); ++ ++ int MAX_PROXIES = 16384; ++ btVector3 bulletGravity (m_physicsData->getWorldCinfo()->m_gravity(0),m_physicsData->getWorldCinfo()->m_gravity(1),m_physicsData->getWorldCinfo()->m_gravity(2)); ++ ++ btVector3 worldAabbMin( ++ m_physicsData->getWorldCinfo()->m_broadPhaseWorldAabb.m_min(0), ++ m_physicsData->getWorldCinfo()->m_broadPhaseWorldAabb.m_min(1), ++ m_physicsData->getWorldCinfo()->m_broadPhaseWorldAabb.m_min(2)); ++ btVector3 worldAabbMax( ++ m_physicsData->getWorldCinfo()->m_broadPhaseWorldAabb.m_max(0), ++ m_physicsData->getWorldCinfo()->m_broadPhaseWorldAabb.m_max(1), ++ m_physicsData->getWorldCinfo()->m_broadPhaseWorldAabb.m_max(2)); ++ ++ int bulletNumSolverIterations = m_physicsData->getWorldCinfo()->m_solverIterations; ++ ++ btBroadphaseInterface* bulletPairCache = new btAxisSweep3(worldAabbMin,worldAabbMax,MAX_PROXIES); ++ btConstraintSolver* bulletSolver = new btSequentialImpulseConstraintSolver(); ++ btDefaultCollisionConfiguration* bulletCollisionConfiguration = new btDefaultCollisionConfiguration(); ++ btCollisionDispatcher* bulletDispatcher = new btCollisionDispatcher(bulletCollisionConfiguration); ++ btDiscreteDynamicsWorld* bulletWorld = new btDiscreteDynamicsWorld(bulletDispatcher,bulletPairCache,bulletSolver,bulletCollisionConfiguration); ++ //bulletNumSolverIterations is not exported, but just to show how to use the Bullet API ++ bulletWorld->getSolverInfo().m_numIterations = bulletNumSolverIterations; ++ ++ + m_world->lock(); + + // Register all collision agents + hkpAgentRegisterUtil::registerAllAgents( m_world->getCollisionDispatcher() ); + ++ printf("Number of Physics Systems:%d\n",m_physicsData->getPhysicsSystems().getSize()); ++ ++ converter = new ColladaConverter(bulletWorld); ++ + // Add all the physics systems to the world + for ( int i = 0; i < m_physicsData->getPhysicsSystems().getSize(); ++i ) + { +- m_world->addPhysicsSystem( m_physicsData->getPhysicsSystems()[i] ); ++ hkpPhysicsSystem* physSystem = m_physicsData->getPhysicsSystems()[i]; ++ m_world->addPhysicsSystem( physSystem ); ++ int numRigidBodies = physSystem->getRigidBodies().getSize(); ++ printf("Number of Rigid Bodies:%d\n",numRigidBodies); ++ for (int r=0;rgetRigidBodies()[r]; ++ bool isDynamic = !hrb->isFixedOrKeyframed(); ++ btTransform bulletTrans = getBulletFromHavokTransform(hrb->getCollidable()->getTransform()); ++ ++ const hkpShape* havokShape = hrb->getCollidable()->getShape(); ++ btCollisionShape* bulletShape = createBulletFromHavokShape(havokShape); ++ ++ if (bulletShape) ++ { ++ btRigidBody* body = converter->createRigidBody(isDynamic,hrb->getMass(),bulletTrans,bulletShape); ++ hrb->setUserData((hkUlong)body); ++ } ++ } ++ ++ int numConstraints = physSystem->getConstraints().getSize(); ++ printf("Number of Constraints:%d\n",numConstraints); ++ ++ for (int c=0;cgetConstraints()[c]; ++ switch (constraint->getData()->getType()) ++ { ++ ++ case hkpConstraintData::CONSTRAINT_TYPE_BALLANDSOCKET: ++ { ++ printf("TODO: create ballsocket constraint\n"); ++ break; ++ } ++ case hkpConstraintData::CONSTRAINT_TYPE_HINGE: ++ { ++ printf("TODO: create hinge constraint\n"); ++ break; ++ } ++ case hkpConstraintData::CONSTRAINT_TYPE_PRISMATIC: ++ { ++ printf("TODO: create prismatic (slider) constraint\n"); ++ break; ++ } ++ case hkpConstraintData::CONSTRAINT_TYPE_GENERIC: ++ { ++ printf("TODO: create generic constraint\n"); ++ break; ++ } ++ case hkpConstraintData::CONSTRAINT_TYPE_LIMITEDHINGE: ++ { ++ hkpLimitedHingeConstraintData* limHingeData = (hkpLimitedHingeConstraintData*)constraint->getData(); ++ ++ hkpConstraintData::ConstraintInfo infoOut; ++ limHingeData->getConstraintInfo(infoOut); ++ ++ int i=0; ++ ++ btTransform localAttachmentFrameRef; ++ localAttachmentFrameRef.setIdentity(); ++ btTransform localAttachmentFrameOther; ++ localAttachmentFrameOther.setIdentity(); ++ ++ if (infoOut.m_atoms) ++ { ++ while (infoOut.m_atoms[i].getType() != hkpConstraintAtom::TYPE_INVALID) ++ { ++ switch (infoOut.m_atoms[i].getType()) ++ { ++ ++ case hkpConstraintAtom::TYPE_SET_LOCAL_TRANSFORMS: ++ { ++ localAttachmentFrameRef = getBulletFromHavokTransform(limHingeData->m_atoms.m_transforms.m_transformA); ++ localAttachmentFrameOther = getBulletFromHavokTransform(limHingeData->m_atoms.m_transforms.m_transformB); ++ ++ break; ++ } ++ case hkpConstraintAtom::TYPE_SET_LOCAL_TRANSLATIONS: ++ { ++ //??? ++ localAttachmentFrameRef = getBulletFromHavokTransform(limHingeData->m_atoms.m_transforms.m_transformA); ++ localAttachmentFrameOther = getBulletFromHavokTransform(limHingeData->m_atoms.m_transforms.m_transformB); ++ break; ++ } ++ case hkpConstraintAtom::TYPE_SET_LOCAL_ROTATIONS: ++ { ++ //??? ++ localAttachmentFrameRef = getBulletFromHavokTransform(limHingeData->m_atoms.m_transforms.m_transformA); ++ localAttachmentFrameOther = getBulletFromHavokTransform(limHingeData->m_atoms.m_transforms.m_transformB); ++ break; ++ } ++ ++ default: ++ { ++ printf("unhandled constraint atom\n"); ++ } ++ }; ++ i++; ++ } ++ ++ } ++ ++ ++ ++ bool disableCollisionsBetweenLinkedBodies = true; ++ btRigidBody* body0 = (btRigidBody*) constraint->getRigidBodyA()->getUserData(); ++ btRigidBody* body1 = (btRigidBody*) constraint->getRigidBodyB()->getUserData(); ++ //if (body0 || body1) ++ { ++ ++ ++ btVector3 linearMinLimits(0,0,0); ++ btVector3 linMaxLimits(0,0,0); ++ btVector3 angularMinLimits(1,0,0); ++ btVector3 angularMaxLimits(-1,0,0); ++ btTypedConstraint* constraint = converter->createUniversalD6Constraint(body0,body1,localAttachmentFrameRef,localAttachmentFrameOther,linearMinLimits,linMaxLimits,angularMinLimits,angularMaxLimits,disableCollisionsBetweenLinkedBodies); ++ if (constraint) ++ { ++ printf("create limited hinge constraint\n"); ++ } else ++ { ++ printf("unable to create limited hinge constraint\n"); ++ } ++ } ++ ++ break; ++ } ++ ++ //CONSTRAINT_TYPE_LIMITEDHINGE = 2, ++ //CONSTRAINT_TYPE_POINTTOPATH = 3, ++ //CONSTRAINT_TYPE_RAGDOLL = 7, ++ //CONSTRAINT_TYPE_STIFFSPRING = 8, ++ //CONSTRAINT_TYPE_WHEEL = 9, ++ //CONSTRAINT_TYPE_CONTACT = 11, ++ //CONSTRAINT_TYPE_BREAKABLE = 12, ++ //CONSTRAINT_TYPE_MALLEABLE = 13, ++ //CONSTRAINT_TYPE_POINTTOPLANE = 14, ++ //CONSTRAINT_TYPE_PULLEY = 15, ++ //CONSTRAINT_TYPE_ROTATIONAL = 16, ++ //CONSTRAINT_TYPE_HINGE_LIMITS = 18, ++ //CONSTRAINT_TYPE_RAGDOLL_LIMITS = 19, ++ //CONSTRAINT_TYPE_CUSTOM = 20, ++ // Constraint Chains ++ //BEGIN_CONSTRAINT_CHAIN_TYPES = 100, ++ //CONSTRAINT_TYPE_STIFF_SPRING_CHAIN = 100, ++ //CONSTRAINT_TYPE_BALL_SOCKET_CHAIN = 101, ++ //CONSTRAINT_TYPE_POWERED_CHAIN = 102 ++ default: ++ { ++ printf("Unrecognized constraint type=$d\n",constraint->getData()->getType()); ++ } ++ ++ }; ++ } ++ + } + ++ ++ ++ //Export the Bullet dynamics world to COLLADA .dae XML ++ ++ converter ->save("havokToCollada.dae"); ++ ++ + // Setup graphics - this creates graphics objects for all rigid bodies and phantoms in the world + setupGraphics(); + diff --git a/Extras/khx2dae/readme.txt b/Extras/khx2dae/readme.txt new file mode 100644 index 0000000..76ec94b --- /dev/null +++ b/Extras/khx2dae/readme.txt @@ -0,0 +1,6 @@ + +hkx2dae converts Havok HKX files to COLLADA Physics .dae files. So Havok tools can be used with any COLLADA Physics enabled application, such as the Bullet physics engine. +Use the patch in combination with the free Havok 5.5 version to add COLLADA Physics export to the Havok SimpleLoad serialization sample (hk550\Demo\Demos\Common\Api\Serialize\SimpleLoad). + +For precompiled binary and further information, visit: +http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=12&t=2218 diff --git a/Extras/premake4.lua b/Extras/premake4.lua new file mode 100644 index 0000000..ca5c766 --- /dev/null +++ b/Extras/premake4.lua @@ -0,0 +1,6 @@ + +include "HACD" +include "ConvexDecomposition" + +include "Serialize/BulletFileLoader" +include "Serialize/BulletWorldImporter" diff --git a/Extras/simdmathlibrary/LICENSE b/Extras/simdmathlibrary/LICENSE new file mode 100644 index 0000000..5c31653 --- /dev/null +++ b/Extras/simdmathlibrary/LICENSE @@ -0,0 +1,28 @@ + SIMD math library functions for both the PowerPC (PPU) and the SPU. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + diff --git a/Extras/simdmathlibrary/Make.defs b/Extras/simdmathlibrary/Make.defs new file mode 100644 index 0000000..87e9aee --- /dev/null +++ b/Extras/simdmathlibrary/Make.defs @@ -0,0 +1,92 @@ +# -*- Makefile -*- +# Common definition for all make files in the libsimdmath library. +# Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. +# 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 Sony Computer Entertainment Inc 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. + +# PowerPC (32 bit) +ARCH_CFLAGS_ppu = -m32 -maltivec -mabi=altivec -fPIC +ARCH_LDFLAGS_ppu = -m32 +ENABLE_STATIC_ppu = 1 +ENABLE_SHARED_ppu = 1 + +# PowerPC (64 bit) +ARCH_DIR_ppu64 = ppu +ARCH_CFLAGS_ppu64 = -m64 -maltivec -mabi=altivec -fPIC +ARCH_LDFLAGS_ppu64 = -m64 +ENABLE_STATIC_ppu64 = 1 +ENABLE_SHARED_ppu64 = 1 + +# SPU +prefix_spu = /usr/spu +CROSS_spu = spu- +ENABLE_STATIC_spu = 1 +ENABLE_SHARED_spu = 0 + +# Common +prefix = $(if $(prefix_$(ARCH)),$(prefix_$(ARCH)),/usr) +DESTDIR = + +ARCH_DIR = $(if $(ARCH_DIR_$(ARCH)),$(ARCH_DIR_$(ARCH)),$(ARCH)) + +CROSS = $(CROSS_$(ARCH)) + +AR = $(CROSS)ar +CC= $(CROSS)gcc +CXX = $(CROSS)g++ +RANLIB = $(CROSS)ranlib + +ARCH_CFLAGS = $(ARCH_CFLAGS_$(ARCH)) +ARCH_LDFLAGS = $(ARCH_LDFLAGS_$(ARCH)) + +CFLAGS = -O2 -W -Wall -std=gnu99 -I. -I$(topdir)/common $(ARCH_CFLAGS) +LDFLAGS = $(ARCH_LDFLAGS) + +ENABLE_STATIC = $(ENABLE_STATIC_$(ARCH)) +ENABLE_SHARED = $(ENABLE_SHARED_$(ARCH)) + +INSTALL = install + +TEST_CMD = + +LIB_MAJOR_VERSION = 1 +LIB_MINOR_VERSION = 0 +LIB_RELEASE = 2 +LIB_FULL_VERSION = $(LIB_MAJOR_VERSION).$(LIB_MINOR_VERSION).$(LIB_RELEASE) + +LIB_BASE = simdmath +LIB_NAME = lib$(LIB_BASE) + +STATIC_LIB = $(LIB_NAME).a +ALL_STATIC_LIBS = $(STATIC_LIB) + +SHARED_LIB = $(LIB_NAME).so +SHARED_LIB_SONAME = $(SHARED_LIB).$(LIB_MAJOR_VERSION) +SHARED_LIB_FULL = $(SHARED_LIB).$(LIB_FULL_VERSION) +ALL_SHARED_LIBS = $(SHARED_LIB) $(SHARED_LIB_FULL) $(SHARED_LIB_SONAME) + +TAR_NAME = $(LIB_BASE)-$(LIB_FULL_VERSION) +TAR_BALL = $(TAR_NAME).tar.gz diff --git a/Extras/simdmathlibrary/Make.rules b/Extras/simdmathlibrary/Make.rules new file mode 100644 index 0000000..ff58e2f --- /dev/null +++ b/Extras/simdmathlibrary/Make.rules @@ -0,0 +1,82 @@ +# -*- Makefile -*- +# Common make rules for all make files in the libsimdmath library. +# Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. +# 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 Sony Computer Entertainment Inc 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. + +ifeq ($(ENABLE_STATIC),1) + ALL_LIBS += $(ALL_STATIC_LIBS) + INSTALL_LIBS += install-static +endif + +ifeq ($(ENABLE_SHARED),1) + ALL_LIBS += $(ALL_SHARED_LIBS) + INSTALL_LIBS += install-shared +endif + +all: $(ALL_LIBS) + +static: $(STATIC_LIB) + +shared: $(SHARED_LIB) + +$(STATIC_LIB): $(OBJS) + $(AR) cr $@ $(OBJS) + $(RANLIB) $@ + +$(SHARED_LIB_FULL): $(OBJS) + $(CC) -shared $(OBJS) -o $@ $(LDFLAGS) -Wl,-h,$(SHARED_LIB_SONAME) + +$(SHARED_LIB) $(SHARED_LIB_SONAME): $(SHARED_LIB_FULL) + ln -fs $(SHARED_LIB_FULL) $@ + +install: install-headers $(INSTALL_LIBS) + +install-headers: + $(INSTALL) -m 755 -d $(DESTDIR)$(prefix)/include + $(INSTALL) -m 755 -d $(DESTDIR)$(prefix)/include/simdmath + $(INSTALL) -m 644 simdmath/*.h $(DESTDIR)$(prefix)/include/simdmath/ + +install-static: $(ALL_STATIC_LIBS) + $(INSTALL) -m 755 -d $(DESTDIR)$(prefix)/lib + $(INSTALL) -m 644 $(STATIC_LIB) $(DESTDIR)$(prefix)/lib/$(STATIC_LIB) + +install-shared: $(ALL_SHARED_LIBS) + $(INSTALL) -m 755 $(SHARED_LIB_FULL) $(DESTDIR)$(prefix)/lib/$(SHARED_LIB_FULL) + ln -fs $(SHARED_LIB_FULL) $(DESTDIR)$(prefix)/lib/$(SHARED_LIB_SONAME) + ln -fs $(SHARED_LIB_SONAME) $(DESTDIR)$(prefix)/lib/$(SHARED_LIB) + +clean: + $(MAKE) -C tests clean + -rm -f $(OBJS) + -rm -f $(STATIC_LIB) $(SHARED_LIB) $(SHARED_LIB_SONAME) $(SHARED_LIB_FULL) + +check: $(ALL_LIBS) + $(MAKE) -C tests all + $(MAKE) -C tests check + +%.o: ../common/%.c simdmath/%.h + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/Extras/simdmathlibrary/Make.test b/Extras/simdmathlibrary/Make.test new file mode 100644 index 0000000..59c9772 --- /dev/null +++ b/Extras/simdmathlibrary/Make.test @@ -0,0 +1,87 @@ +# -*- Makefile -*- +# Common make rules for tests in the libsimdmath library. +# Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. +# 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 Sony Computer Entertainment Inc 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. + +STATIC_TESTS = $(TESTS) +SHARED_TESTS = $(TESTS:=.shared) + +ifeq ($(ENABLE_STATIC),1) + ALL_TESTS += $(STATIC_TESTS) +endif + +ifeq ($(ENABLE_SHARED),1) + ALL_TESTS += $(SHARED_TESTS) +endif + +STATIC_LDFLAGS = -static +SHARED_LDFLAGS = -Wl,-rpath=.. + +LDFLAGS += -L../ -l$(LIB_BASE) -lm + +all: $(ALL_TESTS) + +$(STATIC_TESTS): %: %.o ../$(STATIC_LIB) $(OBJS) + $(CC) $*.o $(OBJS) $(LDFLAGS) $(STATIC_LDFLAGS) -o $@ + +$(SHARED_TESTS): %.shared: %.o ../$(SHARED_LIB) $(OBJS) + $(CC) $*.o $(OBJS) $(LDFLAGS) $(SHARED_LDFLAGS) -o $@ + +clean: + rm -f *.o + rm -f $(STATIC_TESTS) $(SHARED_TESTS) + rm -f core* + +check: $(ALL_TESTS) + for test in $(ALL_TESTS); do \ + echo "TEST $${test}"; \ + if $(TEST_CMD) ./$${test}; then \ + pass="$$pass $$test"; \ + else \ + fail="$$fail $$test"; \ + fi \ + done; \ + echo; echo "PASS:$$pass"; echo "FAIL:$$fail"; \ + test -z "$$fail" + +static_check: + $(MAKE) ALL_TESTS="$(STATIC_TESTS)" check + +shared_check: + $(MAKE) ALL_TESTS="$(SHARED_TESTS)" check + +../$(STATIC_LIB): + $(MAKE) -C .. $(STATIC_LIB) + +../$(SHARED_LIB): + $(MAKE) -C .. $(SHARED_LIB) + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +%.o: %.cc + $(CXX) $(CFLAGS) -c -o $@ $< diff --git a/Extras/simdmathlibrary/Makefile b/Extras/simdmathlibrary/Makefile new file mode 100644 index 0000000..70e0839 --- /dev/null +++ b/Extras/simdmathlibrary/Makefile @@ -0,0 +1,53 @@ +# Toplevel make file to build the libsimdmath library for both SPU and PPU +# Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. +# 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 Sony Computer Entertainment Inc 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. + +topdir = . +ARCH = unknown + +include $(topdir)/Make.defs + +SUBDIRS = common $(ARCH_DIR) + +all install check: + @for _d in $(SUBDIRS); do $(MAKE) -C $$_d $@ || exit 1; done + +clean: + -@for _d in $(SUBDIRS); do $(MAKE) -C $$_d $@; done + -rm -rf $(TAR_BALL) .dist + +dist: + -rm -rf .dist + mkdir -p .dist/$(TAR_NAME) + find . -name .dist -prune -o -name '*~' -prune -o \ + -name .CVS -prune -o -name .svn -prune -o \ + -name .pc -prune -o -name patches -prune -o \ + '(' -name README -o -name LICENSE -o \ + -name 'Make*' -o -name '*.[ch]' -o -name '*.spec' ')' \ + -print | tar -T - -cf - | tar xf - -C .dist/$(TAR_NAME) + tar zcf $(TAR_BALL) -C .dist $(TAR_NAME) + -rm -rf .dist diff --git a/Extras/simdmathlibrary/README b/Extras/simdmathlibrary/README new file mode 100644 index 0000000..638535f --- /dev/null +++ b/Extras/simdmathlibrary/README @@ -0,0 +1,128 @@ + SIMD math library + + +* Overview + + The SIMD math library (SIMD math lib) is a SIMDized version of the + C99 standard math library (libm). + + +* License + + This library is licensed under the terms in the file 'LICENSE' in + this directory. + + +* Installing + + To install this library, run following commands: + + - 32 bit mode PowerPC with VMX + + $ make ARCH=ppu + $ make ARCH=ppu install + + - 64 bit mode PowerPC with VMX + + $ make ARCH=ppu64 + $ make ARCH=ppu64 install + + - SPU (Cell Broadband Engine Synergistic Processor Unit) + + $ make ARCH=spu + $ make ARCH=spu install + + The same library is created and installed for SPU regardless of + PPU's mode. + + + By default, files in the library will be placed as below: + + - libraries (except SPU library) + + /usr/lib/libsimdmath.a (static library) + /usr/lib/libsimdmath.so (shared library) + + - headers (except SPU headers) + + /usr/lib/simdmath.h (main header) + /usr/lib/simdmath/.h (header of inline version) + + - SPU library + + /usr/spu/lib/libsimdmath.a (static library) + (no shared library for SPU) + + - SPU headers + + /usr/spu/lib/simdmath.h (main header) + /usr/spu/lib/simdmath/.h (header of inline version) + + +* Packaging + + By running following command in this directory, a source tarball + 'simdmath-.tar.gz' can be created: + + $ make dist + + You can also create RPM packages by executing the command below with + the tarball: + + $ rpmbuild -tb simdmath-1.0.1.tar.gz --target=ppc + + Three packages, simdmath, simdmath-devel and spu-simdmath-devel, + will be created. + + +* Quick start + + - Including headers + + You must include the header simdmat.h in your source code, as + following: + + e.g.) + + #include + + If you want to use inlined version of the functions, you need to + include simdmath/.h instead of simdmath.h: + + e.g.) + + #include + + - Linking with library + + If you use non-inlined version of the library, you need to link + the library libsimdmath.a or libsimdmath.so: + + e.g.) + + $ gcc -o foo foo.o -lsimdmath + $ spu-gcc -o bar bar.o -lsimdmath + + - Function reference + + To obtain details about each function in this library, the + specification document "SIMD Math Library Specification for Cell + Broadband Engine Architecture" is avaiable at + "http://cell.scei.co.jp/". + + Note that the name of each inlined version of function is prefixed + by a character '_' against the corresponding non-inlined one. + + +* Contacting the project + + Module maintainer: Erwin Coumans + + Feedback and patches: + http://www.bulletphysics.com/Bullet/phpBB2/viewforum.php?f=18 + + Main repository URL: + http://bullet.svn.sourceforge.net/viewvc/bullet/trunk/Extras/simdmathlibrary + +--- +EOF diff --git a/Extras/simdmathlibrary/common/Makefile b/Extras/simdmathlibrary/common/Makefile new file mode 100644 index 0000000..62c9832 --- /dev/null +++ b/Extras/simdmathlibrary/common/Makefile @@ -0,0 +1,47 @@ +# make file to build the libsimdmath library for PPU and SPU +# Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. +# 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 Sony Computer Entertainment Inc 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. + +topdir = .. +ARCH = unknown + +include $(topdir)/Make.defs + +all: + @true + +install: + $(INSTALL) -m 755 -d $(DESTDIR)$(prefix)/include + $(INSTALL) -m 755 -d $(DESTDIR)$(prefix)/include/simdmath + $(INSTALL) -m 644 simdmath.h $(DESTDIR)$(prefix)/include/ + $(INSTALL) -m 644 simdmath/*.h $(DESTDIR)$(prefix)/include/simdmath/ + +check: + @true + +clean: + @true diff --git a/Extras/simdmathlibrary/common/absi4.c b/Extras/simdmathlibrary/common/absi4.c new file mode 100644 index 0000000..220103e --- /dev/null +++ b/Extras/simdmathlibrary/common/absi4.c @@ -0,0 +1,36 @@ +/* absi4 - for each of four integer slots, compute absolute value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector signed int +absi4 (vector signed int x) +{ + return _absi4( x ); +} diff --git a/Extras/simdmathlibrary/common/acosf4.c b/Extras/simdmathlibrary/common/acosf4.c new file mode 100644 index 0000000..f43eacb --- /dev/null +++ b/Extras/simdmathlibrary/common/acosf4.c @@ -0,0 +1,36 @@ +/* acosf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +acosf4 (vector float x) +{ + return _acosf4( x ); +} diff --git a/Extras/simdmathlibrary/common/asinf4.c b/Extras/simdmathlibrary/common/asinf4.c new file mode 100644 index 0000000..b713292 --- /dev/null +++ b/Extras/simdmathlibrary/common/asinf4.c @@ -0,0 +1,36 @@ +/* asinf4 - Computes the inverse sine of all four slots of x + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +asinf4 (vector float x) +{ + return _asinf4( x ); +} diff --git a/Extras/simdmathlibrary/common/atan2f4.c b/Extras/simdmathlibrary/common/atan2f4.c new file mode 100644 index 0000000..c7282f6 --- /dev/null +++ b/Extras/simdmathlibrary/common/atan2f4.c @@ -0,0 +1,36 @@ +/* atan2f4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +atan2f4 (vector float y, vector float x) +{ + return _atan2f4( y, x ); +} diff --git a/Extras/simdmathlibrary/common/atanf4.c b/Extras/simdmathlibrary/common/atanf4.c new file mode 100644 index 0000000..0fc5073 --- /dev/null +++ b/Extras/simdmathlibrary/common/atanf4.c @@ -0,0 +1,36 @@ +/* atanf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +atanf4 (vector float x) +{ + return _atanf4( x ); +} diff --git a/Extras/simdmathlibrary/common/cbrtf4.c b/Extras/simdmathlibrary/common/cbrtf4.c new file mode 100644 index 0000000..a51e8b1 --- /dev/null +++ b/Extras/simdmathlibrary/common/cbrtf4.c @@ -0,0 +1,36 @@ +/* cbrtf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +cbrtf4 (vector float x) +{ + return _cbrtf4( x ); +} diff --git a/Extras/simdmathlibrary/common/ceild2.c b/Extras/simdmathlibrary/common/ceild2.c new file mode 100644 index 0000000..be4f3ff --- /dev/null +++ b/Extras/simdmathlibrary/common/ceild2.c @@ -0,0 +1,36 @@ +/* ceild2 - for each of two doule slots, round up to smallest integer not less than the value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +ceild2(vector double in) +{ + return _ceild2(in); +} diff --git a/Extras/simdmathlibrary/common/ceilf4.c b/Extras/simdmathlibrary/common/ceilf4.c new file mode 100644 index 0000000..d5de69d --- /dev/null +++ b/Extras/simdmathlibrary/common/ceilf4.c @@ -0,0 +1,36 @@ +/* ceilf4 - for each of four float slots, round up to smallest integer not less than the value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +ceilf4 (vector float x) +{ + return _ceilf4( x ); +} diff --git a/Extras/simdmathlibrary/common/common-test.h b/Extras/simdmathlibrary/common/common-test.h new file mode 100644 index 0000000..175effa --- /dev/null +++ b/Extras/simdmathlibrary/common/common-test.h @@ -0,0 +1,228 @@ +/* Header file for common parts of the testsuite + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include + +#ifdef __SPU__ + +#include + +static inline unsigned long long clock_start(void) +{ + spu_writech(SPU_WrDec, 0); + return -spu_readch(SPU_RdDec); +} + +static inline unsigned long long clock_stop(void) +{ + return -spu_readch(SPU_RdDec); +} + +#else + +static inline unsigned long long clock(void) +{ + unsigned long long ret; + /* This need to be fixed for the hardware errata. */ + __asm __volatile__ ( "mftb %0\n" + : "=r" (ret) + : + : "memory"); + return (ret); +} + +static inline unsigned long long clock_start(void) +{ + return clock(); +} + +static inline unsigned long long clock_stop(void) +{ + return clock(); +} + +#endif + +// Test files begin with TEST_SET_START("your initials","test set description") +// Individual tests begin with TEST_START("name of test") +// and end with TEST_PASS(), TEST_FAIL("reason for failure") or TEST_CHECK() +// Or you can run a test encapsulated in a function with: +// TEST_FUNCTION("name of test", function(), "reason for failure") +// +// The clock starts when you call TEST_START and stops with TEST_PASS, TEST_FAIL or TEST_CHECK +// After a start there can be several PASS, FAIL or CHECK calls, each one counts as a test, time is measured from the prior call +// +char + *__initials, // Test owner's initials + *__description, // short descriptive name for this test set + *__name, // name of the currently running test + *__set_id; // id of the the test set +int +// __zip=0, + __success=1, // set to 0 if any tests failed + __count, // Total number of tests run + __passed; // Total number of tests passed +unsigned long long + __ttemp, + __time, // For timing tests (usually start time of last test) + __ttime; // Cumulative test runtime NOT counting runtime of the TEST macros + +// TEST_SET_START +// Call at the start of a set of related tests to identify them +// Prints a "start of set banner message" +// set_id - unique test set identifyer a time in the format yyyymmddhhmmss followed by your initials ie: 20040716104615GAC +// initials - your initials +// description - brief descriptive name for this test set +#define TEST_SET_START(set_id,initials,description) \ + do { \ + __set_id=set_id; \ + __initials=initials; \ + __description=description; \ + __count=0; \ + __passed=0; \ + __ttime=0; \ + printf("0\t%s\t%d\t%s\tSTART\tpassed\ttotal\ttime\t%s\tunique test id \t%s\n",__FILE__,__LINE__,__initials,__set_id, __description); \ + __time = clock_start(); \ + } while(0) + +// TEST_START +// Begins a test, and starts the clock +// name - brief name for this test +#define TEST_START(name) \ + do { \ + (void)clock_stop(); \ + __name=name; \ + __time = clock_start(); \ + } while(0) + +// TEST_PASS +// Indicates the test passed +// test_id - unique test ID number, same format as the set_id number +// This should match the id provided to the matching TEST_FAIL call +#define TEST_PASS(test_id) \ + do { \ + __ttemp=clock_stop(); \ + __time=__ttemp-__time; \ + __ttime+=__time; \ + __count++; \ + __passed++; \ + printf("1\t%s\t%d\t%s\tPASS\t%d\t%d\t%lld\t%s\t%s\t%s\n",__FILE__,__LINE__,__initials,__passed,__count,__time,__set_id,test_id,__name); \ + __time=clock_start(); \ + } while(0) + +// TEST_FAIL +// Indicates the test failed +// test_id - unique test ID number, same format as the set_id number +// This should match the id provided to the matching TEST_PASS call +// why - brief description of why it failed +#define TEST_FAIL(test_id,why,error_code) \ + do { \ + __ttemp=clock_stop(); \ + __time=__ttemp-__time; \ + __ttime+=__time; \ + __count++; \ + __success=0; \ + printf("1\t%s\t%d\t%s\tFAIL\t%d\t%d\t%lld\t%s\t%s\t%s\tFAILED BECAUSE: %s\t%d\n",__FILE__,__LINE__,__initials,__passed,__count,__time,__set_id,test_id,__name,why,error_code); \ + __time=clock_start(); \ + } while(0) + +// TEST_CHECK +// Passes or fails the test after evaluating the "test" argument (just like assert but without terminating the program) +// The clock is immediately stopped so the time required to evaluate "test" will NOT be included in the reported time +// If the test failed, the reason will be printed as FAILED BECAUSE: check (value of "test") failed +// test_id - unique test ID number, same format as the set_id number +// test - expression evaluating to true/false +#define TEST_CHECK(test_id,test,error_code) \ + do { \ + __ttemp=clock_stop(); \ + __time=__ttemp-__time; \ + __ttime+=__time; \ + __count++; \ + if(test) \ + { \ + __passed++; \ + printf("1\t%s\t%d\t%s\tPASS\t%d\t%d\t%lld\t%s\t%s\t%s\n",__FILE__,__LINE__,__initials,__passed,__count,__time,__set_id,test_id,__name); \ + } \ + else \ + { \ + __success=0; \ + printf("1\t%s\t%d\t%s\tFAIL\t%d\t%d\t%lld\t%s\t%s\t%s\tFAILED BECAUSE: check %s failed\t%d\n",__FILE__,__LINE__,__initials,__passed,__count,__time,__set_id,test_id,__name,#test,error_code); \ + } \ + __time=clock_start(); \ + } while(0) + +// TEST_FUNCTION +// Runs a test encapsulated in a function that returns 0 if the test passed and an error number if it failed +// The clock is started on calling the function and stopped as soon as it returns so the branching logic will not be included in the time +// test_id - unique test ID number, same format as the set_id number +// name - brief name for the test +// func - function invocation (should include parenthesis, may have arguments) +// why - brief description to print if the test fails +#define TEST_FUNCTION(test_id,name,func,why) \ + do { \ + TEST_START(name); \ + int result=func; \ + __ttemp=clock_stop(); \ + __time=__ttemp-__time; \ + __ttime+=__time; \ + __count++; \ + if(result==0) \ + { \ + __passed++; \ + printf("1\t%s\t%d\t%s\tPASS\t%d\t%d\t%d\t%s\t%s\t%s\n",__FILE__,__LINE__,__initials,__passed,__count,__time,__set_id,test_id,__name); \ + } \ + else \ + { \ + __success=0; \ + printf("1\t%s\t%d\t%s\tFAIL\t%d\t%d\t%d\t%s\t%s\t%s\tFAILED BECAUSE: %s\t%d\n",__FILE__,__LINE__,__initials,__passed,__count,__time,__set_id,test_id,__name,why,result); \ + } \ + __time=clock_start(); \ + } while(0) + +// TEST_SET_DONE +// Ends a set of tests, prints out the closing banner (OK if all tests pass, PROBLEM if any fail) +// Also prints count of tests passed, tests run and total time +#define TEST_SET_DONE() \ + do { \ + printf("9\t%s\t%d\t%s\t%s\t%d\t%d\t%lld\t%s\tunique test id \t%s\n",__FILE__,__LINE__,__initials,(__count==__passed)?"OK":"PROBLEM",__passed,__count,__ttime,__set_id,__description); \ + } while(0) + +// TEST_EXIT +// Call this ONCE at the very end of the test program, it calls "exit" to return +// EXIT_SUCCESS if all tests passed or EXIT_FAILURE if any tests failed. +// This allows the makefile/shell script running the tests to know which ones failed +#define TEST_EXIT() \ + do { \ + printf("FINISHED!\n"); \ + if(__success) \ + exit(0); \ + else \ + exit(-1); \ + } while (0) diff --git a/Extras/simdmathlibrary/common/copysignd2.c b/Extras/simdmathlibrary/common/copysignd2.c new file mode 100644 index 0000000..0321c1e --- /dev/null +++ b/Extras/simdmathlibrary/common/copysignd2.c @@ -0,0 +1,36 @@ +/* copysignd2 - for each of two double slots, return value with magnitude from x and sign from y. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +copysignd2 (vector double x, vector double y) +{ + return _copysignd2(x, y); +} diff --git a/Extras/simdmathlibrary/common/copysignf4.c b/Extras/simdmathlibrary/common/copysignf4.c new file mode 100644 index 0000000..8857531 --- /dev/null +++ b/Extras/simdmathlibrary/common/copysignf4.c @@ -0,0 +1,36 @@ +/* copysignf4 - for each of four float slots, return value with magnitude from x and sign from y. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +copysignf4 (vector float x, vector float y) +{ + return _copysignf4( x, y ); +} diff --git a/Extras/simdmathlibrary/common/cosd2.c b/Extras/simdmathlibrary/common/cosd2.c new file mode 100644 index 0000000..8e9167f --- /dev/null +++ b/Extras/simdmathlibrary/common/cosd2.c @@ -0,0 +1,36 @@ +/* cosd2 - Computes the cosine of the each of two double slots. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +cosd2 (vector double x) +{ + return _cosd2(x); +} diff --git a/Extras/simdmathlibrary/common/cosf4.c b/Extras/simdmathlibrary/common/cosf4.c new file mode 100644 index 0000000..1570c5e --- /dev/null +++ b/Extras/simdmathlibrary/common/cosf4.c @@ -0,0 +1,36 @@ +/* cosf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +cosf4 (vector float x) +{ + return _cosf4( x ); +} diff --git a/Extras/simdmathlibrary/common/divd2.c b/Extras/simdmathlibrary/common/divd2.c new file mode 100644 index 0000000..4c18c2d --- /dev/null +++ b/Extras/simdmathlibrary/common/divd2.c @@ -0,0 +1,36 @@ +/* divd2 - for each of two double slots, divide numer by denom. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +divd2 (vector double numer, vector double denom) +{ + return _divd2(numer, denom); +} diff --git a/Extras/simdmathlibrary/common/divf4.c b/Extras/simdmathlibrary/common/divf4.c new file mode 100644 index 0000000..45aa122 --- /dev/null +++ b/Extras/simdmathlibrary/common/divf4.c @@ -0,0 +1,36 @@ +/* divf4 - for each of four float slots, divide numer by denom. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +divf4 (vector float numer, vector float denom) +{ + return _divf4( numer, denom ); +} diff --git a/Extras/simdmathlibrary/common/divi4.c b/Extras/simdmathlibrary/common/divi4.c new file mode 100644 index 0000000..7d2910a --- /dev/null +++ b/Extras/simdmathlibrary/common/divi4.c @@ -0,0 +1,36 @@ +/* divi4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +divi4_t +divi4 (vector signed int numer, vector signed int denom ) +{ + return _divi4( numer, denom ); +} diff --git a/Extras/simdmathlibrary/common/divu4.c b/Extras/simdmathlibrary/common/divu4.c new file mode 100644 index 0000000..0110300 --- /dev/null +++ b/Extras/simdmathlibrary/common/divu4.c @@ -0,0 +1,36 @@ +/* divu4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +divu4_t +divu4 (vector unsigned int numer, vector unsigned int denom) +{ + return _divu4(numer, denom); +} diff --git a/Extras/simdmathlibrary/common/exp2f4.c b/Extras/simdmathlibrary/common/exp2f4.c new file mode 100644 index 0000000..8e07fb0 --- /dev/null +++ b/Extras/simdmathlibrary/common/exp2f4.c @@ -0,0 +1,36 @@ +/* exp2f4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +exp2f4 (vector float x) +{ + return _exp2f4( x ); +} diff --git a/Extras/simdmathlibrary/common/expf4.c b/Extras/simdmathlibrary/common/expf4.c new file mode 100644 index 0000000..3950d4b --- /dev/null +++ b/Extras/simdmathlibrary/common/expf4.c @@ -0,0 +1,36 @@ +/* expf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +expf4 (vector float x) +{ + return _expf4( x ); +} diff --git a/Extras/simdmathlibrary/common/expm1f4.c b/Extras/simdmathlibrary/common/expm1f4.c new file mode 100644 index 0000000..faa4290 --- /dev/null +++ b/Extras/simdmathlibrary/common/expm1f4.c @@ -0,0 +1,36 @@ +/* expm1f4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +expm1f4 (vector float x) +{ + return _expm1f4( x ); +} diff --git a/Extras/simdmathlibrary/common/fabsd2.c b/Extras/simdmathlibrary/common/fabsd2.c new file mode 100644 index 0000000..e38e333 --- /dev/null +++ b/Extras/simdmathlibrary/common/fabsd2.c @@ -0,0 +1,36 @@ +/* fabsd2 - for each of two double slots, compute absolute value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +fabsd2 (vector double x) +{ + return _fabsd2(x); +} diff --git a/Extras/simdmathlibrary/common/fabsf4.c b/Extras/simdmathlibrary/common/fabsf4.c new file mode 100644 index 0000000..2fd7d22 --- /dev/null +++ b/Extras/simdmathlibrary/common/fabsf4.c @@ -0,0 +1,37 @@ +/* fabsf4 - for each of four float slots, compute absolute value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +fabsf4 (vector float x) +{ + return _fabsf4( x ); +} + diff --git a/Extras/simdmathlibrary/common/fdimd2.c b/Extras/simdmathlibrary/common/fdimd2.c new file mode 100644 index 0000000..447f57b --- /dev/null +++ b/Extras/simdmathlibrary/common/fdimd2.c @@ -0,0 +1,36 @@ +/* fdimd2 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +fdimd2 (vector double x, vector double y) +{ + return _fdimd2(x, y); +} diff --git a/Extras/simdmathlibrary/common/fdimf4.c b/Extras/simdmathlibrary/common/fdimf4.c new file mode 100644 index 0000000..d476788 --- /dev/null +++ b/Extras/simdmathlibrary/common/fdimf4.c @@ -0,0 +1,36 @@ +/* fdimf - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +fdimf4 (vector float x, vector float y) +{ + return _fdimf4( x, y ); +} diff --git a/Extras/simdmathlibrary/common/floord2.c b/Extras/simdmathlibrary/common/floord2.c new file mode 100644 index 0000000..0dec5d5 --- /dev/null +++ b/Extras/simdmathlibrary/common/floord2.c @@ -0,0 +1,36 @@ +/* floord2 - for each of two doule slots, round up to smallest integer not more than the value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +floord2(vector double in) +{ + return _floord2(in); +} diff --git a/Extras/simdmathlibrary/common/floorf4.c b/Extras/simdmathlibrary/common/floorf4.c new file mode 100644 index 0000000..3ef6e6f --- /dev/null +++ b/Extras/simdmathlibrary/common/floorf4.c @@ -0,0 +1,36 @@ +/* floorf4 - for each of four float slots, round down to largest integer not greater than the value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +floorf4 (vector float x) +{ + return _floorf4( x ); +} diff --git a/Extras/simdmathlibrary/common/fmad2.c b/Extras/simdmathlibrary/common/fmad2.c new file mode 100644 index 0000000..b470080 --- /dev/null +++ b/Extras/simdmathlibrary/common/fmad2.c @@ -0,0 +1,36 @@ +/* fmad2 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +fmad2 (vector double x, vector double y, vector double z) +{ + return _fmad2(x, y, z); +} diff --git a/Extras/simdmathlibrary/common/fmaf4.c b/Extras/simdmathlibrary/common/fmaf4.c new file mode 100644 index 0000000..b26afbc --- /dev/null +++ b/Extras/simdmathlibrary/common/fmaf4.c @@ -0,0 +1,36 @@ +/* fmaf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +fmaf4 (vector float x, vector float y, vector float z) +{ + return _fmaf4( x, y, z ); +} diff --git a/Extras/simdmathlibrary/common/fmaxd2.c b/Extras/simdmathlibrary/common/fmaxd2.c new file mode 100644 index 0000000..1380f28 --- /dev/null +++ b/Extras/simdmathlibrary/common/fmaxd2.c @@ -0,0 +1,36 @@ +/* fmaxd2 - for each of two double slots, compute maximum of x and y + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +fmaxd2 (vector double x, vector double y) +{ + return _fmaxd2(x, y); +} diff --git a/Extras/simdmathlibrary/common/fmaxf4.c b/Extras/simdmathlibrary/common/fmaxf4.c new file mode 100644 index 0000000..ca51692 --- /dev/null +++ b/Extras/simdmathlibrary/common/fmaxf4.c @@ -0,0 +1,36 @@ +/* fmaxf4 - for each of four float slots, compute maximum of x and y + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +fmaxf4 (vector float x, vector float y) +{ + return _fmaxf4( x, y ); +} diff --git a/Extras/simdmathlibrary/common/fmind2.c b/Extras/simdmathlibrary/common/fmind2.c new file mode 100644 index 0000000..b30242f --- /dev/null +++ b/Extras/simdmathlibrary/common/fmind2.c @@ -0,0 +1,36 @@ +/* fmind2 - for each of two double slots, compute minimum of x and y + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +fmind2 (vector double x, vector double y) +{ + return _fmind2(x, y); +} diff --git a/Extras/simdmathlibrary/common/fminf4.c b/Extras/simdmathlibrary/common/fminf4.c new file mode 100644 index 0000000..6bc2db8 --- /dev/null +++ b/Extras/simdmathlibrary/common/fminf4.c @@ -0,0 +1,36 @@ +/* fminf4 - for each of four float slots, compute minimum of x and y + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +fminf4 (vector float x, vector float y) +{ + return _fminf4( x, y ); +} diff --git a/Extras/simdmathlibrary/common/fmodd2.c b/Extras/simdmathlibrary/common/fmodd2.c new file mode 100644 index 0000000..7428a9a --- /dev/null +++ b/Extras/simdmathlibrary/common/fmodd2.c @@ -0,0 +1,36 @@ +/* fmodd2 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +fmodd2(vector double x, vector double y) +{ + return _fmodd2(x, y); +} diff --git a/Extras/simdmathlibrary/common/fmodf4.c b/Extras/simdmathlibrary/common/fmodf4.c new file mode 100644 index 0000000..d5446b4 --- /dev/null +++ b/Extras/simdmathlibrary/common/fmodf4.c @@ -0,0 +1,36 @@ +/* fmodf4 - for each of four float slots, compute remainder of x/y defined as x - truncated_integer(x/y) * y. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +fmodf4 (vector float x, vector float y) +{ + return _fmodf4( x, y ); +} diff --git a/Extras/simdmathlibrary/common/fpclassifyd2.c b/Extras/simdmathlibrary/common/fpclassifyd2.c new file mode 100644 index 0000000..b0f55be --- /dev/null +++ b/Extras/simdmathlibrary/common/fpclassifyd2.c @@ -0,0 +1,36 @@ +/* fpclassifyd2 - for each element of vector x, return classification of x': FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector signed long long +fpclassifyd2 (vector double x) +{ + return _fpclassifyd2(x); +} diff --git a/Extras/simdmathlibrary/common/fpclassifyf4.c b/Extras/simdmathlibrary/common/fpclassifyf4.c new file mode 100644 index 0000000..1bc07c6 --- /dev/null +++ b/Extras/simdmathlibrary/common/fpclassifyf4.c @@ -0,0 +1,36 @@ +/* fpclassifyf4 - for each element of vector x, return classification of x': FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector signed int +fpclassifyf4 (vector float x) +{ + return _fpclassifyf4(x); +} diff --git a/Extras/simdmathlibrary/common/frexpd2.c b/Extras/simdmathlibrary/common/frexpd2.c new file mode 100644 index 0000000..c950cac --- /dev/null +++ b/Extras/simdmathlibrary/common/frexpd2.c @@ -0,0 +1,36 @@ +/* frexpd2 - for each element of vector x, return the normalized fraction and store the exponent of x' + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +frexpd2 (vector double x, vector signed long long *pexp) +{ + return _frexpd2(x, pexp); +} diff --git a/Extras/simdmathlibrary/common/frexpf4.c b/Extras/simdmathlibrary/common/frexpf4.c new file mode 100644 index 0000000..f65c520 --- /dev/null +++ b/Extras/simdmathlibrary/common/frexpf4.c @@ -0,0 +1,36 @@ +/* frexpf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +frexpf4 (vector float x, vector signed int *exp) +{ + return _frexpf4( x, exp ); +} diff --git a/Extras/simdmathlibrary/common/hypotd2.c b/Extras/simdmathlibrary/common/hypotd2.c new file mode 100644 index 0000000..ab8edca --- /dev/null +++ b/Extras/simdmathlibrary/common/hypotd2.c @@ -0,0 +1,36 @@ +/* hypotd2 - for each element of vector x and y, return the square root of (x')^2 + (y')^2 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +hypotd2 (vector double x, vector double y) +{ + return _hypotd2(x, y); +} diff --git a/Extras/simdmathlibrary/common/hypotf4.c b/Extras/simdmathlibrary/common/hypotf4.c new file mode 100644 index 0000000..7bcf73c --- /dev/null +++ b/Extras/simdmathlibrary/common/hypotf4.c @@ -0,0 +1,36 @@ +/* hypotf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +hypotf4 (vector float x, vector float y) +{ + return _hypotf4( x, y ); +} diff --git a/Extras/simdmathlibrary/common/ilogbd2.c b/Extras/simdmathlibrary/common/ilogbd2.c new file mode 100644 index 0000000..c0a7452 --- /dev/null +++ b/Extras/simdmathlibrary/common/ilogbd2.c @@ -0,0 +1,36 @@ +/* ilogbd2 - for each element of vector x, return integer exponent of normalized double x', FP_ILOGBNAN, or FP_ILOGB0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector signed long long +ilogbd2 (vector double x) +{ + return _ilogbd2(x); +} diff --git a/Extras/simdmathlibrary/common/ilogbf4.c b/Extras/simdmathlibrary/common/ilogbf4.c new file mode 100644 index 0000000..0dd3a02 --- /dev/null +++ b/Extras/simdmathlibrary/common/ilogbf4.c @@ -0,0 +1,36 @@ +/* ilogbf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector signed int +ilogbf4 (vector float x) +{ + return _ilogbf4( x ); +} diff --git a/Extras/simdmathlibrary/common/irintf4.c b/Extras/simdmathlibrary/common/irintf4.c new file mode 100644 index 0000000..2378b67 --- /dev/null +++ b/Extras/simdmathlibrary/common/irintf4.c @@ -0,0 +1,39 @@ +/* irintf4 - for each of four float slots, round to the nearest integer, + consistent with the current rounding model. + On SPU, the rounding mode for float is always towards zero. + vector singned int is returned. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector signed int +irintf4(vector float in) +{ + return _irintf4(in); +} diff --git a/Extras/simdmathlibrary/common/iroundf4.c b/Extras/simdmathlibrary/common/iroundf4.c new file mode 100644 index 0000000..8f2f4c8 --- /dev/null +++ b/Extras/simdmathlibrary/common/iroundf4.c @@ -0,0 +1,38 @@ +/* iroundf4 - for each of four float slots, round to the nearest integer, + halfway cases are rounded away form zero. + + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector signed int +iroundf4(vector float in) +{ + return _iroundf4(in); +} diff --git a/Extras/simdmathlibrary/common/is0denormd2.c b/Extras/simdmathlibrary/common/is0denormd2.c new file mode 100644 index 0000000..7549666 --- /dev/null +++ b/Extras/simdmathlibrary/common/is0denormd2.c @@ -0,0 +1,36 @@ +/* is0denormd2 - for each of two double slots, if input equals 0 or denorm return mask of ones, else 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned long long +is0denormd2 (vector double x) +{ + return _is0denormd2(x); +} diff --git a/Extras/simdmathlibrary/common/is0denormf4.c b/Extras/simdmathlibrary/common/is0denormf4.c new file mode 100644 index 0000000..9e665b1 --- /dev/null +++ b/Extras/simdmathlibrary/common/is0denormf4.c @@ -0,0 +1,35 @@ +/* is0denormf4 - for each element of vector x, return a mask of ones if x' is zero or denorm, zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ +#include + +vector unsigned int +is0denormf4 (vector float x) +{ + return _is0denormf4(x); +} diff --git a/Extras/simdmathlibrary/common/isequald2.c b/Extras/simdmathlibrary/common/isequald2.c new file mode 100644 index 0000000..eeda92f --- /dev/null +++ b/Extras/simdmathlibrary/common/isequald2.c @@ -0,0 +1,35 @@ +/* isequald2 - for each of two double slots, if x = y return a mask of ones, else zero + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ +#include + +vector unsigned long long +isequald2 (vector double x, vector double y) +{ + return _isequald2(x, y); +} diff --git a/Extras/simdmathlibrary/common/isequalf4.c b/Extras/simdmathlibrary/common/isequalf4.c new file mode 100644 index 0000000..0bc43ba --- /dev/null +++ b/Extras/simdmathlibrary/common/isequalf4.c @@ -0,0 +1,36 @@ +/* isequalf4 - for each element of vector x and y, return a mask of ones if x' is equal to y', zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned int +isequalf4 (vector float x, vector float y) +{ + return _isequalf4(x, y); +} diff --git a/Extras/simdmathlibrary/common/isfinited2.c b/Extras/simdmathlibrary/common/isfinited2.c new file mode 100644 index 0000000..2ccc0a8 --- /dev/null +++ b/Extras/simdmathlibrary/common/isfinited2.c @@ -0,0 +1,37 @@ +/* isfinited2 - for each element of vector x, return a mask of ones if x' is finite, zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned long long +isfinited2 (vector double x) +{ + return _isfinited2(x); +} + diff --git a/Extras/simdmathlibrary/common/isfinitef4.c b/Extras/simdmathlibrary/common/isfinitef4.c new file mode 100644 index 0000000..52d37a1 --- /dev/null +++ b/Extras/simdmathlibrary/common/isfinitef4.c @@ -0,0 +1,36 @@ +/* isfinitef4 - for each element of vector x, return a mask of ones if x' is finite, zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned int +isfinitef4 (vector float x) +{ + return _isfinitef4(x); +} diff --git a/Extras/simdmathlibrary/common/isgreaterd2.c b/Extras/simdmathlibrary/common/isgreaterd2.c new file mode 100644 index 0000000..ff9fd0d --- /dev/null +++ b/Extras/simdmathlibrary/common/isgreaterd2.c @@ -0,0 +1,36 @@ +/* isgreaterd2 - for each of two double slots, if x > y return mask of ones, else 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned long long +isgreaterd2 (vector double x, vector double y) +{ + return _isgreaterd2(x, y); +} diff --git a/Extras/simdmathlibrary/common/isgreaterequald2.c b/Extras/simdmathlibrary/common/isgreaterequald2.c new file mode 100644 index 0000000..d8a9c45 --- /dev/null +++ b/Extras/simdmathlibrary/common/isgreaterequald2.c @@ -0,0 +1,36 @@ +/* isgreaterequald2 - for each of two double slots, if x is greater or equal to y return a mask of ones, else zero + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned long long +isgreaterequald2 (vector double x, vector double y) +{ + return _isgreaterequald2(x, y); +} diff --git a/Extras/simdmathlibrary/common/isgreaterequalf4.c b/Extras/simdmathlibrary/common/isgreaterequalf4.c new file mode 100644 index 0000000..e06dd0f --- /dev/null +++ b/Extras/simdmathlibrary/common/isgreaterequalf4.c @@ -0,0 +1,36 @@ +/* isgreaterequalf4 - for each element of vector x and y, return a mask of ones if x' is greater than or equal to y', zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned int +isgreaterequalf4 (vector float x, vector float y) +{ + return _isgreaterequalf4(x, y); +} diff --git a/Extras/simdmathlibrary/common/isgreaterf4.c b/Extras/simdmathlibrary/common/isgreaterf4.c new file mode 100644 index 0000000..2297898 --- /dev/null +++ b/Extras/simdmathlibrary/common/isgreaterf4.c @@ -0,0 +1,36 @@ +/* isgreaterf4 - for each element of vector x and y, return a mask of ones if x' is greater than y', zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned int +isgreaterf4 (vector float x, vector float y) +{ + return _isgreaterf4(x, y); +} diff --git a/Extras/simdmathlibrary/common/isinfd2.c b/Extras/simdmathlibrary/common/isinfd2.c new file mode 100644 index 0000000..500fa26 --- /dev/null +++ b/Extras/simdmathlibrary/common/isinfd2.c @@ -0,0 +1,36 @@ +/* isinfd2 - for each of two double slots, if input equals +Inf or -Inf return mask of ones, else 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned long long +isinfd2 (vector double x) +{ + return _isinfd2(x); +} diff --git a/Extras/simdmathlibrary/common/isinff4.c b/Extras/simdmathlibrary/common/isinff4.c new file mode 100644 index 0000000..15afc8b --- /dev/null +++ b/Extras/simdmathlibrary/common/isinff4.c @@ -0,0 +1,36 @@ +/* isinff4 - for each element of vector x, return a mask of ones if x' is INF, zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned int +isinff4 (vector float x) +{ + return _isinff4(x); +} diff --git a/Extras/simdmathlibrary/common/islessd2.c b/Extras/simdmathlibrary/common/islessd2.c new file mode 100644 index 0000000..40aecb8 --- /dev/null +++ b/Extras/simdmathlibrary/common/islessd2.c @@ -0,0 +1,36 @@ +/* islessd2 - for each of two double slots, if x < y return a mask of ones, else zero + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned long long +islessd2 (vector double x, vector double y) +{ + return _islessd2(x, y); +} diff --git a/Extras/simdmathlibrary/common/islessequald2.c b/Extras/simdmathlibrary/common/islessequald2.c new file mode 100644 index 0000000..983e749 --- /dev/null +++ b/Extras/simdmathlibrary/common/islessequald2.c @@ -0,0 +1,36 @@ +/* islessequald2 - for each of two double slots, if x <= y return mask of ones, else 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned long long +islessequald2 (vector double x, vector double y) +{ + return _islessequald2(x, y); +} diff --git a/Extras/simdmathlibrary/common/islessequalf4.c b/Extras/simdmathlibrary/common/islessequalf4.c new file mode 100644 index 0000000..0eb7d7c --- /dev/null +++ b/Extras/simdmathlibrary/common/islessequalf4.c @@ -0,0 +1,36 @@ +/* islessequalf4 - for each element of vector x and y, return a mask of ones if x' is less than or equal to y', zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned int +islessequalf4 (vector float x, vector float y) +{ + return _islessequalf4(x, y); +} diff --git a/Extras/simdmathlibrary/common/islessf4.c b/Extras/simdmathlibrary/common/islessf4.c new file mode 100644 index 0000000..e6d99f0 --- /dev/null +++ b/Extras/simdmathlibrary/common/islessf4.c @@ -0,0 +1,36 @@ +/* islessf4 - for each element of vector x and y, return a mask of ones if x' is less than y', zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned int +islessf4 (vector float x, vector float y) +{ + return _islessf4(x, y); +} diff --git a/Extras/simdmathlibrary/common/islessgreaterd2.c b/Extras/simdmathlibrary/common/islessgreaterd2.c new file mode 100644 index 0000000..af4e5d8 --- /dev/null +++ b/Extras/simdmathlibrary/common/islessgreaterd2.c @@ -0,0 +1,36 @@ +/* islessgreaterd2 - for each of two double slots, if x is less or greater than y return a mask of ones, else zero + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned long long +islessgreaterd2 (vector double x, vector double y) +{ + return _islessgreaterd2(x, y); +} diff --git a/Extras/simdmathlibrary/common/islessgreaterf4.c b/Extras/simdmathlibrary/common/islessgreaterf4.c new file mode 100644 index 0000000..acb9dee --- /dev/null +++ b/Extras/simdmathlibrary/common/islessgreaterf4.c @@ -0,0 +1,36 @@ +/* islessgreaterf4 - for each element of vector x and y, return a mask of ones if x' is less than or greater than y', zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned int +islessgreaterf4 (vector float x, vector float y) +{ + return _islessgreaterf4(x, y); +} diff --git a/Extras/simdmathlibrary/common/isnand2.c b/Extras/simdmathlibrary/common/isnand2.c new file mode 100644 index 0000000..cea8223 --- /dev/null +++ b/Extras/simdmathlibrary/common/isnand2.c @@ -0,0 +1,36 @@ +/* isnand2 - for each of two double slots, if input is any type of NaN return mask of ones, else 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned long long +isnand2 (vector double x) +{ + return _isnand2(x); +} diff --git a/Extras/simdmathlibrary/common/isnanf4.c b/Extras/simdmathlibrary/common/isnanf4.c new file mode 100644 index 0000000..2e0f8fe --- /dev/null +++ b/Extras/simdmathlibrary/common/isnanf4.c @@ -0,0 +1,36 @@ +/* isnanf4 - for each element of vector x, return a mask of ones if x' is NaN, zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned int +isnanf4 (vector float x) +{ + return _isnanf4(x); +} diff --git a/Extras/simdmathlibrary/common/isnormald2.c b/Extras/simdmathlibrary/common/isnormald2.c new file mode 100644 index 0000000..21a313f --- /dev/null +++ b/Extras/simdmathlibrary/common/isnormald2.c @@ -0,0 +1,36 @@ +/* isnormald2 - for each element of vector x, return a mask of ones if x' is normal, not a NaN or INF, zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned long long +isnormald2 (vector double x) +{ + return _isnormald2(x); +} diff --git a/Extras/simdmathlibrary/common/isnormalf4.c b/Extras/simdmathlibrary/common/isnormalf4.c new file mode 100644 index 0000000..1271313 --- /dev/null +++ b/Extras/simdmathlibrary/common/isnormalf4.c @@ -0,0 +1,36 @@ +/* isnormalf4 - for each element of vector x, return a mask of ones if x' is normal, not a NaN or INF, zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned int +isnormalf4 (vector float x) +{ + return _isnormalf4(x); +} diff --git a/Extras/simdmathlibrary/common/isunorderedd2.c b/Extras/simdmathlibrary/common/isunorderedd2.c new file mode 100644 index 0000000..ee135f3 --- /dev/null +++ b/Extras/simdmathlibrary/common/isunorderedd2.c @@ -0,0 +1,36 @@ +/* isunorderedd2 - for each element of vector x and y, return a mask of ones if x' is unordered to y', zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned long long +isunorderedd2 (vector double x, vector double y) +{ + return _isunorderedd2(x, y); +} diff --git a/Extras/simdmathlibrary/common/isunorderedf4.c b/Extras/simdmathlibrary/common/isunorderedf4.c new file mode 100644 index 0000000..d216f4e --- /dev/null +++ b/Extras/simdmathlibrary/common/isunorderedf4.c @@ -0,0 +1,36 @@ +/* isunorderedf4 - for each element of vector x and y, return a mask of ones if x' is unordered to y', zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned int +isunorderedf4 (vector float x, vector float y) +{ + return _isunorderedf4(x, y); +} diff --git a/Extras/simdmathlibrary/common/ldexpd2.c b/Extras/simdmathlibrary/common/ldexpd2.c new file mode 100644 index 0000000..a5b3543 --- /dev/null +++ b/Extras/simdmathlibrary/common/ldexpd2.c @@ -0,0 +1,38 @@ +/* ldexpd2 - Multiply Double by 2 Raised to its Power + For large elements of ex (overflow), returns HUGE_VALF + For small elements of ex (underflow), returns 0. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +ldexpd2(vector double x, vector signed long long ex) +{ + return _ldexpd2(x, ex); +} diff --git a/Extras/simdmathlibrary/common/ldexpf4.c b/Extras/simdmathlibrary/common/ldexpf4.c new file mode 100644 index 0000000..e168079 --- /dev/null +++ b/Extras/simdmathlibrary/common/ldexpf4.c @@ -0,0 +1,36 @@ +/* ldexpf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +ldexpf4 (vector float x, vector signed int exp) +{ + return _ldexpf4( x, exp ); +} diff --git a/Extras/simdmathlibrary/common/llabsi2.c b/Extras/simdmathlibrary/common/llabsi2.c new file mode 100644 index 0000000..454a3e0 --- /dev/null +++ b/Extras/simdmathlibrary/common/llabsi2.c @@ -0,0 +1,36 @@ +/* llabsi2 - returns absolute value of input. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector signed long long +llabsi2 (vector signed long long in) +{ + return _llabsi2(in); +} diff --git a/Extras/simdmathlibrary/common/lldivi2.c b/Extras/simdmathlibrary/common/lldivi2.c new file mode 100644 index 0000000..7e14fde --- /dev/null +++ b/Extras/simdmathlibrary/common/lldivi2.c @@ -0,0 +1,36 @@ +/* lldivi2 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +lldivi2_t +lldivi2 (vector signed long long numer, vector signed long long denom) +{ + return _lldivi2(numer, denom); +} diff --git a/Extras/simdmathlibrary/common/lldivu2.c b/Extras/simdmathlibrary/common/lldivu2.c new file mode 100644 index 0000000..5b2fd89 --- /dev/null +++ b/Extras/simdmathlibrary/common/lldivu2.c @@ -0,0 +1,36 @@ +/* lldivu2 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +lldivu2_t +lldivu2 (vector unsigned long long numer, vector unsigned long long denom) +{ + return _lldivu2(numer, denom); +} diff --git a/Extras/simdmathlibrary/common/llrintd2.c b/Extras/simdmathlibrary/common/llrintd2.c new file mode 100644 index 0000000..3d44561 --- /dev/null +++ b/Extras/simdmathlibrary/common/llrintd2.c @@ -0,0 +1,37 @@ +/* llrintd2 - rounds two doubles in to two nearest 64bit integer. + consistent with the current rounding mode. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector signed long long +llrintd2 (vector double in) +{ + return _llrintd2(in); +} diff --git a/Extras/simdmathlibrary/common/llrintf4.c b/Extras/simdmathlibrary/common/llrintf4.c new file mode 100644 index 0000000..96f956a --- /dev/null +++ b/Extras/simdmathlibrary/common/llrintf4.c @@ -0,0 +1,37 @@ +/* llrintf4 - rounds four floats in to four nearest 64bit integer. + On SPU the rounding mode for floats is always towards 0. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +llroundf4_t +llrintf4 (vector float in) +{ + return _llrintf4(in); +} diff --git a/Extras/simdmathlibrary/common/llroundd2.c b/Extras/simdmathlibrary/common/llroundd2.c new file mode 100644 index 0000000..680408e --- /dev/null +++ b/Extras/simdmathlibrary/common/llroundd2.c @@ -0,0 +1,37 @@ +/* llroundd2 - rounds two doubles in to two nearest 64bit integer. + 0.5 will be rounded to far from 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector signed long long +llroundd2 (vector double in) +{ + return _llroundd2(in); +} diff --git a/Extras/simdmathlibrary/common/llroundf4.c b/Extras/simdmathlibrary/common/llroundf4.c new file mode 100644 index 0000000..db00e9c --- /dev/null +++ b/Extras/simdmathlibrary/common/llroundf4.c @@ -0,0 +1,37 @@ +/* llroundf4 - rounds four floats in to four nearest 64bit integer. + 0.5 will be rounded to far from 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +llroundf4_t +llroundf4 (vector float in) +{ + return _llroundf4(in); +} diff --git a/Extras/simdmathlibrary/common/log10f4.c b/Extras/simdmathlibrary/common/log10f4.c new file mode 100644 index 0000000..a246f1f --- /dev/null +++ b/Extras/simdmathlibrary/common/log10f4.c @@ -0,0 +1,36 @@ +/* log10f4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +log10f4 (vector float x) +{ + return _log10f4( x ); +} diff --git a/Extras/simdmathlibrary/common/log1pf4.c b/Extras/simdmathlibrary/common/log1pf4.c new file mode 100644 index 0000000..5571df0 --- /dev/null +++ b/Extras/simdmathlibrary/common/log1pf4.c @@ -0,0 +1,36 @@ +/* log1pf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +log1pf4 (vector float x) +{ + return _log1pf4( x ); +} diff --git a/Extras/simdmathlibrary/common/log2f4.c b/Extras/simdmathlibrary/common/log2f4.c new file mode 100644 index 0000000..3c9d93a --- /dev/null +++ b/Extras/simdmathlibrary/common/log2f4.c @@ -0,0 +1,36 @@ +/* log2f4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +log2f4 (vector float x) +{ + return _log2f4( x ); +} diff --git a/Extras/simdmathlibrary/common/logbd2.c b/Extras/simdmathlibrary/common/logbd2.c new file mode 100644 index 0000000..0ea5b7d --- /dev/null +++ b/Extras/simdmathlibrary/common/logbd2.c @@ -0,0 +1,36 @@ +/* logbd2 - for each element of vector x, return the exponent of normalized double x' as floating point value + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +logbd2 (vector double x) +{ + return _logbd2(x); +} diff --git a/Extras/simdmathlibrary/common/logbf4.c b/Extras/simdmathlibrary/common/logbf4.c new file mode 100644 index 0000000..19ab3a1 --- /dev/null +++ b/Extras/simdmathlibrary/common/logbf4.c @@ -0,0 +1,36 @@ +/* logbf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +logbf4 (vector float x) +{ + return _logbf4( x ); +} diff --git a/Extras/simdmathlibrary/common/logf4.c b/Extras/simdmathlibrary/common/logf4.c new file mode 100644 index 0000000..fc2372e --- /dev/null +++ b/Extras/simdmathlibrary/common/logf4.c @@ -0,0 +1,36 @@ +/* logf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +logf4 (vector float x) +{ + return _logf4( x ); +} diff --git a/Extras/simdmathlibrary/common/modfd2.c b/Extras/simdmathlibrary/common/modfd2.c new file mode 100644 index 0000000..52dcb34 --- /dev/null +++ b/Extras/simdmathlibrary/common/modfd2.c @@ -0,0 +1,36 @@ +/* modfd2 - for each of two double slots, compute fractional and integral parts. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +modfd2 (vector double x, vector double *iptr) +{ + return _modfd2(x, iptr); +} diff --git a/Extras/simdmathlibrary/common/modff4.c b/Extras/simdmathlibrary/common/modff4.c new file mode 100644 index 0000000..b460ccf --- /dev/null +++ b/Extras/simdmathlibrary/common/modff4.c @@ -0,0 +1,36 @@ +/* modff4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +modff4 (vector float x, vector float *iptr) +{ + return _modff4( x, iptr ); +} diff --git a/Extras/simdmathlibrary/common/nearbyintd2.c b/Extras/simdmathlibrary/common/nearbyintd2.c new file mode 100644 index 0000000..354d7f0 --- /dev/null +++ b/Extras/simdmathlibrary/common/nearbyintd2.c @@ -0,0 +1,37 @@ +/* nearbyintd2 - Round the input to the nearest integer according to + the current rounding mode without raising an inexact exception. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +nearbyintd2(vector double in) +{ + return _nearbyintd2(in); +} diff --git a/Extras/simdmathlibrary/common/nearbyintf4.c b/Extras/simdmathlibrary/common/nearbyintf4.c new file mode 100644 index 0000000..5625650 --- /dev/null +++ b/Extras/simdmathlibrary/common/nearbyintf4.c @@ -0,0 +1,39 @@ +/* nearbyintf4 - for each of four float slots, round to the nearest integer, + consistent with the current rounding model, + without raising an inexact floating-point exception. + On SPU, the rounding mode for float is always towards zero. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +nearbyintf4(vector float x) +{ + return _nearbyintf4(x); +} diff --git a/Extras/simdmathlibrary/common/negated2.c b/Extras/simdmathlibrary/common/negated2.c new file mode 100644 index 0000000..66847d0 --- /dev/null +++ b/Extras/simdmathlibrary/common/negated2.c @@ -0,0 +1,37 @@ +/* negated2 - for each of two double slots, negate the sign bit. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +negated2 (vector double x) +{ + return _negated2(x); +} + diff --git a/Extras/simdmathlibrary/common/negatef4.c b/Extras/simdmathlibrary/common/negatef4.c new file mode 100644 index 0000000..1856663 --- /dev/null +++ b/Extras/simdmathlibrary/common/negatef4.c @@ -0,0 +1,36 @@ +/* negatef4 - for each of four float slots, negate the sign bit. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +negatef4 (vector float x) +{ + return _negatef4( x ); +} diff --git a/Extras/simdmathlibrary/common/negatei4.c b/Extras/simdmathlibrary/common/negatei4.c new file mode 100644 index 0000000..622fb7a --- /dev/null +++ b/Extras/simdmathlibrary/common/negatei4.c @@ -0,0 +1,36 @@ +/* negatei4 - for each of four int slots, negate the sign bit. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector signed int +negatei4 (vector signed int x) +{ + return _negatei4( x ); +} diff --git a/Extras/simdmathlibrary/common/negatell2.c b/Extras/simdmathlibrary/common/negatell2.c new file mode 100644 index 0000000..36fc706 --- /dev/null +++ b/Extras/simdmathlibrary/common/negatell2.c @@ -0,0 +1,36 @@ +/* negatell2 - for each of 2 signed long long slots, negate the sign bit. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector signed long long +negatell2 (vector signed long long x) +{ + return _negatell2(x); +} diff --git a/Extras/simdmathlibrary/common/nextafterd2.c b/Extras/simdmathlibrary/common/nextafterd2.c new file mode 100644 index 0000000..8b7f48c --- /dev/null +++ b/Extras/simdmathlibrary/common/nextafterd2.c @@ -0,0 +1,36 @@ +/* nextafterd2 - find next representable floating-point value towards 2nd param. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +nextafterd2 (vector double xx, vector double yy) +{ + return _nextafterd2(xx, yy); +} diff --git a/Extras/simdmathlibrary/common/nextafterf4.c b/Extras/simdmathlibrary/common/nextafterf4.c new file mode 100644 index 0000000..9742db4 --- /dev/null +++ b/Extras/simdmathlibrary/common/nextafterf4.c @@ -0,0 +1,38 @@ +/* nextafterf4 - for each of four float slots, + return the the next representable value after x in the direction fo y, + if x is euqal to y, the result is y. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +nextafterf4(vector float x, vector float y) +{ + return _nextafterf4(x, y); +} diff --git a/Extras/simdmathlibrary/common/powf4.c b/Extras/simdmathlibrary/common/powf4.c new file mode 100644 index 0000000..00c3a82 --- /dev/null +++ b/Extras/simdmathlibrary/common/powf4.c @@ -0,0 +1,36 @@ +/* exp2f4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +powf4 (vector float x, vector float y) +{ + return _powf4( x, y ); +} diff --git a/Extras/simdmathlibrary/common/recipd2.c b/Extras/simdmathlibrary/common/recipd2.c new file mode 100644 index 0000000..d84d01b --- /dev/null +++ b/Extras/simdmathlibrary/common/recipd2.c @@ -0,0 +1,36 @@ +/* recipd2 - for each of two double slots, compute reciprocal. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +recipd2 (vector double x) +{ + return _recipd2(x); +} diff --git a/Extras/simdmathlibrary/common/recipf4.c b/Extras/simdmathlibrary/common/recipf4.c new file mode 100644 index 0000000..9743efe --- /dev/null +++ b/Extras/simdmathlibrary/common/recipf4.c @@ -0,0 +1,36 @@ +/* recipf4 - for each of four float slots, compute reciprocal. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +recipf4 (vector float x) +{ + return _recipf4( x ); +} diff --git a/Extras/simdmathlibrary/common/remainderd2.c b/Extras/simdmathlibrary/common/remainderd2.c new file mode 100644 index 0000000..082e988 --- /dev/null +++ b/Extras/simdmathlibrary/common/remainderd2.c @@ -0,0 +1,37 @@ +/* A vector double is returned that contains the remainder xi REM yi, + for the corresponding elements of vector double x and vector double y. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +remainderd2(vector double x, vector double yy) +{ + return _remainderd2(x, yy); +} diff --git a/Extras/simdmathlibrary/common/remainderf4.c b/Extras/simdmathlibrary/common/remainderf4.c new file mode 100644 index 0000000..f653587 --- /dev/null +++ b/Extras/simdmathlibrary/common/remainderf4.c @@ -0,0 +1,36 @@ +/* remainderf4 - for each of four float slots, compute remainder of x/y defined as x - nearest_integer(x/y) * y. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +remainderf4 (vector float x, vector float y) +{ + return _remainderf4(x, y); +} diff --git a/Extras/simdmathlibrary/common/remquod2.c b/Extras/simdmathlibrary/common/remquod2.c new file mode 100644 index 0000000..c06a4b4 --- /dev/null +++ b/Extras/simdmathlibrary/common/remquod2.c @@ -0,0 +1,36 @@ +/* remquod2 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +remquod2(vector double x, vector double yy, vector signed long long *quo) +{ + return _remquod2(x, yy, quo); +} diff --git a/Extras/simdmathlibrary/common/remquof4.c b/Extras/simdmathlibrary/common/remquof4.c new file mode 100644 index 0000000..2429f95 --- /dev/null +++ b/Extras/simdmathlibrary/common/remquof4.c @@ -0,0 +1,36 @@ +/* remquof4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +remquof4(vector float x, vector float y, vector signed int *quo) +{ + return _remquof4(x, y, quo); +} diff --git a/Extras/simdmathlibrary/common/rintd2.c b/Extras/simdmathlibrary/common/rintd2.c new file mode 100644 index 0000000..a2e9435 --- /dev/null +++ b/Extras/simdmathlibrary/common/rintd2.c @@ -0,0 +1,37 @@ +/* rintd2 - Round the input to the nearest integer according to + the current rounding mode. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +rintd2(vector double in) +{ + return _rintd2(in); +} diff --git a/Extras/simdmathlibrary/common/rintf4.c b/Extras/simdmathlibrary/common/rintf4.c new file mode 100644 index 0000000..c8069dc --- /dev/null +++ b/Extras/simdmathlibrary/common/rintf4.c @@ -0,0 +1,38 @@ +/* rintf4 - for each of four float slots, round to the nearest integer, + consistent with the current rounding model. + On SPU, the rounding mode for float is always towards zero. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +rintf4(vector float x) +{ + return _rintf4(x); +} diff --git a/Extras/simdmathlibrary/common/roundd2.c b/Extras/simdmathlibrary/common/roundd2.c new file mode 100644 index 0000000..fadc41b --- /dev/null +++ b/Extras/simdmathlibrary/common/roundd2.c @@ -0,0 +1,37 @@ +/* roundd2 - rounds to nearest integer value in floating point format. + 0.5 will be rounded to far from 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +roundd2 (vector double in) +{ + return _roundd2(in); +} diff --git a/Extras/simdmathlibrary/common/roundf4.c b/Extras/simdmathlibrary/common/roundf4.c new file mode 100644 index 0000000..6527715 --- /dev/null +++ b/Extras/simdmathlibrary/common/roundf4.c @@ -0,0 +1,37 @@ +/* roundf4 - for each of four float slots, round to the nearest integer, + halfway cases are rounded away form zero. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +roundf4(vector float in) +{ + return _roundf4(in); +} diff --git a/Extras/simdmathlibrary/common/rsqrtd2.c b/Extras/simdmathlibrary/common/rsqrtd2.c new file mode 100644 index 0000000..bbd58c4 --- /dev/null +++ b/Extras/simdmathlibrary/common/rsqrtd2.c @@ -0,0 +1,36 @@ +/* rsqrtd2 - for each of two double slots, compute reciprocal square root. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +rsqrtd2 (vector double x) +{ + return _rsqrtd2(x); +} diff --git a/Extras/simdmathlibrary/common/rsqrtf4.c b/Extras/simdmathlibrary/common/rsqrtf4.c new file mode 100644 index 0000000..fa0dec3 --- /dev/null +++ b/Extras/simdmathlibrary/common/rsqrtf4.c @@ -0,0 +1,36 @@ +/* sqrtf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +rsqrtf4 (vector float x) +{ + return _rsqrtf4( x ); +} diff --git a/Extras/simdmathlibrary/common/scalbllnd2.c b/Extras/simdmathlibrary/common/scalbllnd2.c new file mode 100644 index 0000000..aad9e5c --- /dev/null +++ b/Extras/simdmathlibrary/common/scalbllnd2.c @@ -0,0 +1,38 @@ +/* scalbllnd2 - Multiply Double by 2 Raised to its Power + For large elements of ex (overflow), returns HUGE_VALF + For small elements of ex (underflow), returns 0. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +scalbllnd2(vector double x, vector signed long long ex) +{ + return _scalbllnd2(x, ex); +} diff --git a/Extras/simdmathlibrary/common/scalbnf4.c b/Extras/simdmathlibrary/common/scalbnf4.c new file mode 100644 index 0000000..49db439 --- /dev/null +++ b/Extras/simdmathlibrary/common/scalbnf4.c @@ -0,0 +1,38 @@ +/* scalbnf4 computes x * 2^exp. This function is computed without + the assistence of any floating point operations and as such does + not set any floating point exceptions. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +scalbnf4(vector float x, vector signed int n) +{ + return _scalbnf4(x, n); +} diff --git a/Extras/simdmathlibrary/common/signbitd2.c b/Extras/simdmathlibrary/common/signbitd2.c new file mode 100644 index 0000000..facdb6c --- /dev/null +++ b/Extras/simdmathlibrary/common/signbitd2.c @@ -0,0 +1,36 @@ +/* signbitd2 - for each of two double slots, if input has negative sign bit return mask of ones, else 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned long long +signbitd2 (vector double x) +{ + return _signbitd2(x); +} diff --git a/Extras/simdmathlibrary/common/signbitf4.c b/Extras/simdmathlibrary/common/signbitf4.c new file mode 100644 index 0000000..811879e --- /dev/null +++ b/Extras/simdmathlibrary/common/signbitf4.c @@ -0,0 +1,36 @@ +/* signbitf4 - for each element of vector x, return a mask of ones if x' has signbit one, zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector unsigned int +signbitf4 (vector float x) +{ + return _signbitf4(x); +} diff --git a/Extras/simdmathlibrary/common/simdmath.h b/Extras/simdmathlibrary/common/simdmath.h new file mode 100644 index 0000000..e953d8d --- /dev/null +++ b/Extras/simdmathlibrary/common/simdmath.h @@ -0,0 +1,732 @@ +/* SIMD math library functions for both the PowerPC (PPU) and the SPU. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + +#ifndef ___SIMD_MATH_H___ +#define ___SIMD_MATH_H___ + +#define __SIMD_MATH_HAVE_VECTOR_f4 0 +#define __SIMD_MATH_HAVE_VECTOR_i4 0 +#define __SIMD_MATH_HAVE_VECTOR_d2 0 +#define __SIMD_MATH_HAVE_VECTOR_ll2 0 + +#ifdef __SPU__ + +/* SPU has vector float, vector double, + vector {un,}signed long long, and vector {un,signed} int. */ + +#include + +#undef __SIMD_MATH_HAVE_VECTOR_f4 +#define __SIMD_MATH_HAVE_VECTOR_f4 1 + +#undef __SIMD_MATH_HAVE_VECTOR_i4 +#define __SIMD_MATH_HAVE_VECTOR_i4 1 + +#undef __SIMD_MATH_HAVE_VECTOR_d2 +#define __SIMD_MATH_HAVE_VECTOR_d2 1 + +#undef __SIMD_MATH_HAVE_VECTOR_ll2 +#define __SIMD_MATH_HAVE_VECTOR_ll2 1 + +#elif defined(__ALTIVEC__) + +#include + +/* PPU has vector float, and vector int. */ +#undef __SIMD_MATH_HAVE_VECTOR_f4 +#define __SIMD_MATH_HAVE_VECTOR_f4 1 + +#undef __SIMD_MATH_HAVE_VECTOR_i4 +#define __SIMD_MATH_HAVE_VECTOR_i4 1 + +#else + +/* Just in case someone tries to include this in say a i686 build. */ + +#error "No functions defined" + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Types */ + +#if __SIMD_MATH_HAVE_VECTOR_i4 +typedef struct divi4_s { + vector signed int quot; + vector signed int rem; +} divi4_t; +#endif + +#if __SIMD_MATH_HAVE_VECTOR_i4 +typedef struct divu4_s { + vector unsigned int quot; + vector unsigned int rem; +} divu4_t; +#endif + +#if __SIMD_MATH_HAVE_VECTOR_ll2 +typedef struct lldivi2_s { + vector signed long long quot; + vector signed long long rem; +} lldivi2_t; +#endif + +#if __SIMD_MATH_HAVE_VECTOR_ll2 +typedef struct lldivu2_s { + vector unsigned long long quot; + vector unsigned long long rem; +} lldivu2_t; +#endif + +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_ll2 +typedef struct llroundf4_s { + vector signed long long vll[2]; +} llroundf4_t; +#endif + +/* integer divide */ + +#if __SIMD_MATH_HAVE_VECTOR_i4 +divi4_t divi4 (vector signed int, vector signed int); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_i4 +divu4_t divu4 (vector unsigned int, vector unsigned int); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_ll2 +lldivi2_t lldivi2 (vector signed long long, vector signed long long); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_ll2 +lldivu2_t lldivu2 (vector unsigned long long, vector unsigned long long); +#endif + +/* abs value */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float fabsf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double fabsd2 (vector double); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_i4 +vector signed int absi4 (vector signed int); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_ll2 +vector signed long long llabsi2 (vector signed long long); +#endif + +/* negate value */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float negatef4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double negated2 (vector double); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_i4 +vector signed int negatei4 (vector signed int); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_ll2 +vector signed long long negatell2 (vector signed long long); +#endif + +/* trunc */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float truncf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double trund2 (vector double); +#endif + +/* floor */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float floorf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double floord2 (vector double); +#endif + +/* ceil */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float ceilf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double ceild2 (vector double); +#endif + +/* exp */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float expf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double expd2 (vector double); +#endif + +/* exp */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float exp2f4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double exp2d2 (vector double); +#endif + +/* expm1 */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float expm1f4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double expm1d2 (vector double); +#endif + +/* log */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float logf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double logd2 (vector double); +#endif + +/* log10 */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float log10f4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double log10d2 (vector double); +#endif + +/* log1p */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float log1pf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double log1pd2 (vector double); +#endif + +/* pow */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float powf4 (vector float, vector float); +#endif + +/* fma */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float fmaf4 (vector float, vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double fmad2 (vector double, vector double, vector double); +#endif + +/* fmax */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float fmaxf4 (vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double fmaxd2 (vector double, vector double); +#endif + +/* fmin */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float fminf4 (vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double fmind2 (vector double, vector double); +#endif + +/* fdim */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float fdimf4 (vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double fdimd2 (vector double, vector double); +#endif + + +/* fmod */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float fmodf4 (vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double fmodd2 (vector double, vector double); +#endif + +/* log2 */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float log2f4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double log2d2 (vector double); +#endif + +/* logb */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float logbf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double logbd2 (vector double); +#endif + +/* ilogb */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector signed int ilogbf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector signed long long ilogbd2 (vector double); +#endif + +/* modf */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float modff4 (vector float, vector float *); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double modfd2 (vector double, vector double *); +#endif + +/* sqrt */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float sqrtf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double sqrtd2 (vector double); +#endif + +/* hypot */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float hypotf4 (vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double hypotd2 (vector double, vector double); +#endif + +/* cbrtf4 */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float cbrtf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double cbrtd2 (vector double); +#endif + +/* sin */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float sinf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double sind2 (vector double); +#endif + + +/* asin */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float asinf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double asind2 (vector double); +#endif + + + +/* divide */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float divf4 (vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double divd2 (vector double, vector double); +#endif + +/* remainder */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float remainderf4 (vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double remainderd2 (vector double, vector double); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector float remquof4(vector float x, vector float y, vector signed int *quo); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector double remquod2(vector double x, vector double y, vector signed long long *quo); +#endif + +/* copysign */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float copysignf4 (vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double copysignd2 (vector double, vector double); +#endif + +/* cos */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float cosf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double cosd2 (vector double); +#endif + +/* acos */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float acosf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double acosd2 (vector double); +#endif + +/* atan */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float atanf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double atand2 (vector double); +#endif + +/* atan2 */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float atan2f4 (vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double atan2d2 (vector double, vector double); +#endif + + +/* tan */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float tanf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double tand2 (vector double); +#endif + +/* sincos */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +void sincosf4 (vector float, vector float *, vector float *); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +void sincosd2 (vector double, vector double *, vector double *); +#endif + + + +/* recip */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float recipf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double recipd2 (vector double); +#endif + + +/* rsqrt */ +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float rsqrtf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double rsqrtd2 (vector double); +#endif + + +/* frexp */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector float frexpf4 (vector float, vector signed int *); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector double frexpd2 (vector double, vector signed long long *); +#endif + +/* ldexp */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector float ldexpf4 (vector float, vector signed int ); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector double ldexpd2 (vector double, vector signed long long ); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector float scalbnf4(vector float x, vector signed int n); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector double scalbllnd2 (vector double, vector signed long long ); +#endif + + +/* isnan */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector unsigned int isnanf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector unsigned long long isnand2 (vector double); +#endif + +/* isinf */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector unsigned int isinff4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector unsigned long long isinfd2 (vector double); +#endif + +/* isfinite */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector unsigned int isfinitef4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector unsigned long long isfinited2 (vector double); +#endif + +/* isnormal */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector unsigned int isnormalf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector unsigned long long isnormald2 (vector double); +#endif + +/* isunordered */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector unsigned int isunorderedf4 (vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector unsigned long long isunorderedd2 (vector double, vector double); +#endif + +/* is0denorm */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector unsigned int is0denormf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector unsigned long long is0denormd2 (vector double); +#endif + +/* signbit */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector unsigned int signbitf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector unsigned long long signbitd2 (vector double); +#endif + +/* isequal */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector unsigned int isequalf4 (vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector unsigned long long isequald2 (vector double, vector double); +#endif + +/* islessgreater */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector unsigned int islessgreaterf4 (vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector unsigned long long islessgreaterd2 (vector double, vector double); +#endif + +/* isless */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector unsigned int islessf4 (vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector unsigned long long islessd2 (vector double, vector double); +#endif + +/* isgreater */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector unsigned int isgreaterf4 (vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector unsigned long long isgreaterd2 (vector double, vector double); +#endif + +/* islessequal */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector unsigned int islessequalf4 (vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector unsigned long long islessequald2 (vector double, vector double); +#endif + +/* isgreaterequal */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector unsigned int isgreaterequalf4 (vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector unsigned long long isgreaterequald2 (vector double, vector double); +#endif + +/* fpclassify */ +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector signed int fpclassifyf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector signed long long fpclassifyd2 (vector double); +#endif + +/* round */ +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector signed long long llroundd2 (vector double); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_ll2 +llroundf4_t llroundf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_ll2 +llroundf4_t llrintf4 (vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 && __SIMD_MATH_HAVE_VECTOR_ll2 +vector signed long long llrintd2 (vector double); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float roundf4(vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector signed int iroundf4(vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float rintf4(vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_f4 && __SIMD_MATH_HAVE_VECTOR_i4 +vector signed int irintf4(vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double nextafterd2 (vector double, vector double); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float nextafterf4(vector float, vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double nearbyintd2 (vector double); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_f4 +vector float nearbyintf4(vector float); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double truncd2 (vector double); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double roundd2 (vector double); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double rintd2 (vector double); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double ceild2(vector double); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double floord2(vector double); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double fmodd2(vector double, vector double); +#endif + +#if __SIMD_MATH_HAVE_VECTOR_d2 +vector double remainderd2(vector double, vector double); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Extras/simdmathlibrary/common/simdmath/_sincos.h b/Extras/simdmathlibrary/common/simdmath/_sincos.h new file mode 100644 index 0000000..a604ae1 --- /dev/null +++ b/Extras/simdmathlibrary/common/simdmath/_sincos.h @@ -0,0 +1,78 @@ +/* Common constants for Sin/Cos/Tan + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH__SINCOS_H___ +#define ___SIMD_MATH__SINCOS_H___ + +// +// Common constants used to evaluate sind2/cosd2/tand2 +// +#define __SINCOSD_CC0 0.00000000206374484196 +#define __SINCOSD_CC1 -0.00000027555365134677 +#define __SINCOSD_CC2 0.00002480157946764225 +#define __SINCOSD_CC3 -0.00138888888730525966 +#define __SINCOSD_CC4 0.04166666666651986722 +#define __SINCOSD_CC5 -0.49999999999999547304 + +#define __SINCOSD_SC0 0.00000000015893606014 +#define __SINCOSD_SC1 -0.00000002505069049138 +#define __SINCOSD_SC2 0.00000275573131527032 +#define __SINCOSD_SC3 -0.00019841269827816117 +#define __SINCOSD_SC4 0.00833333333331908278 +#define __SINCOSD_SC5 -0.16666666666666612594 + +#define __SINCOSD_KC1 (13176794.0 / 8388608.0) +#define __SINCOSD_KC2 7.5497899548918821691639751442098584e-8 + + +// +// Common constants used to evaluate sinf4/cosf4/tanf4 +// +#define __SINCOSF_CC0 -0.0013602249f +#define __SINCOSF_CC1 0.0416566950f +#define __SINCOSF_CC2 -0.4999990225f +#define __SINCOSF_SC0 -0.0001950727f +#define __SINCOSF_SC1 0.0083320758f +#define __SINCOSF_SC2 -0.1666665247f + +#define __SINCOSF_KC1 1.57079625129f +#define __SINCOSF_KC2 7.54978995489e-8f + +// +// Common constants used to evaluate sinf4est/cosf4est +// +#define __SINCOSF_R1 -0.1666665668f +#define __SINCOSF_R2 0.8333025139e-2f +#define __SINCOSF_R3 -0.1980741872e-3f +#define __SINCOSF_R4 0.2601903036e-5f + +#define __SINCOSF_C1 (201.0f/64.0f) +#define __SINCOSF_C2 9.67653589793e-4f + +#endif diff --git a/Extras/simdmathlibrary/common/sincosd2.c b/Extras/simdmathlibrary/common/sincosd2.c new file mode 100644 index 0000000..f5dce4d --- /dev/null +++ b/Extras/simdmathlibrary/common/sincosd2.c @@ -0,0 +1,36 @@ +/* sincosd2 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +void +sincosd2 (vector double x, vector double *s, vector double *c) +{ + _sincosd2( x, s, c ); +} diff --git a/Extras/simdmathlibrary/common/sincosf4.c b/Extras/simdmathlibrary/common/sincosf4.c new file mode 100644 index 0000000..dfa2333 --- /dev/null +++ b/Extras/simdmathlibrary/common/sincosf4.c @@ -0,0 +1,36 @@ +/* sincosf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +void +sincosf4 (vector float x, vector float *s, vector float *c) +{ + _sincosf4( x, s, c ); +} diff --git a/Extras/simdmathlibrary/common/sind2.c b/Extras/simdmathlibrary/common/sind2.c new file mode 100644 index 0000000..25e8ca0 --- /dev/null +++ b/Extras/simdmathlibrary/common/sind2.c @@ -0,0 +1,36 @@ +/* sind2 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +sind2 (vector double x) +{ + return _sind2(x); +} diff --git a/Extras/simdmathlibrary/common/sinf4.c b/Extras/simdmathlibrary/common/sinf4.c new file mode 100644 index 0000000..7e5ffd0 --- /dev/null +++ b/Extras/simdmathlibrary/common/sinf4.c @@ -0,0 +1,36 @@ +/* sinf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +sinf4 (vector float x) +{ + return _sinf4( x ); +} diff --git a/Extras/simdmathlibrary/common/sqrtd2.c b/Extras/simdmathlibrary/common/sqrtd2.c new file mode 100644 index 0000000..b73d953 --- /dev/null +++ b/Extras/simdmathlibrary/common/sqrtd2.c @@ -0,0 +1,36 @@ +/* sqrtd2 - for each of two double slots, compute square root. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +sqrtd2 (vector double x) +{ + return _sqrtd2(x); +} diff --git a/Extras/simdmathlibrary/common/sqrtf4.c b/Extras/simdmathlibrary/common/sqrtf4.c new file mode 100644 index 0000000..557c80f --- /dev/null +++ b/Extras/simdmathlibrary/common/sqrtf4.c @@ -0,0 +1,36 @@ +/* sqrtf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +sqrtf4 (vector float x) +{ + return _sqrtf4( x ); +} diff --git a/Extras/simdmathlibrary/common/tand2.c b/Extras/simdmathlibrary/common/tand2.c new file mode 100644 index 0000000..083a35d --- /dev/null +++ b/Extras/simdmathlibrary/common/tand2.c @@ -0,0 +1,36 @@ +/* tand2 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +tand2 (vector double x) +{ + return _tand2(x); +} diff --git a/Extras/simdmathlibrary/common/tanf4.c b/Extras/simdmathlibrary/common/tanf4.c new file mode 100644 index 0000000..1857e04 --- /dev/null +++ b/Extras/simdmathlibrary/common/tanf4.c @@ -0,0 +1,36 @@ +/* tanf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +tanf4 (vector float x) +{ + return _tanf4( x ); +} diff --git a/Extras/simdmathlibrary/common/truncd2.c b/Extras/simdmathlibrary/common/truncd2.c new file mode 100644 index 0000000..7a01c48 --- /dev/null +++ b/Extras/simdmathlibrary/common/truncd2.c @@ -0,0 +1,37 @@ +/* truncd2 - Round the input to the nearest integer. + Always rounds towards 0. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector double +truncd2(vector double in) +{ + return _truncd2(in); +} diff --git a/Extras/simdmathlibrary/common/truncf4.c b/Extras/simdmathlibrary/common/truncf4.c new file mode 100644 index 0000000..2e73376 --- /dev/null +++ b/Extras/simdmathlibrary/common/truncf4.c @@ -0,0 +1,37 @@ +/* truncf4 - for each of four float slots, round towards zero to integer value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +vector float +truncf4 (vector float x) +{ + return _truncf4( x ); +} + diff --git a/Extras/simdmathlibrary/ppu/Makefile b/Extras/simdmathlibrary/ppu/Makefile new file mode 100644 index 0000000..59316cc --- /dev/null +++ b/Extras/simdmathlibrary/ppu/Makefile @@ -0,0 +1,52 @@ +# make file to build the libsimdmath library for PPU +# Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. +# 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 Sony Computer Entertainment Inc 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. + +topdir = .. +ARCH = ppu + +include $(topdir)/Make.defs + +# All that you do to add a file is edit OBJS, the rest will just work + +OBJS = fabsf4.o absi4.o truncf4.o sqrtf4.o tanf4.o \ + negatef4.o fmaf4.o copysignf4.o modff4.o \ + fmaxf4.o fminf4.o fdimf4.o sinf4.o asinf4.o \ + floorf4.o recipf4.o ceilf4.o divf4.o divi4.o \ + cosf4.o hypotf4.o cbrtf4.o logf4.o sincosf4.o \ + rsqrtf4.o log2f4.o ldexpf4.o expf4.o frexpf4.o \ + expm1f4.o logbf4.o log1pf4.o log10f4.o ilogbf4.o \ + fmodf4.o negatei4.o exp2f4.o powf4.o atanf4.o \ + atan2f4.o acosf4.o + +include $(topdir)/Make.rules + +$(OBJS): ../common/simdmath.h simdmath/_vec_utils.h + + +# Some Objects have special header files. +sinf4.o cosf4.o sincosf4.o tanf4.o: ../common/simdmath/_sincos.h diff --git a/Extras/simdmathlibrary/ppu/simdmath/_vec_utils.h b/Extras/simdmathlibrary/ppu/simdmath/_vec_utils.h new file mode 100644 index 0000000..b5bf40a --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/_vec_utils.h @@ -0,0 +1,51 @@ +/* Common types for PPU SIMD Math Library + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_VEC_UTILS_H___ +#define ___SIMD_MATH_VEC_UTILS_H___ + +static inline vector float +__vec_splatsf4(const float x) +{ + return (vector float) {x, x, x, x}; +} + +static inline vector signed int +__vec_splatsi4(const signed int x) +{ + return (vector signed int) {x, x, x, x}; +} + +static inline vector unsigned int +__vec_splatsu4(const unsigned int x) +{ + return (vector unsigned int) {x, x, x, x}; +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/absi4.h b/Extras/simdmathlibrary/ppu/simdmath/absi4.h new file mode 100644 index 0000000..65cdc95 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/absi4.h @@ -0,0 +1,42 @@ +/* absi4 - for each of four integer slots, compute absolute value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ABSI4_H___ +#define ___SIMD_MATH_ABSI4_H___ + +#include +#include + +static inline vector signed int +_absi4 (vector signed int x) +{ + return vec_abs( x ); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/acosf4.h b/Extras/simdmathlibrary/ppu/simdmath/acosf4.h new file mode 100644 index 0000000..e84e803 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/acosf4.h @@ -0,0 +1,82 @@ +/* acosf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ACOSF4_H___ +#define ___SIMD_MATH_ACOSF4_H___ + +#include +#include + +#include + +// +// Computes the inverse cosine of all four slots of x. +// +static inline vector float +_acosf4 (vector float x) +{ + vector float result, xabs; + vector float t1; + vector float xabs2, xabs4; + vector float hi, lo; + vector float neg, pos; + vector unsigned int select; + + xabs = vec_abs(x); + select = (vector unsigned int)(vec_sra((vector signed int)(x), __vec_splatsu4(31))); + + t1 = _sqrtf4(vec_sub(__vec_splatsf4(1.0f), xabs)); + + /* Instruction counts can be reduced if the polynomial was + * computed entirely from nested (dependent) fma's. However, + * to reduce the number of pipeline stalls, the polygon is evaluated + * in two halves (hi amd lo). + */ + xabs2 = vec_madd(xabs, xabs, __vec_splatsf4(0.0f) ); + xabs4 = vec_madd(xabs2, xabs2, __vec_splatsf4(0.0f) ); + hi = vec_madd(__vec_splatsf4(-0.0012624911) , xabs, __vec_splatsf4(0.0066700901)); + hi = vec_madd(hi, xabs, __vec_splatsf4(-0.0170881256)); + hi = vec_madd(hi, xabs, __vec_splatsf4( 0.0308918810)); + lo = vec_madd(__vec_splatsf4(-0.0501743046), xabs, __vec_splatsf4(0.0889789874)); + lo = vec_madd(lo, xabs, __vec_splatsf4(-0.2145988016)); + lo = vec_madd(lo, xabs, __vec_splatsf4( 1.5707963050)); + + result = vec_madd(hi, xabs4, lo); + + /* Adjust the result if x is negactive. + */ + neg = vec_nmsub(t1, result, __vec_splatsf4(3.1415926535898f)); + pos = vec_madd(t1, result, __vec_splatsf4(0.0f)); + + result = vec_sel(pos, neg, select); + + return result; +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/asinf4.h b/Extras/simdmathlibrary/ppu/simdmath/asinf4.h new file mode 100644 index 0000000..51a7d67 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/asinf4.h @@ -0,0 +1,95 @@ +/* asinf4 - Computes the inverse sine of all four slots of x + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ASINF4_H___ +#define ___SIMD_MATH_ASINF4_H___ + +#include +#include + +#include +#include + +static inline vector float +_asinf4 (vector float x) +{ + // positive = (x > 0) + // + vector unsigned int positive = (vector unsigned int)vec_cmpgt(x, __vec_splatsf4(0.0f)); + + // x = absf(x) + // + x = vec_abs(x); + + // gtHalf = (|x| > 0.5) + // + vector unsigned int gtHalf = (vector unsigned int)vec_cmpgt(x, __vec_splatsf4(0.5f)); + + + // if (x > 0.5) + // g = 0.5 - 0.5*x + // x = -2 * sqrtf(g) + // else + // g = x * x + // + vector float g = + vec_sel(vec_madd(x, x, __vec_splatsf4(0.0f)), + vec_madd(__vec_splatsf4(-0.5f), x, __vec_splatsf4(0.5f)), gtHalf); + + x = vec_sel(x, vec_madd(__vec_splatsf4(-2.0f), _sqrtf4(g), __vec_splatsf4(0.0f)), gtHalf); + + // Compute the polynomials and take their ratio + // denom = (1.0f*g + -0.554846723e+1f)*g + 5.603603363f + // num = x * g * (-0.504400557f * g + 0.933933258f) + // + vector float denom = vec_add(g, __vec_splatsf4(-5.54846723f)); + vector float num = vec_madd(__vec_splatsf4(-0.504400557f), g, __vec_splatsf4(0.933933258f)); + denom = vec_madd(denom, g, __vec_splatsf4(5.603603363f)); + num = vec_madd(vec_madd(x, g, __vec_splatsf4(0.0f)), num, __vec_splatsf4(0.0f)); + + + // x = x + num / denom + // + x = vec_add(x,_divf4(num,denom)); + + // if (x > 0.5) + // x = x + M_PI_2 + // + x = vec_sel(x,vec_add(x, __vec_splatsf4(1.57079632679489661923f)), gtHalf); + + + // if (!positive) x = -x + // + x = vec_sel((vector float)vec_xor(__vec_splatsi4(0x80000000), (vector signed int)x), + x, positive); + + return x; +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/atan2f4.h b/Extras/simdmathlibrary/ppu/simdmath/atan2f4.h new file mode 100644 index 0000000..d201e35 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/atan2f4.h @@ -0,0 +1,67 @@ +/* atan2f4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ATAN2F4_H___ +#define ___SIMD_MATH_ATAN2F4_H___ + +#include +#include + +#include + +// +// Inverse tangent function of two variables +// +static inline vector float +_atan2f4 (vector float y, vector float x) +{ + vector float res = _atanf4(divf4(y,x)); + + // Use the arguments to determine the quadrant of the result: + // if (x < 0) + // if (y < 0) + // res = -PI + res + // else + // res = PI + res + // + vector unsigned int yNeg = (vector unsigned int)vec_cmpgt(__vec_splatsf4(0.0f), y); + vector unsigned int xNeg = (vector unsigned int)vec_cmpgt(__vec_splatsf4(0.0f) ,x); + + vector float bias = + vec_sel(__vec_splatsf4(3.14159265358979323846f), + __vec_splatsf4(-3.14159265358979323846f), yNeg); + + vector float newRes = vec_add(bias, res); + + res = vec_sel(res,newRes,xNeg); + + return res; +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/atanf4.h b/Extras/simdmathlibrary/ppu/simdmath/atanf4.h new file mode 100644 index 0000000..a495ecb --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/atanf4.h @@ -0,0 +1,87 @@ +/* atanf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ATANF4_H___ +#define ___SIMD_MATH_ATANF4_H___ + +#include +#include + +#include + +// +// Computes the inverse tangent of all four slots of x. +// +static inline vector float +_atanf4 (vector float x) +{ + vector float bias; + vector float x2, x3, x4, x8, x9; + vector float hi, lo; + vector float result; + vector float inv_x; + vector unsigned int sign; + vector unsigned int select; + vector float xabs; + vector float vzero = __vec_splatsf4(0.0f); + + sign = vec_and((vector unsigned int)x, __vec_splatsu4(0x80000000)); + xabs = (vector float)vec_andc((vector unsigned int)x, __vec_splatsu4(0x80000000)); + inv_x = _recipf4(x); + inv_x = (vector float)vec_xor((vector unsigned int)inv_x, __vec_splatsu4(0x80000000)); + select = (vector unsigned int)vec_cmpgt(xabs, __vec_splatsf4(1.0f)); + bias = (vector float)vec_or(sign, (vector unsigned int)(__vec_splatsf4(1.57079632679489661923f))); + bias = (vector float)vec_and((vector unsigned int)bias, select); + + x = vec_sel(x, inv_x, select); + + /* Instruction counts can be reduced if the polynomial was + * computed entirely from nested (dependent) fma's. However, + * to reduce the number of pipeline stalls, the polygon is evaluated + * in two halves(hi and lo). + */ + bias = vec_add(bias, x); + x2 = vec_madd(x, x, vzero); + x3 = vec_madd(x2, x, vzero); + x4 = vec_madd(x2, x2, vzero); + x8 = vec_madd(x4, x4, vzero); + x9 = vec_madd(x8, x, vzero); + hi = vec_madd(__vec_splatsf4(0.0028662257), x2, __vec_splatsf4(-0.0161657367)); + hi = vec_madd(hi, x2, __vec_splatsf4(0.0429096138)); + hi = vec_madd(hi, x2, __vec_splatsf4(-0.0752896400)); + hi = vec_madd(hi, x2, __vec_splatsf4(0.1065626393)); + lo = vec_madd(__vec_splatsf4(-0.1420889944), x2, __vec_splatsf4(0.1999355085)); + lo = vec_madd(lo, x2, __vec_splatsf4(-0.3333314528)); + lo = vec_madd(lo, x3, bias); + + result = vec_madd(hi, x9, lo); + return result; +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/cbrtf4.h b/Extras/simdmathlibrary/ppu/simdmath/cbrtf4.h new file mode 100644 index 0000000..3546b40 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/cbrtf4.h @@ -0,0 +1,97 @@ +/* cbrtf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_CBRTF4_H___ +#define ___SIMD_MATH_CBRTF4_H___ + +#include +#include + +#include +#include +#include + +static inline vector signed int +__cbrtf4_calc_quot(vector signed int n) +{ + vector signed int quot; + vector unsigned int negxexpmask = (vector unsigned int)vec_cmpgt(__vec_splatsi4(0), n); + n = vec_sel(n, vec_add(n, __vec_splatsi4(2)), negxexpmask); + + quot = vec_add(vec_sra(n, __vec_splatsu4(2)), vec_sra(n, __vec_splatsu4(4))); + quot = vec_add(quot, vec_sra(quot, __vec_splatsu4(4))); + quot = vec_add(quot, vec_sra(quot, __vec_splatsu4(8))); + quot = vec_add(quot, vec_sra(quot, __vec_splatsu4(16))); + vector signed int r = vec_sub(vec_sub(n,quot), vec_sl(quot, __vec_splatsu4(1))); + quot = vec_add(quot, + vec_sra(vec_add(vec_add(r, __vec_splatsi4(5)), + vec_sl (r, __vec_splatsu4(2))), + __vec_splatsu4(4))); + + return quot; +} + +#define __CBRTF_cbrt2 1.2599210498948731648 // 2^(1/3) +#define __CBRTF_sqr_cbrt2 1.5874010519681994748 // 2^(2/3) + +static inline vector float +_cbrtf4 (vector float x) +{ + vector float zeros = __vec_splatsf4(0.0f); + vector signed int xexp; + vector float sgnmask = (vector float)__vec_splatsi4(0x80000000); + vector unsigned int negmask = (vector unsigned int)vec_cmpgt(zeros, x); + x = vec_andc(x, sgnmask); + + x = _frexpf4(x, &xexp); + vector float p = + vec_madd(vec_madd(x, __vec_splatsf4(-0.191502161678719066f), __vec_splatsf4(0.697570460207922770f)), + x, + __vec_splatsf4(0.492659620528969547f)); + vector float p3 = vec_madd(p, vec_madd(p, p, zeros), zeros); + + vector signed int quot = __cbrtf4_calc_quot(xexp); + // mod = xexp - 3*quotient + vector signed int modval = vec_sub(vec_sub(xexp,quot), vec_sl(quot, __vec_splatsu4(1))); + vector float factor = __vec_splatsf4(1.0/__CBRTF_sqr_cbrt2); + factor = vec_sel(factor, __vec_splatsf4(1.0/__CBRTF_cbrt2), vec_cmpeq(modval, __vec_splatsi4(-1))); + factor = vec_sel(factor, __vec_splatsf4( 1.0), vec_cmpeq(modval, __vec_splatsi4( 0))); + factor = vec_sel(factor, __vec_splatsf4( __CBRTF_cbrt2), vec_cmpeq(modval, __vec_splatsi4( 1))); + factor = vec_sel(factor, __vec_splatsf4(__CBRTF_sqr_cbrt2), vec_cmpeq(modval, __vec_splatsi4( 2))); + + vector float pre = vec_madd(p, factor, zeros); + vector float numr = vec_madd(x , __vec_splatsf4(2.0f), p3); + vector float denr = vec_madd(p3, __vec_splatsf4(2.0f), x ); + vector float res = vec_madd(pre, _divf4(numr, denr), zeros); + res = _ldexpf4(res, quot); + + return vec_sel(res, vec_or(res,sgnmask), negmask); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/ceilf4.h b/Extras/simdmathlibrary/ppu/simdmath/ceilf4.h new file mode 100644 index 0000000..9235a94 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/ceilf4.h @@ -0,0 +1,42 @@ +/* ceilf4 - for each of four float slots, round up to smallest integer not less than the value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_CEILF4_H___ +#define ___SIMD_MATH_CEILF4_H___ + +#include +#include + +static inline vector float +_ceilf4(vector float x) +{ + return vec_ceil( x ); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/copysignf4.h b/Extras/simdmathlibrary/ppu/simdmath/copysignf4.h new file mode 100644 index 0000000..ad16c84 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/copysignf4.h @@ -0,0 +1,45 @@ +/* copysignf4 - for each of four float slots, return value with magnitude from x and sign from y. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_COPYSIGNF4_H___ +#define ___SIMD_MATH_COPYSIGNF4_H___ + +#include +#include + +#include + + +static inline vector float +_copysignf4(vector float x, vector float y) +{ + return vec_sel(x, y, __vec_splatsu4(0x80000000)); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/cosf4.h b/Extras/simdmathlibrary/ppu/simdmath/cosf4.h new file mode 100644 index 0000000..d774a83 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/cosf4.h @@ -0,0 +1,107 @@ +/* cosf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_COSF4_H___ +#define ___SIMD_MATH_COSF4_H___ + +#include +#include + +#include +#include + + +// +// Computes the cosine of each of the four slots +// by using a polynomial approximation. +// +static inline vector float +_cosf4 (vector float x) +{ + vector float xl,xl2,xl3,res; + vector signed int q; + + // Range reduction using : xl = angle * TwoOverPi; + // + xl = vec_madd(x, __vec_splatsf4(0.63661977236f), __vec_splatsf4(0.0f)); + + // Find the quadrant the angle falls in + // using: q = (int) (ceil(abs(xl))*sign(xl)) + // + xl = vec_add(xl, vec_sel(__vec_splatsf4(0.5f), xl, __vec_splatsu4(0x80000000))); + q = vec_cts(xl, 0); + + + // Compute an offset based on the quadrant that the angle falls in + // + vector signed int offset = vec_add(__vec_splatsi4(1), vec_and(q, __vec_splatsi4(0x3))); + + // Remainder in range [-pi/4..pi/4] + // + vector float qf = vec_ctf(q,0); + vector float p1 = vec_nmsub(qf, __vec_splatsf4(__SINCOSF_KC1), x); + xl = vec_nmsub(qf, __vec_splatsf4(__SINCOSF_KC2), p1); + + // Compute x^2 and x^3 + // + xl2 = vec_madd(xl, xl, __vec_splatsf4(0.0f)); + xl3 = vec_madd(xl2, xl, __vec_splatsf4(0.0f)); + + + // Compute both the sin and cos of the angles + // using a polynomial expression: + // cx = 1.0f + xl2 * ((C0 * xl2 + C1) * xl2 + C2), and + // sx = xl + xl3 * ((S0 * xl2 + S1) * xl2 + S2) + // + vector float ct1 = vec_madd(__vec_splatsf4(__SINCOSF_CC0), xl2, __vec_splatsf4(__SINCOSF_CC1)); + vector float st1 = vec_madd(__vec_splatsf4(__SINCOSF_SC0), xl2, __vec_splatsf4(__SINCOSF_SC1)); + + vector float ct2 = vec_madd(ct1, xl2, __vec_splatsf4(__SINCOSF_CC2)); + vector float st2 = vec_madd(st1, xl2, __vec_splatsf4(__SINCOSF_SC2)); + + vector float cx = vec_madd(ct2, xl2, __vec_splatsf4(1.0f)); + vector float sx = vec_madd(st2, xl3, xl); + + // Use the cosine when the offset is odd and the sin + // when the offset is even + // + vector unsigned int mask1 = + (vector unsigned int)vec_cmpeq(vec_and(offset, __vec_splatsi4(0x1)), __vec_splatsi4(0)); + res = vec_sel(cx, sx, mask1); + + // Flip the sign of the result when (offset mod 4) = 1 or 2 + // + vector unsigned int mask2 = + (vector unsigned int)vec_cmpeq(vec_and(offset, __vec_splatsi4(0x2)), __vec_splatsi4(0)); + res = vec_sel((vector float)vec_xor(__vec_splatsu4(0x80000000U), (vector unsigned int)res), res, mask2); + + return res; +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/divf4.h b/Extras/simdmathlibrary/ppu/simdmath/divf4.h new file mode 100644 index 0000000..67d7dae --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/divf4.h @@ -0,0 +1,51 @@ +/* divf4 - for each of four float slots, divide numer by denom. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_DIVF4_H___ +#define ___SIMD_MATH_DIVF4_H___ + +#include +#include + +#include + + +static inline vector float +_divf4 (vector float numer, vector float denom) +{ + // Reciprocal estimate and 1 Newton-Raphson iteration. + + vector float y0, y0numer; + + y0 = vec_re(denom); + y0numer = vec_madd(numer, y0, __vec_splatsf4(0.0f)); + return vec_madd(vec_nmsub(denom, y0, __vec_splatsf4(1.0f)), y0numer, y0numer); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/divi4.h b/Extras/simdmathlibrary/ppu/simdmath/divi4.h new file mode 100644 index 0000000..8290cfb --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/divi4.h @@ -0,0 +1,105 @@ +/* divi4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_DIVI4_H___ +#define ___SIMD_MATH_DIVI4_H___ + +#include +#include + +#include + +// divi4 - for each of four integer slots, compute quotient and remainder of numer/denom +// and store in divi4_t struct. Divide by zero produces quotient = 0, remainder = numerator. + +static inline divi4_t +_divi4 (vector signed int numer, vector signed int denom ) +{ + vector signed int minusone = __vec_splatsi4(-1); + vector unsigned int zero = __vec_splatsu4(0); + vector unsigned int one = __vec_splatsu4(1); + vector unsigned int k158 = __vec_splatsu4(158); + vector unsigned int k23 = __vec_splatsu4(23); + + divi4_t res; + vector unsigned int numerPos, denomPos, quotNeg; + vector unsigned int numerAbs, denomAbs; + vector unsigned int denomZeros, numerZeros, shift, denomShifted, oneShifted; + vector unsigned int quot, newQuot, skip, newNum, cont; + int anyCont; + + // determine whether result needs sign change + + numerPos = (vector unsigned int)vec_cmpgt( numer, minusone ); + denomPos = (vector unsigned int)vec_cmpgt( denom, minusone ); + quotNeg = vec_xor( numerPos, denomPos ); + + // use absolute values of numerator, denominator + + numerAbs = (vector unsigned int)vec_sel( vec_sub( (vector signed int)zero, numer ), numer, numerPos ); + denomAbs = (vector unsigned int)vec_sel( vec_sub( (vector signed int)zero, denom ), denom, denomPos ); + + // get difference of leading zeros to align denom with numer + + denomZeros = vec_sub( k158, vec_sr( (vector unsigned int)vec_ctf( denomAbs, 0 ), k23 ) ); + numerZeros = vec_sub( k158, vec_sr( (vector unsigned int)vec_ctf( numerAbs, 0 ), k23 ) ); + + shift = vec_sub( denomZeros, numerZeros ); + denomShifted = vec_sl( denomAbs, shift ); + oneShifted = vec_sl( one, shift ); + oneShifted = vec_sel( oneShifted, zero, vec_or( vec_cmpeq( denomAbs, zero ), + vec_cmpgt( denomAbs, numerAbs ) ) ); + + // long division + + quot = zero; + + do + { + cont = (vector unsigned int)vec_cmpgt( oneShifted, zero ); + anyCont = vec_any_gt( oneShifted, zero ); + skip = (vector unsigned int)vec_cmpgt( denomShifted, numerAbs ); + + newQuot = vec_or( quot, oneShifted ); + newNum = vec_sub( numerAbs, denomShifted ); + + oneShifted = vec_sr( oneShifted, one ); + denomShifted = vec_sr( denomShifted, one ); + + quot = vec_sel( newQuot, quot, skip ); + numerAbs = vec_sel( numerAbs, newNum, vec_andc( cont, skip ) ); + } + while ( anyCont ); + + res.quot = (vector signed int)vec_sel( quot, vec_sub( zero, quot ), quotNeg ); + res.rem = (vector signed int)vec_sel( (vector unsigned int)vec_sub( (vector signed int)zero, (vector signed int)numerAbs ), numerAbs, numerPos ); + return res; +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/exp2f4.h b/Extras/simdmathlibrary/ppu/simdmath/exp2f4.h new file mode 100644 index 0000000..6a4bc0f --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/exp2f4.h @@ -0,0 +1,137 @@ +/* exp2f4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_EXP2F4_H___ +#define ___SIMD_MATH_EXP2F4_H___ + +#include +#include +#include + +#include + +/* + * FUNCTION + * vector float _exp2_v(vector float x) + * + * DESCRIPTION + * _exp2_v computes 2 raised to the input vector x. Computation is + * performed by observing the 2^(a+b) = 2^a * 2^b. + * We decompose x into a and b (above) by letting. + * a = ceil(x), b = x - a; + * + * 2^a is easilty computed by placing a into the exponent + * or a floating point number whose mantissa is all zeros. + * + * 2^b is computed using the following polynomial approximation. + * (C. Hastings, Jr, 1955). + * + * __7__ + * \ + * \ + * 2^(-x) = / Ci*x^i + * /____ + * i=1 + * + * for x in the range 0.0 to 1.0 + * + * C0 = 1.0 + * C1 = -0.9999999995 + * C2 = 0.4999999206 + * C3 = -0.1666653019 + * C4 = 0.0416573475 + * C5 = -0.0083013598 + * C6 = 0.0013298820 + * C7 = -0.0001413161 + * + * This function does not handle out of range conditions. It + * assumes that x is in the range (-128.0, 127.0]. Values outside + * this range will produce undefined results. + */ + + +#define __EXP2F_LN2 0.69314718055995f /* ln(2) */ + +static inline vector float +_exp2f4 (vector float x) +{ + vector signed int ix; + vector unsigned int overflow; + vector unsigned int underflow; + vector float frac, frac2, frac4; + vector float exp_int, exp_frac; + vector float result; + vector float hi, lo; + vector float zeros = __vec_splatsf4(0.0f); + vector float bias; + /* Break in the input x into two parts ceil(x), x - ceil(x). + */ +#if 1 + bias = (vector float)(vec_sra((vector signed int)x, __vec_splatsu4(31) )); + bias = (vector float)(vec_andc(__vec_splatsu4(0x3F7FFFFF), (vector unsigned int)bias)); + ix = vec_cts(vec_add(x, bias), 0); +#else + bias = vec_sel(vec_floor(x), vec_ceil(x), vec_cmpgt(x, __vec_splatsf4(0.0f))); + ix = vec_cts(bias, 0); +#endif + frac = vec_sub(vec_ctf(ix, 0), x); + frac = vec_madd(frac, __vec_splatsf4(__EXP2F_LN2), zeros); + + overflow = (vector unsigned int)vec_cmpgt(x, (vector float)(__vec_splatsi4(0x4300FFFF))); // !!! Biggest possible exponent to fit in range. + underflow = (vector unsigned int)vec_cmpgt(__vec_splatsf4(-126.0f), x); + + exp_int = (vector float)(vec_sl(vec_add(ix, __vec_splatsi4(126)), __vec_splatsu4(23))); // !!! HRD <- add with saturation + + /* Instruction counts can be reduced if the polynomial was + * computed entirely from nested (dependent) fma's. However, + * to reduce the number of pipeline stalls, the polygon is evaluated + * in two halves (hi amd lo). + */ + frac2 = vec_madd(frac, frac, zeros); + frac4 = vec_madd(frac2, frac2, zeros); + + hi = vec_madd(frac, __vec_splatsf4(-0.0001413161), __vec_splatsf4(0.0013298820)); + hi = vec_madd(frac, hi, __vec_splatsf4(-0.0083013598)); + hi = vec_madd(frac, hi, __vec_splatsf4(0.0416573475)); + lo = vec_madd(frac, __vec_splatsf4(-0.1666653019), __vec_splatsf4(0.4999999206)); + lo = vec_madd(frac, lo, __vec_splatsf4(-0.9999999995)); + lo = vec_madd(frac, lo, __vec_splatsf4(1.0)); + + exp_frac = vec_madd(frac4, hi, lo); + result = vec_madd(exp_frac, exp_int, zeros); + result = vec_madd(exp_frac, exp_int, result); // !!! HRD + + /* Handle overflow */ + result = vec_sel(result, __vec_splatsf4(HUGE_VALF), overflow); + result = vec_sel(result, zeros, underflow); + + return (result); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/expf4.h b/Extras/simdmathlibrary/ppu/simdmath/expf4.h new file mode 100644 index 0000000..ccdf071 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/expf4.h @@ -0,0 +1,69 @@ +/* expf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_EXPF4_H___ +#define ___SIMD_MATH_EXPF4_H___ + +#include +#include + +#include +#include + +#define __EXPF_C1 -0.6931470632553101f +#define __EXPF_C2 -1.1730463525082e-7f + +#define __EXPF_INVLN2 1.4426950408889634f + +static inline vector float +_expf4 (vector float x) +{ + vector float zeros = __vec_splatsf4(0.0f); + vector unsigned int xnegmask = (vector unsigned int)vec_cmpgt(zeros, x); + vector float goffset = vec_sel(__vec_splatsf4( 0.5f),__vec_splatsf4(-0.5f),xnegmask); + vector float g = vec_madd(x, __vec_splatsf4(__EXPF_INVLN2), zeros); + vector signed int xexp = vec_cts(vec_add(g, goffset),0); + + g = vec_ctf(xexp, 0); + g = vec_madd(g, __vec_splatsf4(__EXPF_C2), vec_madd(g, __vec_splatsf4(__EXPF_C1), x)); + vector float z = vec_madd(g, g, zeros); + vector float a = vec_madd(z, __vec_splatsf4(0.0999748594f), zeros); + vector float b = vec_madd(g, + vec_madd(z, + __vec_splatsf4(0.0083208258f), + __vec_splatsf4(0.4999999992f)), + zeros); + + vector float foo = _divf4(vec_add(__vec_splatsf4(1.0f), vec_add(a, b)), + vec_add(__vec_splatsf4(1.0f), vec_sub(a, b))); + + return _ldexpf4(foo, xexp); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/expm1f4.h b/Extras/simdmathlibrary/ppu/simdmath/expm1f4.h new file mode 100644 index 0000000..4bc566f --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/expm1f4.h @@ -0,0 +1,63 @@ +/* expm1f4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_EXPM1F4_H___ +#define ___SIMD_MATH_EXPM1F4_H___ + +#include +#include + +#include + +#define __EXPM1F_ln1by2 -0.6931471805599f +#define __EXPM1F_ln3by2 0.4054651081082f + +static inline vector float +_expm1f4 (vector float x) +{ + vector float zeros = __vec_splatsf4(0.0f); + vector unsigned int nearzeromask = + (vector unsigned int)vec_and(vec_cmpgt(x, __vec_splatsf4(__EXPM1F_ln1by2)), + vec_cmpgt(__vec_splatsf4(__EXPM1F_ln3by2), x)); + vector float x2 = vec_madd(x,x,zeros); + vector float d0, d1, n0, n1; + + d0 = vec_madd(x , __vec_splatsf4(-0.3203561199f), __vec_splatsf4(0.9483177697f)); + d1 = vec_madd(x2, __vec_splatsf4( 0.0326527809f), d0); + + n0 = vec_madd(x , __vec_splatsf4(0.1538026623f), __vec_splatsf4(0.9483177732f)); + n1 = vec_madd(x , __vec_splatsf4(0.0024490478f), __vec_splatsf4(0.0305274668f)); + n1 = vec_madd(x2, n1, n0); + + return vec_sel(vec_sub(expf4(x), __vec_splatsf4(1.0f)), + vec_madd(x, divf4(n1, d1), zeros), + nearzeromask); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/fabsf4.h b/Extras/simdmathlibrary/ppu/simdmath/fabsf4.h new file mode 100644 index 0000000..e2a3fc9 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/fabsf4.h @@ -0,0 +1,42 @@ +/* fabsf4 - for each of four float slots, compute absolute value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FABSF4_H___ +#define ___SIMD_MATH_FABSF4_H___ + +#include +#include + +static inline vector float +_fabsf4(vector float x) +{ + return vec_abs( x ); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/fdimf4.h b/Extras/simdmathlibrary/ppu/simdmath/fdimf4.h new file mode 100644 index 0000000..f6b9407 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/fdimf4.h @@ -0,0 +1,45 @@ +/* fdimf - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FDIMF4_H___ +#define ___SIMD_MATH_FDIMF4_H___ + +#include +#include + +#include + +static inline vector float +_fdimf4 (vector float x, vector float y) +{ + vector float diff = vec_sub(x,y); + return vec_sel(__vec_splatsf4(0.0f), diff, vec_cmpgt(x,y)); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/floorf4.h b/Extras/simdmathlibrary/ppu/simdmath/floorf4.h new file mode 100644 index 0000000..099c7a9 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/floorf4.h @@ -0,0 +1,43 @@ +/* floorf4 - for each of four float slots, round down to largest integer not greater than the value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FLOORF4_H___ +#define ___SIMD_MATH_FLOORF4_H___ + +#include +#include + + +static inline vector float +_floorf4 (vector float x) +{ + return vec_floor( x ); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/fmaf4.h b/Extras/simdmathlibrary/ppu/simdmath/fmaf4.h new file mode 100644 index 0000000..08262f0 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/fmaf4.h @@ -0,0 +1,42 @@ +/* fmaf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FMAF4_H___ +#define ___SIMD_MATH_FMAF4_H___ + +#include +#include + +static inline vector float +_fmaf4 (vector float x, vector float y, vector float z) +{ + return vec_madd(x,y,z); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/fmaxf4.h b/Extras/simdmathlibrary/ppu/simdmath/fmaxf4.h new file mode 100644 index 0000000..e5932d1 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/fmaxf4.h @@ -0,0 +1,43 @@ +/* fmaxf4 - for each of four float slots, compute maximum of x and y + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FMAXF4_H___ +#define ___SIMD_MATH_FMAXF4_H___ + +#include +#include + + +static inline vector float +_fmaxf4 (vector float x, vector float y) +{ + return vec_max( x, y ); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/fminf4.h b/Extras/simdmathlibrary/ppu/simdmath/fminf4.h new file mode 100644 index 0000000..1bf0f09 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/fminf4.h @@ -0,0 +1,43 @@ +/* fminf4 - for each of four float slots, compute minimum of x and y + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FMINF4_H___ +#define ___SIMD_MATH_FMINF4_H___ + +#include +#include + + +static inline vector float +_fminf4 (vector float x, vector float y) +{ + return vec_min( x, y ); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/fmodf4.h b/Extras/simdmathlibrary/ppu/simdmath/fmodf4.h new file mode 100644 index 0000000..37292d3 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/fmodf4.h @@ -0,0 +1,88 @@ +/* fmodf4 - for each of four float slots, compute remainder of x/y defined as x - truncated_integer(x/y) * y. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FMODF4_H___ +#define ___SIMD_MATH_FMODF4_H___ + +#include +#include + +#include +#include +#include + +// +// This returns an accurate result when |divf4(x,y)| < 2^20 and |x| < 2^128, and otherwise returns zero. +// If x == 0, the result is 0. +// If x != 0 and y == 0, the result is undefined. + +static inline vector float +_fmodf4 (vector float x, vector float y) +{ + vector float q, xabs, yabs, qabs, xabs2; + vector signed int qi0, qi1, qi2; + vector float i0, i1, i2, r1, r2, i; + vector unsigned int inrange; + + // Find i = truncated_integer(|x/y|) + + // If |divf4(x,y)| < 2^20, the quotient is at most off by 1.0. + // Thus i is either the truncated quotient, one less, or one greater. + + q = _divf4( x, y ); + xabs = _fabsf4( x ); + yabs = _fabsf4( y ); + qabs = _fabsf4( q ); + xabs2 = vec_add( xabs, xabs ); + + inrange = (vector unsigned int)vec_cmpgt( (vector float)(__vec_splatsu4(0x49800000)), qabs ); + + qi1 = vec_cts( qabs, 0 ); + qi0 = vec_add( qi1, __vec_splatsi4(-1) ); + qi2 = vec_add( qi1, __vec_splatsi4(1) ); + + i0 = vec_ctf( qi0, 0 ); + i1 = vec_ctf( qi1, 0 ); + i2 = vec_ctf( qi2, 0 ); + + // Correct i will be the largest one such that |x| - i*|y| >= 0. + + r1 = vec_nmsub( i1, yabs, xabs ); + r2 = vec_nmsub( i2, yabs, xabs ); + + i = i0; + i = vec_sel( i1, i, vec_cmpgt( __vec_splatsi4(0), (vector signed int)r1 ) ); + i = vec_sel( i2, i, vec_cmpgt( __vec_splatsi4(0), (vector signed int)r2 ) ); + + i = _copysignf4( i, q ); + + return vec_sel( __vec_splatsf4(0.0f), vec_nmsub( i, y, x ), inrange ); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/frexpf4.h b/Extras/simdmathlibrary/ppu/simdmath/frexpf4.h new file mode 100644 index 0000000..0cb809e --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/frexpf4.h @@ -0,0 +1,54 @@ +/* frexpf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FREXPF4_H___ +#define ___SIMD_MATH_FREXPF4_H___ + +#include +#include + +#include + +static inline vector float +_frexpf4 (vector float x, vector signed int *exp) +{ + vector signed int zeros = __vec_splatsi4(0); + vector unsigned int zeromask = (vector unsigned int)vec_cmpeq(x, (vector float)zeros); + + vector signed int expmask = __vec_splatsi4(0x7F800000); + vector signed int e1 = vec_and ( (vector signed int)x, expmask); + vector signed int e2 = vec_sub(vec_sr(e1, __vec_splatsu4(23) ), __vec_splatsi4(126) ); + *exp = vec_sel(e2, zeros, zeromask); + + vector float m2 = vec_sel(x, (vector float)(__vec_splatsi4(0x3F000000)), (vector unsigned int)expmask); + + return vec_sel(m2, (vector float)zeros, zeromask); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/hypotf4.h b/Extras/simdmathlibrary/ppu/simdmath/hypotf4.h new file mode 100644 index 0000000..1e692c3 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/hypotf4.h @@ -0,0 +1,46 @@ +/* hypotf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_HYPOTF4_H___ +#define ___SIMD_MATH_HYPOTF4_H___ + +#include +#include + +#include + +static inline vector float +_hypotf4 (vector float x, vector float y) +{ + vector float sum = vec_madd( x, x, __vec_splatsf4(0.0f) ); + sum = vec_madd(y, y, sum); + return _sqrtf4(sum); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/ilogbf4.h b/Extras/simdmathlibrary/ppu/simdmath/ilogbf4.h new file mode 100644 index 0000000..2ca8287 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/ilogbf4.h @@ -0,0 +1,52 @@ +/* ilogbf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ILOGBF4_H___ +#define ___SIMD_MATH_ILOGBF4_H___ + +#include +#include +#include + +#include + +static inline vector signed int +_ilogbf4 (vector float x) +{ + vector signed int minus127 = __vec_splatsi4(-127); + + vector signed int e1 = vec_and((vector signed int)x, __vec_splatsi4(0x7F800000)); + vector unsigned int zeromask = (vector unsigned int)vec_cmpeq(e1, __vec_splatsi4(0)); + vector signed int e2 = vec_add(vec_sr(e1,__vec_splatsu4(23)), minus127); + + return vec_sel(e2, __vec_splatsi4(FP_ILOGB0), zeromask); + +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/ldexpf4.h b/Extras/simdmathlibrary/ppu/simdmath/ldexpf4.h new file mode 100644 index 0000000..05a61a2 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/ldexpf4.h @@ -0,0 +1,63 @@ +/* ldexpf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LDEXPF4_H___ +#define ___SIMD_MATH_LDEXPF4_H___ + +#include +#include + +#include + +static inline vector float +_ldexpf4 (vector float x, vector signed int exp) +{ + vector signed int zeros = __vec_splatsi4(0); + + vector signed int expmask = __vec_splatsi4(0x7F800000); + vector signed int e1 = vec_and((vector signed int)x, expmask); + vector signed int e2 = vec_sr(e1,__vec_splatsu4(23)); + + vector unsigned int maxmask = (vector unsigned int)vec_cmpgt(exp, __vec_splatsi4(255)); + vector unsigned int minmask = (vector unsigned int)vec_cmpgt(__vec_splatsi4(-255), exp); + minmask = vec_or (minmask, (vector unsigned int)vec_cmpeq(x, (vector float)zeros)); + + vector signed int esum = vec_add(e2, exp); + + maxmask = vec_or (maxmask, (vector unsigned int)vec_cmpgt(esum, __vec_splatsi4(255))); + maxmask = vec_and(maxmask, __vec_splatsu4(0x7FFFFFFF)); + minmask = vec_or (minmask, (vector unsigned int)vec_cmpgt(zeros, esum)); + + x = vec_sel(x, (vector float)vec_sl(esum,__vec_splatsu4(23)), (vector unsigned int)expmask); + x = vec_sel(x, (vector float)zeros, minmask); + x = vec_sel(x, (vector float)maxmask, maxmask); + return x; +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/log10f4.h b/Extras/simdmathlibrary/ppu/simdmath/log10f4.h new file mode 100644 index 0000000..9eeaf38 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/log10f4.h @@ -0,0 +1,83 @@ +/* log10f4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LOG10F4_H___ +#define ___SIMD_MATH_LOG10F4_H___ + +#include +#include + +#include + +#define __LOG10F_loga2msb 0.3010299205780f +#define __LOG10F_loga2lsb 7.5085978266e-8f +#define __LOG10F_logaemsb 0.4342944622040f +#define __LOG10F_logaelsb 1.9699272335e-8f +#define __LOG10F_neglogae -0.4342944819033f + +#define __LOG10F_c0 -0.2988439998f +#define __LOG10F_c1 -0.3997655209f +#define __LOG10F_c2 -0.6666679125f + +static inline vector float +_log10f4 (vector float x) +{ + vector signed int zeros = __vec_splatsi4(0); + vector float ones = __vec_splatsf4(1.0f); + + vector signed int expmask = __vec_splatsi4(0x7F800000); + vector signed int xexp = + vec_add( vec_sr(vec_and((vector signed int)x, expmask), __vec_splatsu4(23)), __vec_splatsi4(-126) ); + x = vec_sel(x, (vector float)(__vec_splatsi4(0x3F000000)), (vector unsigned int)expmask); + + vector unsigned int mask = (vector unsigned int)vec_cmpgt( __vec_splatsf4(0.7071067811865f), x); + x = vec_sel(x , vec_add(x, x) , mask); + xexp = vec_sel(xexp, vec_sub(xexp, __vec_splatsi4(1)), mask); + + vector float x1 = vec_sub(x , ones); + vector float z = _divf4 (x1, vec_add(x, ones)); + vector float w = vec_madd(z , z, (vector float)zeros); + vector float polywneg; + polywneg = vec_madd(__vec_splatsf4(__LOG10F_c0), w, __vec_splatsf4(__LOG10F_c1)); + polywneg = vec_madd(polywneg , w, __vec_splatsf4(__LOG10F_c2)); + + vector float y = vec_madd(z, vec_madd(polywneg, w, x1), (vector float)zeros); + vector float wnew = vec_ctf(xexp,0); + + vector float zz1 = vec_madd(__vec_splatsf4(__LOG10F_logaemsb), x1, + vec_madd(__vec_splatsf4(__LOG10F_loga2msb),wnew,(vector float)zeros)); + vector float zz2 = vec_madd(__vec_splatsf4(__LOG10F_logaelsb), x1, + vec_madd(__vec_splatsf4(__LOG10F_loga2lsb), wnew, + vec_madd(__vec_splatsf4(__LOG10F_neglogae),y,(vector float)zeros)) + ); + + return vec_add(zz1, zz2); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/log1pf4.h b/Extras/simdmathlibrary/ppu/simdmath/log1pf4.h new file mode 100644 index 0000000..16a9de4 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/log1pf4.h @@ -0,0 +1,61 @@ +/* log1pf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LOG1PF4_H___ +#define ___SIMD_MATH_LOG1PF4_H___ + +#include +#include + +#include +#include + +static inline vector float +_log1pf4 (vector float x) +{ + vector unsigned int nearzeromask = + (vector unsigned int)vec_and(vec_cmpgt(x, __vec_splatsf4(-0.5f)), + vec_cmpgt(__vec_splatsf4(0.5f), x)); + vector float x2 = vec_madd(x,x,__vec_splatsf4(0.0f)); + vector float d0, d1, n0, n1; + + d0 = vec_madd(x , __vec_splatsf4(1.5934420741f), __vec_splatsf4(0.8952856868f)); + d1 = vec_madd(x , __vec_splatsf4(0.1198195734f), __vec_splatsf4(0.8377145063f)); + d1 = vec_madd(x2, d1, d0); + + n0 = vec_madd(x , __vec_splatsf4(1.1457993413f), __vec_splatsf4(0.8952856678f)); + n1 = vec_madd(x , __vec_splatsf4(0.0082862580f), __vec_splatsf4(0.3394238808f)); + n1 = vec_madd(x2, n1, n0); + + return vec_sel(_logf4(vec_add(x, __vec_splatsf4(1.0f))), + vec_madd(x, _divf4(n1, d1), __vec_splatsf4(0.0f)), + nearzeromask); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/log2f4.h b/Extras/simdmathlibrary/ppu/simdmath/log2f4.h new file mode 100644 index 0000000..a8baca1 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/log2f4.h @@ -0,0 +1,77 @@ +/* log2f4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LOG2F4_H___ +#define ___SIMD_MATH_LOG2F4_H___ + +#include +#include + +#include + + +#define __LOG2F_l2emsb 1.4426950216293f +#define __LOG2F_l2elsb 1.9259629911e-8f +#define __LOG2F_negl2e -1.4426950408890f + +#define __LOG2F_c0 -0.2988439998f +#define __LOG2F_c1 -0.3997655209f +#define __LOG2F_c2 -0.6666679125f + +static inline vector float +_log2f4 (vector float x) +{ + vector signed int zeros = __vec_splatsi4(0); + vector float ones = __vec_splatsf4(1.0f); + + vector signed int expmask = __vec_splatsi4(0x7F800000); + vector signed int xexp = + vec_add( vec_sr(vec_and((vector signed int)x, expmask), __vec_splatsu4(23)), __vec_splatsi4(-126) ); + x = vec_sel(x, (vector float)(__vec_splatsi4(0x3F000000)), (vector unsigned int)expmask); + + vector unsigned int mask = (vector unsigned int)vec_cmpgt( __vec_splatsf4(0.7071067811865f), x); + x = vec_sel(x , vec_add(x, x) , mask); + xexp = vec_sel(xexp, vec_sub(xexp, __vec_splatsi4(1) ), mask); + + vector float x1 = vec_sub(x , ones); + vector float z = _divf4(x1, vec_add(x, ones)); + vector float w = vec_madd(z , z, (vector float)zeros); + vector float polywneg; + polywneg = vec_madd(__vec_splatsf4(__LOG2F_c0), w, __vec_splatsf4(__LOG2F_c1)); + polywneg = vec_madd(polywneg , w, __vec_splatsf4(__LOG2F_c2)); + + vector float y = vec_madd(z, vec_madd(polywneg, w, x1), (vector float)zeros); + vector float zz1 = vec_madd(__vec_splatsf4(__LOG2F_l2emsb), x1, vec_ctf(xexp,0)); + vector float zz2 = vec_madd(__vec_splatsf4(__LOG2F_l2elsb), x1, + vec_madd(__vec_splatsf4(__LOG2F_negl2e), y, (vector float)zeros)); + + return vec_add(zz1,zz2); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/logbf4.h b/Extras/simdmathlibrary/ppu/simdmath/logbf4.h new file mode 100644 index 0000000..b6f43d7 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/logbf4.h @@ -0,0 +1,48 @@ +/* logbf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LOGBF4_H___ +#define ___SIMD_MATH_LOGBF4_H___ + +#include +#include +#include + +#include + +static inline vector float +_logbf4 (vector float x) +{ + vector signed int e1 = vec_and((vector signed int)x, __vec_splatsi4(0x7F800000)); + vector unsigned int zeromask = (vector unsigned int)vec_cmpeq(e1, __vec_splatsi4(0)); + e1 = vec_sub(e1, __vec_splatsi4(0x3F800000)); + return vec_sel(vec_ctf(e1,23), __vec_splatsf4(-HUGE_VALF), zeromask); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/logf4.h b/Extras/simdmathlibrary/ppu/simdmath/logf4.h new file mode 100644 index 0000000..c6d66d6 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/logf4.h @@ -0,0 +1,77 @@ +/* logf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LOGF4_H___ +#define ___SIMD_MATH_LOGF4_H___ + +#include +#include + +#include + + +#define __LOGF_ln2msb 0.6931470632553f +#define __LOGF_negln2lsb -1.1730463525e-7f + +#define __LOGF_c0 -0.2988439998f +#define __LOGF_c1 -0.3997655209f +#define __LOGF_c2 -0.6666679125f + +static inline vector float +_logf4 (vector float x) +{ + vector signed int zeros = __vec_splatsi4(0); + vector float ones = __vec_splatsf4(1.0f); + + vector signed int expmask = __vec_splatsi4(0x7F800000); + vector signed int xexp = + vec_add( vec_sr(vec_and((vector signed int)x, expmask), __vec_splatsu4(23)), __vec_splatsi4(-126) ); + x = vec_sel(x, (vector float)(__vec_splatsi4(0x3F000000)), (vector unsigned int)expmask); + + + vector unsigned int mask = (vector unsigned int)vec_cmpgt(__vec_splatsf4(0.7071067811865f), x); + x = vec_sel(x , vec_add(x, x) , mask); + xexp = vec_sel(xexp, vec_sub(xexp,__vec_splatsi4(1)), mask); + + vector float x1 = vec_sub(x , ones); + vector float z = _divf4 (x1, vec_add(x, ones)); + vector float w = vec_madd(z , z, (vector float)zeros); + vector float polywneg; + polywneg = vec_madd(__vec_splatsf4(__LOGF_c0), w, __vec_splatsf4(__LOGF_c1)); + polywneg = vec_madd(polywneg , w, __vec_splatsf4(__LOGF_c2)); + + vector float y = vec_madd(z, vec_madd(polywneg, w, x1), (vector float)zeros); + vector float wnew = vec_ctf(xexp,0); + vector float zz1 = vec_madd(__vec_splatsf4(__LOGF_ln2msb) , wnew, x1); + vector float zz2neg = vec_madd(__vec_splatsf4(__LOGF_negln2lsb), wnew, y ); + + return vec_sub(zz1,zz2neg); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/modff4.h b/Extras/simdmathlibrary/ppu/simdmath/modff4.h new file mode 100644 index 0000000..3d6f7e7 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/modff4.h @@ -0,0 +1,53 @@ +/* modff4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_MODFF4_H___ +#define ___SIMD_MATH_MODFF4_H___ + +#include +#include + +#include + +// modff4 - for each of four float slots, compute fractional and integral parts. +// Returns fractional part and stores integral part in *iptr. + +static inline vector float +_modff4 (vector float x, vector float *iptr) +{ + vector float integral, fraction; + + integral = _truncf4( x ); + fraction = vec_sub( x, integral ); + + *iptr = integral; + return fraction; +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/negatef4.h b/Extras/simdmathlibrary/ppu/simdmath/negatef4.h new file mode 100644 index 0000000..292b6ab --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/negatef4.h @@ -0,0 +1,44 @@ +/* negatef4 - for each of four float slots, negate the sign bit. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_NEGATEF4_H___ +#define ___SIMD_MATH_NEGATEF4_H___ + +#include +#include + +#include + +static inline vector float +_negatef4 (vector float x) +{ + return (vector float)vec_xor( (vector unsigned int)x, __vec_splatsu4(0x80000000) ); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/negatei4.h b/Extras/simdmathlibrary/ppu/simdmath/negatei4.h new file mode 100644 index 0000000..57ddd65 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/negatei4.h @@ -0,0 +1,45 @@ +/* negatei4 - for each of four int slots, negate the sign bit. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_NEGATEI4_H___ +#define ___SIMD_MATH_NEGATEI4_H___ + +#include +#include + +#include + +static inline vector signed int +_negatei4 (vector signed int x) +{ + vector signed int zero = __vec_splatsi4(0); + return vec_sub (zero, x); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/powf4.h b/Extras/simdmathlibrary/ppu/simdmath/powf4.h new file mode 100644 index 0000000..d7fcbfd --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/powf4.h @@ -0,0 +1,61 @@ +/* exp2f4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_POWF4_H___ +#define ___SIMD_MATH_POWF4_H___ + +#include +#include +#include + +#include +#include + +static inline vector float +_powf4 (vector float x, vector float y) +{ + vector signed int zeros = __vec_splatsi4(0); + vector unsigned int zeromask = (vector unsigned int)vec_cmpeq((vector float)zeros, x); + + vector unsigned int negmask = (vector unsigned int)vec_cmpgt((vector float)zeros, x); + + vector float sbit = (vector float)(__vec_splatsi4(0x80000000)); + vector float absx = vec_andc(x, sbit); + vector float absy = vec_andc(y, sbit); + vector unsigned int oddy = vec_and(vec_ctu(absy, 0), __vec_splatsu4(0x00000001)); + negmask = vec_and(negmask, (vector unsigned int)vec_cmpgt(oddy, (vector unsigned int)zeros)); + + vector float res = _exp2f4(vec_madd(y, _log2f4(absx), (vector float)zeros)); + res = vec_sel(res, vec_or(sbit, res), negmask); + + + return vec_sel(res, (vector float)zeros, zeromask); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/recipf4.h b/Extras/simdmathlibrary/ppu/simdmath/recipf4.h new file mode 100644 index 0000000..a570986 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/recipf4.h @@ -0,0 +1,50 @@ +/* recipf4 - for each of four float slots, compute reciprocal. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_RECIPF4_H___ +#define ___SIMD_MATH_RECIPF4_H___ + +#include +#include + +#include + +static inline vector float +_recipf4 (vector float x) +{ + // Reciprocal estimate and 1 Newton-Raphson iteration. + + vector float y0; + vector float ones = __vec_splatsf4(1.0f); + + y0 = vec_re( x ); + return vec_madd( vec_nmsub( x, y0, ones), y0, y0 ); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/rsqrtf4.h b/Extras/simdmathlibrary/ppu/simdmath/rsqrtf4.h new file mode 100644 index 0000000..5fd3495 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/rsqrtf4.h @@ -0,0 +1,57 @@ +/* sqrtf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_RSQRTF4_H___ +#define ___SIMD_MATH_RSQRTF4_H___ + +#include +#include + +#include + +// rsqrtf4 - for each of four float slots, compute reciprocal square root. +// Undefined if input < 0. + +static inline vector float +_rsqrtf4 (vector float x) +{ + // Reciprocal square root estimate and 1 Newton-Raphson iteration. + + vector float zero = __vec_splatsf4(0.0f); + vector float half = __vec_splatsf4(0.5f); + vector float one = __vec_splatsf4(1.0f); + vector float y0, y0x, y0half; + + y0 = vec_rsqrte( x ); + y0x = vec_madd( y0, x, zero ); + y0half = vec_madd( y0, half, zero ); + return vec_madd( vec_nmsub( y0, y0x, one ), y0half, y0 ); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/sincosf4.h b/Extras/simdmathlibrary/ppu/simdmath/sincosf4.h new file mode 100644 index 0000000..0a0bc3e --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/sincosf4.h @@ -0,0 +1,113 @@ +/* sincosf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_SINCOSF4_H___ +#define ___SIMD_MATH_SINCOSF4_H___ + +#include +#include + +#include +#include + +// +// Computes both the sine and cosine of the all four slots of x +// by using a polynomial approximation. +// +static inline void +_sincosf4 (vector float x, vector float *s, vector float *c) +{ + vector float xl,xl2,xl3; + vector signed int q; + vector signed int offsetSin, offsetCos; + + // Range reduction using : xl = angle * TwoOverPi; + // + xl = vec_madd(x, __vec_splatsf4(0.63661977236f),__vec_splatsf4(0.0f)); + + // Find the quadrant the angle falls in + // using: q = (int) (ceil(abs(xl))*sign(xl)) + // + xl = vec_add(xl,vec_sel(__vec_splatsf4(0.5f),xl,__vec_splatsu4(0x80000000))); + q = vec_cts(xl,0); + + + // Compute the offset based on the quadrant that the angle falls in. + // Add 1 to the offset for the cosine. + // + offsetSin = vec_and(q,__vec_splatsi4((int)0x3)); + offsetCos = vec_add(__vec_splatsi4(1),offsetSin); + + // Remainder in range [-pi/4..pi/4] + // + vector float qf = vec_ctf(q,0); + vector float p1 = vec_nmsub(qf,__vec_splatsf4(__SINCOSF_KC1),x); + xl = vec_nmsub(qf,__vec_splatsf4(__SINCOSF_KC2),p1); + + // Compute x^2 and x^3 + // + xl2 = vec_madd(xl,xl,__vec_splatsf4(0.0f)); + xl3 = vec_madd(xl2,xl,__vec_splatsf4(0.0f)); + + + // Compute both the sin and cos of the angles + // using a polynomial expression: + // cx = 1.0f + xl2 * ((C0 * xl2 + C1) * xl2 + C2), and + // sx = xl + xl3 * ((S0 * xl2 + S1) * xl2 + S2) + // + vector float ct1 = vec_madd(__vec_splatsf4(__SINCOSF_CC0),xl2,__vec_splatsf4(__SINCOSF_CC1)); + vector float st1 = vec_madd(__vec_splatsf4(__SINCOSF_SC0),xl2,__vec_splatsf4(__SINCOSF_SC1)); + + vector float ct2 = vec_madd(ct1,xl2,__vec_splatsf4(__SINCOSF_CC2)); + vector float st2 = vec_madd(st1,xl2,__vec_splatsf4(__SINCOSF_SC2)); + + vector float cx = vec_madd(ct2,xl2,__vec_splatsf4(1.0f)); + vector float sx = vec_madd(st2,xl3,xl); + + // Use the cosine when the offset is odd and the sin + // when the offset is even + // + vector unsigned int sinMask = + (vector unsigned int)vec_cmpeq(vec_and(offsetSin,__vec_splatsi4(0x1)),__vec_splatsi4(0)); + vector unsigned int cosMask = + (vector unsigned int)vec_cmpeq(vec_and(offsetCos,__vec_splatsi4(0x1)),__vec_splatsi4(0)); + *s = vec_sel(cx,sx,sinMask); + *c = vec_sel(cx,sx,cosMask); + + // Flip the sign of the result when (offset mod 4) = 1 or 2 + // + sinMask = (vector unsigned int)vec_cmpeq(vec_and(offsetSin,__vec_splatsi4(0x2)),__vec_splatsi4(0)); + cosMask = (vector unsigned int)vec_cmpeq(vec_and(offsetCos,__vec_splatsi4(0x2)),__vec_splatsi4(0)); + + *s = vec_sel((vector float)vec_xor(__vec_splatsu4(0x80000000),(vector unsigned int)*s),*s,sinMask); + *c = vec_sel((vector float)vec_xor(__vec_splatsu4(0x80000000),(vector unsigned int)*c),*c,cosMask); + +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/sinf4.h b/Extras/simdmathlibrary/ppu/simdmath/sinf4.h new file mode 100644 index 0000000..12e3ec4 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/sinf4.h @@ -0,0 +1,107 @@ +/* sinf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_SINF4_H___ +#define ___SIMD_MATH_SINF4_H___ + +#include +#include + +#include +#include +// +// Computes the sine of each of the four slots +// by using a polynomial approximation. +// + +static inline vector float +_sinf4 (vector float x) +{ + vector float xl,xl2,xl3,res; + vector signed int q; + + // Range reduction using : xl = angle * TwoOverPi; + // + xl = vec_madd(x, __vec_splatsf4(0.63661977236f),__vec_splatsf4(0.0f)); + + // Find the quadrant the angle falls in + // using: q = (int) (ceil(abs(xl))*sign(xl)) + // + xl = vec_add(xl,vec_sel(__vec_splatsf4(0.5f),xl,__vec_splatsu4(0x80000000))); + q = vec_cts(xl,0); + + + // Compute an offset based on the quadrant that the angle falls in + // + vector signed int offset = vec_and(q,__vec_splatsi4((int)0x3)); + + // Remainder in range [-pi/4..pi/4] + // + vector float qf = vec_ctf(q,0); + vector float p1 = vec_nmsub(qf,__vec_splatsf4(__SINCOSF_KC1),x); + xl = vec_nmsub(qf,__vec_splatsf4(__SINCOSF_KC2),p1); + + // Compute x^2 and x^3 + // + xl2 = vec_madd(xl,xl,__vec_splatsf4(0.0f)); + xl3 = vec_madd(xl2,xl,__vec_splatsf4(0.0f)); + + + // Compute both the sin and cos of the angles + // using a polynomial expression: + // cx = 1.0f + xl2 * ((C0 * xl2 + C1) * xl2 + C2), and + // sx = xl + xl3 * ((S0 * xl2 + S1) * xl2 + S2) + // + vector float ct1 = vec_madd(__vec_splatsf4(__SINCOSF_CC0),xl2,__vec_splatsf4(__SINCOSF_CC1)); + vector float st1 = vec_madd(__vec_splatsf4(__SINCOSF_SC0),xl2,__vec_splatsf4(__SINCOSF_SC1)); + + vector float ct2 = vec_madd(ct1,xl2,__vec_splatsf4(__SINCOSF_CC2)); + vector float st2 = vec_madd(st1,xl2,__vec_splatsf4(__SINCOSF_SC2)); + + vector float cx = vec_madd(ct2,xl2,__vec_splatsf4(1.0f)); + vector float sx = vec_madd(st2,xl3,xl); + + // Use the cosine when the offset is odd and the sin + // when the offset is even + // + vector unsigned int mask1 = (vector unsigned int)vec_cmpeq(vec_and(offset, + __vec_splatsi4(0x1)), + __vec_splatsi4((int)(0))); + res = vec_sel(cx,sx,mask1); + + // Flip the sign of the result when (offset mod 4) = 1 or 2 + // + vector unsigned int mask2 = + (vector unsigned int)vec_cmpeq(vec_and(offset,__vec_splatsi4(0x2)),__vec_splatsi4((int)0)); + res = vec_sel((vector float)vec_xor(__vec_splatsu4(0x80000000U),(vector unsigned int)res),res,mask2); + + return res; +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/sqrtf4.h b/Extras/simdmathlibrary/ppu/simdmath/sqrtf4.h new file mode 100644 index 0000000..3b4a0d1 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/sqrtf4.h @@ -0,0 +1,59 @@ +/* sqrtf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_SQRTF4_H___ +#define ___SIMD_MATH_SQRTF4_H___ + +#include +#include + +#include + +// sqrtf4 - for each of four float slots, compute square root. +// Undefined if input < 0. + +static inline vector float +_sqrtf4 (vector float x) +{ + // Reciprocal square root estimate and 1 Newton-Raphson iteration. + + vector float zero = __vec_splatsf4(0.0f); + vector float half = __vec_splatsf4(0.5f); + vector float one = __vec_splatsf4(1.0f); + vector float y0, y0x, y0xhalf; + vector unsigned int cmp_zero; + + y0 = vec_rsqrte( x ); + cmp_zero = (vector unsigned int)vec_cmpeq( x, zero ); + y0x = vec_madd( y0, x, zero ); + y0xhalf = vec_madd( y0x, half, zero ); + return vec_sel( vec_madd( vec_nmsub( y0, y0x, one ), y0xhalf, y0x ), zero, cmp_zero ); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/tanf4.h b/Extras/simdmathlibrary/ppu/simdmath/tanf4.h new file mode 100644 index 0000000..cdb692a --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/tanf4.h @@ -0,0 +1,98 @@ +/* tanf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_TANF4_H___ +#define ___SIMD_MATH_TANF4_H___ + +#include +#include + +#include +#include + +// +// Computes the tangent of all four slots of x by using a polynomia approximation. +// +static inline vector float +_tanf4 (vector float x) +{ + vector float xl,xl2,xl3,res; + vector signed int q; + + // Range reduction using : xl = angle * TwoOverPi; + // + xl = vec_madd(x, __vec_splatsf4(0.63661977236f),__vec_splatsf4(0.0f)); + + // Find the quadrant the angle falls in + // using: q = (int) (ceil(abs(x))*sign(x)) + // + xl = vec_add(xl,vec_sel(__vec_splatsf4(0.5f),xl,__vec_splatsu4(0x80000000))); + q = vec_cts(xl,0); + + + // Remainder in range [-pi/4..pi/4] + // + vector float qf = vec_ctf(q,0); + vector float p1 = vec_nmsub(qf,__vec_splatsf4(__SINCOSF_KC1),x); + xl = vec_nmsub(qf,__vec_splatsf4(__SINCOSF_KC2),p1); + + // Compute x^2 and x^3 + // + xl2 = vec_madd(xl,xl,__vec_splatsf4(0.0f)); + xl3 = vec_madd(xl2,xl,__vec_splatsf4(0.0f)); + + // Compute both the sin and cos of the angles + // using a polynomial expression: + // cx = 1.0f + x2 * (C0 * x2 + C1), and + // sx = xl + x3 * S0 + // + vector float ct2 = vec_madd(__vec_splatsf4( 0.0097099364f),xl2,__vec_splatsf4(-0.4291161787f)); + + vector float cx = vec_madd(ct2,xl2,__vec_splatsf4(1.0f)); + vector float sx = vec_madd(__vec_splatsf4(-0.0957822992f),xl3,xl); + + + // Compute both cx/sx and sx/cx + // + vector float cxosx = _divf4(cx,sx); + vector float sxocx = _divf4(sx,cx); + + vector float ncxosx = (vector float)vec_xor(__vec_splatsu4(0x80000000),(vector unsigned int)cxosx); + + // For odd numbered quadrants return -cx/sx , otherwise return + // sx/cx + // + vector unsigned int mask = + (vector unsigned int)vec_cmpeq(vec_and(q,__vec_splatsi4(0x1)),__vec_splatsi4(0)); + res = vec_sel(ncxosx,sxocx,mask); + + return res; +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/simdmath/truncf4.h b/Extras/simdmathlibrary/ppu/simdmath/truncf4.h new file mode 100644 index 0000000..ab0edad --- /dev/null +++ b/Extras/simdmathlibrary/ppu/simdmath/truncf4.h @@ -0,0 +1,43 @@ +/* truncf4 - for each of four float slots, round towards zero to integer value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_TRUNCF4_H___ +#define ___SIMD_MATH_TRUNCF4_H___ + +#include +#include + + +static inline vector float +_truncf4 (vector float x) +{ + return vec_trunc( x ); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/tests/Makefile b/Extras/simdmathlibrary/ppu/tests/Makefile new file mode 100644 index 0000000..a65d050 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/Makefile @@ -0,0 +1,41 @@ +# Makefile for testsuite for the PPU SIMD math library +# Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. +# 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 Sony Computer Entertainment Inc 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. + +topdir = ../.. +ARCH = ppu + +include $(topdir)/Make.defs + +TESTS = fabsf4 absi4 truncf4 sqrtf4 negatef4 \ + copysignf4 modff4 fminf4_fmaxf4 \ + floorf4 recipf4 ceilf4 divf4 divi4 \ + rsqrtf4 fmodf4 negatei4 + +OBJS = testutils.o + +include $(topdir)/Make.test diff --git a/Extras/simdmathlibrary/ppu/tests/absi4.c b/Extras/simdmathlibrary/ppu/tests/absi4.c new file mode 100644 index 0000000..926e8d9 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/absi4.c @@ -0,0 +1,73 @@ +/* Testcase for absi4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "common-test.h" +#include "testutils.h" +#include "simdmath.h" +int main() +{ + TEST_SET_START("20040908101807EJL","EJL", "abs"); + + int x0n = hide_int(0); + int x0p = hide_int(0); + int x1n = hide_int(-1); + int x1p = hide_int(1); + int x2n = hide_int(-83532); + int x2p = hide_int(83532); + + vec_int4 x0n_v = vec_splat_int(x0n); + vec_int4 x0p_v = vec_splat_int(x0p); + vec_int4 x1n_v = vec_splat_int(x1n); + vec_int4 x1p_v = vec_splat_int(x1p); + vec_int4 x2n_v = vec_splat_int(x2n); + vec_int4 x2p_v = vec_splat_int(x2p); + + vec_int4 res_v; + + TEST_START("absi4"); + res_v = absi4(x0n_v); + TEST_CHECK("20040908103824EJL", allequal_int4( res_v, x0p_v ), 0); + res_v = absi4(x0p_v); + TEST_CHECK("20040908103903EJL", allequal_int4( res_v, x0p_v ), 0); + res_v = absi4(x1n_v); + TEST_CHECK("20040908103905EJL", allequal_int4( res_v, x1p_v ), 0); + res_v = absi4(x1p_v); + TEST_CHECK("20040908114003EJL", allequal_int4( res_v, x1p_v ), 0); + res_v = absi4(x2n_v); + TEST_CHECK("20040908114714EJL", allequal_int4( res_v, x2p_v ), 0); + res_v = absi4(x2p_v); + TEST_CHECK("20040908114715EJL", allequal_int4( res_v, x2p_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/ppu/tests/ceilf4.c b/Extras/simdmathlibrary/ppu/tests/ceilf4.c new file mode 100644 index 0000000..e06c0f7 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/ceilf4.c @@ -0,0 +1,92 @@ +/* Testcase for ceilf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "common-test.h" +#include "testutils.h" +#include "simdmath.h" + + +int main() +{ + TEST_SET_START("20040916103300EJL","EJL", "ceilf"); + + unsigned int i3 = 0x4affffff; // 2^23 - 0.5, largest truncatable value. + unsigned int i3i = 0x4b000000; + unsigned int i4 = 0x4b000000; // 2^23, no fractional part. + unsigned int i5 = 0xcf000001; // -2^31, one more large, and negative, value. + + float x0 = hide_float(0.91825f); + float x0i = hide_float(1.0f); + float x1 = hide_float(-0.12958f); + float x1i = hide_float(0.0f); + float x2 = hide_float(-79615.1875f); + float x2i = hide_float(-79615.0f); + float x3 = hide_float(make_float(i3)); + float x3i = hide_float(make_float(i3i)); + float x4 = hide_float(make_float(i4)); + float x4i = hide_float(make_float(i4)); + float x5 = hide_float(make_float(i5)); + float x5i = hide_float(make_float(i5)); + + vec_float4 x0_v = vec_splat_float(x0); + vec_float4 x0i_v = vec_splat_float(x0i); + vec_float4 x1_v = vec_splat_float(x1); + vec_float4 x1i_v = vec_splat_float(x1i); + vec_float4 x2_v = vec_splat_float(x2); + vec_float4 x2i_v = vec_splat_float(x2i); + vec_float4 x3_v = vec_splat_float(x3); + vec_float4 x3i_v = vec_splat_float(x3i); + vec_float4 x4_v = vec_splat_float(x4); + vec_float4 x4i_v = vec_splat_float(x4i); + vec_float4 x5_v = vec_splat_float(x5); + vec_float4 x5i_v = vec_splat_float(x5i); + + vec_float4 res_v; + + TEST_START("ceilf4"); + res_v = ceilf4(x0_v); + TEST_CHECK("20040916103310EJL", allequal_float4( res_v, x0i_v ), 0); + res_v = ceilf4(x1_v); + TEST_CHECK("20040916103324EJL", allequal_float4( res_v, x1i_v ), 0); + res_v = ceilf4(x2_v); + TEST_CHECK("20040916103334EJL", allequal_float4( res_v, x2i_v ), 0); + res_v = ceilf4(x3_v); + TEST_CHECK("20040916103341EJL", allequal_float4( res_v, x3i_v ), 0); + res_v = ceilf4(x4_v); + TEST_CHECK("20040916103350EJL", allequal_float4( res_v, x4i_v ), 0); + res_v = ceilf4(x5_v); + TEST_CHECK("20040916103357EJL", allequal_float4( res_v, x5i_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/ppu/tests/copysignf4.c b/Extras/simdmathlibrary/ppu/tests/copysignf4.c new file mode 100644 index 0000000..db7adcb --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/copysignf4.c @@ -0,0 +1,67 @@ +/* Testcase for copysignf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "common-test.h" +#include "testutils.h" +#include "simdmath.h" + +int main() +{ + TEST_SET_START("20040917114054EJL", "EJL", "copysignf"); + + float x0m = hide_float(1989.0f); + float x0s = hide_float(-319875.0f); + float x0c = hide_float(-1989.0f); + float x1m = hide_float(9013.0f); + float x1s = hide_float(185.0f); + float x1c = hide_float(9013.0f); + + vec_float4 x0m_v = vec_splat_float(x0m); + vec_float4 x0s_v = vec_splat_float(x0s); + vec_float4 x0c_v = vec_splat_float(x0c); + + vec_float4 x1m_v = vec_splat_float(x1m); + vec_float4 x1s_v = vec_splat_float(x1s); + vec_float4 x1c_v = vec_splat_float(x1c); + + vec_float4 res_v; + + TEST_START("copysignf4"); + res_v = copysignf4( x0m_v, x0s_v ); + TEST_CHECK("20040917114058EJL", allequal_float4( res_v, x0c_v ), 0); + res_v = copysignf4( x1m_v, x1s_v ); + TEST_CHECK("20040917114100EJL", allequal_float4( res_v, x1c_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/ppu/tests/divf4.c b/Extras/simdmathlibrary/ppu/tests/divf4.c new file mode 100644 index 0000000..8816b7e --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/divf4.c @@ -0,0 +1,128 @@ +/* Testcase for divf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "common-test.h" +#include "testutils.h" +#include "simdmath.h" + + +int main() +{ + TEST_SET_START("20040928105926EJL","EJL", "divf4"); + + unsigned int i0n = 0x75013340; + unsigned int i0d = 0x75e7753f; + unsigned int i0r = 0x3e8ee64b; + unsigned int i1n = 0x4c7fed5a; + unsigned int i1d = 0x3a0731f0; + unsigned int i1r = 0x51f24e86; + unsigned int i2n = 0x5b08b303; + unsigned int i2d = 0x562f5046; + unsigned int i2r = 0x44479d24; + unsigned int i3n = 0x748a9b87; + unsigned int i3d = 0x6b014b46; + unsigned int i3r = 0x49093864; + unsigned int i4n = 0x35dcf9d8; + unsigned int i4d = 0x6278d6e0; + unsigned int i4r = 0x12e355b5; + unsigned int i5n = 0x74d505fd; + unsigned int i5d = 0x61ef565e; + unsigned int i5r = 0x5263daa3; + + float x0n = hide_float(make_float(i0n)); + float x0d = hide_float(make_float(i0d)); + float x0r = hide_float(make_float(i0r)); + + float x1n = hide_float(make_float(i1n)); + float x1d = hide_float(make_float(i1d)); + float x1r = hide_float(make_float(i1r)); + + float x2n = hide_float(make_float(i2n)); + float x2d = hide_float(make_float(i2d)); + float x2r = hide_float(make_float(i2r)); + + float x3n = hide_float(make_float(i3n)); + float x3d = hide_float(make_float(i3d)); + float x3r = hide_float(make_float(i3r)); + + float x4n = hide_float(make_float(i4n)); + float x4d = hide_float(make_float(i4d)); + float x4r = hide_float(make_float(i4r)); + + float x5n = hide_float(make_float(i5n)); + float x5d = hide_float(make_float(i5d)); + float x5r = hide_float(make_float(i5r)); + + vec_float4 x0n_v = vec_splat_float(x0n); + vec_float4 x0d_v = vec_splat_float(x0d); + vec_float4 x0r_v = vec_splat_float(x0r); + + vec_float4 x1n_v = vec_splat_float(x1n); + vec_float4 x1d_v = vec_splat_float(x1d); + vec_float4 x1r_v = vec_splat_float(x1r); + + vec_float4 x2n_v = vec_splat_float(x2n); + vec_float4 x2d_v = vec_splat_float(x2d); + vec_float4 x2r_v = vec_splat_float(x2r); + + vec_float4 x3n_v = vec_splat_float(x3n); + vec_float4 x3d_v = vec_splat_float(x3d); + vec_float4 x3r_v = vec_splat_float(x3r); + + vec_float4 x4n_v = vec_splat_float(x4n); + vec_float4 x4d_v = vec_splat_float(x4d); + vec_float4 x4r_v = vec_splat_float(x4r); + + vec_float4 x5n_v = vec_splat_float(x5n); + vec_float4 x5d_v = vec_splat_float(x5d); + vec_float4 x5r_v = vec_splat_float(x5r); + + vec_float4 res_v; + + TEST_START("divf4"); + res_v = divf4(x0n_v, x0d_v); + TEST_CHECK("20040928105932EJL", allequal_ulps_float4( res_v, x0r_v, 2 ), 0); + res_v = divf4(x1n_v, x1d_v); + TEST_CHECK("20040928105934EJL", allequal_ulps_float4( res_v, x1r_v, 2 ), 0); + res_v = divf4(x2n_v, x2d_v); + TEST_CHECK("20040928105936EJL", allequal_ulps_float4( res_v, x2r_v, 2 ), 0); + res_v = divf4(x3n_v, x3d_v); + TEST_CHECK("20040928105938EJL", allequal_ulps_float4( res_v, x3r_v, 2 ), 0); + res_v = divf4(x4n_v, x4d_v); + TEST_CHECK("20040928105940EJL", allequal_ulps_float4( res_v, x4r_v, 2 ), 0); + res_v = divf4(x5n_v, x5d_v); + TEST_CHECK("20040928105943EJL", allequal_ulps_float4( res_v, x5r_v, 2 ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/ppu/tests/divi4.c b/Extras/simdmathlibrary/ppu/tests/divi4.c new file mode 100644 index 0000000..701c1ce --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/divi4.c @@ -0,0 +1,124 @@ +/* Testcase for divi4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "common-test.h" +#include "testutils.h" +#include "simdmath.h" + + + +int main() +{ + TEST_SET_START("20040928161739EJL","EJL", "divi4"); + + int x0n = 0xffccb78d; + int x0d = 0x0 ; + int x0q = 0x0 ; + int x0r = 0xffccb78d; + int x1n = 0x0; + int x1d = 0xff976bb6; + int x1q = 0x0 ; + int x1r = 0x0; + int x2n = 0x0; + int x2d = 0x0; + int x2q = 0x0 ; + int x2r = 0x0; + int x3n = 0xf0e91618; + int x3d = 0xfddff7ac; + int x3q = 0x7 ; + int x3r = 0xffc95064; + + int x4n = 0xf2128d9d; + int x4d = 0xe0f76 ; + int x4q = 0xffffff03; + int x4r = 0xfff7d53b; + int x5n = 0xda1ba2ce; + int x5d = 0x4c9 ; + int x5q = 0xfff814d3; + int x5r = 0xfffffd23; + int x6n = 0xdd4426a6; + int x6d = 0xf8d245cf; + int x6q = 0x4 ; + int x6r = 0xf9fb0f6a; + int x7n = 0xd1d5ae9 ; + int x7d = 0x333ab105; + int x7q = 0x0 ; + int x7r = 0xd1d5ae9 ; + + int x8n = 0x3e0c6 ; + int x8d = 0xfff24255; + int x8q = 0x0 ; + int x8r = 0x3e0c6 ; + int x9n = 0xfd6fe27e; + int x9d = 0xf32454 ; + int x9q = 0xfffffffe; + int x9r = 0xff562b26; + int x10n =0xfb150f79; + int x10d =0xf521 ; + int x10q =0xfffffade; + int x10r =0xffff42db; + int x11n =0xfe88071f; + int x11d =0xfff937c2; + int x11q =0x37 ; + int x11r =0xfffd0c71; + + + vec_int4 x0n_v = (vec_int4){ x0n, x1n, x2n, x3n }; + vec_int4 x1n_v = (vec_int4){ x4n, x5n, x6n, x7n }; + vec_int4 x2n_v = (vec_int4){ x8n, x9n, x10n, x11n }; + + vec_int4 x0d_v = (vec_int4){ x0d, x1d, x2d, x3d }; + vec_int4 x1d_v = (vec_int4){ x4d, x5d, x6d, x7d }; + vec_int4 x2d_v = (vec_int4){ x8d, x9d, x10d, x11d }; + + vec_int4 x0q_v = (vec_int4){ x0q, x1q, x2q, x3q }; + vec_int4 x1q_v = (vec_int4){ x4q, x5q, x6q, x7q }; + vec_int4 x2q_v = (vec_int4){ x8q, x9q, x10q, x11q }; + + vec_int4 x0r_v = (vec_int4){ x0r, x1r, x2r, x3r }; + vec_int4 x1r_v = (vec_int4){ x4r, x5r, x6r, x7r }; + vec_int4 x2r_v = (vec_int4){ x8r, x9r, x10r, x11r }; + + divi4_t res; + + TEST_START("divi4"); + res = divi4(x0n_v, x0d_v); + TEST_CHECK("20040928161846EJL", allequal_int4( res.quot, x0q_v ) && allequal_int4( res.rem, x0r_v ), 0); + res = divi4(x1n_v, x1d_v); + TEST_CHECK("20040928161851EJL", allequal_int4( res.quot, x1q_v ) && allequal_int4( res.rem, x1r_v ), 0); + res = divi4(x2n_v, x2d_v); + TEST_CHECK("20040928161855EJL", allequal_int4( res.quot, x2q_v ) && allequal_int4( res.rem, x2r_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/ppu/tests/fabsf4.c b/Extras/simdmathlibrary/ppu/tests/fabsf4.c new file mode 100644 index 0000000..4864e46 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/fabsf4.c @@ -0,0 +1,85 @@ +/* Testcase for fabsf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "common-test.h" +#include "testutils.h" +#include "simdmath.h" + +int main() +{ + TEST_SET_START("20040915032605EJL","EJL", "fabsf"); + + unsigned int i3n = 0xff000000; + unsigned int i3p = 0x7f000000; + + float x0n = hide_float(-0.0f); + float x0p = hide_float(0.0f); + float x1n = hide_float(-83532.96153153f); + float x1p = hide_float(83532.96153153f); + float x2n = hide_float(-0.0000000013152f); + float x2p = hide_float(0.0000000013152f); + float x3n = hide_float(make_float(i3n)); + float x3p = hide_float(make_float(i3p)); + + vec_float4 x0n_v = vec_splat_float(x0n); + vec_float4 x0p_v = vec_splat_float(x0p); + vec_float4 x1n_v = vec_splat_float(x1n); + vec_float4 x1p_v = vec_splat_float(x1p); + vec_float4 x2n_v = vec_splat_float(x2n); + vec_float4 x2p_v = vec_splat_float(x2p); + vec_float4 x3n_v = vec_splat_float(x3n); + vec_float4 x3p_v = vec_splat_float(x3p); + + vec_float4 res_v; + + TEST_START("fabsf4"); + res_v = fabsf4(x0n_v); + TEST_CHECK("20040915032618EJL", allequal_float4( res_v, x0p_v ), 0); + res_v = fabsf4(x0p_v); + TEST_CHECK("20040915032632EJL", allequal_float4( res_v, x0p_v ), 0); + res_v = fabsf4(x1n_v); + TEST_CHECK("20040915032643EJL", allequal_float4( res_v, x1p_v ), 0); + res_v = fabsf4(x1p_v); + TEST_CHECK("20040915032654EJL", allequal_float4( res_v, x1p_v ), 0); + res_v = fabsf4(x2n_v); + TEST_CHECK("20040915032704EJL", allequal_float4( res_v, x2p_v ), 0); + res_v = fabsf4(x2p_v); + TEST_CHECK("20040915032712EJL", allequal_float4( res_v, x2p_v ), 0); + res_v = fabsf4(x3n_v); + TEST_CHECK("20040915032719EJL", allequal_float4( res_v, x3p_v ), 0); + res_v = fabsf4(x3p_v); + TEST_CHECK("20040915032729EJL", allequal_float4( res_v, x3p_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/ppu/tests/floorf4.c b/Extras/simdmathlibrary/ppu/tests/floorf4.c new file mode 100644 index 0000000..26435ea --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/floorf4.c @@ -0,0 +1,92 @@ +/* Testcase for floorf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "common-test.h" +#include "testutils.h" +#include "simdmath.h" + + +int main() +{ + TEST_SET_START("20040916145017EJL","EJL", "floorf"); + + unsigned int i3 = 0x4affffff; // 2^23 - 0.5, largest truncatable value. + unsigned int i3i = 0x4afffffe; + unsigned int i4 = 0x4b000000; // 2^23, no fractional part. + unsigned int i5 = 0xcf000001; // -2^31, one more large, and negative, value. + + float x0 = hide_float(0.91825f); + float x0i = hide_float(0.0f); + float x1 = hide_float(-0.12958f); + float x1i = hide_float(-1.0f); + float x2 = hide_float(-79615.1875f); + float x2i = hide_float(-79616.0f); + float x3 = hide_float(make_float(i3)); + float x3i = hide_float(make_float(i3i)); + float x4 = hide_float(make_float(i4)); + float x4i = hide_float(make_float(i4)); + float x5 = hide_float(make_float(i5)); + float x5i = hide_float(make_float(i5)); + + vec_float4 x0_v = vec_splat_float(x0); + vec_float4 x0i_v = vec_splat_float(x0i); + vec_float4 x1_v = vec_splat_float(x1); + vec_float4 x1i_v = vec_splat_float(x1i); + vec_float4 x2_v = vec_splat_float(x2); + vec_float4 x2i_v = vec_splat_float(x2i); + vec_float4 x3_v = vec_splat_float(x3); + vec_float4 x3i_v = vec_splat_float(x3i); + vec_float4 x4_v = vec_splat_float(x4); + vec_float4 x4i_v = vec_splat_float(x4i); + vec_float4 x5_v = vec_splat_float(x5); + vec_float4 x5i_v = vec_splat_float(x5i); + + vec_float4 res_v; + + TEST_START("floorf4"); + res_v = floorf4(x0_v); + TEST_CHECK("20040916145022EJL", allequal_float4( res_v, x0i_v ), 0); + res_v = floorf4(x1_v); + TEST_CHECK("20040916145024EJL", allequal_float4( res_v, x1i_v ), 0); + res_v = floorf4(x2_v); + TEST_CHECK("20040916145027EJL", allequal_float4( res_v, x2i_v ), 0); + res_v = floorf4(x3_v); + TEST_CHECK("20040916145029EJL", allequal_float4( res_v, x3i_v ), 0); + res_v = floorf4(x4_v); + TEST_CHECK("20040916145032EJL", allequal_float4( res_v, x4i_v ), 0); + res_v = floorf4(x5_v); + TEST_CHECK("20040916145034EJL", allequal_float4( res_v, x5i_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/ppu/tests/fminf4_fmaxf4.c b/Extras/simdmathlibrary/ppu/tests/fminf4_fmaxf4.c new file mode 100644 index 0000000..5c45fa4 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/fminf4_fmaxf4.c @@ -0,0 +1,91 @@ +/* Testcase for fminf4 and fmaxf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "common-test.h" +#include "testutils.h" +#include "simdmath.h" + +int main() +{ + TEST_SET_START("20040928184342EJL","EJL", "fminf4_fmaxf4"); + + float x0min = hide_float(1760.135f); + float x0max = hide_float(19355.03f); + + float x1min = hide_float(-12351.9f); + float x1max = hide_float(-139.035f); + + float x2min = hide_float(-1.0); + float x2max = hide_float(0.0); + + vec_float4 x0min_v = vec_splat_float(x0min); + vec_float4 x0max_v = vec_splat_float(x0max); + + vec_float4 x1min_v = vec_splat_float(x1min); + vec_float4 x1max_v = vec_splat_float(x1max); + + vec_float4 x2min_v = vec_splat_float(x2min); + vec_float4 x2max_v = vec_splat_float(x2max); + + vec_float4 res_v; + + TEST_START("fminf4"); + res_v = fminf4(x0min_v, x0max_v); + TEST_CHECK("20040928184345EJL", allequal_float4( res_v, x0min_v ), 0); + res_v = fminf4(x0max_v, x0min_v); + TEST_CHECK("20040928184349EJL", allequal_float4( res_v, x0min_v ), 0); + res_v = fminf4(x1min_v, x1max_v); + TEST_CHECK("20040928184351EJL", allequal_float4( res_v, x1min_v ), 0); + res_v = fminf4(x1max_v, x1min_v); + TEST_CHECK("20040928184353EJL", allequal_float4( res_v, x1min_v ), 0); + res_v = fminf4(x2min_v, x2max_v); + TEST_CHECK("20040928184354EJL", allequal_float4( res_v, x2min_v ), 0); + res_v = fminf4(x2max_v, x2min_v); + TEST_CHECK("20040928184356EJL", allequal_float4( res_v, x2min_v ), 0); + + TEST_START("fmaxf4"); + res_v = fmaxf4(x0min_v, x0max_v); + TEST_CHECK("20040928184411EJL", allequal_float4( res_v, x0max_v ), 0); + res_v = fmaxf4(x0max_v, x0min_v); + TEST_CHECK("20040928184413EJL", allequal_float4( res_v, x0max_v ), 0); + res_v = fmaxf4(x1min_v, x1max_v); + TEST_CHECK("20040928184415EJL", allequal_float4( res_v, x1max_v ), 0); + res_v = fmaxf4(x1max_v, x1min_v); + TEST_CHECK("20040928184416EJL", allequal_float4( res_v, x1max_v ), 0); + res_v = fmaxf4(x2min_v, x2max_v); + TEST_CHECK("20040928184417EJL", allequal_float4( res_v, x2max_v ), 0); + res_v = fmaxf4(x2max_v, x2min_v); + TEST_CHECK("20040928184419EJL", allequal_float4( res_v, x2max_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/ppu/tests/fmodf4.c b/Extras/simdmathlibrary/ppu/tests/fmodf4.c new file mode 100644 index 0000000..9574e88 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/fmodf4.c @@ -0,0 +1,129 @@ +/* Testcase for fmodf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "common-test.h" +#include "testutils.h" +#include "simdmath.h" + + + +int main() +{ + TEST_SET_START("20040928191240EJL","EJL", "fmodf4"); + + unsigned int i0n = 0x449edbc6; + unsigned int i0d = 0x40cf799d; + unsigned int i0r = 0x3daa7300; + unsigned int i1n = 0x6bca107a; + unsigned int i1d = 0x6c4a107a; + unsigned int i1r = 0x6bca107a; + unsigned int i2n = 0x1c123605; + unsigned int i2d = 0x1c923602; + unsigned int i2r = 0x1c123605; + unsigned int i3n = 0x2b4c50fa; + unsigned int i3d = 0x253a3ae3; + unsigned int i3r = 0x25141df9; + unsigned int i4n = 0x73addffc; + unsigned int i4d = 0x742ddffc; + unsigned int i4r = 0x73addffc; + unsigned int i5n = 0x29d4d97c; + unsigned int i5d = 0x2a546e77; + unsigned int i5r = 0x29d4d97c; + + float x0n = hide_float(make_float(i0n)); + float x0d = hide_float(make_float(i0d)); + float x0r = hide_float(make_float(i0r)); + + float x1n = hide_float(make_float(i1n)); + float x1d = hide_float(make_float(i1d)); + float x1r = hide_float(make_float(i1r)); + + float x2n = hide_float(make_float(i2n)); + float x2d = hide_float(make_float(i2d)); + float x2r = hide_float(make_float(i2r)); + + float x3n = hide_float(make_float(i3n)); + float x3d = hide_float(make_float(i3d)); + float x3r = hide_float(make_float(i3r)); + + float x4n = hide_float(make_float(i4n)); + float x4d = hide_float(make_float(i4d)); + float x4r = hide_float(make_float(i4r)); + + float x5n = hide_float(make_float(i5n)); + float x5d = hide_float(make_float(i5d)); + float x5r = hide_float(make_float(i5r)); + + vec_float4 x0n_v = vec_splat_float(x0n); + vec_float4 x0d_v = vec_splat_float(x0d); + vec_float4 x0r_v = vec_splat_float(x0r); + + vec_float4 x1n_v = vec_splat_float(x1n); + vec_float4 x1d_v = vec_splat_float(x1d); + vec_float4 x1r_v = vec_splat_float(x1r); + + vec_float4 x2n_v = vec_splat_float(x2n); + vec_float4 x2d_v = vec_splat_float(x2d); + vec_float4 x2r_v = vec_splat_float(x2r); + + vec_float4 x3n_v = vec_splat_float(x3n); + vec_float4 x3d_v = vec_splat_float(x3d); + vec_float4 x3r_v = vec_splat_float(x3r); + + vec_float4 x4n_v = vec_splat_float(x4n); + vec_float4 x4d_v = vec_splat_float(x4d); + vec_float4 x4r_v = vec_splat_float(x4r); + + vec_float4 x5n_v = vec_splat_float(x5n); + vec_float4 x5d_v = vec_splat_float(x5d); + vec_float4 x5r_v = vec_splat_float(x5r); + + vec_float4 res_v; + + TEST_START("fmodf4"); + res_v = fmodf4(x0n_v, x0d_v); + TEST_CHECK("20040928191245EJL", allequal_ulps_float4( res_v, x0r_v, 1 ), 0); + res_v = fmodf4(x1n_v, x1d_v); + TEST_CHECK("20040928191247EJL", allequal_ulps_float4( res_v, x1r_v, 1 ), 0); + res_v = fmodf4(x2n_v, x2d_v); + TEST_CHECK("20040928191249EJL", allequal_ulps_float4( res_v, x2r_v, 1 ), 0); + res_v = fmodf4(x3n_v, x3d_v); + TEST_CHECK("20040928191251EJL", allequal_ulps_float4( res_v, x3r_v, 1 ), 0); + res_v = fmodf4(x4n_v, x4d_v); + TEST_CHECK("20040928191253EJL", allequal_ulps_float4( res_v, x4r_v, 1 ), 0); + res_v = fmodf4(x5n_v, x5d_v); + TEST_CHECK("20040928191255EJL", allequal_ulps_float4( res_v, x5r_v, 1 ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/ppu/tests/modff4.c b/Extras/simdmathlibrary/ppu/tests/modff4.c new file mode 100644 index 0000000..1379fa2 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/modff4.c @@ -0,0 +1,108 @@ +/* Testcase for modff4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "common-test.h" +#include "testutils.h" +#include "simdmath.h" + +int main() +{ + TEST_SET_START("20040916170642EJL", "EJL", "modff"); + + unsigned int i3 = 0x4affffff; // 2^23 - 0.5, largest truncatable value. + unsigned int i3i = 0x4afffffe; + unsigned int i4 = 0x4b000000; // 2^23, no fractional part. + unsigned int i5 = 0xcf000001; // -2^31, one more large, and negative, value. + + float x0 = hide_float(0.91825f); + float x0i = hide_float(0.0f); + float x0f = hide_float(0.91825f); + + float x1 = hide_float(-0.12958f); + float x1i = hide_float(0.0f); + float x1f = hide_float(-0.12958f); + + float x2 = hide_float(-79615.1875f); + float x2i = hide_float(-79615.0f); + float x2f = hide_float(-0.1875f); + + float x3 = hide_float(make_float(i3)); + float x3i = hide_float(make_float(i3i)); + float x3f = hide_float(0.5f); + + float x4 = hide_float(make_float(i4)); + float x4i = hide_float(make_float(i4)); + float x4f = hide_float(0.0f); + + float x5 = hide_float(make_float(i5)); + float x5i = hide_float(make_float(i5)); + float x5f = hide_float(0.0f); + + vec_float4 x0_v = vec_splat_float(x0); + vec_float4 x0i_v = vec_splat_float(x0i); + vec_float4 x0f_v = vec_splat_float(x0f); + vec_float4 x1_v = vec_splat_float(x1); + vec_float4 x1i_v = vec_splat_float(x1i); + vec_float4 x1f_v = vec_splat_float(x1f); + vec_float4 x2_v = vec_splat_float(x2); + vec_float4 x2i_v = vec_splat_float(x2i); + vec_float4 x2f_v = vec_splat_float(x2f); + vec_float4 x3_v = vec_splat_float(x3); + vec_float4 x3i_v = vec_splat_float(x3i); + vec_float4 x3f_v = vec_splat_float(x3f); + vec_float4 x4_v = vec_splat_float(x4); + vec_float4 x4i_v = vec_splat_float(x4i); + vec_float4 x4f_v = vec_splat_float(x4f); + vec_float4 x5_v = vec_splat_float(x5); + vec_float4 x5i_v = vec_splat_float(x5i); + vec_float4 x5f_v = vec_splat_float(x5f); + + vec_float4 integer_v, fraction_v; + + TEST_START("modff4"); + fraction_v = modff4(x0_v, &integer_v); + TEST_CHECK("20040916170647EJL", allequal_float4( integer_v, x0i_v ) && allequal_float4( fraction_v, x0f_v ), 0); + fraction_v = modff4(x1_v, &integer_v); + TEST_CHECK("20040916170650EJL", allequal_float4( integer_v, x1i_v ) && allequal_float4( fraction_v, x1f_v ), 0); + fraction_v = modff4(x2_v, &integer_v); + TEST_CHECK("20040916170653EJL", allequal_float4( integer_v, x2i_v ) && allequal_float4( fraction_v, x2f_v ), 0); + fraction_v = modff4(x3_v, &integer_v); + TEST_CHECK("20040916170656EJL", allequal_float4( integer_v, x3i_v ) && allequal_float4( fraction_v, x3f_v ), 0); + fraction_v = modff4(x4_v, &integer_v); + TEST_CHECK("20040916170658EJL", allequal_float4( integer_v, x4i_v ) && allequal_float4( fraction_v, x4f_v ), 0); + fraction_v = modff4(x5_v, &integer_v); + TEST_CHECK("20040916170701EJL", allequal_float4( integer_v, x5i_v ) && allequal_float4( fraction_v, x5f_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/ppu/tests/negatef4.c b/Extras/simdmathlibrary/ppu/tests/negatef4.c new file mode 100644 index 0000000..c0f809f --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/negatef4.c @@ -0,0 +1,86 @@ +/* Testcase for negatef4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "common-test.h" +#include "testutils.h" +#include "simdmath.h" + + +int main() +{ + TEST_SET_START("20040930102649EJL","EJL", "negatef4"); + + unsigned int i3n = 0xff000000; + unsigned int i3p = 0x7f000000; + + float x0n = hide_float(-0.0f); + float x0p = hide_float(0.0f); + float x1n = hide_float(-83532.96153153f); + float x1p = hide_float(83532.96153153f); + float x2n = hide_float(-0.0000000013152f); + float x2p = hide_float(0.0000000013152f); + float x3n = hide_float(make_float(i3n)); + float x3p = hide_float(make_float(i3p)); + + vec_float4 x0n_v = vec_splat_float(x0n); + vec_float4 x0p_v = vec_splat_float(x0p); + vec_float4 x1n_v = vec_splat_float(x1n); + vec_float4 x1p_v = vec_splat_float(x1p); + vec_float4 x2n_v = vec_splat_float(x2n); + vec_float4 x2p_v = vec_splat_float(x2p); + vec_float4 x3n_v = vec_splat_float(x3n); + vec_float4 x3p_v = vec_splat_float(x3p); + + vec_float4 res_v; + + TEST_START("negatef4"); + res_v = negatef4(x0n_v); + TEST_CHECK("20040930102652EJL", allequal_float4( res_v, x0p_v ), 0); + res_v = negatef4(x0p_v); + TEST_CHECK("20040930102653EJL", allequal_float4( res_v, x0n_v ), 0); + res_v = negatef4(x1n_v); + TEST_CHECK("20040930102655EJL", allequal_float4( res_v, x1p_v ), 0); + res_v = negatef4(x1p_v); + TEST_CHECK("20040930102657EJL", allequal_float4( res_v, x1n_v ), 0); + res_v = negatef4(x2n_v); + TEST_CHECK("20040930102659EJL", allequal_float4( res_v, x2p_v ), 0); + res_v = negatef4(x2p_v); + TEST_CHECK("20040930102701EJL", allequal_float4( res_v, x2n_v ), 0); + res_v = negatef4(x3n_v); + TEST_CHECK("20040930102703EJL", allequal_float4( res_v, x3p_v ), 0); + res_v = negatef4(x3p_v); + TEST_CHECK("20040930102705EJL", allequal_float4( res_v, x3n_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/ppu/tests/negatei4.c b/Extras/simdmathlibrary/ppu/tests/negatei4.c new file mode 100644 index 0000000..ad78aa9 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/negatei4.c @@ -0,0 +1,83 @@ +/* Testcase for negatei4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "common-test.h" +#include "testutils.h" +#include "simdmath.h" + + +int main() +{ + TEST_SET_START("20040930102649EJL","EJL", "negatei4"); + + int x0n = hide_int(0); + int x0p = hide_int(0); + int x1n = hide_int(-83532); + int x1p = hide_int(83532); + int x2n = hide_int(-13152); + int x2p = hide_int(13152); + int x3n = hide_int(-1); + int x3p = hide_int(1); + + vec_int4 x0n_v = vec_splat_int(x0n); + vec_int4 x0p_v = vec_splat_int(x0p); + vec_int4 x1n_v = vec_splat_int(x1n); + vec_int4 x1p_v = vec_splat_int(x1p); + vec_int4 x2n_v = vec_splat_int(x2n); + vec_int4 x2p_v = vec_splat_int(x2p); + vec_int4 x3n_v = vec_splat_int(x3n); + vec_int4 x3p_v = vec_splat_int(x3p); + + vec_int4 res_v; + + TEST_START("negatei4"); + res_v = negatei4(x0n_v); + TEST_CHECK("20040930102652EJL", allequal_int4( res_v, x0p_v ), 0); + res_v = negatei4(x0p_v); + TEST_CHECK("20040930102653EJL", allequal_int4( res_v, x0n_v ), 0); + res_v = negatei4(x1n_v); + TEST_CHECK("20040930102655EJL", allequal_int4( res_v, x1p_v ), 0); + res_v = negatei4(x1p_v); + TEST_CHECK("20040930102657EJL", allequal_int4( res_v, x1n_v ), 0); + res_v = negatei4(x2n_v); + TEST_CHECK("20040930102659EJL", allequal_int4( res_v, x2p_v ), 0); + res_v = negatei4(x2p_v); + TEST_CHECK("20040930102701EJL", allequal_int4( res_v, x2n_v ), 0); + res_v = negatei4(x3n_v); + TEST_CHECK("20040930102703EJL", allequal_int4( res_v, x3p_v ), 0); + res_v = negatei4(x3p_v); + TEST_CHECK("20040930102705EJL", allequal_int4( res_v, x3n_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/ppu/tests/recipf4.c b/Extras/simdmathlibrary/ppu/tests/recipf4.c new file mode 100644 index 0000000..52f1e56 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/recipf4.c @@ -0,0 +1,108 @@ +/* Testcase for recipf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "common-test.h" +#include "testutils.h" +#include "simdmath.h" + + +int main() +{ + TEST_SET_START("20040920142553EJL","EJL", "recipf4"); + + unsigned int i1 = 0xff000000; // -2^127 + unsigned int i2 = 0xfe7fffff; // -2^126 - 1 ulp + unsigned int i2r = 0x80800001; + unsigned int i3 = 0x75013340; // random values + unsigned int i3r = 0x09fd9f35; + unsigned int i4 = 0x75e7753f; + unsigned int i4r = 0x090d9277; + unsigned int i5 = 0x4c7fed5a; + unsigned int i5r = 0x32800954; + unsigned int i6 = 0x3a0731f0; + unsigned int i6r = 0x44f2602e; + unsigned int i7 = 0x69784a07; + unsigned int i7r = 0x1583f9a3; + + float x1 = hide_float(make_float(i1)); + float x1r = hide_float(0.0f); + float x2 = hide_float(make_float(i2)); + float x2r = hide_float(make_float(i2r)); + float x3 = hide_float(make_float(i3)); + float x3r = hide_float(make_float(i3r)); + float x4 = hide_float(make_float(i4)); + float x4r = hide_float(make_float(i4r)); + float x5 = hide_float(make_float(i5)); + float x5r = hide_float(make_float(i5r)); + float x6 = hide_float(make_float(i6)); + float x6r = hide_float(make_float(i6r)); + float x7 = hide_float(make_float(i7)); + float x7r = hide_float(make_float(i7r)); + + vec_float4 x1_v = vec_splat_float(x1); + vec_float4 x1r_v = vec_splat_float(x1r); + vec_float4 x2_v = vec_splat_float(x2); + vec_float4 x2r_v = vec_splat_float(x2r); + vec_float4 x3_v = vec_splat_float(x3); + vec_float4 x3r_v = vec_splat_float(x3r); + vec_float4 x4_v = vec_splat_float(x4); + vec_float4 x4r_v = vec_splat_float(x4r); + vec_float4 x5_v = vec_splat_float(x5); + vec_float4 x5r_v = vec_splat_float(x5r); + vec_float4 x6_v = vec_splat_float(x6); + vec_float4 x6r_v = vec_splat_float(x6r); + vec_float4 x7_v = vec_splat_float(x7); + vec_float4 x7r_v = vec_splat_float(x7r); + + vec_float4 res_v; + + TEST_START("recipf4"); + res_v = recipf4(x1_v); + TEST_CHECK("20040920142600EJL", allequal_float4( res_v, x1r_v), 0); + res_v = recipf4(x2_v); + TEST_CHECK("20040920142602EJL", allequal_ulps_float4( res_v, x2r_v, 2 ), 0); + res_v = recipf4(x3_v); + TEST_CHECK("20040920142604EJL", allequal_ulps_float4( res_v, x3r_v, 2 ), 0); + res_v = recipf4(x4_v); + TEST_CHECK("20040920142606EJL", allequal_ulps_float4( res_v, x4r_v, 2 ), 0); + res_v = recipf4(x5_v); + TEST_CHECK("20040920142608EJL", allequal_ulps_float4( res_v, x5r_v, 2 ), 0); + res_v = recipf4(x6_v); + TEST_CHECK("20040920142609EJL", allequal_ulps_float4( res_v, x6r_v, 2 ), 0); + res_v = recipf4(x7_v); + TEST_CHECK("20040920142611EJL", allequal_ulps_float4( res_v, x7r_v, 2 ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/ppu/tests/rsqrtf4.c b/Extras/simdmathlibrary/ppu/tests/rsqrtf4.c new file mode 100644 index 0000000..1a8801e --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/rsqrtf4.c @@ -0,0 +1,95 @@ +/* Testcase for rsqrtf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "common-test.h" +#include "testutils.h" +#include "simdmath.h" + + + + +int main() +{ + TEST_SET_START("20040928182349EJL","EJL", "rsqrtf4"); + + unsigned int i3 = 0x742c4455; + unsigned int i3r = 0x251c099a; + unsigned int i4 = 0x75e7753f; + unsigned int i4r = 0x243e5fe2; + unsigned int i5 = 0x4baa9e3c; + unsigned int i5r = 0x395dbbeb; + unsigned int i6 = 0x39344296; + unsigned int i6r = 0x429889eb; + unsigned int i7 = 0x68a586b0; + unsigned int i7r = 0x2ae11e67; + + float x3 = hide_float(make_float(i3)); + float x3r = hide_float(make_float(i3r)); + float x4 = hide_float(make_float(i4)); + float x4r = hide_float(make_float(i4r)); + float x5 = hide_float(make_float(i5)); + float x5r = hide_float(make_float(i5r)); + float x6 = hide_float(make_float(i6)); + float x6r = hide_float(make_float(i6r)); + float x7 = hide_float(make_float(i7)); + float x7r = hide_float(make_float(i7r)); + + vec_float4 x3_v = vec_splat_float(x3); + vec_float4 x3r_v = vec_splat_float(x3r); + vec_float4 x4_v = vec_splat_float(x4); + vec_float4 x4r_v = vec_splat_float(x4r); + vec_float4 x5_v = vec_splat_float(x5); + vec_float4 x5r_v = vec_splat_float(x5r); + vec_float4 x6_v = vec_splat_float(x6); + vec_float4 x6r_v = vec_splat_float(x6r); + vec_float4 x7_v = vec_splat_float(x7); + vec_float4 x7r_v = vec_splat_float(x7r); + + vec_float4 res_v; + + TEST_START("rsqrtf4"); + res_v = rsqrtf4(x3_v); + TEST_CHECK("20040928182352EJL", allequal_ulps_float4( res_v, x3r_v, 2 ), 0); + res_v = rsqrtf4(x4_v); + TEST_CHECK("20040928182355EJL", allequal_ulps_float4( res_v, x4r_v, 2 ), 0); + res_v = rsqrtf4(x5_v); + TEST_CHECK("20040928182357EJL", allequal_ulps_float4( res_v, x5r_v, 2 ), 0); + res_v = rsqrtf4(x6_v); + TEST_CHECK("20040928182358EJL", allequal_ulps_float4( res_v, x6r_v, 2 ), 0); + res_v = rsqrtf4(x7_v); + TEST_CHECK("20040928182401EJL", allequal_ulps_float4( res_v, x7r_v, 2 ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/ppu/tests/sqrtf4.c b/Extras/simdmathlibrary/ppu/tests/sqrtf4.c new file mode 100644 index 0000000..70bee97 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/sqrtf4.c @@ -0,0 +1,100 @@ +/* Testcase for sqrtf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "common-test.h" +#include "testutils.h" +#include "simdmath.h" + + +int main() +{ + TEST_SET_START("20040928182549EJL","EJL", "sqrtf4"); + + unsigned int i3 = 0x742c4455; + unsigned int i3r = 0x59d20034; + unsigned int i4 = 0x75e7753f; + unsigned int i4r = 0x5aac1fb5; + unsigned int i5 = 0x4baa9e3c; + unsigned int i5r = 0x4593c7d8; + unsigned int i6 = 0x39344296; + unsigned int i6r = 0x3c56d14c; + unsigned int i7 = 0x68a586b0; + unsigned int i7r = 0x54118f09; + + float x0 = hide_float(0.0f); + float x0r = hide_float(0.0f); + + float x3 = hide_float(make_float(i3)); + float x3r = hide_float(make_float(i3r)); + float x4 = hide_float(make_float(i4)); + float x4r = hide_float(make_float(i4r)); + float x5 = hide_float(make_float(i5)); + float x5r = hide_float(make_float(i5r)); + float x6 = hide_float(make_float(i6)); + float x6r = hide_float(make_float(i6r)); + float x7 = hide_float(make_float(i7)); + float x7r = hide_float(make_float(i7r)); + + vec_float4 x0_v = vec_splat_float(x0); + vec_float4 x0r_v = vec_splat_float(x0r); + + vec_float4 x3_v = vec_splat_float(x3); + vec_float4 x3r_v = vec_splat_float(x3r); + vec_float4 x4_v = vec_splat_float(x4); + vec_float4 x4r_v = vec_splat_float(x4r); + vec_float4 x5_v = vec_splat_float(x5); + vec_float4 x5r_v = vec_splat_float(x5r); + vec_float4 x6_v = vec_splat_float(x6); + vec_float4 x6r_v = vec_splat_float(x6r); + vec_float4 x7_v = vec_splat_float(x7); + vec_float4 x7r_v = vec_splat_float(x7r); + + vec_float4 res_v; + + TEST_START("sqrtf4"); + res_v = sqrtf4(x0_v); + TEST_CHECK("20040928182551EJL", allequal_float4( res_v, x0r_v ), 0); + res_v = sqrtf4(x3_v); + TEST_CHECK("20040928182552EJL", allequal_ulps_float4( res_v, x3r_v, 2 ), 0); + res_v = sqrtf4(x4_v); + TEST_CHECK("20040928182554EJL", allequal_ulps_float4( res_v, x4r_v, 2 ), 0); + res_v = sqrtf4(x5_v); + TEST_CHECK("20040928182556EJL", allequal_ulps_float4( res_v, x5r_v, 2 ), 0); + res_v = sqrtf4(x6_v); + TEST_CHECK("20040928182557EJL", allequal_ulps_float4( res_v, x6r_v, 2 ), 0); + res_v = sqrtf4(x7_v); + TEST_CHECK("20040928182559EJL", allequal_ulps_float4( res_v, x7r_v, 2 ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/ppu/tests/testutils.c b/Extras/simdmathlibrary/ppu/tests/testutils.c new file mode 100644 index 0000000..f5bfa3b --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/testutils.c @@ -0,0 +1,67 @@ +/* Common part of the testsuite + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ + +unsigned int +hide_uint( unsigned int x ) +{ + return x; +} + +int +hide_int( int x ) +{ + return x; +} + +float +hide_float( float x ) +{ + return x; +} + +double +hide_double( double x ) +{ + return x; +} + +float +make_float( unsigned int x ) +{ + + union + { + unsigned int i; + float f; + }fi; + fi.i = x; + return fi.f; +} + + diff --git a/Extras/simdmathlibrary/ppu/tests/testutils.h b/Extras/simdmathlibrary/ppu/tests/testutils.h new file mode 100644 index 0000000..7b905ed --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/testutils.h @@ -0,0 +1,110 @@ +/* Header file for common parts of the testsuite + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ + + +/* FIXME: Don't use altivec style initializers. */ + +#ifndef _TESTUTILS_H_ + +#include +#define vec_uchar16 vector unsigned char +#define vec_char16 vector signed char +#define vec_ushort8 vector unsigned short +#define vec_short8 vector signed short +#define vec_uint4 vector unsigned int +#define vec_int4 vector signed int +#define vec_ullong2 vector unsigned long long +#define vec_llong2 vector signed long long +#define vec_float4 vector float +#define vec_double2 vector double + +extern unsigned int hide_uint( unsigned int x ); +extern int hide_int( int x ); +extern float hide_float( float x ); +extern float make_float( unsigned int x ); + +inline vec_int4 vec_splat_int( int x ) +{ + return (vec_int4){x, x, x, x}; +} + +inline vec_float4 vec_splat_float( float x ) +{ + return (vec_float4){x, x, x, x}; +} + +inline vec_uint4 bitDiff_f4(vec_float4 ref, vec_float4 vals) { + vec_int4 refi = (vec_int4)ref; + vec_int4 valsi = (vec_int4)vals; + vec_int4 diff = vec_sub( refi, valsi ); + vec_int4 negdiff = vec_sub( vec_splat_int(0), diff ); + vec_uint4 lz; + + diff = vec_sel( negdiff, diff, vec_cmpgt( diff, vec_splat_int(0) ) ); + + lz = vec_sub( (vec_uint4)vec_splat_int(158), vec_sr( (vec_uint4)vec_ctf( diff, 0 ), (vec_uint4)vec_splat_int(23) ) ); + lz = vec_sel( lz, (vec_uint4)vec_splat_int(32), vec_cmpeq( diff, vec_splat_int(0) ) ); + + return vec_sub( (vec_uint4)vec_splat_int(32), lz ); +} + +inline vec_uint4 ulpDiff_f4(vec_float4 ref, vec_float4 vals) { + vec_int4 refi = (vec_int4)ref; + vec_int4 valsi = (vec_int4)vals; + vec_int4 diff = vec_sub( refi, valsi ); + vec_int4 negdiff = vec_sub( vec_splat_int(0), diff ); + + return (vec_uint4)( vec_sel( negdiff, diff, vec_cmpgt( diff, vec_splat_int(0) ) ) ); +} + +inline int allequal_int4( vec_int4 x, vec_int4 y ) +{ + return ( vec_all_eq( x, y ) ); +} + +inline int allequal_float4( vec_float4 x, vec_float4 y ) +{ + return ( vec_all_eq( x, y ) ); +} + +inline int allequal_ulps_float4( vec_float4 x, vec_float4 y, int tolerance ) +{ + vec_uint4 vtol = (vec_uint4)vec_splat_int( tolerance ); + vec_uint4 ulps = ulpDiff_f4( x, y ); + return vec_all_le( ulps, vtol ); +} + +inline int allequal_bits_float4( vec_float4 x, vec_float4 y, int tolerance ) +{ + vec_uint4 vtol = (vec_uint4)vec_splat_int( tolerance ); + vec_uint4 bits = bitDiff_f4( x, y ); + return vec_all_le( bits, vtol ); +} + +#endif diff --git a/Extras/simdmathlibrary/ppu/tests/truncf4.c b/Extras/simdmathlibrary/ppu/tests/truncf4.c new file mode 100644 index 0000000..7244413 --- /dev/null +++ b/Extras/simdmathlibrary/ppu/tests/truncf4.c @@ -0,0 +1,93 @@ +/* Testcase for truncf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "common-test.h" +#include "testutils.h" +#include "simdmath.h" + + +int main() +{ + TEST_SET_START("20040916100012EJL","EJL", "truncf"); + + unsigned int i3 = 0x4affffff; // 2^23 - 0.5, largest truncatable value. + unsigned int i3i = 0x4afffffe; + unsigned int i4 = 0x4b000000; // 2^23, no fractional part. + unsigned int i5 = 0xcf000001; // -2^31, one more large, and negative, value. + + float x0 = hide_float(0.91825f); + float x0i = hide_float(0.0f); + float x1 = hide_float(-0.12958f); + float x1i = hide_float(0.0f); + float x2 = hide_float(-79615.1875f); + float x2i = hide_float(-79615.0f); + float x3 = hide_float(make_float(i3)); + float x3i = hide_float(make_float(i3i)); + float x4 = hide_float(make_float(i4)); + float x4i = hide_float(make_float(i4)); + float x5 = hide_float(make_float(i5)); + float x5i = hide_float(make_float(i5)); + + vec_float4 x0_v = vec_splat_float(x0); + vec_float4 x0i_v = vec_splat_float(x0i); + vec_float4 x1_v = vec_splat_float(x1); + vec_float4 x1i_v = vec_splat_float(x1i); + vec_float4 x2_v = vec_splat_float(x2); + vec_float4 x2i_v = vec_splat_float(x2i); + vec_float4 x3_v = vec_splat_float(x3); + vec_float4 x3i_v = vec_splat_float(x3i); + vec_float4 x4_v = vec_splat_float(x4); + vec_float4 x4i_v = vec_splat_float(x4i); + vec_float4 x5_v = vec_splat_float(x5); + vec_float4 x5i_v = vec_splat_float(x5i); + + vec_float4 res_v; + + TEST_START("truncf4"); + res_v = truncf4(x0_v); + TEST_CHECK("20040916100023EJL", allequal_float4( res_v, x0i_v ), 0); + res_v = truncf4(x1_v); + TEST_CHECK("20040916100034EJL", allequal_float4( res_v, x1i_v ), 0); + res_v = truncf4(x2_v); + TEST_CHECK("20040916100043EJL", allequal_float4( res_v, x2i_v ), 0); + res_v = truncf4(x3_v); + TEST_CHECK("20040916100054EJL", allequal_float4( res_v, x3i_v ), 0); + res_v = truncf4(x4_v); + TEST_CHECK("20040916100103EJL", allequal_float4( res_v, x4i_v ), 0); + res_v = truncf4(x5_v); + TEST_CHECK("20040916100111EJL", allequal_float4( res_v, x5i_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/simdmath.spec b/Extras/simdmathlibrary/simdmath.spec new file mode 100644 index 0000000..0cf0e65 --- /dev/null +++ b/Extras/simdmathlibrary/simdmath.spec @@ -0,0 +1,108 @@ +%define lib_version 1.0.2 + +Summary: SIMD math library. +Name: simdmath +Version: %{lib_version} +Release: 1 +License: BSD +Group: System Environment/Libraries +Source0: %{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root + +%define _enable_spu 0 + +%ifarch ppc +%define _arch ppu +%define _libdir %{_exec_prefix}/lib +%define _enable_spu 1 +%endif + +%ifarch ppc64 +%define _arch ppu64 +%define _libdir %{_exec_prefix}/lib64 +%define _enable_spu 1 +%endif + +%define _spe_prefix %{_prefix}/spu +%define _spe_exec_prefix %{_exec_prefix}/spu +%define _spe_includedir %{_spe_prefix}/include +%define _spe_libdir %{_spe_exec_prefix}/lib + +%define __os_install_post %{nil} + +%package -n %{name}-devel +Summary: SIMD math library. +Group: Development/Libraries +Requires: %{name} = %{version} + +%if %{_enable_spu} +%package -n spu-%{name}-devel +Summary: SIMD math library. +Group: Development/Libraries +%endif + +%description +SIMD math library. + +%description -n %{name}-devel +SIMD math library. + +%if %{_enable_spu} +%description -n spu-%{name}-devel +SIMD math library. +%endif + +%prep +%setup -q + +%build + +make ARCH=%{_arch} + +%if %{_enable_spu} +make ARCH=spu +%endif + +%install +rm -rf %{buildroot} + +make ARCH=%{_arch} DESTDIR=%{buildroot} install + +%if %{_enable_spu} +make ARCH=spu DESTDIR=%{buildroot} install +%endif + +if [ "%{_libdir}" != /usr/lib ]; then + mv %{buildroot}/usr/lib %{buildroot}%{_libdir} +fi + +mkdir -p %{buildroot}/%{_docdir}/%{name}-%{version} +cp README LICENSE %{buildroot}/%{_docdir}/%{name}-%{version}/ + +%clean +rm -rf %{buildroot} + +%files +%defattr(-,root,root,-) +%{_libdir}/*.so.* +%{_docdir}/* + +%files -n %{name}-devel +%defattr(-,root,root,-) +%{_includedir}/* +%{_libdir}/*.a +%{_libdir}/*.so + +%if %{_enable_spu} +%files -n spu-%{name}-devel +%defattr(-,root,root,-) +%{_spe_includedir}/* +%{_spe_libdir}/* +%endif + +%changelog +* Thu Aug 9 2007 Kazunori Asayama - 1.0.1-2 +- Add documents. + +* Fri Aug 25 2006 Kazunori Asayama - 1.0.1-1 +- Initial build. diff --git a/Extras/simdmathlibrary/spu/Makefile b/Extras/simdmathlibrary/spu/Makefile new file mode 100644 index 0000000..9e74faa --- /dev/null +++ b/Extras/simdmathlibrary/spu/Makefile @@ -0,0 +1,60 @@ +# make file to build the libsimdmath library for SPU +# Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. +# 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 Sony Computer Entertainment Inc 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. + +topdir = .. +ARCH = spu + +include $(topdir)/Make.defs + +# All that you do to add a file is edit OBJS, the rest will just work + +OBJS = fabsd2.o fabsf4.o truncf4.o divf4.o tanf4.o isnanf4.o isnand2.o isinff4.o isinfd2.o \ + is0denormf4.o is0denormd2.o recipd2.o divd2.o tand2.o sqrtf4.o absi4.o sqrtd2.o \ + sinf4.o isgreaterd2.o sind2.o sincosd2.o sincosf4.o rsqrtf4.o signbitf4.o signbitd2.o \ + rsqrtd2.o copysignf4.o remainderf4.o recipf4.o copysignd2.o log2f4.o \ + negatef4.o negated2.o modff4.o asinf4.o frexpf4.o frexpd2.o ldexpf4.o cbrtf4.o \ + cosd2.o cosf4.o hypotf4.o hypotd2.o ceilf4.o fmaf4.o fmaxf4.o fminf4.o floorf4.o \ + fdimf4.o fmodf4.o negatei4.o logf4.o log1pf4.o log10f4.o expm1f4.o \ + expf4.o divi4.o exp2f4.o powf4.o atanf4.o atan2f4.o acosf4.o ilogbf4.o ilogbd2.o \ + logbf4.o logbd2.o llroundd2.o llroundf4.o llrintf4.o isequalf4.o isequald2.o \ + islessgreaterf4.o islessgreaterd2.o islessf4.o islessd2.o isgreaterf4.o \ + isgreaterd2.o islessequalf4.o islessequald2.o isgreaterequalf4.o isgreaterequald2.o \ + isfinitef4.o isfinited2.o isnormalf4.o isnormald2.o isunorderedf4.o isunorderedd2.o \ + llrintd2.o roundf4.o rintf4.o irintf4.o iroundf4.o fmad2.o fmaxd2.o fmind2.o fdimd2.o \ + nextafterd2.o fpclassifyf4.o fpclassifyd2.o nearbyintd2.o nextafterf4.o nearbyintf4.o \ + llabsi2.o truncd2.o roundd2.o rintd2.o negatell2.o divu4.o modfd2.o lldivu2.o \ + ceild2.o floord2.o ldexpd2.o scalbnf4.o scalbllnd2.o lldivi2.o remquof4.o remquod2.o\ + fmodd2.o remainderd2.o + +include $(topdir)/Make.rules + +$(OBJS): ../common/simdmath.h + +# Some Objects have special header files. +sinf4.o sind2.o sincosf4.o cosd2.o: ../common/simdmath/_sincos.h +lldivu2.o lldivi2.o : simdmath/_lldiv.h diff --git a/Extras/simdmathlibrary/spu/simdmath/_lldiv.h b/Extras/simdmathlibrary/spu/simdmath/_lldiv.h new file mode 100644 index 0000000..b3d8a2b --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/_lldiv.h @@ -0,0 +1,116 @@ +/* Common functions for lldivi2/lldivu2 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LLDIV_H___ +#define ___SIMD_MATH_LLDIV_H___ + +#include + +static inline vector unsigned long long +__ll_spu_cntlz(vector unsigned long long x) +{ + vec_uint4 cnt; + + cnt = spu_cntlz((vec_uint4)x); + cnt = spu_add(cnt, spu_and(spu_cmpeq(cnt, 32), spu_rlqwbyte(cnt, 4))); + cnt = spu_shuffle(cnt, cnt, ((vec_uchar16){0x80,0x80,0x80,0x80, 0,1,2,3, 0x80,0x80,0x80,0x80, 8,9,10,11})); + + return (vec_ullong2)cnt; +} + +static inline vector unsigned long long +__ll_spu_sl(vector unsigned long long x, vector unsigned long long count) +{ + vec_ullong2 mask = (vec_ullong2){0xffffffffffffffffull, 0ull}; + vec_ullong2 x_upper, x_lower; + + // shift upper word + x_upper = spu_and(x, mask); + x_upper = spu_slqwbytebc(x_upper, spu_extract((vec_uint4)count, 1)); + x_upper = spu_slqw(x_upper, spu_extract((vec_uint4)count, 1)); + + // shift lower word + x_lower = spu_slqwbytebc(x, spu_extract((vec_uint4)count, 3)); + x_lower = spu_slqw(x_lower, spu_extract((vec_uint4)count, 3)); + + return spu_sel(x_lower, x_upper, mask); +} + +static inline vector unsigned long long +__ll_spu_rlmask(vector unsigned long long x, vector unsigned long long count) +{ + vec_ullong2 mask = (vec_ullong2){0xffffffffffffffffull, 0ull}; + vec_ullong2 x_upper, x_lower; + vec_uint4 cnt_byte; + + cnt_byte = spu_add((vec_uint4)count, 7); + + // shift upper word + x_upper = spu_rlmaskqwbytebc(x, spu_extract(cnt_byte, 1)); + x_upper = spu_rlmaskqw(x_upper, spu_extract((vec_uint4)count, 1)); + + // shift lower word + x_lower = spu_andc(x, mask); + x_lower = spu_rlmaskqwbytebc(x_lower, spu_extract(cnt_byte, 3)); + x_lower = spu_rlmaskqw(x_lower, spu_extract((vec_uint4)count, 3)); + + return spu_sel(x_lower, x_upper, mask); +} + +static inline vector unsigned long long +__ll_spu_cmpeq_zero(vector unsigned long long x) +{ + vec_uint4 cmp; + + cmp = spu_cmpeq((vec_uint4)x, 0); + return (vec_ullong2)spu_and(cmp, spu_shuffle(cmp, cmp, ((vec_uchar16){4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11}))); +} + +static inline vector unsigned long long +__ll_spu_cmpgt(vector unsigned long long x, vector unsigned long long y) +{ + vec_uint4 gt; + + gt = spu_cmpgt((vec_uint4)x, (vec_uint4)y); + gt = spu_sel(gt, spu_rlqwbyte(gt, 4), spu_cmpeq((vec_uint4)x, (vec_uint4)y)); + return (vec_ullong2)spu_shuffle(gt, gt, ((vec_uchar16){0,1,2,3, 0,1,2,3, 8,9,10,11, 8,9,10,11})); +} + +static inline vector unsigned long long +__ll_spu_sub(vector unsigned long long x, vector unsigned long long y) +{ + vec_uint4 borrow; + + borrow = spu_genb((vec_uint4)x, (vec_uint4)y); + borrow = spu_shuffle(borrow, borrow, ((vec_uchar16){4,5,6,7, 0xc0,0xc0,0xc0,0xc0, 12,13,14,15, 0xc0,0xc0,0xc0,0xc0})); + return (vec_ullong2)spu_subx((vec_uint4)x, (vec_uint4)y, borrow); +} + +#endif // __LLDIV_H__ + diff --git a/Extras/simdmathlibrary/spu/simdmath/_remainder.h b/Extras/simdmathlibrary/spu/simdmath/_remainder.h new file mode 100644 index 0000000..b4dcbf9 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/_remainder.h @@ -0,0 +1,84 @@ +/* A vector double is returned that contains the internal routine regarding remainder. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH__REMAINDER_H___ +#define ___SIMD_MATH__REMAINDER_H___ + +#include + +/* + * double formated x2 + */ +static inline vec_uint4 +__rem_twice_d(vec_uint4 aa) +{ + vec_uint4 norm = spu_cmpgt(aa, (vec_uint4)(spu_splats(0x000FFFFFFFFFFFFFULL))); // exp > 0 + norm = spu_shuffle(norm, norm, ((vec_uchar16){ 0,1,2,3,0,1,2,3, 8,9,10,11, 8,9,10,11})); + + // if denorm or zero << 1 , if norm exp + 1 + return spu_sel(spu_slqw(aa, 1), spu_add(aa, (vec_uint4)(spu_splats(0x0010000000000000ULL))), norm); // x2 +} + +/* + * subtraction function in limited confdition + */ +static inline vec_uint4 +__rem_sub_d(vec_uint4 aa, vec_uint4 bb) +{ + // which is bigger input aa or bb + vec_uint4 is_bigb = __vec_gt64(bb, aa); // bb > aa + + // need denorm calc ? + vec_uint4 norm_a, norm_b; + norm_a = spu_cmpgt(aa, (vec_uint4)(spu_splats(0x000FFFFFFFFFFFFFULL))); + norm_b = spu_cmpgt(bb, (vec_uint4)(spu_splats(0x000FFFFFFFFFFFFFULL))); + norm_a = spu_and(norm_a, norm_b); + norm_a = spu_shuffle(norm_a, norm_a,((vec_uchar16){ 0,1,2,3,0,1,2,3, 8,9,10,11, 8,9,10,11})); + + // calc (aa - bb) and (bb - aa) + vec_uint4 res_a, res_b, res; + vec_uint4 borrow_a, borrow_b; + vec_uchar16 mask_b = ((vec_uchar16){4,5,6,7,192,192,192,192,12,13,14,15,192,192,192,192}); + borrow_a = spu_genb(aa, bb); + borrow_b = spu_genb(bb, aa); + borrow_a = spu_shuffle(borrow_a, borrow_a, mask_b); + borrow_b = spu_shuffle(borrow_b, borrow_b, mask_b); + res_a = spu_subx(aa, bb, borrow_a); + res_b = spu_subx(bb, aa, borrow_b); + res_b = spu_or(res_b, ((vec_uint4){0x80000000,0,0x80000000,0})); // set sign + + res = spu_sel(res_a, res_b, is_bigb); // select (aa - bb) or (bb - aa) + // select normal calc or special + res = spu_sel(res, (vec_uint4)spu_sub((vec_double2)aa, (vec_double2)bb), norm_a); + + return res; +} + +#endif + diff --git a/Extras/simdmathlibrary/spu/simdmath/_vec_utils.h b/Extras/simdmathlibrary/spu/simdmath/_vec_utils.h new file mode 100644 index 0000000..037eeec --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/_vec_utils.h @@ -0,0 +1,57 @@ +/* Common types for SPU SIMD Math Library + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH__VEC_UTILS_H___ +#define ___SIMD_MATH__VEC_UTILS_H___ + +/* + * extend spu_cmpgt function to 64bit data + */ +static inline vec_uint4 +__vec_gt64_half(vec_uint4 aa, vec_uint4 bb) +{ + vec_uint4 gt = spu_cmpgt(aa, bb); // aa > bb + vec_uint4 eq = spu_cmpeq(aa, bb); // aa = bb + return spu_or(gt, spu_and(eq, spu_rlqwbyte(gt, 4))); // only higher is right +} +static inline vec_uint4 +__vec_gt64(vec_uint4 aa, vec_uint4 bb) +{ + vec_uint4 gt_hi = __vec_gt64_half(aa, bb); // only higher is right + return spu_shuffle(gt_hi, gt_hi, ((vec_uchar16){ 0,1,2,3,0,1,2,3, 8,9,10,11, 8,9,10,11})); +} + +static inline vec_uint4 +__vec_eq64_half(vec_uint4 aa, vec_uint4 bb) +{ + vec_uint4 eq = spu_cmpeq(aa, bb); + return spu_and(eq, spu_shuffle(eq, eq, ((vec_uchar16){4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11}))); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/absi4.h b/Extras/simdmathlibrary/spu/simdmath/absi4.h new file mode 100644 index 0000000..813041c --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/absi4.h @@ -0,0 +1,44 @@ +/* absi4 - for each of four integer slots, compute absolute value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ABSI4_H___ +#define ___SIMD_MATH_ABSI4_H___ + +#include +#include + +static inline vector signed int +_absi4 (vector signed int x) +{ + vec_int4 neg; + neg = spu_sub( 0, x ); + return spu_sel( neg, x, spu_cmpgt( x, -1 ) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/acosf4.h b/Extras/simdmathlibrary/spu/simdmath/acosf4.h new file mode 100644 index 0000000..c492d53 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/acosf4.h @@ -0,0 +1,82 @@ +/* acosf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ACOSF4_H___ +#define ___SIMD_MATH_ACOSF4_H___ + +#include +#include + +#include + +// +// Computes the inverse cosine of all four slots of x +// +static inline vector float +_acosf4 (vector float x) +{ + vec_float4 result, xabs; + vec_float4 t1; + vec_float4 xabs2, xabs4; + vec_float4 hi, lo; + vec_float4 neg, pos; + vec_uint4 select; + + xabs = (vec_float4)(spu_rlmask(spu_sl((vec_uint4)(x), 1), -1)); + select = (vec_uint4)(spu_rlmaska((vector signed int)(x), -31)); + + t1 = _sqrtf4(spu_sub( spu_splats(1.0f), xabs)); + + /* Instruction counts can be reduced if the polynomial was + * computed entirely from nested (dependent) fma's. However, + * to reduce the number of pipeline stalls, the polygon is evaluated + * in two halves (hi amd lo). + */ + xabs2 = spu_mul(xabs, xabs); + xabs4 = spu_mul(xabs2, xabs2); + hi = spu_madd(spu_splats(-0.0012624911f), xabs, spu_splats(0.0066700901f)); + hi = spu_madd(hi, xabs, spu_splats(-0.0170881256f)); + hi = spu_madd(hi, xabs, spu_splats( 0.0308918810f)); + lo = spu_madd(spu_splats(-0.0501743046f), xabs, spu_splats(0.0889789874f)); + lo = spu_madd(lo, xabs, spu_splats(-0.2145988016f)); + lo = spu_madd(lo, xabs, spu_splats( 1.5707963050f)); + + result = spu_madd(hi, xabs4, lo); + + /* Adjust the result if x is negactive. + */ + neg = spu_nmsub(t1, result, spu_splats(3.1415926535898f)); + pos = spu_mul(t1, result); + + result = spu_sel(pos, neg, select); + + return result; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/asinf4.h b/Extras/simdmathlibrary/spu/simdmath/asinf4.h new file mode 100644 index 0000000..eb62731 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/asinf4.h @@ -0,0 +1,92 @@ +/* asinf4 - Computes the inverse sine of all four slots of x + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ASINF4_H___ +#define ___SIMD_MATH_ASINF4_H___ + +#include +#include + +#include +#include + +static inline vector float +_asinf4 (vector float x) +{ + // positive = (x > 0) + // + vec_uint4 positive = spu_cmpgt(x,spu_splats(0.0f)); + + // gtHalf = (|x| > 0.5) + // + vec_uint4 gtHalf = spu_cmpabsgt(x,spu_splats(0.5f)); + + // x = absf(x) + // + x = (vec_float4)spu_and((vec_int4)x,spu_splats((int)0x7fffffff)); + + + // if (x > 0.5) + // g = 0.5 - 0.5*x + // x = -2 * sqrtf(g) + // else + // g = x * x + // + vec_float4 g = spu_sel(spu_mul(x,x),spu_madd(spu_splats(-0.5f),x,spu_splats(0.5f)),gtHalf); + + x = spu_sel(x,spu_mul(spu_splats(-2.0f),_sqrtf4(g)),gtHalf); + + // Compute the polynomials and take their ratio + // denom = (1.0f*g + -0.554846723e+1f)*g + 5.603603363f + // num = x * g * (-0.504400557f * g + 0.933933258f) + // + vec_float4 denom = spu_add(g,spu_splats(-5.54846723f)); + vec_float4 num = spu_madd(spu_splats(-0.504400557f),g,spu_splats(0.933933258f)); + denom = spu_madd(denom,g,spu_splats(5.603603363f)); + num = spu_mul(spu_mul(x,g),num); + + + // x = x + num / denom + // + x = spu_add(x,_divf4(num,denom)); + + // if (x > 0.5) + // x = x + M_PI_2 + // + x = spu_sel(x,spu_add(x,spu_splats(1.57079632679489661923f)),gtHalf); + + + // if (!positive) x = -x + // + x = spu_sel((vec_float4)spu_xor(spu_splats((int)0x80000000),(vec_int4)x),x,positive); + + return x; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/atan2f4.h b/Extras/simdmathlibrary/spu/simdmath/atan2f4.h new file mode 100644 index 0000000..d17993e --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/atan2f4.h @@ -0,0 +1,66 @@ +/* atan2f4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ATAN2F4_H___ +#define ___SIMD_MATH_ATAN2F4_H___ + +#include +#include + +#include +#include + +// +// Inverse tangent function of two variables +// +static inline vector float +_atan2f4 (vector float y, vector float x) +{ + vec_float4 res = _atanf4(_divf4(y,x)); + + // Use the arguments to determine the quadrant of the result: + // if (x < 0) + // if (y < 0) + // res = -PI + res + // else + // res = PI + res + // + vec_uint4 yNeg = spu_cmpgt(spu_splats(0.0f),y); + vec_uint4 xNeg = spu_cmpgt(spu_splats(0.0f),x); + + vec_float4 bias = spu_sel(spu_splats(3.14159265358979323846f),spu_splats(-3.14159265358979323846f),yNeg); + + vec_float4 newRes = spu_add(bias, res); + + res = spu_sel(res,newRes,xNeg); + + return res; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/atanf4.h b/Extras/simdmathlibrary/spu/simdmath/atanf4.h new file mode 100644 index 0000000..49c8bee --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/atanf4.h @@ -0,0 +1,81 @@ +/* atanf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ATANF4_H___ +#define ___SIMD_MATH_ATANF4_H___ + +#include +#include + +#include + +// +// Computes the inverse tangent of all four slots of x. +// +static inline vector float +_atanf4 (vector float x) +{ + vec_float4 bias; + vec_float4 x2, x3, x4, x8, x9; + vec_float4 hi, lo; + vec_float4 result; + vec_float4 inv_x; + vec_uint4 sign; + vec_uint4 select; + + sign = spu_sl(spu_rlmask((vec_uint4)x, -31), 31); + inv_x = _recipf4(x); + inv_x = (vec_float4)spu_xor((vec_uint4)inv_x, spu_splats(0x80000000u)); + + select = (vec_uint4)spu_cmpabsgt(x, spu_splats(1.0f)); + bias = (vec_float4)spu_or(sign, (vec_uint4)(spu_splats(1.57079632679489661923f))); + bias = (vec_float4)spu_and((vec_uint4)bias, select); + + x = spu_sel(x, inv_x, select); + + bias = spu_add(bias, x); + x2 = spu_mul(x, x); + x3 = spu_mul(x2, x); + x4 = spu_mul(x2, x2); + x8 = spu_mul(x4, x4); + x9 = spu_mul(x8, x); + hi = spu_madd(spu_splats(0.0028662257f), x2, spu_splats(-0.0161657367f)); + hi = spu_madd(hi, x2, spu_splats(0.0429096138f)); + hi = spu_madd(hi, x2, spu_splats(-0.0752896400f)); + hi = spu_madd(hi, x2, spu_splats(0.1065626393f)); + lo = spu_madd(spu_splats(-0.1420889944f), x2, spu_splats(0.1999355085f)); + lo = spu_madd(lo, x2, spu_splats(-0.3333314528f)); + lo = spu_madd(lo, x3, bias); + + result = spu_madd(hi, x9, lo); + + return result; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/cbrtf4.h b/Extras/simdmathlibrary/spu/simdmath/cbrtf4.h new file mode 100644 index 0000000..c44aa2f --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/cbrtf4.h @@ -0,0 +1,95 @@ +/* cbrtf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_CBRTF4_H___ +#define ___SIMD_MATH_CBRTF4_H___ + +#include +#include + +#include +#include +#include + +static inline vec_int4 +__cbrtf4_calc_quot(vec_int4 n) +{ + vec_int4 quot; + vec_uint4 negxexpmask = spu_cmpgt(spu_splats(0), n); + n = spu_sel(n, spu_add(n,2), negxexpmask); + + quot = spu_add(spu_rlmaska(n,-2), spu_rlmaska(n,-4)); + quot = spu_add(quot, spu_rlmaska(quot, -4)); + quot = spu_add(quot, spu_rlmaska(quot, -8)); + quot = spu_add(quot, spu_rlmaska(quot,-16)); + vec_int4 r = spu_sub(spu_sub(n,quot), spu_sl(quot,1)); + quot = spu_add(quot, spu_rlmaska(spu_add(spu_add(r,5), spu_sl (r,2)), -4)); + return quot; +} + +#define __CBRTF_cbrt2 1.2599210498948731648 // 2^(1/3) +#define __CBRTF_sqr_cbrt2 1.5874010519681994748 // 2^(2/3) + +static inline vector float +_cbrtf4 (vector float x) +{ + vec_float4 zeros = spu_splats(0.0f); + vec_uint4 zeromask = spu_cmpeq(x, zeros); + vec_int4 xexp; + vec_float4 sgnmask = (vec_float4)spu_splats(0x7FFFFFFF); + vec_uint4 negmask = spu_cmpgt(spu_splats(0.0f), x); + x = spu_and(x, sgnmask); + + x = _frexpf4(x, &xexp); + vec_float4 p = spu_madd( + spu_madd(x, spu_splats(-0.191502161678719066f), spu_splats(0.697570460207922770f)), + x, + spu_splats(0.492659620528969547f) + ); + vec_float4 p3 = spu_mul(p, spu_mul(p, p)); + vec_int4 quot = __cbrtf4_calc_quot(xexp); + vec_int4 modval = spu_sub(spu_sub(xexp,quot), spu_sl(quot,1)); // mod = xexp - 3*quotient + vec_float4 factor = spu_splats((float)(1.0/__CBRTF_sqr_cbrt2)); + factor = spu_sel(factor, spu_splats((float)(1.0/__CBRTF_cbrt2)), spu_cmpeq(modval,-1)); + factor = spu_sel(factor, spu_splats((float)( 1.0)), spu_cmpeq(modval, 0)); + factor = spu_sel(factor, spu_splats((float)( __CBRTF_cbrt2)), spu_cmpeq(modval, 1)); + factor = spu_sel(factor, spu_splats((float)(__CBRTF_sqr_cbrt2)), spu_cmpeq(modval, 2)); + + vec_float4 pre = spu_mul(p, factor); + vec_float4 numr = spu_madd(x , spu_splats(2.0f), p3); + vec_float4 denr = spu_madd(p3, spu_splats(2.0f), x ); + vec_float4 res = spu_mul(pre, _divf4(numr, denr)); + res = _ldexpf4(res, quot); + + return spu_sel(spu_sel(res, spu_orc(res,sgnmask), negmask), + zeros, + zeromask); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/ceild2.h b/Extras/simdmathlibrary/spu/simdmath/ceild2.h new file mode 100644 index 0000000..a2d7d3f --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/ceild2.h @@ -0,0 +1,99 @@ +/* ceild2 - for each of two doule slots, round up to smallest integer not less than the value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_CEILD2_H___ +#define ___SIMD_MATH_CEILD2_H___ + +#include +#include + +static inline vector double +_ceild2(vector double in) +{ + vec_uchar16 swap_words = ((vec_uchar16){4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11}); + vec_uchar16 splat_hi = ((vec_uchar16){0,1,2,3,0,1,2,3, 8,9,10,11, 8,9,10,11}); + vec_uint4 one = ((vec_uint4){0, 1, 0, 1}); + vec_int4 exp, shift; + vec_uint4 mask, mask_1, frac_mask, addend, insert, pos, equal0, e_0, e_00, e_sign, exp_ge0; + vec_ullong2 sign = spu_splats(0x8000000000000000ULL); + vec_double2 in_hi, out; + vec_double2 one_d = spu_splats((double)1.0); + vec_uint4 zero = spu_splats((unsigned int)0x0); + + /* This function generates the following component + * based upon the inputs. + * + * mask = bits of the input that need to be replaced. + * insert = value of the bits that need to be replaced + * addend = value to be added to perform function. + * + * These are applied as follows:. + * + * out = ((in & mask) | insert) + addend + */ + + in_hi = spu_shuffle(in, in, splat_hi); + exp = spu_and(spu_rlmask((vec_int4)in_hi, -20), 0x7FF); + shift = spu_sub(((vec_int4){1023, 1043, 1023, 1043}), exp); + + /* clamp shift to the range 0 to -31. + */ + shift = spu_sel(spu_splats((int)-32), spu_andc(shift, (vec_int4)spu_cmpgt(shift, 0)), spu_cmpgt(shift, -32)); + frac_mask = spu_rlmask(((vec_uint4){0xFFFFF, -1, 0xFFFFF, -1}), shift); + exp_ge0 = spu_cmpgt(exp, 0x3FE); + mask = spu_orc(frac_mask, exp_ge0); + + /* addend = ((in & mask) && (in >= 0)) ? mask+1 : 0 + */ + mask_1 = spu_addx(mask, one, spu_rlqwbyte(spu_genc(mask, one), 4)); + pos = spu_cmpgt((vec_int4)in_hi, -1); + //pos = spu_cmpgt((vec_int4)in_hi, 0x0); //it is also work + equal0 = spu_cmpeq(spu_and((vec_uint4)in, mask), 0); + addend = spu_andc(spu_and(mask_1, pos), spu_and(equal0, spu_shuffle(equal0, equal0, swap_words))); + + /* insert + */ + e_0 = spu_cmpeq(spu_andc((vec_uint4)in, (vec_uint4)sign), zero); + e_00 = spu_and(e_0, spu_shuffle(e_0, e_0, swap_words)); + // e_sign = spu_sel(spu_splats((unsigned int)0x0), (vec_uint4)one_d, spu_cmpeq( spu_and((vec_uint4)in_hi, spu_splats((unsigned int)0x80000000)), zero)); + e_sign = spu_and( (vec_uint4)one_d, spu_cmpeq( spu_and((vec_uint4)in_hi,spu_splats((unsigned int)0x80000000)), zero)); + insert =spu_andc(spu_andc(e_sign, e_00), exp_ge0); + + /* replace insert + */ + in = spu_sel(in, (vec_double2)insert, spu_andc((vec_ullong2)mask, sign)); + + /* in + addend + */ + out = (vec_double2)spu_addx((vec_uint4)in, addend, spu_rlqwbyte(spu_genc((vec_uint4)in, addend), 4)); + + return (out); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/ceilf4.h b/Extras/simdmathlibrary/spu/simdmath/ceilf4.h new file mode 100644 index 0000000..06468a2 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/ceilf4.h @@ -0,0 +1,58 @@ +/* ceilf4 - for each of four float slots, round up to smallest integer not less than the value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_CEILF4_H___ +#define ___SIMD_MATH_CEILF4_H___ + +#include +#include + +static inline vector float +_ceilf4 (vector float x) +{ + vec_int4 xi, xi1; + vec_uint4 inrange; + vec_float4 truncated, truncated1; + + // Find truncated value and one greater. + + inrange = spu_cmpabsgt( (vec_float4)spu_splats(0x4b000000), x ); + + xi = spu_convts( x, 0 ); + xi1 = spu_add( xi, 1 ); + + truncated = spu_sel( x, spu_convtf( xi, 0 ), inrange ); + truncated1 = spu_sel( x, spu_convtf( xi1, 0 ), inrange ); + + // If truncated value is less than input, add one. + + return spu_sel( truncated, truncated1, spu_cmpgt( x, truncated ) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/copysignd2.h b/Extras/simdmathlibrary/spu/simdmath/copysignd2.h new file mode 100644 index 0000000..be4137a --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/copysignd2.h @@ -0,0 +1,43 @@ +/* copysignd2 - for each of two double slots, return value with magnitude from x and sign from y. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_COPYSIGND2_H___ +#define ___SIMD_MATH_COPYSIGND2_H___ + +#include +#include + + +static inline vector double +_copysignd2 (vector double x, vector double y) +{ + return spu_sel( x, y, spu_splats(0x8000000000000000ull) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/copysignf4.h b/Extras/simdmathlibrary/spu/simdmath/copysignf4.h new file mode 100644 index 0000000..1871a4b --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/copysignf4.h @@ -0,0 +1,43 @@ +/* copysignf4 - for each of four float slots, return value with magnitude from x and sign from y. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_COPYSIGNF4_H___ +#define ___SIMD_MATH_COPYSIGNF4_H___ + +#include +#include + + +static inline vector float +_copysignf4 (vector float x, vector float y) +{ + return spu_sel( x, y, spu_splats(0x80000000) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/cosd2.h b/Extras/simdmathlibrary/spu/simdmath/cosd2.h new file mode 100644 index 0000000..5fd6bf0 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/cosd2.h @@ -0,0 +1,46 @@ +/* cosd2 - Computes the cosine of the each of two double slots. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_COSD2_H___ +#define ___SIMD_MATH_COSD2_H___ + +#include +#include + +#include + +static inline vector double +_cosd2 (vector double x) +{ + vec_double2 s, c; + _sincosd2(x, &s, &c); + return c; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/cosf4.h b/Extras/simdmathlibrary/spu/simdmath/cosf4.h new file mode 100644 index 0000000..c3d2be5 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/cosf4.h @@ -0,0 +1,46 @@ +/* cosf4 - Computes the cosine of each of the four slots by using a polynomial approximation + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_COSF4_H___ +#define ___SIMD_MATH_COSF4_H___ + +#include +#include + +#include + +static inline vector float +_cosf4 (vector float x) +{ + vec_float4 s, c; + _sincosf4(x, &s, &c); + return c; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/divd2.h b/Extras/simdmathlibrary/spu/simdmath/divd2.h new file mode 100644 index 0000000..35cfe6e --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/divd2.h @@ -0,0 +1,47 @@ +/* divd2 - for each of two double slots, divide numer by denom. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_DIVD2_H___ +#define ___SIMD_MATH_DIVD2_H___ + +// Equal to numer * recipd2(denom) +// See recipd2 for results of special values. + +#include +#include + +#include + +static inline vector double +_divd2 (vector double numer, vector double denom) +{ + return spu_mul( numer, _recipd2( denom ) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/divf4.h b/Extras/simdmathlibrary/spu/simdmath/divf4.h new file mode 100644 index 0000000..6edfab1 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/divf4.h @@ -0,0 +1,50 @@ +/* divf4 - for each of four float slots, divide numer by denom. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_DIVF4_H___ +#define ___SIMD_MATH_DIVF4_H___ + +#include +#include + +static inline vector float +_divf4 (vector float numer, vector float denom) +{ + // Reciprocal estimate and 1 Newton-Raphson iteration. + // Uses constant of 1.0 + 1 ulp to improve accuracy. + + vector float y0, y0numer; + vector float oneish = (vector float)spu_splats(0x3f800001); + + y0 = spu_re( denom ); + y0numer = spu_mul( numer, y0 ); + return spu_madd( spu_nmsub( denom, y0, oneish ), y0numer, y0numer ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/divi4.h b/Extras/simdmathlibrary/spu/simdmath/divi4.h new file mode 100644 index 0000000..f4f7e96 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/divi4.h @@ -0,0 +1,67 @@ +/* divi4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_DIVI4_H___ +#define ___SIMD_MATH_DIVI4_H___ + +#include +#include + +#include + +// divi4 - for each of four integer slots, compute quotient and remainder of numer/denom +// and store in divi4_t struct. Divide by zero produces quotient = 0, remainder = numerator. + +static inline divi4_t +_divi4 (vector signed int numer, vector signed int denom) +{ + divu4_t resAbs; + divi4_t res; + vec_uint4 numerPos, denomPos, quotNeg; + vec_uint4 numerAbs, denomAbs; + + // Determine whether result needs sign change + + numerPos = spu_cmpgt( numer, -1 ); + denomPos = spu_cmpgt( denom, -1 ); + quotNeg = spu_xor( numerPos, denomPos ); + + // Use absolute values of numerator, denominator + + numerAbs = (vec_uint4)spu_sel( spu_sub( 0, numer ), numer, numerPos ); + denomAbs = (vec_uint4)spu_sel( spu_sub( 0, denom ), denom, denomPos ); + + resAbs = _divu4(numerAbs, denomAbs); + + res.quot = spu_sel( (vec_int4)resAbs.quot, spu_sub( 0, (vec_int4)resAbs.quot ), quotNeg ); + res.rem = spu_sel( spu_sub( 0, (vec_int4)resAbs.rem ), (vec_int4)resAbs.rem, numerPos ); + return res; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/divu4.h b/Extras/simdmathlibrary/spu/simdmath/divu4.h new file mode 100644 index 0000000..f28c09d --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/divu4.h @@ -0,0 +1,102 @@ +/* divu4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_DIVU4_H___ +#define ___SIMD_MATH_DIVU4_H___ + +#include +#include + +// divu4 - for each of four unsigned integer slots, compute quotient and remainder of numer/denom +// and store in divu4_t struct. Divide by zero produces quotient = 0, remainder = numerator. + +static inline divu4_t +_divu4 (vector unsigned int numer, vector unsigned int denom) +{ + divu4_t res; + vec_int4 shift; + vec_uint4 quot, newQuot; + vec_uint4 denomZeros, numerZeros, denomLeft, oneLeft, denomShifted, oneShifted; + vec_uint4 newNum, skip, cont; + int anyCont; + + // Get difference of leading zeros. + // Any possible negative value will be interpreted as a shift > 31 + + denomZeros = spu_cntlz( denom ); + numerZeros = spu_cntlz( numer ); + + shift = (vec_int4)spu_sub( denomZeros, numerZeros ); + + // Shift denom to align leading one with numerator's + + denomShifted = spu_sl( denom, (vec_uint4)shift ); + oneShifted = spu_sl( spu_splats(1U), (vec_uint4)shift ); + oneShifted = spu_sel( oneShifted, spu_splats(0U), spu_cmpeq( denom, 0 ) ); + + // Shift left all leading zeros. + + denomLeft = spu_sl( denom, denomZeros ); + oneLeft = spu_sl( spu_splats(1U), denomZeros ); + + quot = spu_splats(0U); + + do + { + cont = spu_cmpgt( oneShifted, 0U ); + anyCont = spu_extract( spu_gather( cont ), 0 ); + + newQuot = spu_or( quot, oneShifted ); + + // Subtract shifted denominator from remaining numerator + // when denominator is not greater. + + skip = spu_cmpgt( denomShifted, numer ); + newNum = spu_sub( numer, denomShifted ); + + // If denominator is greater, next shift is one more, otherwise + // next shift is number of leading zeros of remaining numerator. + + numerZeros = spu_sel( spu_cntlz( newNum ), numerZeros, skip ); + shift = (vec_int4)spu_sub( skip, numerZeros ); + + oneShifted = spu_rlmask( oneLeft, shift ); + denomShifted = spu_rlmask( denomLeft, shift ); + + quot = spu_sel( newQuot, quot, skip ); + numer = spu_sel( newNum, numer, spu_orc(skip,cont) ); + } + while ( anyCont ); + + res.quot = quot; + res.rem = numer; + return res; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/exp2f4.h b/Extras/simdmathlibrary/spu/simdmath/exp2f4.h new file mode 100644 index 0000000..4e8a9ab --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/exp2f4.h @@ -0,0 +1,135 @@ +/* exp2f4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_EXP2F4_H___ +#define ___SIMD_MATH_EXP2F4_H___ + +#include +#include + + +/* + * FUNCTION + * vec_float4 _exp2_v(vec_float4 x) + * + * DESCRIPTION + * _exp2_v computes 2 raised to the input vector x. Computation is + * performed by observing the 2^(a+b) = 2^a * 2^b. + * We decompose x into a and b (above) by letting. + * a = ceil(x), b = x - a; + * + * 2^a is easilty computed by placing a into the exponent + * or a floating point number whose mantissa is all zeros. + * + * 2^b is computed using the following polynomial approximation. + * (C. Hastings, Jr, 1955). + * + * __7__ + * \ + * \ + * 2^(-x) = / Ci*x^i + * /____ + * i=1 + * + * for x in the range 0.0 to 1.0 + * + * C0 = 1.0 + * C1 = -0.9999999995 + * C2 = 0.4999999206 + * C3 = -0.1666653019 + * C4 = 0.0416573475 + * C5 = -0.0083013598 + * C6 = 0.0013298820 + * C7 = -0.0001413161 + * + * This function does not handle out of range conditions. It + * assumes that x is in the range (-128.0, 127.0]. Values outside + * this range will produce undefined results. + */ + + +#define __EXP2F_LN2 0.69314718055995f /* ln(2) */ + +static inline vector float +_exp2f4 (vector float x) +{ + vec_int4 ix; + vec_uint4 overflow, underflow; + vec_float4 frac, frac2, frac4; + vec_float4 exp_int, exp_frac; + vec_float4 result; + vec_float4 hi, lo; + + vec_float4 bias; + /* Break in the input x into two parts ceil(x), x - ceil(x). + */ + bias = (vec_float4)(spu_rlmaska((vec_int4)(x), -31)); + bias = (vec_float4)(spu_andc(spu_splats(0x3F7FFFFFu), (vec_uint4)bias)); + ix = spu_convts(spu_add(x, bias), 0); + frac = spu_sub(spu_convtf(ix, 0), x); + frac = spu_mul(frac, spu_splats(__EXP2F_LN2)); + + // !!! HRD Changing weird un-understandable and incorrect overflow handling code + //overflow = spu_sel((vec_uint4)spu_splats(0x7FFFFFFF), (vec_uint4)x, (vec_uchar16)spu_splats(0x80000000)); + overflow = spu_cmpgt(x, (vec_float4)spu_splats(0x4300FFFFu)); // !!! Biggest possible exponent to fit in range. + underflow = spu_cmpgt(spu_splats(-126.0f), x); + + //exp_int = (vec_float4)(spu_sl(spu_add(ix, 127), 23)); // !!! HRD <- changing this to correct for + // !!! overflow (x >= 127.999999f) + exp_int = (vec_float4)(spu_sl(spu_add(ix, 126), 23)); // !!! HRD <- add with saturation + exp_int = spu_add(exp_int, exp_int); // !!! HRD + + /* Instruction counts can be reduced if the polynomial was + * computed entirely from nested (dependent) fma's. However, + * to reduce the number of pipeline stalls, the polygon is evaluated + * in two halves (hi amd lo). + */ + frac2 = spu_mul(frac, frac); + frac4 = spu_mul(frac2, frac2); + + hi = spu_madd(frac, spu_splats(-0.0001413161f), spu_splats(0.0013298820f)); + hi = spu_madd(frac, hi, spu_splats(-0.0083013598f)); + hi = spu_madd(frac, hi, spu_splats(0.0416573475f)); + lo = spu_madd(frac, spu_splats(-0.1666653019f), spu_splats(0.4999999206f)); + lo = spu_madd(frac, lo, spu_splats(-0.9999999995f)); + lo = spu_madd(frac, lo, spu_splats(1.0f)); + + exp_frac = spu_madd(frac4, hi, lo); + ix = spu_add(ix, spu_rlmask((vec_int4)(exp_frac), -23)); + result = spu_mul(exp_frac, exp_int); + + /* Handle overflow */ + result = spu_sel(result, (vec_float4)spu_splats(0x7FFFFFFF), overflow); + result = spu_sel(result, (vec_float4)spu_splats(0), underflow); + //result = spu_sel(result, (vec_float4)(overflow), spu_cmpgt((vec_uint4)(ix), 255)); + + return (result); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/expf4.h b/Extras/simdmathlibrary/spu/simdmath/expf4.h new file mode 100644 index 0000000..d870d82 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/expf4.h @@ -0,0 +1,70 @@ +/* expm1f4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_EXPF4_H___ +#define ___SIMD_MATH_EXPF4_H___ + +#include +#include + +#include +#include + +#define __EXPF_C1 -0.6931470632553101f +#define __EXPF_C2 -1.1730463525082e-7f + +#define __EXPF_INVLN2 1.4426950408889634f + +static inline vector float +_expf4 (vector float x) +{ + vec_uint4 xnegmask = spu_cmpgt(spu_splats(0.0f), x); + vec_float4 goffset = spu_sel(spu_splats(0.5f),spu_splats(-0.5f),xnegmask); + vec_float4 g = spu_mul(x, spu_splats(__EXPF_INVLN2)); + vec_int4 xexp = spu_convts(spu_add(g, goffset),0); + + g = spu_convtf(xexp, 0); + g = spu_madd(g, spu_splats(__EXPF_C2), spu_madd(g, spu_splats(__EXPF_C1), x)); + vec_float4 z = spu_mul(g, g); + vec_float4 a = spu_mul(z, spu_splats(0.0999748594f)); + vec_float4 b = spu_mul(g, + spu_madd(z, + spu_splats(0.0083208258f), + spu_splats(0.4999999992f) + ) + ); + + vec_float4 foo = _divf4(spu_add(spu_splats(1.0f), spu_add(a, b)), + spu_add(spu_splats(1.0f), spu_sub(a, b))); + + return _ldexpf4(foo, xexp); + +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/expm1f4.h b/Extras/simdmathlibrary/spu/simdmath/expm1f4.h new file mode 100644 index 0000000..78e63ab --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/expm1f4.h @@ -0,0 +1,62 @@ +/* expm1f4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_EXPMLF4_H___ +#define ___SIMD_MATH_EXPMLF4_H___ + +#include +#include + +#include +#include + +#define __EXPM1F_ln1by2 -0.6931471805599f +#define __EXPM1F_ln3by2 0.4054651081082f + +static inline vector float +_expm1f4 (vector float x) +{ + vec_uint4 nearzeromask = spu_and(spu_cmpgt(x, spu_splats(__EXPM1F_ln1by2)), + spu_cmpgt(spu_splats(__EXPM1F_ln3by2), x)); + vec_float4 x2 = spu_mul(x,x); + vec_float4 d0, d1, n0, n1; + + d0 = spu_madd(x , spu_splats(-0.3203561199f), spu_splats(0.9483177697f)); + d1 = spu_madd(x2, spu_splats(0.0326527809f), d0); + + n0 = spu_madd(x , spu_splats(0.1538026623f), spu_splats(0.9483177732f)); + n1 = spu_madd(x , spu_splats(0.0024490478f), spu_splats(0.0305274668f)); + n1 = spu_madd(x2, n1, n0); + + return spu_sel(spu_sub(_expf4(x), spu_splats(1.0f)), + spu_mul(x, _divf4(n1, d1)), + nearzeromask); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/fabsd2.h b/Extras/simdmathlibrary/spu/simdmath/fabsd2.h new file mode 100644 index 0000000..3ba4e39 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/fabsd2.h @@ -0,0 +1,42 @@ +/* fabsd2 - for each of two double slots, compute absolute value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FABSD2_H___ +#define ___SIMD_MATH_FABSD2_H___ + +#include +#include + +static inline vector double +_fabsd2 (vector double x) +{ + return (vec_double2)spu_andc( (vec_ullong2)x, spu_splats(0x8000000000000000ull) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/fabsf4.h b/Extras/simdmathlibrary/spu/simdmath/fabsf4.h new file mode 100644 index 0000000..bad63e5 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/fabsf4.h @@ -0,0 +1,42 @@ +/* fabsf4 - for each of 4 float slots, compute absolute value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FABSF4_H___ +#define ___SIMD_MATH_FABSF4_H___ + +#include +#include + +static inline vector float +_fabsf4 (vector float x) +{ + return (vec_float4)spu_andc( (vec_uint4)x, spu_splats(0x80000000) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/fdimd2.h b/Extras/simdmathlibrary/spu/simdmath/fdimd2.h new file mode 100644 index 0000000..5cbb1a3 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/fdimd2.h @@ -0,0 +1,51 @@ +/* fdimd2 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FDIMD2_H___ +#define ___SIMD_MATH_FDIMD2_H___ + +#include +#include + +/* fdim_v - compute the positive difference of x and y. + */ +static inline vector double +_fdimd2 (vector double x, vector double y) +{ + vec_double2 v; + vec_uint4 mask; + + v = spu_sub(x, y); + mask = (vec_uint4)spu_shuffle(v, v, ((vec_uchar16){0,0,0,0,0,0,0,0, 8,8,8,8,8,8,8,8})); + v = spu_andc(v, (vec_double2)spu_rlmaska(mask, -31)); + + return (v); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/fdimf4.h b/Extras/simdmathlibrary/spu/simdmath/fdimf4.h new file mode 100644 index 0000000..f81482f --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/fdimf4.h @@ -0,0 +1,43 @@ +/* fdimf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FDIMF4_H___ +#define ___SIMD_MATH_FDIMF4_H___ + +#include +#include + +static inline vector float +_fdimf4 (vector float x, vector float y) +{ + vec_float4 diff = spu_sub(x,y); + return spu_sel(spu_splats(0.0f),diff, spu_cmpgt(x,y)); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/floord2.h b/Extras/simdmathlibrary/spu/simdmath/floord2.h new file mode 100644 index 0000000..e249988 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/floord2.h @@ -0,0 +1,99 @@ +/* floord2 - for each of two doule slots, round up to smallest integer not more than the value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FLOORD2_H___ +#define ___SIMD_MATH_FLOORD2_H___ + +#include +#include + +static inline vector double +_floord2(vector double in) +{ + vec_uchar16 swap_words = ((vec_uchar16){4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11}); + vec_uchar16 splat_hi = ((vec_uchar16){0,1,2,3,0,1,2,3, 8,9,10,11, 8,9,10,11}); + vec_uint4 one = ((vec_uint4){0, 1, 0, 1}); + vec_int4 exp, shift; + vec_uint4 mask, mask_1, frac_mask, addend, insert, pos, equal0, e_0, e_00, e_sign, exp_ge0; + vec_ullong2 sign = spu_splats(0x8000000000000000ULL); + vec_double2 in_hi, out; + vec_double2 one_d = spu_splats((double)1.0); + vec_uint4 zero = spu_splats((unsigned int)0x0); + + /* This function generates the following component + * based upon the inputs. + * + * mask = bits of the input that need to be replaced. + * insert = value of the bits that need to be replaced + * addend = value to be added to perform function. + * + * These are applied as follows:. + * + * out = ((in & mask) | insert) + addend + */ + + in_hi = spu_shuffle(in, in, splat_hi); + exp = spu_and(spu_rlmask((vec_int4)in_hi, -20), 0x7FF); + shift = spu_sub(((vec_int4){1023, 1043, 1023, 1043}), exp); + + /* clamp shift to the range 0 to -31. + */ + shift = spu_sel(spu_splats((int)-32), spu_andc(shift, (vec_int4)spu_cmpgt(shift, 0)), spu_cmpgt(shift, -32)); + frac_mask = spu_rlmask(((vec_uint4){0xFFFFF, -1, 0xFFFFF, -1}), shift); + exp_ge0 = spu_cmpgt(exp, 0x3FE); + mask = spu_orc(frac_mask, exp_ge0); + + /* addend = ((in & mask) && (in >= 0)) ? mask+1 : 0 + */ + mask_1 = spu_addx(mask, one, spu_rlqwbyte(spu_genc(mask, one), 4)); + pos = spu_cmpgt((vec_int4)in_hi, -1); + //pos = spu_cmpgt((vec_int4)in_hi, 0x0); //it is also work + equal0 = spu_cmpeq(spu_and((vec_uint4)in, mask), 0); + addend = spu_andc(spu_andc(mask_1, pos), spu_and(equal0, spu_shuffle(equal0, equal0, swap_words))); + + /* insert + */ + e_0 = spu_cmpeq(spu_andc((vec_uint4)in, (vec_uint4)sign), zero); + e_00 = spu_and(e_0, spu_shuffle(e_0, e_0, swap_words)); + // e_sign = spu_sel((vec_uint4)one_d, zero, spu_cmpeq( spu_and((vec_uint4)in_hi, spu_splats((unsigned int)0x80000000)), zero)); + e_sign = spu_andc( (vec_uint4)one_d, spu_cmpeq( spu_and((vec_uint4)in_hi,spu_splats((unsigned int)0x80000000)), zero)); + insert =spu_andc(spu_andc(e_sign, e_00), exp_ge0); + + /* replace insert + */ + in = spu_sel(in, (vec_double2)insert, spu_andc((vec_ullong2)mask, sign)); + + /* in + addend + */ + out = (vec_double2)spu_addx((vec_uint4)in, addend, spu_rlqwbyte(spu_genc((vec_uint4)in, addend), 4)); + + return (out); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/floorf4.h b/Extras/simdmathlibrary/spu/simdmath/floorf4.h new file mode 100644 index 0000000..2e8f625 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/floorf4.h @@ -0,0 +1,58 @@ +/* floorf4 - for each of four float slots, round down to largest integer not greater than the value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FLOORF4_H___ +#define ___SIMD_MATH_FLOORF4_H___ + +#include +#include + +static inline vector float +_floorf4 (vector float x) +{ + vec_int4 xi, xi1; + vec_uint4 inrange; + vec_float4 truncated, truncated1; + + // Find truncated value and one less. + + inrange = spu_cmpabsgt( (vec_float4)spu_splats(0x4b000000), x ); + + xi = spu_convts( x, 0 ); + xi1 = spu_add( xi, -1 ); + + truncated = spu_sel( x, spu_convtf( xi, 0 ), inrange ); + truncated1 = spu_sel( x, spu_convtf( xi1, 0 ), inrange ); + + // If truncated value is greater than input, subtract one. + + return spu_sel( truncated, truncated1, spu_cmpgt( truncated, x ) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/fmad2.h b/Extras/simdmathlibrary/spu/simdmath/fmad2.h new file mode 100644 index 0000000..b1047cd --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/fmad2.h @@ -0,0 +1,42 @@ +/* fmad2 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FMAD2_H___ +#define ___SIMD_MATH_FMAD2_H___ + +#include +#include + +static inline vector double +_fmad2 (vector double x, vector double y, vector double z) +{ + return spu_madd(x,y,z); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/fmaf4.h b/Extras/simdmathlibrary/spu/simdmath/fmaf4.h new file mode 100644 index 0000000..7dd344f --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/fmaf4.h @@ -0,0 +1,42 @@ +/* fmaf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FMAF4_H___ +#define ___SIMD_MATH_FMAF4_H___ + +#include +#include + +static inline vector float +_fmaf4 (vector float x, vector float y, vector float z) +{ + return spu_madd(x,y,z); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/fmaxd2.h b/Extras/simdmathlibrary/spu/simdmath/fmaxd2.h new file mode 100644 index 0000000..944881f --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/fmaxd2.h @@ -0,0 +1,71 @@ +/* fmaxd2 - for each of two double slots, compute maximum of x and y + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FMAXD2_H___ +#define ___SIMD_MATH_FMAXD2_H___ + +#include +#include + +/* Return the maximum numeric value of their arguments. If one argument + * is a NaN, fmax returns the other value. If both are NaNs, then a NaN + * is returned. + */ + +static inline vector double +_fmaxd2 (vector double x, vector double y) +{ + vec_ullong2 selector, denorm; + vec_double2 x_offset, y_offset, diff; + vec_uint4 nan_x, abs_x, gt, eq; + vec_uint4 sign = (vec_uint4){0x80000000, 0, 0x80000000, 0}; + vec_uint4 infinity = (vec_uint4){0x7FF00000, 0, 0x7FF00000, 0}; + vec_uint4 exp0 = (vec_uint4){0x3FF00000, 0, 0x3FF00000, 0}; + + /* If both x and y are denorm or zero, then set 0x3ff to exponent + */ + denorm = (vec_ullong2)spu_cmpeq(spu_and((vec_uint4)spu_or(x, y), infinity), 0); + x_offset = spu_sel(x, spu_or(x, (vec_double2)exp0), denorm); + y_offset = spu_sel(y, spu_or(y, (vec_double2)exp0), denorm); + + /* If x is a NaN, then select y as max + */ + abs_x = spu_andc((vec_uint4)x, sign); + gt = spu_cmpgt(abs_x, infinity); + eq = spu_cmpeq(abs_x, infinity); + nan_x = spu_or(gt, spu_and(eq, spu_rlqwbyte(gt, 4))); + + diff = spu_sub(x_offset, y_offset); + selector = (vec_ullong2)spu_orc(nan_x, spu_cmpgt((vec_int4)diff, -1)); + selector = spu_shuffle(selector, selector, ((vec_uchar16){0,1,2,3, 0,1,2,3, 8,9,10,11, 8,9,10,11})); + + return spu_sel(x, y, selector); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/fmaxf4.h b/Extras/simdmathlibrary/spu/simdmath/fmaxf4.h new file mode 100644 index 0000000..cdaecdc --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/fmaxf4.h @@ -0,0 +1,43 @@ +/* fmaxf4 - for each of four float slots, compute maximum of x and y + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FMAXF4_H___ +#define ___SIMD_MATH_FMAXF4_H___ + +#include +#include + + +static inline vector float +_fmaxf4 (vector float x, vector float y) +{ + return spu_sel( x, y, spu_cmpgt( y, x ) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/fmind2.h b/Extras/simdmathlibrary/spu/simdmath/fmind2.h new file mode 100644 index 0000000..df641c0 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/fmind2.h @@ -0,0 +1,71 @@ +/* fmind2 - for each of two double slots, compute minimum of x and y + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FMIND2_H___ +#define ___SIMD_MATH_FMIND2_H___ + +#include +#include + +/* Return the minimum numeric value of their arguments. If one argument + * is a NaN, fmin returns the other value. If both are NaNs, then a NaN + * is returned. + */ + +static inline vector double +_fmind2 (vector double x, vector double y) +{ + vec_ullong2 selector, denorm; + vec_double2 x_offset, y_offset, diff; + vec_uint4 nan_x, abs_x, gt, eq; + vec_uint4 sign = (vec_uint4){0x80000000, 0, 0x80000000, 0}; + vec_uint4 infinity = (vec_uint4){0x7FF00000, 0, 0x7FF00000, 0}; + vec_uint4 exp0 = (vec_uint4){0x3FF00000, 0, 0x3FF00000, 0}; + + /* If both x and y are denorm or zero, then set 0x3ff to exponent + */ + denorm = (vec_ullong2)spu_cmpeq(spu_and((vec_uint4)spu_or(x, y), infinity), 0); + x_offset = spu_sel(x, spu_or(x, (vec_double2)exp0), denorm); + y_offset = spu_sel(y, spu_or(y, (vec_double2)exp0), denorm); + + /* If x is a NaN, then select y as min + */ + abs_x = spu_andc((vec_uint4)x, sign); + gt = spu_cmpgt(abs_x, infinity); + eq = spu_cmpeq(abs_x, infinity); + nan_x = spu_or(gt, spu_and(eq, spu_rlqwbyte(gt, 4))); + + diff = spu_sub(y_offset, x_offset); + selector = (vec_ullong2)spu_orc(nan_x, spu_cmpgt((vec_int4)diff, -1)); + selector = spu_shuffle(selector, selector, ((vec_uchar16){0,1,2,3, 0,1,2,3, 8,9,10,11, 8,9,10,11})); + + return spu_sel(x, y, selector); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/fminf4.h b/Extras/simdmathlibrary/spu/simdmath/fminf4.h new file mode 100644 index 0000000..c422e60 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/fminf4.h @@ -0,0 +1,43 @@ +/* fminf4 - for each of four float slots, compute minimum of x and y + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FMINF4_H___ +#define ___SIMD_MATH_FMINF4_H___ + +#include +#include + + +static inline vector float +_fminf4 (vector float x, vector float y) +{ + return spu_sel( x, y, spu_cmpgt( x, y ) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/fmodd2.h b/Extras/simdmathlibrary/spu/simdmath/fmodd2.h new file mode 100644 index 0000000..cf7b717 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/fmodd2.h @@ -0,0 +1,282 @@ +/* fmodd2 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FMODD2_H___ +#define ___SIMD_MATH_FMODD2_H___ + +#include +#include + +#include + +/* + * a vector is returned that contains the remainder of xi/yi, + * for coresponding elements of vector double x and vector double y, + * as described below: + * if yi is 0, the result is 0 + * otherwise, the funciton determines the unique signed integer value i + * such that the returned element is xi - i * yi with the same sign as xi and + * magnitude less than |yi| + */ + +static inline vector double +_fmodd2(vector double x, vector double y) +{ + int shift0, shift1; + vec_uchar16 swap_words = (vec_uchar16){4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11}; + vec_uchar16 propagate = (vec_uchar16){4,5,6,7, 192,192,192,192, 12,13,14,15, 192,192,192,192}; + vec_uchar16 splat_hi = (vec_uchar16){0,1,2,3,0,1,2,3, 8,9,10,11, 8,9,10,11}; + vec_uchar16 merge = (vec_uchar16){8,9,10,11,12,13,14,15, 24,25,26,27,28,29,30,31}; + vec_int4 n, shift, power; + vec_uint4 z; + vec_uint4 x_hi, y_hi; + vec_uint4 abs_x, abs_y; + vec_uint4 exp_x, exp_y; + vec_uint4 zero_x, zero_y; + vec_uint4 mant_x, mant_x0, mant_x1, mant_y ; + vec_uint4 norm, denorm, norm0, norm1, denorm0, denorm1; + vec_uint4 result, result0, resultx, cnt, sign, borrow, mask; + vec_uint4 x_7ff, x_inf, x_nan, y_7ff, y_inf, y_nan, is_normal; + vec_uint4 x_is_norm, y_is_norm, frac_x, frac_y, cnt_x, cnt_y, mant_x_norm, mant_y_norm; + vec_uint4 mant_x_denorm0, mant_x_denorm1, mant_x_denorm; + vec_uint4 mant_y_denorm0, mant_y_denorm1, mant_y_denorm; + vec_uint4 lsb = (vec_uint4)(spu_splats(0x0000000000000001ULL)); + vec_uint4 sign_mask = (vec_uint4)(spu_splats(0x8000000000000000ULL)); + vec_uint4 implied_1 = (vec_uint4)(spu_splats(0x0010000000000000ULL)); + vec_uint4 mant_mask = (vec_uint4)(spu_splats(0x000FFFFFFFFFFFFFULL)); + + sign = spu_and((vec_uint4)x, sign_mask); + + abs_x = spu_andc((vec_uint4)x, sign_mask); + abs_y = spu_andc((vec_uint4)y, sign_mask); + + x_hi = spu_shuffle(abs_x, abs_x, splat_hi); + y_hi = spu_shuffle(abs_y, abs_y, splat_hi); + + exp_x = spu_rlmask(x_hi, -20); + exp_y = spu_rlmask(y_hi, -20); + + // y>x + resultx = __vec_gt64(abs_y, abs_x); + + //is Inf, is Nan + x_7ff = spu_cmpgt(x_hi, spu_splats((unsigned int)0x7fefffff)); + x_inf = __vec_eq64_half(abs_x, ((vec_uint4){0x7ff00000,0x0,0x7ff00000,0x0})); + x_nan = spu_andc(x_7ff, x_inf); + + y_7ff = spu_cmpgt(y_hi, spu_splats((unsigned int)0x7fefffff)); + y_inf = __vec_eq64_half(abs_y, ((vec_uint4){0x7ff00000,0x0,0x7ff00000,0x0})); + y_nan = spu_andc(y_7ff, y_inf); + + // is zero + zero_x = __vec_eq64_half(abs_x, spu_splats((unsigned int)0x0)); + zero_y = __vec_eq64_half(abs_y, spu_splats((unsigned int)0x0)); + + + /* Determine ilogb of abs_x and abs_y and + * extract the mantissas (mant_x, mant_y) + */ + /* change form*/ + // 0 -> ! is_normal + // 0 don't care (because (x=0, y!=0)match xx || y<=x + result = spu_sel(spu_andc(result, spu_rlmask(result0, -1)), + (vec_uint4)x, resultx); + //y=+-inf => 0 + result = spu_sel(result, (vec_uint4)x, y_inf); + //x=+-inf => NaN + result = spu_sel(result, ((vec_uint4){0x7ff80000, 0x0, 0x7ff80000, 0x0}), x_inf); + //y=0 => 0 + result = spu_andc(result, zero_y); + + //x=NaN or y=NaN => 0 + result = spu_sel(result, (vec_uint4)x, x_nan); + result = spu_sel(result, (vec_uint4)y, y_nan); + + return ((vec_double2)result); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/fmodf4.h b/Extras/simdmathlibrary/spu/simdmath/fmodf4.h new file mode 100644 index 0000000..61b5473 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/fmodf4.h @@ -0,0 +1,94 @@ +/* fmodf4 - for each of four float slots, compute remainder of x/y defined as x - truncated_integer(x/y) * y. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FMODF4_H___ +#define ___SIMD_MATH_FMODF4_H___ + +#include +#include + +#include +#include +#include + +// +// This returns an accurate result when |divf4(x,y)| < 2^20 and |x| < 2^128, and otherwise returns zero. +// If x == 0, the result is 0. +// If x != 0 and y == 0, the result is undefined. + +static inline vector float +_fmodf4 (vector float x, vector float y) +{ + vec_float4 q, xabs, yabs, qabs, xabs2; + vec_int4 qi0, qi1, qi2; + vec_float4 i0, i1, i2, r1, r2, i; + vec_uint4 inrange; + + // Find i = truncated_integer(|x/y|) + + // If |divf4(x,y)| < 2^20, the quotient is at most off by 1.0. + // Thus i is either the truncated quotient, one less, or one greater. + + q = _divf4( x, y ); + xabs = _fabsf4( x ); + yabs = _fabsf4( y ); + qabs = _fabsf4( q ); + xabs2 = spu_add( xabs, xabs ); + + inrange = spu_cmpabsgt( (vec_float4)spu_splats(0x49800000), q ); + inrange = spu_and( inrange, spu_cmpabsgt( (vec_float4)spu_splats(0x7f800000), x ) ); + + qi1 = spu_convts( qabs, 0 ); + qi0 = spu_add( qi1, -1 ); + qi2 = spu_add( qi1, 1 ); + + i0 = spu_convtf( qi0, 0 ); + i1 = spu_convtf( qi1, 0 ); + i2 = spu_convtf( qi2, 0 ); + + // Correct i will be the largest one such that |x| - i*|y| >= 0. Can test instead as + // 2*|x| - i*|y| >= |x|: + // + // With exact inputs, the negative-multiply-subtract gives the exact result rounded towards zero. + // Thus |x| - i*|y| may be < 0 but still round to zero. However, if 2*|x| - i*|y| < |x|, the computed + // answer will be rounded down to < |x|. 2*|x| can be represented exactly provided |x| < 2^128. + + r1 = spu_nmsub( i1, yabs, xabs2 ); + r2 = spu_nmsub( i2, yabs, xabs2 ); + + i = i0; + i = spu_sel( i1, i, spu_cmpgt( xabs, r1 ) ); + i = spu_sel( i2, i, spu_cmpgt( xabs, r2 ) ); + + i = _copysignf4( i, q ); + + return spu_sel( spu_splats(0.0f), spu_nmsub( i, y, x ), inrange ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/fpclassifyd2.h b/Extras/simdmathlibrary/spu/simdmath/fpclassifyd2.h new file mode 100644 index 0000000..bbccbfc --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/fpclassifyd2.h @@ -0,0 +1,83 @@ +/* fpclassifyd2 - for each element of vector x, return classification of x': FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FPCLASSIFYD2_H___ +#define ___SIMD_MATH_FPCLASSIFYD2_H___ + +#include +#include +#include + +static inline vector signed long long +_fpclassifyd2 (vector double x) +{ + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_uchar16 odd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x04050607, 0x0c0d0e0f, 0x0c0d0e0f }; + vec_uchar16 swapEvenOdd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x00010203, 0x0c0d0e0f, 0x08090a0b }; + + vec_ullong2 sign = spu_splats(0x8000000000000000ull); + vec_ullong2 expn = spu_splats(0x7ff0000000000000ull); + vec_ullong2 signexpn = spu_splats(0xfff0000000000000ull); + vec_ullong2 zero = spu_splats(0x0000000000000000ull); + + vec_ullong2 mask; + vec_llong2 classtype; + vec_uint4 cmpgt, cmpeq; + + //FP_NORMAL: normal unless nan, infinity, zero, or denorm + classtype = spu_splats((long long)FP_NORMAL); + + //FP_NAN: all-ones exponent and non-zero mantissa + cmpgt = spu_cmpgt( (vec_uint4)spu_or( (vec_ullong2)x, sign ), (vec_uint4)signexpn ); + cmpeq = spu_cmpeq( (vec_uint4)spu_or( (vec_ullong2)x, sign ), (vec_uint4)signexpn ); + mask = (vec_ullong2)spu_or( spu_shuffle( cmpgt, cmpgt, even ), + spu_and( spu_shuffle( cmpeq, cmpeq, even ), + spu_shuffle( cmpgt, cmpgt, odd ) ) ); + classtype = spu_sel( classtype, spu_splats((long long)FP_NAN), mask ); + + //FP_INFINITE: all-ones exponent and zero mantissa + mask = (vec_ullong2)spu_and( cmpeq, spu_shuffle( cmpeq, cmpeq, swapEvenOdd ) ); + classtype = spu_sel( classtype, spu_splats((long long)FP_INFINITE), mask ); + + //FP_ZERO: zero exponent and zero mantissa + cmpeq = spu_cmpeq( (vec_uint4)spu_andc( (vec_ullong2)x, sign ), (vec_uint4)zero ); + mask = (vec_ullong2)spu_and( cmpeq, spu_shuffle( cmpeq, cmpeq, swapEvenOdd ) ); + classtype = spu_sel( classtype, spu_splats((long long)FP_ZERO), mask ); + + //FP_SUBNORMAL: zero exponent and non-zero mantissa + cmpeq = spu_cmpeq( (vec_uint4)spu_and( (vec_ullong2)x, expn ), (vec_uint4)zero ); + cmpgt = spu_cmpgt( (vec_uint4)spu_andc( (vec_ullong2)x, signexpn ), (vec_uint4)zero ); + mask = (vec_ullong2)spu_and( spu_shuffle( cmpeq, cmpeq, even ), + spu_or( cmpgt, spu_shuffle( cmpgt, cmpgt, swapEvenOdd ) ) ); + classtype = spu_sel( classtype, spu_splats((long long)FP_SUBNORMAL), mask ); + + return classtype; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/fpclassifyf4.h b/Extras/simdmathlibrary/spu/simdmath/fpclassifyf4.h new file mode 100644 index 0000000..fc251f9 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/fpclassifyf4.h @@ -0,0 +1,67 @@ +/* fpclassifyf4 - for each element of vector x, return classification of x': FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FPCLASSIFYF4_H___ +#define ___SIMD_MATH_FPCLASSIFYF4_H___ + +#include +#include +#include + +static inline vector signed int +_fpclassifyf4 (vector float x) +{ + vec_uint4 zero = spu_splats((unsigned int)0x00000000); + + vec_uint4 mask; + vec_uint4 unclassified = spu_splats((unsigned int)0xffffffff); + vec_int4 classtype = (vec_int4)zero; + + //FP_NAN: NaN not supported on SPU, never return FP_NAN + + //FP_INFINITE: Inf not supported on SPU, never return FP_INFINITE + + //FP_ZERO: zero exponent and zero mantissa + mask = spu_cmpeq( spu_andc( (vec_uint4)x, spu_splats((unsigned int)0x80000000)), zero ); + classtype = spu_sel( classtype, spu_splats((int)FP_ZERO), mask ); + unclassified = spu_andc( unclassified, mask ); + + //FP_SUBNORMAL: zero exponent and non-zero mantissa + mask = spu_and( spu_cmpeq( spu_and( (vec_uint4)x, spu_splats((unsigned int)0x7f800000)), zero ), + spu_cmpgt( spu_and( (vec_uint4)x, spu_splats((unsigned int)0x007fffff)), zero ) ); + classtype = spu_sel( classtype, spu_splats((int)FP_SUBNORMAL), mask ); + unclassified = spu_andc( unclassified, mask ); + + //FP_NORMAL: none of the above + classtype = spu_sel( classtype, spu_splats((int)FP_NORMAL), unclassified ); + + return classtype; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/frexpd2.h b/Extras/simdmathlibrary/spu/simdmath/frexpd2.h new file mode 100644 index 0000000..9564129 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/frexpd2.h @@ -0,0 +1,98 @@ +/* frexpd2 - for each element of vector x, return the normalized fraction and store the exponent of x' + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FREXPD2_H___ +#define ___SIMD_MATH_FREXPD2_H___ + +#include +#include +#include + +#define __FREXPD_DBL_NAN 0x7FF8000000000000ull + +static inline vector double +_frexpd2 (vector double x, vector signed long long *pexp) +{ + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_uchar16 swapEvenOdd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x00010203, 0x0c0d0e0f, 0x08090a0b }; + + vec_ullong2 maskdw = (vec_ullong2){0xffffffffffffffffull, 0ull}; + + vec_ullong2 sign = spu_splats(0x8000000000000000ull); + vec_ullong2 expn = spu_splats(0x7ff0000000000000ull); + vec_ullong2 zero = spu_splats(0x0000000000000000ull); + + vec_ullong2 isnan, isinf, iszero; + vec_ullong2 e0, x0, x1; + vec_uint4 cmpgt, cmpeq, cmpzr; + vec_int4 lz, lz0, sh, ex; + vec_double2 fr, frac = (vec_double2)zero; + + //NAN: x is NaN (all-ones exponent and non-zero mantissa) + cmpgt = spu_cmpgt( (vec_uint4)spu_or( (vec_ullong2)x, sign ), (vec_uint4)spu_or(sign, expn) ); + cmpeq = spu_cmpeq( (vec_uint4)spu_or( (vec_ullong2)x, sign ), (vec_uint4)spu_or(sign, expn) ); + isnan = (vec_ullong2)spu_or( cmpgt, spu_and( cmpeq, spu_rlqwbyte( cmpgt, -4 ) ) ); + isnan = (vec_ullong2)spu_shuffle( isnan, isnan, even ); + frac = spu_sel( frac, (vec_double2)spu_splats(__FREXPD_DBL_NAN), isnan ); + + //INF: x is infinite (all-ones exponent and zero mantissa) + isinf = (vec_ullong2)spu_and( cmpeq, spu_shuffle( cmpeq, cmpeq, swapEvenOdd ) ); + frac = spu_sel( frac, x , isinf ); + + //x is zero (zero exponent and zero mantissa) + cmpzr = spu_cmpeq( (vec_uint4)spu_andc( (vec_ullong2)x, sign ), (vec_uint4)zero ); + iszero = (vec_ullong2)spu_and( cmpzr, spu_shuffle( cmpzr, cmpzr, swapEvenOdd ) ); + + frac = spu_sel( frac, (vec_double2)zero , iszero ); + *pexp = spu_sel( *pexp, (vec_llong2)zero , iszero ); + + //Integer Exponent: if x is normal or subnormal + + //...shift left to normalize fraction, zero shift if normal + lz = (vec_int4)spu_cntlz( (vec_uint4)spu_andc( (vec_ullong2)x, sign) ); + lz0 = (vec_int4)spu_shuffle( lz, lz, even ); + sh = spu_sel( (vec_int4)zero, spu_sub( lz0, spu_splats((int)11) ), spu_cmpgt( lz0, (int)11 ) ); + sh = spu_sel( sh, spu_add( sh, lz ), spu_cmpeq( lz0, (int)32 ) ); + + x0 = spu_slqw( spu_slqwbytebc( spu_and( (vec_ullong2)x, maskdw ), spu_extract(sh, 1) ), spu_extract(sh, 1) ); + x1 = spu_slqw( spu_slqwbytebc( (vec_ullong2)x, spu_extract(sh, 3) ), spu_extract(sh, 3) ); + fr = (vec_double2)spu_sel( x1, x0, maskdw ); + fr = spu_sel( fr, (vec_double2)spu_splats(0x3FE0000000000000ull), expn ); + fr = spu_sel( fr, x, sign ); + + e0 = spu_rlmaskqw( spu_rlmaskqwbyte(spu_and( (vec_ullong2)x, expn ),-6), -4 ); + ex = spu_sel( spu_sub( (vec_int4)e0, spu_splats((int)1022) ), spu_sub( spu_splats((int)-1021), sh ), spu_cmpgt( sh, (int)0 ) ); + + frac = spu_sel( frac, fr, spu_nor( isnan, spu_or( isinf, iszero ) ) ); + *pexp = spu_sel( *pexp, spu_extend( ex ), spu_nor( isnan, spu_or( isinf, iszero ) ) ); + + return frac; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/frexpf4.h b/Extras/simdmathlibrary/spu/simdmath/frexpf4.h new file mode 100644 index 0000000..698f790 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/frexpf4.h @@ -0,0 +1,52 @@ +/* frexpf4 - for each element of vector x, return the normalized fraction and store the exponent of x' + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_FREXPF4_H___ +#define ___SIMD_MATH_FREXPF4_H___ + +#include +#include + +static inline vector float +_frexpf4 (vector float x, vector signed int *pexp) +{ + vec_int4 zeros = spu_splats((int)0); + vec_uint4 zeromask = spu_cmpeq(x, (vec_float4)zeros); + + vec_uint4 expmask = spu_splats(0x7F800000U); + vec_int4 e1 = spu_and((vec_int4)x, (vec_int4)expmask); + vec_int4 e2 = spu_sub(spu_rlmask(e1,-23), spu_splats((int)126)); + *pexp = spu_sel(e2, zeros, zeromask); + + vec_float4 m2 = spu_sel(x, (vec_float4)spu_splats((int)0x3F000000), expmask); + + return spu_sel(m2, (vec_float4)zeros, zeromask); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/hypotd2.h b/Extras/simdmathlibrary/spu/simdmath/hypotd2.h new file mode 100644 index 0000000..e2676d4 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/hypotd2.h @@ -0,0 +1,47 @@ +/* hypotd2 - for each element of vector x and y, return the square root of (x')^2 + (y')^2 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_HYPOTD2_H___ +#define ___SIMD_MATH_HYPOTD2_H___ + +#include +#include + +#include + +static inline vector double +_hypotd2 (vector double x, vector double y) +{ + vec_double2 sum = spu_mul(x,x); + sum = spu_madd(y,y,sum); + + return _sqrtd2(sum); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/hypotf4.h b/Extras/simdmathlibrary/spu/simdmath/hypotf4.h new file mode 100644 index 0000000..b607a84 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/hypotf4.h @@ -0,0 +1,47 @@ +/* hypotf4 - for each element of vector x and y, return the square root of (x')^2 + (y')^2 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_HYPOTF4_H___ +#define ___SIMD_MATH_HYPOTF4_H___ + +#include +#include + +#include + +static inline vector float +_hypotf4 (vector float x, vector float y) +{ + vec_float4 sum = spu_mul(x,x); + sum = spu_madd(y,y,sum); + + return _sqrtf4(sum); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/ilogbd2.h b/Extras/simdmathlibrary/spu/simdmath/ilogbd2.h new file mode 100644 index 0000000..9103925 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/ilogbd2.h @@ -0,0 +1,83 @@ +/* ilogbd2 - for each element of vector x, return integer exponent of normalized double x', FP_ILOGBNAN, or FP_ILOGB0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ILOGBD2_H___ +#define ___SIMD_MATH_ILOGBD2_H___ + +#include +#include +#include +#include + +static inline vector signed long long +_ilogbd2 (vector double x) +{ + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_uchar16 odd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x04050607, 0x0c0d0e0f, 0x0c0d0e0f }; + vec_uchar16 swapEvenOdd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x00010203, 0x0c0d0e0f, 0x08090a0b }; + + vec_ullong2 sign = spu_splats(0x8000000000000000ull); + vec_ullong2 expn = spu_splats(0x7ff0000000000000ull); + vec_ullong2 zero = spu_splats(0x0000000000000000ull); + + vec_ullong2 isnan, iszeroinf; + vec_llong2 ilogb = (vec_llong2)zero; + vec_llong2 e1, e2; + vec_uint4 cmpgt, cmpeq, cmpzr; + vec_int4 lz, lz0, lz1; + + //FP_ILOGBNAN: x is NaN (all-ones exponent and non-zero mantissa) + cmpgt = spu_cmpgt( (vec_uint4)spu_or( (vec_ullong2)x, sign ), (vec_uint4)spu_or(sign, expn) ); + cmpeq = spu_cmpeq( (vec_uint4)spu_or( (vec_ullong2)x, sign ), (vec_uint4)spu_or(sign, expn) ); + isnan = (vec_ullong2)spu_or( spu_shuffle( cmpgt, cmpgt, even ), + spu_and( spu_shuffle( cmpeq, cmpeq, even ), + spu_shuffle( cmpgt, cmpgt, odd ) ) ); + ilogb = spu_sel( ilogb, spu_splats((long long)FP_ILOGBNAN), isnan ); + + //FP_ILOGB0: x is zero (zero exponent and zero mantissa) or infinity (all-ones exponent and zero mantissa) + cmpzr = spu_cmpeq( (vec_uint4)spu_andc( (vec_ullong2)x, sign ), (vec_uint4)zero ); + iszeroinf = (vec_ullong2)spu_or( spu_and( cmpzr, spu_shuffle( cmpzr, cmpzr, swapEvenOdd ) ), + spu_and( cmpeq, spu_shuffle( cmpeq, cmpeq, swapEvenOdd ) ) ); + ilogb = spu_sel( ilogb, spu_splats((long long)FP_ILOGB0), iszeroinf ); + + //Integer Exponent: if x is normal or subnormal, return unbiased exponent of normalized double x + e1 = (vec_llong2)spu_and( (vec_llong2)x, (vec_llong2)expn ); + e2 = (vec_llong2)spu_rlmaskqw( spu_rlmaskqwbyte(e1,-6), -4 ); + + lz = (vec_int4)spu_cntlz( (vec_uint4)spu_andc( (vec_ullong2)x, sign) ); + lz0 = (vec_int4)spu_shuffle( lz, lz, even ); + lz0 = spu_sel( (vec_int4)zero, spu_sub( lz0, spu_splats((int)12) ), spu_cmpgt( lz0, (int)11 ) ); + lz1 = spu_sel( (vec_int4)zero, spu_shuffle( lz, lz, odd), spu_cmpeq( lz0, (int)20 ) ); + + ilogb = spu_sel( ilogb, spu_extend( spu_sub( spu_sub( (vec_int4)e2, spu_splats((int)1023)), spu_add( lz0, lz1 ) ) ), spu_nor( isnan, iszeroinf ) ); + + return ilogb; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/ilogbf4.h b/Extras/simdmathlibrary/spu/simdmath/ilogbf4.h new file mode 100644 index 0000000..6ebd88a --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/ilogbf4.h @@ -0,0 +1,50 @@ +/* ilogbf4 - for each element of vector x, return integer exponent of x', FP_ILOGBNAN, or FP_ILOGB0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ILOGBF4_H___ +#define ___SIMD_MATH_ILOGBF4_H___ + +#include +#include +#include +#include + +static inline vector signed int +_ilogbf4 (vector float x) +{ + vec_int4 minus127 = spu_splats((int)-127); + + vec_int4 e1 = spu_and((vec_int4)x, spu_splats((int)0x7F800000)); + vec_uint4 zeromask = spu_cmpeq(e1, 0); + vec_int4 e2 = spu_add(spu_rlmask(e1,-23), minus127); + + return spu_sel(e2, (vec_int4)spu_splats(FP_ILOGB0), zeromask); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/irintf4.h b/Extras/simdmathlibrary/spu/simdmath/irintf4.h new file mode 100644 index 0000000..4c56db6 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/irintf4.h @@ -0,0 +1,45 @@ +/* irintf4 - for each of four float slots, round to the nearest integer, + consistent with the current rounding model. + On SPU, the rounding mode for float is always towards zero. + vector singned int is returned. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_IRINTF4_H___ +#define ___SIMD_MATH_IRINTF4_H___ + +#include +#include + +static inline vector signed int +_irintf4(vector float in) +{ + return spu_convts(in,0); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/iroundf4.h b/Extras/simdmathlibrary/spu/simdmath/iroundf4.h new file mode 100644 index 0000000..c2cc36c --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/iroundf4.h @@ -0,0 +1,61 @@ +/* iroundf4 - for each of four float slots, round to the nearest integer, + halfway cases are rounded away form zero. + + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_IROUNDF4_H___ +#define ___SIMD_MATH_IROUNDF4_H___ + +#include +#include + +static inline vector signed int +_iroundf4(vector float in) +{ + vec_int4 exp, out; + vec_uint4 addend; + + /* Add 0.5 (fixed precision to eliminate rounding issues + */ + exp = spu_sub(125, spu_and(spu_rlmask((vec_int4)in, -23), 0xFF)); + + addend = spu_and(spu_rlmask( spu_splats((unsigned int)0x1000000), exp), + spu_cmpgt((vec_uint4)exp, -31)); + + in = (vec_float4)spu_add((vec_uint4)in, addend); + + + /* Truncate the result. + */ + out = spu_convts(in,0); + + return (out); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/is0denormd2.h b/Extras/simdmathlibrary/spu/simdmath/is0denormd2.h new file mode 100644 index 0000000..fcc76ce --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/is0denormd2.h @@ -0,0 +1,51 @@ +/* is0denormd2 - for each of two double slots, if input equals 0 or denorm return mask of ones, else 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_IS0DENORMD2_H___ +#define ___SIMD_MATH_IS0DENORMD2_H___ + +#include +#include + + +static inline vector unsigned long long +_is0denormd2 (vector double x) +{ + vec_double2 xexp; + vec_ullong2 cmp; + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + + xexp = (vec_double2)spu_and( (vec_ullong2)x, spu_splats(0x7ff0000000000000ull) ); + cmp = (vec_ullong2)spu_cmpeq( (vec_uint4)xexp, (vec_uint4)spu_splats(0) ); + cmp = spu_shuffle( cmp, cmp, even ); + + return cmp; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/is0denormf4.h b/Extras/simdmathlibrary/spu/simdmath/is0denormf4.h new file mode 100644 index 0000000..97549d7 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/is0denormf4.h @@ -0,0 +1,42 @@ +/* is0denormf4 - for each element of vector x, return a mask of ones if x' is zero or denorm, zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_IS0DENORMF4_H___ +#define ___SIMD_MATH_IS0DENORMF4_H___ + +#include +#include + +static inline vector unsigned int +_is0denormf4 (vector float x) +{ + return spu_cmpeq( (vec_uint4)spu_and( (vec_uint4)x, spu_splats((unsigned int)0x7f800000) ), (vec_uint4)spu_splats(0x00000000) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/isequald2.h b/Extras/simdmathlibrary/spu/simdmath/isequald2.h new file mode 100644 index 0000000..edf48c4 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/isequald2.h @@ -0,0 +1,61 @@ +/* isequald2 - for each of two double slots, if x = y return a mask of ones, else zero + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISEQUALD2_H___ +#define ___SIMD_MATH_ISEQUALD2_H___ + +#include +#include + +#include + +static inline vector unsigned long long +_isequald2 (vector double x, vector double y) +{ + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_uchar16 odd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x04050607, 0x0c0d0e0f, 0x0c0d0e0f }; + vec_uchar16 swapEvenOdd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x00010203, 0x0c0d0e0f, 0x08090a0b }; + vec_ullong2 sign = spu_splats(0x8000000000000000ull); + vec_uint4 cmpeq_i, cmpeq_i_even, cmpeq_i_odd; + vec_ullong2 bothzero; + + cmpeq_i = spu_cmpeq( (vec_int4)x, (vec_int4)y ); + + cmpeq_i_even = spu_shuffle( cmpeq_i, cmpeq_i, even ); + cmpeq_i_odd = spu_shuffle( cmpeq_i, cmpeq_i, odd ); + + bothzero = spu_andc( spu_or( (vec_ullong2)x, (vec_ullong2)y ), sign ); + bothzero = (vec_ullong2)spu_cmpeq( (vec_uint4)bothzero, 0U ); + bothzero = spu_and( bothzero, spu_shuffle( bothzero, bothzero, swapEvenOdd ) ); + + return spu_andc( spu_or( (vec_ullong2)spu_and( cmpeq_i_even, cmpeq_i_odd), bothzero), + spu_or( _isnand2( x ), _isnand2( y ) ) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/isequalf4.h b/Extras/simdmathlibrary/spu/simdmath/isequalf4.h new file mode 100644 index 0000000..8af4d70 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/isequalf4.h @@ -0,0 +1,42 @@ +/* isequalf4 - for each element of vector x and y, return a mask of ones if x' is equal to y', zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISEQUALF4_H___ +#define ___SIMD_MATH_ISEQUALF4_H___ + +#include +#include + +static inline vector unsigned int +_isequalf4 (vector float x, vector float y) +{ + return spu_cmpeq(x, y); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/isfinited2.h b/Extras/simdmathlibrary/spu/simdmath/isfinited2.h new file mode 100644 index 0000000..4efc9c8 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/isfinited2.h @@ -0,0 +1,51 @@ +/* isfinited2 - for each element of vector x, return a mask of ones if x' is finite, zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISFINITED2_H___ +#define ___SIMD_MATH_ISFINITED2_H___ + +#include +#include + +static inline vector unsigned long long +_isfinited2 (vector double x) +{ + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_ullong2 expn = spu_splats(0x7ff0000000000000ull); + vec_ullong2 cmpr; + + //Finite unless NaN or Inf, check for 'not all-ones exponent' + + cmpr = (vec_ullong2)spu_cmpgt( (vec_uint4)expn, (vec_uint4)spu_and( (vec_ullong2)x, expn ) ); + cmpr = spu_shuffle( cmpr, cmpr, even); + + return cmpr; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/isfinitef4.h b/Extras/simdmathlibrary/spu/simdmath/isfinitef4.h new file mode 100644 index 0000000..7846f2e --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/isfinitef4.h @@ -0,0 +1,45 @@ +/* isfinitef4 - for each element of vector x, return a mask of ones if x' is finite, zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISFINITEF4_H___ +#define ___SIMD_MATH_ISFINITEF4_H___ + +#include +#include + +static inline vector unsigned int +_isfinitef4 (vector float x) +{ + (void)x; + + // NaN, INF not supported on SPU, result always a mask of ones + return spu_splats((unsigned int)0xffffffff); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/isgreaterd2.h b/Extras/simdmathlibrary/spu/simdmath/isgreaterd2.h new file mode 100644 index 0000000..d4fa0c7 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/isgreaterd2.h @@ -0,0 +1,71 @@ +/* isgreaterd2 - for each of two double slots, if x > y return mask of ones, else 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISGREATERD2_H___ +#define ___SIMD_MATH_ISGREATERD2_H___ + +#include +#include + +#include + +static inline vector unsigned long long +_isgreaterd2 (vector double x, vector double y) +{ + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_uchar16 odd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x04050607, 0x0c0d0e0f, 0x0c0d0e0f }; + vec_uchar16 swapEvenOdd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x00010203, 0x0c0d0e0f, 0x08090a0b }; + vec_ullong2 sign = spu_splats(0x8000000000000000ull); + vec_uint4 cmpgt_i, cmpgt_ui, cmpeq_i, cmpeq_i_even; + vec_ullong2 cmpgt_ll, cmplt_ll, cmpeq_ll; + vec_ullong2 bothneg, bothzero; + + cmpgt_i = spu_cmpgt( (vec_int4)x, (vec_int4)y ); + cmpeq_i = spu_cmpeq( (vec_int4)x, (vec_int4)y ); + cmpgt_ui = spu_cmpgt( (vec_uint4)x, (vec_uint4)y ); + + cmpeq_i_even = spu_shuffle( cmpeq_i, cmpeq_i, even ); + cmpgt_ll = (vec_ullong2)spu_or( spu_shuffle( cmpgt_i, cmpgt_i, even ), + spu_and( cmpeq_i_even, spu_shuffle( cmpgt_ui, cmpgt_ui, odd ) ) ); + cmpeq_ll = (vec_ullong2)spu_and( cmpeq_i_even, spu_shuffle( cmpeq_i, cmpeq_i, odd ) ); + cmplt_ll = spu_nor( cmpeq_ll, cmpgt_ll ); + + bothzero = spu_andc( spu_or( (vec_ullong2)x, (vec_ullong2)y ), sign ); + bothzero = (vec_ullong2)spu_cmpeq( (vec_uint4)bothzero, 0U ); + bothzero = spu_and( bothzero, spu_shuffle( bothzero, bothzero, swapEvenOdd ) ); + + bothneg = spu_and( (vec_ullong2)x, (vec_ullong2)y ); + bothneg = (vec_ullong2)spu_cmpgt( spu_splats(0), (vec_int4)bothneg ); + bothneg = spu_shuffle( bothneg, bothneg, even ); + + return spu_andc( spu_sel( cmpgt_ll, cmplt_ll, bothneg ), + spu_or( bothzero, spu_or( _isnand2 ( x ), _isnand2 ( y ) ) ) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/isgreaterequald2.h b/Extras/simdmathlibrary/spu/simdmath/isgreaterequald2.h new file mode 100644 index 0000000..5f14988 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/isgreaterequald2.h @@ -0,0 +1,73 @@ +/* isgreaterequald2 - for each of two double slots, if x is greater or equal to y return a mask of ones, else zero + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISGREATEREQUALD2_H___ +#define ___SIMD_MATH_ISGREATEREQUALD2_H___ + +#include +#include + +#include + +static inline vector unsigned long long +_isgreaterequald2 (vector double x, vector double y) +{ + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_uchar16 odd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x04050607, 0x0c0d0e0f, 0x0c0d0e0f }; + vec_uchar16 swapEvenOdd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x00010203, 0x0c0d0e0f, 0x08090a0b }; + vec_ullong2 sign = spu_splats(0x8000000000000000ull); + vec_uint4 cmpgt_i, cmpgt_ui, cmpeq_i, cmpeq_i_even; + vec_ullong2 cmpgt_ll, cmplt_ll, cmpeq_ll; + vec_ullong2 bothneg, bothzero; + + cmpgt_i = spu_cmpgt( (vec_int4)x, (vec_int4)y ); + cmpeq_i = spu_cmpeq( (vec_int4)x, (vec_int4)y ); + cmpgt_ui = spu_cmpgt( (vec_uint4)x, (vec_uint4)y ); + + cmpeq_i_even = spu_shuffle( cmpeq_i, cmpeq_i, even ); + cmpgt_ll = (vec_ullong2)spu_or( spu_shuffle( cmpgt_i, cmpgt_i, even ), + spu_and( cmpeq_i_even, spu_shuffle( cmpgt_ui, cmpgt_ui, odd ) ) ); + cmpeq_ll = (vec_ullong2)spu_and( cmpeq_i_even, spu_shuffle( cmpeq_i, cmpeq_i, odd ) ); + cmplt_ll = spu_nor( cmpeq_ll, cmpgt_ll ); + + bothzero = spu_andc( spu_or( (vec_ullong2)x, (vec_ullong2)y ), sign ); + bothzero = (vec_ullong2)spu_cmpeq( (vec_uint4)bothzero, 0U ); + bothzero = spu_and( bothzero, spu_shuffle( bothzero, bothzero, swapEvenOdd ) ); + + cmpeq_ll = spu_or( cmpeq_ll, bothzero); + + bothneg = spu_and( (vec_ullong2)x, (vec_ullong2)y ); + bothneg = (vec_ullong2)spu_cmpgt( spu_splats(0), (vec_int4)bothneg ); + bothneg = spu_shuffle( bothneg, bothneg, even ); + + return spu_andc( spu_or( spu_sel ( cmpgt_ll, cmplt_ll, bothneg ), cmpeq_ll ), + spu_or( _isnand2 ( x ), _isnand2 ( y ) ) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/isgreaterequalf4.h b/Extras/simdmathlibrary/spu/simdmath/isgreaterequalf4.h new file mode 100644 index 0000000..c952334 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/isgreaterequalf4.h @@ -0,0 +1,46 @@ +/* isgreaterequalf4 - for each element of vector x and y, return a mask of ones if x' is greater than or equal to y', zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISGREATEREQUALF4_H___ +#define ___SIMD_MATH_ISGREATEREQUALF4_H___ + +#include +#include + +static inline vector unsigned int +_isgreaterequalf4 (vector float x, vector float y) +{ + vec_uint4 var; + + var = spu_cmpgt(y, x); + + return spu_nor(var, var); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/isgreaterf4.h b/Extras/simdmathlibrary/spu/simdmath/isgreaterf4.h new file mode 100644 index 0000000..13c4c00 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/isgreaterf4.h @@ -0,0 +1,42 @@ +/* isgreaterf4 - for each element of vector x and y, return a mask of ones if x' is greater than y', zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISGREATERF4_H___ +#define ___SIMD_MATH_ISGREATERF4_H___ + +#include +#include + +static inline vector unsigned int +_isgreaterf4 (vector float x, vector float y) +{ + return spu_cmpgt(x, y); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/isinfd2.h b/Extras/simdmathlibrary/spu/simdmath/isinfd2.h new file mode 100644 index 0000000..ba4d608 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/isinfd2.h @@ -0,0 +1,51 @@ +/* isinfd2 - for each of two double slots, if input equals +Inf or -Inf return mask of ones, else 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISINFD2_H___ +#define ___SIMD_MATH_ISINFD2_H___ + +#include +#include + + +static inline vector unsigned long long +_isinfd2 (vector double x) +{ + vec_uchar16 swapEvenOdd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x00010203, 0x0c0d0e0f, 0x08090a0b }; + vec_double2 xabs; + vec_ullong2 cmp; + + xabs = (vec_double2)spu_andc( (vec_ullong2)x, spu_splats(0x8000000000000000ull) ); + cmp = (vec_ullong2)spu_cmpeq( (vec_uint4)xabs, (vec_uint4)spu_splats(0x7ff0000000000000ull) ); + cmp = spu_and( cmp, spu_shuffle( cmp, cmp, swapEvenOdd ) ); + + return cmp; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/isinff4.h b/Extras/simdmathlibrary/spu/simdmath/isinff4.h new file mode 100644 index 0000000..a3872d7 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/isinff4.h @@ -0,0 +1,45 @@ +/* isinff4 - for each element of vector x, return a mask of ones if x' is INF, zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISINFF4_H___ +#define ___SIMD_MATH_ISINFF4_H___ + +#include +#include + +static inline vector unsigned int +_isinff4 (vector float x) +{ + (void)x; + + // INF not supported on SPU, result always zero + return spu_splats((unsigned int)0x00000000); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/islessd2.h b/Extras/simdmathlibrary/spu/simdmath/islessd2.h new file mode 100644 index 0000000..9278e0e --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/islessd2.h @@ -0,0 +1,71 @@ +/* islessd2 - for each of two double slots, if x < y return a mask of ones, else zero + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISLESSD2_H___ +#define ___SIMD_MATH_ISLESSD2_H___ + +#include +#include + +#include + +static inline vector unsigned long long +_islessd2 (vector double x, vector double y) +{ + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_uchar16 odd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x04050607, 0x0c0d0e0f, 0x0c0d0e0f }; + vec_uchar16 swapEvenOdd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x00010203, 0x0c0d0e0f, 0x08090a0b }; + vec_ullong2 sign = spu_splats(0x8000000000000000ull); + vec_uint4 cmpgt_i, cmpgt_ui, cmpeq_i, cmpeq_i_even; + vec_ullong2 cmpgt_ll, cmplt_ll, cmpeq_ll; + vec_ullong2 bothneg, bothzero; + + cmpgt_i = spu_cmpgt( (vec_int4)y, (vec_int4)x ); + cmpeq_i = spu_cmpeq( (vec_int4)y, (vec_int4)x ); + cmpgt_ui = spu_cmpgt( (vec_uint4)y, (vec_uint4)x ); + + cmpeq_i_even = spu_shuffle( cmpeq_i, cmpeq_i, even ); + cmpgt_ll = (vec_ullong2)spu_or( spu_shuffle( cmpgt_i, cmpgt_i, even ), + spu_and( cmpeq_i_even, spu_shuffle( cmpgt_ui, cmpgt_ui, odd ) ) ); + cmpeq_ll = (vec_ullong2)spu_and( cmpeq_i_even, spu_shuffle( cmpeq_i, cmpeq_i, odd ) ); + cmplt_ll = spu_nor( cmpeq_ll, cmpgt_ll ); + + bothzero = spu_andc( spu_or( (vec_ullong2)x, (vec_ullong2)y ), sign ); + bothzero = (vec_ullong2)spu_cmpeq( (vec_uint4)bothzero, 0U ); + bothzero = spu_and( bothzero, spu_shuffle( bothzero, bothzero, swapEvenOdd ) ); + + bothneg = spu_and( (vec_ullong2)x, (vec_ullong2)y ); + bothneg = (vec_ullong2)spu_cmpgt( spu_splats(0), (vec_int4)bothneg ); + bothneg = spu_shuffle( bothneg, bothneg, even ); + + return spu_andc( spu_sel( cmpgt_ll, cmplt_ll, bothneg ), + spu_or( bothzero, spu_or( _isnand2 ( x ), _isnand2 ( y ) ) ) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/islessequald2.h b/Extras/simdmathlibrary/spu/simdmath/islessequald2.h new file mode 100644 index 0000000..51148cb --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/islessequald2.h @@ -0,0 +1,73 @@ +/* islessequald2 - for each of two double slots, if x <= y return mask of ones, else 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISLESSEQUALD2_H___ +#define ___SIMD_MATH_ISLESSEQUALD2_H___ + +#include +#include + +#include + +static inline vector unsigned long long +_islessequald2 (vector double x, vector double y) +{ + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_uchar16 odd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x04050607, 0x0c0d0e0f, 0x0c0d0e0f }; + vec_uchar16 swapEvenOdd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x00010203, 0x0c0d0e0f, 0x08090a0b }; + vec_ullong2 sign = spu_splats(0x8000000000000000ull); + vec_uint4 cmpgt_i, cmpgt_ui, cmpeq_i, cmpeq_i_even; + vec_ullong2 cmpgt_ll, cmplt_ll, cmpeq_ll; + vec_ullong2 bothneg, bothzero; + + cmpgt_i = spu_cmpgt( (vec_int4)x, (vec_int4)y ); + cmpeq_i = spu_cmpeq( (vec_int4)x, (vec_int4)y ); + cmpgt_ui = spu_cmpgt( (vec_uint4)x, (vec_uint4)y ); + + cmpeq_i_even = spu_shuffle( cmpeq_i, cmpeq_i, even ); + cmpgt_ll = (vec_ullong2)spu_or( spu_shuffle( cmpgt_i, cmpgt_i, even ), + spu_and( cmpeq_i_even, spu_shuffle( cmpgt_ui, cmpgt_ui, odd ) ) ); + cmpeq_ll = (vec_ullong2)spu_and( cmpeq_i_even, spu_shuffle( cmpeq_i, cmpeq_i, odd ) ); + cmplt_ll = spu_nor( cmpeq_ll, cmpgt_ll ); + + bothzero = spu_andc( spu_or( (vec_ullong2)x, (vec_ullong2)y ), sign ); + bothzero = (vec_ullong2)spu_cmpeq( (vec_uint4)bothzero, 0U ); + bothzero = spu_and( bothzero, spu_shuffle( bothzero, bothzero, swapEvenOdd ) ); + + cmpeq_ll = spu_or( cmpeq_ll, bothzero); + + bothneg = spu_and( (vec_ullong2)x, (vec_ullong2)y ); + bothneg = (vec_ullong2)spu_cmpgt( spu_splats(0), (vec_int4)bothneg ); + bothneg = spu_shuffle( bothneg, bothneg, even ); + + return spu_andc( spu_or( spu_sel( cmplt_ll, cmpgt_ll, bothneg ), cmpeq_ll), + spu_or( _isnand2 ( x ), _isnand2 ( y ) ) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/islessequalf4.h b/Extras/simdmathlibrary/spu/simdmath/islessequalf4.h new file mode 100644 index 0000000..5e6b5f5 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/islessequalf4.h @@ -0,0 +1,46 @@ +/* islessequalf4 - for each element of vector x and y, return a mask of ones if x' is less than or equal to y', zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISLESSEQUALF4_H___ +#define ___SIMD_MATH_ISLESSEQUALF4_H___ + +#include +#include + +static inline vector unsigned int +_islessequalf4 (vector float x, vector float y) +{ + vec_uint4 var; + + var = spu_cmpgt(x, y); + + return spu_nor(var, var); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/islessf4.h b/Extras/simdmathlibrary/spu/simdmath/islessf4.h new file mode 100644 index 0000000..ca84fae --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/islessf4.h @@ -0,0 +1,42 @@ +/* islessf4 - for each element of vector x and y, return a mask of ones if x' is less than y', zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISLESSF4_H___ +#define ___SIMD_MATH_ISLESSF4_H___ + +#include +#include + +static inline vector unsigned int +_islessf4 (vector float x, vector float y) +{ + return spu_cmpgt(y, x); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/islessgreaterd2.h b/Extras/simdmathlibrary/spu/simdmath/islessgreaterd2.h new file mode 100644 index 0000000..7c23c8b --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/islessgreaterd2.h @@ -0,0 +1,61 @@ +/* islessgreaterd2 - for each of two double slots, if x is less or greater than y return a mask of ones, else zero + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISLESSGREATERD2_H___ +#define ___SIMD_MATH_ISLESSGREATERD2_H___ + +#include +#include + +#include + +static inline vector unsigned long long +_islessgreaterd2 (vector double x, vector double y) +{ + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_uchar16 odd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x04050607, 0x0c0d0e0f, 0x0c0d0e0f }; + vec_uchar16 swapEvenOdd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x00010203, 0x0c0d0e0f, 0x08090a0b }; + vec_ullong2 sign = spu_splats(0x8000000000000000ull); + vec_uint4 cmpeq_i, cmpeq_i_even, cmpeq_i_odd; + vec_ullong2 bothzero; + + cmpeq_i = spu_cmpeq( (vec_int4)x, (vec_int4)y ); + + cmpeq_i_even = spu_shuffle( cmpeq_i, cmpeq_i, even ); + cmpeq_i_odd = spu_shuffle( cmpeq_i, cmpeq_i, odd ); + + bothzero = spu_andc( spu_or( (vec_ullong2)x, (vec_ullong2)y ), sign ); + bothzero = (vec_ullong2)spu_cmpeq( (vec_uint4)bothzero, 0U ); + bothzero = spu_and( bothzero, spu_shuffle( bothzero, bothzero, swapEvenOdd ) ); + + return spu_andc( (vec_ullong2)spu_nand( cmpeq_i_even, cmpeq_i_odd), + spu_or( bothzero, spu_or( _isnand2 ( x ), _isnand2 ( y ) ) ) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/islessgreaterf4.h b/Extras/simdmathlibrary/spu/simdmath/islessgreaterf4.h new file mode 100644 index 0000000..0143b49 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/islessgreaterf4.h @@ -0,0 +1,46 @@ +/* islessgreaterf4 - for each element of vector x and y, return a mask of ones if x' is less than or greater than y', zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISLESSGREATERF4_H___ +#define ___SIMD_MATH_ISLESSGREATERF4_H___ + +#include +#include + +static inline vector unsigned int +_islessgreaterf4 (vector float x, vector float y) +{ + vec_uint4 var; + + var = spu_cmpeq(x, y); + + return spu_nor(var, var); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/isnand2.h b/Extras/simdmathlibrary/spu/simdmath/isnand2.h new file mode 100644 index 0000000..eabb20c --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/isnand2.h @@ -0,0 +1,56 @@ +/* isnand2 - for each of two double slots, if input is any type of NaN return mask of ones, else 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISNAND2_H___ +#define ___SIMD_MATH_ISNAND2_H___ + +#include +#include + +static inline vector unsigned long long +_isnand2 (vector double x) +{ + vec_double2 xneg; + vec_ullong2 cmpgt, cmpeq, cmpnan; + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_uchar16 odd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x04050607, 0x0c0d0e0f, 0x0c0d0e0f }; + vec_uint4 expmask = (vec_uint4)spu_splats(0xfff0000000000000ull); + + xneg = (vec_double2)spu_or( (vec_ullong2)x, spu_splats(0x8000000000000000ull) ); + cmpgt = (vec_ullong2)spu_cmpgt( (vec_uint4)xneg, expmask ); + cmpeq = (vec_ullong2)spu_cmpeq( (vec_uint4)xneg, expmask ); + + cmpnan = spu_or( spu_shuffle( cmpgt, cmpgt, even ), + spu_and( spu_shuffle( cmpeq, cmpeq, even ), + spu_shuffle( cmpgt, cmpgt, odd ) ) ); + + return cmpnan; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/isnanf4.h b/Extras/simdmathlibrary/spu/simdmath/isnanf4.h new file mode 100644 index 0000000..6dabfd0 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/isnanf4.h @@ -0,0 +1,45 @@ +/* isnanf4 - for each element of vector x, return a mask of ones if x' is NaN, zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISNANF4_H___ +#define ___SIMD_MATH_ISNANF4_H___ + +#include +#include + +static inline vector unsigned int +_isnanf4 (vector float x) +{ + (void)x; + + // NaN not supported on SPU, result always zero + return spu_splats((unsigned int)0x00000000); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/isnormald2.h b/Extras/simdmathlibrary/spu/simdmath/isnormald2.h new file mode 100644 index 0000000..72d6c4d --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/isnormald2.h @@ -0,0 +1,53 @@ +/* isnormald2 - for each element of vector x, return a mask of ones if x' is normal, not a NaN or INF, zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISNORMALD2_H___ +#define ___SIMD_MATH_ISNORMALD2_H___ + +#include +#include + +static inline vector unsigned long long +_isnormald2 (vector double x) +{ + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_ullong2 expn = spu_splats(0x7ff0000000000000ull); + vec_ullong2 cmpr; + + //Normal unless nan, infinite, denorm, or zero + + //Check for 'not zero or all-ones exponent' + cmpr = (vec_ullong2)spu_and( spu_cmpgt( (vec_uint4)spu_and( (vec_ullong2)x, expn ), (vec_uint4)spu_splats(0x0000000000000000ull) ), + spu_cmpgt( (vec_uint4)expn, (vec_uint4)spu_and( (vec_ullong2)x, expn ) ) ); + cmpr = spu_shuffle( cmpr, cmpr, even); + + return cmpr; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/isnormalf4.h b/Extras/simdmathlibrary/spu/simdmath/isnormalf4.h new file mode 100644 index 0000000..b0420d5 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/isnormalf4.h @@ -0,0 +1,43 @@ +/* isnormalf4 - for each element of vector x, return a mask of ones if x' is normal, not a NaN or INF, zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISNORMALF4_H___ +#define ___SIMD_MATH_ISNORMALF4_H___ + +#include +#include + +static inline vector unsigned int +_isnormalf4 (vector float x) +{ + // NaN, INF not supported on SPU; normal unless zero + return spu_cmpabsgt(x, (vector float)spu_splats(0x00000000)); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/isunorderedd2.h b/Extras/simdmathlibrary/spu/simdmath/isunorderedd2.h new file mode 100644 index 0000000..f5bd7b4 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/isunorderedd2.h @@ -0,0 +1,67 @@ +/* isunorderedd2 - for each element of vector x and y, return a mask of ones if x' is unordered to y', zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISUNORDEREDD2_H___ +#define ___SIMD_MATH_ISUNORDEREDD2_H___ + +#include +#include + +static inline vector unsigned long long +_isunorderedd2 (vector double x, vector double y) +{ + vec_double2 neg; + vec_ullong2 cmpgt, cmpeq, cmpnanx, cmpnany; + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_uchar16 odd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x04050607, 0x0c0d0e0f, 0x0c0d0e0f }; + vec_ullong2 expn = (vec_ullong2)spu_splats(0xfff0000000000000ull); + vec_ullong2 sign = (vec_ullong2)spu_splats(0x8000000000000000ull); + + //Check if x is nan + neg = (vec_double2)spu_or( (vec_ullong2)x, sign ); + cmpgt = (vec_ullong2)spu_cmpgt( (vec_uint4)neg, (vec_uint4)expn ); + cmpeq = (vec_ullong2)spu_cmpeq( (vec_uint4)neg, (vec_uint4)expn ); + + cmpnanx = spu_or( spu_shuffle( cmpgt, cmpgt, even ), + spu_and( spu_shuffle( cmpeq, cmpeq, even ), + spu_shuffle( cmpgt, cmpgt, odd ) ) ); + + //Check if y is nan + neg = (vec_double2)spu_or( (vec_ullong2)y, sign ); + cmpgt = (vec_ullong2)spu_cmpgt( (vec_uint4)neg, (vec_uint4)expn ); + cmpeq = (vec_ullong2)spu_cmpeq( (vec_uint4)neg, (vec_uint4)expn ); + + cmpnany = spu_or( spu_shuffle( cmpgt, cmpgt, even ), + spu_and( spu_shuffle( cmpeq, cmpeq, even ), + spu_shuffle( cmpgt, cmpgt, odd ) ) ); + + return spu_or( cmpnanx, cmpnany ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/isunorderedf4.h b/Extras/simdmathlibrary/spu/simdmath/isunorderedf4.h new file mode 100644 index 0000000..917bf4a --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/isunorderedf4.h @@ -0,0 +1,46 @@ +/* isunorderedf4 - for each element of vector x and y, return a mask of ones if x' is unordered to y', zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ISUNORDEREDF4_H___ +#define ___SIMD_MATH_ISUNORDEREDF4_H___ + +#include +#include + +static inline vector unsigned int +_isunorderedf4 (vector float x, vector float y) +{ + (void)x; + (void)y; + + // NaN not supported on SPU, result always zero + return spu_splats((unsigned int)0x00000000); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/ldexpd2.h b/Extras/simdmathlibrary/spu/simdmath/ldexpd2.h new file mode 100644 index 0000000..a5d9a0e --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/ldexpd2.h @@ -0,0 +1,266 @@ +/* ldexpd2 - Multiply Double by 2 Raised to its Power + For large elements of ex (overflow), returns HUGE_VALF + For small elements of ex (underflow), returns 0. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LDEXPD2_H___ +#define ___SIMD_MATH_LDEXPD2_H___ + +#include +#include + +static inline vector double +_ldexpd2(vector double x, vector signed long long ex) +{ + vec_int4 e1, e2; + vec_int4 min = spu_splats(-2099); + // vec_int4 min = spu_splats(-2044); + vec_int4 max = spu_splats( 2098); + // vec_int4 max = spu_splats( 2046); + vec_uint4 cmp_min, cmp_max; + vec_uint4 shift = ((vec_uint4){20, 32, 20, 32}); + vec_double2 f1, f2; + vec_double2 out; + vec_double2 in = x; + vec_int4 exp_in; + + // check input data range + vec_int4 exp0 = spu_shuffle( (vec_int4)ex, (vec_int4)ex, ((vec_uchar16){4,5,6,7, 4,5,6,7, 12,13,14,15, 12,13,14,15})); + vec_int4 dmy = spu_shuffle( (vec_int4)spu_splats(0x10000), (vec_int4)ex, ((vec_uchar16){16,1,2,3, 16,1,2,3, 24,1,2,3,24,1,2,3})); + // (-)0xFFFFFFFF80000000 or (+)0x000000007FFFFFFF + vec_int4 msk_range = ((vec_int4){0,0x80000000, 0,0x80000000}); + vec_int4 inrange = spu_addx( (vec_int4)ex, msk_range, spu_rlqwbyte(spu_genc((vec_int4)ex, msk_range), 4)); + inrange = (vec_int4)spu_cmpeq( inrange, 0 ); + inrange = spu_shuffle(inrange,inrange,((vec_uchar16){0,1,2,3,0,1,2,3,8,9,10,11,8,9,10,11})); + + // select dummy over ranged data or input data + vec_int4 exp = spu_sel( dmy, exp0, (vec_uint4)inrange); + exp_in = exp; + /* Clamp the specified exponent to the range -2044 to 2046. + */ + cmp_min = spu_cmpgt(exp, min); + cmp_max = spu_cmpgt(exp, max); + exp = spu_sel(min, exp, cmp_min); + exp = spu_sel(exp, max, cmp_max); + + /* Generate the factors f1 = 2^e1 and f2 = 2^e2 + */ + e1 = spu_rlmaska(exp, -1); + e2 = spu_sub(exp, e1); + + f1 = (vec_double2)spu_sl(spu_add(e1, 1023), shift); + + vec_double2 otmp = spu_mul(x, f1); + vec_uint4 fpscr1 = spu_mffpscr(); + + f2 = (vec_double2)spu_sl(spu_add(e2, 1023), shift); + + out = spu_mul(otmp, f2); + vec_uint4 fpscr2 = spu_mffpscr(); + + /* Compute the product x * 2^e1 * 2^e2 + */ + // out = spu_mul(spu_mul(x, f1), f2); + + // check floating point register DENORM bit + vec_uint4 fpscr0, fpscr; + fpscr0 = spu_or(fpscr1, fpscr2); + fpscr = spu_shuffle(fpscr0, fpscr0, ((vec_uchar16){0x80,0x80,0x80,0x80,0x80,0x80,10,0x80,0x80,0x80,6,0x80,0x80,0x80,0x80,0x80})); + fpscr = spu_or(fpscr0, fpscr); + if ( __builtin_expect(spu_extract(fpscr, 1) == 0, 1) ) return out; + + + ////////////////////// + // Denormalized calc// + ////////////////////// + + vec_uchar16 splat_msb = { 0,0,0,0,0,0,0,0, 8,8,8,8,8,8,8,8}; + vec_uint4 signmask = ((vec_uint4){0x80000000,0,0x80000000,0}); + vec_int4 zeros = spu_splats(0); + vec_uchar16 msk_64_eq = ((vec_uchar16){4,5,6,7,0,1,2,3,12,13,14,15,8,9,10,11}); + + //check input was zero + vec_uint4 x_body = spu_and( (vec_uint4)x, ((vec_uint4){0x7FFFFFFF,-1,0x7FFFFFFF,-1})); + vec_uint4 x_zero = spu_cmpeq( x_body, (vec_uint4)zeros ); + x_zero = spu_and( x_zero, spu_shuffle(x_zero,x_zero,msk_64_eq)); + + // check Denormalized input + vec_int4 cnt_zero = (vec_int4)spu_cntlz(x_body); + vec_uint4 is_den = (vec_uint4)spu_cmpgt(cnt_zero, 11); // Denormalized data 000XXXXX XXXXXXXX + is_den = spu_shuffle( is_den, is_den, splat_msb); + is_den = spu_sel(is_den, (vec_uint4)zeros, x_zero); // exclude zero from denormalized + + // count 0bits for 64bit + vec_uint4 cnt_ex = (vec_uint4)spu_cmpgt(cnt_zero, 31); // Denormalized data 00000000 XXXXXXXX + vec_int4 cnt_z = spu_shuffle( cnt_zero, cnt_zero, ((vec_uchar16){4,5,6,7,0,1,2,3,12,13,14,15,8,9,10,11})); + cnt_zero = spu_add(cnt_zero, spu_sel(zeros, cnt_z, cnt_ex)); + cnt_zero = spu_shuffle(cnt_zero, cnt_zero, ((vec_uchar16){0,1,2,3,0,1,2,3,8,9,10,11,8,9,10,11})); + + // extract each 64bit data + x_body = spu_and( (vec_uint4)x, ((vec_uint4){0x000FFFFF,-1,0x000FFFFF,-1})); + vec_uint4 mant0 = spu_shuffle(x_body, x_body, ((vec_uchar16){0,1, 2, 3, 4, 5, 6, 7,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80})); + vec_uint4 mant1 = spu_shuffle(x_body, x_body, ((vec_uchar16){8,9,10,11,12,13,14,15,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80})); + vec_uint4 sign = (vec_uint4)spu_rlmaska((vec_int4)exp_in, -31); + sign = spu_shuffle(sign, sign, splat_msb); + + // set max shift count + vec_int4 sht = spu_add( cnt_zero, ((vec_int4){-11,-64,-11,-64})); + + // denorm & exp+ shift left + vec_uint4 cmp = spu_cmpgt( sht, exp_in); + vec_int4 sht_l = spu_sel(sht, exp_in, cmp); + int shtl0 = spu_extract(sht_l, 0); + int shtl1 = spu_extract(sht_l, 2); + vec_uint4 mant0l = spu_slqwbytebc( spu_slqw(mant0, shtl0), shtl0 ); + vec_uint4 mant1l = spu_slqwbytebc( spu_slqw(mant1, shtl1), shtl1 ); + vec_int4 expp = spu_shuffle(spu_sub(exp_in, sht_l), zeros, ((vec_uchar16){0,1,2,3,0,1,2,3,8,9,10,11,8,9,10,11})); + + exp0 = spu_sel( expp, exp_in, sign ); // select plus or minus caluc + vec_uint4 mantl = spu_shuffle( mant0l, mant1l, ((vec_uchar16){0,1,2,3,4,5,6,7,16,17,18,19,20,21,22,23})); + vec_uint4 mant = spu_sel( mantl, (vec_uint4)x, sign); + exp = spu_sel( exp_in, exp0, is_den ); // select denormalized + x = (vec_double2)spu_sel( (vec_uint4)x, mant, is_den); + + + ////////////////////////////////////////////////////////////////////////// + // from ldexpf4 + vec_int4 expmask = ((vec_int4){0x7FF00000, 0, 0x7FF00000, 0}); + e1 = spu_and((vec_int4)x, expmask); + e2 = spu_rlmask(e1,-20); + + vec_uchar16 maxmask = (vec_uchar16)spu_cmpgt(exp, 2046); + vec_uchar16 minmask = (vec_uchar16)spu_cmpgt(spu_splats(-2044), exp); + minmask = spu_or (minmask, (vec_uchar16)x_zero); + + vec_int4 esum = spu_add(e2, exp); + + maxmask = spu_or (maxmask, (vec_uchar16)spu_cmpgt(esum, 2046)); + maxmask = spu_shuffle(maxmask, maxmask, splat_msb); + // maxmask = spu_and(maxmask, ((vec_uchar16)spu_splats((long long)0x7FFFFFFFFFFFFFFFLL))); + minmask = spu_or (minmask, (vec_uchar16)spu_cmpgt(zeros, esum)); + minmask = spu_shuffle(minmask, minmask, splat_msb); + + // check denorm + vec_uint4 mxmask = spu_and(spu_cmpgt(e2, 0), ((vec_uint4){0x00100000,0,0x00100000,0})); // not denorm + vec_int4 esum2 = spu_sub(esum, (vec_int4)spu_rlmask(mxmask, -20)); // reverse to norm + vec_uint4 mrange = spu_and(spu_cmpgt(zeros, esum2), spu_cmpgt(esum2, -55)); // denorm range + mrange = spu_shuffle(mrange, mrange, splat_msb); + + vec_int4 sht_r = spu_sel(spu_splats(-54), esum2, spu_cmpgt(esum2, spu_splats(-54)) ); + vec_int4 sht_rh = spu_add( sht_r, ((vec_int4){7,7,7,7})); + + x_body = spu_or( x_body, mxmask ); + mant0 = spu_shuffle(x_body, x_body, ((vec_uchar16){0,1, 2, 3, 4, 5, 6, 7,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80})); + mant1 = spu_shuffle(x_body, x_body, ((vec_uchar16){8,9,10,11,12,13,14,15,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80})); + vec_uint4 mant0r = spu_rlmaskqwbytebc( spu_rlmaskqw(mant0, spu_extract(sht_r, 0)), spu_extract(sht_rh,0) ); + vec_uint4 mant1r = spu_rlmaskqwbytebc( spu_rlmaskqw(mant1, spu_extract(sht_r, 2)), spu_extract(sht_rh,2) ); + +#ifdef LDEXPD2_ROUND + // check current round mode + fpscr = spu_shuffle(fpscr2, fpscr2, ((vec_uchar16){0x80,0x80,0x80,0x80,0,1,2,3,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80})); + fpscr0 = spu_and(fpscr, ((vec_uint4){0,0xc00,0,0})); + fpscr1 = spu_and(fpscr, ((vec_uint4){0,0x300,0,0})); + + // prepare round data + vec_uint4 rnd0 = spu_slqwbytebc( spu_slqw( mant0r, 31), 31); + vec_uint4 rnd1 = spu_slqwbytebc( spu_slqw( mant1r, 31), 31); + vec_uint4 rnd0w = (vec_uint4)spu_cntb( (vec_uchar16)rnd0 ); + vec_uint4 rnd1w = (vec_uint4)spu_cntb( (vec_uchar16)rnd1 ); + rnd0w = spu_or( spu_slqwbyte(rnd0w,4), spu_slqwbyte(rnd0w,8)); + rnd1w = spu_or( spu_slqwbyte(rnd1w,4), spu_slqwbyte(rnd1w,8)); + rnd0 = spu_or( rnd0, rnd0w); + rnd1 = spu_or( rnd1, rnd1w); + + // nearest + // check half + vec_uint4 hit0 = spu_cmpeq(rnd0, ((vec_uint4){0,0xc0000000,0,0})); //odd + round out + vec_uint4 hit1 = spu_cmpeq(rnd1, ((vec_uint4){0,0xc0000000,0,0})); //odd + round out + vec_uint4 add0 = spu_sel((vec_uint4)zeros, ((vec_uint4){0,1,0,0}), hit0); + vec_uint4 add1 = spu_sel((vec_uint4)zeros, ((vec_uint4){0,1,0,0}), hit1); + // check greater than half + rnd0 = spu_and( rnd0, ((vec_uint4){0,0x7FFFFFFF,0,0})); + rnd1 = spu_and( rnd1, ((vec_uint4){0,0x7FFFFFFF,0,0})); + hit0 = spu_cmpgt(rnd0, ((vec_uint4){0,0x40000000,0,0})); + hit1 = spu_cmpgt(rnd1, ((vec_uint4){0,0x40000000,0,0})); + add0 = spu_sel(add0, ((vec_uint4){0,1,0,0}), hit0); + add1 = spu_sel(add1, ((vec_uint4){0,1,0,0}), hit1); + // select if fp0 + add0 = spu_sel((vec_uint4)zeros, add0, spu_cmpeq(fpscr0, (vec_uint4)zeros)); + add1 = spu_sel((vec_uint4)zeros, add1, spu_cmpeq(fpscr1, (vec_uint4)zeros)); + + // toward zero do nothing + // upward + sign = spu_rlmaska((vec_uint4)in, -31); + vec_uint4 sign0 = spu_shuffle(sign, sign, ((vec_uchar16){0x80,0x80,0x80,0x80,0,0,0,0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80})); + vec_uint4 sign1 = spu_shuffle(sign, sign, ((vec_uchar16){0x80,0x80,0x80,0x80,8,8,8,8,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80})); + vec_uint4 hit0w = spu_cmpgt(rnd0, ((vec_uint4){0,0,0,0})); + vec_uint4 hit1w = spu_cmpgt(rnd1, ((vec_uint4){0,0,0,0})); + + hit0 = spu_andc(hit0w, sign0); + hit1 = spu_andc(hit1w, sign1); + hit0 = spu_and(hit0, spu_cmpeq(fpscr0, ((vec_uint4){0,0x800,0,0}))); + hit1 = spu_and(hit1, spu_cmpeq(fpscr1, ((vec_uint4){0,0x200,0,0}))); + // select if fp2 + add0 = spu_sel(add0, ((vec_uint4){0,1,0,0}), hit0); + add1 = spu_sel(add1, ((vec_uint4){0,1,0,0}), hit1); + + // downward + hit0 = spu_and(hit0w, sign0); + hit1 = spu_and(hit1w, sign1); + hit0 = spu_and(hit0, spu_cmpeq(fpscr0, ((vec_uint4){0,0xc00,0,0}))); + hit1 = spu_and(hit1, spu_cmpeq(fpscr1, ((vec_uint4){0,0x300,0,0}))); + // select if fp3 + add0 = spu_sel(add0, ((vec_uint4){0,1,0,0}), hit0); + add1 = spu_sel(add1, ((vec_uint4){0,1,0,0}), hit1); + + // calc round + mant0r = spu_addx(mant0r, add0, spu_rlqwbyte(spu_genc(mant0r, add0), 4)); + mant1r = spu_addx(mant1r, add1, spu_rlqwbyte(spu_genc(mant1r, add1), 4)); + +#endif // LDEXPD2_ROUND + + vec_uint4 mantr = spu_shuffle( mant0r, mant1r, ((vec_uchar16){0,1,2,3,4,5,6,7,16,17,18,19,20,21,22,23})); + + // select right answer + x = spu_sel(x, (vec_double2)spu_sl(esum,20), (vec_ullong2)expmask); + x = spu_sel(x, (vec_double2)zeros, (vec_ullong2)minmask); + x = spu_sel(x, (vec_double2)spu_splats((long long)0x7FEFFFFFFFFFFFFFLL), (vec_ullong2)maxmask); + + out = (vec_double2)spu_sel((vec_uint4)x , mantr, mrange); + + // check Infinity,NaN + vec_uint4 is_inf = spu_cmpeq(e1, expmask); + is_inf = spu_and( is_inf, spu_shuffle(is_inf,is_inf,msk_64_eq)); + out = (vec_double2)spu_sel((vec_uint4)out , (vec_uint4)in, is_inf); + + out = spu_sel(out, in, (vec_ullong2)signmask); + return out; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/ldexpf4.h b/Extras/simdmathlibrary/spu/simdmath/ldexpf4.h new file mode 100644 index 0000000..d698457 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/ldexpf4.h @@ -0,0 +1,62 @@ +/* ldexpf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LDEXPF4_H___ +#define ___SIMD_MATH_LDEXPF4_H___ + +#include +#include + +static inline vector float +_ldexpf4 (vector float x, vector signed int exp) +{ + vec_int4 zeros = spu_splats(0); + + vec_uint4 expmask = spu_splats(0x7F800000U); + vec_int4 e1 = spu_and((vec_int4)x, (vec_int4)expmask); + vec_int4 e2 = spu_rlmask(e1,-23); + + vec_uint4 maxmask = spu_cmpgt(exp, 255); + vec_uint4 minmask = spu_cmpgt(spu_splats(-255), exp); + minmask = spu_or (minmask, spu_cmpeq(x, (vec_float4)zeros)); + + vec_int4 esum = spu_add(e2, exp); + + maxmask = spu_or (maxmask, spu_cmpgt(esum, 255)); + maxmask = spu_and(maxmask, spu_splats(0x7FFFFFFFU)); + minmask = spu_or (minmask, spu_cmpgt(zeros, esum)); + + x = spu_sel(x, (vec_float4)spu_sl(esum,23), expmask); + x = spu_sel(x, (vec_float4)zeros, minmask); + //x = spu_sel(x, (vec_float4)spu_splats((int)0xFFFFFFFF), maxmask); + x = spu_sel(x, (vec_float4)maxmask, maxmask); + return x; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/llabsi2.h b/Extras/simdmathlibrary/spu/simdmath/llabsi2.h new file mode 100644 index 0000000..3041988 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/llabsi2.h @@ -0,0 +1,50 @@ +/* llabsi2 - returns absolute value of input. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LLABSI2_H___ +#define ___SIMD_MATH_LLABSI2_H___ + +#include +#include + +static inline vector signed long long +_llabsi2 (vector signed long long in) +{ + vec_uint4 sign = (vec_uint4)spu_rlmaska((vec_int4)in, -31); + sign = spu_shuffle(sign, sign, ((vec_uchar16){ 0,0,0,0,0,0,0,0, 8,8,8,8,8,8,8,8})); + + vec_uint4 add_1 = ((vec_uint4){0,1,0,1}); + vec_uint4 res = spu_nor((vec_uint4)in, (vec_uint4)in); + res = spu_addx( res, add_1, spu_slqwbyte(spu_genc(res, add_1), 4)); + res = spu_sel( (vec_uint4)in, res, sign); + + return ((vec_llong2)(res)); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/lldivi2.h b/Extras/simdmathlibrary/spu/simdmath/lldivi2.h new file mode 100644 index 0000000..c0a8ca2 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/lldivi2.h @@ -0,0 +1,85 @@ +/* lldivi2 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LLDIVI2_H___ +#define ___SIMD_MATH_LLDIVI2_H___ + +#include +#include + +#include +#include + +static inline vector signed long long +__lldivi2_negatell2 (vector signed long long x) +{ + vector signed int zero = (vector signed int){0,0,0,0}; + vector signed int borrow; + + borrow = spu_genb(zero, (vec_int4)x); + borrow = spu_shuffle(borrow, borrow, ((vec_uchar16){4,5,6,7, 0xc0,0xc0,0xc0,0xc0, 12,13,14,15, 0xc0,0xc0,0xc0,0xc0})); + return (vec_llong2)spu_subx(zero, (vec_int4)x, borrow); +} + +// lldivi2 - for each of two signed long long interger slots, compute quotient and remainder of +// numer/denom and store in lldivi2_t struct. Divide by zero produces quotient = 0, remainder = numerator. + +static inline lldivi2_t +_lldivi2 (vector signed long long numer, vector signed long long denom) +{ + lldivi2_t res; + lldivu2_t resAbs; + vec_ullong2 numerAbs, denomAbs; + vec_uint4 numerPos, denomPos, quotNeg; + + // Determine whether result needs sign change + + numerPos = spu_cmpgt((vec_int4)numer, -1); + numerPos = spu_shuffle(numerPos, numerPos, ((vec_uchar16){0,0,0,0,0,0,0,0, 8,8,8,8,8,8,8,8})); + denomPos = spu_cmpgt((vec_int4)denom, -1); + denomPos = spu_shuffle(denomPos, denomPos, ((vec_uchar16){0,0,0,0,0,0,0,0, 8,8,8,8,8,8,8,8})); + quotNeg = spu_xor( numerPos, denomPos ); + + // Use absolute values of numerator, denominator + + numerAbs = (vec_ullong2)spu_sel(__lldivi2_negatell2(numer), numer, (vec_ullong2)numerPos); + denomAbs = (vec_ullong2)spu_sel(__lldivi2_negatell2(denom), denom, (vec_ullong2)denomPos); + + // Get difference of leading zeros. + + resAbs = _lldivu2(numerAbs, denomAbs); + res.quot = spu_sel((vec_llong2)resAbs.quot, __lldivi2_negatell2((vec_llong2)resAbs.quot), + (vec_ullong2)quotNeg); + res.rem = spu_sel(__lldivi2_negatell2((vec_llong2)resAbs.rem), (vec_llong2)resAbs.rem, + (vec_ullong2)numerPos); + + return res; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/lldivu2.h b/Extras/simdmathlibrary/spu/simdmath/lldivu2.h new file mode 100644 index 0000000..f58c305 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/lldivu2.h @@ -0,0 +1,104 @@ +/* lldivu2 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LLDIVU2_H___ +#define ___SIMD_MATH_LLDIVU2_H___ + +#include +#include + +#include + +// lldivu2 - for each of two unsigned long long interger slots, compute quotient and remainder of +// numer/denom and store in lldivu2_t struct. Divide by zero produces quotient = 0, remainder = numerator. + +static inline lldivu2_t +_lldivu2 (vector unsigned long long numer, vector unsigned long long denom) +{ + lldivu2_t res; + vec_uint4 denomZeros, numerZeros; + vec_int4 shift; + vec_ullong2 denomShifted, oneShifted, denomLeft, oneLeft; + vec_ullong2 quot, newQuot; + vec_ullong2 newNum, skip, cont; + int anyCont; + + // Get difference of leading zeros. + + denomZeros = (vec_uint4)__ll_spu_cntlz( denom ); + numerZeros = (vec_uint4)__ll_spu_cntlz( numer ); + + shift = (vec_int4)spu_sub( denomZeros, numerZeros ); + + // Shift denom to align leading one with numerator's + + denomShifted = __ll_spu_sl( denom, (vec_ullong2)shift ); + oneShifted = __ll_spu_sl( spu_splats(1ull), (vec_ullong2)shift ); + oneShifted = spu_sel( oneShifted, spu_splats(0ull), __ll_spu_cmpeq_zero( denom ) ); + + // Shift left all leading zeros. + + denomLeft = __ll_spu_sl( denom, (vec_ullong2)denomZeros ); + oneLeft = __ll_spu_sl( spu_splats(1ull), (vec_ullong2)denomZeros ); + + quot = spu_splats(0ull); + + do + { + cont = __ll_spu_cmpgt( oneShifted, spu_splats(0ull) ); + anyCont = spu_extract( spu_gather((vec_uint4)cont ), 0 ); + + newQuot = spu_or( quot, oneShifted ); + + // Subtract shifted denominator from remaining numerator + // when denominator is not greater. + + skip = __ll_spu_cmpgt( denomShifted, numer ); + newNum = __ll_spu_sub( numer, denomShifted ); + + // If denominator is greater, next shift is one more, otherwise + // next shift is number of leading zeros of remaining numerator. + + numerZeros = (vec_uint4)spu_sel( __ll_spu_cntlz( newNum ), (vec_ullong2)numerZeros, skip ); + shift = (vec_int4)spu_sub( (vec_uint4)skip, numerZeros ); + + oneShifted = __ll_spu_rlmask( oneLeft, (vec_ullong2)shift ); + denomShifted = __ll_spu_rlmask( denomLeft, (vec_ullong2)shift ); + + quot = spu_sel( newQuot, quot, skip ); + numer = spu_sel( newNum, numer, spu_orc(skip,cont) ); + } + while ( anyCont ); + + res.quot = quot; + res.rem = numer; + return res; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/llrintd2.h b/Extras/simdmathlibrary/spu/simdmath/llrintd2.h new file mode 100644 index 0000000..02ebacd --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/llrintd2.h @@ -0,0 +1,115 @@ +/* llrintd2 - rounds two doubles in to two nearest 64bit integer. + consistent with the current rounding mode. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LLRINTD2_H___ +#define ___SIMD_MATH_LLRINTD2_H___ + +#include +#include + +// +// Handles no exception +// over flow will return unspecified data + +static inline vector signed long long +_llrintd2 (vector double in) +{ + int shift0, shift1; + vec_uchar16 splat_msb = ((vec_uchar16){0,0,0,0,0,0,0,0, 8,8,8,8,8,8,8,8}); + vec_int4 exp; + vec_uint4 mant, mant0, mant1, sign, mask, borrow; + vec_uint4 implied_one = ((vec_uint4){ 0, 0, 0x00100000, 0}); + vec_uint4 exp_mask = ((vec_uint4){-1,-1, 0xFFF00000, 0}); + vec_double2 bias; + + vec_uint4 vec_zero = ((vec_uint4){0,0,0,0}); + // check denormalized + vec_uint4 exp_in = spu_and( (vec_uint4)in, 0x7FF00000 ); + vec_uint4 is_denorm = spu_cmpeq( exp_in, 0 ); + vec_uint4 ofs = spu_and( ((vec_uint4){0x00100000,0,0x00100000,0}), is_denorm); + + // check zero + vec_uint4 abs_x = spu_and((vec_uint4)in, ((vec_uint4){0x7FFFFFFF,-1,0x7FFFFFFF,-1})); + vec_uint4 is_zerox = spu_cmpeq( abs_x, vec_zero); + is_zerox = spu_and( is_zerox, spu_shuffle(is_zerox,is_zerox, ((vec_uchar16){4,5,6,7,0,1,2,3,12,13,14,15,8,9,10,11}))); + ofs = spu_sel( ofs, vec_zero, is_zerox); + + vec_double2 xx = (vec_double2)spu_or( (vec_uint4)in, ofs ); + + /* Round the input according to the current rounding mode. + */ + vec_uint4 is_large = spu_cmpgt( exp_in, 0x43200000 ); + is_large = spu_shuffle(is_large,is_large,((vec_uchar16){0,0,0,0,0,0,0,0,8,8,8,8,8,8,8,8})); + bias = spu_sel((vec_double2)((vec_ullong2){0x4330000000000000ULL,0x4330000000000000ULL}), ((vec_double2){0.0,0.0}), (vec_ullong2)is_large); + bias = spu_sel(bias, xx, (vec_ullong2)spu_splats(0x8000000000000000ULL)); + + // bias = spu_sel((vec_double2)((vec_ullong2)spu_splats(0x4330000000000000ULL)), xx, + // (vec_ullong2)spu_splats(0x8000000000000000ULL)); + mant = (vec_uint4)(spu_sub(spu_add(xx, bias), bias)); + + /* Determine how many bits to shift the mantissa to correctly + * align it into long long element 0. + */ + exp = spu_and(spu_rlmask((vec_int4)mant, -20), 0x7FF); + exp = spu_add(exp, -1011); + shift0 = spu_extract(exp, 0); + shift1 = spu_extract(exp, 2); + + mask = spu_cmpgt(exp, 0); + mask = spu_shuffle(mask, mask, splat_msb); + + /* Algn mantissa bits + */ + mant0 = spu_sel(spu_rlmaskqwbyte(mant, -8), implied_one, exp_mask); + mant1 = spu_sel(mant, implied_one, exp_mask); + + mant0 = spu_slqwbytebc(spu_slqw(mant0, shift0), shift0); + mant1 = spu_slqwbytebc(spu_slqw(mant1, shift1), shift1); + + mant = spu_shuffle(mant0, mant1, ((vec_uchar16){0,1,2,3,4,5,6,7, 16,17,18,19,20,21,22,23})); + mant = spu_and(mant, mask); + + /* Compute the two's complement of the mantissa if the + * input is negative. + */ + sign = (vec_uint4)spu_rlmaska((vec_int4)xx, -31); + sign = spu_shuffle(sign, sign, splat_msb); + + mant = spu_xor(mant, sign); + borrow = spu_genb(mant, sign); + borrow = spu_shuffle(borrow, borrow, ((vec_uchar16){ + 4,5,6,7, 192,192,192,192, + 12,13,14,15, 192,192,192,192})); + mant = spu_subx(mant, sign, borrow); + + return ((vec_llong2)(mant)); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/llrintf4.h b/Extras/simdmathlibrary/spu/simdmath/llrintf4.h new file mode 100644 index 0000000..d00279b --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/llrintf4.h @@ -0,0 +1,107 @@ +/* llrintf4 - rounds four floats in to four nearest 64bit integer. + On SPU the rounding mode for floats is always towards 0. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LLRINTF4_H___ +#define ___SIMD_MATH_LLRINTF4_H___ + +#include +#include + +// +// Handles no exception +// over flow will return unspecified data + +static inline llroundf4_t +_llrintf4 (vector float in) +{ + llroundf4_t res; + vec_int4 exp; + vec_uint4 mant0, mant1, mant2, mant3; + vec_uint4 mask, mask0, mask1; + vec_uint4 sign, sign0, sign1; + vec_uint4 borrow0, borrow1; + vec_uint4 res0, res1; + int shift0, shift1, shift2, shift3; + + /* Place mantissa bits (including implied most signficant + * bit) into the most significant bits of element 3. Elements + * 0, 1, and 2 are zeroed. + */ + mant0 = spu_sel(spu_rlmaskqwbyte((vec_uint4)in,-11), ((vec_uint4){0, 0, 0, 0x80000000}), ((vec_uint4){-1, -1, -1, 0x800000FF})); + mant1 = spu_sel(spu_rlmaskqwbyte((vec_uint4)in, -7), ((vec_uint4){0, 0, 0, 0x80000000}), ((vec_uint4){-1, -1, -1, 0x800000FF})); + mant2 = spu_sel(spu_rlmaskqwbyte((vec_uint4)in, -3), ((vec_uint4){0, 0, 0, 0x80000000}), ((vec_uint4){-1, -1, -1, 0x800000FF})); + mant3 = spu_sel( spu_rlqwbyte((vec_uint4)in, 1), ((vec_uint4){0, 0, 0, 0x80000000}), ((vec_uint4){-1, -1, -1, 0x800000FF})); + + /* Determine how many bits to shift the mantissa to correctly + * align it into long long element 0. + */ + exp = spu_and(spu_rlmask((vec_int4)in, -23), 0xFF); + exp = spu_add(exp, -94); + shift0 = spu_extract(exp, 0); + shift1 = spu_extract(exp, 1); + shift2 = spu_extract(exp, 2); + shift3 = spu_extract(exp, 3); + + /* Algn mantissa bits + */ + mant0 = spu_slqwbytebc(spu_slqw(mant0, shift0), shift0); + mant1 = spu_slqwbytebc(spu_slqw(mant1, shift1), shift1); + mant2 = spu_slqwbytebc(spu_slqw(mant2, shift2), shift2); + mant3 = spu_slqwbytebc(spu_slqw(mant3, shift3), shift3); + + mask = spu_cmpgt(exp, 0); + mask0 = spu_shuffle(mask, mask, ((vec_uchar16){0,0,0,0,0,0,0,0, 4, 4, 4, 4, 4, 4, 4, 4})); + mask1 = spu_shuffle(mask, mask, ((vec_uchar16){8,8,8,8,8,8,8,8, 12,12,12,12,12,12,12,12})); + + res0 = spu_shuffle(mant0, mant1,((vec_uchar16){0,1,2,3,4,5,6,7, 16,17,18,19,20,21,22,23})); + res1 = spu_shuffle(mant2, mant3,((vec_uchar16){0,1,2,3,4,5,6,7, 16,17,18,19,20,21,22,23})); + res0 = spu_and(res0, mask0); + res1 = spu_and(res1, mask1); + + /* Compute the two's complement of the mantissa if the + * input is negative. + */ + sign = (vec_uint4)spu_rlmaska((vec_int4)in, -31); + sign0 = spu_shuffle(sign, sign, ((vec_uchar16){0,0,0,0,0,0,0,0, 4, 4, 4, 4, 4, 4, 4, 4})); + sign1 = spu_shuffle(sign, sign, ((vec_uchar16){8,8,8,8,8,8,8,8, 12,12,12,12,12,12,12,12})); + + res0 = spu_xor(res0, sign0); + res1 = spu_xor(res1, sign1); + borrow0 = spu_genb(res0, sign0); + borrow1 = spu_genb(res1, sign1); + borrow0 = spu_shuffle(borrow0, borrow0, ((vec_uchar16){4,5,6,7,0xc0,0xc0,0xc0,0xc0, 12,13,14,15,0xc0,0xc0,0xc0,0xc0})); + borrow1 = spu_shuffle(borrow1, borrow1, ((vec_uchar16){4,5,6,7,0xc0,0xc0,0xc0,0xc0, 12,13,14,15,0xc0,0xc0,0xc0,0xc0})); + res.vll[0] = (vec_llong2)spu_subx(res0, sign0, borrow0); + res.vll[1] = (vec_llong2)spu_subx(res1, sign1, borrow1); + + return res; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/llroundd2.h b/Extras/simdmathlibrary/spu/simdmath/llroundd2.h new file mode 100644 index 0000000..0efd472 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/llroundd2.h @@ -0,0 +1,97 @@ +/* llroundd2 - rounds two doubles in to two nearest 64bit integer. + 0.5 will be rounded to far from 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LLROUNDD2_H___ +#define ___SIMD_MATH_LLROUNDD2_H___ + +#include +#include + +// +// Handles no exception +// over flow will return unspecified data + +static inline vector signed long long +_llroundd2 (vector double in) +{ + int shift0, shift1; + vec_uchar16 splat_msb = { 0,0,0,0,0,0,0,0, 8,8,8,8,8,8,8,8}; + vec_int4 exp; + vec_uint4 mant, mant0, mant1, sign, mask, borrow, addend; + vec_uint4 implied_one = { 0, 0, 0x00100000, 0}; + vec_uint4 exp_mask = { -1, -1,0xFFF00000, 0}; + + /* Determine how many bits to shift the mantissa to correctly + * align it into long long element 0. + */ + exp = spu_and(spu_rlmask((vec_int4)in, -20), 0x7FF); + exp = spu_add(exp, -1011); + shift0 = spu_extract(exp, 0); + shift1 = spu_extract(exp, 2); + + mask = spu_cmpgt(exp, 0); + mask = spu_shuffle(mask, mask, splat_msb); + + /* Algn mantissa bits + */ + mant0 = spu_sel(spu_rlmaskqwbyte((vec_uint4)in, -8), implied_one, exp_mask); + mant1 = spu_sel((vec_uint4)in, implied_one, exp_mask); + + mant0 = spu_slqwbytebc(spu_slqw(mant0, shift0), shift0); + mant1 = spu_slqwbytebc(spu_slqw(mant1, shift1), shift1); + + mant = spu_shuffle(mant0, mant1, ((vec_uchar16){0,1,2,3,4,5,6,7, 16,17,18,19,20,21,22,23})); + mant = spu_and(mant, mask); + + /* Perform round by adding 1 if the fraction bits are + * greater than or equal to .5 + */ + addend = spu_shuffle(mant0, mant1, ((vec_uchar16){0x80,0x80,0x80,0x80,0x80,0x80,0x80,8, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,24})); + addend = spu_rlmask(addend, -7); + // addend = spu_and(spu_rlqw(mant, 1), ((vec_uint4){ 0,1,0,1})); + mant = spu_addx(mant, addend, spu_rlqwbyte(spu_genc(mant, addend), 4)); + + /* Compute the two's complement of the mantissa if the + * input is negative. + */ + sign = (vec_uint4)spu_rlmaska((vec_int4)in, -31); + sign = spu_shuffle(sign, sign, splat_msb); + + mant = spu_xor(mant, sign); + borrow = spu_genb(mant, sign); + borrow = spu_shuffle(borrow, borrow, ((vec_uchar16){ + 4,5,6,7, 192,192,192,192, + 12,13,14,15, 192,192,192,192})); + mant = spu_subx(mant, sign, borrow); + + return ((vec_llong2)(mant)); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/llroundf4.h b/Extras/simdmathlibrary/spu/simdmath/llroundf4.h new file mode 100644 index 0000000..77345d8 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/llroundf4.h @@ -0,0 +1,120 @@ +/* llroundf4 - rounds four floats in to four nearest 64bit integer. + 0.5 will be rounded to far from 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LLROUNDF4_H___ +#define ___SIMD_MATH_LLROUNDF4_H___ + +#include +#include + +// +// Handles no exception +// over flow will return unspecified data + +static inline llroundf4_t +_llroundf4 (vector float in) +{ + llroundf4_t res; + vec_int4 exp; + vec_uint4 mant0, mant1, mant2, mant3; + vec_uint4 mask, mask0, mask1; + vec_uint4 sign, sign0, sign1; + vec_uint4 addend0, addend1; + vec_uint4 borrow0, borrow1; + vec_uint4 res0, res1; + int shift0, shift1, shift2, shift3; + + /* Place mantissa bits (including implied most signficant + * bit) into the most significant bits of element 3. Elements + * 0, 1, and 2 are zeroed. + */ + mant0 = spu_sel(spu_rlmaskqwbyte((vec_uint4)in,-11), ((vec_uint4){0, 0, 0, 0x80000000}), ((vec_uint4){-1, -1, -1, 0x800000FF})); + mant1 = spu_sel(spu_rlmaskqwbyte((vec_uint4)in, -7), ((vec_uint4){0, 0, 0, 0x80000000}), ((vec_uint4){-1, -1, -1, 0x800000FF})); + mant2 = spu_sel(spu_rlmaskqwbyte((vec_uint4)in, -3), ((vec_uint4){0, 0, 0, 0x80000000}), ((vec_uint4){-1, -1, -1, 0x800000FF})); + mant3 = spu_sel( spu_rlqwbyte((vec_uint4)in, 1), ((vec_uint4){0, 0, 0, 0x80000000}), ((vec_uint4){-1, -1, -1, 0x800000FF})); + + /* Determine how many bits to shift the mantissa to correctly + * align it into long long element 0. + */ + exp = spu_and(spu_rlmask((vec_int4)in, -23), 0xFF); + exp = spu_add(exp, -94); + shift0 = spu_extract(exp, 0); + shift1 = spu_extract(exp, 1); + shift2 = spu_extract(exp, 2); + shift3 = spu_extract(exp, 3); + + /* Algn mantissa bits + */ + mant0 = spu_slqwbytebc(spu_slqw(mant0, shift0), shift0); + mant1 = spu_slqwbytebc(spu_slqw(mant1, shift1), shift1); + mant2 = spu_slqwbytebc(spu_slqw(mant2, shift2), shift2); + mant3 = spu_slqwbytebc(spu_slqw(mant3, shift3), shift3); + + mask = spu_cmpgt(exp, 0); + mask0 = spu_shuffle(mask, mask, ((vec_uchar16){0,0,0,0,0,0,0,0, 4, 4, 4, 4, 4, 4, 4, 4})); + mask1 = spu_shuffle(mask, mask, ((vec_uchar16){8,8,8,8,8,8,8,8, 12,12,12,12,12,12,12,12})); + + res0 = spu_shuffle(mant0, mant1,((vec_uchar16){0,1,2,3,4,5,6,7, 16,17,18,19,20,21,22,23})); + res1 = spu_shuffle(mant2, mant3,((vec_uchar16){0,1,2,3,4,5,6,7, 16,17,18,19,20,21,22,23})); + res0 = spu_and(res0, mask0); + res1 = spu_and(res1, mask1); + + /* Perform round by adding 1 if the fraction bits are + * greater than or equal to .5 + */ + addend0 = spu_shuffle(mant0, mant1, ((vec_uchar16){0x80,0x80,0x80,0x80,0x80,0x80,0x80,8, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,24})); + addend1 = spu_shuffle(mant2, mant3, ((vec_uchar16){0x80,0x80,0x80,0x80,0x80,0x80,0x80,8, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,24})); + addend0 = spu_rlmask(addend0, -7); + addend1 = spu_rlmask(addend1, -7); + // addend0 = spu_and(spu_rlqw(res0, 1), ((vec_uint4){ 0,1,0,1})); + // addend1 = spu_and(spu_rlqw(res1, 1), ((vec_uint4){ 0,1,0,1})); + res0 = spu_addx(res0, addend0, spu_rlqwbyte(spu_genc(res0, addend0), 4)); + res1 = spu_addx(res1, addend1, spu_rlqwbyte(spu_genc(res1, addend1), 4)); + + /* Compute the two's complement of the mantissa if the + * input is negative. + */ + sign = (vec_uint4)spu_rlmaska((vec_int4)in, -31); + sign0 = spu_shuffle(sign, sign, ((vec_uchar16){0,0,0,0,0,0,0,0, 4, 4, 4, 4, 4, 4, 4, 4})); + sign1 = spu_shuffle(sign, sign, ((vec_uchar16){8,8,8,8,8,8,8,8, 12,12,12,12,12,12,12,12})); + + res0 = spu_xor(res0, sign0); + res1 = spu_xor(res1, sign1); + borrow0 = spu_genb(res0, sign0); + borrow1 = spu_genb(res1, sign1); + borrow0 = spu_shuffle(borrow0, borrow0, ((vec_uchar16){4,5,6,7,0xc0,0xc0,0xc0,0xc0, 12,13,14,15,0xc0,0xc0,0xc0,0xc0})); + borrow1 = spu_shuffle(borrow1, borrow1, ((vec_uchar16){4,5,6,7,0xc0,0xc0,0xc0,0xc0, 12,13,14,15,0xc0,0xc0,0xc0,0xc0})); + res.vll[0] = (vec_llong2)spu_subx(res0, sign0, borrow0); + res.vll[1] = (vec_llong2)spu_subx(res1, sign1, borrow1); + + return res; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/log10f4.h b/Extras/simdmathlibrary/spu/simdmath/log10f4.h new file mode 100644 index 0000000..9f28103 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/log10f4.h @@ -0,0 +1,83 @@ +/* log10f4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LOG10F4_H___ +#define ___SIMD_MATH_LOG10F4_H___ + +#include +#include + +#include + +#define __LOG10F_loga2msb 0.3010299205780f +#define __LOG10F_loga2lsb 7.5085978266e-8f +#define __LOG10F_logaemsb 0.4342944622040f +#define __LOG10F_logaelsb 1.9699272335e-8f +#define __LOG10F_logae 0.4342944819033f + +#define __LOG10F_c0 0.2988439998f +#define __LOG10F_c1 0.3997655209f +#define __LOG10F_c2 0.6666679125f + +static inline vector float +_log10f4 (vector float x) +{ + vec_int4 zeros = spu_splats((int)0); + vec_float4 ones = spu_splats(1.0f); + vec_uint4 zeromask = spu_cmpeq(x, (vec_float4)zeros); + + vec_uint4 expmask = spu_splats(0x7F800000U); + vec_int4 xexp = spu_add( spu_rlmask(spu_and((vec_int4)x, (vec_int4)expmask), -23), -126 ); + x = spu_sel(x, (vec_float4)spu_splats((int)0x3F000000), expmask); + + vec_uint4 mask = spu_cmpgt(spu_splats(0.7071067811865f), x); + x = spu_sel(x , spu_add(x, x) , mask); + xexp = spu_sel(xexp, spu_sub(xexp,spu_splats((int)1)), mask); + + vec_float4 x1 = spu_sub(x , ones); + vec_float4 z = _divf4 (x1, spu_add(x, ones)); + vec_float4 w = spu_mul(z , z); + vec_float4 polyw; + polyw = spu_madd(spu_splats(__LOG10F_c0), w, spu_splats(__LOG10F_c1)); + polyw = spu_madd(polyw , w, spu_splats(__LOG10F_c2)); + + vec_float4 yneg = spu_mul(z, spu_msub(polyw, w, x1)); + vec_float4 wnew = spu_convtf(xexp,0); + + vec_float4 zz1 = spu_madd(spu_splats(__LOG10F_logaemsb), x1, + spu_mul(spu_splats(__LOG10F_loga2msb),wnew)); + vec_float4 zz2 = spu_madd(spu_splats(__LOG10F_logaelsb), x1, + spu_madd(spu_splats(__LOG10F_loga2lsb), wnew, + spu_mul(spu_splats(__LOG10F_logae), yneg)) + ); + + return spu_sel(spu_add(zz1,zz2), (vec_float4)zeromask, zeromask); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/log1pf4.h b/Extras/simdmathlibrary/spu/simdmath/log1pf4.h new file mode 100644 index 0000000..6715aa4 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/log1pf4.h @@ -0,0 +1,60 @@ +/* log1pf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LOG1PF4_H___ +#define ___SIMD_MATH_LOG1PF4_H___ + +#include +#include + +#include +#include + +static inline vector float +_log1pf4 (vector float x) +{ + vec_uint4 nearzeromask = spu_and(spu_cmpgt(x, spu_splats(-0.5f)), + spu_cmpgt(spu_splats(0.5f), x)); + vec_float4 x2 = spu_mul(x,x); + vec_float4 d0, d1, n0, n1; + + d0 = spu_madd(x , spu_splats(1.5934420741f), spu_splats(0.8952856868f)); + d1 = spu_madd(x , spu_splats(0.1198195734f), spu_splats(0.8377145063f)); + d1 = spu_madd(x2, d1, d0); + + n0 = spu_madd(x , spu_splats(1.1457993413f), spu_splats(0.8952856678f)); + n1 = spu_madd(x , spu_splats(0.0082862580f), spu_splats(0.3394238808f)); + n1 = spu_madd(x2, n1, n0); + + return spu_sel(_logf4(spu_add(x, spu_splats(1.0f))), + spu_mul(x, _divf4(n1, d1)), + nearzeromask); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/log2f4.h b/Extras/simdmathlibrary/spu/simdmath/log2f4.h new file mode 100644 index 0000000..43d2dfc --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/log2f4.h @@ -0,0 +1,78 @@ +/* log2f4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LOG2F4_H___ +#define ___SIMD_MATH_LOG2F4_H___ + +#include +#include + +#include + +#define __LOG2F_l2emsb 1.4426950216293f +#define __LOG2F_l2elsb 1.9259629911e-8f +#define __LOG2F_l2e 1.4426950408890f + +#define __LOG2F_c0 0.2988439998f +#define __LOG2F_c1 0.3997655209f +#define __LOG2F_c2 0.6666679125f + +static inline vector float +_log2f4 (vector float x) +{ + vec_int4 zeros = spu_splats((int)0); + vec_float4 ones = spu_splats(1.0f); + vec_uint4 zeromask = spu_cmpeq(x, (vec_float4)zeros); + + vec_int4 expmask = spu_splats((int)0x7F800000); + vec_int4 xexp = spu_add( spu_rlmask(spu_and((vec_int4)x, expmask), -23), -126 ); + x = spu_sel(x, (vec_float4)spu_splats((int)0x3F000000), (vec_uint4)expmask); + + + vec_uint4 mask = spu_cmpgt(spu_splats(0.7071067811865f), x); + x = spu_sel(x , spu_add(x, x) , mask); + xexp = spu_sel(xexp, spu_sub(xexp,spu_splats((int)1)), mask); + + vec_float4 x1 = spu_sub(x , ones); + vec_float4 z = _divf4(x1, spu_add(x, ones)); + vec_float4 w = spu_mul(z , z); + vec_float4 polyw; + polyw = spu_madd(spu_splats(__LOG2F_c0), w, spu_splats(__LOG2F_c1)); + polyw = spu_madd(polyw , w, spu_splats(__LOG2F_c2)); + + vec_float4 yneg = spu_mul(z, spu_msub(polyw, w, x1)); + vec_float4 zz1 = spu_madd(spu_splats(__LOG2F_l2emsb), x1, spu_convtf(xexp,0)); + vec_float4 zz2 = spu_madd(spu_splats(__LOG2F_l2elsb), x1, + spu_mul(spu_splats(__LOG2F_l2e), yneg) + ); + + return spu_sel(spu_add(zz1,zz2), (vec_float4)zeromask, zeromask); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/logbd2.h b/Extras/simdmathlibrary/spu/simdmath/logbd2.h new file mode 100644 index 0000000..55bfdc8 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/logbd2.h @@ -0,0 +1,86 @@ +/* logbd2 - for each element of vector x, return the exponent of normalized double x' as floating point value + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LOGBD2_H___ +#define ___SIMD_MATH_LOGBD2_H___ + +#include +#include +#include + +static inline vector double +_logbd2 (vector double x) +{ + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_uchar16 odd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x04050607, 0x0c0d0e0f, 0x0c0d0e0f }; + vec_uchar16 swapEvenOdd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x00010203, 0x0c0d0e0f, 0x08090a0b }; + + vec_ullong2 sign = spu_splats(0x8000000000000000ull); + vec_ullong2 expn = spu_splats(0x7ff0000000000000ull); + vec_ullong2 zero = spu_splats(0x0000000000000000ull); + + vec_ullong2 isnan, isinf, iszero; + vec_double2 logb = (vec_double2)zero; + vec_llong2 e1, e2; + vec_uint4 cmpgt, cmpeq, cmpzr; + vec_int4 lz, lz0, lz1; + + //NAN: x is NaN (all-ones exponent and non-zero mantissa) + cmpgt = spu_cmpgt( (vec_uint4)spu_or( (vec_ullong2)x, sign ), (vec_uint4)spu_or(sign, expn) ); + cmpeq = spu_cmpeq( (vec_uint4)spu_or( (vec_ullong2)x, sign ), (vec_uint4)spu_or(sign, expn) ); + isnan = (vec_ullong2)spu_or( spu_shuffle( cmpgt, cmpgt, even ), + spu_and( spu_shuffle( cmpeq, cmpeq, even ), + spu_shuffle( cmpgt, cmpgt, odd ) ) ); + logb = spu_sel( logb, (vec_double2)spu_splats(0x7FF8000000000000ll), isnan ); + + //INF: x is infinite (all-ones exponent and zero mantissa) + isinf = (vec_ullong2)spu_and( cmpeq, spu_shuffle( cmpeq, cmpeq, swapEvenOdd ) ); + logb = spu_sel( logb, (vec_double2)spu_splats(__builtin_huge_val()), isinf ); + + //HUGE_VAL: x is zero (zero exponent and zero mantissa) + cmpzr = spu_cmpeq( (vec_uint4)spu_andc( (vec_ullong2)x, sign ), (vec_uint4)zero ); + iszero = (vec_ullong2)spu_and( cmpzr, spu_shuffle( cmpzr, cmpzr, swapEvenOdd ) ); + logb = spu_sel( logb, (vec_double2)spu_splats(-__builtin_huge_val()), iszero ); + + //Integer Exponent: if x is normal or subnormal, return unbiased exponent of normalized double x + e1 = (vec_llong2)spu_and( (vec_llong2)x, (vec_llong2)expn ); + e2 = (vec_llong2)spu_rlmask((vec_uint4)e1, -20); + + lz = (vec_int4)spu_cntlz( (vec_uint4)spu_andc( (vec_ullong2)x, sign) ); + lz0 = (vec_int4)spu_shuffle( lz, lz, even ); + lz0 = spu_sel( (vec_int4)zero, spu_sub( lz0, spu_splats((int)12) ), spu_cmpgt( lz0, (int)11 ) ); + lz1 = spu_sel( (vec_int4)zero, spu_shuffle( lz, lz, odd), spu_cmpeq( lz0, (int)20 ) ); + + logb = spu_sel( logb, spu_extend( spu_convtf( spu_sub( spu_sub( (vec_int4)e2, spu_splats((int)1023) ), spu_add( lz0, lz1 ) ), 0 ) ), + spu_nor( isnan, spu_or( isinf, iszero ) ) ); + + return logb; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/logbf4.h b/Extras/simdmathlibrary/spu/simdmath/logbf4.h new file mode 100644 index 0000000..40e0d7a --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/logbf4.h @@ -0,0 +1,46 @@ +/* logbf4 - for each element of vector x, return the exponent of x' as floating point value + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LOGBF4_H___ +#define ___SIMD_MATH_LOGBF4_H___ + +#include +#include +#include + +static inline vector float +_logbf4 (vector float x) +{ + vec_int4 e1 = spu_and((vec_int4)x, spu_splats((int)0x7F800000)); + vec_uint4 zeromask = spu_cmpeq(e1, 0); + e1 = spu_sub(e1, spu_splats((int)0x3F800000)); + return spu_sel(spu_convtf(e1,23), (vec_float4)spu_splats(-HUGE_VALF), zeromask); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/logf4.h b/Extras/simdmathlibrary/spu/simdmath/logf4.h new file mode 100644 index 0000000..2b901a5 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/logf4.h @@ -0,0 +1,76 @@ +/* logf4 - for each of four slots, calculate the natural log + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_LOGF4_H___ +#define ___SIMD_MATH_LOGF4_H___ + +#include +#include + +#include + +#define __LOGF_ln2msb 0.6931470632553f +#define __LOGF_ln2lsb 1.1730463525e-7f + +#define __LOGF_c0 0.2988439998f +#define __LOGF_c1 0.3997655209f +#define __LOGF_c2 0.6666679125f + +static inline vector float +_logf4 (vector float x) +{ + vec_int4 zeros = spu_splats((int)0); + vec_float4 ones = spu_splats(1.0f); + vec_uint4 zeromask = spu_cmpeq(x, (vec_float4)zeros); + + vec_uint4 expmask = spu_splats(0x7F800000U); + vec_int4 xexp = spu_add( spu_rlmask(spu_and((vec_int4)x, (vec_int4)expmask), -23), -126 ); + x = spu_sel(x, (vec_float4)spu_splats((int)0x3F000000), expmask); + + + vec_uint4 mask = spu_cmpgt(spu_splats(0.7071067811865f), x); + x = spu_sel(x , spu_add(x, x) , mask); + xexp = spu_sel(xexp, spu_sub(xexp,spu_splats((int)1)), mask); + + vec_float4 x1 = spu_sub(x , ones); + vec_float4 z = _divf4 (x1, spu_add(x, ones)); + vec_float4 w = spu_mul(z , z); + vec_float4 polyw; + polyw = spu_madd(spu_splats(__LOGF_c0), w, spu_splats(__LOGF_c1)); + polyw = spu_madd(polyw , w, spu_splats(__LOGF_c2)); + + vec_float4 yneg = spu_mul(z, spu_msub(polyw, w, x1)); + vec_float4 wnew = spu_convtf(xexp,0); + vec_float4 zz1 = spu_madd(spu_splats(__LOGF_ln2msb), wnew, x1); + vec_float4 zz2 = spu_madd(spu_splats(__LOGF_ln2lsb), wnew, yneg); + + return spu_sel(spu_add(zz1,zz2), (vec_float4)zeromask, zeromask); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/modfd2.h b/Extras/simdmathlibrary/spu/simdmath/modfd2.h new file mode 100644 index 0000000..cb9f525 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/modfd2.h @@ -0,0 +1,59 @@ +/* modfd2 - for each of two double slots, compute fractional and integral parts. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_MODFD2_H___ +#define ___SIMD_MATH_MODFD2_H___ + +#include +#include + +#include + +// Returns fractional part and stores integral part in *iptr. + +static inline vector double +_modfd2 (vector double x, vector double *iptr) +{ + vec_double2 integral, fraction; + vec_uint4 iszero; + vec_uint4 sign = (vec_uint4){0x80000000, 0, 0x80000000, 0}; + vec_uchar16 pattern = (vec_uchar16){4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11}; + + integral = _truncd2( x ); + + // if integral is zero, then fraction is x. + iszero = spu_cmpeq(spu_andc((vec_uint4)integral, sign), 0); + iszero = spu_and(iszero, spu_shuffle(iszero, iszero, pattern)); + fraction = spu_sel(spu_sub( x, integral ), x, (vec_ullong2)iszero); + + *iptr = integral; + return fraction; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/modff4.h b/Extras/simdmathlibrary/spu/simdmath/modff4.h new file mode 100644 index 0000000..e18cb59 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/modff4.h @@ -0,0 +1,52 @@ +/* modff4 - for each of four float slots, compute fractional and integral parts. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_MODFF4_H___ +#define ___SIMD_MATH_MODFF4_H___ + +#include +#include + +#include + +// Returns fractional part and stores integral part in *iptr. + +static inline vector float +_modff4 (vector float x, vector float *iptr) +{ + vec_float4 integral, fraction; + + integral = _truncf4( x ); + fraction = spu_sub( x, integral ); + + *iptr = integral; + return fraction; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/nearbyintd2.h b/Extras/simdmathlibrary/spu/simdmath/nearbyintd2.h new file mode 100644 index 0000000..111bb01 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/nearbyintd2.h @@ -0,0 +1,76 @@ +/* nearbyintd2 - Round the input to the nearest integer according to + the current rounding mode without raising an inexact exception. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_NEARBYINTD2_H___ +#define ___SIMD_MATH_NEARBYINTD2_H___ + +#include +#include + +static inline vector double +_nearbyintd2(vector double in) +{ + vec_uint4 fpscr; + vec_ullong2 sign = ((vec_ullong2){0x8000000000000000ULL,0x8000000000000000ULL}); + vec_double2 out, addend; + vec_uint4 vec_zero = ((vec_uint4){0,0,0,0}); + + fpscr = spu_mffpscr(); + + // check denormalized + vec_uint4 exp = spu_and( (vec_uint4)in, 0x7FF00000 ); + vec_uint4 is_denorm = spu_cmpeq( exp, 0 ); + vec_uint4 ofs = spu_and( ((vec_uint4){0x00100000,0,0x00100000,0}), is_denorm); + + // check zero + vec_uint4 abs_x = spu_and((vec_uint4)in, ((vec_uint4){0x7FFFFFFF,-1,0x7FFFFFFF,-1})); + vec_uint4 is_zerox = spu_cmpeq( abs_x, vec_zero); + is_zerox = spu_and( is_zerox, spu_shuffle(is_zerox,is_zerox, ((vec_uchar16){4,5,6,7,0,1,2,3,12,13,14,15,8,9,10,11}))); + ofs = spu_sel( ofs, vec_zero, is_zerox); + + vec_double2 xx = (vec_double2)spu_or( (vec_uint4)in, ofs ); + + /* Add 2^53 and then subtract 2^53 to affect a round to be performed by the + * hardware. Also preserve the input sign so that negative inputs that + * round to zero generate a -0.0. + */ + vec_uint4 is_large = spu_cmpgt( exp, 0x43200000 ); + is_large = spu_shuffle(is_large,is_large,((vec_uchar16){0,0,0,0,0,0,0,0,8,8,8,8,8,8,8,8})); + addend = spu_sel((vec_double2)((vec_ullong2){0x4330000000000000ULL,0x4330000000000000ULL}), ((vec_double2){0.0,0.0}), (vec_ullong2)is_large); + addend = spu_sel(addend, xx, sign); + + out = spu_sel(spu_sub(spu_add(xx, addend), addend), xx, sign); + + spu_mtfpscr(fpscr); + + return (out); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/nearbyintf4.h b/Extras/simdmathlibrary/spu/simdmath/nearbyintf4.h new file mode 100644 index 0000000..99d31df --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/nearbyintf4.h @@ -0,0 +1,55 @@ +/* nearbyintf4 - for each of four float slots, round to the nearest integer, + consistent with the current rounding model, + without raising an inexact floating-point exception. + On SPU, the rounding mode for float is always towards zero. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_NEARBYINTF4_H___ +#define ___SIMD_MATH_NEARBYINTF4_H___ + +#include +#include + +static inline vector float +_nearbyintf4(vector float x) +{ + vector signed int xi; + vector unsigned int inrange; + + // Can convert to and from signed integer to truncate values in range [-2^31, 2^31). + // However, no truncation needed if exponent > 22. + + inrange = spu_cmpabsgt( (vector float)spu_splats(0x4b000000), x ); + + xi = spu_convts( x, 0 ); + + return spu_sel( x, spu_convtf( xi, 0 ), inrange ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/negated2.h b/Extras/simdmathlibrary/spu/simdmath/negated2.h new file mode 100644 index 0000000..19c9028 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/negated2.h @@ -0,0 +1,42 @@ +/* negated2 - for each of two double slots, negate the sign bit. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_NEGATED2_H___ +#define ___SIMD_MATH_NEGATED2_H___ + +#include +#include + +static inline vector double +_negated2 (vector double x) +{ + return (vec_double2)spu_xor( (vec_ullong2)x, spu_splats(0x8000000000000000ull) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/negatef4.h b/Extras/simdmathlibrary/spu/simdmath/negatef4.h new file mode 100644 index 0000000..52dd3a1 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/negatef4.h @@ -0,0 +1,43 @@ +/* negatef4 - for each of four float slots, negate the sign bit. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_NEGATEF4_H___ +#define ___SIMD_MATH_NEGATEF4_H___ + +#include +#include + + +static inline vector float +_negatef4 (vector float x) +{ + return (vec_float4)spu_xor( (vec_uint4)x, spu_splats(0x80000000) ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/negatei4.h b/Extras/simdmathlibrary/spu/simdmath/negatei4.h new file mode 100644 index 0000000..3b29c50 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/negatei4.h @@ -0,0 +1,43 @@ +/* negatei4 - for each of 4 signed int slots, negate the sign bit. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_NEGATEI4_H___ +#define ___SIMD_MATH_NEGATEI4_H___ + +#include +#include + +static inline vector signed int +_negatei4 (vector signed int x) +{ + vector signed int zero = (vector signed int){0,0,0,0}; + return spu_sub (zero, x); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/negatell2.h b/Extras/simdmathlibrary/spu/simdmath/negatell2.h new file mode 100644 index 0000000..b618e11 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/negatell2.h @@ -0,0 +1,47 @@ +/* negatell2 - for each of 2 signed long long slots, negate the sign bit. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_NEGATELL2_H___ +#define ___SIMD_MATH_NEGATELL2_H___ + +#include +#include + +static inline vector signed long long +_negatell2 (vector signed long long x) +{ + vector signed int zero = (vector signed int){0,0,0,0}; + vector signed int borrow; + + borrow = spu_genb(zero, (vec_int4)x); + borrow = spu_shuffle(borrow, borrow, ((vec_uchar16){4,5,6,7, 0xC0,0xC0,0xC0,0xC0, 12,13,14,15, 0xC0,0xC0,0xC0,0xC0})); + return (vec_llong2)spu_subx(zero, (vec_int4)x, borrow); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/nextafterd2.h b/Extras/simdmathlibrary/spu/simdmath/nextafterd2.h new file mode 100644 index 0000000..2fcd98f --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/nextafterd2.h @@ -0,0 +1,97 @@ +/* nextafterd2 - find next representable floating-point value towards 2nd param. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_NEXTAFTERD2_H___ +#define ___SIMD_MATH_NEXTAFTERD2_H___ + +#include +#include + +static inline vector double +_nextafterd2 (vector double xx, vector double yy) +{ + vec_uint4 abs_x, abs_y, sign_x, abs_dif; + vec_uint4 is_sub, is_zerox, is_zeroy; + vec_uint4 is_equal, is_infy, is_nany; + vec_uint4 res0, res1, res; + vec_uint4 vec_zero = ((vec_uint4){0,0,0,0}); + vec_uint4 vec_one = ((vec_uint4){0,1,0,1}); + vec_uint4 vec_m1 = ((vec_uint4){0x80000000,1,0x80000000,1}); + vec_uint4 msk_exp = ((vec_uint4){0x7FF00000,0,0x7FF00000,0}); + vec_uint4 msk_abs = ((vec_uint4){0x7FFFFFFF,-1,0x7FFFFFFF,-1}); + vec_uchar16 msk_all_eq = ((vec_uchar16){4,5,6,7,0,1,2,3,12,13,14,15,8,9,10,11}); + + // mask sign bit + abs_x = spu_and( (vec_uint4)xx, msk_abs); + abs_y = spu_and( (vec_uint4)yy, msk_abs); + + is_zerox = spu_cmpeq( abs_x, vec_zero); + is_zerox = spu_and( is_zerox, spu_shuffle(is_zerox,is_zerox,msk_all_eq)); + + // -0 exception + sign_x = spu_and((vec_uint4)xx, ((vec_uint4){0x80000000,0,0x80000000,0})); + sign_x = spu_sel(sign_x, vec_zero, is_zerox); + + // if same sign |y| < |x| -> decrease + abs_dif = spu_subx(abs_y, abs_x, spu_rlqwbyte(spu_genb(abs_y, abs_x), 4)); + is_sub = spu_xor((vec_uint4)yy, sign_x); // not same sign -> decrease + is_sub = spu_or(is_sub, abs_dif); + is_sub = spu_rlmaska(is_sub, -31); + is_sub = spu_shuffle(is_sub,is_sub,((vec_uchar16){0,0,0,0,0,0,0,0,8,8,8,8,8,8,8,8})); + + res0 = spu_addx( abs_x, vec_one, spu_rlqwbyte(spu_genc(abs_x,vec_one),4)); // calc increase + res1 = spu_subx( abs_x, vec_one, spu_rlqwbyte(spu_genb(abs_x,vec_one),4)); // calc decrease + res = spu_sel( res0, res1, is_sub); // select increase or decrease + res = spu_or( res, sign_x); // set sign + + // check exception + // 0 -> -1 + res = spu_sel(res, vec_m1, spu_and(is_zerox, is_sub)); + + // check equal (include 0,-0) + is_zeroy = spu_cmpeq( abs_y, vec_zero); + is_zeroy = spu_and( is_zeroy, spu_shuffle(is_zeroy,is_zeroy,msk_all_eq)); + is_equal = spu_cmpeq((vec_uint4)xx, (vec_uint4)yy); + is_equal = spu_and(is_equal, spu_shuffle(is_equal,is_equal,msk_all_eq)); + is_equal = spu_or(is_equal, spu_and(is_zeroy, is_zerox)); + res = spu_sel(res, (vec_uint4)yy, is_equal); + + // check nan + is_infy = spu_cmpeq( abs_y, msk_exp); + is_infy = spu_and( is_infy, spu_shuffle(is_infy,is_infy,msk_all_eq)); + is_nany = spu_and( abs_y, msk_exp); + is_nany = spu_cmpeq( is_nany, msk_exp); + is_nany = spu_and( is_nany, spu_shuffle(is_nany,is_nany,msk_all_eq)); + is_nany = spu_sel( is_nany, vec_zero, is_infy); + res = spu_sel(res, (vec_uint4)yy, is_nany); + + return (vec_double2)res; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/nextafterf4.h b/Extras/simdmathlibrary/spu/simdmath/nextafterf4.h new file mode 100644 index 0000000..cf32a4f --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/nextafterf4.h @@ -0,0 +1,72 @@ +/* nextafterf4 - for each of four float slots, + return the the next representable value after x in the direction fo y, + if x is euqal to y, the result is y. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_NEXTAFTERF4_H___ +#define ___SIMD_MATH_NEXTAFTERF4_H___ + +#include +#include + + +static inline vector float +_nextafterf4(vector float x, vector float y) +{ + vec_float4 x_not_dec, lala_inc, lala_dec; + vec_uint4 abs_inc_number, abs_dec_number; + + vec_uint4 A, B; + + //abs_inc, abs_dec + abs_inc_number = spu_sel(spu_splats((unsigned int)0x800000), spu_add((vec_uint4)x, spu_splats((unsigned int)0x1)), spu_cmpabsgt(x, spu_splats(0.0f))); + abs_dec_number = (vec_uint4)spu_add((vec_float4)spu_sub((vec_uint4)x, spu_splats((unsigned int)0x1)), spu_splats(0.0f)); + + //x<= y + A= spu_andc(abs_inc_number, spu_splats((unsigned int)0x80000000)); + // in < 0 + B= abs_dec_number; + + lala_inc = spu_sel((vec_float4)A, (vec_float4)B, spu_cmpgt(spu_splats(0.0f), x)); + + // in <=0, abs_inc ( if in==0, set result's sign to -) + //A= spu_or(spu_splats((unsigned int)0x80000000), spu_andc(abs_inc_number, spu_splats((unsigned int)0x80000000))); + A= spu_or(abs_inc_number, spu_splats((unsigned int)0x80000000)); + // in > 0 + B = abs_dec_number; + lala_dec = spu_sel((vec_float4)A, (vec_float4)B, spu_cmpgt(x, spu_splats(0.0f))); + + + x_not_dec = spu_sel(y, lala_inc, spu_cmpgt(y, x)); + + // (x <= y) || (x > y) + return spu_sel(x_not_dec, lala_dec, spu_cmpgt(x, y)); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/powf4.h b/Extras/simdmathlibrary/spu/simdmath/powf4.h new file mode 100644 index 0000000..aacb61e --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/powf4.h @@ -0,0 +1,60 @@ +/* powf4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_POWF4_H___ +#define ___SIMD_MATH_POWF4_H___ + +#include +#include + +#include +#include + +static inline vector float +_powf4 (vector float x, vector float y) +{ + vec_int4 zeros = spu_splats((int)0); + vec_uint4 zeromask = spu_cmpeq((vec_float4)zeros, x); + + vec_uint4 negmask = spu_cmpgt(spu_splats(0.0f), x); + + vec_float4 sbit = (vec_float4)spu_splats((int)0x80000000); + vec_float4 absx = spu_andc(x, sbit); + vec_float4 absy = spu_andc(y, sbit); + vec_uint4 oddy = spu_and(spu_convtu(absy, 0), spu_splats(0x00000001U)); + negmask = spu_and(negmask, spu_cmpgt(oddy, (vec_uint4)zeros)); + + vec_float4 res = _exp2f4(spu_mul(y, _log2f4(absx))); + res = spu_sel(res, spu_or(sbit, res), negmask); + + + return spu_sel(res, (vec_float4)zeros, zeromask); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/recipd2.h b/Extras/simdmathlibrary/spu/simdmath/recipd2.h new file mode 100644 index 0000000..906ca33 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/recipd2.h @@ -0,0 +1,88 @@ +/* recipd2 - for each of two double slots, compute reciprocal. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_RECIPD2_H___ +#define ___SIMD_MATH_RECIPD2_H___ + +#include +#include + +#include +#include +#include + +// Handles exceptional values as follows: +// NaN -> NaN +// (+,-)Inf -> (+,-)0 +// (+,-)0 -> (+,-)Inf +// Denormal inputs are treated as zero. + +static inline vector double +_recipd2 (vector double x) +{ + vec_ullong2 expmask, signmask; + vec_double2 one, man, exp, nexp, y1, y2, y3, zero, inf, result; + vec_float4 onef, manf, y0f, y1f; + + expmask = spu_splats(0x7ff0000000000000ull); + signmask = spu_splats(0x8000000000000000ull); + onef = spu_splats(1.0f); + one = spu_extend( onef ); + + // Factor ( mantissa x 2^exponent ) into ( mantissa x 2 ) and ( 2^(exponent-1) ). + // Invert exponent part with subtraction. + + exp = spu_and( x, (vec_double2)expmask ); + nexp = (vec_double2)spu_sub( (vec_uint4)expmask, (vec_uint4)exp ); + man = spu_sel( x, (vec_double2)spu_splats(0x40000000), expmask ); + + // Compute mantissa part with single and double precision Newton-Raphson steps. + // Then multiply with 2^(1-exponent). + + manf = spu_roundtf( man ); + y0f = spu_re( manf ); + y1f = spu_madd( spu_nmsub( manf, y0f, onef ), y0f, y0f ); + y1 = spu_extend( y1f ); + y2 = spu_madd( spu_nmsub( man, y1, one ), y1, y1 ); + y3 = spu_madd( spu_nmsub( man, y2, one ), y2, y2 ); + y3 = spu_mul( y3, nexp ); + + // Choose iterated result or special value. + + zero = spu_and( x, (vec_double2)signmask ); + inf = spu_sel( (vec_double2)expmask, x, signmask ); + + result = spu_sel( y3, zero, _isinfd2 ( x ) ); + result = spu_sel( result, inf, _is0denormd2 ( x ) ); + result = spu_sel( result, x, _isnand2( x ) ); + + return result; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/recipf4.h b/Extras/simdmathlibrary/spu/simdmath/recipf4.h new file mode 100644 index 0000000..e7dfd86 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/recipf4.h @@ -0,0 +1,50 @@ +/* recipf4 - for each of four float slots, compute reciprocal. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_RECIPF4_H___ +#define ___SIMD_MATH_RECIPF4_H___ + +#include +#include + +static inline vector float +_recipf4 (vector float x) +{ + // Reciprocal estimate and 1 Newton-Raphson iteration. + // A constant of 1.0 + 1 ulp in the Newton-Raphson step results in exact + // answers for powers of 2, and a slightly smaller relative error bound. + + vec_float4 y0; + vec_float4 oneish = (vec_float4)spu_splats(0x3f800001); + + y0 = spu_re( x ); + return spu_madd( spu_nmsub( x, y0, oneish ), y0, y0 ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/remainderd2.h b/Extras/simdmathlibrary/spu/simdmath/remainderd2.h new file mode 100644 index 0000000..3bdc67e --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/remainderd2.h @@ -0,0 +1,110 @@ +/* A vector double is returned that contains the remainder xi REM yi, + for the corresponding elements of vector double x and vector double y. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_REMAINDERD2_H___ +#define ___SIMD_MATH_REMAINDERD2_H___ + +#include +#include + +#include +#include + + +static inline vector double +_remainderd2(vector double x, vector double yy) +{ + vec_uchar16 splat_hi = ((vec_uchar16){ 0,1,2,3,0,1,2,3, 8,9,10,11, 8,9,10,11}); + vec_uint4 y_hi; + vec_uint4 abs_x, abs_yy, abs_2x, abs_2y; + vec_uint4 bias; + vec_uint4 nan_out, overflow; + vec_uint4 result; + vec_uint4 half_smax = spu_splats((unsigned int)0x7FEFFFFF); + vec_uint4 sign_mask = (vec_uint4)(spu_splats(0x8000000000000000ULL)); + vec_uint4 exp_mask = (vec_uint4)(spu_splats(0x7FF0000000000000ULL)); + vec_uint4 val_nan = (vec_uint4)(spu_splats(0x7FF8000000000000ULL)); + vec_uint4 vec_zero = spu_splats((unsigned int)0); + vec_uint4 is_zeroy; + + // cut sign + abs_x = spu_andc((vec_uint4)x, sign_mask); + abs_yy = spu_andc((vec_uint4)yy, sign_mask); + y_hi = spu_shuffle(abs_yy, abs_yy, splat_hi); + + + // check nan out + is_zeroy = spu_cmpeq(abs_yy, vec_zero); + is_zeroy = spu_and(is_zeroy, spu_rlqwbyte(is_zeroy, 4)); + nan_out = __vec_gt64_half(abs_yy, exp_mask); // y > 7FF00000 + nan_out = spu_or(nan_out, spu_cmpgt(abs_x, half_smax)); // x >= 7FF0000000000000 + nan_out = spu_or(nan_out, is_zeroy); // y = 0 + nan_out = spu_shuffle(nan_out, nan_out, splat_hi); + + + // make y x2 + abs_2y = __rem_twice_d(abs_yy); // 2 x y + + result = (vec_uint4)_fmodd2((vec_double2)abs_x, (vec_double2)abs_2y); + + // abs_x = spu_sel(spu_andc(result, sign_mask), abs_x, spu_cmpgt(y_hi, spu_splats((unsigned int)0x7FBFFFFF))); + abs_x = spu_sel(result, abs_x, spu_cmpgt(y_hi, spu_splats((unsigned int)0x7FEFFFFF))); + + /* if (2*x > y) + * x -= y + * if (2*x >= y) x -= y + */ + overflow = spu_cmpgt(y_hi, spu_splats((unsigned int)0x7FEFFFFF)); + // make x2 + abs_2x = __rem_twice_d(abs_x); // 2 x x + + bias = __vec_gt64(abs_2x, abs_yy); // abs_2x > abs_yy + bias = spu_andc(bias, overflow); + + abs_x = spu_sel(abs_x, __rem_sub_d(abs_x, abs_yy), bias); + + + overflow = spu_or(overflow, spu_shuffle(spu_rlmaska(abs_x, -31), vec_zero, splat_hi)); // minous + + // make x2 + abs_2x = __rem_twice_d(spu_andc(abs_x, sign_mask)); // 2 x x unsupport minous + bias = spu_andc(bias, spu_rlmaska(__rem_sub_d(abs_2x, abs_yy), -31)); + bias = spu_andc(spu_shuffle(bias, bias, splat_hi), overflow); + abs_x = spu_sel(abs_x, __rem_sub_d(abs_x, abs_yy), bias); + + /* select final answer + */ + result = spu_xor(abs_x, spu_and((vec_uint4)x, sign_mask)); // set sign + result = spu_sel(result, val_nan, nan_out); // if nan + + return ((vec_double2)result); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/remainderf4.h b/Extras/simdmathlibrary/spu/simdmath/remainderf4.h new file mode 100644 index 0000000..32d5cfa --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/remainderf4.h @@ -0,0 +1,115 @@ +/* remainderf4 - for each of four float slots, compute remainder of x/y defined as x - nearest_integer(x/y) * y. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_REMAINDERF4_H___ +#define ___SIMD_MATH_REMAINDERF4_H___ + +#include +#include + +#include +#include +#include + +// +// This returns an accurate result when |divf4(x,y)| < 2^20 and |x| < 2^128, and otherwise returns zero. +// If x == 0, the result is 0. +// If x != 0 and y == 0, the result is undefined. +static inline vector float +_remainderf4 (vector float x, vector float y) +{ + vec_float4 q, xabs, yabs, qabs, xabs2, yabshalf; + vec_int4 qi0, qi1, qi2; + vec_float4 i0, i1, i2, i, rem; + vec_uint4 inrange, odd0, odd1, odd2, cmp1, cmp2, odd; + + // Find i = truncated_integer(|x/y|) + + // By the error bounds of divf4, if |x/y| is < 2^20, the quotient is at most off by 1.0. + // Thus the exact truncation is either the truncated quotient, one less, or one greater. + + q = _divf4( x, y ); + xabs = _fabsf4( x ); + yabs = _fabsf4( y ); + qabs = _fabsf4( q ); + xabs2 = spu_add( xabs, xabs ); + + inrange = spu_cmpabsgt( (vec_float4)spu_splats(0x49800000), q ); + inrange = spu_and( inrange, spu_cmpabsgt( (vec_float4)spu_splats(0x7f800000), x ) ); + + qi1 = spu_convts( qabs, 0 ); + qi0 = spu_add( qi1, -1 ); + qi2 = spu_add( qi1, 1 ); + + odd1 = spu_cmpeq( spu_and( qi1, 1 ), 1 ); + odd0 = odd2 = spu_nor( odd1, odd1 ); + + i0 = spu_convtf( qi0, 0 ); + i1 = spu_convtf( qi1, 0 ); + i2 = spu_convtf( qi2, 0 ); + + // Correct i will be the largest one such that |x| - i*|y| >= 0. Can test instead as + // 2*|x| - i*|y| >= |x|: + // + // With exact inputs, the negative-multiply-subtract gives the exact result rounded towards zero. + // Thus |x| - i*|y| may be < 0 but still round to zero. However, if 2*|x| - i*|y| < |x|, the computed + // answer will be rounded down to < |x|. 2*|x| can be represented exactly provided |x| < 2^128. + + cmp1 = spu_cmpgt( xabs, spu_nmsub( i1, yabs, xabs2 ) ); + cmp2 = spu_cmpgt( xabs, spu_nmsub( i2, yabs, xabs2 ) ); + + i = i0; + i = spu_sel( i1, i, cmp1 ); + i = spu_sel( i2, i, cmp2 ); + + odd = odd0; + odd = spu_sel( odd1, odd, cmp1 ); + odd = spu_sel( odd2, odd, cmp2 ); + + rem = spu_nmsub( i, yabs, xabs ); + + // Test whether i or i+1 = nearest_integer(|x/y|) + // + // i+1 is correct if: + // + // rem > 0.5*|y| + // or + // rem = 0.5*|y| and i is odd + + yabshalf = spu_mul( yabs, spu_splats(0.5f) ); + cmp1 = spu_cmpgt( rem, yabshalf ); + cmp2 = spu_and( spu_cmpeq( rem, yabshalf ), odd ); + + i = spu_sel( i, spu_add( i, spu_splats(1.0f) ), spu_or( cmp1, cmp2 ) ); + i = _copysignf4( i, q ); + + return spu_sel( spu_splats(0.0f), spu_nmsub( i, y, x ), inrange ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/remquod2.h b/Extras/simdmathlibrary/spu/simdmath/remquod2.h new file mode 100644 index 0000000..ef1ea78 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/remquod2.h @@ -0,0 +1,155 @@ +/* remquod2 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_REMQUOD2_H___ +#define ___SIMD_MATH_REMQUOD2_H___ + +#include +#include + +#include +#include + +/* + * This function returns the same vector double result as remainderd2(). + * In addition a vector signed long long is storedin *pquo, + * that contains the corresponding element values whose sign is + * the sign of xi / yi and whose magnitude is congruent modulo 2n to + * the magnitude of the integral quotient of xi / yi, where n is + * an implementation-defined integer greater than or equal to 3. + */ + +static inline vector double +_remquod2(vector double x, vector double yy, vector signed long long *quo) +{ + vec_uchar16 splat_hi = ((vec_uchar16){ 0,1,2,3,0,1,2,3, 8,9,10,11, 8,9,10,11}); + vec_int4 quotient, quotient0; + vec_uint4 y_hi; + vec_uint4 abs_x, abs_yy, abs_2x, abs_8y, abs_4y, abs_2y; + vec_uint4 bias; + vec_uint4 nan_out, not_ge, quo_pos, overflow; + vec_uint4 result; + vec_uint4 half_smax = spu_splats((unsigned int)0x7FEFFFFF); + vec_uint4 sign_mask = (vec_uint4)(spu_splats(0x8000000000000000ULL)); + vec_uint4 exp_mask = (vec_uint4)(spu_splats(0x7FF0000000000000ULL)); + vec_uint4 val_nan = (vec_uint4)(spu_splats(0x7FF8000000000000ULL)); + vec_uint4 vec_zero = spu_splats((unsigned int)0); + vec_uint4 is_zeroy; + + // cut sign + abs_x = spu_andc((vec_uint4)x, sign_mask); + abs_yy = spu_andc((vec_uint4)yy, sign_mask); + y_hi = spu_shuffle(abs_yy, abs_yy, splat_hi); + + quo_pos = spu_cmpgt((vec_int4)spu_and((vec_uint4)spu_xor(x, yy), sign_mask), -1); + quo_pos = spu_shuffle(quo_pos, quo_pos, splat_hi); + + // check nan out + is_zeroy = spu_cmpeq(abs_yy, vec_zero); + is_zeroy = spu_and(is_zeroy, spu_rlqwbyte(is_zeroy, 4)); + nan_out = __vec_gt64_half(abs_yy, exp_mask); // y > 7FF00000 + nan_out = spu_or(nan_out, spu_cmpgt(abs_x, half_smax)); // x >= 7FF0000000000000 + nan_out = spu_or(nan_out, is_zeroy); // y = 0 + nan_out = spu_shuffle(nan_out, nan_out, splat_hi); + + + // make y x8 + abs_2y = __rem_twice_d(abs_yy); // 2 x y + abs_4y = __rem_twice_d(abs_2y); // 4 x y + abs_8y = __rem_twice_d(abs_4y); // 2 x y + + result = (vec_uint4)_fmodd2((vec_double2)abs_x, (vec_double2)abs_8y); + + // if y (x8->exp+3 7FF-7FC) overflow + // abs_x = spu_sel(spu_andc(result, sign_mask), abs_x, spu_cmpgt(y_hi, spu_splats((unsigned int)0x7FBFFFFF))); + abs_x = spu_sel(result, abs_x, spu_cmpgt(y_hi, spu_splats((unsigned int)0x7FBFFFFF))); + + /* if (x >= 4*y) + * x -= 4*y + * quotient = 4 + * else + * quotient = 0 + */ + overflow = spu_cmpgt(y_hi, spu_splats((unsigned int)0x7FCFFFFF)); + + not_ge = __vec_gt64(abs_4y, abs_x); + not_ge = spu_or(not_ge, overflow); + abs_x = spu_sel(__rem_sub_d(abs_x, abs_4y), abs_x, not_ge); + quotient = spu_andc(spu_splats((int)4), (vec_int4)not_ge); + + /* if (x >= 2*y + * x -= 2*y + * quotient += 2 + */ + overflow = spu_cmpgt(y_hi, spu_splats((unsigned int)0x7FDFFFFF)); + + not_ge = __vec_gt64(abs_2y, abs_x); // abs_2y > abs_x + not_ge = spu_or(not_ge, overflow); + + abs_x = spu_sel(__rem_sub_d(abs_x, abs_2y), abs_x, not_ge); + quotient = spu_sel(spu_add(quotient, 2), quotient, not_ge); + + /* if (2*x > y) + * x -= y + * if (2*x >= y) x -= y + */ + overflow = spu_cmpgt(y_hi, spu_splats((unsigned int)0x7FEFFFFF)); + // make x2 + abs_2x = __rem_twice_d(abs_x); // 2 x x + + bias = __vec_gt64(abs_2x, abs_yy); // abs_2x > abs_yy + bias = spu_andc(bias, overflow); + + abs_x = spu_sel(abs_x, __rem_sub_d(abs_x, abs_yy), bias); + quotient = spu_sub(quotient, (vec_int4)bias); + + overflow = spu_or(overflow, spu_shuffle(spu_rlmaska(abs_x, -31), vec_zero, splat_hi)); // minous + + // make x2 + abs_2x = __rem_twice_d(spu_andc(abs_x, sign_mask)); // 2 x x unsupport minous + bias = spu_andc(bias, spu_rlmaska(__rem_sub_d(abs_2x, abs_yy), -31)); + bias = spu_andc(spu_shuffle(bias, bias, splat_hi), overflow); + abs_x = spu_sel(abs_x, __rem_sub_d(abs_x, abs_yy), bias); + quotient = spu_sub(quotient, (vec_int4)bias); + + /* select final answer + */ + result = spu_xor(abs_x, spu_and((vec_uint4)x, sign_mask)); // set sign + result = spu_sel(result, val_nan, nan_out); // if nan + + quotient = spu_and(quotient, ((vec_int4){0,7,0,7})); // limit to 3bit + quotient0 = spu_subx( (vec_int4)vec_zero, quotient, spu_rlqwbyte(spu_genb((vec_int4)vec_zero,quotient),4)); + quotient = spu_sel(quotient0, quotient, quo_pos); + + *quo = (vec_llong2)quotient; + + return ((vec_double2)result); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/remquof4.h b/Extras/simdmathlibrary/spu/simdmath/remquof4.h new file mode 100644 index 0000000..734df87 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/remquof4.h @@ -0,0 +1,191 @@ +/* remquof4 - + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/* remquof4 - This function returns the same vector float result as + * remainderf4(). In addition a vector signed int is stored in + * *pquo, that contains the corresponding element values whose sign is + * the sign of xi / yi and whose magnitude is congruent modulo 2n to + * the magnitude of the integral quotient of xi / yi, where n is an + * implementation-defined integer + * greater than or equal to 3. + */ + +#ifndef ___SIMD_MATH_REMQUODF4_H___ +#define ___SIMD_MATH_REMQUODF4_H___ + +#include +#include + +static inline vector float +_remquof4(vector float x, vector float y, vector signed int *quo) +{ + vec_int4 n; + vec_int4 quotient; + vec_uint4 z, y2, y4; + vec_uint4 abs_x, abs_y, abs_2x, abs_8y; + vec_uint4 exp_x, exp_y; + vec_uint4 zero_x, zero_y; + // vec_uint4 logb_x, logb_y; + vec_uint4 mant_x, mant_y; + vec_uint4 not_ge, overflow, quo_pos, mask; + vec_uint4 result, result0, resultx, cnt, sign, bias; + vec_uint4 sign_mask = spu_splats((unsigned int)0x80000000); + vec_uint4 implied_1 = spu_splats((unsigned int)0x00800000); + vec_uint4 mant_mask = spu_splats((unsigned int)0x007FFFFF); + + abs_x = spu_andc((vec_uint4)x, sign_mask); + abs_y = spu_andc((vec_uint4)y, sign_mask); + + abs_8y = spu_add(abs_y, spu_splats((unsigned int)0x01800000)); /* abs_8y = (2^3) * abs_y */ + + sign = spu_and((vec_uint4)x, sign_mask); + + quo_pos = spu_cmpgt((vec_int4)spu_and(spu_xor((vec_uint4)x, (vec_uint4)y), sign_mask), -1); + + /* Compute abs_x = fmodf(abs_x, 8*abs_y). If y is greater than 0.125*SMAX + * (SMAX is the maximum representable float), then return abs_x. + */ + { + /* Determine ilogb of abs_x and abs_8y and + * extract the mantissas (mant_x, mant_y) + */ + exp_x = spu_rlmask(abs_x, -23); + exp_y = spu_rlmask(abs_8y, -23); + + resultx = spu_or(spu_cmpgt(abs_8y, abs_x), spu_cmpgt(abs_y, spu_splats((unsigned int)0x7E7FFFFF))); + + zero_x = spu_cmpeq(exp_x, 0); + // zero_y = spu_cmpeq(exp_y, 0); + zero_y = spu_cmpgt(implied_1, abs_y ); + + // logb_x = spu_add(exp_x, -127); + // logb_y = spu_add(exp_y, -127); + + mant_x = spu_andc(spu_sel(implied_1, abs_x, mant_mask), zero_x); + mant_y = spu_andc(spu_sel(implied_1, abs_8y, mant_mask), zero_y); + + /* Compute fixed point fmod of mant_x and mant_y. Set the flag, + * result0, to all ones if we detect that the final result is + * ever 0. + */ + result0 = spu_or(zero_x, zero_y); + + // n = spu_sub((vec_int4)logb_x, (vec_int4)logb_y); + n = spu_sub((vec_int4)exp_x, (vec_int4)exp_y); // (exp_x-127)-(exp_y-127)=exp_x-exp_y + mask = spu_cmpgt(n, 0); + + while (spu_extract(spu_gather(mask), 0)) { + z = spu_sub(mant_x, mant_y); + + result0 = spu_or(spu_and(spu_cmpeq(z, 0), mask), result0); + + mant_x = spu_sel(mant_x, + spu_sel(spu_add(mant_x, mant_x), + spu_add(z, z), + spu_cmpgt((vec_int4)z, -1)), + mask); + + n = spu_add(n, -1); + mask = spu_cmpgt(n, 0); + } + + z = spu_sub(mant_x, mant_y); + mant_x = spu_sel(mant_x, z, spu_cmpgt((vec_int4)z, -1)); + + result0 = spu_or(spu_cmpeq(mant_x, 0), result0); + + /* Convert the result back to floating point and restore + * the sign. If we flagged the result to be zero (result0), + * zero it. If we flagged the result to equal its input x, + * (resultx) then return x. + */ + cnt = spu_add(spu_cntlz(mant_x), -8); + + // hide hidden bit and shift left side zero + mant_x = spu_rl(spu_andc(mant_x, implied_1), (vec_int4)cnt); + + exp_y = spu_sub(exp_y, cnt); //adjust exponent + result0 = spu_orc(result0, spu_cmpgt((vec_int4)exp_y, 0)); /* zero denorm results */ + exp_y = spu_rl(exp_y, 23); + + result = spu_sel(exp_y, mant_x, mant_mask); + abs_x = spu_sel(spu_andc(result, spu_rlmask(result0, -1)), abs_x, resultx); + result0 = spu_andc(result0, resultx); + } + + /* if (x >= 4*y) + * x -= 4*y + * quotient = 4 + * else + * quotient = 0 + */ + y4 = spu_andc(spu_add(abs_y, spu_splats((unsigned int)0x01000000)), zero_y); + + overflow = spu_cmpgt(abs_y, spu_splats((unsigned int)0x7EFFFFFF)); + not_ge = spu_or(spu_cmpgt(y4, abs_x), overflow); + + abs_x = spu_sel((vec_uint4)spu_sub((vec_float4)abs_x, (vec_float4)y4), abs_x, not_ge); + quotient = spu_andc(spu_splats((int)4), (vec_int4)not_ge); + + /* if (x >= 2*y + * x -= 2*y + * quotient += 2 + */ + y2 = spu_andc(spu_add(abs_y, implied_1), zero_y); + not_ge = spu_cmpgt(y2, abs_x); + + abs_x = spu_sel((vec_uint4)spu_sub((vec_float4)abs_x, (vec_float4)y2), abs_x, not_ge); + quotient = spu_sel(spu_add(quotient, 2), quotient, not_ge); + + /* if (2*x > y) + * x -= y + * if (2*x >= y) x -= y + */ + abs_2x = spu_add(abs_x, implied_1); + bias = spu_cmpgt(abs_2x, abs_y); + abs_x = spu_sel(abs_x, (vec_uint4)spu_sub((vec_float4)abs_x, (vec_float4)abs_y), bias); + quotient = spu_sub(quotient, (vec_int4)bias); + + bias = spu_andc(bias, spu_rlmaska((vec_uint4)spu_msub((vec_float4)abs_x, spu_splats(2.0f), (vec_float4)abs_y), -31)); + abs_x = spu_sel(abs_x, (vec_uint4)spu_sub((vec_float4)abs_x, (vec_float4)abs_y), bias); + quotient = spu_sub(quotient, (vec_int4)bias); + + /* Generate a correct final sign + */ + result = spu_sel(abs_x, ((vec_uint4){0,0,0,0}), result0); // reminder 0 + result = spu_xor(result, sign); // set sign + + quotient = spu_and(quotient, 7); + quotient = spu_sel(spu_sub(0, quotient), quotient, quo_pos); + + *quo = quotient; + + return ((vec_float4)result); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/rintd2.h b/Extras/simdmathlibrary/spu/simdmath/rintd2.h new file mode 100644 index 0000000..286b416 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/rintd2.h @@ -0,0 +1,72 @@ +/* rintd2 - Round the input to the nearest integer according to + the current rounding mode. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_RINTD2_H___ +#define ___SIMD_MATH_RINTD2_H___ + +#include +#include + +static inline vector double +_rintd2(vector double in) +{ + vec_ullong2 sign = ((vec_ullong2){0x8000000000000000ULL,0x8000000000000000ULL}); + vec_uint4 vec_norm = ((vec_uint4){0x00100000,0,0x00100000,0}); + vec_uint4 vec_bias = ((vec_uint4){0x43300000,0,0x43300000,0}); + vec_double2 addend, xx; + vec_uint4 abs_x; + vec_uint4 is_zerox; + vec_uint4 is_denorm; + vec_uint4 ofs; + + abs_x = spu_andc((vec_uint4)in, (vec_uint4)sign); + + // check denormalized + is_zerox = spu_cmpeq( abs_x, 0); + is_denorm = spu_cmpgt( vec_norm, abs_x ); + is_zerox = spu_and( is_zerox, spu_shuffle(is_zerox,is_zerox, ((vec_uchar16){4,5,6,7,0,1,2,3,12,13,14,15,8,9,10,11}))); + is_denorm = spu_andc(is_denorm, is_zerox); + ofs = spu_and( vec_norm, is_denorm); + + xx = spu_or( in, (vec_double2)ofs ); + + /* Add 2^53 and then subtract 2^53 to affect a round to be performed by the + * hardware. Also preserve the input sign so that negative inputs that + * round to zero generate a -0.0. + */ + addend = (vec_double2)spu_and(vec_bias, spu_cmpgt( vec_bias, abs_x )); + addend = spu_sel(addend, in, sign); + + return spu_sel(spu_sub(spu_add(xx, addend), addend), in, sign); + + +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/rintf4.h b/Extras/simdmathlibrary/spu/simdmath/rintf4.h new file mode 100644 index 0000000..db8fdcc --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/rintf4.h @@ -0,0 +1,54 @@ +/* rintf4 - for each of four float slots, round to the nearest integer, + consistent with the current rounding model. + On SPU, the rounding mode for float is always towards zero. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_RINTF4_H___ +#define ___SIMD_MATH_RINTF4_H___ + +#include +#include + +static inline vector float +_rintf4(vector float x) +{ + vector signed int xi; + vector unsigned int inrange; + + // Can convert to and from signed integer to truncate values in range [-2^31, 2^31). + // However, no truncation needed if exponent > 22. + + inrange = spu_cmpabsgt( (vector float)spu_splats(0x4b000000), x ); + + xi = spu_convts( x, 0 ); + + return spu_sel( x, spu_convtf( xi, 0 ), inrange ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/roundd2.h b/Extras/simdmathlibrary/spu/simdmath/roundd2.h new file mode 100644 index 0000000..fdd9bd5 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/roundd2.h @@ -0,0 +1,78 @@ +/* roundd2 - rounds to nearest integer value in floating point format. + 0.5 will be rounded to far from 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ROUNDD2_H___ +#define ___SIMD_MATH_ROUNDD2_H___ + +#include +#include + + +static inline vector double +_roundd2 (vector double in) +{ + vec_uchar16 splat_hi = ((vec_uchar16){ 0,1,2,3,0,1,2,3, 8,9,10,11, 8,9,10,11}); + vec_int4 exp, shift; + vec_uint4 sign = ((vec_uint4){ 0x80000000, 0, 0x80000000, 0}); + vec_uint4 or_mask, and_mask, mask, addend; + vec_double2 in_hi, out; + + /* Add 0.5 (fixed precision to eliminate rounding issues) + */ + in_hi = spu_shuffle(in, in, splat_hi); + exp = spu_and(spu_rlmask((vec_int4)in_hi, -20), 0x7FF); + + shift = spu_sub(((vec_int4){ 1022, 1043, 1022, 1043}), exp); + + addend = spu_and(spu_rlmask(((vec_uint4){ 0x100000, 0x80000000, 0x100000, 0x80000000}), shift), + spu_cmpgt((vec_uint4)spu_add(shift, -1), -33)); + + in = (vec_double2)spu_addx((vec_uint4)in, addend, spu_rlqwbyte(spu_genc((vec_uint4)in, addend), 4)); + + /* Truncate the result. + */ + in_hi = spu_shuffle(in, in, splat_hi); + exp = spu_and(spu_rlmask((vec_int4)in_hi, -20), 0x7FF); + + shift = spu_sub(((vec_int4){ 1023, 1043, 1023, 1043}), exp); + or_mask = spu_andc(spu_cmpgt(shift, 0), sign); + + and_mask = spu_rlmask(((vec_uint4){ 0xFFFFF, -1, 0xFFFFF, -1}), shift); + // mask = spu_or(spu_and(and_mask, spu_cmpgt(shift, -31)), or_mask); + mask = spu_or(spu_and(and_mask, spu_cmpgt(shift, -32)), or_mask); + + /* Apply the mask and return the result. + */ + out = spu_andc(in, (vec_double2)(mask)); + + return (out); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/roundf4.h b/Extras/simdmathlibrary/spu/simdmath/roundf4.h new file mode 100644 index 0000000..b0f85fd --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/roundf4.h @@ -0,0 +1,69 @@ +/* roundf4 - for each of four float slots, round to the nearest integer, + halfway cases are rounded away form zero. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_ROUNDF4_H___ +#define ___SIMD_MATH_ROUNDF4_H___ + +#include +#include + +static inline vector float +_roundf4(vector float in) +{ + vec_int4 exp; + vec_uint4 or_mask, and_mask, mask, addend; + vec_float4 out; + + /* Add 0.5 (fixed precision to eliminate rounding issues + */ + exp = spu_sub(125, spu_and(spu_rlmask((vec_int4)in, -23), 0xFF)); + + addend = spu_and(spu_rlmask( spu_splats((unsigned int)0x1000000), exp), + spu_cmpgt((vec_uint4)exp, -31)); + + in = (vec_float4)spu_add((vec_uint4)in, addend); + + + /* Truncate the result. + */ + exp = spu_sub(127, spu_and(spu_rlmask((vec_int4)in, -23), 0xFF)); + + or_mask = spu_cmpgt(exp, 0); + + and_mask = spu_rlmask(spu_splats((unsigned int)0x7FFFFF), exp); + + mask = spu_or(spu_and(and_mask, spu_cmpgt(exp, -31)), or_mask); + + out = spu_andc(in, (vec_float4)(mask)); + + return (out); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/rsqrtd2.h b/Extras/simdmathlibrary/spu/simdmath/rsqrtd2.h new file mode 100644 index 0000000..6c4dd31 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/rsqrtd2.h @@ -0,0 +1,105 @@ +/* rsqrtd2 - for each of two double slots, compute reciprocal square root. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_RSQRTD2_H___ +#define ___SIMD_MATH_RSQRTD2_H___ + +#include +#include + +#include +#include +#include + +// +// Handles exceptional values as follows: +// NaN -> NaN +// (+,-)0 -> (+,-)Inf +// +Inf -> +0 +// -Inf -> Nan +// -Finite -> Nan +// Denormal inputs are treated as zero. + +static inline vector double +_rsqrtd2 (vector double x) +{ + vec_ullong2 expmask, onemask, signmask, evenexp; + vec_double2 half, one, man, exp, nexp, y1, y2, y3, zero, inf, nan, result; + vec_float4 halff, onef, manf, y0f, y1f; + + expmask = spu_splats(0x7ff0000000000000ull); + onemask = spu_splats(0x0010000000000000ull); + signmask = spu_splats(0x8000000000000000ull); + onef = spu_splats(1.0f); + one = spu_extend( onef ); + halff = spu_splats(0.5f); + half = spu_extend( halff ); + + // Factor input ( mantissa x 2^exponent ) into ( mantissa x 2^(-i) ) and ( 2^(exponent+i) ) + // where i = 0 when exponent is even and i = 1 when exponent is odd. + // + // Compute reciprocal-square-root of second factor by finding -(exponent+i)/2: + // + // biased_exp = 1023 + exponent + // new_biased_exp = 1023 - (exponent+i)/2 + // = 1023 - (biased_exp-1023+i)/2 + // = (3069 - (biased_exp+i)) / 2 + + evenexp = spu_and( (vec_ullong2)x, onemask ); + man = spu_sel( x, (vec_double2)spu_add( spu_splats(0x3fe00000u), (vec_uint4)evenexp ), expmask ); + + exp = spu_and( x, (vec_double2)expmask ); + nexp = spu_or( exp, (vec_double2)onemask ); + nexp = (vec_double2)spu_rlmask( spu_sub( (vec_uint4)spu_splats(0xbfd0000000000000ull), (vec_uint4)nexp ), -1 ); + + // Compute mantissa part in single precision. + // Convert back to double and multiply with 2^(-(exponent+i)/2), then + // do two Newton-Raphson steps for full precision. + + manf = spu_roundtf( man ); + y0f = spu_rsqrte( manf ); + y1f = spu_madd( spu_mul( y0f, halff ), spu_nmsub( y0f, spu_mul( y0f, manf ), onef ), y0f ); + y1 = spu_mul( spu_extend( y1f ), nexp ); + y2 = spu_madd( spu_mul( y1, half ), spu_nmsub( y1, spu_mul( y1, x ), one ), y1 ); + y3 = spu_madd( spu_mul( y2, half ), spu_nmsub( y2, spu_mul( y2, x ), one ), y2 ); + + // Choose iterated result or special value. + + zero = spu_and( x, (vec_double2)signmask ); + inf = spu_sel( (vec_double2)expmask, x, signmask ); + nan = (vec_double2)spu_splats(0x7ff8000000000000ull); + + result = spu_sel( y3, zero, _isinfd2 ( x ) ); + result = spu_sel( result, nan, _signbitd2 ( x ) ); + result = spu_sel( result, inf, _is0denormd2 ( x ) ); + + return result; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/rsqrtf4.h b/Extras/simdmathlibrary/spu/simdmath/rsqrtf4.h new file mode 100644 index 0000000..605a479 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/rsqrtf4.h @@ -0,0 +1,51 @@ +/* rsqrtf4 - for each of four float slots, compute reciprocal square root. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +// Undefined if input < 0. + +#ifndef ___SIMD_MATH_RSQRTF4_H___ +#define ___SIMD_MATH_RSQRTF4_H___ + +#include +#include + +static inline vector float +_rsqrtf4 (vector float x) +{ + // Reciprocal square root estimate and 1 Newton-Raphson iteration. + + vec_float4 y0, y0x, y0half; + vec_float4 oneish = (vec_float4)spu_splats(0x3f800001); + + y0 = spu_rsqrte( x ); + y0x = spu_mul( y0, x ); + y0half = spu_mul( y0, spu_splats(0.5f) ); + return spu_madd( spu_nmsub( y0, y0x, oneish ), y0half, y0 ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/scalbllnd2.h b/Extras/simdmathlibrary/spu/simdmath/scalbllnd2.h new file mode 100644 index 0000000..b51063e --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/scalbllnd2.h @@ -0,0 +1,268 @@ +/* scalbllnd2 - Multiply Double by 2 Raised to its Power + For large elements of ex (overflow), returns HUGE_VALF + For small elements of ex (underflow), returns 0. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_SCALBLLND2_H___ +#define ___SIMD_MATH_SCALBLLND2_H___ + +#undef _SCALBLLND2_ROUND + +#include +#include + +static inline vector double +_scalbllnd2(vector double x, vector signed long long ex) +{ + vec_int4 e1, e2; + vec_int4 min = spu_splats(-2099); + // vec_int4 min = spu_splats(-2044); + vec_int4 max = spu_splats( 2098); + // vec_int4 max = spu_splats( 2046); + vec_uint4 cmp_min, cmp_max; + vec_uint4 shift = ((vec_uint4){20, 32, 20, 32}); + vec_double2 f1, f2; + vec_double2 out; + vec_double2 in = x; + vec_int4 exp_in; + + // check input data range + vec_int4 exp0 = spu_shuffle( (vec_int4)ex, (vec_int4)ex, ((vec_uchar16){4,5,6,7, 4,5,6,7, 12,13,14,15, 12,13,14,15})); + vec_int4 dmy = spu_shuffle( (vec_int4)spu_splats(0x10000), (vec_int4)ex, ((vec_uchar16){16,1,2,3, 16,1,2,3, 24,1,2,3,24,1,2,3})); + // (-)0xFFFFFFFF80000000 or (+)0x000000007FFFFFFF + vec_int4 msk_range = ((vec_int4){0,0x80000000, 0,0x80000000}); + vec_int4 inrange = spu_addx( (vec_int4)ex, msk_range, spu_rlqwbyte(spu_genc((vec_int4)ex, msk_range), 4)); + inrange = (vec_int4)spu_cmpeq( inrange, 0 ); + inrange = spu_shuffle(inrange,inrange,((vec_uchar16){0,1,2,3,0,1,2,3,8,9,10,11,8,9,10,11})); + + // select dummy over ranged data or input data + vec_int4 exp = spu_sel( dmy, exp0, (vec_uint4)inrange); + exp_in = exp; + /* Clamp the specified exponent to the range -2044 to 2046. + */ + cmp_min = spu_cmpgt(exp, min); + cmp_max = spu_cmpgt(exp, max); + exp = spu_sel(min, exp, cmp_min); + exp = spu_sel(exp, max, cmp_max); + + /* Generate the factors f1 = 2^e1 and f2 = 2^e2 + */ + e1 = spu_rlmaska(exp, -1); + e2 = spu_sub(exp, e1); + + f1 = (vec_double2)spu_sl(spu_add(e1, 1023), shift); + + vec_double2 otmp = spu_mul(x, f1); + vec_uint4 fpscr1 = spu_mffpscr(); + + f2 = (vec_double2)spu_sl(spu_add(e2, 1023), shift); + + out = spu_mul(otmp, f2); + vec_uint4 fpscr2 = spu_mffpscr(); + + /* Compute the product x * 2^e1 * 2^e2 + */ + // out = spu_mul(spu_mul(x, f1), f2); + + // check floating point register DENORM bit + vec_uint4 fpscr0, fpscr; + fpscr0 = spu_or(fpscr1, fpscr2); + fpscr = spu_shuffle(fpscr0, fpscr0, ((vec_uchar16){0x80,0x80,0x80,0x80,0x80,0x80,10,0x80,0x80,0x80,6,0x80,0x80,0x80,0x80,0x80})); + fpscr = spu_or(fpscr0, fpscr); + if ( __builtin_expect(spu_extract(fpscr, 1) == 0, 1) ) return out; + + + ////////////////////// + // Denormalized calc// + ////////////////////// + + vec_uchar16 splat_msb = { 0,0,0,0,0,0,0,0, 8,8,8,8,8,8,8,8}; + vec_uint4 signmask = ((vec_uint4){0x80000000,0,0x80000000,0}); + vec_int4 zeros = spu_splats(0); + vec_uchar16 msk_64_eq = ((vec_uchar16){4,5,6,7,0,1,2,3,12,13,14,15,8,9,10,11}); + + //check input was zero + vec_uint4 x_body = spu_and( (vec_uint4)x, ((vec_uint4){0x7FFFFFFF,-1,0x7FFFFFFF,-1})); + vec_uint4 x_zero = spu_cmpeq( x_body, (vec_uint4)zeros ); + x_zero = spu_and( x_zero, spu_shuffle(x_zero,x_zero,msk_64_eq)); + + // check Denormalized input + vec_int4 cnt_zero = (vec_int4)spu_cntlz(x_body); + vec_uint4 is_den = (vec_uint4)spu_cmpgt(cnt_zero, 11); // Denormalized data 000XXXXX XXXXXXXX + is_den = spu_shuffle( is_den, is_den, splat_msb); + is_den = spu_sel(is_den, (vec_uint4)zeros, x_zero); // exclude zero from denormalized + + // count 0bits for 64bit + vec_uint4 cnt_ex = (vec_uint4)spu_cmpgt(cnt_zero, 31); // Denormalized data 00000000 XXXXXXXX + vec_int4 cnt_z = spu_shuffle( cnt_zero, cnt_zero, ((vec_uchar16){4,5,6,7,0,1,2,3,12,13,14,15,8,9,10,11})); + cnt_zero = spu_add(cnt_zero, spu_sel(zeros, cnt_z, cnt_ex)); + cnt_zero = spu_shuffle(cnt_zero, cnt_zero, ((vec_uchar16){0,1,2,3,0,1,2,3,8,9,10,11,8,9,10,11})); + + // extract each 64bit data + x_body = spu_and( (vec_uint4)x, ((vec_uint4){0x000FFFFF,-1,0x000FFFFF,-1})); + vec_uint4 mant0 = spu_shuffle(x_body, x_body, ((vec_uchar16){0,1, 2, 3, 4, 5, 6, 7,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80})); + vec_uint4 mant1 = spu_shuffle(x_body, x_body, ((vec_uchar16){8,9,10,11,12,13,14,15,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80})); + vec_uint4 sign = (vec_uint4)spu_rlmaska((vec_int4)exp_in, -31); + sign = spu_shuffle(sign, sign, splat_msb); + + // set max shift count + vec_int4 sht = spu_add( cnt_zero, ((vec_int4){-11,-64,-11,-64})); + + // denorm & exp+ shift left + vec_uint4 cmp = spu_cmpgt( sht, exp_in); + vec_int4 sht_l = spu_sel(sht, exp_in, cmp); + int shtl0 = spu_extract(sht_l, 0); + int shtl1 = spu_extract(sht_l, 2); + vec_uint4 mant0l = spu_slqwbytebc( spu_slqw(mant0, shtl0), shtl0 ); + vec_uint4 mant1l = spu_slqwbytebc( spu_slqw(mant1, shtl1), shtl1 ); + vec_int4 expp = spu_shuffle(spu_sub(exp_in, sht_l), zeros, ((vec_uchar16){0,1,2,3,0,1,2,3,8,9,10,11,8,9,10,11})); + + exp0 = spu_sel( expp, exp_in, sign ); // select plus or minus caluc + vec_uint4 mantl = spu_shuffle( mant0l, mant1l, ((vec_uchar16){0,1,2,3,4,5,6,7,16,17,18,19,20,21,22,23})); + vec_uint4 mant = spu_sel( mantl, (vec_uint4)x, sign); + exp = spu_sel( exp_in, exp0, is_den ); // select denormalized + x = (vec_double2)spu_sel( (vec_uint4)x, mant, is_den); + + + ////////////////////////////////////////////////////////////////////////// + // from ldexpf4 + vec_int4 expmask = ((vec_int4){0x7FF00000, 0, 0x7FF00000, 0}); + e1 = spu_and((vec_int4)x, expmask); + e2 = spu_rlmask(e1,-20); + + vec_uchar16 maxmask = (vec_uchar16)spu_cmpgt(exp, 2046); + vec_uchar16 minmask = (vec_uchar16)spu_cmpgt(spu_splats(-2044), exp); + minmask = spu_or (minmask, (vec_uchar16)x_zero); + + vec_int4 esum = spu_add(e2, exp); + + maxmask = spu_or (maxmask, (vec_uchar16)spu_cmpgt(esum, 2046)); + maxmask = spu_shuffle(maxmask, maxmask, splat_msb); + // maxmask = spu_and(maxmask, ((vec_uchar16)spu_splats((long long)0x7FFFFFFFFFFFFFFFLL))); + minmask = spu_or (minmask, (vec_uchar16)spu_cmpgt(zeros, esum)); + minmask = spu_shuffle(minmask, minmask, splat_msb); + + // check denorm + vec_uint4 mxmask = spu_and(spu_cmpgt(e2, 0), ((vec_uint4){0x00100000,0,0x00100000,0})); // not denorm + vec_int4 esum2 = spu_sub(esum, (vec_int4)spu_rlmask(mxmask, -20)); // reverse to norm + vec_uint4 mrange = spu_and(spu_cmpgt(zeros, esum2), spu_cmpgt(esum2, -55)); // denorm range + mrange = spu_shuffle(mrange, mrange, splat_msb); + + vec_int4 sht_r = spu_sel(spu_splats(-54), esum2, spu_cmpgt(esum2, spu_splats(-54)) ); + vec_int4 sht_rh = spu_add( sht_r, ((vec_int4){7,7,7,7})); + + x_body = spu_or( x_body, mxmask ); + mant0 = spu_shuffle(x_body, x_body, ((vec_uchar16){0,1, 2, 3, 4, 5, 6, 7,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80})); + mant1 = spu_shuffle(x_body, x_body, ((vec_uchar16){8,9,10,11,12,13,14,15,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80})); + vec_uint4 mant0r = spu_rlmaskqwbytebc( spu_rlmaskqw(mant0, spu_extract(sht_r, 0)), spu_extract(sht_rh,0) ); + vec_uint4 mant1r = spu_rlmaskqwbytebc( spu_rlmaskqw(mant1, spu_extract(sht_r, 2)), spu_extract(sht_rh,2) ); + +#ifdef _SCALBLLND2_ROUND + // check current round mode + fpscr = spu_shuffle(fpscr2, fpscr2, ((vec_uchar16){0x80,0x80,0x80,0x80,0,1,2,3,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80})); + fpscr0 = spu_and(fpscr, ((vec_uint4){0,0xc00,0,0})); + fpscr1 = spu_and(fpscr, ((vec_uint4){0,0x300,0,0})); + + // prepare round data + vec_uint4 rnd0 = spu_slqwbytebc( spu_slqw( mant0r, 31), 31); + vec_uint4 rnd1 = spu_slqwbytebc( spu_slqw( mant1r, 31), 31); + vec_uint4 rnd0w = (vec_uint4)spu_cntb( (vec_uchar16)rnd0 ); + vec_uint4 rnd1w = (vec_uint4)spu_cntb( (vec_uchar16)rnd1 ); + rnd0w = spu_or( spu_slqwbyte(rnd0w,4), spu_slqwbyte(rnd0w,8)); + rnd1w = spu_or( spu_slqwbyte(rnd1w,4), spu_slqwbyte(rnd1w,8)); + rnd0 = spu_or( rnd0, rnd0w); + rnd1 = spu_or( rnd1, rnd1w); + + // nearest + // check half + vec_uint4 hit0 = spu_cmpeq(rnd0, ((vec_uint4){0,0xc0000000,0,0})); //odd + round out + vec_uint4 hit1 = spu_cmpeq(rnd1, ((vec_uint4){0,0xc0000000,0,0})); //odd + round out + vec_uint4 add0 = spu_sel((vec_uint4)zeros, ((vec_uint4){0,1,0,0}), hit0); + vec_uint4 add1 = spu_sel((vec_uint4)zeros, ((vec_uint4){0,1,0,0}), hit1); + // check greater than half + rnd0 = spu_and( rnd0, ((vec_uint4){0,0x7FFFFFFF,0,0})); + rnd1 = spu_and( rnd1, ((vec_uint4){0,0x7FFFFFFF,0,0})); + hit0 = spu_cmpgt(rnd0, ((vec_uint4){0,0x40000000,0,0})); + hit1 = spu_cmpgt(rnd1, ((vec_uint4){0,0x40000000,0,0})); + add0 = spu_sel(add0, ((vec_uint4){0,1,0,0}), hit0); + add1 = spu_sel(add1, ((vec_uint4){0,1,0,0}), hit1); + // select if fp0 + add0 = spu_sel((vec_uint4)zeros, add0, spu_cmpeq(fpscr0, (vec_uint4)zeros)); + add1 = spu_sel((vec_uint4)zeros, add1, spu_cmpeq(fpscr1, (vec_uint4)zeros)); + + // toward zero do nothing + // upward + sign = spu_rlmaska((vec_uint4)in, -31); + vec_uint4 sign0 = spu_shuffle(sign, sign, ((vec_uchar16){0x80,0x80,0x80,0x80,0,0,0,0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80})); + vec_uint4 sign1 = spu_shuffle(sign, sign, ((vec_uchar16){0x80,0x80,0x80,0x80,8,8,8,8,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80})); + vec_uint4 hit0w = spu_cmpgt(rnd0, ((vec_uint4){0,0,0,0})); + vec_uint4 hit1w = spu_cmpgt(rnd1, ((vec_uint4){0,0,0,0})); + + hit0 = spu_and(hit0w, spu_nor(sign0, sign0)); + hit1 = spu_and(hit1w, spu_nor(sign1, sign1)); + hit0 = spu_and(hit0, spu_cmpeq(fpscr0, ((vec_uint4){0,0x800,0,0}))); + hit1 = spu_and(hit1, spu_cmpeq(fpscr1, ((vec_uint4){0,0x200,0,0}))); + // select if fp2 + add0 = spu_sel(add0, ((vec_uint4){0,1,0,0}), hit0); + add1 = spu_sel(add1, ((vec_uint4){0,1,0,0}), hit1); + + // downward + hit0 = spu_and(hit0w, sign0); + hit1 = spu_and(hit1w, sign1); + hit0 = spu_and(hit0, spu_cmpeq(fpscr0, ((vec_uint4){0,0xc00,0,0}))); + hit1 = spu_and(hit1, spu_cmpeq(fpscr1, ((vec_uint4){0,0x300,0,0}))); + // select if fp3 + add0 = spu_sel(add0, ((vec_uint4){0,1,0,0}), hit0); + add1 = spu_sel(add1, ((vec_uint4){0,1,0,0}), hit1); + + // calc round + mant0r = spu_addx(mant0r, add0, spu_rlqwbyte(spu_genc(mant0r, add0), 4)); + mant1r = spu_addx(mant1r, add1, spu_rlqwbyte(spu_genc(mant1r, add1), 4)); + +#endif // _SCALBLLND2_ROUND + + vec_uint4 mantr = spu_shuffle( mant0r, mant1r, ((vec_uchar16){0,1,2,3,4,5,6,7,16,17,18,19,20,21,22,23})); + + // select right answer + x = spu_sel(x, (vec_double2)spu_sl(esum,20), (vec_ullong2)expmask); + x = spu_sel(x, (vec_double2)zeros, (vec_ullong2)minmask); + x = spu_sel(x, (vec_double2)spu_splats((long long)0x7FEFFFFFFFFFFFFFLL), (vec_ullong2)maxmask); + + out = (vec_double2)spu_sel((vec_uint4)x , mantr, mrange); + + // check Infinity,NaN + vec_uint4 is_inf = spu_cmpeq(e1, expmask); + is_inf = spu_and( is_inf, spu_shuffle(is_inf,is_inf,msk_64_eq)); + out = (vec_double2)spu_sel((vec_uint4)out , (vec_uint4)in, is_inf); + + out = spu_sel(out, in, (vec_ullong2)signmask); + return out; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/scalbnf4.h b/Extras/simdmathlibrary/spu/simdmath/scalbnf4.h new file mode 100644 index 0000000..f138266 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/scalbnf4.h @@ -0,0 +1,75 @@ +/* scalbnf4 computes x * 2^exp. This function is computed without + the assistence of any floating point operations and as such does + not set any floating point exceptions. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_SCALBNF4_H___ +#define ___SIMD_MATH_SCALBNF4_H___ + +#include +#include + +static inline vector float +_scalbnf4(vector float x, vector signed int n) +{ + vec_int4 x_exp; + vec_uint4 zero, overflow; + vec_uint4 exp_mask = spu_splats((unsigned int)0x7F800000); + vec_float4 out; + + /* Extract exponent from x. If the exponent is 0, then + * x is either 0 or a denorm and x*2^exp is a zero. + */ + x_exp = spu_and(spu_rlmask((vec_int4)x, -23), 0xFF); + + zero = spu_cmpeq(x_exp, 0); + + /* Compute the expected exponent and determine if the + * result is within range. + */ + x_exp = spu_add(n, x_exp); + + zero = spu_orc(zero, spu_cmpgt(x_exp, 0)); + + // overflow = spu_rlmask(spu_cmpgt(x_exp, 255), -1); + overflow = spu_cmpgt(x_exp, 255); + + /* Merge the expect exponent with x's mantissa. Zero the + * result if underflow and force to max if overflow. + */ + out = spu_sel(x, (vec_float4)spu_rl(x_exp, 23), exp_mask); + out = spu_andc(out, (vec_float4)zero); + out = spu_or(out, (vec_float4)overflow); + // add sign bit + out = spu_sel(out, x, spu_splats((unsigned int)0x80000000)); + + return out; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/signbitd2.h b/Extras/simdmathlibrary/spu/simdmath/signbitd2.h new file mode 100644 index 0000000..7cdbb84 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/signbitd2.h @@ -0,0 +1,48 @@ +/* signbitd2 - for each of two double slots, if input has negative sign bit return mask of ones, else 0 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_SIGNBITD2_H___ +#define ___SIMD_MATH_SIGNBITD2_H___ + +#include +#include + +static inline vector unsigned long long +_signbitd2 (vector double x) +{ + vec_ullong2 cmp; + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + + cmp = (vec_ullong2)spu_cmpgt( spu_splats(0), (vec_int4)x ); + cmp = spu_shuffle( cmp, cmp, even ); + + return cmp; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/signbitf4.h b/Extras/simdmathlibrary/spu/simdmath/signbitf4.h new file mode 100644 index 0000000..7fbda7a --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/signbitf4.h @@ -0,0 +1,42 @@ +/* signbitf4 - for each element of vector x, return a mask of ones if x' has signbit one, zero otherwise + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_SIGNBITF4_H___ +#define ___SIMD_MATH_SIGNBITF4_H___ + +#include +#include + +static inline vector unsigned int +_signbitf4 (vector float x) +{ + return spu_cmpgt( spu_splats(0), (vec_int4)x ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/sincosd2.h b/Extras/simdmathlibrary/spu/simdmath/sincosd2.h new file mode 100644 index 0000000..f8482cd --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/sincosd2.h @@ -0,0 +1,149 @@ +/* sind2 and cosd2 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH__SINCOSD2_H___ +#define ___SIMD_MATH__SINCOSD2_H___ + +#include +#include + +#include +#include +#include +#include + +// +// Computes the sine of the each of two double slots. +// +static inline void +_sincosd2(vector double x, vec_double2 *s, vec_double2 *c) +{ + vec_double2 xl,xl2,xl3; + vec_double2 nan = (vec_double2)spu_splats(0x7ff8000000000000ull); + vec_uchar16 copyEven = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_double2 tiny = (vec_double2)spu_splats(0x3e40000000000000ull); + vec_double2 ts, tc; + + // Range reduction using : x = angle * TwoOverPi; + // + xl = spu_mul(x, spu_splats(0.63661977236758134307553505349005744)); + + // Find the quadrant the angle falls in + // using: q = (int) (ceil(abs(x))*sign(x)) + // + xl = spu_add(xl,spu_sel(spu_splats(0.5),xl,spu_splats(0x8000000000000000ull))); + vec_float4 xf = spu_roundtf(xl); + vec_int4 q = spu_convts(xf,0); + q = spu_shuffle(q,q,copyEven); + + + // Compute an offset based on the quadrant that the angle falls in + // + vec_int4 offsetSin = spu_and(q,spu_splats(0x3)); + vec_int4 offsetCos = spu_add(spu_splats(1),offsetSin); + + // Remainder in range [-pi/4..pi/4] + // + vec_float4 qf = spu_convtf(q,0); + vec_double2 qd = spu_extend(qf); + vec_double2 p1 = spu_nmsub(qd,spu_splats(__SINCOSD_KC1),x); + xl = spu_nmsub(qd,spu_splats(__SINCOSD_KC2),p1); + + // Check if |xl| is a really small number + // + vec_double2 absXl = (vec_double2)spu_andc((vec_ullong2)xl, spu_splats(0x8000000000000000ull)); + vec_ullong2 isTiny = (vec_ullong2)_isgreaterd2(tiny,absXl); + + // Compute x^2 and x^3 + // + xl2 = spu_mul(xl,xl); + xl3 = spu_mul(xl2,xl); + + // Compute both the sin and cos of the angles + // using a polynomial expression: + // cx = 1.0f + xl2 * ((((((c0 * xl2 + c1) * xl2 + c2) * xl2 + c3) * xl2 + c4) * xl2 + c5), and + // sx = xl + xl3 * (((((s0 * xl2 + s1) * xl2 + s2) * xl2 + s3) * xl2 + s4) * xl2 + s5) + // + + vec_double2 ct0 = spu_mul(xl2,xl2); + vec_double2 ct1 = spu_madd(spu_splats(__SINCOSD_CC0),xl2,spu_splats(__SINCOSD_CC1)); + vec_double2 ct2 = spu_madd(spu_splats(__SINCOSD_CC2),xl2,spu_splats(__SINCOSD_CC3)); + vec_double2 ct3 = spu_madd(spu_splats(__SINCOSD_CC4),xl2,spu_splats(__SINCOSD_CC5)); + vec_double2 st1 = spu_madd(spu_splats(__SINCOSD_SC0),xl2,spu_splats(__SINCOSD_SC1)); + vec_double2 st2 = spu_madd(spu_splats(__SINCOSD_SC2),xl2,spu_splats(__SINCOSD_SC3)); + vec_double2 st3 = spu_madd(spu_splats(__SINCOSD_SC4),xl2,spu_splats(__SINCOSD_SC5)); + vec_double2 ct4 = spu_madd(ct2,ct0,ct3); + vec_double2 st4 = spu_madd(st2,ct0,st3); + vec_double2 ct5 = spu_mul(ct0,ct0); + + vec_double2 ct6 = spu_madd(ct5,ct1,ct4); + vec_double2 st6 = spu_madd(ct5,st1,st4); + + vec_double2 cx = spu_madd(ct6,xl2,spu_splats(1.0)); + vec_double2 sx = spu_madd(st6,xl3,xl); + + // Small angle approximation: sin(tiny) = tiny, cos(tiny) = 1.0 + // + sx = spu_sel(sx,xl,isTiny); + cx = spu_sel(cx,spu_splats(1.0),isTiny); + + // Use the cosine when the offset is odd and the sin + // when the offset is even + // + vec_ullong2 sinMask = (vec_ullong2)spu_cmpeq(spu_and(offsetSin,(int)0x1),spu_splats((int)0)); + vec_ullong2 cosMask = (vec_ullong2)spu_cmpeq(spu_and(offsetCos,(int)0x1),spu_splats((int)0)); + ts = spu_sel(cx,sx,sinMask); + tc = spu_sel(cx,sx,cosMask); + + // Flip the sign of the result when (offset mod 4) = 1 or 2 + // + sinMask = (vec_ullong2)spu_cmpeq(spu_and(offsetSin,(int)0x2),spu_splats((int)0)); + sinMask = spu_shuffle(sinMask,sinMask,copyEven); + ts = spu_sel((vec_double2)spu_xor(spu_splats(0x8000000000000000ull),(vec_ullong2)ts),ts,sinMask); + + cosMask = (vec_ullong2)spu_cmpeq(spu_and(offsetCos,(int)0x2),spu_splats((int)0)); + cosMask = spu_shuffle(cosMask,cosMask,copyEven); + tc = spu_sel((vec_double2)spu_xor(spu_splats(0x8000000000000000ull),(vec_ullong2)tc),tc,cosMask); + + // if input = +/-Inf return NAN + // + ts = spu_sel(ts, nan, _isnand2 (x)); + tc = spu_sel(tc, nan, _isnand2 (x)); + + // if input = 0 or denorm return 'result0' + // + vec_ullong2 zeroMask = _is0denormd2 (x); + ts = spu_sel(ts,x,zeroMask); + tc = spu_sel(tc,spu_splats(1.0),zeroMask); + + *s = ts; + *c = tc; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/sincosf4.h b/Extras/simdmathlibrary/spu/simdmath/sincosf4.h new file mode 100644 index 0000000..db9cf8d --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/sincosf4.h @@ -0,0 +1,113 @@ +/* sincosf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_SINCOSF4_H___ +#define ___SIMD_MATH_SINCOSF4_H___ + +#include +#include + +#include + +// +// Computes both the sine and cosine of the all four slots of x +// by using a polynomial approximation. +// +static inline void +_sincosf4 (vector float x, vector float *s, vector float *c) +{ + vec_float4 xl,xl2,xl3; + vec_int4 q; + vec_int4 offsetSin, offsetCos; + vec_float4 ts, tc; + + // Range reduction using : xl = angle * TwoOverPi; + // + xl = spu_mul(x, spu_splats(0.63661977236f)); + + // Find the quadrant the angle falls in + // using: q = (int) (ceil(abs(xl))*sign(xl)) + // + xl = spu_add(xl,spu_sel(spu_splats(0.5f),xl,spu_splats(0x80000000))); + q = spu_convts(xl,0); + + + // Compute the offset based on the quadrant that the angle falls in. + // Add 1 to the offset for the cosine. + // + offsetSin = spu_and(q,spu_splats((int)0x3)); + offsetCos = spu_add(spu_splats(1),offsetSin); + + // Remainder in range [-pi/4..pi/4] + // + vec_float4 qf = spu_convtf(q,0); + vec_float4 p1 = spu_nmsub(qf,spu_splats(__SINCOSF_KC1),x); + xl = spu_nmsub(qf,spu_splats(__SINCOSF_KC2),p1); + + // Compute x^2 and x^3 + // + xl2 = spu_mul(xl,xl); + xl3 = spu_mul(xl2,xl); + + + // Compute both the sin and cos of the angles + // using a polynomial expression: + // cx = 1.0f + xl2 * ((C0 * xl2 + C1) * xl2 + C2), and + // sx = xl + xl3 * ((S0 * xl2 + S1) * xl2 + S2) + // + vec_float4 ct1 = spu_madd(spu_splats(__SINCOSF_CC0),xl2,spu_splats(__SINCOSF_CC1)); + vec_float4 st1 = spu_madd(spu_splats(__SINCOSF_SC0),xl2,spu_splats(__SINCOSF_SC1)); + + vec_float4 ct2 = spu_madd(ct1,xl2,spu_splats(__SINCOSF_CC2)); + vec_float4 st2 = spu_madd(st1,xl2,spu_splats(__SINCOSF_SC2)); + + vec_float4 cx = spu_madd(ct2,xl2,spu_splats(1.0f)); + vec_float4 sx = spu_madd(st2,xl3,xl); + + // Use the cosine when the offset is odd and the sin + // when the offset is even + // + vec_uint4 sinMask = spu_cmpeq(spu_and(offsetSin,(int)0x1),spu_splats((int)0)); + vec_uint4 cosMask = spu_cmpeq(spu_and(offsetCos,(int)0x1),spu_splats((int)0)); + ts = spu_sel(cx,sx,sinMask); + tc = spu_sel(cx,sx,cosMask); + + // Flip the sign of the result when (offset mod 4) = 1 or 2 + // + sinMask = spu_cmpeq(spu_and(offsetSin,(int)0x2),spu_splats((int)0)); + cosMask = spu_cmpeq(spu_and(offsetCos,(int)0x2),spu_splats((int)0)); + + ts = spu_sel((vec_float4)spu_xor(spu_splats(0x80000000),(vec_uint4)ts),ts,sinMask); + tc = spu_sel((vec_float4)spu_xor(spu_splats(0x80000000),(vec_uint4)tc),tc,cosMask); + + *s = ts; + *c = tc; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/sind2.h b/Extras/simdmathlibrary/spu/simdmath/sind2.h new file mode 100644 index 0000000..a2f4a17 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/sind2.h @@ -0,0 +1,49 @@ +/* sind2 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_SIND2_H___ +#define ___SIMD_MATH_SIND2_H___ + +#include +#include + +#include + +// +// Computes the sine of the each of two double slots. +// +static inline vector double +_sind2 (vector double x) +{ + vec_double2 s, c; + _sincosd2(x, &s, &c); + return s; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/sinf4.h b/Extras/simdmathlibrary/spu/simdmath/sinf4.h new file mode 100644 index 0000000..b2f1aac --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/sinf4.h @@ -0,0 +1,49 @@ +/* sinf4 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_SINF4_H___ +#define ___SIMD_MATH_SINF4_H___ + +#include +#include + +#include + +// +// Computes the sine of each of the four slots by using a polynomia approximation +// +static inline vector float +_sinf4 (vector float x) +{ + vec_float4 s, c; + _sincosf4(x, &s, &c); + return s; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/sqrtd2.h b/Extras/simdmathlibrary/spu/simdmath/sqrtd2.h new file mode 100644 index 0000000..60a17d2 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/sqrtd2.h @@ -0,0 +1,113 @@ +/* sqrtd2 - for each of two double slots, compute square root. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_SQRTD2_H___ +#define ___SIMD_MATH_SQRTD2_H___ + +#include +#include + +#include +#include +#include + +// +// Handles exceptional values as follows: +// NaN -> NaN +// -Inf -> Nan +// -Finite -> Nan +// Denormal inputs are treated as zero. + +static inline vector double +_sqrtd2 (vector double x) +{ + vec_ullong2 expmask, onemask, signmask, evenexp; + vec_double2 half, one, man, exp, nexp, y1, y2, y3, zero, inf, nan, neg, result; + vec_float4 halff, onef, manf, y0f, y1f; + + expmask = spu_splats(0x7ff0000000000000ull); + onemask = spu_splats(0x0010000000000000ull); + signmask = spu_splats(0x8000000000000000ull); + onef = spu_splats(1.0f); + one = spu_extend( onef ); + halff = spu_splats(0.5f); + half = spu_extend( halff ); + + // First compute reciprocal square root. + // Factor input ( mantissa x 2^exponent ) into ( mantissa x 2^(-i) ) and ( 2^(exponent+i) ) + // where i = 0 when exponent is even and i = 1 when exponent is odd. + // + // Compute reciprocal-square-root of second factor by finding -(exponent+i)/2: + // + // biased_exp = 1023 + exponent + // new_biased_exp = 1023 - (exponent+i)/2 + // = 1023 - (biased_exp-1023+i)/2 + // = (3069 - (biased_exp+i)) / 2 + + evenexp = spu_and( (vec_ullong2)x, onemask ); + man = spu_sel( x, (vec_double2)spu_add( spu_splats(0x3fe00000u), (vec_uint4)evenexp ), expmask ); + + exp = spu_and( x, (vec_double2)expmask ); + nexp = spu_or( exp, (vec_double2)onemask ); + nexp = (vec_double2)spu_rlmask( spu_sub( (vec_uint4)spu_splats(0xbfd0000000000000ull), (vec_uint4)nexp ), -1 ); + + // Compute mantissa part in single precision. + // Convert back to double and multiply with 2^(-(exponent+i)/2), then + // do two Newton-Raphson steps for full precision. + + manf = spu_roundtf( man ); + y0f = spu_rsqrte( manf ); + y1f = spu_madd( spu_mul( y0f, halff ), spu_nmsub( y0f, spu_mul( y0f, manf ), onef ), y0f ); + y1 = spu_mul( spu_extend( y1f ), nexp ); + y2 = spu_madd( spu_mul( y1, half ), spu_nmsub( y1, spu_mul( y1, x ), one ), y1 ); + y3 = spu_madd( spu_mul( y2, half ), spu_nmsub( y2, spu_mul( y2, x ), one ), y2 ); + + // Multiply by input to get square root. + + y3 = spu_mul( y3, x ); + + // Choose iterated result or special value. + + zero = spu_and( x, (vec_double2)signmask ); + inf = (vec_double2)expmask; + nan = (vec_double2)spu_splats(0x7ff8000000000000ull); + + neg = spu_and(x, (vec_double2)spu_splats(0x8000000000000000ull)); + neg = spu_shuffle(neg, neg, ((vec_uchar16){0,0,0,0,0,0,0,0,8,8,8,8,8,8,8,8})); + neg = (vec_double2)spu_rlmaska((vec_int4)neg, -31); + + result = spu_sel( y3, inf, _isinfd2 ( x ) ); + result = spu_sel( result, nan, _isnand2 ( x ) ); + result = spu_sel( result, nan, (vec_ullong2)neg ); + result = spu_sel( result, zero, _is0denormd2 ( x ) ); + + return result; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/sqrtf4.h b/Extras/simdmathlibrary/spu/simdmath/sqrtf4.h new file mode 100644 index 0000000..ae3f8f6 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/sqrtf4.h @@ -0,0 +1,52 @@ +/* sqrtf4 - for each of four float slots, compute square root. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ + +// Undefined if input < 0. + +#ifndef ___SIMD_MATH_SQRTF4_H___ +#define ___SIMD_MATH_SQRTF4_H___ + +#include +#include + +static inline vector float +_sqrtf4 (vector float x) +{ + // Reciprocal square root estimate and 1 Newton-Raphson iteration. + + vec_float4 y0, y0x, y0xhalf; + vec_float4 oneish = (vec_float4)spu_splats(0x3f800001); + + y0 = spu_rsqrte( x ); + y0x = spu_mul( y0, x ); + y0xhalf = spu_mul( y0x, spu_splats(0.5f) ); + return spu_madd( spu_nmsub( y0, y0x, oneish ), y0xhalf, y0x ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/tand2.h b/Extras/simdmathlibrary/spu/simdmath/tand2.h new file mode 100644 index 0000000..c96907a --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/tand2.h @@ -0,0 +1,125 @@ +/* tand2 + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_TAND2_H___ +#define ___SIMD_MATH_TAND2_H___ + +#include +#include + +#include +#include +#include +#include + +#define __TAND_CC0 -0.00020844956382258822 +#define __TAND_CC1 0.02334489464693293380 +#define __TAND_CC2 -0.46161689768996201755 +#define __TAND_SC0 -0.00000748373924372997 +#define __TAND_SC1 0.00280592875035233052 +#define __TAND_SC2 -0.12828356435663158978 + +/* + * Computes the tangent of the given angles by first reducing the + * range to [-pi/4..pi/4] and performing the appropriate sin/cos ratio + */ +static inline vector double +_tand2 (vector double x) +{ + vec_double2 xl,x2,x3,res; + vec_double2 nan = (vec_double2)spu_splats(0x7ff8000000000000ull); + vec_uchar16 copyEven = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + + // Range reduction using : xl = angle * TwoOverPi; + // + xl = spu_mul(x, spu_splats(0.63661977236758134307553505349005744)); + + + // Find the quadrant the angle falls in + // using: q = (int) (ceil(abs(xl))*sign(xl)) + // + xl = spu_add(xl,spu_sel(spu_splats(0.5),xl,spu_splats(0x8000000000000000ull))); + vec_float4 xf = spu_roundtf(xl); + vec_int4 q = spu_convts(xf,0); + q = spu_shuffle(q,q,copyEven); + + + // Remainder in range [-pi/4..pi/4] + // + vec_float4 qf = spu_convtf(q,0); + vec_double2 qd = spu_extend(qf); + vec_double2 p1 = spu_nmsub(qd,spu_splats(__SINCOSD_KC1),x); + xl = spu_nmsub(qd,spu_splats(__SINCOSD_KC2),p1); + + // Compute x^2 and x^3 + // + x2 = spu_mul(xl,xl); + x3 = spu_mul(x2,xl); + + + // Compute both the sin and cos of the angles + // using a polynomial expression: + // cx = 1.0f + x2 * ((C0 * x2 + C1) * x2 + C2), and + // sx = x + x3 * ((S0 * x2 + S1) * x2 + S2) + // + vec_double2 ct1 = spu_madd(spu_splats(__TAND_CC0),x2,spu_splats(__TAND_CC1)); + vec_double2 st1 = spu_madd(spu_splats(__TAND_SC0),x2,spu_splats(__TAND_SC1)); + + vec_double2 ct2 = spu_madd(ct1,x2,spu_splats(__TAND_CC2)); + vec_double2 st2 = spu_madd(st1,x2,spu_splats(__TAND_SC2)); + + vec_double2 cx = spu_madd(ct2,x2,spu_splats(1.0)); + vec_double2 sx = spu_madd(st2,x3,xl); + + + // Compute both cx/sx and sx/cx + // + vec_double2 cxosx = _divd2(cx,sx); + vec_double2 sxocx = _divd2(sx,cx); + + vec_double2 ncxosx = (vec_double2)spu_xor(spu_splats(0x8000000000000000ull),(vec_ullong2)cxosx); + + // For odd numbered quadrants return -cx/sx , otherwise return + // sx/cx + // + vec_ullong2 mask = (vec_ullong2)spu_cmpeq(spu_and(q,(int)0x1),spu_splats((int)0)); + res = spu_sel(ncxosx,sxocx,mask); + + // If input = +/-Inf return NAN + // + res = spu_sel(res,nan,_isinfd2 (x)); + + // If input =0 or denorm return input + // + res = spu_sel(res,x, _is0denormd2 (x)); + + return res; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/tanf4.h b/Extras/simdmathlibrary/spu/simdmath/tanf4.h new file mode 100644 index 0000000..8894669 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/tanf4.h @@ -0,0 +1,95 @@ +/* tanf4 - for each of four float slots, compute the tangent by using a polynomial approximation. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_TANF4_H___ +#define ___SIMD_MATH_TANF4_H___ + +#include +#include + +#include +#include + +static inline vector float +_tanf4 (vector float x) +{ + vector float xl,x2,x3,res; + vector signed int q; + + // Range reduction using : xl = angle * TwoOverPi; + // + xl = spu_mul(x, spu_splats(0.63661977236f)); + + // Find the quadrant the angle falls in + // using: q = (int) (ceil(abs(x))*sign(x)) + // + xl = spu_add(xl,spu_sel(spu_splats(0.5f),xl,spu_splats(0x80000000))); + q = spu_convts(xl,0); + + + // Remainder in range [-pi/4..pi/4] + // + vec_float4 qf = spu_convtf(q,0); + vec_float4 p1 = spu_nmsub(qf,spu_splats(__SINCOSF_KC1),x); + xl = spu_nmsub(qf,spu_splats(__SINCOSF_KC2),p1); + + // Compute x^2 and x^3 + // + x2 = spu_mul(xl,xl); + x3 = spu_mul(x2,xl); + + + // Compute both the sin and cos of the angles + // using a polynomial expression: + // cx = 1.0f + x2 * (C0 * x2 + C1), and + // sx = xl + x3 * S0 + // + vec_float4 ct2 = spu_madd(spu_splats( 0.0097099364f),x2,spu_splats(-0.4291161787f)); + + vec_float4 cx = spu_madd(ct2,x2,spu_splats(1.0f)); + vec_float4 sx = spu_madd(spu_splats(-0.0957822992f),x3,xl); + + + // Compute both cx/sx and sx/cx + // + vec_float4 cxosx = _divf4(cx,sx); + vec_float4 sxocx = _divf4(sx,cx); + + vec_float4 ncxosx = (vec_float4)spu_xor(spu_splats(0x80000000),(vec_uint4)cxosx); + + // For odd numbered quadrants return -cx/sx , otherwise return + // sx/cx + // + vec_uint4 mask = spu_cmpeq(spu_and(q,(int)0x1),spu_splats((int)0)); + res = spu_sel(ncxosx,sxocx,mask); + + return res; +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/truncd2.h b/Extras/simdmathlibrary/spu/simdmath/truncd2.h new file mode 100644 index 0000000..a5201ab --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/truncd2.h @@ -0,0 +1,66 @@ +/* truncd2 - Round the input to the nearest integer. + Always rounds towards 0. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_TRUNCD2_H___ +#define ___SIMD_MATH_TRUNCD2_H___ + +#include +#include + +static inline vector double +_truncd2(vector double in) +{ + vec_uchar16 splat_hi = ((vec_uchar16){ 0,1,2,3,0,1,2,3, 8,9,10,11, 8,9,10,11}); + vec_int4 exp, shift; + vec_uint4 sign = ((vec_uint4){ 0x80000000, 0, 0x80000000, 0}); + vec_uint4 or_mask, and_mask, mask; + vec_double2 in_hi, out; + + /* Construct a mask to remove the fraction bits. The mask + * depends on the exponent of the floating point + * input value. + */ + in_hi = spu_shuffle(in, in, splat_hi); + exp = spu_and(spu_rlmask((vec_int4)in_hi, -20), 0x7FF); + + shift = spu_sub(((vec_int4){ 1023, 1043, 1023, 1043}), exp); + or_mask = spu_andc(spu_cmpgt(shift, 0), sign); + + and_mask = spu_rlmask(((vec_uint4){ 0xFFFFF, -1, 0xFFFFF, -1}), shift); + mask = spu_or(spu_and(and_mask, spu_cmpgt(shift, -32)), or_mask); + + /* Apply the mask and return the result. + */ + out = spu_andc(in, (vec_double2)(mask)); + + return (out); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/simdmath/truncf4.h b/Extras/simdmathlibrary/spu/simdmath/truncf4.h new file mode 100644 index 0000000..b519160 --- /dev/null +++ b/Extras/simdmathlibrary/spu/simdmath/truncf4.h @@ -0,0 +1,52 @@ +/* truncf4 - for each of four float slots, round towards zero to integer value. + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ___SIMD_MATH_TRUNCF4_H___ +#define ___SIMD_MATH_TRUNCF4_H___ + +#include +#include + +static inline vector float +_truncf4 (vector float x) +{ + vector signed int xi; + vector unsigned int inrange; + + // Can convert to and from signed integer to truncate values in range [-2^31, 2^31). + // However, no truncation needed if exponent > 22. + + inrange = spu_cmpabsgt( (vector float)spu_splats(0x4b000000), x ); + + xi = spu_convts( x, 0 ); + + return spu_sel( x, spu_convtf( xi, 0 ), inrange ); +} + +#endif diff --git a/Extras/simdmathlibrary/spu/tests/Makefile b/Extras/simdmathlibrary/spu/tests/Makefile new file mode 100644 index 0000000..57c5f61 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/Makefile @@ -0,0 +1,51 @@ +# Makefile for testsuite for the SPU SIMD math library +# Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. +# 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 Sony Computer Entertainment Inc 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. + +topdir = ../.. +ARCH = spu + +include $(topdir)/Make.defs + +TESTS = fabsd2 fabsf4 truncf4 divf4 recipd2 divd2 sqrtf4 \ + absi4 sqrtd2 rsqrtf4 rsqrtd2 copysignf4 remainderf4 \ + recipf4 copysignd2 negatef4 negated2 modff4 ceilf4 \ + fminf4_fmaxf4 floorf4 negatei4 divi4 llroundd2 llroundf4 \ + llrintf4 isequalf4 isequald2 islessgreaterf4 islessgreaterd2 \ + islessf4 islessd2 isgreaterf4 isgreaterd2 islessequalf4 islessequald2 \ + isgreaterequalf4 isgreaterequald2 isnanf4 isnand2 isinff4 isinfd2 \ + isfinitef4 isfinited2 isnormalf4 isnormald2 isunorderedf4 isunorderedd2 \ + is0denormf4 is0denormd2 signbitf4 signbitd2 llrintd2 \ + roundf4 iroundf4 rintf4 irintf4 fmind2_fmaxd2 fdimd2 \ + fmad2 nextafterd2 nextafterf4 fpclassifyf4 fpclassifyd2 nearbyintd2 nearbyintf4 \ + llabsi2 truncd2 roundd2 rintd2 negatell2 hypotf4 hypotd2 divu4 modfd2 \ + lldivu2 ceild2 floord2 ldexpd2 ilogbd2 ilogbf4 logbf4 logbd2 scalbnf4 \ + scalbllnd2 lldivi2 frexpf4 frexpd2 remquof4 remquod2 fmodd2 remainderd2 + +OBJS = testutils.o + +include $(topdir)/Make.test diff --git a/Extras/simdmathlibrary/spu/tests/absi4.c b/Extras/simdmathlibrary/spu/tests/absi4.c new file mode 100644 index 0000000..bd150e4 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/absi4.c @@ -0,0 +1,90 @@ +/* Test absi4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20040908101807EJL","EJL", "abs"); + + int x0n = hide_int(0); + int x0p = hide_int(0); + int x1n = hide_int(-1); + int x1p = hide_int(1); + int x2n = hide_int(-83532); + int x2p = hide_int(83532); + + vec_int4 x0n_v = spu_splats(x0n); + vec_int4 x0p_v = spu_splats(x0p); + vec_int4 x1n_v = spu_splats(x1n); + vec_int4 x1p_v = spu_splats(x1p); + vec_int4 x2n_v = spu_splats(x2n); + vec_int4 x2p_v = spu_splats(x2p); + + int res; + vec_int4 res_v; + + TEST_START("absi4"); + res_v = absi4(x0n_v); + TEST_CHECK("20040908103824EJL", allequal_int4( res_v, x0p_v ), 0); + res_v = absi4(x0p_v); + TEST_CHECK("20040908103903EJL", allequal_int4( res_v, x0p_v ), 0); + res_v = absi4(x1n_v); + TEST_CHECK("20040908103905EJL", allequal_int4( res_v, x1p_v ), 0); + res_v = absi4(x1p_v); + TEST_CHECK("20040908114003EJL", allequal_int4( res_v, x1p_v ), 0); + res_v = absi4(x2n_v); + TEST_CHECK("20040908114714EJL", allequal_int4( res_v, x2p_v ), 0); + res_v = absi4(x2p_v); + TEST_CHECK("20040908114715EJL", allequal_int4( res_v, x2p_v ), 0); + + TEST_START("abs"); + res = abs(x0n); + TEST_CHECK("20040908114718EJL", res == x0p, 0); + res = abs(x0p); + TEST_CHECK("20040908114719EJL", res == x0p, 0); + res = abs(x1n); + TEST_CHECK("20040908114720EJL", res == x1p, 0); + res = abs(x1p); + TEST_CHECK("20040908114721EJL", res == x1p, 0); + res = abs(x2n); + TEST_CHECK("20040908114722EJL", res == x2p, 0); + res = abs(x2p); + TEST_CHECK("20040908114723EJL", res == x2p, 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/ceild2.c b/Extras/simdmathlibrary/spu/tests/ceild2.c new file mode 100644 index 0000000..7712c5b --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/ceild2.c @@ -0,0 +1,156 @@ +/* Test roundd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/** + * + *@@ ceild2for each of two doule slots, + * round up to smallest integer not less than the value. + * + *@brief + * boundary test for ceild2. + * + * + *@pre + * + *@criteria + * Run this program and check no error will be occurred. + * + *@note + * + * + **/ +#include +#include +#include +//#include +#include + +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +typedef union { + struct { + double xxx[2]; + double ans[2]; + } dbl; + struct { + unsigned long long xxx[2]; + unsigned long long ans[2]; + } ull; +} TestVec_Roundd2; + +int main() +{ + TestVec_Roundd2 test_a[] = { + { + ull:{ + // 0 -> 0 , -0 -> -0 + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL} + } + },{ + ull:{ + // -Inf -> -Inf , Inf -> Inf + {0xFFF0000000000000ULL,0x7FF0000000000000ULL}, + {0xFFF0000000000000ULL,0x7FF0000000000000ULL} + } + },{ + ull:{ + // MAX -> MAX , MIN -> MIN + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL} + } + },{ + ull:{ + // Denormalize -> 0 + {0x0000000000000001ULL,0x8000000000000010ULL}, + {0x3ff0000000000000ULL,0x8000000000000000ULL} + } + },{ + ull:{ + // Denormalize -> 0 + {0x800FFFFFFFFFFFFFULL,0x000FFFFFFFFFFFFFULL}, + {0x8000000000000000ULL,0x3ff0000000000000ULL} + } + },{ + ull:{ + // border + {0x4320000000000001ULL,0xC320000000000001ULL}, + {0x4320000000000002ULL,0xC320000000000000ULL} + } + },{ + dbl:{ + {1.0, -1.0}, + {1.0, -1.0} + } + },{ + dbl:{ + {0.5, -0.5}, + {1.0, -0.0} + } + },{ + dbl:{ + {-2.75, 3.2}, + {-2.0, 4.0} + } + },{ + ull:{ + // Nan + {0xFFF0000000000001ULL,0x7FF0000000000001ULL}, + {0xFFF0000000000001ULL,0x7FF0000000000001ULL} + } + },{ + ull:{ + {0ULL,0ULL}, + {0ULL,0ULL} + } + } + }; + int ii, test_ctr = 1; + char msg[80]; + vec_double2 res_v; + //vec_double2 input; + + TEST_SET_START("51651906100000NM","CED", "ceild2"); + + TEST_START("ceild2"); + + for (ii=0; ; ii++) { + if ( (test_a[ii].ull.xxx[0] == 0) && (test_a[ii].ull.xxx[1] == 0) ) break; + //input = *((vec_double2 *)&test_a[ii].dbl.xxx[0]); + res_v = ceild2 (*((vec_double2 *)&test_a[ii].dbl.xxx[0]) ); + sprintf(msg,"5165190610%04dCED", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, (vec_llong2)*((vec_double2 *)&test_a[ii].dbl.ans[0])), 0); + } + + TEST_SET_DONE(); + + TEST_EXIT(); + +} diff --git a/Extras/simdmathlibrary/spu/tests/ceilf4.c b/Extras/simdmathlibrary/spu/tests/ceilf4.c new file mode 100644 index 0000000..d130176 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/ceilf4.c @@ -0,0 +1,108 @@ +/* Test ceilf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20040916103300EJL","EJL", "ceilf"); + + unsigned int i3 = 0x4affffff; // 2^23 - 0.5, largest truncatable value. + unsigned int i3i = 0x4b000000; + unsigned int i4 = 0x4b000000; // 2^23, no fractional part. + unsigned int i5 = 0xcf000001; // -2^31, one more large, and negative, value. + + float x0 = hide_float(0.91825f); + float x0i = hide_float(1.0f); + float x1 = hide_float(-0.12958f); + float x1i = hide_float(0.0f); + float x2 = hide_float(-79615.1875f); + float x2i = hide_float(-79615.0f); + float x3 = hide_float(make_float(i3)); + float x3i = hide_float(make_float(i3i)); + float x4 = hide_float(make_float(i4)); + float x4i = hide_float(make_float(i4)); + float x5 = hide_float(make_float(i5)); + float x5i = hide_float(make_float(i5)); + + vec_float4 x0_v = spu_splats(x0); + vec_float4 x0i_v = spu_splats(x0i); + vec_float4 x1_v = spu_splats(x1); + vec_float4 x1i_v = spu_splats(x1i); + vec_float4 x2_v = spu_splats(x2); + vec_float4 x2i_v = spu_splats(x2i); + vec_float4 x3_v = spu_splats(x3); + vec_float4 x3i_v = spu_splats(x3i); + vec_float4 x4_v = spu_splats(x4); + vec_float4 x4i_v = spu_splats(x4i); + vec_float4 x5_v = spu_splats(x5); + vec_float4 x5i_v = spu_splats(x5i); + + float res; + vec_float4 res_v; + + TEST_START("ceilf4"); + res_v = ceilf4(x0_v); + TEST_CHECK("20040916103310EJL", allequal_float4( res_v, x0i_v ), 0); + res_v = ceilf4(x1_v); + TEST_CHECK("20040916103324EJL", allequal_float4( res_v, x1i_v ), 0); + res_v = ceilf4(x2_v); + TEST_CHECK("20040916103334EJL", allequal_float4( res_v, x2i_v ), 0); + res_v = ceilf4(x3_v); + TEST_CHECK("20040916103341EJL", allequal_float4( res_v, x3i_v ), 0); + res_v = ceilf4(x4_v); + TEST_CHECK("20040916103350EJL", allequal_float4( res_v, x4i_v ), 0); + res_v = ceilf4(x5_v); + TEST_CHECK("20040916103357EJL", allequal_float4( res_v, x5i_v ), 0); + + TEST_START("ceilf"); + res = ceilf(x0); + TEST_CHECK("20040916103407EJL", res == x0i, 0); + res = ceilf(x1); + TEST_CHECK("20040916103418EJL", res == x1i, 0); + res = ceilf(x2); + TEST_CHECK("20040916103428EJL", res == x2i, 0); + res = ceilf(x3); + TEST_CHECK("20040916103437EJL", res == x3i, 0); + res = ceilf(x4); + TEST_CHECK("20040916103448EJL", res == x4i, 0); + res = ceilf(x5); + TEST_CHECK("20040916103457EJL", res == x5i, 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/copysignd2.c b/Extras/simdmathlibrary/spu/tests/copysignd2.c new file mode 100644 index 0000000..0aa8312 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/copysignd2.c @@ -0,0 +1,74 @@ +/* Test copysignd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" +int main() +{ + TEST_SET_START("20040928185245EJL","EJL", "copysign"); + + double x0m = hide_double(1989.0); + double x0s = hide_double(-319875.0); + double x0c = hide_double(-1989.0); + double x1m = hide_double(9013.0); + double x1s = hide_double(185.0); + double x1c = hide_double(9013.0); + + vec_double2 x0m_v = spu_splats(x0m); + vec_double2 x0s_v = spu_splats(x0s); + vec_double2 x0c_v = spu_splats(x0c); + + vec_double2 x1m_v = spu_splats(x1m); + vec_double2 x1s_v = spu_splats(x1s); + vec_double2 x1c_v = spu_splats(x1c); + + double res; + vec_double2 res_v; + + TEST_START("copysignd2"); + res_v = copysignd2( x0m_v, x0s_v ); + TEST_CHECK("20040928185248EJL", allequal_double2( res_v, x0c_v ), 0); + res_v = copysignd2( x1m_v, x1s_v ); + TEST_CHECK("20040928185251EJL", allequal_double2( res_v, x1c_v ), 0); + + TEST_START("copysign"); + res = copysign( x0m, x0s ); + TEST_CHECK("20040928185253EJL", res == x0c, 0); + res = copysign( x1m, x1s ); + TEST_CHECK("20040928185256EJL", res == x1c, 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/copysignf4.c b/Extras/simdmathlibrary/spu/tests/copysignf4.c new file mode 100644 index 0000000..148ecca --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/copysignf4.c @@ -0,0 +1,75 @@ +/* Test copysignf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20040917114054EJL", "EJL", "copysignf"); + + float x0m = hide_float(1989.0f); + float x0s = hide_float(-319875.0f); + float x0c = hide_float(-1989.0f); + float x1m = hide_float(9013.0f); + float x1s = hide_float(185.0f); + float x1c = hide_float(9013.0f); + + vec_float4 x0m_v = spu_splats(x0m); + vec_float4 x0s_v = spu_splats(x0s); + vec_float4 x0c_v = spu_splats(x0c); + + vec_float4 x1m_v = spu_splats(x1m); + vec_float4 x1s_v = spu_splats(x1s); + vec_float4 x1c_v = spu_splats(x1c); + + float res; + vec_float4 res_v; + + TEST_START("copysignf4"); + res_v = copysignf4( x0m_v, x0s_v ); + TEST_CHECK("20040917114058EJL", allequal_float4( res_v, x0c_v ), 0); + res_v = copysignf4( x1m_v, x1s_v ); + TEST_CHECK("20040917114100EJL", allequal_float4( res_v, x1c_v ), 0); + + TEST_START("copysignf"); + res = copysignf( x0m, x0s ); + TEST_CHECK("20040917114102EJL", res == x0c, 0); + res = copysignf( x1m, x1s ); + TEST_CHECK("20040917114104EJL", res == x1c, 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/divd2.c b/Extras/simdmathlibrary/spu/tests/divd2.c new file mode 100644 index 0000000..66a6dca --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/divd2.c @@ -0,0 +1,153 @@ +/* Test divd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + + +int main() +{ + TEST_SET_START("20040927182952EJL","EJL", "divd2"); + + unsigned long long i3n = 0x747f7fefa0c3274aull; + unsigned long long i3d = 0x7606a4533cf5605eull; + unsigned long long i3r = 0x3e66426af0ec01b0ull; + unsigned long long i4n = 0x4c042c295376566eull; + unsigned long long i4d = 0x39b3720562510408ull; + unsigned long long i4r = 0x52409928d3244077ull; + unsigned long long i5n = 0x6911a64538a389aeull; + unsigned long long i5d = 0x1ac4d062d451c99dull; + unsigned long long i5r = 0x7ff0000000000000ull; + unsigned long long i6n = 0x5b112f9d39e7de27ull; + unsigned long long i6d = 0x5659f8dbe4993d7cull; + unsigned long long i6r = 0x44a52cb9b9d2b2cdull; + unsigned long long i7n = 0x7410065c772e25daull; + unsigned long long i7d = 0x6a576b936e5f1034ull; + unsigned long long i7r = 0x49a5e53936c1b556ull; + unsigned long long i8n = 0x3605d9b2916be0f5ull; + unsigned long long i8d = 0x61f25e39867b0a9eull; + unsigned long long i8r = 0x1403088aa08482f2ull; + + double x0n = hide_double(-HUGE_VAL); // -Inf/ Inf == NaN + double x0d = hide_double(HUGE_VAL); + + double x1n = hide_double(0.0); // 0 / 0 == NaN + double x1d = hide_double(-0.0); + + double x2n = hide_double(nan("")); // NaN / 2 == NaN + double x2d = hide_double(2.0); + + double x3n = hide_double(make_double(i3n)); + double x3d = hide_double(make_double(i3d)); + double x3r = hide_double(make_double(i3r)); + + double x4n = hide_double(make_double(i4n)); + double x4d = hide_double(make_double(i4d)); + double x4r = hide_double(make_double(i4r)); + + double x5n = hide_double(make_double(i5n)); + double x5d = hide_double(make_double(i5d)); + double x5r = hide_double(make_double(i5r)); + + double x6n = hide_double(make_double(i6n)); + double x6d = hide_double(make_double(i6d)); + double x6r = hide_double(make_double(i6r)); + + double x7n = hide_double(make_double(i7n)); + double x7d = hide_double(make_double(i7d)); + double x7r = hide_double(make_double(i7r)); + + double x8n = hide_double(make_double(i8n)); + double x8d = hide_double(make_double(i8d)); + double x8r = hide_double(make_double(i8r)); + + vec_double2 x0n_v = spu_splats(x0n); + vec_double2 x0d_v = spu_splats(x0d); + + vec_double2 x1n_v = spu_splats(x1n); + vec_double2 x1d_v = spu_splats(x1d); + + vec_double2 x2n_v = spu_splats(x2n); + vec_double2 x2d_v = spu_splats(x2d); + + vec_double2 x3n_v = spu_splats(x3n); + vec_double2 x3d_v = spu_splats(x3d); + vec_double2 x3r_v = spu_splats(x3r); + + vec_double2 x4n_v = spu_splats(x4n); + vec_double2 x4d_v = spu_splats(x4d); + vec_double2 x4r_v = spu_splats(x4r); + + vec_double2 x5n_v = spu_splats(x5n); + vec_double2 x5d_v = spu_splats(x5d); + vec_double2 x5r_v = spu_splats(x5r); + + vec_double2 x6n_v = spu_splats(x6n); + vec_double2 x6d_v = spu_splats(x6d); + vec_double2 x6r_v = spu_splats(x6r); + + vec_double2 x7n_v = spu_splats(x7n); + vec_double2 x7d_v = spu_splats(x7d); + vec_double2 x7r_v = spu_splats(x7r); + + vec_double2 x8n_v = spu_splats(x8n); + vec_double2 x8d_v = spu_splats(x8d); + vec_double2 x8r_v = spu_splats(x8r); + + vec_double2 res_v; + + TEST_START("divd2"); + res_v = divd2(x0n_v, x0d_v); + TEST_CHECK("20040927183001EJL", allnan_double2( res_v ), 0); + res_v = divd2(x1n_v, x1d_v); + TEST_CHECK("20040927183003EJL", allnan_double2( res_v ), 0); + res_v = divd2(x2n_v, x2d_v); + TEST_CHECK("20040927183006EJL", allnan_double2( res_v ), 0); + res_v = divd2(x3n_v, x3d_v); + TEST_CHECK("20040927183008EJL", allequal_ulps_double2( res_v, x3r_v, 1 ), 0 ); + res_v = divd2(x4n_v, x4d_v); + TEST_CHECK("20040927183010EJL", allequal_ulps_double2( res_v, x4r_v, 1 ), 0 ); + res_v = divd2(x5n_v, x5d_v); + TEST_CHECK("20040927183012EJL", allequal_ulps_double2( res_v, x5r_v, 1 ), 0 ); + res_v = divd2(x6n_v, x6d_v); + TEST_CHECK("20040927183014EJL", allequal_ulps_double2( res_v, x6r_v, 1 ), 0 ); + res_v = divd2(x7n_v, x7d_v); + TEST_CHECK("20040927183016EJL", allequal_ulps_double2( res_v, x7r_v, 1 ), 0 ); + res_v = divd2(x8n_v, x8d_v); + TEST_CHECK("20040927183018EJL", allequal_ulps_double2( res_v, x8r_v, 1 ), 0 ); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/divf4.c b/Extras/simdmathlibrary/spu/tests/divf4.c new file mode 100644 index 0000000..e60b668 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/divf4.c @@ -0,0 +1,128 @@ +/* Test divf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20040928105926EJL","EJL", "divf4"); + + unsigned int i0n = 0x75013340; + unsigned int i0d = 0x75e7753f; + unsigned int i0r = 0x3e8ee64b; + unsigned int i1n = 0x4c7fed5a; + unsigned int i1d = 0x3a0731f0; + unsigned int i1r = 0x51f24e86; + unsigned int i2n = 0x5b08b303; + unsigned int i2d = 0x562f5046; + unsigned int i2r = 0x44479d24; + unsigned int i3n = 0x748a9b87; + unsigned int i3d = 0x6b014b46; + unsigned int i3r = 0x49093864; + unsigned int i4n = 0x35dcf9d8; + unsigned int i4d = 0x6278d6e0; + unsigned int i4r = 0x12e355b5; + unsigned int i5n = 0x74d505fd; + unsigned int i5d = 0x61ef565e; + unsigned int i5r = 0x5263daa3; + + float x0n = hide_float(make_float(i0n)); + float x0d = hide_float(make_float(i0d)); + float x0r = hide_float(make_float(i0r)); + + float x1n = hide_float(make_float(i1n)); + float x1d = hide_float(make_float(i1d)); + float x1r = hide_float(make_float(i1r)); + + float x2n = hide_float(make_float(i2n)); + float x2d = hide_float(make_float(i2d)); + float x2r = hide_float(make_float(i2r)); + + float x3n = hide_float(make_float(i3n)); + float x3d = hide_float(make_float(i3d)); + float x3r = hide_float(make_float(i3r)); + + float x4n = hide_float(make_float(i4n)); + float x4d = hide_float(make_float(i4d)); + float x4r = hide_float(make_float(i4r)); + + float x5n = hide_float(make_float(i5n)); + float x5d = hide_float(make_float(i5d)); + float x5r = hide_float(make_float(i5r)); + + vec_float4 x0n_v = spu_splats(x0n); + vec_float4 x0d_v = spu_splats(x0d); + vec_float4 x0r_v = spu_splats(x0r); + + vec_float4 x1n_v = spu_splats(x1n); + vec_float4 x1d_v = spu_splats(x1d); + vec_float4 x1r_v = spu_splats(x1r); + + vec_float4 x2n_v = spu_splats(x2n); + vec_float4 x2d_v = spu_splats(x2d); + vec_float4 x2r_v = spu_splats(x2r); + + vec_float4 x3n_v = spu_splats(x3n); + vec_float4 x3d_v = spu_splats(x3d); + vec_float4 x3r_v = spu_splats(x3r); + + vec_float4 x4n_v = spu_splats(x4n); + vec_float4 x4d_v = spu_splats(x4d); + vec_float4 x4r_v = spu_splats(x4r); + + vec_float4 x5n_v = spu_splats(x5n); + vec_float4 x5d_v = spu_splats(x5d); + vec_float4 x5r_v = spu_splats(x5r); + + vec_float4 res_v; + + TEST_START("divf4"); + res_v = divf4(x0n_v, x0d_v); + TEST_CHECK("20040928105932EJL", allequal_ulps_float4( res_v, x0r_v, 2 ), 0); + res_v = divf4(x1n_v, x1d_v); + TEST_CHECK("20040928105934EJL", allequal_ulps_float4( res_v, x1r_v, 2 ), 0); + res_v = divf4(x2n_v, x2d_v); + TEST_CHECK("20040928105936EJL", allequal_ulps_float4( res_v, x2r_v, 2 ), 0); + res_v = divf4(x3n_v, x3d_v); + TEST_CHECK("20040928105938EJL", allequal_ulps_float4( res_v, x3r_v, 2 ), 0); + res_v = divf4(x4n_v, x4d_v); + TEST_CHECK("20040928105940EJL", allequal_ulps_float4( res_v, x4r_v, 2 ), 0); + res_v = divf4(x5n_v, x5d_v); + TEST_CHECK("20040928105943EJL", allequal_ulps_float4( res_v, x5r_v, 2 ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/divi4.c b/Extras/simdmathlibrary/spu/tests/divi4.c new file mode 100644 index 0000000..a56239b --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/divi4.c @@ -0,0 +1,123 @@ +/* Test divi4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20040928161739EJL","EJL", "divi4"); + + int x0n = 0xffccb78d; + int x0d = 0x0 ; + int x0q = 0x0 ; + int x0r = 0xffccb78d; + int x1n = 0xff978333; + int x1d = 0xff976bb6; + int x1q = 0x0 ; + int x1r = 0xff978333; + int x2n = 0x5e146 ; + int x2d = 0xd14ebe0e; + int x2q = 0x0 ; + int x2r = 0x5e146 ; + int x3n = 0xf0e91618; + int x3d = 0xfddff7ac; + int x3q = 0x7 ; + int x3r = 0xffc95064; + + int x4n = 0xf2128d9d; + int x4d = 0xe0f76 ; + int x4q = 0xffffff03; + int x4r = 0xfff7d53b; + int x5n = 0xda1ba2ce; + int x5d = 0x4c9 ; + int x5q = 0xfff814d3; + int x5r = 0xfffffd23; + int x6n = 0xdd4426a6; + int x6d = 0xf8d245cf; + int x6q = 0x4 ; + int x6r = 0xf9fb0f6a; + int x7n = 0xd1d5ae9 ; + int x7d = 0x333ab105; + int x7q = 0x0 ; + int x7r = 0xd1d5ae9 ; + + int x8n = 0x3e0c6 ; + int x8d = 0xfff24255; + int x8q = 0x0 ; + int x8r = 0x3e0c6 ; + int x9n = 0xfd6fe27e; + int x9d = 0xf32454 ; + int x9q = 0xfffffffe; + int x9r = 0xff562b26; + int x10n =0xfb150f79; + int x10d =0xf521 ; + int x10q =0xfffffade; + int x10r =0xffff42db; + int x11n =0xfe88071f; + int x11d =0xfff937c2; + int x11q =0x37 ; + int x11r =0xfffd0c71; + + + vec_int4 x0n_v = (vec_int4){ x0n, x1n, x2n, x3n }; + vec_int4 x1n_v = (vec_int4){ x4n, x5n, x6n, x7n }; + vec_int4 x2n_v = (vec_int4){ x8n, x9n, x10n, x11n }; + + vec_int4 x0d_v = (vec_int4){ x0d, x1d, x2d, x3d }; + vec_int4 x1d_v = (vec_int4){ x4d, x5d, x6d, x7d }; + vec_int4 x2d_v = (vec_int4){ x8d, x9d, x10d, x11d }; + + vec_int4 x0q_v = (vec_int4){ x0q, x1q, x2q, x3q }; + vec_int4 x1q_v = (vec_int4){ x4q, x5q, x6q, x7q }; + vec_int4 x2q_v = (vec_int4){ x8q, x9q, x10q, x11q }; + + vec_int4 x0r_v = (vec_int4){ x0r, x1r, x2r, x3r }; + vec_int4 x1r_v = (vec_int4){ x4r, x5r, x6r, x7r }; + vec_int4 x2r_v = (vec_int4){ x8r, x9r, x10r, x11r }; + + divi4_t res; + + TEST_START("divi4"); + res = divi4(x0n_v, x0d_v); + TEST_CHECK("20040928161846EJL", allequal_int4( res.quot, x0q_v ) && allequal_int4( res.rem, x0r_v ), 0); + res = divi4(x1n_v, x1d_v); + TEST_CHECK("20040928161851EJL", allequal_int4( res.quot, x1q_v ) && allequal_int4( res.rem, x1r_v ), 0); + res = divi4(x2n_v, x2d_v); + TEST_CHECK("20040928161855EJL", allequal_int4( res.quot, x2q_v ) && allequal_int4( res.rem, x2r_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/divu4.c b/Extras/simdmathlibrary/spu/tests/divu4.c new file mode 100644 index 0000000..a5fff1d --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/divu4.c @@ -0,0 +1,146 @@ +/* Test divu4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060901150000MH","MH", "divu4"); + + unsigned int x0n = 0xffccb78d; + unsigned int x0d = 0x0 ; + unsigned int x0q = 0x0 ; + unsigned int x0r = 0xffccb78d; + unsigned int x1n = 0xff978333; + unsigned int x1d = 0xff976bb6; + unsigned int x1q = 0x1 ; + unsigned int x1r = 0x177d ; + unsigned int x2n = 0x5e146 ; + unsigned int x2d = 0xd14ebe0e; + unsigned int x2q = 0x0 ; + unsigned int x2r = 0x5e146 ; + unsigned int x3n = 0xf0e91618; + unsigned int x3d = 0xfddff7ac; + unsigned int x3q = 0x0 ; + unsigned int x3r = 0xf0e91618; + + unsigned int x4n = 0xf2128d9d; + unsigned int x4d = 0xe0f76 ; + unsigned int x4q = 0x1137 ; + unsigned int x4r = 0x66543 ; + unsigned int x5n = 0xda1ba2ce; + unsigned int x5d = 0x4c9 ; + unsigned int x5q = 0x2d9482 ; + unsigned int x5r = 0xbc ; + unsigned int x6n = 0xdd4426a6; + unsigned int x6d = 0xf8d245cf; + unsigned int x6q = 0x0 ; + unsigned int x6r = 0xdd4426a6; + unsigned int x7n = 0xd1d5ae9 ; + unsigned int x7d = 0x333ab105; + unsigned int x7q = 0x0 ; + unsigned int x7r = 0xd1d5ae9 ; + + unsigned int x8n = 0x3e0c6 ; + unsigned int x8d = 0xfff24255; + unsigned int x8q = 0x0 ; + unsigned int x8r = 0x3e0c6 ; + unsigned int x9n = 0xfd6fe27e; + unsigned int x9d = 0xf32454 ; + unsigned int x9q = 0x10a ; + unsigned int x9r = 0xcc2336 ; + unsigned int x10n =0xfb150f79; + unsigned int x10d =0xf521 ; + unsigned int x10q =0x10637 ; + unsigned int x10r =0x9f62 ; + unsigned int x11n =0xfe88071f; + unsigned int x11d =0xfff937c2; + unsigned int x11q =0x0 ; + unsigned int x11r =0xfe88071f; + + unsigned int x12n =0xc374fa4 ; + unsigned int x12d =0x1234 ; + unsigned int x12q =0xabcd ; + unsigned int x12r =0x0 ; + unsigned int x13n =0xffffffff; + unsigned int x13d =0x2 ; + unsigned int x13q =0x7fffffff; + unsigned int x13r =0x1 ; + unsigned int x14n =0x0 ; + unsigned int x14d =0x12345678; + unsigned int x14q =0x0 ; + unsigned int x14r =0x0 ; + unsigned int x15n =0xffffffff; + unsigned int x15d =0x1 ; + unsigned int x15q =0xffffffff; + unsigned int x15r =0x0 ; + + vec_uint4 x0n_v = (vec_uint4){ x0n, x1n, x2n, x3n }; + vec_uint4 x1n_v = (vec_uint4){ x4n, x5n, x6n, x7n }; + vec_uint4 x2n_v = (vec_uint4){ x8n, x9n, x10n, x11n }; + vec_uint4 x3n_v = (vec_uint4){ x12n, x13n, x14n, x15n }; + + vec_uint4 x0d_v = (vec_uint4){ x0d, x1d, x2d, x3d }; + vec_uint4 x1d_v = (vec_uint4){ x4d, x5d, x6d, x7d }; + vec_uint4 x2d_v = (vec_uint4){ x8d, x9d, x10d, x11d }; + vec_uint4 x3d_v = (vec_uint4){ x12d, x13d, x14d, x15d }; + + vec_uint4 x0q_v = (vec_uint4){ x0q, x1q, x2q, x3q }; + vec_uint4 x1q_v = (vec_uint4){ x4q, x5q, x6q, x7q }; + vec_uint4 x2q_v = (vec_uint4){ x8q, x9q, x10q, x11q }; + vec_uint4 x3q_v = (vec_uint4){ x12q, x13q, x14q, x15q }; + + vec_uint4 x0r_v = (vec_uint4){ x0r, x1r, x2r, x3r }; + vec_uint4 x1r_v = (vec_uint4){ x4r, x5r, x6r, x7r }; + vec_uint4 x2r_v = (vec_uint4){ x8r, x9r, x10r, x11r }; + vec_uint4 x3r_v = (vec_uint4){ x12r, x13r, x14r, x15r }; + + divu4_t res; + + TEST_START("divu4"); + res = divu4(x0n_v, x0d_v); + TEST_CHECK("20060901150001MH", allequal_uint4( res.quot, x0q_v ) && allequal_uint4( res.rem, x0r_v ), 0); + res = divu4(x1n_v, x1d_v); + TEST_CHECK("20060901150002MH", allequal_uint4( res.quot, x1q_v ) && allequal_uint4( res.rem, x1r_v ), 0); + res = divu4(x2n_v, x2d_v); + TEST_CHECK("20060901150003MH", allequal_uint4( res.quot, x2q_v ) && allequal_uint4( res.rem, x2r_v ), 0); + res = divu4(x3n_v, x3d_v); + TEST_CHECK("20060901150004MH", allequal_uint4( res.quot, x3q_v ) && allequal_uint4( res.rem, x3r_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/fabsd2.c b/Extras/simdmathlibrary/spu/tests/fabsd2.c new file mode 100644 index 0000000..11e366d --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/fabsd2.c @@ -0,0 +1,103 @@ +/* Test fabsd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20040908022501EJL","EJL", "fabs"); + + double x0n = hide_double(-0.0); + double x0p = hide_double(0.0); + double x1n = hide_double(-83532.96153153); + double x1p = hide_double(83532.96153153); + double x2n = hide_double(-0.0000000013152); + double x2p = hide_double(0.0000000013152); + double x3n = hide_double(-HUGE_VAL); + double x3p = hide_double(HUGE_VAL); + + vec_double2 x0n_v = spu_splats(x0n); + vec_double2 x0p_v = spu_splats(x0p); + vec_double2 x1n_v = spu_splats(x1n); + vec_double2 x1p_v = spu_splats(x1p); + vec_double2 x2n_v = spu_splats(x2n); + vec_double2 x2p_v = spu_splats(x2p); + vec_double2 x3n_v = spu_splats(x3n); + vec_double2 x3p_v = spu_splats(x3p); + + double res; + vec_double2 res_v; + + TEST_START("fabsd2"); + res_v = fabsd2(x0n_v); + TEST_CHECK("20040908022502EJL", allequal_double2( res_v, x0p_v ), 0); + res_v = fabsd2(x0p_v); + TEST_CHECK("20040908022503EJL", allequal_double2( res_v, x0p_v ), 0); + res_v = fabsd2(x1n_v); + TEST_CHECK("20040908022504EJL", allequal_double2( res_v, x1p_v ), 0); + res_v = fabsd2(x1p_v); + TEST_CHECK("20040908022505EJL", allequal_double2( res_v, x1p_v ), 0); + res_v = fabsd2(x2n_v); + TEST_CHECK("20040908022506EJL", allequal_double2( res_v, x2p_v ), 0); + res_v = fabsd2(x2p_v); + TEST_CHECK("20040908022507EJL", allequal_double2( res_v, x2p_v ), 0); + res_v = fabsd2(x3n_v); + TEST_CHECK("20040908022508EJL", allposinf_double2( res_v ), 0); + res_v = fabsd2(x3p_v); + TEST_CHECK("20040908022509EJL", allposinf_double2( res_v ), 0); + + TEST_START("fabs"); + res = fabs( x0n ); + TEST_CHECK("20040908022510EJL", res == x0p, 0); + res = fabs( x0p ); + TEST_CHECK("20040908022511EJL", res == x0p, 0); + res = fabs( x1n ); + TEST_CHECK("20040908022512EJL", res == x1p, 0); + res = fabs( x1p ); + TEST_CHECK("20040908022513EJL", res == x1p, 0); + res = fabs( x2n ); + TEST_CHECK("20040908022514EJL", res == x2p, 0); + res = fabs( x2p ); + TEST_CHECK("20040908022515EJL", res == x2p, 0); + res = fabs( x3n ); + TEST_CHECK("20040908022516EJL", isinf(res) == 1, 0); + res = fabs( x3p ); + TEST_CHECK("20040908022517EJL", isinf(res) == 1, 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/fabsf4.c b/Extras/simdmathlibrary/spu/tests/fabsf4.c new file mode 100644 index 0000000..4d62074 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/fabsf4.c @@ -0,0 +1,106 @@ +/* Test fabsf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20040915032605EJL","EJL", "fabsf"); + + unsigned int i3n = 0xffffffff; + unsigned int i3p = 0x7fffffff; + + float x0n = hide_float(-0.0f); + float x0p = hide_float(0.0f); + float x1n = hide_float(-83532.96153153f); + float x1p = hide_float(83532.96153153f); + float x2n = hide_float(-0.0000000013152f); + float x2p = hide_float(0.0000000013152f); + float x3n = hide_float(make_float(i3n)); + float x3p = hide_float(make_float(i3p)); + + vec_float4 x0n_v = spu_splats(x0n); + vec_float4 x0p_v = spu_splats(x0p); + vec_float4 x1n_v = spu_splats(x1n); + vec_float4 x1p_v = spu_splats(x1p); + vec_float4 x2n_v = spu_splats(x2n); + vec_float4 x2p_v = spu_splats(x2p); + vec_float4 x3n_v = spu_splats(x3n); + vec_float4 x3p_v = spu_splats(x3p); + + float res; + vec_float4 res_v; + + TEST_START("fabsf4"); + res_v = fabsf4(x0n_v); + TEST_CHECK("20040915032618EJL", allequal_float4( res_v, x0p_v ), 0); + res_v = fabsf4(x0p_v); + TEST_CHECK("20040915032632EJL", allequal_float4( res_v, x0p_v ), 0); + res_v = fabsf4(x1n_v); + TEST_CHECK("20040915032643EJL", allequal_float4( res_v, x1p_v ), 0); + res_v = fabsf4(x1p_v); + TEST_CHECK("20040915032654EJL", allequal_float4( res_v, x1p_v ), 0); + res_v = fabsf4(x2n_v); + TEST_CHECK("20040915032704EJL", allequal_float4( res_v, x2p_v ), 0); + res_v = fabsf4(x2p_v); + TEST_CHECK("20040915032712EJL", allequal_float4( res_v, x2p_v ), 0); + res_v = fabsf4(x3n_v); + TEST_CHECK("20040915032719EJL", allequal_float4( res_v, x3p_v ), 0); + res_v = fabsf4(x3p_v); + TEST_CHECK("20040915032729EJL", allequal_float4( res_v, x3p_v ), 0); + + TEST_START("fabsf"); + res = fabsf( x0n ); + TEST_CHECK("20040915032739EJL", res == x0p, 0); + res = fabsf( x0p ); + TEST_CHECK("20040915032747EJL", res == x0p, 0); + res = fabsf( x1n ); + TEST_CHECK("20040915032755EJL", res == x1p, 0); + res = fabsf( x1p ); + TEST_CHECK("20040915032806EJL", res == x1p, 0); + res = fabsf( x2n ); + TEST_CHECK("20040915032814EJL", res == x2p, 0); + res = fabsf( x2p ); + TEST_CHECK("20040915032826EJL", res == x2p, 0); + res = fabsf( x3n ); + TEST_CHECK("20040915032834EJL", res == x3p, 0); + res = fabsf( x3p ); + TEST_CHECK("20040915032841EJL", res == x3p, 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/fdimd2.c b/Extras/simdmathlibrary/spu/tests/fdimd2.c new file mode 100644 index 0000000..d71a48e --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/fdimd2.c @@ -0,0 +1,173 @@ +/* Test fdimd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/** + * + *@@ fdimd2 - compute positive difference. + * + *@brief + * boundary test for fdimd2. + * + *@pre + * + *@criteria + * when both of two values are denormalized, it may not work correctly. + * + *@note + * source of fdimd2.c was modified from IBM SDK1.1 math library + * + **/ + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + + +int main() +{ + TEST_SET_START("20060824151500MH","MH", "fdimd2"); + + double x0min = hide_double(1760.135); + double x0max = hide_double(19355.03); + double x0dim = hide_double(19355.03 - 1760.135); + + double x1min = hide_double(-12351.9); + double x1max = hide_double(-139.035); + double x1dim = hide_double((-139.035) - (-12351.9)); + + double x2min = hide_double(-1.0); + double x2max = hide_double(0.0); + double x2dim = hide_double(1.0); + + double x3min = hide_double(nan("")); + double x3max = hide_double(-1.0); + + double x4min = hide_double(-0.0); + double x4max = hide_double(0.0); + + double x5min = hide_double(5.0e-324); + double x5max = hide_double(1.0e-323); + double x5dim = hide_double(1.0e-323) - hide_double(5.0e-324); + + double x6min = hide_double(DBL_MAX); + double x6max = hide_double(HUGE_VAL); + + double x7min = hide_double(-HUGE_VAL); + double x7max = hide_double(19355.03); + + double x8min = hide_double(-HUGE_VAL); + double x8max = hide_double(HUGE_VAL); + + vec_double2 x0min_v = spu_splats(x0min); + vec_double2 x0max_v = spu_splats(x0max); + vec_double2 x0dim_v = spu_splats(x0dim); + + vec_double2 x1min_v = spu_splats(x1min); + vec_double2 x1max_v = spu_splats(x1max); + vec_double2 x1dim_v = spu_splats(x1dim); + + vec_double2 x2min_v = spu_splats(x2min); + vec_double2 x2max_v = spu_splats(x2max); + vec_double2 x2dim_v = spu_splats(x2dim); + + vec_double2 x3min_v = spu_splats(x3min); + vec_double2 x3max_v = spu_splats(x3max); + + vec_double2 x4min_v = spu_splats(x4min); + vec_double2 x4max_v = spu_splats(x4max); + + vec_double2 x5min_v = spu_splats(x5min); + vec_double2 x5max_v = spu_splats(x5max); + vec_double2 x5dim_v = spu_splats(x5dim); + + vec_double2 x6min_v = spu_splats(x6min); + vec_double2 x6max_v = spu_splats(x6max); + + vec_double2 x7min_v = spu_splats(x7min); + vec_double2 x7max_v = spu_splats(x7max); + + vec_double2 x8min_v = spu_splats(x8min); + vec_double2 x8max_v = spu_splats(x8max); + + vec_double2 x9minmax_v = (vec_double2){x0min, x1max}; + vec_double2 x9maxmin_v = (vec_double2){x0max, x1min}; + vec_double2 x9dim1_v = (vec_double2){x0dim, 0.0}; + vec_double2 x9dim2_v = (vec_double2){0.0, x1dim}; + + vec_double2 res_v; + + TEST_START("fdimd2"); + res_v = fdimd2(x0min_v, x0max_v); + TEST_CHECK("20060824151501MH", allposzero_double2( res_v ), 0); + res_v = fdimd2(x0max_v, x0min_v); + TEST_CHECK("20060824151502MH", allequal_double2( res_v, x0dim_v ), 0); + res_v = fdimd2(x1min_v, x1max_v); + TEST_CHECK("20060824151503MH", allposzero_double2( res_v ), 0); + res_v = fdimd2(x1max_v, x1min_v); + TEST_CHECK("20060824151504MH", allequal_double2( res_v, x1dim_v ), 0); + res_v = fdimd2(x2min_v, x2max_v); + TEST_CHECK("20060824151505MH", allposzero_double2( res_v ), 0); + res_v = fdimd2(x2max_v, x2min_v); + TEST_CHECK("20060824151506MH", allequal_double2( res_v, x2dim_v ), 0); + res_v = fdimd2(x3min_v, x3max_v); + TEST_CHECK("20060824151507MH", allnan_double2( res_v ), 0); + res_v = fdimd2(x3max_v, x3min_v); + TEST_CHECK("20060824151508MH", allnan_double2( res_v ), 0); + res_v = fdimd2(x4min_v, x4max_v); + TEST_CHECK("20060824151509MH", allposzero_double2( res_v ), 0); + res_v = fdimd2(x4max_v, x4min_v); + TEST_CHECK("20060824151510MH", allposzero_double2( res_v ), 0); + res_v = fdimd2(x5min_v, x5max_v); + TEST_CHECK("20060824151511MH", allposzero_double2( res_v ), 0); + res_v = fdimd2(x5max_v, x5min_v); + TEST_CHECK("20060824151512MH", allequal_double2( res_v, x5dim_v ), 0); + res_v = fdimd2(x6min_v, x6max_v); + TEST_CHECK("20060824151513MH", allposzero_double2( res_v ), 0); + res_v = fdimd2(x6max_v, x6min_v); + TEST_CHECK("20060824151514MH", allposinf_double2( res_v ), 0); + res_v = fdimd2(x7min_v, x7max_v); + TEST_CHECK("20060824151515MH", allposzero_double2( res_v ), 0); + res_v = fdimd2(x7max_v, x7min_v); + TEST_CHECK("20060824151516MH", allposinf_double2( res_v ), 0); + res_v = fdimd2(x8min_v, x8max_v); + TEST_CHECK("20060824151517MH", allposzero_double2( res_v ), 0); + res_v = fdimd2(x8max_v, x8min_v); + TEST_CHECK("20060824151518MH", allposinf_double2( res_v ), 0); + res_v = fdimd2(x9minmax_v, x9maxmin_v); + TEST_CHECK("20060824151519MH", allequal_double2( res_v, x9dim2_v ), 0); + res_v = fdimd2(x9maxmin_v, x9minmax_v); + TEST_CHECK("20060824151520MH", allequal_double2( res_v, x9dim1_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/floord2.c b/Extras/simdmathlibrary/spu/tests/floord2.c new file mode 100644 index 0000000..01ad0e1 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/floord2.c @@ -0,0 +1,157 @@ +/* Test roundd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/** + * + *@@ floord2 - for each of two doule slots, + * round up to smallest integer not more than the value. + * + *@brief + * boundary test for floord2. + * + * + *@pre + * + *@criteria + * Run this program and check no error will be occurred. + * + *@note + * + * + **/ +#include +#include +#include +//#include +#include + +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + + +typedef union { + struct { + double xxx[2]; + double ans[2]; + } dbl; + struct { + unsigned long long xxx[2]; + unsigned long long ans[2]; + } ull; +} TestVec_Roundd2; + +int main() +{ + TestVec_Roundd2 test_a[] = { + { + ull:{ + // 0 -> 0 , -0 -> -0 + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL} + } + },{ + ull:{ + // -Inf -> -Inf , Inf -> Inf + {0xFFF0000000000000ULL,0x7FF0000000000000ULL}, + {0xFFF0000000000000ULL,0x7FF0000000000000ULL} + } + },{ + ull:{ + // MAX -> MAX , MIN -> MIN + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL} + } + },{ + ull:{ + // +Denormalize -> 0, -Denormalize -> -1.0 + {0x0000000000000001ULL,0x8000000000000010ULL}, + {0x0000000000000000ULL,0xbff0000000000000ULL} + } + },{ + ull:{ + // +Denormalize -> 0, -Denormalize -> -1.0 + {0x000FFFFFFFFFFFFFULL,0x800FFFFFFFFFFFFFULL}, + {0x0000000000000000ULL,0xbff0000000000000ULL} + } + },{ + ull:{ + // border + {0x4320000000000001ULL,0xC320000000000001ULL}, + {0x4320000000000000ULL,0xC320000000000002ULL} + } + },{ + dbl:{ + {1.0, -1.0}, + {1.0, -1.0} + } + },{ + dbl:{ + {0.5, -0.5}, + {0.0, -1.0} + } + },{ + dbl:{ + {-2.75, 3.25}, + {-3.0, 3.0} + } + },{ + ull:{ + // Nan + {0xFFF0000000000001ULL,0x7FF0000000000001ULL}, + {0xFFF0000000000001ULL,0x7FF0000000000001ULL} + } + },{ + ull:{ + {0ULL,0ULL}, + {0ULL,0ULL} + } + } + }; + int ii, test_ctr = 1; + char msg[80]; + vec_double2 res_v; + //vec_double2 input; + + TEST_SET_START("96743652190000NM","FLR", "floord2"); + + TEST_START("floord2"); + + for (ii=0; ; ii++) { + if ( (test_a[ii].ull.xxx[0] == 0) && (test_a[ii].ull.xxx[1] == 0) ) break; + //input = *((vec_double2 *)&test_a[ii].dbl.xxx[0]); + res_v = floord2 (*((vec_double2 *)&test_a[ii].dbl.xxx[0]) ); + sprintf(msg,"9674365219%04dFLR", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, (vec_llong2)*((vec_double2 *)&test_a[ii].dbl.ans[0])), 0); + } + + TEST_SET_DONE(); + + TEST_EXIT(); + +} diff --git a/Extras/simdmathlibrary/spu/tests/floorf4.c b/Extras/simdmathlibrary/spu/tests/floorf4.c new file mode 100644 index 0000000..fa514ed --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/floorf4.c @@ -0,0 +1,109 @@ +/* Test floorf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + + +int main() +{ + TEST_SET_START("20040916145017EJL","EJL", "floorf"); + + unsigned int i3 = 0x4affffff; // 2^23 - 0.5, largest truncatable value. + unsigned int i3i = 0x4afffffe; + unsigned int i4 = 0x4b000000; // 2^23, no fractional part. + unsigned int i5 = 0xcf000001; // -2^31, one more large, and negative, value. + + float x0 = hide_float(0.91825f); + float x0i = hide_float(0.0f); + float x1 = hide_float(-0.12958f); + float x1i = hide_float(-1.0f); + float x2 = hide_float(-79615.1875f); + float x2i = hide_float(-79616.0f); + float x3 = hide_float(make_float(i3)); + float x3i = hide_float(make_float(i3i)); + float x4 = hide_float(make_float(i4)); + float x4i = hide_float(make_float(i4)); + float x5 = hide_float(make_float(i5)); + float x5i = hide_float(make_float(i5)); + + vec_float4 x0_v = spu_splats(x0); + vec_float4 x0i_v = spu_splats(x0i); + vec_float4 x1_v = spu_splats(x1); + vec_float4 x1i_v = spu_splats(x1i); + vec_float4 x2_v = spu_splats(x2); + vec_float4 x2i_v = spu_splats(x2i); + vec_float4 x3_v = spu_splats(x3); + vec_float4 x3i_v = spu_splats(x3i); + vec_float4 x4_v = spu_splats(x4); + vec_float4 x4i_v = spu_splats(x4i); + vec_float4 x5_v = spu_splats(x5); + vec_float4 x5i_v = spu_splats(x5i); + + float res; + vec_float4 res_v; + + TEST_START("floorf4"); + res_v = floorf4(x0_v); + TEST_CHECK("20040916145022EJL", allequal_float4( res_v, x0i_v ), 0); + res_v = floorf4(x1_v); + TEST_CHECK("20040916145024EJL", allequal_float4( res_v, x1i_v ), 0); + res_v = floorf4(x2_v); + TEST_CHECK("20040916145027EJL", allequal_float4( res_v, x2i_v ), 0); + res_v = floorf4(x3_v); + TEST_CHECK("20040916145029EJL", allequal_float4( res_v, x3i_v ), 0); + res_v = floorf4(x4_v); + TEST_CHECK("20040916145032EJL", allequal_float4( res_v, x4i_v ), 0); + res_v = floorf4(x5_v); + TEST_CHECK("20040916145034EJL", allequal_float4( res_v, x5i_v ), 0); + + TEST_START("floorf"); + res = floorf(x0); + TEST_CHECK("20040916155814EJL", res == x0i, 0); + res = floorf(x1); + TEST_CHECK("20040916155818EJL", res == x1i, 0); + res = floorf(x2); + TEST_CHECK("20040916155822EJL", res == x2i, 0); + res = floorf(x3); + TEST_CHECK("20040916155825EJL", res == x3i, 0); + res = floorf(x4); + TEST_CHECK("20040916155827EJL", res == x4i, 0); + res = floorf(x5); + TEST_CHECK("20040916155830EJL", res == x5i, 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/fmad2.c b/Extras/simdmathlibrary/spu/tests/fmad2.c new file mode 100644 index 0000000..2c3ea6a --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/fmad2.c @@ -0,0 +1,146 @@ +/* Test fmad2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ + +/** + * + *@@ fmad2 - multiply and add (double). + * + *@brief + * boundary test for fmad2. + * + *@pre + * + *@criteria + * if input parameters are denorm, it may not work correctly. + * + *@note + * + **/ + + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060828114000MH","MH", "fmad2"); + +// double denorm_min = hide_double(make_double(0x0000000000000001ull)); + double denorm_max = hide_double(make_double(0x000fffffffffffffull)); +// double norm_min = hide_double(make_double(0x0010000000000000ull)); + double norm_max = hide_double(make_double(0x7fefffffffffffffull)); + + double x0 = hide_double(1760.135); + double y0 = hide_double(19355.03); + double z0 = hide_double(-12351.9); + double a0 = hide_double(34055113.82905); + + double x1 = hide_double(-139.035); + double y1 = hide_double(0.0); + double z1 = hide_double(-1.0); + + double x2 = hide_double(nan("")); + double y2 = hide_double(-1.0); + double z2 = hide_double(-0.0); + + double x3 = hide_double(1.0); + double y3 = hide_double(HUGE_VAL); + double z3 = hide_double(-1.0); + + double x4 = norm_max; + double y4 = norm_max; + double z4 = hide_double(0.0); + + double x5 = hide_double(100.0); + double y5 = denorm_max; + double z5 = hide_double(0.0); + double a5 = hide_double(make_double(0x0078fffffffffffeull)); + + vec_double2 x0_v = spu_splats(x0); + vec_double2 y0_v = spu_splats(y0); + vec_double2 z0_v = spu_splats(z0); + vec_double2 x1_v = spu_splats(x1); + vec_double2 y1_v = spu_splats(y1); + vec_double2 z1_v = spu_splats(z1); + vec_double2 x2_v = spu_splats(x2); + vec_double2 y2_v = spu_splats(y2); + vec_double2 z2_v = spu_splats(z2); + vec_double2 x3_v = spu_splats(x3); + vec_double2 y3_v = spu_splats(y3); + vec_double2 z3_v = spu_splats(z3); + vec_double2 x4_v = spu_splats(x4); + vec_double2 y4_v = spu_splats(y4); + vec_double2 z4_v = spu_splats(z4); + vec_double2 x5_v = spu_splats(x5); + vec_double2 y5_v = spu_splats(y5); + vec_double2 z5_v = spu_splats(z5); + + vec_double2 a0_v = spu_splats(a0); + vec_double2 a1_v = spu_splats(z1); + vec_double2 a5_v = spu_splats(a5); + + vec_double2 res_v; + + TEST_START("fmad2"); + res_v = fmad2(x0_v, y0_v, z0_v); + TEST_CHECK("20060828114001MH", allequal_ulps_double2( res_v, a0_v, 1 ), 0); + res_v = fmad2(y0_v, x0_v, z0_v); + TEST_CHECK("20060828114002MH", allequal_ulps_double2( res_v, a0_v, 1 ), 0); + res_v = fmad2(x1_v, y1_v, z1_v); + TEST_CHECK("20060828114003MH", allequal_ulps_double2( res_v, a1_v, 1 ), 0); + res_v = fmad2(y1_v, x1_v, z1_v); + TEST_CHECK("20060828114004MH", allequal_ulps_double2( res_v, a1_v, 1 ), 0); + res_v = fmad2(x2_v, y2_v, z2_v); + TEST_CHECK("20060828114005MH", allnan_double2( res_v ), 0); + res_v = fmad2(y2_v, x2_v, z2_v); + TEST_CHECK("20060828114006MH", allnan_double2( res_v ), 0); + res_v = fmad2(x3_v, y3_v, z3_v); + TEST_CHECK("20060828114007MH", allposinf_double2( res_v ), 0); + res_v = fmad2(y3_v, x3_v, z3_v); + TEST_CHECK("20060828114008MH", allposinf_double2( res_v ), 0); + res_v = fmad2(x4_v, y4_v, z4_v); + TEST_CHECK("20060828114009MH", allposinf_double2( res_v ), 0); + res_v = fmad2(y4_v, x4_v, z4_v); + TEST_CHECK("20060828114010MH", allposinf_double2( res_v ), 0); + res_v = fmad2(x5_v, y5_v, z5_v); + TEST_CHECK("20060828114011MH", allequal_ulps_double2( res_v, a5_v, 1 ), 0); + res_v = fmad2(y5_v, x5_v, z5_v); + TEST_CHECK("20060828114012MH", allequal_ulps_double2( res_v, a5_v, 1 ), 0); +//printf("res:%.10le, a5:%.10le\n", spu_extract(res_v, 0), spu_extract(a5_v, 0)); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/fmind2_fmaxd2.c b/Extras/simdmathlibrary/spu/tests/fmind2_fmaxd2.c new file mode 100644 index 0000000..bfaed20 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/fmind2_fmaxd2.c @@ -0,0 +1,225 @@ +/* Test fmind2 and fmaxd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ + +/** + * + *@@ fmind2_fmaxd2 - find minimum/maximum value. + * + *@brief + * boundary test for fmind2/fmaxd2. + * + *@pre + * + *@criteria + * + *@note + * + **/ + + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + + +int main() +{ + TEST_SET_START("20060824103000MH","MH", "fmind2_fmaxd2"); + + double denorm_min = hide_double(make_double(0x0000000000000001ull)); + double denorm_max = hide_double(make_double(0x000fffffffffffffull)); + double norm_min = hide_double(make_double(0x0010000000000000ull)); + double norm_max = hide_double(make_double(0x7fefffffffffffffull)); + + double x0min = hide_double(1760.135); + double x0max = hide_double(19355.03); + + double x1min = hide_double(-12351.9); + double x1max = hide_double(-139.035); + + double x2min = hide_double(-1.0); + double x2max = hide_double(0.0); + + double x3min = hide_double(nan("")); + double x3max = hide_double(-1.0); + + double x4min = hide_double(-0.0); + double x4max = hide_double(0.0); + + double x5min = denorm_min; + double x5max = hide_double(1.0e-323); + + double x6min = norm_max; + double x6max = hide_double(HUGE_VAL); + + double x7min = hide_double(-HUGE_VAL); + double x7max = hide_double(19355.03); + + double x8min = hide_double(-HUGE_VAL); + double x8max = hide_double(HUGE_VAL); + + double x9min = denorm_max; + double x9max = norm_min; + + vec_double2 x0min_v = spu_splats(x0min); + vec_double2 x0max_v = spu_splats(x0max); + + vec_double2 x1min_v = spu_splats(x1min); + vec_double2 x1max_v = spu_splats(x1max); + + vec_double2 x2min_v = spu_splats(x2min); + vec_double2 x2max_v = spu_splats(x2max); + + vec_double2 x3min_v = spu_splats(x3min); + vec_double2 x3max_v = spu_splats(x3max); + + vec_double2 x4min_v = spu_splats(x4min); + vec_double2 x4max_v = spu_splats(x4max); + + vec_double2 x5min_v = spu_splats(x5min); + vec_double2 x5max_v = spu_splats(x5max); + + vec_double2 x6min_v = spu_splats(x6min); + vec_double2 x6max_v = spu_splats(x6max); + + vec_double2 x7min_v = spu_splats(x7min); + vec_double2 x7max_v = spu_splats(x7max); + + vec_double2 x8min_v = spu_splats(x8min); + vec_double2 x8max_v = spu_splats(x8max); + + vec_double2 x9min_v = spu_splats(x9min); + vec_double2 x9max_v = spu_splats(x9max); + + vec_double2 x51min_v = (vec_double2){x5min, x1min}; + vec_double2 x51max_v = (vec_double2){x5max, x1max}; + + vec_double2 res_v; + + TEST_START("fmind2"); + res_v = fmind2(x0min_v, x0max_v); + TEST_CHECK("20060824103001MH", allequal_double2( res_v, x0min_v ), 0); + res_v = fmind2(x0max_v, x0min_v); + TEST_CHECK("20060824103002MH", allequal_double2( res_v, x0min_v ), 0); + res_v = fmind2(x1min_v, x1max_v); + TEST_CHECK("20060824103003MH", allequal_double2( res_v, x1min_v ), 0); + res_v = fmind2(x1max_v, x1min_v); + TEST_CHECK("20060824103004MH", allequal_double2( res_v, x1min_v ), 0); + res_v = fmind2(x2min_v, x2max_v); + TEST_CHECK("20060824103005MH", allequal_double2( res_v, x2min_v ), 0); + res_v = fmind2(x2max_v, x2min_v); + TEST_CHECK("20060824103006MH", allequal_double2( res_v, x2min_v ), 0); + res_v = fmind2(x3min_v, x3max_v); + TEST_CHECK("20060824103007MH", allequal_double2( res_v, x3max_v ), 0); + res_v = fmind2(x3max_v, x3min_v); + TEST_CHECK("20060824103008MH", allequal_double2( res_v, x3max_v ), 0); + res_v = fmind2(x4min_v, x4max_v); + TEST_CHECK("20060824103009MH", allequal_double2( res_v, x4min_v ), 0); + res_v = fmind2(x4max_v, x4min_v); + TEST_CHECK("20060824103010MH", allequal_double2( res_v, x4min_v ), 0); + res_v = fmind2(x5min_v, x5max_v); + TEST_CHECK("20060824103011MH", allequal_double2( res_v, x5min_v ), 0); + res_v = fmind2(x5max_v, x5min_v); + TEST_CHECK("20060824103012MH", allequal_double2( res_v, x5min_v ), 0); + res_v = fmind2(x6min_v, x6max_v); + TEST_CHECK("20060824103013MH", allequal_double2( res_v, x6min_v ), 0); + res_v = fmind2(x6max_v, x6min_v); + TEST_CHECK("20060824103014MH", allequal_double2( res_v, x6min_v ), 0); + res_v = fmind2(x7min_v, x7max_v); + TEST_CHECK("20060824103015MH", allequal_double2( res_v, x7min_v ), 0); + res_v = fmind2(x7max_v, x7min_v); + TEST_CHECK("20060824103016MH", allequal_double2( res_v, x7min_v ), 0); + res_v = fmind2(x8min_v, x8max_v); + TEST_CHECK("20060824103017MH", allequal_double2( res_v, x8min_v ), 0); + res_v = fmind2(x8max_v, x8min_v); + TEST_CHECK("20060824103018MH", allequal_double2( res_v, x8min_v ), 0); + res_v = fmind2(x9min_v, x9max_v); + TEST_CHECK("20060824103019MH", allequal_double2( res_v, x9min_v ), 0); + res_v = fmind2(x9max_v, x9min_v); + TEST_CHECK("20060824103020MH", allequal_double2( res_v, x9min_v ), 0); + res_v = fmind2(x51min_v, x51max_v); + TEST_CHECK("20060824103021MH", allequal_double2( res_v, x51min_v ), 0); + res_v = fmind2(x51max_v, x51min_v); + TEST_CHECK("20060824103022MH", allequal_double2( res_v, x51min_v ), 0); + + TEST_START("fmaxd2"); + res_v = fmaxd2(x0min_v, x0max_v); + TEST_CHECK("20060824103101MH", allequal_double2( res_v, x0max_v ), 0); + res_v = fmaxd2(x0max_v, x0min_v); + TEST_CHECK("20060824103102MH", allequal_double2( res_v, x0max_v ), 0); + res_v = fmaxd2(x1min_v, x1max_v); + TEST_CHECK("20060824103103MH", allequal_double2( res_v, x1max_v ), 0); + res_v = fmaxd2(x1max_v, x1min_v); + TEST_CHECK("20060824103104MH", allequal_double2( res_v, x1max_v ), 0); + res_v = fmaxd2(x2min_v, x2max_v); + TEST_CHECK("20060824103105MH", allequal_double2( res_v, x2max_v ), 0); + res_v = fmaxd2(x2max_v, x2min_v); + TEST_CHECK("20060824103106MH", allequal_double2( res_v, x2max_v ), 0); + res_v = fmaxd2(x3min_v, x3max_v); + TEST_CHECK("20060824103107MH", allequal_double2( res_v, x3max_v ), 0); + res_v = fmaxd2(x3max_v, x3min_v); + TEST_CHECK("20060824103108MH", allequal_double2( res_v, x3max_v ), 0); + res_v = fmaxd2(x4min_v, x4max_v); + TEST_CHECK("20060824103109MH", allequal_double2( res_v, x4max_v ), 0); + res_v = fmaxd2(x4max_v, x4min_v); + TEST_CHECK("20060824103110MH", allequal_double2( res_v, x4max_v ), 0); + res_v = fmaxd2(x5min_v, x5max_v); + TEST_CHECK("20060824103111MH", allequal_double2( res_v, x5max_v ), 0); + res_v = fmaxd2(x5max_v, x5min_v); + TEST_CHECK("20060824103112MH", allequal_double2( res_v, x5max_v ), 0); + res_v = fmaxd2(x6min_v, x6max_v); + TEST_CHECK("20060824103113MH", allequal_double2( res_v, x6max_v ), 0); + res_v = fmaxd2(x6max_v, x6min_v); + TEST_CHECK("20060824103114MH", allequal_double2( res_v, x6max_v ), 0); + res_v = fmaxd2(x7min_v, x7max_v); + TEST_CHECK("20060824103115MH", allequal_double2( res_v, x7max_v ), 0); + res_v = fmaxd2(x7max_v, x7min_v); + TEST_CHECK("20060824103116MH", allequal_double2( res_v, x7max_v ), 0); + res_v = fmaxd2(x8min_v, x8max_v); + TEST_CHECK("20060824103117MH", allequal_double2( res_v, x8max_v ), 0); + res_v = fmaxd2(x8max_v, x8min_v); + TEST_CHECK("20060824103118MH", allequal_double2( res_v, x8max_v ), 0); + res_v = fmaxd2(x9min_v, x9max_v); + TEST_CHECK("20060824103119MH", allequal_double2( res_v, x9max_v ), 0); + res_v = fmaxd2(x9max_v, x9min_v); + TEST_CHECK("20060824103120MH", allequal_double2( res_v, x9max_v ), 0); + res_v = fmaxd2(x51min_v, x51max_v); + TEST_CHECK("20060824103121MH", allequal_double2( res_v, x51max_v ), 0); + res_v = fmaxd2(x51max_v, x51min_v); + TEST_CHECK("20060824103122MH", allequal_double2( res_v, x51max_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/fminf4_fmaxf4.c b/Extras/simdmathlibrary/spu/tests/fminf4_fmaxf4.c new file mode 100644 index 0000000..dd0bcd4 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/fminf4_fmaxf4.c @@ -0,0 +1,124 @@ +/* Test fminf4 and fmaxf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + + +int main() +{ + TEST_SET_START("20040928184342EJL","EJL", "fminf4_fmaxf4"); + + float x0min = hide_float(1760.135f); + float x0max = hide_float(19355.03f); + + float x1min = hide_float(-12351.9f); + float x1max = hide_float(-139.035f); + + float x2min = hide_float(-1.0); + float x2max = hide_float(0.0); + + vec_float4 x0min_v = spu_splats(x0min); + vec_float4 x0max_v = spu_splats(x0max); + + vec_float4 x1min_v = spu_splats(x1min); + vec_float4 x1max_v = spu_splats(x1max); + + vec_float4 x2min_v = spu_splats(x2min); + vec_float4 x2max_v = spu_splats(x2max); + + float res; + vec_float4 res_v; + + TEST_START("fminf4"); + res_v = fminf4(x0min_v, x0max_v); + TEST_CHECK("20040928184345EJL", allequal_float4( res_v, x0min_v ), 0); + res_v = fminf4(x0max_v, x0min_v); + TEST_CHECK("20040928184349EJL", allequal_float4( res_v, x0min_v ), 0); + res_v = fminf4(x1min_v, x1max_v); + TEST_CHECK("20040928184351EJL", allequal_float4( res_v, x1min_v ), 0); + res_v = fminf4(x1max_v, x1min_v); + TEST_CHECK("20040928184353EJL", allequal_float4( res_v, x1min_v ), 0); + res_v = fminf4(x2min_v, x2max_v); + TEST_CHECK("20040928184354EJL", allequal_float4( res_v, x2min_v ), 0); + res_v = fminf4(x2max_v, x2min_v); + TEST_CHECK("20040928184356EJL", allequal_float4( res_v, x2min_v ), 0); + + TEST_START("fminf"); + res = fminf(x0min, x0max); + TEST_CHECK("20040928184358EJL", res == x0min, 0); + res = fminf(x0max, x0min); + TEST_CHECK("20040928184400EJL", res == x0min, 0); + res = fminf(x1min, x1max); + TEST_CHECK("20040928184401EJL", res == x1min, 0); + res = fminf(x1max, x1min); + TEST_CHECK("20040928184403EJL", res == x1min, 0); + res = fminf(x2min, x2max); + TEST_CHECK("20040928184405EJL", res == x2min, 0); + res = fminf(x2max, x2min); + TEST_CHECK("20040928184406EJL", res == x2min, 0); + + TEST_START("fmaxf4"); + res_v = fmaxf4(x0min_v, x0max_v); + TEST_CHECK("20040928184411EJL", allequal_float4( res_v, x0max_v ), 0); + res_v = fmaxf4(x0max_v, x0min_v); + TEST_CHECK("20040928184413EJL", allequal_float4( res_v, x0max_v ), 0); + res_v = fmaxf4(x1min_v, x1max_v); + TEST_CHECK("20040928184415EJL", allequal_float4( res_v, x1max_v ), 0); + res_v = fmaxf4(x1max_v, x1min_v); + TEST_CHECK("20040928184416EJL", allequal_float4( res_v, x1max_v ), 0); + res_v = fmaxf4(x2min_v, x2max_v); + TEST_CHECK("20040928184417EJL", allequal_float4( res_v, x2max_v ), 0); + res_v = fmaxf4(x2max_v, x2min_v); + TEST_CHECK("20040928184419EJL", allequal_float4( res_v, x2max_v ), 0); + + TEST_START("fmaxf"); + res = fmaxf(x0min, x0max); + TEST_CHECK("20040928184420EJL", res == x0max, 0); + res = fmaxf(x0max, x0min); + TEST_CHECK("20040928184422EJL", res == x0max, 0); + res = fmaxf(x1min, x1max); + TEST_CHECK("20040928184423EJL", res == x1max, 0); + res = fmaxf(x1max, x1min); + TEST_CHECK("20040928184424EJL", res == x1max, 0); + res = fmaxf(x2min, x2max); + TEST_CHECK("20040928184426EJL", res == x2max, 0); + res = fmaxf(x2max, x2min); + TEST_CHECK("20040928184428EJL", res == x2max, 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/fmodd2.c b/Extras/simdmathlibrary/spu/tests/fmodd2.c new file mode 100644 index 0000000..6e1b842 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/fmodd2.c @@ -0,0 +1,364 @@ +/* Test roundd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/** + * + *@@ fmodd2 + + * + *@brief + * boundary test for fmodd2. + * + * + *@pre + * + *@criteria + * Run this program and check no error will be occurred. + * + *@note + * + * + **/ + +#include +#include +#include +//#include +#include + +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + + +typedef union { + struct { + double xxx[2]; + double yyy[2]; + double rrr[2]; + } dbl; + struct { + unsigned long long xxx[2]; + unsigned long long yyy[2]; + unsigned long long rrr[2]; + } ull; +} TestVec_Roundd2; + +int main() +{ + TestVec_Roundd2 test_a[] = { +{ +ull:{ +// 1.00...11 / 1.0...0 -> 0.00...11, 1.00...1 /1.0...0 -> 0.0...1 +{0x3ff0000000000003ULL,0x3ff0000000000001ULL}, +{0x3fe0000000000000ULL,0x3fe0000000000000ULL}, +{0x3cc8000000000000ULL,0x3cb0000000000000ULL} +} +},{ +ull:{ +// 1.00...1111 / 0.10...0 -> 0.00...11, 1.00...1 /0.10...0 -> 0.0...1 +{0x3ff000000000000fULL,0x3ff0000000000001ULL}, +{0x3fe0000000000000ULL,0x3fe0000000000000ULL}, +{0x3cee000000000000ULL,0x3cb0000000000000ULL} +} +}, + +{ +ull:{ +{0x7fffffffeffffffeULL, 0x7fffffffeffffffeULL},/*(nan nan)*/ +{0x0000000000000000ULL, 0x7aa0000000000000ULL},/*(0.000000 4646927838993072071243945306718439250410188130185607684549287060362314553626263667328650982800488595593121011844353040782670578892327830336846345565944983205571783876398312106070895030732180427719497486819848241268961714708993375275490934188589556509412640954544199727574266715045888.000000)*/ +{0x7fffffffeffffffeULL, 0x7fffffffeffffffeULL}/*(nan, nan)*/ +} +}, +{ +ull:{ +{0x7fffffffeffffffeULL, 0x7fffffffeffffffeULL},/*(nan nan)*/ +{0x7ff0000000000000ULL, 0x0000000000000001ULL},/*(inf 0.000000)*/ +{0x7fffffffeffffffeULL, 0x7fffffffeffffffeULL}/*(nan, nan)*/ +} +}, +{ +ull:{ +{0x7fffffffeffffffeULL, 0x7fffffffeffffffeULL},/*(nan nan)*/ +{0xfff0000000000000ULL, 0x7fffffffeffffffeULL},/*(-inf nan)*/ +{0x7fffffffeffffffeULL, 0x7fffffffeffffffeULL}/*(nan, nan)*/ +} +}, +{ +ull:{ +{0x0000000000000000ULL, 0x7aa0000000000000ULL},/*(0.000000 4646927838993072071243945306718439250410188130185607684549287060362314553626263667328650982800488595593121011844353040782670578892327830336846345565944983205571783876398312106070895030732180427719497486819848241268961714708993375275490934188589556509412640954544199727574266715045888.000000)*/ +{0x7fffffffeffffffeULL, 0x7fffffffeffffffeULL},/*(nan nan)*/ +{0x7fffffffeffffffeULL, 0x7fffffffeffffffeULL}/*(nan, nan)*/ +} +}, +{ +ull:{ +{0x7ff0000000000000ULL, 0x0000000000000001ULL},/*(inf 0.000000)*/ +{0x7fffffffeffffffeULL, 0x7fffffffeffffffeULL},/*(nan nan)*/ +{0x7fffffffeffffffeULL, 0x7fffffffeffffffeULL}/*(nan, nan)*/ +} +}, +{ +ull:{ +{0xfff0000000000000ULL, 0x7fffffffeffffffeULL},/*(-inf nan)*/ +{0x7fffffffeffffffeULL, 0x7fffffffeffffffeULL},/*(nan nan)*/ +{0x7fffffffeffffffeULL, 0x7fffffffeffffffeULL}/*(nan, nan)*/ +} +}, +{ +ull:{ +{0x0000000000000000ULL, 0x7aa0000000000000ULL},/*(0.000000 4646927838993072071243945306718439250410188130185607684549287060362314553626263667328650982800488595593121011844353040782670578892327830336846345565944983205571783876398312106070895030732180427719497486819848241268961714708993375275490934188589556509412640954544199727574266715045888.000000)*/ +{0x0000000000000000ULL, 0x0000000000000000ULL},/*(0.000000 0.000000)*/ +{0x0000000000000000ULL, 0x0000000000000000ULL}/*(0.000000, 0.000000)*/ +} +}, +{ +ull:{ +{0x7ff0000000000000ULL, 0x0000000000000001ULL},/*(inf 0.000000)*/ +{0x0000000000000000ULL, 0x0000000000000000ULL},/*(0.000000 0.000000)*/ +{0x0000000000000000ULL, 0x0000000000000000ULL}/*(0.000000, 0.000000)*/ +} +}, +{ +ull:{ +{0xfff0000000000000ULL, 0x7fffffffeffffffeULL},/*(-inf nan)*/ +{0x0000000000000000ULL, 0x0000000000000000ULL},/*(0.000000 0.000000)*/ +{0x0000000000000000ULL, 0x7fffffffeffffffeULL}/*(0.000000, nan)*/ +} +}, +{ +ull:{ +{0x7ff0000000000000ULL, 0x7ff0000000000000ULL},/*(inf inf)*/ +{0x7ff0000000000000ULL, 0xfff0000000000000ULL},/*(inf -inf)*/ +{0x7ff8000000000000ULL, 0x7ff8000000000000ULL}/*(nan, nan)*/ +} +}, +{ +ull:{ +{0xfff0000000000000ULL, 0xfff0000000000000ULL},/*(-inf -inf)*/ +{0x7ff0000000000000ULL, 0xfff0000000000000ULL},/*(inf -inf)*/ +{0x7ff8000000000000ULL, 0x7ff8000000000000ULL}/*(nan, nan)*/ +} +}, +{ +ull:{ +{0x7ff0000000000000ULL, 0xfff0000000000000ULL},/*(inf -inf)*/ +{0x7aa0000000000000ULL, 0x7aa0000000000000ULL},/*(4646927838993072071243945306718439250410188130185607684549287060362314553626263667328650982800488595593121011844353040782670578892327830336846345565944983205571783876398312106070895030732180427719497486819848241268961714708993375275490934188589556509412640954544199727574266715045888.000000 4646927838993072071243945306718439250410188130185607684549287060362314553626263667328650982800488595593121011844353040782670578892327830336846345565944983205571783876398312106070895030732180427719497486819848241268961714708993375275490934188589556509412640954544199727574266715045888.000000)*/ +{0x7ff8000000000000ULL, 0x7ff8000000000000ULL}/*(nan, nan)*/ +} +}, +{ +ull:{ +{0x7ff0000000000000ULL, 0xfff0000000000000ULL},/*(inf -inf)*/ +{0x0000000000000001ULL, 0x0000000000000001ULL},/*(0.000000 0.000000)*/ +{0x7ff8000000000000ULL, 0x7ff8000000000000ULL}/*(nan, nan)*/ +} +}, +{ +ull:{ +{0x7aa0000000000000ULL, 0x0000000000000001ULL},/*(4646927838993072071243945306718439250410188130185607684549287060362314553626263667328650982800488595593121011844353040782670578892327830336846345565944983205571783876398312106070895030732180427719497486819848241268961714708993375275490934188589556509412640954544199727574266715045888.000000 0.000000)*/ +{0x7ff0000000000000ULL, 0xfff0000000000000ULL},/*(inf -inf)*/ +{0x7aa0000000000000ULL, 0x0000000000000001ULL}/*(4646927838993072071243945306718439250410188130185607684549287060362314553626263667328650982800488595593121011844353040782670578892327830336846345565944983205571783876398312106070895030732180427719497486819848241268961714708993375275490934188589556509412640954544199727574266715045888.000000, 0.000000)*/ +} +}, +{ +ull:{ +{0x0000000000000000ULL, 0x0000000000000000ULL},/*(0.000000 0.000000)*/ +{0x7ff0000000000000ULL, 0xfff0000000000000ULL},/*(inf -inf)*/ +{0x0000000000000000ULL, 0x0000000000000000ULL}/*(0.000000, 0.000000)*/ +} +}, +{ +ull:{ +{0x7fefffffffffffffULL, 0x7fefffffffffffffULL},/*(179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000)*/ +{0x7feffffffffffffeULL, 0x7feeffffffffffffULL},/*(179769313486231550856124328384506240234343437157459335924404872448581845754556114388470639943126220321960804027157371570809852884964511743044087662767600909594331927728237078876188760579532563768698654064825262115771015791463983014857704008123419459386245141723703148097529108423358883457665451722744025579520.000000 174151522439786833602873345010488654505514389466650288559122786766978114661106633662692418716441642670880455394768401421807484146614013663315566064496053950599244663907024235661361045727850388502842959666202477512028391028080020983119748774627722497113443122745251401348739825745341808746724299140883367854080.000000)*/ +{0x7ca0000000000000ULL, 0x7fa0000000000000ULL}/*(19958403095347198116563727130368385660674512604354575415025472424372118918689640657849579654926357010893424468441924952439724379883935936607391717982848314203200056729510856765175377214443629871826533567445439239933308104551208703888888552684480441575071209068757560416423584952303440099278848.000000, 5617791046444737211654078721215702292556178059194708039794690036179146118921905097897139916325235500660003558745981042426837180275450519452901482207483566386805246669527046414884444362538940441232908842252656430276192208823201965046059784704400851161354703458893321819998351435577491134526104885300757004288.000000)*/ +} +}, +{ +ull:{ +{0x0008000000000000ULL, 0x7fefffffffffffffULL},/*(0.000000 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000)*/ +{0x7ff0000000000000ULL, 0x7ff0000000000000ULL},/*(inf inf)*/ +{0x0008000000000000ULL, 0x7fefffffffffffffULL}/*(0.000000, 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000)*/ +} +}, +{ +ull:{ +{0x7fefffffffffffffULL, 0x0010000000000000ULL},/*(179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 0.000000)*/ +{0x7fdfffffffffffffULL, 0x0008000000000003ULL},/*(89884656743115785407263711865852178399035283762922498299458738401578630390014269380294779316383439085770229476757191232117160663444732091384233773351768758493024955288275641038122745045194664472037934254227566971152291618451611474082904279666061674137398913102072361584369088590459649940625202013092062429184.000000 0.000000)*/ +{0x0000000000000000ULL, 0x0007fffffffffffdULL}/*(0.000000, 0.000000)*/ +} +}, +{ +ull:{ +{0x7ff0000000000000ULL, 0x7fefffffffffffffULL},/*(inf 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000)*/ +{0x7fefffffffffffffULL, 0x0000000000000003ULL},/*(179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 0.000000)*/ +{0x7ff8000000000000ULL, 0x0000000000000002ULL}/*(nan, 0.000000)*/ +} +}, +{ +ull:{ +{0xffe0000000000000ULL, 0x7fefffffffffffffULL},/*(-89884656743115795386465259539451236680898848947115328636715040578866337902750481566354238661203768010560056939935696678829394884407208311246423715319737062188883946712432742638151109800623047059726541476042502884419075341171231440736956555270413618581675255342293149119973622969239858152417678164812112068608.000000 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000)*/ +{0x0008000000000000ULL, 0x0010000000000000ULL},/*(0.000000 0.000000)*/ +{0x8000000000000000ULL, 0x0000000000000000ULL}/*(-0.000000, 0.000000)*/ +} +}, +{ +ull:{ +{0x4004000000000000ULL, 0x403d000000000000ULL},/*(2.500000 29.000000)*/ +{0x3ff8000000000000ULL, 0x4008000000000000ULL},/*(1.500000 3.000000)*/ +{0x3ff0000000000000ULL, 0x4000000000000000ULL}/*(1.000000, 2.000000)*/ +} +}, +{ +ull:{ +{0x8010000000000002ULL, 0x9000000000000000ULL},/*(-0.000000 -0.000000)*/ +{0x8000000000000000ULL, 0x0000000000000000ULL},/*(-0.000000 0.000000)*/ +{0x0000000000000000ULL, 0x0000000000000000ULL}/*(0.000000, 0.000000)*/ +} +}, +{ +ull:{ +{0xffefffffffffffffULL, 0x7fefffffffffffffULL},/*(-179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000)*/ +{0xffefffffffffffffULL, 0x7fefffffffffffffULL},/*(-179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000)*/ +{0x8000000000000000ULL, 0x0000000000000000ULL}/*(-0.000000, 0.000000)*/ +} +}, +{ +ull:{ +{0xfff0000000000000ULL, 0x7ff0000000000000ULL},/*(-inf inf)*/ +{0xfff0000000000000ULL, 0x7ff0000000000000ULL},/*(-inf inf)*/ +{0x7ff8000000000000ULL, 0x7ff8000000000000ULL}/*(nan, nan)*/ +} +}, +{ +ull:{ +{0x800ffffffffffff3ULL, 0x09d0000000000006ULL},/*(-0.000000 0.000000)*/ +{0x8000000000000005ULL, 0x8010000000000005ULL},/*(-0.000000 -0.000000)*/ +{0x8000000000000003ULL, 0x000fffffffffff88ULL}/*(-0.000000, 0.000000)*/ +} +}, +{ +ull:{ +{0x1000000000000000ULL, 0x0000000000000001ULL},/*(0.000000 0.000000)*/ +{0x0010000000000005ULL, 0x8000000000000001ULL},/*(0.000000 -0.000000)*/ +{0x00058000000001eaULL, 0x0000000000000000ULL}/*(0.000000, 0.000000)*/ +} +}, +{ +ull:{ +{0x0010000000000002ULL, 0x1000000000000000ULL},/*(0.000000 0.000000)*/ +{0x800000000000000bULL, 0x0010000000000007ULL},/*(-0.000000 0.000000)*/ +{0x0000000000000006ULL, 0x000c800000000e62ULL}/*(0.000000, 0.000000)*/ +} +}, +{ +ull:{ +{0x0000000000000002ULL, 0x0000000000000003ULL},/*(0.000000 0.000000)*/ +{0x0000000000000003ULL, 0x0000000000000002ULL},/*(0.000000 0.000000)*/ +{0x0000000000000002ULL, 0x0000000000000001ULL}/*(0.000000, 0.000000)*/ +} +}, +{ +ull:{ +{0x806ffffffffffff3ULL, 0x0010000000000000ULL},/*(-0.000000 0.000000)*/ +{0x8000000000000005ULL, 0x0000000000000009ULL},/*(-0.000000 0.000000)*/ +{0x8000000000000003ULL, 0x0000000000000007ULL}/*(-0.000000, 0.000000)*/ +} +}, +{ +ull:{ +{0x0000000000000000ULL, 0x8000000000000000ULL},/*(0.000000 -0.000000)*/ +{0x800ffffffffffff1ULL, 0x0000000000000003ULL},/*(-0.000000 0.000000)*/ +{0x0000000000000000ULL, 0x8000000000000000ULL}/*(0.000000, -0.000000)*/ +} +}, +{ +ull:{ +{0x1000000000000000ULL, 0x8000000000000000ULL},/*(0.000000 -0.000000)*/ +{0x0010000000000005ULL, 0x0000000000000001ULL},/*(0.000000 0.000000)*/ +{0x00058000000001eaULL, 0x8000000000000000ULL}/*(0.000000, -0.000000)*/ +} +}, +{ +ull:{ +{0x0fbfffffffffffffULL, 0x0f30000000000000ULL},/*(0.000000 0.000000)*/ +{0x000ffffffffffff1ULL, 0x0000000000000003ULL},/*(0.000000 0.000000)*/ +{0x000b7400000053f7ULL, 0x0000000000000001ULL}/*(0.000000, 0.000000)*/ +} +}, +{ +ull:{ +{0x0000000000000003ULL, 0x0000000000000003ULL},/*(0.000000 0.000000)*/ +{0x0000000000000006ULL, 0x8000000000000006ULL},/*(0.000000 -0.000000)*/ +{0x0000000000000003ULL, 0x0000000000000003ULL}/*(0.000000, 0.000000)*/ +} +}, +{ +ull:{ +{0x0020000000000001ULL, 0x8020000000000001ULL},/*(0.000000 -0.000000)*/ +{0x8010000000000002ULL, 0x0010000000000002ULL},/*(-0.000000 0.000000)*/ +{0x0010000000000000ULL, 0x8010000000000000ULL}/*(0.000000, -0.000000)*/ +} +}, + + + { + ull:{ + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL} + } + } + }; + int ii, test_ctr = 1; + char msg[80]; + vec_double2 res_v; + //vec_double2 input; + + TEST_SET_START("96743652190000NM","FLR", "floord2"); + + TEST_START("floord2"); + + for (ii=0; ; ii++) { + if ( (test_a[ii].ull.xxx[0] == 0) + && (test_a[ii].ull.xxx[1] == 0) + && (test_a[ii].ull.xxx[2] == 0) ) break; + + //input = *((vec_double2 *)&test_a[ii].dbl.xxx[0]); + res_v = fmodd2 (*((vec_double2 *)&test_a[ii].dbl.xxx[0]), + *((vec_double2 *)&test_a[ii].dbl.yyy[0]) ); + sprintf(msg,"9674365219%04dFLR", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, (vec_llong2)*((vec_double2 *)&test_a[ii].dbl.rrr[0])), 0); + } + + TEST_SET_DONE(); + + TEST_EXIT(); + +} diff --git a/Extras/simdmathlibrary/spu/tests/fmodf4.c b/Extras/simdmathlibrary/spu/tests/fmodf4.c new file mode 100644 index 0000000..48766f4 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/fmodf4.c @@ -0,0 +1,145 @@ +/* Test fmodf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + + +int main() +{ + TEST_SET_START("20040928191240EJL","EJL", "fmodf4"); + + unsigned int i0n = 0x449edbc6; + unsigned int i0d = 0x40cf799d; + unsigned int i0r = 0x3daa7300; + unsigned int i1n = 0x6bca107a; + unsigned int i1d = 0x6c4a107a; + unsigned int i1r = 0x6bca107a; + unsigned int i2n = 0x1c123605; + unsigned int i2d = 0x1c923602; + unsigned int i2r = 0x1c123605; + unsigned int i3n = 0x2b4c50fa; + unsigned int i3d = 0x253a3ae3; + unsigned int i3r = 0x25141df9; + unsigned int i4n = 0x73addffc; + unsigned int i4d = 0x742ddffc; + unsigned int i4r = 0x73addffc; + unsigned int i5n = 0x29d4d97c; + unsigned int i5d = 0x2a546e77; + unsigned int i5r = 0x29d4d97c; + + float x0n = hide_float(make_float(i0n)); + float x0d = hide_float(make_float(i0d)); + float x0r = hide_float(make_float(i0r)); + + float x1n = hide_float(make_float(i1n)); + float x1d = hide_float(make_float(i1d)); + float x1r = hide_float(make_float(i1r)); + + float x2n = hide_float(make_float(i2n)); + float x2d = hide_float(make_float(i2d)); + float x2r = hide_float(make_float(i2r)); + + float x3n = hide_float(make_float(i3n)); + float x3d = hide_float(make_float(i3d)); + float x3r = hide_float(make_float(i3r)); + + float x4n = hide_float(make_float(i4n)); + float x4d = hide_float(make_float(i4d)); + float x4r = hide_float(make_float(i4r)); + + float x5n = hide_float(make_float(i5n)); + float x5d = hide_float(make_float(i5d)); + float x5r = hide_float(make_float(i5r)); + + vec_float4 x0n_v = spu_splats(x0n); + vec_float4 x0d_v = spu_splats(x0d); + vec_float4 x0r_v = spu_splats(x0r); + + vec_float4 x1n_v = spu_splats(x1n); + vec_float4 x1d_v = spu_splats(x1d); + vec_float4 x1r_v = spu_splats(x1r); + + vec_float4 x2n_v = spu_splats(x2n); + vec_float4 x2d_v = spu_splats(x2d); + vec_float4 x2r_v = spu_splats(x2r); + + vec_float4 x3n_v = spu_splats(x3n); + vec_float4 x3d_v = spu_splats(x3d); + vec_float4 x3r_v = spu_splats(x3r); + + vec_float4 x4n_v = spu_splats(x4n); + vec_float4 x4d_v = spu_splats(x4d); + vec_float4 x4r_v = spu_splats(x4r); + + vec_float4 x5n_v = spu_splats(x5n); + vec_float4 x5d_v = spu_splats(x5d); + vec_float4 x5r_v = spu_splats(x5r); + + float res; + vec_float4 res_v; + + TEST_START("fmodf4"); + res_v = fmodf4(x0n_v, x0d_v); + TEST_CHECK("20040928191245EJL", allequal_ulps_float4( res_v, x0r_v, 1 ), 0); + res_v = fmodf4(x1n_v, x1d_v); + TEST_CHECK("20040928191247EJL", allequal_ulps_float4( res_v, x1r_v, 1 ), 0); + res_v = fmodf4(x2n_v, x2d_v); + TEST_CHECK("20040928191249EJL", allequal_ulps_float4( res_v, x2r_v, 1 ), 0); + res_v = fmodf4(x3n_v, x3d_v); + TEST_CHECK("20040928191251EJL", allequal_ulps_float4( res_v, x3r_v, 1 ), 0); + res_v = fmodf4(x4n_v, x4d_v); + TEST_CHECK("20040928191253EJL", allequal_ulps_float4( res_v, x4r_v, 1 ), 0); + res_v = fmodf4(x5n_v, x5d_v); + TEST_CHECK("20040928191255EJL", allequal_ulps_float4( res_v, x5r_v, 1 ), 0); + + TEST_START("fmodf"); + res = fmodf(x0n, x0d); + TEST_CHECK("20040928191258EJL", ulpDiff_f( res, x0r ) <= 1, 0); + res = fmodf(x1n, x1d); + TEST_CHECK("20040928191300EJL", ulpDiff_f( res, x1r ) <= 1, 0); + res = fmodf(x2n, x2d); + TEST_CHECK("20040928191302EJL", ulpDiff_f( res, x2r ) <= 1, 0); + res = fmodf(x3n, x3d); + TEST_CHECK("20040928191303EJL", ulpDiff_f( res, x3r ) <= 1, 0); + res = fmodf(x4n, x4d); + TEST_CHECK("20040928191305EJL", ulpDiff_f( res, x4r ) <= 1, 0); + res = fmodf(x5n, x5d); + TEST_CHECK("20040928191307EJL", ulpDiff_f( res, x5r ) <= 1, 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/fpclassifyd2.c b/Extras/simdmathlibrary/spu/tests/fpclassifyd2.c new file mode 100644 index 0000000..b7206bb --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/fpclassifyd2.c @@ -0,0 +1,225 @@ +/* Test fpclassifyd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060828000000AAN","AAN", "fpclassifyd2"); + + // -Nan + double x0 = hide_double(-nan("")); + long long r0 = FP_NAN; + + // -Inf + double x1 = hide_double(-HUGE_VAL); + long long r1 = FP_INFINITE; + + // -Dmax + double x2 = hide_double(-DBL_MAX); + long long r2 = FP_NORMAL; + + // -Norm + double x3 = hide_double(-824842.58421394); + long long r3 = FP_NORMAL; + + // -Dmin + double x4 = hide_double(-DBL_MIN); + long long r4 = FP_NORMAL; + + // -Denorm + double x5 = hide_double(-2.40e-310); + long long r5 = FP_SUBNORMAL; + + // -Unf + double x6 = hide_double(-1.0e-999); + long long r6 = FP_ZERO; + + // -0 + double x7 = hide_double(-0.0); + long long r7 = FP_ZERO; + + // 0 + double x8 = hide_double( 0.0); + long long r8 = FP_ZERO; + + // +Unf + double x9 = hide_double( 1.0e-999); + long long r9 = FP_ZERO; + + // +Denorm + double x10 = hide_double( 2.40e-310); + long long r10 = FP_SUBNORMAL; + + // +Dmin + double x11 = hide_double( DBL_MIN); + long long r11 = FP_NORMAL; + + // +Norm + double x12 = hide_double(3.14152634); + long long r12 = FP_NORMAL; + + // +Dmax + double x13 = hide_double(DBL_MAX); + long long r13 = FP_NORMAL; + + // +Inf + double x14 = hide_double(HUGE_VAL); + long long r14 = FP_INFINITE; + + //+Nan + double x15 = hide_double( nan("")); + long long r15 = FP_NAN; + + // Compound + vec_double2 x16_v = (vec_double2) {make_double(0x000AAAAAAAAAAAAAull), -1.0e-999 }; + vec_llong2 r16_v = (vec_llong2) {FP_SUBNORMAL, FP_ZERO}; + + // Compound + vec_double2 x17_v = (vec_double2) { 345.27533, -2.40e-310 }; + vec_llong2 r17_v = (vec_llong2) {FP_NORMAL, FP_SUBNORMAL}; + + // Compound + vec_double2 x18_v = (vec_double2) { nan(""), -3678342.8765343 }; + vec_llong2 r18_v = (vec_llong2) {FP_NAN, FP_NORMAL}; + + // Compound + vec_double2 x19_v = (vec_double2) {HUGE_VAL, -nan("") }; + vec_llong2 r19_v = (vec_llong2) {FP_INFINITE, FP_NAN}; + + // Compound + vec_double2 x20_v = (vec_double2) { -1.0e-999, -HUGE_VAL} ; + vec_llong2 r20_v = (vec_llong2) {FP_ZERO, FP_INFINITE}; + + vec_double2 x0_v = spu_splats(x0); + vec_llong2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_llong2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_llong2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_llong2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_llong2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_llong2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_llong2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_llong2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_llong2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_llong2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_llong2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_llong2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_llong2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_llong2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_llong2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_llong2 r15_v = spu_splats(r15); + + vec_llong2 res_v; + + TEST_START("fpclassifyd2"); + + res_v = (vec_llong2)fpclassifyd2(x0_v); + TEST_CHECK("20060828000000AAN", allequal_llong2( res_v, r0_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x1_v); + TEST_CHECK("20060828000001AAN", allequal_llong2( res_v, r1_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x2_v); + TEST_CHECK("20060828000002AAN", allequal_llong2( res_v, r2_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x3_v); + TEST_CHECK("20060828000003AAN", allequal_llong2( res_v, r3_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x4_v); + TEST_CHECK("20060828000004AAN", allequal_llong2( res_v, r4_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x5_v); + TEST_CHECK("20060828000005AAN", allequal_llong2( res_v, r5_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x6_v); + TEST_CHECK("20060828000006AAN", allequal_llong2( res_v, r6_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x7_v); + TEST_CHECK("20060828000007AAN", allequal_llong2( res_v, r7_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x8_v); + TEST_CHECK("20060828000008AAN", allequal_llong2( res_v, r8_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x9_v); + TEST_CHECK("20060828000009AAN", allequal_llong2( res_v, r9_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x10_v); + TEST_CHECK("20060828000010AAN", allequal_llong2( res_v, r10_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x11_v); + TEST_CHECK("20060828000011AAN", allequal_llong2( res_v, r11_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x12_v); + TEST_CHECK("20060828000012AAN", allequal_llong2( res_v, r12_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x13_v); + TEST_CHECK("20060828000013AAN", allequal_llong2( res_v, r13_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x14_v); + TEST_CHECK("20060828000014AAN", allequal_llong2( res_v, r14_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x15_v); + TEST_CHECK("20060828000015AAN", allequal_llong2( res_v, r15_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x16_v); + TEST_CHECK("20060828000016AAN", allequal_llong2( res_v, r16_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x17_v); + TEST_CHECK("20060828000017AAN", allequal_llong2( res_v, r17_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x18_v); + TEST_CHECK("20060828000018AAN", allequal_llong2( res_v, r18_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x19_v); + TEST_CHECK("20060828000019AAN", allequal_llong2( res_v, r19_v ), 0); + res_v = (vec_llong2)fpclassifyd2(x20_v); + TEST_CHECK("20060828000020AAN", allequal_llong2( res_v, r20_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/fpclassifyf4.c b/Extras/simdmathlibrary/spu/tests/fpclassifyf4.c new file mode 100644 index 0000000..e1cdc8d --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/fpclassifyf4.c @@ -0,0 +1,200 @@ +/* Test fpclassifyf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060828000000AAN","AAN", "fpclassifyf4"); + + // -Nan + float x0 = hide_float(-NANF); + int r0 = FP_NORMAL; + + // -Inf + float x1 = hide_float(-HUGE_VALF); + int r1 = FP_NORMAL; + + // -Smax + float x2 = hide_float(make_float(0xFFFFFFFF)); + int r2 = FP_NORMAL; + + // -Norm + float x3 = hide_float(-824842.58421394f); + int r3 = FP_NORMAL; + + // -Smin + float x4 = hide_float(make_float(0x80800000)); + int r4 = FP_NORMAL; + + // -Denorm + float x5 = hide_float(make_float(0x803AAAAA)); + int r5 = FP_SUBNORMAL; + + // -Unf + float x6 = hide_float(-1.0e-999); + int r6 = FP_ZERO; + + // -0 + float x7 = hide_float(-0.0f); + int r7 = FP_ZERO; + + // 0 + float x8 = hide_float( 0.0f); + int r8 = FP_ZERO; + + // +Unf + float x9 = hide_float( 1.0e-999); + int r9 = FP_ZERO; + + // +Denorm + float x10 = hide_float(make_float(0x003AAAAA)); + int r10 = FP_SUBNORMAL; + + // +Smin + float x11 = hide_float(make_float(0x00800000)); + int r11 = FP_NORMAL; + + // +Norm + float x12 = hide_float(3.14152634f); + int r12 = FP_NORMAL; + + // +Smax + float x13 = hide_float(make_float(0x7FFFFFFF)); + int r13 = FP_NORMAL; + + // +Inf + float x14 = hide_float(HUGE_VALF); + int r14 = FP_NORMAL; + + //+Nan + float x15 = hide_float(NANF); + int r15 = FP_NORMAL; + + // Compound + vec_float4 x16_v = (vec_float4) {make_float(0x003AAAAA), -1.0e-999, 345.27533, make_float(0x803AAAAA)}; + vec_int4 r16_v = (vec_int4) {FP_SUBNORMAL, FP_ZERO, FP_NORMAL, FP_SUBNORMAL}; + + vec_float4 x0_v = spu_splats(x0); + vec_int4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_int4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_int4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_int4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_int4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_int4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_int4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_int4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_int4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_int4 r9_v = spu_splats(r9); + + vec_float4 x10_v = spu_splats(x10); + vec_int4 r10_v = spu_splats(r10); + + vec_float4 x11_v = spu_splats(x11); + vec_int4 r11_v = spu_splats(r11); + + vec_float4 x12_v = spu_splats(x12); + vec_int4 r12_v = spu_splats(r12); + + vec_float4 x13_v = spu_splats(x13); + vec_int4 r13_v = spu_splats(r13); + + vec_float4 x14_v = spu_splats(x14); + vec_int4 r14_v = spu_splats(r14); + + vec_float4 x15_v = spu_splats(x15); + vec_int4 r15_v = spu_splats(r15); + + vec_int4 res_v; + + TEST_START("fpclassifyf4"); + + res_v = (vec_int4)fpclassifyf4(x0_v); + TEST_CHECK("20060828000000AAN", allequal_int4( res_v, r0_v ), 0); + res_v = (vec_int4)fpclassifyf4(x1_v); + TEST_CHECK("20060828000001AAN", allequal_int4( res_v, r1_v ), 0); + res_v = (vec_int4)fpclassifyf4(x2_v); + TEST_CHECK("20060828000002AAN", allequal_int4( res_v, r2_v ), 0); + res_v = (vec_int4)fpclassifyf4(x3_v); + TEST_CHECK("20060828000003AAN", allequal_int4( res_v, r3_v ), 0); + res_v = (vec_int4)fpclassifyf4(x4_v); + TEST_CHECK("20060828000004AAN", allequal_int4( res_v, r4_v ), 0); + res_v = (vec_int4)fpclassifyf4(x5_v); + TEST_CHECK("20060828000005AAN", allequal_int4( res_v, r5_v ), 0); + res_v = (vec_int4)fpclassifyf4(x6_v); + TEST_CHECK("20060828000006AAN", allequal_int4( res_v, r6_v ), 0); + res_v = (vec_int4)fpclassifyf4(x7_v); + TEST_CHECK("20060828000007AAN", allequal_int4( res_v, r7_v ), 0); + res_v = (vec_int4)fpclassifyf4(x8_v); + TEST_CHECK("20060828000008AAN", allequal_int4( res_v, r8_v ), 0); + res_v = (vec_int4)fpclassifyf4(x9_v); + TEST_CHECK("20060828000009AAN", allequal_int4( res_v, r9_v ), 0); + res_v = (vec_int4)fpclassifyf4(x10_v); + TEST_CHECK("20060828000010AAN", allequal_int4( res_v, r10_v ), 0); + res_v = (vec_int4)fpclassifyf4(x11_v); + TEST_CHECK("20060828000011AAN", allequal_int4( res_v, r11_v ), 0); + res_v = (vec_int4)fpclassifyf4(x12_v); + TEST_CHECK("20060828000012AAN", allequal_int4( res_v, r12_v ), 0); + res_v = (vec_int4)fpclassifyf4(x13_v); + TEST_CHECK("20060828000013AAN", allequal_int4( res_v, r13_v ), 0); + res_v = (vec_int4)fpclassifyf4(x14_v); + TEST_CHECK("20060828000014AAN", allequal_int4( res_v, r14_v ), 0); + res_v = (vec_int4)fpclassifyf4(x15_v); + TEST_CHECK("20060828000015AAN", allequal_int4( res_v, r15_v ), 0); + res_v = (vec_int4)fpclassifyf4(x16_v); + TEST_CHECK("20060828000016AAN", allequal_int4( res_v, r16_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/frexpd2.c b/Extras/simdmathlibrary/spu/tests/frexpd2.c new file mode 100644 index 0000000..e7ddefd --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/frexpd2.c @@ -0,0 +1,418 @@ +/* Test frexpd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060907000000AAN","AAN", "frexpd2"); + + vec_double2 res_v; + vec_llong2 exp_v; + + // -Nan + double x0 = hide_double(-nan("")); + double r0 = hide_double( nan("")); + //long long e0 = 0; + + // -Inf + double x1 = hide_double(-HUGE_VAL); + double r1 = x1; + //long long e1 = 0; + + // -Dmax + double x2 = hide_double(-DBL_MAX); + double r2 = hide_double(make_double(0xBFEFFFFFFFFFFFFFull)); + long long e2 = 1024; + + // -Norm + double x3 = hide_double(-824842.58421394); + double r3 = hide_double(make_double(0xBFE92C152B1E16ECull)); + long long e3 = 20; + + // -Dmin + double x4 = hide_double(make_double(0x8000000000000001ull)); + double r4 = hide_double(make_double(0xBFE0000000000000ull)); + long long e4 = -1073; + + // -Denorm + double x5 = hide_double(-2.40e-310); + double r5 = hide_double(make_double(0xBFE6170DBAADCD80ull)); + long long e5 = -1028; + + // -Unf + double x6 = hide_double(-1.0e-999); + double r6 = hide_double(make_double(0x0000000000000000ull)); + long long e6 = 0; + + // -0 + double x7 = hide_double(-0.0); + double r7 = hide_double(make_double(0x0000000000000000ull)); + long long e7 = 0; + + // 0 + double x8 = hide_double( 0.0); + double r8 = hide_double(make_double(0x0000000000000000ull)); + long long e8 = 0; + + // +Unf + double x9 = hide_double( 1.0e-999); + double r9 = hide_double(make_double(0x0000000000000000ull)); + long long e9 = 0; + + // +Denorm + double x10 = hide_double( 2.40e-310); + double r10 = hide_double(make_double(0x3FE6170DBAADCD80ull)); + long long e10 = -1028; + + // +Dmin + double x11 = hide_double(make_double(0x0000000000000001ull)); + double r11 = hide_double(make_double(0x3FE0000000000000ull)); + long long e11 = -1073; + + // +Norm + double x12 = hide_double(3.14152634); + double r12 = hide_double(make_double(0x3FE921D88FCE94A3ull)); + long long e12 = 2; + + // +Norm + double x13 = hide_double(7.0673903e149); + double r13 = hide_double(make_double(0x3FEBA2C056BA0DB2ull)); + long long e13 = 498; + + // +Norm + double x14 = hide_double(2.4673e304); + double r14 = hide_double(make_double(0x3FE1FD485BDF688Eull)); + long long e14 = 1012; + + // +Norm + double x15 = hide_double(7.235672e-25); + double r15 = hide_double(make_double(0x3FEBFDDCCA6FF682ull)); + long long e15 = -80; + + // +Denorm + double x16 = hide_double(9.452854e-312); + double r16 = hide_double(make_double(0x3FEBD784FE999000ull)); + long long e16 = -1033; + + // +Demorm + double x17 = hide_double(3.045784e-320); + double r17 = hide_double(make_double(0x3FE8150000000000ull)); + long long e17 = -1061; + + // -Norm + double x18 = hide_double(-6.459273e7); + double r18 = hide_double(make_double(0xBFEECCDAD0000000ull)); + long long e18 = 26; + + // -Norm + double x19 = hide_double(-2.493472e-99); + double r19 = hide_double(make_double(0xBFE5D0BDA52F448Cull)); + long long e19 = -327; + + // -Norm + double x20 = hide_double(-1.4824543e128); + double r20 = hide_double(make_double(0xBFEB5FFBEAE7B3E1ull)); + long long e20 = 426; + + // -Denorm + double x21 = hide_double(-5.53856231e-315); + double r21 = hide_double(make_double(0xBFE0B457A5000000ull)); + long long e21 = -1043; + + // -Demorm + double x22 = hide_double(-2.5684367e-312); + double r22 = hide_double(make_double(0xBFEE427A82514000ull)); + long long e22 = -1035; + + // +Dmax + double x23 = hide_double(DBL_MAX); + double r23 = hide_double(make_double(0x3FEFFFFFFFFFFFFFull)); + long long e23 = 1024; + + // +Inf + double x24 = hide_double(HUGE_VAL); + double r24 = x24; + //long long e24 = 0; + + //+Nan + double x25 = hide_double( nan("")); + double r25 = hide_double( nan("")); + //long long e25 = 0; + + // Compound + vec_double2 x26_v = (vec_double2) { -2.561286432e-317, -1.0e-999 }; + vec_double2 r26_v = (vec_double2) { hide_double(make_double(0xBFE3C69940000000ull)), 0.0 }; + vec_llong2 e26_v = (vec_llong2) { -1051, 0 }; + + // Compound + vec_double2 x27_v = (vec_double2) { 345.27533, -8.673e-310 }; + vec_double2 r27_v = (vec_double2) { hide_double(make_double(0x3FE59467C06E19B9ull)), hide_double(make_double(0xBFE3F4FCCDB156C0ull)) }; + vec_llong2 e27_v = (vec_llong2) { 9, -1026 }; + + // Compound + vec_llong2 keep28_v = exp_v; + vec_double2 x28_v = (vec_double2) { nan(""), -3678342.8765343 }; + vec_double2 r28_v = (vec_double2) { nan(""), hide_double(make_double(0xBFEC1043703246A4ull)) }; + vec_llong2 e28_v = (vec_llong2) { spu_extract(exp_v, 0), 22 }; + + // Compound + vec_llong2 keep29_v = exp_v; + vec_double2 x29_v = (vec_double2) { HUGE_VAL, -nan("") }; + vec_double2 r29_v = (vec_double2) { HUGE_VAL, nan("") }; + vec_llong2 e29_v = (vec_llong2) { spu_extract(exp_v, 0), spu_extract(exp_v, 1) }; + + // Compound + vec_llong2 keep30_v = exp_v; + vec_double2 x30_v = (vec_double2) { -1.2e-99, -HUGE_VAL } ; + vec_double2 r30_v = (vec_double2) { hide_double(make_double(0xBFE4FF632B6A83E4ull)), -HUGE_VAL }; + vec_llong2 e30_v = (vec_llong2) { -328, spu_extract(exp_v, 1) }; + + vec_llong2 keep0_v = exp_v; + vec_double2 x0_v = spu_splats(x0); + vec_double2 r0_v = spu_splats(r0); + vec_llong2 e0_v = exp_v; + + vec_llong2 keep1_v = exp_v; + vec_double2 x1_v = spu_splats(x1); + vec_double2 r1_v = spu_splats(r1); + vec_llong2 e1_v = exp_v; + + vec_double2 x2_v = spu_splats(x2); + vec_double2 r2_v = spu_splats(r2); + vec_llong2 e2_v = spu_splats(e2); + + vec_double2 x3_v = spu_splats(x3); + vec_double2 r3_v = spu_splats(r3); + vec_llong2 e3_v = spu_splats(e3); + + vec_double2 x4_v = spu_splats(x4); + vec_double2 r4_v = spu_splats(r4); + vec_llong2 e4_v = spu_splats(e4); + + vec_double2 x5_v = spu_splats(x5); + vec_double2 r5_v = spu_splats(r5); + vec_llong2 e5_v = spu_splats(e5); + + vec_double2 x6_v = spu_splats(x6); + vec_double2 r6_v = spu_splats(r6); + vec_llong2 e6_v = spu_splats(e6); + + vec_double2 x7_v = spu_splats(x7); + vec_double2 r7_v = spu_splats(r7); + vec_llong2 e7_v = spu_splats(e7); + + vec_double2 x8_v = spu_splats(x8); + vec_double2 r8_v = spu_splats(r8); + vec_llong2 e8_v = spu_splats(e8); + + vec_double2 x9_v = spu_splats(x9); + vec_double2 r9_v = spu_splats(r9); + vec_llong2 e9_v = spu_splats(e9); + + vec_double2 x10_v = spu_splats(x10); + vec_double2 r10_v = spu_splats(r10); + vec_llong2 e10_v = spu_splats(e10); + + vec_double2 x11_v = spu_splats(x11); + vec_double2 r11_v = spu_splats(r11); + vec_llong2 e11_v = spu_splats(e11); + + vec_double2 x12_v = spu_splats(x12); + vec_double2 r12_v = spu_splats(r12); + vec_llong2 e12_v = spu_splats(e12); + + vec_double2 x13_v = spu_splats(x13); + vec_double2 r13_v = spu_splats(r13); + vec_llong2 e13_v = spu_splats(e13); + + vec_double2 x14_v = spu_splats(x14); + vec_double2 r14_v = spu_splats(r14); + vec_llong2 e14_v = spu_splats(e14); + + vec_double2 x15_v = spu_splats(x15); + vec_double2 r15_v = spu_splats(r15); + vec_llong2 e15_v = spu_splats(e15); + + vec_double2 x16_v = spu_splats(x16); + vec_double2 r16_v = spu_splats(r16); + vec_llong2 e16_v = spu_splats(e16); + + vec_double2 x17_v = spu_splats(x17); + vec_double2 r17_v = spu_splats(r17); + vec_llong2 e17_v = spu_splats(e17); + + vec_double2 x18_v = spu_splats(x18); + vec_double2 r18_v = spu_splats(r18); + vec_llong2 e18_v = spu_splats(e18); + + vec_double2 x19_v = spu_splats(x19); + vec_double2 r19_v = spu_splats(r19); + vec_llong2 e19_v = spu_splats(e19); + + vec_double2 x20_v = spu_splats(x20); + vec_double2 r20_v = spu_splats(r20); + vec_llong2 e20_v = spu_splats(e20); + + vec_double2 x21_v = spu_splats(x21); + vec_double2 r21_v = spu_splats(r21); + vec_llong2 e21_v = spu_splats(e21); + + vec_double2 x22_v = spu_splats(x22); + vec_double2 r22_v = spu_splats(r22); + vec_llong2 e22_v = spu_splats(e22); + + vec_double2 x23_v = spu_splats(x23); + vec_double2 r23_v = spu_splats(r23); + vec_llong2 e23_v = spu_splats(e23); + + vec_llong2 keep24_v = exp_v; + vec_double2 x24_v = spu_splats(x24); + vec_double2 r24_v = spu_splats(r24); + vec_llong2 e24_v = exp_v; + + vec_llong2 keep25_v = exp_v; + vec_double2 x25_v = spu_splats(x25); + vec_double2 r25_v = spu_splats(r25); + vec_llong2 e25_v = exp_v; + + TEST_START("frexpd2"); + + exp_v = keep0_v; + res_v = (vec_double2)frexpd2(x0_v, &exp_v); + TEST_CHECK("20060907000000AAN", allnan_double2( res_v ), 0); (void)r0_v; + TEST_CHECK("20060907000000AAN", allequal_llong2( exp_v, e0_v ), 0); + exp_v = keep1_v; + res_v = (vec_double2)frexpd2(x1_v, &exp_v); + TEST_CHECK("20060907000001AAN", allequal_double2( res_v, r1_v ), 0); + TEST_CHECK("20060907000001AAN", allequal_llong2( exp_v, e1_v ), 0); + res_v = (vec_double2)frexpd2(x2_v, &exp_v); + TEST_CHECK("20060907000002AAN", allequal_double2( res_v, r2_v ), 0); + TEST_CHECK("20060907000002AAN", allequal_llong2( exp_v, e2_v ), 0); + res_v = (vec_double2)frexpd2(x3_v, &exp_v); + TEST_CHECK("20060907000003AAN", allequal_double2( res_v, r3_v ), 0); + TEST_CHECK("20060907000003AAN", allequal_llong2( exp_v, e3_v ), 0); + res_v = (vec_double2)frexpd2(x4_v, &exp_v); + TEST_CHECK("20060907000004AAN", allequal_double2( res_v, r4_v ), 0); + TEST_CHECK("20060907000004AAN", allequal_llong2( exp_v, e4_v ), 0); + res_v = (vec_double2)frexpd2(x5_v, &exp_v); + TEST_CHECK("20060907000005AAN", allequal_double2( res_v, r5_v ), 0); + TEST_CHECK("20060907000005AAN", allequal_llong2( exp_v, e5_v ), 0); + res_v = (vec_double2)frexpd2(x6_v, &exp_v); + TEST_CHECK("20060907000006AAN", allequal_double2( res_v, r6_v ), 0); + TEST_CHECK("20060907000006AAN", allequal_llong2( exp_v, e6_v ), 0); + res_v = (vec_double2)frexpd2(x7_v, &exp_v); + TEST_CHECK("20060907000007AAN", allequal_double2( res_v, r7_v ), 0); + TEST_CHECK("20060907000007AAN", allequal_llong2( exp_v, e7_v ), 0); + res_v = (vec_double2)frexpd2(x8_v, &exp_v); + TEST_CHECK("20060907000008AAN", allequal_double2( res_v, r8_v ), 0); + TEST_CHECK("20060907000008AAN", allequal_llong2( exp_v, e8_v ), 0); + res_v = (vec_double2)frexpd2(x9_v, &exp_v); + TEST_CHECK("20060907000009AAN", allequal_double2( res_v, r9_v ), 0); + TEST_CHECK("20060907000009AAN", allequal_llong2( exp_v, e9_v ), 0); + res_v = (vec_double2)frexpd2(x10_v, &exp_v); + TEST_CHECK("20060907000010AAN", allequal_double2( res_v, r10_v ), 0); + TEST_CHECK("20060907000010AAN", allequal_llong2( exp_v, e10_v ), 0); + res_v = (vec_double2)frexpd2(x11_v, &exp_v); + TEST_CHECK("20060907000011AAN", allequal_double2( res_v, r11_v ), 0); + TEST_CHECK("20060907000011AAN", allequal_llong2( exp_v, e11_v ), 0); + res_v = (vec_double2)frexpd2(x12_v, &exp_v); + TEST_CHECK("20060907000012AAN", allequal_double2( res_v, r12_v ), 0); + TEST_CHECK("20060907000012AAN", allequal_llong2( exp_v, e12_v ), 0); + res_v = (vec_double2)frexpd2(x13_v, &exp_v); + TEST_CHECK("20060907000013AAN", allequal_double2( res_v, r13_v ), 0); + TEST_CHECK("20060907000013AAN", allequal_llong2( exp_v, e13_v ), 0); + res_v = (vec_double2)frexpd2(x14_v, &exp_v); + TEST_CHECK("20060907000014AAN", allequal_double2( res_v, r14_v ), 0); + TEST_CHECK("20060907000014AAN", allequal_llong2( exp_v, e14_v ), 0); + res_v = (vec_double2)frexpd2(x15_v, &exp_v); + TEST_CHECK("20060907000015AAN", allequal_double2( res_v, r15_v ), 0); + TEST_CHECK("20060907000015AAN", allequal_llong2( exp_v, e15_v ), 0); + res_v = (vec_double2)frexpd2(x16_v, &exp_v); + TEST_CHECK("20060907000016AAN", allequal_double2( res_v, r16_v ), 0); + TEST_CHECK("20060907000016AAN", allequal_llong2( exp_v, e16_v ), 0); + res_v = (vec_double2)frexpd2(x17_v, &exp_v); + TEST_CHECK("20060907000017AAN", allequal_double2( res_v, r17_v ), 0); + TEST_CHECK("20060907000017AAN", allequal_llong2( exp_v, e17_v ), 0); + res_v = (vec_double2)frexpd2(x18_v, &exp_v); + TEST_CHECK("20060907000018AAN", allequal_double2( res_v, r18_v ), 0); + TEST_CHECK("20060907000018AAN", allequal_llong2( exp_v, e18_v ), 0); + res_v = (vec_double2)frexpd2(x19_v, &exp_v); + TEST_CHECK("20060907000019AAN", allequal_double2( res_v, r19_v ), 0); + TEST_CHECK("20060907000019AAN", allequal_llong2( exp_v, e19_v ), 0); + res_v = (vec_double2)frexpd2(x20_v, &exp_v); + TEST_CHECK("20060907000020AAN", allequal_double2( res_v, r20_v ), 0); + TEST_CHECK("20060907000020AAN", allequal_llong2( exp_v, e20_v ), 0); + res_v = (vec_double2)frexpd2(x21_v, &exp_v); + TEST_CHECK("20060907000021AAN", allequal_double2( res_v, r21_v ), 0); + TEST_CHECK("20060907000021AAN", allequal_llong2( exp_v, e21_v ), 0); + res_v = (vec_double2)frexpd2(x22_v, &exp_v); + TEST_CHECK("20060907000022AAN", allequal_double2( res_v, r22_v ), 0); + TEST_CHECK("20060907000022AAN", allequal_llong2( exp_v, e22_v ), 0); + res_v = (vec_double2)frexpd2(x23_v, &exp_v); + TEST_CHECK("20060907000023AAN", allequal_double2( res_v, r23_v ), 0); + TEST_CHECK("20060907000023AAN", allequal_llong2( exp_v, e23_v ), 0); + exp_v = keep24_v; + res_v = (vec_double2)frexpd2(x24_v, &exp_v); + TEST_CHECK("20060907000024AAN", allequal_double2( res_v, r24_v ), 0); + TEST_CHECK("20060907000024AAN", allequal_llong2( exp_v, e24_v ), 0); + exp_v = keep25_v; + res_v = (vec_double2)frexpd2(x25_v, &exp_v); + TEST_CHECK("20060907000025AAN", allnan_double2( res_v ), 0); (void)r25_v; + TEST_CHECK("20060907000025AAN", allequal_llong2( exp_v, e25_v ), 0); + res_v = (vec_double2)frexpd2(x26_v, &exp_v); + TEST_CHECK("20060907000026AAN", allequal_double2( res_v, r26_v ), 0); + TEST_CHECK("20060907000026AAN", allequal_llong2( exp_v, e26_v ), 0); + res_v = (vec_double2)frexpd2(x27_v, &exp_v); + TEST_CHECK("20060907000027AAN", allequal_double2( res_v, r27_v ), 0); + TEST_CHECK("20060907000027AAN", allequal_llong2( exp_v, e27_v ), 0); + exp_v = keep28_v; + res_v = (vec_double2)frexpd2(x28_v, &exp_v); + TEST_CHECK("20060907000028AAN", allequal_ulps_double2( res_v, r28_v, 0 ), 0); + TEST_CHECK("20060907000028AAN", allequal_llong2( exp_v, e28_v ), 0); + exp_v = keep29_v; + res_v = (vec_double2)frexpd2(x29_v, &exp_v); + TEST_CHECK("20060907000029AAN", allequal_ulps_double2( res_v, r29_v, 0 ), 0); + TEST_CHECK("20060907000029AAN", allequal_llong2( exp_v, e29_v ), 0); + exp_v = keep30_v; + res_v = (vec_double2)frexpd2(x30_v, &exp_v); + TEST_CHECK("20060907000030AAN", allequal_ulps_double2( res_v, r30_v, 0 ), 0); + TEST_CHECK("20060907000000AAN", allequal_llong2( exp_v, e30_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/frexpf4.c b/Extras/simdmathlibrary/spu/tests/frexpf4.c new file mode 100644 index 0000000..645b5ce --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/frexpf4.c @@ -0,0 +1,405 @@ +/* Test frexpf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + + +int main() +{ + TEST_SET_START("20060907000000AAN","AAN", "frexpf4"); + + // -Norm (IEEE-754: -Nan) + float x0 = hide_float(make_float(0xFFC00000)); + float r0 = hide_float(make_float(0xBF400000)); + int e0 = 129; + + // -Norm (IEEE-754: -Inf) + float x1 = hide_float(-HUGE_VALF); + float r1 = hide_float(make_float(0xBF7FFFFF)); + int e1 = 129; + + // -Smax + float x2 = hide_float(make_float(0xFFFFFFFF)); + float r2 = hide_float(make_float(0xBF7FFFFF)); + int e2 = 129; + + // -Norm + float x3 = hide_float(-824842.58421394); + float r3 = hide_float(make_float(0xBF4960A9)); + int e3 = 20; + + // -Smin + float x4 = hide_float(make_float(0x80800000)); + float r4 = hide_float(make_float(0xBF000000)); + int e4 = -125; + + // -Denorm + float x5 = hide_float(make_float(0x807AAAAA)); + float r5 = 0.0; + int e5 = 0; + + // -Unf + float x6 = hide_float(-1.0e-999); + float r6 = 0.0; + int e6 = 0; + + // -0 + float x7 = hide_float(-0.0); + float r7 = 0.0; + int e7 = 0; + + // 0 + float x8 = hide_float( 0.0); + float r8 = 0.0; + int e8 = 0; + + // +Unf + float x9 = hide_float( 1.0e-999); + float r9 = 0.0; + int e9 = 0; + + // +Denorm + float x10 = hide_float(make_float(0x007AAAAA)); + float r10 = 0.0; + int e10 = 0; + + // +Smin + float x11 = hide_float(make_float(0x00800000)); + float r11 = hide_float(make_float(0x3F000000)); + int e11 = -125; + + // +Norm + float x12 = hide_float(3.14152634); + float r12 = hide_float(make_float(0x3F490EC4)); + int e12 = 2; + + // +Norm + float x13 = hide_float(7.0673903e37); + float r13 = hide_float(make_float(0x3F54AD32)); + int e13 = 126; + + // +Norm + float x14 = hide_float(2.4673e14); + float r14 = hide_float(make_float(0x3F60664E)); + int e14 = 48; + + // +Norm + float x15 = hide_float(7.235672e-25); + float r15 = hide_float(make_float(0x3F5FEEE6)); + int e15 = -80; + + // +Norm + float x16 = hide_float(9.452854e17); + float r16 = hide_float(make_float(0x3F51E541)); + int e16 = 60; + + // +Norm + float x17 = hide_float(3.045784e-18); + float r17 = hide_float(make_float(0x3F60BD3C)); + int e17 = -58; + + // -Norm + float x18 = hide_float(-6.459273e7); + float r18 = hide_float(make_float(0xBF7666D6)); + int e18 = 26; + + // -Norm + float x19 = hide_float(-2.493472e-9); + float r19 = hide_float(make_float(0xBF2B59A0)); + int e19 = -28; + + // -Norm + float x20 = hide_float(-1.4824543e28); + float r20 = hide_float(make_float(0xBF3F9A4C)); + int e20 = 94; + + // -Norm + float x21 = hide_float(-5.53856231e-27); + float r21 = hide_float(make_float(0xBF5B67B2)); + int e21 = -87; + + // -Norm + float x22 = hide_float(-1.000001); + float r22 = hide_float(make_float(0xBF000008)); + int e22 = 1; + + // +Smax + float x23 = hide_float(make_float(0x7FFFFFFF)); + float r23 = hide_float(make_float(0x3F7FFFFF)); + int e23 = 129; + + //+Norm (IEEE-754: +Inf) + float x24 = hide_float(HUGE_VALF); + float r24 = hide_float(make_float(0x3F7FFFFF)); + int e24 = 129; + + //+Norm (IEEE-754: +Nan) + float x25 = hide_float(make_float(0x7FC00000)); + float r25 = hide_float(make_float(0x3F400000)); + int e25 = 129; + + // Compound + vec_float4 x26_v = (vec_float4) { -2.561286432e10, make_float(0x7FFFFFFF), -1.0e-999, 7.235672e-25 }; + vec_float4 r26_v = (vec_float4) { make_float(0xBF3ED4A9), make_float(0x3F7FFFFF), 0.0, make_float(0x3F5FEEE6) }; + vec_int4 e26_v = (vec_int4) { 35, 129, 0, -80 }; + + // Compound + vec_float4 x27_v = (vec_float4) { 345.27533f, 7.0673903e37, -0.0f, -2.40e-310 }; + vec_float4 r27_v = (vec_float4) { make_float(0x3F2CA33E), make_float(0x3F54AD32), 0.0, 0.0}; + vec_int4 e27_v = (vec_int4) { 9, 126, 0, 0 }; + + // Compound + vec_float4 x28_v = (vec_float4) { make_float(0x7FC00000), -824842.58421394f, -0.0f, -3678342.8765343f }; + vec_float4 r28_v = (vec_float4) { make_float(0x3F400000), make_float(0xBF4960A9), 0.0, make_float(0xBF60821B) }; + vec_int4 e28_v = (vec_int4) { 129, 20, 0, 22 }; + + // Compound + vec_float4 x29_v = (vec_float4) { HUGE_VALF, 1.0e-99, -5.53856231e-27, make_float(0xFFC00000) }; + vec_float4 r29_v = (vec_float4) { make_float(0x3F7FFFFF), 0.0, make_float(0xBF5B67B2), make_float(0xBF400000) }; + vec_int4 e29_v = (vec_int4) { 129, 0, -87, 129 }; + + // Compound + vec_float4 x30_v = (vec_float4) { 1.2e-57, -1.2e-19, 3.045784e-18, -HUGE_VALF } ; + vec_float4 r30_v = (vec_float4) { 0.0, make_float(0xBF0DABC6 ), make_float(0x3F60BD3C), make_float(0xBF7FFFFF) }; + vec_int4 e30_v = (vec_int4) { 0, -62, -58, 129 }; + + vec_float4 x0_v = spu_splats(x0); + vec_float4 r0_v = spu_splats(r0); + vec_int4 e0_v = spu_splats(e0); + + vec_float4 x1_v = spu_splats(x1); + vec_float4 r1_v = spu_splats(r1); + vec_int4 e1_v = spu_splats(e1); + + vec_float4 x2_v = spu_splats(x2); + vec_float4 r2_v = spu_splats(r2); + vec_int4 e2_v = spu_splats(e2); + + vec_float4 x3_v = spu_splats(x3); + vec_float4 r3_v = spu_splats(r3); + vec_int4 e3_v = spu_splats(e3); + + vec_float4 x4_v = spu_splats(x4); + vec_float4 r4_v = spu_splats(r4); + vec_int4 e4_v = spu_splats(e4); + + vec_float4 x5_v = spu_splats(x5); + vec_float4 r5_v = spu_splats(r5); + vec_int4 e5_v = spu_splats(e5); + + vec_float4 x6_v = spu_splats(x6); + vec_float4 r6_v = spu_splats(r6); + vec_int4 e6_v = spu_splats(e6); + + vec_float4 x7_v = spu_splats(x7); + vec_float4 r7_v = spu_splats(r7); + vec_int4 e7_v = spu_splats(e7); + + vec_float4 x8_v = spu_splats(x8); + vec_float4 r8_v = spu_splats(r8); + vec_int4 e8_v = spu_splats(e8); + + vec_float4 x9_v = spu_splats(x9); + vec_float4 r9_v = spu_splats(r9); + vec_int4 e9_v = spu_splats(e9); + + vec_float4 x10_v = spu_splats(x10); + vec_float4 r10_v = spu_splats(r10); + vec_int4 e10_v = spu_splats(e10); + + vec_float4 x11_v = spu_splats(x11); + vec_float4 r11_v = spu_splats(r11); + vec_int4 e11_v = spu_splats(e11); + + vec_float4 x12_v = spu_splats(x12); + vec_float4 r12_v = spu_splats(r12); + vec_int4 e12_v = spu_splats(e12); + + vec_float4 x13_v = spu_splats(x13); + vec_float4 r13_v = spu_splats(r13); + vec_int4 e13_v = spu_splats(e13); + + vec_float4 x14_v = spu_splats(x14); + vec_float4 r14_v = spu_splats(r14); + vec_int4 e14_v = spu_splats(e14); + + vec_float4 x15_v = spu_splats(x15); + vec_float4 r15_v = spu_splats(r15); + vec_int4 e15_v = spu_splats(e15); + + vec_float4 x16_v = spu_splats(x16); + vec_float4 r16_v = spu_splats(r16); + vec_int4 e16_v = spu_splats(e16); + + vec_float4 x17_v = spu_splats(x17); + vec_float4 r17_v = spu_splats(r17); + vec_int4 e17_v = spu_splats(e17); + + vec_float4 x18_v = spu_splats(x18); + vec_float4 r18_v = spu_splats(r18); + vec_int4 e18_v = spu_splats(e18); + + vec_float4 x19_v = spu_splats(x19); + vec_float4 r19_v = spu_splats(r19); + vec_int4 e19_v = spu_splats(e19); + + vec_float4 x20_v = spu_splats(x20); + vec_float4 r20_v = spu_splats(r20); + vec_int4 e20_v = spu_splats(e20); + + vec_float4 x21_v = spu_splats(x21); + vec_float4 r21_v = spu_splats(r21); + vec_int4 e21_v = spu_splats(e21); + + vec_float4 x22_v = spu_splats(x22); + vec_float4 r22_v = spu_splats(r22); + vec_int4 e22_v = spu_splats(e22); + + vec_float4 x23_v = spu_splats(x23); + vec_float4 r23_v = spu_splats(r23); + vec_int4 e23_v = spu_splats(e23); + + vec_float4 x24_v = spu_splats(x24); + vec_float4 r24_v = spu_splats(r24); + vec_int4 e24_v = spu_splats(e24); + + vec_float4 x25_v = spu_splats(x25); + vec_float4 r25_v = spu_splats(r25); + vec_int4 e25_v = spu_splats(e25); + + vec_float4 res_v; + vec_int4 exp_v; + + TEST_START("frexpf4"); + + res_v = (vec_float4)frexpf4(x0_v, &exp_v); + TEST_CHECK("20060907000000AAN", allequal_ulps_float4( res_v, r0_v, 0 ), 0); + TEST_CHECK("20060907000000AAN", allequal_int4( exp_v, e0_v ), 0); + res_v = (vec_float4)frexpf4(x1_v, &exp_v); + TEST_CHECK("20060907000001AAN", allequal_ulps_float4( res_v, r1_v, 0 ), 0); + TEST_CHECK("20060907000001AAN", allequal_int4( exp_v, e1_v ), 0); + res_v = (vec_float4)frexpf4(x2_v, &exp_v); + TEST_CHECK("20060907000002AAN", allequal_ulps_float4( res_v, r2_v, 0 ), 0); + TEST_CHECK("20060907000002AAN", allequal_int4( exp_v, e2_v ), 0); + res_v = (vec_float4)frexpf4(x3_v, &exp_v); + TEST_CHECK("20060907000003AAN", allequal_float4( res_v, r3_v ), 0); + TEST_CHECK("20060907000003AAN", allequal_int4( exp_v, e3_v ), 0); + res_v = (vec_float4)frexpf4(x4_v, &exp_v); + TEST_CHECK("20060907000004AAN", allequal_float4( res_v, r4_v ), 0); + TEST_CHECK("20060907000004AAN", allequal_int4( exp_v, e4_v ), 0); + res_v = (vec_float4)frexpf4(x5_v, &exp_v); + TEST_CHECK("20060907000005AAN", allequal_float4( res_v, r5_v ), 0); + TEST_CHECK("20060907000005AAN", allequal_int4( exp_v, e5_v ), 0); + res_v = (vec_float4)frexpf4(x6_v, &exp_v); + TEST_CHECK("20060907000006AAN", allequal_float4( res_v, r6_v ), 0); + TEST_CHECK("20060907000006AAN", allequal_int4( exp_v, e6_v ), 0); + res_v = (vec_float4)frexpf4(x7_v, &exp_v); + TEST_CHECK("20060907000007AAN", allequal_float4( res_v, r7_v ), 0); + TEST_CHECK("20060907000007AAN", allequal_int4( exp_v, e7_v ), 0); + res_v = (vec_float4)frexpf4(x8_v, &exp_v); + TEST_CHECK("20060907000008AAN", allequal_float4( res_v, r8_v ), 0); + TEST_CHECK("20060907000008AAN", allequal_int4( exp_v, e8_v ), 0); + res_v = (vec_float4)frexpf4(x9_v, &exp_v); + TEST_CHECK("20060907000009AAN", allequal_float4( res_v, r9_v ), 0); + TEST_CHECK("20060907000009AAN", allequal_int4( exp_v, e9_v ), 0); + res_v = (vec_float4)frexpf4(x10_v, &exp_v); + TEST_CHECK("20060907000010AAN", allequal_float4( res_v, r10_v ), 0); + TEST_CHECK("20060907000010AAN", allequal_int4( exp_v, e10_v ), 0); + res_v = (vec_float4)frexpf4(x11_v, &exp_v); + TEST_CHECK("20060907000011AAN", allequal_float4( res_v, r11_v ), 0); + TEST_CHECK("20060907000011AAN", allequal_int4( exp_v, e11_v ), 0); + res_v = (vec_float4)frexpf4(x12_v, &exp_v); + TEST_CHECK("20060907000012AAN", allequal_float4( res_v, r12_v ), 0); + TEST_CHECK("20060907000012AAN", allequal_int4( exp_v, e12_v ), 0); + res_v = (vec_float4)frexpf4(x13_v, &exp_v); + TEST_CHECK("20060907000013AAN", allequal_float4( res_v, r13_v ), 0); + TEST_CHECK("20060907000013AAN", allequal_int4( exp_v, e13_v ), 0); + res_v = (vec_float4)frexpf4(x14_v, &exp_v); + TEST_CHECK("20060907000014AAN", allequal_float4( res_v, r14_v ), 0); + TEST_CHECK("20060907000014AAN", allequal_int4( exp_v, e14_v ), 0); + res_v = (vec_float4)frexpf4(x15_v, &exp_v); + TEST_CHECK("20060907000015AAN", allequal_float4( res_v, r15_v ), 0); + TEST_CHECK("20060907000015AAN", allequal_int4( exp_v, e15_v ), 0); + res_v = (vec_float4)frexpf4(x16_v, &exp_v); + TEST_CHECK("20060907000016AAN", allequal_float4( res_v, r16_v ), 0); + TEST_CHECK("20060907000016AAN", allequal_int4( exp_v, e16_v ), 0); + res_v = (vec_float4)frexpf4(x17_v, &exp_v); + TEST_CHECK("20060907000017AAN", allequal_float4( res_v, r17_v ), 0); + TEST_CHECK("20060907000017AAN", allequal_int4( exp_v, e17_v ), 0); + res_v = (vec_float4)frexpf4(x18_v, &exp_v); + TEST_CHECK("20060907000018AAN", allequal_float4( res_v, r18_v ), 0); + TEST_CHECK("20060907000018AAN", allequal_int4( exp_v, e18_v ), 0); + res_v = (vec_float4)frexpf4(x19_v, &exp_v); + TEST_CHECK("20060907000019AAN", allequal_float4( res_v, r19_v ), 0); + TEST_CHECK("20060907000019AAN", allequal_int4( exp_v, e19_v ), 0); + res_v = (vec_float4)frexpf4(x20_v, &exp_v); + TEST_CHECK("20060907000020AAN", allequal_float4( res_v, r20_v ), 0); + TEST_CHECK("20060907000020AAN", allequal_int4( exp_v, e20_v ), 0); + res_v = (vec_float4)frexpf4(x21_v, &exp_v); + TEST_CHECK("20060907000021AAN", allequal_float4( res_v, r21_v ), 0); + TEST_CHECK("20060907000021AAN", allequal_int4( exp_v, e21_v ), 0); + res_v = (vec_float4)frexpf4(x22_v, &exp_v); + TEST_CHECK("20060907000022AAN", allequal_float4( res_v, r22_v ), 0); + TEST_CHECK("20060907000022AAN", allequal_int4( exp_v, e22_v ), 0); + res_v = (vec_float4)frexpf4(x23_v, &exp_v); + TEST_CHECK("20060907000023AAN", allequal_float4( res_v, r23_v ), 0); + TEST_CHECK("20060907000023AAN", allequal_int4( exp_v, e23_v ), 0); + res_v = (vec_float4)frexpf4(x24_v, &exp_v); + TEST_CHECK("20060907000024AAN", allequal_float4( res_v, r24_v ), 0); + TEST_CHECK("20060907000024AAN", allequal_int4( exp_v, e24_v ), 0); + res_v = (vec_float4)frexpf4(x25_v, &exp_v); + TEST_CHECK("20060907000025AAN", allequal_float4( res_v, r25_v ), 0); + TEST_CHECK("20060907000025AAN", allequal_int4( exp_v, e25_v ), 0); + res_v = (vec_float4)frexpf4(x26_v, &exp_v); + TEST_CHECK("20060907000026AAN", allequal_float4( res_v, r26_v ), 0); + TEST_CHECK("20060907000026AAN", allequal_int4( exp_v, e26_v ), 0); + res_v = (vec_float4)frexpf4(x27_v, &exp_v); + TEST_CHECK("20060907000027AAN", allequal_float4( res_v, r27_v ), 0); + TEST_CHECK("20060907000027AAN", allequal_int4( exp_v, e27_v ), 0); + res_v = (vec_float4)frexpf4(x28_v, &exp_v); + TEST_CHECK("20060907000028AAN", allequal_float4( res_v, r28_v ), 0); + TEST_CHECK("20060907000028AAN", allequal_int4( exp_v, e28_v ), 0); + res_v = (vec_float4)frexpf4(x29_v, &exp_v); + TEST_CHECK("20060907000029AAN", allequal_float4( res_v, r29_v ), 0); + TEST_CHECK("20060907000029AAN", allequal_int4( exp_v, e29_v ), 0); + res_v = (vec_float4)frexpf4(x30_v, &exp_v); + TEST_CHECK("20060907000030AAN", allequal_float4( res_v, r30_v ), 0); + TEST_CHECK("20060907000030AAN", allequal_int4( exp_v, e30_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/hypotd2.c b/Extras/simdmathlibrary/spu/tests/hypotd2.c new file mode 100644 index 0000000..d66d1a4 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/hypotd2.c @@ -0,0 +1,341 @@ +/* Test hypotd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060831000000AAN","AAN", "hypotd2"); + + // Does not test precesion, which depends on sqrtd2 implementation + // Uses Pythagorean triplets to test result validity + + //-QNaN, Norm + double x0 = hide_double(-nan("")); + double y0 = hide_double(1.0); + double r0 = hide_double( nan("")); + + //-QNaN, -Norm + double x1 = hide_double(-nan("")); + double y1 = hide_double(-21345853556.492); + double r1 = hide_double( nan("")); + + //-Inf, -QNaN + double x2 = hide_double(-HUGE_VAL); + double y2 = hide_double(make_double(0xFFFFFFFFFFFFFFFFull)); + double r2 = hide_double( nan("")); + + //-Norm, -SNaN + double x3 = hide_double(-67418234.34256245); + double y3 = hide_double(make_double(0xFFF7FFFFFFFFFFFFull)); + double r3 = hide_double( nan("")); + + //-Norm, -Denorm + double x4 = hide_double(-4.0e120); + double y4 = hide_double(-3.0e-320); + double r4 = hide_double( 4.0e120); + + //-Norm, -Inf + double x5 = hide_double(-168.97345223013); + double y5 = hide_double(-HUGE_VAL); + double r5 = hide_double(HUGE_VAL); + + //+Inf, -Inf + double x6 = hide_double(HUGE_VAL); + double y6 = hide_double(-HUGE_VAL); + double r6 = hide_double(HUGE_VAL); + + //-Norm, -0 + double x7 = hide_double(-168.97345223013); + double y7 = hide_double(-0.0); + double r7 = hide_double( 168.97345223013); + + //-Unf, -Norm + double x8 = hide_double(-1.0e-999); + double y8 = hide_double(-83532.96153153); + double r8 = hide_double( 83532.96153153); + + //-Unf, 0 + double x9 = hide_double(-1.0e-999); + double y9 = hide_double(0.0); + double r9 = hide_double(0.0); + + //QNaN, 0 + double x10 = hide_double(make_double(0x7FFFFFFFFFFFFFFFull)); + double y10 = hide_double( 0.0); + double r10 = hide_double( nan("")); + + //+Unf, +QNaN + double x11 = hide_double( 1.0e-999); + double y11 = hide_double( nan("")); + double r11 = hide_double( nan("")); + + //+Unf, +Norm + double x12 = hide_double( 1e-999); + double y12 = hide_double(0.0031529324); + double r12 = hide_double(0.0031529324); + + //+Norm, +Norm + double x13 = hide_double(55000.0e116); + double y13 = hide_double(480.0e118); + double r13 = hide_double(7.3e120); + + //+Norm, -Denorm + double x14 = hide_double(120.0e120); + double y14 = hide_double(-5.0e-321); + double r14 = hide_double(120.0e120/*1.3e101*/); + + //-Norm, +Demorm + double x15 = hide_double(-0.0000000008); + double y15 = hide_double(1.5e-320); + double r15 = hide_double( 0.8e-9); + + //+Norm, -Norm + double x16 = hide_double( 7.0e-6); + double y16 = hide_double(-24.0e-6); + double r16 = hide_double(25.0e-6); + + //+Norm, +Norm + double x17 = hide_double(0.0055); + double y17 = hide_double(0.0048); + double r17 = hide_double(0.0073); + + //+Denorm, +Norm + double x18 = hide_double(4.5e-320); + double y18 = hide_double(2.8); + double r18 = hide_double(2.8); + + //-Norm, +Norm + double x19 = hide_double(-8000.0); + double y19 = hide_double(39.0e2); + double r19 = hide_double(8900.0); + + //+Norm, +Norm + double x20 = hide_double(6.5e128); + double y20 = hide_double(7.2e128); + double r20 = hide_double(9.7e128); + + //-Norm, -Norm + double x21 = hide_double(-0.0035); + double y21 = hide_double(-1.2e-3); + double r21 = hide_double( 0.0037); + + //+Norm, +Norm + double x22 = hide_double(456548.6027761); + double y22 = hide_double(106165.2293520); + double r22 = hide_double(468729.8610289); + + //+Inf, +Ovf + double x23 = hide_double(HUGE_VAL); + double y23 = hide_double(1.0e999); + double r23 = hide_double(HUGE_VAL); + + //+Norm, +QNaN + double x24 = hide_double(264.345643345); + double y24 = hide_double(make_double(0x7FFAAAAAAAAAAAAAull)); + double r24 = hide_double( nan("")); + + //+Inf, +QNaN + double x25 = hide_double(HUGE_VAL); + double y25 = hide_double(nan("")); + double r25 = hide_double(nan("")); + + vec_double2 x0_v = spu_splats(x0); + vec_double2 y0_v = spu_splats(y0); + vec_double2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_double2 y1_v = spu_splats(y1); + vec_double2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_double2 y2_v = spu_splats(y2); + vec_double2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_double2 y3_v = spu_splats(y3); + vec_double2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_double2 y4_v = spu_splats(y4); + vec_double2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_double2 y5_v = spu_splats(y5); + vec_double2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_double2 y6_v = spu_splats(y6); + vec_double2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_double2 y7_v = spu_splats(y7); + vec_double2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_double2 y8_v = spu_splats(y8); + vec_double2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_double2 y9_v = spu_splats(y9); + vec_double2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_double2 y10_v = spu_splats(y10); + vec_double2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_double2 y11_v = spu_splats(y11); + vec_double2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_double2 y12_v = spu_splats(y12); + vec_double2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_double2 y13_v = spu_splats(y13); + vec_double2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_double2 y14_v = spu_splats(y14); + vec_double2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_double2 y15_v = spu_splats(y15); + vec_double2 r15_v = spu_splats(r15); + + vec_double2 x16_v = spu_splats(x16); + vec_double2 y16_v = spu_splats(y16); + vec_double2 r16_v = spu_splats(r16); + + vec_double2 x17_v = spu_splats(x17); + vec_double2 y17_v = spu_splats(y17); + vec_double2 r17_v = spu_splats(r17); + + vec_double2 x18_v = spu_splats(x18); + vec_double2 y18_v = spu_splats(y18); + vec_double2 r18_v = spu_splats(r18); + + vec_double2 x19_v = spu_splats(x19); + vec_double2 y19_v = spu_splats(y19); + vec_double2 r19_v = spu_splats(r19); + + vec_double2 x20_v = spu_splats(x20); + vec_double2 y20_v = spu_splats(y20); + vec_double2 r20_v = spu_splats(r20); + + vec_double2 x21_v = spu_splats(x21); + vec_double2 y21_v = spu_splats(y21); + vec_double2 r21_v = spu_splats(r21); + + vec_double2 x22_v = spu_splats(x22); + vec_double2 y22_v = spu_splats(y22); + vec_double2 r22_v = spu_splats(r22); + + vec_double2 x23_v = spu_splats(x23); + vec_double2 y23_v = spu_splats(y23); + vec_double2 r23_v = spu_splats(r23); + + vec_double2 x24_v = spu_splats(x24); + vec_double2 y24_v = spu_splats(y24); + vec_double2 r24_v = spu_splats(r24); + + vec_double2 x25_v = spu_splats(x25); + vec_double2 y25_v = spu_splats(y25); + vec_double2 r25_v = spu_splats(r25); + + vec_double2 res_v; + int tolerance = (int)0x0000000000000001ull; + + TEST_START("hypotd2"); + + res_v = (vec_double2)hypotd2(x0_v, y0_v); + TEST_CHECK("20060831000000AAN", allnan_double2( res_v ), 0); (void)r0_v; + res_v = (vec_double2)hypotd2(x1_v, y1_v); + TEST_CHECK("20060831000001AAN", allnan_double2( res_v ), 0); (void)r1_v; + res_v = (vec_double2)hypotd2(x2_v, y2_v); + TEST_CHECK("20060831000002AAN", allnan_double2( res_v ), 0); (void)r2_v; + res_v = (vec_double2)hypotd2(x3_v, y3_v); + TEST_CHECK("20060831000003AAN", allnan_double2( res_v ), 0); (void)r3_v; + res_v = (vec_double2)hypotd2(x4_v, y4_v); + TEST_CHECK("20060831000004AAN", allequal_ulps_double2( res_v, r4_v, tolerance ), 0); + res_v = (vec_double2)hypotd2(x5_v, y5_v); + TEST_CHECK("20060831000005AAN", allequal_ulps_double2( res_v, r5_v, 0 ), 0); + res_v = (vec_double2)hypotd2(x6_v, y6_v); + TEST_CHECK("20060831000006AAN", allequal_ulps_double2( res_v, r6_v, 0 ), 0); + res_v = (vec_double2)hypotd2(x7_v, y7_v); + TEST_CHECK("20060831000007AAN", allequal_ulps_double2( res_v, r7_v, tolerance ), 0); + res_v = (vec_double2)hypotd2(x8_v, y8_v); + TEST_CHECK("20060831000008AAN", allequal_ulps_double2( res_v, r8_v, tolerance ), 0); + res_v = (vec_double2)hypotd2(x9_v, y9_v); + TEST_CHECK("20060831000009AAN", allequal_ulps_double2( res_v, r9_v, tolerance ), 0); + res_v = (vec_double2)hypotd2(x10_v, y10_v); + TEST_CHECK("20060831000010AAN", allnan_double2( res_v ), 0); (void)r10_v; + res_v = (vec_double2)hypotd2(x11_v, y11_v); + TEST_CHECK("20060831000011AAN", allnan_double2( res_v ), 0); (void)r11_v; + res_v = (vec_double2)hypotd2(x12_v, y12_v); + TEST_CHECK("20060831000012AAN", allequal_ulps_double2( res_v, r12_v, tolerance ), 0); + res_v = (vec_double2)hypotd2(x13_v, y13_v); + TEST_CHECK("20060831000013AAN", allequal_ulps_double2( res_v, r13_v, tolerance ), 0); + res_v = (vec_double2)hypotd2(x14_v, y14_v); + TEST_CHECK("20060831000014AAN", allequal_ulps_double2( res_v, r14_v, tolerance ), 0); + res_v = (vec_double2)hypotd2(x15_v, y15_v); + TEST_CHECK("20060831000015AAN", allequal_ulps_double2( res_v, r15_v, tolerance ), 0); + res_v = (vec_double2)hypotd2(x16_v, y16_v); + TEST_CHECK("20060831000016AAN", allequal_ulps_double2( res_v, r16_v, tolerance ), 0); + res_v = (vec_double2)hypotd2(x17_v, y17_v); + TEST_CHECK("20060831000017AAN", allequal_ulps_double2( res_v, r17_v, tolerance ), 0); + res_v = (vec_double2)hypotd2(x18_v, y18_v); + TEST_CHECK("20060831000018AAN", allequal_ulps_double2( res_v, r18_v, tolerance ), 0); + res_v = (vec_double2)hypotd2(x19_v, y19_v); + TEST_CHECK("20060831000019AAN", allequal_ulps_double2( res_v, r19_v, tolerance ), 0); + res_v = (vec_double2)hypotd2(x20_v, y20_v); + TEST_CHECK("20060831000020AAN", allequal_ulps_double2( res_v, r20_v, tolerance ), 0); + res_v = (vec_double2)hypotd2(x21_v, y21_v); + TEST_CHECK("20060831000021AAN", allequal_ulps_double2( res_v, r21_v, tolerance ), 0); + res_v = (vec_double2)hypotd2(x22_v, y22_v); + TEST_CHECK("20060831000022AAN", allequal_ulps_double2( res_v, r22_v, tolerance ), 0); + res_v = (vec_double2)hypotd2(x23_v, y23_v); + TEST_CHECK("20060831000023AAN", allequal_ulps_double2( res_v, r23_v, 0 ), 0); + res_v = (vec_double2)hypotd2(x24_v, y24_v); + TEST_CHECK("20060831000024AAN", allnan_double2( res_v ), 0); (void)r24_v; + res_v = (vec_double2)hypotd2(x25_v, y25_v); + TEST_CHECK("20060831000025AAN", allnan_double2( res_v ), 0); (void)r25_v; + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/hypotf4.c b/Extras/simdmathlibrary/spu/tests/hypotf4.c new file mode 100644 index 0000000..a71f798 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/hypotf4.c @@ -0,0 +1,208 @@ +/* Test hypotf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060831000000AAN","AAN", "hypotf4"); + + // Does not test precesion, which depends on sqrtf4 implementation + // Uses Pythagorean triplets to test result validity + + //-Norm, -0 + float x0 = hide_float(-168.97345223013f); + float y0 = hide_float(-0.0); + float r0 = hide_float( 168.97345223013f); + + //-Unf, -Norm + float x1 = hide_float(-1.0e-999); + float y1 = hide_float(-83532.96153153f); + float r1 = hide_float( 83532.96153153f); + + //-Unf, 0 + float x2 = hide_float(-1.0e-999); + float y2 = hide_float( 0.0); + float r2 = hide_float( 0.0); + + //+Unf, +Norm + float x3 = hide_float(1.0e-999); + float y3 = hide_float(0.0031529324f); + float r3 = hide_float(0.0031529324f); + + //+Norm, +Norm + float x4 = hide_float(5.5e12); + float y4 = hide_float(4.8e12); + float r4 = hide_float(7.3e12); + + //+Norm, -Denorm + float x5 = hide_float(12.0e12); + float y5 = hide_float(make_float(0x803AAAAA)); + float r5 = hide_float(12.0e12); + + //-Norm, +Norm + float x6 = hide_float(-0.0000000008); + float y6 = hide_float( 0.0000000015); + float r6 = hide_float( 0.0000000017); + + //+Norm, -Norm + float x7 = hide_float( 7.0e-6); + float y7 = hide_float(-24.0e-6); + float r7 = hide_float( 25.0e-6); + + //+Norm, +Norm + float x8 = hide_float(0.0055f); + float y8 = hide_float(0.0048f); + float r8 = hide_float(0.0073f); + + //+Denorm, +Norm + float x9 = hide_float(make_float(0x007AAAAA)); + float y9 = hide_float(2.8f); + float r9 = hide_float(2.8f); + + //-Norm, +Norm + float x10 = hide_float(-8000.0); + float y10 = hide_float(39.0e2); + float r10 = hide_float(8900.0); + + //+Norm, +Norm + float x11 = hide_float(6.5e16); + float y11 = hide_float(7.2e16); + float r11 = hide_float(9.7e16); + + //-Norm, -Norm + float x12 = hide_float(-0.0035); + float y12 = hide_float(-12e-4); + float r12 = hide_float(3700e-6); + + //+Norm, +Norm + float x13 = hide_float(456548.6027761f); + float y13 = hide_float(106165.2293520f); + float r13 = hide_float(468729.8610289f); + + vec_float4 x0_v = spu_splats(x0); + vec_float4 y0_v = spu_splats(y0); + vec_float4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_float4 y1_v = spu_splats(y1); + vec_float4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_float4 y2_v = spu_splats(y2); + vec_float4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_float4 y3_v = spu_splats(y3); + vec_float4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_float4 y4_v = spu_splats(y4); + vec_float4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_float4 y5_v = spu_splats(y5); + vec_float4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_float4 y6_v = spu_splats(y6); + vec_float4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_float4 y7_v = spu_splats(y7); + vec_float4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_float4 y8_v = spu_splats(y8); + vec_float4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_float4 y9_v = spu_splats(y9); + vec_float4 r9_v = spu_splats(r9); + + vec_float4 x10_v = spu_splats(x10); + vec_float4 y10_v = spu_splats(y10); + vec_float4 r10_v = spu_splats(r10); + + vec_float4 x11_v = spu_splats(x11); + vec_float4 y11_v = spu_splats(y11); + vec_float4 r11_v = spu_splats(r11); + + vec_float4 x12_v = spu_splats(x12); + vec_float4 y12_v = spu_splats(y12); + vec_float4 r12_v = spu_splats(r12); + + vec_float4 x13_v = spu_splats(x13); + vec_float4 y13_v = spu_splats(y13); + vec_float4 r13_v = spu_splats(r13); + + vec_float4 res_v; + int tolerance = 0x00000001; + + TEST_START("hypotf4"); + + res_v = (vec_float4)hypotf4(x0_v, y0_v); + TEST_CHECK("20060831000000AAN", allequal_ulps_float4( res_v, r0_v, tolerance ), 0); + res_v = (vec_float4)hypotf4(x1_v, y1_v); + TEST_CHECK("20060831000001AAN", allequal_ulps_float4( res_v, r1_v, tolerance ), 0); + res_v = (vec_float4)hypotf4(x2_v, y2_v); + TEST_CHECK("20060831000002AAN", allequal_ulps_float4( res_v, r2_v, tolerance ), 0); + res_v = (vec_float4)hypotf4(x3_v, y3_v); + TEST_CHECK("20060831000003AAN", allequal_ulps_float4( res_v, r3_v, tolerance ), 0); + res_v = (vec_float4)hypotf4(x4_v, y4_v); + TEST_CHECK("20060831000004AAN", allequal_ulps_float4( res_v, r4_v, tolerance ), 0); + res_v = (vec_float4)hypotf4(x5_v, y5_v); + TEST_CHECK("20060831000005AAN", allequal_ulps_float4( res_v, r5_v, tolerance ), 0); + res_v = (vec_float4)hypotf4(x6_v, y6_v); + TEST_CHECK("20060831000006AAN", allequal_ulps_float4( res_v, r6_v, tolerance ), 0); + res_v = (vec_float4)hypotf4(x7_v, y7_v); + TEST_CHECK("20060831000007AAN", allequal_ulps_float4( res_v, r7_v, tolerance ), 0); + res_v = (vec_float4)hypotf4(x8_v, y8_v); + TEST_CHECK("20060831000008AAN", allequal_ulps_float4( res_v, r8_v, tolerance ), 0); + res_v = (vec_float4)hypotf4(x9_v, y9_v); + TEST_CHECK("20060831000009AAN", allequal_ulps_float4( res_v, r9_v, tolerance ), 0); + res_v = (vec_float4)hypotf4(x10_v, y10_v); + TEST_CHECK("20060831000010AAN", allequal_ulps_float4( res_v, r10_v, tolerance ), 0); + res_v = (vec_float4)hypotf4(x11_v, y11_v); + TEST_CHECK("20060831000011AAN", allequal_ulps_float4( res_v, r11_v, tolerance ), 0); + res_v = (vec_float4)hypotf4(x12_v, y12_v); + TEST_CHECK("20060831000012AAN", allequal_ulps_float4( res_v, r12_v, tolerance ), 0); + res_v = (vec_float4)hypotf4(x13_v, y13_v); + TEST_CHECK("20060831000013AAN", allequal_ulps_float4( res_v, r13_v, tolerance ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/ilogbd2.c b/Extras/simdmathlibrary/spu/tests/ilogbd2.c new file mode 100644 index 0000000..38cd981 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/ilogbd2.c @@ -0,0 +1,316 @@ +/* Test ilogbd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060904000000AAN","AAN", "ilogbd2"); + + // -Nan + double x0 = hide_double(-nan("")); + long long r0 = (long long)FP_ILOGBNAN; + + // -Inf + double x1 = hide_double(-HUGE_VAL); + long long r1 = (long long)FP_ILOGB0; + + // -Dmax + double x2 = hide_double(-DBL_MAX); + long long r2 = 1023ll; + + // -Norm + double x3 = hide_double(-824842.58421394); + long long r3 = 19ll; + + // -Dmin + double x4 = hide_double(-DBL_MIN); + long long r4 = -1022ll; + + // -Denorm + double x5 = hide_double(-2.40e-310); + long long r5 = -1029ll; + + // -Unf + double x6 = hide_double(-1.0e-999); + long long r6 = (long long)FP_ILOGB0; + + // -0 + double x7 = hide_double(-0.0); + long long r7 = (long long)FP_ILOGB0; + + // 0 + double x8 = hide_double( 0.0); + long long r8 = (long long)FP_ILOGB0; + + // +Unf + double x9 = hide_double( 1.0e-999); + long long r9 = (long long)FP_ILOGB0; + + // +Denorm + double x10 = hide_double( 2.40e-310); + long long r10 = -1029ll; + + // +Dmin + double x11 = hide_double( DBL_MIN); + long long r11 = -1022ll; + + // +Norm + double x12 = hide_double(3.14152634); + long long r12 = 1ll; + + // +Norm + double x13 = hide_double(7.0673903e149); + long long r13 = 497ll; + + // +Norm + double x14 = hide_double(2.4673e304); + long long r14 = 1011ll; + + // +Norm + double x15 = hide_double(7.235672e-25); + long long r15 = -81ll; + + // +Denorm + double x16 = hide_double(9.452854e-312); + long long r16 = -1034ll; + + // +Demorm + double x17 = hide_double(3.045784e-320); + long long r17 = -1062ll; + + // -Norm + double x18 = hide_double(-6.459273e7); + long long r18 = 25ll; + + // -Norm + double x19 = hide_double(-2.493472e-99); + long long r19 = -328ll; + + // -Norm + double x20 = hide_double(-1.4824543e128); + long long r20 = 425ll; + + // -Denorm + double x21 = hide_double(-5.53856231e-315); + long long r21 = -1044ll; + + // -Demorm + double x22 = hide_double(-2.5684367e-312); + long long r22 = -1036ll; + + // +Dmax + double x23 = hide_double(DBL_MAX); + long long r23 = 1023ll; + + // +Inf + double x24 = hide_double(HUGE_VAL); + long long r24 = (long long)FP_ILOGB0; + + //+Nan + double x25 = hide_double( nan("")); + long long r25 = (long long)FP_ILOGBNAN; + + // Compound + vec_double2 x26_v = (vec_double2) { -2.561286432e-317, -1.0e-999 }; + vec_llong2 r26_v = (vec_llong2) { -1052ll, FP_ILOGB0 }; + + // Compound + vec_double2 x27_v = (vec_double2) { 345.27533, -8.673e-310 }; + vec_llong2 r27_v = (vec_llong2) { 8ll, -1027ll }; + + // Compound + vec_double2 x28_v = (vec_double2) { nan(""), -3678342.8765343 }; + vec_llong2 r28_v = (vec_llong2) { FP_ILOGBNAN, 21ll }; + + // Compound + vec_double2 x29_v = (vec_double2) { HUGE_VAL, -nan("") }; + vec_llong2 r29_v = (vec_llong2) { FP_ILOGB0, FP_ILOGBNAN }; + + // Compound + vec_double2 x30_v = (vec_double2) { -1.2e-99, -HUGE_VAL } ; + vec_llong2 r30_v = (vec_llong2) { -329ll, FP_ILOGB0 }; + + vec_double2 x0_v = spu_splats(x0); + vec_llong2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_llong2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_llong2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_llong2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_llong2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_llong2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_llong2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_llong2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_llong2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_llong2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_llong2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_llong2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_llong2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_llong2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_llong2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_llong2 r15_v = spu_splats(r15); + + vec_double2 x16_v = spu_splats(x16); + vec_llong2 r16_v = spu_splats(r16); + + vec_double2 x17_v = spu_splats(x17); + vec_llong2 r17_v = spu_splats(r17); + + vec_double2 x18_v = spu_splats(x18); + vec_llong2 r18_v = spu_splats(r18); + + vec_double2 x19_v = spu_splats(x19); + vec_llong2 r19_v = spu_splats(r19); + + vec_double2 x20_v = spu_splats(x20); + vec_llong2 r20_v = spu_splats(r20); + + vec_double2 x21_v = spu_splats(x21); + vec_llong2 r21_v = spu_splats(r21); + + vec_double2 x22_v = spu_splats(x22); + vec_llong2 r22_v = spu_splats(r22); + + vec_double2 x23_v = spu_splats(x23); + vec_llong2 r23_v = spu_splats(r23); + + vec_double2 x24_v = spu_splats(x24); + vec_llong2 r24_v = spu_splats(r24); + + vec_double2 x25_v = spu_splats(x25); + vec_llong2 r25_v = spu_splats(r25); + + vec_llong2 res_v; + + TEST_START("ilogbd2"); + + res_v = (vec_llong2)ilogbd2(x0_v); + TEST_CHECK("20060904000000AAN", allequal_llong2( res_v, r0_v ), 0); + res_v = (vec_llong2)ilogbd2(x1_v); + TEST_CHECK("20060904000001AAN", allequal_llong2( res_v, r1_v ), 0); + res_v = (vec_llong2)ilogbd2(x2_v); + TEST_CHECK("20060904000002AAN", allequal_llong2( res_v, r2_v ), 0); + res_v = (vec_llong2)ilogbd2(x3_v); + TEST_CHECK("20060904000003AAN", allequal_llong2( res_v, r3_v ), 0); + res_v = (vec_llong2)ilogbd2(x4_v); + TEST_CHECK("20060904000004AAN", allequal_llong2( res_v, r4_v ), 0); + res_v = (vec_llong2)ilogbd2(x5_v); + TEST_CHECK("20060904000005AAN", allequal_llong2( res_v, r5_v ), 0); + res_v = (vec_llong2)ilogbd2(x6_v); + TEST_CHECK("20060904000006AAN", allequal_llong2( res_v, r6_v ), 0); + res_v = (vec_llong2)ilogbd2(x7_v); + TEST_CHECK("20060904000007AAN", allequal_llong2( res_v, r7_v ), 0); + res_v = (vec_llong2)ilogbd2(x8_v); + TEST_CHECK("20060904000008AAN", allequal_llong2( res_v, r8_v ), 0); + res_v = (vec_llong2)ilogbd2(x9_v); + TEST_CHECK("20060904000009AAN", allequal_llong2( res_v, r9_v ), 0); + res_v = (vec_llong2)ilogbd2(x10_v); + TEST_CHECK("20060904000010AAN", allequal_llong2( res_v, r10_v ), 0); + res_v = (vec_llong2)ilogbd2(x11_v); + TEST_CHECK("20060904000011AAN", allequal_llong2( res_v, r11_v ), 0); + res_v = (vec_llong2)ilogbd2(x12_v); + TEST_CHECK("20060904000012AAN", allequal_llong2( res_v, r12_v ), 0); + res_v = (vec_llong2)ilogbd2(x13_v); + TEST_CHECK("20060904000013AAN", allequal_llong2( res_v, r13_v ), 0); + res_v = (vec_llong2)ilogbd2(x14_v); + TEST_CHECK("20060904000014AAN", allequal_llong2( res_v, r14_v ), 0); + res_v = (vec_llong2)ilogbd2(x15_v); + TEST_CHECK("20060904000015AAN", allequal_llong2( res_v, r15_v ), 0); + res_v = (vec_llong2)ilogbd2(x16_v); + TEST_CHECK("20060904000016AAN", allequal_llong2( res_v, r16_v ), 0); + res_v = (vec_llong2)ilogbd2(x17_v); + TEST_CHECK("20060904000017AAN", allequal_llong2( res_v, r17_v ), 0); + res_v = (vec_llong2)ilogbd2(x18_v); + TEST_CHECK("20060904000018AAN", allequal_llong2( res_v, r18_v ), 0); + res_v = (vec_llong2)ilogbd2(x19_v); + TEST_CHECK("20060904000019AAN", allequal_llong2( res_v, r19_v ), 0); + res_v = (vec_llong2)ilogbd2(x20_v); + TEST_CHECK("20060904000020AAN", allequal_llong2( res_v, r20_v ), 0); + res_v = (vec_llong2)ilogbd2(x21_v); + TEST_CHECK("20060904000021AAN", allequal_llong2( res_v, r21_v ), 0); + res_v = (vec_llong2)ilogbd2(x22_v); + TEST_CHECK("20060904000022AAN", allequal_llong2( res_v, r22_v ), 0); + res_v = (vec_llong2)ilogbd2(x23_v); + TEST_CHECK("20060904000023AAN", allequal_llong2( res_v, r23_v ), 0); + res_v = (vec_llong2)ilogbd2(x24_v); + TEST_CHECK("20060904000024AAN", allequal_llong2( res_v, r24_v ), 0); + res_v = (vec_llong2)ilogbd2(x25_v); + TEST_CHECK("20060904000025AAN", allequal_llong2( res_v, r25_v ), 0); + res_v = (vec_llong2)ilogbd2(x26_v); + TEST_CHECK("20060904000026AAN", allequal_llong2( res_v, r26_v ), 0); + res_v = (vec_llong2)ilogbd2(x27_v); + TEST_CHECK("20060904000027AAN", allequal_llong2( res_v, r27_v ), 0); + res_v = (vec_llong2)ilogbd2(x28_v); + TEST_CHECK("20060904000028AAN", allequal_llong2( res_v, r28_v ), 0); + res_v = (vec_llong2)ilogbd2(x29_v); + TEST_CHECK("20060904000029AAN", allequal_llong2( res_v, r29_v ), 0); + res_v = (vec_llong2)ilogbd2(x30_v); + TEST_CHECK("20060904000030AAN", allequal_llong2( res_v, r30_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/ilogbf4.c b/Extras/simdmathlibrary/spu/tests/ilogbf4.c new file mode 100644 index 0000000..cb804aa --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/ilogbf4.c @@ -0,0 +1,317 @@ +/* Test ilogbf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060904000000AAN","AAN", "ilogbf4"); + + // -Norm (IEEE-754: -Nan) + float x0 = hide_float(make_float(0xFFC00000)); + int r0 = 128; + + // -Norm (IEEE-754: -Inf) + float x1 = hide_float(-HUGE_VALF); + int r1 = 128; + + // -Smax + float x2 = hide_float(-FLT_MAX); + int r2 = 128; + + // -Norm + float x3 = hide_float(-824842.58421394); + int r3 = 19; + + // -Smin + float x4 = hide_float(make_float(0x80800000)); + int r4 = -126; + + // -Denorm + float x5 = hide_float(make_float(0x807AAAAA)); + int r5 = (int)FP_ILOGB0; + + // -Unf + float x6 = hide_float(-1.0e-999); + int r6 = (int)FP_ILOGB0; + + // -0 + float x7 = hide_float(-0.0); + int r7 = (int)FP_ILOGB0; + + // 0 + float x8 = hide_float( 0.0); + int r8 = (int)FP_ILOGB0; + + // +Unf + float x9 = hide_float( 1.0e-999); + int r9 = (int)FP_ILOGB0; + + // +Denorm + float x10 = hide_float(make_float(0x007AAAAA)); + int r10 = (int)FP_ILOGB0; + + // +Smin + float x11 = hide_float(make_float(0x00800000)); + int r11 = -126; + + // +Norm + float x12 = hide_float(3.14152634); + int r12 = 1; + + // +Norm + float x13 = hide_float(7.0673903e37); + int r13 = 125; + + // +Norm + float x14 = hide_float(2.4673e14); + int r14 = 47; + + // +Norm + float x15 = hide_float(7.235672e-25); + int r15 = -81; + + // +Norm + float x16 = hide_float(9.452854e17); + int r16 = 59; + + // +Norm + float x17 = hide_float(3.045784e-18); + int r17 = -59; + + // -Norm + float x18 = hide_float(-6.459273e7); + int r18 = 25; + + // -Norm + float x19 = hide_float(-2.493472e-9); + int r19 = -29; + + // -Norm + float x20 = hide_float(-1.4824543e28); + int r20 = 93; + + // -Norm + float x21 = hide_float(-5.53856231e-27); + int r21 = -88; + + // -Norm + float x22 = hide_float(-1.000001); + int r22 = 0; + + // +Smax + float x23 = hide_float(FLT_MAX); + int r23 = 128; + + //+Norm (IEEE-754: +Inf) + float x24 = hide_float( HUGE_VALF); + int r24 = 128; + + //+Norm (IEEE-754: +Nan) + float x25 = hide_float(make_float(0x7FC00000)); + int r25 = 128; + + // Compound + vec_float4 x26_v = (vec_float4) { -2.561286432e10, FLT_MAX, -1.0e-999, 7.235672e-25 }; + vec_int4 r26_v = (vec_int4) { 34, 128, FP_ILOGB0, -81 }; + + // Compound + vec_float4 x27_v = (vec_float4) { 345.27533, 7.0673903e37, -0.0, -2.40e-310 }; + vec_int4 r27_v = (vec_int4) { 8, 125, FP_ILOGB0, FP_ILOGB0 }; + + // Compound + vec_float4 x28_v = (vec_float4) { make_float(0x7FC00000), -824842.58421394, -0.0, -3678342.8765343 }; + vec_int4 r28_v = (vec_int4) { 128, 19, FP_ILOGB0, 21 }; + + // Compound + vec_float4 x29_v = (vec_float4) { HUGE_VALF, 1.0e-99, -5.53856231e-27, make_float(0xFFC00000) }; + vec_int4 r29_v = (vec_int4) { 128, FP_ILOGB0, -88, 128 }; + + // Compound + vec_float4 x30_v = (vec_float4) { 1.2e-57, -1.2e-19, 3.045784e-18, -HUGE_VALF } ; + vec_int4 r30_v = (vec_int4) { FP_ILOGB0, -63, -59, 128 }; + + vec_float4 x0_v = spu_splats(x0); + vec_int4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_int4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_int4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_int4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_int4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_int4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_int4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_int4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_int4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_int4 r9_v = spu_splats(r9); + + vec_float4 x10_v = spu_splats(x10); + vec_int4 r10_v = spu_splats(r10); + + vec_float4 x11_v = spu_splats(x11); + vec_int4 r11_v = spu_splats(r11); + + vec_float4 x12_v = spu_splats(x12); + vec_int4 r12_v = spu_splats(r12); + + vec_float4 x13_v = spu_splats(x13); + vec_int4 r13_v = spu_splats(r13); + + vec_float4 x14_v = spu_splats(x14); + vec_int4 r14_v = spu_splats(r14); + + vec_float4 x15_v = spu_splats(x15); + vec_int4 r15_v = spu_splats(r15); + + vec_float4 x16_v = spu_splats(x16); + vec_int4 r16_v = spu_splats(r16); + + vec_float4 x17_v = spu_splats(x17); + vec_int4 r17_v = spu_splats(r17); + + vec_float4 x18_v = spu_splats(x18); + vec_int4 r18_v = spu_splats(r18); + + vec_float4 x19_v = spu_splats(x19); + vec_int4 r19_v = spu_splats(r19); + + vec_float4 x20_v = spu_splats(x20); + vec_int4 r20_v = spu_splats(r20); + + vec_float4 x21_v = spu_splats(x21); + vec_int4 r21_v = spu_splats(r21); + + vec_float4 x22_v = spu_splats(x22); + vec_int4 r22_v = spu_splats(r22); + + vec_float4 x23_v = spu_splats(x23); + vec_int4 r23_v = spu_splats(r23); + + vec_float4 x24_v = spu_splats(x24); + vec_int4 r24_v = spu_splats(r24); + + vec_float4 x25_v = spu_splats(x25); + vec_int4 r25_v = spu_splats(r25); + + vec_int4 res_v; + + TEST_START("ilogbf4"); + + res_v = (vec_int4)ilogbf4(x0_v); + TEST_CHECK("20060904000000AAN", allequal_int4( res_v, r0_v ), 0); + res_v = (vec_int4)ilogbf4(x1_v); + TEST_CHECK("20060904000001AAN", allequal_int4( res_v, r1_v ), 0); + res_v = (vec_int4)ilogbf4(x2_v); + TEST_CHECK("20060904000002AAN", allequal_int4( res_v, r2_v ), 0); + res_v = (vec_int4)ilogbf4(x3_v); + TEST_CHECK("20060904000003AAN", allequal_int4( res_v, r3_v ), 0); + res_v = (vec_int4)ilogbf4(x4_v); + TEST_CHECK("20060904000004AAN", allequal_int4( res_v, r4_v ), 0); + res_v = (vec_int4)ilogbf4(x5_v); + TEST_CHECK("20060904000005AAN", allequal_int4( res_v, r5_v ), 0); + res_v = (vec_int4)ilogbf4(x6_v); + TEST_CHECK("20060904000006AAN", allequal_int4( res_v, r6_v ), 0); + res_v = (vec_int4)ilogbf4(x7_v); + TEST_CHECK("20060904000007AAN", allequal_int4( res_v, r7_v ), 0); + res_v = (vec_int4)ilogbf4(x8_v); + TEST_CHECK("20060904000008AAN", allequal_int4( res_v, r8_v ), 0); + res_v = (vec_int4)ilogbf4(x9_v); + TEST_CHECK("20060904000009AAN", allequal_int4( res_v, r9_v ), 0); + res_v = (vec_int4)ilogbf4(x10_v); + TEST_CHECK("20060904000010AAN", allequal_int4( res_v, r10_v ), 0); + res_v = (vec_int4)ilogbf4(x11_v); + TEST_CHECK("20060904000011AAN", allequal_int4( res_v, r11_v ), 0); + res_v = (vec_int4)ilogbf4(x12_v); + TEST_CHECK("20060904000012AAN", allequal_int4( res_v, r12_v ), 0); + res_v = (vec_int4)ilogbf4(x13_v); + TEST_CHECK("20060904000013AAN", allequal_int4( res_v, r13_v ), 0); + res_v = (vec_int4)ilogbf4(x14_v); + TEST_CHECK("20060904000014AAN", allequal_int4( res_v, r14_v ), 0); + res_v = (vec_int4)ilogbf4(x15_v); + TEST_CHECK("20060904000015AAN", allequal_int4( res_v, r15_v ), 0); + res_v = (vec_int4)ilogbf4(x16_v); + TEST_CHECK("20060904000016AAN", allequal_int4( res_v, r16_v ), 0); + res_v = (vec_int4)ilogbf4(x17_v); + TEST_CHECK("20060904000017AAN", allequal_int4( res_v, r17_v ), 0); + res_v = (vec_int4)ilogbf4(x18_v); + TEST_CHECK("20060904000018AAN", allequal_int4( res_v, r18_v ), 0); + res_v = (vec_int4)ilogbf4(x19_v); + TEST_CHECK("20060904000019AAN", allequal_int4( res_v, r19_v ), 0); + res_v = (vec_int4)ilogbf4(x20_v); + TEST_CHECK("20060904000020AAN", allequal_int4( res_v, r20_v ), 0); + res_v = (vec_int4)ilogbf4(x21_v); + TEST_CHECK("20060904000021AAN", allequal_int4( res_v, r21_v ), 0); + res_v = (vec_int4)ilogbf4(x22_v); + TEST_CHECK("20060904000022AAN", allequal_int4( res_v, r22_v ), 0); + res_v = (vec_int4)ilogbf4(x23_v); + TEST_CHECK("20060904000023AAN", allequal_int4( res_v, r23_v ), 0); + res_v = (vec_int4)ilogbf4(x24_v); + TEST_CHECK("20060904000024AAN", allequal_int4( res_v, r24_v ), 0); + res_v = (vec_int4)ilogbf4(x25_v); + TEST_CHECK("20060904000025AAN", allequal_int4( res_v, r25_v ), 0); + res_v = (vec_int4)ilogbf4(x26_v); + TEST_CHECK("20060904000026AAN", allequal_int4( res_v, r26_v ), 0); + res_v = (vec_int4)ilogbf4(x27_v); + TEST_CHECK("20060904000027AAN", allequal_int4( res_v, r27_v ), 0); + res_v = (vec_int4)ilogbf4(x28_v); + TEST_CHECK("20060904000028AAN", allequal_int4( res_v, r28_v ), 0); + res_v = (vec_int4)ilogbf4(x29_v); + TEST_CHECK("20060904000029AAN", allequal_int4( res_v, r29_v ), 0); + res_v = (vec_int4)ilogbf4(x30_v); + TEST_CHECK("20060904000030AAN", allequal_int4( res_v, r30_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/irintf4.c b/Extras/simdmathlibrary/spu/tests/irintf4.c new file mode 100644 index 0000000..afd1cbc --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/irintf4.c @@ -0,0 +1,96 @@ +/* Test irintf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +#define DEFINE_DATA(val,a,b)\ + float val = hide_float(a); \ + signed int val ## _out =b;\ + vec_float4 val ## _v = spu_splats(val);\ + vec_int4 val ## _out_v = spu_splats(val ## _out); + +#define DEFINE_DATA_UNSIGNED(val,a,b)\ + unsigned int val ## _in = a;\ + float val = make_float(val ## _in);\ + signed int val ## _out = b;\ + vec_float4 val ## _v = spu_splats(val);\ + vec_int4 val ## _out_v = spu_splats(val ## _out); + +#define DO_TEST(var,id) \ + res_v = irintf4(var ## _v); \ + TEST_CHECK(" #id ", allequal_int4( res_v, var ## _out_v ), 0); + +int main() +{ + vec_int4 res_v; + + TEST_SET_START("921537538600","RNT", "irintf4"); + + /* + Define original values and the results + */ + //s=0 + DEFINE_DATA(x1, 1.0, 1) + DEFINE_DATA(x2, -1.0,-1) + + //s=-1 + DEFINE_DATA(x3, 0.5, 0) + DEFINE_DATA(x4, -0.5, 0) + //s=-2 + DEFINE_DATA(x5, 0.25, 0) + //s=-3 + DEFINE_DATA(x6, 0.125, 0) + + //s=0, e=27, f=0 -> 134217728 + DEFINE_DATA_UNSIGNED(x7, 0x4d000000,134217728) + //s=0, e=-126, f=0 --> 0 + DEFINE_DATA_UNSIGNED(x8, 0x800000,0) + + /* TEST */ + TEST_START("irintf4"); + + DO_TEST(x1,921537538601RNT) + DO_TEST(x2,921537538602RNT) + DO_TEST(x3,921537538603RNT) + DO_TEST(x4,921537538604RNT) + DO_TEST(x5,921537538605RNT) + DO_TEST(x6,921537538606RNT) + DO_TEST(x7,921537538607RNT) + DO_TEST(x8,921537538608RNT) + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/iroundf4.c b/Extras/simdmathlibrary/spu/tests/iroundf4.c new file mode 100644 index 0000000..a6d3fe1 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/iroundf4.c @@ -0,0 +1,96 @@ +/* Test iroundf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +#define DEFINE_DATA(val,a,b)\ + float val = hide_float(a); \ + signed int val ## _out =b;\ + vec_float4 val ## _v = spu_splats(val);\ + vec_int4 val ## _out_v = spu_splats(val ## _out); + +#define DEFINE_DATA_UNSIGNED(val,a,b)\ + unsigned int val ## _in = a;\ + float val = make_float(val ## _in);\ + signed int val ## _out = b;\ + vec_float4 val ## _v = spu_splats(val);\ + vec_int4 val ## _out_v = spu_splats(val ## _out); + +#define DO_TEST(var,id) \ + res_v = iroundf4(var ## _v); \ + TEST_CHECK(" #id ", allequal_int4( res_v, var ## _out_v ), 0); + + +int main() +{ + vec_int4 res_v; + + TEST_SET_START("592642590100","RUD", "iroundf4"); + + /* + Define original values and the results + */ + //s=0 + DEFINE_DATA(x1, 1.0, 1.0f) + DEFINE_DATA(x2, -1.0,-1.0f) + //s=-1 + DEFINE_DATA(x3, 0.5, 1.0f) + DEFINE_DATA(x4, -0.5, -1.0f) + //s=-2 + DEFINE_DATA(x5, 0.25, 0.0f) + //s=-3 + DEFINE_DATA(x6, 0.125, 0.0f) + //s=0, e=27, f=0 -> 134217728 + DEFINE_DATA_UNSIGNED(x7, 0x4d000000,134217728) + //s=0, e=-126, f=0 --> 0 + DEFINE_DATA_UNSIGNED(x8, 0x800000,0) + + /* TEST */ + TEST_START("iroundf4"); + + DO_TEST(x1,592642590101RUD) + DO_TEST(x2,592642590102RUD) + DO_TEST(x3,592642590103RUD) + DO_TEST(x4,592642590104RUD) + DO_TEST(x5,592642590105RUD) + DO_TEST(x6,592642590106RUD) + DO_TEST(x7,592642590107RUD) + DO_TEST(x8,592642590108RUD) + + TEST_SET_DONE(); + + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/is0denormd2.c b/Extras/simdmathlibrary/spu/tests/is0denormd2.c new file mode 100644 index 0000000..9433749 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/is0denormd2.c @@ -0,0 +1,225 @@ +/* Test is0denormd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060830000000AAN","AAN", "is0denormd2"); + + // -Nan + double x0 = hide_double(-nan("")); + unsigned long long r0 = 0x0000000000000000ull; + + // -Inf + double x1 = hide_double(-HUGE_VAL); + unsigned long long r1 = 0x0000000000000000ull; + + // -Dmax + double x2 = hide_double(-DBL_MAX); + unsigned long long r2 = 0x0000000000000000ull; + + // -Norm + double x3 = hide_double(-824842.58421394); + unsigned long long r3 = 0x0000000000000000ull; + + // -Dmin + double x4 = hide_double(-DBL_MIN); + unsigned long long r4 = 0x0000000000000000ull; + + // -Denorm + double x5 = hide_double(-2.40e-310); + unsigned long long r5 = 0xffffffffffffffffull; + + // -Unf + double x6 = hide_double(-1.0e-999); + unsigned long long r6 = 0xffffffffffffffffull; + + // -0 + double x7 = hide_double(-0.0); + unsigned long long r7 = 0xffffffffffffffffull; + + // 0 + double x8 = hide_double( 0.0); + unsigned long long r8 = 0xffffffffffffffffull; + + // +Unf + double x9 = hide_double( 1.0e-999); + unsigned long long r9 = 0xffffffffffffffffull; + + // +Denorm + double x10 = hide_double( 2.40e-310); + unsigned long long r10 = 0xffffffffffffffffull; + + // +Dmin + double x11 = hide_double( DBL_MIN); + unsigned long long r11 = 0x0000000000000000ull; + + // +Norm + double x12 = hide_double(3.14152634); + unsigned long long r12 = 0x0000000000000000ull; + + // +Dmax + double x13 = hide_double(DBL_MAX); + unsigned long long r13 = 0x0000000000000000ull; + + // +Inf + double x14 = hide_double( HUGE_VAL); + unsigned long long r14 = 0x0000000000000000ull; + + //+Nan + double x15 = hide_double( nan("")); + unsigned long long r15 = 0x0000000000000000ull; + + // Compound + vec_double2 x16_v = (vec_double2) {make_double(0x000AAAAAAAAAAAAAull), -1.0e-999 }; + vec_ullong2 r16_v = (vec_ullong2) {0xffffffffffffffffull, 0xffffffffffffffffull}; + + // Compound + vec_double2 x17_v = (vec_double2) { 345.27533, -2.40e-310 }; + vec_ullong2 r17_v = (vec_ullong2) {0x0000000000000000ull, 0xffffffffffffffffull}; + + // Compound + vec_double2 x18_v = (vec_double2) { nan(""), -3678342.8765343 }; + vec_ullong2 r18_v = (vec_ullong2) {0x0000000000000000ull, 0x0000000000000000ull}; + + // Compound + vec_double2 x19_v = (vec_double2) { HUGE_VAL, -nan("") }; + vec_ullong2 r19_v = (vec_ullong2) {0x0000000000000000ull, 0x0000000000000000ull}; + + // Compound + vec_double2 x20_v = (vec_double2) { -1.0e-999, -HUGE_VAL} ; + vec_ullong2 r20_v = (vec_ullong2) {0xffffffffffffffffull, 0x0000000000000000ull}; + + vec_double2 x0_v = spu_splats(x0); + vec_ullong2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_ullong2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_ullong2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_ullong2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_ullong2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_ullong2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_ullong2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_ullong2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_ullong2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_ullong2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_ullong2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_ullong2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_ullong2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_ullong2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_ullong2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_ullong2 r15_v = spu_splats(r15); + + vec_ullong2 res_v; + + TEST_START("is0denormd2"); + + res_v = (vec_ullong2)is0denormd2(x0_v); + TEST_CHECK("20060830000000AAN", allequal_ullong2( res_v, r0_v ), 0); + res_v = (vec_ullong2)is0denormd2(x1_v); + TEST_CHECK("20060830000001AAN", allequal_ullong2( res_v, r1_v ), 0); + res_v = (vec_ullong2)is0denormd2(x2_v); + TEST_CHECK("20060830000002AAN", allequal_ullong2( res_v, r2_v ), 0); + res_v = (vec_ullong2)is0denormd2(x3_v); + TEST_CHECK("20060830000003AAN", allequal_ullong2( res_v, r3_v ), 0); + res_v = (vec_ullong2)is0denormd2(x4_v); + TEST_CHECK("20060830000004AAN", allequal_ullong2( res_v, r4_v ), 0); + res_v = (vec_ullong2)is0denormd2(x5_v); + TEST_CHECK("20060830000005AAN", allequal_ullong2( res_v, r5_v ), 0); + res_v = (vec_ullong2)is0denormd2(x6_v); + TEST_CHECK("20060830000006AAN", allequal_ullong2( res_v, r6_v ), 0); + res_v = (vec_ullong2)is0denormd2(x7_v); + TEST_CHECK("20060830000007AAN", allequal_ullong2( res_v, r7_v ), 0); + res_v = (vec_ullong2)is0denormd2(x8_v); + TEST_CHECK("20060830000008AAN", allequal_ullong2( res_v, r8_v ), 0); + res_v = (vec_ullong2)is0denormd2(x9_v); + TEST_CHECK("20060830000009AAN", allequal_ullong2( res_v, r9_v ), 0); + res_v = (vec_ullong2)is0denormd2(x10_v); + TEST_CHECK("20060830000010AAN", allequal_ullong2( res_v, r10_v ), 0); + res_v = (vec_ullong2)is0denormd2(x11_v); + TEST_CHECK("20060830000011AAN", allequal_ullong2( res_v, r11_v ), 0); + res_v = (vec_ullong2)is0denormd2(x12_v); + TEST_CHECK("20060830000012AAN", allequal_ullong2( res_v, r12_v ), 0); + res_v = (vec_ullong2)is0denormd2(x13_v); + TEST_CHECK("20060830000013AAN", allequal_ullong2( res_v, r13_v ), 0); + res_v = (vec_ullong2)is0denormd2(x14_v); + TEST_CHECK("20060830000014AAN", allequal_ullong2( res_v, r14_v ), 0); + res_v = (vec_ullong2)is0denormd2(x15_v); + TEST_CHECK("20060830000015AAN", allequal_ullong2( res_v, r15_v ), 0); + res_v = (vec_ullong2)is0denormd2(x16_v); + TEST_CHECK("20060830000016AAN", allequal_ullong2( res_v, r16_v ), 0); + res_v = (vec_ullong2)is0denormd2(x17_v); + TEST_CHECK("20060830000017AAN", allequal_ullong2( res_v, r17_v ), 0); + res_v = (vec_ullong2)is0denormd2(x18_v); + TEST_CHECK("20060830000018AAN", allequal_ullong2( res_v, r18_v ), 0); + res_v = (vec_ullong2)is0denormd2(x19_v); + TEST_CHECK("20060830000019AAN", allequal_ullong2( res_v, r19_v ), 0); + res_v = (vec_ullong2)is0denormd2(x20_v); + TEST_CHECK("20060830000020AAN", allequal_ullong2( res_v, r20_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/is0denormf4.c b/Extras/simdmathlibrary/spu/tests/is0denormf4.c new file mode 100644 index 0000000..dcb91d6 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/is0denormf4.c @@ -0,0 +1,200 @@ +/* Test is0denormf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060830000000AAN","AAN", "is0denormf4"); + + // -Nan + float x0 = hide_float(-NANF); + unsigned int r0 = 0x00000000; + + // -Inf + float x1 = hide_float(-HUGE_VALF); + unsigned int r1 = 0x00000000; + + // -Smax + float x2 = hide_float(make_float(0xffffffff)); + unsigned int r2 = 0x00000000; + + // -Norm + float x3 = hide_float(-824842.58421394f); + unsigned int r3 = 0x00000000; + + // -Smin + float x4 = hide_float(make_float(0x80800000)); + unsigned int r4 = 0x00000000; + + // -Denorm + float x5 = hide_float(make_float(0x803aaaaa)); + unsigned int r5 = 0xffffffff; + + // -Unf + float x6 = hide_float(-1.0e-999); + unsigned int r6 = 0xffffffff; + + // -0 + float x7 = hide_float(-0.0f); + unsigned int r7 = 0xffffffff; + + // 0 + float x8 = hide_float( 0.0f); + unsigned int r8 = 0xffffffff; + + // +Unf + float x9 = hide_float( 1.0e-999); + unsigned int r9 = 0xffffffff; + + // +Denorm + float x10 = hide_float(make_float(0x003aaaaa)); + unsigned int r10 = 0xffffffff; + + // +Smin + float x11 = hide_float(make_float(0x00800000)); + unsigned int r11 = 0x00000000; + + // +Norm + float x12 = hide_float(3.14152634f); + unsigned int r12 = 0x00000000; + + // +Smax + float x13 = hide_float(make_float(0x7fffffff)); + unsigned int r13 = 0x00000000; + + // +Inf + float x14 = hide_float( HUGE_VALF); + unsigned int r14 = 0x00000000; + + //+Nan + float x15 = hide_float(NANF); + unsigned int r15 = 0x00000000; + + // Compound + vec_float4 x16_v = (vec_float4) {make_float(0x003AAAAA), -1.0e-999, 345.27533, make_float(0x803AAAAA)}; + vec_uint4 r16_v = (vec_uint4) {0xffffffff, 0xffffffff, 0x00000000, 0xffffffff}; + + vec_float4 x0_v = spu_splats(x0); + vec_uint4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_uint4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_uint4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_uint4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_uint4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_uint4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_uint4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_uint4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_uint4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_uint4 r9_v = spu_splats(r9); + + vec_float4 x10_v = spu_splats(x10); + vec_uint4 r10_v = spu_splats(r10); + + vec_float4 x11_v = spu_splats(x11); + vec_uint4 r11_v = spu_splats(r11); + + vec_float4 x12_v = spu_splats(x12); + vec_uint4 r12_v = spu_splats(r12); + + vec_float4 x13_v = spu_splats(x13); + vec_uint4 r13_v = spu_splats(r13); + + vec_float4 x14_v = spu_splats(x14); + vec_uint4 r14_v = spu_splats(r14); + + vec_float4 x15_v = spu_splats(x15); + vec_uint4 r15_v = spu_splats(r15); + + vec_uint4 res_v; + + TEST_START("is0denormf4"); + + res_v = (vec_uint4)is0denormf4(x0_v); + TEST_CHECK("20060830000000AAN", allequal_uint4( res_v, r0_v ), 0); + res_v = (vec_uint4)is0denormf4(x1_v); + TEST_CHECK("20060830000001AAN", allequal_uint4( res_v, r1_v ), 0); + res_v = (vec_uint4)is0denormf4(x2_v); + TEST_CHECK("20060830000002AAN", allequal_uint4( res_v, r2_v ), 0); + res_v = (vec_uint4)is0denormf4(x3_v); + TEST_CHECK("20060830000003AAN", allequal_uint4( res_v, r3_v ), 0); + res_v = (vec_uint4)is0denormf4(x4_v); + TEST_CHECK("20060830000004AAN", allequal_uint4( res_v, r4_v ), 0); + res_v = (vec_uint4)is0denormf4(x5_v); + TEST_CHECK("20060830000005AAN", allequal_uint4( res_v, r5_v ), 0); + res_v = (vec_uint4)is0denormf4(x6_v); + TEST_CHECK("20060830000006AAN", allequal_uint4( res_v, r6_v ), 0); + res_v = (vec_uint4)is0denormf4(x7_v); + TEST_CHECK("20060830000007AAN", allequal_uint4( res_v, r7_v ), 0); + res_v = (vec_uint4)is0denormf4(x8_v); + TEST_CHECK("20060830000008AAN", allequal_uint4( res_v, r8_v ), 0); + res_v = (vec_uint4)is0denormf4(x9_v); + TEST_CHECK("20060830000009AAN", allequal_uint4( res_v, r9_v ), 0); + res_v = (vec_uint4)is0denormf4(x10_v); + TEST_CHECK("20060830000010AAN", allequal_uint4( res_v, r10_v ), 0); + res_v = (vec_uint4)is0denormf4(x11_v); + TEST_CHECK("20060830000011AAN", allequal_uint4( res_v, r11_v ), 0); + res_v = (vec_uint4)is0denormf4(x12_v); + TEST_CHECK("20060830000012AAN", allequal_uint4( res_v, r12_v ), 0); + res_v = (vec_uint4)is0denormf4(x13_v); + TEST_CHECK("20060830000013AAN", allequal_uint4( res_v, r13_v ), 0); + res_v = (vec_uint4)is0denormf4(x14_v); + TEST_CHECK("20060830000014AAN", allequal_uint4( res_v, r14_v ), 0); + res_v = (vec_uint4)is0denormf4(x15_v); + TEST_CHECK("20060830000015AAN", allequal_uint4( res_v, r15_v ), 0); + res_v = (vec_uint4)is0denormf4(x16_v); + TEST_CHECK("20060830000016AAN", allequal_uint4( res_v, r16_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/isequald2.c b/Extras/simdmathlibrary/spu/tests/isequald2.c new file mode 100644 index 0000000..5e80be8 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/isequald2.c @@ -0,0 +1,271 @@ +/* Test isequald2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060825000000AAN","AAN", "isequald2"); + + //-QNaN: NG + double x0 = hide_double(-nan("")); + double y0 = hide_double(1.0); + unsigned long long r0 = 0x0000000000000000ull; + + //+Inf > -Inf + double x1 = hide_double( HUGE_VAL); + double y1 = hide_double(-HUGE_VAL); + unsigned long long r1 = 0x0000000000000000ull; + + //-Inf < -Dmax + double x2 = hide_double(-HUGE_VAL); + double y2 = hide_double(-DBL_MAX); + unsigned long long r2 = 0x0000000000000000ull; + + //-Norm > -Inf + double x3 = hide_double(-67418234.34256245); + double y3 = hide_double(-HUGE_VAL); + unsigned long long r3 = 0x0000000000000000ull; + + //-Norm < -Denorm + double x4 = hide_double(-273453.3234458053); + double y4 = hide_double(-3.0e-321); + unsigned long long r4 = 0x0000000000000000ull; + + //-Norm = -Norm + double x5 = hide_double(-168.97345223013); + double y5 = hide_double(-168.97345223013); + unsigned long long r5 = 0xffffffffffffffffull; + + //-Norm > -Norm + double x6 = hide_double(-168.97345223013); + double y6 = hide_double(-21345853556.492); + unsigned long long r6 = 0x0000000000000000ull; + + //-Norm < -0 + double x7 = hide_double(-168.97345223013); + double y7 = hide_double(-0.0); + unsigned long long r7 = 0x0000000000000000ull; + + //-Unf > -Norm + double x8 = hide_double(-1.0e-999); + double y8 = hide_double(-83532.96153153); + unsigned long long r8 = 0x0000000000000000ull; + + //-Unf = 0 + double x9 = hide_double(-1.0e-999); + double y9 = hide_double(0.0); + unsigned long long r9 = 0xffffffffffffffffull; + + //-0 = 0 + double x10 = hide_double(-0.0); + double y10 = hide_double( 0.0); + unsigned long long r10 = 0xffffffffffffffffull; + + //+Unf = 0 + double x11 = hide_double( 1.0e-999); + double y11 = hide_double( 0.0); + unsigned long long r11 = 0xffffffffffffffffull; + + //+Unf < +Norm + double x12 = hide_double( 1e-999); + double y12 = hide_double(0.0031529324); + unsigned long long r12 = 0x0000000000000000ull; + + //+Norm > +Denorm + double x13 = hide_double(5172.2845321); + double y13 = hide_double(3.0e-321); + unsigned long long r13 = 0x0000000000000000ull; + + //+Norm = +Norm + double x14 = hide_double(5172.2845321); + double y14 = hide_double(5172.2845321); + unsigned long long r14 = 0xffffffffffffffffull; + + //+Norm < +Norm + double x15 = hide_double(264.345643345); + double y15 = hide_double(2353705.31415); + unsigned long long r15 = 0x0000000000000000ull; + + //+Norm > -Norm + double x16 = hide_double( 926.605118542); + double y16 = hide_double(-9.43574552184); + unsigned long long r16 = 0x0000000000000000ull; + + //+Norm < +Dmax + double x17 = hide_double( 926.605118542); + double y17 = hide_double(DBL_MAX); + unsigned long long r17 = 0x0000000000000000ull; + + //+Inf > +Dmax + double x18 = hide_double(HUGE_VAL); + double y18 = hide_double(DBL_MAX); + unsigned long long r18 = 0x0000000000000000ull; + + //+QNaN: NG + double x19 = hide_double(nan("")); + double y19 = hide_double(3.14); + unsigned long long r19 = 0x0000000000000000ull; + + vec_double2 x0_v = spu_splats(x0); + vec_double2 y0_v = spu_splats(y0); + vec_ullong2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_double2 y1_v = spu_splats(y1); + vec_ullong2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_double2 y2_v = spu_splats(y2); + vec_ullong2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_double2 y3_v = spu_splats(y3); + vec_ullong2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_double2 y4_v = spu_splats(y4); + vec_ullong2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_double2 y5_v = spu_splats(y5); + vec_ullong2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_double2 y6_v = spu_splats(y6); + vec_ullong2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_double2 y7_v = spu_splats(y7); + vec_ullong2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_double2 y8_v = spu_splats(y8); + vec_ullong2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_double2 y9_v = spu_splats(y9); + vec_ullong2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_double2 y10_v = spu_splats(y10); + vec_ullong2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_double2 y11_v = spu_splats(y11); + vec_ullong2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_double2 y12_v = spu_splats(y12); + vec_ullong2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_double2 y13_v = spu_splats(y13); + vec_ullong2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_double2 y14_v = spu_splats(y14); + vec_ullong2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_double2 y15_v = spu_splats(y15); + vec_ullong2 r15_v = spu_splats(r15); + + vec_double2 x16_v = spu_splats(x16); + vec_double2 y16_v = spu_splats(y16); + vec_ullong2 r16_v = spu_splats(r16); + + vec_double2 x17_v = spu_splats(x17); + vec_double2 y17_v = spu_splats(y17); + vec_ullong2 r17_v = spu_splats(r17); + + vec_double2 x18_v = spu_splats(x18); + vec_double2 y18_v = spu_splats(y18); + vec_ullong2 r18_v = spu_splats(r18); + + vec_double2 x19_v = spu_splats(x19); + vec_double2 y19_v = spu_splats(y19); + vec_ullong2 r19_v = spu_splats(r19); + + vec_ullong2 res_v; + + TEST_START("isequald2"); + + res_v = (vec_ullong2)isequald2(x0_v, y0_v); + TEST_CHECK("20060825000000AAN", allequal_ullong2( res_v, r0_v ), 0); + res_v = (vec_ullong2)isequald2(x1_v, y1_v); + TEST_CHECK("20060825000001AAN", allequal_ullong2( res_v, r1_v ), 0); + res_v = (vec_ullong2)isequald2(x2_v, y2_v); + TEST_CHECK("20060825000002AAN", allequal_ullong2( res_v, r2_v ), 0); + res_v = (vec_ullong2)isequald2(x3_v, y3_v); + TEST_CHECK("20060825000003AAN", allequal_ullong2( res_v, r3_v ), 0); + res_v = (vec_ullong2)isequald2(x4_v, y4_v); + TEST_CHECK("20060825000004AAN", allequal_ullong2( res_v, r4_v ), 0); + res_v = (vec_ullong2)isequald2(x5_v, y5_v); + TEST_CHECK("20060825000005AAN", allequal_ullong2( res_v, r5_v ), 0); + res_v = (vec_ullong2)isequald2(x6_v, y6_v); + TEST_CHECK("20060825000006AAN", allequal_ullong2( res_v, r6_v ), 0); + res_v = (vec_ullong2)isequald2(x7_v, y7_v); + TEST_CHECK("20060825000007AAN", allequal_ullong2( res_v, r7_v ), 0); + res_v = (vec_ullong2)isequald2(x8_v, y8_v); + TEST_CHECK("20060825000008AAN", allequal_ullong2( res_v, r8_v ), 0); + res_v = (vec_ullong2)isequald2(x9_v, y9_v); + TEST_CHECK("20060825000009AAN", allequal_ullong2( res_v, r9_v ), 0); + res_v = (vec_ullong2)isequald2(x10_v, y10_v); + TEST_CHECK("20060825000000AAN", allequal_ullong2( res_v, r10_v ), 0); + res_v = (vec_ullong2)isequald2(x11_v, y11_v); + TEST_CHECK("20060825000001AAN", allequal_ullong2( res_v, r11_v ), 0); + res_v = (vec_ullong2)isequald2(x12_v, y12_v); + TEST_CHECK("20060825000002AAN", allequal_ullong2( res_v, r12_v ), 0); + res_v = (vec_ullong2)isequald2(x13_v, y13_v); + TEST_CHECK("20060825000003AAN", allequal_ullong2( res_v, r13_v ), 0); + res_v = (vec_ullong2)isequald2(x14_v, y14_v); + TEST_CHECK("20060825000004AAN", allequal_ullong2( res_v, r14_v ), 0); + res_v = (vec_ullong2)isequald2(x15_v, y15_v); + TEST_CHECK("20060825000005AAN", allequal_ullong2( res_v, r15_v ), 0); + res_v = (vec_ullong2)isequald2(x16_v, y16_v); + TEST_CHECK("20060825000006AAN", allequal_ullong2( res_v, r16_v ), 0); + res_v = (vec_ullong2)isequald2(x17_v, y17_v); + TEST_CHECK("20060825000007AAN", allequal_ullong2( res_v, r17_v ), 0); + res_v = (vec_ullong2)isequald2(x18_v, y18_v); + TEST_CHECK("20060825000008AAN", allequal_ullong2( res_v, r18_v ), 0); + res_v = (vec_ullong2)isequald2(x19_v, y19_v); + TEST_CHECK("20060825000009AAN", allequal_ullong2( res_v, r19_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/isequalf4.c b/Extras/simdmathlibrary/spu/tests/isequalf4.c new file mode 100644 index 0000000..52c5ad5 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/isequalf4.c @@ -0,0 +1,151 @@ +/* Test isequalf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060817000000AAN","AAN", "isequalf4"); + + float x0 = hide_float(-0.0f); + float y0 = hide_float( 0.0f); + unsigned int r0 = 0xffffffff; + + float x1 = hide_float(FLT_MAX); //+Smax + float y1 = hide_float(-FLT_MAX); //-Smax + unsigned int r1 = 0x00000000; + + float x2 = hide_float(-0.0000000013152f); + float y2 = hide_float(-234245.85323441f); + unsigned int r2 = 0x00000000; + + float x3 = hide_float(-168.97345223013f); + float y3 = hide_float(-168.97345223013f); + unsigned int r3 = 0xffffffff; + + float x4 = hide_float(-83532.96153153f); + float y4 = hide_float(-1e-999); //-Smin + unsigned int r4 = 0x00000000; + + float x5 = hide_float(-321.01234567f); + float y5 = hide_float(876543.12345f); + unsigned int r5 = 0x00000000; + + float x6 = hide_float( 1e-999); // Smin + float y6 = hide_float(0.0031529324f); + unsigned int r6 = 0x00000000; + + float x7 = hide_float(5172.2845321f); + float y7 = hide_float(5172.2845321f); + unsigned int r7 = 0xffffffff; + + float x8 = hide_float(264.345643345f); + float y8 = hide_float(2353705.31415f); + unsigned int r8 = 0x00000000; + + float x9 = hide_float(FLT_MAX); // Smax + float y9 = hide_float(9.43574552184f); + unsigned int r9 = 0x00000000; + + vec_float4 x0_v = spu_splats(x0); + vec_float4 y0_v = spu_splats(y0); + vec_uint4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_float4 y1_v = spu_splats(y1); + vec_uint4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_float4 y2_v = spu_splats(y2); + vec_uint4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_float4 y3_v = spu_splats(y3); + vec_uint4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_float4 y4_v = spu_splats(y4); + vec_uint4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_float4 y5_v = spu_splats(y5); + vec_uint4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_float4 y6_v = spu_splats(y6); + vec_uint4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_float4 y7_v = spu_splats(y7); + vec_uint4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_float4 y8_v = spu_splats(y8); + vec_uint4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_float4 y9_v = spu_splats(y9); + vec_uint4 r9_v = spu_splats(r9); + + vec_uint4 res_v; + + TEST_START("isequalf4"); + + res_v = (vec_uint4)isequalf4(x0_v, y0_v); + TEST_CHECK("20060817000000AAN", allequal_uint4( res_v, r0_v ), 0); + res_v = (vec_uint4)isequalf4(x1_v, y1_v); + TEST_CHECK("20060817000001AAN", allequal_uint4( res_v, r1_v ), 0); + res_v = (vec_uint4)isequalf4(x2_v, y2_v); + TEST_CHECK("20060817000002AAN", allequal_uint4( res_v, r2_v ), 0); + res_v = (vec_uint4)isequalf4(x3_v, y3_v); + TEST_CHECK("20060817000003AAN", allequal_uint4( res_v, r3_v ), 0); + res_v = (vec_uint4)isequalf4(x4_v, y4_v); + TEST_CHECK("20060817000004AAN", allequal_uint4( res_v, r4_v ), 0); + res_v = (vec_uint4)isequalf4(x5_v, y5_v); + TEST_CHECK("20060817000005AAN", allequal_uint4( res_v, r5_v ), 0); + res_v = (vec_uint4)isequalf4(x6_v, y6_v); + TEST_CHECK("20060817000006AAN", allequal_uint4( res_v, r6_v ), 0); + res_v = (vec_uint4)isequalf4(x7_v, y7_v); + TEST_CHECK("20060817000007AAN", allequal_uint4( res_v, r7_v ), 0); + res_v = (vec_uint4)isequalf4(x8_v, y8_v); + TEST_CHECK("20060817000008AAN", allequal_uint4( res_v, r8_v ), 0); + res_v = (vec_uint4)isequalf4(x9_v, y9_v); + TEST_CHECK("20060817000009AAN", allequal_uint4( res_v, r9_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/isfinited2.c b/Extras/simdmathlibrary/spu/tests/isfinited2.c new file mode 100644 index 0000000..7981955 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/isfinited2.c @@ -0,0 +1,225 @@ +/* Test isfinited2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060830000000AAN","AAN", "isfinited2"); + + // -Nan + double x0 = hide_double(-nan("")); + unsigned long long r0 = 0x0000000000000000ull; + + // -Inf + double x1 = hide_double(-HUGE_VAL); + unsigned long long r1 = 0x0000000000000000ull; + + // -Dmax + double x2 = hide_double(-DBL_MAX); + unsigned long long r2 = 0xffffffffffffffffull; + + // -Norm + double x3 = hide_double(-824842.58421394); + unsigned long long r3 = 0xffffffffffffffffull; + + // -Dmin + double x4 = hide_double(-DBL_MIN); + unsigned long long r4 = 0xffffffffffffffffull; + + // -Denorm + double x5 = hide_double(-2.40e-310); + unsigned long long r5 = 0xffffffffffffffffull; + + // -Unf + double x6 = hide_double(-1.0e-999); + unsigned long long r6 = 0xffffffffffffffffull; + + // -0 + double x7 = hide_double(-0.0); + unsigned long long r7 = 0xffffffffffffffffull; + + // 0 + double x8 = hide_double( 0.0); + unsigned long long r8 = 0xffffffffffffffffull; + + // +Unf + double x9 = hide_double( 1.0e-999); + unsigned long long r9 = 0xffffffffffffffffull; + + // +Denorm + double x10 = hide_double( 2.40e-310); + unsigned long long r10 = 0xffffffffffffffffull; + + // +Dmin + double x11 = hide_double( DBL_MIN); + unsigned long long r11 = 0xffffffffffffffffull; + + // +Norm + double x12 = hide_double(3.14152634); + unsigned long long r12 = 0xffffffffffffffffull; + + // +Dmax + double x13 = hide_double(DBL_MAX); + unsigned long long r13 = 0xffffffffffffffffull; + + // +Inf + double x14 = hide_double(HUGE_VAL); + unsigned long long r14 = 0x0000000000000000ull; + + //+Nan + double x15 = hide_double( nan("")); + unsigned long long r15 = 0x0000000000000000ull; + + // Compound + vec_double2 x16_v = (vec_double2) {make_double(0x000AAAAAAAAAAAAAull), -1.0e-999 }; + vec_ullong2 r16_v = (vec_ullong2) {0xffffffffffffffffull, 0xffffffffffffffffull}; + + // Compound + vec_double2 x17_v = (vec_double2) { 345.27533, -2.40e-310 }; + vec_ullong2 r17_v = (vec_ullong2) {0xffffffffffffffffull, 0xffffffffffffffffull}; + + // Compound + vec_double2 x18_v = (vec_double2) { nan(""), -3678342.8765343 }; + vec_ullong2 r18_v = (vec_ullong2) {0x0000000000000000ull, 0xffffffffffffffffull}; + + // Compound + vec_double2 x19_v = (vec_double2) { HUGE_VAL, -nan("") }; + vec_ullong2 r19_v = (vec_ullong2) {0x0000000000000000ull, 0x0000000000000000ull}; + + // Compound + vec_double2 x20_v = (vec_double2) { -1.0e-999, -HUGE_VAL} ; + vec_ullong2 r20_v = (vec_ullong2) {0xffffffffffffffffull, 0x0000000000000000ull}; + + vec_double2 x0_v = spu_splats(x0); + vec_ullong2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_ullong2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_ullong2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_ullong2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_ullong2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_ullong2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_ullong2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_ullong2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_ullong2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_ullong2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_ullong2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_ullong2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_ullong2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_ullong2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_ullong2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_ullong2 r15_v = spu_splats(r15); + + vec_ullong2 res_v; + + TEST_START("isfinited2"); + + res_v = (vec_ullong2)isfinited2(x0_v); + TEST_CHECK("20060830000000AAN", allequal_ullong2( res_v, r0_v ), 0); + res_v = (vec_ullong2)isfinited2(x1_v); + TEST_CHECK("20060830000001AAN", allequal_ullong2( res_v, r1_v ), 0); + res_v = (vec_ullong2)isfinited2(x2_v); + TEST_CHECK("20060830000002AAN", allequal_ullong2( res_v, r2_v ), 0); + res_v = (vec_ullong2)isfinited2(x3_v); + TEST_CHECK("20060830000003AAN", allequal_ullong2( res_v, r3_v ), 0); + res_v = (vec_ullong2)isfinited2(x4_v); + TEST_CHECK("20060830000004AAN", allequal_ullong2( res_v, r4_v ), 0); + res_v = (vec_ullong2)isfinited2(x5_v); + TEST_CHECK("20060830000005AAN", allequal_ullong2( res_v, r5_v ), 0); + res_v = (vec_ullong2)isfinited2(x6_v); + TEST_CHECK("20060830000006AAN", allequal_ullong2( res_v, r6_v ), 0); + res_v = (vec_ullong2)isfinited2(x7_v); + TEST_CHECK("20060830000007AAN", allequal_ullong2( res_v, r7_v ), 0); + res_v = (vec_ullong2)isfinited2(x8_v); + TEST_CHECK("20060830000008AAN", allequal_ullong2( res_v, r8_v ), 0); + res_v = (vec_ullong2)isfinited2(x9_v); + TEST_CHECK("20060830000009AAN", allequal_ullong2( res_v, r9_v ), 0); + res_v = (vec_ullong2)isfinited2(x10_v); + TEST_CHECK("20060830000010AAN", allequal_ullong2( res_v, r10_v ), 0); + res_v = (vec_ullong2)isfinited2(x11_v); + TEST_CHECK("20060830000011AAN", allequal_ullong2( res_v, r11_v ), 0); + res_v = (vec_ullong2)isfinited2(x12_v); + TEST_CHECK("20060830000012AAN", allequal_ullong2( res_v, r12_v ), 0); + res_v = (vec_ullong2)isfinited2(x13_v); + TEST_CHECK("20060830000013AAN", allequal_ullong2( res_v, r13_v ), 0); + res_v = (vec_ullong2)isfinited2(x14_v); + TEST_CHECK("20060830000014AAN", allequal_ullong2( res_v, r14_v ), 0); + res_v = (vec_ullong2)isfinited2(x15_v); + TEST_CHECK("20060830000015AAN", allequal_ullong2( res_v, r15_v ), 0); + res_v = (vec_ullong2)isfinited2(x16_v); + TEST_CHECK("20060830000016AAN", allequal_ullong2( res_v, r16_v ), 0); + res_v = (vec_ullong2)isfinited2(x17_v); + TEST_CHECK("20060830000017AAN", allequal_ullong2( res_v, r17_v ), 0); + res_v = (vec_ullong2)isfinited2(x18_v); + TEST_CHECK("20060830000018AAN", allequal_ullong2( res_v, r18_v ), 0); + res_v = (vec_ullong2)isfinited2(x19_v); + TEST_CHECK("20060830000019AAN", allequal_ullong2( res_v, r19_v ), 0); + res_v = (vec_ullong2)isfinited2(x20_v); + TEST_CHECK("20060830000020AAN", allequal_ullong2( res_v, r20_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/isfinitef4.c b/Extras/simdmathlibrary/spu/tests/isfinitef4.c new file mode 100644 index 0000000..aff25a2 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/isfinitef4.c @@ -0,0 +1,131 @@ +/* Test isfinitef4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060822000000AAN","AAN", "isfinitef4"); + + float x0 = hide_float(-0.0f); + unsigned int r0 = 0xffffffff; + + float x1 = hide_float(-FLT_MAX); //-Smax + unsigned int r1 = 0xffffffff; + + float x2 = hide_float(-0.0000000013152f); + unsigned int r2 = 0xffffffff; + + float x3 = hide_float(-168.97345223013f); + unsigned int r3 = 0xffffffff; + + float x4 = hide_float(-1e-999); //-Smin + unsigned int r4 = 0xffffffff; + + float x5 = hide_float(876543.12345f); + unsigned int r5 = 0xffffffff; + + float x6 = hide_float( 1e-999); // Smin + unsigned int r6 = 0xffffffff; + + float x7 = hide_float(5172.2845321f); + unsigned int r7 = 0xffffffff; + + float x8 = hide_float(2353705.31415f); + unsigned int r8 = 0xffffffff; + + float x9 = hide_float(FLT_MAX); // Smax + unsigned int r9 = 0xffffffff; + + vec_float4 x0_v = spu_splats(x0); + vec_uint4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_uint4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_uint4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_uint4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_uint4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_uint4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_uint4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_uint4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_uint4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_uint4 r9_v = spu_splats(r9); + + vec_uint4 res_v; + + TEST_START("isfinitef4"); + + res_v = (vec_uint4)isfinitef4(x0_v); + TEST_CHECK("20060822000000AAN", allequal_uint4( res_v, r0_v ), 0); + res_v = (vec_uint4)isfinitef4(x1_v); + TEST_CHECK("20060822000001AAN", allequal_uint4( res_v, r1_v ), 0); + res_v = (vec_uint4)isfinitef4(x2_v); + TEST_CHECK("20060822000002AAN", allequal_uint4( res_v, r2_v ), 0); + res_v = (vec_uint4)isfinitef4(x3_v); + TEST_CHECK("20060822000003AAN", allequal_uint4( res_v, r3_v ), 0); + res_v = (vec_uint4)isfinitef4(x4_v); + TEST_CHECK("20060822000004AAN", allequal_uint4( res_v, r4_v ), 0); + res_v = (vec_uint4)isfinitef4(x5_v); + TEST_CHECK("20060822000005AAN", allequal_uint4( res_v, r5_v ), 0); + res_v = (vec_uint4)isfinitef4(x6_v); + TEST_CHECK("20060822000006AAN", allequal_uint4( res_v, r6_v ), 0); + res_v = (vec_uint4)isfinitef4(x7_v); + TEST_CHECK("20060822000007AAN", allequal_uint4( res_v, r7_v ), 0); + res_v = (vec_uint4)isfinitef4(x8_v); + TEST_CHECK("20060822000008AAN", allequal_uint4( res_v, r8_v ), 0); + res_v = (vec_uint4)isfinitef4(x9_v); + TEST_CHECK("20060822000009AAN", allequal_uint4( res_v, r9_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/isgreaterd2.c b/Extras/simdmathlibrary/spu/tests/isgreaterd2.c new file mode 100644 index 0000000..5c4ff59 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/isgreaterd2.c @@ -0,0 +1,271 @@ +/* Test isgreaterd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060825000000AAN","AAN", "isgreaterd2"); + + //-QNaN: NG + double x0 = hide_double(-nan("")); + double y0 = hide_double(1.0); + unsigned long long r0 = 0x0000000000000000ull; + + //+Inf > -Inf + double x1 = hide_double( HUGE_VAL); + double y1 = hide_double(-HUGE_VAL); + unsigned long long r1 = 0xffffffffffffffffull; + + //-Inf < -Dmax + double x2 = hide_double(-HUGE_VAL); + double y2 = hide_double(-DBL_MAX); + unsigned long long r2 = 0x0000000000000000ull; + + //-Norm > -Inf + double x3 = hide_double(-67418234.34256245); + double y3 = hide_double(-HUGE_VAL); + unsigned long long r3 = 0xffffffffffffffffull; + + //-Norm < -Denorm + double x4 = hide_double(-273453.3234458053); + double y4 = hide_double(-3.0e-321); + unsigned long long r4 = 0x0000000000000000ull; + + //-Norm = -Norm + double x5 = hide_double(-168.97345223013); + double y5 = hide_double(-168.97345223013); + unsigned long long r5 = 0x0000000000000000ull; + + //-Norm > -Norm + double x6 = hide_double(-168.97345223013); + double y6 = hide_double(-21345853556.492); + unsigned long long r6 = 0xffffffffffffffffull; + + //-Norm < -0 + double x7 = hide_double(-168.97345223013); + double y7 = hide_double(-0.0); + unsigned long long r7 = 0x0000000000000000ull; + + //-Unf > -Norm + double x8 = hide_double(-1.0e-999); + double y8 = hide_double(-83532.96153153); + unsigned long long r8 = 0xffffffffffffffffull; + + //-Unf = 0 + double x9 = hide_double(-1.0e-999); + double y9 = hide_double(0.0); + unsigned long long r9 = 0x0000000000000000ull; + + //-0 = 0 + double x10 = hide_double(-0.0); + double y10 = hide_double( 0.0); + unsigned long long r10 = 0x0000000000000000ull; + + //+Unf = 0 + double x11 = hide_double( 1.0e-999); + double y11 = hide_double( 0.0); + unsigned long long r11 = 0x0000000000000000ull; + + //+Unf < +Norm + double x12 = hide_double( 1e-999); + double y12 = hide_double(0.0031529324); + unsigned long long r12 = 0x0000000000000000ull; + + //+Norm > +Denorm + double x13 = hide_double(5172.2845321); + double y13 = hide_double(3.0e-321); + unsigned long long r13 = 0xffffffffffffffffull; + + //+Norm = +Norm + double x14 = hide_double(5172.2845321); + double y14 = hide_double(5172.2845321); + unsigned long long r14 = 0x0000000000000000ull; + + //+Norm < +Norm + double x15 = hide_double(264.345643345); + double y15 = hide_double(2353705.31415); + unsigned long long r15 = 0x0000000000000000ull; + + //+Norm > -Norm + double x16 = hide_double( 926.605118542); + double y16 = hide_double(-9.43574552184); + unsigned long long r16 = 0xffffffffffffffffull; + + //+Norm < +Dmax + double x17 = hide_double( 926.605118542); + double y17 = hide_double(DBL_MAX); + unsigned long long r17 = 0x0000000000000000ull; + + //+Inf > +Dmax + double x18 = hide_double(HUGE_VAL); + double y18 = hide_double(DBL_MAX); + unsigned long long r18 = 0xffffffffffffffffull; + + //+QNaN: NG + double x19 = hide_double(nan("")); + double y19 = hide_double(3.14); + unsigned long long r19 = 0x0000000000000000ull; + + vec_double2 x0_v = spu_splats(x0); + vec_double2 y0_v = spu_splats(y0); + vec_ullong2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_double2 y1_v = spu_splats(y1); + vec_ullong2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_double2 y2_v = spu_splats(y2); + vec_ullong2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_double2 y3_v = spu_splats(y3); + vec_ullong2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_double2 y4_v = spu_splats(y4); + vec_ullong2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_double2 y5_v = spu_splats(y5); + vec_ullong2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_double2 y6_v = spu_splats(y6); + vec_ullong2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_double2 y7_v = spu_splats(y7); + vec_ullong2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_double2 y8_v = spu_splats(y8); + vec_ullong2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_double2 y9_v = spu_splats(y9); + vec_ullong2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_double2 y10_v = spu_splats(y10); + vec_ullong2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_double2 y11_v = spu_splats(y11); + vec_ullong2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_double2 y12_v = spu_splats(y12); + vec_ullong2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_double2 y13_v = spu_splats(y13); + vec_ullong2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_double2 y14_v = spu_splats(y14); + vec_ullong2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_double2 y15_v = spu_splats(y15); + vec_ullong2 r15_v = spu_splats(r15); + + vec_double2 x16_v = spu_splats(x16); + vec_double2 y16_v = spu_splats(y16); + vec_ullong2 r16_v = spu_splats(r16); + + vec_double2 x17_v = spu_splats(x17); + vec_double2 y17_v = spu_splats(y17); + vec_ullong2 r17_v = spu_splats(r17); + + vec_double2 x18_v = spu_splats(x18); + vec_double2 y18_v = spu_splats(y18); + vec_ullong2 r18_v = spu_splats(r18); + + vec_double2 x19_v = spu_splats(x19); + vec_double2 y19_v = spu_splats(y19); + vec_ullong2 r19_v = spu_splats(r19); + + vec_ullong2 res_v; + + TEST_START("isgreaterd2"); + + res_v = (vec_ullong2)isgreaterd2(x0_v, y0_v); + TEST_CHECK("20060825000000AAN", allequal_ullong2( res_v, r0_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x1_v, y1_v); + TEST_CHECK("20060825000001AAN", allequal_ullong2( res_v, r1_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x2_v, y2_v); + TEST_CHECK("20060825000002AAN", allequal_ullong2( res_v, r2_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x3_v, y3_v); + TEST_CHECK("20060825000003AAN", allequal_ullong2( res_v, r3_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x4_v, y4_v); + TEST_CHECK("20060825000004AAN", allequal_ullong2( res_v, r4_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x5_v, y5_v); + TEST_CHECK("20060825000005AAN", allequal_ullong2( res_v, r5_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x6_v, y6_v); + TEST_CHECK("20060825000006AAN", allequal_ullong2( res_v, r6_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x7_v, y7_v); + TEST_CHECK("20060825000007AAN", allequal_ullong2( res_v, r7_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x8_v, y8_v); + TEST_CHECK("20060825000008AAN", allequal_ullong2( res_v, r8_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x9_v, y9_v); + TEST_CHECK("20060825000009AAN", allequal_ullong2( res_v, r9_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x10_v, y10_v); + TEST_CHECK("20060825000000AAN", allequal_ullong2( res_v, r10_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x11_v, y11_v); + TEST_CHECK("20060825000001AAN", allequal_ullong2( res_v, r11_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x12_v, y12_v); + TEST_CHECK("20060825000002AAN", allequal_ullong2( res_v, r12_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x13_v, y13_v); + TEST_CHECK("20060825000003AAN", allequal_ullong2( res_v, r13_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x14_v, y14_v); + TEST_CHECK("20060825000004AAN", allequal_ullong2( res_v, r14_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x15_v, y15_v); + TEST_CHECK("20060825000005AAN", allequal_ullong2( res_v, r15_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x16_v, y16_v); + TEST_CHECK("20060825000006AAN", allequal_ullong2( res_v, r16_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x17_v, y17_v); + TEST_CHECK("20060825000007AAN", allequal_ullong2( res_v, r17_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x18_v, y18_v); + TEST_CHECK("20060825000008AAN", allequal_ullong2( res_v, r18_v ), 0); + res_v = (vec_ullong2)isgreaterd2(x19_v, y19_v); + TEST_CHECK("20060825000009AAN", allequal_ullong2( res_v, r19_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/isgreaterequald2.c b/Extras/simdmathlibrary/spu/tests/isgreaterequald2.c new file mode 100644 index 0000000..00bf97a --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/isgreaterequald2.c @@ -0,0 +1,271 @@ +/* Test isgreaterequald2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060825000000AAN","AAN", "isgreaterequald2"); + + //-QNaN: NG + double x0 = hide_double(-nan("")); + double y0 = hide_double(1.0); + unsigned long long r0 = 0x0000000000000000ull; + + //+Inf > -Inf + double x1 = hide_double( HUGE_VAL); + double y1 = hide_double(-HUGE_VAL); + unsigned long long r1 = 0xffffffffffffffffull; + + //-Inf < -Dmax + double x2 = hide_double(-HUGE_VAL); + double y2 = hide_double(-DBL_MAX); + unsigned long long r2 = 0x0000000000000000ull; + + //-Norm > -Inf + double x3 = hide_double(-67418234.34256245); + double y3 = hide_double(-HUGE_VAL); + unsigned long long r3 = 0xffffffffffffffffull; + + //-Norm < -Denorm + double x4 = hide_double(-273453.3234458053); + double y4 = hide_double(-3.0e-321); + unsigned long long r4 = 0x0000000000000000ull; + + //-Norm = -Norm + double x5 = hide_double(-168.97345223013); + double y5 = hide_double(-168.97345223013); + unsigned long long r5 = 0xffffffffffffffffull; + + //-Norm > -Norm + double x6 = hide_double(-168.97345223013); + double y6 = hide_double(-21345853556.492); + unsigned long long r6 = 0xffffffffffffffffull; + + //-Norm < -0 + double x7 = hide_double(-168.97345223013); + double y7 = hide_double(-0.0); + unsigned long long r7 = 0x0000000000000000ull; + + //-Unf > -Norm + double x8 = hide_double(-1.0e-999); + double y8 = hide_double(-83532.96153153); + unsigned long long r8 = 0xffffffffffffffffull; + + //-Unf = 0 + double x9 = hide_double(-1.0e-999); + double y9 = hide_double(0.0); + unsigned long long r9 = 0xffffffffffffffffull; + + //-0 = 0 + double x10 = hide_double(-0.0); + double y10 = hide_double( 0.0); + unsigned long long r10 = 0xffffffffffffffffull; + + //+Unf = 0 + double x11 = hide_double( 1.0e-999); + double y11 = hide_double( 0.0); + unsigned long long r11 = 0xffffffffffffffffull; + + //+Unf < +Norm + double x12 = hide_double( 1e-999); + double y12 = hide_double(0.0031529324); + unsigned long long r12 = 0x0000000000000000ull; + + //+Norm > +Denorm + double x13 = hide_double(5172.2845321); + double y13 = hide_double(3.0e-321); + unsigned long long r13 = 0xffffffffffffffffull; + + //+Norm = +Norm + double x14 = hide_double(5172.2845321); + double y14 = hide_double(5172.2845321); + unsigned long long r14 = 0xffffffffffffffffull; + + //+Norm < +Norm + double x15 = hide_double(264.345643345); + double y15 = hide_double(2353705.31415); + unsigned long long r15 = 0x0000000000000000ull; + + //+Norm > -Norm + double x16 = hide_double( 926.605118542); + double y16 = hide_double(-9.43574552184); + unsigned long long r16 = 0xffffffffffffffffull; + + //+Norm < +Dmax + double x17 = hide_double( 926.605118542); + double y17 = hide_double(DBL_MAX); + unsigned long long r17 = 0x0000000000000000ull; + + //+Inf > +Dmax + double x18 = hide_double(HUGE_VAL); + double y18 = hide_double(DBL_MAX); + unsigned long long r18 = 0xffffffffffffffffull; + + //+QNaN: NG + double x19 = hide_double(nan("")); + double y19 = hide_double(3.14); + unsigned long long r19 = 0x0000000000000000ull; + + vec_double2 x0_v = spu_splats(x0); + vec_double2 y0_v = spu_splats(y0); + vec_ullong2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_double2 y1_v = spu_splats(y1); + vec_ullong2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_double2 y2_v = spu_splats(y2); + vec_ullong2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_double2 y3_v = spu_splats(y3); + vec_ullong2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_double2 y4_v = spu_splats(y4); + vec_ullong2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_double2 y5_v = spu_splats(y5); + vec_ullong2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_double2 y6_v = spu_splats(y6); + vec_ullong2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_double2 y7_v = spu_splats(y7); + vec_ullong2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_double2 y8_v = spu_splats(y8); + vec_ullong2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_double2 y9_v = spu_splats(y9); + vec_ullong2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_double2 y10_v = spu_splats(y10); + vec_ullong2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_double2 y11_v = spu_splats(y11); + vec_ullong2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_double2 y12_v = spu_splats(y12); + vec_ullong2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_double2 y13_v = spu_splats(y13); + vec_ullong2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_double2 y14_v = spu_splats(y14); + vec_ullong2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_double2 y15_v = spu_splats(y15); + vec_ullong2 r15_v = spu_splats(r15); + + vec_double2 x16_v = spu_splats(x16); + vec_double2 y16_v = spu_splats(y16); + vec_ullong2 r16_v = spu_splats(r16); + + vec_double2 x17_v = spu_splats(x17); + vec_double2 y17_v = spu_splats(y17); + vec_ullong2 r17_v = spu_splats(r17); + + vec_double2 x18_v = spu_splats(x18); + vec_double2 y18_v = spu_splats(y18); + vec_ullong2 r18_v = spu_splats(r18); + + vec_double2 x19_v = spu_splats(x19); + vec_double2 y19_v = spu_splats(y19); + vec_ullong2 r19_v = spu_splats(r19); + + vec_ullong2 res_v; + + TEST_START("isgreaterequald2"); + + res_v = (vec_ullong2)isgreaterequald2(x0_v, y0_v); + TEST_CHECK("20060825000000AAN", allequal_ullong2( res_v, r0_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x1_v, y1_v); + TEST_CHECK("20060825000001AAN", allequal_ullong2( res_v, r1_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x2_v, y2_v); + TEST_CHECK("20060825000002AAN", allequal_ullong2( res_v, r2_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x3_v, y3_v); + TEST_CHECK("20060825000003AAN", allequal_ullong2( res_v, r3_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x4_v, y4_v); + TEST_CHECK("20060825000004AAN", allequal_ullong2( res_v, r4_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x5_v, y5_v); + TEST_CHECK("20060825000005AAN", allequal_ullong2( res_v, r5_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x6_v, y6_v); + TEST_CHECK("20060825000006AAN", allequal_ullong2( res_v, r6_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x7_v, y7_v); + TEST_CHECK("20060825000007AAN", allequal_ullong2( res_v, r7_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x8_v, y8_v); + TEST_CHECK("20060825000008AAN", allequal_ullong2( res_v, r8_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x9_v, y9_v); + TEST_CHECK("20060825000009AAN", allequal_ullong2( res_v, r9_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x10_v, y10_v); + TEST_CHECK("20060825000000AAN", allequal_ullong2( res_v, r10_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x11_v, y11_v); + TEST_CHECK("20060825000001AAN", allequal_ullong2( res_v, r11_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x12_v, y12_v); + TEST_CHECK("20060825000002AAN", allequal_ullong2( res_v, r12_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x13_v, y13_v); + TEST_CHECK("20060825000003AAN", allequal_ullong2( res_v, r13_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x14_v, y14_v); + TEST_CHECK("20060825000004AAN", allequal_ullong2( res_v, r14_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x15_v, y15_v); + TEST_CHECK("20060825000005AAN", allequal_ullong2( res_v, r15_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x16_v, y16_v); + TEST_CHECK("20060825000006AAN", allequal_ullong2( res_v, r16_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x17_v, y17_v); + TEST_CHECK("20060825000007AAN", allequal_ullong2( res_v, r17_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x18_v, y18_v); + TEST_CHECK("20060825000008AAN", allequal_ullong2( res_v, r18_v ), 0); + res_v = (vec_ullong2)isgreaterequald2(x19_v, y19_v); + TEST_CHECK("20060825000009AAN", allequal_ullong2( res_v, r19_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/isgreaterequalf4.c b/Extras/simdmathlibrary/spu/tests/isgreaterequalf4.c new file mode 100644 index 0000000..ac13a26 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/isgreaterequalf4.c @@ -0,0 +1,151 @@ +/* Test isgreaterequalf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060817000000AAN","AAN", "isgreaterequalf4"); + + float x0 = hide_float(-0.0f); + float y0 = hide_float( 0.0f); + unsigned int r0 = 0xffffffff; + + float x1 = hide_float(FLT_MAX); //+Smax + float y1 = hide_float(-FLT_MAX); //-Smax + unsigned int r1 = 0xffffffff; + + float x2 = hide_float(-0.0000000013152f); + float y2 = hide_float(-234245.85323441f); + unsigned int r2 = 0xffffffff; + + float x3 = hide_float(-168.97345223013f); + float y3 = hide_float(-168.97345223013f); + unsigned int r3 = 0xffffffff; + + float x4 = hide_float(-83532.96153153f); + float y4 = hide_float(-FLT_MIN); //-Smin + unsigned int r4 = 0x00000000; + + float x5 = hide_float(-321.01234567f); + float y5 = hide_float(876543.12345f); + unsigned int r5 = 0x00000000; + + float x6 = hide_float(FLT_MIN); // Smin + float y6 = hide_float(0.0031529324f); + unsigned int r6 = 0x00000000; + + float x7 = hide_float(5172.2845321f); + float y7 = hide_float(5172.2845321f); + unsigned int r7 = 0xffffffff; + + float x8 = hide_float(264.345643345f); + float y8 = hide_float(2353705.31415f); + unsigned int r8 = 0x00000000; + + float x9 = hide_float(FLT_MAX); // Smax + float y9 = hide_float(9.43574552184f); + unsigned int r9 = 0xffffffff; + + vec_float4 x0_v = spu_splats(x0); + vec_float4 y0_v = spu_splats(y0); + vec_uint4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_float4 y1_v = spu_splats(y1); + vec_uint4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_float4 y2_v = spu_splats(y2); + vec_uint4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_float4 y3_v = spu_splats(y3); + vec_uint4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_float4 y4_v = spu_splats(y4); + vec_uint4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_float4 y5_v = spu_splats(y5); + vec_uint4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_float4 y6_v = spu_splats(y6); + vec_uint4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_float4 y7_v = spu_splats(y7); + vec_uint4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_float4 y8_v = spu_splats(y8); + vec_uint4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_float4 y9_v = spu_splats(y9); + vec_uint4 r9_v = spu_splats(r9); + + vec_uint4 res_v; + + TEST_START("isgreaterequalf4"); + + res_v = (vec_uint4)isgreaterequalf4(x0_v, y0_v); + TEST_CHECK("20060817000000AAN", allequal_uint4( res_v, r0_v ), 0); + res_v = (vec_uint4)isgreaterequalf4(x1_v, y1_v); + TEST_CHECK("20060817000001AAN", allequal_uint4( res_v, r1_v ), 0); + res_v = (vec_uint4)isgreaterequalf4(x2_v, y2_v); + TEST_CHECK("20060817000002AAN", allequal_uint4( res_v, r2_v ), 0); + res_v = (vec_uint4)isgreaterequalf4(x3_v, y3_v); + TEST_CHECK("20060817000003AAN", allequal_uint4( res_v, r3_v ), 0); + res_v = (vec_uint4)isgreaterequalf4(x4_v, y4_v); + TEST_CHECK("20060817000004AAN", allequal_uint4( res_v, r4_v ), 0); + res_v = (vec_uint4)isgreaterequalf4(x5_v, y5_v); + TEST_CHECK("20060817000005AAN", allequal_uint4( res_v, r5_v ), 0); + res_v = (vec_uint4)isgreaterequalf4(x6_v, y6_v); + TEST_CHECK("20060817000006AAN", allequal_uint4( res_v, r6_v ), 0); + res_v = (vec_uint4)isgreaterequalf4(x7_v, y7_v); + TEST_CHECK("20060817000007AAN", allequal_uint4( res_v, r7_v ), 0); + res_v = (vec_uint4)isgreaterequalf4(x8_v, y8_v); + TEST_CHECK("20060817000008AAN", allequal_uint4( res_v, r8_v ), 0); + res_v = (vec_uint4)isgreaterequalf4(x9_v, y9_v); + TEST_CHECK("20060817000009AAN", allequal_uint4( res_v, r9_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/isgreaterf4.c b/Extras/simdmathlibrary/spu/tests/isgreaterf4.c new file mode 100644 index 0000000..8390f8c --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/isgreaterf4.c @@ -0,0 +1,151 @@ +/* Test isgreaterf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060817000000AAN","AAN", "isgreaterf4"); + + float x0 = hide_float(-0.0f); + float y0 = hide_float( 0.0f); + unsigned int r0 = 0x00000000; + + float x1 = hide_float(FLT_MAX); //+Smax + float y1 = hide_float(-FLT_MAX); //-Smax + unsigned int r1 = 0xffffffff; + + float x2 = hide_float(-0.0000000013152f); + float y2 = hide_float(-234245.85323441f); + unsigned int r2 = 0xffffffff; + + float x3 = hide_float(-168.97345223013f); + float y3 = hide_float(-168.97345223013f); + unsigned int r3 = 0x00000000; + + float x4 = hide_float(-83532.96153153f); + float y4 = hide_float(-FLT_MIN); //-Smin + unsigned int r4 = 0x00000000; + + float x5 = hide_float(-321.01234567f); + float y5 = hide_float(876543.12345f); + unsigned int r5 = 0x00000000; + + float x6 = hide_float(FLT_MIN); // Smin + float y6 = hide_float(0.0031529324f); + unsigned int r6 = 0x00000000; + + float x7 = hide_float(5172.2845321f); + float y7 = hide_float(5172.2845321f); + unsigned int r7 = 0x00000000; + + float x8 = hide_float(264.345643345f); + float y8 = hide_float(2353705.31415f); + unsigned int r8 = 0x00000000; + + float x9 = hide_float(FLT_MAX); // Smax + float y9 = hide_float(9.43574552184f); + unsigned int r9 = 0xffffffff; + + vec_float4 x0_v = spu_splats(x0); + vec_float4 y0_v = spu_splats(y0); + vec_uint4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_float4 y1_v = spu_splats(y1); + vec_uint4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_float4 y2_v = spu_splats(y2); + vec_uint4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_float4 y3_v = spu_splats(y3); + vec_uint4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_float4 y4_v = spu_splats(y4); + vec_uint4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_float4 y5_v = spu_splats(y5); + vec_uint4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_float4 y6_v = spu_splats(y6); + vec_uint4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_float4 y7_v = spu_splats(y7); + vec_uint4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_float4 y8_v = spu_splats(y8); + vec_uint4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_float4 y9_v = spu_splats(y9); + vec_uint4 r9_v = spu_splats(r9); + + vec_uint4 res_v; + + TEST_START("isgreaterf4"); + + res_v = (vec_uint4)isgreaterf4(x0_v, y0_v); + TEST_CHECK("20060817000000AAN", allequal_uint4( res_v, r0_v ), 0); + res_v = (vec_uint4)isgreaterf4(x1_v, y1_v); + TEST_CHECK("20060817000001AAN", allequal_uint4( res_v, r1_v ), 0); + res_v = (vec_uint4)isgreaterf4(x2_v, y2_v); + TEST_CHECK("20060817000002AAN", allequal_uint4( res_v, r2_v ), 0); + res_v = (vec_uint4)isgreaterf4(x3_v, y3_v); + TEST_CHECK("20060817000003AAN", allequal_uint4( res_v, r3_v ), 0); + res_v = (vec_uint4)isgreaterf4(x4_v, y4_v); + TEST_CHECK("20060817000004AAN", allequal_uint4( res_v, r4_v ), 0); + res_v = (vec_uint4)isgreaterf4(x5_v, y5_v); + TEST_CHECK("20060817000005AAN", allequal_uint4( res_v, r5_v ), 0); + res_v = (vec_uint4)isgreaterf4(x6_v, y6_v); + TEST_CHECK("20060817000006AAN", allequal_uint4( res_v, r6_v ), 0); + res_v = (vec_uint4)isgreaterf4(x7_v, y7_v); + TEST_CHECK("20060817000007AAN", allequal_uint4( res_v, r7_v ), 0); + res_v = (vec_uint4)isgreaterf4(x8_v, y8_v); + TEST_CHECK("20060817000008AAN", allequal_uint4( res_v, r8_v ), 0); + res_v = (vec_uint4)isgreaterf4(x9_v, y9_v); + TEST_CHECK("20060817000009AAN", allequal_uint4( res_v, r9_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/isinfd2.c b/Extras/simdmathlibrary/spu/tests/isinfd2.c new file mode 100644 index 0000000..94b49a3 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/isinfd2.c @@ -0,0 +1,225 @@ +/* Test isinfd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060830000000AAN","AAN", "isinfd2"); + + // -Nan + double x0 = hide_double(-nan("")); + unsigned long long r0 = 0x0000000000000000ull; + + // -Inf + double x1 = hide_double(-HUGE_VAL); + unsigned long long r1 = 0xffffffffffffffffull; + + // -Dmax + double x2 = hide_double(-DBL_MAX); + unsigned long long r2 = 0x0000000000000000ull; + + // -Norm + double x3 = hide_double(-824842.58421394); + unsigned long long r3 = 0x0000000000000000ull; + + // -Dmin + double x4 = hide_double(-DBL_MIN); + unsigned long long r4 = 0x0000000000000000ull; + + // -Denorm + double x5 = hide_double(-2.40e-310); + unsigned long long r5 = 0x0000000000000000ull; + + // -Unf + double x6 = hide_double(-1.0e-999); + unsigned long long r6 = 0x0000000000000000ull; + + // -0 + double x7 = hide_double(-0.0); + unsigned long long r7 = 0x0000000000000000ull; + + // 0 + double x8 = hide_double( 0.0); + unsigned long long r8 = 0x0000000000000000ull; + + // +Inf + double x9 = hide_double( 1.0e999); + unsigned long long r9 = 0xffffffffffffffffull; + + // +Denorm + double x10 = hide_double( 2.40e-310); + unsigned long long r10 = 0x0000000000000000ull; + + // +Dmin + double x11 = hide_double( DBL_MIN); + unsigned long long r11 = 0x0000000000000000ull; + + // +Norm + double x12 = hide_double(3.14152634); + unsigned long long r12 = 0x0000000000000000ull; + + // +Dmax + double x13 = hide_double(DBL_MAX); + unsigned long long r13 = 0x0000000000000000ull; + + // +Inf + double x14 = hide_double(HUGE_VAL); + unsigned long long r14 = 0xffffffffffffffffull; + + //+Nan + double x15 = hide_double( nan("")); + unsigned long long r15 = 0x0000000000000000ull; + + // Compound + vec_double2 x16_v = (vec_double2) {make_double(0x000AAAAAAAAAAAAAull), -1.0e-999 }; + vec_ullong2 r16_v = (vec_ullong2) {0x0000000000000000ull, 0x0000000000000000ull}; + + // Compound + vec_double2 x17_v = (vec_double2) { 345.27533, -2.40e-310 }; + vec_ullong2 r17_v = (vec_ullong2) {0x0000000000000000ull, 0x0000000000000000ull}; + + // Compound + vec_double2 x18_v = (vec_double2) { nan(""), 1.0e999 }; + vec_ullong2 r18_v = (vec_ullong2) {0x0000000000000000ull, 0xffffffffffffffffull}; + + // Compound + vec_double2 x19_v = (vec_double2) { HUGE_VAL, -nan("") }; + vec_ullong2 r19_v = (vec_ullong2) {0xffffffffffffffffull, 0x0000000000000000ull}; + + // Compound + vec_double2 x20_v = (vec_double2) { -1.0e999, -HUGE_VAL} ; + vec_ullong2 r20_v = (vec_ullong2) {0xffffffffffffffffull, 0xffffffffffffffffull}; + + vec_double2 x0_v = spu_splats(x0); + vec_ullong2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_ullong2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_ullong2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_ullong2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_ullong2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_ullong2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_ullong2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_ullong2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_ullong2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_ullong2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_ullong2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_ullong2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_ullong2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_ullong2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_ullong2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_ullong2 r15_v = spu_splats(r15); + + vec_ullong2 res_v; + + TEST_START("isinfd2"); + + res_v = (vec_ullong2)isinfd2(x0_v); + TEST_CHECK("20060830000000AAN", allequal_ullong2( res_v, r0_v ), 0); + res_v = (vec_ullong2)isinfd2(x1_v); + TEST_CHECK("20060830000001AAN", allequal_ullong2( res_v, r1_v ), 0); + res_v = (vec_ullong2)isinfd2(x2_v); + TEST_CHECK("20060830000002AAN", allequal_ullong2( res_v, r2_v ), 0); + res_v = (vec_ullong2)isinfd2(x3_v); + TEST_CHECK("20060830000003AAN", allequal_ullong2( res_v, r3_v ), 0); + res_v = (vec_ullong2)isinfd2(x4_v); + TEST_CHECK("20060830000004AAN", allequal_ullong2( res_v, r4_v ), 0); + res_v = (vec_ullong2)isinfd2(x5_v); + TEST_CHECK("20060830000005AAN", allequal_ullong2( res_v, r5_v ), 0); + res_v = (vec_ullong2)isinfd2(x6_v); + TEST_CHECK("20060830000006AAN", allequal_ullong2( res_v, r6_v ), 0); + res_v = (vec_ullong2)isinfd2(x7_v); + TEST_CHECK("20060830000007AAN", allequal_ullong2( res_v, r7_v ), 0); + res_v = (vec_ullong2)isinfd2(x8_v); + TEST_CHECK("20060830000008AAN", allequal_ullong2( res_v, r8_v ), 0); + res_v = (vec_ullong2)isinfd2(x9_v); + TEST_CHECK("20060830000009AAN", allequal_ullong2( res_v, r9_v ), 0); + res_v = (vec_ullong2)isinfd2(x10_v); + TEST_CHECK("20060830000010AAN", allequal_ullong2( res_v, r10_v ), 0); + res_v = (vec_ullong2)isinfd2(x11_v); + TEST_CHECK("20060830000011AAN", allequal_ullong2( res_v, r11_v ), 0); + res_v = (vec_ullong2)isinfd2(x12_v); + TEST_CHECK("20060830000012AAN", allequal_ullong2( res_v, r12_v ), 0); + res_v = (vec_ullong2)isinfd2(x13_v); + TEST_CHECK("20060830000013AAN", allequal_ullong2( res_v, r13_v ), 0); + res_v = (vec_ullong2)isinfd2(x14_v); + TEST_CHECK("20060830000014AAN", allequal_ullong2( res_v, r14_v ), 0); + res_v = (vec_ullong2)isinfd2(x15_v); + TEST_CHECK("20060830000015AAN", allequal_ullong2( res_v, r15_v ), 0); + res_v = (vec_ullong2)isinfd2(x16_v); + TEST_CHECK("20060830000016AAN", allequal_ullong2( res_v, r16_v ), 0); + res_v = (vec_ullong2)isinfd2(x17_v); + TEST_CHECK("20060830000017AAN", allequal_ullong2( res_v, r17_v ), 0); + res_v = (vec_ullong2)isinfd2(x18_v); + TEST_CHECK("20060830000018AAN", allequal_ullong2( res_v, r18_v ), 0); + res_v = (vec_ullong2)isinfd2(x19_v); + TEST_CHECK("20060830000019AAN", allequal_ullong2( res_v, r19_v ), 0); + res_v = (vec_ullong2)isinfd2(x20_v); + TEST_CHECK("20060830000020AAN", allequal_ullong2( res_v, r20_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/isinff4.c b/Extras/simdmathlibrary/spu/tests/isinff4.c new file mode 100644 index 0000000..f2bf174 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/isinff4.c @@ -0,0 +1,131 @@ +/* Test isinff4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060822000000AAN","AAN", "isinff4"); + + float x0 = hide_float(-0.0f); + unsigned int r0 = 0x00000000; + + float x1 = hide_float(-FLT_MAX); //-Smax + unsigned int r1 = 0x00000000; + + float x2 = hide_float(-0.0000000013152f); + unsigned int r2 = 0x00000000; + + float x3 = hide_float(-168.97345223013f); + unsigned int r3 = 0x00000000; + + float x4 = hide_float(-1e-999); //-Smin + unsigned int r4 = 0x00000000; + + float x5 = hide_float(876543.12345f); + unsigned int r5 = 0x00000000; + + float x6 = hide_float( 1e-999); // Smin + unsigned int r6 = 0x00000000; + + float x7 = hide_float(5172.2845321f); + unsigned int r7 = 0x00000000; + + float x8 = hide_float(2353705.31415f); + unsigned int r8 = 0x00000000; + + float x9 = hide_float(FLT_MAX); // Smax + unsigned int r9 = 0x00000000; + + vec_float4 x0_v = spu_splats(x0); + vec_uint4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_uint4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_uint4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_uint4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_uint4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_uint4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_uint4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_uint4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_uint4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_uint4 r9_v = spu_splats(r9); + + vec_uint4 res_v; + + TEST_START("isinff4"); + + res_v = (vec_uint4)isinff4(x0_v); + TEST_CHECK("20060822000000AAN", allequal_uint4( res_v, r0_v ), 0); + res_v = (vec_uint4)isinff4(x1_v); + TEST_CHECK("20060822000001AAN", allequal_uint4( res_v, r1_v ), 0); + res_v = (vec_uint4)isinff4(x2_v); + TEST_CHECK("20060822000002AAN", allequal_uint4( res_v, r2_v ), 0); + res_v = (vec_uint4)isinff4(x3_v); + TEST_CHECK("20060822000003AAN", allequal_uint4( res_v, r3_v ), 0); + res_v = (vec_uint4)isinff4(x4_v); + TEST_CHECK("20060822000004AAN", allequal_uint4( res_v, r4_v ), 0); + res_v = (vec_uint4)isinff4(x5_v); + TEST_CHECK("20060822000005AAN", allequal_uint4( res_v, r5_v ), 0); + res_v = (vec_uint4)isinff4(x6_v); + TEST_CHECK("20060822000006AAN", allequal_uint4( res_v, r6_v ), 0); + res_v = (vec_uint4)isinff4(x7_v); + TEST_CHECK("20060822000007AAN", allequal_uint4( res_v, r7_v ), 0); + res_v = (vec_uint4)isinff4(x8_v); + TEST_CHECK("20060822000008AAN", allequal_uint4( res_v, r8_v ), 0); + res_v = (vec_uint4)isinff4(x9_v); + TEST_CHECK("20060822000009AAN", allequal_uint4( res_v, r9_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/islessd2.c b/Extras/simdmathlibrary/spu/tests/islessd2.c new file mode 100644 index 0000000..087df29 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/islessd2.c @@ -0,0 +1,272 @@ +/* Test islessd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060825000000AAN","AAN", "islessd2"); + + //-QNaN: NG + double x0 = hide_double(-nan("")); + double y0 = hide_double(1.0); + unsigned long long r0 = 0x0000000000000000ull; + + //+Inf > -Inf + double x1 = hide_double( HUGE_VAL); + double y1 = hide_double(-HUGE_VAL); + unsigned long long r1 = 0x0000000000000000ull; + + //-Inf < -Dmax + double x2 = hide_double(-HUGE_VAL); + double y2 = hide_double(-DBL_MAX); + unsigned long long r2 = 0xffffffffffffffffull; + + //-Norm > -Inf + double x3 = hide_double(-67418234.34256245); + double y3 = hide_double(-HUGE_VAL); + unsigned long long r3 = 0x0000000000000000ull; + + //-Norm < -Denorm + double x4 = hide_double(-273453.3234458053); + double y4 = hide_double(-3.0e-321); + unsigned long long r4 = 0xffffffffffffffffull; + + //-Norm = -Norm + double x5 = hide_double(-168.97345223013); + double y5 = hide_double(-168.97345223013); + unsigned long long r5 = 0x0000000000000000ull; + + //-Norm > -Norm + double x6 = hide_double(-168.97345223013); + double y6 = hide_double(-21345853556.492); + unsigned long long r6 = 0x0000000000000000ull; + + //-Norm < -0 + double x7 = hide_double(-168.97345223013); + double y7 = hide_double(-0.0); + unsigned long long r7 = 0xffffffffffffffffull; + + //-Unf > -Norm + double x8 = hide_double(-1.0e-999); + double y8 = hide_double(-83532.96153153); + unsigned long long r8 = 0x0000000000000000ull; + + //-Unf = 0 + double x9 = hide_double(-1.0e-999); + double y9 = hide_double(0.0); + unsigned long long r9 = 0x0000000000000000ull; + + //-0 = 0 + double x10 = hide_double(-0.0); + double y10 = hide_double( 0.0); + unsigned long long r10 = 0x0000000000000000ull; + + //+Unf = 0 + double x11 = hide_double( 1.0e-999); + double y11 = hide_double( 0.0); + unsigned long long r11 = 0x0000000000000000ull; + + //+Unf < +Norm + double x12 = hide_double( 1e-999); + double y12 = hide_double(0.0031529324); + unsigned long long r12 = 0xffffffffffffffffull; + + //+Norm > +Denorm + double x13 = hide_double(5172.2845321); + double y13 = hide_double(3.0e-321); + unsigned long long r13 = 0x0000000000000000ull; + + //+Norm = +Norm + double x14 = hide_double(5172.2845321); + double y14 = hide_double(5172.2845321); + unsigned long long r14 = 0x0000000000000000ull; + + //+Norm < +Norm + double x15 = hide_double(264.345643345); + double y15 = hide_double(2353705.31415); + unsigned long long r15 = 0xffffffffffffffffull; + + //+Norm > -Norm + double x16 = hide_double( 926.605118542); + double y16 = hide_double(-9.43574552184); + unsigned long long r16 = 0x0000000000000000ull; + + //+Norm < +Dmax + double x17 = hide_double( 926.605118542); + double y17 = hide_double(DBL_MAX); + unsigned long long r17 = 0xffffffffffffffffull; + + //+Inf > +Dmax + double x18 = hide_double(HUGE_VAL); + double y18 = hide_double(DBL_MAX); + unsigned long long r18 = 0x0000000000000000ull; + + //+QNaN: NG + double x19 = hide_double(nan("")); + double y19 = hide_double(3.14); + unsigned long long r19 = 0x0000000000000000ull; + + vec_double2 x0_v = spu_splats(x0); + vec_double2 y0_v = spu_splats(y0); + vec_ullong2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_double2 y1_v = spu_splats(y1); + vec_ullong2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_double2 y2_v = spu_splats(y2); + vec_ullong2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_double2 y3_v = spu_splats(y3); + vec_ullong2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_double2 y4_v = spu_splats(y4); + vec_ullong2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_double2 y5_v = spu_splats(y5); + vec_ullong2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_double2 y6_v = spu_splats(y6); + vec_ullong2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_double2 y7_v = spu_splats(y7); + vec_ullong2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_double2 y8_v = spu_splats(y8); + vec_ullong2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_double2 y9_v = spu_splats(y9); + vec_ullong2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_double2 y10_v = spu_splats(y10); + vec_ullong2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_double2 y11_v = spu_splats(y11); + vec_ullong2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_double2 y12_v = spu_splats(y12); + vec_ullong2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_double2 y13_v = spu_splats(y13); + vec_ullong2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_double2 y14_v = spu_splats(y14); + vec_ullong2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_double2 y15_v = spu_splats(y15); + vec_ullong2 r15_v = spu_splats(r15); + + vec_double2 x16_v = spu_splats(x16); + vec_double2 y16_v = spu_splats(y16); + vec_ullong2 r16_v = spu_splats(r16); + + vec_double2 x17_v = spu_splats(x17); + vec_double2 y17_v = spu_splats(y17); + vec_ullong2 r17_v = spu_splats(r17); + + vec_double2 x18_v = spu_splats(x18); + vec_double2 y18_v = spu_splats(y18); + vec_ullong2 r18_v = spu_splats(r18); + + vec_double2 x19_v = spu_splats(x19); + vec_double2 y19_v = spu_splats(y19); + vec_ullong2 r19_v = spu_splats(r19); + + vec_ullong2 res_v; + + TEST_START("islessd2"); + + res_v = (vec_ullong2)islessd2(x0_v, y0_v); + TEST_CHECK("20060825000000AAN", allequal_ullong2( res_v, r0_v ), 0); + res_v = (vec_ullong2)islessd2(x1_v, y1_v); + TEST_CHECK("20060825000001AAN", allequal_ullong2( res_v, r1_v ), 0); + res_v = (vec_ullong2)islessd2(x2_v, y2_v); + TEST_CHECK("20060825000002AAN", allequal_ullong2( res_v, r2_v ), 0); + res_v = (vec_ullong2)islessd2(x3_v, y3_v); + TEST_CHECK("20060825000003AAN", allequal_ullong2( res_v, r3_v ), 0); + res_v = (vec_ullong2)islessd2(x4_v, y4_v); + TEST_CHECK("20060825000004AAN", allequal_ullong2( res_v, r4_v ), 0); + res_v = (vec_ullong2)islessd2(x5_v, y5_v); + TEST_CHECK("20060825000005AAN", allequal_ullong2( res_v, r5_v ), 0); + res_v = (vec_ullong2)islessd2(x6_v, y6_v); + TEST_CHECK("20060825000006AAN", allequal_ullong2( res_v, r6_v ), 0); + res_v = (vec_ullong2)islessd2(x7_v, y7_v); + TEST_CHECK("20060825000007AAN", allequal_ullong2( res_v, r7_v ), 0); + res_v = (vec_ullong2)islessd2(x8_v, y8_v); + TEST_CHECK("20060825000008AAN", allequal_ullong2( res_v, r8_v ), 0); + res_v = (vec_ullong2)islessd2(x9_v, y9_v); + TEST_CHECK("20060825000009AAN", allequal_ullong2( res_v, r9_v ), 0); + res_v = (vec_ullong2)islessd2(x10_v, y10_v); + TEST_CHECK("20060825000000AAN", allequal_ullong2( res_v, r10_v ), 0); + res_v = (vec_ullong2)islessd2(x11_v, y11_v); + TEST_CHECK("20060825000001AAN", allequal_ullong2( res_v, r11_v ), 0); + res_v = (vec_ullong2)islessd2(x12_v, y12_v); + TEST_CHECK("20060825000002AAN", allequal_ullong2( res_v, r12_v ), 0); + res_v = (vec_ullong2)islessd2(x13_v, y13_v); + TEST_CHECK("20060825000003AAN", allequal_ullong2( res_v, r13_v ), 0); + res_v = (vec_ullong2)islessd2(x14_v, y14_v); + TEST_CHECK("20060825000004AAN", allequal_ullong2( res_v, r14_v ), 0); + res_v = (vec_ullong2)islessd2(x15_v, y15_v); + TEST_CHECK("20060825000005AAN", allequal_ullong2( res_v, r15_v ), 0); + res_v = (vec_ullong2)islessd2(x16_v, y16_v); + TEST_CHECK("20060825000006AAN", allequal_ullong2( res_v, r16_v ), 0); + res_v = (vec_ullong2)islessd2(x17_v, y17_v); + TEST_CHECK("20060825000007AAN", allequal_ullong2( res_v, r17_v ), 0); + res_v = (vec_ullong2)islessd2(x18_v, y18_v); + TEST_CHECK("20060825000008AAN", allequal_ullong2( res_v, r18_v ), 0); + res_v = (vec_ullong2)islessd2(x19_v, y19_v); + TEST_CHECK("20060825000009AAN", allequal_ullong2( res_v, r19_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/islessequald2.c b/Extras/simdmathlibrary/spu/tests/islessequald2.c new file mode 100644 index 0000000..52c9ea4 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/islessequald2.c @@ -0,0 +1,271 @@ +/* Test islessequald2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060825000000AAN","AAN", "islessequald2"); + + //-QNaN: NG + double x0 = hide_double(-nan("")); + double y0 = hide_double(1.0); + unsigned long long r0 = 0x0000000000000000ull; + + //+Inf > -Inf + double x1 = hide_double( HUGE_VAL); + double y1 = hide_double(-HUGE_VAL); + unsigned long long r1 = 0x0000000000000000ull; + + //-Inf < -Dmax + double x2 = hide_double(-HUGE_VAL); + double y2 = hide_double(-DBL_MAX); + unsigned long long r2 = 0xffffffffffffffffull; + + //-Norm > -Inf + double x3 = hide_double(-67418234.34256245); + double y3 = hide_double(-HUGE_VAL); + unsigned long long r3 = 0x0000000000000000ull; + + //-Norm < -Denorm + double x4 = hide_double(-273453.3234458053); + double y4 = hide_double(-3.0e-321); + unsigned long long r4 = 0xffffffffffffffffull; + + //-Norm = -Norm + double x5 = hide_double(-168.97345223013); + double y5 = hide_double(-168.97345223013); + unsigned long long r5 = 0xffffffffffffffffull; + + //-Norm > -Norm + double x6 = hide_double(-168.97345223013); + double y6 = hide_double(-21345853556.492); + unsigned long long r6 = 0x0000000000000000ull; + + //-Norm < -0 + double x7 = hide_double(-168.97345223013); + double y7 = hide_double(-0.0); + unsigned long long r7 = 0xffffffffffffffffull; + + //-Unf > -Norm + double x8 = hide_double(-1.0e-999); + double y8 = hide_double(-83532.96153153); + unsigned long long r8 = 0x0000000000000000ull; + + //-Unf = 0 + double x9 = hide_double(-1.0e-999); + double y9 = hide_double(0.0); + unsigned long long r9 = 0xffffffffffffffffull; + + //-0 = 0 + double x10 = hide_double(-0.0); + double y10 = hide_double( 0.0); + unsigned long long r10 = 0xffffffffffffffffull; + + //+Unf = 0 + double x11 = hide_double( 1.0e-999); + double y11 = hide_double( 0.0); + unsigned long long r11 = 0xffffffffffffffffull; + + //+Unf < +Norm + double x12 = hide_double( 1e-999); + double y12 = hide_double(0.0031529324); + unsigned long long r12 = 0xffffffffffffffffull; + + //+Norm > +Denorm + double x13 = hide_double(5172.2845321); + double y13 = hide_double(3.0e-321); + unsigned long long r13 = 0x0000000000000000ull; + + //+Norm = +Norm + double x14 = hide_double(5172.2845321); + double y14 = hide_double(5172.2845321); + unsigned long long r14 = 0xffffffffffffffffull; + + //+Norm < +Norm + double x15 = hide_double(264.345643345); + double y15 = hide_double(2353705.31415); + unsigned long long r15 = 0xffffffffffffffffull; + + //+Norm > -Norm + double x16 = hide_double( 926.605118542); + double y16 = hide_double(-9.43574552184); + unsigned long long r16 = 0x0000000000000000ull; + + //+Norm < +Dmax + double x17 = hide_double( 926.605118542); + double y17 = hide_double(DBL_MAX); + unsigned long long r17 = 0xffffffffffffffffull; + + //+Inf > +Dmax + double x18 = hide_double(HUGE_VAL); + double y18 = hide_double(DBL_MAX); + unsigned long long r18 = 0x0000000000000000ull; + + //+QNaN: NG + double x19 = hide_double(nan("")); + double y19 = hide_double(3.14); + unsigned long long r19 = 0x0000000000000000ull; + + vec_double2 x0_v = spu_splats(x0); + vec_double2 y0_v = spu_splats(y0); + vec_ullong2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_double2 y1_v = spu_splats(y1); + vec_ullong2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_double2 y2_v = spu_splats(y2); + vec_ullong2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_double2 y3_v = spu_splats(y3); + vec_ullong2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_double2 y4_v = spu_splats(y4); + vec_ullong2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_double2 y5_v = spu_splats(y5); + vec_ullong2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_double2 y6_v = spu_splats(y6); + vec_ullong2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_double2 y7_v = spu_splats(y7); + vec_ullong2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_double2 y8_v = spu_splats(y8); + vec_ullong2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_double2 y9_v = spu_splats(y9); + vec_ullong2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_double2 y10_v = spu_splats(y10); + vec_ullong2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_double2 y11_v = spu_splats(y11); + vec_ullong2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_double2 y12_v = spu_splats(y12); + vec_ullong2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_double2 y13_v = spu_splats(y13); + vec_ullong2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_double2 y14_v = spu_splats(y14); + vec_ullong2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_double2 y15_v = spu_splats(y15); + vec_ullong2 r15_v = spu_splats(r15); + + vec_double2 x16_v = spu_splats(x16); + vec_double2 y16_v = spu_splats(y16); + vec_ullong2 r16_v = spu_splats(r16); + + vec_double2 x17_v = spu_splats(x17); + vec_double2 y17_v = spu_splats(y17); + vec_ullong2 r17_v = spu_splats(r17); + + vec_double2 x18_v = spu_splats(x18); + vec_double2 y18_v = spu_splats(y18); + vec_ullong2 r18_v = spu_splats(r18); + + vec_double2 x19_v = spu_splats(x19); + vec_double2 y19_v = spu_splats(y19); + vec_ullong2 r19_v = spu_splats(r19); + + vec_ullong2 res_v; + + TEST_START("islessequald2"); + + res_v = (vec_ullong2)islessequald2(x0_v, y0_v); + TEST_CHECK("20060825000000AAN", allequal_ullong2( res_v, r0_v ), 0); + res_v = (vec_ullong2)islessequald2(x1_v, y1_v); + TEST_CHECK("20060825000001AAN", allequal_ullong2( res_v, r1_v ), 0); + res_v = (vec_ullong2)islessequald2(x2_v, y2_v); + TEST_CHECK("20060825000002AAN", allequal_ullong2( res_v, r2_v ), 0); + res_v = (vec_ullong2)islessequald2(x3_v, y3_v); + TEST_CHECK("20060825000003AAN", allequal_ullong2( res_v, r3_v ), 0); + res_v = (vec_ullong2)islessequald2(x4_v, y4_v); + TEST_CHECK("20060825000004AAN", allequal_ullong2( res_v, r4_v ), 0); + res_v = (vec_ullong2)islessequald2(x5_v, y5_v); + TEST_CHECK("20060825000005AAN", allequal_ullong2( res_v, r5_v ), 0); + res_v = (vec_ullong2)islessequald2(x6_v, y6_v); + TEST_CHECK("20060825000006AAN", allequal_ullong2( res_v, r6_v ), 0); + res_v = (vec_ullong2)islessequald2(x7_v, y7_v); + TEST_CHECK("20060825000007AAN", allequal_ullong2( res_v, r7_v ), 0); + res_v = (vec_ullong2)islessequald2(x8_v, y8_v); + TEST_CHECK("20060825000008AAN", allequal_ullong2( res_v, r8_v ), 0); + res_v = (vec_ullong2)islessequald2(x9_v, y9_v); + TEST_CHECK("20060825000009AAN", allequal_ullong2( res_v, r9_v ), 0); + res_v = (vec_ullong2)islessequald2(x10_v, y10_v); + TEST_CHECK("20060825000000AAN", allequal_ullong2( res_v, r10_v ), 0); + res_v = (vec_ullong2)islessequald2(x11_v, y11_v); + TEST_CHECK("20060825000001AAN", allequal_ullong2( res_v, r11_v ), 0); + res_v = (vec_ullong2)islessequald2(x12_v, y12_v); + TEST_CHECK("20060825000002AAN", allequal_ullong2( res_v, r12_v ), 0); + res_v = (vec_ullong2)islessequald2(x13_v, y13_v); + TEST_CHECK("20060825000003AAN", allequal_ullong2( res_v, r13_v ), 0); + res_v = (vec_ullong2)islessequald2(x14_v, y14_v); + TEST_CHECK("20060825000004AAN", allequal_ullong2( res_v, r14_v ), 0); + res_v = (vec_ullong2)islessequald2(x15_v, y15_v); + TEST_CHECK("20060825000005AAN", allequal_ullong2( res_v, r15_v ), 0); + res_v = (vec_ullong2)islessequald2(x16_v, y16_v); + TEST_CHECK("20060825000006AAN", allequal_ullong2( res_v, r16_v ), 0); + res_v = (vec_ullong2)islessequald2(x17_v, y17_v); + TEST_CHECK("20060825000007AAN", allequal_ullong2( res_v, r17_v ), 0); + res_v = (vec_ullong2)islessequald2(x18_v, y18_v); + TEST_CHECK("20060825000008AAN", allequal_ullong2( res_v, r18_v ), 0); + res_v = (vec_ullong2)islessequald2(x19_v, y19_v); + TEST_CHECK("20060825000009AAN", allequal_ullong2( res_v, r19_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/islessequalf4.c b/Extras/simdmathlibrary/spu/tests/islessequalf4.c new file mode 100644 index 0000000..0960e1c --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/islessequalf4.c @@ -0,0 +1,151 @@ +/* Test islessequalf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060816000000AAN","AAN", "islessequalf4"); + + float x0 = hide_float(-0.0f); + float y0 = hide_float( 0.0f); + unsigned int r0 = 0xffffffff; + + float x1 = hide_float(FLT_MAX); //+Smax + float y1 = hide_float(-FLT_MAX); //-Smax + unsigned int r1 = 0x00000000; + + float x2 = hide_float(-0.0000000013152f); + float y2 = hide_float(-234245.85323441f); + unsigned int r2 = 0x00000000; + + float x3 = hide_float(-168.97345223013f); + float y3 = hide_float(-168.97345223013f); + unsigned int r3 = 0xffffffff; + + float x4 = hide_float(-83532.96153153f); + float y4 = hide_float(-FLT_MIN); //-Smin + unsigned int r4 = 0xffffffff; + + float x5 = hide_float(-321.01234567f); + float y5 = hide_float(876543.12345f); + unsigned int r5 = 0xffffffff; + + float x6 = hide_float(FLT_MIN); // Smin + float y6 = hide_float(0.0031529324f); + unsigned int r6 = 0xffffffff; + + float x7 = hide_float(5172.2845321f); + float y7 = hide_float(5172.2845321f); + unsigned int r7 = 0xffffffff; + + float x8 = hide_float(264.345643345f); + float y8 = hide_float(2353705.31415f); + unsigned int r8 = 0xffffffff; + + float x9 = hide_float(FLT_MAX); // Smax + float y9 = hide_float(9.43574552184f); + unsigned int r9 = 0x00000000; + + vec_float4 x0_v = spu_splats(x0); + vec_float4 y0_v = spu_splats(y0); + vec_uint4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_float4 y1_v = spu_splats(y1); + vec_uint4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_float4 y2_v = spu_splats(y2); + vec_uint4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_float4 y3_v = spu_splats(y3); + vec_uint4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_float4 y4_v = spu_splats(y4); + vec_uint4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_float4 y5_v = spu_splats(y5); + vec_uint4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_float4 y6_v = spu_splats(y6); + vec_uint4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_float4 y7_v = spu_splats(y7); + vec_uint4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_float4 y8_v = spu_splats(y8); + vec_uint4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_float4 y9_v = spu_splats(y9); + vec_uint4 r9_v = spu_splats(r9); + + vec_uint4 res_v; + + TEST_START("islessequalf4"); + + res_v = (vec_uint4)islessequalf4(x0_v, y0_v); + TEST_CHECK("20060816000000AAN", allequal_uint4( res_v, r0_v ), 0); + res_v = (vec_uint4)islessequalf4(x1_v, y1_v); + TEST_CHECK("20060816000001AAN", allequal_uint4( res_v, r1_v ), 0); + res_v = (vec_uint4)islessequalf4(x2_v, y2_v); + TEST_CHECK("20060816000002AAN", allequal_uint4( res_v, r2_v ), 0); + res_v = (vec_uint4)islessequalf4(x3_v, y3_v); + TEST_CHECK("20060816000003AAN", allequal_uint4( res_v, r3_v ), 0); + res_v = (vec_uint4)islessequalf4(x4_v, y4_v); + TEST_CHECK("20060816000004AAN", allequal_uint4( res_v, r4_v ), 0); + res_v = (vec_uint4)islessequalf4(x5_v, y5_v); + TEST_CHECK("20060816000005AAN", allequal_uint4( res_v, r5_v ), 0); + res_v = (vec_uint4)islessequalf4(x6_v, y6_v); + TEST_CHECK("20060816000006AAN", allequal_uint4( res_v, r6_v ), 0); + res_v = (vec_uint4)islessequalf4(x7_v, y7_v); + TEST_CHECK("20060816000007AAN", allequal_uint4( res_v, r7_v ), 0); + res_v = (vec_uint4)islessequalf4(x8_v, y8_v); + TEST_CHECK("20060816000008AAN", allequal_uint4( res_v, r8_v ), 0); + res_v = (vec_uint4)islessequalf4(x9_v, y9_v); + TEST_CHECK("20060816000009AAN", allequal_uint4( res_v, r9_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/islessf4.c b/Extras/simdmathlibrary/spu/tests/islessf4.c new file mode 100644 index 0000000..593cea6 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/islessf4.c @@ -0,0 +1,151 @@ +/* Test islessf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060815000000AAN","AAN", "islessf4"); + + float x0 = hide_float(-0.0f); + float y0 = hide_float( 0.0f); + unsigned int r0 = 0x00000000; + + float x1 = hide_float(FLT_MAX); //+Smax + float y1 = hide_float(-FLT_MAX); //-Smax + unsigned int r1 = 0x00000000; + + float x2 = hide_float(-0.0000000013152f); + float y2 = hide_float(-234245.85323441f); + unsigned int r2 = 0x00000000; + + float x3 = hide_float(-168.97345223013f); + float y3 = hide_float(-168.97345223013f); + unsigned int r3 = 0x00000000; + + float x4 = hide_float(-83532.96153153f); + float y4 = hide_float(-FLT_MIN); //-Smin + unsigned int r4 = 0xffffffff; + + float x5 = hide_float(-321.01234567f); + float y5 = hide_float(876543.12345f); + unsigned int r5 = 0xffffffff; + + float x6 = hide_float(FLT_MIN); // Smin + float y6 = hide_float(0.0031529324f); + unsigned int r6 = 0xffffffff; + + float x7 = hide_float(5172.2845321f); + float y7 = hide_float(5172.2845321f); + unsigned int r7 = 0x00000000; + + float x8 = hide_float(264.345643345f); + float y8 = hide_float(2353705.31415f); + unsigned int r8 = 0xffffffff; + + float x9 = hide_float(FLT_MAX); // Smax + float y9 = hide_float(9.43574552184f); + unsigned int r9 = 0x00000000; + + vec_float4 x0_v = spu_splats(x0); + vec_float4 y0_v = spu_splats(y0); + vec_uint4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_float4 y1_v = spu_splats(y1); + vec_uint4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_float4 y2_v = spu_splats(y2); + vec_uint4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_float4 y3_v = spu_splats(y3); + vec_uint4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_float4 y4_v = spu_splats(y4); + vec_uint4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_float4 y5_v = spu_splats(y5); + vec_uint4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_float4 y6_v = spu_splats(y6); + vec_uint4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_float4 y7_v = spu_splats(y7); + vec_uint4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_float4 y8_v = spu_splats(y8); + vec_uint4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_float4 y9_v = spu_splats(y9); + vec_uint4 r9_v = spu_splats(r9); + + vec_uint4 res_v; + + TEST_START("islessf4"); + + res_v = (vec_uint4)islessf4(x0_v, y0_v); + TEST_CHECK("20060815000000AAN", allequal_uint4( res_v, r0_v ), 0); + res_v = (vec_uint4)islessf4(x1_v, y1_v); + TEST_CHECK("20060815000001AAN", allequal_uint4( res_v, r1_v ), 0); + res_v = (vec_uint4)islessf4(x2_v, y2_v); + TEST_CHECK("20060815000002AAN", allequal_uint4( res_v, r2_v ), 0); + res_v = (vec_uint4)islessf4(x3_v, y3_v); + TEST_CHECK("20060815000003AAN", allequal_uint4( res_v, r3_v ), 0); + res_v = (vec_uint4)islessf4(x4_v, y4_v); + TEST_CHECK("20060815000004AAN", allequal_uint4( res_v, r4_v ), 0); + res_v = (vec_uint4)islessf4(x5_v, y5_v); + TEST_CHECK("20060815000005AAN", allequal_uint4( res_v, r5_v ), 0); + res_v = (vec_uint4)islessf4(x6_v, y6_v); + TEST_CHECK("20060815000006AAN", allequal_uint4( res_v, r6_v ), 0); + res_v = (vec_uint4)islessf4(x7_v, y7_v); + TEST_CHECK("20060815000007AAN", allequal_uint4( res_v, r7_v ), 0); + res_v = (vec_uint4)islessf4(x8_v, y8_v); + TEST_CHECK("20060815000008AAN", allequal_uint4( res_v, r8_v ), 0); + res_v = (vec_uint4)islessf4(x9_v, y9_v); + TEST_CHECK("20060815000009AAN", allequal_uint4( res_v, r9_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/islessgreaterd2.c b/Extras/simdmathlibrary/spu/tests/islessgreaterd2.c new file mode 100644 index 0000000..e16ec86 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/islessgreaterd2.c @@ -0,0 +1,271 @@ +/* Test islessgreaterd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060825000000AAN","AAN", "islessgreaterd2"); + + //-QNaN: NG + double x0 = hide_double(-nan("")); + double y0 = hide_double(1.0); + unsigned long long r0 = 0x0000000000000000ull; + + //+Inf > -Inf + double x1 = hide_double( HUGE_VAL); + double y1 = hide_double(-HUGE_VAL); + unsigned long long r1 = 0xffffffffffffffffull; + + //-Inf < -Dmax + double x2 = hide_double(-HUGE_VAL); + double y2 = hide_double(-DBL_MAX); + unsigned long long r2 = 0xffffffffffffffffull; + + //-Norm > -Inf + double x3 = hide_double(-67418234.34256245); + double y3 = hide_double(-HUGE_VAL); + unsigned long long r3 = 0xffffffffffffffffull; + + //-Norm < -Denorm + double x4 = hide_double(-273453.3234458053); + double y4 = hide_double(-3.0e-321); + unsigned long long r4 = 0xffffffffffffffffull; + + //-Norm = -Norm + double x5 = hide_double(-168.97345223013); + double y5 = hide_double(-168.97345223013); + unsigned long long r5 = 0x0000000000000000ull; + + //-Norm > -Norm + double x6 = hide_double(-168.97345223013); + double y6 = hide_double(-21345853556.492); + unsigned long long r6 = 0xffffffffffffffffull; + + //-Norm < -0 + double x7 = hide_double(-168.97345223013); + double y7 = hide_double(-0.0); + unsigned long long r7 = 0xffffffffffffffffull; + + //-Unf > -Norm + double x8 = hide_double(-1.0e-999); + double y8 = hide_double(-83532.96153153); + unsigned long long r8 = 0xffffffffffffffffull; + + //-Unf = 0 + double x9 = hide_double(-1.0e-999); + double y9 = hide_double(0.0); + unsigned long long r9 = 0x0000000000000000ull; + + //-0 = 0 + double x10 = hide_double(-0.0); + double y10 = hide_double( 0.0); + unsigned long long r10 = 0x0000000000000000ull; + + //+Unf = 0 + double x11 = hide_double( 1.0e-999); + double y11 = hide_double( 0.0); + unsigned long long r11 = 0x0000000000000000ull; + + //+Unf < +Norm + double x12 = hide_double( 1e-999); + double y12 = hide_double(0.0031529324); + unsigned long long r12 = 0xffffffffffffffffull; + + //+Norm > +Denorm + double x13 = hide_double(5172.2845321); + double y13 = hide_double(3.0e-321); + unsigned long long r13 = 0xffffffffffffffffull; + + //+Norm = +Norm + double x14 = hide_double(5172.2845321); + double y14 = hide_double(5172.2845321); + unsigned long long r14 = 0x0000000000000000ull; + + //+Norm < +Norm + double x15 = hide_double(264.345643345); + double y15 = hide_double(2353705.31415); + unsigned long long r15 = 0xffffffffffffffffull; + + //+Norm > -Norm + double x16 = hide_double( 926.605118542); + double y16 = hide_double(-9.43574552184); + unsigned long long r16 = 0xffffffffffffffffull; + + //+Norm < +Dmax + double x17 = hide_double( 926.605118542); + double y17 = hide_double(DBL_MAX); + unsigned long long r17 = 0xffffffffffffffffull; + + //+Inf > +Dmax + double x18 = hide_double(HUGE_VAL); + double y18 = hide_double(DBL_MAX); + unsigned long long r18 = 0xffffffffffffffffull; + + //+QNaN: NG + double x19 = hide_double(nan("")); + double y19 = hide_double(3.14); + unsigned long long r19 = 0x0000000000000000ull; + + vec_double2 x0_v = spu_splats(x0); + vec_double2 y0_v = spu_splats(y0); + vec_ullong2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_double2 y1_v = spu_splats(y1); + vec_ullong2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_double2 y2_v = spu_splats(y2); + vec_ullong2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_double2 y3_v = spu_splats(y3); + vec_ullong2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_double2 y4_v = spu_splats(y4); + vec_ullong2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_double2 y5_v = spu_splats(y5); + vec_ullong2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_double2 y6_v = spu_splats(y6); + vec_ullong2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_double2 y7_v = spu_splats(y7); + vec_ullong2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_double2 y8_v = spu_splats(y8); + vec_ullong2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_double2 y9_v = spu_splats(y9); + vec_ullong2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_double2 y10_v = spu_splats(y10); + vec_ullong2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_double2 y11_v = spu_splats(y11); + vec_ullong2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_double2 y12_v = spu_splats(y12); + vec_ullong2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_double2 y13_v = spu_splats(y13); + vec_ullong2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_double2 y14_v = spu_splats(y14); + vec_ullong2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_double2 y15_v = spu_splats(y15); + vec_ullong2 r15_v = spu_splats(r15); + + vec_double2 x16_v = spu_splats(x16); + vec_double2 y16_v = spu_splats(y16); + vec_ullong2 r16_v = spu_splats(r16); + + vec_double2 x17_v = spu_splats(x17); + vec_double2 y17_v = spu_splats(y17); + vec_ullong2 r17_v = spu_splats(r17); + + vec_double2 x18_v = spu_splats(x18); + vec_double2 y18_v = spu_splats(y18); + vec_ullong2 r18_v = spu_splats(r18); + + vec_double2 x19_v = spu_splats(x19); + vec_double2 y19_v = spu_splats(y19); + vec_ullong2 r19_v = spu_splats(r19); + + vec_ullong2 res_v; + + TEST_START("islessgreaterd2"); + + res_v = (vec_ullong2)islessgreaterd2(x0_v, y0_v); + TEST_CHECK("20060825000000AAN", allequal_ullong2( res_v, r0_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x1_v, y1_v); + TEST_CHECK("20060825000001AAN", allequal_ullong2( res_v, r1_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x2_v, y2_v); + TEST_CHECK("20060825000002AAN", allequal_ullong2( res_v, r2_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x3_v, y3_v); + TEST_CHECK("20060825000003AAN", allequal_ullong2( res_v, r3_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x4_v, y4_v); + TEST_CHECK("20060825000004AAN", allequal_ullong2( res_v, r4_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x5_v, y5_v); + TEST_CHECK("20060825000005AAN", allequal_ullong2( res_v, r5_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x6_v, y6_v); + TEST_CHECK("20060825000006AAN", allequal_ullong2( res_v, r6_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x7_v, y7_v); + TEST_CHECK("20060825000007AAN", allequal_ullong2( res_v, r7_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x8_v, y8_v); + TEST_CHECK("20060825000008AAN", allequal_ullong2( res_v, r8_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x9_v, y9_v); + TEST_CHECK("20060825000009AAN", allequal_ullong2( res_v, r9_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x10_v, y10_v); + TEST_CHECK("20060825000000AAN", allequal_ullong2( res_v, r10_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x11_v, y11_v); + TEST_CHECK("20060825000001AAN", allequal_ullong2( res_v, r11_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x12_v, y12_v); + TEST_CHECK("20060825000002AAN", allequal_ullong2( res_v, r12_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x13_v, y13_v); + TEST_CHECK("20060825000003AAN", allequal_ullong2( res_v, r13_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x14_v, y14_v); + TEST_CHECK("20060825000004AAN", allequal_ullong2( res_v, r14_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x15_v, y15_v); + TEST_CHECK("20060825000005AAN", allequal_ullong2( res_v, r15_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x16_v, y16_v); + TEST_CHECK("20060825000006AAN", allequal_ullong2( res_v, r16_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x17_v, y17_v); + TEST_CHECK("20060825000007AAN", allequal_ullong2( res_v, r17_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x18_v, y18_v); + TEST_CHECK("20060825000008AAN", allequal_ullong2( res_v, r18_v ), 0); + res_v = (vec_ullong2)islessgreaterd2(x19_v, y19_v); + TEST_CHECK("20060825000009AAN", allequal_ullong2( res_v, r19_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/islessgreaterf4.c b/Extras/simdmathlibrary/spu/tests/islessgreaterf4.c new file mode 100644 index 0000000..ae8e123 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/islessgreaterf4.c @@ -0,0 +1,151 @@ +/* Test islessgreaterf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060816000000AAN","AAN", "islessgreaterf4"); + + float x0 = hide_float(-0.0f); + float y0 = hide_float( 0.0f); + unsigned int r0 = 0x00000000; + + float x1 = hide_float( FLT_MAX); //+Smax + float y1 = hide_float(-FLT_MAX); //-Smax + unsigned int r1 = 0xffffffff; + + float x2 = hide_float(-0.0000000013152f); + float y2 = hide_float(-234245.85323441f); + unsigned int r2 = 0xffffffff; + + float x3 = hide_float(-168.97345223013f); + float y3 = hide_float(-168.97345223013f); + unsigned int r3 = 0x00000000; + + float x4 = hide_float(-83532.96153153f); + float y4 = hide_float(-1e-999); //-Smin + unsigned int r4 = 0xffffffff; + + float x5 = hide_float(-321.01234567f); + float y5 = hide_float(876543.12345f); + unsigned int r5 = 0xffffffff; + + float x6 = hide_float( 1e-999); // Smin + float y6 = hide_float(0.0031529324f); + unsigned int r6 = 0xffffffff; + + float x7 = hide_float(5172.2845321f); + float y7 = hide_float(5172.2845321f); + unsigned int r7 = 0x00000000; + + float x8 = hide_float(264.345643345f); + float y8 = hide_float(2353705.31415f); + unsigned int r8 = 0xffffffff; + + float x9 = hide_float(FLT_MAX); // Smax + float y9 = hide_float(9.43574552184f); + unsigned int r9 = 0xffffffff; + + vec_float4 x0_v = spu_splats(x0); + vec_float4 y0_v = spu_splats(y0); + vec_uint4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_float4 y1_v = spu_splats(y1); + vec_uint4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_float4 y2_v = spu_splats(y2); + vec_uint4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_float4 y3_v = spu_splats(y3); + vec_uint4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_float4 y4_v = spu_splats(y4); + vec_uint4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_float4 y5_v = spu_splats(y5); + vec_uint4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_float4 y6_v = spu_splats(y6); + vec_uint4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_float4 y7_v = spu_splats(y7); + vec_uint4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_float4 y8_v = spu_splats(y8); + vec_uint4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_float4 y9_v = spu_splats(y9); + vec_uint4 r9_v = spu_splats(r9); + + vec_uint4 res_v; + + TEST_START("islessgreaterf4"); + + res_v = (vec_uint4)islessgreaterf4(x0_v, y0_v); + TEST_CHECK("20060816000000AAN", allequal_uint4( res_v, r0_v ), 0); + res_v = (vec_uint4)islessgreaterf4(x1_v, y1_v); + TEST_CHECK("20060816000001AAN", allequal_uint4( res_v, r1_v ), 0); + res_v = (vec_uint4)islessgreaterf4(x2_v, y2_v); + TEST_CHECK("20060816000002AAN", allequal_uint4( res_v, r2_v ), 0); + res_v = (vec_uint4)islessgreaterf4(x3_v, y3_v); + TEST_CHECK("20060816000003AAN", allequal_uint4( res_v, r3_v ), 0); + res_v = (vec_uint4)islessgreaterf4(x4_v, y4_v); + TEST_CHECK("20060816000004AAN", allequal_uint4( res_v, r4_v ), 0); + res_v = (vec_uint4)islessgreaterf4(x5_v, y5_v); + TEST_CHECK("20060816000005AAN", allequal_uint4( res_v, r5_v ), 0); + res_v = (vec_uint4)islessgreaterf4(x6_v, y6_v); + TEST_CHECK("20060816000006AAN", allequal_uint4( res_v, r6_v ), 0); + res_v = (vec_uint4)islessgreaterf4(x7_v, y7_v); + TEST_CHECK("20060816000007AAN", allequal_uint4( res_v, r7_v ), 0); + res_v = (vec_uint4)islessgreaterf4(x8_v, y8_v); + TEST_CHECK("20060816000008AAN", allequal_uint4( res_v, r8_v ), 0); + res_v = (vec_uint4)islessgreaterf4(x9_v, y9_v); + TEST_CHECK("20060816000009AAN", allequal_uint4( res_v, r9_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/isnand2.c b/Extras/simdmathlibrary/spu/tests/isnand2.c new file mode 100644 index 0000000..9d42a7d --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/isnand2.c @@ -0,0 +1,226 @@ +/* Test isnand2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060830000000AAN","AAN", "isnand2"); + + // -QNan + double x0 = hide_double(-nan("")); + unsigned long long r0 = 0xffffffffffffffffull; + + // -Inf + double x1 = hide_double(-HUGE_VAL); + unsigned long long r1 = 0x0000000000000000ull; + + // -Dmax + double x2 = hide_double(-DBL_MAX); + unsigned long long r2 = 0x0000000000000000ull; + + // -QNaN + double x3 = hide_double(make_double(0xFFFFFFFFFFFFFFFFull)); + unsigned long long r3 = 0xffffffffffffffffull; + + // -SNaN + double x4 = hide_double(make_double(0xFFF7FFFFFFFFFFFFull)); + unsigned long long r4 = 0xffffffffffffffffull; + + // -Denorm + double x5 = hide_double(-2.40e-310); + unsigned long long r5 = 0x0000000000000000ull; + + // -Unf + double x6 = hide_double(-1.0e-999); + unsigned long long r6 = 0x0000000000000000ull; + + // -0 + double x7 = hide_double(-0.0); + unsigned long long r7 = 0x0000000000000000ull; + + // 0 + double x8 = hide_double( 0.0); + unsigned long long r8 = 0x0000000000000000ull; + + // +Inf + double x9 = hide_double( 1.0e999); + unsigned long long r9 = 0x0000000000000000ull; + + // +QNaN + double x10 = hide_double(make_double(0x7FFFFFFFFFFFFFFFull)); + unsigned long long r10 = 0xffffffffffffffffull; + + // +Dmin + double x11 = hide_double( DBL_MIN); + unsigned long long r11 = 0x0000000000000000ull; + + // +Norm + double x12 = hide_double(3.14152634); + unsigned long long r12 = 0x0000000000000000ull; + + // +SNaN + double x13 = hide_double(make_double(0x7FF3333333333333ull)); + unsigned long long r13 = 0xffffffffffffffffull; + + // +Inf + double x14 = hide_double(HUGE_VAL); + unsigned long long r14 = 0x0000000000000000ull; + + //+Nan + double x15 = hide_double( nan("")); + unsigned long long r15 = 0xffffffffffffffffull; + + // Compound + vec_double2 x16_v = (vec_double2) {make_double(0xFFF7000000000000ull), -1.0e-999 }; + vec_ullong2 r16_v = (vec_ullong2) {0xffffffffffffffffull, 0x0000000000000000ull}; + + // Compound + vec_double2 x17_v = (vec_double2) { 345.27533, -2.40e-310 }; + vec_ullong2 r17_v = (vec_ullong2) {0x0000000000000000ull, 0x0000000000000000ull}; + + // Compound + vec_double2 x18_v = (vec_double2) { nan(""), -3678342.8765343 }; + vec_ullong2 r18_v = (vec_ullong2) {0xffffffffffffffffull, 0x0000000000000000ull}; + + // Compound + vec_double2 x19_v = (vec_double2) { HUGE_VAL, -nan("") }; + vec_ullong2 r19_v = (vec_ullong2) {0x0000000000000000ull, 0xffffffffffffffffull}; + + // Compound + vec_double2 x20_v = (vec_double2) { make_double(0x7FF8000000000000ull), -HUGE_VAL} ; + vec_ullong2 r20_v = (vec_ullong2) {0xffffffffffffffffull, 0x0000000000000000ull}; + + vec_double2 x0_v = spu_splats(x0); + vec_ullong2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_ullong2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_ullong2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_ullong2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_ullong2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_ullong2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_ullong2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_ullong2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_ullong2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_ullong2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_ullong2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_ullong2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_ullong2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_ullong2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_ullong2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_ullong2 r15_v = spu_splats(r15); + + vec_ullong2 res_v; + + TEST_START("isnand2"); + + res_v = (vec_ullong2)isnand2(x0_v); + TEST_CHECK("20060830000000AAN", allequal_ullong2( res_v, r0_v ), 0); + res_v = (vec_ullong2)isnand2(x1_v); + TEST_CHECK("20060830000001AAN", allequal_ullong2( res_v, r1_v ), 0); + res_v = (vec_ullong2)isnand2(x2_v); + TEST_CHECK("20060830000002AAN", allequal_ullong2( res_v, r2_v ), 0); + res_v = (vec_ullong2)isnand2(x3_v); + TEST_CHECK("20060830000003AAN", allequal_ullong2( res_v, r3_v ), 0); + res_v = (vec_ullong2)isnand2(x4_v); + TEST_CHECK("20060830000004AAN", allequal_ullong2( res_v, r4_v ), 0); + res_v = (vec_ullong2)isnand2(x5_v); + TEST_CHECK("20060830000005AAN", allequal_ullong2( res_v, r5_v ), 0); + res_v = (vec_ullong2)isnand2(x6_v); + TEST_CHECK("20060830000006AAN", allequal_ullong2( res_v, r6_v ), 0); + res_v = (vec_ullong2)isnand2(x7_v); + TEST_CHECK("20060830000007AAN", allequal_ullong2( res_v, r7_v ), 0); + res_v = (vec_ullong2)isnand2(x8_v); + TEST_CHECK("20060830000008AAN", allequal_ullong2( res_v, r8_v ), 0); + res_v = (vec_ullong2)isnand2(x9_v); + TEST_CHECK("20060830000009AAN", allequal_ullong2( res_v, r9_v ), 0); + res_v = (vec_ullong2)isnand2(x10_v); + TEST_CHECK("20060830000010AAN", allequal_ullong2( res_v, r10_v ), 0); + res_v = (vec_ullong2)isnand2(x11_v); + TEST_CHECK("20060830000011AAN", allequal_ullong2( res_v, r11_v ), 0); + res_v = (vec_ullong2)isnand2(x12_v); + TEST_CHECK("20060830000012AAN", allequal_ullong2( res_v, r12_v ), 0); + res_v = (vec_ullong2)isnand2(x13_v); + TEST_CHECK("20060830000013AAN", allequal_ullong2( res_v, r13_v ), 0); + res_v = (vec_ullong2)isnand2(x14_v); + TEST_CHECK("20060830000014AAN", allequal_ullong2( res_v, r14_v ), 0); + res_v = (vec_ullong2)isnand2(x15_v); + TEST_CHECK("20060830000015AAN", allequal_ullong2( res_v, r15_v ), 0); + res_v = (vec_ullong2)isnand2(x16_v); + TEST_CHECK("20060830000016AAN", allequal_ullong2( res_v, r16_v ), 0); + res_v = (vec_ullong2)isnand2(x17_v); + TEST_CHECK("20060830000017AAN", allequal_ullong2( res_v, r17_v ), 0); + res_v = (vec_ullong2)isnand2(x18_v); + TEST_CHECK("20060830000018AAN", allequal_ullong2( res_v, r18_v ), 0); + res_v = (vec_ullong2)isnand2(x19_v); + TEST_CHECK("20060830000019AAN", allequal_ullong2( res_v, r19_v ), 0); + res_v = (vec_ullong2)isnand2(x20_v); + TEST_CHECK("20060830000020AAN", allequal_ullong2( res_v, r20_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/isnanf4.c b/Extras/simdmathlibrary/spu/tests/isnanf4.c new file mode 100644 index 0000000..c0c5572 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/isnanf4.c @@ -0,0 +1,130 @@ +/* Test isnanf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060822000000AAN","AAN", "isnanf4"); + + float x0 = hide_float(-0.0f); + unsigned int r0 = 0x00000000; + + float x1 = hide_float(-FLT_MAX); //-Smax + unsigned int r1 = 0x00000000; + + float x2 = hide_float(-0.0000000013152f); + unsigned int r2 = 0x00000000; + + float x3 = hide_float(-168.97345223013f); + unsigned int r3 = 0x00000000; + + float x4 = hide_float(-1e-999); //-Smin + unsigned int r4 = 0x00000000; + + float x5 = hide_float(876543.12345f); + unsigned int r5 = 0x00000000; + + float x6 = hide_float( 1e-999); // Smin + unsigned int r6 = 0x00000000; + + float x7 = hide_float(5172.2845321f); + unsigned int r7 = 0x00000000; + + float x8 = hide_float(2353705.31415f); + unsigned int r8 = 0x00000000; + + float x9 = hide_float(FLT_MAX); // Smax + unsigned int r9 = 0x00000000; + + vec_float4 x0_v = spu_splats(x0); + vec_uint4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_uint4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_uint4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_uint4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_uint4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_uint4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_uint4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_uint4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_uint4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_uint4 r9_v = spu_splats(r9); + + vec_uint4 res_v; + + TEST_START("isnanf4"); + + res_v = (vec_uint4)isnanf4(x0_v); + TEST_CHECK("20060822000000AAN", allequal_uint4( res_v, r0_v ), 0); + res_v = (vec_uint4)isnanf4(x1_v); + TEST_CHECK("20060822000001AAN", allequal_uint4( res_v, r1_v ), 0); + res_v = (vec_uint4)isnanf4(x2_v); + TEST_CHECK("20060822000002AAN", allequal_uint4( res_v, r2_v ), 0); + res_v = (vec_uint4)isnanf4(x3_v); + TEST_CHECK("20060822000003AAN", allequal_uint4( res_v, r3_v ), 0); + res_v = (vec_uint4)isnanf4(x4_v); + TEST_CHECK("20060822000004AAN", allequal_uint4( res_v, r4_v ), 0); + res_v = (vec_uint4)isnanf4(x5_v); + TEST_CHECK("20060822000005AAN", allequal_uint4( res_v, r5_v ), 0); + res_v = (vec_uint4)isnanf4(x6_v); + TEST_CHECK("20060822000006AAN", allequal_uint4( res_v, r6_v ), 0); + res_v = (vec_uint4)isnanf4(x7_v); + TEST_CHECK("20060822000007AAN", allequal_uint4( res_v, r7_v ), 0); + res_v = (vec_uint4)isnanf4(x8_v); + TEST_CHECK("20060822000008AAN", allequal_uint4( res_v, r8_v ), 0); + res_v = (vec_uint4)isnanf4(x9_v); + TEST_CHECK("20060822000009AAN", allequal_uint4( res_v, r9_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/isnormald2.c b/Extras/simdmathlibrary/spu/tests/isnormald2.c new file mode 100644 index 0000000..7200dd5 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/isnormald2.c @@ -0,0 +1,225 @@ +/* Test isnormald2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060830000000AAN","AAN", "isnormald2"); + + // -Nan + double x0 = hide_double(-nan("")); + unsigned long long r0 = 0x0000000000000000ull; + + // -Inf + double x1 = hide_double(-HUGE_VAL); + unsigned long long r1 = 0x0000000000000000ull; + + // -Dmax + double x2 = hide_double(-DBL_MAX); + unsigned long long r2 = 0xffffffffffffffffull; + + // -Norm + double x3 = hide_double(-824842.58421394); + unsigned long long r3 = 0xffffffffffffffffull; + + // -Dmin + double x4 = hide_double(-DBL_MIN); + unsigned long long r4 = 0xffffffffffffffffull; + + // -Denorm + double x5 = hide_double(-2.40e-310); + unsigned long long r5 = 0x0000000000000000ull; + + // -Unf + double x6 = hide_double(-1.0e-999); + unsigned long long r6 = 0x0000000000000000ull; + + // -0 + double x7 = hide_double(-0.0); + unsigned long long r7 = 0x0000000000000000ull; + + // 0 + double x8 = hide_double( 0.0); + unsigned long long r8 = 0x0000000000000000ull; + + // +Unf + double x9 = hide_double( 1.0e-999); + unsigned long long r9 = 0x0000000000000000ull; + + // +Denorm + double x10 = hide_double( 2.40e-310); + unsigned long long r10 = 0x0000000000000000ull; + + // +Dmin + double x11 = hide_double( DBL_MIN); + unsigned long long r11 = 0xffffffffffffffffull; + + // +Norm + double x12 = hide_double(3.14152634); + unsigned long long r12 = 0xffffffffffffffffull; + + // +Dmax + double x13 = hide_double(DBL_MAX); + unsigned long long r13 = 0xffffffffffffffffull; + + // +Inf + double x14 = hide_double(HUGE_VAL); + unsigned long long r14 = 0x0000000000000000ull; + + //+Nan + double x15 = hide_double( nan("")); + unsigned long long r15 = 0x0000000000000000ull; + + // Compound + vec_double2 x16_v = (vec_double2) {make_double(0x000AAAAAAAAAAAAAull), -1.0e-999 }; + vec_ullong2 r16_v = (vec_ullong2) {0x0000000000000000ull, 0x0000000000000000ull}; + + // Compound + vec_double2 x17_v = (vec_double2) { 345.27533, -2.40e-310 }; + vec_ullong2 r17_v = (vec_ullong2) {0xffffffffffffffffull, 0x0000000000000000ull}; + + // Compound + vec_double2 x18_v = (vec_double2) { nan(""), -3678342.8765343 }; + vec_ullong2 r18_v = (vec_ullong2) {0x0000000000000000ull, 0xffffffffffffffffull}; + + // Compound + vec_double2 x19_v = (vec_double2) { HUGE_VAL, -nan("") }; + vec_ullong2 r19_v = (vec_ullong2) {0x0000000000000000ull, 0x0000000000000000ull}; + + // Compound + vec_double2 x20_v = (vec_double2) { -1.0e-999, -HUGE_VAL}; + vec_ullong2 r20_v = (vec_ullong2) {0x0000000000000000ull, 0x0000000000000000ull}; + + vec_double2 x0_v = spu_splats(x0); + vec_ullong2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_ullong2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_ullong2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_ullong2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_ullong2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_ullong2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_ullong2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_ullong2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_ullong2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_ullong2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_ullong2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_ullong2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_ullong2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_ullong2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_ullong2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_ullong2 r15_v = spu_splats(r15); + + vec_ullong2 res_v; + + TEST_START("isnormald2"); + + res_v = (vec_ullong2)isnormald2(x0_v); + TEST_CHECK("20060830000000AAN", allequal_ullong2( res_v, r0_v ), 0); + res_v = (vec_ullong2)isnormald2(x1_v); + TEST_CHECK("20060830000001AAN", allequal_ullong2( res_v, r1_v ), 0); + res_v = (vec_ullong2)isnormald2(x2_v); + TEST_CHECK("20060830000002AAN", allequal_ullong2( res_v, r2_v ), 0); + res_v = (vec_ullong2)isnormald2(x3_v); + TEST_CHECK("20060830000003AAN", allequal_ullong2( res_v, r3_v ), 0); + res_v = (vec_ullong2)isnormald2(x4_v); + TEST_CHECK("20060830000004AAN", allequal_ullong2( res_v, r4_v ), 0); + res_v = (vec_ullong2)isnormald2(x5_v); + TEST_CHECK("20060830000005AAN", allequal_ullong2( res_v, r5_v ), 0); + res_v = (vec_ullong2)isnormald2(x6_v); + TEST_CHECK("20060830000006AAN", allequal_ullong2( res_v, r6_v ), 0); + res_v = (vec_ullong2)isnormald2(x7_v); + TEST_CHECK("20060830000007AAN", allequal_ullong2( res_v, r7_v ), 0); + res_v = (vec_ullong2)isnormald2(x8_v); + TEST_CHECK("20060830000008AAN", allequal_ullong2( res_v, r8_v ), 0); + res_v = (vec_ullong2)isnormald2(x9_v); + TEST_CHECK("20060830000009AAN", allequal_ullong2( res_v, r9_v ), 0); + res_v = (vec_ullong2)isnormald2(x10_v); + TEST_CHECK("20060830000010AAN", allequal_ullong2( res_v, r10_v ), 0); + res_v = (vec_ullong2)isnormald2(x11_v); + TEST_CHECK("20060830000011AAN", allequal_ullong2( res_v, r11_v ), 0); + res_v = (vec_ullong2)isnormald2(x12_v); + TEST_CHECK("20060830000012AAN", allequal_ullong2( res_v, r12_v ), 0); + res_v = (vec_ullong2)isnormald2(x13_v); + TEST_CHECK("20060830000013AAN", allequal_ullong2( res_v, r13_v ), 0); + res_v = (vec_ullong2)isnormald2(x14_v); + TEST_CHECK("20060830000014AAN", allequal_ullong2( res_v, r14_v ), 0); + res_v = (vec_ullong2)isnormald2(x15_v); + TEST_CHECK("20060830000015AAN", allequal_ullong2( res_v, r15_v ), 0); + res_v = (vec_ullong2)isnormald2(x16_v); + TEST_CHECK("20060830000016AAN", allequal_ullong2( res_v, r16_v ), 0); + res_v = (vec_ullong2)isnormald2(x17_v); + TEST_CHECK("20060830000017AAN", allequal_ullong2( res_v, r17_v ), 0); + res_v = (vec_ullong2)isnormald2(x18_v); + TEST_CHECK("20060830000018AAN", allequal_ullong2( res_v, r18_v ), 0); + res_v = (vec_ullong2)isnormald2(x19_v); + TEST_CHECK("20060830000019AAN", allequal_ullong2( res_v, r19_v ), 0); + res_v = (vec_ullong2)isnormald2(x20_v); + TEST_CHECK("20060830000020AAN", allequal_ullong2( res_v, r20_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/isnormalf4.c b/Extras/simdmathlibrary/spu/tests/isnormalf4.c new file mode 100644 index 0000000..30cde09 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/isnormalf4.c @@ -0,0 +1,131 @@ +/* Test isnormalf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060822000000AAN","AAN", "isnormalf4"); + + float x0 = hide_float(-0.0f); + unsigned int r0 = 0x00000000; + + float x1 = hide_float(-FLT_MAX); //-Smax + unsigned int r1 = 0xffffffff; + + float x2 = hide_float( 0.0f); + unsigned int r2 = 0x00000000; + + float x3 = hide_float(-168.97345223013f); + unsigned int r3 = 0xffffffff; + + float x4 = hide_float(-1e-999); //-Smin + unsigned int r4 = 0x00000000; + + float x5 = hide_float(876543.12345f); + unsigned int r5 = 0xffffffff; + + float x6 = hide_float(1e-999); // Smin + unsigned int r6 = 0x00000000; + + float x7 = hide_float(5172.2845321f); + unsigned int r7 = 0xffffffff; + + float x8 = hide_float(2353705.31415f); + unsigned int r8 = 0xffffffff; + + float x9 = hide_float(FLT_MAX); // Smax + unsigned int r9 = 0xffffffff; + + vec_float4 x0_v = spu_splats(x0); + vec_uint4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_uint4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_uint4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_uint4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_uint4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_uint4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_uint4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_uint4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_uint4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_uint4 r9_v = spu_splats(r9); + + vec_uint4 res_v; + + TEST_START("isnormalf4"); + + res_v = (vec_uint4)isnormalf4(x0_v); + TEST_CHECK("20060822000000AAN", allequal_uint4( res_v, r0_v ), 0); + res_v = (vec_uint4)isnormalf4(x1_v); + TEST_CHECK("20060822000001AAN", allequal_uint4( res_v, r1_v ), 0); + res_v = (vec_uint4)isnormalf4(x2_v); + TEST_CHECK("20060822000002AAN", allequal_uint4( res_v, r2_v ), 0); + res_v = (vec_uint4)isnormalf4(x3_v); + TEST_CHECK("20060822000003AAN", allequal_uint4( res_v, r3_v ), 0); + res_v = (vec_uint4)isnormalf4(x4_v); + TEST_CHECK("20060822000004AAN", allequal_uint4( res_v, r4_v ), 0); + res_v = (vec_uint4)isnormalf4(x5_v); + TEST_CHECK("20060822000005AAN", allequal_uint4( res_v, r5_v ), 0); + res_v = (vec_uint4)isnormalf4(x6_v); + TEST_CHECK("20060822000006AAN", allequal_uint4( res_v, r6_v ), 0); + res_v = (vec_uint4)isnormalf4(x7_v); + TEST_CHECK("20060822000007AAN", allequal_uint4( res_v, r7_v ), 0); + res_v = (vec_uint4)isnormalf4(x8_v); + TEST_CHECK("20060822000008AAN", allequal_uint4( res_v, r8_v ), 0); + res_v = (vec_uint4)isnormalf4(x9_v); + TEST_CHECK("20060822000009AAN", allequal_uint4( res_v, r9_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/isunorderedd2.c b/Extras/simdmathlibrary/spu/tests/isunorderedd2.c new file mode 100644 index 0000000..4f562b3 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/isunorderedd2.c @@ -0,0 +1,271 @@ +/* Test isunorderedd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060830000000AAN","AAN", "isunorderedd2"); + + //-QNaN, Norm + double x0 = hide_double(-nan("")); + double y0 = hide_double(1.0); + unsigned long long r0 = 0xffffffffffffffffull; + + //+Inf, -Inf + double x1 = hide_double( HUGE_VAL); + double y1 = hide_double(-HUGE_VAL); + unsigned long long r1 = 0x0000000000000000ull; + + //-Inf, -QNaN + double x2 = hide_double(-HUGE_VAL); + double y2 = hide_double(make_double(0xFFFFFFFFFFFFFFFFull)); + unsigned long long r2 = 0xffffffffffffffffull; + + //-Norm, -SNaN + double x3 = hide_double(-67418234.34256245); + double y3 = hide_double(make_double(0xFFF7FFFFFFFFFFFFull)); + unsigned long long r3 = 0xffffffffffffffffull; + + //-Norm, -Denorm + double x4 = hide_double(-273453.3234458053); + double y4 = hide_double(-3.0e-321); + unsigned long long r4 = 0x0000000000000000ull; + + //-Norm, -Inf + double x5 = hide_double(-168.97345223013); + double y5 = hide_double(-HUGE_VAL); + unsigned long long r5 = 0x0000000000000000ull; + + //-QNaN, -Norm + double x6 = hide_double(-nan("")); + double y6 = hide_double(-21345853556.492); + unsigned long long r6 = 0xffffffffffffffffull; + + //-Norm, -0 + double x7 = hide_double(-168.97345223013); + double y7 = hide_double(-0.0); + unsigned long long r7 = 0x0000000000000000ull; + + //-Unf, -Norm + double x8 = hide_double(-1.0e-999); + double y8 = hide_double(-83532.96153153); + unsigned long long r8 = 0x0000000000000000ull; + + //-Unf, 0 + double x9 = hide_double(-1.0e-999); + double y9 = hide_double(0.0); + unsigned long long r9 = 0x0000000000000000ull; + + //QNaN, 0 + double x10 = hide_double(make_double(0x7FFFFFFFFFFFFFFFull)); + double y10 = hide_double( 0.0); + unsigned long long r10 = 0xffffffffffffffffull; + + //+Unf, +QNaN + double x11 = hide_double( 1.0e-999); + double y11 = hide_double( nan("")); + unsigned long long r11 = 0xffffffffffffffffull; + + //+Unf, +Norm + double x12 = hide_double( 1e-999); + double y12 = hide_double(0.0031529324); + unsigned long long r12 = 0x0000000000000000ull; + + //+Norm, +Denorm + double x13 = hide_double(5172.2845321); + double y13 = hide_double(3.0e-321); + unsigned long long r13 = 0x0000000000000000ull; + + //+SNaN, +Norm + double x14 = hide_double(make_double(0x7FF3333333333333ull)); + double y14 = hide_double(5172.2845321); + unsigned long long r14 = 0xffffffffffffffffull; + + //+Norm, +QNaN + double x15 = hide_double(264.345643345); + double y15 = hide_double(make_double(0x7FFAAAAAAAAAAAAAull)); + unsigned long long r15 = 0xffffffffffffffffull; + + //+Norm, -Norm + double x16 = hide_double( 926.605118542); + double y16 = hide_double(-9.43574552184); + unsigned long long r16 = 0x0000000000000000ull; + + //+Norm, +Dmax + double x17 = hide_double( 926.605118542); + double y17 = hide_double(DBL_MAX); + unsigned long long r17 = 0x0000000000000000ull; + + //+Inf, +Ovf + double x18 = hide_double( HUGE_VAL); + double y18 = hide_double( 1.0e999); + unsigned long long r18 = 0x0000000000000000ull; + + //+Inf, +QNaN + double x19 = hide_double( HUGE_VAL); + double y19 = hide_double(nan("")); + unsigned long long r19 = 0xffffffffffffffffull; + + vec_double2 x0_v = spu_splats(x0); + vec_double2 y0_v = spu_splats(y0); + vec_ullong2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_double2 y1_v = spu_splats(y1); + vec_ullong2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_double2 y2_v = spu_splats(y2); + vec_ullong2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_double2 y3_v = spu_splats(y3); + vec_ullong2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_double2 y4_v = spu_splats(y4); + vec_ullong2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_double2 y5_v = spu_splats(y5); + vec_ullong2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_double2 y6_v = spu_splats(y6); + vec_ullong2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_double2 y7_v = spu_splats(y7); + vec_ullong2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_double2 y8_v = spu_splats(y8); + vec_ullong2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_double2 y9_v = spu_splats(y9); + vec_ullong2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_double2 y10_v = spu_splats(y10); + vec_ullong2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_double2 y11_v = spu_splats(y11); + vec_ullong2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_double2 y12_v = spu_splats(y12); + vec_ullong2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_double2 y13_v = spu_splats(y13); + vec_ullong2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_double2 y14_v = spu_splats(y14); + vec_ullong2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_double2 y15_v = spu_splats(y15); + vec_ullong2 r15_v = spu_splats(r15); + + vec_double2 x16_v = spu_splats(x16); + vec_double2 y16_v = spu_splats(y16); + vec_ullong2 r16_v = spu_splats(r16); + + vec_double2 x17_v = spu_splats(x17); + vec_double2 y17_v = spu_splats(y17); + vec_ullong2 r17_v = spu_splats(r17); + + vec_double2 x18_v = spu_splats(x18); + vec_double2 y18_v = spu_splats(y18); + vec_ullong2 r18_v = spu_splats(r18); + + vec_double2 x19_v = spu_splats(x19); + vec_double2 y19_v = spu_splats(y19); + vec_ullong2 r19_v = spu_splats(r19); + + vec_ullong2 res_v; + + TEST_START("isunorderedd2"); + + res_v = (vec_ullong2)isunorderedd2(x0_v, y0_v); + TEST_CHECK("20060830000000AAN", allequal_ullong2( res_v, r0_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x1_v, y1_v); + TEST_CHECK("20060830000001AAN", allequal_ullong2( res_v, r1_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x2_v, y2_v); + TEST_CHECK("20060830000002AAN", allequal_ullong2( res_v, r2_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x3_v, y3_v); + TEST_CHECK("20060830000003AAN", allequal_ullong2( res_v, r3_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x4_v, y4_v); + TEST_CHECK("20060830000004AAN", allequal_ullong2( res_v, r4_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x5_v, y5_v); + TEST_CHECK("20060830000005AAN", allequal_ullong2( res_v, r5_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x6_v, y6_v); + TEST_CHECK("20060830000006AAN", allequal_ullong2( res_v, r6_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x7_v, y7_v); + TEST_CHECK("20060830000007AAN", allequal_ullong2( res_v, r7_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x8_v, y8_v); + TEST_CHECK("20060830000008AAN", allequal_ullong2( res_v, r8_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x9_v, y9_v); + TEST_CHECK("20060830000009AAN", allequal_ullong2( res_v, r9_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x10_v, y10_v); + TEST_CHECK("20060830000010AAN", allequal_ullong2( res_v, r10_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x11_v, y11_v); + TEST_CHECK("20060830000011AAN", allequal_ullong2( res_v, r11_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x12_v, y12_v); + TEST_CHECK("20060830000012AAN", allequal_ullong2( res_v, r12_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x13_v, y13_v); + TEST_CHECK("20060830000013AAN", allequal_ullong2( res_v, r13_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x14_v, y14_v); + TEST_CHECK("20060830000014AAN", allequal_ullong2( res_v, r14_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x15_v, y15_v); + TEST_CHECK("20060830000015AAN", allequal_ullong2( res_v, r15_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x16_v, y16_v); + TEST_CHECK("20060830000016AAN", allequal_ullong2( res_v, r16_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x17_v, y17_v); + TEST_CHECK("20060830000017AAN", allequal_ullong2( res_v, r17_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x18_v, y18_v); + TEST_CHECK("20060830000018AAN", allequal_ullong2( res_v, r18_v ), 0); + res_v = (vec_ullong2)isunorderedd2(x19_v, y19_v); + TEST_CHECK("20060830000019AAN", allequal_ullong2( res_v, r19_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/isunorderedf4.c b/Extras/simdmathlibrary/spu/tests/isunorderedf4.c new file mode 100644 index 0000000..d26a6c8 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/isunorderedf4.c @@ -0,0 +1,151 @@ +/* Test isunorderedf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060822000000AAN","AAN", "isunorderedf4"); + + float x0 = hide_float(-0.0f); + float y0 = hide_float( 0.0f); + unsigned int r0 = 0x00000000; + + float x1 = hide_float( FLT_MAX); //+Smax + float y1 = hide_float(-FLT_MAX); //-Smax + unsigned int r1 = 0x00000000; + + float x2 = hide_float(-0.0000000013152f); + float y2 = hide_float(-234245.85323441f); + unsigned int r2 = 0x00000000; + + float x3 = hide_float(-168.97345223013f); + float y3 = hide_float(-168.97345223013f); + unsigned int r3 = 0x00000000; + + float x4 = hide_float(-83532.96153153f); + float y4 = hide_float(-1e-999); //-Smin + unsigned int r4 = 0x00000000; + + float x5 = hide_float(-321.01234567f); + float y5 = hide_float(876543.12345f); + unsigned int r5 = 0x00000000; + + float x6 = hide_float( 1e-999); // Smin + float y6 = hide_float(0.0031529324f); + unsigned int r6 = 0x00000000; + + float x7 = hide_float(5172.2845321f); + float y7 = hide_float(5172.2845321f); + unsigned int r7 = 0x00000000; + + float x8 = hide_float(264.345643345f); + float y8 = hide_float(2353705.31415f); + unsigned int r8 = 0x00000000; + + float x9 = hide_float(FLT_MAX); // Smax + float y9 = hide_float(9.43574552184f); + unsigned int r9 = 0x00000000; + + vec_float4 x0_v = spu_splats(x0); + vec_float4 y0_v = spu_splats(y0); + vec_uint4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_float4 y1_v = spu_splats(y1); + vec_uint4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_float4 y2_v = spu_splats(y2); + vec_uint4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_float4 y3_v = spu_splats(y3); + vec_uint4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_float4 y4_v = spu_splats(y4); + vec_uint4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_float4 y5_v = spu_splats(y5); + vec_uint4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_float4 y6_v = spu_splats(y6); + vec_uint4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_float4 y7_v = spu_splats(y7); + vec_uint4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_float4 y8_v = spu_splats(y8); + vec_uint4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_float4 y9_v = spu_splats(y9); + vec_uint4 r9_v = spu_splats(r9); + + vec_uint4 res_v; + + TEST_START("isunorderedf4"); + + res_v = (vec_uint4)isunorderedf4(x0_v, y0_v); + TEST_CHECK("20060822000000AAN", allequal_uint4( res_v, r0_v ), 0); + res_v = (vec_uint4)isunorderedf4(x1_v, y1_v); + TEST_CHECK("20060822000001AAN", allequal_uint4( res_v, r1_v ), 0); + res_v = (vec_uint4)isunorderedf4(x2_v, y2_v); + TEST_CHECK("20060822000002AAN", allequal_uint4( res_v, r2_v ), 0); + res_v = (vec_uint4)isunorderedf4(x3_v, y3_v); + TEST_CHECK("20060822000003AAN", allequal_uint4( res_v, r3_v ), 0); + res_v = (vec_uint4)isunorderedf4(x4_v, y4_v); + TEST_CHECK("20060822000004AAN", allequal_uint4( res_v, r4_v ), 0); + res_v = (vec_uint4)isunorderedf4(x5_v, y5_v); + TEST_CHECK("20060822000005AAN", allequal_uint4( res_v, r5_v ), 0); + res_v = (vec_uint4)isunorderedf4(x6_v, y6_v); + TEST_CHECK("20060822000006AAN", allequal_uint4( res_v, r6_v ), 0); + res_v = (vec_uint4)isunorderedf4(x7_v, y7_v); + TEST_CHECK("20060822000007AAN", allequal_uint4( res_v, r7_v ), 0); + res_v = (vec_uint4)isunorderedf4(x8_v, y8_v); + TEST_CHECK("20060822000008AAN", allequal_uint4( res_v, r8_v ), 0); + res_v = (vec_uint4)isunorderedf4(x9_v, y9_v); + TEST_CHECK("20060822000009AAN", allequal_uint4( res_v, r9_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/ldexpd2.c b/Extras/simdmathlibrary/spu/tests/ldexpd2.c new file mode 100644 index 0000000..bb95982 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/ldexpd2.c @@ -0,0 +1,250 @@ +/* Test ldexpd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/** + * + *@@ ldexpd2 - Multiply Double by 2 Raised to its Power + * For large elements of ex (overflow), returns HUGE_VALF + * For small elements of ex (underflow), returns 0. + * + *@brief + * boundary test for ldexpd2. + * + * + *@pre + * + *@criteria + * Run this program and check no error will be occurred. + * + *@note + * + * + **/ + + +#include +#include +#include +//#include +#include + +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +#undef LDEXPD2_ROUND + + +typedef struct { + unsigned long long int xxx[2]; + unsigned long long int exp[2]; + unsigned long long int ans0[2]; + unsigned long long int ans1[2]; + unsigned long long int ans2[2]; + unsigned long long int ans3[2]; +} TestVec64_Ldexp; + +int main() +{ + TestVec64_Ldexp test_a[] = { + { + // zero + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000400ULL,0xFFFFFFFFFFFFFC00ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL} + },{ + // MIN , MAX + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL}, + {0x0000000000000001ULL,0x0000000000000001ULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL} + },{ + // Inf , -Inf + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x0000000000000001ULL,0x0000000000000001ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL} + },{ +#ifdef LDEXPD2_ROUND + // denotmalized + {0x8000000000000003ULL,0x0000000000000003ULL}, + {0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL}, + {0x8000000000000002ULL,0x0000000000000001ULL}, + {0x8000000000000001ULL,0x0000000000000002ULL}, + {0x8000000000000001ULL,0x0000000000000001ULL}, + {0x8000000000000002ULL,0x0000000000000002ULL} + },{ + // denotmalized -54 + {0x0010000000000001ULL,0x8010000000000001ULL}, + {0xFFFFFFFFFFFFFFCAULL,0xFFFFFFFFFFFFFFCAULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000001ULL,0x8000000000000001ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL} + },{ + // max -> ! + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0xFFFFFFFFFFFFF7CEULL,0xFFFFFFFFFFFFF7CEULL}, + {0x0000000000000001ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000001ULL,0x8000000000000001ULL}, + {0x0000000000000000ULL,0x8000000000000001ULL} + },{ + // max -> ! + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0xFFFFFFFFFFFFF7CDULL,0xFFFFFFFFFFFFF7CDULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000001ULL,0x8000000000000001ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL} + },{ +#else // LDEXPD2_ROUND + // denotmalized + {0x8000000000000003ULL,0x0000000000000003ULL}, + {0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL}, + {0x8000000000000001ULL,0x0000000000000001ULL}, + {0x8000000000000001ULL,0x0000000000000001ULL}, + {0x8000000000000001ULL,0x0000000000000001ULL}, + {0x8000000000000001ULL,0x0000000000000001ULL} + },{ + +#endif // LDEXPD2_ROUND + // denotmalized + {0x0010000000000000ULL,0x8010000000000000ULL}, + {0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL}, + {0x0008000000000000ULL,0x8008000000000000ULL}, + {0x0008000000000000ULL,0x8008000000000000ULL}, + {0x0008000000000000ULL,0x8008000000000000ULL}, + {0x0008000000000000ULL,0x8008000000000000ULL} + },{ + // denotmalized + {0x0008000000000000ULL,0x8008000000000000ULL}, + {0x0000000000000001ULL,0x0000000000000001ULL}, + {0x0010000000000000ULL,0x8010000000000000ULL}, + {0x0010000000000000ULL,0x8010000000000000ULL}, + {0x0010000000000000ULL,0x8010000000000000ULL}, + {0x0010000000000000ULL,0x8010000000000000ULL} + },{ + // 1.0 + {0x3ff0000000000000ULL,0xbff0000000000000ULL}, + {0x00000000000003ffULL,0x00000000000003ffULL}, + {0x7FE0000000000000ULL,0xFFE0000000000000ULL}, + {0x7FE0000000000000ULL,0xFFE0000000000000ULL}, + {0x7FE0000000000000ULL,0xFFE0000000000000ULL}, + {0x7FE0000000000000ULL,0xFFE0000000000000ULL} + },{ + // 1.0 -> max + {0x3ff0000000000000ULL,0xbff0000000000000ULL}, + {0x0000000000000400ULL,0x0000000000000400ULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL} + },{ + // max -> ! + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0xFFFFFFFF00000000ULL,0xFFFFFFFF00000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL} + },{ + // min-> + {0x0000000000000001ULL,0x8000000000000001ULL}, + {0x0FFFFFFFFFFFFFFFULL,0x0FFFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL} + },{ + // NaN , -NaN + {0x7FFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL}, + {0x0000000000000001ULL,0x0000000000000001ULL}, + {0x7FFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL}, + {0x7FFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL}, + {0x7FFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL}, + {0x7FFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL} + },{ + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL} + } + }; + int ii, test_ctr = 1; + char msg[80]; + vec_double2 res_v; + + TEST_SET_START("20060905160000NM","NM", "ldexpd2"); + + TEST_START("ldexpd2"); + + for (ii=0; ; ii++) { + if ( (test_a[ii].xxx[0] == 0) && (test_a[ii].xxx[1] == 0) ) break; + + // set Floating point round mode + spu_mtfpscr(((vec_uint4){0x0100,0,0,0})); + res_v = ldexpd2 (*((vec_double2 *)&test_a[ii].xxx[0]), *((vec_llong2 *)&test_a[ii].exp[0])); + sprintf(msg,"2006090516%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans0[0])), 0); + +#ifdef LDEXPD2_ROUND + + spu_mtfpscr(((vec_uint4){0x0600,0,0,0})); + res_v = ldexpd2 (*((vec_double2 *)&test_a[ii].xxx[0]), *((vec_llong2 *)&test_a[ii].exp[0])); + sprintf(msg,"2006090516%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans1[0])), 0); + + spu_mtfpscr(((vec_uint4){0x0b00,0,0,0})); + res_v = ldexpd2 (*((vec_double2 *)&test_a[ii].xxx[0]), *((vec_llong2 *)&test_a[ii].exp[0])); + sprintf(msg,"2006090516%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans2[0])), 0); + + spu_mtfpscr(((vec_uint4){0x0c00,0,0,0})); + res_v = ldexpd2 (*((vec_double2 *)&test_a[ii].xxx[0]), *((vec_llong2 *)&test_a[ii].exp[0])); + sprintf(msg,"2006090516%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans3[0])), 0); +#endif // LDEXPD2_ROUND + + } + + + TEST_SET_DONE(); + + TEST_EXIT(); + +} diff --git a/Extras/simdmathlibrary/spu/tests/llabsi2.c b/Extras/simdmathlibrary/spu/tests/llabsi2.c new file mode 100644 index 0000000..3b08ab1 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/llabsi2.c @@ -0,0 +1,94 @@ +/* Test llabsi2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/** + * + *@@ llabsi2 - returns absolute value of input. + * + *@brief + * boundary test for llabsi2. + * + *@pre + * + *@criteria + * Run this program and check no error will be occurred. + * + *@note + * + * + **/ + + +#include +#include +#include +//#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + + +int main() +{ + TEST_SET_START("20060831134500NM","NM", "llabsi2"); + + vec_llong2 x0_v = ((vec_llong2){ 0, 0}); + vec_llong2 r0_v = ((vec_llong2){ 0, 0}); + + vec_llong2 x1_v = ((vec_llong2){-1, 1}); + vec_llong2 r1_v = ((vec_llong2){ 1, 1}); + + vec_llong2 x2_v = ((vec_llong2){ 1,-1}); + vec_llong2 r2_v = ((vec_llong2){ 1, 1}); + // 0x7FFFFFFFFFFFFFFF + vec_llong2 x3_v = ((vec_llong2){ 9223372036854775807LL,-9223372036854775807LL}); + vec_llong2 r3_v = ((vec_llong2){ 9223372036854775807LL, 9223372036854775807LL}); + // 0x8000000000000000 + vec_llong2 x4_v = ((vec_llong2){0x8000000000000000LL,0x8000000000000000LL}); + vec_llong2 r4_v = ((vec_llong2){0x8000000000000000LL,0x8000000000000000LL}); + + vec_llong2 res_v; + + TEST_START("llabsi2"); + res_v = llabsi2 (x0_v); + TEST_CHECK("20060831134501NM", allequal_llong2( res_v, r0_v ), 0); + res_v = llabsi2 (x1_v); + TEST_CHECK("20060831134502NM", allequal_llong2( res_v, r1_v ), 0); + res_v = llabsi2 (x2_v); + TEST_CHECK("20060831134503NM", allequal_llong2( res_v, r2_v ), 0); + res_v = llabsi2 (x3_v); + TEST_CHECK("20060831134504NM", allequal_llong2( res_v, r3_v ), 0); + res_v = llabsi2 (x4_v); + TEST_CHECK("20060831134505NM", allequal_llong2( res_v, r4_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); + +} diff --git a/Extras/simdmathlibrary/spu/tests/lldivi2.c b/Extras/simdmathlibrary/spu/tests/lldivi2.c new file mode 100644 index 0000000..2c0b9e3 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/lldivi2.c @@ -0,0 +1,126 @@ +/* Test lldivi2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060908152000MH","MH", "lldivi2"); + + signed long long x0n = 0x0c0e84c75f216c43ll; + signed long long x0d = 0x00000000000abcdell; + signed long long x0q = 0x0000011f71fb04cbll; + signed long long x0r = 0x0000000000003039ll; + signed long long x1n = 0x0c0e84c75f216c43ll; + signed long long x1d = 0x0000011f71fb04cbll; + signed long long x1q = 0x00000000000abcdell; + signed long long x1r = 0x0000000000003039ll; + + signed long long x2n = 0x08e732f9d4baf903ll; + signed long long x2d = 0x0000000000976bb6ll; + signed long long x2q = 0x0000000f0d55f4d9ll; + signed long long x2r = 0x00000000004933bdll; + signed long long x3n = 0x08e732f9d4baf903ll; + signed long long x3d = 0x0000000f0d55f4d9ll; + signed long long x3q = 0x0000000000976bb6ll; + signed long long x3r = 0x00000000004933bdll; + + signed long long x4n = 0xffffffffffffffffll; + signed long long x4d = 0xfffffffffffffffell; + signed long long x4q = 0x0000000000000000ll; + signed long long x4r = 0xffffffffffffffffll; + signed long long x5n = 0xffffffffffffffffll; + signed long long x5d = 0x0000000000000001ll; + signed long long x5q = 0xffffffffffffffffll; + signed long long x5r = 0x0000000000000000ll; + + signed long long x6n = 0xffffffffffffffffll; + signed long long x6d = 0x0000000000000002ll; + signed long long x6q = 0x0000000000000000ll; + signed long long x6r = 0xffffffffffffffffll; + signed long long x7n = 0xffffffffffffffffll; + signed long long x7d = 0x7fffffffffffffffll; + signed long long x7q = 0x0000000000000000ll; + signed long long x7r = 0xffffffffffffffffll; + + signed long long x8n = 0xf8c0d45d0ff344f0ll; + signed long long x8d = 0x000019aa3e41e0bdll; + signed long long x8q = 0xffffffffffffb7b8ll; + signed long long x8r = 0xffffedc119afa218ll; + signed long long x9n = 0xf8c0d45d0ff344f0ll; + signed long long x9d = 0x000000000009b13bll; + signed long long x9q = 0xffffff4097efb39ell; + signed long long x9r = 0xfffffffffff6a186ll; + + vec_llong2 x0n_v = (vec_llong2){ x0n, x1n }; + vec_llong2 x0d_v = (vec_llong2){ x0d, x1d }; + vec_llong2 x0q_v = (vec_llong2){ x0q, x1q }; + vec_llong2 x0r_v = (vec_llong2){ x0r, x1r }; + vec_llong2 x1n_v = (vec_llong2){ x2n, x3n }; + vec_llong2 x1d_v = (vec_llong2){ x2d, x3d }; + vec_llong2 x1q_v = (vec_llong2){ x2q, x3q }; + vec_llong2 x1r_v = (vec_llong2){ x2r, x3r }; + vec_llong2 x2n_v = (vec_llong2){ x4n, x5n }; + vec_llong2 x2d_v = (vec_llong2){ x4d, x5d }; + vec_llong2 x2q_v = (vec_llong2){ x4q, x5q }; + vec_llong2 x2r_v = (vec_llong2){ x4r, x5r }; + vec_llong2 x3n_v = (vec_llong2){ x6n, x7n }; + vec_llong2 x3d_v = (vec_llong2){ x6d, x7d }; + vec_llong2 x3q_v = (vec_llong2){ x6q, x7q }; + vec_llong2 x3r_v = (vec_llong2){ x6r, x7r }; + vec_llong2 x4n_v = (vec_llong2){ x8n, x9n }; + vec_llong2 x4d_v = (vec_llong2){ x8d, x9d }; + vec_llong2 x4q_v = (vec_llong2){ x8q, x9q }; + vec_llong2 x4r_v = (vec_llong2){ x8r, x9r }; + + lldivi2_t res; + + TEST_START("lldivi2"); + res = lldivi2(x0n_v, x0d_v); + TEST_CHECK("20060908152001MH", allequal_llong2( res.quot, x0q_v ) && allequal_llong2( res.rem, x0r_v ), 0); + res = lldivi2(x1n_v, x1d_v); + TEST_CHECK("20060908152002MH", allequal_llong2( res.quot, x1q_v ) && allequal_llong2( res.rem, x1r_v ), 0); + res = lldivi2(x2n_v, x2d_v); + TEST_CHECK("20060908152003MH", allequal_llong2( res.quot, x2q_v ) && allequal_llong2( res.rem, x2r_v ), 0); + res = lldivi2(x3n_v, x3d_v); + TEST_CHECK("20060908152004MH", allequal_llong2( res.quot, x3q_v ) && allequal_llong2( res.rem, x3r_v ), 0); + res = lldivi2(x4n_v, x4d_v); + TEST_CHECK("20060908152005MH", allequal_llong2( res.quot, x4q_v ) && allequal_llong2( res.rem, x4r_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/lldivu2.c b/Extras/simdmathlibrary/spu/tests/lldivu2.c new file mode 100644 index 0000000..813b2d2 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/lldivu2.c @@ -0,0 +1,125 @@ +/* Test lldivu2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060904200000MH","MH", "lldivu2"); + + unsigned long long x0n = 0x0c0e84c75f216c43ull; + unsigned long long x0d = 0x00000000000abcdeull; + unsigned long long x0q = 0x0000011f71fb04cbull; + unsigned long long x0r = 0x0000000000003039ull; + unsigned long long x1n = 0x0c0e84c75f216c43ull; + unsigned long long x1d = 0x0000011f71fb04cbull; + unsigned long long x1q = 0x00000000000abcdeull; + unsigned long long x1r = 0x0000000000003039ull; + + unsigned long long x2n = 0x08e732f9d4baf903ull; + unsigned long long x2d = 0x0000000000976bb6ull; + unsigned long long x2q = 0x0000000f0d55f4d9ull; + unsigned long long x2r = 0x00000000004933bdull; + unsigned long long x3n = 0x08e732f9d4baf903ull; + unsigned long long x3d = 0x0000000f0d55f4d9ull; + unsigned long long x3q = 0x0000000000976bb6ull; + unsigned long long x3r = 0x00000000004933bdull; + + unsigned long long x4n = 0xffffffffffffffffull; + unsigned long long x4d = 0xfffffffffffffffeull; + unsigned long long x4q = 0x0000000000000001ull; + unsigned long long x4r = 0x0000000000000001ull; + unsigned long long x5n = 0xffffffffffffffffull; + unsigned long long x5d = 0x0000000000000001ull; + unsigned long long x5q = 0xffffffffffffffffull; + unsigned long long x5r = 0x0000000000000000ull; + + unsigned long long x6n = 0xffffffffffffffffull; + unsigned long long x6d = 0x0000000000000002ull; + unsigned long long x6q = 0x7fffffffffffffffull; + unsigned long long x6r = 0x0000000000000001ull; + unsigned long long x7n = 0xffffffffffffffffull; + unsigned long long x7d = 0x7fffffffffffffffull; + unsigned long long x7q = 0x0000000000000002ull; + unsigned long long x7r = 0x0000000000000001ull; + + unsigned long long x8n = 0xf8c0d45d0ff344f0ull; + unsigned long long x8d = 0x000019aa3e41e0bdull; + unsigned long long x8q = 0x000000000009b13bull; + unsigned long long x8r = 0x000004c443bccc61ull; + unsigned long long x9n = 0xf8c0d45d0ff344f0ull; + unsigned long long x9d = 0x000000000009b13bull; + unsigned long long x9q = 0x000019aa3ebfc739ull; + unsigned long long x9r = 0x000000000000f1cdull; + + vec_ullong2 x0n_v = (vec_ullong2){ x0n, x1n }; + vec_ullong2 x0d_v = (vec_ullong2){ x0d, x1d }; + vec_ullong2 x0q_v = (vec_ullong2){ x0q, x1q }; + vec_ullong2 x0r_v = (vec_ullong2){ x0r, x1r }; + vec_ullong2 x1n_v = (vec_ullong2){ x2n, x3n }; + vec_ullong2 x1d_v = (vec_ullong2){ x2d, x3d }; + vec_ullong2 x1q_v = (vec_ullong2){ x2q, x3q }; + vec_ullong2 x1r_v = (vec_ullong2){ x2r, x3r }; + vec_ullong2 x2n_v = (vec_ullong2){ x4n, x5n }; + vec_ullong2 x2d_v = (vec_ullong2){ x4d, x5d }; + vec_ullong2 x2q_v = (vec_ullong2){ x4q, x5q }; + vec_ullong2 x2r_v = (vec_ullong2){ x4r, x5r }; + vec_ullong2 x3n_v = (vec_ullong2){ x6n, x7n }; + vec_ullong2 x3d_v = (vec_ullong2){ x6d, x7d }; + vec_ullong2 x3q_v = (vec_ullong2){ x6q, x7q }; + vec_ullong2 x3r_v = (vec_ullong2){ x6r, x7r }; + vec_ullong2 x4n_v = (vec_ullong2){ x8n, x9n }; + vec_ullong2 x4d_v = (vec_ullong2){ x8d, x9d }; + vec_ullong2 x4q_v = (vec_ullong2){ x8q, x9q }; + vec_ullong2 x4r_v = (vec_ullong2){ x8r, x9r }; + + lldivu2_t res; + + TEST_START("lldivu2"); + res = lldivu2(x0n_v, x0d_v); + TEST_CHECK("20060904200001MH", allequal_ullong2( res.quot, x0q_v ) && allequal_ullong2( res.rem, x0r_v ), 0); + res = lldivu2(x1n_v, x1d_v); + TEST_CHECK("20060904200002MH", allequal_ullong2( res.quot, x1q_v ) && allequal_ullong2( res.rem, x1r_v ), 0); + res = lldivu2(x2n_v, x2d_v); + TEST_CHECK("20060904200003MH", allequal_ullong2( res.quot, x2q_v ) && allequal_ullong2( res.rem, x2r_v ), 0); + res = lldivu2(x3n_v, x3d_v); + TEST_CHECK("20060904200004MH", allequal_ullong2( res.quot, x3q_v ) && allequal_ullong2( res.rem, x3r_v ), 0); + res = lldivu2(x4n_v, x4d_v); + TEST_CHECK("20060904200005MH", allequal_ullong2( res.quot, x4q_v ) && allequal_ullong2( res.rem, x4r_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/llrintd2.c b/Extras/simdmathlibrary/spu/tests/llrintd2.c new file mode 100644 index 0000000..449bb4c --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/llrintd2.c @@ -0,0 +1,215 @@ +/* Test llrintd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/** + * + *@@ llrintd2 - rounds two doubles in to two nearest 64bit integer. + * + *@brief + * boundary test for llrintd2. + * consistent with the current rounding mode. + * + *@pre + * + *@criteria + * Run this program and check no error will be occurred. + * + *@note + * + **/ + + +#include +#include +#include +//#include +#include + +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + typedef union { + unsigned long long int ll; + double x; + } SrcType64; + SrcType64 tmp64; + TEST_SET_START("20060921101000NM","NM", "llrintd2"); + +// unsigned long long i11 = 0x7FFFFFFFFFFFFDFFull; //limit +// unsigned long long i12 = 0xFFFFFFFFFFFFFDFFull; //limit + +// double x0 = hide_double(-HUGE_VAL); // -Inf +// double x1 = hide_double(HUGE_VAL); // Inf + double x2 = hide_double(0.0); // +0 + double x3 = hide_double(-0.0); // -0 +// double x4 = hide_double(nan("")); // NaN -> NaN + double x5 = hide_double( 0.5); + double x6 = hide_double(-0.5); + double x7 = hide_double( 0.4999999999999999); // 0 + double x8 = hide_double(-0.4999999999999999); // 0 + double x9 = hide_double( 999999999999999.5); // 1000000000000000 + double x10 = hide_double(-999999999999999.5); //-1000000000000000 +// double x11 = hide_double(make_double(i11)); // 9223372036854774784 +// double x12 = hide_double(make_double(i12)); //-9223372036854774784 + double x11 = hide_double(9223372036854774784ll); // 9223372036854774784 + double x12 = hide_double(-9223372036854774784ll); //-9223372036854774784 + double x13 = DBL_MIN; + double x14 = (0.0 - DBL_MIN); + + double x15 = hide_double( 0.5000000000000001); + double x16 = hide_double(-0.000001); + + tmp64.ll = 0x3FEFFFFFFFFFFFFFULL; + double x17 = tmp64.x; + tmp64.ll = 0xC32FFFFFFFFFFFFFULL; + double x18 = tmp64.x; + + vec_double2 x0_v = ((vec_double2){x2, x3}); //+0,-0 + vec_llong2 r0_v = ((vec_llong2){0,0}); // 0, 0 + vec_double2 x1_v = ((vec_double2){x5, x8}); //+0.5,-0.4999999999999999 + vec_llong2 r10_v = ((vec_llong2){0,0}); + vec_llong2 r11_v = ((vec_llong2){0,0}); + vec_llong2 r12_v = ((vec_llong2){1,0}); + vec_llong2 r13_v = ((vec_llong2){0,-1}); + vec_double2 x2_v = ((vec_double2){x7, x6}); //+0.4999999999999999, -0.5 + vec_llong2 r20_v = ((vec_llong2){0,0}); + vec_llong2 r21_v = ((vec_llong2){0,0}); + vec_llong2 r22_v = ((vec_llong2){1,0}); + vec_llong2 r23_v = ((vec_llong2){0,-1}); + vec_double2 x3_v = ((vec_double2){x10, x11}); //-999999999999999.5, 9223372036854774784 + vec_llong2 r30_v = ((vec_llong2){-1000000000000000ll,9223372036854774784ll}); + vec_llong2 r31_v = ((vec_llong2){-999999999999999ll, 9223372036854774784ll}); + vec_llong2 r32_v = ((vec_llong2){-999999999999999ll, 9223372036854774784ll}); + vec_llong2 r33_v = ((vec_llong2){-1000000000000000ll,9223372036854774784ll}); + vec_double2 x4_v = ((vec_double2){x12, x9}); //-9223372036854774784, 999999999999999.5 + vec_llong2 r40_v = ((vec_llong2){-9223372036854774784ll,1000000000000000ll}); + vec_llong2 r41_v = ((vec_llong2){-9223372036854774784ll,999999999999999ll}); + vec_llong2 r42_v = ((vec_llong2){-9223372036854774784ll,1000000000000000ll}); + vec_llong2 r43_v = ((vec_llong2){-9223372036854774784ll,999999999999999ll}); + vec_double2 x5_v = ((vec_double2){x13, x14}); + vec_llong2 r50_v = ((vec_llong2){0,0}); + vec_llong2 r51_v = ((vec_llong2){0,0}); + vec_llong2 r52_v = ((vec_llong2){1,0}); + vec_llong2 r53_v = ((vec_llong2){0,-1}); + vec_double2 x6_v = ((vec_double2){x15, x16}); + vec_llong2 r60_v = ((vec_llong2){1,0}); + vec_llong2 r61_v = ((vec_llong2){0,0}); + vec_llong2 r62_v = ((vec_llong2){1,0}); + vec_llong2 r63_v = ((vec_llong2){0,-1}); + + vec_double2 x7_v = ((vec_double2){x17, x18}); + vec_llong2 r70_v = ((vec_llong2){1,-4503599627370496LL}); + vec_llong2 r71_v = ((vec_llong2){0,-4503599627370495LL}); + vec_llong2 r72_v = ((vec_llong2){1,-4503599627370495LL}); + vec_llong2 r73_v = ((vec_llong2){0,-4503599627370496LL}); + + vec_llong2 res_v; + + TEST_START("llrintd2"); + + spu_mtfpscr(((vec_uint4){0x0000,0,0,0})); //change FP mode + res_v = llrintd2 (x0_v); + TEST_CHECK("20060921101001NM", allequal_llong2( res_v, r0_v ), 0); + res_v = llrintd2 (x1_v); + TEST_CHECK("20060921101002NM", allequal_llong2( res_v, r10_v ), 0); + res_v = llrintd2 (x2_v); + TEST_CHECK("20060921101003NM", allequal_llong2( res_v, r20_v ), 0); + res_v = llrintd2 (x3_v); + TEST_CHECK("20060921101004NM", allequal_llong2( res_v, r30_v ), 0); + res_v = llrintd2 (x4_v); + TEST_CHECK("20060921101005NM", allequal_llong2( res_v, r40_v ), 0); + res_v = llrintd2 (x5_v); + TEST_CHECK("20060921101006NM", allequal_llong2( res_v, r50_v ), 0); + res_v = llrintd2 (x6_v); + TEST_CHECK("20060921101007NM", allequal_llong2( res_v, r60_v ), 0); + res_v = llrintd2 (x7_v); + TEST_CHECK("20060921101017NM", allequal_llong2( res_v, r70_v ), 0); + + spu_mtfpscr(((vec_uint4){0x0500,0,0,0})); //change FP mode + res_v = llrintd2 (x0_v); + TEST_CHECK("20060921101008NM", allequal_llong2( res_v, r0_v ), 0); + res_v = llrintd2 (x1_v); + TEST_CHECK("20060921101009NM", allequal_llong2( res_v, r11_v ), 0); + res_v = llrintd2 (x2_v); + TEST_CHECK("20060921101010NM", allequal_llong2( res_v, r21_v ), 0); + res_v = llrintd2 (x3_v); + TEST_CHECK("20060921101011NM", allequal_llong2( res_v, r31_v ), 0); + res_v = llrintd2 (x4_v); + TEST_CHECK("20060921101012NM", allequal_llong2( res_v, r41_v ), 0); + res_v = llrintd2 (x5_v); + TEST_CHECK("20060921101013NM", allequal_llong2( res_v, r51_v ), 0); + res_v = llrintd2 (x6_v); + TEST_CHECK("20060921101014NM", allequal_llong2( res_v, r61_v ), 0); + res_v = llrintd2 (x7_v); + TEST_CHECK("20060921101027NM", allequal_llong2( res_v, r71_v ), 0); + + spu_mtfpscr(((vec_uint4){0x0a00,0,0,0})); //change FP mode + res_v = llrintd2 (x0_v); + TEST_CHECK("20060921101015NM", allequal_llong2( res_v, r0_v ), 0); + res_v = llrintd2 (x1_v); + TEST_CHECK("20060921101016NM", allequal_llong2( res_v, r12_v ), 0); + res_v = llrintd2 (x2_v); + TEST_CHECK("20060921101017NM", allequal_llong2( res_v, r22_v ), 0); + res_v = llrintd2 (x3_v); + TEST_CHECK("20060921101018NM", allequal_llong2( res_v, r32_v ), 0); + res_v = llrintd2 (x4_v); + TEST_CHECK("20060921101019NM", allequal_llong2( res_v, r42_v ), 0); + res_v = llrintd2 (x5_v); + TEST_CHECK("20060921101020NM", allequal_llong2( res_v, r52_v ), 0); + res_v = llrintd2 (x6_v); + TEST_CHECK("20060921101021NM", allequal_llong2( res_v, r62_v ), 0); + res_v = llrintd2 (x7_v); + TEST_CHECK("20060921101037NM", allequal_llong2( res_v, r72_v ), 0); + + spu_mtfpscr(((vec_uint4){0x0f00,0,0,0})); //change FP mode + res_v = llrintd2 (x0_v); + TEST_CHECK("20060921101022NM", allequal_llong2( res_v, r0_v ), 0); + res_v = llrintd2 (x1_v); + TEST_CHECK("20060921101023NM", allequal_llong2( res_v, r13_v ), 0); + res_v = llrintd2 (x2_v); + TEST_CHECK("20060921101024NM", allequal_llong2( res_v, r23_v ), 0); + res_v = llrintd2 (x3_v); + TEST_CHECK("20060921101025NM", allequal_llong2( res_v, r33_v ), 0); + res_v = llrintd2 (x4_v); + TEST_CHECK("20060921101026NM", allequal_llong2( res_v, r43_v ), 0); + res_v = llrintd2 (x5_v); + TEST_CHECK("20060921101027NM", allequal_llong2( res_v, r53_v ), 0); + res_v = llrintd2 (x6_v); + TEST_CHECK("20060921101028NM", allequal_llong2( res_v, r63_v ), 0); + res_v = llrintd2 (x7_v); + TEST_CHECK("20060921101047NM", allequal_llong2( res_v, r73_v ), 0); + + + TEST_SET_DONE(); + + TEST_EXIT(); + +} diff --git a/Extras/simdmathlibrary/spu/tests/llrintf4.c b/Extras/simdmathlibrary/spu/tests/llrintf4.c new file mode 100644 index 0000000..75b6777 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/llrintf4.c @@ -0,0 +1,123 @@ +/* Test llrintf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/** + * + *@@ llrintf4 - rounds four floats in to four nearest 64bit integer. + * + *@brief + * boundary test for llrintf4. On SPU the rounding mode for floats is always towards 0. + * + *@pre + * + *@criteria + * Run this program and check no error will be occurred. + * + *@note + * + **/ + + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +static inline llroundf4_t set_llrintf4_t(long long int in0, long long int in1, long long int in2, long long int in3) +{ + llroundf4_t res; + + res.vll[0] = ((vec_llong2){in0,in1}); + res.vll[1] = ((vec_llong2){in2,in3}); + + return res; +} +int main() +{ + TEST_SET_START("20060918101000NM","NM", "llrintf4"); + +// unsigned long i11 = 0x5efffffful; // 9223371487098961920 +// unsigned long i12 = 0xdefffffful; //-9223371487098961920 +// unsigned long i11 = 0x49fffffful; //2097151.875000 +// unsigned long i12 = 0x4a7ffffful; //4194303.750000 + +// float x0 = hide_float(-FLT_MAX); // -Inf +// float x1 = hide_float(FLT_MAX); // Inf + float x2 = hide_float(0.0); // +0 + float x3 = hide_float(-0.0); // -0 +// float x4 = hide_float(NANF); // NaN -> NaN + float x5 = hide_float( 0.5); + float x6 = hide_float(-0.5); + float x7 = hide_float(-0.499999); + float x8 = hide_float( 0.499999); + float x9 = hide_float(-999999.5); + float x10 = hide_float( 999999.5); +// float x11 = hide_float(make_float(i11)); +// float x12 = hide_float(make_float(i12)); + float x11 = hide_float( 9223371487098961920.); + float x12 = hide_float(-9223371487098961920.); + float x13 = (0.0 - FLT_MIN); + float x14 = FLT_MIN; + float x15 = hide_float(-2097151.875000); + float x16 = hide_float(-4194303.750000); + float x17 = hide_float( 4194303.750000); + float x18 = hide_float( 2097151.875000); + + vec_float4 x0_v = ((vec_float4){ x2, x3, x5, x6}); + llroundf4_t r0_v = set_llrintf4_t(0, 0, 0, 0); + + vec_float4 x1_v = ((vec_float4){ x7, x8, x9, x10}); + llroundf4_t r1_v = set_llrintf4_t(0, 0, -999999, 999999); + + vec_float4 x2_v = ((vec_float4){ x11, x12, x13, x14}); + llroundf4_t r2_v = set_llrintf4_t(9223371487098961920ll, -9223371487098961920ll, 0, 0); + + vec_float4 x3_v = ((vec_float4){ x15, x16, x17, x18}); + llroundf4_t r3_v = set_llrintf4_t(-2097151, -4194303, 4194303, 2097151); + + llroundf4_t res_v; + + TEST_START("llrintf4"); + res_v = llrintf4 (x0_v); + TEST_CHECK("20060918101001NM", allequal_llroundf4( res_v, r0_v ), 0); + res_v = llrintf4 (x1_v); + TEST_CHECK("20060918101002NM", allequal_llroundf4( res_v, r1_v ), 0); + res_v = llrintf4 (x2_v); + TEST_CHECK("20060918101003NM", allequal_llroundf4( res_v, r2_v ), 0); + res_v = llrintf4 (x3_v); + TEST_CHECK("20060918101004NM", allequal_llroundf4( res_v, r3_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); + +} diff --git a/Extras/simdmathlibrary/spu/tests/llroundd2.c b/Extras/simdmathlibrary/spu/tests/llroundd2.c new file mode 100644 index 0000000..6111180 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/llroundd2.c @@ -0,0 +1,113 @@ +/* Test llroundd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/** + * + *@@ llroundd2 - rounds two doubles in to two nearest 64bit integer. + * + *@brief + * boundary test for llroundd2. 0.5 will be rounded to far from 0. + * + *@pre + * + *@criteria + * Run this program and check no error will be occurred. + * + *@note + * + **/ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + + +int main() +{ + TEST_SET_START("20060916101000NM","NM", "llroundd2"); + +// unsigned long long i11 = 0x7FFFFFFFFFFFFDFFull; //limit +// unsigned long long i12 = 0xFFFFFFFFFFFFFDFFull; //limit + +// double x0 = hide_double(-HUGE_VAL); // -Inf +// double x1 = hide_double(HUGE_VAL); // Inf + double x2 = hide_double(0.0); // +0 + double x3 = hide_double(-0.0); // -0 +// double x4 = hide_double(nan("")); // NaN -> NaN + double x5 = hide_double( 0.5); + double x6 = hide_double(-0.5); + double x7 = hide_double( 0.4999999999999999); // 0 + double x8 = hide_double(-0.4999999999999999); // 0 + double x9 = hide_double( 999999999999999.5); // 1000000000000000 + double x10 = hide_double(-999999999999999.5); //-1000000000000000 +// double x11 = hide_double(make_double(i11)); // 9223372036854774784 +// double x12 = hide_double(make_double(i12)); //-9223372036854774784 + double x11 = hide_double(9223372036854774784ll); // 9223372036854774784 + double x12 = hide_double(-9223372036854774784ll); //-9223372036854774784 + double x13 = DBL_MIN; + double x14 = (0.0 - DBL_MIN); + + vec_double2 x0_v = ((vec_double2){x2, x3}); //+0,-0 + vec_llong2 r0_v = ((vec_llong2){0,0}); // 0, 0 + vec_double2 x1_v = ((vec_double2){x5, x8}); //+0.5,-0.4999999999999999 + vec_llong2 r1_v = ((vec_llong2){1,0}); // 1, 0 + vec_double2 x2_v = ((vec_double2){x7, x6}); //+0.4999999999999999, -0.5 + vec_llong2 r2_v = ((vec_llong2){0,-1}); // 0, -1 + vec_double2 x3_v = ((vec_double2){x10, x11}); //-999999999999999.5, 9223372036854774784 + vec_llong2 r3_v = ((vec_llong2){-1000000000000000ll,9223372036854774784ll}); + vec_double2 x4_v = ((vec_double2){x12, x9}); //-9223372036854774784, 999999999999999.5 + vec_llong2 r4_v = ((vec_llong2){-9223372036854774784ll,1000000000000000ll}); + vec_double2 x5_v = ((vec_double2){x13, x14}); + vec_llong2 r5_v = ((vec_llong2){0,0}); + + vec_llong2 res_v; + + TEST_START("llroundd2"); + res_v = llroundd2 (x0_v); + TEST_CHECK("20060916101001NM", allequal_llong2( res_v, r0_v ), 0); + res_v = llroundd2 (x1_v); + TEST_CHECK("20060916101002NM", allequal_llong2( res_v, r1_v ), 0); + res_v = llroundd2 (x2_v); + TEST_CHECK("20060916101003NM", allequal_llong2( res_v, r2_v ), 0); + res_v = llroundd2 (x3_v); + TEST_CHECK("20060916101004NM", allequal_llong2( res_v, r3_v ), 0); + res_v = llroundd2 (x4_v); + TEST_CHECK("20060916101005NM", allequal_llong2( res_v, r4_v ), 0); + res_v = llroundd2 (x5_v); + TEST_CHECK("20060916101006NM", allequal_llong2( res_v, r5_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); + +} diff --git a/Extras/simdmathlibrary/spu/tests/llroundf4.c b/Extras/simdmathlibrary/spu/tests/llroundf4.c new file mode 100644 index 0000000..8025a2c --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/llroundf4.c @@ -0,0 +1,125 @@ +/* Test llroundf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/** + * + *@@ llroundf4 - rounds four floats in to four nearest 64bit integer. + * + *@brief + * boundary test for llroundf4. 0.5 will be rounded to far from 0. + * + *@pre + * + *@criteria + * Run this program and check no error will be occurred. + * + *@note + * when comparing with return of ppu scalar math library + * answer of 0x??7fffff and 0x??ffffff was something strange + * + **/ + + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +static inline llroundf4_t set_llroundf4_t(long long int in0, long long int in1, long long int in2, long long int in3) +{ + llroundf4_t res; + + res.vll[0] = ((vec_llong2){in0,in1}); + res.vll[1] = ((vec_llong2){in2,in3}); + + return res; +} +int main() +{ + TEST_SET_START("20060917101000NM","NM", "llroundf4"); + +// unsigned long i11 = 0x5efffffful; // 9223371487098961920 +// unsigned long i12 = 0xdefffffful; //-9223371487098961920 +// unsigned long i11 = 0x49fffffful; //2097151.875000 +// unsigned long i12 = 0x4a7ffffful; //4194303.750000 + +// float x0 = hide_float(-FLT_MAX); // -Inf +// float x1 = hide_float(FLT_MAX); // Inf + float x2 = hide_float(0.0); // +0 + float x3 = hide_float(-0.0); // -0 +// float x4 = hide_float(NANF); // NaN -> NaN + float x5 = hide_float( 0.5); + float x6 = hide_float(-0.5); + float x7 = hide_float(-0.499999); + float x8 = hide_float( 0.499999); + float x9 = hide_float(-999999.5); + float x10 = hide_float( 999999.5); +// float x11 = hide_float(make_float(i11)); +// float x12 = hide_float(make_float(i12)); + float x11 = hide_float( 9223371487098961920.); + float x12 = hide_float(-9223371487098961920.); + float x13 = (0.0 - FLT_MIN); + float x14 = FLT_MIN; + float x15 = hide_float(-2097151.875000); + float x16 = hide_float(-4194303.750000); + float x17 = hide_float( 4194303.750000); + float x18 = hide_float( 2097151.875000); + + vec_float4 x0_v = ((vec_float4){ x2, x3, x5, x6}); + llroundf4_t r0_v = set_llroundf4_t(0, 0, 1, -1); + + vec_float4 x1_v = ((vec_float4){ x7, x8, x9, x10}); + llroundf4_t r1_v = set_llroundf4_t(0, 0, -1000000, 1000000); + + vec_float4 x2_v = ((vec_float4){ x11, x12, x13, x14}); + llroundf4_t r2_v = set_llroundf4_t(9223371487098961920ll, -9223371487098961920ll, 0, 0); + + vec_float4 x3_v = ((vec_float4){ x15, x16, x17, x18}); + llroundf4_t r3_v = set_llroundf4_t(-2097152, -4194304, 4194304, 2097152); + + llroundf4_t res_v; + + TEST_START("llroundf4"); + res_v = llroundf4 (x0_v); + TEST_CHECK("20060916101001NM", allequal_llroundf4( res_v, r0_v ), 0); + res_v = llroundf4 (x1_v); + TEST_CHECK("20060916101002NM", allequal_llroundf4( res_v, r1_v ), 0); + res_v = llroundf4 (x2_v); + TEST_CHECK("20060916101003NM", allequal_llroundf4( res_v, r2_v ), 0); + res_v = llroundf4 (x3_v); + TEST_CHECK("20060916101004NM", allequal_llroundf4( res_v, r3_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); + +} diff --git a/Extras/simdmathlibrary/spu/tests/logbd2.c b/Extras/simdmathlibrary/spu/tests/logbd2.c new file mode 100644 index 0000000..60dbd1c --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/logbd2.c @@ -0,0 +1,314 @@ +/* Test logbd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060905000000AAN","AAN", "logbd2"); + + // -Nan + double x0 = hide_double(-nan("")); + double r0 = hide_double( nan("")); + + // -Inf + double x1 = hide_double(-HUGE_VAL); + double r1 = hide_double(HUGE_VAL); + + // -Dmax + double x2 = hide_double(-DBL_MAX); + double r2 = 1023.0; + + // -Norm + double x3 = hide_double(-824842.58421394); + double r3 = 19.0; + + // -Dmin + double x4 = hide_double(-DBL_MIN); + double r4 = -1022.0; + + // -Denorm + double x5 = hide_double(-2.40e-310); + double r5 = -1029.0; + + // -Unf + double x6 = hide_double(-1.0e-999); + double r6 = hide_double(-HUGE_VAL); + + // -0 + double x7 = hide_double(-0.0); + double r7 = hide_double(-HUGE_VAL); + + // 0 + double x8 = hide_double( 0.0); + double r8 = hide_double(-HUGE_VAL); + + // +Unf + double x9 = hide_double( 1.0e-999); + double r9 = hide_double(-HUGE_VAL); + + // +Denorm + double x10 = hide_double( 2.40e-310); + double r10 = -1029.0; + + // +Dmin + double x11 = hide_double( DBL_MIN); + double r11 = -1022.0; + + // +Norm + double x12 = hide_double(3.14152634); + double r12 = 1.0; + + // +Norm + double x13 = hide_double(7.0673903e149); + double r13 = 497.0; + + // +Norm + double x14 = hide_double(2.4673e304); + double r14 = 1011.0; + + // +Norm + double x15 = hide_double(7.235672e-25); + double r15 = -81.0; + + // +Denorm + double x16 = hide_double(9.452854e-312); + double r16 = -1034.0; + + // +Demorm + double x17 = hide_double(3.045784e-320); + double r17 = -1062.0; + + // -Norm + double x18 = hide_double(-6.459273e7); + double r18 = 25.0; + + // -Norm + double x19 = hide_double(-2.493472e-99); + double r19 = -328.0; + + // -Norm + double x20 = hide_double(-1.4824543e128); + double r20 = 425.0; + + // -Denorm + double x21 = hide_double(-5.53856231e-315); + double r21 = -1044.0; + + // -Demorm + double x22 = hide_double(-2.5684367e-312); + double r22 = -1036.0; + + // +Dmax + double x23 = hide_double(DBL_MAX); + double r23 = 1023.0; + + // +Inf + double x24 = hide_double(HUGE_VAL); + double r24 = hide_double(HUGE_VAL); + + //+Nan + double x25 = hide_double( nan("")); + double r25 = hide_double( nan("")); + + // Compound + vec_double2 x26_v = (vec_double2) { -2.561286432e-317, -1.0e-999 }; + vec_double2 r26_v = (vec_double2) { -1052.0, hide_double(-HUGE_VAL) }; + + // Compound + vec_double2 x27_v = (vec_double2) { 345.27533, -8.673e-310 }; + vec_double2 r27_v = (vec_double2) { 8.0, -1027.0 }; + + // Compound + vec_double2 x28_v = (vec_double2) { nan(""), -3678342.8765343 }; + vec_double2 r28_v = (vec_double2) { nan(""), 21.0 }; + + // Compound + vec_double2 x29_v = (vec_double2) { HUGE_VAL, -nan("") }; + vec_double2 r29_v = (vec_double2) { HUGE_VAL, nan("") }; + + // Compound + vec_double2 x30_v = (vec_double2) { -1.2e-99, -HUGE_VAL } ; + vec_double2 r30_v = (vec_double2) { -329.0, HUGE_VAL }; + + vec_double2 x0_v = spu_splats(x0); + vec_double2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_double2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_double2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_double2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_double2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_double2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_double2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_double2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_double2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_double2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_double2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_double2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_double2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_double2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_double2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_double2 r15_v = spu_splats(r15); + + vec_double2 x16_v = spu_splats(x16); + vec_double2 r16_v = spu_splats(r16); + + vec_double2 x17_v = spu_splats(x17); + vec_double2 r17_v = spu_splats(r17); + + vec_double2 x18_v = spu_splats(x18); + vec_double2 r18_v = spu_splats(r18); + + vec_double2 x19_v = spu_splats(x19); + vec_double2 r19_v = spu_splats(r19); + + vec_double2 x20_v = spu_splats(x20); + vec_double2 r20_v = spu_splats(r20); + + vec_double2 x21_v = spu_splats(x21); + vec_double2 r21_v = spu_splats(r21); + + vec_double2 x22_v = spu_splats(x22); + vec_double2 r22_v = spu_splats(r22); + + vec_double2 x23_v = spu_splats(x23); + vec_double2 r23_v = spu_splats(r23); + + vec_double2 x24_v = spu_splats(x24); + vec_double2 r24_v = spu_splats(r24); + + vec_double2 x25_v = spu_splats(x25); + vec_double2 r25_v = spu_splats(r25); + + vec_double2 res_v; + + TEST_START("logbd2"); + + res_v = (vec_double2)logbd2(x0_v); + TEST_CHECK("20060905000000AAN", allnan_double2( res_v ), 0); (void)r0_v; + res_v = (vec_double2)logbd2(x1_v); + TEST_CHECK("20060905000001AAN", allequal_double2( res_v, r1_v ), 0); + res_v = (vec_double2)logbd2(x2_v); + TEST_CHECK("20060905000002AAN", allequal_double2( res_v, r2_v ), 0); + res_v = (vec_double2)logbd2(x3_v); + TEST_CHECK("20060905000003AAN", allequal_double2( res_v, r3_v ), 0); + res_v = (vec_double2)logbd2(x4_v); + TEST_CHECK("20060905000004AAN", allequal_double2( res_v, r4_v ), 0); + res_v = (vec_double2)logbd2(x5_v); + TEST_CHECK("20060905000005AAN", allequal_double2( res_v, r5_v ), 0); + res_v = (vec_double2)logbd2(x6_v); + TEST_CHECK("20060905000006AAN", allequal_double2( res_v, r6_v ), 0); + res_v = (vec_double2)logbd2(x7_v); + TEST_CHECK("20060905000007AAN", allequal_double2( res_v, r7_v ), 0); + res_v = (vec_double2)logbd2(x8_v); + TEST_CHECK("20060905000008AAN", allequal_double2( res_v, r8_v ), 0); + res_v = (vec_double2)logbd2(x9_v); + TEST_CHECK("20060905000009AAN", allequal_double2( res_v, r9_v ), 0); + res_v = (vec_double2)logbd2(x10_v); + TEST_CHECK("20060905000010AAN", allequal_double2( res_v, r10_v ), 0); + res_v = (vec_double2)logbd2(x11_v); + TEST_CHECK("20060905000011AAN", allequal_double2( res_v, r11_v ), 0); + res_v = (vec_double2)logbd2(x12_v); + TEST_CHECK("20060905000012AAN", allequal_double2( res_v, r12_v ), 0); + res_v = (vec_double2)logbd2(x13_v); + TEST_CHECK("20060905000013AAN", allequal_double2( res_v, r13_v ), 0); + res_v = (vec_double2)logbd2(x14_v); + TEST_CHECK("20060905000014AAN", allequal_double2( res_v, r14_v ), 0); + res_v = (vec_double2)logbd2(x15_v); + TEST_CHECK("20060905000015AAN", allequal_double2( res_v, r15_v ), 0); + res_v = (vec_double2)logbd2(x16_v); + TEST_CHECK("20060905000016AAN", allequal_double2( res_v, r16_v ), 0); + res_v = (vec_double2)logbd2(x17_v); + TEST_CHECK("20060905000017AAN", allequal_double2( res_v, r17_v ), 0); + res_v = (vec_double2)logbd2(x18_v); + TEST_CHECK("20060905000018AAN", allequal_double2( res_v, r18_v ), 0); + res_v = (vec_double2)logbd2(x19_v); + TEST_CHECK("20060905000019AAN", allequal_double2( res_v, r19_v ), 0); + res_v = (vec_double2)logbd2(x20_v); + TEST_CHECK("20060905000020AAN", allequal_double2( res_v, r20_v ), 0); + res_v = (vec_double2)logbd2(x21_v); + TEST_CHECK("20060905000021AAN", allequal_double2( res_v, r21_v ), 0); + res_v = (vec_double2)logbd2(x22_v); + TEST_CHECK("20060905000022AAN", allequal_double2( res_v, r22_v ), 0); + res_v = (vec_double2)logbd2(x23_v); + TEST_CHECK("20060905000023AAN", allequal_double2( res_v, r23_v ), 0); + res_v = (vec_double2)logbd2(x24_v); + TEST_CHECK("20060905000024AAN", allequal_double2( res_v, r24_v ), 0); + res_v = (vec_double2)logbd2(x25_v); + TEST_CHECK("20060905000025AAN", allnan_double2( res_v ), 0); (void)r25_v; + res_v = (vec_double2)logbd2(x26_v); + TEST_CHECK("20060905000026AAN", allequal_double2( res_v, r26_v ), 0); + res_v = (vec_double2)logbd2(x27_v); + TEST_CHECK("20060905000027AAN", allequal_double2( res_v, r27_v ), 0); + res_v = (vec_double2)logbd2(x28_v); + TEST_CHECK("20060905000028AAN", allequal_ulps_double2( res_v, r28_v, 0 ), 0); + res_v = (vec_double2)logbd2(x29_v); + TEST_CHECK("20060905000029AAN", allequal_ulps_double2( res_v, r29_v, 0 ), 0); + res_v = (vec_double2)logbd2(x30_v); + TEST_CHECK("20060905000030AAN", allequal_double2( res_v, r30_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/logbf4.c b/Extras/simdmathlibrary/spu/tests/logbf4.c new file mode 100644 index 0000000..476a940 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/logbf4.c @@ -0,0 +1,316 @@ +/* Test logbf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060905000000AAN","AAN", "logbf4"); + + // -Norm (IEEE-754: -Nan) + float x0 = hide_float(make_float(0xFFC00000)); + float r0 = 128.0f; + + // -Norm (IEEE-754: -Inf) + float x1 = hide_float(-HUGE_VALF); + float r1 = 128.0f; + + // -Smax + float x2 = hide_float(-FLT_MAX); + float r2 = 128.0f; + + // -Norm + float x3 = hide_float(-824842.58421394); + float r3 = 19.0f; + + // -Smin + float x4 = hide_float(make_float(0x80800000)); + float r4 = -126.0f; + + // -Denorm + float x5 = hide_float(make_float(0x807AAAAA)); + float r5 = -HUGE_VALF; + + // -Unf + float x6 = hide_float(-1.0e-999); + float r6 = -HUGE_VALF; + + // -0 + float x7 = hide_float(-0.0); + float r7 = -HUGE_VALF; + + // 0 + float x8 = hide_float( 0.0); + float r8 = -HUGE_VALF; + + // +Unf + float x9 = hide_float( 1.0e-999); + float r9 = -HUGE_VALF; + + // +Denorm + float x10 = hide_float(make_float(0x007AAAAA)); + float r10 = -HUGE_VALF; + + // +Smin + float x11 = hide_float(make_float(0x00800000)); + float r11 = -126.0f; + + // +Norm + float x12 = hide_float(3.14152634); + float r12 = 1.0f; + + // +Norm + float x13 = hide_float(7.0673903e37); + float r13 = 125.0f; + + // +Norm + float x14 = hide_float(2.4673e14); + float r14 = 47.0f; + + // +Norm + float x15 = hide_float(7.235672e-25); + float r15 = -81.0f; + + // +Norm + float x16 = hide_float(9.452854e17); + float r16 = 59.0f; + + // +Norm + float x17 = hide_float(3.045784e-18); + float r17 = -59.0f; + + // -Norm + float x18 = hide_float(-6.459273e7); + float r18 = 25.0f; + + // -Norm + float x19 = hide_float(-2.493472e-9); + float r19 = -29.0f; + + // -Norm + float x20 = hide_float(-1.4824543e28); + float r20 = 93.0f; + + // -Norm + float x21 = hide_float(-5.53856231e-27); + float r21 = -88.0f; + + // -Norm + float x22 = hide_float(-1.000001); + float r22 = 0.0f; + + // +Smax + float x23 = hide_float(FLT_MAX); + float r23 = 128.0f; + + //+Norm (IEEE-754: +Inf) + float x24 = hide_float(HUGE_VALF); + float r24 = 128.0f; + + //+Norm (IEEE-754: +Nan) + float x25 = hide_float(make_float(0x7FC00000)); + float r25 = 128.0f; + + // Compound + vec_float4 x26_v = (vec_float4) { -2.561286432e10, FLT_MAX, -1.0e-999, 7.235672e-25 }; + vec_float4 r26_v = (vec_float4) { 34.0f, 128.0f, -HUGE_VALF, -81.0f }; + + // Compound + vec_float4 x27_v = (vec_float4) { 345.27533f, 7.0673903e37, -0.0f, -2.40e-310 }; + vec_float4 r27_v = (vec_float4) { 8.0f, 125.0f, -HUGE_VALF, -HUGE_VALF }; + + // Compound + vec_float4 x28_v = (vec_float4) { make_float(0x7FC00000), -824842.58421394f, -0.0f, -3678342.8765343f }; + vec_float4 r28_v = (vec_float4) { 128.0f, 19.0f, -HUGE_VALF, 21.0f }; + + // Compound + vec_float4 x29_v = (vec_float4) { HUGE_VALF, 1.0e-99, -5.53856231e-27, make_float(0xFFC00000) }; + vec_float4 r29_v = (vec_float4) { 128.0f, -HUGE_VALF, -88.0f, 128.0f }; + + // Compound + vec_float4 x30_v = (vec_float4) { 1.2e-57, -1.2e-19, 3.045784e-18, -HUGE_VALF } ; + vec_float4 r30_v = (vec_float4) { -HUGE_VALF, -63.0f, -59.0f, 128.0f }; + + vec_float4 x0_v = spu_splats(x0); + vec_float4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_float4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_float4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_float4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_float4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_float4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_float4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_float4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_float4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_float4 r9_v = spu_splats(r9); + + vec_float4 x10_v = spu_splats(x10); + vec_float4 r10_v = spu_splats(r10); + + vec_float4 x11_v = spu_splats(x11); + vec_float4 r11_v = spu_splats(r11); + + vec_float4 x12_v = spu_splats(x12); + vec_float4 r12_v = spu_splats(r12); + + vec_float4 x13_v = spu_splats(x13); + vec_float4 r13_v = spu_splats(r13); + + vec_float4 x14_v = spu_splats(x14); + vec_float4 r14_v = spu_splats(r14); + + vec_float4 x15_v = spu_splats(x15); + vec_float4 r15_v = spu_splats(r15); + + vec_float4 x16_v = spu_splats(x16); + vec_float4 r16_v = spu_splats(r16); + + vec_float4 x17_v = spu_splats(x17); + vec_float4 r17_v = spu_splats(r17); + + vec_float4 x18_v = spu_splats(x18); + vec_float4 r18_v = spu_splats(r18); + + vec_float4 x19_v = spu_splats(x19); + vec_float4 r19_v = spu_splats(r19); + + vec_float4 x20_v = spu_splats(x20); + vec_float4 r20_v = spu_splats(r20); + + vec_float4 x21_v = spu_splats(x21); + vec_float4 r21_v = spu_splats(r21); + + vec_float4 x22_v = spu_splats(x22); + vec_float4 r22_v = spu_splats(r22); + + vec_float4 x23_v = spu_splats(x23); + vec_float4 r23_v = spu_splats(r23); + + vec_float4 x24_v = spu_splats(x24); + vec_float4 r24_v = spu_splats(r24); + + vec_float4 x25_v = spu_splats(x25); + vec_float4 r25_v = spu_splats(r25); + + vec_float4 res_v; + + TEST_START("logbf4"); + + res_v = (vec_float4)logbf4(x0_v); + TEST_CHECK("20060905000000AAN", allequal_float4( res_v, r0_v ), 0); + res_v = (vec_float4)logbf4(x1_v); + TEST_CHECK("20060905000001AAN", allequal_float4( res_v, r1_v ), 0); + res_v = (vec_float4)logbf4(x2_v); + TEST_CHECK("20060905000002AAN", allequal_float4( res_v, r2_v ), 0); + res_v = (vec_float4)logbf4(x3_v); + TEST_CHECK("20060905000003AAN", allequal_float4( res_v, r3_v ), 0); + res_v = (vec_float4)logbf4(x4_v); + TEST_CHECK("20060905000004AAN", allequal_float4( res_v, r4_v ), 0); + res_v = (vec_float4)logbf4(x5_v); + TEST_CHECK("20060905000005AAN", allequal_float4( res_v, r5_v ), 0); + res_v = (vec_float4)logbf4(x6_v); + TEST_CHECK("20060905000006AAN", allequal_float4( res_v, r6_v ), 0); + res_v = (vec_float4)logbf4(x7_v); + TEST_CHECK("20060905000007AAN", allequal_float4( res_v, r7_v ), 0); + res_v = (vec_float4)logbf4(x8_v); + TEST_CHECK("20060905000008AAN", allequal_float4( res_v, r8_v ), 0); + res_v = (vec_float4)logbf4(x9_v); + TEST_CHECK("20060905000009AAN", allequal_float4( res_v, r9_v ), 0); + res_v = (vec_float4)logbf4(x10_v); + TEST_CHECK("20060905000010AAN", allequal_float4( res_v, r10_v ), 0); + res_v = (vec_float4)logbf4(x11_v); + TEST_CHECK("20060905000011AAN", allequal_float4( res_v, r11_v ), 0); + res_v = (vec_float4)logbf4(x12_v); + TEST_CHECK("20060905000012AAN", allequal_float4( res_v, r12_v ), 0); + res_v = (vec_float4)logbf4(x13_v); + TEST_CHECK("20060905000013AAN", allequal_float4( res_v, r13_v ), 0); + res_v = (vec_float4)logbf4(x14_v); + TEST_CHECK("20060905000014AAN", allequal_float4( res_v, r14_v ), 0); + res_v = (vec_float4)logbf4(x15_v); + TEST_CHECK("20060905000015AAN", allequal_float4( res_v, r15_v ), 0); + res_v = (vec_float4)logbf4(x16_v); + TEST_CHECK("20060905000016AAN", allequal_float4( res_v, r16_v ), 0); + res_v = (vec_float4)logbf4(x17_v); + TEST_CHECK("20060905000017AAN", allequal_float4( res_v, r17_v ), 0); + res_v = (vec_float4)logbf4(x18_v); + TEST_CHECK("20060905000018AAN", allequal_float4( res_v, r18_v ), 0); + res_v = (vec_float4)logbf4(x19_v); + TEST_CHECK("20060905000019AAN", allequal_float4( res_v, r19_v ), 0); + res_v = (vec_float4)logbf4(x20_v); + TEST_CHECK("20060905000020AAN", allequal_float4( res_v, r20_v ), 0); + res_v = (vec_float4)logbf4(x21_v); + TEST_CHECK("20060905000021AAN", allequal_float4( res_v, r21_v ), 0); + res_v = (vec_float4)logbf4(x22_v); + TEST_CHECK("20060905000022AAN", allequal_float4( res_v, r22_v ), 0); + res_v = (vec_float4)logbf4(x23_v); + TEST_CHECK("20060905000023AAN", allequal_float4( res_v, r23_v ), 0); + res_v = (vec_float4)logbf4(x24_v); + TEST_CHECK("20060905000024AAN", allequal_float4( res_v, r24_v ), 0); + res_v = (vec_float4)logbf4(x25_v); + TEST_CHECK("20060905000025AAN", allequal_float4( res_v, r25_v ), 0); + res_v = (vec_float4)logbf4(x26_v); + TEST_CHECK("20060905000026AAN", allequal_float4( res_v, r26_v ), 0); + res_v = (vec_float4)logbf4(x27_v); + TEST_CHECK("20060905000027AAN", allequal_float4( res_v, r27_v ), 0); + res_v = (vec_float4)logbf4(x28_v); + TEST_CHECK("20060905000028AAN", allequal_float4( res_v, r28_v ), 0); + res_v = (vec_float4)logbf4(x29_v); + TEST_CHECK("20060905000029AAN", allequal_float4( res_v, r29_v ), 0); + res_v = (vec_float4)logbf4(x30_v); + TEST_CHECK("20060905000030AAN", allequal_float4( res_v, r30_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/modfd2.c b/Extras/simdmathlibrary/spu/tests/modfd2.c new file mode 100644 index 0000000..88ee903 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/modfd2.c @@ -0,0 +1,109 @@ +/* Test modfd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060901173000MH", "MH", "modfd2"); + + unsigned long long i3 = 0x432fffffffffffffull; // 2^52 - 0.5, largest truncatable value. + unsigned long long i3i = 0x432ffffffffffffeull; + unsigned long long i4 = 0x4330000000000000ull; // 2^53, no fractional part. + unsigned long long i5 = 0xcff0000000000001ull; // one more large, and negative, value. + + double x0 = hide_double(0.91825); + double x0i = hide_double(0.0); + double x0f = hide_double(0.91825); + + double x1 = hide_double(-0.12958); + double x1i = hide_double(0.0); + double x1f = hide_double(-0.12958); + + double x2 = hide_double(-79615.1875); + double x2i = hide_double(-79615.0); + double x2f = hide_double(-0.1875); + + double x3 = hide_double(make_double(i3)); + double x3i = hide_double(make_double(i3i)); + double x3f = hide_double(0.5); + + double x4 = hide_double(make_double(i4)); + double x4i = hide_double(make_double(i4)); + double x4f = hide_double(0.0); + + double x5 = hide_double(make_double(i5)); + double x5i = hide_double(make_double(i5)); + double x5f = hide_double(0.0); + + vec_double2 x0_v = spu_splats(x0); + vec_double2 x0i_v = spu_splats(x0i); + vec_double2 x0f_v = spu_splats(x0f); + vec_double2 x1_v = spu_splats(x1); + vec_double2 x1i_v = spu_splats(x1i); + vec_double2 x1f_v = spu_splats(x1f); + vec_double2 x2_v = spu_splats(x2); + vec_double2 x2i_v = spu_splats(x2i); + vec_double2 x2f_v = spu_splats(x2f); + vec_double2 x3_v = spu_splats(x3); + vec_double2 x3i_v = spu_splats(x3i); + vec_double2 x3f_v = spu_splats(x3f); + vec_double2 x4_v = spu_splats(x4); + vec_double2 x4i_v = spu_splats(x4i); + vec_double2 x4f_v = spu_splats(x4f); + vec_double2 x5_v = spu_splats(x5); + vec_double2 x5i_v = spu_splats(x5i); + vec_double2 x5f_v = spu_splats(x5f); + + vec_double2 integer_v, fraction_v; + + TEST_START("modff4"); + fraction_v = modfd2(x0_v, &integer_v); + TEST_CHECK("20040916170647EJL", allequal_double2( integer_v, x0i_v ) && allequal_double2( fraction_v, x0f_v ), 0); + fraction_v = modfd2(x1_v, &integer_v); + TEST_CHECK("20040916170650EJL", allequal_double2( integer_v, x1i_v ) && allequal_double2( fraction_v, x1f_v ), 0); + fraction_v = modfd2(x2_v, &integer_v); + TEST_CHECK("20040916170653EJL", allequal_double2( integer_v, x2i_v ) && allequal_double2( fraction_v, x2f_v ), 0); + fraction_v = modfd2(x3_v, &integer_v); + TEST_CHECK("20040916170656EJL", allequal_double2( integer_v, x3i_v ) && allequal_double2( fraction_v, x3f_v ), 0); + fraction_v = modfd2(x4_v, &integer_v); + TEST_CHECK("20040916170658EJL", allequal_double2( integer_v, x4i_v ) && allequal_double2( fraction_v, x4f_v ), 0); + fraction_v = modfd2(x5_v, &integer_v); + TEST_CHECK("20040916170701EJL", allequal_double2( integer_v, x5i_v ) && allequal_double2( fraction_v, x5f_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/modff4.c b/Extras/simdmathlibrary/spu/tests/modff4.c new file mode 100644 index 0000000..df547a9 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/modff4.c @@ -0,0 +1,124 @@ +/* Test modff4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20040916170642EJL", "EJL", "modff"); + + unsigned int i3 = 0x4affffff; // 2^23 - 0.5, largest truncatable value. + unsigned int i3i = 0x4afffffe; + unsigned int i4 = 0x4b000000; // 2^23, no fractional part. + unsigned int i5 = 0xcf000001; // -2^31, one more large, and negative, value. + + float x0 = hide_float(0.91825f); + float x0i = hide_float(0.0f); + float x0f = hide_float(0.91825f); + + float x1 = hide_float(-0.12958f); + float x1i = hide_float(0.0f); + float x1f = hide_float(-0.12958f); + + float x2 = hide_float(-79615.1875f); + float x2i = hide_float(-79615.0f); + float x2f = hide_float(-0.1875f); + + float x3 = hide_float(make_float(i3)); + float x3i = hide_float(make_float(i3i)); + float x3f = hide_float(0.5f); + + float x4 = hide_float(make_float(i4)); + float x4i = hide_float(make_float(i4)); + float x4f = hide_float(0.0f); + + float x5 = hide_float(make_float(i5)); + float x5i = hide_float(make_float(i5)); + float x5f = hide_float(0.0f); + + vec_float4 x0_v = spu_splats(x0); + vec_float4 x0i_v = spu_splats(x0i); + vec_float4 x0f_v = spu_splats(x0f); + vec_float4 x1_v = spu_splats(x1); + vec_float4 x1i_v = spu_splats(x1i); + vec_float4 x1f_v = spu_splats(x1f); + vec_float4 x2_v = spu_splats(x2); + vec_float4 x2i_v = spu_splats(x2i); + vec_float4 x2f_v = spu_splats(x2f); + vec_float4 x3_v = spu_splats(x3); + vec_float4 x3i_v = spu_splats(x3i); + vec_float4 x3f_v = spu_splats(x3f); + vec_float4 x4_v = spu_splats(x4); + vec_float4 x4i_v = spu_splats(x4i); + vec_float4 x4f_v = spu_splats(x4f); + vec_float4 x5_v = spu_splats(x5); + vec_float4 x5i_v = spu_splats(x5i); + vec_float4 x5f_v = spu_splats(x5f); + + float integer, fraction; + vec_float4 integer_v, fraction_v; + + TEST_START("modff4"); + fraction_v = modff4(x0_v, &integer_v); + TEST_CHECK("20040916170647EJL", allequal_float4( integer_v, x0i_v ) && allequal_float4( fraction_v, x0f_v ), 0); + fraction_v = modff4(x1_v, &integer_v); + TEST_CHECK("20040916170650EJL", allequal_float4( integer_v, x1i_v ) && allequal_float4( fraction_v, x1f_v ), 0); + fraction_v = modff4(x2_v, &integer_v); + TEST_CHECK("20040916170653EJL", allequal_float4( integer_v, x2i_v ) && allequal_float4( fraction_v, x2f_v ), 0); + fraction_v = modff4(x3_v, &integer_v); + TEST_CHECK("20040916170656EJL", allequal_float4( integer_v, x3i_v ) && allequal_float4( fraction_v, x3f_v ), 0); + fraction_v = modff4(x4_v, &integer_v); + TEST_CHECK("20040916170658EJL", allequal_float4( integer_v, x4i_v ) && allequal_float4( fraction_v, x4f_v ), 0); + fraction_v = modff4(x5_v, &integer_v); + TEST_CHECK("20040916170701EJL", allequal_float4( integer_v, x5i_v ) && allequal_float4( fraction_v, x5f_v ), 0); + + TEST_START("modff"); + fraction = modff(x0, &integer); + TEST_CHECK("20040916170704EJL", integer == x0i && fraction == x0f, 0); + fraction = modff(x1, &integer); + TEST_CHECK("20040916170706EJL", integer == x1i && fraction == x1f, 0); + fraction = modff(x2, &integer); + TEST_CHECK("20040916170709EJL", integer == x2i && fraction == x2f, 0); + fraction = modff(x3, &integer); + TEST_CHECK("20040916170711EJL", integer == x3i && fraction == x3f, 0); + fraction = modff(x4, &integer); + TEST_CHECK("20040916170714EJL", integer == x4i && fraction == x4f, 0); + fraction = modff(x5, &integer); + TEST_CHECK("20040916170716EJL", integer == x5i && fraction == x5f, 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/nearbyintd2.c b/Extras/simdmathlibrary/spu/tests/nearbyintd2.c new file mode 100644 index 0000000..e15a1f6 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/nearbyintd2.c @@ -0,0 +1,178 @@ +/* Test nearbyintd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/** + * + *@@ nearbyintd2 - Round the input to the nearest integer according to + * the current rounding mode without raising an inexact exception. + * + *@brief + * boundary test for nearbyintd2. + * + * + *@pre + * + *@criteria + * Run this program and check no error will be occurred. + * + *@note + * + **/ + + +#include +#include +#include +//#include +#include + +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +typedef struct { + unsigned long long int xxx[2]; + unsigned long long int ans0[2]; + unsigned long long int ans1[2]; + unsigned long long int ans2[2]; + unsigned long long int ans3[2]; +} TestVec64_NerI; + +int main() +{ + TestVec64_NerI test_a[] = { + { + // zero + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL} + },{ + // border + {0xc330000000000000ULL,0x4330000000000000ULL}, + {0xc330000000000000ULL,0x4330000000000000ULL}, + {0xc330000000000000ULL,0x4330000000000000ULL}, + {0xc330000000000000ULL,0x4330000000000000ULL}, + {0xc330000000000000ULL,0x4330000000000000ULL} + },{ + // MIN , MAX + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL} + },{ + // Inf , -Inf + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL} + },{ + // denotmalized + {0x8000000000000001ULL,0x0000000000000001ULL}, + {0x8000000000000000ULL,0x0000000000000000ULL}, + {0x8000000000000000ULL,0x0000000000000000ULL}, + {0x8000000000000000ULL,0x3ff0000000000000ULL}, + {0xbff0000000000000ULL,0x0000000000000000ULL} + },{ + // denotmalized + {0x0008000000000000ULL,0x8008000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x3ff0000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0xbff0000000000000ULL} + },{ + // 1.0 + {0x3ff0000000000000ULL,0xbff0000000000000ULL}, + {0x3ff0000000000000ULL,0xbff0000000000000ULL}, + {0x3ff0000000000000ULL,0xbff0000000000000ULL}, + {0x3ff0000000000000ULL,0xbff0000000000000ULL}, + {0x3ff0000000000000ULL,0xbff0000000000000ULL} + },{ + // 1.5 + {0x3ff8000000000000ULL,0xbff8000000000000ULL}, + {0x4000000000000000ULL,0xc000000000000000ULL}, + {0x3ff0000000000000ULL,0xbff0000000000000ULL}, + {0x4000000000000000ULL,0xbff0000000000000ULL}, + {0x3ff0000000000000ULL,0xc000000000000000ULL} + },{ + // 2.5 + {0x4004000000000000ULL,0xc004000000000000ULL}, + {0x4000000000000000ULL,0xc000000000000000ULL}, + {0x4000000000000000ULL,0xc000000000000000ULL}, + {0x4008000000000000ULL,0xc000000000000000ULL}, + {0x4000000000000000ULL,0xc008000000000000ULL} + },{ + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL} + + } + }; + int ii, test_ctr = 1; + char msg[80]; + vec_double2 res_v; + + TEST_SET_START("20060829200000NM","NM", "nearbyintd2"); + + TEST_START("nearbyintd2"); + + for (ii=0; ; ii++) { + if ( (test_a[ii].xxx[0] == 0) && (test_a[ii].xxx[1] == 0) ) break; + + // set Floating point round mode + spu_mtfpscr(((vec_uint4){0x0000,0,0,0})); + res_v = nearbyintd2 (*((vec_double2 *)&test_a[ii].xxx[0])); + sprintf(msg,"2006082920%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans0[0])), 0); + + spu_mtfpscr(((vec_uint4){0x0500,0,0,0})); + res_v = nearbyintd2 (*((vec_double2 *)&test_a[ii].xxx[0])); + sprintf(msg,"2006082920%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans1[0])), 0); + + spu_mtfpscr(((vec_uint4){0x0a00,0,0,0})); + res_v = nearbyintd2 (*((vec_double2 *)&test_a[ii].xxx[0])); + sprintf(msg,"2006082920%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans2[0])), 0); + + spu_mtfpscr(((vec_uint4){0x0f00,0,0,0})); + res_v = nearbyintd2 (*((vec_double2 *)&test_a[ii].xxx[0])); + sprintf(msg,"2006082920%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans3[0])), 0); + } + + TEST_SET_DONE(); + + TEST_EXIT(); + +} diff --git a/Extras/simdmathlibrary/spu/tests/nearbyintf4.c b/Extras/simdmathlibrary/spu/tests/nearbyintf4.c new file mode 100644 index 0000000..ca6a72b --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/nearbyintf4.c @@ -0,0 +1,95 @@ +/* Test nearbyintf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +#define DEFINE_DATA(var,a,b) \ + float var = hide_float(a); \ + float var ## _out = hide_float(b); \ + vec_float4 var ## _v = spu_splats(var); \ + vec_float4 var ## _out_v = spu_splats(var ## _out); + +/* + */ +#define DEFINE_DATA_UNSIGNED(var,a,b)\ + unsigned int var ## _ina = a ; \ + unsigned int var ## _inb = b ; \ + float var = make_float(var ## _ina); \ + float var ## _out = make_float(var ## _inb); \ + vec_float4 var ## _v = spu_splats(var); \ + vec_float4 var ## _out_v = spu_splats(var ## _out); + +#define DO_TEST(var,id) \ + res_v = nearbyintf4(var ## _v); \ + TEST_CHECK(" #id ", allequal_float4( res_v, var ## _out_v ), 0); + + +int main() +{ + vec_float4 res_v; + + TEST_SET_START("625018616200","NBI", "nearbyintf4"); + + + + + //s=0, e=100, f=7fffff --> s=0, e=100, f=7fffff + DEFINE_DATA_UNSIGNED(x1,0x71ffffff,0x71ffffff) + //s=0, e=22, f=0x7fffff --> s=0,e=22,f=0x7ffffe + DEFINE_DATA_UNSIGNED(x2, 0x4affffff,0x4afffffe) + //s=0, e=23, f=0 --> s=0,e=23,f=0 + DEFINE_DATA_UNSIGNED(x3, 0x4b000000,0x4b000000) + //s=0, e=-126, f=0 --> 0 + DEFINE_DATA_UNSIGNED(x4, 0x800000,0x0) + DEFINE_DATA(x5, 1.001f, 1.f) + DEFINE_DATA(x6, -.05f, 0.f) + DEFINE_DATA(x7, 0.9999f, 0.f) + DEFINE_DATA(x8, 0.4999f, 0.f) + + TEST_START("nearbyintf4"); + DO_TEST(x1,625018616201NBI) + DO_TEST(x2,625018616202NBI) + DO_TEST(x3,625018616203NBI) + DO_TEST(x4,625018616204NBI) + DO_TEST(x5,625018616205NBI) + DO_TEST(x6,625018616206NBI) + DO_TEST(x7,625018616207NBI) + DO_TEST(x8,625018616208NBI) + TEST_SET_DONE(); + + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/negated2.c b/Extras/simdmathlibrary/spu/tests/negated2.c new file mode 100644 index 0000000..071a90b --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/negated2.c @@ -0,0 +1,83 @@ +/* Test negated2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20040930102626EJL","EJL", "negated2"); + + double x0n = hide_double(-0.0); + double x0p = hide_double(0.0); + double x1n = hide_double(-83532.96153153); + double x1p = hide_double(83532.96153153); + double x2n = hide_double(-0.0000000013152); + double x2p = hide_double(0.0000000013152); + double x3n = hide_double(-HUGE_VAL); + double x3p = hide_double(HUGE_VAL); + + vec_double2 x0n_v = spu_splats(x0n); + vec_double2 x0p_v = spu_splats(x0p); + vec_double2 x1n_v = spu_splats(x1n); + vec_double2 x1p_v = spu_splats(x1p); + vec_double2 x2n_v = spu_splats(x2n); + vec_double2 x2p_v = spu_splats(x2p); + vec_double2 x3n_v = spu_splats(x3n); + vec_double2 x3p_v = spu_splats(x3p); + + vec_double2 res_v; + + TEST_START("negated2"); + res_v = negated2(x0n_v); + TEST_CHECK("20040930102629EJL", allequal_double2( res_v, x0p_v ), 0); + res_v = negated2(x0p_v); + TEST_CHECK("20040930102631EJL", allequal_double2( res_v, x0n_v ), 0); + res_v = negated2(x1n_v); + TEST_CHECK("20040930102632EJL", allequal_double2( res_v, x1p_v ), 0); + res_v = negated2(x1p_v); + TEST_CHECK("20040930102635EJL", allequal_double2( res_v, x1n_v ), 0); + res_v = negated2(x2n_v); + TEST_CHECK("20040930102637EJL", allequal_double2( res_v, x2p_v ), 0); + res_v = negated2(x2p_v); + TEST_CHECK("20040930102639EJL", allequal_double2( res_v, x2n_v ), 0); + res_v = negated2(x3n_v); + TEST_CHECK("20040930102641EJL", allposinf_double2( res_v ), 0); + res_v = negated2(x3p_v); + TEST_CHECK("20040930102643EJL", allneginf_double2( res_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/negatef4.c b/Extras/simdmathlibrary/spu/tests/negatef4.c new file mode 100644 index 0000000..cb9310e --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/negatef4.c @@ -0,0 +1,87 @@ +/* Test negatef4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20040930102649EJL","EJL", "negatef4"); + + unsigned int i3n = 0xffffffff; + unsigned int i3p = 0x7fffffff; + + float x0n = hide_float(-0.0f); + float x0p = hide_float(0.0f); + float x1n = hide_float(-83532.96153153f); + float x1p = hide_float(83532.96153153f); + float x2n = hide_float(-0.0000000013152f); + float x2p = hide_float(0.0000000013152f); + float x3n = hide_float(make_float(i3n)); + float x3p = hide_float(make_float(i3p)); + + vec_float4 x0n_v = spu_splats(x0n); + vec_float4 x0p_v = spu_splats(x0p); + vec_float4 x1n_v = spu_splats(x1n); + vec_float4 x1p_v = spu_splats(x1p); + vec_float4 x2n_v = spu_splats(x2n); + vec_float4 x2p_v = spu_splats(x2p); + vec_float4 x3n_v = spu_splats(x3n); + vec_float4 x3p_v = spu_splats(x3p); + + vec_float4 res_v; + + TEST_START("negatef4"); + res_v = negatef4(x0n_v); + TEST_CHECK("20040930102652EJL", allequal_float4( res_v, x0p_v ), 0); + res_v = negatef4(x0p_v); + TEST_CHECK("20040930102653EJL", allequal_float4( res_v, x0n_v ), 0); + res_v = negatef4(x1n_v); + TEST_CHECK("20040930102655EJL", allequal_float4( res_v, x1p_v ), 0); + res_v = negatef4(x1p_v); + TEST_CHECK("20040930102657EJL", allequal_float4( res_v, x1n_v ), 0); + res_v = negatef4(x2n_v); + TEST_CHECK("20040930102659EJL", allequal_float4( res_v, x2p_v ), 0); + res_v = negatef4(x2p_v); + TEST_CHECK("20040930102701EJL", allequal_float4( res_v, x2n_v ), 0); + res_v = negatef4(x3n_v); + TEST_CHECK("20040930102703EJL", allequal_float4( res_v, x3p_v ), 0); + res_v = negatef4(x3p_v); + TEST_CHECK("20040930102705EJL", allequal_float4( res_v, x3n_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/negatei4.c b/Extras/simdmathlibrary/spu/tests/negatei4.c new file mode 100644 index 0000000..5ef6df5 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/negatei4.c @@ -0,0 +1,83 @@ +/* Test negatei4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20040930102649EJL","EJL", "negatei4"); + + int x0n = hide_int(0); + int x0p = hide_int(0); + int x1n = hide_int(-83532); + int x1p = hide_int(83532); + int x2n = hide_int(-13152); + int x2p = hide_int(13152); + int x3n = hide_int(-1); + int x3p = hide_int(1); + + vec_int4 x0n_v = spu_splats(x0n); + vec_int4 x0p_v = spu_splats(x0p); + vec_int4 x1n_v = spu_splats(x1n); + vec_int4 x1p_v = spu_splats(x1p); + vec_int4 x2n_v = spu_splats(x2n); + vec_int4 x2p_v = spu_splats(x2p); + vec_int4 x3n_v = spu_splats(x3n); + vec_int4 x3p_v = spu_splats(x3p); + + vec_int4 res_v; + + TEST_START("negatei4"); + res_v = negatei4(x0n_v); + TEST_CHECK("20040930102652EJL", allequal_int4( res_v, x0p_v ), 0); + res_v = negatei4(x0p_v); + TEST_CHECK("20040930102653EJL", allequal_int4( res_v, x0n_v ), 0); + res_v = negatei4(x1n_v); + TEST_CHECK("20040930102655EJL", allequal_int4( res_v, x1p_v ), 0); + res_v = negatei4(x1p_v); + TEST_CHECK("20040930102657EJL", allequal_int4( res_v, x1n_v ), 0); + res_v = negatei4(x2n_v); + TEST_CHECK("20040930102659EJL", allequal_int4( res_v, x2p_v ), 0); + res_v = negatei4(x2p_v); + TEST_CHECK("20040930102701EJL", allequal_int4( res_v, x2n_v ), 0); + res_v = negatei4(x3n_v); + TEST_CHECK("20040930102703EJL", allequal_int4( res_v, x3p_v ), 0); + res_v = negatei4(x3p_v); + TEST_CHECK("20040930102705EJL", allequal_int4( res_v, x3n_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/negatell2.c b/Extras/simdmathlibrary/spu/tests/negatell2.c new file mode 100644 index 0000000..76d346f --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/negatell2.c @@ -0,0 +1,86 @@ +/* Test negatell2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060731203500MH","MH", "negatell2"); + + vec_llong2 x0n_v = spu_splats(0LL); + vec_llong2 x0p_v = spu_splats(0LL); + vec_llong2 x1n_v = spu_splats(-83582LL); + vec_llong2 x1p_v = spu_splats(83582LL); + vec_llong2 x2n_v = spu_splats(-13152LL); + vec_llong2 x2p_v = spu_splats(13152LL); + vec_llong2 x3n_v = spu_splats(-1LL); + vec_llong2 x3p_v = spu_splats(1LL); + vec_llong2 x4n_v = spu_splats((long long)0x8000000000000001ULL); + vec_llong2 x4p_v = spu_splats(0x7fffffffffffffffLL); + vec_llong2 x5n_v = spu_splats((long long)0x8000000100000000ULL); + vec_llong2 x5p_v = spu_splats(0x7fffffff00000000LL); + + vec_llong2 res_v; + + TEST_START("negatell2"); + res_v = negatell2(x0n_v); + TEST_CHECK("20060731203501MH", allequal_llong2( res_v, x0p_v ), 0); + res_v = negatell2(x0p_v); + TEST_CHECK("20060731203502MH", allequal_llong2( res_v, x0n_v ), 0); + res_v = negatell2(x1n_v); + TEST_CHECK("20060731203503MH", allequal_llong2( res_v, x1p_v ), 0); + res_v = negatell2(x1p_v); + TEST_CHECK("20060731203504MH", allequal_llong2( res_v, x1n_v ), 0); + res_v = negatell2(x2n_v); + TEST_CHECK("20060731203505MH", allequal_llong2( res_v, x2p_v ), 0); + res_v = negatell2(x2p_v); + TEST_CHECK("20060731203506MH", allequal_llong2( res_v, x2n_v ), 0); + res_v = negatell2(x3n_v); + TEST_CHECK("20060731203507MH", allequal_llong2( res_v, x3p_v ), 0); + res_v = negatell2(x3p_v); + TEST_CHECK("20060731203508MH", allequal_llong2( res_v, x3n_v ), 0); + res_v = negatell2(x4n_v); + TEST_CHECK("20060731203509MH", allequal_llong2( res_v, x4p_v ), 0); + res_v = negatell2(x4p_v); + TEST_CHECK("20060731203510MH", allequal_llong2( res_v, x4n_v ), 0); + res_v = negatell2(x5n_v); + TEST_CHECK("20060731203511MH", allequal_llong2( res_v, x5p_v ), 0); + res_v = negatell2(x5p_v); + TEST_CHECK("20060731203512MH", allequal_llong2( res_v, x5n_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/nextafterd2.c b/Extras/simdmathlibrary/spu/tests/nextafterd2.c new file mode 100644 index 0000000..cb40978 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/nextafterd2.c @@ -0,0 +1,153 @@ +/* Test nextafterd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/** + * + *@@ nextafterd2 - find next representable floating-point value towards 2nd param. + * + *@brief + * boundary test for nextafterd2. + * + * + *@pre + * + *@criteria + * Run this program and check no error will be occurred. + * + *@note + * + * + **/ + +#include +#include +#include +//#include +#include + +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +typedef struct { + unsigned long long int xxx[2]; + unsigned long long int yyy[2]; + unsigned long long int ans[2]; +} TestVec64_NexA; + +int main() +{ + TestVec64_NexA test_a[] = { + { + // -1 -> -0 , 0 -> -1 + {0x8000000000000001ULL,0x0000000000000000ULL}, + {0x8000000000000000ULL,0x8000000000000001ULL}, + {0x8000000000000000ULL,0x8000000000000001ULL} + },{ + // -1 -> -0 , 0 -> -1 + {0x8000000000000001ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000001ULL}, + {0x8000000000000000ULL,0x8000000000000001ULL} + },{ + // 0 -> -0 , -0 -> 0 + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x8000000000000000ULL,0x0000000000000000ULL}, + {0x8000000000000000ULL,0x0000000000000000ULL} + },{ + // -Inf -> MIN , Inf -> MAX + {0xFFF0000000000000ULL,0x7FF0000000000000ULL}, + {0x0010000000000000ULL,0x0000000000000000ULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL} + },{ + // MAX -> Inf , MIN -> -Inf + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL} + },{ + // Denormalize -> Denormalize + {0x0000000000000001ULL,0x8000000000000010ULL}, + {0x0000000000000003ULL,0x8000000000000020ULL}, + {0x0000000000000002ULL,0x8000000000000011ULL} + },{ + // Denormalize -> Normalize + {0x000FFFFFFFFFFFFFULL,0x800FFFFFFFFFFFFFULL}, + {0x0020000000000000ULL,0x8020000000000000ULL}, + {0x0010000000000000ULL,0x8010000000000000ULL} + },{ + // Normalize -> Denormalize + {0x0010000000000000ULL,0x8010000000000000ULL}, + {0x8010000000000000ULL,0x0020000000000000ULL}, + {0x000FFFFFFFFFFFFFULL,0x800FFFFFFFFFFFFFULL} + },{ + // equal + {0x8FFFFFFFFFFFFFFFULL,0x0FFFFFFFFFFFFFFFULL}, + {0x8FFFFFFFFFFFFFFFULL,0x0FFFFFFFFFFFFFFFULL}, + {0x8FFFFFFFFFFFFFFFULL,0x0FFFFFFFFFFFFFFFULL} + },{ + // + {0x8FFFFFFFFFFFFFFFULL,0x0FFFFFFFFFFFFFFFULL}, + {0x9FFFFFFFFFFFFFFFULL,0x1FFFFFFFFFFFFFFFULL}, + {0x9000000000000000ULL,0x1000000000000000ULL} + },{ + // + {0x7000000000000000ULL,0xF000000000000000ULL}, + {0x0000000000000001ULL,0x8000000000000001ULL}, + {0x6FFFFFFFFFFFFFFFULL,0xEFFFFFFFFFFFFFFFULL} + },{ + // Nan + {0x7000000000000000ULL,0xF000000000000000ULL}, + {0xFFF0000000000001ULL,0x7FF0000000000001ULL}, + {0xFFF0000000000001ULL,0x7FF0000000000001ULL} + },{ + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL} + + } + }; + int ii, test_ctr = 1; + char msg[80]; + vec_double2 res_v; + + TEST_SET_START("20060828130000NM","NM", "nextafterd2"); + + TEST_START("nextafterd2"); + + for (ii=0; ; ii++) { + if ( (test_a[ii].xxx[0] == 0) && (test_a[ii].xxx[1] == 0) ) break; + + res_v = nextafterd2 (*((vec_double2 *)&test_a[ii].xxx[0]), *((vec_double2 *)&test_a[ii].yyy[0])); + sprintf(msg,"2006082813%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans[0])), 0); + } + + TEST_SET_DONE(); + + TEST_EXIT(); + +} diff --git a/Extras/simdmathlibrary/spu/tests/nextafterf4.c b/Extras/simdmathlibrary/spu/tests/nextafterf4.c new file mode 100644 index 0000000..c6cea84 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/nextafterf4.c @@ -0,0 +1,162 @@ +/* Test nextafterf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +//a :float, b: float: c:bit pattern +#define DEFINE_DATA(var,a,b,c) \ + float var ## _a = a;\ +vec_float4 var ## _a_v = spu_splats(var ## _a); \ + float var ## _b = b;\ +vec_float4 var ## _b_v = spu_splats(var ## _b); \ + unsigned int var ## _inc = c ; \ + float var ## _out = make_float(var ## _inc);\ + vec_float4 var ## _out_v = spu_splats(var ## _out);\ + +//a :bit pattern, b: bit pattern: c:bit pattern +#define DEFINE_DATA_UNSIGNED(var,a,b,c) \ + unsigned int var ## _ina = a ; \ + float var ## _a = make_float(var ## _ina); \ + vec_float4 var ## _a_v = spu_splats(var ## _a); \ + unsigned int var ## _inb = b ; \ + float var ## _b = make_float(var ## _inb); \ + vec_float4 var ## _b_v = spu_splats(var ## _b); \ + unsigned int var ## _inc = c ; \ + float var ## _out = make_float(var ## _inc); \ + vec_float4 var ## _out_v = spu_splats(var ## _out); + +#define DO_TEST(var,id) \ + res_v = nextafterf4(var ## _a_v, var ## _b_v);\ + TEST_CHECK(" #id ", allequal_float4( res_v, var ## _out_v ), 0); + + +int main() +{ + vec_float4 res_v; + + TEST_SET_START("958726589700","NAR", "nextafterf4"); + + + + // == + // 1.0f --> 1.0f + DEFINE_DATA(x1, 1.0f, 1.0f, 0x3f800000) + DEFINE_DATA(x2, 0.0f, 0.0f, 0x0) + + // * Icrement * + + // -FLT_MAX -> + DEFINE_DATA_UNSIGNED(x3,0xffffffff, 0x0, 0xfffffffe) + //(1, 40, 0) --> (1, 39, 7fffff) + DEFINE_DATA_UNSIGNED(x4,0xd3800000, 0x0, 0xd37fffff) + // (1,-40,0 ) --> (1,-41,0x7fffff) + DEFINE_DATA_UNSIGNED(x5,0xab800000, 0x0, 0xab7fffff) + //-FLT_MIN --> 0 + DEFINE_DATA_UNSIGNED(x6,0x80800000, 0x0, 0x0) + //0.0f --> FLT_MIN + DEFINE_DATA(x7, 0.0f, 1.0f, 0x800000) + //-0.0f --> FLT_MIN + DEFINE_DATA_UNSIGNED(x8, 0x80000000, 0x7fffffff, 0x800000) + //FLT_MIN --> + DEFINE_DATA_UNSIGNED(x9, 0x800000, 0x7fffffff, 0x800001) + // (0, -41, 7fffff) --> (0, -40, 0) + DEFINE_DATA_UNSIGNED(x10, 0x2b7fffff, 0x7fffffff, 0x2b800000) + // (0, 40, 7fffff) --> (0, 41, 0) + DEFINE_DATA_UNSIGNED(x11, 0x53ffffff, 0x7fffffff, 0x54000000) + // FLT_MAX --> + DEFINE_DATA_UNSIGNED(x12,0x7fffffff,0x7fffffff,0x7fffffff) + + // * Decrement * + + // FLT_MAX --> FLT_MAX + DEFINE_DATA_UNSIGNED(x13,0x7fffffff,0x7fffffff,0x7fffffff) + // FLT_MAX --> + DEFINE_DATA_UNSIGNED(x14,0x7fffffff,0x0,0x7ffffffe) + // (0, 41, 0) --> (0, 40, 7fffff) + DEFINE_DATA_UNSIGNED(x15, 0x54000000, 0x0, 0x53ffffff) + // (0, -40, 0) --> (0, -41, 7fffff) + DEFINE_DATA_UNSIGNED(x16, 0x2b800000,0x0, 0x2b7fffff) + // -> FLT_MIN + DEFINE_DATA_UNSIGNED(x17, 0x800001, 0x800000, 0x800000) + // FLT_MIN --> 0 + DEFINE_DATA_UNSIGNED(x18, 0x800000, 0x0, 0x0) + // 0.0 -> -FLT_MIN + DEFINE_DATA_UNSIGNED(x19, 0x0, 0xffffffff, 0x80800000) + // -0.0 -> FLT_MIN + DEFINE_DATA_UNSIGNED(x20, 0x80000000, 0xffffffff, 0x80800000) + //-FLT_MIN --> + DEFINE_DATA_UNSIGNED(x21, 0x80800000, 0xffffffff, 0x80800001) + // (1,-41,0x7fffff) --> (1,-40,0 ) + DEFINE_DATA_UNSIGNED(x22, 0xab7fffff, 0xffffffff, 0xab800000) + //(1, 40, 0) --> (1, 39, 7fffff) + DEFINE_DATA_UNSIGNED(x23, 0xd37fffff, 0xffffffff, 0xd3800000) + // --> -FLT_MAX + DEFINE_DATA_UNSIGNED(x24,0xfffffffe, 0xffffffff, 0xffffffff) + + + //TEST + TEST_START("nextafterf4"); + DO_TEST(x1,958726589701NAR) + DO_TEST(x2,958726589702NAR) + DO_TEST(x3,958726589703NAR) + DO_TEST(x4,958726589704NAR) + DO_TEST(x5,958726589705NAR) + DO_TEST(x6,958726589706NAR) + DO_TEST(x7,958726589707NAR) + DO_TEST(x8,958726589708NAR) + DO_TEST(x9,958726589709NAR) + DO_TEST(x10,958726589710NAR) + DO_TEST(x11,958726589711NAR) + DO_TEST(x12,958726589712NAR) + DO_TEST(x13,958726589713NAR) + DO_TEST(x14,958726589714NAR) + DO_TEST(x15,958726589715NAR) + DO_TEST(x16,958726589716NAR) + DO_TEST(x17,958726589717NAR) + DO_TEST(x18,958726589718NAR) + DO_TEST(x19,958726589719NAR) + DO_TEST(x20,958726589720NAR) + DO_TEST(x21,958726589721NAR) + DO_TEST(x22,958726589722NAR) + DO_TEST(x23,958726589723NAR) + DO_TEST(x24,958726589724NAR) + + TEST_SET_DONE(); + + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/recipd2.c b/Extras/simdmathlibrary/spu/tests/recipd2.c new file mode 100644 index 0000000..573a691 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/recipd2.c @@ -0,0 +1,131 @@ +/* Test recipd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20040920095218EJL","EJL", "recipd2"); + + unsigned long long i6 = 0x7fd0000000000001ull; // 2^1022 + 1 ulp + unsigned long long i7 = 0xffd0000000000000ull; // -2^1022 + unsigned long long i7r = 0x8010000000000000ull; // -2^-1022 + unsigned long long i8 = 0x7606a4533cf5605eull; // random values + unsigned long long i8r = 0x09d69cea2b5b5b57ull; + unsigned long long i9 = 0x4c042c295376566eull; + unsigned long long i9r = 0x33d9618e87b961f4ull; + unsigned long long i10 = 0x39b3720562510408ull; + unsigned long long i10r = 0x462a54842d7f9b5dull; + unsigned long long i11 = 0x6911a64538a389aeull; + unsigned long long i11r = 0x16cd02637ed13ff2ull; + unsigned long long i12 = 0x1ac4d062d451c99dull; + unsigned long long i12r = 0x6518994c26ebbb3eull; + + double x0 = hide_double(-HUGE_VAL); // -Inf + double x1 = hide_double(HUGE_VAL); // Inf + double x2 = hide_double(0.0); // 0 + double x3 = hide_double(-0.0); // -0 + double x4 = hide_double(nan("")); // NaN + double x5 = hide_double(2.0); + double x5r = hide_double(0.5); + double x6 = hide_double(make_double(i6)); + double x7 = hide_double(make_double(i7)); + double x7r = hide_double(make_double(i7r)); + double x8 = hide_double(make_double(i8)); + double x8r = hide_double(make_double(i8r)); + double x9 = hide_double(make_double(i9)); + double x9r = hide_double(make_double(i9r)); + double x10 = hide_double(make_double(i10)); + double x10r = hide_double(make_double(i10r)); + double x11 = hide_double(make_double(i11)); + double x11r = hide_double(make_double(i11r)); + double x12 = hide_double(make_double(i12)); + double x12r = hide_double(make_double(i12r)); + + vec_double2 x0_v = spu_splats(x0); + vec_double2 x1_v = spu_splats(x1); + vec_double2 x2_v = spu_splats(x2); + vec_double2 x3_v = spu_splats(x3); + vec_double2 x4_v = spu_splats(x4); + vec_double2 x5_v = spu_splats(x5); + vec_double2 x5r_v = spu_splats(x5r); + vec_double2 x6_v = spu_splats(x6); + vec_double2 x7_v = spu_splats(x7); + vec_double2 x7r_v = spu_splats(x7r); + vec_double2 x8_v = spu_splats(x8); + vec_double2 x8r_v = spu_splats(x8r); + vec_double2 x9_v = spu_splats(x9); + vec_double2 x9r_v = spu_splats(x9r); + vec_double2 x10_v = spu_splats(x10); + vec_double2 x10r_v = spu_splats(x10r); + vec_double2 x11_v = spu_splats(x11); + vec_double2 x11r_v = spu_splats(x11r); + vec_double2 x12_v = spu_splats(x12); + vec_double2 x12r_v = spu_splats(x12r); + + vec_double2 res_v; + + TEST_START("recipd2"); + res_v = recipd2(x0_v); + TEST_CHECK("20040920095224EJL", allnegzero_double2( res_v ), 0); + res_v = recipd2(x1_v); + TEST_CHECK("20040920095226EJL", allposzero_double2( res_v ), 0); + res_v = recipd2(x2_v); + TEST_CHECK("20040920095228EJL", allposinf_double2( res_v ), 0); + res_v = recipd2(x3_v); + TEST_CHECK("20040920095233EJL", allneginf_double2( res_v ), 0); + res_v = recipd2(x4_v); + TEST_CHECK("20040920095235EJL", allnan_double2( res_v ), 0); + res_v = recipd2(x5_v); + TEST_CHECK("20040920095237EJL", allequal_double2( res_v, x5r_v ), 0); + res_v = recipd2(x6_v); + TEST_CHECK("20040920095239EJL", allzerodenorm_double2( res_v ), 0); + res_v = recipd2(x7_v); + TEST_CHECK("20040920095242EJL", allequal_double2( res_v, x7r_v ), 0); + res_v = recipd2(x8_v); + TEST_CHECK("20040920095245EJL", allequal_ulps_double2( res_v, x8r_v, 1 ), 0); + res_v = recipd2(x9_v); + TEST_CHECK("20040920095247EJL", allequal_ulps_double2( res_v, x9r_v, 1 ), 0); + res_v = recipd2(x10_v); + TEST_CHECK("20040920095248EJL", allequal_ulps_double2( res_v, x10r_v, 1 ), 0); + res_v = recipd2(x11_v); + TEST_CHECK("20040920095250EJL", allequal_ulps_double2( res_v, x11r_v, 1 ), 0); + res_v = recipd2(x12_v); + TEST_CHECK("20040920095252EJL", allequal_ulps_double2( res_v, x12r_v, 1 ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/recipf4.c b/Extras/simdmathlibrary/spu/tests/recipf4.c new file mode 100644 index 0000000..eb252c1 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/recipf4.c @@ -0,0 +1,114 @@ +/* Test recipf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20040920142553EJL","EJL", "recipf4"); + + unsigned int i0r = 0x7fffffff; + unsigned int i1 = 0xff000000; // -2^127 + unsigned int i2 = 0xfe7fffff; // -2^126 - 1 ulp + unsigned int i2r = 0x80800001; + unsigned int i3 = 0x75013340; // random values + unsigned int i3r = 0x09fd9f35; + unsigned int i4 = 0x75e7753f; + unsigned int i4r = 0x090d9277; + unsigned int i5 = 0x4c7fed5a; + unsigned int i5r = 0x32800954; + unsigned int i6 = 0x3a0731f0; + unsigned int i6r = 0x44f2602e; + unsigned int i7 = 0x69784a07; + unsigned int i7r = 0x1583f9a3; + + float x0 = hide_float(0.0f); + float x0r = hide_float(make_float(i0r)); + float x1 = hide_float(make_float(i1)); + float x1r = hide_float(0.0f); + float x2 = hide_float(make_float(i2)); + float x2r = hide_float(make_float(i2r)); + float x3 = hide_float(make_float(i3)); + float x3r = hide_float(make_float(i3r)); + float x4 = hide_float(make_float(i4)); + float x4r = hide_float(make_float(i4r)); + float x5 = hide_float(make_float(i5)); + float x5r = hide_float(make_float(i5r)); + float x6 = hide_float(make_float(i6)); + float x6r = hide_float(make_float(i6r)); + float x7 = hide_float(make_float(i7)); + float x7r = hide_float(make_float(i7r)); + + vec_float4 x0_v = spu_splats(x0); + vec_float4 x0r_v = spu_splats(x0r); + vec_float4 x1_v = spu_splats(x1); + vec_float4 x1r_v = spu_splats(x1r); + vec_float4 x2_v = spu_splats(x2); + vec_float4 x2r_v = spu_splats(x2r); + vec_float4 x3_v = spu_splats(x3); + vec_float4 x3r_v = spu_splats(x3r); + vec_float4 x4_v = spu_splats(x4); + vec_float4 x4r_v = spu_splats(x4r); + vec_float4 x5_v = spu_splats(x5); + vec_float4 x5r_v = spu_splats(x5r); + vec_float4 x6_v = spu_splats(x6); + vec_float4 x6r_v = spu_splats(x6r); + vec_float4 x7_v = spu_splats(x7); + vec_float4 x7r_v = spu_splats(x7r); + + vec_float4 res_v; + + TEST_START("recipf4"); + res_v = recipf4(x0_v); + TEST_CHECK("20040920142558EJL", allequal_float4( res_v, x0r_v ), 0); + res_v = recipf4(x1_v); + TEST_CHECK("20040920142600EJL", allequal_float4( res_v, x1r_v), 0); + res_v = recipf4(x2_v); + TEST_CHECK("20040920142602EJL", allequal_ulps_float4( res_v, x2r_v, 2 ), 0); + res_v = recipf4(x3_v); + TEST_CHECK("20040920142604EJL", allequal_ulps_float4( res_v, x3r_v, 2 ), 0); + res_v = recipf4(x4_v); + TEST_CHECK("20040920142606EJL", allequal_ulps_float4( res_v, x4r_v, 2 ), 0); + res_v = recipf4(x5_v); + TEST_CHECK("20040920142608EJL", allequal_ulps_float4( res_v, x5r_v, 2 ), 0); + res_v = recipf4(x6_v); + TEST_CHECK("20040920142609EJL", allequal_ulps_float4( res_v, x6r_v, 2 ), 0); + res_v = recipf4(x7_v); + TEST_CHECK("20040920142611EJL", allequal_ulps_float4( res_v, x7r_v, 2 ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/remainderd2.c b/Extras/simdmathlibrary/spu/tests/remainderd2.c new file mode 100644 index 0000000..8100c9e --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/remainderd2.c @@ -0,0 +1,125 @@ +/* Test remainderd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +typedef struct { + unsigned long long int xxx[2]; + unsigned long long int yyy[2]; + unsigned long long int a_res[2]; +} TestVec64_RemqD; + +int main() +{ + TestVec64_RemqD test_a[] = { + { + // normal 2.5/1.5 29/3 + {0x4004000000000000ULL,0x403d000000000000ULL}, + {0x3ff8000000000000ULL,0x4008000000000000ULL}, + {0xbfe0000000000000ULL,0xbff0000000000000ULL} + },{ + // normal + {0x09d0000000000006ULL,0x1000000000000000ULL}, + {0x8010000000000005ULL,0x0010000000000007ULL}, + {0x800000000000007dULL,0x80037ffffffff1a5ULL} + },{ + // denorm + {0x0000000000000001ULL,0x800ffffffffffff3ULL}, + {0x8000000000000001ULL,0x8000000000000005ULL}, + {0x0000000000000000ULL,0x0000000000000002ULL} + },{ + // divide by inf + {0xFFEFFFFFFFFFFFFFULL,0x0001000000000000ULL}, + {0x7FF0000000000000ULL,0x7FF0000000000000ULL}, + {0xFFEFFFFFFFFFFFFFULL,0x0001000000000000ULL} + },{ + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL} + + } + }; + TestVec64_RemqD test_b[] = { + { + // divide by zero -> nan + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x7ff8000000000000ULL,0x7ff8000000000000ULL} + },{ + // Inf , -Inf + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7ff8000000000000ULL,0x7ff8000000000000ULL} + },{ + // border + {0xFFE0000000000000ULL,0x7FEFFFFFFFFFFFFFULL}, + {0x0008000000000000ULL,0x0010000000000000ULL}, + {0x8000000000000000ULL,0x0000000000000000ULL} + },{ + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL} + + } + }; + int ii, test_ctr = 1; + char msg[80]; + vec_double2 res_v; + + TEST_SET_START("20060919210000NM","NM", "remquod2"); + + TEST_START("remquod2"); + + for (ii=0; ; ii++) { + if ( (test_a[ii].xxx[0] == 0) && (test_a[ii].xxx[1] == 0) ) break; + + // set Floating point round mode + res_v = remainderd2 (*((vec_double2 *)&test_a[ii].xxx[0]), *((vec_double2 *)&test_a[ii].yyy[0])); + sprintf(msg,"2006092621%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].a_res[0])), 0); + } + for (ii=0; ; ii++) { + if ( (test_b[ii].xxx[0] == 0) && (test_b[ii].xxx[1] == 0) ) break; + + // set Floating point round mode + res_v = remainderd2 (*((vec_double2 *)&test_b[ii].xxx[0]), *((vec_double2 *)&test_b[ii].yyy[0])); + sprintf(msg,"2006092623%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_b[ii].a_res[0])), 0); + } + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/remainderf4.c b/Extras/simdmathlibrary/spu/tests/remainderf4.c new file mode 100644 index 0000000..7f09e0d --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/remainderf4.c @@ -0,0 +1,143 @@ +/* Test remainderf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20040928191927EJL","EJL", "remainderf4"); + + unsigned int i0n = 0x449edbc6; + unsigned int i0d = 0x40cf799d; + unsigned int i0r = 0x3daa7300; + unsigned int i1n = 0x6bca107a; + unsigned int i1d = 0x6c4a107a; + unsigned int i1r = 0x6bca107a; + unsigned int i2n = 0x1c123605; + unsigned int i2d = 0x1c923602; + unsigned int i2r = 0x9c1235ff; + unsigned int i3n = 0x2b4c50fa; + unsigned int i3d = 0x253a3ae3; + unsigned int i3r = 0xa41873a8; + unsigned int i4n = 0x73addffc; + unsigned int i4d = 0x742ddffc; + unsigned int i4r = 0x73addffc; + unsigned int i5n = 0x29d4d97c; + unsigned int i5d = 0x2a546e77; + unsigned int i5r = 0xa9d40372; + + float x0n = hide_float(make_float(i0n)); + float x0d = hide_float(make_float(i0d)); + float x0r = hide_float(make_float(i0r)); + + float x1n = hide_float(make_float(i1n)); + float x1d = hide_float(make_float(i1d)); + float x1r = hide_float(make_float(i1r)); + + float x2n = hide_float(make_float(i2n)); + float x2d = hide_float(make_float(i2d)); + float x2r = hide_float(make_float(i2r)); + + float x3n = hide_float(make_float(i3n)); + float x3d = hide_float(make_float(i3d)); + float x3r = hide_float(make_float(i3r)); + + float x4n = hide_float(make_float(i4n)); + float x4d = hide_float(make_float(i4d)); + float x4r = hide_float(make_float(i4r)); + + float x5n = hide_float(make_float(i5n)); + float x5d = hide_float(make_float(i5d)); + float x5r = hide_float(make_float(i5r)); + + vec_float4 x0n_v = spu_splats(x0n); + vec_float4 x0d_v = spu_splats(x0d); + vec_float4 x0r_v = spu_splats(x0r); + + vec_float4 x1n_v = spu_splats(x1n); + vec_float4 x1d_v = spu_splats(x1d); + vec_float4 x1r_v = spu_splats(x1r); + + vec_float4 x2n_v = spu_splats(x2n); + vec_float4 x2d_v = spu_splats(x2d); + vec_float4 x2r_v = spu_splats(x2r); + + vec_float4 x3n_v = spu_splats(x3n); + vec_float4 x3d_v = spu_splats(x3d); + vec_float4 x3r_v = spu_splats(x3r); + + vec_float4 x4n_v = spu_splats(x4n); + vec_float4 x4d_v = spu_splats(x4d); + vec_float4 x4r_v = spu_splats(x4r); + + vec_float4 x5n_v = spu_splats(x5n); + vec_float4 x5d_v = spu_splats(x5d); + vec_float4 x5r_v = spu_splats(x5r); + + float res; + vec_float4 res_v; + + TEST_START("remainderf4"); + res_v = remainderf4(x0n_v, x0d_v); + TEST_CHECK("20040928191931EJL", allequal_ulps_float4( res_v, x0r_v, 1 ), 0); + res_v = remainderf4(x1n_v, x1d_v); + TEST_CHECK("20040928191933EJL", allequal_ulps_float4( res_v, x1r_v, 1 ), 0); + res_v = remainderf4(x2n_v, x2d_v); + TEST_CHECK("20040928191934EJL", allequal_ulps_float4( res_v, x2r_v, 1 ), 0); + res_v = remainderf4(x3n_v, x3d_v); + TEST_CHECK("20040928191936EJL", allequal_ulps_float4( res_v, x3r_v, 1 ), 0); + res_v = remainderf4(x4n_v, x4d_v); + TEST_CHECK("20040928191937EJL", allequal_ulps_float4( res_v, x4r_v, 1 ), 0); + res_v = remainderf4(x5n_v, x5d_v); + TEST_CHECK("20040928191938EJL", allequal_ulps_float4( res_v, x5r_v, 1 ), 0); + + TEST_START("remainderf"); + res = remainderf(x0n, x0d); + TEST_CHECK("20040928191941EJL", ulpDiff_f( res, x0r ) <= 1, 0); + res = remainderf(x1n, x1d); + TEST_CHECK("20040928191942EJL", ulpDiff_f( res, x1r ) <= 1, 0); + res = remainderf(x2n, x2d); + TEST_CHECK("20040928191943EJL", ulpDiff_f( res, x2r ) <= 1, 0); + res = remainderf(x3n, x3d); + TEST_CHECK("20040928191948EJL", ulpDiff_f( res, x3r ) <= 1, 0); + res = remainderf(x4n, x4d); + TEST_CHECK("20040928191949EJL", ulpDiff_f( res, x4r ) <= 1, 0); + res = remainderf(x5n, x5d); + TEST_CHECK("20040928191950EJL", ulpDiff_f( res, x5r ) <= 1, 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/remquod2.c b/Extras/simdmathlibrary/spu/tests/remquod2.c new file mode 100644 index 0000000..4060ed0 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/remquod2.c @@ -0,0 +1,151 @@ +/* Test remquod2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ + +/* + * note: cannot calc too far numbers correctry + * ex. x=0xFFE0000000000000,y=0x0008000000000000 + */ + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +typedef struct { + unsigned long long int xxx[2]; + unsigned long long int yyy[2]; + unsigned long long int quo[2]; + unsigned long long int a_res[2]; + unsigned long long int a_quo[2]; +} TestVec64_RemqD; + +int main() +{ + TestVec64_RemqD test_a[] = { + { + // normal 2.5/1.5 29/3 + {0x4004000000000000ULL,0x403d000000000000ULL}, + {0x3ff8000000000000ULL,0x4008000000000000ULL}, + {0x0000000000000000ULL,0x0000000000000000ULL}, + {0xbfe0000000000000ULL,0xbff0000000000000ULL}, + {0x0000000000000002ULL,0x0000000000000002ULL} + },{ + // normal + {0x09d0000000000006ULL,0x1000000000000000ULL}, + {0x8010000000000005ULL,0x0010000000000007ULL}, + {0x0000000000000000ULL,0x0000000000000000ULL}, + {0x800000000000007dULL,0x80037ffffffff1a5ULL}, + {0xFFFFFFFFFFFFFFFFULL,0x0000000000000003ULL} + },{ + // denorm + {0x0000000000000001ULL,0x800ffffffffffff3ULL}, + {0x8000000000000001ULL,0x8000000000000005ULL}, + {0x0000000000000000ULL,0x0000000000000000ULL}, + {0x0000000000000000ULL,0x0000000000000002ULL}, + {0xFFFFFFFFFFFFFFFFULL,0x0000000000000001ULL} + },{ + // divide by inf + {0xFFEFFFFFFFFFFFFFULL,0x0001000000000000ULL}, + {0x7FF0000000000000ULL,0x7FF0000000000000ULL}, + {0x0000000000000000ULL,0x0000000000000000ULL}, + {0xFFEFFFFFFFFFFFFFULL,0x0001000000000000ULL}, + {0x0000000000000000ULL,0x0000000000000000ULL} + },{ + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL} + + } + }; + TestVec64_RemqD test_b[] = { + { + // divide by zero -> nan + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x0000000000000000ULL}, + {0x7ff8000000000000ULL,0x7ff8000000000000ULL}, + {0x0000000000000000ULL,0x0000000000000000ULL} + },{ + // Inf , -Inf + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x0000000000000000ULL,0x0000000000000000ULL}, + {0x7ff8000000000000ULL,0x7ff8000000000000ULL}, + {0x0000000000000000ULL,0x0000000000000000ULL} + },{ + // border + {0xFFE0000000000000ULL,0x7FEFFFFFFFFFFFFFULL}, + {0x0008000000000000ULL,0x0010000000000000ULL}, + {0x0000000000000000ULL,0x0000000000000000ULL}, + {0x8000000000000000ULL,0x0000000000000000ULL}, + {0x0000000000000000ULL,0x0000000000000000ULL} + },{ + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL} + + } + }; + int ii, test_ctr = 1; + char msg[80]; + vec_double2 res_v; + + TEST_SET_START("20060919210000NM","NM", "remquod2"); + + TEST_START("remquod2"); + + for (ii=0; ; ii++) { + if ( (test_a[ii].xxx[0] == 0) && (test_a[ii].xxx[1] == 0) ) break; + + // set Floating point round mode + res_v = remquod2 (*((vec_double2 *)&test_a[ii].xxx[0]), *((vec_double2 *)&test_a[ii].yyy[0]), ((vec_llong2 *)&test_a[ii].quo[0])); + sprintf(msg,"2006091921%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].a_res[0])), 0); + sprintf(msg,"2006091922%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( *((vec_llong2 *)&test_a[ii].quo[0]), *((vec_llong2 *)&test_a[ii].a_quo[0])), 0); + } + for (ii=0; ; ii++) { + if ( (test_b[ii].xxx[0] == 0) && (test_b[ii].xxx[1] == 0) ) break; + + // set Floating point round mode + res_v = remquod2 (*((vec_double2 *)&test_b[ii].xxx[0]), *((vec_double2 *)&test_b[ii].yyy[0]), ((vec_llong2 *)&test_b[ii].quo[0])); + sprintf(msg,"2006091923%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_b[ii].a_res[0])), 0); + } + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/remquof4.c b/Extras/simdmathlibrary/spu/tests/remquof4.c new file mode 100644 index 0000000..c350efd --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/remquof4.c @@ -0,0 +1,145 @@ +/* Test remquof4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ + +/* + * copied test data from remainderf4 + * wrong quotient returns in scalar function + */ + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060912170027NM","NM", "remquof4"); + + unsigned int i0n = 0x449edbc6; + unsigned int i0d = 0x40cf799d; + unsigned int i0r = 0x3daa7300; + unsigned int i0q = 4; + unsigned int i1n = 0x6bca107a; + unsigned int i1d = 0x6c4a107a; + unsigned int i1r = 0x6bca107a; + unsigned int i1q = 0; + unsigned int i2n = 0x1c123605; + unsigned int i2d = 0x1c923602; + unsigned int i2r = 0x9c1235ff; + unsigned int i2q = 1; + unsigned int i3n = 0x2b4c50fa; + unsigned int i3d = 0x253a3ae3; + unsigned int i3r = 0xa41873a8; + unsigned int i3q = 6; + unsigned int i4n = 0x73addffc; + unsigned int i4d = 0x742ddffc; + unsigned int i4r = 0x73addffc; + unsigned int i4q = 0; + unsigned int i5n = 0x29d4d97c; + unsigned int i5d = 0x2a546e77; + unsigned int i5r = 0xa9d40372; + unsigned int i5q = 1; + + float x0n = hide_float(make_float(i0n)); + float x0d = hide_float(make_float(i0d)); + float x0r = hide_float(make_float(i0r)); + + float x1n = hide_float(make_float(i1n)); + float x1d = hide_float(make_float(i1d)); + float x1r = hide_float(make_float(i1r)); + + float x2n = hide_float(make_float(i2n)); + float x2d = hide_float(make_float(i2d)); + float x2r = hide_float(make_float(i2r)); + + float x3n = hide_float(make_float(i3n)); + float x3d = hide_float(make_float(i3d)); + float x3r = hide_float(make_float(i3r)); + + float x4n = hide_float(make_float(i4n)); + float x4d = hide_float(make_float(i4d)); + float x4r = hide_float(make_float(i4r)); + + float x5n = hide_float(make_float(i5n)); + float x5d = hide_float(make_float(i5d)); + float x5r = hide_float(make_float(i5r)); + + vec_float4 x0n_v = spu_splats(x0n); + vec_float4 x0d_v = spu_splats(x0d); + vec_float4 x0r_v = spu_splats(x0r); + + vec_float4 x1n_v = spu_splats(x1n); + vec_float4 x1d_v = spu_splats(x1d); + vec_float4 x1r_v = spu_splats(x1r); + + vec_float4 x2n_v = spu_splats(x2n); + vec_float4 x2d_v = spu_splats(x2d); + vec_float4 x2r_v = spu_splats(x2r); + + vec_float4 x3n_v = spu_splats(x3n); + vec_float4 x3d_v = spu_splats(x3d); + vec_float4 x3r_v = spu_splats(x3r); + + vec_float4 x4n_v = spu_splats(x4n); + vec_float4 x4d_v = spu_splats(x4d); + vec_float4 x4r_v = spu_splats(x4r); + + vec_float4 x5n_v = spu_splats(x5n); + vec_float4 x5d_v = spu_splats(x5d); + vec_float4 x5r_v = spu_splats(x5r); + + vec_float4 res_v; + vec_int4 quo_v; + + TEST_START("remquof4"); + res_v = remquof4(x0n_v, x0d_v, &quo_v); + TEST_CHECK("20060912170031NM", allequal_ulps_float4( res_v, x0r_v, 1 ), 0); + TEST_CHECK("20060912170131NM", allequal_int4( quo_v, spu_splats((int)i0q) ), 0); + res_v = remquof4(x1n_v, x1d_v, &quo_v); + TEST_CHECK("20060912170033NM", allequal_ulps_float4( res_v, x1r_v, 1 ), 0); + TEST_CHECK("20060912170133NM", allequal_int4( quo_v, spu_splats((int)i1q) ), 0); + res_v = remquof4(x2n_v, x2d_v, &quo_v); + TEST_CHECK("20060912170034NM", allequal_ulps_float4( res_v, x2r_v, 1 ), 0); + TEST_CHECK("20060912170134NM", allequal_int4( quo_v, spu_splats((int)i2q) ), 0); + res_v = remquof4(x3n_v, x3d_v, &quo_v); + TEST_CHECK("20060912170036NM", allequal_ulps_float4( res_v, x3r_v, 1 ), 0); + TEST_CHECK("20060912170136NM", allequal_int4( quo_v, spu_splats((int)i3q) ), 0); + res_v = remquof4(x4n_v, x4d_v, &quo_v); + TEST_CHECK("20060912170037NM", allequal_ulps_float4( res_v, x4r_v, 1 ), 0); + TEST_CHECK("20060912170137NM", allequal_int4( quo_v, spu_splats((int)i4q) ), 0); + res_v = remquof4(x5n_v, x5d_v, &quo_v); + TEST_CHECK("20060912170038NM", allequal_ulps_float4( res_v, x5r_v, 1 ), 0); + TEST_CHECK("20060912170138NM", allequal_int4( quo_v, spu_splats((int)i5q) ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/rintd2.c b/Extras/simdmathlibrary/spu/tests/rintd2.c new file mode 100644 index 0000000..7eeb40b --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/rintd2.c @@ -0,0 +1,180 @@ +/* Test rintd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/** + * + *@@ rintd2 - Round the input to the nearest integer according to + * the current rounding mode. + * + *@brief + * boundary test for rintd2. + * + * + *@pre + * + *@criteria + * Run this program and check no error will be occurred. + * + *@note + * add Denormalized handling + * changed over 0x4330000000000000(ABS) handling + * + * + **/ + +#include +#include +#include +//#include +#include + +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +typedef struct { + unsigned long long int xxx[2]; + unsigned long long int ans0[2]; + unsigned long long int ans1[2]; + unsigned long long int ans2[2]; + unsigned long long int ans3[2]; +} TestVec64_NerI; + +int main() +{ + TestVec64_NerI test_a[] = { + { + // zero + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL} + },{ + // border + {0xc330000000000000ULL,0x4330000000000000ULL}, + {0xc330000000000000ULL,0x4330000000000000ULL}, + {0xc330000000000000ULL,0x4330000000000000ULL}, + {0xc330000000000000ULL,0x4330000000000000ULL}, + {0xc330000000000000ULL,0x4330000000000000ULL} + },{ + // MIN , MAX + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL} + },{ + // Inf , -Inf + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL} + },{ + // denotmalized + {0x8000000000000001ULL,0x0000000000000001ULL}, + {0x8000000000000000ULL,0x0000000000000000ULL}, + {0x8000000000000000ULL,0x0000000000000000ULL}, + {0x8000000000000000ULL,0x3ff0000000000000ULL}, + {0xbff0000000000000ULL,0x0000000000000000ULL} + },{ + // denotmalized + {0x0008000000000000ULL,0x8008000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x3ff0000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0xbff0000000000000ULL} + },{ + // 1.0 + {0x3ff0000000000000ULL,0xbff0000000000000ULL}, + {0x3ff0000000000000ULL,0xbff0000000000000ULL}, + {0x3ff0000000000000ULL,0xbff0000000000000ULL}, + {0x3ff0000000000000ULL,0xbff0000000000000ULL}, + {0x3ff0000000000000ULL,0xbff0000000000000ULL} + },{ + // 1.5 + {0x3ff8000000000000ULL,0xbff8000000000000ULL}, + {0x4000000000000000ULL,0xc000000000000000ULL}, + {0x3ff0000000000000ULL,0xbff0000000000000ULL}, + {0x4000000000000000ULL,0xbff0000000000000ULL}, + {0x3ff0000000000000ULL,0xc000000000000000ULL} + },{ + // 2.5 + {0x4004000000000000ULL,0xc004000000000000ULL}, + {0x4000000000000000ULL,0xc000000000000000ULL}, + {0x4000000000000000ULL,0xc000000000000000ULL}, + {0x4008000000000000ULL,0xc000000000000000ULL}, + {0x4000000000000000ULL,0xc008000000000000ULL} + },{ + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL} + + } + }; + int ii, test_ctr = 1; + char msg[80]; + vec_double2 res_v; + + TEST_SET_START("20060831210000NM","NM", "rintd2"); + + TEST_START("rintd2"); + + for (ii=0; ; ii++) { + if ( (test_a[ii].xxx[0] == 0) && (test_a[ii].xxx[1] == 0) ) break; + + // set Floating point round mode + spu_mtfpscr(((vec_uint4){0x0000,0,0,0})); + res_v = rintd2 (*((vec_double2 *)&test_a[ii].xxx[0])); + sprintf(msg,"2006083121%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans0[0])), 0); + + spu_mtfpscr(((vec_uint4){0x0500,0,0,0})); + res_v = rintd2 (*((vec_double2 *)&test_a[ii].xxx[0])); + sprintf(msg,"2006083121%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans1[0])), 0); + + spu_mtfpscr(((vec_uint4){0x0a00,0,0,0})); + res_v = rintd2 (*((vec_double2 *)&test_a[ii].xxx[0])); + sprintf(msg,"2006083121%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans2[0])), 0); + + spu_mtfpscr(((vec_uint4){0x0f00,0,0,0})); + res_v = rintd2 (*((vec_double2 *)&test_a[ii].xxx[0])); + sprintf(msg,"2006083121%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans3[0])), 0); + } + + TEST_SET_DONE(); + + TEST_EXIT(); + +} diff --git a/Extras/simdmathlibrary/spu/tests/rintf4.c b/Extras/simdmathlibrary/spu/tests/rintf4.c new file mode 100644 index 0000000..c845240 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/rintf4.c @@ -0,0 +1,94 @@ +/* Test rintf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +#define DEFINE_DATA(var,a,b) \ + float var = hide_float(a); \ + float var ## _out = hide_float(b); \ + vec_float4 var ## _v = spu_splats(var); \ + vec_float4 var ## _out_v = spu_splats(var ## _out); + +/* + */ +#define DEFINE_DATA_UNSIGNED(var,a,b)\ + unsigned int var ## _ina = a ; \ + unsigned int var ## _inb = b ; \ + float var = make_float(var ## _ina); \ + float var ## _out = make_float(var ## _inb); \ + vec_float4 var ## _v = spu_splats(var); \ + vec_float4 var ## _out_v = spu_splats(var ## _out); + +#define DO_TEST(var,id) \ + res_v = rintf4(var ## _v); \ + TEST_CHECK(" #id ", allequal_float4( res_v, var ## _out_v ), 0); + + +int main() +{ + vec_float4 res_v; + + TEST_SET_START("184604792300","RNT", "rintf4"); + + + + + //s=0, e=100, f=7fffff --> s=0, e=100, f=7fffff + DEFINE_DATA_UNSIGNED(x1,0x71ffffff,0x71ffffff) + //s=0, e=22, f=0x7fffff --> s=0,e=22,f=0x7ffffe + DEFINE_DATA_UNSIGNED(x2, 0x4affffff,0x4afffffe) + //s=0, e=23, f=0 --> s=0,e=23,f=0 + DEFINE_DATA_UNSIGNED(x3, 0x4b000000,0x4b000000) + //s=0, e=-126, f=0 --> 0 + DEFINE_DATA_UNSIGNED(x4, 0x800000,0x0) + DEFINE_DATA(x5, 1.001f, 1.f) + DEFINE_DATA(x6, -.05f, 0.f) + DEFINE_DATA(x7, 0.9999f, 0.f) + DEFINE_DATA(x8, 0.4999f, 0.f) + + TEST_START("rintf4"); + DO_TEST(x1,184604792301RNT) + DO_TEST(x2,184604792302RNT) + DO_TEST(x3,184604792303RNT) + DO_TEST(x4,184604792304RNT) + DO_TEST(x5,184604792305RNT) + DO_TEST(x6,184604792306RNT) + DO_TEST(x7,184604792307RNT) + DO_TEST(x8,184604792308RNT) + TEST_SET_DONE(); + + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/roundd2.c b/Extras/simdmathlibrary/spu/tests/roundd2.c new file mode 100644 index 0000000..bdb780f --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/roundd2.c @@ -0,0 +1,151 @@ +/* Test roundd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/** + * + *@@ roundd2 - Round the input to the nearest integer. + * + *@brief + * boundary test for nextafterd2. + * + * + *@pre + * + *@criteria + * Run this program and check no error will be occurred. + * + *@note + * + * + **/ + + +#include +#include +#include +//#include +#include + +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +typedef union { + struct { + double xxx[2]; + double ans[2]; + } dbl; + struct { + unsigned long long xxx[2]; + unsigned long long ans[2]; + } ull; +} TestVec_Roundd2; + +int main() +{ + TestVec_Roundd2 test_a[] = { + { + ull:{ + // 0 -> 0 , -0 -> -0 + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL} + } + },{ + ull:{ + // -Inf -> -Inf , Inf -> Inf + {0xFFF0000000000000ULL,0x7FF0000000000000ULL}, + {0xFFF0000000000000ULL,0x7FF0000000000000ULL} + } + },{ + ull:{ + // MAX -> MAX , MIN -> MIN + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL} + } + },{ + ull:{ + // Denormalize -> 0 + {0x0000000000000001ULL,0x8000000000000010ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL} + } + },{ + ull:{ + // Denormalize -> 0 + {0x800FFFFFFFFFFFFFULL,0x000FFFFFFFFFFFFFULL}, + {0x8000000000000000ULL,0x0000000000000000ULL} + } + },{ + ull:{ + // border + {0x4320000000000001ULL,0xC320000000000001ULL}, + {0x4320000000000002ULL,0xC320000000000002ULL} + } + },{ + dbl:{ + {1.0, -1.0}, + {1.0, -1.0} + } + },{ + dbl:{ + {-2.5, 3.5}, + {-3.0, 4.0} + } + },{ + ull:{ + // Nan + {0xFFF0000000000001ULL,0x7FF0000000000001ULL}, + {0xFFF0000000000001ULL,0x7FF0000000000001ULL} + } + },{ + ull:{ + {0ULL,0ULL}, + {0ULL,0ULL} + } + } + }; + int ii, test_ctr = 1; + char msg[80]; + vec_double2 res_v; + + TEST_SET_START("20060831200000NM","NM", "roundd2"); + + TEST_START("roundd2"); + + for (ii=0; ; ii++) { + if ( (test_a[ii].ull.xxx[0] == 0) && (test_a[ii].ull.xxx[1] == 0) ) break; + + res_v = roundd2 (*((vec_double2 *)&test_a[ii].dbl.xxx[0]) ); + sprintf(msg,"2006083120%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, (vec_llong2)*((vec_double2 *)&test_a[ii].dbl.ans[0])), 0); + } + + TEST_SET_DONE(); + + TEST_EXIT(); + +} diff --git a/Extras/simdmathlibrary/spu/tests/roundf4.c b/Extras/simdmathlibrary/spu/tests/roundf4.c new file mode 100644 index 0000000..9bbbcbc --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/roundf4.c @@ -0,0 +1,100 @@ +/* Test roundf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +// a: float b:float +#define DEFINE_DATA(var,a,b) \ + float var = hide_float(a); \ + float var ## _out = hide_float(b); \ + vec_float4 var ## _v = spu_splats(var); \ + vec_float4 var ## _out_v = spu_splats(var ## _out); + +// a: bit pattern b: bit pattern +#define DEFINE_DATA_UNSIGNED(var,a,b) \ + unsigned int var ## _ina = a ; \ + unsigned int var ## _inb = b ; \ + float var = make_float (var ## _ina); \ + float var ## _out = make_float(var ## _inb); \ + vec_float4 var ## _v = spu_splats(var); \ + vec_float4 var ## _out_v = spu_splats(var ## _out); + +#define DO_TEST(var,id) \ + res_v = roundf4(var ## _v); \ + TEST_CHECK(" #id ", allequal_float4( res_v, var ## _out_v ), 0); + + +int main() +{ + vec_float4 res_v; + + TEST_SET_START("164260798500","RUD", "roundf4"); + + + + //s=0 + DEFINE_DATA(x1, 1.0, 1.0f) + DEFINE_DATA(x2, -1.0,-1.0f) + //s=-1 + DEFINE_DATA(x3, 0.5, 1.0f) + DEFINE_DATA(x4, -0.5, -1.0f) + //s=-2 + DEFINE_DATA(x5, 0.25, 0.0f) + //s=-3 + DEFINE_DATA(x6, 0.125, 0.0f) + //s=0, e=128, f=7fffff --> s=0, e=128, f=7fffff + DEFINE_DATA_UNSIGNED(x7,0x7fffffff,0x7fffffff) + //s=0, e=-126, f=0 --> 0 + DEFINE_DATA_UNSIGNED(x8, 0x800000,0x0) + DEFINE_DATA(x9, 0.4999, 0.f) + DEFINE_DATA(x10, 0.9999, 1.f) + + //TEST + TEST_START("roundf4"); + DO_TEST(x1,164260798501RUD) + DO_TEST(x2,164260798502RUD) + DO_TEST(x3,164260798503RUD) + DO_TEST(x4,164260798504RUD) + DO_TEST(x5,164260798505RUD) + DO_TEST(x6,164260798506RUD) + DO_TEST(x7,164260798507RUD) + DO_TEST(x8,164260798508RUD) + DO_TEST(x9,164260798509RUD) + DO_TEST(x10,164260798510RUD) + TEST_SET_DONE(); + + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/rsqrtd2.c b/Extras/simdmathlibrary/spu/tests/rsqrtd2.c new file mode 100644 index 0000000..52247a3 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/rsqrtd2.c @@ -0,0 +1,126 @@ +/* Test rsqrtd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20040928174038EJL","EJL", "rsqrtd2"); + + unsigned long long i6 = 0x7464fff515d76f87ull; + unsigned long long i6r = 0x25b3c03b72dba06cull; + unsigned long long i7 = 0x7606a4533cf5605eull; + unsigned long long i7r = 0x24e3056f4b45f6a9ull; + unsigned long long i8 = 0x4beae58c6f48733eull; + unsigned long long i8r = 0x39f173b787396c5full; + unsigned long long i9 = 0x3999ed5c8316b00bull; + unsigned long long i9r = 0x43192359a70ec761ull; + unsigned long long i10 = 0x68f7885c4b84b793ull; + unsigned long long i10r = 0x2b6a62d48c269d90ull; + unsigned long long i11 = 0x1aabc083c5c26227ull; + unsigned long long i11r = 0x52912e543817fabbull; + + double x0 = hide_double(-HUGE_VAL); // -Inf -> NaN + double x1 = hide_double(HUGE_VAL); // Inf -> +0 + double x2 = hide_double(0.0); // +0 -> Inf + double x3 = hide_double(-0.0); // -0 -> -Inf + double x4 = hide_double(nan("")); // NaN -> NaN + double x5 = hide_double(4.0); + double x5r = hide_double(0.5); + double x6 = hide_double(make_double(i6)); + double x6r = hide_double(make_double(i6r)); + double x7 = hide_double(make_double(i7)); + double x7r = hide_double(make_double(i7r)); + double x8 = hide_double(make_double(i8)); + double x8r = hide_double(make_double(i8r)); + double x9 = hide_double(make_double(i9)); + double x9r = hide_double(make_double(i9r)); + double x10 = hide_double(make_double(i10)); + double x10r = hide_double(make_double(i10r)); + double x11 = hide_double(make_double(i11)); + double x11r = hide_double(make_double(i11r)); + + vec_double2 x0_v = spu_splats(x0); + vec_double2 x1_v = spu_splats(x1); + vec_double2 x2_v = spu_splats(x2); + vec_double2 x3_v = spu_splats(x3); + vec_double2 x4_v = spu_splats(x4); + vec_double2 x5_v = spu_splats(x5); + vec_double2 x5r_v = spu_splats(x5r); + vec_double2 x6_v = spu_splats(x6); + vec_double2 x6r_v = spu_splats(x6r); + vec_double2 x7_v = spu_splats(x7); + vec_double2 x7r_v = spu_splats(x7r); + vec_double2 x8_v = spu_splats(x8); + vec_double2 x8r_v = spu_splats(x8r); + vec_double2 x9_v = spu_splats(x9); + vec_double2 x9r_v = spu_splats(x9r); + vec_double2 x10_v = spu_splats(x10); + vec_double2 x10r_v = spu_splats(x10r); + vec_double2 x11_v = spu_splats(x11); + vec_double2 x11r_v = spu_splats(x11r); + + vec_double2 res_v; + + TEST_START("rsqrtd2"); + res_v = rsqrtd2(x0_v); + TEST_CHECK("20040928174042EJL", allnan_double2( res_v ), 0); + res_v = rsqrtd2(x1_v); + TEST_CHECK("20040928174045EJL", allposzero_double2( res_v ), 0); + res_v = rsqrtd2(x2_v); + TEST_CHECK("20040928174047EJL", allposinf_double2( res_v ), 0); + res_v = rsqrtd2(x3_v); + TEST_CHECK("20040928174049EJL", allneginf_double2( res_v ), 0); + res_v = rsqrtd2(x4_v); + TEST_CHECK("20040928174054EJL", allnan_double2( res_v ), 0); + res_v = rsqrtd2(x5_v); + TEST_CHECK("20040928174058EJL", allequal_double2( res_v, x5r_v ), 0); + res_v = rsqrtd2(x6_v); + TEST_CHECK("20040928174101EJL", allequal_ulps_double2( res_v, x6r_v, 1 ), 0); + res_v = rsqrtd2(x7_v); + TEST_CHECK("20040928174104EJL", allequal_ulps_double2( res_v, x7r_v, 1 ), 0); + res_v = rsqrtd2(x8_v); + TEST_CHECK("20040928174106EJL", allequal_ulps_double2( res_v, x8r_v, 1 ), 0); + res_v = rsqrtd2(x9_v); + TEST_CHECK("20040928174108EJL", allequal_ulps_double2( res_v, x9r_v, 1 ), 0); + res_v = rsqrtd2(x10_v); + TEST_CHECK("20040928174110EJL", allequal_ulps_double2( res_v, x10r_v, 1 ), 0); + res_v = rsqrtd2(x11_v); + TEST_CHECK("20040928174113EJL", allequal_ulps_double2( res_v, x11r_v, 1 ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/rsqrtf4.c b/Extras/simdmathlibrary/spu/tests/rsqrtf4.c new file mode 100644 index 0000000..898ad5b --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/rsqrtf4.c @@ -0,0 +1,93 @@ +/* Test rsqrtf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + + +int main() +{ + TEST_SET_START("20040928182349EJL","EJL", "rsqrtf4"); + + unsigned int i3 = 0x742c4455; + unsigned int i3r = 0x251c099a; + unsigned int i4 = 0x75e7753f; + unsigned int i4r = 0x243e5fe2; + unsigned int i5 = 0x4baa9e3c; + unsigned int i5r = 0x395dbbeb; + unsigned int i6 = 0x39344296; + unsigned int i6r = 0x429889eb; + unsigned int i7 = 0x68a586b0; + unsigned int i7r = 0x2ae11e67; + + float x3 = hide_float(make_float(i3)); + float x3r = hide_float(make_float(i3r)); + float x4 = hide_float(make_float(i4)); + float x4r = hide_float(make_float(i4r)); + float x5 = hide_float(make_float(i5)); + float x5r = hide_float(make_float(i5r)); + float x6 = hide_float(make_float(i6)); + float x6r = hide_float(make_float(i6r)); + float x7 = hide_float(make_float(i7)); + float x7r = hide_float(make_float(i7r)); + + vec_float4 x3_v = spu_splats(x3); + vec_float4 x3r_v = spu_splats(x3r); + vec_float4 x4_v = spu_splats(x4); + vec_float4 x4r_v = spu_splats(x4r); + vec_float4 x5_v = spu_splats(x5); + vec_float4 x5r_v = spu_splats(x5r); + vec_float4 x6_v = spu_splats(x6); + vec_float4 x6r_v = spu_splats(x6r); + vec_float4 x7_v = spu_splats(x7); + vec_float4 x7r_v = spu_splats(x7r); + + vec_float4 res_v; + + TEST_START("rsqrtf4"); + res_v = rsqrtf4(x3_v); + TEST_CHECK("20040928182352EJL", allequal_ulps_float4( res_v, x3r_v, 2 ), 0); + res_v = rsqrtf4(x4_v); + TEST_CHECK("20040928182355EJL", allequal_ulps_float4( res_v, x4r_v, 2 ), 0); + res_v = rsqrtf4(x5_v); + TEST_CHECK("20040928182357EJL", allequal_ulps_float4( res_v, x5r_v, 2 ), 0); + res_v = rsqrtf4(x6_v); + TEST_CHECK("20040928182358EJL", allequal_ulps_float4( res_v, x6r_v, 2 ), 0); + res_v = rsqrtf4(x7_v); + TEST_CHECK("20040928182401EJL", allequal_ulps_float4( res_v, x7r_v, 2 ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/scalbllnd2.c b/Extras/simdmathlibrary/spu/tests/scalbllnd2.c new file mode 100644 index 0000000..e3484b3 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/scalbllnd2.c @@ -0,0 +1,251 @@ +/* Test scalbllnd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/** + * + *@@ scalbllnd2 - Multiply Double by 2 Raised to its Power + * For large elements of ex (overflow), returns HUGE_VALF + * For small elements of ex (underflow), returns 0. + * + *@brief + * boundary test for scalbllnd2. + * + * + *@pre + * + *@criteria + * Run this program and check no error will be occurred. + * + *@note + * add Denormalized handling + * Round mode was passed because of spec. (underflow returns 0) + * + * + **/ + +#include +#include +#include +//#include +#include + +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +#undef SCALBLLND2_ROUND + + +typedef struct { + unsigned long long int xxx[2]; + unsigned long long int exp[2]; + unsigned long long int ans0[2]; + unsigned long long int ans1[2]; + unsigned long long int ans2[2]; + unsigned long long int ans3[2]; +} TestVec64_Ldexp; + +int main() +{ + TestVec64_Ldexp test_a[] = { + { + // zero + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000400ULL,0xFFFFFFFFFFFFFC00ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL} + },{ + // MIN , MAX + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL}, + {0x0000000000000001ULL,0x0000000000000001ULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL}, + {0xFFEFFFFFFFFFFFFFULL,0x7FEFFFFFFFFFFFFFULL} + },{ + // Inf , -Inf + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x0000000000000001ULL,0x0000000000000001ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL}, + {0x7FF0000000000000ULL,0xFFF0000000000000ULL} + },{ +#ifdef SCALBLLND2_ROUND + // denotmalized + {0x8000000000000003ULL,0x0000000000000003ULL}, + {0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL}, + {0x8000000000000002ULL,0x0000000000000001ULL}, + {0x8000000000000001ULL,0x0000000000000002ULL}, + {0x8000000000000001ULL,0x0000000000000001ULL}, + {0x8000000000000002ULL,0x0000000000000002ULL} + },{ + // denotmalized -54 + {0x0010000000000001ULL,0x8010000000000001ULL}, + {0xFFFFFFFFFFFFFFCAULL,0xFFFFFFFFFFFFFFCAULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000001ULL,0x8000000000000001ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL} + },{ + // max -> ! + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0xFFFFFFFFFFFFF7CEULL,0xFFFFFFFFFFFFF7CEULL}, + {0x0000000000000001ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000001ULL,0x8000000000000001ULL}, + {0x0000000000000000ULL,0x8000000000000001ULL} + },{ + // max -> ! + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0xFFFFFFFFFFFFF7CDULL,0xFFFFFFFFFFFFF7CDULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000001ULL,0x8000000000000001ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL} + },{ +#else // SCALBLLND2_ROUND + // denotmalized + {0x8000000000000003ULL,0x0000000000000003ULL}, + {0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL}, + {0x8000000000000001ULL,0x0000000000000001ULL}, + {0x8000000000000001ULL,0x0000000000000001ULL}, + {0x8000000000000001ULL,0x0000000000000001ULL}, + {0x8000000000000001ULL,0x0000000000000001ULL} + },{ + +#endif // SCALBLLND2_ROUND + // denotmalized + {0x0010000000000000ULL,0x8010000000000000ULL}, + {0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL}, + {0x0008000000000000ULL,0x8008000000000000ULL}, + {0x0008000000000000ULL,0x8008000000000000ULL}, + {0x0008000000000000ULL,0x8008000000000000ULL}, + {0x0008000000000000ULL,0x8008000000000000ULL} + },{ + // denotmalized + {0x0008000000000000ULL,0x8008000000000000ULL}, + {0x0000000000000001ULL,0x0000000000000001ULL}, + {0x0010000000000000ULL,0x8010000000000000ULL}, + {0x0010000000000000ULL,0x8010000000000000ULL}, + {0x0010000000000000ULL,0x8010000000000000ULL}, + {0x0010000000000000ULL,0x8010000000000000ULL} + },{ + // 1.0 + {0x3ff0000000000000ULL,0xbff0000000000000ULL}, + {0x00000000000003ffULL,0x00000000000003ffULL}, + {0x7FE0000000000000ULL,0xFFE0000000000000ULL}, + {0x7FE0000000000000ULL,0xFFE0000000000000ULL}, + {0x7FE0000000000000ULL,0xFFE0000000000000ULL}, + {0x7FE0000000000000ULL,0xFFE0000000000000ULL} + },{ + // 1.0 -> max + {0x3ff0000000000000ULL,0xbff0000000000000ULL}, + {0x0000000000000400ULL,0x0000000000000400ULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL} + },{ + // max -> ! + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0xFFFFFFFF00000000ULL,0xFFFFFFFF00000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL} + },{ + // min-> + {0x0000000000000001ULL,0x8000000000000001ULL}, + {0x0FFFFFFFFFFFFFFFULL,0x0FFFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL} + },{ + // NaN , -NaN + {0x7FFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL}, + {0x0000000000000001ULL,0x0000000000000001ULL}, + {0x7FFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL}, + {0x7FFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL}, + {0x7FFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL}, + {0x7FFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL} + },{ + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL}, + {0ULL,0ULL} + } + }; + int ii, test_ctr = 1; + char msg[80]; + vec_double2 res_v; + + TEST_SET_START("20060907180000NM","NM", "scalbllnd2"); + + TEST_START("scalbllnd2"); + + for (ii=0; ; ii++) { + if ( (test_a[ii].xxx[0] == 0) && (test_a[ii].xxx[1] == 0) ) break; + + // set Floating point round mode + spu_mtfpscr(((vec_uint4){0x0100,0,0,0})); + res_v = scalbllnd2 (*((vec_double2 *)&test_a[ii].xxx[0]), *((vec_llong2 *)&test_a[ii].exp[0])); + sprintf(msg,"2006090718%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans0[0])), 0); + +#ifdef SCALBLLND2_ROUND + + spu_mtfpscr(((vec_uint4){0x0600,0,0,0})); + res_v = scalbllnd2 (*((vec_double2 *)&test_a[ii].xxx[0]), *((vec_llong2 *)&test_a[ii].exp[0])); + sprintf(msg,"2006090718%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans1[0])), 0); + + spu_mtfpscr(((vec_uint4){0x0b00,0,0,0})); + res_v = scalbllnd2 (*((vec_double2 *)&test_a[ii].xxx[0]), *((vec_llong2 *)&test_a[ii].exp[0])); + sprintf(msg,"2006090718%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans2[0])), 0); + + spu_mtfpscr(((vec_uint4){0x0c00,0,0,0})); + res_v = scalbllnd2 (*((vec_double2 *)&test_a[ii].xxx[0]), *((vec_llong2 *)&test_a[ii].exp[0])); + sprintf(msg,"2006090718%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, *((vec_llong2 *)&test_a[ii].ans3[0])), 0); +#endif // SCALBLLND2_ROUND + + } + + + TEST_SET_DONE(); + + TEST_EXIT(); + +} diff --git a/Extras/simdmathlibrary/spu/tests/scalbnf4.c b/Extras/simdmathlibrary/spu/tests/scalbnf4.c new file mode 100644 index 0000000..3961ebd --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/scalbnf4.c @@ -0,0 +1,117 @@ +/* Test nextafterf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +typedef union { + struct { + float xxx[4]; + int exp[4]; + float ans[4]; + } flt; + struct { + unsigned int xxx[4]; + unsigned int exp[4]; + unsigned int ans[4]; + } ui; +} TestVec_ScalF4; + + +int main() +{ + TestVec_ScalF4 test_a[] = { + { + ui:{ + // 0 -> 0 , -0 -> -0 + {0x00000000,0x80000000,0x80000000,0x00000000}, + {0x000000FF,0x00000001,0xFFFFFFFF,0xFFFFFF00}, + {0x00000000,0x80000000,0x80000000,0x00000000} + } + },{ + ui:{ + // Inf + {0xFF800000,0x7F800000,0x7F800000,0xFF800000}, + {0x000000FF,0x00000001,0xFFFFFFFF,0xFFFFFF00}, + {0xFFFFFFFF,0x7FFFFFFF,0x7F000000,0x80000000} + } + },{ + ui:{ + // MAX MIN + {0x7F7FFFFF,0xFF7FFFFF,0x7F7FFFFF,0xFF7FFFFF}, + {0x00000001,0x00000001,0xFFFFFFFF,0xFFFFFF00}, + {0x7FFFFFFF,0xFFFFFFFF,0x7EFFFFFF,0x00000000} + } + },{ + flt:{ + {-1.0, 1.0, -1.0, 1.0}, + { 1, 1, -1, -1}, + {-2.0, 2.0, -0.5, 0.5} + } + },{ + ui:{ + // + {0x80ffffff,0x80ffffff,0x00ffffff,0x00ffffff}, + {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}, + {0x80000000,0x80000000,0x00000000,0x00000000} + } + },{ + ui:{ + {0,0,0,0}, + {0,0,0,0}, + {0,0,0,0} + } + } + }; + int ii, test_ctr = 1; + char msg[80]; + vec_float4 res_v; + + TEST_SET_START("20060907150000NM","NM", "scalbnf4"); + + TEST_START("scalbnf4"); + + for (ii=0; ; ii++) { + if ( (test_a[ii].ui.xxx[0] == 0) && (test_a[ii].ui.xxx[1] == 0) ) break; + + res_v = scalbnf4 (*((vec_float4 *)&test_a[ii].flt.xxx[0]), *((vec_int4 *)&test_a[ii].flt.exp[0]) ); + sprintf(msg,"2006090715%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_float4( res_v, *((vec_float4 *)&test_a[ii].flt.ans[0])), 0); + } + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/signbitd2.c b/Extras/simdmathlibrary/spu/tests/signbitd2.c new file mode 100644 index 0000000..b81d0b9 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/signbitd2.c @@ -0,0 +1,195 @@ +/* Test signbitd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060829000000AAN","AAN", "signbitd2"); + + //-Nan + double x0 = hide_double(-nan("")); + unsigned long long r0 = 0xffffffffffffffffull; + + //-Inf + double x1 = hide_double(-HUGE_VAL); + unsigned long long r1 = 0xffffffffffffffffull; + + //-Smax + double x2 = hide_double(-DBL_MAX); + unsigned long long r2 = 0xffffffffffffffffull; + + //-Norm + double x3 = hide_double(-168.97345223013); + unsigned long long r3 = 0xffffffffffffffffull; + + //-Denorm + double x4 = hide_double(make_double(0x803AAAAAAAAAAAAAull)); + unsigned long long r4 = 0xffffffffffffffffull; + + //-Smin + double x5 = hide_double(-DBL_MIN); + unsigned long long r5 = 0xffffffffffffffffull; + + //-Unf + double x6 = hide_double(-1.0e-999); + unsigned long long r6 = 0xffffffffffffffffull; + + // -0 + double x7 = hide_double(-0.0); + unsigned long long r7 = 0xffffffffffffffffull; + + // 0 + double x8 = hide_double( 0.0); + unsigned long long r8 = 0x0000000000000000ull; + + //+Unf + double x9 = hide_double( 1.0e-999); + unsigned long long r9 = 0x0000000000000000ull; + + //+Smin + double x10 = hide_double( DBL_MIN); + unsigned long long r10 = 0x0000000000000000ull; + + //+Denorm + double x11 = hide_double(make_double(0x007AAAAAAAAAAAAAull)); + unsigned long long r11 = 0x0000000000000000ull; + + //+Norm + double x12 = hide_double( 672953.74593); + unsigned long long r12 = 0x0000000000000000ull; + + //+Smax + double x13 = hide_double( DBL_MAX); + unsigned long long r13 = 0x0000000000000000ull; + + //+Inf + double x14 = hide_double(HUGE_VAL); + unsigned long long r14 = 0x0000000000000000ull; + + //+NaN + double x15 = hide_double( nan("")); + unsigned long long r15 = 0x0000000000000000ull; + + vec_double2 x0_v = spu_splats(x0); + vec_ullong2 r0_v = spu_splats(r0); + + vec_double2 x1_v = spu_splats(x1); + vec_ullong2 r1_v = spu_splats(r1); + + vec_double2 x2_v = spu_splats(x2); + vec_ullong2 r2_v = spu_splats(r2); + + vec_double2 x3_v = spu_splats(x3); + vec_ullong2 r3_v = spu_splats(r3); + + vec_double2 x4_v = spu_splats(x4); + vec_ullong2 r4_v = spu_splats(r4); + + vec_double2 x5_v = spu_splats(x5); + vec_ullong2 r5_v = spu_splats(r5); + + vec_double2 x6_v = spu_splats(x6); + vec_ullong2 r6_v = spu_splats(r6); + + vec_double2 x7_v = spu_splats(x7); + vec_ullong2 r7_v = spu_splats(r7); + + vec_double2 x8_v = spu_splats(x8); + vec_ullong2 r8_v = spu_splats(r8); + + vec_double2 x9_v = spu_splats(x9); + vec_ullong2 r9_v = spu_splats(r9); + + vec_double2 x10_v = spu_splats(x10); + vec_ullong2 r10_v = spu_splats(r10); + + vec_double2 x11_v = spu_splats(x11); + vec_ullong2 r11_v = spu_splats(r11); + + vec_double2 x12_v = spu_splats(x12); + vec_ullong2 r12_v = spu_splats(r12); + + vec_double2 x13_v = spu_splats(x13); + vec_ullong2 r13_v = spu_splats(r13); + + vec_double2 x14_v = spu_splats(x14); + vec_ullong2 r14_v = spu_splats(r14); + + vec_double2 x15_v = spu_splats(x15); + vec_ullong2 r15_v = spu_splats(r15); + + vec_ullong2 res_v; + + TEST_START("signbitd2"); + + res_v = (vec_ullong2)signbitd2(x0_v); + TEST_CHECK("20060829000000AAN", allequal_ullong2( res_v, r0_v ), 0); + res_v = (vec_ullong2)signbitd2(x1_v); + TEST_CHECK("20060829000001AAN", allequal_ullong2( res_v, r1_v ), 0); + res_v = (vec_ullong2)signbitd2(x2_v); + TEST_CHECK("20060829000002AAN", allequal_ullong2( res_v, r2_v ), 0); + res_v = (vec_ullong2)signbitd2(x3_v); + TEST_CHECK("20060829000003AAN", allequal_ullong2( res_v, r3_v ), 0); + res_v = (vec_ullong2)signbitd2(x4_v); + TEST_CHECK("20060829000004AAN", allequal_ullong2( res_v, r4_v ), 0); + res_v = (vec_ullong2)signbitd2(x5_v); + TEST_CHECK("20060829000005AAN", allequal_ullong2( res_v, r5_v ), 0); + res_v = (vec_ullong2)signbitd2(x6_v); + TEST_CHECK("20060829000006AAN", allequal_ullong2( res_v, r6_v ), 0); + res_v = (vec_ullong2)signbitd2(x7_v); + TEST_CHECK("20060829000007AAN", allequal_ullong2( res_v, r7_v ), 0); + res_v = (vec_ullong2)signbitd2(x8_v); + TEST_CHECK("20060829000008AAN", allequal_ullong2( res_v, r8_v ), 0); + res_v = (vec_ullong2)signbitd2(x9_v); + TEST_CHECK("20060829000009AAN", allequal_ullong2( res_v, r9_v ), 0); + res_v = (vec_ullong2)signbitd2(x10_v); + TEST_CHECK("20060829000010AAN", allequal_ullong2( res_v, r10_v ), 0); + res_v = (vec_ullong2)signbitd2(x11_v); + TEST_CHECK("20060829000011AAN", allequal_ullong2( res_v, r11_v ), 0); + res_v = (vec_ullong2)signbitd2(x12_v); + TEST_CHECK("20060829000012AAN", allequal_ullong2( res_v, r12_v ), 0); + res_v = (vec_ullong2)signbitd2(x13_v); + TEST_CHECK("20060829000013AAN", allequal_ullong2( res_v, r13_v ), 0); + res_v = (vec_ullong2)signbitd2(x14_v); + TEST_CHECK("20060829000014AAN", allequal_ullong2( res_v, r14_v ), 0); + res_v = (vec_ullong2)signbitd2(x15_v); + TEST_CHECK("20060829000015AAN", allequal_ullong2( res_v, r15_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/signbitf4.c b/Extras/simdmathlibrary/spu/tests/signbitf4.c new file mode 100644 index 0000000..156cc2d --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/signbitf4.c @@ -0,0 +1,195 @@ +/* Test signbitf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20060829000000AAN","AAN", "signbitf4"); + + //-Nan + float x0 = hide_float(-NANF); + unsigned int r0 = 0xffffffff; + + //-Inf + float x1 = hide_float(-HUGE_VAL); + unsigned int r1 = 0xffffffff; + + //-Smax + float x2 = hide_float(-FLT_MAX); + unsigned int r2 = 0xffffffff; + + //-Norm + float x3 = hide_float(-168.97345223013f); + unsigned int r3 = 0xffffffff; + + //-Denorm + float x4 = hide_float(make_float(0x803AAAAA)); + unsigned int r4 = 0xffffffff; + + //-Smin + float x5 = hide_float(-FLT_MIN); + unsigned int r5 = 0xffffffff; + + //-Unf + float x6 = hide_float(-1.0e-999); + unsigned int r6 = 0xffffffff; + + // -0 + float x7 = hide_float(-0.0f); + unsigned int r7 = 0xffffffff; + + // 0 + float x8 = hide_float( 0.0f); + unsigned int r8 = 0x00000000; + + //+Unf + float x9 = hide_float( 1.0e-999); + unsigned int r9 = 0x00000000; + + //+Smin + float x10 = hide_float( FLT_MIN); + unsigned int r10 = 0x00000000; + + //+Denorm + float x11 = hide_float(make_float(0x007AAAAA)); + unsigned int r11 = 0x00000000; + + //+Norm + float x12 = hide_float( 672953.74593f); + unsigned int r12 = 0x00000000; + + //+Smax + float x13 = hide_float( FLT_MAX); + unsigned int r13 = 0x00000000; + + //+Inf + float x14 = hide_float(HUGE_VAL); + unsigned int r14 = 0x00000000; + + //+NaN + float x15 = hide_float(NANF); + unsigned int r15 = 0x00000000; + + vec_float4 x0_v = spu_splats(x0); + vec_uint4 r0_v = spu_splats(r0); + + vec_float4 x1_v = spu_splats(x1); + vec_uint4 r1_v = spu_splats(r1); + + vec_float4 x2_v = spu_splats(x2); + vec_uint4 r2_v = spu_splats(r2); + + vec_float4 x3_v = spu_splats(x3); + vec_uint4 r3_v = spu_splats(r3); + + vec_float4 x4_v = spu_splats(x4); + vec_uint4 r4_v = spu_splats(r4); + + vec_float4 x5_v = spu_splats(x5); + vec_uint4 r5_v = spu_splats(r5); + + vec_float4 x6_v = spu_splats(x6); + vec_uint4 r6_v = spu_splats(r6); + + vec_float4 x7_v = spu_splats(x7); + vec_uint4 r7_v = spu_splats(r7); + + vec_float4 x8_v = spu_splats(x8); + vec_uint4 r8_v = spu_splats(r8); + + vec_float4 x9_v = spu_splats(x9); + vec_uint4 r9_v = spu_splats(r9); + + vec_float4 x10_v = spu_splats(x10); + vec_uint4 r10_v = spu_splats(r10); + + vec_float4 x11_v = spu_splats(x11); + vec_uint4 r11_v = spu_splats(r11); + + vec_float4 x12_v = spu_splats(x12); + vec_uint4 r12_v = spu_splats(r12); + + vec_float4 x13_v = spu_splats(x13); + vec_uint4 r13_v = spu_splats(r13); + + vec_float4 x14_v = spu_splats(x14); + vec_uint4 r14_v = spu_splats(r14); + + vec_float4 x15_v = spu_splats(x15); + vec_uint4 r15_v = spu_splats(r15); + + vec_uint4 res_v; + + TEST_START("signbitf4"); + + res_v = (vec_uint4)signbitf4(x0_v); + TEST_CHECK("20060829000000AAN", allequal_uint4( res_v, r0_v ), 0); + res_v = (vec_uint4)signbitf4(x1_v); + TEST_CHECK("20060829000001AAN", allequal_uint4( res_v, r1_v ), 0); + res_v = (vec_uint4)signbitf4(x2_v); + TEST_CHECK("20060829000002AAN", allequal_uint4( res_v, r2_v ), 0); + res_v = (vec_uint4)signbitf4(x3_v); + TEST_CHECK("20060829000003AAN", allequal_uint4( res_v, r3_v ), 0); + res_v = (vec_uint4)signbitf4(x4_v); + TEST_CHECK("20060829000004AAN", allequal_uint4( res_v, r4_v ), 0); + res_v = (vec_uint4)signbitf4(x5_v); + TEST_CHECK("20060829000005AAN", allequal_uint4( res_v, r5_v ), 0); + res_v = (vec_uint4)signbitf4(x6_v); + TEST_CHECK("20060829000006AAN", allequal_uint4( res_v, r6_v ), 0); + res_v = (vec_uint4)signbitf4(x7_v); + TEST_CHECK("20060829000007AAN", allequal_uint4( res_v, r7_v ), 0); + res_v = (vec_uint4)signbitf4(x8_v); + TEST_CHECK("20060829000008AAN", allequal_uint4( res_v, r8_v ), 0); + res_v = (vec_uint4)signbitf4(x9_v); + TEST_CHECK("20060829000009AAN", allequal_uint4( res_v, r9_v ), 0); + res_v = (vec_uint4)signbitf4(x10_v); + TEST_CHECK("20060829000010AAN", allequal_uint4( res_v, r10_v ), 0); + res_v = (vec_uint4)signbitf4(x11_v); + TEST_CHECK("20060829000011AAN", allequal_uint4( res_v, r11_v ), 0); + res_v = (vec_uint4)signbitf4(x12_v); + TEST_CHECK("20060829000012AAN", allequal_uint4( res_v, r12_v ), 0); + res_v = (vec_uint4)signbitf4(x13_v); + TEST_CHECK("20060829000013AAN", allequal_uint4( res_v, r13_v ), 0); + res_v = (vec_uint4)signbitf4(x14_v); + TEST_CHECK("20060829000014AAN", allequal_uint4( res_v, r14_v ), 0); + res_v = (vec_uint4)signbitf4(x15_v); + TEST_CHECK("20060829000015AAN", allequal_uint4( res_v, r15_v ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/sqrtd2.c b/Extras/simdmathlibrary/spu/tests/sqrtd2.c new file mode 100644 index 0000000..0863949 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/sqrtd2.c @@ -0,0 +1,128 @@ +/* Test sqrtd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + + + +int main() +{ + TEST_SET_START("20040928181417EJL","EJL", "sqrtd2"); + + unsigned long long i6 = 0x7464fff515d76f87ull; + unsigned long long i6r = 0x5a29ec408d8da268ull; + unsigned long long i7 = 0x7606a4533cf5605eull; + unsigned long long i7r = 0x5afaead3b0ed2de5ull; + unsigned long long i8 = 0x4beae58c6f48733eull; + unsigned long long i8r = 0x45ed566b9c6464d6ull; + unsigned long long i9 = 0x3999ed5c8316b00bull; + unsigned long long i9r = 0x3cc45e14871d1b1full; + unsigned long long i10 = 0x68f7885c4b84b793ull; + unsigned long long i10r = 0x54736778e6778980ull; + unsigned long long i11 = 0x1aabc083c5c26227ull; + unsigned long long i11r = 0x2d4dcce790f64a35ull; + + double x0 = hide_double(-HUGE_VAL); // -Inf -> NaN + double x1 = hide_double(HUGE_VAL); // Inf -> Inf + double x2 = hide_double(0.0); // +0 -> +0 + double x3 = hide_double(-0.0); // -0 -> -0 + double x4 = hide_double(nan("")); // NaN -> NaN + double x5 = hide_double(4.0); + double x5r = hide_double(2.0); + double x6 = hide_double(make_double(i6)); + double x6r = hide_double(make_double(i6r)); + double x7 = hide_double(make_double(i7)); + double x7r = hide_double(make_double(i7r)); + double x8 = hide_double(make_double(i8)); + double x8r = hide_double(make_double(i8r)); + double x9 = hide_double(make_double(i9)); + double x9r = hide_double(make_double(i9r)); + double x10 = hide_double(make_double(i10)); + double x10r = hide_double(make_double(i10r)); + double x11 = hide_double(make_double(i11)); + double x11r = hide_double(make_double(i11r)); + + vec_double2 x0_v = spu_splats(x0); + vec_double2 x1_v = spu_splats(x1); + vec_double2 x2_v = spu_splats(x2); + vec_double2 x3_v = spu_splats(x3); + vec_double2 x4_v = spu_splats(x4); + vec_double2 x5_v = spu_splats(x5); + vec_double2 x5r_v = spu_splats(x5r); + vec_double2 x6_v = spu_splats(x6); + vec_double2 x6r_v = spu_splats(x6r); + vec_double2 x7_v = spu_splats(x7); + vec_double2 x7r_v = spu_splats(x7r); + vec_double2 x8_v = spu_splats(x8); + vec_double2 x8r_v = spu_splats(x8r); + vec_double2 x9_v = spu_splats(x9); + vec_double2 x9r_v = spu_splats(x9r); + vec_double2 x10_v = spu_splats(x10); + vec_double2 x10r_v = spu_splats(x10r); + vec_double2 x11_v = spu_splats(x11); + vec_double2 x11r_v = spu_splats(x11r); + + vec_double2 res_v; + + TEST_START("sqrtd2"); + res_v = sqrtd2(x0_v); + TEST_CHECK("20040928181422EJL", allnan_double2( res_v ), 0); + res_v = sqrtd2(x1_v); + TEST_CHECK("20040928181424EJL", allposinf_double2( res_v ), 0); + res_v = sqrtd2(x2_v); + TEST_CHECK("20040928181426EJL", allposzero_double2( res_v ), 0); + res_v = sqrtd2(x3_v); + TEST_CHECK("20040928181430EJL", allnegzero_double2( res_v ), 0); + res_v = sqrtd2(x4_v); + TEST_CHECK("20040928181432EJL", allnan_double2( res_v ), 0); + res_v = sqrtd2(x5_v); + TEST_CHECK("20040928181434EJL", allequal_double2( res_v, x5r_v ), 0); + res_v = sqrtd2(x6_v); + TEST_CHECK("20040928181436EJL", allequal_ulps_double2( res_v, x6r_v, 1 ), 0); + res_v = sqrtd2(x7_v); + TEST_CHECK("20040928181438EJL", allequal_ulps_double2( res_v, x7r_v, 1 ), 0); + res_v = sqrtd2(x8_v); + TEST_CHECK("20040928181440EJL", allequal_ulps_double2( res_v, x8r_v, 1 ), 0); + res_v = sqrtd2(x9_v); + TEST_CHECK("20040928181442EJL", allequal_ulps_double2( res_v, x9r_v, 1 ), 0); + res_v = sqrtd2(x10_v); + TEST_CHECK("20040928181444EJL", allequal_ulps_double2( res_v, x10r_v, 1 ), 0); + res_v = sqrtd2(x11_v); + TEST_CHECK("20040928181446EJL", allequal_ulps_double2( res_v, x11r_v, 1 ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/sqrtf4.c b/Extras/simdmathlibrary/spu/tests/sqrtf4.c new file mode 100644 index 0000000..736f812 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/sqrtf4.c @@ -0,0 +1,92 @@ +/* Test sqrtf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +int main() +{ + TEST_SET_START("20040928182549EJL","EJL", "sqrtf4"); + + unsigned int i3 = 0x742c4455; + unsigned int i3r = 0x59d20034; + unsigned int i4 = 0x75e7753f; + unsigned int i4r = 0x5aac1fb5; + unsigned int i5 = 0x4baa9e3c; + unsigned int i5r = 0x4593c7d8; + unsigned int i6 = 0x39344296; + unsigned int i6r = 0x3c56d14c; + unsigned int i7 = 0x68a586b0; + unsigned int i7r = 0x54118f09; + + float x3 = hide_float(make_float(i3)); + float x3r = hide_float(make_float(i3r)); + float x4 = hide_float(make_float(i4)); + float x4r = hide_float(make_float(i4r)); + float x5 = hide_float(make_float(i5)); + float x5r = hide_float(make_float(i5r)); + float x6 = hide_float(make_float(i6)); + float x6r = hide_float(make_float(i6r)); + float x7 = hide_float(make_float(i7)); + float x7r = hide_float(make_float(i7r)); + + vec_float4 x3_v = spu_splats(x3); + vec_float4 x3r_v = spu_splats(x3r); + vec_float4 x4_v = spu_splats(x4); + vec_float4 x4r_v = spu_splats(x4r); + vec_float4 x5_v = spu_splats(x5); + vec_float4 x5r_v = spu_splats(x5r); + vec_float4 x6_v = spu_splats(x6); + vec_float4 x6r_v = spu_splats(x6r); + vec_float4 x7_v = spu_splats(x7); + vec_float4 x7r_v = spu_splats(x7r); + + vec_float4 res_v; + + TEST_START("sqrtf4"); + res_v = sqrtf4(x3_v); + TEST_CHECK("20040928182552EJL", allequal_ulps_float4( res_v, x3r_v, 2 ), 0); + res_v = sqrtf4(x4_v); + TEST_CHECK("20040928182554EJL", allequal_ulps_float4( res_v, x4r_v, 2 ), 0); + res_v = sqrtf4(x5_v); + TEST_CHECK("20040928182556EJL", allequal_ulps_float4( res_v, x5r_v, 2 ), 0); + res_v = sqrtf4(x6_v); + TEST_CHECK("20040928182557EJL", allequal_ulps_float4( res_v, x6r_v, 2 ), 0); + res_v = sqrtf4(x7_v); + TEST_CHECK("20040928182559EJL", allequal_ulps_float4( res_v, x7r_v, 2 ), 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/simdmathlibrary/spu/tests/testutils.c b/Extras/simdmathlibrary/spu/tests/testutils.c new file mode 100644 index 0000000..58af0df --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/testutils.c @@ -0,0 +1,321 @@ +/* Common part of testsuite for SPU SIMD Math library + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "testutils.h" + +typedef union { + unsigned int ui; + float f; +} conv4_t; + +typedef union { + unsigned long long ull; + double df; +} conv8_t; + +unsigned int +hide_uint( unsigned int x ) +{ + return x; +} + +int +hide_int( int x ) +{ + return x; +} + +float +hide_float( float x ) +{ + return x; +} + +double +hide_double( double x ) +{ + return x; +} + +float +make_float( unsigned int x ) +{ + conv4_t val; + val.ui = x; + return val.f; +} + +unsigned int +make_uint( float x ) +{ + conv4_t val; + val.f = x; + return val.ui; +} + +double +make_double( unsigned long long x ) +{ + conv8_t val; + val.ull = x; + return val.df; +} + +unsigned long long +make_ulonglong( double x ) +{ + conv8_t val; + val.df = x; + return val.ull; +} + +vec_uint4 bitDiff_f4(vec_float4 ref, vec_float4 vals) { + vec_int4 refi = (vec_int4)ref; + vec_int4 valsi = (vec_int4)vals; + vec_int4 diff = spu_sub(refi, valsi); + vec_int4 negdiff = spu_sub(spu_splats((int)0), diff); + + return spu_sub((vec_uint4)spu_splats(32), spu_cntlz(spu_sel(negdiff, diff, spu_cmpgt(diff, 0)))); +} + +unsigned int bitDiff_f(float ref, float val) { + return spu_extract(bitDiff_f4(spu_promote(ref,0), spu_promote(val,0)), 0); +} + +vec_ullong2 bitDiff_d2(vec_double2 ref, vec_double2 vals) { + double ref0, ref1, vals0, vals1; + long long refi0, refi1, valsi0, valsi1, diff0, diff1; + vec_ullong2 bits; + + ref0 = spu_extract(ref,0); + ref1 = spu_extract(ref,1); + vals0 = spu_extract(vals,0); + vals1 = spu_extract(vals,1); + + refi0 = make_ulonglong(ref0); + refi1 = make_ulonglong(ref1); + valsi0 = make_ulonglong(vals0); + valsi1 = make_ulonglong(vals1); + + diff0 = refi0 - valsi0; + diff1 = refi1 - valsi1; + + if ( diff0 < 0 ) + { + diff0 = valsi0 - refi0; + } + + if ( diff1 < 0 ) + { + diff1 = valsi1 - refi1; + } + + bits = spu_promote( (unsigned long long)ceil(log2((double)diff0)), 0 ); + bits = spu_insert( (unsigned long long)ceil(log2((double)diff1)), bits, 1 ); + + return bits; +} + +unsigned long long bitDiff_d(double ref, double val) { + return spu_extract(bitDiff_d2(spu_promote(ref,0), spu_promote(val,0)), 0); +} + +vec_uint4 ulpDiff_f4(vec_float4 ref, vec_float4 vals) { + vec_int4 refi = (vec_int4)ref; + vec_int4 valsi = (vec_int4)vals; + vec_int4 diff = spu_sub(refi, valsi); + vec_int4 negdiff = spu_sub(spu_splats((int)0), diff); + + return (vec_uint4)(spu_sel(negdiff, diff, spu_cmpgt(diff, 0))); +} + +unsigned int ulpDiff_f(float ref, float val) { + return spu_extract(ulpDiff_f4(spu_promote(ref,0), spu_promote(val,0)), 0); +} + +vec_ullong2 ulpDiff_d2(vec_double2 ref, vec_double2 vals) { + double ref0, ref1, vals0, vals1; + long long refi0, refi1, valsi0, valsi1, diff0, diff1; + vec_ullong2 ulps; + + ref0 = spu_extract(ref,0); + ref1 = spu_extract(ref,1); + vals0 = spu_extract(vals,0); + vals1 = spu_extract(vals,1); + + refi0 = make_ulonglong(ref0); + refi1 = make_ulonglong(ref1); + valsi0 = make_ulonglong(vals0); + valsi1 = make_ulonglong(vals1); + + diff0 = refi0 - valsi0; + diff1 = refi1 - valsi1; + + if ( diff0 < 0 ) + { + diff0 = valsi0 - refi0; + } + + if ( diff1 < 0 ) + { + diff1 = valsi1 - refi1; + } + + ulps = spu_promote( (unsigned long long)diff0, 0 ); + ulps = spu_insert( (unsigned long long)diff1, ulps, 1 ); + + return ulps; +} + +unsigned long long ulpDiff_d(double ref, double val) { + return spu_extract(ulpDiff_d2(spu_promote(ref,0), spu_promote(val,0)), 0); +} + +vec_ullong2 cmpposzerod2( vec_double2 x ) +{ + vec_ullong2 cmp; + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_uchar16 odd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x04050607, 0x0c0d0e0f, 0x0c0d0e0f }; + + cmp = (vec_ullong2)spu_cmpeq( (vec_int4)x, spu_splats(0) ); + cmp = spu_and( spu_shuffle( cmp, cmp, even ), spu_shuffle( cmp, cmp, odd ) ); + + return cmp; +} + +vec_ullong2 cmpnegzerod2( vec_double2 x ) +{ + vec_ullong2 cmp; + vec_uchar16 even = (vec_uchar16)(vec_uint4){ 0x00010203, 0x00010203, 0x08090a0b, 0x08090a0b }; + vec_uchar16 odd = (vec_uchar16)(vec_uint4){ 0x04050607, 0x04050607, 0x0c0d0e0f, 0x0c0d0e0f }; + + cmp = (vec_ullong2)spu_cmpeq( (vec_int4)x, (vec_int4)spu_splats(0x8000000000000000ull) ); + cmp = spu_and( spu_shuffle( cmp, cmp, even ), spu_shuffle( cmp, cmp, odd ) ); + + return cmp; +} + +int allequal_int4( vec_int4 x, vec_int4 y ) +{ + return ( spu_extract( spu_gather( spu_cmpeq( x, y ) ), 0 ) == 0xf ); +} +int allequal_llong2( vec_llong2 x, vec_llong2 y ) +{ + return spu_extract( spu_gather( spu_cmpeq ((vec_int4)(x - y), spu_splats((int)0) )), 0) == 0xF; +} + +int allequal_float4( vec_float4 x, vec_float4 y ) +{ + return ( spu_extract( spu_gather( (vec_uint4)spu_cmpeq( x, y ) ), 0 ) == 0xf ); +} + +int allequal_double2( vec_double2 x, vec_double2 y ) +{ + return ( spu_extract(x,0) == spu_extract(y,0) && spu_extract(x,1) == spu_extract(y,1) ); +} + +int allequal_llroundf4( llroundf4_t x, llroundf4_t y ) +{ + return ( spu_extract(x.vll[0],0) == spu_extract(y.vll[0],0) && + spu_extract(x.vll[0],1) == spu_extract(y.vll[0],1) && + spu_extract(x.vll[1],0) == spu_extract(y.vll[1],0) && + spu_extract(x.vll[1],1) == spu_extract(y.vll[1],1) ); +} + +int allequal_ulps_float4( vec_float4 x, vec_float4 y, int tolerance ) +{ + vec_uint4 ulps = ulpDiff_f4( x, y ); + return ( (int)spu_extract(ulps,0) <= tolerance && + (int)spu_extract(ulps,1) <= tolerance && + (int)spu_extract(ulps,2) <= tolerance && + (int)spu_extract(ulps,3) <= tolerance ); +} + +int allequal_ulps_double2( vec_double2 x, vec_double2 y, int tolerance ) +{ + vec_ullong2 ulps = ulpDiff_d2( x, y ); + return ( (int)spu_extract(ulps,0) <= tolerance && (int)spu_extract(ulps,1) <= tolerance ); +} + +int allequal_bits_float4( vec_float4 x, vec_float4 y, int tolerance ) +{ + vec_uint4 bits = bitDiff_f4( x, y ); + return ( (int)spu_extract(bits,0) <= tolerance && + (int)spu_extract(bits,1) <= tolerance && + (int)spu_extract(bits,2) <= tolerance && + (int)spu_extract(bits,3) <= tolerance ); +} + +int allequal_bits_double2( vec_double2 x, vec_double2 y, int tolerance ) +{ + vec_ullong2 bits = bitDiff_d2( x, y ); + return ( (int)spu_extract(bits,0) <= tolerance && (int)spu_extract(bits,1) <= tolerance ); +} + +int allposinf_double2( vec_double2 x ) +{ + vec_ullong2 posinf = spu_andc( isinfd2 ( x ), signbitd2 ( x ) ); + return ( spu_extract(posinf,0) != 0 && spu_extract(posinf,1) != 0 ); +} + +int allneginf_double2( vec_double2 x ) +{ + vec_ullong2 neginf = spu_and( isinfd2 ( x ), signbitd2 ( x ) ); + return ( spu_extract(neginf,0) != 0 && spu_extract(neginf,1) != 0 ); +} + +int allzerodenorm_double2( vec_double2 x ) +{ + vec_ullong2 zero = is0denormd2 ( x ); + return ( spu_extract(zero,0) != 0 && spu_extract(zero,1) != 0 ); +} + +int allposzero_double2( vec_double2 x ) +{ + vec_ullong2 poszero = cmpposzerod2( x ); + return ( spu_extract(poszero,0) != 0 && spu_extract(poszero,1) != 0 ); +} + +int allnegzero_double2( vec_double2 x ) +{ + vec_ullong2 negzero = cmpnegzerod2( x ); + return ( spu_extract(negzero,0) != 0 && spu_extract(negzero,1) != 0 ); +} + +int allnan_double2( vec_double2 x ) +{ + vec_ullong2 nan = isnand2 ( x ); + return ( spu_extract(nan,0) != 0 && spu_extract(nan,1) != 0 ); +} + + diff --git a/Extras/simdmathlibrary/spu/tests/testutils.h b/Extras/simdmathlibrary/spu/tests/testutils.h new file mode 100644 index 0000000..b557b76 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/testutils.h @@ -0,0 +1,87 @@ +/* Common part for SPU SIMD Math library testsuite + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + + + +#ifndef _TESTUTILS_H_ + +#include + +#define NANF __builtin_nanf("") + +extern unsigned int hide_uint( unsigned int x ); +extern int hide_int( int x ); +extern float hide_float( float x ); +extern double hide_double( double x ); + +extern float make_float( unsigned int x ); +extern unsigned int make_uint( float x ); +extern double make_double( unsigned long long x ); +extern unsigned long long make_ulonglong( double x ); + +extern vec_uint4 bitDiff_f4(vec_float4 ref, vec_float4 vals); +extern unsigned int bitDiff_f(float ref, float val); + +extern vec_ullong2 bitDiff_d2(vec_double2 ref, vec_double2 vals); +extern unsigned long long bitDiff_d(double ref, double val); + +extern vec_uint4 ulpDiff_f4(vec_float4 ref, vec_float4 vals); +extern unsigned int ulpDiff_f(float ref, float val); + +extern vec_ullong2 ulpDiff_d2(vec_double2 ref, vec_double2 vals); +extern unsigned long long ulpDiff_d(double ref, double val); + +extern vec_ullong2 cmpposzerod2( vec_double2 x ); +extern vec_ullong2 cmpnegzerod2( vec_double2 x ); +extern int allequal_int4( vec_int4 x, vec_int4 y ); +static inline int allequal_uint4( vec_uint4 x, vec_uint4 y ) +{ + return allequal_int4 ((vec_int4)x, (vec_int4)y); +} +extern int allequal_llong2( vec_llong2 x, vec_llong2 y ); +static inline int allequal_ullong2( vec_ullong2 x, vec_ullong2 y ) +{ + return allequal_llong2((vec_llong2)x, (vec_llong2)y); +} +extern int allequal_float4( vec_float4 x, vec_float4 y ); +extern int allequal_double2( vec_double2 x, vec_double2 y ); +extern int allequal_llroundf4( llroundf4_t x, llroundf4_t y ); +extern int allequal_ulps_float4( vec_float4 x, vec_float4 y, int tolerance ); +extern int allequal_ulps_double2( vec_double2 x, vec_double2 y, int tolerance ); +extern int allequal_bits_float4( vec_float4 x, vec_float4 y, int tolerance ); +extern int allequal_bits_double2( vec_double2 x, vec_double2 y, int tolerance ); +extern int allposinf_double2( vec_double2 x ); +extern int allneginf_double2( vec_double2 x ); +extern int allzerodenorm_double2( vec_double2 x ); +extern int allposzero_double2( vec_double2 x ); +extern int allnegzero_double2( vec_double2 x ); +extern int allnan_double2( vec_double2 x ); + +#endif diff --git a/Extras/simdmathlibrary/spu/tests/truncd2.c b/Extras/simdmathlibrary/spu/tests/truncd2.c new file mode 100644 index 0000000..105a724 --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/truncd2.c @@ -0,0 +1,145 @@ +/* Test truncd2 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + */ +/** + * + *@@ truncd2 - Round the input to the nearest integer. + * Always rounds towards 0. + * + *@brief + * boundary test for nextafterd2. + * + * + *@pre + * + *@criteria + * Run this program and check no error will be occurred. + * + *@note + * + * + **/ + +#include +#include +#include +//#include +#include + +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + +typedef union { + struct { + double xxx[2]; + double ans[2]; + } dbl; + struct { + unsigned long long xxx[2]; + unsigned long long ans[2]; + } ull; +} TestVec_TruncD2; + +int main() +{ + TestVec_TruncD2 test_a[] = { + { + ull:{ + // 0 -> 0 , -0 -> -0 + {0x0000000000000000ULL,0x8000000000000000ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL} + } + },{ + ull:{ + // -Inf -> -Inf , Inf -> Inf + {0xFFF0000000000000ULL,0x7FF0000000000000ULL}, + {0xFFF0000000000000ULL,0x7FF0000000000000ULL} + } + },{ + ull:{ + // MAX -> MAX , MIN -> MIN + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL}, + {0x7FEFFFFFFFFFFFFFULL,0xFFEFFFFFFFFFFFFFULL} + } + },{ + ull:{ + // Denormalize -> 0 + {0x0000000000000001ULL,0x8000000000000010ULL}, + {0x0000000000000000ULL,0x8000000000000000ULL} + } + },{ + ull:{ + // Denormalize -> 0 + {0x800FFFFFFFFFFFFFULL,0x000FFFFFFFFFFFFFULL}, + {0x8000000000000000ULL,0x0000000000000000ULL} + } + },{ + dbl:{ + {1.0, -1.0}, + {1.0, -1.0} + } + },{ + dbl:{ + {-2.5, 3.5}, + {-2.0, 3.0} + } + },{ + ull:{ + // Nan + {0xFFF0000000000001ULL,0x7FF0000000000001ULL}, + {0xFFF0000000000001ULL,0x7FF0000000000001ULL} + } + },{ + ull:{ + {0ULL,0ULL}, + {0ULL,0ULL} + } + } + }; + int ii, test_ctr = 1; + char msg[80]; + vec_double2 res_v; + + TEST_SET_START("20060831180000NM","NM", "truncd2"); + + TEST_START("truncd2"); + + for (ii=0; ; ii++) { + if ( (test_a[ii].ull.xxx[0] == 0) && (test_a[ii].ull.xxx[1] == 0) ) break; + + res_v = truncd2 (*((vec_double2 *)&test_a[ii].dbl.xxx[0]) ); + sprintf(msg,"2006083118%04dNM", test_ctr++); + TEST_CHECK(msg, allequal_llong2( (vec_llong2)res_v, (vec_llong2)*((vec_double2 *)&test_a[ii].dbl.ans[0])), 0); + } + + TEST_SET_DONE(); + + TEST_EXIT(); + +} diff --git a/Extras/simdmathlibrary/spu/tests/truncf4.c b/Extras/simdmathlibrary/spu/tests/truncf4.c new file mode 100644 index 0000000..7085ddd --- /dev/null +++ b/Extras/simdmathlibrary/spu/tests/truncf4.c @@ -0,0 +1,108 @@ +/* Test trunf4 for SPU + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include "simdmath.h" +#include "common-test.h" +#include "testutils.h" + + +int main() +{ + TEST_SET_START("20040916100012EJL","EJL", "truncf"); + + unsigned int i3 = 0x4affffff; // 2^23 - 0.5, largest truncatable value. + unsigned int i3i = 0x4afffffe; + unsigned int i4 = 0x4b000000; // 2^23, no fractional part. + unsigned int i5 = 0xcf000001; // -2^31, one more large, and negative, value. + + float x0 = hide_float(0.91825f); + float x0i = hide_float(0.0f); + float x1 = hide_float(-0.12958f); + float x1i = hide_float(0.0f); + float x2 = hide_float(-79615.1875f); + float x2i = hide_float(-79615.0f); + float x3 = hide_float(make_float(i3)); + float x3i = hide_float(make_float(i3i)); + float x4 = hide_float(make_float(i4)); + float x4i = hide_float(make_float(i4)); + float x5 = hide_float(make_float(i5)); + float x5i = hide_float(make_float(i5)); + + vec_float4 x0_v = spu_splats(x0); + vec_float4 x0i_v = spu_splats(x0i); + vec_float4 x1_v = spu_splats(x1); + vec_float4 x1i_v = spu_splats(x1i); + vec_float4 x2_v = spu_splats(x2); + vec_float4 x2i_v = spu_splats(x2i); + vec_float4 x3_v = spu_splats(x3); + vec_float4 x3i_v = spu_splats(x3i); + vec_float4 x4_v = spu_splats(x4); + vec_float4 x4i_v = spu_splats(x4i); + vec_float4 x5_v = spu_splats(x5); + vec_float4 x5i_v = spu_splats(x5i); + + float res; + vec_float4 res_v; + + TEST_START("truncf4"); + res_v = truncf4(x0_v); + TEST_CHECK("20040916100023EJL", allequal_float4( res_v, x0i_v ), 0); + res_v = truncf4(x1_v); + TEST_CHECK("20040916100034EJL", allequal_float4( res_v, x1i_v ), 0); + res_v = truncf4(x2_v); + TEST_CHECK("20040916100043EJL", allequal_float4( res_v, x2i_v ), 0); + res_v = truncf4(x3_v); + TEST_CHECK("20040916100054EJL", allequal_float4( res_v, x3i_v ), 0); + res_v = truncf4(x4_v); + TEST_CHECK("20040916100103EJL", allequal_float4( res_v, x4i_v ), 0); + res_v = truncf4(x5_v); + TEST_CHECK("20040916100111EJL", allequal_float4( res_v, x5i_v ), 0); + + TEST_START("truncf"); + res = truncf(x0); + TEST_CHECK("20040916100121EJL", res == x0i, 0); + res = truncf(x1); + TEST_CHECK("20040916100129EJL", res == x1i, 0); + res = truncf(x2); + TEST_CHECK("20040916100136EJL", res == x2i, 0); + res = truncf(x3); + TEST_CHECK("20040916100144EJL", res == x3i, 0); + res = truncf(x4); + TEST_CHECK("20040916100153EJL", res == x4i, 0); + res = truncf(x5); + TEST_CHECK("20040916100200EJL", res == x5i, 0); + + TEST_SET_DONE(); + + TEST_EXIT(); +} diff --git a/Extras/software_cache/cache/CommonPublicLicense-1.0 b/Extras/software_cache/cache/CommonPublicLicense-1.0 new file mode 100644 index 0000000..c9990a7 --- /dev/null +++ b/Extras/software_cache/cache/CommonPublicLicense-1.0 @@ -0,0 +1,213 @@ +Common Public License Version 1.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC +LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM +CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial code and +documentation distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + + i) changes to the Program, and + + ii) additions to the Program; + + where such changes and/or additions to the Program originate from and are +distributed by that particular Contributor. A Contribution 'originates' from a +Contributor if it was added to the Program by such Contributor itself or anyone +acting on such Contributor's behalf. Contributions do not include additions to +the Program which: (i) are separate modules of software distributed in +conjunction with the Program under their own license agreement, and (ii) are not +derivative works of the Program. + +"Contributor" means any person or entity that distributes the Program. + +"Licensed Patents " mean patent claims licensable by a Contributor which are +necessarily infringed by the use or sale of its Contribution alone or when +combined with the Program. + +"Program" means the Contributions distributed in accordance with this Agreement. + +"Recipient" means anyone who receives the Program under this Agreement, +including all Contributors. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby grants +Recipient a non-exclusive, worldwide, royalty-free copyright license to +reproduce, prepare derivative works of, publicly display, publicly perform, +distribute and sublicense the Contribution of such Contributor, if any, and such +derivative works, in source code and object code form. + + b) Subject to the terms of this Agreement, each Contributor hereby grants +Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed +Patents to make, use, sell, offer to sell, import and otherwise transfer the +Contribution of such Contributor, if any, in source code and object code form. +This patent license shall apply to the combination of the Contribution and the +Program if, at the time the Contribution is added by the Contributor, such +addition of the Contribution causes such combination to be covered by the +Licensed Patents. The patent license shall not apply to any other combinations +which include the Contribution. No hardware per se is licensed hereunder. + + c) Recipient understands that although each Contributor grants the licenses +to its Contributions set forth herein, no assurances are provided by any +Contributor that the Program does not infringe the patent or other intellectual +property rights of any other entity. Each Contributor disclaims any liability to +Recipient for claims brought by any other entity based on infringement of +intellectual property rights or otherwise. As a condition to exercising the +rights and licenses granted hereunder, each Recipient hereby assumes sole +responsibility to secure any other intellectual property rights needed, if any. +For example, if a third party patent license is required to allow Recipient to +distribute the Program, it is Recipient's responsibility to acquire that license +before distributing the Program. + + d) Each Contributor represents that to its knowledge it has sufficient +copyright rights in its Contribution, if any, to grant the copyright license set +forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code form under its +own license agreement, provided that: + + a) it complies with the terms and conditions of this Agreement; and + + b) its license agreement: + + i) effectively disclaims on behalf of all Contributors all warranties and +conditions, express and implied, including warranties or conditions of title and +non-infringement, and implied warranties or conditions of merchantability and +fitness for a particular purpose; + + ii) effectively excludes on behalf of all Contributors all liability for +damages, including direct, indirect, special, incidental and consequential +damages, such as lost profits; + + iii) states that any provisions which differ from this Agreement are offered +by that Contributor alone and not by any other party; and + + iv) states that source code for the Program is available from such +Contributor, and informs licensees how to obtain it in a reasonable manner on or +through a medium customarily used for software exchange. + +When the Program is made available in source code form: + + a) it must be made available under this Agreement; and + + b) a copy of this Agreement must be included with each copy of the Program. + +Contributors may not remove or alter any copyright notices contained within the +Program. + +Each Contributor must identify itself as the originator of its Contribution, if +any, in a manner that reasonably allows subsequent Recipients to identify the +originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities with +respect to end users, business partners and the like. While this license is +intended to facilitate the commercial use of the Program, the Contributor who +includes the Program in a commercial product offering should do so in a manner +which does not create potential liability for other Contributors. Therefore, if +a Contributor includes the Program in a commercial product offering, such +Contributor ("Commercial Contributor") hereby agrees to defend and indemnify +every other Contributor ("Indemnified Contributor") against any losses, damages +and costs (collectively "Losses") arising from claims, lawsuits and other legal +actions brought by a third party against the Indemnified Contributor to the +extent caused by the acts or omissions of such Commercial Contributor in +connection with its distribution of the Program in a commercial product +offering. The obligations in this section do not apply to any claims or Losses +relating to any actual or alleged intellectual property infringement. In order +to qualify, an Indemnified Contributor must: a) promptly notify the Commercial +Contributor in writing of such claim, and b) allow the Commercial Contributor to +control, and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may participate in +any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial product +offering, Product X. That Contributor is then a Commercial Contributor. If that +Commercial Contributor then makes performance claims, or offers warranties +related to Product X, those performance claims and warranties are such +Commercial Contributor's responsibility alone. Under this section, the +Commercial Contributor would have to defend claims against the other +Contributors related to those performance claims and warranties, and if a court +requires any other Contributor to pay any damages as a result, the Commercial +Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each +Recipient is solely responsible for determining the appropriateness of using and +distributing the Program and assumes all risks associated with its exercise of +rights under this Agreement, including but not limited to the risks and costs of +program errors, compliance with applicable laws, damage to or loss of data, +programs or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY +CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS +GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under applicable +law, it shall not affect the validity or enforceability of the remainder of the +terms of this Agreement, and without further action by the parties hereto, such +provision shall be reformed to the minimum extent necessary to make such +provision valid and enforceable. + +If Recipient institutes patent litigation against a Contributor with respect to +a patent applicable to software (including a cross-claim or counterclaim in a +lawsuit), then any patent licenses granted by that Contributor to such Recipient +under this Agreement shall terminate as of the date such litigation is filed. In +addition, if Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the Program +itself (excluding combinations of the Program with other software or hardware) +infringes such Recipient's patent(s), then such Recipient's rights granted under +Section 2(b) shall terminate as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it fails to +comply with any of the material terms or conditions of this Agreement and does +not cure such failure in a reasonable period of time after becoming aware of +such noncompliance. If all Recipient's rights under this Agreement terminate, +Recipient agrees to cease use and distribution of the Program as soon as +reasonably practicable. However, Recipient's obligations under this Agreement +and any licenses granted by Recipient relating to the Program shall continue and +survive. + +Everyone is permitted to copy and distribute copies of this Agreement, but in +order to avoid inconsistency the Agreement is copyrighted and may only be +modified in the following manner. The Agreement Steward reserves the right to +publish new versions (including revisions) of this Agreement from time to time. +No one other than the Agreement Steward has the right to modify this Agreement. +IBM is the initial Agreement Steward. IBM may assign the responsibility to serve +as the Agreement Steward to a suitable separate entity. Each new version of the +Agreement will be given a distinguishing version number. The Program (including +Contributions) may always be distributed subject to the version of the Agreement +under which it was received. In addition, after a new version of the Agreement +is published, Contributor may elect to distribute the Program (including its +Contributions) under the new version. Except as expressly stated in Sections +2(a) and 2(b) above, Recipient receives no rights or licenses to the +intellectual property of any Contributor under this Agreement, whether +expressly, by implication, estoppel or otherwise. All rights in the Program not +expressly granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and the +intellectual property laws of the United States of America. No party to this +Agreement will bring a legal action under this Agreement more than one year +after the cause of action arose. Each party waives its rights to a jury trial in +any resulting litigation. diff --git a/Extras/software_cache/cache/include/Makefile b/Extras/software_cache/cache/include/Makefile new file mode 100644 index 0000000..51c6202 --- /dev/null +++ b/Extras/software_cache/cache/include/Makefile @@ -0,0 +1,28 @@ +# --------------------------------------------------------------- +# PLEASE DO NOT MODIFY THIS SECTION +# This prolog section is automatically generated. +# +# (C) Copyright 2001,2006, +# International Business Machines Corporation, +# +# All Rights Reserved. +# --------------------------------------------------------------- +# PROLOG END TAG zYx + +######################################################################## +# Common Makefile +######################################################################## + +INSTALL_DIR = $(SDKINC_spu)/cache + +INSTALL_FILES := api.h \ + defs.h \ + dma.h \ + nway.h \ + nway-lookup.h \ + nway-miss.h \ + nway-opt.h \ + nway-replace.h \ + spe_cache.h + +include ../../../../../make.footer diff --git a/Extras/software_cache/cache/include/README b/Extras/software_cache/cache/include/README new file mode 100644 index 0000000..85268b8 --- /dev/null +++ b/Extras/software_cache/cache/include/README @@ -0,0 +1,32 @@ +%% --------------------------------------------------------------- +%% PLEASE DO NOT MODIFY THIS SECTION +%% This prolog section is automatically generated. +%% +%% (C) Copyright 2001,2006, +%% International Business Machines Corporation, +%% +%% All Rights Reserved. +%% --------------------------------------------------------------- +%% PROLOG END TAG zYx +This directory contains implementation of software managed cache for +SPE. Whenever possible, the cache interfaces are implemented as macros +or inline-able functions. + +Depending on compile-time settings, different cache implementations can +be selected. + +The include file heirarchy is: + + + spe_cache.h Top level header. + | + + defs.h Common definitions. + + dma.h Initiate DMA transfers. + + nway.h Top level n-way header. + | + + nway-lookup.h n-way lookup operations. + + nway-miss.h n-way cache miss handler. + + nway-replace.h n-way cache replace handler. + + nway-opt.h "optimized" n-way interfaces. + | + + api.h Basic application interfaces. + diff --git a/Extras/software_cache/cache/include/api.h b/Extras/software_cache/cache/include/api.h new file mode 100644 index 0000000..85f70f9 --- /dev/null +++ b/Extras/software_cache/cache/include/api.h @@ -0,0 +1,31 @@ +/* --------------------------------------------------------------- */ +/* PLEASE DO NOT MODIFY THIS SECTION */ +/* This prolog section is automatically generated. */ +/* */ +/* (C) Copyright 2001,2006, */ +/* International Business Machines Corporation, */ +/* */ +/* All Rights Reserved. */ +/* --------------------------------------------------------------- */ +/* PROLOG END TAG zYx */ +/* api.h + * + * Copyright (C) 2005 IBM Corp. + * + * Simple API for software managed cache on SPEs. + * A sophisticated application would not use these, + * but rather use the low-level lookup functions. + */ + +#ifndef __SPE_CACHE_API_H__ +#define __SPE_CACHE_API_H__ + +typedef void *spe_cache_entry_t; + +#define spe_cache_rd(ea) _spe_cache_lookup_xfer_wait_(ea, 0, 1) +#define spe_cache_tr(ea) _spe_cache_lookup_xfer_(ea, 0, 1) +#define spe_cache_lr(ea) _spe_cache_lookup_(ea, 0) + +#define spe_cache_wait(entry) _spe_cache_wait_(entry) + +#endif diff --git a/Extras/software_cache/cache/include/cbe_mfc.h b/Extras/software_cache/cache/include/cbe_mfc.h new file mode 100644 index 0000000..a5ed207 --- /dev/null +++ b/Extras/software_cache/cache/include/cbe_mfc.h @@ -0,0 +1,245 @@ +/* @(#)17 1.4 src/include/cbe_mfc.h, sw.includes, sdk_pub 10/11/05 16:00:25 */ +/* -------------------------------------------------------------- */ +/* (C) Copyright 2001,2005, */ +/* International Business Machines Corporation, */ +/* Sony Computer Entertainment Incorporated, */ +/* Toshiba Corporation. */ +/* */ +/* All Rights Reserved. */ +/* -------------------------------------------------------------- */ +/* PROLOG END TAG zYx */ +#ifndef _CBEA_MFC_H_ +#define _CBEA_MFC_H_ + +/* This header file contains various definitions related to the Memory Flow + * Controller (MFC) portion of the Cell Broadband Engine Architecture (CBEA). + */ + +/**************************************/ +/* MFC DMA Command Opcode Definitions */ +/**************************************/ + +/****************************************************************************/ +/* MFC DMA Command flags which identify classes of operations. */ +/****************************************************************************/ +/* Note: These flags may be used in conjunction with the base command types + * (i.e. MFC_PUT_CMD, MFC_PUTR_CMD, MFC_GET_CMD, and MFC_SNDSIG_CMD) + * to construct the various command permutations. + */ + +#define MFC_BARRIER_ENABLE 0x01 +#define MFC_FENCE_ENABLE 0x02 +#define MFC_LIST_ENABLE 0x04 /* SPU Only */ +#define MFC_START_ENABLE 0x08 /* proxy Only */ +#define MFC_RESULT_ENABLE 0x10 + +/****************************************************************************/ +/* MFC DMA Put Commands */ +/****************************************************************************/ + +#define MFC_PUT_CMD 0x20 +#define MFC_PUTS_CMD 0x28 /* proxy Only */ +#define MFC_PUTR_CMD 0x30 +#define MFC_PUTF_CMD 0x22 +#define MFC_PUTB_CMD 0x21 +#define MFC_PUTFS_CMD 0x2A /* proxy Only */ +#define MFC_PUTBS_CMD 0x29 /* proxy Only */ +#define MFC_PUTRF_CMD 0x32 +#define MFC_PUTRB_CMD 0x31 +#define MFC_PUTL_CMD 0x24 /* SPU Only */ +#define MFC_PUTRL_CMD 0x34 /* SPU Only */ +#define MFC_PUTLF_CMD 0x26 /* SPU Only */ +#define MFC_PUTLB_CMD 0x25 /* SPU Only */ +#define MFC_PUTRLF_CMD 0x36 /* SPU Only */ +#define MFC_PUTRLB_CMD 0x35 /* SPU Only */ + +/****************************************************************************/ +/* MFC DMA Get Commands */ +/****************************************************************************/ + +#define MFC_GET_CMD 0x40 +#define MFC_GETS_CMD 0x48 /* proxy Only */ +#define MFC_GETF_CMD 0x42 +#define MFC_GETB_CMD 0x41 +#define MFC_GETFS_CMD 0x4A /* proxy Only */ +#define MFC_GETBS_CMD 0x49 /* proxy Only */ +#define MFC_GETL_CMD 0x44 /* SPU Only */ +#define MFC_GETLF_CMD 0x46 /* SPU Only */ +#define MFC_GETLB_CMD 0x45 /* SPU Only */ + +/****************************************************************************/ +/* MFC DMA Storage Control Commands */ +/****************************************************************************/ +/* Note: These are only supported on implementations with a SL1 cache + * They are no-ops on the initial (CBE) implementation. + */ + +#define MFC_SDCRT_CMD 0x80 +#define MFC_SDCRTST_CMD 0x81 +#define MFC_SDCRZ_CMD 0x89 +#define MFC_SDCRS_CMD 0x8D +#define MFC_SDCRF_CMD 0x8F + +/****************************************************************************/ +/* MFC Synchronization Commands */ +/****************************************************************************/ + +#define MFC_GETLLAR_CMD 0xD0 /* SPU Only */ +#define MFC_PUTLLC_CMD 0xB4 /* SPU Only */ +#define MFC_PUTLLUC_CMD 0xB0 /* SPU Only */ +#define MFC_PUTQLLUC_CMD 0xB8 /* SPU Only */ + +#define MFC_SNDSIG_CMD 0xA0 +#define MFC_SNDSIGB_CMD 0xA1 +#define MFC_SNDSIGF_CMD 0xA2 +#define MFC_BARRIER_CMD 0xC0 +#define MFC_EIEIO_CMD 0xC8 +#define MFC_SYNC_CMD 0xCC + + +/****************************************************************************/ +/* Definitions for constructing a 32-bit command word including the transfer + * and replacement class id and the command opcode. + */ +/****************************************************************************/ +#define MFC_TCLASS(_tid) ((_tid) << 24) +#define MFC_RCLASS(_rid) ((_rid) << 16) + +#define MFC_CMD_WORD(_tid, _rid, _cmd) (MFC_TCLASS(_tid) | MFC_RCLASS(_rid) | (_cmd)) + +/****************************************************************************/ +/* Definitions for constructing a 64-bit command word including the size, tag, + * transfer and replacement class id and the command opcode. + */ +/****************************************************************************/ +#define MFC_SIZE(_size) ((unsigned long long)(_size) << 48) +#define MFC_TAG(_tag_id) ((unsigned long long)(_tag_id) << 32) +#define MFC_TR_CMD(_trcmd) ((unsigned long long)(_trcmd)) + +#define MFC_CMD_DWORD(_size, _tag_id, _trcmd) (MFC_SIZE(_size) | MFC_TAG(_tag_id) | MFC_TR_CMD(_trcmd)) + +/****************************************************************************/ +/* Mask definitions for obtaining DMA commands and class ids from packed words. + */ +/****************************************************************************/ +#define MFC_CMD_MASK 0x0000FFFF +#define MFC_CLASS_MASK 0x000000FF + +/****************************************************************************/ +/* DMA max/min size definitions. */ +/****************************************************************************/ +#define MFC_MIN_DMA_SIZE_SHIFT 4 /* 16 bytes */ +#define MFC_MAX_DMA_SIZE_SHIFT 14 /* 16384 bytes */ + +#define MFC_MIN_DMA_SIZE (1 << MFC_MIN_DMA_SIZE_SHIFT) +#define MFC_MAX_DMA_SIZE (1 << MFC_MAX_DMA_SIZE_SHIFT) + +#define MFC_MIN_DMA_SIZE_MASK (MFC_MIN_DMA_SIZE - 1) +#define MFC_MAX_DMA_SIZE_MASK (MFC_MAX_DMA_SIZE - 1) + +#define MFC_MIN_DMA_LIST_SIZE 0x0008 /* 8 bytes */ +#define MFC_MAX_DMA_LIST_SIZE 0x4000 /* 16K bytes */ + +/****************************************************************************/ +/* Mask definition for checking proper address alignment. */ +/****************************************************************************/ +#define MFC_ADDR_MATCH_MASK 0xF +#define MFC_BEST_ADDR_ALIGNMENT 0x80 + +/****************************************************************************/ +/* Definitions related to the Proxy DMA Command Status register (DMA_CMDStatus). + */ +/****************************************************************************/ +#define MFC_PROXY_DMA_CMD_ENQUEUE_SUCCESSFUL 0x00 +#define MFC_PROXY_DMA_CMD_SEQUENCE_ERROR 0x01 +#define MFC_PROXY_DMA_QUEUE_FULL 0x02 + +/****************************************************************************/ +/* Definitions related to the DMA Queue Status register (DMA_QStatus). */ +/****************************************************************************/ +#define MFC_PROXY_MAX_QUEUE_SPACE 0x08 +#define MFC_PROXY_DMA_Q_EMPTY 0x80000000 +#define MFC_PROXY_DMA_Q_FREE_SPACE_MASK 0x0000FFFF + +#define MFC_SPU_MAX_QUEUE_SPACE 0x10 + +/****************************************************************************/ +/* Definitions related to the Proxy Tag-Group Query-Type register + * (Prxy_QueryType). + */ +/****************************************************************************/ +#define MFC_PROXY_DMA_QUERYTYPE_ANY 0x1 +#define MFC_PROXY_DMA_QUERYTYPE_ALL 0x2 + +/****************************************************************************/ +/* Definitions related to the Proxy Tag-Group Query-Mask (Prxy_QueryMask) + * and PU Tag Status (DMA_TagStatus) registers. + * + * NOTE: The only use the bottom 5 bits of the tag id value passed to insure + * a valid tag id is used. + */ +/****************************************************************************/ + +#define MFC_TAGID_TO_TAGMASK(tag_id) (1 << (tag_id & 0x1F)) + +/****************************************************************************/ +/* Definitions related to the Mailbox Status register (SPU_Mbox_Stat) and the + * depths of the outbound Mailbox Register (SPU_OutMbox), the outbound + * interrupting Mailbox Register (SPU_OutIntrMbox), and the inbound Mailbox + * Register (SPU_In_Mbox). + */ +/****************************************************************************/ +#define MFC_SPU_OUT_MBOX_COUNT_STATUS_MASK 0x000000FF +#define MFC_SPU_OUT_MBOX_COUNT_STATUS_SHIFT 0x0 +#define MFC_SPU_IN_MBOX_COUNT_STATUS_MASK 0x0000FF00 +#define MFC_SPU_IN_MBOX_COUNT_STATUS_SHIFT 0x8 +#define MFC_SPU_OUT_INTR_MBOX_COUNT_STATUS_MASK 0x00FF0000 +#define MFC_SPU_OUT_INTR_MBOX_COUNT_STATUS_SHIFT 0x10 + +/****************************************************************************/ +/* Definitions related to the SPC Multi Source Syncronization register + * (MFC_MSSync). + */ +/****************************************************************************/ +#define MFC_SPC_MSS_STATUS_MASK 0x1 +#define MFC_SPC_MSS_COMPLETE 0x0 +#define MFC_SPC_MSS_NOT_COMPLETE 0x1 + + +/******************************************* + * Channel Defines + *******************************************/ + +/* Events Defines for channels: + * 0 (SPU_RdEventStat), + * 1 (SPU_WrEventMask), and + * 2 (SPU_WrEventAck). + */ +#define MFC_TAG_STATUS_UPDATE_EVENT 0x00000001 +#define MFC_LIST_STALL_NOTIFY_EVENT 0x00000002 +#define MFC_COMMAND_QUEUE_AVAILABLE_EVENT 0x00000008 +#define MFC_IN_MBOX_AVAILABLE_EVENT 0x00000010 +#define MFC_DECREMENTER_EVENT 0x00000020 +#define MFC_OUT_INTR_MBOX_AVAILABLE_EVENT 0x00000040 +#define MFC_OUT_MBOX_AVAILABLE_EVENT 0x00000080 +#define MFC_SIGNAL_NOTIFY_2_EVENT 0x00000100 +#define MFC_SIGNAL_NOTIFY_1_EVENT 0x00000200 +#define MFC_LLR_LOST_EVENT 0x00000400 +#define MFC_PRIV_ATTN_EVENT 0x00000800 +#define MFC_MULTI_SRC_SYNC_EVENT 0x00001000 + + + +/* Tag Status Update defines for channel 23 (MFC_WrTagUpdate) + */ +#define MFC_TAG_UPDATE_IMMEDIATE 0x0 +#define MFC_TAG_UPDATE_ANY 0x1 +#define MFC_TAG_UPDATE_ALL 0x2 + +/* Atomic Command Status defines for channel 27 (MFC_RdAtomicStat) + */ +#define MFC_PUTLLC_STATUS 0x00000001 +#define MFC_PUTLLUC_STATUS 0x00000002 +#define MFC_GETLLAR_STATUS 0x00000004 + +#endif /* _CBEA_MFC_H_ */ diff --git a/Extras/software_cache/cache/include/defs.h b/Extras/software_cache/cache/include/defs.h new file mode 100644 index 0000000..6b22224 --- /dev/null +++ b/Extras/software_cache/cache/include/defs.h @@ -0,0 +1,149 @@ +/* --------------------------------------------------------------- */ +/* PLEASE DO NOT MODIFY THIS SECTION */ +/* This prolog section is automatically generated. */ +/* */ +/* (C) Copyright 2001,2006, */ +/* International Business Machines Corporation, */ +/* */ +/* All Rights Reserved. */ +/* --------------------------------------------------------------- */ +/* PROLOG END TAG zYx */ +/* spe_cache_defs.h + * + * Copyright (C) 2005 IBM Corp. + * + * Internal definitions for software managed cache. + */ + +#ifndef __SPE_CACHE_DEFS_H__ +#define __SPE_CACHE_DEFS_H__ + +/** + ** Defn's for number of cache sets. + ** Default is 64 sets. + */ +#if (SPE_CACHE_NSETS==1024) +#define SPE_CACHE_NSETS_SHIFT 10 +#elif (SPE_CACHE_NSETS==512) +#define SPE_CACHE_NSETS_SHIFT 9 +#elif (SPE_CACHE_NSETS==256) +#define SPE_CACHE_NSETS_SHIFT 8 +#elif (SPE_CACHE_NSETS==128) +#define SPE_CACHE_NSETS_SHIFT 7 +#elif (SPE_CACHE_NSETS==64) +#define SPE_CACHE_NSETS_SHIFT 6 +#elif (SPE_CACHE_NSETS==32) +#define SPE_CACHE_NSETS_SHIFT 5 +#elif (SPE_CACHE_NSETS==16) +#define SPE_CACHE_NSETS_SHIFT 4 +#elif (SPE_CACHE_NSETS==8) +#define SPE_CACHE_NSETS_SHIFT 3 +#elif (SPE_CACHE_NSETS==4) +#define SPE_CACHE_NSETS_SHIFT 2 +#elif (SPE_CACHE_NSETS==2) +#define SPE_CACHE_NSETS_SHIFT 1 +#else +#undef SPE_CACHE_NSETS +#define SPE_CACHE_NSETS 64 +#define SPE_CACHE_NSETS_SHIFT 6 +#endif + +/** + ** Defn's for cachline size (bytes). + ** Default is 128 bytes. + */ +#if (SPE_CACHELINE_SIZE==512) +#define SPE_CACHELINE_SHIFT 9 +#elif (SPE_CACHELINE_SIZE==256) +#define SPE_CACHELINE_SHIFT 8 +#elif (SPE_CACHELINE_SIZE==128) +#define SPE_CACHELINE_SHIFT 7 +#elif (SPE_CACHELINE_SIZE==64) +#define SPE_CACHELINE_SHIFT 6 +#elif (SPE_CACHELINE_SIZE==32) +#define SPE_CACHELINE_SHIFT 5 +#else +#undef SPE_CACHELINE_SIZE +#define SPE_CACHELINE_SIZE 128 +#define SPE_CACHELINE_SHIFT 7 +#endif + +/** + ** Defn's derived from above settings. + */ +#define SPE_CACHE_NSETS_MASK (SPE_CACHE_NSETS - 1) +#define SPE_CACHELINE_MASK (SPE_CACHELINE_SIZE - 1) + +/** + ** Defn's for managing cacheline state. + */ +#define SPE_CACHELINE_DIRTY 0x1 +#define SPE_CACHELINE_LOCKED 0x2 +#define SPE_CACHELINE_STATE_MASK (SPE_CACHELINE_DIRTY | SPE_CACHELINE_LOCKED) + +#ifdef _XLC +/** + * FIXME: For now disable manual branch hints + * on XLC due to performance degradation. + */ +#ifndef likely +#define likely(_c) (_c) +#define unlikely(_c) (_c) +#endif + +#else /* !_XLC */ + +#ifndef likely +#define likely(_c) __builtin_expect((_c), 1) +#define unlikely(_c) __builtin_expect((_c), 0) +#endif +#endif + + +/** + ** Debug controls. Set -DNDEBUG to + ** disable both panic and assert. + */ +#include +#define _spe_cache_panic_(c) assert(c) +#ifdef SPE_CACHE_DBG +#define _spe_cache_assert_(c) assert(c) +#else +#define _spe_cache_assert_(c) /* No-op. */ +#endif + +#define _spe_cacheline_byte_offset_(ea) \ + ((ea) & SPE_CACHELINE_MASK) + +#define _spe_cacheline_byte_offset_x4(ea) \ + spu_and ((ea), SPE_CACHELINE_MASK) + +#endif + +static __inline vector unsigned int _load_vec_uint4(unsigned int ui1, unsigned int ui2, unsigned int ui3, unsigned int ui4) +{ + vector unsigned int result; + vector unsigned int iv1, iv2, iv3, iv4; + + vector unsigned char shuffle = VEC_LITERAL(vector unsigned char, + 0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80); + iv1 = spu_promote(ui1, 0); + iv2 = spu_promote(ui2, 0); + iv3 = spu_promote(ui3, 0); + iv4 = spu_promote(ui4, 0); + + result = spu_or(spu_shuffle(iv1, iv2, shuffle), spu_shuffle(iv3, iv4, spu_rlqwbyte(shuffle, 8))); + return (result); +} + +static __inline vector unsigned int _pack_vec_uint4(vector unsigned int ui1, vector unsigned int ui2, vector unsigned int ui3, vector unsigned int ui4) +{ + vector unsigned int result; + vector unsigned char shuffle = VEC_LITERAL(vector unsigned char, + 0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80); + + result = spu_or(spu_shuffle(ui1, ui2, shuffle), spu_shuffle(ui3, ui4, spu_rlqwbyte(shuffle, 8))); + return (result); +} diff --git a/Extras/software_cache/cache/include/dma.h b/Extras/software_cache/cache/include/dma.h new file mode 100644 index 0000000..e4ee891 --- /dev/null +++ b/Extras/software_cache/cache/include/dma.h @@ -0,0 +1,40 @@ +/* --------------------------------------------------------------- */ +/* PLEASE DO NOT MODIFY THIS SECTION */ +/* This prolog section is automatically generated. */ +/* */ +/* (C) Copyright 2001,2006, */ +/* International Business Machines Corporation, */ +/* */ +/* All Rights Reserved. */ +/* --------------------------------------------------------------- */ +/* PROLOG END TAG zYx */ +/* dma.h + * + * Copyright (C) 2005 IBM Corp. + * + * Internal DMA utilities for software + * managed cache. + */ + +#ifndef __SPE_CACHE_DMA_H__ +#define __SPE_CACHE_DMA_H__ + +#define SPE_CACHE_TAGID_SHIFT (SPE_CACHELINE_SHIFT + SPE_CACHE_NWAY_SHIFT) + +#define _SPE_CACHELINE_TAGID(_ptr) (16) +#define _SPE_CACHELINE_TAGMASK(_ptr) (1 << 16) + +#define SPE_CACHELINE_TAGID(_line) \ + _SPE_CACHELINE_TAGID(&spe_cache_mem[_line]) +#define SPE_CACHELINE_TAGMASK(_line) \ + _SPE_CACHELINE_TAGMASK(&spe_cache_mem[_line]) + +#ifndef SPE_CACHE_SET_TAGID +#define SPE_CACHE_SET_TAGID(set) ((set) & 0x1f) +#endif +#define SPE_CACHE_SET_TAGMASK(set) (1 << SPE_CACHE_SET_TAGID(set)) + +#define SPE_CACHE_PUT MFC_PUTF_CMD +#define SPE_CACHE_GET MFC_GET_CMD + +#endif diff --git a/Extras/software_cache/cache/include/ilog2.h b/Extras/software_cache/cache/include/ilog2.h new file mode 100644 index 0000000..37fa2c6 --- /dev/null +++ b/Extras/software_cache/cache/include/ilog2.h @@ -0,0 +1,35 @@ +/* @(#)12 1.5 src/lib/math/ilog2.h, sw.lib, sdk_pub 10/11/05 15:35:56 */ +/* -------------------------------------------------------------- */ +/* (C) Copyright 2001,2005, */ +/* International Business Machines Corporation, */ +/* Sony Computer Entertainment Incorporated, */ +/* Toshiba Corporation. */ +/* */ +/* All Rights Reserved. */ +/* -------------------------------------------------------------- */ +/* PROLOG END TAG zYx */ +#ifndef _ILOG2_H_ +#define _ILOG2_H_ 1 + +/* + * FUNCTION + * signed int _ilog2(signed int x) + * + * DESCRIPTION + * _ilog2 computes ceiling of log (base 2) of the input value x. + * The input value, x, must be a non-zero positive value. + */ + +static __inline signed int _ilog2(signed int x) +{ +#ifdef __SPU__ + return (32 - spu_extract(spu_cntlz(spu_promote(x - 1, 0)), 0)); +#else + signed int result; + + for (result=0, x--; x > 0; result++, x>>=1); + return (result); +#endif +} + +#endif /* _ILOG2_H_ */ diff --git a/Extras/software_cache/cache/include/memset.h b/Extras/software_cache/cache/include/memset.h new file mode 100644 index 0000000..5dbdbac --- /dev/null +++ b/Extras/software_cache/cache/include/memset.h @@ -0,0 +1,68 @@ +/* @(#)85 1.4 src/lib/c/memset.h, sw.lib, sdk_pub 10/13/05 10:17:09 */ +/* -------------------------------------------------------------- */ +/* (C) Copyright 2001,2005, */ +/* International Business Machines Corporation, */ +/* Sony Computer Entertainment Incorporated, */ +/* Toshiba Corporation. */ +/* */ +/* All Rights Reserved. */ +/* -------------------------------------------------------------- */ +/* PROLOG END TAG zYx */ +#include +#include + +/* Fills the first n bytes of the memory area pointed to by s + * with the constant byte c. Returns a pointer to the memory area s. + */ +static __inline void * _memset(void *s, int c, size_t n) +{ + int skip, cnt, i; + vec_uchar16 *vs; + vec_uchar16 vc, mask; + + vs = (vec_uchar16 *)(s); + vc = spu_splats((unsigned char)c); + cnt = (int)(n); + + /* Handle any leading partial quadwords as well a + * very short settings (ie, such that the n characters + * all reside in a single quadword. + */ + skip = (int)(s) & 15; + if (skip) { + mask = spu_rlmaskqwbyte((vec_uchar16)(-1), 0-skip); + cnt -= 16 - skip; + if (cnt < 0) { + mask = spu_and(mask, spu_slqwbyte((vec_uchar16)(-1), (unsigned int)(-cnt))); + } + *vs = spu_sel(*vs, vc, mask); + vs++; + } + + /* Handle 8 quadwords at a time + */ + for (i=127; i 0) { + mask = spu_slqwbyte((vec_uchar16)(-1), (unsigned int)(16-cnt)); + *vs = spu_sel(*vs, vc, mask); + } + + return (s); +} diff --git a/Extras/software_cache/cache/include/nway-lookup.h b/Extras/software_cache/cache/include/nway-lookup.h new file mode 100644 index 0000000..c12218f --- /dev/null +++ b/Extras/software_cache/cache/include/nway-lookup.h @@ -0,0 +1,194 @@ +/* --------------------------------------------------------------- */ +/* PLEASE DO NOT MODIFY THIS SECTION */ +/* This prolog section is automatically generated. */ +/* */ +/* (C) Copyright 2001,2006, */ +/* International Business Machines Corporation, */ +/* */ +/* All Rights Reserved. */ +/* --------------------------------------------------------------- */ +/* PROLOG END TAG zYx */ +/* nway-lookup.h + * + * Copyright (C) 2005 IBM Corp. + * + * Internal lookup operations for software + * managed cache. + * + * See nway-opt.h for "optimized" nway + * lookup operations. + */ + +#ifndef __SPE_CACHE_NWAY_LOOKUP_H_ +#define __SPE_CACHE_NWAY_LOOKUP_H_ + + +/** + * _decl_set_entries_ + * Load up set entries (by 4) from an n-way + * set associative cache. Mask off the dirty + * bit, as needed. + */ +#define _decl_set_entries_(set, name, index) \ + vec_uint4 name = *((vec_uint4 *) &spe_cache_dir[set][index]) + + +#define _spe_cache_4_way_lookup_(set, ea) \ +({ \ + _decl_set_entries_(set, e0123, 0); \ + spu_gather(spu_cmpeq(e0123, ea)); \ +}) + +/** + * _spe_cache_set_lookup_ + * Compare 'ea' against all entries of + * a set, and return a result that is + * consistent with spu_gather(). + */ +#define _spe_cache_set_lookup_(set, ea) \ + _spe_cache_4_way_lookup_(set, ea) + + +/** + * _spe_cache_nway_lookup_x4_ + * Declare local variables and lookup four addresses + * in the n-way set associative cache. Upon return, + * 'idx_x4' contains the matching elements in the sets, + * or -1 if not found. + */ +#define _spe_cache_nway_lookup_x4(ea_x4, set_x4, idx_x4) \ +({ \ + vector unsigned int ea_aligned_x4 = spu_and ((ea_x4), ~SPE_CACHELINE_MASK); \ + vector unsigned char splat0 = VEC_LITERAL(vector unsigned char, \ + 0x00, 0x01, 0x02, 0x03, \ + 0x00, 0x01, 0x02, 0x03, \ + 0x00, 0x01, 0x02, 0x03, \ + 0x00, 0x01, 0x02, 0x03); \ + vector unsigned char splat1 = VEC_LITERAL(vector unsigned char, \ + 0x04, 0x05, 0x06, 0x07, \ + 0x04, 0x05, 0x06, 0x07, \ + 0x04, 0x05, 0x06, 0x07, \ + 0x04, 0x05, 0x06, 0x07); \ + vector unsigned char splat2 = VEC_LITERAL(vector unsigned char, \ + 0x08, 0x09, 0x0a, 0x0b, \ + 0x08, 0x09, 0x0a, 0x0b, \ + 0x08, 0x09, 0x0a, 0x0b, \ + 0x08, 0x09, 0x0a, 0x0b); \ + vector unsigned char splat3 = VEC_LITERAL(vector unsigned char, \ + 0x0c, 0x0d, 0x0e, 0x0f, \ + 0x0c, 0x0d, 0x0e, 0x0f, \ + 0x0c, 0x0d, 0x0e, 0x0f, \ + 0x0c, 0x0d, 0x0e, 0x0f); \ + vec_uint4 ea_aligned0 = spu_shuffle(ea_aligned_x4, ea_aligned_x4, splat0); \ + vec_uint4 ea_aligned1 = spu_shuffle(ea_aligned_x4, ea_aligned_x4, splat1); \ + vec_uint4 ea_aligned2 = spu_shuffle(ea_aligned_x4, ea_aligned_x4, splat2); \ + vec_uint4 ea_aligned3 = spu_shuffle(ea_aligned_x4, ea_aligned_x4, splat3); \ + vec_uint4 found0, found1, found2, found3; \ + vec_uint4 found_x4; \ + (set_x4) = _spe_cache_set_num_x4(ea_x4); \ + found0 = _spe_cache_set_lookup_(spu_extract (set_x4, 0), ea_aligned0); \ + found1 = _spe_cache_set_lookup_(spu_extract (set_x4, 1), ea_aligned1); \ + found2 = _spe_cache_set_lookup_(spu_extract (set_x4, 2), ea_aligned2); \ + found3 = _spe_cache_set_lookup_(spu_extract (set_x4, 3), ea_aligned3); \ + found_x4 = _pack_vec_uint4 (found0, found1, found2, found3); \ + (idx_x4) = (vector signed int)_spe_cache_idx_num_x4(found_x4); \ +}) + +#define _spe_cache_nway_lookup_(ea, set, idx) \ +({ \ + unsigned int ea_aligned = (ea) & ~SPE_CACHELINE_MASK; \ + vec_uint4 ea_aligned4 = spu_splats(ea_aligned); \ + vec_uint4 found; \ + (set) = _spe_cache_set_num_(ea); \ + found = _spe_cache_set_lookup_(set, ea_aligned4); \ + (idx) = _spe_cache_idx_num_(found); \ +}) + +/** + * _spe_cache_lookup_ + * Lookup and return the LSA of an EA + * that is known to be in the cache. + */ +#define _spe_cache_lookup_(ea, is_write) \ +({ \ + int set, idx, line, byte; \ + _spe_cache_nway_lookup_(ea, set, idx); \ + \ + line = _spe_cacheline_num_(set, idx); \ + byte = _spe_cacheline_byte_offset_(ea); \ + (void *) &spe_cache_mem[line + byte]; \ +}) + +/** + * _spe_cache_wait_ + * Wait for transfer of a cache line + * to complete. + */ +#define _spe_cache_wait_(_lsa) \ +({ \ + spu_writech(22, _SPE_CACHELINE_TAGMASK(_lsa)); \ + spu_mfcstat(MFC_TAG_UPDATE_ALL); \ +}) + +/** + * _spe_cache_lookup_wait_ + * Lookup and return the LSA of an EA + * that is known to be in the cache, + * and guarantee that its transfer is + * complete. + */ +#define _spe_cache_lookup_wait_(ea, is_write) \ +({ \ + int set, idx, line, byte; \ + _spe_cache_nway_lookup_(ea, set, idx); \ + \ + line = _spe_cacheline_num_(set, idx); \ + byte = _spe_cacheline_byte_offset_(ea); \ + spu_writech(22, SPE_CACHE_SET_TAGMASK(set)); \ + spu_mfcstat(MFC_TAG_UPDATE_ALL); \ + (void *) &spe_cache_mem[line + byte]; \ +}) + +/** + * _spe_cache_lookup_xfer_ + * Lookup and return the LSA of an EA, where + * the line may either be in the cache or not. + * If not, initiate transfer but do not wait + * for completion. + */ +#define _spe_cache_lookup_xfer_(ea, is_write, rb) \ +({ \ + int set, idx, line, byte; \ + _spe_cache_nway_lookup_(ea, set, idx); \ + \ + if (unlikely(idx < 0)) { \ + idx = _spe_cache_miss_(ea, set, -1); \ + } \ + line = _spe_cacheline_num_(set, idx); \ + byte = _spe_cacheline_byte_offset_(ea); \ + (void *) &spe_cache_mem[line + byte]; \ +}) + +/** + * _spe_cache_lookup_xfer_wait_ + * Lookup and return the LSA of an EA, where + * the line may either be in the cache or not. + * If not, initiate transfer and guarantee + * completion. + */ +#define _spe_cache_lookup_xfer_wait_(ea, is_write, rb) \ +({ \ + int set, idx, line, byte; \ + _spe_cache_nway_lookup_(ea, set, idx); \ + \ + if (unlikely(idx < 0)) { \ + idx = _spe_cache_miss_(ea, set, -1); \ + spu_writech(22, SPE_CACHE_SET_TAGMASK(set)); \ + spu_mfcstat(MFC_TAG_UPDATE_ALL); \ + } \ + line = _spe_cacheline_num_(set, idx); \ + byte = _spe_cacheline_byte_offset_(ea); \ + (void *) &spe_cache_mem[line + byte]; \ +}) + +#endif diff --git a/Extras/software_cache/cache/include/nway-miss.h b/Extras/software_cache/cache/include/nway-miss.h new file mode 100644 index 0000000..dfe50f2 --- /dev/null +++ b/Extras/software_cache/cache/include/nway-miss.h @@ -0,0 +1,51 @@ +/* --------------------------------------------------------------- */ +/* PLEASE DO NOT MODIFY THIS SECTION */ +/* This prolog section is automatically generated. */ +/* */ +/* (C) Copyright 2001,2006, */ +/* International Business Machines Corporation, */ +/* */ +/* All Rights Reserved. */ +/* --------------------------------------------------------------- */ +/* PROLOG END TAG zYx */ +/* nway-miss.h + * + * Copyright (C) 2005 IBM Corp. + * + * Internal handler for cache misses. + */ + +#ifndef __SPE_CACHE_NWAY_MISS_H__ +#define __SPE_CACHE_NWAY_MISS_H__ + +static int _spe_cache_miss_(unsigned int ea, int set, int avail) +{ + unsigned int ea_aligned = ea & ~SPE_CACHELINE_MASK; + vec_uint4 slot; + vec_uint4 exists = _spe_cache_set_lookup_(set, ea_aligned); + int idx, line; + + /* Double check to make sure that the entry has not + * already been allocated in this set. This condition + * might occur if multiple lookups are being perfomed + * simultaneously. + */ + if (unlikely(spu_extract(exists, 0) != 0)) { + return _spe_cache_idx_num_(exists); + } + + /* Now check to see if there are empty slots + * that are available in the set. + */ + slot = _spe_cache_replace_(set, avail); + idx = _spe_cache_idx_num_(slot); + line = _spe_cacheline_num_(set, idx); + + spu_mfcdma32(&spe_cache_mem[line], ea_aligned, SPE_CACHELINE_SIZE, + SPE_CACHE_SET_TAGID(set), SPE_CACHE_GET); + + spe_cache_dir[set][SPE_CACHE_NWAY_MASK - idx] = ea_aligned; + + return idx; +} +#endif diff --git a/Extras/software_cache/cache/include/nway-opt.h b/Extras/software_cache/cache/include/nway-opt.h new file mode 100644 index 0000000..ec3993a --- /dev/null +++ b/Extras/software_cache/cache/include/nway-opt.h @@ -0,0 +1,153 @@ +/* --------------------------------------------------------------- */ +/* PLEASE DO NOT MODIFY THIS SECTION */ +/* This prolog section is automatically generated. */ +/* */ +/* (C) Copyright 2001,2006, */ +/* International Business Machines Corporation, */ +/* */ +/* All Rights Reserved. */ +/* --------------------------------------------------------------- */ +/* PROLOG END TAG zYx */ +/* nway-opt.h + * + * Copyright (C) 2006 IBM Corp. + * + * "Optimized" lookup operations for n-way set associative + * software managed cache. + */ +#include + +#ifndef __SPE_CACHE_NWAY_OPT_H_ +#define __SPE_CACHE_NWAY_OPT_H_ + +/* __spe_cache_rd + * Look up and return data from the cache. If the data + * is not currently in cache then transfer it from main + * storage. + * + * This code uses a conditional branch to the cache miss + * handler in the event that the requested data is not + * in the cache. A branch hint is used to avoid paying + * the branch stall penalty. + */ +#define __spe_cache_rd(type, ea) \ +({ \ + int set, idx, lnum, byte; \ + type ret; \ + _spe_cache_nway_lookup_(ea, set, idx); \ + if (unlikely(idx < 0)) { \ + idx = _spe_cache_miss_(ea, set, -1); \ + spu_writech(22, SPE_CACHE_SET_TAGMASK(set)); \ + spu_mfcstat(MFC_TAG_UPDATE_ALL); \ + } \ + lnum = _spe_cacheline_num_(set, idx); \ + byte = _spe_cacheline_byte_offset_(ea); \ + ret = *((type *) (&spe_cache_mem[lnum + byte])); \ + ret; \ +}) + +/** + * __spe_cache_rd_x4 + * Fetch four data elements from the cache. + * + * This code uses one conditional branch in + * the event that any of the four elements + * are missing. + * + * On a miss, light weight locking is used to + * avoid casting out entries that were found. + * Further, we wait just once for the transfers, + * allowing for parallel [rather than serial] + * transfers. + */ + +#define __spe_cache_rd_x4(type, ea_x4) \ +({ \ + vector unsigned int missing; \ + unsigned int ms; \ + vector unsigned int cindex; \ + unsigned int d0, d1, d2, d3; \ + vector unsigned int s_x4; \ + vector signed int i_x4; \ + vector unsigned int ibyte, iline; \ + vector unsigned int ret; \ + unsigned int idx0, idx1, idx2, idx3; \ + \ + _spe_cache_nway_lookup_x4(ea_x4, s_x4, i_x4); \ + missing = spu_rlmask ((vector unsigned int)i_x4, -8); \ + ms = spu_extract (spu_gather (missing), 0); \ + \ + ibyte = _spe_cacheline_byte_offset_x4(ea_x4); \ + \ + iline = _spe_cacheline_num_x4(s_x4, \ + (vector unsigned int)i_x4); \ + \ + cindex = spu_add (iline, ibyte); \ + \ + idx0 = spu_extract (cindex, 0); \ + idx1 = spu_extract (cindex, 1); \ + idx2 = spu_extract (cindex, 2); \ + idx3 = spu_extract (cindex, 3); \ + \ + d0 = *((type *) (&spe_cache_mem[idx0])); \ + d1 = *((type *) (&spe_cache_mem[idx1])); \ + d2 = *((type *) (&spe_cache_mem[idx2])); \ + d3 = *((type *) (&spe_cache_mem[idx3])); \ + \ + ret = _load_vec_uint4 (d0, d1, d2, d3); \ + \ + if (unlikely(ms)) { \ + int b0 = spu_extract (ibyte, 0); \ + int b1 = spu_extract (ibyte, 1); \ + int b2 = spu_extract (ibyte, 2); \ + int b3 = spu_extract (ibyte, 3); \ + int lnum0; \ + int lnum1; \ + int lnum2; \ + int lnum3; \ + int s0 = spu_extract (s_x4, 0); \ + int s1 = spu_extract (s_x4, 1); \ + int s2 = spu_extract (s_x4, 2); \ + int s3 = spu_extract (s_x4, 3); \ + int i0 = spu_extract (i_x4, 0); \ + int i1 = spu_extract (i_x4, 1); \ + int i2 = spu_extract (i_x4, 2); \ + int i3 = spu_extract (i_x4, 3); \ + unsigned int ea0 = spu_extract(ea_x4, 0); \ + unsigned int ea1 = spu_extract(ea_x4, 1); \ + unsigned int ea2 = spu_extract(ea_x4, 2); \ + unsigned int ea3 = spu_extract(ea_x4, 3); \ + int avail = -1; \ + \ + avail &= ~(((i0 < 0) ? 0 : (1 << i0)) | \ + ((i1 < 0) ? 0 : (1 << i1)) | \ + ((i2 < 0) ? 0 : (1 << i2)) | \ + ((i3 < 0) ? 0 : (1 << i3))); \ + \ + i0 = _spe_cache_miss_(ea0, s0, avail); \ + avail &= ~(1 << i0); \ + i1 = _spe_cache_miss_(ea1, s1, avail); \ + avail &= ~(1 << i1); \ + i2 = _spe_cache_miss_(ea2, s2, avail); \ + avail &= ~(1 << i2); \ + i3 = _spe_cache_miss_(ea3, s3, avail); \ + \ + lnum0 = _spe_cacheline_num_(s0, i0); \ + lnum1 = _spe_cacheline_num_(s1, i1); \ + lnum2 = _spe_cacheline_num_(s2, i2); \ + lnum3 = _spe_cacheline_num_(s3, i3); \ + \ + spu_writech(22, SPE_CACHE_SET_TAGMASK(set)); \ + spu_mfcstat(MFC_TAG_UPDATE_ALL); \ + \ + d0 = *((type *) (&spe_cache_mem[lnum0 + b0])); \ + d1 = *((type *) (&spe_cache_mem[lnum1 + b1])); \ + d2 = *((type *) (&spe_cache_mem[lnum2 + b2])); \ + d3 = *((type *) (&spe_cache_mem[lnum3 + b3])); \ + \ + ret = _load_vec_uint4 (d0, d1, d2, d3); \ + } \ + ret; \ +}) + +#endif /* _SPE_CACHE_NWAY_OPT_H_ */ diff --git a/Extras/software_cache/cache/include/nway-replace.h b/Extras/software_cache/cache/include/nway-replace.h new file mode 100644 index 0000000..213301c --- /dev/null +++ b/Extras/software_cache/cache/include/nway-replace.h @@ -0,0 +1,38 @@ +/* --------------------------------------------------------------- */ +/* PLEASE DO NOT MODIFY THIS SECTION */ +/* This prolog section is automatically generated. */ +/* */ +/* (C) Copyright 2001,2006, */ +/* International Business Machines Corporation, */ +/* */ +/* All Rights Reserved. */ +/* --------------------------------------------------------------- */ +/* PROLOG END TAG zYx */ +/* nway-replace.h + * + * Copyright (C) 2005 IBM Corp. + * + * Implement replacement for software + * managed cache. + */ + +#ifndef __SPE_CACHE_NWAY_REPLACE_H_ +#define __SPE_CACHE_NWAY_REPLACE_H_ + +static vec_uint4 spe_cache_replace_cntr[SPE_CACHE_NSETS+1]; + +static inline vec_uint4 _spe_cache_replace_(int set, int avail) +{ + unsigned int mask = ((1 << SPE_CACHE_NWAY) - 1) & avail; + unsigned int curr, currbit, next; + + curr = spu_extract(spe_cache_replace_cntr[set], 0) & SPE_CACHE_NWAY_MASK; + currbit = (1 << curr); + next = (curr + 1) & SPE_CACHE_NWAY_MASK; + spe_cache_replace_cntr[set] = (vec_uint4) spu_promote(next, 0); + mask = (mask & currbit) ? currbit : mask; + + return (vec_uint4) spu_promote(mask, 0); +} + +#endif diff --git a/Extras/software_cache/cache/include/nway.h b/Extras/software_cache/cache/include/nway.h new file mode 100644 index 0000000..0b37817 --- /dev/null +++ b/Extras/software_cache/cache/include/nway.h @@ -0,0 +1,105 @@ +/* --------------------------------------------------------------- */ +/* PLEASE DO NOT MODIFY THIS SECTION */ +/* This prolog section is automatically generated. */ +/* */ +/* (C) Copyright 2001,2006, */ +/* International Business Machines Corporation, */ +/* */ +/* All Rights Reserved. */ +/* --------------------------------------------------------------- */ +/* PROLOG END TAG zYx */ +/* nway.h + * + * Copyright (C) 2005 IBM Corp. + * + * Support for n-way set associative software + * managed cache. The 4-way associative cache + * is the only interface exposed currently. + */ + +#ifndef __SPE_CACHE_NWAY_H_ +#define __SPE_CACHE_NWAY_H_ + +/** + ** Defn's for n-way set associativity. + ** Default is 4-way. + */ +#define SPE_CACHE_NWAY 4 +#define SPE_CACHE_NWAY_SHIFT 2 + +#define SPE_CACHE_NWAY_MASK (SPE_CACHE_NWAY - 1) +#define SPE_CACHE_NENTRIES (SPE_CACHE_NWAY * SPE_CACHE_NSETS) +#define SPE_CACHE_MEM_SIZE (SPE_CACHE_NENTRIES * SPE_CACHELINE_SIZE) + +#define _spe_cache_set_num_(ea) \ +({ \ + unsigned int ead, eadm, ret; \ + ead = ((ea) >> SPE_CACHELINE_SHIFT); \ + eadm = ((ea) >> (SPE_CACHELINE_SHIFT+2)); \ + ret = (ead ^ eadm) & SPE_CACHE_NSETS_MASK; \ + ret; \ +}) + +#define _spe_cache_set_num_x4(ea_x4) \ +({ \ + vector unsigned int tmp0; \ + vector unsigned int tmp1; \ + tmp0 = spu_rlmask (ea_x4, -SPE_CACHELINE_SHIFT); \ + tmp1 = spu_rlmask (ea_x4, -(SPE_CACHELINE_SHIFT+1)); \ + spu_and (spu_xor (tmp0, tmp1), SPE_CACHE_NSETS_MASK); \ +}) + +#define _spe_cache_idx_num_x4(found) \ + spu_sub((unsigned int) 31, spu_cntlz(found)) + +#define _spe_cache_idx_num_(found) \ + spu_extract(spu_sub((unsigned int) 31, spu_cntlz(found)), 0) + +#define _spe_cacheline_num_(set, idx) \ + (((set << SPE_CACHE_NWAY_SHIFT) + idx) << SPE_CACHELINE_SHIFT) + +#define _spe_cacheline_num_x4(set, idx) \ + spu_sl (spu_add (spu_sl (set, SPE_CACHE_NWAY_SHIFT), idx), SPE_CACHELINE_SHIFT) + +#define _spe_cacheline_is_dirty_(set, idx) \ + (spe_cache_dir[set][SPE_CACHE_NWAY_MASK-(idx)] & SPE_CACHELINE_DIRTY) + +#define _spe_cacheline_is_locked_(set, idx) \ + (spe_cache_dir[set][SPE_CACHE_NWAY_MASK-(idx)] & SPE_CACHELINE_LOCKED) + +#define _spe_lock_cacheline_(set, idx) \ + spe_cache_dir[set][SPE_CACHE_NWAY_MASK-(idx)] |= SPE_CACHELINE_LOCKED + +#define _spe_unlock_cacheline_(set, idx) \ + spe_cache_dir[set][SPE_CACHE_NWAY_MASK-(idx)] &= ~SPE_CACHELINE_LOCKED + + +/** + * spe_cache_dir + * This is the n-way set associative cache + * directory. Entries are either zero (unused) + * or non-zero (used). + * + * State for one additional (dummy) set is + * allocated to improve efficiency of cache + * line locking. + * volatile seems not to be necessary here, the SCE toolchain guarantees a barrier after dma transfer + */ +static unsigned int spe_cache_dir[SPE_CACHE_NSETS+1][SPE_CACHE_NWAY] + __attribute__ ((aligned(16))); + +/** + * spe_cache_mem + * A contiguous set of cachelines in LS memory, + * one line for each entry in the cache. + * volatile seems not to be necessary here, the SCE toolchain guarantees a barrier after dma transfer + */ +static char spe_cache_mem[SPE_CACHE_MEM_SIZE] + __attribute__ ((aligned(128))); + +#include "nway-lookup.h" +#include "nway-replace.h" +#include "nway-miss.h" +#include "nway-opt.h" + +#endif diff --git a/Extras/software_cache/cache/include/spe_cache.h b/Extras/software_cache/cache/include/spe_cache.h new file mode 100644 index 0000000..89b0bbb --- /dev/null +++ b/Extras/software_cache/cache/include/spe_cache.h @@ -0,0 +1,32 @@ +/* --------------------------------------------------------------- */ +/* PLEASE DO NOT MODIFY THIS SECTION */ +/* This prolog section is automatically generated. */ +/* */ +/* (C) Copyright 2001,2006, */ +/* International Business Machines Corporation, */ +/* */ +/* All Rights Reserved. */ +/* --------------------------------------------------------------- */ +/* PROLOG END TAG zYx */ +/* spe_cache.h + * + * Copyright (C) 2005 IBM Corp. + * + * Top level include file implementing + * software managed cache. + */ + +#ifndef __SPE_CACHE_H__ +#define __SPE_CACHE_H__ 1 + +#include "vec_literal.h" +#include "ilog2.h" +#include "memset.h" +//#include + +#include "defs.h" +#include "dma.h" +#include "nway.h" +#include "api.h" + +#endif diff --git a/Extras/software_cache/cache/include/vec_literal.h b/Extras/software_cache/cache/include/vec_literal.h new file mode 100644 index 0000000..c58e1b5 --- /dev/null +++ b/Extras/software_cache/cache/include/vec_literal.h @@ -0,0 +1,74 @@ +/* @(#)86 1.3 src/include/vec_literal.h, sw.includes, sdk_pub 10/11/05 16:00:27 */ +/* -------------------------------------------------------------- */ +/* (C) Copyright 2001,2005, */ +/* International Business Machines Corporation, */ +/* Sony Computer Entertainment Incorporated, */ +/* Toshiba Corporation. */ +/* */ +/* All Rights Reserved. */ +/* -------------------------------------------------------------- */ +/* PROLOG END TAG zYx */ +#ifndef _VEC_LITERAL_H_ +#define _VEC_LITERAL_H_ + +/* This header files provides an abstraction for the various implementations + * of vector literal construction. The two formats are: + * + * 1) Altivec styled using parenthesis + * 2) C grammer friendly styled using curly braces + * + * The macro, VEC_LITERAL has been developed to provide some portability + * in these two styles. To achieve true portability, user must specify all + * elements of the vector being initialized. A single element can be provided + * but only the first element guarenteed across both construction styles. + * + * The VEC_SPLAT_* macros have been provided for portability of vector literal + * construction when all the elements of the vector contain the same value. + */ + +#ifdef __SPU__ +#include +#endif + + +#ifdef __ALTIVEC_LITERAL_STYLE__ +/* Use altivec style. + */ +#define VEC_LITERAL(_type, ...) ((_type)(__VA_ARGS__)) + +#define VEC_SPLAT_U8(_val) ((vector unsigned char)(_val)) +#define VEC_SPLAT_S8(_val) ((vector signed char)(_val)) + +#define VEC_SPLAT_U16(_val) ((vector unsigned short)(_val)) +#define VEC_SPLAT_S16(_val) ((vector signed short)(_val)) + +#define VEC_SPLAT_U32(_val) ((vector unsigned int)(_val)) +#define VEC_SPLAT_S32(_val) ((vector signed int)(_val)) +#define VEC_SPLAT_F32(_val) ((vector float)(_val)) + +#define VEC_SPLAT_U64(_val) ((vector unsigned long long)(_val)) +#define VEC_SPLAT_S64(_val) ((vector signed long long)(_val)) +#define VEC_SPLAT_F64(_val) ((vector double)(_val)) + +#else +/* Use curly brace style. + */ +#define VEC_LITERAL(_type, ...) ((_type){__VA_ARGS__}) + +#define VEC_SPLAT_U8(_val) ((vector unsigned char){_val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val}) +#define VEC_SPLAT_S8(_val) ((vector signed char){_val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val}) + +#define VEC_SPLAT_U16(_val) ((vector unsigned short){_val, _val, _val, _val, _val, _val, _val, _val}) +#define VEC_SPLAT_S16(_val) ((vector signed short){_val, _val, _val, _val, _val, _val, _val, _val}) + +#define VEC_SPLAT_U32(_val) ((vector unsigned int){_val, _val, _val, _val}) +#define VEC_SPLAT_S32(_val) ((vector signed int){_val, _val, _val, _val}) +#define VEC_SPLAT_F32(_val) ((vector float){_val, _val, _val, _val}) + +#define VEC_SPLAT_U64(_val) ((vector unsigned long long){_val, _val}) +#define VEC_SPLAT_S64(_val) ((vector signed long long){_val, _val}) +#define VEC_SPLAT_F64(_val) ((vector double){_val, _val}) + +#endif + +#endif /* _VEC_LITERAL_H_ */ diff --git a/Extras/sph/READ_ME.txt b/Extras/sph/READ_ME.txt new file mode 100644 index 0000000..59546ca --- /dev/null +++ b/Extras/sph/READ_ME.txt @@ -0,0 +1,35 @@ + +FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU +Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com + +A fast CPU and GPU fluid simulator. See website above for details. + +Notes +(April 2009) +------------------- + +- Press 'h' for help screen. This shows keyboard cmds available. + +- By default, GPU simulation is off. + When running the fluid_gpu.exe, press 'g' to start/stop GPU simulation. + +- Disabling shadows in common_defs.h will greatly speed up the simulation + (You can also press 's' to render without shadows) + +- As of April 2009, CUDA builds only under Visual Studio 2005, not VS 2008. + To enable the CUDA build in VS2005, set the BUILD_CUDA define in common_defs.h + Be sure this is turned off if you build with VS2008. + +- The GPU integrator is not yet complete. Integration always takes place on the CPU, in both CPU and GPU modes. (As a result, this forces a bus transfer to and from the GPU per cycle. Once the integrator is finished, GPU simulation performance should increase significantly.) + +- Occassionally, the GPU simulation with crash cuda, causing the screen to blink and particles to move randomly. This is believed to be due to a not-yet-found out of bounds condition. + +ZLib License +------------------- +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. \ No newline at end of file diff --git a/Extras/sph/cmp.sh b/Extras/sph/cmp.sh new file mode 100644 index 0000000..97c0352 --- /dev/null +++ b/Extras/sph/cmp.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +g++ -O3 -L./common -I./common -L./particles -I./particles -lGL -lglut common/matrix.cpp common/mdebug.cpp common/merror.cpp common/vector.cpp common/mtime.cpp particles/particle.cpp particles/particle_system.cpp GLee.c main.cpp +g++ -g -L./common -I./common -L./particles -I./particles -lGL -lglut common/matrix.cpp common/mdebug.cpp common/merror.cpp common/vector.cpp common/mtime.cpp particles/particle.cpp particles/particle_system.cpp GLee.c main.cpp -o sph_sim.debug + diff --git a/Extras/sph/common/GLee.c b/Extras/sph/common/GLee.c new file mode 100644 index 0000000..245b04d --- /dev/null +++ b/Extras/sph/common/GLee.c @@ -0,0 +1,18170 @@ +/*************************************************************************** +* +* GLee.c +* GLee (OpenGL Easy Extension library) +* Version : 5.4 +* +* Copyright (c)2009 Ben Woodhouse All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer as +* the first lines of this file unmodified. +* 2. 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. +* +* THIS SOFTWARE IS PROVIDED BY BEN WOODHOUSE ``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 BEN WOODHOUSE 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. + +* Web: http://elf-stone.com/glee.php +* +* [This file was automatically generated by GLeeGen 7.0 +* +***************************************************************************/ + +#ifdef _MSC_VER + #pragma optimize( "g", off ) +#endif + +#include +#include +#include +#include "GLee.h" + +#if defined(__APPLE__) || defined(__APPLE_CC__) + #include +#endif + +typedef GLuint(*GLEE_LINK_FUNCTION)(void); + +GLboolean __GLeeInited=GL_FALSE; + +#ifndef _WIN32 + #define __stdcall /* nothing */ +#endif + +void * __GLeeGetProcAddress(const char *extname) +{ +#ifdef WIN32 + return (void*)wglGetProcAddress(extname); +#elif defined(__APPLE__) || defined(__APPLE_CC__) + CFBundleRef bundle; + CFURLRef bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/System/Library/Frameworks/OpenGL.framework"), kCFURLPOSIXPathStyle, true); + + CFStringRef functionName = CFStringCreateWithCString(kCFAllocatorDefault, extname, kCFStringEncodingASCII); + + void *function; + + bundle = CFBundleCreate(kCFAllocatorDefault, bundleURL); + assert(bundle != NULL); + + function = CFBundleGetFunctionPointerForName(bundle, functionName); + + CFRelease(bundleURL); + CFRelease(functionName); + CFRelease(bundle); + + return function; +#else + return (void*)glXGetProcAddressARB((const GLubyte *)extname); +#endif +} + + + + +/* Extension querying variables */ + +GLboolean _GLEE_VERSION_1_2 = GL_FALSE; +GLboolean _GLEE_ARB_imaging = GL_FALSE; +GLboolean _GLEE_VERSION_1_3 = GL_FALSE; +GLboolean _GLEE_VERSION_1_4 = GL_FALSE; +GLboolean _GLEE_VERSION_1_5 = GL_FALSE; +GLboolean _GLEE_VERSION_2_0 = GL_FALSE; +GLboolean _GLEE_VERSION_2_1 = GL_FALSE; +GLboolean _GLEE_VERSION_3_0 = GL_FALSE; +GLboolean _GLEE_ARB_multitexture = GL_FALSE; +GLboolean _GLEE_ARB_transpose_matrix = GL_FALSE; +GLboolean _GLEE_ARB_multisample = GL_FALSE; +GLboolean _GLEE_ARB_texture_env_add = GL_FALSE; +GLboolean _GLEE_ARB_texture_cube_map = GL_FALSE; +GLboolean _GLEE_ARB_texture_compression = GL_FALSE; +GLboolean _GLEE_ARB_texture_border_clamp = GL_FALSE; +GLboolean _GLEE_ARB_point_parameters = GL_FALSE; +GLboolean _GLEE_ARB_vertex_blend = GL_FALSE; +GLboolean _GLEE_ARB_matrix_palette = GL_FALSE; +GLboolean _GLEE_ARB_texture_env_combine = GL_FALSE; +GLboolean _GLEE_ARB_texture_env_crossbar = GL_FALSE; +GLboolean _GLEE_ARB_texture_env_dot3 = GL_FALSE; +GLboolean _GLEE_ARB_texture_mirrored_repeat = GL_FALSE; +GLboolean _GLEE_ARB_depth_texture = GL_FALSE; +GLboolean _GLEE_ARB_shadow = GL_FALSE; +GLboolean _GLEE_ARB_shadow_ambient = GL_FALSE; +GLboolean _GLEE_ARB_window_pos = GL_FALSE; +GLboolean _GLEE_ARB_vertex_program = GL_FALSE; +GLboolean _GLEE_ARB_fragment_program = GL_FALSE; +GLboolean _GLEE_ARB_vertex_buffer_object = GL_FALSE; +GLboolean _GLEE_ARB_occlusion_query = GL_FALSE; +GLboolean _GLEE_ARB_shader_objects = GL_FALSE; +GLboolean _GLEE_ARB_vertex_shader = GL_FALSE; +GLboolean _GLEE_ARB_fragment_shader = GL_FALSE; +GLboolean _GLEE_ARB_shading_language_100 = GL_FALSE; +GLboolean _GLEE_ARB_texture_non_power_of_two = GL_FALSE; +GLboolean _GLEE_ARB_point_sprite = GL_FALSE; +GLboolean _GLEE_ARB_fragment_program_shadow = GL_FALSE; +GLboolean _GLEE_ARB_draw_buffers = GL_FALSE; +GLboolean _GLEE_ARB_texture_rectangle = GL_FALSE; +GLboolean _GLEE_ARB_color_buffer_float = GL_FALSE; +GLboolean _GLEE_ARB_half_float_pixel = GL_FALSE; +GLboolean _GLEE_ARB_texture_float = GL_FALSE; +GLboolean _GLEE_ARB_pixel_buffer_object = GL_FALSE; +GLboolean _GLEE_ARB_depth_buffer_float = GL_FALSE; +GLboolean _GLEE_ARB_draw_instanced = GL_FALSE; +GLboolean _GLEE_ARB_framebuffer_object = GL_FALSE; +GLboolean _GLEE_ARB_framebuffer_sRGB = GL_FALSE; +GLboolean _GLEE_ARB_geometry_shader4 = GL_FALSE; +GLboolean _GLEE_ARB_half_float_vertex = GL_FALSE; +GLboolean _GLEE_ARB_instanced_arrays = GL_FALSE; +GLboolean _GLEE_ARB_map_buffer_range = GL_FALSE; +GLboolean _GLEE_ARB_texture_buffer_object = GL_FALSE; +GLboolean _GLEE_ARB_texture_compression_rgtc = GL_FALSE; +GLboolean _GLEE_ARB_texture_rg = GL_FALSE; +GLboolean _GLEE_ARB_vertex_array_object = GL_FALSE; +GLboolean _GLEE_EXT_abgr = GL_FALSE; +GLboolean _GLEE_EXT_blend_color = GL_FALSE; +GLboolean _GLEE_EXT_polygon_offset = GL_FALSE; +GLboolean _GLEE_EXT_texture = GL_FALSE; +GLboolean _GLEE_EXT_texture3D = GL_FALSE; +GLboolean _GLEE_SGIS_texture_filter4 = GL_FALSE; +GLboolean _GLEE_EXT_subtexture = GL_FALSE; +GLboolean _GLEE_EXT_copy_texture = GL_FALSE; +GLboolean _GLEE_EXT_histogram = GL_FALSE; +GLboolean _GLEE_EXT_convolution = GL_FALSE; +GLboolean _GLEE_SGI_color_matrix = GL_FALSE; +GLboolean _GLEE_SGI_color_table = GL_FALSE; +GLboolean _GLEE_SGIS_pixel_texture = GL_FALSE; +GLboolean _GLEE_SGIX_pixel_texture = GL_FALSE; +GLboolean _GLEE_SGIS_texture4D = GL_FALSE; +GLboolean _GLEE_SGI_texture_color_table = GL_FALSE; +GLboolean _GLEE_EXT_cmyka = GL_FALSE; +GLboolean _GLEE_EXT_texture_object = GL_FALSE; +GLboolean _GLEE_SGIS_detail_texture = GL_FALSE; +GLboolean _GLEE_SGIS_sharpen_texture = GL_FALSE; +GLboolean _GLEE_EXT_packed_pixels = GL_FALSE; +GLboolean _GLEE_SGIS_texture_lod = GL_FALSE; +GLboolean _GLEE_SGIS_multisample = GL_FALSE; +GLboolean _GLEE_EXT_rescale_normal = GL_FALSE; +GLboolean _GLEE_EXT_vertex_array = GL_FALSE; +GLboolean _GLEE_EXT_misc_attribute = GL_FALSE; +GLboolean _GLEE_SGIS_generate_mipmap = GL_FALSE; +GLboolean _GLEE_SGIX_clipmap = GL_FALSE; +GLboolean _GLEE_SGIX_shadow = GL_FALSE; +GLboolean _GLEE_SGIS_texture_edge_clamp = GL_FALSE; +GLboolean _GLEE_SGIS_texture_border_clamp = GL_FALSE; +GLboolean _GLEE_EXT_blend_minmax = GL_FALSE; +GLboolean _GLEE_EXT_blend_subtract = GL_FALSE; +GLboolean _GLEE_EXT_blend_logic_op = GL_FALSE; +GLboolean _GLEE_SGIX_interlace = GL_FALSE; +GLboolean _GLEE_SGIX_pixel_tiles = GL_FALSE; +GLboolean _GLEE_SGIS_texture_select = GL_FALSE; +GLboolean _GLEE_SGIX_sprite = GL_FALSE; +GLboolean _GLEE_SGIX_texture_multi_buffer = GL_FALSE; +GLboolean _GLEE_EXT_point_parameters = GL_FALSE; +GLboolean _GLEE_SGIS_point_parameters = GL_FALSE; +GLboolean _GLEE_SGIX_instruments = GL_FALSE; +GLboolean _GLEE_SGIX_texture_scale_bias = GL_FALSE; +GLboolean _GLEE_SGIX_framezoom = GL_FALSE; +GLboolean _GLEE_SGIX_tag_sample_buffer = GL_FALSE; +GLboolean _GLEE_FfdMaskSGIX = GL_FALSE; +GLboolean _GLEE_SGIX_polynomial_ffd = GL_FALSE; +GLboolean _GLEE_SGIX_reference_plane = GL_FALSE; +GLboolean _GLEE_SGIX_flush_raster = GL_FALSE; +GLboolean _GLEE_SGIX_depth_texture = GL_FALSE; +GLboolean _GLEE_SGIS_fog_function = GL_FALSE; +GLboolean _GLEE_SGIX_fog_offset = GL_FALSE; +GLboolean _GLEE_HP_image_transform = GL_FALSE; +GLboolean _GLEE_HP_convolution_border_modes = GL_FALSE; +GLboolean _GLEE_INGR_palette_buffer = GL_FALSE; +GLboolean _GLEE_SGIX_texture_add_env = GL_FALSE; +GLboolean _GLEE_EXT_color_subtable = GL_FALSE; +GLboolean _GLEE_PGI_vertex_hints = GL_FALSE; +GLboolean _GLEE_PGI_misc_hints = GL_FALSE; +GLboolean _GLEE_EXT_paletted_texture = GL_FALSE; +GLboolean _GLEE_EXT_clip_volume_hint = GL_FALSE; +GLboolean _GLEE_SGIX_list_priority = GL_FALSE; +GLboolean _GLEE_SGIX_ir_instrument1 = GL_FALSE; +GLboolean _GLEE_SGIX_calligraphic_fragment = GL_FALSE; +GLboolean _GLEE_SGIX_texture_lod_bias = GL_FALSE; +GLboolean _GLEE_SGIX_shadow_ambient = GL_FALSE; +GLboolean _GLEE_EXT_index_texture = GL_FALSE; +GLboolean _GLEE_EXT_index_material = GL_FALSE; +GLboolean _GLEE_EXT_index_func = GL_FALSE; +GLboolean _GLEE_EXT_index_array_formats = GL_FALSE; +GLboolean _GLEE_EXT_compiled_vertex_array = GL_FALSE; +GLboolean _GLEE_EXT_cull_vertex = GL_FALSE; +GLboolean _GLEE_SGIX_ycrcb = GL_FALSE; +GLboolean _GLEE_SGIX_fragment_lighting = GL_FALSE; +GLboolean _GLEE_IBM_rasterpos_clip = GL_FALSE; +GLboolean _GLEE_HP_texture_lighting = GL_FALSE; +GLboolean _GLEE_EXT_draw_range_elements = GL_FALSE; +GLboolean _GLEE_WIN_phong_shading = GL_FALSE; +GLboolean _GLEE_WIN_specular_fog = GL_FALSE; +GLboolean _GLEE_EXT_light_texture = GL_FALSE; +GLboolean _GLEE_SGIX_blend_alpha_minmax = GL_FALSE; +GLboolean _GLEE_SGIX_impact_pixel_texture = GL_FALSE; +GLboolean _GLEE_EXT_bgra = GL_FALSE; +GLboolean _GLEE_SGIX_async = GL_FALSE; +GLboolean _GLEE_SGIX_async_pixel = GL_FALSE; +GLboolean _GLEE_SGIX_async_histogram = GL_FALSE; +GLboolean _GLEE_INTEL_texture_scissor = GL_FALSE; +GLboolean _GLEE_INTEL_parallel_arrays = GL_FALSE; +GLboolean _GLEE_HP_occlusion_test = GL_FALSE; +GLboolean _GLEE_EXT_pixel_transform = GL_FALSE; +GLboolean _GLEE_EXT_pixel_transform_color_table = GL_FALSE; +GLboolean _GLEE_EXT_shared_texture_palette = GL_FALSE; +GLboolean _GLEE_EXT_separate_specular_color = GL_FALSE; +GLboolean _GLEE_EXT_secondary_color = GL_FALSE; +GLboolean _GLEE_EXT_texture_perturb_normal = GL_FALSE; +GLboolean _GLEE_EXT_multi_draw_arrays = GL_FALSE; +GLboolean _GLEE_EXT_fog_coord = GL_FALSE; +GLboolean _GLEE_REND_screen_coordinates = GL_FALSE; +GLboolean _GLEE_EXT_coordinate_frame = GL_FALSE; +GLboolean _GLEE_EXT_texture_env_combine = GL_FALSE; +GLboolean _GLEE_APPLE_specular_vector = GL_FALSE; +GLboolean _GLEE_APPLE_transform_hint = GL_FALSE; +GLboolean _GLEE_SGIX_fog_scale = GL_FALSE; +GLboolean _GLEE_SUNX_constant_data = GL_FALSE; +GLboolean _GLEE_SUN_global_alpha = GL_FALSE; +GLboolean _GLEE_SUN_triangle_list = GL_FALSE; +GLboolean _GLEE_SUN_vertex = GL_FALSE; +GLboolean _GLEE_EXT_blend_func_separate = GL_FALSE; +GLboolean _GLEE_INGR_color_clamp = GL_FALSE; +GLboolean _GLEE_INGR_interlace_read = GL_FALSE; +GLboolean _GLEE_EXT_stencil_wrap = GL_FALSE; +GLboolean _GLEE_EXT_422_pixels = GL_FALSE; +GLboolean _GLEE_NV_texgen_reflection = GL_FALSE; +GLboolean _GLEE_EXT_texture_cube_map = GL_FALSE; +GLboolean _GLEE_SUN_convolution_border_modes = GL_FALSE; +GLboolean _GLEE_EXT_texture_env_add = GL_FALSE; +GLboolean _GLEE_EXT_texture_lod_bias = GL_FALSE; +GLboolean _GLEE_EXT_texture_filter_anisotropic = GL_FALSE; +GLboolean _GLEE_EXT_vertex_weighting = GL_FALSE; +GLboolean _GLEE_NV_light_max_exponent = GL_FALSE; +GLboolean _GLEE_NV_vertex_array_range = GL_FALSE; +GLboolean _GLEE_NV_register_combiners = GL_FALSE; +GLboolean _GLEE_NV_fog_distance = GL_FALSE; +GLboolean _GLEE_NV_texgen_emboss = GL_FALSE; +GLboolean _GLEE_NV_blend_square = GL_FALSE; +GLboolean _GLEE_NV_texture_env_combine4 = GL_FALSE; +GLboolean _GLEE_MESA_resize_buffers = GL_FALSE; +GLboolean _GLEE_MESA_window_pos = GL_FALSE; +GLboolean _GLEE_EXT_texture_compression_s3tc = GL_FALSE; +GLboolean _GLEE_IBM_cull_vertex = GL_FALSE; +GLboolean _GLEE_IBM_multimode_draw_arrays = GL_FALSE; +GLboolean _GLEE_IBM_vertex_array_lists = GL_FALSE; +GLboolean _GLEE_SGIX_subsample = GL_FALSE; +GLboolean _GLEE_SGIX_ycrcb_subsample = GL_FALSE; +GLboolean _GLEE_SGIX_ycrcba = GL_FALSE; +GLboolean _GLEE_SGI_depth_pass_instrument = GL_FALSE; +GLboolean _GLEE_3DFX_texture_compression_FXT1 = GL_FALSE; +GLboolean _GLEE_3DFX_multisample = GL_FALSE; +GLboolean _GLEE_3DFX_tbuffer = GL_FALSE; +GLboolean _GLEE_EXT_multisample = GL_FALSE; +GLboolean _GLEE_SGIX_vertex_preclip = GL_FALSE; +GLboolean _GLEE_SGIX_convolution_accuracy = GL_FALSE; +GLboolean _GLEE_SGIX_resample = GL_FALSE; +GLboolean _GLEE_SGIS_point_line_texgen = GL_FALSE; +GLboolean _GLEE_SGIS_texture_color_mask = GL_FALSE; +GLboolean _GLEE_EXT_texture_env_dot3 = GL_FALSE; +GLboolean _GLEE_ATI_texture_mirror_once = GL_FALSE; +GLboolean _GLEE_NV_fence = GL_FALSE; +GLboolean _GLEE_IBM_texture_mirrored_repeat = GL_FALSE; +GLboolean _GLEE_NV_evaluators = GL_FALSE; +GLboolean _GLEE_NV_packed_depth_stencil = GL_FALSE; +GLboolean _GLEE_NV_register_combiners2 = GL_FALSE; +GLboolean _GLEE_NV_texture_compression_vtc = GL_FALSE; +GLboolean _GLEE_NV_texture_rectangle = GL_FALSE; +GLboolean _GLEE_NV_texture_shader = GL_FALSE; +GLboolean _GLEE_NV_texture_shader2 = GL_FALSE; +GLboolean _GLEE_NV_vertex_array_range2 = GL_FALSE; +GLboolean _GLEE_NV_vertex_program = GL_FALSE; +GLboolean _GLEE_SGIX_texture_coordinate_clamp = GL_FALSE; +GLboolean _GLEE_SGIX_scalebias_hint = GL_FALSE; +GLboolean _GLEE_OML_interlace = GL_FALSE; +GLboolean _GLEE_OML_subsample = GL_FALSE; +GLboolean _GLEE_OML_resample = GL_FALSE; +GLboolean _GLEE_NV_copy_depth_to_color = GL_FALSE; +GLboolean _GLEE_ATI_envmap_bumpmap = GL_FALSE; +GLboolean _GLEE_ATI_fragment_shader = GL_FALSE; +GLboolean _GLEE_ATI_pn_triangles = GL_FALSE; +GLboolean _GLEE_ATI_vertex_array_object = GL_FALSE; +GLboolean _GLEE_EXT_vertex_shader = GL_FALSE; +GLboolean _GLEE_ATI_vertex_streams = GL_FALSE; +GLboolean _GLEE_ATI_element_array = GL_FALSE; +GLboolean _GLEE_SUN_mesh_array = GL_FALSE; +GLboolean _GLEE_SUN_slice_accum = GL_FALSE; +GLboolean _GLEE_NV_multisample_filter_hint = GL_FALSE; +GLboolean _GLEE_NV_depth_clamp = GL_FALSE; +GLboolean _GLEE_NV_occlusion_query = GL_FALSE; +GLboolean _GLEE_NV_point_sprite = GL_FALSE; +GLboolean _GLEE_NV_texture_shader3 = GL_FALSE; +GLboolean _GLEE_NV_vertex_program1_1 = GL_FALSE; +GLboolean _GLEE_EXT_shadow_funcs = GL_FALSE; +GLboolean _GLEE_EXT_stencil_two_side = GL_FALSE; +GLboolean _GLEE_ATI_text_fragment_shader = GL_FALSE; +GLboolean _GLEE_APPLE_client_storage = GL_FALSE; +GLboolean _GLEE_APPLE_element_array = GL_FALSE; +GLboolean _GLEE_APPLE_fence = GL_FALSE; +GLboolean _GLEE_APPLE_vertex_array_object = GL_FALSE; +GLboolean _GLEE_APPLE_vertex_array_range = GL_FALSE; +GLboolean _GLEE_APPLE_ycbcr_422 = GL_FALSE; +GLboolean _GLEE_S3_s3tc = GL_FALSE; +GLboolean _GLEE_ATI_draw_buffers = GL_FALSE; +GLboolean _GLEE_ATI_pixel_format_float = GL_FALSE; +GLboolean _GLEE_ATI_texture_env_combine3 = GL_FALSE; +GLboolean _GLEE_ATI_texture_float = GL_FALSE; +GLboolean _GLEE_NV_float_buffer = GL_FALSE; +GLboolean _GLEE_NV_fragment_program = GL_FALSE; +GLboolean _GLEE_NV_half_float = GL_FALSE; +GLboolean _GLEE_NV_pixel_data_range = GL_FALSE; +GLboolean _GLEE_NV_primitive_restart = GL_FALSE; +GLboolean _GLEE_NV_texture_expand_normal = GL_FALSE; +GLboolean _GLEE_NV_vertex_program2 = GL_FALSE; +GLboolean _GLEE_ATI_map_object_buffer = GL_FALSE; +GLboolean _GLEE_ATI_separate_stencil = GL_FALSE; +GLboolean _GLEE_ATI_vertex_attrib_array_object = GL_FALSE; +GLboolean _GLEE_OES_read_format = GL_FALSE; +GLboolean _GLEE_EXT_depth_bounds_test = GL_FALSE; +GLboolean _GLEE_EXT_texture_mirror_clamp = GL_FALSE; +GLboolean _GLEE_EXT_blend_equation_separate = GL_FALSE; +GLboolean _GLEE_MESA_pack_invert = GL_FALSE; +GLboolean _GLEE_MESA_ycbcr_texture = GL_FALSE; +GLboolean _GLEE_EXT_pixel_buffer_object = GL_FALSE; +GLboolean _GLEE_NV_fragment_program_option = GL_FALSE; +GLboolean _GLEE_NV_fragment_program2 = GL_FALSE; +GLboolean _GLEE_NV_vertex_program2_option = GL_FALSE; +GLboolean _GLEE_NV_vertex_program3 = GL_FALSE; +GLboolean _GLEE_EXT_framebuffer_object = GL_FALSE; +GLboolean _GLEE_GREMEDY_string_marker = GL_FALSE; +GLboolean _GLEE_EXT_packed_depth_stencil = GL_FALSE; +GLboolean _GLEE_EXT_stencil_clear_tag = GL_FALSE; +GLboolean _GLEE_EXT_texture_sRGB = GL_FALSE; +GLboolean _GLEE_EXT_framebuffer_blit = GL_FALSE; +GLboolean _GLEE_EXT_framebuffer_multisample = GL_FALSE; +GLboolean _GLEE_MESAX_texture_stack = GL_FALSE; +GLboolean _GLEE_EXT_timer_query = GL_FALSE; +GLboolean _GLEE_EXT_gpu_program_parameters = GL_FALSE; +GLboolean _GLEE_APPLE_flush_buffer_range = GL_FALSE; +GLboolean _GLEE_EXT_gpu_shader4 = GL_FALSE; +GLboolean _GLEE_EXT_draw_instanced = GL_FALSE; +GLboolean _GLEE_EXT_packed_float = GL_FALSE; +GLboolean _GLEE_EXT_texture_array = GL_FALSE; +GLboolean _GLEE_EXT_texture_buffer_object = GL_FALSE; +GLboolean _GLEE_EXT_texture_compression_latc = GL_FALSE; +GLboolean _GLEE_EXT_texture_compression_rgtc = GL_FALSE; +GLboolean _GLEE_EXT_texture_shared_exponent = GL_FALSE; +GLboolean _GLEE_NV_depth_buffer_float = GL_FALSE; +GLboolean _GLEE_NV_framebuffer_multisample_coverage = GL_FALSE; +GLboolean _GLEE_EXT_framebuffer_sRGB = GL_FALSE; +GLboolean _GLEE_NV_geometry_shader4 = GL_FALSE; +GLboolean _GLEE_NV_parameter_buffer_object = GL_FALSE; +GLboolean _GLEE_EXT_draw_buffers2 = GL_FALSE; +GLboolean _GLEE_NV_transform_feedback = GL_FALSE; +GLboolean _GLEE_EXT_bindable_uniform = GL_FALSE; +GLboolean _GLEE_EXT_texture_integer = GL_FALSE; +GLboolean _GLEE_GREMEDY_frame_terminator = GL_FALSE; +GLboolean _GLEE_NV_conditional_render = GL_FALSE; +GLboolean _GLEE_NV_present_video = GL_FALSE; +GLboolean _GLEE_EXT_transform_feedback = GL_FALSE; +GLboolean _GLEE_EXT_direct_state_access = GL_FALSE; +GLboolean _GLEE_EXT_vertex_array_bgra = GL_FALSE; +GLboolean _GLEE_EXT_texture_swizzle = GL_FALSE; +GLboolean _GLEE_NV_explicit_multisample = GL_FALSE; +GLboolean _GLEE_NV_transform_feedback2 = GL_FALSE; +GLboolean _GLEE_SGIX_texture_select = GL_FALSE; +GLboolean _GLEE_INGR_blend_func_separate = GL_FALSE; +GLboolean _GLEE_SGIX_depth_pass_instrument = GL_FALSE; +GLboolean _GLEE_SGIX_igloo_interface = GL_FALSE; +GLboolean _GLEE_EXT_fragment_lighting = GL_FALSE; +GLboolean _GLEE_EXT_geometry_shader4 = GL_FALSE; +GLboolean _GLEE_EXT_scene_marker = GL_FALSE; +GLboolean _GLEE_EXT_texture_compression_dxt1 = GL_FALSE; +GLboolean _GLEE_EXT_texture_env = GL_FALSE; +GLboolean _GLEE_IBM_static_data = GL_FALSE; +GLboolean _GLEE_NV_gpu_program4 = GL_FALSE; +GLboolean _GLEE_OES_byte_coordinates = GL_FALSE; +GLboolean _GLEE_OES_compressed_paletted_texture = GL_FALSE; +GLboolean _GLEE_OES_single_precision = GL_FALSE; +GLboolean _GLEE_SGIX_pixel_texture_bits = GL_FALSE; +GLboolean _GLEE_SGIX_texture_range = GL_FALSE; + +/* GL Extension names */ + +char __GLeeGLExtensionNames[322][39]={ + "GL_VERSION_1_2", + "GL_ARB_imaging", + "GL_VERSION_1_3", + "GL_VERSION_1_4", + "GL_VERSION_1_5", + "GL_VERSION_2_0", + "GL_VERSION_2_1", + "GL_VERSION_3_0", + "GL_ARB_multitexture", + "GL_ARB_transpose_matrix", + "GL_ARB_multisample", + "GL_ARB_texture_env_add", + "GL_ARB_texture_cube_map", + "GL_ARB_texture_compression", + "GL_ARB_texture_border_clamp", + "GL_ARB_point_parameters", + "GL_ARB_vertex_blend", + "GL_ARB_matrix_palette", + "GL_ARB_texture_env_combine", + "GL_ARB_texture_env_crossbar", + "GL_ARB_texture_env_dot3", + "GL_ARB_texture_mirrored_repeat", + "GL_ARB_depth_texture", + "GL_ARB_shadow", + "GL_ARB_shadow_ambient", + "GL_ARB_window_pos", + "GL_ARB_vertex_program", + "GL_ARB_fragment_program", + "GL_ARB_vertex_buffer_object", + "GL_ARB_occlusion_query", + "GL_ARB_shader_objects", + "GL_ARB_vertex_shader", + "GL_ARB_fragment_shader", + "GL_ARB_shading_language_100", + "GL_ARB_texture_non_power_of_two", + "GL_ARB_point_sprite", + "GL_ARB_fragment_program_shadow", + "GL_ARB_draw_buffers", + "GL_ARB_texture_rectangle", + "GL_ARB_color_buffer_float", + "GL_ARB_half_float_pixel", + "GL_ARB_texture_float", + "GL_ARB_pixel_buffer_object", + "GL_ARB_depth_buffer_float", + "GL_ARB_draw_instanced", + "GL_ARB_framebuffer_object", + "GL_ARB_framebuffer_sRGB", + "GL_ARB_geometry_shader4", + "GL_ARB_half_float_vertex", + "GL_ARB_instanced_arrays", + "GL_ARB_map_buffer_range", + "GL_ARB_texture_buffer_object", + "GL_ARB_texture_compression_rgtc", + "GL_ARB_texture_rg", + "GL_ARB_vertex_array_object", + "GL_EXT_abgr", + "GL_EXT_blend_color", + "GL_EXT_polygon_offset", + "GL_EXT_texture", + "GL_EXT_texture3D", + "GL_SGIS_texture_filter4", + "GL_EXT_subtexture", + "GL_EXT_copy_texture", + "GL_EXT_histogram", + "GL_EXT_convolution", + "GL_SGI_color_matrix", + "GL_SGI_color_table", + "GL_SGIS_pixel_texture", + "GL_SGIX_pixel_texture", + "GL_SGIS_texture4D", + "GL_SGI_texture_color_table", + "GL_EXT_cmyka", + "GL_EXT_texture_object", + "GL_SGIS_detail_texture", + "GL_SGIS_sharpen_texture", + "GL_EXT_packed_pixels", + "GL_SGIS_texture_lod", + "GL_SGIS_multisample", + "GL_EXT_rescale_normal", + "GL_EXT_vertex_array", + "GL_EXT_misc_attribute", + "GL_SGIS_generate_mipmap", + "GL_SGIX_clipmap", + "GL_SGIX_shadow", + "GL_SGIS_texture_edge_clamp", + "GL_SGIS_texture_border_clamp", + "GL_EXT_blend_minmax", + "GL_EXT_blend_subtract", + "GL_EXT_blend_logic_op", + "GL_SGIX_interlace", + "GL_SGIX_pixel_tiles", + "GL_SGIS_texture_select", + "GL_SGIX_sprite", + "GL_SGIX_texture_multi_buffer", + "GL_EXT_point_parameters", + "GL_SGIS_point_parameters", + "GL_SGIX_instruments", + "GL_SGIX_texture_scale_bias", + "GL_SGIX_framezoom", + "GL_SGIX_tag_sample_buffer", + "GL_FfdMaskSGIX", + "GL_SGIX_polynomial_ffd", + "GL_SGIX_reference_plane", + "GL_SGIX_flush_raster", + "GL_SGIX_depth_texture", + "GL_SGIS_fog_function", + "GL_SGIX_fog_offset", + "GL_HP_image_transform", + "GL_HP_convolution_border_modes", + "GL_INGR_palette_buffer", + "GL_SGIX_texture_add_env", + "GL_EXT_color_subtable", + "GL_PGI_vertex_hints", + "GL_PGI_misc_hints", + "GL_EXT_paletted_texture", + "GL_EXT_clip_volume_hint", + "GL_SGIX_list_priority", + "GL_SGIX_ir_instrument1", + "GL_SGIX_calligraphic_fragment", + "GL_SGIX_texture_lod_bias", + "GL_SGIX_shadow_ambient", + "GL_EXT_index_texture", + "GL_EXT_index_material", + "GL_EXT_index_func", + "GL_EXT_index_array_formats", + "GL_EXT_compiled_vertex_array", + "GL_EXT_cull_vertex", + "GL_SGIX_ycrcb", + "GL_SGIX_fragment_lighting", + "GL_IBM_rasterpos_clip", + "GL_HP_texture_lighting", + "GL_EXT_draw_range_elements", + "GL_WIN_phong_shading", + "GL_WIN_specular_fog", + "GL_EXT_light_texture", + "GL_SGIX_blend_alpha_minmax", + "GL_SGIX_impact_pixel_texture", + "GL_EXT_bgra", + "GL_SGIX_async", + "GL_SGIX_async_pixel", + "GL_SGIX_async_histogram", + "GL_INTEL_texture_scissor", + "GL_INTEL_parallel_arrays", + "GL_HP_occlusion_test", + "GL_EXT_pixel_transform", + "GL_EXT_pixel_transform_color_table", + "GL_EXT_shared_texture_palette", + "GL_EXT_separate_specular_color", + "GL_EXT_secondary_color", + "GL_EXT_texture_perturb_normal", + "GL_EXT_multi_draw_arrays", + "GL_EXT_fog_coord", + "GL_REND_screen_coordinates", + "GL_EXT_coordinate_frame", + "GL_EXT_texture_env_combine", + "GL_APPLE_specular_vector", + "GL_APPLE_transform_hint", + "GL_SGIX_fog_scale", + "GL_SUNX_constant_data", + "GL_SUN_global_alpha", + "GL_SUN_triangle_list", + "GL_SUN_vertex", + "GL_EXT_blend_func_separate", + "GL_INGR_color_clamp", + "GL_INGR_interlace_read", + "GL_EXT_stencil_wrap", + "GL_EXT_422_pixels", + "GL_NV_texgen_reflection", + "GL_EXT_texture_cube_map", + "GL_SUN_convolution_border_modes", + "GL_EXT_texture_env_add", + "GL_EXT_texture_lod_bias", + "GL_EXT_texture_filter_anisotropic", + "GL_EXT_vertex_weighting", + "GL_NV_light_max_exponent", + "GL_NV_vertex_array_range", + "GL_NV_register_combiners", + "GL_NV_fog_distance", + "GL_NV_texgen_emboss", + "GL_NV_blend_square", + "GL_NV_texture_env_combine4", + "GL_MESA_resize_buffers", + "GL_MESA_window_pos", + "GL_EXT_texture_compression_s3tc", + "GL_IBM_cull_vertex", + "GL_IBM_multimode_draw_arrays", + "GL_IBM_vertex_array_lists", + "GL_SGIX_subsample", + "GL_SGIX_ycrcb_subsample", + "GL_SGIX_ycrcba", + "GL_SGI_depth_pass_instrument", + "GL_3DFX_texture_compression_FXT1", + "GL_3DFX_multisample", + "GL_3DFX_tbuffer", + "GL_EXT_multisample", + "GL_SGIX_vertex_preclip", + "GL_SGIX_convolution_accuracy", + "GL_SGIX_resample", + "GL_SGIS_point_line_texgen", + "GL_SGIS_texture_color_mask", + "GL_EXT_texture_env_dot3", + "GL_ATI_texture_mirror_once", + "GL_NV_fence", + "GL_IBM_texture_mirrored_repeat", + "GL_NV_evaluators", + "GL_NV_packed_depth_stencil", + "GL_NV_register_combiners2", + "GL_NV_texture_compression_vtc", + "GL_NV_texture_rectangle", + "GL_NV_texture_shader", + "GL_NV_texture_shader2", + "GL_NV_vertex_array_range2", + "GL_NV_vertex_program", + "GL_SGIX_texture_coordinate_clamp", + "GL_SGIX_scalebias_hint", + "GL_OML_interlace", + "GL_OML_subsample", + "GL_OML_resample", + "GL_NV_copy_depth_to_color", + "GL_ATI_envmap_bumpmap", + "GL_ATI_fragment_shader", + "GL_ATI_pn_triangles", + "GL_ATI_vertex_array_object", + "GL_EXT_vertex_shader", + "GL_ATI_vertex_streams", + "GL_ATI_element_array", + "GL_SUN_mesh_array", + "GL_SUN_slice_accum", + "GL_NV_multisample_filter_hint", + "GL_NV_depth_clamp", + "GL_NV_occlusion_query", + "GL_NV_point_sprite", + "GL_NV_texture_shader3", + "GL_NV_vertex_program1_1", + "GL_EXT_shadow_funcs", + "GL_EXT_stencil_two_side", + "GL_ATI_text_fragment_shader", + "GL_APPLE_client_storage", + "GL_APPLE_element_array", + "GL_APPLE_fence", + "GL_APPLE_vertex_array_object", + "GL_APPLE_vertex_array_range", + "GL_APPLE_ycbcr_422", + "GL_S3_s3tc", + "GL_ATI_draw_buffers", + "GL_ATI_pixel_format_float", + "GL_ATI_texture_env_combine3", + "GL_ATI_texture_float", + "GL_NV_float_buffer", + "GL_NV_fragment_program", + "GL_NV_half_float", + "GL_NV_pixel_data_range", + "GL_NV_primitive_restart", + "GL_NV_texture_expand_normal", + "GL_NV_vertex_program2", + "GL_ATI_map_object_buffer", + "GL_ATI_separate_stencil", + "GL_ATI_vertex_attrib_array_object", + "GL_OES_read_format", + "GL_EXT_depth_bounds_test", + "GL_EXT_texture_mirror_clamp", + "GL_EXT_blend_equation_separate", + "GL_MESA_pack_invert", + "GL_MESA_ycbcr_texture", + "GL_EXT_pixel_buffer_object", + "GL_NV_fragment_program_option", + "GL_NV_fragment_program2", + "GL_NV_vertex_program2_option", + "GL_NV_vertex_program3", + "GL_EXT_framebuffer_object", + "GL_GREMEDY_string_marker", + "GL_EXT_packed_depth_stencil", + "GL_EXT_stencil_clear_tag", + "GL_EXT_texture_sRGB", + "GL_EXT_framebuffer_blit", + "GL_EXT_framebuffer_multisample", + "GL_MESAX_texture_stack", + "GL_EXT_timer_query", + "GL_EXT_gpu_program_parameters", + "GL_APPLE_flush_buffer_range", + "GL_EXT_gpu_shader4", + "GL_EXT_draw_instanced", + "GL_EXT_packed_float", + "GL_EXT_texture_array", + "GL_EXT_texture_buffer_object", + "GL_EXT_texture_compression_latc", + "GL_EXT_texture_compression_rgtc", + "GL_EXT_texture_shared_exponent", + "GL_NV_depth_buffer_float", + "GL_NV_framebuffer_multisample_coverage", + "GL_EXT_framebuffer_sRGB", + "GL_NV_geometry_shader4", + "GL_NV_parameter_buffer_object", + "GL_EXT_draw_buffers2", + "GL_NV_transform_feedback", + "GL_EXT_bindable_uniform", + "GL_EXT_texture_integer", + "GL_GREMEDY_frame_terminator", + "GL_NV_conditional_render", + "GL_NV_present_video", + "GL_EXT_transform_feedback", + "GL_EXT_direct_state_access", + "GL_EXT_vertex_array_bgra", + "GL_EXT_texture_swizzle", + "GL_NV_explicit_multisample", + "GL_NV_transform_feedback2", + "GL_SGIX_texture_select", + "GL_INGR_blend_func_separate", + "GL_SGIX_depth_pass_instrument", + "GL_SGIX_igloo_interface", + "GL_EXT_fragment_lighting", + "GL_EXT_geometry_shader4", + "GL_EXT_scene_marker", + "GL_EXT_texture_compression_dxt1", + "GL_EXT_texture_env", + "GL_IBM_static_data", + "GL_NV_gpu_program4", + "GL_OES_byte_coordinates", + "GL_OES_compressed_paletted_texture", + "GL_OES_single_precision", + "GL_SGIX_pixel_texture_bits", + "GL_SGIX_texture_range" +}; +int __GLeeGLNumExtensions=322; + +/* GL_VERSION_1_2 */ + +#ifdef __GLEE_GL_VERSION_1_2 +#ifndef GLEE_C_DEFINED_glBlendColor +#define GLEE_C_DEFINED_glBlendColor + void __stdcall GLee_Lazy_glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {if (GLeeInit()) glBlendColor(red, green, blue, alpha);} + GLEEPFNGLBLENDCOLORPROC GLeeFuncPtr_glBlendColor=GLee_Lazy_glBlendColor; +#endif +#ifndef GLEE_C_DEFINED_glBlendEquation +#define GLEE_C_DEFINED_glBlendEquation + void __stdcall GLee_Lazy_glBlendEquation(GLenum mode) {if (GLeeInit()) glBlendEquation(mode);} + GLEEPFNGLBLENDEQUATIONPROC GLeeFuncPtr_glBlendEquation=GLee_Lazy_glBlendEquation; +#endif +#ifndef GLEE_C_DEFINED_glDrawRangeElements +#define GLEE_C_DEFINED_glDrawRangeElements + void __stdcall GLee_Lazy_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices) {if (GLeeInit()) glDrawRangeElements(mode, start, end, count, type, indices);} + GLEEPFNGLDRAWRANGEELEMENTSPROC GLeeFuncPtr_glDrawRangeElements=GLee_Lazy_glDrawRangeElements; +#endif +#ifndef GLEE_C_DEFINED_glColorTable +#define GLEE_C_DEFINED_glColorTable + void __stdcall GLee_Lazy_glColorTable(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * table) {if (GLeeInit()) glColorTable(target, internalformat, width, format, type, table);} + GLEEPFNGLCOLORTABLEPROC GLeeFuncPtr_glColorTable=GLee_Lazy_glColorTable; +#endif +#ifndef GLEE_C_DEFINED_glColorTableParameterfv +#define GLEE_C_DEFINED_glColorTableParameterfv + void __stdcall GLee_Lazy_glColorTableParameterfv(GLenum target, GLenum pname, const GLfloat * params) {if (GLeeInit()) glColorTableParameterfv(target, pname, params);} + GLEEPFNGLCOLORTABLEPARAMETERFVPROC GLeeFuncPtr_glColorTableParameterfv=GLee_Lazy_glColorTableParameterfv; +#endif +#ifndef GLEE_C_DEFINED_glColorTableParameteriv +#define GLEE_C_DEFINED_glColorTableParameteriv + void __stdcall GLee_Lazy_glColorTableParameteriv(GLenum target, GLenum pname, const GLint * params) {if (GLeeInit()) glColorTableParameteriv(target, pname, params);} + GLEEPFNGLCOLORTABLEPARAMETERIVPROC GLeeFuncPtr_glColorTableParameteriv=GLee_Lazy_glColorTableParameteriv; +#endif +#ifndef GLEE_C_DEFINED_glCopyColorTable +#define GLEE_C_DEFINED_glCopyColorTable + void __stdcall GLee_Lazy_glCopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) {if (GLeeInit()) glCopyColorTable(target, internalformat, x, y, width);} + GLEEPFNGLCOPYCOLORTABLEPROC GLeeFuncPtr_glCopyColorTable=GLee_Lazy_glCopyColorTable; +#endif +#ifndef GLEE_C_DEFINED_glGetColorTable +#define GLEE_C_DEFINED_glGetColorTable + void __stdcall GLee_Lazy_glGetColorTable(GLenum target, GLenum format, GLenum type, GLvoid * table) {if (GLeeInit()) glGetColorTable(target, format, type, table);} + GLEEPFNGLGETCOLORTABLEPROC GLeeFuncPtr_glGetColorTable=GLee_Lazy_glGetColorTable; +#endif +#ifndef GLEE_C_DEFINED_glGetColorTableParameterfv +#define GLEE_C_DEFINED_glGetColorTableParameterfv + void __stdcall GLee_Lazy_glGetColorTableParameterfv(GLenum target, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetColorTableParameterfv(target, pname, params);} + GLEEPFNGLGETCOLORTABLEPARAMETERFVPROC GLeeFuncPtr_glGetColorTableParameterfv=GLee_Lazy_glGetColorTableParameterfv; +#endif +#ifndef GLEE_C_DEFINED_glGetColorTableParameteriv +#define GLEE_C_DEFINED_glGetColorTableParameteriv + void __stdcall GLee_Lazy_glGetColorTableParameteriv(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetColorTableParameteriv(target, pname, params);} + GLEEPFNGLGETCOLORTABLEPARAMETERIVPROC GLeeFuncPtr_glGetColorTableParameteriv=GLee_Lazy_glGetColorTableParameteriv; +#endif +#ifndef GLEE_C_DEFINED_glColorSubTable +#define GLEE_C_DEFINED_glColorSubTable + void __stdcall GLee_Lazy_glColorSubTable(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid * data) {if (GLeeInit()) glColorSubTable(target, start, count, format, type, data);} + GLEEPFNGLCOLORSUBTABLEPROC GLeeFuncPtr_glColorSubTable=GLee_Lazy_glColorSubTable; +#endif +#ifndef GLEE_C_DEFINED_glCopyColorSubTable +#define GLEE_C_DEFINED_glCopyColorSubTable + void __stdcall GLee_Lazy_glCopyColorSubTable(GLenum target, GLsizei start, GLint x, GLint y, GLsizei width) {if (GLeeInit()) glCopyColorSubTable(target, start, x, y, width);} + GLEEPFNGLCOPYCOLORSUBTABLEPROC GLeeFuncPtr_glCopyColorSubTable=GLee_Lazy_glCopyColorSubTable; +#endif +#ifndef GLEE_C_DEFINED_glConvolutionFilter1D +#define GLEE_C_DEFINED_glConvolutionFilter1D + void __stdcall GLee_Lazy_glConvolutionFilter1D(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * image) {if (GLeeInit()) glConvolutionFilter1D(target, internalformat, width, format, type, image);} + GLEEPFNGLCONVOLUTIONFILTER1DPROC GLeeFuncPtr_glConvolutionFilter1D=GLee_Lazy_glConvolutionFilter1D; +#endif +#ifndef GLEE_C_DEFINED_glConvolutionFilter2D +#define GLEE_C_DEFINED_glConvolutionFilter2D + void __stdcall GLee_Lazy_glConvolutionFilter2D(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * image) {if (GLeeInit()) glConvolutionFilter2D(target, internalformat, width, height, format, type, image);} + GLEEPFNGLCONVOLUTIONFILTER2DPROC GLeeFuncPtr_glConvolutionFilter2D=GLee_Lazy_glConvolutionFilter2D; +#endif +#ifndef GLEE_C_DEFINED_glConvolutionParameterf +#define GLEE_C_DEFINED_glConvolutionParameterf + void __stdcall GLee_Lazy_glConvolutionParameterf(GLenum target, GLenum pname, GLfloat params) {if (GLeeInit()) glConvolutionParameterf(target, pname, params);} + GLEEPFNGLCONVOLUTIONPARAMETERFPROC GLeeFuncPtr_glConvolutionParameterf=GLee_Lazy_glConvolutionParameterf; +#endif +#ifndef GLEE_C_DEFINED_glConvolutionParameterfv +#define GLEE_C_DEFINED_glConvolutionParameterfv + void __stdcall GLee_Lazy_glConvolutionParameterfv(GLenum target, GLenum pname, const GLfloat * params) {if (GLeeInit()) glConvolutionParameterfv(target, pname, params);} + GLEEPFNGLCONVOLUTIONPARAMETERFVPROC GLeeFuncPtr_glConvolutionParameterfv=GLee_Lazy_glConvolutionParameterfv; +#endif +#ifndef GLEE_C_DEFINED_glConvolutionParameteri +#define GLEE_C_DEFINED_glConvolutionParameteri + void __stdcall GLee_Lazy_glConvolutionParameteri(GLenum target, GLenum pname, GLint params) {if (GLeeInit()) glConvolutionParameteri(target, pname, params);} + GLEEPFNGLCONVOLUTIONPARAMETERIPROC GLeeFuncPtr_glConvolutionParameteri=GLee_Lazy_glConvolutionParameteri; +#endif +#ifndef GLEE_C_DEFINED_glConvolutionParameteriv +#define GLEE_C_DEFINED_glConvolutionParameteriv + void __stdcall GLee_Lazy_glConvolutionParameteriv(GLenum target, GLenum pname, const GLint * params) {if (GLeeInit()) glConvolutionParameteriv(target, pname, params);} + GLEEPFNGLCONVOLUTIONPARAMETERIVPROC GLeeFuncPtr_glConvolutionParameteriv=GLee_Lazy_glConvolutionParameteriv; +#endif +#ifndef GLEE_C_DEFINED_glCopyConvolutionFilter1D +#define GLEE_C_DEFINED_glCopyConvolutionFilter1D + void __stdcall GLee_Lazy_glCopyConvolutionFilter1D(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) {if (GLeeInit()) glCopyConvolutionFilter1D(target, internalformat, x, y, width);} + GLEEPFNGLCOPYCONVOLUTIONFILTER1DPROC GLeeFuncPtr_glCopyConvolutionFilter1D=GLee_Lazy_glCopyConvolutionFilter1D; +#endif +#ifndef GLEE_C_DEFINED_glCopyConvolutionFilter2D +#define GLEE_C_DEFINED_glCopyConvolutionFilter2D + void __stdcall GLee_Lazy_glCopyConvolutionFilter2D(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height) {if (GLeeInit()) glCopyConvolutionFilter2D(target, internalformat, x, y, width, height);} + GLEEPFNGLCOPYCONVOLUTIONFILTER2DPROC GLeeFuncPtr_glCopyConvolutionFilter2D=GLee_Lazy_glCopyConvolutionFilter2D; +#endif +#ifndef GLEE_C_DEFINED_glGetConvolutionFilter +#define GLEE_C_DEFINED_glGetConvolutionFilter + void __stdcall GLee_Lazy_glGetConvolutionFilter(GLenum target, GLenum format, GLenum type, GLvoid * image) {if (GLeeInit()) glGetConvolutionFilter(target, format, type, image);} + GLEEPFNGLGETCONVOLUTIONFILTERPROC GLeeFuncPtr_glGetConvolutionFilter=GLee_Lazy_glGetConvolutionFilter; +#endif +#ifndef GLEE_C_DEFINED_glGetConvolutionParameterfv +#define GLEE_C_DEFINED_glGetConvolutionParameterfv + void __stdcall GLee_Lazy_glGetConvolutionParameterfv(GLenum target, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetConvolutionParameterfv(target, pname, params);} + GLEEPFNGLGETCONVOLUTIONPARAMETERFVPROC GLeeFuncPtr_glGetConvolutionParameterfv=GLee_Lazy_glGetConvolutionParameterfv; +#endif +#ifndef GLEE_C_DEFINED_glGetConvolutionParameteriv +#define GLEE_C_DEFINED_glGetConvolutionParameteriv + void __stdcall GLee_Lazy_glGetConvolutionParameteriv(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetConvolutionParameteriv(target, pname, params);} + GLEEPFNGLGETCONVOLUTIONPARAMETERIVPROC GLeeFuncPtr_glGetConvolutionParameteriv=GLee_Lazy_glGetConvolutionParameteriv; +#endif +#ifndef GLEE_C_DEFINED_glGetSeparableFilter +#define GLEE_C_DEFINED_glGetSeparableFilter + void __stdcall GLee_Lazy_glGetSeparableFilter(GLenum target, GLenum format, GLenum type, GLvoid * row, GLvoid * column, GLvoid * span) {if (GLeeInit()) glGetSeparableFilter(target, format, type, row, column, span);} + GLEEPFNGLGETSEPARABLEFILTERPROC GLeeFuncPtr_glGetSeparableFilter=GLee_Lazy_glGetSeparableFilter; +#endif +#ifndef GLEE_C_DEFINED_glSeparableFilter2D +#define GLEE_C_DEFINED_glSeparableFilter2D + void __stdcall GLee_Lazy_glSeparableFilter2D(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * row, const GLvoid * column) {if (GLeeInit()) glSeparableFilter2D(target, internalformat, width, height, format, type, row, column);} + GLEEPFNGLSEPARABLEFILTER2DPROC GLeeFuncPtr_glSeparableFilter2D=GLee_Lazy_glSeparableFilter2D; +#endif +#ifndef GLEE_C_DEFINED_glGetHistogram +#define GLEE_C_DEFINED_glGetHistogram + void __stdcall GLee_Lazy_glGetHistogram(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values) {if (GLeeInit()) glGetHistogram(target, reset, format, type, values);} + GLEEPFNGLGETHISTOGRAMPROC GLeeFuncPtr_glGetHistogram=GLee_Lazy_glGetHistogram; +#endif +#ifndef GLEE_C_DEFINED_glGetHistogramParameterfv +#define GLEE_C_DEFINED_glGetHistogramParameterfv + void __stdcall GLee_Lazy_glGetHistogramParameterfv(GLenum target, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetHistogramParameterfv(target, pname, params);} + GLEEPFNGLGETHISTOGRAMPARAMETERFVPROC GLeeFuncPtr_glGetHistogramParameterfv=GLee_Lazy_glGetHistogramParameterfv; +#endif +#ifndef GLEE_C_DEFINED_glGetHistogramParameteriv +#define GLEE_C_DEFINED_glGetHistogramParameteriv + void __stdcall GLee_Lazy_glGetHistogramParameteriv(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetHistogramParameteriv(target, pname, params);} + GLEEPFNGLGETHISTOGRAMPARAMETERIVPROC GLeeFuncPtr_glGetHistogramParameteriv=GLee_Lazy_glGetHistogramParameteriv; +#endif +#ifndef GLEE_C_DEFINED_glGetMinmax +#define GLEE_C_DEFINED_glGetMinmax + void __stdcall GLee_Lazy_glGetMinmax(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values) {if (GLeeInit()) glGetMinmax(target, reset, format, type, values);} + GLEEPFNGLGETMINMAXPROC GLeeFuncPtr_glGetMinmax=GLee_Lazy_glGetMinmax; +#endif +#ifndef GLEE_C_DEFINED_glGetMinmaxParameterfv +#define GLEE_C_DEFINED_glGetMinmaxParameterfv + void __stdcall GLee_Lazy_glGetMinmaxParameterfv(GLenum target, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetMinmaxParameterfv(target, pname, params);} + GLEEPFNGLGETMINMAXPARAMETERFVPROC GLeeFuncPtr_glGetMinmaxParameterfv=GLee_Lazy_glGetMinmaxParameterfv; +#endif +#ifndef GLEE_C_DEFINED_glGetMinmaxParameteriv +#define GLEE_C_DEFINED_glGetMinmaxParameteriv + void __stdcall GLee_Lazy_glGetMinmaxParameteriv(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetMinmaxParameteriv(target, pname, params);} + GLEEPFNGLGETMINMAXPARAMETERIVPROC GLeeFuncPtr_glGetMinmaxParameteriv=GLee_Lazy_glGetMinmaxParameteriv; +#endif +#ifndef GLEE_C_DEFINED_glHistogram +#define GLEE_C_DEFINED_glHistogram + void __stdcall GLee_Lazy_glHistogram(GLenum target, GLsizei width, GLenum internalformat, GLboolean sink) {if (GLeeInit()) glHistogram(target, width, internalformat, sink);} + GLEEPFNGLHISTOGRAMPROC GLeeFuncPtr_glHistogram=GLee_Lazy_glHistogram; +#endif +#ifndef GLEE_C_DEFINED_glMinmax +#define GLEE_C_DEFINED_glMinmax + void __stdcall GLee_Lazy_glMinmax(GLenum target, GLenum internalformat, GLboolean sink) {if (GLeeInit()) glMinmax(target, internalformat, sink);} + GLEEPFNGLMINMAXPROC GLeeFuncPtr_glMinmax=GLee_Lazy_glMinmax; +#endif +#ifndef GLEE_C_DEFINED_glResetHistogram +#define GLEE_C_DEFINED_glResetHistogram + void __stdcall GLee_Lazy_glResetHistogram(GLenum target) {if (GLeeInit()) glResetHistogram(target);} + GLEEPFNGLRESETHISTOGRAMPROC GLeeFuncPtr_glResetHistogram=GLee_Lazy_glResetHistogram; +#endif +#ifndef GLEE_C_DEFINED_glResetMinmax +#define GLEE_C_DEFINED_glResetMinmax + void __stdcall GLee_Lazy_glResetMinmax(GLenum target) {if (GLeeInit()) glResetMinmax(target);} + GLEEPFNGLRESETMINMAXPROC GLeeFuncPtr_glResetMinmax=GLee_Lazy_glResetMinmax; +#endif +#ifndef GLEE_C_DEFINED_glTexImage3D +#define GLEE_C_DEFINED_glTexImage3D + void __stdcall GLee_Lazy_glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glTexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels);} + GLEEPFNGLTEXIMAGE3DPROC GLeeFuncPtr_glTexImage3D=GLee_Lazy_glTexImage3D; +#endif +#ifndef GLEE_C_DEFINED_glTexSubImage3D +#define GLEE_C_DEFINED_glTexSubImage3D + void __stdcall GLee_Lazy_glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);} + GLEEPFNGLTEXSUBIMAGE3DPROC GLeeFuncPtr_glTexSubImage3D=GLee_Lazy_glTexSubImage3D; +#endif +#ifndef GLEE_C_DEFINED_glCopyTexSubImage3D +#define GLEE_C_DEFINED_glCopyTexSubImage3D + void __stdcall GLee_Lazy_glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {if (GLeeInit()) glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);} + GLEEPFNGLCOPYTEXSUBIMAGE3DPROC GLeeFuncPtr_glCopyTexSubImage3D=GLee_Lazy_glCopyTexSubImage3D; +#endif +#endif + +/* GL_ARB_imaging */ + +#ifdef __GLEE_GL_ARB_imaging +#endif + +/* GL_VERSION_1_3 */ + +#ifdef __GLEE_GL_VERSION_1_3 +#ifndef GLEE_C_DEFINED_glActiveTexture +#define GLEE_C_DEFINED_glActiveTexture + void __stdcall GLee_Lazy_glActiveTexture(GLenum texture) {if (GLeeInit()) glActiveTexture(texture);} + GLEEPFNGLACTIVETEXTUREPROC GLeeFuncPtr_glActiveTexture=GLee_Lazy_glActiveTexture; +#endif +#ifndef GLEE_C_DEFINED_glClientActiveTexture +#define GLEE_C_DEFINED_glClientActiveTexture + void __stdcall GLee_Lazy_glClientActiveTexture(GLenum texture) {if (GLeeInit()) glClientActiveTexture(texture);} + GLEEPFNGLCLIENTACTIVETEXTUREPROC GLeeFuncPtr_glClientActiveTexture=GLee_Lazy_glClientActiveTexture; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1d +#define GLEE_C_DEFINED_glMultiTexCoord1d + void __stdcall GLee_Lazy_glMultiTexCoord1d(GLenum target, GLdouble s) {if (GLeeInit()) glMultiTexCoord1d(target, s);} + GLEEPFNGLMULTITEXCOORD1DPROC GLeeFuncPtr_glMultiTexCoord1d=GLee_Lazy_glMultiTexCoord1d; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1dv +#define GLEE_C_DEFINED_glMultiTexCoord1dv + void __stdcall GLee_Lazy_glMultiTexCoord1dv(GLenum target, const GLdouble * v) {if (GLeeInit()) glMultiTexCoord1dv(target, v);} + GLEEPFNGLMULTITEXCOORD1DVPROC GLeeFuncPtr_glMultiTexCoord1dv=GLee_Lazy_glMultiTexCoord1dv; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1f +#define GLEE_C_DEFINED_glMultiTexCoord1f + void __stdcall GLee_Lazy_glMultiTexCoord1f(GLenum target, GLfloat s) {if (GLeeInit()) glMultiTexCoord1f(target, s);} + GLEEPFNGLMULTITEXCOORD1FPROC GLeeFuncPtr_glMultiTexCoord1f=GLee_Lazy_glMultiTexCoord1f; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1fv +#define GLEE_C_DEFINED_glMultiTexCoord1fv + void __stdcall GLee_Lazy_glMultiTexCoord1fv(GLenum target, const GLfloat * v) {if (GLeeInit()) glMultiTexCoord1fv(target, v);} + GLEEPFNGLMULTITEXCOORD1FVPROC GLeeFuncPtr_glMultiTexCoord1fv=GLee_Lazy_glMultiTexCoord1fv; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1i +#define GLEE_C_DEFINED_glMultiTexCoord1i + void __stdcall GLee_Lazy_glMultiTexCoord1i(GLenum target, GLint s) {if (GLeeInit()) glMultiTexCoord1i(target, s);} + GLEEPFNGLMULTITEXCOORD1IPROC GLeeFuncPtr_glMultiTexCoord1i=GLee_Lazy_glMultiTexCoord1i; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1iv +#define GLEE_C_DEFINED_glMultiTexCoord1iv + void __stdcall GLee_Lazy_glMultiTexCoord1iv(GLenum target, const GLint * v) {if (GLeeInit()) glMultiTexCoord1iv(target, v);} + GLEEPFNGLMULTITEXCOORD1IVPROC GLeeFuncPtr_glMultiTexCoord1iv=GLee_Lazy_glMultiTexCoord1iv; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1s +#define GLEE_C_DEFINED_glMultiTexCoord1s + void __stdcall GLee_Lazy_glMultiTexCoord1s(GLenum target, GLshort s) {if (GLeeInit()) glMultiTexCoord1s(target, s);} + GLEEPFNGLMULTITEXCOORD1SPROC GLeeFuncPtr_glMultiTexCoord1s=GLee_Lazy_glMultiTexCoord1s; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1sv +#define GLEE_C_DEFINED_glMultiTexCoord1sv + void __stdcall GLee_Lazy_glMultiTexCoord1sv(GLenum target, const GLshort * v) {if (GLeeInit()) glMultiTexCoord1sv(target, v);} + GLEEPFNGLMULTITEXCOORD1SVPROC GLeeFuncPtr_glMultiTexCoord1sv=GLee_Lazy_glMultiTexCoord1sv; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2d +#define GLEE_C_DEFINED_glMultiTexCoord2d + void __stdcall GLee_Lazy_glMultiTexCoord2d(GLenum target, GLdouble s, GLdouble t) {if (GLeeInit()) glMultiTexCoord2d(target, s, t);} + GLEEPFNGLMULTITEXCOORD2DPROC GLeeFuncPtr_glMultiTexCoord2d=GLee_Lazy_glMultiTexCoord2d; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2dv +#define GLEE_C_DEFINED_glMultiTexCoord2dv + void __stdcall GLee_Lazy_glMultiTexCoord2dv(GLenum target, const GLdouble * v) {if (GLeeInit()) glMultiTexCoord2dv(target, v);} + GLEEPFNGLMULTITEXCOORD2DVPROC GLeeFuncPtr_glMultiTexCoord2dv=GLee_Lazy_glMultiTexCoord2dv; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2f +#define GLEE_C_DEFINED_glMultiTexCoord2f + void __stdcall GLee_Lazy_glMultiTexCoord2f(GLenum target, GLfloat s, GLfloat t) {if (GLeeInit()) glMultiTexCoord2f(target, s, t);} + GLEEPFNGLMULTITEXCOORD2FPROC GLeeFuncPtr_glMultiTexCoord2f=GLee_Lazy_glMultiTexCoord2f; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2fv +#define GLEE_C_DEFINED_glMultiTexCoord2fv + void __stdcall GLee_Lazy_glMultiTexCoord2fv(GLenum target, const GLfloat * v) {if (GLeeInit()) glMultiTexCoord2fv(target, v);} + GLEEPFNGLMULTITEXCOORD2FVPROC GLeeFuncPtr_glMultiTexCoord2fv=GLee_Lazy_glMultiTexCoord2fv; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2i +#define GLEE_C_DEFINED_glMultiTexCoord2i + void __stdcall GLee_Lazy_glMultiTexCoord2i(GLenum target, GLint s, GLint t) {if (GLeeInit()) glMultiTexCoord2i(target, s, t);} + GLEEPFNGLMULTITEXCOORD2IPROC GLeeFuncPtr_glMultiTexCoord2i=GLee_Lazy_glMultiTexCoord2i; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2iv +#define GLEE_C_DEFINED_glMultiTexCoord2iv + void __stdcall GLee_Lazy_glMultiTexCoord2iv(GLenum target, const GLint * v) {if (GLeeInit()) glMultiTexCoord2iv(target, v);} + GLEEPFNGLMULTITEXCOORD2IVPROC GLeeFuncPtr_glMultiTexCoord2iv=GLee_Lazy_glMultiTexCoord2iv; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2s +#define GLEE_C_DEFINED_glMultiTexCoord2s + void __stdcall GLee_Lazy_glMultiTexCoord2s(GLenum target, GLshort s, GLshort t) {if (GLeeInit()) glMultiTexCoord2s(target, s, t);} + GLEEPFNGLMULTITEXCOORD2SPROC GLeeFuncPtr_glMultiTexCoord2s=GLee_Lazy_glMultiTexCoord2s; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2sv +#define GLEE_C_DEFINED_glMultiTexCoord2sv + void __stdcall GLee_Lazy_glMultiTexCoord2sv(GLenum target, const GLshort * v) {if (GLeeInit()) glMultiTexCoord2sv(target, v);} + GLEEPFNGLMULTITEXCOORD2SVPROC GLeeFuncPtr_glMultiTexCoord2sv=GLee_Lazy_glMultiTexCoord2sv; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3d +#define GLEE_C_DEFINED_glMultiTexCoord3d + void __stdcall GLee_Lazy_glMultiTexCoord3d(GLenum target, GLdouble s, GLdouble t, GLdouble r) {if (GLeeInit()) glMultiTexCoord3d(target, s, t, r);} + GLEEPFNGLMULTITEXCOORD3DPROC GLeeFuncPtr_glMultiTexCoord3d=GLee_Lazy_glMultiTexCoord3d; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3dv +#define GLEE_C_DEFINED_glMultiTexCoord3dv + void __stdcall GLee_Lazy_glMultiTexCoord3dv(GLenum target, const GLdouble * v) {if (GLeeInit()) glMultiTexCoord3dv(target, v);} + GLEEPFNGLMULTITEXCOORD3DVPROC GLeeFuncPtr_glMultiTexCoord3dv=GLee_Lazy_glMultiTexCoord3dv; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3f +#define GLEE_C_DEFINED_glMultiTexCoord3f + void __stdcall GLee_Lazy_glMultiTexCoord3f(GLenum target, GLfloat s, GLfloat t, GLfloat r) {if (GLeeInit()) glMultiTexCoord3f(target, s, t, r);} + GLEEPFNGLMULTITEXCOORD3FPROC GLeeFuncPtr_glMultiTexCoord3f=GLee_Lazy_glMultiTexCoord3f; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3fv +#define GLEE_C_DEFINED_glMultiTexCoord3fv + void __stdcall GLee_Lazy_glMultiTexCoord3fv(GLenum target, const GLfloat * v) {if (GLeeInit()) glMultiTexCoord3fv(target, v);} + GLEEPFNGLMULTITEXCOORD3FVPROC GLeeFuncPtr_glMultiTexCoord3fv=GLee_Lazy_glMultiTexCoord3fv; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3i +#define GLEE_C_DEFINED_glMultiTexCoord3i + void __stdcall GLee_Lazy_glMultiTexCoord3i(GLenum target, GLint s, GLint t, GLint r) {if (GLeeInit()) glMultiTexCoord3i(target, s, t, r);} + GLEEPFNGLMULTITEXCOORD3IPROC GLeeFuncPtr_glMultiTexCoord3i=GLee_Lazy_glMultiTexCoord3i; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3iv +#define GLEE_C_DEFINED_glMultiTexCoord3iv + void __stdcall GLee_Lazy_glMultiTexCoord3iv(GLenum target, const GLint * v) {if (GLeeInit()) glMultiTexCoord3iv(target, v);} + GLEEPFNGLMULTITEXCOORD3IVPROC GLeeFuncPtr_glMultiTexCoord3iv=GLee_Lazy_glMultiTexCoord3iv; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3s +#define GLEE_C_DEFINED_glMultiTexCoord3s + void __stdcall GLee_Lazy_glMultiTexCoord3s(GLenum target, GLshort s, GLshort t, GLshort r) {if (GLeeInit()) glMultiTexCoord3s(target, s, t, r);} + GLEEPFNGLMULTITEXCOORD3SPROC GLeeFuncPtr_glMultiTexCoord3s=GLee_Lazy_glMultiTexCoord3s; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3sv +#define GLEE_C_DEFINED_glMultiTexCoord3sv + void __stdcall GLee_Lazy_glMultiTexCoord3sv(GLenum target, const GLshort * v) {if (GLeeInit()) glMultiTexCoord3sv(target, v);} + GLEEPFNGLMULTITEXCOORD3SVPROC GLeeFuncPtr_glMultiTexCoord3sv=GLee_Lazy_glMultiTexCoord3sv; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4d +#define GLEE_C_DEFINED_glMultiTexCoord4d + void __stdcall GLee_Lazy_glMultiTexCoord4d(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q) {if (GLeeInit()) glMultiTexCoord4d(target, s, t, r, q);} + GLEEPFNGLMULTITEXCOORD4DPROC GLeeFuncPtr_glMultiTexCoord4d=GLee_Lazy_glMultiTexCoord4d; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4dv +#define GLEE_C_DEFINED_glMultiTexCoord4dv + void __stdcall GLee_Lazy_glMultiTexCoord4dv(GLenum target, const GLdouble * v) {if (GLeeInit()) glMultiTexCoord4dv(target, v);} + GLEEPFNGLMULTITEXCOORD4DVPROC GLeeFuncPtr_glMultiTexCoord4dv=GLee_Lazy_glMultiTexCoord4dv; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4f +#define GLEE_C_DEFINED_glMultiTexCoord4f + void __stdcall GLee_Lazy_glMultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {if (GLeeInit()) glMultiTexCoord4f(target, s, t, r, q);} + GLEEPFNGLMULTITEXCOORD4FPROC GLeeFuncPtr_glMultiTexCoord4f=GLee_Lazy_glMultiTexCoord4f; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4fv +#define GLEE_C_DEFINED_glMultiTexCoord4fv + void __stdcall GLee_Lazy_glMultiTexCoord4fv(GLenum target, const GLfloat * v) {if (GLeeInit()) glMultiTexCoord4fv(target, v);} + GLEEPFNGLMULTITEXCOORD4FVPROC GLeeFuncPtr_glMultiTexCoord4fv=GLee_Lazy_glMultiTexCoord4fv; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4i +#define GLEE_C_DEFINED_glMultiTexCoord4i + void __stdcall GLee_Lazy_glMultiTexCoord4i(GLenum target, GLint s, GLint t, GLint r, GLint q) {if (GLeeInit()) glMultiTexCoord4i(target, s, t, r, q);} + GLEEPFNGLMULTITEXCOORD4IPROC GLeeFuncPtr_glMultiTexCoord4i=GLee_Lazy_glMultiTexCoord4i; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4iv +#define GLEE_C_DEFINED_glMultiTexCoord4iv + void __stdcall GLee_Lazy_glMultiTexCoord4iv(GLenum target, const GLint * v) {if (GLeeInit()) glMultiTexCoord4iv(target, v);} + GLEEPFNGLMULTITEXCOORD4IVPROC GLeeFuncPtr_glMultiTexCoord4iv=GLee_Lazy_glMultiTexCoord4iv; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4s +#define GLEE_C_DEFINED_glMultiTexCoord4s + void __stdcall GLee_Lazy_glMultiTexCoord4s(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q) {if (GLeeInit()) glMultiTexCoord4s(target, s, t, r, q);} + GLEEPFNGLMULTITEXCOORD4SPROC GLeeFuncPtr_glMultiTexCoord4s=GLee_Lazy_glMultiTexCoord4s; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4sv +#define GLEE_C_DEFINED_glMultiTexCoord4sv + void __stdcall GLee_Lazy_glMultiTexCoord4sv(GLenum target, const GLshort * v) {if (GLeeInit()) glMultiTexCoord4sv(target, v);} + GLEEPFNGLMULTITEXCOORD4SVPROC GLeeFuncPtr_glMultiTexCoord4sv=GLee_Lazy_glMultiTexCoord4sv; +#endif +#ifndef GLEE_C_DEFINED_glLoadTransposeMatrixf +#define GLEE_C_DEFINED_glLoadTransposeMatrixf + void __stdcall GLee_Lazy_glLoadTransposeMatrixf(const GLfloat * m) {if (GLeeInit()) glLoadTransposeMatrixf(m);} + GLEEPFNGLLOADTRANSPOSEMATRIXFPROC GLeeFuncPtr_glLoadTransposeMatrixf=GLee_Lazy_glLoadTransposeMatrixf; +#endif +#ifndef GLEE_C_DEFINED_glLoadTransposeMatrixd +#define GLEE_C_DEFINED_glLoadTransposeMatrixd + void __stdcall GLee_Lazy_glLoadTransposeMatrixd(const GLdouble * m) {if (GLeeInit()) glLoadTransposeMatrixd(m);} + GLEEPFNGLLOADTRANSPOSEMATRIXDPROC GLeeFuncPtr_glLoadTransposeMatrixd=GLee_Lazy_glLoadTransposeMatrixd; +#endif +#ifndef GLEE_C_DEFINED_glMultTransposeMatrixf +#define GLEE_C_DEFINED_glMultTransposeMatrixf + void __stdcall GLee_Lazy_glMultTransposeMatrixf(const GLfloat * m) {if (GLeeInit()) glMultTransposeMatrixf(m);} + GLEEPFNGLMULTTRANSPOSEMATRIXFPROC GLeeFuncPtr_glMultTransposeMatrixf=GLee_Lazy_glMultTransposeMatrixf; +#endif +#ifndef GLEE_C_DEFINED_glMultTransposeMatrixd +#define GLEE_C_DEFINED_glMultTransposeMatrixd + void __stdcall GLee_Lazy_glMultTransposeMatrixd(const GLdouble * m) {if (GLeeInit()) glMultTransposeMatrixd(m);} + GLEEPFNGLMULTTRANSPOSEMATRIXDPROC GLeeFuncPtr_glMultTransposeMatrixd=GLee_Lazy_glMultTransposeMatrixd; +#endif +#ifndef GLEE_C_DEFINED_glSampleCoverage +#define GLEE_C_DEFINED_glSampleCoverage + void __stdcall GLee_Lazy_glSampleCoverage(GLclampf value, GLboolean invert) {if (GLeeInit()) glSampleCoverage(value, invert);} + GLEEPFNGLSAMPLECOVERAGEPROC GLeeFuncPtr_glSampleCoverage=GLee_Lazy_glSampleCoverage; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTexImage3D +#define GLEE_C_DEFINED_glCompressedTexImage3D + void __stdcall GLee_Lazy_glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid * data) {if (GLeeInit()) glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data);} + GLEEPFNGLCOMPRESSEDTEXIMAGE3DPROC GLeeFuncPtr_glCompressedTexImage3D=GLee_Lazy_glCompressedTexImage3D; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTexImage2D +#define GLEE_C_DEFINED_glCompressedTexImage2D + void __stdcall GLee_Lazy_glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * data) {if (GLeeInit()) glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);} + GLEEPFNGLCOMPRESSEDTEXIMAGE2DPROC GLeeFuncPtr_glCompressedTexImage2D=GLee_Lazy_glCompressedTexImage2D; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTexImage1D +#define GLEE_C_DEFINED_glCompressedTexImage1D + void __stdcall GLee_Lazy_glCompressedTexImage1D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid * data) {if (GLeeInit()) glCompressedTexImage1D(target, level, internalformat, width, border, imageSize, data);} + GLEEPFNGLCOMPRESSEDTEXIMAGE1DPROC GLeeFuncPtr_glCompressedTexImage1D=GLee_Lazy_glCompressedTexImage1D; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTexSubImage3D +#define GLEE_C_DEFINED_glCompressedTexSubImage3D + void __stdcall GLee_Lazy_glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid * data) {if (GLeeInit()) glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);} + GLEEPFNGLCOMPRESSEDTEXSUBIMAGE3DPROC GLeeFuncPtr_glCompressedTexSubImage3D=GLee_Lazy_glCompressedTexSubImage3D; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTexSubImage2D +#define GLEE_C_DEFINED_glCompressedTexSubImage2D + void __stdcall GLee_Lazy_glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid * data) {if (GLeeInit()) glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);} + GLEEPFNGLCOMPRESSEDTEXSUBIMAGE2DPROC GLeeFuncPtr_glCompressedTexSubImage2D=GLee_Lazy_glCompressedTexSubImage2D; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTexSubImage1D +#define GLEE_C_DEFINED_glCompressedTexSubImage1D + void __stdcall GLee_Lazy_glCompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid * data) {if (GLeeInit()) glCompressedTexSubImage1D(target, level, xoffset, width, format, imageSize, data);} + GLEEPFNGLCOMPRESSEDTEXSUBIMAGE1DPROC GLeeFuncPtr_glCompressedTexSubImage1D=GLee_Lazy_glCompressedTexSubImage1D; +#endif +#ifndef GLEE_C_DEFINED_glGetCompressedTexImage +#define GLEE_C_DEFINED_glGetCompressedTexImage + void __stdcall GLee_Lazy_glGetCompressedTexImage(GLenum target, GLint level, GLvoid * img) {if (GLeeInit()) glGetCompressedTexImage(target, level, img);} + GLEEPFNGLGETCOMPRESSEDTEXIMAGEPROC GLeeFuncPtr_glGetCompressedTexImage=GLee_Lazy_glGetCompressedTexImage; +#endif +#endif + +/* GL_VERSION_1_4 */ + +#ifdef __GLEE_GL_VERSION_1_4 +#ifndef GLEE_C_DEFINED_glBlendFuncSeparate +#define GLEE_C_DEFINED_glBlendFuncSeparate + void __stdcall GLee_Lazy_glBlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) {if (GLeeInit()) glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);} + GLEEPFNGLBLENDFUNCSEPARATEPROC GLeeFuncPtr_glBlendFuncSeparate=GLee_Lazy_glBlendFuncSeparate; +#endif +#ifndef GLEE_C_DEFINED_glFogCoordf +#define GLEE_C_DEFINED_glFogCoordf + void __stdcall GLee_Lazy_glFogCoordf(GLfloat coord) {if (GLeeInit()) glFogCoordf(coord);} + GLEEPFNGLFOGCOORDFPROC GLeeFuncPtr_glFogCoordf=GLee_Lazy_glFogCoordf; +#endif +#ifndef GLEE_C_DEFINED_glFogCoordfv +#define GLEE_C_DEFINED_glFogCoordfv + void __stdcall GLee_Lazy_glFogCoordfv(const GLfloat * coord) {if (GLeeInit()) glFogCoordfv(coord);} + GLEEPFNGLFOGCOORDFVPROC GLeeFuncPtr_glFogCoordfv=GLee_Lazy_glFogCoordfv; +#endif +#ifndef GLEE_C_DEFINED_glFogCoordd +#define GLEE_C_DEFINED_glFogCoordd + void __stdcall GLee_Lazy_glFogCoordd(GLdouble coord) {if (GLeeInit()) glFogCoordd(coord);} + GLEEPFNGLFOGCOORDDPROC GLeeFuncPtr_glFogCoordd=GLee_Lazy_glFogCoordd; +#endif +#ifndef GLEE_C_DEFINED_glFogCoorddv +#define GLEE_C_DEFINED_glFogCoorddv + void __stdcall GLee_Lazy_glFogCoorddv(const GLdouble * coord) {if (GLeeInit()) glFogCoorddv(coord);} + GLEEPFNGLFOGCOORDDVPROC GLeeFuncPtr_glFogCoorddv=GLee_Lazy_glFogCoorddv; +#endif +#ifndef GLEE_C_DEFINED_glFogCoordPointer +#define GLEE_C_DEFINED_glFogCoordPointer + void __stdcall GLee_Lazy_glFogCoordPointer(GLenum type, GLsizei stride, const GLvoid * pointer) {if (GLeeInit()) glFogCoordPointer(type, stride, pointer);} + GLEEPFNGLFOGCOORDPOINTERPROC GLeeFuncPtr_glFogCoordPointer=GLee_Lazy_glFogCoordPointer; +#endif +#ifndef GLEE_C_DEFINED_glMultiDrawArrays +#define GLEE_C_DEFINED_glMultiDrawArrays + void __stdcall GLee_Lazy_glMultiDrawArrays(GLenum mode, GLint * first, GLsizei * count, GLsizei primcount) {if (GLeeInit()) glMultiDrawArrays(mode, first, count, primcount);} + GLEEPFNGLMULTIDRAWARRAYSPROC GLeeFuncPtr_glMultiDrawArrays=GLee_Lazy_glMultiDrawArrays; +#endif +#ifndef GLEE_C_DEFINED_glMultiDrawElements +#define GLEE_C_DEFINED_glMultiDrawElements + void __stdcall GLee_Lazy_glMultiDrawElements(GLenum mode, const GLsizei * count, GLenum type, const GLvoid* * indices, GLsizei primcount) {if (GLeeInit()) glMultiDrawElements(mode, count, type, indices, primcount);} + GLEEPFNGLMULTIDRAWELEMENTSPROC GLeeFuncPtr_glMultiDrawElements=GLee_Lazy_glMultiDrawElements; +#endif +#ifndef GLEE_C_DEFINED_glPointParameterf +#define GLEE_C_DEFINED_glPointParameterf + void __stdcall GLee_Lazy_glPointParameterf(GLenum pname, GLfloat param) {if (GLeeInit()) glPointParameterf(pname, param);} + GLEEPFNGLPOINTPARAMETERFPROC GLeeFuncPtr_glPointParameterf=GLee_Lazy_glPointParameterf; +#endif +#ifndef GLEE_C_DEFINED_glPointParameterfv +#define GLEE_C_DEFINED_glPointParameterfv + void __stdcall GLee_Lazy_glPointParameterfv(GLenum pname, const GLfloat * params) {if (GLeeInit()) glPointParameterfv(pname, params);} + GLEEPFNGLPOINTPARAMETERFVPROC GLeeFuncPtr_glPointParameterfv=GLee_Lazy_glPointParameterfv; +#endif +#ifndef GLEE_C_DEFINED_glPointParameteri +#define GLEE_C_DEFINED_glPointParameteri + void __stdcall GLee_Lazy_glPointParameteri(GLenum pname, GLint param) {if (GLeeInit()) glPointParameteri(pname, param);} + GLEEPFNGLPOINTPARAMETERIPROC GLeeFuncPtr_glPointParameteri=GLee_Lazy_glPointParameteri; +#endif +#ifndef GLEE_C_DEFINED_glPointParameteriv +#define GLEE_C_DEFINED_glPointParameteriv + void __stdcall GLee_Lazy_glPointParameteriv(GLenum pname, const GLint * params) {if (GLeeInit()) glPointParameteriv(pname, params);} + GLEEPFNGLPOINTPARAMETERIVPROC GLeeFuncPtr_glPointParameteriv=GLee_Lazy_glPointParameteriv; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3b +#define GLEE_C_DEFINED_glSecondaryColor3b + void __stdcall GLee_Lazy_glSecondaryColor3b(GLbyte red, GLbyte green, GLbyte blue) {if (GLeeInit()) glSecondaryColor3b(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3BPROC GLeeFuncPtr_glSecondaryColor3b=GLee_Lazy_glSecondaryColor3b; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3bv +#define GLEE_C_DEFINED_glSecondaryColor3bv + void __stdcall GLee_Lazy_glSecondaryColor3bv(const GLbyte * v) {if (GLeeInit()) glSecondaryColor3bv(v);} + GLEEPFNGLSECONDARYCOLOR3BVPROC GLeeFuncPtr_glSecondaryColor3bv=GLee_Lazy_glSecondaryColor3bv; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3d +#define GLEE_C_DEFINED_glSecondaryColor3d + void __stdcall GLee_Lazy_glSecondaryColor3d(GLdouble red, GLdouble green, GLdouble blue) {if (GLeeInit()) glSecondaryColor3d(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3DPROC GLeeFuncPtr_glSecondaryColor3d=GLee_Lazy_glSecondaryColor3d; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3dv +#define GLEE_C_DEFINED_glSecondaryColor3dv + void __stdcall GLee_Lazy_glSecondaryColor3dv(const GLdouble * v) {if (GLeeInit()) glSecondaryColor3dv(v);} + GLEEPFNGLSECONDARYCOLOR3DVPROC GLeeFuncPtr_glSecondaryColor3dv=GLee_Lazy_glSecondaryColor3dv; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3f +#define GLEE_C_DEFINED_glSecondaryColor3f + void __stdcall GLee_Lazy_glSecondaryColor3f(GLfloat red, GLfloat green, GLfloat blue) {if (GLeeInit()) glSecondaryColor3f(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3FPROC GLeeFuncPtr_glSecondaryColor3f=GLee_Lazy_glSecondaryColor3f; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3fv +#define GLEE_C_DEFINED_glSecondaryColor3fv + void __stdcall GLee_Lazy_glSecondaryColor3fv(const GLfloat * v) {if (GLeeInit()) glSecondaryColor3fv(v);} + GLEEPFNGLSECONDARYCOLOR3FVPROC GLeeFuncPtr_glSecondaryColor3fv=GLee_Lazy_glSecondaryColor3fv; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3i +#define GLEE_C_DEFINED_glSecondaryColor3i + void __stdcall GLee_Lazy_glSecondaryColor3i(GLint red, GLint green, GLint blue) {if (GLeeInit()) glSecondaryColor3i(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3IPROC GLeeFuncPtr_glSecondaryColor3i=GLee_Lazy_glSecondaryColor3i; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3iv +#define GLEE_C_DEFINED_glSecondaryColor3iv + void __stdcall GLee_Lazy_glSecondaryColor3iv(const GLint * v) {if (GLeeInit()) glSecondaryColor3iv(v);} + GLEEPFNGLSECONDARYCOLOR3IVPROC GLeeFuncPtr_glSecondaryColor3iv=GLee_Lazy_glSecondaryColor3iv; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3s +#define GLEE_C_DEFINED_glSecondaryColor3s + void __stdcall GLee_Lazy_glSecondaryColor3s(GLshort red, GLshort green, GLshort blue) {if (GLeeInit()) glSecondaryColor3s(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3SPROC GLeeFuncPtr_glSecondaryColor3s=GLee_Lazy_glSecondaryColor3s; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3sv +#define GLEE_C_DEFINED_glSecondaryColor3sv + void __stdcall GLee_Lazy_glSecondaryColor3sv(const GLshort * v) {if (GLeeInit()) glSecondaryColor3sv(v);} + GLEEPFNGLSECONDARYCOLOR3SVPROC GLeeFuncPtr_glSecondaryColor3sv=GLee_Lazy_glSecondaryColor3sv; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3ub +#define GLEE_C_DEFINED_glSecondaryColor3ub + void __stdcall GLee_Lazy_glSecondaryColor3ub(GLubyte red, GLubyte green, GLubyte blue) {if (GLeeInit()) glSecondaryColor3ub(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3UBPROC GLeeFuncPtr_glSecondaryColor3ub=GLee_Lazy_glSecondaryColor3ub; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3ubv +#define GLEE_C_DEFINED_glSecondaryColor3ubv + void __stdcall GLee_Lazy_glSecondaryColor3ubv(const GLubyte * v) {if (GLeeInit()) glSecondaryColor3ubv(v);} + GLEEPFNGLSECONDARYCOLOR3UBVPROC GLeeFuncPtr_glSecondaryColor3ubv=GLee_Lazy_glSecondaryColor3ubv; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3ui +#define GLEE_C_DEFINED_glSecondaryColor3ui + void __stdcall GLee_Lazy_glSecondaryColor3ui(GLuint red, GLuint green, GLuint blue) {if (GLeeInit()) glSecondaryColor3ui(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3UIPROC GLeeFuncPtr_glSecondaryColor3ui=GLee_Lazy_glSecondaryColor3ui; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3uiv +#define GLEE_C_DEFINED_glSecondaryColor3uiv + void __stdcall GLee_Lazy_glSecondaryColor3uiv(const GLuint * v) {if (GLeeInit()) glSecondaryColor3uiv(v);} + GLEEPFNGLSECONDARYCOLOR3UIVPROC GLeeFuncPtr_glSecondaryColor3uiv=GLee_Lazy_glSecondaryColor3uiv; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3us +#define GLEE_C_DEFINED_glSecondaryColor3us + void __stdcall GLee_Lazy_glSecondaryColor3us(GLushort red, GLushort green, GLushort blue) {if (GLeeInit()) glSecondaryColor3us(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3USPROC GLeeFuncPtr_glSecondaryColor3us=GLee_Lazy_glSecondaryColor3us; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3usv +#define GLEE_C_DEFINED_glSecondaryColor3usv + void __stdcall GLee_Lazy_glSecondaryColor3usv(const GLushort * v) {if (GLeeInit()) glSecondaryColor3usv(v);} + GLEEPFNGLSECONDARYCOLOR3USVPROC GLeeFuncPtr_glSecondaryColor3usv=GLee_Lazy_glSecondaryColor3usv; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColorPointer +#define GLEE_C_DEFINED_glSecondaryColorPointer + void __stdcall GLee_Lazy_glSecondaryColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {if (GLeeInit()) glSecondaryColorPointer(size, type, stride, pointer);} + GLEEPFNGLSECONDARYCOLORPOINTERPROC GLeeFuncPtr_glSecondaryColorPointer=GLee_Lazy_glSecondaryColorPointer; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2d +#define GLEE_C_DEFINED_glWindowPos2d + void __stdcall GLee_Lazy_glWindowPos2d(GLdouble x, GLdouble y) {if (GLeeInit()) glWindowPos2d(x, y);} + GLEEPFNGLWINDOWPOS2DPROC GLeeFuncPtr_glWindowPos2d=GLee_Lazy_glWindowPos2d; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2dv +#define GLEE_C_DEFINED_glWindowPos2dv + void __stdcall GLee_Lazy_glWindowPos2dv(const GLdouble * v) {if (GLeeInit()) glWindowPos2dv(v);} + GLEEPFNGLWINDOWPOS2DVPROC GLeeFuncPtr_glWindowPos2dv=GLee_Lazy_glWindowPos2dv; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2f +#define GLEE_C_DEFINED_glWindowPos2f + void __stdcall GLee_Lazy_glWindowPos2f(GLfloat x, GLfloat y) {if (GLeeInit()) glWindowPos2f(x, y);} + GLEEPFNGLWINDOWPOS2FPROC GLeeFuncPtr_glWindowPos2f=GLee_Lazy_glWindowPos2f; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2fv +#define GLEE_C_DEFINED_glWindowPos2fv + void __stdcall GLee_Lazy_glWindowPos2fv(const GLfloat * v) {if (GLeeInit()) glWindowPos2fv(v);} + GLEEPFNGLWINDOWPOS2FVPROC GLeeFuncPtr_glWindowPos2fv=GLee_Lazy_glWindowPos2fv; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2i +#define GLEE_C_DEFINED_glWindowPos2i + void __stdcall GLee_Lazy_glWindowPos2i(GLint x, GLint y) {if (GLeeInit()) glWindowPos2i(x, y);} + GLEEPFNGLWINDOWPOS2IPROC GLeeFuncPtr_glWindowPos2i=GLee_Lazy_glWindowPos2i; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2iv +#define GLEE_C_DEFINED_glWindowPos2iv + void __stdcall GLee_Lazy_glWindowPos2iv(const GLint * v) {if (GLeeInit()) glWindowPos2iv(v);} + GLEEPFNGLWINDOWPOS2IVPROC GLeeFuncPtr_glWindowPos2iv=GLee_Lazy_glWindowPos2iv; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2s +#define GLEE_C_DEFINED_glWindowPos2s + void __stdcall GLee_Lazy_glWindowPos2s(GLshort x, GLshort y) {if (GLeeInit()) glWindowPos2s(x, y);} + GLEEPFNGLWINDOWPOS2SPROC GLeeFuncPtr_glWindowPos2s=GLee_Lazy_glWindowPos2s; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2sv +#define GLEE_C_DEFINED_glWindowPos2sv + void __stdcall GLee_Lazy_glWindowPos2sv(const GLshort * v) {if (GLeeInit()) glWindowPos2sv(v);} + GLEEPFNGLWINDOWPOS2SVPROC GLeeFuncPtr_glWindowPos2sv=GLee_Lazy_glWindowPos2sv; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3d +#define GLEE_C_DEFINED_glWindowPos3d + void __stdcall GLee_Lazy_glWindowPos3d(GLdouble x, GLdouble y, GLdouble z) {if (GLeeInit()) glWindowPos3d(x, y, z);} + GLEEPFNGLWINDOWPOS3DPROC GLeeFuncPtr_glWindowPos3d=GLee_Lazy_glWindowPos3d; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3dv +#define GLEE_C_DEFINED_glWindowPos3dv + void __stdcall GLee_Lazy_glWindowPos3dv(const GLdouble * v) {if (GLeeInit()) glWindowPos3dv(v);} + GLEEPFNGLWINDOWPOS3DVPROC GLeeFuncPtr_glWindowPos3dv=GLee_Lazy_glWindowPos3dv; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3f +#define GLEE_C_DEFINED_glWindowPos3f + void __stdcall GLee_Lazy_glWindowPos3f(GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glWindowPos3f(x, y, z);} + GLEEPFNGLWINDOWPOS3FPROC GLeeFuncPtr_glWindowPos3f=GLee_Lazy_glWindowPos3f; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3fv +#define GLEE_C_DEFINED_glWindowPos3fv + void __stdcall GLee_Lazy_glWindowPos3fv(const GLfloat * v) {if (GLeeInit()) glWindowPos3fv(v);} + GLEEPFNGLWINDOWPOS3FVPROC GLeeFuncPtr_glWindowPos3fv=GLee_Lazy_glWindowPos3fv; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3i +#define GLEE_C_DEFINED_glWindowPos3i + void __stdcall GLee_Lazy_glWindowPos3i(GLint x, GLint y, GLint z) {if (GLeeInit()) glWindowPos3i(x, y, z);} + GLEEPFNGLWINDOWPOS3IPROC GLeeFuncPtr_glWindowPos3i=GLee_Lazy_glWindowPos3i; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3iv +#define GLEE_C_DEFINED_glWindowPos3iv + void __stdcall GLee_Lazy_glWindowPos3iv(const GLint * v) {if (GLeeInit()) glWindowPos3iv(v);} + GLEEPFNGLWINDOWPOS3IVPROC GLeeFuncPtr_glWindowPos3iv=GLee_Lazy_glWindowPos3iv; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3s +#define GLEE_C_DEFINED_glWindowPos3s + void __stdcall GLee_Lazy_glWindowPos3s(GLshort x, GLshort y, GLshort z) {if (GLeeInit()) glWindowPos3s(x, y, z);} + GLEEPFNGLWINDOWPOS3SPROC GLeeFuncPtr_glWindowPos3s=GLee_Lazy_glWindowPos3s; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3sv +#define GLEE_C_DEFINED_glWindowPos3sv + void __stdcall GLee_Lazy_glWindowPos3sv(const GLshort * v) {if (GLeeInit()) glWindowPos3sv(v);} + GLEEPFNGLWINDOWPOS3SVPROC GLeeFuncPtr_glWindowPos3sv=GLee_Lazy_glWindowPos3sv; +#endif +#endif + +/* GL_VERSION_1_5 */ + +#ifdef __GLEE_GL_VERSION_1_5 +#ifndef GLEE_C_DEFINED_glGenQueries +#define GLEE_C_DEFINED_glGenQueries + void __stdcall GLee_Lazy_glGenQueries(GLsizei n, GLuint * ids) {if (GLeeInit()) glGenQueries(n, ids);} + GLEEPFNGLGENQUERIESPROC GLeeFuncPtr_glGenQueries=GLee_Lazy_glGenQueries; +#endif +#ifndef GLEE_C_DEFINED_glDeleteQueries +#define GLEE_C_DEFINED_glDeleteQueries + void __stdcall GLee_Lazy_glDeleteQueries(GLsizei n, const GLuint * ids) {if (GLeeInit()) glDeleteQueries(n, ids);} + GLEEPFNGLDELETEQUERIESPROC GLeeFuncPtr_glDeleteQueries=GLee_Lazy_glDeleteQueries; +#endif +#ifndef GLEE_C_DEFINED_glIsQuery +#define GLEE_C_DEFINED_glIsQuery + GLboolean __stdcall GLee_Lazy_glIsQuery(GLuint id) {if (GLeeInit()) return glIsQuery(id); return (GLboolean)0;} + GLEEPFNGLISQUERYPROC GLeeFuncPtr_glIsQuery=GLee_Lazy_glIsQuery; +#endif +#ifndef GLEE_C_DEFINED_glBeginQuery +#define GLEE_C_DEFINED_glBeginQuery + void __stdcall GLee_Lazy_glBeginQuery(GLenum target, GLuint id) {if (GLeeInit()) glBeginQuery(target, id);} + GLEEPFNGLBEGINQUERYPROC GLeeFuncPtr_glBeginQuery=GLee_Lazy_glBeginQuery; +#endif +#ifndef GLEE_C_DEFINED_glEndQuery +#define GLEE_C_DEFINED_glEndQuery + void __stdcall GLee_Lazy_glEndQuery(GLenum target) {if (GLeeInit()) glEndQuery(target);} + GLEEPFNGLENDQUERYPROC GLeeFuncPtr_glEndQuery=GLee_Lazy_glEndQuery; +#endif +#ifndef GLEE_C_DEFINED_glGetQueryiv +#define GLEE_C_DEFINED_glGetQueryiv + void __stdcall GLee_Lazy_glGetQueryiv(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetQueryiv(target, pname, params);} + GLEEPFNGLGETQUERYIVPROC GLeeFuncPtr_glGetQueryiv=GLee_Lazy_glGetQueryiv; +#endif +#ifndef GLEE_C_DEFINED_glGetQueryObjectiv +#define GLEE_C_DEFINED_glGetQueryObjectiv + void __stdcall GLee_Lazy_glGetQueryObjectiv(GLuint id, GLenum pname, GLint * params) {if (GLeeInit()) glGetQueryObjectiv(id, pname, params);} + GLEEPFNGLGETQUERYOBJECTIVPROC GLeeFuncPtr_glGetQueryObjectiv=GLee_Lazy_glGetQueryObjectiv; +#endif +#ifndef GLEE_C_DEFINED_glGetQueryObjectuiv +#define GLEE_C_DEFINED_glGetQueryObjectuiv + void __stdcall GLee_Lazy_glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint * params) {if (GLeeInit()) glGetQueryObjectuiv(id, pname, params);} + GLEEPFNGLGETQUERYOBJECTUIVPROC GLeeFuncPtr_glGetQueryObjectuiv=GLee_Lazy_glGetQueryObjectuiv; +#endif +#ifndef GLEE_C_DEFINED_glBindBuffer +#define GLEE_C_DEFINED_glBindBuffer + void __stdcall GLee_Lazy_glBindBuffer(GLenum target, GLuint buffer) {if (GLeeInit()) glBindBuffer(target, buffer);} + GLEEPFNGLBINDBUFFERPROC GLeeFuncPtr_glBindBuffer=GLee_Lazy_glBindBuffer; +#endif +#ifndef GLEE_C_DEFINED_glDeleteBuffers +#define GLEE_C_DEFINED_glDeleteBuffers + void __stdcall GLee_Lazy_glDeleteBuffers(GLsizei n, const GLuint * buffers) {if (GLeeInit()) glDeleteBuffers(n, buffers);} + GLEEPFNGLDELETEBUFFERSPROC GLeeFuncPtr_glDeleteBuffers=GLee_Lazy_glDeleteBuffers; +#endif +#ifndef GLEE_C_DEFINED_glGenBuffers +#define GLEE_C_DEFINED_glGenBuffers + void __stdcall GLee_Lazy_glGenBuffers(GLsizei n, GLuint * buffers) {if (GLeeInit()) glGenBuffers(n, buffers);} + GLEEPFNGLGENBUFFERSPROC GLeeFuncPtr_glGenBuffers=GLee_Lazy_glGenBuffers; +#endif +#ifndef GLEE_C_DEFINED_glIsBuffer +#define GLEE_C_DEFINED_glIsBuffer + GLboolean __stdcall GLee_Lazy_glIsBuffer(GLuint buffer) {if (GLeeInit()) return glIsBuffer(buffer); return (GLboolean)0;} + GLEEPFNGLISBUFFERPROC GLeeFuncPtr_glIsBuffer=GLee_Lazy_glIsBuffer; +#endif +#ifndef GLEE_C_DEFINED_glBufferData +#define GLEE_C_DEFINED_glBufferData + void __stdcall GLee_Lazy_glBufferData(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {if (GLeeInit()) glBufferData(target, size, data, usage);} + GLEEPFNGLBUFFERDATAPROC GLeeFuncPtr_glBufferData=GLee_Lazy_glBufferData; +#endif +#ifndef GLEE_C_DEFINED_glBufferSubData +#define GLEE_C_DEFINED_glBufferSubData + void __stdcall GLee_Lazy_glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {if (GLeeInit()) glBufferSubData(target, offset, size, data);} + GLEEPFNGLBUFFERSUBDATAPROC GLeeFuncPtr_glBufferSubData=GLee_Lazy_glBufferSubData; +#endif +#ifndef GLEE_C_DEFINED_glGetBufferSubData +#define GLEE_C_DEFINED_glGetBufferSubData + void __stdcall GLee_Lazy_glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid * data) {if (GLeeInit()) glGetBufferSubData(target, offset, size, data);} + GLEEPFNGLGETBUFFERSUBDATAPROC GLeeFuncPtr_glGetBufferSubData=GLee_Lazy_glGetBufferSubData; +#endif +#ifndef GLEE_C_DEFINED_glMapBuffer +#define GLEE_C_DEFINED_glMapBuffer + GLvoid* __stdcall GLee_Lazy_glMapBuffer(GLenum target, GLenum access) {if (GLeeInit()) return glMapBuffer(target, access); return (GLvoid*)0;} + GLEEPFNGLMAPBUFFERPROC GLeeFuncPtr_glMapBuffer=GLee_Lazy_glMapBuffer; +#endif +#ifndef GLEE_C_DEFINED_glUnmapBuffer +#define GLEE_C_DEFINED_glUnmapBuffer + GLboolean __stdcall GLee_Lazy_glUnmapBuffer(GLenum target) {if (GLeeInit()) return glUnmapBuffer(target); return (GLboolean)0;} + GLEEPFNGLUNMAPBUFFERPROC GLeeFuncPtr_glUnmapBuffer=GLee_Lazy_glUnmapBuffer; +#endif +#ifndef GLEE_C_DEFINED_glGetBufferParameteriv +#define GLEE_C_DEFINED_glGetBufferParameteriv + void __stdcall GLee_Lazy_glGetBufferParameteriv(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetBufferParameteriv(target, pname, params);} + GLEEPFNGLGETBUFFERPARAMETERIVPROC GLeeFuncPtr_glGetBufferParameteriv=GLee_Lazy_glGetBufferParameteriv; +#endif +#ifndef GLEE_C_DEFINED_glGetBufferPointerv +#define GLEE_C_DEFINED_glGetBufferPointerv + void __stdcall GLee_Lazy_glGetBufferPointerv(GLenum target, GLenum pname, GLvoid* * params) {if (GLeeInit()) glGetBufferPointerv(target, pname, params);} + GLEEPFNGLGETBUFFERPOINTERVPROC GLeeFuncPtr_glGetBufferPointerv=GLee_Lazy_glGetBufferPointerv; +#endif +#endif + +/* GL_VERSION_2_0 */ + +#ifdef __GLEE_GL_VERSION_2_0 +#ifndef GLEE_C_DEFINED_glBlendEquationSeparate +#define GLEE_C_DEFINED_glBlendEquationSeparate + void __stdcall GLee_Lazy_glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {if (GLeeInit()) glBlendEquationSeparate(modeRGB, modeAlpha);} + GLEEPFNGLBLENDEQUATIONSEPARATEPROC GLeeFuncPtr_glBlendEquationSeparate=GLee_Lazy_glBlendEquationSeparate; +#endif +#ifndef GLEE_C_DEFINED_glDrawBuffers +#define GLEE_C_DEFINED_glDrawBuffers + void __stdcall GLee_Lazy_glDrawBuffers(GLsizei n, const GLenum * bufs) {if (GLeeInit()) glDrawBuffers(n, bufs);} + GLEEPFNGLDRAWBUFFERSPROC GLeeFuncPtr_glDrawBuffers=GLee_Lazy_glDrawBuffers; +#endif +#ifndef GLEE_C_DEFINED_glStencilOpSeparate +#define GLEE_C_DEFINED_glStencilOpSeparate + void __stdcall GLee_Lazy_glStencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) {if (GLeeInit()) glStencilOpSeparate(face, sfail, dpfail, dppass);} + GLEEPFNGLSTENCILOPSEPARATEPROC GLeeFuncPtr_glStencilOpSeparate=GLee_Lazy_glStencilOpSeparate; +#endif +#ifndef GLEE_C_DEFINED_glStencilFuncSeparate +#define GLEE_C_DEFINED_glStencilFuncSeparate + void __stdcall GLee_Lazy_glStencilFuncSeparate(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask) {if (GLeeInit()) glStencilFuncSeparate(frontfunc, backfunc, ref, mask);} + GLEEPFNGLSTENCILFUNCSEPARATEPROC GLeeFuncPtr_glStencilFuncSeparate=GLee_Lazy_glStencilFuncSeparate; +#endif +#ifndef GLEE_C_DEFINED_glStencilMaskSeparate +#define GLEE_C_DEFINED_glStencilMaskSeparate + void __stdcall GLee_Lazy_glStencilMaskSeparate(GLenum face, GLuint mask) {if (GLeeInit()) glStencilMaskSeparate(face, mask);} + GLEEPFNGLSTENCILMASKSEPARATEPROC GLeeFuncPtr_glStencilMaskSeparate=GLee_Lazy_glStencilMaskSeparate; +#endif +#ifndef GLEE_C_DEFINED_glAttachShader +#define GLEE_C_DEFINED_glAttachShader + void __stdcall GLee_Lazy_glAttachShader(GLuint program, GLuint shader) {if (GLeeInit()) glAttachShader(program, shader);} + GLEEPFNGLATTACHSHADERPROC GLeeFuncPtr_glAttachShader=GLee_Lazy_glAttachShader; +#endif +#ifndef GLEE_C_DEFINED_glBindAttribLocation +#define GLEE_C_DEFINED_glBindAttribLocation + void __stdcall GLee_Lazy_glBindAttribLocation(GLuint program, GLuint index, const GLchar * name) {if (GLeeInit()) glBindAttribLocation(program, index, name);} + GLEEPFNGLBINDATTRIBLOCATIONPROC GLeeFuncPtr_glBindAttribLocation=GLee_Lazy_glBindAttribLocation; +#endif +#ifndef GLEE_C_DEFINED_glCompileShader +#define GLEE_C_DEFINED_glCompileShader + void __stdcall GLee_Lazy_glCompileShader(GLuint shader) {if (GLeeInit()) glCompileShader(shader);} + GLEEPFNGLCOMPILESHADERPROC GLeeFuncPtr_glCompileShader=GLee_Lazy_glCompileShader; +#endif +#ifndef GLEE_C_DEFINED_glCreateProgram +#define GLEE_C_DEFINED_glCreateProgram + GLuint __stdcall GLee_Lazy_glCreateProgram(void) {if (GLeeInit()) return glCreateProgram(); return (GLuint)0;} + GLEEPFNGLCREATEPROGRAMPROC GLeeFuncPtr_glCreateProgram=GLee_Lazy_glCreateProgram; +#endif +#ifndef GLEE_C_DEFINED_glCreateShader +#define GLEE_C_DEFINED_glCreateShader + GLuint __stdcall GLee_Lazy_glCreateShader(GLenum type) {if (GLeeInit()) return glCreateShader(type); return (GLuint)0;} + GLEEPFNGLCREATESHADERPROC GLeeFuncPtr_glCreateShader=GLee_Lazy_glCreateShader; +#endif +#ifndef GLEE_C_DEFINED_glDeleteProgram +#define GLEE_C_DEFINED_glDeleteProgram + void __stdcall GLee_Lazy_glDeleteProgram(GLuint program) {if (GLeeInit()) glDeleteProgram(program);} + GLEEPFNGLDELETEPROGRAMPROC GLeeFuncPtr_glDeleteProgram=GLee_Lazy_glDeleteProgram; +#endif +#ifndef GLEE_C_DEFINED_glDeleteShader +#define GLEE_C_DEFINED_glDeleteShader + void __stdcall GLee_Lazy_glDeleteShader(GLuint shader) {if (GLeeInit()) glDeleteShader(shader);} + GLEEPFNGLDELETESHADERPROC GLeeFuncPtr_glDeleteShader=GLee_Lazy_glDeleteShader; +#endif +#ifndef GLEE_C_DEFINED_glDetachShader +#define GLEE_C_DEFINED_glDetachShader + void __stdcall GLee_Lazy_glDetachShader(GLuint program, GLuint shader) {if (GLeeInit()) glDetachShader(program, shader);} + GLEEPFNGLDETACHSHADERPROC GLeeFuncPtr_glDetachShader=GLee_Lazy_glDetachShader; +#endif +#ifndef GLEE_C_DEFINED_glDisableVertexAttribArray +#define GLEE_C_DEFINED_glDisableVertexAttribArray + void __stdcall GLee_Lazy_glDisableVertexAttribArray(GLuint index) {if (GLeeInit()) glDisableVertexAttribArray(index);} + GLEEPFNGLDISABLEVERTEXATTRIBARRAYPROC GLeeFuncPtr_glDisableVertexAttribArray=GLee_Lazy_glDisableVertexAttribArray; +#endif +#ifndef GLEE_C_DEFINED_glEnableVertexAttribArray +#define GLEE_C_DEFINED_glEnableVertexAttribArray + void __stdcall GLee_Lazy_glEnableVertexAttribArray(GLuint index) {if (GLeeInit()) glEnableVertexAttribArray(index);} + GLEEPFNGLENABLEVERTEXATTRIBARRAYPROC GLeeFuncPtr_glEnableVertexAttribArray=GLee_Lazy_glEnableVertexAttribArray; +#endif +#ifndef GLEE_C_DEFINED_glGetActiveAttrib +#define GLEE_C_DEFINED_glGetActiveAttrib + void __stdcall GLee_Lazy_glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name) {if (GLeeInit()) glGetActiveAttrib(program, index, bufSize, length, size, type, name);} + GLEEPFNGLGETACTIVEATTRIBPROC GLeeFuncPtr_glGetActiveAttrib=GLee_Lazy_glGetActiveAttrib; +#endif +#ifndef GLEE_C_DEFINED_glGetActiveUniform +#define GLEE_C_DEFINED_glGetActiveUniform + void __stdcall GLee_Lazy_glGetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name) {if (GLeeInit()) glGetActiveUniform(program, index, bufSize, length, size, type, name);} + GLEEPFNGLGETACTIVEUNIFORMPROC GLeeFuncPtr_glGetActiveUniform=GLee_Lazy_glGetActiveUniform; +#endif +#ifndef GLEE_C_DEFINED_glGetAttachedShaders +#define GLEE_C_DEFINED_glGetAttachedShaders + void __stdcall GLee_Lazy_glGetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * obj) {if (GLeeInit()) glGetAttachedShaders(program, maxCount, count, obj);} + GLEEPFNGLGETATTACHEDSHADERSPROC GLeeFuncPtr_glGetAttachedShaders=GLee_Lazy_glGetAttachedShaders; +#endif +#ifndef GLEE_C_DEFINED_glGetAttribLocation +#define GLEE_C_DEFINED_glGetAttribLocation + GLint __stdcall GLee_Lazy_glGetAttribLocation(GLuint program, const GLchar * name) {if (GLeeInit()) return glGetAttribLocation(program, name); return (GLint)0;} + GLEEPFNGLGETATTRIBLOCATIONPROC GLeeFuncPtr_glGetAttribLocation=GLee_Lazy_glGetAttribLocation; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramiv +#define GLEE_C_DEFINED_glGetProgramiv + void __stdcall GLee_Lazy_glGetProgramiv(GLuint program, GLenum pname, GLint * params) {if (GLeeInit()) glGetProgramiv(program, pname, params);} + GLEEPFNGLGETPROGRAMIVPROC GLeeFuncPtr_glGetProgramiv=GLee_Lazy_glGetProgramiv; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramInfoLog +#define GLEE_C_DEFINED_glGetProgramInfoLog + void __stdcall GLee_Lazy_glGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog) {if (GLeeInit()) glGetProgramInfoLog(program, bufSize, length, infoLog);} + GLEEPFNGLGETPROGRAMINFOLOGPROC GLeeFuncPtr_glGetProgramInfoLog=GLee_Lazy_glGetProgramInfoLog; +#endif +#ifndef GLEE_C_DEFINED_glGetShaderiv +#define GLEE_C_DEFINED_glGetShaderiv + void __stdcall GLee_Lazy_glGetShaderiv(GLuint shader, GLenum pname, GLint * params) {if (GLeeInit()) glGetShaderiv(shader, pname, params);} + GLEEPFNGLGETSHADERIVPROC GLeeFuncPtr_glGetShaderiv=GLee_Lazy_glGetShaderiv; +#endif +#ifndef GLEE_C_DEFINED_glGetShaderInfoLog +#define GLEE_C_DEFINED_glGetShaderInfoLog + void __stdcall GLee_Lazy_glGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog) {if (GLeeInit()) glGetShaderInfoLog(shader, bufSize, length, infoLog);} + GLEEPFNGLGETSHADERINFOLOGPROC GLeeFuncPtr_glGetShaderInfoLog=GLee_Lazy_glGetShaderInfoLog; +#endif +#ifndef GLEE_C_DEFINED_glGetShaderSource +#define GLEE_C_DEFINED_glGetShaderSource + void __stdcall GLee_Lazy_glGetShaderSource(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source) {if (GLeeInit()) glGetShaderSource(shader, bufSize, length, source);} + GLEEPFNGLGETSHADERSOURCEPROC GLeeFuncPtr_glGetShaderSource=GLee_Lazy_glGetShaderSource; +#endif +#ifndef GLEE_C_DEFINED_glGetUniformLocation +#define GLEE_C_DEFINED_glGetUniformLocation + GLint __stdcall GLee_Lazy_glGetUniformLocation(GLuint program, const GLchar * name) {if (GLeeInit()) return glGetUniformLocation(program, name); return (GLint)0;} + GLEEPFNGLGETUNIFORMLOCATIONPROC GLeeFuncPtr_glGetUniformLocation=GLee_Lazy_glGetUniformLocation; +#endif +#ifndef GLEE_C_DEFINED_glGetUniformfv +#define GLEE_C_DEFINED_glGetUniformfv + void __stdcall GLee_Lazy_glGetUniformfv(GLuint program, GLint location, GLfloat * params) {if (GLeeInit()) glGetUniformfv(program, location, params);} + GLEEPFNGLGETUNIFORMFVPROC GLeeFuncPtr_glGetUniformfv=GLee_Lazy_glGetUniformfv; +#endif +#ifndef GLEE_C_DEFINED_glGetUniformiv +#define GLEE_C_DEFINED_glGetUniformiv + void __stdcall GLee_Lazy_glGetUniformiv(GLuint program, GLint location, GLint * params) {if (GLeeInit()) glGetUniformiv(program, location, params);} + GLEEPFNGLGETUNIFORMIVPROC GLeeFuncPtr_glGetUniformiv=GLee_Lazy_glGetUniformiv; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribdv +#define GLEE_C_DEFINED_glGetVertexAttribdv + void __stdcall GLee_Lazy_glGetVertexAttribdv(GLuint index, GLenum pname, GLdouble * params) {if (GLeeInit()) glGetVertexAttribdv(index, pname, params);} + GLEEPFNGLGETVERTEXATTRIBDVPROC GLeeFuncPtr_glGetVertexAttribdv=GLee_Lazy_glGetVertexAttribdv; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribfv +#define GLEE_C_DEFINED_glGetVertexAttribfv + void __stdcall GLee_Lazy_glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetVertexAttribfv(index, pname, params);} + GLEEPFNGLGETVERTEXATTRIBFVPROC GLeeFuncPtr_glGetVertexAttribfv=GLee_Lazy_glGetVertexAttribfv; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribiv +#define GLEE_C_DEFINED_glGetVertexAttribiv + void __stdcall GLee_Lazy_glGetVertexAttribiv(GLuint index, GLenum pname, GLint * params) {if (GLeeInit()) glGetVertexAttribiv(index, pname, params);} + GLEEPFNGLGETVERTEXATTRIBIVPROC GLeeFuncPtr_glGetVertexAttribiv=GLee_Lazy_glGetVertexAttribiv; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribPointerv +#define GLEE_C_DEFINED_glGetVertexAttribPointerv + void __stdcall GLee_Lazy_glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid* * pointer) {if (GLeeInit()) glGetVertexAttribPointerv(index, pname, pointer);} + GLEEPFNGLGETVERTEXATTRIBPOINTERVPROC GLeeFuncPtr_glGetVertexAttribPointerv=GLee_Lazy_glGetVertexAttribPointerv; +#endif +#ifndef GLEE_C_DEFINED_glIsProgram +#define GLEE_C_DEFINED_glIsProgram + GLboolean __stdcall GLee_Lazy_glIsProgram(GLuint program) {if (GLeeInit()) return glIsProgram(program); return (GLboolean)0;} + GLEEPFNGLISPROGRAMPROC GLeeFuncPtr_glIsProgram=GLee_Lazy_glIsProgram; +#endif +#ifndef GLEE_C_DEFINED_glIsShader +#define GLEE_C_DEFINED_glIsShader + GLboolean __stdcall GLee_Lazy_glIsShader(GLuint shader) {if (GLeeInit()) return glIsShader(shader); return (GLboolean)0;} + GLEEPFNGLISSHADERPROC GLeeFuncPtr_glIsShader=GLee_Lazy_glIsShader; +#endif +#ifndef GLEE_C_DEFINED_glLinkProgram +#define GLEE_C_DEFINED_glLinkProgram + void __stdcall GLee_Lazy_glLinkProgram(GLuint program) {if (GLeeInit()) glLinkProgram(program);} + GLEEPFNGLLINKPROGRAMPROC GLeeFuncPtr_glLinkProgram=GLee_Lazy_glLinkProgram; +#endif +#ifndef GLEE_C_DEFINED_glShaderSource +#define GLEE_C_DEFINED_glShaderSource + void __stdcall GLee_Lazy_glShaderSource(GLuint shader, GLsizei count, const GLchar* * string, const GLint * length) {if (GLeeInit()) glShaderSource(shader, count, string, length);} + GLEEPFNGLSHADERSOURCEPROC GLeeFuncPtr_glShaderSource=GLee_Lazy_glShaderSource; +#endif +#ifndef GLEE_C_DEFINED_glUseProgram +#define GLEE_C_DEFINED_glUseProgram + void __stdcall GLee_Lazy_glUseProgram(GLuint program) {if (GLeeInit()) glUseProgram(program);} + GLEEPFNGLUSEPROGRAMPROC GLeeFuncPtr_glUseProgram=GLee_Lazy_glUseProgram; +#endif +#ifndef GLEE_C_DEFINED_glUniform1f +#define GLEE_C_DEFINED_glUniform1f + void __stdcall GLee_Lazy_glUniform1f(GLint location, GLfloat v0) {if (GLeeInit()) glUniform1f(location, v0);} + GLEEPFNGLUNIFORM1FPROC GLeeFuncPtr_glUniform1f=GLee_Lazy_glUniform1f; +#endif +#ifndef GLEE_C_DEFINED_glUniform2f +#define GLEE_C_DEFINED_glUniform2f + void __stdcall GLee_Lazy_glUniform2f(GLint location, GLfloat v0, GLfloat v1) {if (GLeeInit()) glUniform2f(location, v0, v1);} + GLEEPFNGLUNIFORM2FPROC GLeeFuncPtr_glUniform2f=GLee_Lazy_glUniform2f; +#endif +#ifndef GLEE_C_DEFINED_glUniform3f +#define GLEE_C_DEFINED_glUniform3f + void __stdcall GLee_Lazy_glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {if (GLeeInit()) glUniform3f(location, v0, v1, v2);} + GLEEPFNGLUNIFORM3FPROC GLeeFuncPtr_glUniform3f=GLee_Lazy_glUniform3f; +#endif +#ifndef GLEE_C_DEFINED_glUniform4f +#define GLEE_C_DEFINED_glUniform4f + void __stdcall GLee_Lazy_glUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {if (GLeeInit()) glUniform4f(location, v0, v1, v2, v3);} + GLEEPFNGLUNIFORM4FPROC GLeeFuncPtr_glUniform4f=GLee_Lazy_glUniform4f; +#endif +#ifndef GLEE_C_DEFINED_glUniform1i +#define GLEE_C_DEFINED_glUniform1i + void __stdcall GLee_Lazy_glUniform1i(GLint location, GLint v0) {if (GLeeInit()) glUniform1i(location, v0);} + GLEEPFNGLUNIFORM1IPROC GLeeFuncPtr_glUniform1i=GLee_Lazy_glUniform1i; +#endif +#ifndef GLEE_C_DEFINED_glUniform2i +#define GLEE_C_DEFINED_glUniform2i + void __stdcall GLee_Lazy_glUniform2i(GLint location, GLint v0, GLint v1) {if (GLeeInit()) glUniform2i(location, v0, v1);} + GLEEPFNGLUNIFORM2IPROC GLeeFuncPtr_glUniform2i=GLee_Lazy_glUniform2i; +#endif +#ifndef GLEE_C_DEFINED_glUniform3i +#define GLEE_C_DEFINED_glUniform3i + void __stdcall GLee_Lazy_glUniform3i(GLint location, GLint v0, GLint v1, GLint v2) {if (GLeeInit()) glUniform3i(location, v0, v1, v2);} + GLEEPFNGLUNIFORM3IPROC GLeeFuncPtr_glUniform3i=GLee_Lazy_glUniform3i; +#endif +#ifndef GLEE_C_DEFINED_glUniform4i +#define GLEE_C_DEFINED_glUniform4i + void __stdcall GLee_Lazy_glUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {if (GLeeInit()) glUniform4i(location, v0, v1, v2, v3);} + GLEEPFNGLUNIFORM4IPROC GLeeFuncPtr_glUniform4i=GLee_Lazy_glUniform4i; +#endif +#ifndef GLEE_C_DEFINED_glUniform1fv +#define GLEE_C_DEFINED_glUniform1fv + void __stdcall GLee_Lazy_glUniform1fv(GLint location, GLsizei count, const GLfloat * value) {if (GLeeInit()) glUniform1fv(location, count, value);} + GLEEPFNGLUNIFORM1FVPROC GLeeFuncPtr_glUniform1fv=GLee_Lazy_glUniform1fv; +#endif +#ifndef GLEE_C_DEFINED_glUniform2fv +#define GLEE_C_DEFINED_glUniform2fv + void __stdcall GLee_Lazy_glUniform2fv(GLint location, GLsizei count, const GLfloat * value) {if (GLeeInit()) glUniform2fv(location, count, value);} + GLEEPFNGLUNIFORM2FVPROC GLeeFuncPtr_glUniform2fv=GLee_Lazy_glUniform2fv; +#endif +#ifndef GLEE_C_DEFINED_glUniform3fv +#define GLEE_C_DEFINED_glUniform3fv + void __stdcall GLee_Lazy_glUniform3fv(GLint location, GLsizei count, const GLfloat * value) {if (GLeeInit()) glUniform3fv(location, count, value);} + GLEEPFNGLUNIFORM3FVPROC GLeeFuncPtr_glUniform3fv=GLee_Lazy_glUniform3fv; +#endif +#ifndef GLEE_C_DEFINED_glUniform4fv +#define GLEE_C_DEFINED_glUniform4fv + void __stdcall GLee_Lazy_glUniform4fv(GLint location, GLsizei count, const GLfloat * value) {if (GLeeInit()) glUniform4fv(location, count, value);} + GLEEPFNGLUNIFORM4FVPROC GLeeFuncPtr_glUniform4fv=GLee_Lazy_glUniform4fv; +#endif +#ifndef GLEE_C_DEFINED_glUniform1iv +#define GLEE_C_DEFINED_glUniform1iv + void __stdcall GLee_Lazy_glUniform1iv(GLint location, GLsizei count, const GLint * value) {if (GLeeInit()) glUniform1iv(location, count, value);} + GLEEPFNGLUNIFORM1IVPROC GLeeFuncPtr_glUniform1iv=GLee_Lazy_glUniform1iv; +#endif +#ifndef GLEE_C_DEFINED_glUniform2iv +#define GLEE_C_DEFINED_glUniform2iv + void __stdcall GLee_Lazy_glUniform2iv(GLint location, GLsizei count, const GLint * value) {if (GLeeInit()) glUniform2iv(location, count, value);} + GLEEPFNGLUNIFORM2IVPROC GLeeFuncPtr_glUniform2iv=GLee_Lazy_glUniform2iv; +#endif +#ifndef GLEE_C_DEFINED_glUniform3iv +#define GLEE_C_DEFINED_glUniform3iv + void __stdcall GLee_Lazy_glUniform3iv(GLint location, GLsizei count, const GLint * value) {if (GLeeInit()) glUniform3iv(location, count, value);} + GLEEPFNGLUNIFORM3IVPROC GLeeFuncPtr_glUniform3iv=GLee_Lazy_glUniform3iv; +#endif +#ifndef GLEE_C_DEFINED_glUniform4iv +#define GLEE_C_DEFINED_glUniform4iv + void __stdcall GLee_Lazy_glUniform4iv(GLint location, GLsizei count, const GLint * value) {if (GLeeInit()) glUniform4iv(location, count, value);} + GLEEPFNGLUNIFORM4IVPROC GLeeFuncPtr_glUniform4iv=GLee_Lazy_glUniform4iv; +#endif +#ifndef GLEE_C_DEFINED_glUniformMatrix2fv +#define GLEE_C_DEFINED_glUniformMatrix2fv + void __stdcall GLee_Lazy_glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glUniformMatrix2fv(location, count, transpose, value);} + GLEEPFNGLUNIFORMMATRIX2FVPROC GLeeFuncPtr_glUniformMatrix2fv=GLee_Lazy_glUniformMatrix2fv; +#endif +#ifndef GLEE_C_DEFINED_glUniformMatrix3fv +#define GLEE_C_DEFINED_glUniformMatrix3fv + void __stdcall GLee_Lazy_glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glUniformMatrix3fv(location, count, transpose, value);} + GLEEPFNGLUNIFORMMATRIX3FVPROC GLeeFuncPtr_glUniformMatrix3fv=GLee_Lazy_glUniformMatrix3fv; +#endif +#ifndef GLEE_C_DEFINED_glUniformMatrix4fv +#define GLEE_C_DEFINED_glUniformMatrix4fv + void __stdcall GLee_Lazy_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glUniformMatrix4fv(location, count, transpose, value);} + GLEEPFNGLUNIFORMMATRIX4FVPROC GLeeFuncPtr_glUniformMatrix4fv=GLee_Lazy_glUniformMatrix4fv; +#endif +#ifndef GLEE_C_DEFINED_glValidateProgram +#define GLEE_C_DEFINED_glValidateProgram + void __stdcall GLee_Lazy_glValidateProgram(GLuint program) {if (GLeeInit()) glValidateProgram(program);} + GLEEPFNGLVALIDATEPROGRAMPROC GLeeFuncPtr_glValidateProgram=GLee_Lazy_glValidateProgram; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1d +#define GLEE_C_DEFINED_glVertexAttrib1d + void __stdcall GLee_Lazy_glVertexAttrib1d(GLuint index, GLdouble x) {if (GLeeInit()) glVertexAttrib1d(index, x);} + GLEEPFNGLVERTEXATTRIB1DPROC GLeeFuncPtr_glVertexAttrib1d=GLee_Lazy_glVertexAttrib1d; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1dv +#define GLEE_C_DEFINED_glVertexAttrib1dv + void __stdcall GLee_Lazy_glVertexAttrib1dv(GLuint index, const GLdouble * v) {if (GLeeInit()) glVertexAttrib1dv(index, v);} + GLEEPFNGLVERTEXATTRIB1DVPROC GLeeFuncPtr_glVertexAttrib1dv=GLee_Lazy_glVertexAttrib1dv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1f +#define GLEE_C_DEFINED_glVertexAttrib1f + void __stdcall GLee_Lazy_glVertexAttrib1f(GLuint index, GLfloat x) {if (GLeeInit()) glVertexAttrib1f(index, x);} + GLEEPFNGLVERTEXATTRIB1FPROC GLeeFuncPtr_glVertexAttrib1f=GLee_Lazy_glVertexAttrib1f; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1fv +#define GLEE_C_DEFINED_glVertexAttrib1fv + void __stdcall GLee_Lazy_glVertexAttrib1fv(GLuint index, const GLfloat * v) {if (GLeeInit()) glVertexAttrib1fv(index, v);} + GLEEPFNGLVERTEXATTRIB1FVPROC GLeeFuncPtr_glVertexAttrib1fv=GLee_Lazy_glVertexAttrib1fv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1s +#define GLEE_C_DEFINED_glVertexAttrib1s + void __stdcall GLee_Lazy_glVertexAttrib1s(GLuint index, GLshort x) {if (GLeeInit()) glVertexAttrib1s(index, x);} + GLEEPFNGLVERTEXATTRIB1SPROC GLeeFuncPtr_glVertexAttrib1s=GLee_Lazy_glVertexAttrib1s; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1sv +#define GLEE_C_DEFINED_glVertexAttrib1sv + void __stdcall GLee_Lazy_glVertexAttrib1sv(GLuint index, const GLshort * v) {if (GLeeInit()) glVertexAttrib1sv(index, v);} + GLEEPFNGLVERTEXATTRIB1SVPROC GLeeFuncPtr_glVertexAttrib1sv=GLee_Lazy_glVertexAttrib1sv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2d +#define GLEE_C_DEFINED_glVertexAttrib2d + void __stdcall GLee_Lazy_glVertexAttrib2d(GLuint index, GLdouble x, GLdouble y) {if (GLeeInit()) glVertexAttrib2d(index, x, y);} + GLEEPFNGLVERTEXATTRIB2DPROC GLeeFuncPtr_glVertexAttrib2d=GLee_Lazy_glVertexAttrib2d; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2dv +#define GLEE_C_DEFINED_glVertexAttrib2dv + void __stdcall GLee_Lazy_glVertexAttrib2dv(GLuint index, const GLdouble * v) {if (GLeeInit()) glVertexAttrib2dv(index, v);} + GLEEPFNGLVERTEXATTRIB2DVPROC GLeeFuncPtr_glVertexAttrib2dv=GLee_Lazy_glVertexAttrib2dv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2f +#define GLEE_C_DEFINED_glVertexAttrib2f + void __stdcall GLee_Lazy_glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) {if (GLeeInit()) glVertexAttrib2f(index, x, y);} + GLEEPFNGLVERTEXATTRIB2FPROC GLeeFuncPtr_glVertexAttrib2f=GLee_Lazy_glVertexAttrib2f; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2fv +#define GLEE_C_DEFINED_glVertexAttrib2fv + void __stdcall GLee_Lazy_glVertexAttrib2fv(GLuint index, const GLfloat * v) {if (GLeeInit()) glVertexAttrib2fv(index, v);} + GLEEPFNGLVERTEXATTRIB2FVPROC GLeeFuncPtr_glVertexAttrib2fv=GLee_Lazy_glVertexAttrib2fv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2s +#define GLEE_C_DEFINED_glVertexAttrib2s + void __stdcall GLee_Lazy_glVertexAttrib2s(GLuint index, GLshort x, GLshort y) {if (GLeeInit()) glVertexAttrib2s(index, x, y);} + GLEEPFNGLVERTEXATTRIB2SPROC GLeeFuncPtr_glVertexAttrib2s=GLee_Lazy_glVertexAttrib2s; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2sv +#define GLEE_C_DEFINED_glVertexAttrib2sv + void __stdcall GLee_Lazy_glVertexAttrib2sv(GLuint index, const GLshort * v) {if (GLeeInit()) glVertexAttrib2sv(index, v);} + GLEEPFNGLVERTEXATTRIB2SVPROC GLeeFuncPtr_glVertexAttrib2sv=GLee_Lazy_glVertexAttrib2sv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3d +#define GLEE_C_DEFINED_glVertexAttrib3d + void __stdcall GLee_Lazy_glVertexAttrib3d(GLuint index, GLdouble x, GLdouble y, GLdouble z) {if (GLeeInit()) glVertexAttrib3d(index, x, y, z);} + GLEEPFNGLVERTEXATTRIB3DPROC GLeeFuncPtr_glVertexAttrib3d=GLee_Lazy_glVertexAttrib3d; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3dv +#define GLEE_C_DEFINED_glVertexAttrib3dv + void __stdcall GLee_Lazy_glVertexAttrib3dv(GLuint index, const GLdouble * v) {if (GLeeInit()) glVertexAttrib3dv(index, v);} + GLEEPFNGLVERTEXATTRIB3DVPROC GLeeFuncPtr_glVertexAttrib3dv=GLee_Lazy_glVertexAttrib3dv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3f +#define GLEE_C_DEFINED_glVertexAttrib3f + void __stdcall GLee_Lazy_glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glVertexAttrib3f(index, x, y, z);} + GLEEPFNGLVERTEXATTRIB3FPROC GLeeFuncPtr_glVertexAttrib3f=GLee_Lazy_glVertexAttrib3f; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3fv +#define GLEE_C_DEFINED_glVertexAttrib3fv + void __stdcall GLee_Lazy_glVertexAttrib3fv(GLuint index, const GLfloat * v) {if (GLeeInit()) glVertexAttrib3fv(index, v);} + GLEEPFNGLVERTEXATTRIB3FVPROC GLeeFuncPtr_glVertexAttrib3fv=GLee_Lazy_glVertexAttrib3fv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3s +#define GLEE_C_DEFINED_glVertexAttrib3s + void __stdcall GLee_Lazy_glVertexAttrib3s(GLuint index, GLshort x, GLshort y, GLshort z) {if (GLeeInit()) glVertexAttrib3s(index, x, y, z);} + GLEEPFNGLVERTEXATTRIB3SPROC GLeeFuncPtr_glVertexAttrib3s=GLee_Lazy_glVertexAttrib3s; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3sv +#define GLEE_C_DEFINED_glVertexAttrib3sv + void __stdcall GLee_Lazy_glVertexAttrib3sv(GLuint index, const GLshort * v) {if (GLeeInit()) glVertexAttrib3sv(index, v);} + GLEEPFNGLVERTEXATTRIB3SVPROC GLeeFuncPtr_glVertexAttrib3sv=GLee_Lazy_glVertexAttrib3sv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4Nbv +#define GLEE_C_DEFINED_glVertexAttrib4Nbv + void __stdcall GLee_Lazy_glVertexAttrib4Nbv(GLuint index, const GLbyte * v) {if (GLeeInit()) glVertexAttrib4Nbv(index, v);} + GLEEPFNGLVERTEXATTRIB4NBVPROC GLeeFuncPtr_glVertexAttrib4Nbv=GLee_Lazy_glVertexAttrib4Nbv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4Niv +#define GLEE_C_DEFINED_glVertexAttrib4Niv + void __stdcall GLee_Lazy_glVertexAttrib4Niv(GLuint index, const GLint * v) {if (GLeeInit()) glVertexAttrib4Niv(index, v);} + GLEEPFNGLVERTEXATTRIB4NIVPROC GLeeFuncPtr_glVertexAttrib4Niv=GLee_Lazy_glVertexAttrib4Niv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4Nsv +#define GLEE_C_DEFINED_glVertexAttrib4Nsv + void __stdcall GLee_Lazy_glVertexAttrib4Nsv(GLuint index, const GLshort * v) {if (GLeeInit()) glVertexAttrib4Nsv(index, v);} + GLEEPFNGLVERTEXATTRIB4NSVPROC GLeeFuncPtr_glVertexAttrib4Nsv=GLee_Lazy_glVertexAttrib4Nsv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4Nub +#define GLEE_C_DEFINED_glVertexAttrib4Nub + void __stdcall GLee_Lazy_glVertexAttrib4Nub(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) {if (GLeeInit()) glVertexAttrib4Nub(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIB4NUBPROC GLeeFuncPtr_glVertexAttrib4Nub=GLee_Lazy_glVertexAttrib4Nub; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4Nubv +#define GLEE_C_DEFINED_glVertexAttrib4Nubv + void __stdcall GLee_Lazy_glVertexAttrib4Nubv(GLuint index, const GLubyte * v) {if (GLeeInit()) glVertexAttrib4Nubv(index, v);} + GLEEPFNGLVERTEXATTRIB4NUBVPROC GLeeFuncPtr_glVertexAttrib4Nubv=GLee_Lazy_glVertexAttrib4Nubv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4Nuiv +#define GLEE_C_DEFINED_glVertexAttrib4Nuiv + void __stdcall GLee_Lazy_glVertexAttrib4Nuiv(GLuint index, const GLuint * v) {if (GLeeInit()) glVertexAttrib4Nuiv(index, v);} + GLEEPFNGLVERTEXATTRIB4NUIVPROC GLeeFuncPtr_glVertexAttrib4Nuiv=GLee_Lazy_glVertexAttrib4Nuiv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4Nusv +#define GLEE_C_DEFINED_glVertexAttrib4Nusv + void __stdcall GLee_Lazy_glVertexAttrib4Nusv(GLuint index, const GLushort * v) {if (GLeeInit()) glVertexAttrib4Nusv(index, v);} + GLEEPFNGLVERTEXATTRIB4NUSVPROC GLeeFuncPtr_glVertexAttrib4Nusv=GLee_Lazy_glVertexAttrib4Nusv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4bv +#define GLEE_C_DEFINED_glVertexAttrib4bv + void __stdcall GLee_Lazy_glVertexAttrib4bv(GLuint index, const GLbyte * v) {if (GLeeInit()) glVertexAttrib4bv(index, v);} + GLEEPFNGLVERTEXATTRIB4BVPROC GLeeFuncPtr_glVertexAttrib4bv=GLee_Lazy_glVertexAttrib4bv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4d +#define GLEE_C_DEFINED_glVertexAttrib4d + void __stdcall GLee_Lazy_glVertexAttrib4d(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) {if (GLeeInit()) glVertexAttrib4d(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIB4DPROC GLeeFuncPtr_glVertexAttrib4d=GLee_Lazy_glVertexAttrib4d; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4dv +#define GLEE_C_DEFINED_glVertexAttrib4dv + void __stdcall GLee_Lazy_glVertexAttrib4dv(GLuint index, const GLdouble * v) {if (GLeeInit()) glVertexAttrib4dv(index, v);} + GLEEPFNGLVERTEXATTRIB4DVPROC GLeeFuncPtr_glVertexAttrib4dv=GLee_Lazy_glVertexAttrib4dv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4f +#define GLEE_C_DEFINED_glVertexAttrib4f + void __stdcall GLee_Lazy_glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {if (GLeeInit()) glVertexAttrib4f(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIB4FPROC GLeeFuncPtr_glVertexAttrib4f=GLee_Lazy_glVertexAttrib4f; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4fv +#define GLEE_C_DEFINED_glVertexAttrib4fv + void __stdcall GLee_Lazy_glVertexAttrib4fv(GLuint index, const GLfloat * v) {if (GLeeInit()) glVertexAttrib4fv(index, v);} + GLEEPFNGLVERTEXATTRIB4FVPROC GLeeFuncPtr_glVertexAttrib4fv=GLee_Lazy_glVertexAttrib4fv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4iv +#define GLEE_C_DEFINED_glVertexAttrib4iv + void __stdcall GLee_Lazy_glVertexAttrib4iv(GLuint index, const GLint * v) {if (GLeeInit()) glVertexAttrib4iv(index, v);} + GLEEPFNGLVERTEXATTRIB4IVPROC GLeeFuncPtr_glVertexAttrib4iv=GLee_Lazy_glVertexAttrib4iv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4s +#define GLEE_C_DEFINED_glVertexAttrib4s + void __stdcall GLee_Lazy_glVertexAttrib4s(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) {if (GLeeInit()) glVertexAttrib4s(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIB4SPROC GLeeFuncPtr_glVertexAttrib4s=GLee_Lazy_glVertexAttrib4s; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4sv +#define GLEE_C_DEFINED_glVertexAttrib4sv + void __stdcall GLee_Lazy_glVertexAttrib4sv(GLuint index, const GLshort * v) {if (GLeeInit()) glVertexAttrib4sv(index, v);} + GLEEPFNGLVERTEXATTRIB4SVPROC GLeeFuncPtr_glVertexAttrib4sv=GLee_Lazy_glVertexAttrib4sv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4ubv +#define GLEE_C_DEFINED_glVertexAttrib4ubv + void __stdcall GLee_Lazy_glVertexAttrib4ubv(GLuint index, const GLubyte * v) {if (GLeeInit()) glVertexAttrib4ubv(index, v);} + GLEEPFNGLVERTEXATTRIB4UBVPROC GLeeFuncPtr_glVertexAttrib4ubv=GLee_Lazy_glVertexAttrib4ubv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4uiv +#define GLEE_C_DEFINED_glVertexAttrib4uiv + void __stdcall GLee_Lazy_glVertexAttrib4uiv(GLuint index, const GLuint * v) {if (GLeeInit()) glVertexAttrib4uiv(index, v);} + GLEEPFNGLVERTEXATTRIB4UIVPROC GLeeFuncPtr_glVertexAttrib4uiv=GLee_Lazy_glVertexAttrib4uiv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4usv +#define GLEE_C_DEFINED_glVertexAttrib4usv + void __stdcall GLee_Lazy_glVertexAttrib4usv(GLuint index, const GLushort * v) {if (GLeeInit()) glVertexAttrib4usv(index, v);} + GLEEPFNGLVERTEXATTRIB4USVPROC GLeeFuncPtr_glVertexAttrib4usv=GLee_Lazy_glVertexAttrib4usv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribPointer +#define GLEE_C_DEFINED_glVertexAttribPointer + void __stdcall GLee_Lazy_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer) {if (GLeeInit()) glVertexAttribPointer(index, size, type, normalized, stride, pointer);} + GLEEPFNGLVERTEXATTRIBPOINTERPROC GLeeFuncPtr_glVertexAttribPointer=GLee_Lazy_glVertexAttribPointer; +#endif +#endif + +/* GL_VERSION_2_1 */ + +#ifdef __GLEE_GL_VERSION_2_1 +#ifndef GLEE_C_DEFINED_glUniformMatrix2x3fv +#define GLEE_C_DEFINED_glUniformMatrix2x3fv + void __stdcall GLee_Lazy_glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glUniformMatrix2x3fv(location, count, transpose, value);} + GLEEPFNGLUNIFORMMATRIX2X3FVPROC GLeeFuncPtr_glUniformMatrix2x3fv=GLee_Lazy_glUniformMatrix2x3fv; +#endif +#ifndef GLEE_C_DEFINED_glUniformMatrix3x2fv +#define GLEE_C_DEFINED_glUniformMatrix3x2fv + void __stdcall GLee_Lazy_glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glUniformMatrix3x2fv(location, count, transpose, value);} + GLEEPFNGLUNIFORMMATRIX3X2FVPROC GLeeFuncPtr_glUniformMatrix3x2fv=GLee_Lazy_glUniformMatrix3x2fv; +#endif +#ifndef GLEE_C_DEFINED_glUniformMatrix2x4fv +#define GLEE_C_DEFINED_glUniformMatrix2x4fv + void __stdcall GLee_Lazy_glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glUniformMatrix2x4fv(location, count, transpose, value);} + GLEEPFNGLUNIFORMMATRIX2X4FVPROC GLeeFuncPtr_glUniformMatrix2x4fv=GLee_Lazy_glUniformMatrix2x4fv; +#endif +#ifndef GLEE_C_DEFINED_glUniformMatrix4x2fv +#define GLEE_C_DEFINED_glUniformMatrix4x2fv + void __stdcall GLee_Lazy_glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glUniformMatrix4x2fv(location, count, transpose, value);} + GLEEPFNGLUNIFORMMATRIX4X2FVPROC GLeeFuncPtr_glUniformMatrix4x2fv=GLee_Lazy_glUniformMatrix4x2fv; +#endif +#ifndef GLEE_C_DEFINED_glUniformMatrix3x4fv +#define GLEE_C_DEFINED_glUniformMatrix3x4fv + void __stdcall GLee_Lazy_glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glUniformMatrix3x4fv(location, count, transpose, value);} + GLEEPFNGLUNIFORMMATRIX3X4FVPROC GLeeFuncPtr_glUniformMatrix3x4fv=GLee_Lazy_glUniformMatrix3x4fv; +#endif +#ifndef GLEE_C_DEFINED_glUniformMatrix4x3fv +#define GLEE_C_DEFINED_glUniformMatrix4x3fv + void __stdcall GLee_Lazy_glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glUniformMatrix4x3fv(location, count, transpose, value);} + GLEEPFNGLUNIFORMMATRIX4X3FVPROC GLeeFuncPtr_glUniformMatrix4x3fv=GLee_Lazy_glUniformMatrix4x3fv; +#endif +#endif + +/* GL_VERSION_3_0 */ + +#ifdef __GLEE_GL_VERSION_3_0 +#ifndef GLEE_C_DEFINED_glColorMaski +#define GLEE_C_DEFINED_glColorMaski + void __stdcall GLee_Lazy_glColorMaski(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) {if (GLeeInit()) glColorMaski(index, r, g, b, a);} + GLEEPFNGLCOLORMASKIPROC GLeeFuncPtr_glColorMaski=GLee_Lazy_glColorMaski; +#endif +#ifndef GLEE_C_DEFINED_glGetBooleani_v +#define GLEE_C_DEFINED_glGetBooleani_v + void __stdcall GLee_Lazy_glGetBooleani_v(GLenum target, GLuint index, GLboolean * data) {if (GLeeInit()) glGetBooleani_v(target, index, data);} + GLEEPFNGLGETBOOLEANI_VPROC GLeeFuncPtr_glGetBooleani_v=GLee_Lazy_glGetBooleani_v; +#endif +#ifndef GLEE_C_DEFINED_glGetIntegeri_v +#define GLEE_C_DEFINED_glGetIntegeri_v + void __stdcall GLee_Lazy_glGetIntegeri_v(GLenum target, GLuint index, GLint * data) {if (GLeeInit()) glGetIntegeri_v(target, index, data);} + GLEEPFNGLGETINTEGERI_VPROC GLeeFuncPtr_glGetIntegeri_v=GLee_Lazy_glGetIntegeri_v; +#endif +#ifndef GLEE_C_DEFINED_glEnablei +#define GLEE_C_DEFINED_glEnablei + void __stdcall GLee_Lazy_glEnablei(GLenum target, GLuint index) {if (GLeeInit()) glEnablei(target, index);} + GLEEPFNGLENABLEIPROC GLeeFuncPtr_glEnablei=GLee_Lazy_glEnablei; +#endif +#ifndef GLEE_C_DEFINED_glDisablei +#define GLEE_C_DEFINED_glDisablei + void __stdcall GLee_Lazy_glDisablei(GLenum target, GLuint index) {if (GLeeInit()) glDisablei(target, index);} + GLEEPFNGLDISABLEIPROC GLeeFuncPtr_glDisablei=GLee_Lazy_glDisablei; +#endif +#ifndef GLEE_C_DEFINED_glIsEnabledi +#define GLEE_C_DEFINED_glIsEnabledi + GLboolean __stdcall GLee_Lazy_glIsEnabledi(GLenum target, GLuint index) {if (GLeeInit()) return glIsEnabledi(target, index); return (GLboolean)0;} + GLEEPFNGLISENABLEDIPROC GLeeFuncPtr_glIsEnabledi=GLee_Lazy_glIsEnabledi; +#endif +#ifndef GLEE_C_DEFINED_glBeginTransformFeedback +#define GLEE_C_DEFINED_glBeginTransformFeedback + void __stdcall GLee_Lazy_glBeginTransformFeedback(GLenum primitiveMode) {if (GLeeInit()) glBeginTransformFeedback(primitiveMode);} + GLEEPFNGLBEGINTRANSFORMFEEDBACKPROC GLeeFuncPtr_glBeginTransformFeedback=GLee_Lazy_glBeginTransformFeedback; +#endif +#ifndef GLEE_C_DEFINED_glEndTransformFeedback +#define GLEE_C_DEFINED_glEndTransformFeedback + void __stdcall GLee_Lazy_glEndTransformFeedback(void) {if (GLeeInit()) glEndTransformFeedback();} + GLEEPFNGLENDTRANSFORMFEEDBACKPROC GLeeFuncPtr_glEndTransformFeedback=GLee_Lazy_glEndTransformFeedback; +#endif +#ifndef GLEE_C_DEFINED_glBindBufferRange +#define GLEE_C_DEFINED_glBindBufferRange + void __stdcall GLee_Lazy_glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {if (GLeeInit()) glBindBufferRange(target, index, buffer, offset, size);} + GLEEPFNGLBINDBUFFERRANGEPROC GLeeFuncPtr_glBindBufferRange=GLee_Lazy_glBindBufferRange; +#endif +#ifndef GLEE_C_DEFINED_glBindBufferBase +#define GLEE_C_DEFINED_glBindBufferBase + void __stdcall GLee_Lazy_glBindBufferBase(GLenum target, GLuint index, GLuint buffer) {if (GLeeInit()) glBindBufferBase(target, index, buffer);} + GLEEPFNGLBINDBUFFERBASEPROC GLeeFuncPtr_glBindBufferBase=GLee_Lazy_glBindBufferBase; +#endif +#ifndef GLEE_C_DEFINED_glTransformFeedbackVaryings +#define GLEE_C_DEFINED_glTransformFeedbackVaryings + void __stdcall GLee_Lazy_glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLint * locations, GLenum bufferMode) {if (GLeeInit()) glTransformFeedbackVaryings(program, count, locations, bufferMode);} + GLEEPFNGLTRANSFORMFEEDBACKVARYINGSPROC GLeeFuncPtr_glTransformFeedbackVaryings=GLee_Lazy_glTransformFeedbackVaryings; +#endif +#ifndef GLEE_C_DEFINED_glGetTransformFeedbackVarying +#define GLEE_C_DEFINED_glGetTransformFeedbackVarying + void __stdcall GLee_Lazy_glGetTransformFeedbackVarying(GLuint program, GLuint index, GLint * location) {if (GLeeInit()) glGetTransformFeedbackVarying(program, index, location);} + GLEEPFNGLGETTRANSFORMFEEDBACKVARYINGPROC GLeeFuncPtr_glGetTransformFeedbackVarying=GLee_Lazy_glGetTransformFeedbackVarying; +#endif +#ifndef GLEE_C_DEFINED_glClampColor +#define GLEE_C_DEFINED_glClampColor + void __stdcall GLee_Lazy_glClampColor(GLenum target, GLenum clamp) {if (GLeeInit()) glClampColor(target, clamp);} + GLEEPFNGLCLAMPCOLORPROC GLeeFuncPtr_glClampColor=GLee_Lazy_glClampColor; +#endif +#ifndef GLEE_C_DEFINED_glBeginConditionalRender +#define GLEE_C_DEFINED_glBeginConditionalRender + void __stdcall GLee_Lazy_glBeginConditionalRender(GLuint id, GLenum mode) {if (GLeeInit()) glBeginConditionalRender(id, mode);} + GLEEPFNGLBEGINCONDITIONALRENDERPROC GLeeFuncPtr_glBeginConditionalRender=GLee_Lazy_glBeginConditionalRender; +#endif +#ifndef GLEE_C_DEFINED_glEndConditionalRender +#define GLEE_C_DEFINED_glEndConditionalRender + void __stdcall GLee_Lazy_glEndConditionalRender(void) {if (GLeeInit()) glEndConditionalRender();} + GLEEPFNGLENDCONDITIONALRENDERPROC GLeeFuncPtr_glEndConditionalRender=GLee_Lazy_glEndConditionalRender; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI1i +#define GLEE_C_DEFINED_glVertexAttribI1i + void __stdcall GLee_Lazy_glVertexAttribI1i(GLuint index, GLint x) {if (GLeeInit()) glVertexAttribI1i(index, x);} + GLEEPFNGLVERTEXATTRIBI1IPROC GLeeFuncPtr_glVertexAttribI1i=GLee_Lazy_glVertexAttribI1i; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI2i +#define GLEE_C_DEFINED_glVertexAttribI2i + void __stdcall GLee_Lazy_glVertexAttribI2i(GLuint index, GLint x, GLint y) {if (GLeeInit()) glVertexAttribI2i(index, x, y);} + GLEEPFNGLVERTEXATTRIBI2IPROC GLeeFuncPtr_glVertexAttribI2i=GLee_Lazy_glVertexAttribI2i; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI3i +#define GLEE_C_DEFINED_glVertexAttribI3i + void __stdcall GLee_Lazy_glVertexAttribI3i(GLuint index, GLint x, GLint y, GLint z) {if (GLeeInit()) glVertexAttribI3i(index, x, y, z);} + GLEEPFNGLVERTEXATTRIBI3IPROC GLeeFuncPtr_glVertexAttribI3i=GLee_Lazy_glVertexAttribI3i; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI4i +#define GLEE_C_DEFINED_glVertexAttribI4i + void __stdcall GLee_Lazy_glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) {if (GLeeInit()) glVertexAttribI4i(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIBI4IPROC GLeeFuncPtr_glVertexAttribI4i=GLee_Lazy_glVertexAttribI4i; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI1ui +#define GLEE_C_DEFINED_glVertexAttribI1ui + void __stdcall GLee_Lazy_glVertexAttribI1ui(GLuint index, GLuint x) {if (GLeeInit()) glVertexAttribI1ui(index, x);} + GLEEPFNGLVERTEXATTRIBI1UIPROC GLeeFuncPtr_glVertexAttribI1ui=GLee_Lazy_glVertexAttribI1ui; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI2ui +#define GLEE_C_DEFINED_glVertexAttribI2ui + void __stdcall GLee_Lazy_glVertexAttribI2ui(GLuint index, GLuint x, GLuint y) {if (GLeeInit()) glVertexAttribI2ui(index, x, y);} + GLEEPFNGLVERTEXATTRIBI2UIPROC GLeeFuncPtr_glVertexAttribI2ui=GLee_Lazy_glVertexAttribI2ui; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI3ui +#define GLEE_C_DEFINED_glVertexAttribI3ui + void __stdcall GLee_Lazy_glVertexAttribI3ui(GLuint index, GLuint x, GLuint y, GLuint z) {if (GLeeInit()) glVertexAttribI3ui(index, x, y, z);} + GLEEPFNGLVERTEXATTRIBI3UIPROC GLeeFuncPtr_glVertexAttribI3ui=GLee_Lazy_glVertexAttribI3ui; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI4ui +#define GLEE_C_DEFINED_glVertexAttribI4ui + void __stdcall GLee_Lazy_glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) {if (GLeeInit()) glVertexAttribI4ui(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIBI4UIPROC GLeeFuncPtr_glVertexAttribI4ui=GLee_Lazy_glVertexAttribI4ui; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI1iv +#define GLEE_C_DEFINED_glVertexAttribI1iv + void __stdcall GLee_Lazy_glVertexAttribI1iv(GLuint index, const GLint * v) {if (GLeeInit()) glVertexAttribI1iv(index, v);} + GLEEPFNGLVERTEXATTRIBI1IVPROC GLeeFuncPtr_glVertexAttribI1iv=GLee_Lazy_glVertexAttribI1iv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI2iv +#define GLEE_C_DEFINED_glVertexAttribI2iv + void __stdcall GLee_Lazy_glVertexAttribI2iv(GLuint index, const GLint * v) {if (GLeeInit()) glVertexAttribI2iv(index, v);} + GLEEPFNGLVERTEXATTRIBI2IVPROC GLeeFuncPtr_glVertexAttribI2iv=GLee_Lazy_glVertexAttribI2iv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI3iv +#define GLEE_C_DEFINED_glVertexAttribI3iv + void __stdcall GLee_Lazy_glVertexAttribI3iv(GLuint index, const GLint * v) {if (GLeeInit()) glVertexAttribI3iv(index, v);} + GLEEPFNGLVERTEXATTRIBI3IVPROC GLeeFuncPtr_glVertexAttribI3iv=GLee_Lazy_glVertexAttribI3iv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI4iv +#define GLEE_C_DEFINED_glVertexAttribI4iv + void __stdcall GLee_Lazy_glVertexAttribI4iv(GLuint index, const GLint * v) {if (GLeeInit()) glVertexAttribI4iv(index, v);} + GLEEPFNGLVERTEXATTRIBI4IVPROC GLeeFuncPtr_glVertexAttribI4iv=GLee_Lazy_glVertexAttribI4iv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI1uiv +#define GLEE_C_DEFINED_glVertexAttribI1uiv + void __stdcall GLee_Lazy_glVertexAttribI1uiv(GLuint index, const GLuint * v) {if (GLeeInit()) glVertexAttribI1uiv(index, v);} + GLEEPFNGLVERTEXATTRIBI1UIVPROC GLeeFuncPtr_glVertexAttribI1uiv=GLee_Lazy_glVertexAttribI1uiv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI2uiv +#define GLEE_C_DEFINED_glVertexAttribI2uiv + void __stdcall GLee_Lazy_glVertexAttribI2uiv(GLuint index, const GLuint * v) {if (GLeeInit()) glVertexAttribI2uiv(index, v);} + GLEEPFNGLVERTEXATTRIBI2UIVPROC GLeeFuncPtr_glVertexAttribI2uiv=GLee_Lazy_glVertexAttribI2uiv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI3uiv +#define GLEE_C_DEFINED_glVertexAttribI3uiv + void __stdcall GLee_Lazy_glVertexAttribI3uiv(GLuint index, const GLuint * v) {if (GLeeInit()) glVertexAttribI3uiv(index, v);} + GLEEPFNGLVERTEXATTRIBI3UIVPROC GLeeFuncPtr_glVertexAttribI3uiv=GLee_Lazy_glVertexAttribI3uiv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI4uiv +#define GLEE_C_DEFINED_glVertexAttribI4uiv + void __stdcall GLee_Lazy_glVertexAttribI4uiv(GLuint index, const GLuint * v) {if (GLeeInit()) glVertexAttribI4uiv(index, v);} + GLEEPFNGLVERTEXATTRIBI4UIVPROC GLeeFuncPtr_glVertexAttribI4uiv=GLee_Lazy_glVertexAttribI4uiv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI4bv +#define GLEE_C_DEFINED_glVertexAttribI4bv + void __stdcall GLee_Lazy_glVertexAttribI4bv(GLuint index, const GLbyte * v) {if (GLeeInit()) glVertexAttribI4bv(index, v);} + GLEEPFNGLVERTEXATTRIBI4BVPROC GLeeFuncPtr_glVertexAttribI4bv=GLee_Lazy_glVertexAttribI4bv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI4sv +#define GLEE_C_DEFINED_glVertexAttribI4sv + void __stdcall GLee_Lazy_glVertexAttribI4sv(GLuint index, const GLshort * v) {if (GLeeInit()) glVertexAttribI4sv(index, v);} + GLEEPFNGLVERTEXATTRIBI4SVPROC GLeeFuncPtr_glVertexAttribI4sv=GLee_Lazy_glVertexAttribI4sv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI4ubv +#define GLEE_C_DEFINED_glVertexAttribI4ubv + void __stdcall GLee_Lazy_glVertexAttribI4ubv(GLuint index, const GLubyte * v) {if (GLeeInit()) glVertexAttribI4ubv(index, v);} + GLEEPFNGLVERTEXATTRIBI4UBVPROC GLeeFuncPtr_glVertexAttribI4ubv=GLee_Lazy_glVertexAttribI4ubv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI4usv +#define GLEE_C_DEFINED_glVertexAttribI4usv + void __stdcall GLee_Lazy_glVertexAttribI4usv(GLuint index, const GLushort * v) {if (GLeeInit()) glVertexAttribI4usv(index, v);} + GLEEPFNGLVERTEXATTRIBI4USVPROC GLeeFuncPtr_glVertexAttribI4usv=GLee_Lazy_glVertexAttribI4usv; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribIPointer +#define GLEE_C_DEFINED_glVertexAttribIPointer + void __stdcall GLee_Lazy_glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {if (GLeeInit()) glVertexAttribIPointer(index, size, type, stride, pointer);} + GLEEPFNGLVERTEXATTRIBIPOINTERPROC GLeeFuncPtr_glVertexAttribIPointer=GLee_Lazy_glVertexAttribIPointer; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribIiv +#define GLEE_C_DEFINED_glGetVertexAttribIiv + void __stdcall GLee_Lazy_glGetVertexAttribIiv(GLuint index, GLenum pname, GLint * params) {if (GLeeInit()) glGetVertexAttribIiv(index, pname, params);} + GLEEPFNGLGETVERTEXATTRIBIIVPROC GLeeFuncPtr_glGetVertexAttribIiv=GLee_Lazy_glGetVertexAttribIiv; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribIuiv +#define GLEE_C_DEFINED_glGetVertexAttribIuiv + void __stdcall GLee_Lazy_glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint * params) {if (GLeeInit()) glGetVertexAttribIuiv(index, pname, params);} + GLEEPFNGLGETVERTEXATTRIBIUIVPROC GLeeFuncPtr_glGetVertexAttribIuiv=GLee_Lazy_glGetVertexAttribIuiv; +#endif +#ifndef GLEE_C_DEFINED_glGetUniformuiv +#define GLEE_C_DEFINED_glGetUniformuiv + void __stdcall GLee_Lazy_glGetUniformuiv(GLuint program, GLint location, GLuint * params) {if (GLeeInit()) glGetUniformuiv(program, location, params);} + GLEEPFNGLGETUNIFORMUIVPROC GLeeFuncPtr_glGetUniformuiv=GLee_Lazy_glGetUniformuiv; +#endif +#ifndef GLEE_C_DEFINED_glBindFragDataLocation +#define GLEE_C_DEFINED_glBindFragDataLocation + void __stdcall GLee_Lazy_glBindFragDataLocation(GLuint program, GLuint color, const GLchar * name) {if (GLeeInit()) glBindFragDataLocation(program, color, name);} + GLEEPFNGLBINDFRAGDATALOCATIONPROC GLeeFuncPtr_glBindFragDataLocation=GLee_Lazy_glBindFragDataLocation; +#endif +#ifndef GLEE_C_DEFINED_glGetFragDataLocation +#define GLEE_C_DEFINED_glGetFragDataLocation + GLint __stdcall GLee_Lazy_glGetFragDataLocation(GLuint program, const GLchar * name) {if (GLeeInit()) return glGetFragDataLocation(program, name); return (GLint)0;} + GLEEPFNGLGETFRAGDATALOCATIONPROC GLeeFuncPtr_glGetFragDataLocation=GLee_Lazy_glGetFragDataLocation; +#endif +#ifndef GLEE_C_DEFINED_glUniform1ui +#define GLEE_C_DEFINED_glUniform1ui + void __stdcall GLee_Lazy_glUniform1ui(GLint location, GLuint v0) {if (GLeeInit()) glUniform1ui(location, v0);} + GLEEPFNGLUNIFORM1UIPROC GLeeFuncPtr_glUniform1ui=GLee_Lazy_glUniform1ui; +#endif +#ifndef GLEE_C_DEFINED_glUniform2ui +#define GLEE_C_DEFINED_glUniform2ui + void __stdcall GLee_Lazy_glUniform2ui(GLint location, GLuint v0, GLuint v1) {if (GLeeInit()) glUniform2ui(location, v0, v1);} + GLEEPFNGLUNIFORM2UIPROC GLeeFuncPtr_glUniform2ui=GLee_Lazy_glUniform2ui; +#endif +#ifndef GLEE_C_DEFINED_glUniform3ui +#define GLEE_C_DEFINED_glUniform3ui + void __stdcall GLee_Lazy_glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) {if (GLeeInit()) glUniform3ui(location, v0, v1, v2);} + GLEEPFNGLUNIFORM3UIPROC GLeeFuncPtr_glUniform3ui=GLee_Lazy_glUniform3ui; +#endif +#ifndef GLEE_C_DEFINED_glUniform4ui +#define GLEE_C_DEFINED_glUniform4ui + void __stdcall GLee_Lazy_glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {if (GLeeInit()) glUniform4ui(location, v0, v1, v2, v3);} + GLEEPFNGLUNIFORM4UIPROC GLeeFuncPtr_glUniform4ui=GLee_Lazy_glUniform4ui; +#endif +#ifndef GLEE_C_DEFINED_glUniform1uiv +#define GLEE_C_DEFINED_glUniform1uiv + void __stdcall GLee_Lazy_glUniform1uiv(GLint location, GLsizei count, const GLuint * value) {if (GLeeInit()) glUniform1uiv(location, count, value);} + GLEEPFNGLUNIFORM1UIVPROC GLeeFuncPtr_glUniform1uiv=GLee_Lazy_glUniform1uiv; +#endif +#ifndef GLEE_C_DEFINED_glUniform2uiv +#define GLEE_C_DEFINED_glUniform2uiv + void __stdcall GLee_Lazy_glUniform2uiv(GLint location, GLsizei count, const GLuint * value) {if (GLeeInit()) glUniform2uiv(location, count, value);} + GLEEPFNGLUNIFORM2UIVPROC GLeeFuncPtr_glUniform2uiv=GLee_Lazy_glUniform2uiv; +#endif +#ifndef GLEE_C_DEFINED_glUniform3uiv +#define GLEE_C_DEFINED_glUniform3uiv + void __stdcall GLee_Lazy_glUniform3uiv(GLint location, GLsizei count, const GLuint * value) {if (GLeeInit()) glUniform3uiv(location, count, value);} + GLEEPFNGLUNIFORM3UIVPROC GLeeFuncPtr_glUniform3uiv=GLee_Lazy_glUniform3uiv; +#endif +#ifndef GLEE_C_DEFINED_glUniform4uiv +#define GLEE_C_DEFINED_glUniform4uiv + void __stdcall GLee_Lazy_glUniform4uiv(GLint location, GLsizei count, const GLuint * value) {if (GLeeInit()) glUniform4uiv(location, count, value);} + GLEEPFNGLUNIFORM4UIVPROC GLeeFuncPtr_glUniform4uiv=GLee_Lazy_glUniform4uiv; +#endif +#ifndef GLEE_C_DEFINED_glTexParameterIiv +#define GLEE_C_DEFINED_glTexParameterIiv + void __stdcall GLee_Lazy_glTexParameterIiv(GLenum target, GLenum pname, const GLint * params) {if (GLeeInit()) glTexParameterIiv(target, pname, params);} + GLEEPFNGLTEXPARAMETERIIVPROC GLeeFuncPtr_glTexParameterIiv=GLee_Lazy_glTexParameterIiv; +#endif +#ifndef GLEE_C_DEFINED_glTexParameterIuiv +#define GLEE_C_DEFINED_glTexParameterIuiv + void __stdcall GLee_Lazy_glTexParameterIuiv(GLenum target, GLenum pname, const GLuint * params) {if (GLeeInit()) glTexParameterIuiv(target, pname, params);} + GLEEPFNGLTEXPARAMETERIUIVPROC GLeeFuncPtr_glTexParameterIuiv=GLee_Lazy_glTexParameterIuiv; +#endif +#ifndef GLEE_C_DEFINED_glGetTexParameterIiv +#define GLEE_C_DEFINED_glGetTexParameterIiv + void __stdcall GLee_Lazy_glGetTexParameterIiv(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetTexParameterIiv(target, pname, params);} + GLEEPFNGLGETTEXPARAMETERIIVPROC GLeeFuncPtr_glGetTexParameterIiv=GLee_Lazy_glGetTexParameterIiv; +#endif +#ifndef GLEE_C_DEFINED_glGetTexParameterIuiv +#define GLEE_C_DEFINED_glGetTexParameterIuiv + void __stdcall GLee_Lazy_glGetTexParameterIuiv(GLenum target, GLenum pname, GLuint * params) {if (GLeeInit()) glGetTexParameterIuiv(target, pname, params);} + GLEEPFNGLGETTEXPARAMETERIUIVPROC GLeeFuncPtr_glGetTexParameterIuiv=GLee_Lazy_glGetTexParameterIuiv; +#endif +#ifndef GLEE_C_DEFINED_glClearBufferiv +#define GLEE_C_DEFINED_glClearBufferiv + void __stdcall GLee_Lazy_glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint * value) {if (GLeeInit()) glClearBufferiv(buffer, drawbuffer, value);} + GLEEPFNGLCLEARBUFFERIVPROC GLeeFuncPtr_glClearBufferiv=GLee_Lazy_glClearBufferiv; +#endif +#ifndef GLEE_C_DEFINED_glClearBufferuiv +#define GLEE_C_DEFINED_glClearBufferuiv + void __stdcall GLee_Lazy_glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint * value) {if (GLeeInit()) glClearBufferuiv(buffer, drawbuffer, value);} + GLEEPFNGLCLEARBUFFERUIVPROC GLeeFuncPtr_glClearBufferuiv=GLee_Lazy_glClearBufferuiv; +#endif +#ifndef GLEE_C_DEFINED_glClearBufferfv +#define GLEE_C_DEFINED_glClearBufferfv + void __stdcall GLee_Lazy_glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat * value) {if (GLeeInit()) glClearBufferfv(buffer, drawbuffer, value);} + GLEEPFNGLCLEARBUFFERFVPROC GLeeFuncPtr_glClearBufferfv=GLee_Lazy_glClearBufferfv; +#endif +#ifndef GLEE_C_DEFINED_glClearBufferfi +#define GLEE_C_DEFINED_glClearBufferfi + void __stdcall GLee_Lazy_glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) {if (GLeeInit()) glClearBufferfi(buffer, drawbuffer, depth, stencil);} + GLEEPFNGLCLEARBUFFERFIPROC GLeeFuncPtr_glClearBufferfi=GLee_Lazy_glClearBufferfi; +#endif +#ifndef GLEE_C_DEFINED_glGetStringi +#define GLEE_C_DEFINED_glGetStringi + const GLubyte * __stdcall GLee_Lazy_glGetStringi(GLenum name, GLuint index) {if (GLeeInit()) return glGetStringi(name, index); return (const GLubyte *)0;} + GLEEPFNGLGETSTRINGIPROC GLeeFuncPtr_glGetStringi=GLee_Lazy_glGetStringi; +#endif +#endif + +/* GL_ARB_multitexture */ + +#ifdef __GLEE_GL_ARB_multitexture +#ifndef GLEE_C_DEFINED_glActiveTextureARB +#define GLEE_C_DEFINED_glActiveTextureARB + void __stdcall GLee_Lazy_glActiveTextureARB(GLenum texture) {if (GLeeInit()) glActiveTextureARB(texture);} + GLEEPFNGLACTIVETEXTUREARBPROC GLeeFuncPtr_glActiveTextureARB=GLee_Lazy_glActiveTextureARB; +#endif +#ifndef GLEE_C_DEFINED_glClientActiveTextureARB +#define GLEE_C_DEFINED_glClientActiveTextureARB + void __stdcall GLee_Lazy_glClientActiveTextureARB(GLenum texture) {if (GLeeInit()) glClientActiveTextureARB(texture);} + GLEEPFNGLCLIENTACTIVETEXTUREARBPROC GLeeFuncPtr_glClientActiveTextureARB=GLee_Lazy_glClientActiveTextureARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1dARB +#define GLEE_C_DEFINED_glMultiTexCoord1dARB + void __stdcall GLee_Lazy_glMultiTexCoord1dARB(GLenum target, GLdouble s) {if (GLeeInit()) glMultiTexCoord1dARB(target, s);} + GLEEPFNGLMULTITEXCOORD1DARBPROC GLeeFuncPtr_glMultiTexCoord1dARB=GLee_Lazy_glMultiTexCoord1dARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1dvARB +#define GLEE_C_DEFINED_glMultiTexCoord1dvARB + void __stdcall GLee_Lazy_glMultiTexCoord1dvARB(GLenum target, const GLdouble * v) {if (GLeeInit()) glMultiTexCoord1dvARB(target, v);} + GLEEPFNGLMULTITEXCOORD1DVARBPROC GLeeFuncPtr_glMultiTexCoord1dvARB=GLee_Lazy_glMultiTexCoord1dvARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1fARB +#define GLEE_C_DEFINED_glMultiTexCoord1fARB + void __stdcall GLee_Lazy_glMultiTexCoord1fARB(GLenum target, GLfloat s) {if (GLeeInit()) glMultiTexCoord1fARB(target, s);} + GLEEPFNGLMULTITEXCOORD1FARBPROC GLeeFuncPtr_glMultiTexCoord1fARB=GLee_Lazy_glMultiTexCoord1fARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1fvARB +#define GLEE_C_DEFINED_glMultiTexCoord1fvARB + void __stdcall GLee_Lazy_glMultiTexCoord1fvARB(GLenum target, const GLfloat * v) {if (GLeeInit()) glMultiTexCoord1fvARB(target, v);} + GLEEPFNGLMULTITEXCOORD1FVARBPROC GLeeFuncPtr_glMultiTexCoord1fvARB=GLee_Lazy_glMultiTexCoord1fvARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1iARB +#define GLEE_C_DEFINED_glMultiTexCoord1iARB + void __stdcall GLee_Lazy_glMultiTexCoord1iARB(GLenum target, GLint s) {if (GLeeInit()) glMultiTexCoord1iARB(target, s);} + GLEEPFNGLMULTITEXCOORD1IARBPROC GLeeFuncPtr_glMultiTexCoord1iARB=GLee_Lazy_glMultiTexCoord1iARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1ivARB +#define GLEE_C_DEFINED_glMultiTexCoord1ivARB + void __stdcall GLee_Lazy_glMultiTexCoord1ivARB(GLenum target, const GLint * v) {if (GLeeInit()) glMultiTexCoord1ivARB(target, v);} + GLEEPFNGLMULTITEXCOORD1IVARBPROC GLeeFuncPtr_glMultiTexCoord1ivARB=GLee_Lazy_glMultiTexCoord1ivARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1sARB +#define GLEE_C_DEFINED_glMultiTexCoord1sARB + void __stdcall GLee_Lazy_glMultiTexCoord1sARB(GLenum target, GLshort s) {if (GLeeInit()) glMultiTexCoord1sARB(target, s);} + GLEEPFNGLMULTITEXCOORD1SARBPROC GLeeFuncPtr_glMultiTexCoord1sARB=GLee_Lazy_glMultiTexCoord1sARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1svARB +#define GLEE_C_DEFINED_glMultiTexCoord1svARB + void __stdcall GLee_Lazy_glMultiTexCoord1svARB(GLenum target, const GLshort * v) {if (GLeeInit()) glMultiTexCoord1svARB(target, v);} + GLEEPFNGLMULTITEXCOORD1SVARBPROC GLeeFuncPtr_glMultiTexCoord1svARB=GLee_Lazy_glMultiTexCoord1svARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2dARB +#define GLEE_C_DEFINED_glMultiTexCoord2dARB + void __stdcall GLee_Lazy_glMultiTexCoord2dARB(GLenum target, GLdouble s, GLdouble t) {if (GLeeInit()) glMultiTexCoord2dARB(target, s, t);} + GLEEPFNGLMULTITEXCOORD2DARBPROC GLeeFuncPtr_glMultiTexCoord2dARB=GLee_Lazy_glMultiTexCoord2dARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2dvARB +#define GLEE_C_DEFINED_glMultiTexCoord2dvARB + void __stdcall GLee_Lazy_glMultiTexCoord2dvARB(GLenum target, const GLdouble * v) {if (GLeeInit()) glMultiTexCoord2dvARB(target, v);} + GLEEPFNGLMULTITEXCOORD2DVARBPROC GLeeFuncPtr_glMultiTexCoord2dvARB=GLee_Lazy_glMultiTexCoord2dvARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2fARB +#define GLEE_C_DEFINED_glMultiTexCoord2fARB + void __stdcall GLee_Lazy_glMultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t) {if (GLeeInit()) glMultiTexCoord2fARB(target, s, t);} + GLEEPFNGLMULTITEXCOORD2FARBPROC GLeeFuncPtr_glMultiTexCoord2fARB=GLee_Lazy_glMultiTexCoord2fARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2fvARB +#define GLEE_C_DEFINED_glMultiTexCoord2fvARB + void __stdcall GLee_Lazy_glMultiTexCoord2fvARB(GLenum target, const GLfloat * v) {if (GLeeInit()) glMultiTexCoord2fvARB(target, v);} + GLEEPFNGLMULTITEXCOORD2FVARBPROC GLeeFuncPtr_glMultiTexCoord2fvARB=GLee_Lazy_glMultiTexCoord2fvARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2iARB +#define GLEE_C_DEFINED_glMultiTexCoord2iARB + void __stdcall GLee_Lazy_glMultiTexCoord2iARB(GLenum target, GLint s, GLint t) {if (GLeeInit()) glMultiTexCoord2iARB(target, s, t);} + GLEEPFNGLMULTITEXCOORD2IARBPROC GLeeFuncPtr_glMultiTexCoord2iARB=GLee_Lazy_glMultiTexCoord2iARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2ivARB +#define GLEE_C_DEFINED_glMultiTexCoord2ivARB + void __stdcall GLee_Lazy_glMultiTexCoord2ivARB(GLenum target, const GLint * v) {if (GLeeInit()) glMultiTexCoord2ivARB(target, v);} + GLEEPFNGLMULTITEXCOORD2IVARBPROC GLeeFuncPtr_glMultiTexCoord2ivARB=GLee_Lazy_glMultiTexCoord2ivARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2sARB +#define GLEE_C_DEFINED_glMultiTexCoord2sARB + void __stdcall GLee_Lazy_glMultiTexCoord2sARB(GLenum target, GLshort s, GLshort t) {if (GLeeInit()) glMultiTexCoord2sARB(target, s, t);} + GLEEPFNGLMULTITEXCOORD2SARBPROC GLeeFuncPtr_glMultiTexCoord2sARB=GLee_Lazy_glMultiTexCoord2sARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2svARB +#define GLEE_C_DEFINED_glMultiTexCoord2svARB + void __stdcall GLee_Lazy_glMultiTexCoord2svARB(GLenum target, const GLshort * v) {if (GLeeInit()) glMultiTexCoord2svARB(target, v);} + GLEEPFNGLMULTITEXCOORD2SVARBPROC GLeeFuncPtr_glMultiTexCoord2svARB=GLee_Lazy_glMultiTexCoord2svARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3dARB +#define GLEE_C_DEFINED_glMultiTexCoord3dARB + void __stdcall GLee_Lazy_glMultiTexCoord3dARB(GLenum target, GLdouble s, GLdouble t, GLdouble r) {if (GLeeInit()) glMultiTexCoord3dARB(target, s, t, r);} + GLEEPFNGLMULTITEXCOORD3DARBPROC GLeeFuncPtr_glMultiTexCoord3dARB=GLee_Lazy_glMultiTexCoord3dARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3dvARB +#define GLEE_C_DEFINED_glMultiTexCoord3dvARB + void __stdcall GLee_Lazy_glMultiTexCoord3dvARB(GLenum target, const GLdouble * v) {if (GLeeInit()) glMultiTexCoord3dvARB(target, v);} + GLEEPFNGLMULTITEXCOORD3DVARBPROC GLeeFuncPtr_glMultiTexCoord3dvARB=GLee_Lazy_glMultiTexCoord3dvARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3fARB +#define GLEE_C_DEFINED_glMultiTexCoord3fARB + void __stdcall GLee_Lazy_glMultiTexCoord3fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r) {if (GLeeInit()) glMultiTexCoord3fARB(target, s, t, r);} + GLEEPFNGLMULTITEXCOORD3FARBPROC GLeeFuncPtr_glMultiTexCoord3fARB=GLee_Lazy_glMultiTexCoord3fARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3fvARB +#define GLEE_C_DEFINED_glMultiTexCoord3fvARB + void __stdcall GLee_Lazy_glMultiTexCoord3fvARB(GLenum target, const GLfloat * v) {if (GLeeInit()) glMultiTexCoord3fvARB(target, v);} + GLEEPFNGLMULTITEXCOORD3FVARBPROC GLeeFuncPtr_glMultiTexCoord3fvARB=GLee_Lazy_glMultiTexCoord3fvARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3iARB +#define GLEE_C_DEFINED_glMultiTexCoord3iARB + void __stdcall GLee_Lazy_glMultiTexCoord3iARB(GLenum target, GLint s, GLint t, GLint r) {if (GLeeInit()) glMultiTexCoord3iARB(target, s, t, r);} + GLEEPFNGLMULTITEXCOORD3IARBPROC GLeeFuncPtr_glMultiTexCoord3iARB=GLee_Lazy_glMultiTexCoord3iARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3ivARB +#define GLEE_C_DEFINED_glMultiTexCoord3ivARB + void __stdcall GLee_Lazy_glMultiTexCoord3ivARB(GLenum target, const GLint * v) {if (GLeeInit()) glMultiTexCoord3ivARB(target, v);} + GLEEPFNGLMULTITEXCOORD3IVARBPROC GLeeFuncPtr_glMultiTexCoord3ivARB=GLee_Lazy_glMultiTexCoord3ivARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3sARB +#define GLEE_C_DEFINED_glMultiTexCoord3sARB + void __stdcall GLee_Lazy_glMultiTexCoord3sARB(GLenum target, GLshort s, GLshort t, GLshort r) {if (GLeeInit()) glMultiTexCoord3sARB(target, s, t, r);} + GLEEPFNGLMULTITEXCOORD3SARBPROC GLeeFuncPtr_glMultiTexCoord3sARB=GLee_Lazy_glMultiTexCoord3sARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3svARB +#define GLEE_C_DEFINED_glMultiTexCoord3svARB + void __stdcall GLee_Lazy_glMultiTexCoord3svARB(GLenum target, const GLshort * v) {if (GLeeInit()) glMultiTexCoord3svARB(target, v);} + GLEEPFNGLMULTITEXCOORD3SVARBPROC GLeeFuncPtr_glMultiTexCoord3svARB=GLee_Lazy_glMultiTexCoord3svARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4dARB +#define GLEE_C_DEFINED_glMultiTexCoord4dARB + void __stdcall GLee_Lazy_glMultiTexCoord4dARB(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q) {if (GLeeInit()) glMultiTexCoord4dARB(target, s, t, r, q);} + GLEEPFNGLMULTITEXCOORD4DARBPROC GLeeFuncPtr_glMultiTexCoord4dARB=GLee_Lazy_glMultiTexCoord4dARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4dvARB +#define GLEE_C_DEFINED_glMultiTexCoord4dvARB + void __stdcall GLee_Lazy_glMultiTexCoord4dvARB(GLenum target, const GLdouble * v) {if (GLeeInit()) glMultiTexCoord4dvARB(target, v);} + GLEEPFNGLMULTITEXCOORD4DVARBPROC GLeeFuncPtr_glMultiTexCoord4dvARB=GLee_Lazy_glMultiTexCoord4dvARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4fARB +#define GLEE_C_DEFINED_glMultiTexCoord4fARB + void __stdcall GLee_Lazy_glMultiTexCoord4fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {if (GLeeInit()) glMultiTexCoord4fARB(target, s, t, r, q);} + GLEEPFNGLMULTITEXCOORD4FARBPROC GLeeFuncPtr_glMultiTexCoord4fARB=GLee_Lazy_glMultiTexCoord4fARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4fvARB +#define GLEE_C_DEFINED_glMultiTexCoord4fvARB + void __stdcall GLee_Lazy_glMultiTexCoord4fvARB(GLenum target, const GLfloat * v) {if (GLeeInit()) glMultiTexCoord4fvARB(target, v);} + GLEEPFNGLMULTITEXCOORD4FVARBPROC GLeeFuncPtr_glMultiTexCoord4fvARB=GLee_Lazy_glMultiTexCoord4fvARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4iARB +#define GLEE_C_DEFINED_glMultiTexCoord4iARB + void __stdcall GLee_Lazy_glMultiTexCoord4iARB(GLenum target, GLint s, GLint t, GLint r, GLint q) {if (GLeeInit()) glMultiTexCoord4iARB(target, s, t, r, q);} + GLEEPFNGLMULTITEXCOORD4IARBPROC GLeeFuncPtr_glMultiTexCoord4iARB=GLee_Lazy_glMultiTexCoord4iARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4ivARB +#define GLEE_C_DEFINED_glMultiTexCoord4ivARB + void __stdcall GLee_Lazy_glMultiTexCoord4ivARB(GLenum target, const GLint * v) {if (GLeeInit()) glMultiTexCoord4ivARB(target, v);} + GLEEPFNGLMULTITEXCOORD4IVARBPROC GLeeFuncPtr_glMultiTexCoord4ivARB=GLee_Lazy_glMultiTexCoord4ivARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4sARB +#define GLEE_C_DEFINED_glMultiTexCoord4sARB + void __stdcall GLee_Lazy_glMultiTexCoord4sARB(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q) {if (GLeeInit()) glMultiTexCoord4sARB(target, s, t, r, q);} + GLEEPFNGLMULTITEXCOORD4SARBPROC GLeeFuncPtr_glMultiTexCoord4sARB=GLee_Lazy_glMultiTexCoord4sARB; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4svARB +#define GLEE_C_DEFINED_glMultiTexCoord4svARB + void __stdcall GLee_Lazy_glMultiTexCoord4svARB(GLenum target, const GLshort * v) {if (GLeeInit()) glMultiTexCoord4svARB(target, v);} + GLEEPFNGLMULTITEXCOORD4SVARBPROC GLeeFuncPtr_glMultiTexCoord4svARB=GLee_Lazy_glMultiTexCoord4svARB; +#endif +#endif + +/* GL_ARB_transpose_matrix */ + +#ifdef __GLEE_GL_ARB_transpose_matrix +#ifndef GLEE_C_DEFINED_glLoadTransposeMatrixfARB +#define GLEE_C_DEFINED_glLoadTransposeMatrixfARB + void __stdcall GLee_Lazy_glLoadTransposeMatrixfARB(const GLfloat * m) {if (GLeeInit()) glLoadTransposeMatrixfARB(m);} + GLEEPFNGLLOADTRANSPOSEMATRIXFARBPROC GLeeFuncPtr_glLoadTransposeMatrixfARB=GLee_Lazy_glLoadTransposeMatrixfARB; +#endif +#ifndef GLEE_C_DEFINED_glLoadTransposeMatrixdARB +#define GLEE_C_DEFINED_glLoadTransposeMatrixdARB + void __stdcall GLee_Lazy_glLoadTransposeMatrixdARB(const GLdouble * m) {if (GLeeInit()) glLoadTransposeMatrixdARB(m);} + GLEEPFNGLLOADTRANSPOSEMATRIXDARBPROC GLeeFuncPtr_glLoadTransposeMatrixdARB=GLee_Lazy_glLoadTransposeMatrixdARB; +#endif +#ifndef GLEE_C_DEFINED_glMultTransposeMatrixfARB +#define GLEE_C_DEFINED_glMultTransposeMatrixfARB + void __stdcall GLee_Lazy_glMultTransposeMatrixfARB(const GLfloat * m) {if (GLeeInit()) glMultTransposeMatrixfARB(m);} + GLEEPFNGLMULTTRANSPOSEMATRIXFARBPROC GLeeFuncPtr_glMultTransposeMatrixfARB=GLee_Lazy_glMultTransposeMatrixfARB; +#endif +#ifndef GLEE_C_DEFINED_glMultTransposeMatrixdARB +#define GLEE_C_DEFINED_glMultTransposeMatrixdARB + void __stdcall GLee_Lazy_glMultTransposeMatrixdARB(const GLdouble * m) {if (GLeeInit()) glMultTransposeMatrixdARB(m);} + GLEEPFNGLMULTTRANSPOSEMATRIXDARBPROC GLeeFuncPtr_glMultTransposeMatrixdARB=GLee_Lazy_glMultTransposeMatrixdARB; +#endif +#endif + +/* GL_ARB_multisample */ + +#ifdef __GLEE_GL_ARB_multisample +#ifndef GLEE_C_DEFINED_glSampleCoverageARB +#define GLEE_C_DEFINED_glSampleCoverageARB + void __stdcall GLee_Lazy_glSampleCoverageARB(GLclampf value, GLboolean invert) {if (GLeeInit()) glSampleCoverageARB(value, invert);} + GLEEPFNGLSAMPLECOVERAGEARBPROC GLeeFuncPtr_glSampleCoverageARB=GLee_Lazy_glSampleCoverageARB; +#endif +#endif + +/* GL_ARB_texture_env_add */ + +#ifdef __GLEE_GL_ARB_texture_env_add +#endif + +/* GL_ARB_texture_cube_map */ + +#ifdef __GLEE_GL_ARB_texture_cube_map +#endif + +/* GL_ARB_texture_compression */ + +#ifdef __GLEE_GL_ARB_texture_compression +#ifndef GLEE_C_DEFINED_glCompressedTexImage3DARB +#define GLEE_C_DEFINED_glCompressedTexImage3DARB + void __stdcall GLee_Lazy_glCompressedTexImage3DARB(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid * data) {if (GLeeInit()) glCompressedTexImage3DARB(target, level, internalformat, width, height, depth, border, imageSize, data);} + GLEEPFNGLCOMPRESSEDTEXIMAGE3DARBPROC GLeeFuncPtr_glCompressedTexImage3DARB=GLee_Lazy_glCompressedTexImage3DARB; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTexImage2DARB +#define GLEE_C_DEFINED_glCompressedTexImage2DARB + void __stdcall GLee_Lazy_glCompressedTexImage2DARB(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * data) {if (GLeeInit()) glCompressedTexImage2DARB(target, level, internalformat, width, height, border, imageSize, data);} + GLEEPFNGLCOMPRESSEDTEXIMAGE2DARBPROC GLeeFuncPtr_glCompressedTexImage2DARB=GLee_Lazy_glCompressedTexImage2DARB; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTexImage1DARB +#define GLEE_C_DEFINED_glCompressedTexImage1DARB + void __stdcall GLee_Lazy_glCompressedTexImage1DARB(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid * data) {if (GLeeInit()) glCompressedTexImage1DARB(target, level, internalformat, width, border, imageSize, data);} + GLEEPFNGLCOMPRESSEDTEXIMAGE1DARBPROC GLeeFuncPtr_glCompressedTexImage1DARB=GLee_Lazy_glCompressedTexImage1DARB; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTexSubImage3DARB +#define GLEE_C_DEFINED_glCompressedTexSubImage3DARB + void __stdcall GLee_Lazy_glCompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid * data) {if (GLeeInit()) glCompressedTexSubImage3DARB(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);} + GLEEPFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC GLeeFuncPtr_glCompressedTexSubImage3DARB=GLee_Lazy_glCompressedTexSubImage3DARB; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTexSubImage2DARB +#define GLEE_C_DEFINED_glCompressedTexSubImage2DARB + void __stdcall GLee_Lazy_glCompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid * data) {if (GLeeInit()) glCompressedTexSubImage2DARB(target, level, xoffset, yoffset, width, height, format, imageSize, data);} + GLEEPFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC GLeeFuncPtr_glCompressedTexSubImage2DARB=GLee_Lazy_glCompressedTexSubImage2DARB; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTexSubImage1DARB +#define GLEE_C_DEFINED_glCompressedTexSubImage1DARB + void __stdcall GLee_Lazy_glCompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid * data) {if (GLeeInit()) glCompressedTexSubImage1DARB(target, level, xoffset, width, format, imageSize, data);} + GLEEPFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC GLeeFuncPtr_glCompressedTexSubImage1DARB=GLee_Lazy_glCompressedTexSubImage1DARB; +#endif +#ifndef GLEE_C_DEFINED_glGetCompressedTexImageARB +#define GLEE_C_DEFINED_glGetCompressedTexImageARB + void __stdcall GLee_Lazy_glGetCompressedTexImageARB(GLenum target, GLint level, GLvoid * img) {if (GLeeInit()) glGetCompressedTexImageARB(target, level, img);} + GLEEPFNGLGETCOMPRESSEDTEXIMAGEARBPROC GLeeFuncPtr_glGetCompressedTexImageARB=GLee_Lazy_glGetCompressedTexImageARB; +#endif +#endif + +/* GL_ARB_texture_border_clamp */ + +#ifdef __GLEE_GL_ARB_texture_border_clamp +#endif + +/* GL_ARB_point_parameters */ + +#ifdef __GLEE_GL_ARB_point_parameters +#ifndef GLEE_C_DEFINED_glPointParameterfARB +#define GLEE_C_DEFINED_glPointParameterfARB + void __stdcall GLee_Lazy_glPointParameterfARB(GLenum pname, GLfloat param) {if (GLeeInit()) glPointParameterfARB(pname, param);} + GLEEPFNGLPOINTPARAMETERFARBPROC GLeeFuncPtr_glPointParameterfARB=GLee_Lazy_glPointParameterfARB; +#endif +#ifndef GLEE_C_DEFINED_glPointParameterfvARB +#define GLEE_C_DEFINED_glPointParameterfvARB + void __stdcall GLee_Lazy_glPointParameterfvARB(GLenum pname, const GLfloat * params) {if (GLeeInit()) glPointParameterfvARB(pname, params);} + GLEEPFNGLPOINTPARAMETERFVARBPROC GLeeFuncPtr_glPointParameterfvARB=GLee_Lazy_glPointParameterfvARB; +#endif +#endif + +/* GL_ARB_vertex_blend */ + +#ifdef __GLEE_GL_ARB_vertex_blend +#ifndef GLEE_C_DEFINED_glWeightbvARB +#define GLEE_C_DEFINED_glWeightbvARB + void __stdcall GLee_Lazy_glWeightbvARB(GLint size, const GLbyte * weights) {if (GLeeInit()) glWeightbvARB(size, weights);} + GLEEPFNGLWEIGHTBVARBPROC GLeeFuncPtr_glWeightbvARB=GLee_Lazy_glWeightbvARB; +#endif +#ifndef GLEE_C_DEFINED_glWeightsvARB +#define GLEE_C_DEFINED_glWeightsvARB + void __stdcall GLee_Lazy_glWeightsvARB(GLint size, const GLshort * weights) {if (GLeeInit()) glWeightsvARB(size, weights);} + GLEEPFNGLWEIGHTSVARBPROC GLeeFuncPtr_glWeightsvARB=GLee_Lazy_glWeightsvARB; +#endif +#ifndef GLEE_C_DEFINED_glWeightivARB +#define GLEE_C_DEFINED_glWeightivARB + void __stdcall GLee_Lazy_glWeightivARB(GLint size, const GLint * weights) {if (GLeeInit()) glWeightivARB(size, weights);} + GLEEPFNGLWEIGHTIVARBPROC GLeeFuncPtr_glWeightivARB=GLee_Lazy_glWeightivARB; +#endif +#ifndef GLEE_C_DEFINED_glWeightfvARB +#define GLEE_C_DEFINED_glWeightfvARB + void __stdcall GLee_Lazy_glWeightfvARB(GLint size, const GLfloat * weights) {if (GLeeInit()) glWeightfvARB(size, weights);} + GLEEPFNGLWEIGHTFVARBPROC GLeeFuncPtr_glWeightfvARB=GLee_Lazy_glWeightfvARB; +#endif +#ifndef GLEE_C_DEFINED_glWeightdvARB +#define GLEE_C_DEFINED_glWeightdvARB + void __stdcall GLee_Lazy_glWeightdvARB(GLint size, const GLdouble * weights) {if (GLeeInit()) glWeightdvARB(size, weights);} + GLEEPFNGLWEIGHTDVARBPROC GLeeFuncPtr_glWeightdvARB=GLee_Lazy_glWeightdvARB; +#endif +#ifndef GLEE_C_DEFINED_glWeightubvARB +#define GLEE_C_DEFINED_glWeightubvARB + void __stdcall GLee_Lazy_glWeightubvARB(GLint size, const GLubyte * weights) {if (GLeeInit()) glWeightubvARB(size, weights);} + GLEEPFNGLWEIGHTUBVARBPROC GLeeFuncPtr_glWeightubvARB=GLee_Lazy_glWeightubvARB; +#endif +#ifndef GLEE_C_DEFINED_glWeightusvARB +#define GLEE_C_DEFINED_glWeightusvARB + void __stdcall GLee_Lazy_glWeightusvARB(GLint size, const GLushort * weights) {if (GLeeInit()) glWeightusvARB(size, weights);} + GLEEPFNGLWEIGHTUSVARBPROC GLeeFuncPtr_glWeightusvARB=GLee_Lazy_glWeightusvARB; +#endif +#ifndef GLEE_C_DEFINED_glWeightuivARB +#define GLEE_C_DEFINED_glWeightuivARB + void __stdcall GLee_Lazy_glWeightuivARB(GLint size, const GLuint * weights) {if (GLeeInit()) glWeightuivARB(size, weights);} + GLEEPFNGLWEIGHTUIVARBPROC GLeeFuncPtr_glWeightuivARB=GLee_Lazy_glWeightuivARB; +#endif +#ifndef GLEE_C_DEFINED_glWeightPointerARB +#define GLEE_C_DEFINED_glWeightPointerARB + void __stdcall GLee_Lazy_glWeightPointerARB(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {if (GLeeInit()) glWeightPointerARB(size, type, stride, pointer);} + GLEEPFNGLWEIGHTPOINTERARBPROC GLeeFuncPtr_glWeightPointerARB=GLee_Lazy_glWeightPointerARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexBlendARB +#define GLEE_C_DEFINED_glVertexBlendARB + void __stdcall GLee_Lazy_glVertexBlendARB(GLint count) {if (GLeeInit()) glVertexBlendARB(count);} + GLEEPFNGLVERTEXBLENDARBPROC GLeeFuncPtr_glVertexBlendARB=GLee_Lazy_glVertexBlendARB; +#endif +#endif + +/* GL_ARB_matrix_palette */ + +#ifdef __GLEE_GL_ARB_matrix_palette +#ifndef GLEE_C_DEFINED_glCurrentPaletteMatrixARB +#define GLEE_C_DEFINED_glCurrentPaletteMatrixARB + void __stdcall GLee_Lazy_glCurrentPaletteMatrixARB(GLint index) {if (GLeeInit()) glCurrentPaletteMatrixARB(index);} + GLEEPFNGLCURRENTPALETTEMATRIXARBPROC GLeeFuncPtr_glCurrentPaletteMatrixARB=GLee_Lazy_glCurrentPaletteMatrixARB; +#endif +#ifndef GLEE_C_DEFINED_glMatrixIndexubvARB +#define GLEE_C_DEFINED_glMatrixIndexubvARB + void __stdcall GLee_Lazy_glMatrixIndexubvARB(GLint size, const GLubyte * indices) {if (GLeeInit()) glMatrixIndexubvARB(size, indices);} + GLEEPFNGLMATRIXINDEXUBVARBPROC GLeeFuncPtr_glMatrixIndexubvARB=GLee_Lazy_glMatrixIndexubvARB; +#endif +#ifndef GLEE_C_DEFINED_glMatrixIndexusvARB +#define GLEE_C_DEFINED_glMatrixIndexusvARB + void __stdcall GLee_Lazy_glMatrixIndexusvARB(GLint size, const GLushort * indices) {if (GLeeInit()) glMatrixIndexusvARB(size, indices);} + GLEEPFNGLMATRIXINDEXUSVARBPROC GLeeFuncPtr_glMatrixIndexusvARB=GLee_Lazy_glMatrixIndexusvARB; +#endif +#ifndef GLEE_C_DEFINED_glMatrixIndexuivARB +#define GLEE_C_DEFINED_glMatrixIndexuivARB + void __stdcall GLee_Lazy_glMatrixIndexuivARB(GLint size, const GLuint * indices) {if (GLeeInit()) glMatrixIndexuivARB(size, indices);} + GLEEPFNGLMATRIXINDEXUIVARBPROC GLeeFuncPtr_glMatrixIndexuivARB=GLee_Lazy_glMatrixIndexuivARB; +#endif +#ifndef GLEE_C_DEFINED_glMatrixIndexPointerARB +#define GLEE_C_DEFINED_glMatrixIndexPointerARB + void __stdcall GLee_Lazy_glMatrixIndexPointerARB(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {if (GLeeInit()) glMatrixIndexPointerARB(size, type, stride, pointer);} + GLEEPFNGLMATRIXINDEXPOINTERARBPROC GLeeFuncPtr_glMatrixIndexPointerARB=GLee_Lazy_glMatrixIndexPointerARB; +#endif +#endif + +/* GL_ARB_texture_env_combine */ + +#ifdef __GLEE_GL_ARB_texture_env_combine +#endif + +/* GL_ARB_texture_env_crossbar */ + +#ifdef __GLEE_GL_ARB_texture_env_crossbar +#endif + +/* GL_ARB_texture_env_dot3 */ + +#ifdef __GLEE_GL_ARB_texture_env_dot3 +#endif + +/* GL_ARB_texture_mirrored_repeat */ + +#ifdef __GLEE_GL_ARB_texture_mirrored_repeat +#endif + +/* GL_ARB_depth_texture */ + +#ifdef __GLEE_GL_ARB_depth_texture +#endif + +/* GL_ARB_shadow */ + +#ifdef __GLEE_GL_ARB_shadow +#endif + +/* GL_ARB_shadow_ambient */ + +#ifdef __GLEE_GL_ARB_shadow_ambient +#endif + +/* GL_ARB_window_pos */ + +#ifdef __GLEE_GL_ARB_window_pos +#ifndef GLEE_C_DEFINED_glWindowPos2dARB +#define GLEE_C_DEFINED_glWindowPos2dARB + void __stdcall GLee_Lazy_glWindowPos2dARB(GLdouble x, GLdouble y) {if (GLeeInit()) glWindowPos2dARB(x, y);} + GLEEPFNGLWINDOWPOS2DARBPROC GLeeFuncPtr_glWindowPos2dARB=GLee_Lazy_glWindowPos2dARB; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2dvARB +#define GLEE_C_DEFINED_glWindowPos2dvARB + void __stdcall GLee_Lazy_glWindowPos2dvARB(const GLdouble * v) {if (GLeeInit()) glWindowPos2dvARB(v);} + GLEEPFNGLWINDOWPOS2DVARBPROC GLeeFuncPtr_glWindowPos2dvARB=GLee_Lazy_glWindowPos2dvARB; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2fARB +#define GLEE_C_DEFINED_glWindowPos2fARB + void __stdcall GLee_Lazy_glWindowPos2fARB(GLfloat x, GLfloat y) {if (GLeeInit()) glWindowPos2fARB(x, y);} + GLEEPFNGLWINDOWPOS2FARBPROC GLeeFuncPtr_glWindowPos2fARB=GLee_Lazy_glWindowPos2fARB; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2fvARB +#define GLEE_C_DEFINED_glWindowPos2fvARB + void __stdcall GLee_Lazy_glWindowPos2fvARB(const GLfloat * v) {if (GLeeInit()) glWindowPos2fvARB(v);} + GLEEPFNGLWINDOWPOS2FVARBPROC GLeeFuncPtr_glWindowPos2fvARB=GLee_Lazy_glWindowPos2fvARB; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2iARB +#define GLEE_C_DEFINED_glWindowPos2iARB + void __stdcall GLee_Lazy_glWindowPos2iARB(GLint x, GLint y) {if (GLeeInit()) glWindowPos2iARB(x, y);} + GLEEPFNGLWINDOWPOS2IARBPROC GLeeFuncPtr_glWindowPos2iARB=GLee_Lazy_glWindowPos2iARB; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2ivARB +#define GLEE_C_DEFINED_glWindowPos2ivARB + void __stdcall GLee_Lazy_glWindowPos2ivARB(const GLint * v) {if (GLeeInit()) glWindowPos2ivARB(v);} + GLEEPFNGLWINDOWPOS2IVARBPROC GLeeFuncPtr_glWindowPos2ivARB=GLee_Lazy_glWindowPos2ivARB; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2sARB +#define GLEE_C_DEFINED_glWindowPos2sARB + void __stdcall GLee_Lazy_glWindowPos2sARB(GLshort x, GLshort y) {if (GLeeInit()) glWindowPos2sARB(x, y);} + GLEEPFNGLWINDOWPOS2SARBPROC GLeeFuncPtr_glWindowPos2sARB=GLee_Lazy_glWindowPos2sARB; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2svARB +#define GLEE_C_DEFINED_glWindowPos2svARB + void __stdcall GLee_Lazy_glWindowPos2svARB(const GLshort * v) {if (GLeeInit()) glWindowPos2svARB(v);} + GLEEPFNGLWINDOWPOS2SVARBPROC GLeeFuncPtr_glWindowPos2svARB=GLee_Lazy_glWindowPos2svARB; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3dARB +#define GLEE_C_DEFINED_glWindowPos3dARB + void __stdcall GLee_Lazy_glWindowPos3dARB(GLdouble x, GLdouble y, GLdouble z) {if (GLeeInit()) glWindowPos3dARB(x, y, z);} + GLEEPFNGLWINDOWPOS3DARBPROC GLeeFuncPtr_glWindowPos3dARB=GLee_Lazy_glWindowPos3dARB; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3dvARB +#define GLEE_C_DEFINED_glWindowPos3dvARB + void __stdcall GLee_Lazy_glWindowPos3dvARB(const GLdouble * v) {if (GLeeInit()) glWindowPos3dvARB(v);} + GLEEPFNGLWINDOWPOS3DVARBPROC GLeeFuncPtr_glWindowPos3dvARB=GLee_Lazy_glWindowPos3dvARB; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3fARB +#define GLEE_C_DEFINED_glWindowPos3fARB + void __stdcall GLee_Lazy_glWindowPos3fARB(GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glWindowPos3fARB(x, y, z);} + GLEEPFNGLWINDOWPOS3FARBPROC GLeeFuncPtr_glWindowPos3fARB=GLee_Lazy_glWindowPos3fARB; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3fvARB +#define GLEE_C_DEFINED_glWindowPos3fvARB + void __stdcall GLee_Lazy_glWindowPos3fvARB(const GLfloat * v) {if (GLeeInit()) glWindowPos3fvARB(v);} + GLEEPFNGLWINDOWPOS3FVARBPROC GLeeFuncPtr_glWindowPos3fvARB=GLee_Lazy_glWindowPos3fvARB; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3iARB +#define GLEE_C_DEFINED_glWindowPos3iARB + void __stdcall GLee_Lazy_glWindowPos3iARB(GLint x, GLint y, GLint z) {if (GLeeInit()) glWindowPos3iARB(x, y, z);} + GLEEPFNGLWINDOWPOS3IARBPROC GLeeFuncPtr_glWindowPos3iARB=GLee_Lazy_glWindowPos3iARB; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3ivARB +#define GLEE_C_DEFINED_glWindowPos3ivARB + void __stdcall GLee_Lazy_glWindowPos3ivARB(const GLint * v) {if (GLeeInit()) glWindowPos3ivARB(v);} + GLEEPFNGLWINDOWPOS3IVARBPROC GLeeFuncPtr_glWindowPos3ivARB=GLee_Lazy_glWindowPos3ivARB; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3sARB +#define GLEE_C_DEFINED_glWindowPos3sARB + void __stdcall GLee_Lazy_glWindowPos3sARB(GLshort x, GLshort y, GLshort z) {if (GLeeInit()) glWindowPos3sARB(x, y, z);} + GLEEPFNGLWINDOWPOS3SARBPROC GLeeFuncPtr_glWindowPos3sARB=GLee_Lazy_glWindowPos3sARB; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3svARB +#define GLEE_C_DEFINED_glWindowPos3svARB + void __stdcall GLee_Lazy_glWindowPos3svARB(const GLshort * v) {if (GLeeInit()) glWindowPos3svARB(v);} + GLEEPFNGLWINDOWPOS3SVARBPROC GLeeFuncPtr_glWindowPos3svARB=GLee_Lazy_glWindowPos3svARB; +#endif +#endif + +/* GL_ARB_vertex_program */ + +#ifdef __GLEE_GL_ARB_vertex_program +#ifndef GLEE_C_DEFINED_glVertexAttrib1dARB +#define GLEE_C_DEFINED_glVertexAttrib1dARB + void __stdcall GLee_Lazy_glVertexAttrib1dARB(GLuint index, GLdouble x) {if (GLeeInit()) glVertexAttrib1dARB(index, x);} + GLEEPFNGLVERTEXATTRIB1DARBPROC GLeeFuncPtr_glVertexAttrib1dARB=GLee_Lazy_glVertexAttrib1dARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1dvARB +#define GLEE_C_DEFINED_glVertexAttrib1dvARB + void __stdcall GLee_Lazy_glVertexAttrib1dvARB(GLuint index, const GLdouble * v) {if (GLeeInit()) glVertexAttrib1dvARB(index, v);} + GLEEPFNGLVERTEXATTRIB1DVARBPROC GLeeFuncPtr_glVertexAttrib1dvARB=GLee_Lazy_glVertexAttrib1dvARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1fARB +#define GLEE_C_DEFINED_glVertexAttrib1fARB + void __stdcall GLee_Lazy_glVertexAttrib1fARB(GLuint index, GLfloat x) {if (GLeeInit()) glVertexAttrib1fARB(index, x);} + GLEEPFNGLVERTEXATTRIB1FARBPROC GLeeFuncPtr_glVertexAttrib1fARB=GLee_Lazy_glVertexAttrib1fARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1fvARB +#define GLEE_C_DEFINED_glVertexAttrib1fvARB + void __stdcall GLee_Lazy_glVertexAttrib1fvARB(GLuint index, const GLfloat * v) {if (GLeeInit()) glVertexAttrib1fvARB(index, v);} + GLEEPFNGLVERTEXATTRIB1FVARBPROC GLeeFuncPtr_glVertexAttrib1fvARB=GLee_Lazy_glVertexAttrib1fvARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1sARB +#define GLEE_C_DEFINED_glVertexAttrib1sARB + void __stdcall GLee_Lazy_glVertexAttrib1sARB(GLuint index, GLshort x) {if (GLeeInit()) glVertexAttrib1sARB(index, x);} + GLEEPFNGLVERTEXATTRIB1SARBPROC GLeeFuncPtr_glVertexAttrib1sARB=GLee_Lazy_glVertexAttrib1sARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1svARB +#define GLEE_C_DEFINED_glVertexAttrib1svARB + void __stdcall GLee_Lazy_glVertexAttrib1svARB(GLuint index, const GLshort * v) {if (GLeeInit()) glVertexAttrib1svARB(index, v);} + GLEEPFNGLVERTEXATTRIB1SVARBPROC GLeeFuncPtr_glVertexAttrib1svARB=GLee_Lazy_glVertexAttrib1svARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2dARB +#define GLEE_C_DEFINED_glVertexAttrib2dARB + void __stdcall GLee_Lazy_glVertexAttrib2dARB(GLuint index, GLdouble x, GLdouble y) {if (GLeeInit()) glVertexAttrib2dARB(index, x, y);} + GLEEPFNGLVERTEXATTRIB2DARBPROC GLeeFuncPtr_glVertexAttrib2dARB=GLee_Lazy_glVertexAttrib2dARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2dvARB +#define GLEE_C_DEFINED_glVertexAttrib2dvARB + void __stdcall GLee_Lazy_glVertexAttrib2dvARB(GLuint index, const GLdouble * v) {if (GLeeInit()) glVertexAttrib2dvARB(index, v);} + GLEEPFNGLVERTEXATTRIB2DVARBPROC GLeeFuncPtr_glVertexAttrib2dvARB=GLee_Lazy_glVertexAttrib2dvARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2fARB +#define GLEE_C_DEFINED_glVertexAttrib2fARB + void __stdcall GLee_Lazy_glVertexAttrib2fARB(GLuint index, GLfloat x, GLfloat y) {if (GLeeInit()) glVertexAttrib2fARB(index, x, y);} + GLEEPFNGLVERTEXATTRIB2FARBPROC GLeeFuncPtr_glVertexAttrib2fARB=GLee_Lazy_glVertexAttrib2fARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2fvARB +#define GLEE_C_DEFINED_glVertexAttrib2fvARB + void __stdcall GLee_Lazy_glVertexAttrib2fvARB(GLuint index, const GLfloat * v) {if (GLeeInit()) glVertexAttrib2fvARB(index, v);} + GLEEPFNGLVERTEXATTRIB2FVARBPROC GLeeFuncPtr_glVertexAttrib2fvARB=GLee_Lazy_glVertexAttrib2fvARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2sARB +#define GLEE_C_DEFINED_glVertexAttrib2sARB + void __stdcall GLee_Lazy_glVertexAttrib2sARB(GLuint index, GLshort x, GLshort y) {if (GLeeInit()) glVertexAttrib2sARB(index, x, y);} + GLEEPFNGLVERTEXATTRIB2SARBPROC GLeeFuncPtr_glVertexAttrib2sARB=GLee_Lazy_glVertexAttrib2sARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2svARB +#define GLEE_C_DEFINED_glVertexAttrib2svARB + void __stdcall GLee_Lazy_glVertexAttrib2svARB(GLuint index, const GLshort * v) {if (GLeeInit()) glVertexAttrib2svARB(index, v);} + GLEEPFNGLVERTEXATTRIB2SVARBPROC GLeeFuncPtr_glVertexAttrib2svARB=GLee_Lazy_glVertexAttrib2svARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3dARB +#define GLEE_C_DEFINED_glVertexAttrib3dARB + void __stdcall GLee_Lazy_glVertexAttrib3dARB(GLuint index, GLdouble x, GLdouble y, GLdouble z) {if (GLeeInit()) glVertexAttrib3dARB(index, x, y, z);} + GLEEPFNGLVERTEXATTRIB3DARBPROC GLeeFuncPtr_glVertexAttrib3dARB=GLee_Lazy_glVertexAttrib3dARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3dvARB +#define GLEE_C_DEFINED_glVertexAttrib3dvARB + void __stdcall GLee_Lazy_glVertexAttrib3dvARB(GLuint index, const GLdouble * v) {if (GLeeInit()) glVertexAttrib3dvARB(index, v);} + GLEEPFNGLVERTEXATTRIB3DVARBPROC GLeeFuncPtr_glVertexAttrib3dvARB=GLee_Lazy_glVertexAttrib3dvARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3fARB +#define GLEE_C_DEFINED_glVertexAttrib3fARB + void __stdcall GLee_Lazy_glVertexAttrib3fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glVertexAttrib3fARB(index, x, y, z);} + GLEEPFNGLVERTEXATTRIB3FARBPROC GLeeFuncPtr_glVertexAttrib3fARB=GLee_Lazy_glVertexAttrib3fARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3fvARB +#define GLEE_C_DEFINED_glVertexAttrib3fvARB + void __stdcall GLee_Lazy_glVertexAttrib3fvARB(GLuint index, const GLfloat * v) {if (GLeeInit()) glVertexAttrib3fvARB(index, v);} + GLEEPFNGLVERTEXATTRIB3FVARBPROC GLeeFuncPtr_glVertexAttrib3fvARB=GLee_Lazy_glVertexAttrib3fvARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3sARB +#define GLEE_C_DEFINED_glVertexAttrib3sARB + void __stdcall GLee_Lazy_glVertexAttrib3sARB(GLuint index, GLshort x, GLshort y, GLshort z) {if (GLeeInit()) glVertexAttrib3sARB(index, x, y, z);} + GLEEPFNGLVERTEXATTRIB3SARBPROC GLeeFuncPtr_glVertexAttrib3sARB=GLee_Lazy_glVertexAttrib3sARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3svARB +#define GLEE_C_DEFINED_glVertexAttrib3svARB + void __stdcall GLee_Lazy_glVertexAttrib3svARB(GLuint index, const GLshort * v) {if (GLeeInit()) glVertexAttrib3svARB(index, v);} + GLEEPFNGLVERTEXATTRIB3SVARBPROC GLeeFuncPtr_glVertexAttrib3svARB=GLee_Lazy_glVertexAttrib3svARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4NbvARB +#define GLEE_C_DEFINED_glVertexAttrib4NbvARB + void __stdcall GLee_Lazy_glVertexAttrib4NbvARB(GLuint index, const GLbyte * v) {if (GLeeInit()) glVertexAttrib4NbvARB(index, v);} + GLEEPFNGLVERTEXATTRIB4NBVARBPROC GLeeFuncPtr_glVertexAttrib4NbvARB=GLee_Lazy_glVertexAttrib4NbvARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4NivARB +#define GLEE_C_DEFINED_glVertexAttrib4NivARB + void __stdcall GLee_Lazy_glVertexAttrib4NivARB(GLuint index, const GLint * v) {if (GLeeInit()) glVertexAttrib4NivARB(index, v);} + GLEEPFNGLVERTEXATTRIB4NIVARBPROC GLeeFuncPtr_glVertexAttrib4NivARB=GLee_Lazy_glVertexAttrib4NivARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4NsvARB +#define GLEE_C_DEFINED_glVertexAttrib4NsvARB + void __stdcall GLee_Lazy_glVertexAttrib4NsvARB(GLuint index, const GLshort * v) {if (GLeeInit()) glVertexAttrib4NsvARB(index, v);} + GLEEPFNGLVERTEXATTRIB4NSVARBPROC GLeeFuncPtr_glVertexAttrib4NsvARB=GLee_Lazy_glVertexAttrib4NsvARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4NubARB +#define GLEE_C_DEFINED_glVertexAttrib4NubARB + void __stdcall GLee_Lazy_glVertexAttrib4NubARB(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) {if (GLeeInit()) glVertexAttrib4NubARB(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIB4NUBARBPROC GLeeFuncPtr_glVertexAttrib4NubARB=GLee_Lazy_glVertexAttrib4NubARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4NubvARB +#define GLEE_C_DEFINED_glVertexAttrib4NubvARB + void __stdcall GLee_Lazy_glVertexAttrib4NubvARB(GLuint index, const GLubyte * v) {if (GLeeInit()) glVertexAttrib4NubvARB(index, v);} + GLEEPFNGLVERTEXATTRIB4NUBVARBPROC GLeeFuncPtr_glVertexAttrib4NubvARB=GLee_Lazy_glVertexAttrib4NubvARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4NuivARB +#define GLEE_C_DEFINED_glVertexAttrib4NuivARB + void __stdcall GLee_Lazy_glVertexAttrib4NuivARB(GLuint index, const GLuint * v) {if (GLeeInit()) glVertexAttrib4NuivARB(index, v);} + GLEEPFNGLVERTEXATTRIB4NUIVARBPROC GLeeFuncPtr_glVertexAttrib4NuivARB=GLee_Lazy_glVertexAttrib4NuivARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4NusvARB +#define GLEE_C_DEFINED_glVertexAttrib4NusvARB + void __stdcall GLee_Lazy_glVertexAttrib4NusvARB(GLuint index, const GLushort * v) {if (GLeeInit()) glVertexAttrib4NusvARB(index, v);} + GLEEPFNGLVERTEXATTRIB4NUSVARBPROC GLeeFuncPtr_glVertexAttrib4NusvARB=GLee_Lazy_glVertexAttrib4NusvARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4bvARB +#define GLEE_C_DEFINED_glVertexAttrib4bvARB + void __stdcall GLee_Lazy_glVertexAttrib4bvARB(GLuint index, const GLbyte * v) {if (GLeeInit()) glVertexAttrib4bvARB(index, v);} + GLEEPFNGLVERTEXATTRIB4BVARBPROC GLeeFuncPtr_glVertexAttrib4bvARB=GLee_Lazy_glVertexAttrib4bvARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4dARB +#define GLEE_C_DEFINED_glVertexAttrib4dARB + void __stdcall GLee_Lazy_glVertexAttrib4dARB(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) {if (GLeeInit()) glVertexAttrib4dARB(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIB4DARBPROC GLeeFuncPtr_glVertexAttrib4dARB=GLee_Lazy_glVertexAttrib4dARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4dvARB +#define GLEE_C_DEFINED_glVertexAttrib4dvARB + void __stdcall GLee_Lazy_glVertexAttrib4dvARB(GLuint index, const GLdouble * v) {if (GLeeInit()) glVertexAttrib4dvARB(index, v);} + GLEEPFNGLVERTEXATTRIB4DVARBPROC GLeeFuncPtr_glVertexAttrib4dvARB=GLee_Lazy_glVertexAttrib4dvARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4fARB +#define GLEE_C_DEFINED_glVertexAttrib4fARB + void __stdcall GLee_Lazy_glVertexAttrib4fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {if (GLeeInit()) glVertexAttrib4fARB(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIB4FARBPROC GLeeFuncPtr_glVertexAttrib4fARB=GLee_Lazy_glVertexAttrib4fARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4fvARB +#define GLEE_C_DEFINED_glVertexAttrib4fvARB + void __stdcall GLee_Lazy_glVertexAttrib4fvARB(GLuint index, const GLfloat * v) {if (GLeeInit()) glVertexAttrib4fvARB(index, v);} + GLEEPFNGLVERTEXATTRIB4FVARBPROC GLeeFuncPtr_glVertexAttrib4fvARB=GLee_Lazy_glVertexAttrib4fvARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4ivARB +#define GLEE_C_DEFINED_glVertexAttrib4ivARB + void __stdcall GLee_Lazy_glVertexAttrib4ivARB(GLuint index, const GLint * v) {if (GLeeInit()) glVertexAttrib4ivARB(index, v);} + GLEEPFNGLVERTEXATTRIB4IVARBPROC GLeeFuncPtr_glVertexAttrib4ivARB=GLee_Lazy_glVertexAttrib4ivARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4sARB +#define GLEE_C_DEFINED_glVertexAttrib4sARB + void __stdcall GLee_Lazy_glVertexAttrib4sARB(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) {if (GLeeInit()) glVertexAttrib4sARB(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIB4SARBPROC GLeeFuncPtr_glVertexAttrib4sARB=GLee_Lazy_glVertexAttrib4sARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4svARB +#define GLEE_C_DEFINED_glVertexAttrib4svARB + void __stdcall GLee_Lazy_glVertexAttrib4svARB(GLuint index, const GLshort * v) {if (GLeeInit()) glVertexAttrib4svARB(index, v);} + GLEEPFNGLVERTEXATTRIB4SVARBPROC GLeeFuncPtr_glVertexAttrib4svARB=GLee_Lazy_glVertexAttrib4svARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4ubvARB +#define GLEE_C_DEFINED_glVertexAttrib4ubvARB + void __stdcall GLee_Lazy_glVertexAttrib4ubvARB(GLuint index, const GLubyte * v) {if (GLeeInit()) glVertexAttrib4ubvARB(index, v);} + GLEEPFNGLVERTEXATTRIB4UBVARBPROC GLeeFuncPtr_glVertexAttrib4ubvARB=GLee_Lazy_glVertexAttrib4ubvARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4uivARB +#define GLEE_C_DEFINED_glVertexAttrib4uivARB + void __stdcall GLee_Lazy_glVertexAttrib4uivARB(GLuint index, const GLuint * v) {if (GLeeInit()) glVertexAttrib4uivARB(index, v);} + GLEEPFNGLVERTEXATTRIB4UIVARBPROC GLeeFuncPtr_glVertexAttrib4uivARB=GLee_Lazy_glVertexAttrib4uivARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4usvARB +#define GLEE_C_DEFINED_glVertexAttrib4usvARB + void __stdcall GLee_Lazy_glVertexAttrib4usvARB(GLuint index, const GLushort * v) {if (GLeeInit()) glVertexAttrib4usvARB(index, v);} + GLEEPFNGLVERTEXATTRIB4USVARBPROC GLeeFuncPtr_glVertexAttrib4usvARB=GLee_Lazy_glVertexAttrib4usvARB; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribPointerARB +#define GLEE_C_DEFINED_glVertexAttribPointerARB + void __stdcall GLee_Lazy_glVertexAttribPointerARB(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer) {if (GLeeInit()) glVertexAttribPointerARB(index, size, type, normalized, stride, pointer);} + GLEEPFNGLVERTEXATTRIBPOINTERARBPROC GLeeFuncPtr_glVertexAttribPointerARB=GLee_Lazy_glVertexAttribPointerARB; +#endif +#ifndef GLEE_C_DEFINED_glEnableVertexAttribArrayARB +#define GLEE_C_DEFINED_glEnableVertexAttribArrayARB + void __stdcall GLee_Lazy_glEnableVertexAttribArrayARB(GLuint index) {if (GLeeInit()) glEnableVertexAttribArrayARB(index);} + GLEEPFNGLENABLEVERTEXATTRIBARRAYARBPROC GLeeFuncPtr_glEnableVertexAttribArrayARB=GLee_Lazy_glEnableVertexAttribArrayARB; +#endif +#ifndef GLEE_C_DEFINED_glDisableVertexAttribArrayARB +#define GLEE_C_DEFINED_glDisableVertexAttribArrayARB + void __stdcall GLee_Lazy_glDisableVertexAttribArrayARB(GLuint index) {if (GLeeInit()) glDisableVertexAttribArrayARB(index);} + GLEEPFNGLDISABLEVERTEXATTRIBARRAYARBPROC GLeeFuncPtr_glDisableVertexAttribArrayARB=GLee_Lazy_glDisableVertexAttribArrayARB; +#endif +#ifndef GLEE_C_DEFINED_glProgramStringARB +#define GLEE_C_DEFINED_glProgramStringARB + void __stdcall GLee_Lazy_glProgramStringARB(GLenum target, GLenum format, GLsizei len, const GLvoid * string) {if (GLeeInit()) glProgramStringARB(target, format, len, string);} + GLEEPFNGLPROGRAMSTRINGARBPROC GLeeFuncPtr_glProgramStringARB=GLee_Lazy_glProgramStringARB; +#endif +#ifndef GLEE_C_DEFINED_glBindProgramARB +#define GLEE_C_DEFINED_glBindProgramARB + void __stdcall GLee_Lazy_glBindProgramARB(GLenum target, GLuint program) {if (GLeeInit()) glBindProgramARB(target, program);} + GLEEPFNGLBINDPROGRAMARBPROC GLeeFuncPtr_glBindProgramARB=GLee_Lazy_glBindProgramARB; +#endif +#ifndef GLEE_C_DEFINED_glDeleteProgramsARB +#define GLEE_C_DEFINED_glDeleteProgramsARB + void __stdcall GLee_Lazy_glDeleteProgramsARB(GLsizei n, const GLuint * programs) {if (GLeeInit()) glDeleteProgramsARB(n, programs);} + GLEEPFNGLDELETEPROGRAMSARBPROC GLeeFuncPtr_glDeleteProgramsARB=GLee_Lazy_glDeleteProgramsARB; +#endif +#ifndef GLEE_C_DEFINED_glGenProgramsARB +#define GLEE_C_DEFINED_glGenProgramsARB + void __stdcall GLee_Lazy_glGenProgramsARB(GLsizei n, GLuint * programs) {if (GLeeInit()) glGenProgramsARB(n, programs);} + GLEEPFNGLGENPROGRAMSARBPROC GLeeFuncPtr_glGenProgramsARB=GLee_Lazy_glGenProgramsARB; +#endif +#ifndef GLEE_C_DEFINED_glProgramEnvParameter4dARB +#define GLEE_C_DEFINED_glProgramEnvParameter4dARB + void __stdcall GLee_Lazy_glProgramEnvParameter4dARB(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) {if (GLeeInit()) glProgramEnvParameter4dARB(target, index, x, y, z, w);} + GLEEPFNGLPROGRAMENVPARAMETER4DARBPROC GLeeFuncPtr_glProgramEnvParameter4dARB=GLee_Lazy_glProgramEnvParameter4dARB; +#endif +#ifndef GLEE_C_DEFINED_glProgramEnvParameter4dvARB +#define GLEE_C_DEFINED_glProgramEnvParameter4dvARB + void __stdcall GLee_Lazy_glProgramEnvParameter4dvARB(GLenum target, GLuint index, const GLdouble * params) {if (GLeeInit()) glProgramEnvParameter4dvARB(target, index, params);} + GLEEPFNGLPROGRAMENVPARAMETER4DVARBPROC GLeeFuncPtr_glProgramEnvParameter4dvARB=GLee_Lazy_glProgramEnvParameter4dvARB; +#endif +#ifndef GLEE_C_DEFINED_glProgramEnvParameter4fARB +#define GLEE_C_DEFINED_glProgramEnvParameter4fARB + void __stdcall GLee_Lazy_glProgramEnvParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {if (GLeeInit()) glProgramEnvParameter4fARB(target, index, x, y, z, w);} + GLEEPFNGLPROGRAMENVPARAMETER4FARBPROC GLeeFuncPtr_glProgramEnvParameter4fARB=GLee_Lazy_glProgramEnvParameter4fARB; +#endif +#ifndef GLEE_C_DEFINED_glProgramEnvParameter4fvARB +#define GLEE_C_DEFINED_glProgramEnvParameter4fvARB + void __stdcall GLee_Lazy_glProgramEnvParameter4fvARB(GLenum target, GLuint index, const GLfloat * params) {if (GLeeInit()) glProgramEnvParameter4fvARB(target, index, params);} + GLEEPFNGLPROGRAMENVPARAMETER4FVARBPROC GLeeFuncPtr_glProgramEnvParameter4fvARB=GLee_Lazy_glProgramEnvParameter4fvARB; +#endif +#ifndef GLEE_C_DEFINED_glProgramLocalParameter4dARB +#define GLEE_C_DEFINED_glProgramLocalParameter4dARB + void __stdcall GLee_Lazy_glProgramLocalParameter4dARB(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) {if (GLeeInit()) glProgramLocalParameter4dARB(target, index, x, y, z, w);} + GLEEPFNGLPROGRAMLOCALPARAMETER4DARBPROC GLeeFuncPtr_glProgramLocalParameter4dARB=GLee_Lazy_glProgramLocalParameter4dARB; +#endif +#ifndef GLEE_C_DEFINED_glProgramLocalParameter4dvARB +#define GLEE_C_DEFINED_glProgramLocalParameter4dvARB + void __stdcall GLee_Lazy_glProgramLocalParameter4dvARB(GLenum target, GLuint index, const GLdouble * params) {if (GLeeInit()) glProgramLocalParameter4dvARB(target, index, params);} + GLEEPFNGLPROGRAMLOCALPARAMETER4DVARBPROC GLeeFuncPtr_glProgramLocalParameter4dvARB=GLee_Lazy_glProgramLocalParameter4dvARB; +#endif +#ifndef GLEE_C_DEFINED_glProgramLocalParameter4fARB +#define GLEE_C_DEFINED_glProgramLocalParameter4fARB + void __stdcall GLee_Lazy_glProgramLocalParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {if (GLeeInit()) glProgramLocalParameter4fARB(target, index, x, y, z, w);} + GLEEPFNGLPROGRAMLOCALPARAMETER4FARBPROC GLeeFuncPtr_glProgramLocalParameter4fARB=GLee_Lazy_glProgramLocalParameter4fARB; +#endif +#ifndef GLEE_C_DEFINED_glProgramLocalParameter4fvARB +#define GLEE_C_DEFINED_glProgramLocalParameter4fvARB + void __stdcall GLee_Lazy_glProgramLocalParameter4fvARB(GLenum target, GLuint index, const GLfloat * params) {if (GLeeInit()) glProgramLocalParameter4fvARB(target, index, params);} + GLEEPFNGLPROGRAMLOCALPARAMETER4FVARBPROC GLeeFuncPtr_glProgramLocalParameter4fvARB=GLee_Lazy_glProgramLocalParameter4fvARB; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramEnvParameterdvARB +#define GLEE_C_DEFINED_glGetProgramEnvParameterdvARB + void __stdcall GLee_Lazy_glGetProgramEnvParameterdvARB(GLenum target, GLuint index, GLdouble * params) {if (GLeeInit()) glGetProgramEnvParameterdvARB(target, index, params);} + GLEEPFNGLGETPROGRAMENVPARAMETERDVARBPROC GLeeFuncPtr_glGetProgramEnvParameterdvARB=GLee_Lazy_glGetProgramEnvParameterdvARB; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramEnvParameterfvARB +#define GLEE_C_DEFINED_glGetProgramEnvParameterfvARB + void __stdcall GLee_Lazy_glGetProgramEnvParameterfvARB(GLenum target, GLuint index, GLfloat * params) {if (GLeeInit()) glGetProgramEnvParameterfvARB(target, index, params);} + GLEEPFNGLGETPROGRAMENVPARAMETERFVARBPROC GLeeFuncPtr_glGetProgramEnvParameterfvARB=GLee_Lazy_glGetProgramEnvParameterfvARB; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramLocalParameterdvARB +#define GLEE_C_DEFINED_glGetProgramLocalParameterdvARB + void __stdcall GLee_Lazy_glGetProgramLocalParameterdvARB(GLenum target, GLuint index, GLdouble * params) {if (GLeeInit()) glGetProgramLocalParameterdvARB(target, index, params);} + GLEEPFNGLGETPROGRAMLOCALPARAMETERDVARBPROC GLeeFuncPtr_glGetProgramLocalParameterdvARB=GLee_Lazy_glGetProgramLocalParameterdvARB; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramLocalParameterfvARB +#define GLEE_C_DEFINED_glGetProgramLocalParameterfvARB + void __stdcall GLee_Lazy_glGetProgramLocalParameterfvARB(GLenum target, GLuint index, GLfloat * params) {if (GLeeInit()) glGetProgramLocalParameterfvARB(target, index, params);} + GLEEPFNGLGETPROGRAMLOCALPARAMETERFVARBPROC GLeeFuncPtr_glGetProgramLocalParameterfvARB=GLee_Lazy_glGetProgramLocalParameterfvARB; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramivARB +#define GLEE_C_DEFINED_glGetProgramivARB + void __stdcall GLee_Lazy_glGetProgramivARB(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetProgramivARB(target, pname, params);} + GLEEPFNGLGETPROGRAMIVARBPROC GLeeFuncPtr_glGetProgramivARB=GLee_Lazy_glGetProgramivARB; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramStringARB +#define GLEE_C_DEFINED_glGetProgramStringARB + void __stdcall GLee_Lazy_glGetProgramStringARB(GLenum target, GLenum pname, GLvoid * string) {if (GLeeInit()) glGetProgramStringARB(target, pname, string);} + GLEEPFNGLGETPROGRAMSTRINGARBPROC GLeeFuncPtr_glGetProgramStringARB=GLee_Lazy_glGetProgramStringARB; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribdvARB +#define GLEE_C_DEFINED_glGetVertexAttribdvARB + void __stdcall GLee_Lazy_glGetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble * params) {if (GLeeInit()) glGetVertexAttribdvARB(index, pname, params);} + GLEEPFNGLGETVERTEXATTRIBDVARBPROC GLeeFuncPtr_glGetVertexAttribdvARB=GLee_Lazy_glGetVertexAttribdvARB; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribfvARB +#define GLEE_C_DEFINED_glGetVertexAttribfvARB + void __stdcall GLee_Lazy_glGetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetVertexAttribfvARB(index, pname, params);} + GLEEPFNGLGETVERTEXATTRIBFVARBPROC GLeeFuncPtr_glGetVertexAttribfvARB=GLee_Lazy_glGetVertexAttribfvARB; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribivARB +#define GLEE_C_DEFINED_glGetVertexAttribivARB + void __stdcall GLee_Lazy_glGetVertexAttribivARB(GLuint index, GLenum pname, GLint * params) {if (GLeeInit()) glGetVertexAttribivARB(index, pname, params);} + GLEEPFNGLGETVERTEXATTRIBIVARBPROC GLeeFuncPtr_glGetVertexAttribivARB=GLee_Lazy_glGetVertexAttribivARB; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribPointervARB +#define GLEE_C_DEFINED_glGetVertexAttribPointervARB + void __stdcall GLee_Lazy_glGetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid* * pointer) {if (GLeeInit()) glGetVertexAttribPointervARB(index, pname, pointer);} + GLEEPFNGLGETVERTEXATTRIBPOINTERVARBPROC GLeeFuncPtr_glGetVertexAttribPointervARB=GLee_Lazy_glGetVertexAttribPointervARB; +#endif +#ifndef GLEE_C_DEFINED_glIsProgramARB +#define GLEE_C_DEFINED_glIsProgramARB + GLboolean __stdcall GLee_Lazy_glIsProgramARB(GLuint program) {if (GLeeInit()) return glIsProgramARB(program); return (GLboolean)0;} + GLEEPFNGLISPROGRAMARBPROC GLeeFuncPtr_glIsProgramARB=GLee_Lazy_glIsProgramARB; +#endif +#endif + +/* GL_ARB_fragment_program */ + +#ifdef __GLEE_GL_ARB_fragment_program +#endif + +/* GL_ARB_vertex_buffer_object */ + +#ifdef __GLEE_GL_ARB_vertex_buffer_object +#ifndef GLEE_C_DEFINED_glBindBufferARB +#define GLEE_C_DEFINED_glBindBufferARB + void __stdcall GLee_Lazy_glBindBufferARB(GLenum target, GLuint buffer) {if (GLeeInit()) glBindBufferARB(target, buffer);} + GLEEPFNGLBINDBUFFERARBPROC GLeeFuncPtr_glBindBufferARB=GLee_Lazy_glBindBufferARB; +#endif +#ifndef GLEE_C_DEFINED_glDeleteBuffersARB +#define GLEE_C_DEFINED_glDeleteBuffersARB + void __stdcall GLee_Lazy_glDeleteBuffersARB(GLsizei n, const GLuint * buffers) {if (GLeeInit()) glDeleteBuffersARB(n, buffers);} + GLEEPFNGLDELETEBUFFERSARBPROC GLeeFuncPtr_glDeleteBuffersARB=GLee_Lazy_glDeleteBuffersARB; +#endif +#ifndef GLEE_C_DEFINED_glGenBuffersARB +#define GLEE_C_DEFINED_glGenBuffersARB + void __stdcall GLee_Lazy_glGenBuffersARB(GLsizei n, GLuint * buffers) {if (GLeeInit()) glGenBuffersARB(n, buffers);} + GLEEPFNGLGENBUFFERSARBPROC GLeeFuncPtr_glGenBuffersARB=GLee_Lazy_glGenBuffersARB; +#endif +#ifndef GLEE_C_DEFINED_glIsBufferARB +#define GLEE_C_DEFINED_glIsBufferARB + GLboolean __stdcall GLee_Lazy_glIsBufferARB(GLuint buffer) {if (GLeeInit()) return glIsBufferARB(buffer); return (GLboolean)0;} + GLEEPFNGLISBUFFERARBPROC GLeeFuncPtr_glIsBufferARB=GLee_Lazy_glIsBufferARB; +#endif +#ifndef GLEE_C_DEFINED_glBufferDataARB +#define GLEE_C_DEFINED_glBufferDataARB + void __stdcall GLee_Lazy_glBufferDataARB(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage) {if (GLeeInit()) glBufferDataARB(target, size, data, usage);} + GLEEPFNGLBUFFERDATAARBPROC GLeeFuncPtr_glBufferDataARB=GLee_Lazy_glBufferDataARB; +#endif +#ifndef GLEE_C_DEFINED_glBufferSubDataARB +#define GLEE_C_DEFINED_glBufferSubDataARB + void __stdcall GLee_Lazy_glBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data) {if (GLeeInit()) glBufferSubDataARB(target, offset, size, data);} + GLEEPFNGLBUFFERSUBDATAARBPROC GLeeFuncPtr_glBufferSubDataARB=GLee_Lazy_glBufferSubDataARB; +#endif +#ifndef GLEE_C_DEFINED_glGetBufferSubDataARB +#define GLEE_C_DEFINED_glGetBufferSubDataARB + void __stdcall GLee_Lazy_glGetBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid * data) {if (GLeeInit()) glGetBufferSubDataARB(target, offset, size, data);} + GLEEPFNGLGETBUFFERSUBDATAARBPROC GLeeFuncPtr_glGetBufferSubDataARB=GLee_Lazy_glGetBufferSubDataARB; +#endif +#ifndef GLEE_C_DEFINED_glMapBufferARB +#define GLEE_C_DEFINED_glMapBufferARB + GLvoid* __stdcall GLee_Lazy_glMapBufferARB(GLenum target, GLenum access) {if (GLeeInit()) return glMapBufferARB(target, access); return (GLvoid*)0;} + GLEEPFNGLMAPBUFFERARBPROC GLeeFuncPtr_glMapBufferARB=GLee_Lazy_glMapBufferARB; +#endif +#ifndef GLEE_C_DEFINED_glUnmapBufferARB +#define GLEE_C_DEFINED_glUnmapBufferARB + GLboolean __stdcall GLee_Lazy_glUnmapBufferARB(GLenum target) {if (GLeeInit()) return glUnmapBufferARB(target); return (GLboolean)0;} + GLEEPFNGLUNMAPBUFFERARBPROC GLeeFuncPtr_glUnmapBufferARB=GLee_Lazy_glUnmapBufferARB; +#endif +#ifndef GLEE_C_DEFINED_glGetBufferParameterivARB +#define GLEE_C_DEFINED_glGetBufferParameterivARB + void __stdcall GLee_Lazy_glGetBufferParameterivARB(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetBufferParameterivARB(target, pname, params);} + GLEEPFNGLGETBUFFERPARAMETERIVARBPROC GLeeFuncPtr_glGetBufferParameterivARB=GLee_Lazy_glGetBufferParameterivARB; +#endif +#ifndef GLEE_C_DEFINED_glGetBufferPointervARB +#define GLEE_C_DEFINED_glGetBufferPointervARB + void __stdcall GLee_Lazy_glGetBufferPointervARB(GLenum target, GLenum pname, GLvoid* * params) {if (GLeeInit()) glGetBufferPointervARB(target, pname, params);} + GLEEPFNGLGETBUFFERPOINTERVARBPROC GLeeFuncPtr_glGetBufferPointervARB=GLee_Lazy_glGetBufferPointervARB; +#endif +#endif + +/* GL_ARB_occlusion_query */ + +#ifdef __GLEE_GL_ARB_occlusion_query +#ifndef GLEE_C_DEFINED_glGenQueriesARB +#define GLEE_C_DEFINED_glGenQueriesARB + void __stdcall GLee_Lazy_glGenQueriesARB(GLsizei n, GLuint * ids) {if (GLeeInit()) glGenQueriesARB(n, ids);} + GLEEPFNGLGENQUERIESARBPROC GLeeFuncPtr_glGenQueriesARB=GLee_Lazy_glGenQueriesARB; +#endif +#ifndef GLEE_C_DEFINED_glDeleteQueriesARB +#define GLEE_C_DEFINED_glDeleteQueriesARB + void __stdcall GLee_Lazy_glDeleteQueriesARB(GLsizei n, const GLuint * ids) {if (GLeeInit()) glDeleteQueriesARB(n, ids);} + GLEEPFNGLDELETEQUERIESARBPROC GLeeFuncPtr_glDeleteQueriesARB=GLee_Lazy_glDeleteQueriesARB; +#endif +#ifndef GLEE_C_DEFINED_glIsQueryARB +#define GLEE_C_DEFINED_glIsQueryARB + GLboolean __stdcall GLee_Lazy_glIsQueryARB(GLuint id) {if (GLeeInit()) return glIsQueryARB(id); return (GLboolean)0;} + GLEEPFNGLISQUERYARBPROC GLeeFuncPtr_glIsQueryARB=GLee_Lazy_glIsQueryARB; +#endif +#ifndef GLEE_C_DEFINED_glBeginQueryARB +#define GLEE_C_DEFINED_glBeginQueryARB + void __stdcall GLee_Lazy_glBeginQueryARB(GLenum target, GLuint id) {if (GLeeInit()) glBeginQueryARB(target, id);} + GLEEPFNGLBEGINQUERYARBPROC GLeeFuncPtr_glBeginQueryARB=GLee_Lazy_glBeginQueryARB; +#endif +#ifndef GLEE_C_DEFINED_glEndQueryARB +#define GLEE_C_DEFINED_glEndQueryARB + void __stdcall GLee_Lazy_glEndQueryARB(GLenum target) {if (GLeeInit()) glEndQueryARB(target);} + GLEEPFNGLENDQUERYARBPROC GLeeFuncPtr_glEndQueryARB=GLee_Lazy_glEndQueryARB; +#endif +#ifndef GLEE_C_DEFINED_glGetQueryivARB +#define GLEE_C_DEFINED_glGetQueryivARB + void __stdcall GLee_Lazy_glGetQueryivARB(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetQueryivARB(target, pname, params);} + GLEEPFNGLGETQUERYIVARBPROC GLeeFuncPtr_glGetQueryivARB=GLee_Lazy_glGetQueryivARB; +#endif +#ifndef GLEE_C_DEFINED_glGetQueryObjectivARB +#define GLEE_C_DEFINED_glGetQueryObjectivARB + void __stdcall GLee_Lazy_glGetQueryObjectivARB(GLuint id, GLenum pname, GLint * params) {if (GLeeInit()) glGetQueryObjectivARB(id, pname, params);} + GLEEPFNGLGETQUERYOBJECTIVARBPROC GLeeFuncPtr_glGetQueryObjectivARB=GLee_Lazy_glGetQueryObjectivARB; +#endif +#ifndef GLEE_C_DEFINED_glGetQueryObjectuivARB +#define GLEE_C_DEFINED_glGetQueryObjectuivARB + void __stdcall GLee_Lazy_glGetQueryObjectuivARB(GLuint id, GLenum pname, GLuint * params) {if (GLeeInit()) glGetQueryObjectuivARB(id, pname, params);} + GLEEPFNGLGETQUERYOBJECTUIVARBPROC GLeeFuncPtr_glGetQueryObjectuivARB=GLee_Lazy_glGetQueryObjectuivARB; +#endif +#endif + +/* GL_ARB_shader_objects */ + +#ifdef __GLEE_GL_ARB_shader_objects +#ifndef GLEE_C_DEFINED_glDeleteObjectARB +#define GLEE_C_DEFINED_glDeleteObjectARB + void __stdcall GLee_Lazy_glDeleteObjectARB(GLhandleARB obj) {if (GLeeInit()) glDeleteObjectARB(obj);} + GLEEPFNGLDELETEOBJECTARBPROC GLeeFuncPtr_glDeleteObjectARB=GLee_Lazy_glDeleteObjectARB; +#endif +#ifndef GLEE_C_DEFINED_glGetHandleARB +#define GLEE_C_DEFINED_glGetHandleARB + GLhandleARB __stdcall GLee_Lazy_glGetHandleARB(GLenum pname) {if (GLeeInit()) return glGetHandleARB(pname); return (GLhandleARB)0;} + GLEEPFNGLGETHANDLEARBPROC GLeeFuncPtr_glGetHandleARB=GLee_Lazy_glGetHandleARB; +#endif +#ifndef GLEE_C_DEFINED_glDetachObjectARB +#define GLEE_C_DEFINED_glDetachObjectARB + void __stdcall GLee_Lazy_glDetachObjectARB(GLhandleARB containerObj, GLhandleARB attachedObj) {if (GLeeInit()) glDetachObjectARB(containerObj, attachedObj);} + GLEEPFNGLDETACHOBJECTARBPROC GLeeFuncPtr_glDetachObjectARB=GLee_Lazy_glDetachObjectARB; +#endif +#ifndef GLEE_C_DEFINED_glCreateShaderObjectARB +#define GLEE_C_DEFINED_glCreateShaderObjectARB + GLhandleARB __stdcall GLee_Lazy_glCreateShaderObjectARB(GLenum shaderType) {if (GLeeInit()) return glCreateShaderObjectARB(shaderType); return (GLhandleARB)0;} + GLEEPFNGLCREATESHADEROBJECTARBPROC GLeeFuncPtr_glCreateShaderObjectARB=GLee_Lazy_glCreateShaderObjectARB; +#endif +#ifndef GLEE_C_DEFINED_glShaderSourceARB +#define GLEE_C_DEFINED_glShaderSourceARB + void __stdcall GLee_Lazy_glShaderSourceARB(GLhandleARB shaderObj, GLsizei count, const GLcharARB* * string, const GLint * length) {if (GLeeInit()) glShaderSourceARB(shaderObj, count, string, length);} + GLEEPFNGLSHADERSOURCEARBPROC GLeeFuncPtr_glShaderSourceARB=GLee_Lazy_glShaderSourceARB; +#endif +#ifndef GLEE_C_DEFINED_glCompileShaderARB +#define GLEE_C_DEFINED_glCompileShaderARB + void __stdcall GLee_Lazy_glCompileShaderARB(GLhandleARB shaderObj) {if (GLeeInit()) glCompileShaderARB(shaderObj);} + GLEEPFNGLCOMPILESHADERARBPROC GLeeFuncPtr_glCompileShaderARB=GLee_Lazy_glCompileShaderARB; +#endif +#ifndef GLEE_C_DEFINED_glCreateProgramObjectARB +#define GLEE_C_DEFINED_glCreateProgramObjectARB + GLhandleARB __stdcall GLee_Lazy_glCreateProgramObjectARB(void) {if (GLeeInit()) return glCreateProgramObjectARB(); return (GLhandleARB)0;} + GLEEPFNGLCREATEPROGRAMOBJECTARBPROC GLeeFuncPtr_glCreateProgramObjectARB=GLee_Lazy_glCreateProgramObjectARB; +#endif +#ifndef GLEE_C_DEFINED_glAttachObjectARB +#define GLEE_C_DEFINED_glAttachObjectARB + void __stdcall GLee_Lazy_glAttachObjectARB(GLhandleARB containerObj, GLhandleARB obj) {if (GLeeInit()) glAttachObjectARB(containerObj, obj);} + GLEEPFNGLATTACHOBJECTARBPROC GLeeFuncPtr_glAttachObjectARB=GLee_Lazy_glAttachObjectARB; +#endif +#ifndef GLEE_C_DEFINED_glLinkProgramARB +#define GLEE_C_DEFINED_glLinkProgramARB + void __stdcall GLee_Lazy_glLinkProgramARB(GLhandleARB programObj) {if (GLeeInit()) glLinkProgramARB(programObj);} + GLEEPFNGLLINKPROGRAMARBPROC GLeeFuncPtr_glLinkProgramARB=GLee_Lazy_glLinkProgramARB; +#endif +#ifndef GLEE_C_DEFINED_glUseProgramObjectARB +#define GLEE_C_DEFINED_glUseProgramObjectARB + void __stdcall GLee_Lazy_glUseProgramObjectARB(GLhandleARB programObj) {if (GLeeInit()) glUseProgramObjectARB(programObj);} + GLEEPFNGLUSEPROGRAMOBJECTARBPROC GLeeFuncPtr_glUseProgramObjectARB=GLee_Lazy_glUseProgramObjectARB; +#endif +#ifndef GLEE_C_DEFINED_glValidateProgramARB +#define GLEE_C_DEFINED_glValidateProgramARB + void __stdcall GLee_Lazy_glValidateProgramARB(GLhandleARB programObj) {if (GLeeInit()) glValidateProgramARB(programObj);} + GLEEPFNGLVALIDATEPROGRAMARBPROC GLeeFuncPtr_glValidateProgramARB=GLee_Lazy_glValidateProgramARB; +#endif +#ifndef GLEE_C_DEFINED_glUniform1fARB +#define GLEE_C_DEFINED_glUniform1fARB + void __stdcall GLee_Lazy_glUniform1fARB(GLint location, GLfloat v0) {if (GLeeInit()) glUniform1fARB(location, v0);} + GLEEPFNGLUNIFORM1FARBPROC GLeeFuncPtr_glUniform1fARB=GLee_Lazy_glUniform1fARB; +#endif +#ifndef GLEE_C_DEFINED_glUniform2fARB +#define GLEE_C_DEFINED_glUniform2fARB + void __stdcall GLee_Lazy_glUniform2fARB(GLint location, GLfloat v0, GLfloat v1) {if (GLeeInit()) glUniform2fARB(location, v0, v1);} + GLEEPFNGLUNIFORM2FARBPROC GLeeFuncPtr_glUniform2fARB=GLee_Lazy_glUniform2fARB; +#endif +#ifndef GLEE_C_DEFINED_glUniform3fARB +#define GLEE_C_DEFINED_glUniform3fARB + void __stdcall GLee_Lazy_glUniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {if (GLeeInit()) glUniform3fARB(location, v0, v1, v2);} + GLEEPFNGLUNIFORM3FARBPROC GLeeFuncPtr_glUniform3fARB=GLee_Lazy_glUniform3fARB; +#endif +#ifndef GLEE_C_DEFINED_glUniform4fARB +#define GLEE_C_DEFINED_glUniform4fARB + void __stdcall GLee_Lazy_glUniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {if (GLeeInit()) glUniform4fARB(location, v0, v1, v2, v3);} + GLEEPFNGLUNIFORM4FARBPROC GLeeFuncPtr_glUniform4fARB=GLee_Lazy_glUniform4fARB; +#endif +#ifndef GLEE_C_DEFINED_glUniform1iARB +#define GLEE_C_DEFINED_glUniform1iARB + void __stdcall GLee_Lazy_glUniform1iARB(GLint location, GLint v0) {if (GLeeInit()) glUniform1iARB(location, v0);} + GLEEPFNGLUNIFORM1IARBPROC GLeeFuncPtr_glUniform1iARB=GLee_Lazy_glUniform1iARB; +#endif +#ifndef GLEE_C_DEFINED_glUniform2iARB +#define GLEE_C_DEFINED_glUniform2iARB + void __stdcall GLee_Lazy_glUniform2iARB(GLint location, GLint v0, GLint v1) {if (GLeeInit()) glUniform2iARB(location, v0, v1);} + GLEEPFNGLUNIFORM2IARBPROC GLeeFuncPtr_glUniform2iARB=GLee_Lazy_glUniform2iARB; +#endif +#ifndef GLEE_C_DEFINED_glUniform3iARB +#define GLEE_C_DEFINED_glUniform3iARB + void __stdcall GLee_Lazy_glUniform3iARB(GLint location, GLint v0, GLint v1, GLint v2) {if (GLeeInit()) glUniform3iARB(location, v0, v1, v2);} + GLEEPFNGLUNIFORM3IARBPROC GLeeFuncPtr_glUniform3iARB=GLee_Lazy_glUniform3iARB; +#endif +#ifndef GLEE_C_DEFINED_glUniform4iARB +#define GLEE_C_DEFINED_glUniform4iARB + void __stdcall GLee_Lazy_glUniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {if (GLeeInit()) glUniform4iARB(location, v0, v1, v2, v3);} + GLEEPFNGLUNIFORM4IARBPROC GLeeFuncPtr_glUniform4iARB=GLee_Lazy_glUniform4iARB; +#endif +#ifndef GLEE_C_DEFINED_glUniform1fvARB +#define GLEE_C_DEFINED_glUniform1fvARB + void __stdcall GLee_Lazy_glUniform1fvARB(GLint location, GLsizei count, const GLfloat * value) {if (GLeeInit()) glUniform1fvARB(location, count, value);} + GLEEPFNGLUNIFORM1FVARBPROC GLeeFuncPtr_glUniform1fvARB=GLee_Lazy_glUniform1fvARB; +#endif +#ifndef GLEE_C_DEFINED_glUniform2fvARB +#define GLEE_C_DEFINED_glUniform2fvARB + void __stdcall GLee_Lazy_glUniform2fvARB(GLint location, GLsizei count, const GLfloat * value) {if (GLeeInit()) glUniform2fvARB(location, count, value);} + GLEEPFNGLUNIFORM2FVARBPROC GLeeFuncPtr_glUniform2fvARB=GLee_Lazy_glUniform2fvARB; +#endif +#ifndef GLEE_C_DEFINED_glUniform3fvARB +#define GLEE_C_DEFINED_glUniform3fvARB + void __stdcall GLee_Lazy_glUniform3fvARB(GLint location, GLsizei count, const GLfloat * value) {if (GLeeInit()) glUniform3fvARB(location, count, value);} + GLEEPFNGLUNIFORM3FVARBPROC GLeeFuncPtr_glUniform3fvARB=GLee_Lazy_glUniform3fvARB; +#endif +#ifndef GLEE_C_DEFINED_glUniform4fvARB +#define GLEE_C_DEFINED_glUniform4fvARB + void __stdcall GLee_Lazy_glUniform4fvARB(GLint location, GLsizei count, const GLfloat * value) {if (GLeeInit()) glUniform4fvARB(location, count, value);} + GLEEPFNGLUNIFORM4FVARBPROC GLeeFuncPtr_glUniform4fvARB=GLee_Lazy_glUniform4fvARB; +#endif +#ifndef GLEE_C_DEFINED_glUniform1ivARB +#define GLEE_C_DEFINED_glUniform1ivARB + void __stdcall GLee_Lazy_glUniform1ivARB(GLint location, GLsizei count, const GLint * value) {if (GLeeInit()) glUniform1ivARB(location, count, value);} + GLEEPFNGLUNIFORM1IVARBPROC GLeeFuncPtr_glUniform1ivARB=GLee_Lazy_glUniform1ivARB; +#endif +#ifndef GLEE_C_DEFINED_glUniform2ivARB +#define GLEE_C_DEFINED_glUniform2ivARB + void __stdcall GLee_Lazy_glUniform2ivARB(GLint location, GLsizei count, const GLint * value) {if (GLeeInit()) glUniform2ivARB(location, count, value);} + GLEEPFNGLUNIFORM2IVARBPROC GLeeFuncPtr_glUniform2ivARB=GLee_Lazy_glUniform2ivARB; +#endif +#ifndef GLEE_C_DEFINED_glUniform3ivARB +#define GLEE_C_DEFINED_glUniform3ivARB + void __stdcall GLee_Lazy_glUniform3ivARB(GLint location, GLsizei count, const GLint * value) {if (GLeeInit()) glUniform3ivARB(location, count, value);} + GLEEPFNGLUNIFORM3IVARBPROC GLeeFuncPtr_glUniform3ivARB=GLee_Lazy_glUniform3ivARB; +#endif +#ifndef GLEE_C_DEFINED_glUniform4ivARB +#define GLEE_C_DEFINED_glUniform4ivARB + void __stdcall GLee_Lazy_glUniform4ivARB(GLint location, GLsizei count, const GLint * value) {if (GLeeInit()) glUniform4ivARB(location, count, value);} + GLEEPFNGLUNIFORM4IVARBPROC GLeeFuncPtr_glUniform4ivARB=GLee_Lazy_glUniform4ivARB; +#endif +#ifndef GLEE_C_DEFINED_glUniformMatrix2fvARB +#define GLEE_C_DEFINED_glUniformMatrix2fvARB + void __stdcall GLee_Lazy_glUniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glUniformMatrix2fvARB(location, count, transpose, value);} + GLEEPFNGLUNIFORMMATRIX2FVARBPROC GLeeFuncPtr_glUniformMatrix2fvARB=GLee_Lazy_glUniformMatrix2fvARB; +#endif +#ifndef GLEE_C_DEFINED_glUniformMatrix3fvARB +#define GLEE_C_DEFINED_glUniformMatrix3fvARB + void __stdcall GLee_Lazy_glUniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glUniformMatrix3fvARB(location, count, transpose, value);} + GLEEPFNGLUNIFORMMATRIX3FVARBPROC GLeeFuncPtr_glUniformMatrix3fvARB=GLee_Lazy_glUniformMatrix3fvARB; +#endif +#ifndef GLEE_C_DEFINED_glUniformMatrix4fvARB +#define GLEE_C_DEFINED_glUniformMatrix4fvARB + void __stdcall GLee_Lazy_glUniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glUniformMatrix4fvARB(location, count, transpose, value);} + GLEEPFNGLUNIFORMMATRIX4FVARBPROC GLeeFuncPtr_glUniformMatrix4fvARB=GLee_Lazy_glUniformMatrix4fvARB; +#endif +#ifndef GLEE_C_DEFINED_glGetObjectParameterfvARB +#define GLEE_C_DEFINED_glGetObjectParameterfvARB + void __stdcall GLee_Lazy_glGetObjectParameterfvARB(GLhandleARB obj, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetObjectParameterfvARB(obj, pname, params);} + GLEEPFNGLGETOBJECTPARAMETERFVARBPROC GLeeFuncPtr_glGetObjectParameterfvARB=GLee_Lazy_glGetObjectParameterfvARB; +#endif +#ifndef GLEE_C_DEFINED_glGetObjectParameterivARB +#define GLEE_C_DEFINED_glGetObjectParameterivARB + void __stdcall GLee_Lazy_glGetObjectParameterivARB(GLhandleARB obj, GLenum pname, GLint * params) {if (GLeeInit()) glGetObjectParameterivARB(obj, pname, params);} + GLEEPFNGLGETOBJECTPARAMETERIVARBPROC GLeeFuncPtr_glGetObjectParameterivARB=GLee_Lazy_glGetObjectParameterivARB; +#endif +#ifndef GLEE_C_DEFINED_glGetInfoLogARB +#define GLEE_C_DEFINED_glGetInfoLogARB + void __stdcall GLee_Lazy_glGetInfoLogARB(GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog) {if (GLeeInit()) glGetInfoLogARB(obj, maxLength, length, infoLog);} + GLEEPFNGLGETINFOLOGARBPROC GLeeFuncPtr_glGetInfoLogARB=GLee_Lazy_glGetInfoLogARB; +#endif +#ifndef GLEE_C_DEFINED_glGetAttachedObjectsARB +#define GLEE_C_DEFINED_glGetAttachedObjectsARB + void __stdcall GLee_Lazy_glGetAttachedObjectsARB(GLhandleARB containerObj, GLsizei maxCount, GLsizei * count, GLhandleARB * obj) {if (GLeeInit()) glGetAttachedObjectsARB(containerObj, maxCount, count, obj);} + GLEEPFNGLGETATTACHEDOBJECTSARBPROC GLeeFuncPtr_glGetAttachedObjectsARB=GLee_Lazy_glGetAttachedObjectsARB; +#endif +#ifndef GLEE_C_DEFINED_glGetUniformLocationARB +#define GLEE_C_DEFINED_glGetUniformLocationARB + GLint __stdcall GLee_Lazy_glGetUniformLocationARB(GLhandleARB programObj, const GLcharARB * name) {if (GLeeInit()) return glGetUniformLocationARB(programObj, name); return (GLint)0;} + GLEEPFNGLGETUNIFORMLOCATIONARBPROC GLeeFuncPtr_glGetUniformLocationARB=GLee_Lazy_glGetUniformLocationARB; +#endif +#ifndef GLEE_C_DEFINED_glGetActiveUniformARB +#define GLEE_C_DEFINED_glGetActiveUniformARB + void __stdcall GLee_Lazy_glGetActiveUniformARB(GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length, GLint * size, GLenum * type, GLcharARB * name) {if (GLeeInit()) glGetActiveUniformARB(programObj, index, maxLength, length, size, type, name);} + GLEEPFNGLGETACTIVEUNIFORMARBPROC GLeeFuncPtr_glGetActiveUniformARB=GLee_Lazy_glGetActiveUniformARB; +#endif +#ifndef GLEE_C_DEFINED_glGetUniformfvARB +#define GLEE_C_DEFINED_glGetUniformfvARB + void __stdcall GLee_Lazy_glGetUniformfvARB(GLhandleARB programObj, GLint location, GLfloat * params) {if (GLeeInit()) glGetUniformfvARB(programObj, location, params);} + GLEEPFNGLGETUNIFORMFVARBPROC GLeeFuncPtr_glGetUniformfvARB=GLee_Lazy_glGetUniformfvARB; +#endif +#ifndef GLEE_C_DEFINED_glGetUniformivARB +#define GLEE_C_DEFINED_glGetUniformivARB + void __stdcall GLee_Lazy_glGetUniformivARB(GLhandleARB programObj, GLint location, GLint * params) {if (GLeeInit()) glGetUniformivARB(programObj, location, params);} + GLEEPFNGLGETUNIFORMIVARBPROC GLeeFuncPtr_glGetUniformivARB=GLee_Lazy_glGetUniformivARB; +#endif +#ifndef GLEE_C_DEFINED_glGetShaderSourceARB +#define GLEE_C_DEFINED_glGetShaderSourceARB + void __stdcall GLee_Lazy_glGetShaderSourceARB(GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * source) {if (GLeeInit()) glGetShaderSourceARB(obj, maxLength, length, source);} + GLEEPFNGLGETSHADERSOURCEARBPROC GLeeFuncPtr_glGetShaderSourceARB=GLee_Lazy_glGetShaderSourceARB; +#endif +#endif + +/* GL_ARB_vertex_shader */ + +#ifdef __GLEE_GL_ARB_vertex_shader +#ifndef GLEE_C_DEFINED_glBindAttribLocationARB +#define GLEE_C_DEFINED_glBindAttribLocationARB + void __stdcall GLee_Lazy_glBindAttribLocationARB(GLhandleARB programObj, GLuint index, const GLcharARB * name) {if (GLeeInit()) glBindAttribLocationARB(programObj, index, name);} + GLEEPFNGLBINDATTRIBLOCATIONARBPROC GLeeFuncPtr_glBindAttribLocationARB=GLee_Lazy_glBindAttribLocationARB; +#endif +#ifndef GLEE_C_DEFINED_glGetActiveAttribARB +#define GLEE_C_DEFINED_glGetActiveAttribARB + void __stdcall GLee_Lazy_glGetActiveAttribARB(GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length, GLint * size, GLenum * type, GLcharARB * name) {if (GLeeInit()) glGetActiveAttribARB(programObj, index, maxLength, length, size, type, name);} + GLEEPFNGLGETACTIVEATTRIBARBPROC GLeeFuncPtr_glGetActiveAttribARB=GLee_Lazy_glGetActiveAttribARB; +#endif +#ifndef GLEE_C_DEFINED_glGetAttribLocationARB +#define GLEE_C_DEFINED_glGetAttribLocationARB + GLint __stdcall GLee_Lazy_glGetAttribLocationARB(GLhandleARB programObj, const GLcharARB * name) {if (GLeeInit()) return glGetAttribLocationARB(programObj, name); return (GLint)0;} + GLEEPFNGLGETATTRIBLOCATIONARBPROC GLeeFuncPtr_glGetAttribLocationARB=GLee_Lazy_glGetAttribLocationARB; +#endif +#endif + +/* GL_ARB_fragment_shader */ + +#ifdef __GLEE_GL_ARB_fragment_shader +#endif + +/* GL_ARB_shading_language_100 */ + +#ifdef __GLEE_GL_ARB_shading_language_100 +#endif + +/* GL_ARB_texture_non_power_of_two */ + +#ifdef __GLEE_GL_ARB_texture_non_power_of_two +#endif + +/* GL_ARB_point_sprite */ + +#ifdef __GLEE_GL_ARB_point_sprite +#endif + +/* GL_ARB_fragment_program_shadow */ + +#ifdef __GLEE_GL_ARB_fragment_program_shadow +#endif + +/* GL_ARB_draw_buffers */ + +#ifdef __GLEE_GL_ARB_draw_buffers +#ifndef GLEE_C_DEFINED_glDrawBuffersARB +#define GLEE_C_DEFINED_glDrawBuffersARB + void __stdcall GLee_Lazy_glDrawBuffersARB(GLsizei n, const GLenum * bufs) {if (GLeeInit()) glDrawBuffersARB(n, bufs);} + GLEEPFNGLDRAWBUFFERSARBPROC GLeeFuncPtr_glDrawBuffersARB=GLee_Lazy_glDrawBuffersARB; +#endif +#endif + +/* GL_ARB_texture_rectangle */ + +#ifdef __GLEE_GL_ARB_texture_rectangle +#endif + +/* GL_ARB_color_buffer_float */ + +#ifdef __GLEE_GL_ARB_color_buffer_float +#ifndef GLEE_C_DEFINED_glClampColorARB +#define GLEE_C_DEFINED_glClampColorARB + void __stdcall GLee_Lazy_glClampColorARB(GLenum target, GLenum clamp) {if (GLeeInit()) glClampColorARB(target, clamp);} + GLEEPFNGLCLAMPCOLORARBPROC GLeeFuncPtr_glClampColorARB=GLee_Lazy_glClampColorARB; +#endif +#endif + +/* GL_ARB_half_float_pixel */ + +#ifdef __GLEE_GL_ARB_half_float_pixel +#endif + +/* GL_ARB_texture_float */ + +#ifdef __GLEE_GL_ARB_texture_float +#endif + +/* GL_ARB_pixel_buffer_object */ + +#ifdef __GLEE_GL_ARB_pixel_buffer_object +#endif + +/* GL_ARB_depth_buffer_float */ + +#ifdef __GLEE_GL_ARB_depth_buffer_float +#endif + +/* GL_ARB_draw_instanced */ + +#ifdef __GLEE_GL_ARB_draw_instanced +#ifndef GLEE_C_DEFINED_glDrawArraysInstancedARB +#define GLEE_C_DEFINED_glDrawArraysInstancedARB + void __stdcall GLee_Lazy_glDrawArraysInstancedARB(GLenum mode, GLint first, GLsizei count, GLsizei primcount) {if (GLeeInit()) glDrawArraysInstancedARB(mode, first, count, primcount);} + GLEEPFNGLDRAWARRAYSINSTANCEDARBPROC GLeeFuncPtr_glDrawArraysInstancedARB=GLee_Lazy_glDrawArraysInstancedARB; +#endif +#ifndef GLEE_C_DEFINED_glDrawElementsInstancedARB +#define GLEE_C_DEFINED_glDrawElementsInstancedARB + void __stdcall GLee_Lazy_glDrawElementsInstancedARB(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices, GLsizei primcount) {if (GLeeInit()) glDrawElementsInstancedARB(mode, count, type, indices, primcount);} + GLEEPFNGLDRAWELEMENTSINSTANCEDARBPROC GLeeFuncPtr_glDrawElementsInstancedARB=GLee_Lazy_glDrawElementsInstancedARB; +#endif +#endif + +/* GL_ARB_framebuffer_object */ + +#ifdef __GLEE_GL_ARB_framebuffer_object +#ifndef GLEE_C_DEFINED_glIsRenderbuffer +#define GLEE_C_DEFINED_glIsRenderbuffer + GLboolean __stdcall GLee_Lazy_glIsRenderbuffer(GLuint renderbuffer) {if (GLeeInit()) return glIsRenderbuffer(renderbuffer); return (GLboolean)0;} + GLEEPFNGLISRENDERBUFFERPROC GLeeFuncPtr_glIsRenderbuffer=GLee_Lazy_glIsRenderbuffer; +#endif +#ifndef GLEE_C_DEFINED_glBindRenderbuffer +#define GLEE_C_DEFINED_glBindRenderbuffer + void __stdcall GLee_Lazy_glBindRenderbuffer(GLenum target, GLuint renderbuffer) {if (GLeeInit()) glBindRenderbuffer(target, renderbuffer);} + GLEEPFNGLBINDRENDERBUFFERPROC GLeeFuncPtr_glBindRenderbuffer=GLee_Lazy_glBindRenderbuffer; +#endif +#ifndef GLEE_C_DEFINED_glDeleteRenderbuffers +#define GLEE_C_DEFINED_glDeleteRenderbuffers + void __stdcall GLee_Lazy_glDeleteRenderbuffers(GLsizei n, const GLuint * renderbuffers) {if (GLeeInit()) glDeleteRenderbuffers(n, renderbuffers);} + GLEEPFNGLDELETERENDERBUFFERSPROC GLeeFuncPtr_glDeleteRenderbuffers=GLee_Lazy_glDeleteRenderbuffers; +#endif +#ifndef GLEE_C_DEFINED_glGenRenderbuffers +#define GLEE_C_DEFINED_glGenRenderbuffers + void __stdcall GLee_Lazy_glGenRenderbuffers(GLsizei n, GLuint * renderbuffers) {if (GLeeInit()) glGenRenderbuffers(n, renderbuffers);} + GLEEPFNGLGENRENDERBUFFERSPROC GLeeFuncPtr_glGenRenderbuffers=GLee_Lazy_glGenRenderbuffers; +#endif +#ifndef GLEE_C_DEFINED_glRenderbufferStorage +#define GLEE_C_DEFINED_glRenderbufferStorage + void __stdcall GLee_Lazy_glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {if (GLeeInit()) glRenderbufferStorage(target, internalformat, width, height);} + GLEEPFNGLRENDERBUFFERSTORAGEPROC GLeeFuncPtr_glRenderbufferStorage=GLee_Lazy_glRenderbufferStorage; +#endif +#ifndef GLEE_C_DEFINED_glGetRenderbufferParameteriv +#define GLEE_C_DEFINED_glGetRenderbufferParameteriv + void __stdcall GLee_Lazy_glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetRenderbufferParameteriv(target, pname, params);} + GLEEPFNGLGETRENDERBUFFERPARAMETERIVPROC GLeeFuncPtr_glGetRenderbufferParameteriv=GLee_Lazy_glGetRenderbufferParameteriv; +#endif +#ifndef GLEE_C_DEFINED_glIsFramebuffer +#define GLEE_C_DEFINED_glIsFramebuffer + GLboolean __stdcall GLee_Lazy_glIsFramebuffer(GLuint framebuffer) {if (GLeeInit()) return glIsFramebuffer(framebuffer); return (GLboolean)0;} + GLEEPFNGLISFRAMEBUFFERPROC GLeeFuncPtr_glIsFramebuffer=GLee_Lazy_glIsFramebuffer; +#endif +#ifndef GLEE_C_DEFINED_glBindFramebuffer +#define GLEE_C_DEFINED_glBindFramebuffer + void __stdcall GLee_Lazy_glBindFramebuffer(GLenum target, GLuint framebuffer) {if (GLeeInit()) glBindFramebuffer(target, framebuffer);} + GLEEPFNGLBINDFRAMEBUFFERPROC GLeeFuncPtr_glBindFramebuffer=GLee_Lazy_glBindFramebuffer; +#endif +#ifndef GLEE_C_DEFINED_glDeleteFramebuffers +#define GLEE_C_DEFINED_glDeleteFramebuffers + void __stdcall GLee_Lazy_glDeleteFramebuffers(GLsizei n, const GLuint * framebuffers) {if (GLeeInit()) glDeleteFramebuffers(n, framebuffers);} + GLEEPFNGLDELETEFRAMEBUFFERSPROC GLeeFuncPtr_glDeleteFramebuffers=GLee_Lazy_glDeleteFramebuffers; +#endif +#ifndef GLEE_C_DEFINED_glGenFramebuffers +#define GLEE_C_DEFINED_glGenFramebuffers + void __stdcall GLee_Lazy_glGenFramebuffers(GLsizei n, GLuint * framebuffers) {if (GLeeInit()) glGenFramebuffers(n, framebuffers);} + GLEEPFNGLGENFRAMEBUFFERSPROC GLeeFuncPtr_glGenFramebuffers=GLee_Lazy_glGenFramebuffers; +#endif +#ifndef GLEE_C_DEFINED_glCheckFramebufferStatus +#define GLEE_C_DEFINED_glCheckFramebufferStatus + GLenum __stdcall GLee_Lazy_glCheckFramebufferStatus(GLenum target) {if (GLeeInit()) return glCheckFramebufferStatus(target); return (GLenum)0;} + GLEEPFNGLCHECKFRAMEBUFFERSTATUSPROC GLeeFuncPtr_glCheckFramebufferStatus=GLee_Lazy_glCheckFramebufferStatus; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferTexture1D +#define GLEE_C_DEFINED_glFramebufferTexture1D + void __stdcall GLee_Lazy_glFramebufferTexture1D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {if (GLeeInit()) glFramebufferTexture1D(target, attachment, textarget, texture, level);} + GLEEPFNGLFRAMEBUFFERTEXTURE1DPROC GLeeFuncPtr_glFramebufferTexture1D=GLee_Lazy_glFramebufferTexture1D; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferTexture2D +#define GLEE_C_DEFINED_glFramebufferTexture2D + void __stdcall GLee_Lazy_glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {if (GLeeInit()) glFramebufferTexture2D(target, attachment, textarget, texture, level);} + GLEEPFNGLFRAMEBUFFERTEXTURE2DPROC GLeeFuncPtr_glFramebufferTexture2D=GLee_Lazy_glFramebufferTexture2D; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferTexture3D +#define GLEE_C_DEFINED_glFramebufferTexture3D + void __stdcall GLee_Lazy_glFramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) {if (GLeeInit()) glFramebufferTexture3D(target, attachment, textarget, texture, level, zoffset);} + GLEEPFNGLFRAMEBUFFERTEXTURE3DPROC GLeeFuncPtr_glFramebufferTexture3D=GLee_Lazy_glFramebufferTexture3D; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferRenderbuffer +#define GLEE_C_DEFINED_glFramebufferRenderbuffer + void __stdcall GLee_Lazy_glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {if (GLeeInit()) glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);} + GLEEPFNGLFRAMEBUFFERRENDERBUFFERPROC GLeeFuncPtr_glFramebufferRenderbuffer=GLee_Lazy_glFramebufferRenderbuffer; +#endif +#ifndef GLEE_C_DEFINED_glGetFramebufferAttachmentParameteriv +#define GLEE_C_DEFINED_glGetFramebufferAttachmentParameteriv + void __stdcall GLee_Lazy_glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint * params) {if (GLeeInit()) glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);} + GLEEPFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC GLeeFuncPtr_glGetFramebufferAttachmentParameteriv=GLee_Lazy_glGetFramebufferAttachmentParameteriv; +#endif +#ifndef GLEE_C_DEFINED_glGenerateMipmap +#define GLEE_C_DEFINED_glGenerateMipmap + void __stdcall GLee_Lazy_glGenerateMipmap(GLenum target) {if (GLeeInit()) glGenerateMipmap(target);} + GLEEPFNGLGENERATEMIPMAPPROC GLeeFuncPtr_glGenerateMipmap=GLee_Lazy_glGenerateMipmap; +#endif +#ifndef GLEE_C_DEFINED_glBlitFramebuffer +#define GLEE_C_DEFINED_glBlitFramebuffer + void __stdcall GLee_Lazy_glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {if (GLeeInit()) glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);} + GLEEPFNGLBLITFRAMEBUFFERPROC GLeeFuncPtr_glBlitFramebuffer=GLee_Lazy_glBlitFramebuffer; +#endif +#ifndef GLEE_C_DEFINED_glRenderbufferStorageMultisample +#define GLEE_C_DEFINED_glRenderbufferStorageMultisample + void __stdcall GLee_Lazy_glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {if (GLeeInit()) glRenderbufferStorageMultisample(target, samples, internalformat, width, height);} + GLEEPFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC GLeeFuncPtr_glRenderbufferStorageMultisample=GLee_Lazy_glRenderbufferStorageMultisample; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferTextureLayer +#define GLEE_C_DEFINED_glFramebufferTextureLayer + void __stdcall GLee_Lazy_glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {if (GLeeInit()) glFramebufferTextureLayer(target, attachment, texture, level, layer);} + GLEEPFNGLFRAMEBUFFERTEXTURELAYERPROC GLeeFuncPtr_glFramebufferTextureLayer=GLee_Lazy_glFramebufferTextureLayer; +#endif +#endif + +/* GL_ARB_framebuffer_sRGB */ + +#ifdef __GLEE_GL_ARB_framebuffer_sRGB +#endif + +/* GL_ARB_geometry_shader4 */ + +#ifdef __GLEE_GL_ARB_geometry_shader4 +#ifndef GLEE_C_DEFINED_glProgramParameteriARB +#define GLEE_C_DEFINED_glProgramParameteriARB + void __stdcall GLee_Lazy_glProgramParameteriARB(GLuint program, GLenum pname, GLint value) {if (GLeeInit()) glProgramParameteriARB(program, pname, value);} + GLEEPFNGLPROGRAMPARAMETERIARBPROC GLeeFuncPtr_glProgramParameteriARB=GLee_Lazy_glProgramParameteriARB; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferTextureARB +#define GLEE_C_DEFINED_glFramebufferTextureARB + void __stdcall GLee_Lazy_glFramebufferTextureARB(GLenum target, GLenum attachment, GLuint texture, GLint level) {if (GLeeInit()) glFramebufferTextureARB(target, attachment, texture, level);} + GLEEPFNGLFRAMEBUFFERTEXTUREARBPROC GLeeFuncPtr_glFramebufferTextureARB=GLee_Lazy_glFramebufferTextureARB; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferTextureLayerARB +#define GLEE_C_DEFINED_glFramebufferTextureLayerARB + void __stdcall GLee_Lazy_glFramebufferTextureLayerARB(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {if (GLeeInit()) glFramebufferTextureLayerARB(target, attachment, texture, level, layer);} + GLEEPFNGLFRAMEBUFFERTEXTURELAYERARBPROC GLeeFuncPtr_glFramebufferTextureLayerARB=GLee_Lazy_glFramebufferTextureLayerARB; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferTextureFaceARB +#define GLEE_C_DEFINED_glFramebufferTextureFaceARB + void __stdcall GLee_Lazy_glFramebufferTextureFaceARB(GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face) {if (GLeeInit()) glFramebufferTextureFaceARB(target, attachment, texture, level, face);} + GLEEPFNGLFRAMEBUFFERTEXTUREFACEARBPROC GLeeFuncPtr_glFramebufferTextureFaceARB=GLee_Lazy_glFramebufferTextureFaceARB; +#endif +#endif + +/* GL_ARB_half_float_vertex */ + +#ifdef __GLEE_GL_ARB_half_float_vertex +#endif + +/* GL_ARB_instanced_arrays */ + +#ifdef __GLEE_GL_ARB_instanced_arrays +#ifndef GLEE_C_DEFINED_glVertexAttribDivisor +#define GLEE_C_DEFINED_glVertexAttribDivisor + void __stdcall GLee_Lazy_glVertexAttribDivisor(GLuint index, GLuint divisor) {if (GLeeInit()) glVertexAttribDivisor(index, divisor);} + GLEEPFNGLVERTEXATTRIBDIVISORPROC GLeeFuncPtr_glVertexAttribDivisor=GLee_Lazy_glVertexAttribDivisor; +#endif +#endif + +/* GL_ARB_map_buffer_range */ + +#ifdef __GLEE_GL_ARB_map_buffer_range +#ifndef GLEE_C_DEFINED_glMapBufferRange +#define GLEE_C_DEFINED_glMapBufferRange + void __stdcall GLee_Lazy_glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {if (GLeeInit()) glMapBufferRange(target, offset, length, access);} + GLEEPFNGLMAPBUFFERRANGEPROC GLeeFuncPtr_glMapBufferRange=GLee_Lazy_glMapBufferRange; +#endif +#ifndef GLEE_C_DEFINED_glFlushMappedBufferRange +#define GLEE_C_DEFINED_glFlushMappedBufferRange + void __stdcall GLee_Lazy_glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) {if (GLeeInit()) glFlushMappedBufferRange(target, offset, length);} + GLEEPFNGLFLUSHMAPPEDBUFFERRANGEPROC GLeeFuncPtr_glFlushMappedBufferRange=GLee_Lazy_glFlushMappedBufferRange; +#endif +#endif + +/* GL_ARB_texture_buffer_object */ + +#ifdef __GLEE_GL_ARB_texture_buffer_object +#ifndef GLEE_C_DEFINED_glTexBufferARB +#define GLEE_C_DEFINED_glTexBufferARB + void __stdcall GLee_Lazy_glTexBufferARB(GLenum target, GLenum internalformat, GLuint buffer) {if (GLeeInit()) glTexBufferARB(target, internalformat, buffer);} + GLEEPFNGLTEXBUFFERARBPROC GLeeFuncPtr_glTexBufferARB=GLee_Lazy_glTexBufferARB; +#endif +#endif + +/* GL_ARB_texture_compression_rgtc */ + +#ifdef __GLEE_GL_ARB_texture_compression_rgtc +#endif + +/* GL_ARB_texture_rg */ + +#ifdef __GLEE_GL_ARB_texture_rg +#endif + +/* GL_ARB_vertex_array_object */ + +#ifdef __GLEE_GL_ARB_vertex_array_object +#ifndef GLEE_C_DEFINED_glBindVertexArray +#define GLEE_C_DEFINED_glBindVertexArray + void __stdcall GLee_Lazy_glBindVertexArray(GLuint array) {if (GLeeInit()) glBindVertexArray(array);} + GLEEPFNGLBINDVERTEXARRAYPROC GLeeFuncPtr_glBindVertexArray=GLee_Lazy_glBindVertexArray; +#endif +#ifndef GLEE_C_DEFINED_glDeleteVertexArrays +#define GLEE_C_DEFINED_glDeleteVertexArrays + void __stdcall GLee_Lazy_glDeleteVertexArrays(GLsizei n, const GLuint * arrays) {if (GLeeInit()) glDeleteVertexArrays(n, arrays);} + GLEEPFNGLDELETEVERTEXARRAYSPROC GLeeFuncPtr_glDeleteVertexArrays=GLee_Lazy_glDeleteVertexArrays; +#endif +#ifndef GLEE_C_DEFINED_glGenVertexArrays +#define GLEE_C_DEFINED_glGenVertexArrays + void __stdcall GLee_Lazy_glGenVertexArrays(GLsizei n, GLuint * arrays) {if (GLeeInit()) glGenVertexArrays(n, arrays);} + GLEEPFNGLGENVERTEXARRAYSPROC GLeeFuncPtr_glGenVertexArrays=GLee_Lazy_glGenVertexArrays; +#endif +#ifndef GLEE_C_DEFINED_glIsVertexArray +#define GLEE_C_DEFINED_glIsVertexArray + GLboolean __stdcall GLee_Lazy_glIsVertexArray(GLuint array) {if (GLeeInit()) return glIsVertexArray(array); return (GLboolean)0;} + GLEEPFNGLISVERTEXARRAYPROC GLeeFuncPtr_glIsVertexArray=GLee_Lazy_glIsVertexArray; +#endif +#endif + +/* GL_EXT_abgr */ + +#ifdef __GLEE_GL_EXT_abgr +#endif + +/* GL_EXT_blend_color */ + +#ifdef __GLEE_GL_EXT_blend_color +#ifndef GLEE_C_DEFINED_glBlendColorEXT +#define GLEE_C_DEFINED_glBlendColorEXT + void __stdcall GLee_Lazy_glBlendColorEXT(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {if (GLeeInit()) glBlendColorEXT(red, green, blue, alpha);} + GLEEPFNGLBLENDCOLOREXTPROC GLeeFuncPtr_glBlendColorEXT=GLee_Lazy_glBlendColorEXT; +#endif +#endif + +/* GL_EXT_polygon_offset */ + +#ifdef __GLEE_GL_EXT_polygon_offset +#ifndef GLEE_C_DEFINED_glPolygonOffsetEXT +#define GLEE_C_DEFINED_glPolygonOffsetEXT + void __stdcall GLee_Lazy_glPolygonOffsetEXT(GLfloat factor, GLfloat bias) {if (GLeeInit()) glPolygonOffsetEXT(factor, bias);} + GLEEPFNGLPOLYGONOFFSETEXTPROC GLeeFuncPtr_glPolygonOffsetEXT=GLee_Lazy_glPolygonOffsetEXT; +#endif +#endif + +/* GL_EXT_texture */ + +#ifdef __GLEE_GL_EXT_texture +#endif + +/* GL_EXT_texture3D */ + +#ifdef __GLEE_GL_EXT_texture3D +#ifndef GLEE_C_DEFINED_glTexImage3DEXT +#define GLEE_C_DEFINED_glTexImage3DEXT + void __stdcall GLee_Lazy_glTexImage3DEXT(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glTexImage3DEXT(target, level, internalformat, width, height, depth, border, format, type, pixels);} + GLEEPFNGLTEXIMAGE3DEXTPROC GLeeFuncPtr_glTexImage3DEXT=GLee_Lazy_glTexImage3DEXT; +#endif +#ifndef GLEE_C_DEFINED_glTexSubImage3DEXT +#define GLEE_C_DEFINED_glTexSubImage3DEXT + void __stdcall GLee_Lazy_glTexSubImage3DEXT(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glTexSubImage3DEXT(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);} + GLEEPFNGLTEXSUBIMAGE3DEXTPROC GLeeFuncPtr_glTexSubImage3DEXT=GLee_Lazy_glTexSubImage3DEXT; +#endif +#endif + +/* GL_SGIS_texture_filter4 */ + +#ifdef __GLEE_GL_SGIS_texture_filter4 +#ifndef GLEE_C_DEFINED_glGetTexFilterFuncSGIS +#define GLEE_C_DEFINED_glGetTexFilterFuncSGIS + void __stdcall GLee_Lazy_glGetTexFilterFuncSGIS(GLenum target, GLenum filter, GLfloat * weights) {if (GLeeInit()) glGetTexFilterFuncSGIS(target, filter, weights);} + GLEEPFNGLGETTEXFILTERFUNCSGISPROC GLeeFuncPtr_glGetTexFilterFuncSGIS=GLee_Lazy_glGetTexFilterFuncSGIS; +#endif +#ifndef GLEE_C_DEFINED_glTexFilterFuncSGIS +#define GLEE_C_DEFINED_glTexFilterFuncSGIS + void __stdcall GLee_Lazy_glTexFilterFuncSGIS(GLenum target, GLenum filter, GLsizei n, const GLfloat * weights) {if (GLeeInit()) glTexFilterFuncSGIS(target, filter, n, weights);} + GLEEPFNGLTEXFILTERFUNCSGISPROC GLeeFuncPtr_glTexFilterFuncSGIS=GLee_Lazy_glTexFilterFuncSGIS; +#endif +#endif + +/* GL_EXT_subtexture */ + +#ifdef __GLEE_GL_EXT_subtexture +#ifndef GLEE_C_DEFINED_glTexSubImage1DEXT +#define GLEE_C_DEFINED_glTexSubImage1DEXT + void __stdcall GLee_Lazy_glTexSubImage1DEXT(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glTexSubImage1DEXT(target, level, xoffset, width, format, type, pixels);} + GLEEPFNGLTEXSUBIMAGE1DEXTPROC GLeeFuncPtr_glTexSubImage1DEXT=GLee_Lazy_glTexSubImage1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glTexSubImage2DEXT +#define GLEE_C_DEFINED_glTexSubImage2DEXT + void __stdcall GLee_Lazy_glTexSubImage2DEXT(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glTexSubImage2DEXT(target, level, xoffset, yoffset, width, height, format, type, pixels);} + GLEEPFNGLTEXSUBIMAGE2DEXTPROC GLeeFuncPtr_glTexSubImage2DEXT=GLee_Lazy_glTexSubImage2DEXT; +#endif +#endif + +/* GL_EXT_copy_texture */ + +#ifdef __GLEE_GL_EXT_copy_texture +#ifndef GLEE_C_DEFINED_glCopyTexImage1DEXT +#define GLEE_C_DEFINED_glCopyTexImage1DEXT + void __stdcall GLee_Lazy_glCopyTexImage1DEXT(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border) {if (GLeeInit()) glCopyTexImage1DEXT(target, level, internalformat, x, y, width, border);} + GLEEPFNGLCOPYTEXIMAGE1DEXTPROC GLeeFuncPtr_glCopyTexImage1DEXT=GLee_Lazy_glCopyTexImage1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyTexImage2DEXT +#define GLEE_C_DEFINED_glCopyTexImage2DEXT + void __stdcall GLee_Lazy_glCopyTexImage2DEXT(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {if (GLeeInit()) glCopyTexImage2DEXT(target, level, internalformat, x, y, width, height, border);} + GLEEPFNGLCOPYTEXIMAGE2DEXTPROC GLeeFuncPtr_glCopyTexImage2DEXT=GLee_Lazy_glCopyTexImage2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyTexSubImage1DEXT +#define GLEE_C_DEFINED_glCopyTexSubImage1DEXT + void __stdcall GLee_Lazy_glCopyTexSubImage1DEXT(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) {if (GLeeInit()) glCopyTexSubImage1DEXT(target, level, xoffset, x, y, width);} + GLEEPFNGLCOPYTEXSUBIMAGE1DEXTPROC GLeeFuncPtr_glCopyTexSubImage1DEXT=GLee_Lazy_glCopyTexSubImage1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyTexSubImage2DEXT +#define GLEE_C_DEFINED_glCopyTexSubImage2DEXT + void __stdcall GLee_Lazy_glCopyTexSubImage2DEXT(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {if (GLeeInit()) glCopyTexSubImage2DEXT(target, level, xoffset, yoffset, x, y, width, height);} + GLEEPFNGLCOPYTEXSUBIMAGE2DEXTPROC GLeeFuncPtr_glCopyTexSubImage2DEXT=GLee_Lazy_glCopyTexSubImage2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyTexSubImage3DEXT +#define GLEE_C_DEFINED_glCopyTexSubImage3DEXT + void __stdcall GLee_Lazy_glCopyTexSubImage3DEXT(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {if (GLeeInit()) glCopyTexSubImage3DEXT(target, level, xoffset, yoffset, zoffset, x, y, width, height);} + GLEEPFNGLCOPYTEXSUBIMAGE3DEXTPROC GLeeFuncPtr_glCopyTexSubImage3DEXT=GLee_Lazy_glCopyTexSubImage3DEXT; +#endif +#endif + +/* GL_EXT_histogram */ + +#ifdef __GLEE_GL_EXT_histogram +#ifndef GLEE_C_DEFINED_glGetHistogramEXT +#define GLEE_C_DEFINED_glGetHistogramEXT + void __stdcall GLee_Lazy_glGetHistogramEXT(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values) {if (GLeeInit()) glGetHistogramEXT(target, reset, format, type, values);} + GLEEPFNGLGETHISTOGRAMEXTPROC GLeeFuncPtr_glGetHistogramEXT=GLee_Lazy_glGetHistogramEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetHistogramParameterfvEXT +#define GLEE_C_DEFINED_glGetHistogramParameterfvEXT + void __stdcall GLee_Lazy_glGetHistogramParameterfvEXT(GLenum target, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetHistogramParameterfvEXT(target, pname, params);} + GLEEPFNGLGETHISTOGRAMPARAMETERFVEXTPROC GLeeFuncPtr_glGetHistogramParameterfvEXT=GLee_Lazy_glGetHistogramParameterfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetHistogramParameterivEXT +#define GLEE_C_DEFINED_glGetHistogramParameterivEXT + void __stdcall GLee_Lazy_glGetHistogramParameterivEXT(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetHistogramParameterivEXT(target, pname, params);} + GLEEPFNGLGETHISTOGRAMPARAMETERIVEXTPROC GLeeFuncPtr_glGetHistogramParameterivEXT=GLee_Lazy_glGetHistogramParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetMinmaxEXT +#define GLEE_C_DEFINED_glGetMinmaxEXT + void __stdcall GLee_Lazy_glGetMinmaxEXT(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values) {if (GLeeInit()) glGetMinmaxEXT(target, reset, format, type, values);} + GLEEPFNGLGETMINMAXEXTPROC GLeeFuncPtr_glGetMinmaxEXT=GLee_Lazy_glGetMinmaxEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetMinmaxParameterfvEXT +#define GLEE_C_DEFINED_glGetMinmaxParameterfvEXT + void __stdcall GLee_Lazy_glGetMinmaxParameterfvEXT(GLenum target, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetMinmaxParameterfvEXT(target, pname, params);} + GLEEPFNGLGETMINMAXPARAMETERFVEXTPROC GLeeFuncPtr_glGetMinmaxParameterfvEXT=GLee_Lazy_glGetMinmaxParameterfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetMinmaxParameterivEXT +#define GLEE_C_DEFINED_glGetMinmaxParameterivEXT + void __stdcall GLee_Lazy_glGetMinmaxParameterivEXT(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetMinmaxParameterivEXT(target, pname, params);} + GLEEPFNGLGETMINMAXPARAMETERIVEXTPROC GLeeFuncPtr_glGetMinmaxParameterivEXT=GLee_Lazy_glGetMinmaxParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glHistogramEXT +#define GLEE_C_DEFINED_glHistogramEXT + void __stdcall GLee_Lazy_glHistogramEXT(GLenum target, GLsizei width, GLenum internalformat, GLboolean sink) {if (GLeeInit()) glHistogramEXT(target, width, internalformat, sink);} + GLEEPFNGLHISTOGRAMEXTPROC GLeeFuncPtr_glHistogramEXT=GLee_Lazy_glHistogramEXT; +#endif +#ifndef GLEE_C_DEFINED_glMinmaxEXT +#define GLEE_C_DEFINED_glMinmaxEXT + void __stdcall GLee_Lazy_glMinmaxEXT(GLenum target, GLenum internalformat, GLboolean sink) {if (GLeeInit()) glMinmaxEXT(target, internalformat, sink);} + GLEEPFNGLMINMAXEXTPROC GLeeFuncPtr_glMinmaxEXT=GLee_Lazy_glMinmaxEXT; +#endif +#ifndef GLEE_C_DEFINED_glResetHistogramEXT +#define GLEE_C_DEFINED_glResetHistogramEXT + void __stdcall GLee_Lazy_glResetHistogramEXT(GLenum target) {if (GLeeInit()) glResetHistogramEXT(target);} + GLEEPFNGLRESETHISTOGRAMEXTPROC GLeeFuncPtr_glResetHistogramEXT=GLee_Lazy_glResetHistogramEXT; +#endif +#ifndef GLEE_C_DEFINED_glResetMinmaxEXT +#define GLEE_C_DEFINED_glResetMinmaxEXT + void __stdcall GLee_Lazy_glResetMinmaxEXT(GLenum target) {if (GLeeInit()) glResetMinmaxEXT(target);} + GLEEPFNGLRESETMINMAXEXTPROC GLeeFuncPtr_glResetMinmaxEXT=GLee_Lazy_glResetMinmaxEXT; +#endif +#endif + +/* GL_EXT_convolution */ + +#ifdef __GLEE_GL_EXT_convolution +#ifndef GLEE_C_DEFINED_glConvolutionFilter1DEXT +#define GLEE_C_DEFINED_glConvolutionFilter1DEXT + void __stdcall GLee_Lazy_glConvolutionFilter1DEXT(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * image) {if (GLeeInit()) glConvolutionFilter1DEXT(target, internalformat, width, format, type, image);} + GLEEPFNGLCONVOLUTIONFILTER1DEXTPROC GLeeFuncPtr_glConvolutionFilter1DEXT=GLee_Lazy_glConvolutionFilter1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glConvolutionFilter2DEXT +#define GLEE_C_DEFINED_glConvolutionFilter2DEXT + void __stdcall GLee_Lazy_glConvolutionFilter2DEXT(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * image) {if (GLeeInit()) glConvolutionFilter2DEXT(target, internalformat, width, height, format, type, image);} + GLEEPFNGLCONVOLUTIONFILTER2DEXTPROC GLeeFuncPtr_glConvolutionFilter2DEXT=GLee_Lazy_glConvolutionFilter2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glConvolutionParameterfEXT +#define GLEE_C_DEFINED_glConvolutionParameterfEXT + void __stdcall GLee_Lazy_glConvolutionParameterfEXT(GLenum target, GLenum pname, GLfloat params) {if (GLeeInit()) glConvolutionParameterfEXT(target, pname, params);} + GLEEPFNGLCONVOLUTIONPARAMETERFEXTPROC GLeeFuncPtr_glConvolutionParameterfEXT=GLee_Lazy_glConvolutionParameterfEXT; +#endif +#ifndef GLEE_C_DEFINED_glConvolutionParameterfvEXT +#define GLEE_C_DEFINED_glConvolutionParameterfvEXT + void __stdcall GLee_Lazy_glConvolutionParameterfvEXT(GLenum target, GLenum pname, const GLfloat * params) {if (GLeeInit()) glConvolutionParameterfvEXT(target, pname, params);} + GLEEPFNGLCONVOLUTIONPARAMETERFVEXTPROC GLeeFuncPtr_glConvolutionParameterfvEXT=GLee_Lazy_glConvolutionParameterfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glConvolutionParameteriEXT +#define GLEE_C_DEFINED_glConvolutionParameteriEXT + void __stdcall GLee_Lazy_glConvolutionParameteriEXT(GLenum target, GLenum pname, GLint params) {if (GLeeInit()) glConvolutionParameteriEXT(target, pname, params);} + GLEEPFNGLCONVOLUTIONPARAMETERIEXTPROC GLeeFuncPtr_glConvolutionParameteriEXT=GLee_Lazy_glConvolutionParameteriEXT; +#endif +#ifndef GLEE_C_DEFINED_glConvolutionParameterivEXT +#define GLEE_C_DEFINED_glConvolutionParameterivEXT + void __stdcall GLee_Lazy_glConvolutionParameterivEXT(GLenum target, GLenum pname, const GLint * params) {if (GLeeInit()) glConvolutionParameterivEXT(target, pname, params);} + GLEEPFNGLCONVOLUTIONPARAMETERIVEXTPROC GLeeFuncPtr_glConvolutionParameterivEXT=GLee_Lazy_glConvolutionParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyConvolutionFilter1DEXT +#define GLEE_C_DEFINED_glCopyConvolutionFilter1DEXT + void __stdcall GLee_Lazy_glCopyConvolutionFilter1DEXT(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) {if (GLeeInit()) glCopyConvolutionFilter1DEXT(target, internalformat, x, y, width);} + GLEEPFNGLCOPYCONVOLUTIONFILTER1DEXTPROC GLeeFuncPtr_glCopyConvolutionFilter1DEXT=GLee_Lazy_glCopyConvolutionFilter1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyConvolutionFilter2DEXT +#define GLEE_C_DEFINED_glCopyConvolutionFilter2DEXT + void __stdcall GLee_Lazy_glCopyConvolutionFilter2DEXT(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height) {if (GLeeInit()) glCopyConvolutionFilter2DEXT(target, internalformat, x, y, width, height);} + GLEEPFNGLCOPYCONVOLUTIONFILTER2DEXTPROC GLeeFuncPtr_glCopyConvolutionFilter2DEXT=GLee_Lazy_glCopyConvolutionFilter2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetConvolutionFilterEXT +#define GLEE_C_DEFINED_glGetConvolutionFilterEXT + void __stdcall GLee_Lazy_glGetConvolutionFilterEXT(GLenum target, GLenum format, GLenum type, GLvoid * image) {if (GLeeInit()) glGetConvolutionFilterEXT(target, format, type, image);} + GLEEPFNGLGETCONVOLUTIONFILTEREXTPROC GLeeFuncPtr_glGetConvolutionFilterEXT=GLee_Lazy_glGetConvolutionFilterEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetConvolutionParameterfvEXT +#define GLEE_C_DEFINED_glGetConvolutionParameterfvEXT + void __stdcall GLee_Lazy_glGetConvolutionParameterfvEXT(GLenum target, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetConvolutionParameterfvEXT(target, pname, params);} + GLEEPFNGLGETCONVOLUTIONPARAMETERFVEXTPROC GLeeFuncPtr_glGetConvolutionParameterfvEXT=GLee_Lazy_glGetConvolutionParameterfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetConvolutionParameterivEXT +#define GLEE_C_DEFINED_glGetConvolutionParameterivEXT + void __stdcall GLee_Lazy_glGetConvolutionParameterivEXT(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetConvolutionParameterivEXT(target, pname, params);} + GLEEPFNGLGETCONVOLUTIONPARAMETERIVEXTPROC GLeeFuncPtr_glGetConvolutionParameterivEXT=GLee_Lazy_glGetConvolutionParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetSeparableFilterEXT +#define GLEE_C_DEFINED_glGetSeparableFilterEXT + void __stdcall GLee_Lazy_glGetSeparableFilterEXT(GLenum target, GLenum format, GLenum type, GLvoid * row, GLvoid * column, GLvoid * span) {if (GLeeInit()) glGetSeparableFilterEXT(target, format, type, row, column, span);} + GLEEPFNGLGETSEPARABLEFILTEREXTPROC GLeeFuncPtr_glGetSeparableFilterEXT=GLee_Lazy_glGetSeparableFilterEXT; +#endif +#ifndef GLEE_C_DEFINED_glSeparableFilter2DEXT +#define GLEE_C_DEFINED_glSeparableFilter2DEXT + void __stdcall GLee_Lazy_glSeparableFilter2DEXT(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * row, const GLvoid * column) {if (GLeeInit()) glSeparableFilter2DEXT(target, internalformat, width, height, format, type, row, column);} + GLEEPFNGLSEPARABLEFILTER2DEXTPROC GLeeFuncPtr_glSeparableFilter2DEXT=GLee_Lazy_glSeparableFilter2DEXT; +#endif +#endif + +/* GL_SGI_color_matrix */ + +#ifdef __GLEE_GL_SGI_color_matrix +#endif + +/* GL_SGI_color_table */ + +#ifdef __GLEE_GL_SGI_color_table +#ifndef GLEE_C_DEFINED_glColorTableSGI +#define GLEE_C_DEFINED_glColorTableSGI + void __stdcall GLee_Lazy_glColorTableSGI(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * table) {if (GLeeInit()) glColorTableSGI(target, internalformat, width, format, type, table);} + GLEEPFNGLCOLORTABLESGIPROC GLeeFuncPtr_glColorTableSGI=GLee_Lazy_glColorTableSGI; +#endif +#ifndef GLEE_C_DEFINED_glColorTableParameterfvSGI +#define GLEE_C_DEFINED_glColorTableParameterfvSGI + void __stdcall GLee_Lazy_glColorTableParameterfvSGI(GLenum target, GLenum pname, const GLfloat * params) {if (GLeeInit()) glColorTableParameterfvSGI(target, pname, params);} + GLEEPFNGLCOLORTABLEPARAMETERFVSGIPROC GLeeFuncPtr_glColorTableParameterfvSGI=GLee_Lazy_glColorTableParameterfvSGI; +#endif +#ifndef GLEE_C_DEFINED_glColorTableParameterivSGI +#define GLEE_C_DEFINED_glColorTableParameterivSGI + void __stdcall GLee_Lazy_glColorTableParameterivSGI(GLenum target, GLenum pname, const GLint * params) {if (GLeeInit()) glColorTableParameterivSGI(target, pname, params);} + GLEEPFNGLCOLORTABLEPARAMETERIVSGIPROC GLeeFuncPtr_glColorTableParameterivSGI=GLee_Lazy_glColorTableParameterivSGI; +#endif +#ifndef GLEE_C_DEFINED_glCopyColorTableSGI +#define GLEE_C_DEFINED_glCopyColorTableSGI + void __stdcall GLee_Lazy_glCopyColorTableSGI(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) {if (GLeeInit()) glCopyColorTableSGI(target, internalformat, x, y, width);} + GLEEPFNGLCOPYCOLORTABLESGIPROC GLeeFuncPtr_glCopyColorTableSGI=GLee_Lazy_glCopyColorTableSGI; +#endif +#ifndef GLEE_C_DEFINED_glGetColorTableSGI +#define GLEE_C_DEFINED_glGetColorTableSGI + void __stdcall GLee_Lazy_glGetColorTableSGI(GLenum target, GLenum format, GLenum type, GLvoid * table) {if (GLeeInit()) glGetColorTableSGI(target, format, type, table);} + GLEEPFNGLGETCOLORTABLESGIPROC GLeeFuncPtr_glGetColorTableSGI=GLee_Lazy_glGetColorTableSGI; +#endif +#ifndef GLEE_C_DEFINED_glGetColorTableParameterfvSGI +#define GLEE_C_DEFINED_glGetColorTableParameterfvSGI + void __stdcall GLee_Lazy_glGetColorTableParameterfvSGI(GLenum target, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetColorTableParameterfvSGI(target, pname, params);} + GLEEPFNGLGETCOLORTABLEPARAMETERFVSGIPROC GLeeFuncPtr_glGetColorTableParameterfvSGI=GLee_Lazy_glGetColorTableParameterfvSGI; +#endif +#ifndef GLEE_C_DEFINED_glGetColorTableParameterivSGI +#define GLEE_C_DEFINED_glGetColorTableParameterivSGI + void __stdcall GLee_Lazy_glGetColorTableParameterivSGI(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetColorTableParameterivSGI(target, pname, params);} + GLEEPFNGLGETCOLORTABLEPARAMETERIVSGIPROC GLeeFuncPtr_glGetColorTableParameterivSGI=GLee_Lazy_glGetColorTableParameterivSGI; +#endif +#endif + +/* GL_SGIS_pixel_texture */ + +#ifdef __GLEE_GL_SGIS_pixel_texture +#ifndef GLEE_C_DEFINED_glPixelTexGenParameteriSGIS +#define GLEE_C_DEFINED_glPixelTexGenParameteriSGIS + void __stdcall GLee_Lazy_glPixelTexGenParameteriSGIS(GLenum pname, GLint param) {if (GLeeInit()) glPixelTexGenParameteriSGIS(pname, param);} + GLEEPFNGLPIXELTEXGENPARAMETERISGISPROC GLeeFuncPtr_glPixelTexGenParameteriSGIS=GLee_Lazy_glPixelTexGenParameteriSGIS; +#endif +#ifndef GLEE_C_DEFINED_glPixelTexGenParameterivSGIS +#define GLEE_C_DEFINED_glPixelTexGenParameterivSGIS + void __stdcall GLee_Lazy_glPixelTexGenParameterivSGIS(GLenum pname, const GLint * params) {if (GLeeInit()) glPixelTexGenParameterivSGIS(pname, params);} + GLEEPFNGLPIXELTEXGENPARAMETERIVSGISPROC GLeeFuncPtr_glPixelTexGenParameterivSGIS=GLee_Lazy_glPixelTexGenParameterivSGIS; +#endif +#ifndef GLEE_C_DEFINED_glPixelTexGenParameterfSGIS +#define GLEE_C_DEFINED_glPixelTexGenParameterfSGIS + void __stdcall GLee_Lazy_glPixelTexGenParameterfSGIS(GLenum pname, GLfloat param) {if (GLeeInit()) glPixelTexGenParameterfSGIS(pname, param);} + GLEEPFNGLPIXELTEXGENPARAMETERFSGISPROC GLeeFuncPtr_glPixelTexGenParameterfSGIS=GLee_Lazy_glPixelTexGenParameterfSGIS; +#endif +#ifndef GLEE_C_DEFINED_glPixelTexGenParameterfvSGIS +#define GLEE_C_DEFINED_glPixelTexGenParameterfvSGIS + void __stdcall GLee_Lazy_glPixelTexGenParameterfvSGIS(GLenum pname, const GLfloat * params) {if (GLeeInit()) glPixelTexGenParameterfvSGIS(pname, params);} + GLEEPFNGLPIXELTEXGENPARAMETERFVSGISPROC GLeeFuncPtr_glPixelTexGenParameterfvSGIS=GLee_Lazy_glPixelTexGenParameterfvSGIS; +#endif +#ifndef GLEE_C_DEFINED_glGetPixelTexGenParameterivSGIS +#define GLEE_C_DEFINED_glGetPixelTexGenParameterivSGIS + void __stdcall GLee_Lazy_glGetPixelTexGenParameterivSGIS(GLenum pname, GLint * params) {if (GLeeInit()) glGetPixelTexGenParameterivSGIS(pname, params);} + GLEEPFNGLGETPIXELTEXGENPARAMETERIVSGISPROC GLeeFuncPtr_glGetPixelTexGenParameterivSGIS=GLee_Lazy_glGetPixelTexGenParameterivSGIS; +#endif +#ifndef GLEE_C_DEFINED_glGetPixelTexGenParameterfvSGIS +#define GLEE_C_DEFINED_glGetPixelTexGenParameterfvSGIS + void __stdcall GLee_Lazy_glGetPixelTexGenParameterfvSGIS(GLenum pname, GLfloat * params) {if (GLeeInit()) glGetPixelTexGenParameterfvSGIS(pname, params);} + GLEEPFNGLGETPIXELTEXGENPARAMETERFVSGISPROC GLeeFuncPtr_glGetPixelTexGenParameterfvSGIS=GLee_Lazy_glGetPixelTexGenParameterfvSGIS; +#endif +#endif + +/* GL_SGIX_pixel_texture */ + +#ifdef __GLEE_GL_SGIX_pixel_texture +#ifndef GLEE_C_DEFINED_glPixelTexGenSGIX +#define GLEE_C_DEFINED_glPixelTexGenSGIX + void __stdcall GLee_Lazy_glPixelTexGenSGIX(GLenum mode) {if (GLeeInit()) glPixelTexGenSGIX(mode);} + GLEEPFNGLPIXELTEXGENSGIXPROC GLeeFuncPtr_glPixelTexGenSGIX=GLee_Lazy_glPixelTexGenSGIX; +#endif +#endif + +/* GL_SGIS_texture4D */ + +#ifdef __GLEE_GL_SGIS_texture4D +#ifndef GLEE_C_DEFINED_glTexImage4DSGIS +#define GLEE_C_DEFINED_glTexImage4DSGIS + void __stdcall GLee_Lazy_glTexImage4DSGIS(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glTexImage4DSGIS(target, level, internalformat, width, height, depth, size4d, border, format, type, pixels);} + GLEEPFNGLTEXIMAGE4DSGISPROC GLeeFuncPtr_glTexImage4DSGIS=GLee_Lazy_glTexImage4DSGIS; +#endif +#ifndef GLEE_C_DEFINED_glTexSubImage4DSGIS +#define GLEE_C_DEFINED_glTexSubImage4DSGIS + void __stdcall GLee_Lazy_glTexSubImage4DSGIS(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glTexSubImage4DSGIS(target, level, xoffset, yoffset, zoffset, woffset, width, height, depth, size4d, format, type, pixels);} + GLEEPFNGLTEXSUBIMAGE4DSGISPROC GLeeFuncPtr_glTexSubImage4DSGIS=GLee_Lazy_glTexSubImage4DSGIS; +#endif +#endif + +/* GL_SGI_texture_color_table */ + +#ifdef __GLEE_GL_SGI_texture_color_table +#endif + +/* GL_EXT_cmyka */ + +#ifdef __GLEE_GL_EXT_cmyka +#endif + +/* GL_EXT_texture_object */ + +#ifdef __GLEE_GL_EXT_texture_object +#ifndef GLEE_C_DEFINED_glAreTexturesResidentEXT +#define GLEE_C_DEFINED_glAreTexturesResidentEXT + GLboolean __stdcall GLee_Lazy_glAreTexturesResidentEXT(GLsizei n, const GLuint * textures, GLboolean * residences) {if (GLeeInit()) return glAreTexturesResidentEXT(n, textures, residences); return (GLboolean)0;} + GLEEPFNGLARETEXTURESRESIDENTEXTPROC GLeeFuncPtr_glAreTexturesResidentEXT=GLee_Lazy_glAreTexturesResidentEXT; +#endif +#ifndef GLEE_C_DEFINED_glBindTextureEXT +#define GLEE_C_DEFINED_glBindTextureEXT + void __stdcall GLee_Lazy_glBindTextureEXT(GLenum target, GLuint texture) {if (GLeeInit()) glBindTextureEXT(target, texture);} + GLEEPFNGLBINDTEXTUREEXTPROC GLeeFuncPtr_glBindTextureEXT=GLee_Lazy_glBindTextureEXT; +#endif +#ifndef GLEE_C_DEFINED_glDeleteTexturesEXT +#define GLEE_C_DEFINED_glDeleteTexturesEXT + void __stdcall GLee_Lazy_glDeleteTexturesEXT(GLsizei n, const GLuint * textures) {if (GLeeInit()) glDeleteTexturesEXT(n, textures);} + GLEEPFNGLDELETETEXTURESEXTPROC GLeeFuncPtr_glDeleteTexturesEXT=GLee_Lazy_glDeleteTexturesEXT; +#endif +#ifndef GLEE_C_DEFINED_glGenTexturesEXT +#define GLEE_C_DEFINED_glGenTexturesEXT + void __stdcall GLee_Lazy_glGenTexturesEXT(GLsizei n, GLuint * textures) {if (GLeeInit()) glGenTexturesEXT(n, textures);} + GLEEPFNGLGENTEXTURESEXTPROC GLeeFuncPtr_glGenTexturesEXT=GLee_Lazy_glGenTexturesEXT; +#endif +#ifndef GLEE_C_DEFINED_glIsTextureEXT +#define GLEE_C_DEFINED_glIsTextureEXT + GLboolean __stdcall GLee_Lazy_glIsTextureEXT(GLuint texture) {if (GLeeInit()) return glIsTextureEXT(texture); return (GLboolean)0;} + GLEEPFNGLISTEXTUREEXTPROC GLeeFuncPtr_glIsTextureEXT=GLee_Lazy_glIsTextureEXT; +#endif +#ifndef GLEE_C_DEFINED_glPrioritizeTexturesEXT +#define GLEE_C_DEFINED_glPrioritizeTexturesEXT + void __stdcall GLee_Lazy_glPrioritizeTexturesEXT(GLsizei n, const GLuint * textures, const GLclampf * priorities) {if (GLeeInit()) glPrioritizeTexturesEXT(n, textures, priorities);} + GLEEPFNGLPRIORITIZETEXTURESEXTPROC GLeeFuncPtr_glPrioritizeTexturesEXT=GLee_Lazy_glPrioritizeTexturesEXT; +#endif +#endif + +/* GL_SGIS_detail_texture */ + +#ifdef __GLEE_GL_SGIS_detail_texture +#ifndef GLEE_C_DEFINED_glDetailTexFuncSGIS +#define GLEE_C_DEFINED_glDetailTexFuncSGIS + void __stdcall GLee_Lazy_glDetailTexFuncSGIS(GLenum target, GLsizei n, const GLfloat * points) {if (GLeeInit()) glDetailTexFuncSGIS(target, n, points);} + GLEEPFNGLDETAILTEXFUNCSGISPROC GLeeFuncPtr_glDetailTexFuncSGIS=GLee_Lazy_glDetailTexFuncSGIS; +#endif +#ifndef GLEE_C_DEFINED_glGetDetailTexFuncSGIS +#define GLEE_C_DEFINED_glGetDetailTexFuncSGIS + void __stdcall GLee_Lazy_glGetDetailTexFuncSGIS(GLenum target, GLfloat * points) {if (GLeeInit()) glGetDetailTexFuncSGIS(target, points);} + GLEEPFNGLGETDETAILTEXFUNCSGISPROC GLeeFuncPtr_glGetDetailTexFuncSGIS=GLee_Lazy_glGetDetailTexFuncSGIS; +#endif +#endif + +/* GL_SGIS_sharpen_texture */ + +#ifdef __GLEE_GL_SGIS_sharpen_texture +#ifndef GLEE_C_DEFINED_glSharpenTexFuncSGIS +#define GLEE_C_DEFINED_glSharpenTexFuncSGIS + void __stdcall GLee_Lazy_glSharpenTexFuncSGIS(GLenum target, GLsizei n, const GLfloat * points) {if (GLeeInit()) glSharpenTexFuncSGIS(target, n, points);} + GLEEPFNGLSHARPENTEXFUNCSGISPROC GLeeFuncPtr_glSharpenTexFuncSGIS=GLee_Lazy_glSharpenTexFuncSGIS; +#endif +#ifndef GLEE_C_DEFINED_glGetSharpenTexFuncSGIS +#define GLEE_C_DEFINED_glGetSharpenTexFuncSGIS + void __stdcall GLee_Lazy_glGetSharpenTexFuncSGIS(GLenum target, GLfloat * points) {if (GLeeInit()) glGetSharpenTexFuncSGIS(target, points);} + GLEEPFNGLGETSHARPENTEXFUNCSGISPROC GLeeFuncPtr_glGetSharpenTexFuncSGIS=GLee_Lazy_glGetSharpenTexFuncSGIS; +#endif +#endif + +/* GL_EXT_packed_pixels */ + +#ifdef __GLEE_GL_EXT_packed_pixels +#endif + +/* GL_SGIS_texture_lod */ + +#ifdef __GLEE_GL_SGIS_texture_lod +#endif + +/* GL_SGIS_multisample */ + +#ifdef __GLEE_GL_SGIS_multisample +#ifndef GLEE_C_DEFINED_glSampleMaskSGIS +#define GLEE_C_DEFINED_glSampleMaskSGIS + void __stdcall GLee_Lazy_glSampleMaskSGIS(GLclampf value, GLboolean invert) {if (GLeeInit()) glSampleMaskSGIS(value, invert);} + GLEEPFNGLSAMPLEMASKSGISPROC GLeeFuncPtr_glSampleMaskSGIS=GLee_Lazy_glSampleMaskSGIS; +#endif +#ifndef GLEE_C_DEFINED_glSamplePatternSGIS +#define GLEE_C_DEFINED_glSamplePatternSGIS + void __stdcall GLee_Lazy_glSamplePatternSGIS(GLenum pattern) {if (GLeeInit()) glSamplePatternSGIS(pattern);} + GLEEPFNGLSAMPLEPATTERNSGISPROC GLeeFuncPtr_glSamplePatternSGIS=GLee_Lazy_glSamplePatternSGIS; +#endif +#endif + +/* GL_EXT_rescale_normal */ + +#ifdef __GLEE_GL_EXT_rescale_normal +#endif + +/* GL_EXT_vertex_array */ + +#ifdef __GLEE_GL_EXT_vertex_array +#ifndef GLEE_C_DEFINED_glArrayElementEXT +#define GLEE_C_DEFINED_glArrayElementEXT + void __stdcall GLee_Lazy_glArrayElementEXT(GLint i) {if (GLeeInit()) glArrayElementEXT(i);} + GLEEPFNGLARRAYELEMENTEXTPROC GLeeFuncPtr_glArrayElementEXT=GLee_Lazy_glArrayElementEXT; +#endif +#ifndef GLEE_C_DEFINED_glColorPointerEXT +#define GLEE_C_DEFINED_glColorPointerEXT + void __stdcall GLee_Lazy_glColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer) {if (GLeeInit()) glColorPointerEXT(size, type, stride, count, pointer);} + GLEEPFNGLCOLORPOINTEREXTPROC GLeeFuncPtr_glColorPointerEXT=GLee_Lazy_glColorPointerEXT; +#endif +#ifndef GLEE_C_DEFINED_glDrawArraysEXT +#define GLEE_C_DEFINED_glDrawArraysEXT + void __stdcall GLee_Lazy_glDrawArraysEXT(GLenum mode, GLint first, GLsizei count) {if (GLeeInit()) glDrawArraysEXT(mode, first, count);} + GLEEPFNGLDRAWARRAYSEXTPROC GLeeFuncPtr_glDrawArraysEXT=GLee_Lazy_glDrawArraysEXT; +#endif +#ifndef GLEE_C_DEFINED_glEdgeFlagPointerEXT +#define GLEE_C_DEFINED_glEdgeFlagPointerEXT + void __stdcall GLee_Lazy_glEdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean * pointer) {if (GLeeInit()) glEdgeFlagPointerEXT(stride, count, pointer);} + GLEEPFNGLEDGEFLAGPOINTEREXTPROC GLeeFuncPtr_glEdgeFlagPointerEXT=GLee_Lazy_glEdgeFlagPointerEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetPointervEXT +#define GLEE_C_DEFINED_glGetPointervEXT + void __stdcall GLee_Lazy_glGetPointervEXT(GLenum pname, GLvoid* * params) {if (GLeeInit()) glGetPointervEXT(pname, params);} + GLEEPFNGLGETPOINTERVEXTPROC GLeeFuncPtr_glGetPointervEXT=GLee_Lazy_glGetPointervEXT; +#endif +#ifndef GLEE_C_DEFINED_glIndexPointerEXT +#define GLEE_C_DEFINED_glIndexPointerEXT + void __stdcall GLee_Lazy_glIndexPointerEXT(GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer) {if (GLeeInit()) glIndexPointerEXT(type, stride, count, pointer);} + GLEEPFNGLINDEXPOINTEREXTPROC GLeeFuncPtr_glIndexPointerEXT=GLee_Lazy_glIndexPointerEXT; +#endif +#ifndef GLEE_C_DEFINED_glNormalPointerEXT +#define GLEE_C_DEFINED_glNormalPointerEXT + void __stdcall GLee_Lazy_glNormalPointerEXT(GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer) {if (GLeeInit()) glNormalPointerEXT(type, stride, count, pointer);} + GLEEPFNGLNORMALPOINTEREXTPROC GLeeFuncPtr_glNormalPointerEXT=GLee_Lazy_glNormalPointerEXT; +#endif +#ifndef GLEE_C_DEFINED_glTexCoordPointerEXT +#define GLEE_C_DEFINED_glTexCoordPointerEXT + void __stdcall GLee_Lazy_glTexCoordPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer) {if (GLeeInit()) glTexCoordPointerEXT(size, type, stride, count, pointer);} + GLEEPFNGLTEXCOORDPOINTEREXTPROC GLeeFuncPtr_glTexCoordPointerEXT=GLee_Lazy_glTexCoordPointerEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexPointerEXT +#define GLEE_C_DEFINED_glVertexPointerEXT + void __stdcall GLee_Lazy_glVertexPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer) {if (GLeeInit()) glVertexPointerEXT(size, type, stride, count, pointer);} + GLEEPFNGLVERTEXPOINTEREXTPROC GLeeFuncPtr_glVertexPointerEXT=GLee_Lazy_glVertexPointerEXT; +#endif +#endif + +/* GL_EXT_misc_attribute */ + +#ifdef __GLEE_GL_EXT_misc_attribute +#endif + +/* GL_SGIS_generate_mipmap */ + +#ifdef __GLEE_GL_SGIS_generate_mipmap +#endif + +/* GL_SGIX_clipmap */ + +#ifdef __GLEE_GL_SGIX_clipmap +#endif + +/* GL_SGIX_shadow */ + +#ifdef __GLEE_GL_SGIX_shadow +#endif + +/* GL_SGIS_texture_edge_clamp */ + +#ifdef __GLEE_GL_SGIS_texture_edge_clamp +#endif + +/* GL_SGIS_texture_border_clamp */ + +#ifdef __GLEE_GL_SGIS_texture_border_clamp +#endif + +/* GL_EXT_blend_minmax */ + +#ifdef __GLEE_GL_EXT_blend_minmax +#ifndef GLEE_C_DEFINED_glBlendEquationEXT +#define GLEE_C_DEFINED_glBlendEquationEXT + void __stdcall GLee_Lazy_glBlendEquationEXT(GLenum mode) {if (GLeeInit()) glBlendEquationEXT(mode);} + GLEEPFNGLBLENDEQUATIONEXTPROC GLeeFuncPtr_glBlendEquationEXT=GLee_Lazy_glBlendEquationEXT; +#endif +#endif + +/* GL_EXT_blend_subtract */ + +#ifdef __GLEE_GL_EXT_blend_subtract +#endif + +/* GL_EXT_blend_logic_op */ + +#ifdef __GLEE_GL_EXT_blend_logic_op +#endif + +/* GL_SGIX_interlace */ + +#ifdef __GLEE_GL_SGIX_interlace +#endif + +/* GL_SGIX_pixel_tiles */ + +#ifdef __GLEE_GL_SGIX_pixel_tiles +#endif + +/* GL_SGIS_texture_select */ + +#ifdef __GLEE_GL_SGIS_texture_select +#endif + +/* GL_SGIX_sprite */ + +#ifdef __GLEE_GL_SGIX_sprite +#ifndef GLEE_C_DEFINED_glSpriteParameterfSGIX +#define GLEE_C_DEFINED_glSpriteParameterfSGIX + void __stdcall GLee_Lazy_glSpriteParameterfSGIX(GLenum pname, GLfloat param) {if (GLeeInit()) glSpriteParameterfSGIX(pname, param);} + GLEEPFNGLSPRITEPARAMETERFSGIXPROC GLeeFuncPtr_glSpriteParameterfSGIX=GLee_Lazy_glSpriteParameterfSGIX; +#endif +#ifndef GLEE_C_DEFINED_glSpriteParameterfvSGIX +#define GLEE_C_DEFINED_glSpriteParameterfvSGIX + void __stdcall GLee_Lazy_glSpriteParameterfvSGIX(GLenum pname, const GLfloat * params) {if (GLeeInit()) glSpriteParameterfvSGIX(pname, params);} + GLEEPFNGLSPRITEPARAMETERFVSGIXPROC GLeeFuncPtr_glSpriteParameterfvSGIX=GLee_Lazy_glSpriteParameterfvSGIX; +#endif +#ifndef GLEE_C_DEFINED_glSpriteParameteriSGIX +#define GLEE_C_DEFINED_glSpriteParameteriSGIX + void __stdcall GLee_Lazy_glSpriteParameteriSGIX(GLenum pname, GLint param) {if (GLeeInit()) glSpriteParameteriSGIX(pname, param);} + GLEEPFNGLSPRITEPARAMETERISGIXPROC GLeeFuncPtr_glSpriteParameteriSGIX=GLee_Lazy_glSpriteParameteriSGIX; +#endif +#ifndef GLEE_C_DEFINED_glSpriteParameterivSGIX +#define GLEE_C_DEFINED_glSpriteParameterivSGIX + void __stdcall GLee_Lazy_glSpriteParameterivSGIX(GLenum pname, const GLint * params) {if (GLeeInit()) glSpriteParameterivSGIX(pname, params);} + GLEEPFNGLSPRITEPARAMETERIVSGIXPROC GLeeFuncPtr_glSpriteParameterivSGIX=GLee_Lazy_glSpriteParameterivSGIX; +#endif +#endif + +/* GL_SGIX_texture_multi_buffer */ + +#ifdef __GLEE_GL_SGIX_texture_multi_buffer +#endif + +/* GL_EXT_point_parameters */ + +#ifdef __GLEE_GL_EXT_point_parameters +#ifndef GLEE_C_DEFINED_glPointParameterfEXT +#define GLEE_C_DEFINED_glPointParameterfEXT + void __stdcall GLee_Lazy_glPointParameterfEXT(GLenum pname, GLfloat param) {if (GLeeInit()) glPointParameterfEXT(pname, param);} + GLEEPFNGLPOINTPARAMETERFEXTPROC GLeeFuncPtr_glPointParameterfEXT=GLee_Lazy_glPointParameterfEXT; +#endif +#ifndef GLEE_C_DEFINED_glPointParameterfvEXT +#define GLEE_C_DEFINED_glPointParameterfvEXT + void __stdcall GLee_Lazy_glPointParameterfvEXT(GLenum pname, const GLfloat * params) {if (GLeeInit()) glPointParameterfvEXT(pname, params);} + GLEEPFNGLPOINTPARAMETERFVEXTPROC GLeeFuncPtr_glPointParameterfvEXT=GLee_Lazy_glPointParameterfvEXT; +#endif +#endif + +/* GL_SGIS_point_parameters */ + +#ifdef __GLEE_GL_SGIS_point_parameters +#ifndef GLEE_C_DEFINED_glPointParameterfSGIS +#define GLEE_C_DEFINED_glPointParameterfSGIS + void __stdcall GLee_Lazy_glPointParameterfSGIS(GLenum pname, GLfloat param) {if (GLeeInit()) glPointParameterfSGIS(pname, param);} + GLEEPFNGLPOINTPARAMETERFSGISPROC GLeeFuncPtr_glPointParameterfSGIS=GLee_Lazy_glPointParameterfSGIS; +#endif +#ifndef GLEE_C_DEFINED_glPointParameterfvSGIS +#define GLEE_C_DEFINED_glPointParameterfvSGIS + void __stdcall GLee_Lazy_glPointParameterfvSGIS(GLenum pname, const GLfloat * params) {if (GLeeInit()) glPointParameterfvSGIS(pname, params);} + GLEEPFNGLPOINTPARAMETERFVSGISPROC GLeeFuncPtr_glPointParameterfvSGIS=GLee_Lazy_glPointParameterfvSGIS; +#endif +#endif + +/* GL_SGIX_instruments */ + +#ifdef __GLEE_GL_SGIX_instruments +#ifndef GLEE_C_DEFINED_glGetInstrumentsSGIX +#define GLEE_C_DEFINED_glGetInstrumentsSGIX + GLint __stdcall GLee_Lazy_glGetInstrumentsSGIX(void) {if (GLeeInit()) return glGetInstrumentsSGIX(); return (GLint)0;} + GLEEPFNGLGETINSTRUMENTSSGIXPROC GLeeFuncPtr_glGetInstrumentsSGIX=GLee_Lazy_glGetInstrumentsSGIX; +#endif +#ifndef GLEE_C_DEFINED_glInstrumentsBufferSGIX +#define GLEE_C_DEFINED_glInstrumentsBufferSGIX + void __stdcall GLee_Lazy_glInstrumentsBufferSGIX(GLsizei size, GLint * buffer) {if (GLeeInit()) glInstrumentsBufferSGIX(size, buffer);} + GLEEPFNGLINSTRUMENTSBUFFERSGIXPROC GLeeFuncPtr_glInstrumentsBufferSGIX=GLee_Lazy_glInstrumentsBufferSGIX; +#endif +#ifndef GLEE_C_DEFINED_glPollInstrumentsSGIX +#define GLEE_C_DEFINED_glPollInstrumentsSGIX + GLint __stdcall GLee_Lazy_glPollInstrumentsSGIX(GLint * marker_p) {if (GLeeInit()) return glPollInstrumentsSGIX(marker_p); return (GLint)0;} + GLEEPFNGLPOLLINSTRUMENTSSGIXPROC GLeeFuncPtr_glPollInstrumentsSGIX=GLee_Lazy_glPollInstrumentsSGIX; +#endif +#ifndef GLEE_C_DEFINED_glReadInstrumentsSGIX +#define GLEE_C_DEFINED_glReadInstrumentsSGIX + void __stdcall GLee_Lazy_glReadInstrumentsSGIX(GLint marker) {if (GLeeInit()) glReadInstrumentsSGIX(marker);} + GLEEPFNGLREADINSTRUMENTSSGIXPROC GLeeFuncPtr_glReadInstrumentsSGIX=GLee_Lazy_glReadInstrumentsSGIX; +#endif +#ifndef GLEE_C_DEFINED_glStartInstrumentsSGIX +#define GLEE_C_DEFINED_glStartInstrumentsSGIX + void __stdcall GLee_Lazy_glStartInstrumentsSGIX(void) {if (GLeeInit()) glStartInstrumentsSGIX();} + GLEEPFNGLSTARTINSTRUMENTSSGIXPROC GLeeFuncPtr_glStartInstrumentsSGIX=GLee_Lazy_glStartInstrumentsSGIX; +#endif +#ifndef GLEE_C_DEFINED_glStopInstrumentsSGIX +#define GLEE_C_DEFINED_glStopInstrumentsSGIX + void __stdcall GLee_Lazy_glStopInstrumentsSGIX(GLint marker) {if (GLeeInit()) glStopInstrumentsSGIX(marker);} + GLEEPFNGLSTOPINSTRUMENTSSGIXPROC GLeeFuncPtr_glStopInstrumentsSGIX=GLee_Lazy_glStopInstrumentsSGIX; +#endif +#endif + +/* GL_SGIX_texture_scale_bias */ + +#ifdef __GLEE_GL_SGIX_texture_scale_bias +#endif + +/* GL_SGIX_framezoom */ + +#ifdef __GLEE_GL_SGIX_framezoom +#ifndef GLEE_C_DEFINED_glFrameZoomSGIX +#define GLEE_C_DEFINED_glFrameZoomSGIX + void __stdcall GLee_Lazy_glFrameZoomSGIX(GLint factor) {if (GLeeInit()) glFrameZoomSGIX(factor);} + GLEEPFNGLFRAMEZOOMSGIXPROC GLeeFuncPtr_glFrameZoomSGIX=GLee_Lazy_glFrameZoomSGIX; +#endif +#endif + +/* GL_SGIX_tag_sample_buffer */ + +#ifdef __GLEE_GL_SGIX_tag_sample_buffer +#ifndef GLEE_C_DEFINED_glTagSampleBufferSGIX +#define GLEE_C_DEFINED_glTagSampleBufferSGIX + void __stdcall GLee_Lazy_glTagSampleBufferSGIX(void) {if (GLeeInit()) glTagSampleBufferSGIX();} + GLEEPFNGLTAGSAMPLEBUFFERSGIXPROC GLeeFuncPtr_glTagSampleBufferSGIX=GLee_Lazy_glTagSampleBufferSGIX; +#endif +#endif + +/* GL_FfdMaskSGIX */ + +#ifdef __GLEE_GL_FfdMaskSGIX +#endif + +/* GL_SGIX_polynomial_ffd */ + +#ifdef __GLEE_GL_SGIX_polynomial_ffd +#ifndef GLEE_C_DEFINED_glDeformationMap3dSGIX +#define GLEE_C_DEFINED_glDeformationMap3dSGIX + void __stdcall GLee_Lazy_glDeformationMap3dSGIX(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble * points) {if (GLeeInit()) glDeformationMap3dSGIX(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, w1, w2, wstride, worder, points);} + GLEEPFNGLDEFORMATIONMAP3DSGIXPROC GLeeFuncPtr_glDeformationMap3dSGIX=GLee_Lazy_glDeformationMap3dSGIX; +#endif +#ifndef GLEE_C_DEFINED_glDeformationMap3fSGIX +#define GLEE_C_DEFINED_glDeformationMap3fSGIX + void __stdcall GLee_Lazy_glDeformationMap3fSGIX(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat * points) {if (GLeeInit()) glDeformationMap3fSGIX(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, w1, w2, wstride, worder, points);} + GLEEPFNGLDEFORMATIONMAP3FSGIXPROC GLeeFuncPtr_glDeformationMap3fSGIX=GLee_Lazy_glDeformationMap3fSGIX; +#endif +#ifndef GLEE_C_DEFINED_glDeformSGIX +#define GLEE_C_DEFINED_glDeformSGIX + void __stdcall GLee_Lazy_glDeformSGIX(GLbitfield mask) {if (GLeeInit()) glDeformSGIX(mask);} + GLEEPFNGLDEFORMSGIXPROC GLeeFuncPtr_glDeformSGIX=GLee_Lazy_glDeformSGIX; +#endif +#ifndef GLEE_C_DEFINED_glLoadIdentityDeformationMapSGIX +#define GLEE_C_DEFINED_glLoadIdentityDeformationMapSGIX + void __stdcall GLee_Lazy_glLoadIdentityDeformationMapSGIX(GLbitfield mask) {if (GLeeInit()) glLoadIdentityDeformationMapSGIX(mask);} + GLEEPFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC GLeeFuncPtr_glLoadIdentityDeformationMapSGIX=GLee_Lazy_glLoadIdentityDeformationMapSGIX; +#endif +#endif + +/* GL_SGIX_reference_plane */ + +#ifdef __GLEE_GL_SGIX_reference_plane +#ifndef GLEE_C_DEFINED_glReferencePlaneSGIX +#define GLEE_C_DEFINED_glReferencePlaneSGIX + void __stdcall GLee_Lazy_glReferencePlaneSGIX(const GLdouble * equation) {if (GLeeInit()) glReferencePlaneSGIX(equation);} + GLEEPFNGLREFERENCEPLANESGIXPROC GLeeFuncPtr_glReferencePlaneSGIX=GLee_Lazy_glReferencePlaneSGIX; +#endif +#endif + +/* GL_SGIX_flush_raster */ + +#ifdef __GLEE_GL_SGIX_flush_raster +#ifndef GLEE_C_DEFINED_glFlushRasterSGIX +#define GLEE_C_DEFINED_glFlushRasterSGIX + void __stdcall GLee_Lazy_glFlushRasterSGIX(void) {if (GLeeInit()) glFlushRasterSGIX();} + GLEEPFNGLFLUSHRASTERSGIXPROC GLeeFuncPtr_glFlushRasterSGIX=GLee_Lazy_glFlushRasterSGIX; +#endif +#endif + +/* GL_SGIX_depth_texture */ + +#ifdef __GLEE_GL_SGIX_depth_texture +#endif + +/* GL_SGIS_fog_function */ + +#ifdef __GLEE_GL_SGIS_fog_function +#ifndef GLEE_C_DEFINED_glFogFuncSGIS +#define GLEE_C_DEFINED_glFogFuncSGIS + void __stdcall GLee_Lazy_glFogFuncSGIS(GLsizei n, const GLfloat * points) {if (GLeeInit()) glFogFuncSGIS(n, points);} + GLEEPFNGLFOGFUNCSGISPROC GLeeFuncPtr_glFogFuncSGIS=GLee_Lazy_glFogFuncSGIS; +#endif +#ifndef GLEE_C_DEFINED_glGetFogFuncSGIS +#define GLEE_C_DEFINED_glGetFogFuncSGIS + void __stdcall GLee_Lazy_glGetFogFuncSGIS(GLfloat * points) {if (GLeeInit()) glGetFogFuncSGIS(points);} + GLEEPFNGLGETFOGFUNCSGISPROC GLeeFuncPtr_glGetFogFuncSGIS=GLee_Lazy_glGetFogFuncSGIS; +#endif +#endif + +/* GL_SGIX_fog_offset */ + +#ifdef __GLEE_GL_SGIX_fog_offset +#endif + +/* GL_HP_image_transform */ + +#ifdef __GLEE_GL_HP_image_transform +#ifndef GLEE_C_DEFINED_glImageTransformParameteriHP +#define GLEE_C_DEFINED_glImageTransformParameteriHP + void __stdcall GLee_Lazy_glImageTransformParameteriHP(GLenum target, GLenum pname, GLint param) {if (GLeeInit()) glImageTransformParameteriHP(target, pname, param);} + GLEEPFNGLIMAGETRANSFORMPARAMETERIHPPROC GLeeFuncPtr_glImageTransformParameteriHP=GLee_Lazy_glImageTransformParameteriHP; +#endif +#ifndef GLEE_C_DEFINED_glImageTransformParameterfHP +#define GLEE_C_DEFINED_glImageTransformParameterfHP + void __stdcall GLee_Lazy_glImageTransformParameterfHP(GLenum target, GLenum pname, GLfloat param) {if (GLeeInit()) glImageTransformParameterfHP(target, pname, param);} + GLEEPFNGLIMAGETRANSFORMPARAMETERFHPPROC GLeeFuncPtr_glImageTransformParameterfHP=GLee_Lazy_glImageTransformParameterfHP; +#endif +#ifndef GLEE_C_DEFINED_glImageTransformParameterivHP +#define GLEE_C_DEFINED_glImageTransformParameterivHP + void __stdcall GLee_Lazy_glImageTransformParameterivHP(GLenum target, GLenum pname, const GLint * params) {if (GLeeInit()) glImageTransformParameterivHP(target, pname, params);} + GLEEPFNGLIMAGETRANSFORMPARAMETERIVHPPROC GLeeFuncPtr_glImageTransformParameterivHP=GLee_Lazy_glImageTransformParameterivHP; +#endif +#ifndef GLEE_C_DEFINED_glImageTransformParameterfvHP +#define GLEE_C_DEFINED_glImageTransformParameterfvHP + void __stdcall GLee_Lazy_glImageTransformParameterfvHP(GLenum target, GLenum pname, const GLfloat * params) {if (GLeeInit()) glImageTransformParameterfvHP(target, pname, params);} + GLEEPFNGLIMAGETRANSFORMPARAMETERFVHPPROC GLeeFuncPtr_glImageTransformParameterfvHP=GLee_Lazy_glImageTransformParameterfvHP; +#endif +#ifndef GLEE_C_DEFINED_glGetImageTransformParameterivHP +#define GLEE_C_DEFINED_glGetImageTransformParameterivHP + void __stdcall GLee_Lazy_glGetImageTransformParameterivHP(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetImageTransformParameterivHP(target, pname, params);} + GLEEPFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC GLeeFuncPtr_glGetImageTransformParameterivHP=GLee_Lazy_glGetImageTransformParameterivHP; +#endif +#ifndef GLEE_C_DEFINED_glGetImageTransformParameterfvHP +#define GLEE_C_DEFINED_glGetImageTransformParameterfvHP + void __stdcall GLee_Lazy_glGetImageTransformParameterfvHP(GLenum target, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetImageTransformParameterfvHP(target, pname, params);} + GLEEPFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC GLeeFuncPtr_glGetImageTransformParameterfvHP=GLee_Lazy_glGetImageTransformParameterfvHP; +#endif +#endif + +/* GL_HP_convolution_border_modes */ + +#ifdef __GLEE_GL_HP_convolution_border_modes +#endif + +/* GL_INGR_palette_buffer */ + +#ifdef __GLEE_GL_INGR_palette_buffer +#endif + +/* GL_SGIX_texture_add_env */ + +#ifdef __GLEE_GL_SGIX_texture_add_env +#endif + +/* GL_EXT_color_subtable */ + +#ifdef __GLEE_GL_EXT_color_subtable +#ifndef GLEE_C_DEFINED_glColorSubTableEXT +#define GLEE_C_DEFINED_glColorSubTableEXT + void __stdcall GLee_Lazy_glColorSubTableEXT(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid * data) {if (GLeeInit()) glColorSubTableEXT(target, start, count, format, type, data);} + GLEEPFNGLCOLORSUBTABLEEXTPROC GLeeFuncPtr_glColorSubTableEXT=GLee_Lazy_glColorSubTableEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyColorSubTableEXT +#define GLEE_C_DEFINED_glCopyColorSubTableEXT + void __stdcall GLee_Lazy_glCopyColorSubTableEXT(GLenum target, GLsizei start, GLint x, GLint y, GLsizei width) {if (GLeeInit()) glCopyColorSubTableEXT(target, start, x, y, width);} + GLEEPFNGLCOPYCOLORSUBTABLEEXTPROC GLeeFuncPtr_glCopyColorSubTableEXT=GLee_Lazy_glCopyColorSubTableEXT; +#endif +#endif + +/* GL_PGI_vertex_hints */ + +#ifdef __GLEE_GL_PGI_vertex_hints +#endif + +/* GL_PGI_misc_hints */ + +#ifdef __GLEE_GL_PGI_misc_hints +#ifndef GLEE_C_DEFINED_glHintPGI +#define GLEE_C_DEFINED_glHintPGI + void __stdcall GLee_Lazy_glHintPGI(GLenum target, GLint mode) {if (GLeeInit()) glHintPGI(target, mode);} + GLEEPFNGLHINTPGIPROC GLeeFuncPtr_glHintPGI=GLee_Lazy_glHintPGI; +#endif +#endif + +/* GL_EXT_paletted_texture */ + +#ifdef __GLEE_GL_EXT_paletted_texture +#ifndef GLEE_C_DEFINED_glColorTableEXT +#define GLEE_C_DEFINED_glColorTableEXT + void __stdcall GLee_Lazy_glColorTableEXT(GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid * table) {if (GLeeInit()) glColorTableEXT(target, internalFormat, width, format, type, table);} + GLEEPFNGLCOLORTABLEEXTPROC GLeeFuncPtr_glColorTableEXT=GLee_Lazy_glColorTableEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetColorTableEXT +#define GLEE_C_DEFINED_glGetColorTableEXT + void __stdcall GLee_Lazy_glGetColorTableEXT(GLenum target, GLenum format, GLenum type, GLvoid * data) {if (GLeeInit()) glGetColorTableEXT(target, format, type, data);} + GLEEPFNGLGETCOLORTABLEEXTPROC GLeeFuncPtr_glGetColorTableEXT=GLee_Lazy_glGetColorTableEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetColorTableParameterivEXT +#define GLEE_C_DEFINED_glGetColorTableParameterivEXT + void __stdcall GLee_Lazy_glGetColorTableParameterivEXT(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetColorTableParameterivEXT(target, pname, params);} + GLEEPFNGLGETCOLORTABLEPARAMETERIVEXTPROC GLeeFuncPtr_glGetColorTableParameterivEXT=GLee_Lazy_glGetColorTableParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetColorTableParameterfvEXT +#define GLEE_C_DEFINED_glGetColorTableParameterfvEXT + void __stdcall GLee_Lazy_glGetColorTableParameterfvEXT(GLenum target, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetColorTableParameterfvEXT(target, pname, params);} + GLEEPFNGLGETCOLORTABLEPARAMETERFVEXTPROC GLeeFuncPtr_glGetColorTableParameterfvEXT=GLee_Lazy_glGetColorTableParameterfvEXT; +#endif +#endif + +/* GL_EXT_clip_volume_hint */ + +#ifdef __GLEE_GL_EXT_clip_volume_hint +#endif + +/* GL_SGIX_list_priority */ + +#ifdef __GLEE_GL_SGIX_list_priority +#ifndef GLEE_C_DEFINED_glGetListParameterfvSGIX +#define GLEE_C_DEFINED_glGetListParameterfvSGIX + void __stdcall GLee_Lazy_glGetListParameterfvSGIX(GLuint list, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetListParameterfvSGIX(list, pname, params);} + GLEEPFNGLGETLISTPARAMETERFVSGIXPROC GLeeFuncPtr_glGetListParameterfvSGIX=GLee_Lazy_glGetListParameterfvSGIX; +#endif +#ifndef GLEE_C_DEFINED_glGetListParameterivSGIX +#define GLEE_C_DEFINED_glGetListParameterivSGIX + void __stdcall GLee_Lazy_glGetListParameterivSGIX(GLuint list, GLenum pname, GLint * params) {if (GLeeInit()) glGetListParameterivSGIX(list, pname, params);} + GLEEPFNGLGETLISTPARAMETERIVSGIXPROC GLeeFuncPtr_glGetListParameterivSGIX=GLee_Lazy_glGetListParameterivSGIX; +#endif +#ifndef GLEE_C_DEFINED_glListParameterfSGIX +#define GLEE_C_DEFINED_glListParameterfSGIX + void __stdcall GLee_Lazy_glListParameterfSGIX(GLuint list, GLenum pname, GLfloat param) {if (GLeeInit()) glListParameterfSGIX(list, pname, param);} + GLEEPFNGLLISTPARAMETERFSGIXPROC GLeeFuncPtr_glListParameterfSGIX=GLee_Lazy_glListParameterfSGIX; +#endif +#ifndef GLEE_C_DEFINED_glListParameterfvSGIX +#define GLEE_C_DEFINED_glListParameterfvSGIX + void __stdcall GLee_Lazy_glListParameterfvSGIX(GLuint list, GLenum pname, const GLfloat * params) {if (GLeeInit()) glListParameterfvSGIX(list, pname, params);} + GLEEPFNGLLISTPARAMETERFVSGIXPROC GLeeFuncPtr_glListParameterfvSGIX=GLee_Lazy_glListParameterfvSGIX; +#endif +#ifndef GLEE_C_DEFINED_glListParameteriSGIX +#define GLEE_C_DEFINED_glListParameteriSGIX + void __stdcall GLee_Lazy_glListParameteriSGIX(GLuint list, GLenum pname, GLint param) {if (GLeeInit()) glListParameteriSGIX(list, pname, param);} + GLEEPFNGLLISTPARAMETERISGIXPROC GLeeFuncPtr_glListParameteriSGIX=GLee_Lazy_glListParameteriSGIX; +#endif +#ifndef GLEE_C_DEFINED_glListParameterivSGIX +#define GLEE_C_DEFINED_glListParameterivSGIX + void __stdcall GLee_Lazy_glListParameterivSGIX(GLuint list, GLenum pname, const GLint * params) {if (GLeeInit()) glListParameterivSGIX(list, pname, params);} + GLEEPFNGLLISTPARAMETERIVSGIXPROC GLeeFuncPtr_glListParameterivSGIX=GLee_Lazy_glListParameterivSGIX; +#endif +#endif + +/* GL_SGIX_ir_instrument1 */ + +#ifdef __GLEE_GL_SGIX_ir_instrument1 +#endif + +/* GL_SGIX_calligraphic_fragment */ + +#ifdef __GLEE_GL_SGIX_calligraphic_fragment +#endif + +/* GL_SGIX_texture_lod_bias */ + +#ifdef __GLEE_GL_SGIX_texture_lod_bias +#endif + +/* GL_SGIX_shadow_ambient */ + +#ifdef __GLEE_GL_SGIX_shadow_ambient +#endif + +/* GL_EXT_index_texture */ + +#ifdef __GLEE_GL_EXT_index_texture +#endif + +/* GL_EXT_index_material */ + +#ifdef __GLEE_GL_EXT_index_material +#ifndef GLEE_C_DEFINED_glIndexMaterialEXT +#define GLEE_C_DEFINED_glIndexMaterialEXT + void __stdcall GLee_Lazy_glIndexMaterialEXT(GLenum face, GLenum mode) {if (GLeeInit()) glIndexMaterialEXT(face, mode);} + GLEEPFNGLINDEXMATERIALEXTPROC GLeeFuncPtr_glIndexMaterialEXT=GLee_Lazy_glIndexMaterialEXT; +#endif +#endif + +/* GL_EXT_index_func */ + +#ifdef __GLEE_GL_EXT_index_func +#ifndef GLEE_C_DEFINED_glIndexFuncEXT +#define GLEE_C_DEFINED_glIndexFuncEXT + void __stdcall GLee_Lazy_glIndexFuncEXT(GLenum func, GLclampf ref) {if (GLeeInit()) glIndexFuncEXT(func, ref);} + GLEEPFNGLINDEXFUNCEXTPROC GLeeFuncPtr_glIndexFuncEXT=GLee_Lazy_glIndexFuncEXT; +#endif +#endif + +/* GL_EXT_index_array_formats */ + +#ifdef __GLEE_GL_EXT_index_array_formats +#endif + +/* GL_EXT_compiled_vertex_array */ + +#ifdef __GLEE_GL_EXT_compiled_vertex_array +#ifndef GLEE_C_DEFINED_glLockArraysEXT +#define GLEE_C_DEFINED_glLockArraysEXT + void __stdcall GLee_Lazy_glLockArraysEXT(GLint first, GLsizei count) {if (GLeeInit()) glLockArraysEXT(first, count);} + GLEEPFNGLLOCKARRAYSEXTPROC GLeeFuncPtr_glLockArraysEXT=GLee_Lazy_glLockArraysEXT; +#endif +#ifndef GLEE_C_DEFINED_glUnlockArraysEXT +#define GLEE_C_DEFINED_glUnlockArraysEXT + void __stdcall GLee_Lazy_glUnlockArraysEXT(void) {if (GLeeInit()) glUnlockArraysEXT();} + GLEEPFNGLUNLOCKARRAYSEXTPROC GLeeFuncPtr_glUnlockArraysEXT=GLee_Lazy_glUnlockArraysEXT; +#endif +#endif + +/* GL_EXT_cull_vertex */ + +#ifdef __GLEE_GL_EXT_cull_vertex +#ifndef GLEE_C_DEFINED_glCullParameterdvEXT +#define GLEE_C_DEFINED_glCullParameterdvEXT + void __stdcall GLee_Lazy_glCullParameterdvEXT(GLenum pname, GLdouble * params) {if (GLeeInit()) glCullParameterdvEXT(pname, params);} + GLEEPFNGLCULLPARAMETERDVEXTPROC GLeeFuncPtr_glCullParameterdvEXT=GLee_Lazy_glCullParameterdvEXT; +#endif +#ifndef GLEE_C_DEFINED_glCullParameterfvEXT +#define GLEE_C_DEFINED_glCullParameterfvEXT + void __stdcall GLee_Lazy_glCullParameterfvEXT(GLenum pname, GLfloat * params) {if (GLeeInit()) glCullParameterfvEXT(pname, params);} + GLEEPFNGLCULLPARAMETERFVEXTPROC GLeeFuncPtr_glCullParameterfvEXT=GLee_Lazy_glCullParameterfvEXT; +#endif +#endif + +/* GL_SGIX_ycrcb */ + +#ifdef __GLEE_GL_SGIX_ycrcb +#endif + +/* GL_SGIX_fragment_lighting */ + +#ifdef __GLEE_GL_SGIX_fragment_lighting +#ifndef GLEE_C_DEFINED_glFragmentColorMaterialSGIX +#define GLEE_C_DEFINED_glFragmentColorMaterialSGIX + void __stdcall GLee_Lazy_glFragmentColorMaterialSGIX(GLenum face, GLenum mode) {if (GLeeInit()) glFragmentColorMaterialSGIX(face, mode);} + GLEEPFNGLFRAGMENTCOLORMATERIALSGIXPROC GLeeFuncPtr_glFragmentColorMaterialSGIX=GLee_Lazy_glFragmentColorMaterialSGIX; +#endif +#ifndef GLEE_C_DEFINED_glFragmentLightfSGIX +#define GLEE_C_DEFINED_glFragmentLightfSGIX + void __stdcall GLee_Lazy_glFragmentLightfSGIX(GLenum light, GLenum pname, GLfloat param) {if (GLeeInit()) glFragmentLightfSGIX(light, pname, param);} + GLEEPFNGLFRAGMENTLIGHTFSGIXPROC GLeeFuncPtr_glFragmentLightfSGIX=GLee_Lazy_glFragmentLightfSGIX; +#endif +#ifndef GLEE_C_DEFINED_glFragmentLightfvSGIX +#define GLEE_C_DEFINED_glFragmentLightfvSGIX + void __stdcall GLee_Lazy_glFragmentLightfvSGIX(GLenum light, GLenum pname, const GLfloat * params) {if (GLeeInit()) glFragmentLightfvSGIX(light, pname, params);} + GLEEPFNGLFRAGMENTLIGHTFVSGIXPROC GLeeFuncPtr_glFragmentLightfvSGIX=GLee_Lazy_glFragmentLightfvSGIX; +#endif +#ifndef GLEE_C_DEFINED_glFragmentLightiSGIX +#define GLEE_C_DEFINED_glFragmentLightiSGIX + void __stdcall GLee_Lazy_glFragmentLightiSGIX(GLenum light, GLenum pname, GLint param) {if (GLeeInit()) glFragmentLightiSGIX(light, pname, param);} + GLEEPFNGLFRAGMENTLIGHTISGIXPROC GLeeFuncPtr_glFragmentLightiSGIX=GLee_Lazy_glFragmentLightiSGIX; +#endif +#ifndef GLEE_C_DEFINED_glFragmentLightivSGIX +#define GLEE_C_DEFINED_glFragmentLightivSGIX + void __stdcall GLee_Lazy_glFragmentLightivSGIX(GLenum light, GLenum pname, const GLint * params) {if (GLeeInit()) glFragmentLightivSGIX(light, pname, params);} + GLEEPFNGLFRAGMENTLIGHTIVSGIXPROC GLeeFuncPtr_glFragmentLightivSGIX=GLee_Lazy_glFragmentLightivSGIX; +#endif +#ifndef GLEE_C_DEFINED_glFragmentLightModelfSGIX +#define GLEE_C_DEFINED_glFragmentLightModelfSGIX + void __stdcall GLee_Lazy_glFragmentLightModelfSGIX(GLenum pname, GLfloat param) {if (GLeeInit()) glFragmentLightModelfSGIX(pname, param);} + GLEEPFNGLFRAGMENTLIGHTMODELFSGIXPROC GLeeFuncPtr_glFragmentLightModelfSGIX=GLee_Lazy_glFragmentLightModelfSGIX; +#endif +#ifndef GLEE_C_DEFINED_glFragmentLightModelfvSGIX +#define GLEE_C_DEFINED_glFragmentLightModelfvSGIX + void __stdcall GLee_Lazy_glFragmentLightModelfvSGIX(GLenum pname, const GLfloat * params) {if (GLeeInit()) glFragmentLightModelfvSGIX(pname, params);} + GLEEPFNGLFRAGMENTLIGHTMODELFVSGIXPROC GLeeFuncPtr_glFragmentLightModelfvSGIX=GLee_Lazy_glFragmentLightModelfvSGIX; +#endif +#ifndef GLEE_C_DEFINED_glFragmentLightModeliSGIX +#define GLEE_C_DEFINED_glFragmentLightModeliSGIX + void __stdcall GLee_Lazy_glFragmentLightModeliSGIX(GLenum pname, GLint param) {if (GLeeInit()) glFragmentLightModeliSGIX(pname, param);} + GLEEPFNGLFRAGMENTLIGHTMODELISGIXPROC GLeeFuncPtr_glFragmentLightModeliSGIX=GLee_Lazy_glFragmentLightModeliSGIX; +#endif +#ifndef GLEE_C_DEFINED_glFragmentLightModelivSGIX +#define GLEE_C_DEFINED_glFragmentLightModelivSGIX + void __stdcall GLee_Lazy_glFragmentLightModelivSGIX(GLenum pname, const GLint * params) {if (GLeeInit()) glFragmentLightModelivSGIX(pname, params);} + GLEEPFNGLFRAGMENTLIGHTMODELIVSGIXPROC GLeeFuncPtr_glFragmentLightModelivSGIX=GLee_Lazy_glFragmentLightModelivSGIX; +#endif +#ifndef GLEE_C_DEFINED_glFragmentMaterialfSGIX +#define GLEE_C_DEFINED_glFragmentMaterialfSGIX + void __stdcall GLee_Lazy_glFragmentMaterialfSGIX(GLenum face, GLenum pname, GLfloat param) {if (GLeeInit()) glFragmentMaterialfSGIX(face, pname, param);} + GLEEPFNGLFRAGMENTMATERIALFSGIXPROC GLeeFuncPtr_glFragmentMaterialfSGIX=GLee_Lazy_glFragmentMaterialfSGIX; +#endif +#ifndef GLEE_C_DEFINED_glFragmentMaterialfvSGIX +#define GLEE_C_DEFINED_glFragmentMaterialfvSGIX + void __stdcall GLee_Lazy_glFragmentMaterialfvSGIX(GLenum face, GLenum pname, const GLfloat * params) {if (GLeeInit()) glFragmentMaterialfvSGIX(face, pname, params);} + GLEEPFNGLFRAGMENTMATERIALFVSGIXPROC GLeeFuncPtr_glFragmentMaterialfvSGIX=GLee_Lazy_glFragmentMaterialfvSGIX; +#endif +#ifndef GLEE_C_DEFINED_glFragmentMaterialiSGIX +#define GLEE_C_DEFINED_glFragmentMaterialiSGIX + void __stdcall GLee_Lazy_glFragmentMaterialiSGIX(GLenum face, GLenum pname, GLint param) {if (GLeeInit()) glFragmentMaterialiSGIX(face, pname, param);} + GLEEPFNGLFRAGMENTMATERIALISGIXPROC GLeeFuncPtr_glFragmentMaterialiSGIX=GLee_Lazy_glFragmentMaterialiSGIX; +#endif +#ifndef GLEE_C_DEFINED_glFragmentMaterialivSGIX +#define GLEE_C_DEFINED_glFragmentMaterialivSGIX + void __stdcall GLee_Lazy_glFragmentMaterialivSGIX(GLenum face, GLenum pname, const GLint * params) {if (GLeeInit()) glFragmentMaterialivSGIX(face, pname, params);} + GLEEPFNGLFRAGMENTMATERIALIVSGIXPROC GLeeFuncPtr_glFragmentMaterialivSGIX=GLee_Lazy_glFragmentMaterialivSGIX; +#endif +#ifndef GLEE_C_DEFINED_glGetFragmentLightfvSGIX +#define GLEE_C_DEFINED_glGetFragmentLightfvSGIX + void __stdcall GLee_Lazy_glGetFragmentLightfvSGIX(GLenum light, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetFragmentLightfvSGIX(light, pname, params);} + GLEEPFNGLGETFRAGMENTLIGHTFVSGIXPROC GLeeFuncPtr_glGetFragmentLightfvSGIX=GLee_Lazy_glGetFragmentLightfvSGIX; +#endif +#ifndef GLEE_C_DEFINED_glGetFragmentLightivSGIX +#define GLEE_C_DEFINED_glGetFragmentLightivSGIX + void __stdcall GLee_Lazy_glGetFragmentLightivSGIX(GLenum light, GLenum pname, GLint * params) {if (GLeeInit()) glGetFragmentLightivSGIX(light, pname, params);} + GLEEPFNGLGETFRAGMENTLIGHTIVSGIXPROC GLeeFuncPtr_glGetFragmentLightivSGIX=GLee_Lazy_glGetFragmentLightivSGIX; +#endif +#ifndef GLEE_C_DEFINED_glGetFragmentMaterialfvSGIX +#define GLEE_C_DEFINED_glGetFragmentMaterialfvSGIX + void __stdcall GLee_Lazy_glGetFragmentMaterialfvSGIX(GLenum face, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetFragmentMaterialfvSGIX(face, pname, params);} + GLEEPFNGLGETFRAGMENTMATERIALFVSGIXPROC GLeeFuncPtr_glGetFragmentMaterialfvSGIX=GLee_Lazy_glGetFragmentMaterialfvSGIX; +#endif +#ifndef GLEE_C_DEFINED_glGetFragmentMaterialivSGIX +#define GLEE_C_DEFINED_glGetFragmentMaterialivSGIX + void __stdcall GLee_Lazy_glGetFragmentMaterialivSGIX(GLenum face, GLenum pname, GLint * params) {if (GLeeInit()) glGetFragmentMaterialivSGIX(face, pname, params);} + GLEEPFNGLGETFRAGMENTMATERIALIVSGIXPROC GLeeFuncPtr_glGetFragmentMaterialivSGIX=GLee_Lazy_glGetFragmentMaterialivSGIX; +#endif +#ifndef GLEE_C_DEFINED_glLightEnviSGIX +#define GLEE_C_DEFINED_glLightEnviSGIX + void __stdcall GLee_Lazy_glLightEnviSGIX(GLenum pname, GLint param) {if (GLeeInit()) glLightEnviSGIX(pname, param);} + GLEEPFNGLLIGHTENVISGIXPROC GLeeFuncPtr_glLightEnviSGIX=GLee_Lazy_glLightEnviSGIX; +#endif +#endif + +/* GL_IBM_rasterpos_clip */ + +#ifdef __GLEE_GL_IBM_rasterpos_clip +#endif + +/* GL_HP_texture_lighting */ + +#ifdef __GLEE_GL_HP_texture_lighting +#endif + +/* GL_EXT_draw_range_elements */ + +#ifdef __GLEE_GL_EXT_draw_range_elements +#ifndef GLEE_C_DEFINED_glDrawRangeElementsEXT +#define GLEE_C_DEFINED_glDrawRangeElementsEXT + void __stdcall GLee_Lazy_glDrawRangeElementsEXT(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices) {if (GLeeInit()) glDrawRangeElementsEXT(mode, start, end, count, type, indices);} + GLEEPFNGLDRAWRANGEELEMENTSEXTPROC GLeeFuncPtr_glDrawRangeElementsEXT=GLee_Lazy_glDrawRangeElementsEXT; +#endif +#endif + +/* GL_WIN_phong_shading */ + +#ifdef __GLEE_GL_WIN_phong_shading +#endif + +/* GL_WIN_specular_fog */ + +#ifdef __GLEE_GL_WIN_specular_fog +#endif + +/* GL_EXT_light_texture */ + +#ifdef __GLEE_GL_EXT_light_texture +#ifndef GLEE_C_DEFINED_glApplyTextureEXT +#define GLEE_C_DEFINED_glApplyTextureEXT + void __stdcall GLee_Lazy_glApplyTextureEXT(GLenum mode) {if (GLeeInit()) glApplyTextureEXT(mode);} + GLEEPFNGLAPPLYTEXTUREEXTPROC GLeeFuncPtr_glApplyTextureEXT=GLee_Lazy_glApplyTextureEXT; +#endif +#ifndef GLEE_C_DEFINED_glTextureLightEXT +#define GLEE_C_DEFINED_glTextureLightEXT + void __stdcall GLee_Lazy_glTextureLightEXT(GLenum pname) {if (GLeeInit()) glTextureLightEXT(pname);} + GLEEPFNGLTEXTURELIGHTEXTPROC GLeeFuncPtr_glTextureLightEXT=GLee_Lazy_glTextureLightEXT; +#endif +#ifndef GLEE_C_DEFINED_glTextureMaterialEXT +#define GLEE_C_DEFINED_glTextureMaterialEXT + void __stdcall GLee_Lazy_glTextureMaterialEXT(GLenum face, GLenum mode) {if (GLeeInit()) glTextureMaterialEXT(face, mode);} + GLEEPFNGLTEXTUREMATERIALEXTPROC GLeeFuncPtr_glTextureMaterialEXT=GLee_Lazy_glTextureMaterialEXT; +#endif +#endif + +/* GL_SGIX_blend_alpha_minmax */ + +#ifdef __GLEE_GL_SGIX_blend_alpha_minmax +#endif + +/* GL_SGIX_impact_pixel_texture */ + +#ifdef __GLEE_GL_SGIX_impact_pixel_texture +#endif + +/* GL_EXT_bgra */ + +#ifdef __GLEE_GL_EXT_bgra +#endif + +/* GL_SGIX_async */ + +#ifdef __GLEE_GL_SGIX_async +#ifndef GLEE_C_DEFINED_glAsyncMarkerSGIX +#define GLEE_C_DEFINED_glAsyncMarkerSGIX + void __stdcall GLee_Lazy_glAsyncMarkerSGIX(GLuint marker) {if (GLeeInit()) glAsyncMarkerSGIX(marker);} + GLEEPFNGLASYNCMARKERSGIXPROC GLeeFuncPtr_glAsyncMarkerSGIX=GLee_Lazy_glAsyncMarkerSGIX; +#endif +#ifndef GLEE_C_DEFINED_glFinishAsyncSGIX +#define GLEE_C_DEFINED_glFinishAsyncSGIX + GLint __stdcall GLee_Lazy_glFinishAsyncSGIX(GLuint * markerp) {if (GLeeInit()) return glFinishAsyncSGIX(markerp); return (GLint)0;} + GLEEPFNGLFINISHASYNCSGIXPROC GLeeFuncPtr_glFinishAsyncSGIX=GLee_Lazy_glFinishAsyncSGIX; +#endif +#ifndef GLEE_C_DEFINED_glPollAsyncSGIX +#define GLEE_C_DEFINED_glPollAsyncSGIX + GLint __stdcall GLee_Lazy_glPollAsyncSGIX(GLuint * markerp) {if (GLeeInit()) return glPollAsyncSGIX(markerp); return (GLint)0;} + GLEEPFNGLPOLLASYNCSGIXPROC GLeeFuncPtr_glPollAsyncSGIX=GLee_Lazy_glPollAsyncSGIX; +#endif +#ifndef GLEE_C_DEFINED_glGenAsyncMarkersSGIX +#define GLEE_C_DEFINED_glGenAsyncMarkersSGIX + GLuint __stdcall GLee_Lazy_glGenAsyncMarkersSGIX(GLsizei range) {if (GLeeInit()) return glGenAsyncMarkersSGIX(range); return (GLuint)0;} + GLEEPFNGLGENASYNCMARKERSSGIXPROC GLeeFuncPtr_glGenAsyncMarkersSGIX=GLee_Lazy_glGenAsyncMarkersSGIX; +#endif +#ifndef GLEE_C_DEFINED_glDeleteAsyncMarkersSGIX +#define GLEE_C_DEFINED_glDeleteAsyncMarkersSGIX + void __stdcall GLee_Lazy_glDeleteAsyncMarkersSGIX(GLuint marker, GLsizei range) {if (GLeeInit()) glDeleteAsyncMarkersSGIX(marker, range);} + GLEEPFNGLDELETEASYNCMARKERSSGIXPROC GLeeFuncPtr_glDeleteAsyncMarkersSGIX=GLee_Lazy_glDeleteAsyncMarkersSGIX; +#endif +#ifndef GLEE_C_DEFINED_glIsAsyncMarkerSGIX +#define GLEE_C_DEFINED_glIsAsyncMarkerSGIX + GLboolean __stdcall GLee_Lazy_glIsAsyncMarkerSGIX(GLuint marker) {if (GLeeInit()) return glIsAsyncMarkerSGIX(marker); return (GLboolean)0;} + GLEEPFNGLISASYNCMARKERSGIXPROC GLeeFuncPtr_glIsAsyncMarkerSGIX=GLee_Lazy_glIsAsyncMarkerSGIX; +#endif +#endif + +/* GL_SGIX_async_pixel */ + +#ifdef __GLEE_GL_SGIX_async_pixel +#endif + +/* GL_SGIX_async_histogram */ + +#ifdef __GLEE_GL_SGIX_async_histogram +#endif + +/* GL_INTEL_texture_scissor */ + +#ifdef __GLEE_GL_INTEL_texture_scissor +#endif + +/* GL_INTEL_parallel_arrays */ + +#ifdef __GLEE_GL_INTEL_parallel_arrays +#ifndef GLEE_C_DEFINED_glVertexPointervINTEL +#define GLEE_C_DEFINED_glVertexPointervINTEL + void __stdcall GLee_Lazy_glVertexPointervINTEL(GLint size, GLenum type, const GLvoid* * pointer) {if (GLeeInit()) glVertexPointervINTEL(size, type, pointer);} + GLEEPFNGLVERTEXPOINTERVINTELPROC GLeeFuncPtr_glVertexPointervINTEL=GLee_Lazy_glVertexPointervINTEL; +#endif +#ifndef GLEE_C_DEFINED_glNormalPointervINTEL +#define GLEE_C_DEFINED_glNormalPointervINTEL + void __stdcall GLee_Lazy_glNormalPointervINTEL(GLenum type, const GLvoid* * pointer) {if (GLeeInit()) glNormalPointervINTEL(type, pointer);} + GLEEPFNGLNORMALPOINTERVINTELPROC GLeeFuncPtr_glNormalPointervINTEL=GLee_Lazy_glNormalPointervINTEL; +#endif +#ifndef GLEE_C_DEFINED_glColorPointervINTEL +#define GLEE_C_DEFINED_glColorPointervINTEL + void __stdcall GLee_Lazy_glColorPointervINTEL(GLint size, GLenum type, const GLvoid* * pointer) {if (GLeeInit()) glColorPointervINTEL(size, type, pointer);} + GLEEPFNGLCOLORPOINTERVINTELPROC GLeeFuncPtr_glColorPointervINTEL=GLee_Lazy_glColorPointervINTEL; +#endif +#ifndef GLEE_C_DEFINED_glTexCoordPointervINTEL +#define GLEE_C_DEFINED_glTexCoordPointervINTEL + void __stdcall GLee_Lazy_glTexCoordPointervINTEL(GLint size, GLenum type, const GLvoid* * pointer) {if (GLeeInit()) glTexCoordPointervINTEL(size, type, pointer);} + GLEEPFNGLTEXCOORDPOINTERVINTELPROC GLeeFuncPtr_glTexCoordPointervINTEL=GLee_Lazy_glTexCoordPointervINTEL; +#endif +#endif + +/* GL_HP_occlusion_test */ + +#ifdef __GLEE_GL_HP_occlusion_test +#endif + +/* GL_EXT_pixel_transform */ + +#ifdef __GLEE_GL_EXT_pixel_transform +#ifndef GLEE_C_DEFINED_glPixelTransformParameteriEXT +#define GLEE_C_DEFINED_glPixelTransformParameteriEXT + void __stdcall GLee_Lazy_glPixelTransformParameteriEXT(GLenum target, GLenum pname, GLint param) {if (GLeeInit()) glPixelTransformParameteriEXT(target, pname, param);} + GLEEPFNGLPIXELTRANSFORMPARAMETERIEXTPROC GLeeFuncPtr_glPixelTransformParameteriEXT=GLee_Lazy_glPixelTransformParameteriEXT; +#endif +#ifndef GLEE_C_DEFINED_glPixelTransformParameterfEXT +#define GLEE_C_DEFINED_glPixelTransformParameterfEXT + void __stdcall GLee_Lazy_glPixelTransformParameterfEXT(GLenum target, GLenum pname, GLfloat param) {if (GLeeInit()) glPixelTransformParameterfEXT(target, pname, param);} + GLEEPFNGLPIXELTRANSFORMPARAMETERFEXTPROC GLeeFuncPtr_glPixelTransformParameterfEXT=GLee_Lazy_glPixelTransformParameterfEXT; +#endif +#ifndef GLEE_C_DEFINED_glPixelTransformParameterivEXT +#define GLEE_C_DEFINED_glPixelTransformParameterivEXT + void __stdcall GLee_Lazy_glPixelTransformParameterivEXT(GLenum target, GLenum pname, const GLint * params) {if (GLeeInit()) glPixelTransformParameterivEXT(target, pname, params);} + GLEEPFNGLPIXELTRANSFORMPARAMETERIVEXTPROC GLeeFuncPtr_glPixelTransformParameterivEXT=GLee_Lazy_glPixelTransformParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glPixelTransformParameterfvEXT +#define GLEE_C_DEFINED_glPixelTransformParameterfvEXT + void __stdcall GLee_Lazy_glPixelTransformParameterfvEXT(GLenum target, GLenum pname, const GLfloat * params) {if (GLeeInit()) glPixelTransformParameterfvEXT(target, pname, params);} + GLEEPFNGLPIXELTRANSFORMPARAMETERFVEXTPROC GLeeFuncPtr_glPixelTransformParameterfvEXT=GLee_Lazy_glPixelTransformParameterfvEXT; +#endif +#endif + +/* GL_EXT_pixel_transform_color_table */ + +#ifdef __GLEE_GL_EXT_pixel_transform_color_table +#endif + +/* GL_EXT_shared_texture_palette */ + +#ifdef __GLEE_GL_EXT_shared_texture_palette +#endif + +/* GL_EXT_separate_specular_color */ + +#ifdef __GLEE_GL_EXT_separate_specular_color +#endif + +/* GL_EXT_secondary_color */ + +#ifdef __GLEE_GL_EXT_secondary_color +#ifndef GLEE_C_DEFINED_glSecondaryColor3bEXT +#define GLEE_C_DEFINED_glSecondaryColor3bEXT + void __stdcall GLee_Lazy_glSecondaryColor3bEXT(GLbyte red, GLbyte green, GLbyte blue) {if (GLeeInit()) glSecondaryColor3bEXT(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3BEXTPROC GLeeFuncPtr_glSecondaryColor3bEXT=GLee_Lazy_glSecondaryColor3bEXT; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3bvEXT +#define GLEE_C_DEFINED_glSecondaryColor3bvEXT + void __stdcall GLee_Lazy_glSecondaryColor3bvEXT(const GLbyte * v) {if (GLeeInit()) glSecondaryColor3bvEXT(v);} + GLEEPFNGLSECONDARYCOLOR3BVEXTPROC GLeeFuncPtr_glSecondaryColor3bvEXT=GLee_Lazy_glSecondaryColor3bvEXT; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3dEXT +#define GLEE_C_DEFINED_glSecondaryColor3dEXT + void __stdcall GLee_Lazy_glSecondaryColor3dEXT(GLdouble red, GLdouble green, GLdouble blue) {if (GLeeInit()) glSecondaryColor3dEXT(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3DEXTPROC GLeeFuncPtr_glSecondaryColor3dEXT=GLee_Lazy_glSecondaryColor3dEXT; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3dvEXT +#define GLEE_C_DEFINED_glSecondaryColor3dvEXT + void __stdcall GLee_Lazy_glSecondaryColor3dvEXT(const GLdouble * v) {if (GLeeInit()) glSecondaryColor3dvEXT(v);} + GLEEPFNGLSECONDARYCOLOR3DVEXTPROC GLeeFuncPtr_glSecondaryColor3dvEXT=GLee_Lazy_glSecondaryColor3dvEXT; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3fEXT +#define GLEE_C_DEFINED_glSecondaryColor3fEXT + void __stdcall GLee_Lazy_glSecondaryColor3fEXT(GLfloat red, GLfloat green, GLfloat blue) {if (GLeeInit()) glSecondaryColor3fEXT(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3FEXTPROC GLeeFuncPtr_glSecondaryColor3fEXT=GLee_Lazy_glSecondaryColor3fEXT; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3fvEXT +#define GLEE_C_DEFINED_glSecondaryColor3fvEXT + void __stdcall GLee_Lazy_glSecondaryColor3fvEXT(const GLfloat * v) {if (GLeeInit()) glSecondaryColor3fvEXT(v);} + GLEEPFNGLSECONDARYCOLOR3FVEXTPROC GLeeFuncPtr_glSecondaryColor3fvEXT=GLee_Lazy_glSecondaryColor3fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3iEXT +#define GLEE_C_DEFINED_glSecondaryColor3iEXT + void __stdcall GLee_Lazy_glSecondaryColor3iEXT(GLint red, GLint green, GLint blue) {if (GLeeInit()) glSecondaryColor3iEXT(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3IEXTPROC GLeeFuncPtr_glSecondaryColor3iEXT=GLee_Lazy_glSecondaryColor3iEXT; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3ivEXT +#define GLEE_C_DEFINED_glSecondaryColor3ivEXT + void __stdcall GLee_Lazy_glSecondaryColor3ivEXT(const GLint * v) {if (GLeeInit()) glSecondaryColor3ivEXT(v);} + GLEEPFNGLSECONDARYCOLOR3IVEXTPROC GLeeFuncPtr_glSecondaryColor3ivEXT=GLee_Lazy_glSecondaryColor3ivEXT; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3sEXT +#define GLEE_C_DEFINED_glSecondaryColor3sEXT + void __stdcall GLee_Lazy_glSecondaryColor3sEXT(GLshort red, GLshort green, GLshort blue) {if (GLeeInit()) glSecondaryColor3sEXT(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3SEXTPROC GLeeFuncPtr_glSecondaryColor3sEXT=GLee_Lazy_glSecondaryColor3sEXT; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3svEXT +#define GLEE_C_DEFINED_glSecondaryColor3svEXT + void __stdcall GLee_Lazy_glSecondaryColor3svEXT(const GLshort * v) {if (GLeeInit()) glSecondaryColor3svEXT(v);} + GLEEPFNGLSECONDARYCOLOR3SVEXTPROC GLeeFuncPtr_glSecondaryColor3svEXT=GLee_Lazy_glSecondaryColor3svEXT; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3ubEXT +#define GLEE_C_DEFINED_glSecondaryColor3ubEXT + void __stdcall GLee_Lazy_glSecondaryColor3ubEXT(GLubyte red, GLubyte green, GLubyte blue) {if (GLeeInit()) glSecondaryColor3ubEXT(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3UBEXTPROC GLeeFuncPtr_glSecondaryColor3ubEXT=GLee_Lazy_glSecondaryColor3ubEXT; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3ubvEXT +#define GLEE_C_DEFINED_glSecondaryColor3ubvEXT + void __stdcall GLee_Lazy_glSecondaryColor3ubvEXT(const GLubyte * v) {if (GLeeInit()) glSecondaryColor3ubvEXT(v);} + GLEEPFNGLSECONDARYCOLOR3UBVEXTPROC GLeeFuncPtr_glSecondaryColor3ubvEXT=GLee_Lazy_glSecondaryColor3ubvEXT; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3uiEXT +#define GLEE_C_DEFINED_glSecondaryColor3uiEXT + void __stdcall GLee_Lazy_glSecondaryColor3uiEXT(GLuint red, GLuint green, GLuint blue) {if (GLeeInit()) glSecondaryColor3uiEXT(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3UIEXTPROC GLeeFuncPtr_glSecondaryColor3uiEXT=GLee_Lazy_glSecondaryColor3uiEXT; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3uivEXT +#define GLEE_C_DEFINED_glSecondaryColor3uivEXT + void __stdcall GLee_Lazy_glSecondaryColor3uivEXT(const GLuint * v) {if (GLeeInit()) glSecondaryColor3uivEXT(v);} + GLEEPFNGLSECONDARYCOLOR3UIVEXTPROC GLeeFuncPtr_glSecondaryColor3uivEXT=GLee_Lazy_glSecondaryColor3uivEXT; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3usEXT +#define GLEE_C_DEFINED_glSecondaryColor3usEXT + void __stdcall GLee_Lazy_glSecondaryColor3usEXT(GLushort red, GLushort green, GLushort blue) {if (GLeeInit()) glSecondaryColor3usEXT(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3USEXTPROC GLeeFuncPtr_glSecondaryColor3usEXT=GLee_Lazy_glSecondaryColor3usEXT; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3usvEXT +#define GLEE_C_DEFINED_glSecondaryColor3usvEXT + void __stdcall GLee_Lazy_glSecondaryColor3usvEXT(const GLushort * v) {if (GLeeInit()) glSecondaryColor3usvEXT(v);} + GLEEPFNGLSECONDARYCOLOR3USVEXTPROC GLeeFuncPtr_glSecondaryColor3usvEXT=GLee_Lazy_glSecondaryColor3usvEXT; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColorPointerEXT +#define GLEE_C_DEFINED_glSecondaryColorPointerEXT + void __stdcall GLee_Lazy_glSecondaryColorPointerEXT(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {if (GLeeInit()) glSecondaryColorPointerEXT(size, type, stride, pointer);} + GLEEPFNGLSECONDARYCOLORPOINTEREXTPROC GLeeFuncPtr_glSecondaryColorPointerEXT=GLee_Lazy_glSecondaryColorPointerEXT; +#endif +#endif + +/* GL_EXT_texture_perturb_normal */ + +#ifdef __GLEE_GL_EXT_texture_perturb_normal +#ifndef GLEE_C_DEFINED_glTextureNormalEXT +#define GLEE_C_DEFINED_glTextureNormalEXT + void __stdcall GLee_Lazy_glTextureNormalEXT(GLenum mode) {if (GLeeInit()) glTextureNormalEXT(mode);} + GLEEPFNGLTEXTURENORMALEXTPROC GLeeFuncPtr_glTextureNormalEXT=GLee_Lazy_glTextureNormalEXT; +#endif +#endif + +/* GL_EXT_multi_draw_arrays */ + +#ifdef __GLEE_GL_EXT_multi_draw_arrays +#ifndef GLEE_C_DEFINED_glMultiDrawArraysEXT +#define GLEE_C_DEFINED_glMultiDrawArraysEXT + void __stdcall GLee_Lazy_glMultiDrawArraysEXT(GLenum mode, GLint * first, GLsizei * count, GLsizei primcount) {if (GLeeInit()) glMultiDrawArraysEXT(mode, first, count, primcount);} + GLEEPFNGLMULTIDRAWARRAYSEXTPROC GLeeFuncPtr_glMultiDrawArraysEXT=GLee_Lazy_glMultiDrawArraysEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiDrawElementsEXT +#define GLEE_C_DEFINED_glMultiDrawElementsEXT + void __stdcall GLee_Lazy_glMultiDrawElementsEXT(GLenum mode, const GLsizei * count, GLenum type, const GLvoid* * indices, GLsizei primcount) {if (GLeeInit()) glMultiDrawElementsEXT(mode, count, type, indices, primcount);} + GLEEPFNGLMULTIDRAWELEMENTSEXTPROC GLeeFuncPtr_glMultiDrawElementsEXT=GLee_Lazy_glMultiDrawElementsEXT; +#endif +#endif + +/* GL_EXT_fog_coord */ + +#ifdef __GLEE_GL_EXT_fog_coord +#ifndef GLEE_C_DEFINED_glFogCoordfEXT +#define GLEE_C_DEFINED_glFogCoordfEXT + void __stdcall GLee_Lazy_glFogCoordfEXT(GLfloat coord) {if (GLeeInit()) glFogCoordfEXT(coord);} + GLEEPFNGLFOGCOORDFEXTPROC GLeeFuncPtr_glFogCoordfEXT=GLee_Lazy_glFogCoordfEXT; +#endif +#ifndef GLEE_C_DEFINED_glFogCoordfvEXT +#define GLEE_C_DEFINED_glFogCoordfvEXT + void __stdcall GLee_Lazy_glFogCoordfvEXT(const GLfloat * coord) {if (GLeeInit()) glFogCoordfvEXT(coord);} + GLEEPFNGLFOGCOORDFVEXTPROC GLeeFuncPtr_glFogCoordfvEXT=GLee_Lazy_glFogCoordfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glFogCoorddEXT +#define GLEE_C_DEFINED_glFogCoorddEXT + void __stdcall GLee_Lazy_glFogCoorddEXT(GLdouble coord) {if (GLeeInit()) glFogCoorddEXT(coord);} + GLEEPFNGLFOGCOORDDEXTPROC GLeeFuncPtr_glFogCoorddEXT=GLee_Lazy_glFogCoorddEXT; +#endif +#ifndef GLEE_C_DEFINED_glFogCoorddvEXT +#define GLEE_C_DEFINED_glFogCoorddvEXT + void __stdcall GLee_Lazy_glFogCoorddvEXT(const GLdouble * coord) {if (GLeeInit()) glFogCoorddvEXT(coord);} + GLEEPFNGLFOGCOORDDVEXTPROC GLeeFuncPtr_glFogCoorddvEXT=GLee_Lazy_glFogCoorddvEXT; +#endif +#ifndef GLEE_C_DEFINED_glFogCoordPointerEXT +#define GLEE_C_DEFINED_glFogCoordPointerEXT + void __stdcall GLee_Lazy_glFogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid * pointer) {if (GLeeInit()) glFogCoordPointerEXT(type, stride, pointer);} + GLEEPFNGLFOGCOORDPOINTEREXTPROC GLeeFuncPtr_glFogCoordPointerEXT=GLee_Lazy_glFogCoordPointerEXT; +#endif +#endif + +/* GL_REND_screen_coordinates */ + +#ifdef __GLEE_GL_REND_screen_coordinates +#endif + +/* GL_EXT_coordinate_frame */ + +#ifdef __GLEE_GL_EXT_coordinate_frame +#ifndef GLEE_C_DEFINED_glTangent3bEXT +#define GLEE_C_DEFINED_glTangent3bEXT + void __stdcall GLee_Lazy_glTangent3bEXT(GLbyte tx, GLbyte ty, GLbyte tz) {if (GLeeInit()) glTangent3bEXT(tx, ty, tz);} + GLEEPFNGLTANGENT3BEXTPROC GLeeFuncPtr_glTangent3bEXT=GLee_Lazy_glTangent3bEXT; +#endif +#ifndef GLEE_C_DEFINED_glTangent3bvEXT +#define GLEE_C_DEFINED_glTangent3bvEXT + void __stdcall GLee_Lazy_glTangent3bvEXT(const GLbyte * v) {if (GLeeInit()) glTangent3bvEXT(v);} + GLEEPFNGLTANGENT3BVEXTPROC GLeeFuncPtr_glTangent3bvEXT=GLee_Lazy_glTangent3bvEXT; +#endif +#ifndef GLEE_C_DEFINED_glTangent3dEXT +#define GLEE_C_DEFINED_glTangent3dEXT + void __stdcall GLee_Lazy_glTangent3dEXT(GLdouble tx, GLdouble ty, GLdouble tz) {if (GLeeInit()) glTangent3dEXT(tx, ty, tz);} + GLEEPFNGLTANGENT3DEXTPROC GLeeFuncPtr_glTangent3dEXT=GLee_Lazy_glTangent3dEXT; +#endif +#ifndef GLEE_C_DEFINED_glTangent3dvEXT +#define GLEE_C_DEFINED_glTangent3dvEXT + void __stdcall GLee_Lazy_glTangent3dvEXT(const GLdouble * v) {if (GLeeInit()) glTangent3dvEXT(v);} + GLEEPFNGLTANGENT3DVEXTPROC GLeeFuncPtr_glTangent3dvEXT=GLee_Lazy_glTangent3dvEXT; +#endif +#ifndef GLEE_C_DEFINED_glTangent3fEXT +#define GLEE_C_DEFINED_glTangent3fEXT + void __stdcall GLee_Lazy_glTangent3fEXT(GLfloat tx, GLfloat ty, GLfloat tz) {if (GLeeInit()) glTangent3fEXT(tx, ty, tz);} + GLEEPFNGLTANGENT3FEXTPROC GLeeFuncPtr_glTangent3fEXT=GLee_Lazy_glTangent3fEXT; +#endif +#ifndef GLEE_C_DEFINED_glTangent3fvEXT +#define GLEE_C_DEFINED_glTangent3fvEXT + void __stdcall GLee_Lazy_glTangent3fvEXT(const GLfloat * v) {if (GLeeInit()) glTangent3fvEXT(v);} + GLEEPFNGLTANGENT3FVEXTPROC GLeeFuncPtr_glTangent3fvEXT=GLee_Lazy_glTangent3fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glTangent3iEXT +#define GLEE_C_DEFINED_glTangent3iEXT + void __stdcall GLee_Lazy_glTangent3iEXT(GLint tx, GLint ty, GLint tz) {if (GLeeInit()) glTangent3iEXT(tx, ty, tz);} + GLEEPFNGLTANGENT3IEXTPROC GLeeFuncPtr_glTangent3iEXT=GLee_Lazy_glTangent3iEXT; +#endif +#ifndef GLEE_C_DEFINED_glTangent3ivEXT +#define GLEE_C_DEFINED_glTangent3ivEXT + void __stdcall GLee_Lazy_glTangent3ivEXT(const GLint * v) {if (GLeeInit()) glTangent3ivEXT(v);} + GLEEPFNGLTANGENT3IVEXTPROC GLeeFuncPtr_glTangent3ivEXT=GLee_Lazy_glTangent3ivEXT; +#endif +#ifndef GLEE_C_DEFINED_glTangent3sEXT +#define GLEE_C_DEFINED_glTangent3sEXT + void __stdcall GLee_Lazy_glTangent3sEXT(GLshort tx, GLshort ty, GLshort tz) {if (GLeeInit()) glTangent3sEXT(tx, ty, tz);} + GLEEPFNGLTANGENT3SEXTPROC GLeeFuncPtr_glTangent3sEXT=GLee_Lazy_glTangent3sEXT; +#endif +#ifndef GLEE_C_DEFINED_glTangent3svEXT +#define GLEE_C_DEFINED_glTangent3svEXT + void __stdcall GLee_Lazy_glTangent3svEXT(const GLshort * v) {if (GLeeInit()) glTangent3svEXT(v);} + GLEEPFNGLTANGENT3SVEXTPROC GLeeFuncPtr_glTangent3svEXT=GLee_Lazy_glTangent3svEXT; +#endif +#ifndef GLEE_C_DEFINED_glBinormal3bEXT +#define GLEE_C_DEFINED_glBinormal3bEXT + void __stdcall GLee_Lazy_glBinormal3bEXT(GLbyte bx, GLbyte by, GLbyte bz) {if (GLeeInit()) glBinormal3bEXT(bx, by, bz);} + GLEEPFNGLBINORMAL3BEXTPROC GLeeFuncPtr_glBinormal3bEXT=GLee_Lazy_glBinormal3bEXT; +#endif +#ifndef GLEE_C_DEFINED_glBinormal3bvEXT +#define GLEE_C_DEFINED_glBinormal3bvEXT + void __stdcall GLee_Lazy_glBinormal3bvEXT(const GLbyte * v) {if (GLeeInit()) glBinormal3bvEXT(v);} + GLEEPFNGLBINORMAL3BVEXTPROC GLeeFuncPtr_glBinormal3bvEXT=GLee_Lazy_glBinormal3bvEXT; +#endif +#ifndef GLEE_C_DEFINED_glBinormal3dEXT +#define GLEE_C_DEFINED_glBinormal3dEXT + void __stdcall GLee_Lazy_glBinormal3dEXT(GLdouble bx, GLdouble by, GLdouble bz) {if (GLeeInit()) glBinormal3dEXT(bx, by, bz);} + GLEEPFNGLBINORMAL3DEXTPROC GLeeFuncPtr_glBinormal3dEXT=GLee_Lazy_glBinormal3dEXT; +#endif +#ifndef GLEE_C_DEFINED_glBinormal3dvEXT +#define GLEE_C_DEFINED_glBinormal3dvEXT + void __stdcall GLee_Lazy_glBinormal3dvEXT(const GLdouble * v) {if (GLeeInit()) glBinormal3dvEXT(v);} + GLEEPFNGLBINORMAL3DVEXTPROC GLeeFuncPtr_glBinormal3dvEXT=GLee_Lazy_glBinormal3dvEXT; +#endif +#ifndef GLEE_C_DEFINED_glBinormal3fEXT +#define GLEE_C_DEFINED_glBinormal3fEXT + void __stdcall GLee_Lazy_glBinormal3fEXT(GLfloat bx, GLfloat by, GLfloat bz) {if (GLeeInit()) glBinormal3fEXT(bx, by, bz);} + GLEEPFNGLBINORMAL3FEXTPROC GLeeFuncPtr_glBinormal3fEXT=GLee_Lazy_glBinormal3fEXT; +#endif +#ifndef GLEE_C_DEFINED_glBinormal3fvEXT +#define GLEE_C_DEFINED_glBinormal3fvEXT + void __stdcall GLee_Lazy_glBinormal3fvEXT(const GLfloat * v) {if (GLeeInit()) glBinormal3fvEXT(v);} + GLEEPFNGLBINORMAL3FVEXTPROC GLeeFuncPtr_glBinormal3fvEXT=GLee_Lazy_glBinormal3fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glBinormal3iEXT +#define GLEE_C_DEFINED_glBinormal3iEXT + void __stdcall GLee_Lazy_glBinormal3iEXT(GLint bx, GLint by, GLint bz) {if (GLeeInit()) glBinormal3iEXT(bx, by, bz);} + GLEEPFNGLBINORMAL3IEXTPROC GLeeFuncPtr_glBinormal3iEXT=GLee_Lazy_glBinormal3iEXT; +#endif +#ifndef GLEE_C_DEFINED_glBinormal3ivEXT +#define GLEE_C_DEFINED_glBinormal3ivEXT + void __stdcall GLee_Lazy_glBinormal3ivEXT(const GLint * v) {if (GLeeInit()) glBinormal3ivEXT(v);} + GLEEPFNGLBINORMAL3IVEXTPROC GLeeFuncPtr_glBinormal3ivEXT=GLee_Lazy_glBinormal3ivEXT; +#endif +#ifndef GLEE_C_DEFINED_glBinormal3sEXT +#define GLEE_C_DEFINED_glBinormal3sEXT + void __stdcall GLee_Lazy_glBinormal3sEXT(GLshort bx, GLshort by, GLshort bz) {if (GLeeInit()) glBinormal3sEXT(bx, by, bz);} + GLEEPFNGLBINORMAL3SEXTPROC GLeeFuncPtr_glBinormal3sEXT=GLee_Lazy_glBinormal3sEXT; +#endif +#ifndef GLEE_C_DEFINED_glBinormal3svEXT +#define GLEE_C_DEFINED_glBinormal3svEXT + void __stdcall GLee_Lazy_glBinormal3svEXT(const GLshort * v) {if (GLeeInit()) glBinormal3svEXT(v);} + GLEEPFNGLBINORMAL3SVEXTPROC GLeeFuncPtr_glBinormal3svEXT=GLee_Lazy_glBinormal3svEXT; +#endif +#ifndef GLEE_C_DEFINED_glTangentPointerEXT +#define GLEE_C_DEFINED_glTangentPointerEXT + void __stdcall GLee_Lazy_glTangentPointerEXT(GLenum type, GLsizei stride, const GLvoid * pointer) {if (GLeeInit()) glTangentPointerEXT(type, stride, pointer);} + GLEEPFNGLTANGENTPOINTEREXTPROC GLeeFuncPtr_glTangentPointerEXT=GLee_Lazy_glTangentPointerEXT; +#endif +#ifndef GLEE_C_DEFINED_glBinormalPointerEXT +#define GLEE_C_DEFINED_glBinormalPointerEXT + void __stdcall GLee_Lazy_glBinormalPointerEXT(GLenum type, GLsizei stride, const GLvoid * pointer) {if (GLeeInit()) glBinormalPointerEXT(type, stride, pointer);} + GLEEPFNGLBINORMALPOINTEREXTPROC GLeeFuncPtr_glBinormalPointerEXT=GLee_Lazy_glBinormalPointerEXT; +#endif +#endif + +/* GL_EXT_texture_env_combine */ + +#ifdef __GLEE_GL_EXT_texture_env_combine +#endif + +/* GL_APPLE_specular_vector */ + +#ifdef __GLEE_GL_APPLE_specular_vector +#endif + +/* GL_APPLE_transform_hint */ + +#ifdef __GLEE_GL_APPLE_transform_hint +#endif + +/* GL_SGIX_fog_scale */ + +#ifdef __GLEE_GL_SGIX_fog_scale +#endif + +/* GL_SUNX_constant_data */ + +#ifdef __GLEE_GL_SUNX_constant_data +#ifndef GLEE_C_DEFINED_glFinishTextureSUNX +#define GLEE_C_DEFINED_glFinishTextureSUNX + void __stdcall GLee_Lazy_glFinishTextureSUNX(void) {if (GLeeInit()) glFinishTextureSUNX();} + GLEEPFNGLFINISHTEXTURESUNXPROC GLeeFuncPtr_glFinishTextureSUNX=GLee_Lazy_glFinishTextureSUNX; +#endif +#endif + +/* GL_SUN_global_alpha */ + +#ifdef __GLEE_GL_SUN_global_alpha +#ifndef GLEE_C_DEFINED_glGlobalAlphaFactorbSUN +#define GLEE_C_DEFINED_glGlobalAlphaFactorbSUN + void __stdcall GLee_Lazy_glGlobalAlphaFactorbSUN(GLbyte factor) {if (GLeeInit()) glGlobalAlphaFactorbSUN(factor);} + GLEEPFNGLGLOBALALPHAFACTORBSUNPROC GLeeFuncPtr_glGlobalAlphaFactorbSUN=GLee_Lazy_glGlobalAlphaFactorbSUN; +#endif +#ifndef GLEE_C_DEFINED_glGlobalAlphaFactorsSUN +#define GLEE_C_DEFINED_glGlobalAlphaFactorsSUN + void __stdcall GLee_Lazy_glGlobalAlphaFactorsSUN(GLshort factor) {if (GLeeInit()) glGlobalAlphaFactorsSUN(factor);} + GLEEPFNGLGLOBALALPHAFACTORSSUNPROC GLeeFuncPtr_glGlobalAlphaFactorsSUN=GLee_Lazy_glGlobalAlphaFactorsSUN; +#endif +#ifndef GLEE_C_DEFINED_glGlobalAlphaFactoriSUN +#define GLEE_C_DEFINED_glGlobalAlphaFactoriSUN + void __stdcall GLee_Lazy_glGlobalAlphaFactoriSUN(GLint factor) {if (GLeeInit()) glGlobalAlphaFactoriSUN(factor);} + GLEEPFNGLGLOBALALPHAFACTORISUNPROC GLeeFuncPtr_glGlobalAlphaFactoriSUN=GLee_Lazy_glGlobalAlphaFactoriSUN; +#endif +#ifndef GLEE_C_DEFINED_glGlobalAlphaFactorfSUN +#define GLEE_C_DEFINED_glGlobalAlphaFactorfSUN + void __stdcall GLee_Lazy_glGlobalAlphaFactorfSUN(GLfloat factor) {if (GLeeInit()) glGlobalAlphaFactorfSUN(factor);} + GLEEPFNGLGLOBALALPHAFACTORFSUNPROC GLeeFuncPtr_glGlobalAlphaFactorfSUN=GLee_Lazy_glGlobalAlphaFactorfSUN; +#endif +#ifndef GLEE_C_DEFINED_glGlobalAlphaFactordSUN +#define GLEE_C_DEFINED_glGlobalAlphaFactordSUN + void __stdcall GLee_Lazy_glGlobalAlphaFactordSUN(GLdouble factor) {if (GLeeInit()) glGlobalAlphaFactordSUN(factor);} + GLEEPFNGLGLOBALALPHAFACTORDSUNPROC GLeeFuncPtr_glGlobalAlphaFactordSUN=GLee_Lazy_glGlobalAlphaFactordSUN; +#endif +#ifndef GLEE_C_DEFINED_glGlobalAlphaFactorubSUN +#define GLEE_C_DEFINED_glGlobalAlphaFactorubSUN + void __stdcall GLee_Lazy_glGlobalAlphaFactorubSUN(GLubyte factor) {if (GLeeInit()) glGlobalAlphaFactorubSUN(factor);} + GLEEPFNGLGLOBALALPHAFACTORUBSUNPROC GLeeFuncPtr_glGlobalAlphaFactorubSUN=GLee_Lazy_glGlobalAlphaFactorubSUN; +#endif +#ifndef GLEE_C_DEFINED_glGlobalAlphaFactorusSUN +#define GLEE_C_DEFINED_glGlobalAlphaFactorusSUN + void __stdcall GLee_Lazy_glGlobalAlphaFactorusSUN(GLushort factor) {if (GLeeInit()) glGlobalAlphaFactorusSUN(factor);} + GLEEPFNGLGLOBALALPHAFACTORUSSUNPROC GLeeFuncPtr_glGlobalAlphaFactorusSUN=GLee_Lazy_glGlobalAlphaFactorusSUN; +#endif +#ifndef GLEE_C_DEFINED_glGlobalAlphaFactoruiSUN +#define GLEE_C_DEFINED_glGlobalAlphaFactoruiSUN + void __stdcall GLee_Lazy_glGlobalAlphaFactoruiSUN(GLuint factor) {if (GLeeInit()) glGlobalAlphaFactoruiSUN(factor);} + GLEEPFNGLGLOBALALPHAFACTORUISUNPROC GLeeFuncPtr_glGlobalAlphaFactoruiSUN=GLee_Lazy_glGlobalAlphaFactoruiSUN; +#endif +#endif + +/* GL_SUN_triangle_list */ + +#ifdef __GLEE_GL_SUN_triangle_list +#ifndef GLEE_C_DEFINED_glReplacementCodeuiSUN +#define GLEE_C_DEFINED_glReplacementCodeuiSUN + void __stdcall GLee_Lazy_glReplacementCodeuiSUN(GLuint code) {if (GLeeInit()) glReplacementCodeuiSUN(code);} + GLEEPFNGLREPLACEMENTCODEUISUNPROC GLeeFuncPtr_glReplacementCodeuiSUN=GLee_Lazy_glReplacementCodeuiSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeusSUN +#define GLEE_C_DEFINED_glReplacementCodeusSUN + void __stdcall GLee_Lazy_glReplacementCodeusSUN(GLushort code) {if (GLeeInit()) glReplacementCodeusSUN(code);} + GLEEPFNGLREPLACEMENTCODEUSSUNPROC GLeeFuncPtr_glReplacementCodeusSUN=GLee_Lazy_glReplacementCodeusSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeubSUN +#define GLEE_C_DEFINED_glReplacementCodeubSUN + void __stdcall GLee_Lazy_glReplacementCodeubSUN(GLubyte code) {if (GLeeInit()) glReplacementCodeubSUN(code);} + GLEEPFNGLREPLACEMENTCODEUBSUNPROC GLeeFuncPtr_glReplacementCodeubSUN=GLee_Lazy_glReplacementCodeubSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuivSUN +#define GLEE_C_DEFINED_glReplacementCodeuivSUN + void __stdcall GLee_Lazy_glReplacementCodeuivSUN(const GLuint * code) {if (GLeeInit()) glReplacementCodeuivSUN(code);} + GLEEPFNGLREPLACEMENTCODEUIVSUNPROC GLeeFuncPtr_glReplacementCodeuivSUN=GLee_Lazy_glReplacementCodeuivSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeusvSUN +#define GLEE_C_DEFINED_glReplacementCodeusvSUN + void __stdcall GLee_Lazy_glReplacementCodeusvSUN(const GLushort * code) {if (GLeeInit()) glReplacementCodeusvSUN(code);} + GLEEPFNGLREPLACEMENTCODEUSVSUNPROC GLeeFuncPtr_glReplacementCodeusvSUN=GLee_Lazy_glReplacementCodeusvSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeubvSUN +#define GLEE_C_DEFINED_glReplacementCodeubvSUN + void __stdcall GLee_Lazy_glReplacementCodeubvSUN(const GLubyte * code) {if (GLeeInit()) glReplacementCodeubvSUN(code);} + GLEEPFNGLREPLACEMENTCODEUBVSUNPROC GLeeFuncPtr_glReplacementCodeubvSUN=GLee_Lazy_glReplacementCodeubvSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodePointerSUN +#define GLEE_C_DEFINED_glReplacementCodePointerSUN + void __stdcall GLee_Lazy_glReplacementCodePointerSUN(GLenum type, GLsizei stride, const GLvoid* * pointer) {if (GLeeInit()) glReplacementCodePointerSUN(type, stride, pointer);} + GLEEPFNGLREPLACEMENTCODEPOINTERSUNPROC GLeeFuncPtr_glReplacementCodePointerSUN=GLee_Lazy_glReplacementCodePointerSUN; +#endif +#endif + +/* GL_SUN_vertex */ + +#ifdef __GLEE_GL_SUN_vertex +#ifndef GLEE_C_DEFINED_glColor4ubVertex2fSUN +#define GLEE_C_DEFINED_glColor4ubVertex2fSUN + void __stdcall GLee_Lazy_glColor4ubVertex2fSUN(GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y) {if (GLeeInit()) glColor4ubVertex2fSUN(r, g, b, a, x, y);} + GLEEPFNGLCOLOR4UBVERTEX2FSUNPROC GLeeFuncPtr_glColor4ubVertex2fSUN=GLee_Lazy_glColor4ubVertex2fSUN; +#endif +#ifndef GLEE_C_DEFINED_glColor4ubVertex2fvSUN +#define GLEE_C_DEFINED_glColor4ubVertex2fvSUN + void __stdcall GLee_Lazy_glColor4ubVertex2fvSUN(const GLubyte * c, const GLfloat * v) {if (GLeeInit()) glColor4ubVertex2fvSUN(c, v);} + GLEEPFNGLCOLOR4UBVERTEX2FVSUNPROC GLeeFuncPtr_glColor4ubVertex2fvSUN=GLee_Lazy_glColor4ubVertex2fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glColor4ubVertex3fSUN +#define GLEE_C_DEFINED_glColor4ubVertex3fSUN + void __stdcall GLee_Lazy_glColor4ubVertex3fSUN(GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glColor4ubVertex3fSUN(r, g, b, a, x, y, z);} + GLEEPFNGLCOLOR4UBVERTEX3FSUNPROC GLeeFuncPtr_glColor4ubVertex3fSUN=GLee_Lazy_glColor4ubVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glColor4ubVertex3fvSUN +#define GLEE_C_DEFINED_glColor4ubVertex3fvSUN + void __stdcall GLee_Lazy_glColor4ubVertex3fvSUN(const GLubyte * c, const GLfloat * v) {if (GLeeInit()) glColor4ubVertex3fvSUN(c, v);} + GLEEPFNGLCOLOR4UBVERTEX3FVSUNPROC GLeeFuncPtr_glColor4ubVertex3fvSUN=GLee_Lazy_glColor4ubVertex3fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glColor3fVertex3fSUN +#define GLEE_C_DEFINED_glColor3fVertex3fSUN + void __stdcall GLee_Lazy_glColor3fVertex3fSUN(GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glColor3fVertex3fSUN(r, g, b, x, y, z);} + GLEEPFNGLCOLOR3FVERTEX3FSUNPROC GLeeFuncPtr_glColor3fVertex3fSUN=GLee_Lazy_glColor3fVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glColor3fVertex3fvSUN +#define GLEE_C_DEFINED_glColor3fVertex3fvSUN + void __stdcall GLee_Lazy_glColor3fVertex3fvSUN(const GLfloat * c, const GLfloat * v) {if (GLeeInit()) glColor3fVertex3fvSUN(c, v);} + GLEEPFNGLCOLOR3FVERTEX3FVSUNPROC GLeeFuncPtr_glColor3fVertex3fvSUN=GLee_Lazy_glColor3fVertex3fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glNormal3fVertex3fSUN +#define GLEE_C_DEFINED_glNormal3fVertex3fSUN + void __stdcall GLee_Lazy_glNormal3fVertex3fSUN(GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glNormal3fVertex3fSUN(nx, ny, nz, x, y, z);} + GLEEPFNGLNORMAL3FVERTEX3FSUNPROC GLeeFuncPtr_glNormal3fVertex3fSUN=GLee_Lazy_glNormal3fVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glNormal3fVertex3fvSUN +#define GLEE_C_DEFINED_glNormal3fVertex3fvSUN + void __stdcall GLee_Lazy_glNormal3fVertex3fvSUN(const GLfloat * n, const GLfloat * v) {if (GLeeInit()) glNormal3fVertex3fvSUN(n, v);} + GLEEPFNGLNORMAL3FVERTEX3FVSUNPROC GLeeFuncPtr_glNormal3fVertex3fvSUN=GLee_Lazy_glNormal3fVertex3fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glColor4fNormal3fVertex3fSUN +#define GLEE_C_DEFINED_glColor4fNormal3fVertex3fSUN + void __stdcall GLee_Lazy_glColor4fNormal3fVertex3fSUN(GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glColor4fNormal3fVertex3fSUN(r, g, b, a, nx, ny, nz, x, y, z);} + GLEEPFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC GLeeFuncPtr_glColor4fNormal3fVertex3fSUN=GLee_Lazy_glColor4fNormal3fVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glColor4fNormal3fVertex3fvSUN +#define GLEE_C_DEFINED_glColor4fNormal3fVertex3fvSUN + void __stdcall GLee_Lazy_glColor4fNormal3fVertex3fvSUN(const GLfloat * c, const GLfloat * n, const GLfloat * v) {if (GLeeInit()) glColor4fNormal3fVertex3fvSUN(c, n, v);} + GLEEPFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC GLeeFuncPtr_glColor4fNormal3fVertex3fvSUN=GLee_Lazy_glColor4fNormal3fVertex3fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord2fVertex3fSUN +#define GLEE_C_DEFINED_glTexCoord2fVertex3fSUN + void __stdcall GLee_Lazy_glTexCoord2fVertex3fSUN(GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glTexCoord2fVertex3fSUN(s, t, x, y, z);} + GLEEPFNGLTEXCOORD2FVERTEX3FSUNPROC GLeeFuncPtr_glTexCoord2fVertex3fSUN=GLee_Lazy_glTexCoord2fVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord2fVertex3fvSUN +#define GLEE_C_DEFINED_glTexCoord2fVertex3fvSUN + void __stdcall GLee_Lazy_glTexCoord2fVertex3fvSUN(const GLfloat * tc, const GLfloat * v) {if (GLeeInit()) glTexCoord2fVertex3fvSUN(tc, v);} + GLEEPFNGLTEXCOORD2FVERTEX3FVSUNPROC GLeeFuncPtr_glTexCoord2fVertex3fvSUN=GLee_Lazy_glTexCoord2fVertex3fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord4fVertex4fSUN +#define GLEE_C_DEFINED_glTexCoord4fVertex4fSUN + void __stdcall GLee_Lazy_glTexCoord4fVertex4fSUN(GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {if (GLeeInit()) glTexCoord4fVertex4fSUN(s, t, p, q, x, y, z, w);} + GLEEPFNGLTEXCOORD4FVERTEX4FSUNPROC GLeeFuncPtr_glTexCoord4fVertex4fSUN=GLee_Lazy_glTexCoord4fVertex4fSUN; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord4fVertex4fvSUN +#define GLEE_C_DEFINED_glTexCoord4fVertex4fvSUN + void __stdcall GLee_Lazy_glTexCoord4fVertex4fvSUN(const GLfloat * tc, const GLfloat * v) {if (GLeeInit()) glTexCoord4fVertex4fvSUN(tc, v);} + GLEEPFNGLTEXCOORD4FVERTEX4FVSUNPROC GLeeFuncPtr_glTexCoord4fVertex4fvSUN=GLee_Lazy_glTexCoord4fVertex4fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord2fColor4ubVertex3fSUN +#define GLEE_C_DEFINED_glTexCoord2fColor4ubVertex3fSUN + void __stdcall GLee_Lazy_glTexCoord2fColor4ubVertex3fSUN(GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glTexCoord2fColor4ubVertex3fSUN(s, t, r, g, b, a, x, y, z);} + GLEEPFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC GLeeFuncPtr_glTexCoord2fColor4ubVertex3fSUN=GLee_Lazy_glTexCoord2fColor4ubVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord2fColor4ubVertex3fvSUN +#define GLEE_C_DEFINED_glTexCoord2fColor4ubVertex3fvSUN + void __stdcall GLee_Lazy_glTexCoord2fColor4ubVertex3fvSUN(const GLfloat * tc, const GLubyte * c, const GLfloat * v) {if (GLeeInit()) glTexCoord2fColor4ubVertex3fvSUN(tc, c, v);} + GLEEPFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC GLeeFuncPtr_glTexCoord2fColor4ubVertex3fvSUN=GLee_Lazy_glTexCoord2fColor4ubVertex3fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord2fColor3fVertex3fSUN +#define GLEE_C_DEFINED_glTexCoord2fColor3fVertex3fSUN + void __stdcall GLee_Lazy_glTexCoord2fColor3fVertex3fSUN(GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glTexCoord2fColor3fVertex3fSUN(s, t, r, g, b, x, y, z);} + GLEEPFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC GLeeFuncPtr_glTexCoord2fColor3fVertex3fSUN=GLee_Lazy_glTexCoord2fColor3fVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord2fColor3fVertex3fvSUN +#define GLEE_C_DEFINED_glTexCoord2fColor3fVertex3fvSUN + void __stdcall GLee_Lazy_glTexCoord2fColor3fVertex3fvSUN(const GLfloat * tc, const GLfloat * c, const GLfloat * v) {if (GLeeInit()) glTexCoord2fColor3fVertex3fvSUN(tc, c, v);} + GLEEPFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC GLeeFuncPtr_glTexCoord2fColor3fVertex3fvSUN=GLee_Lazy_glTexCoord2fColor3fVertex3fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord2fNormal3fVertex3fSUN +#define GLEE_C_DEFINED_glTexCoord2fNormal3fVertex3fSUN + void __stdcall GLee_Lazy_glTexCoord2fNormal3fVertex3fSUN(GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glTexCoord2fNormal3fVertex3fSUN(s, t, nx, ny, nz, x, y, z);} + GLEEPFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC GLeeFuncPtr_glTexCoord2fNormal3fVertex3fSUN=GLee_Lazy_glTexCoord2fNormal3fVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord2fNormal3fVertex3fvSUN +#define GLEE_C_DEFINED_glTexCoord2fNormal3fVertex3fvSUN + void __stdcall GLee_Lazy_glTexCoord2fNormal3fVertex3fvSUN(const GLfloat * tc, const GLfloat * n, const GLfloat * v) {if (GLeeInit()) glTexCoord2fNormal3fVertex3fvSUN(tc, n, v);} + GLEEPFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC GLeeFuncPtr_glTexCoord2fNormal3fVertex3fvSUN=GLee_Lazy_glTexCoord2fNormal3fVertex3fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord2fColor4fNormal3fVertex3fSUN +#define GLEE_C_DEFINED_glTexCoord2fColor4fNormal3fVertex3fSUN + void __stdcall GLee_Lazy_glTexCoord2fColor4fNormal3fVertex3fSUN(GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glTexCoord2fColor4fNormal3fVertex3fSUN(s, t, r, g, b, a, nx, ny, nz, x, y, z);} + GLEEPFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC GLeeFuncPtr_glTexCoord2fColor4fNormal3fVertex3fSUN=GLee_Lazy_glTexCoord2fColor4fNormal3fVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord2fColor4fNormal3fVertex3fvSUN +#define GLEE_C_DEFINED_glTexCoord2fColor4fNormal3fVertex3fvSUN + void __stdcall GLee_Lazy_glTexCoord2fColor4fNormal3fVertex3fvSUN(const GLfloat * tc, const GLfloat * c, const GLfloat * n, const GLfloat * v) {if (GLeeInit()) glTexCoord2fColor4fNormal3fVertex3fvSUN(tc, c, n, v);} + GLEEPFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC GLeeFuncPtr_glTexCoord2fColor4fNormal3fVertex3fvSUN=GLee_Lazy_glTexCoord2fColor4fNormal3fVertex3fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord4fColor4fNormal3fVertex4fSUN +#define GLEE_C_DEFINED_glTexCoord4fColor4fNormal3fVertex4fSUN + void __stdcall GLee_Lazy_glTexCoord4fColor4fNormal3fVertex4fSUN(GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {if (GLeeInit()) glTexCoord4fColor4fNormal3fVertex4fSUN(s, t, p, q, r, g, b, a, nx, ny, nz, x, y, z, w);} + GLEEPFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC GLeeFuncPtr_glTexCoord4fColor4fNormal3fVertex4fSUN=GLee_Lazy_glTexCoord4fColor4fNormal3fVertex4fSUN; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord4fColor4fNormal3fVertex4fvSUN +#define GLEE_C_DEFINED_glTexCoord4fColor4fNormal3fVertex4fvSUN + void __stdcall GLee_Lazy_glTexCoord4fColor4fNormal3fVertex4fvSUN(const GLfloat * tc, const GLfloat * c, const GLfloat * n, const GLfloat * v) {if (GLeeInit()) glTexCoord4fColor4fNormal3fVertex4fvSUN(tc, c, n, v);} + GLEEPFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC GLeeFuncPtr_glTexCoord4fColor4fNormal3fVertex4fvSUN=GLee_Lazy_glTexCoord4fColor4fNormal3fVertex4fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuiVertex3fSUN +#define GLEE_C_DEFINED_glReplacementCodeuiVertex3fSUN + void __stdcall GLee_Lazy_glReplacementCodeuiVertex3fSUN(GLuint rc, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glReplacementCodeuiVertex3fSUN(rc, x, y, z);} + GLEEPFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC GLeeFuncPtr_glReplacementCodeuiVertex3fSUN=GLee_Lazy_glReplacementCodeuiVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuiVertex3fvSUN +#define GLEE_C_DEFINED_glReplacementCodeuiVertex3fvSUN + void __stdcall GLee_Lazy_glReplacementCodeuiVertex3fvSUN(const GLuint * rc, const GLfloat * v) {if (GLeeInit()) glReplacementCodeuiVertex3fvSUN(rc, v);} + GLEEPFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC GLeeFuncPtr_glReplacementCodeuiVertex3fvSUN=GLee_Lazy_glReplacementCodeuiVertex3fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuiColor4ubVertex3fSUN +#define GLEE_C_DEFINED_glReplacementCodeuiColor4ubVertex3fSUN + void __stdcall GLee_Lazy_glReplacementCodeuiColor4ubVertex3fSUN(GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glReplacementCodeuiColor4ubVertex3fSUN(rc, r, g, b, a, x, y, z);} + GLEEPFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC GLeeFuncPtr_glReplacementCodeuiColor4ubVertex3fSUN=GLee_Lazy_glReplacementCodeuiColor4ubVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuiColor4ubVertex3fvSUN +#define GLEE_C_DEFINED_glReplacementCodeuiColor4ubVertex3fvSUN + void __stdcall GLee_Lazy_glReplacementCodeuiColor4ubVertex3fvSUN(const GLuint * rc, const GLubyte * c, const GLfloat * v) {if (GLeeInit()) glReplacementCodeuiColor4ubVertex3fvSUN(rc, c, v);} + GLEEPFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC GLeeFuncPtr_glReplacementCodeuiColor4ubVertex3fvSUN=GLee_Lazy_glReplacementCodeuiColor4ubVertex3fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuiColor3fVertex3fSUN +#define GLEE_C_DEFINED_glReplacementCodeuiColor3fVertex3fSUN + void __stdcall GLee_Lazy_glReplacementCodeuiColor3fVertex3fSUN(GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glReplacementCodeuiColor3fVertex3fSUN(rc, r, g, b, x, y, z);} + GLEEPFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC GLeeFuncPtr_glReplacementCodeuiColor3fVertex3fSUN=GLee_Lazy_glReplacementCodeuiColor3fVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuiColor3fVertex3fvSUN +#define GLEE_C_DEFINED_glReplacementCodeuiColor3fVertex3fvSUN + void __stdcall GLee_Lazy_glReplacementCodeuiColor3fVertex3fvSUN(const GLuint * rc, const GLfloat * c, const GLfloat * v) {if (GLeeInit()) glReplacementCodeuiColor3fVertex3fvSUN(rc, c, v);} + GLEEPFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC GLeeFuncPtr_glReplacementCodeuiColor3fVertex3fvSUN=GLee_Lazy_glReplacementCodeuiColor3fVertex3fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuiNormal3fVertex3fSUN +#define GLEE_C_DEFINED_glReplacementCodeuiNormal3fVertex3fSUN + void __stdcall GLee_Lazy_glReplacementCodeuiNormal3fVertex3fSUN(GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glReplacementCodeuiNormal3fVertex3fSUN(rc, nx, ny, nz, x, y, z);} + GLEEPFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC GLeeFuncPtr_glReplacementCodeuiNormal3fVertex3fSUN=GLee_Lazy_glReplacementCodeuiNormal3fVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuiNormal3fVertex3fvSUN +#define GLEE_C_DEFINED_glReplacementCodeuiNormal3fVertex3fvSUN + void __stdcall GLee_Lazy_glReplacementCodeuiNormal3fVertex3fvSUN(const GLuint * rc, const GLfloat * n, const GLfloat * v) {if (GLeeInit()) glReplacementCodeuiNormal3fVertex3fvSUN(rc, n, v);} + GLEEPFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC GLeeFuncPtr_glReplacementCodeuiNormal3fVertex3fvSUN=GLee_Lazy_glReplacementCodeuiNormal3fVertex3fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuiColor4fNormal3fVertex3fSUN +#define GLEE_C_DEFINED_glReplacementCodeuiColor4fNormal3fVertex3fSUN + void __stdcall GLee_Lazy_glReplacementCodeuiColor4fNormal3fVertex3fSUN(GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glReplacementCodeuiColor4fNormal3fVertex3fSUN(rc, r, g, b, a, nx, ny, nz, x, y, z);} + GLEEPFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC GLeeFuncPtr_glReplacementCodeuiColor4fNormal3fVertex3fSUN=GLee_Lazy_glReplacementCodeuiColor4fNormal3fVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuiColor4fNormal3fVertex3fvSUN +#define GLEE_C_DEFINED_glReplacementCodeuiColor4fNormal3fVertex3fvSUN + void __stdcall GLee_Lazy_glReplacementCodeuiColor4fNormal3fVertex3fvSUN(const GLuint * rc, const GLfloat * c, const GLfloat * n, const GLfloat * v) {if (GLeeInit()) glReplacementCodeuiColor4fNormal3fVertex3fvSUN(rc, c, n, v);} + GLEEPFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC GLeeFuncPtr_glReplacementCodeuiColor4fNormal3fVertex3fvSUN=GLee_Lazy_glReplacementCodeuiColor4fNormal3fVertex3fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuiTexCoord2fVertex3fSUN +#define GLEE_C_DEFINED_glReplacementCodeuiTexCoord2fVertex3fSUN + void __stdcall GLee_Lazy_glReplacementCodeuiTexCoord2fVertex3fSUN(GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glReplacementCodeuiTexCoord2fVertex3fSUN(rc, s, t, x, y, z);} + GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC GLeeFuncPtr_glReplacementCodeuiTexCoord2fVertex3fSUN=GLee_Lazy_glReplacementCodeuiTexCoord2fVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuiTexCoord2fVertex3fvSUN +#define GLEE_C_DEFINED_glReplacementCodeuiTexCoord2fVertex3fvSUN + void __stdcall GLee_Lazy_glReplacementCodeuiTexCoord2fVertex3fvSUN(const GLuint * rc, const GLfloat * tc, const GLfloat * v) {if (GLeeInit()) glReplacementCodeuiTexCoord2fVertex3fvSUN(rc, tc, v);} + GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC GLeeFuncPtr_glReplacementCodeuiTexCoord2fVertex3fvSUN=GLee_Lazy_glReplacementCodeuiTexCoord2fVertex3fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN +#define GLEE_C_DEFINED_glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN + void __stdcall GLee_Lazy_glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN(GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN(rc, s, t, nx, ny, nz, x, y, z);} + GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC GLeeFuncPtr_glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN=GLee_Lazy_glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN +#define GLEE_C_DEFINED_glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN + void __stdcall GLee_Lazy_glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN(const GLuint * rc, const GLfloat * tc, const GLfloat * n, const GLfloat * v) {if (GLeeInit()) glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN(rc, tc, n, v);} + GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC GLeeFuncPtr_glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN=GLee_Lazy_glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN +#define GLEE_C_DEFINED_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN + void __stdcall GLee_Lazy_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN(GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN(rc, s, t, r, g, b, a, nx, ny, nz, x, y, z);} + GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC GLeeFuncPtr_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN=GLee_Lazy_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN; +#endif +#ifndef GLEE_C_DEFINED_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN +#define GLEE_C_DEFINED_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN + void __stdcall GLee_Lazy_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN(const GLuint * rc, const GLfloat * tc, const GLfloat * c, const GLfloat * n, const GLfloat * v) {if (GLeeInit()) glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN(rc, tc, c, n, v);} + GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC GLeeFuncPtr_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN=GLee_Lazy_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN; +#endif +#endif + +/* GL_EXT_blend_func_separate */ + +#ifdef __GLEE_GL_EXT_blend_func_separate +#ifndef GLEE_C_DEFINED_glBlendFuncSeparateEXT +#define GLEE_C_DEFINED_glBlendFuncSeparateEXT + void __stdcall GLee_Lazy_glBlendFuncSeparateEXT(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) {if (GLeeInit()) glBlendFuncSeparateEXT(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);} + GLEEPFNGLBLENDFUNCSEPARATEEXTPROC GLeeFuncPtr_glBlendFuncSeparateEXT=GLee_Lazy_glBlendFuncSeparateEXT; +#endif +#endif + +/* GL_INGR_color_clamp */ + +#ifdef __GLEE_GL_INGR_color_clamp +#endif + +/* GL_INGR_interlace_read */ + +#ifdef __GLEE_GL_INGR_interlace_read +#endif + +/* GL_EXT_stencil_wrap */ + +#ifdef __GLEE_GL_EXT_stencil_wrap +#endif + +/* GL_EXT_422_pixels */ + +#ifdef __GLEE_GL_EXT_422_pixels +#endif + +/* GL_NV_texgen_reflection */ + +#ifdef __GLEE_GL_NV_texgen_reflection +#endif + +/* GL_EXT_texture_cube_map */ + +#ifdef __GLEE_GL_EXT_texture_cube_map +#endif + +/* GL_SUN_convolution_border_modes */ + +#ifdef __GLEE_GL_SUN_convolution_border_modes +#endif + +/* GL_EXT_texture_env_add */ + +#ifdef __GLEE_GL_EXT_texture_env_add +#endif + +/* GL_EXT_texture_lod_bias */ + +#ifdef __GLEE_GL_EXT_texture_lod_bias +#endif + +/* GL_EXT_texture_filter_anisotropic */ + +#ifdef __GLEE_GL_EXT_texture_filter_anisotropic +#endif + +/* GL_EXT_vertex_weighting */ + +#ifdef __GLEE_GL_EXT_vertex_weighting +#ifndef GLEE_C_DEFINED_glVertexWeightfEXT +#define GLEE_C_DEFINED_glVertexWeightfEXT + void __stdcall GLee_Lazy_glVertexWeightfEXT(GLfloat weight) {if (GLeeInit()) glVertexWeightfEXT(weight);} + GLEEPFNGLVERTEXWEIGHTFEXTPROC GLeeFuncPtr_glVertexWeightfEXT=GLee_Lazy_glVertexWeightfEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexWeightfvEXT +#define GLEE_C_DEFINED_glVertexWeightfvEXT + void __stdcall GLee_Lazy_glVertexWeightfvEXT(const GLfloat * weight) {if (GLeeInit()) glVertexWeightfvEXT(weight);} + GLEEPFNGLVERTEXWEIGHTFVEXTPROC GLeeFuncPtr_glVertexWeightfvEXT=GLee_Lazy_glVertexWeightfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexWeightPointerEXT +#define GLEE_C_DEFINED_glVertexWeightPointerEXT + void __stdcall GLee_Lazy_glVertexWeightPointerEXT(GLsizei size, GLenum type, GLsizei stride, const GLvoid * pointer) {if (GLeeInit()) glVertexWeightPointerEXT(size, type, stride, pointer);} + GLEEPFNGLVERTEXWEIGHTPOINTEREXTPROC GLeeFuncPtr_glVertexWeightPointerEXT=GLee_Lazy_glVertexWeightPointerEXT; +#endif +#endif + +/* GL_NV_light_max_exponent */ + +#ifdef __GLEE_GL_NV_light_max_exponent +#endif + +/* GL_NV_vertex_array_range */ + +#ifdef __GLEE_GL_NV_vertex_array_range +#ifndef GLEE_C_DEFINED_glFlushVertexArrayRangeNV +#define GLEE_C_DEFINED_glFlushVertexArrayRangeNV + void __stdcall GLee_Lazy_glFlushVertexArrayRangeNV(void) {if (GLeeInit()) glFlushVertexArrayRangeNV();} + GLEEPFNGLFLUSHVERTEXARRAYRANGENVPROC GLeeFuncPtr_glFlushVertexArrayRangeNV=GLee_Lazy_glFlushVertexArrayRangeNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexArrayRangeNV +#define GLEE_C_DEFINED_glVertexArrayRangeNV + void __stdcall GLee_Lazy_glVertexArrayRangeNV(GLsizei length, const GLvoid * pointer) {if (GLeeInit()) glVertexArrayRangeNV(length, pointer);} + GLEEPFNGLVERTEXARRAYRANGENVPROC GLeeFuncPtr_glVertexArrayRangeNV=GLee_Lazy_glVertexArrayRangeNV; +#endif +#endif + +/* GL_NV_register_combiners */ + +#ifdef __GLEE_GL_NV_register_combiners +#ifndef GLEE_C_DEFINED_glCombinerParameterfvNV +#define GLEE_C_DEFINED_glCombinerParameterfvNV + void __stdcall GLee_Lazy_glCombinerParameterfvNV(GLenum pname, const GLfloat * params) {if (GLeeInit()) glCombinerParameterfvNV(pname, params);} + GLEEPFNGLCOMBINERPARAMETERFVNVPROC GLeeFuncPtr_glCombinerParameterfvNV=GLee_Lazy_glCombinerParameterfvNV; +#endif +#ifndef GLEE_C_DEFINED_glCombinerParameterfNV +#define GLEE_C_DEFINED_glCombinerParameterfNV + void __stdcall GLee_Lazy_glCombinerParameterfNV(GLenum pname, GLfloat param) {if (GLeeInit()) glCombinerParameterfNV(pname, param);} + GLEEPFNGLCOMBINERPARAMETERFNVPROC GLeeFuncPtr_glCombinerParameterfNV=GLee_Lazy_glCombinerParameterfNV; +#endif +#ifndef GLEE_C_DEFINED_glCombinerParameterivNV +#define GLEE_C_DEFINED_glCombinerParameterivNV + void __stdcall GLee_Lazy_glCombinerParameterivNV(GLenum pname, const GLint * params) {if (GLeeInit()) glCombinerParameterivNV(pname, params);} + GLEEPFNGLCOMBINERPARAMETERIVNVPROC GLeeFuncPtr_glCombinerParameterivNV=GLee_Lazy_glCombinerParameterivNV; +#endif +#ifndef GLEE_C_DEFINED_glCombinerParameteriNV +#define GLEE_C_DEFINED_glCombinerParameteriNV + void __stdcall GLee_Lazy_glCombinerParameteriNV(GLenum pname, GLint param) {if (GLeeInit()) glCombinerParameteriNV(pname, param);} + GLEEPFNGLCOMBINERPARAMETERINVPROC GLeeFuncPtr_glCombinerParameteriNV=GLee_Lazy_glCombinerParameteriNV; +#endif +#ifndef GLEE_C_DEFINED_glCombinerInputNV +#define GLEE_C_DEFINED_glCombinerInputNV + void __stdcall GLee_Lazy_glCombinerInputNV(GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage) {if (GLeeInit()) glCombinerInputNV(stage, portion, variable, input, mapping, componentUsage);} + GLEEPFNGLCOMBINERINPUTNVPROC GLeeFuncPtr_glCombinerInputNV=GLee_Lazy_glCombinerInputNV; +#endif +#ifndef GLEE_C_DEFINED_glCombinerOutputNV +#define GLEE_C_DEFINED_glCombinerOutputNV + void __stdcall GLee_Lazy_glCombinerOutputNV(GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum) {if (GLeeInit()) glCombinerOutputNV(stage, portion, abOutput, cdOutput, sumOutput, scale, bias, abDotProduct, cdDotProduct, muxSum);} + GLEEPFNGLCOMBINEROUTPUTNVPROC GLeeFuncPtr_glCombinerOutputNV=GLee_Lazy_glCombinerOutputNV; +#endif +#ifndef GLEE_C_DEFINED_glFinalCombinerInputNV +#define GLEE_C_DEFINED_glFinalCombinerInputNV + void __stdcall GLee_Lazy_glFinalCombinerInputNV(GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage) {if (GLeeInit()) glFinalCombinerInputNV(variable, input, mapping, componentUsage);} + GLEEPFNGLFINALCOMBINERINPUTNVPROC GLeeFuncPtr_glFinalCombinerInputNV=GLee_Lazy_glFinalCombinerInputNV; +#endif +#ifndef GLEE_C_DEFINED_glGetCombinerInputParameterfvNV +#define GLEE_C_DEFINED_glGetCombinerInputParameterfvNV + void __stdcall GLee_Lazy_glGetCombinerInputParameterfvNV(GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetCombinerInputParameterfvNV(stage, portion, variable, pname, params);} + GLEEPFNGLGETCOMBINERINPUTPARAMETERFVNVPROC GLeeFuncPtr_glGetCombinerInputParameterfvNV=GLee_Lazy_glGetCombinerInputParameterfvNV; +#endif +#ifndef GLEE_C_DEFINED_glGetCombinerInputParameterivNV +#define GLEE_C_DEFINED_glGetCombinerInputParameterivNV + void __stdcall GLee_Lazy_glGetCombinerInputParameterivNV(GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint * params) {if (GLeeInit()) glGetCombinerInputParameterivNV(stage, portion, variable, pname, params);} + GLEEPFNGLGETCOMBINERINPUTPARAMETERIVNVPROC GLeeFuncPtr_glGetCombinerInputParameterivNV=GLee_Lazy_glGetCombinerInputParameterivNV; +#endif +#ifndef GLEE_C_DEFINED_glGetCombinerOutputParameterfvNV +#define GLEE_C_DEFINED_glGetCombinerOutputParameterfvNV + void __stdcall GLee_Lazy_glGetCombinerOutputParameterfvNV(GLenum stage, GLenum portion, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetCombinerOutputParameterfvNV(stage, portion, pname, params);} + GLEEPFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC GLeeFuncPtr_glGetCombinerOutputParameterfvNV=GLee_Lazy_glGetCombinerOutputParameterfvNV; +#endif +#ifndef GLEE_C_DEFINED_glGetCombinerOutputParameterivNV +#define GLEE_C_DEFINED_glGetCombinerOutputParameterivNV + void __stdcall GLee_Lazy_glGetCombinerOutputParameterivNV(GLenum stage, GLenum portion, GLenum pname, GLint * params) {if (GLeeInit()) glGetCombinerOutputParameterivNV(stage, portion, pname, params);} + GLEEPFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC GLeeFuncPtr_glGetCombinerOutputParameterivNV=GLee_Lazy_glGetCombinerOutputParameterivNV; +#endif +#ifndef GLEE_C_DEFINED_glGetFinalCombinerInputParameterfvNV +#define GLEE_C_DEFINED_glGetFinalCombinerInputParameterfvNV + void __stdcall GLee_Lazy_glGetFinalCombinerInputParameterfvNV(GLenum variable, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetFinalCombinerInputParameterfvNV(variable, pname, params);} + GLEEPFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC GLeeFuncPtr_glGetFinalCombinerInputParameterfvNV=GLee_Lazy_glGetFinalCombinerInputParameterfvNV; +#endif +#ifndef GLEE_C_DEFINED_glGetFinalCombinerInputParameterivNV +#define GLEE_C_DEFINED_glGetFinalCombinerInputParameterivNV + void __stdcall GLee_Lazy_glGetFinalCombinerInputParameterivNV(GLenum variable, GLenum pname, GLint * params) {if (GLeeInit()) glGetFinalCombinerInputParameterivNV(variable, pname, params);} + GLEEPFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC GLeeFuncPtr_glGetFinalCombinerInputParameterivNV=GLee_Lazy_glGetFinalCombinerInputParameterivNV; +#endif +#endif + +/* GL_NV_fog_distance */ + +#ifdef __GLEE_GL_NV_fog_distance +#endif + +/* GL_NV_texgen_emboss */ + +#ifdef __GLEE_GL_NV_texgen_emboss +#endif + +/* GL_NV_blend_square */ + +#ifdef __GLEE_GL_NV_blend_square +#endif + +/* GL_NV_texture_env_combine4 */ + +#ifdef __GLEE_GL_NV_texture_env_combine4 +#endif + +/* GL_MESA_resize_buffers */ + +#ifdef __GLEE_GL_MESA_resize_buffers +#ifndef GLEE_C_DEFINED_glResizeBuffersMESA +#define GLEE_C_DEFINED_glResizeBuffersMESA + void __stdcall GLee_Lazy_glResizeBuffersMESA(void) {if (GLeeInit()) glResizeBuffersMESA();} + GLEEPFNGLRESIZEBUFFERSMESAPROC GLeeFuncPtr_glResizeBuffersMESA=GLee_Lazy_glResizeBuffersMESA; +#endif +#endif + +/* GL_MESA_window_pos */ + +#ifdef __GLEE_GL_MESA_window_pos +#ifndef GLEE_C_DEFINED_glWindowPos2dMESA +#define GLEE_C_DEFINED_glWindowPos2dMESA + void __stdcall GLee_Lazy_glWindowPos2dMESA(GLdouble x, GLdouble y) {if (GLeeInit()) glWindowPos2dMESA(x, y);} + GLEEPFNGLWINDOWPOS2DMESAPROC GLeeFuncPtr_glWindowPos2dMESA=GLee_Lazy_glWindowPos2dMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2dvMESA +#define GLEE_C_DEFINED_glWindowPos2dvMESA + void __stdcall GLee_Lazy_glWindowPos2dvMESA(const GLdouble * v) {if (GLeeInit()) glWindowPos2dvMESA(v);} + GLEEPFNGLWINDOWPOS2DVMESAPROC GLeeFuncPtr_glWindowPos2dvMESA=GLee_Lazy_glWindowPos2dvMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2fMESA +#define GLEE_C_DEFINED_glWindowPos2fMESA + void __stdcall GLee_Lazy_glWindowPos2fMESA(GLfloat x, GLfloat y) {if (GLeeInit()) glWindowPos2fMESA(x, y);} + GLEEPFNGLWINDOWPOS2FMESAPROC GLeeFuncPtr_glWindowPos2fMESA=GLee_Lazy_glWindowPos2fMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2fvMESA +#define GLEE_C_DEFINED_glWindowPos2fvMESA + void __stdcall GLee_Lazy_glWindowPos2fvMESA(const GLfloat * v) {if (GLeeInit()) glWindowPos2fvMESA(v);} + GLEEPFNGLWINDOWPOS2FVMESAPROC GLeeFuncPtr_glWindowPos2fvMESA=GLee_Lazy_glWindowPos2fvMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2iMESA +#define GLEE_C_DEFINED_glWindowPos2iMESA + void __stdcall GLee_Lazy_glWindowPos2iMESA(GLint x, GLint y) {if (GLeeInit()) glWindowPos2iMESA(x, y);} + GLEEPFNGLWINDOWPOS2IMESAPROC GLeeFuncPtr_glWindowPos2iMESA=GLee_Lazy_glWindowPos2iMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2ivMESA +#define GLEE_C_DEFINED_glWindowPos2ivMESA + void __stdcall GLee_Lazy_glWindowPos2ivMESA(const GLint * v) {if (GLeeInit()) glWindowPos2ivMESA(v);} + GLEEPFNGLWINDOWPOS2IVMESAPROC GLeeFuncPtr_glWindowPos2ivMESA=GLee_Lazy_glWindowPos2ivMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2sMESA +#define GLEE_C_DEFINED_glWindowPos2sMESA + void __stdcall GLee_Lazy_glWindowPos2sMESA(GLshort x, GLshort y) {if (GLeeInit()) glWindowPos2sMESA(x, y);} + GLEEPFNGLWINDOWPOS2SMESAPROC GLeeFuncPtr_glWindowPos2sMESA=GLee_Lazy_glWindowPos2sMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos2svMESA +#define GLEE_C_DEFINED_glWindowPos2svMESA + void __stdcall GLee_Lazy_glWindowPos2svMESA(const GLshort * v) {if (GLeeInit()) glWindowPos2svMESA(v);} + GLEEPFNGLWINDOWPOS2SVMESAPROC GLeeFuncPtr_glWindowPos2svMESA=GLee_Lazy_glWindowPos2svMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3dMESA +#define GLEE_C_DEFINED_glWindowPos3dMESA + void __stdcall GLee_Lazy_glWindowPos3dMESA(GLdouble x, GLdouble y, GLdouble z) {if (GLeeInit()) glWindowPos3dMESA(x, y, z);} + GLEEPFNGLWINDOWPOS3DMESAPROC GLeeFuncPtr_glWindowPos3dMESA=GLee_Lazy_glWindowPos3dMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3dvMESA +#define GLEE_C_DEFINED_glWindowPos3dvMESA + void __stdcall GLee_Lazy_glWindowPos3dvMESA(const GLdouble * v) {if (GLeeInit()) glWindowPos3dvMESA(v);} + GLEEPFNGLWINDOWPOS3DVMESAPROC GLeeFuncPtr_glWindowPos3dvMESA=GLee_Lazy_glWindowPos3dvMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3fMESA +#define GLEE_C_DEFINED_glWindowPos3fMESA + void __stdcall GLee_Lazy_glWindowPos3fMESA(GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glWindowPos3fMESA(x, y, z);} + GLEEPFNGLWINDOWPOS3FMESAPROC GLeeFuncPtr_glWindowPos3fMESA=GLee_Lazy_glWindowPos3fMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3fvMESA +#define GLEE_C_DEFINED_glWindowPos3fvMESA + void __stdcall GLee_Lazy_glWindowPos3fvMESA(const GLfloat * v) {if (GLeeInit()) glWindowPos3fvMESA(v);} + GLEEPFNGLWINDOWPOS3FVMESAPROC GLeeFuncPtr_glWindowPos3fvMESA=GLee_Lazy_glWindowPos3fvMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3iMESA +#define GLEE_C_DEFINED_glWindowPos3iMESA + void __stdcall GLee_Lazy_glWindowPos3iMESA(GLint x, GLint y, GLint z) {if (GLeeInit()) glWindowPos3iMESA(x, y, z);} + GLEEPFNGLWINDOWPOS3IMESAPROC GLeeFuncPtr_glWindowPos3iMESA=GLee_Lazy_glWindowPos3iMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3ivMESA +#define GLEE_C_DEFINED_glWindowPos3ivMESA + void __stdcall GLee_Lazy_glWindowPos3ivMESA(const GLint * v) {if (GLeeInit()) glWindowPos3ivMESA(v);} + GLEEPFNGLWINDOWPOS3IVMESAPROC GLeeFuncPtr_glWindowPos3ivMESA=GLee_Lazy_glWindowPos3ivMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3sMESA +#define GLEE_C_DEFINED_glWindowPos3sMESA + void __stdcall GLee_Lazy_glWindowPos3sMESA(GLshort x, GLshort y, GLshort z) {if (GLeeInit()) glWindowPos3sMESA(x, y, z);} + GLEEPFNGLWINDOWPOS3SMESAPROC GLeeFuncPtr_glWindowPos3sMESA=GLee_Lazy_glWindowPos3sMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos3svMESA +#define GLEE_C_DEFINED_glWindowPos3svMESA + void __stdcall GLee_Lazy_glWindowPos3svMESA(const GLshort * v) {if (GLeeInit()) glWindowPos3svMESA(v);} + GLEEPFNGLWINDOWPOS3SVMESAPROC GLeeFuncPtr_glWindowPos3svMESA=GLee_Lazy_glWindowPos3svMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos4dMESA +#define GLEE_C_DEFINED_glWindowPos4dMESA + void __stdcall GLee_Lazy_glWindowPos4dMESA(GLdouble x, GLdouble y, GLdouble z, GLdouble w) {if (GLeeInit()) glWindowPos4dMESA(x, y, z, w);} + GLEEPFNGLWINDOWPOS4DMESAPROC GLeeFuncPtr_glWindowPos4dMESA=GLee_Lazy_glWindowPos4dMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos4dvMESA +#define GLEE_C_DEFINED_glWindowPos4dvMESA + void __stdcall GLee_Lazy_glWindowPos4dvMESA(const GLdouble * v) {if (GLeeInit()) glWindowPos4dvMESA(v);} + GLEEPFNGLWINDOWPOS4DVMESAPROC GLeeFuncPtr_glWindowPos4dvMESA=GLee_Lazy_glWindowPos4dvMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos4fMESA +#define GLEE_C_DEFINED_glWindowPos4fMESA + void __stdcall GLee_Lazy_glWindowPos4fMESA(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {if (GLeeInit()) glWindowPos4fMESA(x, y, z, w);} + GLEEPFNGLWINDOWPOS4FMESAPROC GLeeFuncPtr_glWindowPos4fMESA=GLee_Lazy_glWindowPos4fMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos4fvMESA +#define GLEE_C_DEFINED_glWindowPos4fvMESA + void __stdcall GLee_Lazy_glWindowPos4fvMESA(const GLfloat * v) {if (GLeeInit()) glWindowPos4fvMESA(v);} + GLEEPFNGLWINDOWPOS4FVMESAPROC GLeeFuncPtr_glWindowPos4fvMESA=GLee_Lazy_glWindowPos4fvMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos4iMESA +#define GLEE_C_DEFINED_glWindowPos4iMESA + void __stdcall GLee_Lazy_glWindowPos4iMESA(GLint x, GLint y, GLint z, GLint w) {if (GLeeInit()) glWindowPos4iMESA(x, y, z, w);} + GLEEPFNGLWINDOWPOS4IMESAPROC GLeeFuncPtr_glWindowPos4iMESA=GLee_Lazy_glWindowPos4iMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos4ivMESA +#define GLEE_C_DEFINED_glWindowPos4ivMESA + void __stdcall GLee_Lazy_glWindowPos4ivMESA(const GLint * v) {if (GLeeInit()) glWindowPos4ivMESA(v);} + GLEEPFNGLWINDOWPOS4IVMESAPROC GLeeFuncPtr_glWindowPos4ivMESA=GLee_Lazy_glWindowPos4ivMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos4sMESA +#define GLEE_C_DEFINED_glWindowPos4sMESA + void __stdcall GLee_Lazy_glWindowPos4sMESA(GLshort x, GLshort y, GLshort z, GLshort w) {if (GLeeInit()) glWindowPos4sMESA(x, y, z, w);} + GLEEPFNGLWINDOWPOS4SMESAPROC GLeeFuncPtr_glWindowPos4sMESA=GLee_Lazy_glWindowPos4sMESA; +#endif +#ifndef GLEE_C_DEFINED_glWindowPos4svMESA +#define GLEE_C_DEFINED_glWindowPos4svMESA + void __stdcall GLee_Lazy_glWindowPos4svMESA(const GLshort * v) {if (GLeeInit()) glWindowPos4svMESA(v);} + GLEEPFNGLWINDOWPOS4SVMESAPROC GLeeFuncPtr_glWindowPos4svMESA=GLee_Lazy_glWindowPos4svMESA; +#endif +#endif + +/* GL_EXT_texture_compression_s3tc */ + +#ifdef __GLEE_GL_EXT_texture_compression_s3tc +#endif + +/* GL_IBM_cull_vertex */ + +#ifdef __GLEE_GL_IBM_cull_vertex +#endif + +/* GL_IBM_multimode_draw_arrays */ + +#ifdef __GLEE_GL_IBM_multimode_draw_arrays +#ifndef GLEE_C_DEFINED_glMultiModeDrawArraysIBM +#define GLEE_C_DEFINED_glMultiModeDrawArraysIBM + void __stdcall GLee_Lazy_glMultiModeDrawArraysIBM(const GLenum * mode, const GLint * first, const GLsizei * count, GLsizei primcount, GLint modestride) {if (GLeeInit()) glMultiModeDrawArraysIBM(mode, first, count, primcount, modestride);} + GLEEPFNGLMULTIMODEDRAWARRAYSIBMPROC GLeeFuncPtr_glMultiModeDrawArraysIBM=GLee_Lazy_glMultiModeDrawArraysIBM; +#endif +#ifndef GLEE_C_DEFINED_glMultiModeDrawElementsIBM +#define GLEE_C_DEFINED_glMultiModeDrawElementsIBM + void __stdcall GLee_Lazy_glMultiModeDrawElementsIBM(const GLenum * mode, const GLsizei * count, GLenum type, const GLvoid* const * indices, GLsizei primcount, GLint modestride) {if (GLeeInit()) glMultiModeDrawElementsIBM(mode, count, type, indices, primcount, modestride);} + GLEEPFNGLMULTIMODEDRAWELEMENTSIBMPROC GLeeFuncPtr_glMultiModeDrawElementsIBM=GLee_Lazy_glMultiModeDrawElementsIBM; +#endif +#endif + +/* GL_IBM_vertex_array_lists */ + +#ifdef __GLEE_GL_IBM_vertex_array_lists +#ifndef GLEE_C_DEFINED_glColorPointerListIBM +#define GLEE_C_DEFINED_glColorPointerListIBM + void __stdcall GLee_Lazy_glColorPointerListIBM(GLint size, GLenum type, GLint stride, const GLvoid* * pointer, GLint ptrstride) {if (GLeeInit()) glColorPointerListIBM(size, type, stride, pointer, ptrstride);} + GLEEPFNGLCOLORPOINTERLISTIBMPROC GLeeFuncPtr_glColorPointerListIBM=GLee_Lazy_glColorPointerListIBM; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColorPointerListIBM +#define GLEE_C_DEFINED_glSecondaryColorPointerListIBM + void __stdcall GLee_Lazy_glSecondaryColorPointerListIBM(GLint size, GLenum type, GLint stride, const GLvoid* * pointer, GLint ptrstride) {if (GLeeInit()) glSecondaryColorPointerListIBM(size, type, stride, pointer, ptrstride);} + GLEEPFNGLSECONDARYCOLORPOINTERLISTIBMPROC GLeeFuncPtr_glSecondaryColorPointerListIBM=GLee_Lazy_glSecondaryColorPointerListIBM; +#endif +#ifndef GLEE_C_DEFINED_glEdgeFlagPointerListIBM +#define GLEE_C_DEFINED_glEdgeFlagPointerListIBM + void __stdcall GLee_Lazy_glEdgeFlagPointerListIBM(GLint stride, const GLboolean* * pointer, GLint ptrstride) {if (GLeeInit()) glEdgeFlagPointerListIBM(stride, pointer, ptrstride);} + GLEEPFNGLEDGEFLAGPOINTERLISTIBMPROC GLeeFuncPtr_glEdgeFlagPointerListIBM=GLee_Lazy_glEdgeFlagPointerListIBM; +#endif +#ifndef GLEE_C_DEFINED_glFogCoordPointerListIBM +#define GLEE_C_DEFINED_glFogCoordPointerListIBM + void __stdcall GLee_Lazy_glFogCoordPointerListIBM(GLenum type, GLint stride, const GLvoid* * pointer, GLint ptrstride) {if (GLeeInit()) glFogCoordPointerListIBM(type, stride, pointer, ptrstride);} + GLEEPFNGLFOGCOORDPOINTERLISTIBMPROC GLeeFuncPtr_glFogCoordPointerListIBM=GLee_Lazy_glFogCoordPointerListIBM; +#endif +#ifndef GLEE_C_DEFINED_glIndexPointerListIBM +#define GLEE_C_DEFINED_glIndexPointerListIBM + void __stdcall GLee_Lazy_glIndexPointerListIBM(GLenum type, GLint stride, const GLvoid* * pointer, GLint ptrstride) {if (GLeeInit()) glIndexPointerListIBM(type, stride, pointer, ptrstride);} + GLEEPFNGLINDEXPOINTERLISTIBMPROC GLeeFuncPtr_glIndexPointerListIBM=GLee_Lazy_glIndexPointerListIBM; +#endif +#ifndef GLEE_C_DEFINED_glNormalPointerListIBM +#define GLEE_C_DEFINED_glNormalPointerListIBM + void __stdcall GLee_Lazy_glNormalPointerListIBM(GLenum type, GLint stride, const GLvoid* * pointer, GLint ptrstride) {if (GLeeInit()) glNormalPointerListIBM(type, stride, pointer, ptrstride);} + GLEEPFNGLNORMALPOINTERLISTIBMPROC GLeeFuncPtr_glNormalPointerListIBM=GLee_Lazy_glNormalPointerListIBM; +#endif +#ifndef GLEE_C_DEFINED_glTexCoordPointerListIBM +#define GLEE_C_DEFINED_glTexCoordPointerListIBM + void __stdcall GLee_Lazy_glTexCoordPointerListIBM(GLint size, GLenum type, GLint stride, const GLvoid* * pointer, GLint ptrstride) {if (GLeeInit()) glTexCoordPointerListIBM(size, type, stride, pointer, ptrstride);} + GLEEPFNGLTEXCOORDPOINTERLISTIBMPROC GLeeFuncPtr_glTexCoordPointerListIBM=GLee_Lazy_glTexCoordPointerListIBM; +#endif +#ifndef GLEE_C_DEFINED_glVertexPointerListIBM +#define GLEE_C_DEFINED_glVertexPointerListIBM + void __stdcall GLee_Lazy_glVertexPointerListIBM(GLint size, GLenum type, GLint stride, const GLvoid* * pointer, GLint ptrstride) {if (GLeeInit()) glVertexPointerListIBM(size, type, stride, pointer, ptrstride);} + GLEEPFNGLVERTEXPOINTERLISTIBMPROC GLeeFuncPtr_glVertexPointerListIBM=GLee_Lazy_glVertexPointerListIBM; +#endif +#endif + +/* GL_SGIX_subsample */ + +#ifdef __GLEE_GL_SGIX_subsample +#endif + +/* GL_SGIX_ycrcb_subsample */ + +#ifdef __GLEE_GL_SGIX_ycrcb_subsample +#endif + +/* GL_SGIX_ycrcba */ + +#ifdef __GLEE_GL_SGIX_ycrcba +#endif + +/* GL_SGI_depth_pass_instrument */ + +#ifdef __GLEE_GL_SGI_depth_pass_instrument +#endif + +/* GL_3DFX_texture_compression_FXT1 */ + +#ifdef __GLEE_GL_3DFX_texture_compression_FXT1 +#endif + +/* GL_3DFX_multisample */ + +#ifdef __GLEE_GL_3DFX_multisample +#endif + +/* GL_3DFX_tbuffer */ + +#ifdef __GLEE_GL_3DFX_tbuffer +#ifndef GLEE_C_DEFINED_glTbufferMask3DFX +#define GLEE_C_DEFINED_glTbufferMask3DFX + void __stdcall GLee_Lazy_glTbufferMask3DFX(GLuint mask) {if (GLeeInit()) glTbufferMask3DFX(mask);} + GLEEPFNGLTBUFFERMASK3DFXPROC GLeeFuncPtr_glTbufferMask3DFX=GLee_Lazy_glTbufferMask3DFX; +#endif +#endif + +/* GL_EXT_multisample */ + +#ifdef __GLEE_GL_EXT_multisample +#ifndef GLEE_C_DEFINED_glSampleMaskEXT +#define GLEE_C_DEFINED_glSampleMaskEXT + void __stdcall GLee_Lazy_glSampleMaskEXT(GLclampf value, GLboolean invert) {if (GLeeInit()) glSampleMaskEXT(value, invert);} + GLEEPFNGLSAMPLEMASKEXTPROC GLeeFuncPtr_glSampleMaskEXT=GLee_Lazy_glSampleMaskEXT; +#endif +#ifndef GLEE_C_DEFINED_glSamplePatternEXT +#define GLEE_C_DEFINED_glSamplePatternEXT + void __stdcall GLee_Lazy_glSamplePatternEXT(GLenum pattern) {if (GLeeInit()) glSamplePatternEXT(pattern);} + GLEEPFNGLSAMPLEPATTERNEXTPROC GLeeFuncPtr_glSamplePatternEXT=GLee_Lazy_glSamplePatternEXT; +#endif +#endif + +/* GL_SGIX_vertex_preclip */ + +#ifdef __GLEE_GL_SGIX_vertex_preclip +#endif + +/* GL_SGIX_convolution_accuracy */ + +#ifdef __GLEE_GL_SGIX_convolution_accuracy +#endif + +/* GL_SGIX_resample */ + +#ifdef __GLEE_GL_SGIX_resample +#endif + +/* GL_SGIS_point_line_texgen */ + +#ifdef __GLEE_GL_SGIS_point_line_texgen +#endif + +/* GL_SGIS_texture_color_mask */ + +#ifdef __GLEE_GL_SGIS_texture_color_mask +#ifndef GLEE_C_DEFINED_glTextureColorMaskSGIS +#define GLEE_C_DEFINED_glTextureColorMaskSGIS + void __stdcall GLee_Lazy_glTextureColorMaskSGIS(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {if (GLeeInit()) glTextureColorMaskSGIS(red, green, blue, alpha);} + GLEEPFNGLTEXTURECOLORMASKSGISPROC GLeeFuncPtr_glTextureColorMaskSGIS=GLee_Lazy_glTextureColorMaskSGIS; +#endif +#endif + +/* GL_EXT_texture_env_dot3 */ + +#ifdef __GLEE_GL_EXT_texture_env_dot3 +#endif + +/* GL_ATI_texture_mirror_once */ + +#ifdef __GLEE_GL_ATI_texture_mirror_once +#endif + +/* GL_NV_fence */ + +#ifdef __GLEE_GL_NV_fence +#ifndef GLEE_C_DEFINED_glDeleteFencesNV +#define GLEE_C_DEFINED_glDeleteFencesNV + void __stdcall GLee_Lazy_glDeleteFencesNV(GLsizei n, const GLuint * fences) {if (GLeeInit()) glDeleteFencesNV(n, fences);} + GLEEPFNGLDELETEFENCESNVPROC GLeeFuncPtr_glDeleteFencesNV=GLee_Lazy_glDeleteFencesNV; +#endif +#ifndef GLEE_C_DEFINED_glGenFencesNV +#define GLEE_C_DEFINED_glGenFencesNV + void __stdcall GLee_Lazy_glGenFencesNV(GLsizei n, GLuint * fences) {if (GLeeInit()) glGenFencesNV(n, fences);} + GLEEPFNGLGENFENCESNVPROC GLeeFuncPtr_glGenFencesNV=GLee_Lazy_glGenFencesNV; +#endif +#ifndef GLEE_C_DEFINED_glIsFenceNV +#define GLEE_C_DEFINED_glIsFenceNV + GLboolean __stdcall GLee_Lazy_glIsFenceNV(GLuint fence) {if (GLeeInit()) return glIsFenceNV(fence); return (GLboolean)0;} + GLEEPFNGLISFENCENVPROC GLeeFuncPtr_glIsFenceNV=GLee_Lazy_glIsFenceNV; +#endif +#ifndef GLEE_C_DEFINED_glTestFenceNV +#define GLEE_C_DEFINED_glTestFenceNV + GLboolean __stdcall GLee_Lazy_glTestFenceNV(GLuint fence) {if (GLeeInit()) return glTestFenceNV(fence); return (GLboolean)0;} + GLEEPFNGLTESTFENCENVPROC GLeeFuncPtr_glTestFenceNV=GLee_Lazy_glTestFenceNV; +#endif +#ifndef GLEE_C_DEFINED_glGetFenceivNV +#define GLEE_C_DEFINED_glGetFenceivNV + void __stdcall GLee_Lazy_glGetFenceivNV(GLuint fence, GLenum pname, GLint * params) {if (GLeeInit()) glGetFenceivNV(fence, pname, params);} + GLEEPFNGLGETFENCEIVNVPROC GLeeFuncPtr_glGetFenceivNV=GLee_Lazy_glGetFenceivNV; +#endif +#ifndef GLEE_C_DEFINED_glFinishFenceNV +#define GLEE_C_DEFINED_glFinishFenceNV + void __stdcall GLee_Lazy_glFinishFenceNV(GLuint fence) {if (GLeeInit()) glFinishFenceNV(fence);} + GLEEPFNGLFINISHFENCENVPROC GLeeFuncPtr_glFinishFenceNV=GLee_Lazy_glFinishFenceNV; +#endif +#ifndef GLEE_C_DEFINED_glSetFenceNV +#define GLEE_C_DEFINED_glSetFenceNV + void __stdcall GLee_Lazy_glSetFenceNV(GLuint fence, GLenum condition) {if (GLeeInit()) glSetFenceNV(fence, condition);} + GLEEPFNGLSETFENCENVPROC GLeeFuncPtr_glSetFenceNV=GLee_Lazy_glSetFenceNV; +#endif +#endif + +/* GL_IBM_texture_mirrored_repeat */ + +#ifdef __GLEE_GL_IBM_texture_mirrored_repeat +#endif + +/* GL_NV_evaluators */ + +#ifdef __GLEE_GL_NV_evaluators +#ifndef GLEE_C_DEFINED_glMapControlPointsNV +#define GLEE_C_DEFINED_glMapControlPointsNV + void __stdcall GLee_Lazy_glMapControlPointsNV(GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid * points) {if (GLeeInit()) glMapControlPointsNV(target, index, type, ustride, vstride, uorder, vorder, packed, points);} + GLEEPFNGLMAPCONTROLPOINTSNVPROC GLeeFuncPtr_glMapControlPointsNV=GLee_Lazy_glMapControlPointsNV; +#endif +#ifndef GLEE_C_DEFINED_glMapParameterivNV +#define GLEE_C_DEFINED_glMapParameterivNV + void __stdcall GLee_Lazy_glMapParameterivNV(GLenum target, GLenum pname, const GLint * params) {if (GLeeInit()) glMapParameterivNV(target, pname, params);} + GLEEPFNGLMAPPARAMETERIVNVPROC GLeeFuncPtr_glMapParameterivNV=GLee_Lazy_glMapParameterivNV; +#endif +#ifndef GLEE_C_DEFINED_glMapParameterfvNV +#define GLEE_C_DEFINED_glMapParameterfvNV + void __stdcall GLee_Lazy_glMapParameterfvNV(GLenum target, GLenum pname, const GLfloat * params) {if (GLeeInit()) glMapParameterfvNV(target, pname, params);} + GLEEPFNGLMAPPARAMETERFVNVPROC GLeeFuncPtr_glMapParameterfvNV=GLee_Lazy_glMapParameterfvNV; +#endif +#ifndef GLEE_C_DEFINED_glGetMapControlPointsNV +#define GLEE_C_DEFINED_glGetMapControlPointsNV + void __stdcall GLee_Lazy_glGetMapControlPointsNV(GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid * points) {if (GLeeInit()) glGetMapControlPointsNV(target, index, type, ustride, vstride, packed, points);} + GLEEPFNGLGETMAPCONTROLPOINTSNVPROC GLeeFuncPtr_glGetMapControlPointsNV=GLee_Lazy_glGetMapControlPointsNV; +#endif +#ifndef GLEE_C_DEFINED_glGetMapParameterivNV +#define GLEE_C_DEFINED_glGetMapParameterivNV + void __stdcall GLee_Lazy_glGetMapParameterivNV(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetMapParameterivNV(target, pname, params);} + GLEEPFNGLGETMAPPARAMETERIVNVPROC GLeeFuncPtr_glGetMapParameterivNV=GLee_Lazy_glGetMapParameterivNV; +#endif +#ifndef GLEE_C_DEFINED_glGetMapParameterfvNV +#define GLEE_C_DEFINED_glGetMapParameterfvNV + void __stdcall GLee_Lazy_glGetMapParameterfvNV(GLenum target, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetMapParameterfvNV(target, pname, params);} + GLEEPFNGLGETMAPPARAMETERFVNVPROC GLeeFuncPtr_glGetMapParameterfvNV=GLee_Lazy_glGetMapParameterfvNV; +#endif +#ifndef GLEE_C_DEFINED_glGetMapAttribParameterivNV +#define GLEE_C_DEFINED_glGetMapAttribParameterivNV + void __stdcall GLee_Lazy_glGetMapAttribParameterivNV(GLenum target, GLuint index, GLenum pname, GLint * params) {if (GLeeInit()) glGetMapAttribParameterivNV(target, index, pname, params);} + GLEEPFNGLGETMAPATTRIBPARAMETERIVNVPROC GLeeFuncPtr_glGetMapAttribParameterivNV=GLee_Lazy_glGetMapAttribParameterivNV; +#endif +#ifndef GLEE_C_DEFINED_glGetMapAttribParameterfvNV +#define GLEE_C_DEFINED_glGetMapAttribParameterfvNV + void __stdcall GLee_Lazy_glGetMapAttribParameterfvNV(GLenum target, GLuint index, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetMapAttribParameterfvNV(target, index, pname, params);} + GLEEPFNGLGETMAPATTRIBPARAMETERFVNVPROC GLeeFuncPtr_glGetMapAttribParameterfvNV=GLee_Lazy_glGetMapAttribParameterfvNV; +#endif +#ifndef GLEE_C_DEFINED_glEvalMapsNV +#define GLEE_C_DEFINED_glEvalMapsNV + void __stdcall GLee_Lazy_glEvalMapsNV(GLenum target, GLenum mode) {if (GLeeInit()) glEvalMapsNV(target, mode);} + GLEEPFNGLEVALMAPSNVPROC GLeeFuncPtr_glEvalMapsNV=GLee_Lazy_glEvalMapsNV; +#endif +#endif + +/* GL_NV_packed_depth_stencil */ + +#ifdef __GLEE_GL_NV_packed_depth_stencil +#endif + +/* GL_NV_register_combiners2 */ + +#ifdef __GLEE_GL_NV_register_combiners2 +#ifndef GLEE_C_DEFINED_glCombinerStageParameterfvNV +#define GLEE_C_DEFINED_glCombinerStageParameterfvNV + void __stdcall GLee_Lazy_glCombinerStageParameterfvNV(GLenum stage, GLenum pname, const GLfloat * params) {if (GLeeInit()) glCombinerStageParameterfvNV(stage, pname, params);} + GLEEPFNGLCOMBINERSTAGEPARAMETERFVNVPROC GLeeFuncPtr_glCombinerStageParameterfvNV=GLee_Lazy_glCombinerStageParameterfvNV; +#endif +#ifndef GLEE_C_DEFINED_glGetCombinerStageParameterfvNV +#define GLEE_C_DEFINED_glGetCombinerStageParameterfvNV + void __stdcall GLee_Lazy_glGetCombinerStageParameterfvNV(GLenum stage, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetCombinerStageParameterfvNV(stage, pname, params);} + GLEEPFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC GLeeFuncPtr_glGetCombinerStageParameterfvNV=GLee_Lazy_glGetCombinerStageParameterfvNV; +#endif +#endif + +/* GL_NV_texture_compression_vtc */ + +#ifdef __GLEE_GL_NV_texture_compression_vtc +#endif + +/* GL_NV_texture_rectangle */ + +#ifdef __GLEE_GL_NV_texture_rectangle +#endif + +/* GL_NV_texture_shader */ + +#ifdef __GLEE_GL_NV_texture_shader +#endif + +/* GL_NV_texture_shader2 */ + +#ifdef __GLEE_GL_NV_texture_shader2 +#endif + +/* GL_NV_vertex_array_range2 */ + +#ifdef __GLEE_GL_NV_vertex_array_range2 +#endif + +/* GL_NV_vertex_program */ + +#ifdef __GLEE_GL_NV_vertex_program +#ifndef GLEE_C_DEFINED_glAreProgramsResidentNV +#define GLEE_C_DEFINED_glAreProgramsResidentNV + GLboolean __stdcall GLee_Lazy_glAreProgramsResidentNV(GLsizei n, const GLuint * programs, GLboolean * residences) {if (GLeeInit()) return glAreProgramsResidentNV(n, programs, residences); return (GLboolean)0;} + GLEEPFNGLAREPROGRAMSRESIDENTNVPROC GLeeFuncPtr_glAreProgramsResidentNV=GLee_Lazy_glAreProgramsResidentNV; +#endif +#ifndef GLEE_C_DEFINED_glBindProgramNV +#define GLEE_C_DEFINED_glBindProgramNV + void __stdcall GLee_Lazy_glBindProgramNV(GLenum target, GLuint id) {if (GLeeInit()) glBindProgramNV(target, id);} + GLEEPFNGLBINDPROGRAMNVPROC GLeeFuncPtr_glBindProgramNV=GLee_Lazy_glBindProgramNV; +#endif +#ifndef GLEE_C_DEFINED_glDeleteProgramsNV +#define GLEE_C_DEFINED_glDeleteProgramsNV + void __stdcall GLee_Lazy_glDeleteProgramsNV(GLsizei n, const GLuint * programs) {if (GLeeInit()) glDeleteProgramsNV(n, programs);} + GLEEPFNGLDELETEPROGRAMSNVPROC GLeeFuncPtr_glDeleteProgramsNV=GLee_Lazy_glDeleteProgramsNV; +#endif +#ifndef GLEE_C_DEFINED_glExecuteProgramNV +#define GLEE_C_DEFINED_glExecuteProgramNV + void __stdcall GLee_Lazy_glExecuteProgramNV(GLenum target, GLuint id, const GLfloat * params) {if (GLeeInit()) glExecuteProgramNV(target, id, params);} + GLEEPFNGLEXECUTEPROGRAMNVPROC GLeeFuncPtr_glExecuteProgramNV=GLee_Lazy_glExecuteProgramNV; +#endif +#ifndef GLEE_C_DEFINED_glGenProgramsNV +#define GLEE_C_DEFINED_glGenProgramsNV + void __stdcall GLee_Lazy_glGenProgramsNV(GLsizei n, GLuint * programs) {if (GLeeInit()) glGenProgramsNV(n, programs);} + GLEEPFNGLGENPROGRAMSNVPROC GLeeFuncPtr_glGenProgramsNV=GLee_Lazy_glGenProgramsNV; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramParameterdvNV +#define GLEE_C_DEFINED_glGetProgramParameterdvNV + void __stdcall GLee_Lazy_glGetProgramParameterdvNV(GLenum target, GLuint index, GLenum pname, GLdouble * params) {if (GLeeInit()) glGetProgramParameterdvNV(target, index, pname, params);} + GLEEPFNGLGETPROGRAMPARAMETERDVNVPROC GLeeFuncPtr_glGetProgramParameterdvNV=GLee_Lazy_glGetProgramParameterdvNV; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramParameterfvNV +#define GLEE_C_DEFINED_glGetProgramParameterfvNV + void __stdcall GLee_Lazy_glGetProgramParameterfvNV(GLenum target, GLuint index, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetProgramParameterfvNV(target, index, pname, params);} + GLEEPFNGLGETPROGRAMPARAMETERFVNVPROC GLeeFuncPtr_glGetProgramParameterfvNV=GLee_Lazy_glGetProgramParameterfvNV; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramivNV +#define GLEE_C_DEFINED_glGetProgramivNV + void __stdcall GLee_Lazy_glGetProgramivNV(GLuint id, GLenum pname, GLint * params) {if (GLeeInit()) glGetProgramivNV(id, pname, params);} + GLEEPFNGLGETPROGRAMIVNVPROC GLeeFuncPtr_glGetProgramivNV=GLee_Lazy_glGetProgramivNV; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramStringNV +#define GLEE_C_DEFINED_glGetProgramStringNV + void __stdcall GLee_Lazy_glGetProgramStringNV(GLuint id, GLenum pname, GLubyte * program) {if (GLeeInit()) glGetProgramStringNV(id, pname, program);} + GLEEPFNGLGETPROGRAMSTRINGNVPROC GLeeFuncPtr_glGetProgramStringNV=GLee_Lazy_glGetProgramStringNV; +#endif +#ifndef GLEE_C_DEFINED_glGetTrackMatrixivNV +#define GLEE_C_DEFINED_glGetTrackMatrixivNV + void __stdcall GLee_Lazy_glGetTrackMatrixivNV(GLenum target, GLuint address, GLenum pname, GLint * params) {if (GLeeInit()) glGetTrackMatrixivNV(target, address, pname, params);} + GLEEPFNGLGETTRACKMATRIXIVNVPROC GLeeFuncPtr_glGetTrackMatrixivNV=GLee_Lazy_glGetTrackMatrixivNV; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribdvNV +#define GLEE_C_DEFINED_glGetVertexAttribdvNV + void __stdcall GLee_Lazy_glGetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble * params) {if (GLeeInit()) glGetVertexAttribdvNV(index, pname, params);} + GLEEPFNGLGETVERTEXATTRIBDVNVPROC GLeeFuncPtr_glGetVertexAttribdvNV=GLee_Lazy_glGetVertexAttribdvNV; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribfvNV +#define GLEE_C_DEFINED_glGetVertexAttribfvNV + void __stdcall GLee_Lazy_glGetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetVertexAttribfvNV(index, pname, params);} + GLEEPFNGLGETVERTEXATTRIBFVNVPROC GLeeFuncPtr_glGetVertexAttribfvNV=GLee_Lazy_glGetVertexAttribfvNV; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribivNV +#define GLEE_C_DEFINED_glGetVertexAttribivNV + void __stdcall GLee_Lazy_glGetVertexAttribivNV(GLuint index, GLenum pname, GLint * params) {if (GLeeInit()) glGetVertexAttribivNV(index, pname, params);} + GLEEPFNGLGETVERTEXATTRIBIVNVPROC GLeeFuncPtr_glGetVertexAttribivNV=GLee_Lazy_glGetVertexAttribivNV; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribPointervNV +#define GLEE_C_DEFINED_glGetVertexAttribPointervNV + void __stdcall GLee_Lazy_glGetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid* * pointer) {if (GLeeInit()) glGetVertexAttribPointervNV(index, pname, pointer);} + GLEEPFNGLGETVERTEXATTRIBPOINTERVNVPROC GLeeFuncPtr_glGetVertexAttribPointervNV=GLee_Lazy_glGetVertexAttribPointervNV; +#endif +#ifndef GLEE_C_DEFINED_glIsProgramNV +#define GLEE_C_DEFINED_glIsProgramNV + GLboolean __stdcall GLee_Lazy_glIsProgramNV(GLuint id) {if (GLeeInit()) return glIsProgramNV(id); return (GLboolean)0;} + GLEEPFNGLISPROGRAMNVPROC GLeeFuncPtr_glIsProgramNV=GLee_Lazy_glIsProgramNV; +#endif +#ifndef GLEE_C_DEFINED_glLoadProgramNV +#define GLEE_C_DEFINED_glLoadProgramNV + void __stdcall GLee_Lazy_glLoadProgramNV(GLenum target, GLuint id, GLsizei len, const GLubyte * program) {if (GLeeInit()) glLoadProgramNV(target, id, len, program);} + GLEEPFNGLLOADPROGRAMNVPROC GLeeFuncPtr_glLoadProgramNV=GLee_Lazy_glLoadProgramNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramParameter4dNV +#define GLEE_C_DEFINED_glProgramParameter4dNV + void __stdcall GLee_Lazy_glProgramParameter4dNV(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) {if (GLeeInit()) glProgramParameter4dNV(target, index, x, y, z, w);} + GLEEPFNGLPROGRAMPARAMETER4DNVPROC GLeeFuncPtr_glProgramParameter4dNV=GLee_Lazy_glProgramParameter4dNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramParameter4dvNV +#define GLEE_C_DEFINED_glProgramParameter4dvNV + void __stdcall GLee_Lazy_glProgramParameter4dvNV(GLenum target, GLuint index, const GLdouble * v) {if (GLeeInit()) glProgramParameter4dvNV(target, index, v);} + GLEEPFNGLPROGRAMPARAMETER4DVNVPROC GLeeFuncPtr_glProgramParameter4dvNV=GLee_Lazy_glProgramParameter4dvNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramParameter4fNV +#define GLEE_C_DEFINED_glProgramParameter4fNV + void __stdcall GLee_Lazy_glProgramParameter4fNV(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {if (GLeeInit()) glProgramParameter4fNV(target, index, x, y, z, w);} + GLEEPFNGLPROGRAMPARAMETER4FNVPROC GLeeFuncPtr_glProgramParameter4fNV=GLee_Lazy_glProgramParameter4fNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramParameter4fvNV +#define GLEE_C_DEFINED_glProgramParameter4fvNV + void __stdcall GLee_Lazy_glProgramParameter4fvNV(GLenum target, GLuint index, const GLfloat * v) {if (GLeeInit()) glProgramParameter4fvNV(target, index, v);} + GLEEPFNGLPROGRAMPARAMETER4FVNVPROC GLeeFuncPtr_glProgramParameter4fvNV=GLee_Lazy_glProgramParameter4fvNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramParameters4dvNV +#define GLEE_C_DEFINED_glProgramParameters4dvNV + void __stdcall GLee_Lazy_glProgramParameters4dvNV(GLenum target, GLuint index, GLuint count, const GLdouble * v) {if (GLeeInit()) glProgramParameters4dvNV(target, index, count, v);} + GLEEPFNGLPROGRAMPARAMETERS4DVNVPROC GLeeFuncPtr_glProgramParameters4dvNV=GLee_Lazy_glProgramParameters4dvNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramParameters4fvNV +#define GLEE_C_DEFINED_glProgramParameters4fvNV + void __stdcall GLee_Lazy_glProgramParameters4fvNV(GLenum target, GLuint index, GLuint count, const GLfloat * v) {if (GLeeInit()) glProgramParameters4fvNV(target, index, count, v);} + GLEEPFNGLPROGRAMPARAMETERS4FVNVPROC GLeeFuncPtr_glProgramParameters4fvNV=GLee_Lazy_glProgramParameters4fvNV; +#endif +#ifndef GLEE_C_DEFINED_glRequestResidentProgramsNV +#define GLEE_C_DEFINED_glRequestResidentProgramsNV + void __stdcall GLee_Lazy_glRequestResidentProgramsNV(GLsizei n, const GLuint * programs) {if (GLeeInit()) glRequestResidentProgramsNV(n, programs);} + GLEEPFNGLREQUESTRESIDENTPROGRAMSNVPROC GLeeFuncPtr_glRequestResidentProgramsNV=GLee_Lazy_glRequestResidentProgramsNV; +#endif +#ifndef GLEE_C_DEFINED_glTrackMatrixNV +#define GLEE_C_DEFINED_glTrackMatrixNV + void __stdcall GLee_Lazy_glTrackMatrixNV(GLenum target, GLuint address, GLenum matrix, GLenum transform) {if (GLeeInit()) glTrackMatrixNV(target, address, matrix, transform);} + GLEEPFNGLTRACKMATRIXNVPROC GLeeFuncPtr_glTrackMatrixNV=GLee_Lazy_glTrackMatrixNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribPointerNV +#define GLEE_C_DEFINED_glVertexAttribPointerNV + void __stdcall GLee_Lazy_glVertexAttribPointerNV(GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid * pointer) {if (GLeeInit()) glVertexAttribPointerNV(index, fsize, type, stride, pointer);} + GLEEPFNGLVERTEXATTRIBPOINTERNVPROC GLeeFuncPtr_glVertexAttribPointerNV=GLee_Lazy_glVertexAttribPointerNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1dNV +#define GLEE_C_DEFINED_glVertexAttrib1dNV + void __stdcall GLee_Lazy_glVertexAttrib1dNV(GLuint index, GLdouble x) {if (GLeeInit()) glVertexAttrib1dNV(index, x);} + GLEEPFNGLVERTEXATTRIB1DNVPROC GLeeFuncPtr_glVertexAttrib1dNV=GLee_Lazy_glVertexAttrib1dNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1dvNV +#define GLEE_C_DEFINED_glVertexAttrib1dvNV + void __stdcall GLee_Lazy_glVertexAttrib1dvNV(GLuint index, const GLdouble * v) {if (GLeeInit()) glVertexAttrib1dvNV(index, v);} + GLEEPFNGLVERTEXATTRIB1DVNVPROC GLeeFuncPtr_glVertexAttrib1dvNV=GLee_Lazy_glVertexAttrib1dvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1fNV +#define GLEE_C_DEFINED_glVertexAttrib1fNV + void __stdcall GLee_Lazy_glVertexAttrib1fNV(GLuint index, GLfloat x) {if (GLeeInit()) glVertexAttrib1fNV(index, x);} + GLEEPFNGLVERTEXATTRIB1FNVPROC GLeeFuncPtr_glVertexAttrib1fNV=GLee_Lazy_glVertexAttrib1fNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1fvNV +#define GLEE_C_DEFINED_glVertexAttrib1fvNV + void __stdcall GLee_Lazy_glVertexAttrib1fvNV(GLuint index, const GLfloat * v) {if (GLeeInit()) glVertexAttrib1fvNV(index, v);} + GLEEPFNGLVERTEXATTRIB1FVNVPROC GLeeFuncPtr_glVertexAttrib1fvNV=GLee_Lazy_glVertexAttrib1fvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1sNV +#define GLEE_C_DEFINED_glVertexAttrib1sNV + void __stdcall GLee_Lazy_glVertexAttrib1sNV(GLuint index, GLshort x) {if (GLeeInit()) glVertexAttrib1sNV(index, x);} + GLEEPFNGLVERTEXATTRIB1SNVPROC GLeeFuncPtr_glVertexAttrib1sNV=GLee_Lazy_glVertexAttrib1sNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1svNV +#define GLEE_C_DEFINED_glVertexAttrib1svNV + void __stdcall GLee_Lazy_glVertexAttrib1svNV(GLuint index, const GLshort * v) {if (GLeeInit()) glVertexAttrib1svNV(index, v);} + GLEEPFNGLVERTEXATTRIB1SVNVPROC GLeeFuncPtr_glVertexAttrib1svNV=GLee_Lazy_glVertexAttrib1svNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2dNV +#define GLEE_C_DEFINED_glVertexAttrib2dNV + void __stdcall GLee_Lazy_glVertexAttrib2dNV(GLuint index, GLdouble x, GLdouble y) {if (GLeeInit()) glVertexAttrib2dNV(index, x, y);} + GLEEPFNGLVERTEXATTRIB2DNVPROC GLeeFuncPtr_glVertexAttrib2dNV=GLee_Lazy_glVertexAttrib2dNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2dvNV +#define GLEE_C_DEFINED_glVertexAttrib2dvNV + void __stdcall GLee_Lazy_glVertexAttrib2dvNV(GLuint index, const GLdouble * v) {if (GLeeInit()) glVertexAttrib2dvNV(index, v);} + GLEEPFNGLVERTEXATTRIB2DVNVPROC GLeeFuncPtr_glVertexAttrib2dvNV=GLee_Lazy_glVertexAttrib2dvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2fNV +#define GLEE_C_DEFINED_glVertexAttrib2fNV + void __stdcall GLee_Lazy_glVertexAttrib2fNV(GLuint index, GLfloat x, GLfloat y) {if (GLeeInit()) glVertexAttrib2fNV(index, x, y);} + GLEEPFNGLVERTEXATTRIB2FNVPROC GLeeFuncPtr_glVertexAttrib2fNV=GLee_Lazy_glVertexAttrib2fNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2fvNV +#define GLEE_C_DEFINED_glVertexAttrib2fvNV + void __stdcall GLee_Lazy_glVertexAttrib2fvNV(GLuint index, const GLfloat * v) {if (GLeeInit()) glVertexAttrib2fvNV(index, v);} + GLEEPFNGLVERTEXATTRIB2FVNVPROC GLeeFuncPtr_glVertexAttrib2fvNV=GLee_Lazy_glVertexAttrib2fvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2sNV +#define GLEE_C_DEFINED_glVertexAttrib2sNV + void __stdcall GLee_Lazy_glVertexAttrib2sNV(GLuint index, GLshort x, GLshort y) {if (GLeeInit()) glVertexAttrib2sNV(index, x, y);} + GLEEPFNGLVERTEXATTRIB2SNVPROC GLeeFuncPtr_glVertexAttrib2sNV=GLee_Lazy_glVertexAttrib2sNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2svNV +#define GLEE_C_DEFINED_glVertexAttrib2svNV + void __stdcall GLee_Lazy_glVertexAttrib2svNV(GLuint index, const GLshort * v) {if (GLeeInit()) glVertexAttrib2svNV(index, v);} + GLEEPFNGLVERTEXATTRIB2SVNVPROC GLeeFuncPtr_glVertexAttrib2svNV=GLee_Lazy_glVertexAttrib2svNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3dNV +#define GLEE_C_DEFINED_glVertexAttrib3dNV + void __stdcall GLee_Lazy_glVertexAttrib3dNV(GLuint index, GLdouble x, GLdouble y, GLdouble z) {if (GLeeInit()) glVertexAttrib3dNV(index, x, y, z);} + GLEEPFNGLVERTEXATTRIB3DNVPROC GLeeFuncPtr_glVertexAttrib3dNV=GLee_Lazy_glVertexAttrib3dNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3dvNV +#define GLEE_C_DEFINED_glVertexAttrib3dvNV + void __stdcall GLee_Lazy_glVertexAttrib3dvNV(GLuint index, const GLdouble * v) {if (GLeeInit()) glVertexAttrib3dvNV(index, v);} + GLEEPFNGLVERTEXATTRIB3DVNVPROC GLeeFuncPtr_glVertexAttrib3dvNV=GLee_Lazy_glVertexAttrib3dvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3fNV +#define GLEE_C_DEFINED_glVertexAttrib3fNV + void __stdcall GLee_Lazy_glVertexAttrib3fNV(GLuint index, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glVertexAttrib3fNV(index, x, y, z);} + GLEEPFNGLVERTEXATTRIB3FNVPROC GLeeFuncPtr_glVertexAttrib3fNV=GLee_Lazy_glVertexAttrib3fNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3fvNV +#define GLEE_C_DEFINED_glVertexAttrib3fvNV + void __stdcall GLee_Lazy_glVertexAttrib3fvNV(GLuint index, const GLfloat * v) {if (GLeeInit()) glVertexAttrib3fvNV(index, v);} + GLEEPFNGLVERTEXATTRIB3FVNVPROC GLeeFuncPtr_glVertexAttrib3fvNV=GLee_Lazy_glVertexAttrib3fvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3sNV +#define GLEE_C_DEFINED_glVertexAttrib3sNV + void __stdcall GLee_Lazy_glVertexAttrib3sNV(GLuint index, GLshort x, GLshort y, GLshort z) {if (GLeeInit()) glVertexAttrib3sNV(index, x, y, z);} + GLEEPFNGLVERTEXATTRIB3SNVPROC GLeeFuncPtr_glVertexAttrib3sNV=GLee_Lazy_glVertexAttrib3sNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3svNV +#define GLEE_C_DEFINED_glVertexAttrib3svNV + void __stdcall GLee_Lazy_glVertexAttrib3svNV(GLuint index, const GLshort * v) {if (GLeeInit()) glVertexAttrib3svNV(index, v);} + GLEEPFNGLVERTEXATTRIB3SVNVPROC GLeeFuncPtr_glVertexAttrib3svNV=GLee_Lazy_glVertexAttrib3svNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4dNV +#define GLEE_C_DEFINED_glVertexAttrib4dNV + void __stdcall GLee_Lazy_glVertexAttrib4dNV(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) {if (GLeeInit()) glVertexAttrib4dNV(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIB4DNVPROC GLeeFuncPtr_glVertexAttrib4dNV=GLee_Lazy_glVertexAttrib4dNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4dvNV +#define GLEE_C_DEFINED_glVertexAttrib4dvNV + void __stdcall GLee_Lazy_glVertexAttrib4dvNV(GLuint index, const GLdouble * v) {if (GLeeInit()) glVertexAttrib4dvNV(index, v);} + GLEEPFNGLVERTEXATTRIB4DVNVPROC GLeeFuncPtr_glVertexAttrib4dvNV=GLee_Lazy_glVertexAttrib4dvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4fNV +#define GLEE_C_DEFINED_glVertexAttrib4fNV + void __stdcall GLee_Lazy_glVertexAttrib4fNV(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {if (GLeeInit()) glVertexAttrib4fNV(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIB4FNVPROC GLeeFuncPtr_glVertexAttrib4fNV=GLee_Lazy_glVertexAttrib4fNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4fvNV +#define GLEE_C_DEFINED_glVertexAttrib4fvNV + void __stdcall GLee_Lazy_glVertexAttrib4fvNV(GLuint index, const GLfloat * v) {if (GLeeInit()) glVertexAttrib4fvNV(index, v);} + GLEEPFNGLVERTEXATTRIB4FVNVPROC GLeeFuncPtr_glVertexAttrib4fvNV=GLee_Lazy_glVertexAttrib4fvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4sNV +#define GLEE_C_DEFINED_glVertexAttrib4sNV + void __stdcall GLee_Lazy_glVertexAttrib4sNV(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) {if (GLeeInit()) glVertexAttrib4sNV(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIB4SNVPROC GLeeFuncPtr_glVertexAttrib4sNV=GLee_Lazy_glVertexAttrib4sNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4svNV +#define GLEE_C_DEFINED_glVertexAttrib4svNV + void __stdcall GLee_Lazy_glVertexAttrib4svNV(GLuint index, const GLshort * v) {if (GLeeInit()) glVertexAttrib4svNV(index, v);} + GLEEPFNGLVERTEXATTRIB4SVNVPROC GLeeFuncPtr_glVertexAttrib4svNV=GLee_Lazy_glVertexAttrib4svNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4ubNV +#define GLEE_C_DEFINED_glVertexAttrib4ubNV + void __stdcall GLee_Lazy_glVertexAttrib4ubNV(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) {if (GLeeInit()) glVertexAttrib4ubNV(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIB4UBNVPROC GLeeFuncPtr_glVertexAttrib4ubNV=GLee_Lazy_glVertexAttrib4ubNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4ubvNV +#define GLEE_C_DEFINED_glVertexAttrib4ubvNV + void __stdcall GLee_Lazy_glVertexAttrib4ubvNV(GLuint index, const GLubyte * v) {if (GLeeInit()) glVertexAttrib4ubvNV(index, v);} + GLEEPFNGLVERTEXATTRIB4UBVNVPROC GLeeFuncPtr_glVertexAttrib4ubvNV=GLee_Lazy_glVertexAttrib4ubvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs1dvNV +#define GLEE_C_DEFINED_glVertexAttribs1dvNV + void __stdcall GLee_Lazy_glVertexAttribs1dvNV(GLuint index, GLsizei count, const GLdouble * v) {if (GLeeInit()) glVertexAttribs1dvNV(index, count, v);} + GLEEPFNGLVERTEXATTRIBS1DVNVPROC GLeeFuncPtr_glVertexAttribs1dvNV=GLee_Lazy_glVertexAttribs1dvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs1fvNV +#define GLEE_C_DEFINED_glVertexAttribs1fvNV + void __stdcall GLee_Lazy_glVertexAttribs1fvNV(GLuint index, GLsizei count, const GLfloat * v) {if (GLeeInit()) glVertexAttribs1fvNV(index, count, v);} + GLEEPFNGLVERTEXATTRIBS1FVNVPROC GLeeFuncPtr_glVertexAttribs1fvNV=GLee_Lazy_glVertexAttribs1fvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs1svNV +#define GLEE_C_DEFINED_glVertexAttribs1svNV + void __stdcall GLee_Lazy_glVertexAttribs1svNV(GLuint index, GLsizei count, const GLshort * v) {if (GLeeInit()) glVertexAttribs1svNV(index, count, v);} + GLEEPFNGLVERTEXATTRIBS1SVNVPROC GLeeFuncPtr_glVertexAttribs1svNV=GLee_Lazy_glVertexAttribs1svNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs2dvNV +#define GLEE_C_DEFINED_glVertexAttribs2dvNV + void __stdcall GLee_Lazy_glVertexAttribs2dvNV(GLuint index, GLsizei count, const GLdouble * v) {if (GLeeInit()) glVertexAttribs2dvNV(index, count, v);} + GLEEPFNGLVERTEXATTRIBS2DVNVPROC GLeeFuncPtr_glVertexAttribs2dvNV=GLee_Lazy_glVertexAttribs2dvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs2fvNV +#define GLEE_C_DEFINED_glVertexAttribs2fvNV + void __stdcall GLee_Lazy_glVertexAttribs2fvNV(GLuint index, GLsizei count, const GLfloat * v) {if (GLeeInit()) glVertexAttribs2fvNV(index, count, v);} + GLEEPFNGLVERTEXATTRIBS2FVNVPROC GLeeFuncPtr_glVertexAttribs2fvNV=GLee_Lazy_glVertexAttribs2fvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs2svNV +#define GLEE_C_DEFINED_glVertexAttribs2svNV + void __stdcall GLee_Lazy_glVertexAttribs2svNV(GLuint index, GLsizei count, const GLshort * v) {if (GLeeInit()) glVertexAttribs2svNV(index, count, v);} + GLEEPFNGLVERTEXATTRIBS2SVNVPROC GLeeFuncPtr_glVertexAttribs2svNV=GLee_Lazy_glVertexAttribs2svNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs3dvNV +#define GLEE_C_DEFINED_glVertexAttribs3dvNV + void __stdcall GLee_Lazy_glVertexAttribs3dvNV(GLuint index, GLsizei count, const GLdouble * v) {if (GLeeInit()) glVertexAttribs3dvNV(index, count, v);} + GLEEPFNGLVERTEXATTRIBS3DVNVPROC GLeeFuncPtr_glVertexAttribs3dvNV=GLee_Lazy_glVertexAttribs3dvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs3fvNV +#define GLEE_C_DEFINED_glVertexAttribs3fvNV + void __stdcall GLee_Lazy_glVertexAttribs3fvNV(GLuint index, GLsizei count, const GLfloat * v) {if (GLeeInit()) glVertexAttribs3fvNV(index, count, v);} + GLEEPFNGLVERTEXATTRIBS3FVNVPROC GLeeFuncPtr_glVertexAttribs3fvNV=GLee_Lazy_glVertexAttribs3fvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs3svNV +#define GLEE_C_DEFINED_glVertexAttribs3svNV + void __stdcall GLee_Lazy_glVertexAttribs3svNV(GLuint index, GLsizei count, const GLshort * v) {if (GLeeInit()) glVertexAttribs3svNV(index, count, v);} + GLEEPFNGLVERTEXATTRIBS3SVNVPROC GLeeFuncPtr_glVertexAttribs3svNV=GLee_Lazy_glVertexAttribs3svNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs4dvNV +#define GLEE_C_DEFINED_glVertexAttribs4dvNV + void __stdcall GLee_Lazy_glVertexAttribs4dvNV(GLuint index, GLsizei count, const GLdouble * v) {if (GLeeInit()) glVertexAttribs4dvNV(index, count, v);} + GLEEPFNGLVERTEXATTRIBS4DVNVPROC GLeeFuncPtr_glVertexAttribs4dvNV=GLee_Lazy_glVertexAttribs4dvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs4fvNV +#define GLEE_C_DEFINED_glVertexAttribs4fvNV + void __stdcall GLee_Lazy_glVertexAttribs4fvNV(GLuint index, GLsizei count, const GLfloat * v) {if (GLeeInit()) glVertexAttribs4fvNV(index, count, v);} + GLEEPFNGLVERTEXATTRIBS4FVNVPROC GLeeFuncPtr_glVertexAttribs4fvNV=GLee_Lazy_glVertexAttribs4fvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs4svNV +#define GLEE_C_DEFINED_glVertexAttribs4svNV + void __stdcall GLee_Lazy_glVertexAttribs4svNV(GLuint index, GLsizei count, const GLshort * v) {if (GLeeInit()) glVertexAttribs4svNV(index, count, v);} + GLEEPFNGLVERTEXATTRIBS4SVNVPROC GLeeFuncPtr_glVertexAttribs4svNV=GLee_Lazy_glVertexAttribs4svNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs4ubvNV +#define GLEE_C_DEFINED_glVertexAttribs4ubvNV + void __stdcall GLee_Lazy_glVertexAttribs4ubvNV(GLuint index, GLsizei count, const GLubyte * v) {if (GLeeInit()) glVertexAttribs4ubvNV(index, count, v);} + GLEEPFNGLVERTEXATTRIBS4UBVNVPROC GLeeFuncPtr_glVertexAttribs4ubvNV=GLee_Lazy_glVertexAttribs4ubvNV; +#endif +#endif + +/* GL_SGIX_texture_coordinate_clamp */ + +#ifdef __GLEE_GL_SGIX_texture_coordinate_clamp +#endif + +/* GL_SGIX_scalebias_hint */ + +#ifdef __GLEE_GL_SGIX_scalebias_hint +#endif + +/* GL_OML_interlace */ + +#ifdef __GLEE_GL_OML_interlace +#endif + +/* GL_OML_subsample */ + +#ifdef __GLEE_GL_OML_subsample +#endif + +/* GL_OML_resample */ + +#ifdef __GLEE_GL_OML_resample +#endif + +/* GL_NV_copy_depth_to_color */ + +#ifdef __GLEE_GL_NV_copy_depth_to_color +#endif + +/* GL_ATI_envmap_bumpmap */ + +#ifdef __GLEE_GL_ATI_envmap_bumpmap +#ifndef GLEE_C_DEFINED_glTexBumpParameterivATI +#define GLEE_C_DEFINED_glTexBumpParameterivATI + void __stdcall GLee_Lazy_glTexBumpParameterivATI(GLenum pname, const GLint * param) {if (GLeeInit()) glTexBumpParameterivATI(pname, param);} + GLEEPFNGLTEXBUMPPARAMETERIVATIPROC GLeeFuncPtr_glTexBumpParameterivATI=GLee_Lazy_glTexBumpParameterivATI; +#endif +#ifndef GLEE_C_DEFINED_glTexBumpParameterfvATI +#define GLEE_C_DEFINED_glTexBumpParameterfvATI + void __stdcall GLee_Lazy_glTexBumpParameterfvATI(GLenum pname, const GLfloat * param) {if (GLeeInit()) glTexBumpParameterfvATI(pname, param);} + GLEEPFNGLTEXBUMPPARAMETERFVATIPROC GLeeFuncPtr_glTexBumpParameterfvATI=GLee_Lazy_glTexBumpParameterfvATI; +#endif +#ifndef GLEE_C_DEFINED_glGetTexBumpParameterivATI +#define GLEE_C_DEFINED_glGetTexBumpParameterivATI + void __stdcall GLee_Lazy_glGetTexBumpParameterivATI(GLenum pname, GLint * param) {if (GLeeInit()) glGetTexBumpParameterivATI(pname, param);} + GLEEPFNGLGETTEXBUMPPARAMETERIVATIPROC GLeeFuncPtr_glGetTexBumpParameterivATI=GLee_Lazy_glGetTexBumpParameterivATI; +#endif +#ifndef GLEE_C_DEFINED_glGetTexBumpParameterfvATI +#define GLEE_C_DEFINED_glGetTexBumpParameterfvATI + void __stdcall GLee_Lazy_glGetTexBumpParameterfvATI(GLenum pname, GLfloat * param) {if (GLeeInit()) glGetTexBumpParameterfvATI(pname, param);} + GLEEPFNGLGETTEXBUMPPARAMETERFVATIPROC GLeeFuncPtr_glGetTexBumpParameterfvATI=GLee_Lazy_glGetTexBumpParameterfvATI; +#endif +#endif + +/* GL_ATI_fragment_shader */ + +#ifdef __GLEE_GL_ATI_fragment_shader +#ifndef GLEE_C_DEFINED_glGenFragmentShadersATI +#define GLEE_C_DEFINED_glGenFragmentShadersATI + GLuint __stdcall GLee_Lazy_glGenFragmentShadersATI(GLuint range) {if (GLeeInit()) return glGenFragmentShadersATI(range); return (GLuint)0;} + GLEEPFNGLGENFRAGMENTSHADERSATIPROC GLeeFuncPtr_glGenFragmentShadersATI=GLee_Lazy_glGenFragmentShadersATI; +#endif +#ifndef GLEE_C_DEFINED_glBindFragmentShaderATI +#define GLEE_C_DEFINED_glBindFragmentShaderATI + void __stdcall GLee_Lazy_glBindFragmentShaderATI(GLuint id) {if (GLeeInit()) glBindFragmentShaderATI(id);} + GLEEPFNGLBINDFRAGMENTSHADERATIPROC GLeeFuncPtr_glBindFragmentShaderATI=GLee_Lazy_glBindFragmentShaderATI; +#endif +#ifndef GLEE_C_DEFINED_glDeleteFragmentShaderATI +#define GLEE_C_DEFINED_glDeleteFragmentShaderATI + void __stdcall GLee_Lazy_glDeleteFragmentShaderATI(GLuint id) {if (GLeeInit()) glDeleteFragmentShaderATI(id);} + GLEEPFNGLDELETEFRAGMENTSHADERATIPROC GLeeFuncPtr_glDeleteFragmentShaderATI=GLee_Lazy_glDeleteFragmentShaderATI; +#endif +#ifndef GLEE_C_DEFINED_glBeginFragmentShaderATI +#define GLEE_C_DEFINED_glBeginFragmentShaderATI + void __stdcall GLee_Lazy_glBeginFragmentShaderATI(void) {if (GLeeInit()) glBeginFragmentShaderATI();} + GLEEPFNGLBEGINFRAGMENTSHADERATIPROC GLeeFuncPtr_glBeginFragmentShaderATI=GLee_Lazy_glBeginFragmentShaderATI; +#endif +#ifndef GLEE_C_DEFINED_glEndFragmentShaderATI +#define GLEE_C_DEFINED_glEndFragmentShaderATI + void __stdcall GLee_Lazy_glEndFragmentShaderATI(void) {if (GLeeInit()) glEndFragmentShaderATI();} + GLEEPFNGLENDFRAGMENTSHADERATIPROC GLeeFuncPtr_glEndFragmentShaderATI=GLee_Lazy_glEndFragmentShaderATI; +#endif +#ifndef GLEE_C_DEFINED_glPassTexCoordATI +#define GLEE_C_DEFINED_glPassTexCoordATI + void __stdcall GLee_Lazy_glPassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle) {if (GLeeInit()) glPassTexCoordATI(dst, coord, swizzle);} + GLEEPFNGLPASSTEXCOORDATIPROC GLeeFuncPtr_glPassTexCoordATI=GLee_Lazy_glPassTexCoordATI; +#endif +#ifndef GLEE_C_DEFINED_glSampleMapATI +#define GLEE_C_DEFINED_glSampleMapATI + void __stdcall GLee_Lazy_glSampleMapATI(GLuint dst, GLuint interp, GLenum swizzle) {if (GLeeInit()) glSampleMapATI(dst, interp, swizzle);} + GLEEPFNGLSAMPLEMAPATIPROC GLeeFuncPtr_glSampleMapATI=GLee_Lazy_glSampleMapATI; +#endif +#ifndef GLEE_C_DEFINED_glColorFragmentOp1ATI +#define GLEE_C_DEFINED_glColorFragmentOp1ATI + void __stdcall GLee_Lazy_glColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) {if (GLeeInit()) glColorFragmentOp1ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod);} + GLEEPFNGLCOLORFRAGMENTOP1ATIPROC GLeeFuncPtr_glColorFragmentOp1ATI=GLee_Lazy_glColorFragmentOp1ATI; +#endif +#ifndef GLEE_C_DEFINED_glColorFragmentOp2ATI +#define GLEE_C_DEFINED_glColorFragmentOp2ATI + void __stdcall GLee_Lazy_glColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) {if (GLeeInit()) glColorFragmentOp2ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod);} + GLEEPFNGLCOLORFRAGMENTOP2ATIPROC GLeeFuncPtr_glColorFragmentOp2ATI=GLee_Lazy_glColorFragmentOp2ATI; +#endif +#ifndef GLEE_C_DEFINED_glColorFragmentOp3ATI +#define GLEE_C_DEFINED_glColorFragmentOp3ATI + void __stdcall GLee_Lazy_glColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod) {if (GLeeInit()) glColorFragmentOp3ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);} + GLEEPFNGLCOLORFRAGMENTOP3ATIPROC GLeeFuncPtr_glColorFragmentOp3ATI=GLee_Lazy_glColorFragmentOp3ATI; +#endif +#ifndef GLEE_C_DEFINED_glAlphaFragmentOp1ATI +#define GLEE_C_DEFINED_glAlphaFragmentOp1ATI + void __stdcall GLee_Lazy_glAlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) {if (GLeeInit()) glAlphaFragmentOp1ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod);} + GLEEPFNGLALPHAFRAGMENTOP1ATIPROC GLeeFuncPtr_glAlphaFragmentOp1ATI=GLee_Lazy_glAlphaFragmentOp1ATI; +#endif +#ifndef GLEE_C_DEFINED_glAlphaFragmentOp2ATI +#define GLEE_C_DEFINED_glAlphaFragmentOp2ATI + void __stdcall GLee_Lazy_glAlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) {if (GLeeInit()) glAlphaFragmentOp2ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod);} + GLEEPFNGLALPHAFRAGMENTOP2ATIPROC GLeeFuncPtr_glAlphaFragmentOp2ATI=GLee_Lazy_glAlphaFragmentOp2ATI; +#endif +#ifndef GLEE_C_DEFINED_glAlphaFragmentOp3ATI +#define GLEE_C_DEFINED_glAlphaFragmentOp3ATI + void __stdcall GLee_Lazy_glAlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod) {if (GLeeInit()) glAlphaFragmentOp3ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);} + GLEEPFNGLALPHAFRAGMENTOP3ATIPROC GLeeFuncPtr_glAlphaFragmentOp3ATI=GLee_Lazy_glAlphaFragmentOp3ATI; +#endif +#ifndef GLEE_C_DEFINED_glSetFragmentShaderConstantATI +#define GLEE_C_DEFINED_glSetFragmentShaderConstantATI + void __stdcall GLee_Lazy_glSetFragmentShaderConstantATI(GLuint dst, const GLfloat * value) {if (GLeeInit()) glSetFragmentShaderConstantATI(dst, value);} + GLEEPFNGLSETFRAGMENTSHADERCONSTANTATIPROC GLeeFuncPtr_glSetFragmentShaderConstantATI=GLee_Lazy_glSetFragmentShaderConstantATI; +#endif +#endif + +/* GL_ATI_pn_triangles */ + +#ifdef __GLEE_GL_ATI_pn_triangles +#ifndef GLEE_C_DEFINED_glPNTrianglesiATI +#define GLEE_C_DEFINED_glPNTrianglesiATI + void __stdcall GLee_Lazy_glPNTrianglesiATI(GLenum pname, GLint param) {if (GLeeInit()) glPNTrianglesiATI(pname, param);} + GLEEPFNGLPNTRIANGLESIATIPROC GLeeFuncPtr_glPNTrianglesiATI=GLee_Lazy_glPNTrianglesiATI; +#endif +#ifndef GLEE_C_DEFINED_glPNTrianglesfATI +#define GLEE_C_DEFINED_glPNTrianglesfATI + void __stdcall GLee_Lazy_glPNTrianglesfATI(GLenum pname, GLfloat param) {if (GLeeInit()) glPNTrianglesfATI(pname, param);} + GLEEPFNGLPNTRIANGLESFATIPROC GLeeFuncPtr_glPNTrianglesfATI=GLee_Lazy_glPNTrianglesfATI; +#endif +#endif + +/* GL_ATI_vertex_array_object */ + +#ifdef __GLEE_GL_ATI_vertex_array_object +#ifndef GLEE_C_DEFINED_glNewObjectBufferATI +#define GLEE_C_DEFINED_glNewObjectBufferATI + GLuint __stdcall GLee_Lazy_glNewObjectBufferATI(GLsizei size, const GLvoid * pointer, GLenum usage) {if (GLeeInit()) return glNewObjectBufferATI(size, pointer, usage); return (GLuint)0;} + GLEEPFNGLNEWOBJECTBUFFERATIPROC GLeeFuncPtr_glNewObjectBufferATI=GLee_Lazy_glNewObjectBufferATI; +#endif +#ifndef GLEE_C_DEFINED_glIsObjectBufferATI +#define GLEE_C_DEFINED_glIsObjectBufferATI + GLboolean __stdcall GLee_Lazy_glIsObjectBufferATI(GLuint buffer) {if (GLeeInit()) return glIsObjectBufferATI(buffer); return (GLboolean)0;} + GLEEPFNGLISOBJECTBUFFERATIPROC GLeeFuncPtr_glIsObjectBufferATI=GLee_Lazy_glIsObjectBufferATI; +#endif +#ifndef GLEE_C_DEFINED_glUpdateObjectBufferATI +#define GLEE_C_DEFINED_glUpdateObjectBufferATI + void __stdcall GLee_Lazy_glUpdateObjectBufferATI(GLuint buffer, GLuint offset, GLsizei size, const GLvoid * pointer, GLenum preserve) {if (GLeeInit()) glUpdateObjectBufferATI(buffer, offset, size, pointer, preserve);} + GLEEPFNGLUPDATEOBJECTBUFFERATIPROC GLeeFuncPtr_glUpdateObjectBufferATI=GLee_Lazy_glUpdateObjectBufferATI; +#endif +#ifndef GLEE_C_DEFINED_glGetObjectBufferfvATI +#define GLEE_C_DEFINED_glGetObjectBufferfvATI + void __stdcall GLee_Lazy_glGetObjectBufferfvATI(GLuint buffer, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetObjectBufferfvATI(buffer, pname, params);} + GLEEPFNGLGETOBJECTBUFFERFVATIPROC GLeeFuncPtr_glGetObjectBufferfvATI=GLee_Lazy_glGetObjectBufferfvATI; +#endif +#ifndef GLEE_C_DEFINED_glGetObjectBufferivATI +#define GLEE_C_DEFINED_glGetObjectBufferivATI + void __stdcall GLee_Lazy_glGetObjectBufferivATI(GLuint buffer, GLenum pname, GLint * params) {if (GLeeInit()) glGetObjectBufferivATI(buffer, pname, params);} + GLEEPFNGLGETOBJECTBUFFERIVATIPROC GLeeFuncPtr_glGetObjectBufferivATI=GLee_Lazy_glGetObjectBufferivATI; +#endif +#ifndef GLEE_C_DEFINED_glFreeObjectBufferATI +#define GLEE_C_DEFINED_glFreeObjectBufferATI + void __stdcall GLee_Lazy_glFreeObjectBufferATI(GLuint buffer) {if (GLeeInit()) glFreeObjectBufferATI(buffer);} + GLEEPFNGLFREEOBJECTBUFFERATIPROC GLeeFuncPtr_glFreeObjectBufferATI=GLee_Lazy_glFreeObjectBufferATI; +#endif +#ifndef GLEE_C_DEFINED_glArrayObjectATI +#define GLEE_C_DEFINED_glArrayObjectATI + void __stdcall GLee_Lazy_glArrayObjectATI(GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset) {if (GLeeInit()) glArrayObjectATI(array, size, type, stride, buffer, offset);} + GLEEPFNGLARRAYOBJECTATIPROC GLeeFuncPtr_glArrayObjectATI=GLee_Lazy_glArrayObjectATI; +#endif +#ifndef GLEE_C_DEFINED_glGetArrayObjectfvATI +#define GLEE_C_DEFINED_glGetArrayObjectfvATI + void __stdcall GLee_Lazy_glGetArrayObjectfvATI(GLenum array, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetArrayObjectfvATI(array, pname, params);} + GLEEPFNGLGETARRAYOBJECTFVATIPROC GLeeFuncPtr_glGetArrayObjectfvATI=GLee_Lazy_glGetArrayObjectfvATI; +#endif +#ifndef GLEE_C_DEFINED_glGetArrayObjectivATI +#define GLEE_C_DEFINED_glGetArrayObjectivATI + void __stdcall GLee_Lazy_glGetArrayObjectivATI(GLenum array, GLenum pname, GLint * params) {if (GLeeInit()) glGetArrayObjectivATI(array, pname, params);} + GLEEPFNGLGETARRAYOBJECTIVATIPROC GLeeFuncPtr_glGetArrayObjectivATI=GLee_Lazy_glGetArrayObjectivATI; +#endif +#ifndef GLEE_C_DEFINED_glVariantArrayObjectATI +#define GLEE_C_DEFINED_glVariantArrayObjectATI + void __stdcall GLee_Lazy_glVariantArrayObjectATI(GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset) {if (GLeeInit()) glVariantArrayObjectATI(id, type, stride, buffer, offset);} + GLEEPFNGLVARIANTARRAYOBJECTATIPROC GLeeFuncPtr_glVariantArrayObjectATI=GLee_Lazy_glVariantArrayObjectATI; +#endif +#ifndef GLEE_C_DEFINED_glGetVariantArrayObjectfvATI +#define GLEE_C_DEFINED_glGetVariantArrayObjectfvATI + void __stdcall GLee_Lazy_glGetVariantArrayObjectfvATI(GLuint id, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetVariantArrayObjectfvATI(id, pname, params);} + GLEEPFNGLGETVARIANTARRAYOBJECTFVATIPROC GLeeFuncPtr_glGetVariantArrayObjectfvATI=GLee_Lazy_glGetVariantArrayObjectfvATI; +#endif +#ifndef GLEE_C_DEFINED_glGetVariantArrayObjectivATI +#define GLEE_C_DEFINED_glGetVariantArrayObjectivATI + void __stdcall GLee_Lazy_glGetVariantArrayObjectivATI(GLuint id, GLenum pname, GLint * params) {if (GLeeInit()) glGetVariantArrayObjectivATI(id, pname, params);} + GLEEPFNGLGETVARIANTARRAYOBJECTIVATIPROC GLeeFuncPtr_glGetVariantArrayObjectivATI=GLee_Lazy_glGetVariantArrayObjectivATI; +#endif +#endif + +/* GL_EXT_vertex_shader */ + +#ifdef __GLEE_GL_EXT_vertex_shader +#ifndef GLEE_C_DEFINED_glBeginVertexShaderEXT +#define GLEE_C_DEFINED_glBeginVertexShaderEXT + void __stdcall GLee_Lazy_glBeginVertexShaderEXT(void) {if (GLeeInit()) glBeginVertexShaderEXT();} + GLEEPFNGLBEGINVERTEXSHADEREXTPROC GLeeFuncPtr_glBeginVertexShaderEXT=GLee_Lazy_glBeginVertexShaderEXT; +#endif +#ifndef GLEE_C_DEFINED_glEndVertexShaderEXT +#define GLEE_C_DEFINED_glEndVertexShaderEXT + void __stdcall GLee_Lazy_glEndVertexShaderEXT(void) {if (GLeeInit()) glEndVertexShaderEXT();} + GLEEPFNGLENDVERTEXSHADEREXTPROC GLeeFuncPtr_glEndVertexShaderEXT=GLee_Lazy_glEndVertexShaderEXT; +#endif +#ifndef GLEE_C_DEFINED_glBindVertexShaderEXT +#define GLEE_C_DEFINED_glBindVertexShaderEXT + void __stdcall GLee_Lazy_glBindVertexShaderEXT(GLuint id) {if (GLeeInit()) glBindVertexShaderEXT(id);} + GLEEPFNGLBINDVERTEXSHADEREXTPROC GLeeFuncPtr_glBindVertexShaderEXT=GLee_Lazy_glBindVertexShaderEXT; +#endif +#ifndef GLEE_C_DEFINED_glGenVertexShadersEXT +#define GLEE_C_DEFINED_glGenVertexShadersEXT + GLuint __stdcall GLee_Lazy_glGenVertexShadersEXT(GLuint range) {if (GLeeInit()) return glGenVertexShadersEXT(range); return (GLuint)0;} + GLEEPFNGLGENVERTEXSHADERSEXTPROC GLeeFuncPtr_glGenVertexShadersEXT=GLee_Lazy_glGenVertexShadersEXT; +#endif +#ifndef GLEE_C_DEFINED_glDeleteVertexShaderEXT +#define GLEE_C_DEFINED_glDeleteVertexShaderEXT + void __stdcall GLee_Lazy_glDeleteVertexShaderEXT(GLuint id) {if (GLeeInit()) glDeleteVertexShaderEXT(id);} + GLEEPFNGLDELETEVERTEXSHADEREXTPROC GLeeFuncPtr_glDeleteVertexShaderEXT=GLee_Lazy_glDeleteVertexShaderEXT; +#endif +#ifndef GLEE_C_DEFINED_glShaderOp1EXT +#define GLEE_C_DEFINED_glShaderOp1EXT + void __stdcall GLee_Lazy_glShaderOp1EXT(GLenum op, GLuint res, GLuint arg1) {if (GLeeInit()) glShaderOp1EXT(op, res, arg1);} + GLEEPFNGLSHADEROP1EXTPROC GLeeFuncPtr_glShaderOp1EXT=GLee_Lazy_glShaderOp1EXT; +#endif +#ifndef GLEE_C_DEFINED_glShaderOp2EXT +#define GLEE_C_DEFINED_glShaderOp2EXT + void __stdcall GLee_Lazy_glShaderOp2EXT(GLenum op, GLuint res, GLuint arg1, GLuint arg2) {if (GLeeInit()) glShaderOp2EXT(op, res, arg1, arg2);} + GLEEPFNGLSHADEROP2EXTPROC GLeeFuncPtr_glShaderOp2EXT=GLee_Lazy_glShaderOp2EXT; +#endif +#ifndef GLEE_C_DEFINED_glShaderOp3EXT +#define GLEE_C_DEFINED_glShaderOp3EXT + void __stdcall GLee_Lazy_glShaderOp3EXT(GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3) {if (GLeeInit()) glShaderOp3EXT(op, res, arg1, arg2, arg3);} + GLEEPFNGLSHADEROP3EXTPROC GLeeFuncPtr_glShaderOp3EXT=GLee_Lazy_glShaderOp3EXT; +#endif +#ifndef GLEE_C_DEFINED_glSwizzleEXT +#define GLEE_C_DEFINED_glSwizzleEXT + void __stdcall GLee_Lazy_glSwizzleEXT(GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW) {if (GLeeInit()) glSwizzleEXT(res, in, outX, outY, outZ, outW);} + GLEEPFNGLSWIZZLEEXTPROC GLeeFuncPtr_glSwizzleEXT=GLee_Lazy_glSwizzleEXT; +#endif +#ifndef GLEE_C_DEFINED_glWriteMaskEXT +#define GLEE_C_DEFINED_glWriteMaskEXT + void __stdcall GLee_Lazy_glWriteMaskEXT(GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW) {if (GLeeInit()) glWriteMaskEXT(res, in, outX, outY, outZ, outW);} + GLEEPFNGLWRITEMASKEXTPROC GLeeFuncPtr_glWriteMaskEXT=GLee_Lazy_glWriteMaskEXT; +#endif +#ifndef GLEE_C_DEFINED_glInsertComponentEXT +#define GLEE_C_DEFINED_glInsertComponentEXT + void __stdcall GLee_Lazy_glInsertComponentEXT(GLuint res, GLuint src, GLuint num) {if (GLeeInit()) glInsertComponentEXT(res, src, num);} + GLEEPFNGLINSERTCOMPONENTEXTPROC GLeeFuncPtr_glInsertComponentEXT=GLee_Lazy_glInsertComponentEXT; +#endif +#ifndef GLEE_C_DEFINED_glExtractComponentEXT +#define GLEE_C_DEFINED_glExtractComponentEXT + void __stdcall GLee_Lazy_glExtractComponentEXT(GLuint res, GLuint src, GLuint num) {if (GLeeInit()) glExtractComponentEXT(res, src, num);} + GLEEPFNGLEXTRACTCOMPONENTEXTPROC GLeeFuncPtr_glExtractComponentEXT=GLee_Lazy_glExtractComponentEXT; +#endif +#ifndef GLEE_C_DEFINED_glGenSymbolsEXT +#define GLEE_C_DEFINED_glGenSymbolsEXT + GLuint __stdcall GLee_Lazy_glGenSymbolsEXT(GLenum datatype, GLenum storagetype, GLenum range, GLuint components) {if (GLeeInit()) return glGenSymbolsEXT(datatype, storagetype, range, components); return (GLuint)0;} + GLEEPFNGLGENSYMBOLSEXTPROC GLeeFuncPtr_glGenSymbolsEXT=GLee_Lazy_glGenSymbolsEXT; +#endif +#ifndef GLEE_C_DEFINED_glSetInvariantEXT +#define GLEE_C_DEFINED_glSetInvariantEXT + void __stdcall GLee_Lazy_glSetInvariantEXT(GLuint id, GLenum type, const GLvoid * addr) {if (GLeeInit()) glSetInvariantEXT(id, type, addr);} + GLEEPFNGLSETINVARIANTEXTPROC GLeeFuncPtr_glSetInvariantEXT=GLee_Lazy_glSetInvariantEXT; +#endif +#ifndef GLEE_C_DEFINED_glSetLocalConstantEXT +#define GLEE_C_DEFINED_glSetLocalConstantEXT + void __stdcall GLee_Lazy_glSetLocalConstantEXT(GLuint id, GLenum type, const GLvoid * addr) {if (GLeeInit()) glSetLocalConstantEXT(id, type, addr);} + GLEEPFNGLSETLOCALCONSTANTEXTPROC GLeeFuncPtr_glSetLocalConstantEXT=GLee_Lazy_glSetLocalConstantEXT; +#endif +#ifndef GLEE_C_DEFINED_glVariantbvEXT +#define GLEE_C_DEFINED_glVariantbvEXT + void __stdcall GLee_Lazy_glVariantbvEXT(GLuint id, const GLbyte * addr) {if (GLeeInit()) glVariantbvEXT(id, addr);} + GLEEPFNGLVARIANTBVEXTPROC GLeeFuncPtr_glVariantbvEXT=GLee_Lazy_glVariantbvEXT; +#endif +#ifndef GLEE_C_DEFINED_glVariantsvEXT +#define GLEE_C_DEFINED_glVariantsvEXT + void __stdcall GLee_Lazy_glVariantsvEXT(GLuint id, const GLshort * addr) {if (GLeeInit()) glVariantsvEXT(id, addr);} + GLEEPFNGLVARIANTSVEXTPROC GLeeFuncPtr_glVariantsvEXT=GLee_Lazy_glVariantsvEXT; +#endif +#ifndef GLEE_C_DEFINED_glVariantivEXT +#define GLEE_C_DEFINED_glVariantivEXT + void __stdcall GLee_Lazy_glVariantivEXT(GLuint id, const GLint * addr) {if (GLeeInit()) glVariantivEXT(id, addr);} + GLEEPFNGLVARIANTIVEXTPROC GLeeFuncPtr_glVariantivEXT=GLee_Lazy_glVariantivEXT; +#endif +#ifndef GLEE_C_DEFINED_glVariantfvEXT +#define GLEE_C_DEFINED_glVariantfvEXT + void __stdcall GLee_Lazy_glVariantfvEXT(GLuint id, const GLfloat * addr) {if (GLeeInit()) glVariantfvEXT(id, addr);} + GLEEPFNGLVARIANTFVEXTPROC GLeeFuncPtr_glVariantfvEXT=GLee_Lazy_glVariantfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glVariantdvEXT +#define GLEE_C_DEFINED_glVariantdvEXT + void __stdcall GLee_Lazy_glVariantdvEXT(GLuint id, const GLdouble * addr) {if (GLeeInit()) glVariantdvEXT(id, addr);} + GLEEPFNGLVARIANTDVEXTPROC GLeeFuncPtr_glVariantdvEXT=GLee_Lazy_glVariantdvEXT; +#endif +#ifndef GLEE_C_DEFINED_glVariantubvEXT +#define GLEE_C_DEFINED_glVariantubvEXT + void __stdcall GLee_Lazy_glVariantubvEXT(GLuint id, const GLubyte * addr) {if (GLeeInit()) glVariantubvEXT(id, addr);} + GLEEPFNGLVARIANTUBVEXTPROC GLeeFuncPtr_glVariantubvEXT=GLee_Lazy_glVariantubvEXT; +#endif +#ifndef GLEE_C_DEFINED_glVariantusvEXT +#define GLEE_C_DEFINED_glVariantusvEXT + void __stdcall GLee_Lazy_glVariantusvEXT(GLuint id, const GLushort * addr) {if (GLeeInit()) glVariantusvEXT(id, addr);} + GLEEPFNGLVARIANTUSVEXTPROC GLeeFuncPtr_glVariantusvEXT=GLee_Lazy_glVariantusvEXT; +#endif +#ifndef GLEE_C_DEFINED_glVariantuivEXT +#define GLEE_C_DEFINED_glVariantuivEXT + void __stdcall GLee_Lazy_glVariantuivEXT(GLuint id, const GLuint * addr) {if (GLeeInit()) glVariantuivEXT(id, addr);} + GLEEPFNGLVARIANTUIVEXTPROC GLeeFuncPtr_glVariantuivEXT=GLee_Lazy_glVariantuivEXT; +#endif +#ifndef GLEE_C_DEFINED_glVariantPointerEXT +#define GLEE_C_DEFINED_glVariantPointerEXT + void __stdcall GLee_Lazy_glVariantPointerEXT(GLuint id, GLenum type, GLuint stride, const GLvoid * addr) {if (GLeeInit()) glVariantPointerEXT(id, type, stride, addr);} + GLEEPFNGLVARIANTPOINTEREXTPROC GLeeFuncPtr_glVariantPointerEXT=GLee_Lazy_glVariantPointerEXT; +#endif +#ifndef GLEE_C_DEFINED_glEnableVariantClientStateEXT +#define GLEE_C_DEFINED_glEnableVariantClientStateEXT + void __stdcall GLee_Lazy_glEnableVariantClientStateEXT(GLuint id) {if (GLeeInit()) glEnableVariantClientStateEXT(id);} + GLEEPFNGLENABLEVARIANTCLIENTSTATEEXTPROC GLeeFuncPtr_glEnableVariantClientStateEXT=GLee_Lazy_glEnableVariantClientStateEXT; +#endif +#ifndef GLEE_C_DEFINED_glDisableVariantClientStateEXT +#define GLEE_C_DEFINED_glDisableVariantClientStateEXT + void __stdcall GLee_Lazy_glDisableVariantClientStateEXT(GLuint id) {if (GLeeInit()) glDisableVariantClientStateEXT(id);} + GLEEPFNGLDISABLEVARIANTCLIENTSTATEEXTPROC GLeeFuncPtr_glDisableVariantClientStateEXT=GLee_Lazy_glDisableVariantClientStateEXT; +#endif +#ifndef GLEE_C_DEFINED_glBindLightParameterEXT +#define GLEE_C_DEFINED_glBindLightParameterEXT + GLuint __stdcall GLee_Lazy_glBindLightParameterEXT(GLenum light, GLenum value) {if (GLeeInit()) return glBindLightParameterEXT(light, value); return (GLuint)0;} + GLEEPFNGLBINDLIGHTPARAMETEREXTPROC GLeeFuncPtr_glBindLightParameterEXT=GLee_Lazy_glBindLightParameterEXT; +#endif +#ifndef GLEE_C_DEFINED_glBindMaterialParameterEXT +#define GLEE_C_DEFINED_glBindMaterialParameterEXT + GLuint __stdcall GLee_Lazy_glBindMaterialParameterEXT(GLenum face, GLenum value) {if (GLeeInit()) return glBindMaterialParameterEXT(face, value); return (GLuint)0;} + GLEEPFNGLBINDMATERIALPARAMETEREXTPROC GLeeFuncPtr_glBindMaterialParameterEXT=GLee_Lazy_glBindMaterialParameterEXT; +#endif +#ifndef GLEE_C_DEFINED_glBindTexGenParameterEXT +#define GLEE_C_DEFINED_glBindTexGenParameterEXT + GLuint __stdcall GLee_Lazy_glBindTexGenParameterEXT(GLenum unit, GLenum coord, GLenum value) {if (GLeeInit()) return glBindTexGenParameterEXT(unit, coord, value); return (GLuint)0;} + GLEEPFNGLBINDTEXGENPARAMETEREXTPROC GLeeFuncPtr_glBindTexGenParameterEXT=GLee_Lazy_glBindTexGenParameterEXT; +#endif +#ifndef GLEE_C_DEFINED_glBindTextureUnitParameterEXT +#define GLEE_C_DEFINED_glBindTextureUnitParameterEXT + GLuint __stdcall GLee_Lazy_glBindTextureUnitParameterEXT(GLenum unit, GLenum value) {if (GLeeInit()) return glBindTextureUnitParameterEXT(unit, value); return (GLuint)0;} + GLEEPFNGLBINDTEXTUREUNITPARAMETEREXTPROC GLeeFuncPtr_glBindTextureUnitParameterEXT=GLee_Lazy_glBindTextureUnitParameterEXT; +#endif +#ifndef GLEE_C_DEFINED_glBindParameterEXT +#define GLEE_C_DEFINED_glBindParameterEXT + GLuint __stdcall GLee_Lazy_glBindParameterEXT(GLenum value) {if (GLeeInit()) return glBindParameterEXT(value); return (GLuint)0;} + GLEEPFNGLBINDPARAMETEREXTPROC GLeeFuncPtr_glBindParameterEXT=GLee_Lazy_glBindParameterEXT; +#endif +#ifndef GLEE_C_DEFINED_glIsVariantEnabledEXT +#define GLEE_C_DEFINED_glIsVariantEnabledEXT + GLboolean __stdcall GLee_Lazy_glIsVariantEnabledEXT(GLuint id, GLenum cap) {if (GLeeInit()) return glIsVariantEnabledEXT(id, cap); return (GLboolean)0;} + GLEEPFNGLISVARIANTENABLEDEXTPROC GLeeFuncPtr_glIsVariantEnabledEXT=GLee_Lazy_glIsVariantEnabledEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetVariantBooleanvEXT +#define GLEE_C_DEFINED_glGetVariantBooleanvEXT + void __stdcall GLee_Lazy_glGetVariantBooleanvEXT(GLuint id, GLenum value, GLboolean * data) {if (GLeeInit()) glGetVariantBooleanvEXT(id, value, data);} + GLEEPFNGLGETVARIANTBOOLEANVEXTPROC GLeeFuncPtr_glGetVariantBooleanvEXT=GLee_Lazy_glGetVariantBooleanvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetVariantIntegervEXT +#define GLEE_C_DEFINED_glGetVariantIntegervEXT + void __stdcall GLee_Lazy_glGetVariantIntegervEXT(GLuint id, GLenum value, GLint * data) {if (GLeeInit()) glGetVariantIntegervEXT(id, value, data);} + GLEEPFNGLGETVARIANTINTEGERVEXTPROC GLeeFuncPtr_glGetVariantIntegervEXT=GLee_Lazy_glGetVariantIntegervEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetVariantFloatvEXT +#define GLEE_C_DEFINED_glGetVariantFloatvEXT + void __stdcall GLee_Lazy_glGetVariantFloatvEXT(GLuint id, GLenum value, GLfloat * data) {if (GLeeInit()) glGetVariantFloatvEXT(id, value, data);} + GLEEPFNGLGETVARIANTFLOATVEXTPROC GLeeFuncPtr_glGetVariantFloatvEXT=GLee_Lazy_glGetVariantFloatvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetVariantPointervEXT +#define GLEE_C_DEFINED_glGetVariantPointervEXT + void __stdcall GLee_Lazy_glGetVariantPointervEXT(GLuint id, GLenum value, GLvoid* * data) {if (GLeeInit()) glGetVariantPointervEXT(id, value, data);} + GLEEPFNGLGETVARIANTPOINTERVEXTPROC GLeeFuncPtr_glGetVariantPointervEXT=GLee_Lazy_glGetVariantPointervEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetInvariantBooleanvEXT +#define GLEE_C_DEFINED_glGetInvariantBooleanvEXT + void __stdcall GLee_Lazy_glGetInvariantBooleanvEXT(GLuint id, GLenum value, GLboolean * data) {if (GLeeInit()) glGetInvariantBooleanvEXT(id, value, data);} + GLEEPFNGLGETINVARIANTBOOLEANVEXTPROC GLeeFuncPtr_glGetInvariantBooleanvEXT=GLee_Lazy_glGetInvariantBooleanvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetInvariantIntegervEXT +#define GLEE_C_DEFINED_glGetInvariantIntegervEXT + void __stdcall GLee_Lazy_glGetInvariantIntegervEXT(GLuint id, GLenum value, GLint * data) {if (GLeeInit()) glGetInvariantIntegervEXT(id, value, data);} + GLEEPFNGLGETINVARIANTINTEGERVEXTPROC GLeeFuncPtr_glGetInvariantIntegervEXT=GLee_Lazy_glGetInvariantIntegervEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetInvariantFloatvEXT +#define GLEE_C_DEFINED_glGetInvariantFloatvEXT + void __stdcall GLee_Lazy_glGetInvariantFloatvEXT(GLuint id, GLenum value, GLfloat * data) {if (GLeeInit()) glGetInvariantFloatvEXT(id, value, data);} + GLEEPFNGLGETINVARIANTFLOATVEXTPROC GLeeFuncPtr_glGetInvariantFloatvEXT=GLee_Lazy_glGetInvariantFloatvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetLocalConstantBooleanvEXT +#define GLEE_C_DEFINED_glGetLocalConstantBooleanvEXT + void __stdcall GLee_Lazy_glGetLocalConstantBooleanvEXT(GLuint id, GLenum value, GLboolean * data) {if (GLeeInit()) glGetLocalConstantBooleanvEXT(id, value, data);} + GLEEPFNGLGETLOCALCONSTANTBOOLEANVEXTPROC GLeeFuncPtr_glGetLocalConstantBooleanvEXT=GLee_Lazy_glGetLocalConstantBooleanvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetLocalConstantIntegervEXT +#define GLEE_C_DEFINED_glGetLocalConstantIntegervEXT + void __stdcall GLee_Lazy_glGetLocalConstantIntegervEXT(GLuint id, GLenum value, GLint * data) {if (GLeeInit()) glGetLocalConstantIntegervEXT(id, value, data);} + GLEEPFNGLGETLOCALCONSTANTINTEGERVEXTPROC GLeeFuncPtr_glGetLocalConstantIntegervEXT=GLee_Lazy_glGetLocalConstantIntegervEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetLocalConstantFloatvEXT +#define GLEE_C_DEFINED_glGetLocalConstantFloatvEXT + void __stdcall GLee_Lazy_glGetLocalConstantFloatvEXT(GLuint id, GLenum value, GLfloat * data) {if (GLeeInit()) glGetLocalConstantFloatvEXT(id, value, data);} + GLEEPFNGLGETLOCALCONSTANTFLOATVEXTPROC GLeeFuncPtr_glGetLocalConstantFloatvEXT=GLee_Lazy_glGetLocalConstantFloatvEXT; +#endif +#endif + +/* GL_ATI_vertex_streams */ + +#ifdef __GLEE_GL_ATI_vertex_streams +#ifndef GLEE_C_DEFINED_glVertexStream1sATI +#define GLEE_C_DEFINED_glVertexStream1sATI + void __stdcall GLee_Lazy_glVertexStream1sATI(GLenum stream, GLshort x) {if (GLeeInit()) glVertexStream1sATI(stream, x);} + GLEEPFNGLVERTEXSTREAM1SATIPROC GLeeFuncPtr_glVertexStream1sATI=GLee_Lazy_glVertexStream1sATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream1svATI +#define GLEE_C_DEFINED_glVertexStream1svATI + void __stdcall GLee_Lazy_glVertexStream1svATI(GLenum stream, const GLshort * coords) {if (GLeeInit()) glVertexStream1svATI(stream, coords);} + GLEEPFNGLVERTEXSTREAM1SVATIPROC GLeeFuncPtr_glVertexStream1svATI=GLee_Lazy_glVertexStream1svATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream1iATI +#define GLEE_C_DEFINED_glVertexStream1iATI + void __stdcall GLee_Lazy_glVertexStream1iATI(GLenum stream, GLint x) {if (GLeeInit()) glVertexStream1iATI(stream, x);} + GLEEPFNGLVERTEXSTREAM1IATIPROC GLeeFuncPtr_glVertexStream1iATI=GLee_Lazy_glVertexStream1iATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream1ivATI +#define GLEE_C_DEFINED_glVertexStream1ivATI + void __stdcall GLee_Lazy_glVertexStream1ivATI(GLenum stream, const GLint * coords) {if (GLeeInit()) glVertexStream1ivATI(stream, coords);} + GLEEPFNGLVERTEXSTREAM1IVATIPROC GLeeFuncPtr_glVertexStream1ivATI=GLee_Lazy_glVertexStream1ivATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream1fATI +#define GLEE_C_DEFINED_glVertexStream1fATI + void __stdcall GLee_Lazy_glVertexStream1fATI(GLenum stream, GLfloat x) {if (GLeeInit()) glVertexStream1fATI(stream, x);} + GLEEPFNGLVERTEXSTREAM1FATIPROC GLeeFuncPtr_glVertexStream1fATI=GLee_Lazy_glVertexStream1fATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream1fvATI +#define GLEE_C_DEFINED_glVertexStream1fvATI + void __stdcall GLee_Lazy_glVertexStream1fvATI(GLenum stream, const GLfloat * coords) {if (GLeeInit()) glVertexStream1fvATI(stream, coords);} + GLEEPFNGLVERTEXSTREAM1FVATIPROC GLeeFuncPtr_glVertexStream1fvATI=GLee_Lazy_glVertexStream1fvATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream1dATI +#define GLEE_C_DEFINED_glVertexStream1dATI + void __stdcall GLee_Lazy_glVertexStream1dATI(GLenum stream, GLdouble x) {if (GLeeInit()) glVertexStream1dATI(stream, x);} + GLEEPFNGLVERTEXSTREAM1DATIPROC GLeeFuncPtr_glVertexStream1dATI=GLee_Lazy_glVertexStream1dATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream1dvATI +#define GLEE_C_DEFINED_glVertexStream1dvATI + void __stdcall GLee_Lazy_glVertexStream1dvATI(GLenum stream, const GLdouble * coords) {if (GLeeInit()) glVertexStream1dvATI(stream, coords);} + GLEEPFNGLVERTEXSTREAM1DVATIPROC GLeeFuncPtr_glVertexStream1dvATI=GLee_Lazy_glVertexStream1dvATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream2sATI +#define GLEE_C_DEFINED_glVertexStream2sATI + void __stdcall GLee_Lazy_glVertexStream2sATI(GLenum stream, GLshort x, GLshort y) {if (GLeeInit()) glVertexStream2sATI(stream, x, y);} + GLEEPFNGLVERTEXSTREAM2SATIPROC GLeeFuncPtr_glVertexStream2sATI=GLee_Lazy_glVertexStream2sATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream2svATI +#define GLEE_C_DEFINED_glVertexStream2svATI + void __stdcall GLee_Lazy_glVertexStream2svATI(GLenum stream, const GLshort * coords) {if (GLeeInit()) glVertexStream2svATI(stream, coords);} + GLEEPFNGLVERTEXSTREAM2SVATIPROC GLeeFuncPtr_glVertexStream2svATI=GLee_Lazy_glVertexStream2svATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream2iATI +#define GLEE_C_DEFINED_glVertexStream2iATI + void __stdcall GLee_Lazy_glVertexStream2iATI(GLenum stream, GLint x, GLint y) {if (GLeeInit()) glVertexStream2iATI(stream, x, y);} + GLEEPFNGLVERTEXSTREAM2IATIPROC GLeeFuncPtr_glVertexStream2iATI=GLee_Lazy_glVertexStream2iATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream2ivATI +#define GLEE_C_DEFINED_glVertexStream2ivATI + void __stdcall GLee_Lazy_glVertexStream2ivATI(GLenum stream, const GLint * coords) {if (GLeeInit()) glVertexStream2ivATI(stream, coords);} + GLEEPFNGLVERTEXSTREAM2IVATIPROC GLeeFuncPtr_glVertexStream2ivATI=GLee_Lazy_glVertexStream2ivATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream2fATI +#define GLEE_C_DEFINED_glVertexStream2fATI + void __stdcall GLee_Lazy_glVertexStream2fATI(GLenum stream, GLfloat x, GLfloat y) {if (GLeeInit()) glVertexStream2fATI(stream, x, y);} + GLEEPFNGLVERTEXSTREAM2FATIPROC GLeeFuncPtr_glVertexStream2fATI=GLee_Lazy_glVertexStream2fATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream2fvATI +#define GLEE_C_DEFINED_glVertexStream2fvATI + void __stdcall GLee_Lazy_glVertexStream2fvATI(GLenum stream, const GLfloat * coords) {if (GLeeInit()) glVertexStream2fvATI(stream, coords);} + GLEEPFNGLVERTEXSTREAM2FVATIPROC GLeeFuncPtr_glVertexStream2fvATI=GLee_Lazy_glVertexStream2fvATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream2dATI +#define GLEE_C_DEFINED_glVertexStream2dATI + void __stdcall GLee_Lazy_glVertexStream2dATI(GLenum stream, GLdouble x, GLdouble y) {if (GLeeInit()) glVertexStream2dATI(stream, x, y);} + GLEEPFNGLVERTEXSTREAM2DATIPROC GLeeFuncPtr_glVertexStream2dATI=GLee_Lazy_glVertexStream2dATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream2dvATI +#define GLEE_C_DEFINED_glVertexStream2dvATI + void __stdcall GLee_Lazy_glVertexStream2dvATI(GLenum stream, const GLdouble * coords) {if (GLeeInit()) glVertexStream2dvATI(stream, coords);} + GLEEPFNGLVERTEXSTREAM2DVATIPROC GLeeFuncPtr_glVertexStream2dvATI=GLee_Lazy_glVertexStream2dvATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream3sATI +#define GLEE_C_DEFINED_glVertexStream3sATI + void __stdcall GLee_Lazy_glVertexStream3sATI(GLenum stream, GLshort x, GLshort y, GLshort z) {if (GLeeInit()) glVertexStream3sATI(stream, x, y, z);} + GLEEPFNGLVERTEXSTREAM3SATIPROC GLeeFuncPtr_glVertexStream3sATI=GLee_Lazy_glVertexStream3sATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream3svATI +#define GLEE_C_DEFINED_glVertexStream3svATI + void __stdcall GLee_Lazy_glVertexStream3svATI(GLenum stream, const GLshort * coords) {if (GLeeInit()) glVertexStream3svATI(stream, coords);} + GLEEPFNGLVERTEXSTREAM3SVATIPROC GLeeFuncPtr_glVertexStream3svATI=GLee_Lazy_glVertexStream3svATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream3iATI +#define GLEE_C_DEFINED_glVertexStream3iATI + void __stdcall GLee_Lazy_glVertexStream3iATI(GLenum stream, GLint x, GLint y, GLint z) {if (GLeeInit()) glVertexStream3iATI(stream, x, y, z);} + GLEEPFNGLVERTEXSTREAM3IATIPROC GLeeFuncPtr_glVertexStream3iATI=GLee_Lazy_glVertexStream3iATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream3ivATI +#define GLEE_C_DEFINED_glVertexStream3ivATI + void __stdcall GLee_Lazy_glVertexStream3ivATI(GLenum stream, const GLint * coords) {if (GLeeInit()) glVertexStream3ivATI(stream, coords);} + GLEEPFNGLVERTEXSTREAM3IVATIPROC GLeeFuncPtr_glVertexStream3ivATI=GLee_Lazy_glVertexStream3ivATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream3fATI +#define GLEE_C_DEFINED_glVertexStream3fATI + void __stdcall GLee_Lazy_glVertexStream3fATI(GLenum stream, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glVertexStream3fATI(stream, x, y, z);} + GLEEPFNGLVERTEXSTREAM3FATIPROC GLeeFuncPtr_glVertexStream3fATI=GLee_Lazy_glVertexStream3fATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream3fvATI +#define GLEE_C_DEFINED_glVertexStream3fvATI + void __stdcall GLee_Lazy_glVertexStream3fvATI(GLenum stream, const GLfloat * coords) {if (GLeeInit()) glVertexStream3fvATI(stream, coords);} + GLEEPFNGLVERTEXSTREAM3FVATIPROC GLeeFuncPtr_glVertexStream3fvATI=GLee_Lazy_glVertexStream3fvATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream3dATI +#define GLEE_C_DEFINED_glVertexStream3dATI + void __stdcall GLee_Lazy_glVertexStream3dATI(GLenum stream, GLdouble x, GLdouble y, GLdouble z) {if (GLeeInit()) glVertexStream3dATI(stream, x, y, z);} + GLEEPFNGLVERTEXSTREAM3DATIPROC GLeeFuncPtr_glVertexStream3dATI=GLee_Lazy_glVertexStream3dATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream3dvATI +#define GLEE_C_DEFINED_glVertexStream3dvATI + void __stdcall GLee_Lazy_glVertexStream3dvATI(GLenum stream, const GLdouble * coords) {if (GLeeInit()) glVertexStream3dvATI(stream, coords);} + GLEEPFNGLVERTEXSTREAM3DVATIPROC GLeeFuncPtr_glVertexStream3dvATI=GLee_Lazy_glVertexStream3dvATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream4sATI +#define GLEE_C_DEFINED_glVertexStream4sATI + void __stdcall GLee_Lazy_glVertexStream4sATI(GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w) {if (GLeeInit()) glVertexStream4sATI(stream, x, y, z, w);} + GLEEPFNGLVERTEXSTREAM4SATIPROC GLeeFuncPtr_glVertexStream4sATI=GLee_Lazy_glVertexStream4sATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream4svATI +#define GLEE_C_DEFINED_glVertexStream4svATI + void __stdcall GLee_Lazy_glVertexStream4svATI(GLenum stream, const GLshort * coords) {if (GLeeInit()) glVertexStream4svATI(stream, coords);} + GLEEPFNGLVERTEXSTREAM4SVATIPROC GLeeFuncPtr_glVertexStream4svATI=GLee_Lazy_glVertexStream4svATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream4iATI +#define GLEE_C_DEFINED_glVertexStream4iATI + void __stdcall GLee_Lazy_glVertexStream4iATI(GLenum stream, GLint x, GLint y, GLint z, GLint w) {if (GLeeInit()) glVertexStream4iATI(stream, x, y, z, w);} + GLEEPFNGLVERTEXSTREAM4IATIPROC GLeeFuncPtr_glVertexStream4iATI=GLee_Lazy_glVertexStream4iATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream4ivATI +#define GLEE_C_DEFINED_glVertexStream4ivATI + void __stdcall GLee_Lazy_glVertexStream4ivATI(GLenum stream, const GLint * coords) {if (GLeeInit()) glVertexStream4ivATI(stream, coords);} + GLEEPFNGLVERTEXSTREAM4IVATIPROC GLeeFuncPtr_glVertexStream4ivATI=GLee_Lazy_glVertexStream4ivATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream4fATI +#define GLEE_C_DEFINED_glVertexStream4fATI + void __stdcall GLee_Lazy_glVertexStream4fATI(GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {if (GLeeInit()) glVertexStream4fATI(stream, x, y, z, w);} + GLEEPFNGLVERTEXSTREAM4FATIPROC GLeeFuncPtr_glVertexStream4fATI=GLee_Lazy_glVertexStream4fATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream4fvATI +#define GLEE_C_DEFINED_glVertexStream4fvATI + void __stdcall GLee_Lazy_glVertexStream4fvATI(GLenum stream, const GLfloat * coords) {if (GLeeInit()) glVertexStream4fvATI(stream, coords);} + GLEEPFNGLVERTEXSTREAM4FVATIPROC GLeeFuncPtr_glVertexStream4fvATI=GLee_Lazy_glVertexStream4fvATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream4dATI +#define GLEE_C_DEFINED_glVertexStream4dATI + void __stdcall GLee_Lazy_glVertexStream4dATI(GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w) {if (GLeeInit()) glVertexStream4dATI(stream, x, y, z, w);} + GLEEPFNGLVERTEXSTREAM4DATIPROC GLeeFuncPtr_glVertexStream4dATI=GLee_Lazy_glVertexStream4dATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexStream4dvATI +#define GLEE_C_DEFINED_glVertexStream4dvATI + void __stdcall GLee_Lazy_glVertexStream4dvATI(GLenum stream, const GLdouble * coords) {if (GLeeInit()) glVertexStream4dvATI(stream, coords);} + GLEEPFNGLVERTEXSTREAM4DVATIPROC GLeeFuncPtr_glVertexStream4dvATI=GLee_Lazy_glVertexStream4dvATI; +#endif +#ifndef GLEE_C_DEFINED_glNormalStream3bATI +#define GLEE_C_DEFINED_glNormalStream3bATI + void __stdcall GLee_Lazy_glNormalStream3bATI(GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz) {if (GLeeInit()) glNormalStream3bATI(stream, nx, ny, nz);} + GLEEPFNGLNORMALSTREAM3BATIPROC GLeeFuncPtr_glNormalStream3bATI=GLee_Lazy_glNormalStream3bATI; +#endif +#ifndef GLEE_C_DEFINED_glNormalStream3bvATI +#define GLEE_C_DEFINED_glNormalStream3bvATI + void __stdcall GLee_Lazy_glNormalStream3bvATI(GLenum stream, const GLbyte * coords) {if (GLeeInit()) glNormalStream3bvATI(stream, coords);} + GLEEPFNGLNORMALSTREAM3BVATIPROC GLeeFuncPtr_glNormalStream3bvATI=GLee_Lazy_glNormalStream3bvATI; +#endif +#ifndef GLEE_C_DEFINED_glNormalStream3sATI +#define GLEE_C_DEFINED_glNormalStream3sATI + void __stdcall GLee_Lazy_glNormalStream3sATI(GLenum stream, GLshort nx, GLshort ny, GLshort nz) {if (GLeeInit()) glNormalStream3sATI(stream, nx, ny, nz);} + GLEEPFNGLNORMALSTREAM3SATIPROC GLeeFuncPtr_glNormalStream3sATI=GLee_Lazy_glNormalStream3sATI; +#endif +#ifndef GLEE_C_DEFINED_glNormalStream3svATI +#define GLEE_C_DEFINED_glNormalStream3svATI + void __stdcall GLee_Lazy_glNormalStream3svATI(GLenum stream, const GLshort * coords) {if (GLeeInit()) glNormalStream3svATI(stream, coords);} + GLEEPFNGLNORMALSTREAM3SVATIPROC GLeeFuncPtr_glNormalStream3svATI=GLee_Lazy_glNormalStream3svATI; +#endif +#ifndef GLEE_C_DEFINED_glNormalStream3iATI +#define GLEE_C_DEFINED_glNormalStream3iATI + void __stdcall GLee_Lazy_glNormalStream3iATI(GLenum stream, GLint nx, GLint ny, GLint nz) {if (GLeeInit()) glNormalStream3iATI(stream, nx, ny, nz);} + GLEEPFNGLNORMALSTREAM3IATIPROC GLeeFuncPtr_glNormalStream3iATI=GLee_Lazy_glNormalStream3iATI; +#endif +#ifndef GLEE_C_DEFINED_glNormalStream3ivATI +#define GLEE_C_DEFINED_glNormalStream3ivATI + void __stdcall GLee_Lazy_glNormalStream3ivATI(GLenum stream, const GLint * coords) {if (GLeeInit()) glNormalStream3ivATI(stream, coords);} + GLEEPFNGLNORMALSTREAM3IVATIPROC GLeeFuncPtr_glNormalStream3ivATI=GLee_Lazy_glNormalStream3ivATI; +#endif +#ifndef GLEE_C_DEFINED_glNormalStream3fATI +#define GLEE_C_DEFINED_glNormalStream3fATI + void __stdcall GLee_Lazy_glNormalStream3fATI(GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz) {if (GLeeInit()) glNormalStream3fATI(stream, nx, ny, nz);} + GLEEPFNGLNORMALSTREAM3FATIPROC GLeeFuncPtr_glNormalStream3fATI=GLee_Lazy_glNormalStream3fATI; +#endif +#ifndef GLEE_C_DEFINED_glNormalStream3fvATI +#define GLEE_C_DEFINED_glNormalStream3fvATI + void __stdcall GLee_Lazy_glNormalStream3fvATI(GLenum stream, const GLfloat * coords) {if (GLeeInit()) glNormalStream3fvATI(stream, coords);} + GLEEPFNGLNORMALSTREAM3FVATIPROC GLeeFuncPtr_glNormalStream3fvATI=GLee_Lazy_glNormalStream3fvATI; +#endif +#ifndef GLEE_C_DEFINED_glNormalStream3dATI +#define GLEE_C_DEFINED_glNormalStream3dATI + void __stdcall GLee_Lazy_glNormalStream3dATI(GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz) {if (GLeeInit()) glNormalStream3dATI(stream, nx, ny, nz);} + GLEEPFNGLNORMALSTREAM3DATIPROC GLeeFuncPtr_glNormalStream3dATI=GLee_Lazy_glNormalStream3dATI; +#endif +#ifndef GLEE_C_DEFINED_glNormalStream3dvATI +#define GLEE_C_DEFINED_glNormalStream3dvATI + void __stdcall GLee_Lazy_glNormalStream3dvATI(GLenum stream, const GLdouble * coords) {if (GLeeInit()) glNormalStream3dvATI(stream, coords);} + GLEEPFNGLNORMALSTREAM3DVATIPROC GLeeFuncPtr_glNormalStream3dvATI=GLee_Lazy_glNormalStream3dvATI; +#endif +#ifndef GLEE_C_DEFINED_glClientActiveVertexStreamATI +#define GLEE_C_DEFINED_glClientActiveVertexStreamATI + void __stdcall GLee_Lazy_glClientActiveVertexStreamATI(GLenum stream) {if (GLeeInit()) glClientActiveVertexStreamATI(stream);} + GLEEPFNGLCLIENTACTIVEVERTEXSTREAMATIPROC GLeeFuncPtr_glClientActiveVertexStreamATI=GLee_Lazy_glClientActiveVertexStreamATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexBlendEnviATI +#define GLEE_C_DEFINED_glVertexBlendEnviATI + void __stdcall GLee_Lazy_glVertexBlendEnviATI(GLenum pname, GLint param) {if (GLeeInit()) glVertexBlendEnviATI(pname, param);} + GLEEPFNGLVERTEXBLENDENVIATIPROC GLeeFuncPtr_glVertexBlendEnviATI=GLee_Lazy_glVertexBlendEnviATI; +#endif +#ifndef GLEE_C_DEFINED_glVertexBlendEnvfATI +#define GLEE_C_DEFINED_glVertexBlendEnvfATI + void __stdcall GLee_Lazy_glVertexBlendEnvfATI(GLenum pname, GLfloat param) {if (GLeeInit()) glVertexBlendEnvfATI(pname, param);} + GLEEPFNGLVERTEXBLENDENVFATIPROC GLeeFuncPtr_glVertexBlendEnvfATI=GLee_Lazy_glVertexBlendEnvfATI; +#endif +#endif + +/* GL_ATI_element_array */ + +#ifdef __GLEE_GL_ATI_element_array +#ifndef GLEE_C_DEFINED_glElementPointerATI +#define GLEE_C_DEFINED_glElementPointerATI + void __stdcall GLee_Lazy_glElementPointerATI(GLenum type, const GLvoid * pointer) {if (GLeeInit()) glElementPointerATI(type, pointer);} + GLEEPFNGLELEMENTPOINTERATIPROC GLeeFuncPtr_glElementPointerATI=GLee_Lazy_glElementPointerATI; +#endif +#ifndef GLEE_C_DEFINED_glDrawElementArrayATI +#define GLEE_C_DEFINED_glDrawElementArrayATI + void __stdcall GLee_Lazy_glDrawElementArrayATI(GLenum mode, GLsizei count) {if (GLeeInit()) glDrawElementArrayATI(mode, count);} + GLEEPFNGLDRAWELEMENTARRAYATIPROC GLeeFuncPtr_glDrawElementArrayATI=GLee_Lazy_glDrawElementArrayATI; +#endif +#ifndef GLEE_C_DEFINED_glDrawRangeElementArrayATI +#define GLEE_C_DEFINED_glDrawRangeElementArrayATI + void __stdcall GLee_Lazy_glDrawRangeElementArrayATI(GLenum mode, GLuint start, GLuint end, GLsizei count) {if (GLeeInit()) glDrawRangeElementArrayATI(mode, start, end, count);} + GLEEPFNGLDRAWRANGEELEMENTARRAYATIPROC GLeeFuncPtr_glDrawRangeElementArrayATI=GLee_Lazy_glDrawRangeElementArrayATI; +#endif +#endif + +/* GL_SUN_mesh_array */ + +#ifdef __GLEE_GL_SUN_mesh_array +#ifndef GLEE_C_DEFINED_glDrawMeshArraysSUN +#define GLEE_C_DEFINED_glDrawMeshArraysSUN + void __stdcall GLee_Lazy_glDrawMeshArraysSUN(GLenum mode, GLint first, GLsizei count, GLsizei width) {if (GLeeInit()) glDrawMeshArraysSUN(mode, first, count, width);} + GLEEPFNGLDRAWMESHARRAYSSUNPROC GLeeFuncPtr_glDrawMeshArraysSUN=GLee_Lazy_glDrawMeshArraysSUN; +#endif +#endif + +/* GL_SUN_slice_accum */ + +#ifdef __GLEE_GL_SUN_slice_accum +#endif + +/* GL_NV_multisample_filter_hint */ + +#ifdef __GLEE_GL_NV_multisample_filter_hint +#endif + +/* GL_NV_depth_clamp */ + +#ifdef __GLEE_GL_NV_depth_clamp +#endif + +/* GL_NV_occlusion_query */ + +#ifdef __GLEE_GL_NV_occlusion_query +#ifndef GLEE_C_DEFINED_glGenOcclusionQueriesNV +#define GLEE_C_DEFINED_glGenOcclusionQueriesNV + void __stdcall GLee_Lazy_glGenOcclusionQueriesNV(GLsizei n, GLuint * ids) {if (GLeeInit()) glGenOcclusionQueriesNV(n, ids);} + GLEEPFNGLGENOCCLUSIONQUERIESNVPROC GLeeFuncPtr_glGenOcclusionQueriesNV=GLee_Lazy_glGenOcclusionQueriesNV; +#endif +#ifndef GLEE_C_DEFINED_glDeleteOcclusionQueriesNV +#define GLEE_C_DEFINED_glDeleteOcclusionQueriesNV + void __stdcall GLee_Lazy_glDeleteOcclusionQueriesNV(GLsizei n, const GLuint * ids) {if (GLeeInit()) glDeleteOcclusionQueriesNV(n, ids);} + GLEEPFNGLDELETEOCCLUSIONQUERIESNVPROC GLeeFuncPtr_glDeleteOcclusionQueriesNV=GLee_Lazy_glDeleteOcclusionQueriesNV; +#endif +#ifndef GLEE_C_DEFINED_glIsOcclusionQueryNV +#define GLEE_C_DEFINED_glIsOcclusionQueryNV + GLboolean __stdcall GLee_Lazy_glIsOcclusionQueryNV(GLuint id) {if (GLeeInit()) return glIsOcclusionQueryNV(id); return (GLboolean)0;} + GLEEPFNGLISOCCLUSIONQUERYNVPROC GLeeFuncPtr_glIsOcclusionQueryNV=GLee_Lazy_glIsOcclusionQueryNV; +#endif +#ifndef GLEE_C_DEFINED_glBeginOcclusionQueryNV +#define GLEE_C_DEFINED_glBeginOcclusionQueryNV + void __stdcall GLee_Lazy_glBeginOcclusionQueryNV(GLuint id) {if (GLeeInit()) glBeginOcclusionQueryNV(id);} + GLEEPFNGLBEGINOCCLUSIONQUERYNVPROC GLeeFuncPtr_glBeginOcclusionQueryNV=GLee_Lazy_glBeginOcclusionQueryNV; +#endif +#ifndef GLEE_C_DEFINED_glEndOcclusionQueryNV +#define GLEE_C_DEFINED_glEndOcclusionQueryNV + void __stdcall GLee_Lazy_glEndOcclusionQueryNV(void) {if (GLeeInit()) glEndOcclusionQueryNV();} + GLEEPFNGLENDOCCLUSIONQUERYNVPROC GLeeFuncPtr_glEndOcclusionQueryNV=GLee_Lazy_glEndOcclusionQueryNV; +#endif +#ifndef GLEE_C_DEFINED_glGetOcclusionQueryivNV +#define GLEE_C_DEFINED_glGetOcclusionQueryivNV + void __stdcall GLee_Lazy_glGetOcclusionQueryivNV(GLuint id, GLenum pname, GLint * params) {if (GLeeInit()) glGetOcclusionQueryivNV(id, pname, params);} + GLEEPFNGLGETOCCLUSIONQUERYIVNVPROC GLeeFuncPtr_glGetOcclusionQueryivNV=GLee_Lazy_glGetOcclusionQueryivNV; +#endif +#ifndef GLEE_C_DEFINED_glGetOcclusionQueryuivNV +#define GLEE_C_DEFINED_glGetOcclusionQueryuivNV + void __stdcall GLee_Lazy_glGetOcclusionQueryuivNV(GLuint id, GLenum pname, GLuint * params) {if (GLeeInit()) glGetOcclusionQueryuivNV(id, pname, params);} + GLEEPFNGLGETOCCLUSIONQUERYUIVNVPROC GLeeFuncPtr_glGetOcclusionQueryuivNV=GLee_Lazy_glGetOcclusionQueryuivNV; +#endif +#endif + +/* GL_NV_point_sprite */ + +#ifdef __GLEE_GL_NV_point_sprite +#ifndef GLEE_C_DEFINED_glPointParameteriNV +#define GLEE_C_DEFINED_glPointParameteriNV + void __stdcall GLee_Lazy_glPointParameteriNV(GLenum pname, GLint param) {if (GLeeInit()) glPointParameteriNV(pname, param);} + GLEEPFNGLPOINTPARAMETERINVPROC GLeeFuncPtr_glPointParameteriNV=GLee_Lazy_glPointParameteriNV; +#endif +#ifndef GLEE_C_DEFINED_glPointParameterivNV +#define GLEE_C_DEFINED_glPointParameterivNV + void __stdcall GLee_Lazy_glPointParameterivNV(GLenum pname, const GLint * params) {if (GLeeInit()) glPointParameterivNV(pname, params);} + GLEEPFNGLPOINTPARAMETERIVNVPROC GLeeFuncPtr_glPointParameterivNV=GLee_Lazy_glPointParameterivNV; +#endif +#endif + +/* GL_NV_texture_shader3 */ + +#ifdef __GLEE_GL_NV_texture_shader3 +#endif + +/* GL_NV_vertex_program1_1 */ + +#ifdef __GLEE_GL_NV_vertex_program1_1 +#endif + +/* GL_EXT_shadow_funcs */ + +#ifdef __GLEE_GL_EXT_shadow_funcs +#endif + +/* GL_EXT_stencil_two_side */ + +#ifdef __GLEE_GL_EXT_stencil_two_side +#ifndef GLEE_C_DEFINED_glActiveStencilFaceEXT +#define GLEE_C_DEFINED_glActiveStencilFaceEXT + void __stdcall GLee_Lazy_glActiveStencilFaceEXT(GLenum face) {if (GLeeInit()) glActiveStencilFaceEXT(face);} + GLEEPFNGLACTIVESTENCILFACEEXTPROC GLeeFuncPtr_glActiveStencilFaceEXT=GLee_Lazy_glActiveStencilFaceEXT; +#endif +#endif + +/* GL_ATI_text_fragment_shader */ + +#ifdef __GLEE_GL_ATI_text_fragment_shader +#endif + +/* GL_APPLE_client_storage */ + +#ifdef __GLEE_GL_APPLE_client_storage +#endif + +/* GL_APPLE_element_array */ + +#ifdef __GLEE_GL_APPLE_element_array +#ifndef GLEE_C_DEFINED_glElementPointerAPPLE +#define GLEE_C_DEFINED_glElementPointerAPPLE + void __stdcall GLee_Lazy_glElementPointerAPPLE(GLenum type, const GLvoid * pointer) {if (GLeeInit()) glElementPointerAPPLE(type, pointer);} + GLEEPFNGLELEMENTPOINTERAPPLEPROC GLeeFuncPtr_glElementPointerAPPLE=GLee_Lazy_glElementPointerAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glDrawElementArrayAPPLE +#define GLEE_C_DEFINED_glDrawElementArrayAPPLE + void __stdcall GLee_Lazy_glDrawElementArrayAPPLE(GLenum mode, GLint first, GLsizei count) {if (GLeeInit()) glDrawElementArrayAPPLE(mode, first, count);} + GLEEPFNGLDRAWELEMENTARRAYAPPLEPROC GLeeFuncPtr_glDrawElementArrayAPPLE=GLee_Lazy_glDrawElementArrayAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glDrawRangeElementArrayAPPLE +#define GLEE_C_DEFINED_glDrawRangeElementArrayAPPLE + void __stdcall GLee_Lazy_glDrawRangeElementArrayAPPLE(GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count) {if (GLeeInit()) glDrawRangeElementArrayAPPLE(mode, start, end, first, count);} + GLEEPFNGLDRAWRANGEELEMENTARRAYAPPLEPROC GLeeFuncPtr_glDrawRangeElementArrayAPPLE=GLee_Lazy_glDrawRangeElementArrayAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glMultiDrawElementArrayAPPLE +#define GLEE_C_DEFINED_glMultiDrawElementArrayAPPLE + void __stdcall GLee_Lazy_glMultiDrawElementArrayAPPLE(GLenum mode, const GLint * first, const GLsizei * count, GLsizei primcount) {if (GLeeInit()) glMultiDrawElementArrayAPPLE(mode, first, count, primcount);} + GLEEPFNGLMULTIDRAWELEMENTARRAYAPPLEPROC GLeeFuncPtr_glMultiDrawElementArrayAPPLE=GLee_Lazy_glMultiDrawElementArrayAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glMultiDrawRangeElementArrayAPPLE +#define GLEE_C_DEFINED_glMultiDrawRangeElementArrayAPPLE + void __stdcall GLee_Lazy_glMultiDrawRangeElementArrayAPPLE(GLenum mode, GLuint start, GLuint end, const GLint * first, const GLsizei * count, GLsizei primcount) {if (GLeeInit()) glMultiDrawRangeElementArrayAPPLE(mode, start, end, first, count, primcount);} + GLEEPFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC GLeeFuncPtr_glMultiDrawRangeElementArrayAPPLE=GLee_Lazy_glMultiDrawRangeElementArrayAPPLE; +#endif +#endif + +/* GL_APPLE_fence */ + +#ifdef __GLEE_GL_APPLE_fence +#ifndef GLEE_C_DEFINED_glGenFencesAPPLE +#define GLEE_C_DEFINED_glGenFencesAPPLE + void __stdcall GLee_Lazy_glGenFencesAPPLE(GLsizei n, GLuint * fences) {if (GLeeInit()) glGenFencesAPPLE(n, fences);} + GLEEPFNGLGENFENCESAPPLEPROC GLeeFuncPtr_glGenFencesAPPLE=GLee_Lazy_glGenFencesAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glDeleteFencesAPPLE +#define GLEE_C_DEFINED_glDeleteFencesAPPLE + void __stdcall GLee_Lazy_glDeleteFencesAPPLE(GLsizei n, const GLuint * fences) {if (GLeeInit()) glDeleteFencesAPPLE(n, fences);} + GLEEPFNGLDELETEFENCESAPPLEPROC GLeeFuncPtr_glDeleteFencesAPPLE=GLee_Lazy_glDeleteFencesAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glSetFenceAPPLE +#define GLEE_C_DEFINED_glSetFenceAPPLE + void __stdcall GLee_Lazy_glSetFenceAPPLE(GLuint fence) {if (GLeeInit()) glSetFenceAPPLE(fence);} + GLEEPFNGLSETFENCEAPPLEPROC GLeeFuncPtr_glSetFenceAPPLE=GLee_Lazy_glSetFenceAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glIsFenceAPPLE +#define GLEE_C_DEFINED_glIsFenceAPPLE + GLboolean __stdcall GLee_Lazy_glIsFenceAPPLE(GLuint fence) {if (GLeeInit()) return glIsFenceAPPLE(fence); return (GLboolean)0;} + GLEEPFNGLISFENCEAPPLEPROC GLeeFuncPtr_glIsFenceAPPLE=GLee_Lazy_glIsFenceAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glTestFenceAPPLE +#define GLEE_C_DEFINED_glTestFenceAPPLE + GLboolean __stdcall GLee_Lazy_glTestFenceAPPLE(GLuint fence) {if (GLeeInit()) return glTestFenceAPPLE(fence); return (GLboolean)0;} + GLEEPFNGLTESTFENCEAPPLEPROC GLeeFuncPtr_glTestFenceAPPLE=GLee_Lazy_glTestFenceAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glFinishFenceAPPLE +#define GLEE_C_DEFINED_glFinishFenceAPPLE + void __stdcall GLee_Lazy_glFinishFenceAPPLE(GLuint fence) {if (GLeeInit()) glFinishFenceAPPLE(fence);} + GLEEPFNGLFINISHFENCEAPPLEPROC GLeeFuncPtr_glFinishFenceAPPLE=GLee_Lazy_glFinishFenceAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glTestObjectAPPLE +#define GLEE_C_DEFINED_glTestObjectAPPLE + GLboolean __stdcall GLee_Lazy_glTestObjectAPPLE(GLenum object, GLuint name) {if (GLeeInit()) return glTestObjectAPPLE(object, name); return (GLboolean)0;} + GLEEPFNGLTESTOBJECTAPPLEPROC GLeeFuncPtr_glTestObjectAPPLE=GLee_Lazy_glTestObjectAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glFinishObjectAPPLE +#define GLEE_C_DEFINED_glFinishObjectAPPLE + void __stdcall GLee_Lazy_glFinishObjectAPPLE(GLenum object, GLint name) {if (GLeeInit()) glFinishObjectAPPLE(object, name);} + GLEEPFNGLFINISHOBJECTAPPLEPROC GLeeFuncPtr_glFinishObjectAPPLE=GLee_Lazy_glFinishObjectAPPLE; +#endif +#endif + +/* GL_APPLE_vertex_array_object */ + +#ifdef __GLEE_GL_APPLE_vertex_array_object +#ifndef GLEE_C_DEFINED_glBindVertexArrayAPPLE +#define GLEE_C_DEFINED_glBindVertexArrayAPPLE + void __stdcall GLee_Lazy_glBindVertexArrayAPPLE(GLuint array) {if (GLeeInit()) glBindVertexArrayAPPLE(array);} + GLEEPFNGLBINDVERTEXARRAYAPPLEPROC GLeeFuncPtr_glBindVertexArrayAPPLE=GLee_Lazy_glBindVertexArrayAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glDeleteVertexArraysAPPLE +#define GLEE_C_DEFINED_glDeleteVertexArraysAPPLE + void __stdcall GLee_Lazy_glDeleteVertexArraysAPPLE(GLsizei n, const GLuint * arrays) {if (GLeeInit()) glDeleteVertexArraysAPPLE(n, arrays);} + GLEEPFNGLDELETEVERTEXARRAYSAPPLEPROC GLeeFuncPtr_glDeleteVertexArraysAPPLE=GLee_Lazy_glDeleteVertexArraysAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glGenVertexArraysAPPLE +#define GLEE_C_DEFINED_glGenVertexArraysAPPLE + void __stdcall GLee_Lazy_glGenVertexArraysAPPLE(GLsizei n, GLuint * arrays) {if (GLeeInit()) glGenVertexArraysAPPLE(n, arrays);} + GLEEPFNGLGENVERTEXARRAYSAPPLEPROC GLeeFuncPtr_glGenVertexArraysAPPLE=GLee_Lazy_glGenVertexArraysAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glIsVertexArrayAPPLE +#define GLEE_C_DEFINED_glIsVertexArrayAPPLE + GLboolean __stdcall GLee_Lazy_glIsVertexArrayAPPLE(GLuint array) {if (GLeeInit()) return glIsVertexArrayAPPLE(array); return (GLboolean)0;} + GLEEPFNGLISVERTEXARRAYAPPLEPROC GLeeFuncPtr_glIsVertexArrayAPPLE=GLee_Lazy_glIsVertexArrayAPPLE; +#endif +#endif + +/* GL_APPLE_vertex_array_range */ + +#ifdef __GLEE_GL_APPLE_vertex_array_range +#ifndef GLEE_C_DEFINED_glVertexArrayRangeAPPLE +#define GLEE_C_DEFINED_glVertexArrayRangeAPPLE + void __stdcall GLee_Lazy_glVertexArrayRangeAPPLE(GLsizei length, GLvoid * pointer) {if (GLeeInit()) glVertexArrayRangeAPPLE(length, pointer);} + GLEEPFNGLVERTEXARRAYRANGEAPPLEPROC GLeeFuncPtr_glVertexArrayRangeAPPLE=GLee_Lazy_glVertexArrayRangeAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glFlushVertexArrayRangeAPPLE +#define GLEE_C_DEFINED_glFlushVertexArrayRangeAPPLE + void __stdcall GLee_Lazy_glFlushVertexArrayRangeAPPLE(GLsizei length, GLvoid * pointer) {if (GLeeInit()) glFlushVertexArrayRangeAPPLE(length, pointer);} + GLEEPFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC GLeeFuncPtr_glFlushVertexArrayRangeAPPLE=GLee_Lazy_glFlushVertexArrayRangeAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glVertexArrayParameteriAPPLE +#define GLEE_C_DEFINED_glVertexArrayParameteriAPPLE + void __stdcall GLee_Lazy_glVertexArrayParameteriAPPLE(GLenum pname, GLint param) {if (GLeeInit()) glVertexArrayParameteriAPPLE(pname, param);} + GLEEPFNGLVERTEXARRAYPARAMETERIAPPLEPROC GLeeFuncPtr_glVertexArrayParameteriAPPLE=GLee_Lazy_glVertexArrayParameteriAPPLE; +#endif +#endif + +/* GL_APPLE_ycbcr_422 */ + +#ifdef __GLEE_GL_APPLE_ycbcr_422 +#endif + +/* GL_S3_s3tc */ + +#ifdef __GLEE_GL_S3_s3tc +#endif + +/* GL_ATI_draw_buffers */ + +#ifdef __GLEE_GL_ATI_draw_buffers +#ifndef GLEE_C_DEFINED_glDrawBuffersATI +#define GLEE_C_DEFINED_glDrawBuffersATI + void __stdcall GLee_Lazy_glDrawBuffersATI(GLsizei n, const GLenum * bufs) {if (GLeeInit()) glDrawBuffersATI(n, bufs);} + GLEEPFNGLDRAWBUFFERSATIPROC GLeeFuncPtr_glDrawBuffersATI=GLee_Lazy_glDrawBuffersATI; +#endif +#endif + +/* GL_ATI_pixel_format_float */ + +#ifdef __GLEE_GL_ATI_pixel_format_float +#endif + +/* GL_ATI_texture_env_combine3 */ + +#ifdef __GLEE_GL_ATI_texture_env_combine3 +#endif + +/* GL_ATI_texture_float */ + +#ifdef __GLEE_GL_ATI_texture_float +#endif + +/* GL_NV_float_buffer */ + +#ifdef __GLEE_GL_NV_float_buffer +#endif + +/* GL_NV_fragment_program */ + +#ifdef __GLEE_GL_NV_fragment_program +#ifndef GLEE_C_DEFINED_glProgramNamedParameter4fNV +#define GLEE_C_DEFINED_glProgramNamedParameter4fNV + void __stdcall GLee_Lazy_glProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte * name, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {if (GLeeInit()) glProgramNamedParameter4fNV(id, len, name, x, y, z, w);} + GLEEPFNGLPROGRAMNAMEDPARAMETER4FNVPROC GLeeFuncPtr_glProgramNamedParameter4fNV=GLee_Lazy_glProgramNamedParameter4fNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramNamedParameter4dNV +#define GLEE_C_DEFINED_glProgramNamedParameter4dNV + void __stdcall GLee_Lazy_glProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte * name, GLdouble x, GLdouble y, GLdouble z, GLdouble w) {if (GLeeInit()) glProgramNamedParameter4dNV(id, len, name, x, y, z, w);} + GLEEPFNGLPROGRAMNAMEDPARAMETER4DNVPROC GLeeFuncPtr_glProgramNamedParameter4dNV=GLee_Lazy_glProgramNamedParameter4dNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramNamedParameter4fvNV +#define GLEE_C_DEFINED_glProgramNamedParameter4fvNV + void __stdcall GLee_Lazy_glProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte * name, const GLfloat * v) {if (GLeeInit()) glProgramNamedParameter4fvNV(id, len, name, v);} + GLEEPFNGLPROGRAMNAMEDPARAMETER4FVNVPROC GLeeFuncPtr_glProgramNamedParameter4fvNV=GLee_Lazy_glProgramNamedParameter4fvNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramNamedParameter4dvNV +#define GLEE_C_DEFINED_glProgramNamedParameter4dvNV + void __stdcall GLee_Lazy_glProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte * name, const GLdouble * v) {if (GLeeInit()) glProgramNamedParameter4dvNV(id, len, name, v);} + GLEEPFNGLPROGRAMNAMEDPARAMETER4DVNVPROC GLeeFuncPtr_glProgramNamedParameter4dvNV=GLee_Lazy_glProgramNamedParameter4dvNV; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramNamedParameterfvNV +#define GLEE_C_DEFINED_glGetProgramNamedParameterfvNV + void __stdcall GLee_Lazy_glGetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte * name, GLfloat * params) {if (GLeeInit()) glGetProgramNamedParameterfvNV(id, len, name, params);} + GLEEPFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC GLeeFuncPtr_glGetProgramNamedParameterfvNV=GLee_Lazy_glGetProgramNamedParameterfvNV; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramNamedParameterdvNV +#define GLEE_C_DEFINED_glGetProgramNamedParameterdvNV + void __stdcall GLee_Lazy_glGetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte * name, GLdouble * params) {if (GLeeInit()) glGetProgramNamedParameterdvNV(id, len, name, params);} + GLEEPFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC GLeeFuncPtr_glGetProgramNamedParameterdvNV=GLee_Lazy_glGetProgramNamedParameterdvNV; +#endif +#endif + +/* GL_NV_half_float */ + +#ifdef __GLEE_GL_NV_half_float +#ifndef GLEE_C_DEFINED_glVertex2hNV +#define GLEE_C_DEFINED_glVertex2hNV + void __stdcall GLee_Lazy_glVertex2hNV(GLhalfNV x, GLhalfNV y) {if (GLeeInit()) glVertex2hNV(x, y);} + GLEEPFNGLVERTEX2HNVPROC GLeeFuncPtr_glVertex2hNV=GLee_Lazy_glVertex2hNV; +#endif +#ifndef GLEE_C_DEFINED_glVertex2hvNV +#define GLEE_C_DEFINED_glVertex2hvNV + void __stdcall GLee_Lazy_glVertex2hvNV(const GLhalfNV * v) {if (GLeeInit()) glVertex2hvNV(v);} + GLEEPFNGLVERTEX2HVNVPROC GLeeFuncPtr_glVertex2hvNV=GLee_Lazy_glVertex2hvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertex3hNV +#define GLEE_C_DEFINED_glVertex3hNV + void __stdcall GLee_Lazy_glVertex3hNV(GLhalfNV x, GLhalfNV y, GLhalfNV z) {if (GLeeInit()) glVertex3hNV(x, y, z);} + GLEEPFNGLVERTEX3HNVPROC GLeeFuncPtr_glVertex3hNV=GLee_Lazy_glVertex3hNV; +#endif +#ifndef GLEE_C_DEFINED_glVertex3hvNV +#define GLEE_C_DEFINED_glVertex3hvNV + void __stdcall GLee_Lazy_glVertex3hvNV(const GLhalfNV * v) {if (GLeeInit()) glVertex3hvNV(v);} + GLEEPFNGLVERTEX3HVNVPROC GLeeFuncPtr_glVertex3hvNV=GLee_Lazy_glVertex3hvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertex4hNV +#define GLEE_C_DEFINED_glVertex4hNV + void __stdcall GLee_Lazy_glVertex4hNV(GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w) {if (GLeeInit()) glVertex4hNV(x, y, z, w);} + GLEEPFNGLVERTEX4HNVPROC GLeeFuncPtr_glVertex4hNV=GLee_Lazy_glVertex4hNV; +#endif +#ifndef GLEE_C_DEFINED_glVertex4hvNV +#define GLEE_C_DEFINED_glVertex4hvNV + void __stdcall GLee_Lazy_glVertex4hvNV(const GLhalfNV * v) {if (GLeeInit()) glVertex4hvNV(v);} + GLEEPFNGLVERTEX4HVNVPROC GLeeFuncPtr_glVertex4hvNV=GLee_Lazy_glVertex4hvNV; +#endif +#ifndef GLEE_C_DEFINED_glNormal3hNV +#define GLEE_C_DEFINED_glNormal3hNV + void __stdcall GLee_Lazy_glNormal3hNV(GLhalfNV nx, GLhalfNV ny, GLhalfNV nz) {if (GLeeInit()) glNormal3hNV(nx, ny, nz);} + GLEEPFNGLNORMAL3HNVPROC GLeeFuncPtr_glNormal3hNV=GLee_Lazy_glNormal3hNV; +#endif +#ifndef GLEE_C_DEFINED_glNormal3hvNV +#define GLEE_C_DEFINED_glNormal3hvNV + void __stdcall GLee_Lazy_glNormal3hvNV(const GLhalfNV * v) {if (GLeeInit()) glNormal3hvNV(v);} + GLEEPFNGLNORMAL3HVNVPROC GLeeFuncPtr_glNormal3hvNV=GLee_Lazy_glNormal3hvNV; +#endif +#ifndef GLEE_C_DEFINED_glColor3hNV +#define GLEE_C_DEFINED_glColor3hNV + void __stdcall GLee_Lazy_glColor3hNV(GLhalfNV red, GLhalfNV green, GLhalfNV blue) {if (GLeeInit()) glColor3hNV(red, green, blue);} + GLEEPFNGLCOLOR3HNVPROC GLeeFuncPtr_glColor3hNV=GLee_Lazy_glColor3hNV; +#endif +#ifndef GLEE_C_DEFINED_glColor3hvNV +#define GLEE_C_DEFINED_glColor3hvNV + void __stdcall GLee_Lazy_glColor3hvNV(const GLhalfNV * v) {if (GLeeInit()) glColor3hvNV(v);} + GLEEPFNGLCOLOR3HVNVPROC GLeeFuncPtr_glColor3hvNV=GLee_Lazy_glColor3hvNV; +#endif +#ifndef GLEE_C_DEFINED_glColor4hNV +#define GLEE_C_DEFINED_glColor4hNV + void __stdcall GLee_Lazy_glColor4hNV(GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha) {if (GLeeInit()) glColor4hNV(red, green, blue, alpha);} + GLEEPFNGLCOLOR4HNVPROC GLeeFuncPtr_glColor4hNV=GLee_Lazy_glColor4hNV; +#endif +#ifndef GLEE_C_DEFINED_glColor4hvNV +#define GLEE_C_DEFINED_glColor4hvNV + void __stdcall GLee_Lazy_glColor4hvNV(const GLhalfNV * v) {if (GLeeInit()) glColor4hvNV(v);} + GLEEPFNGLCOLOR4HVNVPROC GLeeFuncPtr_glColor4hvNV=GLee_Lazy_glColor4hvNV; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord1hNV +#define GLEE_C_DEFINED_glTexCoord1hNV + void __stdcall GLee_Lazy_glTexCoord1hNV(GLhalfNV s) {if (GLeeInit()) glTexCoord1hNV(s);} + GLEEPFNGLTEXCOORD1HNVPROC GLeeFuncPtr_glTexCoord1hNV=GLee_Lazy_glTexCoord1hNV; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord1hvNV +#define GLEE_C_DEFINED_glTexCoord1hvNV + void __stdcall GLee_Lazy_glTexCoord1hvNV(const GLhalfNV * v) {if (GLeeInit()) glTexCoord1hvNV(v);} + GLEEPFNGLTEXCOORD1HVNVPROC GLeeFuncPtr_glTexCoord1hvNV=GLee_Lazy_glTexCoord1hvNV; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord2hNV +#define GLEE_C_DEFINED_glTexCoord2hNV + void __stdcall GLee_Lazy_glTexCoord2hNV(GLhalfNV s, GLhalfNV t) {if (GLeeInit()) glTexCoord2hNV(s, t);} + GLEEPFNGLTEXCOORD2HNVPROC GLeeFuncPtr_glTexCoord2hNV=GLee_Lazy_glTexCoord2hNV; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord2hvNV +#define GLEE_C_DEFINED_glTexCoord2hvNV + void __stdcall GLee_Lazy_glTexCoord2hvNV(const GLhalfNV * v) {if (GLeeInit()) glTexCoord2hvNV(v);} + GLEEPFNGLTEXCOORD2HVNVPROC GLeeFuncPtr_glTexCoord2hvNV=GLee_Lazy_glTexCoord2hvNV; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord3hNV +#define GLEE_C_DEFINED_glTexCoord3hNV + void __stdcall GLee_Lazy_glTexCoord3hNV(GLhalfNV s, GLhalfNV t, GLhalfNV r) {if (GLeeInit()) glTexCoord3hNV(s, t, r);} + GLEEPFNGLTEXCOORD3HNVPROC GLeeFuncPtr_glTexCoord3hNV=GLee_Lazy_glTexCoord3hNV; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord3hvNV +#define GLEE_C_DEFINED_glTexCoord3hvNV + void __stdcall GLee_Lazy_glTexCoord3hvNV(const GLhalfNV * v) {if (GLeeInit()) glTexCoord3hvNV(v);} + GLEEPFNGLTEXCOORD3HVNVPROC GLeeFuncPtr_glTexCoord3hvNV=GLee_Lazy_glTexCoord3hvNV; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord4hNV +#define GLEE_C_DEFINED_glTexCoord4hNV + void __stdcall GLee_Lazy_glTexCoord4hNV(GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q) {if (GLeeInit()) glTexCoord4hNV(s, t, r, q);} + GLEEPFNGLTEXCOORD4HNVPROC GLeeFuncPtr_glTexCoord4hNV=GLee_Lazy_glTexCoord4hNV; +#endif +#ifndef GLEE_C_DEFINED_glTexCoord4hvNV +#define GLEE_C_DEFINED_glTexCoord4hvNV + void __stdcall GLee_Lazy_glTexCoord4hvNV(const GLhalfNV * v) {if (GLeeInit()) glTexCoord4hvNV(v);} + GLEEPFNGLTEXCOORD4HVNVPROC GLeeFuncPtr_glTexCoord4hvNV=GLee_Lazy_glTexCoord4hvNV; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1hNV +#define GLEE_C_DEFINED_glMultiTexCoord1hNV + void __stdcall GLee_Lazy_glMultiTexCoord1hNV(GLenum target, GLhalfNV s) {if (GLeeInit()) glMultiTexCoord1hNV(target, s);} + GLEEPFNGLMULTITEXCOORD1HNVPROC GLeeFuncPtr_glMultiTexCoord1hNV=GLee_Lazy_glMultiTexCoord1hNV; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord1hvNV +#define GLEE_C_DEFINED_glMultiTexCoord1hvNV + void __stdcall GLee_Lazy_glMultiTexCoord1hvNV(GLenum target, const GLhalfNV * v) {if (GLeeInit()) glMultiTexCoord1hvNV(target, v);} + GLEEPFNGLMULTITEXCOORD1HVNVPROC GLeeFuncPtr_glMultiTexCoord1hvNV=GLee_Lazy_glMultiTexCoord1hvNV; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2hNV +#define GLEE_C_DEFINED_glMultiTexCoord2hNV + void __stdcall GLee_Lazy_glMultiTexCoord2hNV(GLenum target, GLhalfNV s, GLhalfNV t) {if (GLeeInit()) glMultiTexCoord2hNV(target, s, t);} + GLEEPFNGLMULTITEXCOORD2HNVPROC GLeeFuncPtr_glMultiTexCoord2hNV=GLee_Lazy_glMultiTexCoord2hNV; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord2hvNV +#define GLEE_C_DEFINED_glMultiTexCoord2hvNV + void __stdcall GLee_Lazy_glMultiTexCoord2hvNV(GLenum target, const GLhalfNV * v) {if (GLeeInit()) glMultiTexCoord2hvNV(target, v);} + GLEEPFNGLMULTITEXCOORD2HVNVPROC GLeeFuncPtr_glMultiTexCoord2hvNV=GLee_Lazy_glMultiTexCoord2hvNV; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3hNV +#define GLEE_C_DEFINED_glMultiTexCoord3hNV + void __stdcall GLee_Lazy_glMultiTexCoord3hNV(GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r) {if (GLeeInit()) glMultiTexCoord3hNV(target, s, t, r);} + GLEEPFNGLMULTITEXCOORD3HNVPROC GLeeFuncPtr_glMultiTexCoord3hNV=GLee_Lazy_glMultiTexCoord3hNV; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord3hvNV +#define GLEE_C_DEFINED_glMultiTexCoord3hvNV + void __stdcall GLee_Lazy_glMultiTexCoord3hvNV(GLenum target, const GLhalfNV * v) {if (GLeeInit()) glMultiTexCoord3hvNV(target, v);} + GLEEPFNGLMULTITEXCOORD3HVNVPROC GLeeFuncPtr_glMultiTexCoord3hvNV=GLee_Lazy_glMultiTexCoord3hvNV; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4hNV +#define GLEE_C_DEFINED_glMultiTexCoord4hNV + void __stdcall GLee_Lazy_glMultiTexCoord4hNV(GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q) {if (GLeeInit()) glMultiTexCoord4hNV(target, s, t, r, q);} + GLEEPFNGLMULTITEXCOORD4HNVPROC GLeeFuncPtr_glMultiTexCoord4hNV=GLee_Lazy_glMultiTexCoord4hNV; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoord4hvNV +#define GLEE_C_DEFINED_glMultiTexCoord4hvNV + void __stdcall GLee_Lazy_glMultiTexCoord4hvNV(GLenum target, const GLhalfNV * v) {if (GLeeInit()) glMultiTexCoord4hvNV(target, v);} + GLEEPFNGLMULTITEXCOORD4HVNVPROC GLeeFuncPtr_glMultiTexCoord4hvNV=GLee_Lazy_glMultiTexCoord4hvNV; +#endif +#ifndef GLEE_C_DEFINED_glFogCoordhNV +#define GLEE_C_DEFINED_glFogCoordhNV + void __stdcall GLee_Lazy_glFogCoordhNV(GLhalfNV fog) {if (GLeeInit()) glFogCoordhNV(fog);} + GLEEPFNGLFOGCOORDHNVPROC GLeeFuncPtr_glFogCoordhNV=GLee_Lazy_glFogCoordhNV; +#endif +#ifndef GLEE_C_DEFINED_glFogCoordhvNV +#define GLEE_C_DEFINED_glFogCoordhvNV + void __stdcall GLee_Lazy_glFogCoordhvNV(const GLhalfNV * fog) {if (GLeeInit()) glFogCoordhvNV(fog);} + GLEEPFNGLFOGCOORDHVNVPROC GLeeFuncPtr_glFogCoordhvNV=GLee_Lazy_glFogCoordhvNV; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3hNV +#define GLEE_C_DEFINED_glSecondaryColor3hNV + void __stdcall GLee_Lazy_glSecondaryColor3hNV(GLhalfNV red, GLhalfNV green, GLhalfNV blue) {if (GLeeInit()) glSecondaryColor3hNV(red, green, blue);} + GLEEPFNGLSECONDARYCOLOR3HNVPROC GLeeFuncPtr_glSecondaryColor3hNV=GLee_Lazy_glSecondaryColor3hNV; +#endif +#ifndef GLEE_C_DEFINED_glSecondaryColor3hvNV +#define GLEE_C_DEFINED_glSecondaryColor3hvNV + void __stdcall GLee_Lazy_glSecondaryColor3hvNV(const GLhalfNV * v) {if (GLeeInit()) glSecondaryColor3hvNV(v);} + GLEEPFNGLSECONDARYCOLOR3HVNVPROC GLeeFuncPtr_glSecondaryColor3hvNV=GLee_Lazy_glSecondaryColor3hvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexWeighthNV +#define GLEE_C_DEFINED_glVertexWeighthNV + void __stdcall GLee_Lazy_glVertexWeighthNV(GLhalfNV weight) {if (GLeeInit()) glVertexWeighthNV(weight);} + GLEEPFNGLVERTEXWEIGHTHNVPROC GLeeFuncPtr_glVertexWeighthNV=GLee_Lazy_glVertexWeighthNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexWeighthvNV +#define GLEE_C_DEFINED_glVertexWeighthvNV + void __stdcall GLee_Lazy_glVertexWeighthvNV(const GLhalfNV * weight) {if (GLeeInit()) glVertexWeighthvNV(weight);} + GLEEPFNGLVERTEXWEIGHTHVNVPROC GLeeFuncPtr_glVertexWeighthvNV=GLee_Lazy_glVertexWeighthvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1hNV +#define GLEE_C_DEFINED_glVertexAttrib1hNV + void __stdcall GLee_Lazy_glVertexAttrib1hNV(GLuint index, GLhalfNV x) {if (GLeeInit()) glVertexAttrib1hNV(index, x);} + GLEEPFNGLVERTEXATTRIB1HNVPROC GLeeFuncPtr_glVertexAttrib1hNV=GLee_Lazy_glVertexAttrib1hNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib1hvNV +#define GLEE_C_DEFINED_glVertexAttrib1hvNV + void __stdcall GLee_Lazy_glVertexAttrib1hvNV(GLuint index, const GLhalfNV * v) {if (GLeeInit()) glVertexAttrib1hvNV(index, v);} + GLEEPFNGLVERTEXATTRIB1HVNVPROC GLeeFuncPtr_glVertexAttrib1hvNV=GLee_Lazy_glVertexAttrib1hvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2hNV +#define GLEE_C_DEFINED_glVertexAttrib2hNV + void __stdcall GLee_Lazy_glVertexAttrib2hNV(GLuint index, GLhalfNV x, GLhalfNV y) {if (GLeeInit()) glVertexAttrib2hNV(index, x, y);} + GLEEPFNGLVERTEXATTRIB2HNVPROC GLeeFuncPtr_glVertexAttrib2hNV=GLee_Lazy_glVertexAttrib2hNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib2hvNV +#define GLEE_C_DEFINED_glVertexAttrib2hvNV + void __stdcall GLee_Lazy_glVertexAttrib2hvNV(GLuint index, const GLhalfNV * v) {if (GLeeInit()) glVertexAttrib2hvNV(index, v);} + GLEEPFNGLVERTEXATTRIB2HVNVPROC GLeeFuncPtr_glVertexAttrib2hvNV=GLee_Lazy_glVertexAttrib2hvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3hNV +#define GLEE_C_DEFINED_glVertexAttrib3hNV + void __stdcall GLee_Lazy_glVertexAttrib3hNV(GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z) {if (GLeeInit()) glVertexAttrib3hNV(index, x, y, z);} + GLEEPFNGLVERTEXATTRIB3HNVPROC GLeeFuncPtr_glVertexAttrib3hNV=GLee_Lazy_glVertexAttrib3hNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib3hvNV +#define GLEE_C_DEFINED_glVertexAttrib3hvNV + void __stdcall GLee_Lazy_glVertexAttrib3hvNV(GLuint index, const GLhalfNV * v) {if (GLeeInit()) glVertexAttrib3hvNV(index, v);} + GLEEPFNGLVERTEXATTRIB3HVNVPROC GLeeFuncPtr_glVertexAttrib3hvNV=GLee_Lazy_glVertexAttrib3hvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4hNV +#define GLEE_C_DEFINED_glVertexAttrib4hNV + void __stdcall GLee_Lazy_glVertexAttrib4hNV(GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w) {if (GLeeInit()) glVertexAttrib4hNV(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIB4HNVPROC GLeeFuncPtr_glVertexAttrib4hNV=GLee_Lazy_glVertexAttrib4hNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttrib4hvNV +#define GLEE_C_DEFINED_glVertexAttrib4hvNV + void __stdcall GLee_Lazy_glVertexAttrib4hvNV(GLuint index, const GLhalfNV * v) {if (GLeeInit()) glVertexAttrib4hvNV(index, v);} + GLEEPFNGLVERTEXATTRIB4HVNVPROC GLeeFuncPtr_glVertexAttrib4hvNV=GLee_Lazy_glVertexAttrib4hvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs1hvNV +#define GLEE_C_DEFINED_glVertexAttribs1hvNV + void __stdcall GLee_Lazy_glVertexAttribs1hvNV(GLuint index, GLsizei n, const GLhalfNV * v) {if (GLeeInit()) glVertexAttribs1hvNV(index, n, v);} + GLEEPFNGLVERTEXATTRIBS1HVNVPROC GLeeFuncPtr_glVertexAttribs1hvNV=GLee_Lazy_glVertexAttribs1hvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs2hvNV +#define GLEE_C_DEFINED_glVertexAttribs2hvNV + void __stdcall GLee_Lazy_glVertexAttribs2hvNV(GLuint index, GLsizei n, const GLhalfNV * v) {if (GLeeInit()) glVertexAttribs2hvNV(index, n, v);} + GLEEPFNGLVERTEXATTRIBS2HVNVPROC GLeeFuncPtr_glVertexAttribs2hvNV=GLee_Lazy_glVertexAttribs2hvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs3hvNV +#define GLEE_C_DEFINED_glVertexAttribs3hvNV + void __stdcall GLee_Lazy_glVertexAttribs3hvNV(GLuint index, GLsizei n, const GLhalfNV * v) {if (GLeeInit()) glVertexAttribs3hvNV(index, n, v);} + GLEEPFNGLVERTEXATTRIBS3HVNVPROC GLeeFuncPtr_glVertexAttribs3hvNV=GLee_Lazy_glVertexAttribs3hvNV; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribs4hvNV +#define GLEE_C_DEFINED_glVertexAttribs4hvNV + void __stdcall GLee_Lazy_glVertexAttribs4hvNV(GLuint index, GLsizei n, const GLhalfNV * v) {if (GLeeInit()) glVertexAttribs4hvNV(index, n, v);} + GLEEPFNGLVERTEXATTRIBS4HVNVPROC GLeeFuncPtr_glVertexAttribs4hvNV=GLee_Lazy_glVertexAttribs4hvNV; +#endif +#endif + +/* GL_NV_pixel_data_range */ + +#ifdef __GLEE_GL_NV_pixel_data_range +#ifndef GLEE_C_DEFINED_glPixelDataRangeNV +#define GLEE_C_DEFINED_glPixelDataRangeNV + void __stdcall GLee_Lazy_glPixelDataRangeNV(GLenum target, GLsizei length, GLvoid * pointer) {if (GLeeInit()) glPixelDataRangeNV(target, length, pointer);} + GLEEPFNGLPIXELDATARANGENVPROC GLeeFuncPtr_glPixelDataRangeNV=GLee_Lazy_glPixelDataRangeNV; +#endif +#ifndef GLEE_C_DEFINED_glFlushPixelDataRangeNV +#define GLEE_C_DEFINED_glFlushPixelDataRangeNV + void __stdcall GLee_Lazy_glFlushPixelDataRangeNV(GLenum target) {if (GLeeInit()) glFlushPixelDataRangeNV(target);} + GLEEPFNGLFLUSHPIXELDATARANGENVPROC GLeeFuncPtr_glFlushPixelDataRangeNV=GLee_Lazy_glFlushPixelDataRangeNV; +#endif +#endif + +/* GL_NV_primitive_restart */ + +#ifdef __GLEE_GL_NV_primitive_restart +#ifndef GLEE_C_DEFINED_glPrimitiveRestartNV +#define GLEE_C_DEFINED_glPrimitiveRestartNV + void __stdcall GLee_Lazy_glPrimitiveRestartNV(void) {if (GLeeInit()) glPrimitiveRestartNV();} + GLEEPFNGLPRIMITIVERESTARTNVPROC GLeeFuncPtr_glPrimitiveRestartNV=GLee_Lazy_glPrimitiveRestartNV; +#endif +#ifndef GLEE_C_DEFINED_glPrimitiveRestartIndexNV +#define GLEE_C_DEFINED_glPrimitiveRestartIndexNV + void __stdcall GLee_Lazy_glPrimitiveRestartIndexNV(GLuint index) {if (GLeeInit()) glPrimitiveRestartIndexNV(index);} + GLEEPFNGLPRIMITIVERESTARTINDEXNVPROC GLeeFuncPtr_glPrimitiveRestartIndexNV=GLee_Lazy_glPrimitiveRestartIndexNV; +#endif +#endif + +/* GL_NV_texture_expand_normal */ + +#ifdef __GLEE_GL_NV_texture_expand_normal +#endif + +/* GL_NV_vertex_program2 */ + +#ifdef __GLEE_GL_NV_vertex_program2 +#endif + +/* GL_ATI_map_object_buffer */ + +#ifdef __GLEE_GL_ATI_map_object_buffer +#ifndef GLEE_C_DEFINED_glMapObjectBufferATI +#define GLEE_C_DEFINED_glMapObjectBufferATI + GLvoid* __stdcall GLee_Lazy_glMapObjectBufferATI(GLuint buffer) {if (GLeeInit()) return glMapObjectBufferATI(buffer); return (GLvoid*)0;} + GLEEPFNGLMAPOBJECTBUFFERATIPROC GLeeFuncPtr_glMapObjectBufferATI=GLee_Lazy_glMapObjectBufferATI; +#endif +#ifndef GLEE_C_DEFINED_glUnmapObjectBufferATI +#define GLEE_C_DEFINED_glUnmapObjectBufferATI + void __stdcall GLee_Lazy_glUnmapObjectBufferATI(GLuint buffer) {if (GLeeInit()) glUnmapObjectBufferATI(buffer);} + GLEEPFNGLUNMAPOBJECTBUFFERATIPROC GLeeFuncPtr_glUnmapObjectBufferATI=GLee_Lazy_glUnmapObjectBufferATI; +#endif +#endif + +/* GL_ATI_separate_stencil */ + +#ifdef __GLEE_GL_ATI_separate_stencil +#ifndef GLEE_C_DEFINED_glStencilOpSeparateATI +#define GLEE_C_DEFINED_glStencilOpSeparateATI + void __stdcall GLee_Lazy_glStencilOpSeparateATI(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) {if (GLeeInit()) glStencilOpSeparateATI(face, sfail, dpfail, dppass);} + GLEEPFNGLSTENCILOPSEPARATEATIPROC GLeeFuncPtr_glStencilOpSeparateATI=GLee_Lazy_glStencilOpSeparateATI; +#endif +#ifndef GLEE_C_DEFINED_glStencilFuncSeparateATI +#define GLEE_C_DEFINED_glStencilFuncSeparateATI + void __stdcall GLee_Lazy_glStencilFuncSeparateATI(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask) {if (GLeeInit()) glStencilFuncSeparateATI(frontfunc, backfunc, ref, mask);} + GLEEPFNGLSTENCILFUNCSEPARATEATIPROC GLeeFuncPtr_glStencilFuncSeparateATI=GLee_Lazy_glStencilFuncSeparateATI; +#endif +#endif + +/* GL_ATI_vertex_attrib_array_object */ + +#ifdef __GLEE_GL_ATI_vertex_attrib_array_object +#ifndef GLEE_C_DEFINED_glVertexAttribArrayObjectATI +#define GLEE_C_DEFINED_glVertexAttribArrayObjectATI + void __stdcall GLee_Lazy_glVertexAttribArrayObjectATI(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset) {if (GLeeInit()) glVertexAttribArrayObjectATI(index, size, type, normalized, stride, buffer, offset);} + GLEEPFNGLVERTEXATTRIBARRAYOBJECTATIPROC GLeeFuncPtr_glVertexAttribArrayObjectATI=GLee_Lazy_glVertexAttribArrayObjectATI; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribArrayObjectfvATI +#define GLEE_C_DEFINED_glGetVertexAttribArrayObjectfvATI + void __stdcall GLee_Lazy_glGetVertexAttribArrayObjectfvATI(GLuint index, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetVertexAttribArrayObjectfvATI(index, pname, params);} + GLEEPFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC GLeeFuncPtr_glGetVertexAttribArrayObjectfvATI=GLee_Lazy_glGetVertexAttribArrayObjectfvATI; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribArrayObjectivATI +#define GLEE_C_DEFINED_glGetVertexAttribArrayObjectivATI + void __stdcall GLee_Lazy_glGetVertexAttribArrayObjectivATI(GLuint index, GLenum pname, GLint * params) {if (GLeeInit()) glGetVertexAttribArrayObjectivATI(index, pname, params);} + GLEEPFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC GLeeFuncPtr_glGetVertexAttribArrayObjectivATI=GLee_Lazy_glGetVertexAttribArrayObjectivATI; +#endif +#endif + +/* GL_OES_read_format */ + +#ifdef __GLEE_GL_OES_read_format +#endif + +/* GL_EXT_depth_bounds_test */ + +#ifdef __GLEE_GL_EXT_depth_bounds_test +#ifndef GLEE_C_DEFINED_glDepthBoundsEXT +#define GLEE_C_DEFINED_glDepthBoundsEXT + void __stdcall GLee_Lazy_glDepthBoundsEXT(GLclampd zmin, GLclampd zmax) {if (GLeeInit()) glDepthBoundsEXT(zmin, zmax);} + GLEEPFNGLDEPTHBOUNDSEXTPROC GLeeFuncPtr_glDepthBoundsEXT=GLee_Lazy_glDepthBoundsEXT; +#endif +#endif + +/* GL_EXT_texture_mirror_clamp */ + +#ifdef __GLEE_GL_EXT_texture_mirror_clamp +#endif + +/* GL_EXT_blend_equation_separate */ + +#ifdef __GLEE_GL_EXT_blend_equation_separate +#ifndef GLEE_C_DEFINED_glBlendEquationSeparateEXT +#define GLEE_C_DEFINED_glBlendEquationSeparateEXT + void __stdcall GLee_Lazy_glBlendEquationSeparateEXT(GLenum modeRGB, GLenum modeAlpha) {if (GLeeInit()) glBlendEquationSeparateEXT(modeRGB, modeAlpha);} + GLEEPFNGLBLENDEQUATIONSEPARATEEXTPROC GLeeFuncPtr_glBlendEquationSeparateEXT=GLee_Lazy_glBlendEquationSeparateEXT; +#endif +#endif + +/* GL_MESA_pack_invert */ + +#ifdef __GLEE_GL_MESA_pack_invert +#endif + +/* GL_MESA_ycbcr_texture */ + +#ifdef __GLEE_GL_MESA_ycbcr_texture +#endif + +/* GL_EXT_pixel_buffer_object */ + +#ifdef __GLEE_GL_EXT_pixel_buffer_object +#endif + +/* GL_NV_fragment_program_option */ + +#ifdef __GLEE_GL_NV_fragment_program_option +#endif + +/* GL_NV_fragment_program2 */ + +#ifdef __GLEE_GL_NV_fragment_program2 +#endif + +/* GL_NV_vertex_program2_option */ + +#ifdef __GLEE_GL_NV_vertex_program2_option +#endif + +/* GL_NV_vertex_program3 */ + +#ifdef __GLEE_GL_NV_vertex_program3 +#endif + +/* GL_EXT_framebuffer_object */ + +#ifdef __GLEE_GL_EXT_framebuffer_object +#ifndef GLEE_C_DEFINED_glIsRenderbufferEXT +#define GLEE_C_DEFINED_glIsRenderbufferEXT + GLboolean __stdcall GLee_Lazy_glIsRenderbufferEXT(GLuint renderbuffer) {if (GLeeInit()) return glIsRenderbufferEXT(renderbuffer); return (GLboolean)0;} + GLEEPFNGLISRENDERBUFFEREXTPROC GLeeFuncPtr_glIsRenderbufferEXT=GLee_Lazy_glIsRenderbufferEXT; +#endif +#ifndef GLEE_C_DEFINED_glBindRenderbufferEXT +#define GLEE_C_DEFINED_glBindRenderbufferEXT + void __stdcall GLee_Lazy_glBindRenderbufferEXT(GLenum target, GLuint renderbuffer) {if (GLeeInit()) glBindRenderbufferEXT(target, renderbuffer);} + GLEEPFNGLBINDRENDERBUFFEREXTPROC GLeeFuncPtr_glBindRenderbufferEXT=GLee_Lazy_glBindRenderbufferEXT; +#endif +#ifndef GLEE_C_DEFINED_glDeleteRenderbuffersEXT +#define GLEE_C_DEFINED_glDeleteRenderbuffersEXT + void __stdcall GLee_Lazy_glDeleteRenderbuffersEXT(GLsizei n, const GLuint * renderbuffers) {if (GLeeInit()) glDeleteRenderbuffersEXT(n, renderbuffers);} + GLEEPFNGLDELETERENDERBUFFERSEXTPROC GLeeFuncPtr_glDeleteRenderbuffersEXT=GLee_Lazy_glDeleteRenderbuffersEXT; +#endif +#ifndef GLEE_C_DEFINED_glGenRenderbuffersEXT +#define GLEE_C_DEFINED_glGenRenderbuffersEXT + void __stdcall GLee_Lazy_glGenRenderbuffersEXT(GLsizei n, GLuint * renderbuffers) {if (GLeeInit()) glGenRenderbuffersEXT(n, renderbuffers);} + GLEEPFNGLGENRENDERBUFFERSEXTPROC GLeeFuncPtr_glGenRenderbuffersEXT=GLee_Lazy_glGenRenderbuffersEXT; +#endif +#ifndef GLEE_C_DEFINED_glRenderbufferStorageEXT +#define GLEE_C_DEFINED_glRenderbufferStorageEXT + void __stdcall GLee_Lazy_glRenderbufferStorageEXT(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {if (GLeeInit()) glRenderbufferStorageEXT(target, internalformat, width, height);} + GLEEPFNGLRENDERBUFFERSTORAGEEXTPROC GLeeFuncPtr_glRenderbufferStorageEXT=GLee_Lazy_glRenderbufferStorageEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetRenderbufferParameterivEXT +#define GLEE_C_DEFINED_glGetRenderbufferParameterivEXT + void __stdcall GLee_Lazy_glGetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetRenderbufferParameterivEXT(target, pname, params);} + GLEEPFNGLGETRENDERBUFFERPARAMETERIVEXTPROC GLeeFuncPtr_glGetRenderbufferParameterivEXT=GLee_Lazy_glGetRenderbufferParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glIsFramebufferEXT +#define GLEE_C_DEFINED_glIsFramebufferEXT + GLboolean __stdcall GLee_Lazy_glIsFramebufferEXT(GLuint framebuffer) {if (GLeeInit()) return glIsFramebufferEXT(framebuffer); return (GLboolean)0;} + GLEEPFNGLISFRAMEBUFFEREXTPROC GLeeFuncPtr_glIsFramebufferEXT=GLee_Lazy_glIsFramebufferEXT; +#endif +#ifndef GLEE_C_DEFINED_glBindFramebufferEXT +#define GLEE_C_DEFINED_glBindFramebufferEXT + void __stdcall GLee_Lazy_glBindFramebufferEXT(GLenum target, GLuint framebuffer) {if (GLeeInit()) glBindFramebufferEXT(target, framebuffer);} + GLEEPFNGLBINDFRAMEBUFFEREXTPROC GLeeFuncPtr_glBindFramebufferEXT=GLee_Lazy_glBindFramebufferEXT; +#endif +#ifndef GLEE_C_DEFINED_glDeleteFramebuffersEXT +#define GLEE_C_DEFINED_glDeleteFramebuffersEXT + void __stdcall GLee_Lazy_glDeleteFramebuffersEXT(GLsizei n, const GLuint * framebuffers) {if (GLeeInit()) glDeleteFramebuffersEXT(n, framebuffers);} + GLEEPFNGLDELETEFRAMEBUFFERSEXTPROC GLeeFuncPtr_glDeleteFramebuffersEXT=GLee_Lazy_glDeleteFramebuffersEXT; +#endif +#ifndef GLEE_C_DEFINED_glGenFramebuffersEXT +#define GLEE_C_DEFINED_glGenFramebuffersEXT + void __stdcall GLee_Lazy_glGenFramebuffersEXT(GLsizei n, GLuint * framebuffers) {if (GLeeInit()) glGenFramebuffersEXT(n, framebuffers);} + GLEEPFNGLGENFRAMEBUFFERSEXTPROC GLeeFuncPtr_glGenFramebuffersEXT=GLee_Lazy_glGenFramebuffersEXT; +#endif +#ifndef GLEE_C_DEFINED_glCheckFramebufferStatusEXT +#define GLEE_C_DEFINED_glCheckFramebufferStatusEXT + GLenum __stdcall GLee_Lazy_glCheckFramebufferStatusEXT(GLenum target) {if (GLeeInit()) return glCheckFramebufferStatusEXT(target); return (GLenum)0;} + GLEEPFNGLCHECKFRAMEBUFFERSTATUSEXTPROC GLeeFuncPtr_glCheckFramebufferStatusEXT=GLee_Lazy_glCheckFramebufferStatusEXT; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferTexture1DEXT +#define GLEE_C_DEFINED_glFramebufferTexture1DEXT + void __stdcall GLee_Lazy_glFramebufferTexture1DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {if (GLeeInit()) glFramebufferTexture1DEXT(target, attachment, textarget, texture, level);} + GLEEPFNGLFRAMEBUFFERTEXTURE1DEXTPROC GLeeFuncPtr_glFramebufferTexture1DEXT=GLee_Lazy_glFramebufferTexture1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferTexture2DEXT +#define GLEE_C_DEFINED_glFramebufferTexture2DEXT + void __stdcall GLee_Lazy_glFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {if (GLeeInit()) glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);} + GLEEPFNGLFRAMEBUFFERTEXTURE2DEXTPROC GLeeFuncPtr_glFramebufferTexture2DEXT=GLee_Lazy_glFramebufferTexture2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferTexture3DEXT +#define GLEE_C_DEFINED_glFramebufferTexture3DEXT + void __stdcall GLee_Lazy_glFramebufferTexture3DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) {if (GLeeInit()) glFramebufferTexture3DEXT(target, attachment, textarget, texture, level, zoffset);} + GLEEPFNGLFRAMEBUFFERTEXTURE3DEXTPROC GLeeFuncPtr_glFramebufferTexture3DEXT=GLee_Lazy_glFramebufferTexture3DEXT; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferRenderbufferEXT +#define GLEE_C_DEFINED_glFramebufferRenderbufferEXT + void __stdcall GLee_Lazy_glFramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {if (GLeeInit()) glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, renderbuffer);} + GLEEPFNGLFRAMEBUFFERRENDERBUFFEREXTPROC GLeeFuncPtr_glFramebufferRenderbufferEXT=GLee_Lazy_glFramebufferRenderbufferEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetFramebufferAttachmentParameterivEXT +#define GLEE_C_DEFINED_glGetFramebufferAttachmentParameterivEXT + void __stdcall GLee_Lazy_glGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, GLenum pname, GLint * params) {if (GLeeInit()) glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);} + GLEEPFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC GLeeFuncPtr_glGetFramebufferAttachmentParameterivEXT=GLee_Lazy_glGetFramebufferAttachmentParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGenerateMipmapEXT +#define GLEE_C_DEFINED_glGenerateMipmapEXT + void __stdcall GLee_Lazy_glGenerateMipmapEXT(GLenum target) {if (GLeeInit()) glGenerateMipmapEXT(target);} + GLEEPFNGLGENERATEMIPMAPEXTPROC GLeeFuncPtr_glGenerateMipmapEXT=GLee_Lazy_glGenerateMipmapEXT; +#endif +#endif + +/* GL_GREMEDY_string_marker */ + +#ifdef __GLEE_GL_GREMEDY_string_marker +#ifndef GLEE_C_DEFINED_glStringMarkerGREMEDY +#define GLEE_C_DEFINED_glStringMarkerGREMEDY + void __stdcall GLee_Lazy_glStringMarkerGREMEDY(GLsizei len, const GLvoid * string) {if (GLeeInit()) glStringMarkerGREMEDY(len, string);} + GLEEPFNGLSTRINGMARKERGREMEDYPROC GLeeFuncPtr_glStringMarkerGREMEDY=GLee_Lazy_glStringMarkerGREMEDY; +#endif +#endif + +/* GL_EXT_packed_depth_stencil */ + +#ifdef __GLEE_GL_EXT_packed_depth_stencil +#endif + +/* GL_EXT_stencil_clear_tag */ + +#ifdef __GLEE_GL_EXT_stencil_clear_tag +#ifndef GLEE_C_DEFINED_glStencilClearTagEXT +#define GLEE_C_DEFINED_glStencilClearTagEXT + void __stdcall GLee_Lazy_glStencilClearTagEXT(GLsizei stencilTagBits, GLuint stencilClearTag) {if (GLeeInit()) glStencilClearTagEXT(stencilTagBits, stencilClearTag);} + GLEEPFNGLSTENCILCLEARTAGEXTPROC GLeeFuncPtr_glStencilClearTagEXT=GLee_Lazy_glStencilClearTagEXT; +#endif +#endif + +/* GL_EXT_texture_sRGB */ + +#ifdef __GLEE_GL_EXT_texture_sRGB +#endif + +/* GL_EXT_framebuffer_blit */ + +#ifdef __GLEE_GL_EXT_framebuffer_blit +#ifndef GLEE_C_DEFINED_glBlitFramebufferEXT +#define GLEE_C_DEFINED_glBlitFramebufferEXT + void __stdcall GLee_Lazy_glBlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {if (GLeeInit()) glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);} + GLEEPFNGLBLITFRAMEBUFFEREXTPROC GLeeFuncPtr_glBlitFramebufferEXT=GLee_Lazy_glBlitFramebufferEXT; +#endif +#endif + +/* GL_EXT_framebuffer_multisample */ + +#ifdef __GLEE_GL_EXT_framebuffer_multisample +#ifndef GLEE_C_DEFINED_glRenderbufferStorageMultisampleEXT +#define GLEE_C_DEFINED_glRenderbufferStorageMultisampleEXT + void __stdcall GLee_Lazy_glRenderbufferStorageMultisampleEXT(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {if (GLeeInit()) glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height);} + GLEEPFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC GLeeFuncPtr_glRenderbufferStorageMultisampleEXT=GLee_Lazy_glRenderbufferStorageMultisampleEXT; +#endif +#endif + +/* GL_MESAX_texture_stack */ + +#ifdef __GLEE_GL_MESAX_texture_stack +#endif + +/* GL_EXT_timer_query */ + +#ifdef __GLEE_GL_EXT_timer_query +#ifndef GLEE_C_DEFINED_glGetQueryObjecti64vEXT +#define GLEE_C_DEFINED_glGetQueryObjecti64vEXT + void __stdcall GLee_Lazy_glGetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT * params) {if (GLeeInit()) glGetQueryObjecti64vEXT(id, pname, params);} + GLEEPFNGLGETQUERYOBJECTI64VEXTPROC GLeeFuncPtr_glGetQueryObjecti64vEXT=GLee_Lazy_glGetQueryObjecti64vEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetQueryObjectui64vEXT +#define GLEE_C_DEFINED_glGetQueryObjectui64vEXT + void __stdcall GLee_Lazy_glGetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT * params) {if (GLeeInit()) glGetQueryObjectui64vEXT(id, pname, params);} + GLEEPFNGLGETQUERYOBJECTUI64VEXTPROC GLeeFuncPtr_glGetQueryObjectui64vEXT=GLee_Lazy_glGetQueryObjectui64vEXT; +#endif +#endif + +/* GL_EXT_gpu_program_parameters */ + +#ifdef __GLEE_GL_EXT_gpu_program_parameters +#ifndef GLEE_C_DEFINED_glProgramEnvParameters4fvEXT +#define GLEE_C_DEFINED_glProgramEnvParameters4fvEXT + void __stdcall GLee_Lazy_glProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count, const GLfloat * params) {if (GLeeInit()) glProgramEnvParameters4fvEXT(target, index, count, params);} + GLEEPFNGLPROGRAMENVPARAMETERS4FVEXTPROC GLeeFuncPtr_glProgramEnvParameters4fvEXT=GLee_Lazy_glProgramEnvParameters4fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramLocalParameters4fvEXT +#define GLEE_C_DEFINED_glProgramLocalParameters4fvEXT + void __stdcall GLee_Lazy_glProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count, const GLfloat * params) {if (GLeeInit()) glProgramLocalParameters4fvEXT(target, index, count, params);} + GLEEPFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC GLeeFuncPtr_glProgramLocalParameters4fvEXT=GLee_Lazy_glProgramLocalParameters4fvEXT; +#endif +#endif + +/* GL_APPLE_flush_buffer_range */ + +#ifdef __GLEE_GL_APPLE_flush_buffer_range +#ifndef GLEE_C_DEFINED_glBufferParameteriAPPLE +#define GLEE_C_DEFINED_glBufferParameteriAPPLE + void __stdcall GLee_Lazy_glBufferParameteriAPPLE(GLenum target, GLenum pname, GLint param) {if (GLeeInit()) glBufferParameteriAPPLE(target, pname, param);} + GLEEPFNGLBUFFERPARAMETERIAPPLEPROC GLeeFuncPtr_glBufferParameteriAPPLE=GLee_Lazy_glBufferParameteriAPPLE; +#endif +#ifndef GLEE_C_DEFINED_glFlushMappedBufferRangeAPPLE +#define GLEE_C_DEFINED_glFlushMappedBufferRangeAPPLE + void __stdcall GLee_Lazy_glFlushMappedBufferRangeAPPLE(GLenum target, GLintptr offset, GLsizeiptr size) {if (GLeeInit()) glFlushMappedBufferRangeAPPLE(target, offset, size);} + GLEEPFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC GLeeFuncPtr_glFlushMappedBufferRangeAPPLE=GLee_Lazy_glFlushMappedBufferRangeAPPLE; +#endif +#endif + +/* GL_EXT_gpu_shader4 */ + +#ifdef __GLEE_GL_EXT_gpu_shader4 +#ifndef GLEE_C_DEFINED_glGetUniformuivEXT +#define GLEE_C_DEFINED_glGetUniformuivEXT + void __stdcall GLee_Lazy_glGetUniformuivEXT(GLuint program, GLint location, GLuint * params) {if (GLeeInit()) glGetUniformuivEXT(program, location, params);} + GLEEPFNGLGETUNIFORMUIVEXTPROC GLeeFuncPtr_glGetUniformuivEXT=GLee_Lazy_glGetUniformuivEXT; +#endif +#ifndef GLEE_C_DEFINED_glBindFragDataLocationEXT +#define GLEE_C_DEFINED_glBindFragDataLocationEXT + void __stdcall GLee_Lazy_glBindFragDataLocationEXT(GLuint program, GLuint color, const GLchar * name) {if (GLeeInit()) glBindFragDataLocationEXT(program, color, name);} + GLEEPFNGLBINDFRAGDATALOCATIONEXTPROC GLeeFuncPtr_glBindFragDataLocationEXT=GLee_Lazy_glBindFragDataLocationEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetFragDataLocationEXT +#define GLEE_C_DEFINED_glGetFragDataLocationEXT + GLint __stdcall GLee_Lazy_glGetFragDataLocationEXT(GLuint program, const GLchar * name) {if (GLeeInit()) return glGetFragDataLocationEXT(program, name); return (GLint)0;} + GLEEPFNGLGETFRAGDATALOCATIONEXTPROC GLeeFuncPtr_glGetFragDataLocationEXT=GLee_Lazy_glGetFragDataLocationEXT; +#endif +#ifndef GLEE_C_DEFINED_glUniform1uiEXT +#define GLEE_C_DEFINED_glUniform1uiEXT + void __stdcall GLee_Lazy_glUniform1uiEXT(GLint location, GLuint v0) {if (GLeeInit()) glUniform1uiEXT(location, v0);} + GLEEPFNGLUNIFORM1UIEXTPROC GLeeFuncPtr_glUniform1uiEXT=GLee_Lazy_glUniform1uiEXT; +#endif +#ifndef GLEE_C_DEFINED_glUniform2uiEXT +#define GLEE_C_DEFINED_glUniform2uiEXT + void __stdcall GLee_Lazy_glUniform2uiEXT(GLint location, GLuint v0, GLuint v1) {if (GLeeInit()) glUniform2uiEXT(location, v0, v1);} + GLEEPFNGLUNIFORM2UIEXTPROC GLeeFuncPtr_glUniform2uiEXT=GLee_Lazy_glUniform2uiEXT; +#endif +#ifndef GLEE_C_DEFINED_glUniform3uiEXT +#define GLEE_C_DEFINED_glUniform3uiEXT + void __stdcall GLee_Lazy_glUniform3uiEXT(GLint location, GLuint v0, GLuint v1, GLuint v2) {if (GLeeInit()) glUniform3uiEXT(location, v0, v1, v2);} + GLEEPFNGLUNIFORM3UIEXTPROC GLeeFuncPtr_glUniform3uiEXT=GLee_Lazy_glUniform3uiEXT; +#endif +#ifndef GLEE_C_DEFINED_glUniform4uiEXT +#define GLEE_C_DEFINED_glUniform4uiEXT + void __stdcall GLee_Lazy_glUniform4uiEXT(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {if (GLeeInit()) glUniform4uiEXT(location, v0, v1, v2, v3);} + GLEEPFNGLUNIFORM4UIEXTPROC GLeeFuncPtr_glUniform4uiEXT=GLee_Lazy_glUniform4uiEXT; +#endif +#ifndef GLEE_C_DEFINED_glUniform1uivEXT +#define GLEE_C_DEFINED_glUniform1uivEXT + void __stdcall GLee_Lazy_glUniform1uivEXT(GLint location, GLsizei count, const GLuint * value) {if (GLeeInit()) glUniform1uivEXT(location, count, value);} + GLEEPFNGLUNIFORM1UIVEXTPROC GLeeFuncPtr_glUniform1uivEXT=GLee_Lazy_glUniform1uivEXT; +#endif +#ifndef GLEE_C_DEFINED_glUniform2uivEXT +#define GLEE_C_DEFINED_glUniform2uivEXT + void __stdcall GLee_Lazy_glUniform2uivEXT(GLint location, GLsizei count, const GLuint * value) {if (GLeeInit()) glUniform2uivEXT(location, count, value);} + GLEEPFNGLUNIFORM2UIVEXTPROC GLeeFuncPtr_glUniform2uivEXT=GLee_Lazy_glUniform2uivEXT; +#endif +#ifndef GLEE_C_DEFINED_glUniform3uivEXT +#define GLEE_C_DEFINED_glUniform3uivEXT + void __stdcall GLee_Lazy_glUniform3uivEXT(GLint location, GLsizei count, const GLuint * value) {if (GLeeInit()) glUniform3uivEXT(location, count, value);} + GLEEPFNGLUNIFORM3UIVEXTPROC GLeeFuncPtr_glUniform3uivEXT=GLee_Lazy_glUniform3uivEXT; +#endif +#ifndef GLEE_C_DEFINED_glUniform4uivEXT +#define GLEE_C_DEFINED_glUniform4uivEXT + void __stdcall GLee_Lazy_glUniform4uivEXT(GLint location, GLsizei count, const GLuint * value) {if (GLeeInit()) glUniform4uivEXT(location, count, value);} + GLEEPFNGLUNIFORM4UIVEXTPROC GLeeFuncPtr_glUniform4uivEXT=GLee_Lazy_glUniform4uivEXT; +#endif +#endif + +/* GL_EXT_draw_instanced */ + +#ifdef __GLEE_GL_EXT_draw_instanced +#ifndef GLEE_C_DEFINED_glDrawArraysInstancedEXT +#define GLEE_C_DEFINED_glDrawArraysInstancedEXT + void __stdcall GLee_Lazy_glDrawArraysInstancedEXT(GLenum mode, GLint start, GLsizei count, GLsizei primcount) {if (GLeeInit()) glDrawArraysInstancedEXT(mode, start, count, primcount);} + GLEEPFNGLDRAWARRAYSINSTANCEDEXTPROC GLeeFuncPtr_glDrawArraysInstancedEXT=GLee_Lazy_glDrawArraysInstancedEXT; +#endif +#ifndef GLEE_C_DEFINED_glDrawElementsInstancedEXT +#define GLEE_C_DEFINED_glDrawElementsInstancedEXT + void __stdcall GLee_Lazy_glDrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices, GLsizei primcount) {if (GLeeInit()) glDrawElementsInstancedEXT(mode, count, type, indices, primcount);} + GLEEPFNGLDRAWELEMENTSINSTANCEDEXTPROC GLeeFuncPtr_glDrawElementsInstancedEXT=GLee_Lazy_glDrawElementsInstancedEXT; +#endif +#endif + +/* GL_EXT_packed_float */ + +#ifdef __GLEE_GL_EXT_packed_float +#endif + +/* GL_EXT_texture_array */ + +#ifdef __GLEE_GL_EXT_texture_array +#endif + +/* GL_EXT_texture_buffer_object */ + +#ifdef __GLEE_GL_EXT_texture_buffer_object +#ifndef GLEE_C_DEFINED_glTexBufferEXT +#define GLEE_C_DEFINED_glTexBufferEXT + void __stdcall GLee_Lazy_glTexBufferEXT(GLenum target, GLenum internalformat, GLuint buffer) {if (GLeeInit()) glTexBufferEXT(target, internalformat, buffer);} + GLEEPFNGLTEXBUFFEREXTPROC GLeeFuncPtr_glTexBufferEXT=GLee_Lazy_glTexBufferEXT; +#endif +#endif + +/* GL_EXT_texture_compression_latc */ + +#ifdef __GLEE_GL_EXT_texture_compression_latc +#endif + +/* GL_EXT_texture_compression_rgtc */ + +#ifdef __GLEE_GL_EXT_texture_compression_rgtc +#endif + +/* GL_EXT_texture_shared_exponent */ + +#ifdef __GLEE_GL_EXT_texture_shared_exponent +#endif + +/* GL_NV_depth_buffer_float */ + +#ifdef __GLEE_GL_NV_depth_buffer_float +#ifndef GLEE_C_DEFINED_glDepthRangedNV +#define GLEE_C_DEFINED_glDepthRangedNV + void __stdcall GLee_Lazy_glDepthRangedNV(GLdouble zNear, GLdouble zFar) {if (GLeeInit()) glDepthRangedNV(zNear, zFar);} + GLEEPFNGLDEPTHRANGEDNVPROC GLeeFuncPtr_glDepthRangedNV=GLee_Lazy_glDepthRangedNV; +#endif +#ifndef GLEE_C_DEFINED_glClearDepthdNV +#define GLEE_C_DEFINED_glClearDepthdNV + void __stdcall GLee_Lazy_glClearDepthdNV(GLdouble depth) {if (GLeeInit()) glClearDepthdNV(depth);} + GLEEPFNGLCLEARDEPTHDNVPROC GLeeFuncPtr_glClearDepthdNV=GLee_Lazy_glClearDepthdNV; +#endif +#ifndef GLEE_C_DEFINED_glDepthBoundsdNV +#define GLEE_C_DEFINED_glDepthBoundsdNV + void __stdcall GLee_Lazy_glDepthBoundsdNV(GLdouble zmin, GLdouble zmax) {if (GLeeInit()) glDepthBoundsdNV(zmin, zmax);} + GLEEPFNGLDEPTHBOUNDSDNVPROC GLeeFuncPtr_glDepthBoundsdNV=GLee_Lazy_glDepthBoundsdNV; +#endif +#endif + +/* GL_NV_framebuffer_multisample_coverage */ + +#ifdef __GLEE_GL_NV_framebuffer_multisample_coverage +#ifndef GLEE_C_DEFINED_glRenderbufferStorageMultisampleCoverageNV +#define GLEE_C_DEFINED_glRenderbufferStorageMultisampleCoverageNV + void __stdcall GLee_Lazy_glRenderbufferStorageMultisampleCoverageNV(GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height) {if (GLeeInit()) glRenderbufferStorageMultisampleCoverageNV(target, coverageSamples, colorSamples, internalformat, width, height);} + GLEEPFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC GLeeFuncPtr_glRenderbufferStorageMultisampleCoverageNV=GLee_Lazy_glRenderbufferStorageMultisampleCoverageNV; +#endif +#endif + +/* GL_EXT_framebuffer_sRGB */ + +#ifdef __GLEE_GL_EXT_framebuffer_sRGB +#endif + +/* GL_NV_geometry_shader4 */ + +#ifdef __GLEE_GL_NV_geometry_shader4 +#endif + +/* GL_NV_parameter_buffer_object */ + +#ifdef __GLEE_GL_NV_parameter_buffer_object +#ifndef GLEE_C_DEFINED_glProgramBufferParametersfvNV +#define GLEE_C_DEFINED_glProgramBufferParametersfvNV + void __stdcall GLee_Lazy_glProgramBufferParametersfvNV(GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat * params) {if (GLeeInit()) glProgramBufferParametersfvNV(target, buffer, index, count, params);} + GLEEPFNGLPROGRAMBUFFERPARAMETERSFVNVPROC GLeeFuncPtr_glProgramBufferParametersfvNV=GLee_Lazy_glProgramBufferParametersfvNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramBufferParametersIivNV +#define GLEE_C_DEFINED_glProgramBufferParametersIivNV + void __stdcall GLee_Lazy_glProgramBufferParametersIivNV(GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint * params) {if (GLeeInit()) glProgramBufferParametersIivNV(target, buffer, index, count, params);} + GLEEPFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC GLeeFuncPtr_glProgramBufferParametersIivNV=GLee_Lazy_glProgramBufferParametersIivNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramBufferParametersIuivNV +#define GLEE_C_DEFINED_glProgramBufferParametersIuivNV + void __stdcall GLee_Lazy_glProgramBufferParametersIuivNV(GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint * params) {if (GLeeInit()) glProgramBufferParametersIuivNV(target, buffer, index, count, params);} + GLEEPFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC GLeeFuncPtr_glProgramBufferParametersIuivNV=GLee_Lazy_glProgramBufferParametersIuivNV; +#endif +#endif + +/* GL_EXT_draw_buffers2 */ + +#ifdef __GLEE_GL_EXT_draw_buffers2 +#ifndef GLEE_C_DEFINED_glColorMaskIndexedEXT +#define GLEE_C_DEFINED_glColorMaskIndexedEXT + void __stdcall GLee_Lazy_glColorMaskIndexedEXT(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) {if (GLeeInit()) glColorMaskIndexedEXT(index, r, g, b, a);} + GLEEPFNGLCOLORMASKINDEXEDEXTPROC GLeeFuncPtr_glColorMaskIndexedEXT=GLee_Lazy_glColorMaskIndexedEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetBooleanIndexedvEXT +#define GLEE_C_DEFINED_glGetBooleanIndexedvEXT + void __stdcall GLee_Lazy_glGetBooleanIndexedvEXT(GLenum target, GLuint index, GLboolean * data) {if (GLeeInit()) glGetBooleanIndexedvEXT(target, index, data);} + GLEEPFNGLGETBOOLEANINDEXEDVEXTPROC GLeeFuncPtr_glGetBooleanIndexedvEXT=GLee_Lazy_glGetBooleanIndexedvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetIntegerIndexedvEXT +#define GLEE_C_DEFINED_glGetIntegerIndexedvEXT + void __stdcall GLee_Lazy_glGetIntegerIndexedvEXT(GLenum target, GLuint index, GLint * data) {if (GLeeInit()) glGetIntegerIndexedvEXT(target, index, data);} + GLEEPFNGLGETINTEGERINDEXEDVEXTPROC GLeeFuncPtr_glGetIntegerIndexedvEXT=GLee_Lazy_glGetIntegerIndexedvEXT; +#endif +#ifndef GLEE_C_DEFINED_glEnableIndexedEXT +#define GLEE_C_DEFINED_glEnableIndexedEXT + void __stdcall GLee_Lazy_glEnableIndexedEXT(GLenum target, GLuint index) {if (GLeeInit()) glEnableIndexedEXT(target, index);} + GLEEPFNGLENABLEINDEXEDEXTPROC GLeeFuncPtr_glEnableIndexedEXT=GLee_Lazy_glEnableIndexedEXT; +#endif +#ifndef GLEE_C_DEFINED_glDisableIndexedEXT +#define GLEE_C_DEFINED_glDisableIndexedEXT + void __stdcall GLee_Lazy_glDisableIndexedEXT(GLenum target, GLuint index) {if (GLeeInit()) glDisableIndexedEXT(target, index);} + GLEEPFNGLDISABLEINDEXEDEXTPROC GLeeFuncPtr_glDisableIndexedEXT=GLee_Lazy_glDisableIndexedEXT; +#endif +#ifndef GLEE_C_DEFINED_glIsEnabledIndexedEXT +#define GLEE_C_DEFINED_glIsEnabledIndexedEXT + GLboolean __stdcall GLee_Lazy_glIsEnabledIndexedEXT(GLenum target, GLuint index) {if (GLeeInit()) return glIsEnabledIndexedEXT(target, index); return (GLboolean)0;} + GLEEPFNGLISENABLEDINDEXEDEXTPROC GLeeFuncPtr_glIsEnabledIndexedEXT=GLee_Lazy_glIsEnabledIndexedEXT; +#endif +#endif + +/* GL_NV_transform_feedback */ + +#ifdef __GLEE_GL_NV_transform_feedback +#ifndef GLEE_C_DEFINED_glBeginTransformFeedbackNV +#define GLEE_C_DEFINED_glBeginTransformFeedbackNV + void __stdcall GLee_Lazy_glBeginTransformFeedbackNV(GLenum primitiveMode) {if (GLeeInit()) glBeginTransformFeedbackNV(primitiveMode);} + GLEEPFNGLBEGINTRANSFORMFEEDBACKNVPROC GLeeFuncPtr_glBeginTransformFeedbackNV=GLee_Lazy_glBeginTransformFeedbackNV; +#endif +#ifndef GLEE_C_DEFINED_glEndTransformFeedbackNV +#define GLEE_C_DEFINED_glEndTransformFeedbackNV + void __stdcall GLee_Lazy_glEndTransformFeedbackNV(void) {if (GLeeInit()) glEndTransformFeedbackNV();} + GLEEPFNGLENDTRANSFORMFEEDBACKNVPROC GLeeFuncPtr_glEndTransformFeedbackNV=GLee_Lazy_glEndTransformFeedbackNV; +#endif +#ifndef GLEE_C_DEFINED_glTransformFeedbackAttribsNV +#define GLEE_C_DEFINED_glTransformFeedbackAttribsNV + void __stdcall GLee_Lazy_glTransformFeedbackAttribsNV(GLuint count, const GLint * attribs, GLenum bufferMode) {if (GLeeInit()) glTransformFeedbackAttribsNV(count, attribs, bufferMode);} + GLEEPFNGLTRANSFORMFEEDBACKATTRIBSNVPROC GLeeFuncPtr_glTransformFeedbackAttribsNV=GLee_Lazy_glTransformFeedbackAttribsNV; +#endif +#ifndef GLEE_C_DEFINED_glBindBufferRangeNV +#define GLEE_C_DEFINED_glBindBufferRangeNV + void __stdcall GLee_Lazy_glBindBufferRangeNV(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {if (GLeeInit()) glBindBufferRangeNV(target, index, buffer, offset, size);} + GLEEPFNGLBINDBUFFERRANGENVPROC GLeeFuncPtr_glBindBufferRangeNV=GLee_Lazy_glBindBufferRangeNV; +#endif +#ifndef GLEE_C_DEFINED_glBindBufferOffsetNV +#define GLEE_C_DEFINED_glBindBufferOffsetNV + void __stdcall GLee_Lazy_glBindBufferOffsetNV(GLenum target, GLuint index, GLuint buffer, GLintptr offset) {if (GLeeInit()) glBindBufferOffsetNV(target, index, buffer, offset);} + GLEEPFNGLBINDBUFFEROFFSETNVPROC GLeeFuncPtr_glBindBufferOffsetNV=GLee_Lazy_glBindBufferOffsetNV; +#endif +#ifndef GLEE_C_DEFINED_glBindBufferBaseNV +#define GLEE_C_DEFINED_glBindBufferBaseNV + void __stdcall GLee_Lazy_glBindBufferBaseNV(GLenum target, GLuint index, GLuint buffer) {if (GLeeInit()) glBindBufferBaseNV(target, index, buffer);} + GLEEPFNGLBINDBUFFERBASENVPROC GLeeFuncPtr_glBindBufferBaseNV=GLee_Lazy_glBindBufferBaseNV; +#endif +#ifndef GLEE_C_DEFINED_glTransformFeedbackVaryingsNV +#define GLEE_C_DEFINED_glTransformFeedbackVaryingsNV + void __stdcall GLee_Lazy_glTransformFeedbackVaryingsNV(GLuint program, GLsizei count, const GLint * locations, GLenum bufferMode) {if (GLeeInit()) glTransformFeedbackVaryingsNV(program, count, locations, bufferMode);} + GLEEPFNGLTRANSFORMFEEDBACKVARYINGSNVPROC GLeeFuncPtr_glTransformFeedbackVaryingsNV=GLee_Lazy_glTransformFeedbackVaryingsNV; +#endif +#ifndef GLEE_C_DEFINED_glActiveVaryingNV +#define GLEE_C_DEFINED_glActiveVaryingNV + void __stdcall GLee_Lazy_glActiveVaryingNV(GLuint program, const GLchar * name) {if (GLeeInit()) glActiveVaryingNV(program, name);} + GLEEPFNGLACTIVEVARYINGNVPROC GLeeFuncPtr_glActiveVaryingNV=GLee_Lazy_glActiveVaryingNV; +#endif +#ifndef GLEE_C_DEFINED_glGetVaryingLocationNV +#define GLEE_C_DEFINED_glGetVaryingLocationNV + GLint __stdcall GLee_Lazy_glGetVaryingLocationNV(GLuint program, const GLchar * name) {if (GLeeInit()) return glGetVaryingLocationNV(program, name); return (GLint)0;} + GLEEPFNGLGETVARYINGLOCATIONNVPROC GLeeFuncPtr_glGetVaryingLocationNV=GLee_Lazy_glGetVaryingLocationNV; +#endif +#ifndef GLEE_C_DEFINED_glGetActiveVaryingNV +#define GLEE_C_DEFINED_glGetActiveVaryingNV + void __stdcall GLee_Lazy_glGetActiveVaryingNV(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name) {if (GLeeInit()) glGetActiveVaryingNV(program, index, bufSize, length, size, type, name);} + GLEEPFNGLGETACTIVEVARYINGNVPROC GLeeFuncPtr_glGetActiveVaryingNV=GLee_Lazy_glGetActiveVaryingNV; +#endif +#ifndef GLEE_C_DEFINED_glGetTransformFeedbackVaryingNV +#define GLEE_C_DEFINED_glGetTransformFeedbackVaryingNV + void __stdcall GLee_Lazy_glGetTransformFeedbackVaryingNV(GLuint program, GLuint index, GLint * location) {if (GLeeInit()) glGetTransformFeedbackVaryingNV(program, index, location);} + GLEEPFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC GLeeFuncPtr_glGetTransformFeedbackVaryingNV=GLee_Lazy_glGetTransformFeedbackVaryingNV; +#endif +#endif + +/* GL_EXT_bindable_uniform */ + +#ifdef __GLEE_GL_EXT_bindable_uniform +#ifndef GLEE_C_DEFINED_glUniformBufferEXT +#define GLEE_C_DEFINED_glUniformBufferEXT + void __stdcall GLee_Lazy_glUniformBufferEXT(GLuint program, GLint location, GLuint buffer) {if (GLeeInit()) glUniformBufferEXT(program, location, buffer);} + GLEEPFNGLUNIFORMBUFFEREXTPROC GLeeFuncPtr_glUniformBufferEXT=GLee_Lazy_glUniformBufferEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetUniformBufferSizeEXT +#define GLEE_C_DEFINED_glGetUniformBufferSizeEXT + GLint __stdcall GLee_Lazy_glGetUniformBufferSizeEXT(GLuint program, GLint location) {if (GLeeInit()) return glGetUniformBufferSizeEXT(program, location); return (GLint)0;} + GLEEPFNGLGETUNIFORMBUFFERSIZEEXTPROC GLeeFuncPtr_glGetUniformBufferSizeEXT=GLee_Lazy_glGetUniformBufferSizeEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetUniformOffsetEXT +#define GLEE_C_DEFINED_glGetUniformOffsetEXT + GLintptr __stdcall GLee_Lazy_glGetUniformOffsetEXT(GLuint program, GLint location) {if (GLeeInit()) return glGetUniformOffsetEXT(program, location); return (GLintptr)0;} + GLEEPFNGLGETUNIFORMOFFSETEXTPROC GLeeFuncPtr_glGetUniformOffsetEXT=GLee_Lazy_glGetUniformOffsetEXT; +#endif +#endif + +/* GL_EXT_texture_integer */ + +#ifdef __GLEE_GL_EXT_texture_integer +#ifndef GLEE_C_DEFINED_glTexParameterIivEXT +#define GLEE_C_DEFINED_glTexParameterIivEXT + void __stdcall GLee_Lazy_glTexParameterIivEXT(GLenum target, GLenum pname, const GLint * params) {if (GLeeInit()) glTexParameterIivEXT(target, pname, params);} + GLEEPFNGLTEXPARAMETERIIVEXTPROC GLeeFuncPtr_glTexParameterIivEXT=GLee_Lazy_glTexParameterIivEXT; +#endif +#ifndef GLEE_C_DEFINED_glTexParameterIuivEXT +#define GLEE_C_DEFINED_glTexParameterIuivEXT + void __stdcall GLee_Lazy_glTexParameterIuivEXT(GLenum target, GLenum pname, const GLuint * params) {if (GLeeInit()) glTexParameterIuivEXT(target, pname, params);} + GLEEPFNGLTEXPARAMETERIUIVEXTPROC GLeeFuncPtr_glTexParameterIuivEXT=GLee_Lazy_glTexParameterIuivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetTexParameterIivEXT +#define GLEE_C_DEFINED_glGetTexParameterIivEXT + void __stdcall GLee_Lazy_glGetTexParameterIivEXT(GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetTexParameterIivEXT(target, pname, params);} + GLEEPFNGLGETTEXPARAMETERIIVEXTPROC GLeeFuncPtr_glGetTexParameterIivEXT=GLee_Lazy_glGetTexParameterIivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetTexParameterIuivEXT +#define GLEE_C_DEFINED_glGetTexParameterIuivEXT + void __stdcall GLee_Lazy_glGetTexParameterIuivEXT(GLenum target, GLenum pname, GLuint * params) {if (GLeeInit()) glGetTexParameterIuivEXT(target, pname, params);} + GLEEPFNGLGETTEXPARAMETERIUIVEXTPROC GLeeFuncPtr_glGetTexParameterIuivEXT=GLee_Lazy_glGetTexParameterIuivEXT; +#endif +#ifndef GLEE_C_DEFINED_glClearColorIiEXT +#define GLEE_C_DEFINED_glClearColorIiEXT + void __stdcall GLee_Lazy_glClearColorIiEXT(GLint red, GLint green, GLint blue, GLint alpha) {if (GLeeInit()) glClearColorIiEXT(red, green, blue, alpha);} + GLEEPFNGLCLEARCOLORIIEXTPROC GLeeFuncPtr_glClearColorIiEXT=GLee_Lazy_glClearColorIiEXT; +#endif +#ifndef GLEE_C_DEFINED_glClearColorIuiEXT +#define GLEE_C_DEFINED_glClearColorIuiEXT + void __stdcall GLee_Lazy_glClearColorIuiEXT(GLuint red, GLuint green, GLuint blue, GLuint alpha) {if (GLeeInit()) glClearColorIuiEXT(red, green, blue, alpha);} + GLEEPFNGLCLEARCOLORIUIEXTPROC GLeeFuncPtr_glClearColorIuiEXT=GLee_Lazy_glClearColorIuiEXT; +#endif +#endif + +/* GL_GREMEDY_frame_terminator */ + +#ifdef __GLEE_GL_GREMEDY_frame_terminator +#ifndef GLEE_C_DEFINED_glFrameTerminatorGREMEDY +#define GLEE_C_DEFINED_glFrameTerminatorGREMEDY + void __stdcall GLee_Lazy_glFrameTerminatorGREMEDY(void) {if (GLeeInit()) glFrameTerminatorGREMEDY();} + GLEEPFNGLFRAMETERMINATORGREMEDYPROC GLeeFuncPtr_glFrameTerminatorGREMEDY=GLee_Lazy_glFrameTerminatorGREMEDY; +#endif +#endif + +/* GL_NV_conditional_render */ + +#ifdef __GLEE_GL_NV_conditional_render +#ifndef GLEE_C_DEFINED_glBeginConditionalRenderNV +#define GLEE_C_DEFINED_glBeginConditionalRenderNV + void __stdcall GLee_Lazy_glBeginConditionalRenderNV(GLuint id, GLenum mode) {if (GLeeInit()) glBeginConditionalRenderNV(id, mode);} + GLEEPFNGLBEGINCONDITIONALRENDERNVPROC GLeeFuncPtr_glBeginConditionalRenderNV=GLee_Lazy_glBeginConditionalRenderNV; +#endif +#ifndef GLEE_C_DEFINED_glEndConditionalRenderNV +#define GLEE_C_DEFINED_glEndConditionalRenderNV + void __stdcall GLee_Lazy_glEndConditionalRenderNV(void) {if (GLeeInit()) glEndConditionalRenderNV();} + GLEEPFNGLENDCONDITIONALRENDERNVPROC GLeeFuncPtr_glEndConditionalRenderNV=GLee_Lazy_glEndConditionalRenderNV; +#endif +#endif + +/* GL_NV_present_video */ + +#ifdef __GLEE_GL_NV_present_video +#endif + +/* GL_EXT_transform_feedback */ + +#ifdef __GLEE_GL_EXT_transform_feedback +#ifndef GLEE_C_DEFINED_glBeginTransformFeedbackEXT +#define GLEE_C_DEFINED_glBeginTransformFeedbackEXT + void __stdcall GLee_Lazy_glBeginTransformFeedbackEXT(GLenum primitiveMode) {if (GLeeInit()) glBeginTransformFeedbackEXT(primitiveMode);} + GLEEPFNGLBEGINTRANSFORMFEEDBACKEXTPROC GLeeFuncPtr_glBeginTransformFeedbackEXT=GLee_Lazy_glBeginTransformFeedbackEXT; +#endif +#ifndef GLEE_C_DEFINED_glEndTransformFeedbackEXT +#define GLEE_C_DEFINED_glEndTransformFeedbackEXT + void __stdcall GLee_Lazy_glEndTransformFeedbackEXT(void) {if (GLeeInit()) glEndTransformFeedbackEXT();} + GLEEPFNGLENDTRANSFORMFEEDBACKEXTPROC GLeeFuncPtr_glEndTransformFeedbackEXT=GLee_Lazy_glEndTransformFeedbackEXT; +#endif +#ifndef GLEE_C_DEFINED_glBindBufferRangeEXT +#define GLEE_C_DEFINED_glBindBufferRangeEXT + void __stdcall GLee_Lazy_glBindBufferRangeEXT(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {if (GLeeInit()) glBindBufferRangeEXT(target, index, buffer, offset, size);} + GLEEPFNGLBINDBUFFERRANGEEXTPROC GLeeFuncPtr_glBindBufferRangeEXT=GLee_Lazy_glBindBufferRangeEXT; +#endif +#ifndef GLEE_C_DEFINED_glBindBufferOffsetEXT +#define GLEE_C_DEFINED_glBindBufferOffsetEXT + void __stdcall GLee_Lazy_glBindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer, GLintptr offset) {if (GLeeInit()) glBindBufferOffsetEXT(target, index, buffer, offset);} + GLEEPFNGLBINDBUFFEROFFSETEXTPROC GLeeFuncPtr_glBindBufferOffsetEXT=GLee_Lazy_glBindBufferOffsetEXT; +#endif +#ifndef GLEE_C_DEFINED_glBindBufferBaseEXT +#define GLEE_C_DEFINED_glBindBufferBaseEXT + void __stdcall GLee_Lazy_glBindBufferBaseEXT(GLenum target, GLuint index, GLuint buffer) {if (GLeeInit()) glBindBufferBaseEXT(target, index, buffer);} + GLEEPFNGLBINDBUFFERBASEEXTPROC GLeeFuncPtr_glBindBufferBaseEXT=GLee_Lazy_glBindBufferBaseEXT; +#endif +#ifndef GLEE_C_DEFINED_glTransformFeedbackVaryingsEXT +#define GLEE_C_DEFINED_glTransformFeedbackVaryingsEXT + void __stdcall GLee_Lazy_glTransformFeedbackVaryingsEXT(GLuint program, GLsizei count, const GLint * locations, GLenum bufferMode) {if (GLeeInit()) glTransformFeedbackVaryingsEXT(program, count, locations, bufferMode);} + GLEEPFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC GLeeFuncPtr_glTransformFeedbackVaryingsEXT=GLee_Lazy_glTransformFeedbackVaryingsEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetTransformFeedbackVaryingEXT +#define GLEE_C_DEFINED_glGetTransformFeedbackVaryingEXT + void __stdcall GLee_Lazy_glGetTransformFeedbackVaryingEXT(GLuint program, GLuint index, GLint * location) {if (GLeeInit()) glGetTransformFeedbackVaryingEXT(program, index, location);} + GLEEPFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC GLeeFuncPtr_glGetTransformFeedbackVaryingEXT=GLee_Lazy_glGetTransformFeedbackVaryingEXT; +#endif +#endif + +/* GL_EXT_direct_state_access */ + +#ifdef __GLEE_GL_EXT_direct_state_access +#ifndef GLEE_C_DEFINED_glClientAttribDefaultEXT +#define GLEE_C_DEFINED_glClientAttribDefaultEXT + void __stdcall GLee_Lazy_glClientAttribDefaultEXT(GLbitfield mask) {if (GLeeInit()) glClientAttribDefaultEXT(mask);} + GLEEPFNGLCLIENTATTRIBDEFAULTEXTPROC GLeeFuncPtr_glClientAttribDefaultEXT=GLee_Lazy_glClientAttribDefaultEXT; +#endif +#ifndef GLEE_C_DEFINED_glPushClientAttribDefaultEXT +#define GLEE_C_DEFINED_glPushClientAttribDefaultEXT + void __stdcall GLee_Lazy_glPushClientAttribDefaultEXT(GLbitfield mask) {if (GLeeInit()) glPushClientAttribDefaultEXT(mask);} + GLEEPFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC GLeeFuncPtr_glPushClientAttribDefaultEXT=GLee_Lazy_glPushClientAttribDefaultEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixLoadfEXT +#define GLEE_C_DEFINED_glMatrixLoadfEXT + void __stdcall GLee_Lazy_glMatrixLoadfEXT(GLenum mode, const GLfloat * m) {if (GLeeInit()) glMatrixLoadfEXT(mode, m);} + GLEEPFNGLMATRIXLOADFEXTPROC GLeeFuncPtr_glMatrixLoadfEXT=GLee_Lazy_glMatrixLoadfEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixLoaddEXT +#define GLEE_C_DEFINED_glMatrixLoaddEXT + void __stdcall GLee_Lazy_glMatrixLoaddEXT(GLenum mode, const GLdouble * m) {if (GLeeInit()) glMatrixLoaddEXT(mode, m);} + GLEEPFNGLMATRIXLOADDEXTPROC GLeeFuncPtr_glMatrixLoaddEXT=GLee_Lazy_glMatrixLoaddEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixMultfEXT +#define GLEE_C_DEFINED_glMatrixMultfEXT + void __stdcall GLee_Lazy_glMatrixMultfEXT(GLenum mode, const GLfloat * m) {if (GLeeInit()) glMatrixMultfEXT(mode, m);} + GLEEPFNGLMATRIXMULTFEXTPROC GLeeFuncPtr_glMatrixMultfEXT=GLee_Lazy_glMatrixMultfEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixMultdEXT +#define GLEE_C_DEFINED_glMatrixMultdEXT + void __stdcall GLee_Lazy_glMatrixMultdEXT(GLenum mode, const GLdouble * m) {if (GLeeInit()) glMatrixMultdEXT(mode, m);} + GLEEPFNGLMATRIXMULTDEXTPROC GLeeFuncPtr_glMatrixMultdEXT=GLee_Lazy_glMatrixMultdEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixLoadIdentityEXT +#define GLEE_C_DEFINED_glMatrixLoadIdentityEXT + void __stdcall GLee_Lazy_glMatrixLoadIdentityEXT(GLenum mode) {if (GLeeInit()) glMatrixLoadIdentityEXT(mode);} + GLEEPFNGLMATRIXLOADIDENTITYEXTPROC GLeeFuncPtr_glMatrixLoadIdentityEXT=GLee_Lazy_glMatrixLoadIdentityEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixRotatefEXT +#define GLEE_C_DEFINED_glMatrixRotatefEXT + void __stdcall GLee_Lazy_glMatrixRotatefEXT(GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glMatrixRotatefEXT(mode, angle, x, y, z);} + GLEEPFNGLMATRIXROTATEFEXTPROC GLeeFuncPtr_glMatrixRotatefEXT=GLee_Lazy_glMatrixRotatefEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixRotatedEXT +#define GLEE_C_DEFINED_glMatrixRotatedEXT + void __stdcall GLee_Lazy_glMatrixRotatedEXT(GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z) {if (GLeeInit()) glMatrixRotatedEXT(mode, angle, x, y, z);} + GLEEPFNGLMATRIXROTATEDEXTPROC GLeeFuncPtr_glMatrixRotatedEXT=GLee_Lazy_glMatrixRotatedEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixScalefEXT +#define GLEE_C_DEFINED_glMatrixScalefEXT + void __stdcall GLee_Lazy_glMatrixScalefEXT(GLenum mode, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glMatrixScalefEXT(mode, x, y, z);} + GLEEPFNGLMATRIXSCALEFEXTPROC GLeeFuncPtr_glMatrixScalefEXT=GLee_Lazy_glMatrixScalefEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixScaledEXT +#define GLEE_C_DEFINED_glMatrixScaledEXT + void __stdcall GLee_Lazy_glMatrixScaledEXT(GLenum mode, GLdouble x, GLdouble y, GLdouble z) {if (GLeeInit()) glMatrixScaledEXT(mode, x, y, z);} + GLEEPFNGLMATRIXSCALEDEXTPROC GLeeFuncPtr_glMatrixScaledEXT=GLee_Lazy_glMatrixScaledEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixTranslatefEXT +#define GLEE_C_DEFINED_glMatrixTranslatefEXT + void __stdcall GLee_Lazy_glMatrixTranslatefEXT(GLenum mode, GLfloat x, GLfloat y, GLfloat z) {if (GLeeInit()) glMatrixTranslatefEXT(mode, x, y, z);} + GLEEPFNGLMATRIXTRANSLATEFEXTPROC GLeeFuncPtr_glMatrixTranslatefEXT=GLee_Lazy_glMatrixTranslatefEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixTranslatedEXT +#define GLEE_C_DEFINED_glMatrixTranslatedEXT + void __stdcall GLee_Lazy_glMatrixTranslatedEXT(GLenum mode, GLdouble x, GLdouble y, GLdouble z) {if (GLeeInit()) glMatrixTranslatedEXT(mode, x, y, z);} + GLEEPFNGLMATRIXTRANSLATEDEXTPROC GLeeFuncPtr_glMatrixTranslatedEXT=GLee_Lazy_glMatrixTranslatedEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixFrustumEXT +#define GLEE_C_DEFINED_glMatrixFrustumEXT + void __stdcall GLee_Lazy_glMatrixFrustumEXT(GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) {if (GLeeInit()) glMatrixFrustumEXT(mode, left, right, bottom, top, zNear, zFar);} + GLEEPFNGLMATRIXFRUSTUMEXTPROC GLeeFuncPtr_glMatrixFrustumEXT=GLee_Lazy_glMatrixFrustumEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixOrthoEXT +#define GLEE_C_DEFINED_glMatrixOrthoEXT + void __stdcall GLee_Lazy_glMatrixOrthoEXT(GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) {if (GLeeInit()) glMatrixOrthoEXT(mode, left, right, bottom, top, zNear, zFar);} + GLEEPFNGLMATRIXORTHOEXTPROC GLeeFuncPtr_glMatrixOrthoEXT=GLee_Lazy_glMatrixOrthoEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixPopEXT +#define GLEE_C_DEFINED_glMatrixPopEXT + void __stdcall GLee_Lazy_glMatrixPopEXT(GLenum mode) {if (GLeeInit()) glMatrixPopEXT(mode);} + GLEEPFNGLMATRIXPOPEXTPROC GLeeFuncPtr_glMatrixPopEXT=GLee_Lazy_glMatrixPopEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixPushEXT +#define GLEE_C_DEFINED_glMatrixPushEXT + void __stdcall GLee_Lazy_glMatrixPushEXT(GLenum mode) {if (GLeeInit()) glMatrixPushEXT(mode);} + GLEEPFNGLMATRIXPUSHEXTPROC GLeeFuncPtr_glMatrixPushEXT=GLee_Lazy_glMatrixPushEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixLoadTransposefEXT +#define GLEE_C_DEFINED_glMatrixLoadTransposefEXT + void __stdcall GLee_Lazy_glMatrixLoadTransposefEXT(GLenum mode, const GLfloat * m) {if (GLeeInit()) glMatrixLoadTransposefEXT(mode, m);} + GLEEPFNGLMATRIXLOADTRANSPOSEFEXTPROC GLeeFuncPtr_glMatrixLoadTransposefEXT=GLee_Lazy_glMatrixLoadTransposefEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixLoadTransposedEXT +#define GLEE_C_DEFINED_glMatrixLoadTransposedEXT + void __stdcall GLee_Lazy_glMatrixLoadTransposedEXT(GLenum mode, const GLdouble * m) {if (GLeeInit()) glMatrixLoadTransposedEXT(mode, m);} + GLEEPFNGLMATRIXLOADTRANSPOSEDEXTPROC GLeeFuncPtr_glMatrixLoadTransposedEXT=GLee_Lazy_glMatrixLoadTransposedEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixMultTransposefEXT +#define GLEE_C_DEFINED_glMatrixMultTransposefEXT + void __stdcall GLee_Lazy_glMatrixMultTransposefEXT(GLenum mode, const GLfloat * m) {if (GLeeInit()) glMatrixMultTransposefEXT(mode, m);} + GLEEPFNGLMATRIXMULTTRANSPOSEFEXTPROC GLeeFuncPtr_glMatrixMultTransposefEXT=GLee_Lazy_glMatrixMultTransposefEXT; +#endif +#ifndef GLEE_C_DEFINED_glMatrixMultTransposedEXT +#define GLEE_C_DEFINED_glMatrixMultTransposedEXT + void __stdcall GLee_Lazy_glMatrixMultTransposedEXT(GLenum mode, const GLdouble * m) {if (GLeeInit()) glMatrixMultTransposedEXT(mode, m);} + GLEEPFNGLMATRIXMULTTRANSPOSEDEXTPROC GLeeFuncPtr_glMatrixMultTransposedEXT=GLee_Lazy_glMatrixMultTransposedEXT; +#endif +#ifndef GLEE_C_DEFINED_glTextureParameterfEXT +#define GLEE_C_DEFINED_glTextureParameterfEXT + void __stdcall GLee_Lazy_glTextureParameterfEXT(GLuint texture, GLenum target, GLenum pname, GLfloat param) {if (GLeeInit()) glTextureParameterfEXT(texture, target, pname, param);} + GLEEPFNGLTEXTUREPARAMETERFEXTPROC GLeeFuncPtr_glTextureParameterfEXT=GLee_Lazy_glTextureParameterfEXT; +#endif +#ifndef GLEE_C_DEFINED_glTextureParameterfvEXT +#define GLEE_C_DEFINED_glTextureParameterfvEXT + void __stdcall GLee_Lazy_glTextureParameterfvEXT(GLuint texture, GLenum target, GLenum pname, const GLfloat * params) {if (GLeeInit()) glTextureParameterfvEXT(texture, target, pname, params);} + GLEEPFNGLTEXTUREPARAMETERFVEXTPROC GLeeFuncPtr_glTextureParameterfvEXT=GLee_Lazy_glTextureParameterfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glTextureParameteriEXT +#define GLEE_C_DEFINED_glTextureParameteriEXT + void __stdcall GLee_Lazy_glTextureParameteriEXT(GLuint texture, GLenum target, GLenum pname, GLint param) {if (GLeeInit()) glTextureParameteriEXT(texture, target, pname, param);} + GLEEPFNGLTEXTUREPARAMETERIEXTPROC GLeeFuncPtr_glTextureParameteriEXT=GLee_Lazy_glTextureParameteriEXT; +#endif +#ifndef GLEE_C_DEFINED_glTextureParameterivEXT +#define GLEE_C_DEFINED_glTextureParameterivEXT + void __stdcall GLee_Lazy_glTextureParameterivEXT(GLuint texture, GLenum target, GLenum pname, const GLint * params) {if (GLeeInit()) glTextureParameterivEXT(texture, target, pname, params);} + GLEEPFNGLTEXTUREPARAMETERIVEXTPROC GLeeFuncPtr_glTextureParameterivEXT=GLee_Lazy_glTextureParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glTextureImage1DEXT +#define GLEE_C_DEFINED_glTextureImage1DEXT + void __stdcall GLee_Lazy_glTextureImage1DEXT(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glTextureImage1DEXT(texture, target, level, internalformat, width, border, format, type, pixels);} + GLEEPFNGLTEXTUREIMAGE1DEXTPROC GLeeFuncPtr_glTextureImage1DEXT=GLee_Lazy_glTextureImage1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glTextureImage2DEXT +#define GLEE_C_DEFINED_glTextureImage2DEXT + void __stdcall GLee_Lazy_glTextureImage2DEXT(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glTextureImage2DEXT(texture, target, level, internalformat, width, height, border, format, type, pixels);} + GLEEPFNGLTEXTUREIMAGE2DEXTPROC GLeeFuncPtr_glTextureImage2DEXT=GLee_Lazy_glTextureImage2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glTextureSubImage1DEXT +#define GLEE_C_DEFINED_glTextureSubImage1DEXT + void __stdcall GLee_Lazy_glTextureSubImage1DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glTextureSubImage1DEXT(texture, target, level, xoffset, width, format, type, pixels);} + GLEEPFNGLTEXTURESUBIMAGE1DEXTPROC GLeeFuncPtr_glTextureSubImage1DEXT=GLee_Lazy_glTextureSubImage1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glTextureSubImage2DEXT +#define GLEE_C_DEFINED_glTextureSubImage2DEXT + void __stdcall GLee_Lazy_glTextureSubImage2DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glTextureSubImage2DEXT(texture, target, level, xoffset, yoffset, width, height, format, type, pixels);} + GLEEPFNGLTEXTURESUBIMAGE2DEXTPROC GLeeFuncPtr_glTextureSubImage2DEXT=GLee_Lazy_glTextureSubImage2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyTextureImage1DEXT +#define GLEE_C_DEFINED_glCopyTextureImage1DEXT + void __stdcall GLee_Lazy_glCopyTextureImage1DEXT(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border) {if (GLeeInit()) glCopyTextureImage1DEXT(texture, target, level, internalformat, x, y, width, border);} + GLEEPFNGLCOPYTEXTUREIMAGE1DEXTPROC GLeeFuncPtr_glCopyTextureImage1DEXT=GLee_Lazy_glCopyTextureImage1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyTextureImage2DEXT +#define GLEE_C_DEFINED_glCopyTextureImage2DEXT + void __stdcall GLee_Lazy_glCopyTextureImage2DEXT(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {if (GLeeInit()) glCopyTextureImage2DEXT(texture, target, level, internalformat, x, y, width, height, border);} + GLEEPFNGLCOPYTEXTUREIMAGE2DEXTPROC GLeeFuncPtr_glCopyTextureImage2DEXT=GLee_Lazy_glCopyTextureImage2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyTextureSubImage1DEXT +#define GLEE_C_DEFINED_glCopyTextureSubImage1DEXT + void __stdcall GLee_Lazy_glCopyTextureSubImage1DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) {if (GLeeInit()) glCopyTextureSubImage1DEXT(texture, target, level, xoffset, x, y, width);} + GLEEPFNGLCOPYTEXTURESUBIMAGE1DEXTPROC GLeeFuncPtr_glCopyTextureSubImage1DEXT=GLee_Lazy_glCopyTextureSubImage1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyTextureSubImage2DEXT +#define GLEE_C_DEFINED_glCopyTextureSubImage2DEXT + void __stdcall GLee_Lazy_glCopyTextureSubImage2DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {if (GLeeInit()) glCopyTextureSubImage2DEXT(texture, target, level, xoffset, yoffset, x, y, width, height);} + GLEEPFNGLCOPYTEXTURESUBIMAGE2DEXTPROC GLeeFuncPtr_glCopyTextureSubImage2DEXT=GLee_Lazy_glCopyTextureSubImage2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetTextureImageEXT +#define GLEE_C_DEFINED_glGetTextureImageEXT + void __stdcall GLee_Lazy_glGetTextureImageEXT(GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, GLvoid * pixels) {if (GLeeInit()) glGetTextureImageEXT(texture, target, level, format, type, pixels);} + GLEEPFNGLGETTEXTUREIMAGEEXTPROC GLeeFuncPtr_glGetTextureImageEXT=GLee_Lazy_glGetTextureImageEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetTextureParameterfvEXT +#define GLEE_C_DEFINED_glGetTextureParameterfvEXT + void __stdcall GLee_Lazy_glGetTextureParameterfvEXT(GLuint texture, GLenum target, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetTextureParameterfvEXT(texture, target, pname, params);} + GLEEPFNGLGETTEXTUREPARAMETERFVEXTPROC GLeeFuncPtr_glGetTextureParameterfvEXT=GLee_Lazy_glGetTextureParameterfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetTextureParameterivEXT +#define GLEE_C_DEFINED_glGetTextureParameterivEXT + void __stdcall GLee_Lazy_glGetTextureParameterivEXT(GLuint texture, GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetTextureParameterivEXT(texture, target, pname, params);} + GLEEPFNGLGETTEXTUREPARAMETERIVEXTPROC GLeeFuncPtr_glGetTextureParameterivEXT=GLee_Lazy_glGetTextureParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetTextureLevelParameterfvEXT +#define GLEE_C_DEFINED_glGetTextureLevelParameterfvEXT + void __stdcall GLee_Lazy_glGetTextureLevelParameterfvEXT(GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetTextureLevelParameterfvEXT(texture, target, level, pname, params);} + GLEEPFNGLGETTEXTURELEVELPARAMETERFVEXTPROC GLeeFuncPtr_glGetTextureLevelParameterfvEXT=GLee_Lazy_glGetTextureLevelParameterfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetTextureLevelParameterivEXT +#define GLEE_C_DEFINED_glGetTextureLevelParameterivEXT + void __stdcall GLee_Lazy_glGetTextureLevelParameterivEXT(GLuint texture, GLenum target, GLint level, GLenum pname, GLint * params) {if (GLeeInit()) glGetTextureLevelParameterivEXT(texture, target, level, pname, params);} + GLEEPFNGLGETTEXTURELEVELPARAMETERIVEXTPROC GLeeFuncPtr_glGetTextureLevelParameterivEXT=GLee_Lazy_glGetTextureLevelParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glTextureImage3DEXT +#define GLEE_C_DEFINED_glTextureImage3DEXT + void __stdcall GLee_Lazy_glTextureImage3DEXT(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glTextureImage3DEXT(texture, target, level, internalformat, width, height, depth, border, format, type, pixels);} + GLEEPFNGLTEXTUREIMAGE3DEXTPROC GLeeFuncPtr_glTextureImage3DEXT=GLee_Lazy_glTextureImage3DEXT; +#endif +#ifndef GLEE_C_DEFINED_glTextureSubImage3DEXT +#define GLEE_C_DEFINED_glTextureSubImage3DEXT + void __stdcall GLee_Lazy_glTextureSubImage3DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glTextureSubImage3DEXT(texture, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);} + GLEEPFNGLTEXTURESUBIMAGE3DEXTPROC GLeeFuncPtr_glTextureSubImage3DEXT=GLee_Lazy_glTextureSubImage3DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyTextureSubImage3DEXT +#define GLEE_C_DEFINED_glCopyTextureSubImage3DEXT + void __stdcall GLee_Lazy_glCopyTextureSubImage3DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {if (GLeeInit()) glCopyTextureSubImage3DEXT(texture, target, level, xoffset, yoffset, zoffset, x, y, width, height);} + GLEEPFNGLCOPYTEXTURESUBIMAGE3DEXTPROC GLeeFuncPtr_glCopyTextureSubImage3DEXT=GLee_Lazy_glCopyTextureSubImage3DEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexParameterfEXT +#define GLEE_C_DEFINED_glMultiTexParameterfEXT + void __stdcall GLee_Lazy_glMultiTexParameterfEXT(GLenum texunit, GLenum target, GLenum pname, GLfloat param) {if (GLeeInit()) glMultiTexParameterfEXT(texunit, target, pname, param);} + GLEEPFNGLMULTITEXPARAMETERFEXTPROC GLeeFuncPtr_glMultiTexParameterfEXT=GLee_Lazy_glMultiTexParameterfEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexParameterfvEXT +#define GLEE_C_DEFINED_glMultiTexParameterfvEXT + void __stdcall GLee_Lazy_glMultiTexParameterfvEXT(GLenum texunit, GLenum target, GLenum pname, const GLfloat * params) {if (GLeeInit()) glMultiTexParameterfvEXT(texunit, target, pname, params);} + GLEEPFNGLMULTITEXPARAMETERFVEXTPROC GLeeFuncPtr_glMultiTexParameterfvEXT=GLee_Lazy_glMultiTexParameterfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexParameteriEXT +#define GLEE_C_DEFINED_glMultiTexParameteriEXT + void __stdcall GLee_Lazy_glMultiTexParameteriEXT(GLenum texunit, GLenum target, GLenum pname, GLint param) {if (GLeeInit()) glMultiTexParameteriEXT(texunit, target, pname, param);} + GLEEPFNGLMULTITEXPARAMETERIEXTPROC GLeeFuncPtr_glMultiTexParameteriEXT=GLee_Lazy_glMultiTexParameteriEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexParameterivEXT +#define GLEE_C_DEFINED_glMultiTexParameterivEXT + void __stdcall GLee_Lazy_glMultiTexParameterivEXT(GLenum texunit, GLenum target, GLenum pname, const GLint * params) {if (GLeeInit()) glMultiTexParameterivEXT(texunit, target, pname, params);} + GLEEPFNGLMULTITEXPARAMETERIVEXTPROC GLeeFuncPtr_glMultiTexParameterivEXT=GLee_Lazy_glMultiTexParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexImage1DEXT +#define GLEE_C_DEFINED_glMultiTexImage1DEXT + void __stdcall GLee_Lazy_glMultiTexImage1DEXT(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glMultiTexImage1DEXT(texunit, target, level, internalformat, width, border, format, type, pixels);} + GLEEPFNGLMULTITEXIMAGE1DEXTPROC GLeeFuncPtr_glMultiTexImage1DEXT=GLee_Lazy_glMultiTexImage1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexImage2DEXT +#define GLEE_C_DEFINED_glMultiTexImage2DEXT + void __stdcall GLee_Lazy_glMultiTexImage2DEXT(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glMultiTexImage2DEXT(texunit, target, level, internalformat, width, height, border, format, type, pixels);} + GLEEPFNGLMULTITEXIMAGE2DEXTPROC GLeeFuncPtr_glMultiTexImage2DEXT=GLee_Lazy_glMultiTexImage2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexSubImage1DEXT +#define GLEE_C_DEFINED_glMultiTexSubImage1DEXT + void __stdcall GLee_Lazy_glMultiTexSubImage1DEXT(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glMultiTexSubImage1DEXT(texunit, target, level, xoffset, width, format, type, pixels);} + GLEEPFNGLMULTITEXSUBIMAGE1DEXTPROC GLeeFuncPtr_glMultiTexSubImage1DEXT=GLee_Lazy_glMultiTexSubImage1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexSubImage2DEXT +#define GLEE_C_DEFINED_glMultiTexSubImage2DEXT + void __stdcall GLee_Lazy_glMultiTexSubImage2DEXT(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glMultiTexSubImage2DEXT(texunit, target, level, xoffset, yoffset, width, height, format, type, pixels);} + GLEEPFNGLMULTITEXSUBIMAGE2DEXTPROC GLeeFuncPtr_glMultiTexSubImage2DEXT=GLee_Lazy_glMultiTexSubImage2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyMultiTexImage1DEXT +#define GLEE_C_DEFINED_glCopyMultiTexImage1DEXT + void __stdcall GLee_Lazy_glCopyMultiTexImage1DEXT(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border) {if (GLeeInit()) glCopyMultiTexImage1DEXT(texunit, target, level, internalformat, x, y, width, border);} + GLEEPFNGLCOPYMULTITEXIMAGE1DEXTPROC GLeeFuncPtr_glCopyMultiTexImage1DEXT=GLee_Lazy_glCopyMultiTexImage1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyMultiTexImage2DEXT +#define GLEE_C_DEFINED_glCopyMultiTexImage2DEXT + void __stdcall GLee_Lazy_glCopyMultiTexImage2DEXT(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {if (GLeeInit()) glCopyMultiTexImage2DEXT(texunit, target, level, internalformat, x, y, width, height, border);} + GLEEPFNGLCOPYMULTITEXIMAGE2DEXTPROC GLeeFuncPtr_glCopyMultiTexImage2DEXT=GLee_Lazy_glCopyMultiTexImage2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyMultiTexSubImage1DEXT +#define GLEE_C_DEFINED_glCopyMultiTexSubImage1DEXT + void __stdcall GLee_Lazy_glCopyMultiTexSubImage1DEXT(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) {if (GLeeInit()) glCopyMultiTexSubImage1DEXT(texunit, target, level, xoffset, x, y, width);} + GLEEPFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC GLeeFuncPtr_glCopyMultiTexSubImage1DEXT=GLee_Lazy_glCopyMultiTexSubImage1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyMultiTexSubImage2DEXT +#define GLEE_C_DEFINED_glCopyMultiTexSubImage2DEXT + void __stdcall GLee_Lazy_glCopyMultiTexSubImage2DEXT(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {if (GLeeInit()) glCopyMultiTexSubImage2DEXT(texunit, target, level, xoffset, yoffset, x, y, width, height);} + GLEEPFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC GLeeFuncPtr_glCopyMultiTexSubImage2DEXT=GLee_Lazy_glCopyMultiTexSubImage2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetMultiTexImageEXT +#define GLEE_C_DEFINED_glGetMultiTexImageEXT + void __stdcall GLee_Lazy_glGetMultiTexImageEXT(GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, GLvoid * pixels) {if (GLeeInit()) glGetMultiTexImageEXT(texunit, target, level, format, type, pixels);} + GLEEPFNGLGETMULTITEXIMAGEEXTPROC GLeeFuncPtr_glGetMultiTexImageEXT=GLee_Lazy_glGetMultiTexImageEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetMultiTexParameterfvEXT +#define GLEE_C_DEFINED_glGetMultiTexParameterfvEXT + void __stdcall GLee_Lazy_glGetMultiTexParameterfvEXT(GLenum texunit, GLenum target, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetMultiTexParameterfvEXT(texunit, target, pname, params);} + GLEEPFNGLGETMULTITEXPARAMETERFVEXTPROC GLeeFuncPtr_glGetMultiTexParameterfvEXT=GLee_Lazy_glGetMultiTexParameterfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetMultiTexParameterivEXT +#define GLEE_C_DEFINED_glGetMultiTexParameterivEXT + void __stdcall GLee_Lazy_glGetMultiTexParameterivEXT(GLenum texunit, GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetMultiTexParameterivEXT(texunit, target, pname, params);} + GLEEPFNGLGETMULTITEXPARAMETERIVEXTPROC GLeeFuncPtr_glGetMultiTexParameterivEXT=GLee_Lazy_glGetMultiTexParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetMultiTexLevelParameterfvEXT +#define GLEE_C_DEFINED_glGetMultiTexLevelParameterfvEXT + void __stdcall GLee_Lazy_glGetMultiTexLevelParameterfvEXT(GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetMultiTexLevelParameterfvEXT(texunit, target, level, pname, params);} + GLEEPFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC GLeeFuncPtr_glGetMultiTexLevelParameterfvEXT=GLee_Lazy_glGetMultiTexLevelParameterfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetMultiTexLevelParameterivEXT +#define GLEE_C_DEFINED_glGetMultiTexLevelParameterivEXT + void __stdcall GLee_Lazy_glGetMultiTexLevelParameterivEXT(GLenum texunit, GLenum target, GLint level, GLenum pname, GLint * params) {if (GLeeInit()) glGetMultiTexLevelParameterivEXT(texunit, target, level, pname, params);} + GLEEPFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC GLeeFuncPtr_glGetMultiTexLevelParameterivEXT=GLee_Lazy_glGetMultiTexLevelParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexImage3DEXT +#define GLEE_C_DEFINED_glMultiTexImage3DEXT + void __stdcall GLee_Lazy_glMultiTexImage3DEXT(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glMultiTexImage3DEXT(texunit, target, level, internalformat, width, height, depth, border, format, type, pixels);} + GLEEPFNGLMULTITEXIMAGE3DEXTPROC GLeeFuncPtr_glMultiTexImage3DEXT=GLee_Lazy_glMultiTexImage3DEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexSubImage3DEXT +#define GLEE_C_DEFINED_glMultiTexSubImage3DEXT + void __stdcall GLee_Lazy_glMultiTexSubImage3DEXT(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid * pixels) {if (GLeeInit()) glMultiTexSubImage3DEXT(texunit, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);} + GLEEPFNGLMULTITEXSUBIMAGE3DEXTPROC GLeeFuncPtr_glMultiTexSubImage3DEXT=GLee_Lazy_glMultiTexSubImage3DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCopyMultiTexSubImage3DEXT +#define GLEE_C_DEFINED_glCopyMultiTexSubImage3DEXT + void __stdcall GLee_Lazy_glCopyMultiTexSubImage3DEXT(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {if (GLeeInit()) glCopyMultiTexSubImage3DEXT(texunit, target, level, xoffset, yoffset, zoffset, x, y, width, height);} + GLEEPFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC GLeeFuncPtr_glCopyMultiTexSubImage3DEXT=GLee_Lazy_glCopyMultiTexSubImage3DEXT; +#endif +#ifndef GLEE_C_DEFINED_glBindMultiTextureEXT +#define GLEE_C_DEFINED_glBindMultiTextureEXT + void __stdcall GLee_Lazy_glBindMultiTextureEXT(GLenum texunit, GLenum target, GLuint texture) {if (GLeeInit()) glBindMultiTextureEXT(texunit, target, texture);} + GLEEPFNGLBINDMULTITEXTUREEXTPROC GLeeFuncPtr_glBindMultiTextureEXT=GLee_Lazy_glBindMultiTextureEXT; +#endif +#ifndef GLEE_C_DEFINED_glEnableClientStateIndexedEXT +#define GLEE_C_DEFINED_glEnableClientStateIndexedEXT + void __stdcall GLee_Lazy_glEnableClientStateIndexedEXT(GLenum array, GLuint index) {if (GLeeInit()) glEnableClientStateIndexedEXT(array, index);} + GLEEPFNGLENABLECLIENTSTATEINDEXEDEXTPROC GLeeFuncPtr_glEnableClientStateIndexedEXT=GLee_Lazy_glEnableClientStateIndexedEXT; +#endif +#ifndef GLEE_C_DEFINED_glDisableClientStateIndexedEXT +#define GLEE_C_DEFINED_glDisableClientStateIndexedEXT + void __stdcall GLee_Lazy_glDisableClientStateIndexedEXT(GLenum array, GLuint index) {if (GLeeInit()) glDisableClientStateIndexedEXT(array, index);} + GLEEPFNGLDISABLECLIENTSTATEINDEXEDEXTPROC GLeeFuncPtr_glDisableClientStateIndexedEXT=GLee_Lazy_glDisableClientStateIndexedEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexCoordPointerEXT +#define GLEE_C_DEFINED_glMultiTexCoordPointerEXT + void __stdcall GLee_Lazy_glMultiTexCoordPointerEXT(GLenum texunit, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {if (GLeeInit()) glMultiTexCoordPointerEXT(texunit, size, type, stride, pointer);} + GLEEPFNGLMULTITEXCOORDPOINTEREXTPROC GLeeFuncPtr_glMultiTexCoordPointerEXT=GLee_Lazy_glMultiTexCoordPointerEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexEnvfEXT +#define GLEE_C_DEFINED_glMultiTexEnvfEXT + void __stdcall GLee_Lazy_glMultiTexEnvfEXT(GLenum texunit, GLenum target, GLenum pname, GLfloat param) {if (GLeeInit()) glMultiTexEnvfEXT(texunit, target, pname, param);} + GLEEPFNGLMULTITEXENVFEXTPROC GLeeFuncPtr_glMultiTexEnvfEXT=GLee_Lazy_glMultiTexEnvfEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexEnvfvEXT +#define GLEE_C_DEFINED_glMultiTexEnvfvEXT + void __stdcall GLee_Lazy_glMultiTexEnvfvEXT(GLenum texunit, GLenum target, GLenum pname, const GLfloat * params) {if (GLeeInit()) glMultiTexEnvfvEXT(texunit, target, pname, params);} + GLEEPFNGLMULTITEXENVFVEXTPROC GLeeFuncPtr_glMultiTexEnvfvEXT=GLee_Lazy_glMultiTexEnvfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexEnviEXT +#define GLEE_C_DEFINED_glMultiTexEnviEXT + void __stdcall GLee_Lazy_glMultiTexEnviEXT(GLenum texunit, GLenum target, GLenum pname, GLint param) {if (GLeeInit()) glMultiTexEnviEXT(texunit, target, pname, param);} + GLEEPFNGLMULTITEXENVIEXTPROC GLeeFuncPtr_glMultiTexEnviEXT=GLee_Lazy_glMultiTexEnviEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexEnvivEXT +#define GLEE_C_DEFINED_glMultiTexEnvivEXT + void __stdcall GLee_Lazy_glMultiTexEnvivEXT(GLenum texunit, GLenum target, GLenum pname, const GLint * params) {if (GLeeInit()) glMultiTexEnvivEXT(texunit, target, pname, params);} + GLEEPFNGLMULTITEXENVIVEXTPROC GLeeFuncPtr_glMultiTexEnvivEXT=GLee_Lazy_glMultiTexEnvivEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexGendEXT +#define GLEE_C_DEFINED_glMultiTexGendEXT + void __stdcall GLee_Lazy_glMultiTexGendEXT(GLenum texunit, GLenum coord, GLenum pname, GLdouble param) {if (GLeeInit()) glMultiTexGendEXT(texunit, coord, pname, param);} + GLEEPFNGLMULTITEXGENDEXTPROC GLeeFuncPtr_glMultiTexGendEXT=GLee_Lazy_glMultiTexGendEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexGendvEXT +#define GLEE_C_DEFINED_glMultiTexGendvEXT + void __stdcall GLee_Lazy_glMultiTexGendvEXT(GLenum texunit, GLenum coord, GLenum pname, const GLdouble * params) {if (GLeeInit()) glMultiTexGendvEXT(texunit, coord, pname, params);} + GLEEPFNGLMULTITEXGENDVEXTPROC GLeeFuncPtr_glMultiTexGendvEXT=GLee_Lazy_glMultiTexGendvEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexGenfEXT +#define GLEE_C_DEFINED_glMultiTexGenfEXT + void __stdcall GLee_Lazy_glMultiTexGenfEXT(GLenum texunit, GLenum coord, GLenum pname, GLfloat param) {if (GLeeInit()) glMultiTexGenfEXT(texunit, coord, pname, param);} + GLEEPFNGLMULTITEXGENFEXTPROC GLeeFuncPtr_glMultiTexGenfEXT=GLee_Lazy_glMultiTexGenfEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexGenfvEXT +#define GLEE_C_DEFINED_glMultiTexGenfvEXT + void __stdcall GLee_Lazy_glMultiTexGenfvEXT(GLenum texunit, GLenum coord, GLenum pname, const GLfloat * params) {if (GLeeInit()) glMultiTexGenfvEXT(texunit, coord, pname, params);} + GLEEPFNGLMULTITEXGENFVEXTPROC GLeeFuncPtr_glMultiTexGenfvEXT=GLee_Lazy_glMultiTexGenfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexGeniEXT +#define GLEE_C_DEFINED_glMultiTexGeniEXT + void __stdcall GLee_Lazy_glMultiTexGeniEXT(GLenum texunit, GLenum coord, GLenum pname, GLint param) {if (GLeeInit()) glMultiTexGeniEXT(texunit, coord, pname, param);} + GLEEPFNGLMULTITEXGENIEXTPROC GLeeFuncPtr_glMultiTexGeniEXT=GLee_Lazy_glMultiTexGeniEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexGenivEXT +#define GLEE_C_DEFINED_glMultiTexGenivEXT + void __stdcall GLee_Lazy_glMultiTexGenivEXT(GLenum texunit, GLenum coord, GLenum pname, const GLint * params) {if (GLeeInit()) glMultiTexGenivEXT(texunit, coord, pname, params);} + GLEEPFNGLMULTITEXGENIVEXTPROC GLeeFuncPtr_glMultiTexGenivEXT=GLee_Lazy_glMultiTexGenivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetMultiTexEnvfvEXT +#define GLEE_C_DEFINED_glGetMultiTexEnvfvEXT + void __stdcall GLee_Lazy_glGetMultiTexEnvfvEXT(GLenum texunit, GLenum target, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetMultiTexEnvfvEXT(texunit, target, pname, params);} + GLEEPFNGLGETMULTITEXENVFVEXTPROC GLeeFuncPtr_glGetMultiTexEnvfvEXT=GLee_Lazy_glGetMultiTexEnvfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetMultiTexEnvivEXT +#define GLEE_C_DEFINED_glGetMultiTexEnvivEXT + void __stdcall GLee_Lazy_glGetMultiTexEnvivEXT(GLenum texunit, GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetMultiTexEnvivEXT(texunit, target, pname, params);} + GLEEPFNGLGETMULTITEXENVIVEXTPROC GLeeFuncPtr_glGetMultiTexEnvivEXT=GLee_Lazy_glGetMultiTexEnvivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetMultiTexGendvEXT +#define GLEE_C_DEFINED_glGetMultiTexGendvEXT + void __stdcall GLee_Lazy_glGetMultiTexGendvEXT(GLenum texunit, GLenum coord, GLenum pname, GLdouble * params) {if (GLeeInit()) glGetMultiTexGendvEXT(texunit, coord, pname, params);} + GLEEPFNGLGETMULTITEXGENDVEXTPROC GLeeFuncPtr_glGetMultiTexGendvEXT=GLee_Lazy_glGetMultiTexGendvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetMultiTexGenfvEXT +#define GLEE_C_DEFINED_glGetMultiTexGenfvEXT + void __stdcall GLee_Lazy_glGetMultiTexGenfvEXT(GLenum texunit, GLenum coord, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetMultiTexGenfvEXT(texunit, coord, pname, params);} + GLEEPFNGLGETMULTITEXGENFVEXTPROC GLeeFuncPtr_glGetMultiTexGenfvEXT=GLee_Lazy_glGetMultiTexGenfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetMultiTexGenivEXT +#define GLEE_C_DEFINED_glGetMultiTexGenivEXT + void __stdcall GLee_Lazy_glGetMultiTexGenivEXT(GLenum texunit, GLenum coord, GLenum pname, GLint * params) {if (GLeeInit()) glGetMultiTexGenivEXT(texunit, coord, pname, params);} + GLEEPFNGLGETMULTITEXGENIVEXTPROC GLeeFuncPtr_glGetMultiTexGenivEXT=GLee_Lazy_glGetMultiTexGenivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetFloatIndexedvEXT +#define GLEE_C_DEFINED_glGetFloatIndexedvEXT + void __stdcall GLee_Lazy_glGetFloatIndexedvEXT(GLenum target, GLuint index, GLfloat * data) {if (GLeeInit()) glGetFloatIndexedvEXT(target, index, data);} + GLEEPFNGLGETFLOATINDEXEDVEXTPROC GLeeFuncPtr_glGetFloatIndexedvEXT=GLee_Lazy_glGetFloatIndexedvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetDoubleIndexedvEXT +#define GLEE_C_DEFINED_glGetDoubleIndexedvEXT + void __stdcall GLee_Lazy_glGetDoubleIndexedvEXT(GLenum target, GLuint index, GLdouble * data) {if (GLeeInit()) glGetDoubleIndexedvEXT(target, index, data);} + GLEEPFNGLGETDOUBLEINDEXEDVEXTPROC GLeeFuncPtr_glGetDoubleIndexedvEXT=GLee_Lazy_glGetDoubleIndexedvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetPointerIndexedvEXT +#define GLEE_C_DEFINED_glGetPointerIndexedvEXT + void __stdcall GLee_Lazy_glGetPointerIndexedvEXT(GLenum target, GLuint index, GLvoid* * data) {if (GLeeInit()) glGetPointerIndexedvEXT(target, index, data);} + GLEEPFNGLGETPOINTERINDEXEDVEXTPROC GLeeFuncPtr_glGetPointerIndexedvEXT=GLee_Lazy_glGetPointerIndexedvEXT; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTextureImage3DEXT +#define GLEE_C_DEFINED_glCompressedTextureImage3DEXT + void __stdcall GLee_Lazy_glCompressedTextureImage3DEXT(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid * bits) {if (GLeeInit()) glCompressedTextureImage3DEXT(texture, target, level, internalformat, width, height, depth, border, imageSize, bits);} + GLEEPFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC GLeeFuncPtr_glCompressedTextureImage3DEXT=GLee_Lazy_glCompressedTextureImage3DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTextureImage2DEXT +#define GLEE_C_DEFINED_glCompressedTextureImage2DEXT + void __stdcall GLee_Lazy_glCompressedTextureImage2DEXT(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * bits) {if (GLeeInit()) glCompressedTextureImage2DEXT(texture, target, level, internalformat, width, height, border, imageSize, bits);} + GLEEPFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC GLeeFuncPtr_glCompressedTextureImage2DEXT=GLee_Lazy_glCompressedTextureImage2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTextureImage1DEXT +#define GLEE_C_DEFINED_glCompressedTextureImage1DEXT + void __stdcall GLee_Lazy_glCompressedTextureImage1DEXT(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid * bits) {if (GLeeInit()) glCompressedTextureImage1DEXT(texture, target, level, internalformat, width, border, imageSize, bits);} + GLEEPFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC GLeeFuncPtr_glCompressedTextureImage1DEXT=GLee_Lazy_glCompressedTextureImage1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTextureSubImage3DEXT +#define GLEE_C_DEFINED_glCompressedTextureSubImage3DEXT + void __stdcall GLee_Lazy_glCompressedTextureSubImage3DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid * bits) {if (GLeeInit()) glCompressedTextureSubImage3DEXT(texture, target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, bits);} + GLEEPFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC GLeeFuncPtr_glCompressedTextureSubImage3DEXT=GLee_Lazy_glCompressedTextureSubImage3DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTextureSubImage2DEXT +#define GLEE_C_DEFINED_glCompressedTextureSubImage2DEXT + void __stdcall GLee_Lazy_glCompressedTextureSubImage2DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid * bits) {if (GLeeInit()) glCompressedTextureSubImage2DEXT(texture, target, level, xoffset, yoffset, width, height, format, imageSize, bits);} + GLEEPFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC GLeeFuncPtr_glCompressedTextureSubImage2DEXT=GLee_Lazy_glCompressedTextureSubImage2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCompressedTextureSubImage1DEXT +#define GLEE_C_DEFINED_glCompressedTextureSubImage1DEXT + void __stdcall GLee_Lazy_glCompressedTextureSubImage1DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid * bits) {if (GLeeInit()) glCompressedTextureSubImage1DEXT(texture, target, level, xoffset, width, format, imageSize, bits);} + GLEEPFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC GLeeFuncPtr_glCompressedTextureSubImage1DEXT=GLee_Lazy_glCompressedTextureSubImage1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetCompressedTextureImageEXT +#define GLEE_C_DEFINED_glGetCompressedTextureImageEXT + void __stdcall GLee_Lazy_glGetCompressedTextureImageEXT(GLuint texture, GLenum target, GLint lod, GLvoid * img) {if (GLeeInit()) glGetCompressedTextureImageEXT(texture, target, lod, img);} + GLEEPFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC GLeeFuncPtr_glGetCompressedTextureImageEXT=GLee_Lazy_glGetCompressedTextureImageEXT; +#endif +#ifndef GLEE_C_DEFINED_glCompressedMultiTexImage3DEXT +#define GLEE_C_DEFINED_glCompressedMultiTexImage3DEXT + void __stdcall GLee_Lazy_glCompressedMultiTexImage3DEXT(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid * bits) {if (GLeeInit()) glCompressedMultiTexImage3DEXT(texunit, target, level, internalformat, width, height, depth, border, imageSize, bits);} + GLEEPFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC GLeeFuncPtr_glCompressedMultiTexImage3DEXT=GLee_Lazy_glCompressedMultiTexImage3DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCompressedMultiTexImage2DEXT +#define GLEE_C_DEFINED_glCompressedMultiTexImage2DEXT + void __stdcall GLee_Lazy_glCompressedMultiTexImage2DEXT(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * bits) {if (GLeeInit()) glCompressedMultiTexImage2DEXT(texunit, target, level, internalformat, width, height, border, imageSize, bits);} + GLEEPFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC GLeeFuncPtr_glCompressedMultiTexImage2DEXT=GLee_Lazy_glCompressedMultiTexImage2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCompressedMultiTexImage1DEXT +#define GLEE_C_DEFINED_glCompressedMultiTexImage1DEXT + void __stdcall GLee_Lazy_glCompressedMultiTexImage1DEXT(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid * bits) {if (GLeeInit()) glCompressedMultiTexImage1DEXT(texunit, target, level, internalformat, width, border, imageSize, bits);} + GLEEPFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC GLeeFuncPtr_glCompressedMultiTexImage1DEXT=GLee_Lazy_glCompressedMultiTexImage1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCompressedMultiTexSubImage3DEXT +#define GLEE_C_DEFINED_glCompressedMultiTexSubImage3DEXT + void __stdcall GLee_Lazy_glCompressedMultiTexSubImage3DEXT(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid * bits) {if (GLeeInit()) glCompressedMultiTexSubImage3DEXT(texunit, target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, bits);} + GLEEPFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC GLeeFuncPtr_glCompressedMultiTexSubImage3DEXT=GLee_Lazy_glCompressedMultiTexSubImage3DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCompressedMultiTexSubImage2DEXT +#define GLEE_C_DEFINED_glCompressedMultiTexSubImage2DEXT + void __stdcall GLee_Lazy_glCompressedMultiTexSubImage2DEXT(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid * bits) {if (GLeeInit()) glCompressedMultiTexSubImage2DEXT(texunit, target, level, xoffset, yoffset, width, height, format, imageSize, bits);} + GLEEPFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC GLeeFuncPtr_glCompressedMultiTexSubImage2DEXT=GLee_Lazy_glCompressedMultiTexSubImage2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glCompressedMultiTexSubImage1DEXT +#define GLEE_C_DEFINED_glCompressedMultiTexSubImage1DEXT + void __stdcall GLee_Lazy_glCompressedMultiTexSubImage1DEXT(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid * bits) {if (GLeeInit()) glCompressedMultiTexSubImage1DEXT(texunit, target, level, xoffset, width, format, imageSize, bits);} + GLEEPFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC GLeeFuncPtr_glCompressedMultiTexSubImage1DEXT=GLee_Lazy_glCompressedMultiTexSubImage1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetCompressedMultiTexImageEXT +#define GLEE_C_DEFINED_glGetCompressedMultiTexImageEXT + void __stdcall GLee_Lazy_glGetCompressedMultiTexImageEXT(GLenum texunit, GLenum target, GLint lod, GLvoid * img) {if (GLeeInit()) glGetCompressedMultiTexImageEXT(texunit, target, lod, img);} + GLEEPFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC GLeeFuncPtr_glGetCompressedMultiTexImageEXT=GLee_Lazy_glGetCompressedMultiTexImageEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedProgramStringEXT +#define GLEE_C_DEFINED_glNamedProgramStringEXT + void __stdcall GLee_Lazy_glNamedProgramStringEXT(GLuint program, GLenum target, GLenum format, GLsizei len, const GLvoid * string) {if (GLeeInit()) glNamedProgramStringEXT(program, target, format, len, string);} + GLEEPFNGLNAMEDPROGRAMSTRINGEXTPROC GLeeFuncPtr_glNamedProgramStringEXT=GLee_Lazy_glNamedProgramStringEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedProgramLocalParameter4dEXT +#define GLEE_C_DEFINED_glNamedProgramLocalParameter4dEXT + void __stdcall GLee_Lazy_glNamedProgramLocalParameter4dEXT(GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) {if (GLeeInit()) glNamedProgramLocalParameter4dEXT(program, target, index, x, y, z, w);} + GLEEPFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC GLeeFuncPtr_glNamedProgramLocalParameter4dEXT=GLee_Lazy_glNamedProgramLocalParameter4dEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedProgramLocalParameter4dvEXT +#define GLEE_C_DEFINED_glNamedProgramLocalParameter4dvEXT + void __stdcall GLee_Lazy_glNamedProgramLocalParameter4dvEXT(GLuint program, GLenum target, GLuint index, const GLdouble * params) {if (GLeeInit()) glNamedProgramLocalParameter4dvEXT(program, target, index, params);} + GLEEPFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC GLeeFuncPtr_glNamedProgramLocalParameter4dvEXT=GLee_Lazy_glNamedProgramLocalParameter4dvEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedProgramLocalParameter4fEXT +#define GLEE_C_DEFINED_glNamedProgramLocalParameter4fEXT + void __stdcall GLee_Lazy_glNamedProgramLocalParameter4fEXT(GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {if (GLeeInit()) glNamedProgramLocalParameter4fEXT(program, target, index, x, y, z, w);} + GLEEPFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC GLeeFuncPtr_glNamedProgramLocalParameter4fEXT=GLee_Lazy_glNamedProgramLocalParameter4fEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedProgramLocalParameter4fvEXT +#define GLEE_C_DEFINED_glNamedProgramLocalParameter4fvEXT + void __stdcall GLee_Lazy_glNamedProgramLocalParameter4fvEXT(GLuint program, GLenum target, GLuint index, const GLfloat * params) {if (GLeeInit()) glNamedProgramLocalParameter4fvEXT(program, target, index, params);} + GLEEPFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC GLeeFuncPtr_glNamedProgramLocalParameter4fvEXT=GLee_Lazy_glNamedProgramLocalParameter4fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetNamedProgramLocalParameterdvEXT +#define GLEE_C_DEFINED_glGetNamedProgramLocalParameterdvEXT + void __stdcall GLee_Lazy_glGetNamedProgramLocalParameterdvEXT(GLuint program, GLenum target, GLuint index, GLdouble * params) {if (GLeeInit()) glGetNamedProgramLocalParameterdvEXT(program, target, index, params);} + GLEEPFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC GLeeFuncPtr_glGetNamedProgramLocalParameterdvEXT=GLee_Lazy_glGetNamedProgramLocalParameterdvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetNamedProgramLocalParameterfvEXT +#define GLEE_C_DEFINED_glGetNamedProgramLocalParameterfvEXT + void __stdcall GLee_Lazy_glGetNamedProgramLocalParameterfvEXT(GLuint program, GLenum target, GLuint index, GLfloat * params) {if (GLeeInit()) glGetNamedProgramLocalParameterfvEXT(program, target, index, params);} + GLEEPFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC GLeeFuncPtr_glGetNamedProgramLocalParameterfvEXT=GLee_Lazy_glGetNamedProgramLocalParameterfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetNamedProgramivEXT +#define GLEE_C_DEFINED_glGetNamedProgramivEXT + void __stdcall GLee_Lazy_glGetNamedProgramivEXT(GLuint program, GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetNamedProgramivEXT(program, target, pname, params);} + GLEEPFNGLGETNAMEDPROGRAMIVEXTPROC GLeeFuncPtr_glGetNamedProgramivEXT=GLee_Lazy_glGetNamedProgramivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetNamedProgramStringEXT +#define GLEE_C_DEFINED_glGetNamedProgramStringEXT + void __stdcall GLee_Lazy_glGetNamedProgramStringEXT(GLuint program, GLenum target, GLenum pname, GLvoid * string) {if (GLeeInit()) glGetNamedProgramStringEXT(program, target, pname, string);} + GLEEPFNGLGETNAMEDPROGRAMSTRINGEXTPROC GLeeFuncPtr_glGetNamedProgramStringEXT=GLee_Lazy_glGetNamedProgramStringEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedProgramLocalParameters4fvEXT +#define GLEE_C_DEFINED_glNamedProgramLocalParameters4fvEXT + void __stdcall GLee_Lazy_glNamedProgramLocalParameters4fvEXT(GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat * params) {if (GLeeInit()) glNamedProgramLocalParameters4fvEXT(program, target, index, count, params);} + GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC GLeeFuncPtr_glNamedProgramLocalParameters4fvEXT=GLee_Lazy_glNamedProgramLocalParameters4fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedProgramLocalParameterI4iEXT +#define GLEE_C_DEFINED_glNamedProgramLocalParameterI4iEXT + void __stdcall GLee_Lazy_glNamedProgramLocalParameterI4iEXT(GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w) {if (GLeeInit()) glNamedProgramLocalParameterI4iEXT(program, target, index, x, y, z, w);} + GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC GLeeFuncPtr_glNamedProgramLocalParameterI4iEXT=GLee_Lazy_glNamedProgramLocalParameterI4iEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedProgramLocalParameterI4ivEXT +#define GLEE_C_DEFINED_glNamedProgramLocalParameterI4ivEXT + void __stdcall GLee_Lazy_glNamedProgramLocalParameterI4ivEXT(GLuint program, GLenum target, GLuint index, const GLint * params) {if (GLeeInit()) glNamedProgramLocalParameterI4ivEXT(program, target, index, params);} + GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC GLeeFuncPtr_glNamedProgramLocalParameterI4ivEXT=GLee_Lazy_glNamedProgramLocalParameterI4ivEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedProgramLocalParametersI4ivEXT +#define GLEE_C_DEFINED_glNamedProgramLocalParametersI4ivEXT + void __stdcall GLee_Lazy_glNamedProgramLocalParametersI4ivEXT(GLuint program, GLenum target, GLuint index, GLsizei count, const GLint * params) {if (GLeeInit()) glNamedProgramLocalParametersI4ivEXT(program, target, index, count, params);} + GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC GLeeFuncPtr_glNamedProgramLocalParametersI4ivEXT=GLee_Lazy_glNamedProgramLocalParametersI4ivEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedProgramLocalParameterI4uiEXT +#define GLEE_C_DEFINED_glNamedProgramLocalParameterI4uiEXT + void __stdcall GLee_Lazy_glNamedProgramLocalParameterI4uiEXT(GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) {if (GLeeInit()) glNamedProgramLocalParameterI4uiEXT(program, target, index, x, y, z, w);} + GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC GLeeFuncPtr_glNamedProgramLocalParameterI4uiEXT=GLee_Lazy_glNamedProgramLocalParameterI4uiEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedProgramLocalParameterI4uivEXT +#define GLEE_C_DEFINED_glNamedProgramLocalParameterI4uivEXT + void __stdcall GLee_Lazy_glNamedProgramLocalParameterI4uivEXT(GLuint program, GLenum target, GLuint index, const GLuint * params) {if (GLeeInit()) glNamedProgramLocalParameterI4uivEXT(program, target, index, params);} + GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC GLeeFuncPtr_glNamedProgramLocalParameterI4uivEXT=GLee_Lazy_glNamedProgramLocalParameterI4uivEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedProgramLocalParametersI4uivEXT +#define GLEE_C_DEFINED_glNamedProgramLocalParametersI4uivEXT + void __stdcall GLee_Lazy_glNamedProgramLocalParametersI4uivEXT(GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint * params) {if (GLeeInit()) glNamedProgramLocalParametersI4uivEXT(program, target, index, count, params);} + GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC GLeeFuncPtr_glNamedProgramLocalParametersI4uivEXT=GLee_Lazy_glNamedProgramLocalParametersI4uivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetNamedProgramLocalParameterIivEXT +#define GLEE_C_DEFINED_glGetNamedProgramLocalParameterIivEXT + void __stdcall GLee_Lazy_glGetNamedProgramLocalParameterIivEXT(GLuint program, GLenum target, GLuint index, GLint * params) {if (GLeeInit()) glGetNamedProgramLocalParameterIivEXT(program, target, index, params);} + GLEEPFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC GLeeFuncPtr_glGetNamedProgramLocalParameterIivEXT=GLee_Lazy_glGetNamedProgramLocalParameterIivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetNamedProgramLocalParameterIuivEXT +#define GLEE_C_DEFINED_glGetNamedProgramLocalParameterIuivEXT + void __stdcall GLee_Lazy_glGetNamedProgramLocalParameterIuivEXT(GLuint program, GLenum target, GLuint index, GLuint * params) {if (GLeeInit()) glGetNamedProgramLocalParameterIuivEXT(program, target, index, params);} + GLEEPFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC GLeeFuncPtr_glGetNamedProgramLocalParameterIuivEXT=GLee_Lazy_glGetNamedProgramLocalParameterIuivEXT; +#endif +#ifndef GLEE_C_DEFINED_glTextureParameterIivEXT +#define GLEE_C_DEFINED_glTextureParameterIivEXT + void __stdcall GLee_Lazy_glTextureParameterIivEXT(GLuint texture, GLenum target, GLenum pname, const GLint * params) {if (GLeeInit()) glTextureParameterIivEXT(texture, target, pname, params);} + GLEEPFNGLTEXTUREPARAMETERIIVEXTPROC GLeeFuncPtr_glTextureParameterIivEXT=GLee_Lazy_glTextureParameterIivEXT; +#endif +#ifndef GLEE_C_DEFINED_glTextureParameterIuivEXT +#define GLEE_C_DEFINED_glTextureParameterIuivEXT + void __stdcall GLee_Lazy_glTextureParameterIuivEXT(GLuint texture, GLenum target, GLenum pname, const GLuint * params) {if (GLeeInit()) glTextureParameterIuivEXT(texture, target, pname, params);} + GLEEPFNGLTEXTUREPARAMETERIUIVEXTPROC GLeeFuncPtr_glTextureParameterIuivEXT=GLee_Lazy_glTextureParameterIuivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetTextureParameterIivEXT +#define GLEE_C_DEFINED_glGetTextureParameterIivEXT + void __stdcall GLee_Lazy_glGetTextureParameterIivEXT(GLuint texture, GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetTextureParameterIivEXT(texture, target, pname, params);} + GLEEPFNGLGETTEXTUREPARAMETERIIVEXTPROC GLeeFuncPtr_glGetTextureParameterIivEXT=GLee_Lazy_glGetTextureParameterIivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetTextureParameterIuivEXT +#define GLEE_C_DEFINED_glGetTextureParameterIuivEXT + void __stdcall GLee_Lazy_glGetTextureParameterIuivEXT(GLuint texture, GLenum target, GLenum pname, GLuint * params) {if (GLeeInit()) glGetTextureParameterIuivEXT(texture, target, pname, params);} + GLEEPFNGLGETTEXTUREPARAMETERIUIVEXTPROC GLeeFuncPtr_glGetTextureParameterIuivEXT=GLee_Lazy_glGetTextureParameterIuivEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexParameterIivEXT +#define GLEE_C_DEFINED_glMultiTexParameterIivEXT + void __stdcall GLee_Lazy_glMultiTexParameterIivEXT(GLenum texunit, GLenum target, GLenum pname, const GLint * params) {if (GLeeInit()) glMultiTexParameterIivEXT(texunit, target, pname, params);} + GLEEPFNGLMULTITEXPARAMETERIIVEXTPROC GLeeFuncPtr_glMultiTexParameterIivEXT=GLee_Lazy_glMultiTexParameterIivEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexParameterIuivEXT +#define GLEE_C_DEFINED_glMultiTexParameterIuivEXT + void __stdcall GLee_Lazy_glMultiTexParameterIuivEXT(GLenum texunit, GLenum target, GLenum pname, const GLuint * params) {if (GLeeInit()) glMultiTexParameterIuivEXT(texunit, target, pname, params);} + GLEEPFNGLMULTITEXPARAMETERIUIVEXTPROC GLeeFuncPtr_glMultiTexParameterIuivEXT=GLee_Lazy_glMultiTexParameterIuivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetMultiTexParameterIivEXT +#define GLEE_C_DEFINED_glGetMultiTexParameterIivEXT + void __stdcall GLee_Lazy_glGetMultiTexParameterIivEXT(GLenum texunit, GLenum target, GLenum pname, GLint * params) {if (GLeeInit()) glGetMultiTexParameterIivEXT(texunit, target, pname, params);} + GLEEPFNGLGETMULTITEXPARAMETERIIVEXTPROC GLeeFuncPtr_glGetMultiTexParameterIivEXT=GLee_Lazy_glGetMultiTexParameterIivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetMultiTexParameterIuivEXT +#define GLEE_C_DEFINED_glGetMultiTexParameterIuivEXT + void __stdcall GLee_Lazy_glGetMultiTexParameterIuivEXT(GLenum texunit, GLenum target, GLenum pname, GLuint * params) {if (GLeeInit()) glGetMultiTexParameterIuivEXT(texunit, target, pname, params);} + GLEEPFNGLGETMULTITEXPARAMETERIUIVEXTPROC GLeeFuncPtr_glGetMultiTexParameterIuivEXT=GLee_Lazy_glGetMultiTexParameterIuivEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform1fEXT +#define GLEE_C_DEFINED_glProgramUniform1fEXT + void __stdcall GLee_Lazy_glProgramUniform1fEXT(GLuint program, GLint location, GLfloat v0) {if (GLeeInit()) glProgramUniform1fEXT(program, location, v0);} + GLEEPFNGLPROGRAMUNIFORM1FEXTPROC GLeeFuncPtr_glProgramUniform1fEXT=GLee_Lazy_glProgramUniform1fEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform2fEXT +#define GLEE_C_DEFINED_glProgramUniform2fEXT + void __stdcall GLee_Lazy_glProgramUniform2fEXT(GLuint program, GLint location, GLfloat v0, GLfloat v1) {if (GLeeInit()) glProgramUniform2fEXT(program, location, v0, v1);} + GLEEPFNGLPROGRAMUNIFORM2FEXTPROC GLeeFuncPtr_glProgramUniform2fEXT=GLee_Lazy_glProgramUniform2fEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform3fEXT +#define GLEE_C_DEFINED_glProgramUniform3fEXT + void __stdcall GLee_Lazy_glProgramUniform3fEXT(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {if (GLeeInit()) glProgramUniform3fEXT(program, location, v0, v1, v2);} + GLEEPFNGLPROGRAMUNIFORM3FEXTPROC GLeeFuncPtr_glProgramUniform3fEXT=GLee_Lazy_glProgramUniform3fEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform4fEXT +#define GLEE_C_DEFINED_glProgramUniform4fEXT + void __stdcall GLee_Lazy_glProgramUniform4fEXT(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {if (GLeeInit()) glProgramUniform4fEXT(program, location, v0, v1, v2, v3);} + GLEEPFNGLPROGRAMUNIFORM4FEXTPROC GLeeFuncPtr_glProgramUniform4fEXT=GLee_Lazy_glProgramUniform4fEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform1iEXT +#define GLEE_C_DEFINED_glProgramUniform1iEXT + void __stdcall GLee_Lazy_glProgramUniform1iEXT(GLuint program, GLint location, GLint v0) {if (GLeeInit()) glProgramUniform1iEXT(program, location, v0);} + GLEEPFNGLPROGRAMUNIFORM1IEXTPROC GLeeFuncPtr_glProgramUniform1iEXT=GLee_Lazy_glProgramUniform1iEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform2iEXT +#define GLEE_C_DEFINED_glProgramUniform2iEXT + void __stdcall GLee_Lazy_glProgramUniform2iEXT(GLuint program, GLint location, GLint v0, GLint v1) {if (GLeeInit()) glProgramUniform2iEXT(program, location, v0, v1);} + GLEEPFNGLPROGRAMUNIFORM2IEXTPROC GLeeFuncPtr_glProgramUniform2iEXT=GLee_Lazy_glProgramUniform2iEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform3iEXT +#define GLEE_C_DEFINED_glProgramUniform3iEXT + void __stdcall GLee_Lazy_glProgramUniform3iEXT(GLuint program, GLint location, GLint v0, GLint v1, GLint v2) {if (GLeeInit()) glProgramUniform3iEXT(program, location, v0, v1, v2);} + GLEEPFNGLPROGRAMUNIFORM3IEXTPROC GLeeFuncPtr_glProgramUniform3iEXT=GLee_Lazy_glProgramUniform3iEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform4iEXT +#define GLEE_C_DEFINED_glProgramUniform4iEXT + void __stdcall GLee_Lazy_glProgramUniform4iEXT(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {if (GLeeInit()) glProgramUniform4iEXT(program, location, v0, v1, v2, v3);} + GLEEPFNGLPROGRAMUNIFORM4IEXTPROC GLeeFuncPtr_glProgramUniform4iEXT=GLee_Lazy_glProgramUniform4iEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform1fvEXT +#define GLEE_C_DEFINED_glProgramUniform1fvEXT + void __stdcall GLee_Lazy_glProgramUniform1fvEXT(GLuint program, GLint location, GLsizei count, const GLfloat * value) {if (GLeeInit()) glProgramUniform1fvEXT(program, location, count, value);} + GLEEPFNGLPROGRAMUNIFORM1FVEXTPROC GLeeFuncPtr_glProgramUniform1fvEXT=GLee_Lazy_glProgramUniform1fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform2fvEXT +#define GLEE_C_DEFINED_glProgramUniform2fvEXT + void __stdcall GLee_Lazy_glProgramUniform2fvEXT(GLuint program, GLint location, GLsizei count, const GLfloat * value) {if (GLeeInit()) glProgramUniform2fvEXT(program, location, count, value);} + GLEEPFNGLPROGRAMUNIFORM2FVEXTPROC GLeeFuncPtr_glProgramUniform2fvEXT=GLee_Lazy_glProgramUniform2fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform3fvEXT +#define GLEE_C_DEFINED_glProgramUniform3fvEXT + void __stdcall GLee_Lazy_glProgramUniform3fvEXT(GLuint program, GLint location, GLsizei count, const GLfloat * value) {if (GLeeInit()) glProgramUniform3fvEXT(program, location, count, value);} + GLEEPFNGLPROGRAMUNIFORM3FVEXTPROC GLeeFuncPtr_glProgramUniform3fvEXT=GLee_Lazy_glProgramUniform3fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform4fvEXT +#define GLEE_C_DEFINED_glProgramUniform4fvEXT + void __stdcall GLee_Lazy_glProgramUniform4fvEXT(GLuint program, GLint location, GLsizei count, const GLfloat * value) {if (GLeeInit()) glProgramUniform4fvEXT(program, location, count, value);} + GLEEPFNGLPROGRAMUNIFORM4FVEXTPROC GLeeFuncPtr_glProgramUniform4fvEXT=GLee_Lazy_glProgramUniform4fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform1ivEXT +#define GLEE_C_DEFINED_glProgramUniform1ivEXT + void __stdcall GLee_Lazy_glProgramUniform1ivEXT(GLuint program, GLint location, GLsizei count, const GLint * value) {if (GLeeInit()) glProgramUniform1ivEXT(program, location, count, value);} + GLEEPFNGLPROGRAMUNIFORM1IVEXTPROC GLeeFuncPtr_glProgramUniform1ivEXT=GLee_Lazy_glProgramUniform1ivEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform2ivEXT +#define GLEE_C_DEFINED_glProgramUniform2ivEXT + void __stdcall GLee_Lazy_glProgramUniform2ivEXT(GLuint program, GLint location, GLsizei count, const GLint * value) {if (GLeeInit()) glProgramUniform2ivEXT(program, location, count, value);} + GLEEPFNGLPROGRAMUNIFORM2IVEXTPROC GLeeFuncPtr_glProgramUniform2ivEXT=GLee_Lazy_glProgramUniform2ivEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform3ivEXT +#define GLEE_C_DEFINED_glProgramUniform3ivEXT + void __stdcall GLee_Lazy_glProgramUniform3ivEXT(GLuint program, GLint location, GLsizei count, const GLint * value) {if (GLeeInit()) glProgramUniform3ivEXT(program, location, count, value);} + GLEEPFNGLPROGRAMUNIFORM3IVEXTPROC GLeeFuncPtr_glProgramUniform3ivEXT=GLee_Lazy_glProgramUniform3ivEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform4ivEXT +#define GLEE_C_DEFINED_glProgramUniform4ivEXT + void __stdcall GLee_Lazy_glProgramUniform4ivEXT(GLuint program, GLint location, GLsizei count, const GLint * value) {if (GLeeInit()) glProgramUniform4ivEXT(program, location, count, value);} + GLEEPFNGLPROGRAMUNIFORM4IVEXTPROC GLeeFuncPtr_glProgramUniform4ivEXT=GLee_Lazy_glProgramUniform4ivEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniformMatrix2fvEXT +#define GLEE_C_DEFINED_glProgramUniformMatrix2fvEXT + void __stdcall GLee_Lazy_glProgramUniformMatrix2fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glProgramUniformMatrix2fvEXT(program, location, count, transpose, value);} + GLEEPFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix2fvEXT=GLee_Lazy_glProgramUniformMatrix2fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniformMatrix3fvEXT +#define GLEE_C_DEFINED_glProgramUniformMatrix3fvEXT + void __stdcall GLee_Lazy_glProgramUniformMatrix3fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glProgramUniformMatrix3fvEXT(program, location, count, transpose, value);} + GLEEPFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix3fvEXT=GLee_Lazy_glProgramUniformMatrix3fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniformMatrix4fvEXT +#define GLEE_C_DEFINED_glProgramUniformMatrix4fvEXT + void __stdcall GLee_Lazy_glProgramUniformMatrix4fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glProgramUniformMatrix4fvEXT(program, location, count, transpose, value);} + GLEEPFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix4fvEXT=GLee_Lazy_glProgramUniformMatrix4fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniformMatrix2x3fvEXT +#define GLEE_C_DEFINED_glProgramUniformMatrix2x3fvEXT + void __stdcall GLee_Lazy_glProgramUniformMatrix2x3fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glProgramUniformMatrix2x3fvEXT(program, location, count, transpose, value);} + GLEEPFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix2x3fvEXT=GLee_Lazy_glProgramUniformMatrix2x3fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniformMatrix3x2fvEXT +#define GLEE_C_DEFINED_glProgramUniformMatrix3x2fvEXT + void __stdcall GLee_Lazy_glProgramUniformMatrix3x2fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glProgramUniformMatrix3x2fvEXT(program, location, count, transpose, value);} + GLEEPFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix3x2fvEXT=GLee_Lazy_glProgramUniformMatrix3x2fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniformMatrix2x4fvEXT +#define GLEE_C_DEFINED_glProgramUniformMatrix2x4fvEXT + void __stdcall GLee_Lazy_glProgramUniformMatrix2x4fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glProgramUniformMatrix2x4fvEXT(program, location, count, transpose, value);} + GLEEPFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix2x4fvEXT=GLee_Lazy_glProgramUniformMatrix2x4fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniformMatrix4x2fvEXT +#define GLEE_C_DEFINED_glProgramUniformMatrix4x2fvEXT + void __stdcall GLee_Lazy_glProgramUniformMatrix4x2fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glProgramUniformMatrix4x2fvEXT(program, location, count, transpose, value);} + GLEEPFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix4x2fvEXT=GLee_Lazy_glProgramUniformMatrix4x2fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniformMatrix3x4fvEXT +#define GLEE_C_DEFINED_glProgramUniformMatrix3x4fvEXT + void __stdcall GLee_Lazy_glProgramUniformMatrix3x4fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glProgramUniformMatrix3x4fvEXT(program, location, count, transpose, value);} + GLEEPFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix3x4fvEXT=GLee_Lazy_glProgramUniformMatrix3x4fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniformMatrix4x3fvEXT +#define GLEE_C_DEFINED_glProgramUniformMatrix4x3fvEXT + void __stdcall GLee_Lazy_glProgramUniformMatrix4x3fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {if (GLeeInit()) glProgramUniformMatrix4x3fvEXT(program, location, count, transpose, value);} + GLEEPFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix4x3fvEXT=GLee_Lazy_glProgramUniformMatrix4x3fvEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform1uiEXT +#define GLEE_C_DEFINED_glProgramUniform1uiEXT + void __stdcall GLee_Lazy_glProgramUniform1uiEXT(GLuint program, GLint location, GLuint v0) {if (GLeeInit()) glProgramUniform1uiEXT(program, location, v0);} + GLEEPFNGLPROGRAMUNIFORM1UIEXTPROC GLeeFuncPtr_glProgramUniform1uiEXT=GLee_Lazy_glProgramUniform1uiEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform2uiEXT +#define GLEE_C_DEFINED_glProgramUniform2uiEXT + void __stdcall GLee_Lazy_glProgramUniform2uiEXT(GLuint program, GLint location, GLuint v0, GLuint v1) {if (GLeeInit()) glProgramUniform2uiEXT(program, location, v0, v1);} + GLEEPFNGLPROGRAMUNIFORM2UIEXTPROC GLeeFuncPtr_glProgramUniform2uiEXT=GLee_Lazy_glProgramUniform2uiEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform3uiEXT +#define GLEE_C_DEFINED_glProgramUniform3uiEXT + void __stdcall GLee_Lazy_glProgramUniform3uiEXT(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2) {if (GLeeInit()) glProgramUniform3uiEXT(program, location, v0, v1, v2);} + GLEEPFNGLPROGRAMUNIFORM3UIEXTPROC GLeeFuncPtr_glProgramUniform3uiEXT=GLee_Lazy_glProgramUniform3uiEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform4uiEXT +#define GLEE_C_DEFINED_glProgramUniform4uiEXT + void __stdcall GLee_Lazy_glProgramUniform4uiEXT(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {if (GLeeInit()) glProgramUniform4uiEXT(program, location, v0, v1, v2, v3);} + GLEEPFNGLPROGRAMUNIFORM4UIEXTPROC GLeeFuncPtr_glProgramUniform4uiEXT=GLee_Lazy_glProgramUniform4uiEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform1uivEXT +#define GLEE_C_DEFINED_glProgramUniform1uivEXT + void __stdcall GLee_Lazy_glProgramUniform1uivEXT(GLuint program, GLint location, GLsizei count, const GLuint * value) {if (GLeeInit()) glProgramUniform1uivEXT(program, location, count, value);} + GLEEPFNGLPROGRAMUNIFORM1UIVEXTPROC GLeeFuncPtr_glProgramUniform1uivEXT=GLee_Lazy_glProgramUniform1uivEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform2uivEXT +#define GLEE_C_DEFINED_glProgramUniform2uivEXT + void __stdcall GLee_Lazy_glProgramUniform2uivEXT(GLuint program, GLint location, GLsizei count, const GLuint * value) {if (GLeeInit()) glProgramUniform2uivEXT(program, location, count, value);} + GLEEPFNGLPROGRAMUNIFORM2UIVEXTPROC GLeeFuncPtr_glProgramUniform2uivEXT=GLee_Lazy_glProgramUniform2uivEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform3uivEXT +#define GLEE_C_DEFINED_glProgramUniform3uivEXT + void __stdcall GLee_Lazy_glProgramUniform3uivEXT(GLuint program, GLint location, GLsizei count, const GLuint * value) {if (GLeeInit()) glProgramUniform3uivEXT(program, location, count, value);} + GLEEPFNGLPROGRAMUNIFORM3UIVEXTPROC GLeeFuncPtr_glProgramUniform3uivEXT=GLee_Lazy_glProgramUniform3uivEXT; +#endif +#ifndef GLEE_C_DEFINED_glProgramUniform4uivEXT +#define GLEE_C_DEFINED_glProgramUniform4uivEXT + void __stdcall GLee_Lazy_glProgramUniform4uivEXT(GLuint program, GLint location, GLsizei count, const GLuint * value) {if (GLeeInit()) glProgramUniform4uivEXT(program, location, count, value);} + GLEEPFNGLPROGRAMUNIFORM4UIVEXTPROC GLeeFuncPtr_glProgramUniform4uivEXT=GLee_Lazy_glProgramUniform4uivEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedBufferDataEXT +#define GLEE_C_DEFINED_glNamedBufferDataEXT + void __stdcall GLee_Lazy_glNamedBufferDataEXT(GLuint buffer, GLsizeiptr size, const GLvoid * data, GLenum usage) {if (GLeeInit()) glNamedBufferDataEXT(buffer, size, data, usage);} + GLEEPFNGLNAMEDBUFFERDATAEXTPROC GLeeFuncPtr_glNamedBufferDataEXT=GLee_Lazy_glNamedBufferDataEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedBufferSubDataEXT +#define GLEE_C_DEFINED_glNamedBufferSubDataEXT + void __stdcall GLee_Lazy_glNamedBufferSubDataEXT(GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid * data) {if (GLeeInit()) glNamedBufferSubDataEXT(buffer, offset, size, data);} + GLEEPFNGLNAMEDBUFFERSUBDATAEXTPROC GLeeFuncPtr_glNamedBufferSubDataEXT=GLee_Lazy_glNamedBufferSubDataEXT; +#endif +#ifndef GLEE_C_DEFINED_glMapNamedBufferEXT +#define GLEE_C_DEFINED_glMapNamedBufferEXT + GLvoid* __stdcall GLee_Lazy_glMapNamedBufferEXT(GLuint buffer, GLenum access) {if (GLeeInit()) return glMapNamedBufferEXT(buffer, access); return (GLvoid*)0;} + GLEEPFNGLMAPNAMEDBUFFEREXTPROC GLeeFuncPtr_glMapNamedBufferEXT=GLee_Lazy_glMapNamedBufferEXT; +#endif +#ifndef GLEE_C_DEFINED_glUnmapNamedBufferEXT +#define GLEE_C_DEFINED_glUnmapNamedBufferEXT + GLboolean __stdcall GLee_Lazy_glUnmapNamedBufferEXT(GLuint buffer) {if (GLeeInit()) return glUnmapNamedBufferEXT(buffer); return (GLboolean)0;} + GLEEPFNGLUNMAPNAMEDBUFFEREXTPROC GLeeFuncPtr_glUnmapNamedBufferEXT=GLee_Lazy_glUnmapNamedBufferEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetNamedBufferParameterivEXT +#define GLEE_C_DEFINED_glGetNamedBufferParameterivEXT + void __stdcall GLee_Lazy_glGetNamedBufferParameterivEXT(GLuint buffer, GLenum pname, GLint * params) {if (GLeeInit()) glGetNamedBufferParameterivEXT(buffer, pname, params);} + GLEEPFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC GLeeFuncPtr_glGetNamedBufferParameterivEXT=GLee_Lazy_glGetNamedBufferParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetNamedBufferPointervEXT +#define GLEE_C_DEFINED_glGetNamedBufferPointervEXT + void __stdcall GLee_Lazy_glGetNamedBufferPointervEXT(GLuint buffer, GLenum pname, GLvoid* * params) {if (GLeeInit()) glGetNamedBufferPointervEXT(buffer, pname, params);} + GLEEPFNGLGETNAMEDBUFFERPOINTERVEXTPROC GLeeFuncPtr_glGetNamedBufferPointervEXT=GLee_Lazy_glGetNamedBufferPointervEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetNamedBufferSubDataEXT +#define GLEE_C_DEFINED_glGetNamedBufferSubDataEXT + void __stdcall GLee_Lazy_glGetNamedBufferSubDataEXT(GLuint buffer, GLintptr offset, GLsizeiptr size, GLvoid * data) {if (GLeeInit()) glGetNamedBufferSubDataEXT(buffer, offset, size, data);} + GLEEPFNGLGETNAMEDBUFFERSUBDATAEXTPROC GLeeFuncPtr_glGetNamedBufferSubDataEXT=GLee_Lazy_glGetNamedBufferSubDataEXT; +#endif +#ifndef GLEE_C_DEFINED_glTextureBufferEXT +#define GLEE_C_DEFINED_glTextureBufferEXT + void __stdcall GLee_Lazy_glTextureBufferEXT(GLuint texture, GLenum target, GLenum internalformat, GLuint buffer) {if (GLeeInit()) glTextureBufferEXT(texture, target, internalformat, buffer);} + GLEEPFNGLTEXTUREBUFFEREXTPROC GLeeFuncPtr_glTextureBufferEXT=GLee_Lazy_glTextureBufferEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexBufferEXT +#define GLEE_C_DEFINED_glMultiTexBufferEXT + void __stdcall GLee_Lazy_glMultiTexBufferEXT(GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer) {if (GLeeInit()) glMultiTexBufferEXT(texunit, target, internalformat, buffer);} + GLEEPFNGLMULTITEXBUFFEREXTPROC GLeeFuncPtr_glMultiTexBufferEXT=GLee_Lazy_glMultiTexBufferEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedRenderbufferStorageEXT +#define GLEE_C_DEFINED_glNamedRenderbufferStorageEXT + void __stdcall GLee_Lazy_glNamedRenderbufferStorageEXT(GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height) {if (GLeeInit()) glNamedRenderbufferStorageEXT(renderbuffer, internalformat, width, height);} + GLEEPFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC GLeeFuncPtr_glNamedRenderbufferStorageEXT=GLee_Lazy_glNamedRenderbufferStorageEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetNamedRenderbufferParameterivEXT +#define GLEE_C_DEFINED_glGetNamedRenderbufferParameterivEXT + void __stdcall GLee_Lazy_glGetNamedRenderbufferParameterivEXT(GLuint renderbuffer, GLenum pname, GLint * params) {if (GLeeInit()) glGetNamedRenderbufferParameterivEXT(renderbuffer, pname, params);} + GLEEPFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC GLeeFuncPtr_glGetNamedRenderbufferParameterivEXT=GLee_Lazy_glGetNamedRenderbufferParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glCheckNamedFramebufferStatusEXT +#define GLEE_C_DEFINED_glCheckNamedFramebufferStatusEXT + GLenum __stdcall GLee_Lazy_glCheckNamedFramebufferStatusEXT(GLuint framebuffer, GLenum target) {if (GLeeInit()) return glCheckNamedFramebufferStatusEXT(framebuffer, target); return (GLenum)0;} + GLEEPFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC GLeeFuncPtr_glCheckNamedFramebufferStatusEXT=GLee_Lazy_glCheckNamedFramebufferStatusEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedFramebufferTexture1DEXT +#define GLEE_C_DEFINED_glNamedFramebufferTexture1DEXT + void __stdcall GLee_Lazy_glNamedFramebufferTexture1DEXT(GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {if (GLeeInit()) glNamedFramebufferTexture1DEXT(framebuffer, attachment, textarget, texture, level);} + GLEEPFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC GLeeFuncPtr_glNamedFramebufferTexture1DEXT=GLee_Lazy_glNamedFramebufferTexture1DEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedFramebufferTexture2DEXT +#define GLEE_C_DEFINED_glNamedFramebufferTexture2DEXT + void __stdcall GLee_Lazy_glNamedFramebufferTexture2DEXT(GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {if (GLeeInit()) glNamedFramebufferTexture2DEXT(framebuffer, attachment, textarget, texture, level);} + GLEEPFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC GLeeFuncPtr_glNamedFramebufferTexture2DEXT=GLee_Lazy_glNamedFramebufferTexture2DEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedFramebufferTexture3DEXT +#define GLEE_C_DEFINED_glNamedFramebufferTexture3DEXT + void __stdcall GLee_Lazy_glNamedFramebufferTexture3DEXT(GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) {if (GLeeInit()) glNamedFramebufferTexture3DEXT(framebuffer, attachment, textarget, texture, level, zoffset);} + GLEEPFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC GLeeFuncPtr_glNamedFramebufferTexture3DEXT=GLee_Lazy_glNamedFramebufferTexture3DEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedFramebufferRenderbufferEXT +#define GLEE_C_DEFINED_glNamedFramebufferRenderbufferEXT + void __stdcall GLee_Lazy_glNamedFramebufferRenderbufferEXT(GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {if (GLeeInit()) glNamedFramebufferRenderbufferEXT(framebuffer, attachment, renderbuffertarget, renderbuffer);} + GLEEPFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC GLeeFuncPtr_glNamedFramebufferRenderbufferEXT=GLee_Lazy_glNamedFramebufferRenderbufferEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetNamedFramebufferAttachmentParameterivEXT +#define GLEE_C_DEFINED_glGetNamedFramebufferAttachmentParameterivEXT + void __stdcall GLee_Lazy_glGetNamedFramebufferAttachmentParameterivEXT(GLuint framebuffer, GLenum attachment, GLenum pname, GLint * params) {if (GLeeInit()) glGetNamedFramebufferAttachmentParameterivEXT(framebuffer, attachment, pname, params);} + GLEEPFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC GLeeFuncPtr_glGetNamedFramebufferAttachmentParameterivEXT=GLee_Lazy_glGetNamedFramebufferAttachmentParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGenerateTextureMipmapEXT +#define GLEE_C_DEFINED_glGenerateTextureMipmapEXT + void __stdcall GLee_Lazy_glGenerateTextureMipmapEXT(GLuint texture, GLenum target) {if (GLeeInit()) glGenerateTextureMipmapEXT(texture, target);} + GLEEPFNGLGENERATETEXTUREMIPMAPEXTPROC GLeeFuncPtr_glGenerateTextureMipmapEXT=GLee_Lazy_glGenerateTextureMipmapEXT; +#endif +#ifndef GLEE_C_DEFINED_glGenerateMultiTexMipmapEXT +#define GLEE_C_DEFINED_glGenerateMultiTexMipmapEXT + void __stdcall GLee_Lazy_glGenerateMultiTexMipmapEXT(GLenum texunit, GLenum target) {if (GLeeInit()) glGenerateMultiTexMipmapEXT(texunit, target);} + GLEEPFNGLGENERATEMULTITEXMIPMAPEXTPROC GLeeFuncPtr_glGenerateMultiTexMipmapEXT=GLee_Lazy_glGenerateMultiTexMipmapEXT; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferDrawBufferEXT +#define GLEE_C_DEFINED_glFramebufferDrawBufferEXT + void __stdcall GLee_Lazy_glFramebufferDrawBufferEXT(GLuint framebuffer, GLenum mode) {if (GLeeInit()) glFramebufferDrawBufferEXT(framebuffer, mode);} + GLEEPFNGLFRAMEBUFFERDRAWBUFFEREXTPROC GLeeFuncPtr_glFramebufferDrawBufferEXT=GLee_Lazy_glFramebufferDrawBufferEXT; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferDrawBuffersEXT +#define GLEE_C_DEFINED_glFramebufferDrawBuffersEXT + void __stdcall GLee_Lazy_glFramebufferDrawBuffersEXT(GLuint framebuffer, GLsizei n, const GLenum * bufs) {if (GLeeInit()) glFramebufferDrawBuffersEXT(framebuffer, n, bufs);} + GLEEPFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC GLeeFuncPtr_glFramebufferDrawBuffersEXT=GLee_Lazy_glFramebufferDrawBuffersEXT; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferReadBufferEXT +#define GLEE_C_DEFINED_glFramebufferReadBufferEXT + void __stdcall GLee_Lazy_glFramebufferReadBufferEXT(GLuint framebuffer, GLenum mode) {if (GLeeInit()) glFramebufferReadBufferEXT(framebuffer, mode);} + GLEEPFNGLFRAMEBUFFERREADBUFFEREXTPROC GLeeFuncPtr_glFramebufferReadBufferEXT=GLee_Lazy_glFramebufferReadBufferEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetFramebufferParameterivEXT +#define GLEE_C_DEFINED_glGetFramebufferParameterivEXT + void __stdcall GLee_Lazy_glGetFramebufferParameterivEXT(GLuint framebuffer, GLenum pname, GLint * params) {if (GLeeInit()) glGetFramebufferParameterivEXT(framebuffer, pname, params);} + GLEEPFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC GLeeFuncPtr_glGetFramebufferParameterivEXT=GLee_Lazy_glGetFramebufferParameterivEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedRenderbufferStorageMultisampleEXT +#define GLEE_C_DEFINED_glNamedRenderbufferStorageMultisampleEXT + void __stdcall GLee_Lazy_glNamedRenderbufferStorageMultisampleEXT(GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {if (GLeeInit()) glNamedRenderbufferStorageMultisampleEXT(renderbuffer, samples, internalformat, width, height);} + GLEEPFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC GLeeFuncPtr_glNamedRenderbufferStorageMultisampleEXT=GLee_Lazy_glNamedRenderbufferStorageMultisampleEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedRenderbufferStorageMultisampleCoverageEXT +#define GLEE_C_DEFINED_glNamedRenderbufferStorageMultisampleCoverageEXT + void __stdcall GLee_Lazy_glNamedRenderbufferStorageMultisampleCoverageEXT(GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height) {if (GLeeInit()) glNamedRenderbufferStorageMultisampleCoverageEXT(renderbuffer, coverageSamples, colorSamples, internalformat, width, height);} + GLEEPFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC GLeeFuncPtr_glNamedRenderbufferStorageMultisampleCoverageEXT=GLee_Lazy_glNamedRenderbufferStorageMultisampleCoverageEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedFramebufferTextureEXT +#define GLEE_C_DEFINED_glNamedFramebufferTextureEXT + void __stdcall GLee_Lazy_glNamedFramebufferTextureEXT(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level) {if (GLeeInit()) glNamedFramebufferTextureEXT(framebuffer, attachment, texture, level);} + GLEEPFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC GLeeFuncPtr_glNamedFramebufferTextureEXT=GLee_Lazy_glNamedFramebufferTextureEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedFramebufferTextureLayerEXT +#define GLEE_C_DEFINED_glNamedFramebufferTextureLayerEXT + void __stdcall GLee_Lazy_glNamedFramebufferTextureLayerEXT(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer) {if (GLeeInit()) glNamedFramebufferTextureLayerEXT(framebuffer, attachment, texture, level, layer);} + GLEEPFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC GLeeFuncPtr_glNamedFramebufferTextureLayerEXT=GLee_Lazy_glNamedFramebufferTextureLayerEXT; +#endif +#ifndef GLEE_C_DEFINED_glNamedFramebufferTextureFaceEXT +#define GLEE_C_DEFINED_glNamedFramebufferTextureFaceEXT + void __stdcall GLee_Lazy_glNamedFramebufferTextureFaceEXT(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face) {if (GLeeInit()) glNamedFramebufferTextureFaceEXT(framebuffer, attachment, texture, level, face);} + GLEEPFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC GLeeFuncPtr_glNamedFramebufferTextureFaceEXT=GLee_Lazy_glNamedFramebufferTextureFaceEXT; +#endif +#ifndef GLEE_C_DEFINED_glTextureRenderbufferEXT +#define GLEE_C_DEFINED_glTextureRenderbufferEXT + void __stdcall GLee_Lazy_glTextureRenderbufferEXT(GLuint texture, GLenum target, GLuint renderbuffer) {if (GLeeInit()) glTextureRenderbufferEXT(texture, target, renderbuffer);} + GLEEPFNGLTEXTURERENDERBUFFEREXTPROC GLeeFuncPtr_glTextureRenderbufferEXT=GLee_Lazy_glTextureRenderbufferEXT; +#endif +#ifndef GLEE_C_DEFINED_glMultiTexRenderbufferEXT +#define GLEE_C_DEFINED_glMultiTexRenderbufferEXT + void __stdcall GLee_Lazy_glMultiTexRenderbufferEXT(GLenum texunit, GLenum target, GLuint renderbuffer) {if (GLeeInit()) glMultiTexRenderbufferEXT(texunit, target, renderbuffer);} + GLEEPFNGLMULTITEXRENDERBUFFEREXTPROC GLeeFuncPtr_glMultiTexRenderbufferEXT=GLee_Lazy_glMultiTexRenderbufferEXT; +#endif +#endif + +/* GL_EXT_vertex_array_bgra */ + +#ifdef __GLEE_GL_EXT_vertex_array_bgra +#endif + +/* GL_EXT_texture_swizzle */ + +#ifdef __GLEE_GL_EXT_texture_swizzle +#endif + +/* GL_NV_explicit_multisample */ + +#ifdef __GLEE_GL_NV_explicit_multisample +#ifndef GLEE_C_DEFINED_glGetMultisamplefvNV +#define GLEE_C_DEFINED_glGetMultisamplefvNV + void __stdcall GLee_Lazy_glGetMultisamplefvNV(GLenum pname, GLuint index, GLfloat * val) {if (GLeeInit()) glGetMultisamplefvNV(pname, index, val);} + GLEEPFNGLGETMULTISAMPLEFVNVPROC GLeeFuncPtr_glGetMultisamplefvNV=GLee_Lazy_glGetMultisamplefvNV; +#endif +#ifndef GLEE_C_DEFINED_glSampleMaskIndexedNV +#define GLEE_C_DEFINED_glSampleMaskIndexedNV + void __stdcall GLee_Lazy_glSampleMaskIndexedNV(GLuint index, GLbitfield mask) {if (GLeeInit()) glSampleMaskIndexedNV(index, mask);} + GLEEPFNGLSAMPLEMASKINDEXEDNVPROC GLeeFuncPtr_glSampleMaskIndexedNV=GLee_Lazy_glSampleMaskIndexedNV; +#endif +#ifndef GLEE_C_DEFINED_glTexRenderbufferNV +#define GLEE_C_DEFINED_glTexRenderbufferNV + void __stdcall GLee_Lazy_glTexRenderbufferNV(GLenum target, GLuint renderbuffer) {if (GLeeInit()) glTexRenderbufferNV(target, renderbuffer);} + GLEEPFNGLTEXRENDERBUFFERNVPROC GLeeFuncPtr_glTexRenderbufferNV=GLee_Lazy_glTexRenderbufferNV; +#endif +#endif + +/* GL_NV_transform_feedback2 */ + +#ifdef __GLEE_GL_NV_transform_feedback2 +#ifndef GLEE_C_DEFINED_glBindTransformFeedbackNV +#define GLEE_C_DEFINED_glBindTransformFeedbackNV + void __stdcall GLee_Lazy_glBindTransformFeedbackNV(GLenum target, GLuint id) {if (GLeeInit()) glBindTransformFeedbackNV(target, id);} + GLEEPFNGLBINDTRANSFORMFEEDBACKNVPROC GLeeFuncPtr_glBindTransformFeedbackNV=GLee_Lazy_glBindTransformFeedbackNV; +#endif +#ifndef GLEE_C_DEFINED_glDeleteTransformFeedbacksNV +#define GLEE_C_DEFINED_glDeleteTransformFeedbacksNV + void __stdcall GLee_Lazy_glDeleteTransformFeedbacksNV(GLsizei n, const GLuint * ids) {if (GLeeInit()) glDeleteTransformFeedbacksNV(n, ids);} + GLEEPFNGLDELETETRANSFORMFEEDBACKSNVPROC GLeeFuncPtr_glDeleteTransformFeedbacksNV=GLee_Lazy_glDeleteTransformFeedbacksNV; +#endif +#ifndef GLEE_C_DEFINED_glGenTransformFeedbacksNV +#define GLEE_C_DEFINED_glGenTransformFeedbacksNV + void __stdcall GLee_Lazy_glGenTransformFeedbacksNV(GLsizei n, GLuint * ids) {if (GLeeInit()) glGenTransformFeedbacksNV(n, ids);} + GLEEPFNGLGENTRANSFORMFEEDBACKSNVPROC GLeeFuncPtr_glGenTransformFeedbacksNV=GLee_Lazy_glGenTransformFeedbacksNV; +#endif +#ifndef GLEE_C_DEFINED_glIsTransformFeedbackNV +#define GLEE_C_DEFINED_glIsTransformFeedbackNV + GLboolean __stdcall GLee_Lazy_glIsTransformFeedbackNV(GLuint id) {if (GLeeInit()) return glIsTransformFeedbackNV(id); return (GLboolean)0;} + GLEEPFNGLISTRANSFORMFEEDBACKNVPROC GLeeFuncPtr_glIsTransformFeedbackNV=GLee_Lazy_glIsTransformFeedbackNV; +#endif +#ifndef GLEE_C_DEFINED_glPauseTransformFeedbackNV +#define GLEE_C_DEFINED_glPauseTransformFeedbackNV + void __stdcall GLee_Lazy_glPauseTransformFeedbackNV(void) {if (GLeeInit()) glPauseTransformFeedbackNV();} + GLEEPFNGLPAUSETRANSFORMFEEDBACKNVPROC GLeeFuncPtr_glPauseTransformFeedbackNV=GLee_Lazy_glPauseTransformFeedbackNV; +#endif +#ifndef GLEE_C_DEFINED_glResumeTransformFeedbackNV +#define GLEE_C_DEFINED_glResumeTransformFeedbackNV + void __stdcall GLee_Lazy_glResumeTransformFeedbackNV(void) {if (GLeeInit()) glResumeTransformFeedbackNV();} + GLEEPFNGLRESUMETRANSFORMFEEDBACKNVPROC GLeeFuncPtr_glResumeTransformFeedbackNV=GLee_Lazy_glResumeTransformFeedbackNV; +#endif +#ifndef GLEE_C_DEFINED_glDrawTransformFeedbackNV +#define GLEE_C_DEFINED_glDrawTransformFeedbackNV + void __stdcall GLee_Lazy_glDrawTransformFeedbackNV(GLenum mode, GLuint id) {if (GLeeInit()) glDrawTransformFeedbackNV(mode, id);} + GLEEPFNGLDRAWTRANSFORMFEEDBACKNVPROC GLeeFuncPtr_glDrawTransformFeedbackNV=GLee_Lazy_glDrawTransformFeedbackNV; +#endif +#endif + +/* GL_SGIX_texture_select */ + +#ifdef __GLEE_GL_SGIX_texture_select +#endif + +/* GL_INGR_blend_func_separate */ + +#ifdef __GLEE_GL_INGR_blend_func_separate +#ifndef GLEE_C_DEFINED_glBlendFuncSeparateINGR +#define GLEE_C_DEFINED_glBlendFuncSeparateINGR + void __stdcall GLee_Lazy_glBlendFuncSeparateINGR(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) {if (GLeeInit()) glBlendFuncSeparateINGR(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);} + GLEEPFNGLBLENDFUNCSEPARATEINGRPROC GLeeFuncPtr_glBlendFuncSeparateINGR=GLee_Lazy_glBlendFuncSeparateINGR; +#endif +#endif + +/* GL_SGIX_depth_pass_instrument */ + +#ifdef __GLEE_GL_SGIX_depth_pass_instrument +#endif + +/* GL_SGIX_igloo_interface */ + +#ifdef __GLEE_GL_SGIX_igloo_interface +#ifndef GLEE_C_DEFINED_glIglooInterfaceSGIX +#define GLEE_C_DEFINED_glIglooInterfaceSGIX + void __stdcall GLee_Lazy_glIglooInterfaceSGIX(GLenum pname, const GLvoid * params) {if (GLeeInit()) glIglooInterfaceSGIX(pname, params);} + GLEEPFNGLIGLOOINTERFACESGIXPROC GLeeFuncPtr_glIglooInterfaceSGIX=GLee_Lazy_glIglooInterfaceSGIX; +#endif +#endif + +/* GL_EXT_fragment_lighting */ + +#ifdef __GLEE_GL_EXT_fragment_lighting +#ifndef GLEE_C_DEFINED_glFragmentLightModeliEXT +#define GLEE_C_DEFINED_glFragmentLightModeliEXT + GLvoid __stdcall GLee_Lazy_glFragmentLightModeliEXT(GLenum pname, GLint param) {if (GLeeInit()) glFragmentLightModeliEXT(pname, param);} + GLEEPFNGLFRAGMENTLIGHTMODELIEXTPROC GLeeFuncPtr_glFragmentLightModeliEXT=GLee_Lazy_glFragmentLightModeliEXT; +#endif +#ifndef GLEE_C_DEFINED_glFragmentLightModelfEXT +#define GLEE_C_DEFINED_glFragmentLightModelfEXT + GLvoid __stdcall GLee_Lazy_glFragmentLightModelfEXT(GLenum pname, GLfloat param) {if (GLeeInit()) glFragmentLightModelfEXT(pname, param);} + GLEEPFNGLFRAGMENTLIGHTMODELFEXTPROC GLeeFuncPtr_glFragmentLightModelfEXT=GLee_Lazy_glFragmentLightModelfEXT; +#endif +#ifndef GLEE_C_DEFINED_glFragmentLightModelivEXT +#define GLEE_C_DEFINED_glFragmentLightModelivEXT + GLvoid __stdcall GLee_Lazy_glFragmentLightModelivEXT(GLenum pname, GLint * params) {if (GLeeInit()) glFragmentLightModelivEXT(pname, params);} + GLEEPFNGLFRAGMENTLIGHTMODELIVEXTPROC GLeeFuncPtr_glFragmentLightModelivEXT=GLee_Lazy_glFragmentLightModelivEXT; +#endif +#ifndef GLEE_C_DEFINED_glFragmentLightModelfvEXT +#define GLEE_C_DEFINED_glFragmentLightModelfvEXT + GLvoid __stdcall GLee_Lazy_glFragmentLightModelfvEXT(GLenum pname, GLfloat * params) {if (GLeeInit()) glFragmentLightModelfvEXT(pname, params);} + GLEEPFNGLFRAGMENTLIGHTMODELFVEXTPROC GLeeFuncPtr_glFragmentLightModelfvEXT=GLee_Lazy_glFragmentLightModelfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glFragmentLightiEXT +#define GLEE_C_DEFINED_glFragmentLightiEXT + GLvoid __stdcall GLee_Lazy_glFragmentLightiEXT(GLenum light, GLenum pname, GLint param) {if (GLeeInit()) glFragmentLightiEXT(light, pname, param);} + GLEEPFNGLFRAGMENTLIGHTIEXTPROC GLeeFuncPtr_glFragmentLightiEXT=GLee_Lazy_glFragmentLightiEXT; +#endif +#ifndef GLEE_C_DEFINED_glFragmentLightfEXT +#define GLEE_C_DEFINED_glFragmentLightfEXT + GLvoid __stdcall GLee_Lazy_glFragmentLightfEXT(GLenum light, GLenum pname, GLfloat param) {if (GLeeInit()) glFragmentLightfEXT(light, pname, param);} + GLEEPFNGLFRAGMENTLIGHTFEXTPROC GLeeFuncPtr_glFragmentLightfEXT=GLee_Lazy_glFragmentLightfEXT; +#endif +#ifndef GLEE_C_DEFINED_glFragmentLightivEXT +#define GLEE_C_DEFINED_glFragmentLightivEXT + GLvoid __stdcall GLee_Lazy_glFragmentLightivEXT(GLenum light, GLenum pname, GLint * params) {if (GLeeInit()) glFragmentLightivEXT(light, pname, params);} + GLEEPFNGLFRAGMENTLIGHTIVEXTPROC GLeeFuncPtr_glFragmentLightivEXT=GLee_Lazy_glFragmentLightivEXT; +#endif +#ifndef GLEE_C_DEFINED_glFragmentLightfvEXT +#define GLEE_C_DEFINED_glFragmentLightfvEXT + GLvoid __stdcall GLee_Lazy_glFragmentLightfvEXT(GLenum light, GLenum pname, GLfloat * params) {if (GLeeInit()) glFragmentLightfvEXT(light, pname, params);} + GLEEPFNGLFRAGMENTLIGHTFVEXTPROC GLeeFuncPtr_glFragmentLightfvEXT=GLee_Lazy_glFragmentLightfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetFragmentLightivEXT +#define GLEE_C_DEFINED_glGetFragmentLightivEXT + GLvoid __stdcall GLee_Lazy_glGetFragmentLightivEXT(GLenum light, GLenum pname, GLint * params) {if (GLeeInit()) glGetFragmentLightivEXT(light, pname, params);} + GLEEPFNGLGETFRAGMENTLIGHTIVEXTPROC GLeeFuncPtr_glGetFragmentLightivEXT=GLee_Lazy_glGetFragmentLightivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetFragmentLightfvEXT +#define GLEE_C_DEFINED_glGetFragmentLightfvEXT + GLvoid __stdcall GLee_Lazy_glGetFragmentLightfvEXT(GLenum light, GLenum pname, GLfloat * params) {if (GLeeInit()) glGetFragmentLightfvEXT(light, pname, params);} + GLEEPFNGLGETFRAGMENTLIGHTFVEXTPROC GLeeFuncPtr_glGetFragmentLightfvEXT=GLee_Lazy_glGetFragmentLightfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glFragmentMaterialfEXT +#define GLEE_C_DEFINED_glFragmentMaterialfEXT + GLvoid __stdcall GLee_Lazy_glFragmentMaterialfEXT(GLenum face, GLenum pname, const GLfloat param) {if (GLeeInit()) glFragmentMaterialfEXT(face, pname, param);} + GLEEPFNGLFRAGMENTMATERIALFEXTPROC GLeeFuncPtr_glFragmentMaterialfEXT=GLee_Lazy_glFragmentMaterialfEXT; +#endif +#ifndef GLEE_C_DEFINED_glFragmentMaterialiEXT +#define GLEE_C_DEFINED_glFragmentMaterialiEXT + GLvoid __stdcall GLee_Lazy_glFragmentMaterialiEXT(GLenum face, GLenum pname, const GLint param) {if (GLeeInit()) glFragmentMaterialiEXT(face, pname, param);} + GLEEPFNGLFRAGMENTMATERIALIEXTPROC GLeeFuncPtr_glFragmentMaterialiEXT=GLee_Lazy_glFragmentMaterialiEXT; +#endif +#ifndef GLEE_C_DEFINED_glFragmentMaterialfvEXT +#define GLEE_C_DEFINED_glFragmentMaterialfvEXT + GLvoid __stdcall GLee_Lazy_glFragmentMaterialfvEXT(GLenum face, GLenum pname, const GLfloat * params) {if (GLeeInit()) glFragmentMaterialfvEXT(face, pname, params);} + GLEEPFNGLFRAGMENTMATERIALFVEXTPROC GLeeFuncPtr_glFragmentMaterialfvEXT=GLee_Lazy_glFragmentMaterialfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glFragmentMaterialivEXT +#define GLEE_C_DEFINED_glFragmentMaterialivEXT + GLvoid __stdcall GLee_Lazy_glFragmentMaterialivEXT(GLenum face, GLenum pname, const GLint * params) {if (GLeeInit()) glFragmentMaterialivEXT(face, pname, params);} + GLEEPFNGLFRAGMENTMATERIALIVEXTPROC GLeeFuncPtr_glFragmentMaterialivEXT=GLee_Lazy_glFragmentMaterialivEXT; +#endif +#ifndef GLEE_C_DEFINED_glFragmentColorMaterialEXT +#define GLEE_C_DEFINED_glFragmentColorMaterialEXT + GLvoid __stdcall GLee_Lazy_glFragmentColorMaterialEXT(GLenum face, GLenum mode) {if (GLeeInit()) glFragmentColorMaterialEXT(face, mode);} + GLEEPFNGLFRAGMENTCOLORMATERIALEXTPROC GLeeFuncPtr_glFragmentColorMaterialEXT=GLee_Lazy_glFragmentColorMaterialEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetFragmentMaterialfvEXT +#define GLEE_C_DEFINED_glGetFragmentMaterialfvEXT + GLvoid __stdcall GLee_Lazy_glGetFragmentMaterialfvEXT(GLenum face, GLenum pname, const GLfloat * params) {if (GLeeInit()) glGetFragmentMaterialfvEXT(face, pname, params);} + GLEEPFNGLGETFRAGMENTMATERIALFVEXTPROC GLeeFuncPtr_glGetFragmentMaterialfvEXT=GLee_Lazy_glGetFragmentMaterialfvEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetFragmentMaterialivEXT +#define GLEE_C_DEFINED_glGetFragmentMaterialivEXT + GLvoid __stdcall GLee_Lazy_glGetFragmentMaterialivEXT(GLenum face, GLenum pname, const GLint * params) {if (GLeeInit()) glGetFragmentMaterialivEXT(face, pname, params);} + GLEEPFNGLGETFRAGMENTMATERIALIVEXTPROC GLeeFuncPtr_glGetFragmentMaterialivEXT=GLee_Lazy_glGetFragmentMaterialivEXT; +#endif +#ifndef GLEE_C_DEFINED_glLightEnviEXT +#define GLEE_C_DEFINED_glLightEnviEXT + GLvoid __stdcall GLee_Lazy_glLightEnviEXT(GLenum pname, GLint param) {if (GLeeInit()) glLightEnviEXT(pname, param);} + GLEEPFNGLLIGHTENVIEXTPROC GLeeFuncPtr_glLightEnviEXT=GLee_Lazy_glLightEnviEXT; +#endif +#endif + +/* GL_EXT_geometry_shader4 */ + +#ifdef __GLEE_GL_EXT_geometry_shader4 +#ifndef GLEE_C_DEFINED_glProgramParameteriEXT +#define GLEE_C_DEFINED_glProgramParameteriEXT + GLvoid __stdcall GLee_Lazy_glProgramParameteriEXT(GLuint program, GLenum pname, GLint value) {if (GLeeInit()) glProgramParameteriEXT(program, pname, value);} + GLEEPFNGLPROGRAMPARAMETERIEXTPROC GLeeFuncPtr_glProgramParameteriEXT=GLee_Lazy_glProgramParameteriEXT; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferTextureEXT +#define GLEE_C_DEFINED_glFramebufferTextureEXT + GLvoid __stdcall GLee_Lazy_glFramebufferTextureEXT(GLenum target, GLenum attachment, GLuint texture, GLint level) {if (GLeeInit()) glFramebufferTextureEXT(target, attachment, texture, level);} + GLEEPFNGLFRAMEBUFFERTEXTUREEXTPROC GLeeFuncPtr_glFramebufferTextureEXT=GLee_Lazy_glFramebufferTextureEXT; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferTextureLayerEXT +#define GLEE_C_DEFINED_glFramebufferTextureLayerEXT + GLvoid __stdcall GLee_Lazy_glFramebufferTextureLayerEXT(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {if (GLeeInit()) glFramebufferTextureLayerEXT(target, attachment, texture, level, layer);} + GLEEPFNGLFRAMEBUFFERTEXTURELAYEREXTPROC GLeeFuncPtr_glFramebufferTextureLayerEXT=GLee_Lazy_glFramebufferTextureLayerEXT; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferTextureFaceEXT +#define GLEE_C_DEFINED_glFramebufferTextureFaceEXT + GLvoid __stdcall GLee_Lazy_glFramebufferTextureFaceEXT(GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face) {if (GLeeInit()) glFramebufferTextureFaceEXT(target, attachment, texture, level, face);} + GLEEPFNGLFRAMEBUFFERTEXTUREFACEEXTPROC GLeeFuncPtr_glFramebufferTextureFaceEXT=GLee_Lazy_glFramebufferTextureFaceEXT; +#endif +#endif + +/* GL_EXT_scene_marker */ + +#ifdef __GLEE_GL_EXT_scene_marker +#ifndef GLEE_C_DEFINED_glBeginSceneEXT +#define GLEE_C_DEFINED_glBeginSceneEXT + GLvoid __stdcall GLee_Lazy_glBeginSceneEXT(void) {if (GLeeInit()) glBeginSceneEXT();} + GLEEPFNGLBEGINSCENEEXTPROC GLeeFuncPtr_glBeginSceneEXT=GLee_Lazy_glBeginSceneEXT; +#endif +#ifndef GLEE_C_DEFINED_glEndSceneEXT +#define GLEE_C_DEFINED_glEndSceneEXT + GLvoid __stdcall GLee_Lazy_glEndSceneEXT(void) {if (GLeeInit()) glEndSceneEXT();} + GLEEPFNGLENDSCENEEXTPROC GLeeFuncPtr_glEndSceneEXT=GLee_Lazy_glEndSceneEXT; +#endif +#endif + +/* GL_EXT_texture_compression_dxt1 */ + +#ifdef __GLEE_GL_EXT_texture_compression_dxt1 +#endif + +/* GL_EXT_texture_env */ + +#ifdef __GLEE_GL_EXT_texture_env +#endif + +/* GL_IBM_static_data */ + +#ifdef __GLEE_GL_IBM_static_data +#endif + +/* GL_NV_gpu_program4 */ + +#ifdef __GLEE_GL_NV_gpu_program4 +#ifndef GLEE_C_DEFINED_glProgramLocalParameterI4iNV +#define GLEE_C_DEFINED_glProgramLocalParameterI4iNV + GLvoid __stdcall GLee_Lazy_glProgramLocalParameterI4iNV(GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w) {if (GLeeInit()) glProgramLocalParameterI4iNV(target, index, x, y, z, w);} + GLEEPFNGLPROGRAMLOCALPARAMETERI4INVPROC GLeeFuncPtr_glProgramLocalParameterI4iNV=GLee_Lazy_glProgramLocalParameterI4iNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramLocalParameterI4ivNV +#define GLEE_C_DEFINED_glProgramLocalParameterI4ivNV + GLvoid __stdcall GLee_Lazy_glProgramLocalParameterI4ivNV(GLenum target, GLuint index, const GLint * params) {if (GLeeInit()) glProgramLocalParameterI4ivNV(target, index, params);} + GLEEPFNGLPROGRAMLOCALPARAMETERI4IVNVPROC GLeeFuncPtr_glProgramLocalParameterI4ivNV=GLee_Lazy_glProgramLocalParameterI4ivNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramLocalParametersI4ivNV +#define GLEE_C_DEFINED_glProgramLocalParametersI4ivNV + GLvoid __stdcall GLee_Lazy_glProgramLocalParametersI4ivNV(GLenum target, GLuint index, GLsizei count, const GLint * params) {if (GLeeInit()) glProgramLocalParametersI4ivNV(target, index, count, params);} + GLEEPFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC GLeeFuncPtr_glProgramLocalParametersI4ivNV=GLee_Lazy_glProgramLocalParametersI4ivNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramLocalParameterI4uiNV +#define GLEE_C_DEFINED_glProgramLocalParameterI4uiNV + GLvoid __stdcall GLee_Lazy_glProgramLocalParameterI4uiNV(GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) {if (GLeeInit()) glProgramLocalParameterI4uiNV(target, index, x, y, z, w);} + GLEEPFNGLPROGRAMLOCALPARAMETERI4UINVPROC GLeeFuncPtr_glProgramLocalParameterI4uiNV=GLee_Lazy_glProgramLocalParameterI4uiNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramLocalParameterI4uivNV +#define GLEE_C_DEFINED_glProgramLocalParameterI4uivNV + GLvoid __stdcall GLee_Lazy_glProgramLocalParameterI4uivNV(GLenum target, GLuint index, const GLuint * params) {if (GLeeInit()) glProgramLocalParameterI4uivNV(target, index, params);} + GLEEPFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC GLeeFuncPtr_glProgramLocalParameterI4uivNV=GLee_Lazy_glProgramLocalParameterI4uivNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramLocalParametersI4uivNV +#define GLEE_C_DEFINED_glProgramLocalParametersI4uivNV + GLvoid __stdcall GLee_Lazy_glProgramLocalParametersI4uivNV(GLenum target, GLuint index, GLsizei count, const GLuint * params) {if (GLeeInit()) glProgramLocalParametersI4uivNV(target, index, count, params);} + GLEEPFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC GLeeFuncPtr_glProgramLocalParametersI4uivNV=GLee_Lazy_glProgramLocalParametersI4uivNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramEnvParameterI4iNV +#define GLEE_C_DEFINED_glProgramEnvParameterI4iNV + GLvoid __stdcall GLee_Lazy_glProgramEnvParameterI4iNV(GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w) {if (GLeeInit()) glProgramEnvParameterI4iNV(target, index, x, y, z, w);} + GLEEPFNGLPROGRAMENVPARAMETERI4INVPROC GLeeFuncPtr_glProgramEnvParameterI4iNV=GLee_Lazy_glProgramEnvParameterI4iNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramEnvParameterI4ivNV +#define GLEE_C_DEFINED_glProgramEnvParameterI4ivNV + GLvoid __stdcall GLee_Lazy_glProgramEnvParameterI4ivNV(GLenum target, GLuint index, const GLint * params) {if (GLeeInit()) glProgramEnvParameterI4ivNV(target, index, params);} + GLEEPFNGLPROGRAMENVPARAMETERI4IVNVPROC GLeeFuncPtr_glProgramEnvParameterI4ivNV=GLee_Lazy_glProgramEnvParameterI4ivNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramEnvParametersI4ivNV +#define GLEE_C_DEFINED_glProgramEnvParametersI4ivNV + GLvoid __stdcall GLee_Lazy_glProgramEnvParametersI4ivNV(GLenum target, GLuint index, GLsizei count, const GLint * params) {if (GLeeInit()) glProgramEnvParametersI4ivNV(target, index, count, params);} + GLEEPFNGLPROGRAMENVPARAMETERSI4IVNVPROC GLeeFuncPtr_glProgramEnvParametersI4ivNV=GLee_Lazy_glProgramEnvParametersI4ivNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramEnvParameterI4uiNV +#define GLEE_C_DEFINED_glProgramEnvParameterI4uiNV + GLvoid __stdcall GLee_Lazy_glProgramEnvParameterI4uiNV(GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) {if (GLeeInit()) glProgramEnvParameterI4uiNV(target, index, x, y, z, w);} + GLEEPFNGLPROGRAMENVPARAMETERI4UINVPROC GLeeFuncPtr_glProgramEnvParameterI4uiNV=GLee_Lazy_glProgramEnvParameterI4uiNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramEnvParameterI4uivNV +#define GLEE_C_DEFINED_glProgramEnvParameterI4uivNV + GLvoid __stdcall GLee_Lazy_glProgramEnvParameterI4uivNV(GLenum target, GLuint index, const GLuint * params) {if (GLeeInit()) glProgramEnvParameterI4uivNV(target, index, params);} + GLEEPFNGLPROGRAMENVPARAMETERI4UIVNVPROC GLeeFuncPtr_glProgramEnvParameterI4uivNV=GLee_Lazy_glProgramEnvParameterI4uivNV; +#endif +#ifndef GLEE_C_DEFINED_glProgramEnvParametersI4uivNV +#define GLEE_C_DEFINED_glProgramEnvParametersI4uivNV + GLvoid __stdcall GLee_Lazy_glProgramEnvParametersI4uivNV(GLenum target, GLuint index, GLsizei count, const GLuint * params) {if (GLeeInit()) glProgramEnvParametersI4uivNV(target, index, count, params);} + GLEEPFNGLPROGRAMENVPARAMETERSI4UIVNVPROC GLeeFuncPtr_glProgramEnvParametersI4uivNV=GLee_Lazy_glProgramEnvParametersI4uivNV; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramLocalParameterIivNV +#define GLEE_C_DEFINED_glGetProgramLocalParameterIivNV + GLvoid __stdcall GLee_Lazy_glGetProgramLocalParameterIivNV(GLenum target, GLuint index, GLint * params) {if (GLeeInit()) glGetProgramLocalParameterIivNV(target, index, params);} + GLEEPFNGLGETPROGRAMLOCALPARAMETERIIVNVPROC GLeeFuncPtr_glGetProgramLocalParameterIivNV=GLee_Lazy_glGetProgramLocalParameterIivNV; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramLocalParameterIuivNV +#define GLEE_C_DEFINED_glGetProgramLocalParameterIuivNV + GLvoid __stdcall GLee_Lazy_glGetProgramLocalParameterIuivNV(GLenum target, GLuint index, GLuint * params) {if (GLeeInit()) glGetProgramLocalParameterIuivNV(target, index, params);} + GLEEPFNGLGETPROGRAMLOCALPARAMETERIUIVNVPROC GLeeFuncPtr_glGetProgramLocalParameterIuivNV=GLee_Lazy_glGetProgramLocalParameterIuivNV; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramEnvParameterIivNV +#define GLEE_C_DEFINED_glGetProgramEnvParameterIivNV + GLvoid __stdcall GLee_Lazy_glGetProgramEnvParameterIivNV(GLenum target, GLuint index, GLint * params) {if (GLeeInit()) glGetProgramEnvParameterIivNV(target, index, params);} + GLEEPFNGLGETPROGRAMENVPARAMETERIIVNVPROC GLeeFuncPtr_glGetProgramEnvParameterIivNV=GLee_Lazy_glGetProgramEnvParameterIivNV; +#endif +#ifndef GLEE_C_DEFINED_glGetProgramEnvParameterIuivNV +#define GLEE_C_DEFINED_glGetProgramEnvParameterIuivNV + GLvoid __stdcall GLee_Lazy_glGetProgramEnvParameterIuivNV(GLenum target, GLuint index, GLuint * params) {if (GLeeInit()) glGetProgramEnvParameterIuivNV(target, index, params);} + GLEEPFNGLGETPROGRAMENVPARAMETERIUIVNVPROC GLeeFuncPtr_glGetProgramEnvParameterIuivNV=GLee_Lazy_glGetProgramEnvParameterIuivNV; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferTextureEXT +#define GLEE_C_DEFINED_glFramebufferTextureEXT + GLvoid __stdcall GLee_Lazy_glFramebufferTextureEXT(GLenum target, GLenum attachment, GLuint texture, GLint level) {if (GLeeInit()) glFramebufferTextureEXT(target, attachment, texture, level);} + GLEEPFNGLFRAMEBUFFERTEXTUREEXTPROC GLeeFuncPtr_glFramebufferTextureEXT=GLee_Lazy_glFramebufferTextureEXT; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferTextureLayerEXT +#define GLEE_C_DEFINED_glFramebufferTextureLayerEXT + GLvoid __stdcall GLee_Lazy_glFramebufferTextureLayerEXT(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {if (GLeeInit()) glFramebufferTextureLayerEXT(target, attachment, texture, level, layer);} + GLEEPFNGLFRAMEBUFFERTEXTURELAYEREXTPROC GLeeFuncPtr_glFramebufferTextureLayerEXT=GLee_Lazy_glFramebufferTextureLayerEXT; +#endif +#ifndef GLEE_C_DEFINED_glFramebufferTextureFaceEXT +#define GLEE_C_DEFINED_glFramebufferTextureFaceEXT + GLvoid __stdcall GLee_Lazy_glFramebufferTextureFaceEXT(GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face) {if (GLeeInit()) glFramebufferTextureFaceEXT(target, attachment, texture, level, face);} + GLEEPFNGLFRAMEBUFFERTEXTUREFACEEXTPROC GLeeFuncPtr_glFramebufferTextureFaceEXT=GLee_Lazy_glFramebufferTextureFaceEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI2iEXT +#define GLEE_C_DEFINED_glVertexAttribI2iEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI2iEXT(GLuint index, GLint x, GLint y) {if (GLeeInit()) glVertexAttribI2iEXT(index, x, y);} + GLEEPFNGLVERTEXATTRIBI2IEXTPROC GLeeFuncPtr_glVertexAttribI2iEXT=GLee_Lazy_glVertexAttribI2iEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI3iEXT +#define GLEE_C_DEFINED_glVertexAttribI3iEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI3iEXT(GLuint index, GLint x, GLint y, GLint z) {if (GLeeInit()) glVertexAttribI3iEXT(index, x, y, z);} + GLEEPFNGLVERTEXATTRIBI3IEXTPROC GLeeFuncPtr_glVertexAttribI3iEXT=GLee_Lazy_glVertexAttribI3iEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI4iEXT +#define GLEE_C_DEFINED_glVertexAttribI4iEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI4iEXT(GLuint index, GLint x, GLint y, GLint z, GLint w) {if (GLeeInit()) glVertexAttribI4iEXT(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIBI4IEXTPROC GLeeFuncPtr_glVertexAttribI4iEXT=GLee_Lazy_glVertexAttribI4iEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI1uiEXT +#define GLEE_C_DEFINED_glVertexAttribI1uiEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI1uiEXT(GLuint index, GLuint x) {if (GLeeInit()) glVertexAttribI1uiEXT(index, x);} + GLEEPFNGLVERTEXATTRIBI1UIEXTPROC GLeeFuncPtr_glVertexAttribI1uiEXT=GLee_Lazy_glVertexAttribI1uiEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI2uiEXT +#define GLEE_C_DEFINED_glVertexAttribI2uiEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI2uiEXT(GLuint index, GLuint x, GLuint y) {if (GLeeInit()) glVertexAttribI2uiEXT(index, x, y);} + GLEEPFNGLVERTEXATTRIBI2UIEXTPROC GLeeFuncPtr_glVertexAttribI2uiEXT=GLee_Lazy_glVertexAttribI2uiEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI3uiEXT +#define GLEE_C_DEFINED_glVertexAttribI3uiEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI3uiEXT(GLuint index, GLuint x, GLuint y, GLuint z) {if (GLeeInit()) glVertexAttribI3uiEXT(index, x, y, z);} + GLEEPFNGLVERTEXATTRIBI3UIEXTPROC GLeeFuncPtr_glVertexAttribI3uiEXT=GLee_Lazy_glVertexAttribI3uiEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI4uiEXT +#define GLEE_C_DEFINED_glVertexAttribI4uiEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI4uiEXT(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) {if (GLeeInit()) glVertexAttribI4uiEXT(index, x, y, z, w);} + GLEEPFNGLVERTEXATTRIBI4UIEXTPROC GLeeFuncPtr_glVertexAttribI4uiEXT=GLee_Lazy_glVertexAttribI4uiEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI1ivEXT +#define GLEE_C_DEFINED_glVertexAttribI1ivEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI1ivEXT(GLuint index, const GLint * v) {if (GLeeInit()) glVertexAttribI1ivEXT(index, v);} + GLEEPFNGLVERTEXATTRIBI1IVEXTPROC GLeeFuncPtr_glVertexAttribI1ivEXT=GLee_Lazy_glVertexAttribI1ivEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI2ivEXT +#define GLEE_C_DEFINED_glVertexAttribI2ivEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI2ivEXT(GLuint index, const GLint * v) {if (GLeeInit()) glVertexAttribI2ivEXT(index, v);} + GLEEPFNGLVERTEXATTRIBI2IVEXTPROC GLeeFuncPtr_glVertexAttribI2ivEXT=GLee_Lazy_glVertexAttribI2ivEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI3ivEXT +#define GLEE_C_DEFINED_glVertexAttribI3ivEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI3ivEXT(GLuint index, const GLint * v) {if (GLeeInit()) glVertexAttribI3ivEXT(index, v);} + GLEEPFNGLVERTEXATTRIBI3IVEXTPROC GLeeFuncPtr_glVertexAttribI3ivEXT=GLee_Lazy_glVertexAttribI3ivEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI4ivEXT +#define GLEE_C_DEFINED_glVertexAttribI4ivEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI4ivEXT(GLuint index, const GLint * v) {if (GLeeInit()) glVertexAttribI4ivEXT(index, v);} + GLEEPFNGLVERTEXATTRIBI4IVEXTPROC GLeeFuncPtr_glVertexAttribI4ivEXT=GLee_Lazy_glVertexAttribI4ivEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI1uivEXT +#define GLEE_C_DEFINED_glVertexAttribI1uivEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI1uivEXT(GLuint index, const GLuint * v) {if (GLeeInit()) glVertexAttribI1uivEXT(index, v);} + GLEEPFNGLVERTEXATTRIBI1UIVEXTPROC GLeeFuncPtr_glVertexAttribI1uivEXT=GLee_Lazy_glVertexAttribI1uivEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI2uivEXT +#define GLEE_C_DEFINED_glVertexAttribI2uivEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI2uivEXT(GLuint index, const GLuint * v) {if (GLeeInit()) glVertexAttribI2uivEXT(index, v);} + GLEEPFNGLVERTEXATTRIBI2UIVEXTPROC GLeeFuncPtr_glVertexAttribI2uivEXT=GLee_Lazy_glVertexAttribI2uivEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI3uivEXT +#define GLEE_C_DEFINED_glVertexAttribI3uivEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI3uivEXT(GLuint index, const GLuint * v) {if (GLeeInit()) glVertexAttribI3uivEXT(index, v);} + GLEEPFNGLVERTEXATTRIBI3UIVEXTPROC GLeeFuncPtr_glVertexAttribI3uivEXT=GLee_Lazy_glVertexAttribI3uivEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI4uivEXT +#define GLEE_C_DEFINED_glVertexAttribI4uivEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI4uivEXT(GLuint index, const GLuint * v) {if (GLeeInit()) glVertexAttribI4uivEXT(index, v);} + GLEEPFNGLVERTEXATTRIBI4UIVEXTPROC GLeeFuncPtr_glVertexAttribI4uivEXT=GLee_Lazy_glVertexAttribI4uivEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI4bvEXT +#define GLEE_C_DEFINED_glVertexAttribI4bvEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI4bvEXT(GLuint index, const GLbyte * v) {if (GLeeInit()) glVertexAttribI4bvEXT(index, v);} + GLEEPFNGLVERTEXATTRIBI4BVEXTPROC GLeeFuncPtr_glVertexAttribI4bvEXT=GLee_Lazy_glVertexAttribI4bvEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI4svEXT +#define GLEE_C_DEFINED_glVertexAttribI4svEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI4svEXT(GLuint index, const GLshort * v) {if (GLeeInit()) glVertexAttribI4svEXT(index, v);} + GLEEPFNGLVERTEXATTRIBI4SVEXTPROC GLeeFuncPtr_glVertexAttribI4svEXT=GLee_Lazy_glVertexAttribI4svEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI4ubvEXT +#define GLEE_C_DEFINED_glVertexAttribI4ubvEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI4ubvEXT(GLuint index, const GLubyte * v) {if (GLeeInit()) glVertexAttribI4ubvEXT(index, v);} + GLEEPFNGLVERTEXATTRIBI4UBVEXTPROC GLeeFuncPtr_glVertexAttribI4ubvEXT=GLee_Lazy_glVertexAttribI4ubvEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribI4usvEXT +#define GLEE_C_DEFINED_glVertexAttribI4usvEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribI4usvEXT(GLuint index, const GLushort * v) {if (GLeeInit()) glVertexAttribI4usvEXT(index, v);} + GLEEPFNGLVERTEXATTRIBI4USVEXTPROC GLeeFuncPtr_glVertexAttribI4usvEXT=GLee_Lazy_glVertexAttribI4usvEXT; +#endif +#ifndef GLEE_C_DEFINED_glVertexAttribIPointerEXT +#define GLEE_C_DEFINED_glVertexAttribIPointerEXT + GLvoid __stdcall GLee_Lazy_glVertexAttribIPointerEXT(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {if (GLeeInit()) glVertexAttribIPointerEXT(index, size, type, stride, pointer);} + GLEEPFNGLVERTEXATTRIBIPOINTEREXTPROC GLeeFuncPtr_glVertexAttribIPointerEXT=GLee_Lazy_glVertexAttribIPointerEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribIivEXT +#define GLEE_C_DEFINED_glGetVertexAttribIivEXT + GLvoid __stdcall GLee_Lazy_glGetVertexAttribIivEXT(GLuint index, GLenum pname, GLint * params) {if (GLeeInit()) glGetVertexAttribIivEXT(index, pname, params);} + GLEEPFNGLGETVERTEXATTRIBIIVEXTPROC GLeeFuncPtr_glGetVertexAttribIivEXT=GLee_Lazy_glGetVertexAttribIivEXT; +#endif +#ifndef GLEE_C_DEFINED_glGetVertexAttribIuivEXT +#define GLEE_C_DEFINED_glGetVertexAttribIuivEXT + GLvoid __stdcall GLee_Lazy_glGetVertexAttribIuivEXT(GLuint index, GLenum pname, GLuint * params) {if (GLeeInit()) glGetVertexAttribIuivEXT(index, pname, params);} + GLEEPFNGLGETVERTEXATTRIBIUIVEXTPROC GLeeFuncPtr_glGetVertexAttribIuivEXT=GLee_Lazy_glGetVertexAttribIuivEXT; +#endif +#endif + +/* GL_OES_byte_coordinates */ + +#ifdef __GLEE_GL_OES_byte_coordinates +#endif + +/* GL_OES_compressed_paletted_texture */ + +#ifdef __GLEE_GL_OES_compressed_paletted_texture +#endif + +/* GL_OES_single_precision */ + +#ifdef __GLEE_GL_OES_single_precision +#ifndef GLEE_C_DEFINED_glDepthRangefOES +#define GLEE_C_DEFINED_glDepthRangefOES + GLvoid __stdcall GLee_Lazy_glDepthRangefOES(GLclampf n, GLclampf f) {if (GLeeInit()) glDepthRangefOES(n, f);} + GLEEPFNGLDEPTHRANGEFOESPROC GLeeFuncPtr_glDepthRangefOES=GLee_Lazy_glDepthRangefOES; +#endif +#ifndef GLEE_C_DEFINED_glFrustumfOES +#define GLEE_C_DEFINED_glFrustumfOES + GLvoid __stdcall GLee_Lazy_glFrustumfOES(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) {if (GLeeInit()) glFrustumfOES(l, r, b, t, n, f);} + GLEEPFNGLFRUSTUMFOESPROC GLeeFuncPtr_glFrustumfOES=GLee_Lazy_glFrustumfOES; +#endif +#ifndef GLEE_C_DEFINED_glOrthofOES +#define GLEE_C_DEFINED_glOrthofOES + GLvoid __stdcall GLee_Lazy_glOrthofOES(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) {if (GLeeInit()) glOrthofOES(l, r, b, t, n, f);} + GLEEPFNGLORTHOFOESPROC GLeeFuncPtr_glOrthofOES=GLee_Lazy_glOrthofOES; +#endif +#ifndef GLEE_C_DEFINED_glClipPlanefOES +#define GLEE_C_DEFINED_glClipPlanefOES + GLvoid __stdcall GLee_Lazy_glClipPlanefOES(GLenum plane, const GLfloat* equation) {if (GLeeInit()) glClipPlanefOES(plane, equation);} + GLEEPFNGLCLIPPLANEFOESPROC GLeeFuncPtr_glClipPlanefOES=GLee_Lazy_glClipPlanefOES; +#endif +#ifndef GLEE_C_DEFINED_glGetClipPlanefOES +#define GLEE_C_DEFINED_glGetClipPlanefOES + GLvoid __stdcall GLee_Lazy_glGetClipPlanefOES(GLenum plane, GLfloat* equation) {if (GLeeInit()) glGetClipPlanefOES(plane, equation);} + GLEEPFNGLGETCLIPPLANEFOESPROC GLeeFuncPtr_glGetClipPlanefOES=GLee_Lazy_glGetClipPlanefOES; +#endif +#ifndef GLEE_C_DEFINED_glClearDepthfOES +#define GLEE_C_DEFINED_glClearDepthfOES + GLvoid __stdcall GLee_Lazy_glClearDepthfOES(GLclampd depth) {if (GLeeInit()) glClearDepthfOES(depth);} + GLEEPFNGLCLEARDEPTHFOESPROC GLeeFuncPtr_glClearDepthfOES=GLee_Lazy_glClearDepthfOES; +#endif +#endif + +/* GL_SGIX_pixel_texture_bits */ + +#ifdef __GLEE_GL_SGIX_pixel_texture_bits +#endif + +/* GL_SGIX_texture_range */ + +#ifdef __GLEE_GL_SGIX_texture_range +#endif + +/* WGL */ + +#ifdef WIN32 + +/* Extension querying variables */ + +GLboolean _GLEE_WGL_ARB_buffer_region = GL_FALSE; +GLboolean _GLEE_WGL_ARB_multisample = GL_FALSE; +GLboolean _GLEE_WGL_ARB_extensions_string = GL_FALSE; +GLboolean _GLEE_WGL_ARB_pixel_format = GL_FALSE; +GLboolean _GLEE_WGL_ARB_make_current_read = GL_FALSE; +GLboolean _GLEE_WGL_ARB_pbuffer = GL_FALSE; +GLboolean _GLEE_WGL_ARB_render_texture = GL_FALSE; +GLboolean _GLEE_WGL_ARB_pixel_format_float = GL_FALSE; +GLboolean _GLEE_WGL_ARB_create_context = GL_FALSE; +GLboolean _GLEE_WGL_EXT_make_current_read = GL_FALSE; +GLboolean _GLEE_WGL_EXT_pixel_format = GL_FALSE; +GLboolean _GLEE_WGL_EXT_pbuffer = GL_FALSE; +GLboolean _GLEE_WGL_EXT_depth_float = GL_FALSE; +GLboolean _GLEE_WGL_3DFX_multisample = GL_FALSE; +GLboolean _GLEE_WGL_EXT_multisample = GL_FALSE; +GLboolean _GLEE_WGL_I3D_digital_video_control = GL_FALSE; +GLboolean _GLEE_WGL_I3D_gamma = GL_FALSE; +GLboolean _GLEE_WGL_I3D_genlock = GL_FALSE; +GLboolean _GLEE_WGL_I3D_image_buffer = GL_FALSE; +GLboolean _GLEE_WGL_I3D_swap_frame_lock = GL_FALSE; +GLboolean _GLEE_WGL_NV_render_depth_texture = GL_FALSE; +GLboolean _GLEE_WGL_NV_render_texture_rectangle = GL_FALSE; +GLboolean _GLEE_WGL_ATI_pixel_format_float = GL_FALSE; +GLboolean _GLEE_WGL_NV_float_buffer = GL_FALSE; +GLboolean _GLEE_WGL_3DL_stereo_control = GL_FALSE; +GLboolean _GLEE_WGL_EXT_pixel_format_packed_float = GL_FALSE; +GLboolean _GLEE_WGL_EXT_framebuffer_sRGB = GL_FALSE; +GLboolean _GLEE_WGL_NV_present_video = GL_FALSE; +GLboolean _GLEE_WGL_NV_swap_group = GL_FALSE; +GLboolean _GLEE_WGL_NV_gpu_affinity = GL_FALSE; +GLboolean _GLEE_WGL_EXT_display_color_table = GL_FALSE; +GLboolean _GLEE_WGL_EXT_extensions_string = GL_FALSE; +GLboolean _GLEE_WGL_EXT_swap_control = GL_FALSE; +GLboolean _GLEE_WGL_NV_vertex_array_range = GL_FALSE; +GLboolean _GLEE_WGL_OML_sync_control = GL_FALSE; +GLboolean _GLEE_WGL_I3D_swap_frame_usage = GL_FALSE; +GLboolean _GLEE_WGL_NV_video_output = GL_FALSE; + +/* WGL Extension names */ + +char __GLeeWGLExtensionNames[37][34]={ + "WGL_ARB_buffer_region", + "WGL_ARB_multisample", + "WGL_ARB_extensions_string", + "WGL_ARB_pixel_format", + "WGL_ARB_make_current_read", + "WGL_ARB_pbuffer", + "WGL_ARB_render_texture", + "WGL_ARB_pixel_format_float", + "WGL_ARB_create_context", + "WGL_EXT_make_current_read", + "WGL_EXT_pixel_format", + "WGL_EXT_pbuffer", + "WGL_EXT_depth_float", + "WGL_3DFX_multisample", + "WGL_EXT_multisample", + "WGL_I3D_digital_video_control", + "WGL_I3D_gamma", + "WGL_I3D_genlock", + "WGL_I3D_image_buffer", + "WGL_I3D_swap_frame_lock", + "WGL_NV_render_depth_texture", + "WGL_NV_render_texture_rectangle", + "WGL_ATI_pixel_format_float", + "WGL_NV_float_buffer", + "WGL_3DL_stereo_control", + "WGL_EXT_pixel_format_packed_float", + "WGL_EXT_framebuffer_sRGB", + "WGL_NV_present_video", + "WGL_NV_swap_group", + "WGL_NV_gpu_affinity", + "WGL_EXT_display_color_table", + "WGL_EXT_extensions_string", + "WGL_EXT_swap_control", + "WGL_NV_vertex_array_range", + "WGL_OML_sync_control", + "WGL_I3D_swap_frame_usage", + "WGL_NV_video_output" +}; +int __GLeeWGLNumExtensions=37; + +/* WGL_ARB_buffer_region */ + +#ifdef __GLEE_WGL_ARB_buffer_region +#ifndef GLEE_C_DEFINED_wglCreateBufferRegionARB +#define GLEE_C_DEFINED_wglCreateBufferRegionARB + HANDLE __stdcall GLee_Lazy_wglCreateBufferRegionARB(HDC hDC, int iLayerPlane, UINT uType) {if (GLeeInit()) return wglCreateBufferRegionARB(hDC, iLayerPlane, uType); return (HANDLE)0;} + GLEEPFNWGLCREATEBUFFERREGIONARBPROC GLeeFuncPtr_wglCreateBufferRegionARB=GLee_Lazy_wglCreateBufferRegionARB; +#endif +#ifndef GLEE_C_DEFINED_wglDeleteBufferRegionARB +#define GLEE_C_DEFINED_wglDeleteBufferRegionARB + VOID __stdcall GLee_Lazy_wglDeleteBufferRegionARB(HANDLE hRegion) {if (GLeeInit()) wglDeleteBufferRegionARB(hRegion);} + GLEEPFNWGLDELETEBUFFERREGIONARBPROC GLeeFuncPtr_wglDeleteBufferRegionARB=GLee_Lazy_wglDeleteBufferRegionARB; +#endif +#ifndef GLEE_C_DEFINED_wglSaveBufferRegionARB +#define GLEE_C_DEFINED_wglSaveBufferRegionARB + BOOL __stdcall GLee_Lazy_wglSaveBufferRegionARB(HANDLE hRegion, int x, int y, int width, int height) {if (GLeeInit()) return wglSaveBufferRegionARB(hRegion, x, y, width, height); return (BOOL)0;} + GLEEPFNWGLSAVEBUFFERREGIONARBPROC GLeeFuncPtr_wglSaveBufferRegionARB=GLee_Lazy_wglSaveBufferRegionARB; +#endif +#ifndef GLEE_C_DEFINED_wglRestoreBufferRegionARB +#define GLEE_C_DEFINED_wglRestoreBufferRegionARB + BOOL __stdcall GLee_Lazy_wglRestoreBufferRegionARB(HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc) {if (GLeeInit()) return wglRestoreBufferRegionARB(hRegion, x, y, width, height, xSrc, ySrc); return (BOOL)0;} + GLEEPFNWGLRESTOREBUFFERREGIONARBPROC GLeeFuncPtr_wglRestoreBufferRegionARB=GLee_Lazy_wglRestoreBufferRegionARB; +#endif +#endif + +/* WGL_ARB_multisample */ + +#ifdef __GLEE_WGL_ARB_multisample +#endif + +/* WGL_ARB_extensions_string */ + +#ifdef __GLEE_WGL_ARB_extensions_string +#ifndef GLEE_C_DEFINED_wglGetExtensionsStringARB +#define GLEE_C_DEFINED_wglGetExtensionsStringARB + const char * __stdcall GLee_Lazy_wglGetExtensionsStringARB(HDC hdc) {if (GLeeInit()) return wglGetExtensionsStringARB(hdc); return (const char *)0;} + GLEEPFNWGLGETEXTENSIONSSTRINGARBPROC GLeeFuncPtr_wglGetExtensionsStringARB=GLee_Lazy_wglGetExtensionsStringARB; +#endif +#endif + +/* WGL_ARB_pixel_format */ + +#ifdef __GLEE_WGL_ARB_pixel_format +#ifndef GLEE_C_DEFINED_wglGetPixelFormatAttribivARB +#define GLEE_C_DEFINED_wglGetPixelFormatAttribivARB + BOOL __stdcall GLee_Lazy_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int * piAttributes, int * piValues) {if (GLeeInit()) return wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues); return (BOOL)0;} + GLEEPFNWGLGETPIXELFORMATATTRIBIVARBPROC GLeeFuncPtr_wglGetPixelFormatAttribivARB=GLee_Lazy_wglGetPixelFormatAttribivARB; +#endif +#ifndef GLEE_C_DEFINED_wglGetPixelFormatAttribfvARB +#define GLEE_C_DEFINED_wglGetPixelFormatAttribfvARB + BOOL __stdcall GLee_Lazy_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int * piAttributes, FLOAT * pfValues) {if (GLeeInit()) return wglGetPixelFormatAttribfvARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues); return (BOOL)0;} + GLEEPFNWGLGETPIXELFORMATATTRIBFVARBPROC GLeeFuncPtr_wglGetPixelFormatAttribfvARB=GLee_Lazy_wglGetPixelFormatAttribfvARB; +#endif +#ifndef GLEE_C_DEFINED_wglChoosePixelFormatARB +#define GLEE_C_DEFINED_wglChoosePixelFormatARB + BOOL __stdcall GLee_Lazy_wglChoosePixelFormatARB(HDC hdc, const int * piAttribIList, const FLOAT * pfAttribFList, UINT nMaxFormats, int * piFormats, UINT * nNumFormats) {if (GLeeInit()) return wglChoosePixelFormatARB(hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats); return (BOOL)0;} + GLEEPFNWGLCHOOSEPIXELFORMATARBPROC GLeeFuncPtr_wglChoosePixelFormatARB=GLee_Lazy_wglChoosePixelFormatARB; +#endif +#endif + +/* WGL_ARB_make_current_read */ + +#ifdef __GLEE_WGL_ARB_make_current_read +#ifndef GLEE_C_DEFINED_wglMakeContextCurrentARB +#define GLEE_C_DEFINED_wglMakeContextCurrentARB + BOOL __stdcall GLee_Lazy_wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc) {if (GLeeInit()) return wglMakeContextCurrentARB(hDrawDC, hReadDC, hglrc); return (BOOL)0;} + GLEEPFNWGLMAKECONTEXTCURRENTARBPROC GLeeFuncPtr_wglMakeContextCurrentARB=GLee_Lazy_wglMakeContextCurrentARB; +#endif +#ifndef GLEE_C_DEFINED_wglGetCurrentReadDCARB +#define GLEE_C_DEFINED_wglGetCurrentReadDCARB + HDC __stdcall GLee_Lazy_wglGetCurrentReadDCARB(void) {if (GLeeInit()) return wglGetCurrentReadDCARB(); return (HDC)0;} + GLEEPFNWGLGETCURRENTREADDCARBPROC GLeeFuncPtr_wglGetCurrentReadDCARB=GLee_Lazy_wglGetCurrentReadDCARB; +#endif +#endif + +/* WGL_ARB_pbuffer */ + +#ifdef __GLEE_WGL_ARB_pbuffer +#ifndef GLEE_C_DEFINED_wglCreatePbufferARB +#define GLEE_C_DEFINED_wglCreatePbufferARB + HPBUFFERARB __stdcall GLee_Lazy_wglCreatePbufferARB(HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int * piAttribList) {if (GLeeInit()) return wglCreatePbufferARB(hDC, iPixelFormat, iWidth, iHeight, piAttribList); return (HPBUFFERARB)0;} + GLEEPFNWGLCREATEPBUFFERARBPROC GLeeFuncPtr_wglCreatePbufferARB=GLee_Lazy_wglCreatePbufferARB; +#endif +#ifndef GLEE_C_DEFINED_wglGetPbufferDCARB +#define GLEE_C_DEFINED_wglGetPbufferDCARB + HDC __stdcall GLee_Lazy_wglGetPbufferDCARB(HPBUFFERARB hPbuffer) {if (GLeeInit()) return wglGetPbufferDCARB(hPbuffer); return (HDC)0;} + GLEEPFNWGLGETPBUFFERDCARBPROC GLeeFuncPtr_wglGetPbufferDCARB=GLee_Lazy_wglGetPbufferDCARB; +#endif +#ifndef GLEE_C_DEFINED_wglReleasePbufferDCARB +#define GLEE_C_DEFINED_wglReleasePbufferDCARB + int __stdcall GLee_Lazy_wglReleasePbufferDCARB(HPBUFFERARB hPbuffer, HDC hDC) {if (GLeeInit()) return wglReleasePbufferDCARB(hPbuffer, hDC); return (int)0;} + GLEEPFNWGLRELEASEPBUFFERDCARBPROC GLeeFuncPtr_wglReleasePbufferDCARB=GLee_Lazy_wglReleasePbufferDCARB; +#endif +#ifndef GLEE_C_DEFINED_wglDestroyPbufferARB +#define GLEE_C_DEFINED_wglDestroyPbufferARB + BOOL __stdcall GLee_Lazy_wglDestroyPbufferARB(HPBUFFERARB hPbuffer) {if (GLeeInit()) return wglDestroyPbufferARB(hPbuffer); return (BOOL)0;} + GLEEPFNWGLDESTROYPBUFFERARBPROC GLeeFuncPtr_wglDestroyPbufferARB=GLee_Lazy_wglDestroyPbufferARB; +#endif +#ifndef GLEE_C_DEFINED_wglQueryPbufferARB +#define GLEE_C_DEFINED_wglQueryPbufferARB + BOOL __stdcall GLee_Lazy_wglQueryPbufferARB(HPBUFFERARB hPbuffer, int iAttribute, int * piValue) {if (GLeeInit()) return wglQueryPbufferARB(hPbuffer, iAttribute, piValue); return (BOOL)0;} + GLEEPFNWGLQUERYPBUFFERARBPROC GLeeFuncPtr_wglQueryPbufferARB=GLee_Lazy_wglQueryPbufferARB; +#endif +#endif + +/* WGL_ARB_render_texture */ + +#ifdef __GLEE_WGL_ARB_render_texture +#ifndef GLEE_C_DEFINED_wglBindTexImageARB +#define GLEE_C_DEFINED_wglBindTexImageARB + BOOL __stdcall GLee_Lazy_wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer) {if (GLeeInit()) return wglBindTexImageARB(hPbuffer, iBuffer); return (BOOL)0;} + GLEEPFNWGLBINDTEXIMAGEARBPROC GLeeFuncPtr_wglBindTexImageARB=GLee_Lazy_wglBindTexImageARB; +#endif +#ifndef GLEE_C_DEFINED_wglReleaseTexImageARB +#define GLEE_C_DEFINED_wglReleaseTexImageARB + BOOL __stdcall GLee_Lazy_wglReleaseTexImageARB(HPBUFFERARB hPbuffer, int iBuffer) {if (GLeeInit()) return wglReleaseTexImageARB(hPbuffer, iBuffer); return (BOOL)0;} + GLEEPFNWGLRELEASETEXIMAGEARBPROC GLeeFuncPtr_wglReleaseTexImageARB=GLee_Lazy_wglReleaseTexImageARB; +#endif +#ifndef GLEE_C_DEFINED_wglSetPbufferAttribARB +#define GLEE_C_DEFINED_wglSetPbufferAttribARB + BOOL __stdcall GLee_Lazy_wglSetPbufferAttribARB(HPBUFFERARB hPbuffer, const int * piAttribList) {if (GLeeInit()) return wglSetPbufferAttribARB(hPbuffer, piAttribList); return (BOOL)0;} + GLEEPFNWGLSETPBUFFERATTRIBARBPROC GLeeFuncPtr_wglSetPbufferAttribARB=GLee_Lazy_wglSetPbufferAttribARB; +#endif +#endif + +/* WGL_ARB_pixel_format_float */ + +#ifdef __GLEE_WGL_ARB_pixel_format_float +#endif + +/* WGL_ARB_create_context */ + +#ifdef __GLEE_WGL_ARB_create_context +#ifndef GLEE_C_DEFINED_wglCreateContextAttribsARB +#define GLEE_C_DEFINED_wglCreateContextAttribsARB + HGLRC __stdcall GLee_Lazy_wglCreateContextAttribsARB(HDC hDC, HGLRC hShareContext, const int * attribList) {if (GLeeInit()) return wglCreateContextAttribsARB(hDC, hShareContext, attribList); return (HGLRC)0;} + GLEEPFNWGLCREATECONTEXTATTRIBSARBPROC GLeeFuncPtr_wglCreateContextAttribsARB=GLee_Lazy_wglCreateContextAttribsARB; +#endif +#endif + +/* WGL_EXT_make_current_read */ + +#ifdef __GLEE_WGL_EXT_make_current_read +#ifndef GLEE_C_DEFINED_wglMakeContextCurrentEXT +#define GLEE_C_DEFINED_wglMakeContextCurrentEXT + BOOL __stdcall GLee_Lazy_wglMakeContextCurrentEXT(HDC hDrawDC, HDC hReadDC, HGLRC hglrc) {if (GLeeInit()) return wglMakeContextCurrentEXT(hDrawDC, hReadDC, hglrc); return (BOOL)0;} + GLEEPFNWGLMAKECONTEXTCURRENTEXTPROC GLeeFuncPtr_wglMakeContextCurrentEXT=GLee_Lazy_wglMakeContextCurrentEXT; +#endif +#ifndef GLEE_C_DEFINED_wglGetCurrentReadDCEXT +#define GLEE_C_DEFINED_wglGetCurrentReadDCEXT + HDC __stdcall GLee_Lazy_wglGetCurrentReadDCEXT(void) {if (GLeeInit()) return wglGetCurrentReadDCEXT(); return (HDC)0;} + GLEEPFNWGLGETCURRENTREADDCEXTPROC GLeeFuncPtr_wglGetCurrentReadDCEXT=GLee_Lazy_wglGetCurrentReadDCEXT; +#endif +#endif + +/* WGL_EXT_pixel_format */ + +#ifdef __GLEE_WGL_EXT_pixel_format +#ifndef GLEE_C_DEFINED_wglGetPixelFormatAttribivEXT +#define GLEE_C_DEFINED_wglGetPixelFormatAttribivEXT + BOOL __stdcall GLee_Lazy_wglGetPixelFormatAttribivEXT(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int * piAttributes, int * piValues) {if (GLeeInit()) return wglGetPixelFormatAttribivEXT(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues); return (BOOL)0;} + GLEEPFNWGLGETPIXELFORMATATTRIBIVEXTPROC GLeeFuncPtr_wglGetPixelFormatAttribivEXT=GLee_Lazy_wglGetPixelFormatAttribivEXT; +#endif +#ifndef GLEE_C_DEFINED_wglGetPixelFormatAttribfvEXT +#define GLEE_C_DEFINED_wglGetPixelFormatAttribfvEXT + BOOL __stdcall GLee_Lazy_wglGetPixelFormatAttribfvEXT(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int * piAttributes, FLOAT * pfValues) {if (GLeeInit()) return wglGetPixelFormatAttribfvEXT(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues); return (BOOL)0;} + GLEEPFNWGLGETPIXELFORMATATTRIBFVEXTPROC GLeeFuncPtr_wglGetPixelFormatAttribfvEXT=GLee_Lazy_wglGetPixelFormatAttribfvEXT; +#endif +#ifndef GLEE_C_DEFINED_wglChoosePixelFormatEXT +#define GLEE_C_DEFINED_wglChoosePixelFormatEXT + BOOL __stdcall GLee_Lazy_wglChoosePixelFormatEXT(HDC hdc, const int * piAttribIList, const FLOAT * pfAttribFList, UINT nMaxFormats, int * piFormats, UINT * nNumFormats) {if (GLeeInit()) return wglChoosePixelFormatEXT(hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats); return (BOOL)0;} + GLEEPFNWGLCHOOSEPIXELFORMATEXTPROC GLeeFuncPtr_wglChoosePixelFormatEXT=GLee_Lazy_wglChoosePixelFormatEXT; +#endif +#endif + +/* WGL_EXT_pbuffer */ + +#ifdef __GLEE_WGL_EXT_pbuffer +#ifndef GLEE_C_DEFINED_wglCreatePbufferEXT +#define GLEE_C_DEFINED_wglCreatePbufferEXT + HPBUFFEREXT __stdcall GLee_Lazy_wglCreatePbufferEXT(HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int * piAttribList) {if (GLeeInit()) return wglCreatePbufferEXT(hDC, iPixelFormat, iWidth, iHeight, piAttribList); return (HPBUFFEREXT)0;} + GLEEPFNWGLCREATEPBUFFEREXTPROC GLeeFuncPtr_wglCreatePbufferEXT=GLee_Lazy_wglCreatePbufferEXT; +#endif +#ifndef GLEE_C_DEFINED_wglGetPbufferDCEXT +#define GLEE_C_DEFINED_wglGetPbufferDCEXT + HDC __stdcall GLee_Lazy_wglGetPbufferDCEXT(HPBUFFEREXT hPbuffer) {if (GLeeInit()) return wglGetPbufferDCEXT(hPbuffer); return (HDC)0;} + GLEEPFNWGLGETPBUFFERDCEXTPROC GLeeFuncPtr_wglGetPbufferDCEXT=GLee_Lazy_wglGetPbufferDCEXT; +#endif +#ifndef GLEE_C_DEFINED_wglReleasePbufferDCEXT +#define GLEE_C_DEFINED_wglReleasePbufferDCEXT + int __stdcall GLee_Lazy_wglReleasePbufferDCEXT(HPBUFFEREXT hPbuffer, HDC hDC) {if (GLeeInit()) return wglReleasePbufferDCEXT(hPbuffer, hDC); return (int)0;} + GLEEPFNWGLRELEASEPBUFFERDCEXTPROC GLeeFuncPtr_wglReleasePbufferDCEXT=GLee_Lazy_wglReleasePbufferDCEXT; +#endif +#ifndef GLEE_C_DEFINED_wglDestroyPbufferEXT +#define GLEE_C_DEFINED_wglDestroyPbufferEXT + BOOL __stdcall GLee_Lazy_wglDestroyPbufferEXT(HPBUFFEREXT hPbuffer) {if (GLeeInit()) return wglDestroyPbufferEXT(hPbuffer); return (BOOL)0;} + GLEEPFNWGLDESTROYPBUFFEREXTPROC GLeeFuncPtr_wglDestroyPbufferEXT=GLee_Lazy_wglDestroyPbufferEXT; +#endif +#ifndef GLEE_C_DEFINED_wglQueryPbufferEXT +#define GLEE_C_DEFINED_wglQueryPbufferEXT + BOOL __stdcall GLee_Lazy_wglQueryPbufferEXT(HPBUFFEREXT hPbuffer, int iAttribute, int * piValue) {if (GLeeInit()) return wglQueryPbufferEXT(hPbuffer, iAttribute, piValue); return (BOOL)0;} + GLEEPFNWGLQUERYPBUFFEREXTPROC GLeeFuncPtr_wglQueryPbufferEXT=GLee_Lazy_wglQueryPbufferEXT; +#endif +#endif + +/* WGL_EXT_depth_float */ + +#ifdef __GLEE_WGL_EXT_depth_float +#endif + +/* WGL_3DFX_multisample */ + +#ifdef __GLEE_WGL_3DFX_multisample +#endif + +/* WGL_EXT_multisample */ + +#ifdef __GLEE_WGL_EXT_multisample +#endif + +/* WGL_I3D_digital_video_control */ + +#ifdef __GLEE_WGL_I3D_digital_video_control +#ifndef GLEE_C_DEFINED_wglGetDigitalVideoParametersI3D +#define GLEE_C_DEFINED_wglGetDigitalVideoParametersI3D + BOOL __stdcall GLee_Lazy_wglGetDigitalVideoParametersI3D(HDC hDC, int iAttribute, int * piValue) {if (GLeeInit()) return wglGetDigitalVideoParametersI3D(hDC, iAttribute, piValue); return (BOOL)0;} + GLEEPFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC GLeeFuncPtr_wglGetDigitalVideoParametersI3D=GLee_Lazy_wglGetDigitalVideoParametersI3D; +#endif +#ifndef GLEE_C_DEFINED_wglSetDigitalVideoParametersI3D +#define GLEE_C_DEFINED_wglSetDigitalVideoParametersI3D + BOOL __stdcall GLee_Lazy_wglSetDigitalVideoParametersI3D(HDC hDC, int iAttribute, const int * piValue) {if (GLeeInit()) return wglSetDigitalVideoParametersI3D(hDC, iAttribute, piValue); return (BOOL)0;} + GLEEPFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC GLeeFuncPtr_wglSetDigitalVideoParametersI3D=GLee_Lazy_wglSetDigitalVideoParametersI3D; +#endif +#endif + +/* WGL_I3D_gamma */ + +#ifdef __GLEE_WGL_I3D_gamma +#ifndef GLEE_C_DEFINED_wglGetGammaTableParametersI3D +#define GLEE_C_DEFINED_wglGetGammaTableParametersI3D + BOOL __stdcall GLee_Lazy_wglGetGammaTableParametersI3D(HDC hDC, int iAttribute, int * piValue) {if (GLeeInit()) return wglGetGammaTableParametersI3D(hDC, iAttribute, piValue); return (BOOL)0;} + GLEEPFNWGLGETGAMMATABLEPARAMETERSI3DPROC GLeeFuncPtr_wglGetGammaTableParametersI3D=GLee_Lazy_wglGetGammaTableParametersI3D; +#endif +#ifndef GLEE_C_DEFINED_wglSetGammaTableParametersI3D +#define GLEE_C_DEFINED_wglSetGammaTableParametersI3D + BOOL __stdcall GLee_Lazy_wglSetGammaTableParametersI3D(HDC hDC, int iAttribute, const int * piValue) {if (GLeeInit()) return wglSetGammaTableParametersI3D(hDC, iAttribute, piValue); return (BOOL)0;} + GLEEPFNWGLSETGAMMATABLEPARAMETERSI3DPROC GLeeFuncPtr_wglSetGammaTableParametersI3D=GLee_Lazy_wglSetGammaTableParametersI3D; +#endif +#ifndef GLEE_C_DEFINED_wglGetGammaTableI3D +#define GLEE_C_DEFINED_wglGetGammaTableI3D + BOOL __stdcall GLee_Lazy_wglGetGammaTableI3D(HDC hDC, int iEntries, USHORT * puRed, USHORT * puGreen, USHORT * puBlue) {if (GLeeInit()) return wglGetGammaTableI3D(hDC, iEntries, puRed, puGreen, puBlue); return (BOOL)0;} + GLEEPFNWGLGETGAMMATABLEI3DPROC GLeeFuncPtr_wglGetGammaTableI3D=GLee_Lazy_wglGetGammaTableI3D; +#endif +#ifndef GLEE_C_DEFINED_wglSetGammaTableI3D +#define GLEE_C_DEFINED_wglSetGammaTableI3D + BOOL __stdcall GLee_Lazy_wglSetGammaTableI3D(HDC hDC, int iEntries, const USHORT * puRed, const USHORT * puGreen, const USHORT * puBlue) {if (GLeeInit()) return wglSetGammaTableI3D(hDC, iEntries, puRed, puGreen, puBlue); return (BOOL)0;} + GLEEPFNWGLSETGAMMATABLEI3DPROC GLeeFuncPtr_wglSetGammaTableI3D=GLee_Lazy_wglSetGammaTableI3D; +#endif +#endif + +/* WGL_I3D_genlock */ + +#ifdef __GLEE_WGL_I3D_genlock +#ifndef GLEE_C_DEFINED_wglEnableGenlockI3D +#define GLEE_C_DEFINED_wglEnableGenlockI3D + BOOL __stdcall GLee_Lazy_wglEnableGenlockI3D(HDC hDC) {if (GLeeInit()) return wglEnableGenlockI3D(hDC); return (BOOL)0;} + GLEEPFNWGLENABLEGENLOCKI3DPROC GLeeFuncPtr_wglEnableGenlockI3D=GLee_Lazy_wglEnableGenlockI3D; +#endif +#ifndef GLEE_C_DEFINED_wglDisableGenlockI3D +#define GLEE_C_DEFINED_wglDisableGenlockI3D + BOOL __stdcall GLee_Lazy_wglDisableGenlockI3D(HDC hDC) {if (GLeeInit()) return wglDisableGenlockI3D(hDC); return (BOOL)0;} + GLEEPFNWGLDISABLEGENLOCKI3DPROC GLeeFuncPtr_wglDisableGenlockI3D=GLee_Lazy_wglDisableGenlockI3D; +#endif +#ifndef GLEE_C_DEFINED_wglIsEnabledGenlockI3D +#define GLEE_C_DEFINED_wglIsEnabledGenlockI3D + BOOL __stdcall GLee_Lazy_wglIsEnabledGenlockI3D(HDC hDC, BOOL * pFlag) {if (GLeeInit()) return wglIsEnabledGenlockI3D(hDC, pFlag); return (BOOL)0;} + GLEEPFNWGLISENABLEDGENLOCKI3DPROC GLeeFuncPtr_wglIsEnabledGenlockI3D=GLee_Lazy_wglIsEnabledGenlockI3D; +#endif +#ifndef GLEE_C_DEFINED_wglGenlockSourceI3D +#define GLEE_C_DEFINED_wglGenlockSourceI3D + BOOL __stdcall GLee_Lazy_wglGenlockSourceI3D(HDC hDC, UINT uSource) {if (GLeeInit()) return wglGenlockSourceI3D(hDC, uSource); return (BOOL)0;} + GLEEPFNWGLGENLOCKSOURCEI3DPROC GLeeFuncPtr_wglGenlockSourceI3D=GLee_Lazy_wglGenlockSourceI3D; +#endif +#ifndef GLEE_C_DEFINED_wglGetGenlockSourceI3D +#define GLEE_C_DEFINED_wglGetGenlockSourceI3D + BOOL __stdcall GLee_Lazy_wglGetGenlockSourceI3D(HDC hDC, UINT * uSource) {if (GLeeInit()) return wglGetGenlockSourceI3D(hDC, uSource); return (BOOL)0;} + GLEEPFNWGLGETGENLOCKSOURCEI3DPROC GLeeFuncPtr_wglGetGenlockSourceI3D=GLee_Lazy_wglGetGenlockSourceI3D; +#endif +#ifndef GLEE_C_DEFINED_wglGenlockSourceEdgeI3D +#define GLEE_C_DEFINED_wglGenlockSourceEdgeI3D + BOOL __stdcall GLee_Lazy_wglGenlockSourceEdgeI3D(HDC hDC, UINT uEdge) {if (GLeeInit()) return wglGenlockSourceEdgeI3D(hDC, uEdge); return (BOOL)0;} + GLEEPFNWGLGENLOCKSOURCEEDGEI3DPROC GLeeFuncPtr_wglGenlockSourceEdgeI3D=GLee_Lazy_wglGenlockSourceEdgeI3D; +#endif +#ifndef GLEE_C_DEFINED_wglGetGenlockSourceEdgeI3D +#define GLEE_C_DEFINED_wglGetGenlockSourceEdgeI3D + BOOL __stdcall GLee_Lazy_wglGetGenlockSourceEdgeI3D(HDC hDC, UINT * uEdge) {if (GLeeInit()) return wglGetGenlockSourceEdgeI3D(hDC, uEdge); return (BOOL)0;} + GLEEPFNWGLGETGENLOCKSOURCEEDGEI3DPROC GLeeFuncPtr_wglGetGenlockSourceEdgeI3D=GLee_Lazy_wglGetGenlockSourceEdgeI3D; +#endif +#ifndef GLEE_C_DEFINED_wglGenlockSampleRateI3D +#define GLEE_C_DEFINED_wglGenlockSampleRateI3D + BOOL __stdcall GLee_Lazy_wglGenlockSampleRateI3D(HDC hDC, UINT uRate) {if (GLeeInit()) return wglGenlockSampleRateI3D(hDC, uRate); return (BOOL)0;} + GLEEPFNWGLGENLOCKSAMPLERATEI3DPROC GLeeFuncPtr_wglGenlockSampleRateI3D=GLee_Lazy_wglGenlockSampleRateI3D; +#endif +#ifndef GLEE_C_DEFINED_wglGetGenlockSampleRateI3D +#define GLEE_C_DEFINED_wglGetGenlockSampleRateI3D + BOOL __stdcall GLee_Lazy_wglGetGenlockSampleRateI3D(HDC hDC, UINT * uRate) {if (GLeeInit()) return wglGetGenlockSampleRateI3D(hDC, uRate); return (BOOL)0;} + GLEEPFNWGLGETGENLOCKSAMPLERATEI3DPROC GLeeFuncPtr_wglGetGenlockSampleRateI3D=GLee_Lazy_wglGetGenlockSampleRateI3D; +#endif +#ifndef GLEE_C_DEFINED_wglGenlockSourceDelayI3D +#define GLEE_C_DEFINED_wglGenlockSourceDelayI3D + BOOL __stdcall GLee_Lazy_wglGenlockSourceDelayI3D(HDC hDC, UINT uDelay) {if (GLeeInit()) return wglGenlockSourceDelayI3D(hDC, uDelay); return (BOOL)0;} + GLEEPFNWGLGENLOCKSOURCEDELAYI3DPROC GLeeFuncPtr_wglGenlockSourceDelayI3D=GLee_Lazy_wglGenlockSourceDelayI3D; +#endif +#ifndef GLEE_C_DEFINED_wglGetGenlockSourceDelayI3D +#define GLEE_C_DEFINED_wglGetGenlockSourceDelayI3D + BOOL __stdcall GLee_Lazy_wglGetGenlockSourceDelayI3D(HDC hDC, UINT * uDelay) {if (GLeeInit()) return wglGetGenlockSourceDelayI3D(hDC, uDelay); return (BOOL)0;} + GLEEPFNWGLGETGENLOCKSOURCEDELAYI3DPROC GLeeFuncPtr_wglGetGenlockSourceDelayI3D=GLee_Lazy_wglGetGenlockSourceDelayI3D; +#endif +#ifndef GLEE_C_DEFINED_wglQueryGenlockMaxSourceDelayI3D +#define GLEE_C_DEFINED_wglQueryGenlockMaxSourceDelayI3D + BOOL __stdcall GLee_Lazy_wglQueryGenlockMaxSourceDelayI3D(HDC hDC, UINT * uMaxLineDelay, UINT * uMaxPixelDelay) {if (GLeeInit()) return wglQueryGenlockMaxSourceDelayI3D(hDC, uMaxLineDelay, uMaxPixelDelay); return (BOOL)0;} + GLEEPFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC GLeeFuncPtr_wglQueryGenlockMaxSourceDelayI3D=GLee_Lazy_wglQueryGenlockMaxSourceDelayI3D; +#endif +#endif + +/* WGL_I3D_image_buffer */ + +#ifdef __GLEE_WGL_I3D_image_buffer +#ifndef GLEE_C_DEFINED_wglCreateImageBufferI3D +#define GLEE_C_DEFINED_wglCreateImageBufferI3D + LPVOID __stdcall GLee_Lazy_wglCreateImageBufferI3D(HDC hDC, DWORD dwSize, UINT uFlags) {if (GLeeInit()) return wglCreateImageBufferI3D(hDC, dwSize, uFlags); return (LPVOID)0;} + GLEEPFNWGLCREATEIMAGEBUFFERI3DPROC GLeeFuncPtr_wglCreateImageBufferI3D=GLee_Lazy_wglCreateImageBufferI3D; +#endif +#ifndef GLEE_C_DEFINED_wglDestroyImageBufferI3D +#define GLEE_C_DEFINED_wglDestroyImageBufferI3D + BOOL __stdcall GLee_Lazy_wglDestroyImageBufferI3D(HDC hDC, LPVOID pAddress) {if (GLeeInit()) return wglDestroyImageBufferI3D(hDC, pAddress); return (BOOL)0;} + GLEEPFNWGLDESTROYIMAGEBUFFERI3DPROC GLeeFuncPtr_wglDestroyImageBufferI3D=GLee_Lazy_wglDestroyImageBufferI3D; +#endif +#ifndef GLEE_C_DEFINED_wglAssociateImageBufferEventsI3D +#define GLEE_C_DEFINED_wglAssociateImageBufferEventsI3D + BOOL __stdcall GLee_Lazy_wglAssociateImageBufferEventsI3D(HDC hDC, const HANDLE * pEvent, const LPVOID * pAddress, const DWORD * pSize, UINT count) {if (GLeeInit()) return wglAssociateImageBufferEventsI3D(hDC, pEvent, pAddress, pSize, count); return (BOOL)0;} + GLEEPFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC GLeeFuncPtr_wglAssociateImageBufferEventsI3D=GLee_Lazy_wglAssociateImageBufferEventsI3D; +#endif +#ifndef GLEE_C_DEFINED_wglReleaseImageBufferEventsI3D +#define GLEE_C_DEFINED_wglReleaseImageBufferEventsI3D + BOOL __stdcall GLee_Lazy_wglReleaseImageBufferEventsI3D(HDC hDC, const LPVOID * pAddress, UINT count) {if (GLeeInit()) return wglReleaseImageBufferEventsI3D(hDC, pAddress, count); return (BOOL)0;} + GLEEPFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC GLeeFuncPtr_wglReleaseImageBufferEventsI3D=GLee_Lazy_wglReleaseImageBufferEventsI3D; +#endif +#endif + +/* WGL_I3D_swap_frame_lock */ + +#ifdef __GLEE_WGL_I3D_swap_frame_lock +#ifndef GLEE_C_DEFINED_wglEnableFrameLockI3D +#define GLEE_C_DEFINED_wglEnableFrameLockI3D + BOOL __stdcall GLee_Lazy_wglEnableFrameLockI3D(void) {if (GLeeInit()) return wglEnableFrameLockI3D(); return (BOOL)0;} + GLEEPFNWGLENABLEFRAMELOCKI3DPROC GLeeFuncPtr_wglEnableFrameLockI3D=GLee_Lazy_wglEnableFrameLockI3D; +#endif +#ifndef GLEE_C_DEFINED_wglDisableFrameLockI3D +#define GLEE_C_DEFINED_wglDisableFrameLockI3D + BOOL __stdcall GLee_Lazy_wglDisableFrameLockI3D(void) {if (GLeeInit()) return wglDisableFrameLockI3D(); return (BOOL)0;} + GLEEPFNWGLDISABLEFRAMELOCKI3DPROC GLeeFuncPtr_wglDisableFrameLockI3D=GLee_Lazy_wglDisableFrameLockI3D; +#endif +#ifndef GLEE_C_DEFINED_wglIsEnabledFrameLockI3D +#define GLEE_C_DEFINED_wglIsEnabledFrameLockI3D + BOOL __stdcall GLee_Lazy_wglIsEnabledFrameLockI3D(BOOL * pFlag) {if (GLeeInit()) return wglIsEnabledFrameLockI3D(pFlag); return (BOOL)0;} + GLEEPFNWGLISENABLEDFRAMELOCKI3DPROC GLeeFuncPtr_wglIsEnabledFrameLockI3D=GLee_Lazy_wglIsEnabledFrameLockI3D; +#endif +#ifndef GLEE_C_DEFINED_wglQueryFrameLockMasterI3D +#define GLEE_C_DEFINED_wglQueryFrameLockMasterI3D + BOOL __stdcall GLee_Lazy_wglQueryFrameLockMasterI3D(BOOL * pFlag) {if (GLeeInit()) return wglQueryFrameLockMasterI3D(pFlag); return (BOOL)0;} + GLEEPFNWGLQUERYFRAMELOCKMASTERI3DPROC GLeeFuncPtr_wglQueryFrameLockMasterI3D=GLee_Lazy_wglQueryFrameLockMasterI3D; +#endif +#endif + +/* WGL_NV_render_depth_texture */ + +#ifdef __GLEE_WGL_NV_render_depth_texture +#endif + +/* WGL_NV_render_texture_rectangle */ + +#ifdef __GLEE_WGL_NV_render_texture_rectangle +#endif + +/* WGL_ATI_pixel_format_float */ + +#ifdef __GLEE_WGL_ATI_pixel_format_float +#endif + +/* WGL_NV_float_buffer */ + +#ifdef __GLEE_WGL_NV_float_buffer +#endif + +/* WGL_3DL_stereo_control */ + +#ifdef __GLEE_WGL_3DL_stereo_control +#endif + +/* WGL_EXT_pixel_format_packed_float */ + +#ifdef __GLEE_WGL_EXT_pixel_format_packed_float +#endif + +/* WGL_EXT_framebuffer_sRGB */ + +#ifdef __GLEE_WGL_EXT_framebuffer_sRGB +#endif + +/* WGL_NV_present_video */ + +#ifdef __GLEE_WGL_NV_present_video +#ifndef GLEE_C_DEFINED_wglEnumerateVideoDevicesNV +#define GLEE_C_DEFINED_wglEnumerateVideoDevicesNV + int __stdcall GLee_Lazy_wglEnumerateVideoDevicesNV(HDC hDC, HVIDEOOUTPUTDEVICENV * phDeviceList) {if (GLeeInit()) return wglEnumerateVideoDevicesNV(hDC, phDeviceList); return (int)0;} + GLEEPFNWGLENUMERATEVIDEODEVICESNVPROC GLeeFuncPtr_wglEnumerateVideoDevicesNV=GLee_Lazy_wglEnumerateVideoDevicesNV; +#endif +#ifndef GLEE_C_DEFINED_wglBindVideoDeviceNV +#define GLEE_C_DEFINED_wglBindVideoDeviceNV + BOOL __stdcall GLee_Lazy_wglBindVideoDeviceNV(HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int * piAttribList) {if (GLeeInit()) return wglBindVideoDeviceNV(hDC, uVideoSlot, hVideoDevice, piAttribList); return (BOOL)0;} + GLEEPFNWGLBINDVIDEODEVICENVPROC GLeeFuncPtr_wglBindVideoDeviceNV=GLee_Lazy_wglBindVideoDeviceNV; +#endif +#ifndef GLEE_C_DEFINED_wglQueryCurrentContextNV +#define GLEE_C_DEFINED_wglQueryCurrentContextNV + BOOL __stdcall GLee_Lazy_wglQueryCurrentContextNV(int iAttribute, int * piValue) {if (GLeeInit()) return wglQueryCurrentContextNV(iAttribute, piValue); return (BOOL)0;} + GLEEPFNWGLQUERYCURRENTCONTEXTNVPROC GLeeFuncPtr_wglQueryCurrentContextNV=GLee_Lazy_wglQueryCurrentContextNV; +#endif +#endif + +/* WGL_NV_swap_group */ + +#ifdef __GLEE_WGL_NV_swap_group +#ifndef GLEE_C_DEFINED_wglJoinSwapGroupNV +#define GLEE_C_DEFINED_wglJoinSwapGroupNV + BOOL __stdcall GLee_Lazy_wglJoinSwapGroupNV(HDC hDC, GLuint group) {if (GLeeInit()) return wglJoinSwapGroupNV(hDC, group); return (BOOL)0;} + GLEEPFNWGLJOINSWAPGROUPNVPROC GLeeFuncPtr_wglJoinSwapGroupNV=GLee_Lazy_wglJoinSwapGroupNV; +#endif +#ifndef GLEE_C_DEFINED_wglBindSwapBarrierNV +#define GLEE_C_DEFINED_wglBindSwapBarrierNV + BOOL __stdcall GLee_Lazy_wglBindSwapBarrierNV(GLuint group, GLuint barrier) {if (GLeeInit()) return wglBindSwapBarrierNV(group, barrier); return (BOOL)0;} + GLEEPFNWGLBINDSWAPBARRIERNVPROC GLeeFuncPtr_wglBindSwapBarrierNV=GLee_Lazy_wglBindSwapBarrierNV; +#endif +#ifndef GLEE_C_DEFINED_wglQuerySwapGroupNV +#define GLEE_C_DEFINED_wglQuerySwapGroupNV + BOOL __stdcall GLee_Lazy_wglQuerySwapGroupNV(HDC hDC, GLuint * group, GLuint * barrier) {if (GLeeInit()) return wglQuerySwapGroupNV(hDC, group, barrier); return (BOOL)0;} + GLEEPFNWGLQUERYSWAPGROUPNVPROC GLeeFuncPtr_wglQuerySwapGroupNV=GLee_Lazy_wglQuerySwapGroupNV; +#endif +#ifndef GLEE_C_DEFINED_wglQueryMaxSwapGroupsNV +#define GLEE_C_DEFINED_wglQueryMaxSwapGroupsNV + BOOL __stdcall GLee_Lazy_wglQueryMaxSwapGroupsNV(HDC hDC, GLuint * maxGroups, GLuint * maxBarriers) {if (GLeeInit()) return wglQueryMaxSwapGroupsNV(hDC, maxGroups, maxBarriers); return (BOOL)0;} + GLEEPFNWGLQUERYMAXSWAPGROUPSNVPROC GLeeFuncPtr_wglQueryMaxSwapGroupsNV=GLee_Lazy_wglQueryMaxSwapGroupsNV; +#endif +#ifndef GLEE_C_DEFINED_wglQueryFrameCountNV +#define GLEE_C_DEFINED_wglQueryFrameCountNV + BOOL __stdcall GLee_Lazy_wglQueryFrameCountNV(HDC hDC, GLuint * count) {if (GLeeInit()) return wglQueryFrameCountNV(hDC, count); return (BOOL)0;} + GLEEPFNWGLQUERYFRAMECOUNTNVPROC GLeeFuncPtr_wglQueryFrameCountNV=GLee_Lazy_wglQueryFrameCountNV; +#endif +#ifndef GLEE_C_DEFINED_wglResetFrameCountNV +#define GLEE_C_DEFINED_wglResetFrameCountNV + BOOL __stdcall GLee_Lazy_wglResetFrameCountNV(HDC hDC) {if (GLeeInit()) return wglResetFrameCountNV(hDC); return (BOOL)0;} + GLEEPFNWGLRESETFRAMECOUNTNVPROC GLeeFuncPtr_wglResetFrameCountNV=GLee_Lazy_wglResetFrameCountNV; +#endif +#endif + +/* WGL_NV_gpu_affinity */ + +#ifdef __GLEE_WGL_NV_gpu_affinity +#ifndef GLEE_C_DEFINED_wglEnumGpusNV +#define GLEE_C_DEFINED_wglEnumGpusNV + BOOL __stdcall GLee_Lazy_wglEnumGpusNV(UINT iGpuIndex, HGPUNV * phGpu) {if (GLeeInit()) return wglEnumGpusNV(iGpuIndex, phGpu); return (BOOL)0;} + GLEEPFNWGLENUMGPUSNVPROC GLeeFuncPtr_wglEnumGpusNV=GLee_Lazy_wglEnumGpusNV; +#endif +#ifndef GLEE_C_DEFINED_wglEnumGpuDevicesNV +#define GLEE_C_DEFINED_wglEnumGpuDevicesNV + BOOL __stdcall GLee_Lazy_wglEnumGpuDevicesNV(HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice) {if (GLeeInit()) return wglEnumGpuDevicesNV(hGpu, iDeviceIndex, lpGpuDevice); return (BOOL)0;} + GLEEPFNWGLENUMGPUDEVICESNVPROC GLeeFuncPtr_wglEnumGpuDevicesNV=GLee_Lazy_wglEnumGpuDevicesNV; +#endif +#ifndef GLEE_C_DEFINED_wglCreateAffinityDCNV +#define GLEE_C_DEFINED_wglCreateAffinityDCNV + HDC __stdcall GLee_Lazy_wglCreateAffinityDCNV(const HGPUNV * phGpuList) {if (GLeeInit()) return wglCreateAffinityDCNV(phGpuList); return (HDC)0;} + GLEEPFNWGLCREATEAFFINITYDCNVPROC GLeeFuncPtr_wglCreateAffinityDCNV=GLee_Lazy_wglCreateAffinityDCNV; +#endif +#ifndef GLEE_C_DEFINED_wglEnumGpusFromAffinityDCNV +#define GLEE_C_DEFINED_wglEnumGpusFromAffinityDCNV + BOOL __stdcall GLee_Lazy_wglEnumGpusFromAffinityDCNV(HDC hAffinityDC, UINT iGpuIndex, HGPUNV * hGpu) {if (GLeeInit()) return wglEnumGpusFromAffinityDCNV(hAffinityDC, iGpuIndex, hGpu); return (BOOL)0;} + GLEEPFNWGLENUMGPUSFROMAFFINITYDCNVPROC GLeeFuncPtr_wglEnumGpusFromAffinityDCNV=GLee_Lazy_wglEnumGpusFromAffinityDCNV; +#endif +#ifndef GLEE_C_DEFINED_wglDeleteDCNV +#define GLEE_C_DEFINED_wglDeleteDCNV + BOOL __stdcall GLee_Lazy_wglDeleteDCNV(HDC hdc) {if (GLeeInit()) return wglDeleteDCNV(hdc); return (BOOL)0;} + GLEEPFNWGLDELETEDCNVPROC GLeeFuncPtr_wglDeleteDCNV=GLee_Lazy_wglDeleteDCNV; +#endif +#endif + +/* WGL_EXT_display_color_table */ + +#ifdef __GLEE_WGL_EXT_display_color_table +#ifndef GLEE_C_DEFINED_wglCreateDisplayColorTableEXT +#define GLEE_C_DEFINED_wglCreateDisplayColorTableEXT + GLboolean __stdcall GLee_Lazy_wglCreateDisplayColorTableEXT(GLushort id) {if (GLeeInit()) return wglCreateDisplayColorTableEXT(id); return (GLboolean)0;} + GLEEPFNWGLCREATEDISPLAYCOLORTABLEEXTPROC GLeeFuncPtr_wglCreateDisplayColorTableEXT=GLee_Lazy_wglCreateDisplayColorTableEXT; +#endif +#ifndef GLEE_C_DEFINED_wglLoadDisplayColorTableEXT +#define GLEE_C_DEFINED_wglLoadDisplayColorTableEXT + GLboolean __stdcall GLee_Lazy_wglLoadDisplayColorTableEXT(const GLushort * table, GLuint length) {if (GLeeInit()) return wglLoadDisplayColorTableEXT(table, length); return (GLboolean)0;} + GLEEPFNWGLLOADDISPLAYCOLORTABLEEXTPROC GLeeFuncPtr_wglLoadDisplayColorTableEXT=GLee_Lazy_wglLoadDisplayColorTableEXT; +#endif +#ifndef GLEE_C_DEFINED_wglBindDisplayColorTableEXT +#define GLEE_C_DEFINED_wglBindDisplayColorTableEXT + GLboolean __stdcall GLee_Lazy_wglBindDisplayColorTableEXT(GLushort id) {if (GLeeInit()) return wglBindDisplayColorTableEXT(id); return (GLboolean)0;} + GLEEPFNWGLBINDDISPLAYCOLORTABLEEXTPROC GLeeFuncPtr_wglBindDisplayColorTableEXT=GLee_Lazy_wglBindDisplayColorTableEXT; +#endif +#ifndef GLEE_C_DEFINED_wglDestroyDisplayColorTableEXT +#define GLEE_C_DEFINED_wglDestroyDisplayColorTableEXT + VOID __stdcall GLee_Lazy_wglDestroyDisplayColorTableEXT(GLushort id) {if (GLeeInit()) wglDestroyDisplayColorTableEXT(id);} + GLEEPFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC GLeeFuncPtr_wglDestroyDisplayColorTableEXT=GLee_Lazy_wglDestroyDisplayColorTableEXT; +#endif +#endif + +/* WGL_EXT_extensions_string */ + +#ifdef __GLEE_WGL_EXT_extensions_string +#ifndef GLEE_C_DEFINED_wglGetExtensionsStringEXT +#define GLEE_C_DEFINED_wglGetExtensionsStringEXT + const char * __stdcall GLee_Lazy_wglGetExtensionsStringEXT(void) {if (GLeeInit()) return wglGetExtensionsStringEXT(); return (const char *)0;} + GLEEPFNWGLGETEXTENSIONSSTRINGEXTPROC GLeeFuncPtr_wglGetExtensionsStringEXT=GLee_Lazy_wglGetExtensionsStringEXT; +#endif +#endif + +/* WGL_EXT_swap_control */ + +#ifdef __GLEE_WGL_EXT_swap_control +#ifndef GLEE_C_DEFINED_wglSwapIntervalEXT +#define GLEE_C_DEFINED_wglSwapIntervalEXT + BOOL __stdcall GLee_Lazy_wglSwapIntervalEXT(int interval) {if (GLeeInit()) return wglSwapIntervalEXT(interval); return (BOOL)0;} + GLEEPFNWGLSWAPINTERVALEXTPROC GLeeFuncPtr_wglSwapIntervalEXT=GLee_Lazy_wglSwapIntervalEXT; +#endif +#ifndef GLEE_C_DEFINED_wglGetSwapIntervalEXT +#define GLEE_C_DEFINED_wglGetSwapIntervalEXT + int __stdcall GLee_Lazy_wglGetSwapIntervalEXT(void) {if (GLeeInit()) return wglGetSwapIntervalEXT(); return (int)0;} + GLEEPFNWGLGETSWAPINTERVALEXTPROC GLeeFuncPtr_wglGetSwapIntervalEXT=GLee_Lazy_wglGetSwapIntervalEXT; +#endif +#endif + +/* WGL_NV_vertex_array_range */ + +#ifdef __GLEE_WGL_NV_vertex_array_range +#ifndef GLEE_C_DEFINED_wglAllocateMemoryNV +#define GLEE_C_DEFINED_wglAllocateMemoryNV + void* __stdcall GLee_Lazy_wglAllocateMemoryNV(GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority) {if (GLeeInit()) return wglAllocateMemoryNV(size, readfreq, writefreq, priority); return (void*)0;} + GLEEPFNWGLALLOCATEMEMORYNVPROC GLeeFuncPtr_wglAllocateMemoryNV=GLee_Lazy_wglAllocateMemoryNV; +#endif +#ifndef GLEE_C_DEFINED_wglFreeMemoryNV +#define GLEE_C_DEFINED_wglFreeMemoryNV + void __stdcall GLee_Lazy_wglFreeMemoryNV(void * pointer) {if (GLeeInit()) wglFreeMemoryNV(pointer);} + GLEEPFNWGLFREEMEMORYNVPROC GLeeFuncPtr_wglFreeMemoryNV=GLee_Lazy_wglFreeMemoryNV; +#endif +#endif + +/* WGL_OML_sync_control */ + +#ifdef __GLEE_WGL_OML_sync_control +#ifndef GLEE_C_DEFINED_wglGetSyncValuesOML +#define GLEE_C_DEFINED_wglGetSyncValuesOML + BOOL __stdcall GLee_Lazy_wglGetSyncValuesOML(HDC hdc, INT64 * ust, INT64 * msc, INT64 * sbc) {if (GLeeInit()) return wglGetSyncValuesOML(hdc, ust, msc, sbc); return (BOOL)0;} + GLEEPFNWGLGETSYNCVALUESOMLPROC GLeeFuncPtr_wglGetSyncValuesOML=GLee_Lazy_wglGetSyncValuesOML; +#endif +#ifndef GLEE_C_DEFINED_wglGetMscRateOML +#define GLEE_C_DEFINED_wglGetMscRateOML + BOOL __stdcall GLee_Lazy_wglGetMscRateOML(HDC hdc, INT32 * numerator, INT32 * denominator) {if (GLeeInit()) return wglGetMscRateOML(hdc, numerator, denominator); return (BOOL)0;} + GLEEPFNWGLGETMSCRATEOMLPROC GLeeFuncPtr_wglGetMscRateOML=GLee_Lazy_wglGetMscRateOML; +#endif +#ifndef GLEE_C_DEFINED_wglSwapBuffersMscOML +#define GLEE_C_DEFINED_wglSwapBuffersMscOML + INT64 __stdcall GLee_Lazy_wglSwapBuffersMscOML(HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder) {if (GLeeInit()) return wglSwapBuffersMscOML(hdc, target_msc, divisor, remainder); return (INT64)0;} + GLEEPFNWGLSWAPBUFFERSMSCOMLPROC GLeeFuncPtr_wglSwapBuffersMscOML=GLee_Lazy_wglSwapBuffersMscOML; +#endif +#ifndef GLEE_C_DEFINED_wglSwapLayerBuffersMscOML +#define GLEE_C_DEFINED_wglSwapLayerBuffersMscOML + INT64 __stdcall GLee_Lazy_wglSwapLayerBuffersMscOML(HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder) {if (GLeeInit()) return wglSwapLayerBuffersMscOML(hdc, fuPlanes, target_msc, divisor, remainder); return (INT64)0;} + GLEEPFNWGLSWAPLAYERBUFFERSMSCOMLPROC GLeeFuncPtr_wglSwapLayerBuffersMscOML=GLee_Lazy_wglSwapLayerBuffersMscOML; +#endif +#ifndef GLEE_C_DEFINED_wglWaitForMscOML +#define GLEE_C_DEFINED_wglWaitForMscOML + BOOL __stdcall GLee_Lazy_wglWaitForMscOML(HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 * ust, INT64 * msc, INT64 * sbc) {if (GLeeInit()) return wglWaitForMscOML(hdc, target_msc, divisor, remainder, ust, msc, sbc); return (BOOL)0;} + GLEEPFNWGLWAITFORMSCOMLPROC GLeeFuncPtr_wglWaitForMscOML=GLee_Lazy_wglWaitForMscOML; +#endif +#ifndef GLEE_C_DEFINED_wglWaitForSbcOML +#define GLEE_C_DEFINED_wglWaitForSbcOML + BOOL __stdcall GLee_Lazy_wglWaitForSbcOML(HDC hdc, INT64 target_sbc, INT64 * ust, INT64 * msc, INT64 * sbc) {if (GLeeInit()) return wglWaitForSbcOML(hdc, target_sbc, ust, msc, sbc); return (BOOL)0;} + GLEEPFNWGLWAITFORSBCOMLPROC GLeeFuncPtr_wglWaitForSbcOML=GLee_Lazy_wglWaitForSbcOML; +#endif +#endif + +/* WGL_I3D_swap_frame_usage */ + +#ifdef __GLEE_WGL_I3D_swap_frame_usage +#ifndef GLEE_C_DEFINED_wglGetFrameUsageI3D +#define GLEE_C_DEFINED_wglGetFrameUsageI3D + BOOL __stdcall GLee_Lazy_wglGetFrameUsageI3D(float * pUsage) {if (GLeeInit()) return wglGetFrameUsageI3D(pUsage); return (BOOL)0;} + GLEEPFNWGLGETFRAMEUSAGEI3DPROC GLeeFuncPtr_wglGetFrameUsageI3D=GLee_Lazy_wglGetFrameUsageI3D; +#endif +#ifndef GLEE_C_DEFINED_wglBeginFrameTrackingI3D +#define GLEE_C_DEFINED_wglBeginFrameTrackingI3D + BOOL __stdcall GLee_Lazy_wglBeginFrameTrackingI3D(void) {if (GLeeInit()) return wglBeginFrameTrackingI3D(); return (BOOL)0;} + GLEEPFNWGLBEGINFRAMETRACKINGI3DPROC GLeeFuncPtr_wglBeginFrameTrackingI3D=GLee_Lazy_wglBeginFrameTrackingI3D; +#endif +#ifndef GLEE_C_DEFINED_wglEndFrameTrackingI3D +#define GLEE_C_DEFINED_wglEndFrameTrackingI3D + BOOL __stdcall GLee_Lazy_wglEndFrameTrackingI3D(void) {if (GLeeInit()) return wglEndFrameTrackingI3D(); return (BOOL)0;} + GLEEPFNWGLENDFRAMETRACKINGI3DPROC GLeeFuncPtr_wglEndFrameTrackingI3D=GLee_Lazy_wglEndFrameTrackingI3D; +#endif +#ifndef GLEE_C_DEFINED_wglQueryFrameTrackingI3D +#define GLEE_C_DEFINED_wglQueryFrameTrackingI3D + BOOL __stdcall GLee_Lazy_wglQueryFrameTrackingI3D(DWORD * pFrameCount, DWORD * pMissedFrames, float * pLastMissedUsage) {if (GLeeInit()) return wglQueryFrameTrackingI3D(pFrameCount, pMissedFrames, pLastMissedUsage); return (BOOL)0;} + GLEEPFNWGLQUERYFRAMETRACKINGI3DPROC GLeeFuncPtr_wglQueryFrameTrackingI3D=GLee_Lazy_wglQueryFrameTrackingI3D; +#endif +#endif + +/* WGL_NV_video_output */ + +#ifdef __GLEE_WGL_NV_video_output +#ifndef GLEE_C_DEFINED_wglGetVideoDeviceNV +#define GLEE_C_DEFINED_wglGetVideoDeviceNV + BOOL __stdcall GLee_Lazy_wglGetVideoDeviceNV(HDC hDC, int numDevices, HPVIDEODEV * hVideoDevice) {if (GLeeInit()) return wglGetVideoDeviceNV(hDC, numDevices, hVideoDevice); return (BOOL)0;} + GLEEPFNWGLGETVIDEODEVICENVPROC GLeeFuncPtr_wglGetVideoDeviceNV=GLee_Lazy_wglGetVideoDeviceNV; +#endif +#ifndef GLEE_C_DEFINED_wglReleaseVideoDeviceNV +#define GLEE_C_DEFINED_wglReleaseVideoDeviceNV + BOOL __stdcall GLee_Lazy_wglReleaseVideoDeviceNV(HPVIDEODEV hVideoDevice) {if (GLeeInit()) return wglReleaseVideoDeviceNV(hVideoDevice); return (BOOL)0;} + GLEEPFNWGLRELEASEVIDEODEVICENVPROC GLeeFuncPtr_wglReleaseVideoDeviceNV=GLee_Lazy_wglReleaseVideoDeviceNV; +#endif +#ifndef GLEE_C_DEFINED_wglBindVideoImageNV +#define GLEE_C_DEFINED_wglBindVideoImageNV + BOOL __stdcall GLee_Lazy_wglBindVideoImageNV(HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer) {if (GLeeInit()) return wglBindVideoImageNV(hVideoDevice, hPbuffer, iVideoBuffer); return (BOOL)0;} + GLEEPFNWGLBINDVIDEOIMAGENVPROC GLeeFuncPtr_wglBindVideoImageNV=GLee_Lazy_wglBindVideoImageNV; +#endif +#ifndef GLEE_C_DEFINED_wglReleaseVideoImageNV +#define GLEE_C_DEFINED_wglReleaseVideoImageNV + BOOL __stdcall GLee_Lazy_wglReleaseVideoImageNV(HPBUFFERARB hPbuffer, int iVideoBuffer) {if (GLeeInit()) return wglReleaseVideoImageNV(hPbuffer, iVideoBuffer); return (BOOL)0;} + GLEEPFNWGLRELEASEVIDEOIMAGENVPROC GLeeFuncPtr_wglReleaseVideoImageNV=GLee_Lazy_wglReleaseVideoImageNV; +#endif +#ifndef GLEE_C_DEFINED_wglSendPbufferToVideoNV +#define GLEE_C_DEFINED_wglSendPbufferToVideoNV + BOOL __stdcall GLee_Lazy_wglSendPbufferToVideoNV(HPBUFFERARB hPbuffer, int iBufferType, unsigned long * pulCounterPbuffer, BOOL bBlock) {if (GLeeInit()) return wglSendPbufferToVideoNV(hPbuffer, iBufferType, pulCounterPbuffer, bBlock); return (BOOL)0;} + GLEEPFNWGLSENDPBUFFERTOVIDEONVPROC GLeeFuncPtr_wglSendPbufferToVideoNV=GLee_Lazy_wglSendPbufferToVideoNV; +#endif +#ifndef GLEE_C_DEFINED_wglGetVideoInfoNV +#define GLEE_C_DEFINED_wglGetVideoInfoNV + BOOL __stdcall GLee_Lazy_wglGetVideoInfoNV(HPVIDEODEV hpVideoDevice, unsigned long * pulCounterOutputPbuffer, unsigned long * pulCounterOutputVideo) {if (GLeeInit()) return wglGetVideoInfoNV(hpVideoDevice, pulCounterOutputPbuffer, pulCounterOutputVideo); return (BOOL)0;} + GLEEPFNWGLGETVIDEOINFONVPROC GLeeFuncPtr_wglGetVideoInfoNV=GLee_Lazy_wglGetVideoInfoNV; +#endif +#endif +#elif defined(__APPLE__) || defined(__APPLE_CC__) +#else /* GLX */ + +/* Extension querying variables */ + +GLboolean _GLEE_GLX_VERSION_1_3 = GL_FALSE; +GLboolean _GLEE_GLX_VERSION_1_4 = GL_FALSE; +GLboolean _GLEE_GLX_ARB_multisample = GL_FALSE; +GLboolean _GLEE_GLX_ARB_fbconfig_float = GL_FALSE; +GLboolean _GLEE_GLX_ARB_create_context = GL_FALSE; +GLboolean _GLEE_GLX_SGIS_multisample = GL_FALSE; +GLboolean _GLEE_GLX_EXT_visual_info = GL_FALSE; +GLboolean _GLEE_GLX_SGI_swap_control = GL_FALSE; +GLboolean _GLEE_GLX_SGI_video_sync = GL_FALSE; +GLboolean _GLEE_GLX_SGI_make_current_read = GL_FALSE; +GLboolean _GLEE_GLX_EXT_visual_rating = GL_FALSE; +GLboolean _GLEE_GLX_EXT_import_context = GL_FALSE; +GLboolean _GLEE_GLX_SGIX_fbconfig = GL_FALSE; +GLboolean _GLEE_GLX_SGIX_pbuffer = GL_FALSE; +GLboolean _GLEE_GLX_SGI_cushion = GL_FALSE; +GLboolean _GLEE_GLX_SGIX_video_resize = GL_FALSE; +GLboolean _GLEE_GLX_SGIX_swap_group = GL_FALSE; +GLboolean _GLEE_GLX_SGIX_swap_barrier = GL_FALSE; +GLboolean _GLEE_GLX_SGIS_blended_overlay = GL_FALSE; +GLboolean _GLEE_GLX_SGIS_shared_multisample = GL_FALSE; +GLboolean _GLEE_GLX_SUN_get_transparent_index = GL_FALSE; +GLboolean _GLEE_GLX_3DFX_multisample = GL_FALSE; +GLboolean _GLEE_GLX_MESA_copy_sub_buffer = GL_FALSE; +GLboolean _GLEE_GLX_MESA_pixmap_colormap = GL_FALSE; +GLboolean _GLEE_GLX_MESA_release_buffers = GL_FALSE; +GLboolean _GLEE_GLX_MESA_set_3dfx_mode = GL_FALSE; +GLboolean _GLEE_GLX_SGIX_visual_select_group = GL_FALSE; +GLboolean _GLEE_GLX_OML_swap_method = GL_FALSE; +GLboolean _GLEE_GLX_OML_sync_control = GL_FALSE; +GLboolean _GLEE_GLX_NV_float_buffer = GL_FALSE; +GLboolean _GLEE_GLX_SGIX_hyperpipe = GL_FALSE; +GLboolean _GLEE_GLX_MESA_agp_offset = GL_FALSE; +GLboolean _GLEE_GLX_EXT_fbconfig_packed_float = GL_FALSE; +GLboolean _GLEE_GLX_EXT_framebuffer_sRGB = GL_FALSE; +GLboolean _GLEE_GLX_EXT_texture_from_pixmap = GL_FALSE; +GLboolean _GLEE_GLX_NV_present_video = GL_FALSE; +GLboolean _GLEE_GLX_NV_video_out = GL_FALSE; +GLboolean _GLEE_GLX_NV_swap_group = GL_FALSE; +GLboolean _GLEE_GLX_EXT_scene_marker = GL_FALSE; +GLboolean _GLEE_GLX_NV_video_output = GL_FALSE; + +/* GLX Extension names */ + +char __GLeeGLXExtensionNames[40][30]={ + "GLX_VERSION_1_3", + "GLX_VERSION_1_4", + "GLX_ARB_multisample", + "GLX_ARB_fbconfig_float", + "GLX_ARB_create_context", + "GLX_SGIS_multisample", + "GLX_EXT_visual_info", + "GLX_SGI_swap_control", + "GLX_SGI_video_sync", + "GLX_SGI_make_current_read", + "GLX_EXT_visual_rating", + "GLX_EXT_import_context", + "GLX_SGIX_fbconfig", + "GLX_SGIX_pbuffer", + "GLX_SGI_cushion", + "GLX_SGIX_video_resize", + "GLX_SGIX_swap_group", + "GLX_SGIX_swap_barrier", + "GLX_SGIS_blended_overlay", + "GLX_SGIS_shared_multisample", + "GLX_SUN_get_transparent_index", + "GLX_3DFX_multisample", + "GLX_MESA_copy_sub_buffer", + "GLX_MESA_pixmap_colormap", + "GLX_MESA_release_buffers", + "GLX_MESA_set_3dfx_mode", + "GLX_SGIX_visual_select_group", + "GLX_OML_swap_method", + "GLX_OML_sync_control", + "GLX_NV_float_buffer", + "GLX_SGIX_hyperpipe", + "GLX_MESA_agp_offset", + "GLX_EXT_fbconfig_packed_float", + "GLX_EXT_framebuffer_sRGB", + "GLX_EXT_texture_from_pixmap", + "GLX_NV_present_video", + "GLX_NV_video_out", + "GLX_NV_swap_group", + "GLX_EXT_scene_marker", + "GLX_NV_video_output" +}; +int __GLeeGLXNumExtensions=40; + +/* GLX_VERSION_1_3 */ + +#ifdef __GLEE_GLX_VERSION_1_3 +#ifndef GLEE_C_DEFINED_glXGetFBConfigs +#define GLEE_C_DEFINED_glXGetFBConfigs + GLXFBConfig * __stdcall GLee_Lazy_glXGetFBConfigs(Display * dpy, int screen, int * nelements) {if (GLeeInit()) return glXGetFBConfigs(dpy, screen, nelements); return (GLXFBConfig *)0;} + GLEEPFNGLXGETFBCONFIGSPROC GLeeFuncPtr_glXGetFBConfigs=GLee_Lazy_glXGetFBConfigs; +#endif +#ifndef GLEE_C_DEFINED_glXChooseFBConfig +#define GLEE_C_DEFINED_glXChooseFBConfig + GLXFBConfig * __stdcall GLee_Lazy_glXChooseFBConfig(Display * dpy, int screen, const int * attrib_list, int * nelements) {if (GLeeInit()) return glXChooseFBConfig(dpy, screen, attrib_list, nelements); return (GLXFBConfig *)0;} + GLEEPFNGLXCHOOSEFBCONFIGPROC GLeeFuncPtr_glXChooseFBConfig=GLee_Lazy_glXChooseFBConfig; +#endif +#ifndef GLEE_C_DEFINED_glXGetFBConfigAttrib +#define GLEE_C_DEFINED_glXGetFBConfigAttrib + int __stdcall GLee_Lazy_glXGetFBConfigAttrib(Display * dpy, GLXFBConfig config, int attribute, int * value) {if (GLeeInit()) return glXGetFBConfigAttrib(dpy, config, attribute, value); return (int)0;} + GLEEPFNGLXGETFBCONFIGATTRIBPROC GLeeFuncPtr_glXGetFBConfigAttrib=GLee_Lazy_glXGetFBConfigAttrib; +#endif +#ifndef GLEE_C_DEFINED_glXGetVisualFromFBConfig +#define GLEE_C_DEFINED_glXGetVisualFromFBConfig + XVisualInfo * __stdcall GLee_Lazy_glXGetVisualFromFBConfig(Display * dpy, GLXFBConfig config) {if (GLeeInit()) return glXGetVisualFromFBConfig(dpy, config); return (XVisualInfo *)0;} + GLEEPFNGLXGETVISUALFROMFBCONFIGPROC GLeeFuncPtr_glXGetVisualFromFBConfig=GLee_Lazy_glXGetVisualFromFBConfig; +#endif +#ifndef GLEE_C_DEFINED_glXCreateWindow +#define GLEE_C_DEFINED_glXCreateWindow + GLXWindow __stdcall GLee_Lazy_glXCreateWindow(Display * dpy, GLXFBConfig config, Window win, const int * attrib_list) {if (GLeeInit()) return glXCreateWindow(dpy, config, win, attrib_list); return (GLXWindow)0;} + GLEEPFNGLXCREATEWINDOWPROC GLeeFuncPtr_glXCreateWindow=GLee_Lazy_glXCreateWindow; +#endif +#ifndef GLEE_C_DEFINED_glXDestroyWindow +#define GLEE_C_DEFINED_glXDestroyWindow + void __stdcall GLee_Lazy_glXDestroyWindow(Display * dpy, GLXWindow win) {if (GLeeInit()) glXDestroyWindow(dpy, win);} + GLEEPFNGLXDESTROYWINDOWPROC GLeeFuncPtr_glXDestroyWindow=GLee_Lazy_glXDestroyWindow; +#endif +#ifndef GLEE_C_DEFINED_glXCreatePixmap +#define GLEE_C_DEFINED_glXCreatePixmap + GLXPixmap __stdcall GLee_Lazy_glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap, const int * attrib_list) {if (GLeeInit()) return glXCreatePixmap(dpy, config, pixmap, attrib_list); return (GLXPixmap)0;} + GLEEPFNGLXCREATEPIXMAPPROC GLeeFuncPtr_glXCreatePixmap=GLee_Lazy_glXCreatePixmap; +#endif +#ifndef GLEE_C_DEFINED_glXDestroyPixmap +#define GLEE_C_DEFINED_glXDestroyPixmap + void __stdcall GLee_Lazy_glXDestroyPixmap(Display * dpy, GLXPixmap pixmap) {if (GLeeInit()) glXDestroyPixmap(dpy, pixmap);} + GLEEPFNGLXDESTROYPIXMAPPROC GLeeFuncPtr_glXDestroyPixmap=GLee_Lazy_glXDestroyPixmap; +#endif +#ifndef GLEE_C_DEFINED_glXCreatePbuffer +#define GLEE_C_DEFINED_glXCreatePbuffer + GLXPbuffer __stdcall GLee_Lazy_glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int * attrib_list) {if (GLeeInit()) return glXCreatePbuffer(dpy, config, attrib_list); return (GLXPbuffer)0;} + GLEEPFNGLXCREATEPBUFFERPROC GLeeFuncPtr_glXCreatePbuffer=GLee_Lazy_glXCreatePbuffer; +#endif +#ifndef GLEE_C_DEFINED_glXDestroyPbuffer +#define GLEE_C_DEFINED_glXDestroyPbuffer + void __stdcall GLee_Lazy_glXDestroyPbuffer(Display * dpy, GLXPbuffer pbuf) {if (GLeeInit()) glXDestroyPbuffer(dpy, pbuf);} + GLEEPFNGLXDESTROYPBUFFERPROC GLeeFuncPtr_glXDestroyPbuffer=GLee_Lazy_glXDestroyPbuffer; +#endif +#ifndef GLEE_C_DEFINED_glXQueryDrawable +#define GLEE_C_DEFINED_glXQueryDrawable + void __stdcall GLee_Lazy_glXQueryDrawable(Display * dpy, GLXDrawable draw, int attribute, unsigned int * value) {if (GLeeInit()) glXQueryDrawable(dpy, draw, attribute, value);} + GLEEPFNGLXQUERYDRAWABLEPROC GLeeFuncPtr_glXQueryDrawable=GLee_Lazy_glXQueryDrawable; +#endif +#ifndef GLEE_C_DEFINED_glXCreateNewContext +#define GLEE_C_DEFINED_glXCreateNewContext + GLXContext __stdcall GLee_Lazy_glXCreateNewContext(Display * dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct) {if (GLeeInit()) return glXCreateNewContext(dpy, config, render_type, share_list, direct); return (GLXContext)0;} + GLEEPFNGLXCREATENEWCONTEXTPROC GLeeFuncPtr_glXCreateNewContext=GLee_Lazy_glXCreateNewContext; +#endif +#ifndef GLEE_C_DEFINED_glXMakeContextCurrent +#define GLEE_C_DEFINED_glXMakeContextCurrent + Bool __stdcall GLee_Lazy_glXMakeContextCurrent(Display * dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx) {if (GLeeInit()) return glXMakeContextCurrent(dpy, draw, read, ctx); return (Bool)0;} + GLEEPFNGLXMAKECONTEXTCURRENTPROC GLeeFuncPtr_glXMakeContextCurrent=GLee_Lazy_glXMakeContextCurrent; +#endif +#ifndef GLEE_C_DEFINED_glXGetCurrentReadDrawable +#define GLEE_C_DEFINED_glXGetCurrentReadDrawable + GLXDrawable __stdcall GLee_Lazy_glXGetCurrentReadDrawable(void) {if (GLeeInit()) return glXGetCurrentReadDrawable(); return (GLXDrawable)0;} + GLEEPFNGLXGETCURRENTREADDRAWABLEPROC GLeeFuncPtr_glXGetCurrentReadDrawable=GLee_Lazy_glXGetCurrentReadDrawable; +#endif +#ifndef GLEE_C_DEFINED_glXGetCurrentDisplay +#define GLEE_C_DEFINED_glXGetCurrentDisplay + Display * __stdcall GLee_Lazy_glXGetCurrentDisplay(void) {if (GLeeInit()) return glXGetCurrentDisplay(); return (Display *)0;} + GLEEPFNGLXGETCURRENTDISPLAYPROC GLeeFuncPtr_glXGetCurrentDisplay=GLee_Lazy_glXGetCurrentDisplay; +#endif +#ifndef GLEE_C_DEFINED_glXQueryContext +#define GLEE_C_DEFINED_glXQueryContext + int __stdcall GLee_Lazy_glXQueryContext(Display * dpy, GLXContext ctx, int attribute, int * value) {if (GLeeInit()) return glXQueryContext(dpy, ctx, attribute, value); return (int)0;} + GLEEPFNGLXQUERYCONTEXTPROC GLeeFuncPtr_glXQueryContext=GLee_Lazy_glXQueryContext; +#endif +#ifndef GLEE_C_DEFINED_glXSelectEvent +#define GLEE_C_DEFINED_glXSelectEvent + void __stdcall GLee_Lazy_glXSelectEvent(Display * dpy, GLXDrawable draw, unsigned long event_mask) {if (GLeeInit()) glXSelectEvent(dpy, draw, event_mask);} + GLEEPFNGLXSELECTEVENTPROC GLeeFuncPtr_glXSelectEvent=GLee_Lazy_glXSelectEvent; +#endif +#ifndef GLEE_C_DEFINED_glXGetSelectedEvent +#define GLEE_C_DEFINED_glXGetSelectedEvent + void __stdcall GLee_Lazy_glXGetSelectedEvent(Display * dpy, GLXDrawable draw, unsigned long * event_mask) {if (GLeeInit()) glXGetSelectedEvent(dpy, draw, event_mask);} + GLEEPFNGLXGETSELECTEDEVENTPROC GLeeFuncPtr_glXGetSelectedEvent=GLee_Lazy_glXGetSelectedEvent; +#endif +#endif + +/* GLX_VERSION_1_4 */ + +#ifdef __GLEE_GLX_VERSION_1_4 +#ifndef GLEE_C_DEFINED_glXGetProcAddress +#define GLEE_C_DEFINED_glXGetProcAddress + __GLXextFuncPtr __stdcall GLee_Lazy_glXGetProcAddress(const GLubyte * procName) {if (GLeeInit()) return glXGetProcAddress(procName); return (__GLXextFuncPtr)0;} + GLEEPFNGLXGETPROCADDRESSPROC GLeeFuncPtr_glXGetProcAddress=GLee_Lazy_glXGetProcAddress; +#endif +#endif + +/* GLX_ARB_multisample */ + +#ifdef __GLEE_GLX_ARB_multisample +#endif + +/* GLX_ARB_fbconfig_float */ + +#ifdef __GLEE_GLX_ARB_fbconfig_float +#endif + +/* GLX_ARB_create_context */ + +#ifdef __GLEE_GLX_ARB_create_context +#ifndef GLEE_C_DEFINED_glXCreateContextAttribsARB +#define GLEE_C_DEFINED_glXCreateContextAttribsARB + GLXContext __stdcall GLee_Lazy_glXCreateContextAttribsARB(Display * dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int * attrib_list) {if (GLeeInit()) return glXCreateContextAttribsARB(dpy, config, share_context, direct, attrib_list); return (GLXContext)0;} + GLEEPFNGLXCREATECONTEXTATTRIBSARBPROC GLeeFuncPtr_glXCreateContextAttribsARB=GLee_Lazy_glXCreateContextAttribsARB; +#endif +#endif + +/* GLX_SGIS_multisample */ + +#ifdef __GLEE_GLX_SGIS_multisample +#endif + +/* GLX_EXT_visual_info */ + +#ifdef __GLEE_GLX_EXT_visual_info +#endif + +/* GLX_SGI_swap_control */ + +#ifdef __GLEE_GLX_SGI_swap_control +#ifndef GLEE_C_DEFINED_glXSwapIntervalSGI +#define GLEE_C_DEFINED_glXSwapIntervalSGI + int __stdcall GLee_Lazy_glXSwapIntervalSGI(int interval) {if (GLeeInit()) return glXSwapIntervalSGI(interval); return (int)0;} + GLEEPFNGLXSWAPINTERVALSGIPROC GLeeFuncPtr_glXSwapIntervalSGI=GLee_Lazy_glXSwapIntervalSGI; +#endif +#endif + +/* GLX_SGI_video_sync */ + +#ifdef __GLEE_GLX_SGI_video_sync +#ifndef GLEE_C_DEFINED_glXGetVideoSyncSGI +#define GLEE_C_DEFINED_glXGetVideoSyncSGI + int __stdcall GLee_Lazy_glXGetVideoSyncSGI(unsigned int * count) {if (GLeeInit()) return glXGetVideoSyncSGI(count); return (int)0;} + GLEEPFNGLXGETVIDEOSYNCSGIPROC GLeeFuncPtr_glXGetVideoSyncSGI=GLee_Lazy_glXGetVideoSyncSGI; +#endif +#ifndef GLEE_C_DEFINED_glXWaitVideoSyncSGI +#define GLEE_C_DEFINED_glXWaitVideoSyncSGI + int __stdcall GLee_Lazy_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int * count) {if (GLeeInit()) return glXWaitVideoSyncSGI(divisor, remainder, count); return (int)0;} + GLEEPFNGLXWAITVIDEOSYNCSGIPROC GLeeFuncPtr_glXWaitVideoSyncSGI=GLee_Lazy_glXWaitVideoSyncSGI; +#endif +#endif + +/* GLX_SGI_make_current_read */ + +#ifdef __GLEE_GLX_SGI_make_current_read +#ifndef GLEE_C_DEFINED_glXMakeCurrentReadSGI +#define GLEE_C_DEFINED_glXMakeCurrentReadSGI + Bool __stdcall GLee_Lazy_glXMakeCurrentReadSGI(Display * dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx) {if (GLeeInit()) return glXMakeCurrentReadSGI(dpy, draw, read, ctx); return (Bool)0;} + GLEEPFNGLXMAKECURRENTREADSGIPROC GLeeFuncPtr_glXMakeCurrentReadSGI=GLee_Lazy_glXMakeCurrentReadSGI; +#endif +#ifndef GLEE_C_DEFINED_glXGetCurrentReadDrawableSGI +#define GLEE_C_DEFINED_glXGetCurrentReadDrawableSGI + GLXDrawable __stdcall GLee_Lazy_glXGetCurrentReadDrawableSGI(void) {if (GLeeInit()) return glXGetCurrentReadDrawableSGI(); return (GLXDrawable)0;} + GLEEPFNGLXGETCURRENTREADDRAWABLESGIPROC GLeeFuncPtr_glXGetCurrentReadDrawableSGI=GLee_Lazy_glXGetCurrentReadDrawableSGI; +#endif +#endif + +/* GLX_EXT_visual_rating */ + +#ifdef __GLEE_GLX_EXT_visual_rating +#endif + +/* GLX_EXT_import_context */ + +#ifdef __GLEE_GLX_EXT_import_context +#ifndef GLEE_C_DEFINED_glXGetCurrentDisplayEXT +#define GLEE_C_DEFINED_glXGetCurrentDisplayEXT + Display * __stdcall GLee_Lazy_glXGetCurrentDisplayEXT(void) {if (GLeeInit()) return glXGetCurrentDisplayEXT(); return (Display *)0;} + GLEEPFNGLXGETCURRENTDISPLAYEXTPROC GLeeFuncPtr_glXGetCurrentDisplayEXT=GLee_Lazy_glXGetCurrentDisplayEXT; +#endif +#ifndef GLEE_C_DEFINED_glXQueryContextInfoEXT +#define GLEE_C_DEFINED_glXQueryContextInfoEXT + int __stdcall GLee_Lazy_glXQueryContextInfoEXT(Display * dpy, GLXContext context, int attribute, int * value) {if (GLeeInit()) return glXQueryContextInfoEXT(dpy, context, attribute, value); return (int)0;} + GLEEPFNGLXQUERYCONTEXTINFOEXTPROC GLeeFuncPtr_glXQueryContextInfoEXT=GLee_Lazy_glXQueryContextInfoEXT; +#endif +#ifndef GLEE_C_DEFINED_glXGetContextIDEXT +#define GLEE_C_DEFINED_glXGetContextIDEXT + GLXContextID __stdcall GLee_Lazy_glXGetContextIDEXT(const GLXContext context) {if (GLeeInit()) return glXGetContextIDEXT(context); return (GLXContextID)0;} + GLEEPFNGLXGETCONTEXTIDEXTPROC GLeeFuncPtr_glXGetContextIDEXT=GLee_Lazy_glXGetContextIDEXT; +#endif +#ifndef GLEE_C_DEFINED_glXImportContextEXT +#define GLEE_C_DEFINED_glXImportContextEXT + GLXContext __stdcall GLee_Lazy_glXImportContextEXT(Display * dpy, GLXContextID contextID) {if (GLeeInit()) return glXImportContextEXT(dpy, contextID); return (GLXContext)0;} + GLEEPFNGLXIMPORTCONTEXTEXTPROC GLeeFuncPtr_glXImportContextEXT=GLee_Lazy_glXImportContextEXT; +#endif +#ifndef GLEE_C_DEFINED_glXFreeContextEXT +#define GLEE_C_DEFINED_glXFreeContextEXT + void __stdcall GLee_Lazy_glXFreeContextEXT(Display * dpy, GLXContext context) {if (GLeeInit()) glXFreeContextEXT(dpy, context);} + GLEEPFNGLXFREECONTEXTEXTPROC GLeeFuncPtr_glXFreeContextEXT=GLee_Lazy_glXFreeContextEXT; +#endif +#endif + +/* GLX_SGIX_fbconfig */ + +#ifdef __GLEE_GLX_SGIX_fbconfig +#ifndef GLEE_C_DEFINED_glXGetFBConfigAttribSGIX +#define GLEE_C_DEFINED_glXGetFBConfigAttribSGIX + int __stdcall GLee_Lazy_glXGetFBConfigAttribSGIX(Display * dpy, GLXFBConfigSGIX config, int attribute, int * value) {if (GLeeInit()) return glXGetFBConfigAttribSGIX(dpy, config, attribute, value); return (int)0;} + GLEEPFNGLXGETFBCONFIGATTRIBSGIXPROC GLeeFuncPtr_glXGetFBConfigAttribSGIX=GLee_Lazy_glXGetFBConfigAttribSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXChooseFBConfigSGIX +#define GLEE_C_DEFINED_glXChooseFBConfigSGIX + GLXFBConfigSGIX * __stdcall GLee_Lazy_glXChooseFBConfigSGIX(Display * dpy, int screen, int * attrib_list, int * nelements) {if (GLeeInit()) return glXChooseFBConfigSGIX(dpy, screen, attrib_list, nelements); return (GLXFBConfigSGIX *)0;} + GLEEPFNGLXCHOOSEFBCONFIGSGIXPROC GLeeFuncPtr_glXChooseFBConfigSGIX=GLee_Lazy_glXChooseFBConfigSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXCreateGLXPixmapWithConfigSGIX +#define GLEE_C_DEFINED_glXCreateGLXPixmapWithConfigSGIX + GLXPixmap __stdcall GLee_Lazy_glXCreateGLXPixmapWithConfigSGIX(Display * dpy, GLXFBConfigSGIX config, Pixmap pixmap) {if (GLeeInit()) return glXCreateGLXPixmapWithConfigSGIX(dpy, config, pixmap); return (GLXPixmap)0;} + GLEEPFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC GLeeFuncPtr_glXCreateGLXPixmapWithConfigSGIX=GLee_Lazy_glXCreateGLXPixmapWithConfigSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXCreateContextWithConfigSGIX +#define GLEE_C_DEFINED_glXCreateContextWithConfigSGIX + GLXContext __stdcall GLee_Lazy_glXCreateContextWithConfigSGIX(Display * dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct) {if (GLeeInit()) return glXCreateContextWithConfigSGIX(dpy, config, render_type, share_list, direct); return (GLXContext)0;} + GLEEPFNGLXCREATECONTEXTWITHCONFIGSGIXPROC GLeeFuncPtr_glXCreateContextWithConfigSGIX=GLee_Lazy_glXCreateContextWithConfigSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXGetVisualFromFBConfigSGIX +#define GLEE_C_DEFINED_glXGetVisualFromFBConfigSGIX + XVisualInfo * __stdcall GLee_Lazy_glXGetVisualFromFBConfigSGIX(Display * dpy, GLXFBConfigSGIX config) {if (GLeeInit()) return glXGetVisualFromFBConfigSGIX(dpy, config); return (XVisualInfo *)0;} + GLEEPFNGLXGETVISUALFROMFBCONFIGSGIXPROC GLeeFuncPtr_glXGetVisualFromFBConfigSGIX=GLee_Lazy_glXGetVisualFromFBConfigSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXGetFBConfigFromVisualSGIX +#define GLEE_C_DEFINED_glXGetFBConfigFromVisualSGIX + GLXFBConfigSGIX __stdcall GLee_Lazy_glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis) {if (GLeeInit()) return glXGetFBConfigFromVisualSGIX(dpy, vis); return (GLXFBConfigSGIX)0;} + GLEEPFNGLXGETFBCONFIGFROMVISUALSGIXPROC GLeeFuncPtr_glXGetFBConfigFromVisualSGIX=GLee_Lazy_glXGetFBConfigFromVisualSGIX; +#endif +#endif + +/* GLX_SGIX_pbuffer */ + +#ifdef __GLEE_GLX_SGIX_pbuffer +#ifndef GLEE_C_DEFINED_glXCreateGLXPbufferSGIX +#define GLEE_C_DEFINED_glXCreateGLXPbufferSGIX + GLXPbufferSGIX __stdcall GLee_Lazy_glXCreateGLXPbufferSGIX(Display * dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int * attrib_list) {if (GLeeInit()) return glXCreateGLXPbufferSGIX(dpy, config, width, height, attrib_list); return (GLXPbufferSGIX)0;} + GLEEPFNGLXCREATEGLXPBUFFERSGIXPROC GLeeFuncPtr_glXCreateGLXPbufferSGIX=GLee_Lazy_glXCreateGLXPbufferSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXDestroyGLXPbufferSGIX +#define GLEE_C_DEFINED_glXDestroyGLXPbufferSGIX + void __stdcall GLee_Lazy_glXDestroyGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX pbuf) {if (GLeeInit()) glXDestroyGLXPbufferSGIX(dpy, pbuf);} + GLEEPFNGLXDESTROYGLXPBUFFERSGIXPROC GLeeFuncPtr_glXDestroyGLXPbufferSGIX=GLee_Lazy_glXDestroyGLXPbufferSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXQueryGLXPbufferSGIX +#define GLEE_C_DEFINED_glXQueryGLXPbufferSGIX + int __stdcall GLee_Lazy_glXQueryGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int * value) {if (GLeeInit()) return glXQueryGLXPbufferSGIX(dpy, pbuf, attribute, value); return (int)0;} + GLEEPFNGLXQUERYGLXPBUFFERSGIXPROC GLeeFuncPtr_glXQueryGLXPbufferSGIX=GLee_Lazy_glXQueryGLXPbufferSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXSelectEventSGIX +#define GLEE_C_DEFINED_glXSelectEventSGIX + void __stdcall GLee_Lazy_glXSelectEventSGIX(Display * dpy, GLXDrawable drawable, unsigned long mask) {if (GLeeInit()) glXSelectEventSGIX(dpy, drawable, mask);} + GLEEPFNGLXSELECTEVENTSGIXPROC GLeeFuncPtr_glXSelectEventSGIX=GLee_Lazy_glXSelectEventSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXGetSelectedEventSGIX +#define GLEE_C_DEFINED_glXGetSelectedEventSGIX + void __stdcall GLee_Lazy_glXGetSelectedEventSGIX(Display * dpy, GLXDrawable drawable, unsigned long * mask) {if (GLeeInit()) glXGetSelectedEventSGIX(dpy, drawable, mask);} + GLEEPFNGLXGETSELECTEDEVENTSGIXPROC GLeeFuncPtr_glXGetSelectedEventSGIX=GLee_Lazy_glXGetSelectedEventSGIX; +#endif +#endif + +/* GLX_SGI_cushion */ + +#ifdef __GLEE_GLX_SGI_cushion +#ifndef GLEE_C_DEFINED_glXCushionSGI +#define GLEE_C_DEFINED_glXCushionSGI + void __stdcall GLee_Lazy_glXCushionSGI(Display * dpy, Window window, float cushion) {if (GLeeInit()) glXCushionSGI(dpy, window, cushion);} + GLEEPFNGLXCUSHIONSGIPROC GLeeFuncPtr_glXCushionSGI=GLee_Lazy_glXCushionSGI; +#endif +#endif + +/* GLX_SGIX_video_resize */ + +#ifdef __GLEE_GLX_SGIX_video_resize +#ifndef GLEE_C_DEFINED_glXBindChannelToWindowSGIX +#define GLEE_C_DEFINED_glXBindChannelToWindowSGIX + int __stdcall GLee_Lazy_glXBindChannelToWindowSGIX(Display * display, int screen, int channel, Window window) {if (GLeeInit()) return glXBindChannelToWindowSGIX(display, screen, channel, window); return (int)0;} + GLEEPFNGLXBINDCHANNELTOWINDOWSGIXPROC GLeeFuncPtr_glXBindChannelToWindowSGIX=GLee_Lazy_glXBindChannelToWindowSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXChannelRectSGIX +#define GLEE_C_DEFINED_glXChannelRectSGIX + int __stdcall GLee_Lazy_glXChannelRectSGIX(Display * display, int screen, int channel, int x, int y, int w, int h) {if (GLeeInit()) return glXChannelRectSGIX(display, screen, channel, x, y, w, h); return (int)0;} + GLEEPFNGLXCHANNELRECTSGIXPROC GLeeFuncPtr_glXChannelRectSGIX=GLee_Lazy_glXChannelRectSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXQueryChannelRectSGIX +#define GLEE_C_DEFINED_glXQueryChannelRectSGIX + int __stdcall GLee_Lazy_glXQueryChannelRectSGIX(Display * display, int screen, int channel, int * dx, int * dy, int * dw, int * dh) {if (GLeeInit()) return glXQueryChannelRectSGIX(display, screen, channel, dx, dy, dw, dh); return (int)0;} + GLEEPFNGLXQUERYCHANNELRECTSGIXPROC GLeeFuncPtr_glXQueryChannelRectSGIX=GLee_Lazy_glXQueryChannelRectSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXQueryChannelDeltasSGIX +#define GLEE_C_DEFINED_glXQueryChannelDeltasSGIX + int __stdcall GLee_Lazy_glXQueryChannelDeltasSGIX(Display * display, int screen, int channel, int * x, int * y, int * w, int * h) {if (GLeeInit()) return glXQueryChannelDeltasSGIX(display, screen, channel, x, y, w, h); return (int)0;} + GLEEPFNGLXQUERYCHANNELDELTASSGIXPROC GLeeFuncPtr_glXQueryChannelDeltasSGIX=GLee_Lazy_glXQueryChannelDeltasSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXChannelRectSyncSGIX +#define GLEE_C_DEFINED_glXChannelRectSyncSGIX + int __stdcall GLee_Lazy_glXChannelRectSyncSGIX(Display * display, int screen, int channel, GLenum synctype) {if (GLeeInit()) return glXChannelRectSyncSGIX(display, screen, channel, synctype); return (int)0;} + GLEEPFNGLXCHANNELRECTSYNCSGIXPROC GLeeFuncPtr_glXChannelRectSyncSGIX=GLee_Lazy_glXChannelRectSyncSGIX; +#endif +#endif + +/* GLX_SGIX_swap_group */ + +#ifdef __GLEE_GLX_SGIX_swap_group +#ifndef GLEE_C_DEFINED_glXJoinSwapGroupSGIX +#define GLEE_C_DEFINED_glXJoinSwapGroupSGIX + void __stdcall GLee_Lazy_glXJoinSwapGroupSGIX(Display * dpy, GLXDrawable drawable, GLXDrawable member) {if (GLeeInit()) glXJoinSwapGroupSGIX(dpy, drawable, member);} + GLEEPFNGLXJOINSWAPGROUPSGIXPROC GLeeFuncPtr_glXJoinSwapGroupSGIX=GLee_Lazy_glXJoinSwapGroupSGIX; +#endif +#endif + +/* GLX_SGIX_swap_barrier */ + +#ifdef __GLEE_GLX_SGIX_swap_barrier +#ifndef GLEE_C_DEFINED_glXBindSwapBarrierSGIX +#define GLEE_C_DEFINED_glXBindSwapBarrierSGIX + void __stdcall GLee_Lazy_glXBindSwapBarrierSGIX(Display * dpy, GLXDrawable drawable, int barrier) {if (GLeeInit()) glXBindSwapBarrierSGIX(dpy, drawable, barrier);} + GLEEPFNGLXBINDSWAPBARRIERSGIXPROC GLeeFuncPtr_glXBindSwapBarrierSGIX=GLee_Lazy_glXBindSwapBarrierSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXQueryMaxSwapBarriersSGIX +#define GLEE_C_DEFINED_glXQueryMaxSwapBarriersSGIX + Bool __stdcall GLee_Lazy_glXQueryMaxSwapBarriersSGIX(Display * dpy, int screen, int * max) {if (GLeeInit()) return glXQueryMaxSwapBarriersSGIX(dpy, screen, max); return (Bool)0;} + GLEEPFNGLXQUERYMAXSWAPBARRIERSSGIXPROC GLeeFuncPtr_glXQueryMaxSwapBarriersSGIX=GLee_Lazy_glXQueryMaxSwapBarriersSGIX; +#endif +#endif + +/* GLX_SGIS_blended_overlay */ + +#ifdef __GLEE_GLX_SGIS_blended_overlay +#endif + +/* GLX_SGIS_shared_multisample */ + +#ifdef __GLEE_GLX_SGIS_shared_multisample +#endif + +/* GLX_SUN_get_transparent_index */ + +#ifdef __GLEE_GLX_SUN_get_transparent_index +#ifndef GLEE_C_DEFINED_glXGetTransparentIndexSUN +#define GLEE_C_DEFINED_glXGetTransparentIndexSUN + Status __stdcall GLee_Lazy_glXGetTransparentIndexSUN(Display * dpy, Window overlay, Window underlay, long * pTransparentIndex) {if (GLeeInit()) return glXGetTransparentIndexSUN(dpy, overlay, underlay, pTransparentIndex); return (Status)0;} + GLEEPFNGLXGETTRANSPARENTINDEXSUNPROC GLeeFuncPtr_glXGetTransparentIndexSUN=GLee_Lazy_glXGetTransparentIndexSUN; +#endif +#endif + +/* GLX_3DFX_multisample */ + +#ifdef __GLEE_GLX_3DFX_multisample +#endif + +/* GLX_MESA_copy_sub_buffer */ + +#ifdef __GLEE_GLX_MESA_copy_sub_buffer +#ifndef GLEE_C_DEFINED_glXCopySubBufferMESA +#define GLEE_C_DEFINED_glXCopySubBufferMESA + void __stdcall GLee_Lazy_glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable, int x, int y, int width, int height) {if (GLeeInit()) glXCopySubBufferMESA(dpy, drawable, x, y, width, height);} + GLEEPFNGLXCOPYSUBBUFFERMESAPROC GLeeFuncPtr_glXCopySubBufferMESA=GLee_Lazy_glXCopySubBufferMESA; +#endif +#endif + +/* GLX_MESA_pixmap_colormap */ + +#ifdef __GLEE_GLX_MESA_pixmap_colormap +#ifndef GLEE_C_DEFINED_glXCreateGLXPixmapMESA +#define GLEE_C_DEFINED_glXCreateGLXPixmapMESA + GLXPixmap __stdcall GLee_Lazy_glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual, Pixmap pixmap, Colormap cmap) {if (GLeeInit()) return glXCreateGLXPixmapMESA(dpy, visual, pixmap, cmap); return (GLXPixmap)0;} + GLEEPFNGLXCREATEGLXPIXMAPMESAPROC GLeeFuncPtr_glXCreateGLXPixmapMESA=GLee_Lazy_glXCreateGLXPixmapMESA; +#endif +#endif + +/* GLX_MESA_release_buffers */ + +#ifdef __GLEE_GLX_MESA_release_buffers +#ifndef GLEE_C_DEFINED_glXReleaseBuffersMESA +#define GLEE_C_DEFINED_glXReleaseBuffersMESA + Bool __stdcall GLee_Lazy_glXReleaseBuffersMESA(Display * dpy, GLXDrawable drawable) {if (GLeeInit()) return glXReleaseBuffersMESA(dpy, drawable); return (Bool)0;} + GLEEPFNGLXRELEASEBUFFERSMESAPROC GLeeFuncPtr_glXReleaseBuffersMESA=GLee_Lazy_glXReleaseBuffersMESA; +#endif +#endif + +/* GLX_MESA_set_3dfx_mode */ + +#ifdef __GLEE_GLX_MESA_set_3dfx_mode +#ifndef GLEE_C_DEFINED_glXSet3DfxModeMESA +#define GLEE_C_DEFINED_glXSet3DfxModeMESA + Bool __stdcall GLee_Lazy_glXSet3DfxModeMESA(int mode) {if (GLeeInit()) return glXSet3DfxModeMESA(mode); return (Bool)0;} + GLEEPFNGLXSET3DFXMODEMESAPROC GLeeFuncPtr_glXSet3DfxModeMESA=GLee_Lazy_glXSet3DfxModeMESA; +#endif +#endif + +/* GLX_SGIX_visual_select_group */ + +#ifdef __GLEE_GLX_SGIX_visual_select_group +#endif + +/* GLX_OML_swap_method */ + +#ifdef __GLEE_GLX_OML_swap_method +#endif + +/* GLX_OML_sync_control */ + +#ifdef __GLEE_GLX_OML_sync_control +#ifndef GLEE_C_DEFINED_glXGetSyncValuesOML +#define GLEE_C_DEFINED_glXGetSyncValuesOML + Bool __stdcall GLee_Lazy_glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable, int64_t * ust, int64_t * msc, int64_t * sbc) {if (GLeeInit()) return glXGetSyncValuesOML(dpy, drawable, ust, msc, sbc); return (Bool)0;} + GLEEPFNGLXGETSYNCVALUESOMLPROC GLeeFuncPtr_glXGetSyncValuesOML=GLee_Lazy_glXGetSyncValuesOML; +#endif +#ifndef GLEE_C_DEFINED_glXGetMscRateOML +#define GLEE_C_DEFINED_glXGetMscRateOML + Bool __stdcall GLee_Lazy_glXGetMscRateOML(Display * dpy, GLXDrawable drawable, int32_t * numerator, int32_t * denominator) {if (GLeeInit()) return glXGetMscRateOML(dpy, drawable, numerator, denominator); return (Bool)0;} + GLEEPFNGLXGETMSCRATEOMLPROC GLeeFuncPtr_glXGetMscRateOML=GLee_Lazy_glXGetMscRateOML; +#endif +#ifndef GLEE_C_DEFINED_glXSwapBuffersMscOML +#define GLEE_C_DEFINED_glXSwapBuffersMscOML + int64_t __stdcall GLee_Lazy_glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder) {if (GLeeInit()) return glXSwapBuffersMscOML(dpy, drawable, target_msc, divisor, remainder); return (int64_t)0;} + GLEEPFNGLXSWAPBUFFERSMSCOMLPROC GLeeFuncPtr_glXSwapBuffersMscOML=GLee_Lazy_glXSwapBuffersMscOML; +#endif +#ifndef GLEE_C_DEFINED_glXWaitForMscOML +#define GLEE_C_DEFINED_glXWaitForMscOML + Bool __stdcall GLee_Lazy_glXWaitForMscOML(Display * dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t * ust, int64_t * msc, int64_t * sbc) {if (GLeeInit()) return glXWaitForMscOML(dpy, drawable, target_msc, divisor, remainder, ust, msc, sbc); return (Bool)0;} + GLEEPFNGLXWAITFORMSCOMLPROC GLeeFuncPtr_glXWaitForMscOML=GLee_Lazy_glXWaitForMscOML; +#endif +#ifndef GLEE_C_DEFINED_glXWaitForSbcOML +#define GLEE_C_DEFINED_glXWaitForSbcOML + Bool __stdcall GLee_Lazy_glXWaitForSbcOML(Display * dpy, GLXDrawable drawable, int64_t target_sbc, int64_t * ust, int64_t * msc, int64_t * sbc) {if (GLeeInit()) return glXWaitForSbcOML(dpy, drawable, target_sbc, ust, msc, sbc); return (Bool)0;} + GLEEPFNGLXWAITFORSBCOMLPROC GLeeFuncPtr_glXWaitForSbcOML=GLee_Lazy_glXWaitForSbcOML; +#endif +#endif + +/* GLX_NV_float_buffer */ + +#ifdef __GLEE_GLX_NV_float_buffer +#endif + +/* GLX_SGIX_hyperpipe */ + +#ifdef __GLEE_GLX_SGIX_hyperpipe +#ifndef GLEE_C_DEFINED_glXQueryHyperpipeNetworkSGIX +#define GLEE_C_DEFINED_glXQueryHyperpipeNetworkSGIX + GLXHyperpipeNetworkSGIX * __stdcall GLee_Lazy_glXQueryHyperpipeNetworkSGIX(Display * dpy, int * npipes) {if (GLeeInit()) return glXQueryHyperpipeNetworkSGIX(dpy, npipes); return (GLXHyperpipeNetworkSGIX *)0;} + GLEEPFNGLXQUERYHYPERPIPENETWORKSGIXPROC GLeeFuncPtr_glXQueryHyperpipeNetworkSGIX=GLee_Lazy_glXQueryHyperpipeNetworkSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXHyperpipeConfigSGIX +#define GLEE_C_DEFINED_glXHyperpipeConfigSGIX + int __stdcall GLee_Lazy_glXHyperpipeConfigSGIX(Display * dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX * cfg, int * hpId) {if (GLeeInit()) return glXHyperpipeConfigSGIX(dpy, networkId, npipes, cfg, hpId); return (int)0;} + GLEEPFNGLXHYPERPIPECONFIGSGIXPROC GLeeFuncPtr_glXHyperpipeConfigSGIX=GLee_Lazy_glXHyperpipeConfigSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXQueryHyperpipeConfigSGIX +#define GLEE_C_DEFINED_glXQueryHyperpipeConfigSGIX + GLXHyperpipeConfigSGIX * __stdcall GLee_Lazy_glXQueryHyperpipeConfigSGIX(Display * dpy, int hpId, int * npipes) {if (GLeeInit()) return glXQueryHyperpipeConfigSGIX(dpy, hpId, npipes); return (GLXHyperpipeConfigSGIX *)0;} + GLEEPFNGLXQUERYHYPERPIPECONFIGSGIXPROC GLeeFuncPtr_glXQueryHyperpipeConfigSGIX=GLee_Lazy_glXQueryHyperpipeConfigSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXDestroyHyperpipeConfigSGIX +#define GLEE_C_DEFINED_glXDestroyHyperpipeConfigSGIX + int __stdcall GLee_Lazy_glXDestroyHyperpipeConfigSGIX(Display * dpy, int hpId) {if (GLeeInit()) return glXDestroyHyperpipeConfigSGIX(dpy, hpId); return (int)0;} + GLEEPFNGLXDESTROYHYPERPIPECONFIGSGIXPROC GLeeFuncPtr_glXDestroyHyperpipeConfigSGIX=GLee_Lazy_glXDestroyHyperpipeConfigSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXBindHyperpipeSGIX +#define GLEE_C_DEFINED_glXBindHyperpipeSGIX + int __stdcall GLee_Lazy_glXBindHyperpipeSGIX(Display * dpy, int hpId) {if (GLeeInit()) return glXBindHyperpipeSGIX(dpy, hpId); return (int)0;} + GLEEPFNGLXBINDHYPERPIPESGIXPROC GLeeFuncPtr_glXBindHyperpipeSGIX=GLee_Lazy_glXBindHyperpipeSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXQueryHyperpipeBestAttribSGIX +#define GLEE_C_DEFINED_glXQueryHyperpipeBestAttribSGIX + int __stdcall GLee_Lazy_glXQueryHyperpipeBestAttribSGIX(Display * dpy, int timeSlice, int attrib, int size, void * attribList, void * returnAttribList) {if (GLeeInit()) return glXQueryHyperpipeBestAttribSGIX(dpy, timeSlice, attrib, size, attribList, returnAttribList); return (int)0;} + GLEEPFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC GLeeFuncPtr_glXQueryHyperpipeBestAttribSGIX=GLee_Lazy_glXQueryHyperpipeBestAttribSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXHyperpipeAttribSGIX +#define GLEE_C_DEFINED_glXHyperpipeAttribSGIX + int __stdcall GLee_Lazy_glXHyperpipeAttribSGIX(Display * dpy, int timeSlice, int attrib, int size, void * attribList) {if (GLeeInit()) return glXHyperpipeAttribSGIX(dpy, timeSlice, attrib, size, attribList); return (int)0;} + GLEEPFNGLXHYPERPIPEATTRIBSGIXPROC GLeeFuncPtr_glXHyperpipeAttribSGIX=GLee_Lazy_glXHyperpipeAttribSGIX; +#endif +#ifndef GLEE_C_DEFINED_glXQueryHyperpipeAttribSGIX +#define GLEE_C_DEFINED_glXQueryHyperpipeAttribSGIX + int __stdcall GLee_Lazy_glXQueryHyperpipeAttribSGIX(Display * dpy, int timeSlice, int attrib, int size, void * returnAttribList) {if (GLeeInit()) return glXQueryHyperpipeAttribSGIX(dpy, timeSlice, attrib, size, returnAttribList); return (int)0;} + GLEEPFNGLXQUERYHYPERPIPEATTRIBSGIXPROC GLeeFuncPtr_glXQueryHyperpipeAttribSGIX=GLee_Lazy_glXQueryHyperpipeAttribSGIX; +#endif +#endif + +/* GLX_MESA_agp_offset */ + +#ifdef __GLEE_GLX_MESA_agp_offset +#ifndef GLEE_C_DEFINED_glXGetAGPOffsetMESA +#define GLEE_C_DEFINED_glXGetAGPOffsetMESA + unsigned int __stdcall GLee_Lazy_glXGetAGPOffsetMESA(const void * pointer) {if (GLeeInit()) return glXGetAGPOffsetMESA(pointer); return (unsigned int)0;} + GLEEPFNGLXGETAGPOFFSETMESAPROC GLeeFuncPtr_glXGetAGPOffsetMESA=GLee_Lazy_glXGetAGPOffsetMESA; +#endif +#endif + +/* GLX_EXT_fbconfig_packed_float */ + +#ifdef __GLEE_GLX_EXT_fbconfig_packed_float +#endif + +/* GLX_EXT_framebuffer_sRGB */ + +#ifdef __GLEE_GLX_EXT_framebuffer_sRGB +#endif + +/* GLX_EXT_texture_from_pixmap */ + +#ifdef __GLEE_GLX_EXT_texture_from_pixmap +#ifndef GLEE_C_DEFINED_glXBindTexImageEXT +#define GLEE_C_DEFINED_glXBindTexImageEXT + void __stdcall GLee_Lazy_glXBindTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer, const int * attrib_list) {if (GLeeInit()) glXBindTexImageEXT(dpy, drawable, buffer, attrib_list);} + GLEEPFNGLXBINDTEXIMAGEEXTPROC GLeeFuncPtr_glXBindTexImageEXT=GLee_Lazy_glXBindTexImageEXT; +#endif +#ifndef GLEE_C_DEFINED_glXReleaseTexImageEXT +#define GLEE_C_DEFINED_glXReleaseTexImageEXT + void __stdcall GLee_Lazy_glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer) {if (GLeeInit()) glXReleaseTexImageEXT(dpy, drawable, buffer);} + GLEEPFNGLXRELEASETEXIMAGEEXTPROC GLeeFuncPtr_glXReleaseTexImageEXT=GLee_Lazy_glXReleaseTexImageEXT; +#endif +#endif + +/* GLX_NV_present_video */ + +#ifdef __GLEE_GLX_NV_present_video +#endif + +/* GLX_NV_video_out */ + +#ifdef __GLEE_GLX_NV_video_out +#endif + +/* GLX_NV_swap_group */ + +#ifdef __GLEE_GLX_NV_swap_group +#endif + +/* GLX_EXT_scene_marker */ + +#ifdef __GLEE_GLX_EXT_scene_marker +#endif + +/* GLX_NV_video_output */ + +#ifdef __GLEE_GLX_NV_video_output +#ifndef GLEE_C_DEFINED_glXGetVideoDeviceNV +#define GLEE_C_DEFINED_glXGetVideoDeviceNV + int __stdcall GLee_Lazy_glXGetVideoDeviceNV(Display * dpy, int screen, int numVideoDevices, GLXVideoDeviceNV * pVideoDevice) {if (GLeeInit()) return glXGetVideoDeviceNV(dpy, screen, numVideoDevices, pVideoDevice); return (int)0;} + GLEEPFNGLXGETVIDEODEVICENVPROC GLeeFuncPtr_glXGetVideoDeviceNV=GLee_Lazy_glXGetVideoDeviceNV; +#endif +#ifndef GLEE_C_DEFINED_glXReleaseVideoDeviceNV +#define GLEE_C_DEFINED_glXReleaseVideoDeviceNV + int __stdcall GLee_Lazy_glXReleaseVideoDeviceNV(Display * dpy, int screen, GLXVideoDeviceNV VideoDevice) {if (GLeeInit()) return glXReleaseVideoDeviceNV(dpy, screen, VideoDevice); return (int)0;} + GLEEPFNGLXRELEASEVIDEODEVICENVPROC GLeeFuncPtr_glXReleaseVideoDeviceNV=GLee_Lazy_glXReleaseVideoDeviceNV; +#endif +#ifndef GLEE_C_DEFINED_glXBindVideoImageNV +#define GLEE_C_DEFINED_glXBindVideoImageNV + int __stdcall GLee_Lazy_glXBindVideoImageNV(Display * dpy, GLXVideoDeviceNV VideoDevice, GLXPbuffer pbuf, int iVideoBuffer) {if (GLeeInit()) return glXBindVideoImageNV(dpy, VideoDevice, pbuf, iVideoBuffer); return (int)0;} + GLEEPFNGLXBINDVIDEOIMAGENVPROC GLeeFuncPtr_glXBindVideoImageNV=GLee_Lazy_glXBindVideoImageNV; +#endif +#ifndef GLEE_C_DEFINED_glXReleaseVideoImageNV +#define GLEE_C_DEFINED_glXReleaseVideoImageNV + int __stdcall GLee_Lazy_glXReleaseVideoImageNV(Display * dpy, GLXPbuffer pbuf) {if (GLeeInit()) return glXReleaseVideoImageNV(dpy, pbuf); return (int)0;} + GLEEPFNGLXRELEASEVIDEOIMAGENVPROC GLeeFuncPtr_glXReleaseVideoImageNV=GLee_Lazy_glXReleaseVideoImageNV; +#endif +#ifndef GLEE_C_DEFINED_glXSendPbufferToVideoNV +#define GLEE_C_DEFINED_glXSendPbufferToVideoNV + int __stdcall GLee_Lazy_glXSendPbufferToVideoNV(Display * dpy, GLXPbuffer pbuf, int iBufferType, unsigned long * pulCounterPbuffer, GLboolean bBlock) {if (GLeeInit()) return glXSendPbufferToVideoNV(dpy, pbuf, iBufferType, pulCounterPbuffer, bBlock); return (int)0;} + GLEEPFNGLXSENDPBUFFERTOVIDEONVPROC GLeeFuncPtr_glXSendPbufferToVideoNV=GLee_Lazy_glXSendPbufferToVideoNV; +#endif +#ifndef GLEE_C_DEFINED_glXGetVideoInfoNV +#define GLEE_C_DEFINED_glXGetVideoInfoNV + int __stdcall GLee_Lazy_glXGetVideoInfoNV(Display * dpy, int screen, GLXVideoDeviceNV VideoDevice, unsigned long * pulCounterOutputPbuffer, unsigned long * pulCounterOutputVideo) {if (GLeeInit()) return glXGetVideoInfoNV(dpy, screen, VideoDevice, pulCounterOutputPbuffer, pulCounterOutputVideo); return (int)0;} + GLEEPFNGLXGETVIDEOINFONVPROC GLeeFuncPtr_glXGetVideoInfoNV=GLee_Lazy_glXGetVideoInfoNV; +#endif +#endif +#endif /* end GLX */ +/***************************************************************** +* Extension link functions +*****************************************************************/ + +GLuint __GLeeLink_GL_VERSION_1_2(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_VERSION_1_2 + if ((GLeeFuncPtr_glBlendColor = (GLEEPFNGLBLENDCOLORPROC) __GLeeGetProcAddress("glBlendColor"))!=0) nLinked++; + if ((GLeeFuncPtr_glBlendEquation = (GLEEPFNGLBLENDEQUATIONPROC) __GLeeGetProcAddress("glBlendEquation"))!=0) nLinked++; + if ((GLeeFuncPtr_glDrawRangeElements = (GLEEPFNGLDRAWRANGEELEMENTSPROC) __GLeeGetProcAddress("glDrawRangeElements"))!=0) nLinked++; + if ((GLeeFuncPtr_glColorTable = (GLEEPFNGLCOLORTABLEPROC) __GLeeGetProcAddress("glColorTable"))!=0) nLinked++; + if ((GLeeFuncPtr_glColorTableParameterfv = (GLEEPFNGLCOLORTABLEPARAMETERFVPROC) __GLeeGetProcAddress("glColorTableParameterfv"))!=0) nLinked++; + if ((GLeeFuncPtr_glColorTableParameteriv = (GLEEPFNGLCOLORTABLEPARAMETERIVPROC) __GLeeGetProcAddress("glColorTableParameteriv"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyColorTable = (GLEEPFNGLCOPYCOLORTABLEPROC) __GLeeGetProcAddress("glCopyColorTable"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetColorTable = (GLEEPFNGLGETCOLORTABLEPROC) __GLeeGetProcAddress("glGetColorTable"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetColorTableParameterfv = (GLEEPFNGLGETCOLORTABLEPARAMETERFVPROC) __GLeeGetProcAddress("glGetColorTableParameterfv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetColorTableParameteriv = (GLEEPFNGLGETCOLORTABLEPARAMETERIVPROC) __GLeeGetProcAddress("glGetColorTableParameteriv"))!=0) nLinked++; + if ((GLeeFuncPtr_glColorSubTable = (GLEEPFNGLCOLORSUBTABLEPROC) __GLeeGetProcAddress("glColorSubTable"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyColorSubTable = (GLEEPFNGLCOPYCOLORSUBTABLEPROC) __GLeeGetProcAddress("glCopyColorSubTable"))!=0) nLinked++; + if ((GLeeFuncPtr_glConvolutionFilter1D = (GLEEPFNGLCONVOLUTIONFILTER1DPROC) __GLeeGetProcAddress("glConvolutionFilter1D"))!=0) nLinked++; + if ((GLeeFuncPtr_glConvolutionFilter2D = (GLEEPFNGLCONVOLUTIONFILTER2DPROC) __GLeeGetProcAddress("glConvolutionFilter2D"))!=0) nLinked++; + if ((GLeeFuncPtr_glConvolutionParameterf = (GLEEPFNGLCONVOLUTIONPARAMETERFPROC) __GLeeGetProcAddress("glConvolutionParameterf"))!=0) nLinked++; + if ((GLeeFuncPtr_glConvolutionParameterfv = (GLEEPFNGLCONVOLUTIONPARAMETERFVPROC) __GLeeGetProcAddress("glConvolutionParameterfv"))!=0) nLinked++; + if ((GLeeFuncPtr_glConvolutionParameteri = (GLEEPFNGLCONVOLUTIONPARAMETERIPROC) __GLeeGetProcAddress("glConvolutionParameteri"))!=0) nLinked++; + if ((GLeeFuncPtr_glConvolutionParameteriv = (GLEEPFNGLCONVOLUTIONPARAMETERIVPROC) __GLeeGetProcAddress("glConvolutionParameteriv"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyConvolutionFilter1D = (GLEEPFNGLCOPYCONVOLUTIONFILTER1DPROC) __GLeeGetProcAddress("glCopyConvolutionFilter1D"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyConvolutionFilter2D = (GLEEPFNGLCOPYCONVOLUTIONFILTER2DPROC) __GLeeGetProcAddress("glCopyConvolutionFilter2D"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetConvolutionFilter = (GLEEPFNGLGETCONVOLUTIONFILTERPROC) __GLeeGetProcAddress("glGetConvolutionFilter"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetConvolutionParameterfv = (GLEEPFNGLGETCONVOLUTIONPARAMETERFVPROC) __GLeeGetProcAddress("glGetConvolutionParameterfv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetConvolutionParameteriv = (GLEEPFNGLGETCONVOLUTIONPARAMETERIVPROC) __GLeeGetProcAddress("glGetConvolutionParameteriv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetSeparableFilter = (GLEEPFNGLGETSEPARABLEFILTERPROC) __GLeeGetProcAddress("glGetSeparableFilter"))!=0) nLinked++; + if ((GLeeFuncPtr_glSeparableFilter2D = (GLEEPFNGLSEPARABLEFILTER2DPROC) __GLeeGetProcAddress("glSeparableFilter2D"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetHistogram = (GLEEPFNGLGETHISTOGRAMPROC) __GLeeGetProcAddress("glGetHistogram"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetHistogramParameterfv = (GLEEPFNGLGETHISTOGRAMPARAMETERFVPROC) __GLeeGetProcAddress("glGetHistogramParameterfv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetHistogramParameteriv = (GLEEPFNGLGETHISTOGRAMPARAMETERIVPROC) __GLeeGetProcAddress("glGetHistogramParameteriv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMinmax = (GLEEPFNGLGETMINMAXPROC) __GLeeGetProcAddress("glGetMinmax"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMinmaxParameterfv = (GLEEPFNGLGETMINMAXPARAMETERFVPROC) __GLeeGetProcAddress("glGetMinmaxParameterfv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMinmaxParameteriv = (GLEEPFNGLGETMINMAXPARAMETERIVPROC) __GLeeGetProcAddress("glGetMinmaxParameteriv"))!=0) nLinked++; + if ((GLeeFuncPtr_glHistogram = (GLEEPFNGLHISTOGRAMPROC) __GLeeGetProcAddress("glHistogram"))!=0) nLinked++; + if ((GLeeFuncPtr_glMinmax = (GLEEPFNGLMINMAXPROC) __GLeeGetProcAddress("glMinmax"))!=0) nLinked++; + if ((GLeeFuncPtr_glResetHistogram = (GLEEPFNGLRESETHISTOGRAMPROC) __GLeeGetProcAddress("glResetHistogram"))!=0) nLinked++; + if ((GLeeFuncPtr_glResetMinmax = (GLEEPFNGLRESETMINMAXPROC) __GLeeGetProcAddress("glResetMinmax"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexImage3D = (GLEEPFNGLTEXIMAGE3DPROC) __GLeeGetProcAddress("glTexImage3D"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexSubImage3D = (GLEEPFNGLTEXSUBIMAGE3DPROC) __GLeeGetProcAddress("glTexSubImage3D"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyTexSubImage3D = (GLEEPFNGLCOPYTEXSUBIMAGE3DPROC) __GLeeGetProcAddress("glCopyTexSubImage3D"))!=0) nLinked++; +#endif + if (nLinked==38) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_imaging(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_VERSION_1_3(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_VERSION_1_3 + if ((GLeeFuncPtr_glActiveTexture = (GLEEPFNGLACTIVETEXTUREPROC) __GLeeGetProcAddress("glActiveTexture"))!=0) nLinked++; + if ((GLeeFuncPtr_glClientActiveTexture = (GLEEPFNGLCLIENTACTIVETEXTUREPROC) __GLeeGetProcAddress("glClientActiveTexture"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1d = (GLEEPFNGLMULTITEXCOORD1DPROC) __GLeeGetProcAddress("glMultiTexCoord1d"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1dv = (GLEEPFNGLMULTITEXCOORD1DVPROC) __GLeeGetProcAddress("glMultiTexCoord1dv"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1f = (GLEEPFNGLMULTITEXCOORD1FPROC) __GLeeGetProcAddress("glMultiTexCoord1f"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1fv = (GLEEPFNGLMULTITEXCOORD1FVPROC) __GLeeGetProcAddress("glMultiTexCoord1fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1i = (GLEEPFNGLMULTITEXCOORD1IPROC) __GLeeGetProcAddress("glMultiTexCoord1i"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1iv = (GLEEPFNGLMULTITEXCOORD1IVPROC) __GLeeGetProcAddress("glMultiTexCoord1iv"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1s = (GLEEPFNGLMULTITEXCOORD1SPROC) __GLeeGetProcAddress("glMultiTexCoord1s"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1sv = (GLEEPFNGLMULTITEXCOORD1SVPROC) __GLeeGetProcAddress("glMultiTexCoord1sv"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2d = (GLEEPFNGLMULTITEXCOORD2DPROC) __GLeeGetProcAddress("glMultiTexCoord2d"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2dv = (GLEEPFNGLMULTITEXCOORD2DVPROC) __GLeeGetProcAddress("glMultiTexCoord2dv"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2f = (GLEEPFNGLMULTITEXCOORD2FPROC) __GLeeGetProcAddress("glMultiTexCoord2f"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2fv = (GLEEPFNGLMULTITEXCOORD2FVPROC) __GLeeGetProcAddress("glMultiTexCoord2fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2i = (GLEEPFNGLMULTITEXCOORD2IPROC) __GLeeGetProcAddress("glMultiTexCoord2i"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2iv = (GLEEPFNGLMULTITEXCOORD2IVPROC) __GLeeGetProcAddress("glMultiTexCoord2iv"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2s = (GLEEPFNGLMULTITEXCOORD2SPROC) __GLeeGetProcAddress("glMultiTexCoord2s"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2sv = (GLEEPFNGLMULTITEXCOORD2SVPROC) __GLeeGetProcAddress("glMultiTexCoord2sv"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3d = (GLEEPFNGLMULTITEXCOORD3DPROC) __GLeeGetProcAddress("glMultiTexCoord3d"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3dv = (GLEEPFNGLMULTITEXCOORD3DVPROC) __GLeeGetProcAddress("glMultiTexCoord3dv"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3f = (GLEEPFNGLMULTITEXCOORD3FPROC) __GLeeGetProcAddress("glMultiTexCoord3f"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3fv = (GLEEPFNGLMULTITEXCOORD3FVPROC) __GLeeGetProcAddress("glMultiTexCoord3fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3i = (GLEEPFNGLMULTITEXCOORD3IPROC) __GLeeGetProcAddress("glMultiTexCoord3i"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3iv = (GLEEPFNGLMULTITEXCOORD3IVPROC) __GLeeGetProcAddress("glMultiTexCoord3iv"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3s = (GLEEPFNGLMULTITEXCOORD3SPROC) __GLeeGetProcAddress("glMultiTexCoord3s"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3sv = (GLEEPFNGLMULTITEXCOORD3SVPROC) __GLeeGetProcAddress("glMultiTexCoord3sv"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4d = (GLEEPFNGLMULTITEXCOORD4DPROC) __GLeeGetProcAddress("glMultiTexCoord4d"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4dv = (GLEEPFNGLMULTITEXCOORD4DVPROC) __GLeeGetProcAddress("glMultiTexCoord4dv"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4f = (GLEEPFNGLMULTITEXCOORD4FPROC) __GLeeGetProcAddress("glMultiTexCoord4f"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4fv = (GLEEPFNGLMULTITEXCOORD4FVPROC) __GLeeGetProcAddress("glMultiTexCoord4fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4i = (GLEEPFNGLMULTITEXCOORD4IPROC) __GLeeGetProcAddress("glMultiTexCoord4i"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4iv = (GLEEPFNGLMULTITEXCOORD4IVPROC) __GLeeGetProcAddress("glMultiTexCoord4iv"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4s = (GLEEPFNGLMULTITEXCOORD4SPROC) __GLeeGetProcAddress("glMultiTexCoord4s"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4sv = (GLEEPFNGLMULTITEXCOORD4SVPROC) __GLeeGetProcAddress("glMultiTexCoord4sv"))!=0) nLinked++; + if ((GLeeFuncPtr_glLoadTransposeMatrixf = (GLEEPFNGLLOADTRANSPOSEMATRIXFPROC) __GLeeGetProcAddress("glLoadTransposeMatrixf"))!=0) nLinked++; + if ((GLeeFuncPtr_glLoadTransposeMatrixd = (GLEEPFNGLLOADTRANSPOSEMATRIXDPROC) __GLeeGetProcAddress("glLoadTransposeMatrixd"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultTransposeMatrixf = (GLEEPFNGLMULTTRANSPOSEMATRIXFPROC) __GLeeGetProcAddress("glMultTransposeMatrixf"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultTransposeMatrixd = (GLEEPFNGLMULTTRANSPOSEMATRIXDPROC) __GLeeGetProcAddress("glMultTransposeMatrixd"))!=0) nLinked++; + if ((GLeeFuncPtr_glSampleCoverage = (GLEEPFNGLSAMPLECOVERAGEPROC) __GLeeGetProcAddress("glSampleCoverage"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTexImage3D = (GLEEPFNGLCOMPRESSEDTEXIMAGE3DPROC) __GLeeGetProcAddress("glCompressedTexImage3D"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTexImage2D = (GLEEPFNGLCOMPRESSEDTEXIMAGE2DPROC) __GLeeGetProcAddress("glCompressedTexImage2D"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTexImage1D = (GLEEPFNGLCOMPRESSEDTEXIMAGE1DPROC) __GLeeGetProcAddress("glCompressedTexImage1D"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTexSubImage3D = (GLEEPFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) __GLeeGetProcAddress("glCompressedTexSubImage3D"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTexSubImage2D = (GLEEPFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) __GLeeGetProcAddress("glCompressedTexSubImage2D"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTexSubImage1D = (GLEEPFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) __GLeeGetProcAddress("glCompressedTexSubImage1D"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetCompressedTexImage = (GLEEPFNGLGETCOMPRESSEDTEXIMAGEPROC) __GLeeGetProcAddress("glGetCompressedTexImage"))!=0) nLinked++; +#endif + if (nLinked==46) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_VERSION_1_4(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_VERSION_1_4 + if ((GLeeFuncPtr_glBlendFuncSeparate = (GLEEPFNGLBLENDFUNCSEPARATEPROC) __GLeeGetProcAddress("glBlendFuncSeparate"))!=0) nLinked++; + if ((GLeeFuncPtr_glFogCoordf = (GLEEPFNGLFOGCOORDFPROC) __GLeeGetProcAddress("glFogCoordf"))!=0) nLinked++; + if ((GLeeFuncPtr_glFogCoordfv = (GLEEPFNGLFOGCOORDFVPROC) __GLeeGetProcAddress("glFogCoordfv"))!=0) nLinked++; + if ((GLeeFuncPtr_glFogCoordd = (GLEEPFNGLFOGCOORDDPROC) __GLeeGetProcAddress("glFogCoordd"))!=0) nLinked++; + if ((GLeeFuncPtr_glFogCoorddv = (GLEEPFNGLFOGCOORDDVPROC) __GLeeGetProcAddress("glFogCoorddv"))!=0) nLinked++; + if ((GLeeFuncPtr_glFogCoordPointer = (GLEEPFNGLFOGCOORDPOINTERPROC) __GLeeGetProcAddress("glFogCoordPointer"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiDrawArrays = (GLEEPFNGLMULTIDRAWARRAYSPROC) __GLeeGetProcAddress("glMultiDrawArrays"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiDrawElements = (GLEEPFNGLMULTIDRAWELEMENTSPROC) __GLeeGetProcAddress("glMultiDrawElements"))!=0) nLinked++; + if ((GLeeFuncPtr_glPointParameterf = (GLEEPFNGLPOINTPARAMETERFPROC) __GLeeGetProcAddress("glPointParameterf"))!=0) nLinked++; + if ((GLeeFuncPtr_glPointParameterfv = (GLEEPFNGLPOINTPARAMETERFVPROC) __GLeeGetProcAddress("glPointParameterfv"))!=0) nLinked++; + if ((GLeeFuncPtr_glPointParameteri = (GLEEPFNGLPOINTPARAMETERIPROC) __GLeeGetProcAddress("glPointParameteri"))!=0) nLinked++; + if ((GLeeFuncPtr_glPointParameteriv = (GLEEPFNGLPOINTPARAMETERIVPROC) __GLeeGetProcAddress("glPointParameteriv"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3b = (GLEEPFNGLSECONDARYCOLOR3BPROC) __GLeeGetProcAddress("glSecondaryColor3b"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3bv = (GLEEPFNGLSECONDARYCOLOR3BVPROC) __GLeeGetProcAddress("glSecondaryColor3bv"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3d = (GLEEPFNGLSECONDARYCOLOR3DPROC) __GLeeGetProcAddress("glSecondaryColor3d"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3dv = (GLEEPFNGLSECONDARYCOLOR3DVPROC) __GLeeGetProcAddress("glSecondaryColor3dv"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3f = (GLEEPFNGLSECONDARYCOLOR3FPROC) __GLeeGetProcAddress("glSecondaryColor3f"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3fv = (GLEEPFNGLSECONDARYCOLOR3FVPROC) __GLeeGetProcAddress("glSecondaryColor3fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3i = (GLEEPFNGLSECONDARYCOLOR3IPROC) __GLeeGetProcAddress("glSecondaryColor3i"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3iv = (GLEEPFNGLSECONDARYCOLOR3IVPROC) __GLeeGetProcAddress("glSecondaryColor3iv"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3s = (GLEEPFNGLSECONDARYCOLOR3SPROC) __GLeeGetProcAddress("glSecondaryColor3s"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3sv = (GLEEPFNGLSECONDARYCOLOR3SVPROC) __GLeeGetProcAddress("glSecondaryColor3sv"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3ub = (GLEEPFNGLSECONDARYCOLOR3UBPROC) __GLeeGetProcAddress("glSecondaryColor3ub"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3ubv = (GLEEPFNGLSECONDARYCOLOR3UBVPROC) __GLeeGetProcAddress("glSecondaryColor3ubv"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3ui = (GLEEPFNGLSECONDARYCOLOR3UIPROC) __GLeeGetProcAddress("glSecondaryColor3ui"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3uiv = (GLEEPFNGLSECONDARYCOLOR3UIVPROC) __GLeeGetProcAddress("glSecondaryColor3uiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3us = (GLEEPFNGLSECONDARYCOLOR3USPROC) __GLeeGetProcAddress("glSecondaryColor3us"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3usv = (GLEEPFNGLSECONDARYCOLOR3USVPROC) __GLeeGetProcAddress("glSecondaryColor3usv"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColorPointer = (GLEEPFNGLSECONDARYCOLORPOINTERPROC) __GLeeGetProcAddress("glSecondaryColorPointer"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2d = (GLEEPFNGLWINDOWPOS2DPROC) __GLeeGetProcAddress("glWindowPos2d"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2dv = (GLEEPFNGLWINDOWPOS2DVPROC) __GLeeGetProcAddress("glWindowPos2dv"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2f = (GLEEPFNGLWINDOWPOS2FPROC) __GLeeGetProcAddress("glWindowPos2f"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2fv = (GLEEPFNGLWINDOWPOS2FVPROC) __GLeeGetProcAddress("glWindowPos2fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2i = (GLEEPFNGLWINDOWPOS2IPROC) __GLeeGetProcAddress("glWindowPos2i"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2iv = (GLEEPFNGLWINDOWPOS2IVPROC) __GLeeGetProcAddress("glWindowPos2iv"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2s = (GLEEPFNGLWINDOWPOS2SPROC) __GLeeGetProcAddress("glWindowPos2s"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2sv = (GLEEPFNGLWINDOWPOS2SVPROC) __GLeeGetProcAddress("glWindowPos2sv"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3d = (GLEEPFNGLWINDOWPOS3DPROC) __GLeeGetProcAddress("glWindowPos3d"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3dv = (GLEEPFNGLWINDOWPOS3DVPROC) __GLeeGetProcAddress("glWindowPos3dv"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3f = (GLEEPFNGLWINDOWPOS3FPROC) __GLeeGetProcAddress("glWindowPos3f"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3fv = (GLEEPFNGLWINDOWPOS3FVPROC) __GLeeGetProcAddress("glWindowPos3fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3i = (GLEEPFNGLWINDOWPOS3IPROC) __GLeeGetProcAddress("glWindowPos3i"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3iv = (GLEEPFNGLWINDOWPOS3IVPROC) __GLeeGetProcAddress("glWindowPos3iv"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3s = (GLEEPFNGLWINDOWPOS3SPROC) __GLeeGetProcAddress("glWindowPos3s"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3sv = (GLEEPFNGLWINDOWPOS3SVPROC) __GLeeGetProcAddress("glWindowPos3sv"))!=0) nLinked++; +#endif + if (nLinked==45) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_VERSION_1_5(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_VERSION_1_5 + if ((GLeeFuncPtr_glGenQueries = (GLEEPFNGLGENQUERIESPROC) __GLeeGetProcAddress("glGenQueries"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteQueries = (GLEEPFNGLDELETEQUERIESPROC) __GLeeGetProcAddress("glDeleteQueries"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsQuery = (GLEEPFNGLISQUERYPROC) __GLeeGetProcAddress("glIsQuery"))!=0) nLinked++; + if ((GLeeFuncPtr_glBeginQuery = (GLEEPFNGLBEGINQUERYPROC) __GLeeGetProcAddress("glBeginQuery"))!=0) nLinked++; + if ((GLeeFuncPtr_glEndQuery = (GLEEPFNGLENDQUERYPROC) __GLeeGetProcAddress("glEndQuery"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetQueryiv = (GLEEPFNGLGETQUERYIVPROC) __GLeeGetProcAddress("glGetQueryiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetQueryObjectiv = (GLEEPFNGLGETQUERYOBJECTIVPROC) __GLeeGetProcAddress("glGetQueryObjectiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetQueryObjectuiv = (GLEEPFNGLGETQUERYOBJECTUIVPROC) __GLeeGetProcAddress("glGetQueryObjectuiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindBuffer = (GLEEPFNGLBINDBUFFERPROC) __GLeeGetProcAddress("glBindBuffer"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteBuffers = (GLEEPFNGLDELETEBUFFERSPROC) __GLeeGetProcAddress("glDeleteBuffers"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenBuffers = (GLEEPFNGLGENBUFFERSPROC) __GLeeGetProcAddress("glGenBuffers"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsBuffer = (GLEEPFNGLISBUFFERPROC) __GLeeGetProcAddress("glIsBuffer"))!=0) nLinked++; + if ((GLeeFuncPtr_glBufferData = (GLEEPFNGLBUFFERDATAPROC) __GLeeGetProcAddress("glBufferData"))!=0) nLinked++; + if ((GLeeFuncPtr_glBufferSubData = (GLEEPFNGLBUFFERSUBDATAPROC) __GLeeGetProcAddress("glBufferSubData"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetBufferSubData = (GLEEPFNGLGETBUFFERSUBDATAPROC) __GLeeGetProcAddress("glGetBufferSubData"))!=0) nLinked++; + if ((GLeeFuncPtr_glMapBuffer = (GLEEPFNGLMAPBUFFERPROC) __GLeeGetProcAddress("glMapBuffer"))!=0) nLinked++; + if ((GLeeFuncPtr_glUnmapBuffer = (GLEEPFNGLUNMAPBUFFERPROC) __GLeeGetProcAddress("glUnmapBuffer"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetBufferParameteriv = (GLEEPFNGLGETBUFFERPARAMETERIVPROC) __GLeeGetProcAddress("glGetBufferParameteriv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetBufferPointerv = (GLEEPFNGLGETBUFFERPOINTERVPROC) __GLeeGetProcAddress("glGetBufferPointerv"))!=0) nLinked++; +#endif + if (nLinked==19) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_VERSION_2_0(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_VERSION_2_0 + if ((GLeeFuncPtr_glBlendEquationSeparate = (GLEEPFNGLBLENDEQUATIONSEPARATEPROC) __GLeeGetProcAddress("glBlendEquationSeparate"))!=0) nLinked++; + if ((GLeeFuncPtr_glDrawBuffers = (GLEEPFNGLDRAWBUFFERSPROC) __GLeeGetProcAddress("glDrawBuffers"))!=0) nLinked++; + if ((GLeeFuncPtr_glStencilOpSeparate = (GLEEPFNGLSTENCILOPSEPARATEPROC) __GLeeGetProcAddress("glStencilOpSeparate"))!=0) nLinked++; + if ((GLeeFuncPtr_glStencilFuncSeparate = (GLEEPFNGLSTENCILFUNCSEPARATEPROC) __GLeeGetProcAddress("glStencilFuncSeparate"))!=0) nLinked++; + if ((GLeeFuncPtr_glStencilMaskSeparate = (GLEEPFNGLSTENCILMASKSEPARATEPROC) __GLeeGetProcAddress("glStencilMaskSeparate"))!=0) nLinked++; + if ((GLeeFuncPtr_glAttachShader = (GLEEPFNGLATTACHSHADERPROC) __GLeeGetProcAddress("glAttachShader"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindAttribLocation = (GLEEPFNGLBINDATTRIBLOCATIONPROC) __GLeeGetProcAddress("glBindAttribLocation"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompileShader = (GLEEPFNGLCOMPILESHADERPROC) __GLeeGetProcAddress("glCompileShader"))!=0) nLinked++; + if ((GLeeFuncPtr_glCreateProgram = (GLEEPFNGLCREATEPROGRAMPROC) __GLeeGetProcAddress("glCreateProgram"))!=0) nLinked++; + if ((GLeeFuncPtr_glCreateShader = (GLEEPFNGLCREATESHADERPROC) __GLeeGetProcAddress("glCreateShader"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteProgram = (GLEEPFNGLDELETEPROGRAMPROC) __GLeeGetProcAddress("glDeleteProgram"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteShader = (GLEEPFNGLDELETESHADERPROC) __GLeeGetProcAddress("glDeleteShader"))!=0) nLinked++; + if ((GLeeFuncPtr_glDetachShader = (GLEEPFNGLDETACHSHADERPROC) __GLeeGetProcAddress("glDetachShader"))!=0) nLinked++; + if ((GLeeFuncPtr_glDisableVertexAttribArray = (GLEEPFNGLDISABLEVERTEXATTRIBARRAYPROC) __GLeeGetProcAddress("glDisableVertexAttribArray"))!=0) nLinked++; + if ((GLeeFuncPtr_glEnableVertexAttribArray = (GLEEPFNGLENABLEVERTEXATTRIBARRAYPROC) __GLeeGetProcAddress("glEnableVertexAttribArray"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetActiveAttrib = (GLEEPFNGLGETACTIVEATTRIBPROC) __GLeeGetProcAddress("glGetActiveAttrib"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetActiveUniform = (GLEEPFNGLGETACTIVEUNIFORMPROC) __GLeeGetProcAddress("glGetActiveUniform"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetAttachedShaders = (GLEEPFNGLGETATTACHEDSHADERSPROC) __GLeeGetProcAddress("glGetAttachedShaders"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetAttribLocation = (GLEEPFNGLGETATTRIBLOCATIONPROC) __GLeeGetProcAddress("glGetAttribLocation"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramiv = (GLEEPFNGLGETPROGRAMIVPROC) __GLeeGetProcAddress("glGetProgramiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramInfoLog = (GLEEPFNGLGETPROGRAMINFOLOGPROC) __GLeeGetProcAddress("glGetProgramInfoLog"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetShaderiv = (GLEEPFNGLGETSHADERIVPROC) __GLeeGetProcAddress("glGetShaderiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetShaderInfoLog = (GLEEPFNGLGETSHADERINFOLOGPROC) __GLeeGetProcAddress("glGetShaderInfoLog"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetShaderSource = (GLEEPFNGLGETSHADERSOURCEPROC) __GLeeGetProcAddress("glGetShaderSource"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetUniformLocation = (GLEEPFNGLGETUNIFORMLOCATIONPROC) __GLeeGetProcAddress("glGetUniformLocation"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetUniformfv = (GLEEPFNGLGETUNIFORMFVPROC) __GLeeGetProcAddress("glGetUniformfv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetUniformiv = (GLEEPFNGLGETUNIFORMIVPROC) __GLeeGetProcAddress("glGetUniformiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribdv = (GLEEPFNGLGETVERTEXATTRIBDVPROC) __GLeeGetProcAddress("glGetVertexAttribdv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribfv = (GLEEPFNGLGETVERTEXATTRIBFVPROC) __GLeeGetProcAddress("glGetVertexAttribfv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribiv = (GLEEPFNGLGETVERTEXATTRIBIVPROC) __GLeeGetProcAddress("glGetVertexAttribiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribPointerv = (GLEEPFNGLGETVERTEXATTRIBPOINTERVPROC) __GLeeGetProcAddress("glGetVertexAttribPointerv"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsProgram = (GLEEPFNGLISPROGRAMPROC) __GLeeGetProcAddress("glIsProgram"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsShader = (GLEEPFNGLISSHADERPROC) __GLeeGetProcAddress("glIsShader"))!=0) nLinked++; + if ((GLeeFuncPtr_glLinkProgram = (GLEEPFNGLLINKPROGRAMPROC) __GLeeGetProcAddress("glLinkProgram"))!=0) nLinked++; + if ((GLeeFuncPtr_glShaderSource = (GLEEPFNGLSHADERSOURCEPROC) __GLeeGetProcAddress("glShaderSource"))!=0) nLinked++; + if ((GLeeFuncPtr_glUseProgram = (GLEEPFNGLUSEPROGRAMPROC) __GLeeGetProcAddress("glUseProgram"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform1f = (GLEEPFNGLUNIFORM1FPROC) __GLeeGetProcAddress("glUniform1f"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform2f = (GLEEPFNGLUNIFORM2FPROC) __GLeeGetProcAddress("glUniform2f"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform3f = (GLEEPFNGLUNIFORM3FPROC) __GLeeGetProcAddress("glUniform3f"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform4f = (GLEEPFNGLUNIFORM4FPROC) __GLeeGetProcAddress("glUniform4f"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform1i = (GLEEPFNGLUNIFORM1IPROC) __GLeeGetProcAddress("glUniform1i"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform2i = (GLEEPFNGLUNIFORM2IPROC) __GLeeGetProcAddress("glUniform2i"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform3i = (GLEEPFNGLUNIFORM3IPROC) __GLeeGetProcAddress("glUniform3i"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform4i = (GLEEPFNGLUNIFORM4IPROC) __GLeeGetProcAddress("glUniform4i"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform1fv = (GLEEPFNGLUNIFORM1FVPROC) __GLeeGetProcAddress("glUniform1fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform2fv = (GLEEPFNGLUNIFORM2FVPROC) __GLeeGetProcAddress("glUniform2fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform3fv = (GLEEPFNGLUNIFORM3FVPROC) __GLeeGetProcAddress("glUniform3fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform4fv = (GLEEPFNGLUNIFORM4FVPROC) __GLeeGetProcAddress("glUniform4fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform1iv = (GLEEPFNGLUNIFORM1IVPROC) __GLeeGetProcAddress("glUniform1iv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform2iv = (GLEEPFNGLUNIFORM2IVPROC) __GLeeGetProcAddress("glUniform2iv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform3iv = (GLEEPFNGLUNIFORM3IVPROC) __GLeeGetProcAddress("glUniform3iv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform4iv = (GLEEPFNGLUNIFORM4IVPROC) __GLeeGetProcAddress("glUniform4iv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniformMatrix2fv = (GLEEPFNGLUNIFORMMATRIX2FVPROC) __GLeeGetProcAddress("glUniformMatrix2fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniformMatrix3fv = (GLEEPFNGLUNIFORMMATRIX3FVPROC) __GLeeGetProcAddress("glUniformMatrix3fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniformMatrix4fv = (GLEEPFNGLUNIFORMMATRIX4FVPROC) __GLeeGetProcAddress("glUniformMatrix4fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glValidateProgram = (GLEEPFNGLVALIDATEPROGRAMPROC) __GLeeGetProcAddress("glValidateProgram"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1d = (GLEEPFNGLVERTEXATTRIB1DPROC) __GLeeGetProcAddress("glVertexAttrib1d"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1dv = (GLEEPFNGLVERTEXATTRIB1DVPROC) __GLeeGetProcAddress("glVertexAttrib1dv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1f = (GLEEPFNGLVERTEXATTRIB1FPROC) __GLeeGetProcAddress("glVertexAttrib1f"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1fv = (GLEEPFNGLVERTEXATTRIB1FVPROC) __GLeeGetProcAddress("glVertexAttrib1fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1s = (GLEEPFNGLVERTEXATTRIB1SPROC) __GLeeGetProcAddress("glVertexAttrib1s"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1sv = (GLEEPFNGLVERTEXATTRIB1SVPROC) __GLeeGetProcAddress("glVertexAttrib1sv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2d = (GLEEPFNGLVERTEXATTRIB2DPROC) __GLeeGetProcAddress("glVertexAttrib2d"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2dv = (GLEEPFNGLVERTEXATTRIB2DVPROC) __GLeeGetProcAddress("glVertexAttrib2dv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2f = (GLEEPFNGLVERTEXATTRIB2FPROC) __GLeeGetProcAddress("glVertexAttrib2f"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2fv = (GLEEPFNGLVERTEXATTRIB2FVPROC) __GLeeGetProcAddress("glVertexAttrib2fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2s = (GLEEPFNGLVERTEXATTRIB2SPROC) __GLeeGetProcAddress("glVertexAttrib2s"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2sv = (GLEEPFNGLVERTEXATTRIB2SVPROC) __GLeeGetProcAddress("glVertexAttrib2sv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3d = (GLEEPFNGLVERTEXATTRIB3DPROC) __GLeeGetProcAddress("glVertexAttrib3d"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3dv = (GLEEPFNGLVERTEXATTRIB3DVPROC) __GLeeGetProcAddress("glVertexAttrib3dv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3f = (GLEEPFNGLVERTEXATTRIB3FPROC) __GLeeGetProcAddress("glVertexAttrib3f"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3fv = (GLEEPFNGLVERTEXATTRIB3FVPROC) __GLeeGetProcAddress("glVertexAttrib3fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3s = (GLEEPFNGLVERTEXATTRIB3SPROC) __GLeeGetProcAddress("glVertexAttrib3s"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3sv = (GLEEPFNGLVERTEXATTRIB3SVPROC) __GLeeGetProcAddress("glVertexAttrib3sv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4Nbv = (GLEEPFNGLVERTEXATTRIB4NBVPROC) __GLeeGetProcAddress("glVertexAttrib4Nbv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4Niv = (GLEEPFNGLVERTEXATTRIB4NIVPROC) __GLeeGetProcAddress("glVertexAttrib4Niv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4Nsv = (GLEEPFNGLVERTEXATTRIB4NSVPROC) __GLeeGetProcAddress("glVertexAttrib4Nsv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4Nub = (GLEEPFNGLVERTEXATTRIB4NUBPROC) __GLeeGetProcAddress("glVertexAttrib4Nub"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4Nubv = (GLEEPFNGLVERTEXATTRIB4NUBVPROC) __GLeeGetProcAddress("glVertexAttrib4Nubv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4Nuiv = (GLEEPFNGLVERTEXATTRIB4NUIVPROC) __GLeeGetProcAddress("glVertexAttrib4Nuiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4Nusv = (GLEEPFNGLVERTEXATTRIB4NUSVPROC) __GLeeGetProcAddress("glVertexAttrib4Nusv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4bv = (GLEEPFNGLVERTEXATTRIB4BVPROC) __GLeeGetProcAddress("glVertexAttrib4bv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4d = (GLEEPFNGLVERTEXATTRIB4DPROC) __GLeeGetProcAddress("glVertexAttrib4d"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4dv = (GLEEPFNGLVERTEXATTRIB4DVPROC) __GLeeGetProcAddress("glVertexAttrib4dv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4f = (GLEEPFNGLVERTEXATTRIB4FPROC) __GLeeGetProcAddress("glVertexAttrib4f"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4fv = (GLEEPFNGLVERTEXATTRIB4FVPROC) __GLeeGetProcAddress("glVertexAttrib4fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4iv = (GLEEPFNGLVERTEXATTRIB4IVPROC) __GLeeGetProcAddress("glVertexAttrib4iv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4s = (GLEEPFNGLVERTEXATTRIB4SPROC) __GLeeGetProcAddress("glVertexAttrib4s"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4sv = (GLEEPFNGLVERTEXATTRIB4SVPROC) __GLeeGetProcAddress("glVertexAttrib4sv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4ubv = (GLEEPFNGLVERTEXATTRIB4UBVPROC) __GLeeGetProcAddress("glVertexAttrib4ubv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4uiv = (GLEEPFNGLVERTEXATTRIB4UIVPROC) __GLeeGetProcAddress("glVertexAttrib4uiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4usv = (GLEEPFNGLVERTEXATTRIB4USVPROC) __GLeeGetProcAddress("glVertexAttrib4usv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribPointer = (GLEEPFNGLVERTEXATTRIBPOINTERPROC) __GLeeGetProcAddress("glVertexAttribPointer"))!=0) nLinked++; +#endif + if (nLinked==93) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_VERSION_2_1(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_VERSION_2_1 + if ((GLeeFuncPtr_glUniformMatrix2x3fv = (GLEEPFNGLUNIFORMMATRIX2X3FVPROC) __GLeeGetProcAddress("glUniformMatrix2x3fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniformMatrix3x2fv = (GLEEPFNGLUNIFORMMATRIX3X2FVPROC) __GLeeGetProcAddress("glUniformMatrix3x2fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniformMatrix2x4fv = (GLEEPFNGLUNIFORMMATRIX2X4FVPROC) __GLeeGetProcAddress("glUniformMatrix2x4fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniformMatrix4x2fv = (GLEEPFNGLUNIFORMMATRIX4X2FVPROC) __GLeeGetProcAddress("glUniformMatrix4x2fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniformMatrix3x4fv = (GLEEPFNGLUNIFORMMATRIX3X4FVPROC) __GLeeGetProcAddress("glUniformMatrix3x4fv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniformMatrix4x3fv = (GLEEPFNGLUNIFORMMATRIX4X3FVPROC) __GLeeGetProcAddress("glUniformMatrix4x3fv"))!=0) nLinked++; +#endif + if (nLinked==6) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_VERSION_3_0(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_VERSION_3_0 + if ((GLeeFuncPtr_glColorMaski = (GLEEPFNGLCOLORMASKIPROC) __GLeeGetProcAddress("glColorMaski"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetBooleani_v = (GLEEPFNGLGETBOOLEANI_VPROC) __GLeeGetProcAddress("glGetBooleani_v"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetIntegeri_v = (GLEEPFNGLGETINTEGERI_VPROC) __GLeeGetProcAddress("glGetIntegeri_v"))!=0) nLinked++; + if ((GLeeFuncPtr_glEnablei = (GLEEPFNGLENABLEIPROC) __GLeeGetProcAddress("glEnablei"))!=0) nLinked++; + if ((GLeeFuncPtr_glDisablei = (GLEEPFNGLDISABLEIPROC) __GLeeGetProcAddress("glDisablei"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsEnabledi = (GLEEPFNGLISENABLEDIPROC) __GLeeGetProcAddress("glIsEnabledi"))!=0) nLinked++; + if ((GLeeFuncPtr_glBeginTransformFeedback = (GLEEPFNGLBEGINTRANSFORMFEEDBACKPROC) __GLeeGetProcAddress("glBeginTransformFeedback"))!=0) nLinked++; + if ((GLeeFuncPtr_glEndTransformFeedback = (GLEEPFNGLENDTRANSFORMFEEDBACKPROC) __GLeeGetProcAddress("glEndTransformFeedback"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindBufferRange = (GLEEPFNGLBINDBUFFERRANGEPROC) __GLeeGetProcAddress("glBindBufferRange"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindBufferBase = (GLEEPFNGLBINDBUFFERBASEPROC) __GLeeGetProcAddress("glBindBufferBase"))!=0) nLinked++; + if ((GLeeFuncPtr_glTransformFeedbackVaryings = (GLEEPFNGLTRANSFORMFEEDBACKVARYINGSPROC) __GLeeGetProcAddress("glTransformFeedbackVaryings"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTransformFeedbackVarying = (GLEEPFNGLGETTRANSFORMFEEDBACKVARYINGPROC) __GLeeGetProcAddress("glGetTransformFeedbackVarying"))!=0) nLinked++; + if ((GLeeFuncPtr_glClampColor = (GLEEPFNGLCLAMPCOLORPROC) __GLeeGetProcAddress("glClampColor"))!=0) nLinked++; + if ((GLeeFuncPtr_glBeginConditionalRender = (GLEEPFNGLBEGINCONDITIONALRENDERPROC) __GLeeGetProcAddress("glBeginConditionalRender"))!=0) nLinked++; + if ((GLeeFuncPtr_glEndConditionalRender = (GLEEPFNGLENDCONDITIONALRENDERPROC) __GLeeGetProcAddress("glEndConditionalRender"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI1i = (GLEEPFNGLVERTEXATTRIBI1IPROC) __GLeeGetProcAddress("glVertexAttribI1i"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI2i = (GLEEPFNGLVERTEXATTRIBI2IPROC) __GLeeGetProcAddress("glVertexAttribI2i"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI3i = (GLEEPFNGLVERTEXATTRIBI3IPROC) __GLeeGetProcAddress("glVertexAttribI3i"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI4i = (GLEEPFNGLVERTEXATTRIBI4IPROC) __GLeeGetProcAddress("glVertexAttribI4i"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI1ui = (GLEEPFNGLVERTEXATTRIBI1UIPROC) __GLeeGetProcAddress("glVertexAttribI1ui"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI2ui = (GLEEPFNGLVERTEXATTRIBI2UIPROC) __GLeeGetProcAddress("glVertexAttribI2ui"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI3ui = (GLEEPFNGLVERTEXATTRIBI3UIPROC) __GLeeGetProcAddress("glVertexAttribI3ui"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI4ui = (GLEEPFNGLVERTEXATTRIBI4UIPROC) __GLeeGetProcAddress("glVertexAttribI4ui"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI1iv = (GLEEPFNGLVERTEXATTRIBI1IVPROC) __GLeeGetProcAddress("glVertexAttribI1iv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI2iv = (GLEEPFNGLVERTEXATTRIBI2IVPROC) __GLeeGetProcAddress("glVertexAttribI2iv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI3iv = (GLEEPFNGLVERTEXATTRIBI3IVPROC) __GLeeGetProcAddress("glVertexAttribI3iv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI4iv = (GLEEPFNGLVERTEXATTRIBI4IVPROC) __GLeeGetProcAddress("glVertexAttribI4iv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI1uiv = (GLEEPFNGLVERTEXATTRIBI1UIVPROC) __GLeeGetProcAddress("glVertexAttribI1uiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI2uiv = (GLEEPFNGLVERTEXATTRIBI2UIVPROC) __GLeeGetProcAddress("glVertexAttribI2uiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI3uiv = (GLEEPFNGLVERTEXATTRIBI3UIVPROC) __GLeeGetProcAddress("glVertexAttribI3uiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI4uiv = (GLEEPFNGLVERTEXATTRIBI4UIVPROC) __GLeeGetProcAddress("glVertexAttribI4uiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI4bv = (GLEEPFNGLVERTEXATTRIBI4BVPROC) __GLeeGetProcAddress("glVertexAttribI4bv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI4sv = (GLEEPFNGLVERTEXATTRIBI4SVPROC) __GLeeGetProcAddress("glVertexAttribI4sv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI4ubv = (GLEEPFNGLVERTEXATTRIBI4UBVPROC) __GLeeGetProcAddress("glVertexAttribI4ubv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI4usv = (GLEEPFNGLVERTEXATTRIBI4USVPROC) __GLeeGetProcAddress("glVertexAttribI4usv"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribIPointer = (GLEEPFNGLVERTEXATTRIBIPOINTERPROC) __GLeeGetProcAddress("glVertexAttribIPointer"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribIiv = (GLEEPFNGLGETVERTEXATTRIBIIVPROC) __GLeeGetProcAddress("glGetVertexAttribIiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribIuiv = (GLEEPFNGLGETVERTEXATTRIBIUIVPROC) __GLeeGetProcAddress("glGetVertexAttribIuiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetUniformuiv = (GLEEPFNGLGETUNIFORMUIVPROC) __GLeeGetProcAddress("glGetUniformuiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindFragDataLocation = (GLEEPFNGLBINDFRAGDATALOCATIONPROC) __GLeeGetProcAddress("glBindFragDataLocation"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFragDataLocation = (GLEEPFNGLGETFRAGDATALOCATIONPROC) __GLeeGetProcAddress("glGetFragDataLocation"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform1ui = (GLEEPFNGLUNIFORM1UIPROC) __GLeeGetProcAddress("glUniform1ui"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform2ui = (GLEEPFNGLUNIFORM2UIPROC) __GLeeGetProcAddress("glUniform2ui"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform3ui = (GLEEPFNGLUNIFORM3UIPROC) __GLeeGetProcAddress("glUniform3ui"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform4ui = (GLEEPFNGLUNIFORM4UIPROC) __GLeeGetProcAddress("glUniform4ui"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform1uiv = (GLEEPFNGLUNIFORM1UIVPROC) __GLeeGetProcAddress("glUniform1uiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform2uiv = (GLEEPFNGLUNIFORM2UIVPROC) __GLeeGetProcAddress("glUniform2uiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform3uiv = (GLEEPFNGLUNIFORM3UIVPROC) __GLeeGetProcAddress("glUniform3uiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform4uiv = (GLEEPFNGLUNIFORM4UIVPROC) __GLeeGetProcAddress("glUniform4uiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexParameterIiv = (GLEEPFNGLTEXPARAMETERIIVPROC) __GLeeGetProcAddress("glTexParameterIiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexParameterIuiv = (GLEEPFNGLTEXPARAMETERIUIVPROC) __GLeeGetProcAddress("glTexParameterIuiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTexParameterIiv = (GLEEPFNGLGETTEXPARAMETERIIVPROC) __GLeeGetProcAddress("glGetTexParameterIiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTexParameterIuiv = (GLEEPFNGLGETTEXPARAMETERIUIVPROC) __GLeeGetProcAddress("glGetTexParameterIuiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glClearBufferiv = (GLEEPFNGLCLEARBUFFERIVPROC) __GLeeGetProcAddress("glClearBufferiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glClearBufferuiv = (GLEEPFNGLCLEARBUFFERUIVPROC) __GLeeGetProcAddress("glClearBufferuiv"))!=0) nLinked++; + if ((GLeeFuncPtr_glClearBufferfv = (GLEEPFNGLCLEARBUFFERFVPROC) __GLeeGetProcAddress("glClearBufferfv"))!=0) nLinked++; + if ((GLeeFuncPtr_glClearBufferfi = (GLEEPFNGLCLEARBUFFERFIPROC) __GLeeGetProcAddress("glClearBufferfi"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetStringi = (GLEEPFNGLGETSTRINGIPROC) __GLeeGetProcAddress("glGetStringi"))!=0) nLinked++; +#endif + if (nLinked==58) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_multitexture(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_multitexture + if ((GLeeFuncPtr_glActiveTextureARB = (GLEEPFNGLACTIVETEXTUREARBPROC) __GLeeGetProcAddress("glActiveTextureARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glClientActiveTextureARB = (GLEEPFNGLCLIENTACTIVETEXTUREARBPROC) __GLeeGetProcAddress("glClientActiveTextureARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1dARB = (GLEEPFNGLMULTITEXCOORD1DARBPROC) __GLeeGetProcAddress("glMultiTexCoord1dARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1dvARB = (GLEEPFNGLMULTITEXCOORD1DVARBPROC) __GLeeGetProcAddress("glMultiTexCoord1dvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1fARB = (GLEEPFNGLMULTITEXCOORD1FARBPROC) __GLeeGetProcAddress("glMultiTexCoord1fARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1fvARB = (GLEEPFNGLMULTITEXCOORD1FVARBPROC) __GLeeGetProcAddress("glMultiTexCoord1fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1iARB = (GLEEPFNGLMULTITEXCOORD1IARBPROC) __GLeeGetProcAddress("glMultiTexCoord1iARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1ivARB = (GLEEPFNGLMULTITEXCOORD1IVARBPROC) __GLeeGetProcAddress("glMultiTexCoord1ivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1sARB = (GLEEPFNGLMULTITEXCOORD1SARBPROC) __GLeeGetProcAddress("glMultiTexCoord1sARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1svARB = (GLEEPFNGLMULTITEXCOORD1SVARBPROC) __GLeeGetProcAddress("glMultiTexCoord1svARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2dARB = (GLEEPFNGLMULTITEXCOORD2DARBPROC) __GLeeGetProcAddress("glMultiTexCoord2dARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2dvARB = (GLEEPFNGLMULTITEXCOORD2DVARBPROC) __GLeeGetProcAddress("glMultiTexCoord2dvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2fARB = (GLEEPFNGLMULTITEXCOORD2FARBPROC) __GLeeGetProcAddress("glMultiTexCoord2fARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2fvARB = (GLEEPFNGLMULTITEXCOORD2FVARBPROC) __GLeeGetProcAddress("glMultiTexCoord2fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2iARB = (GLEEPFNGLMULTITEXCOORD2IARBPROC) __GLeeGetProcAddress("glMultiTexCoord2iARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2ivARB = (GLEEPFNGLMULTITEXCOORD2IVARBPROC) __GLeeGetProcAddress("glMultiTexCoord2ivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2sARB = (GLEEPFNGLMULTITEXCOORD2SARBPROC) __GLeeGetProcAddress("glMultiTexCoord2sARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2svARB = (GLEEPFNGLMULTITEXCOORD2SVARBPROC) __GLeeGetProcAddress("glMultiTexCoord2svARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3dARB = (GLEEPFNGLMULTITEXCOORD3DARBPROC) __GLeeGetProcAddress("glMultiTexCoord3dARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3dvARB = (GLEEPFNGLMULTITEXCOORD3DVARBPROC) __GLeeGetProcAddress("glMultiTexCoord3dvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3fARB = (GLEEPFNGLMULTITEXCOORD3FARBPROC) __GLeeGetProcAddress("glMultiTexCoord3fARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3fvARB = (GLEEPFNGLMULTITEXCOORD3FVARBPROC) __GLeeGetProcAddress("glMultiTexCoord3fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3iARB = (GLEEPFNGLMULTITEXCOORD3IARBPROC) __GLeeGetProcAddress("glMultiTexCoord3iARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3ivARB = (GLEEPFNGLMULTITEXCOORD3IVARBPROC) __GLeeGetProcAddress("glMultiTexCoord3ivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3sARB = (GLEEPFNGLMULTITEXCOORD3SARBPROC) __GLeeGetProcAddress("glMultiTexCoord3sARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3svARB = (GLEEPFNGLMULTITEXCOORD3SVARBPROC) __GLeeGetProcAddress("glMultiTexCoord3svARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4dARB = (GLEEPFNGLMULTITEXCOORD4DARBPROC) __GLeeGetProcAddress("glMultiTexCoord4dARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4dvARB = (GLEEPFNGLMULTITEXCOORD4DVARBPROC) __GLeeGetProcAddress("glMultiTexCoord4dvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4fARB = (GLEEPFNGLMULTITEXCOORD4FARBPROC) __GLeeGetProcAddress("glMultiTexCoord4fARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4fvARB = (GLEEPFNGLMULTITEXCOORD4FVARBPROC) __GLeeGetProcAddress("glMultiTexCoord4fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4iARB = (GLEEPFNGLMULTITEXCOORD4IARBPROC) __GLeeGetProcAddress("glMultiTexCoord4iARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4ivARB = (GLEEPFNGLMULTITEXCOORD4IVARBPROC) __GLeeGetProcAddress("glMultiTexCoord4ivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4sARB = (GLEEPFNGLMULTITEXCOORD4SARBPROC) __GLeeGetProcAddress("glMultiTexCoord4sARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4svARB = (GLEEPFNGLMULTITEXCOORD4SVARBPROC) __GLeeGetProcAddress("glMultiTexCoord4svARB"))!=0) nLinked++; +#endif + if (nLinked==34) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_transpose_matrix(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_transpose_matrix + if ((GLeeFuncPtr_glLoadTransposeMatrixfARB = (GLEEPFNGLLOADTRANSPOSEMATRIXFARBPROC) __GLeeGetProcAddress("glLoadTransposeMatrixfARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glLoadTransposeMatrixdARB = (GLEEPFNGLLOADTRANSPOSEMATRIXDARBPROC) __GLeeGetProcAddress("glLoadTransposeMatrixdARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultTransposeMatrixfARB = (GLEEPFNGLMULTTRANSPOSEMATRIXFARBPROC) __GLeeGetProcAddress("glMultTransposeMatrixfARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultTransposeMatrixdARB = (GLEEPFNGLMULTTRANSPOSEMATRIXDARBPROC) __GLeeGetProcAddress("glMultTransposeMatrixdARB"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_multisample(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_multisample + if ((GLeeFuncPtr_glSampleCoverageARB = (GLEEPFNGLSAMPLECOVERAGEARBPROC) __GLeeGetProcAddress("glSampleCoverageARB"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_texture_env_add(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_texture_cube_map(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_texture_compression(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_texture_compression + if ((GLeeFuncPtr_glCompressedTexImage3DARB = (GLEEPFNGLCOMPRESSEDTEXIMAGE3DARBPROC) __GLeeGetProcAddress("glCompressedTexImage3DARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTexImage2DARB = (GLEEPFNGLCOMPRESSEDTEXIMAGE2DARBPROC) __GLeeGetProcAddress("glCompressedTexImage2DARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTexImage1DARB = (GLEEPFNGLCOMPRESSEDTEXIMAGE1DARBPROC) __GLeeGetProcAddress("glCompressedTexImage1DARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTexSubImage3DARB = (GLEEPFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) __GLeeGetProcAddress("glCompressedTexSubImage3DARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTexSubImage2DARB = (GLEEPFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) __GLeeGetProcAddress("glCompressedTexSubImage2DARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTexSubImage1DARB = (GLEEPFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) __GLeeGetProcAddress("glCompressedTexSubImage1DARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetCompressedTexImageARB = (GLEEPFNGLGETCOMPRESSEDTEXIMAGEARBPROC) __GLeeGetProcAddress("glGetCompressedTexImageARB"))!=0) nLinked++; +#endif + if (nLinked==7) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_texture_border_clamp(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_point_parameters(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_point_parameters + if ((GLeeFuncPtr_glPointParameterfARB = (GLEEPFNGLPOINTPARAMETERFARBPROC) __GLeeGetProcAddress("glPointParameterfARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glPointParameterfvARB = (GLEEPFNGLPOINTPARAMETERFVARBPROC) __GLeeGetProcAddress("glPointParameterfvARB"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_vertex_blend(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_vertex_blend + if ((GLeeFuncPtr_glWeightbvARB = (GLEEPFNGLWEIGHTBVARBPROC) __GLeeGetProcAddress("glWeightbvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWeightsvARB = (GLEEPFNGLWEIGHTSVARBPROC) __GLeeGetProcAddress("glWeightsvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWeightivARB = (GLEEPFNGLWEIGHTIVARBPROC) __GLeeGetProcAddress("glWeightivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWeightfvARB = (GLEEPFNGLWEIGHTFVARBPROC) __GLeeGetProcAddress("glWeightfvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWeightdvARB = (GLEEPFNGLWEIGHTDVARBPROC) __GLeeGetProcAddress("glWeightdvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWeightubvARB = (GLEEPFNGLWEIGHTUBVARBPROC) __GLeeGetProcAddress("glWeightubvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWeightusvARB = (GLEEPFNGLWEIGHTUSVARBPROC) __GLeeGetProcAddress("glWeightusvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWeightuivARB = (GLEEPFNGLWEIGHTUIVARBPROC) __GLeeGetProcAddress("glWeightuivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWeightPointerARB = (GLEEPFNGLWEIGHTPOINTERARBPROC) __GLeeGetProcAddress("glWeightPointerARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexBlendARB = (GLEEPFNGLVERTEXBLENDARBPROC) __GLeeGetProcAddress("glVertexBlendARB"))!=0) nLinked++; +#endif + if (nLinked==10) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_matrix_palette(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_matrix_palette + if ((GLeeFuncPtr_glCurrentPaletteMatrixARB = (GLEEPFNGLCURRENTPALETTEMATRIXARBPROC) __GLeeGetProcAddress("glCurrentPaletteMatrixARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixIndexubvARB = (GLEEPFNGLMATRIXINDEXUBVARBPROC) __GLeeGetProcAddress("glMatrixIndexubvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixIndexusvARB = (GLEEPFNGLMATRIXINDEXUSVARBPROC) __GLeeGetProcAddress("glMatrixIndexusvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixIndexuivARB = (GLEEPFNGLMATRIXINDEXUIVARBPROC) __GLeeGetProcAddress("glMatrixIndexuivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixIndexPointerARB = (GLEEPFNGLMATRIXINDEXPOINTERARBPROC) __GLeeGetProcAddress("glMatrixIndexPointerARB"))!=0) nLinked++; +#endif + if (nLinked==5) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_texture_env_combine(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_texture_env_crossbar(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_texture_env_dot3(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_texture_mirrored_repeat(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_depth_texture(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_shadow(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_shadow_ambient(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_window_pos(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_window_pos + if ((GLeeFuncPtr_glWindowPos2dARB = (GLEEPFNGLWINDOWPOS2DARBPROC) __GLeeGetProcAddress("glWindowPos2dARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2dvARB = (GLEEPFNGLWINDOWPOS2DVARBPROC) __GLeeGetProcAddress("glWindowPos2dvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2fARB = (GLEEPFNGLWINDOWPOS2FARBPROC) __GLeeGetProcAddress("glWindowPos2fARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2fvARB = (GLEEPFNGLWINDOWPOS2FVARBPROC) __GLeeGetProcAddress("glWindowPos2fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2iARB = (GLEEPFNGLWINDOWPOS2IARBPROC) __GLeeGetProcAddress("glWindowPos2iARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2ivARB = (GLEEPFNGLWINDOWPOS2IVARBPROC) __GLeeGetProcAddress("glWindowPos2ivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2sARB = (GLEEPFNGLWINDOWPOS2SARBPROC) __GLeeGetProcAddress("glWindowPos2sARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2svARB = (GLEEPFNGLWINDOWPOS2SVARBPROC) __GLeeGetProcAddress("glWindowPos2svARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3dARB = (GLEEPFNGLWINDOWPOS3DARBPROC) __GLeeGetProcAddress("glWindowPos3dARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3dvARB = (GLEEPFNGLWINDOWPOS3DVARBPROC) __GLeeGetProcAddress("glWindowPos3dvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3fARB = (GLEEPFNGLWINDOWPOS3FARBPROC) __GLeeGetProcAddress("glWindowPos3fARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3fvARB = (GLEEPFNGLWINDOWPOS3FVARBPROC) __GLeeGetProcAddress("glWindowPos3fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3iARB = (GLEEPFNGLWINDOWPOS3IARBPROC) __GLeeGetProcAddress("glWindowPos3iARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3ivARB = (GLEEPFNGLWINDOWPOS3IVARBPROC) __GLeeGetProcAddress("glWindowPos3ivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3sARB = (GLEEPFNGLWINDOWPOS3SARBPROC) __GLeeGetProcAddress("glWindowPos3sARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3svARB = (GLEEPFNGLWINDOWPOS3SVARBPROC) __GLeeGetProcAddress("glWindowPos3svARB"))!=0) nLinked++; +#endif + if (nLinked==16) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_vertex_program(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_vertex_program + if ((GLeeFuncPtr_glVertexAttrib1dARB = (GLEEPFNGLVERTEXATTRIB1DARBPROC) __GLeeGetProcAddress("glVertexAttrib1dARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1dvARB = (GLEEPFNGLVERTEXATTRIB1DVARBPROC) __GLeeGetProcAddress("glVertexAttrib1dvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1fARB = (GLEEPFNGLVERTEXATTRIB1FARBPROC) __GLeeGetProcAddress("glVertexAttrib1fARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1fvARB = (GLEEPFNGLVERTEXATTRIB1FVARBPROC) __GLeeGetProcAddress("glVertexAttrib1fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1sARB = (GLEEPFNGLVERTEXATTRIB1SARBPROC) __GLeeGetProcAddress("glVertexAttrib1sARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1svARB = (GLEEPFNGLVERTEXATTRIB1SVARBPROC) __GLeeGetProcAddress("glVertexAttrib1svARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2dARB = (GLEEPFNGLVERTEXATTRIB2DARBPROC) __GLeeGetProcAddress("glVertexAttrib2dARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2dvARB = (GLEEPFNGLVERTEXATTRIB2DVARBPROC) __GLeeGetProcAddress("glVertexAttrib2dvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2fARB = (GLEEPFNGLVERTEXATTRIB2FARBPROC) __GLeeGetProcAddress("glVertexAttrib2fARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2fvARB = (GLEEPFNGLVERTEXATTRIB2FVARBPROC) __GLeeGetProcAddress("glVertexAttrib2fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2sARB = (GLEEPFNGLVERTEXATTRIB2SARBPROC) __GLeeGetProcAddress("glVertexAttrib2sARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2svARB = (GLEEPFNGLVERTEXATTRIB2SVARBPROC) __GLeeGetProcAddress("glVertexAttrib2svARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3dARB = (GLEEPFNGLVERTEXATTRIB3DARBPROC) __GLeeGetProcAddress("glVertexAttrib3dARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3dvARB = (GLEEPFNGLVERTEXATTRIB3DVARBPROC) __GLeeGetProcAddress("glVertexAttrib3dvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3fARB = (GLEEPFNGLVERTEXATTRIB3FARBPROC) __GLeeGetProcAddress("glVertexAttrib3fARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3fvARB = (GLEEPFNGLVERTEXATTRIB3FVARBPROC) __GLeeGetProcAddress("glVertexAttrib3fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3sARB = (GLEEPFNGLVERTEXATTRIB3SARBPROC) __GLeeGetProcAddress("glVertexAttrib3sARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3svARB = (GLEEPFNGLVERTEXATTRIB3SVARBPROC) __GLeeGetProcAddress("glVertexAttrib3svARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4NbvARB = (GLEEPFNGLVERTEXATTRIB4NBVARBPROC) __GLeeGetProcAddress("glVertexAttrib4NbvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4NivARB = (GLEEPFNGLVERTEXATTRIB4NIVARBPROC) __GLeeGetProcAddress("glVertexAttrib4NivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4NsvARB = (GLEEPFNGLVERTEXATTRIB4NSVARBPROC) __GLeeGetProcAddress("glVertexAttrib4NsvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4NubARB = (GLEEPFNGLVERTEXATTRIB4NUBARBPROC) __GLeeGetProcAddress("glVertexAttrib4NubARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4NubvARB = (GLEEPFNGLVERTEXATTRIB4NUBVARBPROC) __GLeeGetProcAddress("glVertexAttrib4NubvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4NuivARB = (GLEEPFNGLVERTEXATTRIB4NUIVARBPROC) __GLeeGetProcAddress("glVertexAttrib4NuivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4NusvARB = (GLEEPFNGLVERTEXATTRIB4NUSVARBPROC) __GLeeGetProcAddress("glVertexAttrib4NusvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4bvARB = (GLEEPFNGLVERTEXATTRIB4BVARBPROC) __GLeeGetProcAddress("glVertexAttrib4bvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4dARB = (GLEEPFNGLVERTEXATTRIB4DARBPROC) __GLeeGetProcAddress("glVertexAttrib4dARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4dvARB = (GLEEPFNGLVERTEXATTRIB4DVARBPROC) __GLeeGetProcAddress("glVertexAttrib4dvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4fARB = (GLEEPFNGLVERTEXATTRIB4FARBPROC) __GLeeGetProcAddress("glVertexAttrib4fARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4fvARB = (GLEEPFNGLVERTEXATTRIB4FVARBPROC) __GLeeGetProcAddress("glVertexAttrib4fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4ivARB = (GLEEPFNGLVERTEXATTRIB4IVARBPROC) __GLeeGetProcAddress("glVertexAttrib4ivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4sARB = (GLEEPFNGLVERTEXATTRIB4SARBPROC) __GLeeGetProcAddress("glVertexAttrib4sARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4svARB = (GLEEPFNGLVERTEXATTRIB4SVARBPROC) __GLeeGetProcAddress("glVertexAttrib4svARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4ubvARB = (GLEEPFNGLVERTEXATTRIB4UBVARBPROC) __GLeeGetProcAddress("glVertexAttrib4ubvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4uivARB = (GLEEPFNGLVERTEXATTRIB4UIVARBPROC) __GLeeGetProcAddress("glVertexAttrib4uivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4usvARB = (GLEEPFNGLVERTEXATTRIB4USVARBPROC) __GLeeGetProcAddress("glVertexAttrib4usvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribPointerARB = (GLEEPFNGLVERTEXATTRIBPOINTERARBPROC) __GLeeGetProcAddress("glVertexAttribPointerARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glEnableVertexAttribArrayARB = (GLEEPFNGLENABLEVERTEXATTRIBARRAYARBPROC) __GLeeGetProcAddress("glEnableVertexAttribArrayARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glDisableVertexAttribArrayARB = (GLEEPFNGLDISABLEVERTEXATTRIBARRAYARBPROC) __GLeeGetProcAddress("glDisableVertexAttribArrayARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramStringARB = (GLEEPFNGLPROGRAMSTRINGARBPROC) __GLeeGetProcAddress("glProgramStringARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindProgramARB = (GLEEPFNGLBINDPROGRAMARBPROC) __GLeeGetProcAddress("glBindProgramARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteProgramsARB = (GLEEPFNGLDELETEPROGRAMSARBPROC) __GLeeGetProcAddress("glDeleteProgramsARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenProgramsARB = (GLEEPFNGLGENPROGRAMSARBPROC) __GLeeGetProcAddress("glGenProgramsARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramEnvParameter4dARB = (GLEEPFNGLPROGRAMENVPARAMETER4DARBPROC) __GLeeGetProcAddress("glProgramEnvParameter4dARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramEnvParameter4dvARB = (GLEEPFNGLPROGRAMENVPARAMETER4DVARBPROC) __GLeeGetProcAddress("glProgramEnvParameter4dvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramEnvParameter4fARB = (GLEEPFNGLPROGRAMENVPARAMETER4FARBPROC) __GLeeGetProcAddress("glProgramEnvParameter4fARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramEnvParameter4fvARB = (GLEEPFNGLPROGRAMENVPARAMETER4FVARBPROC) __GLeeGetProcAddress("glProgramEnvParameter4fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramLocalParameter4dARB = (GLEEPFNGLPROGRAMLOCALPARAMETER4DARBPROC) __GLeeGetProcAddress("glProgramLocalParameter4dARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramLocalParameter4dvARB = (GLEEPFNGLPROGRAMLOCALPARAMETER4DVARBPROC) __GLeeGetProcAddress("glProgramLocalParameter4dvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramLocalParameter4fARB = (GLEEPFNGLPROGRAMLOCALPARAMETER4FARBPROC) __GLeeGetProcAddress("glProgramLocalParameter4fARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramLocalParameter4fvARB = (GLEEPFNGLPROGRAMLOCALPARAMETER4FVARBPROC) __GLeeGetProcAddress("glProgramLocalParameter4fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramEnvParameterdvARB = (GLEEPFNGLGETPROGRAMENVPARAMETERDVARBPROC) __GLeeGetProcAddress("glGetProgramEnvParameterdvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramEnvParameterfvARB = (GLEEPFNGLGETPROGRAMENVPARAMETERFVARBPROC) __GLeeGetProcAddress("glGetProgramEnvParameterfvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramLocalParameterdvARB = (GLEEPFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) __GLeeGetProcAddress("glGetProgramLocalParameterdvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramLocalParameterfvARB = (GLEEPFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) __GLeeGetProcAddress("glGetProgramLocalParameterfvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramivARB = (GLEEPFNGLGETPROGRAMIVARBPROC) __GLeeGetProcAddress("glGetProgramivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramStringARB = (GLEEPFNGLGETPROGRAMSTRINGARBPROC) __GLeeGetProcAddress("glGetProgramStringARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribdvARB = (GLEEPFNGLGETVERTEXATTRIBDVARBPROC) __GLeeGetProcAddress("glGetVertexAttribdvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribfvARB = (GLEEPFNGLGETVERTEXATTRIBFVARBPROC) __GLeeGetProcAddress("glGetVertexAttribfvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribivARB = (GLEEPFNGLGETVERTEXATTRIBIVARBPROC) __GLeeGetProcAddress("glGetVertexAttribivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribPointervARB = (GLEEPFNGLGETVERTEXATTRIBPOINTERVARBPROC) __GLeeGetProcAddress("glGetVertexAttribPointervARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsProgramARB = (GLEEPFNGLISPROGRAMARBPROC) __GLeeGetProcAddress("glIsProgramARB"))!=0) nLinked++; +#endif + if (nLinked==62) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_fragment_program(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_vertex_buffer_object(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_vertex_buffer_object + if ((GLeeFuncPtr_glBindBufferARB = (GLEEPFNGLBINDBUFFERARBPROC) __GLeeGetProcAddress("glBindBufferARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteBuffersARB = (GLEEPFNGLDELETEBUFFERSARBPROC) __GLeeGetProcAddress("glDeleteBuffersARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenBuffersARB = (GLEEPFNGLGENBUFFERSARBPROC) __GLeeGetProcAddress("glGenBuffersARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsBufferARB = (GLEEPFNGLISBUFFERARBPROC) __GLeeGetProcAddress("glIsBufferARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glBufferDataARB = (GLEEPFNGLBUFFERDATAARBPROC) __GLeeGetProcAddress("glBufferDataARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glBufferSubDataARB = (GLEEPFNGLBUFFERSUBDATAARBPROC) __GLeeGetProcAddress("glBufferSubDataARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetBufferSubDataARB = (GLEEPFNGLGETBUFFERSUBDATAARBPROC) __GLeeGetProcAddress("glGetBufferSubDataARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glMapBufferARB = (GLEEPFNGLMAPBUFFERARBPROC) __GLeeGetProcAddress("glMapBufferARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUnmapBufferARB = (GLEEPFNGLUNMAPBUFFERARBPROC) __GLeeGetProcAddress("glUnmapBufferARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetBufferParameterivARB = (GLEEPFNGLGETBUFFERPARAMETERIVARBPROC) __GLeeGetProcAddress("glGetBufferParameterivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetBufferPointervARB = (GLEEPFNGLGETBUFFERPOINTERVARBPROC) __GLeeGetProcAddress("glGetBufferPointervARB"))!=0) nLinked++; +#endif + if (nLinked==11) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_occlusion_query(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_occlusion_query + if ((GLeeFuncPtr_glGenQueriesARB = (GLEEPFNGLGENQUERIESARBPROC) __GLeeGetProcAddress("glGenQueriesARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteQueriesARB = (GLEEPFNGLDELETEQUERIESARBPROC) __GLeeGetProcAddress("glDeleteQueriesARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsQueryARB = (GLEEPFNGLISQUERYARBPROC) __GLeeGetProcAddress("glIsQueryARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glBeginQueryARB = (GLEEPFNGLBEGINQUERYARBPROC) __GLeeGetProcAddress("glBeginQueryARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glEndQueryARB = (GLEEPFNGLENDQUERYARBPROC) __GLeeGetProcAddress("glEndQueryARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetQueryivARB = (GLEEPFNGLGETQUERYIVARBPROC) __GLeeGetProcAddress("glGetQueryivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetQueryObjectivARB = (GLEEPFNGLGETQUERYOBJECTIVARBPROC) __GLeeGetProcAddress("glGetQueryObjectivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetQueryObjectuivARB = (GLEEPFNGLGETQUERYOBJECTUIVARBPROC) __GLeeGetProcAddress("glGetQueryObjectuivARB"))!=0) nLinked++; +#endif + if (nLinked==8) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_shader_objects(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_shader_objects + if ((GLeeFuncPtr_glDeleteObjectARB = (GLEEPFNGLDELETEOBJECTARBPROC) __GLeeGetProcAddress("glDeleteObjectARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetHandleARB = (GLEEPFNGLGETHANDLEARBPROC) __GLeeGetProcAddress("glGetHandleARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glDetachObjectARB = (GLEEPFNGLDETACHOBJECTARBPROC) __GLeeGetProcAddress("glDetachObjectARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glCreateShaderObjectARB = (GLEEPFNGLCREATESHADEROBJECTARBPROC) __GLeeGetProcAddress("glCreateShaderObjectARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glShaderSourceARB = (GLEEPFNGLSHADERSOURCEARBPROC) __GLeeGetProcAddress("glShaderSourceARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompileShaderARB = (GLEEPFNGLCOMPILESHADERARBPROC) __GLeeGetProcAddress("glCompileShaderARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glCreateProgramObjectARB = (GLEEPFNGLCREATEPROGRAMOBJECTARBPROC) __GLeeGetProcAddress("glCreateProgramObjectARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glAttachObjectARB = (GLEEPFNGLATTACHOBJECTARBPROC) __GLeeGetProcAddress("glAttachObjectARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glLinkProgramARB = (GLEEPFNGLLINKPROGRAMARBPROC) __GLeeGetProcAddress("glLinkProgramARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUseProgramObjectARB = (GLEEPFNGLUSEPROGRAMOBJECTARBPROC) __GLeeGetProcAddress("glUseProgramObjectARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glValidateProgramARB = (GLEEPFNGLVALIDATEPROGRAMARBPROC) __GLeeGetProcAddress("glValidateProgramARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform1fARB = (GLEEPFNGLUNIFORM1FARBPROC) __GLeeGetProcAddress("glUniform1fARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform2fARB = (GLEEPFNGLUNIFORM2FARBPROC) __GLeeGetProcAddress("glUniform2fARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform3fARB = (GLEEPFNGLUNIFORM3FARBPROC) __GLeeGetProcAddress("glUniform3fARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform4fARB = (GLEEPFNGLUNIFORM4FARBPROC) __GLeeGetProcAddress("glUniform4fARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform1iARB = (GLEEPFNGLUNIFORM1IARBPROC) __GLeeGetProcAddress("glUniform1iARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform2iARB = (GLEEPFNGLUNIFORM2IARBPROC) __GLeeGetProcAddress("glUniform2iARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform3iARB = (GLEEPFNGLUNIFORM3IARBPROC) __GLeeGetProcAddress("glUniform3iARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform4iARB = (GLEEPFNGLUNIFORM4IARBPROC) __GLeeGetProcAddress("glUniform4iARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform1fvARB = (GLEEPFNGLUNIFORM1FVARBPROC) __GLeeGetProcAddress("glUniform1fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform2fvARB = (GLEEPFNGLUNIFORM2FVARBPROC) __GLeeGetProcAddress("glUniform2fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform3fvARB = (GLEEPFNGLUNIFORM3FVARBPROC) __GLeeGetProcAddress("glUniform3fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform4fvARB = (GLEEPFNGLUNIFORM4FVARBPROC) __GLeeGetProcAddress("glUniform4fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform1ivARB = (GLEEPFNGLUNIFORM1IVARBPROC) __GLeeGetProcAddress("glUniform1ivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform2ivARB = (GLEEPFNGLUNIFORM2IVARBPROC) __GLeeGetProcAddress("glUniform2ivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform3ivARB = (GLEEPFNGLUNIFORM3IVARBPROC) __GLeeGetProcAddress("glUniform3ivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform4ivARB = (GLEEPFNGLUNIFORM4IVARBPROC) __GLeeGetProcAddress("glUniform4ivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniformMatrix2fvARB = (GLEEPFNGLUNIFORMMATRIX2FVARBPROC) __GLeeGetProcAddress("glUniformMatrix2fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniformMatrix3fvARB = (GLEEPFNGLUNIFORMMATRIX3FVARBPROC) __GLeeGetProcAddress("glUniformMatrix3fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniformMatrix4fvARB = (GLEEPFNGLUNIFORMMATRIX4FVARBPROC) __GLeeGetProcAddress("glUniformMatrix4fvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetObjectParameterfvARB = (GLEEPFNGLGETOBJECTPARAMETERFVARBPROC) __GLeeGetProcAddress("glGetObjectParameterfvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetObjectParameterivARB = (GLEEPFNGLGETOBJECTPARAMETERIVARBPROC) __GLeeGetProcAddress("glGetObjectParameterivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetInfoLogARB = (GLEEPFNGLGETINFOLOGARBPROC) __GLeeGetProcAddress("glGetInfoLogARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetAttachedObjectsARB = (GLEEPFNGLGETATTACHEDOBJECTSARBPROC) __GLeeGetProcAddress("glGetAttachedObjectsARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetUniformLocationARB = (GLEEPFNGLGETUNIFORMLOCATIONARBPROC) __GLeeGetProcAddress("glGetUniformLocationARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetActiveUniformARB = (GLEEPFNGLGETACTIVEUNIFORMARBPROC) __GLeeGetProcAddress("glGetActiveUniformARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetUniformfvARB = (GLEEPFNGLGETUNIFORMFVARBPROC) __GLeeGetProcAddress("glGetUniformfvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetUniformivARB = (GLEEPFNGLGETUNIFORMIVARBPROC) __GLeeGetProcAddress("glGetUniformivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetShaderSourceARB = (GLEEPFNGLGETSHADERSOURCEARBPROC) __GLeeGetProcAddress("glGetShaderSourceARB"))!=0) nLinked++; +#endif + if (nLinked==39) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_vertex_shader(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_vertex_shader + if ((GLeeFuncPtr_glBindAttribLocationARB = (GLEEPFNGLBINDATTRIBLOCATIONARBPROC) __GLeeGetProcAddress("glBindAttribLocationARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetActiveAttribARB = (GLEEPFNGLGETACTIVEATTRIBARBPROC) __GLeeGetProcAddress("glGetActiveAttribARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetAttribLocationARB = (GLEEPFNGLGETATTRIBLOCATIONARBPROC) __GLeeGetProcAddress("glGetAttribLocationARB"))!=0) nLinked++; +#endif + if (nLinked==3) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_fragment_shader(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_shading_language_100(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_texture_non_power_of_two(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_point_sprite(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_fragment_program_shadow(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_draw_buffers(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_draw_buffers + if ((GLeeFuncPtr_glDrawBuffersARB = (GLEEPFNGLDRAWBUFFERSARBPROC) __GLeeGetProcAddress("glDrawBuffersARB"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_texture_rectangle(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_color_buffer_float(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_color_buffer_float + if ((GLeeFuncPtr_glClampColorARB = (GLEEPFNGLCLAMPCOLORARBPROC) __GLeeGetProcAddress("glClampColorARB"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_half_float_pixel(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_texture_float(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_pixel_buffer_object(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_depth_buffer_float(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_draw_instanced(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_draw_instanced + if ((GLeeFuncPtr_glDrawArraysInstancedARB = (GLEEPFNGLDRAWARRAYSINSTANCEDARBPROC) __GLeeGetProcAddress("glDrawArraysInstancedARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glDrawElementsInstancedARB = (GLEEPFNGLDRAWELEMENTSINSTANCEDARBPROC) __GLeeGetProcAddress("glDrawElementsInstancedARB"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_framebuffer_object(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_framebuffer_object + if ((GLeeFuncPtr_glIsRenderbuffer = (GLEEPFNGLISRENDERBUFFERPROC) __GLeeGetProcAddress("glIsRenderbuffer"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindRenderbuffer = (GLEEPFNGLBINDRENDERBUFFERPROC) __GLeeGetProcAddress("glBindRenderbuffer"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteRenderbuffers = (GLEEPFNGLDELETERENDERBUFFERSPROC) __GLeeGetProcAddress("glDeleteRenderbuffers"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenRenderbuffers = (GLEEPFNGLGENRENDERBUFFERSPROC) __GLeeGetProcAddress("glGenRenderbuffers"))!=0) nLinked++; + if ((GLeeFuncPtr_glRenderbufferStorage = (GLEEPFNGLRENDERBUFFERSTORAGEPROC) __GLeeGetProcAddress("glRenderbufferStorage"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetRenderbufferParameteriv = (GLEEPFNGLGETRENDERBUFFERPARAMETERIVPROC) __GLeeGetProcAddress("glGetRenderbufferParameteriv"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsFramebuffer = (GLEEPFNGLISFRAMEBUFFERPROC) __GLeeGetProcAddress("glIsFramebuffer"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindFramebuffer = (GLEEPFNGLBINDFRAMEBUFFERPROC) __GLeeGetProcAddress("glBindFramebuffer"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteFramebuffers = (GLEEPFNGLDELETEFRAMEBUFFERSPROC) __GLeeGetProcAddress("glDeleteFramebuffers"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenFramebuffers = (GLEEPFNGLGENFRAMEBUFFERSPROC) __GLeeGetProcAddress("glGenFramebuffers"))!=0) nLinked++; + if ((GLeeFuncPtr_glCheckFramebufferStatus = (GLEEPFNGLCHECKFRAMEBUFFERSTATUSPROC) __GLeeGetProcAddress("glCheckFramebufferStatus"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferTexture1D = (GLEEPFNGLFRAMEBUFFERTEXTURE1DPROC) __GLeeGetProcAddress("glFramebufferTexture1D"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferTexture2D = (GLEEPFNGLFRAMEBUFFERTEXTURE2DPROC) __GLeeGetProcAddress("glFramebufferTexture2D"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferTexture3D = (GLEEPFNGLFRAMEBUFFERTEXTURE3DPROC) __GLeeGetProcAddress("glFramebufferTexture3D"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferRenderbuffer = (GLEEPFNGLFRAMEBUFFERRENDERBUFFERPROC) __GLeeGetProcAddress("glFramebufferRenderbuffer"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFramebufferAttachmentParameteriv = (GLEEPFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) __GLeeGetProcAddress("glGetFramebufferAttachmentParameteriv"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenerateMipmap = (GLEEPFNGLGENERATEMIPMAPPROC) __GLeeGetProcAddress("glGenerateMipmap"))!=0) nLinked++; + if ((GLeeFuncPtr_glBlitFramebuffer = (GLEEPFNGLBLITFRAMEBUFFERPROC) __GLeeGetProcAddress("glBlitFramebuffer"))!=0) nLinked++; + if ((GLeeFuncPtr_glRenderbufferStorageMultisample = (GLEEPFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) __GLeeGetProcAddress("glRenderbufferStorageMultisample"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferTextureLayer = (GLEEPFNGLFRAMEBUFFERTEXTURELAYERPROC) __GLeeGetProcAddress("glFramebufferTextureLayer"))!=0) nLinked++; +#endif + if (nLinked==20) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_framebuffer_sRGB(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_geometry_shader4(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_geometry_shader4 + if ((GLeeFuncPtr_glProgramParameteriARB = (GLEEPFNGLPROGRAMPARAMETERIARBPROC) __GLeeGetProcAddress("glProgramParameteriARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferTextureARB = (GLEEPFNGLFRAMEBUFFERTEXTUREARBPROC) __GLeeGetProcAddress("glFramebufferTextureARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferTextureLayerARB = (GLEEPFNGLFRAMEBUFFERTEXTURELAYERARBPROC) __GLeeGetProcAddress("glFramebufferTextureLayerARB"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferTextureFaceARB = (GLEEPFNGLFRAMEBUFFERTEXTUREFACEARBPROC) __GLeeGetProcAddress("glFramebufferTextureFaceARB"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_half_float_vertex(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_instanced_arrays(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_instanced_arrays + if ((GLeeFuncPtr_glVertexAttribDivisor = (GLEEPFNGLVERTEXATTRIBDIVISORPROC) __GLeeGetProcAddress("glVertexAttribDivisor"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_map_buffer_range(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_map_buffer_range + if ((GLeeFuncPtr_glMapBufferRange = (GLEEPFNGLMAPBUFFERRANGEPROC) __GLeeGetProcAddress("glMapBufferRange"))!=0) nLinked++; + if ((GLeeFuncPtr_glFlushMappedBufferRange = (GLEEPFNGLFLUSHMAPPEDBUFFERRANGEPROC) __GLeeGetProcAddress("glFlushMappedBufferRange"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_texture_buffer_object(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_texture_buffer_object + if ((GLeeFuncPtr_glTexBufferARB = (GLEEPFNGLTEXBUFFERARBPROC) __GLeeGetProcAddress("glTexBufferARB"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ARB_texture_compression_rgtc(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_texture_rg(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ARB_vertex_array_object(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ARB_vertex_array_object + if ((GLeeFuncPtr_glBindVertexArray = (GLEEPFNGLBINDVERTEXARRAYPROC) __GLeeGetProcAddress("glBindVertexArray"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteVertexArrays = (GLEEPFNGLDELETEVERTEXARRAYSPROC) __GLeeGetProcAddress("glDeleteVertexArrays"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenVertexArrays = (GLEEPFNGLGENVERTEXARRAYSPROC) __GLeeGetProcAddress("glGenVertexArrays"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsVertexArray = (GLEEPFNGLISVERTEXARRAYPROC) __GLeeGetProcAddress("glIsVertexArray"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_abgr(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_blend_color(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_blend_color + if ((GLeeFuncPtr_glBlendColorEXT = (GLEEPFNGLBLENDCOLOREXTPROC) __GLeeGetProcAddress("glBlendColorEXT"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_polygon_offset(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_polygon_offset + if ((GLeeFuncPtr_glPolygonOffsetEXT = (GLEEPFNGLPOLYGONOFFSETEXTPROC) __GLeeGetProcAddress("glPolygonOffsetEXT"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_texture(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_texture3D(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_texture3D + if ((GLeeFuncPtr_glTexImage3DEXT = (GLEEPFNGLTEXIMAGE3DEXTPROC) __GLeeGetProcAddress("glTexImage3DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexSubImage3DEXT = (GLEEPFNGLTEXSUBIMAGE3DEXTPROC) __GLeeGetProcAddress("glTexSubImage3DEXT"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIS_texture_filter4(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIS_texture_filter4 + if ((GLeeFuncPtr_glGetTexFilterFuncSGIS = (GLEEPFNGLGETTEXFILTERFUNCSGISPROC) __GLeeGetProcAddress("glGetTexFilterFuncSGIS"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexFilterFuncSGIS = (GLEEPFNGLTEXFILTERFUNCSGISPROC) __GLeeGetProcAddress("glTexFilterFuncSGIS"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_subtexture(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_subtexture + if ((GLeeFuncPtr_glTexSubImage1DEXT = (GLEEPFNGLTEXSUBIMAGE1DEXTPROC) __GLeeGetProcAddress("glTexSubImage1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexSubImage2DEXT = (GLEEPFNGLTEXSUBIMAGE2DEXTPROC) __GLeeGetProcAddress("glTexSubImage2DEXT"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_copy_texture(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_copy_texture + if ((GLeeFuncPtr_glCopyTexImage1DEXT = (GLEEPFNGLCOPYTEXIMAGE1DEXTPROC) __GLeeGetProcAddress("glCopyTexImage1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyTexImage2DEXT = (GLEEPFNGLCOPYTEXIMAGE2DEXTPROC) __GLeeGetProcAddress("glCopyTexImage2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyTexSubImage1DEXT = (GLEEPFNGLCOPYTEXSUBIMAGE1DEXTPROC) __GLeeGetProcAddress("glCopyTexSubImage1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyTexSubImage2DEXT = (GLEEPFNGLCOPYTEXSUBIMAGE2DEXTPROC) __GLeeGetProcAddress("glCopyTexSubImage2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyTexSubImage3DEXT = (GLEEPFNGLCOPYTEXSUBIMAGE3DEXTPROC) __GLeeGetProcAddress("glCopyTexSubImage3DEXT"))!=0) nLinked++; +#endif + if (nLinked==5) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_histogram(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_histogram + if ((GLeeFuncPtr_glGetHistogramEXT = (GLEEPFNGLGETHISTOGRAMEXTPROC) __GLeeGetProcAddress("glGetHistogramEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetHistogramParameterfvEXT = (GLEEPFNGLGETHISTOGRAMPARAMETERFVEXTPROC) __GLeeGetProcAddress("glGetHistogramParameterfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetHistogramParameterivEXT = (GLEEPFNGLGETHISTOGRAMPARAMETERIVEXTPROC) __GLeeGetProcAddress("glGetHistogramParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMinmaxEXT = (GLEEPFNGLGETMINMAXEXTPROC) __GLeeGetProcAddress("glGetMinmaxEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMinmaxParameterfvEXT = (GLEEPFNGLGETMINMAXPARAMETERFVEXTPROC) __GLeeGetProcAddress("glGetMinmaxParameterfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMinmaxParameterivEXT = (GLEEPFNGLGETMINMAXPARAMETERIVEXTPROC) __GLeeGetProcAddress("glGetMinmaxParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glHistogramEXT = (GLEEPFNGLHISTOGRAMEXTPROC) __GLeeGetProcAddress("glHistogramEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMinmaxEXT = (GLEEPFNGLMINMAXEXTPROC) __GLeeGetProcAddress("glMinmaxEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glResetHistogramEXT = (GLEEPFNGLRESETHISTOGRAMEXTPROC) __GLeeGetProcAddress("glResetHistogramEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glResetMinmaxEXT = (GLEEPFNGLRESETMINMAXEXTPROC) __GLeeGetProcAddress("glResetMinmaxEXT"))!=0) nLinked++; +#endif + if (nLinked==10) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_convolution(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_convolution + if ((GLeeFuncPtr_glConvolutionFilter1DEXT = (GLEEPFNGLCONVOLUTIONFILTER1DEXTPROC) __GLeeGetProcAddress("glConvolutionFilter1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glConvolutionFilter2DEXT = (GLEEPFNGLCONVOLUTIONFILTER2DEXTPROC) __GLeeGetProcAddress("glConvolutionFilter2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glConvolutionParameterfEXT = (GLEEPFNGLCONVOLUTIONPARAMETERFEXTPROC) __GLeeGetProcAddress("glConvolutionParameterfEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glConvolutionParameterfvEXT = (GLEEPFNGLCONVOLUTIONPARAMETERFVEXTPROC) __GLeeGetProcAddress("glConvolutionParameterfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glConvolutionParameteriEXT = (GLEEPFNGLCONVOLUTIONPARAMETERIEXTPROC) __GLeeGetProcAddress("glConvolutionParameteriEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glConvolutionParameterivEXT = (GLEEPFNGLCONVOLUTIONPARAMETERIVEXTPROC) __GLeeGetProcAddress("glConvolutionParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyConvolutionFilter1DEXT = (GLEEPFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) __GLeeGetProcAddress("glCopyConvolutionFilter1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyConvolutionFilter2DEXT = (GLEEPFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) __GLeeGetProcAddress("glCopyConvolutionFilter2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetConvolutionFilterEXT = (GLEEPFNGLGETCONVOLUTIONFILTEREXTPROC) __GLeeGetProcAddress("glGetConvolutionFilterEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetConvolutionParameterfvEXT = (GLEEPFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) __GLeeGetProcAddress("glGetConvolutionParameterfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetConvolutionParameterivEXT = (GLEEPFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) __GLeeGetProcAddress("glGetConvolutionParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetSeparableFilterEXT = (GLEEPFNGLGETSEPARABLEFILTEREXTPROC) __GLeeGetProcAddress("glGetSeparableFilterEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSeparableFilter2DEXT = (GLEEPFNGLSEPARABLEFILTER2DEXTPROC) __GLeeGetProcAddress("glSeparableFilter2DEXT"))!=0) nLinked++; +#endif + if (nLinked==13) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGI_color_matrix(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGI_color_table(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGI_color_table + if ((GLeeFuncPtr_glColorTableSGI = (GLEEPFNGLCOLORTABLESGIPROC) __GLeeGetProcAddress("glColorTableSGI"))!=0) nLinked++; + if ((GLeeFuncPtr_glColorTableParameterfvSGI = (GLEEPFNGLCOLORTABLEPARAMETERFVSGIPROC) __GLeeGetProcAddress("glColorTableParameterfvSGI"))!=0) nLinked++; + if ((GLeeFuncPtr_glColorTableParameterivSGI = (GLEEPFNGLCOLORTABLEPARAMETERIVSGIPROC) __GLeeGetProcAddress("glColorTableParameterivSGI"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyColorTableSGI = (GLEEPFNGLCOPYCOLORTABLESGIPROC) __GLeeGetProcAddress("glCopyColorTableSGI"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetColorTableSGI = (GLEEPFNGLGETCOLORTABLESGIPROC) __GLeeGetProcAddress("glGetColorTableSGI"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetColorTableParameterfvSGI = (GLEEPFNGLGETCOLORTABLEPARAMETERFVSGIPROC) __GLeeGetProcAddress("glGetColorTableParameterfvSGI"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetColorTableParameterivSGI = (GLEEPFNGLGETCOLORTABLEPARAMETERIVSGIPROC) __GLeeGetProcAddress("glGetColorTableParameterivSGI"))!=0) nLinked++; +#endif + if (nLinked==7) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIS_pixel_texture(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIS_pixel_texture + if ((GLeeFuncPtr_glPixelTexGenParameteriSGIS = (GLEEPFNGLPIXELTEXGENPARAMETERISGISPROC) __GLeeGetProcAddress("glPixelTexGenParameteriSGIS"))!=0) nLinked++; + if ((GLeeFuncPtr_glPixelTexGenParameterivSGIS = (GLEEPFNGLPIXELTEXGENPARAMETERIVSGISPROC) __GLeeGetProcAddress("glPixelTexGenParameterivSGIS"))!=0) nLinked++; + if ((GLeeFuncPtr_glPixelTexGenParameterfSGIS = (GLEEPFNGLPIXELTEXGENPARAMETERFSGISPROC) __GLeeGetProcAddress("glPixelTexGenParameterfSGIS"))!=0) nLinked++; + if ((GLeeFuncPtr_glPixelTexGenParameterfvSGIS = (GLEEPFNGLPIXELTEXGENPARAMETERFVSGISPROC) __GLeeGetProcAddress("glPixelTexGenParameterfvSGIS"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetPixelTexGenParameterivSGIS = (GLEEPFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) __GLeeGetProcAddress("glGetPixelTexGenParameterivSGIS"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetPixelTexGenParameterfvSGIS = (GLEEPFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) __GLeeGetProcAddress("glGetPixelTexGenParameterfvSGIS"))!=0) nLinked++; +#endif + if (nLinked==6) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_pixel_texture(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIX_pixel_texture + if ((GLeeFuncPtr_glPixelTexGenSGIX = (GLEEPFNGLPIXELTEXGENSGIXPROC) __GLeeGetProcAddress("glPixelTexGenSGIX"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIS_texture4D(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIS_texture4D + if ((GLeeFuncPtr_glTexImage4DSGIS = (GLEEPFNGLTEXIMAGE4DSGISPROC) __GLeeGetProcAddress("glTexImage4DSGIS"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexSubImage4DSGIS = (GLEEPFNGLTEXSUBIMAGE4DSGISPROC) __GLeeGetProcAddress("glTexSubImage4DSGIS"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGI_texture_color_table(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_cmyka(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_texture_object(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_texture_object + if ((GLeeFuncPtr_glAreTexturesResidentEXT = (GLEEPFNGLARETEXTURESRESIDENTEXTPROC) __GLeeGetProcAddress("glAreTexturesResidentEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindTextureEXT = (GLEEPFNGLBINDTEXTUREEXTPROC) __GLeeGetProcAddress("glBindTextureEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteTexturesEXT = (GLEEPFNGLDELETETEXTURESEXTPROC) __GLeeGetProcAddress("glDeleteTexturesEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenTexturesEXT = (GLEEPFNGLGENTEXTURESEXTPROC) __GLeeGetProcAddress("glGenTexturesEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsTextureEXT = (GLEEPFNGLISTEXTUREEXTPROC) __GLeeGetProcAddress("glIsTextureEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glPrioritizeTexturesEXT = (GLEEPFNGLPRIORITIZETEXTURESEXTPROC) __GLeeGetProcAddress("glPrioritizeTexturesEXT"))!=0) nLinked++; +#endif + if (nLinked==6) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIS_detail_texture(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIS_detail_texture + if ((GLeeFuncPtr_glDetailTexFuncSGIS = (GLEEPFNGLDETAILTEXFUNCSGISPROC) __GLeeGetProcAddress("glDetailTexFuncSGIS"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetDetailTexFuncSGIS = (GLEEPFNGLGETDETAILTEXFUNCSGISPROC) __GLeeGetProcAddress("glGetDetailTexFuncSGIS"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIS_sharpen_texture(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIS_sharpen_texture + if ((GLeeFuncPtr_glSharpenTexFuncSGIS = (GLEEPFNGLSHARPENTEXFUNCSGISPROC) __GLeeGetProcAddress("glSharpenTexFuncSGIS"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetSharpenTexFuncSGIS = (GLEEPFNGLGETSHARPENTEXFUNCSGISPROC) __GLeeGetProcAddress("glGetSharpenTexFuncSGIS"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_packed_pixels(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIS_texture_lod(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIS_multisample(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIS_multisample + if ((GLeeFuncPtr_glSampleMaskSGIS = (GLEEPFNGLSAMPLEMASKSGISPROC) __GLeeGetProcAddress("glSampleMaskSGIS"))!=0) nLinked++; + if ((GLeeFuncPtr_glSamplePatternSGIS = (GLEEPFNGLSAMPLEPATTERNSGISPROC) __GLeeGetProcAddress("glSamplePatternSGIS"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_rescale_normal(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_vertex_array(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_vertex_array + if ((GLeeFuncPtr_glArrayElementEXT = (GLEEPFNGLARRAYELEMENTEXTPROC) __GLeeGetProcAddress("glArrayElementEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glColorPointerEXT = (GLEEPFNGLCOLORPOINTEREXTPROC) __GLeeGetProcAddress("glColorPointerEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glDrawArraysEXT = (GLEEPFNGLDRAWARRAYSEXTPROC) __GLeeGetProcAddress("glDrawArraysEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glEdgeFlagPointerEXT = (GLEEPFNGLEDGEFLAGPOINTEREXTPROC) __GLeeGetProcAddress("glEdgeFlagPointerEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetPointervEXT = (GLEEPFNGLGETPOINTERVEXTPROC) __GLeeGetProcAddress("glGetPointervEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glIndexPointerEXT = (GLEEPFNGLINDEXPOINTEREXTPROC) __GLeeGetProcAddress("glIndexPointerEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormalPointerEXT = (GLEEPFNGLNORMALPOINTEREXTPROC) __GLeeGetProcAddress("glNormalPointerEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoordPointerEXT = (GLEEPFNGLTEXCOORDPOINTEREXTPROC) __GLeeGetProcAddress("glTexCoordPointerEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexPointerEXT = (GLEEPFNGLVERTEXPOINTEREXTPROC) __GLeeGetProcAddress("glVertexPointerEXT"))!=0) nLinked++; +#endif + if (nLinked==9) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_misc_attribute(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIS_generate_mipmap(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_clipmap(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_shadow(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIS_texture_edge_clamp(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIS_texture_border_clamp(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_blend_minmax(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_blend_minmax + if ((GLeeFuncPtr_glBlendEquationEXT = (GLEEPFNGLBLENDEQUATIONEXTPROC) __GLeeGetProcAddress("glBlendEquationEXT"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_blend_subtract(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_blend_logic_op(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_interlace(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_pixel_tiles(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIS_texture_select(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_sprite(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIX_sprite + if ((GLeeFuncPtr_glSpriteParameterfSGIX = (GLEEPFNGLSPRITEPARAMETERFSGIXPROC) __GLeeGetProcAddress("glSpriteParameterfSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glSpriteParameterfvSGIX = (GLEEPFNGLSPRITEPARAMETERFVSGIXPROC) __GLeeGetProcAddress("glSpriteParameterfvSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glSpriteParameteriSGIX = (GLEEPFNGLSPRITEPARAMETERISGIXPROC) __GLeeGetProcAddress("glSpriteParameteriSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glSpriteParameterivSGIX = (GLEEPFNGLSPRITEPARAMETERIVSGIXPROC) __GLeeGetProcAddress("glSpriteParameterivSGIX"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_texture_multi_buffer(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_point_parameters(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_point_parameters + if ((GLeeFuncPtr_glPointParameterfEXT = (GLEEPFNGLPOINTPARAMETERFEXTPROC) __GLeeGetProcAddress("glPointParameterfEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glPointParameterfvEXT = (GLEEPFNGLPOINTPARAMETERFVEXTPROC) __GLeeGetProcAddress("glPointParameterfvEXT"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIS_point_parameters(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIS_point_parameters + if ((GLeeFuncPtr_glPointParameterfSGIS = (GLEEPFNGLPOINTPARAMETERFSGISPROC) __GLeeGetProcAddress("glPointParameterfSGIS"))!=0) nLinked++; + if ((GLeeFuncPtr_glPointParameterfvSGIS = (GLEEPFNGLPOINTPARAMETERFVSGISPROC) __GLeeGetProcAddress("glPointParameterfvSGIS"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_instruments(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIX_instruments + if ((GLeeFuncPtr_glGetInstrumentsSGIX = (GLEEPFNGLGETINSTRUMENTSSGIXPROC) __GLeeGetProcAddress("glGetInstrumentsSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glInstrumentsBufferSGIX = (GLEEPFNGLINSTRUMENTSBUFFERSGIXPROC) __GLeeGetProcAddress("glInstrumentsBufferSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glPollInstrumentsSGIX = (GLEEPFNGLPOLLINSTRUMENTSSGIXPROC) __GLeeGetProcAddress("glPollInstrumentsSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glReadInstrumentsSGIX = (GLEEPFNGLREADINSTRUMENTSSGIXPROC) __GLeeGetProcAddress("glReadInstrumentsSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glStartInstrumentsSGIX = (GLEEPFNGLSTARTINSTRUMENTSSGIXPROC) __GLeeGetProcAddress("glStartInstrumentsSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glStopInstrumentsSGIX = (GLEEPFNGLSTOPINSTRUMENTSSGIXPROC) __GLeeGetProcAddress("glStopInstrumentsSGIX"))!=0) nLinked++; +#endif + if (nLinked==6) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_texture_scale_bias(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_framezoom(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIX_framezoom + if ((GLeeFuncPtr_glFrameZoomSGIX = (GLEEPFNGLFRAMEZOOMSGIXPROC) __GLeeGetProcAddress("glFrameZoomSGIX"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_tag_sample_buffer(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIX_tag_sample_buffer + if ((GLeeFuncPtr_glTagSampleBufferSGIX = (GLEEPFNGLTAGSAMPLEBUFFERSGIXPROC) __GLeeGetProcAddress("glTagSampleBufferSGIX"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_FfdMaskSGIX(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_polynomial_ffd(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIX_polynomial_ffd + if ((GLeeFuncPtr_glDeformationMap3dSGIX = (GLEEPFNGLDEFORMATIONMAP3DSGIXPROC) __GLeeGetProcAddress("glDeformationMap3dSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeformationMap3fSGIX = (GLEEPFNGLDEFORMATIONMAP3FSGIXPROC) __GLeeGetProcAddress("glDeformationMap3fSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeformSGIX = (GLEEPFNGLDEFORMSGIXPROC) __GLeeGetProcAddress("glDeformSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glLoadIdentityDeformationMapSGIX = (GLEEPFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC) __GLeeGetProcAddress("glLoadIdentityDeformationMapSGIX"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_reference_plane(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIX_reference_plane + if ((GLeeFuncPtr_glReferencePlaneSGIX = (GLEEPFNGLREFERENCEPLANESGIXPROC) __GLeeGetProcAddress("glReferencePlaneSGIX"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_flush_raster(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIX_flush_raster + if ((GLeeFuncPtr_glFlushRasterSGIX = (GLEEPFNGLFLUSHRASTERSGIXPROC) __GLeeGetProcAddress("glFlushRasterSGIX"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_depth_texture(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIS_fog_function(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIS_fog_function + if ((GLeeFuncPtr_glFogFuncSGIS = (GLEEPFNGLFOGFUNCSGISPROC) __GLeeGetProcAddress("glFogFuncSGIS"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFogFuncSGIS = (GLEEPFNGLGETFOGFUNCSGISPROC) __GLeeGetProcAddress("glGetFogFuncSGIS"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_fog_offset(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_HP_image_transform(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_HP_image_transform + if ((GLeeFuncPtr_glImageTransformParameteriHP = (GLEEPFNGLIMAGETRANSFORMPARAMETERIHPPROC) __GLeeGetProcAddress("glImageTransformParameteriHP"))!=0) nLinked++; + if ((GLeeFuncPtr_glImageTransformParameterfHP = (GLEEPFNGLIMAGETRANSFORMPARAMETERFHPPROC) __GLeeGetProcAddress("glImageTransformParameterfHP"))!=0) nLinked++; + if ((GLeeFuncPtr_glImageTransformParameterivHP = (GLEEPFNGLIMAGETRANSFORMPARAMETERIVHPPROC) __GLeeGetProcAddress("glImageTransformParameterivHP"))!=0) nLinked++; + if ((GLeeFuncPtr_glImageTransformParameterfvHP = (GLEEPFNGLIMAGETRANSFORMPARAMETERFVHPPROC) __GLeeGetProcAddress("glImageTransformParameterfvHP"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetImageTransformParameterivHP = (GLEEPFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) __GLeeGetProcAddress("glGetImageTransformParameterivHP"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetImageTransformParameterfvHP = (GLEEPFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) __GLeeGetProcAddress("glGetImageTransformParameterfvHP"))!=0) nLinked++; +#endif + if (nLinked==6) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_HP_convolution_border_modes(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_INGR_palette_buffer(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_texture_add_env(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_color_subtable(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_color_subtable + if ((GLeeFuncPtr_glColorSubTableEXT = (GLEEPFNGLCOLORSUBTABLEEXTPROC) __GLeeGetProcAddress("glColorSubTableEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyColorSubTableEXT = (GLEEPFNGLCOPYCOLORSUBTABLEEXTPROC) __GLeeGetProcAddress("glCopyColorSubTableEXT"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_PGI_vertex_hints(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_PGI_misc_hints(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_PGI_misc_hints + if ((GLeeFuncPtr_glHintPGI = (GLEEPFNGLHINTPGIPROC) __GLeeGetProcAddress("glHintPGI"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_paletted_texture(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_paletted_texture + if ((GLeeFuncPtr_glColorTableEXT = (GLEEPFNGLCOLORTABLEEXTPROC) __GLeeGetProcAddress("glColorTableEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetColorTableEXT = (GLEEPFNGLGETCOLORTABLEEXTPROC) __GLeeGetProcAddress("glGetColorTableEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetColorTableParameterivEXT = (GLEEPFNGLGETCOLORTABLEPARAMETERIVEXTPROC) __GLeeGetProcAddress("glGetColorTableParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetColorTableParameterfvEXT = (GLEEPFNGLGETCOLORTABLEPARAMETERFVEXTPROC) __GLeeGetProcAddress("glGetColorTableParameterfvEXT"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_clip_volume_hint(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_list_priority(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIX_list_priority + if ((GLeeFuncPtr_glGetListParameterfvSGIX = (GLEEPFNGLGETLISTPARAMETERFVSGIXPROC) __GLeeGetProcAddress("glGetListParameterfvSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetListParameterivSGIX = (GLEEPFNGLGETLISTPARAMETERIVSGIXPROC) __GLeeGetProcAddress("glGetListParameterivSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glListParameterfSGIX = (GLEEPFNGLLISTPARAMETERFSGIXPROC) __GLeeGetProcAddress("glListParameterfSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glListParameterfvSGIX = (GLEEPFNGLLISTPARAMETERFVSGIXPROC) __GLeeGetProcAddress("glListParameterfvSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glListParameteriSGIX = (GLEEPFNGLLISTPARAMETERISGIXPROC) __GLeeGetProcAddress("glListParameteriSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glListParameterivSGIX = (GLEEPFNGLLISTPARAMETERIVSGIXPROC) __GLeeGetProcAddress("glListParameterivSGIX"))!=0) nLinked++; +#endif + if (nLinked==6) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_ir_instrument1(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_calligraphic_fragment(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_texture_lod_bias(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_shadow_ambient(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_index_texture(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_index_material(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_index_material + if ((GLeeFuncPtr_glIndexMaterialEXT = (GLEEPFNGLINDEXMATERIALEXTPROC) __GLeeGetProcAddress("glIndexMaterialEXT"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_index_func(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_index_func + if ((GLeeFuncPtr_glIndexFuncEXT = (GLEEPFNGLINDEXFUNCEXTPROC) __GLeeGetProcAddress("glIndexFuncEXT"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_index_array_formats(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_compiled_vertex_array(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_compiled_vertex_array + if ((GLeeFuncPtr_glLockArraysEXT = (GLEEPFNGLLOCKARRAYSEXTPROC) __GLeeGetProcAddress("glLockArraysEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glUnlockArraysEXT = (GLEEPFNGLUNLOCKARRAYSEXTPROC) __GLeeGetProcAddress("glUnlockArraysEXT"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_cull_vertex(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_cull_vertex + if ((GLeeFuncPtr_glCullParameterdvEXT = (GLEEPFNGLCULLPARAMETERDVEXTPROC) __GLeeGetProcAddress("glCullParameterdvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCullParameterfvEXT = (GLEEPFNGLCULLPARAMETERFVEXTPROC) __GLeeGetProcAddress("glCullParameterfvEXT"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_ycrcb(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_fragment_lighting(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIX_fragment_lighting + if ((GLeeFuncPtr_glFragmentColorMaterialSGIX = (GLEEPFNGLFRAGMENTCOLORMATERIALSGIXPROC) __GLeeGetProcAddress("glFragmentColorMaterialSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentLightfSGIX = (GLEEPFNGLFRAGMENTLIGHTFSGIXPROC) __GLeeGetProcAddress("glFragmentLightfSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentLightfvSGIX = (GLEEPFNGLFRAGMENTLIGHTFVSGIXPROC) __GLeeGetProcAddress("glFragmentLightfvSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentLightiSGIX = (GLEEPFNGLFRAGMENTLIGHTISGIXPROC) __GLeeGetProcAddress("glFragmentLightiSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentLightivSGIX = (GLEEPFNGLFRAGMENTLIGHTIVSGIXPROC) __GLeeGetProcAddress("glFragmentLightivSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentLightModelfSGIX = (GLEEPFNGLFRAGMENTLIGHTMODELFSGIXPROC) __GLeeGetProcAddress("glFragmentLightModelfSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentLightModelfvSGIX = (GLEEPFNGLFRAGMENTLIGHTMODELFVSGIXPROC) __GLeeGetProcAddress("glFragmentLightModelfvSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentLightModeliSGIX = (GLEEPFNGLFRAGMENTLIGHTMODELISGIXPROC) __GLeeGetProcAddress("glFragmentLightModeliSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentLightModelivSGIX = (GLEEPFNGLFRAGMENTLIGHTMODELIVSGIXPROC) __GLeeGetProcAddress("glFragmentLightModelivSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentMaterialfSGIX = (GLEEPFNGLFRAGMENTMATERIALFSGIXPROC) __GLeeGetProcAddress("glFragmentMaterialfSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentMaterialfvSGIX = (GLEEPFNGLFRAGMENTMATERIALFVSGIXPROC) __GLeeGetProcAddress("glFragmentMaterialfvSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentMaterialiSGIX = (GLEEPFNGLFRAGMENTMATERIALISGIXPROC) __GLeeGetProcAddress("glFragmentMaterialiSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentMaterialivSGIX = (GLEEPFNGLFRAGMENTMATERIALIVSGIXPROC) __GLeeGetProcAddress("glFragmentMaterialivSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFragmentLightfvSGIX = (GLEEPFNGLGETFRAGMENTLIGHTFVSGIXPROC) __GLeeGetProcAddress("glGetFragmentLightfvSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFragmentLightivSGIX = (GLEEPFNGLGETFRAGMENTLIGHTIVSGIXPROC) __GLeeGetProcAddress("glGetFragmentLightivSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFragmentMaterialfvSGIX = (GLEEPFNGLGETFRAGMENTMATERIALFVSGIXPROC) __GLeeGetProcAddress("glGetFragmentMaterialfvSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFragmentMaterialivSGIX = (GLEEPFNGLGETFRAGMENTMATERIALIVSGIXPROC) __GLeeGetProcAddress("glGetFragmentMaterialivSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glLightEnviSGIX = (GLEEPFNGLLIGHTENVISGIXPROC) __GLeeGetProcAddress("glLightEnviSGIX"))!=0) nLinked++; +#endif + if (nLinked==18) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_IBM_rasterpos_clip(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_HP_texture_lighting(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_draw_range_elements(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_draw_range_elements + if ((GLeeFuncPtr_glDrawRangeElementsEXT = (GLEEPFNGLDRAWRANGEELEMENTSEXTPROC) __GLeeGetProcAddress("glDrawRangeElementsEXT"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_WIN_phong_shading(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_WIN_specular_fog(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_light_texture(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_light_texture + if ((GLeeFuncPtr_glApplyTextureEXT = (GLEEPFNGLAPPLYTEXTUREEXTPROC) __GLeeGetProcAddress("glApplyTextureEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTextureLightEXT = (GLEEPFNGLTEXTURELIGHTEXTPROC) __GLeeGetProcAddress("glTextureLightEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTextureMaterialEXT = (GLEEPFNGLTEXTUREMATERIALEXTPROC) __GLeeGetProcAddress("glTextureMaterialEXT"))!=0) nLinked++; +#endif + if (nLinked==3) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_blend_alpha_minmax(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_impact_pixel_texture(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_bgra(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_async(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIX_async + if ((GLeeFuncPtr_glAsyncMarkerSGIX = (GLEEPFNGLASYNCMARKERSGIXPROC) __GLeeGetProcAddress("glAsyncMarkerSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glFinishAsyncSGIX = (GLEEPFNGLFINISHASYNCSGIXPROC) __GLeeGetProcAddress("glFinishAsyncSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glPollAsyncSGIX = (GLEEPFNGLPOLLASYNCSGIXPROC) __GLeeGetProcAddress("glPollAsyncSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenAsyncMarkersSGIX = (GLEEPFNGLGENASYNCMARKERSSGIXPROC) __GLeeGetProcAddress("glGenAsyncMarkersSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteAsyncMarkersSGIX = (GLEEPFNGLDELETEASYNCMARKERSSGIXPROC) __GLeeGetProcAddress("glDeleteAsyncMarkersSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsAsyncMarkerSGIX = (GLEEPFNGLISASYNCMARKERSGIXPROC) __GLeeGetProcAddress("glIsAsyncMarkerSGIX"))!=0) nLinked++; +#endif + if (nLinked==6) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_async_pixel(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_async_histogram(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_INTEL_texture_scissor(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_INTEL_parallel_arrays(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_INTEL_parallel_arrays + if ((GLeeFuncPtr_glVertexPointervINTEL = (GLEEPFNGLVERTEXPOINTERVINTELPROC) __GLeeGetProcAddress("glVertexPointervINTEL"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormalPointervINTEL = (GLEEPFNGLNORMALPOINTERVINTELPROC) __GLeeGetProcAddress("glNormalPointervINTEL"))!=0) nLinked++; + if ((GLeeFuncPtr_glColorPointervINTEL = (GLEEPFNGLCOLORPOINTERVINTELPROC) __GLeeGetProcAddress("glColorPointervINTEL"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoordPointervINTEL = (GLEEPFNGLTEXCOORDPOINTERVINTELPROC) __GLeeGetProcAddress("glTexCoordPointervINTEL"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_HP_occlusion_test(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_pixel_transform(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_pixel_transform + if ((GLeeFuncPtr_glPixelTransformParameteriEXT = (GLEEPFNGLPIXELTRANSFORMPARAMETERIEXTPROC) __GLeeGetProcAddress("glPixelTransformParameteriEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glPixelTransformParameterfEXT = (GLEEPFNGLPIXELTRANSFORMPARAMETERFEXTPROC) __GLeeGetProcAddress("glPixelTransformParameterfEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glPixelTransformParameterivEXT = (GLEEPFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) __GLeeGetProcAddress("glPixelTransformParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glPixelTransformParameterfvEXT = (GLEEPFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) __GLeeGetProcAddress("glPixelTransformParameterfvEXT"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_pixel_transform_color_table(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_shared_texture_palette(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_separate_specular_color(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_secondary_color(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_secondary_color + if ((GLeeFuncPtr_glSecondaryColor3bEXT = (GLEEPFNGLSECONDARYCOLOR3BEXTPROC) __GLeeGetProcAddress("glSecondaryColor3bEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3bvEXT = (GLEEPFNGLSECONDARYCOLOR3BVEXTPROC) __GLeeGetProcAddress("glSecondaryColor3bvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3dEXT = (GLEEPFNGLSECONDARYCOLOR3DEXTPROC) __GLeeGetProcAddress("glSecondaryColor3dEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3dvEXT = (GLEEPFNGLSECONDARYCOLOR3DVEXTPROC) __GLeeGetProcAddress("glSecondaryColor3dvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3fEXT = (GLEEPFNGLSECONDARYCOLOR3FEXTPROC) __GLeeGetProcAddress("glSecondaryColor3fEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3fvEXT = (GLEEPFNGLSECONDARYCOLOR3FVEXTPROC) __GLeeGetProcAddress("glSecondaryColor3fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3iEXT = (GLEEPFNGLSECONDARYCOLOR3IEXTPROC) __GLeeGetProcAddress("glSecondaryColor3iEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3ivEXT = (GLEEPFNGLSECONDARYCOLOR3IVEXTPROC) __GLeeGetProcAddress("glSecondaryColor3ivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3sEXT = (GLEEPFNGLSECONDARYCOLOR3SEXTPROC) __GLeeGetProcAddress("glSecondaryColor3sEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3svEXT = (GLEEPFNGLSECONDARYCOLOR3SVEXTPROC) __GLeeGetProcAddress("glSecondaryColor3svEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3ubEXT = (GLEEPFNGLSECONDARYCOLOR3UBEXTPROC) __GLeeGetProcAddress("glSecondaryColor3ubEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3ubvEXT = (GLEEPFNGLSECONDARYCOLOR3UBVEXTPROC) __GLeeGetProcAddress("glSecondaryColor3ubvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3uiEXT = (GLEEPFNGLSECONDARYCOLOR3UIEXTPROC) __GLeeGetProcAddress("glSecondaryColor3uiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3uivEXT = (GLEEPFNGLSECONDARYCOLOR3UIVEXTPROC) __GLeeGetProcAddress("glSecondaryColor3uivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3usEXT = (GLEEPFNGLSECONDARYCOLOR3USEXTPROC) __GLeeGetProcAddress("glSecondaryColor3usEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3usvEXT = (GLEEPFNGLSECONDARYCOLOR3USVEXTPROC) __GLeeGetProcAddress("glSecondaryColor3usvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColorPointerEXT = (GLEEPFNGLSECONDARYCOLORPOINTEREXTPROC) __GLeeGetProcAddress("glSecondaryColorPointerEXT"))!=0) nLinked++; +#endif + if (nLinked==17) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_texture_perturb_normal(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_texture_perturb_normal + if ((GLeeFuncPtr_glTextureNormalEXT = (GLEEPFNGLTEXTURENORMALEXTPROC) __GLeeGetProcAddress("glTextureNormalEXT"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_multi_draw_arrays(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_multi_draw_arrays + if ((GLeeFuncPtr_glMultiDrawArraysEXT = (GLEEPFNGLMULTIDRAWARRAYSEXTPROC) __GLeeGetProcAddress("glMultiDrawArraysEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiDrawElementsEXT = (GLEEPFNGLMULTIDRAWELEMENTSEXTPROC) __GLeeGetProcAddress("glMultiDrawElementsEXT"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_fog_coord(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_fog_coord + if ((GLeeFuncPtr_glFogCoordfEXT = (GLEEPFNGLFOGCOORDFEXTPROC) __GLeeGetProcAddress("glFogCoordfEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFogCoordfvEXT = (GLEEPFNGLFOGCOORDFVEXTPROC) __GLeeGetProcAddress("glFogCoordfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFogCoorddEXT = (GLEEPFNGLFOGCOORDDEXTPROC) __GLeeGetProcAddress("glFogCoorddEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFogCoorddvEXT = (GLEEPFNGLFOGCOORDDVEXTPROC) __GLeeGetProcAddress("glFogCoorddvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFogCoordPointerEXT = (GLEEPFNGLFOGCOORDPOINTEREXTPROC) __GLeeGetProcAddress("glFogCoordPointerEXT"))!=0) nLinked++; +#endif + if (nLinked==5) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_REND_screen_coordinates(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_coordinate_frame(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_coordinate_frame + if ((GLeeFuncPtr_glTangent3bEXT = (GLEEPFNGLTANGENT3BEXTPROC) __GLeeGetProcAddress("glTangent3bEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTangent3bvEXT = (GLEEPFNGLTANGENT3BVEXTPROC) __GLeeGetProcAddress("glTangent3bvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTangent3dEXT = (GLEEPFNGLTANGENT3DEXTPROC) __GLeeGetProcAddress("glTangent3dEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTangent3dvEXT = (GLEEPFNGLTANGENT3DVEXTPROC) __GLeeGetProcAddress("glTangent3dvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTangent3fEXT = (GLEEPFNGLTANGENT3FEXTPROC) __GLeeGetProcAddress("glTangent3fEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTangent3fvEXT = (GLEEPFNGLTANGENT3FVEXTPROC) __GLeeGetProcAddress("glTangent3fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTangent3iEXT = (GLEEPFNGLTANGENT3IEXTPROC) __GLeeGetProcAddress("glTangent3iEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTangent3ivEXT = (GLEEPFNGLTANGENT3IVEXTPROC) __GLeeGetProcAddress("glTangent3ivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTangent3sEXT = (GLEEPFNGLTANGENT3SEXTPROC) __GLeeGetProcAddress("glTangent3sEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTangent3svEXT = (GLEEPFNGLTANGENT3SVEXTPROC) __GLeeGetProcAddress("glTangent3svEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBinormal3bEXT = (GLEEPFNGLBINORMAL3BEXTPROC) __GLeeGetProcAddress("glBinormal3bEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBinormal3bvEXT = (GLEEPFNGLBINORMAL3BVEXTPROC) __GLeeGetProcAddress("glBinormal3bvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBinormal3dEXT = (GLEEPFNGLBINORMAL3DEXTPROC) __GLeeGetProcAddress("glBinormal3dEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBinormal3dvEXT = (GLEEPFNGLBINORMAL3DVEXTPROC) __GLeeGetProcAddress("glBinormal3dvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBinormal3fEXT = (GLEEPFNGLBINORMAL3FEXTPROC) __GLeeGetProcAddress("glBinormal3fEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBinormal3fvEXT = (GLEEPFNGLBINORMAL3FVEXTPROC) __GLeeGetProcAddress("glBinormal3fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBinormal3iEXT = (GLEEPFNGLBINORMAL3IEXTPROC) __GLeeGetProcAddress("glBinormal3iEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBinormal3ivEXT = (GLEEPFNGLBINORMAL3IVEXTPROC) __GLeeGetProcAddress("glBinormal3ivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBinormal3sEXT = (GLEEPFNGLBINORMAL3SEXTPROC) __GLeeGetProcAddress("glBinormal3sEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBinormal3svEXT = (GLEEPFNGLBINORMAL3SVEXTPROC) __GLeeGetProcAddress("glBinormal3svEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTangentPointerEXT = (GLEEPFNGLTANGENTPOINTEREXTPROC) __GLeeGetProcAddress("glTangentPointerEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBinormalPointerEXT = (GLEEPFNGLBINORMALPOINTEREXTPROC) __GLeeGetProcAddress("glBinormalPointerEXT"))!=0) nLinked++; +#endif + if (nLinked==22) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_texture_env_combine(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_APPLE_specular_vector(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_APPLE_transform_hint(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_fog_scale(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SUNX_constant_data(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SUNX_constant_data + if ((GLeeFuncPtr_glFinishTextureSUNX = (GLEEPFNGLFINISHTEXTURESUNXPROC) __GLeeGetProcAddress("glFinishTextureSUNX"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SUN_global_alpha(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SUN_global_alpha + if ((GLeeFuncPtr_glGlobalAlphaFactorbSUN = (GLEEPFNGLGLOBALALPHAFACTORBSUNPROC) __GLeeGetProcAddress("glGlobalAlphaFactorbSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glGlobalAlphaFactorsSUN = (GLEEPFNGLGLOBALALPHAFACTORSSUNPROC) __GLeeGetProcAddress("glGlobalAlphaFactorsSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glGlobalAlphaFactoriSUN = (GLEEPFNGLGLOBALALPHAFACTORISUNPROC) __GLeeGetProcAddress("glGlobalAlphaFactoriSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glGlobalAlphaFactorfSUN = (GLEEPFNGLGLOBALALPHAFACTORFSUNPROC) __GLeeGetProcAddress("glGlobalAlphaFactorfSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glGlobalAlphaFactordSUN = (GLEEPFNGLGLOBALALPHAFACTORDSUNPROC) __GLeeGetProcAddress("glGlobalAlphaFactordSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glGlobalAlphaFactorubSUN = (GLEEPFNGLGLOBALALPHAFACTORUBSUNPROC) __GLeeGetProcAddress("glGlobalAlphaFactorubSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glGlobalAlphaFactorusSUN = (GLEEPFNGLGLOBALALPHAFACTORUSSUNPROC) __GLeeGetProcAddress("glGlobalAlphaFactorusSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glGlobalAlphaFactoruiSUN = (GLEEPFNGLGLOBALALPHAFACTORUISUNPROC) __GLeeGetProcAddress("glGlobalAlphaFactoruiSUN"))!=0) nLinked++; +#endif + if (nLinked==8) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SUN_triangle_list(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SUN_triangle_list + if ((GLeeFuncPtr_glReplacementCodeuiSUN = (GLEEPFNGLREPLACEMENTCODEUISUNPROC) __GLeeGetProcAddress("glReplacementCodeuiSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeusSUN = (GLEEPFNGLREPLACEMENTCODEUSSUNPROC) __GLeeGetProcAddress("glReplacementCodeusSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeubSUN = (GLEEPFNGLREPLACEMENTCODEUBSUNPROC) __GLeeGetProcAddress("glReplacementCodeubSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuivSUN = (GLEEPFNGLREPLACEMENTCODEUIVSUNPROC) __GLeeGetProcAddress("glReplacementCodeuivSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeusvSUN = (GLEEPFNGLREPLACEMENTCODEUSVSUNPROC) __GLeeGetProcAddress("glReplacementCodeusvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeubvSUN = (GLEEPFNGLREPLACEMENTCODEUBVSUNPROC) __GLeeGetProcAddress("glReplacementCodeubvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodePointerSUN = (GLEEPFNGLREPLACEMENTCODEPOINTERSUNPROC) __GLeeGetProcAddress("glReplacementCodePointerSUN"))!=0) nLinked++; +#endif + if (nLinked==7) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SUN_vertex(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SUN_vertex + if ((GLeeFuncPtr_glColor4ubVertex2fSUN = (GLEEPFNGLCOLOR4UBVERTEX2FSUNPROC) __GLeeGetProcAddress("glColor4ubVertex2fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glColor4ubVertex2fvSUN = (GLEEPFNGLCOLOR4UBVERTEX2FVSUNPROC) __GLeeGetProcAddress("glColor4ubVertex2fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glColor4ubVertex3fSUN = (GLEEPFNGLCOLOR4UBVERTEX3FSUNPROC) __GLeeGetProcAddress("glColor4ubVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glColor4ubVertex3fvSUN = (GLEEPFNGLCOLOR4UBVERTEX3FVSUNPROC) __GLeeGetProcAddress("glColor4ubVertex3fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glColor3fVertex3fSUN = (GLEEPFNGLCOLOR3FVERTEX3FSUNPROC) __GLeeGetProcAddress("glColor3fVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glColor3fVertex3fvSUN = (GLEEPFNGLCOLOR3FVERTEX3FVSUNPROC) __GLeeGetProcAddress("glColor3fVertex3fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormal3fVertex3fSUN = (GLEEPFNGLNORMAL3FVERTEX3FSUNPROC) __GLeeGetProcAddress("glNormal3fVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormal3fVertex3fvSUN = (GLEEPFNGLNORMAL3FVERTEX3FVSUNPROC) __GLeeGetProcAddress("glNormal3fVertex3fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glColor4fNormal3fVertex3fSUN = (GLEEPFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) __GLeeGetProcAddress("glColor4fNormal3fVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glColor4fNormal3fVertex3fvSUN = (GLEEPFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) __GLeeGetProcAddress("glColor4fNormal3fVertex3fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord2fVertex3fSUN = (GLEEPFNGLTEXCOORD2FVERTEX3FSUNPROC) __GLeeGetProcAddress("glTexCoord2fVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord2fVertex3fvSUN = (GLEEPFNGLTEXCOORD2FVERTEX3FVSUNPROC) __GLeeGetProcAddress("glTexCoord2fVertex3fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord4fVertex4fSUN = (GLEEPFNGLTEXCOORD4FVERTEX4FSUNPROC) __GLeeGetProcAddress("glTexCoord4fVertex4fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord4fVertex4fvSUN = (GLEEPFNGLTEXCOORD4FVERTEX4FVSUNPROC) __GLeeGetProcAddress("glTexCoord4fVertex4fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord2fColor4ubVertex3fSUN = (GLEEPFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) __GLeeGetProcAddress("glTexCoord2fColor4ubVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord2fColor4ubVertex3fvSUN = (GLEEPFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) __GLeeGetProcAddress("glTexCoord2fColor4ubVertex3fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord2fColor3fVertex3fSUN = (GLEEPFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) __GLeeGetProcAddress("glTexCoord2fColor3fVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord2fColor3fVertex3fvSUN = (GLEEPFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) __GLeeGetProcAddress("glTexCoord2fColor3fVertex3fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord2fNormal3fVertex3fSUN = (GLEEPFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) __GLeeGetProcAddress("glTexCoord2fNormal3fVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord2fNormal3fVertex3fvSUN = (GLEEPFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) __GLeeGetProcAddress("glTexCoord2fNormal3fVertex3fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord2fColor4fNormal3fVertex3fSUN = (GLEEPFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) __GLeeGetProcAddress("glTexCoord2fColor4fNormal3fVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord2fColor4fNormal3fVertex3fvSUN = (GLEEPFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) __GLeeGetProcAddress("glTexCoord2fColor4fNormal3fVertex3fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord4fColor4fNormal3fVertex4fSUN = (GLEEPFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) __GLeeGetProcAddress("glTexCoord4fColor4fNormal3fVertex4fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord4fColor4fNormal3fVertex4fvSUN = (GLEEPFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) __GLeeGetProcAddress("glTexCoord4fColor4fNormal3fVertex4fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuiVertex3fSUN = (GLEEPFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) __GLeeGetProcAddress("glReplacementCodeuiVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuiVertex3fvSUN = (GLEEPFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) __GLeeGetProcAddress("glReplacementCodeuiVertex3fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuiColor4ubVertex3fSUN = (GLEEPFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) __GLeeGetProcAddress("glReplacementCodeuiColor4ubVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuiColor4ubVertex3fvSUN = (GLEEPFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) __GLeeGetProcAddress("glReplacementCodeuiColor4ubVertex3fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuiColor3fVertex3fSUN = (GLEEPFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) __GLeeGetProcAddress("glReplacementCodeuiColor3fVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuiColor3fVertex3fvSUN = (GLEEPFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) __GLeeGetProcAddress("glReplacementCodeuiColor3fVertex3fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuiNormal3fVertex3fSUN = (GLEEPFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) __GLeeGetProcAddress("glReplacementCodeuiNormal3fVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuiNormal3fVertex3fvSUN = (GLEEPFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) __GLeeGetProcAddress("glReplacementCodeuiNormal3fVertex3fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuiColor4fNormal3fVertex3fSUN = (GLEEPFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) __GLeeGetProcAddress("glReplacementCodeuiColor4fNormal3fVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuiColor4fNormal3fVertex3fvSUN = (GLEEPFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) __GLeeGetProcAddress("glReplacementCodeuiColor4fNormal3fVertex3fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuiTexCoord2fVertex3fSUN = (GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) __GLeeGetProcAddress("glReplacementCodeuiTexCoord2fVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuiTexCoord2fVertex3fvSUN = (GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) __GLeeGetProcAddress("glReplacementCodeuiTexCoord2fVertex3fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN = (GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) __GLeeGetProcAddress("glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN = (GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) __GLeeGetProcAddress("glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN = (GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) __GLeeGetProcAddress("glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN"))!=0) nLinked++; + if ((GLeeFuncPtr_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN = (GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) __GLeeGetProcAddress("glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN"))!=0) nLinked++; +#endif + if (nLinked==40) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_blend_func_separate(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_blend_func_separate + if ((GLeeFuncPtr_glBlendFuncSeparateEXT = (GLEEPFNGLBLENDFUNCSEPARATEEXTPROC) __GLeeGetProcAddress("glBlendFuncSeparateEXT"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_INGR_color_clamp(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_INGR_interlace_read(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_stencil_wrap(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_422_pixels(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_texgen_reflection(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_texture_cube_map(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SUN_convolution_border_modes(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_texture_env_add(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_texture_lod_bias(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_texture_filter_anisotropic(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_vertex_weighting(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_vertex_weighting + if ((GLeeFuncPtr_glVertexWeightfEXT = (GLEEPFNGLVERTEXWEIGHTFEXTPROC) __GLeeGetProcAddress("glVertexWeightfEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexWeightfvEXT = (GLEEPFNGLVERTEXWEIGHTFVEXTPROC) __GLeeGetProcAddress("glVertexWeightfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexWeightPointerEXT = (GLEEPFNGLVERTEXWEIGHTPOINTEREXTPROC) __GLeeGetProcAddress("glVertexWeightPointerEXT"))!=0) nLinked++; +#endif + if (nLinked==3) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_NV_light_max_exponent(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_vertex_array_range(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_vertex_array_range + if ((GLeeFuncPtr_glFlushVertexArrayRangeNV = (GLEEPFNGLFLUSHVERTEXARRAYRANGENVPROC) __GLeeGetProcAddress("glFlushVertexArrayRangeNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexArrayRangeNV = (GLEEPFNGLVERTEXARRAYRANGENVPROC) __GLeeGetProcAddress("glVertexArrayRangeNV"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_NV_register_combiners(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_register_combiners + if ((GLeeFuncPtr_glCombinerParameterfvNV = (GLEEPFNGLCOMBINERPARAMETERFVNVPROC) __GLeeGetProcAddress("glCombinerParameterfvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glCombinerParameterfNV = (GLEEPFNGLCOMBINERPARAMETERFNVPROC) __GLeeGetProcAddress("glCombinerParameterfNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glCombinerParameterivNV = (GLEEPFNGLCOMBINERPARAMETERIVNVPROC) __GLeeGetProcAddress("glCombinerParameterivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glCombinerParameteriNV = (GLEEPFNGLCOMBINERPARAMETERINVPROC) __GLeeGetProcAddress("glCombinerParameteriNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glCombinerInputNV = (GLEEPFNGLCOMBINERINPUTNVPROC) __GLeeGetProcAddress("glCombinerInputNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glCombinerOutputNV = (GLEEPFNGLCOMBINEROUTPUTNVPROC) __GLeeGetProcAddress("glCombinerOutputNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glFinalCombinerInputNV = (GLEEPFNGLFINALCOMBINERINPUTNVPROC) __GLeeGetProcAddress("glFinalCombinerInputNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetCombinerInputParameterfvNV = (GLEEPFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) __GLeeGetProcAddress("glGetCombinerInputParameterfvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetCombinerInputParameterivNV = (GLEEPFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) __GLeeGetProcAddress("glGetCombinerInputParameterivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetCombinerOutputParameterfvNV = (GLEEPFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) __GLeeGetProcAddress("glGetCombinerOutputParameterfvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetCombinerOutputParameterivNV = (GLEEPFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) __GLeeGetProcAddress("glGetCombinerOutputParameterivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFinalCombinerInputParameterfvNV = (GLEEPFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) __GLeeGetProcAddress("glGetFinalCombinerInputParameterfvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFinalCombinerInputParameterivNV = (GLEEPFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) __GLeeGetProcAddress("glGetFinalCombinerInputParameterivNV"))!=0) nLinked++; +#endif + if (nLinked==13) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_NV_fog_distance(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_texgen_emboss(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_blend_square(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_texture_env_combine4(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_MESA_resize_buffers(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_MESA_resize_buffers + if ((GLeeFuncPtr_glResizeBuffersMESA = (GLEEPFNGLRESIZEBUFFERSMESAPROC) __GLeeGetProcAddress("glResizeBuffersMESA"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_MESA_window_pos(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_MESA_window_pos + if ((GLeeFuncPtr_glWindowPos2dMESA = (GLEEPFNGLWINDOWPOS2DMESAPROC) __GLeeGetProcAddress("glWindowPos2dMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2dvMESA = (GLEEPFNGLWINDOWPOS2DVMESAPROC) __GLeeGetProcAddress("glWindowPos2dvMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2fMESA = (GLEEPFNGLWINDOWPOS2FMESAPROC) __GLeeGetProcAddress("glWindowPos2fMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2fvMESA = (GLEEPFNGLWINDOWPOS2FVMESAPROC) __GLeeGetProcAddress("glWindowPos2fvMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2iMESA = (GLEEPFNGLWINDOWPOS2IMESAPROC) __GLeeGetProcAddress("glWindowPos2iMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2ivMESA = (GLEEPFNGLWINDOWPOS2IVMESAPROC) __GLeeGetProcAddress("glWindowPos2ivMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2sMESA = (GLEEPFNGLWINDOWPOS2SMESAPROC) __GLeeGetProcAddress("glWindowPos2sMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos2svMESA = (GLEEPFNGLWINDOWPOS2SVMESAPROC) __GLeeGetProcAddress("glWindowPos2svMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3dMESA = (GLEEPFNGLWINDOWPOS3DMESAPROC) __GLeeGetProcAddress("glWindowPos3dMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3dvMESA = (GLEEPFNGLWINDOWPOS3DVMESAPROC) __GLeeGetProcAddress("glWindowPos3dvMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3fMESA = (GLEEPFNGLWINDOWPOS3FMESAPROC) __GLeeGetProcAddress("glWindowPos3fMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3fvMESA = (GLEEPFNGLWINDOWPOS3FVMESAPROC) __GLeeGetProcAddress("glWindowPos3fvMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3iMESA = (GLEEPFNGLWINDOWPOS3IMESAPROC) __GLeeGetProcAddress("glWindowPos3iMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3ivMESA = (GLEEPFNGLWINDOWPOS3IVMESAPROC) __GLeeGetProcAddress("glWindowPos3ivMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3sMESA = (GLEEPFNGLWINDOWPOS3SMESAPROC) __GLeeGetProcAddress("glWindowPos3sMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos3svMESA = (GLEEPFNGLWINDOWPOS3SVMESAPROC) __GLeeGetProcAddress("glWindowPos3svMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos4dMESA = (GLEEPFNGLWINDOWPOS4DMESAPROC) __GLeeGetProcAddress("glWindowPos4dMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos4dvMESA = (GLEEPFNGLWINDOWPOS4DVMESAPROC) __GLeeGetProcAddress("glWindowPos4dvMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos4fMESA = (GLEEPFNGLWINDOWPOS4FMESAPROC) __GLeeGetProcAddress("glWindowPos4fMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos4fvMESA = (GLEEPFNGLWINDOWPOS4FVMESAPROC) __GLeeGetProcAddress("glWindowPos4fvMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos4iMESA = (GLEEPFNGLWINDOWPOS4IMESAPROC) __GLeeGetProcAddress("glWindowPos4iMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos4ivMESA = (GLEEPFNGLWINDOWPOS4IVMESAPROC) __GLeeGetProcAddress("glWindowPos4ivMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos4sMESA = (GLEEPFNGLWINDOWPOS4SMESAPROC) __GLeeGetProcAddress("glWindowPos4sMESA"))!=0) nLinked++; + if ((GLeeFuncPtr_glWindowPos4svMESA = (GLEEPFNGLWINDOWPOS4SVMESAPROC) __GLeeGetProcAddress("glWindowPos4svMESA"))!=0) nLinked++; +#endif + if (nLinked==24) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_texture_compression_s3tc(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_IBM_cull_vertex(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_IBM_multimode_draw_arrays(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_IBM_multimode_draw_arrays + if ((GLeeFuncPtr_glMultiModeDrawArraysIBM = (GLEEPFNGLMULTIMODEDRAWARRAYSIBMPROC) __GLeeGetProcAddress("glMultiModeDrawArraysIBM"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiModeDrawElementsIBM = (GLEEPFNGLMULTIMODEDRAWELEMENTSIBMPROC) __GLeeGetProcAddress("glMultiModeDrawElementsIBM"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_IBM_vertex_array_lists(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_IBM_vertex_array_lists + if ((GLeeFuncPtr_glColorPointerListIBM = (GLEEPFNGLCOLORPOINTERLISTIBMPROC) __GLeeGetProcAddress("glColorPointerListIBM"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColorPointerListIBM = (GLEEPFNGLSECONDARYCOLORPOINTERLISTIBMPROC) __GLeeGetProcAddress("glSecondaryColorPointerListIBM"))!=0) nLinked++; + if ((GLeeFuncPtr_glEdgeFlagPointerListIBM = (GLEEPFNGLEDGEFLAGPOINTERLISTIBMPROC) __GLeeGetProcAddress("glEdgeFlagPointerListIBM"))!=0) nLinked++; + if ((GLeeFuncPtr_glFogCoordPointerListIBM = (GLEEPFNGLFOGCOORDPOINTERLISTIBMPROC) __GLeeGetProcAddress("glFogCoordPointerListIBM"))!=0) nLinked++; + if ((GLeeFuncPtr_glIndexPointerListIBM = (GLEEPFNGLINDEXPOINTERLISTIBMPROC) __GLeeGetProcAddress("glIndexPointerListIBM"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormalPointerListIBM = (GLEEPFNGLNORMALPOINTERLISTIBMPROC) __GLeeGetProcAddress("glNormalPointerListIBM"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoordPointerListIBM = (GLEEPFNGLTEXCOORDPOINTERLISTIBMPROC) __GLeeGetProcAddress("glTexCoordPointerListIBM"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexPointerListIBM = (GLEEPFNGLVERTEXPOINTERLISTIBMPROC) __GLeeGetProcAddress("glVertexPointerListIBM"))!=0) nLinked++; +#endif + if (nLinked==8) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_subsample(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_ycrcb_subsample(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_ycrcba(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGI_depth_pass_instrument(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_3DFX_texture_compression_FXT1(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_3DFX_multisample(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_3DFX_tbuffer(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_3DFX_tbuffer + if ((GLeeFuncPtr_glTbufferMask3DFX = (GLEEPFNGLTBUFFERMASK3DFXPROC) __GLeeGetProcAddress("glTbufferMask3DFX"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_multisample(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_multisample + if ((GLeeFuncPtr_glSampleMaskEXT = (GLEEPFNGLSAMPLEMASKEXTPROC) __GLeeGetProcAddress("glSampleMaskEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSamplePatternEXT = (GLEEPFNGLSAMPLEPATTERNEXTPROC) __GLeeGetProcAddress("glSamplePatternEXT"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_vertex_preclip(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_convolution_accuracy(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_resample(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIS_point_line_texgen(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIS_texture_color_mask(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIS_texture_color_mask + if ((GLeeFuncPtr_glTextureColorMaskSGIS = (GLEEPFNGLTEXTURECOLORMASKSGISPROC) __GLeeGetProcAddress("glTextureColorMaskSGIS"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_texture_env_dot3(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ATI_texture_mirror_once(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_fence(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_fence + if ((GLeeFuncPtr_glDeleteFencesNV = (GLEEPFNGLDELETEFENCESNVPROC) __GLeeGetProcAddress("glDeleteFencesNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenFencesNV = (GLEEPFNGLGENFENCESNVPROC) __GLeeGetProcAddress("glGenFencesNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsFenceNV = (GLEEPFNGLISFENCENVPROC) __GLeeGetProcAddress("glIsFenceNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glTestFenceNV = (GLEEPFNGLTESTFENCENVPROC) __GLeeGetProcAddress("glTestFenceNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFenceivNV = (GLEEPFNGLGETFENCEIVNVPROC) __GLeeGetProcAddress("glGetFenceivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glFinishFenceNV = (GLEEPFNGLFINISHFENCENVPROC) __GLeeGetProcAddress("glFinishFenceNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glSetFenceNV = (GLEEPFNGLSETFENCENVPROC) __GLeeGetProcAddress("glSetFenceNV"))!=0) nLinked++; +#endif + if (nLinked==7) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_IBM_texture_mirrored_repeat(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_evaluators(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_evaluators + if ((GLeeFuncPtr_glMapControlPointsNV = (GLEEPFNGLMAPCONTROLPOINTSNVPROC) __GLeeGetProcAddress("glMapControlPointsNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glMapParameterivNV = (GLEEPFNGLMAPPARAMETERIVNVPROC) __GLeeGetProcAddress("glMapParameterivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glMapParameterfvNV = (GLEEPFNGLMAPPARAMETERFVNVPROC) __GLeeGetProcAddress("glMapParameterfvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMapControlPointsNV = (GLEEPFNGLGETMAPCONTROLPOINTSNVPROC) __GLeeGetProcAddress("glGetMapControlPointsNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMapParameterivNV = (GLEEPFNGLGETMAPPARAMETERIVNVPROC) __GLeeGetProcAddress("glGetMapParameterivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMapParameterfvNV = (GLEEPFNGLGETMAPPARAMETERFVNVPROC) __GLeeGetProcAddress("glGetMapParameterfvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMapAttribParameterivNV = (GLEEPFNGLGETMAPATTRIBPARAMETERIVNVPROC) __GLeeGetProcAddress("glGetMapAttribParameterivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMapAttribParameterfvNV = (GLEEPFNGLGETMAPATTRIBPARAMETERFVNVPROC) __GLeeGetProcAddress("glGetMapAttribParameterfvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glEvalMapsNV = (GLEEPFNGLEVALMAPSNVPROC) __GLeeGetProcAddress("glEvalMapsNV"))!=0) nLinked++; +#endif + if (nLinked==9) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_NV_packed_depth_stencil(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_register_combiners2(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_register_combiners2 + if ((GLeeFuncPtr_glCombinerStageParameterfvNV = (GLEEPFNGLCOMBINERSTAGEPARAMETERFVNVPROC) __GLeeGetProcAddress("glCombinerStageParameterfvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetCombinerStageParameterfvNV = (GLEEPFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) __GLeeGetProcAddress("glGetCombinerStageParameterfvNV"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_NV_texture_compression_vtc(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_texture_rectangle(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_texture_shader(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_texture_shader2(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_vertex_array_range2(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_vertex_program(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_vertex_program + if ((GLeeFuncPtr_glAreProgramsResidentNV = (GLEEPFNGLAREPROGRAMSRESIDENTNVPROC) __GLeeGetProcAddress("glAreProgramsResidentNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindProgramNV = (GLEEPFNGLBINDPROGRAMNVPROC) __GLeeGetProcAddress("glBindProgramNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteProgramsNV = (GLEEPFNGLDELETEPROGRAMSNVPROC) __GLeeGetProcAddress("glDeleteProgramsNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glExecuteProgramNV = (GLEEPFNGLEXECUTEPROGRAMNVPROC) __GLeeGetProcAddress("glExecuteProgramNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenProgramsNV = (GLEEPFNGLGENPROGRAMSNVPROC) __GLeeGetProcAddress("glGenProgramsNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramParameterdvNV = (GLEEPFNGLGETPROGRAMPARAMETERDVNVPROC) __GLeeGetProcAddress("glGetProgramParameterdvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramParameterfvNV = (GLEEPFNGLGETPROGRAMPARAMETERFVNVPROC) __GLeeGetProcAddress("glGetProgramParameterfvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramivNV = (GLEEPFNGLGETPROGRAMIVNVPROC) __GLeeGetProcAddress("glGetProgramivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramStringNV = (GLEEPFNGLGETPROGRAMSTRINGNVPROC) __GLeeGetProcAddress("glGetProgramStringNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTrackMatrixivNV = (GLEEPFNGLGETTRACKMATRIXIVNVPROC) __GLeeGetProcAddress("glGetTrackMatrixivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribdvNV = (GLEEPFNGLGETVERTEXATTRIBDVNVPROC) __GLeeGetProcAddress("glGetVertexAttribdvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribfvNV = (GLEEPFNGLGETVERTEXATTRIBFVNVPROC) __GLeeGetProcAddress("glGetVertexAttribfvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribivNV = (GLEEPFNGLGETVERTEXATTRIBIVNVPROC) __GLeeGetProcAddress("glGetVertexAttribivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribPointervNV = (GLEEPFNGLGETVERTEXATTRIBPOINTERVNVPROC) __GLeeGetProcAddress("glGetVertexAttribPointervNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsProgramNV = (GLEEPFNGLISPROGRAMNVPROC) __GLeeGetProcAddress("glIsProgramNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glLoadProgramNV = (GLEEPFNGLLOADPROGRAMNVPROC) __GLeeGetProcAddress("glLoadProgramNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramParameter4dNV = (GLEEPFNGLPROGRAMPARAMETER4DNVPROC) __GLeeGetProcAddress("glProgramParameter4dNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramParameter4dvNV = (GLEEPFNGLPROGRAMPARAMETER4DVNVPROC) __GLeeGetProcAddress("glProgramParameter4dvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramParameter4fNV = (GLEEPFNGLPROGRAMPARAMETER4FNVPROC) __GLeeGetProcAddress("glProgramParameter4fNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramParameter4fvNV = (GLEEPFNGLPROGRAMPARAMETER4FVNVPROC) __GLeeGetProcAddress("glProgramParameter4fvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramParameters4dvNV = (GLEEPFNGLPROGRAMPARAMETERS4DVNVPROC) __GLeeGetProcAddress("glProgramParameters4dvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramParameters4fvNV = (GLEEPFNGLPROGRAMPARAMETERS4FVNVPROC) __GLeeGetProcAddress("glProgramParameters4fvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glRequestResidentProgramsNV = (GLEEPFNGLREQUESTRESIDENTPROGRAMSNVPROC) __GLeeGetProcAddress("glRequestResidentProgramsNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glTrackMatrixNV = (GLEEPFNGLTRACKMATRIXNVPROC) __GLeeGetProcAddress("glTrackMatrixNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribPointerNV = (GLEEPFNGLVERTEXATTRIBPOINTERNVPROC) __GLeeGetProcAddress("glVertexAttribPointerNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1dNV = (GLEEPFNGLVERTEXATTRIB1DNVPROC) __GLeeGetProcAddress("glVertexAttrib1dNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1dvNV = (GLEEPFNGLVERTEXATTRIB1DVNVPROC) __GLeeGetProcAddress("glVertexAttrib1dvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1fNV = (GLEEPFNGLVERTEXATTRIB1FNVPROC) __GLeeGetProcAddress("glVertexAttrib1fNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1fvNV = (GLEEPFNGLVERTEXATTRIB1FVNVPROC) __GLeeGetProcAddress("glVertexAttrib1fvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1sNV = (GLEEPFNGLVERTEXATTRIB1SNVPROC) __GLeeGetProcAddress("glVertexAttrib1sNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1svNV = (GLEEPFNGLVERTEXATTRIB1SVNVPROC) __GLeeGetProcAddress("glVertexAttrib1svNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2dNV = (GLEEPFNGLVERTEXATTRIB2DNVPROC) __GLeeGetProcAddress("glVertexAttrib2dNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2dvNV = (GLEEPFNGLVERTEXATTRIB2DVNVPROC) __GLeeGetProcAddress("glVertexAttrib2dvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2fNV = (GLEEPFNGLVERTEXATTRIB2FNVPROC) __GLeeGetProcAddress("glVertexAttrib2fNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2fvNV = (GLEEPFNGLVERTEXATTRIB2FVNVPROC) __GLeeGetProcAddress("glVertexAttrib2fvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2sNV = (GLEEPFNGLVERTEXATTRIB2SNVPROC) __GLeeGetProcAddress("glVertexAttrib2sNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2svNV = (GLEEPFNGLVERTEXATTRIB2SVNVPROC) __GLeeGetProcAddress("glVertexAttrib2svNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3dNV = (GLEEPFNGLVERTEXATTRIB3DNVPROC) __GLeeGetProcAddress("glVertexAttrib3dNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3dvNV = (GLEEPFNGLVERTEXATTRIB3DVNVPROC) __GLeeGetProcAddress("glVertexAttrib3dvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3fNV = (GLEEPFNGLVERTEXATTRIB3FNVPROC) __GLeeGetProcAddress("glVertexAttrib3fNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3fvNV = (GLEEPFNGLVERTEXATTRIB3FVNVPROC) __GLeeGetProcAddress("glVertexAttrib3fvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3sNV = (GLEEPFNGLVERTEXATTRIB3SNVPROC) __GLeeGetProcAddress("glVertexAttrib3sNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3svNV = (GLEEPFNGLVERTEXATTRIB3SVNVPROC) __GLeeGetProcAddress("glVertexAttrib3svNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4dNV = (GLEEPFNGLVERTEXATTRIB4DNVPROC) __GLeeGetProcAddress("glVertexAttrib4dNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4dvNV = (GLEEPFNGLVERTEXATTRIB4DVNVPROC) __GLeeGetProcAddress("glVertexAttrib4dvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4fNV = (GLEEPFNGLVERTEXATTRIB4FNVPROC) __GLeeGetProcAddress("glVertexAttrib4fNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4fvNV = (GLEEPFNGLVERTEXATTRIB4FVNVPROC) __GLeeGetProcAddress("glVertexAttrib4fvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4sNV = (GLEEPFNGLVERTEXATTRIB4SNVPROC) __GLeeGetProcAddress("glVertexAttrib4sNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4svNV = (GLEEPFNGLVERTEXATTRIB4SVNVPROC) __GLeeGetProcAddress("glVertexAttrib4svNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4ubNV = (GLEEPFNGLVERTEXATTRIB4UBNVPROC) __GLeeGetProcAddress("glVertexAttrib4ubNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4ubvNV = (GLEEPFNGLVERTEXATTRIB4UBVNVPROC) __GLeeGetProcAddress("glVertexAttrib4ubvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs1dvNV = (GLEEPFNGLVERTEXATTRIBS1DVNVPROC) __GLeeGetProcAddress("glVertexAttribs1dvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs1fvNV = (GLEEPFNGLVERTEXATTRIBS1FVNVPROC) __GLeeGetProcAddress("glVertexAttribs1fvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs1svNV = (GLEEPFNGLVERTEXATTRIBS1SVNVPROC) __GLeeGetProcAddress("glVertexAttribs1svNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs2dvNV = (GLEEPFNGLVERTEXATTRIBS2DVNVPROC) __GLeeGetProcAddress("glVertexAttribs2dvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs2fvNV = (GLEEPFNGLVERTEXATTRIBS2FVNVPROC) __GLeeGetProcAddress("glVertexAttribs2fvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs2svNV = (GLEEPFNGLVERTEXATTRIBS2SVNVPROC) __GLeeGetProcAddress("glVertexAttribs2svNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs3dvNV = (GLEEPFNGLVERTEXATTRIBS3DVNVPROC) __GLeeGetProcAddress("glVertexAttribs3dvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs3fvNV = (GLEEPFNGLVERTEXATTRIBS3FVNVPROC) __GLeeGetProcAddress("glVertexAttribs3fvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs3svNV = (GLEEPFNGLVERTEXATTRIBS3SVNVPROC) __GLeeGetProcAddress("glVertexAttribs3svNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs4dvNV = (GLEEPFNGLVERTEXATTRIBS4DVNVPROC) __GLeeGetProcAddress("glVertexAttribs4dvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs4fvNV = (GLEEPFNGLVERTEXATTRIBS4FVNVPROC) __GLeeGetProcAddress("glVertexAttribs4fvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs4svNV = (GLEEPFNGLVERTEXATTRIBS4SVNVPROC) __GLeeGetProcAddress("glVertexAttribs4svNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs4ubvNV = (GLEEPFNGLVERTEXATTRIBS4UBVNVPROC) __GLeeGetProcAddress("glVertexAttribs4ubvNV"))!=0) nLinked++; +#endif + if (nLinked==64) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_texture_coordinate_clamp(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_scalebias_hint(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_OML_interlace(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_OML_subsample(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_OML_resample(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_copy_depth_to_color(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ATI_envmap_bumpmap(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ATI_envmap_bumpmap + if ((GLeeFuncPtr_glTexBumpParameterivATI = (GLEEPFNGLTEXBUMPPARAMETERIVATIPROC) __GLeeGetProcAddress("glTexBumpParameterivATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexBumpParameterfvATI = (GLEEPFNGLTEXBUMPPARAMETERFVATIPROC) __GLeeGetProcAddress("glTexBumpParameterfvATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTexBumpParameterivATI = (GLEEPFNGLGETTEXBUMPPARAMETERIVATIPROC) __GLeeGetProcAddress("glGetTexBumpParameterivATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTexBumpParameterfvATI = (GLEEPFNGLGETTEXBUMPPARAMETERFVATIPROC) __GLeeGetProcAddress("glGetTexBumpParameterfvATI"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ATI_fragment_shader(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ATI_fragment_shader + if ((GLeeFuncPtr_glGenFragmentShadersATI = (GLEEPFNGLGENFRAGMENTSHADERSATIPROC) __GLeeGetProcAddress("glGenFragmentShadersATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindFragmentShaderATI = (GLEEPFNGLBINDFRAGMENTSHADERATIPROC) __GLeeGetProcAddress("glBindFragmentShaderATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteFragmentShaderATI = (GLEEPFNGLDELETEFRAGMENTSHADERATIPROC) __GLeeGetProcAddress("glDeleteFragmentShaderATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glBeginFragmentShaderATI = (GLEEPFNGLBEGINFRAGMENTSHADERATIPROC) __GLeeGetProcAddress("glBeginFragmentShaderATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glEndFragmentShaderATI = (GLEEPFNGLENDFRAGMENTSHADERATIPROC) __GLeeGetProcAddress("glEndFragmentShaderATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glPassTexCoordATI = (GLEEPFNGLPASSTEXCOORDATIPROC) __GLeeGetProcAddress("glPassTexCoordATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glSampleMapATI = (GLEEPFNGLSAMPLEMAPATIPROC) __GLeeGetProcAddress("glSampleMapATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glColorFragmentOp1ATI = (GLEEPFNGLCOLORFRAGMENTOP1ATIPROC) __GLeeGetProcAddress("glColorFragmentOp1ATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glColorFragmentOp2ATI = (GLEEPFNGLCOLORFRAGMENTOP2ATIPROC) __GLeeGetProcAddress("glColorFragmentOp2ATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glColorFragmentOp3ATI = (GLEEPFNGLCOLORFRAGMENTOP3ATIPROC) __GLeeGetProcAddress("glColorFragmentOp3ATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glAlphaFragmentOp1ATI = (GLEEPFNGLALPHAFRAGMENTOP1ATIPROC) __GLeeGetProcAddress("glAlphaFragmentOp1ATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glAlphaFragmentOp2ATI = (GLEEPFNGLALPHAFRAGMENTOP2ATIPROC) __GLeeGetProcAddress("glAlphaFragmentOp2ATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glAlphaFragmentOp3ATI = (GLEEPFNGLALPHAFRAGMENTOP3ATIPROC) __GLeeGetProcAddress("glAlphaFragmentOp3ATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glSetFragmentShaderConstantATI = (GLEEPFNGLSETFRAGMENTSHADERCONSTANTATIPROC) __GLeeGetProcAddress("glSetFragmentShaderConstantATI"))!=0) nLinked++; +#endif + if (nLinked==14) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ATI_pn_triangles(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ATI_pn_triangles + if ((GLeeFuncPtr_glPNTrianglesiATI = (GLEEPFNGLPNTRIANGLESIATIPROC) __GLeeGetProcAddress("glPNTrianglesiATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glPNTrianglesfATI = (GLEEPFNGLPNTRIANGLESFATIPROC) __GLeeGetProcAddress("glPNTrianglesfATI"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ATI_vertex_array_object(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ATI_vertex_array_object + if ((GLeeFuncPtr_glNewObjectBufferATI = (GLEEPFNGLNEWOBJECTBUFFERATIPROC) __GLeeGetProcAddress("glNewObjectBufferATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsObjectBufferATI = (GLEEPFNGLISOBJECTBUFFERATIPROC) __GLeeGetProcAddress("glIsObjectBufferATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glUpdateObjectBufferATI = (GLEEPFNGLUPDATEOBJECTBUFFERATIPROC) __GLeeGetProcAddress("glUpdateObjectBufferATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetObjectBufferfvATI = (GLEEPFNGLGETOBJECTBUFFERFVATIPROC) __GLeeGetProcAddress("glGetObjectBufferfvATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetObjectBufferivATI = (GLEEPFNGLGETOBJECTBUFFERIVATIPROC) __GLeeGetProcAddress("glGetObjectBufferivATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glFreeObjectBufferATI = (GLEEPFNGLFREEOBJECTBUFFERATIPROC) __GLeeGetProcAddress("glFreeObjectBufferATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glArrayObjectATI = (GLEEPFNGLARRAYOBJECTATIPROC) __GLeeGetProcAddress("glArrayObjectATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetArrayObjectfvATI = (GLEEPFNGLGETARRAYOBJECTFVATIPROC) __GLeeGetProcAddress("glGetArrayObjectfvATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetArrayObjectivATI = (GLEEPFNGLGETARRAYOBJECTIVATIPROC) __GLeeGetProcAddress("glGetArrayObjectivATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVariantArrayObjectATI = (GLEEPFNGLVARIANTARRAYOBJECTATIPROC) __GLeeGetProcAddress("glVariantArrayObjectATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVariantArrayObjectfvATI = (GLEEPFNGLGETVARIANTARRAYOBJECTFVATIPROC) __GLeeGetProcAddress("glGetVariantArrayObjectfvATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVariantArrayObjectivATI = (GLEEPFNGLGETVARIANTARRAYOBJECTIVATIPROC) __GLeeGetProcAddress("glGetVariantArrayObjectivATI"))!=0) nLinked++; +#endif + if (nLinked==12) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_vertex_shader(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_vertex_shader + if ((GLeeFuncPtr_glBeginVertexShaderEXT = (GLEEPFNGLBEGINVERTEXSHADEREXTPROC) __GLeeGetProcAddress("glBeginVertexShaderEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glEndVertexShaderEXT = (GLEEPFNGLENDVERTEXSHADEREXTPROC) __GLeeGetProcAddress("glEndVertexShaderEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindVertexShaderEXT = (GLEEPFNGLBINDVERTEXSHADEREXTPROC) __GLeeGetProcAddress("glBindVertexShaderEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenVertexShadersEXT = (GLEEPFNGLGENVERTEXSHADERSEXTPROC) __GLeeGetProcAddress("glGenVertexShadersEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteVertexShaderEXT = (GLEEPFNGLDELETEVERTEXSHADEREXTPROC) __GLeeGetProcAddress("glDeleteVertexShaderEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glShaderOp1EXT = (GLEEPFNGLSHADEROP1EXTPROC) __GLeeGetProcAddress("glShaderOp1EXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glShaderOp2EXT = (GLEEPFNGLSHADEROP2EXTPROC) __GLeeGetProcAddress("glShaderOp2EXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glShaderOp3EXT = (GLEEPFNGLSHADEROP3EXTPROC) __GLeeGetProcAddress("glShaderOp3EXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSwizzleEXT = (GLEEPFNGLSWIZZLEEXTPROC) __GLeeGetProcAddress("glSwizzleEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glWriteMaskEXT = (GLEEPFNGLWRITEMASKEXTPROC) __GLeeGetProcAddress("glWriteMaskEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glInsertComponentEXT = (GLEEPFNGLINSERTCOMPONENTEXTPROC) __GLeeGetProcAddress("glInsertComponentEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glExtractComponentEXT = (GLEEPFNGLEXTRACTCOMPONENTEXTPROC) __GLeeGetProcAddress("glExtractComponentEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenSymbolsEXT = (GLEEPFNGLGENSYMBOLSEXTPROC) __GLeeGetProcAddress("glGenSymbolsEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSetInvariantEXT = (GLEEPFNGLSETINVARIANTEXTPROC) __GLeeGetProcAddress("glSetInvariantEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glSetLocalConstantEXT = (GLEEPFNGLSETLOCALCONSTANTEXTPROC) __GLeeGetProcAddress("glSetLocalConstantEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVariantbvEXT = (GLEEPFNGLVARIANTBVEXTPROC) __GLeeGetProcAddress("glVariantbvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVariantsvEXT = (GLEEPFNGLVARIANTSVEXTPROC) __GLeeGetProcAddress("glVariantsvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVariantivEXT = (GLEEPFNGLVARIANTIVEXTPROC) __GLeeGetProcAddress("glVariantivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVariantfvEXT = (GLEEPFNGLVARIANTFVEXTPROC) __GLeeGetProcAddress("glVariantfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVariantdvEXT = (GLEEPFNGLVARIANTDVEXTPROC) __GLeeGetProcAddress("glVariantdvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVariantubvEXT = (GLEEPFNGLVARIANTUBVEXTPROC) __GLeeGetProcAddress("glVariantubvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVariantusvEXT = (GLEEPFNGLVARIANTUSVEXTPROC) __GLeeGetProcAddress("glVariantusvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVariantuivEXT = (GLEEPFNGLVARIANTUIVEXTPROC) __GLeeGetProcAddress("glVariantuivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVariantPointerEXT = (GLEEPFNGLVARIANTPOINTEREXTPROC) __GLeeGetProcAddress("glVariantPointerEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glEnableVariantClientStateEXT = (GLEEPFNGLENABLEVARIANTCLIENTSTATEEXTPROC) __GLeeGetProcAddress("glEnableVariantClientStateEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glDisableVariantClientStateEXT = (GLEEPFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) __GLeeGetProcAddress("glDisableVariantClientStateEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindLightParameterEXT = (GLEEPFNGLBINDLIGHTPARAMETEREXTPROC) __GLeeGetProcAddress("glBindLightParameterEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindMaterialParameterEXT = (GLEEPFNGLBINDMATERIALPARAMETEREXTPROC) __GLeeGetProcAddress("glBindMaterialParameterEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindTexGenParameterEXT = (GLEEPFNGLBINDTEXGENPARAMETEREXTPROC) __GLeeGetProcAddress("glBindTexGenParameterEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindTextureUnitParameterEXT = (GLEEPFNGLBINDTEXTUREUNITPARAMETEREXTPROC) __GLeeGetProcAddress("glBindTextureUnitParameterEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindParameterEXT = (GLEEPFNGLBINDPARAMETEREXTPROC) __GLeeGetProcAddress("glBindParameterEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsVariantEnabledEXT = (GLEEPFNGLISVARIANTENABLEDEXTPROC) __GLeeGetProcAddress("glIsVariantEnabledEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVariantBooleanvEXT = (GLEEPFNGLGETVARIANTBOOLEANVEXTPROC) __GLeeGetProcAddress("glGetVariantBooleanvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVariantIntegervEXT = (GLEEPFNGLGETVARIANTINTEGERVEXTPROC) __GLeeGetProcAddress("glGetVariantIntegervEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVariantFloatvEXT = (GLEEPFNGLGETVARIANTFLOATVEXTPROC) __GLeeGetProcAddress("glGetVariantFloatvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVariantPointervEXT = (GLEEPFNGLGETVARIANTPOINTERVEXTPROC) __GLeeGetProcAddress("glGetVariantPointervEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetInvariantBooleanvEXT = (GLEEPFNGLGETINVARIANTBOOLEANVEXTPROC) __GLeeGetProcAddress("glGetInvariantBooleanvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetInvariantIntegervEXT = (GLEEPFNGLGETINVARIANTINTEGERVEXTPROC) __GLeeGetProcAddress("glGetInvariantIntegervEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetInvariantFloatvEXT = (GLEEPFNGLGETINVARIANTFLOATVEXTPROC) __GLeeGetProcAddress("glGetInvariantFloatvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetLocalConstantBooleanvEXT = (GLEEPFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) __GLeeGetProcAddress("glGetLocalConstantBooleanvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetLocalConstantIntegervEXT = (GLEEPFNGLGETLOCALCONSTANTINTEGERVEXTPROC) __GLeeGetProcAddress("glGetLocalConstantIntegervEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetLocalConstantFloatvEXT = (GLEEPFNGLGETLOCALCONSTANTFLOATVEXTPROC) __GLeeGetProcAddress("glGetLocalConstantFloatvEXT"))!=0) nLinked++; +#endif + if (nLinked==42) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ATI_vertex_streams(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ATI_vertex_streams + if ((GLeeFuncPtr_glVertexStream1sATI = (GLEEPFNGLVERTEXSTREAM1SATIPROC) __GLeeGetProcAddress("glVertexStream1sATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream1svATI = (GLEEPFNGLVERTEXSTREAM1SVATIPROC) __GLeeGetProcAddress("glVertexStream1svATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream1iATI = (GLEEPFNGLVERTEXSTREAM1IATIPROC) __GLeeGetProcAddress("glVertexStream1iATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream1ivATI = (GLEEPFNGLVERTEXSTREAM1IVATIPROC) __GLeeGetProcAddress("glVertexStream1ivATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream1fATI = (GLEEPFNGLVERTEXSTREAM1FATIPROC) __GLeeGetProcAddress("glVertexStream1fATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream1fvATI = (GLEEPFNGLVERTEXSTREAM1FVATIPROC) __GLeeGetProcAddress("glVertexStream1fvATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream1dATI = (GLEEPFNGLVERTEXSTREAM1DATIPROC) __GLeeGetProcAddress("glVertexStream1dATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream1dvATI = (GLEEPFNGLVERTEXSTREAM1DVATIPROC) __GLeeGetProcAddress("glVertexStream1dvATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream2sATI = (GLEEPFNGLVERTEXSTREAM2SATIPROC) __GLeeGetProcAddress("glVertexStream2sATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream2svATI = (GLEEPFNGLVERTEXSTREAM2SVATIPROC) __GLeeGetProcAddress("glVertexStream2svATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream2iATI = (GLEEPFNGLVERTEXSTREAM2IATIPROC) __GLeeGetProcAddress("glVertexStream2iATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream2ivATI = (GLEEPFNGLVERTEXSTREAM2IVATIPROC) __GLeeGetProcAddress("glVertexStream2ivATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream2fATI = (GLEEPFNGLVERTEXSTREAM2FATIPROC) __GLeeGetProcAddress("glVertexStream2fATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream2fvATI = (GLEEPFNGLVERTEXSTREAM2FVATIPROC) __GLeeGetProcAddress("glVertexStream2fvATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream2dATI = (GLEEPFNGLVERTEXSTREAM2DATIPROC) __GLeeGetProcAddress("glVertexStream2dATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream2dvATI = (GLEEPFNGLVERTEXSTREAM2DVATIPROC) __GLeeGetProcAddress("glVertexStream2dvATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream3sATI = (GLEEPFNGLVERTEXSTREAM3SATIPROC) __GLeeGetProcAddress("glVertexStream3sATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream3svATI = (GLEEPFNGLVERTEXSTREAM3SVATIPROC) __GLeeGetProcAddress("glVertexStream3svATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream3iATI = (GLEEPFNGLVERTEXSTREAM3IATIPROC) __GLeeGetProcAddress("glVertexStream3iATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream3ivATI = (GLEEPFNGLVERTEXSTREAM3IVATIPROC) __GLeeGetProcAddress("glVertexStream3ivATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream3fATI = (GLEEPFNGLVERTEXSTREAM3FATIPROC) __GLeeGetProcAddress("glVertexStream3fATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream3fvATI = (GLEEPFNGLVERTEXSTREAM3FVATIPROC) __GLeeGetProcAddress("glVertexStream3fvATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream3dATI = (GLEEPFNGLVERTEXSTREAM3DATIPROC) __GLeeGetProcAddress("glVertexStream3dATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream3dvATI = (GLEEPFNGLVERTEXSTREAM3DVATIPROC) __GLeeGetProcAddress("glVertexStream3dvATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream4sATI = (GLEEPFNGLVERTEXSTREAM4SATIPROC) __GLeeGetProcAddress("glVertexStream4sATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream4svATI = (GLEEPFNGLVERTEXSTREAM4SVATIPROC) __GLeeGetProcAddress("glVertexStream4svATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream4iATI = (GLEEPFNGLVERTEXSTREAM4IATIPROC) __GLeeGetProcAddress("glVertexStream4iATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream4ivATI = (GLEEPFNGLVERTEXSTREAM4IVATIPROC) __GLeeGetProcAddress("glVertexStream4ivATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream4fATI = (GLEEPFNGLVERTEXSTREAM4FATIPROC) __GLeeGetProcAddress("glVertexStream4fATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream4fvATI = (GLEEPFNGLVERTEXSTREAM4FVATIPROC) __GLeeGetProcAddress("glVertexStream4fvATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream4dATI = (GLEEPFNGLVERTEXSTREAM4DATIPROC) __GLeeGetProcAddress("glVertexStream4dATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexStream4dvATI = (GLEEPFNGLVERTEXSTREAM4DVATIPROC) __GLeeGetProcAddress("glVertexStream4dvATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormalStream3bATI = (GLEEPFNGLNORMALSTREAM3BATIPROC) __GLeeGetProcAddress("glNormalStream3bATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormalStream3bvATI = (GLEEPFNGLNORMALSTREAM3BVATIPROC) __GLeeGetProcAddress("glNormalStream3bvATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormalStream3sATI = (GLEEPFNGLNORMALSTREAM3SATIPROC) __GLeeGetProcAddress("glNormalStream3sATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormalStream3svATI = (GLEEPFNGLNORMALSTREAM3SVATIPROC) __GLeeGetProcAddress("glNormalStream3svATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormalStream3iATI = (GLEEPFNGLNORMALSTREAM3IATIPROC) __GLeeGetProcAddress("glNormalStream3iATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormalStream3ivATI = (GLEEPFNGLNORMALSTREAM3IVATIPROC) __GLeeGetProcAddress("glNormalStream3ivATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormalStream3fATI = (GLEEPFNGLNORMALSTREAM3FATIPROC) __GLeeGetProcAddress("glNormalStream3fATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormalStream3fvATI = (GLEEPFNGLNORMALSTREAM3FVATIPROC) __GLeeGetProcAddress("glNormalStream3fvATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormalStream3dATI = (GLEEPFNGLNORMALSTREAM3DATIPROC) __GLeeGetProcAddress("glNormalStream3dATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormalStream3dvATI = (GLEEPFNGLNORMALSTREAM3DVATIPROC) __GLeeGetProcAddress("glNormalStream3dvATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glClientActiveVertexStreamATI = (GLEEPFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) __GLeeGetProcAddress("glClientActiveVertexStreamATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexBlendEnviATI = (GLEEPFNGLVERTEXBLENDENVIATIPROC) __GLeeGetProcAddress("glVertexBlendEnviATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexBlendEnvfATI = (GLEEPFNGLVERTEXBLENDENVFATIPROC) __GLeeGetProcAddress("glVertexBlendEnvfATI"))!=0) nLinked++; +#endif + if (nLinked==45) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ATI_element_array(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ATI_element_array + if ((GLeeFuncPtr_glElementPointerATI = (GLEEPFNGLELEMENTPOINTERATIPROC) __GLeeGetProcAddress("glElementPointerATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glDrawElementArrayATI = (GLEEPFNGLDRAWELEMENTARRAYATIPROC) __GLeeGetProcAddress("glDrawElementArrayATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glDrawRangeElementArrayATI = (GLEEPFNGLDRAWRANGEELEMENTARRAYATIPROC) __GLeeGetProcAddress("glDrawRangeElementArrayATI"))!=0) nLinked++; +#endif + if (nLinked==3) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SUN_mesh_array(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SUN_mesh_array + if ((GLeeFuncPtr_glDrawMeshArraysSUN = (GLEEPFNGLDRAWMESHARRAYSSUNPROC) __GLeeGetProcAddress("glDrawMeshArraysSUN"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SUN_slice_accum(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_multisample_filter_hint(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_depth_clamp(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_occlusion_query(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_occlusion_query + if ((GLeeFuncPtr_glGenOcclusionQueriesNV = (GLEEPFNGLGENOCCLUSIONQUERIESNVPROC) __GLeeGetProcAddress("glGenOcclusionQueriesNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteOcclusionQueriesNV = (GLEEPFNGLDELETEOCCLUSIONQUERIESNVPROC) __GLeeGetProcAddress("glDeleteOcclusionQueriesNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsOcclusionQueryNV = (GLEEPFNGLISOCCLUSIONQUERYNVPROC) __GLeeGetProcAddress("glIsOcclusionQueryNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glBeginOcclusionQueryNV = (GLEEPFNGLBEGINOCCLUSIONQUERYNVPROC) __GLeeGetProcAddress("glBeginOcclusionQueryNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glEndOcclusionQueryNV = (GLEEPFNGLENDOCCLUSIONQUERYNVPROC) __GLeeGetProcAddress("glEndOcclusionQueryNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetOcclusionQueryivNV = (GLEEPFNGLGETOCCLUSIONQUERYIVNVPROC) __GLeeGetProcAddress("glGetOcclusionQueryivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetOcclusionQueryuivNV = (GLEEPFNGLGETOCCLUSIONQUERYUIVNVPROC) __GLeeGetProcAddress("glGetOcclusionQueryuivNV"))!=0) nLinked++; +#endif + if (nLinked==7) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_NV_point_sprite(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_point_sprite + if ((GLeeFuncPtr_glPointParameteriNV = (GLEEPFNGLPOINTPARAMETERINVPROC) __GLeeGetProcAddress("glPointParameteriNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glPointParameterivNV = (GLEEPFNGLPOINTPARAMETERIVNVPROC) __GLeeGetProcAddress("glPointParameterivNV"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_NV_texture_shader3(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_vertex_program1_1(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_shadow_funcs(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_stencil_two_side(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_stencil_two_side + if ((GLeeFuncPtr_glActiveStencilFaceEXT = (GLEEPFNGLACTIVESTENCILFACEEXTPROC) __GLeeGetProcAddress("glActiveStencilFaceEXT"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ATI_text_fragment_shader(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_APPLE_client_storage(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_APPLE_element_array(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_APPLE_element_array + if ((GLeeFuncPtr_glElementPointerAPPLE = (GLEEPFNGLELEMENTPOINTERAPPLEPROC) __GLeeGetProcAddress("glElementPointerAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glDrawElementArrayAPPLE = (GLEEPFNGLDRAWELEMENTARRAYAPPLEPROC) __GLeeGetProcAddress("glDrawElementArrayAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glDrawRangeElementArrayAPPLE = (GLEEPFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) __GLeeGetProcAddress("glDrawRangeElementArrayAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiDrawElementArrayAPPLE = (GLEEPFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) __GLeeGetProcAddress("glMultiDrawElementArrayAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiDrawRangeElementArrayAPPLE = (GLEEPFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) __GLeeGetProcAddress("glMultiDrawRangeElementArrayAPPLE"))!=0) nLinked++; +#endif + if (nLinked==5) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_APPLE_fence(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_APPLE_fence + if ((GLeeFuncPtr_glGenFencesAPPLE = (GLEEPFNGLGENFENCESAPPLEPROC) __GLeeGetProcAddress("glGenFencesAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteFencesAPPLE = (GLEEPFNGLDELETEFENCESAPPLEPROC) __GLeeGetProcAddress("glDeleteFencesAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glSetFenceAPPLE = (GLEEPFNGLSETFENCEAPPLEPROC) __GLeeGetProcAddress("glSetFenceAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsFenceAPPLE = (GLEEPFNGLISFENCEAPPLEPROC) __GLeeGetProcAddress("glIsFenceAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glTestFenceAPPLE = (GLEEPFNGLTESTFENCEAPPLEPROC) __GLeeGetProcAddress("glTestFenceAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glFinishFenceAPPLE = (GLEEPFNGLFINISHFENCEAPPLEPROC) __GLeeGetProcAddress("glFinishFenceAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glTestObjectAPPLE = (GLEEPFNGLTESTOBJECTAPPLEPROC) __GLeeGetProcAddress("glTestObjectAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glFinishObjectAPPLE = (GLEEPFNGLFINISHOBJECTAPPLEPROC) __GLeeGetProcAddress("glFinishObjectAPPLE"))!=0) nLinked++; +#endif + if (nLinked==8) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_APPLE_vertex_array_object(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_APPLE_vertex_array_object + if ((GLeeFuncPtr_glBindVertexArrayAPPLE = (GLEEPFNGLBINDVERTEXARRAYAPPLEPROC) __GLeeGetProcAddress("glBindVertexArrayAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteVertexArraysAPPLE = (GLEEPFNGLDELETEVERTEXARRAYSAPPLEPROC) __GLeeGetProcAddress("glDeleteVertexArraysAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenVertexArraysAPPLE = (GLEEPFNGLGENVERTEXARRAYSAPPLEPROC) __GLeeGetProcAddress("glGenVertexArraysAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsVertexArrayAPPLE = (GLEEPFNGLISVERTEXARRAYAPPLEPROC) __GLeeGetProcAddress("glIsVertexArrayAPPLE"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_APPLE_vertex_array_range(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_APPLE_vertex_array_range + if ((GLeeFuncPtr_glVertexArrayRangeAPPLE = (GLEEPFNGLVERTEXARRAYRANGEAPPLEPROC) __GLeeGetProcAddress("glVertexArrayRangeAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glFlushVertexArrayRangeAPPLE = (GLEEPFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) __GLeeGetProcAddress("glFlushVertexArrayRangeAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexArrayParameteriAPPLE = (GLEEPFNGLVERTEXARRAYPARAMETERIAPPLEPROC) __GLeeGetProcAddress("glVertexArrayParameteriAPPLE"))!=0) nLinked++; +#endif + if (nLinked==3) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_APPLE_ycbcr_422(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_S3_s3tc(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ATI_draw_buffers(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ATI_draw_buffers + if ((GLeeFuncPtr_glDrawBuffersATI = (GLEEPFNGLDRAWBUFFERSATIPROC) __GLeeGetProcAddress("glDrawBuffersATI"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ATI_pixel_format_float(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ATI_texture_env_combine3(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ATI_texture_float(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_float_buffer(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_fragment_program(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_fragment_program + if ((GLeeFuncPtr_glProgramNamedParameter4fNV = (GLEEPFNGLPROGRAMNAMEDPARAMETER4FNVPROC) __GLeeGetProcAddress("glProgramNamedParameter4fNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramNamedParameter4dNV = (GLEEPFNGLPROGRAMNAMEDPARAMETER4DNVPROC) __GLeeGetProcAddress("glProgramNamedParameter4dNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramNamedParameter4fvNV = (GLEEPFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) __GLeeGetProcAddress("glProgramNamedParameter4fvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramNamedParameter4dvNV = (GLEEPFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) __GLeeGetProcAddress("glProgramNamedParameter4dvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramNamedParameterfvNV = (GLEEPFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) __GLeeGetProcAddress("glGetProgramNamedParameterfvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramNamedParameterdvNV = (GLEEPFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) __GLeeGetProcAddress("glGetProgramNamedParameterdvNV"))!=0) nLinked++; +#endif + if (nLinked==6) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_NV_half_float(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_half_float + if ((GLeeFuncPtr_glVertex2hNV = (GLEEPFNGLVERTEX2HNVPROC) __GLeeGetProcAddress("glVertex2hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertex2hvNV = (GLEEPFNGLVERTEX2HVNVPROC) __GLeeGetProcAddress("glVertex2hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertex3hNV = (GLEEPFNGLVERTEX3HNVPROC) __GLeeGetProcAddress("glVertex3hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertex3hvNV = (GLEEPFNGLVERTEX3HVNVPROC) __GLeeGetProcAddress("glVertex3hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertex4hNV = (GLEEPFNGLVERTEX4HNVPROC) __GLeeGetProcAddress("glVertex4hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertex4hvNV = (GLEEPFNGLVERTEX4HVNVPROC) __GLeeGetProcAddress("glVertex4hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormal3hNV = (GLEEPFNGLNORMAL3HNVPROC) __GLeeGetProcAddress("glNormal3hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glNormal3hvNV = (GLEEPFNGLNORMAL3HVNVPROC) __GLeeGetProcAddress("glNormal3hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glColor3hNV = (GLEEPFNGLCOLOR3HNVPROC) __GLeeGetProcAddress("glColor3hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glColor3hvNV = (GLEEPFNGLCOLOR3HVNVPROC) __GLeeGetProcAddress("glColor3hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glColor4hNV = (GLEEPFNGLCOLOR4HNVPROC) __GLeeGetProcAddress("glColor4hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glColor4hvNV = (GLEEPFNGLCOLOR4HVNVPROC) __GLeeGetProcAddress("glColor4hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord1hNV = (GLEEPFNGLTEXCOORD1HNVPROC) __GLeeGetProcAddress("glTexCoord1hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord1hvNV = (GLEEPFNGLTEXCOORD1HVNVPROC) __GLeeGetProcAddress("glTexCoord1hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord2hNV = (GLEEPFNGLTEXCOORD2HNVPROC) __GLeeGetProcAddress("glTexCoord2hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord2hvNV = (GLEEPFNGLTEXCOORD2HVNVPROC) __GLeeGetProcAddress("glTexCoord2hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord3hNV = (GLEEPFNGLTEXCOORD3HNVPROC) __GLeeGetProcAddress("glTexCoord3hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord3hvNV = (GLEEPFNGLTEXCOORD3HVNVPROC) __GLeeGetProcAddress("glTexCoord3hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord4hNV = (GLEEPFNGLTEXCOORD4HNVPROC) __GLeeGetProcAddress("glTexCoord4hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexCoord4hvNV = (GLEEPFNGLTEXCOORD4HVNVPROC) __GLeeGetProcAddress("glTexCoord4hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1hNV = (GLEEPFNGLMULTITEXCOORD1HNVPROC) __GLeeGetProcAddress("glMultiTexCoord1hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord1hvNV = (GLEEPFNGLMULTITEXCOORD1HVNVPROC) __GLeeGetProcAddress("glMultiTexCoord1hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2hNV = (GLEEPFNGLMULTITEXCOORD2HNVPROC) __GLeeGetProcAddress("glMultiTexCoord2hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord2hvNV = (GLEEPFNGLMULTITEXCOORD2HVNVPROC) __GLeeGetProcAddress("glMultiTexCoord2hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3hNV = (GLEEPFNGLMULTITEXCOORD3HNVPROC) __GLeeGetProcAddress("glMultiTexCoord3hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord3hvNV = (GLEEPFNGLMULTITEXCOORD3HVNVPROC) __GLeeGetProcAddress("glMultiTexCoord3hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4hNV = (GLEEPFNGLMULTITEXCOORD4HNVPROC) __GLeeGetProcAddress("glMultiTexCoord4hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoord4hvNV = (GLEEPFNGLMULTITEXCOORD4HVNVPROC) __GLeeGetProcAddress("glMultiTexCoord4hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glFogCoordhNV = (GLEEPFNGLFOGCOORDHNVPROC) __GLeeGetProcAddress("glFogCoordhNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glFogCoordhvNV = (GLEEPFNGLFOGCOORDHVNVPROC) __GLeeGetProcAddress("glFogCoordhvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3hNV = (GLEEPFNGLSECONDARYCOLOR3HNVPROC) __GLeeGetProcAddress("glSecondaryColor3hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glSecondaryColor3hvNV = (GLEEPFNGLSECONDARYCOLOR3HVNVPROC) __GLeeGetProcAddress("glSecondaryColor3hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexWeighthNV = (GLEEPFNGLVERTEXWEIGHTHNVPROC) __GLeeGetProcAddress("glVertexWeighthNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexWeighthvNV = (GLEEPFNGLVERTEXWEIGHTHVNVPROC) __GLeeGetProcAddress("glVertexWeighthvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1hNV = (GLEEPFNGLVERTEXATTRIB1HNVPROC) __GLeeGetProcAddress("glVertexAttrib1hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib1hvNV = (GLEEPFNGLVERTEXATTRIB1HVNVPROC) __GLeeGetProcAddress("glVertexAttrib1hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2hNV = (GLEEPFNGLVERTEXATTRIB2HNVPROC) __GLeeGetProcAddress("glVertexAttrib2hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib2hvNV = (GLEEPFNGLVERTEXATTRIB2HVNVPROC) __GLeeGetProcAddress("glVertexAttrib2hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3hNV = (GLEEPFNGLVERTEXATTRIB3HNVPROC) __GLeeGetProcAddress("glVertexAttrib3hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib3hvNV = (GLEEPFNGLVERTEXATTRIB3HVNVPROC) __GLeeGetProcAddress("glVertexAttrib3hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4hNV = (GLEEPFNGLVERTEXATTRIB4HNVPROC) __GLeeGetProcAddress("glVertexAttrib4hNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttrib4hvNV = (GLEEPFNGLVERTEXATTRIB4HVNVPROC) __GLeeGetProcAddress("glVertexAttrib4hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs1hvNV = (GLEEPFNGLVERTEXATTRIBS1HVNVPROC) __GLeeGetProcAddress("glVertexAttribs1hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs2hvNV = (GLEEPFNGLVERTEXATTRIBS2HVNVPROC) __GLeeGetProcAddress("glVertexAttribs2hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs3hvNV = (GLEEPFNGLVERTEXATTRIBS3HVNVPROC) __GLeeGetProcAddress("glVertexAttribs3hvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribs4hvNV = (GLEEPFNGLVERTEXATTRIBS4HVNVPROC) __GLeeGetProcAddress("glVertexAttribs4hvNV"))!=0) nLinked++; +#endif + if (nLinked==46) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_NV_pixel_data_range(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_pixel_data_range + if ((GLeeFuncPtr_glPixelDataRangeNV = (GLEEPFNGLPIXELDATARANGENVPROC) __GLeeGetProcAddress("glPixelDataRangeNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glFlushPixelDataRangeNV = (GLEEPFNGLFLUSHPIXELDATARANGENVPROC) __GLeeGetProcAddress("glFlushPixelDataRangeNV"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_NV_primitive_restart(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_primitive_restart + if ((GLeeFuncPtr_glPrimitiveRestartNV = (GLEEPFNGLPRIMITIVERESTARTNVPROC) __GLeeGetProcAddress("glPrimitiveRestartNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glPrimitiveRestartIndexNV = (GLEEPFNGLPRIMITIVERESTARTINDEXNVPROC) __GLeeGetProcAddress("glPrimitiveRestartIndexNV"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_NV_texture_expand_normal(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_vertex_program2(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_ATI_map_object_buffer(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ATI_map_object_buffer + if ((GLeeFuncPtr_glMapObjectBufferATI = (GLEEPFNGLMAPOBJECTBUFFERATIPROC) __GLeeGetProcAddress("glMapObjectBufferATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glUnmapObjectBufferATI = (GLEEPFNGLUNMAPOBJECTBUFFERATIPROC) __GLeeGetProcAddress("glUnmapObjectBufferATI"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ATI_separate_stencil(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ATI_separate_stencil + if ((GLeeFuncPtr_glStencilOpSeparateATI = (GLEEPFNGLSTENCILOPSEPARATEATIPROC) __GLeeGetProcAddress("glStencilOpSeparateATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glStencilFuncSeparateATI = (GLEEPFNGLSTENCILFUNCSEPARATEATIPROC) __GLeeGetProcAddress("glStencilFuncSeparateATI"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_ATI_vertex_attrib_array_object(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_ATI_vertex_attrib_array_object + if ((GLeeFuncPtr_glVertexAttribArrayObjectATI = (GLEEPFNGLVERTEXATTRIBARRAYOBJECTATIPROC) __GLeeGetProcAddress("glVertexAttribArrayObjectATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribArrayObjectfvATI = (GLEEPFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) __GLeeGetProcAddress("glGetVertexAttribArrayObjectfvATI"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribArrayObjectivATI = (GLEEPFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) __GLeeGetProcAddress("glGetVertexAttribArrayObjectivATI"))!=0) nLinked++; +#endif + if (nLinked==3) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_OES_read_format(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_depth_bounds_test(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_depth_bounds_test + if ((GLeeFuncPtr_glDepthBoundsEXT = (GLEEPFNGLDEPTHBOUNDSEXTPROC) __GLeeGetProcAddress("glDepthBoundsEXT"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_texture_mirror_clamp(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_blend_equation_separate(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_blend_equation_separate + if ((GLeeFuncPtr_glBlendEquationSeparateEXT = (GLEEPFNGLBLENDEQUATIONSEPARATEEXTPROC) __GLeeGetProcAddress("glBlendEquationSeparateEXT"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_MESA_pack_invert(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_MESA_ycbcr_texture(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_pixel_buffer_object(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_fragment_program_option(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_fragment_program2(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_vertex_program2_option(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_vertex_program3(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_framebuffer_object(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_framebuffer_object + if ((GLeeFuncPtr_glIsRenderbufferEXT = (GLEEPFNGLISRENDERBUFFEREXTPROC) __GLeeGetProcAddress("glIsRenderbufferEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindRenderbufferEXT = (GLEEPFNGLBINDRENDERBUFFEREXTPROC) __GLeeGetProcAddress("glBindRenderbufferEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteRenderbuffersEXT = (GLEEPFNGLDELETERENDERBUFFERSEXTPROC) __GLeeGetProcAddress("glDeleteRenderbuffersEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenRenderbuffersEXT = (GLEEPFNGLGENRENDERBUFFERSEXTPROC) __GLeeGetProcAddress("glGenRenderbuffersEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glRenderbufferStorageEXT = (GLEEPFNGLRENDERBUFFERSTORAGEEXTPROC) __GLeeGetProcAddress("glRenderbufferStorageEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetRenderbufferParameterivEXT = (GLEEPFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) __GLeeGetProcAddress("glGetRenderbufferParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsFramebufferEXT = (GLEEPFNGLISFRAMEBUFFEREXTPROC) __GLeeGetProcAddress("glIsFramebufferEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindFramebufferEXT = (GLEEPFNGLBINDFRAMEBUFFEREXTPROC) __GLeeGetProcAddress("glBindFramebufferEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteFramebuffersEXT = (GLEEPFNGLDELETEFRAMEBUFFERSEXTPROC) __GLeeGetProcAddress("glDeleteFramebuffersEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenFramebuffersEXT = (GLEEPFNGLGENFRAMEBUFFERSEXTPROC) __GLeeGetProcAddress("glGenFramebuffersEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCheckFramebufferStatusEXT = (GLEEPFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) __GLeeGetProcAddress("glCheckFramebufferStatusEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferTexture1DEXT = (GLEEPFNGLFRAMEBUFFERTEXTURE1DEXTPROC) __GLeeGetProcAddress("glFramebufferTexture1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferTexture2DEXT = (GLEEPFNGLFRAMEBUFFERTEXTURE2DEXTPROC) __GLeeGetProcAddress("glFramebufferTexture2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferTexture3DEXT = (GLEEPFNGLFRAMEBUFFERTEXTURE3DEXTPROC) __GLeeGetProcAddress("glFramebufferTexture3DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferRenderbufferEXT = (GLEEPFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) __GLeeGetProcAddress("glFramebufferRenderbufferEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFramebufferAttachmentParameterivEXT = (GLEEPFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) __GLeeGetProcAddress("glGetFramebufferAttachmentParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenerateMipmapEXT = (GLEEPFNGLGENERATEMIPMAPEXTPROC) __GLeeGetProcAddress("glGenerateMipmapEXT"))!=0) nLinked++; +#endif + if (nLinked==17) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_GREMEDY_string_marker(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_GREMEDY_string_marker + if ((GLeeFuncPtr_glStringMarkerGREMEDY = (GLEEPFNGLSTRINGMARKERGREMEDYPROC) __GLeeGetProcAddress("glStringMarkerGREMEDY"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_packed_depth_stencil(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_stencil_clear_tag(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_stencil_clear_tag + if ((GLeeFuncPtr_glStencilClearTagEXT = (GLEEPFNGLSTENCILCLEARTAGEXTPROC) __GLeeGetProcAddress("glStencilClearTagEXT"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_texture_sRGB(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_framebuffer_blit(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_framebuffer_blit + if ((GLeeFuncPtr_glBlitFramebufferEXT = (GLEEPFNGLBLITFRAMEBUFFEREXTPROC) __GLeeGetProcAddress("glBlitFramebufferEXT"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_framebuffer_multisample(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_framebuffer_multisample + if ((GLeeFuncPtr_glRenderbufferStorageMultisampleEXT = (GLEEPFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) __GLeeGetProcAddress("glRenderbufferStorageMultisampleEXT"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_MESAX_texture_stack(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_timer_query(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_timer_query + if ((GLeeFuncPtr_glGetQueryObjecti64vEXT = (GLEEPFNGLGETQUERYOBJECTI64VEXTPROC) __GLeeGetProcAddress("glGetQueryObjecti64vEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetQueryObjectui64vEXT = (GLEEPFNGLGETQUERYOBJECTUI64VEXTPROC) __GLeeGetProcAddress("glGetQueryObjectui64vEXT"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_gpu_program_parameters(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_gpu_program_parameters + if ((GLeeFuncPtr_glProgramEnvParameters4fvEXT = (GLEEPFNGLPROGRAMENVPARAMETERS4FVEXTPROC) __GLeeGetProcAddress("glProgramEnvParameters4fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramLocalParameters4fvEXT = (GLEEPFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) __GLeeGetProcAddress("glProgramLocalParameters4fvEXT"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_APPLE_flush_buffer_range(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_APPLE_flush_buffer_range + if ((GLeeFuncPtr_glBufferParameteriAPPLE = (GLEEPFNGLBUFFERPARAMETERIAPPLEPROC) __GLeeGetProcAddress("glBufferParameteriAPPLE"))!=0) nLinked++; + if ((GLeeFuncPtr_glFlushMappedBufferRangeAPPLE = (GLEEPFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) __GLeeGetProcAddress("glFlushMappedBufferRangeAPPLE"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_gpu_shader4(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_gpu_shader4 + if ((GLeeFuncPtr_glGetUniformuivEXT = (GLEEPFNGLGETUNIFORMUIVEXTPROC) __GLeeGetProcAddress("glGetUniformuivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindFragDataLocationEXT = (GLEEPFNGLBINDFRAGDATALOCATIONEXTPROC) __GLeeGetProcAddress("glBindFragDataLocationEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFragDataLocationEXT = (GLEEPFNGLGETFRAGDATALOCATIONEXTPROC) __GLeeGetProcAddress("glGetFragDataLocationEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform1uiEXT = (GLEEPFNGLUNIFORM1UIEXTPROC) __GLeeGetProcAddress("glUniform1uiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform2uiEXT = (GLEEPFNGLUNIFORM2UIEXTPROC) __GLeeGetProcAddress("glUniform2uiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform3uiEXT = (GLEEPFNGLUNIFORM3UIEXTPROC) __GLeeGetProcAddress("glUniform3uiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform4uiEXT = (GLEEPFNGLUNIFORM4UIEXTPROC) __GLeeGetProcAddress("glUniform4uiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform1uivEXT = (GLEEPFNGLUNIFORM1UIVEXTPROC) __GLeeGetProcAddress("glUniform1uivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform2uivEXT = (GLEEPFNGLUNIFORM2UIVEXTPROC) __GLeeGetProcAddress("glUniform2uivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform3uivEXT = (GLEEPFNGLUNIFORM3UIVEXTPROC) __GLeeGetProcAddress("glUniform3uivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glUniform4uivEXT = (GLEEPFNGLUNIFORM4UIVEXTPROC) __GLeeGetProcAddress("glUniform4uivEXT"))!=0) nLinked++; +#endif + if (nLinked==11) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_draw_instanced(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_draw_instanced + if ((GLeeFuncPtr_glDrawArraysInstancedEXT = (GLEEPFNGLDRAWARRAYSINSTANCEDEXTPROC) __GLeeGetProcAddress("glDrawArraysInstancedEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glDrawElementsInstancedEXT = (GLEEPFNGLDRAWELEMENTSINSTANCEDEXTPROC) __GLeeGetProcAddress("glDrawElementsInstancedEXT"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_packed_float(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_texture_array(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_texture_buffer_object(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_texture_buffer_object + if ((GLeeFuncPtr_glTexBufferEXT = (GLEEPFNGLTEXBUFFEREXTPROC) __GLeeGetProcAddress("glTexBufferEXT"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_texture_compression_latc(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_texture_compression_rgtc(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_texture_shared_exponent(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_depth_buffer_float(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_depth_buffer_float + if ((GLeeFuncPtr_glDepthRangedNV = (GLEEPFNGLDEPTHRANGEDNVPROC) __GLeeGetProcAddress("glDepthRangedNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glClearDepthdNV = (GLEEPFNGLCLEARDEPTHDNVPROC) __GLeeGetProcAddress("glClearDepthdNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glDepthBoundsdNV = (GLEEPFNGLDEPTHBOUNDSDNVPROC) __GLeeGetProcAddress("glDepthBoundsdNV"))!=0) nLinked++; +#endif + if (nLinked==3) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_NV_framebuffer_multisample_coverage(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_framebuffer_multisample_coverage + if ((GLeeFuncPtr_glRenderbufferStorageMultisampleCoverageNV = (GLEEPFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) __GLeeGetProcAddress("glRenderbufferStorageMultisampleCoverageNV"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_framebuffer_sRGB(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_geometry_shader4(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_parameter_buffer_object(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_parameter_buffer_object + if ((GLeeFuncPtr_glProgramBufferParametersfvNV = (GLEEPFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) __GLeeGetProcAddress("glProgramBufferParametersfvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramBufferParametersIivNV = (GLEEPFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) __GLeeGetProcAddress("glProgramBufferParametersIivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramBufferParametersIuivNV = (GLEEPFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) __GLeeGetProcAddress("glProgramBufferParametersIuivNV"))!=0) nLinked++; +#endif + if (nLinked==3) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_draw_buffers2(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_draw_buffers2 + if ((GLeeFuncPtr_glColorMaskIndexedEXT = (GLEEPFNGLCOLORMASKINDEXEDEXTPROC) __GLeeGetProcAddress("glColorMaskIndexedEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetBooleanIndexedvEXT = (GLEEPFNGLGETBOOLEANINDEXEDVEXTPROC) __GLeeGetProcAddress("glGetBooleanIndexedvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetIntegerIndexedvEXT = (GLEEPFNGLGETINTEGERINDEXEDVEXTPROC) __GLeeGetProcAddress("glGetIntegerIndexedvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glEnableIndexedEXT = (GLEEPFNGLENABLEINDEXEDEXTPROC) __GLeeGetProcAddress("glEnableIndexedEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glDisableIndexedEXT = (GLEEPFNGLDISABLEINDEXEDEXTPROC) __GLeeGetProcAddress("glDisableIndexedEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsEnabledIndexedEXT = (GLEEPFNGLISENABLEDINDEXEDEXTPROC) __GLeeGetProcAddress("glIsEnabledIndexedEXT"))!=0) nLinked++; +#endif + if (nLinked==6) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_NV_transform_feedback(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_transform_feedback + if ((GLeeFuncPtr_glBeginTransformFeedbackNV = (GLEEPFNGLBEGINTRANSFORMFEEDBACKNVPROC) __GLeeGetProcAddress("glBeginTransformFeedbackNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glEndTransformFeedbackNV = (GLEEPFNGLENDTRANSFORMFEEDBACKNVPROC) __GLeeGetProcAddress("glEndTransformFeedbackNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glTransformFeedbackAttribsNV = (GLEEPFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) __GLeeGetProcAddress("glTransformFeedbackAttribsNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindBufferRangeNV = (GLEEPFNGLBINDBUFFERRANGENVPROC) __GLeeGetProcAddress("glBindBufferRangeNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindBufferOffsetNV = (GLEEPFNGLBINDBUFFEROFFSETNVPROC) __GLeeGetProcAddress("glBindBufferOffsetNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindBufferBaseNV = (GLEEPFNGLBINDBUFFERBASENVPROC) __GLeeGetProcAddress("glBindBufferBaseNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glTransformFeedbackVaryingsNV = (GLEEPFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) __GLeeGetProcAddress("glTransformFeedbackVaryingsNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glActiveVaryingNV = (GLEEPFNGLACTIVEVARYINGNVPROC) __GLeeGetProcAddress("glActiveVaryingNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVaryingLocationNV = (GLEEPFNGLGETVARYINGLOCATIONNVPROC) __GLeeGetProcAddress("glGetVaryingLocationNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetActiveVaryingNV = (GLEEPFNGLGETACTIVEVARYINGNVPROC) __GLeeGetProcAddress("glGetActiveVaryingNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTransformFeedbackVaryingNV = (GLEEPFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) __GLeeGetProcAddress("glGetTransformFeedbackVaryingNV"))!=0) nLinked++; +#endif + if (nLinked==11) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_bindable_uniform(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_bindable_uniform + if ((GLeeFuncPtr_glUniformBufferEXT = (GLEEPFNGLUNIFORMBUFFEREXTPROC) __GLeeGetProcAddress("glUniformBufferEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetUniformBufferSizeEXT = (GLEEPFNGLGETUNIFORMBUFFERSIZEEXTPROC) __GLeeGetProcAddress("glGetUniformBufferSizeEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetUniformOffsetEXT = (GLEEPFNGLGETUNIFORMOFFSETEXTPROC) __GLeeGetProcAddress("glGetUniformOffsetEXT"))!=0) nLinked++; +#endif + if (nLinked==3) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_texture_integer(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_texture_integer + if ((GLeeFuncPtr_glTexParameterIivEXT = (GLEEPFNGLTEXPARAMETERIIVEXTPROC) __GLeeGetProcAddress("glTexParameterIivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexParameterIuivEXT = (GLEEPFNGLTEXPARAMETERIUIVEXTPROC) __GLeeGetProcAddress("glTexParameterIuivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTexParameterIivEXT = (GLEEPFNGLGETTEXPARAMETERIIVEXTPROC) __GLeeGetProcAddress("glGetTexParameterIivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTexParameterIuivEXT = (GLEEPFNGLGETTEXPARAMETERIUIVEXTPROC) __GLeeGetProcAddress("glGetTexParameterIuivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glClearColorIiEXT = (GLEEPFNGLCLEARCOLORIIEXTPROC) __GLeeGetProcAddress("glClearColorIiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glClearColorIuiEXT = (GLEEPFNGLCLEARCOLORIUIEXTPROC) __GLeeGetProcAddress("glClearColorIuiEXT"))!=0) nLinked++; +#endif + if (nLinked==6) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_GREMEDY_frame_terminator(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_GREMEDY_frame_terminator + if ((GLeeFuncPtr_glFrameTerminatorGREMEDY = (GLEEPFNGLFRAMETERMINATORGREMEDYPROC) __GLeeGetProcAddress("glFrameTerminatorGREMEDY"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_NV_conditional_render(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_conditional_render + if ((GLeeFuncPtr_glBeginConditionalRenderNV = (GLEEPFNGLBEGINCONDITIONALRENDERNVPROC) __GLeeGetProcAddress("glBeginConditionalRenderNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glEndConditionalRenderNV = (GLEEPFNGLENDCONDITIONALRENDERNVPROC) __GLeeGetProcAddress("glEndConditionalRenderNV"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_NV_present_video(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_transform_feedback(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_transform_feedback + if ((GLeeFuncPtr_glBeginTransformFeedbackEXT = (GLEEPFNGLBEGINTRANSFORMFEEDBACKEXTPROC) __GLeeGetProcAddress("glBeginTransformFeedbackEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glEndTransformFeedbackEXT = (GLEEPFNGLENDTRANSFORMFEEDBACKEXTPROC) __GLeeGetProcAddress("glEndTransformFeedbackEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindBufferRangeEXT = (GLEEPFNGLBINDBUFFERRANGEEXTPROC) __GLeeGetProcAddress("glBindBufferRangeEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindBufferOffsetEXT = (GLEEPFNGLBINDBUFFEROFFSETEXTPROC) __GLeeGetProcAddress("glBindBufferOffsetEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindBufferBaseEXT = (GLEEPFNGLBINDBUFFERBASEEXTPROC) __GLeeGetProcAddress("glBindBufferBaseEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTransformFeedbackVaryingsEXT = (GLEEPFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) __GLeeGetProcAddress("glTransformFeedbackVaryingsEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTransformFeedbackVaryingEXT = (GLEEPFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) __GLeeGetProcAddress("glGetTransformFeedbackVaryingEXT"))!=0) nLinked++; +#endif + if (nLinked==7) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_direct_state_access(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_direct_state_access + if ((GLeeFuncPtr_glClientAttribDefaultEXT = (GLEEPFNGLCLIENTATTRIBDEFAULTEXTPROC) __GLeeGetProcAddress("glClientAttribDefaultEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glPushClientAttribDefaultEXT = (GLEEPFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) __GLeeGetProcAddress("glPushClientAttribDefaultEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixLoadfEXT = (GLEEPFNGLMATRIXLOADFEXTPROC) __GLeeGetProcAddress("glMatrixLoadfEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixLoaddEXT = (GLEEPFNGLMATRIXLOADDEXTPROC) __GLeeGetProcAddress("glMatrixLoaddEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixMultfEXT = (GLEEPFNGLMATRIXMULTFEXTPROC) __GLeeGetProcAddress("glMatrixMultfEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixMultdEXT = (GLEEPFNGLMATRIXMULTDEXTPROC) __GLeeGetProcAddress("glMatrixMultdEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixLoadIdentityEXT = (GLEEPFNGLMATRIXLOADIDENTITYEXTPROC) __GLeeGetProcAddress("glMatrixLoadIdentityEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixRotatefEXT = (GLEEPFNGLMATRIXROTATEFEXTPROC) __GLeeGetProcAddress("glMatrixRotatefEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixRotatedEXT = (GLEEPFNGLMATRIXROTATEDEXTPROC) __GLeeGetProcAddress("glMatrixRotatedEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixScalefEXT = (GLEEPFNGLMATRIXSCALEFEXTPROC) __GLeeGetProcAddress("glMatrixScalefEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixScaledEXT = (GLEEPFNGLMATRIXSCALEDEXTPROC) __GLeeGetProcAddress("glMatrixScaledEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixTranslatefEXT = (GLEEPFNGLMATRIXTRANSLATEFEXTPROC) __GLeeGetProcAddress("glMatrixTranslatefEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixTranslatedEXT = (GLEEPFNGLMATRIXTRANSLATEDEXTPROC) __GLeeGetProcAddress("glMatrixTranslatedEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixFrustumEXT = (GLEEPFNGLMATRIXFRUSTUMEXTPROC) __GLeeGetProcAddress("glMatrixFrustumEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixOrthoEXT = (GLEEPFNGLMATRIXORTHOEXTPROC) __GLeeGetProcAddress("glMatrixOrthoEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixPopEXT = (GLEEPFNGLMATRIXPOPEXTPROC) __GLeeGetProcAddress("glMatrixPopEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixPushEXT = (GLEEPFNGLMATRIXPUSHEXTPROC) __GLeeGetProcAddress("glMatrixPushEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixLoadTransposefEXT = (GLEEPFNGLMATRIXLOADTRANSPOSEFEXTPROC) __GLeeGetProcAddress("glMatrixLoadTransposefEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixLoadTransposedEXT = (GLEEPFNGLMATRIXLOADTRANSPOSEDEXTPROC) __GLeeGetProcAddress("glMatrixLoadTransposedEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixMultTransposefEXT = (GLEEPFNGLMATRIXMULTTRANSPOSEFEXTPROC) __GLeeGetProcAddress("glMatrixMultTransposefEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMatrixMultTransposedEXT = (GLEEPFNGLMATRIXMULTTRANSPOSEDEXTPROC) __GLeeGetProcAddress("glMatrixMultTransposedEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTextureParameterfEXT = (GLEEPFNGLTEXTUREPARAMETERFEXTPROC) __GLeeGetProcAddress("glTextureParameterfEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTextureParameterfvEXT = (GLEEPFNGLTEXTUREPARAMETERFVEXTPROC) __GLeeGetProcAddress("glTextureParameterfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTextureParameteriEXT = (GLEEPFNGLTEXTUREPARAMETERIEXTPROC) __GLeeGetProcAddress("glTextureParameteriEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTextureParameterivEXT = (GLEEPFNGLTEXTUREPARAMETERIVEXTPROC) __GLeeGetProcAddress("glTextureParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTextureImage1DEXT = (GLEEPFNGLTEXTUREIMAGE1DEXTPROC) __GLeeGetProcAddress("glTextureImage1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTextureImage2DEXT = (GLEEPFNGLTEXTUREIMAGE2DEXTPROC) __GLeeGetProcAddress("glTextureImage2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTextureSubImage1DEXT = (GLEEPFNGLTEXTURESUBIMAGE1DEXTPROC) __GLeeGetProcAddress("glTextureSubImage1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTextureSubImage2DEXT = (GLEEPFNGLTEXTURESUBIMAGE2DEXTPROC) __GLeeGetProcAddress("glTextureSubImage2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyTextureImage1DEXT = (GLEEPFNGLCOPYTEXTUREIMAGE1DEXTPROC) __GLeeGetProcAddress("glCopyTextureImage1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyTextureImage2DEXT = (GLEEPFNGLCOPYTEXTUREIMAGE2DEXTPROC) __GLeeGetProcAddress("glCopyTextureImage2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyTextureSubImage1DEXT = (GLEEPFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) __GLeeGetProcAddress("glCopyTextureSubImage1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyTextureSubImage2DEXT = (GLEEPFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) __GLeeGetProcAddress("glCopyTextureSubImage2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTextureImageEXT = (GLEEPFNGLGETTEXTUREIMAGEEXTPROC) __GLeeGetProcAddress("glGetTextureImageEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTextureParameterfvEXT = (GLEEPFNGLGETTEXTUREPARAMETERFVEXTPROC) __GLeeGetProcAddress("glGetTextureParameterfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTextureParameterivEXT = (GLEEPFNGLGETTEXTUREPARAMETERIVEXTPROC) __GLeeGetProcAddress("glGetTextureParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTextureLevelParameterfvEXT = (GLEEPFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) __GLeeGetProcAddress("glGetTextureLevelParameterfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTextureLevelParameterivEXT = (GLEEPFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) __GLeeGetProcAddress("glGetTextureLevelParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTextureImage3DEXT = (GLEEPFNGLTEXTUREIMAGE3DEXTPROC) __GLeeGetProcAddress("glTextureImage3DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTextureSubImage3DEXT = (GLEEPFNGLTEXTURESUBIMAGE3DEXTPROC) __GLeeGetProcAddress("glTextureSubImage3DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyTextureSubImage3DEXT = (GLEEPFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) __GLeeGetProcAddress("glCopyTextureSubImage3DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexParameterfEXT = (GLEEPFNGLMULTITEXPARAMETERFEXTPROC) __GLeeGetProcAddress("glMultiTexParameterfEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexParameterfvEXT = (GLEEPFNGLMULTITEXPARAMETERFVEXTPROC) __GLeeGetProcAddress("glMultiTexParameterfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexParameteriEXT = (GLEEPFNGLMULTITEXPARAMETERIEXTPROC) __GLeeGetProcAddress("glMultiTexParameteriEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexParameterivEXT = (GLEEPFNGLMULTITEXPARAMETERIVEXTPROC) __GLeeGetProcAddress("glMultiTexParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexImage1DEXT = (GLEEPFNGLMULTITEXIMAGE1DEXTPROC) __GLeeGetProcAddress("glMultiTexImage1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexImage2DEXT = (GLEEPFNGLMULTITEXIMAGE2DEXTPROC) __GLeeGetProcAddress("glMultiTexImage2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexSubImage1DEXT = (GLEEPFNGLMULTITEXSUBIMAGE1DEXTPROC) __GLeeGetProcAddress("glMultiTexSubImage1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexSubImage2DEXT = (GLEEPFNGLMULTITEXSUBIMAGE2DEXTPROC) __GLeeGetProcAddress("glMultiTexSubImage2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyMultiTexImage1DEXT = (GLEEPFNGLCOPYMULTITEXIMAGE1DEXTPROC) __GLeeGetProcAddress("glCopyMultiTexImage1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyMultiTexImage2DEXT = (GLEEPFNGLCOPYMULTITEXIMAGE2DEXTPROC) __GLeeGetProcAddress("glCopyMultiTexImage2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyMultiTexSubImage1DEXT = (GLEEPFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) __GLeeGetProcAddress("glCopyMultiTexSubImage1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyMultiTexSubImage2DEXT = (GLEEPFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) __GLeeGetProcAddress("glCopyMultiTexSubImage2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMultiTexImageEXT = (GLEEPFNGLGETMULTITEXIMAGEEXTPROC) __GLeeGetProcAddress("glGetMultiTexImageEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMultiTexParameterfvEXT = (GLEEPFNGLGETMULTITEXPARAMETERFVEXTPROC) __GLeeGetProcAddress("glGetMultiTexParameterfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMultiTexParameterivEXT = (GLEEPFNGLGETMULTITEXPARAMETERIVEXTPROC) __GLeeGetProcAddress("glGetMultiTexParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMultiTexLevelParameterfvEXT = (GLEEPFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) __GLeeGetProcAddress("glGetMultiTexLevelParameterfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMultiTexLevelParameterivEXT = (GLEEPFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) __GLeeGetProcAddress("glGetMultiTexLevelParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexImage3DEXT = (GLEEPFNGLMULTITEXIMAGE3DEXTPROC) __GLeeGetProcAddress("glMultiTexImage3DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexSubImage3DEXT = (GLEEPFNGLMULTITEXSUBIMAGE3DEXTPROC) __GLeeGetProcAddress("glMultiTexSubImage3DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCopyMultiTexSubImage3DEXT = (GLEEPFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) __GLeeGetProcAddress("glCopyMultiTexSubImage3DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glBindMultiTextureEXT = (GLEEPFNGLBINDMULTITEXTUREEXTPROC) __GLeeGetProcAddress("glBindMultiTextureEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glEnableClientStateIndexedEXT = (GLEEPFNGLENABLECLIENTSTATEINDEXEDEXTPROC) __GLeeGetProcAddress("glEnableClientStateIndexedEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glDisableClientStateIndexedEXT = (GLEEPFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) __GLeeGetProcAddress("glDisableClientStateIndexedEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexCoordPointerEXT = (GLEEPFNGLMULTITEXCOORDPOINTEREXTPROC) __GLeeGetProcAddress("glMultiTexCoordPointerEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexEnvfEXT = (GLEEPFNGLMULTITEXENVFEXTPROC) __GLeeGetProcAddress("glMultiTexEnvfEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexEnvfvEXT = (GLEEPFNGLMULTITEXENVFVEXTPROC) __GLeeGetProcAddress("glMultiTexEnvfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexEnviEXT = (GLEEPFNGLMULTITEXENVIEXTPROC) __GLeeGetProcAddress("glMultiTexEnviEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexEnvivEXT = (GLEEPFNGLMULTITEXENVIVEXTPROC) __GLeeGetProcAddress("glMultiTexEnvivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexGendEXT = (GLEEPFNGLMULTITEXGENDEXTPROC) __GLeeGetProcAddress("glMultiTexGendEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexGendvEXT = (GLEEPFNGLMULTITEXGENDVEXTPROC) __GLeeGetProcAddress("glMultiTexGendvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexGenfEXT = (GLEEPFNGLMULTITEXGENFEXTPROC) __GLeeGetProcAddress("glMultiTexGenfEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexGenfvEXT = (GLEEPFNGLMULTITEXGENFVEXTPROC) __GLeeGetProcAddress("glMultiTexGenfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexGeniEXT = (GLEEPFNGLMULTITEXGENIEXTPROC) __GLeeGetProcAddress("glMultiTexGeniEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexGenivEXT = (GLEEPFNGLMULTITEXGENIVEXTPROC) __GLeeGetProcAddress("glMultiTexGenivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMultiTexEnvfvEXT = (GLEEPFNGLGETMULTITEXENVFVEXTPROC) __GLeeGetProcAddress("glGetMultiTexEnvfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMultiTexEnvivEXT = (GLEEPFNGLGETMULTITEXENVIVEXTPROC) __GLeeGetProcAddress("glGetMultiTexEnvivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMultiTexGendvEXT = (GLEEPFNGLGETMULTITEXGENDVEXTPROC) __GLeeGetProcAddress("glGetMultiTexGendvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMultiTexGenfvEXT = (GLEEPFNGLGETMULTITEXGENFVEXTPROC) __GLeeGetProcAddress("glGetMultiTexGenfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMultiTexGenivEXT = (GLEEPFNGLGETMULTITEXGENIVEXTPROC) __GLeeGetProcAddress("glGetMultiTexGenivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFloatIndexedvEXT = (GLEEPFNGLGETFLOATINDEXEDVEXTPROC) __GLeeGetProcAddress("glGetFloatIndexedvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetDoubleIndexedvEXT = (GLEEPFNGLGETDOUBLEINDEXEDVEXTPROC) __GLeeGetProcAddress("glGetDoubleIndexedvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetPointerIndexedvEXT = (GLEEPFNGLGETPOINTERINDEXEDVEXTPROC) __GLeeGetProcAddress("glGetPointerIndexedvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTextureImage3DEXT = (GLEEPFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) __GLeeGetProcAddress("glCompressedTextureImage3DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTextureImage2DEXT = (GLEEPFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) __GLeeGetProcAddress("glCompressedTextureImage2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTextureImage1DEXT = (GLEEPFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) __GLeeGetProcAddress("glCompressedTextureImage1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTextureSubImage3DEXT = (GLEEPFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) __GLeeGetProcAddress("glCompressedTextureSubImage3DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTextureSubImage2DEXT = (GLEEPFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) __GLeeGetProcAddress("glCompressedTextureSubImage2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedTextureSubImage1DEXT = (GLEEPFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) __GLeeGetProcAddress("glCompressedTextureSubImage1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetCompressedTextureImageEXT = (GLEEPFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) __GLeeGetProcAddress("glGetCompressedTextureImageEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedMultiTexImage3DEXT = (GLEEPFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) __GLeeGetProcAddress("glCompressedMultiTexImage3DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedMultiTexImage2DEXT = (GLEEPFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) __GLeeGetProcAddress("glCompressedMultiTexImage2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedMultiTexImage1DEXT = (GLEEPFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) __GLeeGetProcAddress("glCompressedMultiTexImage1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedMultiTexSubImage3DEXT = (GLEEPFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) __GLeeGetProcAddress("glCompressedMultiTexSubImage3DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedMultiTexSubImage2DEXT = (GLEEPFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) __GLeeGetProcAddress("glCompressedMultiTexSubImage2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCompressedMultiTexSubImage1DEXT = (GLEEPFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) __GLeeGetProcAddress("glCompressedMultiTexSubImage1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetCompressedMultiTexImageEXT = (GLEEPFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) __GLeeGetProcAddress("glGetCompressedMultiTexImageEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedProgramStringEXT = (GLEEPFNGLNAMEDPROGRAMSTRINGEXTPROC) __GLeeGetProcAddress("glNamedProgramStringEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedProgramLocalParameter4dEXT = (GLEEPFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) __GLeeGetProcAddress("glNamedProgramLocalParameter4dEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedProgramLocalParameter4dvEXT = (GLEEPFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) __GLeeGetProcAddress("glNamedProgramLocalParameter4dvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedProgramLocalParameter4fEXT = (GLEEPFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) __GLeeGetProcAddress("glNamedProgramLocalParameter4fEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedProgramLocalParameter4fvEXT = (GLEEPFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) __GLeeGetProcAddress("glNamedProgramLocalParameter4fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetNamedProgramLocalParameterdvEXT = (GLEEPFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) __GLeeGetProcAddress("glGetNamedProgramLocalParameterdvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetNamedProgramLocalParameterfvEXT = (GLEEPFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) __GLeeGetProcAddress("glGetNamedProgramLocalParameterfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetNamedProgramivEXT = (GLEEPFNGLGETNAMEDPROGRAMIVEXTPROC) __GLeeGetProcAddress("glGetNamedProgramivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetNamedProgramStringEXT = (GLEEPFNGLGETNAMEDPROGRAMSTRINGEXTPROC) __GLeeGetProcAddress("glGetNamedProgramStringEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedProgramLocalParameters4fvEXT = (GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) __GLeeGetProcAddress("glNamedProgramLocalParameters4fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedProgramLocalParameterI4iEXT = (GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) __GLeeGetProcAddress("glNamedProgramLocalParameterI4iEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedProgramLocalParameterI4ivEXT = (GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) __GLeeGetProcAddress("glNamedProgramLocalParameterI4ivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedProgramLocalParametersI4ivEXT = (GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) __GLeeGetProcAddress("glNamedProgramLocalParametersI4ivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedProgramLocalParameterI4uiEXT = (GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) __GLeeGetProcAddress("glNamedProgramLocalParameterI4uiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedProgramLocalParameterI4uivEXT = (GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) __GLeeGetProcAddress("glNamedProgramLocalParameterI4uivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedProgramLocalParametersI4uivEXT = (GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) __GLeeGetProcAddress("glNamedProgramLocalParametersI4uivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetNamedProgramLocalParameterIivEXT = (GLEEPFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) __GLeeGetProcAddress("glGetNamedProgramLocalParameterIivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetNamedProgramLocalParameterIuivEXT = (GLEEPFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) __GLeeGetProcAddress("glGetNamedProgramLocalParameterIuivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTextureParameterIivEXT = (GLEEPFNGLTEXTUREPARAMETERIIVEXTPROC) __GLeeGetProcAddress("glTextureParameterIivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTextureParameterIuivEXT = (GLEEPFNGLTEXTUREPARAMETERIUIVEXTPROC) __GLeeGetProcAddress("glTextureParameterIuivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTextureParameterIivEXT = (GLEEPFNGLGETTEXTUREPARAMETERIIVEXTPROC) __GLeeGetProcAddress("glGetTextureParameterIivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetTextureParameterIuivEXT = (GLEEPFNGLGETTEXTUREPARAMETERIUIVEXTPROC) __GLeeGetProcAddress("glGetTextureParameterIuivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexParameterIivEXT = (GLEEPFNGLMULTITEXPARAMETERIIVEXTPROC) __GLeeGetProcAddress("glMultiTexParameterIivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexParameterIuivEXT = (GLEEPFNGLMULTITEXPARAMETERIUIVEXTPROC) __GLeeGetProcAddress("glMultiTexParameterIuivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMultiTexParameterIivEXT = (GLEEPFNGLGETMULTITEXPARAMETERIIVEXTPROC) __GLeeGetProcAddress("glGetMultiTexParameterIivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetMultiTexParameterIuivEXT = (GLEEPFNGLGETMULTITEXPARAMETERIUIVEXTPROC) __GLeeGetProcAddress("glGetMultiTexParameterIuivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform1fEXT = (GLEEPFNGLPROGRAMUNIFORM1FEXTPROC) __GLeeGetProcAddress("glProgramUniform1fEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform2fEXT = (GLEEPFNGLPROGRAMUNIFORM2FEXTPROC) __GLeeGetProcAddress("glProgramUniform2fEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform3fEXT = (GLEEPFNGLPROGRAMUNIFORM3FEXTPROC) __GLeeGetProcAddress("glProgramUniform3fEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform4fEXT = (GLEEPFNGLPROGRAMUNIFORM4FEXTPROC) __GLeeGetProcAddress("glProgramUniform4fEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform1iEXT = (GLEEPFNGLPROGRAMUNIFORM1IEXTPROC) __GLeeGetProcAddress("glProgramUniform1iEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform2iEXT = (GLEEPFNGLPROGRAMUNIFORM2IEXTPROC) __GLeeGetProcAddress("glProgramUniform2iEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform3iEXT = (GLEEPFNGLPROGRAMUNIFORM3IEXTPROC) __GLeeGetProcAddress("glProgramUniform3iEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform4iEXT = (GLEEPFNGLPROGRAMUNIFORM4IEXTPROC) __GLeeGetProcAddress("glProgramUniform4iEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform1fvEXT = (GLEEPFNGLPROGRAMUNIFORM1FVEXTPROC) __GLeeGetProcAddress("glProgramUniform1fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform2fvEXT = (GLEEPFNGLPROGRAMUNIFORM2FVEXTPROC) __GLeeGetProcAddress("glProgramUniform2fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform3fvEXT = (GLEEPFNGLPROGRAMUNIFORM3FVEXTPROC) __GLeeGetProcAddress("glProgramUniform3fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform4fvEXT = (GLEEPFNGLPROGRAMUNIFORM4FVEXTPROC) __GLeeGetProcAddress("glProgramUniform4fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform1ivEXT = (GLEEPFNGLPROGRAMUNIFORM1IVEXTPROC) __GLeeGetProcAddress("glProgramUniform1ivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform2ivEXT = (GLEEPFNGLPROGRAMUNIFORM2IVEXTPROC) __GLeeGetProcAddress("glProgramUniform2ivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform3ivEXT = (GLEEPFNGLPROGRAMUNIFORM3IVEXTPROC) __GLeeGetProcAddress("glProgramUniform3ivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform4ivEXT = (GLEEPFNGLPROGRAMUNIFORM4IVEXTPROC) __GLeeGetProcAddress("glProgramUniform4ivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniformMatrix2fvEXT = (GLEEPFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) __GLeeGetProcAddress("glProgramUniformMatrix2fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniformMatrix3fvEXT = (GLEEPFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) __GLeeGetProcAddress("glProgramUniformMatrix3fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniformMatrix4fvEXT = (GLEEPFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) __GLeeGetProcAddress("glProgramUniformMatrix4fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniformMatrix2x3fvEXT = (GLEEPFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) __GLeeGetProcAddress("glProgramUniformMatrix2x3fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniformMatrix3x2fvEXT = (GLEEPFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) __GLeeGetProcAddress("glProgramUniformMatrix3x2fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniformMatrix2x4fvEXT = (GLEEPFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) __GLeeGetProcAddress("glProgramUniformMatrix2x4fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniformMatrix4x2fvEXT = (GLEEPFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) __GLeeGetProcAddress("glProgramUniformMatrix4x2fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniformMatrix3x4fvEXT = (GLEEPFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) __GLeeGetProcAddress("glProgramUniformMatrix3x4fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniformMatrix4x3fvEXT = (GLEEPFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) __GLeeGetProcAddress("glProgramUniformMatrix4x3fvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform1uiEXT = (GLEEPFNGLPROGRAMUNIFORM1UIEXTPROC) __GLeeGetProcAddress("glProgramUniform1uiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform2uiEXT = (GLEEPFNGLPROGRAMUNIFORM2UIEXTPROC) __GLeeGetProcAddress("glProgramUniform2uiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform3uiEXT = (GLEEPFNGLPROGRAMUNIFORM3UIEXTPROC) __GLeeGetProcAddress("glProgramUniform3uiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform4uiEXT = (GLEEPFNGLPROGRAMUNIFORM4UIEXTPROC) __GLeeGetProcAddress("glProgramUniform4uiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform1uivEXT = (GLEEPFNGLPROGRAMUNIFORM1UIVEXTPROC) __GLeeGetProcAddress("glProgramUniform1uivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform2uivEXT = (GLEEPFNGLPROGRAMUNIFORM2UIVEXTPROC) __GLeeGetProcAddress("glProgramUniform2uivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform3uivEXT = (GLEEPFNGLPROGRAMUNIFORM3UIVEXTPROC) __GLeeGetProcAddress("glProgramUniform3uivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramUniform4uivEXT = (GLEEPFNGLPROGRAMUNIFORM4UIVEXTPROC) __GLeeGetProcAddress("glProgramUniform4uivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedBufferDataEXT = (GLEEPFNGLNAMEDBUFFERDATAEXTPROC) __GLeeGetProcAddress("glNamedBufferDataEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedBufferSubDataEXT = (GLEEPFNGLNAMEDBUFFERSUBDATAEXTPROC) __GLeeGetProcAddress("glNamedBufferSubDataEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMapNamedBufferEXT = (GLEEPFNGLMAPNAMEDBUFFEREXTPROC) __GLeeGetProcAddress("glMapNamedBufferEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glUnmapNamedBufferEXT = (GLEEPFNGLUNMAPNAMEDBUFFEREXTPROC) __GLeeGetProcAddress("glUnmapNamedBufferEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetNamedBufferParameterivEXT = (GLEEPFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) __GLeeGetProcAddress("glGetNamedBufferParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetNamedBufferPointervEXT = (GLEEPFNGLGETNAMEDBUFFERPOINTERVEXTPROC) __GLeeGetProcAddress("glGetNamedBufferPointervEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetNamedBufferSubDataEXT = (GLEEPFNGLGETNAMEDBUFFERSUBDATAEXTPROC) __GLeeGetProcAddress("glGetNamedBufferSubDataEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTextureBufferEXT = (GLEEPFNGLTEXTUREBUFFEREXTPROC) __GLeeGetProcAddress("glTextureBufferEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexBufferEXT = (GLEEPFNGLMULTITEXBUFFEREXTPROC) __GLeeGetProcAddress("glMultiTexBufferEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedRenderbufferStorageEXT = (GLEEPFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) __GLeeGetProcAddress("glNamedRenderbufferStorageEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetNamedRenderbufferParameterivEXT = (GLEEPFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) __GLeeGetProcAddress("glGetNamedRenderbufferParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glCheckNamedFramebufferStatusEXT = (GLEEPFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) __GLeeGetProcAddress("glCheckNamedFramebufferStatusEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedFramebufferTexture1DEXT = (GLEEPFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) __GLeeGetProcAddress("glNamedFramebufferTexture1DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedFramebufferTexture2DEXT = (GLEEPFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) __GLeeGetProcAddress("glNamedFramebufferTexture2DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedFramebufferTexture3DEXT = (GLEEPFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) __GLeeGetProcAddress("glNamedFramebufferTexture3DEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedFramebufferRenderbufferEXT = (GLEEPFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) __GLeeGetProcAddress("glNamedFramebufferRenderbufferEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetNamedFramebufferAttachmentParameterivEXT = (GLEEPFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) __GLeeGetProcAddress("glGetNamedFramebufferAttachmentParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenerateTextureMipmapEXT = (GLEEPFNGLGENERATETEXTUREMIPMAPEXTPROC) __GLeeGetProcAddress("glGenerateTextureMipmapEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenerateMultiTexMipmapEXT = (GLEEPFNGLGENERATEMULTITEXMIPMAPEXTPROC) __GLeeGetProcAddress("glGenerateMultiTexMipmapEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferDrawBufferEXT = (GLEEPFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) __GLeeGetProcAddress("glFramebufferDrawBufferEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferDrawBuffersEXT = (GLEEPFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) __GLeeGetProcAddress("glFramebufferDrawBuffersEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferReadBufferEXT = (GLEEPFNGLFRAMEBUFFERREADBUFFEREXTPROC) __GLeeGetProcAddress("glFramebufferReadBufferEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFramebufferParameterivEXT = (GLEEPFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) __GLeeGetProcAddress("glGetFramebufferParameterivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedRenderbufferStorageMultisampleEXT = (GLEEPFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) __GLeeGetProcAddress("glNamedRenderbufferStorageMultisampleEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedRenderbufferStorageMultisampleCoverageEXT = (GLEEPFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) __GLeeGetProcAddress("glNamedRenderbufferStorageMultisampleCoverageEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedFramebufferTextureEXT = (GLEEPFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) __GLeeGetProcAddress("glNamedFramebufferTextureEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedFramebufferTextureLayerEXT = (GLEEPFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) __GLeeGetProcAddress("glNamedFramebufferTextureLayerEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glNamedFramebufferTextureFaceEXT = (GLEEPFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) __GLeeGetProcAddress("glNamedFramebufferTextureFaceEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glTextureRenderbufferEXT = (GLEEPFNGLTEXTURERENDERBUFFEREXTPROC) __GLeeGetProcAddress("glTextureRenderbufferEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glMultiTexRenderbufferEXT = (GLEEPFNGLMULTITEXRENDERBUFFEREXTPROC) __GLeeGetProcAddress("glMultiTexRenderbufferEXT"))!=0) nLinked++; +#endif + if (nLinked==186) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_vertex_array_bgra(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_texture_swizzle(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_explicit_multisample(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_explicit_multisample + if ((GLeeFuncPtr_glGetMultisamplefvNV = (GLEEPFNGLGETMULTISAMPLEFVNVPROC) __GLeeGetProcAddress("glGetMultisamplefvNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glSampleMaskIndexedNV = (GLEEPFNGLSAMPLEMASKINDEXEDNVPROC) __GLeeGetProcAddress("glSampleMaskIndexedNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glTexRenderbufferNV = (GLEEPFNGLTEXRENDERBUFFERNVPROC) __GLeeGetProcAddress("glTexRenderbufferNV"))!=0) nLinked++; +#endif + if (nLinked==3) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_NV_transform_feedback2(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_transform_feedback2 + if ((GLeeFuncPtr_glBindTransformFeedbackNV = (GLEEPFNGLBINDTRANSFORMFEEDBACKNVPROC) __GLeeGetProcAddress("glBindTransformFeedbackNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glDeleteTransformFeedbacksNV = (GLEEPFNGLDELETETRANSFORMFEEDBACKSNVPROC) __GLeeGetProcAddress("glDeleteTransformFeedbacksNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGenTransformFeedbacksNV = (GLEEPFNGLGENTRANSFORMFEEDBACKSNVPROC) __GLeeGetProcAddress("glGenTransformFeedbacksNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glIsTransformFeedbackNV = (GLEEPFNGLISTRANSFORMFEEDBACKNVPROC) __GLeeGetProcAddress("glIsTransformFeedbackNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glPauseTransformFeedbackNV = (GLEEPFNGLPAUSETRANSFORMFEEDBACKNVPROC) __GLeeGetProcAddress("glPauseTransformFeedbackNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glResumeTransformFeedbackNV = (GLEEPFNGLRESUMETRANSFORMFEEDBACKNVPROC) __GLeeGetProcAddress("glResumeTransformFeedbackNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glDrawTransformFeedbackNV = (GLEEPFNGLDRAWTRANSFORMFEEDBACKNVPROC) __GLeeGetProcAddress("glDrawTransformFeedbackNV"))!=0) nLinked++; +#endif + if (nLinked==7) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_texture_select(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_INGR_blend_func_separate(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_INGR_blend_func_separate + if ((GLeeFuncPtr_glBlendFuncSeparateINGR = (GLEEPFNGLBLENDFUNCSEPARATEINGRPROC) __GLeeGetProcAddress("glBlendFuncSeparateINGR"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_depth_pass_instrument(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_igloo_interface(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_SGIX_igloo_interface + if ((GLeeFuncPtr_glIglooInterfaceSGIX = (GLEEPFNGLIGLOOINTERFACESGIXPROC) __GLeeGetProcAddress("glIglooInterfaceSGIX"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_fragment_lighting(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_fragment_lighting + if ((GLeeFuncPtr_glFragmentLightModeliEXT = (GLEEPFNGLFRAGMENTLIGHTMODELIEXTPROC) __GLeeGetProcAddress("glFragmentLightModeliEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentLightModelfEXT = (GLEEPFNGLFRAGMENTLIGHTMODELFEXTPROC) __GLeeGetProcAddress("glFragmentLightModelfEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentLightModelivEXT = (GLEEPFNGLFRAGMENTLIGHTMODELIVEXTPROC) __GLeeGetProcAddress("glFragmentLightModelivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentLightModelfvEXT = (GLEEPFNGLFRAGMENTLIGHTMODELFVEXTPROC) __GLeeGetProcAddress("glFragmentLightModelfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentLightiEXT = (GLEEPFNGLFRAGMENTLIGHTIEXTPROC) __GLeeGetProcAddress("glFragmentLightiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentLightfEXT = (GLEEPFNGLFRAGMENTLIGHTFEXTPROC) __GLeeGetProcAddress("glFragmentLightfEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentLightivEXT = (GLEEPFNGLFRAGMENTLIGHTIVEXTPROC) __GLeeGetProcAddress("glFragmentLightivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentLightfvEXT = (GLEEPFNGLFRAGMENTLIGHTFVEXTPROC) __GLeeGetProcAddress("glFragmentLightfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFragmentLightivEXT = (GLEEPFNGLGETFRAGMENTLIGHTIVEXTPROC) __GLeeGetProcAddress("glGetFragmentLightivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFragmentLightfvEXT = (GLEEPFNGLGETFRAGMENTLIGHTFVEXTPROC) __GLeeGetProcAddress("glGetFragmentLightfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentMaterialfEXT = (GLEEPFNGLFRAGMENTMATERIALFEXTPROC) __GLeeGetProcAddress("glFragmentMaterialfEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentMaterialiEXT = (GLEEPFNGLFRAGMENTMATERIALIEXTPROC) __GLeeGetProcAddress("glFragmentMaterialiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentMaterialfvEXT = (GLEEPFNGLFRAGMENTMATERIALFVEXTPROC) __GLeeGetProcAddress("glFragmentMaterialfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentMaterialivEXT = (GLEEPFNGLFRAGMENTMATERIALIVEXTPROC) __GLeeGetProcAddress("glFragmentMaterialivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFragmentColorMaterialEXT = (GLEEPFNGLFRAGMENTCOLORMATERIALEXTPROC) __GLeeGetProcAddress("glFragmentColorMaterialEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFragmentMaterialfvEXT = (GLEEPFNGLGETFRAGMENTMATERIALFVEXTPROC) __GLeeGetProcAddress("glGetFragmentMaterialfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetFragmentMaterialivEXT = (GLEEPFNGLGETFRAGMENTMATERIALIVEXTPROC) __GLeeGetProcAddress("glGetFragmentMaterialivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glLightEnviEXT = (GLEEPFNGLLIGHTENVIEXTPROC) __GLeeGetProcAddress("glLightEnviEXT"))!=0) nLinked++; +#endif + if (nLinked==18) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_geometry_shader4(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_geometry_shader4 + if ((GLeeFuncPtr_glProgramParameteriEXT = (GLEEPFNGLPROGRAMPARAMETERIEXTPROC) __GLeeGetProcAddress("glProgramParameteriEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferTextureEXT = (GLEEPFNGLFRAMEBUFFERTEXTUREEXTPROC) __GLeeGetProcAddress("glFramebufferTextureEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferTextureLayerEXT = (GLEEPFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) __GLeeGetProcAddress("glFramebufferTextureLayerEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferTextureFaceEXT = (GLEEPFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) __GLeeGetProcAddress("glFramebufferTextureFaceEXT"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_scene_marker(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_EXT_scene_marker + if ((GLeeFuncPtr_glBeginSceneEXT = (GLEEPFNGLBEGINSCENEEXTPROC) __GLeeGetProcAddress("glBeginSceneEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glEndSceneEXT = (GLEEPFNGLENDSCENEEXTPROC) __GLeeGetProcAddress("glEndSceneEXT"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_EXT_texture_compression_dxt1(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_EXT_texture_env(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_IBM_static_data(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_NV_gpu_program4(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_NV_gpu_program4 + if ((GLeeFuncPtr_glProgramLocalParameterI4iNV = (GLEEPFNGLPROGRAMLOCALPARAMETERI4INVPROC) __GLeeGetProcAddress("glProgramLocalParameterI4iNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramLocalParameterI4ivNV = (GLEEPFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) __GLeeGetProcAddress("glProgramLocalParameterI4ivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramLocalParametersI4ivNV = (GLEEPFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) __GLeeGetProcAddress("glProgramLocalParametersI4ivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramLocalParameterI4uiNV = (GLEEPFNGLPROGRAMLOCALPARAMETERI4UINVPROC) __GLeeGetProcAddress("glProgramLocalParameterI4uiNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramLocalParameterI4uivNV = (GLEEPFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) __GLeeGetProcAddress("glProgramLocalParameterI4uivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramLocalParametersI4uivNV = (GLEEPFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) __GLeeGetProcAddress("glProgramLocalParametersI4uivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramEnvParameterI4iNV = (GLEEPFNGLPROGRAMENVPARAMETERI4INVPROC) __GLeeGetProcAddress("glProgramEnvParameterI4iNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramEnvParameterI4ivNV = (GLEEPFNGLPROGRAMENVPARAMETERI4IVNVPROC) __GLeeGetProcAddress("glProgramEnvParameterI4ivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramEnvParametersI4ivNV = (GLEEPFNGLPROGRAMENVPARAMETERSI4IVNVPROC) __GLeeGetProcAddress("glProgramEnvParametersI4ivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramEnvParameterI4uiNV = (GLEEPFNGLPROGRAMENVPARAMETERI4UINVPROC) __GLeeGetProcAddress("glProgramEnvParameterI4uiNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramEnvParameterI4uivNV = (GLEEPFNGLPROGRAMENVPARAMETERI4UIVNVPROC) __GLeeGetProcAddress("glProgramEnvParameterI4uivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glProgramEnvParametersI4uivNV = (GLEEPFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) __GLeeGetProcAddress("glProgramEnvParametersI4uivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramLocalParameterIivNV = (GLEEPFNGLGETPROGRAMLOCALPARAMETERIIVNVPROC) __GLeeGetProcAddress("glGetProgramLocalParameterIivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramLocalParameterIuivNV = (GLEEPFNGLGETPROGRAMLOCALPARAMETERIUIVNVPROC) __GLeeGetProcAddress("glGetProgramLocalParameterIuivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramEnvParameterIivNV = (GLEEPFNGLGETPROGRAMENVPARAMETERIIVNVPROC) __GLeeGetProcAddress("glGetProgramEnvParameterIivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetProgramEnvParameterIuivNV = (GLEEPFNGLGETPROGRAMENVPARAMETERIUIVNVPROC) __GLeeGetProcAddress("glGetProgramEnvParameterIuivNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferTextureEXT = (GLEEPFNGLFRAMEBUFFERTEXTUREEXTPROC) __GLeeGetProcAddress("glFramebufferTextureEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferTextureLayerEXT = (GLEEPFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) __GLeeGetProcAddress("glFramebufferTextureLayerEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glFramebufferTextureFaceEXT = (GLEEPFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) __GLeeGetProcAddress("glFramebufferTextureFaceEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI2iEXT = (GLEEPFNGLVERTEXATTRIBI2IEXTPROC) __GLeeGetProcAddress("glVertexAttribI2iEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI3iEXT = (GLEEPFNGLVERTEXATTRIBI3IEXTPROC) __GLeeGetProcAddress("glVertexAttribI3iEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI4iEXT = (GLEEPFNGLVERTEXATTRIBI4IEXTPROC) __GLeeGetProcAddress("glVertexAttribI4iEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI1uiEXT = (GLEEPFNGLVERTEXATTRIBI1UIEXTPROC) __GLeeGetProcAddress("glVertexAttribI1uiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI2uiEXT = (GLEEPFNGLVERTEXATTRIBI2UIEXTPROC) __GLeeGetProcAddress("glVertexAttribI2uiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI3uiEXT = (GLEEPFNGLVERTEXATTRIBI3UIEXTPROC) __GLeeGetProcAddress("glVertexAttribI3uiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI4uiEXT = (GLEEPFNGLVERTEXATTRIBI4UIEXTPROC) __GLeeGetProcAddress("glVertexAttribI4uiEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI1ivEXT = (GLEEPFNGLVERTEXATTRIBI1IVEXTPROC) __GLeeGetProcAddress("glVertexAttribI1ivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI2ivEXT = (GLEEPFNGLVERTEXATTRIBI2IVEXTPROC) __GLeeGetProcAddress("glVertexAttribI2ivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI3ivEXT = (GLEEPFNGLVERTEXATTRIBI3IVEXTPROC) __GLeeGetProcAddress("glVertexAttribI3ivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI4ivEXT = (GLEEPFNGLVERTEXATTRIBI4IVEXTPROC) __GLeeGetProcAddress("glVertexAttribI4ivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI1uivEXT = (GLEEPFNGLVERTEXATTRIBI1UIVEXTPROC) __GLeeGetProcAddress("glVertexAttribI1uivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI2uivEXT = (GLEEPFNGLVERTEXATTRIBI2UIVEXTPROC) __GLeeGetProcAddress("glVertexAttribI2uivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI3uivEXT = (GLEEPFNGLVERTEXATTRIBI3UIVEXTPROC) __GLeeGetProcAddress("glVertexAttribI3uivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI4uivEXT = (GLEEPFNGLVERTEXATTRIBI4UIVEXTPROC) __GLeeGetProcAddress("glVertexAttribI4uivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI4bvEXT = (GLEEPFNGLVERTEXATTRIBI4BVEXTPROC) __GLeeGetProcAddress("glVertexAttribI4bvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI4svEXT = (GLEEPFNGLVERTEXATTRIBI4SVEXTPROC) __GLeeGetProcAddress("glVertexAttribI4svEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI4ubvEXT = (GLEEPFNGLVERTEXATTRIBI4UBVEXTPROC) __GLeeGetProcAddress("glVertexAttribI4ubvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribI4usvEXT = (GLEEPFNGLVERTEXATTRIBI4USVEXTPROC) __GLeeGetProcAddress("glVertexAttribI4usvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glVertexAttribIPointerEXT = (GLEEPFNGLVERTEXATTRIBIPOINTEREXTPROC) __GLeeGetProcAddress("glVertexAttribIPointerEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribIivEXT = (GLEEPFNGLGETVERTEXATTRIBIIVEXTPROC) __GLeeGetProcAddress("glGetVertexAttribIivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetVertexAttribIuivEXT = (GLEEPFNGLGETVERTEXATTRIBIUIVEXTPROC) __GLeeGetProcAddress("glGetVertexAttribIuivEXT"))!=0) nLinked++; +#endif + if (nLinked==41) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_OES_byte_coordinates(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_OES_compressed_paletted_texture(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_OES_single_precision(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GL_OES_single_precision + if ((GLeeFuncPtr_glDepthRangefOES = (GLEEPFNGLDEPTHRANGEFOESPROC) __GLeeGetProcAddress("glDepthRangefOES"))!=0) nLinked++; + if ((GLeeFuncPtr_glFrustumfOES = (GLEEPFNGLFRUSTUMFOESPROC) __GLeeGetProcAddress("glFrustumfOES"))!=0) nLinked++; + if ((GLeeFuncPtr_glOrthofOES = (GLEEPFNGLORTHOFOESPROC) __GLeeGetProcAddress("glOrthofOES"))!=0) nLinked++; + if ((GLeeFuncPtr_glClipPlanefOES = (GLEEPFNGLCLIPPLANEFOESPROC) __GLeeGetProcAddress("glClipPlanefOES"))!=0) nLinked++; + if ((GLeeFuncPtr_glGetClipPlanefOES = (GLEEPFNGLGETCLIPPLANEFOESPROC) __GLeeGetProcAddress("glGetClipPlanefOES"))!=0) nLinked++; + if ((GLeeFuncPtr_glClearDepthfOES = (GLEEPFNGLCLEARDEPTHFOESPROC) __GLeeGetProcAddress("glClearDepthfOES"))!=0) nLinked++; +#endif + if (nLinked==6) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GL_SGIX_pixel_texture_bits(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GL_SGIX_texture_range(void) {return GLEE_LINK_COMPLETE;} + +GLEE_LINK_FUNCTION __GLeeGLLoadFunction[322]; + +void initGLLoadFunctions(void) +{ + __GLeeGLLoadFunction[0]=__GLeeLink_GL_VERSION_1_2; + __GLeeGLLoadFunction[1]=__GLeeLink_GL_ARB_imaging; + __GLeeGLLoadFunction[2]=__GLeeLink_GL_VERSION_1_3; + __GLeeGLLoadFunction[3]=__GLeeLink_GL_VERSION_1_4; + __GLeeGLLoadFunction[4]=__GLeeLink_GL_VERSION_1_5; + __GLeeGLLoadFunction[5]=__GLeeLink_GL_VERSION_2_0; + __GLeeGLLoadFunction[6]=__GLeeLink_GL_VERSION_2_1; + __GLeeGLLoadFunction[7]=__GLeeLink_GL_VERSION_3_0; + __GLeeGLLoadFunction[8]=__GLeeLink_GL_ARB_multitexture; + __GLeeGLLoadFunction[9]=__GLeeLink_GL_ARB_transpose_matrix; + __GLeeGLLoadFunction[10]=__GLeeLink_GL_ARB_multisample; + __GLeeGLLoadFunction[11]=__GLeeLink_GL_ARB_texture_env_add; + __GLeeGLLoadFunction[12]=__GLeeLink_GL_ARB_texture_cube_map; + __GLeeGLLoadFunction[13]=__GLeeLink_GL_ARB_texture_compression; + __GLeeGLLoadFunction[14]=__GLeeLink_GL_ARB_texture_border_clamp; + __GLeeGLLoadFunction[15]=__GLeeLink_GL_ARB_point_parameters; + __GLeeGLLoadFunction[16]=__GLeeLink_GL_ARB_vertex_blend; + __GLeeGLLoadFunction[17]=__GLeeLink_GL_ARB_matrix_palette; + __GLeeGLLoadFunction[18]=__GLeeLink_GL_ARB_texture_env_combine; + __GLeeGLLoadFunction[19]=__GLeeLink_GL_ARB_texture_env_crossbar; + __GLeeGLLoadFunction[20]=__GLeeLink_GL_ARB_texture_env_dot3; + __GLeeGLLoadFunction[21]=__GLeeLink_GL_ARB_texture_mirrored_repeat; + __GLeeGLLoadFunction[22]=__GLeeLink_GL_ARB_depth_texture; + __GLeeGLLoadFunction[23]=__GLeeLink_GL_ARB_shadow; + __GLeeGLLoadFunction[24]=__GLeeLink_GL_ARB_shadow_ambient; + __GLeeGLLoadFunction[25]=__GLeeLink_GL_ARB_window_pos; + __GLeeGLLoadFunction[26]=__GLeeLink_GL_ARB_vertex_program; + __GLeeGLLoadFunction[27]=__GLeeLink_GL_ARB_fragment_program; + __GLeeGLLoadFunction[28]=__GLeeLink_GL_ARB_vertex_buffer_object; + __GLeeGLLoadFunction[29]=__GLeeLink_GL_ARB_occlusion_query; + __GLeeGLLoadFunction[30]=__GLeeLink_GL_ARB_shader_objects; + __GLeeGLLoadFunction[31]=__GLeeLink_GL_ARB_vertex_shader; + __GLeeGLLoadFunction[32]=__GLeeLink_GL_ARB_fragment_shader; + __GLeeGLLoadFunction[33]=__GLeeLink_GL_ARB_shading_language_100; + __GLeeGLLoadFunction[34]=__GLeeLink_GL_ARB_texture_non_power_of_two; + __GLeeGLLoadFunction[35]=__GLeeLink_GL_ARB_point_sprite; + __GLeeGLLoadFunction[36]=__GLeeLink_GL_ARB_fragment_program_shadow; + __GLeeGLLoadFunction[37]=__GLeeLink_GL_ARB_draw_buffers; + __GLeeGLLoadFunction[38]=__GLeeLink_GL_ARB_texture_rectangle; + __GLeeGLLoadFunction[39]=__GLeeLink_GL_ARB_color_buffer_float; + __GLeeGLLoadFunction[40]=__GLeeLink_GL_ARB_half_float_pixel; + __GLeeGLLoadFunction[41]=__GLeeLink_GL_ARB_texture_float; + __GLeeGLLoadFunction[42]=__GLeeLink_GL_ARB_pixel_buffer_object; + __GLeeGLLoadFunction[43]=__GLeeLink_GL_ARB_depth_buffer_float; + __GLeeGLLoadFunction[44]=__GLeeLink_GL_ARB_draw_instanced; + __GLeeGLLoadFunction[45]=__GLeeLink_GL_ARB_framebuffer_object; + __GLeeGLLoadFunction[46]=__GLeeLink_GL_ARB_framebuffer_sRGB; + __GLeeGLLoadFunction[47]=__GLeeLink_GL_ARB_geometry_shader4; + __GLeeGLLoadFunction[48]=__GLeeLink_GL_ARB_half_float_vertex; + __GLeeGLLoadFunction[49]=__GLeeLink_GL_ARB_instanced_arrays; + __GLeeGLLoadFunction[50]=__GLeeLink_GL_ARB_map_buffer_range; + __GLeeGLLoadFunction[51]=__GLeeLink_GL_ARB_texture_buffer_object; + __GLeeGLLoadFunction[52]=__GLeeLink_GL_ARB_texture_compression_rgtc; + __GLeeGLLoadFunction[53]=__GLeeLink_GL_ARB_texture_rg; + __GLeeGLLoadFunction[54]=__GLeeLink_GL_ARB_vertex_array_object; + __GLeeGLLoadFunction[55]=__GLeeLink_GL_EXT_abgr; + __GLeeGLLoadFunction[56]=__GLeeLink_GL_EXT_blend_color; + __GLeeGLLoadFunction[57]=__GLeeLink_GL_EXT_polygon_offset; + __GLeeGLLoadFunction[58]=__GLeeLink_GL_EXT_texture; + __GLeeGLLoadFunction[59]=__GLeeLink_GL_EXT_texture3D; + __GLeeGLLoadFunction[60]=__GLeeLink_GL_SGIS_texture_filter4; + __GLeeGLLoadFunction[61]=__GLeeLink_GL_EXT_subtexture; + __GLeeGLLoadFunction[62]=__GLeeLink_GL_EXT_copy_texture; + __GLeeGLLoadFunction[63]=__GLeeLink_GL_EXT_histogram; + __GLeeGLLoadFunction[64]=__GLeeLink_GL_EXT_convolution; + __GLeeGLLoadFunction[65]=__GLeeLink_GL_SGI_color_matrix; + __GLeeGLLoadFunction[66]=__GLeeLink_GL_SGI_color_table; + __GLeeGLLoadFunction[67]=__GLeeLink_GL_SGIS_pixel_texture; + __GLeeGLLoadFunction[68]=__GLeeLink_GL_SGIX_pixel_texture; + __GLeeGLLoadFunction[69]=__GLeeLink_GL_SGIS_texture4D; + __GLeeGLLoadFunction[70]=__GLeeLink_GL_SGI_texture_color_table; + __GLeeGLLoadFunction[71]=__GLeeLink_GL_EXT_cmyka; + __GLeeGLLoadFunction[72]=__GLeeLink_GL_EXT_texture_object; + __GLeeGLLoadFunction[73]=__GLeeLink_GL_SGIS_detail_texture; + __GLeeGLLoadFunction[74]=__GLeeLink_GL_SGIS_sharpen_texture; + __GLeeGLLoadFunction[75]=__GLeeLink_GL_EXT_packed_pixels; + __GLeeGLLoadFunction[76]=__GLeeLink_GL_SGIS_texture_lod; + __GLeeGLLoadFunction[77]=__GLeeLink_GL_SGIS_multisample; + __GLeeGLLoadFunction[78]=__GLeeLink_GL_EXT_rescale_normal; + __GLeeGLLoadFunction[79]=__GLeeLink_GL_EXT_vertex_array; + __GLeeGLLoadFunction[80]=__GLeeLink_GL_EXT_misc_attribute; + __GLeeGLLoadFunction[81]=__GLeeLink_GL_SGIS_generate_mipmap; + __GLeeGLLoadFunction[82]=__GLeeLink_GL_SGIX_clipmap; + __GLeeGLLoadFunction[83]=__GLeeLink_GL_SGIX_shadow; + __GLeeGLLoadFunction[84]=__GLeeLink_GL_SGIS_texture_edge_clamp; + __GLeeGLLoadFunction[85]=__GLeeLink_GL_SGIS_texture_border_clamp; + __GLeeGLLoadFunction[86]=__GLeeLink_GL_EXT_blend_minmax; + __GLeeGLLoadFunction[87]=__GLeeLink_GL_EXT_blend_subtract; + __GLeeGLLoadFunction[88]=__GLeeLink_GL_EXT_blend_logic_op; + __GLeeGLLoadFunction[89]=__GLeeLink_GL_SGIX_interlace; + __GLeeGLLoadFunction[90]=__GLeeLink_GL_SGIX_pixel_tiles; + __GLeeGLLoadFunction[91]=__GLeeLink_GL_SGIS_texture_select; + __GLeeGLLoadFunction[92]=__GLeeLink_GL_SGIX_sprite; + __GLeeGLLoadFunction[93]=__GLeeLink_GL_SGIX_texture_multi_buffer; + __GLeeGLLoadFunction[94]=__GLeeLink_GL_EXT_point_parameters; + __GLeeGLLoadFunction[95]=__GLeeLink_GL_SGIS_point_parameters; + __GLeeGLLoadFunction[96]=__GLeeLink_GL_SGIX_instruments; + __GLeeGLLoadFunction[97]=__GLeeLink_GL_SGIX_texture_scale_bias; + __GLeeGLLoadFunction[98]=__GLeeLink_GL_SGIX_framezoom; + __GLeeGLLoadFunction[99]=__GLeeLink_GL_SGIX_tag_sample_buffer; + __GLeeGLLoadFunction[100]=__GLeeLink_GL_FfdMaskSGIX; + __GLeeGLLoadFunction[101]=__GLeeLink_GL_SGIX_polynomial_ffd; + __GLeeGLLoadFunction[102]=__GLeeLink_GL_SGIX_reference_plane; + __GLeeGLLoadFunction[103]=__GLeeLink_GL_SGIX_flush_raster; + __GLeeGLLoadFunction[104]=__GLeeLink_GL_SGIX_depth_texture; + __GLeeGLLoadFunction[105]=__GLeeLink_GL_SGIS_fog_function; + __GLeeGLLoadFunction[106]=__GLeeLink_GL_SGIX_fog_offset; + __GLeeGLLoadFunction[107]=__GLeeLink_GL_HP_image_transform; + __GLeeGLLoadFunction[108]=__GLeeLink_GL_HP_convolution_border_modes; + __GLeeGLLoadFunction[109]=__GLeeLink_GL_INGR_palette_buffer; + __GLeeGLLoadFunction[110]=__GLeeLink_GL_SGIX_texture_add_env; + __GLeeGLLoadFunction[111]=__GLeeLink_GL_EXT_color_subtable; + __GLeeGLLoadFunction[112]=__GLeeLink_GL_PGI_vertex_hints; + __GLeeGLLoadFunction[113]=__GLeeLink_GL_PGI_misc_hints; + __GLeeGLLoadFunction[114]=__GLeeLink_GL_EXT_paletted_texture; + __GLeeGLLoadFunction[115]=__GLeeLink_GL_EXT_clip_volume_hint; + __GLeeGLLoadFunction[116]=__GLeeLink_GL_SGIX_list_priority; + __GLeeGLLoadFunction[117]=__GLeeLink_GL_SGIX_ir_instrument1; + __GLeeGLLoadFunction[118]=__GLeeLink_GL_SGIX_calligraphic_fragment; + __GLeeGLLoadFunction[119]=__GLeeLink_GL_SGIX_texture_lod_bias; + __GLeeGLLoadFunction[120]=__GLeeLink_GL_SGIX_shadow_ambient; + __GLeeGLLoadFunction[121]=__GLeeLink_GL_EXT_index_texture; + __GLeeGLLoadFunction[122]=__GLeeLink_GL_EXT_index_material; + __GLeeGLLoadFunction[123]=__GLeeLink_GL_EXT_index_func; + __GLeeGLLoadFunction[124]=__GLeeLink_GL_EXT_index_array_formats; + __GLeeGLLoadFunction[125]=__GLeeLink_GL_EXT_compiled_vertex_array; + __GLeeGLLoadFunction[126]=__GLeeLink_GL_EXT_cull_vertex; + __GLeeGLLoadFunction[127]=__GLeeLink_GL_SGIX_ycrcb; + __GLeeGLLoadFunction[128]=__GLeeLink_GL_SGIX_fragment_lighting; + __GLeeGLLoadFunction[129]=__GLeeLink_GL_IBM_rasterpos_clip; + __GLeeGLLoadFunction[130]=__GLeeLink_GL_HP_texture_lighting; + __GLeeGLLoadFunction[131]=__GLeeLink_GL_EXT_draw_range_elements; + __GLeeGLLoadFunction[132]=__GLeeLink_GL_WIN_phong_shading; + __GLeeGLLoadFunction[133]=__GLeeLink_GL_WIN_specular_fog; + __GLeeGLLoadFunction[134]=__GLeeLink_GL_EXT_light_texture; + __GLeeGLLoadFunction[135]=__GLeeLink_GL_SGIX_blend_alpha_minmax; + __GLeeGLLoadFunction[136]=__GLeeLink_GL_SGIX_impact_pixel_texture; + __GLeeGLLoadFunction[137]=__GLeeLink_GL_EXT_bgra; + __GLeeGLLoadFunction[138]=__GLeeLink_GL_SGIX_async; + __GLeeGLLoadFunction[139]=__GLeeLink_GL_SGIX_async_pixel; + __GLeeGLLoadFunction[140]=__GLeeLink_GL_SGIX_async_histogram; + __GLeeGLLoadFunction[141]=__GLeeLink_GL_INTEL_texture_scissor; + __GLeeGLLoadFunction[142]=__GLeeLink_GL_INTEL_parallel_arrays; + __GLeeGLLoadFunction[143]=__GLeeLink_GL_HP_occlusion_test; + __GLeeGLLoadFunction[144]=__GLeeLink_GL_EXT_pixel_transform; + __GLeeGLLoadFunction[145]=__GLeeLink_GL_EXT_pixel_transform_color_table; + __GLeeGLLoadFunction[146]=__GLeeLink_GL_EXT_shared_texture_palette; + __GLeeGLLoadFunction[147]=__GLeeLink_GL_EXT_separate_specular_color; + __GLeeGLLoadFunction[148]=__GLeeLink_GL_EXT_secondary_color; + __GLeeGLLoadFunction[149]=__GLeeLink_GL_EXT_texture_perturb_normal; + __GLeeGLLoadFunction[150]=__GLeeLink_GL_EXT_multi_draw_arrays; + __GLeeGLLoadFunction[151]=__GLeeLink_GL_EXT_fog_coord; + __GLeeGLLoadFunction[152]=__GLeeLink_GL_REND_screen_coordinates; + __GLeeGLLoadFunction[153]=__GLeeLink_GL_EXT_coordinate_frame; + __GLeeGLLoadFunction[154]=__GLeeLink_GL_EXT_texture_env_combine; + __GLeeGLLoadFunction[155]=__GLeeLink_GL_APPLE_specular_vector; + __GLeeGLLoadFunction[156]=__GLeeLink_GL_APPLE_transform_hint; + __GLeeGLLoadFunction[157]=__GLeeLink_GL_SGIX_fog_scale; + __GLeeGLLoadFunction[158]=__GLeeLink_GL_SUNX_constant_data; + __GLeeGLLoadFunction[159]=__GLeeLink_GL_SUN_global_alpha; + __GLeeGLLoadFunction[160]=__GLeeLink_GL_SUN_triangle_list; + __GLeeGLLoadFunction[161]=__GLeeLink_GL_SUN_vertex; + __GLeeGLLoadFunction[162]=__GLeeLink_GL_EXT_blend_func_separate; + __GLeeGLLoadFunction[163]=__GLeeLink_GL_INGR_color_clamp; + __GLeeGLLoadFunction[164]=__GLeeLink_GL_INGR_interlace_read; + __GLeeGLLoadFunction[165]=__GLeeLink_GL_EXT_stencil_wrap; + __GLeeGLLoadFunction[166]=__GLeeLink_GL_EXT_422_pixels; + __GLeeGLLoadFunction[167]=__GLeeLink_GL_NV_texgen_reflection; + __GLeeGLLoadFunction[168]=__GLeeLink_GL_EXT_texture_cube_map; + __GLeeGLLoadFunction[169]=__GLeeLink_GL_SUN_convolution_border_modes; + __GLeeGLLoadFunction[170]=__GLeeLink_GL_EXT_texture_env_add; + __GLeeGLLoadFunction[171]=__GLeeLink_GL_EXT_texture_lod_bias; + __GLeeGLLoadFunction[172]=__GLeeLink_GL_EXT_texture_filter_anisotropic; + __GLeeGLLoadFunction[173]=__GLeeLink_GL_EXT_vertex_weighting; + __GLeeGLLoadFunction[174]=__GLeeLink_GL_NV_light_max_exponent; + __GLeeGLLoadFunction[175]=__GLeeLink_GL_NV_vertex_array_range; + __GLeeGLLoadFunction[176]=__GLeeLink_GL_NV_register_combiners; + __GLeeGLLoadFunction[177]=__GLeeLink_GL_NV_fog_distance; + __GLeeGLLoadFunction[178]=__GLeeLink_GL_NV_texgen_emboss; + __GLeeGLLoadFunction[179]=__GLeeLink_GL_NV_blend_square; + __GLeeGLLoadFunction[180]=__GLeeLink_GL_NV_texture_env_combine4; + __GLeeGLLoadFunction[181]=__GLeeLink_GL_MESA_resize_buffers; + __GLeeGLLoadFunction[182]=__GLeeLink_GL_MESA_window_pos; + __GLeeGLLoadFunction[183]=__GLeeLink_GL_EXT_texture_compression_s3tc; + __GLeeGLLoadFunction[184]=__GLeeLink_GL_IBM_cull_vertex; + __GLeeGLLoadFunction[185]=__GLeeLink_GL_IBM_multimode_draw_arrays; + __GLeeGLLoadFunction[186]=__GLeeLink_GL_IBM_vertex_array_lists; + __GLeeGLLoadFunction[187]=__GLeeLink_GL_SGIX_subsample; + __GLeeGLLoadFunction[188]=__GLeeLink_GL_SGIX_ycrcb_subsample; + __GLeeGLLoadFunction[189]=__GLeeLink_GL_SGIX_ycrcba; + __GLeeGLLoadFunction[190]=__GLeeLink_GL_SGI_depth_pass_instrument; + __GLeeGLLoadFunction[191]=__GLeeLink_GL_3DFX_texture_compression_FXT1; + __GLeeGLLoadFunction[192]=__GLeeLink_GL_3DFX_multisample; + __GLeeGLLoadFunction[193]=__GLeeLink_GL_3DFX_tbuffer; + __GLeeGLLoadFunction[194]=__GLeeLink_GL_EXT_multisample; + __GLeeGLLoadFunction[195]=__GLeeLink_GL_SGIX_vertex_preclip; + __GLeeGLLoadFunction[196]=__GLeeLink_GL_SGIX_convolution_accuracy; + __GLeeGLLoadFunction[197]=__GLeeLink_GL_SGIX_resample; + __GLeeGLLoadFunction[198]=__GLeeLink_GL_SGIS_point_line_texgen; + __GLeeGLLoadFunction[199]=__GLeeLink_GL_SGIS_texture_color_mask; + __GLeeGLLoadFunction[200]=__GLeeLink_GL_EXT_texture_env_dot3; + __GLeeGLLoadFunction[201]=__GLeeLink_GL_ATI_texture_mirror_once; + __GLeeGLLoadFunction[202]=__GLeeLink_GL_NV_fence; + __GLeeGLLoadFunction[203]=__GLeeLink_GL_IBM_texture_mirrored_repeat; + __GLeeGLLoadFunction[204]=__GLeeLink_GL_NV_evaluators; + __GLeeGLLoadFunction[205]=__GLeeLink_GL_NV_packed_depth_stencil; + __GLeeGLLoadFunction[206]=__GLeeLink_GL_NV_register_combiners2; + __GLeeGLLoadFunction[207]=__GLeeLink_GL_NV_texture_compression_vtc; + __GLeeGLLoadFunction[208]=__GLeeLink_GL_NV_texture_rectangle; + __GLeeGLLoadFunction[209]=__GLeeLink_GL_NV_texture_shader; + __GLeeGLLoadFunction[210]=__GLeeLink_GL_NV_texture_shader2; + __GLeeGLLoadFunction[211]=__GLeeLink_GL_NV_vertex_array_range2; + __GLeeGLLoadFunction[212]=__GLeeLink_GL_NV_vertex_program; + __GLeeGLLoadFunction[213]=__GLeeLink_GL_SGIX_texture_coordinate_clamp; + __GLeeGLLoadFunction[214]=__GLeeLink_GL_SGIX_scalebias_hint; + __GLeeGLLoadFunction[215]=__GLeeLink_GL_OML_interlace; + __GLeeGLLoadFunction[216]=__GLeeLink_GL_OML_subsample; + __GLeeGLLoadFunction[217]=__GLeeLink_GL_OML_resample; + __GLeeGLLoadFunction[218]=__GLeeLink_GL_NV_copy_depth_to_color; + __GLeeGLLoadFunction[219]=__GLeeLink_GL_ATI_envmap_bumpmap; + __GLeeGLLoadFunction[220]=__GLeeLink_GL_ATI_fragment_shader; + __GLeeGLLoadFunction[221]=__GLeeLink_GL_ATI_pn_triangles; + __GLeeGLLoadFunction[222]=__GLeeLink_GL_ATI_vertex_array_object; + __GLeeGLLoadFunction[223]=__GLeeLink_GL_EXT_vertex_shader; + __GLeeGLLoadFunction[224]=__GLeeLink_GL_ATI_vertex_streams; + __GLeeGLLoadFunction[225]=__GLeeLink_GL_ATI_element_array; + __GLeeGLLoadFunction[226]=__GLeeLink_GL_SUN_mesh_array; + __GLeeGLLoadFunction[227]=__GLeeLink_GL_SUN_slice_accum; + __GLeeGLLoadFunction[228]=__GLeeLink_GL_NV_multisample_filter_hint; + __GLeeGLLoadFunction[229]=__GLeeLink_GL_NV_depth_clamp; + __GLeeGLLoadFunction[230]=__GLeeLink_GL_NV_occlusion_query; + __GLeeGLLoadFunction[231]=__GLeeLink_GL_NV_point_sprite; + __GLeeGLLoadFunction[232]=__GLeeLink_GL_NV_texture_shader3; + __GLeeGLLoadFunction[233]=__GLeeLink_GL_NV_vertex_program1_1; + __GLeeGLLoadFunction[234]=__GLeeLink_GL_EXT_shadow_funcs; + __GLeeGLLoadFunction[235]=__GLeeLink_GL_EXT_stencil_two_side; + __GLeeGLLoadFunction[236]=__GLeeLink_GL_ATI_text_fragment_shader; + __GLeeGLLoadFunction[237]=__GLeeLink_GL_APPLE_client_storage; + __GLeeGLLoadFunction[238]=__GLeeLink_GL_APPLE_element_array; + __GLeeGLLoadFunction[239]=__GLeeLink_GL_APPLE_fence; + __GLeeGLLoadFunction[240]=__GLeeLink_GL_APPLE_vertex_array_object; + __GLeeGLLoadFunction[241]=__GLeeLink_GL_APPLE_vertex_array_range; + __GLeeGLLoadFunction[242]=__GLeeLink_GL_APPLE_ycbcr_422; + __GLeeGLLoadFunction[243]=__GLeeLink_GL_S3_s3tc; + __GLeeGLLoadFunction[244]=__GLeeLink_GL_ATI_draw_buffers; + __GLeeGLLoadFunction[245]=__GLeeLink_GL_ATI_pixel_format_float; + __GLeeGLLoadFunction[246]=__GLeeLink_GL_ATI_texture_env_combine3; + __GLeeGLLoadFunction[247]=__GLeeLink_GL_ATI_texture_float; + __GLeeGLLoadFunction[248]=__GLeeLink_GL_NV_float_buffer; + __GLeeGLLoadFunction[249]=__GLeeLink_GL_NV_fragment_program; + __GLeeGLLoadFunction[250]=__GLeeLink_GL_NV_half_float; + __GLeeGLLoadFunction[251]=__GLeeLink_GL_NV_pixel_data_range; + __GLeeGLLoadFunction[252]=__GLeeLink_GL_NV_primitive_restart; + __GLeeGLLoadFunction[253]=__GLeeLink_GL_NV_texture_expand_normal; + __GLeeGLLoadFunction[254]=__GLeeLink_GL_NV_vertex_program2; + __GLeeGLLoadFunction[255]=__GLeeLink_GL_ATI_map_object_buffer; + __GLeeGLLoadFunction[256]=__GLeeLink_GL_ATI_separate_stencil; + __GLeeGLLoadFunction[257]=__GLeeLink_GL_ATI_vertex_attrib_array_object; + __GLeeGLLoadFunction[258]=__GLeeLink_GL_OES_read_format; + __GLeeGLLoadFunction[259]=__GLeeLink_GL_EXT_depth_bounds_test; + __GLeeGLLoadFunction[260]=__GLeeLink_GL_EXT_texture_mirror_clamp; + __GLeeGLLoadFunction[261]=__GLeeLink_GL_EXT_blend_equation_separate; + __GLeeGLLoadFunction[262]=__GLeeLink_GL_MESA_pack_invert; + __GLeeGLLoadFunction[263]=__GLeeLink_GL_MESA_ycbcr_texture; + __GLeeGLLoadFunction[264]=__GLeeLink_GL_EXT_pixel_buffer_object; + __GLeeGLLoadFunction[265]=__GLeeLink_GL_NV_fragment_program_option; + __GLeeGLLoadFunction[266]=__GLeeLink_GL_NV_fragment_program2; + __GLeeGLLoadFunction[267]=__GLeeLink_GL_NV_vertex_program2_option; + __GLeeGLLoadFunction[268]=__GLeeLink_GL_NV_vertex_program3; + __GLeeGLLoadFunction[269]=__GLeeLink_GL_EXT_framebuffer_object; + __GLeeGLLoadFunction[270]=__GLeeLink_GL_GREMEDY_string_marker; + __GLeeGLLoadFunction[271]=__GLeeLink_GL_EXT_packed_depth_stencil; + __GLeeGLLoadFunction[272]=__GLeeLink_GL_EXT_stencil_clear_tag; + __GLeeGLLoadFunction[273]=__GLeeLink_GL_EXT_texture_sRGB; + __GLeeGLLoadFunction[274]=__GLeeLink_GL_EXT_framebuffer_blit; + __GLeeGLLoadFunction[275]=__GLeeLink_GL_EXT_framebuffer_multisample; + __GLeeGLLoadFunction[276]=__GLeeLink_GL_MESAX_texture_stack; + __GLeeGLLoadFunction[277]=__GLeeLink_GL_EXT_timer_query; + __GLeeGLLoadFunction[278]=__GLeeLink_GL_EXT_gpu_program_parameters; + __GLeeGLLoadFunction[279]=__GLeeLink_GL_APPLE_flush_buffer_range; + __GLeeGLLoadFunction[280]=__GLeeLink_GL_EXT_gpu_shader4; + __GLeeGLLoadFunction[281]=__GLeeLink_GL_EXT_draw_instanced; + __GLeeGLLoadFunction[282]=__GLeeLink_GL_EXT_packed_float; + __GLeeGLLoadFunction[283]=__GLeeLink_GL_EXT_texture_array; + __GLeeGLLoadFunction[284]=__GLeeLink_GL_EXT_texture_buffer_object; + __GLeeGLLoadFunction[285]=__GLeeLink_GL_EXT_texture_compression_latc; + __GLeeGLLoadFunction[286]=__GLeeLink_GL_EXT_texture_compression_rgtc; + __GLeeGLLoadFunction[287]=__GLeeLink_GL_EXT_texture_shared_exponent; + __GLeeGLLoadFunction[288]=__GLeeLink_GL_NV_depth_buffer_float; + __GLeeGLLoadFunction[289]=__GLeeLink_GL_NV_framebuffer_multisample_coverage; + __GLeeGLLoadFunction[290]=__GLeeLink_GL_EXT_framebuffer_sRGB; + __GLeeGLLoadFunction[291]=__GLeeLink_GL_NV_geometry_shader4; + __GLeeGLLoadFunction[292]=__GLeeLink_GL_NV_parameter_buffer_object; + __GLeeGLLoadFunction[293]=__GLeeLink_GL_EXT_draw_buffers2; + __GLeeGLLoadFunction[294]=__GLeeLink_GL_NV_transform_feedback; + __GLeeGLLoadFunction[295]=__GLeeLink_GL_EXT_bindable_uniform; + __GLeeGLLoadFunction[296]=__GLeeLink_GL_EXT_texture_integer; + __GLeeGLLoadFunction[297]=__GLeeLink_GL_GREMEDY_frame_terminator; + __GLeeGLLoadFunction[298]=__GLeeLink_GL_NV_conditional_render; + __GLeeGLLoadFunction[299]=__GLeeLink_GL_NV_present_video; + __GLeeGLLoadFunction[300]=__GLeeLink_GL_EXT_transform_feedback; + __GLeeGLLoadFunction[301]=__GLeeLink_GL_EXT_direct_state_access; + __GLeeGLLoadFunction[302]=__GLeeLink_GL_EXT_vertex_array_bgra; + __GLeeGLLoadFunction[303]=__GLeeLink_GL_EXT_texture_swizzle; + __GLeeGLLoadFunction[304]=__GLeeLink_GL_NV_explicit_multisample; + __GLeeGLLoadFunction[305]=__GLeeLink_GL_NV_transform_feedback2; + __GLeeGLLoadFunction[306]=__GLeeLink_GL_SGIX_texture_select; + __GLeeGLLoadFunction[307]=__GLeeLink_GL_INGR_blend_func_separate; + __GLeeGLLoadFunction[308]=__GLeeLink_GL_SGIX_depth_pass_instrument; + __GLeeGLLoadFunction[309]=__GLeeLink_GL_SGIX_igloo_interface; + __GLeeGLLoadFunction[310]=__GLeeLink_GL_EXT_fragment_lighting; + __GLeeGLLoadFunction[311]=__GLeeLink_GL_EXT_geometry_shader4; + __GLeeGLLoadFunction[312]=__GLeeLink_GL_EXT_scene_marker; + __GLeeGLLoadFunction[313]=__GLeeLink_GL_EXT_texture_compression_dxt1; + __GLeeGLLoadFunction[314]=__GLeeLink_GL_EXT_texture_env; + __GLeeGLLoadFunction[315]=__GLeeLink_GL_IBM_static_data; + __GLeeGLLoadFunction[316]=__GLeeLink_GL_NV_gpu_program4; + __GLeeGLLoadFunction[317]=__GLeeLink_GL_OES_byte_coordinates; + __GLeeGLLoadFunction[318]=__GLeeLink_GL_OES_compressed_paletted_texture; + __GLeeGLLoadFunction[319]=__GLeeLink_GL_OES_single_precision; + __GLeeGLLoadFunction[320]=__GLeeLink_GL_SGIX_pixel_texture_bits; + __GLeeGLLoadFunction[321]=__GLeeLink_GL_SGIX_texture_range; +} + +#ifdef WIN32 +GLuint __GLeeLink_WGL_ARB_buffer_region(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_ARB_buffer_region + if ((GLeeFuncPtr_wglCreateBufferRegionARB = (GLEEPFNWGLCREATEBUFFERREGIONARBPROC) __GLeeGetProcAddress("wglCreateBufferRegionARB"))!=0) nLinked++; + if ((GLeeFuncPtr_wglDeleteBufferRegionARB = (GLEEPFNWGLDELETEBUFFERREGIONARBPROC) __GLeeGetProcAddress("wglDeleteBufferRegionARB"))!=0) nLinked++; + if ((GLeeFuncPtr_wglSaveBufferRegionARB = (GLEEPFNWGLSAVEBUFFERREGIONARBPROC) __GLeeGetProcAddress("wglSaveBufferRegionARB"))!=0) nLinked++; + if ((GLeeFuncPtr_wglRestoreBufferRegionARB = (GLEEPFNWGLRESTOREBUFFERREGIONARBPROC) __GLeeGetProcAddress("wglRestoreBufferRegionARB"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_ARB_multisample(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_WGL_ARB_extensions_string(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_ARB_extensions_string + if ((GLeeFuncPtr_wglGetExtensionsStringARB = (GLEEPFNWGLGETEXTENSIONSSTRINGARBPROC) __GLeeGetProcAddress("wglGetExtensionsStringARB"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_ARB_pixel_format(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_ARB_pixel_format + if ((GLeeFuncPtr_wglGetPixelFormatAttribivARB = (GLEEPFNWGLGETPIXELFORMATATTRIBIVARBPROC) __GLeeGetProcAddress("wglGetPixelFormatAttribivARB"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGetPixelFormatAttribfvARB = (GLEEPFNWGLGETPIXELFORMATATTRIBFVARBPROC) __GLeeGetProcAddress("wglGetPixelFormatAttribfvARB"))!=0) nLinked++; + if ((GLeeFuncPtr_wglChoosePixelFormatARB = (GLEEPFNWGLCHOOSEPIXELFORMATARBPROC) __GLeeGetProcAddress("wglChoosePixelFormatARB"))!=0) nLinked++; +#endif + if (nLinked==3) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_ARB_make_current_read(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_ARB_make_current_read + if ((GLeeFuncPtr_wglMakeContextCurrentARB = (GLEEPFNWGLMAKECONTEXTCURRENTARBPROC) __GLeeGetProcAddress("wglMakeContextCurrentARB"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGetCurrentReadDCARB = (GLEEPFNWGLGETCURRENTREADDCARBPROC) __GLeeGetProcAddress("wglGetCurrentReadDCARB"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_ARB_pbuffer(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_ARB_pbuffer + if ((GLeeFuncPtr_wglCreatePbufferARB = (GLEEPFNWGLCREATEPBUFFERARBPROC) __GLeeGetProcAddress("wglCreatePbufferARB"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGetPbufferDCARB = (GLEEPFNWGLGETPBUFFERDCARBPROC) __GLeeGetProcAddress("wglGetPbufferDCARB"))!=0) nLinked++; + if ((GLeeFuncPtr_wglReleasePbufferDCARB = (GLEEPFNWGLRELEASEPBUFFERDCARBPROC) __GLeeGetProcAddress("wglReleasePbufferDCARB"))!=0) nLinked++; + if ((GLeeFuncPtr_wglDestroyPbufferARB = (GLEEPFNWGLDESTROYPBUFFERARBPROC) __GLeeGetProcAddress("wglDestroyPbufferARB"))!=0) nLinked++; + if ((GLeeFuncPtr_wglQueryPbufferARB = (GLEEPFNWGLQUERYPBUFFERARBPROC) __GLeeGetProcAddress("wglQueryPbufferARB"))!=0) nLinked++; +#endif + if (nLinked==5) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_ARB_render_texture(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_ARB_render_texture + if ((GLeeFuncPtr_wglBindTexImageARB = (GLEEPFNWGLBINDTEXIMAGEARBPROC) __GLeeGetProcAddress("wglBindTexImageARB"))!=0) nLinked++; + if ((GLeeFuncPtr_wglReleaseTexImageARB = (GLEEPFNWGLRELEASETEXIMAGEARBPROC) __GLeeGetProcAddress("wglReleaseTexImageARB"))!=0) nLinked++; + if ((GLeeFuncPtr_wglSetPbufferAttribARB = (GLEEPFNWGLSETPBUFFERATTRIBARBPROC) __GLeeGetProcAddress("wglSetPbufferAttribARB"))!=0) nLinked++; +#endif + if (nLinked==3) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_ARB_pixel_format_float(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_WGL_ARB_create_context(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_ARB_create_context + if ((GLeeFuncPtr_wglCreateContextAttribsARB = (GLEEPFNWGLCREATECONTEXTATTRIBSARBPROC) __GLeeGetProcAddress("wglCreateContextAttribsARB"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_EXT_make_current_read(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_EXT_make_current_read + if ((GLeeFuncPtr_wglMakeContextCurrentEXT = (GLEEPFNWGLMAKECONTEXTCURRENTEXTPROC) __GLeeGetProcAddress("wglMakeContextCurrentEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGetCurrentReadDCEXT = (GLEEPFNWGLGETCURRENTREADDCEXTPROC) __GLeeGetProcAddress("wglGetCurrentReadDCEXT"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_EXT_pixel_format(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_EXT_pixel_format + if ((GLeeFuncPtr_wglGetPixelFormatAttribivEXT = (GLEEPFNWGLGETPIXELFORMATATTRIBIVEXTPROC) __GLeeGetProcAddress("wglGetPixelFormatAttribivEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGetPixelFormatAttribfvEXT = (GLEEPFNWGLGETPIXELFORMATATTRIBFVEXTPROC) __GLeeGetProcAddress("wglGetPixelFormatAttribfvEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_wglChoosePixelFormatEXT = (GLEEPFNWGLCHOOSEPIXELFORMATEXTPROC) __GLeeGetProcAddress("wglChoosePixelFormatEXT"))!=0) nLinked++; +#endif + if (nLinked==3) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_EXT_pbuffer(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_EXT_pbuffer + if ((GLeeFuncPtr_wglCreatePbufferEXT = (GLEEPFNWGLCREATEPBUFFEREXTPROC) __GLeeGetProcAddress("wglCreatePbufferEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGetPbufferDCEXT = (GLEEPFNWGLGETPBUFFERDCEXTPROC) __GLeeGetProcAddress("wglGetPbufferDCEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_wglReleasePbufferDCEXT = (GLEEPFNWGLRELEASEPBUFFERDCEXTPROC) __GLeeGetProcAddress("wglReleasePbufferDCEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_wglDestroyPbufferEXT = (GLEEPFNWGLDESTROYPBUFFEREXTPROC) __GLeeGetProcAddress("wglDestroyPbufferEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_wglQueryPbufferEXT = (GLEEPFNWGLQUERYPBUFFEREXTPROC) __GLeeGetProcAddress("wglQueryPbufferEXT"))!=0) nLinked++; +#endif + if (nLinked==5) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_EXT_depth_float(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_WGL_3DFX_multisample(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_WGL_EXT_multisample(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_WGL_I3D_digital_video_control(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_I3D_digital_video_control + if ((GLeeFuncPtr_wglGetDigitalVideoParametersI3D = (GLEEPFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) __GLeeGetProcAddress("wglGetDigitalVideoParametersI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglSetDigitalVideoParametersI3D = (GLEEPFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) __GLeeGetProcAddress("wglSetDigitalVideoParametersI3D"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_I3D_gamma(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_I3D_gamma + if ((GLeeFuncPtr_wglGetGammaTableParametersI3D = (GLEEPFNWGLGETGAMMATABLEPARAMETERSI3DPROC) __GLeeGetProcAddress("wglGetGammaTableParametersI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglSetGammaTableParametersI3D = (GLEEPFNWGLSETGAMMATABLEPARAMETERSI3DPROC) __GLeeGetProcAddress("wglSetGammaTableParametersI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGetGammaTableI3D = (GLEEPFNWGLGETGAMMATABLEI3DPROC) __GLeeGetProcAddress("wglGetGammaTableI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglSetGammaTableI3D = (GLEEPFNWGLSETGAMMATABLEI3DPROC) __GLeeGetProcAddress("wglSetGammaTableI3D"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_I3D_genlock(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_I3D_genlock + if ((GLeeFuncPtr_wglEnableGenlockI3D = (GLEEPFNWGLENABLEGENLOCKI3DPROC) __GLeeGetProcAddress("wglEnableGenlockI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglDisableGenlockI3D = (GLEEPFNWGLDISABLEGENLOCKI3DPROC) __GLeeGetProcAddress("wglDisableGenlockI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglIsEnabledGenlockI3D = (GLEEPFNWGLISENABLEDGENLOCKI3DPROC) __GLeeGetProcAddress("wglIsEnabledGenlockI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGenlockSourceI3D = (GLEEPFNWGLGENLOCKSOURCEI3DPROC) __GLeeGetProcAddress("wglGenlockSourceI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGetGenlockSourceI3D = (GLEEPFNWGLGETGENLOCKSOURCEI3DPROC) __GLeeGetProcAddress("wglGetGenlockSourceI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGenlockSourceEdgeI3D = (GLEEPFNWGLGENLOCKSOURCEEDGEI3DPROC) __GLeeGetProcAddress("wglGenlockSourceEdgeI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGetGenlockSourceEdgeI3D = (GLEEPFNWGLGETGENLOCKSOURCEEDGEI3DPROC) __GLeeGetProcAddress("wglGetGenlockSourceEdgeI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGenlockSampleRateI3D = (GLEEPFNWGLGENLOCKSAMPLERATEI3DPROC) __GLeeGetProcAddress("wglGenlockSampleRateI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGetGenlockSampleRateI3D = (GLEEPFNWGLGETGENLOCKSAMPLERATEI3DPROC) __GLeeGetProcAddress("wglGetGenlockSampleRateI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGenlockSourceDelayI3D = (GLEEPFNWGLGENLOCKSOURCEDELAYI3DPROC) __GLeeGetProcAddress("wglGenlockSourceDelayI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGetGenlockSourceDelayI3D = (GLEEPFNWGLGETGENLOCKSOURCEDELAYI3DPROC) __GLeeGetProcAddress("wglGetGenlockSourceDelayI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglQueryGenlockMaxSourceDelayI3D = (GLEEPFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) __GLeeGetProcAddress("wglQueryGenlockMaxSourceDelayI3D"))!=0) nLinked++; +#endif + if (nLinked==12) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_I3D_image_buffer(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_I3D_image_buffer + if ((GLeeFuncPtr_wglCreateImageBufferI3D = (GLEEPFNWGLCREATEIMAGEBUFFERI3DPROC) __GLeeGetProcAddress("wglCreateImageBufferI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglDestroyImageBufferI3D = (GLEEPFNWGLDESTROYIMAGEBUFFERI3DPROC) __GLeeGetProcAddress("wglDestroyImageBufferI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglAssociateImageBufferEventsI3D = (GLEEPFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) __GLeeGetProcAddress("wglAssociateImageBufferEventsI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglReleaseImageBufferEventsI3D = (GLEEPFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) __GLeeGetProcAddress("wglReleaseImageBufferEventsI3D"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_I3D_swap_frame_lock(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_I3D_swap_frame_lock + if ((GLeeFuncPtr_wglEnableFrameLockI3D = (GLEEPFNWGLENABLEFRAMELOCKI3DPROC) __GLeeGetProcAddress("wglEnableFrameLockI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglDisableFrameLockI3D = (GLEEPFNWGLDISABLEFRAMELOCKI3DPROC) __GLeeGetProcAddress("wglDisableFrameLockI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglIsEnabledFrameLockI3D = (GLEEPFNWGLISENABLEDFRAMELOCKI3DPROC) __GLeeGetProcAddress("wglIsEnabledFrameLockI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglQueryFrameLockMasterI3D = (GLEEPFNWGLQUERYFRAMELOCKMASTERI3DPROC) __GLeeGetProcAddress("wglQueryFrameLockMasterI3D"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_NV_render_depth_texture(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_WGL_NV_render_texture_rectangle(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_WGL_ATI_pixel_format_float(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_WGL_NV_float_buffer(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_WGL_3DL_stereo_control(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_WGL_EXT_pixel_format_packed_float(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_WGL_EXT_framebuffer_sRGB(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_WGL_NV_present_video(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_NV_present_video + if ((GLeeFuncPtr_wglEnumerateVideoDevicesNV = (GLEEPFNWGLENUMERATEVIDEODEVICESNVPROC) __GLeeGetProcAddress("wglEnumerateVideoDevicesNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglBindVideoDeviceNV = (GLEEPFNWGLBINDVIDEODEVICENVPROC) __GLeeGetProcAddress("wglBindVideoDeviceNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglQueryCurrentContextNV = (GLEEPFNWGLQUERYCURRENTCONTEXTNVPROC) __GLeeGetProcAddress("wglQueryCurrentContextNV"))!=0) nLinked++; +#endif + if (nLinked==3) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_NV_swap_group(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_NV_swap_group + if ((GLeeFuncPtr_wglJoinSwapGroupNV = (GLEEPFNWGLJOINSWAPGROUPNVPROC) __GLeeGetProcAddress("wglJoinSwapGroupNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglBindSwapBarrierNV = (GLEEPFNWGLBINDSWAPBARRIERNVPROC) __GLeeGetProcAddress("wglBindSwapBarrierNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglQuerySwapGroupNV = (GLEEPFNWGLQUERYSWAPGROUPNVPROC) __GLeeGetProcAddress("wglQuerySwapGroupNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglQueryMaxSwapGroupsNV = (GLEEPFNWGLQUERYMAXSWAPGROUPSNVPROC) __GLeeGetProcAddress("wglQueryMaxSwapGroupsNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglQueryFrameCountNV = (GLEEPFNWGLQUERYFRAMECOUNTNVPROC) __GLeeGetProcAddress("wglQueryFrameCountNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglResetFrameCountNV = (GLEEPFNWGLRESETFRAMECOUNTNVPROC) __GLeeGetProcAddress("wglResetFrameCountNV"))!=0) nLinked++; +#endif + if (nLinked==6) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_NV_gpu_affinity(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_NV_gpu_affinity + if ((GLeeFuncPtr_wglEnumGpusNV = (GLEEPFNWGLENUMGPUSNVPROC) __GLeeGetProcAddress("wglEnumGpusNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglEnumGpuDevicesNV = (GLEEPFNWGLENUMGPUDEVICESNVPROC) __GLeeGetProcAddress("wglEnumGpuDevicesNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglCreateAffinityDCNV = (GLEEPFNWGLCREATEAFFINITYDCNVPROC) __GLeeGetProcAddress("wglCreateAffinityDCNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglEnumGpusFromAffinityDCNV = (GLEEPFNWGLENUMGPUSFROMAFFINITYDCNVPROC) __GLeeGetProcAddress("wglEnumGpusFromAffinityDCNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglDeleteDCNV = (GLEEPFNWGLDELETEDCNVPROC) __GLeeGetProcAddress("wglDeleteDCNV"))!=0) nLinked++; +#endif + if (nLinked==5) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_EXT_display_color_table(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_EXT_display_color_table + if ((GLeeFuncPtr_wglCreateDisplayColorTableEXT = (GLEEPFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) __GLeeGetProcAddress("wglCreateDisplayColorTableEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_wglLoadDisplayColorTableEXT = (GLEEPFNWGLLOADDISPLAYCOLORTABLEEXTPROC) __GLeeGetProcAddress("wglLoadDisplayColorTableEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_wglBindDisplayColorTableEXT = (GLEEPFNWGLBINDDISPLAYCOLORTABLEEXTPROC) __GLeeGetProcAddress("wglBindDisplayColorTableEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_wglDestroyDisplayColorTableEXT = (GLEEPFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) __GLeeGetProcAddress("wglDestroyDisplayColorTableEXT"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_EXT_extensions_string(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_EXT_extensions_string + if ((GLeeFuncPtr_wglGetExtensionsStringEXT = (GLEEPFNWGLGETEXTENSIONSSTRINGEXTPROC) __GLeeGetProcAddress("wglGetExtensionsStringEXT"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_EXT_swap_control(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_EXT_swap_control + if ((GLeeFuncPtr_wglSwapIntervalEXT = (GLEEPFNWGLSWAPINTERVALEXTPROC) __GLeeGetProcAddress("wglSwapIntervalEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGetSwapIntervalEXT = (GLEEPFNWGLGETSWAPINTERVALEXTPROC) __GLeeGetProcAddress("wglGetSwapIntervalEXT"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_NV_vertex_array_range(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_NV_vertex_array_range + if ((GLeeFuncPtr_wglAllocateMemoryNV = (GLEEPFNWGLALLOCATEMEMORYNVPROC) __GLeeGetProcAddress("wglAllocateMemoryNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglFreeMemoryNV = (GLEEPFNWGLFREEMEMORYNVPROC) __GLeeGetProcAddress("wglFreeMemoryNV"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_OML_sync_control(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_OML_sync_control + if ((GLeeFuncPtr_wglGetSyncValuesOML = (GLEEPFNWGLGETSYNCVALUESOMLPROC) __GLeeGetProcAddress("wglGetSyncValuesOML"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGetMscRateOML = (GLEEPFNWGLGETMSCRATEOMLPROC) __GLeeGetProcAddress("wglGetMscRateOML"))!=0) nLinked++; + if ((GLeeFuncPtr_wglSwapBuffersMscOML = (GLEEPFNWGLSWAPBUFFERSMSCOMLPROC) __GLeeGetProcAddress("wglSwapBuffersMscOML"))!=0) nLinked++; + if ((GLeeFuncPtr_wglSwapLayerBuffersMscOML = (GLEEPFNWGLSWAPLAYERBUFFERSMSCOMLPROC) __GLeeGetProcAddress("wglSwapLayerBuffersMscOML"))!=0) nLinked++; + if ((GLeeFuncPtr_wglWaitForMscOML = (GLEEPFNWGLWAITFORMSCOMLPROC) __GLeeGetProcAddress("wglWaitForMscOML"))!=0) nLinked++; + if ((GLeeFuncPtr_wglWaitForSbcOML = (GLEEPFNWGLWAITFORSBCOMLPROC) __GLeeGetProcAddress("wglWaitForSbcOML"))!=0) nLinked++; +#endif + if (nLinked==6) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_I3D_swap_frame_usage(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_I3D_swap_frame_usage + if ((GLeeFuncPtr_wglGetFrameUsageI3D = (GLEEPFNWGLGETFRAMEUSAGEI3DPROC) __GLeeGetProcAddress("wglGetFrameUsageI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglBeginFrameTrackingI3D = (GLEEPFNWGLBEGINFRAMETRACKINGI3DPROC) __GLeeGetProcAddress("wglBeginFrameTrackingI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglEndFrameTrackingI3D = (GLEEPFNWGLENDFRAMETRACKINGI3DPROC) __GLeeGetProcAddress("wglEndFrameTrackingI3D"))!=0) nLinked++; + if ((GLeeFuncPtr_wglQueryFrameTrackingI3D = (GLEEPFNWGLQUERYFRAMETRACKINGI3DPROC) __GLeeGetProcAddress("wglQueryFrameTrackingI3D"))!=0) nLinked++; +#endif + if (nLinked==4) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_WGL_NV_video_output(void) +{ + GLint nLinked=0; +#ifdef __GLEE_WGL_NV_video_output + if ((GLeeFuncPtr_wglGetVideoDeviceNV = (GLEEPFNWGLGETVIDEODEVICENVPROC) __GLeeGetProcAddress("wglGetVideoDeviceNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglReleaseVideoDeviceNV = (GLEEPFNWGLRELEASEVIDEODEVICENVPROC) __GLeeGetProcAddress("wglReleaseVideoDeviceNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglBindVideoImageNV = (GLEEPFNWGLBINDVIDEOIMAGENVPROC) __GLeeGetProcAddress("wglBindVideoImageNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglReleaseVideoImageNV = (GLEEPFNWGLRELEASEVIDEOIMAGENVPROC) __GLeeGetProcAddress("wglReleaseVideoImageNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglSendPbufferToVideoNV = (GLEEPFNWGLSENDPBUFFERTOVIDEONVPROC) __GLeeGetProcAddress("wglSendPbufferToVideoNV"))!=0) nLinked++; + if ((GLeeFuncPtr_wglGetVideoInfoNV = (GLEEPFNWGLGETVIDEOINFONVPROC) __GLeeGetProcAddress("wglGetVideoInfoNV"))!=0) nLinked++; +#endif + if (nLinked==6) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLEE_LINK_FUNCTION __GLeeWGLLoadFunction[37]; + +void initWGLLoadFunctions(void) +{ + __GLeeWGLLoadFunction[0]=__GLeeLink_WGL_ARB_buffer_region; + __GLeeWGLLoadFunction[1]=__GLeeLink_WGL_ARB_multisample; + __GLeeWGLLoadFunction[2]=__GLeeLink_WGL_ARB_extensions_string; + __GLeeWGLLoadFunction[3]=__GLeeLink_WGL_ARB_pixel_format; + __GLeeWGLLoadFunction[4]=__GLeeLink_WGL_ARB_make_current_read; + __GLeeWGLLoadFunction[5]=__GLeeLink_WGL_ARB_pbuffer; + __GLeeWGLLoadFunction[6]=__GLeeLink_WGL_ARB_render_texture; + __GLeeWGLLoadFunction[7]=__GLeeLink_WGL_ARB_pixel_format_float; + __GLeeWGLLoadFunction[8]=__GLeeLink_WGL_ARB_create_context; + __GLeeWGLLoadFunction[9]=__GLeeLink_WGL_EXT_make_current_read; + __GLeeWGLLoadFunction[10]=__GLeeLink_WGL_EXT_pixel_format; + __GLeeWGLLoadFunction[11]=__GLeeLink_WGL_EXT_pbuffer; + __GLeeWGLLoadFunction[12]=__GLeeLink_WGL_EXT_depth_float; + __GLeeWGLLoadFunction[13]=__GLeeLink_WGL_3DFX_multisample; + __GLeeWGLLoadFunction[14]=__GLeeLink_WGL_EXT_multisample; + __GLeeWGLLoadFunction[15]=__GLeeLink_WGL_I3D_digital_video_control; + __GLeeWGLLoadFunction[16]=__GLeeLink_WGL_I3D_gamma; + __GLeeWGLLoadFunction[17]=__GLeeLink_WGL_I3D_genlock; + __GLeeWGLLoadFunction[18]=__GLeeLink_WGL_I3D_image_buffer; + __GLeeWGLLoadFunction[19]=__GLeeLink_WGL_I3D_swap_frame_lock; + __GLeeWGLLoadFunction[20]=__GLeeLink_WGL_NV_render_depth_texture; + __GLeeWGLLoadFunction[21]=__GLeeLink_WGL_NV_render_texture_rectangle; + __GLeeWGLLoadFunction[22]=__GLeeLink_WGL_ATI_pixel_format_float; + __GLeeWGLLoadFunction[23]=__GLeeLink_WGL_NV_float_buffer; + __GLeeWGLLoadFunction[24]=__GLeeLink_WGL_3DL_stereo_control; + __GLeeWGLLoadFunction[25]=__GLeeLink_WGL_EXT_pixel_format_packed_float; + __GLeeWGLLoadFunction[26]=__GLeeLink_WGL_EXT_framebuffer_sRGB; + __GLeeWGLLoadFunction[27]=__GLeeLink_WGL_NV_present_video; + __GLeeWGLLoadFunction[28]=__GLeeLink_WGL_NV_swap_group; + __GLeeWGLLoadFunction[29]=__GLeeLink_WGL_NV_gpu_affinity; + __GLeeWGLLoadFunction[30]=__GLeeLink_WGL_EXT_display_color_table; + __GLeeWGLLoadFunction[31]=__GLeeLink_WGL_EXT_extensions_string; + __GLeeWGLLoadFunction[32]=__GLeeLink_WGL_EXT_swap_control; + __GLeeWGLLoadFunction[33]=__GLeeLink_WGL_NV_vertex_array_range; + __GLeeWGLLoadFunction[34]=__GLeeLink_WGL_OML_sync_control; + __GLeeWGLLoadFunction[35]=__GLeeLink_WGL_I3D_swap_frame_usage; + __GLeeWGLLoadFunction[36]=__GLeeLink_WGL_NV_video_output; +} + +#elif defined(__APPLE__) || defined(__APPLE_CC__) +#else /* Linux */ +GLuint __GLeeLink_GLX_VERSION_1_3(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_VERSION_1_3 + if ((GLeeFuncPtr_glXGetFBConfigs = (GLEEPFNGLXGETFBCONFIGSPROC) __GLeeGetProcAddress("glXGetFBConfigs"))!=0) nLinked++; + if ((GLeeFuncPtr_glXChooseFBConfig = (GLEEPFNGLXCHOOSEFBCONFIGPROC) __GLeeGetProcAddress("glXChooseFBConfig"))!=0) nLinked++; + if ((GLeeFuncPtr_glXGetFBConfigAttrib = (GLEEPFNGLXGETFBCONFIGATTRIBPROC) __GLeeGetProcAddress("glXGetFBConfigAttrib"))!=0) nLinked++; + if ((GLeeFuncPtr_glXGetVisualFromFBConfig = (GLEEPFNGLXGETVISUALFROMFBCONFIGPROC) __GLeeGetProcAddress("glXGetVisualFromFBConfig"))!=0) nLinked++; + if ((GLeeFuncPtr_glXCreateWindow = (GLEEPFNGLXCREATEWINDOWPROC) __GLeeGetProcAddress("glXCreateWindow"))!=0) nLinked++; + if ((GLeeFuncPtr_glXDestroyWindow = (GLEEPFNGLXDESTROYWINDOWPROC) __GLeeGetProcAddress("glXDestroyWindow"))!=0) nLinked++; + if ((GLeeFuncPtr_glXCreatePixmap = (GLEEPFNGLXCREATEPIXMAPPROC) __GLeeGetProcAddress("glXCreatePixmap"))!=0) nLinked++; + if ((GLeeFuncPtr_glXDestroyPixmap = (GLEEPFNGLXDESTROYPIXMAPPROC) __GLeeGetProcAddress("glXDestroyPixmap"))!=0) nLinked++; + if ((GLeeFuncPtr_glXCreatePbuffer = (GLEEPFNGLXCREATEPBUFFERPROC) __GLeeGetProcAddress("glXCreatePbuffer"))!=0) nLinked++; + if ((GLeeFuncPtr_glXDestroyPbuffer = (GLEEPFNGLXDESTROYPBUFFERPROC) __GLeeGetProcAddress("glXDestroyPbuffer"))!=0) nLinked++; + if ((GLeeFuncPtr_glXQueryDrawable = (GLEEPFNGLXQUERYDRAWABLEPROC) __GLeeGetProcAddress("glXQueryDrawable"))!=0) nLinked++; + if ((GLeeFuncPtr_glXCreateNewContext = (GLEEPFNGLXCREATENEWCONTEXTPROC) __GLeeGetProcAddress("glXCreateNewContext"))!=0) nLinked++; + if ((GLeeFuncPtr_glXMakeContextCurrent = (GLEEPFNGLXMAKECONTEXTCURRENTPROC) __GLeeGetProcAddress("glXMakeContextCurrent"))!=0) nLinked++; + if ((GLeeFuncPtr_glXGetCurrentReadDrawable = (GLEEPFNGLXGETCURRENTREADDRAWABLEPROC) __GLeeGetProcAddress("glXGetCurrentReadDrawable"))!=0) nLinked++; + if ((GLeeFuncPtr_glXGetCurrentDisplay = (GLEEPFNGLXGETCURRENTDISPLAYPROC) __GLeeGetProcAddress("glXGetCurrentDisplay"))!=0) nLinked++; + if ((GLeeFuncPtr_glXQueryContext = (GLEEPFNGLXQUERYCONTEXTPROC) __GLeeGetProcAddress("glXQueryContext"))!=0) nLinked++; + if ((GLeeFuncPtr_glXSelectEvent = (GLEEPFNGLXSELECTEVENTPROC) __GLeeGetProcAddress("glXSelectEvent"))!=0) nLinked++; + if ((GLeeFuncPtr_glXGetSelectedEvent = (GLEEPFNGLXGETSELECTEDEVENTPROC) __GLeeGetProcAddress("glXGetSelectedEvent"))!=0) nLinked++; +#endif + if (nLinked==18) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_VERSION_1_4(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_VERSION_1_4 + if ((GLeeFuncPtr_glXGetProcAddress = (GLEEPFNGLXGETPROCADDRESSPROC) __GLeeGetProcAddress("glXGetProcAddress"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_ARB_multisample(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_ARB_fbconfig_float(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_ARB_create_context(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_ARB_create_context + if ((GLeeFuncPtr_glXCreateContextAttribsARB = (GLEEPFNGLXCREATECONTEXTATTRIBSARBPROC) __GLeeGetProcAddress("glXCreateContextAttribsARB"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_SGIS_multisample(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_EXT_visual_info(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_SGI_swap_control(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_SGI_swap_control + if ((GLeeFuncPtr_glXSwapIntervalSGI = (GLEEPFNGLXSWAPINTERVALSGIPROC) __GLeeGetProcAddress("glXSwapIntervalSGI"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_SGI_video_sync(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_SGI_video_sync + if ((GLeeFuncPtr_glXGetVideoSyncSGI = (GLEEPFNGLXGETVIDEOSYNCSGIPROC) __GLeeGetProcAddress("glXGetVideoSyncSGI"))!=0) nLinked++; + if ((GLeeFuncPtr_glXWaitVideoSyncSGI = (GLEEPFNGLXWAITVIDEOSYNCSGIPROC) __GLeeGetProcAddress("glXWaitVideoSyncSGI"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_SGI_make_current_read(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_SGI_make_current_read + if ((GLeeFuncPtr_glXMakeCurrentReadSGI = (GLEEPFNGLXMAKECURRENTREADSGIPROC) __GLeeGetProcAddress("glXMakeCurrentReadSGI"))!=0) nLinked++; + if ((GLeeFuncPtr_glXGetCurrentReadDrawableSGI = (GLEEPFNGLXGETCURRENTREADDRAWABLESGIPROC) __GLeeGetProcAddress("glXGetCurrentReadDrawableSGI"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_EXT_visual_rating(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_EXT_import_context(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_EXT_import_context + if ((GLeeFuncPtr_glXGetCurrentDisplayEXT = (GLEEPFNGLXGETCURRENTDISPLAYEXTPROC) __GLeeGetProcAddress("glXGetCurrentDisplayEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glXQueryContextInfoEXT = (GLEEPFNGLXQUERYCONTEXTINFOEXTPROC) __GLeeGetProcAddress("glXQueryContextInfoEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glXGetContextIDEXT = (GLEEPFNGLXGETCONTEXTIDEXTPROC) __GLeeGetProcAddress("glXGetContextIDEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glXImportContextEXT = (GLEEPFNGLXIMPORTCONTEXTEXTPROC) __GLeeGetProcAddress("glXImportContextEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glXFreeContextEXT = (GLEEPFNGLXFREECONTEXTEXTPROC) __GLeeGetProcAddress("glXFreeContextEXT"))!=0) nLinked++; +#endif + if (nLinked==5) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_SGIX_fbconfig(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_SGIX_fbconfig + if ((GLeeFuncPtr_glXGetFBConfigAttribSGIX = (GLEEPFNGLXGETFBCONFIGATTRIBSGIXPROC) __GLeeGetProcAddress("glXGetFBConfigAttribSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXChooseFBConfigSGIX = (GLEEPFNGLXCHOOSEFBCONFIGSGIXPROC) __GLeeGetProcAddress("glXChooseFBConfigSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXCreateGLXPixmapWithConfigSGIX = (GLEEPFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) __GLeeGetProcAddress("glXCreateGLXPixmapWithConfigSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXCreateContextWithConfigSGIX = (GLEEPFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) __GLeeGetProcAddress("glXCreateContextWithConfigSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXGetVisualFromFBConfigSGIX = (GLEEPFNGLXGETVISUALFROMFBCONFIGSGIXPROC) __GLeeGetProcAddress("glXGetVisualFromFBConfigSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXGetFBConfigFromVisualSGIX = (GLEEPFNGLXGETFBCONFIGFROMVISUALSGIXPROC) __GLeeGetProcAddress("glXGetFBConfigFromVisualSGIX"))!=0) nLinked++; +#endif + if (nLinked==6) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_SGIX_pbuffer(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_SGIX_pbuffer + if ((GLeeFuncPtr_glXCreateGLXPbufferSGIX = (GLEEPFNGLXCREATEGLXPBUFFERSGIXPROC) __GLeeGetProcAddress("glXCreateGLXPbufferSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXDestroyGLXPbufferSGIX = (GLEEPFNGLXDESTROYGLXPBUFFERSGIXPROC) __GLeeGetProcAddress("glXDestroyGLXPbufferSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXQueryGLXPbufferSGIX = (GLEEPFNGLXQUERYGLXPBUFFERSGIXPROC) __GLeeGetProcAddress("glXQueryGLXPbufferSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXSelectEventSGIX = (GLEEPFNGLXSELECTEVENTSGIXPROC) __GLeeGetProcAddress("glXSelectEventSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXGetSelectedEventSGIX = (GLEEPFNGLXGETSELECTEDEVENTSGIXPROC) __GLeeGetProcAddress("glXGetSelectedEventSGIX"))!=0) nLinked++; +#endif + if (nLinked==5) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_SGI_cushion(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_SGI_cushion + if ((GLeeFuncPtr_glXCushionSGI = (GLEEPFNGLXCUSHIONSGIPROC) __GLeeGetProcAddress("glXCushionSGI"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_SGIX_video_resize(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_SGIX_video_resize + if ((GLeeFuncPtr_glXBindChannelToWindowSGIX = (GLEEPFNGLXBINDCHANNELTOWINDOWSGIXPROC) __GLeeGetProcAddress("glXBindChannelToWindowSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXChannelRectSGIX = (GLEEPFNGLXCHANNELRECTSGIXPROC) __GLeeGetProcAddress("glXChannelRectSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXQueryChannelRectSGIX = (GLEEPFNGLXQUERYCHANNELRECTSGIXPROC) __GLeeGetProcAddress("glXQueryChannelRectSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXQueryChannelDeltasSGIX = (GLEEPFNGLXQUERYCHANNELDELTASSGIXPROC) __GLeeGetProcAddress("glXQueryChannelDeltasSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXChannelRectSyncSGIX = (GLEEPFNGLXCHANNELRECTSYNCSGIXPROC) __GLeeGetProcAddress("glXChannelRectSyncSGIX"))!=0) nLinked++; +#endif + if (nLinked==5) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_SGIX_swap_group(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_SGIX_swap_group + if ((GLeeFuncPtr_glXJoinSwapGroupSGIX = (GLEEPFNGLXJOINSWAPGROUPSGIXPROC) __GLeeGetProcAddress("glXJoinSwapGroupSGIX"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_SGIX_swap_barrier(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_SGIX_swap_barrier + if ((GLeeFuncPtr_glXBindSwapBarrierSGIX = (GLEEPFNGLXBINDSWAPBARRIERSGIXPROC) __GLeeGetProcAddress("glXBindSwapBarrierSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXQueryMaxSwapBarriersSGIX = (GLEEPFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) __GLeeGetProcAddress("glXQueryMaxSwapBarriersSGIX"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_SGIS_blended_overlay(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_SGIS_shared_multisample(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_SUN_get_transparent_index(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_SUN_get_transparent_index + if ((GLeeFuncPtr_glXGetTransparentIndexSUN = (GLEEPFNGLXGETTRANSPARENTINDEXSUNPROC) __GLeeGetProcAddress("glXGetTransparentIndexSUN"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_3DFX_multisample(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_MESA_copy_sub_buffer(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_MESA_copy_sub_buffer + if ((GLeeFuncPtr_glXCopySubBufferMESA = (GLEEPFNGLXCOPYSUBBUFFERMESAPROC) __GLeeGetProcAddress("glXCopySubBufferMESA"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_MESA_pixmap_colormap(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_MESA_pixmap_colormap + if ((GLeeFuncPtr_glXCreateGLXPixmapMESA = (GLEEPFNGLXCREATEGLXPIXMAPMESAPROC) __GLeeGetProcAddress("glXCreateGLXPixmapMESA"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_MESA_release_buffers(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_MESA_release_buffers + if ((GLeeFuncPtr_glXReleaseBuffersMESA = (GLEEPFNGLXRELEASEBUFFERSMESAPROC) __GLeeGetProcAddress("glXReleaseBuffersMESA"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_MESA_set_3dfx_mode(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_MESA_set_3dfx_mode + if ((GLeeFuncPtr_glXSet3DfxModeMESA = (GLEEPFNGLXSET3DFXMODEMESAPROC) __GLeeGetProcAddress("glXSet3DfxModeMESA"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_SGIX_visual_select_group(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_OML_swap_method(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_OML_sync_control(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_OML_sync_control + if ((GLeeFuncPtr_glXGetSyncValuesOML = (GLEEPFNGLXGETSYNCVALUESOMLPROC) __GLeeGetProcAddress("glXGetSyncValuesOML"))!=0) nLinked++; + if ((GLeeFuncPtr_glXGetMscRateOML = (GLEEPFNGLXGETMSCRATEOMLPROC) __GLeeGetProcAddress("glXGetMscRateOML"))!=0) nLinked++; + if ((GLeeFuncPtr_glXSwapBuffersMscOML = (GLEEPFNGLXSWAPBUFFERSMSCOMLPROC) __GLeeGetProcAddress("glXSwapBuffersMscOML"))!=0) nLinked++; + if ((GLeeFuncPtr_glXWaitForMscOML = (GLEEPFNGLXWAITFORMSCOMLPROC) __GLeeGetProcAddress("glXWaitForMscOML"))!=0) nLinked++; + if ((GLeeFuncPtr_glXWaitForSbcOML = (GLEEPFNGLXWAITFORSBCOMLPROC) __GLeeGetProcAddress("glXWaitForSbcOML"))!=0) nLinked++; +#endif + if (nLinked==5) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_NV_float_buffer(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_SGIX_hyperpipe(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_SGIX_hyperpipe + if ((GLeeFuncPtr_glXQueryHyperpipeNetworkSGIX = (GLEEPFNGLXQUERYHYPERPIPENETWORKSGIXPROC) __GLeeGetProcAddress("glXQueryHyperpipeNetworkSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXHyperpipeConfigSGIX = (GLEEPFNGLXHYPERPIPECONFIGSGIXPROC) __GLeeGetProcAddress("glXHyperpipeConfigSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXQueryHyperpipeConfigSGIX = (GLEEPFNGLXQUERYHYPERPIPECONFIGSGIXPROC) __GLeeGetProcAddress("glXQueryHyperpipeConfigSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXDestroyHyperpipeConfigSGIX = (GLEEPFNGLXDESTROYHYPERPIPECONFIGSGIXPROC) __GLeeGetProcAddress("glXDestroyHyperpipeConfigSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXBindHyperpipeSGIX = (GLEEPFNGLXBINDHYPERPIPESGIXPROC) __GLeeGetProcAddress("glXBindHyperpipeSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXQueryHyperpipeBestAttribSGIX = (GLEEPFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC) __GLeeGetProcAddress("glXQueryHyperpipeBestAttribSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXHyperpipeAttribSGIX = (GLEEPFNGLXHYPERPIPEATTRIBSGIXPROC) __GLeeGetProcAddress("glXHyperpipeAttribSGIX"))!=0) nLinked++; + if ((GLeeFuncPtr_glXQueryHyperpipeAttribSGIX = (GLEEPFNGLXQUERYHYPERPIPEATTRIBSGIXPROC) __GLeeGetProcAddress("glXQueryHyperpipeAttribSGIX"))!=0) nLinked++; +#endif + if (nLinked==8) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_MESA_agp_offset(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_MESA_agp_offset + if ((GLeeFuncPtr_glXGetAGPOffsetMESA = (GLEEPFNGLXGETAGPOFFSETMESAPROC) __GLeeGetProcAddress("glXGetAGPOffsetMESA"))!=0) nLinked++; +#endif + if (nLinked==1) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_EXT_fbconfig_packed_float(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_EXT_framebuffer_sRGB(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_EXT_texture_from_pixmap(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_EXT_texture_from_pixmap + if ((GLeeFuncPtr_glXBindTexImageEXT = (GLEEPFNGLXBINDTEXIMAGEEXTPROC) __GLeeGetProcAddress("glXBindTexImageEXT"))!=0) nLinked++; + if ((GLeeFuncPtr_glXReleaseTexImageEXT = (GLEEPFNGLXRELEASETEXIMAGEEXTPROC) __GLeeGetProcAddress("glXReleaseTexImageEXT"))!=0) nLinked++; +#endif + if (nLinked==2) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLuint __GLeeLink_GLX_NV_present_video(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_NV_video_out(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_NV_swap_group(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_EXT_scene_marker(void) {return GLEE_LINK_COMPLETE;} + +GLuint __GLeeLink_GLX_NV_video_output(void) +{ + GLint nLinked=0; +#ifdef __GLEE_GLX_NV_video_output + if ((GLeeFuncPtr_glXGetVideoDeviceNV = (GLEEPFNGLXGETVIDEODEVICENVPROC) __GLeeGetProcAddress("glXGetVideoDeviceNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glXReleaseVideoDeviceNV = (GLEEPFNGLXRELEASEVIDEODEVICENVPROC) __GLeeGetProcAddress("glXReleaseVideoDeviceNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glXBindVideoImageNV = (GLEEPFNGLXBINDVIDEOIMAGENVPROC) __GLeeGetProcAddress("glXBindVideoImageNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glXReleaseVideoImageNV = (GLEEPFNGLXRELEASEVIDEOIMAGENVPROC) __GLeeGetProcAddress("glXReleaseVideoImageNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glXSendPbufferToVideoNV = (GLEEPFNGLXSENDPBUFFERTOVIDEONVPROC) __GLeeGetProcAddress("glXSendPbufferToVideoNV"))!=0) nLinked++; + if ((GLeeFuncPtr_glXGetVideoInfoNV = (GLEEPFNGLXGETVIDEOINFONVPROC) __GLeeGetProcAddress("glXGetVideoInfoNV"))!=0) nLinked++; +#endif + if (nLinked==6) return GLEE_LINK_COMPLETE; + if (nLinked==0) return GLEE_LINK_FAIL; + return GLEE_LINK_PARTIAL; +} + +GLEE_LINK_FUNCTION __GLeeGLXLoadFunction[40]; + +void initGLXLoadFunctions(void) +{ + __GLeeGLXLoadFunction[0]=__GLeeLink_GLX_VERSION_1_3; + __GLeeGLXLoadFunction[1]=__GLeeLink_GLX_VERSION_1_4; + __GLeeGLXLoadFunction[2]=__GLeeLink_GLX_ARB_multisample; + __GLeeGLXLoadFunction[3]=__GLeeLink_GLX_ARB_fbconfig_float; + __GLeeGLXLoadFunction[4]=__GLeeLink_GLX_ARB_create_context; + __GLeeGLXLoadFunction[5]=__GLeeLink_GLX_SGIS_multisample; + __GLeeGLXLoadFunction[6]=__GLeeLink_GLX_EXT_visual_info; + __GLeeGLXLoadFunction[7]=__GLeeLink_GLX_SGI_swap_control; + __GLeeGLXLoadFunction[8]=__GLeeLink_GLX_SGI_video_sync; + __GLeeGLXLoadFunction[9]=__GLeeLink_GLX_SGI_make_current_read; + __GLeeGLXLoadFunction[10]=__GLeeLink_GLX_EXT_visual_rating; + __GLeeGLXLoadFunction[11]=__GLeeLink_GLX_EXT_import_context; + __GLeeGLXLoadFunction[12]=__GLeeLink_GLX_SGIX_fbconfig; + __GLeeGLXLoadFunction[13]=__GLeeLink_GLX_SGIX_pbuffer; + __GLeeGLXLoadFunction[14]=__GLeeLink_GLX_SGI_cushion; + __GLeeGLXLoadFunction[15]=__GLeeLink_GLX_SGIX_video_resize; + __GLeeGLXLoadFunction[16]=__GLeeLink_GLX_SGIX_swap_group; + __GLeeGLXLoadFunction[17]=__GLeeLink_GLX_SGIX_swap_barrier; + __GLeeGLXLoadFunction[18]=__GLeeLink_GLX_SGIS_blended_overlay; + __GLeeGLXLoadFunction[19]=__GLeeLink_GLX_SGIS_shared_multisample; + __GLeeGLXLoadFunction[20]=__GLeeLink_GLX_SUN_get_transparent_index; + __GLeeGLXLoadFunction[21]=__GLeeLink_GLX_3DFX_multisample; + __GLeeGLXLoadFunction[22]=__GLeeLink_GLX_MESA_copy_sub_buffer; + __GLeeGLXLoadFunction[23]=__GLeeLink_GLX_MESA_pixmap_colormap; + __GLeeGLXLoadFunction[24]=__GLeeLink_GLX_MESA_release_buffers; + __GLeeGLXLoadFunction[25]=__GLeeLink_GLX_MESA_set_3dfx_mode; + __GLeeGLXLoadFunction[26]=__GLeeLink_GLX_SGIX_visual_select_group; + __GLeeGLXLoadFunction[27]=__GLeeLink_GLX_OML_swap_method; + __GLeeGLXLoadFunction[28]=__GLeeLink_GLX_OML_sync_control; + __GLeeGLXLoadFunction[29]=__GLeeLink_GLX_NV_float_buffer; + __GLeeGLXLoadFunction[30]=__GLeeLink_GLX_SGIX_hyperpipe; + __GLeeGLXLoadFunction[31]=__GLeeLink_GLX_MESA_agp_offset; + __GLeeGLXLoadFunction[32]=__GLeeLink_GLX_EXT_fbconfig_packed_float; + __GLeeGLXLoadFunction[33]=__GLeeLink_GLX_EXT_framebuffer_sRGB; + __GLeeGLXLoadFunction[34]=__GLeeLink_GLX_EXT_texture_from_pixmap; + __GLeeGLXLoadFunction[35]=__GLeeLink_GLX_NV_present_video; + __GLeeGLXLoadFunction[36]=__GLeeLink_GLX_NV_video_out; + __GLeeGLXLoadFunction[37]=__GLeeLink_GLX_NV_swap_group; + __GLeeGLXLoadFunction[38]=__GLeeLink_GLX_EXT_scene_marker; + __GLeeGLXLoadFunction[39]=__GLeeLink_GLX_NV_video_output; +} + +#endif /* end Linux */ + + +/***************************************************************** + * GLee internal types + *****************************************************************/ +typedef struct +{ + char ** names; + int * lengths; + int numNames; +}ExtensionList; + + +/***************************************************************** + * GLee internal variables + *****************************************************************/ +char GLeeErrorString[256]=""; + + +/***************************************************************** + * GLee internal functions + *****************************************************************/ + +void __GLeeExtList_init(ExtensionList *extList) +{ + extList->names=0; + extList->lengths=0; + extList->numNames=0; +} + +void __GLeeExtList_clean(ExtensionList *extList) +{ + int a; + for (a=0;anumNames;a++) + { + if (extList->names[a]!=0) free((void *)extList->names[a]); + } + if (extList->names!=0) free((void *)extList->names); + if (extList->lengths!=0) free((void *)extList->lengths); + extList->names=0; + extList->lengths=0; + extList->numNames=0; +} + +void __GLeeExtList_add(ExtensionList *extList, const char * extName) +{ + int length=strlen(extName)+1; + int i=extList->numNames; + int n=i+1; + if (i==0) + { + extList->lengths=(int *)malloc(sizeof(int)); + extList->names=(char **)malloc(sizeof(char *)); + }else + { + extList->lengths=(int *)realloc((void *)extList->lengths, n*sizeof(int)); + extList->names=(char **)realloc((void *)extList->names, n*sizeof(char *)); + } + extList->names[i]=(char *)malloc(length*sizeof(char)); + strcpy(extList->names[i],extName); + extList->lengths[i]=length; + extList->numNames++; +} + +const char *__GLeeGetExtStrPlat( void ) +{ +#ifdef WIN32 + if (!_GLEE_WGL_ARB_extensions_string) + wglGetExtensionsStringARB = (GLEEPFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB"); + + if (wglGetExtensionsStringARB) + return (const char *)wglGetExtensionsStringARB(wglGetCurrentDC()); +#elif defined(__APPLE__) || defined(__APPLE_CC__) +#else + Display *dpy=glXGetCurrentDisplay(); + if(dpy) + { + int dpynr=DefaultScreen(dpy); + return (const char*)glXQueryExtensionsString(dpy,dpynr); + } +#endif + return 0; +} + +void __GLeeWriteError(const char * errorStr) +{ + int a=0; + for (a=0;a<256;a++) + { + GLeeErrorString[a]=errorStr[a]; + } + GLeeErrorString[255]='\0'; +} + +int __GLeeGetVersionNumber(char *versionStr) +{ + int major=(int)versionStr[0]-(int)'0'; + int minor=(int)versionStr[2]-(int)'0'; + return major<<8 | minor; +} + +GLboolean __GLeeGetExtensions(ExtensionList* extList) +{ + const char * platExtStr; + const char * glExtStr; + char * extStr; + char emptyString[1] = ""; + char extensionName[1024]; + int a,b; + int totalExtStrLen; + int platExtStrLen; + int addASpace; + + /* read the platform specific extension string */ + platExtStr=__GLeeGetExtStrPlat(); + if (!platExtStr) platExtStr=emptyString; + + glExtStr=(const char *)glGetString(GL_EXTENSIONS); + if (glExtStr==0) + { + __GLeeWriteError("glGetString(GL_EXTENSIONS) failed."); + return GL_FALSE; + } + + /* allocate the extension string */ + platExtStrLen = strlen(platExtStr); + totalExtStrLen = platExtStrLen + strlen(glExtStr); + extStr=(char *)malloc( (totalExtStrLen+2) * sizeof(char) ); /* we add 2 to allow for an extra space and a null terminator */ + + /* If the last character of platExtStr is not a space, we need to add one when we concatenate the extension strings*/ + addASpace = 0; + if ( platExtStrLen > 2 ) + { + if ( platExtStr[ platExtStrLen-1 ] != ' ') + { + addASpace = 1; + } + } + + /* concatenate the two extension strings */ + if ( addASpace ) + { + sprintf(extStr,"%s %s",platExtStr,glExtStr); + } + else + { + sprintf(extStr,"%s%s",platExtStr,glExtStr); + } + + /* extract the extensions */ + for ( a=0;anumNames; + int a; + for (a=0;anames[a],name)==0) + return GL_TRUE; + } + return GL_FALSE; +} + +GLEE_EXTERN GLint __GLeeGetExtensionNumber(const char *extensionName, int type) +{ + int a; + switch (type) + { + case 0: + for (a=0;a<__GLeeGLNumExtensions;a++) + if (strcmp(extensionName,__GLeeGLExtensionNames[a])==0) return a; + return -1; +#ifdef WIN32 + case 1: + for (a=0;a<__GLeeWGLNumExtensions;a++) + if (strcmp(extensionName,__GLeeWGLExtensionNames[a])==0) return a; + return -1; +#elif defined(__APPLE__) || defined(__APPLE_CC__) +#else + case 2: + for (a=0;a<__GLeeGLXNumExtensions;a++) + if (strcmp(extensionName,__GLeeGLXExtensionNames[a])==0) return a; + return -1; +#endif + } + return -1; +} + +/***************************************************************** + * GLee external functions + *****************************************************************/ + +#ifdef WIN32 +GLEE_EXTERN const char * GLeeGetExtStrWGL( void ) +{ + return __GLeeGetExtStrPlat(); +} +#elif defined(__APPLE__) || defined(__APPLE_CC__) +#else +GLEE_EXTERN const char * GLeeGetExtStrGLX( void ) +{ + return __GLeeGetExtStrPlat(); +} +#endif + +GLEE_EXTERN const char * GLeeGetExtStrGL( void ) +{ + return (const char *)glGetString(GL_EXTENSIONS); +} + +GLEE_EXTERN const char * GLeeGetErrorString( void ) +{ + return GLeeErrorString; +} + +GLboolean __GLeeInitedLoadFunctions=GL_FALSE; + +GLEE_EXTERN GLint GLeeForceLink(const char * extensionName) +{ + int type=0; + int extNum; + int len=strlen(extensionName); + if (len<5) return GLEE_LINK_FAIL; + if (!__GLeeInitedLoadFunctions) + { + if (!__GLeeInited) GLeeInit(); + initGLLoadFunctions(); +#ifdef WIN32 + initWGLLoadFunctions(); +#elif defined(__APPLE__) || defined(__APPLE_CC__) +#else + initGLXLoadFunctions(); +#endif + __GLeeInitedLoadFunctions=GL_TRUE; + } + if (extensionName[0]=='W') type=1; + else if (extensionName[2]=='X') type=2; + extNum=__GLeeGetExtensionNumber(extensionName,type); + if (extNum==-1) return GLEE_LINK_FAIL; + if (type==0) return __GLeeGLLoadFunction[extNum](); +#ifdef WIN32 + if (type==1) return __GLeeWGLLoadFunction[extNum](); +#elif defined(__APPLE__) || defined(__APPLE_CC__) +#else + if (type==2) return __GLeeGLXLoadFunction[extNum](); +#endif + return GLEE_LINK_FAIL; +} + +GLEE_EXTERN GLboolean GLeeEnabled(GLboolean * extensionQueryingVariable) +{ + if (!__GLeeInited) GLeeInit(); + return *extensionQueryingVariable; +} + +GLEE_EXTERN GLboolean GLeeInit( void ) +{ + int version; + ExtensionList extensionNames; + + if (__GLeeInited) + { + return GL_FALSE; + } + + __GLeeExtList_init(&extensionNames); + if (!__GLeeGetExtensions(&extensionNames)) + { + __GLeeWriteError("GL extension querying failed."); + __GLeeExtList_clean(&extensionNames); + return GL_FALSE; + } + + version=__GLeeGetVersionNumber((char *)glGetString(GL_VERSION)); + + __GLeeInited = GL_TRUE; + + +/***************************************************************** + * Autogenerated linking functions + *****************************************************************/ + if (version>=258) + { + _GLEE_VERSION_1_2 = GL_TRUE; + __GLeeLink_GL_VERSION_1_2(); + } + if (__GLeeCheckExtension("GL_ARB_imaging", &extensionNames) ) + { + _GLEE_ARB_imaging = GL_TRUE; + __GLeeLink_GL_ARB_imaging(); + } + if (version>=259) + { + _GLEE_VERSION_1_3 = GL_TRUE; + __GLeeLink_GL_VERSION_1_3(); + } + if (version>=260) + { + _GLEE_VERSION_1_4 = GL_TRUE; + __GLeeLink_GL_VERSION_1_4(); + } + if (version>=261) + { + _GLEE_VERSION_1_5 = GL_TRUE; + __GLeeLink_GL_VERSION_1_5(); + } + if (version>=512) + { + _GLEE_VERSION_2_0 = GL_TRUE; + __GLeeLink_GL_VERSION_2_0(); + } + if (version>=513) + { + _GLEE_VERSION_2_1 = GL_TRUE; + __GLeeLink_GL_VERSION_2_1(); + } + if (version>=768) + { + _GLEE_VERSION_3_0 = GL_TRUE; + __GLeeLink_GL_VERSION_3_0(); + } + if (__GLeeCheckExtension("GL_ARB_multitexture", &extensionNames) ) + { + _GLEE_ARB_multitexture = GL_TRUE; + __GLeeLink_GL_ARB_multitexture(); + } + if (__GLeeCheckExtension("GL_ARB_transpose_matrix", &extensionNames) ) + { + _GLEE_ARB_transpose_matrix = GL_TRUE; + __GLeeLink_GL_ARB_transpose_matrix(); + } + if (__GLeeCheckExtension("GL_ARB_multisample", &extensionNames) ) + { + _GLEE_ARB_multisample = GL_TRUE; + __GLeeLink_GL_ARB_multisample(); + } + if (__GLeeCheckExtension("GL_ARB_texture_env_add", &extensionNames) ) + { + _GLEE_ARB_texture_env_add = GL_TRUE; + __GLeeLink_GL_ARB_texture_env_add(); + } + if (__GLeeCheckExtension("GL_ARB_texture_cube_map", &extensionNames) ) + { + _GLEE_ARB_texture_cube_map = GL_TRUE; + __GLeeLink_GL_ARB_texture_cube_map(); + } + if (__GLeeCheckExtension("GL_ARB_texture_compression", &extensionNames) ) + { + _GLEE_ARB_texture_compression = GL_TRUE; + __GLeeLink_GL_ARB_texture_compression(); + } + if (__GLeeCheckExtension("GL_ARB_texture_border_clamp", &extensionNames) ) + { + _GLEE_ARB_texture_border_clamp = GL_TRUE; + __GLeeLink_GL_ARB_texture_border_clamp(); + } + if (__GLeeCheckExtension("GL_ARB_point_parameters", &extensionNames) ) + { + _GLEE_ARB_point_parameters = GL_TRUE; + __GLeeLink_GL_ARB_point_parameters(); + } + if (__GLeeCheckExtension("GL_ARB_vertex_blend", &extensionNames) ) + { + _GLEE_ARB_vertex_blend = GL_TRUE; + __GLeeLink_GL_ARB_vertex_blend(); + } + if (__GLeeCheckExtension("GL_ARB_matrix_palette", &extensionNames) ) + { + _GLEE_ARB_matrix_palette = GL_TRUE; + __GLeeLink_GL_ARB_matrix_palette(); + } + if (__GLeeCheckExtension("GL_ARB_texture_env_combine", &extensionNames) ) + { + _GLEE_ARB_texture_env_combine = GL_TRUE; + __GLeeLink_GL_ARB_texture_env_combine(); + } + if (__GLeeCheckExtension("GL_ARB_texture_env_crossbar", &extensionNames) ) + { + _GLEE_ARB_texture_env_crossbar = GL_TRUE; + __GLeeLink_GL_ARB_texture_env_crossbar(); + } + if (__GLeeCheckExtension("GL_ARB_texture_env_dot3", &extensionNames) ) + { + _GLEE_ARB_texture_env_dot3 = GL_TRUE; + __GLeeLink_GL_ARB_texture_env_dot3(); + } + if (__GLeeCheckExtension("GL_ARB_texture_mirrored_repeat", &extensionNames) ) + { + _GLEE_ARB_texture_mirrored_repeat = GL_TRUE; + __GLeeLink_GL_ARB_texture_mirrored_repeat(); + } + if (__GLeeCheckExtension("GL_ARB_depth_texture", &extensionNames) ) + { + _GLEE_ARB_depth_texture = GL_TRUE; + __GLeeLink_GL_ARB_depth_texture(); + } + if (__GLeeCheckExtension("GL_ARB_shadow", &extensionNames) ) + { + _GLEE_ARB_shadow = GL_TRUE; + __GLeeLink_GL_ARB_shadow(); + } + if (__GLeeCheckExtension("GL_ARB_shadow_ambient", &extensionNames) ) + { + _GLEE_ARB_shadow_ambient = GL_TRUE; + __GLeeLink_GL_ARB_shadow_ambient(); + } + if (__GLeeCheckExtension("GL_ARB_window_pos", &extensionNames) ) + { + _GLEE_ARB_window_pos = GL_TRUE; + __GLeeLink_GL_ARB_window_pos(); + } + if (__GLeeCheckExtension("GL_ARB_vertex_program", &extensionNames) ) + { + _GLEE_ARB_vertex_program = GL_TRUE; + __GLeeLink_GL_ARB_vertex_program(); + } + if (__GLeeCheckExtension("GL_ARB_fragment_program", &extensionNames) ) + { + _GLEE_ARB_fragment_program = GL_TRUE; + __GLeeLink_GL_ARB_fragment_program(); + } + if (__GLeeCheckExtension("GL_ARB_vertex_buffer_object", &extensionNames) ) + { + _GLEE_ARB_vertex_buffer_object = GL_TRUE; + __GLeeLink_GL_ARB_vertex_buffer_object(); + } + if (__GLeeCheckExtension("GL_ARB_occlusion_query", &extensionNames) ) + { + _GLEE_ARB_occlusion_query = GL_TRUE; + __GLeeLink_GL_ARB_occlusion_query(); + } + if (__GLeeCheckExtension("GL_ARB_shader_objects", &extensionNames) ) + { + _GLEE_ARB_shader_objects = GL_TRUE; + __GLeeLink_GL_ARB_shader_objects(); + } + if (__GLeeCheckExtension("GL_ARB_vertex_shader", &extensionNames) ) + { + _GLEE_ARB_vertex_shader = GL_TRUE; + __GLeeLink_GL_ARB_vertex_shader(); + } + if (__GLeeCheckExtension("GL_ARB_fragment_shader", &extensionNames) ) + { + _GLEE_ARB_fragment_shader = GL_TRUE; + __GLeeLink_GL_ARB_fragment_shader(); + } + if (__GLeeCheckExtension("GL_ARB_shading_language_100", &extensionNames) ) + { + _GLEE_ARB_shading_language_100 = GL_TRUE; + __GLeeLink_GL_ARB_shading_language_100(); + } + if (__GLeeCheckExtension("GL_ARB_texture_non_power_of_two", &extensionNames) ) + { + _GLEE_ARB_texture_non_power_of_two = GL_TRUE; + __GLeeLink_GL_ARB_texture_non_power_of_two(); + } + if (__GLeeCheckExtension("GL_ARB_point_sprite", &extensionNames) ) + { + _GLEE_ARB_point_sprite = GL_TRUE; + __GLeeLink_GL_ARB_point_sprite(); + } + if (__GLeeCheckExtension("GL_ARB_fragment_program_shadow", &extensionNames) ) + { + _GLEE_ARB_fragment_program_shadow = GL_TRUE; + __GLeeLink_GL_ARB_fragment_program_shadow(); + } + if (__GLeeCheckExtension("GL_ARB_draw_buffers", &extensionNames) ) + { + _GLEE_ARB_draw_buffers = GL_TRUE; + __GLeeLink_GL_ARB_draw_buffers(); + } + if (__GLeeCheckExtension("GL_ARB_texture_rectangle", &extensionNames) ) + { + _GLEE_ARB_texture_rectangle = GL_TRUE; + __GLeeLink_GL_ARB_texture_rectangle(); + } + if (__GLeeCheckExtension("GL_ARB_color_buffer_float", &extensionNames) ) + { + _GLEE_ARB_color_buffer_float = GL_TRUE; + __GLeeLink_GL_ARB_color_buffer_float(); + } + if (__GLeeCheckExtension("GL_ARB_half_float_pixel", &extensionNames) ) + { + _GLEE_ARB_half_float_pixel = GL_TRUE; + __GLeeLink_GL_ARB_half_float_pixel(); + } + if (__GLeeCheckExtension("GL_ARB_texture_float", &extensionNames) ) + { + _GLEE_ARB_texture_float = GL_TRUE; + __GLeeLink_GL_ARB_texture_float(); + } + if (__GLeeCheckExtension("GL_ARB_pixel_buffer_object", &extensionNames) ) + { + _GLEE_ARB_pixel_buffer_object = GL_TRUE; + __GLeeLink_GL_ARB_pixel_buffer_object(); + } + if (__GLeeCheckExtension("GL_ARB_depth_buffer_float", &extensionNames) ) + { + _GLEE_ARB_depth_buffer_float = GL_TRUE; + __GLeeLink_GL_ARB_depth_buffer_float(); + } + if (__GLeeCheckExtension("GL_ARB_draw_instanced", &extensionNames) ) + { + _GLEE_ARB_draw_instanced = GL_TRUE; + __GLeeLink_GL_ARB_draw_instanced(); + } + if (__GLeeCheckExtension("GL_ARB_framebuffer_object", &extensionNames) ) + { + _GLEE_ARB_framebuffer_object = GL_TRUE; + __GLeeLink_GL_ARB_framebuffer_object(); + } + if (__GLeeCheckExtension("GL_ARB_framebuffer_sRGB", &extensionNames) ) + { + _GLEE_ARB_framebuffer_sRGB = GL_TRUE; + __GLeeLink_GL_ARB_framebuffer_sRGB(); + } + if (__GLeeCheckExtension("GL_ARB_geometry_shader4", &extensionNames) ) + { + _GLEE_ARB_geometry_shader4 = GL_TRUE; + __GLeeLink_GL_ARB_geometry_shader4(); + } + if (__GLeeCheckExtension("GL_ARB_half_float_vertex", &extensionNames) ) + { + _GLEE_ARB_half_float_vertex = GL_TRUE; + __GLeeLink_GL_ARB_half_float_vertex(); + } + if (__GLeeCheckExtension("GL_ARB_instanced_arrays", &extensionNames) ) + { + _GLEE_ARB_instanced_arrays = GL_TRUE; + __GLeeLink_GL_ARB_instanced_arrays(); + } + if (__GLeeCheckExtension("GL_ARB_map_buffer_range", &extensionNames) ) + { + _GLEE_ARB_map_buffer_range = GL_TRUE; + __GLeeLink_GL_ARB_map_buffer_range(); + } + if (__GLeeCheckExtension("GL_ARB_texture_buffer_object", &extensionNames) ) + { + _GLEE_ARB_texture_buffer_object = GL_TRUE; + __GLeeLink_GL_ARB_texture_buffer_object(); + } + if (__GLeeCheckExtension("GL_ARB_texture_compression_rgtc", &extensionNames) ) + { + _GLEE_ARB_texture_compression_rgtc = GL_TRUE; + __GLeeLink_GL_ARB_texture_compression_rgtc(); + } + if (__GLeeCheckExtension("GL_ARB_texture_rg", &extensionNames) ) + { + _GLEE_ARB_texture_rg = GL_TRUE; + __GLeeLink_GL_ARB_texture_rg(); + } + if (__GLeeCheckExtension("GL_ARB_vertex_array_object", &extensionNames) ) + { + _GLEE_ARB_vertex_array_object = GL_TRUE; + __GLeeLink_GL_ARB_vertex_array_object(); + } + if (__GLeeCheckExtension("GL_EXT_abgr", &extensionNames) ) + { + _GLEE_EXT_abgr = GL_TRUE; + __GLeeLink_GL_EXT_abgr(); + } + if (__GLeeCheckExtension("GL_EXT_blend_color", &extensionNames) ) + { + _GLEE_EXT_blend_color = GL_TRUE; + __GLeeLink_GL_EXT_blend_color(); + } + if (__GLeeCheckExtension("GL_EXT_polygon_offset", &extensionNames) ) + { + _GLEE_EXT_polygon_offset = GL_TRUE; + __GLeeLink_GL_EXT_polygon_offset(); + } + if (__GLeeCheckExtension("GL_EXT_texture", &extensionNames) ) + { + _GLEE_EXT_texture = GL_TRUE; + __GLeeLink_GL_EXT_texture(); + } + if (__GLeeCheckExtension("GL_EXT_texture3D", &extensionNames) ) + { + _GLEE_EXT_texture3D = GL_TRUE; + __GLeeLink_GL_EXT_texture3D(); + } + if (__GLeeCheckExtension("GL_SGIS_texture_filter4", &extensionNames) ) + { + _GLEE_SGIS_texture_filter4 = GL_TRUE; + __GLeeLink_GL_SGIS_texture_filter4(); + } + if (__GLeeCheckExtension("GL_EXT_subtexture", &extensionNames) ) + { + _GLEE_EXT_subtexture = GL_TRUE; + __GLeeLink_GL_EXT_subtexture(); + } + if (__GLeeCheckExtension("GL_EXT_copy_texture", &extensionNames) ) + { + _GLEE_EXT_copy_texture = GL_TRUE; + __GLeeLink_GL_EXT_copy_texture(); + } + if (__GLeeCheckExtension("GL_EXT_histogram", &extensionNames) ) + { + _GLEE_EXT_histogram = GL_TRUE; + __GLeeLink_GL_EXT_histogram(); + } + if (__GLeeCheckExtension("GL_EXT_convolution", &extensionNames) ) + { + _GLEE_EXT_convolution = GL_TRUE; + __GLeeLink_GL_EXT_convolution(); + } + if (__GLeeCheckExtension("GL_SGI_color_matrix", &extensionNames) ) + { + _GLEE_SGI_color_matrix = GL_TRUE; + __GLeeLink_GL_SGI_color_matrix(); + } + if (__GLeeCheckExtension("GL_SGI_color_table", &extensionNames) ) + { + _GLEE_SGI_color_table = GL_TRUE; + __GLeeLink_GL_SGI_color_table(); + } + if (__GLeeCheckExtension("GL_SGIS_pixel_texture", &extensionNames) ) + { + _GLEE_SGIS_pixel_texture = GL_TRUE; + __GLeeLink_GL_SGIS_pixel_texture(); + } + if (__GLeeCheckExtension("GL_SGIX_pixel_texture", &extensionNames) ) + { + _GLEE_SGIX_pixel_texture = GL_TRUE; + __GLeeLink_GL_SGIX_pixel_texture(); + } + if (__GLeeCheckExtension("GL_SGIS_texture4D", &extensionNames) ) + { + _GLEE_SGIS_texture4D = GL_TRUE; + __GLeeLink_GL_SGIS_texture4D(); + } + if (__GLeeCheckExtension("GL_SGI_texture_color_table", &extensionNames) ) + { + _GLEE_SGI_texture_color_table = GL_TRUE; + __GLeeLink_GL_SGI_texture_color_table(); + } + if (__GLeeCheckExtension("GL_EXT_cmyka", &extensionNames) ) + { + _GLEE_EXT_cmyka = GL_TRUE; + __GLeeLink_GL_EXT_cmyka(); + } + if (__GLeeCheckExtension("GL_EXT_texture_object", &extensionNames) ) + { + _GLEE_EXT_texture_object = GL_TRUE; + __GLeeLink_GL_EXT_texture_object(); + } + if (__GLeeCheckExtension("GL_SGIS_detail_texture", &extensionNames) ) + { + _GLEE_SGIS_detail_texture = GL_TRUE; + __GLeeLink_GL_SGIS_detail_texture(); + } + if (__GLeeCheckExtension("GL_SGIS_sharpen_texture", &extensionNames) ) + { + _GLEE_SGIS_sharpen_texture = GL_TRUE; + __GLeeLink_GL_SGIS_sharpen_texture(); + } + if (__GLeeCheckExtension("GL_EXT_packed_pixels", &extensionNames) ) + { + _GLEE_EXT_packed_pixels = GL_TRUE; + __GLeeLink_GL_EXT_packed_pixels(); + } + if (__GLeeCheckExtension("GL_SGIS_texture_lod", &extensionNames) ) + { + _GLEE_SGIS_texture_lod = GL_TRUE; + __GLeeLink_GL_SGIS_texture_lod(); + } + if (__GLeeCheckExtension("GL_SGIS_multisample", &extensionNames) ) + { + _GLEE_SGIS_multisample = GL_TRUE; + __GLeeLink_GL_SGIS_multisample(); + } + if (__GLeeCheckExtension("GL_EXT_rescale_normal", &extensionNames) ) + { + _GLEE_EXT_rescale_normal = GL_TRUE; + __GLeeLink_GL_EXT_rescale_normal(); + } + if (__GLeeCheckExtension("GL_EXT_vertex_array", &extensionNames) ) + { + _GLEE_EXT_vertex_array = GL_TRUE; + __GLeeLink_GL_EXT_vertex_array(); + } + if (__GLeeCheckExtension("GL_EXT_misc_attribute", &extensionNames) ) + { + _GLEE_EXT_misc_attribute = GL_TRUE; + __GLeeLink_GL_EXT_misc_attribute(); + } + if (__GLeeCheckExtension("GL_SGIS_generate_mipmap", &extensionNames) ) + { + _GLEE_SGIS_generate_mipmap = GL_TRUE; + __GLeeLink_GL_SGIS_generate_mipmap(); + } + if (__GLeeCheckExtension("GL_SGIX_clipmap", &extensionNames) ) + { + _GLEE_SGIX_clipmap = GL_TRUE; + __GLeeLink_GL_SGIX_clipmap(); + } + if (__GLeeCheckExtension("GL_SGIX_shadow", &extensionNames) ) + { + _GLEE_SGIX_shadow = GL_TRUE; + __GLeeLink_GL_SGIX_shadow(); + } + if (__GLeeCheckExtension("GL_SGIS_texture_edge_clamp", &extensionNames) ) + { + _GLEE_SGIS_texture_edge_clamp = GL_TRUE; + __GLeeLink_GL_SGIS_texture_edge_clamp(); + } + if (__GLeeCheckExtension("GL_SGIS_texture_border_clamp", &extensionNames) ) + { + _GLEE_SGIS_texture_border_clamp = GL_TRUE; + __GLeeLink_GL_SGIS_texture_border_clamp(); + } + if (__GLeeCheckExtension("GL_EXT_blend_minmax", &extensionNames) ) + { + _GLEE_EXT_blend_minmax = GL_TRUE; + __GLeeLink_GL_EXT_blend_minmax(); + } + if (__GLeeCheckExtension("GL_EXT_blend_subtract", &extensionNames) ) + { + _GLEE_EXT_blend_subtract = GL_TRUE; + __GLeeLink_GL_EXT_blend_subtract(); + } + if (__GLeeCheckExtension("GL_EXT_blend_logic_op", &extensionNames) ) + { + _GLEE_EXT_blend_logic_op = GL_TRUE; + __GLeeLink_GL_EXT_blend_logic_op(); + } + if (__GLeeCheckExtension("GL_SGIX_interlace", &extensionNames) ) + { + _GLEE_SGIX_interlace = GL_TRUE; + __GLeeLink_GL_SGIX_interlace(); + } + if (__GLeeCheckExtension("GL_SGIX_pixel_tiles", &extensionNames) ) + { + _GLEE_SGIX_pixel_tiles = GL_TRUE; + __GLeeLink_GL_SGIX_pixel_tiles(); + } + if (__GLeeCheckExtension("GL_SGIS_texture_select", &extensionNames) ) + { + _GLEE_SGIS_texture_select = GL_TRUE; + __GLeeLink_GL_SGIS_texture_select(); + } + if (__GLeeCheckExtension("GL_SGIX_sprite", &extensionNames) ) + { + _GLEE_SGIX_sprite = GL_TRUE; + __GLeeLink_GL_SGIX_sprite(); + } + if (__GLeeCheckExtension("GL_SGIX_texture_multi_buffer", &extensionNames) ) + { + _GLEE_SGIX_texture_multi_buffer = GL_TRUE; + __GLeeLink_GL_SGIX_texture_multi_buffer(); + } + if (__GLeeCheckExtension("GL_EXT_point_parameters", &extensionNames) ) + { + _GLEE_EXT_point_parameters = GL_TRUE; + __GLeeLink_GL_EXT_point_parameters(); + } + if (__GLeeCheckExtension("GL_SGIS_point_parameters", &extensionNames) ) + { + _GLEE_SGIS_point_parameters = GL_TRUE; + __GLeeLink_GL_SGIS_point_parameters(); + } + if (__GLeeCheckExtension("GL_SGIX_instruments", &extensionNames) ) + { + _GLEE_SGIX_instruments = GL_TRUE; + __GLeeLink_GL_SGIX_instruments(); + } + if (__GLeeCheckExtension("GL_SGIX_texture_scale_bias", &extensionNames) ) + { + _GLEE_SGIX_texture_scale_bias = GL_TRUE; + __GLeeLink_GL_SGIX_texture_scale_bias(); + } + if (__GLeeCheckExtension("GL_SGIX_framezoom", &extensionNames) ) + { + _GLEE_SGIX_framezoom = GL_TRUE; + __GLeeLink_GL_SGIX_framezoom(); + } + if (__GLeeCheckExtension("GL_SGIX_tag_sample_buffer", &extensionNames) ) + { + _GLEE_SGIX_tag_sample_buffer = GL_TRUE; + __GLeeLink_GL_SGIX_tag_sample_buffer(); + } + if (__GLeeCheckExtension("GL_FfdMaskSGIX", &extensionNames) ) + { + _GLEE_FfdMaskSGIX = GL_TRUE; + __GLeeLink_GL_FfdMaskSGIX(); + } + if (__GLeeCheckExtension("GL_SGIX_polynomial_ffd", &extensionNames) ) + { + _GLEE_SGIX_polynomial_ffd = GL_TRUE; + __GLeeLink_GL_SGIX_polynomial_ffd(); + } + if (__GLeeCheckExtension("GL_SGIX_reference_plane", &extensionNames) ) + { + _GLEE_SGIX_reference_plane = GL_TRUE; + __GLeeLink_GL_SGIX_reference_plane(); + } + if (__GLeeCheckExtension("GL_SGIX_flush_raster", &extensionNames) ) + { + _GLEE_SGIX_flush_raster = GL_TRUE; + __GLeeLink_GL_SGIX_flush_raster(); + } + if (__GLeeCheckExtension("GL_SGIX_depth_texture", &extensionNames) ) + { + _GLEE_SGIX_depth_texture = GL_TRUE; + __GLeeLink_GL_SGIX_depth_texture(); + } + if (__GLeeCheckExtension("GL_SGIS_fog_function", &extensionNames) ) + { + _GLEE_SGIS_fog_function = GL_TRUE; + __GLeeLink_GL_SGIS_fog_function(); + } + if (__GLeeCheckExtension("GL_SGIX_fog_offset", &extensionNames) ) + { + _GLEE_SGIX_fog_offset = GL_TRUE; + __GLeeLink_GL_SGIX_fog_offset(); + } + if (__GLeeCheckExtension("GL_HP_image_transform", &extensionNames) ) + { + _GLEE_HP_image_transform = GL_TRUE; + __GLeeLink_GL_HP_image_transform(); + } + if (__GLeeCheckExtension("GL_HP_convolution_border_modes", &extensionNames) ) + { + _GLEE_HP_convolution_border_modes = GL_TRUE; + __GLeeLink_GL_HP_convolution_border_modes(); + } + if (__GLeeCheckExtension("GL_INGR_palette_buffer", &extensionNames) ) + { + _GLEE_INGR_palette_buffer = GL_TRUE; + __GLeeLink_GL_INGR_palette_buffer(); + } + if (__GLeeCheckExtension("GL_SGIX_texture_add_env", &extensionNames) ) + { + _GLEE_SGIX_texture_add_env = GL_TRUE; + __GLeeLink_GL_SGIX_texture_add_env(); + } + if (__GLeeCheckExtension("GL_EXT_color_subtable", &extensionNames) ) + { + _GLEE_EXT_color_subtable = GL_TRUE; + __GLeeLink_GL_EXT_color_subtable(); + } + if (__GLeeCheckExtension("GL_PGI_vertex_hints", &extensionNames) ) + { + _GLEE_PGI_vertex_hints = GL_TRUE; + __GLeeLink_GL_PGI_vertex_hints(); + } + if (__GLeeCheckExtension("GL_PGI_misc_hints", &extensionNames) ) + { + _GLEE_PGI_misc_hints = GL_TRUE; + __GLeeLink_GL_PGI_misc_hints(); + } + if (__GLeeCheckExtension("GL_EXT_paletted_texture", &extensionNames) ) + { + _GLEE_EXT_paletted_texture = GL_TRUE; + __GLeeLink_GL_EXT_paletted_texture(); + } + if (__GLeeCheckExtension("GL_EXT_clip_volume_hint", &extensionNames) ) + { + _GLEE_EXT_clip_volume_hint = GL_TRUE; + __GLeeLink_GL_EXT_clip_volume_hint(); + } + if (__GLeeCheckExtension("GL_SGIX_list_priority", &extensionNames) ) + { + _GLEE_SGIX_list_priority = GL_TRUE; + __GLeeLink_GL_SGIX_list_priority(); + } + if (__GLeeCheckExtension("GL_SGIX_ir_instrument1", &extensionNames) ) + { + _GLEE_SGIX_ir_instrument1 = GL_TRUE; + __GLeeLink_GL_SGIX_ir_instrument1(); + } + if (__GLeeCheckExtension("GL_SGIX_calligraphic_fragment", &extensionNames) ) + { + _GLEE_SGIX_calligraphic_fragment = GL_TRUE; + __GLeeLink_GL_SGIX_calligraphic_fragment(); + } + if (__GLeeCheckExtension("GL_SGIX_texture_lod_bias", &extensionNames) ) + { + _GLEE_SGIX_texture_lod_bias = GL_TRUE; + __GLeeLink_GL_SGIX_texture_lod_bias(); + } + if (__GLeeCheckExtension("GL_SGIX_shadow_ambient", &extensionNames) ) + { + _GLEE_SGIX_shadow_ambient = GL_TRUE; + __GLeeLink_GL_SGIX_shadow_ambient(); + } + if (__GLeeCheckExtension("GL_EXT_index_texture", &extensionNames) ) + { + _GLEE_EXT_index_texture = GL_TRUE; + __GLeeLink_GL_EXT_index_texture(); + } + if (__GLeeCheckExtension("GL_EXT_index_material", &extensionNames) ) + { + _GLEE_EXT_index_material = GL_TRUE; + __GLeeLink_GL_EXT_index_material(); + } + if (__GLeeCheckExtension("GL_EXT_index_func", &extensionNames) ) + { + _GLEE_EXT_index_func = GL_TRUE; + __GLeeLink_GL_EXT_index_func(); + } + if (__GLeeCheckExtension("GL_EXT_index_array_formats", &extensionNames) ) + { + _GLEE_EXT_index_array_formats = GL_TRUE; + __GLeeLink_GL_EXT_index_array_formats(); + } + if (__GLeeCheckExtension("GL_EXT_compiled_vertex_array", &extensionNames) ) + { + _GLEE_EXT_compiled_vertex_array = GL_TRUE; + __GLeeLink_GL_EXT_compiled_vertex_array(); + } + if (__GLeeCheckExtension("GL_EXT_cull_vertex", &extensionNames) ) + { + _GLEE_EXT_cull_vertex = GL_TRUE; + __GLeeLink_GL_EXT_cull_vertex(); + } + if (__GLeeCheckExtension("GL_SGIX_ycrcb", &extensionNames) ) + { + _GLEE_SGIX_ycrcb = GL_TRUE; + __GLeeLink_GL_SGIX_ycrcb(); + } + if (__GLeeCheckExtension("GL_SGIX_fragment_lighting", &extensionNames) ) + { + _GLEE_SGIX_fragment_lighting = GL_TRUE; + __GLeeLink_GL_SGIX_fragment_lighting(); + } + if (__GLeeCheckExtension("GL_IBM_rasterpos_clip", &extensionNames) ) + { + _GLEE_IBM_rasterpos_clip = GL_TRUE; + __GLeeLink_GL_IBM_rasterpos_clip(); + } + if (__GLeeCheckExtension("GL_HP_texture_lighting", &extensionNames) ) + { + _GLEE_HP_texture_lighting = GL_TRUE; + __GLeeLink_GL_HP_texture_lighting(); + } + if (__GLeeCheckExtension("GL_EXT_draw_range_elements", &extensionNames) ) + { + _GLEE_EXT_draw_range_elements = GL_TRUE; + __GLeeLink_GL_EXT_draw_range_elements(); + } + if (__GLeeCheckExtension("GL_WIN_phong_shading", &extensionNames) ) + { + _GLEE_WIN_phong_shading = GL_TRUE; + __GLeeLink_GL_WIN_phong_shading(); + } + if (__GLeeCheckExtension("GL_WIN_specular_fog", &extensionNames) ) + { + _GLEE_WIN_specular_fog = GL_TRUE; + __GLeeLink_GL_WIN_specular_fog(); + } + if (__GLeeCheckExtension("GL_EXT_light_texture", &extensionNames) ) + { + _GLEE_EXT_light_texture = GL_TRUE; + __GLeeLink_GL_EXT_light_texture(); + } + if (__GLeeCheckExtension("GL_SGIX_blend_alpha_minmax", &extensionNames) ) + { + _GLEE_SGIX_blend_alpha_minmax = GL_TRUE; + __GLeeLink_GL_SGIX_blend_alpha_minmax(); + } + if (__GLeeCheckExtension("GL_SGIX_impact_pixel_texture", &extensionNames) ) + { + _GLEE_SGIX_impact_pixel_texture = GL_TRUE; + __GLeeLink_GL_SGIX_impact_pixel_texture(); + } + if (__GLeeCheckExtension("GL_EXT_bgra", &extensionNames) ) + { + _GLEE_EXT_bgra = GL_TRUE; + __GLeeLink_GL_EXT_bgra(); + } + if (__GLeeCheckExtension("GL_SGIX_async", &extensionNames) ) + { + _GLEE_SGIX_async = GL_TRUE; + __GLeeLink_GL_SGIX_async(); + } + if (__GLeeCheckExtension("GL_SGIX_async_pixel", &extensionNames) ) + { + _GLEE_SGIX_async_pixel = GL_TRUE; + __GLeeLink_GL_SGIX_async_pixel(); + } + if (__GLeeCheckExtension("GL_SGIX_async_histogram", &extensionNames) ) + { + _GLEE_SGIX_async_histogram = GL_TRUE; + __GLeeLink_GL_SGIX_async_histogram(); + } + if (__GLeeCheckExtension("GL_INTEL_texture_scissor", &extensionNames) ) + { + _GLEE_INTEL_texture_scissor = GL_TRUE; + __GLeeLink_GL_INTEL_texture_scissor(); + } + if (__GLeeCheckExtension("GL_INTEL_parallel_arrays", &extensionNames) ) + { + _GLEE_INTEL_parallel_arrays = GL_TRUE; + __GLeeLink_GL_INTEL_parallel_arrays(); + } + if (__GLeeCheckExtension("GL_HP_occlusion_test", &extensionNames) ) + { + _GLEE_HP_occlusion_test = GL_TRUE; + __GLeeLink_GL_HP_occlusion_test(); + } + if (__GLeeCheckExtension("GL_EXT_pixel_transform", &extensionNames) ) + { + _GLEE_EXT_pixel_transform = GL_TRUE; + __GLeeLink_GL_EXT_pixel_transform(); + } + if (__GLeeCheckExtension("GL_EXT_pixel_transform_color_table", &extensionNames) ) + { + _GLEE_EXT_pixel_transform_color_table = GL_TRUE; + __GLeeLink_GL_EXT_pixel_transform_color_table(); + } + if (__GLeeCheckExtension("GL_EXT_shared_texture_palette", &extensionNames) ) + { + _GLEE_EXT_shared_texture_palette = GL_TRUE; + __GLeeLink_GL_EXT_shared_texture_palette(); + } + if (__GLeeCheckExtension("GL_EXT_separate_specular_color", &extensionNames) ) + { + _GLEE_EXT_separate_specular_color = GL_TRUE; + __GLeeLink_GL_EXT_separate_specular_color(); + } + if (__GLeeCheckExtension("GL_EXT_secondary_color", &extensionNames) ) + { + _GLEE_EXT_secondary_color = GL_TRUE; + __GLeeLink_GL_EXT_secondary_color(); + } + if (__GLeeCheckExtension("GL_EXT_texture_perturb_normal", &extensionNames) ) + { + _GLEE_EXT_texture_perturb_normal = GL_TRUE; + __GLeeLink_GL_EXT_texture_perturb_normal(); + } + if (__GLeeCheckExtension("GL_EXT_multi_draw_arrays", &extensionNames) ) + { + _GLEE_EXT_multi_draw_arrays = GL_TRUE; + __GLeeLink_GL_EXT_multi_draw_arrays(); + } + if (__GLeeCheckExtension("GL_EXT_fog_coord", &extensionNames) ) + { + _GLEE_EXT_fog_coord = GL_TRUE; + __GLeeLink_GL_EXT_fog_coord(); + } + if (__GLeeCheckExtension("GL_REND_screen_coordinates", &extensionNames) ) + { + _GLEE_REND_screen_coordinates = GL_TRUE; + __GLeeLink_GL_REND_screen_coordinates(); + } + if (__GLeeCheckExtension("GL_EXT_coordinate_frame", &extensionNames) ) + { + _GLEE_EXT_coordinate_frame = GL_TRUE; + __GLeeLink_GL_EXT_coordinate_frame(); + } + if (__GLeeCheckExtension("GL_EXT_texture_env_combine", &extensionNames) ) + { + _GLEE_EXT_texture_env_combine = GL_TRUE; + __GLeeLink_GL_EXT_texture_env_combine(); + } + if (__GLeeCheckExtension("GL_APPLE_specular_vector", &extensionNames) ) + { + _GLEE_APPLE_specular_vector = GL_TRUE; + __GLeeLink_GL_APPLE_specular_vector(); + } + if (__GLeeCheckExtension("GL_APPLE_transform_hint", &extensionNames) ) + { + _GLEE_APPLE_transform_hint = GL_TRUE; + __GLeeLink_GL_APPLE_transform_hint(); + } + if (__GLeeCheckExtension("GL_SGIX_fog_scale", &extensionNames) ) + { + _GLEE_SGIX_fog_scale = GL_TRUE; + __GLeeLink_GL_SGIX_fog_scale(); + } + if (__GLeeCheckExtension("GL_SUNX_constant_data", &extensionNames) ) + { + _GLEE_SUNX_constant_data = GL_TRUE; + __GLeeLink_GL_SUNX_constant_data(); + } + if (__GLeeCheckExtension("GL_SUN_global_alpha", &extensionNames) ) + { + _GLEE_SUN_global_alpha = GL_TRUE; + __GLeeLink_GL_SUN_global_alpha(); + } + if (__GLeeCheckExtension("GL_SUN_triangle_list", &extensionNames) ) + { + _GLEE_SUN_triangle_list = GL_TRUE; + __GLeeLink_GL_SUN_triangle_list(); + } + if (__GLeeCheckExtension("GL_SUN_vertex", &extensionNames) ) + { + _GLEE_SUN_vertex = GL_TRUE; + __GLeeLink_GL_SUN_vertex(); + } + if (__GLeeCheckExtension("GL_EXT_blend_func_separate", &extensionNames) ) + { + _GLEE_EXT_blend_func_separate = GL_TRUE; + __GLeeLink_GL_EXT_blend_func_separate(); + } + if (__GLeeCheckExtension("GL_INGR_color_clamp", &extensionNames) ) + { + _GLEE_INGR_color_clamp = GL_TRUE; + __GLeeLink_GL_INGR_color_clamp(); + } + if (__GLeeCheckExtension("GL_INGR_interlace_read", &extensionNames) ) + { + _GLEE_INGR_interlace_read = GL_TRUE; + __GLeeLink_GL_INGR_interlace_read(); + } + if (__GLeeCheckExtension("GL_EXT_stencil_wrap", &extensionNames) ) + { + _GLEE_EXT_stencil_wrap = GL_TRUE; + __GLeeLink_GL_EXT_stencil_wrap(); + } + if (__GLeeCheckExtension("GL_EXT_422_pixels", &extensionNames) ) + { + _GLEE_EXT_422_pixels = GL_TRUE; + __GLeeLink_GL_EXT_422_pixels(); + } + if (__GLeeCheckExtension("GL_NV_texgen_reflection", &extensionNames) ) + { + _GLEE_NV_texgen_reflection = GL_TRUE; + __GLeeLink_GL_NV_texgen_reflection(); + } + if (__GLeeCheckExtension("GL_EXT_texture_cube_map", &extensionNames) ) + { + _GLEE_EXT_texture_cube_map = GL_TRUE; + __GLeeLink_GL_EXT_texture_cube_map(); + } + if (__GLeeCheckExtension("GL_SUN_convolution_border_modes", &extensionNames) ) + { + _GLEE_SUN_convolution_border_modes = GL_TRUE; + __GLeeLink_GL_SUN_convolution_border_modes(); + } + if (__GLeeCheckExtension("GL_EXT_texture_env_add", &extensionNames) ) + { + _GLEE_EXT_texture_env_add = GL_TRUE; + __GLeeLink_GL_EXT_texture_env_add(); + } + if (__GLeeCheckExtension("GL_EXT_texture_lod_bias", &extensionNames) ) + { + _GLEE_EXT_texture_lod_bias = GL_TRUE; + __GLeeLink_GL_EXT_texture_lod_bias(); + } + if (__GLeeCheckExtension("GL_EXT_texture_filter_anisotropic", &extensionNames) ) + { + _GLEE_EXT_texture_filter_anisotropic = GL_TRUE; + __GLeeLink_GL_EXT_texture_filter_anisotropic(); + } + if (__GLeeCheckExtension("GL_EXT_vertex_weighting", &extensionNames) ) + { + _GLEE_EXT_vertex_weighting = GL_TRUE; + __GLeeLink_GL_EXT_vertex_weighting(); + } + if (__GLeeCheckExtension("GL_NV_light_max_exponent", &extensionNames) ) + { + _GLEE_NV_light_max_exponent = GL_TRUE; + __GLeeLink_GL_NV_light_max_exponent(); + } + if (__GLeeCheckExtension("GL_NV_vertex_array_range", &extensionNames) ) + { + _GLEE_NV_vertex_array_range = GL_TRUE; + __GLeeLink_GL_NV_vertex_array_range(); + } + if (__GLeeCheckExtension("GL_NV_register_combiners", &extensionNames) ) + { + _GLEE_NV_register_combiners = GL_TRUE; + __GLeeLink_GL_NV_register_combiners(); + } + if (__GLeeCheckExtension("GL_NV_fog_distance", &extensionNames) ) + { + _GLEE_NV_fog_distance = GL_TRUE; + __GLeeLink_GL_NV_fog_distance(); + } + if (__GLeeCheckExtension("GL_NV_texgen_emboss", &extensionNames) ) + { + _GLEE_NV_texgen_emboss = GL_TRUE; + __GLeeLink_GL_NV_texgen_emboss(); + } + if (__GLeeCheckExtension("GL_NV_blend_square", &extensionNames) ) + { + _GLEE_NV_blend_square = GL_TRUE; + __GLeeLink_GL_NV_blend_square(); + } + if (__GLeeCheckExtension("GL_NV_texture_env_combine4", &extensionNames) ) + { + _GLEE_NV_texture_env_combine4 = GL_TRUE; + __GLeeLink_GL_NV_texture_env_combine4(); + } + if (__GLeeCheckExtension("GL_MESA_resize_buffers", &extensionNames) ) + { + _GLEE_MESA_resize_buffers = GL_TRUE; + __GLeeLink_GL_MESA_resize_buffers(); + } + if (__GLeeCheckExtension("GL_MESA_window_pos", &extensionNames) ) + { + _GLEE_MESA_window_pos = GL_TRUE; + __GLeeLink_GL_MESA_window_pos(); + } + if (__GLeeCheckExtension("GL_EXT_texture_compression_s3tc", &extensionNames) ) + { + _GLEE_EXT_texture_compression_s3tc = GL_TRUE; + __GLeeLink_GL_EXT_texture_compression_s3tc(); + } + if (__GLeeCheckExtension("GL_IBM_cull_vertex", &extensionNames) ) + { + _GLEE_IBM_cull_vertex = GL_TRUE; + __GLeeLink_GL_IBM_cull_vertex(); + } + if (__GLeeCheckExtension("GL_IBM_multimode_draw_arrays", &extensionNames) ) + { + _GLEE_IBM_multimode_draw_arrays = GL_TRUE; + __GLeeLink_GL_IBM_multimode_draw_arrays(); + } + if (__GLeeCheckExtension("GL_IBM_vertex_array_lists", &extensionNames) ) + { + _GLEE_IBM_vertex_array_lists = GL_TRUE; + __GLeeLink_GL_IBM_vertex_array_lists(); + } + if (__GLeeCheckExtension("GL_SGIX_subsample", &extensionNames) ) + { + _GLEE_SGIX_subsample = GL_TRUE; + __GLeeLink_GL_SGIX_subsample(); + } + if (__GLeeCheckExtension("GL_SGIX_ycrcb_subsample", &extensionNames) ) + { + _GLEE_SGIX_ycrcb_subsample = GL_TRUE; + __GLeeLink_GL_SGIX_ycrcb_subsample(); + } + if (__GLeeCheckExtension("GL_SGIX_ycrcba", &extensionNames) ) + { + _GLEE_SGIX_ycrcba = GL_TRUE; + __GLeeLink_GL_SGIX_ycrcba(); + } + if (__GLeeCheckExtension("GL_SGI_depth_pass_instrument", &extensionNames) ) + { + _GLEE_SGI_depth_pass_instrument = GL_TRUE; + __GLeeLink_GL_SGI_depth_pass_instrument(); + } + if (__GLeeCheckExtension("GL_3DFX_texture_compression_FXT1", &extensionNames) ) + { + _GLEE_3DFX_texture_compression_FXT1 = GL_TRUE; + __GLeeLink_GL_3DFX_texture_compression_FXT1(); + } + if (__GLeeCheckExtension("GL_3DFX_multisample", &extensionNames) ) + { + _GLEE_3DFX_multisample = GL_TRUE; + __GLeeLink_GL_3DFX_multisample(); + } + if (__GLeeCheckExtension("GL_3DFX_tbuffer", &extensionNames) ) + { + _GLEE_3DFX_tbuffer = GL_TRUE; + __GLeeLink_GL_3DFX_tbuffer(); + } + if (__GLeeCheckExtension("GL_EXT_multisample", &extensionNames) ) + { + _GLEE_EXT_multisample = GL_TRUE; + __GLeeLink_GL_EXT_multisample(); + } + if (__GLeeCheckExtension("GL_SGIX_vertex_preclip", &extensionNames) ) + { + _GLEE_SGIX_vertex_preclip = GL_TRUE; + __GLeeLink_GL_SGIX_vertex_preclip(); + } + if (__GLeeCheckExtension("GL_SGIX_convolution_accuracy", &extensionNames) ) + { + _GLEE_SGIX_convolution_accuracy = GL_TRUE; + __GLeeLink_GL_SGIX_convolution_accuracy(); + } + if (__GLeeCheckExtension("GL_SGIX_resample", &extensionNames) ) + { + _GLEE_SGIX_resample = GL_TRUE; + __GLeeLink_GL_SGIX_resample(); + } + if (__GLeeCheckExtension("GL_SGIS_point_line_texgen", &extensionNames) ) + { + _GLEE_SGIS_point_line_texgen = GL_TRUE; + __GLeeLink_GL_SGIS_point_line_texgen(); + } + if (__GLeeCheckExtension("GL_SGIS_texture_color_mask", &extensionNames) ) + { + _GLEE_SGIS_texture_color_mask = GL_TRUE; + __GLeeLink_GL_SGIS_texture_color_mask(); + } + if (__GLeeCheckExtension("GL_EXT_texture_env_dot3", &extensionNames) ) + { + _GLEE_EXT_texture_env_dot3 = GL_TRUE; + __GLeeLink_GL_EXT_texture_env_dot3(); + } + if (__GLeeCheckExtension("GL_ATI_texture_mirror_once", &extensionNames) ) + { + _GLEE_ATI_texture_mirror_once = GL_TRUE; + __GLeeLink_GL_ATI_texture_mirror_once(); + } + if (__GLeeCheckExtension("GL_NV_fence", &extensionNames) ) + { + _GLEE_NV_fence = GL_TRUE; + __GLeeLink_GL_NV_fence(); + } + if (__GLeeCheckExtension("GL_IBM_texture_mirrored_repeat", &extensionNames) ) + { + _GLEE_IBM_texture_mirrored_repeat = GL_TRUE; + __GLeeLink_GL_IBM_texture_mirrored_repeat(); + } + if (__GLeeCheckExtension("GL_NV_evaluators", &extensionNames) ) + { + _GLEE_NV_evaluators = GL_TRUE; + __GLeeLink_GL_NV_evaluators(); + } + if (__GLeeCheckExtension("GL_NV_packed_depth_stencil", &extensionNames) ) + { + _GLEE_NV_packed_depth_stencil = GL_TRUE; + __GLeeLink_GL_NV_packed_depth_stencil(); + } + if (__GLeeCheckExtension("GL_NV_register_combiners2", &extensionNames) ) + { + _GLEE_NV_register_combiners2 = GL_TRUE; + __GLeeLink_GL_NV_register_combiners2(); + } + if (__GLeeCheckExtension("GL_NV_texture_compression_vtc", &extensionNames) ) + { + _GLEE_NV_texture_compression_vtc = GL_TRUE; + __GLeeLink_GL_NV_texture_compression_vtc(); + } + if (__GLeeCheckExtension("GL_NV_texture_rectangle", &extensionNames) ) + { + _GLEE_NV_texture_rectangle = GL_TRUE; + __GLeeLink_GL_NV_texture_rectangle(); + } + if (__GLeeCheckExtension("GL_NV_texture_shader", &extensionNames) ) + { + _GLEE_NV_texture_shader = GL_TRUE; + __GLeeLink_GL_NV_texture_shader(); + } + if (__GLeeCheckExtension("GL_NV_texture_shader2", &extensionNames) ) + { + _GLEE_NV_texture_shader2 = GL_TRUE; + __GLeeLink_GL_NV_texture_shader2(); + } + if (__GLeeCheckExtension("GL_NV_vertex_array_range2", &extensionNames) ) + { + _GLEE_NV_vertex_array_range2 = GL_TRUE; + __GLeeLink_GL_NV_vertex_array_range2(); + } + if (__GLeeCheckExtension("GL_NV_vertex_program", &extensionNames) ) + { + _GLEE_NV_vertex_program = GL_TRUE; + __GLeeLink_GL_NV_vertex_program(); + } + if (__GLeeCheckExtension("GL_SGIX_texture_coordinate_clamp", &extensionNames) ) + { + _GLEE_SGIX_texture_coordinate_clamp = GL_TRUE; + __GLeeLink_GL_SGIX_texture_coordinate_clamp(); + } + if (__GLeeCheckExtension("GL_SGIX_scalebias_hint", &extensionNames) ) + { + _GLEE_SGIX_scalebias_hint = GL_TRUE; + __GLeeLink_GL_SGIX_scalebias_hint(); + } + if (__GLeeCheckExtension("GL_OML_interlace", &extensionNames) ) + { + _GLEE_OML_interlace = GL_TRUE; + __GLeeLink_GL_OML_interlace(); + } + if (__GLeeCheckExtension("GL_OML_subsample", &extensionNames) ) + { + _GLEE_OML_subsample = GL_TRUE; + __GLeeLink_GL_OML_subsample(); + } + if (__GLeeCheckExtension("GL_OML_resample", &extensionNames) ) + { + _GLEE_OML_resample = GL_TRUE; + __GLeeLink_GL_OML_resample(); + } + if (__GLeeCheckExtension("GL_NV_copy_depth_to_color", &extensionNames) ) + { + _GLEE_NV_copy_depth_to_color = GL_TRUE; + __GLeeLink_GL_NV_copy_depth_to_color(); + } + if (__GLeeCheckExtension("GL_ATI_envmap_bumpmap", &extensionNames) ) + { + _GLEE_ATI_envmap_bumpmap = GL_TRUE; + __GLeeLink_GL_ATI_envmap_bumpmap(); + } + if (__GLeeCheckExtension("GL_ATI_fragment_shader", &extensionNames) ) + { + _GLEE_ATI_fragment_shader = GL_TRUE; + __GLeeLink_GL_ATI_fragment_shader(); + } + if (__GLeeCheckExtension("GL_ATI_pn_triangles", &extensionNames) ) + { + _GLEE_ATI_pn_triangles = GL_TRUE; + __GLeeLink_GL_ATI_pn_triangles(); + } + if (__GLeeCheckExtension("GL_ATI_vertex_array_object", &extensionNames) ) + { + _GLEE_ATI_vertex_array_object = GL_TRUE; + __GLeeLink_GL_ATI_vertex_array_object(); + } + if (__GLeeCheckExtension("GL_EXT_vertex_shader", &extensionNames) ) + { + _GLEE_EXT_vertex_shader = GL_TRUE; + __GLeeLink_GL_EXT_vertex_shader(); + } + if (__GLeeCheckExtension("GL_ATI_vertex_streams", &extensionNames) ) + { + _GLEE_ATI_vertex_streams = GL_TRUE; + __GLeeLink_GL_ATI_vertex_streams(); + } + if (__GLeeCheckExtension("GL_ATI_element_array", &extensionNames) ) + { + _GLEE_ATI_element_array = GL_TRUE; + __GLeeLink_GL_ATI_element_array(); + } + if (__GLeeCheckExtension("GL_SUN_mesh_array", &extensionNames) ) + { + _GLEE_SUN_mesh_array = GL_TRUE; + __GLeeLink_GL_SUN_mesh_array(); + } + if (__GLeeCheckExtension("GL_SUN_slice_accum", &extensionNames) ) + { + _GLEE_SUN_slice_accum = GL_TRUE; + __GLeeLink_GL_SUN_slice_accum(); + } + if (__GLeeCheckExtension("GL_NV_multisample_filter_hint", &extensionNames) ) + { + _GLEE_NV_multisample_filter_hint = GL_TRUE; + __GLeeLink_GL_NV_multisample_filter_hint(); + } + if (__GLeeCheckExtension("GL_NV_depth_clamp", &extensionNames) ) + { + _GLEE_NV_depth_clamp = GL_TRUE; + __GLeeLink_GL_NV_depth_clamp(); + } + if (__GLeeCheckExtension("GL_NV_occlusion_query", &extensionNames) ) + { + _GLEE_NV_occlusion_query = GL_TRUE; + __GLeeLink_GL_NV_occlusion_query(); + } + if (__GLeeCheckExtension("GL_NV_point_sprite", &extensionNames) ) + { + _GLEE_NV_point_sprite = GL_TRUE; + __GLeeLink_GL_NV_point_sprite(); + } + if (__GLeeCheckExtension("GL_NV_texture_shader3", &extensionNames) ) + { + _GLEE_NV_texture_shader3 = GL_TRUE; + __GLeeLink_GL_NV_texture_shader3(); + } + if (__GLeeCheckExtension("GL_NV_vertex_program1_1", &extensionNames) ) + { + _GLEE_NV_vertex_program1_1 = GL_TRUE; + __GLeeLink_GL_NV_vertex_program1_1(); + } + if (__GLeeCheckExtension("GL_EXT_shadow_funcs", &extensionNames) ) + { + _GLEE_EXT_shadow_funcs = GL_TRUE; + __GLeeLink_GL_EXT_shadow_funcs(); + } + if (__GLeeCheckExtension("GL_EXT_stencil_two_side", &extensionNames) ) + { + _GLEE_EXT_stencil_two_side = GL_TRUE; + __GLeeLink_GL_EXT_stencil_two_side(); + } + if (__GLeeCheckExtension("GL_ATI_text_fragment_shader", &extensionNames) ) + { + _GLEE_ATI_text_fragment_shader = GL_TRUE; + __GLeeLink_GL_ATI_text_fragment_shader(); + } + if (__GLeeCheckExtension("GL_APPLE_client_storage", &extensionNames) ) + { + _GLEE_APPLE_client_storage = GL_TRUE; + __GLeeLink_GL_APPLE_client_storage(); + } + if (__GLeeCheckExtension("GL_APPLE_element_array", &extensionNames) ) + { + _GLEE_APPLE_element_array = GL_TRUE; + __GLeeLink_GL_APPLE_element_array(); + } + if (__GLeeCheckExtension("GL_APPLE_fence", &extensionNames) ) + { + _GLEE_APPLE_fence = GL_TRUE; + __GLeeLink_GL_APPLE_fence(); + } + if (__GLeeCheckExtension("GL_APPLE_vertex_array_object", &extensionNames) ) + { + _GLEE_APPLE_vertex_array_object = GL_TRUE; + __GLeeLink_GL_APPLE_vertex_array_object(); + } + if (__GLeeCheckExtension("GL_APPLE_vertex_array_range", &extensionNames) ) + { + _GLEE_APPLE_vertex_array_range = GL_TRUE; + __GLeeLink_GL_APPLE_vertex_array_range(); + } + if (__GLeeCheckExtension("GL_APPLE_ycbcr_422", &extensionNames) ) + { + _GLEE_APPLE_ycbcr_422 = GL_TRUE; + __GLeeLink_GL_APPLE_ycbcr_422(); + } + if (__GLeeCheckExtension("GL_S3_s3tc", &extensionNames) ) + { + _GLEE_S3_s3tc = GL_TRUE; + __GLeeLink_GL_S3_s3tc(); + } + if (__GLeeCheckExtension("GL_ATI_draw_buffers", &extensionNames) ) + { + _GLEE_ATI_draw_buffers = GL_TRUE; + __GLeeLink_GL_ATI_draw_buffers(); + } + if (__GLeeCheckExtension("GL_ATI_pixel_format_float", &extensionNames) ) + { + _GLEE_ATI_pixel_format_float = GL_TRUE; + __GLeeLink_GL_ATI_pixel_format_float(); + } + if (__GLeeCheckExtension("GL_ATI_texture_env_combine3", &extensionNames) ) + { + _GLEE_ATI_texture_env_combine3 = GL_TRUE; + __GLeeLink_GL_ATI_texture_env_combine3(); + } + if (__GLeeCheckExtension("GL_ATI_texture_float", &extensionNames) ) + { + _GLEE_ATI_texture_float = GL_TRUE; + __GLeeLink_GL_ATI_texture_float(); + } + if (__GLeeCheckExtension("GL_NV_float_buffer", &extensionNames) ) + { + _GLEE_NV_float_buffer = GL_TRUE; + __GLeeLink_GL_NV_float_buffer(); + } + if (__GLeeCheckExtension("GL_NV_fragment_program", &extensionNames) ) + { + _GLEE_NV_fragment_program = GL_TRUE; + __GLeeLink_GL_NV_fragment_program(); + } + if (__GLeeCheckExtension("GL_NV_half_float", &extensionNames) ) + { + _GLEE_NV_half_float = GL_TRUE; + __GLeeLink_GL_NV_half_float(); + } + if (__GLeeCheckExtension("GL_NV_pixel_data_range", &extensionNames) ) + { + _GLEE_NV_pixel_data_range = GL_TRUE; + __GLeeLink_GL_NV_pixel_data_range(); + } + if (__GLeeCheckExtension("GL_NV_primitive_restart", &extensionNames) ) + { + _GLEE_NV_primitive_restart = GL_TRUE; + __GLeeLink_GL_NV_primitive_restart(); + } + if (__GLeeCheckExtension("GL_NV_texture_expand_normal", &extensionNames) ) + { + _GLEE_NV_texture_expand_normal = GL_TRUE; + __GLeeLink_GL_NV_texture_expand_normal(); + } + if (__GLeeCheckExtension("GL_NV_vertex_program2", &extensionNames) ) + { + _GLEE_NV_vertex_program2 = GL_TRUE; + __GLeeLink_GL_NV_vertex_program2(); + } + if (__GLeeCheckExtension("GL_ATI_map_object_buffer", &extensionNames) ) + { + _GLEE_ATI_map_object_buffer = GL_TRUE; + __GLeeLink_GL_ATI_map_object_buffer(); + } + if (__GLeeCheckExtension("GL_ATI_separate_stencil", &extensionNames) ) + { + _GLEE_ATI_separate_stencil = GL_TRUE; + __GLeeLink_GL_ATI_separate_stencil(); + } + if (__GLeeCheckExtension("GL_ATI_vertex_attrib_array_object", &extensionNames) ) + { + _GLEE_ATI_vertex_attrib_array_object = GL_TRUE; + __GLeeLink_GL_ATI_vertex_attrib_array_object(); + } + if (__GLeeCheckExtension("GL_OES_read_format", &extensionNames) ) + { + _GLEE_OES_read_format = GL_TRUE; + __GLeeLink_GL_OES_read_format(); + } + if (__GLeeCheckExtension("GL_EXT_depth_bounds_test", &extensionNames) ) + { + _GLEE_EXT_depth_bounds_test = GL_TRUE; + __GLeeLink_GL_EXT_depth_bounds_test(); + } + if (__GLeeCheckExtension("GL_EXT_texture_mirror_clamp", &extensionNames) ) + { + _GLEE_EXT_texture_mirror_clamp = GL_TRUE; + __GLeeLink_GL_EXT_texture_mirror_clamp(); + } + if (__GLeeCheckExtension("GL_EXT_blend_equation_separate", &extensionNames) ) + { + _GLEE_EXT_blend_equation_separate = GL_TRUE; + __GLeeLink_GL_EXT_blend_equation_separate(); + } + if (__GLeeCheckExtension("GL_MESA_pack_invert", &extensionNames) ) + { + _GLEE_MESA_pack_invert = GL_TRUE; + __GLeeLink_GL_MESA_pack_invert(); + } + if (__GLeeCheckExtension("GL_MESA_ycbcr_texture", &extensionNames) ) + { + _GLEE_MESA_ycbcr_texture = GL_TRUE; + __GLeeLink_GL_MESA_ycbcr_texture(); + } + if (__GLeeCheckExtension("GL_EXT_pixel_buffer_object", &extensionNames) ) + { + _GLEE_EXT_pixel_buffer_object = GL_TRUE; + __GLeeLink_GL_EXT_pixel_buffer_object(); + } + if (__GLeeCheckExtension("GL_NV_fragment_program_option", &extensionNames) ) + { + _GLEE_NV_fragment_program_option = GL_TRUE; + __GLeeLink_GL_NV_fragment_program_option(); + } + if (__GLeeCheckExtension("GL_NV_fragment_program2", &extensionNames) ) + { + _GLEE_NV_fragment_program2 = GL_TRUE; + __GLeeLink_GL_NV_fragment_program2(); + } + if (__GLeeCheckExtension("GL_NV_vertex_program2_option", &extensionNames) ) + { + _GLEE_NV_vertex_program2_option = GL_TRUE; + __GLeeLink_GL_NV_vertex_program2_option(); + } + if (__GLeeCheckExtension("GL_NV_vertex_program3", &extensionNames) ) + { + _GLEE_NV_vertex_program3 = GL_TRUE; + __GLeeLink_GL_NV_vertex_program3(); + } + if (__GLeeCheckExtension("GL_EXT_framebuffer_object", &extensionNames) ) + { + _GLEE_EXT_framebuffer_object = GL_TRUE; + __GLeeLink_GL_EXT_framebuffer_object(); + } + if (__GLeeCheckExtension("GL_GREMEDY_string_marker", &extensionNames) ) + { + _GLEE_GREMEDY_string_marker = GL_TRUE; + __GLeeLink_GL_GREMEDY_string_marker(); + } + if (__GLeeCheckExtension("GL_EXT_packed_depth_stencil", &extensionNames) ) + { + _GLEE_EXT_packed_depth_stencil = GL_TRUE; + __GLeeLink_GL_EXT_packed_depth_stencil(); + } + if (__GLeeCheckExtension("GL_EXT_stencil_clear_tag", &extensionNames) ) + { + _GLEE_EXT_stencil_clear_tag = GL_TRUE; + __GLeeLink_GL_EXT_stencil_clear_tag(); + } + if (__GLeeCheckExtension("GL_EXT_texture_sRGB", &extensionNames) ) + { + _GLEE_EXT_texture_sRGB = GL_TRUE; + __GLeeLink_GL_EXT_texture_sRGB(); + } + if (__GLeeCheckExtension("GL_EXT_framebuffer_blit", &extensionNames) ) + { + _GLEE_EXT_framebuffer_blit = GL_TRUE; + __GLeeLink_GL_EXT_framebuffer_blit(); + } + if (__GLeeCheckExtension("GL_EXT_framebuffer_multisample", &extensionNames) ) + { + _GLEE_EXT_framebuffer_multisample = GL_TRUE; + __GLeeLink_GL_EXT_framebuffer_multisample(); + } + if (__GLeeCheckExtension("GL_MESAX_texture_stack", &extensionNames) ) + { + _GLEE_MESAX_texture_stack = GL_TRUE; + __GLeeLink_GL_MESAX_texture_stack(); + } + if (__GLeeCheckExtension("GL_EXT_timer_query", &extensionNames) ) + { + _GLEE_EXT_timer_query = GL_TRUE; + __GLeeLink_GL_EXT_timer_query(); + } + if (__GLeeCheckExtension("GL_EXT_gpu_program_parameters", &extensionNames) ) + { + _GLEE_EXT_gpu_program_parameters = GL_TRUE; + __GLeeLink_GL_EXT_gpu_program_parameters(); + } + if (__GLeeCheckExtension("GL_APPLE_flush_buffer_range", &extensionNames) ) + { + _GLEE_APPLE_flush_buffer_range = GL_TRUE; + __GLeeLink_GL_APPLE_flush_buffer_range(); + } + if (__GLeeCheckExtension("GL_EXT_gpu_shader4", &extensionNames) ) + { + _GLEE_EXT_gpu_shader4 = GL_TRUE; + __GLeeLink_GL_EXT_gpu_shader4(); + } + if (__GLeeCheckExtension("GL_EXT_draw_instanced", &extensionNames) ) + { + _GLEE_EXT_draw_instanced = GL_TRUE; + __GLeeLink_GL_EXT_draw_instanced(); + } + if (__GLeeCheckExtension("GL_EXT_packed_float", &extensionNames) ) + { + _GLEE_EXT_packed_float = GL_TRUE; + __GLeeLink_GL_EXT_packed_float(); + } + if (__GLeeCheckExtension("GL_EXT_texture_array", &extensionNames) ) + { + _GLEE_EXT_texture_array = GL_TRUE; + __GLeeLink_GL_EXT_texture_array(); + } + if (__GLeeCheckExtension("GL_EXT_texture_buffer_object", &extensionNames) ) + { + _GLEE_EXT_texture_buffer_object = GL_TRUE; + __GLeeLink_GL_EXT_texture_buffer_object(); + } + if (__GLeeCheckExtension("GL_EXT_texture_compression_latc", &extensionNames) ) + { + _GLEE_EXT_texture_compression_latc = GL_TRUE; + __GLeeLink_GL_EXT_texture_compression_latc(); + } + if (__GLeeCheckExtension("GL_EXT_texture_compression_rgtc", &extensionNames) ) + { + _GLEE_EXT_texture_compression_rgtc = GL_TRUE; + __GLeeLink_GL_EXT_texture_compression_rgtc(); + } + if (__GLeeCheckExtension("GL_EXT_texture_shared_exponent", &extensionNames) ) + { + _GLEE_EXT_texture_shared_exponent = GL_TRUE; + __GLeeLink_GL_EXT_texture_shared_exponent(); + } + if (__GLeeCheckExtension("GL_NV_depth_buffer_float", &extensionNames) ) + { + _GLEE_NV_depth_buffer_float = GL_TRUE; + __GLeeLink_GL_NV_depth_buffer_float(); + } + if (__GLeeCheckExtension("GL_NV_framebuffer_multisample_coverage", &extensionNames) ) + { + _GLEE_NV_framebuffer_multisample_coverage = GL_TRUE; + __GLeeLink_GL_NV_framebuffer_multisample_coverage(); + } + if (__GLeeCheckExtension("GL_EXT_framebuffer_sRGB", &extensionNames) ) + { + _GLEE_EXT_framebuffer_sRGB = GL_TRUE; + __GLeeLink_GL_EXT_framebuffer_sRGB(); + } + if (__GLeeCheckExtension("GL_NV_geometry_shader4", &extensionNames) ) + { + _GLEE_NV_geometry_shader4 = GL_TRUE; + __GLeeLink_GL_NV_geometry_shader4(); + } + if (__GLeeCheckExtension("GL_NV_parameter_buffer_object", &extensionNames) ) + { + _GLEE_NV_parameter_buffer_object = GL_TRUE; + __GLeeLink_GL_NV_parameter_buffer_object(); + } + if (__GLeeCheckExtension("GL_EXT_draw_buffers2", &extensionNames) ) + { + _GLEE_EXT_draw_buffers2 = GL_TRUE; + __GLeeLink_GL_EXT_draw_buffers2(); + } + if (__GLeeCheckExtension("GL_NV_transform_feedback", &extensionNames) ) + { + _GLEE_NV_transform_feedback = GL_TRUE; + __GLeeLink_GL_NV_transform_feedback(); + } + if (__GLeeCheckExtension("GL_EXT_bindable_uniform", &extensionNames) ) + { + _GLEE_EXT_bindable_uniform = GL_TRUE; + __GLeeLink_GL_EXT_bindable_uniform(); + } + if (__GLeeCheckExtension("GL_EXT_texture_integer", &extensionNames) ) + { + _GLEE_EXT_texture_integer = GL_TRUE; + __GLeeLink_GL_EXT_texture_integer(); + } + if (__GLeeCheckExtension("GL_GREMEDY_frame_terminator", &extensionNames) ) + { + _GLEE_GREMEDY_frame_terminator = GL_TRUE; + __GLeeLink_GL_GREMEDY_frame_terminator(); + } + if (__GLeeCheckExtension("GL_NV_conditional_render", &extensionNames) ) + { + _GLEE_NV_conditional_render = GL_TRUE; + __GLeeLink_GL_NV_conditional_render(); + } + if (__GLeeCheckExtension("GL_NV_present_video", &extensionNames) ) + { + _GLEE_NV_present_video = GL_TRUE; + __GLeeLink_GL_NV_present_video(); + } + if (__GLeeCheckExtension("GL_EXT_transform_feedback", &extensionNames) ) + { + _GLEE_EXT_transform_feedback = GL_TRUE; + __GLeeLink_GL_EXT_transform_feedback(); + } + if (__GLeeCheckExtension("GL_EXT_direct_state_access", &extensionNames) ) + { + _GLEE_EXT_direct_state_access = GL_TRUE; + __GLeeLink_GL_EXT_direct_state_access(); + } + if (__GLeeCheckExtension("GL_EXT_vertex_array_bgra", &extensionNames) ) + { + _GLEE_EXT_vertex_array_bgra = GL_TRUE; + __GLeeLink_GL_EXT_vertex_array_bgra(); + } + if (__GLeeCheckExtension("GL_EXT_texture_swizzle", &extensionNames) ) + { + _GLEE_EXT_texture_swizzle = GL_TRUE; + __GLeeLink_GL_EXT_texture_swizzle(); + } + if (__GLeeCheckExtension("GL_NV_explicit_multisample", &extensionNames) ) + { + _GLEE_NV_explicit_multisample = GL_TRUE; + __GLeeLink_GL_NV_explicit_multisample(); + } + if (__GLeeCheckExtension("GL_NV_transform_feedback2", &extensionNames) ) + { + _GLEE_NV_transform_feedback2 = GL_TRUE; + __GLeeLink_GL_NV_transform_feedback2(); + } + if (__GLeeCheckExtension("GL_SGIX_texture_select", &extensionNames) ) + { + _GLEE_SGIX_texture_select = GL_TRUE; + __GLeeLink_GL_SGIX_texture_select(); + } + if (__GLeeCheckExtension("GL_INGR_blend_func_separate", &extensionNames) ) + { + _GLEE_INGR_blend_func_separate = GL_TRUE; + __GLeeLink_GL_INGR_blend_func_separate(); + } + if (__GLeeCheckExtension("GL_SGIX_depth_pass_instrument", &extensionNames) ) + { + _GLEE_SGIX_depth_pass_instrument = GL_TRUE; + __GLeeLink_GL_SGIX_depth_pass_instrument(); + } + if (__GLeeCheckExtension("GL_SGIX_igloo_interface", &extensionNames) ) + { + _GLEE_SGIX_igloo_interface = GL_TRUE; + __GLeeLink_GL_SGIX_igloo_interface(); + } + if (__GLeeCheckExtension("GL_EXT_fragment_lighting", &extensionNames) ) + { + _GLEE_EXT_fragment_lighting = GL_TRUE; + __GLeeLink_GL_EXT_fragment_lighting(); + } + if (__GLeeCheckExtension("GL_EXT_geometry_shader4", &extensionNames) ) + { + _GLEE_EXT_geometry_shader4 = GL_TRUE; + __GLeeLink_GL_EXT_geometry_shader4(); + } + if (__GLeeCheckExtension("GL_EXT_scene_marker", &extensionNames) ) + { + _GLEE_EXT_scene_marker = GL_TRUE; + __GLeeLink_GL_EXT_scene_marker(); + } + if (__GLeeCheckExtension("GL_EXT_texture_compression_dxt1", &extensionNames) ) + { + _GLEE_EXT_texture_compression_dxt1 = GL_TRUE; + __GLeeLink_GL_EXT_texture_compression_dxt1(); + } + if (__GLeeCheckExtension("GL_EXT_texture_env", &extensionNames) ) + { + _GLEE_EXT_texture_env = GL_TRUE; + __GLeeLink_GL_EXT_texture_env(); + } + if (__GLeeCheckExtension("GL_IBM_static_data", &extensionNames) ) + { + _GLEE_IBM_static_data = GL_TRUE; + __GLeeLink_GL_IBM_static_data(); + } + if (__GLeeCheckExtension("GL_NV_gpu_program4", &extensionNames) ) + { + _GLEE_NV_gpu_program4 = GL_TRUE; + __GLeeLink_GL_NV_gpu_program4(); + } + if (__GLeeCheckExtension("GL_OES_byte_coordinates", &extensionNames) ) + { + _GLEE_OES_byte_coordinates = GL_TRUE; + __GLeeLink_GL_OES_byte_coordinates(); + } + if (__GLeeCheckExtension("GL_OES_compressed_paletted_texture", &extensionNames) ) + { + _GLEE_OES_compressed_paletted_texture = GL_TRUE; + __GLeeLink_GL_OES_compressed_paletted_texture(); + } + if (__GLeeCheckExtension("GL_OES_single_precision", &extensionNames) ) + { + _GLEE_OES_single_precision = GL_TRUE; + __GLeeLink_GL_OES_single_precision(); + } + if (__GLeeCheckExtension("GL_SGIX_pixel_texture_bits", &extensionNames) ) + { + _GLEE_SGIX_pixel_texture_bits = GL_TRUE; + __GLeeLink_GL_SGIX_pixel_texture_bits(); + } + if (__GLeeCheckExtension("GL_SGIX_texture_range", &extensionNames) ) + { + _GLEE_SGIX_texture_range = GL_TRUE; + __GLeeLink_GL_SGIX_texture_range(); + } +#ifdef WIN32 + if (__GLeeCheckExtension("WGL_ARB_buffer_region", &extensionNames) ) + { + _GLEE_WGL_ARB_buffer_region = GL_TRUE; + __GLeeLink_WGL_ARB_buffer_region(); + } + if (__GLeeCheckExtension("WGL_ARB_multisample", &extensionNames) ) + { + _GLEE_WGL_ARB_multisample = GL_TRUE; + __GLeeLink_WGL_ARB_multisample(); + } + if (__GLeeCheckExtension("WGL_ARB_extensions_string", &extensionNames) ) + { + _GLEE_WGL_ARB_extensions_string = GL_TRUE; + __GLeeLink_WGL_ARB_extensions_string(); + } + if (__GLeeCheckExtension("WGL_ARB_pixel_format", &extensionNames) ) + { + _GLEE_WGL_ARB_pixel_format = GL_TRUE; + __GLeeLink_WGL_ARB_pixel_format(); + } + if (__GLeeCheckExtension("WGL_ARB_make_current_read", &extensionNames) ) + { + _GLEE_WGL_ARB_make_current_read = GL_TRUE; + __GLeeLink_WGL_ARB_make_current_read(); + } + if (__GLeeCheckExtension("WGL_ARB_pbuffer", &extensionNames) ) + { + _GLEE_WGL_ARB_pbuffer = GL_TRUE; + __GLeeLink_WGL_ARB_pbuffer(); + } + if (__GLeeCheckExtension("WGL_ARB_render_texture", &extensionNames) ) + { + _GLEE_WGL_ARB_render_texture = GL_TRUE; + __GLeeLink_WGL_ARB_render_texture(); + } + if (__GLeeCheckExtension("WGL_ARB_pixel_format_float", &extensionNames) ) + { + _GLEE_WGL_ARB_pixel_format_float = GL_TRUE; + __GLeeLink_WGL_ARB_pixel_format_float(); + } + if (__GLeeCheckExtension("WGL_ARB_create_context", &extensionNames) ) + { + _GLEE_WGL_ARB_create_context = GL_TRUE; + __GLeeLink_WGL_ARB_create_context(); + } + if (__GLeeCheckExtension("WGL_EXT_make_current_read", &extensionNames) ) + { + _GLEE_WGL_EXT_make_current_read = GL_TRUE; + __GLeeLink_WGL_EXT_make_current_read(); + } + if (__GLeeCheckExtension("WGL_EXT_pixel_format", &extensionNames) ) + { + _GLEE_WGL_EXT_pixel_format = GL_TRUE; + __GLeeLink_WGL_EXT_pixel_format(); + } + if (__GLeeCheckExtension("WGL_EXT_pbuffer", &extensionNames) ) + { + _GLEE_WGL_EXT_pbuffer = GL_TRUE; + __GLeeLink_WGL_EXT_pbuffer(); + } + if (__GLeeCheckExtension("WGL_EXT_depth_float", &extensionNames) ) + { + _GLEE_WGL_EXT_depth_float = GL_TRUE; + __GLeeLink_WGL_EXT_depth_float(); + } + if (__GLeeCheckExtension("WGL_3DFX_multisample", &extensionNames) ) + { + _GLEE_WGL_3DFX_multisample = GL_TRUE; + __GLeeLink_WGL_3DFX_multisample(); + } + if (__GLeeCheckExtension("WGL_EXT_multisample", &extensionNames) ) + { + _GLEE_WGL_EXT_multisample = GL_TRUE; + __GLeeLink_WGL_EXT_multisample(); + } + if (__GLeeCheckExtension("WGL_I3D_digital_video_control", &extensionNames) ) + { + _GLEE_WGL_I3D_digital_video_control = GL_TRUE; + __GLeeLink_WGL_I3D_digital_video_control(); + } + if (__GLeeCheckExtension("WGL_I3D_gamma", &extensionNames) ) + { + _GLEE_WGL_I3D_gamma = GL_TRUE; + __GLeeLink_WGL_I3D_gamma(); + } + if (__GLeeCheckExtension("WGL_I3D_genlock", &extensionNames) ) + { + _GLEE_WGL_I3D_genlock = GL_TRUE; + __GLeeLink_WGL_I3D_genlock(); + } + if (__GLeeCheckExtension("WGL_I3D_image_buffer", &extensionNames) ) + { + _GLEE_WGL_I3D_image_buffer = GL_TRUE; + __GLeeLink_WGL_I3D_image_buffer(); + } + if (__GLeeCheckExtension("WGL_I3D_swap_frame_lock", &extensionNames) ) + { + _GLEE_WGL_I3D_swap_frame_lock = GL_TRUE; + __GLeeLink_WGL_I3D_swap_frame_lock(); + } + if (__GLeeCheckExtension("WGL_NV_render_depth_texture", &extensionNames) ) + { + _GLEE_WGL_NV_render_depth_texture = GL_TRUE; + __GLeeLink_WGL_NV_render_depth_texture(); + } + if (__GLeeCheckExtension("WGL_NV_render_texture_rectangle", &extensionNames) ) + { + _GLEE_WGL_NV_render_texture_rectangle = GL_TRUE; + __GLeeLink_WGL_NV_render_texture_rectangle(); + } + if (__GLeeCheckExtension("WGL_ATI_pixel_format_float", &extensionNames) ) + { + _GLEE_WGL_ATI_pixel_format_float = GL_TRUE; + __GLeeLink_WGL_ATI_pixel_format_float(); + } + if (__GLeeCheckExtension("WGL_NV_float_buffer", &extensionNames) ) + { + _GLEE_WGL_NV_float_buffer = GL_TRUE; + __GLeeLink_WGL_NV_float_buffer(); + } + if (__GLeeCheckExtension("WGL_3DL_stereo_control", &extensionNames) ) + { + _GLEE_WGL_3DL_stereo_control = GL_TRUE; + __GLeeLink_WGL_3DL_stereo_control(); + } + if (__GLeeCheckExtension("WGL_EXT_pixel_format_packed_float", &extensionNames) ) + { + _GLEE_WGL_EXT_pixel_format_packed_float = GL_TRUE; + __GLeeLink_WGL_EXT_pixel_format_packed_float(); + } + if (__GLeeCheckExtension("WGL_EXT_framebuffer_sRGB", &extensionNames) ) + { + _GLEE_WGL_EXT_framebuffer_sRGB = GL_TRUE; + __GLeeLink_WGL_EXT_framebuffer_sRGB(); + } + if (__GLeeCheckExtension("WGL_NV_present_video", &extensionNames) ) + { + _GLEE_WGL_NV_present_video = GL_TRUE; + __GLeeLink_WGL_NV_present_video(); + } + if (__GLeeCheckExtension("WGL_NV_swap_group", &extensionNames) ) + { + _GLEE_WGL_NV_swap_group = GL_TRUE; + __GLeeLink_WGL_NV_swap_group(); + } + if (__GLeeCheckExtension("WGL_NV_gpu_affinity", &extensionNames) ) + { + _GLEE_WGL_NV_gpu_affinity = GL_TRUE; + __GLeeLink_WGL_NV_gpu_affinity(); + } + if (__GLeeCheckExtension("WGL_EXT_display_color_table", &extensionNames) ) + { + _GLEE_WGL_EXT_display_color_table = GL_TRUE; + __GLeeLink_WGL_EXT_display_color_table(); + } + if (__GLeeCheckExtension("WGL_EXT_extensions_string", &extensionNames) ) + { + _GLEE_WGL_EXT_extensions_string = GL_TRUE; + __GLeeLink_WGL_EXT_extensions_string(); + } + if (__GLeeCheckExtension("WGL_EXT_swap_control", &extensionNames) ) + { + _GLEE_WGL_EXT_swap_control = GL_TRUE; + __GLeeLink_WGL_EXT_swap_control(); + } + if (__GLeeCheckExtension("WGL_NV_vertex_array_range", &extensionNames) ) + { + _GLEE_WGL_NV_vertex_array_range = GL_TRUE; + __GLeeLink_WGL_NV_vertex_array_range(); + } + if (__GLeeCheckExtension("WGL_OML_sync_control", &extensionNames) ) + { + _GLEE_WGL_OML_sync_control = GL_TRUE; + __GLeeLink_WGL_OML_sync_control(); + } + if (__GLeeCheckExtension("WGL_I3D_swap_frame_usage", &extensionNames) ) + { + _GLEE_WGL_I3D_swap_frame_usage = GL_TRUE; + __GLeeLink_WGL_I3D_swap_frame_usage(); + } + if (__GLeeCheckExtension("WGL_NV_video_output", &extensionNames) ) + { + _GLEE_WGL_NV_video_output = GL_TRUE; + __GLeeLink_WGL_NV_video_output(); + } +#elif defined(__APPLE__) || defined(__APPLE_CC__) +#else /* GLX */ + if (__GLeeCheckExtension("GLX_VERSION_1_3", &extensionNames) ) + { + _GLEE_GLX_VERSION_1_3 = GL_TRUE; + __GLeeLink_GLX_VERSION_1_3(); + } + if (__GLeeCheckExtension("GLX_VERSION_1_4", &extensionNames) ) + { + _GLEE_GLX_VERSION_1_4 = GL_TRUE; + __GLeeLink_GLX_VERSION_1_4(); + } + if (__GLeeCheckExtension("GLX_ARB_multisample", &extensionNames) ) + { + _GLEE_GLX_ARB_multisample = GL_TRUE; + __GLeeLink_GLX_ARB_multisample(); + } + if (__GLeeCheckExtension("GLX_ARB_fbconfig_float", &extensionNames) ) + { + _GLEE_GLX_ARB_fbconfig_float = GL_TRUE; + __GLeeLink_GLX_ARB_fbconfig_float(); + } + if (__GLeeCheckExtension("GLX_ARB_create_context", &extensionNames) ) + { + _GLEE_GLX_ARB_create_context = GL_TRUE; + __GLeeLink_GLX_ARB_create_context(); + } + if (__GLeeCheckExtension("GLX_SGIS_multisample", &extensionNames) ) + { + _GLEE_GLX_SGIS_multisample = GL_TRUE; + __GLeeLink_GLX_SGIS_multisample(); + } + if (__GLeeCheckExtension("GLX_EXT_visual_info", &extensionNames) ) + { + _GLEE_GLX_EXT_visual_info = GL_TRUE; + __GLeeLink_GLX_EXT_visual_info(); + } + if (__GLeeCheckExtension("GLX_SGI_swap_control", &extensionNames) ) + { + _GLEE_GLX_SGI_swap_control = GL_TRUE; + __GLeeLink_GLX_SGI_swap_control(); + } + if (__GLeeCheckExtension("GLX_SGI_video_sync", &extensionNames) ) + { + _GLEE_GLX_SGI_video_sync = GL_TRUE; + __GLeeLink_GLX_SGI_video_sync(); + } + if (__GLeeCheckExtension("GLX_SGI_make_current_read", &extensionNames) ) + { + _GLEE_GLX_SGI_make_current_read = GL_TRUE; + __GLeeLink_GLX_SGI_make_current_read(); + } + if (__GLeeCheckExtension("GLX_EXT_visual_rating", &extensionNames) ) + { + _GLEE_GLX_EXT_visual_rating = GL_TRUE; + __GLeeLink_GLX_EXT_visual_rating(); + } + if (__GLeeCheckExtension("GLX_EXT_import_context", &extensionNames) ) + { + _GLEE_GLX_EXT_import_context = GL_TRUE; + __GLeeLink_GLX_EXT_import_context(); + } + if (__GLeeCheckExtension("GLX_SGIX_fbconfig", &extensionNames) ) + { + _GLEE_GLX_SGIX_fbconfig = GL_TRUE; + __GLeeLink_GLX_SGIX_fbconfig(); + } + if (__GLeeCheckExtension("GLX_SGIX_pbuffer", &extensionNames) ) + { + _GLEE_GLX_SGIX_pbuffer = GL_TRUE; + __GLeeLink_GLX_SGIX_pbuffer(); + } + if (__GLeeCheckExtension("GLX_SGI_cushion", &extensionNames) ) + { + _GLEE_GLX_SGI_cushion = GL_TRUE; + __GLeeLink_GLX_SGI_cushion(); + } + if (__GLeeCheckExtension("GLX_SGIX_video_resize", &extensionNames) ) + { + _GLEE_GLX_SGIX_video_resize = GL_TRUE; + __GLeeLink_GLX_SGIX_video_resize(); + } + if (__GLeeCheckExtension("GLX_SGIX_swap_group", &extensionNames) ) + { + _GLEE_GLX_SGIX_swap_group = GL_TRUE; + __GLeeLink_GLX_SGIX_swap_group(); + } + if (__GLeeCheckExtension("GLX_SGIX_swap_barrier", &extensionNames) ) + { + _GLEE_GLX_SGIX_swap_barrier = GL_TRUE; + __GLeeLink_GLX_SGIX_swap_barrier(); + } + if (__GLeeCheckExtension("GLX_SGIS_blended_overlay", &extensionNames) ) + { + _GLEE_GLX_SGIS_blended_overlay = GL_TRUE; + __GLeeLink_GLX_SGIS_blended_overlay(); + } + if (__GLeeCheckExtension("GLX_SGIS_shared_multisample", &extensionNames) ) + { + _GLEE_GLX_SGIS_shared_multisample = GL_TRUE; + __GLeeLink_GLX_SGIS_shared_multisample(); + } + if (__GLeeCheckExtension("GLX_SUN_get_transparent_index", &extensionNames) ) + { + _GLEE_GLX_SUN_get_transparent_index = GL_TRUE; + __GLeeLink_GLX_SUN_get_transparent_index(); + } + if (__GLeeCheckExtension("GLX_3DFX_multisample", &extensionNames) ) + { + _GLEE_GLX_3DFX_multisample = GL_TRUE; + __GLeeLink_GLX_3DFX_multisample(); + } + if (__GLeeCheckExtension("GLX_MESA_copy_sub_buffer", &extensionNames) ) + { + _GLEE_GLX_MESA_copy_sub_buffer = GL_TRUE; + __GLeeLink_GLX_MESA_copy_sub_buffer(); + } + if (__GLeeCheckExtension("GLX_MESA_pixmap_colormap", &extensionNames) ) + { + _GLEE_GLX_MESA_pixmap_colormap = GL_TRUE; + __GLeeLink_GLX_MESA_pixmap_colormap(); + } + if (__GLeeCheckExtension("GLX_MESA_release_buffers", &extensionNames) ) + { + _GLEE_GLX_MESA_release_buffers = GL_TRUE; + __GLeeLink_GLX_MESA_release_buffers(); + } + if (__GLeeCheckExtension("GLX_MESA_set_3dfx_mode", &extensionNames) ) + { + _GLEE_GLX_MESA_set_3dfx_mode = GL_TRUE; + __GLeeLink_GLX_MESA_set_3dfx_mode(); + } + if (__GLeeCheckExtension("GLX_SGIX_visual_select_group", &extensionNames) ) + { + _GLEE_GLX_SGIX_visual_select_group = GL_TRUE; + __GLeeLink_GLX_SGIX_visual_select_group(); + } + if (__GLeeCheckExtension("GLX_OML_swap_method", &extensionNames) ) + { + _GLEE_GLX_OML_swap_method = GL_TRUE; + __GLeeLink_GLX_OML_swap_method(); + } + if (__GLeeCheckExtension("GLX_OML_sync_control", &extensionNames) ) + { + _GLEE_GLX_OML_sync_control = GL_TRUE; + __GLeeLink_GLX_OML_sync_control(); + } + if (__GLeeCheckExtension("GLX_NV_float_buffer", &extensionNames) ) + { + _GLEE_GLX_NV_float_buffer = GL_TRUE; + __GLeeLink_GLX_NV_float_buffer(); + } + if (__GLeeCheckExtension("GLX_SGIX_hyperpipe", &extensionNames) ) + { + _GLEE_GLX_SGIX_hyperpipe = GL_TRUE; + __GLeeLink_GLX_SGIX_hyperpipe(); + } + if (__GLeeCheckExtension("GLX_MESA_agp_offset", &extensionNames) ) + { + _GLEE_GLX_MESA_agp_offset = GL_TRUE; + __GLeeLink_GLX_MESA_agp_offset(); + } + if (__GLeeCheckExtension("GLX_EXT_fbconfig_packed_float", &extensionNames) ) + { + _GLEE_GLX_EXT_fbconfig_packed_float = GL_TRUE; + __GLeeLink_GLX_EXT_fbconfig_packed_float(); + } + if (__GLeeCheckExtension("GLX_EXT_framebuffer_sRGB", &extensionNames) ) + { + _GLEE_GLX_EXT_framebuffer_sRGB = GL_TRUE; + __GLeeLink_GLX_EXT_framebuffer_sRGB(); + } + if (__GLeeCheckExtension("GLX_EXT_texture_from_pixmap", &extensionNames) ) + { + _GLEE_GLX_EXT_texture_from_pixmap = GL_TRUE; + __GLeeLink_GLX_EXT_texture_from_pixmap(); + } + if (__GLeeCheckExtension("GLX_NV_present_video", &extensionNames) ) + { + _GLEE_GLX_NV_present_video = GL_TRUE; + __GLeeLink_GLX_NV_present_video(); + } + if (__GLeeCheckExtension("GLX_NV_video_out", &extensionNames) ) + { + _GLEE_GLX_NV_video_out = GL_TRUE; + __GLeeLink_GLX_NV_video_out(); + } + if (__GLeeCheckExtension("GLX_NV_swap_group", &extensionNames) ) + { + _GLEE_GLX_NV_swap_group = GL_TRUE; + __GLeeLink_GLX_NV_swap_group(); + } + if (__GLeeCheckExtension("GLX_EXT_scene_marker", &extensionNames) ) + { + _GLEE_GLX_EXT_scene_marker = GL_TRUE; + __GLeeLink_GLX_EXT_scene_marker(); + } + if (__GLeeCheckExtension("GLX_NV_video_output", &extensionNames) ) + { + _GLEE_GLX_NV_video_output = GL_TRUE; + __GLeeLink_GLX_NV_video_output(); + } +#endif /* end GLX */ + + __GLeeExtList_clean(&extensionNames); + return GL_TRUE; +} diff --git a/Extras/sph/common/GLee.h b/Extras/sph/common/GLee.h new file mode 100644 index 0000000..8987d24 --- /dev/null +++ b/Extras/sph/common/GLee.h @@ -0,0 +1,17647 @@ +/*************************************************************************** +* +* GLee.h +* GLee (OpenGL Easy Extension library) +* Version : 5.4 +* +* Copyright (c)2009 Ben Woodhouse All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer as +* the first lines of this file unmodified. +* 2. 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. +* +* THIS SOFTWARE IS PROVIDED BY BEN WOODHOUSE ``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 BEN WOODHOUSE 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. + +* Web: http://elf-stone.com/glee.php +* +* [This file was automatically generated by GLeeGen 7.0 +* +***************************************************************************/ + +#ifndef __glee_h_ +#define __glee_h_ + +#ifdef __gl_h_ + #error gl.h included before glee.h +#endif + +#ifdef __glext_h_ + #error glext.h included before glee.h +#endif + +#ifdef __wglext_h_ + #error wglext.h included before glee.h +#endif + +#ifdef __glxext_h_ + #error glxext.h included before glee.h +#endif + +#ifdef WIN32 + #define WIN32_LEAN_AND_MEAN + #include + #include +#elif defined(__APPLE__) || defined(__APPLE_CC__) + #define GL_GLEXT_LEGACY + #include +#else // GLX + #define __glext_h_ /* prevent glext.h from being included */ + #define __glxext_h_ /* prevent glxext.h from being included */ + #define GLX_GLXEXT_PROTOTYPES + #include + #include +#endif + +#ifndef APIENTRY + #define APIENTRY +#endif + +#ifndef APIENTRYP + #define APIENTRYP APIENTRY * +#endif + +#define GLEE_EXTERN extern + +#ifdef __cplusplus + extern "C" { /* begin C linkage */ +#endif + +#define GLEE_LINK_FAIL 0 +#define GLEE_LINK_PARTIAL 1 +#define GLEE_LINK_COMPLETE 2 + +/* Extension querying variables */ + +GLEE_EXTERN GLboolean _GLEE_VERSION_1_2; +GLEE_EXTERN GLboolean _GLEE_ARB_imaging; +GLEE_EXTERN GLboolean _GLEE_VERSION_1_3; +GLEE_EXTERN GLboolean _GLEE_VERSION_1_4; +GLEE_EXTERN GLboolean _GLEE_VERSION_1_5; +GLEE_EXTERN GLboolean _GLEE_VERSION_2_0; +GLEE_EXTERN GLboolean _GLEE_VERSION_2_1; +GLEE_EXTERN GLboolean _GLEE_VERSION_3_0; +GLEE_EXTERN GLboolean _GLEE_ARB_multitexture; +GLEE_EXTERN GLboolean _GLEE_ARB_transpose_matrix; +GLEE_EXTERN GLboolean _GLEE_ARB_multisample; +GLEE_EXTERN GLboolean _GLEE_ARB_texture_env_add; +GLEE_EXTERN GLboolean _GLEE_ARB_texture_cube_map; +GLEE_EXTERN GLboolean _GLEE_ARB_texture_compression; +GLEE_EXTERN GLboolean _GLEE_ARB_texture_border_clamp; +GLEE_EXTERN GLboolean _GLEE_ARB_point_parameters; +GLEE_EXTERN GLboolean _GLEE_ARB_vertex_blend; +GLEE_EXTERN GLboolean _GLEE_ARB_matrix_palette; +GLEE_EXTERN GLboolean _GLEE_ARB_texture_env_combine; +GLEE_EXTERN GLboolean _GLEE_ARB_texture_env_crossbar; +GLEE_EXTERN GLboolean _GLEE_ARB_texture_env_dot3; +GLEE_EXTERN GLboolean _GLEE_ARB_texture_mirrored_repeat; +GLEE_EXTERN GLboolean _GLEE_ARB_depth_texture; +GLEE_EXTERN GLboolean _GLEE_ARB_shadow; +GLEE_EXTERN GLboolean _GLEE_ARB_shadow_ambient; +GLEE_EXTERN GLboolean _GLEE_ARB_window_pos; +GLEE_EXTERN GLboolean _GLEE_ARB_vertex_program; +GLEE_EXTERN GLboolean _GLEE_ARB_fragment_program; +GLEE_EXTERN GLboolean _GLEE_ARB_vertex_buffer_object; +GLEE_EXTERN GLboolean _GLEE_ARB_occlusion_query; +GLEE_EXTERN GLboolean _GLEE_ARB_shader_objects; +GLEE_EXTERN GLboolean _GLEE_ARB_vertex_shader; +GLEE_EXTERN GLboolean _GLEE_ARB_fragment_shader; +GLEE_EXTERN GLboolean _GLEE_ARB_shading_language_100; +GLEE_EXTERN GLboolean _GLEE_ARB_texture_non_power_of_two; +GLEE_EXTERN GLboolean _GLEE_ARB_point_sprite; +GLEE_EXTERN GLboolean _GLEE_ARB_fragment_program_shadow; +GLEE_EXTERN GLboolean _GLEE_ARB_draw_buffers; +GLEE_EXTERN GLboolean _GLEE_ARB_texture_rectangle; +GLEE_EXTERN GLboolean _GLEE_ARB_color_buffer_float; +GLEE_EXTERN GLboolean _GLEE_ARB_half_float_pixel; +GLEE_EXTERN GLboolean _GLEE_ARB_texture_float; +GLEE_EXTERN GLboolean _GLEE_ARB_pixel_buffer_object; +GLEE_EXTERN GLboolean _GLEE_ARB_depth_buffer_float; +GLEE_EXTERN GLboolean _GLEE_ARB_draw_instanced; +GLEE_EXTERN GLboolean _GLEE_ARB_framebuffer_object; +GLEE_EXTERN GLboolean _GLEE_ARB_framebuffer_sRGB; +GLEE_EXTERN GLboolean _GLEE_ARB_geometry_shader4; +GLEE_EXTERN GLboolean _GLEE_ARB_half_float_vertex; +GLEE_EXTERN GLboolean _GLEE_ARB_instanced_arrays; +GLEE_EXTERN GLboolean _GLEE_ARB_map_buffer_range; +GLEE_EXTERN GLboolean _GLEE_ARB_texture_buffer_object; +GLEE_EXTERN GLboolean _GLEE_ARB_texture_compression_rgtc; +GLEE_EXTERN GLboolean _GLEE_ARB_texture_rg; +GLEE_EXTERN GLboolean _GLEE_ARB_vertex_array_object; +GLEE_EXTERN GLboolean _GLEE_EXT_abgr; +GLEE_EXTERN GLboolean _GLEE_EXT_blend_color; +GLEE_EXTERN GLboolean _GLEE_EXT_polygon_offset; +GLEE_EXTERN GLboolean _GLEE_EXT_texture; +GLEE_EXTERN GLboolean _GLEE_EXT_texture3D; +GLEE_EXTERN GLboolean _GLEE_SGIS_texture_filter4; +GLEE_EXTERN GLboolean _GLEE_EXT_subtexture; +GLEE_EXTERN GLboolean _GLEE_EXT_copy_texture; +GLEE_EXTERN GLboolean _GLEE_EXT_histogram; +GLEE_EXTERN GLboolean _GLEE_EXT_convolution; +GLEE_EXTERN GLboolean _GLEE_SGI_color_matrix; +GLEE_EXTERN GLboolean _GLEE_SGI_color_table; +GLEE_EXTERN GLboolean _GLEE_SGIS_pixel_texture; +GLEE_EXTERN GLboolean _GLEE_SGIX_pixel_texture; +GLEE_EXTERN GLboolean _GLEE_SGIS_texture4D; +GLEE_EXTERN GLboolean _GLEE_SGI_texture_color_table; +GLEE_EXTERN GLboolean _GLEE_EXT_cmyka; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_object; +GLEE_EXTERN GLboolean _GLEE_SGIS_detail_texture; +GLEE_EXTERN GLboolean _GLEE_SGIS_sharpen_texture; +GLEE_EXTERN GLboolean _GLEE_EXT_packed_pixels; +GLEE_EXTERN GLboolean _GLEE_SGIS_texture_lod; +GLEE_EXTERN GLboolean _GLEE_SGIS_multisample; +GLEE_EXTERN GLboolean _GLEE_EXT_rescale_normal; +GLEE_EXTERN GLboolean _GLEE_EXT_vertex_array; +GLEE_EXTERN GLboolean _GLEE_EXT_misc_attribute; +GLEE_EXTERN GLboolean _GLEE_SGIS_generate_mipmap; +GLEE_EXTERN GLboolean _GLEE_SGIX_clipmap; +GLEE_EXTERN GLboolean _GLEE_SGIX_shadow; +GLEE_EXTERN GLboolean _GLEE_SGIS_texture_edge_clamp; +GLEE_EXTERN GLboolean _GLEE_SGIS_texture_border_clamp; +GLEE_EXTERN GLboolean _GLEE_EXT_blend_minmax; +GLEE_EXTERN GLboolean _GLEE_EXT_blend_subtract; +GLEE_EXTERN GLboolean _GLEE_EXT_blend_logic_op; +GLEE_EXTERN GLboolean _GLEE_SGIX_interlace; +GLEE_EXTERN GLboolean _GLEE_SGIX_pixel_tiles; +GLEE_EXTERN GLboolean _GLEE_SGIS_texture_select; +GLEE_EXTERN GLboolean _GLEE_SGIX_sprite; +GLEE_EXTERN GLboolean _GLEE_SGIX_texture_multi_buffer; +GLEE_EXTERN GLboolean _GLEE_EXT_point_parameters; +GLEE_EXTERN GLboolean _GLEE_SGIS_point_parameters; +GLEE_EXTERN GLboolean _GLEE_SGIX_instruments; +GLEE_EXTERN GLboolean _GLEE_SGIX_texture_scale_bias; +GLEE_EXTERN GLboolean _GLEE_SGIX_framezoom; +GLEE_EXTERN GLboolean _GLEE_SGIX_tag_sample_buffer; +GLEE_EXTERN GLboolean _GLEE_FfdMaskSGIX; +GLEE_EXTERN GLboolean _GLEE_SGIX_polynomial_ffd; +GLEE_EXTERN GLboolean _GLEE_SGIX_reference_plane; +GLEE_EXTERN GLboolean _GLEE_SGIX_flush_raster; +GLEE_EXTERN GLboolean _GLEE_SGIX_depth_texture; +GLEE_EXTERN GLboolean _GLEE_SGIS_fog_function; +GLEE_EXTERN GLboolean _GLEE_SGIX_fog_offset; +GLEE_EXTERN GLboolean _GLEE_HP_image_transform; +GLEE_EXTERN GLboolean _GLEE_HP_convolution_border_modes; +GLEE_EXTERN GLboolean _GLEE_INGR_palette_buffer; +GLEE_EXTERN GLboolean _GLEE_SGIX_texture_add_env; +GLEE_EXTERN GLboolean _GLEE_EXT_color_subtable; +GLEE_EXTERN GLboolean _GLEE_PGI_vertex_hints; +GLEE_EXTERN GLboolean _GLEE_PGI_misc_hints; +GLEE_EXTERN GLboolean _GLEE_EXT_paletted_texture; +GLEE_EXTERN GLboolean _GLEE_EXT_clip_volume_hint; +GLEE_EXTERN GLboolean _GLEE_SGIX_list_priority; +GLEE_EXTERN GLboolean _GLEE_SGIX_ir_instrument1; +GLEE_EXTERN GLboolean _GLEE_SGIX_calligraphic_fragment; +GLEE_EXTERN GLboolean _GLEE_SGIX_texture_lod_bias; +GLEE_EXTERN GLboolean _GLEE_SGIX_shadow_ambient; +GLEE_EXTERN GLboolean _GLEE_EXT_index_texture; +GLEE_EXTERN GLboolean _GLEE_EXT_index_material; +GLEE_EXTERN GLboolean _GLEE_EXT_index_func; +GLEE_EXTERN GLboolean _GLEE_EXT_index_array_formats; +GLEE_EXTERN GLboolean _GLEE_EXT_compiled_vertex_array; +GLEE_EXTERN GLboolean _GLEE_EXT_cull_vertex; +GLEE_EXTERN GLboolean _GLEE_SGIX_ycrcb; +GLEE_EXTERN GLboolean _GLEE_SGIX_fragment_lighting; +GLEE_EXTERN GLboolean _GLEE_IBM_rasterpos_clip; +GLEE_EXTERN GLboolean _GLEE_HP_texture_lighting; +GLEE_EXTERN GLboolean _GLEE_EXT_draw_range_elements; +GLEE_EXTERN GLboolean _GLEE_WIN_phong_shading; +GLEE_EXTERN GLboolean _GLEE_WIN_specular_fog; +GLEE_EXTERN GLboolean _GLEE_EXT_light_texture; +GLEE_EXTERN GLboolean _GLEE_SGIX_blend_alpha_minmax; +GLEE_EXTERN GLboolean _GLEE_SGIX_impact_pixel_texture; +GLEE_EXTERN GLboolean _GLEE_EXT_bgra; +GLEE_EXTERN GLboolean _GLEE_SGIX_async; +GLEE_EXTERN GLboolean _GLEE_SGIX_async_pixel; +GLEE_EXTERN GLboolean _GLEE_SGIX_async_histogram; +GLEE_EXTERN GLboolean _GLEE_INTEL_texture_scissor; +GLEE_EXTERN GLboolean _GLEE_INTEL_parallel_arrays; +GLEE_EXTERN GLboolean _GLEE_HP_occlusion_test; +GLEE_EXTERN GLboolean _GLEE_EXT_pixel_transform; +GLEE_EXTERN GLboolean _GLEE_EXT_pixel_transform_color_table; +GLEE_EXTERN GLboolean _GLEE_EXT_shared_texture_palette; +GLEE_EXTERN GLboolean _GLEE_EXT_separate_specular_color; +GLEE_EXTERN GLboolean _GLEE_EXT_secondary_color; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_perturb_normal; +GLEE_EXTERN GLboolean _GLEE_EXT_multi_draw_arrays; +GLEE_EXTERN GLboolean _GLEE_EXT_fog_coord; +GLEE_EXTERN GLboolean _GLEE_REND_screen_coordinates; +GLEE_EXTERN GLboolean _GLEE_EXT_coordinate_frame; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_env_combine; +GLEE_EXTERN GLboolean _GLEE_APPLE_specular_vector; +GLEE_EXTERN GLboolean _GLEE_APPLE_transform_hint; +GLEE_EXTERN GLboolean _GLEE_SGIX_fog_scale; +GLEE_EXTERN GLboolean _GLEE_SUNX_constant_data; +GLEE_EXTERN GLboolean _GLEE_SUN_global_alpha; +GLEE_EXTERN GLboolean _GLEE_SUN_triangle_list; +GLEE_EXTERN GLboolean _GLEE_SUN_vertex; +GLEE_EXTERN GLboolean _GLEE_EXT_blend_func_separate; +GLEE_EXTERN GLboolean _GLEE_INGR_color_clamp; +GLEE_EXTERN GLboolean _GLEE_INGR_interlace_read; +GLEE_EXTERN GLboolean _GLEE_EXT_stencil_wrap; +GLEE_EXTERN GLboolean _GLEE_EXT_422_pixels; +GLEE_EXTERN GLboolean _GLEE_NV_texgen_reflection; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_cube_map; +GLEE_EXTERN GLboolean _GLEE_SUN_convolution_border_modes; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_env_add; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_lod_bias; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_filter_anisotropic; +GLEE_EXTERN GLboolean _GLEE_EXT_vertex_weighting; +GLEE_EXTERN GLboolean _GLEE_NV_light_max_exponent; +GLEE_EXTERN GLboolean _GLEE_NV_vertex_array_range; +GLEE_EXTERN GLboolean _GLEE_NV_register_combiners; +GLEE_EXTERN GLboolean _GLEE_NV_fog_distance; +GLEE_EXTERN GLboolean _GLEE_NV_texgen_emboss; +GLEE_EXTERN GLboolean _GLEE_NV_blend_square; +GLEE_EXTERN GLboolean _GLEE_NV_texture_env_combine4; +GLEE_EXTERN GLboolean _GLEE_MESA_resize_buffers; +GLEE_EXTERN GLboolean _GLEE_MESA_window_pos; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_compression_s3tc; +GLEE_EXTERN GLboolean _GLEE_IBM_cull_vertex; +GLEE_EXTERN GLboolean _GLEE_IBM_multimode_draw_arrays; +GLEE_EXTERN GLboolean _GLEE_IBM_vertex_array_lists; +GLEE_EXTERN GLboolean _GLEE_SGIX_subsample; +GLEE_EXTERN GLboolean _GLEE_SGIX_ycrcb_subsample; +GLEE_EXTERN GLboolean _GLEE_SGIX_ycrcba; +GLEE_EXTERN GLboolean _GLEE_SGI_depth_pass_instrument; +GLEE_EXTERN GLboolean _GLEE_3DFX_texture_compression_FXT1; +GLEE_EXTERN GLboolean _GLEE_3DFX_multisample; +GLEE_EXTERN GLboolean _GLEE_3DFX_tbuffer; +GLEE_EXTERN GLboolean _GLEE_EXT_multisample; +GLEE_EXTERN GLboolean _GLEE_SGIX_vertex_preclip; +GLEE_EXTERN GLboolean _GLEE_SGIX_convolution_accuracy; +GLEE_EXTERN GLboolean _GLEE_SGIX_resample; +GLEE_EXTERN GLboolean _GLEE_SGIS_point_line_texgen; +GLEE_EXTERN GLboolean _GLEE_SGIS_texture_color_mask; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_env_dot3; +GLEE_EXTERN GLboolean _GLEE_ATI_texture_mirror_once; +GLEE_EXTERN GLboolean _GLEE_NV_fence; +GLEE_EXTERN GLboolean _GLEE_IBM_texture_mirrored_repeat; +GLEE_EXTERN GLboolean _GLEE_NV_evaluators; +GLEE_EXTERN GLboolean _GLEE_NV_packed_depth_stencil; +GLEE_EXTERN GLboolean _GLEE_NV_register_combiners2; +GLEE_EXTERN GLboolean _GLEE_NV_texture_compression_vtc; +GLEE_EXTERN GLboolean _GLEE_NV_texture_rectangle; +GLEE_EXTERN GLboolean _GLEE_NV_texture_shader; +GLEE_EXTERN GLboolean _GLEE_NV_texture_shader2; +GLEE_EXTERN GLboolean _GLEE_NV_vertex_array_range2; +GLEE_EXTERN GLboolean _GLEE_NV_vertex_program; +GLEE_EXTERN GLboolean _GLEE_SGIX_texture_coordinate_clamp; +GLEE_EXTERN GLboolean _GLEE_SGIX_scalebias_hint; +GLEE_EXTERN GLboolean _GLEE_OML_interlace; +GLEE_EXTERN GLboolean _GLEE_OML_subsample; +GLEE_EXTERN GLboolean _GLEE_OML_resample; +GLEE_EXTERN GLboolean _GLEE_NV_copy_depth_to_color; +GLEE_EXTERN GLboolean _GLEE_ATI_envmap_bumpmap; +GLEE_EXTERN GLboolean _GLEE_ATI_fragment_shader; +GLEE_EXTERN GLboolean _GLEE_ATI_pn_triangles; +GLEE_EXTERN GLboolean _GLEE_ATI_vertex_array_object; +GLEE_EXTERN GLboolean _GLEE_EXT_vertex_shader; +GLEE_EXTERN GLboolean _GLEE_ATI_vertex_streams; +GLEE_EXTERN GLboolean _GLEE_ATI_element_array; +GLEE_EXTERN GLboolean _GLEE_SUN_mesh_array; +GLEE_EXTERN GLboolean _GLEE_SUN_slice_accum; +GLEE_EXTERN GLboolean _GLEE_NV_multisample_filter_hint; +GLEE_EXTERN GLboolean _GLEE_NV_depth_clamp; +GLEE_EXTERN GLboolean _GLEE_NV_occlusion_query; +GLEE_EXTERN GLboolean _GLEE_NV_point_sprite; +GLEE_EXTERN GLboolean _GLEE_NV_texture_shader3; +GLEE_EXTERN GLboolean _GLEE_NV_vertex_program1_1; +GLEE_EXTERN GLboolean _GLEE_EXT_shadow_funcs; +GLEE_EXTERN GLboolean _GLEE_EXT_stencil_two_side; +GLEE_EXTERN GLboolean _GLEE_ATI_text_fragment_shader; +GLEE_EXTERN GLboolean _GLEE_APPLE_client_storage; +GLEE_EXTERN GLboolean _GLEE_APPLE_element_array; +GLEE_EXTERN GLboolean _GLEE_APPLE_fence; +GLEE_EXTERN GLboolean _GLEE_APPLE_vertex_array_object; +GLEE_EXTERN GLboolean _GLEE_APPLE_vertex_array_range; +GLEE_EXTERN GLboolean _GLEE_APPLE_ycbcr_422; +GLEE_EXTERN GLboolean _GLEE_S3_s3tc; +GLEE_EXTERN GLboolean _GLEE_ATI_draw_buffers; +GLEE_EXTERN GLboolean _GLEE_ATI_pixel_format_float; +GLEE_EXTERN GLboolean _GLEE_ATI_texture_env_combine3; +GLEE_EXTERN GLboolean _GLEE_ATI_texture_float; +GLEE_EXTERN GLboolean _GLEE_NV_float_buffer; +GLEE_EXTERN GLboolean _GLEE_NV_fragment_program; +GLEE_EXTERN GLboolean _GLEE_NV_half_float; +GLEE_EXTERN GLboolean _GLEE_NV_pixel_data_range; +GLEE_EXTERN GLboolean _GLEE_NV_primitive_restart; +GLEE_EXTERN GLboolean _GLEE_NV_texture_expand_normal; +GLEE_EXTERN GLboolean _GLEE_NV_vertex_program2; +GLEE_EXTERN GLboolean _GLEE_ATI_map_object_buffer; +GLEE_EXTERN GLboolean _GLEE_ATI_separate_stencil; +GLEE_EXTERN GLboolean _GLEE_ATI_vertex_attrib_array_object; +GLEE_EXTERN GLboolean _GLEE_OES_read_format; +GLEE_EXTERN GLboolean _GLEE_EXT_depth_bounds_test; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_mirror_clamp; +GLEE_EXTERN GLboolean _GLEE_EXT_blend_equation_separate; +GLEE_EXTERN GLboolean _GLEE_MESA_pack_invert; +GLEE_EXTERN GLboolean _GLEE_MESA_ycbcr_texture; +GLEE_EXTERN GLboolean _GLEE_EXT_pixel_buffer_object; +GLEE_EXTERN GLboolean _GLEE_NV_fragment_program_option; +GLEE_EXTERN GLboolean _GLEE_NV_fragment_program2; +GLEE_EXTERN GLboolean _GLEE_NV_vertex_program2_option; +GLEE_EXTERN GLboolean _GLEE_NV_vertex_program3; +GLEE_EXTERN GLboolean _GLEE_EXT_framebuffer_object; +GLEE_EXTERN GLboolean _GLEE_GREMEDY_string_marker; +GLEE_EXTERN GLboolean _GLEE_EXT_packed_depth_stencil; +GLEE_EXTERN GLboolean _GLEE_EXT_stencil_clear_tag; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_sRGB; +GLEE_EXTERN GLboolean _GLEE_EXT_framebuffer_blit; +GLEE_EXTERN GLboolean _GLEE_EXT_framebuffer_multisample; +GLEE_EXTERN GLboolean _GLEE_MESAX_texture_stack; +GLEE_EXTERN GLboolean _GLEE_EXT_timer_query; +GLEE_EXTERN GLboolean _GLEE_EXT_gpu_program_parameters; +GLEE_EXTERN GLboolean _GLEE_APPLE_flush_buffer_range; +GLEE_EXTERN GLboolean _GLEE_EXT_gpu_shader4; +GLEE_EXTERN GLboolean _GLEE_EXT_draw_instanced; +GLEE_EXTERN GLboolean _GLEE_EXT_packed_float; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_array; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_buffer_object; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_compression_latc; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_compression_rgtc; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_shared_exponent; +GLEE_EXTERN GLboolean _GLEE_NV_depth_buffer_float; +GLEE_EXTERN GLboolean _GLEE_NV_framebuffer_multisample_coverage; +GLEE_EXTERN GLboolean _GLEE_EXT_framebuffer_sRGB; +GLEE_EXTERN GLboolean _GLEE_NV_geometry_shader4; +GLEE_EXTERN GLboolean _GLEE_NV_parameter_buffer_object; +GLEE_EXTERN GLboolean _GLEE_EXT_draw_buffers2; +GLEE_EXTERN GLboolean _GLEE_NV_transform_feedback; +GLEE_EXTERN GLboolean _GLEE_EXT_bindable_uniform; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_integer; +GLEE_EXTERN GLboolean _GLEE_GREMEDY_frame_terminator; +GLEE_EXTERN GLboolean _GLEE_NV_conditional_render; +GLEE_EXTERN GLboolean _GLEE_NV_present_video; +GLEE_EXTERN GLboolean _GLEE_EXT_transform_feedback; +GLEE_EXTERN GLboolean _GLEE_EXT_direct_state_access; +GLEE_EXTERN GLboolean _GLEE_EXT_vertex_array_bgra; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_swizzle; +GLEE_EXTERN GLboolean _GLEE_NV_explicit_multisample; +GLEE_EXTERN GLboolean _GLEE_NV_transform_feedback2; +GLEE_EXTERN GLboolean _GLEE_SGIX_texture_select; +GLEE_EXTERN GLboolean _GLEE_INGR_blend_func_separate; +GLEE_EXTERN GLboolean _GLEE_SGIX_depth_pass_instrument; +GLEE_EXTERN GLboolean _GLEE_SGIX_igloo_interface; +GLEE_EXTERN GLboolean _GLEE_EXT_fragment_lighting; +GLEE_EXTERN GLboolean _GLEE_EXT_geometry_shader4; +GLEE_EXTERN GLboolean _GLEE_EXT_scene_marker; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_compression_dxt1; +GLEE_EXTERN GLboolean _GLEE_EXT_texture_env; +GLEE_EXTERN GLboolean _GLEE_IBM_static_data; +GLEE_EXTERN GLboolean _GLEE_NV_gpu_program4; +GLEE_EXTERN GLboolean _GLEE_OES_byte_coordinates; +GLEE_EXTERN GLboolean _GLEE_OES_compressed_paletted_texture; +GLEE_EXTERN GLboolean _GLEE_OES_single_precision; +GLEE_EXTERN GLboolean _GLEE_SGIX_pixel_texture_bits; +GLEE_EXTERN GLboolean _GLEE_SGIX_texture_range; + +/* Aliases for extension querying variables */ + +#define GLEE_VERSION_1_2 GLeeEnabled(&_GLEE_VERSION_1_2) +#define GLEE_ARB_imaging GLeeEnabled(&_GLEE_ARB_imaging) +#define GLEE_VERSION_1_3 GLeeEnabled(&_GLEE_VERSION_1_3) +#define GLEE_VERSION_1_4 GLeeEnabled(&_GLEE_VERSION_1_4) +#define GLEE_VERSION_1_5 GLeeEnabled(&_GLEE_VERSION_1_5) +#define GLEE_VERSION_2_0 GLeeEnabled(&_GLEE_VERSION_2_0) +#define GLEE_VERSION_2_1 GLeeEnabled(&_GLEE_VERSION_2_1) +#define GLEE_VERSION_3_0 GLeeEnabled(&_GLEE_VERSION_3_0) +#define GLEE_ARB_multitexture GLeeEnabled(&_GLEE_ARB_multitexture) +#define GLEE_ARB_transpose_matrix GLeeEnabled(&_GLEE_ARB_transpose_matrix) +#define GLEE_ARB_multisample GLeeEnabled(&_GLEE_ARB_multisample) +#define GLEE_ARB_texture_env_add GLeeEnabled(&_GLEE_ARB_texture_env_add) +#define GLEE_ARB_texture_cube_map GLeeEnabled(&_GLEE_ARB_texture_cube_map) +#define GLEE_ARB_texture_compression GLeeEnabled(&_GLEE_ARB_texture_compression) +#define GLEE_ARB_texture_border_clamp GLeeEnabled(&_GLEE_ARB_texture_border_clamp) +#define GLEE_ARB_point_parameters GLeeEnabled(&_GLEE_ARB_point_parameters) +#define GLEE_ARB_vertex_blend GLeeEnabled(&_GLEE_ARB_vertex_blend) +#define GLEE_ARB_matrix_palette GLeeEnabled(&_GLEE_ARB_matrix_palette) +#define GLEE_ARB_texture_env_combine GLeeEnabled(&_GLEE_ARB_texture_env_combine) +#define GLEE_ARB_texture_env_crossbar GLeeEnabled(&_GLEE_ARB_texture_env_crossbar) +#define GLEE_ARB_texture_env_dot3 GLeeEnabled(&_GLEE_ARB_texture_env_dot3) +#define GLEE_ARB_texture_mirrored_repeat GLeeEnabled(&_GLEE_ARB_texture_mirrored_repeat) +#define GLEE_ARB_depth_texture GLeeEnabled(&_GLEE_ARB_depth_texture) +#define GLEE_ARB_shadow GLeeEnabled(&_GLEE_ARB_shadow) +#define GLEE_ARB_shadow_ambient GLeeEnabled(&_GLEE_ARB_shadow_ambient) +#define GLEE_ARB_window_pos GLeeEnabled(&_GLEE_ARB_window_pos) +#define GLEE_ARB_vertex_program GLeeEnabled(&_GLEE_ARB_vertex_program) +#define GLEE_ARB_fragment_program GLeeEnabled(&_GLEE_ARB_fragment_program) +#define GLEE_ARB_vertex_buffer_object GLeeEnabled(&_GLEE_ARB_vertex_buffer_object) +#define GLEE_ARB_occlusion_query GLeeEnabled(&_GLEE_ARB_occlusion_query) +#define GLEE_ARB_shader_objects GLeeEnabled(&_GLEE_ARB_shader_objects) +#define GLEE_ARB_vertex_shader GLeeEnabled(&_GLEE_ARB_vertex_shader) +#define GLEE_ARB_fragment_shader GLeeEnabled(&_GLEE_ARB_fragment_shader) +#define GLEE_ARB_shading_language_100 GLeeEnabled(&_GLEE_ARB_shading_language_100) +#define GLEE_ARB_texture_non_power_of_two GLeeEnabled(&_GLEE_ARB_texture_non_power_of_two) +#define GLEE_ARB_point_sprite GLeeEnabled(&_GLEE_ARB_point_sprite) +#define GLEE_ARB_fragment_program_shadow GLeeEnabled(&_GLEE_ARB_fragment_program_shadow) +#define GLEE_ARB_draw_buffers GLeeEnabled(&_GLEE_ARB_draw_buffers) +#define GLEE_ARB_texture_rectangle GLeeEnabled(&_GLEE_ARB_texture_rectangle) +#define GLEE_ARB_color_buffer_float GLeeEnabled(&_GLEE_ARB_color_buffer_float) +#define GLEE_ARB_half_float_pixel GLeeEnabled(&_GLEE_ARB_half_float_pixel) +#define GLEE_ARB_texture_float GLeeEnabled(&_GLEE_ARB_texture_float) +#define GLEE_ARB_pixel_buffer_object GLeeEnabled(&_GLEE_ARB_pixel_buffer_object) +#define GLEE_ARB_depth_buffer_float GLeeEnabled(&_GLEE_ARB_depth_buffer_float) +#define GLEE_ARB_draw_instanced GLeeEnabled(&_GLEE_ARB_draw_instanced) +#define GLEE_ARB_framebuffer_object GLeeEnabled(&_GLEE_ARB_framebuffer_object) +#define GLEE_ARB_framebuffer_sRGB GLeeEnabled(&_GLEE_ARB_framebuffer_sRGB) +#define GLEE_ARB_geometry_shader4 GLeeEnabled(&_GLEE_ARB_geometry_shader4) +#define GLEE_ARB_half_float_vertex GLeeEnabled(&_GLEE_ARB_half_float_vertex) +#define GLEE_ARB_instanced_arrays GLeeEnabled(&_GLEE_ARB_instanced_arrays) +#define GLEE_ARB_map_buffer_range GLeeEnabled(&_GLEE_ARB_map_buffer_range) +#define GLEE_ARB_texture_buffer_object GLeeEnabled(&_GLEE_ARB_texture_buffer_object) +#define GLEE_ARB_texture_compression_rgtc GLeeEnabled(&_GLEE_ARB_texture_compression_rgtc) +#define GLEE_ARB_texture_rg GLeeEnabled(&_GLEE_ARB_texture_rg) +#define GLEE_ARB_vertex_array_object GLeeEnabled(&_GLEE_ARB_vertex_array_object) +#define GLEE_EXT_abgr GLeeEnabled(&_GLEE_EXT_abgr) +#define GLEE_EXT_blend_color GLeeEnabled(&_GLEE_EXT_blend_color) +#define GLEE_EXT_polygon_offset GLeeEnabled(&_GLEE_EXT_polygon_offset) +#define GLEE_EXT_texture GLeeEnabled(&_GLEE_EXT_texture) +#define GLEE_EXT_texture3D GLeeEnabled(&_GLEE_EXT_texture3D) +#define GLEE_SGIS_texture_filter4 GLeeEnabled(&_GLEE_SGIS_texture_filter4) +#define GLEE_EXT_subtexture GLeeEnabled(&_GLEE_EXT_subtexture) +#define GLEE_EXT_copy_texture GLeeEnabled(&_GLEE_EXT_copy_texture) +#define GLEE_EXT_histogram GLeeEnabled(&_GLEE_EXT_histogram) +#define GLEE_EXT_convolution GLeeEnabled(&_GLEE_EXT_convolution) +#define GLEE_SGI_color_matrix GLeeEnabled(&_GLEE_SGI_color_matrix) +#define GLEE_SGI_color_table GLeeEnabled(&_GLEE_SGI_color_table) +#define GLEE_SGIS_pixel_texture GLeeEnabled(&_GLEE_SGIS_pixel_texture) +#define GLEE_SGIX_pixel_texture GLeeEnabled(&_GLEE_SGIX_pixel_texture) +#define GLEE_SGIS_texture4D GLeeEnabled(&_GLEE_SGIS_texture4D) +#define GLEE_SGI_texture_color_table GLeeEnabled(&_GLEE_SGI_texture_color_table) +#define GLEE_EXT_cmyka GLeeEnabled(&_GLEE_EXT_cmyka) +#define GLEE_EXT_texture_object GLeeEnabled(&_GLEE_EXT_texture_object) +#define GLEE_SGIS_detail_texture GLeeEnabled(&_GLEE_SGIS_detail_texture) +#define GLEE_SGIS_sharpen_texture GLeeEnabled(&_GLEE_SGIS_sharpen_texture) +#define GLEE_EXT_packed_pixels GLeeEnabled(&_GLEE_EXT_packed_pixels) +#define GLEE_SGIS_texture_lod GLeeEnabled(&_GLEE_SGIS_texture_lod) +#define GLEE_SGIS_multisample GLeeEnabled(&_GLEE_SGIS_multisample) +#define GLEE_EXT_rescale_normal GLeeEnabled(&_GLEE_EXT_rescale_normal) +#define GLEE_EXT_vertex_array GLeeEnabled(&_GLEE_EXT_vertex_array) +#define GLEE_EXT_misc_attribute GLeeEnabled(&_GLEE_EXT_misc_attribute) +#define GLEE_SGIS_generate_mipmap GLeeEnabled(&_GLEE_SGIS_generate_mipmap) +#define GLEE_SGIX_clipmap GLeeEnabled(&_GLEE_SGIX_clipmap) +#define GLEE_SGIX_shadow GLeeEnabled(&_GLEE_SGIX_shadow) +#define GLEE_SGIS_texture_edge_clamp GLeeEnabled(&_GLEE_SGIS_texture_edge_clamp) +#define GLEE_SGIS_texture_border_clamp GLeeEnabled(&_GLEE_SGIS_texture_border_clamp) +#define GLEE_EXT_blend_minmax GLeeEnabled(&_GLEE_EXT_blend_minmax) +#define GLEE_EXT_blend_subtract GLeeEnabled(&_GLEE_EXT_blend_subtract) +#define GLEE_EXT_blend_logic_op GLeeEnabled(&_GLEE_EXT_blend_logic_op) +#define GLEE_SGIX_interlace GLeeEnabled(&_GLEE_SGIX_interlace) +#define GLEE_SGIX_pixel_tiles GLeeEnabled(&_GLEE_SGIX_pixel_tiles) +#define GLEE_SGIS_texture_select GLeeEnabled(&_GLEE_SGIS_texture_select) +#define GLEE_SGIX_sprite GLeeEnabled(&_GLEE_SGIX_sprite) +#define GLEE_SGIX_texture_multi_buffer GLeeEnabled(&_GLEE_SGIX_texture_multi_buffer) +#define GLEE_EXT_point_parameters GLeeEnabled(&_GLEE_EXT_point_parameters) +#define GLEE_SGIS_point_parameters GLeeEnabled(&_GLEE_SGIS_point_parameters) +#define GLEE_SGIX_instruments GLeeEnabled(&_GLEE_SGIX_instruments) +#define GLEE_SGIX_texture_scale_bias GLeeEnabled(&_GLEE_SGIX_texture_scale_bias) +#define GLEE_SGIX_framezoom GLeeEnabled(&_GLEE_SGIX_framezoom) +#define GLEE_SGIX_tag_sample_buffer GLeeEnabled(&_GLEE_SGIX_tag_sample_buffer) +#define GLEE_FfdMaskSGIX GLeeEnabled(&_GLEE_FfdMaskSGIX) +#define GLEE_SGIX_polynomial_ffd GLeeEnabled(&_GLEE_SGIX_polynomial_ffd) +#define GLEE_SGIX_reference_plane GLeeEnabled(&_GLEE_SGIX_reference_plane) +#define GLEE_SGIX_flush_raster GLeeEnabled(&_GLEE_SGIX_flush_raster) +#define GLEE_SGIX_depth_texture GLeeEnabled(&_GLEE_SGIX_depth_texture) +#define GLEE_SGIS_fog_function GLeeEnabled(&_GLEE_SGIS_fog_function) +#define GLEE_SGIX_fog_offset GLeeEnabled(&_GLEE_SGIX_fog_offset) +#define GLEE_HP_image_transform GLeeEnabled(&_GLEE_HP_image_transform) +#define GLEE_HP_convolution_border_modes GLeeEnabled(&_GLEE_HP_convolution_border_modes) +#define GLEE_INGR_palette_buffer GLeeEnabled(&_GLEE_INGR_palette_buffer) +#define GLEE_SGIX_texture_add_env GLeeEnabled(&_GLEE_SGIX_texture_add_env) +#define GLEE_EXT_color_subtable GLeeEnabled(&_GLEE_EXT_color_subtable) +#define GLEE_PGI_vertex_hints GLeeEnabled(&_GLEE_PGI_vertex_hints) +#define GLEE_PGI_misc_hints GLeeEnabled(&_GLEE_PGI_misc_hints) +#define GLEE_EXT_paletted_texture GLeeEnabled(&_GLEE_EXT_paletted_texture) +#define GLEE_EXT_clip_volume_hint GLeeEnabled(&_GLEE_EXT_clip_volume_hint) +#define GLEE_SGIX_list_priority GLeeEnabled(&_GLEE_SGIX_list_priority) +#define GLEE_SGIX_ir_instrument1 GLeeEnabled(&_GLEE_SGIX_ir_instrument1) +#define GLEE_SGIX_calligraphic_fragment GLeeEnabled(&_GLEE_SGIX_calligraphic_fragment) +#define GLEE_SGIX_texture_lod_bias GLeeEnabled(&_GLEE_SGIX_texture_lod_bias) +#define GLEE_SGIX_shadow_ambient GLeeEnabled(&_GLEE_SGIX_shadow_ambient) +#define GLEE_EXT_index_texture GLeeEnabled(&_GLEE_EXT_index_texture) +#define GLEE_EXT_index_material GLeeEnabled(&_GLEE_EXT_index_material) +#define GLEE_EXT_index_func GLeeEnabled(&_GLEE_EXT_index_func) +#define GLEE_EXT_index_array_formats GLeeEnabled(&_GLEE_EXT_index_array_formats) +#define GLEE_EXT_compiled_vertex_array GLeeEnabled(&_GLEE_EXT_compiled_vertex_array) +#define GLEE_EXT_cull_vertex GLeeEnabled(&_GLEE_EXT_cull_vertex) +#define GLEE_SGIX_ycrcb GLeeEnabled(&_GLEE_SGIX_ycrcb) +#define GLEE_SGIX_fragment_lighting GLeeEnabled(&_GLEE_SGIX_fragment_lighting) +#define GLEE_IBM_rasterpos_clip GLeeEnabled(&_GLEE_IBM_rasterpos_clip) +#define GLEE_HP_texture_lighting GLeeEnabled(&_GLEE_HP_texture_lighting) +#define GLEE_EXT_draw_range_elements GLeeEnabled(&_GLEE_EXT_draw_range_elements) +#define GLEE_WIN_phong_shading GLeeEnabled(&_GLEE_WIN_phong_shading) +#define GLEE_WIN_specular_fog GLeeEnabled(&_GLEE_WIN_specular_fog) +#define GLEE_EXT_light_texture GLeeEnabled(&_GLEE_EXT_light_texture) +#define GLEE_SGIX_blend_alpha_minmax GLeeEnabled(&_GLEE_SGIX_blend_alpha_minmax) +#define GLEE_SGIX_impact_pixel_texture GLeeEnabled(&_GLEE_SGIX_impact_pixel_texture) +#define GLEE_EXT_bgra GLeeEnabled(&_GLEE_EXT_bgra) +#define GLEE_SGIX_async GLeeEnabled(&_GLEE_SGIX_async) +#define GLEE_SGIX_async_pixel GLeeEnabled(&_GLEE_SGIX_async_pixel) +#define GLEE_SGIX_async_histogram GLeeEnabled(&_GLEE_SGIX_async_histogram) +#define GLEE_INTEL_texture_scissor GLeeEnabled(&_GLEE_INTEL_texture_scissor) +#define GLEE_INTEL_parallel_arrays GLeeEnabled(&_GLEE_INTEL_parallel_arrays) +#define GLEE_HP_occlusion_test GLeeEnabled(&_GLEE_HP_occlusion_test) +#define GLEE_EXT_pixel_transform GLeeEnabled(&_GLEE_EXT_pixel_transform) +#define GLEE_EXT_pixel_transform_color_table GLeeEnabled(&_GLEE_EXT_pixel_transform_color_table) +#define GLEE_EXT_shared_texture_palette GLeeEnabled(&_GLEE_EXT_shared_texture_palette) +#define GLEE_EXT_separate_specular_color GLeeEnabled(&_GLEE_EXT_separate_specular_color) +#define GLEE_EXT_secondary_color GLeeEnabled(&_GLEE_EXT_secondary_color) +#define GLEE_EXT_texture_perturb_normal GLeeEnabled(&_GLEE_EXT_texture_perturb_normal) +#define GLEE_EXT_multi_draw_arrays GLeeEnabled(&_GLEE_EXT_multi_draw_arrays) +#define GLEE_EXT_fog_coord GLeeEnabled(&_GLEE_EXT_fog_coord) +#define GLEE_REND_screen_coordinates GLeeEnabled(&_GLEE_REND_screen_coordinates) +#define GLEE_EXT_coordinate_frame GLeeEnabled(&_GLEE_EXT_coordinate_frame) +#define GLEE_EXT_texture_env_combine GLeeEnabled(&_GLEE_EXT_texture_env_combine) +#define GLEE_APPLE_specular_vector GLeeEnabled(&_GLEE_APPLE_specular_vector) +#define GLEE_APPLE_transform_hint GLeeEnabled(&_GLEE_APPLE_transform_hint) +#define GLEE_SGIX_fog_scale GLeeEnabled(&_GLEE_SGIX_fog_scale) +#define GLEE_SUNX_constant_data GLeeEnabled(&_GLEE_SUNX_constant_data) +#define GLEE_SUN_global_alpha GLeeEnabled(&_GLEE_SUN_global_alpha) +#define GLEE_SUN_triangle_list GLeeEnabled(&_GLEE_SUN_triangle_list) +#define GLEE_SUN_vertex GLeeEnabled(&_GLEE_SUN_vertex) +#define GLEE_EXT_blend_func_separate GLeeEnabled(&_GLEE_EXT_blend_func_separate) +#define GLEE_INGR_color_clamp GLeeEnabled(&_GLEE_INGR_color_clamp) +#define GLEE_INGR_interlace_read GLeeEnabled(&_GLEE_INGR_interlace_read) +#define GLEE_EXT_stencil_wrap GLeeEnabled(&_GLEE_EXT_stencil_wrap) +#define GLEE_EXT_422_pixels GLeeEnabled(&_GLEE_EXT_422_pixels) +#define GLEE_NV_texgen_reflection GLeeEnabled(&_GLEE_NV_texgen_reflection) +#define GLEE_EXT_texture_cube_map GLeeEnabled(&_GLEE_EXT_texture_cube_map) +#define GLEE_SUN_convolution_border_modes GLeeEnabled(&_GLEE_SUN_convolution_border_modes) +#define GLEE_EXT_texture_env_add GLeeEnabled(&_GLEE_EXT_texture_env_add) +#define GLEE_EXT_texture_lod_bias GLeeEnabled(&_GLEE_EXT_texture_lod_bias) +#define GLEE_EXT_texture_filter_anisotropic GLeeEnabled(&_GLEE_EXT_texture_filter_anisotropic) +#define GLEE_EXT_vertex_weighting GLeeEnabled(&_GLEE_EXT_vertex_weighting) +#define GLEE_NV_light_max_exponent GLeeEnabled(&_GLEE_NV_light_max_exponent) +#define GLEE_NV_vertex_array_range GLeeEnabled(&_GLEE_NV_vertex_array_range) +#define GLEE_NV_register_combiners GLeeEnabled(&_GLEE_NV_register_combiners) +#define GLEE_NV_fog_distance GLeeEnabled(&_GLEE_NV_fog_distance) +#define GLEE_NV_texgen_emboss GLeeEnabled(&_GLEE_NV_texgen_emboss) +#define GLEE_NV_blend_square GLeeEnabled(&_GLEE_NV_blend_square) +#define GLEE_NV_texture_env_combine4 GLeeEnabled(&_GLEE_NV_texture_env_combine4) +#define GLEE_MESA_resize_buffers GLeeEnabled(&_GLEE_MESA_resize_buffers) +#define GLEE_MESA_window_pos GLeeEnabled(&_GLEE_MESA_window_pos) +#define GLEE_EXT_texture_compression_s3tc GLeeEnabled(&_GLEE_EXT_texture_compression_s3tc) +#define GLEE_IBM_cull_vertex GLeeEnabled(&_GLEE_IBM_cull_vertex) +#define GLEE_IBM_multimode_draw_arrays GLeeEnabled(&_GLEE_IBM_multimode_draw_arrays) +#define GLEE_IBM_vertex_array_lists GLeeEnabled(&_GLEE_IBM_vertex_array_lists) +#define GLEE_SGIX_subsample GLeeEnabled(&_GLEE_SGIX_subsample) +#define GLEE_SGIX_ycrcb_subsample GLeeEnabled(&_GLEE_SGIX_ycrcb_subsample) +#define GLEE_SGIX_ycrcba GLeeEnabled(&_GLEE_SGIX_ycrcba) +#define GLEE_SGI_depth_pass_instrument GLeeEnabled(&_GLEE_SGI_depth_pass_instrument) +#define GLEE_3DFX_texture_compression_FXT1 GLeeEnabled(&_GLEE_3DFX_texture_compression_FXT1) +#define GLEE_3DFX_multisample GLeeEnabled(&_GLEE_3DFX_multisample) +#define GLEE_3DFX_tbuffer GLeeEnabled(&_GLEE_3DFX_tbuffer) +#define GLEE_EXT_multisample GLeeEnabled(&_GLEE_EXT_multisample) +#define GLEE_SGIX_vertex_preclip GLeeEnabled(&_GLEE_SGIX_vertex_preclip) +#define GLEE_SGIX_convolution_accuracy GLeeEnabled(&_GLEE_SGIX_convolution_accuracy) +#define GLEE_SGIX_resample GLeeEnabled(&_GLEE_SGIX_resample) +#define GLEE_SGIS_point_line_texgen GLeeEnabled(&_GLEE_SGIS_point_line_texgen) +#define GLEE_SGIS_texture_color_mask GLeeEnabled(&_GLEE_SGIS_texture_color_mask) +#define GLEE_EXT_texture_env_dot3 GLeeEnabled(&_GLEE_EXT_texture_env_dot3) +#define GLEE_ATI_texture_mirror_once GLeeEnabled(&_GLEE_ATI_texture_mirror_once) +#define GLEE_NV_fence GLeeEnabled(&_GLEE_NV_fence) +#define GLEE_IBM_texture_mirrored_repeat GLeeEnabled(&_GLEE_IBM_texture_mirrored_repeat) +#define GLEE_NV_evaluators GLeeEnabled(&_GLEE_NV_evaluators) +#define GLEE_NV_packed_depth_stencil GLeeEnabled(&_GLEE_NV_packed_depth_stencil) +#define GLEE_NV_register_combiners2 GLeeEnabled(&_GLEE_NV_register_combiners2) +#define GLEE_NV_texture_compression_vtc GLeeEnabled(&_GLEE_NV_texture_compression_vtc) +#define GLEE_NV_texture_rectangle GLeeEnabled(&_GLEE_NV_texture_rectangle) +#define GLEE_NV_texture_shader GLeeEnabled(&_GLEE_NV_texture_shader) +#define GLEE_NV_texture_shader2 GLeeEnabled(&_GLEE_NV_texture_shader2) +#define GLEE_NV_vertex_array_range2 GLeeEnabled(&_GLEE_NV_vertex_array_range2) +#define GLEE_NV_vertex_program GLeeEnabled(&_GLEE_NV_vertex_program) +#define GLEE_SGIX_texture_coordinate_clamp GLeeEnabled(&_GLEE_SGIX_texture_coordinate_clamp) +#define GLEE_SGIX_scalebias_hint GLeeEnabled(&_GLEE_SGIX_scalebias_hint) +#define GLEE_OML_interlace GLeeEnabled(&_GLEE_OML_interlace) +#define GLEE_OML_subsample GLeeEnabled(&_GLEE_OML_subsample) +#define GLEE_OML_resample GLeeEnabled(&_GLEE_OML_resample) +#define GLEE_NV_copy_depth_to_color GLeeEnabled(&_GLEE_NV_copy_depth_to_color) +#define GLEE_ATI_envmap_bumpmap GLeeEnabled(&_GLEE_ATI_envmap_bumpmap) +#define GLEE_ATI_fragment_shader GLeeEnabled(&_GLEE_ATI_fragment_shader) +#define GLEE_ATI_pn_triangles GLeeEnabled(&_GLEE_ATI_pn_triangles) +#define GLEE_ATI_vertex_array_object GLeeEnabled(&_GLEE_ATI_vertex_array_object) +#define GLEE_EXT_vertex_shader GLeeEnabled(&_GLEE_EXT_vertex_shader) +#define GLEE_ATI_vertex_streams GLeeEnabled(&_GLEE_ATI_vertex_streams) +#define GLEE_ATI_element_array GLeeEnabled(&_GLEE_ATI_element_array) +#define GLEE_SUN_mesh_array GLeeEnabled(&_GLEE_SUN_mesh_array) +#define GLEE_SUN_slice_accum GLeeEnabled(&_GLEE_SUN_slice_accum) +#define GLEE_NV_multisample_filter_hint GLeeEnabled(&_GLEE_NV_multisample_filter_hint) +#define GLEE_NV_depth_clamp GLeeEnabled(&_GLEE_NV_depth_clamp) +#define GLEE_NV_occlusion_query GLeeEnabled(&_GLEE_NV_occlusion_query) +#define GLEE_NV_point_sprite GLeeEnabled(&_GLEE_NV_point_sprite) +#define GLEE_NV_texture_shader3 GLeeEnabled(&_GLEE_NV_texture_shader3) +#define GLEE_NV_vertex_program1_1 GLeeEnabled(&_GLEE_NV_vertex_program1_1) +#define GLEE_EXT_shadow_funcs GLeeEnabled(&_GLEE_EXT_shadow_funcs) +#define GLEE_EXT_stencil_two_side GLeeEnabled(&_GLEE_EXT_stencil_two_side) +#define GLEE_ATI_text_fragment_shader GLeeEnabled(&_GLEE_ATI_text_fragment_shader) +#define GLEE_APPLE_client_storage GLeeEnabled(&_GLEE_APPLE_client_storage) +#define GLEE_APPLE_element_array GLeeEnabled(&_GLEE_APPLE_element_array) +#define GLEE_APPLE_fence GLeeEnabled(&_GLEE_APPLE_fence) +#define GLEE_APPLE_vertex_array_object GLeeEnabled(&_GLEE_APPLE_vertex_array_object) +#define GLEE_APPLE_vertex_array_range GLeeEnabled(&_GLEE_APPLE_vertex_array_range) +#define GLEE_APPLE_ycbcr_422 GLeeEnabled(&_GLEE_APPLE_ycbcr_422) +#define GLEE_S3_s3tc GLeeEnabled(&_GLEE_S3_s3tc) +#define GLEE_ATI_draw_buffers GLeeEnabled(&_GLEE_ATI_draw_buffers) +#define GLEE_ATI_pixel_format_float GLeeEnabled(&_GLEE_ATI_pixel_format_float) +#define GLEE_ATI_texture_env_combine3 GLeeEnabled(&_GLEE_ATI_texture_env_combine3) +#define GLEE_ATI_texture_float GLeeEnabled(&_GLEE_ATI_texture_float) +#define GLEE_NV_float_buffer GLeeEnabled(&_GLEE_NV_float_buffer) +#define GLEE_NV_fragment_program GLeeEnabled(&_GLEE_NV_fragment_program) +#define GLEE_NV_half_float GLeeEnabled(&_GLEE_NV_half_float) +#define GLEE_NV_pixel_data_range GLeeEnabled(&_GLEE_NV_pixel_data_range) +#define GLEE_NV_primitive_restart GLeeEnabled(&_GLEE_NV_primitive_restart) +#define GLEE_NV_texture_expand_normal GLeeEnabled(&_GLEE_NV_texture_expand_normal) +#define GLEE_NV_vertex_program2 GLeeEnabled(&_GLEE_NV_vertex_program2) +#define GLEE_ATI_map_object_buffer GLeeEnabled(&_GLEE_ATI_map_object_buffer) +#define GLEE_ATI_separate_stencil GLeeEnabled(&_GLEE_ATI_separate_stencil) +#define GLEE_ATI_vertex_attrib_array_object GLeeEnabled(&_GLEE_ATI_vertex_attrib_array_object) +#define GLEE_OES_read_format GLeeEnabled(&_GLEE_OES_read_format) +#define GLEE_EXT_depth_bounds_test GLeeEnabled(&_GLEE_EXT_depth_bounds_test) +#define GLEE_EXT_texture_mirror_clamp GLeeEnabled(&_GLEE_EXT_texture_mirror_clamp) +#define GLEE_EXT_blend_equation_separate GLeeEnabled(&_GLEE_EXT_blend_equation_separate) +#define GLEE_MESA_pack_invert GLeeEnabled(&_GLEE_MESA_pack_invert) +#define GLEE_MESA_ycbcr_texture GLeeEnabled(&_GLEE_MESA_ycbcr_texture) +#define GLEE_EXT_pixel_buffer_object GLeeEnabled(&_GLEE_EXT_pixel_buffer_object) +#define GLEE_NV_fragment_program_option GLeeEnabled(&_GLEE_NV_fragment_program_option) +#define GLEE_NV_fragment_program2 GLeeEnabled(&_GLEE_NV_fragment_program2) +#define GLEE_NV_vertex_program2_option GLeeEnabled(&_GLEE_NV_vertex_program2_option) +#define GLEE_NV_vertex_program3 GLeeEnabled(&_GLEE_NV_vertex_program3) +#define GLEE_EXT_framebuffer_object GLeeEnabled(&_GLEE_EXT_framebuffer_object) +#define GLEE_GREMEDY_string_marker GLeeEnabled(&_GLEE_GREMEDY_string_marker) +#define GLEE_EXT_packed_depth_stencil GLeeEnabled(&_GLEE_EXT_packed_depth_stencil) +#define GLEE_EXT_stencil_clear_tag GLeeEnabled(&_GLEE_EXT_stencil_clear_tag) +#define GLEE_EXT_texture_sRGB GLeeEnabled(&_GLEE_EXT_texture_sRGB) +#define GLEE_EXT_framebuffer_blit GLeeEnabled(&_GLEE_EXT_framebuffer_blit) +#define GLEE_EXT_framebuffer_multisample GLeeEnabled(&_GLEE_EXT_framebuffer_multisample) +#define GLEE_MESAX_texture_stack GLeeEnabled(&_GLEE_MESAX_texture_stack) +#define GLEE_EXT_timer_query GLeeEnabled(&_GLEE_EXT_timer_query) +#define GLEE_EXT_gpu_program_parameters GLeeEnabled(&_GLEE_EXT_gpu_program_parameters) +#define GLEE_APPLE_flush_buffer_range GLeeEnabled(&_GLEE_APPLE_flush_buffer_range) +#define GLEE_EXT_gpu_shader4 GLeeEnabled(&_GLEE_EXT_gpu_shader4) +#define GLEE_EXT_draw_instanced GLeeEnabled(&_GLEE_EXT_draw_instanced) +#define GLEE_EXT_packed_float GLeeEnabled(&_GLEE_EXT_packed_float) +#define GLEE_EXT_texture_array GLeeEnabled(&_GLEE_EXT_texture_array) +#define GLEE_EXT_texture_buffer_object GLeeEnabled(&_GLEE_EXT_texture_buffer_object) +#define GLEE_EXT_texture_compression_latc GLeeEnabled(&_GLEE_EXT_texture_compression_latc) +#define GLEE_EXT_texture_compression_rgtc GLeeEnabled(&_GLEE_EXT_texture_compression_rgtc) +#define GLEE_EXT_texture_shared_exponent GLeeEnabled(&_GLEE_EXT_texture_shared_exponent) +#define GLEE_NV_depth_buffer_float GLeeEnabled(&_GLEE_NV_depth_buffer_float) +#define GLEE_NV_framebuffer_multisample_coverage GLeeEnabled(&_GLEE_NV_framebuffer_multisample_coverage) +#define GLEE_EXT_framebuffer_sRGB GLeeEnabled(&_GLEE_EXT_framebuffer_sRGB) +#define GLEE_NV_geometry_shader4 GLeeEnabled(&_GLEE_NV_geometry_shader4) +#define GLEE_NV_parameter_buffer_object GLeeEnabled(&_GLEE_NV_parameter_buffer_object) +#define GLEE_EXT_draw_buffers2 GLeeEnabled(&_GLEE_EXT_draw_buffers2) +#define GLEE_NV_transform_feedback GLeeEnabled(&_GLEE_NV_transform_feedback) +#define GLEE_EXT_bindable_uniform GLeeEnabled(&_GLEE_EXT_bindable_uniform) +#define GLEE_EXT_texture_integer GLeeEnabled(&_GLEE_EXT_texture_integer) +#define GLEE_GREMEDY_frame_terminator GLeeEnabled(&_GLEE_GREMEDY_frame_terminator) +#define GLEE_NV_conditional_render GLeeEnabled(&_GLEE_NV_conditional_render) +#define GLEE_NV_present_video GLeeEnabled(&_GLEE_NV_present_video) +#define GLEE_EXT_transform_feedback GLeeEnabled(&_GLEE_EXT_transform_feedback) +#define GLEE_EXT_direct_state_access GLeeEnabled(&_GLEE_EXT_direct_state_access) +#define GLEE_EXT_vertex_array_bgra GLeeEnabled(&_GLEE_EXT_vertex_array_bgra) +#define GLEE_EXT_texture_swizzle GLeeEnabled(&_GLEE_EXT_texture_swizzle) +#define GLEE_NV_explicit_multisample GLeeEnabled(&_GLEE_NV_explicit_multisample) +#define GLEE_NV_transform_feedback2 GLeeEnabled(&_GLEE_NV_transform_feedback2) +#define GLEE_SGIX_texture_select GLeeEnabled(&_GLEE_SGIX_texture_select) +#define GLEE_INGR_blend_func_separate GLeeEnabled(&_GLEE_INGR_blend_func_separate) +#define GLEE_SGIX_depth_pass_instrument GLeeEnabled(&_GLEE_SGIX_depth_pass_instrument) +#define GLEE_SGIX_igloo_interface GLeeEnabled(&_GLEE_SGIX_igloo_interface) +#define GLEE_EXT_fragment_lighting GLeeEnabled(&_GLEE_EXT_fragment_lighting) +#define GLEE_EXT_geometry_shader4 GLeeEnabled(&_GLEE_EXT_geometry_shader4) +#define GLEE_EXT_scene_marker GLeeEnabled(&_GLEE_EXT_scene_marker) +#define GLEE_EXT_texture_compression_dxt1 GLeeEnabled(&_GLEE_EXT_texture_compression_dxt1) +#define GLEE_EXT_texture_env GLeeEnabled(&_GLEE_EXT_texture_env) +#define GLEE_IBM_static_data GLeeEnabled(&_GLEE_IBM_static_data) +#define GLEE_NV_gpu_program4 GLeeEnabled(&_GLEE_NV_gpu_program4) +#define GLEE_OES_byte_coordinates GLeeEnabled(&_GLEE_OES_byte_coordinates) +#define GLEE_OES_compressed_paletted_texture GLeeEnabled(&_GLEE_OES_compressed_paletted_texture) +#define GLEE_OES_single_precision GLeeEnabled(&_GLEE_OES_single_precision) +#define GLEE_SGIX_pixel_texture_bits GLeeEnabled(&_GLEE_SGIX_pixel_texture_bits) +#define GLEE_SGIX_texture_range GLeeEnabled(&_GLEE_SGIX_texture_range) + + +/***************************************************************** + * Additional types needed for extensions + *****************************************************************/ + +/* Used for GLSL shader text */ +#ifndef GL_VERSION_2_0 + typedef char GLchar; +#endif + +#include + +#ifndef GL_VERSION_1_5 + typedef ptrdiff_t GLintptr; + typedef ptrdiff_t GLsizeiptr; +#endif + +#ifndef GL_NV_half_float + typedef unsigned short GLhalfNV; +#endif + +#ifndef GL_ARB_vertex_buffer_object + typedef ptrdiff_t GLintptrARB; + typedef ptrdiff_t GLsizeiptrARB; +#endif + +#ifndef GL_ARB_shader_objects + typedef int GLhandleARB; + typedef char GLcharARB; +#endif + +#ifndef GL_EXT_timer_query + typedef signed long long GLint64EXT; + typedef unsigned long long GLuint64EXT; +#endif + +/* Platform-specific */ + +#ifdef WIN32 + + /* WGL */ + + #ifndef WGL_ARB_pbuffer + DECLARE_HANDLE(HPBUFFERARB); + #endif + + #ifndef WGL_EXT_pbuffer + DECLARE_HANDLE(HPBUFFEREXT); + #endif + + #ifndef WGL_NV_video_output + DECLARE_HANDLE(HPVIDEODEV); + #endif + + #ifndef WGL_NV_present_video + DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV); + #endif + + #ifndef WGL_NV_gpu_affinity + DECLARE_HANDLE(HPGPUNV); + DECLARE_HANDLE(HGPUNV); + + typedef struct _GPU_DEVICE { + DWORD cb; + CHAR DeviceName[32]; + CHAR DeviceString[128]; + DWORD Flags; + RECT rcVirtualScreen; + } GPU_DEVICE, *PGPU_DEVICE; + #endif + +#elif defined(__APPLE__) || defined(__APPLE_CC__) + + /* Mac OS X */ + +#else + + /* GLX */ + + typedef void (*__GLXextFuncPtr)(void); + + #ifndef GLX_ARB_get_proc_address + #define GLX_ARB_get_proc_address 1 + extern __GLXextFuncPtr glXGetProcAddressARB (const GLubyte *); + extern void ( * glXGetProcAddressARB (const GLubyte *procName))(void); + typedef __GLXextFuncPtr ( * PFNGLXGETPROCADDRESSARBPROC) (const GLubyte *procName); + #endif + + #ifndef GLX_SGIX_fbconfig + typedef XID GLXFBConfigIDSGIX; + typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; + #endif + + #ifndef GLX_SGIX_pbuffer + typedef XID GLXPbufferSGIX; + typedef struct { + int type; + unsigned long serial; + Bool send_event; + Display *display; + GLXDrawable drawable; + int event_type; + int draw_type; + unsigned int mask; + int x, y; + int width, height; + int count; + } GLXBufferClobberEventSGIX; + #endif + + #ifndef GLX_SGIX_hyperpipe + #define _GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80 + typedef struct + { + char pipeName[_GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int networkId; + } GLXHyperpipeNetworkSGIX; + + typedef struct + { + char pipeName[_GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int channel; + unsigned int participationType; + int timeSlice; + } GLXHyperpipeConfigSGIX; + + typedef struct + { + char pipeName[_GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int srcXOrigin; + int srcYOrigin; + int srcWidth; + int srcHeight; + int destXOrigin; + int destYOrigin; + int destWidth; + int destHeight; + } GLXPipeRect; + + typedef struct + { + char pipeName[_GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int XOrigin; + int YOrigin; + int maxHeight; + int maxWidth; + } GLXPipeRectLimits; + #endif + + #ifndef GLX_NV_video_output + typedef unsigned int GLXVideoDeviceNV; + #endif // GLX_NV_video_output + +#endif /* end platform specific */ + + + +/* GL_VERSION_1_2 */ + +#ifndef GL_VERSION_1_2 +#define GL_VERSION_1_2 1 +#define __GLEE_GL_VERSION_1_2 1 +/* Constants */ +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_RESCALE_NORMAL 0x803A +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 +#define GL_SINGLE_COLOR 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR 0x81FA +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#ifndef GLEE_H_DEFINED_glBlendColor +#define GLEE_H_DEFINED_glBlendColor + typedef void (APIENTRYP GLEEPFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + GLEE_EXTERN GLEEPFNGLBLENDCOLORPROC GLeeFuncPtr_glBlendColor; + #define glBlendColor GLeeFuncPtr_glBlendColor +#endif +#ifndef GLEE_H_DEFINED_glBlendEquation +#define GLEE_H_DEFINED_glBlendEquation + typedef void (APIENTRYP GLEEPFNGLBLENDEQUATIONPROC) (GLenum mode); + GLEE_EXTERN GLEEPFNGLBLENDEQUATIONPROC GLeeFuncPtr_glBlendEquation; + #define glBlendEquation GLeeFuncPtr_glBlendEquation +#endif +#ifndef GLEE_H_DEFINED_glDrawRangeElements +#define GLEE_H_DEFINED_glDrawRangeElements + typedef void (APIENTRYP GLEEPFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices); + GLEE_EXTERN GLEEPFNGLDRAWRANGEELEMENTSPROC GLeeFuncPtr_glDrawRangeElements; + #define glDrawRangeElements GLeeFuncPtr_glDrawRangeElements +#endif +#ifndef GLEE_H_DEFINED_glColorTable +#define GLEE_H_DEFINED_glColorTable + typedef void (APIENTRYP GLEEPFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * table); + GLEE_EXTERN GLEEPFNGLCOLORTABLEPROC GLeeFuncPtr_glColorTable; + #define glColorTable GLeeFuncPtr_glColorTable +#endif +#ifndef GLEE_H_DEFINED_glColorTableParameterfv +#define GLEE_H_DEFINED_glColorTableParameterfv + typedef void (APIENTRYP GLEEPFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLCOLORTABLEPARAMETERFVPROC GLeeFuncPtr_glColorTableParameterfv; + #define glColorTableParameterfv GLeeFuncPtr_glColorTableParameterfv +#endif +#ifndef GLEE_H_DEFINED_glColorTableParameteriv +#define GLEE_H_DEFINED_glColorTableParameteriv + typedef void (APIENTRYP GLEEPFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLCOLORTABLEPARAMETERIVPROC GLeeFuncPtr_glColorTableParameteriv; + #define glColorTableParameteriv GLeeFuncPtr_glColorTableParameteriv +#endif +#ifndef GLEE_H_DEFINED_glCopyColorTable +#define GLEE_H_DEFINED_glCopyColorTable + typedef void (APIENTRYP GLEEPFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); + GLEE_EXTERN GLEEPFNGLCOPYCOLORTABLEPROC GLeeFuncPtr_glCopyColorTable; + #define glCopyColorTable GLeeFuncPtr_glCopyColorTable +#endif +#ifndef GLEE_H_DEFINED_glGetColorTable +#define GLEE_H_DEFINED_glGetColorTable + typedef void (APIENTRYP GLEEPFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid * table); + GLEE_EXTERN GLEEPFNGLGETCOLORTABLEPROC GLeeFuncPtr_glGetColorTable; + #define glGetColorTable GLeeFuncPtr_glGetColorTable +#endif +#ifndef GLEE_H_DEFINED_glGetColorTableParameterfv +#define GLEE_H_DEFINED_glGetColorTableParameterfv + typedef void (APIENTRYP GLEEPFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETCOLORTABLEPARAMETERFVPROC GLeeFuncPtr_glGetColorTableParameterfv; + #define glGetColorTableParameterfv GLeeFuncPtr_glGetColorTableParameterfv +#endif +#ifndef GLEE_H_DEFINED_glGetColorTableParameteriv +#define GLEE_H_DEFINED_glGetColorTableParameteriv + typedef void (APIENTRYP GLEEPFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETCOLORTABLEPARAMETERIVPROC GLeeFuncPtr_glGetColorTableParameteriv; + #define glGetColorTableParameteriv GLeeFuncPtr_glGetColorTableParameteriv +#endif +#ifndef GLEE_H_DEFINED_glColorSubTable +#define GLEE_H_DEFINED_glColorSubTable + typedef void (APIENTRYP GLEEPFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLCOLORSUBTABLEPROC GLeeFuncPtr_glColorSubTable; + #define glColorSubTable GLeeFuncPtr_glColorSubTable +#endif +#ifndef GLEE_H_DEFINED_glCopyColorSubTable +#define GLEE_H_DEFINED_glCopyColorSubTable + typedef void (APIENTRYP GLEEPFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); + GLEE_EXTERN GLEEPFNGLCOPYCOLORSUBTABLEPROC GLeeFuncPtr_glCopyColorSubTable; + #define glCopyColorSubTable GLeeFuncPtr_glCopyColorSubTable +#endif +#ifndef GLEE_H_DEFINED_glConvolutionFilter1D +#define GLEE_H_DEFINED_glConvolutionFilter1D + typedef void (APIENTRYP GLEEPFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * image); + GLEE_EXTERN GLEEPFNGLCONVOLUTIONFILTER1DPROC GLeeFuncPtr_glConvolutionFilter1D; + #define glConvolutionFilter1D GLeeFuncPtr_glConvolutionFilter1D +#endif +#ifndef GLEE_H_DEFINED_glConvolutionFilter2D +#define GLEE_H_DEFINED_glConvolutionFilter2D + typedef void (APIENTRYP GLEEPFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * image); + GLEE_EXTERN GLEEPFNGLCONVOLUTIONFILTER2DPROC GLeeFuncPtr_glConvolutionFilter2D; + #define glConvolutionFilter2D GLeeFuncPtr_glConvolutionFilter2D +#endif +#ifndef GLEE_H_DEFINED_glConvolutionParameterf +#define GLEE_H_DEFINED_glConvolutionParameterf + typedef void (APIENTRYP GLEEPFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params); + GLEE_EXTERN GLEEPFNGLCONVOLUTIONPARAMETERFPROC GLeeFuncPtr_glConvolutionParameterf; + #define glConvolutionParameterf GLeeFuncPtr_glConvolutionParameterf +#endif +#ifndef GLEE_H_DEFINED_glConvolutionParameterfv +#define GLEE_H_DEFINED_glConvolutionParameterfv + typedef void (APIENTRYP GLEEPFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLCONVOLUTIONPARAMETERFVPROC GLeeFuncPtr_glConvolutionParameterfv; + #define glConvolutionParameterfv GLeeFuncPtr_glConvolutionParameterfv +#endif +#ifndef GLEE_H_DEFINED_glConvolutionParameteri +#define GLEE_H_DEFINED_glConvolutionParameteri + typedef void (APIENTRYP GLEEPFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params); + GLEE_EXTERN GLEEPFNGLCONVOLUTIONPARAMETERIPROC GLeeFuncPtr_glConvolutionParameteri; + #define glConvolutionParameteri GLeeFuncPtr_glConvolutionParameteri +#endif +#ifndef GLEE_H_DEFINED_glConvolutionParameteriv +#define GLEE_H_DEFINED_glConvolutionParameteriv + typedef void (APIENTRYP GLEEPFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLCONVOLUTIONPARAMETERIVPROC GLeeFuncPtr_glConvolutionParameteriv; + #define glConvolutionParameteriv GLeeFuncPtr_glConvolutionParameteriv +#endif +#ifndef GLEE_H_DEFINED_glCopyConvolutionFilter1D +#define GLEE_H_DEFINED_glCopyConvolutionFilter1D + typedef void (APIENTRYP GLEEPFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); + GLEE_EXTERN GLEEPFNGLCOPYCONVOLUTIONFILTER1DPROC GLeeFuncPtr_glCopyConvolutionFilter1D; + #define glCopyConvolutionFilter1D GLeeFuncPtr_glCopyConvolutionFilter1D +#endif +#ifndef GLEE_H_DEFINED_glCopyConvolutionFilter2D +#define GLEE_H_DEFINED_glCopyConvolutionFilter2D + typedef void (APIENTRYP GLEEPFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLCOPYCONVOLUTIONFILTER2DPROC GLeeFuncPtr_glCopyConvolutionFilter2D; + #define glCopyConvolutionFilter2D GLeeFuncPtr_glCopyConvolutionFilter2D +#endif +#ifndef GLEE_H_DEFINED_glGetConvolutionFilter +#define GLEE_H_DEFINED_glGetConvolutionFilter + typedef void (APIENTRYP GLEEPFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid * image); + GLEE_EXTERN GLEEPFNGLGETCONVOLUTIONFILTERPROC GLeeFuncPtr_glGetConvolutionFilter; + #define glGetConvolutionFilter GLeeFuncPtr_glGetConvolutionFilter +#endif +#ifndef GLEE_H_DEFINED_glGetConvolutionParameterfv +#define GLEE_H_DEFINED_glGetConvolutionParameterfv + typedef void (APIENTRYP GLEEPFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETCONVOLUTIONPARAMETERFVPROC GLeeFuncPtr_glGetConvolutionParameterfv; + #define glGetConvolutionParameterfv GLeeFuncPtr_glGetConvolutionParameterfv +#endif +#ifndef GLEE_H_DEFINED_glGetConvolutionParameteriv +#define GLEE_H_DEFINED_glGetConvolutionParameteriv + typedef void (APIENTRYP GLEEPFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETCONVOLUTIONPARAMETERIVPROC GLeeFuncPtr_glGetConvolutionParameteriv; + #define glGetConvolutionParameteriv GLeeFuncPtr_glGetConvolutionParameteriv +#endif +#ifndef GLEE_H_DEFINED_glGetSeparableFilter +#define GLEE_H_DEFINED_glGetSeparableFilter + typedef void (APIENTRYP GLEEPFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid * row, GLvoid * column, GLvoid * span); + GLEE_EXTERN GLEEPFNGLGETSEPARABLEFILTERPROC GLeeFuncPtr_glGetSeparableFilter; + #define glGetSeparableFilter GLeeFuncPtr_glGetSeparableFilter +#endif +#ifndef GLEE_H_DEFINED_glSeparableFilter2D +#define GLEE_H_DEFINED_glSeparableFilter2D + typedef void (APIENTRYP GLEEPFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * row, const GLvoid * column); + GLEE_EXTERN GLEEPFNGLSEPARABLEFILTER2DPROC GLeeFuncPtr_glSeparableFilter2D; + #define glSeparableFilter2D GLeeFuncPtr_glSeparableFilter2D +#endif +#ifndef GLEE_H_DEFINED_glGetHistogram +#define GLEE_H_DEFINED_glGetHistogram + typedef void (APIENTRYP GLEEPFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values); + GLEE_EXTERN GLEEPFNGLGETHISTOGRAMPROC GLeeFuncPtr_glGetHistogram; + #define glGetHistogram GLeeFuncPtr_glGetHistogram +#endif +#ifndef GLEE_H_DEFINED_glGetHistogramParameterfv +#define GLEE_H_DEFINED_glGetHistogramParameterfv + typedef void (APIENTRYP GLEEPFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETHISTOGRAMPARAMETERFVPROC GLeeFuncPtr_glGetHistogramParameterfv; + #define glGetHistogramParameterfv GLeeFuncPtr_glGetHistogramParameterfv +#endif +#ifndef GLEE_H_DEFINED_glGetHistogramParameteriv +#define GLEE_H_DEFINED_glGetHistogramParameteriv + typedef void (APIENTRYP GLEEPFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETHISTOGRAMPARAMETERIVPROC GLeeFuncPtr_glGetHistogramParameteriv; + #define glGetHistogramParameteriv GLeeFuncPtr_glGetHistogramParameteriv +#endif +#ifndef GLEE_H_DEFINED_glGetMinmax +#define GLEE_H_DEFINED_glGetMinmax + typedef void (APIENTRYP GLEEPFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values); + GLEE_EXTERN GLEEPFNGLGETMINMAXPROC GLeeFuncPtr_glGetMinmax; + #define glGetMinmax GLeeFuncPtr_glGetMinmax +#endif +#ifndef GLEE_H_DEFINED_glGetMinmaxParameterfv +#define GLEE_H_DEFINED_glGetMinmaxParameterfv + typedef void (APIENTRYP GLEEPFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETMINMAXPARAMETERFVPROC GLeeFuncPtr_glGetMinmaxParameterfv; + #define glGetMinmaxParameterfv GLeeFuncPtr_glGetMinmaxParameterfv +#endif +#ifndef GLEE_H_DEFINED_glGetMinmaxParameteriv +#define GLEE_H_DEFINED_glGetMinmaxParameteriv + typedef void (APIENTRYP GLEEPFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETMINMAXPARAMETERIVPROC GLeeFuncPtr_glGetMinmaxParameteriv; + #define glGetMinmaxParameteriv GLeeFuncPtr_glGetMinmaxParameteriv +#endif +#ifndef GLEE_H_DEFINED_glHistogram +#define GLEE_H_DEFINED_glHistogram + typedef void (APIENTRYP GLEEPFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); + GLEE_EXTERN GLEEPFNGLHISTOGRAMPROC GLeeFuncPtr_glHistogram; + #define glHistogram GLeeFuncPtr_glHistogram +#endif +#ifndef GLEE_H_DEFINED_glMinmax +#define GLEE_H_DEFINED_glMinmax + typedef void (APIENTRYP GLEEPFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink); + GLEE_EXTERN GLEEPFNGLMINMAXPROC GLeeFuncPtr_glMinmax; + #define glMinmax GLeeFuncPtr_glMinmax +#endif +#ifndef GLEE_H_DEFINED_glResetHistogram +#define GLEE_H_DEFINED_glResetHistogram + typedef void (APIENTRYP GLEEPFNGLRESETHISTOGRAMPROC) (GLenum target); + GLEE_EXTERN GLEEPFNGLRESETHISTOGRAMPROC GLeeFuncPtr_glResetHistogram; + #define glResetHistogram GLeeFuncPtr_glResetHistogram +#endif +#ifndef GLEE_H_DEFINED_glResetMinmax +#define GLEE_H_DEFINED_glResetMinmax + typedef void (APIENTRYP GLEEPFNGLRESETMINMAXPROC) (GLenum target); + GLEE_EXTERN GLEEPFNGLRESETMINMAXPROC GLeeFuncPtr_glResetMinmax; + #define glResetMinmax GLeeFuncPtr_glResetMinmax +#endif +#ifndef GLEE_H_DEFINED_glTexImage3D +#define GLEE_H_DEFINED_glTexImage3D + typedef void (APIENTRYP GLEEPFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLTEXIMAGE3DPROC GLeeFuncPtr_glTexImage3D; + #define glTexImage3D GLeeFuncPtr_glTexImage3D +#endif +#ifndef GLEE_H_DEFINED_glTexSubImage3D +#define GLEE_H_DEFINED_glTexSubImage3D + typedef void (APIENTRYP GLEEPFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLTEXSUBIMAGE3DPROC GLeeFuncPtr_glTexSubImage3D; + #define glTexSubImage3D GLeeFuncPtr_glTexSubImage3D +#endif +#ifndef GLEE_H_DEFINED_glCopyTexSubImage3D +#define GLEE_H_DEFINED_glCopyTexSubImage3D + typedef void (APIENTRYP GLEEPFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLCOPYTEXSUBIMAGE3DPROC GLeeFuncPtr_glCopyTexSubImage3D; + #define glCopyTexSubImage3D GLeeFuncPtr_glCopyTexSubImage3D +#endif +#endif + +/* GL_ARB_imaging */ + +#ifndef GL_ARB_imaging +#define GL_ARB_imaging 1 +#define __GLEE_GL_ARB_imaging 1 +/* Constants */ +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 +#define GL_FUNC_ADD 0x8006 +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_BLEND_EQUATION 0x8009 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_CONVOLUTION_1D 0x8010 +#define GL_CONVOLUTION_2D 0x8011 +#define GL_SEPARABLE_2D 0x8012 +#define GL_CONVOLUTION_BORDER_MODE 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS 0x8015 +#define GL_REDUCE 0x8016 +#define GL_CONVOLUTION_FORMAT 0x8017 +#define GL_CONVOLUTION_WIDTH 0x8018 +#define GL_CONVOLUTION_HEIGHT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 +#define GL_HISTOGRAM 0x8024 +#define GL_PROXY_HISTOGRAM 0x8025 +#define GL_HISTOGRAM_WIDTH 0x8026 +#define GL_HISTOGRAM_FORMAT 0x8027 +#define GL_HISTOGRAM_RED_SIZE 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C +#define GL_HISTOGRAM_SINK 0x802D +#define GL_MINMAX 0x802E +#define GL_MINMAX_FORMAT 0x802F +#define GL_MINMAX_SINK 0x8030 +#define GL_TABLE_TOO_LARGE 0x8031 +#define GL_COLOR_MATRIX 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB +#define GL_COLOR_TABLE 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 +#define GL_PROXY_COLOR_TABLE 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 +#define GL_COLOR_TABLE_SCALE 0x80D6 +#define GL_COLOR_TABLE_BIAS 0x80D7 +#define GL_COLOR_TABLE_FORMAT 0x80D8 +#define GL_COLOR_TABLE_WIDTH 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF +#define GL_CONSTANT_BORDER 0x8151 +#define GL_REPLICATE_BORDER 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR 0x8154 +#endif + +/* GL_VERSION_1_3 */ + +#ifndef GL_VERSION_1_3 +#define GL_VERSION_1_3 1 +#define __GLEE_GL_VERSION_1_3 1 +/* Constants */ +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 +#define GL_MAX_TEXTURE_UNITS 0x84E2 +#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_MULTISAMPLE_BIT 0x20000000 +#define GL_NORMAL_MAP 0x8511 +#define GL_REFLECTION_MAP 0x8512 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_COMPRESSED_ALPHA 0x84E9 +#define GL_COMPRESSED_LUMINANCE 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB +#define GL_COMPRESSED_INTENSITY 0x84EC +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_COMBINE 0x8570 +#define GL_COMBINE_RGB 0x8571 +#define GL_COMBINE_ALPHA 0x8572 +#define GL_SOURCE0_RGB 0x8580 +#define GL_SOURCE1_RGB 0x8581 +#define GL_SOURCE2_RGB 0x8582 +#define GL_SOURCE0_ALPHA 0x8588 +#define GL_SOURCE1_ALPHA 0x8589 +#define GL_SOURCE2_ALPHA 0x858A +#define GL_OPERAND0_RGB 0x8590 +#define GL_OPERAND1_RGB 0x8591 +#define GL_OPERAND2_RGB 0x8592 +#define GL_OPERAND0_ALPHA 0x8598 +#define GL_OPERAND1_ALPHA 0x8599 +#define GL_OPERAND2_ALPHA 0x859A +#define GL_RGB_SCALE 0x8573 +#define GL_ADD_SIGNED 0x8574 +#define GL_INTERPOLATE 0x8575 +#define GL_SUBTRACT 0x84E7 +#define GL_CONSTANT 0x8576 +#define GL_PRIMARY_COLOR 0x8577 +#define GL_PREVIOUS 0x8578 +#define GL_DOT3_RGB 0x86AE +#define GL_DOT3_RGBA 0x86AF +#ifndef GLEE_H_DEFINED_glActiveTexture +#define GLEE_H_DEFINED_glActiveTexture + typedef void (APIENTRYP GLEEPFNGLACTIVETEXTUREPROC) (GLenum texture); + GLEE_EXTERN GLEEPFNGLACTIVETEXTUREPROC GLeeFuncPtr_glActiveTexture; + #define glActiveTexture GLeeFuncPtr_glActiveTexture +#endif +#ifndef GLEE_H_DEFINED_glClientActiveTexture +#define GLEE_H_DEFINED_glClientActiveTexture + typedef void (APIENTRYP GLEEPFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture); + GLEE_EXTERN GLEEPFNGLCLIENTACTIVETEXTUREPROC GLeeFuncPtr_glClientActiveTexture; + #define glClientActiveTexture GLeeFuncPtr_glClientActiveTexture +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1d +#define GLEE_H_DEFINED_glMultiTexCoord1d + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1DPROC GLeeFuncPtr_glMultiTexCoord1d; + #define glMultiTexCoord1d GLeeFuncPtr_glMultiTexCoord1d +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1dv +#define GLEE_H_DEFINED_glMultiTexCoord1dv + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1DVPROC GLeeFuncPtr_glMultiTexCoord1dv; + #define glMultiTexCoord1dv GLeeFuncPtr_glMultiTexCoord1dv +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1f +#define GLEE_H_DEFINED_glMultiTexCoord1f + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1FPROC GLeeFuncPtr_glMultiTexCoord1f; + #define glMultiTexCoord1f GLeeFuncPtr_glMultiTexCoord1f +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1fv +#define GLEE_H_DEFINED_glMultiTexCoord1fv + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1FVPROC GLeeFuncPtr_glMultiTexCoord1fv; + #define glMultiTexCoord1fv GLeeFuncPtr_glMultiTexCoord1fv +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1i +#define GLEE_H_DEFINED_glMultiTexCoord1i + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1IPROC GLeeFuncPtr_glMultiTexCoord1i; + #define glMultiTexCoord1i GLeeFuncPtr_glMultiTexCoord1i +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1iv +#define GLEE_H_DEFINED_glMultiTexCoord1iv + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1IVPROC GLeeFuncPtr_glMultiTexCoord1iv; + #define glMultiTexCoord1iv GLeeFuncPtr_glMultiTexCoord1iv +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1s +#define GLEE_H_DEFINED_glMultiTexCoord1s + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1SPROC GLeeFuncPtr_glMultiTexCoord1s; + #define glMultiTexCoord1s GLeeFuncPtr_glMultiTexCoord1s +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1sv +#define GLEE_H_DEFINED_glMultiTexCoord1sv + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1SVPROC GLeeFuncPtr_glMultiTexCoord1sv; + #define glMultiTexCoord1sv GLeeFuncPtr_glMultiTexCoord1sv +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2d +#define GLEE_H_DEFINED_glMultiTexCoord2d + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2DPROC GLeeFuncPtr_glMultiTexCoord2d; + #define glMultiTexCoord2d GLeeFuncPtr_glMultiTexCoord2d +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2dv +#define GLEE_H_DEFINED_glMultiTexCoord2dv + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2DVPROC GLeeFuncPtr_glMultiTexCoord2dv; + #define glMultiTexCoord2dv GLeeFuncPtr_glMultiTexCoord2dv +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2f +#define GLEE_H_DEFINED_glMultiTexCoord2f + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2FPROC GLeeFuncPtr_glMultiTexCoord2f; + #define glMultiTexCoord2f GLeeFuncPtr_glMultiTexCoord2f +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2fv +#define GLEE_H_DEFINED_glMultiTexCoord2fv + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2FVPROC GLeeFuncPtr_glMultiTexCoord2fv; + #define glMultiTexCoord2fv GLeeFuncPtr_glMultiTexCoord2fv +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2i +#define GLEE_H_DEFINED_glMultiTexCoord2i + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2IPROC GLeeFuncPtr_glMultiTexCoord2i; + #define glMultiTexCoord2i GLeeFuncPtr_glMultiTexCoord2i +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2iv +#define GLEE_H_DEFINED_glMultiTexCoord2iv + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2IVPROC GLeeFuncPtr_glMultiTexCoord2iv; + #define glMultiTexCoord2iv GLeeFuncPtr_glMultiTexCoord2iv +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2s +#define GLEE_H_DEFINED_glMultiTexCoord2s + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2SPROC GLeeFuncPtr_glMultiTexCoord2s; + #define glMultiTexCoord2s GLeeFuncPtr_glMultiTexCoord2s +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2sv +#define GLEE_H_DEFINED_glMultiTexCoord2sv + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2SVPROC GLeeFuncPtr_glMultiTexCoord2sv; + #define glMultiTexCoord2sv GLeeFuncPtr_glMultiTexCoord2sv +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3d +#define GLEE_H_DEFINED_glMultiTexCoord3d + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3DPROC GLeeFuncPtr_glMultiTexCoord3d; + #define glMultiTexCoord3d GLeeFuncPtr_glMultiTexCoord3d +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3dv +#define GLEE_H_DEFINED_glMultiTexCoord3dv + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3DVPROC GLeeFuncPtr_glMultiTexCoord3dv; + #define glMultiTexCoord3dv GLeeFuncPtr_glMultiTexCoord3dv +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3f +#define GLEE_H_DEFINED_glMultiTexCoord3f + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3FPROC GLeeFuncPtr_glMultiTexCoord3f; + #define glMultiTexCoord3f GLeeFuncPtr_glMultiTexCoord3f +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3fv +#define GLEE_H_DEFINED_glMultiTexCoord3fv + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3FVPROC GLeeFuncPtr_glMultiTexCoord3fv; + #define glMultiTexCoord3fv GLeeFuncPtr_glMultiTexCoord3fv +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3i +#define GLEE_H_DEFINED_glMultiTexCoord3i + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3IPROC GLeeFuncPtr_glMultiTexCoord3i; + #define glMultiTexCoord3i GLeeFuncPtr_glMultiTexCoord3i +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3iv +#define GLEE_H_DEFINED_glMultiTexCoord3iv + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3IVPROC GLeeFuncPtr_glMultiTexCoord3iv; + #define glMultiTexCoord3iv GLeeFuncPtr_glMultiTexCoord3iv +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3s +#define GLEE_H_DEFINED_glMultiTexCoord3s + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3SPROC GLeeFuncPtr_glMultiTexCoord3s; + #define glMultiTexCoord3s GLeeFuncPtr_glMultiTexCoord3s +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3sv +#define GLEE_H_DEFINED_glMultiTexCoord3sv + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3SVPROC GLeeFuncPtr_glMultiTexCoord3sv; + #define glMultiTexCoord3sv GLeeFuncPtr_glMultiTexCoord3sv +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4d +#define GLEE_H_DEFINED_glMultiTexCoord4d + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4DPROC GLeeFuncPtr_glMultiTexCoord4d; + #define glMultiTexCoord4d GLeeFuncPtr_glMultiTexCoord4d +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4dv +#define GLEE_H_DEFINED_glMultiTexCoord4dv + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4DVPROC GLeeFuncPtr_glMultiTexCoord4dv; + #define glMultiTexCoord4dv GLeeFuncPtr_glMultiTexCoord4dv +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4f +#define GLEE_H_DEFINED_glMultiTexCoord4f + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4FPROC GLeeFuncPtr_glMultiTexCoord4f; + #define glMultiTexCoord4f GLeeFuncPtr_glMultiTexCoord4f +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4fv +#define GLEE_H_DEFINED_glMultiTexCoord4fv + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4FVPROC GLeeFuncPtr_glMultiTexCoord4fv; + #define glMultiTexCoord4fv GLeeFuncPtr_glMultiTexCoord4fv +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4i +#define GLEE_H_DEFINED_glMultiTexCoord4i + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4IPROC GLeeFuncPtr_glMultiTexCoord4i; + #define glMultiTexCoord4i GLeeFuncPtr_glMultiTexCoord4i +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4iv +#define GLEE_H_DEFINED_glMultiTexCoord4iv + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4IVPROC GLeeFuncPtr_glMultiTexCoord4iv; + #define glMultiTexCoord4iv GLeeFuncPtr_glMultiTexCoord4iv +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4s +#define GLEE_H_DEFINED_glMultiTexCoord4s + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4SPROC GLeeFuncPtr_glMultiTexCoord4s; + #define glMultiTexCoord4s GLeeFuncPtr_glMultiTexCoord4s +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4sv +#define GLEE_H_DEFINED_glMultiTexCoord4sv + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4SVPROC GLeeFuncPtr_glMultiTexCoord4sv; + #define glMultiTexCoord4sv GLeeFuncPtr_glMultiTexCoord4sv +#endif +#ifndef GLEE_H_DEFINED_glLoadTransposeMatrixf +#define GLEE_H_DEFINED_glLoadTransposeMatrixf + typedef void (APIENTRYP GLEEPFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat * m); + GLEE_EXTERN GLEEPFNGLLOADTRANSPOSEMATRIXFPROC GLeeFuncPtr_glLoadTransposeMatrixf; + #define glLoadTransposeMatrixf GLeeFuncPtr_glLoadTransposeMatrixf +#endif +#ifndef GLEE_H_DEFINED_glLoadTransposeMatrixd +#define GLEE_H_DEFINED_glLoadTransposeMatrixd + typedef void (APIENTRYP GLEEPFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble * m); + GLEE_EXTERN GLEEPFNGLLOADTRANSPOSEMATRIXDPROC GLeeFuncPtr_glLoadTransposeMatrixd; + #define glLoadTransposeMatrixd GLeeFuncPtr_glLoadTransposeMatrixd +#endif +#ifndef GLEE_H_DEFINED_glMultTransposeMatrixf +#define GLEE_H_DEFINED_glMultTransposeMatrixf + typedef void (APIENTRYP GLEEPFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat * m); + GLEE_EXTERN GLEEPFNGLMULTTRANSPOSEMATRIXFPROC GLeeFuncPtr_glMultTransposeMatrixf; + #define glMultTransposeMatrixf GLeeFuncPtr_glMultTransposeMatrixf +#endif +#ifndef GLEE_H_DEFINED_glMultTransposeMatrixd +#define GLEE_H_DEFINED_glMultTransposeMatrixd + typedef void (APIENTRYP GLEEPFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble * m); + GLEE_EXTERN GLEEPFNGLMULTTRANSPOSEMATRIXDPROC GLeeFuncPtr_glMultTransposeMatrixd; + #define glMultTransposeMatrixd GLeeFuncPtr_glMultTransposeMatrixd +#endif +#ifndef GLEE_H_DEFINED_glSampleCoverage +#define GLEE_H_DEFINED_glSampleCoverage + typedef void (APIENTRYP GLEEPFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert); + GLEE_EXTERN GLEEPFNGLSAMPLECOVERAGEPROC GLeeFuncPtr_glSampleCoverage; + #define glSampleCoverage GLeeFuncPtr_glSampleCoverage +#endif +#ifndef GLEE_H_DEFINED_glCompressedTexImage3D +#define GLEE_H_DEFINED_glCompressedTexImage3D + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXIMAGE3DPROC GLeeFuncPtr_glCompressedTexImage3D; + #define glCompressedTexImage3D GLeeFuncPtr_glCompressedTexImage3D +#endif +#ifndef GLEE_H_DEFINED_glCompressedTexImage2D +#define GLEE_H_DEFINED_glCompressedTexImage2D + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXIMAGE2DPROC GLeeFuncPtr_glCompressedTexImage2D; + #define glCompressedTexImage2D GLeeFuncPtr_glCompressedTexImage2D +#endif +#ifndef GLEE_H_DEFINED_glCompressedTexImage1D +#define GLEE_H_DEFINED_glCompressedTexImage1D + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXIMAGE1DPROC GLeeFuncPtr_glCompressedTexImage1D; + #define glCompressedTexImage1D GLeeFuncPtr_glCompressedTexImage1D +#endif +#ifndef GLEE_H_DEFINED_glCompressedTexSubImage3D +#define GLEE_H_DEFINED_glCompressedTexSubImage3D + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXSUBIMAGE3DPROC GLeeFuncPtr_glCompressedTexSubImage3D; + #define glCompressedTexSubImage3D GLeeFuncPtr_glCompressedTexSubImage3D +#endif +#ifndef GLEE_H_DEFINED_glCompressedTexSubImage2D +#define GLEE_H_DEFINED_glCompressedTexSubImage2D + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXSUBIMAGE2DPROC GLeeFuncPtr_glCompressedTexSubImage2D; + #define glCompressedTexSubImage2D GLeeFuncPtr_glCompressedTexSubImage2D +#endif +#ifndef GLEE_H_DEFINED_glCompressedTexSubImage1D +#define GLEE_H_DEFINED_glCompressedTexSubImage1D + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXSUBIMAGE1DPROC GLeeFuncPtr_glCompressedTexSubImage1D; + #define glCompressedTexSubImage1D GLeeFuncPtr_glCompressedTexSubImage1D +#endif +#ifndef GLEE_H_DEFINED_glGetCompressedTexImage +#define GLEE_H_DEFINED_glGetCompressedTexImage + typedef void (APIENTRYP GLEEPFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid * img); + GLEE_EXTERN GLEEPFNGLGETCOMPRESSEDTEXIMAGEPROC GLeeFuncPtr_glGetCompressedTexImage; + #define glGetCompressedTexImage GLeeFuncPtr_glGetCompressedTexImage +#endif +#endif + +/* GL_VERSION_1_4 */ + +#ifndef GL_VERSION_1_4 +#define GL_VERSION_1_4 1 +#define __GLEE_GL_VERSION_1_4 1 +/* Constants */ +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_POINT_SIZE_MIN 0x8126 +#define GL_POINT_SIZE_MAX 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION 0x8129 +#define GL_GENERATE_MIPMAP 0x8191 +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_FOG_COORDINATE_SOURCE 0x8450 +#define GL_FOG_COORDINATE 0x8451 +#define GL_FRAGMENT_DEPTH 0x8452 +#define GL_CURRENT_FOG_COORDINATE 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456 +#define GL_FOG_COORDINATE_ARRAY 0x8457 +#define GL_COLOR_SUM 0x8458 +#define GL_CURRENT_SECONDARY_COLOR 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D +#define GL_SECONDARY_COLOR_ARRAY 0x845E +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_FILTER_CONTROL 0x8500 +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_DEPTH_TEXTURE_MODE 0x884B +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_COMPARE_R_TO_TEXTURE 0x884E +#ifndef GLEE_H_DEFINED_glBlendFuncSeparate +#define GLEE_H_DEFINED_glBlendFuncSeparate + typedef void (APIENTRYP GLEEPFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + GLEE_EXTERN GLEEPFNGLBLENDFUNCSEPARATEPROC GLeeFuncPtr_glBlendFuncSeparate; + #define glBlendFuncSeparate GLeeFuncPtr_glBlendFuncSeparate +#endif +#ifndef GLEE_H_DEFINED_glFogCoordf +#define GLEE_H_DEFINED_glFogCoordf + typedef void (APIENTRYP GLEEPFNGLFOGCOORDFPROC) (GLfloat coord); + GLEE_EXTERN GLEEPFNGLFOGCOORDFPROC GLeeFuncPtr_glFogCoordf; + #define glFogCoordf GLeeFuncPtr_glFogCoordf +#endif +#ifndef GLEE_H_DEFINED_glFogCoordfv +#define GLEE_H_DEFINED_glFogCoordfv + typedef void (APIENTRYP GLEEPFNGLFOGCOORDFVPROC) (const GLfloat * coord); + GLEE_EXTERN GLEEPFNGLFOGCOORDFVPROC GLeeFuncPtr_glFogCoordfv; + #define glFogCoordfv GLeeFuncPtr_glFogCoordfv +#endif +#ifndef GLEE_H_DEFINED_glFogCoordd +#define GLEE_H_DEFINED_glFogCoordd + typedef void (APIENTRYP GLEEPFNGLFOGCOORDDPROC) (GLdouble coord); + GLEE_EXTERN GLEEPFNGLFOGCOORDDPROC GLeeFuncPtr_glFogCoordd; + #define glFogCoordd GLeeFuncPtr_glFogCoordd +#endif +#ifndef GLEE_H_DEFINED_glFogCoorddv +#define GLEE_H_DEFINED_glFogCoorddv + typedef void (APIENTRYP GLEEPFNGLFOGCOORDDVPROC) (const GLdouble * coord); + GLEE_EXTERN GLEEPFNGLFOGCOORDDVPROC GLeeFuncPtr_glFogCoorddv; + #define glFogCoorddv GLeeFuncPtr_glFogCoorddv +#endif +#ifndef GLEE_H_DEFINED_glFogCoordPointer +#define GLEE_H_DEFINED_glFogCoordPointer + typedef void (APIENTRYP GLEEPFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLFOGCOORDPOINTERPROC GLeeFuncPtr_glFogCoordPointer; + #define glFogCoordPointer GLeeFuncPtr_glFogCoordPointer +#endif +#ifndef GLEE_H_DEFINED_glMultiDrawArrays +#define GLEE_H_DEFINED_glMultiDrawArrays + typedef void (APIENTRYP GLEEPFNGLMULTIDRAWARRAYSPROC) (GLenum mode, GLint * first, GLsizei * count, GLsizei primcount); + GLEE_EXTERN GLEEPFNGLMULTIDRAWARRAYSPROC GLeeFuncPtr_glMultiDrawArrays; + #define glMultiDrawArrays GLeeFuncPtr_glMultiDrawArrays +#endif +#ifndef GLEE_H_DEFINED_glMultiDrawElements +#define GLEE_H_DEFINED_glMultiDrawElements + typedef void (APIENTRYP GLEEPFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei * count, GLenum type, const GLvoid* * indices, GLsizei primcount); + GLEE_EXTERN GLEEPFNGLMULTIDRAWELEMENTSPROC GLeeFuncPtr_glMultiDrawElements; + #define glMultiDrawElements GLeeFuncPtr_glMultiDrawElements +#endif +#ifndef GLEE_H_DEFINED_glPointParameterf +#define GLEE_H_DEFINED_glPointParameterf + typedef void (APIENTRYP GLEEPFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLPOINTPARAMETERFPROC GLeeFuncPtr_glPointParameterf; + #define glPointParameterf GLeeFuncPtr_glPointParameterf +#endif +#ifndef GLEE_H_DEFINED_glPointParameterfv +#define GLEE_H_DEFINED_glPointParameterfv + typedef void (APIENTRYP GLEEPFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLPOINTPARAMETERFVPROC GLeeFuncPtr_glPointParameterfv; + #define glPointParameterfv GLeeFuncPtr_glPointParameterfv +#endif +#ifndef GLEE_H_DEFINED_glPointParameteri +#define GLEE_H_DEFINED_glPointParameteri + typedef void (APIENTRYP GLEEPFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLPOINTPARAMETERIPROC GLeeFuncPtr_glPointParameteri; + #define glPointParameteri GLeeFuncPtr_glPointParameteri +#endif +#ifndef GLEE_H_DEFINED_glPointParameteriv +#define GLEE_H_DEFINED_glPointParameteriv + typedef void (APIENTRYP GLEEPFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLPOINTPARAMETERIVPROC GLeeFuncPtr_glPointParameteriv; + #define glPointParameteriv GLeeFuncPtr_glPointParameteriv +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3b +#define GLEE_H_DEFINED_glSecondaryColor3b + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3BPROC GLeeFuncPtr_glSecondaryColor3b; + #define glSecondaryColor3b GLeeFuncPtr_glSecondaryColor3b +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3bv +#define GLEE_H_DEFINED_glSecondaryColor3bv + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3BVPROC) (const GLbyte * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3BVPROC GLeeFuncPtr_glSecondaryColor3bv; + #define glSecondaryColor3bv GLeeFuncPtr_glSecondaryColor3bv +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3d +#define GLEE_H_DEFINED_glSecondaryColor3d + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3DPROC GLeeFuncPtr_glSecondaryColor3d; + #define glSecondaryColor3d GLeeFuncPtr_glSecondaryColor3d +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3dv +#define GLEE_H_DEFINED_glSecondaryColor3dv + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3DVPROC) (const GLdouble * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3DVPROC GLeeFuncPtr_glSecondaryColor3dv; + #define glSecondaryColor3dv GLeeFuncPtr_glSecondaryColor3dv +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3f +#define GLEE_H_DEFINED_glSecondaryColor3f + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3FPROC GLeeFuncPtr_glSecondaryColor3f; + #define glSecondaryColor3f GLeeFuncPtr_glSecondaryColor3f +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3fv +#define GLEE_H_DEFINED_glSecondaryColor3fv + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3FVPROC) (const GLfloat * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3FVPROC GLeeFuncPtr_glSecondaryColor3fv; + #define glSecondaryColor3fv GLeeFuncPtr_glSecondaryColor3fv +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3i +#define GLEE_H_DEFINED_glSecondaryColor3i + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3IPROC GLeeFuncPtr_glSecondaryColor3i; + #define glSecondaryColor3i GLeeFuncPtr_glSecondaryColor3i +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3iv +#define GLEE_H_DEFINED_glSecondaryColor3iv + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3IVPROC) (const GLint * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3IVPROC GLeeFuncPtr_glSecondaryColor3iv; + #define glSecondaryColor3iv GLeeFuncPtr_glSecondaryColor3iv +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3s +#define GLEE_H_DEFINED_glSecondaryColor3s + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3SPROC GLeeFuncPtr_glSecondaryColor3s; + #define glSecondaryColor3s GLeeFuncPtr_glSecondaryColor3s +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3sv +#define GLEE_H_DEFINED_glSecondaryColor3sv + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3SVPROC) (const GLshort * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3SVPROC GLeeFuncPtr_glSecondaryColor3sv; + #define glSecondaryColor3sv GLeeFuncPtr_glSecondaryColor3sv +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3ub +#define GLEE_H_DEFINED_glSecondaryColor3ub + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3UBPROC GLeeFuncPtr_glSecondaryColor3ub; + #define glSecondaryColor3ub GLeeFuncPtr_glSecondaryColor3ub +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3ubv +#define GLEE_H_DEFINED_glSecondaryColor3ubv + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3UBVPROC GLeeFuncPtr_glSecondaryColor3ubv; + #define glSecondaryColor3ubv GLeeFuncPtr_glSecondaryColor3ubv +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3ui +#define GLEE_H_DEFINED_glSecondaryColor3ui + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3UIPROC GLeeFuncPtr_glSecondaryColor3ui; + #define glSecondaryColor3ui GLeeFuncPtr_glSecondaryColor3ui +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3uiv +#define GLEE_H_DEFINED_glSecondaryColor3uiv + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3UIVPROC) (const GLuint * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3UIVPROC GLeeFuncPtr_glSecondaryColor3uiv; + #define glSecondaryColor3uiv GLeeFuncPtr_glSecondaryColor3uiv +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3us +#define GLEE_H_DEFINED_glSecondaryColor3us + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3USPROC GLeeFuncPtr_glSecondaryColor3us; + #define glSecondaryColor3us GLeeFuncPtr_glSecondaryColor3us +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3usv +#define GLEE_H_DEFINED_glSecondaryColor3usv + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3USVPROC) (const GLushort * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3USVPROC GLeeFuncPtr_glSecondaryColor3usv; + #define glSecondaryColor3usv GLeeFuncPtr_glSecondaryColor3usv +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColorPointer +#define GLEE_H_DEFINED_glSecondaryColorPointer + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLORPOINTERPROC GLeeFuncPtr_glSecondaryColorPointer; + #define glSecondaryColorPointer GLeeFuncPtr_glSecondaryColorPointer +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2d +#define GLEE_H_DEFINED_glWindowPos2d + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2DPROC GLeeFuncPtr_glWindowPos2d; + #define glWindowPos2d GLeeFuncPtr_glWindowPos2d +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2dv +#define GLEE_H_DEFINED_glWindowPos2dv + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2DVPROC) (const GLdouble * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2DVPROC GLeeFuncPtr_glWindowPos2dv; + #define glWindowPos2dv GLeeFuncPtr_glWindowPos2dv +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2f +#define GLEE_H_DEFINED_glWindowPos2f + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2FPROC GLeeFuncPtr_glWindowPos2f; + #define glWindowPos2f GLeeFuncPtr_glWindowPos2f +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2fv +#define GLEE_H_DEFINED_glWindowPos2fv + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2FVPROC) (const GLfloat * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2FVPROC GLeeFuncPtr_glWindowPos2fv; + #define glWindowPos2fv GLeeFuncPtr_glWindowPos2fv +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2i +#define GLEE_H_DEFINED_glWindowPos2i + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2IPROC) (GLint x, GLint y); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2IPROC GLeeFuncPtr_glWindowPos2i; + #define glWindowPos2i GLeeFuncPtr_glWindowPos2i +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2iv +#define GLEE_H_DEFINED_glWindowPos2iv + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2IVPROC) (const GLint * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2IVPROC GLeeFuncPtr_glWindowPos2iv; + #define glWindowPos2iv GLeeFuncPtr_glWindowPos2iv +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2s +#define GLEE_H_DEFINED_glWindowPos2s + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2SPROC GLeeFuncPtr_glWindowPos2s; + #define glWindowPos2s GLeeFuncPtr_glWindowPos2s +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2sv +#define GLEE_H_DEFINED_glWindowPos2sv + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2SVPROC) (const GLshort * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2SVPROC GLeeFuncPtr_glWindowPos2sv; + #define glWindowPos2sv GLeeFuncPtr_glWindowPos2sv +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3d +#define GLEE_H_DEFINED_glWindowPos3d + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3DPROC GLeeFuncPtr_glWindowPos3d; + #define glWindowPos3d GLeeFuncPtr_glWindowPos3d +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3dv +#define GLEE_H_DEFINED_glWindowPos3dv + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3DVPROC) (const GLdouble * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3DVPROC GLeeFuncPtr_glWindowPos3dv; + #define glWindowPos3dv GLeeFuncPtr_glWindowPos3dv +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3f +#define GLEE_H_DEFINED_glWindowPos3f + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3FPROC GLeeFuncPtr_glWindowPos3f; + #define glWindowPos3f GLeeFuncPtr_glWindowPos3f +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3fv +#define GLEE_H_DEFINED_glWindowPos3fv + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3FVPROC) (const GLfloat * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3FVPROC GLeeFuncPtr_glWindowPos3fv; + #define glWindowPos3fv GLeeFuncPtr_glWindowPos3fv +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3i +#define GLEE_H_DEFINED_glWindowPos3i + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3IPROC GLeeFuncPtr_glWindowPos3i; + #define glWindowPos3i GLeeFuncPtr_glWindowPos3i +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3iv +#define GLEE_H_DEFINED_glWindowPos3iv + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3IVPROC) (const GLint * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3IVPROC GLeeFuncPtr_glWindowPos3iv; + #define glWindowPos3iv GLeeFuncPtr_glWindowPos3iv +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3s +#define GLEE_H_DEFINED_glWindowPos3s + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3SPROC GLeeFuncPtr_glWindowPos3s; + #define glWindowPos3s GLeeFuncPtr_glWindowPos3s +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3sv +#define GLEE_H_DEFINED_glWindowPos3sv + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3SVPROC) (const GLshort * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3SVPROC GLeeFuncPtr_glWindowPos3sv; + #define glWindowPos3sv GLeeFuncPtr_glWindowPos3sv +#endif +#endif + +/* GL_VERSION_1_5 */ + +#ifndef GL_VERSION_1_5 +#define GL_VERSION_1_5 1 +#define __GLEE_GL_VERSION_1_5 1 +/* Constants */ +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_SAMPLES_PASSED 0x8914 +#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE +#define GL_FOG_COORD GL_FOG_COORDINATE +#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE +#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE +#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE +#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER +#define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY +#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING +#define GL_SRC0_RGB GL_SOURCE0_RGB +#define GL_SRC1_RGB GL_SOURCE1_RGB +#define GL_SRC2_RGB GL_SOURCE2_RGB +#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA +#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA +#define GL_SRC2_ALPHA GL_SOURCE2_ALPHA +#ifndef GLEE_H_DEFINED_glGenQueries +#define GLEE_H_DEFINED_glGenQueries + typedef void (APIENTRYP GLEEPFNGLGENQUERIESPROC) (GLsizei n, GLuint * ids); + GLEE_EXTERN GLEEPFNGLGENQUERIESPROC GLeeFuncPtr_glGenQueries; + #define glGenQueries GLeeFuncPtr_glGenQueries +#endif +#ifndef GLEE_H_DEFINED_glDeleteQueries +#define GLEE_H_DEFINED_glDeleteQueries + typedef void (APIENTRYP GLEEPFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint * ids); + GLEE_EXTERN GLEEPFNGLDELETEQUERIESPROC GLeeFuncPtr_glDeleteQueries; + #define glDeleteQueries GLeeFuncPtr_glDeleteQueries +#endif +#ifndef GLEE_H_DEFINED_glIsQuery +#define GLEE_H_DEFINED_glIsQuery + typedef GLboolean (APIENTRYP GLEEPFNGLISQUERYPROC) (GLuint id); + GLEE_EXTERN GLEEPFNGLISQUERYPROC GLeeFuncPtr_glIsQuery; + #define glIsQuery GLeeFuncPtr_glIsQuery +#endif +#ifndef GLEE_H_DEFINED_glBeginQuery +#define GLEE_H_DEFINED_glBeginQuery + typedef void (APIENTRYP GLEEPFNGLBEGINQUERYPROC) (GLenum target, GLuint id); + GLEE_EXTERN GLEEPFNGLBEGINQUERYPROC GLeeFuncPtr_glBeginQuery; + #define glBeginQuery GLeeFuncPtr_glBeginQuery +#endif +#ifndef GLEE_H_DEFINED_glEndQuery +#define GLEE_H_DEFINED_glEndQuery + typedef void (APIENTRYP GLEEPFNGLENDQUERYPROC) (GLenum target); + GLEE_EXTERN GLEEPFNGLENDQUERYPROC GLeeFuncPtr_glEndQuery; + #define glEndQuery GLeeFuncPtr_glEndQuery +#endif +#ifndef GLEE_H_DEFINED_glGetQueryiv +#define GLEE_H_DEFINED_glGetQueryiv + typedef void (APIENTRYP GLEEPFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETQUERYIVPROC GLeeFuncPtr_glGetQueryiv; + #define glGetQueryiv GLeeFuncPtr_glGetQueryiv +#endif +#ifndef GLEE_H_DEFINED_glGetQueryObjectiv +#define GLEE_H_DEFINED_glGetQueryObjectiv + typedef void (APIENTRYP GLEEPFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETQUERYOBJECTIVPROC GLeeFuncPtr_glGetQueryObjectiv; + #define glGetQueryObjectiv GLeeFuncPtr_glGetQueryObjectiv +#endif +#ifndef GLEE_H_DEFINED_glGetQueryObjectuiv +#define GLEE_H_DEFINED_glGetQueryObjectuiv + typedef void (APIENTRYP GLEEPFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint * params); + GLEE_EXTERN GLEEPFNGLGETQUERYOBJECTUIVPROC GLeeFuncPtr_glGetQueryObjectuiv; + #define glGetQueryObjectuiv GLeeFuncPtr_glGetQueryObjectuiv +#endif +#ifndef GLEE_H_DEFINED_glBindBuffer +#define GLEE_H_DEFINED_glBindBuffer + typedef void (APIENTRYP GLEEPFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); + GLEE_EXTERN GLEEPFNGLBINDBUFFERPROC GLeeFuncPtr_glBindBuffer; + #define glBindBuffer GLeeFuncPtr_glBindBuffer +#endif +#ifndef GLEE_H_DEFINED_glDeleteBuffers +#define GLEE_H_DEFINED_glDeleteBuffers + typedef void (APIENTRYP GLEEPFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint * buffers); + GLEE_EXTERN GLEEPFNGLDELETEBUFFERSPROC GLeeFuncPtr_glDeleteBuffers; + #define glDeleteBuffers GLeeFuncPtr_glDeleteBuffers +#endif +#ifndef GLEE_H_DEFINED_glGenBuffers +#define GLEE_H_DEFINED_glGenBuffers + typedef void (APIENTRYP GLEEPFNGLGENBUFFERSPROC) (GLsizei n, GLuint * buffers); + GLEE_EXTERN GLEEPFNGLGENBUFFERSPROC GLeeFuncPtr_glGenBuffers; + #define glGenBuffers GLeeFuncPtr_glGenBuffers +#endif +#ifndef GLEE_H_DEFINED_glIsBuffer +#define GLEE_H_DEFINED_glIsBuffer + typedef GLboolean (APIENTRYP GLEEPFNGLISBUFFERPROC) (GLuint buffer); + GLEE_EXTERN GLEEPFNGLISBUFFERPROC GLeeFuncPtr_glIsBuffer; + #define glIsBuffer GLeeFuncPtr_glIsBuffer +#endif +#ifndef GLEE_H_DEFINED_glBufferData +#define GLEE_H_DEFINED_glBufferData + typedef void (APIENTRYP GLEEPFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage); + GLEE_EXTERN GLEEPFNGLBUFFERDATAPROC GLeeFuncPtr_glBufferData; + #define glBufferData GLeeFuncPtr_glBufferData +#endif +#ifndef GLEE_H_DEFINED_glBufferSubData +#define GLEE_H_DEFINED_glBufferSubData + typedef void (APIENTRYP GLEEPFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLBUFFERSUBDATAPROC GLeeFuncPtr_glBufferSubData; + #define glBufferSubData GLeeFuncPtr_glBufferSubData +#endif +#ifndef GLEE_H_DEFINED_glGetBufferSubData +#define GLEE_H_DEFINED_glGetBufferSubData + typedef void (APIENTRYP GLEEPFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid * data); + GLEE_EXTERN GLEEPFNGLGETBUFFERSUBDATAPROC GLeeFuncPtr_glGetBufferSubData; + #define glGetBufferSubData GLeeFuncPtr_glGetBufferSubData +#endif +#ifndef GLEE_H_DEFINED_glMapBuffer +#define GLEE_H_DEFINED_glMapBuffer + typedef GLvoid* (APIENTRYP GLEEPFNGLMAPBUFFERPROC) (GLenum target, GLenum access); + GLEE_EXTERN GLEEPFNGLMAPBUFFERPROC GLeeFuncPtr_glMapBuffer; + #define glMapBuffer GLeeFuncPtr_glMapBuffer +#endif +#ifndef GLEE_H_DEFINED_glUnmapBuffer +#define GLEE_H_DEFINED_glUnmapBuffer + typedef GLboolean (APIENTRYP GLEEPFNGLUNMAPBUFFERPROC) (GLenum target); + GLEE_EXTERN GLEEPFNGLUNMAPBUFFERPROC GLeeFuncPtr_glUnmapBuffer; + #define glUnmapBuffer GLeeFuncPtr_glUnmapBuffer +#endif +#ifndef GLEE_H_DEFINED_glGetBufferParameteriv +#define GLEE_H_DEFINED_glGetBufferParameteriv + typedef void (APIENTRYP GLEEPFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETBUFFERPARAMETERIVPROC GLeeFuncPtr_glGetBufferParameteriv; + #define glGetBufferParameteriv GLeeFuncPtr_glGetBufferParameteriv +#endif +#ifndef GLEE_H_DEFINED_glGetBufferPointerv +#define GLEE_H_DEFINED_glGetBufferPointerv + typedef void (APIENTRYP GLEEPFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid* * params); + GLEE_EXTERN GLEEPFNGLGETBUFFERPOINTERVPROC GLeeFuncPtr_glGetBufferPointerv; + #define glGetBufferPointerv GLeeFuncPtr_glGetBufferPointerv +#endif +#endif + +/* GL_VERSION_2_0 */ + +#ifndef GL_VERSION_2_0 +#define GL_VERSION_2_0 1 +#define __GLEE_GL_VERSION_2_0 1 +/* Constants */ +#define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_POINT_SPRITE 0x8861 +#define GL_COORD_REPLACE 0x8862 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_MAX_TEXTURE_COORDS 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_SHADER_TYPE 0x8B4F +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_DELETE_STATUS 0x8B80 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#ifndef GLEE_H_DEFINED_glBlendEquationSeparate +#define GLEE_H_DEFINED_glBlendEquationSeparate + typedef void (APIENTRYP GLEEPFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha); + GLEE_EXTERN GLEEPFNGLBLENDEQUATIONSEPARATEPROC GLeeFuncPtr_glBlendEquationSeparate; + #define glBlendEquationSeparate GLeeFuncPtr_glBlendEquationSeparate +#endif +#ifndef GLEE_H_DEFINED_glDrawBuffers +#define GLEE_H_DEFINED_glDrawBuffers + typedef void (APIENTRYP GLEEPFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum * bufs); + GLEE_EXTERN GLEEPFNGLDRAWBUFFERSPROC GLeeFuncPtr_glDrawBuffers; + #define glDrawBuffers GLeeFuncPtr_glDrawBuffers +#endif +#ifndef GLEE_H_DEFINED_glStencilOpSeparate +#define GLEE_H_DEFINED_glStencilOpSeparate + typedef void (APIENTRYP GLEEPFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); + GLEE_EXTERN GLEEPFNGLSTENCILOPSEPARATEPROC GLeeFuncPtr_glStencilOpSeparate; + #define glStencilOpSeparate GLeeFuncPtr_glStencilOpSeparate +#endif +#ifndef GLEE_H_DEFINED_glStencilFuncSeparate +#define GLEE_H_DEFINED_glStencilFuncSeparate + typedef void (APIENTRYP GLEEPFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); + GLEE_EXTERN GLEEPFNGLSTENCILFUNCSEPARATEPROC GLeeFuncPtr_glStencilFuncSeparate; + #define glStencilFuncSeparate GLeeFuncPtr_glStencilFuncSeparate +#endif +#ifndef GLEE_H_DEFINED_glStencilMaskSeparate +#define GLEE_H_DEFINED_glStencilMaskSeparate + typedef void (APIENTRYP GLEEPFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask); + GLEE_EXTERN GLEEPFNGLSTENCILMASKSEPARATEPROC GLeeFuncPtr_glStencilMaskSeparate; + #define glStencilMaskSeparate GLeeFuncPtr_glStencilMaskSeparate +#endif +#ifndef GLEE_H_DEFINED_glAttachShader +#define GLEE_H_DEFINED_glAttachShader + typedef void (APIENTRYP GLEEPFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); + GLEE_EXTERN GLEEPFNGLATTACHSHADERPROC GLeeFuncPtr_glAttachShader; + #define glAttachShader GLeeFuncPtr_glAttachShader +#endif +#ifndef GLEE_H_DEFINED_glBindAttribLocation +#define GLEE_H_DEFINED_glBindAttribLocation + typedef void (APIENTRYP GLEEPFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar * name); + GLEE_EXTERN GLEEPFNGLBINDATTRIBLOCATIONPROC GLeeFuncPtr_glBindAttribLocation; + #define glBindAttribLocation GLeeFuncPtr_glBindAttribLocation +#endif +#ifndef GLEE_H_DEFINED_glCompileShader +#define GLEE_H_DEFINED_glCompileShader + typedef void (APIENTRYP GLEEPFNGLCOMPILESHADERPROC) (GLuint shader); + GLEE_EXTERN GLEEPFNGLCOMPILESHADERPROC GLeeFuncPtr_glCompileShader; + #define glCompileShader GLeeFuncPtr_glCompileShader +#endif +#ifndef GLEE_H_DEFINED_glCreateProgram +#define GLEE_H_DEFINED_glCreateProgram + typedef GLuint (APIENTRYP GLEEPFNGLCREATEPROGRAMPROC) (); + GLEE_EXTERN GLEEPFNGLCREATEPROGRAMPROC GLeeFuncPtr_glCreateProgram; + #define glCreateProgram GLeeFuncPtr_glCreateProgram +#endif +#ifndef GLEE_H_DEFINED_glCreateShader +#define GLEE_H_DEFINED_glCreateShader + typedef GLuint (APIENTRYP GLEEPFNGLCREATESHADERPROC) (GLenum type); + GLEE_EXTERN GLEEPFNGLCREATESHADERPROC GLeeFuncPtr_glCreateShader; + #define glCreateShader GLeeFuncPtr_glCreateShader +#endif +#ifndef GLEE_H_DEFINED_glDeleteProgram +#define GLEE_H_DEFINED_glDeleteProgram + typedef void (APIENTRYP GLEEPFNGLDELETEPROGRAMPROC) (GLuint program); + GLEE_EXTERN GLEEPFNGLDELETEPROGRAMPROC GLeeFuncPtr_glDeleteProgram; + #define glDeleteProgram GLeeFuncPtr_glDeleteProgram +#endif +#ifndef GLEE_H_DEFINED_glDeleteShader +#define GLEE_H_DEFINED_glDeleteShader + typedef void (APIENTRYP GLEEPFNGLDELETESHADERPROC) (GLuint shader); + GLEE_EXTERN GLEEPFNGLDELETESHADERPROC GLeeFuncPtr_glDeleteShader; + #define glDeleteShader GLeeFuncPtr_glDeleteShader +#endif +#ifndef GLEE_H_DEFINED_glDetachShader +#define GLEE_H_DEFINED_glDetachShader + typedef void (APIENTRYP GLEEPFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); + GLEE_EXTERN GLEEPFNGLDETACHSHADERPROC GLeeFuncPtr_glDetachShader; + #define glDetachShader GLeeFuncPtr_glDetachShader +#endif +#ifndef GLEE_H_DEFINED_glDisableVertexAttribArray +#define GLEE_H_DEFINED_glDisableVertexAttribArray + typedef void (APIENTRYP GLEEPFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index); + GLEE_EXTERN GLEEPFNGLDISABLEVERTEXATTRIBARRAYPROC GLeeFuncPtr_glDisableVertexAttribArray; + #define glDisableVertexAttribArray GLeeFuncPtr_glDisableVertexAttribArray +#endif +#ifndef GLEE_H_DEFINED_glEnableVertexAttribArray +#define GLEE_H_DEFINED_glEnableVertexAttribArray + typedef void (APIENTRYP GLEEPFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); + GLEE_EXTERN GLEEPFNGLENABLEVERTEXATTRIBARRAYPROC GLeeFuncPtr_glEnableVertexAttribArray; + #define glEnableVertexAttribArray GLeeFuncPtr_glEnableVertexAttribArray +#endif +#ifndef GLEE_H_DEFINED_glGetActiveAttrib +#define GLEE_H_DEFINED_glGetActiveAttrib + typedef void (APIENTRYP GLEEPFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name); + GLEE_EXTERN GLEEPFNGLGETACTIVEATTRIBPROC GLeeFuncPtr_glGetActiveAttrib; + #define glGetActiveAttrib GLeeFuncPtr_glGetActiveAttrib +#endif +#ifndef GLEE_H_DEFINED_glGetActiveUniform +#define GLEE_H_DEFINED_glGetActiveUniform + typedef void (APIENTRYP GLEEPFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name); + GLEE_EXTERN GLEEPFNGLGETACTIVEUNIFORMPROC GLeeFuncPtr_glGetActiveUniform; + #define glGetActiveUniform GLeeFuncPtr_glGetActiveUniform +#endif +#ifndef GLEE_H_DEFINED_glGetAttachedShaders +#define GLEE_H_DEFINED_glGetAttachedShaders + typedef void (APIENTRYP GLEEPFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei * count, GLuint * obj); + GLEE_EXTERN GLEEPFNGLGETATTACHEDSHADERSPROC GLeeFuncPtr_glGetAttachedShaders; + #define glGetAttachedShaders GLeeFuncPtr_glGetAttachedShaders +#endif +#ifndef GLEE_H_DEFINED_glGetAttribLocation +#define GLEE_H_DEFINED_glGetAttribLocation + typedef GLint (APIENTRYP GLEEPFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar * name); + GLEE_EXTERN GLEEPFNGLGETATTRIBLOCATIONPROC GLeeFuncPtr_glGetAttribLocation; + #define glGetAttribLocation GLeeFuncPtr_glGetAttribLocation +#endif +#ifndef GLEE_H_DEFINED_glGetProgramiv +#define GLEE_H_DEFINED_glGetProgramiv + typedef void (APIENTRYP GLEEPFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETPROGRAMIVPROC GLeeFuncPtr_glGetProgramiv; + #define glGetProgramiv GLeeFuncPtr_glGetProgramiv +#endif +#ifndef GLEE_H_DEFINED_glGetProgramInfoLog +#define GLEE_H_DEFINED_glGetProgramInfoLog + typedef void (APIENTRYP GLEEPFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog); + GLEE_EXTERN GLEEPFNGLGETPROGRAMINFOLOGPROC GLeeFuncPtr_glGetProgramInfoLog; + #define glGetProgramInfoLog GLeeFuncPtr_glGetProgramInfoLog +#endif +#ifndef GLEE_H_DEFINED_glGetShaderiv +#define GLEE_H_DEFINED_glGetShaderiv + typedef void (APIENTRYP GLEEPFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETSHADERIVPROC GLeeFuncPtr_glGetShaderiv; + #define glGetShaderiv GLeeFuncPtr_glGetShaderiv +#endif +#ifndef GLEE_H_DEFINED_glGetShaderInfoLog +#define GLEE_H_DEFINED_glGetShaderInfoLog + typedef void (APIENTRYP GLEEPFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog); + GLEE_EXTERN GLEEPFNGLGETSHADERINFOLOGPROC GLeeFuncPtr_glGetShaderInfoLog; + #define glGetShaderInfoLog GLeeFuncPtr_glGetShaderInfoLog +#endif +#ifndef GLEE_H_DEFINED_glGetShaderSource +#define GLEE_H_DEFINED_glGetShaderSource + typedef void (APIENTRYP GLEEPFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source); + GLEE_EXTERN GLEEPFNGLGETSHADERSOURCEPROC GLeeFuncPtr_glGetShaderSource; + #define glGetShaderSource GLeeFuncPtr_glGetShaderSource +#endif +#ifndef GLEE_H_DEFINED_glGetUniformLocation +#define GLEE_H_DEFINED_glGetUniformLocation + typedef GLint (APIENTRYP GLEEPFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar * name); + GLEE_EXTERN GLEEPFNGLGETUNIFORMLOCATIONPROC GLeeFuncPtr_glGetUniformLocation; + #define glGetUniformLocation GLeeFuncPtr_glGetUniformLocation +#endif +#ifndef GLEE_H_DEFINED_glGetUniformfv +#define GLEE_H_DEFINED_glGetUniformfv + typedef void (APIENTRYP GLEEPFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETUNIFORMFVPROC GLeeFuncPtr_glGetUniformfv; + #define glGetUniformfv GLeeFuncPtr_glGetUniformfv +#endif +#ifndef GLEE_H_DEFINED_glGetUniformiv +#define GLEE_H_DEFINED_glGetUniformiv + typedef void (APIENTRYP GLEEPFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint * params); + GLEE_EXTERN GLEEPFNGLGETUNIFORMIVPROC GLeeFuncPtr_glGetUniformiv; + #define glGetUniformiv GLeeFuncPtr_glGetUniformiv +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribdv +#define GLEE_H_DEFINED_glGetVertexAttribdv + typedef void (APIENTRYP GLEEPFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble * params); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBDVPROC GLeeFuncPtr_glGetVertexAttribdv; + #define glGetVertexAttribdv GLeeFuncPtr_glGetVertexAttribdv +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribfv +#define GLEE_H_DEFINED_glGetVertexAttribfv + typedef void (APIENTRYP GLEEPFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBFVPROC GLeeFuncPtr_glGetVertexAttribfv; + #define glGetVertexAttribfv GLeeFuncPtr_glGetVertexAttribfv +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribiv +#define GLEE_H_DEFINED_glGetVertexAttribiv + typedef void (APIENTRYP GLEEPFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBIVPROC GLeeFuncPtr_glGetVertexAttribiv; + #define glGetVertexAttribiv GLeeFuncPtr_glGetVertexAttribiv +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribPointerv +#define GLEE_H_DEFINED_glGetVertexAttribPointerv + typedef void (APIENTRYP GLEEPFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, GLvoid* * pointer); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBPOINTERVPROC GLeeFuncPtr_glGetVertexAttribPointerv; + #define glGetVertexAttribPointerv GLeeFuncPtr_glGetVertexAttribPointerv +#endif +#ifndef GLEE_H_DEFINED_glIsProgram +#define GLEE_H_DEFINED_glIsProgram + typedef GLboolean (APIENTRYP GLEEPFNGLISPROGRAMPROC) (GLuint program); + GLEE_EXTERN GLEEPFNGLISPROGRAMPROC GLeeFuncPtr_glIsProgram; + #define glIsProgram GLeeFuncPtr_glIsProgram +#endif +#ifndef GLEE_H_DEFINED_glIsShader +#define GLEE_H_DEFINED_glIsShader + typedef GLboolean (APIENTRYP GLEEPFNGLISSHADERPROC) (GLuint shader); + GLEE_EXTERN GLEEPFNGLISSHADERPROC GLeeFuncPtr_glIsShader; + #define glIsShader GLeeFuncPtr_glIsShader +#endif +#ifndef GLEE_H_DEFINED_glLinkProgram +#define GLEE_H_DEFINED_glLinkProgram + typedef void (APIENTRYP GLEEPFNGLLINKPROGRAMPROC) (GLuint program); + GLEE_EXTERN GLEEPFNGLLINKPROGRAMPROC GLeeFuncPtr_glLinkProgram; + #define glLinkProgram GLeeFuncPtr_glLinkProgram +#endif +#ifndef GLEE_H_DEFINED_glShaderSource +#define GLEE_H_DEFINED_glShaderSource + typedef void (APIENTRYP GLEEPFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* * string, const GLint * length); + GLEE_EXTERN GLEEPFNGLSHADERSOURCEPROC GLeeFuncPtr_glShaderSource; + #define glShaderSource GLeeFuncPtr_glShaderSource +#endif +#ifndef GLEE_H_DEFINED_glUseProgram +#define GLEE_H_DEFINED_glUseProgram + typedef void (APIENTRYP GLEEPFNGLUSEPROGRAMPROC) (GLuint program); + GLEE_EXTERN GLEEPFNGLUSEPROGRAMPROC GLeeFuncPtr_glUseProgram; + #define glUseProgram GLeeFuncPtr_glUseProgram +#endif +#ifndef GLEE_H_DEFINED_glUniform1f +#define GLEE_H_DEFINED_glUniform1f + typedef void (APIENTRYP GLEEPFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); + GLEE_EXTERN GLEEPFNGLUNIFORM1FPROC GLeeFuncPtr_glUniform1f; + #define glUniform1f GLeeFuncPtr_glUniform1f +#endif +#ifndef GLEE_H_DEFINED_glUniform2f +#define GLEE_H_DEFINED_glUniform2f + typedef void (APIENTRYP GLEEPFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); + GLEE_EXTERN GLEEPFNGLUNIFORM2FPROC GLeeFuncPtr_glUniform2f; + #define glUniform2f GLeeFuncPtr_glUniform2f +#endif +#ifndef GLEE_H_DEFINED_glUniform3f +#define GLEE_H_DEFINED_glUniform3f + typedef void (APIENTRYP GLEEPFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); + GLEE_EXTERN GLEEPFNGLUNIFORM3FPROC GLeeFuncPtr_glUniform3f; + #define glUniform3f GLeeFuncPtr_glUniform3f +#endif +#ifndef GLEE_H_DEFINED_glUniform4f +#define GLEE_H_DEFINED_glUniform4f + typedef void (APIENTRYP GLEEPFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); + GLEE_EXTERN GLEEPFNGLUNIFORM4FPROC GLeeFuncPtr_glUniform4f; + #define glUniform4f GLeeFuncPtr_glUniform4f +#endif +#ifndef GLEE_H_DEFINED_glUniform1i +#define GLEE_H_DEFINED_glUniform1i + typedef void (APIENTRYP GLEEPFNGLUNIFORM1IPROC) (GLint location, GLint v0); + GLEE_EXTERN GLEEPFNGLUNIFORM1IPROC GLeeFuncPtr_glUniform1i; + #define glUniform1i GLeeFuncPtr_glUniform1i +#endif +#ifndef GLEE_H_DEFINED_glUniform2i +#define GLEE_H_DEFINED_glUniform2i + typedef void (APIENTRYP GLEEPFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); + GLEE_EXTERN GLEEPFNGLUNIFORM2IPROC GLeeFuncPtr_glUniform2i; + #define glUniform2i GLeeFuncPtr_glUniform2i +#endif +#ifndef GLEE_H_DEFINED_glUniform3i +#define GLEE_H_DEFINED_glUniform3i + typedef void (APIENTRYP GLEEPFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); + GLEE_EXTERN GLEEPFNGLUNIFORM3IPROC GLeeFuncPtr_glUniform3i; + #define glUniform3i GLeeFuncPtr_glUniform3i +#endif +#ifndef GLEE_H_DEFINED_glUniform4i +#define GLEE_H_DEFINED_glUniform4i + typedef void (APIENTRYP GLEEPFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); + GLEE_EXTERN GLEEPFNGLUNIFORM4IPROC GLeeFuncPtr_glUniform4i; + #define glUniform4i GLeeFuncPtr_glUniform4i +#endif +#ifndef GLEE_H_DEFINED_glUniform1fv +#define GLEE_H_DEFINED_glUniform1fv + typedef void (APIENTRYP GLEEPFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORM1FVPROC GLeeFuncPtr_glUniform1fv; + #define glUniform1fv GLeeFuncPtr_glUniform1fv +#endif +#ifndef GLEE_H_DEFINED_glUniform2fv +#define GLEE_H_DEFINED_glUniform2fv + typedef void (APIENTRYP GLEEPFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORM2FVPROC GLeeFuncPtr_glUniform2fv; + #define glUniform2fv GLeeFuncPtr_glUniform2fv +#endif +#ifndef GLEE_H_DEFINED_glUniform3fv +#define GLEE_H_DEFINED_glUniform3fv + typedef void (APIENTRYP GLEEPFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORM3FVPROC GLeeFuncPtr_glUniform3fv; + #define glUniform3fv GLeeFuncPtr_glUniform3fv +#endif +#ifndef GLEE_H_DEFINED_glUniform4fv +#define GLEE_H_DEFINED_glUniform4fv + typedef void (APIENTRYP GLEEPFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORM4FVPROC GLeeFuncPtr_glUniform4fv; + #define glUniform4fv GLeeFuncPtr_glUniform4fv +#endif +#ifndef GLEE_H_DEFINED_glUniform1iv +#define GLEE_H_DEFINED_glUniform1iv + typedef void (APIENTRYP GLEEPFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint * value); + GLEE_EXTERN GLEEPFNGLUNIFORM1IVPROC GLeeFuncPtr_glUniform1iv; + #define glUniform1iv GLeeFuncPtr_glUniform1iv +#endif +#ifndef GLEE_H_DEFINED_glUniform2iv +#define GLEE_H_DEFINED_glUniform2iv + typedef void (APIENTRYP GLEEPFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint * value); + GLEE_EXTERN GLEEPFNGLUNIFORM2IVPROC GLeeFuncPtr_glUniform2iv; + #define glUniform2iv GLeeFuncPtr_glUniform2iv +#endif +#ifndef GLEE_H_DEFINED_glUniform3iv +#define GLEE_H_DEFINED_glUniform3iv + typedef void (APIENTRYP GLEEPFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint * value); + GLEE_EXTERN GLEEPFNGLUNIFORM3IVPROC GLeeFuncPtr_glUniform3iv; + #define glUniform3iv GLeeFuncPtr_glUniform3iv +#endif +#ifndef GLEE_H_DEFINED_glUniform4iv +#define GLEE_H_DEFINED_glUniform4iv + typedef void (APIENTRYP GLEEPFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint * value); + GLEE_EXTERN GLEEPFNGLUNIFORM4IVPROC GLeeFuncPtr_glUniform4iv; + #define glUniform4iv GLeeFuncPtr_glUniform4iv +#endif +#ifndef GLEE_H_DEFINED_glUniformMatrix2fv +#define GLEE_H_DEFINED_glUniformMatrix2fv + typedef void (APIENTRYP GLEEPFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORMMATRIX2FVPROC GLeeFuncPtr_glUniformMatrix2fv; + #define glUniformMatrix2fv GLeeFuncPtr_glUniformMatrix2fv +#endif +#ifndef GLEE_H_DEFINED_glUniformMatrix3fv +#define GLEE_H_DEFINED_glUniformMatrix3fv + typedef void (APIENTRYP GLEEPFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORMMATRIX3FVPROC GLeeFuncPtr_glUniformMatrix3fv; + #define glUniformMatrix3fv GLeeFuncPtr_glUniformMatrix3fv +#endif +#ifndef GLEE_H_DEFINED_glUniformMatrix4fv +#define GLEE_H_DEFINED_glUniformMatrix4fv + typedef void (APIENTRYP GLEEPFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORMMATRIX4FVPROC GLeeFuncPtr_glUniformMatrix4fv; + #define glUniformMatrix4fv GLeeFuncPtr_glUniformMatrix4fv +#endif +#ifndef GLEE_H_DEFINED_glValidateProgram +#define GLEE_H_DEFINED_glValidateProgram + typedef void (APIENTRYP GLEEPFNGLVALIDATEPROGRAMPROC) (GLuint program); + GLEE_EXTERN GLEEPFNGLVALIDATEPROGRAMPROC GLeeFuncPtr_glValidateProgram; + #define glValidateProgram GLeeFuncPtr_glValidateProgram +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1d +#define GLEE_H_DEFINED_glVertexAttrib1d + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1DPROC GLeeFuncPtr_glVertexAttrib1d; + #define glVertexAttrib1d GLeeFuncPtr_glVertexAttrib1d +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1dv +#define GLEE_H_DEFINED_glVertexAttrib1dv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1DVPROC GLeeFuncPtr_glVertexAttrib1dv; + #define glVertexAttrib1dv GLeeFuncPtr_glVertexAttrib1dv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1f +#define GLEE_H_DEFINED_glVertexAttrib1f + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1FPROC GLeeFuncPtr_glVertexAttrib1f; + #define glVertexAttrib1f GLeeFuncPtr_glVertexAttrib1f +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1fv +#define GLEE_H_DEFINED_glVertexAttrib1fv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1FVPROC GLeeFuncPtr_glVertexAttrib1fv; + #define glVertexAttrib1fv GLeeFuncPtr_glVertexAttrib1fv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1s +#define GLEE_H_DEFINED_glVertexAttrib1s + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1SPROC GLeeFuncPtr_glVertexAttrib1s; + #define glVertexAttrib1s GLeeFuncPtr_glVertexAttrib1s +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1sv +#define GLEE_H_DEFINED_glVertexAttrib1sv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1SVPROC GLeeFuncPtr_glVertexAttrib1sv; + #define glVertexAttrib1sv GLeeFuncPtr_glVertexAttrib1sv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2d +#define GLEE_H_DEFINED_glVertexAttrib2d + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2DPROC GLeeFuncPtr_glVertexAttrib2d; + #define glVertexAttrib2d GLeeFuncPtr_glVertexAttrib2d +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2dv +#define GLEE_H_DEFINED_glVertexAttrib2dv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2DVPROC GLeeFuncPtr_glVertexAttrib2dv; + #define glVertexAttrib2dv GLeeFuncPtr_glVertexAttrib2dv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2f +#define GLEE_H_DEFINED_glVertexAttrib2f + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2FPROC GLeeFuncPtr_glVertexAttrib2f; + #define glVertexAttrib2f GLeeFuncPtr_glVertexAttrib2f +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2fv +#define GLEE_H_DEFINED_glVertexAttrib2fv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2FVPROC GLeeFuncPtr_glVertexAttrib2fv; + #define glVertexAttrib2fv GLeeFuncPtr_glVertexAttrib2fv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2s +#define GLEE_H_DEFINED_glVertexAttrib2s + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2SPROC GLeeFuncPtr_glVertexAttrib2s; + #define glVertexAttrib2s GLeeFuncPtr_glVertexAttrib2s +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2sv +#define GLEE_H_DEFINED_glVertexAttrib2sv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2SVPROC GLeeFuncPtr_glVertexAttrib2sv; + #define glVertexAttrib2sv GLeeFuncPtr_glVertexAttrib2sv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3d +#define GLEE_H_DEFINED_glVertexAttrib3d + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3DPROC GLeeFuncPtr_glVertexAttrib3d; + #define glVertexAttrib3d GLeeFuncPtr_glVertexAttrib3d +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3dv +#define GLEE_H_DEFINED_glVertexAttrib3dv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3DVPROC GLeeFuncPtr_glVertexAttrib3dv; + #define glVertexAttrib3dv GLeeFuncPtr_glVertexAttrib3dv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3f +#define GLEE_H_DEFINED_glVertexAttrib3f + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3FPROC GLeeFuncPtr_glVertexAttrib3f; + #define glVertexAttrib3f GLeeFuncPtr_glVertexAttrib3f +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3fv +#define GLEE_H_DEFINED_glVertexAttrib3fv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3FVPROC GLeeFuncPtr_glVertexAttrib3fv; + #define glVertexAttrib3fv GLeeFuncPtr_glVertexAttrib3fv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3s +#define GLEE_H_DEFINED_glVertexAttrib3s + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3SPROC GLeeFuncPtr_glVertexAttrib3s; + #define glVertexAttrib3s GLeeFuncPtr_glVertexAttrib3s +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3sv +#define GLEE_H_DEFINED_glVertexAttrib3sv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3SVPROC GLeeFuncPtr_glVertexAttrib3sv; + #define glVertexAttrib3sv GLeeFuncPtr_glVertexAttrib3sv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4Nbv +#define GLEE_H_DEFINED_glVertexAttrib4Nbv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4NBVPROC GLeeFuncPtr_glVertexAttrib4Nbv; + #define glVertexAttrib4Nbv GLeeFuncPtr_glVertexAttrib4Nbv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4Niv +#define GLEE_H_DEFINED_glVertexAttrib4Niv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4NIVPROC GLeeFuncPtr_glVertexAttrib4Niv; + #define glVertexAttrib4Niv GLeeFuncPtr_glVertexAttrib4Niv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4Nsv +#define GLEE_H_DEFINED_glVertexAttrib4Nsv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4NSVPROC GLeeFuncPtr_glVertexAttrib4Nsv; + #define glVertexAttrib4Nsv GLeeFuncPtr_glVertexAttrib4Nsv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4Nub +#define GLEE_H_DEFINED_glVertexAttrib4Nub + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4NUBPROC GLeeFuncPtr_glVertexAttrib4Nub; + #define glVertexAttrib4Nub GLeeFuncPtr_glVertexAttrib4Nub +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4Nubv +#define GLEE_H_DEFINED_glVertexAttrib4Nubv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4NUBVPROC GLeeFuncPtr_glVertexAttrib4Nubv; + #define glVertexAttrib4Nubv GLeeFuncPtr_glVertexAttrib4Nubv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4Nuiv +#define GLEE_H_DEFINED_glVertexAttrib4Nuiv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4NUIVPROC GLeeFuncPtr_glVertexAttrib4Nuiv; + #define glVertexAttrib4Nuiv GLeeFuncPtr_glVertexAttrib4Nuiv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4Nusv +#define GLEE_H_DEFINED_glVertexAttrib4Nusv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4NUSVPROC GLeeFuncPtr_glVertexAttrib4Nusv; + #define glVertexAttrib4Nusv GLeeFuncPtr_glVertexAttrib4Nusv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4bv +#define GLEE_H_DEFINED_glVertexAttrib4bv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4BVPROC GLeeFuncPtr_glVertexAttrib4bv; + #define glVertexAttrib4bv GLeeFuncPtr_glVertexAttrib4bv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4d +#define GLEE_H_DEFINED_glVertexAttrib4d + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4DPROC GLeeFuncPtr_glVertexAttrib4d; + #define glVertexAttrib4d GLeeFuncPtr_glVertexAttrib4d +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4dv +#define GLEE_H_DEFINED_glVertexAttrib4dv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4DVPROC GLeeFuncPtr_glVertexAttrib4dv; + #define glVertexAttrib4dv GLeeFuncPtr_glVertexAttrib4dv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4f +#define GLEE_H_DEFINED_glVertexAttrib4f + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4FPROC GLeeFuncPtr_glVertexAttrib4f; + #define glVertexAttrib4f GLeeFuncPtr_glVertexAttrib4f +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4fv +#define GLEE_H_DEFINED_glVertexAttrib4fv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4FVPROC GLeeFuncPtr_glVertexAttrib4fv; + #define glVertexAttrib4fv GLeeFuncPtr_glVertexAttrib4fv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4iv +#define GLEE_H_DEFINED_glVertexAttrib4iv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4IVPROC GLeeFuncPtr_glVertexAttrib4iv; + #define glVertexAttrib4iv GLeeFuncPtr_glVertexAttrib4iv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4s +#define GLEE_H_DEFINED_glVertexAttrib4s + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4SPROC GLeeFuncPtr_glVertexAttrib4s; + #define glVertexAttrib4s GLeeFuncPtr_glVertexAttrib4s +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4sv +#define GLEE_H_DEFINED_glVertexAttrib4sv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4SVPROC GLeeFuncPtr_glVertexAttrib4sv; + #define glVertexAttrib4sv GLeeFuncPtr_glVertexAttrib4sv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4ubv +#define GLEE_H_DEFINED_glVertexAttrib4ubv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4UBVPROC GLeeFuncPtr_glVertexAttrib4ubv; + #define glVertexAttrib4ubv GLeeFuncPtr_glVertexAttrib4ubv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4uiv +#define GLEE_H_DEFINED_glVertexAttrib4uiv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4UIVPROC GLeeFuncPtr_glVertexAttrib4uiv; + #define glVertexAttrib4uiv GLeeFuncPtr_glVertexAttrib4uiv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4usv +#define GLEE_H_DEFINED_glVertexAttrib4usv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4USVPROC GLeeFuncPtr_glVertexAttrib4usv; + #define glVertexAttrib4usv GLeeFuncPtr_glVertexAttrib4usv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribPointer +#define GLEE_H_DEFINED_glVertexAttribPointer + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBPOINTERPROC GLeeFuncPtr_glVertexAttribPointer; + #define glVertexAttribPointer GLeeFuncPtr_glVertexAttribPointer +#endif +#endif + +/* GL_VERSION_2_1 */ + +#ifndef GL_VERSION_2_1 +#define GL_VERSION_2_1 1 +#define __GLEE_GL_VERSION_2_1 1 +/* Constants */ +#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB_ALPHA 0x8C42 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_SLUMINANCE_ALPHA 0x8C44 +#define GL_SLUMINANCE8_ALPHA8 0x8C45 +#define GL_SLUMINANCE 0x8C46 +#define GL_SLUMINANCE8 0x8C47 +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 +#define GL_COMPRESSED_SLUMINANCE 0x8C4A +#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B +#ifndef GLEE_H_DEFINED_glUniformMatrix2x3fv +#define GLEE_H_DEFINED_glUniformMatrix2x3fv + typedef void (APIENTRYP GLEEPFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORMMATRIX2X3FVPROC GLeeFuncPtr_glUniformMatrix2x3fv; + #define glUniformMatrix2x3fv GLeeFuncPtr_glUniformMatrix2x3fv +#endif +#ifndef GLEE_H_DEFINED_glUniformMatrix3x2fv +#define GLEE_H_DEFINED_glUniformMatrix3x2fv + typedef void (APIENTRYP GLEEPFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORMMATRIX3X2FVPROC GLeeFuncPtr_glUniformMatrix3x2fv; + #define glUniformMatrix3x2fv GLeeFuncPtr_glUniformMatrix3x2fv +#endif +#ifndef GLEE_H_DEFINED_glUniformMatrix2x4fv +#define GLEE_H_DEFINED_glUniformMatrix2x4fv + typedef void (APIENTRYP GLEEPFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORMMATRIX2X4FVPROC GLeeFuncPtr_glUniformMatrix2x4fv; + #define glUniformMatrix2x4fv GLeeFuncPtr_glUniformMatrix2x4fv +#endif +#ifndef GLEE_H_DEFINED_glUniformMatrix4x2fv +#define GLEE_H_DEFINED_glUniformMatrix4x2fv + typedef void (APIENTRYP GLEEPFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORMMATRIX4X2FVPROC GLeeFuncPtr_glUniformMatrix4x2fv; + #define glUniformMatrix4x2fv GLeeFuncPtr_glUniformMatrix4x2fv +#endif +#ifndef GLEE_H_DEFINED_glUniformMatrix3x4fv +#define GLEE_H_DEFINED_glUniformMatrix3x4fv + typedef void (APIENTRYP GLEEPFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORMMATRIX3X4FVPROC GLeeFuncPtr_glUniformMatrix3x4fv; + #define glUniformMatrix3x4fv GLeeFuncPtr_glUniformMatrix3x4fv +#endif +#ifndef GLEE_H_DEFINED_glUniformMatrix4x3fv +#define GLEE_H_DEFINED_glUniformMatrix4x3fv + typedef void (APIENTRYP GLEEPFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORMMATRIX4X3FVPROC GLeeFuncPtr_glUniformMatrix4x3fv; + #define glUniformMatrix4x3fv GLeeFuncPtr_glUniformMatrix4x3fv +#endif +#endif + +/* GL_VERSION_3_0 */ + +#ifndef GL_VERSION_3_0 +#define GL_VERSION_3_0 1 +#define __GLEE_GL_VERSION_3_0 1 +/* Constants */ +#define GL_COMPARE_REF_TO_TEXTURE GL_COMPARE_R_TO_TEXTURE_ARB +#define GL_CLIP_DISTANCE0 GL_CLIP_PLANE0 +#define GL_CLIP_DISTANCE1 GL_CLIP_PLANE1 +#define GL_CLIP_DISTANCE2 GL_CLIP_PLANE2 +#define GL_CLIP_DISTANCE3 GL_CLIP_PLANE3 +#define GL_CLIP_DISTANCE4 GL_CLIP_PLANE4 +#define GL_CLIP_DISTANCE5 GL_CLIP_PLANE5 +#define GL_MAX_CLIP_DISTANCES GL_MAX_CLIP_PLANES +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_CONTEXT_FLAGS 0x821E +#define GL_DEPTH_BUFFER 0x8223 +#define GL_STENCIL_BUFFER 0x8224 +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RG 0x8226 +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001 +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_CLAMP_VERTEX_COLOR 0x891A +#define GL_CLAMP_FRAGMENT_COLOR 0x891B +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_FIXED_ONLY 0x891D +#define GL_MAX_VARYING_COMPONENTS GL_MAX_VARYING_FLOATS +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14 +#define GL_TEXTURE_INTENSITY_TYPE 0x8C15 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_TEXTURE_1D_ARRAY 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_GREEN_INTEGER 0x8D95 +#define GL_BLUE_INTEGER 0x8D96 +#define GL_ALPHA_INTEGER 0x8D97 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_BGR_INTEGER 0x8D9A +#define GL_BGRA_INTEGER 0x8D9B +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_QUERY_WAIT 0x8E13 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 +#ifndef GLEE_H_DEFINED_glColorMaski +#define GLEE_H_DEFINED_glColorMaski + typedef void (APIENTRYP GLEEPFNGLCOLORMASKIPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); + GLEE_EXTERN GLEEPFNGLCOLORMASKIPROC GLeeFuncPtr_glColorMaski; + #define glColorMaski GLeeFuncPtr_glColorMaski +#endif +#ifndef GLEE_H_DEFINED_glGetBooleani_v +#define GLEE_H_DEFINED_glGetBooleani_v + typedef void (APIENTRYP GLEEPFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean * data); + GLEE_EXTERN GLEEPFNGLGETBOOLEANI_VPROC GLeeFuncPtr_glGetBooleani_v; + #define glGetBooleani_v GLeeFuncPtr_glGetBooleani_v +#endif +#ifndef GLEE_H_DEFINED_glGetIntegeri_v +#define GLEE_H_DEFINED_glGetIntegeri_v + typedef void (APIENTRYP GLEEPFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint * data); + GLEE_EXTERN GLEEPFNGLGETINTEGERI_VPROC GLeeFuncPtr_glGetIntegeri_v; + #define glGetIntegeri_v GLeeFuncPtr_glGetIntegeri_v +#endif +#ifndef GLEE_H_DEFINED_glEnablei +#define GLEE_H_DEFINED_glEnablei + typedef void (APIENTRYP GLEEPFNGLENABLEIPROC) (GLenum target, GLuint index); + GLEE_EXTERN GLEEPFNGLENABLEIPROC GLeeFuncPtr_glEnablei; + #define glEnablei GLeeFuncPtr_glEnablei +#endif +#ifndef GLEE_H_DEFINED_glDisablei +#define GLEE_H_DEFINED_glDisablei + typedef void (APIENTRYP GLEEPFNGLDISABLEIPROC) (GLenum target, GLuint index); + GLEE_EXTERN GLEEPFNGLDISABLEIPROC GLeeFuncPtr_glDisablei; + #define glDisablei GLeeFuncPtr_glDisablei +#endif +#ifndef GLEE_H_DEFINED_glIsEnabledi +#define GLEE_H_DEFINED_glIsEnabledi + typedef GLboolean (APIENTRYP GLEEPFNGLISENABLEDIPROC) (GLenum target, GLuint index); + GLEE_EXTERN GLEEPFNGLISENABLEDIPROC GLeeFuncPtr_glIsEnabledi; + #define glIsEnabledi GLeeFuncPtr_glIsEnabledi +#endif +#ifndef GLEE_H_DEFINED_glBeginTransformFeedback +#define GLEE_H_DEFINED_glBeginTransformFeedback + typedef void (APIENTRYP GLEEPFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode); + GLEE_EXTERN GLEEPFNGLBEGINTRANSFORMFEEDBACKPROC GLeeFuncPtr_glBeginTransformFeedback; + #define glBeginTransformFeedback GLeeFuncPtr_glBeginTransformFeedback +#endif +#ifndef GLEE_H_DEFINED_glEndTransformFeedback +#define GLEE_H_DEFINED_glEndTransformFeedback + typedef void (APIENTRYP GLEEPFNGLENDTRANSFORMFEEDBACKPROC) (); + GLEE_EXTERN GLEEPFNGLENDTRANSFORMFEEDBACKPROC GLeeFuncPtr_glEndTransformFeedback; + #define glEndTransformFeedback GLeeFuncPtr_glEndTransformFeedback +#endif +#ifndef GLEE_H_DEFINED_glBindBufferRange +#define GLEE_H_DEFINED_glBindBufferRange + typedef void (APIENTRYP GLEEPFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); + GLEE_EXTERN GLEEPFNGLBINDBUFFERRANGEPROC GLeeFuncPtr_glBindBufferRange; + #define glBindBufferRange GLeeFuncPtr_glBindBufferRange +#endif +#ifndef GLEE_H_DEFINED_glBindBufferBase +#define GLEE_H_DEFINED_glBindBufferBase + typedef void (APIENTRYP GLEEPFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer); + GLEE_EXTERN GLEEPFNGLBINDBUFFERBASEPROC GLeeFuncPtr_glBindBufferBase; + #define glBindBufferBase GLeeFuncPtr_glBindBufferBase +#endif +#ifndef GLEE_H_DEFINED_glTransformFeedbackVaryings +#define GLEE_H_DEFINED_glTransformFeedbackVaryings + typedef void (APIENTRYP GLEEPFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLint * locations, GLenum bufferMode); + GLEE_EXTERN GLEEPFNGLTRANSFORMFEEDBACKVARYINGSPROC GLeeFuncPtr_glTransformFeedbackVaryings; + #define glTransformFeedbackVaryings GLeeFuncPtr_glTransformFeedbackVaryings +#endif +#ifndef GLEE_H_DEFINED_glGetTransformFeedbackVarying +#define GLEE_H_DEFINED_glGetTransformFeedbackVarying + typedef void (APIENTRYP GLEEPFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLint * location); + GLEE_EXTERN GLEEPFNGLGETTRANSFORMFEEDBACKVARYINGPROC GLeeFuncPtr_glGetTransformFeedbackVarying; + #define glGetTransformFeedbackVarying GLeeFuncPtr_glGetTransformFeedbackVarying +#endif +#ifndef GLEE_H_DEFINED_glClampColor +#define GLEE_H_DEFINED_glClampColor + typedef void (APIENTRYP GLEEPFNGLCLAMPCOLORPROC) (GLenum target, GLenum clamp); + GLEE_EXTERN GLEEPFNGLCLAMPCOLORPROC GLeeFuncPtr_glClampColor; + #define glClampColor GLeeFuncPtr_glClampColor +#endif +#ifndef GLEE_H_DEFINED_glBeginConditionalRender +#define GLEE_H_DEFINED_glBeginConditionalRender + typedef void (APIENTRYP GLEEPFNGLBEGINCONDITIONALRENDERPROC) (GLuint id, GLenum mode); + GLEE_EXTERN GLEEPFNGLBEGINCONDITIONALRENDERPROC GLeeFuncPtr_glBeginConditionalRender; + #define glBeginConditionalRender GLeeFuncPtr_glBeginConditionalRender +#endif +#ifndef GLEE_H_DEFINED_glEndConditionalRender +#define GLEE_H_DEFINED_glEndConditionalRender + typedef void (APIENTRYP GLEEPFNGLENDCONDITIONALRENDERPROC) (); + GLEE_EXTERN GLEEPFNGLENDCONDITIONALRENDERPROC GLeeFuncPtr_glEndConditionalRender; + #define glEndConditionalRender GLeeFuncPtr_glEndConditionalRender +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI1i +#define GLEE_H_DEFINED_glVertexAttribI1i + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI1IPROC) (GLuint index, GLint x); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI1IPROC GLeeFuncPtr_glVertexAttribI1i; + #define glVertexAttribI1i GLeeFuncPtr_glVertexAttribI1i +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI2i +#define GLEE_H_DEFINED_glVertexAttribI2i + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI2IPROC) (GLuint index, GLint x, GLint y); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI2IPROC GLeeFuncPtr_glVertexAttribI2i; + #define glVertexAttribI2i GLeeFuncPtr_glVertexAttribI2i +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI3i +#define GLEE_H_DEFINED_glVertexAttribI3i + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI3IPROC) (GLuint index, GLint x, GLint y, GLint z); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI3IPROC GLeeFuncPtr_glVertexAttribI3i; + #define glVertexAttribI3i GLeeFuncPtr_glVertexAttribI3i +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI4i +#define GLEE_H_DEFINED_glVertexAttribI4i + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI4IPROC GLeeFuncPtr_glVertexAttribI4i; + #define glVertexAttribI4i GLeeFuncPtr_glVertexAttribI4i +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI1ui +#define GLEE_H_DEFINED_glVertexAttribI1ui + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI1UIPROC) (GLuint index, GLuint x); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI1UIPROC GLeeFuncPtr_glVertexAttribI1ui; + #define glVertexAttribI1ui GLeeFuncPtr_glVertexAttribI1ui +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI2ui +#define GLEE_H_DEFINED_glVertexAttribI2ui + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI2UIPROC) (GLuint index, GLuint x, GLuint y); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI2UIPROC GLeeFuncPtr_glVertexAttribI2ui; + #define glVertexAttribI2ui GLeeFuncPtr_glVertexAttribI2ui +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI3ui +#define GLEE_H_DEFINED_glVertexAttribI3ui + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI3UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI3UIPROC GLeeFuncPtr_glVertexAttribI3ui; + #define glVertexAttribI3ui GLeeFuncPtr_glVertexAttribI3ui +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI4ui +#define GLEE_H_DEFINED_glVertexAttribI4ui + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI4UIPROC GLeeFuncPtr_glVertexAttribI4ui; + #define glVertexAttribI4ui GLeeFuncPtr_glVertexAttribI4ui +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI1iv +#define GLEE_H_DEFINED_glVertexAttribI1iv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI1IVPROC) (GLuint index, const GLint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI1IVPROC GLeeFuncPtr_glVertexAttribI1iv; + #define glVertexAttribI1iv GLeeFuncPtr_glVertexAttribI1iv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI2iv +#define GLEE_H_DEFINED_glVertexAttribI2iv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI2IVPROC) (GLuint index, const GLint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI2IVPROC GLeeFuncPtr_glVertexAttribI2iv; + #define glVertexAttribI2iv GLeeFuncPtr_glVertexAttribI2iv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI3iv +#define GLEE_H_DEFINED_glVertexAttribI3iv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI3IVPROC) (GLuint index, const GLint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI3IVPROC GLeeFuncPtr_glVertexAttribI3iv; + #define glVertexAttribI3iv GLeeFuncPtr_glVertexAttribI3iv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI4iv +#define GLEE_H_DEFINED_glVertexAttribI4iv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI4IVPROC GLeeFuncPtr_glVertexAttribI4iv; + #define glVertexAttribI4iv GLeeFuncPtr_glVertexAttribI4iv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI1uiv +#define GLEE_H_DEFINED_glVertexAttribI1uiv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI1UIVPROC) (GLuint index, const GLuint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI1UIVPROC GLeeFuncPtr_glVertexAttribI1uiv; + #define glVertexAttribI1uiv GLeeFuncPtr_glVertexAttribI1uiv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI2uiv +#define GLEE_H_DEFINED_glVertexAttribI2uiv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI2UIVPROC) (GLuint index, const GLuint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI2UIVPROC GLeeFuncPtr_glVertexAttribI2uiv; + #define glVertexAttribI2uiv GLeeFuncPtr_glVertexAttribI2uiv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI3uiv +#define GLEE_H_DEFINED_glVertexAttribI3uiv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI3UIVPROC) (GLuint index, const GLuint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI3UIVPROC GLeeFuncPtr_glVertexAttribI3uiv; + #define glVertexAttribI3uiv GLeeFuncPtr_glVertexAttribI3uiv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI4uiv +#define GLEE_H_DEFINED_glVertexAttribI4uiv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI4UIVPROC GLeeFuncPtr_glVertexAttribI4uiv; + #define glVertexAttribI4uiv GLeeFuncPtr_glVertexAttribI4uiv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI4bv +#define GLEE_H_DEFINED_glVertexAttribI4bv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI4BVPROC) (GLuint index, const GLbyte * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI4BVPROC GLeeFuncPtr_glVertexAttribI4bv; + #define glVertexAttribI4bv GLeeFuncPtr_glVertexAttribI4bv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI4sv +#define GLEE_H_DEFINED_glVertexAttribI4sv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI4SVPROC) (GLuint index, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI4SVPROC GLeeFuncPtr_glVertexAttribI4sv; + #define glVertexAttribI4sv GLeeFuncPtr_glVertexAttribI4sv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI4ubv +#define GLEE_H_DEFINED_glVertexAttribI4ubv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI4UBVPROC) (GLuint index, const GLubyte * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI4UBVPROC GLeeFuncPtr_glVertexAttribI4ubv; + #define glVertexAttribI4ubv GLeeFuncPtr_glVertexAttribI4ubv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI4usv +#define GLEE_H_DEFINED_glVertexAttribI4usv + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBI4USVPROC) (GLuint index, const GLushort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI4USVPROC GLeeFuncPtr_glVertexAttribI4usv; + #define glVertexAttribI4usv GLeeFuncPtr_glVertexAttribI4usv +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribIPointer +#define GLEE_H_DEFINED_glVertexAttribIPointer + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBIPOINTERPROC GLeeFuncPtr_glVertexAttribIPointer; + #define glVertexAttribIPointer GLeeFuncPtr_glVertexAttribIPointer +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribIiv +#define GLEE_H_DEFINED_glGetVertexAttribIiv + typedef void (APIENTRYP GLEEPFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBIIVPROC GLeeFuncPtr_glGetVertexAttribIiv; + #define glGetVertexAttribIiv GLeeFuncPtr_glGetVertexAttribIiv +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribIuiv +#define GLEE_H_DEFINED_glGetVertexAttribIuiv + typedef void (APIENTRYP GLEEPFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint * params); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBIUIVPROC GLeeFuncPtr_glGetVertexAttribIuiv; + #define glGetVertexAttribIuiv GLeeFuncPtr_glGetVertexAttribIuiv +#endif +#ifndef GLEE_H_DEFINED_glGetUniformuiv +#define GLEE_H_DEFINED_glGetUniformuiv + typedef void (APIENTRYP GLEEPFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint * params); + GLEE_EXTERN GLEEPFNGLGETUNIFORMUIVPROC GLeeFuncPtr_glGetUniformuiv; + #define glGetUniformuiv GLeeFuncPtr_glGetUniformuiv +#endif +#ifndef GLEE_H_DEFINED_glBindFragDataLocation +#define GLEE_H_DEFINED_glBindFragDataLocation + typedef void (APIENTRYP GLEEPFNGLBINDFRAGDATALOCATIONPROC) (GLuint program, GLuint color, const GLchar * name); + GLEE_EXTERN GLEEPFNGLBINDFRAGDATALOCATIONPROC GLeeFuncPtr_glBindFragDataLocation; + #define glBindFragDataLocation GLeeFuncPtr_glBindFragDataLocation +#endif +#ifndef GLEE_H_DEFINED_glGetFragDataLocation +#define GLEE_H_DEFINED_glGetFragDataLocation + typedef GLint (APIENTRYP GLEEPFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar * name); + GLEE_EXTERN GLEEPFNGLGETFRAGDATALOCATIONPROC GLeeFuncPtr_glGetFragDataLocation; + #define glGetFragDataLocation GLeeFuncPtr_glGetFragDataLocation +#endif +#ifndef GLEE_H_DEFINED_glUniform1ui +#define GLEE_H_DEFINED_glUniform1ui + typedef void (APIENTRYP GLEEPFNGLUNIFORM1UIPROC) (GLint location, GLuint v0); + GLEE_EXTERN GLEEPFNGLUNIFORM1UIPROC GLeeFuncPtr_glUniform1ui; + #define glUniform1ui GLeeFuncPtr_glUniform1ui +#endif +#ifndef GLEE_H_DEFINED_glUniform2ui +#define GLEE_H_DEFINED_glUniform2ui + typedef void (APIENTRYP GLEEPFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1); + GLEE_EXTERN GLEEPFNGLUNIFORM2UIPROC GLeeFuncPtr_glUniform2ui; + #define glUniform2ui GLeeFuncPtr_glUniform2ui +#endif +#ifndef GLEE_H_DEFINED_glUniform3ui +#define GLEE_H_DEFINED_glUniform3ui + typedef void (APIENTRYP GLEEPFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); + GLEE_EXTERN GLEEPFNGLUNIFORM3UIPROC GLeeFuncPtr_glUniform3ui; + #define glUniform3ui GLeeFuncPtr_glUniform3ui +#endif +#ifndef GLEE_H_DEFINED_glUniform4ui +#define GLEE_H_DEFINED_glUniform4ui + typedef void (APIENTRYP GLEEPFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + GLEE_EXTERN GLEEPFNGLUNIFORM4UIPROC GLeeFuncPtr_glUniform4ui; + #define glUniform4ui GLeeFuncPtr_glUniform4ui +#endif +#ifndef GLEE_H_DEFINED_glUniform1uiv +#define GLEE_H_DEFINED_glUniform1uiv + typedef void (APIENTRYP GLEEPFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint * value); + GLEE_EXTERN GLEEPFNGLUNIFORM1UIVPROC GLeeFuncPtr_glUniform1uiv; + #define glUniform1uiv GLeeFuncPtr_glUniform1uiv +#endif +#ifndef GLEE_H_DEFINED_glUniform2uiv +#define GLEE_H_DEFINED_glUniform2uiv + typedef void (APIENTRYP GLEEPFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint * value); + GLEE_EXTERN GLEEPFNGLUNIFORM2UIVPROC GLeeFuncPtr_glUniform2uiv; + #define glUniform2uiv GLeeFuncPtr_glUniform2uiv +#endif +#ifndef GLEE_H_DEFINED_glUniform3uiv +#define GLEE_H_DEFINED_glUniform3uiv + typedef void (APIENTRYP GLEEPFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint * value); + GLEE_EXTERN GLEEPFNGLUNIFORM3UIVPROC GLeeFuncPtr_glUniform3uiv; + #define glUniform3uiv GLeeFuncPtr_glUniform3uiv +#endif +#ifndef GLEE_H_DEFINED_glUniform4uiv +#define GLEE_H_DEFINED_glUniform4uiv + typedef void (APIENTRYP GLEEPFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint * value); + GLEE_EXTERN GLEEPFNGLUNIFORM4UIVPROC GLeeFuncPtr_glUniform4uiv; + #define glUniform4uiv GLeeFuncPtr_glUniform4uiv +#endif +#ifndef GLEE_H_DEFINED_glTexParameterIiv +#define GLEE_H_DEFINED_glTexParameterIiv + typedef void (APIENTRYP GLEEPFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLTEXPARAMETERIIVPROC GLeeFuncPtr_glTexParameterIiv; + #define glTexParameterIiv GLeeFuncPtr_glTexParameterIiv +#endif +#ifndef GLEE_H_DEFINED_glTexParameterIuiv +#define GLEE_H_DEFINED_glTexParameterIuiv + typedef void (APIENTRYP GLEEPFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint * params); + GLEE_EXTERN GLEEPFNGLTEXPARAMETERIUIVPROC GLeeFuncPtr_glTexParameterIuiv; + #define glTexParameterIuiv GLeeFuncPtr_glTexParameterIuiv +#endif +#ifndef GLEE_H_DEFINED_glGetTexParameterIiv +#define GLEE_H_DEFINED_glGetTexParameterIiv + typedef void (APIENTRYP GLEEPFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETTEXPARAMETERIIVPROC GLeeFuncPtr_glGetTexParameterIiv; + #define glGetTexParameterIiv GLeeFuncPtr_glGetTexParameterIiv +#endif +#ifndef GLEE_H_DEFINED_glGetTexParameterIuiv +#define GLEE_H_DEFINED_glGetTexParameterIuiv + typedef void (APIENTRYP GLEEPFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint * params); + GLEE_EXTERN GLEEPFNGLGETTEXPARAMETERIUIVPROC GLeeFuncPtr_glGetTexParameterIuiv; + #define glGetTexParameterIuiv GLeeFuncPtr_glGetTexParameterIuiv +#endif +#ifndef GLEE_H_DEFINED_glClearBufferiv +#define GLEE_H_DEFINED_glClearBufferiv + typedef void (APIENTRYP GLEEPFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint * value); + GLEE_EXTERN GLEEPFNGLCLEARBUFFERIVPROC GLeeFuncPtr_glClearBufferiv; + #define glClearBufferiv GLeeFuncPtr_glClearBufferiv +#endif +#ifndef GLEE_H_DEFINED_glClearBufferuiv +#define GLEE_H_DEFINED_glClearBufferuiv + typedef void (APIENTRYP GLEEPFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint * value); + GLEE_EXTERN GLEEPFNGLCLEARBUFFERUIVPROC GLeeFuncPtr_glClearBufferuiv; + #define glClearBufferuiv GLeeFuncPtr_glClearBufferuiv +#endif +#ifndef GLEE_H_DEFINED_glClearBufferfv +#define GLEE_H_DEFINED_glClearBufferfv + typedef void (APIENTRYP GLEEPFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLCLEARBUFFERFVPROC GLeeFuncPtr_glClearBufferfv; + #define glClearBufferfv GLeeFuncPtr_glClearBufferfv +#endif +#ifndef GLEE_H_DEFINED_glClearBufferfi +#define GLEE_H_DEFINED_glClearBufferfi + typedef void (APIENTRYP GLEEPFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); + GLEE_EXTERN GLEEPFNGLCLEARBUFFERFIPROC GLeeFuncPtr_glClearBufferfi; + #define glClearBufferfi GLeeFuncPtr_glClearBufferfi +#endif +#ifndef GLEE_H_DEFINED_glGetStringi +#define GLEE_H_DEFINED_glGetStringi + typedef const GLubyte * (APIENTRYP GLEEPFNGLGETSTRINGIPROC) (GLenum name, GLuint index); + GLEE_EXTERN GLEEPFNGLGETSTRINGIPROC GLeeFuncPtr_glGetStringi; + #define glGetStringi GLeeFuncPtr_glGetStringi +#endif +#endif + +/* GL_ARB_multitexture */ + +#ifndef GL_ARB_multitexture +#define GL_ARB_multitexture 1 +#define __GLEE_GL_ARB_multitexture 1 +/* Constants */ +#define GL_TEXTURE0_ARB 0x84C0 +#define GL_TEXTURE1_ARB 0x84C1 +#define GL_TEXTURE2_ARB 0x84C2 +#define GL_TEXTURE3_ARB 0x84C3 +#define GL_TEXTURE4_ARB 0x84C4 +#define GL_TEXTURE5_ARB 0x84C5 +#define GL_TEXTURE6_ARB 0x84C6 +#define GL_TEXTURE7_ARB 0x84C7 +#define GL_TEXTURE8_ARB 0x84C8 +#define GL_TEXTURE9_ARB 0x84C9 +#define GL_TEXTURE10_ARB 0x84CA +#define GL_TEXTURE11_ARB 0x84CB +#define GL_TEXTURE12_ARB 0x84CC +#define GL_TEXTURE13_ARB 0x84CD +#define GL_TEXTURE14_ARB 0x84CE +#define GL_TEXTURE15_ARB 0x84CF +#define GL_TEXTURE16_ARB 0x84D0 +#define GL_TEXTURE17_ARB 0x84D1 +#define GL_TEXTURE18_ARB 0x84D2 +#define GL_TEXTURE19_ARB 0x84D3 +#define GL_TEXTURE20_ARB 0x84D4 +#define GL_TEXTURE21_ARB 0x84D5 +#define GL_TEXTURE22_ARB 0x84D6 +#define GL_TEXTURE23_ARB 0x84D7 +#define GL_TEXTURE24_ARB 0x84D8 +#define GL_TEXTURE25_ARB 0x84D9 +#define GL_TEXTURE26_ARB 0x84DA +#define GL_TEXTURE27_ARB 0x84DB +#define GL_TEXTURE28_ARB 0x84DC +#define GL_TEXTURE29_ARB 0x84DD +#define GL_TEXTURE30_ARB 0x84DE +#define GL_TEXTURE31_ARB 0x84DF +#define GL_ACTIVE_TEXTURE_ARB 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 +#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 +#ifndef GLEE_H_DEFINED_glActiveTextureARB +#define GLEE_H_DEFINED_glActiveTextureARB + typedef void (APIENTRYP GLEEPFNGLACTIVETEXTUREARBPROC) (GLenum texture); + GLEE_EXTERN GLEEPFNGLACTIVETEXTUREARBPROC GLeeFuncPtr_glActiveTextureARB; + #define glActiveTextureARB GLeeFuncPtr_glActiveTextureARB +#endif +#ifndef GLEE_H_DEFINED_glClientActiveTextureARB +#define GLEE_H_DEFINED_glClientActiveTextureARB + typedef void (APIENTRYP GLEEPFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); + GLEE_EXTERN GLEEPFNGLCLIENTACTIVETEXTUREARBPROC GLeeFuncPtr_glClientActiveTextureARB; + #define glClientActiveTextureARB GLeeFuncPtr_glClientActiveTextureARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1dARB +#define GLEE_H_DEFINED_glMultiTexCoord1dARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1DARBPROC GLeeFuncPtr_glMultiTexCoord1dARB; + #define glMultiTexCoord1dARB GLeeFuncPtr_glMultiTexCoord1dARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1dvARB +#define GLEE_H_DEFINED_glMultiTexCoord1dvARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1DVARBPROC GLeeFuncPtr_glMultiTexCoord1dvARB; + #define glMultiTexCoord1dvARB GLeeFuncPtr_glMultiTexCoord1dvARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1fARB +#define GLEE_H_DEFINED_glMultiTexCoord1fARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1FARBPROC GLeeFuncPtr_glMultiTexCoord1fARB; + #define glMultiTexCoord1fARB GLeeFuncPtr_glMultiTexCoord1fARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1fvARB +#define GLEE_H_DEFINED_glMultiTexCoord1fvARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1FVARBPROC GLeeFuncPtr_glMultiTexCoord1fvARB; + #define glMultiTexCoord1fvARB GLeeFuncPtr_glMultiTexCoord1fvARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1iARB +#define GLEE_H_DEFINED_glMultiTexCoord1iARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1IARBPROC GLeeFuncPtr_glMultiTexCoord1iARB; + #define glMultiTexCoord1iARB GLeeFuncPtr_glMultiTexCoord1iARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1ivARB +#define GLEE_H_DEFINED_glMultiTexCoord1ivARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1IVARBPROC GLeeFuncPtr_glMultiTexCoord1ivARB; + #define glMultiTexCoord1ivARB GLeeFuncPtr_glMultiTexCoord1ivARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1sARB +#define GLEE_H_DEFINED_glMultiTexCoord1sARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1SARBPROC GLeeFuncPtr_glMultiTexCoord1sARB; + #define glMultiTexCoord1sARB GLeeFuncPtr_glMultiTexCoord1sARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1svARB +#define GLEE_H_DEFINED_glMultiTexCoord1svARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1SVARBPROC GLeeFuncPtr_glMultiTexCoord1svARB; + #define glMultiTexCoord1svARB GLeeFuncPtr_glMultiTexCoord1svARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2dARB +#define GLEE_H_DEFINED_glMultiTexCoord2dARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2DARBPROC GLeeFuncPtr_glMultiTexCoord2dARB; + #define glMultiTexCoord2dARB GLeeFuncPtr_glMultiTexCoord2dARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2dvARB +#define GLEE_H_DEFINED_glMultiTexCoord2dvARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2DVARBPROC GLeeFuncPtr_glMultiTexCoord2dvARB; + #define glMultiTexCoord2dvARB GLeeFuncPtr_glMultiTexCoord2dvARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2fARB +#define GLEE_H_DEFINED_glMultiTexCoord2fARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2FARBPROC GLeeFuncPtr_glMultiTexCoord2fARB; + #define glMultiTexCoord2fARB GLeeFuncPtr_glMultiTexCoord2fARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2fvARB +#define GLEE_H_DEFINED_glMultiTexCoord2fvARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2FVARBPROC GLeeFuncPtr_glMultiTexCoord2fvARB; + #define glMultiTexCoord2fvARB GLeeFuncPtr_glMultiTexCoord2fvARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2iARB +#define GLEE_H_DEFINED_glMultiTexCoord2iARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2IARBPROC GLeeFuncPtr_glMultiTexCoord2iARB; + #define glMultiTexCoord2iARB GLeeFuncPtr_glMultiTexCoord2iARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2ivARB +#define GLEE_H_DEFINED_glMultiTexCoord2ivARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2IVARBPROC GLeeFuncPtr_glMultiTexCoord2ivARB; + #define glMultiTexCoord2ivARB GLeeFuncPtr_glMultiTexCoord2ivARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2sARB +#define GLEE_H_DEFINED_glMultiTexCoord2sARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2SARBPROC GLeeFuncPtr_glMultiTexCoord2sARB; + #define glMultiTexCoord2sARB GLeeFuncPtr_glMultiTexCoord2sARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2svARB +#define GLEE_H_DEFINED_glMultiTexCoord2svARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2SVARBPROC GLeeFuncPtr_glMultiTexCoord2svARB; + #define glMultiTexCoord2svARB GLeeFuncPtr_glMultiTexCoord2svARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3dARB +#define GLEE_H_DEFINED_glMultiTexCoord3dARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3DARBPROC GLeeFuncPtr_glMultiTexCoord3dARB; + #define glMultiTexCoord3dARB GLeeFuncPtr_glMultiTexCoord3dARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3dvARB +#define GLEE_H_DEFINED_glMultiTexCoord3dvARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3DVARBPROC GLeeFuncPtr_glMultiTexCoord3dvARB; + #define glMultiTexCoord3dvARB GLeeFuncPtr_glMultiTexCoord3dvARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3fARB +#define GLEE_H_DEFINED_glMultiTexCoord3fARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3FARBPROC GLeeFuncPtr_glMultiTexCoord3fARB; + #define glMultiTexCoord3fARB GLeeFuncPtr_glMultiTexCoord3fARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3fvARB +#define GLEE_H_DEFINED_glMultiTexCoord3fvARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3FVARBPROC GLeeFuncPtr_glMultiTexCoord3fvARB; + #define glMultiTexCoord3fvARB GLeeFuncPtr_glMultiTexCoord3fvARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3iARB +#define GLEE_H_DEFINED_glMultiTexCoord3iARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3IARBPROC GLeeFuncPtr_glMultiTexCoord3iARB; + #define glMultiTexCoord3iARB GLeeFuncPtr_glMultiTexCoord3iARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3ivARB +#define GLEE_H_DEFINED_glMultiTexCoord3ivARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3IVARBPROC GLeeFuncPtr_glMultiTexCoord3ivARB; + #define glMultiTexCoord3ivARB GLeeFuncPtr_glMultiTexCoord3ivARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3sARB +#define GLEE_H_DEFINED_glMultiTexCoord3sARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3SARBPROC GLeeFuncPtr_glMultiTexCoord3sARB; + #define glMultiTexCoord3sARB GLeeFuncPtr_glMultiTexCoord3sARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3svARB +#define GLEE_H_DEFINED_glMultiTexCoord3svARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3SVARBPROC GLeeFuncPtr_glMultiTexCoord3svARB; + #define glMultiTexCoord3svARB GLeeFuncPtr_glMultiTexCoord3svARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4dARB +#define GLEE_H_DEFINED_glMultiTexCoord4dARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4DARBPROC GLeeFuncPtr_glMultiTexCoord4dARB; + #define glMultiTexCoord4dARB GLeeFuncPtr_glMultiTexCoord4dARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4dvARB +#define GLEE_H_DEFINED_glMultiTexCoord4dvARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4DVARBPROC GLeeFuncPtr_glMultiTexCoord4dvARB; + #define glMultiTexCoord4dvARB GLeeFuncPtr_glMultiTexCoord4dvARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4fARB +#define GLEE_H_DEFINED_glMultiTexCoord4fARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4FARBPROC GLeeFuncPtr_glMultiTexCoord4fARB; + #define glMultiTexCoord4fARB GLeeFuncPtr_glMultiTexCoord4fARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4fvARB +#define GLEE_H_DEFINED_glMultiTexCoord4fvARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4FVARBPROC GLeeFuncPtr_glMultiTexCoord4fvARB; + #define glMultiTexCoord4fvARB GLeeFuncPtr_glMultiTexCoord4fvARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4iARB +#define GLEE_H_DEFINED_glMultiTexCoord4iARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4IARBPROC GLeeFuncPtr_glMultiTexCoord4iARB; + #define glMultiTexCoord4iARB GLeeFuncPtr_glMultiTexCoord4iARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4ivARB +#define GLEE_H_DEFINED_glMultiTexCoord4ivARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4IVARBPROC GLeeFuncPtr_glMultiTexCoord4ivARB; + #define glMultiTexCoord4ivARB GLeeFuncPtr_glMultiTexCoord4ivARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4sARB +#define GLEE_H_DEFINED_glMultiTexCoord4sARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4SARBPROC GLeeFuncPtr_glMultiTexCoord4sARB; + #define glMultiTexCoord4sARB GLeeFuncPtr_glMultiTexCoord4sARB +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4svARB +#define GLEE_H_DEFINED_glMultiTexCoord4svARB + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4SVARBPROC GLeeFuncPtr_glMultiTexCoord4svARB; + #define glMultiTexCoord4svARB GLeeFuncPtr_glMultiTexCoord4svARB +#endif +#endif + +/* GL_ARB_transpose_matrix */ + +#ifndef GL_ARB_transpose_matrix +#define GL_ARB_transpose_matrix 1 +#define __GLEE_GL_ARB_transpose_matrix 1 +/* Constants */ +#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6 +#ifndef GLEE_H_DEFINED_glLoadTransposeMatrixfARB +#define GLEE_H_DEFINED_glLoadTransposeMatrixfARB + typedef void (APIENTRYP GLEEPFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat * m); + GLEE_EXTERN GLEEPFNGLLOADTRANSPOSEMATRIXFARBPROC GLeeFuncPtr_glLoadTransposeMatrixfARB; + #define glLoadTransposeMatrixfARB GLeeFuncPtr_glLoadTransposeMatrixfARB +#endif +#ifndef GLEE_H_DEFINED_glLoadTransposeMatrixdARB +#define GLEE_H_DEFINED_glLoadTransposeMatrixdARB + typedef void (APIENTRYP GLEEPFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble * m); + GLEE_EXTERN GLEEPFNGLLOADTRANSPOSEMATRIXDARBPROC GLeeFuncPtr_glLoadTransposeMatrixdARB; + #define glLoadTransposeMatrixdARB GLeeFuncPtr_glLoadTransposeMatrixdARB +#endif +#ifndef GLEE_H_DEFINED_glMultTransposeMatrixfARB +#define GLEE_H_DEFINED_glMultTransposeMatrixfARB + typedef void (APIENTRYP GLEEPFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat * m); + GLEE_EXTERN GLEEPFNGLMULTTRANSPOSEMATRIXFARBPROC GLeeFuncPtr_glMultTransposeMatrixfARB; + #define glMultTransposeMatrixfARB GLeeFuncPtr_glMultTransposeMatrixfARB +#endif +#ifndef GLEE_H_DEFINED_glMultTransposeMatrixdARB +#define GLEE_H_DEFINED_glMultTransposeMatrixdARB + typedef void (APIENTRYP GLEEPFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble * m); + GLEE_EXTERN GLEEPFNGLMULTTRANSPOSEMATRIXDARBPROC GLeeFuncPtr_glMultTransposeMatrixdARB; + #define glMultTransposeMatrixdARB GLeeFuncPtr_glMultTransposeMatrixdARB +#endif +#endif + +/* GL_ARB_multisample */ + +#ifndef GL_ARB_multisample +#define GL_ARB_multisample 1 +#define __GLEE_GL_ARB_multisample 1 +/* Constants */ +#define GL_MULTISAMPLE_ARB 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F +#define GL_SAMPLE_COVERAGE_ARB 0x80A0 +#define GL_SAMPLE_BUFFERS_ARB 0x80A8 +#define GL_SAMPLES_ARB 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB +#define GL_MULTISAMPLE_BIT_ARB 0x20000000 +#ifndef GLEE_H_DEFINED_glSampleCoverageARB +#define GLEE_H_DEFINED_glSampleCoverageARB + typedef void (APIENTRYP GLEEPFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert); + GLEE_EXTERN GLEEPFNGLSAMPLECOVERAGEARBPROC GLeeFuncPtr_glSampleCoverageARB; + #define glSampleCoverageARB GLeeFuncPtr_glSampleCoverageARB +#endif +#endif + +/* GL_ARB_texture_env_add */ + +#ifndef GL_ARB_texture_env_add +#define GL_ARB_texture_env_add 1 +#define __GLEE_GL_ARB_texture_env_add 1 +/* Constants */ +#endif + +/* GL_ARB_texture_cube_map */ + +#ifndef GL_ARB_texture_cube_map +#define GL_ARB_texture_cube_map 1 +#define __GLEE_GL_ARB_texture_cube_map 1 +/* Constants */ +#define GL_NORMAL_MAP_ARB 0x8511 +#define GL_REFLECTION_MAP_ARB 0x8512 +#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C +#endif + +/* GL_ARB_texture_compression */ + +#ifndef GL_ARB_texture_compression +#define GL_ARB_texture_compression 1 +#define __GLEE_GL_ARB_texture_compression 1 +/* Constants */ +#define GL_COMPRESSED_ALPHA_ARB 0x84E9 +#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB +#define GL_COMPRESSED_INTENSITY_ARB 0x84EC +#define GL_COMPRESSED_RGB_ARB 0x84ED +#define GL_COMPRESSED_RGBA_ARB 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 +#define GL_TEXTURE_COMPRESSED_ARB 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 +#ifndef GLEE_H_DEFINED_glCompressedTexImage3DARB +#define GLEE_H_DEFINED_glCompressedTexImage3DARB + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXIMAGE3DARBPROC GLeeFuncPtr_glCompressedTexImage3DARB; + #define glCompressedTexImage3DARB GLeeFuncPtr_glCompressedTexImage3DARB +#endif +#ifndef GLEE_H_DEFINED_glCompressedTexImage2DARB +#define GLEE_H_DEFINED_glCompressedTexImage2DARB + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXIMAGE2DARBPROC GLeeFuncPtr_glCompressedTexImage2DARB; + #define glCompressedTexImage2DARB GLeeFuncPtr_glCompressedTexImage2DARB +#endif +#ifndef GLEE_H_DEFINED_glCompressedTexImage1DARB +#define GLEE_H_DEFINED_glCompressedTexImage1DARB + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXIMAGE1DARBPROC GLeeFuncPtr_glCompressedTexImage1DARB; + #define glCompressedTexImage1DARB GLeeFuncPtr_glCompressedTexImage1DARB +#endif +#ifndef GLEE_H_DEFINED_glCompressedTexSubImage3DARB +#define GLEE_H_DEFINED_glCompressedTexSubImage3DARB + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC GLeeFuncPtr_glCompressedTexSubImage3DARB; + #define glCompressedTexSubImage3DARB GLeeFuncPtr_glCompressedTexSubImage3DARB +#endif +#ifndef GLEE_H_DEFINED_glCompressedTexSubImage2DARB +#define GLEE_H_DEFINED_glCompressedTexSubImage2DARB + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC GLeeFuncPtr_glCompressedTexSubImage2DARB; + #define glCompressedTexSubImage2DARB GLeeFuncPtr_glCompressedTexSubImage2DARB +#endif +#ifndef GLEE_H_DEFINED_glCompressedTexSubImage1DARB +#define GLEE_H_DEFINED_glCompressedTexSubImage1DARB + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC GLeeFuncPtr_glCompressedTexSubImage1DARB; + #define glCompressedTexSubImage1DARB GLeeFuncPtr_glCompressedTexSubImage1DARB +#endif +#ifndef GLEE_H_DEFINED_glGetCompressedTexImageARB +#define GLEE_H_DEFINED_glGetCompressedTexImageARB + typedef void (APIENTRYP GLEEPFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, GLvoid * img); + GLEE_EXTERN GLEEPFNGLGETCOMPRESSEDTEXIMAGEARBPROC GLeeFuncPtr_glGetCompressedTexImageARB; + #define glGetCompressedTexImageARB GLeeFuncPtr_glGetCompressedTexImageARB +#endif +#endif + +/* GL_ARB_texture_border_clamp */ + +#ifndef GL_ARB_texture_border_clamp +#define GL_ARB_texture_border_clamp 1 +#define __GLEE_GL_ARB_texture_border_clamp 1 +/* Constants */ +#define GL_CLAMP_TO_BORDER_ARB 0x812D +#endif + +/* GL_ARB_point_parameters */ + +#ifndef GL_ARB_point_parameters +#define GL_ARB_point_parameters 1 +#define __GLEE_GL_ARB_point_parameters 1 +/* Constants */ +#define GL_POINT_SIZE_MIN_ARB 0x8126 +#define GL_POINT_SIZE_MAX_ARB 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129 +#ifndef GLEE_H_DEFINED_glPointParameterfARB +#define GLEE_H_DEFINED_glPointParameterfARB + typedef void (APIENTRYP GLEEPFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLPOINTPARAMETERFARBPROC GLeeFuncPtr_glPointParameterfARB; + #define glPointParameterfARB GLeeFuncPtr_glPointParameterfARB +#endif +#ifndef GLEE_H_DEFINED_glPointParameterfvARB +#define GLEE_H_DEFINED_glPointParameterfvARB + typedef void (APIENTRYP GLEEPFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLPOINTPARAMETERFVARBPROC GLeeFuncPtr_glPointParameterfvARB; + #define glPointParameterfvARB GLeeFuncPtr_glPointParameterfvARB +#endif +#endif + +/* GL_ARB_vertex_blend */ + +#ifndef GL_ARB_vertex_blend +#define GL_ARB_vertex_blend 1 +#define __GLEE_GL_ARB_vertex_blend 1 +/* Constants */ +#define GL_MAX_VERTEX_UNITS_ARB 0x86A4 +#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5 +#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6 +#define GL_VERTEX_BLEND_ARB 0x86A7 +#define GL_CURRENT_WEIGHT_ARB 0x86A8 +#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9 +#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA +#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB +#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC +#define GL_WEIGHT_ARRAY_ARB 0x86AD +#define GL_MODELVIEW0_ARB 0x1700 +#define GL_MODELVIEW1_ARB 0x850A +#define GL_MODELVIEW2_ARB 0x8722 +#define GL_MODELVIEW3_ARB 0x8723 +#define GL_MODELVIEW4_ARB 0x8724 +#define GL_MODELVIEW5_ARB 0x8725 +#define GL_MODELVIEW6_ARB 0x8726 +#define GL_MODELVIEW7_ARB 0x8727 +#define GL_MODELVIEW8_ARB 0x8728 +#define GL_MODELVIEW9_ARB 0x8729 +#define GL_MODELVIEW10_ARB 0x872A +#define GL_MODELVIEW11_ARB 0x872B +#define GL_MODELVIEW12_ARB 0x872C +#define GL_MODELVIEW13_ARB 0x872D +#define GL_MODELVIEW14_ARB 0x872E +#define GL_MODELVIEW15_ARB 0x872F +#define GL_MODELVIEW16_ARB 0x8730 +#define GL_MODELVIEW17_ARB 0x8731 +#define GL_MODELVIEW18_ARB 0x8732 +#define GL_MODELVIEW19_ARB 0x8733 +#define GL_MODELVIEW20_ARB 0x8734 +#define GL_MODELVIEW21_ARB 0x8735 +#define GL_MODELVIEW22_ARB 0x8736 +#define GL_MODELVIEW23_ARB 0x8737 +#define GL_MODELVIEW24_ARB 0x8738 +#define GL_MODELVIEW25_ARB 0x8739 +#define GL_MODELVIEW26_ARB 0x873A +#define GL_MODELVIEW27_ARB 0x873B +#define GL_MODELVIEW28_ARB 0x873C +#define GL_MODELVIEW29_ARB 0x873D +#define GL_MODELVIEW30_ARB 0x873E +#define GL_MODELVIEW31_ARB 0x873F +#ifndef GLEE_H_DEFINED_glWeightbvARB +#define GLEE_H_DEFINED_glWeightbvARB + typedef void (APIENTRYP GLEEPFNGLWEIGHTBVARBPROC) (GLint size, const GLbyte * weights); + GLEE_EXTERN GLEEPFNGLWEIGHTBVARBPROC GLeeFuncPtr_glWeightbvARB; + #define glWeightbvARB GLeeFuncPtr_glWeightbvARB +#endif +#ifndef GLEE_H_DEFINED_glWeightsvARB +#define GLEE_H_DEFINED_glWeightsvARB + typedef void (APIENTRYP GLEEPFNGLWEIGHTSVARBPROC) (GLint size, const GLshort * weights); + GLEE_EXTERN GLEEPFNGLWEIGHTSVARBPROC GLeeFuncPtr_glWeightsvARB; + #define glWeightsvARB GLeeFuncPtr_glWeightsvARB +#endif +#ifndef GLEE_H_DEFINED_glWeightivARB +#define GLEE_H_DEFINED_glWeightivARB + typedef void (APIENTRYP GLEEPFNGLWEIGHTIVARBPROC) (GLint size, const GLint * weights); + GLEE_EXTERN GLEEPFNGLWEIGHTIVARBPROC GLeeFuncPtr_glWeightivARB; + #define glWeightivARB GLeeFuncPtr_glWeightivARB +#endif +#ifndef GLEE_H_DEFINED_glWeightfvARB +#define GLEE_H_DEFINED_glWeightfvARB + typedef void (APIENTRYP GLEEPFNGLWEIGHTFVARBPROC) (GLint size, const GLfloat * weights); + GLEE_EXTERN GLEEPFNGLWEIGHTFVARBPROC GLeeFuncPtr_glWeightfvARB; + #define glWeightfvARB GLeeFuncPtr_glWeightfvARB +#endif +#ifndef GLEE_H_DEFINED_glWeightdvARB +#define GLEE_H_DEFINED_glWeightdvARB + typedef void (APIENTRYP GLEEPFNGLWEIGHTDVARBPROC) (GLint size, const GLdouble * weights); + GLEE_EXTERN GLEEPFNGLWEIGHTDVARBPROC GLeeFuncPtr_glWeightdvARB; + #define glWeightdvARB GLeeFuncPtr_glWeightdvARB +#endif +#ifndef GLEE_H_DEFINED_glWeightubvARB +#define GLEE_H_DEFINED_glWeightubvARB + typedef void (APIENTRYP GLEEPFNGLWEIGHTUBVARBPROC) (GLint size, const GLubyte * weights); + GLEE_EXTERN GLEEPFNGLWEIGHTUBVARBPROC GLeeFuncPtr_glWeightubvARB; + #define glWeightubvARB GLeeFuncPtr_glWeightubvARB +#endif +#ifndef GLEE_H_DEFINED_glWeightusvARB +#define GLEE_H_DEFINED_glWeightusvARB + typedef void (APIENTRYP GLEEPFNGLWEIGHTUSVARBPROC) (GLint size, const GLushort * weights); + GLEE_EXTERN GLEEPFNGLWEIGHTUSVARBPROC GLeeFuncPtr_glWeightusvARB; + #define glWeightusvARB GLeeFuncPtr_glWeightusvARB +#endif +#ifndef GLEE_H_DEFINED_glWeightuivARB +#define GLEE_H_DEFINED_glWeightuivARB + typedef void (APIENTRYP GLEEPFNGLWEIGHTUIVARBPROC) (GLint size, const GLuint * weights); + GLEE_EXTERN GLEEPFNGLWEIGHTUIVARBPROC GLeeFuncPtr_glWeightuivARB; + #define glWeightuivARB GLeeFuncPtr_glWeightuivARB +#endif +#ifndef GLEE_H_DEFINED_glWeightPointerARB +#define GLEE_H_DEFINED_glWeightPointerARB + typedef void (APIENTRYP GLEEPFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLWEIGHTPOINTERARBPROC GLeeFuncPtr_glWeightPointerARB; + #define glWeightPointerARB GLeeFuncPtr_glWeightPointerARB +#endif +#ifndef GLEE_H_DEFINED_glVertexBlendARB +#define GLEE_H_DEFINED_glVertexBlendARB + typedef void (APIENTRYP GLEEPFNGLVERTEXBLENDARBPROC) (GLint count); + GLEE_EXTERN GLEEPFNGLVERTEXBLENDARBPROC GLeeFuncPtr_glVertexBlendARB; + #define glVertexBlendARB GLeeFuncPtr_glVertexBlendARB +#endif +#endif + +/* GL_ARB_matrix_palette */ + +#ifndef GL_ARB_matrix_palette +#define GL_ARB_matrix_palette 1 +#define __GLEE_GL_ARB_matrix_palette 1 +/* Constants */ +#define GL_MATRIX_PALETTE_ARB 0x8840 +#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841 +#define GL_MAX_PALETTE_MATRICES_ARB 0x8842 +#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843 +#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844 +#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845 +#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846 +#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847 +#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848 +#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849 +#ifndef GLEE_H_DEFINED_glCurrentPaletteMatrixARB +#define GLEE_H_DEFINED_glCurrentPaletteMatrixARB + typedef void (APIENTRYP GLEEPFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index); + GLEE_EXTERN GLEEPFNGLCURRENTPALETTEMATRIXARBPROC GLeeFuncPtr_glCurrentPaletteMatrixARB; + #define glCurrentPaletteMatrixARB GLeeFuncPtr_glCurrentPaletteMatrixARB +#endif +#ifndef GLEE_H_DEFINED_glMatrixIndexubvARB +#define GLEE_H_DEFINED_glMatrixIndexubvARB + typedef void (APIENTRYP GLEEPFNGLMATRIXINDEXUBVARBPROC) (GLint size, const GLubyte * indices); + GLEE_EXTERN GLEEPFNGLMATRIXINDEXUBVARBPROC GLeeFuncPtr_glMatrixIndexubvARB; + #define glMatrixIndexubvARB GLeeFuncPtr_glMatrixIndexubvARB +#endif +#ifndef GLEE_H_DEFINED_glMatrixIndexusvARB +#define GLEE_H_DEFINED_glMatrixIndexusvARB + typedef void (APIENTRYP GLEEPFNGLMATRIXINDEXUSVARBPROC) (GLint size, const GLushort * indices); + GLEE_EXTERN GLEEPFNGLMATRIXINDEXUSVARBPROC GLeeFuncPtr_glMatrixIndexusvARB; + #define glMatrixIndexusvARB GLeeFuncPtr_glMatrixIndexusvARB +#endif +#ifndef GLEE_H_DEFINED_glMatrixIndexuivARB +#define GLEE_H_DEFINED_glMatrixIndexuivARB + typedef void (APIENTRYP GLEEPFNGLMATRIXINDEXUIVARBPROC) (GLint size, const GLuint * indices); + GLEE_EXTERN GLEEPFNGLMATRIXINDEXUIVARBPROC GLeeFuncPtr_glMatrixIndexuivARB; + #define glMatrixIndexuivARB GLeeFuncPtr_glMatrixIndexuivARB +#endif +#ifndef GLEE_H_DEFINED_glMatrixIndexPointerARB +#define GLEE_H_DEFINED_glMatrixIndexPointerARB + typedef void (APIENTRYP GLEEPFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLMATRIXINDEXPOINTERARBPROC GLeeFuncPtr_glMatrixIndexPointerARB; + #define glMatrixIndexPointerARB GLeeFuncPtr_glMatrixIndexPointerARB +#endif +#endif + +/* GL_ARB_texture_env_combine */ + +#ifndef GL_ARB_texture_env_combine +#define GL_ARB_texture_env_combine 1 +#define __GLEE_GL_ARB_texture_env_combine 1 +/* Constants */ +#define GL_COMBINE_ARB 0x8570 +#define GL_COMBINE_RGB_ARB 0x8571 +#define GL_COMBINE_ALPHA_ARB 0x8572 +#define GL_SOURCE0_RGB_ARB 0x8580 +#define GL_SOURCE1_RGB_ARB 0x8581 +#define GL_SOURCE2_RGB_ARB 0x8582 +#define GL_SOURCE0_ALPHA_ARB 0x8588 +#define GL_SOURCE1_ALPHA_ARB 0x8589 +#define GL_SOURCE2_ALPHA_ARB 0x858A +#define GL_OPERAND0_RGB_ARB 0x8590 +#define GL_OPERAND1_RGB_ARB 0x8591 +#define GL_OPERAND2_RGB_ARB 0x8592 +#define GL_OPERAND0_ALPHA_ARB 0x8598 +#define GL_OPERAND1_ALPHA_ARB 0x8599 +#define GL_OPERAND2_ALPHA_ARB 0x859A +#define GL_RGB_SCALE_ARB 0x8573 +#define GL_ADD_SIGNED_ARB 0x8574 +#define GL_INTERPOLATE_ARB 0x8575 +#define GL_SUBTRACT_ARB 0x84E7 +#define GL_CONSTANT_ARB 0x8576 +#define GL_PRIMARY_COLOR_ARB 0x8577 +#define GL_PREVIOUS_ARB 0x8578 +#endif + +/* GL_ARB_texture_env_crossbar */ + +#ifndef GL_ARB_texture_env_crossbar +#define GL_ARB_texture_env_crossbar 1 +#define __GLEE_GL_ARB_texture_env_crossbar 1 +/* Constants */ +#endif + +/* GL_ARB_texture_env_dot3 */ + +#ifndef GL_ARB_texture_env_dot3 +#define GL_ARB_texture_env_dot3 1 +#define __GLEE_GL_ARB_texture_env_dot3 1 +/* Constants */ +#define GL_DOT3_RGB_ARB 0x86AE +#define GL_DOT3_RGBA_ARB 0x86AF +#endif + +/* GL_ARB_texture_mirrored_repeat */ + +#ifndef GL_ARB_texture_mirrored_repeat +#define GL_ARB_texture_mirrored_repeat 1 +#define __GLEE_GL_ARB_texture_mirrored_repeat 1 +/* Constants */ +#define GL_MIRRORED_REPEAT_ARB 0x8370 +#endif + +/* GL_ARB_depth_texture */ + +#ifndef GL_ARB_depth_texture +#define GL_ARB_depth_texture 1 +#define __GLEE_GL_ARB_depth_texture 1 +/* Constants */ +#define GL_DEPTH_COMPONENT16_ARB 0x81A5 +#define GL_DEPTH_COMPONENT24_ARB 0x81A6 +#define GL_DEPTH_COMPONENT32_ARB 0x81A7 +#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A +#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B +#endif + +/* GL_ARB_shadow */ + +#ifndef GL_ARB_shadow +#define GL_ARB_shadow 1 +#define __GLEE_GL_ARB_shadow 1 +/* Constants */ +#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C +#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D +#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E +#endif + +/* GL_ARB_shadow_ambient */ + +#ifndef GL_ARB_shadow_ambient +#define GL_ARB_shadow_ambient 1 +#define __GLEE_GL_ARB_shadow_ambient 1 +/* Constants */ +#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF +#endif + +/* GL_ARB_window_pos */ + +#ifndef GL_ARB_window_pos +#define GL_ARB_window_pos 1 +#define __GLEE_GL_ARB_window_pos 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glWindowPos2dARB +#define GLEE_H_DEFINED_glWindowPos2dARB + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2DARBPROC GLeeFuncPtr_glWindowPos2dARB; + #define glWindowPos2dARB GLeeFuncPtr_glWindowPos2dARB +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2dvARB +#define GLEE_H_DEFINED_glWindowPos2dvARB + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2DVARBPROC) (const GLdouble * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2DVARBPROC GLeeFuncPtr_glWindowPos2dvARB; + #define glWindowPos2dvARB GLeeFuncPtr_glWindowPos2dvARB +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2fARB +#define GLEE_H_DEFINED_glWindowPos2fARB + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2FARBPROC GLeeFuncPtr_glWindowPos2fARB; + #define glWindowPos2fARB GLeeFuncPtr_glWindowPos2fARB +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2fvARB +#define GLEE_H_DEFINED_glWindowPos2fvARB + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2FVARBPROC) (const GLfloat * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2FVARBPROC GLeeFuncPtr_glWindowPos2fvARB; + #define glWindowPos2fvARB GLeeFuncPtr_glWindowPos2fvARB +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2iARB +#define GLEE_H_DEFINED_glWindowPos2iARB + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2IARBPROC GLeeFuncPtr_glWindowPos2iARB; + #define glWindowPos2iARB GLeeFuncPtr_glWindowPos2iARB +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2ivARB +#define GLEE_H_DEFINED_glWindowPos2ivARB + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2IVARBPROC) (const GLint * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2IVARBPROC GLeeFuncPtr_glWindowPos2ivARB; + #define glWindowPos2ivARB GLeeFuncPtr_glWindowPos2ivARB +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2sARB +#define GLEE_H_DEFINED_glWindowPos2sARB + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2SARBPROC GLeeFuncPtr_glWindowPos2sARB; + #define glWindowPos2sARB GLeeFuncPtr_glWindowPos2sARB +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2svARB +#define GLEE_H_DEFINED_glWindowPos2svARB + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2SVARBPROC) (const GLshort * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2SVARBPROC GLeeFuncPtr_glWindowPos2svARB; + #define glWindowPos2svARB GLeeFuncPtr_glWindowPos2svARB +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3dARB +#define GLEE_H_DEFINED_glWindowPos3dARB + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3DARBPROC GLeeFuncPtr_glWindowPos3dARB; + #define glWindowPos3dARB GLeeFuncPtr_glWindowPos3dARB +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3dvARB +#define GLEE_H_DEFINED_glWindowPos3dvARB + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3DVARBPROC) (const GLdouble * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3DVARBPROC GLeeFuncPtr_glWindowPos3dvARB; + #define glWindowPos3dvARB GLeeFuncPtr_glWindowPos3dvARB +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3fARB +#define GLEE_H_DEFINED_glWindowPos3fARB + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3FARBPROC GLeeFuncPtr_glWindowPos3fARB; + #define glWindowPos3fARB GLeeFuncPtr_glWindowPos3fARB +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3fvARB +#define GLEE_H_DEFINED_glWindowPos3fvARB + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3FVARBPROC) (const GLfloat * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3FVARBPROC GLeeFuncPtr_glWindowPos3fvARB; + #define glWindowPos3fvARB GLeeFuncPtr_glWindowPos3fvARB +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3iARB +#define GLEE_H_DEFINED_glWindowPos3iARB + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3IARBPROC GLeeFuncPtr_glWindowPos3iARB; + #define glWindowPos3iARB GLeeFuncPtr_glWindowPos3iARB +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3ivARB +#define GLEE_H_DEFINED_glWindowPos3ivARB + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3IVARBPROC) (const GLint * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3IVARBPROC GLeeFuncPtr_glWindowPos3ivARB; + #define glWindowPos3ivARB GLeeFuncPtr_glWindowPos3ivARB +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3sARB +#define GLEE_H_DEFINED_glWindowPos3sARB + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3SARBPROC GLeeFuncPtr_glWindowPos3sARB; + #define glWindowPos3sARB GLeeFuncPtr_glWindowPos3sARB +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3svARB +#define GLEE_H_DEFINED_glWindowPos3svARB + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3SVARBPROC) (const GLshort * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3SVARBPROC GLeeFuncPtr_glWindowPos3svARB; + #define glWindowPos3svARB GLeeFuncPtr_glWindowPos3svARB +#endif +#endif + +/* GL_ARB_vertex_program */ + +#ifndef GL_ARB_vertex_program +#define GL_ARB_vertex_program 1 +#define __GLEE_GL_ARB_vertex_program 1 +/* Constants */ +#define GL_COLOR_SUM_ARB 0x8458 +#define GL_VERTEX_PROGRAM_ARB 0x8620 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 +#define GL_PROGRAM_LENGTH_ARB 0x8627 +#define GL_PROGRAM_STRING_ARB 0x8628 +#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E +#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F +#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 +#define GL_CURRENT_MATRIX_ARB 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 +#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B +#define GL_PROGRAM_BINDING_ARB 0x8677 +#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A +#define GL_PROGRAM_ERROR_STRING_ARB 0x8874 +#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 +#define GL_PROGRAM_FORMAT_ARB 0x8876 +#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0 +#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 +#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 +#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 +#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4 +#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 +#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 +#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 +#define GL_PROGRAM_PARAMETERS_ARB 0x88A8 +#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9 +#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA +#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB +#define GL_PROGRAM_ATTRIBS_ARB 0x88AC +#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD +#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE +#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF +#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 +#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 +#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 +#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 +#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 +#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 +#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 +#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 +#define GL_MATRIX0_ARB 0x88C0 +#define GL_MATRIX1_ARB 0x88C1 +#define GL_MATRIX2_ARB 0x88C2 +#define GL_MATRIX3_ARB 0x88C3 +#define GL_MATRIX4_ARB 0x88C4 +#define GL_MATRIX5_ARB 0x88C5 +#define GL_MATRIX6_ARB 0x88C6 +#define GL_MATRIX7_ARB 0x88C7 +#define GL_MATRIX8_ARB 0x88C8 +#define GL_MATRIX9_ARB 0x88C9 +#define GL_MATRIX10_ARB 0x88CA +#define GL_MATRIX11_ARB 0x88CB +#define GL_MATRIX12_ARB 0x88CC +#define GL_MATRIX13_ARB 0x88CD +#define GL_MATRIX14_ARB 0x88CE +#define GL_MATRIX15_ARB 0x88CF +#define GL_MATRIX16_ARB 0x88D0 +#define GL_MATRIX17_ARB 0x88D1 +#define GL_MATRIX18_ARB 0x88D2 +#define GL_MATRIX19_ARB 0x88D3 +#define GL_MATRIX20_ARB 0x88D4 +#define GL_MATRIX21_ARB 0x88D5 +#define GL_MATRIX22_ARB 0x88D6 +#define GL_MATRIX23_ARB 0x88D7 +#define GL_MATRIX24_ARB 0x88D8 +#define GL_MATRIX25_ARB 0x88D9 +#define GL_MATRIX26_ARB 0x88DA +#define GL_MATRIX27_ARB 0x88DB +#define GL_MATRIX28_ARB 0x88DC +#define GL_MATRIX29_ARB 0x88DD +#define GL_MATRIX30_ARB 0x88DE +#define GL_MATRIX31_ARB 0x88DF +#ifndef GLEE_H_DEFINED_glVertexAttrib1dARB +#define GLEE_H_DEFINED_glVertexAttrib1dARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1DARBPROC GLeeFuncPtr_glVertexAttrib1dARB; + #define glVertexAttrib1dARB GLeeFuncPtr_glVertexAttrib1dARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1dvARB +#define GLEE_H_DEFINED_glVertexAttrib1dvARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1DVARBPROC GLeeFuncPtr_glVertexAttrib1dvARB; + #define glVertexAttrib1dvARB GLeeFuncPtr_glVertexAttrib1dvARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1fARB +#define GLEE_H_DEFINED_glVertexAttrib1fARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1FARBPROC GLeeFuncPtr_glVertexAttrib1fARB; + #define glVertexAttrib1fARB GLeeFuncPtr_glVertexAttrib1fARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1fvARB +#define GLEE_H_DEFINED_glVertexAttrib1fvARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1FVARBPROC GLeeFuncPtr_glVertexAttrib1fvARB; + #define glVertexAttrib1fvARB GLeeFuncPtr_glVertexAttrib1fvARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1sARB +#define GLEE_H_DEFINED_glVertexAttrib1sARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1SARBPROC GLeeFuncPtr_glVertexAttrib1sARB; + #define glVertexAttrib1sARB GLeeFuncPtr_glVertexAttrib1sARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1svARB +#define GLEE_H_DEFINED_glVertexAttrib1svARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1SVARBPROC GLeeFuncPtr_glVertexAttrib1svARB; + #define glVertexAttrib1svARB GLeeFuncPtr_glVertexAttrib1svARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2dARB +#define GLEE_H_DEFINED_glVertexAttrib2dARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2DARBPROC GLeeFuncPtr_glVertexAttrib2dARB; + #define glVertexAttrib2dARB GLeeFuncPtr_glVertexAttrib2dARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2dvARB +#define GLEE_H_DEFINED_glVertexAttrib2dvARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2DVARBPROC GLeeFuncPtr_glVertexAttrib2dvARB; + #define glVertexAttrib2dvARB GLeeFuncPtr_glVertexAttrib2dvARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2fARB +#define GLEE_H_DEFINED_glVertexAttrib2fARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2FARBPROC GLeeFuncPtr_glVertexAttrib2fARB; + #define glVertexAttrib2fARB GLeeFuncPtr_glVertexAttrib2fARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2fvARB +#define GLEE_H_DEFINED_glVertexAttrib2fvARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2FVARBPROC GLeeFuncPtr_glVertexAttrib2fvARB; + #define glVertexAttrib2fvARB GLeeFuncPtr_glVertexAttrib2fvARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2sARB +#define GLEE_H_DEFINED_glVertexAttrib2sARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2SARBPROC GLeeFuncPtr_glVertexAttrib2sARB; + #define glVertexAttrib2sARB GLeeFuncPtr_glVertexAttrib2sARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2svARB +#define GLEE_H_DEFINED_glVertexAttrib2svARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2SVARBPROC GLeeFuncPtr_glVertexAttrib2svARB; + #define glVertexAttrib2svARB GLeeFuncPtr_glVertexAttrib2svARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3dARB +#define GLEE_H_DEFINED_glVertexAttrib3dARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3DARBPROC GLeeFuncPtr_glVertexAttrib3dARB; + #define glVertexAttrib3dARB GLeeFuncPtr_glVertexAttrib3dARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3dvARB +#define GLEE_H_DEFINED_glVertexAttrib3dvARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3DVARBPROC GLeeFuncPtr_glVertexAttrib3dvARB; + #define glVertexAttrib3dvARB GLeeFuncPtr_glVertexAttrib3dvARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3fARB +#define GLEE_H_DEFINED_glVertexAttrib3fARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3FARBPROC GLeeFuncPtr_glVertexAttrib3fARB; + #define glVertexAttrib3fARB GLeeFuncPtr_glVertexAttrib3fARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3fvARB +#define GLEE_H_DEFINED_glVertexAttrib3fvARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3FVARBPROC GLeeFuncPtr_glVertexAttrib3fvARB; + #define glVertexAttrib3fvARB GLeeFuncPtr_glVertexAttrib3fvARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3sARB +#define GLEE_H_DEFINED_glVertexAttrib3sARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3SARBPROC GLeeFuncPtr_glVertexAttrib3sARB; + #define glVertexAttrib3sARB GLeeFuncPtr_glVertexAttrib3sARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3svARB +#define GLEE_H_DEFINED_glVertexAttrib3svARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3SVARBPROC GLeeFuncPtr_glVertexAttrib3svARB; + #define glVertexAttrib3svARB GLeeFuncPtr_glVertexAttrib3svARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4NbvARB +#define GLEE_H_DEFINED_glVertexAttrib4NbvARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4NBVARBPROC GLeeFuncPtr_glVertexAttrib4NbvARB; + #define glVertexAttrib4NbvARB GLeeFuncPtr_glVertexAttrib4NbvARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4NivARB +#define GLEE_H_DEFINED_glVertexAttrib4NivARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4NIVARBPROC GLeeFuncPtr_glVertexAttrib4NivARB; + #define glVertexAttrib4NivARB GLeeFuncPtr_glVertexAttrib4NivARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4NsvARB +#define GLEE_H_DEFINED_glVertexAttrib4NsvARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4NSVARBPROC GLeeFuncPtr_glVertexAttrib4NsvARB; + #define glVertexAttrib4NsvARB GLeeFuncPtr_glVertexAttrib4NsvARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4NubARB +#define GLEE_H_DEFINED_glVertexAttrib4NubARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4NUBARBPROC GLeeFuncPtr_glVertexAttrib4NubARB; + #define glVertexAttrib4NubARB GLeeFuncPtr_glVertexAttrib4NubARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4NubvARB +#define GLEE_H_DEFINED_glVertexAttrib4NubvARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4NUBVARBPROC GLeeFuncPtr_glVertexAttrib4NubvARB; + #define glVertexAttrib4NubvARB GLeeFuncPtr_glVertexAttrib4NubvARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4NuivARB +#define GLEE_H_DEFINED_glVertexAttrib4NuivARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4NUIVARBPROC GLeeFuncPtr_glVertexAttrib4NuivARB; + #define glVertexAttrib4NuivARB GLeeFuncPtr_glVertexAttrib4NuivARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4NusvARB +#define GLEE_H_DEFINED_glVertexAttrib4NusvARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4NUSVARBPROC GLeeFuncPtr_glVertexAttrib4NusvARB; + #define glVertexAttrib4NusvARB GLeeFuncPtr_glVertexAttrib4NusvARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4bvARB +#define GLEE_H_DEFINED_glVertexAttrib4bvARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4BVARBPROC GLeeFuncPtr_glVertexAttrib4bvARB; + #define glVertexAttrib4bvARB GLeeFuncPtr_glVertexAttrib4bvARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4dARB +#define GLEE_H_DEFINED_glVertexAttrib4dARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4DARBPROC GLeeFuncPtr_glVertexAttrib4dARB; + #define glVertexAttrib4dARB GLeeFuncPtr_glVertexAttrib4dARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4dvARB +#define GLEE_H_DEFINED_glVertexAttrib4dvARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4DVARBPROC GLeeFuncPtr_glVertexAttrib4dvARB; + #define glVertexAttrib4dvARB GLeeFuncPtr_glVertexAttrib4dvARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4fARB +#define GLEE_H_DEFINED_glVertexAttrib4fARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4FARBPROC GLeeFuncPtr_glVertexAttrib4fARB; + #define glVertexAttrib4fARB GLeeFuncPtr_glVertexAttrib4fARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4fvARB +#define GLEE_H_DEFINED_glVertexAttrib4fvARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4FVARBPROC GLeeFuncPtr_glVertexAttrib4fvARB; + #define glVertexAttrib4fvARB GLeeFuncPtr_glVertexAttrib4fvARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4ivARB +#define GLEE_H_DEFINED_glVertexAttrib4ivARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4IVARBPROC GLeeFuncPtr_glVertexAttrib4ivARB; + #define glVertexAttrib4ivARB GLeeFuncPtr_glVertexAttrib4ivARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4sARB +#define GLEE_H_DEFINED_glVertexAttrib4sARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4SARBPROC GLeeFuncPtr_glVertexAttrib4sARB; + #define glVertexAttrib4sARB GLeeFuncPtr_glVertexAttrib4sARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4svARB +#define GLEE_H_DEFINED_glVertexAttrib4svARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4SVARBPROC GLeeFuncPtr_glVertexAttrib4svARB; + #define glVertexAttrib4svARB GLeeFuncPtr_glVertexAttrib4svARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4ubvARB +#define GLEE_H_DEFINED_glVertexAttrib4ubvARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4UBVARBPROC GLeeFuncPtr_glVertexAttrib4ubvARB; + #define glVertexAttrib4ubvARB GLeeFuncPtr_glVertexAttrib4ubvARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4uivARB +#define GLEE_H_DEFINED_glVertexAttrib4uivARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4UIVARBPROC GLeeFuncPtr_glVertexAttrib4uivARB; + #define glVertexAttrib4uivARB GLeeFuncPtr_glVertexAttrib4uivARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4usvARB +#define GLEE_H_DEFINED_glVertexAttrib4usvARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4USVARBPROC GLeeFuncPtr_glVertexAttrib4usvARB; + #define glVertexAttrib4usvARB GLeeFuncPtr_glVertexAttrib4usvARB +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribPointerARB +#define GLEE_H_DEFINED_glVertexAttribPointerARB + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBPOINTERARBPROC GLeeFuncPtr_glVertexAttribPointerARB; + #define glVertexAttribPointerARB GLeeFuncPtr_glVertexAttribPointerARB +#endif +#ifndef GLEE_H_DEFINED_glEnableVertexAttribArrayARB +#define GLEE_H_DEFINED_glEnableVertexAttribArrayARB + typedef void (APIENTRYP GLEEPFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); + GLEE_EXTERN GLEEPFNGLENABLEVERTEXATTRIBARRAYARBPROC GLeeFuncPtr_glEnableVertexAttribArrayARB; + #define glEnableVertexAttribArrayARB GLeeFuncPtr_glEnableVertexAttribArrayARB +#endif +#ifndef GLEE_H_DEFINED_glDisableVertexAttribArrayARB +#define GLEE_H_DEFINED_glDisableVertexAttribArrayARB + typedef void (APIENTRYP GLEEPFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); + GLEE_EXTERN GLEEPFNGLDISABLEVERTEXATTRIBARRAYARBPROC GLeeFuncPtr_glDisableVertexAttribArrayARB; + #define glDisableVertexAttribArrayARB GLeeFuncPtr_glDisableVertexAttribArrayARB +#endif +#ifndef GLEE_H_DEFINED_glProgramStringARB +#define GLEE_H_DEFINED_glProgramStringARB + typedef void (APIENTRYP GLEEPFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const GLvoid * string); + GLEE_EXTERN GLEEPFNGLPROGRAMSTRINGARBPROC GLeeFuncPtr_glProgramStringARB; + #define glProgramStringARB GLeeFuncPtr_glProgramStringARB +#endif +#ifndef GLEE_H_DEFINED_glBindProgramARB +#define GLEE_H_DEFINED_glBindProgramARB + typedef void (APIENTRYP GLEEPFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program); + GLEE_EXTERN GLEEPFNGLBINDPROGRAMARBPROC GLeeFuncPtr_glBindProgramARB; + #define glBindProgramARB GLeeFuncPtr_glBindProgramARB +#endif +#ifndef GLEE_H_DEFINED_glDeleteProgramsARB +#define GLEE_H_DEFINED_glDeleteProgramsARB + typedef void (APIENTRYP GLEEPFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint * programs); + GLEE_EXTERN GLEEPFNGLDELETEPROGRAMSARBPROC GLeeFuncPtr_glDeleteProgramsARB; + #define glDeleteProgramsARB GLeeFuncPtr_glDeleteProgramsARB +#endif +#ifndef GLEE_H_DEFINED_glGenProgramsARB +#define GLEE_H_DEFINED_glGenProgramsARB + typedef void (APIENTRYP GLEEPFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint * programs); + GLEE_EXTERN GLEEPFNGLGENPROGRAMSARBPROC GLeeFuncPtr_glGenProgramsARB; + #define glGenProgramsARB GLeeFuncPtr_glGenProgramsARB +#endif +#ifndef GLEE_H_DEFINED_glProgramEnvParameter4dARB +#define GLEE_H_DEFINED_glProgramEnvParameter4dARB + typedef void (APIENTRYP GLEEPFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + GLEE_EXTERN GLEEPFNGLPROGRAMENVPARAMETER4DARBPROC GLeeFuncPtr_glProgramEnvParameter4dARB; + #define glProgramEnvParameter4dARB GLeeFuncPtr_glProgramEnvParameter4dARB +#endif +#ifndef GLEE_H_DEFINED_glProgramEnvParameter4dvARB +#define GLEE_H_DEFINED_glProgramEnvParameter4dvARB + typedef void (APIENTRYP GLEEPFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble * params); + GLEE_EXTERN GLEEPFNGLPROGRAMENVPARAMETER4DVARBPROC GLeeFuncPtr_glProgramEnvParameter4dvARB; + #define glProgramEnvParameter4dvARB GLeeFuncPtr_glProgramEnvParameter4dvARB +#endif +#ifndef GLEE_H_DEFINED_glProgramEnvParameter4fARB +#define GLEE_H_DEFINED_glProgramEnvParameter4fARB + typedef void (APIENTRYP GLEEPFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + GLEE_EXTERN GLEEPFNGLPROGRAMENVPARAMETER4FARBPROC GLeeFuncPtr_glProgramEnvParameter4fARB; + #define glProgramEnvParameter4fARB GLeeFuncPtr_glProgramEnvParameter4fARB +#endif +#ifndef GLEE_H_DEFINED_glProgramEnvParameter4fvARB +#define GLEE_H_DEFINED_glProgramEnvParameter4fvARB + typedef void (APIENTRYP GLEEPFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLPROGRAMENVPARAMETER4FVARBPROC GLeeFuncPtr_glProgramEnvParameter4fvARB; + #define glProgramEnvParameter4fvARB GLeeFuncPtr_glProgramEnvParameter4fvARB +#endif +#ifndef GLEE_H_DEFINED_glProgramLocalParameter4dARB +#define GLEE_H_DEFINED_glProgramLocalParameter4dARB + typedef void (APIENTRYP GLEEPFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + GLEE_EXTERN GLEEPFNGLPROGRAMLOCALPARAMETER4DARBPROC GLeeFuncPtr_glProgramLocalParameter4dARB; + #define glProgramLocalParameter4dARB GLeeFuncPtr_glProgramLocalParameter4dARB +#endif +#ifndef GLEE_H_DEFINED_glProgramLocalParameter4dvARB +#define GLEE_H_DEFINED_glProgramLocalParameter4dvARB + typedef void (APIENTRYP GLEEPFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble * params); + GLEE_EXTERN GLEEPFNGLPROGRAMLOCALPARAMETER4DVARBPROC GLeeFuncPtr_glProgramLocalParameter4dvARB; + #define glProgramLocalParameter4dvARB GLeeFuncPtr_glProgramLocalParameter4dvARB +#endif +#ifndef GLEE_H_DEFINED_glProgramLocalParameter4fARB +#define GLEE_H_DEFINED_glProgramLocalParameter4fARB + typedef void (APIENTRYP GLEEPFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + GLEE_EXTERN GLEEPFNGLPROGRAMLOCALPARAMETER4FARBPROC GLeeFuncPtr_glProgramLocalParameter4fARB; + #define glProgramLocalParameter4fARB GLeeFuncPtr_glProgramLocalParameter4fARB +#endif +#ifndef GLEE_H_DEFINED_glProgramLocalParameter4fvARB +#define GLEE_H_DEFINED_glProgramLocalParameter4fvARB + typedef void (APIENTRYP GLEEPFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLPROGRAMLOCALPARAMETER4FVARBPROC GLeeFuncPtr_glProgramLocalParameter4fvARB; + #define glProgramLocalParameter4fvARB GLeeFuncPtr_glProgramLocalParameter4fvARB +#endif +#ifndef GLEE_H_DEFINED_glGetProgramEnvParameterdvARB +#define GLEE_H_DEFINED_glGetProgramEnvParameterdvARB + typedef void (APIENTRYP GLEEPFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble * params); + GLEE_EXTERN GLEEPFNGLGETPROGRAMENVPARAMETERDVARBPROC GLeeFuncPtr_glGetProgramEnvParameterdvARB; + #define glGetProgramEnvParameterdvARB GLeeFuncPtr_glGetProgramEnvParameterdvARB +#endif +#ifndef GLEE_H_DEFINED_glGetProgramEnvParameterfvARB +#define GLEE_H_DEFINED_glGetProgramEnvParameterfvARB + typedef void (APIENTRYP GLEEPFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETPROGRAMENVPARAMETERFVARBPROC GLeeFuncPtr_glGetProgramEnvParameterfvARB; + #define glGetProgramEnvParameterfvARB GLeeFuncPtr_glGetProgramEnvParameterfvARB +#endif +#ifndef GLEE_H_DEFINED_glGetProgramLocalParameterdvARB +#define GLEE_H_DEFINED_glGetProgramLocalParameterdvARB + typedef void (APIENTRYP GLEEPFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble * params); + GLEE_EXTERN GLEEPFNGLGETPROGRAMLOCALPARAMETERDVARBPROC GLeeFuncPtr_glGetProgramLocalParameterdvARB; + #define glGetProgramLocalParameterdvARB GLeeFuncPtr_glGetProgramLocalParameterdvARB +#endif +#ifndef GLEE_H_DEFINED_glGetProgramLocalParameterfvARB +#define GLEE_H_DEFINED_glGetProgramLocalParameterfvARB + typedef void (APIENTRYP GLEEPFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETPROGRAMLOCALPARAMETERFVARBPROC GLeeFuncPtr_glGetProgramLocalParameterfvARB; + #define glGetProgramLocalParameterfvARB GLeeFuncPtr_glGetProgramLocalParameterfvARB +#endif +#ifndef GLEE_H_DEFINED_glGetProgramivARB +#define GLEE_H_DEFINED_glGetProgramivARB + typedef void (APIENTRYP GLEEPFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETPROGRAMIVARBPROC GLeeFuncPtr_glGetProgramivARB; + #define glGetProgramivARB GLeeFuncPtr_glGetProgramivARB +#endif +#ifndef GLEE_H_DEFINED_glGetProgramStringARB +#define GLEE_H_DEFINED_glGetProgramStringARB + typedef void (APIENTRYP GLEEPFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, GLvoid * string); + GLEE_EXTERN GLEEPFNGLGETPROGRAMSTRINGARBPROC GLeeFuncPtr_glGetProgramStringARB; + #define glGetProgramStringARB GLeeFuncPtr_glGetProgramStringARB +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribdvARB +#define GLEE_H_DEFINED_glGetVertexAttribdvARB + typedef void (APIENTRYP GLEEPFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble * params); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBDVARBPROC GLeeFuncPtr_glGetVertexAttribdvARB; + #define glGetVertexAttribdvARB GLeeFuncPtr_glGetVertexAttribdvARB +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribfvARB +#define GLEE_H_DEFINED_glGetVertexAttribfvARB + typedef void (APIENTRYP GLEEPFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBFVARBPROC GLeeFuncPtr_glGetVertexAttribfvARB; + #define glGetVertexAttribfvARB GLeeFuncPtr_glGetVertexAttribfvARB +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribivARB +#define GLEE_H_DEFINED_glGetVertexAttribivARB + typedef void (APIENTRYP GLEEPFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBIVARBPROC GLeeFuncPtr_glGetVertexAttribivARB; + #define glGetVertexAttribivARB GLeeFuncPtr_glGetVertexAttribivARB +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribPointervARB +#define GLEE_H_DEFINED_glGetVertexAttribPointervARB + typedef void (APIENTRYP GLEEPFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid* * pointer); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBPOINTERVARBPROC GLeeFuncPtr_glGetVertexAttribPointervARB; + #define glGetVertexAttribPointervARB GLeeFuncPtr_glGetVertexAttribPointervARB +#endif +#ifndef GLEE_H_DEFINED_glIsProgramARB +#define GLEE_H_DEFINED_glIsProgramARB + typedef GLboolean (APIENTRYP GLEEPFNGLISPROGRAMARBPROC) (GLuint program); + GLEE_EXTERN GLEEPFNGLISPROGRAMARBPROC GLeeFuncPtr_glIsProgramARB; + #define glIsProgramARB GLeeFuncPtr_glIsProgramARB +#endif +#endif + +/* GL_ARB_fragment_program */ + +#ifndef GL_ARB_fragment_program +#define GL_ARB_fragment_program 1 +#define __GLEE_GL_ARB_fragment_program 1 +/* Constants */ +#define GL_FRAGMENT_PROGRAM_ARB 0x8804 +#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805 +#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806 +#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807 +#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808 +#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809 +#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A +#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B +#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C +#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D +#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E +#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F +#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810 +#define GL_MAX_TEXTURE_COORDS_ARB 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 +#endif + +/* GL_ARB_vertex_buffer_object */ + +#ifndef GL_ARB_vertex_buffer_object +#define GL_ARB_vertex_buffer_object 1 +#define __GLEE_GL_ARB_vertex_buffer_object 1 +/* Constants */ +#define GL_BUFFER_SIZE_ARB 0x8764 +#define GL_BUFFER_USAGE_ARB 0x8765 +#define GL_ARRAY_BUFFER_ARB 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 +#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F +#define GL_READ_ONLY_ARB 0x88B8 +#define GL_WRITE_ONLY_ARB 0x88B9 +#define GL_READ_WRITE_ARB 0x88BA +#define GL_BUFFER_ACCESS_ARB 0x88BB +#define GL_BUFFER_MAPPED_ARB 0x88BC +#define GL_BUFFER_MAP_POINTER_ARB 0x88BD +#define GL_STREAM_DRAW_ARB 0x88E0 +#define GL_STREAM_READ_ARB 0x88E1 +#define GL_STREAM_COPY_ARB 0x88E2 +#define GL_STATIC_DRAW_ARB 0x88E4 +#define GL_STATIC_READ_ARB 0x88E5 +#define GL_STATIC_COPY_ARB 0x88E6 +#define GL_DYNAMIC_DRAW_ARB 0x88E8 +#define GL_DYNAMIC_READ_ARB 0x88E9 +#define GL_DYNAMIC_COPY_ARB 0x88EA +#ifndef GLEE_H_DEFINED_glBindBufferARB +#define GLEE_H_DEFINED_glBindBufferARB + typedef void (APIENTRYP GLEEPFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer); + GLEE_EXTERN GLEEPFNGLBINDBUFFERARBPROC GLeeFuncPtr_glBindBufferARB; + #define glBindBufferARB GLeeFuncPtr_glBindBufferARB +#endif +#ifndef GLEE_H_DEFINED_glDeleteBuffersARB +#define GLEE_H_DEFINED_glDeleteBuffersARB + typedef void (APIENTRYP GLEEPFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint * buffers); + GLEE_EXTERN GLEEPFNGLDELETEBUFFERSARBPROC GLeeFuncPtr_glDeleteBuffersARB; + #define glDeleteBuffersARB GLeeFuncPtr_glDeleteBuffersARB +#endif +#ifndef GLEE_H_DEFINED_glGenBuffersARB +#define GLEE_H_DEFINED_glGenBuffersARB + typedef void (APIENTRYP GLEEPFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint * buffers); + GLEE_EXTERN GLEEPFNGLGENBUFFERSARBPROC GLeeFuncPtr_glGenBuffersARB; + #define glGenBuffersARB GLeeFuncPtr_glGenBuffersARB +#endif +#ifndef GLEE_H_DEFINED_glIsBufferARB +#define GLEE_H_DEFINED_glIsBufferARB + typedef GLboolean (APIENTRYP GLEEPFNGLISBUFFERARBPROC) (GLuint buffer); + GLEE_EXTERN GLEEPFNGLISBUFFERARBPROC GLeeFuncPtr_glIsBufferARB; + #define glIsBufferARB GLeeFuncPtr_glIsBufferARB +#endif +#ifndef GLEE_H_DEFINED_glBufferDataARB +#define GLEE_H_DEFINED_glBufferDataARB + typedef void (APIENTRYP GLEEPFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage); + GLEE_EXTERN GLEEPFNGLBUFFERDATAARBPROC GLeeFuncPtr_glBufferDataARB; + #define glBufferDataARB GLeeFuncPtr_glBufferDataARB +#endif +#ifndef GLEE_H_DEFINED_glBufferSubDataARB +#define GLEE_H_DEFINED_glBufferSubDataARB + typedef void (APIENTRYP GLEEPFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLBUFFERSUBDATAARBPROC GLeeFuncPtr_glBufferSubDataARB; + #define glBufferSubDataARB GLeeFuncPtr_glBufferSubDataARB +#endif +#ifndef GLEE_H_DEFINED_glGetBufferSubDataARB +#define GLEE_H_DEFINED_glGetBufferSubDataARB + typedef void (APIENTRYP GLEEPFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid * data); + GLEE_EXTERN GLEEPFNGLGETBUFFERSUBDATAARBPROC GLeeFuncPtr_glGetBufferSubDataARB; + #define glGetBufferSubDataARB GLeeFuncPtr_glGetBufferSubDataARB +#endif +#ifndef GLEE_H_DEFINED_glMapBufferARB +#define GLEE_H_DEFINED_glMapBufferARB + typedef GLvoid* (APIENTRYP GLEEPFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access); + GLEE_EXTERN GLEEPFNGLMAPBUFFERARBPROC GLeeFuncPtr_glMapBufferARB; + #define glMapBufferARB GLeeFuncPtr_glMapBufferARB +#endif +#ifndef GLEE_H_DEFINED_glUnmapBufferARB +#define GLEE_H_DEFINED_glUnmapBufferARB + typedef GLboolean (APIENTRYP GLEEPFNGLUNMAPBUFFERARBPROC) (GLenum target); + GLEE_EXTERN GLEEPFNGLUNMAPBUFFERARBPROC GLeeFuncPtr_glUnmapBufferARB; + #define glUnmapBufferARB GLeeFuncPtr_glUnmapBufferARB +#endif +#ifndef GLEE_H_DEFINED_glGetBufferParameterivARB +#define GLEE_H_DEFINED_glGetBufferParameterivARB + typedef void (APIENTRYP GLEEPFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETBUFFERPARAMETERIVARBPROC GLeeFuncPtr_glGetBufferParameterivARB; + #define glGetBufferParameterivARB GLeeFuncPtr_glGetBufferParameterivARB +#endif +#ifndef GLEE_H_DEFINED_glGetBufferPointervARB +#define GLEE_H_DEFINED_glGetBufferPointervARB + typedef void (APIENTRYP GLEEPFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid* * params); + GLEE_EXTERN GLEEPFNGLGETBUFFERPOINTERVARBPROC GLeeFuncPtr_glGetBufferPointervARB; + #define glGetBufferPointervARB GLeeFuncPtr_glGetBufferPointervARB +#endif +#endif + +/* GL_ARB_occlusion_query */ + +#ifndef GL_ARB_occlusion_query +#define GL_ARB_occlusion_query 1 +#define __GLEE_GL_ARB_occlusion_query 1 +/* Constants */ +#define GL_QUERY_COUNTER_BITS_ARB 0x8864 +#define GL_CURRENT_QUERY_ARB 0x8865 +#define GL_QUERY_RESULT_ARB 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 +#define GL_SAMPLES_PASSED_ARB 0x8914 +#ifndef GLEE_H_DEFINED_glGenQueriesARB +#define GLEE_H_DEFINED_glGenQueriesARB + typedef void (APIENTRYP GLEEPFNGLGENQUERIESARBPROC) (GLsizei n, GLuint * ids); + GLEE_EXTERN GLEEPFNGLGENQUERIESARBPROC GLeeFuncPtr_glGenQueriesARB; + #define glGenQueriesARB GLeeFuncPtr_glGenQueriesARB +#endif +#ifndef GLEE_H_DEFINED_glDeleteQueriesARB +#define GLEE_H_DEFINED_glDeleteQueriesARB + typedef void (APIENTRYP GLEEPFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint * ids); + GLEE_EXTERN GLEEPFNGLDELETEQUERIESARBPROC GLeeFuncPtr_glDeleteQueriesARB; + #define glDeleteQueriesARB GLeeFuncPtr_glDeleteQueriesARB +#endif +#ifndef GLEE_H_DEFINED_glIsQueryARB +#define GLEE_H_DEFINED_glIsQueryARB + typedef GLboolean (APIENTRYP GLEEPFNGLISQUERYARBPROC) (GLuint id); + GLEE_EXTERN GLEEPFNGLISQUERYARBPROC GLeeFuncPtr_glIsQueryARB; + #define glIsQueryARB GLeeFuncPtr_glIsQueryARB +#endif +#ifndef GLEE_H_DEFINED_glBeginQueryARB +#define GLEE_H_DEFINED_glBeginQueryARB + typedef void (APIENTRYP GLEEPFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id); + GLEE_EXTERN GLEEPFNGLBEGINQUERYARBPROC GLeeFuncPtr_glBeginQueryARB; + #define glBeginQueryARB GLeeFuncPtr_glBeginQueryARB +#endif +#ifndef GLEE_H_DEFINED_glEndQueryARB +#define GLEE_H_DEFINED_glEndQueryARB + typedef void (APIENTRYP GLEEPFNGLENDQUERYARBPROC) (GLenum target); + GLEE_EXTERN GLEEPFNGLENDQUERYARBPROC GLeeFuncPtr_glEndQueryARB; + #define glEndQueryARB GLeeFuncPtr_glEndQueryARB +#endif +#ifndef GLEE_H_DEFINED_glGetQueryivARB +#define GLEE_H_DEFINED_glGetQueryivARB + typedef void (APIENTRYP GLEEPFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETQUERYIVARBPROC GLeeFuncPtr_glGetQueryivARB; + #define glGetQueryivARB GLeeFuncPtr_glGetQueryivARB +#endif +#ifndef GLEE_H_DEFINED_glGetQueryObjectivARB +#define GLEE_H_DEFINED_glGetQueryObjectivARB + typedef void (APIENTRYP GLEEPFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETQUERYOBJECTIVARBPROC GLeeFuncPtr_glGetQueryObjectivARB; + #define glGetQueryObjectivARB GLeeFuncPtr_glGetQueryObjectivARB +#endif +#ifndef GLEE_H_DEFINED_glGetQueryObjectuivARB +#define GLEE_H_DEFINED_glGetQueryObjectuivARB + typedef void (APIENTRYP GLEEPFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint * params); + GLEE_EXTERN GLEEPFNGLGETQUERYOBJECTUIVARBPROC GLeeFuncPtr_glGetQueryObjectuivARB; + #define glGetQueryObjectuivARB GLeeFuncPtr_glGetQueryObjectuivARB +#endif +#endif + +/* GL_ARB_shader_objects */ + +#ifndef GL_ARB_shader_objects +#define GL_ARB_shader_objects 1 +#define __GLEE_GL_ARB_shader_objects 1 +/* Constants */ +#define GL_PROGRAM_OBJECT_ARB 0x8B40 +#define GL_SHADER_OBJECT_ARB 0x8B48 +#define GL_OBJECT_TYPE_ARB 0x8B4E +#define GL_OBJECT_SUBTYPE_ARB 0x8B4F +#define GL_FLOAT_VEC2_ARB 0x8B50 +#define GL_FLOAT_VEC3_ARB 0x8B51 +#define GL_FLOAT_VEC4_ARB 0x8B52 +#define GL_INT_VEC2_ARB 0x8B53 +#define GL_INT_VEC3_ARB 0x8B54 +#define GL_INT_VEC4_ARB 0x8B55 +#define GL_BOOL_ARB 0x8B56 +#define GL_BOOL_VEC2_ARB 0x8B57 +#define GL_BOOL_VEC3_ARB 0x8B58 +#define GL_BOOL_VEC4_ARB 0x8B59 +#define GL_FLOAT_MAT2_ARB 0x8B5A +#define GL_FLOAT_MAT3_ARB 0x8B5B +#define GL_FLOAT_MAT4_ARB 0x8B5C +#define GL_SAMPLER_1D_ARB 0x8B5D +#define GL_SAMPLER_2D_ARB 0x8B5E +#define GL_SAMPLER_3D_ARB 0x8B5F +#define GL_SAMPLER_CUBE_ARB 0x8B60 +#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61 +#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62 +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 +#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80 +#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 +#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 +#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83 +#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 +#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85 +#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86 +#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87 +#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88 +#ifndef GLEE_H_DEFINED_glDeleteObjectARB +#define GLEE_H_DEFINED_glDeleteObjectARB + typedef void (APIENTRYP GLEEPFNGLDELETEOBJECTARBPROC) (GLhandleARB obj); + GLEE_EXTERN GLEEPFNGLDELETEOBJECTARBPROC GLeeFuncPtr_glDeleteObjectARB; + #define glDeleteObjectARB GLeeFuncPtr_glDeleteObjectARB +#endif +#ifndef GLEE_H_DEFINED_glGetHandleARB +#define GLEE_H_DEFINED_glGetHandleARB + typedef GLhandleARB (APIENTRYP GLEEPFNGLGETHANDLEARBPROC) (GLenum pname); + GLEE_EXTERN GLEEPFNGLGETHANDLEARBPROC GLeeFuncPtr_glGetHandleARB; + #define glGetHandleARB GLeeFuncPtr_glGetHandleARB +#endif +#ifndef GLEE_H_DEFINED_glDetachObjectARB +#define GLEE_H_DEFINED_glDetachObjectARB + typedef void (APIENTRYP GLEEPFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj); + GLEE_EXTERN GLEEPFNGLDETACHOBJECTARBPROC GLeeFuncPtr_glDetachObjectARB; + #define glDetachObjectARB GLeeFuncPtr_glDetachObjectARB +#endif +#ifndef GLEE_H_DEFINED_glCreateShaderObjectARB +#define GLEE_H_DEFINED_glCreateShaderObjectARB + typedef GLhandleARB (APIENTRYP GLEEPFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType); + GLEE_EXTERN GLEEPFNGLCREATESHADEROBJECTARBPROC GLeeFuncPtr_glCreateShaderObjectARB; + #define glCreateShaderObjectARB GLeeFuncPtr_glCreateShaderObjectARB +#endif +#ifndef GLEE_H_DEFINED_glShaderSourceARB +#define GLEE_H_DEFINED_glShaderSourceARB + typedef void (APIENTRYP GLEEPFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* * string, const GLint * length); + GLEE_EXTERN GLEEPFNGLSHADERSOURCEARBPROC GLeeFuncPtr_glShaderSourceARB; + #define glShaderSourceARB GLeeFuncPtr_glShaderSourceARB +#endif +#ifndef GLEE_H_DEFINED_glCompileShaderARB +#define GLEE_H_DEFINED_glCompileShaderARB + typedef void (APIENTRYP GLEEPFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj); + GLEE_EXTERN GLEEPFNGLCOMPILESHADERARBPROC GLeeFuncPtr_glCompileShaderARB; + #define glCompileShaderARB GLeeFuncPtr_glCompileShaderARB +#endif +#ifndef GLEE_H_DEFINED_glCreateProgramObjectARB +#define GLEE_H_DEFINED_glCreateProgramObjectARB + typedef GLhandleARB (APIENTRYP GLEEPFNGLCREATEPROGRAMOBJECTARBPROC) (); + GLEE_EXTERN GLEEPFNGLCREATEPROGRAMOBJECTARBPROC GLeeFuncPtr_glCreateProgramObjectARB; + #define glCreateProgramObjectARB GLeeFuncPtr_glCreateProgramObjectARB +#endif +#ifndef GLEE_H_DEFINED_glAttachObjectARB +#define GLEE_H_DEFINED_glAttachObjectARB + typedef void (APIENTRYP GLEEPFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj); + GLEE_EXTERN GLEEPFNGLATTACHOBJECTARBPROC GLeeFuncPtr_glAttachObjectARB; + #define glAttachObjectARB GLeeFuncPtr_glAttachObjectARB +#endif +#ifndef GLEE_H_DEFINED_glLinkProgramARB +#define GLEE_H_DEFINED_glLinkProgramARB + typedef void (APIENTRYP GLEEPFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj); + GLEE_EXTERN GLEEPFNGLLINKPROGRAMARBPROC GLeeFuncPtr_glLinkProgramARB; + #define glLinkProgramARB GLeeFuncPtr_glLinkProgramARB +#endif +#ifndef GLEE_H_DEFINED_glUseProgramObjectARB +#define GLEE_H_DEFINED_glUseProgramObjectARB + typedef void (APIENTRYP GLEEPFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj); + GLEE_EXTERN GLEEPFNGLUSEPROGRAMOBJECTARBPROC GLeeFuncPtr_glUseProgramObjectARB; + #define glUseProgramObjectARB GLeeFuncPtr_glUseProgramObjectARB +#endif +#ifndef GLEE_H_DEFINED_glValidateProgramARB +#define GLEE_H_DEFINED_glValidateProgramARB + typedef void (APIENTRYP GLEEPFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj); + GLEE_EXTERN GLEEPFNGLVALIDATEPROGRAMARBPROC GLeeFuncPtr_glValidateProgramARB; + #define glValidateProgramARB GLeeFuncPtr_glValidateProgramARB +#endif +#ifndef GLEE_H_DEFINED_glUniform1fARB +#define GLEE_H_DEFINED_glUniform1fARB + typedef void (APIENTRYP GLEEPFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0); + GLEE_EXTERN GLEEPFNGLUNIFORM1FARBPROC GLeeFuncPtr_glUniform1fARB; + #define glUniform1fARB GLeeFuncPtr_glUniform1fARB +#endif +#ifndef GLEE_H_DEFINED_glUniform2fARB +#define GLEE_H_DEFINED_glUniform2fARB + typedef void (APIENTRYP GLEEPFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1); + GLEE_EXTERN GLEEPFNGLUNIFORM2FARBPROC GLeeFuncPtr_glUniform2fARB; + #define glUniform2fARB GLeeFuncPtr_glUniform2fARB +#endif +#ifndef GLEE_H_DEFINED_glUniform3fARB +#define GLEE_H_DEFINED_glUniform3fARB + typedef void (APIENTRYP GLEEPFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); + GLEE_EXTERN GLEEPFNGLUNIFORM3FARBPROC GLeeFuncPtr_glUniform3fARB; + #define glUniform3fARB GLeeFuncPtr_glUniform3fARB +#endif +#ifndef GLEE_H_DEFINED_glUniform4fARB +#define GLEE_H_DEFINED_glUniform4fARB + typedef void (APIENTRYP GLEEPFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); + GLEE_EXTERN GLEEPFNGLUNIFORM4FARBPROC GLeeFuncPtr_glUniform4fARB; + #define glUniform4fARB GLeeFuncPtr_glUniform4fARB +#endif +#ifndef GLEE_H_DEFINED_glUniform1iARB +#define GLEE_H_DEFINED_glUniform1iARB + typedef void (APIENTRYP GLEEPFNGLUNIFORM1IARBPROC) (GLint location, GLint v0); + GLEE_EXTERN GLEEPFNGLUNIFORM1IARBPROC GLeeFuncPtr_glUniform1iARB; + #define glUniform1iARB GLeeFuncPtr_glUniform1iARB +#endif +#ifndef GLEE_H_DEFINED_glUniform2iARB +#define GLEE_H_DEFINED_glUniform2iARB + typedef void (APIENTRYP GLEEPFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1); + GLEE_EXTERN GLEEPFNGLUNIFORM2IARBPROC GLeeFuncPtr_glUniform2iARB; + #define glUniform2iARB GLeeFuncPtr_glUniform2iARB +#endif +#ifndef GLEE_H_DEFINED_glUniform3iARB +#define GLEE_H_DEFINED_glUniform3iARB + typedef void (APIENTRYP GLEEPFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2); + GLEE_EXTERN GLEEPFNGLUNIFORM3IARBPROC GLeeFuncPtr_glUniform3iARB; + #define glUniform3iARB GLeeFuncPtr_glUniform3iARB +#endif +#ifndef GLEE_H_DEFINED_glUniform4iARB +#define GLEE_H_DEFINED_glUniform4iARB + typedef void (APIENTRYP GLEEPFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); + GLEE_EXTERN GLEEPFNGLUNIFORM4IARBPROC GLeeFuncPtr_glUniform4iARB; + #define glUniform4iARB GLeeFuncPtr_glUniform4iARB +#endif +#ifndef GLEE_H_DEFINED_glUniform1fvARB +#define GLEE_H_DEFINED_glUniform1fvARB + typedef void (APIENTRYP GLEEPFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORM1FVARBPROC GLeeFuncPtr_glUniform1fvARB; + #define glUniform1fvARB GLeeFuncPtr_glUniform1fvARB +#endif +#ifndef GLEE_H_DEFINED_glUniform2fvARB +#define GLEE_H_DEFINED_glUniform2fvARB + typedef void (APIENTRYP GLEEPFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORM2FVARBPROC GLeeFuncPtr_glUniform2fvARB; + #define glUniform2fvARB GLeeFuncPtr_glUniform2fvARB +#endif +#ifndef GLEE_H_DEFINED_glUniform3fvARB +#define GLEE_H_DEFINED_glUniform3fvARB + typedef void (APIENTRYP GLEEPFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORM3FVARBPROC GLeeFuncPtr_glUniform3fvARB; + #define glUniform3fvARB GLeeFuncPtr_glUniform3fvARB +#endif +#ifndef GLEE_H_DEFINED_glUniform4fvARB +#define GLEE_H_DEFINED_glUniform4fvARB + typedef void (APIENTRYP GLEEPFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORM4FVARBPROC GLeeFuncPtr_glUniform4fvARB; + #define glUniform4fvARB GLeeFuncPtr_glUniform4fvARB +#endif +#ifndef GLEE_H_DEFINED_glUniform1ivARB +#define GLEE_H_DEFINED_glUniform1ivARB + typedef void (APIENTRYP GLEEPFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint * value); + GLEE_EXTERN GLEEPFNGLUNIFORM1IVARBPROC GLeeFuncPtr_glUniform1ivARB; + #define glUniform1ivARB GLeeFuncPtr_glUniform1ivARB +#endif +#ifndef GLEE_H_DEFINED_glUniform2ivARB +#define GLEE_H_DEFINED_glUniform2ivARB + typedef void (APIENTRYP GLEEPFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint * value); + GLEE_EXTERN GLEEPFNGLUNIFORM2IVARBPROC GLeeFuncPtr_glUniform2ivARB; + #define glUniform2ivARB GLeeFuncPtr_glUniform2ivARB +#endif +#ifndef GLEE_H_DEFINED_glUniform3ivARB +#define GLEE_H_DEFINED_glUniform3ivARB + typedef void (APIENTRYP GLEEPFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint * value); + GLEE_EXTERN GLEEPFNGLUNIFORM3IVARBPROC GLeeFuncPtr_glUniform3ivARB; + #define glUniform3ivARB GLeeFuncPtr_glUniform3ivARB +#endif +#ifndef GLEE_H_DEFINED_glUniform4ivARB +#define GLEE_H_DEFINED_glUniform4ivARB + typedef void (APIENTRYP GLEEPFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint * value); + GLEE_EXTERN GLEEPFNGLUNIFORM4IVARBPROC GLeeFuncPtr_glUniform4ivARB; + #define glUniform4ivARB GLeeFuncPtr_glUniform4ivARB +#endif +#ifndef GLEE_H_DEFINED_glUniformMatrix2fvARB +#define GLEE_H_DEFINED_glUniformMatrix2fvARB + typedef void (APIENTRYP GLEEPFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORMMATRIX2FVARBPROC GLeeFuncPtr_glUniformMatrix2fvARB; + #define glUniformMatrix2fvARB GLeeFuncPtr_glUniformMatrix2fvARB +#endif +#ifndef GLEE_H_DEFINED_glUniformMatrix3fvARB +#define GLEE_H_DEFINED_glUniformMatrix3fvARB + typedef void (APIENTRYP GLEEPFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORMMATRIX3FVARBPROC GLeeFuncPtr_glUniformMatrix3fvARB; + #define glUniformMatrix3fvARB GLeeFuncPtr_glUniformMatrix3fvARB +#endif +#ifndef GLEE_H_DEFINED_glUniformMatrix4fvARB +#define GLEE_H_DEFINED_glUniformMatrix4fvARB + typedef void (APIENTRYP GLEEPFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLUNIFORMMATRIX4FVARBPROC GLeeFuncPtr_glUniformMatrix4fvARB; + #define glUniformMatrix4fvARB GLeeFuncPtr_glUniformMatrix4fvARB +#endif +#ifndef GLEE_H_DEFINED_glGetObjectParameterfvARB +#define GLEE_H_DEFINED_glGetObjectParameterfvARB + typedef void (APIENTRYP GLEEPFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETOBJECTPARAMETERFVARBPROC GLeeFuncPtr_glGetObjectParameterfvARB; + #define glGetObjectParameterfvARB GLeeFuncPtr_glGetObjectParameterfvARB +#endif +#ifndef GLEE_H_DEFINED_glGetObjectParameterivARB +#define GLEE_H_DEFINED_glGetObjectParameterivARB + typedef void (APIENTRYP GLEEPFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETOBJECTPARAMETERIVARBPROC GLeeFuncPtr_glGetObjectParameterivARB; + #define glGetObjectParameterivARB GLeeFuncPtr_glGetObjectParameterivARB +#endif +#ifndef GLEE_H_DEFINED_glGetInfoLogARB +#define GLEE_H_DEFINED_glGetInfoLogARB + typedef void (APIENTRYP GLEEPFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog); + GLEE_EXTERN GLEEPFNGLGETINFOLOGARBPROC GLeeFuncPtr_glGetInfoLogARB; + #define glGetInfoLogARB GLeeFuncPtr_glGetInfoLogARB +#endif +#ifndef GLEE_H_DEFINED_glGetAttachedObjectsARB +#define GLEE_H_DEFINED_glGetAttachedObjectsARB + typedef void (APIENTRYP GLEEPFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei * count, GLhandleARB * obj); + GLEE_EXTERN GLEEPFNGLGETATTACHEDOBJECTSARBPROC GLeeFuncPtr_glGetAttachedObjectsARB; + #define glGetAttachedObjectsARB GLeeFuncPtr_glGetAttachedObjectsARB +#endif +#ifndef GLEE_H_DEFINED_glGetUniformLocationARB +#define GLEE_H_DEFINED_glGetUniformLocationARB + typedef GLint (APIENTRYP GLEEPFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB * name); + GLEE_EXTERN GLEEPFNGLGETUNIFORMLOCATIONARBPROC GLeeFuncPtr_glGetUniformLocationARB; + #define glGetUniformLocationARB GLeeFuncPtr_glGetUniformLocationARB +#endif +#ifndef GLEE_H_DEFINED_glGetActiveUniformARB +#define GLEE_H_DEFINED_glGetActiveUniformARB + typedef void (APIENTRYP GLEEPFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length, GLint * size, GLenum * type, GLcharARB * name); + GLEE_EXTERN GLEEPFNGLGETACTIVEUNIFORMARBPROC GLeeFuncPtr_glGetActiveUniformARB; + #define glGetActiveUniformARB GLeeFuncPtr_glGetActiveUniformARB +#endif +#ifndef GLEE_H_DEFINED_glGetUniformfvARB +#define GLEE_H_DEFINED_glGetUniformfvARB + typedef void (APIENTRYP GLEEPFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETUNIFORMFVARBPROC GLeeFuncPtr_glGetUniformfvARB; + #define glGetUniformfvARB GLeeFuncPtr_glGetUniformfvARB +#endif +#ifndef GLEE_H_DEFINED_glGetUniformivARB +#define GLEE_H_DEFINED_glGetUniformivARB + typedef void (APIENTRYP GLEEPFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint * params); + GLEE_EXTERN GLEEPFNGLGETUNIFORMIVARBPROC GLeeFuncPtr_glGetUniformivARB; + #define glGetUniformivARB GLeeFuncPtr_glGetUniformivARB +#endif +#ifndef GLEE_H_DEFINED_glGetShaderSourceARB +#define GLEE_H_DEFINED_glGetShaderSourceARB + typedef void (APIENTRYP GLEEPFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * source); + GLEE_EXTERN GLEEPFNGLGETSHADERSOURCEARBPROC GLeeFuncPtr_glGetShaderSourceARB; + #define glGetShaderSourceARB GLeeFuncPtr_glGetShaderSourceARB +#endif +#endif + +/* GL_ARB_vertex_shader */ + +#ifndef GL_ARB_vertex_shader +#define GL_ARB_vertex_shader 1 +#define __GLEE_GL_ARB_vertex_shader 1 +/* Constants */ +#define GL_VERTEX_SHADER_ARB 0x8B31 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A +#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D +#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89 +#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A +#ifndef GLEE_H_DEFINED_glBindAttribLocationARB +#define GLEE_H_DEFINED_glBindAttribLocationARB + typedef void (APIENTRYP GLEEPFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB * name); + GLEE_EXTERN GLEEPFNGLBINDATTRIBLOCATIONARBPROC GLeeFuncPtr_glBindAttribLocationARB; + #define glBindAttribLocationARB GLeeFuncPtr_glBindAttribLocationARB +#endif +#ifndef GLEE_H_DEFINED_glGetActiveAttribARB +#define GLEE_H_DEFINED_glGetActiveAttribARB + typedef void (APIENTRYP GLEEPFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length, GLint * size, GLenum * type, GLcharARB * name); + GLEE_EXTERN GLEEPFNGLGETACTIVEATTRIBARBPROC GLeeFuncPtr_glGetActiveAttribARB; + #define glGetActiveAttribARB GLeeFuncPtr_glGetActiveAttribARB +#endif +#ifndef GLEE_H_DEFINED_glGetAttribLocationARB +#define GLEE_H_DEFINED_glGetAttribLocationARB + typedef GLint (APIENTRYP GLEEPFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB * name); + GLEE_EXTERN GLEEPFNGLGETATTRIBLOCATIONARBPROC GLeeFuncPtr_glGetAttribLocationARB; + #define glGetAttribLocationARB GLeeFuncPtr_glGetAttribLocationARB +#endif +#endif + +/* GL_ARB_fragment_shader */ + +#ifndef GL_ARB_fragment_shader +#define GL_ARB_fragment_shader 1 +#define __GLEE_GL_ARB_fragment_shader 1 +/* Constants */ +#define GL_FRAGMENT_SHADER_ARB 0x8B30 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B +#endif + +/* GL_ARB_shading_language_100 */ + +#ifndef GL_ARB_shading_language_100 +#define GL_ARB_shading_language_100 1 +#define __GLEE_GL_ARB_shading_language_100 1 +/* Constants */ +#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C +#endif + +/* GL_ARB_texture_non_power_of_two */ + +#ifndef GL_ARB_texture_non_power_of_two +#define GL_ARB_texture_non_power_of_two 1 +#define __GLEE_GL_ARB_texture_non_power_of_two 1 +/* Constants */ +#endif + +/* GL_ARB_point_sprite */ + +#ifndef GL_ARB_point_sprite +#define GL_ARB_point_sprite 1 +#define __GLEE_GL_ARB_point_sprite 1 +/* Constants */ +#define GL_POINT_SPRITE_ARB 0x8861 +#define GL_COORD_REPLACE_ARB 0x8862 +#endif + +/* GL_ARB_fragment_program_shadow */ + +#ifndef GL_ARB_fragment_program_shadow +#define GL_ARB_fragment_program_shadow 1 +#define __GLEE_GL_ARB_fragment_program_shadow 1 +/* Constants */ +#endif + +/* GL_ARB_draw_buffers */ + +#ifndef GL_ARB_draw_buffers +#define GL_ARB_draw_buffers 1 +#define __GLEE_GL_ARB_draw_buffers 1 +/* Constants */ +#define GL_MAX_DRAW_BUFFERS_ARB 0x8824 +#define GL_DRAW_BUFFER0_ARB 0x8825 +#define GL_DRAW_BUFFER1_ARB 0x8826 +#define GL_DRAW_BUFFER2_ARB 0x8827 +#define GL_DRAW_BUFFER3_ARB 0x8828 +#define GL_DRAW_BUFFER4_ARB 0x8829 +#define GL_DRAW_BUFFER5_ARB 0x882A +#define GL_DRAW_BUFFER6_ARB 0x882B +#define GL_DRAW_BUFFER7_ARB 0x882C +#define GL_DRAW_BUFFER8_ARB 0x882D +#define GL_DRAW_BUFFER9_ARB 0x882E +#define GL_DRAW_BUFFER10_ARB 0x882F +#define GL_DRAW_BUFFER11_ARB 0x8830 +#define GL_DRAW_BUFFER12_ARB 0x8831 +#define GL_DRAW_BUFFER13_ARB 0x8832 +#define GL_DRAW_BUFFER14_ARB 0x8833 +#define GL_DRAW_BUFFER15_ARB 0x8834 +#ifndef GLEE_H_DEFINED_glDrawBuffersARB +#define GLEE_H_DEFINED_glDrawBuffersARB + typedef void (APIENTRYP GLEEPFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum * bufs); + GLEE_EXTERN GLEEPFNGLDRAWBUFFERSARBPROC GLeeFuncPtr_glDrawBuffersARB; + #define glDrawBuffersARB GLeeFuncPtr_glDrawBuffersARB +#endif +#endif + +/* GL_ARB_texture_rectangle */ + +#ifndef GL_ARB_texture_rectangle +#define GL_ARB_texture_rectangle 1 +#define __GLEE_GL_ARB_texture_rectangle 1 +/* Constants */ +#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 +#endif + +/* GL_ARB_color_buffer_float */ + +#ifndef GL_ARB_color_buffer_float +#define GL_ARB_color_buffer_float 1 +#define __GLEE_GL_ARB_color_buffer_float 1 +/* Constants */ +#define GL_RGBA_FLOAT_MODE_ARB 0x8820 +#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A +#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B +#define GL_CLAMP_READ_COLOR_ARB 0x891C +#define GL_FIXED_ONLY_ARB 0x891D +#ifndef GLEE_H_DEFINED_glClampColorARB +#define GLEE_H_DEFINED_glClampColorARB + typedef void (APIENTRYP GLEEPFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp); + GLEE_EXTERN GLEEPFNGLCLAMPCOLORARBPROC GLeeFuncPtr_glClampColorARB; + #define glClampColorARB GLeeFuncPtr_glClampColorARB +#endif +#endif + +/* GL_ARB_half_float_pixel */ + +#ifndef GL_ARB_half_float_pixel +#define GL_ARB_half_float_pixel 1 +#define __GLEE_GL_ARB_half_float_pixel 1 +/* Constants */ +#define GL_HALF_FLOAT_ARB 0x140B +#endif + +/* GL_ARB_texture_float */ + +#ifndef GL_ARB_texture_float +#define GL_ARB_texture_float 1 +#define __GLEE_GL_ARB_texture_float 1 +/* Constants */ +#define GL_TEXTURE_RED_TYPE_ARB 0x8C10 +#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11 +#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13 +#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14 +#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15 +#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16 +#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17 +#define GL_RGBA32F_ARB 0x8814 +#define GL_RGB32F_ARB 0x8815 +#define GL_ALPHA32F_ARB 0x8816 +#define GL_INTENSITY32F_ARB 0x8817 +#define GL_LUMINANCE32F_ARB 0x8818 +#define GL_LUMINANCE_ALPHA32F_ARB 0x8819 +#define GL_RGBA16F_ARB 0x881A +#define GL_RGB16F_ARB 0x881B +#define GL_ALPHA16F_ARB 0x881C +#define GL_INTENSITY16F_ARB 0x881D +#define GL_LUMINANCE16F_ARB 0x881E +#define GL_LUMINANCE_ALPHA16F_ARB 0x881F +#endif + +/* GL_ARB_pixel_buffer_object */ + +#ifndef GL_ARB_pixel_buffer_object +#define GL_ARB_pixel_buffer_object 1 +#define __GLEE_GL_ARB_pixel_buffer_object 1 +/* Constants */ +#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF +#endif + +/* GL_ARB_depth_buffer_float */ + +#ifndef GL_ARB_depth_buffer_float +#define GL_ARB_depth_buffer_float 1 +#define __GLEE_GL_ARB_depth_buffer_float 1 +/* Constants */ +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#endif + +/* GL_ARB_draw_instanced */ + +#ifndef GL_ARB_draw_instanced +#define GL_ARB_draw_instanced 1 +#define __GLEE_GL_ARB_draw_instanced 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glDrawArraysInstancedARB +#define GLEE_H_DEFINED_glDrawArraysInstancedARB + typedef void (APIENTRYP GLEEPFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); + GLEE_EXTERN GLEEPFNGLDRAWARRAYSINSTANCEDARBPROC GLeeFuncPtr_glDrawArraysInstancedARB; + #define glDrawArraysInstancedARB GLeeFuncPtr_glDrawArraysInstancedARB +#endif +#ifndef GLEE_H_DEFINED_glDrawElementsInstancedARB +#define GLEE_H_DEFINED_glDrawElementsInstancedARB + typedef void (APIENTRYP GLEEPFNGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid * indices, GLsizei primcount); + GLEE_EXTERN GLEEPFNGLDRAWELEMENTSINSTANCEDARBPROC GLeeFuncPtr_glDrawElementsInstancedARB; + #define glDrawElementsInstancedARB GLeeFuncPtr_glDrawElementsInstancedARB +#endif +#endif + +/* GL_ARB_framebuffer_object */ + +#ifndef GL_ARB_framebuffer_object +#define GL_ARB_framebuffer_object 1 +#define __GLEE_GL_ARB_framebuffer_object 1 +/* Constants */ +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_INDEX 0x8222 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_DRAW_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_STENCIL_INDEX1 0x8D46 +#define GL_STENCIL_INDEX4 0x8D47 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_STENCIL_INDEX16 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 +#ifndef GLEE_H_DEFINED_glIsRenderbuffer +#define GLEE_H_DEFINED_glIsRenderbuffer + typedef GLboolean (APIENTRYP GLEEPFNGLISRENDERBUFFERPROC) (GLuint renderbuffer); + GLEE_EXTERN GLEEPFNGLISRENDERBUFFERPROC GLeeFuncPtr_glIsRenderbuffer; + #define glIsRenderbuffer GLeeFuncPtr_glIsRenderbuffer +#endif +#ifndef GLEE_H_DEFINED_glBindRenderbuffer +#define GLEE_H_DEFINED_glBindRenderbuffer + typedef void (APIENTRYP GLEEPFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer); + GLEE_EXTERN GLEEPFNGLBINDRENDERBUFFERPROC GLeeFuncPtr_glBindRenderbuffer; + #define glBindRenderbuffer GLeeFuncPtr_glBindRenderbuffer +#endif +#ifndef GLEE_H_DEFINED_glDeleteRenderbuffers +#define GLEE_H_DEFINED_glDeleteRenderbuffers + typedef void (APIENTRYP GLEEPFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint * renderbuffers); + GLEE_EXTERN GLEEPFNGLDELETERENDERBUFFERSPROC GLeeFuncPtr_glDeleteRenderbuffers; + #define glDeleteRenderbuffers GLeeFuncPtr_glDeleteRenderbuffers +#endif +#ifndef GLEE_H_DEFINED_glGenRenderbuffers +#define GLEE_H_DEFINED_glGenRenderbuffers + typedef void (APIENTRYP GLEEPFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint * renderbuffers); + GLEE_EXTERN GLEEPFNGLGENRENDERBUFFERSPROC GLeeFuncPtr_glGenRenderbuffers; + #define glGenRenderbuffers GLeeFuncPtr_glGenRenderbuffers +#endif +#ifndef GLEE_H_DEFINED_glRenderbufferStorage +#define GLEE_H_DEFINED_glRenderbufferStorage + typedef void (APIENTRYP GLEEPFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLRENDERBUFFERSTORAGEPROC GLeeFuncPtr_glRenderbufferStorage; + #define glRenderbufferStorage GLeeFuncPtr_glRenderbufferStorage +#endif +#ifndef GLEE_H_DEFINED_glGetRenderbufferParameteriv +#define GLEE_H_DEFINED_glGetRenderbufferParameteriv + typedef void (APIENTRYP GLEEPFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETRENDERBUFFERPARAMETERIVPROC GLeeFuncPtr_glGetRenderbufferParameteriv; + #define glGetRenderbufferParameteriv GLeeFuncPtr_glGetRenderbufferParameteriv +#endif +#ifndef GLEE_H_DEFINED_glIsFramebuffer +#define GLEE_H_DEFINED_glIsFramebuffer + typedef GLboolean (APIENTRYP GLEEPFNGLISFRAMEBUFFERPROC) (GLuint framebuffer); + GLEE_EXTERN GLEEPFNGLISFRAMEBUFFERPROC GLeeFuncPtr_glIsFramebuffer; + #define glIsFramebuffer GLeeFuncPtr_glIsFramebuffer +#endif +#ifndef GLEE_H_DEFINED_glBindFramebuffer +#define GLEE_H_DEFINED_glBindFramebuffer + typedef void (APIENTRYP GLEEPFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer); + GLEE_EXTERN GLEEPFNGLBINDFRAMEBUFFERPROC GLeeFuncPtr_glBindFramebuffer; + #define glBindFramebuffer GLeeFuncPtr_glBindFramebuffer +#endif +#ifndef GLEE_H_DEFINED_glDeleteFramebuffers +#define GLEE_H_DEFINED_glDeleteFramebuffers + typedef void (APIENTRYP GLEEPFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint * framebuffers); + GLEE_EXTERN GLEEPFNGLDELETEFRAMEBUFFERSPROC GLeeFuncPtr_glDeleteFramebuffers; + #define glDeleteFramebuffers GLeeFuncPtr_glDeleteFramebuffers +#endif +#ifndef GLEE_H_DEFINED_glGenFramebuffers +#define GLEE_H_DEFINED_glGenFramebuffers + typedef void (APIENTRYP GLEEPFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint * framebuffers); + GLEE_EXTERN GLEEPFNGLGENFRAMEBUFFERSPROC GLeeFuncPtr_glGenFramebuffers; + #define glGenFramebuffers GLeeFuncPtr_glGenFramebuffers +#endif +#ifndef GLEE_H_DEFINED_glCheckFramebufferStatus +#define GLEE_H_DEFINED_glCheckFramebufferStatus + typedef GLenum (APIENTRYP GLEEPFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target); + GLEE_EXTERN GLEEPFNGLCHECKFRAMEBUFFERSTATUSPROC GLeeFuncPtr_glCheckFramebufferStatus; + #define glCheckFramebufferStatus GLeeFuncPtr_glCheckFramebufferStatus +#endif +#ifndef GLEE_H_DEFINED_glFramebufferTexture1D +#define GLEE_H_DEFINED_glFramebufferTexture1D + typedef void (APIENTRYP GLEEPFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERTEXTURE1DPROC GLeeFuncPtr_glFramebufferTexture1D; + #define glFramebufferTexture1D GLeeFuncPtr_glFramebufferTexture1D +#endif +#ifndef GLEE_H_DEFINED_glFramebufferTexture2D +#define GLEE_H_DEFINED_glFramebufferTexture2D + typedef void (APIENTRYP GLEEPFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERTEXTURE2DPROC GLeeFuncPtr_glFramebufferTexture2D; + #define glFramebufferTexture2D GLeeFuncPtr_glFramebufferTexture2D +#endif +#ifndef GLEE_H_DEFINED_glFramebufferTexture3D +#define GLEE_H_DEFINED_glFramebufferTexture3D + typedef void (APIENTRYP GLEEPFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERTEXTURE3DPROC GLeeFuncPtr_glFramebufferTexture3D; + #define glFramebufferTexture3D GLeeFuncPtr_glFramebufferTexture3D +#endif +#ifndef GLEE_H_DEFINED_glFramebufferRenderbuffer +#define GLEE_H_DEFINED_glFramebufferRenderbuffer + typedef void (APIENTRYP GLEEPFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERRENDERBUFFERPROC GLeeFuncPtr_glFramebufferRenderbuffer; + #define glFramebufferRenderbuffer GLeeFuncPtr_glFramebufferRenderbuffer +#endif +#ifndef GLEE_H_DEFINED_glGetFramebufferAttachmentParameteriv +#define GLEE_H_DEFINED_glGetFramebufferAttachmentParameteriv + typedef void (APIENTRYP GLEEPFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC GLeeFuncPtr_glGetFramebufferAttachmentParameteriv; + #define glGetFramebufferAttachmentParameteriv GLeeFuncPtr_glGetFramebufferAttachmentParameteriv +#endif +#ifndef GLEE_H_DEFINED_glGenerateMipmap +#define GLEE_H_DEFINED_glGenerateMipmap + typedef void (APIENTRYP GLEEPFNGLGENERATEMIPMAPPROC) (GLenum target); + GLEE_EXTERN GLEEPFNGLGENERATEMIPMAPPROC GLeeFuncPtr_glGenerateMipmap; + #define glGenerateMipmap GLeeFuncPtr_glGenerateMipmap +#endif +#ifndef GLEE_H_DEFINED_glBlitFramebuffer +#define GLEE_H_DEFINED_glBlitFramebuffer + typedef void (APIENTRYP GLEEPFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + GLEE_EXTERN GLEEPFNGLBLITFRAMEBUFFERPROC GLeeFuncPtr_glBlitFramebuffer; + #define glBlitFramebuffer GLeeFuncPtr_glBlitFramebuffer +#endif +#ifndef GLEE_H_DEFINED_glRenderbufferStorageMultisample +#define GLEE_H_DEFINED_glRenderbufferStorageMultisample + typedef void (APIENTRYP GLEEPFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC GLeeFuncPtr_glRenderbufferStorageMultisample; + #define glRenderbufferStorageMultisample GLeeFuncPtr_glRenderbufferStorageMultisample +#endif +#ifndef GLEE_H_DEFINED_glFramebufferTextureLayer +#define GLEE_H_DEFINED_glFramebufferTextureLayer + typedef void (APIENTRYP GLEEPFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERTEXTURELAYERPROC GLeeFuncPtr_glFramebufferTextureLayer; + #define glFramebufferTextureLayer GLeeFuncPtr_glFramebufferTextureLayer +#endif +#endif + +/* GL_ARB_framebuffer_sRGB */ + +#ifndef GL_ARB_framebuffer_sRGB +#define GL_ARB_framebuffer_sRGB 1 +#define __GLEE_GL_ARB_framebuffer_sRGB 1 +/* Constants */ +#define GL_FRAMEBUFFER_SRGB 0x8DB9 +#endif + +/* GL_ARB_geometry_shader4 */ + +#ifndef GL_ARB_geometry_shader4 +#define GL_ARB_geometry_shader4 1 +#define __GLEE_GL_ARB_geometry_shader4 1 +/* Constants */ +#define GL_LINES_ADJACENCY_ARB 0x000A +#define GL_LINE_STRIP_ADJACENCY_ARB 0x000B +#define GL_TRIANGLES_ADJACENCY_ARB 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0x000D +#define GL_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9 +#define GL_GEOMETRY_SHADER_ARB 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA +#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD +#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1 +#ifndef GLEE_H_DEFINED_glProgramParameteriARB +#define GLEE_H_DEFINED_glProgramParameteriARB + typedef void (APIENTRYP GLEEPFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value); + GLEE_EXTERN GLEEPFNGLPROGRAMPARAMETERIARBPROC GLeeFuncPtr_glProgramParameteriARB; + #define glProgramParameteriARB GLeeFuncPtr_glProgramParameteriARB +#endif +#ifndef GLEE_H_DEFINED_glFramebufferTextureARB +#define GLEE_H_DEFINED_glFramebufferTextureARB + typedef void (APIENTRYP GLEEPFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERTEXTUREARBPROC GLeeFuncPtr_glFramebufferTextureARB; + #define glFramebufferTextureARB GLeeFuncPtr_glFramebufferTextureARB +#endif +#ifndef GLEE_H_DEFINED_glFramebufferTextureLayerARB +#define GLEE_H_DEFINED_glFramebufferTextureLayerARB + typedef void (APIENTRYP GLEEPFNGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERTEXTURELAYERARBPROC GLeeFuncPtr_glFramebufferTextureLayerARB; + #define glFramebufferTextureLayerARB GLeeFuncPtr_glFramebufferTextureLayerARB +#endif +#ifndef GLEE_H_DEFINED_glFramebufferTextureFaceARB +#define GLEE_H_DEFINED_glFramebufferTextureFaceARB + typedef void (APIENTRYP GLEEPFNGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERTEXTUREFACEARBPROC GLeeFuncPtr_glFramebufferTextureFaceARB; + #define glFramebufferTextureFaceARB GLeeFuncPtr_glFramebufferTextureFaceARB +#endif +#endif + +/* GL_ARB_half_float_vertex */ + +#ifndef GL_ARB_half_float_vertex +#define GL_ARB_half_float_vertex 1 +#define __GLEE_GL_ARB_half_float_vertex 1 +/* Constants */ +#define GL_HALF_FLOAT 0x140B +#endif + +/* GL_ARB_instanced_arrays */ + +#ifndef GL_ARB_instanced_arrays +#define GL_ARB_instanced_arrays 1 +#define __GLEE_GL_ARB_instanced_arrays 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glVertexAttribDivisor +#define GLEE_H_DEFINED_glVertexAttribDivisor + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBDIVISORPROC GLeeFuncPtr_glVertexAttribDivisor; + #define glVertexAttribDivisor GLeeFuncPtr_glVertexAttribDivisor +#endif +#endif + +/* GL_ARB_map_buffer_range */ + +#ifndef GL_ARB_map_buffer_range +#define GL_ARB_map_buffer_range 1 +#define __GLEE_GL_ARB_map_buffer_range 1 +/* Constants */ +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#ifndef GLEE_H_DEFINED_glMapBufferRange +#define GLEE_H_DEFINED_glMapBufferRange + typedef void (APIENTRYP GLEEPFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); + GLEE_EXTERN GLEEPFNGLMAPBUFFERRANGEPROC GLeeFuncPtr_glMapBufferRange; + #define glMapBufferRange GLeeFuncPtr_glMapBufferRange +#endif +#ifndef GLEE_H_DEFINED_glFlushMappedBufferRange +#define GLEE_H_DEFINED_glFlushMappedBufferRange + typedef void (APIENTRYP GLEEPFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length); + GLEE_EXTERN GLEEPFNGLFLUSHMAPPEDBUFFERRANGEPROC GLeeFuncPtr_glFlushMappedBufferRange; + #define glFlushMappedBufferRange GLeeFuncPtr_glFlushMappedBufferRange +#endif +#endif + +/* GL_ARB_texture_buffer_object */ + +#ifndef GL_ARB_texture_buffer_object +#define GL_ARB_texture_buffer_object 1 +#define __GLEE_GL_ARB_texture_buffer_object 1 +/* Constants */ +#define GL_TEXTURE_BUFFER_ARB 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E +#ifndef GLEE_H_DEFINED_glTexBufferARB +#define GLEE_H_DEFINED_glTexBufferARB + typedef void (APIENTRYP GLEEPFNGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer); + GLEE_EXTERN GLEEPFNGLTEXBUFFERARBPROC GLeeFuncPtr_glTexBufferARB; + #define glTexBufferARB GLeeFuncPtr_glTexBufferARB +#endif +#endif + +/* GL_ARB_texture_compression_rgtc */ + +#ifndef GL_ARB_texture_compression_rgtc +#define GL_ARB_texture_compression_rgtc 1 +#define __GLEE_GL_ARB_texture_compression_rgtc 1 +/* Constants */ +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE +#endif + +/* GL_ARB_texture_rg */ + +#ifndef GL_ARB_texture_rg +#define GL_ARB_texture_rg 1 +#define __GLEE_GL_ARB_texture_rg 1 +/* Constants */ +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_R16 0x822A +#define GL_RG8 0x822B +#define GL_RG16 0x822C +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#endif + +/* GL_ARB_vertex_array_object */ + +#ifndef GL_ARB_vertex_array_object +#define GL_ARB_vertex_array_object 1 +#define __GLEE_GL_ARB_vertex_array_object 1 +/* Constants */ +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#ifndef GLEE_H_DEFINED_glBindVertexArray +#define GLEE_H_DEFINED_glBindVertexArray + typedef void (APIENTRYP GLEEPFNGLBINDVERTEXARRAYPROC) (GLuint array); + GLEE_EXTERN GLEEPFNGLBINDVERTEXARRAYPROC GLeeFuncPtr_glBindVertexArray; + #define glBindVertexArray GLeeFuncPtr_glBindVertexArray +#endif +#ifndef GLEE_H_DEFINED_glDeleteVertexArrays +#define GLEE_H_DEFINED_glDeleteVertexArrays + typedef void (APIENTRYP GLEEPFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint * arrays); + GLEE_EXTERN GLEEPFNGLDELETEVERTEXARRAYSPROC GLeeFuncPtr_glDeleteVertexArrays; + #define glDeleteVertexArrays GLeeFuncPtr_glDeleteVertexArrays +#endif +#ifndef GLEE_H_DEFINED_glGenVertexArrays +#define GLEE_H_DEFINED_glGenVertexArrays + typedef void (APIENTRYP GLEEPFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint * arrays); + GLEE_EXTERN GLEEPFNGLGENVERTEXARRAYSPROC GLeeFuncPtr_glGenVertexArrays; + #define glGenVertexArrays GLeeFuncPtr_glGenVertexArrays +#endif +#ifndef GLEE_H_DEFINED_glIsVertexArray +#define GLEE_H_DEFINED_glIsVertexArray + typedef GLboolean (APIENTRYP GLEEPFNGLISVERTEXARRAYPROC) (GLuint array); + GLEE_EXTERN GLEEPFNGLISVERTEXARRAYPROC GLeeFuncPtr_glIsVertexArray; + #define glIsVertexArray GLeeFuncPtr_glIsVertexArray +#endif +#endif + +/* GL_EXT_abgr */ + +#ifndef GL_EXT_abgr +#define GL_EXT_abgr 1 +#define __GLEE_GL_EXT_abgr 1 +/* Constants */ +#define GL_ABGR_EXT 0x8000 +#endif + +/* GL_EXT_blend_color */ + +#ifndef GL_EXT_blend_color +#define GL_EXT_blend_color 1 +#define __GLEE_GL_EXT_blend_color 1 +/* Constants */ +#define GL_CONSTANT_COLOR_EXT 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002 +#define GL_CONSTANT_ALPHA_EXT 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004 +#define GL_BLEND_COLOR_EXT 0x8005 +#ifndef GLEE_H_DEFINED_glBlendColorEXT +#define GLEE_H_DEFINED_glBlendColorEXT + typedef void (APIENTRYP GLEEPFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + GLEE_EXTERN GLEEPFNGLBLENDCOLOREXTPROC GLeeFuncPtr_glBlendColorEXT; + #define glBlendColorEXT GLeeFuncPtr_glBlendColorEXT +#endif +#endif + +/* GL_EXT_polygon_offset */ + +#ifndef GL_EXT_polygon_offset +#define GL_EXT_polygon_offset 1 +#define __GLEE_GL_EXT_polygon_offset 1 +/* Constants */ +#define GL_POLYGON_OFFSET_EXT 0x8037 +#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038 +#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039 +#ifndef GLEE_H_DEFINED_glPolygonOffsetEXT +#define GLEE_H_DEFINED_glPolygonOffsetEXT + typedef void (APIENTRYP GLEEPFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias); + GLEE_EXTERN GLEEPFNGLPOLYGONOFFSETEXTPROC GLeeFuncPtr_glPolygonOffsetEXT; + #define glPolygonOffsetEXT GLeeFuncPtr_glPolygonOffsetEXT +#endif +#endif + +/* GL_EXT_texture */ + +#ifndef GL_EXT_texture +#define GL_EXT_texture 1 +#define __GLEE_GL_EXT_texture 1 +/* Constants */ +#define GL_ALPHA4_EXT 0x803B +#define GL_ALPHA8_EXT 0x803C +#define GL_ALPHA12_EXT 0x803D +#define GL_ALPHA16_EXT 0x803E +#define GL_LUMINANCE4_EXT 0x803F +#define GL_LUMINANCE8_EXT 0x8040 +#define GL_LUMINANCE12_EXT 0x8041 +#define GL_LUMINANCE16_EXT 0x8042 +#define GL_LUMINANCE4_ALPHA4_EXT 0x8043 +#define GL_LUMINANCE6_ALPHA2_EXT 0x8044 +#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +#define GL_LUMINANCE12_ALPHA4_EXT 0x8046 +#define GL_LUMINANCE12_ALPHA12_EXT 0x8047 +#define GL_LUMINANCE16_ALPHA16_EXT 0x8048 +#define GL_INTENSITY_EXT 0x8049 +#define GL_INTENSITY4_EXT 0x804A +#define GL_INTENSITY8_EXT 0x804B +#define GL_INTENSITY12_EXT 0x804C +#define GL_INTENSITY16_EXT 0x804D +#define GL_RGB2_EXT 0x804E +#define GL_RGB4_EXT 0x804F +#define GL_RGB5_EXT 0x8050 +#define GL_RGB8_EXT 0x8051 +#define GL_RGB10_EXT 0x8052 +#define GL_RGB12_EXT 0x8053 +#define GL_RGB16_EXT 0x8054 +#define GL_RGBA2_EXT 0x8055 +#define GL_RGBA4_EXT 0x8056 +#define GL_RGB5_A1_EXT 0x8057 +#define GL_RGBA8_EXT 0x8058 +#define GL_RGB10_A2_EXT 0x8059 +#define GL_RGBA12_EXT 0x805A +#define GL_RGBA16_EXT 0x805B +#define GL_TEXTURE_RED_SIZE_EXT 0x805C +#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D +#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E +#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061 +#define GL_REPLACE_EXT 0x8062 +#define GL_PROXY_TEXTURE_1D_EXT 0x8063 +#define GL_PROXY_TEXTURE_2D_EXT 0x8064 +#define GL_TEXTURE_TOO_LARGE_EXT 0x8065 +#endif + +/* GL_EXT_texture3D */ + +#ifndef GL_EXT_texture3D +#define GL_EXT_texture3D 1 +#define __GLEE_GL_EXT_texture3D 1 +/* Constants */ +#define GL_PACK_SKIP_IMAGES_EXT 0x806B +#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C +#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D +#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E +#define GL_TEXTURE_3D_EXT 0x806F +#define GL_PROXY_TEXTURE_3D_EXT 0x8070 +#define GL_TEXTURE_DEPTH_EXT 0x8071 +#define GL_TEXTURE_WRAP_R_EXT 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 +#ifndef GLEE_H_DEFINED_glTexImage3DEXT +#define GLEE_H_DEFINED_glTexImage3DEXT + typedef void (APIENTRYP GLEEPFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLTEXIMAGE3DEXTPROC GLeeFuncPtr_glTexImage3DEXT; + #define glTexImage3DEXT GLeeFuncPtr_glTexImage3DEXT +#endif +#ifndef GLEE_H_DEFINED_glTexSubImage3DEXT +#define GLEE_H_DEFINED_glTexSubImage3DEXT + typedef void (APIENTRYP GLEEPFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLTEXSUBIMAGE3DEXTPROC GLeeFuncPtr_glTexSubImage3DEXT; + #define glTexSubImage3DEXT GLeeFuncPtr_glTexSubImage3DEXT +#endif +#endif + +/* GL_SGIS_texture_filter4 */ + +#ifndef GL_SGIS_texture_filter4 +#define GL_SGIS_texture_filter4 1 +#define __GLEE_GL_SGIS_texture_filter4 1 +/* Constants */ +#define GL_FILTER4_SGIS 0x8146 +#define GL_TEXTURE_FILTER4_SIZE_SGIS 0x8147 +#ifndef GLEE_H_DEFINED_glGetTexFilterFuncSGIS +#define GLEE_H_DEFINED_glGetTexFilterFuncSGIS + typedef void (APIENTRYP GLEEPFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat * weights); + GLEE_EXTERN GLEEPFNGLGETTEXFILTERFUNCSGISPROC GLeeFuncPtr_glGetTexFilterFuncSGIS; + #define glGetTexFilterFuncSGIS GLeeFuncPtr_glGetTexFilterFuncSGIS +#endif +#ifndef GLEE_H_DEFINED_glTexFilterFuncSGIS +#define GLEE_H_DEFINED_glTexFilterFuncSGIS + typedef void (APIENTRYP GLEEPFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat * weights); + GLEE_EXTERN GLEEPFNGLTEXFILTERFUNCSGISPROC GLeeFuncPtr_glTexFilterFuncSGIS; + #define glTexFilterFuncSGIS GLeeFuncPtr_glTexFilterFuncSGIS +#endif +#endif + +/* GL_EXT_subtexture */ + +#ifndef GL_EXT_subtexture +#define GL_EXT_subtexture 1 +#define __GLEE_GL_EXT_subtexture 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glTexSubImage1DEXT +#define GLEE_H_DEFINED_glTexSubImage1DEXT + typedef void (APIENTRYP GLEEPFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLTEXSUBIMAGE1DEXTPROC GLeeFuncPtr_glTexSubImage1DEXT; + #define glTexSubImage1DEXT GLeeFuncPtr_glTexSubImage1DEXT +#endif +#ifndef GLEE_H_DEFINED_glTexSubImage2DEXT +#define GLEE_H_DEFINED_glTexSubImage2DEXT + typedef void (APIENTRYP GLEEPFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLTEXSUBIMAGE2DEXTPROC GLeeFuncPtr_glTexSubImage2DEXT; + #define glTexSubImage2DEXT GLeeFuncPtr_glTexSubImage2DEXT +#endif +#endif + +/* GL_EXT_copy_texture */ + +#ifndef GL_EXT_copy_texture +#define GL_EXT_copy_texture 1 +#define __GLEE_GL_EXT_copy_texture 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glCopyTexImage1DEXT +#define GLEE_H_DEFINED_glCopyTexImage1DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); + GLEE_EXTERN GLEEPFNGLCOPYTEXIMAGE1DEXTPROC GLeeFuncPtr_glCopyTexImage1DEXT; + #define glCopyTexImage1DEXT GLeeFuncPtr_glCopyTexImage1DEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyTexImage2DEXT +#define GLEE_H_DEFINED_glCopyTexImage2DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); + GLEE_EXTERN GLEEPFNGLCOPYTEXIMAGE2DEXTPROC GLeeFuncPtr_glCopyTexImage2DEXT; + #define glCopyTexImage2DEXT GLeeFuncPtr_glCopyTexImage2DEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyTexSubImage1DEXT +#define GLEE_H_DEFINED_glCopyTexSubImage1DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); + GLEE_EXTERN GLEEPFNGLCOPYTEXSUBIMAGE1DEXTPROC GLeeFuncPtr_glCopyTexSubImage1DEXT; + #define glCopyTexSubImage1DEXT GLeeFuncPtr_glCopyTexSubImage1DEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyTexSubImage2DEXT +#define GLEE_H_DEFINED_glCopyTexSubImage2DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLCOPYTEXSUBIMAGE2DEXTPROC GLeeFuncPtr_glCopyTexSubImage2DEXT; + #define glCopyTexSubImage2DEXT GLeeFuncPtr_glCopyTexSubImage2DEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyTexSubImage3DEXT +#define GLEE_H_DEFINED_glCopyTexSubImage3DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLCOPYTEXSUBIMAGE3DEXTPROC GLeeFuncPtr_glCopyTexSubImage3DEXT; + #define glCopyTexSubImage3DEXT GLeeFuncPtr_glCopyTexSubImage3DEXT +#endif +#endif + +/* GL_EXT_histogram */ + +#ifndef GL_EXT_histogram +#define GL_EXT_histogram 1 +#define __GLEE_GL_EXT_histogram 1 +/* Constants */ +#define GL_HISTOGRAM_EXT 0x8024 +#define GL_PROXY_HISTOGRAM_EXT 0x8025 +#define GL_HISTOGRAM_WIDTH_EXT 0x8026 +#define GL_HISTOGRAM_FORMAT_EXT 0x8027 +#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C +#define GL_HISTOGRAM_SINK_EXT 0x802D +#define GL_MINMAX_EXT 0x802E +#define GL_MINMAX_FORMAT_EXT 0x802F +#define GL_MINMAX_SINK_EXT 0x8030 +#define GL_TABLE_TOO_LARGE_EXT 0x8031 +#ifndef GLEE_H_DEFINED_glGetHistogramEXT +#define GLEE_H_DEFINED_glGetHistogramEXT + typedef void (APIENTRYP GLEEPFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values); + GLEE_EXTERN GLEEPFNGLGETHISTOGRAMEXTPROC GLeeFuncPtr_glGetHistogramEXT; + #define glGetHistogramEXT GLeeFuncPtr_glGetHistogramEXT +#endif +#ifndef GLEE_H_DEFINED_glGetHistogramParameterfvEXT +#define GLEE_H_DEFINED_glGetHistogramParameterfvEXT + typedef void (APIENTRYP GLEEPFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETHISTOGRAMPARAMETERFVEXTPROC GLeeFuncPtr_glGetHistogramParameterfvEXT; + #define glGetHistogramParameterfvEXT GLeeFuncPtr_glGetHistogramParameterfvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetHistogramParameterivEXT +#define GLEE_H_DEFINED_glGetHistogramParameterivEXT + typedef void (APIENTRYP GLEEPFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETHISTOGRAMPARAMETERIVEXTPROC GLeeFuncPtr_glGetHistogramParameterivEXT; + #define glGetHistogramParameterivEXT GLeeFuncPtr_glGetHistogramParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetMinmaxEXT +#define GLEE_H_DEFINED_glGetMinmaxEXT + typedef void (APIENTRYP GLEEPFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values); + GLEE_EXTERN GLEEPFNGLGETMINMAXEXTPROC GLeeFuncPtr_glGetMinmaxEXT; + #define glGetMinmaxEXT GLeeFuncPtr_glGetMinmaxEXT +#endif +#ifndef GLEE_H_DEFINED_glGetMinmaxParameterfvEXT +#define GLEE_H_DEFINED_glGetMinmaxParameterfvEXT + typedef void (APIENTRYP GLEEPFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETMINMAXPARAMETERFVEXTPROC GLeeFuncPtr_glGetMinmaxParameterfvEXT; + #define glGetMinmaxParameterfvEXT GLeeFuncPtr_glGetMinmaxParameterfvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetMinmaxParameterivEXT +#define GLEE_H_DEFINED_glGetMinmaxParameterivEXT + typedef void (APIENTRYP GLEEPFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETMINMAXPARAMETERIVEXTPROC GLeeFuncPtr_glGetMinmaxParameterivEXT; + #define glGetMinmaxParameterivEXT GLeeFuncPtr_glGetMinmaxParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glHistogramEXT +#define GLEE_H_DEFINED_glHistogramEXT + typedef void (APIENTRYP GLEEPFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); + GLEE_EXTERN GLEEPFNGLHISTOGRAMEXTPROC GLeeFuncPtr_glHistogramEXT; + #define glHistogramEXT GLeeFuncPtr_glHistogramEXT +#endif +#ifndef GLEE_H_DEFINED_glMinmaxEXT +#define GLEE_H_DEFINED_glMinmaxEXT + typedef void (APIENTRYP GLEEPFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink); + GLEE_EXTERN GLEEPFNGLMINMAXEXTPROC GLeeFuncPtr_glMinmaxEXT; + #define glMinmaxEXT GLeeFuncPtr_glMinmaxEXT +#endif +#ifndef GLEE_H_DEFINED_glResetHistogramEXT +#define GLEE_H_DEFINED_glResetHistogramEXT + typedef void (APIENTRYP GLEEPFNGLRESETHISTOGRAMEXTPROC) (GLenum target); + GLEE_EXTERN GLEEPFNGLRESETHISTOGRAMEXTPROC GLeeFuncPtr_glResetHistogramEXT; + #define glResetHistogramEXT GLeeFuncPtr_glResetHistogramEXT +#endif +#ifndef GLEE_H_DEFINED_glResetMinmaxEXT +#define GLEE_H_DEFINED_glResetMinmaxEXT + typedef void (APIENTRYP GLEEPFNGLRESETMINMAXEXTPROC) (GLenum target); + GLEE_EXTERN GLEEPFNGLRESETMINMAXEXTPROC GLeeFuncPtr_glResetMinmaxEXT; + #define glResetMinmaxEXT GLeeFuncPtr_glResetMinmaxEXT +#endif +#endif + +/* GL_EXT_convolution */ + +#ifndef GL_EXT_convolution +#define GL_EXT_convolution 1 +#define __GLEE_GL_EXT_convolution 1 +/* Constants */ +#define GL_CONVOLUTION_1D_EXT 0x8010 +#define GL_CONVOLUTION_2D_EXT 0x8011 +#define GL_SEPARABLE_2D_EXT 0x8012 +#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015 +#define GL_REDUCE_EXT 0x8016 +#define GL_CONVOLUTION_FORMAT_EXT 0x8017 +#define GL_CONVOLUTION_WIDTH_EXT 0x8018 +#define GL_CONVOLUTION_HEIGHT_EXT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 +#ifndef GLEE_H_DEFINED_glConvolutionFilter1DEXT +#define GLEE_H_DEFINED_glConvolutionFilter1DEXT + typedef void (APIENTRYP GLEEPFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * image); + GLEE_EXTERN GLEEPFNGLCONVOLUTIONFILTER1DEXTPROC GLeeFuncPtr_glConvolutionFilter1DEXT; + #define glConvolutionFilter1DEXT GLeeFuncPtr_glConvolutionFilter1DEXT +#endif +#ifndef GLEE_H_DEFINED_glConvolutionFilter2DEXT +#define GLEE_H_DEFINED_glConvolutionFilter2DEXT + typedef void (APIENTRYP GLEEPFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * image); + GLEE_EXTERN GLEEPFNGLCONVOLUTIONFILTER2DEXTPROC GLeeFuncPtr_glConvolutionFilter2DEXT; + #define glConvolutionFilter2DEXT GLeeFuncPtr_glConvolutionFilter2DEXT +#endif +#ifndef GLEE_H_DEFINED_glConvolutionParameterfEXT +#define GLEE_H_DEFINED_glConvolutionParameterfEXT + typedef void (APIENTRYP GLEEPFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params); + GLEE_EXTERN GLEEPFNGLCONVOLUTIONPARAMETERFEXTPROC GLeeFuncPtr_glConvolutionParameterfEXT; + #define glConvolutionParameterfEXT GLeeFuncPtr_glConvolutionParameterfEXT +#endif +#ifndef GLEE_H_DEFINED_glConvolutionParameterfvEXT +#define GLEE_H_DEFINED_glConvolutionParameterfvEXT + typedef void (APIENTRYP GLEEPFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLCONVOLUTIONPARAMETERFVEXTPROC GLeeFuncPtr_glConvolutionParameterfvEXT; + #define glConvolutionParameterfvEXT GLeeFuncPtr_glConvolutionParameterfvEXT +#endif +#ifndef GLEE_H_DEFINED_glConvolutionParameteriEXT +#define GLEE_H_DEFINED_glConvolutionParameteriEXT + typedef void (APIENTRYP GLEEPFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params); + GLEE_EXTERN GLEEPFNGLCONVOLUTIONPARAMETERIEXTPROC GLeeFuncPtr_glConvolutionParameteriEXT; + #define glConvolutionParameteriEXT GLeeFuncPtr_glConvolutionParameteriEXT +#endif +#ifndef GLEE_H_DEFINED_glConvolutionParameterivEXT +#define GLEE_H_DEFINED_glConvolutionParameterivEXT + typedef void (APIENTRYP GLEEPFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLCONVOLUTIONPARAMETERIVEXTPROC GLeeFuncPtr_glConvolutionParameterivEXT; + #define glConvolutionParameterivEXT GLeeFuncPtr_glConvolutionParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyConvolutionFilter1DEXT +#define GLEE_H_DEFINED_glCopyConvolutionFilter1DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); + GLEE_EXTERN GLEEPFNGLCOPYCONVOLUTIONFILTER1DEXTPROC GLeeFuncPtr_glCopyConvolutionFilter1DEXT; + #define glCopyConvolutionFilter1DEXT GLeeFuncPtr_glCopyConvolutionFilter1DEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyConvolutionFilter2DEXT +#define GLEE_H_DEFINED_glCopyConvolutionFilter2DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLCOPYCONVOLUTIONFILTER2DEXTPROC GLeeFuncPtr_glCopyConvolutionFilter2DEXT; + #define glCopyConvolutionFilter2DEXT GLeeFuncPtr_glCopyConvolutionFilter2DEXT +#endif +#ifndef GLEE_H_DEFINED_glGetConvolutionFilterEXT +#define GLEE_H_DEFINED_glGetConvolutionFilterEXT + typedef void (APIENTRYP GLEEPFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid * image); + GLEE_EXTERN GLEEPFNGLGETCONVOLUTIONFILTEREXTPROC GLeeFuncPtr_glGetConvolutionFilterEXT; + #define glGetConvolutionFilterEXT GLeeFuncPtr_glGetConvolutionFilterEXT +#endif +#ifndef GLEE_H_DEFINED_glGetConvolutionParameterfvEXT +#define GLEE_H_DEFINED_glGetConvolutionParameterfvEXT + typedef void (APIENTRYP GLEEPFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETCONVOLUTIONPARAMETERFVEXTPROC GLeeFuncPtr_glGetConvolutionParameterfvEXT; + #define glGetConvolutionParameterfvEXT GLeeFuncPtr_glGetConvolutionParameterfvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetConvolutionParameterivEXT +#define GLEE_H_DEFINED_glGetConvolutionParameterivEXT + typedef void (APIENTRYP GLEEPFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETCONVOLUTIONPARAMETERIVEXTPROC GLeeFuncPtr_glGetConvolutionParameterivEXT; + #define glGetConvolutionParameterivEXT GLeeFuncPtr_glGetConvolutionParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetSeparableFilterEXT +#define GLEE_H_DEFINED_glGetSeparableFilterEXT + typedef void (APIENTRYP GLEEPFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid * row, GLvoid * column, GLvoid * span); + GLEE_EXTERN GLEEPFNGLGETSEPARABLEFILTEREXTPROC GLeeFuncPtr_glGetSeparableFilterEXT; + #define glGetSeparableFilterEXT GLeeFuncPtr_glGetSeparableFilterEXT +#endif +#ifndef GLEE_H_DEFINED_glSeparableFilter2DEXT +#define GLEE_H_DEFINED_glSeparableFilter2DEXT + typedef void (APIENTRYP GLEEPFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * row, const GLvoid * column); + GLEE_EXTERN GLEEPFNGLSEPARABLEFILTER2DEXTPROC GLeeFuncPtr_glSeparableFilter2DEXT; + #define glSeparableFilter2DEXT GLeeFuncPtr_glSeparableFilter2DEXT +#endif +#endif + +/* GL_SGI_color_matrix */ + +#ifndef GL_SGI_color_matrix +#define GL_SGI_color_matrix 1 +#define __GLEE_GL_SGI_color_matrix 1 +/* Constants */ +#define GL_COLOR_MATRIX_SGI 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB +#endif + +/* GL_SGI_color_table */ + +#ifndef GL_SGI_color_table +#define GL_SGI_color_table 1 +#define __GLEE_GL_SGI_color_table 1 +/* Constants */ +#define GL_COLOR_TABLE_SGI 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2 +#define GL_PROXY_COLOR_TABLE_SGI 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5 +#define GL_COLOR_TABLE_SCALE_SGI 0x80D6 +#define GL_COLOR_TABLE_BIAS_SGI 0x80D7 +#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8 +#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF +#ifndef GLEE_H_DEFINED_glColorTableSGI +#define GLEE_H_DEFINED_glColorTableSGI + typedef void (APIENTRYP GLEEPFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * table); + GLEE_EXTERN GLEEPFNGLCOLORTABLESGIPROC GLeeFuncPtr_glColorTableSGI; + #define glColorTableSGI GLeeFuncPtr_glColorTableSGI +#endif +#ifndef GLEE_H_DEFINED_glColorTableParameterfvSGI +#define GLEE_H_DEFINED_glColorTableParameterfvSGI + typedef void (APIENTRYP GLEEPFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLCOLORTABLEPARAMETERFVSGIPROC GLeeFuncPtr_glColorTableParameterfvSGI; + #define glColorTableParameterfvSGI GLeeFuncPtr_glColorTableParameterfvSGI +#endif +#ifndef GLEE_H_DEFINED_glColorTableParameterivSGI +#define GLEE_H_DEFINED_glColorTableParameterivSGI + typedef void (APIENTRYP GLEEPFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLCOLORTABLEPARAMETERIVSGIPROC GLeeFuncPtr_glColorTableParameterivSGI; + #define glColorTableParameterivSGI GLeeFuncPtr_glColorTableParameterivSGI +#endif +#ifndef GLEE_H_DEFINED_glCopyColorTableSGI +#define GLEE_H_DEFINED_glCopyColorTableSGI + typedef void (APIENTRYP GLEEPFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); + GLEE_EXTERN GLEEPFNGLCOPYCOLORTABLESGIPROC GLeeFuncPtr_glCopyColorTableSGI; + #define glCopyColorTableSGI GLeeFuncPtr_glCopyColorTableSGI +#endif +#ifndef GLEE_H_DEFINED_glGetColorTableSGI +#define GLEE_H_DEFINED_glGetColorTableSGI + typedef void (APIENTRYP GLEEPFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, GLvoid * table); + GLEE_EXTERN GLEEPFNGLGETCOLORTABLESGIPROC GLeeFuncPtr_glGetColorTableSGI; + #define glGetColorTableSGI GLeeFuncPtr_glGetColorTableSGI +#endif +#ifndef GLEE_H_DEFINED_glGetColorTableParameterfvSGI +#define GLEE_H_DEFINED_glGetColorTableParameterfvSGI + typedef void (APIENTRYP GLEEPFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETCOLORTABLEPARAMETERFVSGIPROC GLeeFuncPtr_glGetColorTableParameterfvSGI; + #define glGetColorTableParameterfvSGI GLeeFuncPtr_glGetColorTableParameterfvSGI +#endif +#ifndef GLEE_H_DEFINED_glGetColorTableParameterivSGI +#define GLEE_H_DEFINED_glGetColorTableParameterivSGI + typedef void (APIENTRYP GLEEPFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETCOLORTABLEPARAMETERIVSGIPROC GLeeFuncPtr_glGetColorTableParameterivSGI; + #define glGetColorTableParameterivSGI GLeeFuncPtr_glGetColorTableParameterivSGI +#endif +#endif + +/* GL_SGIS_pixel_texture */ + +#ifndef GL_SGIS_pixel_texture +#define GL_SGIS_pixel_texture 1 +#define __GLEE_GL_SGIS_pixel_texture 1 +/* Constants */ +#define GL_PIXEL_TEXTURE_SGIS 0x8353 +#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354 +#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355 +#define GL_PIXEL_GROUP_COLOR_SGIS 0x8356 +#ifndef GLEE_H_DEFINED_glPixelTexGenParameteriSGIS +#define GLEE_H_DEFINED_glPixelTexGenParameteriSGIS + typedef void (APIENTRYP GLEEPFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLPIXELTEXGENPARAMETERISGISPROC GLeeFuncPtr_glPixelTexGenParameteriSGIS; + #define glPixelTexGenParameteriSGIS GLeeFuncPtr_glPixelTexGenParameteriSGIS +#endif +#ifndef GLEE_H_DEFINED_glPixelTexGenParameterivSGIS +#define GLEE_H_DEFINED_glPixelTexGenParameterivSGIS + typedef void (APIENTRYP GLEEPFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLPIXELTEXGENPARAMETERIVSGISPROC GLeeFuncPtr_glPixelTexGenParameterivSGIS; + #define glPixelTexGenParameterivSGIS GLeeFuncPtr_glPixelTexGenParameterivSGIS +#endif +#ifndef GLEE_H_DEFINED_glPixelTexGenParameterfSGIS +#define GLEE_H_DEFINED_glPixelTexGenParameterfSGIS + typedef void (APIENTRYP GLEEPFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLPIXELTEXGENPARAMETERFSGISPROC GLeeFuncPtr_glPixelTexGenParameterfSGIS; + #define glPixelTexGenParameterfSGIS GLeeFuncPtr_glPixelTexGenParameterfSGIS +#endif +#ifndef GLEE_H_DEFINED_glPixelTexGenParameterfvSGIS +#define GLEE_H_DEFINED_glPixelTexGenParameterfvSGIS + typedef void (APIENTRYP GLEEPFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLPIXELTEXGENPARAMETERFVSGISPROC GLeeFuncPtr_glPixelTexGenParameterfvSGIS; + #define glPixelTexGenParameterfvSGIS GLeeFuncPtr_glPixelTexGenParameterfvSGIS +#endif +#ifndef GLEE_H_DEFINED_glGetPixelTexGenParameterivSGIS +#define GLEE_H_DEFINED_glGetPixelTexGenParameterivSGIS + typedef void (APIENTRYP GLEEPFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETPIXELTEXGENPARAMETERIVSGISPROC GLeeFuncPtr_glGetPixelTexGenParameterivSGIS; + #define glGetPixelTexGenParameterivSGIS GLeeFuncPtr_glGetPixelTexGenParameterivSGIS +#endif +#ifndef GLEE_H_DEFINED_glGetPixelTexGenParameterfvSGIS +#define GLEE_H_DEFINED_glGetPixelTexGenParameterfvSGIS + typedef void (APIENTRYP GLEEPFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETPIXELTEXGENPARAMETERFVSGISPROC GLeeFuncPtr_glGetPixelTexGenParameterfvSGIS; + #define glGetPixelTexGenParameterfvSGIS GLeeFuncPtr_glGetPixelTexGenParameterfvSGIS +#endif +#endif + +/* GL_SGIX_pixel_texture */ + +#ifndef GL_SGIX_pixel_texture +#define GL_SGIX_pixel_texture 1 +#define __GLEE_GL_SGIX_pixel_texture 1 +/* Constants */ +#define GL_PIXEL_TEX_GEN_SGIX 0x8139 +#define GL_PIXEL_TEX_GEN_MODE_SGIX 0x832B +#ifndef GLEE_H_DEFINED_glPixelTexGenSGIX +#define GLEE_H_DEFINED_glPixelTexGenSGIX + typedef void (APIENTRYP GLEEPFNGLPIXELTEXGENSGIXPROC) (GLenum mode); + GLEE_EXTERN GLEEPFNGLPIXELTEXGENSGIXPROC GLeeFuncPtr_glPixelTexGenSGIX; + #define glPixelTexGenSGIX GLeeFuncPtr_glPixelTexGenSGIX +#endif +#endif + +/* GL_SGIS_texture4D */ + +#ifndef GL_SGIS_texture4D +#define GL_SGIS_texture4D 1 +#define __GLEE_GL_SGIS_texture4D 1 +/* Constants */ +#define GL_PACK_SKIP_VOLUMES_SGIS 0x8130 +#define GL_PACK_IMAGE_DEPTH_SGIS 0x8131 +#define GL_UNPACK_SKIP_VOLUMES_SGIS 0x8132 +#define GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133 +#define GL_TEXTURE_4D_SGIS 0x8134 +#define GL_PROXY_TEXTURE_4D_SGIS 0x8135 +#define GL_TEXTURE_4DSIZE_SGIS 0x8136 +#define GL_TEXTURE_WRAP_Q_SGIS 0x8137 +#define GL_MAX_4D_TEXTURE_SIZE_SGIS 0x8138 +#define GL_TEXTURE_4D_BINDING_SGIS 0x814F +#ifndef GLEE_H_DEFINED_glTexImage4DSGIS +#define GLEE_H_DEFINED_glTexImage4DSGIS + typedef void (APIENTRYP GLEEPFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLTEXIMAGE4DSGISPROC GLeeFuncPtr_glTexImage4DSGIS; + #define glTexImage4DSGIS GLeeFuncPtr_glTexImage4DSGIS +#endif +#ifndef GLEE_H_DEFINED_glTexSubImage4DSGIS +#define GLEE_H_DEFINED_glTexSubImage4DSGIS + typedef void (APIENTRYP GLEEPFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLTEXSUBIMAGE4DSGISPROC GLeeFuncPtr_glTexSubImage4DSGIS; + #define glTexSubImage4DSGIS GLeeFuncPtr_glTexSubImage4DSGIS +#endif +#endif + +/* GL_SGI_texture_color_table */ + +#ifndef GL_SGI_texture_color_table +#define GL_SGI_texture_color_table 1 +#define __GLEE_GL_SGI_texture_color_table 1 +/* Constants */ +#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC +#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD +#endif + +/* GL_EXT_cmyka */ + +#ifndef GL_EXT_cmyka +#define GL_EXT_cmyka 1 +#define __GLEE_GL_EXT_cmyka 1 +/* Constants */ +#define GL_CMYK_EXT 0x800C +#define GL_CMYKA_EXT 0x800D +#define GL_PACK_CMYK_HINT_EXT 0x800E +#define GL_UNPACK_CMYK_HINT_EXT 0x800F +#endif + +/* GL_EXT_texture_object */ + +#ifndef GL_EXT_texture_object +#define GL_EXT_texture_object 1 +#define __GLEE_GL_EXT_texture_object 1 +/* Constants */ +#define GL_TEXTURE_PRIORITY_EXT 0x8066 +#define GL_TEXTURE_RESIDENT_EXT 0x8067 +#define GL_TEXTURE_1D_BINDING_EXT 0x8068 +#define GL_TEXTURE_2D_BINDING_EXT 0x8069 +#define GL_TEXTURE_3D_BINDING_EXT 0x806A +#ifndef GLEE_H_DEFINED_glAreTexturesResidentEXT +#define GLEE_H_DEFINED_glAreTexturesResidentEXT + typedef GLboolean (APIENTRYP GLEEPFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint * textures, GLboolean * residences); + GLEE_EXTERN GLEEPFNGLARETEXTURESRESIDENTEXTPROC GLeeFuncPtr_glAreTexturesResidentEXT; + #define glAreTexturesResidentEXT GLeeFuncPtr_glAreTexturesResidentEXT +#endif +#ifndef GLEE_H_DEFINED_glBindTextureEXT +#define GLEE_H_DEFINED_glBindTextureEXT + typedef void (APIENTRYP GLEEPFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture); + GLEE_EXTERN GLEEPFNGLBINDTEXTUREEXTPROC GLeeFuncPtr_glBindTextureEXT; + #define glBindTextureEXT GLeeFuncPtr_glBindTextureEXT +#endif +#ifndef GLEE_H_DEFINED_glDeleteTexturesEXT +#define GLEE_H_DEFINED_glDeleteTexturesEXT + typedef void (APIENTRYP GLEEPFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint * textures); + GLEE_EXTERN GLEEPFNGLDELETETEXTURESEXTPROC GLeeFuncPtr_glDeleteTexturesEXT; + #define glDeleteTexturesEXT GLeeFuncPtr_glDeleteTexturesEXT +#endif +#ifndef GLEE_H_DEFINED_glGenTexturesEXT +#define GLEE_H_DEFINED_glGenTexturesEXT + typedef void (APIENTRYP GLEEPFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint * textures); + GLEE_EXTERN GLEEPFNGLGENTEXTURESEXTPROC GLeeFuncPtr_glGenTexturesEXT; + #define glGenTexturesEXT GLeeFuncPtr_glGenTexturesEXT +#endif +#ifndef GLEE_H_DEFINED_glIsTextureEXT +#define GLEE_H_DEFINED_glIsTextureEXT + typedef GLboolean (APIENTRYP GLEEPFNGLISTEXTUREEXTPROC) (GLuint texture); + GLEE_EXTERN GLEEPFNGLISTEXTUREEXTPROC GLeeFuncPtr_glIsTextureEXT; + #define glIsTextureEXT GLeeFuncPtr_glIsTextureEXT +#endif +#ifndef GLEE_H_DEFINED_glPrioritizeTexturesEXT +#define GLEE_H_DEFINED_glPrioritizeTexturesEXT + typedef void (APIENTRYP GLEEPFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint * textures, const GLclampf * priorities); + GLEE_EXTERN GLEEPFNGLPRIORITIZETEXTURESEXTPROC GLeeFuncPtr_glPrioritizeTexturesEXT; + #define glPrioritizeTexturesEXT GLeeFuncPtr_glPrioritizeTexturesEXT +#endif +#endif + +/* GL_SGIS_detail_texture */ + +#ifndef GL_SGIS_detail_texture +#define GL_SGIS_detail_texture 1 +#define __GLEE_GL_SGIS_detail_texture 1 +/* Constants */ +#define GL_DETAIL_TEXTURE_2D_SGIS 0x8095 +#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096 +#define GL_LINEAR_DETAIL_SGIS 0x8097 +#define GL_LINEAR_DETAIL_ALPHA_SGIS 0x8098 +#define GL_LINEAR_DETAIL_COLOR_SGIS 0x8099 +#define GL_DETAIL_TEXTURE_LEVEL_SGIS 0x809A +#define GL_DETAIL_TEXTURE_MODE_SGIS 0x809B +#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C +#ifndef GLEE_H_DEFINED_glDetailTexFuncSGIS +#define GLEE_H_DEFINED_glDetailTexFuncSGIS + typedef void (APIENTRYP GLEEPFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat * points); + GLEE_EXTERN GLEEPFNGLDETAILTEXFUNCSGISPROC GLeeFuncPtr_glDetailTexFuncSGIS; + #define glDetailTexFuncSGIS GLeeFuncPtr_glDetailTexFuncSGIS +#endif +#ifndef GLEE_H_DEFINED_glGetDetailTexFuncSGIS +#define GLEE_H_DEFINED_glGetDetailTexFuncSGIS + typedef void (APIENTRYP GLEEPFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat * points); + GLEE_EXTERN GLEEPFNGLGETDETAILTEXFUNCSGISPROC GLeeFuncPtr_glGetDetailTexFuncSGIS; + #define glGetDetailTexFuncSGIS GLeeFuncPtr_glGetDetailTexFuncSGIS +#endif +#endif + +/* GL_SGIS_sharpen_texture */ + +#ifndef GL_SGIS_sharpen_texture +#define GL_SGIS_sharpen_texture 1 +#define __GLEE_GL_SGIS_sharpen_texture 1 +/* Constants */ +#define GL_LINEAR_SHARPEN_SGIS 0x80AD +#define GL_LINEAR_SHARPEN_ALPHA_SGIS 0x80AE +#define GL_LINEAR_SHARPEN_COLOR_SGIS 0x80AF +#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0 +#ifndef GLEE_H_DEFINED_glSharpenTexFuncSGIS +#define GLEE_H_DEFINED_glSharpenTexFuncSGIS + typedef void (APIENTRYP GLEEPFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat * points); + GLEE_EXTERN GLEEPFNGLSHARPENTEXFUNCSGISPROC GLeeFuncPtr_glSharpenTexFuncSGIS; + #define glSharpenTexFuncSGIS GLeeFuncPtr_glSharpenTexFuncSGIS +#endif +#ifndef GLEE_H_DEFINED_glGetSharpenTexFuncSGIS +#define GLEE_H_DEFINED_glGetSharpenTexFuncSGIS + typedef void (APIENTRYP GLEEPFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat * points); + GLEE_EXTERN GLEEPFNGLGETSHARPENTEXFUNCSGISPROC GLeeFuncPtr_glGetSharpenTexFuncSGIS; + #define glGetSharpenTexFuncSGIS GLeeFuncPtr_glGetSharpenTexFuncSGIS +#endif +#endif + +/* GL_EXT_packed_pixels */ + +#ifndef GL_EXT_packed_pixels +#define GL_EXT_packed_pixels 1 +#define __GLEE_GL_EXT_packed_pixels 1 +/* Constants */ +#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036 +#endif + +/* GL_SGIS_texture_lod */ + +#ifndef GL_SGIS_texture_lod +#define GL_SGIS_texture_lod 1 +#define __GLEE_GL_SGIS_texture_lod 1 +/* Constants */ +#define GL_TEXTURE_MIN_LOD_SGIS 0x813A +#define GL_TEXTURE_MAX_LOD_SGIS 0x813B +#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C +#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D +#endif + +/* GL_SGIS_multisample */ + +#ifndef GL_SGIS_multisample +#define GL_SGIS_multisample 1 +#define __GLEE_GL_SGIS_multisample 1 +/* Constants */ +#define GL_MULTISAMPLE_SGIS 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F +#define GL_SAMPLE_MASK_SGIS 0x80A0 +#define GL_1PASS_SGIS 0x80A1 +#define GL_2PASS_0_SGIS 0x80A2 +#define GL_2PASS_1_SGIS 0x80A3 +#define GL_4PASS_0_SGIS 0x80A4 +#define GL_4PASS_1_SGIS 0x80A5 +#define GL_4PASS_2_SGIS 0x80A6 +#define GL_4PASS_3_SGIS 0x80A7 +#define GL_SAMPLE_BUFFERS_SGIS 0x80A8 +#define GL_SAMPLES_SGIS 0x80A9 +#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA +#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB +#define GL_SAMPLE_PATTERN_SGIS 0x80AC +#ifndef GLEE_H_DEFINED_glSampleMaskSGIS +#define GLEE_H_DEFINED_glSampleMaskSGIS + typedef void (APIENTRYP GLEEPFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert); + GLEE_EXTERN GLEEPFNGLSAMPLEMASKSGISPROC GLeeFuncPtr_glSampleMaskSGIS; + #define glSampleMaskSGIS GLeeFuncPtr_glSampleMaskSGIS +#endif +#ifndef GLEE_H_DEFINED_glSamplePatternSGIS +#define GLEE_H_DEFINED_glSamplePatternSGIS + typedef void (APIENTRYP GLEEPFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern); + GLEE_EXTERN GLEEPFNGLSAMPLEPATTERNSGISPROC GLeeFuncPtr_glSamplePatternSGIS; + #define glSamplePatternSGIS GLeeFuncPtr_glSamplePatternSGIS +#endif +#endif + +/* GL_EXT_rescale_normal */ + +#ifndef GL_EXT_rescale_normal +#define GL_EXT_rescale_normal 1 +#define __GLEE_GL_EXT_rescale_normal 1 +/* Constants */ +#define GL_RESCALE_NORMAL_EXT 0x803A +#endif + +/* GL_EXT_vertex_array */ + +#ifndef GL_EXT_vertex_array +#define GL_EXT_vertex_array 1 +#define __GLEE_GL_EXT_vertex_array 1 +/* Constants */ +#define GL_VERTEX_ARRAY_EXT 0x8074 +#define GL_NORMAL_ARRAY_EXT 0x8075 +#define GL_COLOR_ARRAY_EXT 0x8076 +#define GL_INDEX_ARRAY_EXT 0x8077 +#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078 +#define GL_EDGE_FLAG_ARRAY_EXT 0x8079 +#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A +#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B +#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C +#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D +#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E +#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F +#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080 +#define GL_COLOR_ARRAY_SIZE_EXT 0x8081 +#define GL_COLOR_ARRAY_TYPE_EXT 0x8082 +#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083 +#define GL_COLOR_ARRAY_COUNT_EXT 0x8084 +#define GL_INDEX_ARRAY_TYPE_EXT 0x8085 +#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086 +#define GL_INDEX_ARRAY_COUNT_EXT 0x8087 +#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A +#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B +#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C +#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D +#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E +#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F +#define GL_COLOR_ARRAY_POINTER_EXT 0x8090 +#define GL_INDEX_ARRAY_POINTER_EXT 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 +#ifndef GLEE_H_DEFINED_glArrayElementEXT +#define GLEE_H_DEFINED_glArrayElementEXT + typedef void (APIENTRYP GLEEPFNGLARRAYELEMENTEXTPROC) (GLint i); + GLEE_EXTERN GLEEPFNGLARRAYELEMENTEXTPROC GLeeFuncPtr_glArrayElementEXT; + #define glArrayElementEXT GLeeFuncPtr_glArrayElementEXT +#endif +#ifndef GLEE_H_DEFINED_glColorPointerEXT +#define GLEE_H_DEFINED_glColorPointerEXT + typedef void (APIENTRYP GLEEPFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLCOLORPOINTEREXTPROC GLeeFuncPtr_glColorPointerEXT; + #define glColorPointerEXT GLeeFuncPtr_glColorPointerEXT +#endif +#ifndef GLEE_H_DEFINED_glDrawArraysEXT +#define GLEE_H_DEFINED_glDrawArraysEXT + typedef void (APIENTRYP GLEEPFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count); + GLEE_EXTERN GLEEPFNGLDRAWARRAYSEXTPROC GLeeFuncPtr_glDrawArraysEXT; + #define glDrawArraysEXT GLeeFuncPtr_glDrawArraysEXT +#endif +#ifndef GLEE_H_DEFINED_glEdgeFlagPointerEXT +#define GLEE_H_DEFINED_glEdgeFlagPointerEXT + typedef void (APIENTRYP GLEEPFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean * pointer); + GLEE_EXTERN GLEEPFNGLEDGEFLAGPOINTEREXTPROC GLeeFuncPtr_glEdgeFlagPointerEXT; + #define glEdgeFlagPointerEXT GLeeFuncPtr_glEdgeFlagPointerEXT +#endif +#ifndef GLEE_H_DEFINED_glGetPointervEXT +#define GLEE_H_DEFINED_glGetPointervEXT + typedef void (APIENTRYP GLEEPFNGLGETPOINTERVEXTPROC) (GLenum pname, GLvoid* * params); + GLEE_EXTERN GLEEPFNGLGETPOINTERVEXTPROC GLeeFuncPtr_glGetPointervEXT; + #define glGetPointervEXT GLeeFuncPtr_glGetPointervEXT +#endif +#ifndef GLEE_H_DEFINED_glIndexPointerEXT +#define GLEE_H_DEFINED_glIndexPointerEXT + typedef void (APIENTRYP GLEEPFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLINDEXPOINTEREXTPROC GLeeFuncPtr_glIndexPointerEXT; + #define glIndexPointerEXT GLeeFuncPtr_glIndexPointerEXT +#endif +#ifndef GLEE_H_DEFINED_glNormalPointerEXT +#define GLEE_H_DEFINED_glNormalPointerEXT + typedef void (APIENTRYP GLEEPFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLNORMALPOINTEREXTPROC GLeeFuncPtr_glNormalPointerEXT; + #define glNormalPointerEXT GLeeFuncPtr_glNormalPointerEXT +#endif +#ifndef GLEE_H_DEFINED_glTexCoordPointerEXT +#define GLEE_H_DEFINED_glTexCoordPointerEXT + typedef void (APIENTRYP GLEEPFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLTEXCOORDPOINTEREXTPROC GLeeFuncPtr_glTexCoordPointerEXT; + #define glTexCoordPointerEXT GLeeFuncPtr_glTexCoordPointerEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexPointerEXT +#define GLEE_H_DEFINED_glVertexPointerEXT + typedef void (APIENTRYP GLEEPFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLVERTEXPOINTEREXTPROC GLeeFuncPtr_glVertexPointerEXT; + #define glVertexPointerEXT GLeeFuncPtr_glVertexPointerEXT +#endif +#endif + +/* GL_EXT_misc_attribute */ + +#ifndef GL_EXT_misc_attribute +#define GL_EXT_misc_attribute 1 +#define __GLEE_GL_EXT_misc_attribute 1 +/* Constants */ +#endif + +/* GL_SGIS_generate_mipmap */ + +#ifndef GL_SGIS_generate_mipmap +#define GL_SGIS_generate_mipmap 1 +#define __GLEE_GL_SGIS_generate_mipmap 1 +/* Constants */ +#define GL_GENERATE_MIPMAP_SGIS 0x8191 +#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 +#endif + +/* GL_SGIX_clipmap */ + +#ifndef GL_SGIX_clipmap +#define GL_SGIX_clipmap 1 +#define __GLEE_GL_SGIX_clipmap 1 +/* Constants */ +#define GL_LINEAR_CLIPMAP_LINEAR_SGIX 0x8170 +#define GL_TEXTURE_CLIPMAP_CENTER_SGIX 0x8171 +#define GL_TEXTURE_CLIPMAP_FRAME_SGIX 0x8172 +#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX 0x8173 +#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174 +#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175 +#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX 0x8176 +#define GL_MAX_CLIPMAP_DEPTH_SGIX 0x8177 +#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178 +#define GL_NEAREST_CLIPMAP_NEAREST_SGIX 0x844D +#define GL_NEAREST_CLIPMAP_LINEAR_SGIX 0x844E +#define GL_LINEAR_CLIPMAP_NEAREST_SGIX 0x844F +#endif + +/* GL_SGIX_shadow */ + +#ifndef GL_SGIX_shadow +#define GL_SGIX_shadow 1 +#define __GLEE_GL_SGIX_shadow 1 +/* Constants */ +#define GL_TEXTURE_COMPARE_SGIX 0x819A +#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B +#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C +#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D +#endif + +/* GL_SGIS_texture_edge_clamp */ + +#ifndef GL_SGIS_texture_edge_clamp +#define GL_SGIS_texture_edge_clamp 1 +#define __GLEE_GL_SGIS_texture_edge_clamp 1 +/* Constants */ +#define GL_CLAMP_TO_EDGE_SGIS 0x812F +#endif + +/* GL_SGIS_texture_border_clamp */ + +#ifndef GL_SGIS_texture_border_clamp +#define GL_SGIS_texture_border_clamp 1 +#define __GLEE_GL_SGIS_texture_border_clamp 1 +/* Constants */ +#define GL_CLAMP_TO_BORDER_SGIS 0x812D +#endif + +/* GL_EXT_blend_minmax */ + +#ifndef GL_EXT_blend_minmax +#define GL_EXT_blend_minmax 1 +#define __GLEE_GL_EXT_blend_minmax 1 +/* Constants */ +#define GL_FUNC_ADD_EXT 0x8006 +#define GL_MIN_EXT 0x8007 +#define GL_MAX_EXT 0x8008 +#define GL_BLEND_EQUATION_EXT 0x8009 +#ifndef GLEE_H_DEFINED_glBlendEquationEXT +#define GLEE_H_DEFINED_glBlendEquationEXT + typedef void (APIENTRYP GLEEPFNGLBLENDEQUATIONEXTPROC) (GLenum mode); + GLEE_EXTERN GLEEPFNGLBLENDEQUATIONEXTPROC GLeeFuncPtr_glBlendEquationEXT; + #define glBlendEquationEXT GLeeFuncPtr_glBlendEquationEXT +#endif +#endif + +/* GL_EXT_blend_subtract */ + +#ifndef GL_EXT_blend_subtract +#define GL_EXT_blend_subtract 1 +#define __GLEE_GL_EXT_blend_subtract 1 +/* Constants */ +#define GL_FUNC_SUBTRACT_EXT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B +#endif + +/* GL_EXT_blend_logic_op */ + +#ifndef GL_EXT_blend_logic_op +#define GL_EXT_blend_logic_op 1 +#define __GLEE_GL_EXT_blend_logic_op 1 +/* Constants */ +#endif + +/* GL_SGIX_interlace */ + +#ifndef GL_SGIX_interlace +#define GL_SGIX_interlace 1 +#define __GLEE_GL_SGIX_interlace 1 +/* Constants */ +#define GL_INTERLACE_SGIX 0x8094 +#endif + +/* GL_SGIX_pixel_tiles */ + +#ifndef GL_SGIX_pixel_tiles +#define GL_SGIX_pixel_tiles 1 +#define __GLEE_GL_SGIX_pixel_tiles 1 +/* Constants */ +#define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E +#define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F +#define GL_PIXEL_TILE_WIDTH_SGIX 0x8140 +#define GL_PIXEL_TILE_HEIGHT_SGIX 0x8141 +#define GL_PIXEL_TILE_GRID_WIDTH_SGIX 0x8142 +#define GL_PIXEL_TILE_GRID_HEIGHT_SGIX 0x8143 +#define GL_PIXEL_TILE_GRID_DEPTH_SGIX 0x8144 +#define GL_PIXEL_TILE_CACHE_SIZE_SGIX 0x8145 +#endif + +/* GL_SGIS_texture_select */ + +#ifndef GL_SGIS_texture_select +#define GL_SGIS_texture_select 1 +#define __GLEE_GL_SGIS_texture_select 1 +/* Constants */ +#define GL_DUAL_ALPHA4_SGIS 0x8110 +#define GL_DUAL_ALPHA8_SGIS 0x8111 +#define GL_DUAL_ALPHA12_SGIS 0x8112 +#define GL_DUAL_ALPHA16_SGIS 0x8113 +#define GL_DUAL_LUMINANCE4_SGIS 0x8114 +#define GL_DUAL_LUMINANCE8_SGIS 0x8115 +#define GL_DUAL_LUMINANCE12_SGIS 0x8116 +#define GL_DUAL_LUMINANCE16_SGIS 0x8117 +#define GL_DUAL_INTENSITY4_SGIS 0x8118 +#define GL_DUAL_INTENSITY8_SGIS 0x8119 +#define GL_DUAL_INTENSITY12_SGIS 0x811A +#define GL_DUAL_INTENSITY16_SGIS 0x811B +#define GL_DUAL_LUMINANCE_ALPHA4_SGIS 0x811C +#define GL_DUAL_LUMINANCE_ALPHA8_SGIS 0x811D +#define GL_QUAD_ALPHA4_SGIS 0x811E +#define GL_QUAD_ALPHA8_SGIS 0x811F +#define GL_QUAD_LUMINANCE4_SGIS 0x8120 +#define GL_QUAD_LUMINANCE8_SGIS 0x8121 +#define GL_QUAD_INTENSITY4_SGIS 0x8122 +#define GL_QUAD_INTENSITY8_SGIS 0x8123 +#define GL_DUAL_TEXTURE_SELECT_SGIS 0x8124 +#define GL_QUAD_TEXTURE_SELECT_SGIS 0x8125 +#endif + +/* GL_SGIX_sprite */ + +#ifndef GL_SGIX_sprite +#define GL_SGIX_sprite 1 +#define __GLEE_GL_SGIX_sprite 1 +/* Constants */ +#define GL_SPRITE_SGIX 0x8148 +#define GL_SPRITE_MODE_SGIX 0x8149 +#define GL_SPRITE_AXIS_SGIX 0x814A +#define GL_SPRITE_TRANSLATION_SGIX 0x814B +#define GL_SPRITE_AXIAL_SGIX 0x814C +#define GL_SPRITE_OBJECT_ALIGNED_SGIX 0x814D +#define GL_SPRITE_EYE_ALIGNED_SGIX 0x814E +#ifndef GLEE_H_DEFINED_glSpriteParameterfSGIX +#define GLEE_H_DEFINED_glSpriteParameterfSGIX + typedef void (APIENTRYP GLEEPFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLSPRITEPARAMETERFSGIXPROC GLeeFuncPtr_glSpriteParameterfSGIX; + #define glSpriteParameterfSGIX GLeeFuncPtr_glSpriteParameterfSGIX +#endif +#ifndef GLEE_H_DEFINED_glSpriteParameterfvSGIX +#define GLEE_H_DEFINED_glSpriteParameterfvSGIX + typedef void (APIENTRYP GLEEPFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLSPRITEPARAMETERFVSGIXPROC GLeeFuncPtr_glSpriteParameterfvSGIX; + #define glSpriteParameterfvSGIX GLeeFuncPtr_glSpriteParameterfvSGIX +#endif +#ifndef GLEE_H_DEFINED_glSpriteParameteriSGIX +#define GLEE_H_DEFINED_glSpriteParameteriSGIX + typedef void (APIENTRYP GLEEPFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLSPRITEPARAMETERISGIXPROC GLeeFuncPtr_glSpriteParameteriSGIX; + #define glSpriteParameteriSGIX GLeeFuncPtr_glSpriteParameteriSGIX +#endif +#ifndef GLEE_H_DEFINED_glSpriteParameterivSGIX +#define GLEE_H_DEFINED_glSpriteParameterivSGIX + typedef void (APIENTRYP GLEEPFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLSPRITEPARAMETERIVSGIXPROC GLeeFuncPtr_glSpriteParameterivSGIX; + #define glSpriteParameterivSGIX GLeeFuncPtr_glSpriteParameterivSGIX +#endif +#endif + +/* GL_SGIX_texture_multi_buffer */ + +#ifndef GL_SGIX_texture_multi_buffer +#define GL_SGIX_texture_multi_buffer 1 +#define __GLEE_GL_SGIX_texture_multi_buffer 1 +/* Constants */ +#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E +#endif + +/* GL_EXT_point_parameters */ + +#ifndef GL_EXT_point_parameters +#define GL_EXT_point_parameters 1 +#define __GLEE_GL_EXT_point_parameters 1 +/* Constants */ +#define GL_POINT_SIZE_MIN_EXT 0x8126 +#define GL_POINT_SIZE_MAX_EXT 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 +#define GL_DISTANCE_ATTENUATION_EXT 0x8129 +#ifndef GLEE_H_DEFINED_glPointParameterfEXT +#define GLEE_H_DEFINED_glPointParameterfEXT + typedef void (APIENTRYP GLEEPFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLPOINTPARAMETERFEXTPROC GLeeFuncPtr_glPointParameterfEXT; + #define glPointParameterfEXT GLeeFuncPtr_glPointParameterfEXT +#endif +#ifndef GLEE_H_DEFINED_glPointParameterfvEXT +#define GLEE_H_DEFINED_glPointParameterfvEXT + typedef void (APIENTRYP GLEEPFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLPOINTPARAMETERFVEXTPROC GLeeFuncPtr_glPointParameterfvEXT; + #define glPointParameterfvEXT GLeeFuncPtr_glPointParameterfvEXT +#endif +#endif + +/* GL_SGIS_point_parameters */ + +#ifndef GL_SGIS_point_parameters +#define GL_SGIS_point_parameters 1 +#define __GLEE_GL_SGIS_point_parameters 1 +/* Constants */ +#define GL_POINT_SIZE_MIN_SGIS 0x8126 +#define GL_POINT_SIZE_MAX_SGIS 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128 +#define GL_DISTANCE_ATTENUATION_SGIS 0x8129 +#ifndef GLEE_H_DEFINED_glPointParameterfSGIS +#define GLEE_H_DEFINED_glPointParameterfSGIS + typedef void (APIENTRYP GLEEPFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLPOINTPARAMETERFSGISPROC GLeeFuncPtr_glPointParameterfSGIS; + #define glPointParameterfSGIS GLeeFuncPtr_glPointParameterfSGIS +#endif +#ifndef GLEE_H_DEFINED_glPointParameterfvSGIS +#define GLEE_H_DEFINED_glPointParameterfvSGIS + typedef void (APIENTRYP GLEEPFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLPOINTPARAMETERFVSGISPROC GLeeFuncPtr_glPointParameterfvSGIS; + #define glPointParameterfvSGIS GLeeFuncPtr_glPointParameterfvSGIS +#endif +#endif + +/* GL_SGIX_instruments */ + +#ifndef GL_SGIX_instruments +#define GL_SGIX_instruments 1 +#define __GLEE_GL_SGIX_instruments 1 +/* Constants */ +#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180 +#define GL_INSTRUMENT_MEASUREMENTS_SGIX 0x8181 +#ifndef GLEE_H_DEFINED_glGetInstrumentsSGIX +#define GLEE_H_DEFINED_glGetInstrumentsSGIX + typedef GLint (APIENTRYP GLEEPFNGLGETINSTRUMENTSSGIXPROC) (); + GLEE_EXTERN GLEEPFNGLGETINSTRUMENTSSGIXPROC GLeeFuncPtr_glGetInstrumentsSGIX; + #define glGetInstrumentsSGIX GLeeFuncPtr_glGetInstrumentsSGIX +#endif +#ifndef GLEE_H_DEFINED_glInstrumentsBufferSGIX +#define GLEE_H_DEFINED_glInstrumentsBufferSGIX + typedef void (APIENTRYP GLEEPFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint * buffer); + GLEE_EXTERN GLEEPFNGLINSTRUMENTSBUFFERSGIXPROC GLeeFuncPtr_glInstrumentsBufferSGIX; + #define glInstrumentsBufferSGIX GLeeFuncPtr_glInstrumentsBufferSGIX +#endif +#ifndef GLEE_H_DEFINED_glPollInstrumentsSGIX +#define GLEE_H_DEFINED_glPollInstrumentsSGIX + typedef GLint (APIENTRYP GLEEPFNGLPOLLINSTRUMENTSSGIXPROC) (GLint * marker_p); + GLEE_EXTERN GLEEPFNGLPOLLINSTRUMENTSSGIXPROC GLeeFuncPtr_glPollInstrumentsSGIX; + #define glPollInstrumentsSGIX GLeeFuncPtr_glPollInstrumentsSGIX +#endif +#ifndef GLEE_H_DEFINED_glReadInstrumentsSGIX +#define GLEE_H_DEFINED_glReadInstrumentsSGIX + typedef void (APIENTRYP GLEEPFNGLREADINSTRUMENTSSGIXPROC) (GLint marker); + GLEE_EXTERN GLEEPFNGLREADINSTRUMENTSSGIXPROC GLeeFuncPtr_glReadInstrumentsSGIX; + #define glReadInstrumentsSGIX GLeeFuncPtr_glReadInstrumentsSGIX +#endif +#ifndef GLEE_H_DEFINED_glStartInstrumentsSGIX +#define GLEE_H_DEFINED_glStartInstrumentsSGIX + typedef void (APIENTRYP GLEEPFNGLSTARTINSTRUMENTSSGIXPROC) (); + GLEE_EXTERN GLEEPFNGLSTARTINSTRUMENTSSGIXPROC GLeeFuncPtr_glStartInstrumentsSGIX; + #define glStartInstrumentsSGIX GLeeFuncPtr_glStartInstrumentsSGIX +#endif +#ifndef GLEE_H_DEFINED_glStopInstrumentsSGIX +#define GLEE_H_DEFINED_glStopInstrumentsSGIX + typedef void (APIENTRYP GLEEPFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker); + GLEE_EXTERN GLEEPFNGLSTOPINSTRUMENTSSGIXPROC GLeeFuncPtr_glStopInstrumentsSGIX; + #define glStopInstrumentsSGIX GLeeFuncPtr_glStopInstrumentsSGIX +#endif +#endif + +/* GL_SGIX_texture_scale_bias */ + +#ifndef GL_SGIX_texture_scale_bias +#define GL_SGIX_texture_scale_bias 1 +#define __GLEE_GL_SGIX_texture_scale_bias 1 +/* Constants */ +#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179 +#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A +#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B +#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C +#endif + +/* GL_SGIX_framezoom */ + +#ifndef GL_SGIX_framezoom +#define GL_SGIX_framezoom 1 +#define __GLEE_GL_SGIX_framezoom 1 +/* Constants */ +#define GL_FRAMEZOOM_SGIX 0x818B +#define GL_FRAMEZOOM_FACTOR_SGIX 0x818C +#define GL_MAX_FRAMEZOOM_FACTOR_SGIX 0x818D +#ifndef GLEE_H_DEFINED_glFrameZoomSGIX +#define GLEE_H_DEFINED_glFrameZoomSGIX + typedef void (APIENTRYP GLEEPFNGLFRAMEZOOMSGIXPROC) (GLint factor); + GLEE_EXTERN GLEEPFNGLFRAMEZOOMSGIXPROC GLeeFuncPtr_glFrameZoomSGIX; + #define glFrameZoomSGIX GLeeFuncPtr_glFrameZoomSGIX +#endif +#endif + +/* GL_SGIX_tag_sample_buffer */ + +#ifndef GL_SGIX_tag_sample_buffer +#define GL_SGIX_tag_sample_buffer 1 +#define __GLEE_GL_SGIX_tag_sample_buffer 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glTagSampleBufferSGIX +#define GLEE_H_DEFINED_glTagSampleBufferSGIX + typedef void (APIENTRYP GLEEPFNGLTAGSAMPLEBUFFERSGIXPROC) (); + GLEE_EXTERN GLEEPFNGLTAGSAMPLEBUFFERSGIXPROC GLeeFuncPtr_glTagSampleBufferSGIX; + #define glTagSampleBufferSGIX GLeeFuncPtr_glTagSampleBufferSGIX +#endif +#endif + +/* GL_FfdMaskSGIX */ + +#ifndef GL_FfdMaskSGIX +#define GL_FfdMaskSGIX 1 +#define __GLEE_GL_FfdMaskSGIX 1 +/* Constants */ +#define GL_TEXTURE_DEFORMATION_BIT_SGIX 0x00000001 +#define GL_GEOMETRY_DEFORMATION_BIT_SGIX 0x00000002 +#endif + +/* GL_SGIX_polynomial_ffd */ + +#ifndef GL_SGIX_polynomial_ffd +#define GL_SGIX_polynomial_ffd 1 +#define __GLEE_GL_SGIX_polynomial_ffd 1 +/* Constants */ +#define GL_GEOMETRY_DEFORMATION_SGIX 0x8194 +#define GL_TEXTURE_DEFORMATION_SGIX 0x8195 +#define GL_DEFORMATIONS_MASK_SGIX 0x8196 +#define GL_MAX_DEFORMATION_ORDER_SGIX 0x8197 +#ifndef GLEE_H_DEFINED_glDeformationMap3dSGIX +#define GLEE_H_DEFINED_glDeformationMap3dSGIX + typedef void (APIENTRYP GLEEPFNGLDEFORMATIONMAP3DSGIXPROC) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble * points); + GLEE_EXTERN GLEEPFNGLDEFORMATIONMAP3DSGIXPROC GLeeFuncPtr_glDeformationMap3dSGIX; + #define glDeformationMap3dSGIX GLeeFuncPtr_glDeformationMap3dSGIX +#endif +#ifndef GLEE_H_DEFINED_glDeformationMap3fSGIX +#define GLEE_H_DEFINED_glDeformationMap3fSGIX + typedef void (APIENTRYP GLEEPFNGLDEFORMATIONMAP3FSGIXPROC) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat * points); + GLEE_EXTERN GLEEPFNGLDEFORMATIONMAP3FSGIXPROC GLeeFuncPtr_glDeformationMap3fSGIX; + #define glDeformationMap3fSGIX GLeeFuncPtr_glDeformationMap3fSGIX +#endif +#ifndef GLEE_H_DEFINED_glDeformSGIX +#define GLEE_H_DEFINED_glDeformSGIX + typedef void (APIENTRYP GLEEPFNGLDEFORMSGIXPROC) (GLbitfield mask); + GLEE_EXTERN GLEEPFNGLDEFORMSGIXPROC GLeeFuncPtr_glDeformSGIX; + #define glDeformSGIX GLeeFuncPtr_glDeformSGIX +#endif +#ifndef GLEE_H_DEFINED_glLoadIdentityDeformationMapSGIX +#define GLEE_H_DEFINED_glLoadIdentityDeformationMapSGIX + typedef void (APIENTRYP GLEEPFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC) (GLbitfield mask); + GLEE_EXTERN GLEEPFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC GLeeFuncPtr_glLoadIdentityDeformationMapSGIX; + #define glLoadIdentityDeformationMapSGIX GLeeFuncPtr_glLoadIdentityDeformationMapSGIX +#endif +#endif + +/* GL_SGIX_reference_plane */ + +#ifndef GL_SGIX_reference_plane +#define GL_SGIX_reference_plane 1 +#define __GLEE_GL_SGIX_reference_plane 1 +/* Constants */ +#define GL_REFERENCE_PLANE_SGIX 0x817D +#define GL_REFERENCE_PLANE_EQUATION_SGIX 0x817E +#ifndef GLEE_H_DEFINED_glReferencePlaneSGIX +#define GLEE_H_DEFINED_glReferencePlaneSGIX + typedef void (APIENTRYP GLEEPFNGLREFERENCEPLANESGIXPROC) (const GLdouble * equation); + GLEE_EXTERN GLEEPFNGLREFERENCEPLANESGIXPROC GLeeFuncPtr_glReferencePlaneSGIX; + #define glReferencePlaneSGIX GLeeFuncPtr_glReferencePlaneSGIX +#endif +#endif + +/* GL_SGIX_flush_raster */ + +#ifndef GL_SGIX_flush_raster +#define GL_SGIX_flush_raster 1 +#define __GLEE_GL_SGIX_flush_raster 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glFlushRasterSGIX +#define GLEE_H_DEFINED_glFlushRasterSGIX + typedef void (APIENTRYP GLEEPFNGLFLUSHRASTERSGIXPROC) (); + GLEE_EXTERN GLEEPFNGLFLUSHRASTERSGIXPROC GLeeFuncPtr_glFlushRasterSGIX; + #define glFlushRasterSGIX GLeeFuncPtr_glFlushRasterSGIX +#endif +#endif + +/* GL_SGIX_depth_texture */ + +#ifndef GL_SGIX_depth_texture +#define GL_SGIX_depth_texture 1 +#define __GLEE_GL_SGIX_depth_texture 1 +/* Constants */ +#define GL_DEPTH_COMPONENT16_SGIX 0x81A5 +#define GL_DEPTH_COMPONENT24_SGIX 0x81A6 +#define GL_DEPTH_COMPONENT32_SGIX 0x81A7 +#endif + +/* GL_SGIS_fog_function */ + +#ifndef GL_SGIS_fog_function +#define GL_SGIS_fog_function 1 +#define __GLEE_GL_SGIS_fog_function 1 +/* Constants */ +#define GL_FOG_FUNC_SGIS 0x812A +#define GL_FOG_FUNC_POINTS_SGIS 0x812B +#define GL_MAX_FOG_FUNC_POINTS_SGIS 0x812C +#ifndef GLEE_H_DEFINED_glFogFuncSGIS +#define GLEE_H_DEFINED_glFogFuncSGIS + typedef void (APIENTRYP GLEEPFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat * points); + GLEE_EXTERN GLEEPFNGLFOGFUNCSGISPROC GLeeFuncPtr_glFogFuncSGIS; + #define glFogFuncSGIS GLeeFuncPtr_glFogFuncSGIS +#endif +#ifndef GLEE_H_DEFINED_glGetFogFuncSGIS +#define GLEE_H_DEFINED_glGetFogFuncSGIS + typedef void (APIENTRYP GLEEPFNGLGETFOGFUNCSGISPROC) (GLfloat * points); + GLEE_EXTERN GLEEPFNGLGETFOGFUNCSGISPROC GLeeFuncPtr_glGetFogFuncSGIS; + #define glGetFogFuncSGIS GLeeFuncPtr_glGetFogFuncSGIS +#endif +#endif + +/* GL_SGIX_fog_offset */ + +#ifndef GL_SGIX_fog_offset +#define GL_SGIX_fog_offset 1 +#define __GLEE_GL_SGIX_fog_offset 1 +/* Constants */ +#define GL_FOG_OFFSET_SGIX 0x8198 +#define GL_FOG_OFFSET_VALUE_SGIX 0x8199 +#endif + +/* GL_HP_image_transform */ + +#ifndef GL_HP_image_transform +#define GL_HP_image_transform 1 +#define __GLEE_GL_HP_image_transform 1 +/* Constants */ +#define GL_IMAGE_SCALE_X_HP 0x8155 +#define GL_IMAGE_SCALE_Y_HP 0x8156 +#define GL_IMAGE_TRANSLATE_X_HP 0x8157 +#define GL_IMAGE_TRANSLATE_Y_HP 0x8158 +#define GL_IMAGE_ROTATE_ANGLE_HP 0x8159 +#define GL_IMAGE_ROTATE_ORIGIN_X_HP 0x815A +#define GL_IMAGE_ROTATE_ORIGIN_Y_HP 0x815B +#define GL_IMAGE_MAG_FILTER_HP 0x815C +#define GL_IMAGE_MIN_FILTER_HP 0x815D +#define GL_IMAGE_CUBIC_WEIGHT_HP 0x815E +#define GL_CUBIC_HP 0x815F +#define GL_AVERAGE_HP 0x8160 +#define GL_IMAGE_TRANSFORM_2D_HP 0x8161 +#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162 +#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163 +#ifndef GLEE_H_DEFINED_glImageTransformParameteriHP +#define GLEE_H_DEFINED_glImageTransformParameteriHP + typedef void (APIENTRYP GLEEPFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLIMAGETRANSFORMPARAMETERIHPPROC GLeeFuncPtr_glImageTransformParameteriHP; + #define glImageTransformParameteriHP GLeeFuncPtr_glImageTransformParameteriHP +#endif +#ifndef GLEE_H_DEFINED_glImageTransformParameterfHP +#define GLEE_H_DEFINED_glImageTransformParameterfHP + typedef void (APIENTRYP GLEEPFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLIMAGETRANSFORMPARAMETERFHPPROC GLeeFuncPtr_glImageTransformParameterfHP; + #define glImageTransformParameterfHP GLeeFuncPtr_glImageTransformParameterfHP +#endif +#ifndef GLEE_H_DEFINED_glImageTransformParameterivHP +#define GLEE_H_DEFINED_glImageTransformParameterivHP + typedef void (APIENTRYP GLEEPFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLIMAGETRANSFORMPARAMETERIVHPPROC GLeeFuncPtr_glImageTransformParameterivHP; + #define glImageTransformParameterivHP GLeeFuncPtr_glImageTransformParameterivHP +#endif +#ifndef GLEE_H_DEFINED_glImageTransformParameterfvHP +#define GLEE_H_DEFINED_glImageTransformParameterfvHP + typedef void (APIENTRYP GLEEPFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLIMAGETRANSFORMPARAMETERFVHPPROC GLeeFuncPtr_glImageTransformParameterfvHP; + #define glImageTransformParameterfvHP GLeeFuncPtr_glImageTransformParameterfvHP +#endif +#ifndef GLEE_H_DEFINED_glGetImageTransformParameterivHP +#define GLEE_H_DEFINED_glGetImageTransformParameterivHP + typedef void (APIENTRYP GLEEPFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC GLeeFuncPtr_glGetImageTransformParameterivHP; + #define glGetImageTransformParameterivHP GLeeFuncPtr_glGetImageTransformParameterivHP +#endif +#ifndef GLEE_H_DEFINED_glGetImageTransformParameterfvHP +#define GLEE_H_DEFINED_glGetImageTransformParameterfvHP + typedef void (APIENTRYP GLEEPFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC GLeeFuncPtr_glGetImageTransformParameterfvHP; + #define glGetImageTransformParameterfvHP GLeeFuncPtr_glGetImageTransformParameterfvHP +#endif +#endif + +/* GL_HP_convolution_border_modes */ + +#ifndef GL_HP_convolution_border_modes +#define GL_HP_convolution_border_modes 1 +#define __GLEE_GL_HP_convolution_border_modes 1 +/* Constants */ +#define GL_IGNORE_BORDER_HP 0x8150 +#define GL_CONSTANT_BORDER_HP 0x8151 +#define GL_REPLICATE_BORDER_HP 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR_HP 0x8154 +#endif + +/* GL_INGR_palette_buffer */ + +#ifndef GL_INGR_palette_buffer +#define GL_INGR_palette_buffer 1 +#define __GLEE_GL_INGR_palette_buffer 1 +/* Constants */ +#endif + +/* GL_SGIX_texture_add_env */ + +#ifndef GL_SGIX_texture_add_env +#define GL_SGIX_texture_add_env 1 +#define __GLEE_GL_SGIX_texture_add_env 1 +/* Constants */ +#define GL_TEXTURE_ENV_BIAS_SGIX 0x80BE +#endif + +/* GL_EXT_color_subtable */ + +#ifndef GL_EXT_color_subtable +#define GL_EXT_color_subtable 1 +#define __GLEE_GL_EXT_color_subtable 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glColorSubTableEXT +#define GLEE_H_DEFINED_glColorSubTableEXT + typedef void (APIENTRYP GLEEPFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLCOLORSUBTABLEEXTPROC GLeeFuncPtr_glColorSubTableEXT; + #define glColorSubTableEXT GLeeFuncPtr_glColorSubTableEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyColorSubTableEXT +#define GLEE_H_DEFINED_glCopyColorSubTableEXT + typedef void (APIENTRYP GLEEPFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); + GLEE_EXTERN GLEEPFNGLCOPYCOLORSUBTABLEEXTPROC GLeeFuncPtr_glCopyColorSubTableEXT; + #define glCopyColorSubTableEXT GLeeFuncPtr_glCopyColorSubTableEXT +#endif +#endif + +/* GL_PGI_vertex_hints */ + +#ifndef GL_PGI_vertex_hints +#define GL_PGI_vertex_hints 1 +#define __GLEE_GL_PGI_vertex_hints 1 +/* Constants */ +#define GL_VERTEX_DATA_HINT_PGI 0x1A22A +#define GL_VERTEX_CONSISTENT_HINT_PGI 0x1A22B +#define GL_MATERIAL_SIDE_HINT_PGI 0x1A22C +#define GL_MAX_VERTEX_HINT_PGI 0x1A22D +#define GL_COLOR3_BIT_PGI 0x00010000 +#define GL_COLOR4_BIT_PGI 0x00020000 +#define GL_EDGEFLAG_BIT_PGI 0x00040000 +#define GL_INDEX_BIT_PGI 0x00080000 +#define GL_MAT_AMBIENT_BIT_PGI 0x00100000 +#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000 +#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000 +#define GL_MAT_EMISSION_BIT_PGI 0x00800000 +#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000 +#define GL_MAT_SHININESS_BIT_PGI 0x02000000 +#define GL_MAT_SPECULAR_BIT_PGI 0x04000000 +#define GL_NORMAL_BIT_PGI 0x08000000 +#define GL_TEXCOORD1_BIT_PGI 0x10000000 +#define GL_TEXCOORD2_BIT_PGI 0x20000000 +#define GL_TEXCOORD3_BIT_PGI 0x40000000 +#define GL_TEXCOORD4_BIT_PGI 0x80000000 +#define GL_VERTEX23_BIT_PGI 0x00000004 +#define GL_VERTEX4_BIT_PGI 0x00000008 +#endif + +/* GL_PGI_misc_hints */ + +#ifndef GL_PGI_misc_hints +#define GL_PGI_misc_hints 1 +#define __GLEE_GL_PGI_misc_hints 1 +/* Constants */ +#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8 +#define GL_CONSERVE_MEMORY_HINT_PGI 0x1A1FD +#define GL_RECLAIM_MEMORY_HINT_PGI 0x1A1FE +#define GL_NATIVE_GRAPHICS_HANDLE_PGI 0x1A202 +#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203 +#define GL_NATIVE_GRAPHICS_END_HINT_PGI 0x1A204 +#define GL_ALWAYS_FAST_HINT_PGI 0x1A20C +#define GL_ALWAYS_SOFT_HINT_PGI 0x1A20D +#define GL_ALLOW_DRAW_OBJ_HINT_PGI 0x1A20E +#define GL_ALLOW_DRAW_WIN_HINT_PGI 0x1A20F +#define GL_ALLOW_DRAW_FRG_HINT_PGI 0x1A210 +#define GL_ALLOW_DRAW_MEM_HINT_PGI 0x1A211 +#define GL_STRICT_DEPTHFUNC_HINT_PGI 0x1A216 +#define GL_STRICT_LIGHTING_HINT_PGI 0x1A217 +#define GL_STRICT_SCISSOR_HINT_PGI 0x1A218 +#define GL_FULL_STIPPLE_HINT_PGI 0x1A219 +#define GL_CLIP_NEAR_HINT_PGI 0x1A220 +#define GL_CLIP_FAR_HINT_PGI 0x1A221 +#define GL_WIDE_LINE_HINT_PGI 0x1A222 +#define GL_BACK_NORMALS_HINT_PGI 0x1A223 +#ifndef GLEE_H_DEFINED_glHintPGI +#define GLEE_H_DEFINED_glHintPGI + typedef void (APIENTRYP GLEEPFNGLHINTPGIPROC) (GLenum target, GLint mode); + GLEE_EXTERN GLEEPFNGLHINTPGIPROC GLeeFuncPtr_glHintPGI; + #define glHintPGI GLeeFuncPtr_glHintPGI +#endif +#endif + +/* GL_EXT_paletted_texture */ + +#ifndef GL_EXT_paletted_texture +#define GL_EXT_paletted_texture 1 +#define __GLEE_GL_EXT_paletted_texture 1 +/* Constants */ +#define GL_COLOR_INDEX1_EXT 0x80E2 +#define GL_COLOR_INDEX2_EXT 0x80E3 +#define GL_COLOR_INDEX4_EXT 0x80E4 +#define GL_COLOR_INDEX8_EXT 0x80E5 +#define GL_COLOR_INDEX12_EXT 0x80E6 +#define GL_COLOR_INDEX16_EXT 0x80E7 +#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED +#ifndef GLEE_H_DEFINED_glColorTableEXT +#define GLEE_H_DEFINED_glColorTableEXT + typedef void (APIENTRYP GLEEPFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid * table); + GLEE_EXTERN GLEEPFNGLCOLORTABLEEXTPROC GLeeFuncPtr_glColorTableEXT; + #define glColorTableEXT GLeeFuncPtr_glColorTableEXT +#endif +#ifndef GLEE_H_DEFINED_glGetColorTableEXT +#define GLEE_H_DEFINED_glGetColorTableEXT + typedef void (APIENTRYP GLEEPFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid * data); + GLEE_EXTERN GLEEPFNGLGETCOLORTABLEEXTPROC GLeeFuncPtr_glGetColorTableEXT; + #define glGetColorTableEXT GLeeFuncPtr_glGetColorTableEXT +#endif +#ifndef GLEE_H_DEFINED_glGetColorTableParameterivEXT +#define GLEE_H_DEFINED_glGetColorTableParameterivEXT + typedef void (APIENTRYP GLEEPFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETCOLORTABLEPARAMETERIVEXTPROC GLeeFuncPtr_glGetColorTableParameterivEXT; + #define glGetColorTableParameterivEXT GLeeFuncPtr_glGetColorTableParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetColorTableParameterfvEXT +#define GLEE_H_DEFINED_glGetColorTableParameterfvEXT + typedef void (APIENTRYP GLEEPFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETCOLORTABLEPARAMETERFVEXTPROC GLeeFuncPtr_glGetColorTableParameterfvEXT; + #define glGetColorTableParameterfvEXT GLeeFuncPtr_glGetColorTableParameterfvEXT +#endif +#endif + +/* GL_EXT_clip_volume_hint */ + +#ifndef GL_EXT_clip_volume_hint +#define GL_EXT_clip_volume_hint 1 +#define __GLEE_GL_EXT_clip_volume_hint 1 +/* Constants */ +#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0 +#endif + +/* GL_SGIX_list_priority */ + +#ifndef GL_SGIX_list_priority +#define GL_SGIX_list_priority 1 +#define __GLEE_GL_SGIX_list_priority 1 +/* Constants */ +#define GL_LIST_PRIORITY_SGIX 0x8182 +#ifndef GLEE_H_DEFINED_glGetListParameterfvSGIX +#define GLEE_H_DEFINED_glGetListParameterfvSGIX + typedef void (APIENTRYP GLEEPFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETLISTPARAMETERFVSGIXPROC GLeeFuncPtr_glGetListParameterfvSGIX; + #define glGetListParameterfvSGIX GLeeFuncPtr_glGetListParameterfvSGIX +#endif +#ifndef GLEE_H_DEFINED_glGetListParameterivSGIX +#define GLEE_H_DEFINED_glGetListParameterivSGIX + typedef void (APIENTRYP GLEEPFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETLISTPARAMETERIVSGIXPROC GLeeFuncPtr_glGetListParameterivSGIX; + #define glGetListParameterivSGIX GLeeFuncPtr_glGetListParameterivSGIX +#endif +#ifndef GLEE_H_DEFINED_glListParameterfSGIX +#define GLEE_H_DEFINED_glListParameterfSGIX + typedef void (APIENTRYP GLEEPFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLLISTPARAMETERFSGIXPROC GLeeFuncPtr_glListParameterfSGIX; + #define glListParameterfSGIX GLeeFuncPtr_glListParameterfSGIX +#endif +#ifndef GLEE_H_DEFINED_glListParameterfvSGIX +#define GLEE_H_DEFINED_glListParameterfvSGIX + typedef void (APIENTRYP GLEEPFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLLISTPARAMETERFVSGIXPROC GLeeFuncPtr_glListParameterfvSGIX; + #define glListParameterfvSGIX GLeeFuncPtr_glListParameterfvSGIX +#endif +#ifndef GLEE_H_DEFINED_glListParameteriSGIX +#define GLEE_H_DEFINED_glListParameteriSGIX + typedef void (APIENTRYP GLEEPFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLLISTPARAMETERISGIXPROC GLeeFuncPtr_glListParameteriSGIX; + #define glListParameteriSGIX GLeeFuncPtr_glListParameteriSGIX +#endif +#ifndef GLEE_H_DEFINED_glListParameterivSGIX +#define GLEE_H_DEFINED_glListParameterivSGIX + typedef void (APIENTRYP GLEEPFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLLISTPARAMETERIVSGIXPROC GLeeFuncPtr_glListParameterivSGIX; + #define glListParameterivSGIX GLeeFuncPtr_glListParameterivSGIX +#endif +#endif + +/* GL_SGIX_ir_instrument1 */ + +#ifndef GL_SGIX_ir_instrument1 +#define GL_SGIX_ir_instrument1 1 +#define __GLEE_GL_SGIX_ir_instrument1 1 +/* Constants */ +#define GL_IR_INSTRUMENT1_SGIX 0x817F +#endif + +/* GL_SGIX_calligraphic_fragment */ + +#ifndef GL_SGIX_calligraphic_fragment +#define GL_SGIX_calligraphic_fragment 1 +#define __GLEE_GL_SGIX_calligraphic_fragment 1 +/* Constants */ +#define GL_CALLIGRAPHIC_FRAGMENT_SGIX 0x8183 +#endif + +/* GL_SGIX_texture_lod_bias */ + +#ifndef GL_SGIX_texture_lod_bias +#define GL_SGIX_texture_lod_bias 1 +#define __GLEE_GL_SGIX_texture_lod_bias 1 +/* Constants */ +#define GL_TEXTURE_LOD_BIAS_S_SGIX 0x818E +#define GL_TEXTURE_LOD_BIAS_T_SGIX 0x818F +#define GL_TEXTURE_LOD_BIAS_R_SGIX 0x8190 +#endif + +/* GL_SGIX_shadow_ambient */ + +#ifndef GL_SGIX_shadow_ambient +#define GL_SGIX_shadow_ambient 1 +#define __GLEE_GL_SGIX_shadow_ambient 1 +/* Constants */ +#define GL_SHADOW_AMBIENT_SGIX 0x80BF +#endif + +/* GL_EXT_index_texture */ + +#ifndef GL_EXT_index_texture +#define GL_EXT_index_texture 1 +#define __GLEE_GL_EXT_index_texture 1 +/* Constants */ +#endif + +/* GL_EXT_index_material */ + +#ifndef GL_EXT_index_material +#define GL_EXT_index_material 1 +#define __GLEE_GL_EXT_index_material 1 +/* Constants */ +#define GL_INDEX_MATERIAL_EXT 0x81B8 +#define GL_INDEX_MATERIAL_PARAMETER_EXT 0x81B9 +#define GL_INDEX_MATERIAL_FACE_EXT 0x81BA +#ifndef GLEE_H_DEFINED_glIndexMaterialEXT +#define GLEE_H_DEFINED_glIndexMaterialEXT + typedef void (APIENTRYP GLEEPFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode); + GLEE_EXTERN GLEEPFNGLINDEXMATERIALEXTPROC GLeeFuncPtr_glIndexMaterialEXT; + #define glIndexMaterialEXT GLeeFuncPtr_glIndexMaterialEXT +#endif +#endif + +/* GL_EXT_index_func */ + +#ifndef GL_EXT_index_func +#define GL_EXT_index_func 1 +#define __GLEE_GL_EXT_index_func 1 +/* Constants */ +#define GL_INDEX_TEST_EXT 0x81B5 +#define GL_INDEX_TEST_FUNC_EXT 0x81B6 +#define GL_INDEX_TEST_REF_EXT 0x81B7 +#ifndef GLEE_H_DEFINED_glIndexFuncEXT +#define GLEE_H_DEFINED_glIndexFuncEXT + typedef void (APIENTRYP GLEEPFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref); + GLEE_EXTERN GLEEPFNGLINDEXFUNCEXTPROC GLeeFuncPtr_glIndexFuncEXT; + #define glIndexFuncEXT GLeeFuncPtr_glIndexFuncEXT +#endif +#endif + +/* GL_EXT_index_array_formats */ + +#ifndef GL_EXT_index_array_formats +#define GL_EXT_index_array_formats 1 +#define __GLEE_GL_EXT_index_array_formats 1 +/* Constants */ +#define GL_IUI_V2F_EXT 0x81AD +#define GL_IUI_V3F_EXT 0x81AE +#define GL_IUI_N3F_V2F_EXT 0x81AF +#define GL_IUI_N3F_V3F_EXT 0x81B0 +#define GL_T2F_IUI_V2F_EXT 0x81B1 +#define GL_T2F_IUI_V3F_EXT 0x81B2 +#define GL_T2F_IUI_N3F_V2F_EXT 0x81B3 +#define GL_T2F_IUI_N3F_V3F_EXT 0x81B4 +#endif + +/* GL_EXT_compiled_vertex_array */ + +#ifndef GL_EXT_compiled_vertex_array +#define GL_EXT_compiled_vertex_array 1 +#define __GLEE_GL_EXT_compiled_vertex_array 1 +/* Constants */ +#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8 +#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9 +#ifndef GLEE_H_DEFINED_glLockArraysEXT +#define GLEE_H_DEFINED_glLockArraysEXT + typedef void (APIENTRYP GLEEPFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count); + GLEE_EXTERN GLEEPFNGLLOCKARRAYSEXTPROC GLeeFuncPtr_glLockArraysEXT; + #define glLockArraysEXT GLeeFuncPtr_glLockArraysEXT +#endif +#ifndef GLEE_H_DEFINED_glUnlockArraysEXT +#define GLEE_H_DEFINED_glUnlockArraysEXT + typedef void (APIENTRYP GLEEPFNGLUNLOCKARRAYSEXTPROC) (); + GLEE_EXTERN GLEEPFNGLUNLOCKARRAYSEXTPROC GLeeFuncPtr_glUnlockArraysEXT; + #define glUnlockArraysEXT GLeeFuncPtr_glUnlockArraysEXT +#endif +#endif + +/* GL_EXT_cull_vertex */ + +#ifndef GL_EXT_cull_vertex +#define GL_EXT_cull_vertex 1 +#define __GLEE_GL_EXT_cull_vertex 1 +/* Constants */ +#define GL_CULL_VERTEX_EXT 0x81AA +#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB +#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC +#ifndef GLEE_H_DEFINED_glCullParameterdvEXT +#define GLEE_H_DEFINED_glCullParameterdvEXT + typedef void (APIENTRYP GLEEPFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble * params); + GLEE_EXTERN GLEEPFNGLCULLPARAMETERDVEXTPROC GLeeFuncPtr_glCullParameterdvEXT; + #define glCullParameterdvEXT GLeeFuncPtr_glCullParameterdvEXT +#endif +#ifndef GLEE_H_DEFINED_glCullParameterfvEXT +#define GLEE_H_DEFINED_glCullParameterfvEXT + typedef void (APIENTRYP GLEEPFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLCULLPARAMETERFVEXTPROC GLeeFuncPtr_glCullParameterfvEXT; + #define glCullParameterfvEXT GLeeFuncPtr_glCullParameterfvEXT +#endif +#endif + +/* GL_SGIX_ycrcb */ + +#ifndef GL_SGIX_ycrcb +#define GL_SGIX_ycrcb 1 +#define __GLEE_GL_SGIX_ycrcb 1 +/* Constants */ +#define GL_YCRCB_422_SGIX 0x81BB +#define GL_YCRCB_444_SGIX 0x81BC +#endif + +/* GL_SGIX_fragment_lighting */ + +#ifndef GL_SGIX_fragment_lighting +#define GL_SGIX_fragment_lighting 1 +#define __GLEE_GL_SGIX_fragment_lighting 1 +/* Constants */ +#define GL_FRAGMENT_LIGHTING_SGIX 0x8400 +#define GL_FRAGMENT_COLOR_MATERIAL_SGIX 0x8401 +#define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402 +#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403 +#define GL_MAX_FRAGMENT_LIGHTS_SGIX 0x8404 +#define GL_MAX_ACTIVE_LIGHTS_SGIX 0x8405 +#define GL_CURRENT_RASTER_NORMAL_SGIX 0x8406 +#define GL_LIGHT_ENV_MODE_SGIX 0x8407 +#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408 +#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409 +#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A +#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B +#define GL_FRAGMENT_LIGHT0_SGIX 0x840C +#define GL_FRAGMENT_LIGHT1_SGIX 0x840D +#define GL_FRAGMENT_LIGHT2_SGIX 0x840E +#define GL_FRAGMENT_LIGHT3_SGIX 0x840F +#define GL_FRAGMENT_LIGHT4_SGIX 0x8410 +#define GL_FRAGMENT_LIGHT5_SGIX 0x8411 +#define GL_FRAGMENT_LIGHT6_SGIX 0x8412 +#define GL_FRAGMENT_LIGHT7_SGIX 0x8413 +#ifndef GLEE_H_DEFINED_glFragmentColorMaterialSGIX +#define GLEE_H_DEFINED_glFragmentColorMaterialSGIX + typedef void (APIENTRYP GLEEPFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode); + GLEE_EXTERN GLEEPFNGLFRAGMENTCOLORMATERIALSGIXPROC GLeeFuncPtr_glFragmentColorMaterialSGIX; + #define glFragmentColorMaterialSGIX GLeeFuncPtr_glFragmentColorMaterialSGIX +#endif +#ifndef GLEE_H_DEFINED_glFragmentLightfSGIX +#define GLEE_H_DEFINED_glFragmentLightfSGIX + typedef void (APIENTRYP GLEEPFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLFRAGMENTLIGHTFSGIXPROC GLeeFuncPtr_glFragmentLightfSGIX; + #define glFragmentLightfSGIX GLeeFuncPtr_glFragmentLightfSGIX +#endif +#ifndef GLEE_H_DEFINED_glFragmentLightfvSGIX +#define GLEE_H_DEFINED_glFragmentLightfvSGIX + typedef void (APIENTRYP GLEEPFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLFRAGMENTLIGHTFVSGIXPROC GLeeFuncPtr_glFragmentLightfvSGIX; + #define glFragmentLightfvSGIX GLeeFuncPtr_glFragmentLightfvSGIX +#endif +#ifndef GLEE_H_DEFINED_glFragmentLightiSGIX +#define GLEE_H_DEFINED_glFragmentLightiSGIX + typedef void (APIENTRYP GLEEPFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLFRAGMENTLIGHTISGIXPROC GLeeFuncPtr_glFragmentLightiSGIX; + #define glFragmentLightiSGIX GLeeFuncPtr_glFragmentLightiSGIX +#endif +#ifndef GLEE_H_DEFINED_glFragmentLightivSGIX +#define GLEE_H_DEFINED_glFragmentLightivSGIX + typedef void (APIENTRYP GLEEPFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLFRAGMENTLIGHTIVSGIXPROC GLeeFuncPtr_glFragmentLightivSGIX; + #define glFragmentLightivSGIX GLeeFuncPtr_glFragmentLightivSGIX +#endif +#ifndef GLEE_H_DEFINED_glFragmentLightModelfSGIX +#define GLEE_H_DEFINED_glFragmentLightModelfSGIX + typedef void (APIENTRYP GLEEPFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLFRAGMENTLIGHTMODELFSGIXPROC GLeeFuncPtr_glFragmentLightModelfSGIX; + #define glFragmentLightModelfSGIX GLeeFuncPtr_glFragmentLightModelfSGIX +#endif +#ifndef GLEE_H_DEFINED_glFragmentLightModelfvSGIX +#define GLEE_H_DEFINED_glFragmentLightModelfvSGIX + typedef void (APIENTRYP GLEEPFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLFRAGMENTLIGHTMODELFVSGIXPROC GLeeFuncPtr_glFragmentLightModelfvSGIX; + #define glFragmentLightModelfvSGIX GLeeFuncPtr_glFragmentLightModelfvSGIX +#endif +#ifndef GLEE_H_DEFINED_glFragmentLightModeliSGIX +#define GLEE_H_DEFINED_glFragmentLightModeliSGIX + typedef void (APIENTRYP GLEEPFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLFRAGMENTLIGHTMODELISGIXPROC GLeeFuncPtr_glFragmentLightModeliSGIX; + #define glFragmentLightModeliSGIX GLeeFuncPtr_glFragmentLightModeliSGIX +#endif +#ifndef GLEE_H_DEFINED_glFragmentLightModelivSGIX +#define GLEE_H_DEFINED_glFragmentLightModelivSGIX + typedef void (APIENTRYP GLEEPFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLFRAGMENTLIGHTMODELIVSGIXPROC GLeeFuncPtr_glFragmentLightModelivSGIX; + #define glFragmentLightModelivSGIX GLeeFuncPtr_glFragmentLightModelivSGIX +#endif +#ifndef GLEE_H_DEFINED_glFragmentMaterialfSGIX +#define GLEE_H_DEFINED_glFragmentMaterialfSGIX + typedef void (APIENTRYP GLEEPFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLFRAGMENTMATERIALFSGIXPROC GLeeFuncPtr_glFragmentMaterialfSGIX; + #define glFragmentMaterialfSGIX GLeeFuncPtr_glFragmentMaterialfSGIX +#endif +#ifndef GLEE_H_DEFINED_glFragmentMaterialfvSGIX +#define GLEE_H_DEFINED_glFragmentMaterialfvSGIX + typedef void (APIENTRYP GLEEPFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLFRAGMENTMATERIALFVSGIXPROC GLeeFuncPtr_glFragmentMaterialfvSGIX; + #define glFragmentMaterialfvSGIX GLeeFuncPtr_glFragmentMaterialfvSGIX +#endif +#ifndef GLEE_H_DEFINED_glFragmentMaterialiSGIX +#define GLEE_H_DEFINED_glFragmentMaterialiSGIX + typedef void (APIENTRYP GLEEPFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLFRAGMENTMATERIALISGIXPROC GLeeFuncPtr_glFragmentMaterialiSGIX; + #define glFragmentMaterialiSGIX GLeeFuncPtr_glFragmentMaterialiSGIX +#endif +#ifndef GLEE_H_DEFINED_glFragmentMaterialivSGIX +#define GLEE_H_DEFINED_glFragmentMaterialivSGIX + typedef void (APIENTRYP GLEEPFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLFRAGMENTMATERIALIVSGIXPROC GLeeFuncPtr_glFragmentMaterialivSGIX; + #define glFragmentMaterialivSGIX GLeeFuncPtr_glFragmentMaterialivSGIX +#endif +#ifndef GLEE_H_DEFINED_glGetFragmentLightfvSGIX +#define GLEE_H_DEFINED_glGetFragmentLightfvSGIX + typedef void (APIENTRYP GLEEPFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETFRAGMENTLIGHTFVSGIXPROC GLeeFuncPtr_glGetFragmentLightfvSGIX; + #define glGetFragmentLightfvSGIX GLeeFuncPtr_glGetFragmentLightfvSGIX +#endif +#ifndef GLEE_H_DEFINED_glGetFragmentLightivSGIX +#define GLEE_H_DEFINED_glGetFragmentLightivSGIX + typedef void (APIENTRYP GLEEPFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETFRAGMENTLIGHTIVSGIXPROC GLeeFuncPtr_glGetFragmentLightivSGIX; + #define glGetFragmentLightivSGIX GLeeFuncPtr_glGetFragmentLightivSGIX +#endif +#ifndef GLEE_H_DEFINED_glGetFragmentMaterialfvSGIX +#define GLEE_H_DEFINED_glGetFragmentMaterialfvSGIX + typedef void (APIENTRYP GLEEPFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETFRAGMENTMATERIALFVSGIXPROC GLeeFuncPtr_glGetFragmentMaterialfvSGIX; + #define glGetFragmentMaterialfvSGIX GLeeFuncPtr_glGetFragmentMaterialfvSGIX +#endif +#ifndef GLEE_H_DEFINED_glGetFragmentMaterialivSGIX +#define GLEE_H_DEFINED_glGetFragmentMaterialivSGIX + typedef void (APIENTRYP GLEEPFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETFRAGMENTMATERIALIVSGIXPROC GLeeFuncPtr_glGetFragmentMaterialivSGIX; + #define glGetFragmentMaterialivSGIX GLeeFuncPtr_glGetFragmentMaterialivSGIX +#endif +#ifndef GLEE_H_DEFINED_glLightEnviSGIX +#define GLEE_H_DEFINED_glLightEnviSGIX + typedef void (APIENTRYP GLEEPFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLLIGHTENVISGIXPROC GLeeFuncPtr_glLightEnviSGIX; + #define glLightEnviSGIX GLeeFuncPtr_glLightEnviSGIX +#endif +#endif + +/* GL_IBM_rasterpos_clip */ + +#ifndef GL_IBM_rasterpos_clip +#define GL_IBM_rasterpos_clip 1 +#define __GLEE_GL_IBM_rasterpos_clip 1 +/* Constants */ +#define GL_RASTER_POSITION_UNCLIPPED_IBM 0x19262 +#endif + +/* GL_HP_texture_lighting */ + +#ifndef GL_HP_texture_lighting +#define GL_HP_texture_lighting 1 +#define __GLEE_GL_HP_texture_lighting 1 +/* Constants */ +#define GL_TEXTURE_LIGHTING_MODE_HP 0x8167 +#define GL_TEXTURE_POST_SPECULAR_HP 0x8168 +#define GL_TEXTURE_PRE_SPECULAR_HP 0x8169 +#endif + +/* GL_EXT_draw_range_elements */ + +#ifndef GL_EXT_draw_range_elements +#define GL_EXT_draw_range_elements 1 +#define __GLEE_GL_EXT_draw_range_elements 1 +/* Constants */ +#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8 +#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9 +#ifndef GLEE_H_DEFINED_glDrawRangeElementsEXT +#define GLEE_H_DEFINED_glDrawRangeElementsEXT + typedef void (APIENTRYP GLEEPFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices); + GLEE_EXTERN GLEEPFNGLDRAWRANGEELEMENTSEXTPROC GLeeFuncPtr_glDrawRangeElementsEXT; + #define glDrawRangeElementsEXT GLeeFuncPtr_glDrawRangeElementsEXT +#endif +#endif + +/* GL_WIN_phong_shading */ + +#ifndef GL_WIN_phong_shading +#define GL_WIN_phong_shading 1 +#define __GLEE_GL_WIN_phong_shading 1 +/* Constants */ +#define GL_PHONG_WIN 0x80EA +#define GL_PHONG_HINT_WIN 0x80EB +#endif + +/* GL_WIN_specular_fog */ + +#ifndef GL_WIN_specular_fog +#define GL_WIN_specular_fog 1 +#define __GLEE_GL_WIN_specular_fog 1 +/* Constants */ +#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC +#endif + +/* GL_EXT_light_texture */ + +#ifndef GL_EXT_light_texture +#define GL_EXT_light_texture 1 +#define __GLEE_GL_EXT_light_texture 1 +/* Constants */ +#define GL_FRAGMENT_MATERIAL_EXT 0x8349 +#define GL_FRAGMENT_NORMAL_EXT 0x834A +#define GL_FRAGMENT_COLOR_EXT 0x834C +#define GL_ATTENUATION_EXT 0x834D +#define GL_SHADOW_ATTENUATION_EXT 0x834E +#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F +#define GL_TEXTURE_LIGHT_EXT 0x8350 +#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351 +#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352 +#ifndef GLEE_H_DEFINED_glApplyTextureEXT +#define GLEE_H_DEFINED_glApplyTextureEXT + typedef void (APIENTRYP GLEEPFNGLAPPLYTEXTUREEXTPROC) (GLenum mode); + GLEE_EXTERN GLEEPFNGLAPPLYTEXTUREEXTPROC GLeeFuncPtr_glApplyTextureEXT; + #define glApplyTextureEXT GLeeFuncPtr_glApplyTextureEXT +#endif +#ifndef GLEE_H_DEFINED_glTextureLightEXT +#define GLEE_H_DEFINED_glTextureLightEXT + typedef void (APIENTRYP GLEEPFNGLTEXTURELIGHTEXTPROC) (GLenum pname); + GLEE_EXTERN GLEEPFNGLTEXTURELIGHTEXTPROC GLeeFuncPtr_glTextureLightEXT; + #define glTextureLightEXT GLeeFuncPtr_glTextureLightEXT +#endif +#ifndef GLEE_H_DEFINED_glTextureMaterialEXT +#define GLEE_H_DEFINED_glTextureMaterialEXT + typedef void (APIENTRYP GLEEPFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode); + GLEE_EXTERN GLEEPFNGLTEXTUREMATERIALEXTPROC GLeeFuncPtr_glTextureMaterialEXT; + #define glTextureMaterialEXT GLeeFuncPtr_glTextureMaterialEXT +#endif +#endif + +/* GL_SGIX_blend_alpha_minmax */ + +#ifndef GL_SGIX_blend_alpha_minmax +#define GL_SGIX_blend_alpha_minmax 1 +#define __GLEE_GL_SGIX_blend_alpha_minmax 1 +/* Constants */ +#define GL_ALPHA_MIN_SGIX 0x8320 +#define GL_ALPHA_MAX_SGIX 0x8321 +#endif + +/* GL_SGIX_impact_pixel_texture */ + +#ifndef GL_SGIX_impact_pixel_texture +#define GL_SGIX_impact_pixel_texture 1 +#define __GLEE_GL_SGIX_impact_pixel_texture 1 +/* Constants */ +#define GL_PIXEL_TEX_GEN_Q_CEILING_SGIX 0x8184 +#define GL_PIXEL_TEX_GEN_Q_ROUND_SGIX 0x8185 +#define GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX 0x8186 +#define GL_PIXEL_TEX_GEN_ALPHA_REPLACE_SGIX 0x8187 +#define GL_PIXEL_TEX_GEN_ALPHA_NO_REPLACE_SGIX 0x8188 +#define GL_PIXEL_TEX_GEN_ALPHA_LS_SGIX 0x8189 +#define GL_PIXEL_TEX_GEN_ALPHA_MS_SGIX 0x818A +#endif + +/* GL_EXT_bgra */ + +#ifndef GL_EXT_bgra +#define GL_EXT_bgra 1 +#define __GLEE_GL_EXT_bgra 1 +/* Constants */ +#define GL_BGR_EXT 0x80E0 +#define GL_BGRA_EXT 0x80E1 +#endif + +/* GL_SGIX_async */ + +#ifndef GL_SGIX_async +#define GL_SGIX_async 1 +#define __GLEE_GL_SGIX_async 1 +/* Constants */ +#define GL_ASYNC_MARKER_SGIX 0x8329 +#ifndef GLEE_H_DEFINED_glAsyncMarkerSGIX +#define GLEE_H_DEFINED_glAsyncMarkerSGIX + typedef void (APIENTRYP GLEEPFNGLASYNCMARKERSGIXPROC) (GLuint marker); + GLEE_EXTERN GLEEPFNGLASYNCMARKERSGIXPROC GLeeFuncPtr_glAsyncMarkerSGIX; + #define glAsyncMarkerSGIX GLeeFuncPtr_glAsyncMarkerSGIX +#endif +#ifndef GLEE_H_DEFINED_glFinishAsyncSGIX +#define GLEE_H_DEFINED_glFinishAsyncSGIX + typedef GLint (APIENTRYP GLEEPFNGLFINISHASYNCSGIXPROC) (GLuint * markerp); + GLEE_EXTERN GLEEPFNGLFINISHASYNCSGIXPROC GLeeFuncPtr_glFinishAsyncSGIX; + #define glFinishAsyncSGIX GLeeFuncPtr_glFinishAsyncSGIX +#endif +#ifndef GLEE_H_DEFINED_glPollAsyncSGIX +#define GLEE_H_DEFINED_glPollAsyncSGIX + typedef GLint (APIENTRYP GLEEPFNGLPOLLASYNCSGIXPROC) (GLuint * markerp); + GLEE_EXTERN GLEEPFNGLPOLLASYNCSGIXPROC GLeeFuncPtr_glPollAsyncSGIX; + #define glPollAsyncSGIX GLeeFuncPtr_glPollAsyncSGIX +#endif +#ifndef GLEE_H_DEFINED_glGenAsyncMarkersSGIX +#define GLEE_H_DEFINED_glGenAsyncMarkersSGIX + typedef GLuint (APIENTRYP GLEEPFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range); + GLEE_EXTERN GLEEPFNGLGENASYNCMARKERSSGIXPROC GLeeFuncPtr_glGenAsyncMarkersSGIX; + #define glGenAsyncMarkersSGIX GLeeFuncPtr_glGenAsyncMarkersSGIX +#endif +#ifndef GLEE_H_DEFINED_glDeleteAsyncMarkersSGIX +#define GLEE_H_DEFINED_glDeleteAsyncMarkersSGIX + typedef void (APIENTRYP GLEEPFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range); + GLEE_EXTERN GLEEPFNGLDELETEASYNCMARKERSSGIXPROC GLeeFuncPtr_glDeleteAsyncMarkersSGIX; + #define glDeleteAsyncMarkersSGIX GLeeFuncPtr_glDeleteAsyncMarkersSGIX +#endif +#ifndef GLEE_H_DEFINED_glIsAsyncMarkerSGIX +#define GLEE_H_DEFINED_glIsAsyncMarkerSGIX + typedef GLboolean (APIENTRYP GLEEPFNGLISASYNCMARKERSGIXPROC) (GLuint marker); + GLEE_EXTERN GLEEPFNGLISASYNCMARKERSGIXPROC GLeeFuncPtr_glIsAsyncMarkerSGIX; + #define glIsAsyncMarkerSGIX GLeeFuncPtr_glIsAsyncMarkerSGIX +#endif +#endif + +/* GL_SGIX_async_pixel */ + +#ifndef GL_SGIX_async_pixel +#define GL_SGIX_async_pixel 1 +#define __GLEE_GL_SGIX_async_pixel 1 +/* Constants */ +#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C +#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D +#define GL_ASYNC_READ_PIXELS_SGIX 0x835E +#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F +#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360 +#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361 +#endif + +/* GL_SGIX_async_histogram */ + +#ifndef GL_SGIX_async_histogram +#define GL_SGIX_async_histogram 1 +#define __GLEE_GL_SGIX_async_histogram 1 +/* Constants */ +#define GL_ASYNC_HISTOGRAM_SGIX 0x832C +#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D +#endif + +/* GL_INTEL_texture_scissor */ + +#ifndef GL_INTEL_texture_scissor +#define GL_INTEL_texture_scissor 1 +#define __GLEE_GL_INTEL_texture_scissor 1 +/* Constants */ +#endif + +/* GL_INTEL_parallel_arrays */ + +#ifndef GL_INTEL_parallel_arrays +#define GL_INTEL_parallel_arrays 1 +#define __GLEE_GL_INTEL_parallel_arrays 1 +/* Constants */ +#define GL_PARALLEL_ARRAYS_INTEL 0x83F4 +#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5 +#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6 +#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7 +#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8 +#ifndef GLEE_H_DEFINED_glVertexPointervINTEL +#define GLEE_H_DEFINED_glVertexPointervINTEL + typedef void (APIENTRYP GLEEPFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* * pointer); + GLEE_EXTERN GLEEPFNGLVERTEXPOINTERVINTELPROC GLeeFuncPtr_glVertexPointervINTEL; + #define glVertexPointervINTEL GLeeFuncPtr_glVertexPointervINTEL +#endif +#ifndef GLEE_H_DEFINED_glNormalPointervINTEL +#define GLEE_H_DEFINED_glNormalPointervINTEL + typedef void (APIENTRYP GLEEPFNGLNORMALPOINTERVINTELPROC) (GLenum type, const GLvoid* * pointer); + GLEE_EXTERN GLEEPFNGLNORMALPOINTERVINTELPROC GLeeFuncPtr_glNormalPointervINTEL; + #define glNormalPointervINTEL GLeeFuncPtr_glNormalPointervINTEL +#endif +#ifndef GLEE_H_DEFINED_glColorPointervINTEL +#define GLEE_H_DEFINED_glColorPointervINTEL + typedef void (APIENTRYP GLEEPFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* * pointer); + GLEE_EXTERN GLEEPFNGLCOLORPOINTERVINTELPROC GLeeFuncPtr_glColorPointervINTEL; + #define glColorPointervINTEL GLeeFuncPtr_glColorPointervINTEL +#endif +#ifndef GLEE_H_DEFINED_glTexCoordPointervINTEL +#define GLEE_H_DEFINED_glTexCoordPointervINTEL + typedef void (APIENTRYP GLEEPFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* * pointer); + GLEE_EXTERN GLEEPFNGLTEXCOORDPOINTERVINTELPROC GLeeFuncPtr_glTexCoordPointervINTEL; + #define glTexCoordPointervINTEL GLeeFuncPtr_glTexCoordPointervINTEL +#endif +#endif + +/* GL_HP_occlusion_test */ + +#ifndef GL_HP_occlusion_test +#define GL_HP_occlusion_test 1 +#define __GLEE_GL_HP_occlusion_test 1 +/* Constants */ +#define GL_OCCLUSION_TEST_HP 0x8165 +#define GL_OCCLUSION_TEST_RESULT_HP 0x8166 +#endif + +/* GL_EXT_pixel_transform */ + +#ifndef GL_EXT_pixel_transform +#define GL_EXT_pixel_transform 1 +#define __GLEE_GL_EXT_pixel_transform 1 +/* Constants */ +#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330 +#define GL_PIXEL_MAG_FILTER_EXT 0x8331 +#define GL_PIXEL_MIN_FILTER_EXT 0x8332 +#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333 +#define GL_CUBIC_EXT 0x8334 +#define GL_AVERAGE_EXT 0x8335 +#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336 +#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337 +#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338 +#ifndef GLEE_H_DEFINED_glPixelTransformParameteriEXT +#define GLEE_H_DEFINED_glPixelTransformParameteriEXT + typedef void (APIENTRYP GLEEPFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLPIXELTRANSFORMPARAMETERIEXTPROC GLeeFuncPtr_glPixelTransformParameteriEXT; + #define glPixelTransformParameteriEXT GLeeFuncPtr_glPixelTransformParameteriEXT +#endif +#ifndef GLEE_H_DEFINED_glPixelTransformParameterfEXT +#define GLEE_H_DEFINED_glPixelTransformParameterfEXT + typedef void (APIENTRYP GLEEPFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLPIXELTRANSFORMPARAMETERFEXTPROC GLeeFuncPtr_glPixelTransformParameterfEXT; + #define glPixelTransformParameterfEXT GLeeFuncPtr_glPixelTransformParameterfEXT +#endif +#ifndef GLEE_H_DEFINED_glPixelTransformParameterivEXT +#define GLEE_H_DEFINED_glPixelTransformParameterivEXT + typedef void (APIENTRYP GLEEPFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLPIXELTRANSFORMPARAMETERIVEXTPROC GLeeFuncPtr_glPixelTransformParameterivEXT; + #define glPixelTransformParameterivEXT GLeeFuncPtr_glPixelTransformParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glPixelTransformParameterfvEXT +#define GLEE_H_DEFINED_glPixelTransformParameterfvEXT + typedef void (APIENTRYP GLEEPFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLPIXELTRANSFORMPARAMETERFVEXTPROC GLeeFuncPtr_glPixelTransformParameterfvEXT; + #define glPixelTransformParameterfvEXT GLeeFuncPtr_glPixelTransformParameterfvEXT +#endif +#endif + +/* GL_EXT_pixel_transform_color_table */ + +#ifndef GL_EXT_pixel_transform_color_table +#define GL_EXT_pixel_transform_color_table 1 +#define __GLEE_GL_EXT_pixel_transform_color_table 1 +/* Constants */ +#endif + +/* GL_EXT_shared_texture_palette */ + +#ifndef GL_EXT_shared_texture_palette +#define GL_EXT_shared_texture_palette 1 +#define __GLEE_GL_EXT_shared_texture_palette 1 +/* Constants */ +#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB +#endif + +/* GL_EXT_separate_specular_color */ + +#ifndef GL_EXT_separate_specular_color +#define GL_EXT_separate_specular_color 1 +#define __GLEE_GL_EXT_separate_specular_color 1 +/* Constants */ +#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 +#define GL_SINGLE_COLOR_EXT 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA +#endif + +/* GL_EXT_secondary_color */ + +#ifndef GL_EXT_secondary_color +#define GL_EXT_secondary_color 1 +#define __GLEE_GL_EXT_secondary_color 1 +/* Constants */ +#define GL_COLOR_SUM_EXT 0x8458 +#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D +#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E +#ifndef GLEE_H_DEFINED_glSecondaryColor3bEXT +#define GLEE_H_DEFINED_glSecondaryColor3bEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3BEXTPROC GLeeFuncPtr_glSecondaryColor3bEXT; + #define glSecondaryColor3bEXT GLeeFuncPtr_glSecondaryColor3bEXT +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3bvEXT +#define GLEE_H_DEFINED_glSecondaryColor3bvEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3BVEXTPROC GLeeFuncPtr_glSecondaryColor3bvEXT; + #define glSecondaryColor3bvEXT GLeeFuncPtr_glSecondaryColor3bvEXT +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3dEXT +#define GLEE_H_DEFINED_glSecondaryColor3dEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3DEXTPROC GLeeFuncPtr_glSecondaryColor3dEXT; + #define glSecondaryColor3dEXT GLeeFuncPtr_glSecondaryColor3dEXT +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3dvEXT +#define GLEE_H_DEFINED_glSecondaryColor3dvEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3DVEXTPROC GLeeFuncPtr_glSecondaryColor3dvEXT; + #define glSecondaryColor3dvEXT GLeeFuncPtr_glSecondaryColor3dvEXT +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3fEXT +#define GLEE_H_DEFINED_glSecondaryColor3fEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3FEXTPROC GLeeFuncPtr_glSecondaryColor3fEXT; + #define glSecondaryColor3fEXT GLeeFuncPtr_glSecondaryColor3fEXT +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3fvEXT +#define GLEE_H_DEFINED_glSecondaryColor3fvEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3FVEXTPROC GLeeFuncPtr_glSecondaryColor3fvEXT; + #define glSecondaryColor3fvEXT GLeeFuncPtr_glSecondaryColor3fvEXT +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3iEXT +#define GLEE_H_DEFINED_glSecondaryColor3iEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3IEXTPROC GLeeFuncPtr_glSecondaryColor3iEXT; + #define glSecondaryColor3iEXT GLeeFuncPtr_glSecondaryColor3iEXT +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3ivEXT +#define GLEE_H_DEFINED_glSecondaryColor3ivEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3IVEXTPROC GLeeFuncPtr_glSecondaryColor3ivEXT; + #define glSecondaryColor3ivEXT GLeeFuncPtr_glSecondaryColor3ivEXT +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3sEXT +#define GLEE_H_DEFINED_glSecondaryColor3sEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3SEXTPROC GLeeFuncPtr_glSecondaryColor3sEXT; + #define glSecondaryColor3sEXT GLeeFuncPtr_glSecondaryColor3sEXT +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3svEXT +#define GLEE_H_DEFINED_glSecondaryColor3svEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3SVEXTPROC GLeeFuncPtr_glSecondaryColor3svEXT; + #define glSecondaryColor3svEXT GLeeFuncPtr_glSecondaryColor3svEXT +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3ubEXT +#define GLEE_H_DEFINED_glSecondaryColor3ubEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3UBEXTPROC GLeeFuncPtr_glSecondaryColor3ubEXT; + #define glSecondaryColor3ubEXT GLeeFuncPtr_glSecondaryColor3ubEXT +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3ubvEXT +#define GLEE_H_DEFINED_glSecondaryColor3ubvEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3UBVEXTPROC GLeeFuncPtr_glSecondaryColor3ubvEXT; + #define glSecondaryColor3ubvEXT GLeeFuncPtr_glSecondaryColor3ubvEXT +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3uiEXT +#define GLEE_H_DEFINED_glSecondaryColor3uiEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3UIEXTPROC GLeeFuncPtr_glSecondaryColor3uiEXT; + #define glSecondaryColor3uiEXT GLeeFuncPtr_glSecondaryColor3uiEXT +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3uivEXT +#define GLEE_H_DEFINED_glSecondaryColor3uivEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3UIVEXTPROC GLeeFuncPtr_glSecondaryColor3uivEXT; + #define glSecondaryColor3uivEXT GLeeFuncPtr_glSecondaryColor3uivEXT +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3usEXT +#define GLEE_H_DEFINED_glSecondaryColor3usEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3USEXTPROC GLeeFuncPtr_glSecondaryColor3usEXT; + #define glSecondaryColor3usEXT GLeeFuncPtr_glSecondaryColor3usEXT +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3usvEXT +#define GLEE_H_DEFINED_glSecondaryColor3usvEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3USVEXTPROC GLeeFuncPtr_glSecondaryColor3usvEXT; + #define glSecondaryColor3usvEXT GLeeFuncPtr_glSecondaryColor3usvEXT +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColorPointerEXT +#define GLEE_H_DEFINED_glSecondaryColorPointerEXT + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLORPOINTEREXTPROC GLeeFuncPtr_glSecondaryColorPointerEXT; + #define glSecondaryColorPointerEXT GLeeFuncPtr_glSecondaryColorPointerEXT +#endif +#endif + +/* GL_EXT_texture_perturb_normal */ + +#ifndef GL_EXT_texture_perturb_normal +#define GL_EXT_texture_perturb_normal 1 +#define __GLEE_GL_EXT_texture_perturb_normal 1 +/* Constants */ +#define GL_PERTURB_EXT 0x85AE +#define GL_TEXTURE_NORMAL_EXT 0x85AF +#ifndef GLEE_H_DEFINED_glTextureNormalEXT +#define GLEE_H_DEFINED_glTextureNormalEXT + typedef void (APIENTRYP GLEEPFNGLTEXTURENORMALEXTPROC) (GLenum mode); + GLEE_EXTERN GLEEPFNGLTEXTURENORMALEXTPROC GLeeFuncPtr_glTextureNormalEXT; + #define glTextureNormalEXT GLeeFuncPtr_glTextureNormalEXT +#endif +#endif + +/* GL_EXT_multi_draw_arrays */ + +#ifndef GL_EXT_multi_draw_arrays +#define GL_EXT_multi_draw_arrays 1 +#define __GLEE_GL_EXT_multi_draw_arrays 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glMultiDrawArraysEXT +#define GLEE_H_DEFINED_glMultiDrawArraysEXT + typedef void (APIENTRYP GLEEPFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint * first, GLsizei * count, GLsizei primcount); + GLEE_EXTERN GLEEPFNGLMULTIDRAWARRAYSEXTPROC GLeeFuncPtr_glMultiDrawArraysEXT; + #define glMultiDrawArraysEXT GLeeFuncPtr_glMultiDrawArraysEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiDrawElementsEXT +#define GLEE_H_DEFINED_glMultiDrawElementsEXT + typedef void (APIENTRYP GLEEPFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei * count, GLenum type, const GLvoid* * indices, GLsizei primcount); + GLEE_EXTERN GLEEPFNGLMULTIDRAWELEMENTSEXTPROC GLeeFuncPtr_glMultiDrawElementsEXT; + #define glMultiDrawElementsEXT GLeeFuncPtr_glMultiDrawElementsEXT +#endif +#endif + +/* GL_EXT_fog_coord */ + +#ifndef GL_EXT_fog_coord +#define GL_EXT_fog_coord 1 +#define __GLEE_GL_EXT_fog_coord 1 +/* Constants */ +#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450 +#define GL_FOG_COORDINATE_EXT 0x8451 +#define GL_FRAGMENT_DEPTH_EXT 0x8452 +#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456 +#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457 +#ifndef GLEE_H_DEFINED_glFogCoordfEXT +#define GLEE_H_DEFINED_glFogCoordfEXT + typedef void (APIENTRYP GLEEPFNGLFOGCOORDFEXTPROC) (GLfloat coord); + GLEE_EXTERN GLEEPFNGLFOGCOORDFEXTPROC GLeeFuncPtr_glFogCoordfEXT; + #define glFogCoordfEXT GLeeFuncPtr_glFogCoordfEXT +#endif +#ifndef GLEE_H_DEFINED_glFogCoordfvEXT +#define GLEE_H_DEFINED_glFogCoordfvEXT + typedef void (APIENTRYP GLEEPFNGLFOGCOORDFVEXTPROC) (const GLfloat * coord); + GLEE_EXTERN GLEEPFNGLFOGCOORDFVEXTPROC GLeeFuncPtr_glFogCoordfvEXT; + #define glFogCoordfvEXT GLeeFuncPtr_glFogCoordfvEXT +#endif +#ifndef GLEE_H_DEFINED_glFogCoorddEXT +#define GLEE_H_DEFINED_glFogCoorddEXT + typedef void (APIENTRYP GLEEPFNGLFOGCOORDDEXTPROC) (GLdouble coord); + GLEE_EXTERN GLEEPFNGLFOGCOORDDEXTPROC GLeeFuncPtr_glFogCoorddEXT; + #define glFogCoorddEXT GLeeFuncPtr_glFogCoorddEXT +#endif +#ifndef GLEE_H_DEFINED_glFogCoorddvEXT +#define GLEE_H_DEFINED_glFogCoorddvEXT + typedef void (APIENTRYP GLEEPFNGLFOGCOORDDVEXTPROC) (const GLdouble * coord); + GLEE_EXTERN GLEEPFNGLFOGCOORDDVEXTPROC GLeeFuncPtr_glFogCoorddvEXT; + #define glFogCoorddvEXT GLeeFuncPtr_glFogCoorddvEXT +#endif +#ifndef GLEE_H_DEFINED_glFogCoordPointerEXT +#define GLEE_H_DEFINED_glFogCoordPointerEXT + typedef void (APIENTRYP GLEEPFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLFOGCOORDPOINTEREXTPROC GLeeFuncPtr_glFogCoordPointerEXT; + #define glFogCoordPointerEXT GLeeFuncPtr_glFogCoordPointerEXT +#endif +#endif + +/* GL_REND_screen_coordinates */ + +#ifndef GL_REND_screen_coordinates +#define GL_REND_screen_coordinates 1 +#define __GLEE_GL_REND_screen_coordinates 1 +/* Constants */ +#define GL_SCREEN_COORDINATES_REND 0x8490 +#define GL_INVERTED_SCREEN_W_REND 0x8491 +#endif + +/* GL_EXT_coordinate_frame */ + +#ifndef GL_EXT_coordinate_frame +#define GL_EXT_coordinate_frame 1 +#define __GLEE_GL_EXT_coordinate_frame 1 +/* Constants */ +#define GL_TANGENT_ARRAY_EXT 0x8439 +#define GL_BINORMAL_ARRAY_EXT 0x843A +#define GL_CURRENT_TANGENT_EXT 0x843B +#define GL_CURRENT_BINORMAL_EXT 0x843C +#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E +#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F +#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440 +#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441 +#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442 +#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443 +#define GL_MAP1_TANGENT_EXT 0x8444 +#define GL_MAP2_TANGENT_EXT 0x8445 +#define GL_MAP1_BINORMAL_EXT 0x8446 +#define GL_MAP2_BINORMAL_EXT 0x8447 +#ifndef GLEE_H_DEFINED_glTangent3bEXT +#define GLEE_H_DEFINED_glTangent3bEXT + typedef void (APIENTRYP GLEEPFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz); + GLEE_EXTERN GLEEPFNGLTANGENT3BEXTPROC GLeeFuncPtr_glTangent3bEXT; + #define glTangent3bEXT GLeeFuncPtr_glTangent3bEXT +#endif +#ifndef GLEE_H_DEFINED_glTangent3bvEXT +#define GLEE_H_DEFINED_glTangent3bvEXT + typedef void (APIENTRYP GLEEPFNGLTANGENT3BVEXTPROC) (const GLbyte * v); + GLEE_EXTERN GLEEPFNGLTANGENT3BVEXTPROC GLeeFuncPtr_glTangent3bvEXT; + #define glTangent3bvEXT GLeeFuncPtr_glTangent3bvEXT +#endif +#ifndef GLEE_H_DEFINED_glTangent3dEXT +#define GLEE_H_DEFINED_glTangent3dEXT + typedef void (APIENTRYP GLEEPFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz); + GLEE_EXTERN GLEEPFNGLTANGENT3DEXTPROC GLeeFuncPtr_glTangent3dEXT; + #define glTangent3dEXT GLeeFuncPtr_glTangent3dEXT +#endif +#ifndef GLEE_H_DEFINED_glTangent3dvEXT +#define GLEE_H_DEFINED_glTangent3dvEXT + typedef void (APIENTRYP GLEEPFNGLTANGENT3DVEXTPROC) (const GLdouble * v); + GLEE_EXTERN GLEEPFNGLTANGENT3DVEXTPROC GLeeFuncPtr_glTangent3dvEXT; + #define glTangent3dvEXT GLeeFuncPtr_glTangent3dvEXT +#endif +#ifndef GLEE_H_DEFINED_glTangent3fEXT +#define GLEE_H_DEFINED_glTangent3fEXT + typedef void (APIENTRYP GLEEPFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz); + GLEE_EXTERN GLEEPFNGLTANGENT3FEXTPROC GLeeFuncPtr_glTangent3fEXT; + #define glTangent3fEXT GLeeFuncPtr_glTangent3fEXT +#endif +#ifndef GLEE_H_DEFINED_glTangent3fvEXT +#define GLEE_H_DEFINED_glTangent3fvEXT + typedef void (APIENTRYP GLEEPFNGLTANGENT3FVEXTPROC) (const GLfloat * v); + GLEE_EXTERN GLEEPFNGLTANGENT3FVEXTPROC GLeeFuncPtr_glTangent3fvEXT; + #define glTangent3fvEXT GLeeFuncPtr_glTangent3fvEXT +#endif +#ifndef GLEE_H_DEFINED_glTangent3iEXT +#define GLEE_H_DEFINED_glTangent3iEXT + typedef void (APIENTRYP GLEEPFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz); + GLEE_EXTERN GLEEPFNGLTANGENT3IEXTPROC GLeeFuncPtr_glTangent3iEXT; + #define glTangent3iEXT GLeeFuncPtr_glTangent3iEXT +#endif +#ifndef GLEE_H_DEFINED_glTangent3ivEXT +#define GLEE_H_DEFINED_glTangent3ivEXT + typedef void (APIENTRYP GLEEPFNGLTANGENT3IVEXTPROC) (const GLint * v); + GLEE_EXTERN GLEEPFNGLTANGENT3IVEXTPROC GLeeFuncPtr_glTangent3ivEXT; + #define glTangent3ivEXT GLeeFuncPtr_glTangent3ivEXT +#endif +#ifndef GLEE_H_DEFINED_glTangent3sEXT +#define GLEE_H_DEFINED_glTangent3sEXT + typedef void (APIENTRYP GLEEPFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz); + GLEE_EXTERN GLEEPFNGLTANGENT3SEXTPROC GLeeFuncPtr_glTangent3sEXT; + #define glTangent3sEXT GLeeFuncPtr_glTangent3sEXT +#endif +#ifndef GLEE_H_DEFINED_glTangent3svEXT +#define GLEE_H_DEFINED_glTangent3svEXT + typedef void (APIENTRYP GLEEPFNGLTANGENT3SVEXTPROC) (const GLshort * v); + GLEE_EXTERN GLEEPFNGLTANGENT3SVEXTPROC GLeeFuncPtr_glTangent3svEXT; + #define glTangent3svEXT GLeeFuncPtr_glTangent3svEXT +#endif +#ifndef GLEE_H_DEFINED_glBinormal3bEXT +#define GLEE_H_DEFINED_glBinormal3bEXT + typedef void (APIENTRYP GLEEPFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz); + GLEE_EXTERN GLEEPFNGLBINORMAL3BEXTPROC GLeeFuncPtr_glBinormal3bEXT; + #define glBinormal3bEXT GLeeFuncPtr_glBinormal3bEXT +#endif +#ifndef GLEE_H_DEFINED_glBinormal3bvEXT +#define GLEE_H_DEFINED_glBinormal3bvEXT + typedef void (APIENTRYP GLEEPFNGLBINORMAL3BVEXTPROC) (const GLbyte * v); + GLEE_EXTERN GLEEPFNGLBINORMAL3BVEXTPROC GLeeFuncPtr_glBinormal3bvEXT; + #define glBinormal3bvEXT GLeeFuncPtr_glBinormal3bvEXT +#endif +#ifndef GLEE_H_DEFINED_glBinormal3dEXT +#define GLEE_H_DEFINED_glBinormal3dEXT + typedef void (APIENTRYP GLEEPFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz); + GLEE_EXTERN GLEEPFNGLBINORMAL3DEXTPROC GLeeFuncPtr_glBinormal3dEXT; + #define glBinormal3dEXT GLeeFuncPtr_glBinormal3dEXT +#endif +#ifndef GLEE_H_DEFINED_glBinormal3dvEXT +#define GLEE_H_DEFINED_glBinormal3dvEXT + typedef void (APIENTRYP GLEEPFNGLBINORMAL3DVEXTPROC) (const GLdouble * v); + GLEE_EXTERN GLEEPFNGLBINORMAL3DVEXTPROC GLeeFuncPtr_glBinormal3dvEXT; + #define glBinormal3dvEXT GLeeFuncPtr_glBinormal3dvEXT +#endif +#ifndef GLEE_H_DEFINED_glBinormal3fEXT +#define GLEE_H_DEFINED_glBinormal3fEXT + typedef void (APIENTRYP GLEEPFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz); + GLEE_EXTERN GLEEPFNGLBINORMAL3FEXTPROC GLeeFuncPtr_glBinormal3fEXT; + #define glBinormal3fEXT GLeeFuncPtr_glBinormal3fEXT +#endif +#ifndef GLEE_H_DEFINED_glBinormal3fvEXT +#define GLEE_H_DEFINED_glBinormal3fvEXT + typedef void (APIENTRYP GLEEPFNGLBINORMAL3FVEXTPROC) (const GLfloat * v); + GLEE_EXTERN GLEEPFNGLBINORMAL3FVEXTPROC GLeeFuncPtr_glBinormal3fvEXT; + #define glBinormal3fvEXT GLeeFuncPtr_glBinormal3fvEXT +#endif +#ifndef GLEE_H_DEFINED_glBinormal3iEXT +#define GLEE_H_DEFINED_glBinormal3iEXT + typedef void (APIENTRYP GLEEPFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz); + GLEE_EXTERN GLEEPFNGLBINORMAL3IEXTPROC GLeeFuncPtr_glBinormal3iEXT; + #define glBinormal3iEXT GLeeFuncPtr_glBinormal3iEXT +#endif +#ifndef GLEE_H_DEFINED_glBinormal3ivEXT +#define GLEE_H_DEFINED_glBinormal3ivEXT + typedef void (APIENTRYP GLEEPFNGLBINORMAL3IVEXTPROC) (const GLint * v); + GLEE_EXTERN GLEEPFNGLBINORMAL3IVEXTPROC GLeeFuncPtr_glBinormal3ivEXT; + #define glBinormal3ivEXT GLeeFuncPtr_glBinormal3ivEXT +#endif +#ifndef GLEE_H_DEFINED_glBinormal3sEXT +#define GLEE_H_DEFINED_glBinormal3sEXT + typedef void (APIENTRYP GLEEPFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz); + GLEE_EXTERN GLEEPFNGLBINORMAL3SEXTPROC GLeeFuncPtr_glBinormal3sEXT; + #define glBinormal3sEXT GLeeFuncPtr_glBinormal3sEXT +#endif +#ifndef GLEE_H_DEFINED_glBinormal3svEXT +#define GLEE_H_DEFINED_glBinormal3svEXT + typedef void (APIENTRYP GLEEPFNGLBINORMAL3SVEXTPROC) (const GLshort * v); + GLEE_EXTERN GLEEPFNGLBINORMAL3SVEXTPROC GLeeFuncPtr_glBinormal3svEXT; + #define glBinormal3svEXT GLeeFuncPtr_glBinormal3svEXT +#endif +#ifndef GLEE_H_DEFINED_glTangentPointerEXT +#define GLEE_H_DEFINED_glTangentPointerEXT + typedef void (APIENTRYP GLEEPFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLTANGENTPOINTEREXTPROC GLeeFuncPtr_glTangentPointerEXT; + #define glTangentPointerEXT GLeeFuncPtr_glTangentPointerEXT +#endif +#ifndef GLEE_H_DEFINED_glBinormalPointerEXT +#define GLEE_H_DEFINED_glBinormalPointerEXT + typedef void (APIENTRYP GLEEPFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLBINORMALPOINTEREXTPROC GLeeFuncPtr_glBinormalPointerEXT; + #define glBinormalPointerEXT GLeeFuncPtr_glBinormalPointerEXT +#endif +#endif + +/* GL_EXT_texture_env_combine */ + +#ifndef GL_EXT_texture_env_combine +#define GL_EXT_texture_env_combine 1 +#define __GLEE_GL_EXT_texture_env_combine 1 +/* Constants */ +#define GL_COMBINE_EXT 0x8570 +#define GL_COMBINE_RGB_EXT 0x8571 +#define GL_COMBINE_ALPHA_EXT 0x8572 +#define GL_RGB_SCALE_EXT 0x8573 +#define GL_ADD_SIGNED_EXT 0x8574 +#define GL_INTERPOLATE_EXT 0x8575 +#define GL_CONSTANT_EXT 0x8576 +#define GL_PRIMARY_COLOR_EXT 0x8577 +#define GL_PREVIOUS_EXT 0x8578 +#define GL_SOURCE0_RGB_EXT 0x8580 +#define GL_SOURCE1_RGB_EXT 0x8581 +#define GL_SOURCE2_RGB_EXT 0x8582 +#define GL_SOURCE0_ALPHA_EXT 0x8588 +#define GL_SOURCE1_ALPHA_EXT 0x8589 +#define GL_SOURCE2_ALPHA_EXT 0x858A +#define GL_OPERAND0_RGB_EXT 0x8590 +#define GL_OPERAND1_RGB_EXT 0x8591 +#define GL_OPERAND2_RGB_EXT 0x8592 +#define GL_OPERAND0_ALPHA_EXT 0x8598 +#define GL_OPERAND1_ALPHA_EXT 0x8599 +#define GL_OPERAND2_ALPHA_EXT 0x859A +#endif + +/* GL_APPLE_specular_vector */ + +#ifndef GL_APPLE_specular_vector +#define GL_APPLE_specular_vector 1 +#define __GLEE_GL_APPLE_specular_vector 1 +/* Constants */ +#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0 +#endif + +/* GL_APPLE_transform_hint */ + +#ifndef GL_APPLE_transform_hint +#define GL_APPLE_transform_hint 1 +#define __GLEE_GL_APPLE_transform_hint 1 +/* Constants */ +#define GL_TRANSFORM_HINT_APPLE 0x85B1 +#endif + +/* GL_SGIX_fog_scale */ + +#ifndef GL_SGIX_fog_scale +#define GL_SGIX_fog_scale 1 +#define __GLEE_GL_SGIX_fog_scale 1 +/* Constants */ +#define GL_FOG_SCALE_SGIX 0x81FC +#define GL_FOG_SCALE_VALUE_SGIX 0x81FD +#endif + +/* GL_SUNX_constant_data */ + +#ifndef GL_SUNX_constant_data +#define GL_SUNX_constant_data 1 +#define __GLEE_GL_SUNX_constant_data 1 +/* Constants */ +#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5 +#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6 +#ifndef GLEE_H_DEFINED_glFinishTextureSUNX +#define GLEE_H_DEFINED_glFinishTextureSUNX + typedef void (APIENTRYP GLEEPFNGLFINISHTEXTURESUNXPROC) (); + GLEE_EXTERN GLEEPFNGLFINISHTEXTURESUNXPROC GLeeFuncPtr_glFinishTextureSUNX; + #define glFinishTextureSUNX GLeeFuncPtr_glFinishTextureSUNX +#endif +#endif + +/* GL_SUN_global_alpha */ + +#ifndef GL_SUN_global_alpha +#define GL_SUN_global_alpha 1 +#define __GLEE_GL_SUN_global_alpha 1 +/* Constants */ +#define GL_GLOBAL_ALPHA_SUN 0x81D9 +#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA +#ifndef GLEE_H_DEFINED_glGlobalAlphaFactorbSUN +#define GLEE_H_DEFINED_glGlobalAlphaFactorbSUN + typedef void (APIENTRYP GLEEPFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor); + GLEE_EXTERN GLEEPFNGLGLOBALALPHAFACTORBSUNPROC GLeeFuncPtr_glGlobalAlphaFactorbSUN; + #define glGlobalAlphaFactorbSUN GLeeFuncPtr_glGlobalAlphaFactorbSUN +#endif +#ifndef GLEE_H_DEFINED_glGlobalAlphaFactorsSUN +#define GLEE_H_DEFINED_glGlobalAlphaFactorsSUN + typedef void (APIENTRYP GLEEPFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor); + GLEE_EXTERN GLEEPFNGLGLOBALALPHAFACTORSSUNPROC GLeeFuncPtr_glGlobalAlphaFactorsSUN; + #define glGlobalAlphaFactorsSUN GLeeFuncPtr_glGlobalAlphaFactorsSUN +#endif +#ifndef GLEE_H_DEFINED_glGlobalAlphaFactoriSUN +#define GLEE_H_DEFINED_glGlobalAlphaFactoriSUN + typedef void (APIENTRYP GLEEPFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor); + GLEE_EXTERN GLEEPFNGLGLOBALALPHAFACTORISUNPROC GLeeFuncPtr_glGlobalAlphaFactoriSUN; + #define glGlobalAlphaFactoriSUN GLeeFuncPtr_glGlobalAlphaFactoriSUN +#endif +#ifndef GLEE_H_DEFINED_glGlobalAlphaFactorfSUN +#define GLEE_H_DEFINED_glGlobalAlphaFactorfSUN + typedef void (APIENTRYP GLEEPFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor); + GLEE_EXTERN GLEEPFNGLGLOBALALPHAFACTORFSUNPROC GLeeFuncPtr_glGlobalAlphaFactorfSUN; + #define glGlobalAlphaFactorfSUN GLeeFuncPtr_glGlobalAlphaFactorfSUN +#endif +#ifndef GLEE_H_DEFINED_glGlobalAlphaFactordSUN +#define GLEE_H_DEFINED_glGlobalAlphaFactordSUN + typedef void (APIENTRYP GLEEPFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor); + GLEE_EXTERN GLEEPFNGLGLOBALALPHAFACTORDSUNPROC GLeeFuncPtr_glGlobalAlphaFactordSUN; + #define glGlobalAlphaFactordSUN GLeeFuncPtr_glGlobalAlphaFactordSUN +#endif +#ifndef GLEE_H_DEFINED_glGlobalAlphaFactorubSUN +#define GLEE_H_DEFINED_glGlobalAlphaFactorubSUN + typedef void (APIENTRYP GLEEPFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor); + GLEE_EXTERN GLEEPFNGLGLOBALALPHAFACTORUBSUNPROC GLeeFuncPtr_glGlobalAlphaFactorubSUN; + #define glGlobalAlphaFactorubSUN GLeeFuncPtr_glGlobalAlphaFactorubSUN +#endif +#ifndef GLEE_H_DEFINED_glGlobalAlphaFactorusSUN +#define GLEE_H_DEFINED_glGlobalAlphaFactorusSUN + typedef void (APIENTRYP GLEEPFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor); + GLEE_EXTERN GLEEPFNGLGLOBALALPHAFACTORUSSUNPROC GLeeFuncPtr_glGlobalAlphaFactorusSUN; + #define glGlobalAlphaFactorusSUN GLeeFuncPtr_glGlobalAlphaFactorusSUN +#endif +#ifndef GLEE_H_DEFINED_glGlobalAlphaFactoruiSUN +#define GLEE_H_DEFINED_glGlobalAlphaFactoruiSUN + typedef void (APIENTRYP GLEEPFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor); + GLEE_EXTERN GLEEPFNGLGLOBALALPHAFACTORUISUNPROC GLeeFuncPtr_glGlobalAlphaFactoruiSUN; + #define glGlobalAlphaFactoruiSUN GLeeFuncPtr_glGlobalAlphaFactoruiSUN +#endif +#endif + +/* GL_SUN_triangle_list */ + +#ifndef GL_SUN_triangle_list +#define GL_SUN_triangle_list 1 +#define __GLEE_GL_SUN_triangle_list 1 +/* Constants */ +#define GL_RESTART_SUN 0x0001 +#define GL_REPLACE_MIDDLE_SUN 0x0002 +#define GL_REPLACE_OLDEST_SUN 0x0003 +#define GL_TRIANGLE_LIST_SUN 0x81D7 +#define GL_REPLACEMENT_CODE_SUN 0x81D8 +#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0 +#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 +#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 +#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 +#define GL_R1UI_V3F_SUN 0x85C4 +#define GL_R1UI_C4UB_V3F_SUN 0x85C5 +#define GL_R1UI_C3F_V3F_SUN 0x85C6 +#define GL_R1UI_N3F_V3F_SUN 0x85C7 +#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8 +#define GL_R1UI_T2F_V3F_SUN 0x85C9 +#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA +#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB +#ifndef GLEE_H_DEFINED_glReplacementCodeuiSUN +#define GLEE_H_DEFINED_glReplacementCodeuiSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUISUNPROC) (GLuint code); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUISUNPROC GLeeFuncPtr_glReplacementCodeuiSUN; + #define glReplacementCodeuiSUN GLeeFuncPtr_glReplacementCodeuiSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeusSUN +#define GLEE_H_DEFINED_glReplacementCodeusSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUSSUNPROC GLeeFuncPtr_glReplacementCodeusSUN; + #define glReplacementCodeusSUN GLeeFuncPtr_glReplacementCodeusSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeubSUN +#define GLEE_H_DEFINED_glReplacementCodeubSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUBSUNPROC GLeeFuncPtr_glReplacementCodeubSUN; + #define glReplacementCodeubSUN GLeeFuncPtr_glReplacementCodeubSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuivSUN +#define GLEE_H_DEFINED_glReplacementCodeuivSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint * code); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUIVSUNPROC GLeeFuncPtr_glReplacementCodeuivSUN; + #define glReplacementCodeuivSUN GLeeFuncPtr_glReplacementCodeuivSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeusvSUN +#define GLEE_H_DEFINED_glReplacementCodeusvSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort * code); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUSVSUNPROC GLeeFuncPtr_glReplacementCodeusvSUN; + #define glReplacementCodeusvSUN GLeeFuncPtr_glReplacementCodeusvSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeubvSUN +#define GLEE_H_DEFINED_glReplacementCodeubvSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte * code); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUBVSUNPROC GLeeFuncPtr_glReplacementCodeubvSUN; + #define glReplacementCodeubvSUN GLeeFuncPtr_glReplacementCodeubvSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodePointerSUN +#define GLEE_H_DEFINED_glReplacementCodePointerSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const GLvoid* * pointer); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEPOINTERSUNPROC GLeeFuncPtr_glReplacementCodePointerSUN; + #define glReplacementCodePointerSUN GLeeFuncPtr_glReplacementCodePointerSUN +#endif +#endif + +/* GL_SUN_vertex */ + +#ifndef GL_SUN_vertex +#define GL_SUN_vertex 1 +#define __GLEE_GL_SUN_vertex 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glColor4ubVertex2fSUN +#define GLEE_H_DEFINED_glColor4ubVertex2fSUN + typedef void (APIENTRYP GLEEPFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); + GLEE_EXTERN GLEEPFNGLCOLOR4UBVERTEX2FSUNPROC GLeeFuncPtr_glColor4ubVertex2fSUN; + #define glColor4ubVertex2fSUN GLeeFuncPtr_glColor4ubVertex2fSUN +#endif +#ifndef GLEE_H_DEFINED_glColor4ubVertex2fvSUN +#define GLEE_H_DEFINED_glColor4ubVertex2fvSUN + typedef void (APIENTRYP GLEEPFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte * c, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLCOLOR4UBVERTEX2FVSUNPROC GLeeFuncPtr_glColor4ubVertex2fvSUN; + #define glColor4ubVertex2fvSUN GLeeFuncPtr_glColor4ubVertex2fvSUN +#endif +#ifndef GLEE_H_DEFINED_glColor4ubVertex3fSUN +#define GLEE_H_DEFINED_glColor4ubVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLCOLOR4UBVERTEX3FSUNPROC GLeeFuncPtr_glColor4ubVertex3fSUN; + #define glColor4ubVertex3fSUN GLeeFuncPtr_glColor4ubVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glColor4ubVertex3fvSUN +#define GLEE_H_DEFINED_glColor4ubVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte * c, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLCOLOR4UBVERTEX3FVSUNPROC GLeeFuncPtr_glColor4ubVertex3fvSUN; + #define glColor4ubVertex3fvSUN GLeeFuncPtr_glColor4ubVertex3fvSUN +#endif +#ifndef GLEE_H_DEFINED_glColor3fVertex3fSUN +#define GLEE_H_DEFINED_glColor3fVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLCOLOR3FVERTEX3FSUNPROC GLeeFuncPtr_glColor3fVertex3fSUN; + #define glColor3fVertex3fSUN GLeeFuncPtr_glColor3fVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glColor3fVertex3fvSUN +#define GLEE_H_DEFINED_glColor3fVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat * c, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLCOLOR3FVERTEX3FVSUNPROC GLeeFuncPtr_glColor3fVertex3fvSUN; + #define glColor3fVertex3fvSUN GLeeFuncPtr_glColor3fVertex3fvSUN +#endif +#ifndef GLEE_H_DEFINED_glNormal3fVertex3fSUN +#define GLEE_H_DEFINED_glNormal3fVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLNORMAL3FVERTEX3FSUNPROC GLeeFuncPtr_glNormal3fVertex3fSUN; + #define glNormal3fVertex3fSUN GLeeFuncPtr_glNormal3fVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glNormal3fVertex3fvSUN +#define GLEE_H_DEFINED_glNormal3fVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat * n, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLNORMAL3FVERTEX3FVSUNPROC GLeeFuncPtr_glNormal3fVertex3fvSUN; + #define glNormal3fVertex3fvSUN GLeeFuncPtr_glNormal3fVertex3fvSUN +#endif +#ifndef GLEE_H_DEFINED_glColor4fNormal3fVertex3fSUN +#define GLEE_H_DEFINED_glColor4fNormal3fVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC GLeeFuncPtr_glColor4fNormal3fVertex3fSUN; + #define glColor4fNormal3fVertex3fSUN GLeeFuncPtr_glColor4fNormal3fVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glColor4fNormal3fVertex3fvSUN +#define GLEE_H_DEFINED_glColor4fNormal3fVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat * c, const GLfloat * n, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC GLeeFuncPtr_glColor4fNormal3fVertex3fvSUN; + #define glColor4fNormal3fVertex3fvSUN GLeeFuncPtr_glColor4fNormal3fVertex3fvSUN +#endif +#ifndef GLEE_H_DEFINED_glTexCoord2fVertex3fSUN +#define GLEE_H_DEFINED_glTexCoord2fVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLTEXCOORD2FVERTEX3FSUNPROC GLeeFuncPtr_glTexCoord2fVertex3fSUN; + #define glTexCoord2fVertex3fSUN GLeeFuncPtr_glTexCoord2fVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glTexCoord2fVertex3fvSUN +#define GLEE_H_DEFINED_glTexCoord2fVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat * tc, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLTEXCOORD2FVERTEX3FVSUNPROC GLeeFuncPtr_glTexCoord2fVertex3fvSUN; + #define glTexCoord2fVertex3fvSUN GLeeFuncPtr_glTexCoord2fVertex3fvSUN +#endif +#ifndef GLEE_H_DEFINED_glTexCoord4fVertex4fSUN +#define GLEE_H_DEFINED_glTexCoord4fVertex4fSUN + typedef void (APIENTRYP GLEEPFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + GLEE_EXTERN GLEEPFNGLTEXCOORD4FVERTEX4FSUNPROC GLeeFuncPtr_glTexCoord4fVertex4fSUN; + #define glTexCoord4fVertex4fSUN GLeeFuncPtr_glTexCoord4fVertex4fSUN +#endif +#ifndef GLEE_H_DEFINED_glTexCoord4fVertex4fvSUN +#define GLEE_H_DEFINED_glTexCoord4fVertex4fvSUN + typedef void (APIENTRYP GLEEPFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat * tc, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLTEXCOORD4FVERTEX4FVSUNPROC GLeeFuncPtr_glTexCoord4fVertex4fvSUN; + #define glTexCoord4fVertex4fvSUN GLeeFuncPtr_glTexCoord4fVertex4fvSUN +#endif +#ifndef GLEE_H_DEFINED_glTexCoord2fColor4ubVertex3fSUN +#define GLEE_H_DEFINED_glTexCoord2fColor4ubVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC GLeeFuncPtr_glTexCoord2fColor4ubVertex3fSUN; + #define glTexCoord2fColor4ubVertex3fSUN GLeeFuncPtr_glTexCoord2fColor4ubVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glTexCoord2fColor4ubVertex3fvSUN +#define GLEE_H_DEFINED_glTexCoord2fColor4ubVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat * tc, const GLubyte * c, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC GLeeFuncPtr_glTexCoord2fColor4ubVertex3fvSUN; + #define glTexCoord2fColor4ubVertex3fvSUN GLeeFuncPtr_glTexCoord2fColor4ubVertex3fvSUN +#endif +#ifndef GLEE_H_DEFINED_glTexCoord2fColor3fVertex3fSUN +#define GLEE_H_DEFINED_glTexCoord2fColor3fVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC GLeeFuncPtr_glTexCoord2fColor3fVertex3fSUN; + #define glTexCoord2fColor3fVertex3fSUN GLeeFuncPtr_glTexCoord2fColor3fVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glTexCoord2fColor3fVertex3fvSUN +#define GLEE_H_DEFINED_glTexCoord2fColor3fVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat * tc, const GLfloat * c, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC GLeeFuncPtr_glTexCoord2fColor3fVertex3fvSUN; + #define glTexCoord2fColor3fVertex3fvSUN GLeeFuncPtr_glTexCoord2fColor3fVertex3fvSUN +#endif +#ifndef GLEE_H_DEFINED_glTexCoord2fNormal3fVertex3fSUN +#define GLEE_H_DEFINED_glTexCoord2fNormal3fVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC GLeeFuncPtr_glTexCoord2fNormal3fVertex3fSUN; + #define glTexCoord2fNormal3fVertex3fSUN GLeeFuncPtr_glTexCoord2fNormal3fVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glTexCoord2fNormal3fVertex3fvSUN +#define GLEE_H_DEFINED_glTexCoord2fNormal3fVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat * tc, const GLfloat * n, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC GLeeFuncPtr_glTexCoord2fNormal3fVertex3fvSUN; + #define glTexCoord2fNormal3fVertex3fvSUN GLeeFuncPtr_glTexCoord2fNormal3fVertex3fvSUN +#endif +#ifndef GLEE_H_DEFINED_glTexCoord2fColor4fNormal3fVertex3fSUN +#define GLEE_H_DEFINED_glTexCoord2fColor4fNormal3fVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC GLeeFuncPtr_glTexCoord2fColor4fNormal3fVertex3fSUN; + #define glTexCoord2fColor4fNormal3fVertex3fSUN GLeeFuncPtr_glTexCoord2fColor4fNormal3fVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glTexCoord2fColor4fNormal3fVertex3fvSUN +#define GLEE_H_DEFINED_glTexCoord2fColor4fNormal3fVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat * tc, const GLfloat * c, const GLfloat * n, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC GLeeFuncPtr_glTexCoord2fColor4fNormal3fVertex3fvSUN; + #define glTexCoord2fColor4fNormal3fVertex3fvSUN GLeeFuncPtr_glTexCoord2fColor4fNormal3fVertex3fvSUN +#endif +#ifndef GLEE_H_DEFINED_glTexCoord4fColor4fNormal3fVertex4fSUN +#define GLEE_H_DEFINED_glTexCoord4fColor4fNormal3fVertex4fSUN + typedef void (APIENTRYP GLEEPFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + GLEE_EXTERN GLEEPFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC GLeeFuncPtr_glTexCoord4fColor4fNormal3fVertex4fSUN; + #define glTexCoord4fColor4fNormal3fVertex4fSUN GLeeFuncPtr_glTexCoord4fColor4fNormal3fVertex4fSUN +#endif +#ifndef GLEE_H_DEFINED_glTexCoord4fColor4fNormal3fVertex4fvSUN +#define GLEE_H_DEFINED_glTexCoord4fColor4fNormal3fVertex4fvSUN + typedef void (APIENTRYP GLEEPFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat * tc, const GLfloat * c, const GLfloat * n, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC GLeeFuncPtr_glTexCoord4fColor4fNormal3fVertex4fvSUN; + #define glTexCoord4fColor4fNormal3fVertex4fvSUN GLeeFuncPtr_glTexCoord4fColor4fNormal3fVertex4fvSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuiVertex3fSUN +#define GLEE_H_DEFINED_glReplacementCodeuiVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC GLeeFuncPtr_glReplacementCodeuiVertex3fSUN; + #define glReplacementCodeuiVertex3fSUN GLeeFuncPtr_glReplacementCodeuiVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuiVertex3fvSUN +#define GLEE_H_DEFINED_glReplacementCodeuiVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint * rc, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC GLeeFuncPtr_glReplacementCodeuiVertex3fvSUN; + #define glReplacementCodeuiVertex3fvSUN GLeeFuncPtr_glReplacementCodeuiVertex3fvSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuiColor4ubVertex3fSUN +#define GLEE_H_DEFINED_glReplacementCodeuiColor4ubVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC GLeeFuncPtr_glReplacementCodeuiColor4ubVertex3fSUN; + #define glReplacementCodeuiColor4ubVertex3fSUN GLeeFuncPtr_glReplacementCodeuiColor4ubVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuiColor4ubVertex3fvSUN +#define GLEE_H_DEFINED_glReplacementCodeuiColor4ubVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint * rc, const GLubyte * c, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC GLeeFuncPtr_glReplacementCodeuiColor4ubVertex3fvSUN; + #define glReplacementCodeuiColor4ubVertex3fvSUN GLeeFuncPtr_glReplacementCodeuiColor4ubVertex3fvSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuiColor3fVertex3fSUN +#define GLEE_H_DEFINED_glReplacementCodeuiColor3fVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC GLeeFuncPtr_glReplacementCodeuiColor3fVertex3fSUN; + #define glReplacementCodeuiColor3fVertex3fSUN GLeeFuncPtr_glReplacementCodeuiColor3fVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuiColor3fVertex3fvSUN +#define GLEE_H_DEFINED_glReplacementCodeuiColor3fVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint * rc, const GLfloat * c, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC GLeeFuncPtr_glReplacementCodeuiColor3fVertex3fvSUN; + #define glReplacementCodeuiColor3fVertex3fvSUN GLeeFuncPtr_glReplacementCodeuiColor3fVertex3fvSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuiNormal3fVertex3fSUN +#define GLEE_H_DEFINED_glReplacementCodeuiNormal3fVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC GLeeFuncPtr_glReplacementCodeuiNormal3fVertex3fSUN; + #define glReplacementCodeuiNormal3fVertex3fSUN GLeeFuncPtr_glReplacementCodeuiNormal3fVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuiNormal3fVertex3fvSUN +#define GLEE_H_DEFINED_glReplacementCodeuiNormal3fVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint * rc, const GLfloat * n, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC GLeeFuncPtr_glReplacementCodeuiNormal3fVertex3fvSUN; + #define glReplacementCodeuiNormal3fVertex3fvSUN GLeeFuncPtr_glReplacementCodeuiNormal3fVertex3fvSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuiColor4fNormal3fVertex3fSUN +#define GLEE_H_DEFINED_glReplacementCodeuiColor4fNormal3fVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC GLeeFuncPtr_glReplacementCodeuiColor4fNormal3fVertex3fSUN; + #define glReplacementCodeuiColor4fNormal3fVertex3fSUN GLeeFuncPtr_glReplacementCodeuiColor4fNormal3fVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuiColor4fNormal3fVertex3fvSUN +#define GLEE_H_DEFINED_glReplacementCodeuiColor4fNormal3fVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint * rc, const GLfloat * c, const GLfloat * n, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC GLeeFuncPtr_glReplacementCodeuiColor4fNormal3fVertex3fvSUN; + #define glReplacementCodeuiColor4fNormal3fVertex3fvSUN GLeeFuncPtr_glReplacementCodeuiColor4fNormal3fVertex3fvSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuiTexCoord2fVertex3fSUN +#define GLEE_H_DEFINED_glReplacementCodeuiTexCoord2fVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC GLeeFuncPtr_glReplacementCodeuiTexCoord2fVertex3fSUN; + #define glReplacementCodeuiTexCoord2fVertex3fSUN GLeeFuncPtr_glReplacementCodeuiTexCoord2fVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuiTexCoord2fVertex3fvSUN +#define GLEE_H_DEFINED_glReplacementCodeuiTexCoord2fVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint * rc, const GLfloat * tc, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC GLeeFuncPtr_glReplacementCodeuiTexCoord2fVertex3fvSUN; + #define glReplacementCodeuiTexCoord2fVertex3fvSUN GLeeFuncPtr_glReplacementCodeuiTexCoord2fVertex3fvSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN +#define GLEE_H_DEFINED_glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC GLeeFuncPtr_glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN; + #define glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN GLeeFuncPtr_glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN +#define GLEE_H_DEFINED_glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint * rc, const GLfloat * tc, const GLfloat * n, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC GLeeFuncPtr_glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN; + #define glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN GLeeFuncPtr_glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN +#define GLEE_H_DEFINED_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC GLeeFuncPtr_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN; + #define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN GLeeFuncPtr_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN +#endif +#ifndef GLEE_H_DEFINED_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN +#define GLEE_H_DEFINED_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN + typedef void (APIENTRYP GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint * rc, const GLfloat * tc, const GLfloat * c, const GLfloat * n, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC GLeeFuncPtr_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN; + #define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN GLeeFuncPtr_glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN +#endif +#endif + +/* GL_EXT_blend_func_separate */ + +#ifndef GL_EXT_blend_func_separate +#define GL_EXT_blend_func_separate 1 +#define __GLEE_GL_EXT_blend_func_separate 1 +/* Constants */ +#define GL_BLEND_DST_RGB_EXT 0x80C8 +#define GL_BLEND_SRC_RGB_EXT 0x80C9 +#define GL_BLEND_DST_ALPHA_EXT 0x80CA +#define GL_BLEND_SRC_ALPHA_EXT 0x80CB +#ifndef GLEE_H_DEFINED_glBlendFuncSeparateEXT +#define GLEE_H_DEFINED_glBlendFuncSeparateEXT + typedef void (APIENTRYP GLEEPFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + GLEE_EXTERN GLEEPFNGLBLENDFUNCSEPARATEEXTPROC GLeeFuncPtr_glBlendFuncSeparateEXT; + #define glBlendFuncSeparateEXT GLeeFuncPtr_glBlendFuncSeparateEXT +#endif +#endif + +/* GL_INGR_color_clamp */ + +#ifndef GL_INGR_color_clamp +#define GL_INGR_color_clamp 1 +#define __GLEE_GL_INGR_color_clamp 1 +/* Constants */ +#define GL_RED_MIN_CLAMP_INGR 0x8560 +#define GL_GREEN_MIN_CLAMP_INGR 0x8561 +#define GL_BLUE_MIN_CLAMP_INGR 0x8562 +#define GL_ALPHA_MIN_CLAMP_INGR 0x8563 +#define GL_RED_MAX_CLAMP_INGR 0x8564 +#define GL_GREEN_MAX_CLAMP_INGR 0x8565 +#define GL_BLUE_MAX_CLAMP_INGR 0x8566 +#define GL_ALPHA_MAX_CLAMP_INGR 0x8567 +#endif + +/* GL_INGR_interlace_read */ + +#ifndef GL_INGR_interlace_read +#define GL_INGR_interlace_read 1 +#define __GLEE_GL_INGR_interlace_read 1 +/* Constants */ +#define GL_INTERLACE_READ_INGR 0x8568 +#endif + +/* GL_EXT_stencil_wrap */ + +#ifndef GL_EXT_stencil_wrap +#define GL_EXT_stencil_wrap 1 +#define __GLEE_GL_EXT_stencil_wrap 1 +/* Constants */ +#define GL_INCR_WRAP_EXT 0x8507 +#define GL_DECR_WRAP_EXT 0x8508 +#endif + +/* GL_EXT_422_pixels */ + +#ifndef GL_EXT_422_pixels +#define GL_EXT_422_pixels 1 +#define __GLEE_GL_EXT_422_pixels 1 +/* Constants */ +#define GL_422_EXT 0x80CC +#define GL_422_REV_EXT 0x80CD +#define GL_422_AVERAGE_EXT 0x80CE +#define GL_422_REV_AVERAGE_EXT 0x80CF +#endif + +/* GL_NV_texgen_reflection */ + +#ifndef GL_NV_texgen_reflection +#define GL_NV_texgen_reflection 1 +#define __GLEE_GL_NV_texgen_reflection 1 +/* Constants */ +#define GL_NORMAL_MAP_NV 0x8511 +#define GL_REFLECTION_MAP_NV 0x8512 +#endif + +/* GL_EXT_texture_cube_map */ + +#ifndef GL_EXT_texture_cube_map +#define GL_EXT_texture_cube_map 1 +#define __GLEE_GL_EXT_texture_cube_map 1 +/* Constants */ +#define GL_NORMAL_MAP_EXT 0x8511 +#define GL_REFLECTION_MAP_EXT 0x8512 +#define GL_TEXTURE_CUBE_MAP_EXT 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C +#endif + +/* GL_SUN_convolution_border_modes */ + +#ifndef GL_SUN_convolution_border_modes +#define GL_SUN_convolution_border_modes 1 +#define __GLEE_GL_SUN_convolution_border_modes 1 +/* Constants */ +#define GL_WRAP_BORDER_SUN 0x81D4 +#endif + +/* GL_EXT_texture_env_add */ + +#ifndef GL_EXT_texture_env_add +#define GL_EXT_texture_env_add 1 +#define __GLEE_GL_EXT_texture_env_add 1 +/* Constants */ +#endif + +/* GL_EXT_texture_lod_bias */ + +#ifndef GL_EXT_texture_lod_bias +#define GL_EXT_texture_lod_bias 1 +#define __GLEE_GL_EXT_texture_lod_bias 1 +/* Constants */ +#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD +#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500 +#define GL_TEXTURE_LOD_BIAS_EXT 0x8501 +#endif + +/* GL_EXT_texture_filter_anisotropic */ + +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_EXT_texture_filter_anisotropic 1 +#define __GLEE_GL_EXT_texture_filter_anisotropic 1 +/* Constants */ +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#endif + +/* GL_EXT_vertex_weighting */ + +#ifndef GL_EXT_vertex_weighting +#define GL_EXT_vertex_weighting 1 +#define __GLEE_GL_EXT_vertex_weighting 1 +/* Constants */ +#define GL_MODELVIEW0_STACK_DEPTH_EXT GL_MODELVIEW_STACK_DEPTH +#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502 +#define GL_MODELVIEW0_MATRIX_EXT GL_MODELVIEW_MATRIX +#define GL_MODELVIEW1_MATRIX_EXT 0x8506 +#define GL_VERTEX_WEIGHTING_EXT 0x8509 +#define GL_MODELVIEW0_EXT GL_MODELVIEW +#define GL_MODELVIEW1_EXT 0x850A +#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B +#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C +#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D +#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E +#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F +#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 +#ifndef GLEE_H_DEFINED_glVertexWeightfEXT +#define GLEE_H_DEFINED_glVertexWeightfEXT + typedef void (APIENTRYP GLEEPFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight); + GLEE_EXTERN GLEEPFNGLVERTEXWEIGHTFEXTPROC GLeeFuncPtr_glVertexWeightfEXT; + #define glVertexWeightfEXT GLeeFuncPtr_glVertexWeightfEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexWeightfvEXT +#define GLEE_H_DEFINED_glVertexWeightfvEXT + typedef void (APIENTRYP GLEEPFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat * weight); + GLEE_EXTERN GLEEPFNGLVERTEXWEIGHTFVEXTPROC GLeeFuncPtr_glVertexWeightfvEXT; + #define glVertexWeightfvEXT GLeeFuncPtr_glVertexWeightfvEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexWeightPointerEXT +#define GLEE_H_DEFINED_glVertexWeightPointerEXT + typedef void (APIENTRYP GLEEPFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLsizei size, GLenum type, GLsizei stride, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLVERTEXWEIGHTPOINTEREXTPROC GLeeFuncPtr_glVertexWeightPointerEXT; + #define glVertexWeightPointerEXT GLeeFuncPtr_glVertexWeightPointerEXT +#endif +#endif + +/* GL_NV_light_max_exponent */ + +#ifndef GL_NV_light_max_exponent +#define GL_NV_light_max_exponent 1 +#define __GLEE_GL_NV_light_max_exponent 1 +/* Constants */ +#define GL_MAX_SHININESS_NV 0x8504 +#define GL_MAX_SPOT_EXPONENT_NV 0x8505 +#endif + +/* GL_NV_vertex_array_range */ + +#ifndef GL_NV_vertex_array_range +#define GL_NV_vertex_array_range 1 +#define __GLEE_GL_NV_vertex_array_range 1 +/* Constants */ +#define GL_VERTEX_ARRAY_RANGE_NV 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E +#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F +#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520 +#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 +#ifndef GLEE_H_DEFINED_glFlushVertexArrayRangeNV +#define GLEE_H_DEFINED_glFlushVertexArrayRangeNV + typedef void (APIENTRYP GLEEPFNGLFLUSHVERTEXARRAYRANGENVPROC) (); + GLEE_EXTERN GLEEPFNGLFLUSHVERTEXARRAYRANGENVPROC GLeeFuncPtr_glFlushVertexArrayRangeNV; + #define glFlushVertexArrayRangeNV GLeeFuncPtr_glFlushVertexArrayRangeNV +#endif +#ifndef GLEE_H_DEFINED_glVertexArrayRangeNV +#define GLEE_H_DEFINED_glVertexArrayRangeNV + typedef void (APIENTRYP GLEEPFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLVERTEXARRAYRANGENVPROC GLeeFuncPtr_glVertexArrayRangeNV; + #define glVertexArrayRangeNV GLeeFuncPtr_glVertexArrayRangeNV +#endif +#endif + +/* GL_NV_register_combiners */ + +#ifndef GL_NV_register_combiners +#define GL_NV_register_combiners 1 +#define __GLEE_GL_NV_register_combiners 1 +/* Constants */ +#define GL_REGISTER_COMBINERS_NV 0x8522 +#define GL_VARIABLE_A_NV 0x8523 +#define GL_VARIABLE_B_NV 0x8524 +#define GL_VARIABLE_C_NV 0x8525 +#define GL_VARIABLE_D_NV 0x8526 +#define GL_VARIABLE_E_NV 0x8527 +#define GL_VARIABLE_F_NV 0x8528 +#define GL_VARIABLE_G_NV 0x8529 +#define GL_CONSTANT_COLOR0_NV 0x852A +#define GL_CONSTANT_COLOR1_NV 0x852B +#define GL_PRIMARY_COLOR_NV 0x852C +#define GL_SECONDARY_COLOR_NV 0x852D +#define GL_SPARE0_NV 0x852E +#define GL_SPARE1_NV 0x852F +#define GL_DISCARD_NV 0x8530 +#define GL_E_TIMES_F_NV 0x8531 +#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532 +#define GL_UNSIGNED_IDENTITY_NV 0x8536 +#define GL_UNSIGNED_INVERT_NV 0x8537 +#define GL_EXPAND_NORMAL_NV 0x8538 +#define GL_EXPAND_NEGATE_NV 0x8539 +#define GL_HALF_BIAS_NORMAL_NV 0x853A +#define GL_HALF_BIAS_NEGATE_NV 0x853B +#define GL_SIGNED_IDENTITY_NV 0x853C +#define GL_SIGNED_NEGATE_NV 0x853D +#define GL_SCALE_BY_TWO_NV 0x853E +#define GL_SCALE_BY_FOUR_NV 0x853F +#define GL_SCALE_BY_ONE_HALF_NV 0x8540 +#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541 +#define GL_COMBINER_INPUT_NV 0x8542 +#define GL_COMBINER_MAPPING_NV 0x8543 +#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544 +#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545 +#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546 +#define GL_COMBINER_MUX_SUM_NV 0x8547 +#define GL_COMBINER_SCALE_NV 0x8548 +#define GL_COMBINER_BIAS_NV 0x8549 +#define GL_COMBINER_AB_OUTPUT_NV 0x854A +#define GL_COMBINER_CD_OUTPUT_NV 0x854B +#define GL_COMBINER_SUM_OUTPUT_NV 0x854C +#define GL_MAX_GENERAL_COMBINERS_NV 0x854D +#define GL_NUM_GENERAL_COMBINERS_NV 0x854E +#define GL_COLOR_SUM_CLAMP_NV 0x854F +#define GL_COMBINER0_NV 0x8550 +#define GL_COMBINER1_NV 0x8551 +#define GL_COMBINER2_NV 0x8552 +#define GL_COMBINER3_NV 0x8553 +#define GL_COMBINER4_NV 0x8554 +#define GL_COMBINER5_NV 0x8555 +#define GL_COMBINER6_NV 0x8556 +#define GL_COMBINER7_NV 0x8557 +#ifndef GLEE_H_DEFINED_glCombinerParameterfvNV +#define GLEE_H_DEFINED_glCombinerParameterfvNV + typedef void (APIENTRYP GLEEPFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLCOMBINERPARAMETERFVNVPROC GLeeFuncPtr_glCombinerParameterfvNV; + #define glCombinerParameterfvNV GLeeFuncPtr_glCombinerParameterfvNV +#endif +#ifndef GLEE_H_DEFINED_glCombinerParameterfNV +#define GLEE_H_DEFINED_glCombinerParameterfNV + typedef void (APIENTRYP GLEEPFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLCOMBINERPARAMETERFNVPROC GLeeFuncPtr_glCombinerParameterfNV; + #define glCombinerParameterfNV GLeeFuncPtr_glCombinerParameterfNV +#endif +#ifndef GLEE_H_DEFINED_glCombinerParameterivNV +#define GLEE_H_DEFINED_glCombinerParameterivNV + typedef void (APIENTRYP GLEEPFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLCOMBINERPARAMETERIVNVPROC GLeeFuncPtr_glCombinerParameterivNV; + #define glCombinerParameterivNV GLeeFuncPtr_glCombinerParameterivNV +#endif +#ifndef GLEE_H_DEFINED_glCombinerParameteriNV +#define GLEE_H_DEFINED_glCombinerParameteriNV + typedef void (APIENTRYP GLEEPFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLCOMBINERPARAMETERINVPROC GLeeFuncPtr_glCombinerParameteriNV; + #define glCombinerParameteriNV GLeeFuncPtr_glCombinerParameteriNV +#endif +#ifndef GLEE_H_DEFINED_glCombinerInputNV +#define GLEE_H_DEFINED_glCombinerInputNV + typedef void (APIENTRYP GLEEPFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); + GLEE_EXTERN GLEEPFNGLCOMBINERINPUTNVPROC GLeeFuncPtr_glCombinerInputNV; + #define glCombinerInputNV GLeeFuncPtr_glCombinerInputNV +#endif +#ifndef GLEE_H_DEFINED_glCombinerOutputNV +#define GLEE_H_DEFINED_glCombinerOutputNV + typedef void (APIENTRYP GLEEPFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); + GLEE_EXTERN GLEEPFNGLCOMBINEROUTPUTNVPROC GLeeFuncPtr_glCombinerOutputNV; + #define glCombinerOutputNV GLeeFuncPtr_glCombinerOutputNV +#endif +#ifndef GLEE_H_DEFINED_glFinalCombinerInputNV +#define GLEE_H_DEFINED_glFinalCombinerInputNV + typedef void (APIENTRYP GLEEPFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); + GLEE_EXTERN GLEEPFNGLFINALCOMBINERINPUTNVPROC GLeeFuncPtr_glFinalCombinerInputNV; + #define glFinalCombinerInputNV GLeeFuncPtr_glFinalCombinerInputNV +#endif +#ifndef GLEE_H_DEFINED_glGetCombinerInputParameterfvNV +#define GLEE_H_DEFINED_glGetCombinerInputParameterfvNV + typedef void (APIENTRYP GLEEPFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETCOMBINERINPUTPARAMETERFVNVPROC GLeeFuncPtr_glGetCombinerInputParameterfvNV; + #define glGetCombinerInputParameterfvNV GLeeFuncPtr_glGetCombinerInputParameterfvNV +#endif +#ifndef GLEE_H_DEFINED_glGetCombinerInputParameterivNV +#define GLEE_H_DEFINED_glGetCombinerInputParameterivNV + typedef void (APIENTRYP GLEEPFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETCOMBINERINPUTPARAMETERIVNVPROC GLeeFuncPtr_glGetCombinerInputParameterivNV; + #define glGetCombinerInputParameterivNV GLeeFuncPtr_glGetCombinerInputParameterivNV +#endif +#ifndef GLEE_H_DEFINED_glGetCombinerOutputParameterfvNV +#define GLEE_H_DEFINED_glGetCombinerOutputParameterfvNV + typedef void (APIENTRYP GLEEPFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC GLeeFuncPtr_glGetCombinerOutputParameterfvNV; + #define glGetCombinerOutputParameterfvNV GLeeFuncPtr_glGetCombinerOutputParameterfvNV +#endif +#ifndef GLEE_H_DEFINED_glGetCombinerOutputParameterivNV +#define GLEE_H_DEFINED_glGetCombinerOutputParameterivNV + typedef void (APIENTRYP GLEEPFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC GLeeFuncPtr_glGetCombinerOutputParameterivNV; + #define glGetCombinerOutputParameterivNV GLeeFuncPtr_glGetCombinerOutputParameterivNV +#endif +#ifndef GLEE_H_DEFINED_glGetFinalCombinerInputParameterfvNV +#define GLEE_H_DEFINED_glGetFinalCombinerInputParameterfvNV + typedef void (APIENTRYP GLEEPFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC GLeeFuncPtr_glGetFinalCombinerInputParameterfvNV; + #define glGetFinalCombinerInputParameterfvNV GLeeFuncPtr_glGetFinalCombinerInputParameterfvNV +#endif +#ifndef GLEE_H_DEFINED_glGetFinalCombinerInputParameterivNV +#define GLEE_H_DEFINED_glGetFinalCombinerInputParameterivNV + typedef void (APIENTRYP GLEEPFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC GLeeFuncPtr_glGetFinalCombinerInputParameterivNV; + #define glGetFinalCombinerInputParameterivNV GLeeFuncPtr_glGetFinalCombinerInputParameterivNV +#endif +#endif + +/* GL_NV_fog_distance */ + +#ifndef GL_NV_fog_distance +#define GL_NV_fog_distance 1 +#define __GLEE_GL_NV_fog_distance 1 +/* Constants */ +#define GL_FOG_DISTANCE_MODE_NV 0x855A +#define GL_EYE_RADIAL_NV 0x855B +#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C +#endif + +/* GL_NV_texgen_emboss */ + +#ifndef GL_NV_texgen_emboss +#define GL_NV_texgen_emboss 1 +#define __GLEE_GL_NV_texgen_emboss 1 +/* Constants */ +#define GL_EMBOSS_LIGHT_NV 0x855D +#define GL_EMBOSS_CONSTANT_NV 0x855E +#define GL_EMBOSS_MAP_NV 0x855F +#endif + +/* GL_NV_blend_square */ + +#ifndef GL_NV_blend_square +#define GL_NV_blend_square 1 +#define __GLEE_GL_NV_blend_square 1 +/* Constants */ +#endif + +/* GL_NV_texture_env_combine4 */ + +#ifndef GL_NV_texture_env_combine4 +#define GL_NV_texture_env_combine4 1 +#define __GLEE_GL_NV_texture_env_combine4 1 +/* Constants */ +#define GL_COMBINE4_NV 0x8503 +#define GL_SOURCE3_RGB_NV 0x8583 +#define GL_SOURCE3_ALPHA_NV 0x858B +#define GL_OPERAND3_RGB_NV 0x8593 +#define GL_OPERAND3_ALPHA_NV 0x859B +#endif + +/* GL_MESA_resize_buffers */ + +#ifndef GL_MESA_resize_buffers +#define GL_MESA_resize_buffers 1 +#define __GLEE_GL_MESA_resize_buffers 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glResizeBuffersMESA +#define GLEE_H_DEFINED_glResizeBuffersMESA + typedef void (APIENTRYP GLEEPFNGLRESIZEBUFFERSMESAPROC) (); + GLEE_EXTERN GLEEPFNGLRESIZEBUFFERSMESAPROC GLeeFuncPtr_glResizeBuffersMESA; + #define glResizeBuffersMESA GLeeFuncPtr_glResizeBuffersMESA +#endif +#endif + +/* GL_MESA_window_pos */ + +#ifndef GL_MESA_window_pos +#define GL_MESA_window_pos 1 +#define __GLEE_GL_MESA_window_pos 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glWindowPos2dMESA +#define GLEE_H_DEFINED_glWindowPos2dMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2DMESAPROC GLeeFuncPtr_glWindowPos2dMESA; + #define glWindowPos2dMESA GLeeFuncPtr_glWindowPos2dMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2dvMESA +#define GLEE_H_DEFINED_glWindowPos2dvMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2DVMESAPROC) (const GLdouble * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2DVMESAPROC GLeeFuncPtr_glWindowPos2dvMESA; + #define glWindowPos2dvMESA GLeeFuncPtr_glWindowPos2dvMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2fMESA +#define GLEE_H_DEFINED_glWindowPos2fMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2FMESAPROC GLeeFuncPtr_glWindowPos2fMESA; + #define glWindowPos2fMESA GLeeFuncPtr_glWindowPos2fMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2fvMESA +#define GLEE_H_DEFINED_glWindowPos2fvMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2FVMESAPROC) (const GLfloat * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2FVMESAPROC GLeeFuncPtr_glWindowPos2fvMESA; + #define glWindowPos2fvMESA GLeeFuncPtr_glWindowPos2fvMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2iMESA +#define GLEE_H_DEFINED_glWindowPos2iMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2IMESAPROC GLeeFuncPtr_glWindowPos2iMESA; + #define glWindowPos2iMESA GLeeFuncPtr_glWindowPos2iMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2ivMESA +#define GLEE_H_DEFINED_glWindowPos2ivMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2IVMESAPROC) (const GLint * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2IVMESAPROC GLeeFuncPtr_glWindowPos2ivMESA; + #define glWindowPos2ivMESA GLeeFuncPtr_glWindowPos2ivMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2sMESA +#define GLEE_H_DEFINED_glWindowPos2sMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2SMESAPROC GLeeFuncPtr_glWindowPos2sMESA; + #define glWindowPos2sMESA GLeeFuncPtr_glWindowPos2sMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos2svMESA +#define GLEE_H_DEFINED_glWindowPos2svMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS2SVMESAPROC) (const GLshort * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS2SVMESAPROC GLeeFuncPtr_glWindowPos2svMESA; + #define glWindowPos2svMESA GLeeFuncPtr_glWindowPos2svMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3dMESA +#define GLEE_H_DEFINED_glWindowPos3dMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3DMESAPROC GLeeFuncPtr_glWindowPos3dMESA; + #define glWindowPos3dMESA GLeeFuncPtr_glWindowPos3dMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3dvMESA +#define GLEE_H_DEFINED_glWindowPos3dvMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3DVMESAPROC) (const GLdouble * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3DVMESAPROC GLeeFuncPtr_glWindowPos3dvMESA; + #define glWindowPos3dvMESA GLeeFuncPtr_glWindowPos3dvMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3fMESA +#define GLEE_H_DEFINED_glWindowPos3fMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3FMESAPROC GLeeFuncPtr_glWindowPos3fMESA; + #define glWindowPos3fMESA GLeeFuncPtr_glWindowPos3fMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3fvMESA +#define GLEE_H_DEFINED_glWindowPos3fvMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3FVMESAPROC) (const GLfloat * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3FVMESAPROC GLeeFuncPtr_glWindowPos3fvMESA; + #define glWindowPos3fvMESA GLeeFuncPtr_glWindowPos3fvMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3iMESA +#define GLEE_H_DEFINED_glWindowPos3iMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3IMESAPROC GLeeFuncPtr_glWindowPos3iMESA; + #define glWindowPos3iMESA GLeeFuncPtr_glWindowPos3iMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3ivMESA +#define GLEE_H_DEFINED_glWindowPos3ivMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3IVMESAPROC) (const GLint * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3IVMESAPROC GLeeFuncPtr_glWindowPos3ivMESA; + #define glWindowPos3ivMESA GLeeFuncPtr_glWindowPos3ivMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3sMESA +#define GLEE_H_DEFINED_glWindowPos3sMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3SMESAPROC GLeeFuncPtr_glWindowPos3sMESA; + #define glWindowPos3sMESA GLeeFuncPtr_glWindowPos3sMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos3svMESA +#define GLEE_H_DEFINED_glWindowPos3svMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS3SVMESAPROC) (const GLshort * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS3SVMESAPROC GLeeFuncPtr_glWindowPos3svMESA; + #define glWindowPos3svMESA GLeeFuncPtr_glWindowPos3svMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos4dMESA +#define GLEE_H_DEFINED_glWindowPos4dMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w); + GLEE_EXTERN GLEEPFNGLWINDOWPOS4DMESAPROC GLeeFuncPtr_glWindowPos4dMESA; + #define glWindowPos4dMESA GLeeFuncPtr_glWindowPos4dMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos4dvMESA +#define GLEE_H_DEFINED_glWindowPos4dvMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS4DVMESAPROC) (const GLdouble * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS4DVMESAPROC GLeeFuncPtr_glWindowPos4dvMESA; + #define glWindowPos4dvMESA GLeeFuncPtr_glWindowPos4dvMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos4fMESA +#define GLEE_H_DEFINED_glWindowPos4fMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); + GLEE_EXTERN GLEEPFNGLWINDOWPOS4FMESAPROC GLeeFuncPtr_glWindowPos4fMESA; + #define glWindowPos4fMESA GLeeFuncPtr_glWindowPos4fMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos4fvMESA +#define GLEE_H_DEFINED_glWindowPos4fvMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS4FVMESAPROC) (const GLfloat * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS4FVMESAPROC GLeeFuncPtr_glWindowPos4fvMESA; + #define glWindowPos4fvMESA GLeeFuncPtr_glWindowPos4fvMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos4iMESA +#define GLEE_H_DEFINED_glWindowPos4iMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w); + GLEE_EXTERN GLEEPFNGLWINDOWPOS4IMESAPROC GLeeFuncPtr_glWindowPos4iMESA; + #define glWindowPos4iMESA GLeeFuncPtr_glWindowPos4iMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos4ivMESA +#define GLEE_H_DEFINED_glWindowPos4ivMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS4IVMESAPROC) (const GLint * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS4IVMESAPROC GLeeFuncPtr_glWindowPos4ivMESA; + #define glWindowPos4ivMESA GLeeFuncPtr_glWindowPos4ivMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos4sMESA +#define GLEE_H_DEFINED_glWindowPos4sMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w); + GLEE_EXTERN GLEEPFNGLWINDOWPOS4SMESAPROC GLeeFuncPtr_glWindowPos4sMESA; + #define glWindowPos4sMESA GLeeFuncPtr_glWindowPos4sMESA +#endif +#ifndef GLEE_H_DEFINED_glWindowPos4svMESA +#define GLEE_H_DEFINED_glWindowPos4svMESA + typedef void (APIENTRYP GLEEPFNGLWINDOWPOS4SVMESAPROC) (const GLshort * v); + GLEE_EXTERN GLEEPFNGLWINDOWPOS4SVMESAPROC GLeeFuncPtr_glWindowPos4svMESA; + #define glWindowPos4svMESA GLeeFuncPtr_glWindowPos4svMESA +#endif +#endif + +/* GL_EXT_texture_compression_s3tc */ + +#ifndef GL_EXT_texture_compression_s3tc +#define GL_EXT_texture_compression_s3tc 1 +#define __GLEE_GL_EXT_texture_compression_s3tc 1 +/* Constants */ +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 +#endif + +/* GL_IBM_cull_vertex */ + +#ifndef GL_IBM_cull_vertex +#define GL_IBM_cull_vertex 1 +#define __GLEE_GL_IBM_cull_vertex 1 +/* Constants */ +#define GL_CULL_VERTEX_IBM 103050 +#endif + +/* GL_IBM_multimode_draw_arrays */ + +#ifndef GL_IBM_multimode_draw_arrays +#define GL_IBM_multimode_draw_arrays 1 +#define __GLEE_GL_IBM_multimode_draw_arrays 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glMultiModeDrawArraysIBM +#define GLEE_H_DEFINED_glMultiModeDrawArraysIBM + typedef void (APIENTRYP GLEEPFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum * mode, const GLint * first, const GLsizei * count, GLsizei primcount, GLint modestride); + GLEE_EXTERN GLEEPFNGLMULTIMODEDRAWARRAYSIBMPROC GLeeFuncPtr_glMultiModeDrawArraysIBM; + #define glMultiModeDrawArraysIBM GLeeFuncPtr_glMultiModeDrawArraysIBM +#endif +#ifndef GLEE_H_DEFINED_glMultiModeDrawElementsIBM +#define GLEE_H_DEFINED_glMultiModeDrawElementsIBM + typedef void (APIENTRYP GLEEPFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum * mode, const GLsizei * count, GLenum type, const GLvoid* const * indices, GLsizei primcount, GLint modestride); + GLEE_EXTERN GLEEPFNGLMULTIMODEDRAWELEMENTSIBMPROC GLeeFuncPtr_glMultiModeDrawElementsIBM; + #define glMultiModeDrawElementsIBM GLeeFuncPtr_glMultiModeDrawElementsIBM +#endif +#endif + +/* GL_IBM_vertex_array_lists */ + +#ifndef GL_IBM_vertex_array_lists +#define GL_IBM_vertex_array_lists 1 +#define __GLEE_GL_IBM_vertex_array_lists 1 +/* Constants */ +#define GL_VERTEX_ARRAY_LIST_IBM 103070 +#define GL_NORMAL_ARRAY_LIST_IBM 103071 +#define GL_COLOR_ARRAY_LIST_IBM 103072 +#define GL_INDEX_ARRAY_LIST_IBM 103073 +#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074 +#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075 +#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076 +#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077 +#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080 +#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081 +#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082 +#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083 +#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084 +#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085 +#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086 +#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087 +#ifndef GLEE_H_DEFINED_glColorPointerListIBM +#define GLEE_H_DEFINED_glColorPointerListIBM + typedef void (APIENTRYP GLEEPFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* * pointer, GLint ptrstride); + GLEE_EXTERN GLEEPFNGLCOLORPOINTERLISTIBMPROC GLeeFuncPtr_glColorPointerListIBM; + #define glColorPointerListIBM GLeeFuncPtr_glColorPointerListIBM +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColorPointerListIBM +#define GLEE_H_DEFINED_glSecondaryColorPointerListIBM + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* * pointer, GLint ptrstride); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLORPOINTERLISTIBMPROC GLeeFuncPtr_glSecondaryColorPointerListIBM; + #define glSecondaryColorPointerListIBM GLeeFuncPtr_glSecondaryColorPointerListIBM +#endif +#ifndef GLEE_H_DEFINED_glEdgeFlagPointerListIBM +#define GLEE_H_DEFINED_glEdgeFlagPointerListIBM + typedef void (APIENTRYP GLEEPFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean* * pointer, GLint ptrstride); + GLEE_EXTERN GLEEPFNGLEDGEFLAGPOINTERLISTIBMPROC GLeeFuncPtr_glEdgeFlagPointerListIBM; + #define glEdgeFlagPointerListIBM GLeeFuncPtr_glEdgeFlagPointerListIBM +#endif +#ifndef GLEE_H_DEFINED_glFogCoordPointerListIBM +#define GLEE_H_DEFINED_glFogCoordPointerListIBM + typedef void (APIENTRYP GLEEPFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* * pointer, GLint ptrstride); + GLEE_EXTERN GLEEPFNGLFOGCOORDPOINTERLISTIBMPROC GLeeFuncPtr_glFogCoordPointerListIBM; + #define glFogCoordPointerListIBM GLeeFuncPtr_glFogCoordPointerListIBM +#endif +#ifndef GLEE_H_DEFINED_glIndexPointerListIBM +#define GLEE_H_DEFINED_glIndexPointerListIBM + typedef void (APIENTRYP GLEEPFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* * pointer, GLint ptrstride); + GLEE_EXTERN GLEEPFNGLINDEXPOINTERLISTIBMPROC GLeeFuncPtr_glIndexPointerListIBM; + #define glIndexPointerListIBM GLeeFuncPtr_glIndexPointerListIBM +#endif +#ifndef GLEE_H_DEFINED_glNormalPointerListIBM +#define GLEE_H_DEFINED_glNormalPointerListIBM + typedef void (APIENTRYP GLEEPFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* * pointer, GLint ptrstride); + GLEE_EXTERN GLEEPFNGLNORMALPOINTERLISTIBMPROC GLeeFuncPtr_glNormalPointerListIBM; + #define glNormalPointerListIBM GLeeFuncPtr_glNormalPointerListIBM +#endif +#ifndef GLEE_H_DEFINED_glTexCoordPointerListIBM +#define GLEE_H_DEFINED_glTexCoordPointerListIBM + typedef void (APIENTRYP GLEEPFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* * pointer, GLint ptrstride); + GLEE_EXTERN GLEEPFNGLTEXCOORDPOINTERLISTIBMPROC GLeeFuncPtr_glTexCoordPointerListIBM; + #define glTexCoordPointerListIBM GLeeFuncPtr_glTexCoordPointerListIBM +#endif +#ifndef GLEE_H_DEFINED_glVertexPointerListIBM +#define GLEE_H_DEFINED_glVertexPointerListIBM + typedef void (APIENTRYP GLEEPFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* * pointer, GLint ptrstride); + GLEE_EXTERN GLEEPFNGLVERTEXPOINTERLISTIBMPROC GLeeFuncPtr_glVertexPointerListIBM; + #define glVertexPointerListIBM GLeeFuncPtr_glVertexPointerListIBM +#endif +#endif + +/* GL_SGIX_subsample */ + +#ifndef GL_SGIX_subsample +#define GL_SGIX_subsample 1 +#define __GLEE_GL_SGIX_subsample 1 +/* Constants */ +#define GL_PACK_SUBSAMPLE_RATE_SGIX 0x85A0 +#define GL_UNPACK_SUBSAMPLE_RATE_SGIX 0x85A1 +#define GL_PIXEL_SUBSAMPLE_4444_SGIX 0x85A2 +#define GL_PIXEL_SUBSAMPLE_2424_SGIX 0x85A3 +#define GL_PIXEL_SUBSAMPLE_4242_SGIX 0x85A4 +#endif + +/* GL_SGIX_ycrcb_subsample */ + +#ifndef GL_SGIX_ycrcb_subsample +#define GL_SGIX_ycrcb_subsample 1 +#define __GLEE_GL_SGIX_ycrcb_subsample 1 +/* Constants */ +#endif + +/* GL_SGIX_ycrcba */ + +#ifndef GL_SGIX_ycrcba +#define GL_SGIX_ycrcba 1 +#define __GLEE_GL_SGIX_ycrcba 1 +/* Constants */ +#define GL_YCRCB_SGIX 0x8318 +#define GL_YCRCBA_SGIX 0x8319 +#endif + +/* GL_SGI_depth_pass_instrument */ + +#ifndef GL_SGI_depth_pass_instrument +#define GL_SGI_depth_pass_instrument 1 +#define __GLEE_GL_SGI_depth_pass_instrument 1 +/* Constants */ +#define GL_DEPTH_PASS_INSTRUMENT_SGIX 0x8310 +#define GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX 0x8311 +#define GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX 0x8312 +#endif + +/* GL_3DFX_texture_compression_FXT1 */ + +#ifndef GL_3DFX_texture_compression_FXT1 +#define GL_3DFX_texture_compression_FXT1 1 +#define __GLEE_GL_3DFX_texture_compression_FXT1 1 +/* Constants */ +#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0 +#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1 +#endif + +/* GL_3DFX_multisample */ + +#ifndef GL_3DFX_multisample +#define GL_3DFX_multisample 1 +#define __GLEE_GL_3DFX_multisample 1 +/* Constants */ +#define GL_MULTISAMPLE_3DFX 0x86B2 +#define GL_SAMPLE_BUFFERS_3DFX 0x86B3 +#define GL_SAMPLES_3DFX 0x86B4 +#define GL_MULTISAMPLE_BIT_3DFX 0x20000000 +#endif + +/* GL_3DFX_tbuffer */ + +#ifndef GL_3DFX_tbuffer +#define GL_3DFX_tbuffer 1 +#define __GLEE_GL_3DFX_tbuffer 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glTbufferMask3DFX +#define GLEE_H_DEFINED_glTbufferMask3DFX + typedef void (APIENTRYP GLEEPFNGLTBUFFERMASK3DFXPROC) (GLuint mask); + GLEE_EXTERN GLEEPFNGLTBUFFERMASK3DFXPROC GLeeFuncPtr_glTbufferMask3DFX; + #define glTbufferMask3DFX GLeeFuncPtr_glTbufferMask3DFX +#endif +#endif + +/* GL_EXT_multisample */ + +#ifndef GL_EXT_multisample +#define GL_EXT_multisample 1 +#define __GLEE_GL_EXT_multisample 1 +/* Constants */ +#define GL_MULTISAMPLE_EXT 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F +#define GL_SAMPLE_MASK_EXT 0x80A0 +#define GL_1PASS_EXT 0x80A1 +#define GL_2PASS_0_EXT 0x80A2 +#define GL_2PASS_1_EXT 0x80A3 +#define GL_4PASS_0_EXT 0x80A4 +#define GL_4PASS_1_EXT 0x80A5 +#define GL_4PASS_2_EXT 0x80A6 +#define GL_4PASS_3_EXT 0x80A7 +#define GL_SAMPLE_BUFFERS_EXT 0x80A8 +#define GL_SAMPLES_EXT 0x80A9 +#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA +#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB +#define GL_SAMPLE_PATTERN_EXT 0x80AC +#define GL_MULTISAMPLE_BIT_EXT 0x20000000 +#ifndef GLEE_H_DEFINED_glSampleMaskEXT +#define GLEE_H_DEFINED_glSampleMaskEXT + typedef void (APIENTRYP GLEEPFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert); + GLEE_EXTERN GLEEPFNGLSAMPLEMASKEXTPROC GLeeFuncPtr_glSampleMaskEXT; + #define glSampleMaskEXT GLeeFuncPtr_glSampleMaskEXT +#endif +#ifndef GLEE_H_DEFINED_glSamplePatternEXT +#define GLEE_H_DEFINED_glSamplePatternEXT + typedef void (APIENTRYP GLEEPFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); + GLEE_EXTERN GLEEPFNGLSAMPLEPATTERNEXTPROC GLeeFuncPtr_glSamplePatternEXT; + #define glSamplePatternEXT GLeeFuncPtr_glSamplePatternEXT +#endif +#endif + +/* GL_SGIX_vertex_preclip */ + +#ifndef GL_SGIX_vertex_preclip +#define GL_SGIX_vertex_preclip 1 +#define __GLEE_GL_SGIX_vertex_preclip 1 +/* Constants */ +#define GL_VERTEX_PRECLIP_SGIX 0x83EE +#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF +#endif + +/* GL_SGIX_convolution_accuracy */ + +#ifndef GL_SGIX_convolution_accuracy +#define GL_SGIX_convolution_accuracy 1 +#define __GLEE_GL_SGIX_convolution_accuracy 1 +/* Constants */ +#define GL_CONVOLUTION_HINT_SGIX 0x8316 +#endif + +/* GL_SGIX_resample */ + +#ifndef GL_SGIX_resample +#define GL_SGIX_resample 1 +#define __GLEE_GL_SGIX_resample 1 +/* Constants */ +#define GL_PACK_RESAMPLE_SGIX 0x842C +#define GL_UNPACK_RESAMPLE_SGIX 0x842D +#define GL_RESAMPLE_REPLICATE_SGIX 0x842E +#define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F +#define GL_RESAMPLE_DECIMATE_SGIX 0x8430 +#endif + +/* GL_SGIS_point_line_texgen */ + +#ifndef GL_SGIS_point_line_texgen +#define GL_SGIS_point_line_texgen 1 +#define __GLEE_GL_SGIS_point_line_texgen 1 +/* Constants */ +#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0 +#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1 +#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2 +#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3 +#define GL_EYE_POINT_SGIS 0x81F4 +#define GL_OBJECT_POINT_SGIS 0x81F5 +#define GL_EYE_LINE_SGIS 0x81F6 +#define GL_OBJECT_LINE_SGIS 0x81F7 +#endif + +/* GL_SGIS_texture_color_mask */ + +#ifndef GL_SGIS_texture_color_mask +#define GL_SGIS_texture_color_mask 1 +#define __GLEE_GL_SGIS_texture_color_mask 1 +/* Constants */ +#define GL_TEXTURE_COLOR_WRITEMASK_SGIS 0x81EF +#ifndef GLEE_H_DEFINED_glTextureColorMaskSGIS +#define GLEE_H_DEFINED_glTextureColorMaskSGIS + typedef void (APIENTRYP GLEEPFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); + GLEE_EXTERN GLEEPFNGLTEXTURECOLORMASKSGISPROC GLeeFuncPtr_glTextureColorMaskSGIS; + #define glTextureColorMaskSGIS GLeeFuncPtr_glTextureColorMaskSGIS +#endif +#endif + +/* GL_EXT_texture_env_dot3 */ + +#ifndef GL_EXT_texture_env_dot3 +#define GL_EXT_texture_env_dot3 1 +#define __GLEE_GL_EXT_texture_env_dot3 1 +/* Constants */ +#define GL_DOT3_RGB_EXT 0x8740 +#define GL_DOT3_RGBA_EXT 0x8741 +#endif + +/* GL_ATI_texture_mirror_once */ + +#ifndef GL_ATI_texture_mirror_once +#define GL_ATI_texture_mirror_once 1 +#define __GLEE_GL_ATI_texture_mirror_once 1 +/* Constants */ +#define GL_MIRROR_CLAMP_ATI 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743 +#endif + +/* GL_NV_fence */ + +#ifndef GL_NV_fence +#define GL_NV_fence 1 +#define __GLEE_GL_NV_fence 1 +/* Constants */ +#define GL_ALL_COMPLETED_NV 0x84F2 +#define GL_FENCE_STATUS_NV 0x84F3 +#define GL_FENCE_CONDITION_NV 0x84F4 +#ifndef GLEE_H_DEFINED_glDeleteFencesNV +#define GLEE_H_DEFINED_glDeleteFencesNV + typedef void (APIENTRYP GLEEPFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint * fences); + GLEE_EXTERN GLEEPFNGLDELETEFENCESNVPROC GLeeFuncPtr_glDeleteFencesNV; + #define glDeleteFencesNV GLeeFuncPtr_glDeleteFencesNV +#endif +#ifndef GLEE_H_DEFINED_glGenFencesNV +#define GLEE_H_DEFINED_glGenFencesNV + typedef void (APIENTRYP GLEEPFNGLGENFENCESNVPROC) (GLsizei n, GLuint * fences); + GLEE_EXTERN GLEEPFNGLGENFENCESNVPROC GLeeFuncPtr_glGenFencesNV; + #define glGenFencesNV GLeeFuncPtr_glGenFencesNV +#endif +#ifndef GLEE_H_DEFINED_glIsFenceNV +#define GLEE_H_DEFINED_glIsFenceNV + typedef GLboolean (APIENTRYP GLEEPFNGLISFENCENVPROC) (GLuint fence); + GLEE_EXTERN GLEEPFNGLISFENCENVPROC GLeeFuncPtr_glIsFenceNV; + #define glIsFenceNV GLeeFuncPtr_glIsFenceNV +#endif +#ifndef GLEE_H_DEFINED_glTestFenceNV +#define GLEE_H_DEFINED_glTestFenceNV + typedef GLboolean (APIENTRYP GLEEPFNGLTESTFENCENVPROC) (GLuint fence); + GLEE_EXTERN GLEEPFNGLTESTFENCENVPROC GLeeFuncPtr_glTestFenceNV; + #define glTestFenceNV GLeeFuncPtr_glTestFenceNV +#endif +#ifndef GLEE_H_DEFINED_glGetFenceivNV +#define GLEE_H_DEFINED_glGetFenceivNV + typedef void (APIENTRYP GLEEPFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETFENCEIVNVPROC GLeeFuncPtr_glGetFenceivNV; + #define glGetFenceivNV GLeeFuncPtr_glGetFenceivNV +#endif +#ifndef GLEE_H_DEFINED_glFinishFenceNV +#define GLEE_H_DEFINED_glFinishFenceNV + typedef void (APIENTRYP GLEEPFNGLFINISHFENCENVPROC) (GLuint fence); + GLEE_EXTERN GLEEPFNGLFINISHFENCENVPROC GLeeFuncPtr_glFinishFenceNV; + #define glFinishFenceNV GLeeFuncPtr_glFinishFenceNV +#endif +#ifndef GLEE_H_DEFINED_glSetFenceNV +#define GLEE_H_DEFINED_glSetFenceNV + typedef void (APIENTRYP GLEEPFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); + GLEE_EXTERN GLEEPFNGLSETFENCENVPROC GLeeFuncPtr_glSetFenceNV; + #define glSetFenceNV GLeeFuncPtr_glSetFenceNV +#endif +#endif + +/* GL_IBM_texture_mirrored_repeat */ + +#ifndef GL_IBM_texture_mirrored_repeat +#define GL_IBM_texture_mirrored_repeat 1 +#define __GLEE_GL_IBM_texture_mirrored_repeat 1 +/* Constants */ +#define GL_MIRRORED_REPEAT_IBM 0x8370 +#endif + +/* GL_NV_evaluators */ + +#ifndef GL_NV_evaluators +#define GL_NV_evaluators 1 +#define __GLEE_GL_NV_evaluators 1 +/* Constants */ +#define GL_EVAL_2D_NV 0x86C0 +#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1 +#define GL_MAP_TESSELLATION_NV 0x86C2 +#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3 +#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4 +#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5 +#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6 +#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7 +#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8 +#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9 +#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA +#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB +#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC +#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD +#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE +#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF +#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0 +#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1 +#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2 +#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3 +#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4 +#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5 +#define GL_MAX_MAP_TESSELLATION_NV 0x86D6 +#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7 +#ifndef GLEE_H_DEFINED_glMapControlPointsNV +#define GLEE_H_DEFINED_glMapControlPointsNV + typedef void (APIENTRYP GLEEPFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid * points); + GLEE_EXTERN GLEEPFNGLMAPCONTROLPOINTSNVPROC GLeeFuncPtr_glMapControlPointsNV; + #define glMapControlPointsNV GLeeFuncPtr_glMapControlPointsNV +#endif +#ifndef GLEE_H_DEFINED_glMapParameterivNV +#define GLEE_H_DEFINED_glMapParameterivNV + typedef void (APIENTRYP GLEEPFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLMAPPARAMETERIVNVPROC GLeeFuncPtr_glMapParameterivNV; + #define glMapParameterivNV GLeeFuncPtr_glMapParameterivNV +#endif +#ifndef GLEE_H_DEFINED_glMapParameterfvNV +#define GLEE_H_DEFINED_glMapParameterfvNV + typedef void (APIENTRYP GLEEPFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLMAPPARAMETERFVNVPROC GLeeFuncPtr_glMapParameterfvNV; + #define glMapParameterfvNV GLeeFuncPtr_glMapParameterfvNV +#endif +#ifndef GLEE_H_DEFINED_glGetMapControlPointsNV +#define GLEE_H_DEFINED_glGetMapControlPointsNV + typedef void (APIENTRYP GLEEPFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid * points); + GLEE_EXTERN GLEEPFNGLGETMAPCONTROLPOINTSNVPROC GLeeFuncPtr_glGetMapControlPointsNV; + #define glGetMapControlPointsNV GLeeFuncPtr_glGetMapControlPointsNV +#endif +#ifndef GLEE_H_DEFINED_glGetMapParameterivNV +#define GLEE_H_DEFINED_glGetMapParameterivNV + typedef void (APIENTRYP GLEEPFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETMAPPARAMETERIVNVPROC GLeeFuncPtr_glGetMapParameterivNV; + #define glGetMapParameterivNV GLeeFuncPtr_glGetMapParameterivNV +#endif +#ifndef GLEE_H_DEFINED_glGetMapParameterfvNV +#define GLEE_H_DEFINED_glGetMapParameterfvNV + typedef void (APIENTRYP GLEEPFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETMAPPARAMETERFVNVPROC GLeeFuncPtr_glGetMapParameterfvNV; + #define glGetMapParameterfvNV GLeeFuncPtr_glGetMapParameterfvNV +#endif +#ifndef GLEE_H_DEFINED_glGetMapAttribParameterivNV +#define GLEE_H_DEFINED_glGetMapAttribParameterivNV + typedef void (APIENTRYP GLEEPFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETMAPATTRIBPARAMETERIVNVPROC GLeeFuncPtr_glGetMapAttribParameterivNV; + #define glGetMapAttribParameterivNV GLeeFuncPtr_glGetMapAttribParameterivNV +#endif +#ifndef GLEE_H_DEFINED_glGetMapAttribParameterfvNV +#define GLEE_H_DEFINED_glGetMapAttribParameterfvNV + typedef void (APIENTRYP GLEEPFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETMAPATTRIBPARAMETERFVNVPROC GLeeFuncPtr_glGetMapAttribParameterfvNV; + #define glGetMapAttribParameterfvNV GLeeFuncPtr_glGetMapAttribParameterfvNV +#endif +#ifndef GLEE_H_DEFINED_glEvalMapsNV +#define GLEE_H_DEFINED_glEvalMapsNV + typedef void (APIENTRYP GLEEPFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode); + GLEE_EXTERN GLEEPFNGLEVALMAPSNVPROC GLeeFuncPtr_glEvalMapsNV; + #define glEvalMapsNV GLeeFuncPtr_glEvalMapsNV +#endif +#endif + +/* GL_NV_packed_depth_stencil */ + +#ifndef GL_NV_packed_depth_stencil +#define GL_NV_packed_depth_stencil 1 +#define __GLEE_GL_NV_packed_depth_stencil 1 +/* Constants */ +#define GL_DEPTH_STENCIL_NV 0x84F9 +#define GL_UNSIGNED_INT_24_8_NV 0x84FA +#endif + +/* GL_NV_register_combiners2 */ + +#ifndef GL_NV_register_combiners2 +#define GL_NV_register_combiners2 1 +#define __GLEE_GL_NV_register_combiners2 1 +/* Constants */ +#define GL_PER_STAGE_CONSTANTS_NV 0x8535 +#ifndef GLEE_H_DEFINED_glCombinerStageParameterfvNV +#define GLEE_H_DEFINED_glCombinerStageParameterfvNV + typedef void (APIENTRYP GLEEPFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLCOMBINERSTAGEPARAMETERFVNVPROC GLeeFuncPtr_glCombinerStageParameterfvNV; + #define glCombinerStageParameterfvNV GLeeFuncPtr_glCombinerStageParameterfvNV +#endif +#ifndef GLEE_H_DEFINED_glGetCombinerStageParameterfvNV +#define GLEE_H_DEFINED_glGetCombinerStageParameterfvNV + typedef void (APIENTRYP GLEEPFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC GLeeFuncPtr_glGetCombinerStageParameterfvNV; + #define glGetCombinerStageParameterfvNV GLeeFuncPtr_glGetCombinerStageParameterfvNV +#endif +#endif + +/* GL_NV_texture_compression_vtc */ + +#ifndef GL_NV_texture_compression_vtc +#define GL_NV_texture_compression_vtc 1 +#define __GLEE_GL_NV_texture_compression_vtc 1 +/* Constants */ +#endif + +/* GL_NV_texture_rectangle */ + +#ifndef GL_NV_texture_rectangle +#define GL_NV_texture_rectangle 1 +#define __GLEE_GL_NV_texture_rectangle 1 +/* Constants */ +#define GL_TEXTURE_RECTANGLE_NV 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 +#endif + +/* GL_NV_texture_shader */ + +#ifndef GL_NV_texture_shader +#define GL_NV_texture_shader 1 +#define __GLEE_GL_NV_texture_shader 1 +/* Constants */ +#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C +#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D +#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E +#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9 +#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA +#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB +#define GL_DSDT_MAG_INTENSITY_NV 0x86DC +#define GL_SHADER_CONSISTENT_NV 0x86DD +#define GL_TEXTURE_SHADER_NV 0x86DE +#define GL_SHADER_OPERATION_NV 0x86DF +#define GL_CULL_MODES_NV 0x86E0 +#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1 +#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2 +#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 +#define GL_OFFSET_TEXTURE_2D_MATRIX_NV GL_OFFSET_TEXTURE_MATRIX_NV +#define GL_OFFSET_TEXTURE_2D_SCALE_NV GL_OFFSET_TEXTURE_SCALE_NV +#define GL_OFFSET_TEXTURE_2D_BIAS_NV GL_OFFSET_TEXTURE_BIAS_NV +#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4 +#define GL_CONST_EYE_NV 0x86E5 +#define GL_PASS_THROUGH_NV 0x86E6 +#define GL_CULL_FRAGMENT_NV 0x86E7 +#define GL_OFFSET_TEXTURE_2D_NV 0x86E8 +#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9 +#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA +#define GL_DOT_PRODUCT_NV 0x86EC +#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED +#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE +#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0 +#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1 +#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2 +#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3 +#define GL_HILO_NV 0x86F4 +#define GL_DSDT_NV 0x86F5 +#define GL_DSDT_MAG_NV 0x86F6 +#define GL_DSDT_MAG_VIB_NV 0x86F7 +#define GL_HILO16_NV 0x86F8 +#define GL_SIGNED_HILO_NV 0x86F9 +#define GL_SIGNED_HILO16_NV 0x86FA +#define GL_SIGNED_RGBA_NV 0x86FB +#define GL_SIGNED_RGBA8_NV 0x86FC +#define GL_SIGNED_RGB_NV 0x86FE +#define GL_SIGNED_RGB8_NV 0x86FF +#define GL_SIGNED_LUMINANCE_NV 0x8701 +#define GL_SIGNED_LUMINANCE8_NV 0x8702 +#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 +#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 +#define GL_SIGNED_ALPHA_NV 0x8705 +#define GL_SIGNED_ALPHA8_NV 0x8706 +#define GL_SIGNED_INTENSITY_NV 0x8707 +#define GL_SIGNED_INTENSITY8_NV 0x8708 +#define GL_DSDT8_NV 0x8709 +#define GL_DSDT8_MAG8_NV 0x870A +#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B +#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C +#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D +#define GL_HI_SCALE_NV 0x870E +#define GL_LO_SCALE_NV 0x870F +#define GL_DS_SCALE_NV 0x8710 +#define GL_DT_SCALE_NV 0x8711 +#define GL_MAGNITUDE_SCALE_NV 0x8712 +#define GL_VIBRANCE_SCALE_NV 0x8713 +#define GL_HI_BIAS_NV 0x8714 +#define GL_LO_BIAS_NV 0x8715 +#define GL_DS_BIAS_NV 0x8716 +#define GL_DT_BIAS_NV 0x8717 +#define GL_MAGNITUDE_BIAS_NV 0x8718 +#define GL_VIBRANCE_BIAS_NV 0x8719 +#define GL_TEXTURE_BORDER_VALUES_NV 0x871A +#define GL_TEXTURE_HI_SIZE_NV 0x871B +#define GL_TEXTURE_LO_SIZE_NV 0x871C +#define GL_TEXTURE_DS_SIZE_NV 0x871D +#define GL_TEXTURE_DT_SIZE_NV 0x871E +#define GL_TEXTURE_MAG_SIZE_NV 0x871F +#endif + +/* GL_NV_texture_shader2 */ + +#ifndef GL_NV_texture_shader2 +#define GL_NV_texture_shader2 1 +#define __GLEE_GL_NV_texture_shader2 1 +/* Constants */ +#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF +#endif + +/* GL_NV_vertex_array_range2 */ + +#ifndef GL_NV_vertex_array_range2 +#define GL_NV_vertex_array_range2 1 +#define __GLEE_GL_NV_vertex_array_range2 1 +/* Constants */ +#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 +#endif + +/* GL_NV_vertex_program */ + +#ifndef GL_NV_vertex_program +#define GL_NV_vertex_program 1 +#define __GLEE_GL_NV_vertex_program 1 +/* Constants */ +#define GL_VERTEX_PROGRAM_NV 0x8620 +#define GL_VERTEX_STATE_PROGRAM_NV 0x8621 +#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623 +#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624 +#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625 +#define GL_CURRENT_ATTRIB_NV 0x8626 +#define GL_PROGRAM_LENGTH_NV 0x8627 +#define GL_PROGRAM_STRING_NV 0x8628 +#define GL_MODELVIEW_PROJECTION_NV 0x8629 +#define GL_IDENTITY_NV 0x862A +#define GL_INVERSE_NV 0x862B +#define GL_TRANSPOSE_NV 0x862C +#define GL_INVERSE_TRANSPOSE_NV 0x862D +#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E +#define GL_MAX_TRACK_MATRICES_NV 0x862F +#define GL_MATRIX0_NV 0x8630 +#define GL_MATRIX1_NV 0x8631 +#define GL_MATRIX2_NV 0x8632 +#define GL_MATRIX3_NV 0x8633 +#define GL_MATRIX4_NV 0x8634 +#define GL_MATRIX5_NV 0x8635 +#define GL_MATRIX6_NV 0x8636 +#define GL_MATRIX7_NV 0x8637 +#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 +#define GL_CURRENT_MATRIX_NV 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 +#define GL_PROGRAM_PARAMETER_NV 0x8644 +#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645 +#define GL_PROGRAM_TARGET_NV 0x8646 +#define GL_PROGRAM_RESIDENT_NV 0x8647 +#define GL_TRACK_MATRIX_NV 0x8648 +#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649 +#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A +#define GL_PROGRAM_ERROR_POSITION_NV 0x864B +#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650 +#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651 +#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652 +#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653 +#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654 +#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655 +#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656 +#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657 +#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658 +#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659 +#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A +#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B +#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C +#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D +#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E +#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F +#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660 +#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661 +#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662 +#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663 +#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664 +#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665 +#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666 +#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667 +#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668 +#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669 +#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A +#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B +#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C +#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D +#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E +#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F +#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670 +#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671 +#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672 +#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673 +#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674 +#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675 +#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676 +#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677 +#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678 +#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679 +#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A +#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B +#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C +#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D +#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E +#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F +#ifndef GLEE_H_DEFINED_glAreProgramsResidentNV +#define GLEE_H_DEFINED_glAreProgramsResidentNV + typedef GLboolean (APIENTRYP GLEEPFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint * programs, GLboolean * residences); + GLEE_EXTERN GLEEPFNGLAREPROGRAMSRESIDENTNVPROC GLeeFuncPtr_glAreProgramsResidentNV; + #define glAreProgramsResidentNV GLeeFuncPtr_glAreProgramsResidentNV +#endif +#ifndef GLEE_H_DEFINED_glBindProgramNV +#define GLEE_H_DEFINED_glBindProgramNV + typedef void (APIENTRYP GLEEPFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id); + GLEE_EXTERN GLEEPFNGLBINDPROGRAMNVPROC GLeeFuncPtr_glBindProgramNV; + #define glBindProgramNV GLeeFuncPtr_glBindProgramNV +#endif +#ifndef GLEE_H_DEFINED_glDeleteProgramsNV +#define GLEE_H_DEFINED_glDeleteProgramsNV + typedef void (APIENTRYP GLEEPFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint * programs); + GLEE_EXTERN GLEEPFNGLDELETEPROGRAMSNVPROC GLeeFuncPtr_glDeleteProgramsNV; + #define glDeleteProgramsNV GLeeFuncPtr_glDeleteProgramsNV +#endif +#ifndef GLEE_H_DEFINED_glExecuteProgramNV +#define GLEE_H_DEFINED_glExecuteProgramNV + typedef void (APIENTRYP GLEEPFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLEXECUTEPROGRAMNVPROC GLeeFuncPtr_glExecuteProgramNV; + #define glExecuteProgramNV GLeeFuncPtr_glExecuteProgramNV +#endif +#ifndef GLEE_H_DEFINED_glGenProgramsNV +#define GLEE_H_DEFINED_glGenProgramsNV + typedef void (APIENTRYP GLEEPFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint * programs); + GLEE_EXTERN GLEEPFNGLGENPROGRAMSNVPROC GLeeFuncPtr_glGenProgramsNV; + #define glGenProgramsNV GLeeFuncPtr_glGenProgramsNV +#endif +#ifndef GLEE_H_DEFINED_glGetProgramParameterdvNV +#define GLEE_H_DEFINED_glGetProgramParameterdvNV + typedef void (APIENTRYP GLEEPFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble * params); + GLEE_EXTERN GLEEPFNGLGETPROGRAMPARAMETERDVNVPROC GLeeFuncPtr_glGetProgramParameterdvNV; + #define glGetProgramParameterdvNV GLeeFuncPtr_glGetProgramParameterdvNV +#endif +#ifndef GLEE_H_DEFINED_glGetProgramParameterfvNV +#define GLEE_H_DEFINED_glGetProgramParameterfvNV + typedef void (APIENTRYP GLEEPFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETPROGRAMPARAMETERFVNVPROC GLeeFuncPtr_glGetProgramParameterfvNV; + #define glGetProgramParameterfvNV GLeeFuncPtr_glGetProgramParameterfvNV +#endif +#ifndef GLEE_H_DEFINED_glGetProgramivNV +#define GLEE_H_DEFINED_glGetProgramivNV + typedef void (APIENTRYP GLEEPFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETPROGRAMIVNVPROC GLeeFuncPtr_glGetProgramivNV; + #define glGetProgramivNV GLeeFuncPtr_glGetProgramivNV +#endif +#ifndef GLEE_H_DEFINED_glGetProgramStringNV +#define GLEE_H_DEFINED_glGetProgramStringNV + typedef void (APIENTRYP GLEEPFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte * program); + GLEE_EXTERN GLEEPFNGLGETPROGRAMSTRINGNVPROC GLeeFuncPtr_glGetProgramStringNV; + #define glGetProgramStringNV GLeeFuncPtr_glGetProgramStringNV +#endif +#ifndef GLEE_H_DEFINED_glGetTrackMatrixivNV +#define GLEE_H_DEFINED_glGetTrackMatrixivNV + typedef void (APIENTRYP GLEEPFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETTRACKMATRIXIVNVPROC GLeeFuncPtr_glGetTrackMatrixivNV; + #define glGetTrackMatrixivNV GLeeFuncPtr_glGetTrackMatrixivNV +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribdvNV +#define GLEE_H_DEFINED_glGetVertexAttribdvNV + typedef void (APIENTRYP GLEEPFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble * params); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBDVNVPROC GLeeFuncPtr_glGetVertexAttribdvNV; + #define glGetVertexAttribdvNV GLeeFuncPtr_glGetVertexAttribdvNV +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribfvNV +#define GLEE_H_DEFINED_glGetVertexAttribfvNV + typedef void (APIENTRYP GLEEPFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBFVNVPROC GLeeFuncPtr_glGetVertexAttribfvNV; + #define glGetVertexAttribfvNV GLeeFuncPtr_glGetVertexAttribfvNV +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribivNV +#define GLEE_H_DEFINED_glGetVertexAttribivNV + typedef void (APIENTRYP GLEEPFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBIVNVPROC GLeeFuncPtr_glGetVertexAttribivNV; + #define glGetVertexAttribivNV GLeeFuncPtr_glGetVertexAttribivNV +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribPointervNV +#define GLEE_H_DEFINED_glGetVertexAttribPointervNV + typedef void (APIENTRYP GLEEPFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid* * pointer); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBPOINTERVNVPROC GLeeFuncPtr_glGetVertexAttribPointervNV; + #define glGetVertexAttribPointervNV GLeeFuncPtr_glGetVertexAttribPointervNV +#endif +#ifndef GLEE_H_DEFINED_glIsProgramNV +#define GLEE_H_DEFINED_glIsProgramNV + typedef GLboolean (APIENTRYP GLEEPFNGLISPROGRAMNVPROC) (GLuint id); + GLEE_EXTERN GLEEPFNGLISPROGRAMNVPROC GLeeFuncPtr_glIsProgramNV; + #define glIsProgramNV GLeeFuncPtr_glIsProgramNV +#endif +#ifndef GLEE_H_DEFINED_glLoadProgramNV +#define GLEE_H_DEFINED_glLoadProgramNV + typedef void (APIENTRYP GLEEPFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte * program); + GLEE_EXTERN GLEEPFNGLLOADPROGRAMNVPROC GLeeFuncPtr_glLoadProgramNV; + #define glLoadProgramNV GLeeFuncPtr_glLoadProgramNV +#endif +#ifndef GLEE_H_DEFINED_glProgramParameter4dNV +#define GLEE_H_DEFINED_glProgramParameter4dNV + typedef void (APIENTRYP GLEEPFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + GLEE_EXTERN GLEEPFNGLPROGRAMPARAMETER4DNVPROC GLeeFuncPtr_glProgramParameter4dNV; + #define glProgramParameter4dNV GLeeFuncPtr_glProgramParameter4dNV +#endif +#ifndef GLEE_H_DEFINED_glProgramParameter4dvNV +#define GLEE_H_DEFINED_glProgramParameter4dvNV + typedef void (APIENTRYP GLEEPFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLPROGRAMPARAMETER4DVNVPROC GLeeFuncPtr_glProgramParameter4dvNV; + #define glProgramParameter4dvNV GLeeFuncPtr_glProgramParameter4dvNV +#endif +#ifndef GLEE_H_DEFINED_glProgramParameter4fNV +#define GLEE_H_DEFINED_glProgramParameter4fNV + typedef void (APIENTRYP GLEEPFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + GLEE_EXTERN GLEEPFNGLPROGRAMPARAMETER4FNVPROC GLeeFuncPtr_glProgramParameter4fNV; + #define glProgramParameter4fNV GLeeFuncPtr_glProgramParameter4fNV +#endif +#ifndef GLEE_H_DEFINED_glProgramParameter4fvNV +#define GLEE_H_DEFINED_glProgramParameter4fvNV + typedef void (APIENTRYP GLEEPFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLPROGRAMPARAMETER4FVNVPROC GLeeFuncPtr_glProgramParameter4fvNV; + #define glProgramParameter4fvNV GLeeFuncPtr_glProgramParameter4fvNV +#endif +#ifndef GLEE_H_DEFINED_glProgramParameters4dvNV +#define GLEE_H_DEFINED_glProgramParameters4dvNV + typedef void (APIENTRYP GLEEPFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLuint count, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLPROGRAMPARAMETERS4DVNVPROC GLeeFuncPtr_glProgramParameters4dvNV; + #define glProgramParameters4dvNV GLeeFuncPtr_glProgramParameters4dvNV +#endif +#ifndef GLEE_H_DEFINED_glProgramParameters4fvNV +#define GLEE_H_DEFINED_glProgramParameters4fvNV + typedef void (APIENTRYP GLEEPFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLuint count, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLPROGRAMPARAMETERS4FVNVPROC GLeeFuncPtr_glProgramParameters4fvNV; + #define glProgramParameters4fvNV GLeeFuncPtr_glProgramParameters4fvNV +#endif +#ifndef GLEE_H_DEFINED_glRequestResidentProgramsNV +#define GLEE_H_DEFINED_glRequestResidentProgramsNV + typedef void (APIENTRYP GLEEPFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint * programs); + GLEE_EXTERN GLEEPFNGLREQUESTRESIDENTPROGRAMSNVPROC GLeeFuncPtr_glRequestResidentProgramsNV; + #define glRequestResidentProgramsNV GLeeFuncPtr_glRequestResidentProgramsNV +#endif +#ifndef GLEE_H_DEFINED_glTrackMatrixNV +#define GLEE_H_DEFINED_glTrackMatrixNV + typedef void (APIENTRYP GLEEPFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform); + GLEE_EXTERN GLEEPFNGLTRACKMATRIXNVPROC GLeeFuncPtr_glTrackMatrixNV; + #define glTrackMatrixNV GLeeFuncPtr_glTrackMatrixNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribPointerNV +#define GLEE_H_DEFINED_glVertexAttribPointerNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBPOINTERNVPROC GLeeFuncPtr_glVertexAttribPointerNV; + #define glVertexAttribPointerNV GLeeFuncPtr_glVertexAttribPointerNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1dNV +#define GLEE_H_DEFINED_glVertexAttrib1dNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1DNVPROC GLeeFuncPtr_glVertexAttrib1dNV; + #define glVertexAttrib1dNV GLeeFuncPtr_glVertexAttrib1dNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1dvNV +#define GLEE_H_DEFINED_glVertexAttrib1dvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1DVNVPROC GLeeFuncPtr_glVertexAttrib1dvNV; + #define glVertexAttrib1dvNV GLeeFuncPtr_glVertexAttrib1dvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1fNV +#define GLEE_H_DEFINED_glVertexAttrib1fNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1FNVPROC GLeeFuncPtr_glVertexAttrib1fNV; + #define glVertexAttrib1fNV GLeeFuncPtr_glVertexAttrib1fNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1fvNV +#define GLEE_H_DEFINED_glVertexAttrib1fvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1FVNVPROC GLeeFuncPtr_glVertexAttrib1fvNV; + #define glVertexAttrib1fvNV GLeeFuncPtr_glVertexAttrib1fvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1sNV +#define GLEE_H_DEFINED_glVertexAttrib1sNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1SNVPROC GLeeFuncPtr_glVertexAttrib1sNV; + #define glVertexAttrib1sNV GLeeFuncPtr_glVertexAttrib1sNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1svNV +#define GLEE_H_DEFINED_glVertexAttrib1svNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1SVNVPROC GLeeFuncPtr_glVertexAttrib1svNV; + #define glVertexAttrib1svNV GLeeFuncPtr_glVertexAttrib1svNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2dNV +#define GLEE_H_DEFINED_glVertexAttrib2dNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2DNVPROC GLeeFuncPtr_glVertexAttrib2dNV; + #define glVertexAttrib2dNV GLeeFuncPtr_glVertexAttrib2dNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2dvNV +#define GLEE_H_DEFINED_glVertexAttrib2dvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2DVNVPROC GLeeFuncPtr_glVertexAttrib2dvNV; + #define glVertexAttrib2dvNV GLeeFuncPtr_glVertexAttrib2dvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2fNV +#define GLEE_H_DEFINED_glVertexAttrib2fNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2FNVPROC GLeeFuncPtr_glVertexAttrib2fNV; + #define glVertexAttrib2fNV GLeeFuncPtr_glVertexAttrib2fNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2fvNV +#define GLEE_H_DEFINED_glVertexAttrib2fvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2FVNVPROC GLeeFuncPtr_glVertexAttrib2fvNV; + #define glVertexAttrib2fvNV GLeeFuncPtr_glVertexAttrib2fvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2sNV +#define GLEE_H_DEFINED_glVertexAttrib2sNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2SNVPROC GLeeFuncPtr_glVertexAttrib2sNV; + #define glVertexAttrib2sNV GLeeFuncPtr_glVertexAttrib2sNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2svNV +#define GLEE_H_DEFINED_glVertexAttrib2svNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2SVNVPROC GLeeFuncPtr_glVertexAttrib2svNV; + #define glVertexAttrib2svNV GLeeFuncPtr_glVertexAttrib2svNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3dNV +#define GLEE_H_DEFINED_glVertexAttrib3dNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3DNVPROC GLeeFuncPtr_glVertexAttrib3dNV; + #define glVertexAttrib3dNV GLeeFuncPtr_glVertexAttrib3dNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3dvNV +#define GLEE_H_DEFINED_glVertexAttrib3dvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3DVNVPROC GLeeFuncPtr_glVertexAttrib3dvNV; + #define glVertexAttrib3dvNV GLeeFuncPtr_glVertexAttrib3dvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3fNV +#define GLEE_H_DEFINED_glVertexAttrib3fNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3FNVPROC GLeeFuncPtr_glVertexAttrib3fNV; + #define glVertexAttrib3fNV GLeeFuncPtr_glVertexAttrib3fNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3fvNV +#define GLEE_H_DEFINED_glVertexAttrib3fvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3FVNVPROC GLeeFuncPtr_glVertexAttrib3fvNV; + #define glVertexAttrib3fvNV GLeeFuncPtr_glVertexAttrib3fvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3sNV +#define GLEE_H_DEFINED_glVertexAttrib3sNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3SNVPROC GLeeFuncPtr_glVertexAttrib3sNV; + #define glVertexAttrib3sNV GLeeFuncPtr_glVertexAttrib3sNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3svNV +#define GLEE_H_DEFINED_glVertexAttrib3svNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3SVNVPROC GLeeFuncPtr_glVertexAttrib3svNV; + #define glVertexAttrib3svNV GLeeFuncPtr_glVertexAttrib3svNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4dNV +#define GLEE_H_DEFINED_glVertexAttrib4dNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4DNVPROC GLeeFuncPtr_glVertexAttrib4dNV; + #define glVertexAttrib4dNV GLeeFuncPtr_glVertexAttrib4dNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4dvNV +#define GLEE_H_DEFINED_glVertexAttrib4dvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4DVNVPROC GLeeFuncPtr_glVertexAttrib4dvNV; + #define glVertexAttrib4dvNV GLeeFuncPtr_glVertexAttrib4dvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4fNV +#define GLEE_H_DEFINED_glVertexAttrib4fNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4FNVPROC GLeeFuncPtr_glVertexAttrib4fNV; + #define glVertexAttrib4fNV GLeeFuncPtr_glVertexAttrib4fNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4fvNV +#define GLEE_H_DEFINED_glVertexAttrib4fvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4FVNVPROC GLeeFuncPtr_glVertexAttrib4fvNV; + #define glVertexAttrib4fvNV GLeeFuncPtr_glVertexAttrib4fvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4sNV +#define GLEE_H_DEFINED_glVertexAttrib4sNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4SNVPROC GLeeFuncPtr_glVertexAttrib4sNV; + #define glVertexAttrib4sNV GLeeFuncPtr_glVertexAttrib4sNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4svNV +#define GLEE_H_DEFINED_glVertexAttrib4svNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4SVNVPROC GLeeFuncPtr_glVertexAttrib4svNV; + #define glVertexAttrib4svNV GLeeFuncPtr_glVertexAttrib4svNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4ubNV +#define GLEE_H_DEFINED_glVertexAttrib4ubNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4UBNVPROC GLeeFuncPtr_glVertexAttrib4ubNV; + #define glVertexAttrib4ubNV GLeeFuncPtr_glVertexAttrib4ubNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4ubvNV +#define GLEE_H_DEFINED_glVertexAttrib4ubvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4UBVNVPROC GLeeFuncPtr_glVertexAttrib4ubvNV; + #define glVertexAttrib4ubvNV GLeeFuncPtr_glVertexAttrib4ubvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs1dvNV +#define GLEE_H_DEFINED_glVertexAttribs1dvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS1DVNVPROC GLeeFuncPtr_glVertexAttribs1dvNV; + #define glVertexAttribs1dvNV GLeeFuncPtr_glVertexAttribs1dvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs1fvNV +#define GLEE_H_DEFINED_glVertexAttribs1fvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS1FVNVPROC GLeeFuncPtr_glVertexAttribs1fvNV; + #define glVertexAttribs1fvNV GLeeFuncPtr_glVertexAttribs1fvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs1svNV +#define GLEE_H_DEFINED_glVertexAttribs1svNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS1SVNVPROC GLeeFuncPtr_glVertexAttribs1svNV; + #define glVertexAttribs1svNV GLeeFuncPtr_glVertexAttribs1svNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs2dvNV +#define GLEE_H_DEFINED_glVertexAttribs2dvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS2DVNVPROC GLeeFuncPtr_glVertexAttribs2dvNV; + #define glVertexAttribs2dvNV GLeeFuncPtr_glVertexAttribs2dvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs2fvNV +#define GLEE_H_DEFINED_glVertexAttribs2fvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS2FVNVPROC GLeeFuncPtr_glVertexAttribs2fvNV; + #define glVertexAttribs2fvNV GLeeFuncPtr_glVertexAttribs2fvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs2svNV +#define GLEE_H_DEFINED_glVertexAttribs2svNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS2SVNVPROC GLeeFuncPtr_glVertexAttribs2svNV; + #define glVertexAttribs2svNV GLeeFuncPtr_glVertexAttribs2svNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs3dvNV +#define GLEE_H_DEFINED_glVertexAttribs3dvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS3DVNVPROC GLeeFuncPtr_glVertexAttribs3dvNV; + #define glVertexAttribs3dvNV GLeeFuncPtr_glVertexAttribs3dvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs3fvNV +#define GLEE_H_DEFINED_glVertexAttribs3fvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS3FVNVPROC GLeeFuncPtr_glVertexAttribs3fvNV; + #define glVertexAttribs3fvNV GLeeFuncPtr_glVertexAttribs3fvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs3svNV +#define GLEE_H_DEFINED_glVertexAttribs3svNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS3SVNVPROC GLeeFuncPtr_glVertexAttribs3svNV; + #define glVertexAttribs3svNV GLeeFuncPtr_glVertexAttribs3svNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs4dvNV +#define GLEE_H_DEFINED_glVertexAttribs4dvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS4DVNVPROC GLeeFuncPtr_glVertexAttribs4dvNV; + #define glVertexAttribs4dvNV GLeeFuncPtr_glVertexAttribs4dvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs4fvNV +#define GLEE_H_DEFINED_glVertexAttribs4fvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS4FVNVPROC GLeeFuncPtr_glVertexAttribs4fvNV; + #define glVertexAttribs4fvNV GLeeFuncPtr_glVertexAttribs4fvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs4svNV +#define GLEE_H_DEFINED_glVertexAttribs4svNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS4SVNVPROC GLeeFuncPtr_glVertexAttribs4svNV; + #define glVertexAttribs4svNV GLeeFuncPtr_glVertexAttribs4svNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs4ubvNV +#define GLEE_H_DEFINED_glVertexAttribs4ubvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS4UBVNVPROC GLeeFuncPtr_glVertexAttribs4ubvNV; + #define glVertexAttribs4ubvNV GLeeFuncPtr_glVertexAttribs4ubvNV +#endif +#endif + +/* GL_SGIX_texture_coordinate_clamp */ + +#ifndef GL_SGIX_texture_coordinate_clamp +#define GL_SGIX_texture_coordinate_clamp 1 +#define __GLEE_GL_SGIX_texture_coordinate_clamp 1 +/* Constants */ +#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369 +#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A +#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B +#endif + +/* GL_SGIX_scalebias_hint */ + +#ifndef GL_SGIX_scalebias_hint +#define GL_SGIX_scalebias_hint 1 +#define __GLEE_GL_SGIX_scalebias_hint 1 +/* Constants */ +#define GL_SCALEBIAS_HINT_SGIX 0x8322 +#endif + +/* GL_OML_interlace */ + +#ifndef GL_OML_interlace +#define GL_OML_interlace 1 +#define __GLEE_GL_OML_interlace 1 +/* Constants */ +#define GL_INTERLACE_OML 0x8980 +#define GL_INTERLACE_READ_OML 0x8981 +#endif + +/* GL_OML_subsample */ + +#ifndef GL_OML_subsample +#define GL_OML_subsample 1 +#define __GLEE_GL_OML_subsample 1 +/* Constants */ +#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982 +#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983 +#endif + +/* GL_OML_resample */ + +#ifndef GL_OML_resample +#define GL_OML_resample 1 +#define __GLEE_GL_OML_resample 1 +/* Constants */ +#define GL_PACK_RESAMPLE_OML 0x8984 +#define GL_UNPACK_RESAMPLE_OML 0x8985 +#define GL_RESAMPLE_REPLICATE_OML 0x8986 +#define GL_RESAMPLE_ZERO_FILL_OML 0x8987 +#define GL_RESAMPLE_AVERAGE_OML 0x8988 +#define GL_RESAMPLE_DECIMATE_OML 0x8989 +#endif + +/* GL_NV_copy_depth_to_color */ + +#ifndef GL_NV_copy_depth_to_color +#define GL_NV_copy_depth_to_color 1 +#define __GLEE_GL_NV_copy_depth_to_color 1 +/* Constants */ +#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E +#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F +#endif + +/* GL_ATI_envmap_bumpmap */ + +#ifndef GL_ATI_envmap_bumpmap +#define GL_ATI_envmap_bumpmap 1 +#define __GLEE_GL_ATI_envmap_bumpmap 1 +/* Constants */ +#define GL_BUMP_ROT_MATRIX_ATI 0x8775 +#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776 +#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777 +#define GL_BUMP_TEX_UNITS_ATI 0x8778 +#define GL_DUDV_ATI 0x8779 +#define GL_DU8DV8_ATI 0x877A +#define GL_BUMP_ENVMAP_ATI 0x877B +#define GL_BUMP_TARGET_ATI 0x877C +#ifndef GLEE_H_DEFINED_glTexBumpParameterivATI +#define GLEE_H_DEFINED_glTexBumpParameterivATI + typedef void (APIENTRYP GLEEPFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, const GLint * param); + GLEE_EXTERN GLEEPFNGLTEXBUMPPARAMETERIVATIPROC GLeeFuncPtr_glTexBumpParameterivATI; + #define glTexBumpParameterivATI GLeeFuncPtr_glTexBumpParameterivATI +#endif +#ifndef GLEE_H_DEFINED_glTexBumpParameterfvATI +#define GLEE_H_DEFINED_glTexBumpParameterfvATI + typedef void (APIENTRYP GLEEPFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, const GLfloat * param); + GLEE_EXTERN GLEEPFNGLTEXBUMPPARAMETERFVATIPROC GLeeFuncPtr_glTexBumpParameterfvATI; + #define glTexBumpParameterfvATI GLeeFuncPtr_glTexBumpParameterfvATI +#endif +#ifndef GLEE_H_DEFINED_glGetTexBumpParameterivATI +#define GLEE_H_DEFINED_glGetTexBumpParameterivATI + typedef void (APIENTRYP GLEEPFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint * param); + GLEE_EXTERN GLEEPFNGLGETTEXBUMPPARAMETERIVATIPROC GLeeFuncPtr_glGetTexBumpParameterivATI; + #define glGetTexBumpParameterivATI GLeeFuncPtr_glGetTexBumpParameterivATI +#endif +#ifndef GLEE_H_DEFINED_glGetTexBumpParameterfvATI +#define GLEE_H_DEFINED_glGetTexBumpParameterfvATI + typedef void (APIENTRYP GLEEPFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat * param); + GLEE_EXTERN GLEEPFNGLGETTEXBUMPPARAMETERFVATIPROC GLeeFuncPtr_glGetTexBumpParameterfvATI; + #define glGetTexBumpParameterfvATI GLeeFuncPtr_glGetTexBumpParameterfvATI +#endif +#endif + +/* GL_ATI_fragment_shader */ + +#ifndef GL_ATI_fragment_shader +#define GL_ATI_fragment_shader 1 +#define __GLEE_GL_ATI_fragment_shader 1 +/* Constants */ +#define GL_FRAGMENT_SHADER_ATI 0x8920 +#define GL_REG_0_ATI 0x8921 +#define GL_REG_1_ATI 0x8922 +#define GL_REG_2_ATI 0x8923 +#define GL_REG_3_ATI 0x8924 +#define GL_REG_4_ATI 0x8925 +#define GL_REG_5_ATI 0x8926 +#define GL_REG_6_ATI 0x8927 +#define GL_REG_7_ATI 0x8928 +#define GL_REG_8_ATI 0x8929 +#define GL_REG_9_ATI 0x892A +#define GL_REG_10_ATI 0x892B +#define GL_REG_11_ATI 0x892C +#define GL_REG_12_ATI 0x892D +#define GL_REG_13_ATI 0x892E +#define GL_REG_14_ATI 0x892F +#define GL_REG_15_ATI 0x8930 +#define GL_REG_16_ATI 0x8931 +#define GL_REG_17_ATI 0x8932 +#define GL_REG_18_ATI 0x8933 +#define GL_REG_19_ATI 0x8934 +#define GL_REG_20_ATI 0x8935 +#define GL_REG_21_ATI 0x8936 +#define GL_REG_22_ATI 0x8937 +#define GL_REG_23_ATI 0x8938 +#define GL_REG_24_ATI 0x8939 +#define GL_REG_25_ATI 0x893A +#define GL_REG_26_ATI 0x893B +#define GL_REG_27_ATI 0x893C +#define GL_REG_28_ATI 0x893D +#define GL_REG_29_ATI 0x893E +#define GL_REG_30_ATI 0x893F +#define GL_REG_31_ATI 0x8940 +#define GL_CON_0_ATI 0x8941 +#define GL_CON_1_ATI 0x8942 +#define GL_CON_2_ATI 0x8943 +#define GL_CON_3_ATI 0x8944 +#define GL_CON_4_ATI 0x8945 +#define GL_CON_5_ATI 0x8946 +#define GL_CON_6_ATI 0x8947 +#define GL_CON_7_ATI 0x8948 +#define GL_CON_8_ATI 0x8949 +#define GL_CON_9_ATI 0x894A +#define GL_CON_10_ATI 0x894B +#define GL_CON_11_ATI 0x894C +#define GL_CON_12_ATI 0x894D +#define GL_CON_13_ATI 0x894E +#define GL_CON_14_ATI 0x894F +#define GL_CON_15_ATI 0x8950 +#define GL_CON_16_ATI 0x8951 +#define GL_CON_17_ATI 0x8952 +#define GL_CON_18_ATI 0x8953 +#define GL_CON_19_ATI 0x8954 +#define GL_CON_20_ATI 0x8955 +#define GL_CON_21_ATI 0x8956 +#define GL_CON_22_ATI 0x8957 +#define GL_CON_23_ATI 0x8958 +#define GL_CON_24_ATI 0x8959 +#define GL_CON_25_ATI 0x895A +#define GL_CON_26_ATI 0x895B +#define GL_CON_27_ATI 0x895C +#define GL_CON_28_ATI 0x895D +#define GL_CON_29_ATI 0x895E +#define GL_CON_30_ATI 0x895F +#define GL_CON_31_ATI 0x8960 +#define GL_MOV_ATI 0x8961 +#define GL_ADD_ATI 0x8963 +#define GL_MUL_ATI 0x8964 +#define GL_SUB_ATI 0x8965 +#define GL_DOT3_ATI 0x8966 +#define GL_DOT4_ATI 0x8967 +#define GL_MAD_ATI 0x8968 +#define GL_LERP_ATI 0x8969 +#define GL_CND_ATI 0x896A +#define GL_CND0_ATI 0x896B +#define GL_DOT2_ADD_ATI 0x896C +#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D +#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E +#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F +#define GL_NUM_PASSES_ATI 0x8970 +#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971 +#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972 +#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973 +#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974 +#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975 +#define GL_SWIZZLE_STR_ATI 0x8976 +#define GL_SWIZZLE_STQ_ATI 0x8977 +#define GL_SWIZZLE_STR_DR_ATI 0x8978 +#define GL_SWIZZLE_STQ_DQ_ATI 0x8979 +#define GL_SWIZZLE_STRQ_ATI 0x897A +#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B +#define GL_RED_BIT_ATI 0x00000001 +#define GL_GREEN_BIT_ATI 0x00000002 +#define GL_BLUE_BIT_ATI 0x00000004 +#define GL_2X_BIT_ATI 0x00000001 +#define GL_4X_BIT_ATI 0x00000002 +#define GL_8X_BIT_ATI 0x00000004 +#define GL_HALF_BIT_ATI 0x00000008 +#define GL_QUARTER_BIT_ATI 0x00000010 +#define GL_EIGHTH_BIT_ATI 0x00000020 +#define GL_SATURATE_BIT_ATI 0x00000040 +#define GL_COMP_BIT_ATI 0x00000002 +#define GL_NEGATE_BIT_ATI 0x00000004 +#define GL_BIAS_BIT_ATI 0x00000008 +#ifndef GLEE_H_DEFINED_glGenFragmentShadersATI +#define GLEE_H_DEFINED_glGenFragmentShadersATI + typedef GLuint (APIENTRYP GLEEPFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range); + GLEE_EXTERN GLEEPFNGLGENFRAGMENTSHADERSATIPROC GLeeFuncPtr_glGenFragmentShadersATI; + #define glGenFragmentShadersATI GLeeFuncPtr_glGenFragmentShadersATI +#endif +#ifndef GLEE_H_DEFINED_glBindFragmentShaderATI +#define GLEE_H_DEFINED_glBindFragmentShaderATI + typedef void (APIENTRYP GLEEPFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id); + GLEE_EXTERN GLEEPFNGLBINDFRAGMENTSHADERATIPROC GLeeFuncPtr_glBindFragmentShaderATI; + #define glBindFragmentShaderATI GLeeFuncPtr_glBindFragmentShaderATI +#endif +#ifndef GLEE_H_DEFINED_glDeleteFragmentShaderATI +#define GLEE_H_DEFINED_glDeleteFragmentShaderATI + typedef void (APIENTRYP GLEEPFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id); + GLEE_EXTERN GLEEPFNGLDELETEFRAGMENTSHADERATIPROC GLeeFuncPtr_glDeleteFragmentShaderATI; + #define glDeleteFragmentShaderATI GLeeFuncPtr_glDeleteFragmentShaderATI +#endif +#ifndef GLEE_H_DEFINED_glBeginFragmentShaderATI +#define GLEE_H_DEFINED_glBeginFragmentShaderATI + typedef void (APIENTRYP GLEEPFNGLBEGINFRAGMENTSHADERATIPROC) (); + GLEE_EXTERN GLEEPFNGLBEGINFRAGMENTSHADERATIPROC GLeeFuncPtr_glBeginFragmentShaderATI; + #define glBeginFragmentShaderATI GLeeFuncPtr_glBeginFragmentShaderATI +#endif +#ifndef GLEE_H_DEFINED_glEndFragmentShaderATI +#define GLEE_H_DEFINED_glEndFragmentShaderATI + typedef void (APIENTRYP GLEEPFNGLENDFRAGMENTSHADERATIPROC) (); + GLEE_EXTERN GLEEPFNGLENDFRAGMENTSHADERATIPROC GLeeFuncPtr_glEndFragmentShaderATI; + #define glEndFragmentShaderATI GLeeFuncPtr_glEndFragmentShaderATI +#endif +#ifndef GLEE_H_DEFINED_glPassTexCoordATI +#define GLEE_H_DEFINED_glPassTexCoordATI + typedef void (APIENTRYP GLEEPFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle); + GLEE_EXTERN GLEEPFNGLPASSTEXCOORDATIPROC GLeeFuncPtr_glPassTexCoordATI; + #define glPassTexCoordATI GLeeFuncPtr_glPassTexCoordATI +#endif +#ifndef GLEE_H_DEFINED_glSampleMapATI +#define GLEE_H_DEFINED_glSampleMapATI + typedef void (APIENTRYP GLEEPFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle); + GLEE_EXTERN GLEEPFNGLSAMPLEMAPATIPROC GLeeFuncPtr_glSampleMapATI; + #define glSampleMapATI GLeeFuncPtr_glSampleMapATI +#endif +#ifndef GLEE_H_DEFINED_glColorFragmentOp1ATI +#define GLEE_H_DEFINED_glColorFragmentOp1ATI + typedef void (APIENTRYP GLEEPFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); + GLEE_EXTERN GLEEPFNGLCOLORFRAGMENTOP1ATIPROC GLeeFuncPtr_glColorFragmentOp1ATI; + #define glColorFragmentOp1ATI GLeeFuncPtr_glColorFragmentOp1ATI +#endif +#ifndef GLEE_H_DEFINED_glColorFragmentOp2ATI +#define GLEE_H_DEFINED_glColorFragmentOp2ATI + typedef void (APIENTRYP GLEEPFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); + GLEE_EXTERN GLEEPFNGLCOLORFRAGMENTOP2ATIPROC GLeeFuncPtr_glColorFragmentOp2ATI; + #define glColorFragmentOp2ATI GLeeFuncPtr_glColorFragmentOp2ATI +#endif +#ifndef GLEE_H_DEFINED_glColorFragmentOp3ATI +#define GLEE_H_DEFINED_glColorFragmentOp3ATI + typedef void (APIENTRYP GLEEPFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); + GLEE_EXTERN GLEEPFNGLCOLORFRAGMENTOP3ATIPROC GLeeFuncPtr_glColorFragmentOp3ATI; + #define glColorFragmentOp3ATI GLeeFuncPtr_glColorFragmentOp3ATI +#endif +#ifndef GLEE_H_DEFINED_glAlphaFragmentOp1ATI +#define GLEE_H_DEFINED_glAlphaFragmentOp1ATI + typedef void (APIENTRYP GLEEPFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); + GLEE_EXTERN GLEEPFNGLALPHAFRAGMENTOP1ATIPROC GLeeFuncPtr_glAlphaFragmentOp1ATI; + #define glAlphaFragmentOp1ATI GLeeFuncPtr_glAlphaFragmentOp1ATI +#endif +#ifndef GLEE_H_DEFINED_glAlphaFragmentOp2ATI +#define GLEE_H_DEFINED_glAlphaFragmentOp2ATI + typedef void (APIENTRYP GLEEPFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); + GLEE_EXTERN GLEEPFNGLALPHAFRAGMENTOP2ATIPROC GLeeFuncPtr_glAlphaFragmentOp2ATI; + #define glAlphaFragmentOp2ATI GLeeFuncPtr_glAlphaFragmentOp2ATI +#endif +#ifndef GLEE_H_DEFINED_glAlphaFragmentOp3ATI +#define GLEE_H_DEFINED_glAlphaFragmentOp3ATI + typedef void (APIENTRYP GLEEPFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); + GLEE_EXTERN GLEEPFNGLALPHAFRAGMENTOP3ATIPROC GLeeFuncPtr_glAlphaFragmentOp3ATI; + #define glAlphaFragmentOp3ATI GLeeFuncPtr_glAlphaFragmentOp3ATI +#endif +#ifndef GLEE_H_DEFINED_glSetFragmentShaderConstantATI +#define GLEE_H_DEFINED_glSetFragmentShaderConstantATI + typedef void (APIENTRYP GLEEPFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLSETFRAGMENTSHADERCONSTANTATIPROC GLeeFuncPtr_glSetFragmentShaderConstantATI; + #define glSetFragmentShaderConstantATI GLeeFuncPtr_glSetFragmentShaderConstantATI +#endif +#endif + +/* GL_ATI_pn_triangles */ + +#ifndef GL_ATI_pn_triangles +#define GL_ATI_pn_triangles 1 +#define __GLEE_GL_ATI_pn_triangles 1 +/* Constants */ +#define GL_PN_TRIANGLES_ATI 0x87F0 +#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1 +#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2 +#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3 +#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4 +#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5 +#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6 +#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7 +#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8 +#ifndef GLEE_H_DEFINED_glPNTrianglesiATI +#define GLEE_H_DEFINED_glPNTrianglesiATI + typedef void (APIENTRYP GLEEPFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLPNTRIANGLESIATIPROC GLeeFuncPtr_glPNTrianglesiATI; + #define glPNTrianglesiATI GLeeFuncPtr_glPNTrianglesiATI +#endif +#ifndef GLEE_H_DEFINED_glPNTrianglesfATI +#define GLEE_H_DEFINED_glPNTrianglesfATI + typedef void (APIENTRYP GLEEPFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLPNTRIANGLESFATIPROC GLeeFuncPtr_glPNTrianglesfATI; + #define glPNTrianglesfATI GLeeFuncPtr_glPNTrianglesfATI +#endif +#endif + +/* GL_ATI_vertex_array_object */ + +#ifndef GL_ATI_vertex_array_object +#define GL_ATI_vertex_array_object 1 +#define __GLEE_GL_ATI_vertex_array_object 1 +/* Constants */ +#define GL_STATIC_ATI 0x8760 +#define GL_DYNAMIC_ATI 0x8761 +#define GL_PRESERVE_ATI 0x8762 +#define GL_DISCARD_ATI 0x8763 +#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764 +#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765 +#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766 +#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767 +#ifndef GLEE_H_DEFINED_glNewObjectBufferATI +#define GLEE_H_DEFINED_glNewObjectBufferATI + typedef GLuint (APIENTRYP GLEEPFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const GLvoid * pointer, GLenum usage); + GLEE_EXTERN GLEEPFNGLNEWOBJECTBUFFERATIPROC GLeeFuncPtr_glNewObjectBufferATI; + #define glNewObjectBufferATI GLeeFuncPtr_glNewObjectBufferATI +#endif +#ifndef GLEE_H_DEFINED_glIsObjectBufferATI +#define GLEE_H_DEFINED_glIsObjectBufferATI + typedef GLboolean (APIENTRYP GLEEPFNGLISOBJECTBUFFERATIPROC) (GLuint buffer); + GLEE_EXTERN GLEEPFNGLISOBJECTBUFFERATIPROC GLeeFuncPtr_glIsObjectBufferATI; + #define glIsObjectBufferATI GLeeFuncPtr_glIsObjectBufferATI +#endif +#ifndef GLEE_H_DEFINED_glUpdateObjectBufferATI +#define GLEE_H_DEFINED_glUpdateObjectBufferATI + typedef void (APIENTRYP GLEEPFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const GLvoid * pointer, GLenum preserve); + GLEE_EXTERN GLEEPFNGLUPDATEOBJECTBUFFERATIPROC GLeeFuncPtr_glUpdateObjectBufferATI; + #define glUpdateObjectBufferATI GLeeFuncPtr_glUpdateObjectBufferATI +#endif +#ifndef GLEE_H_DEFINED_glGetObjectBufferfvATI +#define GLEE_H_DEFINED_glGetObjectBufferfvATI + typedef void (APIENTRYP GLEEPFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETOBJECTBUFFERFVATIPROC GLeeFuncPtr_glGetObjectBufferfvATI; + #define glGetObjectBufferfvATI GLeeFuncPtr_glGetObjectBufferfvATI +#endif +#ifndef GLEE_H_DEFINED_glGetObjectBufferivATI +#define GLEE_H_DEFINED_glGetObjectBufferivATI + typedef void (APIENTRYP GLEEPFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETOBJECTBUFFERIVATIPROC GLeeFuncPtr_glGetObjectBufferivATI; + #define glGetObjectBufferivATI GLeeFuncPtr_glGetObjectBufferivATI +#endif +#ifndef GLEE_H_DEFINED_glFreeObjectBufferATI +#define GLEE_H_DEFINED_glFreeObjectBufferATI + typedef void (APIENTRYP GLEEPFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer); + GLEE_EXTERN GLEEPFNGLFREEOBJECTBUFFERATIPROC GLeeFuncPtr_glFreeObjectBufferATI; + #define glFreeObjectBufferATI GLeeFuncPtr_glFreeObjectBufferATI +#endif +#ifndef GLEE_H_DEFINED_glArrayObjectATI +#define GLEE_H_DEFINED_glArrayObjectATI + typedef void (APIENTRYP GLEEPFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); + GLEE_EXTERN GLEEPFNGLARRAYOBJECTATIPROC GLeeFuncPtr_glArrayObjectATI; + #define glArrayObjectATI GLeeFuncPtr_glArrayObjectATI +#endif +#ifndef GLEE_H_DEFINED_glGetArrayObjectfvATI +#define GLEE_H_DEFINED_glGetArrayObjectfvATI + typedef void (APIENTRYP GLEEPFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETARRAYOBJECTFVATIPROC GLeeFuncPtr_glGetArrayObjectfvATI; + #define glGetArrayObjectfvATI GLeeFuncPtr_glGetArrayObjectfvATI +#endif +#ifndef GLEE_H_DEFINED_glGetArrayObjectivATI +#define GLEE_H_DEFINED_glGetArrayObjectivATI + typedef void (APIENTRYP GLEEPFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETARRAYOBJECTIVATIPROC GLeeFuncPtr_glGetArrayObjectivATI; + #define glGetArrayObjectivATI GLeeFuncPtr_glGetArrayObjectivATI +#endif +#ifndef GLEE_H_DEFINED_glVariantArrayObjectATI +#define GLEE_H_DEFINED_glVariantArrayObjectATI + typedef void (APIENTRYP GLEEPFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); + GLEE_EXTERN GLEEPFNGLVARIANTARRAYOBJECTATIPROC GLeeFuncPtr_glVariantArrayObjectATI; + #define glVariantArrayObjectATI GLeeFuncPtr_glVariantArrayObjectATI +#endif +#ifndef GLEE_H_DEFINED_glGetVariantArrayObjectfvATI +#define GLEE_H_DEFINED_glGetVariantArrayObjectfvATI + typedef void (APIENTRYP GLEEPFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETVARIANTARRAYOBJECTFVATIPROC GLeeFuncPtr_glGetVariantArrayObjectfvATI; + #define glGetVariantArrayObjectfvATI GLeeFuncPtr_glGetVariantArrayObjectfvATI +#endif +#ifndef GLEE_H_DEFINED_glGetVariantArrayObjectivATI +#define GLEE_H_DEFINED_glGetVariantArrayObjectivATI + typedef void (APIENTRYP GLEEPFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETVARIANTARRAYOBJECTIVATIPROC GLeeFuncPtr_glGetVariantArrayObjectivATI; + #define glGetVariantArrayObjectivATI GLeeFuncPtr_glGetVariantArrayObjectivATI +#endif +#endif + +/* GL_EXT_vertex_shader */ + +#ifndef GL_EXT_vertex_shader +#define GL_EXT_vertex_shader 1 +#define __GLEE_GL_EXT_vertex_shader 1 +/* Constants */ +#define GL_VERTEX_SHADER_EXT 0x8780 +#define GL_VERTEX_SHADER_BINDING_EXT 0x8781 +#define GL_OP_INDEX_EXT 0x8782 +#define GL_OP_NEGATE_EXT 0x8783 +#define GL_OP_DOT3_EXT 0x8784 +#define GL_OP_DOT4_EXT 0x8785 +#define GL_OP_MUL_EXT 0x8786 +#define GL_OP_ADD_EXT 0x8787 +#define GL_OP_MADD_EXT 0x8788 +#define GL_OP_FRAC_EXT 0x8789 +#define GL_OP_MAX_EXT 0x878A +#define GL_OP_MIN_EXT 0x878B +#define GL_OP_SET_GE_EXT 0x878C +#define GL_OP_SET_LT_EXT 0x878D +#define GL_OP_CLAMP_EXT 0x878E +#define GL_OP_FLOOR_EXT 0x878F +#define GL_OP_ROUND_EXT 0x8790 +#define GL_OP_EXP_BASE_2_EXT 0x8791 +#define GL_OP_LOG_BASE_2_EXT 0x8792 +#define GL_OP_POWER_EXT 0x8793 +#define GL_OP_RECIP_EXT 0x8794 +#define GL_OP_RECIP_SQRT_EXT 0x8795 +#define GL_OP_SUB_EXT 0x8796 +#define GL_OP_CROSS_PRODUCT_EXT 0x8797 +#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798 +#define GL_OP_MOV_EXT 0x8799 +#define GL_OUTPUT_VERTEX_EXT 0x879A +#define GL_OUTPUT_COLOR0_EXT 0x879B +#define GL_OUTPUT_COLOR1_EXT 0x879C +#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D +#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E +#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F +#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0 +#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1 +#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2 +#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3 +#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4 +#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5 +#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6 +#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7 +#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8 +#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9 +#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA +#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB +#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC +#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD +#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE +#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF +#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0 +#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1 +#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2 +#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3 +#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4 +#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5 +#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6 +#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7 +#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8 +#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9 +#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA +#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB +#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC +#define GL_OUTPUT_FOG_EXT 0x87BD +#define GL_SCALAR_EXT 0x87BE +#define GL_VECTOR_EXT 0x87BF +#define GL_MATRIX_EXT 0x87C0 +#define GL_VARIANT_EXT 0x87C1 +#define GL_INVARIANT_EXT 0x87C2 +#define GL_LOCAL_CONSTANT_EXT 0x87C3 +#define GL_LOCAL_EXT 0x87C4 +#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5 +#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6 +#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7 +#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8 +#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9 +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE +#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF +#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0 +#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1 +#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2 +#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3 +#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4 +#define GL_X_EXT 0x87D5 +#define GL_Y_EXT 0x87D6 +#define GL_Z_EXT 0x87D7 +#define GL_W_EXT 0x87D8 +#define GL_NEGATIVE_X_EXT 0x87D9 +#define GL_NEGATIVE_Y_EXT 0x87DA +#define GL_NEGATIVE_Z_EXT 0x87DB +#define GL_NEGATIVE_W_EXT 0x87DC +#define GL_ZERO_EXT 0x87DD +#define GL_ONE_EXT 0x87DE +#define GL_NEGATIVE_ONE_EXT 0x87DF +#define GL_NORMALIZED_RANGE_EXT 0x87E0 +#define GL_FULL_RANGE_EXT 0x87E1 +#define GL_CURRENT_VERTEX_EXT 0x87E2 +#define GL_MVP_MATRIX_EXT 0x87E3 +#define GL_VARIANT_VALUE_EXT 0x87E4 +#define GL_VARIANT_DATATYPE_EXT 0x87E5 +#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6 +#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7 +#define GL_VARIANT_ARRAY_EXT 0x87E8 +#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9 +#define GL_INVARIANT_VALUE_EXT 0x87EA +#define GL_INVARIANT_DATATYPE_EXT 0x87EB +#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC +#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED +#ifndef GLEE_H_DEFINED_glBeginVertexShaderEXT +#define GLEE_H_DEFINED_glBeginVertexShaderEXT + typedef void (APIENTRYP GLEEPFNGLBEGINVERTEXSHADEREXTPROC) (); + GLEE_EXTERN GLEEPFNGLBEGINVERTEXSHADEREXTPROC GLeeFuncPtr_glBeginVertexShaderEXT; + #define glBeginVertexShaderEXT GLeeFuncPtr_glBeginVertexShaderEXT +#endif +#ifndef GLEE_H_DEFINED_glEndVertexShaderEXT +#define GLEE_H_DEFINED_glEndVertexShaderEXT + typedef void (APIENTRYP GLEEPFNGLENDVERTEXSHADEREXTPROC) (); + GLEE_EXTERN GLEEPFNGLENDVERTEXSHADEREXTPROC GLeeFuncPtr_glEndVertexShaderEXT; + #define glEndVertexShaderEXT GLeeFuncPtr_glEndVertexShaderEXT +#endif +#ifndef GLEE_H_DEFINED_glBindVertexShaderEXT +#define GLEE_H_DEFINED_glBindVertexShaderEXT + typedef void (APIENTRYP GLEEPFNGLBINDVERTEXSHADEREXTPROC) (GLuint id); + GLEE_EXTERN GLEEPFNGLBINDVERTEXSHADEREXTPROC GLeeFuncPtr_glBindVertexShaderEXT; + #define glBindVertexShaderEXT GLeeFuncPtr_glBindVertexShaderEXT +#endif +#ifndef GLEE_H_DEFINED_glGenVertexShadersEXT +#define GLEE_H_DEFINED_glGenVertexShadersEXT + typedef GLuint (APIENTRYP GLEEPFNGLGENVERTEXSHADERSEXTPROC) (GLuint range); + GLEE_EXTERN GLEEPFNGLGENVERTEXSHADERSEXTPROC GLeeFuncPtr_glGenVertexShadersEXT; + #define glGenVertexShadersEXT GLeeFuncPtr_glGenVertexShadersEXT +#endif +#ifndef GLEE_H_DEFINED_glDeleteVertexShaderEXT +#define GLEE_H_DEFINED_glDeleteVertexShaderEXT + typedef void (APIENTRYP GLEEPFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id); + GLEE_EXTERN GLEEPFNGLDELETEVERTEXSHADEREXTPROC GLeeFuncPtr_glDeleteVertexShaderEXT; + #define glDeleteVertexShaderEXT GLeeFuncPtr_glDeleteVertexShaderEXT +#endif +#ifndef GLEE_H_DEFINED_glShaderOp1EXT +#define GLEE_H_DEFINED_glShaderOp1EXT + typedef void (APIENTRYP GLEEPFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1); + GLEE_EXTERN GLEEPFNGLSHADEROP1EXTPROC GLeeFuncPtr_glShaderOp1EXT; + #define glShaderOp1EXT GLeeFuncPtr_glShaderOp1EXT +#endif +#ifndef GLEE_H_DEFINED_glShaderOp2EXT +#define GLEE_H_DEFINED_glShaderOp2EXT + typedef void (APIENTRYP GLEEPFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2); + GLEE_EXTERN GLEEPFNGLSHADEROP2EXTPROC GLeeFuncPtr_glShaderOp2EXT; + #define glShaderOp2EXT GLeeFuncPtr_glShaderOp2EXT +#endif +#ifndef GLEE_H_DEFINED_glShaderOp3EXT +#define GLEE_H_DEFINED_glShaderOp3EXT + typedef void (APIENTRYP GLEEPFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); + GLEE_EXTERN GLEEPFNGLSHADEROP3EXTPROC GLeeFuncPtr_glShaderOp3EXT; + #define glShaderOp3EXT GLeeFuncPtr_glShaderOp3EXT +#endif +#ifndef GLEE_H_DEFINED_glSwizzleEXT +#define GLEE_H_DEFINED_glSwizzleEXT + typedef void (APIENTRYP GLEEPFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); + GLEE_EXTERN GLEEPFNGLSWIZZLEEXTPROC GLeeFuncPtr_glSwizzleEXT; + #define glSwizzleEXT GLeeFuncPtr_glSwizzleEXT +#endif +#ifndef GLEE_H_DEFINED_glWriteMaskEXT +#define GLEE_H_DEFINED_glWriteMaskEXT + typedef void (APIENTRYP GLEEPFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); + GLEE_EXTERN GLEEPFNGLWRITEMASKEXTPROC GLeeFuncPtr_glWriteMaskEXT; + #define glWriteMaskEXT GLeeFuncPtr_glWriteMaskEXT +#endif +#ifndef GLEE_H_DEFINED_glInsertComponentEXT +#define GLEE_H_DEFINED_glInsertComponentEXT + typedef void (APIENTRYP GLEEPFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); + GLEE_EXTERN GLEEPFNGLINSERTCOMPONENTEXTPROC GLeeFuncPtr_glInsertComponentEXT; + #define glInsertComponentEXT GLeeFuncPtr_glInsertComponentEXT +#endif +#ifndef GLEE_H_DEFINED_glExtractComponentEXT +#define GLEE_H_DEFINED_glExtractComponentEXT + typedef void (APIENTRYP GLEEPFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); + GLEE_EXTERN GLEEPFNGLEXTRACTCOMPONENTEXTPROC GLeeFuncPtr_glExtractComponentEXT; + #define glExtractComponentEXT GLeeFuncPtr_glExtractComponentEXT +#endif +#ifndef GLEE_H_DEFINED_glGenSymbolsEXT +#define GLEE_H_DEFINED_glGenSymbolsEXT + typedef GLuint (APIENTRYP GLEEPFNGLGENSYMBOLSEXTPROC) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components); + GLEE_EXTERN GLEEPFNGLGENSYMBOLSEXTPROC GLeeFuncPtr_glGenSymbolsEXT; + #define glGenSymbolsEXT GLeeFuncPtr_glGenSymbolsEXT +#endif +#ifndef GLEE_H_DEFINED_glSetInvariantEXT +#define GLEE_H_DEFINED_glSetInvariantEXT + typedef void (APIENTRYP GLEEPFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, const GLvoid * addr); + GLEE_EXTERN GLEEPFNGLSETINVARIANTEXTPROC GLeeFuncPtr_glSetInvariantEXT; + #define glSetInvariantEXT GLeeFuncPtr_glSetInvariantEXT +#endif +#ifndef GLEE_H_DEFINED_glSetLocalConstantEXT +#define GLEE_H_DEFINED_glSetLocalConstantEXT + typedef void (APIENTRYP GLEEPFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, const GLvoid * addr); + GLEE_EXTERN GLEEPFNGLSETLOCALCONSTANTEXTPROC GLeeFuncPtr_glSetLocalConstantEXT; + #define glSetLocalConstantEXT GLeeFuncPtr_glSetLocalConstantEXT +#endif +#ifndef GLEE_H_DEFINED_glVariantbvEXT +#define GLEE_H_DEFINED_glVariantbvEXT + typedef void (APIENTRYP GLEEPFNGLVARIANTBVEXTPROC) (GLuint id, const GLbyte * addr); + GLEE_EXTERN GLEEPFNGLVARIANTBVEXTPROC GLeeFuncPtr_glVariantbvEXT; + #define glVariantbvEXT GLeeFuncPtr_glVariantbvEXT +#endif +#ifndef GLEE_H_DEFINED_glVariantsvEXT +#define GLEE_H_DEFINED_glVariantsvEXT + typedef void (APIENTRYP GLEEPFNGLVARIANTSVEXTPROC) (GLuint id, const GLshort * addr); + GLEE_EXTERN GLEEPFNGLVARIANTSVEXTPROC GLeeFuncPtr_glVariantsvEXT; + #define glVariantsvEXT GLeeFuncPtr_glVariantsvEXT +#endif +#ifndef GLEE_H_DEFINED_glVariantivEXT +#define GLEE_H_DEFINED_glVariantivEXT + typedef void (APIENTRYP GLEEPFNGLVARIANTIVEXTPROC) (GLuint id, const GLint * addr); + GLEE_EXTERN GLEEPFNGLVARIANTIVEXTPROC GLeeFuncPtr_glVariantivEXT; + #define glVariantivEXT GLeeFuncPtr_glVariantivEXT +#endif +#ifndef GLEE_H_DEFINED_glVariantfvEXT +#define GLEE_H_DEFINED_glVariantfvEXT + typedef void (APIENTRYP GLEEPFNGLVARIANTFVEXTPROC) (GLuint id, const GLfloat * addr); + GLEE_EXTERN GLEEPFNGLVARIANTFVEXTPROC GLeeFuncPtr_glVariantfvEXT; + #define glVariantfvEXT GLeeFuncPtr_glVariantfvEXT +#endif +#ifndef GLEE_H_DEFINED_glVariantdvEXT +#define GLEE_H_DEFINED_glVariantdvEXT + typedef void (APIENTRYP GLEEPFNGLVARIANTDVEXTPROC) (GLuint id, const GLdouble * addr); + GLEE_EXTERN GLEEPFNGLVARIANTDVEXTPROC GLeeFuncPtr_glVariantdvEXT; + #define glVariantdvEXT GLeeFuncPtr_glVariantdvEXT +#endif +#ifndef GLEE_H_DEFINED_glVariantubvEXT +#define GLEE_H_DEFINED_glVariantubvEXT + typedef void (APIENTRYP GLEEPFNGLVARIANTUBVEXTPROC) (GLuint id, const GLubyte * addr); + GLEE_EXTERN GLEEPFNGLVARIANTUBVEXTPROC GLeeFuncPtr_glVariantubvEXT; + #define glVariantubvEXT GLeeFuncPtr_glVariantubvEXT +#endif +#ifndef GLEE_H_DEFINED_glVariantusvEXT +#define GLEE_H_DEFINED_glVariantusvEXT + typedef void (APIENTRYP GLEEPFNGLVARIANTUSVEXTPROC) (GLuint id, const GLushort * addr); + GLEE_EXTERN GLEEPFNGLVARIANTUSVEXTPROC GLeeFuncPtr_glVariantusvEXT; + #define glVariantusvEXT GLeeFuncPtr_glVariantusvEXT +#endif +#ifndef GLEE_H_DEFINED_glVariantuivEXT +#define GLEE_H_DEFINED_glVariantuivEXT + typedef void (APIENTRYP GLEEPFNGLVARIANTUIVEXTPROC) (GLuint id, const GLuint * addr); + GLEE_EXTERN GLEEPFNGLVARIANTUIVEXTPROC GLeeFuncPtr_glVariantuivEXT; + #define glVariantuivEXT GLeeFuncPtr_glVariantuivEXT +#endif +#ifndef GLEE_H_DEFINED_glVariantPointerEXT +#define GLEE_H_DEFINED_glVariantPointerEXT + typedef void (APIENTRYP GLEEPFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, const GLvoid * addr); + GLEE_EXTERN GLEEPFNGLVARIANTPOINTEREXTPROC GLeeFuncPtr_glVariantPointerEXT; + #define glVariantPointerEXT GLeeFuncPtr_glVariantPointerEXT +#endif +#ifndef GLEE_H_DEFINED_glEnableVariantClientStateEXT +#define GLEE_H_DEFINED_glEnableVariantClientStateEXT + typedef void (APIENTRYP GLEEPFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); + GLEE_EXTERN GLEEPFNGLENABLEVARIANTCLIENTSTATEEXTPROC GLeeFuncPtr_glEnableVariantClientStateEXT; + #define glEnableVariantClientStateEXT GLeeFuncPtr_glEnableVariantClientStateEXT +#endif +#ifndef GLEE_H_DEFINED_glDisableVariantClientStateEXT +#define GLEE_H_DEFINED_glDisableVariantClientStateEXT + typedef void (APIENTRYP GLEEPFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); + GLEE_EXTERN GLEEPFNGLDISABLEVARIANTCLIENTSTATEEXTPROC GLeeFuncPtr_glDisableVariantClientStateEXT; + #define glDisableVariantClientStateEXT GLeeFuncPtr_glDisableVariantClientStateEXT +#endif +#ifndef GLEE_H_DEFINED_glBindLightParameterEXT +#define GLEE_H_DEFINED_glBindLightParameterEXT + typedef GLuint (APIENTRYP GLEEPFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value); + GLEE_EXTERN GLEEPFNGLBINDLIGHTPARAMETEREXTPROC GLeeFuncPtr_glBindLightParameterEXT; + #define glBindLightParameterEXT GLeeFuncPtr_glBindLightParameterEXT +#endif +#ifndef GLEE_H_DEFINED_glBindMaterialParameterEXT +#define GLEE_H_DEFINED_glBindMaterialParameterEXT + typedef GLuint (APIENTRYP GLEEPFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value); + GLEE_EXTERN GLEEPFNGLBINDMATERIALPARAMETEREXTPROC GLeeFuncPtr_glBindMaterialParameterEXT; + #define glBindMaterialParameterEXT GLeeFuncPtr_glBindMaterialParameterEXT +#endif +#ifndef GLEE_H_DEFINED_glBindTexGenParameterEXT +#define GLEE_H_DEFINED_glBindTexGenParameterEXT + typedef GLuint (APIENTRYP GLEEPFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value); + GLEE_EXTERN GLEEPFNGLBINDTEXGENPARAMETEREXTPROC GLeeFuncPtr_glBindTexGenParameterEXT; + #define glBindTexGenParameterEXT GLeeFuncPtr_glBindTexGenParameterEXT +#endif +#ifndef GLEE_H_DEFINED_glBindTextureUnitParameterEXT +#define GLEE_H_DEFINED_glBindTextureUnitParameterEXT + typedef GLuint (APIENTRYP GLEEPFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value); + GLEE_EXTERN GLEEPFNGLBINDTEXTUREUNITPARAMETEREXTPROC GLeeFuncPtr_glBindTextureUnitParameterEXT; + #define glBindTextureUnitParameterEXT GLeeFuncPtr_glBindTextureUnitParameterEXT +#endif +#ifndef GLEE_H_DEFINED_glBindParameterEXT +#define GLEE_H_DEFINED_glBindParameterEXT + typedef GLuint (APIENTRYP GLEEPFNGLBINDPARAMETEREXTPROC) (GLenum value); + GLEE_EXTERN GLEEPFNGLBINDPARAMETEREXTPROC GLeeFuncPtr_glBindParameterEXT; + #define glBindParameterEXT GLeeFuncPtr_glBindParameterEXT +#endif +#ifndef GLEE_H_DEFINED_glIsVariantEnabledEXT +#define GLEE_H_DEFINED_glIsVariantEnabledEXT + typedef GLboolean (APIENTRYP GLEEPFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap); + GLEE_EXTERN GLEEPFNGLISVARIANTENABLEDEXTPROC GLeeFuncPtr_glIsVariantEnabledEXT; + #define glIsVariantEnabledEXT GLeeFuncPtr_glIsVariantEnabledEXT +#endif +#ifndef GLEE_H_DEFINED_glGetVariantBooleanvEXT +#define GLEE_H_DEFINED_glGetVariantBooleanvEXT + typedef void (APIENTRYP GLEEPFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean * data); + GLEE_EXTERN GLEEPFNGLGETVARIANTBOOLEANVEXTPROC GLeeFuncPtr_glGetVariantBooleanvEXT; + #define glGetVariantBooleanvEXT GLeeFuncPtr_glGetVariantBooleanvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetVariantIntegervEXT +#define GLEE_H_DEFINED_glGetVariantIntegervEXT + typedef void (APIENTRYP GLEEPFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint * data); + GLEE_EXTERN GLEEPFNGLGETVARIANTINTEGERVEXTPROC GLeeFuncPtr_glGetVariantIntegervEXT; + #define glGetVariantIntegervEXT GLeeFuncPtr_glGetVariantIntegervEXT +#endif +#ifndef GLEE_H_DEFINED_glGetVariantFloatvEXT +#define GLEE_H_DEFINED_glGetVariantFloatvEXT + typedef void (APIENTRYP GLEEPFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat * data); + GLEE_EXTERN GLEEPFNGLGETVARIANTFLOATVEXTPROC GLeeFuncPtr_glGetVariantFloatvEXT; + #define glGetVariantFloatvEXT GLeeFuncPtr_glGetVariantFloatvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetVariantPointervEXT +#define GLEE_H_DEFINED_glGetVariantPointervEXT + typedef void (APIENTRYP GLEEPFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid* * data); + GLEE_EXTERN GLEEPFNGLGETVARIANTPOINTERVEXTPROC GLeeFuncPtr_glGetVariantPointervEXT; + #define glGetVariantPointervEXT GLeeFuncPtr_glGetVariantPointervEXT +#endif +#ifndef GLEE_H_DEFINED_glGetInvariantBooleanvEXT +#define GLEE_H_DEFINED_glGetInvariantBooleanvEXT + typedef void (APIENTRYP GLEEPFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean * data); + GLEE_EXTERN GLEEPFNGLGETINVARIANTBOOLEANVEXTPROC GLeeFuncPtr_glGetInvariantBooleanvEXT; + #define glGetInvariantBooleanvEXT GLeeFuncPtr_glGetInvariantBooleanvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetInvariantIntegervEXT +#define GLEE_H_DEFINED_glGetInvariantIntegervEXT + typedef void (APIENTRYP GLEEPFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint * data); + GLEE_EXTERN GLEEPFNGLGETINVARIANTINTEGERVEXTPROC GLeeFuncPtr_glGetInvariantIntegervEXT; + #define glGetInvariantIntegervEXT GLeeFuncPtr_glGetInvariantIntegervEXT +#endif +#ifndef GLEE_H_DEFINED_glGetInvariantFloatvEXT +#define GLEE_H_DEFINED_glGetInvariantFloatvEXT + typedef void (APIENTRYP GLEEPFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat * data); + GLEE_EXTERN GLEEPFNGLGETINVARIANTFLOATVEXTPROC GLeeFuncPtr_glGetInvariantFloatvEXT; + #define glGetInvariantFloatvEXT GLeeFuncPtr_glGetInvariantFloatvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetLocalConstantBooleanvEXT +#define GLEE_H_DEFINED_glGetLocalConstantBooleanvEXT + typedef void (APIENTRYP GLEEPFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean * data); + GLEE_EXTERN GLEEPFNGLGETLOCALCONSTANTBOOLEANVEXTPROC GLeeFuncPtr_glGetLocalConstantBooleanvEXT; + #define glGetLocalConstantBooleanvEXT GLeeFuncPtr_glGetLocalConstantBooleanvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetLocalConstantIntegervEXT +#define GLEE_H_DEFINED_glGetLocalConstantIntegervEXT + typedef void (APIENTRYP GLEEPFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint * data); + GLEE_EXTERN GLEEPFNGLGETLOCALCONSTANTINTEGERVEXTPROC GLeeFuncPtr_glGetLocalConstantIntegervEXT; + #define glGetLocalConstantIntegervEXT GLeeFuncPtr_glGetLocalConstantIntegervEXT +#endif +#ifndef GLEE_H_DEFINED_glGetLocalConstantFloatvEXT +#define GLEE_H_DEFINED_glGetLocalConstantFloatvEXT + typedef void (APIENTRYP GLEEPFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat * data); + GLEE_EXTERN GLEEPFNGLGETLOCALCONSTANTFLOATVEXTPROC GLeeFuncPtr_glGetLocalConstantFloatvEXT; + #define glGetLocalConstantFloatvEXT GLeeFuncPtr_glGetLocalConstantFloatvEXT +#endif +#endif + +/* GL_ATI_vertex_streams */ + +#ifndef GL_ATI_vertex_streams +#define GL_ATI_vertex_streams 1 +#define __GLEE_GL_ATI_vertex_streams 1 +/* Constants */ +#define GL_MAX_VERTEX_STREAMS_ATI 0x876B +#define GL_VERTEX_STREAM0_ATI 0x876C +#define GL_VERTEX_STREAM1_ATI 0x876D +#define GL_VERTEX_STREAM2_ATI 0x876E +#define GL_VERTEX_STREAM3_ATI 0x876F +#define GL_VERTEX_STREAM4_ATI 0x8770 +#define GL_VERTEX_STREAM5_ATI 0x8771 +#define GL_VERTEX_STREAM6_ATI 0x8772 +#define GL_VERTEX_STREAM7_ATI 0x8773 +#define GL_VERTEX_SOURCE_ATI 0x8774 +#ifndef GLEE_H_DEFINED_glVertexStream1sATI +#define GLEE_H_DEFINED_glVertexStream1sATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM1SATIPROC) (GLenum stream, GLshort x); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM1SATIPROC GLeeFuncPtr_glVertexStream1sATI; + #define glVertexStream1sATI GLeeFuncPtr_glVertexStream1sATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream1svATI +#define GLEE_H_DEFINED_glVertexStream1svATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM1SVATIPROC) (GLenum stream, const GLshort * coords); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM1SVATIPROC GLeeFuncPtr_glVertexStream1svATI; + #define glVertexStream1svATI GLeeFuncPtr_glVertexStream1svATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream1iATI +#define GLEE_H_DEFINED_glVertexStream1iATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM1IATIPROC) (GLenum stream, GLint x); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM1IATIPROC GLeeFuncPtr_glVertexStream1iATI; + #define glVertexStream1iATI GLeeFuncPtr_glVertexStream1iATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream1ivATI +#define GLEE_H_DEFINED_glVertexStream1ivATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM1IVATIPROC) (GLenum stream, const GLint * coords); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM1IVATIPROC GLeeFuncPtr_glVertexStream1ivATI; + #define glVertexStream1ivATI GLeeFuncPtr_glVertexStream1ivATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream1fATI +#define GLEE_H_DEFINED_glVertexStream1fATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM1FATIPROC) (GLenum stream, GLfloat x); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM1FATIPROC GLeeFuncPtr_glVertexStream1fATI; + #define glVertexStream1fATI GLeeFuncPtr_glVertexStream1fATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream1fvATI +#define GLEE_H_DEFINED_glVertexStream1fvATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM1FVATIPROC) (GLenum stream, const GLfloat * coords); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM1FVATIPROC GLeeFuncPtr_glVertexStream1fvATI; + #define glVertexStream1fvATI GLeeFuncPtr_glVertexStream1fvATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream1dATI +#define GLEE_H_DEFINED_glVertexStream1dATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM1DATIPROC) (GLenum stream, GLdouble x); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM1DATIPROC GLeeFuncPtr_glVertexStream1dATI; + #define glVertexStream1dATI GLeeFuncPtr_glVertexStream1dATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream1dvATI +#define GLEE_H_DEFINED_glVertexStream1dvATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM1DVATIPROC) (GLenum stream, const GLdouble * coords); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM1DVATIPROC GLeeFuncPtr_glVertexStream1dvATI; + #define glVertexStream1dvATI GLeeFuncPtr_glVertexStream1dvATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream2sATI +#define GLEE_H_DEFINED_glVertexStream2sATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM2SATIPROC GLeeFuncPtr_glVertexStream2sATI; + #define glVertexStream2sATI GLeeFuncPtr_glVertexStream2sATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream2svATI +#define GLEE_H_DEFINED_glVertexStream2svATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort * coords); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM2SVATIPROC GLeeFuncPtr_glVertexStream2svATI; + #define glVertexStream2svATI GLeeFuncPtr_glVertexStream2svATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream2iATI +#define GLEE_H_DEFINED_glVertexStream2iATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM2IATIPROC GLeeFuncPtr_glVertexStream2iATI; + #define glVertexStream2iATI GLeeFuncPtr_glVertexStream2iATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream2ivATI +#define GLEE_H_DEFINED_glVertexStream2ivATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint * coords); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM2IVATIPROC GLeeFuncPtr_glVertexStream2ivATI; + #define glVertexStream2ivATI GLeeFuncPtr_glVertexStream2ivATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream2fATI +#define GLEE_H_DEFINED_glVertexStream2fATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM2FATIPROC GLeeFuncPtr_glVertexStream2fATI; + #define glVertexStream2fATI GLeeFuncPtr_glVertexStream2fATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream2fvATI +#define GLEE_H_DEFINED_glVertexStream2fvATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat * coords); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM2FVATIPROC GLeeFuncPtr_glVertexStream2fvATI; + #define glVertexStream2fvATI GLeeFuncPtr_glVertexStream2fvATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream2dATI +#define GLEE_H_DEFINED_glVertexStream2dATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM2DATIPROC GLeeFuncPtr_glVertexStream2dATI; + #define glVertexStream2dATI GLeeFuncPtr_glVertexStream2dATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream2dvATI +#define GLEE_H_DEFINED_glVertexStream2dvATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble * coords); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM2DVATIPROC GLeeFuncPtr_glVertexStream2dvATI; + #define glVertexStream2dvATI GLeeFuncPtr_glVertexStream2dvATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream3sATI +#define GLEE_H_DEFINED_glVertexStream3sATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM3SATIPROC GLeeFuncPtr_glVertexStream3sATI; + #define glVertexStream3sATI GLeeFuncPtr_glVertexStream3sATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream3svATI +#define GLEE_H_DEFINED_glVertexStream3svATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort * coords); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM3SVATIPROC GLeeFuncPtr_glVertexStream3svATI; + #define glVertexStream3svATI GLeeFuncPtr_glVertexStream3svATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream3iATI +#define GLEE_H_DEFINED_glVertexStream3iATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM3IATIPROC GLeeFuncPtr_glVertexStream3iATI; + #define glVertexStream3iATI GLeeFuncPtr_glVertexStream3iATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream3ivATI +#define GLEE_H_DEFINED_glVertexStream3ivATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint * coords); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM3IVATIPROC GLeeFuncPtr_glVertexStream3ivATI; + #define glVertexStream3ivATI GLeeFuncPtr_glVertexStream3ivATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream3fATI +#define GLEE_H_DEFINED_glVertexStream3fATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM3FATIPROC GLeeFuncPtr_glVertexStream3fATI; + #define glVertexStream3fATI GLeeFuncPtr_glVertexStream3fATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream3fvATI +#define GLEE_H_DEFINED_glVertexStream3fvATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat * coords); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM3FVATIPROC GLeeFuncPtr_glVertexStream3fvATI; + #define glVertexStream3fvATI GLeeFuncPtr_glVertexStream3fvATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream3dATI +#define GLEE_H_DEFINED_glVertexStream3dATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM3DATIPROC GLeeFuncPtr_glVertexStream3dATI; + #define glVertexStream3dATI GLeeFuncPtr_glVertexStream3dATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream3dvATI +#define GLEE_H_DEFINED_glVertexStream3dvATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble * coords); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM3DVATIPROC GLeeFuncPtr_glVertexStream3dvATI; + #define glVertexStream3dvATI GLeeFuncPtr_glVertexStream3dvATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream4sATI +#define GLEE_H_DEFINED_glVertexStream4sATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM4SATIPROC GLeeFuncPtr_glVertexStream4sATI; + #define glVertexStream4sATI GLeeFuncPtr_glVertexStream4sATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream4svATI +#define GLEE_H_DEFINED_glVertexStream4svATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort * coords); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM4SVATIPROC GLeeFuncPtr_glVertexStream4svATI; + #define glVertexStream4svATI GLeeFuncPtr_glVertexStream4svATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream4iATI +#define GLEE_H_DEFINED_glVertexStream4iATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM4IATIPROC GLeeFuncPtr_glVertexStream4iATI; + #define glVertexStream4iATI GLeeFuncPtr_glVertexStream4iATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream4ivATI +#define GLEE_H_DEFINED_glVertexStream4ivATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint * coords); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM4IVATIPROC GLeeFuncPtr_glVertexStream4ivATI; + #define glVertexStream4ivATI GLeeFuncPtr_glVertexStream4ivATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream4fATI +#define GLEE_H_DEFINED_glVertexStream4fATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM4FATIPROC GLeeFuncPtr_glVertexStream4fATI; + #define glVertexStream4fATI GLeeFuncPtr_glVertexStream4fATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream4fvATI +#define GLEE_H_DEFINED_glVertexStream4fvATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat * coords); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM4FVATIPROC GLeeFuncPtr_glVertexStream4fvATI; + #define glVertexStream4fvATI GLeeFuncPtr_glVertexStream4fvATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream4dATI +#define GLEE_H_DEFINED_glVertexStream4dATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM4DATIPROC GLeeFuncPtr_glVertexStream4dATI; + #define glVertexStream4dATI GLeeFuncPtr_glVertexStream4dATI +#endif +#ifndef GLEE_H_DEFINED_glVertexStream4dvATI +#define GLEE_H_DEFINED_glVertexStream4dvATI + typedef void (APIENTRYP GLEEPFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble * coords); + GLEE_EXTERN GLEEPFNGLVERTEXSTREAM4DVATIPROC GLeeFuncPtr_glVertexStream4dvATI; + #define glVertexStream4dvATI GLeeFuncPtr_glVertexStream4dvATI +#endif +#ifndef GLEE_H_DEFINED_glNormalStream3bATI +#define GLEE_H_DEFINED_glNormalStream3bATI + typedef void (APIENTRYP GLEEPFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz); + GLEE_EXTERN GLEEPFNGLNORMALSTREAM3BATIPROC GLeeFuncPtr_glNormalStream3bATI; + #define glNormalStream3bATI GLeeFuncPtr_glNormalStream3bATI +#endif +#ifndef GLEE_H_DEFINED_glNormalStream3bvATI +#define GLEE_H_DEFINED_glNormalStream3bvATI + typedef void (APIENTRYP GLEEPFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte * coords); + GLEE_EXTERN GLEEPFNGLNORMALSTREAM3BVATIPROC GLeeFuncPtr_glNormalStream3bvATI; + #define glNormalStream3bvATI GLeeFuncPtr_glNormalStream3bvATI +#endif +#ifndef GLEE_H_DEFINED_glNormalStream3sATI +#define GLEE_H_DEFINED_glNormalStream3sATI + typedef void (APIENTRYP GLEEPFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort nx, GLshort ny, GLshort nz); + GLEE_EXTERN GLEEPFNGLNORMALSTREAM3SATIPROC GLeeFuncPtr_glNormalStream3sATI; + #define glNormalStream3sATI GLeeFuncPtr_glNormalStream3sATI +#endif +#ifndef GLEE_H_DEFINED_glNormalStream3svATI +#define GLEE_H_DEFINED_glNormalStream3svATI + typedef void (APIENTRYP GLEEPFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort * coords); + GLEE_EXTERN GLEEPFNGLNORMALSTREAM3SVATIPROC GLeeFuncPtr_glNormalStream3svATI; + #define glNormalStream3svATI GLeeFuncPtr_glNormalStream3svATI +#endif +#ifndef GLEE_H_DEFINED_glNormalStream3iATI +#define GLEE_H_DEFINED_glNormalStream3iATI + typedef void (APIENTRYP GLEEPFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint nx, GLint ny, GLint nz); + GLEE_EXTERN GLEEPFNGLNORMALSTREAM3IATIPROC GLeeFuncPtr_glNormalStream3iATI; + #define glNormalStream3iATI GLeeFuncPtr_glNormalStream3iATI +#endif +#ifndef GLEE_H_DEFINED_glNormalStream3ivATI +#define GLEE_H_DEFINED_glNormalStream3ivATI + typedef void (APIENTRYP GLEEPFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint * coords); + GLEE_EXTERN GLEEPFNGLNORMALSTREAM3IVATIPROC GLeeFuncPtr_glNormalStream3ivATI; + #define glNormalStream3ivATI GLeeFuncPtr_glNormalStream3ivATI +#endif +#ifndef GLEE_H_DEFINED_glNormalStream3fATI +#define GLEE_H_DEFINED_glNormalStream3fATI + typedef void (APIENTRYP GLEEPFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz); + GLEE_EXTERN GLEEPFNGLNORMALSTREAM3FATIPROC GLeeFuncPtr_glNormalStream3fATI; + #define glNormalStream3fATI GLeeFuncPtr_glNormalStream3fATI +#endif +#ifndef GLEE_H_DEFINED_glNormalStream3fvATI +#define GLEE_H_DEFINED_glNormalStream3fvATI + typedef void (APIENTRYP GLEEPFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat * coords); + GLEE_EXTERN GLEEPFNGLNORMALSTREAM3FVATIPROC GLeeFuncPtr_glNormalStream3fvATI; + #define glNormalStream3fvATI GLeeFuncPtr_glNormalStream3fvATI +#endif +#ifndef GLEE_H_DEFINED_glNormalStream3dATI +#define GLEE_H_DEFINED_glNormalStream3dATI + typedef void (APIENTRYP GLEEPFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz); + GLEE_EXTERN GLEEPFNGLNORMALSTREAM3DATIPROC GLeeFuncPtr_glNormalStream3dATI; + #define glNormalStream3dATI GLeeFuncPtr_glNormalStream3dATI +#endif +#ifndef GLEE_H_DEFINED_glNormalStream3dvATI +#define GLEE_H_DEFINED_glNormalStream3dvATI + typedef void (APIENTRYP GLEEPFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble * coords); + GLEE_EXTERN GLEEPFNGLNORMALSTREAM3DVATIPROC GLeeFuncPtr_glNormalStream3dvATI; + #define glNormalStream3dvATI GLeeFuncPtr_glNormalStream3dvATI +#endif +#ifndef GLEE_H_DEFINED_glClientActiveVertexStreamATI +#define GLEE_H_DEFINED_glClientActiveVertexStreamATI + typedef void (APIENTRYP GLEEPFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream); + GLEE_EXTERN GLEEPFNGLCLIENTACTIVEVERTEXSTREAMATIPROC GLeeFuncPtr_glClientActiveVertexStreamATI; + #define glClientActiveVertexStreamATI GLeeFuncPtr_glClientActiveVertexStreamATI +#endif +#ifndef GLEE_H_DEFINED_glVertexBlendEnviATI +#define GLEE_H_DEFINED_glVertexBlendEnviATI + typedef void (APIENTRYP GLEEPFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLVERTEXBLENDENVIATIPROC GLeeFuncPtr_glVertexBlendEnviATI; + #define glVertexBlendEnviATI GLeeFuncPtr_glVertexBlendEnviATI +#endif +#ifndef GLEE_H_DEFINED_glVertexBlendEnvfATI +#define GLEE_H_DEFINED_glVertexBlendEnvfATI + typedef void (APIENTRYP GLEEPFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLVERTEXBLENDENVFATIPROC GLeeFuncPtr_glVertexBlendEnvfATI; + #define glVertexBlendEnvfATI GLeeFuncPtr_glVertexBlendEnvfATI +#endif +#endif + +/* GL_ATI_element_array */ + +#ifndef GL_ATI_element_array +#define GL_ATI_element_array 1 +#define __GLEE_GL_ATI_element_array 1 +/* Constants */ +#define GL_ELEMENT_ARRAY_ATI 0x8768 +#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769 +#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A +#ifndef GLEE_H_DEFINED_glElementPointerATI +#define GLEE_H_DEFINED_glElementPointerATI + typedef void (APIENTRYP GLEEPFNGLELEMENTPOINTERATIPROC) (GLenum type, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLELEMENTPOINTERATIPROC GLeeFuncPtr_glElementPointerATI; + #define glElementPointerATI GLeeFuncPtr_glElementPointerATI +#endif +#ifndef GLEE_H_DEFINED_glDrawElementArrayATI +#define GLEE_H_DEFINED_glDrawElementArrayATI + typedef void (APIENTRYP GLEEPFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count); + GLEE_EXTERN GLEEPFNGLDRAWELEMENTARRAYATIPROC GLeeFuncPtr_glDrawElementArrayATI; + #define glDrawElementArrayATI GLeeFuncPtr_glDrawElementArrayATI +#endif +#ifndef GLEE_H_DEFINED_glDrawRangeElementArrayATI +#define GLEE_H_DEFINED_glDrawRangeElementArrayATI + typedef void (APIENTRYP GLEEPFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count); + GLEE_EXTERN GLEEPFNGLDRAWRANGEELEMENTARRAYATIPROC GLeeFuncPtr_glDrawRangeElementArrayATI; + #define glDrawRangeElementArrayATI GLeeFuncPtr_glDrawRangeElementArrayATI +#endif +#endif + +/* GL_SUN_mesh_array */ + +#ifndef GL_SUN_mesh_array +#define GL_SUN_mesh_array 1 +#define __GLEE_GL_SUN_mesh_array 1 +/* Constants */ +#define GL_QUAD_MESH_SUN 0x8614 +#define GL_TRIANGLE_MESH_SUN 0x8615 +#ifndef GLEE_H_DEFINED_glDrawMeshArraysSUN +#define GLEE_H_DEFINED_glDrawMeshArraysSUN + typedef void (APIENTRYP GLEEPFNGLDRAWMESHARRAYSSUNPROC) (GLenum mode, GLint first, GLsizei count, GLsizei width); + GLEE_EXTERN GLEEPFNGLDRAWMESHARRAYSSUNPROC GLeeFuncPtr_glDrawMeshArraysSUN; + #define glDrawMeshArraysSUN GLeeFuncPtr_glDrawMeshArraysSUN +#endif +#endif + +/* GL_SUN_slice_accum */ + +#ifndef GL_SUN_slice_accum +#define GL_SUN_slice_accum 1 +#define __GLEE_GL_SUN_slice_accum 1 +/* Constants */ +#define GL_SLICE_ACCUM_SUN 0x85CC +#endif + +/* GL_NV_multisample_filter_hint */ + +#ifndef GL_NV_multisample_filter_hint +#define GL_NV_multisample_filter_hint 1 +#define __GLEE_GL_NV_multisample_filter_hint 1 +/* Constants */ +#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 +#endif + +/* GL_NV_depth_clamp */ + +#ifndef GL_NV_depth_clamp +#define GL_NV_depth_clamp 1 +#define __GLEE_GL_NV_depth_clamp 1 +/* Constants */ +#define GL_DEPTH_CLAMP_NV 0x864F +#endif + +/* GL_NV_occlusion_query */ + +#ifndef GL_NV_occlusion_query +#define GL_NV_occlusion_query 1 +#define __GLEE_GL_NV_occlusion_query 1 +/* Constants */ +#define GL_PIXEL_COUNTER_BITS_NV 0x8864 +#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865 +#define GL_PIXEL_COUNT_NV 0x8866 +#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867 +#ifndef GLEE_H_DEFINED_glGenOcclusionQueriesNV +#define GLEE_H_DEFINED_glGenOcclusionQueriesNV + typedef void (APIENTRYP GLEEPFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint * ids); + GLEE_EXTERN GLEEPFNGLGENOCCLUSIONQUERIESNVPROC GLeeFuncPtr_glGenOcclusionQueriesNV; + #define glGenOcclusionQueriesNV GLeeFuncPtr_glGenOcclusionQueriesNV +#endif +#ifndef GLEE_H_DEFINED_glDeleteOcclusionQueriesNV +#define GLEE_H_DEFINED_glDeleteOcclusionQueriesNV + typedef void (APIENTRYP GLEEPFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint * ids); + GLEE_EXTERN GLEEPFNGLDELETEOCCLUSIONQUERIESNVPROC GLeeFuncPtr_glDeleteOcclusionQueriesNV; + #define glDeleteOcclusionQueriesNV GLeeFuncPtr_glDeleteOcclusionQueriesNV +#endif +#ifndef GLEE_H_DEFINED_glIsOcclusionQueryNV +#define GLEE_H_DEFINED_glIsOcclusionQueryNV + typedef GLboolean (APIENTRYP GLEEPFNGLISOCCLUSIONQUERYNVPROC) (GLuint id); + GLEE_EXTERN GLEEPFNGLISOCCLUSIONQUERYNVPROC GLeeFuncPtr_glIsOcclusionQueryNV; + #define glIsOcclusionQueryNV GLeeFuncPtr_glIsOcclusionQueryNV +#endif +#ifndef GLEE_H_DEFINED_glBeginOcclusionQueryNV +#define GLEE_H_DEFINED_glBeginOcclusionQueryNV + typedef void (APIENTRYP GLEEPFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id); + GLEE_EXTERN GLEEPFNGLBEGINOCCLUSIONQUERYNVPROC GLeeFuncPtr_glBeginOcclusionQueryNV; + #define glBeginOcclusionQueryNV GLeeFuncPtr_glBeginOcclusionQueryNV +#endif +#ifndef GLEE_H_DEFINED_glEndOcclusionQueryNV +#define GLEE_H_DEFINED_glEndOcclusionQueryNV + typedef void (APIENTRYP GLEEPFNGLENDOCCLUSIONQUERYNVPROC) (); + GLEE_EXTERN GLEEPFNGLENDOCCLUSIONQUERYNVPROC GLeeFuncPtr_glEndOcclusionQueryNV; + #define glEndOcclusionQueryNV GLeeFuncPtr_glEndOcclusionQueryNV +#endif +#ifndef GLEE_H_DEFINED_glGetOcclusionQueryivNV +#define GLEE_H_DEFINED_glGetOcclusionQueryivNV + typedef void (APIENTRYP GLEEPFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETOCCLUSIONQUERYIVNVPROC GLeeFuncPtr_glGetOcclusionQueryivNV; + #define glGetOcclusionQueryivNV GLeeFuncPtr_glGetOcclusionQueryivNV +#endif +#ifndef GLEE_H_DEFINED_glGetOcclusionQueryuivNV +#define GLEE_H_DEFINED_glGetOcclusionQueryuivNV + typedef void (APIENTRYP GLEEPFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint * params); + GLEE_EXTERN GLEEPFNGLGETOCCLUSIONQUERYUIVNVPROC GLeeFuncPtr_glGetOcclusionQueryuivNV; + #define glGetOcclusionQueryuivNV GLeeFuncPtr_glGetOcclusionQueryuivNV +#endif +#endif + +/* GL_NV_point_sprite */ + +#ifndef GL_NV_point_sprite +#define GL_NV_point_sprite 1 +#define __GLEE_GL_NV_point_sprite 1 +/* Constants */ +#define GL_POINT_SPRITE_NV 0x8861 +#define GL_COORD_REPLACE_NV 0x8862 +#define GL_POINT_SPRITE_R_MODE_NV 0x8863 +#ifndef GLEE_H_DEFINED_glPointParameteriNV +#define GLEE_H_DEFINED_glPointParameteriNV + typedef void (APIENTRYP GLEEPFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLPOINTPARAMETERINVPROC GLeeFuncPtr_glPointParameteriNV; + #define glPointParameteriNV GLeeFuncPtr_glPointParameteriNV +#endif +#ifndef GLEE_H_DEFINED_glPointParameterivNV +#define GLEE_H_DEFINED_glPointParameterivNV + typedef void (APIENTRYP GLEEPFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLPOINTPARAMETERIVNVPROC GLeeFuncPtr_glPointParameterivNV; + #define glPointParameterivNV GLeeFuncPtr_glPointParameterivNV +#endif +#endif + +/* GL_NV_texture_shader3 */ + +#ifndef GL_NV_texture_shader3 +#define GL_NV_texture_shader3 1 +#define __GLEE_GL_NV_texture_shader3 1 +/* Constants */ +#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850 +#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851 +#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852 +#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853 +#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854 +#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855 +#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856 +#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857 +#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858 +#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859 +#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A +#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B +#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C +#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D +#define GL_HILO8_NV 0x885E +#define GL_SIGNED_HILO8_NV 0x885F +#define GL_FORCE_BLUE_TO_ONE_NV 0x8860 +#endif + +/* GL_NV_vertex_program1_1 */ + +#ifndef GL_NV_vertex_program1_1 +#define GL_NV_vertex_program1_1 1 +#define __GLEE_GL_NV_vertex_program1_1 1 +/* Constants */ +#endif + +/* GL_EXT_shadow_funcs */ + +#ifndef GL_EXT_shadow_funcs +#define GL_EXT_shadow_funcs 1 +#define __GLEE_GL_EXT_shadow_funcs 1 +/* Constants */ +#endif + +/* GL_EXT_stencil_two_side */ + +#ifndef GL_EXT_stencil_two_side +#define GL_EXT_stencil_two_side 1 +#define __GLEE_GL_EXT_stencil_two_side 1 +/* Constants */ +#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910 +#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911 +#ifndef GLEE_H_DEFINED_glActiveStencilFaceEXT +#define GLEE_H_DEFINED_glActiveStencilFaceEXT + typedef void (APIENTRYP GLEEPFNGLACTIVESTENCILFACEEXTPROC) (GLenum face); + GLEE_EXTERN GLEEPFNGLACTIVESTENCILFACEEXTPROC GLeeFuncPtr_glActiveStencilFaceEXT; + #define glActiveStencilFaceEXT GLeeFuncPtr_glActiveStencilFaceEXT +#endif +#endif + +/* GL_ATI_text_fragment_shader */ + +#ifndef GL_ATI_text_fragment_shader +#define GL_ATI_text_fragment_shader 1 +#define __GLEE_GL_ATI_text_fragment_shader 1 +/* Constants */ +#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200 +#endif + +/* GL_APPLE_client_storage */ + +#ifndef GL_APPLE_client_storage +#define GL_APPLE_client_storage 1 +#define __GLEE_GL_APPLE_client_storage 1 +/* Constants */ +#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2 +#endif + +/* GL_APPLE_element_array */ + +#ifndef GL_APPLE_element_array +#define GL_APPLE_element_array 1 +#define __GLEE_GL_APPLE_element_array 1 +/* Constants */ +#define GL_ELEMENT_ARRAY_APPLE 0x8768 +#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8769 +#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x876A +#ifndef GLEE_H_DEFINED_glElementPointerAPPLE +#define GLEE_H_DEFINED_glElementPointerAPPLE + typedef void (APIENTRYP GLEEPFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLELEMENTPOINTERAPPLEPROC GLeeFuncPtr_glElementPointerAPPLE; + #define glElementPointerAPPLE GLeeFuncPtr_glElementPointerAPPLE +#endif +#ifndef GLEE_H_DEFINED_glDrawElementArrayAPPLE +#define GLEE_H_DEFINED_glDrawElementArrayAPPLE + typedef void (APIENTRYP GLEEPFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count); + GLEE_EXTERN GLEEPFNGLDRAWELEMENTARRAYAPPLEPROC GLeeFuncPtr_glDrawElementArrayAPPLE; + #define glDrawElementArrayAPPLE GLeeFuncPtr_glDrawElementArrayAPPLE +#endif +#ifndef GLEE_H_DEFINED_glDrawRangeElementArrayAPPLE +#define GLEE_H_DEFINED_glDrawRangeElementArrayAPPLE + typedef void (APIENTRYP GLEEPFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); + GLEE_EXTERN GLEEPFNGLDRAWRANGEELEMENTARRAYAPPLEPROC GLeeFuncPtr_glDrawRangeElementArrayAPPLE; + #define glDrawRangeElementArrayAPPLE GLeeFuncPtr_glDrawRangeElementArrayAPPLE +#endif +#ifndef GLEE_H_DEFINED_glMultiDrawElementArrayAPPLE +#define GLEE_H_DEFINED_glMultiDrawElementArrayAPPLE + typedef void (APIENTRYP GLEEPFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint * first, const GLsizei * count, GLsizei primcount); + GLEE_EXTERN GLEEPFNGLMULTIDRAWELEMENTARRAYAPPLEPROC GLeeFuncPtr_glMultiDrawElementArrayAPPLE; + #define glMultiDrawElementArrayAPPLE GLeeFuncPtr_glMultiDrawElementArrayAPPLE +#endif +#ifndef GLEE_H_DEFINED_glMultiDrawRangeElementArrayAPPLE +#define GLEE_H_DEFINED_glMultiDrawRangeElementArrayAPPLE + typedef void (APIENTRYP GLEEPFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint * first, const GLsizei * count, GLsizei primcount); + GLEE_EXTERN GLEEPFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC GLeeFuncPtr_glMultiDrawRangeElementArrayAPPLE; + #define glMultiDrawRangeElementArrayAPPLE GLeeFuncPtr_glMultiDrawRangeElementArrayAPPLE +#endif +#endif + +/* GL_APPLE_fence */ + +#ifndef GL_APPLE_fence +#define GL_APPLE_fence 1 +#define __GLEE_GL_APPLE_fence 1 +/* Constants */ +#define GL_DRAW_PIXELS_APPLE 0x8A0A +#define GL_FENCE_APPLE 0x8A0B +#ifndef GLEE_H_DEFINED_glGenFencesAPPLE +#define GLEE_H_DEFINED_glGenFencesAPPLE + typedef void (APIENTRYP GLEEPFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint * fences); + GLEE_EXTERN GLEEPFNGLGENFENCESAPPLEPROC GLeeFuncPtr_glGenFencesAPPLE; + #define glGenFencesAPPLE GLeeFuncPtr_glGenFencesAPPLE +#endif +#ifndef GLEE_H_DEFINED_glDeleteFencesAPPLE +#define GLEE_H_DEFINED_glDeleteFencesAPPLE + typedef void (APIENTRYP GLEEPFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint * fences); + GLEE_EXTERN GLEEPFNGLDELETEFENCESAPPLEPROC GLeeFuncPtr_glDeleteFencesAPPLE; + #define glDeleteFencesAPPLE GLeeFuncPtr_glDeleteFencesAPPLE +#endif +#ifndef GLEE_H_DEFINED_glSetFenceAPPLE +#define GLEE_H_DEFINED_glSetFenceAPPLE + typedef void (APIENTRYP GLEEPFNGLSETFENCEAPPLEPROC) (GLuint fence); + GLEE_EXTERN GLEEPFNGLSETFENCEAPPLEPROC GLeeFuncPtr_glSetFenceAPPLE; + #define glSetFenceAPPLE GLeeFuncPtr_glSetFenceAPPLE +#endif +#ifndef GLEE_H_DEFINED_glIsFenceAPPLE +#define GLEE_H_DEFINED_glIsFenceAPPLE + typedef GLboolean (APIENTRYP GLEEPFNGLISFENCEAPPLEPROC) (GLuint fence); + GLEE_EXTERN GLEEPFNGLISFENCEAPPLEPROC GLeeFuncPtr_glIsFenceAPPLE; + #define glIsFenceAPPLE GLeeFuncPtr_glIsFenceAPPLE +#endif +#ifndef GLEE_H_DEFINED_glTestFenceAPPLE +#define GLEE_H_DEFINED_glTestFenceAPPLE + typedef GLboolean (APIENTRYP GLEEPFNGLTESTFENCEAPPLEPROC) (GLuint fence); + GLEE_EXTERN GLEEPFNGLTESTFENCEAPPLEPROC GLeeFuncPtr_glTestFenceAPPLE; + #define glTestFenceAPPLE GLeeFuncPtr_glTestFenceAPPLE +#endif +#ifndef GLEE_H_DEFINED_glFinishFenceAPPLE +#define GLEE_H_DEFINED_glFinishFenceAPPLE + typedef void (APIENTRYP GLEEPFNGLFINISHFENCEAPPLEPROC) (GLuint fence); + GLEE_EXTERN GLEEPFNGLFINISHFENCEAPPLEPROC GLeeFuncPtr_glFinishFenceAPPLE; + #define glFinishFenceAPPLE GLeeFuncPtr_glFinishFenceAPPLE +#endif +#ifndef GLEE_H_DEFINED_glTestObjectAPPLE +#define GLEE_H_DEFINED_glTestObjectAPPLE + typedef GLboolean (APIENTRYP GLEEPFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name); + GLEE_EXTERN GLEEPFNGLTESTOBJECTAPPLEPROC GLeeFuncPtr_glTestObjectAPPLE; + #define glTestObjectAPPLE GLeeFuncPtr_glTestObjectAPPLE +#endif +#ifndef GLEE_H_DEFINED_glFinishObjectAPPLE +#define GLEE_H_DEFINED_glFinishObjectAPPLE + typedef void (APIENTRYP GLEEPFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name); + GLEE_EXTERN GLEEPFNGLFINISHOBJECTAPPLEPROC GLeeFuncPtr_glFinishObjectAPPLE; + #define glFinishObjectAPPLE GLeeFuncPtr_glFinishObjectAPPLE +#endif +#endif + +/* GL_APPLE_vertex_array_object */ + +#ifndef GL_APPLE_vertex_array_object +#define GL_APPLE_vertex_array_object 1 +#define __GLEE_GL_APPLE_vertex_array_object 1 +/* Constants */ +#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5 +#ifndef GLEE_H_DEFINED_glBindVertexArrayAPPLE +#define GLEE_H_DEFINED_glBindVertexArrayAPPLE + typedef void (APIENTRYP GLEEPFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array); + GLEE_EXTERN GLEEPFNGLBINDVERTEXARRAYAPPLEPROC GLeeFuncPtr_glBindVertexArrayAPPLE; + #define glBindVertexArrayAPPLE GLeeFuncPtr_glBindVertexArrayAPPLE +#endif +#ifndef GLEE_H_DEFINED_glDeleteVertexArraysAPPLE +#define GLEE_H_DEFINED_glDeleteVertexArraysAPPLE + typedef void (APIENTRYP GLEEPFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint * arrays); + GLEE_EXTERN GLEEPFNGLDELETEVERTEXARRAYSAPPLEPROC GLeeFuncPtr_glDeleteVertexArraysAPPLE; + #define glDeleteVertexArraysAPPLE GLeeFuncPtr_glDeleteVertexArraysAPPLE +#endif +#ifndef GLEE_H_DEFINED_glGenVertexArraysAPPLE +#define GLEE_H_DEFINED_glGenVertexArraysAPPLE + typedef void (APIENTRYP GLEEPFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, GLuint * arrays); + GLEE_EXTERN GLEEPFNGLGENVERTEXARRAYSAPPLEPROC GLeeFuncPtr_glGenVertexArraysAPPLE; + #define glGenVertexArraysAPPLE GLeeFuncPtr_glGenVertexArraysAPPLE +#endif +#ifndef GLEE_H_DEFINED_glIsVertexArrayAPPLE +#define GLEE_H_DEFINED_glIsVertexArrayAPPLE + typedef GLboolean (APIENTRYP GLEEPFNGLISVERTEXARRAYAPPLEPROC) (GLuint array); + GLEE_EXTERN GLEEPFNGLISVERTEXARRAYAPPLEPROC GLeeFuncPtr_glIsVertexArrayAPPLE; + #define glIsVertexArrayAPPLE GLeeFuncPtr_glIsVertexArrayAPPLE +#endif +#endif + +/* GL_APPLE_vertex_array_range */ + +#ifndef GL_APPLE_vertex_array_range +#define GL_APPLE_vertex_array_range 1 +#define __GLEE_GL_APPLE_vertex_array_range 1 +/* Constants */ +#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E +#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F +#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521 +#define GL_STORAGE_CACHED_APPLE 0x85BE +#define GL_STORAGE_SHARED_APPLE 0x85BF +#ifndef GLEE_H_DEFINED_glVertexArrayRangeAPPLE +#define GLEE_H_DEFINED_glVertexArrayRangeAPPLE + typedef void (APIENTRYP GLEEPFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLVERTEXARRAYRANGEAPPLEPROC GLeeFuncPtr_glVertexArrayRangeAPPLE; + #define glVertexArrayRangeAPPLE GLeeFuncPtr_glVertexArrayRangeAPPLE +#endif +#ifndef GLEE_H_DEFINED_glFlushVertexArrayRangeAPPLE +#define GLEE_H_DEFINED_glFlushVertexArrayRangeAPPLE + typedef void (APIENTRYP GLEEPFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC GLeeFuncPtr_glFlushVertexArrayRangeAPPLE; + #define glFlushVertexArrayRangeAPPLE GLeeFuncPtr_glFlushVertexArrayRangeAPPLE +#endif +#ifndef GLEE_H_DEFINED_glVertexArrayParameteriAPPLE +#define GLEE_H_DEFINED_glVertexArrayParameteriAPPLE + typedef void (APIENTRYP GLEEPFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLVERTEXARRAYPARAMETERIAPPLEPROC GLeeFuncPtr_glVertexArrayParameteriAPPLE; + #define glVertexArrayParameteriAPPLE GLeeFuncPtr_glVertexArrayParameteriAPPLE +#endif +#endif + +/* GL_APPLE_ycbcr_422 */ + +#ifndef GL_APPLE_ycbcr_422 +#define GL_APPLE_ycbcr_422 1 +#define __GLEE_GL_APPLE_ycbcr_422 1 +/* Constants */ +#define GL_YCBCR_422_APPLE 0x85B9 +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB +#endif + +/* GL_S3_s3tc */ + +#ifndef GL_S3_s3tc +#define GL_S3_s3tc 1 +#define __GLEE_GL_S3_s3tc 1 +/* Constants */ +#define GL_RGB_S3TC 0x83A0 +#define GL_RGB4_S3TC 0x83A1 +#define GL_RGBA_S3TC 0x83A2 +#define GL_RGBA4_S3TC 0x83A3 +#endif + +/* GL_ATI_draw_buffers */ + +#ifndef GL_ATI_draw_buffers +#define GL_ATI_draw_buffers 1 +#define __GLEE_GL_ATI_draw_buffers 1 +/* Constants */ +#define GL_MAX_DRAW_BUFFERS_ATI 0x8824 +#define GL_DRAW_BUFFER0_ATI 0x8825 +#define GL_DRAW_BUFFER1_ATI 0x8826 +#define GL_DRAW_BUFFER2_ATI 0x8827 +#define GL_DRAW_BUFFER3_ATI 0x8828 +#define GL_DRAW_BUFFER4_ATI 0x8829 +#define GL_DRAW_BUFFER5_ATI 0x882A +#define GL_DRAW_BUFFER6_ATI 0x882B +#define GL_DRAW_BUFFER7_ATI 0x882C +#define GL_DRAW_BUFFER8_ATI 0x882D +#define GL_DRAW_BUFFER9_ATI 0x882E +#define GL_DRAW_BUFFER10_ATI 0x882F +#define GL_DRAW_BUFFER11_ATI 0x8830 +#define GL_DRAW_BUFFER12_ATI 0x8831 +#define GL_DRAW_BUFFER13_ATI 0x8832 +#define GL_DRAW_BUFFER14_ATI 0x8833 +#define GL_DRAW_BUFFER15_ATI 0x8834 +#ifndef GLEE_H_DEFINED_glDrawBuffersATI +#define GLEE_H_DEFINED_glDrawBuffersATI + typedef void (APIENTRYP GLEEPFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum * bufs); + GLEE_EXTERN GLEEPFNGLDRAWBUFFERSATIPROC GLeeFuncPtr_glDrawBuffersATI; + #define glDrawBuffersATI GLeeFuncPtr_glDrawBuffersATI +#endif +#endif + +/* GL_ATI_pixel_format_float */ + +#ifndef GL_ATI_pixel_format_float +#define GL_ATI_pixel_format_float 1 +#define __GLEE_GL_ATI_pixel_format_float 1 +/* Constants */ +#define GL_TYPE_RGBA_FLOAT_ATI 0x8820 +#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835 +#endif + +/* GL_ATI_texture_env_combine3 */ + +#ifndef GL_ATI_texture_env_combine3 +#define GL_ATI_texture_env_combine3 1 +#define __GLEE_GL_ATI_texture_env_combine3 1 +/* Constants */ +#define GL_MODULATE_ADD_ATI 0x8744 +#define GL_MODULATE_SIGNED_ADD_ATI 0x8745 +#define GL_MODULATE_SUBTRACT_ATI 0x8746 +#endif + +/* GL_ATI_texture_float */ + +#ifndef GL_ATI_texture_float +#define GL_ATI_texture_float 1 +#define __GLEE_GL_ATI_texture_float 1 +/* Constants */ +#define GL_RGBA_FLOAT32_ATI 0x8814 +#define GL_RGB_FLOAT32_ATI 0x8815 +#define GL_ALPHA_FLOAT32_ATI 0x8816 +#define GL_INTENSITY_FLOAT32_ATI 0x8817 +#define GL_LUMINANCE_FLOAT32_ATI 0x8818 +#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819 +#define GL_RGBA_FLOAT16_ATI 0x881A +#define GL_RGB_FLOAT16_ATI 0x881B +#define GL_ALPHA_FLOAT16_ATI 0x881C +#define GL_INTENSITY_FLOAT16_ATI 0x881D +#define GL_LUMINANCE_FLOAT16_ATI 0x881E +#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F +#endif + +/* GL_NV_float_buffer */ + +#ifndef GL_NV_float_buffer +#define GL_NV_float_buffer 1 +#define __GLEE_GL_NV_float_buffer 1 +/* Constants */ +#define GL_FLOAT_R_NV 0x8880 +#define GL_FLOAT_RG_NV 0x8881 +#define GL_FLOAT_RGB_NV 0x8882 +#define GL_FLOAT_RGBA_NV 0x8883 +#define GL_FLOAT_R16_NV 0x8884 +#define GL_FLOAT_R32_NV 0x8885 +#define GL_FLOAT_RG16_NV 0x8886 +#define GL_FLOAT_RG32_NV 0x8887 +#define GL_FLOAT_RGB16_NV 0x8888 +#define GL_FLOAT_RGB32_NV 0x8889 +#define GL_FLOAT_RGBA16_NV 0x888A +#define GL_FLOAT_RGBA32_NV 0x888B +#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C +#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D +#define GL_FLOAT_RGBA_MODE_NV 0x888E +#endif + +/* GL_NV_fragment_program */ + +#ifndef GL_NV_fragment_program +#define GL_NV_fragment_program 1 +#define __GLEE_GL_NV_fragment_program 1 +/* Constants */ +#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868 +#define GL_FRAGMENT_PROGRAM_NV 0x8870 +#define GL_MAX_TEXTURE_COORDS_NV 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872 +#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873 +#define GL_PROGRAM_ERROR_STRING_NV 0x8874 +#ifndef GLEE_H_DEFINED_glProgramNamedParameter4fNV +#define GLEE_H_DEFINED_glProgramNamedParameter4fNV + typedef void (APIENTRYP GLEEPFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte * name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + GLEE_EXTERN GLEEPFNGLPROGRAMNAMEDPARAMETER4FNVPROC GLeeFuncPtr_glProgramNamedParameter4fNV; + #define glProgramNamedParameter4fNV GLeeFuncPtr_glProgramNamedParameter4fNV +#endif +#ifndef GLEE_H_DEFINED_glProgramNamedParameter4dNV +#define GLEE_H_DEFINED_glProgramNamedParameter4dNV + typedef void (APIENTRYP GLEEPFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte * name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + GLEE_EXTERN GLEEPFNGLPROGRAMNAMEDPARAMETER4DNVPROC GLeeFuncPtr_glProgramNamedParameter4dNV; + #define glProgramNamedParameter4dNV GLeeFuncPtr_glProgramNamedParameter4dNV +#endif +#ifndef GLEE_H_DEFINED_glProgramNamedParameter4fvNV +#define GLEE_H_DEFINED_glProgramNamedParameter4fvNV + typedef void (APIENTRYP GLEEPFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte * name, const GLfloat * v); + GLEE_EXTERN GLEEPFNGLPROGRAMNAMEDPARAMETER4FVNVPROC GLeeFuncPtr_glProgramNamedParameter4fvNV; + #define glProgramNamedParameter4fvNV GLeeFuncPtr_glProgramNamedParameter4fvNV +#endif +#ifndef GLEE_H_DEFINED_glProgramNamedParameter4dvNV +#define GLEE_H_DEFINED_glProgramNamedParameter4dvNV + typedef void (APIENTRYP GLEEPFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte * name, const GLdouble * v); + GLEE_EXTERN GLEEPFNGLPROGRAMNAMEDPARAMETER4DVNVPROC GLeeFuncPtr_glProgramNamedParameter4dvNV; + #define glProgramNamedParameter4dvNV GLeeFuncPtr_glProgramNamedParameter4dvNV +#endif +#ifndef GLEE_H_DEFINED_glGetProgramNamedParameterfvNV +#define GLEE_H_DEFINED_glGetProgramNamedParameterfvNV + typedef void (APIENTRYP GLEEPFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte * name, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC GLeeFuncPtr_glGetProgramNamedParameterfvNV; + #define glGetProgramNamedParameterfvNV GLeeFuncPtr_glGetProgramNamedParameterfvNV +#endif +#ifndef GLEE_H_DEFINED_glGetProgramNamedParameterdvNV +#define GLEE_H_DEFINED_glGetProgramNamedParameterdvNV + typedef void (APIENTRYP GLEEPFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte * name, GLdouble * params); + GLEE_EXTERN GLEEPFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC GLeeFuncPtr_glGetProgramNamedParameterdvNV; + #define glGetProgramNamedParameterdvNV GLeeFuncPtr_glGetProgramNamedParameterdvNV +#endif +#endif + +/* GL_NV_half_float */ + +#ifndef GL_NV_half_float +#define GL_NV_half_float 1 +#define __GLEE_GL_NV_half_float 1 +/* Constants */ +#define GL_HALF_FLOAT_NV 0x140B +#ifndef GLEE_H_DEFINED_glVertex2hNV +#define GLEE_H_DEFINED_glVertex2hNV + typedef void (APIENTRYP GLEEPFNGLVERTEX2HNVPROC) (GLhalfNV x, GLhalfNV y); + GLEE_EXTERN GLEEPFNGLVERTEX2HNVPROC GLeeFuncPtr_glVertex2hNV; + #define glVertex2hNV GLeeFuncPtr_glVertex2hNV +#endif +#ifndef GLEE_H_DEFINED_glVertex2hvNV +#define GLEE_H_DEFINED_glVertex2hvNV + typedef void (APIENTRYP GLEEPFNGLVERTEX2HVNVPROC) (const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLVERTEX2HVNVPROC GLeeFuncPtr_glVertex2hvNV; + #define glVertex2hvNV GLeeFuncPtr_glVertex2hvNV +#endif +#ifndef GLEE_H_DEFINED_glVertex3hNV +#define GLEE_H_DEFINED_glVertex3hNV + typedef void (APIENTRYP GLEEPFNGLVERTEX3HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z); + GLEE_EXTERN GLEEPFNGLVERTEX3HNVPROC GLeeFuncPtr_glVertex3hNV; + #define glVertex3hNV GLeeFuncPtr_glVertex3hNV +#endif +#ifndef GLEE_H_DEFINED_glVertex3hvNV +#define GLEE_H_DEFINED_glVertex3hvNV + typedef void (APIENTRYP GLEEPFNGLVERTEX3HVNVPROC) (const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLVERTEX3HVNVPROC GLeeFuncPtr_glVertex3hvNV; + #define glVertex3hvNV GLeeFuncPtr_glVertex3hvNV +#endif +#ifndef GLEE_H_DEFINED_glVertex4hNV +#define GLEE_H_DEFINED_glVertex4hNV + typedef void (APIENTRYP GLEEPFNGLVERTEX4HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); + GLEE_EXTERN GLEEPFNGLVERTEX4HNVPROC GLeeFuncPtr_glVertex4hNV; + #define glVertex4hNV GLeeFuncPtr_glVertex4hNV +#endif +#ifndef GLEE_H_DEFINED_glVertex4hvNV +#define GLEE_H_DEFINED_glVertex4hvNV + typedef void (APIENTRYP GLEEPFNGLVERTEX4HVNVPROC) (const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLVERTEX4HVNVPROC GLeeFuncPtr_glVertex4hvNV; + #define glVertex4hvNV GLeeFuncPtr_glVertex4hvNV +#endif +#ifndef GLEE_H_DEFINED_glNormal3hNV +#define GLEE_H_DEFINED_glNormal3hNV + typedef void (APIENTRYP GLEEPFNGLNORMAL3HNVPROC) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz); + GLEE_EXTERN GLEEPFNGLNORMAL3HNVPROC GLeeFuncPtr_glNormal3hNV; + #define glNormal3hNV GLeeFuncPtr_glNormal3hNV +#endif +#ifndef GLEE_H_DEFINED_glNormal3hvNV +#define GLEE_H_DEFINED_glNormal3hvNV + typedef void (APIENTRYP GLEEPFNGLNORMAL3HVNVPROC) (const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLNORMAL3HVNVPROC GLeeFuncPtr_glNormal3hvNV; + #define glNormal3hvNV GLeeFuncPtr_glNormal3hvNV +#endif +#ifndef GLEE_H_DEFINED_glColor3hNV +#define GLEE_H_DEFINED_glColor3hNV + typedef void (APIENTRYP GLEEPFNGLCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); + GLEE_EXTERN GLEEPFNGLCOLOR3HNVPROC GLeeFuncPtr_glColor3hNV; + #define glColor3hNV GLeeFuncPtr_glColor3hNV +#endif +#ifndef GLEE_H_DEFINED_glColor3hvNV +#define GLEE_H_DEFINED_glColor3hvNV + typedef void (APIENTRYP GLEEPFNGLCOLOR3HVNVPROC) (const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLCOLOR3HVNVPROC GLeeFuncPtr_glColor3hvNV; + #define glColor3hvNV GLeeFuncPtr_glColor3hvNV +#endif +#ifndef GLEE_H_DEFINED_glColor4hNV +#define GLEE_H_DEFINED_glColor4hNV + typedef void (APIENTRYP GLEEPFNGLCOLOR4HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha); + GLEE_EXTERN GLEEPFNGLCOLOR4HNVPROC GLeeFuncPtr_glColor4hNV; + #define glColor4hNV GLeeFuncPtr_glColor4hNV +#endif +#ifndef GLEE_H_DEFINED_glColor4hvNV +#define GLEE_H_DEFINED_glColor4hvNV + typedef void (APIENTRYP GLEEPFNGLCOLOR4HVNVPROC) (const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLCOLOR4HVNVPROC GLeeFuncPtr_glColor4hvNV; + #define glColor4hvNV GLeeFuncPtr_glColor4hvNV +#endif +#ifndef GLEE_H_DEFINED_glTexCoord1hNV +#define GLEE_H_DEFINED_glTexCoord1hNV + typedef void (APIENTRYP GLEEPFNGLTEXCOORD1HNVPROC) (GLhalfNV s); + GLEE_EXTERN GLEEPFNGLTEXCOORD1HNVPROC GLeeFuncPtr_glTexCoord1hNV; + #define glTexCoord1hNV GLeeFuncPtr_glTexCoord1hNV +#endif +#ifndef GLEE_H_DEFINED_glTexCoord1hvNV +#define GLEE_H_DEFINED_glTexCoord1hvNV + typedef void (APIENTRYP GLEEPFNGLTEXCOORD1HVNVPROC) (const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLTEXCOORD1HVNVPROC GLeeFuncPtr_glTexCoord1hvNV; + #define glTexCoord1hvNV GLeeFuncPtr_glTexCoord1hvNV +#endif +#ifndef GLEE_H_DEFINED_glTexCoord2hNV +#define GLEE_H_DEFINED_glTexCoord2hNV + typedef void (APIENTRYP GLEEPFNGLTEXCOORD2HNVPROC) (GLhalfNV s, GLhalfNV t); + GLEE_EXTERN GLEEPFNGLTEXCOORD2HNVPROC GLeeFuncPtr_glTexCoord2hNV; + #define glTexCoord2hNV GLeeFuncPtr_glTexCoord2hNV +#endif +#ifndef GLEE_H_DEFINED_glTexCoord2hvNV +#define GLEE_H_DEFINED_glTexCoord2hvNV + typedef void (APIENTRYP GLEEPFNGLTEXCOORD2HVNVPROC) (const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLTEXCOORD2HVNVPROC GLeeFuncPtr_glTexCoord2hvNV; + #define glTexCoord2hvNV GLeeFuncPtr_glTexCoord2hvNV +#endif +#ifndef GLEE_H_DEFINED_glTexCoord3hNV +#define GLEE_H_DEFINED_glTexCoord3hNV + typedef void (APIENTRYP GLEEPFNGLTEXCOORD3HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r); + GLEE_EXTERN GLEEPFNGLTEXCOORD3HNVPROC GLeeFuncPtr_glTexCoord3hNV; + #define glTexCoord3hNV GLeeFuncPtr_glTexCoord3hNV +#endif +#ifndef GLEE_H_DEFINED_glTexCoord3hvNV +#define GLEE_H_DEFINED_glTexCoord3hvNV + typedef void (APIENTRYP GLEEPFNGLTEXCOORD3HVNVPROC) (const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLTEXCOORD3HVNVPROC GLeeFuncPtr_glTexCoord3hvNV; + #define glTexCoord3hvNV GLeeFuncPtr_glTexCoord3hvNV +#endif +#ifndef GLEE_H_DEFINED_glTexCoord4hNV +#define GLEE_H_DEFINED_glTexCoord4hNV + typedef void (APIENTRYP GLEEPFNGLTEXCOORD4HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); + GLEE_EXTERN GLEEPFNGLTEXCOORD4HNVPROC GLeeFuncPtr_glTexCoord4hNV; + #define glTexCoord4hNV GLeeFuncPtr_glTexCoord4hNV +#endif +#ifndef GLEE_H_DEFINED_glTexCoord4hvNV +#define GLEE_H_DEFINED_glTexCoord4hvNV + typedef void (APIENTRYP GLEEPFNGLTEXCOORD4HVNVPROC) (const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLTEXCOORD4HVNVPROC GLeeFuncPtr_glTexCoord4hvNV; + #define glTexCoord4hvNV GLeeFuncPtr_glTexCoord4hvNV +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1hNV +#define GLEE_H_DEFINED_glMultiTexCoord1hNV + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalfNV s); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1HNVPROC GLeeFuncPtr_glMultiTexCoord1hNV; + #define glMultiTexCoord1hNV GLeeFuncPtr_glMultiTexCoord1hNV +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord1hvNV +#define GLEE_H_DEFINED_glMultiTexCoord1hvNV + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD1HVNVPROC GLeeFuncPtr_glMultiTexCoord1hvNV; + #define glMultiTexCoord1hvNV GLeeFuncPtr_glMultiTexCoord1hvNV +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2hNV +#define GLEE_H_DEFINED_glMultiTexCoord2hNV + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2HNVPROC GLeeFuncPtr_glMultiTexCoord2hNV; + #define glMultiTexCoord2hNV GLeeFuncPtr_glMultiTexCoord2hNV +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord2hvNV +#define GLEE_H_DEFINED_glMultiTexCoord2hvNV + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD2HVNVPROC GLeeFuncPtr_glMultiTexCoord2hvNV; + #define glMultiTexCoord2hvNV GLeeFuncPtr_glMultiTexCoord2hvNV +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3hNV +#define GLEE_H_DEFINED_glMultiTexCoord3hNV + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3HNVPROC GLeeFuncPtr_glMultiTexCoord3hNV; + #define glMultiTexCoord3hNV GLeeFuncPtr_glMultiTexCoord3hNV +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord3hvNV +#define GLEE_H_DEFINED_glMultiTexCoord3hvNV + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD3HVNVPROC GLeeFuncPtr_glMultiTexCoord3hvNV; + #define glMultiTexCoord3hvNV GLeeFuncPtr_glMultiTexCoord3hvNV +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4hNV +#define GLEE_H_DEFINED_glMultiTexCoord4hNV + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4HNVPROC GLeeFuncPtr_glMultiTexCoord4hNV; + #define glMultiTexCoord4hNV GLeeFuncPtr_glMultiTexCoord4hNV +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoord4hvNV +#define GLEE_H_DEFINED_glMultiTexCoord4hvNV + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORD4HVNVPROC GLeeFuncPtr_glMultiTexCoord4hvNV; + #define glMultiTexCoord4hvNV GLeeFuncPtr_glMultiTexCoord4hvNV +#endif +#ifndef GLEE_H_DEFINED_glFogCoordhNV +#define GLEE_H_DEFINED_glFogCoordhNV + typedef void (APIENTRYP GLEEPFNGLFOGCOORDHNVPROC) (GLhalfNV fog); + GLEE_EXTERN GLEEPFNGLFOGCOORDHNVPROC GLeeFuncPtr_glFogCoordhNV; + #define glFogCoordhNV GLeeFuncPtr_glFogCoordhNV +#endif +#ifndef GLEE_H_DEFINED_glFogCoordhvNV +#define GLEE_H_DEFINED_glFogCoordhvNV + typedef void (APIENTRYP GLEEPFNGLFOGCOORDHVNVPROC) (const GLhalfNV * fog); + GLEE_EXTERN GLEEPFNGLFOGCOORDHVNVPROC GLeeFuncPtr_glFogCoordhvNV; + #define glFogCoordhvNV GLeeFuncPtr_glFogCoordhvNV +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3hNV +#define GLEE_H_DEFINED_glSecondaryColor3hNV + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3HNVPROC GLeeFuncPtr_glSecondaryColor3hNV; + #define glSecondaryColor3hNV GLeeFuncPtr_glSecondaryColor3hNV +#endif +#ifndef GLEE_H_DEFINED_glSecondaryColor3hvNV +#define GLEE_H_DEFINED_glSecondaryColor3hvNV + typedef void (APIENTRYP GLEEPFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLSECONDARYCOLOR3HVNVPROC GLeeFuncPtr_glSecondaryColor3hvNV; + #define glSecondaryColor3hvNV GLeeFuncPtr_glSecondaryColor3hvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexWeighthNV +#define GLEE_H_DEFINED_glVertexWeighthNV + typedef void (APIENTRYP GLEEPFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight); + GLEE_EXTERN GLEEPFNGLVERTEXWEIGHTHNVPROC GLeeFuncPtr_glVertexWeighthNV; + #define glVertexWeighthNV GLeeFuncPtr_glVertexWeighthNV +#endif +#ifndef GLEE_H_DEFINED_glVertexWeighthvNV +#define GLEE_H_DEFINED_glVertexWeighthvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV * weight); + GLEE_EXTERN GLEEPFNGLVERTEXWEIGHTHVNVPROC GLeeFuncPtr_glVertexWeighthvNV; + #define glVertexWeighthvNV GLeeFuncPtr_glVertexWeighthvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1hNV +#define GLEE_H_DEFINED_glVertexAttrib1hNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1HNVPROC GLeeFuncPtr_glVertexAttrib1hNV; + #define glVertexAttrib1hNV GLeeFuncPtr_glVertexAttrib1hNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib1hvNV +#define GLEE_H_DEFINED_glVertexAttrib1hvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB1HVNVPROC GLeeFuncPtr_glVertexAttrib1hvNV; + #define glVertexAttrib1hvNV GLeeFuncPtr_glVertexAttrib1hvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2hNV +#define GLEE_H_DEFINED_glVertexAttrib2hNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2HNVPROC GLeeFuncPtr_glVertexAttrib2hNV; + #define glVertexAttrib2hNV GLeeFuncPtr_glVertexAttrib2hNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib2hvNV +#define GLEE_H_DEFINED_glVertexAttrib2hvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB2HVNVPROC GLeeFuncPtr_glVertexAttrib2hvNV; + #define glVertexAttrib2hvNV GLeeFuncPtr_glVertexAttrib2hvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3hNV +#define GLEE_H_DEFINED_glVertexAttrib3hNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3HNVPROC GLeeFuncPtr_glVertexAttrib3hNV; + #define glVertexAttrib3hNV GLeeFuncPtr_glVertexAttrib3hNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib3hvNV +#define GLEE_H_DEFINED_glVertexAttrib3hvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB3HVNVPROC GLeeFuncPtr_glVertexAttrib3hvNV; + #define glVertexAttrib3hvNV GLeeFuncPtr_glVertexAttrib3hvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4hNV +#define GLEE_H_DEFINED_glVertexAttrib4hNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4HNVPROC GLeeFuncPtr_glVertexAttrib4hNV; + #define glVertexAttrib4hNV GLeeFuncPtr_glVertexAttrib4hNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttrib4hvNV +#define GLEE_H_DEFINED_glVertexAttrib4hvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIB4HVNVPROC GLeeFuncPtr_glVertexAttrib4hvNV; + #define glVertexAttrib4hvNV GLeeFuncPtr_glVertexAttrib4hvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs1hvNV +#define GLEE_H_DEFINED_glVertexAttribs1hvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS1HVNVPROC GLeeFuncPtr_glVertexAttribs1hvNV; + #define glVertexAttribs1hvNV GLeeFuncPtr_glVertexAttribs1hvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs2hvNV +#define GLEE_H_DEFINED_glVertexAttribs2hvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS2HVNVPROC GLeeFuncPtr_glVertexAttribs2hvNV; + #define glVertexAttribs2hvNV GLeeFuncPtr_glVertexAttribs2hvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs3hvNV +#define GLEE_H_DEFINED_glVertexAttribs3hvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS3HVNVPROC GLeeFuncPtr_glVertexAttribs3hvNV; + #define glVertexAttribs3hvNV GLeeFuncPtr_glVertexAttribs3hvNV +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribs4hvNV +#define GLEE_H_DEFINED_glVertexAttribs4hvNV + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBS4HVNVPROC GLeeFuncPtr_glVertexAttribs4hvNV; + #define glVertexAttribs4hvNV GLeeFuncPtr_glVertexAttribs4hvNV +#endif +#endif + +/* GL_NV_pixel_data_range */ + +#ifndef GL_NV_pixel_data_range +#define GL_NV_pixel_data_range 1 +#define __GLEE_GL_NV_pixel_data_range 1 +/* Constants */ +#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878 +#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879 +#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A +#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B +#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C +#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D +#ifndef GLEE_H_DEFINED_glPixelDataRangeNV +#define GLEE_H_DEFINED_glPixelDataRangeNV + typedef void (APIENTRYP GLEEPFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLPIXELDATARANGENVPROC GLeeFuncPtr_glPixelDataRangeNV; + #define glPixelDataRangeNV GLeeFuncPtr_glPixelDataRangeNV +#endif +#ifndef GLEE_H_DEFINED_glFlushPixelDataRangeNV +#define GLEE_H_DEFINED_glFlushPixelDataRangeNV + typedef void (APIENTRYP GLEEPFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target); + GLEE_EXTERN GLEEPFNGLFLUSHPIXELDATARANGENVPROC GLeeFuncPtr_glFlushPixelDataRangeNV; + #define glFlushPixelDataRangeNV GLeeFuncPtr_glFlushPixelDataRangeNV +#endif +#endif + +/* GL_NV_primitive_restart */ + +#ifndef GL_NV_primitive_restart +#define GL_NV_primitive_restart 1 +#define __GLEE_GL_NV_primitive_restart 1 +/* Constants */ +#define GL_PRIMITIVE_RESTART_NV 0x8558 +#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559 +#ifndef GLEE_H_DEFINED_glPrimitiveRestartNV +#define GLEE_H_DEFINED_glPrimitiveRestartNV + typedef void (APIENTRYP GLEEPFNGLPRIMITIVERESTARTNVPROC) (); + GLEE_EXTERN GLEEPFNGLPRIMITIVERESTARTNVPROC GLeeFuncPtr_glPrimitiveRestartNV; + #define glPrimitiveRestartNV GLeeFuncPtr_glPrimitiveRestartNV +#endif +#ifndef GLEE_H_DEFINED_glPrimitiveRestartIndexNV +#define GLEE_H_DEFINED_glPrimitiveRestartIndexNV + typedef void (APIENTRYP GLEEPFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index); + GLEE_EXTERN GLEEPFNGLPRIMITIVERESTARTINDEXNVPROC GLeeFuncPtr_glPrimitiveRestartIndexNV; + #define glPrimitiveRestartIndexNV GLeeFuncPtr_glPrimitiveRestartIndexNV +#endif +#endif + +/* GL_NV_texture_expand_normal */ + +#ifndef GL_NV_texture_expand_normal +#define GL_NV_texture_expand_normal 1 +#define __GLEE_GL_NV_texture_expand_normal 1 +/* Constants */ +#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F +#endif + +/* GL_NV_vertex_program2 */ + +#ifndef GL_NV_vertex_program2 +#define GL_NV_vertex_program2 1 +#define __GLEE_GL_NV_vertex_program2 1 +/* Constants */ +#endif + +/* GL_ATI_map_object_buffer */ + +#ifndef GL_ATI_map_object_buffer +#define GL_ATI_map_object_buffer 1 +#define __GLEE_GL_ATI_map_object_buffer 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glMapObjectBufferATI +#define GLEE_H_DEFINED_glMapObjectBufferATI + typedef GLvoid* (APIENTRYP GLEEPFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer); + GLEE_EXTERN GLEEPFNGLMAPOBJECTBUFFERATIPROC GLeeFuncPtr_glMapObjectBufferATI; + #define glMapObjectBufferATI GLeeFuncPtr_glMapObjectBufferATI +#endif +#ifndef GLEE_H_DEFINED_glUnmapObjectBufferATI +#define GLEE_H_DEFINED_glUnmapObjectBufferATI + typedef void (APIENTRYP GLEEPFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer); + GLEE_EXTERN GLEEPFNGLUNMAPOBJECTBUFFERATIPROC GLeeFuncPtr_glUnmapObjectBufferATI; + #define glUnmapObjectBufferATI GLeeFuncPtr_glUnmapObjectBufferATI +#endif +#endif + +/* GL_ATI_separate_stencil */ + +#ifndef GL_ATI_separate_stencil +#define GL_ATI_separate_stencil 1 +#define __GLEE_GL_ATI_separate_stencil 1 +/* Constants */ +#define GL_STENCIL_BACK_FUNC_ATI 0x8800 +#define GL_STENCIL_BACK_FAIL_ATI 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803 +#ifndef GLEE_H_DEFINED_glStencilOpSeparateATI +#define GLEE_H_DEFINED_glStencilOpSeparateATI + typedef void (APIENTRYP GLEEPFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); + GLEE_EXTERN GLEEPFNGLSTENCILOPSEPARATEATIPROC GLeeFuncPtr_glStencilOpSeparateATI; + #define glStencilOpSeparateATI GLeeFuncPtr_glStencilOpSeparateATI +#endif +#ifndef GLEE_H_DEFINED_glStencilFuncSeparateATI +#define GLEE_H_DEFINED_glStencilFuncSeparateATI + typedef void (APIENTRYP GLEEPFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); + GLEE_EXTERN GLEEPFNGLSTENCILFUNCSEPARATEATIPROC GLeeFuncPtr_glStencilFuncSeparateATI; + #define glStencilFuncSeparateATI GLeeFuncPtr_glStencilFuncSeparateATI +#endif +#endif + +/* GL_ATI_vertex_attrib_array_object */ + +#ifndef GL_ATI_vertex_attrib_array_object +#define GL_ATI_vertex_attrib_array_object 1 +#define __GLEE_GL_ATI_vertex_attrib_array_object 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glVertexAttribArrayObjectATI +#define GLEE_H_DEFINED_glVertexAttribArrayObjectATI + typedef void (APIENTRYP GLEEPFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBARRAYOBJECTATIPROC GLeeFuncPtr_glVertexAttribArrayObjectATI; + #define glVertexAttribArrayObjectATI GLeeFuncPtr_glVertexAttribArrayObjectATI +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribArrayObjectfvATI +#define GLEE_H_DEFINED_glGetVertexAttribArrayObjectfvATI + typedef void (APIENTRYP GLEEPFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC GLeeFuncPtr_glGetVertexAttribArrayObjectfvATI; + #define glGetVertexAttribArrayObjectfvATI GLeeFuncPtr_glGetVertexAttribArrayObjectfvATI +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribArrayObjectivATI +#define GLEE_H_DEFINED_glGetVertexAttribArrayObjectivATI + typedef void (APIENTRYP GLEEPFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC GLeeFuncPtr_glGetVertexAttribArrayObjectivATI; + #define glGetVertexAttribArrayObjectivATI GLeeFuncPtr_glGetVertexAttribArrayObjectivATI +#endif +#endif + +/* GL_OES_read_format */ + +#ifndef GL_OES_read_format +#define GL_OES_read_format 1 +#define __GLEE_GL_OES_read_format 1 +/* Constants */ +#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B +#endif + +/* GL_EXT_depth_bounds_test */ + +#ifndef GL_EXT_depth_bounds_test +#define GL_EXT_depth_bounds_test 1 +#define __GLEE_GL_EXT_depth_bounds_test 1 +/* Constants */ +#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890 +#define GL_DEPTH_BOUNDS_EXT 0x8891 +#ifndef GLEE_H_DEFINED_glDepthBoundsEXT +#define GLEE_H_DEFINED_glDepthBoundsEXT + typedef void (APIENTRYP GLEEPFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax); + GLEE_EXTERN GLEEPFNGLDEPTHBOUNDSEXTPROC GLeeFuncPtr_glDepthBoundsEXT; + #define glDepthBoundsEXT GLeeFuncPtr_glDepthBoundsEXT +#endif +#endif + +/* GL_EXT_texture_mirror_clamp */ + +#ifndef GL_EXT_texture_mirror_clamp +#define GL_EXT_texture_mirror_clamp 1 +#define __GLEE_GL_EXT_texture_mirror_clamp 1 +/* Constants */ +#define GL_MIRROR_CLAMP_EXT 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743 +#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912 +#endif + +/* GL_EXT_blend_equation_separate */ + +#ifndef GL_EXT_blend_equation_separate +#define GL_EXT_blend_equation_separate 1 +#define __GLEE_GL_EXT_blend_equation_separate 1 +/* Constants */ +#define GL_BLEND_EQUATION_RGB_EXT GL_BLEND_EQUATION +#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D +#ifndef GLEE_H_DEFINED_glBlendEquationSeparateEXT +#define GLEE_H_DEFINED_glBlendEquationSeparateEXT + typedef void (APIENTRYP GLEEPFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha); + GLEE_EXTERN GLEEPFNGLBLENDEQUATIONSEPARATEEXTPROC GLeeFuncPtr_glBlendEquationSeparateEXT; + #define glBlendEquationSeparateEXT GLeeFuncPtr_glBlendEquationSeparateEXT +#endif +#endif + +/* GL_MESA_pack_invert */ + +#ifndef GL_MESA_pack_invert +#define GL_MESA_pack_invert 1 +#define __GLEE_GL_MESA_pack_invert 1 +/* Constants */ +#define GL_PACK_INVERT_MESA 0x8758 +#endif + +/* GL_MESA_ycbcr_texture */ + +#ifndef GL_MESA_ycbcr_texture +#define GL_MESA_ycbcr_texture 1 +#define __GLEE_GL_MESA_ycbcr_texture 1 +/* Constants */ +#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB +#define GL_YCBCR_MESA 0x8757 +#endif + +/* GL_EXT_pixel_buffer_object */ + +#ifndef GL_EXT_pixel_buffer_object +#define GL_EXT_pixel_buffer_object 1 +#define __GLEE_GL_EXT_pixel_buffer_object 1 +/* Constants */ +#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF +#endif + +/* GL_NV_fragment_program_option */ + +#ifndef GL_NV_fragment_program_option +#define GL_NV_fragment_program_option 1 +#define __GLEE_GL_NV_fragment_program_option 1 +/* Constants */ +#endif + +/* GL_NV_fragment_program2 */ + +#ifndef GL_NV_fragment_program2 +#define GL_NV_fragment_program2 1 +#define __GLEE_GL_NV_fragment_program2 1 +/* Constants */ +#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 +#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 +#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6 +#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7 +#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8 +#endif + +/* GL_NV_vertex_program2_option */ + +#ifndef GL_NV_vertex_program2_option +#define GL_NV_vertex_program2_option 1 +#define __GLEE_GL_NV_vertex_program2_option 1 +/* Constants */ +#endif + +/* GL_NV_vertex_program3 */ + +#ifndef GL_NV_vertex_program3 +#define GL_NV_vertex_program3 1 +#define __GLEE_GL_NV_vertex_program3 1 +/* Constants */ +#endif + +/* GL_EXT_framebuffer_object */ + +#ifndef GL_EXT_framebuffer_object +#define GL_EXT_framebuffer_object 1 +#define __GLEE_GL_EXT_framebuffer_object 1 +/* Constants */ +#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 +#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 +#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 +#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF +#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 +#define GL_STENCIL_ATTACHMENT_EXT 0x8D20 +#define GL_FRAMEBUFFER_EXT 0x8D40 +#define GL_RENDERBUFFER_EXT 0x8D41 +#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 +#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 +#define GL_STENCIL_INDEX1_EXT 0x8D46 +#define GL_STENCIL_INDEX4_EXT 0x8D47 +#define GL_STENCIL_INDEX8_EXT 0x8D48 +#define GL_STENCIL_INDEX16_EXT 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55 +#ifndef GLEE_H_DEFINED_glIsRenderbufferEXT +#define GLEE_H_DEFINED_glIsRenderbufferEXT + typedef GLboolean (APIENTRYP GLEEPFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer); + GLEE_EXTERN GLEEPFNGLISRENDERBUFFEREXTPROC GLeeFuncPtr_glIsRenderbufferEXT; + #define glIsRenderbufferEXT GLeeFuncPtr_glIsRenderbufferEXT +#endif +#ifndef GLEE_H_DEFINED_glBindRenderbufferEXT +#define GLEE_H_DEFINED_glBindRenderbufferEXT + typedef void (APIENTRYP GLEEPFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer); + GLEE_EXTERN GLEEPFNGLBINDRENDERBUFFEREXTPROC GLeeFuncPtr_glBindRenderbufferEXT; + #define glBindRenderbufferEXT GLeeFuncPtr_glBindRenderbufferEXT +#endif +#ifndef GLEE_H_DEFINED_glDeleteRenderbuffersEXT +#define GLEE_H_DEFINED_glDeleteRenderbuffersEXT + typedef void (APIENTRYP GLEEPFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint * renderbuffers); + GLEE_EXTERN GLEEPFNGLDELETERENDERBUFFERSEXTPROC GLeeFuncPtr_glDeleteRenderbuffersEXT; + #define glDeleteRenderbuffersEXT GLeeFuncPtr_glDeleteRenderbuffersEXT +#endif +#ifndef GLEE_H_DEFINED_glGenRenderbuffersEXT +#define GLEE_H_DEFINED_glGenRenderbuffersEXT + typedef void (APIENTRYP GLEEPFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint * renderbuffers); + GLEE_EXTERN GLEEPFNGLGENRENDERBUFFERSEXTPROC GLeeFuncPtr_glGenRenderbuffersEXT; + #define glGenRenderbuffersEXT GLeeFuncPtr_glGenRenderbuffersEXT +#endif +#ifndef GLEE_H_DEFINED_glRenderbufferStorageEXT +#define GLEE_H_DEFINED_glRenderbufferStorageEXT + typedef void (APIENTRYP GLEEPFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLRENDERBUFFERSTORAGEEXTPROC GLeeFuncPtr_glRenderbufferStorageEXT; + #define glRenderbufferStorageEXT GLeeFuncPtr_glRenderbufferStorageEXT +#endif +#ifndef GLEE_H_DEFINED_glGetRenderbufferParameterivEXT +#define GLEE_H_DEFINED_glGetRenderbufferParameterivEXT + typedef void (APIENTRYP GLEEPFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETRENDERBUFFERPARAMETERIVEXTPROC GLeeFuncPtr_glGetRenderbufferParameterivEXT; + #define glGetRenderbufferParameterivEXT GLeeFuncPtr_glGetRenderbufferParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glIsFramebufferEXT +#define GLEE_H_DEFINED_glIsFramebufferEXT + typedef GLboolean (APIENTRYP GLEEPFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer); + GLEE_EXTERN GLEEPFNGLISFRAMEBUFFEREXTPROC GLeeFuncPtr_glIsFramebufferEXT; + #define glIsFramebufferEXT GLeeFuncPtr_glIsFramebufferEXT +#endif +#ifndef GLEE_H_DEFINED_glBindFramebufferEXT +#define GLEE_H_DEFINED_glBindFramebufferEXT + typedef void (APIENTRYP GLEEPFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer); + GLEE_EXTERN GLEEPFNGLBINDFRAMEBUFFEREXTPROC GLeeFuncPtr_glBindFramebufferEXT; + #define glBindFramebufferEXT GLeeFuncPtr_glBindFramebufferEXT +#endif +#ifndef GLEE_H_DEFINED_glDeleteFramebuffersEXT +#define GLEE_H_DEFINED_glDeleteFramebuffersEXT + typedef void (APIENTRYP GLEEPFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint * framebuffers); + GLEE_EXTERN GLEEPFNGLDELETEFRAMEBUFFERSEXTPROC GLeeFuncPtr_glDeleteFramebuffersEXT; + #define glDeleteFramebuffersEXT GLeeFuncPtr_glDeleteFramebuffersEXT +#endif +#ifndef GLEE_H_DEFINED_glGenFramebuffersEXT +#define GLEE_H_DEFINED_glGenFramebuffersEXT + typedef void (APIENTRYP GLEEPFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint * framebuffers); + GLEE_EXTERN GLEEPFNGLGENFRAMEBUFFERSEXTPROC GLeeFuncPtr_glGenFramebuffersEXT; + #define glGenFramebuffersEXT GLeeFuncPtr_glGenFramebuffersEXT +#endif +#ifndef GLEE_H_DEFINED_glCheckFramebufferStatusEXT +#define GLEE_H_DEFINED_glCheckFramebufferStatusEXT + typedef GLenum (APIENTRYP GLEEPFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target); + GLEE_EXTERN GLEEPFNGLCHECKFRAMEBUFFERSTATUSEXTPROC GLeeFuncPtr_glCheckFramebufferStatusEXT; + #define glCheckFramebufferStatusEXT GLeeFuncPtr_glCheckFramebufferStatusEXT +#endif +#ifndef GLEE_H_DEFINED_glFramebufferTexture1DEXT +#define GLEE_H_DEFINED_glFramebufferTexture1DEXT + typedef void (APIENTRYP GLEEPFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERTEXTURE1DEXTPROC GLeeFuncPtr_glFramebufferTexture1DEXT; + #define glFramebufferTexture1DEXT GLeeFuncPtr_glFramebufferTexture1DEXT +#endif +#ifndef GLEE_H_DEFINED_glFramebufferTexture2DEXT +#define GLEE_H_DEFINED_glFramebufferTexture2DEXT + typedef void (APIENTRYP GLEEPFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERTEXTURE2DEXTPROC GLeeFuncPtr_glFramebufferTexture2DEXT; + #define glFramebufferTexture2DEXT GLeeFuncPtr_glFramebufferTexture2DEXT +#endif +#ifndef GLEE_H_DEFINED_glFramebufferTexture3DEXT +#define GLEE_H_DEFINED_glFramebufferTexture3DEXT + typedef void (APIENTRYP GLEEPFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERTEXTURE3DEXTPROC GLeeFuncPtr_glFramebufferTexture3DEXT; + #define glFramebufferTexture3DEXT GLeeFuncPtr_glFramebufferTexture3DEXT +#endif +#ifndef GLEE_H_DEFINED_glFramebufferRenderbufferEXT +#define GLEE_H_DEFINED_glFramebufferRenderbufferEXT + typedef void (APIENTRYP GLEEPFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERRENDERBUFFEREXTPROC GLeeFuncPtr_glFramebufferRenderbufferEXT; + #define glFramebufferRenderbufferEXT GLeeFuncPtr_glFramebufferRenderbufferEXT +#endif +#ifndef GLEE_H_DEFINED_glGetFramebufferAttachmentParameterivEXT +#define GLEE_H_DEFINED_glGetFramebufferAttachmentParameterivEXT + typedef void (APIENTRYP GLEEPFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC GLeeFuncPtr_glGetFramebufferAttachmentParameterivEXT; + #define glGetFramebufferAttachmentParameterivEXT GLeeFuncPtr_glGetFramebufferAttachmentParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glGenerateMipmapEXT +#define GLEE_H_DEFINED_glGenerateMipmapEXT + typedef void (APIENTRYP GLEEPFNGLGENERATEMIPMAPEXTPROC) (GLenum target); + GLEE_EXTERN GLEEPFNGLGENERATEMIPMAPEXTPROC GLeeFuncPtr_glGenerateMipmapEXT; + #define glGenerateMipmapEXT GLeeFuncPtr_glGenerateMipmapEXT +#endif +#endif + +/* GL_GREMEDY_string_marker */ + +#ifndef GL_GREMEDY_string_marker +#define GL_GREMEDY_string_marker 1 +#define __GLEE_GL_GREMEDY_string_marker 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glStringMarkerGREMEDY +#define GLEE_H_DEFINED_glStringMarkerGREMEDY + typedef void (APIENTRYP GLEEPFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const GLvoid * string); + GLEE_EXTERN GLEEPFNGLSTRINGMARKERGREMEDYPROC GLeeFuncPtr_glStringMarkerGREMEDY; + #define glStringMarkerGREMEDY GLeeFuncPtr_glStringMarkerGREMEDY +#endif +#endif + +/* GL_EXT_packed_depth_stencil */ + +#ifndef GL_EXT_packed_depth_stencil +#define GL_EXT_packed_depth_stencil 1 +#define __GLEE_GL_EXT_packed_depth_stencil 1 +/* Constants */ +#define GL_DEPTH_STENCIL_EXT 0x84F9 +#define GL_UNSIGNED_INT_24_8_EXT 0x84FA +#define GL_DEPTH24_STENCIL8_EXT 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1 +#endif + +/* GL_EXT_stencil_clear_tag */ + +#ifndef GL_EXT_stencil_clear_tag +#define GL_EXT_stencil_clear_tag 1 +#define __GLEE_GL_EXT_stencil_clear_tag 1 +/* Constants */ +#define GL_STENCIL_TAG_BITS_EXT 0x88F2 +#define GL_STENCIL_CLEAR_TAG_VALUE_EXT 0x88F3 +#ifndef GLEE_H_DEFINED_glStencilClearTagEXT +#define GLEE_H_DEFINED_glStencilClearTagEXT + typedef void (APIENTRYP GLEEPFNGLSTENCILCLEARTAGEXTPROC) (GLsizei stencilTagBits, GLuint stencilClearTag); + GLEE_EXTERN GLEEPFNGLSTENCILCLEARTAGEXTPROC GLeeFuncPtr_glStencilClearTagEXT; + #define glStencilClearTagEXT GLeeFuncPtr_glStencilClearTagEXT +#endif +#endif + +/* GL_EXT_texture_sRGB */ + +#ifndef GL_EXT_texture_sRGB +#define GL_EXT_texture_sRGB 1 +#define __GLEE_GL_EXT_texture_sRGB 1 +/* Constants */ +#define GL_SRGB_EXT 0x8C40 +#define GL_SRGB8_EXT 0x8C41 +#define GL_SRGB_ALPHA_EXT 0x8C42 +#define GL_SRGB8_ALPHA8_EXT 0x8C43 +#define GL_SLUMINANCE_ALPHA_EXT 0x8C44 +#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45 +#define GL_SLUMINANCE_EXT 0x8C46 +#define GL_SLUMINANCE8_EXT 0x8C47 +#define GL_COMPRESSED_SRGB_EXT 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49 +#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A +#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B +#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F +#endif + +/* GL_EXT_framebuffer_blit */ + +#ifndef GL_EXT_framebuffer_blit +#define GL_EXT_framebuffer_blit 1 +#define __GLEE_GL_EXT_framebuffer_blit 1 +/* Constants */ +#define GL_READ_FRAMEBUFFER_EXT 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING_EXT GL_FRAMEBUFFER_BINDING_EXT +#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA +#ifndef GLEE_H_DEFINED_glBlitFramebufferEXT +#define GLEE_H_DEFINED_glBlitFramebufferEXT + typedef void (APIENTRYP GLEEPFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + GLEE_EXTERN GLEEPFNGLBLITFRAMEBUFFEREXTPROC GLeeFuncPtr_glBlitFramebufferEXT; + #define glBlitFramebufferEXT GLeeFuncPtr_glBlitFramebufferEXT +#endif +#endif + +/* GL_EXT_framebuffer_multisample */ + +#ifndef GL_EXT_framebuffer_multisample +#define GL_EXT_framebuffer_multisample 1 +#define __GLEE_GL_EXT_framebuffer_multisample 1 +/* Constants */ +#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 +#define GL_MAX_SAMPLES_EXT 0x8D57 +#ifndef GLEE_H_DEFINED_glRenderbufferStorageMultisampleEXT +#define GLEE_H_DEFINED_glRenderbufferStorageMultisampleEXT + typedef void (APIENTRYP GLEEPFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC GLeeFuncPtr_glRenderbufferStorageMultisampleEXT; + #define glRenderbufferStorageMultisampleEXT GLeeFuncPtr_glRenderbufferStorageMultisampleEXT +#endif +#endif + +/* GL_MESAX_texture_stack */ + +#ifndef GL_MESAX_texture_stack +#define GL_MESAX_texture_stack 1 +#define __GLEE_GL_MESAX_texture_stack 1 +/* Constants */ +#define GL_TEXTURE_1D_STACK_MESAX 0x8759 +#define GL_TEXTURE_2D_STACK_MESAX 0x875A +#define GL_PROXY_TEXTURE_1D_STACK_MESAX 0x875B +#define GL_PROXY_TEXTURE_2D_STACK_MESAX 0x875C +#define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D +#define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E +#endif + +/* GL_EXT_timer_query */ + +#ifndef GL_EXT_timer_query +#define GL_EXT_timer_query 1 +#define __GLEE_GL_EXT_timer_query 1 +/* Constants */ +#define GL_TIME_ELAPSED_EXT 0x88BF +#ifndef GLEE_H_DEFINED_glGetQueryObjecti64vEXT +#define GLEE_H_DEFINED_glGetQueryObjecti64vEXT + typedef void (APIENTRYP GLEEPFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64EXT * params); + GLEE_EXTERN GLEEPFNGLGETQUERYOBJECTI64VEXTPROC GLeeFuncPtr_glGetQueryObjecti64vEXT; + #define glGetQueryObjecti64vEXT GLeeFuncPtr_glGetQueryObjecti64vEXT +#endif +#ifndef GLEE_H_DEFINED_glGetQueryObjectui64vEXT +#define GLEE_H_DEFINED_glGetQueryObjectui64vEXT + typedef void (APIENTRYP GLEEPFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64EXT * params); + GLEE_EXTERN GLEEPFNGLGETQUERYOBJECTUI64VEXTPROC GLeeFuncPtr_glGetQueryObjectui64vEXT; + #define glGetQueryObjectui64vEXT GLeeFuncPtr_glGetQueryObjectui64vEXT +#endif +#endif + +/* GL_EXT_gpu_program_parameters */ + +#ifndef GL_EXT_gpu_program_parameters +#define GL_EXT_gpu_program_parameters 1 +#define __GLEE_GL_EXT_gpu_program_parameters 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glProgramEnvParameters4fvEXT +#define GLEE_H_DEFINED_glProgramEnvParameters4fvEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLPROGRAMENVPARAMETERS4FVEXTPROC GLeeFuncPtr_glProgramEnvParameters4fvEXT; + #define glProgramEnvParameters4fvEXT GLeeFuncPtr_glProgramEnvParameters4fvEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramLocalParameters4fvEXT +#define GLEE_H_DEFINED_glProgramLocalParameters4fvEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC GLeeFuncPtr_glProgramLocalParameters4fvEXT; + #define glProgramLocalParameters4fvEXT GLeeFuncPtr_glProgramLocalParameters4fvEXT +#endif +#endif + +/* GL_APPLE_flush_buffer_range */ + +#ifndef GL_APPLE_flush_buffer_range +#define GL_APPLE_flush_buffer_range 1 +#define __GLEE_GL_APPLE_flush_buffer_range 1 +/* Constants */ +#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12 +#define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13 +#ifndef GLEE_H_DEFINED_glBufferParameteriAPPLE +#define GLEE_H_DEFINED_glBufferParameteriAPPLE + typedef void (APIENTRYP GLEEPFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLBUFFERPARAMETERIAPPLEPROC GLeeFuncPtr_glBufferParameteriAPPLE; + #define glBufferParameteriAPPLE GLeeFuncPtr_glBufferParameteriAPPLE +#endif +#ifndef GLEE_H_DEFINED_glFlushMappedBufferRangeAPPLE +#define GLEE_H_DEFINED_glFlushMappedBufferRangeAPPLE + typedef void (APIENTRYP GLEEPFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size); + GLEE_EXTERN GLEEPFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC GLeeFuncPtr_glFlushMappedBufferRangeAPPLE; + #define glFlushMappedBufferRangeAPPLE GLeeFuncPtr_glFlushMappedBufferRangeAPPLE +#endif +#endif + +/* GL_EXT_gpu_shader4 */ + +#ifndef GL_EXT_gpu_shader4 +#define GL_EXT_gpu_shader4 1 +#define __GLEE_GL_EXT_gpu_shader4 1 +/* Constants */ +#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0 +#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1 +#define GL_SAMPLER_BUFFER_EXT 0x8DC2 +#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5 +#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6 +#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7 +#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8 +#define GL_INT_SAMPLER_1D_EXT 0x8DC9 +#define GL_INT_SAMPLER_2D_EXT 0x8DCA +#define GL_INT_SAMPLER_3D_EXT 0x8DCB +#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC +#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD +#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF +#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8 +#ifndef GLEE_H_DEFINED_glGetUniformuivEXT +#define GLEE_H_DEFINED_glGetUniformuivEXT + typedef void (APIENTRYP GLEEPFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint * params); + GLEE_EXTERN GLEEPFNGLGETUNIFORMUIVEXTPROC GLeeFuncPtr_glGetUniformuivEXT; + #define glGetUniformuivEXT GLeeFuncPtr_glGetUniformuivEXT +#endif +#ifndef GLEE_H_DEFINED_glBindFragDataLocationEXT +#define GLEE_H_DEFINED_glBindFragDataLocationEXT + typedef void (APIENTRYP GLEEPFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar * name); + GLEE_EXTERN GLEEPFNGLBINDFRAGDATALOCATIONEXTPROC GLeeFuncPtr_glBindFragDataLocationEXT; + #define glBindFragDataLocationEXT GLeeFuncPtr_glBindFragDataLocationEXT +#endif +#ifndef GLEE_H_DEFINED_glGetFragDataLocationEXT +#define GLEE_H_DEFINED_glGetFragDataLocationEXT + typedef GLint (APIENTRYP GLEEPFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar * name); + GLEE_EXTERN GLEEPFNGLGETFRAGDATALOCATIONEXTPROC GLeeFuncPtr_glGetFragDataLocationEXT; + #define glGetFragDataLocationEXT GLeeFuncPtr_glGetFragDataLocationEXT +#endif +#ifndef GLEE_H_DEFINED_glUniform1uiEXT +#define GLEE_H_DEFINED_glUniform1uiEXT + typedef void (APIENTRYP GLEEPFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0); + GLEE_EXTERN GLEEPFNGLUNIFORM1UIEXTPROC GLeeFuncPtr_glUniform1uiEXT; + #define glUniform1uiEXT GLeeFuncPtr_glUniform1uiEXT +#endif +#ifndef GLEE_H_DEFINED_glUniform2uiEXT +#define GLEE_H_DEFINED_glUniform2uiEXT + typedef void (APIENTRYP GLEEPFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1); + GLEE_EXTERN GLEEPFNGLUNIFORM2UIEXTPROC GLeeFuncPtr_glUniform2uiEXT; + #define glUniform2uiEXT GLeeFuncPtr_glUniform2uiEXT +#endif +#ifndef GLEE_H_DEFINED_glUniform3uiEXT +#define GLEE_H_DEFINED_glUniform3uiEXT + typedef void (APIENTRYP GLEEPFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); + GLEE_EXTERN GLEEPFNGLUNIFORM3UIEXTPROC GLeeFuncPtr_glUniform3uiEXT; + #define glUniform3uiEXT GLeeFuncPtr_glUniform3uiEXT +#endif +#ifndef GLEE_H_DEFINED_glUniform4uiEXT +#define GLEE_H_DEFINED_glUniform4uiEXT + typedef void (APIENTRYP GLEEPFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + GLEE_EXTERN GLEEPFNGLUNIFORM4UIEXTPROC GLeeFuncPtr_glUniform4uiEXT; + #define glUniform4uiEXT GLeeFuncPtr_glUniform4uiEXT +#endif +#ifndef GLEE_H_DEFINED_glUniform1uivEXT +#define GLEE_H_DEFINED_glUniform1uivEXT + typedef void (APIENTRYP GLEEPFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint * value); + GLEE_EXTERN GLEEPFNGLUNIFORM1UIVEXTPROC GLeeFuncPtr_glUniform1uivEXT; + #define glUniform1uivEXT GLeeFuncPtr_glUniform1uivEXT +#endif +#ifndef GLEE_H_DEFINED_glUniform2uivEXT +#define GLEE_H_DEFINED_glUniform2uivEXT + typedef void (APIENTRYP GLEEPFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint * value); + GLEE_EXTERN GLEEPFNGLUNIFORM2UIVEXTPROC GLeeFuncPtr_glUniform2uivEXT; + #define glUniform2uivEXT GLeeFuncPtr_glUniform2uivEXT +#endif +#ifndef GLEE_H_DEFINED_glUniform3uivEXT +#define GLEE_H_DEFINED_glUniform3uivEXT + typedef void (APIENTRYP GLEEPFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint * value); + GLEE_EXTERN GLEEPFNGLUNIFORM3UIVEXTPROC GLeeFuncPtr_glUniform3uivEXT; + #define glUniform3uivEXT GLeeFuncPtr_glUniform3uivEXT +#endif +#ifndef GLEE_H_DEFINED_glUniform4uivEXT +#define GLEE_H_DEFINED_glUniform4uivEXT + typedef void (APIENTRYP GLEEPFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint * value); + GLEE_EXTERN GLEEPFNGLUNIFORM4UIVEXTPROC GLeeFuncPtr_glUniform4uivEXT; + #define glUniform4uivEXT GLeeFuncPtr_glUniform4uivEXT +#endif +#endif + +/* GL_EXT_draw_instanced */ + +#ifndef GL_EXT_draw_instanced +#define GL_EXT_draw_instanced 1 +#define __GLEE_GL_EXT_draw_instanced 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glDrawArraysInstancedEXT +#define GLEE_H_DEFINED_glDrawArraysInstancedEXT + typedef void (APIENTRYP GLEEPFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); + GLEE_EXTERN GLEEPFNGLDRAWARRAYSINSTANCEDEXTPROC GLeeFuncPtr_glDrawArraysInstancedEXT; + #define glDrawArraysInstancedEXT GLeeFuncPtr_glDrawArraysInstancedEXT +#endif +#ifndef GLEE_H_DEFINED_glDrawElementsInstancedEXT +#define GLEE_H_DEFINED_glDrawElementsInstancedEXT + typedef void (APIENTRYP GLEEPFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid * indices, GLsizei primcount); + GLEE_EXTERN GLEEPFNGLDRAWELEMENTSINSTANCEDEXTPROC GLeeFuncPtr_glDrawElementsInstancedEXT; + #define glDrawElementsInstancedEXT GLeeFuncPtr_glDrawElementsInstancedEXT +#endif +#endif + +/* GL_EXT_packed_float */ + +#ifndef GL_EXT_packed_float +#define GL_EXT_packed_float 1 +#define __GLEE_GL_EXT_packed_float 1 +/* Constants */ +#define GL_R11F_G11F_B10F_EXT 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B +#define GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C +#endif + +/* GL_EXT_texture_array */ + +#ifndef GL_EXT_texture_array +#define GL_EXT_texture_array 1 +#define __GLEE_GL_EXT_texture_array 1 +/* Constants */ +#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19 +#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D +#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF +#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E +#endif + +/* GL_EXT_texture_buffer_object */ + +#ifndef GL_EXT_texture_buffer_object +#define GL_EXT_texture_buffer_object 1 +#define __GLEE_GL_EXT_texture_buffer_object 1 +/* Constants */ +#define GL_TEXTURE_BUFFER_EXT 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E +#ifndef GLEE_H_DEFINED_glTexBufferEXT +#define GLEE_H_DEFINED_glTexBufferEXT + typedef void (APIENTRYP GLEEPFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer); + GLEE_EXTERN GLEEPFNGLTEXBUFFEREXTPROC GLeeFuncPtr_glTexBufferEXT; + #define glTexBufferEXT GLeeFuncPtr_glTexBufferEXT +#endif +#endif + +/* GL_EXT_texture_compression_latc */ + +#ifndef GL_EXT_texture_compression_latc +#define GL_EXT_texture_compression_latc 1 +#define __GLEE_GL_EXT_texture_compression_latc 1 +/* Constants */ +#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 +#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71 +#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 +#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73 +#endif + +/* GL_EXT_texture_compression_rgtc */ + +#ifndef GL_EXT_texture_compression_rgtc +#define GL_EXT_texture_compression_rgtc 1 +#define __GLEE_GL_EXT_texture_compression_rgtc 1 +/* Constants */ +#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC +#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD +#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE +#endif + +/* GL_EXT_texture_shared_exponent */ + +#ifndef GL_EXT_texture_shared_exponent +#define GL_EXT_texture_shared_exponent 1 +#define __GLEE_GL_EXT_texture_shared_exponent 1 +/* Constants */ +#define GL_RGB9_E5_EXT 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E +#define GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F +#endif + +/* GL_NV_depth_buffer_float */ + +#ifndef GL_NV_depth_buffer_float +#define GL_NV_depth_buffer_float 1 +#define __GLEE_GL_NV_depth_buffer_float 1 +/* Constants */ +#define GL_DEPTH_COMPONENT32F_NV 0x8DAB +#define GL_DEPTH32F_STENCIL8_NV 0x8DAC +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD +#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF +#ifndef GLEE_H_DEFINED_glDepthRangedNV +#define GLEE_H_DEFINED_glDepthRangedNV + typedef void (APIENTRYP GLEEPFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar); + GLEE_EXTERN GLEEPFNGLDEPTHRANGEDNVPROC GLeeFuncPtr_glDepthRangedNV; + #define glDepthRangedNV GLeeFuncPtr_glDepthRangedNV +#endif +#ifndef GLEE_H_DEFINED_glClearDepthdNV +#define GLEE_H_DEFINED_glClearDepthdNV + typedef void (APIENTRYP GLEEPFNGLCLEARDEPTHDNVPROC) (GLdouble depth); + GLEE_EXTERN GLEEPFNGLCLEARDEPTHDNVPROC GLeeFuncPtr_glClearDepthdNV; + #define glClearDepthdNV GLeeFuncPtr_glClearDepthdNV +#endif +#ifndef GLEE_H_DEFINED_glDepthBoundsdNV +#define GLEE_H_DEFINED_glDepthBoundsdNV + typedef void (APIENTRYP GLEEPFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax); + GLEE_EXTERN GLEEPFNGLDEPTHBOUNDSDNVPROC GLeeFuncPtr_glDepthBoundsdNV; + #define glDepthBoundsdNV GLeeFuncPtr_glDepthBoundsdNV +#endif +#endif + +/* GL_NV_framebuffer_multisample_coverage */ + +#ifndef GL_NV_framebuffer_multisample_coverage +#define GL_NV_framebuffer_multisample_coverage 1 +#define __GLEE_GL_NV_framebuffer_multisample_coverage 1 +/* Constants */ +#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB +#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10 +#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11 +#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12 +#ifndef GLEE_H_DEFINED_glRenderbufferStorageMultisampleCoverageNV +#define GLEE_H_DEFINED_glRenderbufferStorageMultisampleCoverageNV + typedef void (APIENTRYP GLEEPFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC GLeeFuncPtr_glRenderbufferStorageMultisampleCoverageNV; + #define glRenderbufferStorageMultisampleCoverageNV GLeeFuncPtr_glRenderbufferStorageMultisampleCoverageNV +#endif +#endif + +/* GL_EXT_framebuffer_sRGB */ + +#ifndef GL_EXT_framebuffer_sRGB +#define GL_EXT_framebuffer_sRGB 1 +#define __GLEE_GL_EXT_framebuffer_sRGB 1 +/* Constants */ +#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 +#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA +#endif + +/* GL_NV_geometry_shader4 */ + +#ifndef GL_NV_geometry_shader4 +#define GL_NV_geometry_shader4 1 +#define __GLEE_GL_NV_geometry_shader4 1 +/* Constants */ +#endif + +/* GL_NV_parameter_buffer_object */ + +#ifndef GL_NV_parameter_buffer_object +#define GL_NV_parameter_buffer_object 1 +#define __GLEE_GL_NV_parameter_buffer_object 1 +/* Constants */ +#define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0 +#define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1 +#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2 +#define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3 +#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4 +#ifndef GLEE_H_DEFINED_glProgramBufferParametersfvNV +#define GLEE_H_DEFINED_glProgramBufferParametersfvNV + typedef void (APIENTRYP GLEEPFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLPROGRAMBUFFERPARAMETERSFVNVPROC GLeeFuncPtr_glProgramBufferParametersfvNV; + #define glProgramBufferParametersfvNV GLeeFuncPtr_glProgramBufferParametersfvNV +#endif +#ifndef GLEE_H_DEFINED_glProgramBufferParametersIivNV +#define GLEE_H_DEFINED_glProgramBufferParametersIivNV + typedef void (APIENTRYP GLEEPFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint * params); + GLEE_EXTERN GLEEPFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC GLeeFuncPtr_glProgramBufferParametersIivNV; + #define glProgramBufferParametersIivNV GLeeFuncPtr_glProgramBufferParametersIivNV +#endif +#ifndef GLEE_H_DEFINED_glProgramBufferParametersIuivNV +#define GLEE_H_DEFINED_glProgramBufferParametersIuivNV + typedef void (APIENTRYP GLEEPFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint * params); + GLEE_EXTERN GLEEPFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC GLeeFuncPtr_glProgramBufferParametersIuivNV; + #define glProgramBufferParametersIuivNV GLeeFuncPtr_glProgramBufferParametersIuivNV +#endif +#endif + +/* GL_EXT_draw_buffers2 */ + +#ifndef GL_EXT_draw_buffers2 +#define GL_EXT_draw_buffers2 1 +#define __GLEE_GL_EXT_draw_buffers2 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glColorMaskIndexedEXT +#define GLEE_H_DEFINED_glColorMaskIndexedEXT + typedef void (APIENTRYP GLEEPFNGLCOLORMASKINDEXEDEXTPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); + GLEE_EXTERN GLEEPFNGLCOLORMASKINDEXEDEXTPROC GLeeFuncPtr_glColorMaskIndexedEXT; + #define glColorMaskIndexedEXT GLeeFuncPtr_glColorMaskIndexedEXT +#endif +#ifndef GLEE_H_DEFINED_glGetBooleanIndexedvEXT +#define GLEE_H_DEFINED_glGetBooleanIndexedvEXT + typedef void (APIENTRYP GLEEPFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum target, GLuint index, GLboolean * data); + GLEE_EXTERN GLEEPFNGLGETBOOLEANINDEXEDVEXTPROC GLeeFuncPtr_glGetBooleanIndexedvEXT; + #define glGetBooleanIndexedvEXT GLeeFuncPtr_glGetBooleanIndexedvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetIntegerIndexedvEXT +#define GLEE_H_DEFINED_glGetIntegerIndexedvEXT + typedef void (APIENTRYP GLEEPFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLint * data); + GLEE_EXTERN GLEEPFNGLGETINTEGERINDEXEDVEXTPROC GLeeFuncPtr_glGetIntegerIndexedvEXT; + #define glGetIntegerIndexedvEXT GLeeFuncPtr_glGetIntegerIndexedvEXT +#endif +#ifndef GLEE_H_DEFINED_glEnableIndexedEXT +#define GLEE_H_DEFINED_glEnableIndexedEXT + typedef void (APIENTRYP GLEEPFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index); + GLEE_EXTERN GLEEPFNGLENABLEINDEXEDEXTPROC GLeeFuncPtr_glEnableIndexedEXT; + #define glEnableIndexedEXT GLeeFuncPtr_glEnableIndexedEXT +#endif +#ifndef GLEE_H_DEFINED_glDisableIndexedEXT +#define GLEE_H_DEFINED_glDisableIndexedEXT + typedef void (APIENTRYP GLEEPFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index); + GLEE_EXTERN GLEEPFNGLDISABLEINDEXEDEXTPROC GLeeFuncPtr_glDisableIndexedEXT; + #define glDisableIndexedEXT GLeeFuncPtr_glDisableIndexedEXT +#endif +#ifndef GLEE_H_DEFINED_glIsEnabledIndexedEXT +#define GLEE_H_DEFINED_glIsEnabledIndexedEXT + typedef GLboolean (APIENTRYP GLEEPFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index); + GLEE_EXTERN GLEEPFNGLISENABLEDINDEXEDEXTPROC GLeeFuncPtr_glIsEnabledIndexedEXT; + #define glIsEnabledIndexedEXT GLeeFuncPtr_glIsEnabledIndexedEXT +#endif +#endif + +/* GL_NV_transform_feedback */ + +#ifndef GL_NV_transform_feedback +#define GL_NV_transform_feedback 1 +#define __GLEE_GL_NV_transform_feedback 1 +/* Constants */ +#define GL_BACK_PRIMARY_COLOR_NV 0x8C77 +#define GL_BACK_SECONDARY_COLOR_NV 0x8C78 +#define GL_TEXTURE_COORD_NV 0x8C79 +#define GL_CLIP_DISTANCE_NV 0x8C7A +#define GL_VERTEX_ID_NV 0x8C7B +#define GL_PRIMITIVE_ID_NV 0x8C7C +#define GL_GENERIC_ATTRIB_NV 0x8C7D +#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80 +#define GL_ACTIVE_VARYINGS_NV 0x8C81 +#define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82 +#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85 +#define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86 +#define GL_PRIMITIVES_GENERATED_NV 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88 +#define GL_RASTERIZER_DISCARD_NV 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_ATTRIBS_NV 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B +#define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C +#define GL_SEPARATE_ATTRIBS_NV 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F +#ifndef GLEE_H_DEFINED_glBeginTransformFeedbackNV +#define GLEE_H_DEFINED_glBeginTransformFeedbackNV + typedef void (APIENTRYP GLEEPFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode); + GLEE_EXTERN GLEEPFNGLBEGINTRANSFORMFEEDBACKNVPROC GLeeFuncPtr_glBeginTransformFeedbackNV; + #define glBeginTransformFeedbackNV GLeeFuncPtr_glBeginTransformFeedbackNV +#endif +#ifndef GLEE_H_DEFINED_glEndTransformFeedbackNV +#define GLEE_H_DEFINED_glEndTransformFeedbackNV + typedef void (APIENTRYP GLEEPFNGLENDTRANSFORMFEEDBACKNVPROC) (); + GLEE_EXTERN GLEEPFNGLENDTRANSFORMFEEDBACKNVPROC GLeeFuncPtr_glEndTransformFeedbackNV; + #define glEndTransformFeedbackNV GLeeFuncPtr_glEndTransformFeedbackNV +#endif +#ifndef GLEE_H_DEFINED_glTransformFeedbackAttribsNV +#define GLEE_H_DEFINED_glTransformFeedbackAttribsNV + typedef void (APIENTRYP GLEEPFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint * attribs, GLenum bufferMode); + GLEE_EXTERN GLEEPFNGLTRANSFORMFEEDBACKATTRIBSNVPROC GLeeFuncPtr_glTransformFeedbackAttribsNV; + #define glTransformFeedbackAttribsNV GLeeFuncPtr_glTransformFeedbackAttribsNV +#endif +#ifndef GLEE_H_DEFINED_glBindBufferRangeNV +#define GLEE_H_DEFINED_glBindBufferRangeNV + typedef void (APIENTRYP GLEEPFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); + GLEE_EXTERN GLEEPFNGLBINDBUFFERRANGENVPROC GLeeFuncPtr_glBindBufferRangeNV; + #define glBindBufferRangeNV GLeeFuncPtr_glBindBufferRangeNV +#endif +#ifndef GLEE_H_DEFINED_glBindBufferOffsetNV +#define GLEE_H_DEFINED_glBindBufferOffsetNV + typedef void (APIENTRYP GLEEPFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); + GLEE_EXTERN GLEEPFNGLBINDBUFFEROFFSETNVPROC GLeeFuncPtr_glBindBufferOffsetNV; + #define glBindBufferOffsetNV GLeeFuncPtr_glBindBufferOffsetNV +#endif +#ifndef GLEE_H_DEFINED_glBindBufferBaseNV +#define GLEE_H_DEFINED_glBindBufferBaseNV + typedef void (APIENTRYP GLEEPFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer); + GLEE_EXTERN GLEEPFNGLBINDBUFFERBASENVPROC GLeeFuncPtr_glBindBufferBaseNV; + #define glBindBufferBaseNV GLeeFuncPtr_glBindBufferBaseNV +#endif +#ifndef GLEE_H_DEFINED_glTransformFeedbackVaryingsNV +#define GLEE_H_DEFINED_glTransformFeedbackVaryingsNV + typedef void (APIENTRYP GLEEPFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint * locations, GLenum bufferMode); + GLEE_EXTERN GLEEPFNGLTRANSFORMFEEDBACKVARYINGSNVPROC GLeeFuncPtr_glTransformFeedbackVaryingsNV; + #define glTransformFeedbackVaryingsNV GLeeFuncPtr_glTransformFeedbackVaryingsNV +#endif +#ifndef GLEE_H_DEFINED_glActiveVaryingNV +#define GLEE_H_DEFINED_glActiveVaryingNV + typedef void (APIENTRYP GLEEPFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar * name); + GLEE_EXTERN GLEEPFNGLACTIVEVARYINGNVPROC GLeeFuncPtr_glActiveVaryingNV; + #define glActiveVaryingNV GLeeFuncPtr_glActiveVaryingNV +#endif +#ifndef GLEE_H_DEFINED_glGetVaryingLocationNV +#define GLEE_H_DEFINED_glGetVaryingLocationNV + typedef GLint (APIENTRYP GLEEPFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar * name); + GLEE_EXTERN GLEEPFNGLGETVARYINGLOCATIONNVPROC GLeeFuncPtr_glGetVaryingLocationNV; + #define glGetVaryingLocationNV GLeeFuncPtr_glGetVaryingLocationNV +#endif +#ifndef GLEE_H_DEFINED_glGetActiveVaryingNV +#define GLEE_H_DEFINED_glGetActiveVaryingNV + typedef void (APIENTRYP GLEEPFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name); + GLEE_EXTERN GLEEPFNGLGETACTIVEVARYINGNVPROC GLeeFuncPtr_glGetActiveVaryingNV; + #define glGetActiveVaryingNV GLeeFuncPtr_glGetActiveVaryingNV +#endif +#ifndef GLEE_H_DEFINED_glGetTransformFeedbackVaryingNV +#define GLEE_H_DEFINED_glGetTransformFeedbackVaryingNV + typedef void (APIENTRYP GLEEPFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint * location); + GLEE_EXTERN GLEEPFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC GLeeFuncPtr_glGetTransformFeedbackVaryingNV; + #define glGetTransformFeedbackVaryingNV GLeeFuncPtr_glGetTransformFeedbackVaryingNV +#endif +#endif + +/* GL_EXT_bindable_uniform */ + +#ifndef GL_EXT_bindable_uniform +#define GL_EXT_bindable_uniform 1 +#define __GLEE_GL_EXT_bindable_uniform 1 +/* Constants */ +#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2 +#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3 +#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4 +#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED +#define GL_UNIFORM_BUFFER_EXT 0x8DEE +#define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF +#ifndef GLEE_H_DEFINED_glUniformBufferEXT +#define GLEE_H_DEFINED_glUniformBufferEXT + typedef void (APIENTRYP GLEEPFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer); + GLEE_EXTERN GLEEPFNGLUNIFORMBUFFEREXTPROC GLeeFuncPtr_glUniformBufferEXT; + #define glUniformBufferEXT GLeeFuncPtr_glUniformBufferEXT +#endif +#ifndef GLEE_H_DEFINED_glGetUniformBufferSizeEXT +#define GLEE_H_DEFINED_glGetUniformBufferSizeEXT + typedef GLint (APIENTRYP GLEEPFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location); + GLEE_EXTERN GLEEPFNGLGETUNIFORMBUFFERSIZEEXTPROC GLeeFuncPtr_glGetUniformBufferSizeEXT; + #define glGetUniformBufferSizeEXT GLeeFuncPtr_glGetUniformBufferSizeEXT +#endif +#ifndef GLEE_H_DEFINED_glGetUniformOffsetEXT +#define GLEE_H_DEFINED_glGetUniformOffsetEXT + typedef GLintptr (APIENTRYP GLEEPFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location); + GLEE_EXTERN GLEEPFNGLGETUNIFORMOFFSETEXTPROC GLeeFuncPtr_glGetUniformOffsetEXT; + #define glGetUniformOffsetEXT GLeeFuncPtr_glGetUniformOffsetEXT +#endif +#endif + +/* GL_EXT_texture_integer */ + +#ifndef GL_EXT_texture_integer +#define GL_EXT_texture_integer 1 +#define __GLEE_GL_EXT_texture_integer 1 +/* Constants */ +#define GL_RGBA32UI_EXT 0x8D70 +#define GL_RGB32UI_EXT 0x8D71 +#define GL_ALPHA32UI_EXT 0x8D72 +#define GL_INTENSITY32UI_EXT 0x8D73 +#define GL_LUMINANCE32UI_EXT 0x8D74 +#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75 +#define GL_RGBA16UI_EXT 0x8D76 +#define GL_RGB16UI_EXT 0x8D77 +#define GL_ALPHA16UI_EXT 0x8D78 +#define GL_INTENSITY16UI_EXT 0x8D79 +#define GL_LUMINANCE16UI_EXT 0x8D7A +#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B +#define GL_RGBA8UI_EXT 0x8D7C +#define GL_RGB8UI_EXT 0x8D7D +#define GL_ALPHA8UI_EXT 0x8D7E +#define GL_INTENSITY8UI_EXT 0x8D7F +#define GL_LUMINANCE8UI_EXT 0x8D80 +#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81 +#define GL_RGBA32I_EXT 0x8D82 +#define GL_RGB32I_EXT 0x8D83 +#define GL_ALPHA32I_EXT 0x8D84 +#define GL_INTENSITY32I_EXT 0x8D85 +#define GL_LUMINANCE32I_EXT 0x8D86 +#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87 +#define GL_RGBA16I_EXT 0x8D88 +#define GL_RGB16I_EXT 0x8D89 +#define GL_ALPHA16I_EXT 0x8D8A +#define GL_INTENSITY16I_EXT 0x8D8B +#define GL_LUMINANCE16I_EXT 0x8D8C +#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D +#define GL_RGBA8I_EXT 0x8D8E +#define GL_RGB8I_EXT 0x8D8F +#define GL_ALPHA8I_EXT 0x8D90 +#define GL_INTENSITY8I_EXT 0x8D91 +#define GL_LUMINANCE8I_EXT 0x8D92 +#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93 +#define GL_RED_INTEGER_EXT 0x8D94 +#define GL_GREEN_INTEGER_EXT 0x8D95 +#define GL_BLUE_INTEGER_EXT 0x8D96 +#define GL_ALPHA_INTEGER_EXT 0x8D97 +#define GL_RGB_INTEGER_EXT 0x8D98 +#define GL_RGBA_INTEGER_EXT 0x8D99 +#define GL_BGR_INTEGER_EXT 0x8D9A +#define GL_BGRA_INTEGER_EXT 0x8D9B +#define GL_LUMINANCE_INTEGER_EXT 0x8D9C +#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D +#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E +#ifndef GLEE_H_DEFINED_glTexParameterIivEXT +#define GLEE_H_DEFINED_glTexParameterIivEXT + typedef void (APIENTRYP GLEEPFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLTEXPARAMETERIIVEXTPROC GLeeFuncPtr_glTexParameterIivEXT; + #define glTexParameterIivEXT GLeeFuncPtr_glTexParameterIivEXT +#endif +#ifndef GLEE_H_DEFINED_glTexParameterIuivEXT +#define GLEE_H_DEFINED_glTexParameterIuivEXT + typedef void (APIENTRYP GLEEPFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint * params); + GLEE_EXTERN GLEEPFNGLTEXPARAMETERIUIVEXTPROC GLeeFuncPtr_glTexParameterIuivEXT; + #define glTexParameterIuivEXT GLeeFuncPtr_glTexParameterIuivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetTexParameterIivEXT +#define GLEE_H_DEFINED_glGetTexParameterIivEXT + typedef void (APIENTRYP GLEEPFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETTEXPARAMETERIIVEXTPROC GLeeFuncPtr_glGetTexParameterIivEXT; + #define glGetTexParameterIivEXT GLeeFuncPtr_glGetTexParameterIivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetTexParameterIuivEXT +#define GLEE_H_DEFINED_glGetTexParameterIuivEXT + typedef void (APIENTRYP GLEEPFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint * params); + GLEE_EXTERN GLEEPFNGLGETTEXPARAMETERIUIVEXTPROC GLeeFuncPtr_glGetTexParameterIuivEXT; + #define glGetTexParameterIuivEXT GLeeFuncPtr_glGetTexParameterIuivEXT +#endif +#ifndef GLEE_H_DEFINED_glClearColorIiEXT +#define GLEE_H_DEFINED_glClearColorIiEXT + typedef void (APIENTRYP GLEEPFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha); + GLEE_EXTERN GLEEPFNGLCLEARCOLORIIEXTPROC GLeeFuncPtr_glClearColorIiEXT; + #define glClearColorIiEXT GLeeFuncPtr_glClearColorIiEXT +#endif +#ifndef GLEE_H_DEFINED_glClearColorIuiEXT +#define GLEE_H_DEFINED_glClearColorIuiEXT + typedef void (APIENTRYP GLEEPFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha); + GLEE_EXTERN GLEEPFNGLCLEARCOLORIUIEXTPROC GLeeFuncPtr_glClearColorIuiEXT; + #define glClearColorIuiEXT GLeeFuncPtr_glClearColorIuiEXT +#endif +#endif + +/* GL_GREMEDY_frame_terminator */ + +#ifndef GL_GREMEDY_frame_terminator +#define GL_GREMEDY_frame_terminator 1 +#define __GLEE_GL_GREMEDY_frame_terminator 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glFrameTerminatorGREMEDY +#define GLEE_H_DEFINED_glFrameTerminatorGREMEDY + typedef void (APIENTRYP GLEEPFNGLFRAMETERMINATORGREMEDYPROC) (); + GLEE_EXTERN GLEEPFNGLFRAMETERMINATORGREMEDYPROC GLeeFuncPtr_glFrameTerminatorGREMEDY; + #define glFrameTerminatorGREMEDY GLeeFuncPtr_glFrameTerminatorGREMEDY +#endif +#endif + +/* GL_NV_conditional_render */ + +#ifndef GL_NV_conditional_render +#define GL_NV_conditional_render 1 +#define __GLEE_GL_NV_conditional_render 1 +/* Constants */ +#define GL_QUERY_WAIT_NV 0x8E13 +#define GL_QUERY_NO_WAIT_NV 0x8E14 +#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16 +#ifndef GLEE_H_DEFINED_glBeginConditionalRenderNV +#define GLEE_H_DEFINED_glBeginConditionalRenderNV + typedef void (APIENTRYP GLEEPFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode); + GLEE_EXTERN GLEEPFNGLBEGINCONDITIONALRENDERNVPROC GLeeFuncPtr_glBeginConditionalRenderNV; + #define glBeginConditionalRenderNV GLeeFuncPtr_glBeginConditionalRenderNV +#endif +#ifndef GLEE_H_DEFINED_glEndConditionalRenderNV +#define GLEE_H_DEFINED_glEndConditionalRenderNV + typedef void (APIENTRYP GLEEPFNGLENDCONDITIONALRENDERNVPROC) (); + GLEE_EXTERN GLEEPFNGLENDCONDITIONALRENDERNVPROC GLeeFuncPtr_glEndConditionalRenderNV; + #define glEndConditionalRenderNV GLeeFuncPtr_glEndConditionalRenderNV +#endif +#endif + +/* GL_NV_present_video */ + +#ifndef GL_NV_present_video +#define GL_NV_present_video 1 +#define __GLEE_GL_NV_present_video 1 +/* Constants */ +#define GL_FRAME_NV 0x8E26 +#define GL_FIELDS_NV 0x8E27 +#define GL_CURRENT_TIME_NV 0x8E28 +#define GL_NUM_FILL_STREAMS_NV 0x8E29 +#define GL_PRESENT_TIME_NV 0x8E2A +#define GL_PRESENT_DURATION_NV 0x8E2B +#endif + +/* GL_EXT_transform_feedback */ + +#ifndef GL_EXT_transform_feedback +#define GL_EXT_transform_feedback 1 +#define __GLEE_GL_EXT_transform_feedback 1 +/* Constants */ +#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85 +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F +#define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C +#define GL_SEPARATE_ATTRIBS_EXT 0x8C8D +#define GL_PRIMITIVES_GENERATED_EXT 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88 +#define GL_RASTERIZER_DISCARD_EXT 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76 +#ifndef GLEE_H_DEFINED_glBeginTransformFeedbackEXT +#define GLEE_H_DEFINED_glBeginTransformFeedbackEXT + typedef void (APIENTRYP GLEEPFNGLBEGINTRANSFORMFEEDBACKEXTPROC) (GLenum primitiveMode); + GLEE_EXTERN GLEEPFNGLBEGINTRANSFORMFEEDBACKEXTPROC GLeeFuncPtr_glBeginTransformFeedbackEXT; + #define glBeginTransformFeedbackEXT GLeeFuncPtr_glBeginTransformFeedbackEXT +#endif +#ifndef GLEE_H_DEFINED_glEndTransformFeedbackEXT +#define GLEE_H_DEFINED_glEndTransformFeedbackEXT + typedef void (APIENTRYP GLEEPFNGLENDTRANSFORMFEEDBACKEXTPROC) (); + GLEE_EXTERN GLEEPFNGLENDTRANSFORMFEEDBACKEXTPROC GLeeFuncPtr_glEndTransformFeedbackEXT; + #define glEndTransformFeedbackEXT GLeeFuncPtr_glEndTransformFeedbackEXT +#endif +#ifndef GLEE_H_DEFINED_glBindBufferRangeEXT +#define GLEE_H_DEFINED_glBindBufferRangeEXT + typedef void (APIENTRYP GLEEPFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); + GLEE_EXTERN GLEEPFNGLBINDBUFFERRANGEEXTPROC GLeeFuncPtr_glBindBufferRangeEXT; + #define glBindBufferRangeEXT GLeeFuncPtr_glBindBufferRangeEXT +#endif +#ifndef GLEE_H_DEFINED_glBindBufferOffsetEXT +#define GLEE_H_DEFINED_glBindBufferOffsetEXT + typedef void (APIENTRYP GLEEPFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); + GLEE_EXTERN GLEEPFNGLBINDBUFFEROFFSETEXTPROC GLeeFuncPtr_glBindBufferOffsetEXT; + #define glBindBufferOffsetEXT GLeeFuncPtr_glBindBufferOffsetEXT +#endif +#ifndef GLEE_H_DEFINED_glBindBufferBaseEXT +#define GLEE_H_DEFINED_glBindBufferBaseEXT + typedef void (APIENTRYP GLEEPFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint index, GLuint buffer); + GLEE_EXTERN GLEEPFNGLBINDBUFFERBASEEXTPROC GLeeFuncPtr_glBindBufferBaseEXT; + #define glBindBufferBaseEXT GLeeFuncPtr_glBindBufferBaseEXT +#endif +#ifndef GLEE_H_DEFINED_glTransformFeedbackVaryingsEXT +#define GLEE_H_DEFINED_glTransformFeedbackVaryingsEXT + typedef void (APIENTRYP GLEEPFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const GLint * locations, GLenum bufferMode); + GLEE_EXTERN GLEEPFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC GLeeFuncPtr_glTransformFeedbackVaryingsEXT; + #define glTransformFeedbackVaryingsEXT GLeeFuncPtr_glTransformFeedbackVaryingsEXT +#endif +#ifndef GLEE_H_DEFINED_glGetTransformFeedbackVaryingEXT +#define GLEE_H_DEFINED_glGetTransformFeedbackVaryingEXT + typedef void (APIENTRYP GLEEPFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLint * location); + GLEE_EXTERN GLEEPFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC GLeeFuncPtr_glGetTransformFeedbackVaryingEXT; + #define glGetTransformFeedbackVaryingEXT GLeeFuncPtr_glGetTransformFeedbackVaryingEXT +#endif +#endif + +/* GL_EXT_direct_state_access */ + +#ifndef GL_EXT_direct_state_access +#define GL_EXT_direct_state_access 1 +#define __GLEE_GL_EXT_direct_state_access 1 +/* Constants */ +#define GL_PROGRAM_MATRIX_EXT 0x8E2D +#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E +#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F +#ifndef GLEE_H_DEFINED_glClientAttribDefaultEXT +#define GLEE_H_DEFINED_glClientAttribDefaultEXT + typedef void (APIENTRYP GLEEPFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); + GLEE_EXTERN GLEEPFNGLCLIENTATTRIBDEFAULTEXTPROC GLeeFuncPtr_glClientAttribDefaultEXT; + #define glClientAttribDefaultEXT GLeeFuncPtr_glClientAttribDefaultEXT +#endif +#ifndef GLEE_H_DEFINED_glPushClientAttribDefaultEXT +#define GLEE_H_DEFINED_glPushClientAttribDefaultEXT + typedef void (APIENTRYP GLEEPFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); + GLEE_EXTERN GLEEPFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC GLeeFuncPtr_glPushClientAttribDefaultEXT; + #define glPushClientAttribDefaultEXT GLeeFuncPtr_glPushClientAttribDefaultEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixLoadfEXT +#define GLEE_H_DEFINED_glMatrixLoadfEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXLOADFEXTPROC) (GLenum mode, const GLfloat * m); + GLEE_EXTERN GLEEPFNGLMATRIXLOADFEXTPROC GLeeFuncPtr_glMatrixLoadfEXT; + #define glMatrixLoadfEXT GLeeFuncPtr_glMatrixLoadfEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixLoaddEXT +#define GLEE_H_DEFINED_glMatrixLoaddEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXLOADDEXTPROC) (GLenum mode, const GLdouble * m); + GLEE_EXTERN GLEEPFNGLMATRIXLOADDEXTPROC GLeeFuncPtr_glMatrixLoaddEXT; + #define glMatrixLoaddEXT GLeeFuncPtr_glMatrixLoaddEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixMultfEXT +#define GLEE_H_DEFINED_glMatrixMultfEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXMULTFEXTPROC) (GLenum mode, const GLfloat * m); + GLEE_EXTERN GLEEPFNGLMATRIXMULTFEXTPROC GLeeFuncPtr_glMatrixMultfEXT; + #define glMatrixMultfEXT GLeeFuncPtr_glMatrixMultfEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixMultdEXT +#define GLEE_H_DEFINED_glMatrixMultdEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXMULTDEXTPROC) (GLenum mode, const GLdouble * m); + GLEE_EXTERN GLEEPFNGLMATRIXMULTDEXTPROC GLeeFuncPtr_glMatrixMultdEXT; + #define glMatrixMultdEXT GLeeFuncPtr_glMatrixMultdEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixLoadIdentityEXT +#define GLEE_H_DEFINED_glMatrixLoadIdentityEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum mode); + GLEE_EXTERN GLEEPFNGLMATRIXLOADIDENTITYEXTPROC GLeeFuncPtr_glMatrixLoadIdentityEXT; + #define glMatrixLoadIdentityEXT GLeeFuncPtr_glMatrixLoadIdentityEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixRotatefEXT +#define GLEE_H_DEFINED_glMatrixRotatefEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXROTATEFEXTPROC) (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLMATRIXROTATEFEXTPROC GLeeFuncPtr_glMatrixRotatefEXT; + #define glMatrixRotatefEXT GLeeFuncPtr_glMatrixRotatefEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixRotatedEXT +#define GLEE_H_DEFINED_glMatrixRotatedEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXROTATEDEXTPROC) (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z); + GLEE_EXTERN GLEEPFNGLMATRIXROTATEDEXTPROC GLeeFuncPtr_glMatrixRotatedEXT; + #define glMatrixRotatedEXT GLeeFuncPtr_glMatrixRotatedEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixScalefEXT +#define GLEE_H_DEFINED_glMatrixScalefEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXSCALEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLMATRIXSCALEFEXTPROC GLeeFuncPtr_glMatrixScalefEXT; + #define glMatrixScalefEXT GLeeFuncPtr_glMatrixScalefEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixScaledEXT +#define GLEE_H_DEFINED_glMatrixScaledEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXSCALEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z); + GLEE_EXTERN GLEEPFNGLMATRIXSCALEDEXTPROC GLeeFuncPtr_glMatrixScaledEXT; + #define glMatrixScaledEXT GLeeFuncPtr_glMatrixScaledEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixTranslatefEXT +#define GLEE_H_DEFINED_glMatrixTranslatefEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXTRANSLATEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z); + GLEE_EXTERN GLEEPFNGLMATRIXTRANSLATEFEXTPROC GLeeFuncPtr_glMatrixTranslatefEXT; + #define glMatrixTranslatefEXT GLeeFuncPtr_glMatrixTranslatefEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixTranslatedEXT +#define GLEE_H_DEFINED_glMatrixTranslatedEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXTRANSLATEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z); + GLEE_EXTERN GLEEPFNGLMATRIXTRANSLATEDEXTPROC GLeeFuncPtr_glMatrixTranslatedEXT; + #define glMatrixTranslatedEXT GLeeFuncPtr_glMatrixTranslatedEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixFrustumEXT +#define GLEE_H_DEFINED_glMatrixFrustumEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXFRUSTUMEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); + GLEE_EXTERN GLEEPFNGLMATRIXFRUSTUMEXTPROC GLeeFuncPtr_glMatrixFrustumEXT; + #define glMatrixFrustumEXT GLeeFuncPtr_glMatrixFrustumEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixOrthoEXT +#define GLEE_H_DEFINED_glMatrixOrthoEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXORTHOEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); + GLEE_EXTERN GLEEPFNGLMATRIXORTHOEXTPROC GLeeFuncPtr_glMatrixOrthoEXT; + #define glMatrixOrthoEXT GLeeFuncPtr_glMatrixOrthoEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixPopEXT +#define GLEE_H_DEFINED_glMatrixPopEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXPOPEXTPROC) (GLenum mode); + GLEE_EXTERN GLEEPFNGLMATRIXPOPEXTPROC GLeeFuncPtr_glMatrixPopEXT; + #define glMatrixPopEXT GLeeFuncPtr_glMatrixPopEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixPushEXT +#define GLEE_H_DEFINED_glMatrixPushEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXPUSHEXTPROC) (GLenum mode); + GLEE_EXTERN GLEEPFNGLMATRIXPUSHEXTPROC GLeeFuncPtr_glMatrixPushEXT; + #define glMatrixPushEXT GLeeFuncPtr_glMatrixPushEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixLoadTransposefEXT +#define GLEE_H_DEFINED_glMatrixLoadTransposefEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXLOADTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat * m); + GLEE_EXTERN GLEEPFNGLMATRIXLOADTRANSPOSEFEXTPROC GLeeFuncPtr_glMatrixLoadTransposefEXT; + #define glMatrixLoadTransposefEXT GLeeFuncPtr_glMatrixLoadTransposefEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixLoadTransposedEXT +#define GLEE_H_DEFINED_glMatrixLoadTransposedEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble * m); + GLEE_EXTERN GLEEPFNGLMATRIXLOADTRANSPOSEDEXTPROC GLeeFuncPtr_glMatrixLoadTransposedEXT; + #define glMatrixLoadTransposedEXT GLeeFuncPtr_glMatrixLoadTransposedEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixMultTransposefEXT +#define GLEE_H_DEFINED_glMatrixMultTransposefEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXMULTTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat * m); + GLEE_EXTERN GLEEPFNGLMATRIXMULTTRANSPOSEFEXTPROC GLeeFuncPtr_glMatrixMultTransposefEXT; + #define glMatrixMultTransposefEXT GLeeFuncPtr_glMatrixMultTransposefEXT +#endif +#ifndef GLEE_H_DEFINED_glMatrixMultTransposedEXT +#define GLEE_H_DEFINED_glMatrixMultTransposedEXT + typedef void (APIENTRYP GLEEPFNGLMATRIXMULTTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble * m); + GLEE_EXTERN GLEEPFNGLMATRIXMULTTRANSPOSEDEXTPROC GLeeFuncPtr_glMatrixMultTransposedEXT; + #define glMatrixMultTransposedEXT GLeeFuncPtr_glMatrixMultTransposedEXT +#endif +#ifndef GLEE_H_DEFINED_glTextureParameterfEXT +#define GLEE_H_DEFINED_glTextureParameterfEXT + typedef void (APIENTRYP GLEEPFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLTEXTUREPARAMETERFEXTPROC GLeeFuncPtr_glTextureParameterfEXT; + #define glTextureParameterfEXT GLeeFuncPtr_glTextureParameterfEXT +#endif +#ifndef GLEE_H_DEFINED_glTextureParameterfvEXT +#define GLEE_H_DEFINED_glTextureParameterfvEXT + typedef void (APIENTRYP GLEEPFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLTEXTUREPARAMETERFVEXTPROC GLeeFuncPtr_glTextureParameterfvEXT; + #define glTextureParameterfvEXT GLeeFuncPtr_glTextureParameterfvEXT +#endif +#ifndef GLEE_H_DEFINED_glTextureParameteriEXT +#define GLEE_H_DEFINED_glTextureParameteriEXT + typedef void (APIENTRYP GLEEPFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLTEXTUREPARAMETERIEXTPROC GLeeFuncPtr_glTextureParameteriEXT; + #define glTextureParameteriEXT GLeeFuncPtr_glTextureParameteriEXT +#endif +#ifndef GLEE_H_DEFINED_glTextureParameterivEXT +#define GLEE_H_DEFINED_glTextureParameterivEXT + typedef void (APIENTRYP GLEEPFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLTEXTUREPARAMETERIVEXTPROC GLeeFuncPtr_glTextureParameterivEXT; + #define glTextureParameterivEXT GLeeFuncPtr_glTextureParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glTextureImage1DEXT +#define GLEE_H_DEFINED_glTextureImage1DEXT + typedef void (APIENTRYP GLEEPFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLTEXTUREIMAGE1DEXTPROC GLeeFuncPtr_glTextureImage1DEXT; + #define glTextureImage1DEXT GLeeFuncPtr_glTextureImage1DEXT +#endif +#ifndef GLEE_H_DEFINED_glTextureImage2DEXT +#define GLEE_H_DEFINED_glTextureImage2DEXT + typedef void (APIENTRYP GLEEPFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLTEXTUREIMAGE2DEXTPROC GLeeFuncPtr_glTextureImage2DEXT; + #define glTextureImage2DEXT GLeeFuncPtr_glTextureImage2DEXT +#endif +#ifndef GLEE_H_DEFINED_glTextureSubImage1DEXT +#define GLEE_H_DEFINED_glTextureSubImage1DEXT + typedef void (APIENTRYP GLEEPFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLTEXTURESUBIMAGE1DEXTPROC GLeeFuncPtr_glTextureSubImage1DEXT; + #define glTextureSubImage1DEXT GLeeFuncPtr_glTextureSubImage1DEXT +#endif +#ifndef GLEE_H_DEFINED_glTextureSubImage2DEXT +#define GLEE_H_DEFINED_glTextureSubImage2DEXT + typedef void (APIENTRYP GLEEPFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLTEXTURESUBIMAGE2DEXTPROC GLeeFuncPtr_glTextureSubImage2DEXT; + #define glTextureSubImage2DEXT GLeeFuncPtr_glTextureSubImage2DEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyTextureImage1DEXT +#define GLEE_H_DEFINED_glCopyTextureImage1DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); + GLEE_EXTERN GLEEPFNGLCOPYTEXTUREIMAGE1DEXTPROC GLeeFuncPtr_glCopyTextureImage1DEXT; + #define glCopyTextureImage1DEXT GLeeFuncPtr_glCopyTextureImage1DEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyTextureImage2DEXT +#define GLEE_H_DEFINED_glCopyTextureImage2DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); + GLEE_EXTERN GLEEPFNGLCOPYTEXTUREIMAGE2DEXTPROC GLeeFuncPtr_glCopyTextureImage2DEXT; + #define glCopyTextureImage2DEXT GLeeFuncPtr_glCopyTextureImage2DEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyTextureSubImage1DEXT +#define GLEE_H_DEFINED_glCopyTextureSubImage1DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); + GLEE_EXTERN GLEEPFNGLCOPYTEXTURESUBIMAGE1DEXTPROC GLeeFuncPtr_glCopyTextureSubImage1DEXT; + #define glCopyTextureSubImage1DEXT GLeeFuncPtr_glCopyTextureSubImage1DEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyTextureSubImage2DEXT +#define GLEE_H_DEFINED_glCopyTextureSubImage2DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLCOPYTEXTURESUBIMAGE2DEXTPROC GLeeFuncPtr_glCopyTextureSubImage2DEXT; + #define glCopyTextureSubImage2DEXT GLeeFuncPtr_glCopyTextureSubImage2DEXT +#endif +#ifndef GLEE_H_DEFINED_glGetTextureImageEXT +#define GLEE_H_DEFINED_glGetTextureImageEXT + typedef void (APIENTRYP GLEEPFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLGETTEXTUREIMAGEEXTPROC GLeeFuncPtr_glGetTextureImageEXT; + #define glGetTextureImageEXT GLeeFuncPtr_glGetTextureImageEXT +#endif +#ifndef GLEE_H_DEFINED_glGetTextureParameterfvEXT +#define GLEE_H_DEFINED_glGetTextureParameterfvEXT + typedef void (APIENTRYP GLEEPFNGLGETTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETTEXTUREPARAMETERFVEXTPROC GLeeFuncPtr_glGetTextureParameterfvEXT; + #define glGetTextureParameterfvEXT GLeeFuncPtr_glGetTextureParameterfvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetTextureParameterivEXT +#define GLEE_H_DEFINED_glGetTextureParameterivEXT + typedef void (APIENTRYP GLEEPFNGLGETTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETTEXTUREPARAMETERIVEXTPROC GLeeFuncPtr_glGetTextureParameterivEXT; + #define glGetTextureParameterivEXT GLeeFuncPtr_glGetTextureParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetTextureLevelParameterfvEXT +#define GLEE_H_DEFINED_glGetTextureLevelParameterfvEXT + typedef void (APIENTRYP GLEEPFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETTEXTURELEVELPARAMETERFVEXTPROC GLeeFuncPtr_glGetTextureLevelParameterfvEXT; + #define glGetTextureLevelParameterfvEXT GLeeFuncPtr_glGetTextureLevelParameterfvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetTextureLevelParameterivEXT +#define GLEE_H_DEFINED_glGetTextureLevelParameterivEXT + typedef void (APIENTRYP GLEEPFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETTEXTURELEVELPARAMETERIVEXTPROC GLeeFuncPtr_glGetTextureLevelParameterivEXT; + #define glGetTextureLevelParameterivEXT GLeeFuncPtr_glGetTextureLevelParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glTextureImage3DEXT +#define GLEE_H_DEFINED_glTextureImage3DEXT + typedef void (APIENTRYP GLEEPFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLTEXTUREIMAGE3DEXTPROC GLeeFuncPtr_glTextureImage3DEXT; + #define glTextureImage3DEXT GLeeFuncPtr_glTextureImage3DEXT +#endif +#ifndef GLEE_H_DEFINED_glTextureSubImage3DEXT +#define GLEE_H_DEFINED_glTextureSubImage3DEXT + typedef void (APIENTRYP GLEEPFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLTEXTURESUBIMAGE3DEXTPROC GLeeFuncPtr_glTextureSubImage3DEXT; + #define glTextureSubImage3DEXT GLeeFuncPtr_glTextureSubImage3DEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyTextureSubImage3DEXT +#define GLEE_H_DEFINED_glCopyTextureSubImage3DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLCOPYTEXTURESUBIMAGE3DEXTPROC GLeeFuncPtr_glCopyTextureSubImage3DEXT; + #define glCopyTextureSubImage3DEXT GLeeFuncPtr_glCopyTextureSubImage3DEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexParameterfEXT +#define GLEE_H_DEFINED_glMultiTexParameterfEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLMULTITEXPARAMETERFEXTPROC GLeeFuncPtr_glMultiTexParameterfEXT; + #define glMultiTexParameterfEXT GLeeFuncPtr_glMultiTexParameterfEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexParameterfvEXT +#define GLEE_H_DEFINED_glMultiTexParameterfvEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLMULTITEXPARAMETERFVEXTPROC GLeeFuncPtr_glMultiTexParameterfvEXT; + #define glMultiTexParameterfvEXT GLeeFuncPtr_glMultiTexParameterfvEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexParameteriEXT +#define GLEE_H_DEFINED_glMultiTexParameteriEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLMULTITEXPARAMETERIEXTPROC GLeeFuncPtr_glMultiTexParameteriEXT; + #define glMultiTexParameteriEXT GLeeFuncPtr_glMultiTexParameteriEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexParameterivEXT +#define GLEE_H_DEFINED_glMultiTexParameterivEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLMULTITEXPARAMETERIVEXTPROC GLeeFuncPtr_glMultiTexParameterivEXT; + #define glMultiTexParameterivEXT GLeeFuncPtr_glMultiTexParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexImage1DEXT +#define GLEE_H_DEFINED_glMultiTexImage1DEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLMULTITEXIMAGE1DEXTPROC GLeeFuncPtr_glMultiTexImage1DEXT; + #define glMultiTexImage1DEXT GLeeFuncPtr_glMultiTexImage1DEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexImage2DEXT +#define GLEE_H_DEFINED_glMultiTexImage2DEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLMULTITEXIMAGE2DEXTPROC GLeeFuncPtr_glMultiTexImage2DEXT; + #define glMultiTexImage2DEXT GLeeFuncPtr_glMultiTexImage2DEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexSubImage1DEXT +#define GLEE_H_DEFINED_glMultiTexSubImage1DEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLMULTITEXSUBIMAGE1DEXTPROC GLeeFuncPtr_glMultiTexSubImage1DEXT; + #define glMultiTexSubImage1DEXT GLeeFuncPtr_glMultiTexSubImage1DEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexSubImage2DEXT +#define GLEE_H_DEFINED_glMultiTexSubImage2DEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLMULTITEXSUBIMAGE2DEXTPROC GLeeFuncPtr_glMultiTexSubImage2DEXT; + #define glMultiTexSubImage2DEXT GLeeFuncPtr_glMultiTexSubImage2DEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyMultiTexImage1DEXT +#define GLEE_H_DEFINED_glCopyMultiTexImage1DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); + GLEE_EXTERN GLEEPFNGLCOPYMULTITEXIMAGE1DEXTPROC GLeeFuncPtr_glCopyMultiTexImage1DEXT; + #define glCopyMultiTexImage1DEXT GLeeFuncPtr_glCopyMultiTexImage1DEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyMultiTexImage2DEXT +#define GLEE_H_DEFINED_glCopyMultiTexImage2DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); + GLEE_EXTERN GLEEPFNGLCOPYMULTITEXIMAGE2DEXTPROC GLeeFuncPtr_glCopyMultiTexImage2DEXT; + #define glCopyMultiTexImage2DEXT GLeeFuncPtr_glCopyMultiTexImage2DEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyMultiTexSubImage1DEXT +#define GLEE_H_DEFINED_glCopyMultiTexSubImage1DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); + GLEE_EXTERN GLEEPFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC GLeeFuncPtr_glCopyMultiTexSubImage1DEXT; + #define glCopyMultiTexSubImage1DEXT GLeeFuncPtr_glCopyMultiTexSubImage1DEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyMultiTexSubImage2DEXT +#define GLEE_H_DEFINED_glCopyMultiTexSubImage2DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC GLeeFuncPtr_glCopyMultiTexSubImage2DEXT; + #define glCopyMultiTexSubImage2DEXT GLeeFuncPtr_glCopyMultiTexSubImage2DEXT +#endif +#ifndef GLEE_H_DEFINED_glGetMultiTexImageEXT +#define GLEE_H_DEFINED_glGetMultiTexImageEXT + typedef void (APIENTRYP GLEEPFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLGETMULTITEXIMAGEEXTPROC GLeeFuncPtr_glGetMultiTexImageEXT; + #define glGetMultiTexImageEXT GLeeFuncPtr_glGetMultiTexImageEXT +#endif +#ifndef GLEE_H_DEFINED_glGetMultiTexParameterfvEXT +#define GLEE_H_DEFINED_glGetMultiTexParameterfvEXT + typedef void (APIENTRYP GLEEPFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETMULTITEXPARAMETERFVEXTPROC GLeeFuncPtr_glGetMultiTexParameterfvEXT; + #define glGetMultiTexParameterfvEXT GLeeFuncPtr_glGetMultiTexParameterfvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetMultiTexParameterivEXT +#define GLEE_H_DEFINED_glGetMultiTexParameterivEXT + typedef void (APIENTRYP GLEEPFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETMULTITEXPARAMETERIVEXTPROC GLeeFuncPtr_glGetMultiTexParameterivEXT; + #define glGetMultiTexParameterivEXT GLeeFuncPtr_glGetMultiTexParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetMultiTexLevelParameterfvEXT +#define GLEE_H_DEFINED_glGetMultiTexLevelParameterfvEXT + typedef void (APIENTRYP GLEEPFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC GLeeFuncPtr_glGetMultiTexLevelParameterfvEXT; + #define glGetMultiTexLevelParameterfvEXT GLeeFuncPtr_glGetMultiTexLevelParameterfvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetMultiTexLevelParameterivEXT +#define GLEE_H_DEFINED_glGetMultiTexLevelParameterivEXT + typedef void (APIENTRYP GLEEPFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC GLeeFuncPtr_glGetMultiTexLevelParameterivEXT; + #define glGetMultiTexLevelParameterivEXT GLeeFuncPtr_glGetMultiTexLevelParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexImage3DEXT +#define GLEE_H_DEFINED_glMultiTexImage3DEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLMULTITEXIMAGE3DEXTPROC GLeeFuncPtr_glMultiTexImage3DEXT; + #define glMultiTexImage3DEXT GLeeFuncPtr_glMultiTexImage3DEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexSubImage3DEXT +#define GLEE_H_DEFINED_glMultiTexSubImage3DEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid * pixels); + GLEE_EXTERN GLEEPFNGLMULTITEXSUBIMAGE3DEXTPROC GLeeFuncPtr_glMultiTexSubImage3DEXT; + #define glMultiTexSubImage3DEXT GLeeFuncPtr_glMultiTexSubImage3DEXT +#endif +#ifndef GLEE_H_DEFINED_glCopyMultiTexSubImage3DEXT +#define GLEE_H_DEFINED_glCopyMultiTexSubImage3DEXT + typedef void (APIENTRYP GLEEPFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC GLeeFuncPtr_glCopyMultiTexSubImage3DEXT; + #define glCopyMultiTexSubImage3DEXT GLeeFuncPtr_glCopyMultiTexSubImage3DEXT +#endif +#ifndef GLEE_H_DEFINED_glBindMultiTextureEXT +#define GLEE_H_DEFINED_glBindMultiTextureEXT + typedef void (APIENTRYP GLEEPFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture); + GLEE_EXTERN GLEEPFNGLBINDMULTITEXTUREEXTPROC GLeeFuncPtr_glBindMultiTextureEXT; + #define glBindMultiTextureEXT GLeeFuncPtr_glBindMultiTextureEXT +#endif +#ifndef GLEE_H_DEFINED_glEnableClientStateIndexedEXT +#define GLEE_H_DEFINED_glEnableClientStateIndexedEXT + typedef void (APIENTRYP GLEEPFNGLENABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); + GLEE_EXTERN GLEEPFNGLENABLECLIENTSTATEINDEXEDEXTPROC GLeeFuncPtr_glEnableClientStateIndexedEXT; + #define glEnableClientStateIndexedEXT GLeeFuncPtr_glEnableClientStateIndexedEXT +#endif +#ifndef GLEE_H_DEFINED_glDisableClientStateIndexedEXT +#define GLEE_H_DEFINED_glDisableClientStateIndexedEXT + typedef void (APIENTRYP GLEEPFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); + GLEE_EXTERN GLEEPFNGLDISABLECLIENTSTATEINDEXEDEXTPROC GLeeFuncPtr_glDisableClientStateIndexedEXT; + #define glDisableClientStateIndexedEXT GLeeFuncPtr_glDisableClientStateIndexedEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexCoordPointerEXT +#define GLEE_H_DEFINED_glMultiTexCoordPointerEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLMULTITEXCOORDPOINTEREXTPROC GLeeFuncPtr_glMultiTexCoordPointerEXT; + #define glMultiTexCoordPointerEXT GLeeFuncPtr_glMultiTexCoordPointerEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexEnvfEXT +#define GLEE_H_DEFINED_glMultiTexEnvfEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLMULTITEXENVFEXTPROC GLeeFuncPtr_glMultiTexEnvfEXT; + #define glMultiTexEnvfEXT GLeeFuncPtr_glMultiTexEnvfEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexEnvfvEXT +#define GLEE_H_DEFINED_glMultiTexEnvfvEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLMULTITEXENVFVEXTPROC GLeeFuncPtr_glMultiTexEnvfvEXT; + #define glMultiTexEnvfvEXT GLeeFuncPtr_glMultiTexEnvfvEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexEnviEXT +#define GLEE_H_DEFINED_glMultiTexEnviEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLMULTITEXENVIEXTPROC GLeeFuncPtr_glMultiTexEnviEXT; + #define glMultiTexEnviEXT GLeeFuncPtr_glMultiTexEnviEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexEnvivEXT +#define GLEE_H_DEFINED_glMultiTexEnvivEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLMULTITEXENVIVEXTPROC GLeeFuncPtr_glMultiTexEnvivEXT; + #define glMultiTexEnvivEXT GLeeFuncPtr_glMultiTexEnvivEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexGendEXT +#define GLEE_H_DEFINED_glMultiTexGendEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXGENDEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble param); + GLEE_EXTERN GLEEPFNGLMULTITEXGENDEXTPROC GLeeFuncPtr_glMultiTexGendEXT; + #define glMultiTexGendEXT GLeeFuncPtr_glMultiTexGendEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexGendvEXT +#define GLEE_H_DEFINED_glMultiTexGendvEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLdouble * params); + GLEE_EXTERN GLEEPFNGLMULTITEXGENDVEXTPROC GLeeFuncPtr_glMultiTexGendvEXT; + #define glMultiTexGendvEXT GLeeFuncPtr_glMultiTexGendvEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexGenfEXT +#define GLEE_H_DEFINED_glMultiTexGenfEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLMULTITEXGENFEXTPROC GLeeFuncPtr_glMultiTexGenfEXT; + #define glMultiTexGenfEXT GLeeFuncPtr_glMultiTexGenfEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexGenfvEXT +#define GLEE_H_DEFINED_glMultiTexGenfvEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLMULTITEXGENFVEXTPROC GLeeFuncPtr_glMultiTexGenfvEXT; + #define glMultiTexGenfvEXT GLeeFuncPtr_glMultiTexGenfvEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexGeniEXT +#define GLEE_H_DEFINED_glMultiTexGeniEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLMULTITEXGENIEXTPROC GLeeFuncPtr_glMultiTexGeniEXT; + #define glMultiTexGeniEXT GLeeFuncPtr_glMultiTexGeniEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexGenivEXT +#define GLEE_H_DEFINED_glMultiTexGenivEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLMULTITEXGENIVEXTPROC GLeeFuncPtr_glMultiTexGenivEXT; + #define glMultiTexGenivEXT GLeeFuncPtr_glMultiTexGenivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetMultiTexEnvfvEXT +#define GLEE_H_DEFINED_glGetMultiTexEnvfvEXT + typedef void (APIENTRYP GLEEPFNGLGETMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETMULTITEXENVFVEXTPROC GLeeFuncPtr_glGetMultiTexEnvfvEXT; + #define glGetMultiTexEnvfvEXT GLeeFuncPtr_glGetMultiTexEnvfvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetMultiTexEnvivEXT +#define GLEE_H_DEFINED_glGetMultiTexEnvivEXT + typedef void (APIENTRYP GLEEPFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETMULTITEXENVIVEXTPROC GLeeFuncPtr_glGetMultiTexEnvivEXT; + #define glGetMultiTexEnvivEXT GLeeFuncPtr_glGetMultiTexEnvivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetMultiTexGendvEXT +#define GLEE_H_DEFINED_glGetMultiTexGendvEXT + typedef void (APIENTRYP GLEEPFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble * params); + GLEE_EXTERN GLEEPFNGLGETMULTITEXGENDVEXTPROC GLeeFuncPtr_glGetMultiTexGendvEXT; + #define glGetMultiTexGendvEXT GLeeFuncPtr_glGetMultiTexGendvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetMultiTexGenfvEXT +#define GLEE_H_DEFINED_glGetMultiTexGenfvEXT + typedef void (APIENTRYP GLEEPFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETMULTITEXGENFVEXTPROC GLeeFuncPtr_glGetMultiTexGenfvEXT; + #define glGetMultiTexGenfvEXT GLeeFuncPtr_glGetMultiTexGenfvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetMultiTexGenivEXT +#define GLEE_H_DEFINED_glGetMultiTexGenivEXT + typedef void (APIENTRYP GLEEPFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETMULTITEXGENIVEXTPROC GLeeFuncPtr_glGetMultiTexGenivEXT; + #define glGetMultiTexGenivEXT GLeeFuncPtr_glGetMultiTexGenivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetFloatIndexedvEXT +#define GLEE_H_DEFINED_glGetFloatIndexedvEXT + typedef void (APIENTRYP GLEEPFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat * data); + GLEE_EXTERN GLEEPFNGLGETFLOATINDEXEDVEXTPROC GLeeFuncPtr_glGetFloatIndexedvEXT; + #define glGetFloatIndexedvEXT GLeeFuncPtr_glGetFloatIndexedvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetDoubleIndexedvEXT +#define GLEE_H_DEFINED_glGetDoubleIndexedvEXT + typedef void (APIENTRYP GLEEPFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble * data); + GLEE_EXTERN GLEEPFNGLGETDOUBLEINDEXEDVEXTPROC GLeeFuncPtr_glGetDoubleIndexedvEXT; + #define glGetDoubleIndexedvEXT GLeeFuncPtr_glGetDoubleIndexedvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetPointerIndexedvEXT +#define GLEE_H_DEFINED_glGetPointerIndexedvEXT + typedef void (APIENTRYP GLEEPFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLvoid* * data); + GLEE_EXTERN GLEEPFNGLGETPOINTERINDEXEDVEXTPROC GLeeFuncPtr_glGetPointerIndexedvEXT; + #define glGetPointerIndexedvEXT GLeeFuncPtr_glGetPointerIndexedvEXT +#endif +#ifndef GLEE_H_DEFINED_glCompressedTextureImage3DEXT +#define GLEE_H_DEFINED_glCompressedTextureImage3DEXT + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid * bits); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC GLeeFuncPtr_glCompressedTextureImage3DEXT; + #define glCompressedTextureImage3DEXT GLeeFuncPtr_glCompressedTextureImage3DEXT +#endif +#ifndef GLEE_H_DEFINED_glCompressedTextureImage2DEXT +#define GLEE_H_DEFINED_glCompressedTextureImage2DEXT + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * bits); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC GLeeFuncPtr_glCompressedTextureImage2DEXT; + #define glCompressedTextureImage2DEXT GLeeFuncPtr_glCompressedTextureImage2DEXT +#endif +#ifndef GLEE_H_DEFINED_glCompressedTextureImage1DEXT +#define GLEE_H_DEFINED_glCompressedTextureImage1DEXT + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid * bits); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC GLeeFuncPtr_glCompressedTextureImage1DEXT; + #define glCompressedTextureImage1DEXT GLeeFuncPtr_glCompressedTextureImage1DEXT +#endif +#ifndef GLEE_H_DEFINED_glCompressedTextureSubImage3DEXT +#define GLEE_H_DEFINED_glCompressedTextureSubImage3DEXT + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid * bits); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC GLeeFuncPtr_glCompressedTextureSubImage3DEXT; + #define glCompressedTextureSubImage3DEXT GLeeFuncPtr_glCompressedTextureSubImage3DEXT +#endif +#ifndef GLEE_H_DEFINED_glCompressedTextureSubImage2DEXT +#define GLEE_H_DEFINED_glCompressedTextureSubImage2DEXT + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid * bits); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC GLeeFuncPtr_glCompressedTextureSubImage2DEXT; + #define glCompressedTextureSubImage2DEXT GLeeFuncPtr_glCompressedTextureSubImage2DEXT +#endif +#ifndef GLEE_H_DEFINED_glCompressedTextureSubImage1DEXT +#define GLEE_H_DEFINED_glCompressedTextureSubImage1DEXT + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid * bits); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC GLeeFuncPtr_glCompressedTextureSubImage1DEXT; + #define glCompressedTextureSubImage1DEXT GLeeFuncPtr_glCompressedTextureSubImage1DEXT +#endif +#ifndef GLEE_H_DEFINED_glGetCompressedTextureImageEXT +#define GLEE_H_DEFINED_glGetCompressedTextureImageEXT + typedef void (APIENTRYP GLEEPFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint lod, GLvoid * img); + GLEE_EXTERN GLEEPFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC GLeeFuncPtr_glGetCompressedTextureImageEXT; + #define glGetCompressedTextureImageEXT GLeeFuncPtr_glGetCompressedTextureImageEXT +#endif +#ifndef GLEE_H_DEFINED_glCompressedMultiTexImage3DEXT +#define GLEE_H_DEFINED_glCompressedMultiTexImage3DEXT + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid * bits); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC GLeeFuncPtr_glCompressedMultiTexImage3DEXT; + #define glCompressedMultiTexImage3DEXT GLeeFuncPtr_glCompressedMultiTexImage3DEXT +#endif +#ifndef GLEE_H_DEFINED_glCompressedMultiTexImage2DEXT +#define GLEE_H_DEFINED_glCompressedMultiTexImage2DEXT + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * bits); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC GLeeFuncPtr_glCompressedMultiTexImage2DEXT; + #define glCompressedMultiTexImage2DEXT GLeeFuncPtr_glCompressedMultiTexImage2DEXT +#endif +#ifndef GLEE_H_DEFINED_glCompressedMultiTexImage1DEXT +#define GLEE_H_DEFINED_glCompressedMultiTexImage1DEXT + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid * bits); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC GLeeFuncPtr_glCompressedMultiTexImage1DEXT; + #define glCompressedMultiTexImage1DEXT GLeeFuncPtr_glCompressedMultiTexImage1DEXT +#endif +#ifndef GLEE_H_DEFINED_glCompressedMultiTexSubImage3DEXT +#define GLEE_H_DEFINED_glCompressedMultiTexSubImage3DEXT + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid * bits); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC GLeeFuncPtr_glCompressedMultiTexSubImage3DEXT; + #define glCompressedMultiTexSubImage3DEXT GLeeFuncPtr_glCompressedMultiTexSubImage3DEXT +#endif +#ifndef GLEE_H_DEFINED_glCompressedMultiTexSubImage2DEXT +#define GLEE_H_DEFINED_glCompressedMultiTexSubImage2DEXT + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid * bits); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC GLeeFuncPtr_glCompressedMultiTexSubImage2DEXT; + #define glCompressedMultiTexSubImage2DEXT GLeeFuncPtr_glCompressedMultiTexSubImage2DEXT +#endif +#ifndef GLEE_H_DEFINED_glCompressedMultiTexSubImage1DEXT +#define GLEE_H_DEFINED_glCompressedMultiTexSubImage1DEXT + typedef void (APIENTRYP GLEEPFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid * bits); + GLEE_EXTERN GLEEPFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC GLeeFuncPtr_glCompressedMultiTexSubImage1DEXT; + #define glCompressedMultiTexSubImage1DEXT GLeeFuncPtr_glCompressedMultiTexSubImage1DEXT +#endif +#ifndef GLEE_H_DEFINED_glGetCompressedMultiTexImageEXT +#define GLEE_H_DEFINED_glGetCompressedMultiTexImageEXT + typedef void (APIENTRYP GLEEPFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint lod, GLvoid * img); + GLEE_EXTERN GLEEPFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC GLeeFuncPtr_glGetCompressedMultiTexImageEXT; + #define glGetCompressedMultiTexImageEXT GLeeFuncPtr_glGetCompressedMultiTexImageEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedProgramStringEXT +#define GLEE_H_DEFINED_glNamedProgramStringEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const GLvoid * string); + GLEE_EXTERN GLEEPFNGLNAMEDPROGRAMSTRINGEXTPROC GLeeFuncPtr_glNamedProgramStringEXT; + #define glNamedProgramStringEXT GLeeFuncPtr_glNamedProgramStringEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedProgramLocalParameter4dEXT +#define GLEE_H_DEFINED_glNamedProgramLocalParameter4dEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + GLEE_EXTERN GLEEPFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC GLeeFuncPtr_glNamedProgramLocalParameter4dEXT; + #define glNamedProgramLocalParameter4dEXT GLeeFuncPtr_glNamedProgramLocalParameter4dEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedProgramLocalParameter4dvEXT +#define GLEE_H_DEFINED_glNamedProgramLocalParameter4dvEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLdouble * params); + GLEE_EXTERN GLEEPFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC GLeeFuncPtr_glNamedProgramLocalParameter4dvEXT; + #define glNamedProgramLocalParameter4dvEXT GLeeFuncPtr_glNamedProgramLocalParameter4dvEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedProgramLocalParameter4fEXT +#define GLEE_H_DEFINED_glNamedProgramLocalParameter4fEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + GLEE_EXTERN GLEEPFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC GLeeFuncPtr_glNamedProgramLocalParameter4fEXT; + #define glNamedProgramLocalParameter4fEXT GLeeFuncPtr_glNamedProgramLocalParameter4fEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedProgramLocalParameter4fvEXT +#define GLEE_H_DEFINED_glNamedProgramLocalParameter4fvEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC GLeeFuncPtr_glNamedProgramLocalParameter4fvEXT; + #define glNamedProgramLocalParameter4fvEXT GLeeFuncPtr_glNamedProgramLocalParameter4fvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetNamedProgramLocalParameterdvEXT +#define GLEE_H_DEFINED_glGetNamedProgramLocalParameterdvEXT + typedef void (APIENTRYP GLEEPFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble * params); + GLEE_EXTERN GLEEPFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC GLeeFuncPtr_glGetNamedProgramLocalParameterdvEXT; + #define glGetNamedProgramLocalParameterdvEXT GLeeFuncPtr_glGetNamedProgramLocalParameterdvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetNamedProgramLocalParameterfvEXT +#define GLEE_H_DEFINED_glGetNamedProgramLocalParameterfvEXT + typedef void (APIENTRYP GLEEPFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC GLeeFuncPtr_glGetNamedProgramLocalParameterfvEXT; + #define glGetNamedProgramLocalParameterfvEXT GLeeFuncPtr_glGetNamedProgramLocalParameterfvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetNamedProgramivEXT +#define GLEE_H_DEFINED_glGetNamedProgramivEXT + typedef void (APIENTRYP GLEEPFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETNAMEDPROGRAMIVEXTPROC GLeeFuncPtr_glGetNamedProgramivEXT; + #define glGetNamedProgramivEXT GLeeFuncPtr_glGetNamedProgramivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetNamedProgramStringEXT +#define GLEE_H_DEFINED_glGetNamedProgramStringEXT + typedef void (APIENTRYP GLEEPFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, GLvoid * string); + GLEE_EXTERN GLEEPFNGLGETNAMEDPROGRAMSTRINGEXTPROC GLeeFuncPtr_glGetNamedProgramStringEXT; + #define glGetNamedProgramStringEXT GLeeFuncPtr_glGetNamedProgramStringEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedProgramLocalParameters4fvEXT +#define GLEE_H_DEFINED_glNamedProgramLocalParameters4fvEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC GLeeFuncPtr_glNamedProgramLocalParameters4fvEXT; + #define glNamedProgramLocalParameters4fvEXT GLeeFuncPtr_glNamedProgramLocalParameters4fvEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedProgramLocalParameterI4iEXT +#define GLEE_H_DEFINED_glNamedProgramLocalParameterI4iEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); + GLEE_EXTERN GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC GLeeFuncPtr_glNamedProgramLocalParameterI4iEXT; + #define glNamedProgramLocalParameterI4iEXT GLeeFuncPtr_glNamedProgramLocalParameterI4iEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedProgramLocalParameterI4ivEXT +#define GLEE_H_DEFINED_glNamedProgramLocalParameterI4ivEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLint * params); + GLEE_EXTERN GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC GLeeFuncPtr_glNamedProgramLocalParameterI4ivEXT; + #define glNamedProgramLocalParameterI4ivEXT GLeeFuncPtr_glNamedProgramLocalParameterI4ivEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedProgramLocalParametersI4ivEXT +#define GLEE_H_DEFINED_glNamedProgramLocalParametersI4ivEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint * params); + GLEE_EXTERN GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC GLeeFuncPtr_glNamedProgramLocalParametersI4ivEXT; + #define glNamedProgramLocalParametersI4ivEXT GLeeFuncPtr_glNamedProgramLocalParametersI4ivEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedProgramLocalParameterI4uiEXT +#define GLEE_H_DEFINED_glNamedProgramLocalParameterI4uiEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); + GLEE_EXTERN GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC GLeeFuncPtr_glNamedProgramLocalParameterI4uiEXT; + #define glNamedProgramLocalParameterI4uiEXT GLeeFuncPtr_glNamedProgramLocalParameterI4uiEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedProgramLocalParameterI4uivEXT +#define GLEE_H_DEFINED_glNamedProgramLocalParameterI4uivEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLuint * params); + GLEE_EXTERN GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC GLeeFuncPtr_glNamedProgramLocalParameterI4uivEXT; + #define glNamedProgramLocalParameterI4uivEXT GLeeFuncPtr_glNamedProgramLocalParameterI4uivEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedProgramLocalParametersI4uivEXT +#define GLEE_H_DEFINED_glNamedProgramLocalParametersI4uivEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint * params); + GLEE_EXTERN GLEEPFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC GLeeFuncPtr_glNamedProgramLocalParametersI4uivEXT; + #define glNamedProgramLocalParametersI4uivEXT GLeeFuncPtr_glNamedProgramLocalParametersI4uivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetNamedProgramLocalParameterIivEXT +#define GLEE_H_DEFINED_glGetNamedProgramLocalParameterIivEXT + typedef void (APIENTRYP GLEEPFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint * params); + GLEE_EXTERN GLEEPFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC GLeeFuncPtr_glGetNamedProgramLocalParameterIivEXT; + #define glGetNamedProgramLocalParameterIivEXT GLeeFuncPtr_glGetNamedProgramLocalParameterIivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetNamedProgramLocalParameterIuivEXT +#define GLEE_H_DEFINED_glGetNamedProgramLocalParameterIuivEXT + typedef void (APIENTRYP GLEEPFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint * params); + GLEE_EXTERN GLEEPFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC GLeeFuncPtr_glGetNamedProgramLocalParameterIuivEXT; + #define glGetNamedProgramLocalParameterIuivEXT GLeeFuncPtr_glGetNamedProgramLocalParameterIuivEXT +#endif +#ifndef GLEE_H_DEFINED_glTextureParameterIivEXT +#define GLEE_H_DEFINED_glTextureParameterIivEXT + typedef void (APIENTRYP GLEEPFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLTEXTUREPARAMETERIIVEXTPROC GLeeFuncPtr_glTextureParameterIivEXT; + #define glTextureParameterIivEXT GLeeFuncPtr_glTextureParameterIivEXT +#endif +#ifndef GLEE_H_DEFINED_glTextureParameterIuivEXT +#define GLEE_H_DEFINED_glTextureParameterIuivEXT + typedef void (APIENTRYP GLEEPFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint * params); + GLEE_EXTERN GLEEPFNGLTEXTUREPARAMETERIUIVEXTPROC GLeeFuncPtr_glTextureParameterIuivEXT; + #define glTextureParameterIuivEXT GLeeFuncPtr_glTextureParameterIuivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetTextureParameterIivEXT +#define GLEE_H_DEFINED_glGetTextureParameterIivEXT + typedef void (APIENTRYP GLEEPFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETTEXTUREPARAMETERIIVEXTPROC GLeeFuncPtr_glGetTextureParameterIivEXT; + #define glGetTextureParameterIivEXT GLeeFuncPtr_glGetTextureParameterIivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetTextureParameterIuivEXT +#define GLEE_H_DEFINED_glGetTextureParameterIuivEXT + typedef void (APIENTRYP GLEEPFNGLGETTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLuint * params); + GLEE_EXTERN GLEEPFNGLGETTEXTUREPARAMETERIUIVEXTPROC GLeeFuncPtr_glGetTextureParameterIuivEXT; + #define glGetTextureParameterIuivEXT GLeeFuncPtr_glGetTextureParameterIuivEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexParameterIivEXT +#define GLEE_H_DEFINED_glMultiTexParameterIivEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLMULTITEXPARAMETERIIVEXTPROC GLeeFuncPtr_glMultiTexParameterIivEXT; + #define glMultiTexParameterIivEXT GLeeFuncPtr_glMultiTexParameterIivEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexParameterIuivEXT +#define GLEE_H_DEFINED_glMultiTexParameterIuivEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint * params); + GLEE_EXTERN GLEEPFNGLMULTITEXPARAMETERIUIVEXTPROC GLeeFuncPtr_glMultiTexParameterIuivEXT; + #define glMultiTexParameterIuivEXT GLeeFuncPtr_glMultiTexParameterIuivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetMultiTexParameterIivEXT +#define GLEE_H_DEFINED_glGetMultiTexParameterIivEXT + typedef void (APIENTRYP GLEEPFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETMULTITEXPARAMETERIIVEXTPROC GLeeFuncPtr_glGetMultiTexParameterIivEXT; + #define glGetMultiTexParameterIivEXT GLeeFuncPtr_glGetMultiTexParameterIivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetMultiTexParameterIuivEXT +#define GLEE_H_DEFINED_glGetMultiTexParameterIuivEXT + typedef void (APIENTRYP GLEEPFNGLGETMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLuint * params); + GLEE_EXTERN GLEEPFNGLGETMULTITEXPARAMETERIUIVEXTPROC GLeeFuncPtr_glGetMultiTexParameterIuivEXT; + #define glGetMultiTexParameterIuivEXT GLeeFuncPtr_glGetMultiTexParameterIuivEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform1fEXT +#define GLEE_H_DEFINED_glProgramUniform1fEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM1FEXTPROC GLeeFuncPtr_glProgramUniform1fEXT; + #define glProgramUniform1fEXT GLeeFuncPtr_glProgramUniform1fEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform2fEXT +#define GLEE_H_DEFINED_glProgramUniform2fEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM2FEXTPROC GLeeFuncPtr_glProgramUniform2fEXT; + #define glProgramUniform2fEXT GLeeFuncPtr_glProgramUniform2fEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform3fEXT +#define GLEE_H_DEFINED_glProgramUniform3fEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM3FEXTPROC GLeeFuncPtr_glProgramUniform3fEXT; + #define glProgramUniform3fEXT GLeeFuncPtr_glProgramUniform3fEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform4fEXT +#define GLEE_H_DEFINED_glProgramUniform4fEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM4FEXTPROC GLeeFuncPtr_glProgramUniform4fEXT; + #define glProgramUniform4fEXT GLeeFuncPtr_glProgramUniform4fEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform1iEXT +#define GLEE_H_DEFINED_glProgramUniform1iEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM1IEXTPROC GLeeFuncPtr_glProgramUniform1iEXT; + #define glProgramUniform1iEXT GLeeFuncPtr_glProgramUniform1iEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform2iEXT +#define GLEE_H_DEFINED_glProgramUniform2iEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM2IEXTPROC GLeeFuncPtr_glProgramUniform2iEXT; + #define glProgramUniform2iEXT GLeeFuncPtr_glProgramUniform2iEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform3iEXT +#define GLEE_H_DEFINED_glProgramUniform3iEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM3IEXTPROC GLeeFuncPtr_glProgramUniform3iEXT; + #define glProgramUniform3iEXT GLeeFuncPtr_glProgramUniform3iEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform4iEXT +#define GLEE_H_DEFINED_glProgramUniform4iEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM4IEXTPROC GLeeFuncPtr_glProgramUniform4iEXT; + #define glProgramUniform4iEXT GLeeFuncPtr_glProgramUniform4iEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform1fvEXT +#define GLEE_H_DEFINED_glProgramUniform1fvEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM1FVEXTPROC GLeeFuncPtr_glProgramUniform1fvEXT; + #define glProgramUniform1fvEXT GLeeFuncPtr_glProgramUniform1fvEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform2fvEXT +#define GLEE_H_DEFINED_glProgramUniform2fvEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM2FVEXTPROC GLeeFuncPtr_glProgramUniform2fvEXT; + #define glProgramUniform2fvEXT GLeeFuncPtr_glProgramUniform2fvEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform3fvEXT +#define GLEE_H_DEFINED_glProgramUniform3fvEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM3FVEXTPROC GLeeFuncPtr_glProgramUniform3fvEXT; + #define glProgramUniform3fvEXT GLeeFuncPtr_glProgramUniform3fvEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform4fvEXT +#define GLEE_H_DEFINED_glProgramUniform4fvEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM4FVEXTPROC GLeeFuncPtr_glProgramUniform4fvEXT; + #define glProgramUniform4fvEXT GLeeFuncPtr_glProgramUniform4fvEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform1ivEXT +#define GLEE_H_DEFINED_glProgramUniform1ivEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM1IVEXTPROC GLeeFuncPtr_glProgramUniform1ivEXT; + #define glProgramUniform1ivEXT GLeeFuncPtr_glProgramUniform1ivEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform2ivEXT +#define GLEE_H_DEFINED_glProgramUniform2ivEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM2IVEXTPROC GLeeFuncPtr_glProgramUniform2ivEXT; + #define glProgramUniform2ivEXT GLeeFuncPtr_glProgramUniform2ivEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform3ivEXT +#define GLEE_H_DEFINED_glProgramUniform3ivEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM3IVEXTPROC GLeeFuncPtr_glProgramUniform3ivEXT; + #define glProgramUniform3ivEXT GLeeFuncPtr_glProgramUniform3ivEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform4ivEXT +#define GLEE_H_DEFINED_glProgramUniform4ivEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM4IVEXTPROC GLeeFuncPtr_glProgramUniform4ivEXT; + #define glProgramUniform4ivEXT GLeeFuncPtr_glProgramUniform4ivEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniformMatrix2fvEXT +#define GLEE_H_DEFINED_glProgramUniformMatrix2fvEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix2fvEXT; + #define glProgramUniformMatrix2fvEXT GLeeFuncPtr_glProgramUniformMatrix2fvEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniformMatrix3fvEXT +#define GLEE_H_DEFINED_glProgramUniformMatrix3fvEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix3fvEXT; + #define glProgramUniformMatrix3fvEXT GLeeFuncPtr_glProgramUniformMatrix3fvEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniformMatrix4fvEXT +#define GLEE_H_DEFINED_glProgramUniformMatrix4fvEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix4fvEXT; + #define glProgramUniformMatrix4fvEXT GLeeFuncPtr_glProgramUniformMatrix4fvEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniformMatrix2x3fvEXT +#define GLEE_H_DEFINED_glProgramUniformMatrix2x3fvEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix2x3fvEXT; + #define glProgramUniformMatrix2x3fvEXT GLeeFuncPtr_glProgramUniformMatrix2x3fvEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniformMatrix3x2fvEXT +#define GLEE_H_DEFINED_glProgramUniformMatrix3x2fvEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix3x2fvEXT; + #define glProgramUniformMatrix3x2fvEXT GLeeFuncPtr_glProgramUniformMatrix3x2fvEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniformMatrix2x4fvEXT +#define GLEE_H_DEFINED_glProgramUniformMatrix2x4fvEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix2x4fvEXT; + #define glProgramUniformMatrix2x4fvEXT GLeeFuncPtr_glProgramUniformMatrix2x4fvEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniformMatrix4x2fvEXT +#define GLEE_H_DEFINED_glProgramUniformMatrix4x2fvEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix4x2fvEXT; + #define glProgramUniformMatrix4x2fvEXT GLeeFuncPtr_glProgramUniformMatrix4x2fvEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniformMatrix3x4fvEXT +#define GLEE_H_DEFINED_glProgramUniformMatrix3x4fvEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix3x4fvEXT; + #define glProgramUniformMatrix3x4fvEXT GLeeFuncPtr_glProgramUniformMatrix3x4fvEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniformMatrix4x3fvEXT +#define GLEE_H_DEFINED_glProgramUniformMatrix4x3fvEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC GLeeFuncPtr_glProgramUniformMatrix4x3fvEXT; + #define glProgramUniformMatrix4x3fvEXT GLeeFuncPtr_glProgramUniformMatrix4x3fvEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform1uiEXT +#define GLEE_H_DEFINED_glProgramUniform1uiEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM1UIEXTPROC GLeeFuncPtr_glProgramUniform1uiEXT; + #define glProgramUniform1uiEXT GLeeFuncPtr_glProgramUniform1uiEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform2uiEXT +#define GLEE_H_DEFINED_glProgramUniform2uiEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM2UIEXTPROC GLeeFuncPtr_glProgramUniform2uiEXT; + #define glProgramUniform2uiEXT GLeeFuncPtr_glProgramUniform2uiEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform3uiEXT +#define GLEE_H_DEFINED_glProgramUniform3uiEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM3UIEXTPROC GLeeFuncPtr_glProgramUniform3uiEXT; + #define glProgramUniform3uiEXT GLeeFuncPtr_glProgramUniform3uiEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform4uiEXT +#define GLEE_H_DEFINED_glProgramUniform4uiEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM4UIEXTPROC GLeeFuncPtr_glProgramUniform4uiEXT; + #define glProgramUniform4uiEXT GLeeFuncPtr_glProgramUniform4uiEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform1uivEXT +#define GLEE_H_DEFINED_glProgramUniform1uivEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM1UIVEXTPROC GLeeFuncPtr_glProgramUniform1uivEXT; + #define glProgramUniform1uivEXT GLeeFuncPtr_glProgramUniform1uivEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform2uivEXT +#define GLEE_H_DEFINED_glProgramUniform2uivEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM2UIVEXTPROC GLeeFuncPtr_glProgramUniform2uivEXT; + #define glProgramUniform2uivEXT GLeeFuncPtr_glProgramUniform2uivEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform3uivEXT +#define GLEE_H_DEFINED_glProgramUniform3uivEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM3UIVEXTPROC GLeeFuncPtr_glProgramUniform3uivEXT; + #define glProgramUniform3uivEXT GLeeFuncPtr_glProgramUniform3uivEXT +#endif +#ifndef GLEE_H_DEFINED_glProgramUniform4uivEXT +#define GLEE_H_DEFINED_glProgramUniform4uivEXT + typedef void (APIENTRYP GLEEPFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint * value); + GLEE_EXTERN GLEEPFNGLPROGRAMUNIFORM4UIVEXTPROC GLeeFuncPtr_glProgramUniform4uivEXT; + #define glProgramUniform4uivEXT GLeeFuncPtr_glProgramUniform4uivEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedBufferDataEXT +#define GLEE_H_DEFINED_glNamedBufferDataEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const GLvoid * data, GLenum usage); + GLEE_EXTERN GLEEPFNGLNAMEDBUFFERDATAEXTPROC GLeeFuncPtr_glNamedBufferDataEXT; + #define glNamedBufferDataEXT GLeeFuncPtr_glNamedBufferDataEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedBufferSubDataEXT +#define GLEE_H_DEFINED_glNamedBufferSubDataEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid * data); + GLEE_EXTERN GLEEPFNGLNAMEDBUFFERSUBDATAEXTPROC GLeeFuncPtr_glNamedBufferSubDataEXT; + #define glNamedBufferSubDataEXT GLeeFuncPtr_glNamedBufferSubDataEXT +#endif +#ifndef GLEE_H_DEFINED_glMapNamedBufferEXT +#define GLEE_H_DEFINED_glMapNamedBufferEXT + typedef GLvoid* (APIENTRYP GLEEPFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access); + GLEE_EXTERN GLEEPFNGLMAPNAMEDBUFFEREXTPROC GLeeFuncPtr_glMapNamedBufferEXT; + #define glMapNamedBufferEXT GLeeFuncPtr_glMapNamedBufferEXT +#endif +#ifndef GLEE_H_DEFINED_glUnmapNamedBufferEXT +#define GLEE_H_DEFINED_glUnmapNamedBufferEXT + typedef GLboolean (APIENTRYP GLEEPFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer); + GLEE_EXTERN GLEEPFNGLUNMAPNAMEDBUFFEREXTPROC GLeeFuncPtr_glUnmapNamedBufferEXT; + #define glUnmapNamedBufferEXT GLeeFuncPtr_glUnmapNamedBufferEXT +#endif +#ifndef GLEE_H_DEFINED_glGetNamedBufferParameterivEXT +#define GLEE_H_DEFINED_glGetNamedBufferParameterivEXT + typedef void (APIENTRYP GLEEPFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC GLeeFuncPtr_glGetNamedBufferParameterivEXT; + #define glGetNamedBufferParameterivEXT GLeeFuncPtr_glGetNamedBufferParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetNamedBufferPointervEXT +#define GLEE_H_DEFINED_glGetNamedBufferPointervEXT + typedef void (APIENTRYP GLEEPFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, GLvoid* * params); + GLEE_EXTERN GLEEPFNGLGETNAMEDBUFFERPOINTERVEXTPROC GLeeFuncPtr_glGetNamedBufferPointervEXT; + #define glGetNamedBufferPointervEXT GLeeFuncPtr_glGetNamedBufferPointervEXT +#endif +#ifndef GLEE_H_DEFINED_glGetNamedBufferSubDataEXT +#define GLEE_H_DEFINED_glGetNamedBufferSubDataEXT + typedef void (APIENTRYP GLEEPFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLvoid * data); + GLEE_EXTERN GLEEPFNGLGETNAMEDBUFFERSUBDATAEXTPROC GLeeFuncPtr_glGetNamedBufferSubDataEXT; + #define glGetNamedBufferSubDataEXT GLeeFuncPtr_glGetNamedBufferSubDataEXT +#endif +#ifndef GLEE_H_DEFINED_glTextureBufferEXT +#define GLEE_H_DEFINED_glTextureBufferEXT + typedef void (APIENTRYP GLEEPFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer); + GLEE_EXTERN GLEEPFNGLTEXTUREBUFFEREXTPROC GLeeFuncPtr_glTextureBufferEXT; + #define glTextureBufferEXT GLeeFuncPtr_glTextureBufferEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexBufferEXT +#define GLEE_H_DEFINED_glMultiTexBufferEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer); + GLEE_EXTERN GLEEPFNGLMULTITEXBUFFEREXTPROC GLeeFuncPtr_glMultiTexBufferEXT; + #define glMultiTexBufferEXT GLeeFuncPtr_glMultiTexBufferEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedRenderbufferStorageEXT +#define GLEE_H_DEFINED_glNamedRenderbufferStorageEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC GLeeFuncPtr_glNamedRenderbufferStorageEXT; + #define glNamedRenderbufferStorageEXT GLeeFuncPtr_glNamedRenderbufferStorageEXT +#endif +#ifndef GLEE_H_DEFINED_glGetNamedRenderbufferParameterivEXT +#define GLEE_H_DEFINED_glGetNamedRenderbufferParameterivEXT + typedef void (APIENTRYP GLEEPFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC GLeeFuncPtr_glGetNamedRenderbufferParameterivEXT; + #define glGetNamedRenderbufferParameterivEXT GLeeFuncPtr_glGetNamedRenderbufferParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glCheckNamedFramebufferStatusEXT +#define GLEE_H_DEFINED_glCheckNamedFramebufferStatusEXT + typedef GLenum (APIENTRYP GLEEPFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target); + GLEE_EXTERN GLEEPFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC GLeeFuncPtr_glCheckNamedFramebufferStatusEXT; + #define glCheckNamedFramebufferStatusEXT GLeeFuncPtr_glCheckNamedFramebufferStatusEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedFramebufferTexture1DEXT +#define GLEE_H_DEFINED_glNamedFramebufferTexture1DEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + GLEE_EXTERN GLEEPFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC GLeeFuncPtr_glNamedFramebufferTexture1DEXT; + #define glNamedFramebufferTexture1DEXT GLeeFuncPtr_glNamedFramebufferTexture1DEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedFramebufferTexture2DEXT +#define GLEE_H_DEFINED_glNamedFramebufferTexture2DEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + GLEE_EXTERN GLEEPFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC GLeeFuncPtr_glNamedFramebufferTexture2DEXT; + #define glNamedFramebufferTexture2DEXT GLeeFuncPtr_glNamedFramebufferTexture2DEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedFramebufferTexture3DEXT +#define GLEE_H_DEFINED_glNamedFramebufferTexture3DEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); + GLEE_EXTERN GLEEPFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC GLeeFuncPtr_glNamedFramebufferTexture3DEXT; + #define glNamedFramebufferTexture3DEXT GLeeFuncPtr_glNamedFramebufferTexture3DEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedFramebufferRenderbufferEXT +#define GLEE_H_DEFINED_glNamedFramebufferRenderbufferEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + GLEE_EXTERN GLEEPFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC GLeeFuncPtr_glNamedFramebufferRenderbufferEXT; + #define glNamedFramebufferRenderbufferEXT GLeeFuncPtr_glNamedFramebufferRenderbufferEXT +#endif +#ifndef GLEE_H_DEFINED_glGetNamedFramebufferAttachmentParameterivEXT +#define GLEE_H_DEFINED_glGetNamedFramebufferAttachmentParameterivEXT + typedef void (APIENTRYP GLEEPFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC GLeeFuncPtr_glGetNamedFramebufferAttachmentParameterivEXT; + #define glGetNamedFramebufferAttachmentParameterivEXT GLeeFuncPtr_glGetNamedFramebufferAttachmentParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glGenerateTextureMipmapEXT +#define GLEE_H_DEFINED_glGenerateTextureMipmapEXT + typedef void (APIENTRYP GLEEPFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target); + GLEE_EXTERN GLEEPFNGLGENERATETEXTUREMIPMAPEXTPROC GLeeFuncPtr_glGenerateTextureMipmapEXT; + #define glGenerateTextureMipmapEXT GLeeFuncPtr_glGenerateTextureMipmapEXT +#endif +#ifndef GLEE_H_DEFINED_glGenerateMultiTexMipmapEXT +#define GLEE_H_DEFINED_glGenerateMultiTexMipmapEXT + typedef void (APIENTRYP GLEEPFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target); + GLEE_EXTERN GLEEPFNGLGENERATEMULTITEXMIPMAPEXTPROC GLeeFuncPtr_glGenerateMultiTexMipmapEXT; + #define glGenerateMultiTexMipmapEXT GLeeFuncPtr_glGenerateMultiTexMipmapEXT +#endif +#ifndef GLEE_H_DEFINED_glFramebufferDrawBufferEXT +#define GLEE_H_DEFINED_glFramebufferDrawBufferEXT + typedef void (APIENTRYP GLEEPFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERDRAWBUFFEREXTPROC GLeeFuncPtr_glFramebufferDrawBufferEXT; + #define glFramebufferDrawBufferEXT GLeeFuncPtr_glFramebufferDrawBufferEXT +#endif +#ifndef GLEE_H_DEFINED_glFramebufferDrawBuffersEXT +#define GLEE_H_DEFINED_glFramebufferDrawBuffersEXT + typedef void (APIENTRYP GLEEPFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuffer, GLsizei n, const GLenum * bufs); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC GLeeFuncPtr_glFramebufferDrawBuffersEXT; + #define glFramebufferDrawBuffersEXT GLeeFuncPtr_glFramebufferDrawBuffersEXT +#endif +#ifndef GLEE_H_DEFINED_glFramebufferReadBufferEXT +#define GLEE_H_DEFINED_glFramebufferReadBufferEXT + typedef void (APIENTRYP GLEEPFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERREADBUFFEREXTPROC GLeeFuncPtr_glFramebufferReadBufferEXT; + #define glFramebufferReadBufferEXT GLeeFuncPtr_glFramebufferReadBufferEXT +#endif +#ifndef GLEE_H_DEFINED_glGetFramebufferParameterivEXT +#define GLEE_H_DEFINED_glGetFramebufferParameterivEXT + typedef void (APIENTRYP GLEEPFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC GLeeFuncPtr_glGetFramebufferParameterivEXT; + #define glGetFramebufferParameterivEXT GLeeFuncPtr_glGetFramebufferParameterivEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedRenderbufferStorageMultisampleEXT +#define GLEE_H_DEFINED_glNamedRenderbufferStorageMultisampleEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC GLeeFuncPtr_glNamedRenderbufferStorageMultisampleEXT; + #define glNamedRenderbufferStorageMultisampleEXT GLeeFuncPtr_glNamedRenderbufferStorageMultisampleEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedRenderbufferStorageMultisampleCoverageEXT +#define GLEE_H_DEFINED_glNamedRenderbufferStorageMultisampleCoverageEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); + GLEE_EXTERN GLEEPFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC GLeeFuncPtr_glNamedRenderbufferStorageMultisampleCoverageEXT; + #define glNamedRenderbufferStorageMultisampleCoverageEXT GLeeFuncPtr_glNamedRenderbufferStorageMultisampleCoverageEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedFramebufferTextureEXT +#define GLEE_H_DEFINED_glNamedFramebufferTextureEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); + GLEE_EXTERN GLEEPFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC GLeeFuncPtr_glNamedFramebufferTextureEXT; + #define glNamedFramebufferTextureEXT GLeeFuncPtr_glNamedFramebufferTextureEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedFramebufferTextureLayerEXT +#define GLEE_H_DEFINED_glNamedFramebufferTextureLayerEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); + GLEE_EXTERN GLEEPFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC GLeeFuncPtr_glNamedFramebufferTextureLayerEXT; + #define glNamedFramebufferTextureLayerEXT GLeeFuncPtr_glNamedFramebufferTextureLayerEXT +#endif +#ifndef GLEE_H_DEFINED_glNamedFramebufferTextureFaceEXT +#define GLEE_H_DEFINED_glNamedFramebufferTextureFaceEXT + typedef void (APIENTRYP GLEEPFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face); + GLEE_EXTERN GLEEPFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC GLeeFuncPtr_glNamedFramebufferTextureFaceEXT; + #define glNamedFramebufferTextureFaceEXT GLeeFuncPtr_glNamedFramebufferTextureFaceEXT +#endif +#ifndef GLEE_H_DEFINED_glTextureRenderbufferEXT +#define GLEE_H_DEFINED_glTextureRenderbufferEXT + typedef void (APIENTRYP GLEEPFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer); + GLEE_EXTERN GLEEPFNGLTEXTURERENDERBUFFEREXTPROC GLeeFuncPtr_glTextureRenderbufferEXT; + #define glTextureRenderbufferEXT GLeeFuncPtr_glTextureRenderbufferEXT +#endif +#ifndef GLEE_H_DEFINED_glMultiTexRenderbufferEXT +#define GLEE_H_DEFINED_glMultiTexRenderbufferEXT + typedef void (APIENTRYP GLEEPFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer); + GLEE_EXTERN GLEEPFNGLMULTITEXRENDERBUFFEREXTPROC GLeeFuncPtr_glMultiTexRenderbufferEXT; + #define glMultiTexRenderbufferEXT GLeeFuncPtr_glMultiTexRenderbufferEXT +#endif +#endif + +/* GL_EXT_vertex_array_bgra */ + +#ifndef GL_EXT_vertex_array_bgra +#define GL_EXT_vertex_array_bgra 1 +#define __GLEE_GL_EXT_vertex_array_bgra 1 +/* Constants */ +#endif + +/* GL_EXT_texture_swizzle */ + +#ifndef GL_EXT_texture_swizzle +#define GL_EXT_texture_swizzle 1 +#define __GLEE_GL_EXT_texture_swizzle 1 +/* Constants */ +#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42 +#define GL_TEXTURE_SWIZZLE_G_EXT 0x8E43 +#define GL_TEXTURE_SWIZZLE_B_EXT 0x8E44 +#define GL_TEXTURE_SWIZZLE_A_EXT 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46 +#endif + +/* GL_NV_explicit_multisample */ + +#ifndef GL_NV_explicit_multisample +#define GL_NV_explicit_multisample 1 +#define __GLEE_GL_NV_explicit_multisample 1 +/* Constants */ +#define GL_SAMPLE_POSITION_NV 0x8E50 +#define GL_SAMPLE_MASK_NV 0x8E51 +#define GL_SAMPLE_MASK_VALUE_NV 0x8E52 +#define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53 +#define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54 +#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59 +#define GL_TEXTURE_RENDERBUFFER_NV 0x8E55 +#define GL_SAMPLER_RENDERBUFFER_NV 0x8E56 +#define GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57 +#define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58 +#ifndef GLEE_H_DEFINED_glGetMultisamplefvNV +#define GLEE_H_DEFINED_glGetMultisamplefvNV + typedef void (APIENTRYP GLEEPFNGLGETMULTISAMPLEFVNVPROC) (GLenum pname, GLuint index, GLfloat * val); + GLEE_EXTERN GLEEPFNGLGETMULTISAMPLEFVNVPROC GLeeFuncPtr_glGetMultisamplefvNV; + #define glGetMultisamplefvNV GLeeFuncPtr_glGetMultisamplefvNV +#endif +#ifndef GLEE_H_DEFINED_glSampleMaskIndexedNV +#define GLEE_H_DEFINED_glSampleMaskIndexedNV + typedef void (APIENTRYP GLEEPFNGLSAMPLEMASKINDEXEDNVPROC) (GLuint index, GLbitfield mask); + GLEE_EXTERN GLEEPFNGLSAMPLEMASKINDEXEDNVPROC GLeeFuncPtr_glSampleMaskIndexedNV; + #define glSampleMaskIndexedNV GLeeFuncPtr_glSampleMaskIndexedNV +#endif +#ifndef GLEE_H_DEFINED_glTexRenderbufferNV +#define GLEE_H_DEFINED_glTexRenderbufferNV + typedef void (APIENTRYP GLEEPFNGLTEXRENDERBUFFERNVPROC) (GLenum target, GLuint renderbuffer); + GLEE_EXTERN GLEEPFNGLTEXRENDERBUFFERNVPROC GLeeFuncPtr_glTexRenderbufferNV; + #define glTexRenderbufferNV GLeeFuncPtr_glTexRenderbufferNV +#endif +#endif + +/* GL_NV_transform_feedback2 */ + +#ifndef GL_NV_transform_feedback2 +#define GL_NV_transform_feedback2 1 +#define __GLEE_GL_NV_transform_feedback2 1 +/* Constants */ +#define GL_TRANSFORM_FEEDBACK_NV 0x8E22 +#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV 0x8E23 +#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING_NV 0x8E25 +#ifndef GLEE_H_DEFINED_glBindTransformFeedbackNV +#define GLEE_H_DEFINED_glBindTransformFeedbackNV + typedef void (APIENTRYP GLEEPFNGLBINDTRANSFORMFEEDBACKNVPROC) (GLenum target, GLuint id); + GLEE_EXTERN GLEEPFNGLBINDTRANSFORMFEEDBACKNVPROC GLeeFuncPtr_glBindTransformFeedbackNV; + #define glBindTransformFeedbackNV GLeeFuncPtr_glBindTransformFeedbackNV +#endif +#ifndef GLEE_H_DEFINED_glDeleteTransformFeedbacksNV +#define GLEE_H_DEFINED_glDeleteTransformFeedbacksNV + typedef void (APIENTRYP GLEEPFNGLDELETETRANSFORMFEEDBACKSNVPROC) (GLsizei n, const GLuint * ids); + GLEE_EXTERN GLEEPFNGLDELETETRANSFORMFEEDBACKSNVPROC GLeeFuncPtr_glDeleteTransformFeedbacksNV; + #define glDeleteTransformFeedbacksNV GLeeFuncPtr_glDeleteTransformFeedbacksNV +#endif +#ifndef GLEE_H_DEFINED_glGenTransformFeedbacksNV +#define GLEE_H_DEFINED_glGenTransformFeedbacksNV + typedef void (APIENTRYP GLEEPFNGLGENTRANSFORMFEEDBACKSNVPROC) (GLsizei n, GLuint * ids); + GLEE_EXTERN GLEEPFNGLGENTRANSFORMFEEDBACKSNVPROC GLeeFuncPtr_glGenTransformFeedbacksNV; + #define glGenTransformFeedbacksNV GLeeFuncPtr_glGenTransformFeedbacksNV +#endif +#ifndef GLEE_H_DEFINED_glIsTransformFeedbackNV +#define GLEE_H_DEFINED_glIsTransformFeedbackNV + typedef GLboolean (APIENTRYP GLEEPFNGLISTRANSFORMFEEDBACKNVPROC) (GLuint id); + GLEE_EXTERN GLEEPFNGLISTRANSFORMFEEDBACKNVPROC GLeeFuncPtr_glIsTransformFeedbackNV; + #define glIsTransformFeedbackNV GLeeFuncPtr_glIsTransformFeedbackNV +#endif +#ifndef GLEE_H_DEFINED_glPauseTransformFeedbackNV +#define GLEE_H_DEFINED_glPauseTransformFeedbackNV + typedef void (APIENTRYP GLEEPFNGLPAUSETRANSFORMFEEDBACKNVPROC) (); + GLEE_EXTERN GLEEPFNGLPAUSETRANSFORMFEEDBACKNVPROC GLeeFuncPtr_glPauseTransformFeedbackNV; + #define glPauseTransformFeedbackNV GLeeFuncPtr_glPauseTransformFeedbackNV +#endif +#ifndef GLEE_H_DEFINED_glResumeTransformFeedbackNV +#define GLEE_H_DEFINED_glResumeTransformFeedbackNV + typedef void (APIENTRYP GLEEPFNGLRESUMETRANSFORMFEEDBACKNVPROC) (); + GLEE_EXTERN GLEEPFNGLRESUMETRANSFORMFEEDBACKNVPROC GLeeFuncPtr_glResumeTransformFeedbackNV; + #define glResumeTransformFeedbackNV GLeeFuncPtr_glResumeTransformFeedbackNV +#endif +#ifndef GLEE_H_DEFINED_glDrawTransformFeedbackNV +#define GLEE_H_DEFINED_glDrawTransformFeedbackNV + typedef void (APIENTRYP GLEEPFNGLDRAWTRANSFORMFEEDBACKNVPROC) (GLenum mode, GLuint id); + GLEE_EXTERN GLEEPFNGLDRAWTRANSFORMFEEDBACKNVPROC GLeeFuncPtr_glDrawTransformFeedbackNV; + #define glDrawTransformFeedbackNV GLeeFuncPtr_glDrawTransformFeedbackNV +#endif +#endif + +/* GL_SGIX_texture_select */ + +#ifndef GL_SGIX_texture_select +#define GL_SGIX_texture_select 1 +#define __GLEE_GL_SGIX_texture_select 1 +/* Constants */ +#endif + +/* GL_INGR_blend_func_separate */ + +#ifndef GL_INGR_blend_func_separate +#define GL_INGR_blend_func_separate 1 +#define __GLEE_GL_INGR_blend_func_separate 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glBlendFuncSeparateINGR +#define GLEE_H_DEFINED_glBlendFuncSeparateINGR + typedef void (APIENTRYP GLEEPFNGLBLENDFUNCSEPARATEINGRPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + GLEE_EXTERN GLEEPFNGLBLENDFUNCSEPARATEINGRPROC GLeeFuncPtr_glBlendFuncSeparateINGR; + #define glBlendFuncSeparateINGR GLeeFuncPtr_glBlendFuncSeparateINGR +#endif +#endif + +/* GL_SGIX_depth_pass_instrument */ + +#ifndef GL_SGIX_depth_pass_instrument +#define GL_SGIX_depth_pass_instrument 1 +#define __GLEE_GL_SGIX_depth_pass_instrument 1 +/* Constants */ +#endif + +/* GL_SGIX_igloo_interface */ + +#ifndef GL_SGIX_igloo_interface +#define GL_SGIX_igloo_interface 1 +#define __GLEE_GL_SGIX_igloo_interface 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glIglooInterfaceSGIX +#define GLEE_H_DEFINED_glIglooInterfaceSGIX + typedef void (APIENTRYP GLEEPFNGLIGLOOINTERFACESGIXPROC) (GLenum pname, const GLvoid * params); + GLEE_EXTERN GLEEPFNGLIGLOOINTERFACESGIXPROC GLeeFuncPtr_glIglooInterfaceSGIX; + #define glIglooInterfaceSGIX GLeeFuncPtr_glIglooInterfaceSGIX +#endif +#endif + +/* GL_EXT_fragment_lighting */ + +#ifndef GL_EXT_fragment_lighting +#define GL_EXT_fragment_lighting 1 +#define __GLEE_GL_EXT_fragment_lighting 1 +/* Constants */ +#define GL_FRAGMENT_LIGHTING_EXT 0x8400 +#define GL_FRAGMENT_COLOR_MATERIAL_EXT 0x8401 +#define GL_FRAGMENT_COLOR_MATERIAL_FACE_EXT 0x8402 +#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_EXT 0x8403 +#define GL_MAX_FRAGMENT_LIGHTS_EXT 0x8404 +#define GL_MAX_ACTIVE_LIGHTS_EXT 0x8405 +#define GL_CURRENT_RASTER_NORMAL_EXT 0x8406 +#define GL_LIGHT_ENV_MODE_EXT 0x8407 +#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_EXT 0x8408 +#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_EXT 0x8409 +#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_EXT 0x840A +#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_EXT 0x840B +#define GL_FRAGMENT_LIGHT0_EXT 0x840C +#define GL_FRAGMENT_LIGHT7_EXT 0x8413 +#ifndef GLEE_H_DEFINED_glFragmentLightModeliEXT +#define GLEE_H_DEFINED_glFragmentLightModeliEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAGMENTLIGHTMODELIEXTPROC) (GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLFRAGMENTLIGHTMODELIEXTPROC GLeeFuncPtr_glFragmentLightModeliEXT; + #define glFragmentLightModeliEXT GLeeFuncPtr_glFragmentLightModeliEXT +#endif +#ifndef GLEE_H_DEFINED_glFragmentLightModelfEXT +#define GLEE_H_DEFINED_glFragmentLightModelfEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAGMENTLIGHTMODELFEXTPROC) (GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLFRAGMENTLIGHTMODELFEXTPROC GLeeFuncPtr_glFragmentLightModelfEXT; + #define glFragmentLightModelfEXT GLeeFuncPtr_glFragmentLightModelfEXT +#endif +#ifndef GLEE_H_DEFINED_glFragmentLightModelivEXT +#define GLEE_H_DEFINED_glFragmentLightModelivEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAGMENTLIGHTMODELIVEXTPROC) (GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLFRAGMENTLIGHTMODELIVEXTPROC GLeeFuncPtr_glFragmentLightModelivEXT; + #define glFragmentLightModelivEXT GLeeFuncPtr_glFragmentLightModelivEXT +#endif +#ifndef GLEE_H_DEFINED_glFragmentLightModelfvEXT +#define GLEE_H_DEFINED_glFragmentLightModelfvEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAGMENTLIGHTMODELFVEXTPROC) (GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLFRAGMENTLIGHTMODELFVEXTPROC GLeeFuncPtr_glFragmentLightModelfvEXT; + #define glFragmentLightModelfvEXT GLeeFuncPtr_glFragmentLightModelfvEXT +#endif +#ifndef GLEE_H_DEFINED_glFragmentLightiEXT +#define GLEE_H_DEFINED_glFragmentLightiEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAGMENTLIGHTIEXTPROC) (GLenum light, GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLFRAGMENTLIGHTIEXTPROC GLeeFuncPtr_glFragmentLightiEXT; + #define glFragmentLightiEXT GLeeFuncPtr_glFragmentLightiEXT +#endif +#ifndef GLEE_H_DEFINED_glFragmentLightfEXT +#define GLEE_H_DEFINED_glFragmentLightfEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAGMENTLIGHTFEXTPROC) (GLenum light, GLenum pname, GLfloat param); + GLEE_EXTERN GLEEPFNGLFRAGMENTLIGHTFEXTPROC GLeeFuncPtr_glFragmentLightfEXT; + #define glFragmentLightfEXT GLeeFuncPtr_glFragmentLightfEXT +#endif +#ifndef GLEE_H_DEFINED_glFragmentLightivEXT +#define GLEE_H_DEFINED_glFragmentLightivEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLFRAGMENTLIGHTIVEXTPROC GLeeFuncPtr_glFragmentLightivEXT; + #define glFragmentLightivEXT GLeeFuncPtr_glFragmentLightivEXT +#endif +#ifndef GLEE_H_DEFINED_glFragmentLightfvEXT +#define GLEE_H_DEFINED_glFragmentLightfvEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLFRAGMENTLIGHTFVEXTPROC GLeeFuncPtr_glFragmentLightfvEXT; + #define glFragmentLightfvEXT GLeeFuncPtr_glFragmentLightfvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetFragmentLightivEXT +#define GLEE_H_DEFINED_glGetFragmentLightivEXT + typedef GLvoid (APIENTRYP GLEEPFNGLGETFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETFRAGMENTLIGHTIVEXTPROC GLeeFuncPtr_glGetFragmentLightivEXT; + #define glGetFragmentLightivEXT GLeeFuncPtr_glGetFragmentLightivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetFragmentLightfvEXT +#define GLEE_H_DEFINED_glGetFragmentLightfvEXT + typedef GLvoid (APIENTRYP GLEEPFNGLGETFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETFRAGMENTLIGHTFVEXTPROC GLeeFuncPtr_glGetFragmentLightfvEXT; + #define glGetFragmentLightfvEXT GLeeFuncPtr_glGetFragmentLightfvEXT +#endif +#ifndef GLEE_H_DEFINED_glFragmentMaterialfEXT +#define GLEE_H_DEFINED_glFragmentMaterialfEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAGMENTMATERIALFEXTPROC) (GLenum face, GLenum pname, const GLfloat param); + GLEE_EXTERN GLEEPFNGLFRAGMENTMATERIALFEXTPROC GLeeFuncPtr_glFragmentMaterialfEXT; + #define glFragmentMaterialfEXT GLeeFuncPtr_glFragmentMaterialfEXT +#endif +#ifndef GLEE_H_DEFINED_glFragmentMaterialiEXT +#define GLEE_H_DEFINED_glFragmentMaterialiEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAGMENTMATERIALIEXTPROC) (GLenum face, GLenum pname, const GLint param); + GLEE_EXTERN GLEEPFNGLFRAGMENTMATERIALIEXTPROC GLeeFuncPtr_glFragmentMaterialiEXT; + #define glFragmentMaterialiEXT GLeeFuncPtr_glFragmentMaterialiEXT +#endif +#ifndef GLEE_H_DEFINED_glFragmentMaterialfvEXT +#define GLEE_H_DEFINED_glFragmentMaterialfvEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLFRAGMENTMATERIALFVEXTPROC GLeeFuncPtr_glFragmentMaterialfvEXT; + #define glFragmentMaterialfvEXT GLeeFuncPtr_glFragmentMaterialfvEXT +#endif +#ifndef GLEE_H_DEFINED_glFragmentMaterialivEXT +#define GLEE_H_DEFINED_glFragmentMaterialivEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLFRAGMENTMATERIALIVEXTPROC GLeeFuncPtr_glFragmentMaterialivEXT; + #define glFragmentMaterialivEXT GLeeFuncPtr_glFragmentMaterialivEXT +#endif +#ifndef GLEE_H_DEFINED_glFragmentColorMaterialEXT +#define GLEE_H_DEFINED_glFragmentColorMaterialEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAGMENTCOLORMATERIALEXTPROC) (GLenum face, GLenum mode); + GLEE_EXTERN GLEEPFNGLFRAGMENTCOLORMATERIALEXTPROC GLeeFuncPtr_glFragmentColorMaterialEXT; + #define glFragmentColorMaterialEXT GLeeFuncPtr_glFragmentColorMaterialEXT +#endif +#ifndef GLEE_H_DEFINED_glGetFragmentMaterialfvEXT +#define GLEE_H_DEFINED_glGetFragmentMaterialfvEXT + typedef GLvoid (APIENTRYP GLEEPFNGLGETFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat * params); + GLEE_EXTERN GLEEPFNGLGETFRAGMENTMATERIALFVEXTPROC GLeeFuncPtr_glGetFragmentMaterialfvEXT; + #define glGetFragmentMaterialfvEXT GLeeFuncPtr_glGetFragmentMaterialfvEXT +#endif +#ifndef GLEE_H_DEFINED_glGetFragmentMaterialivEXT +#define GLEE_H_DEFINED_glGetFragmentMaterialivEXT + typedef GLvoid (APIENTRYP GLEEPFNGLGETFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint * params); + GLEE_EXTERN GLEEPFNGLGETFRAGMENTMATERIALIVEXTPROC GLeeFuncPtr_glGetFragmentMaterialivEXT; + #define glGetFragmentMaterialivEXT GLeeFuncPtr_glGetFragmentMaterialivEXT +#endif +#ifndef GLEE_H_DEFINED_glLightEnviEXT +#define GLEE_H_DEFINED_glLightEnviEXT + typedef GLvoid (APIENTRYP GLEEPFNGLLIGHTENVIEXTPROC) (GLenum pname, GLint param); + GLEE_EXTERN GLEEPFNGLLIGHTENVIEXTPROC GLeeFuncPtr_glLightEnviEXT; + #define glLightEnviEXT GLeeFuncPtr_glLightEnviEXT +#endif +#endif + +/* GL_EXT_geometry_shader4 */ + +#ifndef GL_EXT_geometry_shader4 +#define GL_EXT_geometry_shader4 1 +#define __GLEE_GL_EXT_geometry_shader4 1 +/* Constants */ +#define GL_GEOMETRY_SHADER_EXT 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA +#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD +#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE +#define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1 +#define GL_LINES_ADJACENCY_EXT 0xA +#define GL_LINE_STRIP_ADJACENCY_EXT 0xB +#define GL_TRIANGLES_ADJACENCY_EXT 0xC +#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 +#define GL_PROGRAM_POINT_SIZE_EXT 0x8642 +#ifndef GLEE_H_DEFINED_glProgramParameteriEXT +#define GLEE_H_DEFINED_glProgramParameteriEXT + typedef GLvoid (APIENTRYP GLEEPFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); + GLEE_EXTERN GLEEPFNGLPROGRAMPARAMETERIEXTPROC GLeeFuncPtr_glProgramParameteriEXT; + #define glProgramParameteriEXT GLeeFuncPtr_glProgramParameteriEXT +#endif +#ifndef GLEE_H_DEFINED_glFramebufferTextureEXT +#define GLEE_H_DEFINED_glFramebufferTextureEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERTEXTUREEXTPROC GLeeFuncPtr_glFramebufferTextureEXT; + #define glFramebufferTextureEXT GLeeFuncPtr_glFramebufferTextureEXT +#endif +#ifndef GLEE_H_DEFINED_glFramebufferTextureLayerEXT +#define GLEE_H_DEFINED_glFramebufferTextureLayerEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERTEXTURELAYEREXTPROC GLeeFuncPtr_glFramebufferTextureLayerEXT; + #define glFramebufferTextureLayerEXT GLeeFuncPtr_glFramebufferTextureLayerEXT +#endif +#ifndef GLEE_H_DEFINED_glFramebufferTextureFaceEXT +#define GLEE_H_DEFINED_glFramebufferTextureFaceEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERTEXTUREFACEEXTPROC GLeeFuncPtr_glFramebufferTextureFaceEXT; + #define glFramebufferTextureFaceEXT GLeeFuncPtr_glFramebufferTextureFaceEXT +#endif +#endif + +/* GL_EXT_scene_marker */ + +#ifndef GL_EXT_scene_marker +#define GL_EXT_scene_marker 1 +#define __GLEE_GL_EXT_scene_marker 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glBeginSceneEXT +#define GLEE_H_DEFINED_glBeginSceneEXT + typedef GLvoid (APIENTRYP GLEEPFNGLBEGINSCENEEXTPROC) (); + GLEE_EXTERN GLEEPFNGLBEGINSCENEEXTPROC GLeeFuncPtr_glBeginSceneEXT; + #define glBeginSceneEXT GLeeFuncPtr_glBeginSceneEXT +#endif +#ifndef GLEE_H_DEFINED_glEndSceneEXT +#define GLEE_H_DEFINED_glEndSceneEXT + typedef GLvoid (APIENTRYP GLEEPFNGLENDSCENEEXTPROC) (); + GLEE_EXTERN GLEEPFNGLENDSCENEEXTPROC GLeeFuncPtr_glEndSceneEXT; + #define glEndSceneEXT GLeeFuncPtr_glEndSceneEXT +#endif +#endif + +/* GL_EXT_texture_compression_dxt1 */ + +#ifndef GL_EXT_texture_compression_dxt1 +#define GL_EXT_texture_compression_dxt1 1 +#define __GLEE_GL_EXT_texture_compression_dxt1 1 +/* Constants */ +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#endif + +/* GL_EXT_texture_env */ + +#ifndef GL_EXT_texture_env +#define GL_EXT_texture_env 1 +#define __GLEE_GL_EXT_texture_env 1 +/* Constants */ +#define GL_TEXTURE_ENV0_EXT 0 +#define GL_TEXTURE_ENV_MODE_ALPHA_EXT 0 +#define GL_ENV_COPY_EXT 0 +#define GL_ENV_REPLACE_EXT 0 +#define GL_ENV_MODULATE_EXT 0 +#define GL_ENV_ADD_EXT 0 +#define GL_ENV_SUBTRACT_EXT 0 +#define GL_ENV_REVERSE_SUBTRACT_EXT 0 +#define GL_ENV_BLEND_EXT 0 +#define GL_ENV_REVERSE_BLEND_EXT 0 +#define GL_TEXTURE_ENV_SHIFT_EXT 0 +#endif + +/* GL_IBM_static_data */ + +#ifndef GL_IBM_static_data +#define GL_IBM_static_data 1 +#define __GLEE_GL_IBM_static_data 1 +/* Constants */ +#define GL_ALL_STATIC_DATA_IBM 103060 +#define GL_STATIC_VERTEX_ARRAY_IBM 103061 +#endif + +/* GL_NV_gpu_program4 */ + +#ifndef GL_NV_gpu_program4 +#define GL_NV_gpu_program4 1 +#define __GLEE_GL_NV_gpu_program4 1 +/* Constants */ +#define GL_MIN_PROGRAM_TEXEL_OFFSET_EXT 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET_EXT 0x8905 +#define GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906 +#define GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907 +#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908 +#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909 +#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5 +#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6 +#define GL_GEOMETRY_PROGRAM_NV 0x8C26 +#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27 +#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28 +#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA +#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 +#define GL_LINES_ADJACENCY_EXT 0xA +#define GL_LINE_STRIP_ADJACENCY_EXT 0xB +#define GL_TRIANGLES_ADJACENCY_EXT 0xC +#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 +#define GL_PROGRAM_POINT_SIZE_EXT 0x8642 +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD +#ifndef GLEE_H_DEFINED_glProgramLocalParameterI4iNV +#define GLEE_H_DEFINED_glProgramLocalParameterI4iNV + typedef GLvoid (APIENTRYP GLEEPFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); + GLEE_EXTERN GLEEPFNGLPROGRAMLOCALPARAMETERI4INVPROC GLeeFuncPtr_glProgramLocalParameterI4iNV; + #define glProgramLocalParameterI4iNV GLeeFuncPtr_glProgramLocalParameterI4iNV +#endif +#ifndef GLEE_H_DEFINED_glProgramLocalParameterI4ivNV +#define GLEE_H_DEFINED_glProgramLocalParameterI4ivNV + typedef GLvoid (APIENTRYP GLEEPFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint * params); + GLEE_EXTERN GLEEPFNGLPROGRAMLOCALPARAMETERI4IVNVPROC GLeeFuncPtr_glProgramLocalParameterI4ivNV; + #define glProgramLocalParameterI4ivNV GLeeFuncPtr_glProgramLocalParameterI4ivNV +#endif +#ifndef GLEE_H_DEFINED_glProgramLocalParametersI4ivNV +#define GLEE_H_DEFINED_glProgramLocalParametersI4ivNV + typedef GLvoid (APIENTRYP GLEEPFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint * params); + GLEE_EXTERN GLEEPFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC GLeeFuncPtr_glProgramLocalParametersI4ivNV; + #define glProgramLocalParametersI4ivNV GLeeFuncPtr_glProgramLocalParametersI4ivNV +#endif +#ifndef GLEE_H_DEFINED_glProgramLocalParameterI4uiNV +#define GLEE_H_DEFINED_glProgramLocalParameterI4uiNV + typedef GLvoid (APIENTRYP GLEEPFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); + GLEE_EXTERN GLEEPFNGLPROGRAMLOCALPARAMETERI4UINVPROC GLeeFuncPtr_glProgramLocalParameterI4uiNV; + #define glProgramLocalParameterI4uiNV GLeeFuncPtr_glProgramLocalParameterI4uiNV +#endif +#ifndef GLEE_H_DEFINED_glProgramLocalParameterI4uivNV +#define GLEE_H_DEFINED_glProgramLocalParameterI4uivNV + typedef GLvoid (APIENTRYP GLEEPFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint * params); + GLEE_EXTERN GLEEPFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC GLeeFuncPtr_glProgramLocalParameterI4uivNV; + #define glProgramLocalParameterI4uivNV GLeeFuncPtr_glProgramLocalParameterI4uivNV +#endif +#ifndef GLEE_H_DEFINED_glProgramLocalParametersI4uivNV +#define GLEE_H_DEFINED_glProgramLocalParametersI4uivNV + typedef GLvoid (APIENTRYP GLEEPFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint * params); + GLEE_EXTERN GLEEPFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC GLeeFuncPtr_glProgramLocalParametersI4uivNV; + #define glProgramLocalParametersI4uivNV GLeeFuncPtr_glProgramLocalParametersI4uivNV +#endif +#ifndef GLEE_H_DEFINED_glProgramEnvParameterI4iNV +#define GLEE_H_DEFINED_glProgramEnvParameterI4iNV + typedef GLvoid (APIENTRYP GLEEPFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); + GLEE_EXTERN GLEEPFNGLPROGRAMENVPARAMETERI4INVPROC GLeeFuncPtr_glProgramEnvParameterI4iNV; + #define glProgramEnvParameterI4iNV GLeeFuncPtr_glProgramEnvParameterI4iNV +#endif +#ifndef GLEE_H_DEFINED_glProgramEnvParameterI4ivNV +#define GLEE_H_DEFINED_glProgramEnvParameterI4ivNV + typedef GLvoid (APIENTRYP GLEEPFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint * params); + GLEE_EXTERN GLEEPFNGLPROGRAMENVPARAMETERI4IVNVPROC GLeeFuncPtr_glProgramEnvParameterI4ivNV; + #define glProgramEnvParameterI4ivNV GLeeFuncPtr_glProgramEnvParameterI4ivNV +#endif +#ifndef GLEE_H_DEFINED_glProgramEnvParametersI4ivNV +#define GLEE_H_DEFINED_glProgramEnvParametersI4ivNV + typedef GLvoid (APIENTRYP GLEEPFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint * params); + GLEE_EXTERN GLEEPFNGLPROGRAMENVPARAMETERSI4IVNVPROC GLeeFuncPtr_glProgramEnvParametersI4ivNV; + #define glProgramEnvParametersI4ivNV GLeeFuncPtr_glProgramEnvParametersI4ivNV +#endif +#ifndef GLEE_H_DEFINED_glProgramEnvParameterI4uiNV +#define GLEE_H_DEFINED_glProgramEnvParameterI4uiNV + typedef GLvoid (APIENTRYP GLEEPFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); + GLEE_EXTERN GLEEPFNGLPROGRAMENVPARAMETERI4UINVPROC GLeeFuncPtr_glProgramEnvParameterI4uiNV; + #define glProgramEnvParameterI4uiNV GLeeFuncPtr_glProgramEnvParameterI4uiNV +#endif +#ifndef GLEE_H_DEFINED_glProgramEnvParameterI4uivNV +#define GLEE_H_DEFINED_glProgramEnvParameterI4uivNV + typedef GLvoid (APIENTRYP GLEEPFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint * params); + GLEE_EXTERN GLEEPFNGLPROGRAMENVPARAMETERI4UIVNVPROC GLeeFuncPtr_glProgramEnvParameterI4uivNV; + #define glProgramEnvParameterI4uivNV GLeeFuncPtr_glProgramEnvParameterI4uivNV +#endif +#ifndef GLEE_H_DEFINED_glProgramEnvParametersI4uivNV +#define GLEE_H_DEFINED_glProgramEnvParametersI4uivNV + typedef GLvoid (APIENTRYP GLEEPFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint * params); + GLEE_EXTERN GLEEPFNGLPROGRAMENVPARAMETERSI4UIVNVPROC GLeeFuncPtr_glProgramEnvParametersI4uivNV; + #define glProgramEnvParametersI4uivNV GLeeFuncPtr_glProgramEnvParametersI4uivNV +#endif +#ifndef GLEE_H_DEFINED_glGetProgramLocalParameterIivNV +#define GLEE_H_DEFINED_glGetProgramLocalParameterIivNV + typedef GLvoid (APIENTRYP GLEEPFNGLGETPROGRAMLOCALPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint * params); + GLEE_EXTERN GLEEPFNGLGETPROGRAMLOCALPARAMETERIIVNVPROC GLeeFuncPtr_glGetProgramLocalParameterIivNV; + #define glGetProgramLocalParameterIivNV GLeeFuncPtr_glGetProgramLocalParameterIivNV +#endif +#ifndef GLEE_H_DEFINED_glGetProgramLocalParameterIuivNV +#define GLEE_H_DEFINED_glGetProgramLocalParameterIuivNV + typedef GLvoid (APIENTRYP GLEEPFNGLGETPROGRAMLOCALPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint * params); + GLEE_EXTERN GLEEPFNGLGETPROGRAMLOCALPARAMETERIUIVNVPROC GLeeFuncPtr_glGetProgramLocalParameterIuivNV; + #define glGetProgramLocalParameterIuivNV GLeeFuncPtr_glGetProgramLocalParameterIuivNV +#endif +#ifndef GLEE_H_DEFINED_glGetProgramEnvParameterIivNV +#define GLEE_H_DEFINED_glGetProgramEnvParameterIivNV + typedef GLvoid (APIENTRYP GLEEPFNGLGETPROGRAMENVPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint * params); + GLEE_EXTERN GLEEPFNGLGETPROGRAMENVPARAMETERIIVNVPROC GLeeFuncPtr_glGetProgramEnvParameterIivNV; + #define glGetProgramEnvParameterIivNV GLeeFuncPtr_glGetProgramEnvParameterIivNV +#endif +#ifndef GLEE_H_DEFINED_glGetProgramEnvParameterIuivNV +#define GLEE_H_DEFINED_glGetProgramEnvParameterIuivNV + typedef GLvoid (APIENTRYP GLEEPFNGLGETPROGRAMENVPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint * params); + GLEE_EXTERN GLEEPFNGLGETPROGRAMENVPARAMETERIUIVNVPROC GLeeFuncPtr_glGetProgramEnvParameterIuivNV; + #define glGetProgramEnvParameterIuivNV GLeeFuncPtr_glGetProgramEnvParameterIuivNV +#endif +#ifndef GLEE_H_DEFINED_glFramebufferTextureEXT +#define GLEE_H_DEFINED_glFramebufferTextureEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERTEXTUREEXTPROC GLeeFuncPtr_glFramebufferTextureEXT; + #define glFramebufferTextureEXT GLeeFuncPtr_glFramebufferTextureEXT +#endif +#ifndef GLEE_H_DEFINED_glFramebufferTextureLayerEXT +#define GLEE_H_DEFINED_glFramebufferTextureLayerEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERTEXTURELAYEREXTPROC GLeeFuncPtr_glFramebufferTextureLayerEXT; + #define glFramebufferTextureLayerEXT GLeeFuncPtr_glFramebufferTextureLayerEXT +#endif +#ifndef GLEE_H_DEFINED_glFramebufferTextureFaceEXT +#define GLEE_H_DEFINED_glFramebufferTextureFaceEXT + typedef GLvoid (APIENTRYP GLEEPFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); + GLEE_EXTERN GLEEPFNGLFRAMEBUFFERTEXTUREFACEEXTPROC GLeeFuncPtr_glFramebufferTextureFaceEXT; + #define glFramebufferTextureFaceEXT GLeeFuncPtr_glFramebufferTextureFaceEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI2iEXT +#define GLEE_H_DEFINED_glVertexAttribI2iEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI2IEXTPROC GLeeFuncPtr_glVertexAttribI2iEXT; + #define glVertexAttribI2iEXT GLeeFuncPtr_glVertexAttribI2iEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI3iEXT +#define GLEE_H_DEFINED_glVertexAttribI3iEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI3IEXTPROC GLeeFuncPtr_glVertexAttribI3iEXT; + #define glVertexAttribI3iEXT GLeeFuncPtr_glVertexAttribI3iEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI4iEXT +#define GLEE_H_DEFINED_glVertexAttribI4iEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI4IEXTPROC GLeeFuncPtr_glVertexAttribI4iEXT; + #define glVertexAttribI4iEXT GLeeFuncPtr_glVertexAttribI4iEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI1uiEXT +#define GLEE_H_DEFINED_glVertexAttribI1uiEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI1UIEXTPROC GLeeFuncPtr_glVertexAttribI1uiEXT; + #define glVertexAttribI1uiEXT GLeeFuncPtr_glVertexAttribI1uiEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI2uiEXT +#define GLEE_H_DEFINED_glVertexAttribI2uiEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI2UIEXTPROC GLeeFuncPtr_glVertexAttribI2uiEXT; + #define glVertexAttribI2uiEXT GLeeFuncPtr_glVertexAttribI2uiEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI3uiEXT +#define GLEE_H_DEFINED_glVertexAttribI3uiEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI3UIEXTPROC GLeeFuncPtr_glVertexAttribI3uiEXT; + #define glVertexAttribI3uiEXT GLeeFuncPtr_glVertexAttribI3uiEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI4uiEXT +#define GLEE_H_DEFINED_glVertexAttribI4uiEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI4UIEXTPROC GLeeFuncPtr_glVertexAttribI4uiEXT; + #define glVertexAttribI4uiEXT GLeeFuncPtr_glVertexAttribI4uiEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI1ivEXT +#define GLEE_H_DEFINED_glVertexAttribI1ivEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI1IVEXTPROC GLeeFuncPtr_glVertexAttribI1ivEXT; + #define glVertexAttribI1ivEXT GLeeFuncPtr_glVertexAttribI1ivEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI2ivEXT +#define GLEE_H_DEFINED_glVertexAttribI2ivEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI2IVEXTPROC GLeeFuncPtr_glVertexAttribI2ivEXT; + #define glVertexAttribI2ivEXT GLeeFuncPtr_glVertexAttribI2ivEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI3ivEXT +#define GLEE_H_DEFINED_glVertexAttribI3ivEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI3IVEXTPROC GLeeFuncPtr_glVertexAttribI3ivEXT; + #define glVertexAttribI3ivEXT GLeeFuncPtr_glVertexAttribI3ivEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI4ivEXT +#define GLEE_H_DEFINED_glVertexAttribI4ivEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI4IVEXTPROC GLeeFuncPtr_glVertexAttribI4ivEXT; + #define glVertexAttribI4ivEXT GLeeFuncPtr_glVertexAttribI4ivEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI1uivEXT +#define GLEE_H_DEFINED_glVertexAttribI1uivEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI1UIVEXTPROC GLeeFuncPtr_glVertexAttribI1uivEXT; + #define glVertexAttribI1uivEXT GLeeFuncPtr_glVertexAttribI1uivEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI2uivEXT +#define GLEE_H_DEFINED_glVertexAttribI2uivEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI2UIVEXTPROC GLeeFuncPtr_glVertexAttribI2uivEXT; + #define glVertexAttribI2uivEXT GLeeFuncPtr_glVertexAttribI2uivEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI3uivEXT +#define GLEE_H_DEFINED_glVertexAttribI3uivEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI3UIVEXTPROC GLeeFuncPtr_glVertexAttribI3uivEXT; + #define glVertexAttribI3uivEXT GLeeFuncPtr_glVertexAttribI3uivEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI4uivEXT +#define GLEE_H_DEFINED_glVertexAttribI4uivEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI4UIVEXTPROC GLeeFuncPtr_glVertexAttribI4uivEXT; + #define glVertexAttribI4uivEXT GLeeFuncPtr_glVertexAttribI4uivEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI4bvEXT +#define GLEE_H_DEFINED_glVertexAttribI4bvEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI4BVEXTPROC GLeeFuncPtr_glVertexAttribI4bvEXT; + #define glVertexAttribI4bvEXT GLeeFuncPtr_glVertexAttribI4bvEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI4svEXT +#define GLEE_H_DEFINED_glVertexAttribI4svEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI4SVEXTPROC GLeeFuncPtr_glVertexAttribI4svEXT; + #define glVertexAttribI4svEXT GLeeFuncPtr_glVertexAttribI4svEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI4ubvEXT +#define GLEE_H_DEFINED_glVertexAttribI4ubvEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI4UBVEXTPROC GLeeFuncPtr_glVertexAttribI4ubvEXT; + #define glVertexAttribI4ubvEXT GLeeFuncPtr_glVertexAttribI4ubvEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribI4usvEXT +#define GLEE_H_DEFINED_glVertexAttribI4usvEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort * v); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBI4USVEXTPROC GLeeFuncPtr_glVertexAttribI4usvEXT; + #define glVertexAttribI4usvEXT GLeeFuncPtr_glVertexAttribI4usvEXT +#endif +#ifndef GLEE_H_DEFINED_glVertexAttribIPointerEXT +#define GLEE_H_DEFINED_glVertexAttribIPointerEXT + typedef GLvoid (APIENTRYP GLEEPFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); + GLEE_EXTERN GLEEPFNGLVERTEXATTRIBIPOINTEREXTPROC GLeeFuncPtr_glVertexAttribIPointerEXT; + #define glVertexAttribIPointerEXT GLeeFuncPtr_glVertexAttribIPointerEXT +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribIivEXT +#define GLEE_H_DEFINED_glGetVertexAttribIivEXT + typedef GLvoid (APIENTRYP GLEEPFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint * params); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBIIVEXTPROC GLeeFuncPtr_glGetVertexAttribIivEXT; + #define glGetVertexAttribIivEXT GLeeFuncPtr_glGetVertexAttribIivEXT +#endif +#ifndef GLEE_H_DEFINED_glGetVertexAttribIuivEXT +#define GLEE_H_DEFINED_glGetVertexAttribIuivEXT + typedef GLvoid (APIENTRYP GLEEPFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint * params); + GLEE_EXTERN GLEEPFNGLGETVERTEXATTRIBIUIVEXTPROC GLeeFuncPtr_glGetVertexAttribIuivEXT; + #define glGetVertexAttribIuivEXT GLeeFuncPtr_glGetVertexAttribIuivEXT +#endif +#endif + +/* GL_OES_byte_coordinates */ + +#ifndef GL_OES_byte_coordinates +#define GL_OES_byte_coordinates 1 +#define __GLEE_GL_OES_byte_coordinates 1 +/* Constants */ +#define GL_BYTE 0x1400 +#endif + +/* GL_OES_compressed_paletted_texture */ + +#ifndef GL_OES_compressed_paletted_texture +#define GL_OES_compressed_paletted_texture 1 +#define __GLEE_GL_OES_compressed_paletted_texture 1 +/* Constants */ +#define GL_PALETTE4_RGB8_OES 0x8B90 +#define GL_PALETTE4_RGBA8_OES 0x8B91 +#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 +#define GL_PALETTE4_RGBA4_OES 0x8B93 +#define GL_PALETTE4_RGB5_A1_OES 0x8B94 +#define GL_PALETTE8_RGB8_OES 0x8B95 +#define GL_PALETTE8_RGBA8_OES 0x8B96 +#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 +#define GL_PALETTE8_RGBA4_OES 0x8B98 +#define GL_PALETTE8_RGB5_A1_OES 0x8B99 +#endif + +/* GL_OES_single_precision */ + +#ifndef GL_OES_single_precision +#define GL_OES_single_precision 1 +#define __GLEE_GL_OES_single_precision 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glDepthRangefOES +#define GLEE_H_DEFINED_glDepthRangefOES + typedef GLvoid (APIENTRYP GLEEPFNGLDEPTHRANGEFOESPROC) (GLclampf n, GLclampf f); + GLEE_EXTERN GLEEPFNGLDEPTHRANGEFOESPROC GLeeFuncPtr_glDepthRangefOES; + #define glDepthRangefOES GLeeFuncPtr_glDepthRangefOES +#endif +#ifndef GLEE_H_DEFINED_glFrustumfOES +#define GLEE_H_DEFINED_glFrustumfOES + typedef GLvoid (APIENTRYP GLEEPFNGLFRUSTUMFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); + GLEE_EXTERN GLEEPFNGLFRUSTUMFOESPROC GLeeFuncPtr_glFrustumfOES; + #define glFrustumfOES GLeeFuncPtr_glFrustumfOES +#endif +#ifndef GLEE_H_DEFINED_glOrthofOES +#define GLEE_H_DEFINED_glOrthofOES + typedef GLvoid (APIENTRYP GLEEPFNGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); + GLEE_EXTERN GLEEPFNGLORTHOFOESPROC GLeeFuncPtr_glOrthofOES; + #define glOrthofOES GLeeFuncPtr_glOrthofOES +#endif +#ifndef GLEE_H_DEFINED_glClipPlanefOES +#define GLEE_H_DEFINED_glClipPlanefOES + typedef GLvoid (APIENTRYP GLEEPFNGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat* equation); + GLEE_EXTERN GLEEPFNGLCLIPPLANEFOESPROC GLeeFuncPtr_glClipPlanefOES; + #define glClipPlanefOES GLeeFuncPtr_glClipPlanefOES +#endif +#ifndef GLEE_H_DEFINED_glGetClipPlanefOES +#define GLEE_H_DEFINED_glGetClipPlanefOES + typedef GLvoid (APIENTRYP GLEEPFNGLGETCLIPPLANEFOESPROC) (GLenum plane, GLfloat* equation); + GLEE_EXTERN GLEEPFNGLGETCLIPPLANEFOESPROC GLeeFuncPtr_glGetClipPlanefOES; + #define glGetClipPlanefOES GLeeFuncPtr_glGetClipPlanefOES +#endif +#ifndef GLEE_H_DEFINED_glClearDepthfOES +#define GLEE_H_DEFINED_glClearDepthfOES + typedef GLvoid (APIENTRYP GLEEPFNGLCLEARDEPTHFOESPROC) (GLclampd depth); + GLEE_EXTERN GLEEPFNGLCLEARDEPTHFOESPROC GLeeFuncPtr_glClearDepthfOES; + #define glClearDepthfOES GLeeFuncPtr_glClearDepthfOES +#endif +#endif + +/* GL_SGIX_pixel_texture_bits */ + +#ifndef GL_SGIX_pixel_texture_bits +#define GL_SGIX_pixel_texture_bits 1 +#define __GLEE_GL_SGIX_pixel_texture_bits 1 +/* Constants */ +#endif + +/* GL_SGIX_texture_range */ + +#ifndef GL_SGIX_texture_range +#define GL_SGIX_texture_range 1 +#define __GLEE_GL_SGIX_texture_range 1 +/* Constants */ +#define GL_RGB_SIGNED_SGIX 0x85E0 +#define GL_RGBA_SIGNED_SGIX 0x85E1 +#define GL_ALPHA_SIGNED_SGIX 0x85E2 +#define GL_LUMINANCE_SIGNED_SGIX 0x85E3 +#define GL_INTENSITY_SIGNED_SGIX 0x85E4 +#define GL_LUMINANCE_ALPHA_SIGNED_SGIX 0x85E5 +#define GL_RGB16_SIGNED_SGIX 0x85E6 +#define GL_RGBA16_SIGNED_SGIX 0x85E7 +#define GL_ALPHA16_SIGNED_SGIX 0x85E8 +#define GL_LUMINANCE16_SIGNED_SGIX 0x85E9 +#define GL_INTENSITY16_SIGNED_SGIX 0x85EA +#define GL_LUMINANCE16_ALPHA16_SIGNED_SGIX 0x85EB +#define GL_RGB_EXTENDED_RANGE_SGIX 0x85EC +#define GL_RGBA_EXTENDED_RANGE_SGIX 0x85ED +#define GL_ALPHA_EXTENDED_RANGE_SGIX 0x85EE +#define GL_LUMINANCE_EXTENDED_RANGE_SGIX 0x85EF +#define GL_INTENSITY_EXTENDED_RANGE_SGIX 0x85F0 +#define GL_LUMINANCE_ALPHA_EXTENDED_RANGE_SGIX 0x85F1 +#define GL_RGB16_EXTENDED_RANGE_SGIX 0x85F2 +#define GL_RGBA16_EXTENDED_RANGE_SGIX 0x85F3 +#define GL_ALPHA16_EXTENDED_RANGE_SGIX 0x85F4 +#define GL_LUMINANCE16_EXTENDED_RANGE_SGIX 0x85F5 +#define GL_INTENSITY16_EXTENDED_RANGE_SGIX 0x85F6 +#define GL_LUMINANCE16_ALPHA16_EXTENDED_RANGE_SGIX 0x85F7 +#define GL_MIN_LUMINANCE_SGIS 0x85F8 +#define GL_MAX_LUMINANCE_SGIS 0x85F9 +#define GL_MIN_INTENSITY_SGIS 0x85FA +#define GL_MAX_INTENSITY_SGIS 0x85FB +#endif + +/* WGL */ + +#ifdef WIN32 + +/* Extension querying variables */ + +GLEE_EXTERN GLboolean _GLEE_WGL_ARB_buffer_region; +GLEE_EXTERN GLboolean _GLEE_WGL_ARB_multisample; +GLEE_EXTERN GLboolean _GLEE_WGL_ARB_extensions_string; +GLEE_EXTERN GLboolean _GLEE_WGL_ARB_pixel_format; +GLEE_EXTERN GLboolean _GLEE_WGL_ARB_make_current_read; +GLEE_EXTERN GLboolean _GLEE_WGL_ARB_pbuffer; +GLEE_EXTERN GLboolean _GLEE_WGL_ARB_render_texture; +GLEE_EXTERN GLboolean _GLEE_WGL_ARB_pixel_format_float; +GLEE_EXTERN GLboolean _GLEE_WGL_ARB_create_context; +GLEE_EXTERN GLboolean _GLEE_WGL_EXT_make_current_read; +GLEE_EXTERN GLboolean _GLEE_WGL_EXT_pixel_format; +GLEE_EXTERN GLboolean _GLEE_WGL_EXT_pbuffer; +GLEE_EXTERN GLboolean _GLEE_WGL_EXT_depth_float; +GLEE_EXTERN GLboolean _GLEE_WGL_3DFX_multisample; +GLEE_EXTERN GLboolean _GLEE_WGL_EXT_multisample; +GLEE_EXTERN GLboolean _GLEE_WGL_I3D_digital_video_control; +GLEE_EXTERN GLboolean _GLEE_WGL_I3D_gamma; +GLEE_EXTERN GLboolean _GLEE_WGL_I3D_genlock; +GLEE_EXTERN GLboolean _GLEE_WGL_I3D_image_buffer; +GLEE_EXTERN GLboolean _GLEE_WGL_I3D_swap_frame_lock; +GLEE_EXTERN GLboolean _GLEE_WGL_NV_render_depth_texture; +GLEE_EXTERN GLboolean _GLEE_WGL_NV_render_texture_rectangle; +GLEE_EXTERN GLboolean _GLEE_WGL_ATI_pixel_format_float; +GLEE_EXTERN GLboolean _GLEE_WGL_NV_float_buffer; +GLEE_EXTERN GLboolean _GLEE_WGL_3DL_stereo_control; +GLEE_EXTERN GLboolean _GLEE_WGL_EXT_pixel_format_packed_float; +GLEE_EXTERN GLboolean _GLEE_WGL_EXT_framebuffer_sRGB; +GLEE_EXTERN GLboolean _GLEE_WGL_NV_present_video; +GLEE_EXTERN GLboolean _GLEE_WGL_NV_swap_group; +GLEE_EXTERN GLboolean _GLEE_WGL_NV_gpu_affinity; +GLEE_EXTERN GLboolean _GLEE_WGL_EXT_display_color_table; +GLEE_EXTERN GLboolean _GLEE_WGL_EXT_extensions_string; +GLEE_EXTERN GLboolean _GLEE_WGL_EXT_swap_control; +GLEE_EXTERN GLboolean _GLEE_WGL_NV_vertex_array_range; +GLEE_EXTERN GLboolean _GLEE_WGL_OML_sync_control; +GLEE_EXTERN GLboolean _GLEE_WGL_I3D_swap_frame_usage; +GLEE_EXTERN GLboolean _GLEE_WGL_NV_video_output; + +/* Aliases for extension querying variables */ + +#define GLEE_WGL_ARB_buffer_region GLeeEnabled(&_GLEE_WGL_ARB_buffer_region) +#define GLEE_WGL_ARB_multisample GLeeEnabled(&_GLEE_WGL_ARB_multisample) +#define GLEE_WGL_ARB_extensions_string GLeeEnabled(&_GLEE_WGL_ARB_extensions_string) +#define GLEE_WGL_ARB_pixel_format GLeeEnabled(&_GLEE_WGL_ARB_pixel_format) +#define GLEE_WGL_ARB_make_current_read GLeeEnabled(&_GLEE_WGL_ARB_make_current_read) +#define GLEE_WGL_ARB_pbuffer GLeeEnabled(&_GLEE_WGL_ARB_pbuffer) +#define GLEE_WGL_ARB_render_texture GLeeEnabled(&_GLEE_WGL_ARB_render_texture) +#define GLEE_WGL_ARB_pixel_format_float GLeeEnabled(&_GLEE_WGL_ARB_pixel_format_float) +#define GLEE_WGL_ARB_create_context GLeeEnabled(&_GLEE_WGL_ARB_create_context) +#define GLEE_WGL_EXT_make_current_read GLeeEnabled(&_GLEE_WGL_EXT_make_current_read) +#define GLEE_WGL_EXT_pixel_format GLeeEnabled(&_GLEE_WGL_EXT_pixel_format) +#define GLEE_WGL_EXT_pbuffer GLeeEnabled(&_GLEE_WGL_EXT_pbuffer) +#define GLEE_WGL_EXT_depth_float GLeeEnabled(&_GLEE_WGL_EXT_depth_float) +#define GLEE_WGL_3DFX_multisample GLeeEnabled(&_GLEE_WGL_3DFX_multisample) +#define GLEE_WGL_EXT_multisample GLeeEnabled(&_GLEE_WGL_EXT_multisample) +#define GLEE_WGL_I3D_digital_video_control GLeeEnabled(&_GLEE_WGL_I3D_digital_video_control) +#define GLEE_WGL_I3D_gamma GLeeEnabled(&_GLEE_WGL_I3D_gamma) +#define GLEE_WGL_I3D_genlock GLeeEnabled(&_GLEE_WGL_I3D_genlock) +#define GLEE_WGL_I3D_image_buffer GLeeEnabled(&_GLEE_WGL_I3D_image_buffer) +#define GLEE_WGL_I3D_swap_frame_lock GLeeEnabled(&_GLEE_WGL_I3D_swap_frame_lock) +#define GLEE_WGL_NV_render_depth_texture GLeeEnabled(&_GLEE_WGL_NV_render_depth_texture) +#define GLEE_WGL_NV_render_texture_rectangle GLeeEnabled(&_GLEE_WGL_NV_render_texture_rectangle) +#define GLEE_WGL_ATI_pixel_format_float GLeeEnabled(&_GLEE_WGL_ATI_pixel_format_float) +#define GLEE_WGL_NV_float_buffer GLeeEnabled(&_GLEE_WGL_NV_float_buffer) +#define GLEE_WGL_3DL_stereo_control GLeeEnabled(&_GLEE_WGL_3DL_stereo_control) +#define GLEE_WGL_EXT_pixel_format_packed_float GLeeEnabled(&_GLEE_WGL_EXT_pixel_format_packed_float) +#define GLEE_WGL_EXT_framebuffer_sRGB GLeeEnabled(&_GLEE_WGL_EXT_framebuffer_sRGB) +#define GLEE_WGL_NV_present_video GLeeEnabled(&_GLEE_WGL_NV_present_video) +#define GLEE_WGL_NV_swap_group GLeeEnabled(&_GLEE_WGL_NV_swap_group) +#define GLEE_WGL_NV_gpu_affinity GLeeEnabled(&_GLEE_WGL_NV_gpu_affinity) +#define GLEE_WGL_EXT_display_color_table GLeeEnabled(&_GLEE_WGL_EXT_display_color_table) +#define GLEE_WGL_EXT_extensions_string GLeeEnabled(&_GLEE_WGL_EXT_extensions_string) +#define GLEE_WGL_EXT_swap_control GLeeEnabled(&_GLEE_WGL_EXT_swap_control) +#define GLEE_WGL_NV_vertex_array_range GLeeEnabled(&_GLEE_WGL_NV_vertex_array_range) +#define GLEE_WGL_OML_sync_control GLeeEnabled(&_GLEE_WGL_OML_sync_control) +#define GLEE_WGL_I3D_swap_frame_usage GLeeEnabled(&_GLEE_WGL_I3D_swap_frame_usage) +#define GLEE_WGL_NV_video_output GLeeEnabled(&_GLEE_WGL_NV_video_output) + +/* WGL_ARB_buffer_region */ + +#ifndef WGL_ARB_buffer_region +#define WGL_ARB_buffer_region 1 +#define __GLEE_WGL_ARB_buffer_region 1 +/* Constants */ +#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 +#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 +#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 +#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 +#ifndef GLEE_H_DEFINED_wglCreateBufferRegionARB +#define GLEE_H_DEFINED_wglCreateBufferRegionARB + typedef HANDLE (APIENTRYP GLEEPFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); + GLEE_EXTERN GLEEPFNWGLCREATEBUFFERREGIONARBPROC GLeeFuncPtr_wglCreateBufferRegionARB; + #define wglCreateBufferRegionARB GLeeFuncPtr_wglCreateBufferRegionARB +#endif +#ifndef GLEE_H_DEFINED_wglDeleteBufferRegionARB +#define GLEE_H_DEFINED_wglDeleteBufferRegionARB + typedef VOID (APIENTRYP GLEEPFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); + GLEE_EXTERN GLEEPFNWGLDELETEBUFFERREGIONARBPROC GLeeFuncPtr_wglDeleteBufferRegionARB; + #define wglDeleteBufferRegionARB GLeeFuncPtr_wglDeleteBufferRegionARB +#endif +#ifndef GLEE_H_DEFINED_wglSaveBufferRegionARB +#define GLEE_H_DEFINED_wglSaveBufferRegionARB + typedef BOOL (APIENTRYP GLEEPFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); + GLEE_EXTERN GLEEPFNWGLSAVEBUFFERREGIONARBPROC GLeeFuncPtr_wglSaveBufferRegionARB; + #define wglSaveBufferRegionARB GLeeFuncPtr_wglSaveBufferRegionARB +#endif +#ifndef GLEE_H_DEFINED_wglRestoreBufferRegionARB +#define GLEE_H_DEFINED_wglRestoreBufferRegionARB + typedef BOOL (APIENTRYP GLEEPFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); + GLEE_EXTERN GLEEPFNWGLRESTOREBUFFERREGIONARBPROC GLeeFuncPtr_wglRestoreBufferRegionARB; + #define wglRestoreBufferRegionARB GLeeFuncPtr_wglRestoreBufferRegionARB +#endif +#endif + +/* WGL_ARB_multisample */ + +#ifndef WGL_ARB_multisample +#define WGL_ARB_multisample 1 +#define __GLEE_WGL_ARB_multisample 1 +/* Constants */ +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 +#endif + +/* WGL_ARB_extensions_string */ + +#ifndef WGL_ARB_extensions_string +#define WGL_ARB_extensions_string 1 +#define __GLEE_WGL_ARB_extensions_string 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_wglGetExtensionsStringARB +#define GLEE_H_DEFINED_wglGetExtensionsStringARB + typedef const char * (APIENTRYP GLEEPFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); + GLEE_EXTERN GLEEPFNWGLGETEXTENSIONSSTRINGARBPROC GLeeFuncPtr_wglGetExtensionsStringARB; + #define wglGetExtensionsStringARB GLeeFuncPtr_wglGetExtensionsStringARB +#endif +#endif + +/* WGL_ARB_pixel_format */ + +#ifndef WGL_ARB_pixel_format +#define WGL_ARB_pixel_format 1 +#define __GLEE_WGL_ARB_pixel_format 1 +/* Constants */ +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +#ifndef GLEE_H_DEFINED_wglGetPixelFormatAttribivARB +#define GLEE_H_DEFINED_wglGetPixelFormatAttribivARB + typedef BOOL (APIENTRYP GLEEPFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int * piAttributes, int * piValues); + GLEE_EXTERN GLEEPFNWGLGETPIXELFORMATATTRIBIVARBPROC GLeeFuncPtr_wglGetPixelFormatAttribivARB; + #define wglGetPixelFormatAttribivARB GLeeFuncPtr_wglGetPixelFormatAttribivARB +#endif +#ifndef GLEE_H_DEFINED_wglGetPixelFormatAttribfvARB +#define GLEE_H_DEFINED_wglGetPixelFormatAttribfvARB + typedef BOOL (APIENTRYP GLEEPFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int * piAttributes, FLOAT * pfValues); + GLEE_EXTERN GLEEPFNWGLGETPIXELFORMATATTRIBFVARBPROC GLeeFuncPtr_wglGetPixelFormatAttribfvARB; + #define wglGetPixelFormatAttribfvARB GLeeFuncPtr_wglGetPixelFormatAttribfvARB +#endif +#ifndef GLEE_H_DEFINED_wglChoosePixelFormatARB +#define GLEE_H_DEFINED_wglChoosePixelFormatARB + typedef BOOL (APIENTRYP GLEEPFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int * piAttribIList, const FLOAT * pfAttribFList, UINT nMaxFormats, int * piFormats, UINT * nNumFormats); + GLEE_EXTERN GLEEPFNWGLCHOOSEPIXELFORMATARBPROC GLeeFuncPtr_wglChoosePixelFormatARB; + #define wglChoosePixelFormatARB GLeeFuncPtr_wglChoosePixelFormatARB +#endif +#endif + +/* WGL_ARB_make_current_read */ + +#ifndef WGL_ARB_make_current_read +#define WGL_ARB_make_current_read 1 +#define __GLEE_WGL_ARB_make_current_read 1 +/* Constants */ +#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 +#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 +#ifndef GLEE_H_DEFINED_wglMakeContextCurrentARB +#define GLEE_H_DEFINED_wglMakeContextCurrentARB + typedef BOOL (APIENTRYP GLEEPFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); + GLEE_EXTERN GLEEPFNWGLMAKECONTEXTCURRENTARBPROC GLeeFuncPtr_wglMakeContextCurrentARB; + #define wglMakeContextCurrentARB GLeeFuncPtr_wglMakeContextCurrentARB +#endif +#ifndef GLEE_H_DEFINED_wglGetCurrentReadDCARB +#define GLEE_H_DEFINED_wglGetCurrentReadDCARB + typedef HDC (APIENTRYP GLEEPFNWGLGETCURRENTREADDCARBPROC) (); + GLEE_EXTERN GLEEPFNWGLGETCURRENTREADDCARBPROC GLeeFuncPtr_wglGetCurrentReadDCARB; + #define wglGetCurrentReadDCARB GLeeFuncPtr_wglGetCurrentReadDCARB +#endif +#endif + +/* WGL_ARB_pbuffer */ + +#ifndef WGL_ARB_pbuffer +#define WGL_ARB_pbuffer 1 +#define __GLEE_WGL_ARB_pbuffer 1 +/* Constants */ +#define WGL_DRAW_TO_PBUFFER_ARB 0x202D +#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E +#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 +#define WGL_PBUFFER_LARGEST_ARB 0x2033 +#define WGL_PBUFFER_WIDTH_ARB 0x2034 +#define WGL_PBUFFER_HEIGHT_ARB 0x2035 +#define WGL_PBUFFER_LOST_ARB 0x2036 +#ifndef GLEE_H_DEFINED_wglCreatePbufferARB +#define GLEE_H_DEFINED_wglCreatePbufferARB + typedef HPBUFFERARB (APIENTRYP GLEEPFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int * piAttribList); + GLEE_EXTERN GLEEPFNWGLCREATEPBUFFERARBPROC GLeeFuncPtr_wglCreatePbufferARB; + #define wglCreatePbufferARB GLeeFuncPtr_wglCreatePbufferARB +#endif +#ifndef GLEE_H_DEFINED_wglGetPbufferDCARB +#define GLEE_H_DEFINED_wglGetPbufferDCARB + typedef HDC (APIENTRYP GLEEPFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); + GLEE_EXTERN GLEEPFNWGLGETPBUFFERDCARBPROC GLeeFuncPtr_wglGetPbufferDCARB; + #define wglGetPbufferDCARB GLeeFuncPtr_wglGetPbufferDCARB +#endif +#ifndef GLEE_H_DEFINED_wglReleasePbufferDCARB +#define GLEE_H_DEFINED_wglReleasePbufferDCARB + typedef int (APIENTRYP GLEEPFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); + GLEE_EXTERN GLEEPFNWGLRELEASEPBUFFERDCARBPROC GLeeFuncPtr_wglReleasePbufferDCARB; + #define wglReleasePbufferDCARB GLeeFuncPtr_wglReleasePbufferDCARB +#endif +#ifndef GLEE_H_DEFINED_wglDestroyPbufferARB +#define GLEE_H_DEFINED_wglDestroyPbufferARB + typedef BOOL (APIENTRYP GLEEPFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); + GLEE_EXTERN GLEEPFNWGLDESTROYPBUFFERARBPROC GLeeFuncPtr_wglDestroyPbufferARB; + #define wglDestroyPbufferARB GLeeFuncPtr_wglDestroyPbufferARB +#endif +#ifndef GLEE_H_DEFINED_wglQueryPbufferARB +#define GLEE_H_DEFINED_wglQueryPbufferARB + typedef BOOL (APIENTRYP GLEEPFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int * piValue); + GLEE_EXTERN GLEEPFNWGLQUERYPBUFFERARBPROC GLeeFuncPtr_wglQueryPbufferARB; + #define wglQueryPbufferARB GLeeFuncPtr_wglQueryPbufferARB +#endif +#endif + +/* WGL_ARB_render_texture */ + +#ifndef WGL_ARB_render_texture +#define WGL_ARB_render_texture 1 +#define __GLEE_WGL_ARB_render_texture 1 +/* Constants */ +#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 +#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 +#define WGL_TEXTURE_FORMAT_ARB 0x2072 +#define WGL_TEXTURE_TARGET_ARB 0x2073 +#define WGL_MIPMAP_TEXTURE_ARB 0x2074 +#define WGL_TEXTURE_RGB_ARB 0x2075 +#define WGL_TEXTURE_RGBA_ARB 0x2076 +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 +#define WGL_TEXTURE_1D_ARB 0x2079 +#define WGL_TEXTURE_2D_ARB 0x207A +#define WGL_MIPMAP_LEVEL_ARB 0x207B +#define WGL_CUBE_MAP_FACE_ARB 0x207C +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 +#define WGL_FRONT_LEFT_ARB 0x2083 +#define WGL_FRONT_RIGHT_ARB 0x2084 +#define WGL_BACK_LEFT_ARB 0x2085 +#define WGL_BACK_RIGHT_ARB 0x2086 +#define WGL_AUX0_ARB 0x2087 +#define WGL_AUX1_ARB 0x2088 +#define WGL_AUX2_ARB 0x2089 +#define WGL_AUX3_ARB 0x208A +#define WGL_AUX4_ARB 0x208B +#define WGL_AUX5_ARB 0x208C +#define WGL_AUX6_ARB 0x208D +#define WGL_AUX7_ARB 0x208E +#define WGL_AUX8_ARB 0x208F +#define WGL_AUX9_ARB 0x2090 +#ifndef GLEE_H_DEFINED_wglBindTexImageARB +#define GLEE_H_DEFINED_wglBindTexImageARB + typedef BOOL (APIENTRYP GLEEPFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); + GLEE_EXTERN GLEEPFNWGLBINDTEXIMAGEARBPROC GLeeFuncPtr_wglBindTexImageARB; + #define wglBindTexImageARB GLeeFuncPtr_wglBindTexImageARB +#endif +#ifndef GLEE_H_DEFINED_wglReleaseTexImageARB +#define GLEE_H_DEFINED_wglReleaseTexImageARB + typedef BOOL (APIENTRYP GLEEPFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); + GLEE_EXTERN GLEEPFNWGLRELEASETEXIMAGEARBPROC GLeeFuncPtr_wglReleaseTexImageARB; + #define wglReleaseTexImageARB GLeeFuncPtr_wglReleaseTexImageARB +#endif +#ifndef GLEE_H_DEFINED_wglSetPbufferAttribARB +#define GLEE_H_DEFINED_wglSetPbufferAttribARB + typedef BOOL (APIENTRYP GLEEPFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int * piAttribList); + GLEE_EXTERN GLEEPFNWGLSETPBUFFERATTRIBARBPROC GLeeFuncPtr_wglSetPbufferAttribARB; + #define wglSetPbufferAttribARB GLeeFuncPtr_wglSetPbufferAttribARB +#endif +#endif + +/* WGL_ARB_pixel_format_float */ + +#ifndef WGL_ARB_pixel_format_float +#define WGL_ARB_pixel_format_float 1 +#define __GLEE_WGL_ARB_pixel_format_float 1 +/* Constants */ +#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 +#endif + +/* WGL_ARB_create_context */ + +#ifndef WGL_ARB_create_context +#define WGL_ARB_create_context 1 +#define __GLEE_WGL_ARB_create_context 1 +/* Constants */ +#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 +#define WGL_CONTEXT_FLAGS_ARB 0x2094 +#define ERROR_INVALID_VERSION_ARB 0x2095 +#ifndef GLEE_H_DEFINED_wglCreateContextAttribsARB +#define GLEE_H_DEFINED_wglCreateContextAttribsARB + typedef HGLRC (APIENTRYP GLEEPFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int * attribList); + GLEE_EXTERN GLEEPFNWGLCREATECONTEXTATTRIBSARBPROC GLeeFuncPtr_wglCreateContextAttribsARB; + #define wglCreateContextAttribsARB GLeeFuncPtr_wglCreateContextAttribsARB +#endif +#endif + +/* WGL_EXT_make_current_read */ + +#ifndef WGL_EXT_make_current_read +#define WGL_EXT_make_current_read 1 +#define __GLEE_WGL_EXT_make_current_read 1 +/* Constants */ +#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 +#ifndef GLEE_H_DEFINED_wglMakeContextCurrentEXT +#define GLEE_H_DEFINED_wglMakeContextCurrentEXT + typedef BOOL (APIENTRYP GLEEPFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); + GLEE_EXTERN GLEEPFNWGLMAKECONTEXTCURRENTEXTPROC GLeeFuncPtr_wglMakeContextCurrentEXT; + #define wglMakeContextCurrentEXT GLeeFuncPtr_wglMakeContextCurrentEXT +#endif +#ifndef GLEE_H_DEFINED_wglGetCurrentReadDCEXT +#define GLEE_H_DEFINED_wglGetCurrentReadDCEXT + typedef HDC (APIENTRYP GLEEPFNWGLGETCURRENTREADDCEXTPROC) (); + GLEE_EXTERN GLEEPFNWGLGETCURRENTREADDCEXTPROC GLeeFuncPtr_wglGetCurrentReadDCEXT; + #define wglGetCurrentReadDCEXT GLeeFuncPtr_wglGetCurrentReadDCEXT +#endif +#endif + +/* WGL_EXT_pixel_format */ + +#ifndef WGL_EXT_pixel_format +#define WGL_EXT_pixel_format 1 +#define __GLEE_WGL_EXT_pixel_format 1 +/* Constants */ +#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 +#define WGL_DRAW_TO_WINDOW_EXT 0x2001 +#define WGL_DRAW_TO_BITMAP_EXT 0x2002 +#define WGL_ACCELERATION_EXT 0x2003 +#define WGL_NEED_PALETTE_EXT 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 +#define WGL_SWAP_METHOD_EXT 0x2007 +#define WGL_NUMBER_OVERLAYS_EXT 0x2008 +#define WGL_NUMBER_UNDERLAYS_EXT 0x2009 +#define WGL_TRANSPARENT_EXT 0x200A +#define WGL_TRANSPARENT_VALUE_EXT 0x200B +#define WGL_SHARE_DEPTH_EXT 0x200C +#define WGL_SHARE_STENCIL_EXT 0x200D +#define WGL_SHARE_ACCUM_EXT 0x200E +#define WGL_SUPPORT_GDI_EXT 0x200F +#define WGL_SUPPORT_OPENGL_EXT 0x2010 +#define WGL_DOUBLE_BUFFER_EXT 0x2011 +#define WGL_STEREO_EXT 0x2012 +#define WGL_PIXEL_TYPE_EXT 0x2013 +#define WGL_COLOR_BITS_EXT 0x2014 +#define WGL_RED_BITS_EXT 0x2015 +#define WGL_RED_SHIFT_EXT 0x2016 +#define WGL_GREEN_BITS_EXT 0x2017 +#define WGL_GREEN_SHIFT_EXT 0x2018 +#define WGL_BLUE_BITS_EXT 0x2019 +#define WGL_BLUE_SHIFT_EXT 0x201A +#define WGL_ALPHA_BITS_EXT 0x201B +#define WGL_ALPHA_SHIFT_EXT 0x201C +#define WGL_ACCUM_BITS_EXT 0x201D +#define WGL_ACCUM_RED_BITS_EXT 0x201E +#define WGL_ACCUM_GREEN_BITS_EXT 0x201F +#define WGL_ACCUM_BLUE_BITS_EXT 0x2020 +#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 +#define WGL_DEPTH_BITS_EXT 0x2022 +#define WGL_STENCIL_BITS_EXT 0x2023 +#define WGL_AUX_BUFFERS_EXT 0x2024 +#define WGL_NO_ACCELERATION_EXT 0x2025 +#define WGL_GENERIC_ACCELERATION_EXT 0x2026 +#define WGL_FULL_ACCELERATION_EXT 0x2027 +#define WGL_SWAP_EXCHANGE_EXT 0x2028 +#define WGL_SWAP_COPY_EXT 0x2029 +#define WGL_SWAP_UNDEFINED_EXT 0x202A +#define WGL_TYPE_RGBA_EXT 0x202B +#define WGL_TYPE_COLORINDEX_EXT 0x202C +#ifndef GLEE_H_DEFINED_wglGetPixelFormatAttribivEXT +#define GLEE_H_DEFINED_wglGetPixelFormatAttribivEXT + typedef BOOL (APIENTRYP GLEEPFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int * piAttributes, int * piValues); + GLEE_EXTERN GLEEPFNWGLGETPIXELFORMATATTRIBIVEXTPROC GLeeFuncPtr_wglGetPixelFormatAttribivEXT; + #define wglGetPixelFormatAttribivEXT GLeeFuncPtr_wglGetPixelFormatAttribivEXT +#endif +#ifndef GLEE_H_DEFINED_wglGetPixelFormatAttribfvEXT +#define GLEE_H_DEFINED_wglGetPixelFormatAttribfvEXT + typedef BOOL (APIENTRYP GLEEPFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int * piAttributes, FLOAT * pfValues); + GLEE_EXTERN GLEEPFNWGLGETPIXELFORMATATTRIBFVEXTPROC GLeeFuncPtr_wglGetPixelFormatAttribfvEXT; + #define wglGetPixelFormatAttribfvEXT GLeeFuncPtr_wglGetPixelFormatAttribfvEXT +#endif +#ifndef GLEE_H_DEFINED_wglChoosePixelFormatEXT +#define GLEE_H_DEFINED_wglChoosePixelFormatEXT + typedef BOOL (APIENTRYP GLEEPFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int * piAttribIList, const FLOAT * pfAttribFList, UINT nMaxFormats, int * piFormats, UINT * nNumFormats); + GLEE_EXTERN GLEEPFNWGLCHOOSEPIXELFORMATEXTPROC GLeeFuncPtr_wglChoosePixelFormatEXT; + #define wglChoosePixelFormatEXT GLeeFuncPtr_wglChoosePixelFormatEXT +#endif +#endif + +/* WGL_EXT_pbuffer */ + +#ifndef WGL_EXT_pbuffer +#define WGL_EXT_pbuffer 1 +#define __GLEE_WGL_EXT_pbuffer 1 +/* Constants */ +#define WGL_DRAW_TO_PBUFFER_EXT 0x202D +#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E +#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 +#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 +#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 +#define WGL_PBUFFER_LARGEST_EXT 0x2033 +#define WGL_PBUFFER_WIDTH_EXT 0x2034 +#define WGL_PBUFFER_HEIGHT_EXT 0x2035 +#ifndef GLEE_H_DEFINED_wglCreatePbufferEXT +#define GLEE_H_DEFINED_wglCreatePbufferEXT + typedef HPBUFFEREXT (APIENTRYP GLEEPFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int * piAttribList); + GLEE_EXTERN GLEEPFNWGLCREATEPBUFFEREXTPROC GLeeFuncPtr_wglCreatePbufferEXT; + #define wglCreatePbufferEXT GLeeFuncPtr_wglCreatePbufferEXT +#endif +#ifndef GLEE_H_DEFINED_wglGetPbufferDCEXT +#define GLEE_H_DEFINED_wglGetPbufferDCEXT + typedef HDC (APIENTRYP GLEEPFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); + GLEE_EXTERN GLEEPFNWGLGETPBUFFERDCEXTPROC GLeeFuncPtr_wglGetPbufferDCEXT; + #define wglGetPbufferDCEXT GLeeFuncPtr_wglGetPbufferDCEXT +#endif +#ifndef GLEE_H_DEFINED_wglReleasePbufferDCEXT +#define GLEE_H_DEFINED_wglReleasePbufferDCEXT + typedef int (APIENTRYP GLEEPFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); + GLEE_EXTERN GLEEPFNWGLRELEASEPBUFFERDCEXTPROC GLeeFuncPtr_wglReleasePbufferDCEXT; + #define wglReleasePbufferDCEXT GLeeFuncPtr_wglReleasePbufferDCEXT +#endif +#ifndef GLEE_H_DEFINED_wglDestroyPbufferEXT +#define GLEE_H_DEFINED_wglDestroyPbufferEXT + typedef BOOL (APIENTRYP GLEEPFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); + GLEE_EXTERN GLEEPFNWGLDESTROYPBUFFEREXTPROC GLeeFuncPtr_wglDestroyPbufferEXT; + #define wglDestroyPbufferEXT GLeeFuncPtr_wglDestroyPbufferEXT +#endif +#ifndef GLEE_H_DEFINED_wglQueryPbufferEXT +#define GLEE_H_DEFINED_wglQueryPbufferEXT + typedef BOOL (APIENTRYP GLEEPFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int * piValue); + GLEE_EXTERN GLEEPFNWGLQUERYPBUFFEREXTPROC GLeeFuncPtr_wglQueryPbufferEXT; + #define wglQueryPbufferEXT GLeeFuncPtr_wglQueryPbufferEXT +#endif +#endif + +/* WGL_EXT_depth_float */ + +#ifndef WGL_EXT_depth_float +#define WGL_EXT_depth_float 1 +#define __GLEE_WGL_EXT_depth_float 1 +/* Constants */ +#define WGL_DEPTH_FLOAT_EXT 0x2040 +#endif + +/* WGL_3DFX_multisample */ + +#ifndef WGL_3DFX_multisample +#define WGL_3DFX_multisample 1 +#define __GLEE_WGL_3DFX_multisample 1 +/* Constants */ +#define WGL_SAMPLE_BUFFERS_3DFX 0x2060 +#define WGL_SAMPLES_3DFX 0x2061 +#endif + +/* WGL_EXT_multisample */ + +#ifndef WGL_EXT_multisample +#define WGL_EXT_multisample 1 +#define __GLEE_WGL_EXT_multisample 1 +/* Constants */ +#define WGL_SAMPLE_BUFFERS_EXT 0x2041 +#define WGL_SAMPLES_EXT 0x2042 +#endif + +/* WGL_I3D_digital_video_control */ + +#ifndef WGL_I3D_digital_video_control +#define WGL_I3D_digital_video_control 1 +#define __GLEE_WGL_I3D_digital_video_control 1 +/* Constants */ +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 +#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 +#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 +#ifndef GLEE_H_DEFINED_wglGetDigitalVideoParametersI3D +#define GLEE_H_DEFINED_wglGetDigitalVideoParametersI3D + typedef BOOL (APIENTRYP GLEEPFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int * piValue); + GLEE_EXTERN GLEEPFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC GLeeFuncPtr_wglGetDigitalVideoParametersI3D; + #define wglGetDigitalVideoParametersI3D GLeeFuncPtr_wglGetDigitalVideoParametersI3D +#endif +#ifndef GLEE_H_DEFINED_wglSetDigitalVideoParametersI3D +#define GLEE_H_DEFINED_wglSetDigitalVideoParametersI3D + typedef BOOL (APIENTRYP GLEEPFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int * piValue); + GLEE_EXTERN GLEEPFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC GLeeFuncPtr_wglSetDigitalVideoParametersI3D; + #define wglSetDigitalVideoParametersI3D GLeeFuncPtr_wglSetDigitalVideoParametersI3D +#endif +#endif + +/* WGL_I3D_gamma */ + +#ifndef WGL_I3D_gamma +#define WGL_I3D_gamma 1 +#define __GLEE_WGL_I3D_gamma 1 +/* Constants */ +#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E +#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F +#ifndef GLEE_H_DEFINED_wglGetGammaTableParametersI3D +#define GLEE_H_DEFINED_wglGetGammaTableParametersI3D + typedef BOOL (APIENTRYP GLEEPFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int * piValue); + GLEE_EXTERN GLEEPFNWGLGETGAMMATABLEPARAMETERSI3DPROC GLeeFuncPtr_wglGetGammaTableParametersI3D; + #define wglGetGammaTableParametersI3D GLeeFuncPtr_wglGetGammaTableParametersI3D +#endif +#ifndef GLEE_H_DEFINED_wglSetGammaTableParametersI3D +#define GLEE_H_DEFINED_wglSetGammaTableParametersI3D + typedef BOOL (APIENTRYP GLEEPFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int * piValue); + GLEE_EXTERN GLEEPFNWGLSETGAMMATABLEPARAMETERSI3DPROC GLeeFuncPtr_wglSetGammaTableParametersI3D; + #define wglSetGammaTableParametersI3D GLeeFuncPtr_wglSetGammaTableParametersI3D +#endif +#ifndef GLEE_H_DEFINED_wglGetGammaTableI3D +#define GLEE_H_DEFINED_wglGetGammaTableI3D + typedef BOOL (APIENTRYP GLEEPFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT * puRed, USHORT * puGreen, USHORT * puBlue); + GLEE_EXTERN GLEEPFNWGLGETGAMMATABLEI3DPROC GLeeFuncPtr_wglGetGammaTableI3D; + #define wglGetGammaTableI3D GLeeFuncPtr_wglGetGammaTableI3D +#endif +#ifndef GLEE_H_DEFINED_wglSetGammaTableI3D +#define GLEE_H_DEFINED_wglSetGammaTableI3D + typedef BOOL (APIENTRYP GLEEPFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT * puRed, const USHORT * puGreen, const USHORT * puBlue); + GLEE_EXTERN GLEEPFNWGLSETGAMMATABLEI3DPROC GLeeFuncPtr_wglSetGammaTableI3D; + #define wglSetGammaTableI3D GLeeFuncPtr_wglSetGammaTableI3D +#endif +#endif + +/* WGL_I3D_genlock */ + +#ifndef WGL_I3D_genlock +#define WGL_I3D_genlock 1 +#define __GLEE_WGL_I3D_genlock 1 +/* Constants */ +#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 +#define WGL_GENLOCK_SOURCE_EXTENAL_SYNC_I3D 0x2045 +#define WGL_GENLOCK_SOURCE_EXTENAL_FIELD_I3D 0x2046 +#define WGL_GENLOCK_SOURCE_EXTENAL_TTL_I3D 0x2047 +#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 +#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 +#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A +#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B +#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C +#ifndef GLEE_H_DEFINED_wglEnableGenlockI3D +#define GLEE_H_DEFINED_wglEnableGenlockI3D + typedef BOOL (APIENTRYP GLEEPFNWGLENABLEGENLOCKI3DPROC) (HDC hDC); + GLEE_EXTERN GLEEPFNWGLENABLEGENLOCKI3DPROC GLeeFuncPtr_wglEnableGenlockI3D; + #define wglEnableGenlockI3D GLeeFuncPtr_wglEnableGenlockI3D +#endif +#ifndef GLEE_H_DEFINED_wglDisableGenlockI3D +#define GLEE_H_DEFINED_wglDisableGenlockI3D + typedef BOOL (APIENTRYP GLEEPFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC); + GLEE_EXTERN GLEEPFNWGLDISABLEGENLOCKI3DPROC GLeeFuncPtr_wglDisableGenlockI3D; + #define wglDisableGenlockI3D GLeeFuncPtr_wglDisableGenlockI3D +#endif +#ifndef GLEE_H_DEFINED_wglIsEnabledGenlockI3D +#define GLEE_H_DEFINED_wglIsEnabledGenlockI3D + typedef BOOL (APIENTRYP GLEEPFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL * pFlag); + GLEE_EXTERN GLEEPFNWGLISENABLEDGENLOCKI3DPROC GLeeFuncPtr_wglIsEnabledGenlockI3D; + #define wglIsEnabledGenlockI3D GLeeFuncPtr_wglIsEnabledGenlockI3D +#endif +#ifndef GLEE_H_DEFINED_wglGenlockSourceI3D +#define GLEE_H_DEFINED_wglGenlockSourceI3D + typedef BOOL (APIENTRYP GLEEPFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource); + GLEE_EXTERN GLEEPFNWGLGENLOCKSOURCEI3DPROC GLeeFuncPtr_wglGenlockSourceI3D; + #define wglGenlockSourceI3D GLeeFuncPtr_wglGenlockSourceI3D +#endif +#ifndef GLEE_H_DEFINED_wglGetGenlockSourceI3D +#define GLEE_H_DEFINED_wglGetGenlockSourceI3D + typedef BOOL (APIENTRYP GLEEPFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT * uSource); + GLEE_EXTERN GLEEPFNWGLGETGENLOCKSOURCEI3DPROC GLeeFuncPtr_wglGetGenlockSourceI3D; + #define wglGetGenlockSourceI3D GLeeFuncPtr_wglGetGenlockSourceI3D +#endif +#ifndef GLEE_H_DEFINED_wglGenlockSourceEdgeI3D +#define GLEE_H_DEFINED_wglGenlockSourceEdgeI3D + typedef BOOL (APIENTRYP GLEEPFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge); + GLEE_EXTERN GLEEPFNWGLGENLOCKSOURCEEDGEI3DPROC GLeeFuncPtr_wglGenlockSourceEdgeI3D; + #define wglGenlockSourceEdgeI3D GLeeFuncPtr_wglGenlockSourceEdgeI3D +#endif +#ifndef GLEE_H_DEFINED_wglGetGenlockSourceEdgeI3D +#define GLEE_H_DEFINED_wglGetGenlockSourceEdgeI3D + typedef BOOL (APIENTRYP GLEEPFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT * uEdge); + GLEE_EXTERN GLEEPFNWGLGETGENLOCKSOURCEEDGEI3DPROC GLeeFuncPtr_wglGetGenlockSourceEdgeI3D; + #define wglGetGenlockSourceEdgeI3D GLeeFuncPtr_wglGetGenlockSourceEdgeI3D +#endif +#ifndef GLEE_H_DEFINED_wglGenlockSampleRateI3D +#define GLEE_H_DEFINED_wglGenlockSampleRateI3D + typedef BOOL (APIENTRYP GLEEPFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate); + GLEE_EXTERN GLEEPFNWGLGENLOCKSAMPLERATEI3DPROC GLeeFuncPtr_wglGenlockSampleRateI3D; + #define wglGenlockSampleRateI3D GLeeFuncPtr_wglGenlockSampleRateI3D +#endif +#ifndef GLEE_H_DEFINED_wglGetGenlockSampleRateI3D +#define GLEE_H_DEFINED_wglGetGenlockSampleRateI3D + typedef BOOL (APIENTRYP GLEEPFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT * uRate); + GLEE_EXTERN GLEEPFNWGLGETGENLOCKSAMPLERATEI3DPROC GLeeFuncPtr_wglGetGenlockSampleRateI3D; + #define wglGetGenlockSampleRateI3D GLeeFuncPtr_wglGetGenlockSampleRateI3D +#endif +#ifndef GLEE_H_DEFINED_wglGenlockSourceDelayI3D +#define GLEE_H_DEFINED_wglGenlockSourceDelayI3D + typedef BOOL (APIENTRYP GLEEPFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay); + GLEE_EXTERN GLEEPFNWGLGENLOCKSOURCEDELAYI3DPROC GLeeFuncPtr_wglGenlockSourceDelayI3D; + #define wglGenlockSourceDelayI3D GLeeFuncPtr_wglGenlockSourceDelayI3D +#endif +#ifndef GLEE_H_DEFINED_wglGetGenlockSourceDelayI3D +#define GLEE_H_DEFINED_wglGetGenlockSourceDelayI3D + typedef BOOL (APIENTRYP GLEEPFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT * uDelay); + GLEE_EXTERN GLEEPFNWGLGETGENLOCKSOURCEDELAYI3DPROC GLeeFuncPtr_wglGetGenlockSourceDelayI3D; + #define wglGetGenlockSourceDelayI3D GLeeFuncPtr_wglGetGenlockSourceDelayI3D +#endif +#ifndef GLEE_H_DEFINED_wglQueryGenlockMaxSourceDelayI3D +#define GLEE_H_DEFINED_wglQueryGenlockMaxSourceDelayI3D + typedef BOOL (APIENTRYP GLEEPFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT * uMaxLineDelay, UINT * uMaxPixelDelay); + GLEE_EXTERN GLEEPFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC GLeeFuncPtr_wglQueryGenlockMaxSourceDelayI3D; + #define wglQueryGenlockMaxSourceDelayI3D GLeeFuncPtr_wglQueryGenlockMaxSourceDelayI3D +#endif +#endif + +/* WGL_I3D_image_buffer */ + +#ifndef WGL_I3D_image_buffer +#define WGL_I3D_image_buffer 1 +#define __GLEE_WGL_I3D_image_buffer 1 +/* Constants */ +#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001 +#define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002 +#ifndef GLEE_H_DEFINED_wglCreateImageBufferI3D +#define GLEE_H_DEFINED_wglCreateImageBufferI3D + typedef LPVOID (APIENTRYP GLEEPFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags); + GLEE_EXTERN GLEEPFNWGLCREATEIMAGEBUFFERI3DPROC GLeeFuncPtr_wglCreateImageBufferI3D; + #define wglCreateImageBufferI3D GLeeFuncPtr_wglCreateImageBufferI3D +#endif +#ifndef GLEE_H_DEFINED_wglDestroyImageBufferI3D +#define GLEE_H_DEFINED_wglDestroyImageBufferI3D + typedef BOOL (APIENTRYP GLEEPFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress); + GLEE_EXTERN GLEEPFNWGLDESTROYIMAGEBUFFERI3DPROC GLeeFuncPtr_wglDestroyImageBufferI3D; + #define wglDestroyImageBufferI3D GLeeFuncPtr_wglDestroyImageBufferI3D +#endif +#ifndef GLEE_H_DEFINED_wglAssociateImageBufferEventsI3D +#define GLEE_H_DEFINED_wglAssociateImageBufferEventsI3D + typedef BOOL (APIENTRYP GLEEPFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const HANDLE * pEvent, const LPVOID * pAddress, const DWORD * pSize, UINT count); + GLEE_EXTERN GLEEPFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC GLeeFuncPtr_wglAssociateImageBufferEventsI3D; + #define wglAssociateImageBufferEventsI3D GLeeFuncPtr_wglAssociateImageBufferEventsI3D +#endif +#ifndef GLEE_H_DEFINED_wglReleaseImageBufferEventsI3D +#define GLEE_H_DEFINED_wglReleaseImageBufferEventsI3D + typedef BOOL (APIENTRYP GLEEPFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const LPVOID * pAddress, UINT count); + GLEE_EXTERN GLEEPFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC GLeeFuncPtr_wglReleaseImageBufferEventsI3D; + #define wglReleaseImageBufferEventsI3D GLeeFuncPtr_wglReleaseImageBufferEventsI3D +#endif +#endif + +/* WGL_I3D_swap_frame_lock */ + +#ifndef WGL_I3D_swap_frame_lock +#define WGL_I3D_swap_frame_lock 1 +#define __GLEE_WGL_I3D_swap_frame_lock 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_wglEnableFrameLockI3D +#define GLEE_H_DEFINED_wglEnableFrameLockI3D + typedef BOOL (APIENTRYP GLEEPFNWGLENABLEFRAMELOCKI3DPROC) (); + GLEE_EXTERN GLEEPFNWGLENABLEFRAMELOCKI3DPROC GLeeFuncPtr_wglEnableFrameLockI3D; + #define wglEnableFrameLockI3D GLeeFuncPtr_wglEnableFrameLockI3D +#endif +#ifndef GLEE_H_DEFINED_wglDisableFrameLockI3D +#define GLEE_H_DEFINED_wglDisableFrameLockI3D + typedef BOOL (APIENTRYP GLEEPFNWGLDISABLEFRAMELOCKI3DPROC) (); + GLEE_EXTERN GLEEPFNWGLDISABLEFRAMELOCKI3DPROC GLeeFuncPtr_wglDisableFrameLockI3D; + #define wglDisableFrameLockI3D GLeeFuncPtr_wglDisableFrameLockI3D +#endif +#ifndef GLEE_H_DEFINED_wglIsEnabledFrameLockI3D +#define GLEE_H_DEFINED_wglIsEnabledFrameLockI3D + typedef BOOL (APIENTRYP GLEEPFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL * pFlag); + GLEE_EXTERN GLEEPFNWGLISENABLEDFRAMELOCKI3DPROC GLeeFuncPtr_wglIsEnabledFrameLockI3D; + #define wglIsEnabledFrameLockI3D GLeeFuncPtr_wglIsEnabledFrameLockI3D +#endif +#ifndef GLEE_H_DEFINED_wglQueryFrameLockMasterI3D +#define GLEE_H_DEFINED_wglQueryFrameLockMasterI3D + typedef BOOL (APIENTRYP GLEEPFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL * pFlag); + GLEE_EXTERN GLEEPFNWGLQUERYFRAMELOCKMASTERI3DPROC GLeeFuncPtr_wglQueryFrameLockMasterI3D; + #define wglQueryFrameLockMasterI3D GLeeFuncPtr_wglQueryFrameLockMasterI3D +#endif +#endif + +/* WGL_NV_render_depth_texture */ + +#ifndef WGL_NV_render_depth_texture +#define WGL_NV_render_depth_texture 1 +#define __GLEE_WGL_NV_render_depth_texture 1 +/* Constants */ +#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 +#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 +#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 +#define WGL_DEPTH_COMPONENT_NV 0x20A7 +#endif + +/* WGL_NV_render_texture_rectangle */ + +#ifndef WGL_NV_render_texture_rectangle +#define WGL_NV_render_texture_rectangle 1 +#define __GLEE_WGL_NV_render_texture_rectangle 1 +/* Constants */ +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 +#define WGL_TEXTURE_RECTANGLE_NV 0x20A2 +#endif + +/* WGL_ATI_pixel_format_float */ + +#ifndef WGL_ATI_pixel_format_float +#define WGL_ATI_pixel_format_float 1 +#define __GLEE_WGL_ATI_pixel_format_float 1 +/* Constants */ +#define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0 +#endif + +/* WGL_NV_float_buffer */ + +#ifndef WGL_NV_float_buffer +#define WGL_NV_float_buffer 1 +#define __GLEE_WGL_NV_float_buffer 1 +/* Constants */ +#define WGL_FLOAT_COMPONENTS_NV 0x20B0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4 +#define WGL_TEXTURE_FLOAT_R_NV 0x20B5 +#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6 +#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7 +#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8 +#endif + +/* WGL_3DL_stereo_control */ + +#ifndef WGL_3DL_stereo_control +#define WGL_3DL_stereo_control 1 +#define __GLEE_WGL_3DL_stereo_control 1 +/* Constants */ +#define WGL_STEREO_EMITTER_ENABLE_3DL 0x2055 +#define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056 +#define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057 +#define WGL_STEREO_POLARITY_INVERT_3DL 0x2058 +#endif + +/* WGL_EXT_pixel_format_packed_float */ + +#ifndef WGL_EXT_pixel_format_packed_float +#define WGL_EXT_pixel_format_packed_float 1 +#define __GLEE_WGL_EXT_pixel_format_packed_float 1 +/* Constants */ +#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8 +#endif + +/* WGL_EXT_framebuffer_sRGB */ + +#ifndef WGL_EXT_framebuffer_sRGB +#define WGL_EXT_framebuffer_sRGB 1 +#define __GLEE_WGL_EXT_framebuffer_sRGB 1 +/* Constants */ +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9 +#endif + +/* WGL_NV_present_video */ + +#ifndef WGL_NV_present_video +#define WGL_NV_present_video 1 +#define __GLEE_WGL_NV_present_video 1 +/* Constants */ +#define WGL_NUM_VIDEO_SLOTS_NV 0x20F0 +#ifndef GLEE_H_DEFINED_wglEnumerateVideoDevicesNV +#define GLEE_H_DEFINED_wglEnumerateVideoDevicesNV + typedef int (APIENTRYP GLEEPFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDC, HVIDEOOUTPUTDEVICENV * phDeviceList); + GLEE_EXTERN GLEEPFNWGLENUMERATEVIDEODEVICESNVPROC GLeeFuncPtr_wglEnumerateVideoDevicesNV; + #define wglEnumerateVideoDevicesNV GLeeFuncPtr_wglEnumerateVideoDevicesNV +#endif +#ifndef GLEE_H_DEFINED_wglBindVideoDeviceNV +#define GLEE_H_DEFINED_wglBindVideoDeviceNV + typedef BOOL (APIENTRYP GLEEPFNWGLBINDVIDEODEVICENVPROC) (HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int * piAttribList); + GLEE_EXTERN GLEEPFNWGLBINDVIDEODEVICENVPROC GLeeFuncPtr_wglBindVideoDeviceNV; + #define wglBindVideoDeviceNV GLeeFuncPtr_wglBindVideoDeviceNV +#endif +#ifndef GLEE_H_DEFINED_wglQueryCurrentContextNV +#define GLEE_H_DEFINED_wglQueryCurrentContextNV + typedef BOOL (APIENTRYP GLEEPFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int * piValue); + GLEE_EXTERN GLEEPFNWGLQUERYCURRENTCONTEXTNVPROC GLeeFuncPtr_wglQueryCurrentContextNV; + #define wglQueryCurrentContextNV GLeeFuncPtr_wglQueryCurrentContextNV +#endif +#endif + +/* WGL_NV_swap_group */ + +#ifndef WGL_NV_swap_group +#define WGL_NV_swap_group 1 +#define __GLEE_WGL_NV_swap_group 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_wglJoinSwapGroupNV +#define GLEE_H_DEFINED_wglJoinSwapGroupNV + typedef BOOL (APIENTRYP GLEEPFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group); + GLEE_EXTERN GLEEPFNWGLJOINSWAPGROUPNVPROC GLeeFuncPtr_wglJoinSwapGroupNV; + #define wglJoinSwapGroupNV GLeeFuncPtr_wglJoinSwapGroupNV +#endif +#ifndef GLEE_H_DEFINED_wglBindSwapBarrierNV +#define GLEE_H_DEFINED_wglBindSwapBarrierNV + typedef BOOL (APIENTRYP GLEEPFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier); + GLEE_EXTERN GLEEPFNWGLBINDSWAPBARRIERNVPROC GLeeFuncPtr_wglBindSwapBarrierNV; + #define wglBindSwapBarrierNV GLeeFuncPtr_wglBindSwapBarrierNV +#endif +#ifndef GLEE_H_DEFINED_wglQuerySwapGroupNV +#define GLEE_H_DEFINED_wglQuerySwapGroupNV + typedef BOOL (APIENTRYP GLEEPFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint * group, GLuint * barrier); + GLEE_EXTERN GLEEPFNWGLQUERYSWAPGROUPNVPROC GLeeFuncPtr_wglQuerySwapGroupNV; + #define wglQuerySwapGroupNV GLeeFuncPtr_wglQuerySwapGroupNV +#endif +#ifndef GLEE_H_DEFINED_wglQueryMaxSwapGroupsNV +#define GLEE_H_DEFINED_wglQueryMaxSwapGroupsNV + typedef BOOL (APIENTRYP GLEEPFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint * maxGroups, GLuint * maxBarriers); + GLEE_EXTERN GLEEPFNWGLQUERYMAXSWAPGROUPSNVPROC GLeeFuncPtr_wglQueryMaxSwapGroupsNV; + #define wglQueryMaxSwapGroupsNV GLeeFuncPtr_wglQueryMaxSwapGroupsNV +#endif +#ifndef GLEE_H_DEFINED_wglQueryFrameCountNV +#define GLEE_H_DEFINED_wglQueryFrameCountNV + typedef BOOL (APIENTRYP GLEEPFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint * count); + GLEE_EXTERN GLEEPFNWGLQUERYFRAMECOUNTNVPROC GLeeFuncPtr_wglQueryFrameCountNV; + #define wglQueryFrameCountNV GLeeFuncPtr_wglQueryFrameCountNV +#endif +#ifndef GLEE_H_DEFINED_wglResetFrameCountNV +#define GLEE_H_DEFINED_wglResetFrameCountNV + typedef BOOL (APIENTRYP GLEEPFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC); + GLEE_EXTERN GLEEPFNWGLRESETFRAMECOUNTNVPROC GLeeFuncPtr_wglResetFrameCountNV; + #define wglResetFrameCountNV GLeeFuncPtr_wglResetFrameCountNV +#endif +#endif + +/* WGL_NV_gpu_affinity */ + +#ifndef WGL_NV_gpu_affinity +#define WGL_NV_gpu_affinity 1 +#define __GLEE_WGL_NV_gpu_affinity 1 +/* Constants */ +#define WGL_ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0 +#define WGL_ERROR_MISSING_AFFINITY_MASK_NV 0x20D1 +#ifndef GLEE_H_DEFINED_wglEnumGpusNV +#define GLEE_H_DEFINED_wglEnumGpusNV + typedef BOOL (APIENTRYP GLEEPFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV * phGpu); + GLEE_EXTERN GLEEPFNWGLENUMGPUSNVPROC GLeeFuncPtr_wglEnumGpusNV; + #define wglEnumGpusNV GLeeFuncPtr_wglEnumGpusNV +#endif +#ifndef GLEE_H_DEFINED_wglEnumGpuDevicesNV +#define GLEE_H_DEFINED_wglEnumGpuDevicesNV + typedef BOOL (APIENTRYP GLEEPFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice); + GLEE_EXTERN GLEEPFNWGLENUMGPUDEVICESNVPROC GLeeFuncPtr_wglEnumGpuDevicesNV; + #define wglEnumGpuDevicesNV GLeeFuncPtr_wglEnumGpuDevicesNV +#endif +#ifndef GLEE_H_DEFINED_wglCreateAffinityDCNV +#define GLEE_H_DEFINED_wglCreateAffinityDCNV + typedef HDC (APIENTRYP GLEEPFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV * phGpuList); + GLEE_EXTERN GLEEPFNWGLCREATEAFFINITYDCNVPROC GLeeFuncPtr_wglCreateAffinityDCNV; + #define wglCreateAffinityDCNV GLeeFuncPtr_wglCreateAffinityDCNV +#endif +#ifndef GLEE_H_DEFINED_wglEnumGpusFromAffinityDCNV +#define GLEE_H_DEFINED_wglEnumGpusFromAffinityDCNV + typedef BOOL (APIENTRYP GLEEPFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV * hGpu); + GLEE_EXTERN GLEEPFNWGLENUMGPUSFROMAFFINITYDCNVPROC GLeeFuncPtr_wglEnumGpusFromAffinityDCNV; + #define wglEnumGpusFromAffinityDCNV GLeeFuncPtr_wglEnumGpusFromAffinityDCNV +#endif +#ifndef GLEE_H_DEFINED_wglDeleteDCNV +#define GLEE_H_DEFINED_wglDeleteDCNV + typedef BOOL (APIENTRYP GLEEPFNWGLDELETEDCNVPROC) (HDC hdc); + GLEE_EXTERN GLEEPFNWGLDELETEDCNVPROC GLeeFuncPtr_wglDeleteDCNV; + #define wglDeleteDCNV GLeeFuncPtr_wglDeleteDCNV +#endif +#endif + +/* WGL_EXT_display_color_table */ + +#ifndef WGL_EXT_display_color_table +#define WGL_EXT_display_color_table 1 +#define __GLEE_WGL_EXT_display_color_table 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_wglCreateDisplayColorTableEXT +#define GLEE_H_DEFINED_wglCreateDisplayColorTableEXT + typedef GLboolean (APIENTRYP GLEEPFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); + GLEE_EXTERN GLEEPFNWGLCREATEDISPLAYCOLORTABLEEXTPROC GLeeFuncPtr_wglCreateDisplayColorTableEXT; + #define wglCreateDisplayColorTableEXT GLeeFuncPtr_wglCreateDisplayColorTableEXT +#endif +#ifndef GLEE_H_DEFINED_wglLoadDisplayColorTableEXT +#define GLEE_H_DEFINED_wglLoadDisplayColorTableEXT + typedef GLboolean (APIENTRYP GLEEPFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort * table, GLuint length); + GLEE_EXTERN GLEEPFNWGLLOADDISPLAYCOLORTABLEEXTPROC GLeeFuncPtr_wglLoadDisplayColorTableEXT; + #define wglLoadDisplayColorTableEXT GLeeFuncPtr_wglLoadDisplayColorTableEXT +#endif +#ifndef GLEE_H_DEFINED_wglBindDisplayColorTableEXT +#define GLEE_H_DEFINED_wglBindDisplayColorTableEXT + typedef GLboolean (APIENTRYP GLEEPFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); + GLEE_EXTERN GLEEPFNWGLBINDDISPLAYCOLORTABLEEXTPROC GLeeFuncPtr_wglBindDisplayColorTableEXT; + #define wglBindDisplayColorTableEXT GLeeFuncPtr_wglBindDisplayColorTableEXT +#endif +#ifndef GLEE_H_DEFINED_wglDestroyDisplayColorTableEXT +#define GLEE_H_DEFINED_wglDestroyDisplayColorTableEXT + typedef VOID (APIENTRYP GLEEPFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); + GLEE_EXTERN GLEEPFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC GLeeFuncPtr_wglDestroyDisplayColorTableEXT; + #define wglDestroyDisplayColorTableEXT GLeeFuncPtr_wglDestroyDisplayColorTableEXT +#endif +#endif + +/* WGL_EXT_extensions_string */ + +#ifndef WGL_EXT_extensions_string +#define WGL_EXT_extensions_string 1 +#define __GLEE_WGL_EXT_extensions_string 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_wglGetExtensionsStringEXT +#define GLEE_H_DEFINED_wglGetExtensionsStringEXT + typedef const char * (APIENTRYP GLEEPFNWGLGETEXTENSIONSSTRINGEXTPROC) (); + GLEE_EXTERN GLEEPFNWGLGETEXTENSIONSSTRINGEXTPROC GLeeFuncPtr_wglGetExtensionsStringEXT; + #define wglGetExtensionsStringEXT GLeeFuncPtr_wglGetExtensionsStringEXT +#endif +#endif + +/* WGL_EXT_swap_control */ + +#ifndef WGL_EXT_swap_control +#define WGL_EXT_swap_control 1 +#define __GLEE_WGL_EXT_swap_control 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_wglSwapIntervalEXT +#define GLEE_H_DEFINED_wglSwapIntervalEXT + typedef BOOL (APIENTRYP GLEEPFNWGLSWAPINTERVALEXTPROC) (int interval); + GLEE_EXTERN GLEEPFNWGLSWAPINTERVALEXTPROC GLeeFuncPtr_wglSwapIntervalEXT; + #define wglSwapIntervalEXT GLeeFuncPtr_wglSwapIntervalEXT +#endif +#ifndef GLEE_H_DEFINED_wglGetSwapIntervalEXT +#define GLEE_H_DEFINED_wglGetSwapIntervalEXT + typedef int (APIENTRYP GLEEPFNWGLGETSWAPINTERVALEXTPROC) (); + GLEE_EXTERN GLEEPFNWGLGETSWAPINTERVALEXTPROC GLeeFuncPtr_wglGetSwapIntervalEXT; + #define wglGetSwapIntervalEXT GLeeFuncPtr_wglGetSwapIntervalEXT +#endif +#endif + +/* WGL_NV_vertex_array_range */ + +#ifndef WGL_NV_vertex_array_range +#define WGL_NV_vertex_array_range 1 +#define __GLEE_WGL_NV_vertex_array_range 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_wglAllocateMemoryNV +#define GLEE_H_DEFINED_wglAllocateMemoryNV + typedef void* (APIENTRYP GLEEPFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); + GLEE_EXTERN GLEEPFNWGLALLOCATEMEMORYNVPROC GLeeFuncPtr_wglAllocateMemoryNV; + #define wglAllocateMemoryNV GLeeFuncPtr_wglAllocateMemoryNV +#endif +#ifndef GLEE_H_DEFINED_wglFreeMemoryNV +#define GLEE_H_DEFINED_wglFreeMemoryNV + typedef void (APIENTRYP GLEEPFNWGLFREEMEMORYNVPROC) (void * pointer); + GLEE_EXTERN GLEEPFNWGLFREEMEMORYNVPROC GLeeFuncPtr_wglFreeMemoryNV; + #define wglFreeMemoryNV GLeeFuncPtr_wglFreeMemoryNV +#endif +#endif + +/* WGL_OML_sync_control */ + +#ifndef WGL_OML_sync_control +#define WGL_OML_sync_control 1 +#define __GLEE_WGL_OML_sync_control 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_wglGetSyncValuesOML +#define GLEE_H_DEFINED_wglGetSyncValuesOML + typedef BOOL (APIENTRYP GLEEPFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64 * ust, INT64 * msc, INT64 * sbc); + GLEE_EXTERN GLEEPFNWGLGETSYNCVALUESOMLPROC GLeeFuncPtr_wglGetSyncValuesOML; + #define wglGetSyncValuesOML GLeeFuncPtr_wglGetSyncValuesOML +#endif +#ifndef GLEE_H_DEFINED_wglGetMscRateOML +#define GLEE_H_DEFINED_wglGetMscRateOML + typedef BOOL (APIENTRYP GLEEPFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32 * numerator, INT32 * denominator); + GLEE_EXTERN GLEEPFNWGLGETMSCRATEOMLPROC GLeeFuncPtr_wglGetMscRateOML; + #define wglGetMscRateOML GLeeFuncPtr_wglGetMscRateOML +#endif +#ifndef GLEE_H_DEFINED_wglSwapBuffersMscOML +#define GLEE_H_DEFINED_wglSwapBuffersMscOML + typedef INT64 (APIENTRYP GLEEPFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); + GLEE_EXTERN GLEEPFNWGLSWAPBUFFERSMSCOMLPROC GLeeFuncPtr_wglSwapBuffersMscOML; + #define wglSwapBuffersMscOML GLeeFuncPtr_wglSwapBuffersMscOML +#endif +#ifndef GLEE_H_DEFINED_wglSwapLayerBuffersMscOML +#define GLEE_H_DEFINED_wglSwapLayerBuffersMscOML + typedef INT64 (APIENTRYP GLEEPFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); + GLEE_EXTERN GLEEPFNWGLSWAPLAYERBUFFERSMSCOMLPROC GLeeFuncPtr_wglSwapLayerBuffersMscOML; + #define wglSwapLayerBuffersMscOML GLeeFuncPtr_wglSwapLayerBuffersMscOML +#endif +#ifndef GLEE_H_DEFINED_wglWaitForMscOML +#define GLEE_H_DEFINED_wglWaitForMscOML + typedef BOOL (APIENTRYP GLEEPFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 * ust, INT64 * msc, INT64 * sbc); + GLEE_EXTERN GLEEPFNWGLWAITFORMSCOMLPROC GLeeFuncPtr_wglWaitForMscOML; + #define wglWaitForMscOML GLeeFuncPtr_wglWaitForMscOML +#endif +#ifndef GLEE_H_DEFINED_wglWaitForSbcOML +#define GLEE_H_DEFINED_wglWaitForSbcOML + typedef BOOL (APIENTRYP GLEEPFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64 * ust, INT64 * msc, INT64 * sbc); + GLEE_EXTERN GLEEPFNWGLWAITFORSBCOMLPROC GLeeFuncPtr_wglWaitForSbcOML; + #define wglWaitForSbcOML GLeeFuncPtr_wglWaitForSbcOML +#endif +#endif + +/* WGL_I3D_swap_frame_usage */ + +#ifndef WGL_I3D_swap_frame_usage +#define WGL_I3D_swap_frame_usage 1 +#define __GLEE_WGL_I3D_swap_frame_usage 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_wglGetFrameUsageI3D +#define GLEE_H_DEFINED_wglGetFrameUsageI3D + typedef BOOL (APIENTRYP GLEEPFNWGLGETFRAMEUSAGEI3DPROC) (float * pUsage); + GLEE_EXTERN GLEEPFNWGLGETFRAMEUSAGEI3DPROC GLeeFuncPtr_wglGetFrameUsageI3D; + #define wglGetFrameUsageI3D GLeeFuncPtr_wglGetFrameUsageI3D +#endif +#ifndef GLEE_H_DEFINED_wglBeginFrameTrackingI3D +#define GLEE_H_DEFINED_wglBeginFrameTrackingI3D + typedef BOOL (APIENTRYP GLEEPFNWGLBEGINFRAMETRACKINGI3DPROC) (); + GLEE_EXTERN GLEEPFNWGLBEGINFRAMETRACKINGI3DPROC GLeeFuncPtr_wglBeginFrameTrackingI3D; + #define wglBeginFrameTrackingI3D GLeeFuncPtr_wglBeginFrameTrackingI3D +#endif +#ifndef GLEE_H_DEFINED_wglEndFrameTrackingI3D +#define GLEE_H_DEFINED_wglEndFrameTrackingI3D + typedef BOOL (APIENTRYP GLEEPFNWGLENDFRAMETRACKINGI3DPROC) (); + GLEE_EXTERN GLEEPFNWGLENDFRAMETRACKINGI3DPROC GLeeFuncPtr_wglEndFrameTrackingI3D; + #define wglEndFrameTrackingI3D GLeeFuncPtr_wglEndFrameTrackingI3D +#endif +#ifndef GLEE_H_DEFINED_wglQueryFrameTrackingI3D +#define GLEE_H_DEFINED_wglQueryFrameTrackingI3D + typedef BOOL (APIENTRYP GLEEPFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD * pFrameCount, DWORD * pMissedFrames, float * pLastMissedUsage); + GLEE_EXTERN GLEEPFNWGLQUERYFRAMETRACKINGI3DPROC GLeeFuncPtr_wglQueryFrameTrackingI3D; + #define wglQueryFrameTrackingI3D GLeeFuncPtr_wglQueryFrameTrackingI3D +#endif +#endif + +/* WGL_NV_video_output */ + +#ifndef WGL_NV_video_output +#define WGL_NV_video_output 1 +#define __GLEE_WGL_NV_video_output 1 +/* Constants */ +#define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0 +#define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1 +#define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2 +#define WGL_VIDEO_OUT_COLOR_NV 0x20C3 +#define WGL_VIDEO_OUT_ALPHA_NV 0x20C4 +#define WGL_VIDEO_OUT_DEPTH_NV 0x20C5 +#define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 +#define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 +#define WGL_VIDEO_OUT_FRAME 0x20C8 +#define WGL_VIDEO_OUT_FIELD_1 0x20C9 +#define WGL_VIDEO_OUT_FIELD_2 0x20CA +#define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB +#define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC +#ifndef GLEE_H_DEFINED_wglGetVideoDeviceNV +#define GLEE_H_DEFINED_wglGetVideoDeviceNV + typedef BOOL (APIENTRYP GLEEPFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV * hVideoDevice); + GLEE_EXTERN GLEEPFNWGLGETVIDEODEVICENVPROC GLeeFuncPtr_wglGetVideoDeviceNV; + #define wglGetVideoDeviceNV GLeeFuncPtr_wglGetVideoDeviceNV +#endif +#ifndef GLEE_H_DEFINED_wglReleaseVideoDeviceNV +#define GLEE_H_DEFINED_wglReleaseVideoDeviceNV + typedef BOOL (APIENTRYP GLEEPFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice); + GLEE_EXTERN GLEEPFNWGLRELEASEVIDEODEVICENVPROC GLeeFuncPtr_wglReleaseVideoDeviceNV; + #define wglReleaseVideoDeviceNV GLeeFuncPtr_wglReleaseVideoDeviceNV +#endif +#ifndef GLEE_H_DEFINED_wglBindVideoImageNV +#define GLEE_H_DEFINED_wglBindVideoImageNV + typedef BOOL (APIENTRYP GLEEPFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer); + GLEE_EXTERN GLEEPFNWGLBINDVIDEOIMAGENVPROC GLeeFuncPtr_wglBindVideoImageNV; + #define wglBindVideoImageNV GLeeFuncPtr_wglBindVideoImageNV +#endif +#ifndef GLEE_H_DEFINED_wglReleaseVideoImageNV +#define GLEE_H_DEFINED_wglReleaseVideoImageNV + typedef BOOL (APIENTRYP GLEEPFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer); + GLEE_EXTERN GLEEPFNWGLRELEASEVIDEOIMAGENVPROC GLeeFuncPtr_wglReleaseVideoImageNV; + #define wglReleaseVideoImageNV GLeeFuncPtr_wglReleaseVideoImageNV +#endif +#ifndef GLEE_H_DEFINED_wglSendPbufferToVideoNV +#define GLEE_H_DEFINED_wglSendPbufferToVideoNV + typedef BOOL (APIENTRYP GLEEPFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long * pulCounterPbuffer, BOOL bBlock); + GLEE_EXTERN GLEEPFNWGLSENDPBUFFERTOVIDEONVPROC GLeeFuncPtr_wglSendPbufferToVideoNV; + #define wglSendPbufferToVideoNV GLeeFuncPtr_wglSendPbufferToVideoNV +#endif +#ifndef GLEE_H_DEFINED_wglGetVideoInfoNV +#define GLEE_H_DEFINED_wglGetVideoInfoNV + typedef BOOL (APIENTRYP GLEEPFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long * pulCounterOutputPbuffer, unsigned long * pulCounterOutputVideo); + GLEE_EXTERN GLEEPFNWGLGETVIDEOINFONVPROC GLeeFuncPtr_wglGetVideoInfoNV; + #define wglGetVideoInfoNV GLeeFuncPtr_wglGetVideoInfoNV +#endif +#endif +#elif defined(__APPLE__) || defined(__APPLE_CC__) +#else /* GLX */ + +/* Extension querying variables */ + +GLEE_EXTERN GLboolean _GLEE_GLX_VERSION_1_3; +GLEE_EXTERN GLboolean _GLEE_GLX_VERSION_1_4; +GLEE_EXTERN GLboolean _GLEE_GLX_ARB_multisample; +GLEE_EXTERN GLboolean _GLEE_GLX_ARB_fbconfig_float; +GLEE_EXTERN GLboolean _GLEE_GLX_ARB_create_context; +GLEE_EXTERN GLboolean _GLEE_GLX_SGIS_multisample; +GLEE_EXTERN GLboolean _GLEE_GLX_EXT_visual_info; +GLEE_EXTERN GLboolean _GLEE_GLX_SGI_swap_control; +GLEE_EXTERN GLboolean _GLEE_GLX_SGI_video_sync; +GLEE_EXTERN GLboolean _GLEE_GLX_SGI_make_current_read; +GLEE_EXTERN GLboolean _GLEE_GLX_EXT_visual_rating; +GLEE_EXTERN GLboolean _GLEE_GLX_EXT_import_context; +GLEE_EXTERN GLboolean _GLEE_GLX_SGIX_fbconfig; +GLEE_EXTERN GLboolean _GLEE_GLX_SGIX_pbuffer; +GLEE_EXTERN GLboolean _GLEE_GLX_SGI_cushion; +GLEE_EXTERN GLboolean _GLEE_GLX_SGIX_video_resize; +GLEE_EXTERN GLboolean _GLEE_GLX_SGIX_swap_group; +GLEE_EXTERN GLboolean _GLEE_GLX_SGIX_swap_barrier; +GLEE_EXTERN GLboolean _GLEE_GLX_SGIS_blended_overlay; +GLEE_EXTERN GLboolean _GLEE_GLX_SGIS_shared_multisample; +GLEE_EXTERN GLboolean _GLEE_GLX_SUN_get_transparent_index; +GLEE_EXTERN GLboolean _GLEE_GLX_3DFX_multisample; +GLEE_EXTERN GLboolean _GLEE_GLX_MESA_copy_sub_buffer; +GLEE_EXTERN GLboolean _GLEE_GLX_MESA_pixmap_colormap; +GLEE_EXTERN GLboolean _GLEE_GLX_MESA_release_buffers; +GLEE_EXTERN GLboolean _GLEE_GLX_MESA_set_3dfx_mode; +GLEE_EXTERN GLboolean _GLEE_GLX_SGIX_visual_select_group; +GLEE_EXTERN GLboolean _GLEE_GLX_OML_swap_method; +GLEE_EXTERN GLboolean _GLEE_GLX_OML_sync_control; +GLEE_EXTERN GLboolean _GLEE_GLX_NV_float_buffer; +GLEE_EXTERN GLboolean _GLEE_GLX_SGIX_hyperpipe; +GLEE_EXTERN GLboolean _GLEE_GLX_MESA_agp_offset; +GLEE_EXTERN GLboolean _GLEE_GLX_EXT_fbconfig_packed_float; +GLEE_EXTERN GLboolean _GLEE_GLX_EXT_framebuffer_sRGB; +GLEE_EXTERN GLboolean _GLEE_GLX_EXT_texture_from_pixmap; +GLEE_EXTERN GLboolean _GLEE_GLX_NV_present_video; +GLEE_EXTERN GLboolean _GLEE_GLX_NV_video_out; +GLEE_EXTERN GLboolean _GLEE_GLX_NV_swap_group; +GLEE_EXTERN GLboolean _GLEE_GLX_EXT_scene_marker; +GLEE_EXTERN GLboolean _GLEE_GLX_NV_video_output; + +/* Aliases for extension querying variables */ + +#define GLEE_GLX_VERSION_1_3 GLeeEnabled(&_GLEE_GLX_VERSION_1_3) +#define GLEE_GLX_VERSION_1_4 GLeeEnabled(&_GLEE_GLX_VERSION_1_4) +#define GLEE_GLX_ARB_multisample GLeeEnabled(&_GLEE_GLX_ARB_multisample) +#define GLEE_GLX_ARB_fbconfig_float GLeeEnabled(&_GLEE_GLX_ARB_fbconfig_float) +#define GLEE_GLX_ARB_create_context GLeeEnabled(&_GLEE_GLX_ARB_create_context) +#define GLEE_GLX_SGIS_multisample GLeeEnabled(&_GLEE_GLX_SGIS_multisample) +#define GLEE_GLX_EXT_visual_info GLeeEnabled(&_GLEE_GLX_EXT_visual_info) +#define GLEE_GLX_SGI_swap_control GLeeEnabled(&_GLEE_GLX_SGI_swap_control) +#define GLEE_GLX_SGI_video_sync GLeeEnabled(&_GLEE_GLX_SGI_video_sync) +#define GLEE_GLX_SGI_make_current_read GLeeEnabled(&_GLEE_GLX_SGI_make_current_read) +#define GLEE_GLX_EXT_visual_rating GLeeEnabled(&_GLEE_GLX_EXT_visual_rating) +#define GLEE_GLX_EXT_import_context GLeeEnabled(&_GLEE_GLX_EXT_import_context) +#define GLEE_GLX_SGIX_fbconfig GLeeEnabled(&_GLEE_GLX_SGIX_fbconfig) +#define GLEE_GLX_SGIX_pbuffer GLeeEnabled(&_GLEE_GLX_SGIX_pbuffer) +#define GLEE_GLX_SGI_cushion GLeeEnabled(&_GLEE_GLX_SGI_cushion) +#define GLEE_GLX_SGIX_video_resize GLeeEnabled(&_GLEE_GLX_SGIX_video_resize) +#define GLEE_GLX_SGIX_swap_group GLeeEnabled(&_GLEE_GLX_SGIX_swap_group) +#define GLEE_GLX_SGIX_swap_barrier GLeeEnabled(&_GLEE_GLX_SGIX_swap_barrier) +#define GLEE_GLX_SGIS_blended_overlay GLeeEnabled(&_GLEE_GLX_SGIS_blended_overlay) +#define GLEE_GLX_SGIS_shared_multisample GLeeEnabled(&_GLEE_GLX_SGIS_shared_multisample) +#define GLEE_GLX_SUN_get_transparent_index GLeeEnabled(&_GLEE_GLX_SUN_get_transparent_index) +#define GLEE_GLX_3DFX_multisample GLeeEnabled(&_GLEE_GLX_3DFX_multisample) +#define GLEE_GLX_MESA_copy_sub_buffer GLeeEnabled(&_GLEE_GLX_MESA_copy_sub_buffer) +#define GLEE_GLX_MESA_pixmap_colormap GLeeEnabled(&_GLEE_GLX_MESA_pixmap_colormap) +#define GLEE_GLX_MESA_release_buffers GLeeEnabled(&_GLEE_GLX_MESA_release_buffers) +#define GLEE_GLX_MESA_set_3dfx_mode GLeeEnabled(&_GLEE_GLX_MESA_set_3dfx_mode) +#define GLEE_GLX_SGIX_visual_select_group GLeeEnabled(&_GLEE_GLX_SGIX_visual_select_group) +#define GLEE_GLX_OML_swap_method GLeeEnabled(&_GLEE_GLX_OML_swap_method) +#define GLEE_GLX_OML_sync_control GLeeEnabled(&_GLEE_GLX_OML_sync_control) +#define GLEE_GLX_NV_float_buffer GLeeEnabled(&_GLEE_GLX_NV_float_buffer) +#define GLEE_GLX_SGIX_hyperpipe GLeeEnabled(&_GLEE_GLX_SGIX_hyperpipe) +#define GLEE_GLX_MESA_agp_offset GLeeEnabled(&_GLEE_GLX_MESA_agp_offset) +#define GLEE_GLX_EXT_fbconfig_packed_float GLeeEnabled(&_GLEE_GLX_EXT_fbconfig_packed_float) +#define GLEE_GLX_EXT_framebuffer_sRGB GLeeEnabled(&_GLEE_GLX_EXT_framebuffer_sRGB) +#define GLEE_GLX_EXT_texture_from_pixmap GLeeEnabled(&_GLEE_GLX_EXT_texture_from_pixmap) +#define GLEE_GLX_NV_present_video GLeeEnabled(&_GLEE_GLX_NV_present_video) +#define GLEE_GLX_NV_video_out GLeeEnabled(&_GLEE_GLX_NV_video_out) +#define GLEE_GLX_NV_swap_group GLeeEnabled(&_GLEE_GLX_NV_swap_group) +#define GLEE_GLX_EXT_scene_marker GLeeEnabled(&_GLEE_GLX_EXT_scene_marker) +#define GLEE_GLX_NV_video_output GLeeEnabled(&_GLEE_GLX_NV_video_output) + +/* GLX_VERSION_1_3 */ + +#ifndef GLX_VERSION_1_3 +#define GLX_VERSION_1_3 1 +#define __GLEE_GLX_VERSION_1_3 1 +/* Constants */ +#define GLX_WINDOW_BIT 0x00000001 +#define GLX_PIXMAP_BIT 0x00000002 +#define GLX_PBUFFER_BIT 0x00000004 +#define GLX_RGBA_BIT 0x00000001 +#define GLX_COLOR_INDEX_BIT 0x00000002 +#define GLX_PBUFFER_CLOBBER_MASK 0x08000000 +#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 +#define GLX_AUX_BUFFERS_BIT 0x00000010 +#define GLX_DEPTH_BUFFER_BIT 0x00000020 +#define GLX_STENCIL_BUFFER_BIT 0x00000040 +#define GLX_ACCUM_BUFFER_BIT 0x00000080 +#define GLX_CONFIG_CAVEAT 0x20 +#define GLX_X_VISUAL_TYPE 0x22 +#define GLX_TRANSPARENT_TYPE 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE 0x24 +#define GLX_TRANSPARENT_RED_VALUE 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE 0x28 +#define GLX_DONT_CARE 0xFFFFFFFF +#define GLX_NONE 0x8000 +#define GLX_SLOW_CONFIG 0x8001 +#define GLX_TRUE_COLOR 0x8002 +#define GLX_DIRECT_COLOR 0x8003 +#define GLX_PSEUDO_COLOR 0x8004 +#define GLX_STATIC_COLOR 0x8005 +#define GLX_GRAY_SCALE 0x8006 +#define GLX_STATIC_GRAY 0x8007 +#define GLX_TRANSPARENT_RGB 0x8008 +#define GLX_TRANSPARENT_INDEX 0x8009 +#define GLX_VISUAL_ID 0x800B +#define GLX_SCREEN 0x800C +#define GLX_NON_CONFORMANT_CONFIG 0x800D +#define GLX_DRAWABLE_TYPE 0x8010 +#define GLX_RENDER_TYPE 0x8011 +#define GLX_X_RENDERABLE 0x8012 +#define GLX_FBCONFIG_ID 0x8013 +#define GLX_RGBA_TYPE 0x8014 +#define GLX_COLOR_INDEX_TYPE 0x8015 +#define GLX_MAX_PBUFFER_WIDTH 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT 0x8017 +#define GLX_MAX_PBUFFER_PIXELS 0x8018 +#define GLX_PRESERVED_CONTENTS 0x801B +#define GLX_LARGEST_PBUFFER 0x801C +#define GLX_WIDTH 0x801D +#define GLX_HEIGHT 0x801E +#define GLX_EVENT_MASK 0x801F +#define GLX_DAMAGED 0x8020 +#define GLX_SAVED 0x8021 +#define GLX_WINDOW 0x8022 +#define GLX_PBUFFER 0x8023 +#define GLX_PBUFFER_HEIGHT 0x8040 +#define GLX_PBUFFER_WIDTH 0x8041 +#ifndef GLEE_H_DEFINED_glXGetFBConfigs +#define GLEE_H_DEFINED_glXGetFBConfigs + typedef GLXFBConfig * (APIENTRYP GLEEPFNGLXGETFBCONFIGSPROC) (Display * dpy, int screen, int * nelements); + GLEE_EXTERN GLEEPFNGLXGETFBCONFIGSPROC GLeeFuncPtr_glXGetFBConfigs; + #define glXGetFBConfigs GLeeFuncPtr_glXGetFBConfigs +#endif +#ifndef GLEE_H_DEFINED_glXChooseFBConfig +#define GLEE_H_DEFINED_glXChooseFBConfig + typedef GLXFBConfig * (APIENTRYP GLEEPFNGLXCHOOSEFBCONFIGPROC) (Display * dpy, int screen, const int * attrib_list, int * nelements); + GLEE_EXTERN GLEEPFNGLXCHOOSEFBCONFIGPROC GLeeFuncPtr_glXChooseFBConfig; + #define glXChooseFBConfig GLeeFuncPtr_glXChooseFBConfig +#endif +#ifndef GLEE_H_DEFINED_glXGetFBConfigAttrib +#define GLEE_H_DEFINED_glXGetFBConfigAttrib + typedef int (APIENTRYP GLEEPFNGLXGETFBCONFIGATTRIBPROC) (Display * dpy, GLXFBConfig config, int attribute, int * value); + GLEE_EXTERN GLEEPFNGLXGETFBCONFIGATTRIBPROC GLeeFuncPtr_glXGetFBConfigAttrib; + #define glXGetFBConfigAttrib GLeeFuncPtr_glXGetFBConfigAttrib +#endif +#ifndef GLEE_H_DEFINED_glXGetVisualFromFBConfig +#define GLEE_H_DEFINED_glXGetVisualFromFBConfig + typedef XVisualInfo * (APIENTRYP GLEEPFNGLXGETVISUALFROMFBCONFIGPROC) (Display * dpy, GLXFBConfig config); + GLEE_EXTERN GLEEPFNGLXGETVISUALFROMFBCONFIGPROC GLeeFuncPtr_glXGetVisualFromFBConfig; + #define glXGetVisualFromFBConfig GLeeFuncPtr_glXGetVisualFromFBConfig +#endif +#ifndef GLEE_H_DEFINED_glXCreateWindow +#define GLEE_H_DEFINED_glXCreateWindow + typedef GLXWindow (APIENTRYP GLEEPFNGLXCREATEWINDOWPROC) (Display * dpy, GLXFBConfig config, Window win, const int * attrib_list); + GLEE_EXTERN GLEEPFNGLXCREATEWINDOWPROC GLeeFuncPtr_glXCreateWindow; + #define glXCreateWindow GLeeFuncPtr_glXCreateWindow +#endif +#ifndef GLEE_H_DEFINED_glXDestroyWindow +#define GLEE_H_DEFINED_glXDestroyWindow + typedef void (APIENTRYP GLEEPFNGLXDESTROYWINDOWPROC) (Display * dpy, GLXWindow win); + GLEE_EXTERN GLEEPFNGLXDESTROYWINDOWPROC GLeeFuncPtr_glXDestroyWindow; + #define glXDestroyWindow GLeeFuncPtr_glXDestroyWindow +#endif +#ifndef GLEE_H_DEFINED_glXCreatePixmap +#define GLEE_H_DEFINED_glXCreatePixmap + typedef GLXPixmap (APIENTRYP GLEEPFNGLXCREATEPIXMAPPROC) (Display * dpy, GLXFBConfig config, Pixmap pixmap, const int * attrib_list); + GLEE_EXTERN GLEEPFNGLXCREATEPIXMAPPROC GLeeFuncPtr_glXCreatePixmap; + #define glXCreatePixmap GLeeFuncPtr_glXCreatePixmap +#endif +#ifndef GLEE_H_DEFINED_glXDestroyPixmap +#define GLEE_H_DEFINED_glXDestroyPixmap + typedef void (APIENTRYP GLEEPFNGLXDESTROYPIXMAPPROC) (Display * dpy, GLXPixmap pixmap); + GLEE_EXTERN GLEEPFNGLXDESTROYPIXMAPPROC GLeeFuncPtr_glXDestroyPixmap; + #define glXDestroyPixmap GLeeFuncPtr_glXDestroyPixmap +#endif +#ifndef GLEE_H_DEFINED_glXCreatePbuffer +#define GLEE_H_DEFINED_glXCreatePbuffer + typedef GLXPbuffer (APIENTRYP GLEEPFNGLXCREATEPBUFFERPROC) (Display * dpy, GLXFBConfig config, const int * attrib_list); + GLEE_EXTERN GLEEPFNGLXCREATEPBUFFERPROC GLeeFuncPtr_glXCreatePbuffer; + #define glXCreatePbuffer GLeeFuncPtr_glXCreatePbuffer +#endif +#ifndef GLEE_H_DEFINED_glXDestroyPbuffer +#define GLEE_H_DEFINED_glXDestroyPbuffer + typedef void (APIENTRYP GLEEPFNGLXDESTROYPBUFFERPROC) (Display * dpy, GLXPbuffer pbuf); + GLEE_EXTERN GLEEPFNGLXDESTROYPBUFFERPROC GLeeFuncPtr_glXDestroyPbuffer; + #define glXDestroyPbuffer GLeeFuncPtr_glXDestroyPbuffer +#endif +#ifndef GLEE_H_DEFINED_glXQueryDrawable +#define GLEE_H_DEFINED_glXQueryDrawable + typedef void (APIENTRYP GLEEPFNGLXQUERYDRAWABLEPROC) (Display * dpy, GLXDrawable draw, int attribute, unsigned int * value); + GLEE_EXTERN GLEEPFNGLXQUERYDRAWABLEPROC GLeeFuncPtr_glXQueryDrawable; + #define glXQueryDrawable GLeeFuncPtr_glXQueryDrawable +#endif +#ifndef GLEE_H_DEFINED_glXCreateNewContext +#define GLEE_H_DEFINED_glXCreateNewContext + typedef GLXContext (APIENTRYP GLEEPFNGLXCREATENEWCONTEXTPROC) (Display * dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); + GLEE_EXTERN GLEEPFNGLXCREATENEWCONTEXTPROC GLeeFuncPtr_glXCreateNewContext; + #define glXCreateNewContext GLeeFuncPtr_glXCreateNewContext +#endif +#ifndef GLEE_H_DEFINED_glXMakeContextCurrent +#define GLEE_H_DEFINED_glXMakeContextCurrent + typedef Bool (APIENTRYP GLEEPFNGLXMAKECONTEXTCURRENTPROC) (Display * dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); + GLEE_EXTERN GLEEPFNGLXMAKECONTEXTCURRENTPROC GLeeFuncPtr_glXMakeContextCurrent; + #define glXMakeContextCurrent GLeeFuncPtr_glXMakeContextCurrent +#endif +#ifndef GLEE_H_DEFINED_glXGetCurrentReadDrawable +#define GLEE_H_DEFINED_glXGetCurrentReadDrawable + typedef GLXDrawable (APIENTRYP GLEEPFNGLXGETCURRENTREADDRAWABLEPROC) (); + GLEE_EXTERN GLEEPFNGLXGETCURRENTREADDRAWABLEPROC GLeeFuncPtr_glXGetCurrentReadDrawable; + #define glXGetCurrentReadDrawable GLeeFuncPtr_glXGetCurrentReadDrawable +#endif +#ifndef GLEE_H_DEFINED_glXGetCurrentDisplay +#define GLEE_H_DEFINED_glXGetCurrentDisplay + typedef Display * (APIENTRYP GLEEPFNGLXGETCURRENTDISPLAYPROC) (); + GLEE_EXTERN GLEEPFNGLXGETCURRENTDISPLAYPROC GLeeFuncPtr_glXGetCurrentDisplay; + #define glXGetCurrentDisplay GLeeFuncPtr_glXGetCurrentDisplay +#endif +#ifndef GLEE_H_DEFINED_glXQueryContext +#define GLEE_H_DEFINED_glXQueryContext + typedef int (APIENTRYP GLEEPFNGLXQUERYCONTEXTPROC) (Display * dpy, GLXContext ctx, int attribute, int * value); + GLEE_EXTERN GLEEPFNGLXQUERYCONTEXTPROC GLeeFuncPtr_glXQueryContext; + #define glXQueryContext GLeeFuncPtr_glXQueryContext +#endif +#ifndef GLEE_H_DEFINED_glXSelectEvent +#define GLEE_H_DEFINED_glXSelectEvent + typedef void (APIENTRYP GLEEPFNGLXSELECTEVENTPROC) (Display * dpy, GLXDrawable draw, unsigned long event_mask); + GLEE_EXTERN GLEEPFNGLXSELECTEVENTPROC GLeeFuncPtr_glXSelectEvent; + #define glXSelectEvent GLeeFuncPtr_glXSelectEvent +#endif +#ifndef GLEE_H_DEFINED_glXGetSelectedEvent +#define GLEE_H_DEFINED_glXGetSelectedEvent + typedef void (APIENTRYP GLEEPFNGLXGETSELECTEDEVENTPROC) (Display * dpy, GLXDrawable draw, unsigned long * event_mask); + GLEE_EXTERN GLEEPFNGLXGETSELECTEDEVENTPROC GLeeFuncPtr_glXGetSelectedEvent; + #define glXGetSelectedEvent GLeeFuncPtr_glXGetSelectedEvent +#endif +#endif + +/* GLX_VERSION_1_4 */ + +#ifndef GLX_VERSION_1_4 +#define GLX_VERSION_1_4 1 +#define __GLEE_GLX_VERSION_1_4 1 +/* Constants */ +#define GLX_SAMPLE_BUFFERS 100000 +#define GLX_SAMPLES 100001 +#ifndef GLEE_H_DEFINED_glXGetProcAddress +#define GLEE_H_DEFINED_glXGetProcAddress + typedef __GLXextFuncPtr (APIENTRYP GLEEPFNGLXGETPROCADDRESSPROC) (const GLubyte * procName); + GLEE_EXTERN GLEEPFNGLXGETPROCADDRESSPROC GLeeFuncPtr_glXGetProcAddress; + #define glXGetProcAddress GLeeFuncPtr_glXGetProcAddress +#endif +#endif + +/* GLX_ARB_multisample */ + +#ifndef GLX_ARB_multisample +#define GLX_ARB_multisample 1 +#define __GLEE_GLX_ARB_multisample 1 +/* Constants */ +#define GLX_SAMPLE_BUFFERS_ARB 100000 +#define GLX_SAMPLES_ARB 100001 +#endif + +/* GLX_ARB_fbconfig_float */ + +#ifndef GLX_ARB_fbconfig_float +#define GLX_ARB_fbconfig_float 1 +#define __GLEE_GLX_ARB_fbconfig_float 1 +/* Constants */ +#define GLX_RGBA_FLOAT_TYPE_ARB 0x20B9 +#define GLX_RGBA_FLOAT_BIT_ARB 0x00000004 +#endif + +/* GLX_ARB_create_context */ + +#ifndef GLX_ARB_create_context +#define GLX_ARB_create_context 1 +#define __GLEE_GLX_ARB_create_context 1 +/* Constants */ +#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001 +#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define GLX_CONTEXT_FLAGS_ARB 0x2094 +#ifndef GLEE_H_DEFINED_glXCreateContextAttribsARB +#define GLEE_H_DEFINED_glXCreateContextAttribsARB + typedef GLXContext (APIENTRYP GLEEPFNGLXCREATECONTEXTATTRIBSARBPROC) (Display * dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int * attrib_list); + GLEE_EXTERN GLEEPFNGLXCREATECONTEXTATTRIBSARBPROC GLeeFuncPtr_glXCreateContextAttribsARB; + #define glXCreateContextAttribsARB GLeeFuncPtr_glXCreateContextAttribsARB +#endif +#endif + +/* GLX_SGIS_multisample */ + +#ifndef GLX_SGIS_multisample +#define GLX_SGIS_multisample 1 +#define __GLEE_GLX_SGIS_multisample 1 +/* Constants */ +#define GLX_SAMPLE_BUFFERS_SGIS 100000 +#define GLX_SAMPLES_SGIS 100001 +#endif + +/* GLX_EXT_visual_info */ + +#ifndef GLX_EXT_visual_info +#define GLX_EXT_visual_info 1 +#define __GLEE_GLX_EXT_visual_info 1 +/* Constants */ +#define GLX_X_VISUAL_TYPE_EXT 0x22 +#define GLX_TRANSPARENT_TYPE_EXT 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24 +#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28 +#define GLX_NONE_EXT 0x8000 +#define GLX_TRUE_COLOR_EXT 0x8002 +#define GLX_DIRECT_COLOR_EXT 0x8003 +#define GLX_PSEUDO_COLOR_EXT 0x8004 +#define GLX_STATIC_COLOR_EXT 0x8005 +#define GLX_GRAY_SCALE_EXT 0x8006 +#define GLX_STATIC_GRAY_EXT 0x8007 +#define GLX_TRANSPARENT_RGB_EXT 0x8008 +#define GLX_TRANSPARENT_INDEX_EXT 0x8009 +#endif + +/* GLX_SGI_swap_control */ + +#ifndef GLX_SGI_swap_control +#define GLX_SGI_swap_control 1 +#define __GLEE_GLX_SGI_swap_control 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glXSwapIntervalSGI +#define GLEE_H_DEFINED_glXSwapIntervalSGI + typedef int (APIENTRYP GLEEPFNGLXSWAPINTERVALSGIPROC) (int interval); + GLEE_EXTERN GLEEPFNGLXSWAPINTERVALSGIPROC GLeeFuncPtr_glXSwapIntervalSGI; + #define glXSwapIntervalSGI GLeeFuncPtr_glXSwapIntervalSGI +#endif +#endif + +/* GLX_SGI_video_sync */ + +#ifndef GLX_SGI_video_sync +#define GLX_SGI_video_sync 1 +#define __GLEE_GLX_SGI_video_sync 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glXGetVideoSyncSGI +#define GLEE_H_DEFINED_glXGetVideoSyncSGI + typedef int (APIENTRYP GLEEPFNGLXGETVIDEOSYNCSGIPROC) (unsigned int * count); + GLEE_EXTERN GLEEPFNGLXGETVIDEOSYNCSGIPROC GLeeFuncPtr_glXGetVideoSyncSGI; + #define glXGetVideoSyncSGI GLeeFuncPtr_glXGetVideoSyncSGI +#endif +#ifndef GLEE_H_DEFINED_glXWaitVideoSyncSGI +#define GLEE_H_DEFINED_glXWaitVideoSyncSGI + typedef int (APIENTRYP GLEEPFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int * count); + GLEE_EXTERN GLEEPFNGLXWAITVIDEOSYNCSGIPROC GLeeFuncPtr_glXWaitVideoSyncSGI; + #define glXWaitVideoSyncSGI GLeeFuncPtr_glXWaitVideoSyncSGI +#endif +#endif + +/* GLX_SGI_make_current_read */ + +#ifndef GLX_SGI_make_current_read +#define GLX_SGI_make_current_read 1 +#define __GLEE_GLX_SGI_make_current_read 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glXMakeCurrentReadSGI +#define GLEE_H_DEFINED_glXMakeCurrentReadSGI + typedef Bool (APIENTRYP GLEEPFNGLXMAKECURRENTREADSGIPROC) (Display * dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); + GLEE_EXTERN GLEEPFNGLXMAKECURRENTREADSGIPROC GLeeFuncPtr_glXMakeCurrentReadSGI; + #define glXMakeCurrentReadSGI GLeeFuncPtr_glXMakeCurrentReadSGI +#endif +#ifndef GLEE_H_DEFINED_glXGetCurrentReadDrawableSGI +#define GLEE_H_DEFINED_glXGetCurrentReadDrawableSGI + typedef GLXDrawable (APIENTRYP GLEEPFNGLXGETCURRENTREADDRAWABLESGIPROC) (); + GLEE_EXTERN GLEEPFNGLXGETCURRENTREADDRAWABLESGIPROC GLeeFuncPtr_glXGetCurrentReadDrawableSGI; + #define glXGetCurrentReadDrawableSGI GLeeFuncPtr_glXGetCurrentReadDrawableSGI +#endif +#endif + +/* GLX_EXT_visual_rating */ + +#ifndef GLX_EXT_visual_rating +#define GLX_EXT_visual_rating 1 +#define __GLEE_GLX_EXT_visual_rating 1 +/* Constants */ +#define GLX_VISUAL_CAVEAT_EXT 0x20 +#define GLX_SLOW_VISUAL_EXT 0x8001 +#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D +#endif + +/* GLX_EXT_import_context */ + +#ifndef GLX_EXT_import_context +#define GLX_EXT_import_context 1 +#define __GLEE_GLX_EXT_import_context 1 +/* Constants */ +#define GLX_SHARE_CONTEXT_EXT 0x800A +#define GLX_VISUAL_ID_EXT 0x800B +#define GLX_SCREEN_EXT 0x800C +#ifndef GLEE_H_DEFINED_glXGetCurrentDisplayEXT +#define GLEE_H_DEFINED_glXGetCurrentDisplayEXT + typedef Display * (APIENTRYP GLEEPFNGLXGETCURRENTDISPLAYEXTPROC) (); + GLEE_EXTERN GLEEPFNGLXGETCURRENTDISPLAYEXTPROC GLeeFuncPtr_glXGetCurrentDisplayEXT; + #define glXGetCurrentDisplayEXT GLeeFuncPtr_glXGetCurrentDisplayEXT +#endif +#ifndef GLEE_H_DEFINED_glXQueryContextInfoEXT +#define GLEE_H_DEFINED_glXQueryContextInfoEXT + typedef int (APIENTRYP GLEEPFNGLXQUERYCONTEXTINFOEXTPROC) (Display * dpy, GLXContext context, int attribute, int * value); + GLEE_EXTERN GLEEPFNGLXQUERYCONTEXTINFOEXTPROC GLeeFuncPtr_glXQueryContextInfoEXT; + #define glXQueryContextInfoEXT GLeeFuncPtr_glXQueryContextInfoEXT +#endif +#ifndef GLEE_H_DEFINED_glXGetContextIDEXT +#define GLEE_H_DEFINED_glXGetContextIDEXT + typedef GLXContextID (APIENTRYP GLEEPFNGLXGETCONTEXTIDEXTPROC) (const GLXContext context); + GLEE_EXTERN GLEEPFNGLXGETCONTEXTIDEXTPROC GLeeFuncPtr_glXGetContextIDEXT; + #define glXGetContextIDEXT GLeeFuncPtr_glXGetContextIDEXT +#endif +#ifndef GLEE_H_DEFINED_glXImportContextEXT +#define GLEE_H_DEFINED_glXImportContextEXT + typedef GLXContext (APIENTRYP GLEEPFNGLXIMPORTCONTEXTEXTPROC) (Display * dpy, GLXContextID contextID); + GLEE_EXTERN GLEEPFNGLXIMPORTCONTEXTEXTPROC GLeeFuncPtr_glXImportContextEXT; + #define glXImportContextEXT GLeeFuncPtr_glXImportContextEXT +#endif +#ifndef GLEE_H_DEFINED_glXFreeContextEXT +#define GLEE_H_DEFINED_glXFreeContextEXT + typedef void (APIENTRYP GLEEPFNGLXFREECONTEXTEXTPROC) (Display * dpy, GLXContext context); + GLEE_EXTERN GLEEPFNGLXFREECONTEXTEXTPROC GLeeFuncPtr_glXFreeContextEXT; + #define glXFreeContextEXT GLeeFuncPtr_glXFreeContextEXT +#endif +#endif + +/* GLX_SGIX_fbconfig */ + +#ifndef GLX_SGIX_fbconfig +#define GLX_SGIX_fbconfig 1 +#define __GLEE_GLX_SGIX_fbconfig 1 +/* Constants */ +#define GLX_WINDOW_BIT_SGIX 0x00000001 +#define GLX_PIXMAP_BIT_SGIX 0x00000002 +#define GLX_RGBA_BIT_SGIX 0x00000001 +#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002 +#define GLX_DRAWABLE_TYPE_SGIX 0x8010 +#define GLX_RENDER_TYPE_SGIX 0x8011 +#define GLX_X_RENDERABLE_SGIX 0x8012 +#define GLX_FBCONFIG_ID_SGIX 0x8013 +#define GLX_RGBA_TYPE_SGIX 0x8014 +#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015 +#ifndef GLEE_H_DEFINED_glXGetFBConfigAttribSGIX +#define GLEE_H_DEFINED_glXGetFBConfigAttribSGIX + typedef int (APIENTRYP GLEEPFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display * dpy, GLXFBConfigSGIX config, int attribute, int * value); + GLEE_EXTERN GLEEPFNGLXGETFBCONFIGATTRIBSGIXPROC GLeeFuncPtr_glXGetFBConfigAttribSGIX; + #define glXGetFBConfigAttribSGIX GLeeFuncPtr_glXGetFBConfigAttribSGIX +#endif +#ifndef GLEE_H_DEFINED_glXChooseFBConfigSGIX +#define GLEE_H_DEFINED_glXChooseFBConfigSGIX + typedef GLXFBConfigSGIX * (APIENTRYP GLEEPFNGLXCHOOSEFBCONFIGSGIXPROC) (Display * dpy, int screen, int * attrib_list, int * nelements); + GLEE_EXTERN GLEEPFNGLXCHOOSEFBCONFIGSGIXPROC GLeeFuncPtr_glXChooseFBConfigSGIX; + #define glXChooseFBConfigSGIX GLeeFuncPtr_glXChooseFBConfigSGIX +#endif +#ifndef GLEE_H_DEFINED_glXCreateGLXPixmapWithConfigSGIX +#define GLEE_H_DEFINED_glXCreateGLXPixmapWithConfigSGIX + typedef GLXPixmap (APIENTRYP GLEEPFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (Display * dpy, GLXFBConfigSGIX config, Pixmap pixmap); + GLEE_EXTERN GLEEPFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC GLeeFuncPtr_glXCreateGLXPixmapWithConfigSGIX; + #define glXCreateGLXPixmapWithConfigSGIX GLeeFuncPtr_glXCreateGLXPixmapWithConfigSGIX +#endif +#ifndef GLEE_H_DEFINED_glXCreateContextWithConfigSGIX +#define GLEE_H_DEFINED_glXCreateContextWithConfigSGIX + typedef GLXContext (APIENTRYP GLEEPFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display * dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct); + GLEE_EXTERN GLEEPFNGLXCREATECONTEXTWITHCONFIGSGIXPROC GLeeFuncPtr_glXCreateContextWithConfigSGIX; + #define glXCreateContextWithConfigSGIX GLeeFuncPtr_glXCreateContextWithConfigSGIX +#endif +#ifndef GLEE_H_DEFINED_glXGetVisualFromFBConfigSGIX +#define GLEE_H_DEFINED_glXGetVisualFromFBConfigSGIX + typedef XVisualInfo * (APIENTRYP GLEEPFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display * dpy, GLXFBConfigSGIX config); + GLEE_EXTERN GLEEPFNGLXGETVISUALFROMFBCONFIGSGIXPROC GLeeFuncPtr_glXGetVisualFromFBConfigSGIX; + #define glXGetVisualFromFBConfigSGIX GLeeFuncPtr_glXGetVisualFromFBConfigSGIX +#endif +#ifndef GLEE_H_DEFINED_glXGetFBConfigFromVisualSGIX +#define GLEE_H_DEFINED_glXGetFBConfigFromVisualSGIX + typedef GLXFBConfigSGIX (APIENTRYP GLEEPFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (Display * dpy, XVisualInfo * vis); + GLEE_EXTERN GLEEPFNGLXGETFBCONFIGFROMVISUALSGIXPROC GLeeFuncPtr_glXGetFBConfigFromVisualSGIX; + #define glXGetFBConfigFromVisualSGIX GLeeFuncPtr_glXGetFBConfigFromVisualSGIX +#endif +#endif + +/* GLX_SGIX_pbuffer */ + +#ifndef GLX_SGIX_pbuffer +#define GLX_SGIX_pbuffer 1 +#define __GLEE_GLX_SGIX_pbuffer 1 +/* Constants */ +#define GLX_PBUFFER_BIT_SGIX 0x00000004 +#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000 +#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008 +#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010 +#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020 +#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040 +#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080 +#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100 +#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017 +#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018 +#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019 +#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A +#define GLX_PRESERVED_CONTENTS_SGIX 0x801B +#define GLX_LARGEST_PBUFFER_SGIX 0x801C +#define GLX_WIDTH_SGIX 0x801D +#define GLX_HEIGHT_SGIX 0x801E +#define GLX_EVENT_MASK_SGIX 0x801F +#define GLX_DAMAGED_SGIX 0x8020 +#define GLX_SAVED_SGIX 0x8021 +#define GLX_WINDOW_SGIX 0x8022 +#define GLX_PBUFFER_SGIX 0x8023 +#ifndef GLEE_H_DEFINED_glXCreateGLXPbufferSGIX +#define GLEE_H_DEFINED_glXCreateGLXPbufferSGIX + typedef GLXPbufferSGIX (APIENTRYP GLEEPFNGLXCREATEGLXPBUFFERSGIXPROC) (Display * dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int * attrib_list); + GLEE_EXTERN GLEEPFNGLXCREATEGLXPBUFFERSGIXPROC GLeeFuncPtr_glXCreateGLXPbufferSGIX; + #define glXCreateGLXPbufferSGIX GLeeFuncPtr_glXCreateGLXPbufferSGIX +#endif +#ifndef GLEE_H_DEFINED_glXDestroyGLXPbufferSGIX +#define GLEE_H_DEFINED_glXDestroyGLXPbufferSGIX + typedef void (APIENTRYP GLEEPFNGLXDESTROYGLXPBUFFERSGIXPROC) (Display * dpy, GLXPbufferSGIX pbuf); + GLEE_EXTERN GLEEPFNGLXDESTROYGLXPBUFFERSGIXPROC GLeeFuncPtr_glXDestroyGLXPbufferSGIX; + #define glXDestroyGLXPbufferSGIX GLeeFuncPtr_glXDestroyGLXPbufferSGIX +#endif +#ifndef GLEE_H_DEFINED_glXQueryGLXPbufferSGIX +#define GLEE_H_DEFINED_glXQueryGLXPbufferSGIX + typedef int (APIENTRYP GLEEPFNGLXQUERYGLXPBUFFERSGIXPROC) (Display * dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int * value); + GLEE_EXTERN GLEEPFNGLXQUERYGLXPBUFFERSGIXPROC GLeeFuncPtr_glXQueryGLXPbufferSGIX; + #define glXQueryGLXPbufferSGIX GLeeFuncPtr_glXQueryGLXPbufferSGIX +#endif +#ifndef GLEE_H_DEFINED_glXSelectEventSGIX +#define GLEE_H_DEFINED_glXSelectEventSGIX + typedef void (APIENTRYP GLEEPFNGLXSELECTEVENTSGIXPROC) (Display * dpy, GLXDrawable drawable, unsigned long mask); + GLEE_EXTERN GLEEPFNGLXSELECTEVENTSGIXPROC GLeeFuncPtr_glXSelectEventSGIX; + #define glXSelectEventSGIX GLeeFuncPtr_glXSelectEventSGIX +#endif +#ifndef GLEE_H_DEFINED_glXGetSelectedEventSGIX +#define GLEE_H_DEFINED_glXGetSelectedEventSGIX + typedef void (APIENTRYP GLEEPFNGLXGETSELECTEDEVENTSGIXPROC) (Display * dpy, GLXDrawable drawable, unsigned long * mask); + GLEE_EXTERN GLEEPFNGLXGETSELECTEDEVENTSGIXPROC GLeeFuncPtr_glXGetSelectedEventSGIX; + #define glXGetSelectedEventSGIX GLeeFuncPtr_glXGetSelectedEventSGIX +#endif +#endif + +/* GLX_SGI_cushion */ + +#ifndef GLX_SGI_cushion +#define GLX_SGI_cushion 1 +#define __GLEE_GLX_SGI_cushion 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glXCushionSGI +#define GLEE_H_DEFINED_glXCushionSGI + typedef void (APIENTRYP GLEEPFNGLXCUSHIONSGIPROC) (Display * dpy, Window window, float cushion); + GLEE_EXTERN GLEEPFNGLXCUSHIONSGIPROC GLeeFuncPtr_glXCushionSGI; + #define glXCushionSGI GLeeFuncPtr_glXCushionSGI +#endif +#endif + +/* GLX_SGIX_video_resize */ + +#ifndef GLX_SGIX_video_resize +#define GLX_SGIX_video_resize 1 +#define __GLEE_GLX_SGIX_video_resize 1 +/* Constants */ +#define GLX_SYNC_FRAME_SGIX 0x00000000 +#define GLX_SYNC_SWAP_SGIX 0x00000001 +#ifndef GLEE_H_DEFINED_glXBindChannelToWindowSGIX +#define GLEE_H_DEFINED_glXBindChannelToWindowSGIX + typedef int (APIENTRYP GLEEPFNGLXBINDCHANNELTOWINDOWSGIXPROC) (Display * display, int screen, int channel, Window window); + GLEE_EXTERN GLEEPFNGLXBINDCHANNELTOWINDOWSGIXPROC GLeeFuncPtr_glXBindChannelToWindowSGIX; + #define glXBindChannelToWindowSGIX GLeeFuncPtr_glXBindChannelToWindowSGIX +#endif +#ifndef GLEE_H_DEFINED_glXChannelRectSGIX +#define GLEE_H_DEFINED_glXChannelRectSGIX + typedef int (APIENTRYP GLEEPFNGLXCHANNELRECTSGIXPROC) (Display * display, int screen, int channel, int x, int y, int w, int h); + GLEE_EXTERN GLEEPFNGLXCHANNELRECTSGIXPROC GLeeFuncPtr_glXChannelRectSGIX; + #define glXChannelRectSGIX GLeeFuncPtr_glXChannelRectSGIX +#endif +#ifndef GLEE_H_DEFINED_glXQueryChannelRectSGIX +#define GLEE_H_DEFINED_glXQueryChannelRectSGIX + typedef int (APIENTRYP GLEEPFNGLXQUERYCHANNELRECTSGIXPROC) (Display * display, int screen, int channel, int * dx, int * dy, int * dw, int * dh); + GLEE_EXTERN GLEEPFNGLXQUERYCHANNELRECTSGIXPROC GLeeFuncPtr_glXQueryChannelRectSGIX; + #define glXQueryChannelRectSGIX GLeeFuncPtr_glXQueryChannelRectSGIX +#endif +#ifndef GLEE_H_DEFINED_glXQueryChannelDeltasSGIX +#define GLEE_H_DEFINED_glXQueryChannelDeltasSGIX + typedef int (APIENTRYP GLEEPFNGLXQUERYCHANNELDELTASSGIXPROC) (Display * display, int screen, int channel, int * x, int * y, int * w, int * h); + GLEE_EXTERN GLEEPFNGLXQUERYCHANNELDELTASSGIXPROC GLeeFuncPtr_glXQueryChannelDeltasSGIX; + #define glXQueryChannelDeltasSGIX GLeeFuncPtr_glXQueryChannelDeltasSGIX +#endif +#ifndef GLEE_H_DEFINED_glXChannelRectSyncSGIX +#define GLEE_H_DEFINED_glXChannelRectSyncSGIX + typedef int (APIENTRYP GLEEPFNGLXCHANNELRECTSYNCSGIXPROC) (Display * display, int screen, int channel, GLenum synctype); + GLEE_EXTERN GLEEPFNGLXCHANNELRECTSYNCSGIXPROC GLeeFuncPtr_glXChannelRectSyncSGIX; + #define glXChannelRectSyncSGIX GLeeFuncPtr_glXChannelRectSyncSGIX +#endif +#endif + +/* GLX_SGIX_swap_group */ + +#ifndef GLX_SGIX_swap_group +#define GLX_SGIX_swap_group 1 +#define __GLEE_GLX_SGIX_swap_group 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glXJoinSwapGroupSGIX +#define GLEE_H_DEFINED_glXJoinSwapGroupSGIX + typedef void (APIENTRYP GLEEPFNGLXJOINSWAPGROUPSGIXPROC) (Display * dpy, GLXDrawable drawable, GLXDrawable member); + GLEE_EXTERN GLEEPFNGLXJOINSWAPGROUPSGIXPROC GLeeFuncPtr_glXJoinSwapGroupSGIX; + #define glXJoinSwapGroupSGIX GLeeFuncPtr_glXJoinSwapGroupSGIX +#endif +#endif + +/* GLX_SGIX_swap_barrier */ + +#ifndef GLX_SGIX_swap_barrier +#define GLX_SGIX_swap_barrier 1 +#define __GLEE_GLX_SGIX_swap_barrier 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glXBindSwapBarrierSGIX +#define GLEE_H_DEFINED_glXBindSwapBarrierSGIX + typedef void (APIENTRYP GLEEPFNGLXBINDSWAPBARRIERSGIXPROC) (Display * dpy, GLXDrawable drawable, int barrier); + GLEE_EXTERN GLEEPFNGLXBINDSWAPBARRIERSGIXPROC GLeeFuncPtr_glXBindSwapBarrierSGIX; + #define glXBindSwapBarrierSGIX GLeeFuncPtr_glXBindSwapBarrierSGIX +#endif +#ifndef GLEE_H_DEFINED_glXQueryMaxSwapBarriersSGIX +#define GLEE_H_DEFINED_glXQueryMaxSwapBarriersSGIX + typedef Bool (APIENTRYP GLEEPFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (Display * dpy, int screen, int * max); + GLEE_EXTERN GLEEPFNGLXQUERYMAXSWAPBARRIERSSGIXPROC GLeeFuncPtr_glXQueryMaxSwapBarriersSGIX; + #define glXQueryMaxSwapBarriersSGIX GLeeFuncPtr_glXQueryMaxSwapBarriersSGIX +#endif +#endif + +/* GLX_SGIS_blended_overlay */ + +#ifndef GLX_SGIS_blended_overlay +#define GLX_SGIS_blended_overlay 1 +#define __GLEE_GLX_SGIS_blended_overlay 1 +/* Constants */ +#define GLX_BLENDED_RGBA_SGIS 0x8025 +#endif + +/* GLX_SGIS_shared_multisample */ + +#ifndef GLX_SGIS_shared_multisample +#define GLX_SGIS_shared_multisample 1 +#define __GLEE_GLX_SGIS_shared_multisample 1 +/* Constants */ +#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026 +#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027 +#endif + +/* GLX_SUN_get_transparent_index */ + +#ifndef GLX_SUN_get_transparent_index +#define GLX_SUN_get_transparent_index 1 +#define __GLEE_GLX_SUN_get_transparent_index 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glXGetTransparentIndexSUN +#define GLEE_H_DEFINED_glXGetTransparentIndexSUN + typedef Status (APIENTRYP GLEEPFNGLXGETTRANSPARENTINDEXSUNPROC) (Display * dpy, Window overlay, Window underlay, long * pTransparentIndex); + GLEE_EXTERN GLEEPFNGLXGETTRANSPARENTINDEXSUNPROC GLeeFuncPtr_glXGetTransparentIndexSUN; + #define glXGetTransparentIndexSUN GLeeFuncPtr_glXGetTransparentIndexSUN +#endif +#endif + +/* GLX_3DFX_multisample */ + +#ifndef GLX_3DFX_multisample +#define GLX_3DFX_multisample 1 +#define __GLEE_GLX_3DFX_multisample 1 +/* Constants */ +#define GLX_SAMPLE_BUFFERS_3DFX 0x8050 +#define GLX_SAMPLES_3DFX 0x8051 +#endif + +/* GLX_MESA_copy_sub_buffer */ + +#ifndef GLX_MESA_copy_sub_buffer +#define GLX_MESA_copy_sub_buffer 1 +#define __GLEE_GLX_MESA_copy_sub_buffer 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glXCopySubBufferMESA +#define GLEE_H_DEFINED_glXCopySubBufferMESA + typedef void (APIENTRYP GLEEPFNGLXCOPYSUBBUFFERMESAPROC) (Display * dpy, GLXDrawable drawable, int x, int y, int width, int height); + GLEE_EXTERN GLEEPFNGLXCOPYSUBBUFFERMESAPROC GLeeFuncPtr_glXCopySubBufferMESA; + #define glXCopySubBufferMESA GLeeFuncPtr_glXCopySubBufferMESA +#endif +#endif + +/* GLX_MESA_pixmap_colormap */ + +#ifndef GLX_MESA_pixmap_colormap +#define GLX_MESA_pixmap_colormap 1 +#define __GLEE_GLX_MESA_pixmap_colormap 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glXCreateGLXPixmapMESA +#define GLEE_H_DEFINED_glXCreateGLXPixmapMESA + typedef GLXPixmap (APIENTRYP GLEEPFNGLXCREATEGLXPIXMAPMESAPROC) (Display * dpy, XVisualInfo * visual, Pixmap pixmap, Colormap cmap); + GLEE_EXTERN GLEEPFNGLXCREATEGLXPIXMAPMESAPROC GLeeFuncPtr_glXCreateGLXPixmapMESA; + #define glXCreateGLXPixmapMESA GLeeFuncPtr_glXCreateGLXPixmapMESA +#endif +#endif + +/* GLX_MESA_release_buffers */ + +#ifndef GLX_MESA_release_buffers +#define GLX_MESA_release_buffers 1 +#define __GLEE_GLX_MESA_release_buffers 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glXReleaseBuffersMESA +#define GLEE_H_DEFINED_glXReleaseBuffersMESA + typedef Bool (APIENTRYP GLEEPFNGLXRELEASEBUFFERSMESAPROC) (Display * dpy, GLXDrawable drawable); + GLEE_EXTERN GLEEPFNGLXRELEASEBUFFERSMESAPROC GLeeFuncPtr_glXReleaseBuffersMESA; + #define glXReleaseBuffersMESA GLeeFuncPtr_glXReleaseBuffersMESA +#endif +#endif + +/* GLX_MESA_set_3dfx_mode */ + +#ifndef GLX_MESA_set_3dfx_mode +#define GLX_MESA_set_3dfx_mode 1 +#define __GLEE_GLX_MESA_set_3dfx_mode 1 +/* Constants */ +#define GLX_3DFX_WINDOW_MODE_MESA 0x1 +#define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2 +#ifndef GLEE_H_DEFINED_glXSet3DfxModeMESA +#define GLEE_H_DEFINED_glXSet3DfxModeMESA + typedef Bool (APIENTRYP GLEEPFNGLXSET3DFXMODEMESAPROC) (int mode); + GLEE_EXTERN GLEEPFNGLXSET3DFXMODEMESAPROC GLeeFuncPtr_glXSet3DfxModeMESA; + #define glXSet3DfxModeMESA GLeeFuncPtr_glXSet3DfxModeMESA +#endif +#endif + +/* GLX_SGIX_visual_select_group */ + +#ifndef GLX_SGIX_visual_select_group +#define GLX_SGIX_visual_select_group 1 +#define __GLEE_GLX_SGIX_visual_select_group 1 +/* Constants */ +#define GLX_VISUAL_SELECT_GROUP_SGIX 0x8028 +#endif + +/* GLX_OML_swap_method */ + +#ifndef GLX_OML_swap_method +#define GLX_OML_swap_method 1 +#define __GLEE_GLX_OML_swap_method 1 +/* Constants */ +#define GLX_SWAP_METHOD_OML 0x8060 +#define GLX_SWAP_EXCHANGE_OML 0x8061 +#define GLX_SWAP_COPY_OML 0x8062 +#define GLX_SWAP_UNDEFINED_OML 0x8063 +#endif + +/* GLX_OML_sync_control */ + +#ifndef GLX_OML_sync_control +#define GLX_OML_sync_control 1 +#define __GLEE_GLX_OML_sync_control 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glXGetSyncValuesOML +#define GLEE_H_DEFINED_glXGetSyncValuesOML + typedef Bool (APIENTRYP GLEEPFNGLXGETSYNCVALUESOMLPROC) (Display * dpy, GLXDrawable drawable, int64_t * ust, int64_t * msc, int64_t * sbc); + GLEE_EXTERN GLEEPFNGLXGETSYNCVALUESOMLPROC GLeeFuncPtr_glXGetSyncValuesOML; + #define glXGetSyncValuesOML GLeeFuncPtr_glXGetSyncValuesOML +#endif +#ifndef GLEE_H_DEFINED_glXGetMscRateOML +#define GLEE_H_DEFINED_glXGetMscRateOML + typedef Bool (APIENTRYP GLEEPFNGLXGETMSCRATEOMLPROC) (Display * dpy, GLXDrawable drawable, int32_t * numerator, int32_t * denominator); + GLEE_EXTERN GLEEPFNGLXGETMSCRATEOMLPROC GLeeFuncPtr_glXGetMscRateOML; + #define glXGetMscRateOML GLeeFuncPtr_glXGetMscRateOML +#endif +#ifndef GLEE_H_DEFINED_glXSwapBuffersMscOML +#define GLEE_H_DEFINED_glXSwapBuffersMscOML + typedef int64_t (APIENTRYP GLEEPFNGLXSWAPBUFFERSMSCOMLPROC) (Display * dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder); + GLEE_EXTERN GLEEPFNGLXSWAPBUFFERSMSCOMLPROC GLeeFuncPtr_glXSwapBuffersMscOML; + #define glXSwapBuffersMscOML GLeeFuncPtr_glXSwapBuffersMscOML +#endif +#ifndef GLEE_H_DEFINED_glXWaitForMscOML +#define GLEE_H_DEFINED_glXWaitForMscOML + typedef Bool (APIENTRYP GLEEPFNGLXWAITFORMSCOMLPROC) (Display * dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t * ust, int64_t * msc, int64_t * sbc); + GLEE_EXTERN GLEEPFNGLXWAITFORMSCOMLPROC GLeeFuncPtr_glXWaitForMscOML; + #define glXWaitForMscOML GLeeFuncPtr_glXWaitForMscOML +#endif +#ifndef GLEE_H_DEFINED_glXWaitForSbcOML +#define GLEE_H_DEFINED_glXWaitForSbcOML + typedef Bool (APIENTRYP GLEEPFNGLXWAITFORSBCOMLPROC) (Display * dpy, GLXDrawable drawable, int64_t target_sbc, int64_t * ust, int64_t * msc, int64_t * sbc); + GLEE_EXTERN GLEEPFNGLXWAITFORSBCOMLPROC GLeeFuncPtr_glXWaitForSbcOML; + #define glXWaitForSbcOML GLeeFuncPtr_glXWaitForSbcOML +#endif +#endif + +/* GLX_NV_float_buffer */ + +#ifndef GLX_NV_float_buffer +#define GLX_NV_float_buffer 1 +#define __GLEE_GLX_NV_float_buffer 1 +/* Constants */ +#define GLX_FLOAT_COMPONENTS_NV 0x20B0 +#endif + +/* GLX_SGIX_hyperpipe */ + +#ifndef GLX_SGIX_hyperpipe +#define GLX_SGIX_hyperpipe 1 +#define __GLEE_GLX_SGIX_hyperpipe 1 +/* Constants */ +#define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80 +#define GLX_BAD_HYPERPIPE_CONFIG_SGIX 91 +#define GLX_BAD_HYPERPIPE_SGIX 92 +#define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001 +#define GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002 +#define GLX_PIPE_RECT_SGIX 0x00000001 +#define GLX_PIPE_RECT_LIMITS_SGIX 0x00000002 +#define GLX_HYPERPIPE_STEREO_SGIX 0x00000003 +#define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004 +#define GLX_HYPERPIPE_ID_SGIX 0x8030 +#ifndef GLEE_H_DEFINED_glXQueryHyperpipeNetworkSGIX +#define GLEE_H_DEFINED_glXQueryHyperpipeNetworkSGIX + typedef GLXHyperpipeNetworkSGIX * (APIENTRYP GLEEPFNGLXQUERYHYPERPIPENETWORKSGIXPROC) (Display * dpy, int * npipes); + GLEE_EXTERN GLEEPFNGLXQUERYHYPERPIPENETWORKSGIXPROC GLeeFuncPtr_glXQueryHyperpipeNetworkSGIX; + #define glXQueryHyperpipeNetworkSGIX GLeeFuncPtr_glXQueryHyperpipeNetworkSGIX +#endif +#ifndef GLEE_H_DEFINED_glXHyperpipeConfigSGIX +#define GLEE_H_DEFINED_glXHyperpipeConfigSGIX + typedef int (APIENTRYP GLEEPFNGLXHYPERPIPECONFIGSGIXPROC) (Display * dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX * cfg, int * hpId); + GLEE_EXTERN GLEEPFNGLXHYPERPIPECONFIGSGIXPROC GLeeFuncPtr_glXHyperpipeConfigSGIX; + #define glXHyperpipeConfigSGIX GLeeFuncPtr_glXHyperpipeConfigSGIX +#endif +#ifndef GLEE_H_DEFINED_glXQueryHyperpipeConfigSGIX +#define GLEE_H_DEFINED_glXQueryHyperpipeConfigSGIX + typedef GLXHyperpipeConfigSGIX * (APIENTRYP GLEEPFNGLXQUERYHYPERPIPECONFIGSGIXPROC) (Display * dpy, int hpId, int * npipes); + GLEE_EXTERN GLEEPFNGLXQUERYHYPERPIPECONFIGSGIXPROC GLeeFuncPtr_glXQueryHyperpipeConfigSGIX; + #define glXQueryHyperpipeConfigSGIX GLeeFuncPtr_glXQueryHyperpipeConfigSGIX +#endif +#ifndef GLEE_H_DEFINED_glXDestroyHyperpipeConfigSGIX +#define GLEE_H_DEFINED_glXDestroyHyperpipeConfigSGIX + typedef int (APIENTRYP GLEEPFNGLXDESTROYHYPERPIPECONFIGSGIXPROC) (Display * dpy, int hpId); + GLEE_EXTERN GLEEPFNGLXDESTROYHYPERPIPECONFIGSGIXPROC GLeeFuncPtr_glXDestroyHyperpipeConfigSGIX; + #define glXDestroyHyperpipeConfigSGIX GLeeFuncPtr_glXDestroyHyperpipeConfigSGIX +#endif +#ifndef GLEE_H_DEFINED_glXBindHyperpipeSGIX +#define GLEE_H_DEFINED_glXBindHyperpipeSGIX + typedef int (APIENTRYP GLEEPFNGLXBINDHYPERPIPESGIXPROC) (Display * dpy, int hpId); + GLEE_EXTERN GLEEPFNGLXBINDHYPERPIPESGIXPROC GLeeFuncPtr_glXBindHyperpipeSGIX; + #define glXBindHyperpipeSGIX GLeeFuncPtr_glXBindHyperpipeSGIX +#endif +#ifndef GLEE_H_DEFINED_glXQueryHyperpipeBestAttribSGIX +#define GLEE_H_DEFINED_glXQueryHyperpipeBestAttribSGIX + typedef int (APIENTRYP GLEEPFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC) (Display * dpy, int timeSlice, int attrib, int size, void * attribList, void * returnAttribList); + GLEE_EXTERN GLEEPFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC GLeeFuncPtr_glXQueryHyperpipeBestAttribSGIX; + #define glXQueryHyperpipeBestAttribSGIX GLeeFuncPtr_glXQueryHyperpipeBestAttribSGIX +#endif +#ifndef GLEE_H_DEFINED_glXHyperpipeAttribSGIX +#define GLEE_H_DEFINED_glXHyperpipeAttribSGIX + typedef int (APIENTRYP GLEEPFNGLXHYPERPIPEATTRIBSGIXPROC) (Display * dpy, int timeSlice, int attrib, int size, void * attribList); + GLEE_EXTERN GLEEPFNGLXHYPERPIPEATTRIBSGIXPROC GLeeFuncPtr_glXHyperpipeAttribSGIX; + #define glXHyperpipeAttribSGIX GLeeFuncPtr_glXHyperpipeAttribSGIX +#endif +#ifndef GLEE_H_DEFINED_glXQueryHyperpipeAttribSGIX +#define GLEE_H_DEFINED_glXQueryHyperpipeAttribSGIX + typedef int (APIENTRYP GLEEPFNGLXQUERYHYPERPIPEATTRIBSGIXPROC) (Display * dpy, int timeSlice, int attrib, int size, void * returnAttribList); + GLEE_EXTERN GLEEPFNGLXQUERYHYPERPIPEATTRIBSGIXPROC GLeeFuncPtr_glXQueryHyperpipeAttribSGIX; + #define glXQueryHyperpipeAttribSGIX GLeeFuncPtr_glXQueryHyperpipeAttribSGIX +#endif +#endif + +/* GLX_MESA_agp_offset */ + +#ifndef GLX_MESA_agp_offset +#define GLX_MESA_agp_offset 1 +#define __GLEE_GLX_MESA_agp_offset 1 +/* Constants */ +#ifndef GLEE_H_DEFINED_glXGetAGPOffsetMESA +#define GLEE_H_DEFINED_glXGetAGPOffsetMESA + typedef unsigned int (APIENTRYP GLEEPFNGLXGETAGPOFFSETMESAPROC) (const void * pointer); + GLEE_EXTERN GLEEPFNGLXGETAGPOFFSETMESAPROC GLeeFuncPtr_glXGetAGPOffsetMESA; + #define glXGetAGPOffsetMESA GLeeFuncPtr_glXGetAGPOffsetMESA +#endif +#endif + +/* GLX_EXT_fbconfig_packed_float */ + +#ifndef GLX_EXT_fbconfig_packed_float +#define GLX_EXT_fbconfig_packed_float 1 +#define __GLEE_GLX_EXT_fbconfig_packed_float 1 +/* Constants */ +#define GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT 0x20B1 +#define GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT 0x00000008 +#endif + +/* GLX_EXT_framebuffer_sRGB */ + +#ifndef GLX_EXT_framebuffer_sRGB +#define GLX_EXT_framebuffer_sRGB 1 +#define __GLEE_GLX_EXT_framebuffer_sRGB 1 +/* Constants */ +#define GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20B2 +#endif + +/* GLX_EXT_texture_from_pixmap */ + +#ifndef GLX_EXT_texture_from_pixmap +#define GLX_EXT_texture_from_pixmap 1 +#define __GLEE_GLX_EXT_texture_from_pixmap 1 +/* Constants */ +#define GLX_TEXTURE_1D_BIT_EXT 0x00000001 +#define GLX_TEXTURE_2D_BIT_EXT 0x00000002 +#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004 +#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0 +#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1 +#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2 +#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3 +#define GLX_Y_INVERTED_EXT 0x20D4 +#define GLX_TEXTURE_FORMAT_EXT 0x20D5 +#define GLX_TEXTURE_TARGET_EXT 0x20D6 +#define GLX_MIPMAP_TEXTURE_EXT 0x20D7 +#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8 +#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9 +#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA +#define GLX_TEXTURE_1D_EXT 0x20DB +#define GLX_TEXTURE_2D_EXT 0x20DC +#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD +#define GLX_FRONT_LEFT_EXT 0x20DE +#define GLX_FRONT_RIGHT_EXT 0x20DF +#define GLX_BACK_LEFT_EXT 0x20E0 +#define GLX_BACK_RIGHT_EXT 0x20E1 +#define GLX_FRONT_EXT GLX_FRONT_LEFT_EXT +#define GLX_BACK_EXT GLX_BACK_LEFT_EXT +#define GLX_AUX0_EXT 0x20E2 +#define GLX_AUX1_EXT 0x20E3 +#define GLX_AUX2_EXT 0x20E4 +#define GLX_AUX3_EXT 0x20E5 +#define GLX_AUX4_EXT 0x20E6 +#define GLX_AUX5_EXT 0x20E7 +#define GLX_AUX6_EXT 0x20E8 +#define GLX_AUX7_EXT 0x20E9 +#define GLX_AUX8_EXT 0x20EA +#define GLX_AUX9_EXT 0x20EB +#ifndef GLEE_H_DEFINED_glXBindTexImageEXT +#define GLEE_H_DEFINED_glXBindTexImageEXT + typedef void (APIENTRYP GLEEPFNGLXBINDTEXIMAGEEXTPROC) (Display * dpy, GLXDrawable drawable, int buffer, const int * attrib_list); + GLEE_EXTERN GLEEPFNGLXBINDTEXIMAGEEXTPROC GLeeFuncPtr_glXBindTexImageEXT; + #define glXBindTexImageEXT GLeeFuncPtr_glXBindTexImageEXT +#endif +#ifndef GLEE_H_DEFINED_glXReleaseTexImageEXT +#define GLEE_H_DEFINED_glXReleaseTexImageEXT + typedef void (APIENTRYP GLEEPFNGLXRELEASETEXIMAGEEXTPROC) (Display * dpy, GLXDrawable drawable, int buffer); + GLEE_EXTERN GLEEPFNGLXRELEASETEXIMAGEEXTPROC GLeeFuncPtr_glXReleaseTexImageEXT; + #define glXReleaseTexImageEXT GLeeFuncPtr_glXReleaseTexImageEXT +#endif +#endif + +/* GLX_NV_present_video */ + +#ifndef GLX_NV_present_video +#define GLX_NV_present_video 1 +#define __GLEE_GLX_NV_present_video 1 +/* Constants */ +#define GLX_NUM_VIDEO_SLOTS_NV 0x20F0 +#endif + +/* GLX_NV_video_out */ + +#ifndef GLX_NV_video_out +#define GLX_NV_video_out 1 +#define __GLEE_GLX_NV_video_out 1 +/* Constants */ +#define GLX_VIDEO_OUT_COLOR_NV 0x20C3 +#define GLX_VIDEO_OUT_ALPHA_NV 0x20C4 +#define GLX_VIDEO_OUT_DEPTH_NV 0x20C5 +#define GLX_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 +#define GLX_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 +#define GLX_VIDEO_OUT_FRAME_NV 0x20C8 +#define GLX_VIDEO_OUT_FIELD_1_NV 0x20C9 +#define GLX_VIDEO_OUT_FIELD_2_NV 0x20CA +#define GLX_VIDEO_OUT_STACKED_FIELDS_1_2_NV 0x20CB +#define GLX_VIDEO_OUT_STACKED_FIELDS_2_1_NV 0x20CC +#endif + +/* GLX_NV_swap_group */ + +#ifndef GLX_NV_swap_group +#define GLX_NV_swap_group 1 +#define __GLEE_GLX_NV_swap_group 1 +/* Constants */ +#endif + +/* GLX_EXT_scene_marker */ + +#ifndef GLX_EXT_scene_marker +#define GLX_EXT_scene_marker 1 +#define __GLEE_GLX_EXT_scene_marker 1 +/* Constants */ +#endif + +/* GLX_NV_video_output */ + +#ifndef GLX_NV_video_output +#define GLX_NV_video_output 1 +#define __GLEE_GLX_NV_video_output 1 +/* Constants */ +#define GLX_VIDEO_OUT_COLOR_NV 0x20C3 +#define GLX_VIDEO_OUT_ALPHA_NV 0x20C4 +#define GLX_VIDEO_OUT_DEPTH_NV 0x20C5 +#define GLX_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 +#define GLX_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 +#define GLX_VIDEO_OUT_FRAME_NV 0x20C8 +#define GLX_VIDEO_OUT_FIELD_1_NV 0x20C9 +#define GLX_VIDEO_OUT_FIELD_2_NV 0x20CA +#define GLX_VIDEO_OUT_STACKED_FIELDS_1_2_NV 0x20CB +#define GLX_VIDEO_OUT_STACKED_FIELDS_2_1_NV 0x20CC +#ifndef GLEE_H_DEFINED_glXGetVideoDeviceNV +#define GLEE_H_DEFINED_glXGetVideoDeviceNV + typedef int (APIENTRYP GLEEPFNGLXGETVIDEODEVICENVPROC) (Display * dpy, int screen, int numVideoDevices, GLXVideoDeviceNV * pVideoDevice); + GLEE_EXTERN GLEEPFNGLXGETVIDEODEVICENVPROC GLeeFuncPtr_glXGetVideoDeviceNV; + #define glXGetVideoDeviceNV GLeeFuncPtr_glXGetVideoDeviceNV +#endif +#ifndef GLEE_H_DEFINED_glXReleaseVideoDeviceNV +#define GLEE_H_DEFINED_glXReleaseVideoDeviceNV + typedef int (APIENTRYP GLEEPFNGLXRELEASEVIDEODEVICENVPROC) (Display * dpy, int screen, GLXVideoDeviceNV VideoDevice); + GLEE_EXTERN GLEEPFNGLXRELEASEVIDEODEVICENVPROC GLeeFuncPtr_glXReleaseVideoDeviceNV; + #define glXReleaseVideoDeviceNV GLeeFuncPtr_glXReleaseVideoDeviceNV +#endif +#ifndef GLEE_H_DEFINED_glXBindVideoImageNV +#define GLEE_H_DEFINED_glXBindVideoImageNV + typedef int (APIENTRYP GLEEPFNGLXBINDVIDEOIMAGENVPROC) (Display * dpy, GLXVideoDeviceNV VideoDevice, GLXPbuffer pbuf, int iVideoBuffer); + GLEE_EXTERN GLEEPFNGLXBINDVIDEOIMAGENVPROC GLeeFuncPtr_glXBindVideoImageNV; + #define glXBindVideoImageNV GLeeFuncPtr_glXBindVideoImageNV +#endif +#ifndef GLEE_H_DEFINED_glXReleaseVideoImageNV +#define GLEE_H_DEFINED_glXReleaseVideoImageNV + typedef int (APIENTRYP GLEEPFNGLXRELEASEVIDEOIMAGENVPROC) (Display * dpy, GLXPbuffer pbuf); + GLEE_EXTERN GLEEPFNGLXRELEASEVIDEOIMAGENVPROC GLeeFuncPtr_glXReleaseVideoImageNV; + #define glXReleaseVideoImageNV GLeeFuncPtr_glXReleaseVideoImageNV +#endif +#ifndef GLEE_H_DEFINED_glXSendPbufferToVideoNV +#define GLEE_H_DEFINED_glXSendPbufferToVideoNV + typedef int (APIENTRYP GLEEPFNGLXSENDPBUFFERTOVIDEONVPROC) (Display * dpy, GLXPbuffer pbuf, int iBufferType, unsigned long * pulCounterPbuffer, GLboolean bBlock); + GLEE_EXTERN GLEEPFNGLXSENDPBUFFERTOVIDEONVPROC GLeeFuncPtr_glXSendPbufferToVideoNV; + #define glXSendPbufferToVideoNV GLeeFuncPtr_glXSendPbufferToVideoNV +#endif +#ifndef GLEE_H_DEFINED_glXGetVideoInfoNV +#define GLEE_H_DEFINED_glXGetVideoInfoNV + typedef int (APIENTRYP GLEEPFNGLXGETVIDEOINFONVPROC) (Display * dpy, int screen, GLXVideoDeviceNV VideoDevice, unsigned long * pulCounterOutputPbuffer, unsigned long * pulCounterOutputVideo); + GLEE_EXTERN GLEEPFNGLXGETVIDEOINFONVPROC GLeeFuncPtr_glXGetVideoInfoNV; + #define glXGetVideoInfoNV GLeeFuncPtr_glXGetVideoInfoNV +#endif +#endif +#endif /*end GLX */ + +/***************************************************************** + * GLee functions + *****************************************************************/ + +GLEE_EXTERN GLboolean GLeeInit( void ); +GLEE_EXTERN GLint GLeeForceLink(const char * extensionName); +GLEE_EXTERN const char * GLeeGetErrorString( void ); +GLEE_EXTERN const char * GLeeGetExtStrGL( void ); +GLEE_EXTERN GLboolean GLeeEnabled(GLboolean * extensionQueryingVariable); + +#ifdef WIN32 +GLEE_EXTERN const char * GLeeGetExtStrWGL( void ); +#elif defined(__APPLE__) || defined(__APPLE_CC__) +#else +GLEE_EXTERN const char * GLeeGetExtStrGLX( void ); +#endif + +#ifdef __cplusplus +} /* end C linkage */ +#endif + +#endif /* __glee_h_ defined */ diff --git a/Extras/sph/common/common_defs.h b/Extras/sph/common/common_defs.h new file mode 100644 index 0000000..0f1628c --- /dev/null +++ b/Extras/sph/common/common_defs.h @@ -0,0 +1,52 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 COMMON_DEF + #define COMMON_DEF + + // Global defs + + //#define USE_SHADOWS // Disable if you don't have FBOs, or to greatly speed up demo. + +// #define USE_JPEG + + #define BUILD_CUDA // CUDA - Visual Studio 2005 only (as of April 2009) + + #define TEX_SIZE 2048 + #define LIGHT_NEAR 0.5 + #define LIGHT_FAR 300.0 + #define DEGtoRAD (3.141592/180.0) + + #ifdef _MSC_VER + #include + #else + typedef unsigned int DWORD; + #endif + typedef unsigned int uint; + + #define COLOR(r,g,b) ( (DWORD(r*255.0f)<<24) | (DWORD(g*255.0f)<<16) | (DWORD(b*255.0f)<<8) ) + #define COLORA(r,g,b,a) ( (DWORD(r*255.0f)<<24) | (DWORD(g*255.0f)<<16) | (DWORD(b*255.0f)<<8) | DWORD(a*255.0f) ) + #define RED(c) (float((c>>24) & 0xFF)/255.0) + #define GRN(c) (float((c>>16) & 0xFF)/255.0) + #define BLUE(c) (float((c>>8) & 0xFF)/255.0) + #define ALPH(c) (float(c & 0xFF)/255.0) +#endif \ No newline at end of file diff --git a/Extras/sph/common/geomx.cpp b/Extras/sph/common/geomx.cpp new file mode 100644 index 0000000..4503fee --- /dev/null +++ b/Extras/sph/common/geomx.cpp @@ -0,0 +1,443 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 +#include "geomx.h" +#include "mdebug.h" + +#include + +GeomX::GeomX () +{ + mHeap = 0x0; +} + +void GeomX::FreeBuffers () +{ + for (int n=0; n < (int) mBuf.size(); n++) { + free ( mBuf[n].data ); + mBuf[n].data = 0x0; + } + mBuf.clear (); + + if ( mHeap != 0x0 ) free ( mHeap ); + mHeap = 0x0; + mHeapNum = 0; + mHeapMax = 0; +} + +void GeomX::ResetHeap () +{ + mHeapNum = 0; + mHeapFree = -1; +} + +int GeomX::GetSize () +{ + int sum = mHeapNum * sizeof(hval) ; + for (int n=0; n < (int) mBuf.size(); n++) + sum += mBuf[n].size; + sum += (int) mAttribute.size() * sizeof(GeomAttr); + return sum; +} + +void GeomX::ClearAttributes () +{ + mAttribute.clear (); +} + +int GeomX::CopyBuffer ( uchar bdest, uchar bsrc, GeomX& src ) +{ + if ( bsrc >= src.GetNumBuf() ) return -1; + + if ( bdest >= GetNumBuf() ) { + for (int n=0; n <= bdest - GetNumBuf(); n++ ) + AddBuffer ( 0, 0, 0 ); + } + if ( mBuf[bdest].data != 0x0 ) { + free ( mBuf[bdest].data ); + mBuf[bdest].data = 0x0; + } + + GeomBuf* buf = src.GetBuffer( bsrc ); + mBuf[bdest].dtype = buf->dtype; + mBuf[bdest].max = buf->max; + mBuf[bdest].num = buf->num; + mBuf[bdest].stride = buf->stride; + mBuf[bdest].size = buf->size; + mBuf[bdest].data = (char*) malloc ( mBuf[bdest].max * mBuf[bdest].stride ); + memcpy ( mBuf[bdest].data, buf->data, mBuf[bdest].num * mBuf[bdest].stride ); + + return bdest; +} + + +void GeomX::CopyBuffers ( GeomX& src ) +{ + FreeBuffers (); + for (int n = 0; n < src.GetNumBuf(); n++) + CopyBuffer ( n, n, src ); + CopyHeap ( src ); +} + +void GeomX::CopyHeap ( GeomX& src ) +{ + hpos num, max, freepos; + hval* src_data = src.GetHeap ( num, max, freepos ); + + if ( mHeap != 0x0 ) { + free ( mHeap ); + mHeap = 0x0; + } + + mHeap = (hval*) malloc ( max * sizeof(hval) ); + mHeapMax = max; + mHeapNum = num; + mHeapFree = freepos; + + memcpy ( mHeap, src_data, mHeapNum * sizeof(hval) ); +} + +hval* GeomX::GetHeap ( hpos& num, hpos& max, hpos& free ) +{ + num = mHeapNum; + max = mHeapMax; + free = mHeapFree; + return mHeap; +} + +void GeomX::CopyAttributes ( GeomX& src ) +{ + GeomAttr* attr; + ClearAttributes (); + int a; + for (int n = 0; n < src.GetNumAttr(); n++) { + attr = src.GetAttribute ( n ); + a = AddAttribute ( (uchar) attr->buf, attr->name, attr->stride, false ); + mAttribute[a].offset = attr->offset; + } +} + + +void GeomX::AddHeap ( int max ) +{ + mHeap = (hval*) malloc ( max * sizeof(hval ) ); + mHeapMax = max; + mHeapNum = 0; + mHeapFree = -1; +} + +int GeomX::AddAttribute ( uchar b, std::string name, ushort stride ) +{ + return AddAttribute ( b, name, stride, true ); +} + +int GeomX::AddAttribute ( uchar b, std::string name, ushort stride, bool bExtend ) +{ + GeomBuf* buf = &mBuf[b]; + GeomAttr attr; + + attr.buf = b; + attr.name = name; + attr.offset = buf->stride; + attr.stride = stride; + + if ( bExtend ) { + int new_stride = buf->stride + attr.stride; + char* new_data = (char*) malloc ( buf->max * new_stride ); + char* old_data = buf->data; + for (int n=0; n < buf->num; n++) { + memcpy ( new_data, old_data, buf->stride ); + old_data += buf->stride; + new_data += new_stride; + } + free ( buf->data ); + buf->data = new_data; + buf->stride = new_stride; + } + mAttribute.push_back ( attr ); + return (int) mAttribute.size()-1; +} + +int GeomX::GetAttribute ( std::string name ) +{ + for (int n=0; n < (int) mAttribute.size(); n++) { + if ( mAttribute[n].name.compare ( name ) == 0 ) + return n; + } + return -1; +} + +int GeomX::GetAttrOffset ( std::string name ) +{ + for (int n=0; n < (int) mAttribute.size(); n++) { + if ( mAttribute[n].name.compare ( name ) == 0 ) + return mAttribute[n].offset; + } + return -1; +} + +int GeomX::AddBuffer ( uchar typ, ushort stride, int max ) +{ + GeomBuf buf; + buf.dtype = typ; + buf.stride = stride; + buf.max = max; + buf.num = 0; + buf.size = 0; + buf.data = (char*) malloc ( buf.max * buf.stride ); + mBuf.push_back ( buf ); + return (int) mBuf.size()-1; +} +void GeomX::ResetBuffer ( uchar b, int n ) +{ + mBuf[b].max = n; + + if ( mBuf[b].data != 0x0 ) free ( mBuf[b].data ); + + char* new_data = (char*) malloc ( mBuf[b].max * mBuf[b].stride ); + + mBuf[b].data = new_data; + + mBuf[b].num = 0; + mBuf[b].size = mBuf[b].num*mBuf[b].stride; +} + +char* GeomX::AddElem ( uchar b, href& ndx ) +{ + if ( mBuf[b].num >= mBuf[b].max ) { + if ( long(mBuf[b].max) * 2 > ELEM_MAX ) { + error.PrintF ( "geom", "Maximum number of elements reached.\n" ); + error.Exit (); + } + mBuf[b].max *= 2; + char* new_data = (char*) malloc ( mBuf[b].max * mBuf[b].stride ); + memcpy ( new_data, mBuf[b].data, mBuf[b].num*mBuf[b].stride ); + free ( mBuf[b].data ); + mBuf[b].data = new_data; + } + mBuf[b].num++; + mBuf[b].size += mBuf[b].stride; + ndx = mBuf[b].num-1; + return mBuf[b].data + ndx*mBuf[b].stride; +} + +char* GeomX::RandomElem ( uchar b, href& ndx ) +{ + ndx = mBuf[b].num * rand() / RAND_MAX; + return mBuf[b].data + ndx*mBuf[b].stride; +} + +int GeomX::AddElem ( uchar b, char* data ) +{ + if ( mBuf[b].num >= mBuf[b].max ) { + mBuf[b].max *= 2; + char* new_data = (char*) malloc ( mBuf[b].max * mBuf[b].stride ); + memcpy ( new_data, mBuf[b].data, mBuf[b].num*mBuf[b].stride ); + free ( mBuf[b].data ); + mBuf[b].data = new_data; + } + memcpy ( mBuf[b].data + mBuf[b].num*mBuf[b].stride, data, mBuf[b].stride ); + mBuf[b].num++; + mBuf[b].size += mBuf[b].stride; + return mBuf[b].num-1; +} + +bool GeomX::DelElem ( uchar b, int n ) +{ + if ( n >= 0 && n < mBuf[b].num ) { + memcpy ( mBuf[b].data + n*mBuf[b].stride, mBuf[b].data + (mBuf[b].num-1)*mBuf[b].stride, mBuf[b].stride ); + mBuf[b].num--; + mBuf[b].size -= mBuf[b].stride; + return true; + } + return false; +} + +hpos GeomX::HeapExpand ( ushort size, ushort& ret ) +{ + mHeapMax *= 2; + if ( mHeapMax > HEAP_MAX ) { + error.PrintF ( "geom", "Geom heap size exceeds range of index.\n" ); + error.Exit (); + } + hval* pNewHeap = (hval*) malloc ( mHeapMax * sizeof(hval) ); + if ( pNewHeap == 0x0 ) { + error.PrintF ( "geom", "Geom heap out of memory.\n" ); + error.Exit (); + } + memcpy ( pNewHeap, mHeap, mHeapNum*sizeof(hval) ); + free ( mHeap ); + mHeap = pNewHeap; + ret = size; + assert ( mHeapNum >= 0 && mHeapNum < mHeapMax ); + return mHeapNum; +} + +#define LIST_INIT 4 + +hpos GeomX::HeapAlloc ( ushort size, ushort& ret ) +{ + hval* pPrev = 0x0; + hval* pCurr = mHeap + mHeapFree; + hpos pos = -1; + + if ( mHeapNum + size < mHeapMax ) { + // Heap not yet full. + pos = mHeapNum; + ret = size; + mHeapNum += size; + } else { + // Heap full, search free space + if ( mHeapFree == -1 ) { + pos = HeapExpand ( size, ret ); + mHeapNum += ret; + } else { + while ( *pCurr < size && pCurr != mHeap-1 ) { + pPrev = pCurr; + pCurr = mHeap + * (hpos*) (pCurr + FPOS); + } + if ( pCurr != mHeap-1 ) { + // Found free space. + if ( pPrev == 0x0 ) { + mHeapFree = * (hpos*) (pCurr + FPOS); + assert ( mHeapFree >= -1 ); + } else { + * (hpos*) (pPrev+FPOS) = * (hpos*) (pCurr+FPOS); + } + pos = pCurr-mHeap; + ret = *pCurr; + } else { + // Heap full, no free space. Expand heap. + pos = HeapExpand ( size, ret ); + mHeapNum += ret; + } + } + } + + assert ( pos >= 0 && pos <= mHeapNum ); + memset ( mHeap+pos, 0, size*sizeof(hval) ); + return pos; +} + +void GeomX::HeapAddFree ( hpos pos, int size ) +{ + // memset ( mHeap+pos, 0xFF, size*sizeof(hval) ); + + if ( pos < mHeapFree || mHeapFree == -1 ) { + // Lowest position. Insert at head of heap. + * (hpos*) (mHeap+pos) = size; + * (hpos*) (mHeap+pos + FPOS) = mHeapFree; + mHeapFree = pos; + if ( mHeapFree != -1 && *(hpos*) (mHeap+mHeapFree+FPOS) == 0x0 ) { error.PrintF ( "geomx", "ERROR: Heap pointer 0. pHeapFree, %d\n", pos ); error.Exit (); } + + assert ( mHeapFree >= -1 ); + } else { + hval* pCurr = mHeap + pos; + hval* pPrev = 0x0; + hval* pNext = mHeap + mHeapFree; + + if ( pCurr == pNext ) { // Freeing the first block + mHeapFree = * (hpos*) (pCurr + FPOS); + * (hpos*) (mHeap+mHeapFree + FPOS) = 0xFFFFFFFF; + * (hpos*) (pCurr + FPOS) = 0xFFFFFFFF; + * (hpos*) pCurr = 0xFFFFFFFF; + return; + + } + + // Find first block greater than new free pos. + while ( pNext < pCurr && pNext != mHeap-1 ) { + pPrev = pNext; + pNext = mHeap + * (hpos*) (pNext + FPOS); + } + + int x = 0; + if ( pPrev + *(pPrev) == pCurr ) { // Prev block touches current one (expand previous) + * (hpos*) pPrev += size; // - prev.size = prev.size + curr.size + x=1; + + } else if ( pCurr + size == pNext && pNext != mHeap-1 ) { // Curr block touches next one (expand current block) + * (hpos*) (pPrev + FPOS) = pos; // - prev.next = curr + * (hpos*) (pCurr + FPOS) = * (hpos*) (pNext + FPOS); // - curr.next = next.next + * (hpos*) pCurr = size + * (hpos*) pNext; // - curr.size = size + next.size + * (hpos*) (pNext) = 0xFFFFFFFF; // - curr = null + * (hpos*) (pNext + FPOS) = 0xFFFFFFFF; // - curr.next = null + x=2; + + } else { // Otherwise (linked list insert) + * (hpos*) (pPrev + FPOS) = pos; // - prev.next = curr + if ( pNext != mHeap-1 ) + * (hpos*) (pCurr + FPOS) = pNext - mHeap; // - curr.next = next + else + * (hpos*) (pCurr + FPOS) = 0xFFFFFFFF; // - curr.next = null (no next node) + * (hpos*) pCurr = size; // - curr.size = size + x=3; + } + if ( pCurr !=mHeap-1 && *(hpos*) (pCurr+FPOS) == 0x0 ) { error.PrintF ( "geomx", "ERROR: Heap pointer 0. pCurr, %d, %d\n", x, pos ); error.Exit (); } + if ( pPrev !=mHeap-1 && *(hpos*) (pPrev+FPOS) == 0x0 ) { error.PrintF ( "geomx", "ERROR: Heap pointer 0. pPrev, %d, %d\n", x, pos ); error.Exit (); } + if ( pNext !=mHeap-1 && *(hpos*) (pNext+FPOS) == 0x0 ) { error.PrintF ( "geomx", "ERROR: Heap pointer 0. pNext, %d, %d\n", x, pos ); error.Exit (); } + if ( *(hpos*) (mHeap+mHeapFree+FPOS) == 0x0 ) { error.PrintF ( "geomx", "ERROR: Heap pointer 0. pHeapFree, %d, %d\n", x, pos ); error.Exit (); } + + // -- check for bugs (remove eventually) + pNext = mHeap + mHeapFree; + while ( pNext != mHeap-1 ) { + pPrev = pNext; + pNext = mHeap + * (hpos*) (pNext + FPOS); + if ( pNext < pPrev && pNext != mHeap-1 ) { + error.PrintF ( "geomx", "ERROR: Heap free space out of order. %d, %d\n", x, pos ); + error.Exit (); + } + } + //--- + } + } + +void GeomX::ClearRefs ( hList& list ) +{ + list.cnt = 0; + list.max = 0; + list.pos = 0; +} + +hval GeomX::AddRef ( hval r, hList& list, hval delta ) +{ + if ( list.max == 0 ) { + list.cnt = 1; + list.pos = HeapAlloc ( LIST_INIT, list.max ); + *(mHeap + list.pos) = r+delta; + } else { + if ( list.cnt >= list.max ) { + int siz = list.max; + hpos new_pos = HeapAlloc ( siz+LIST_INIT, list.max ); // Alloc new location + //printf ( "MOVE %d -> %d\n", list.pos, new_pos ); + memcpy ( mHeap+new_pos, mHeap+list.pos, list.cnt*sizeof(hval) ); // Copy data to new location + HeapAddFree ( list.pos, siz ); // Free old location + list.pos = new_pos; + + } + *(mHeap + list.pos + list.cnt) = r+delta; + list.cnt++; + } + return list.pos; +} \ No newline at end of file diff --git a/Extras/sph/common/geomx.h b/Extras/sph/common/geomx.h new file mode 100644 index 0000000..e1f20f6 --- /dev/null +++ b/Extras/sph/common/geomx.h @@ -0,0 +1,125 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 DEF_GEOM + #define DEF_GEOM + + #include + + #define HEAP_MAX 2147483640 // largest heap size (range of hpos) + + #define ELEM_MAX 2147483640 // largest number of elements in a buffer (range of hval) + //#define ELEM_MAX 32768 // largest number of elements in a buffer (range of hval) + + #define BUF_UNDEF 255 + + #define FPOS 2 // free position offsets + typedef unsigned char uchar; + typedef unsigned short ushort; + typedef signed int hpos; // pointers into heap + typedef signed int hval; // values in heap + typedef hval href; // values are typically references + struct hList { + ushort cnt; + ushort max; + hpos pos; + }; + + class GeomAttr { + public: + GeomAttr() { name = ""; buf = 0; stride = 0; offset = 0; } + std::string name; + ushort buf; + ushort stride; + ushort offset; + }; + + class GeomBuf { + public: + GeomBuf() { dtype = 0; num = 0; max = 0; stride = 0; data = 0x0; } + uchar dtype; + hval num; + hval max; + long size; + ushort stride; + char* data; + }; + + class GeomX { + public: + GeomX (); + + // virtual objType GetType () { return 'geom'; } + + // Basic geometry setup + void FreeBuffers (); + void ClearAttributes (); + void AddHeap ( int max ); + int CopyBuffer ( uchar bdest, uchar bsrc, GeomX& src ); + void CopyBuffers ( GeomX& src ); + void CopyAttributes ( GeomX& src ); + void CopyHeap ( GeomX& src ); + void ResetBuffer ( uchar b, int n ); + void ResetHeap (); + int AddBuffer ( uchar typ, ushort stride, int max ); + int AddAttribute ( uchar b, std::string name, ushort stride ); + int AddAttribute ( uchar b, std::string name, ushort stride, bool bExtend ); + int GetAttribute ( std::string name ); + int GetAttrOffset ( std::string name ); + int NumElem ( uchar b ) { if ( b==BUF_UNDEF) return 0; else return mBuf[b].num; } + int MaxElem ( uchar b ) { if ( b==BUF_UNDEF) return 0; else return mBuf[b].max; } + int GetStride ( uchar b ) { return mBuf[b].stride; } + char* GetElem ( uchar b, int n ) { return mBuf[b].data + n*mBuf[b].stride; } + char* RandomElem ( uchar b, href& ndx ); + char* AddElem ( uchar b, href& pos ); + int AddElem ( uchar b, char* data ); + bool DelElem ( uchar b, int n ); + char* GetStart ( uchar b ) { return mBuf[b].data; } + char* GetEnd ( uchar b ) { return mBuf[b].data + mBuf[b].num*mBuf[b].stride; } + GeomBuf* GetBuffer ( uchar b ) { return &mBuf[b]; } + GeomAttr* GetAttribute ( int n ) { return &mAttribute[n]; } + int GetNumBuf () { return (int) mBuf.size(); } + int GetNumAttr () { return (int) mAttribute.size(); } + hval* GetHeap ( hpos& num, hpos& max, hpos& free ); + + int GetSize (); + + /*int AddRef ( int b, int n, int ref, ushort listpos ); + int AddRef ( int b, int n, int ref, bool bUseHeap, ushort listpos, ushort width );*/ + void ClearRefs ( hList& list ); + hval AddRef ( hval r, hList& list, hval delta ); + hpos HeapAlloc ( ushort size, ushort& ret ); + hpos HeapExpand ( ushort size, ushort& ret ); + void HeapAddFree ( hpos pos, int size ); + + + protected: + std::vector< GeomBuf > mBuf; + std::vector< GeomAttr > mAttribute; + + hpos mHeapNum; + hpos mHeapMax; + hpos mHeapFree; + hval* mHeap; + }; + +#endif diff --git a/Extras/sph/common/gl_helper.cpp b/Extras/sph/common/gl_helper.cpp new file mode 100644 index 0000000..dce10d1 --- /dev/null +++ b/Extras/sph/common/gl_helper.cpp @@ -0,0 +1,402 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 "common_defs.h" +#include "gl_helper.h" + +#include + + +// Shadow Light +float light_proj[16]; +float light_x, light_y, light_z; +float light_tox, light_toy, light_toz; +float light_mfov; + +// Fonts +void *font = GLUT_BITMAP_8_BY_13; +void *fonts[] = {GLUT_BITMAP_9_BY_15, + GLUT_BITMAP_TIMES_ROMAN_10, + GLUT_BITMAP_TIMES_ROMAN_24}; +// Timing +mint::Time tm_last; +int tm_cnt; +float tm_fps; + +GLuint glSphere = 65535; +float glRadius = 0.0; + +void setSphereRadius ( float r ) +{ + if ( glRadius == r ) return; + glRadius = r; + + // GL sphere + if ( glSphere != 65535 ) glDeleteLists ( glSphere, 1 ); + glSphere = glGenLists ( 1 ); + float x, y, z, x1, y1, z1; + glNewList ( glSphere, GL_COMPILE ); + glBegin ( GL_TRIANGLE_STRIP ); + for ( float tilt=-90; tilt <= 90; tilt += 10.0) { + for ( float ang=0; ang <= 360; ang += 30.0) { + x = sin ( ang*DEGtoRAD) * cos ( tilt*DEGtoRAD ); + y = cos ( ang*DEGtoRAD) * cos ( tilt*DEGtoRAD ); + z = sin ( tilt*DEGtoRAD ) ; + x1 = sin ( ang*DEGtoRAD) * cos ( (tilt+10.0)*DEGtoRAD ) ; + y1 = cos ( ang*DEGtoRAD) * cos ( (tilt+10.0)*DEGtoRAD ) ; + z1 = sin ( (tilt+10.0)*DEGtoRAD ); + glNormal3f ( x, y, z ); glVertex3f ( x*r, y*r, z*r ); + glNormal3f ( x1, y1, z1 ); glVertex3f ( x1*r, y1*r, z1*r ); + } + } + glEnd (); + glEndList (); +} + +void drawSphere () +{ + if ( glRadius == 0.0 ) setSphereRadius ( 1.0 ); + glCallList ( glSphere ); +} + +// Check if there have been any openGL problems +void checkOpenGL () +{ + GLenum errCode = glGetError(); + if (errCode != GL_NO_ERROR) { + const GLubyte* errString = gluErrorString(errCode); + fprintf( stderr, "OpenGL error: %s\n", errString ); + } +} + +void drawText ( int x, int y, char* msg) +{ + int len, i; + glRasterPos2f(x, y); + len = (int) strlen(msg); + for (i = 0; i < len; i++) + glutBitmapCharacter(font, msg[i]); +} + +void drawGrid () +{ + glColor3f ( 0.3, 0.3, 0.3 ); + glBegin ( GL_LINES ); + for (float x=-40; x<=40.0; x+=10.0 ) { + glVertex3f ( x, -40.0, 0 ); + glVertex3f ( x, 40.0, 0 ); + } + for (float y=-40; y<=40.0; y+=10.0 ) { + glVertex3f ( -40.0, y, 0 ); + glVertex3f ( 40.0, y, 0 ); + } + glEnd (); +} + +void measureFPS () +{ + // Measure FPS + mint::Time tm_elaps; + if ( ++tm_cnt > 5 ) { + tm_elaps.SetSystemTime ( ACC_NSEC ); // get current sytem time - accurate to 1 ns + tm_elaps = tm_elaps - tm_last; // get elapsed time from 5 frames ago + tm_fps = 5.0 * 1000.0 / tm_elaps.GetMSec (); // compute fps + tm_cnt = 0; // reset frame counter + tm_last.SetSystemTime ( ACC_NSEC ); + } +} + +void checkFrameBuffers () +{ + GLenum status; + status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + switch(status) { + case GL_FRAMEBUFFER_COMPLETE_EXT: printf ( "FBO complete\n" ); break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: printf ( "FBO format unsupported\n"); break; + default: printf ( "Unknown FBO error\n"); + } +} + +void disableShadows () + { + glDisable ( GL_TEXTURE_2D ); + + glActiveTextureARB( GL_TEXTURE1_ARB ); + glBindTexture ( GL_TEXTURE_2D, 0 ); + glDisable ( GL_TEXTURE_GEN_S ); + glDisable ( GL_TEXTURE_GEN_T ); + glDisable ( GL_TEXTURE_GEN_R ); + glDisable ( GL_TEXTURE_GEN_Q ); + + glActiveTextureARB( GL_TEXTURE2_ARB ); + glBindTexture ( GL_TEXTURE_2D, 0 ); + glDisable ( GL_TEXTURE_GEN_S ); + glDisable ( GL_TEXTURE_GEN_T ); + glDisable ( GL_TEXTURE_GEN_R ); + glDisable ( GL_TEXTURE_GEN_Q ); + } + +#ifdef USE_SHADOWS + // Materials & Textures + GLuint shadow1_id = 0; // display buffer shadows + GLuint shadow2_id = 0; // display buffer shadows + + // Frame buffer + GLuint frameBufferObject = 0; // frame buffer shadows + + void createFrameBuffer () + { + //Generate the frame buffer object + glGenFramebuffersEXT (1, &frameBufferObject); + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, frameBufferObject); // Turn on frame buffer object + glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, shadow1_id, 0); + glDrawBuffer (GL_NONE); // Set Draw & ReadBuffer to none since we're rendering depth only + glReadBuffer (GL_NONE); + checkFrameBuffers (); // Check completeness of frame buffer object (no need for stencil and depth attachement) + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); // Turn off frame buffer object + } + + void createShadowTextures () + { + // Create depth texture maps + glActiveTextureARB( GL_TEXTURE1_ARB ); + glGenTextures( 1, &shadow1_id ); + glBindTexture ( GL_TEXTURE_2D, shadow1_id ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + + //-- sets region outside shadow to 0 + //glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER_ARB ); + //glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER_ARB ); + + //-- sets region outside shadow to 1 (border edge color) + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D ( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, TEX_SIZE, TEX_SIZE, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0); + + glActiveTextureARB( GL_TEXTURE2_ARB ); + glGenTextures( 1, &shadow2_id ); + glBindTexture ( GL_TEXTURE_2D, shadow2_id ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + //glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER_ARB ); + //glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER_ARB ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D ( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, TEX_SIZE, TEX_SIZE, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0); + } + + void computeLightMatrix ( int n, int tx, int ty ) + { + int lnum = n; + // Construct projective texturing matrix + + // S - light bias matrix + glMatrixMode ( GL_MODELVIEW ); + glLoadIdentity (); + glTranslatef ( 0.5, 0.5, 0.5 ); + glScalef ( 0.5, 0.5, 0.5 ); + // Plight - light projection matrix + gluPerspective ( light_mfov*2.0, float(tx) / ty, LIGHT_NEAR, LIGHT_FAR ); + // L^-1 - light view inverse matrix + gluLookAt ( light_x, light_y, light_z, light_tox, light_toy, light_toz, 0, 0, 1); + glPushMatrix (); + glGetFloatv ( GL_MODELVIEW_MATRIX, light_proj ); + glPopMatrix (); + + } + + void renderDepthMap_Clear ( float wx, float wy ) + { + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, frameBufferObject); + glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, shadow1_id, 0); + glActiveTextureARB( GL_TEXTURE1_ARB ); // TEXTURE1 = shadow map stage + glViewport (1, 1, TEX_SIZE-2, TEX_SIZE-2); // Note: Avoid artifact cause by drawing into border pixels + glClear ( GL_DEPTH_BUFFER_BIT ); + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); + glViewport ( 0, 0, (GLsizei) wx, (GLsizei) wy ); + } + + void renderDepthMap_FrameBuffer ( int n, float wx, float wy ) + { + float vmat[16]; + + computeLightMatrix ( n, TEX_SIZE, TEX_SIZE ); + + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, frameBufferObject); + + if ( n == 0 ) { + glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, shadow1_id, 0); + } else { + glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, shadow2_id, 0); + } + + if ( n == 0 ) glActiveTextureARB( GL_TEXTURE1_ARB ); // TEXTURE1 = shadow map stage + else glActiveTextureARB( GL_TEXTURE2_ARB ); // TEXTURE2 = shadow map stage + + glViewport (1, 1, TEX_SIZE-2, TEX_SIZE-2); // Note: Avoid artifact cause by drawing into border pixels + glClear ( GL_DEPTH_BUFFER_BIT ); + glLoadIdentity(); + + // Plight - projection matrix of light + glMatrixMode ( GL_PROJECTION ); // Setup projection for depth-map rendering + glLoadIdentity (); + gluPerspective ( light_mfov*2.0, float(TEX_SIZE) / TEX_SIZE, LIGHT_NEAR, LIGHT_FAR ); + + // L^-1 - light view matrix (gluLookAt computes inverse) + glMatrixMode ( GL_MODELVIEW); // Setup view for depth-map rendering + glLoadIdentity (); + gluLookAt ( light_x, light_y, light_z, light_tox, light_toy, light_toz, 0, 0, 1); + glPushMatrix (); // Save view matrix for later + glGetFloatv ( GL_MODELVIEW_MATRIX, vmat ); + glPopMatrix (); + + glDisable ( GL_LIGHTING ); + glColor4f ( 1, 1, 1, 1 ); + glShadeModel (GL_FLAT); // No shading (faster) + + glEnable ( GL_CULL_FACE ); + glCullFace ( GL_FRONT ); + + glEnable ( GL_POLYGON_OFFSET_FILL ); + glPolygonOffset ( 50.0, 0.1 ); // Depth bias + + drawScene ( &vmat[0], false ); // Draw scene. + + glDisable ( GL_POLYGON_OFFSET_FILL ); + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); + glViewport ( 0, 0, (GLsizei) wx, (GLsizei) wy ); + + //glCullFace (GL_BACK); // Restore render states + //glBindTexture ( GL_TEXTURE_2D, 0); + } + + void renderShadowStage ( int n, float* vmat ) + { + GLfloat pos[4]; + GLfloat row[4]; + + computeLightMatrix ( n, TEX_SIZE, TEX_SIZE ); + if ( n == 0 ) { + glActiveTextureARB( GL_TEXTURE1_ARB ); // TEXTURE1 = shadow map stage #1 + } else { + glActiveTextureARB( GL_TEXTURE2_ARB ); // TEXTURE2 = shadow map stage #2 + } + glEnable ( GL_TEXTURE_2D ); + if ( n == 0 ) glBindTexture ( GL_TEXTURE_2D, shadow1_id ); + else glBindTexture ( GL_TEXTURE_2D, shadow2_id ); + + glMatrixMode( GL_MODELVIEW ); + glLoadMatrixf ( vmat ); + + row[0] = light_proj[0]; row[1] = light_proj[4]; row[2] = light_proj[8]; row[3] = light_proj[12]; + glTexGenfv(GL_S, GL_EYE_PLANE, &row[0] ); + row[0] = light_proj[1]; row[1] = light_proj[5]; row[2] = light_proj[9]; row[3] = light_proj[13]; + glTexGenfv(GL_T, GL_EYE_PLANE, &row[0] ); + row[0] = light_proj[2]; row[1] = light_proj[6]; row[2] = light_proj[10]; row[3] = light_proj[14]; + glTexGenfv(GL_R, GL_EYE_PLANE, &row[0] ); + row[0] = light_proj[3]; row[1] = light_proj[7]; row[2] = light_proj[11]; row[3] = light_proj[15]; + glTexGenfv(GL_Q, GL_EYE_PLANE, &row[0] ); + glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + glEnable(GL_TEXTURE_GEN_Q); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE ); + + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE ) ; + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE ) ; + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS ) ; + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT ) ; + + pos[0] = 0.20; + pos[1] = 0.20; + pos[2] = 0.20; + pos[3] = 0.20; + glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &pos[0] ); + } + + void renderShadows ( float* vmat ) + { + GLfloat pos[4]; + + renderShadowStage ( 0, vmat ); + // renderShadowStage ( 1, vmat ); + + glActiveTextureARB( GL_TEXTURE0_ARB ); // Render Tex 0 - Base render + glDisable ( GL_TEXTURE_GEN_S ); + glDisable ( GL_TEXTURE_GEN_T ); + glDisable ( GL_TEXTURE_GEN_R ); + glDisable ( GL_TEXTURE_GEN_Q ); + glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + glEnable ( GL_LIGHTING ); + glLightModeli (GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SEPARATE_SPECULAR_COLOR_EXT); + + glEnable ( GL_LIGHT0 ); + pos[0] = light_x; pos[1] = light_y; pos[2] = light_z; pos[3] = 1.0; + glLightfv ( GL_LIGHT0, GL_POSITION, &pos[0] ); + + /* glEnable ( GL_LIGHT1 ); + pos[0] = light[1].x; pos[1] = light[1].y; pos[2] = light[1].z; pos[3] = 1.0; + glLightfv ( GL_LIGHT1, GL_POSITION, &pos[0] );*/ + } + + + + void setShadowLight ( float fx, float fy, float fz, float tx, float ty, float tz, float fov ) + { + light_x = fx; + light_y = fy; + light_z = fz; + light_tox = tx; + light_toy = ty; + light_toz = tz; + light_mfov = fov; + } + + void setShadowLightColor ( float dr, float dg, float db, float sr, float sg, float sb ) + { + GLfloat amb[4] = {0.0,0.0,0.0,1}; + GLfloat dif[4]; + GLfloat spec[4]; + GLfloat pos[4] = {0.0,0.0,0.0, 100.0}; + + glEnable(GL_LIGHT0); + dif[0] = dr; dif[1] = dg; dif[2] = db; dif[3] = 1; + spec[0] = sr; spec[1] = sg; spec[2] = sb; spec[3] = 1; + glLightfv(GL_LIGHT0, GL_AMBIENT, &amb[0] ); + glLightfv(GL_LIGHT0, GL_DIFFUSE, &dif[0] ); + glLightfv(GL_LIGHT0, GL_SPECULAR, &spec[0] ); + } + +#endif diff --git a/Extras/sph/common/gl_helper.h b/Extras/sph/common/gl_helper.h new file mode 100644 index 0000000..ccf402e --- /dev/null +++ b/Extras/sph/common/gl_helper.h @@ -0,0 +1,89 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 GL_HELPER + #define GL_HELPER + + #include "common_defs.h" + + #include + #include + + #ifdef _MSC_VER // Windows + #ifdef USE_SHADOWS + #include + #include + #endif + #include + #else // Linux + #ifdef USE_SHADOWS + #include "GLee.h" + #endif + #include + #include + #endif + + #include "image.h" + #include "mtime.h" + + extern void checkOpenGL (); + extern void drawText ( int x, int y, char* msg); + extern void drawGrid (); + extern void measureFPS (); + + extern mint::Time tm_last; + extern int tm_cnt; + extern float tm_fps; + + + extern void disableShadows (); + extern void checkFrameBuffers (); + + extern GLuint glSphere; + extern float glRadius; + extern void setSphereRadius ( float f ); + extern void drawSphere (); + + #ifdef USE_SHADOWS + extern void setShadowLight ( float fx, float fy, float fz, float tx, float ty, float tz, float fov ); + extern void setShadowLightColor ( float dr, float dg, float db, float sr, float sg, float sb ); + + extern void createFrameBuffer (); + extern void createShadowTextures (); + extern void computeLightMatrix ( int n, int tx, int ty ); + extern void renderDepthMap_Clear ( float wx, float wy ); + extern void renderDepthMap_FrameBuffer ( int n, float wx, float wy ); + extern void renderShadowStage ( int n, float* vmat ); + extern void renderShadows ( float* vmat ); + extern void drawScene ( float* view_mat, bool bShaders ); // provided by user + + extern float light_proj[16]; + extern float light_x, light_y, light_z; + extern float light_tox, light_toy, light_toz; + extern float light_mfov; + + extern GLuint shadow1_id; + extern GLuint shadow2_id; + #endif + + +#endif \ No newline at end of file diff --git a/Extras/sph/common/glext.h b/Extras/sph/common/glext.h new file mode 100644 index 0000000..7a92b57 --- /dev/null +++ b/Extras/sph/common/glext.h @@ -0,0 +1,7139 @@ +#ifndef __glext_h_ +#define __glext_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + + Copyright NVIDIA Corporation 2006 + + TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED + *AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS + OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL + NVIDIA OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR + CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR + LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, + OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE + THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + DAMAGES. + +******************************************************************************/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2004 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +*/ + +#ifndef GLAPIENTRY +# ifdef _WIN32 +# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) /* Mimic */ +# define GLAPIENTRY __stdcall +# else +# define GLAPIENTRY +# endif +# else +# define GLAPIENTRY +# endif +#endif + +#ifndef GLAPI +# define GLAPI extern +#endif + +#ifndef GLAPIENTRYP +# define GLAPIENTRYP GLAPIENTRY * +#endif + +/*************************************************************/ + +/* Header file version number, required by OpenGL ABI for Linux */ +/* glext.h last updated 2005/06/06 */ +/* Current version at http://oss.sgi.com/projects/ogl-sample/registry/ */ +#define GL_GLEXT_VERSION 28 + +#ifndef GL_VERSION_1_2 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_RESCALE_NORMAL 0x803A +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 +#define GL_SINGLE_COLOR 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR 0x81FA +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#endif + +#ifndef GL_ARB_imaging +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 +#define GL_FUNC_ADD 0x8006 +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_BLEND_EQUATION 0x8009 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_CONVOLUTION_1D 0x8010 +#define GL_CONVOLUTION_2D 0x8011 +#define GL_SEPARABLE_2D 0x8012 +#define GL_CONVOLUTION_BORDER_MODE 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS 0x8015 +#define GL_REDUCE 0x8016 +#define GL_CONVOLUTION_FORMAT 0x8017 +#define GL_CONVOLUTION_WIDTH 0x8018 +#define GL_CONVOLUTION_HEIGHT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 +#define GL_HISTOGRAM 0x8024 +#define GL_PROXY_HISTOGRAM 0x8025 +#define GL_HISTOGRAM_WIDTH 0x8026 +#define GL_HISTOGRAM_FORMAT 0x8027 +#define GL_HISTOGRAM_RED_SIZE 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C +#define GL_HISTOGRAM_SINK 0x802D +#define GL_MINMAX 0x802E +#define GL_MINMAX_FORMAT 0x802F +#define GL_MINMAX_SINK 0x8030 +#define GL_TABLE_TOO_LARGE 0x8031 +#define GL_COLOR_MATRIX 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB +#define GL_COLOR_TABLE 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 +#define GL_PROXY_COLOR_TABLE 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 +#define GL_COLOR_TABLE_SCALE 0x80D6 +#define GL_COLOR_TABLE_BIAS 0x80D7 +#define GL_COLOR_TABLE_FORMAT 0x80D8 +#define GL_COLOR_TABLE_WIDTH 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF +#define GL_CONSTANT_BORDER 0x8151 +#define GL_REPLICATE_BORDER 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR 0x8154 +#endif + +#ifndef GL_VERSION_1_3 +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 +#define GL_MAX_TEXTURE_UNITS 0x84E2 +#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_MULTISAMPLE_BIT 0x20000000 +#define GL_NORMAL_MAP 0x8511 +#define GL_REFLECTION_MAP 0x8512 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_COMPRESSED_ALPHA 0x84E9 +#define GL_COMPRESSED_LUMINANCE 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB +#define GL_COMPRESSED_INTENSITY 0x84EC +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_COMBINE 0x8570 +#define GL_COMBINE_RGB 0x8571 +#define GL_COMBINE_ALPHA 0x8572 +#define GL_SOURCE0_RGB 0x8580 +#define GL_SOURCE1_RGB 0x8581 +#define GL_SOURCE2_RGB 0x8582 +#define GL_SOURCE0_ALPHA 0x8588 +#define GL_SOURCE1_ALPHA 0x8589 +#define GL_SOURCE2_ALPHA 0x858A +#define GL_OPERAND0_RGB 0x8590 +#define GL_OPERAND1_RGB 0x8591 +#define GL_OPERAND2_RGB 0x8592 +#define GL_OPERAND0_ALPHA 0x8598 +#define GL_OPERAND1_ALPHA 0x8599 +#define GL_OPERAND2_ALPHA 0x859A +#define GL_RGB_SCALE 0x8573 +#define GL_ADD_SIGNED 0x8574 +#define GL_INTERPOLATE 0x8575 +#define GL_SUBTRACT 0x84E7 +#define GL_CONSTANT 0x8576 +#define GL_PRIMARY_COLOR 0x8577 +#define GL_PREVIOUS 0x8578 +#define GL_DOT3_RGB 0x86AE +#define GL_DOT3_RGBA 0x86AF +#endif + +#ifndef GL_VERSION_1_4 +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_POINT_SIZE_MIN 0x8126 +#define GL_POINT_SIZE_MAX 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION 0x8129 +#define GL_GENERATE_MIPMAP 0x8191 +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_FOG_COORDINATE_SOURCE 0x8450 +#define GL_FOG_COORDINATE 0x8451 +#define GL_FRAGMENT_DEPTH 0x8452 +#define GL_CURRENT_FOG_COORDINATE 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456 +#define GL_FOG_COORDINATE_ARRAY 0x8457 +#define GL_COLOR_SUM 0x8458 +#define GL_CURRENT_SECONDARY_COLOR 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D +#define GL_SECONDARY_COLOR_ARRAY 0x845E +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_FILTER_CONTROL 0x8500 +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_DEPTH_TEXTURE_MODE 0x884B +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_COMPARE_R_TO_TEXTURE 0x884E +#endif + +#ifndef GL_VERSION_1_5 +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_SAMPLES_PASSED 0x8914 +#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE +#define GL_FOG_COORD GL_FOG_COORDINATE +#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE +#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE +#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE +#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER +#define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY +#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING +#define GL_SRC0_RGB GL_SOURCE0_RGB +#define GL_SRC1_RGB GL_SOURCE1_RGB +#define GL_SRC2_RGB GL_SOURCE2_RGB +#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA +#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA +#define GL_SRC2_ALPHA GL_SOURCE2_ALPHA +#endif + +#ifndef GL_VERSION_2_0 +#define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_POINT_SPRITE 0x8861 +#define GL_COORD_REPLACE 0x8862 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_MAX_TEXTURE_COORDS 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_SHADER_TYPE 0x8B4F +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_DELETE_STATUS 0x8B80 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#endif + +#ifndef GL_VERSION_2_1 +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB_ALPHA 0x8C42 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_SLUMINANCE_ALPHA 0x8C44 +#define GL_SLUMINANCE8_ALPHA8 0x8C45 +#define GL_SLUMINANCE 0x8C46 +#define GL_SLUMINANCE8 0x8C47 +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 +#define GL_COMPRESSED_SLUMINANCE 0x8C4A +#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F +#endif + +#ifndef GL_ARB_multitexture +#define GL_TEXTURE0_ARB 0x84C0 +#define GL_TEXTURE1_ARB 0x84C1 +#define GL_TEXTURE2_ARB 0x84C2 +#define GL_TEXTURE3_ARB 0x84C3 +#define GL_TEXTURE4_ARB 0x84C4 +#define GL_TEXTURE5_ARB 0x84C5 +#define GL_TEXTURE6_ARB 0x84C6 +#define GL_TEXTURE7_ARB 0x84C7 +#define GL_TEXTURE8_ARB 0x84C8 +#define GL_TEXTURE9_ARB 0x84C9 +#define GL_TEXTURE10_ARB 0x84CA +#define GL_TEXTURE11_ARB 0x84CB +#define GL_TEXTURE12_ARB 0x84CC +#define GL_TEXTURE13_ARB 0x84CD +#define GL_TEXTURE14_ARB 0x84CE +#define GL_TEXTURE15_ARB 0x84CF +#define GL_TEXTURE16_ARB 0x84D0 +#define GL_TEXTURE17_ARB 0x84D1 +#define GL_TEXTURE18_ARB 0x84D2 +#define GL_TEXTURE19_ARB 0x84D3 +#define GL_TEXTURE20_ARB 0x84D4 +#define GL_TEXTURE21_ARB 0x84D5 +#define GL_TEXTURE22_ARB 0x84D6 +#define GL_TEXTURE23_ARB 0x84D7 +#define GL_TEXTURE24_ARB 0x84D8 +#define GL_TEXTURE25_ARB 0x84D9 +#define GL_TEXTURE26_ARB 0x84DA +#define GL_TEXTURE27_ARB 0x84DB +#define GL_TEXTURE28_ARB 0x84DC +#define GL_TEXTURE29_ARB 0x84DD +#define GL_TEXTURE30_ARB 0x84DE +#define GL_TEXTURE31_ARB 0x84DF +#define GL_ACTIVE_TEXTURE_ARB 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 +#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 +#endif + +#ifndef GL_ARB_transpose_matrix +#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6 +#endif + +#ifndef GL_ARB_multisample +#define GL_MULTISAMPLE_ARB 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F +#define GL_SAMPLE_COVERAGE_ARB 0x80A0 +#define GL_SAMPLE_BUFFERS_ARB 0x80A8 +#define GL_SAMPLES_ARB 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB +#define GL_MULTISAMPLE_BIT_ARB 0x20000000 +#endif + +#ifndef GL_ARB_texture_env_add +#endif + +#ifndef GL_ARB_texture_cube_map +#define GL_NORMAL_MAP_ARB 0x8511 +#define GL_REFLECTION_MAP_ARB 0x8512 +#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C +#endif + +#ifndef GL_ARB_texture_compression +#define GL_COMPRESSED_ALPHA_ARB 0x84E9 +#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB +#define GL_COMPRESSED_INTENSITY_ARB 0x84EC +#define GL_COMPRESSED_RGB_ARB 0x84ED +#define GL_COMPRESSED_RGBA_ARB 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 +#define GL_TEXTURE_COMPRESSED_ARB 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 +#endif + +#ifndef GL_ARB_texture_border_clamp +#define GL_CLAMP_TO_BORDER_ARB 0x812D +#endif + +#ifndef GL_ARB_point_parameters +#define GL_POINT_SIZE_MIN_ARB 0x8126 +#define GL_POINT_SIZE_MAX_ARB 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129 +#endif + +#ifndef GL_ARB_vertex_blend +#define GL_MAX_VERTEX_UNITS_ARB 0x86A4 +#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5 +#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6 +#define GL_VERTEX_BLEND_ARB 0x86A7 +#define GL_CURRENT_WEIGHT_ARB 0x86A8 +#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9 +#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA +#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB +#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC +#define GL_WEIGHT_ARRAY_ARB 0x86AD +#define GL_MODELVIEW0_ARB 0x1700 +#define GL_MODELVIEW1_ARB 0x850A +#define GL_MODELVIEW2_ARB 0x8722 +#define GL_MODELVIEW3_ARB 0x8723 +#define GL_MODELVIEW4_ARB 0x8724 +#define GL_MODELVIEW5_ARB 0x8725 +#define GL_MODELVIEW6_ARB 0x8726 +#define GL_MODELVIEW7_ARB 0x8727 +#define GL_MODELVIEW8_ARB 0x8728 +#define GL_MODELVIEW9_ARB 0x8729 +#define GL_MODELVIEW10_ARB 0x872A +#define GL_MODELVIEW11_ARB 0x872B +#define GL_MODELVIEW12_ARB 0x872C +#define GL_MODELVIEW13_ARB 0x872D +#define GL_MODELVIEW14_ARB 0x872E +#define GL_MODELVIEW15_ARB 0x872F +#define GL_MODELVIEW16_ARB 0x8730 +#define GL_MODELVIEW17_ARB 0x8731 +#define GL_MODELVIEW18_ARB 0x8732 +#define GL_MODELVIEW19_ARB 0x8733 +#define GL_MODELVIEW20_ARB 0x8734 +#define GL_MODELVIEW21_ARB 0x8735 +#define GL_MODELVIEW22_ARB 0x8736 +#define GL_MODELVIEW23_ARB 0x8737 +#define GL_MODELVIEW24_ARB 0x8738 +#define GL_MODELVIEW25_ARB 0x8739 +#define GL_MODELVIEW26_ARB 0x873A +#define GL_MODELVIEW27_ARB 0x873B +#define GL_MODELVIEW28_ARB 0x873C +#define GL_MODELVIEW29_ARB 0x873D +#define GL_MODELVIEW30_ARB 0x873E +#define GL_MODELVIEW31_ARB 0x873F +#endif + +#ifndef GL_ARB_matrix_palette +#define GL_MATRIX_PALETTE_ARB 0x8840 +#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841 +#define GL_MAX_PALETTE_MATRICES_ARB 0x8842 +#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843 +#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844 +#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845 +#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846 +#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847 +#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848 +#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849 +#endif + +#ifndef GL_ARB_texture_env_combine +#define GL_COMBINE_ARB 0x8570 +#define GL_COMBINE_RGB_ARB 0x8571 +#define GL_COMBINE_ALPHA_ARB 0x8572 +#define GL_SOURCE0_RGB_ARB 0x8580 +#define GL_SOURCE1_RGB_ARB 0x8581 +#define GL_SOURCE2_RGB_ARB 0x8582 +#define GL_SOURCE0_ALPHA_ARB 0x8588 +#define GL_SOURCE1_ALPHA_ARB 0x8589 +#define GL_SOURCE2_ALPHA_ARB 0x858A +#define GL_OPERAND0_RGB_ARB 0x8590 +#define GL_OPERAND1_RGB_ARB 0x8591 +#define GL_OPERAND2_RGB_ARB 0x8592 +#define GL_OPERAND0_ALPHA_ARB 0x8598 +#define GL_OPERAND1_ALPHA_ARB 0x8599 +#define GL_OPERAND2_ALPHA_ARB 0x859A +#define GL_RGB_SCALE_ARB 0x8573 +#define GL_ADD_SIGNED_ARB 0x8574 +#define GL_INTERPOLATE_ARB 0x8575 +#define GL_SUBTRACT_ARB 0x84E7 +#define GL_CONSTANT_ARB 0x8576 +#define GL_PRIMARY_COLOR_ARB 0x8577 +#define GL_PREVIOUS_ARB 0x8578 +#endif + +#ifndef GL_ARB_texture_env_crossbar +#endif + +#ifndef GL_ARB_texture_env_dot3 +#define GL_DOT3_RGB_ARB 0x86AE +#define GL_DOT3_RGBA_ARB 0x86AF +#endif + +#ifndef GL_ARB_texture_mirrored_repeat +#define GL_MIRRORED_REPEAT_ARB 0x8370 +#endif + +#ifndef GL_ARB_depth_texture +#define GL_DEPTH_COMPONENT16_ARB 0x81A5 +#define GL_DEPTH_COMPONENT24_ARB 0x81A6 +#define GL_DEPTH_COMPONENT32_ARB 0x81A7 +#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A +#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B +#endif + +#ifndef GL_ARB_shadow +#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C +#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D +#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E +#endif + +#ifndef GL_ARB_shadow_ambient +#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF +#endif + +#ifndef GL_ARB_window_pos +#endif + +#ifndef GL_ARB_vertex_program +#define GL_COLOR_SUM_ARB 0x8458 +#define GL_VERTEX_PROGRAM_ARB 0x8620 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 +#define GL_PROGRAM_LENGTH_ARB 0x8627 +#define GL_PROGRAM_STRING_ARB 0x8628 +#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E +#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F +#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 +#define GL_CURRENT_MATRIX_ARB 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 +#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B +#define GL_PROGRAM_BINDING_ARB 0x8677 +#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A +#define GL_PROGRAM_ERROR_STRING_ARB 0x8874 +#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 +#define GL_PROGRAM_FORMAT_ARB 0x8876 +#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0 +#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 +#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 +#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 +#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4 +#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 +#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 +#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 +#define GL_PROGRAM_PARAMETERS_ARB 0x88A8 +#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9 +#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA +#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB +#define GL_PROGRAM_ATTRIBS_ARB 0x88AC +#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD +#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE +#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF +#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 +#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 +#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 +#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 +#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 +#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 +#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 +#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 +#define GL_MATRIX0_ARB 0x88C0 +#define GL_MATRIX1_ARB 0x88C1 +#define GL_MATRIX2_ARB 0x88C2 +#define GL_MATRIX3_ARB 0x88C3 +#define GL_MATRIX4_ARB 0x88C4 +#define GL_MATRIX5_ARB 0x88C5 +#define GL_MATRIX6_ARB 0x88C6 +#define GL_MATRIX7_ARB 0x88C7 +#define GL_MATRIX8_ARB 0x88C8 +#define GL_MATRIX9_ARB 0x88C9 +#define GL_MATRIX10_ARB 0x88CA +#define GL_MATRIX11_ARB 0x88CB +#define GL_MATRIX12_ARB 0x88CC +#define GL_MATRIX13_ARB 0x88CD +#define GL_MATRIX14_ARB 0x88CE +#define GL_MATRIX15_ARB 0x88CF +#define GL_MATRIX16_ARB 0x88D0 +#define GL_MATRIX17_ARB 0x88D1 +#define GL_MATRIX18_ARB 0x88D2 +#define GL_MATRIX19_ARB 0x88D3 +#define GL_MATRIX20_ARB 0x88D4 +#define GL_MATRIX21_ARB 0x88D5 +#define GL_MATRIX22_ARB 0x88D6 +#define GL_MATRIX23_ARB 0x88D7 +#define GL_MATRIX24_ARB 0x88D8 +#define GL_MATRIX25_ARB 0x88D9 +#define GL_MATRIX26_ARB 0x88DA +#define GL_MATRIX27_ARB 0x88DB +#define GL_MATRIX28_ARB 0x88DC +#define GL_MATRIX29_ARB 0x88DD +#define GL_MATRIX30_ARB 0x88DE +#define GL_MATRIX31_ARB 0x88DF +#endif + +#ifndef GL_ARB_fragment_program +#define GL_FRAGMENT_PROGRAM_ARB 0x8804 +#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805 +#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806 +#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807 +#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808 +#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809 +#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A +#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B +#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C +#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D +#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E +#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F +#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810 +#define GL_MAX_TEXTURE_COORDS_ARB 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 +#endif + +#ifndef GL_ARB_vertex_buffer_object +#define GL_BUFFER_SIZE_ARB 0x8764 +#define GL_BUFFER_USAGE_ARB 0x8765 +#define GL_ARRAY_BUFFER_ARB 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 +#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F +#define GL_READ_ONLY_ARB 0x88B8 +#define GL_WRITE_ONLY_ARB 0x88B9 +#define GL_READ_WRITE_ARB 0x88BA +#define GL_BUFFER_ACCESS_ARB 0x88BB +#define GL_BUFFER_MAPPED_ARB 0x88BC +#define GL_BUFFER_MAP_POINTER_ARB 0x88BD +#define GL_STREAM_DRAW_ARB 0x88E0 +#define GL_STREAM_READ_ARB 0x88E1 +#define GL_STREAM_COPY_ARB 0x88E2 +#define GL_STATIC_DRAW_ARB 0x88E4 +#define GL_STATIC_READ_ARB 0x88E5 +#define GL_STATIC_COPY_ARB 0x88E6 +#define GL_DYNAMIC_DRAW_ARB 0x88E8 +#define GL_DYNAMIC_READ_ARB 0x88E9 +#define GL_DYNAMIC_COPY_ARB 0x88EA +#endif + +#ifndef GL_ARB_occlusion_query +#define GL_QUERY_COUNTER_BITS_ARB 0x8864 +#define GL_CURRENT_QUERY_ARB 0x8865 +#define GL_QUERY_RESULT_ARB 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 +#define GL_SAMPLES_PASSED_ARB 0x8914 +#endif + +#ifndef GL_ARB_shader_objects +#define GL_PROGRAM_OBJECT_ARB 0x8B40 +#define GL_SHADER_OBJECT_ARB 0x8B48 +#define GL_OBJECT_TYPE_ARB 0x8B4E +#define GL_OBJECT_SUBTYPE_ARB 0x8B4F +#define GL_FLOAT_VEC2_ARB 0x8B50 +#define GL_FLOAT_VEC3_ARB 0x8B51 +#define GL_FLOAT_VEC4_ARB 0x8B52 +#define GL_INT_VEC2_ARB 0x8B53 +#define GL_INT_VEC3_ARB 0x8B54 +#define GL_INT_VEC4_ARB 0x8B55 +#define GL_BOOL_ARB 0x8B56 +#define GL_BOOL_VEC2_ARB 0x8B57 +#define GL_BOOL_VEC3_ARB 0x8B58 +#define GL_BOOL_VEC4_ARB 0x8B59 +#define GL_FLOAT_MAT2_ARB 0x8B5A +#define GL_FLOAT_MAT3_ARB 0x8B5B +#define GL_FLOAT_MAT4_ARB 0x8B5C +#define GL_SAMPLER_1D_ARB 0x8B5D +#define GL_SAMPLER_2D_ARB 0x8B5E +#define GL_SAMPLER_3D_ARB 0x8B5F +#define GL_SAMPLER_CUBE_ARB 0x8B60 +#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61 +#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62 +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 +#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80 +#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 +#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 +#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83 +#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 +#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85 +#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86 +#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87 +#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88 +#endif + +#ifndef GL_ARB_vertex_shader +#define GL_VERTEX_SHADER_ARB 0x8B31 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A +#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D +#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89 +#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A +#endif + +#ifndef GL_ARB_fragment_shader +#define GL_FRAGMENT_SHADER_ARB 0x8B30 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B +#endif + +#ifndef GL_ARB_shading_language_100 +#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C +#endif + +#ifndef GL_ARB_texture_non_power_of_two +#endif + +#ifndef GL_ARB_point_sprite +#define GL_POINT_SPRITE_ARB 0x8861 +#define GL_COORD_REPLACE_ARB 0x8862 +#endif + +#ifndef GL_ARB_fragment_program_shadow +#endif + +#ifndef GL_ARB_draw_buffers +#define GL_MAX_DRAW_BUFFERS_ARB 0x8824 +#define GL_DRAW_BUFFER0_ARB 0x8825 +#define GL_DRAW_BUFFER1_ARB 0x8826 +#define GL_DRAW_BUFFER2_ARB 0x8827 +#define GL_DRAW_BUFFER3_ARB 0x8828 +#define GL_DRAW_BUFFER4_ARB 0x8829 +#define GL_DRAW_BUFFER5_ARB 0x882A +#define GL_DRAW_BUFFER6_ARB 0x882B +#define GL_DRAW_BUFFER7_ARB 0x882C +#define GL_DRAW_BUFFER8_ARB 0x882D +#define GL_DRAW_BUFFER9_ARB 0x882E +#define GL_DRAW_BUFFER10_ARB 0x882F +#define GL_DRAW_BUFFER11_ARB 0x8830 +#define GL_DRAW_BUFFER12_ARB 0x8831 +#define GL_DRAW_BUFFER13_ARB 0x8832 +#define GL_DRAW_BUFFER14_ARB 0x8833 +#define GL_DRAW_BUFFER15_ARB 0x8834 +#endif + +#ifndef GL_ARB_texture_rectangle +#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 +#endif + +#ifndef GL_ARB_color_buffer_float +#define GL_RGBA_FLOAT_MODE_ARB 0x8820 +#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A +#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B +#define GL_CLAMP_READ_COLOR_ARB 0x891C +#define GL_FIXED_ONLY_ARB 0x891D +#endif + +#ifndef GL_ARB_half_float_pixel +#define GL_HALF_FLOAT_ARB 0x140B +#endif + +#ifndef GL_ARB_texture_float +#define GL_TEXTURE_RED_TYPE_ARB 0x8C10 +#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11 +#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13 +#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14 +#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15 +#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16 +#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17 +#define GL_RGBA32F_ARB 0x8814 +#define GL_RGB32F_ARB 0x8815 +#define GL_ALPHA32F_ARB 0x8816 +#define GL_INTENSITY32F_ARB 0x8817 +#define GL_LUMINANCE32F_ARB 0x8818 +#define GL_LUMINANCE_ALPHA32F_ARB 0x8819 +#define GL_RGBA16F_ARB 0x881A +#define GL_RGB16F_ARB 0x881B +#define GL_ALPHA16F_ARB 0x881C +#define GL_INTENSITY16F_ARB 0x881D +#define GL_LUMINANCE16F_ARB 0x881E +#define GL_LUMINANCE_ALPHA16F_ARB 0x881F +#endif + +#ifndef GL_ARB_pixel_buffer_object +#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF +#endif + +#ifndef GL_EXT_abgr +#define GL_ABGR_EXT 0x8000 +#endif + +#ifndef GL_EXT_blend_color +#define GL_CONSTANT_COLOR_EXT 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002 +#define GL_CONSTANT_ALPHA_EXT 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004 +#define GL_BLEND_COLOR_EXT 0x8005 +#endif + +#ifndef GL_EXT_polygon_offset +#define GL_POLYGON_OFFSET_EXT 0x8037 +#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038 +#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039 +#endif + +#ifndef GL_EXT_texture +#define GL_ALPHA4_EXT 0x803B +#define GL_ALPHA8_EXT 0x803C +#define GL_ALPHA12_EXT 0x803D +#define GL_ALPHA16_EXT 0x803E +#define GL_LUMINANCE4_EXT 0x803F +#define GL_LUMINANCE8_EXT 0x8040 +#define GL_LUMINANCE12_EXT 0x8041 +#define GL_LUMINANCE16_EXT 0x8042 +#define GL_LUMINANCE4_ALPHA4_EXT 0x8043 +#define GL_LUMINANCE6_ALPHA2_EXT 0x8044 +#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +#define GL_LUMINANCE12_ALPHA4_EXT 0x8046 +#define GL_LUMINANCE12_ALPHA12_EXT 0x8047 +#define GL_LUMINANCE16_ALPHA16_EXT 0x8048 +#define GL_INTENSITY_EXT 0x8049 +#define GL_INTENSITY4_EXT 0x804A +#define GL_INTENSITY8_EXT 0x804B +#define GL_INTENSITY12_EXT 0x804C +#define GL_INTENSITY16_EXT 0x804D +#define GL_RGB2_EXT 0x804E +#define GL_RGB4_EXT 0x804F +#define GL_RGB5_EXT 0x8050 +#define GL_RGB8_EXT 0x8051 +#define GL_RGB10_EXT 0x8052 +#define GL_RGB12_EXT 0x8053 +#define GL_RGB16_EXT 0x8054 +#define GL_RGBA2_EXT 0x8055 +#define GL_RGBA4_EXT 0x8056 +#define GL_RGB5_A1_EXT 0x8057 +#define GL_RGBA8_EXT 0x8058 +#define GL_RGB10_A2_EXT 0x8059 +#define GL_RGBA12_EXT 0x805A +#define GL_RGBA16_EXT 0x805B +#define GL_TEXTURE_RED_SIZE_EXT 0x805C +#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D +#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E +#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061 +#define GL_REPLACE_EXT 0x8062 +#define GL_PROXY_TEXTURE_1D_EXT 0x8063 +#define GL_PROXY_TEXTURE_2D_EXT 0x8064 +#define GL_TEXTURE_TOO_LARGE_EXT 0x8065 +#endif + +#ifndef GL_EXT_texture3D +#define GL_PACK_SKIP_IMAGES_EXT 0x806B +#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C +#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D +#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E +#define GL_TEXTURE_3D_EXT 0x806F +#define GL_PROXY_TEXTURE_3D_EXT 0x8070 +#define GL_TEXTURE_DEPTH_EXT 0x8071 +#define GL_TEXTURE_WRAP_R_EXT 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 +#endif + +#ifndef GL_SGIS_texture_filter4 +#define GL_FILTER4_SGIS 0x8146 +#define GL_TEXTURE_FILTER4_SIZE_SGIS 0x8147 +#endif + +#ifndef GL_EXT_subtexture +#endif + +#ifndef GL_EXT_copy_texture +#endif + +#ifndef GL_EXT_histogram +#define GL_HISTOGRAM_EXT 0x8024 +#define GL_PROXY_HISTOGRAM_EXT 0x8025 +#define GL_HISTOGRAM_WIDTH_EXT 0x8026 +#define GL_HISTOGRAM_FORMAT_EXT 0x8027 +#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C +#define GL_HISTOGRAM_SINK_EXT 0x802D +#define GL_MINMAX_EXT 0x802E +#define GL_MINMAX_FORMAT_EXT 0x802F +#define GL_MINMAX_SINK_EXT 0x8030 +#define GL_TABLE_TOO_LARGE_EXT 0x8031 +#endif + +#ifndef GL_EXT_convolution +#define GL_CONVOLUTION_1D_EXT 0x8010 +#define GL_CONVOLUTION_2D_EXT 0x8011 +#define GL_SEPARABLE_2D_EXT 0x8012 +#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015 +#define GL_REDUCE_EXT 0x8016 +#define GL_CONVOLUTION_FORMAT_EXT 0x8017 +#define GL_CONVOLUTION_WIDTH_EXT 0x8018 +#define GL_CONVOLUTION_HEIGHT_EXT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 +#endif + +#ifndef GL_SGI_color_matrix +#define GL_COLOR_MATRIX_SGI 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB +#endif + +#ifndef GL_SGI_color_table +#define GL_COLOR_TABLE_SGI 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2 +#define GL_PROXY_COLOR_TABLE_SGI 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5 +#define GL_COLOR_TABLE_SCALE_SGI 0x80D6 +#define GL_COLOR_TABLE_BIAS_SGI 0x80D7 +#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8 +#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF +#endif + +#ifndef GL_SGIS_pixel_texture +#define GL_PIXEL_TEXTURE_SGIS 0x8353 +#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354 +#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355 +#define GL_PIXEL_GROUP_COLOR_SGIS 0x8356 +#endif + +#ifndef GL_SGIX_pixel_texture +#define GL_PIXEL_TEX_GEN_SGIX 0x8139 +#define GL_PIXEL_TEX_GEN_MODE_SGIX 0x832B +#endif + +#ifndef GL_SGIS_texture4D +#define GL_PACK_SKIP_VOLUMES_SGIS 0x8130 +#define GL_PACK_IMAGE_DEPTH_SGIS 0x8131 +#define GL_UNPACK_SKIP_VOLUMES_SGIS 0x8132 +#define GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133 +#define GL_TEXTURE_4D_SGIS 0x8134 +#define GL_PROXY_TEXTURE_4D_SGIS 0x8135 +#define GL_TEXTURE_4DSIZE_SGIS 0x8136 +#define GL_TEXTURE_WRAP_Q_SGIS 0x8137 +#define GL_MAX_4D_TEXTURE_SIZE_SGIS 0x8138 +#define GL_TEXTURE_4D_BINDING_SGIS 0x814F +#endif + +#ifndef GL_SGI_texture_color_table +#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC +#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD +#endif + +#ifndef GL_EXT_cmyka +#define GL_CMYK_EXT 0x800C +#define GL_CMYKA_EXT 0x800D +#define GL_PACK_CMYK_HINT_EXT 0x800E +#define GL_UNPACK_CMYK_HINT_EXT 0x800F +#endif + +#ifndef GL_EXT_texture_object +#define GL_TEXTURE_PRIORITY_EXT 0x8066 +#define GL_TEXTURE_RESIDENT_EXT 0x8067 +#define GL_TEXTURE_1D_BINDING_EXT 0x8068 +#define GL_TEXTURE_2D_BINDING_EXT 0x8069 +#define GL_TEXTURE_3D_BINDING_EXT 0x806A +#endif + +#ifndef GL_SGIS_detail_texture +#define GL_DETAIL_TEXTURE_2D_SGIS 0x8095 +#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096 +#define GL_LINEAR_DETAIL_SGIS 0x8097 +#define GL_LINEAR_DETAIL_ALPHA_SGIS 0x8098 +#define GL_LINEAR_DETAIL_COLOR_SGIS 0x8099 +#define GL_DETAIL_TEXTURE_LEVEL_SGIS 0x809A +#define GL_DETAIL_TEXTURE_MODE_SGIS 0x809B +#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C +#endif + +#ifndef GL_SGIS_sharpen_texture +#define GL_LINEAR_SHARPEN_SGIS 0x80AD +#define GL_LINEAR_SHARPEN_ALPHA_SGIS 0x80AE +#define GL_LINEAR_SHARPEN_COLOR_SGIS 0x80AF +#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0 +#endif + +#ifndef GL_EXT_packed_pixels +#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036 +#endif + +#ifndef GL_SGIS_texture_lod +#define GL_TEXTURE_MIN_LOD_SGIS 0x813A +#define GL_TEXTURE_MAX_LOD_SGIS 0x813B +#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C +#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D +#endif + +#ifndef GL_SGIS_multisample +#define GL_MULTISAMPLE_SGIS 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F +#define GL_SAMPLE_MASK_SGIS 0x80A0 +#define GL_1PASS_SGIS 0x80A1 +#define GL_2PASS_0_SGIS 0x80A2 +#define GL_2PASS_1_SGIS 0x80A3 +#define GL_4PASS_0_SGIS 0x80A4 +#define GL_4PASS_1_SGIS 0x80A5 +#define GL_4PASS_2_SGIS 0x80A6 +#define GL_4PASS_3_SGIS 0x80A7 +#define GL_SAMPLE_BUFFERS_SGIS 0x80A8 +#define GL_SAMPLES_SGIS 0x80A9 +#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA +#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB +#define GL_SAMPLE_PATTERN_SGIS 0x80AC +#endif + +#ifndef GL_EXT_rescale_normal +#define GL_RESCALE_NORMAL_EXT 0x803A +#endif + +#ifndef GL_EXT_vertex_array +#define GL_VERTEX_ARRAY_EXT 0x8074 +#define GL_NORMAL_ARRAY_EXT 0x8075 +#define GL_COLOR_ARRAY_EXT 0x8076 +#define GL_INDEX_ARRAY_EXT 0x8077 +#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078 +#define GL_EDGE_FLAG_ARRAY_EXT 0x8079 +#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A +#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B +#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C +#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D +#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E +#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F +#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080 +#define GL_COLOR_ARRAY_SIZE_EXT 0x8081 +#define GL_COLOR_ARRAY_TYPE_EXT 0x8082 +#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083 +#define GL_COLOR_ARRAY_COUNT_EXT 0x8084 +#define GL_INDEX_ARRAY_TYPE_EXT 0x8085 +#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086 +#define GL_INDEX_ARRAY_COUNT_EXT 0x8087 +#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A +#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B +#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C +#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D +#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E +#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F +#define GL_COLOR_ARRAY_POINTER_EXT 0x8090 +#define GL_INDEX_ARRAY_POINTER_EXT 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 +#endif + +#ifndef GL_EXT_misc_attribute +#endif + +#ifndef GL_SGIS_generate_mipmap +#define GL_GENERATE_MIPMAP_SGIS 0x8191 +#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 +#endif + +#ifndef GL_SGIX_clipmap +#define GL_LINEAR_CLIPMAP_LINEAR_SGIX 0x8170 +#define GL_TEXTURE_CLIPMAP_CENTER_SGIX 0x8171 +#define GL_TEXTURE_CLIPMAP_FRAME_SGIX 0x8172 +#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX 0x8173 +#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174 +#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175 +#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX 0x8176 +#define GL_MAX_CLIPMAP_DEPTH_SGIX 0x8177 +#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178 +#define GL_NEAREST_CLIPMAP_NEAREST_SGIX 0x844D +#define GL_NEAREST_CLIPMAP_LINEAR_SGIX 0x844E +#define GL_LINEAR_CLIPMAP_NEAREST_SGIX 0x844F +#endif + +#ifndef GL_SGIX_shadow +#define GL_TEXTURE_COMPARE_SGIX 0x819A +#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B +#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C +#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D +#endif + +#ifndef GL_SGIS_texture_edge_clamp +#define GL_CLAMP_TO_EDGE_SGIS 0x812F +#endif + +#ifndef GL_SGIS_texture_border_clamp +#define GL_CLAMP_TO_BORDER_SGIS 0x812D +#endif + +#ifndef GL_EXT_blend_minmax +#define GL_FUNC_ADD_EXT 0x8006 +#define GL_MIN_EXT 0x8007 +#define GL_MAX_EXT 0x8008 +#define GL_BLEND_EQUATION_EXT 0x8009 +#endif + +#ifndef GL_EXT_blend_subtract +#define GL_FUNC_SUBTRACT_EXT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B +#endif + +#ifndef GL_EXT_blend_logic_op +#endif + +#ifndef GL_SGIX_interlace +#define GL_INTERLACE_SGIX 0x8094 +#endif + +#ifndef GL_SGIX_pixel_tiles +#define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E +#define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F +#define GL_PIXEL_TILE_WIDTH_SGIX 0x8140 +#define GL_PIXEL_TILE_HEIGHT_SGIX 0x8141 +#define GL_PIXEL_TILE_GRID_WIDTH_SGIX 0x8142 +#define GL_PIXEL_TILE_GRID_HEIGHT_SGIX 0x8143 +#define GL_PIXEL_TILE_GRID_DEPTH_SGIX 0x8144 +#define GL_PIXEL_TILE_CACHE_SIZE_SGIX 0x8145 +#endif + +#ifndef GL_SGIS_texture_select +#define GL_DUAL_ALPHA4_SGIS 0x8110 +#define GL_DUAL_ALPHA8_SGIS 0x8111 +#define GL_DUAL_ALPHA12_SGIS 0x8112 +#define GL_DUAL_ALPHA16_SGIS 0x8113 +#define GL_DUAL_LUMINANCE4_SGIS 0x8114 +#define GL_DUAL_LUMINANCE8_SGIS 0x8115 +#define GL_DUAL_LUMINANCE12_SGIS 0x8116 +#define GL_DUAL_LUMINANCE16_SGIS 0x8117 +#define GL_DUAL_INTENSITY4_SGIS 0x8118 +#define GL_DUAL_INTENSITY8_SGIS 0x8119 +#define GL_DUAL_INTENSITY12_SGIS 0x811A +#define GL_DUAL_INTENSITY16_SGIS 0x811B +#define GL_DUAL_LUMINANCE_ALPHA4_SGIS 0x811C +#define GL_DUAL_LUMINANCE_ALPHA8_SGIS 0x811D +#define GL_QUAD_ALPHA4_SGIS 0x811E +#define GL_QUAD_ALPHA8_SGIS 0x811F +#define GL_QUAD_LUMINANCE4_SGIS 0x8120 +#define GL_QUAD_LUMINANCE8_SGIS 0x8121 +#define GL_QUAD_INTENSITY4_SGIS 0x8122 +#define GL_QUAD_INTENSITY8_SGIS 0x8123 +#define GL_DUAL_TEXTURE_SELECT_SGIS 0x8124 +#define GL_QUAD_TEXTURE_SELECT_SGIS 0x8125 +#endif + +#ifndef GL_SGIX_sprite +#define GL_SPRITE_SGIX 0x8148 +#define GL_SPRITE_MODE_SGIX 0x8149 +#define GL_SPRITE_AXIS_SGIX 0x814A +#define GL_SPRITE_TRANSLATION_SGIX 0x814B +#define GL_SPRITE_AXIAL_SGIX 0x814C +#define GL_SPRITE_OBJECT_ALIGNED_SGIX 0x814D +#define GL_SPRITE_EYE_ALIGNED_SGIX 0x814E +#endif + +#ifndef GL_SGIX_texture_multi_buffer +#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E +#endif + +#ifndef GL_EXT_point_parameters +#define GL_POINT_SIZE_MIN_EXT 0x8126 +#define GL_POINT_SIZE_MAX_EXT 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 +#define GL_DISTANCE_ATTENUATION_EXT 0x8129 +#endif + +#ifndef GL_SGIS_point_parameters +#define GL_POINT_SIZE_MIN_SGIS 0x8126 +#define GL_POINT_SIZE_MAX_SGIS 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128 +#define GL_DISTANCE_ATTENUATION_SGIS 0x8129 +#endif + +#ifndef GL_SGIX_instruments +#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180 +#define GL_INSTRUMENT_MEASUREMENTS_SGIX 0x8181 +#endif + +#ifndef GL_SGIX_texture_scale_bias +#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179 +#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A +#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B +#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C +#endif + +#ifndef GL_SGIX_framezoom +#define GL_FRAMEZOOM_SGIX 0x818B +#define GL_FRAMEZOOM_FACTOR_SGIX 0x818C +#define GL_MAX_FRAMEZOOM_FACTOR_SGIX 0x818D +#endif + +#ifndef GL_SGIX_tag_sample_buffer +#endif + +#ifndef GL_FfdMaskSGIX +#define GL_TEXTURE_DEFORMATION_BIT_SGIX 0x00000001 +#define GL_GEOMETRY_DEFORMATION_BIT_SGIX 0x00000002 +#endif + +#ifndef GL_SGIX_polynomial_ffd +#define GL_GEOMETRY_DEFORMATION_SGIX 0x8194 +#define GL_TEXTURE_DEFORMATION_SGIX 0x8195 +#define GL_DEFORMATIONS_MASK_SGIX 0x8196 +#define GL_MAX_DEFORMATION_ORDER_SGIX 0x8197 +#endif + +#ifndef GL_SGIX_reference_plane +#define GL_REFERENCE_PLANE_SGIX 0x817D +#define GL_REFERENCE_PLANE_EQUATION_SGIX 0x817E +#endif + +#ifndef GL_SGIX_flush_raster +#endif + +#ifndef GL_SGIX_depth_texture +#define GL_DEPTH_COMPONENT16_SGIX 0x81A5 +#define GL_DEPTH_COMPONENT24_SGIX 0x81A6 +#define GL_DEPTH_COMPONENT32_SGIX 0x81A7 +#endif + +#ifndef GL_SGIS_fog_function +#define GL_FOG_FUNC_SGIS 0x812A +#define GL_FOG_FUNC_POINTS_SGIS 0x812B +#define GL_MAX_FOG_FUNC_POINTS_SGIS 0x812C +#endif + +#ifndef GL_SGIX_fog_offset +#define GL_FOG_OFFSET_SGIX 0x8198 +#define GL_FOG_OFFSET_VALUE_SGIX 0x8199 +#endif + +#ifndef GL_HP_image_transform +#define GL_IMAGE_SCALE_X_HP 0x8155 +#define GL_IMAGE_SCALE_Y_HP 0x8156 +#define GL_IMAGE_TRANSLATE_X_HP 0x8157 +#define GL_IMAGE_TRANSLATE_Y_HP 0x8158 +#define GL_IMAGE_ROTATE_ANGLE_HP 0x8159 +#define GL_IMAGE_ROTATE_ORIGIN_X_HP 0x815A +#define GL_IMAGE_ROTATE_ORIGIN_Y_HP 0x815B +#define GL_IMAGE_MAG_FILTER_HP 0x815C +#define GL_IMAGE_MIN_FILTER_HP 0x815D +#define GL_IMAGE_CUBIC_WEIGHT_HP 0x815E +#define GL_CUBIC_HP 0x815F +#define GL_AVERAGE_HP 0x8160 +#define GL_IMAGE_TRANSFORM_2D_HP 0x8161 +#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162 +#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163 +#endif + +#ifndef GL_HP_convolution_border_modes +#define GL_IGNORE_BORDER_HP 0x8150 +#define GL_CONSTANT_BORDER_HP 0x8151 +#define GL_REPLICATE_BORDER_HP 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR_HP 0x8154 +#endif + +#ifndef GL_INGR_palette_buffer +#endif + +#ifndef GL_SGIX_texture_add_env +#define GL_TEXTURE_ENV_BIAS_SGIX 0x80BE +#endif + +#ifndef GL_EXT_color_subtable +#endif + +#ifndef GL_PGI_vertex_hints +#define GL_VERTEX_DATA_HINT_PGI 0x1A22A +#define GL_VERTEX_CONSISTENT_HINT_PGI 0x1A22B +#define GL_MATERIAL_SIDE_HINT_PGI 0x1A22C +#define GL_MAX_VERTEX_HINT_PGI 0x1A22D +#define GL_COLOR3_BIT_PGI 0x00010000 +#define GL_COLOR4_BIT_PGI 0x00020000 +#define GL_EDGEFLAG_BIT_PGI 0x00040000 +#define GL_INDEX_BIT_PGI 0x00080000 +#define GL_MAT_AMBIENT_BIT_PGI 0x00100000 +#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000 +#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000 +#define GL_MAT_EMISSION_BIT_PGI 0x00800000 +#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000 +#define GL_MAT_SHININESS_BIT_PGI 0x02000000 +#define GL_MAT_SPECULAR_BIT_PGI 0x04000000 +#define GL_NORMAL_BIT_PGI 0x08000000 +#define GL_TEXCOORD1_BIT_PGI 0x10000000 +#define GL_TEXCOORD2_BIT_PGI 0x20000000 +#define GL_TEXCOORD3_BIT_PGI 0x40000000 +#define GL_TEXCOORD4_BIT_PGI 0x80000000 +#define GL_VERTEX23_BIT_PGI 0x00000004 +#define GL_VERTEX4_BIT_PGI 0x00000008 +#endif + +#ifndef GL_PGI_misc_hints +#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8 +#define GL_CONSERVE_MEMORY_HINT_PGI 0x1A1FD +#define GL_RECLAIM_MEMORY_HINT_PGI 0x1A1FE +#define GL_NATIVE_GRAPHICS_HANDLE_PGI 0x1A202 +#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203 +#define GL_NATIVE_GRAPHICS_END_HINT_PGI 0x1A204 +#define GL_ALWAYS_FAST_HINT_PGI 0x1A20C +#define GL_ALWAYS_SOFT_HINT_PGI 0x1A20D +#define GL_ALLOW_DRAW_OBJ_HINT_PGI 0x1A20E +#define GL_ALLOW_DRAW_WIN_HINT_PGI 0x1A20F +#define GL_ALLOW_DRAW_FRG_HINT_PGI 0x1A210 +#define GL_ALLOW_DRAW_MEM_HINT_PGI 0x1A211 +#define GL_STRICT_DEPTHFUNC_HINT_PGI 0x1A216 +#define GL_STRICT_LIGHTING_HINT_PGI 0x1A217 +#define GL_STRICT_SCISSOR_HINT_PGI 0x1A218 +#define GL_FULL_STIPPLE_HINT_PGI 0x1A219 +#define GL_CLIP_NEAR_HINT_PGI 0x1A220 +#define GL_CLIP_FAR_HINT_PGI 0x1A221 +#define GL_WIDE_LINE_HINT_PGI 0x1A222 +#define GL_BACK_NORMALS_HINT_PGI 0x1A223 +#endif + +#ifndef GL_EXT_paletted_texture +#define GL_COLOR_INDEX1_EXT 0x80E2 +#define GL_COLOR_INDEX2_EXT 0x80E3 +#define GL_COLOR_INDEX4_EXT 0x80E4 +#define GL_COLOR_INDEX8_EXT 0x80E5 +#define GL_COLOR_INDEX12_EXT 0x80E6 +#define GL_COLOR_INDEX16_EXT 0x80E7 +#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED +#endif + +#ifndef GL_EXT_clip_volume_hint +#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0 +#endif + +#ifndef GL_SGIX_list_priority +#define GL_LIST_PRIORITY_SGIX 0x8182 +#endif + +#ifndef GL_SGIX_ir_instrument1 +#define GL_IR_INSTRUMENT1_SGIX 0x817F +#endif + +#ifndef GL_SGIX_calligraphic_fragment +#define GL_CALLIGRAPHIC_FRAGMENT_SGIX 0x8183 +#endif + +#ifndef GL_SGIX_texture_lod_bias +#define GL_TEXTURE_LOD_BIAS_S_SGIX 0x818E +#define GL_TEXTURE_LOD_BIAS_T_SGIX 0x818F +#define GL_TEXTURE_LOD_BIAS_R_SGIX 0x8190 +#endif + +#ifndef GL_SGIX_shadow_ambient +#define GL_SHADOW_AMBIENT_SGIX 0x80BF +#endif + +#ifndef GL_EXT_index_texture +#endif + +#ifndef GL_EXT_index_material +#define GL_INDEX_MATERIAL_EXT 0x81B8 +#define GL_INDEX_MATERIAL_PARAMETER_EXT 0x81B9 +#define GL_INDEX_MATERIAL_FACE_EXT 0x81BA +#endif + +#ifndef GL_EXT_index_func +#define GL_INDEX_TEST_EXT 0x81B5 +#define GL_INDEX_TEST_FUNC_EXT 0x81B6 +#define GL_INDEX_TEST_REF_EXT 0x81B7 +#endif + +#ifndef GL_EXT_index_array_formats +#define GL_IUI_V2F_EXT 0x81AD +#define GL_IUI_V3F_EXT 0x81AE +#define GL_IUI_N3F_V2F_EXT 0x81AF +#define GL_IUI_N3F_V3F_EXT 0x81B0 +#define GL_T2F_IUI_V2F_EXT 0x81B1 +#define GL_T2F_IUI_V3F_EXT 0x81B2 +#define GL_T2F_IUI_N3F_V2F_EXT 0x81B3 +#define GL_T2F_IUI_N3F_V3F_EXT 0x81B4 +#endif + +#ifndef GL_EXT_compiled_vertex_array +#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8 +#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9 +#endif + +#ifndef GL_EXT_cull_vertex +#define GL_CULL_VERTEX_EXT 0x81AA +#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB +#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC +#endif + +#ifndef GL_SGIX_ycrcb +#define GL_YCRCB_422_SGIX 0x81BB +#define GL_YCRCB_444_SGIX 0x81BC +#endif + +#ifndef GL_SGIX_fragment_lighting +#define GL_FRAGMENT_LIGHTING_SGIX 0x8400 +#define GL_FRAGMENT_COLOR_MATERIAL_SGIX 0x8401 +#define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402 +#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403 +#define GL_MAX_FRAGMENT_LIGHTS_SGIX 0x8404 +#define GL_MAX_ACTIVE_LIGHTS_SGIX 0x8405 +#define GL_CURRENT_RASTER_NORMAL_SGIX 0x8406 +#define GL_LIGHT_ENV_MODE_SGIX 0x8407 +#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408 +#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409 +#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A +#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B +#define GL_FRAGMENT_LIGHT0_SGIX 0x840C +#define GL_FRAGMENT_LIGHT1_SGIX 0x840D +#define GL_FRAGMENT_LIGHT2_SGIX 0x840E +#define GL_FRAGMENT_LIGHT3_SGIX 0x840F +#define GL_FRAGMENT_LIGHT4_SGIX 0x8410 +#define GL_FRAGMENT_LIGHT5_SGIX 0x8411 +#define GL_FRAGMENT_LIGHT6_SGIX 0x8412 +#define GL_FRAGMENT_LIGHT7_SGIX 0x8413 +#endif + +#ifndef GL_IBM_rasterpos_clip +#define GL_RASTER_POSITION_UNCLIPPED_IBM 0x19262 +#endif + +#ifndef GL_HP_texture_lighting +#define GL_TEXTURE_LIGHTING_MODE_HP 0x8167 +#define GL_TEXTURE_POST_SPECULAR_HP 0x8168 +#define GL_TEXTURE_PRE_SPECULAR_HP 0x8169 +#endif + +#ifndef GL_EXT_draw_range_elements +#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8 +#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9 +#endif + +#ifndef GL_WIN_phong_shading +#define GL_PHONG_WIN 0x80EA +#define GL_PHONG_HINT_WIN 0x80EB +#endif + +#ifndef GL_WIN_specular_fog +#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC +#endif + +#ifndef GL_EXT_light_texture +#define GL_FRAGMENT_MATERIAL_EXT 0x8349 +#define GL_FRAGMENT_NORMAL_EXT 0x834A +#define GL_FRAGMENT_COLOR_EXT 0x834C +#define GL_ATTENUATION_EXT 0x834D +#define GL_SHADOW_ATTENUATION_EXT 0x834E +#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F +#define GL_TEXTURE_LIGHT_EXT 0x8350 +#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351 +#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352 +/* reuse GL_FRAGMENT_DEPTH_EXT */ +#endif + +#ifndef GL_SGIX_blend_alpha_minmax +#define GL_ALPHA_MIN_SGIX 0x8320 +#define GL_ALPHA_MAX_SGIX 0x8321 +#endif + +#ifndef GL_SGIX_impact_pixel_texture +#define GL_PIXEL_TEX_GEN_Q_CEILING_SGIX 0x8184 +#define GL_PIXEL_TEX_GEN_Q_ROUND_SGIX 0x8185 +#define GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX 0x8186 +#define GL_PIXEL_TEX_GEN_ALPHA_REPLACE_SGIX 0x8187 +#define GL_PIXEL_TEX_GEN_ALPHA_NO_REPLACE_SGIX 0x8188 +#define GL_PIXEL_TEX_GEN_ALPHA_LS_SGIX 0x8189 +#define GL_PIXEL_TEX_GEN_ALPHA_MS_SGIX 0x818A +#endif + +#ifndef GL_EXT_bgra +#define GL_BGR_EXT 0x80E0 +#define GL_BGRA_EXT 0x80E1 +#endif + +#ifndef GL_SGIX_async +#define GL_ASYNC_MARKER_SGIX 0x8329 +#endif + +#ifndef GL_SGIX_async_pixel +#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C +#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D +#define GL_ASYNC_READ_PIXELS_SGIX 0x835E +#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F +#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360 +#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361 +#endif + +#ifndef GL_SGIX_async_histogram +#define GL_ASYNC_HISTOGRAM_SGIX 0x832C +#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D +#endif + +#ifndef GL_INTEL_texture_scissor +#endif + +#ifndef GL_INTEL_parallel_arrays +#define GL_PARALLEL_ARRAYS_INTEL 0x83F4 +#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5 +#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6 +#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7 +#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8 +#endif + +#ifndef GL_HP_occlusion_test +#define GL_OCCLUSION_TEST_HP 0x8165 +#define GL_OCCLUSION_TEST_RESULT_HP 0x8166 +#endif + +#ifndef GL_EXT_pixel_transform +#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330 +#define GL_PIXEL_MAG_FILTER_EXT 0x8331 +#define GL_PIXEL_MIN_FILTER_EXT 0x8332 +#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333 +#define GL_CUBIC_EXT 0x8334 +#define GL_AVERAGE_EXT 0x8335 +#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336 +#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337 +#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338 +#endif + +#ifndef GL_EXT_pixel_transform_color_table +#endif + +#ifndef GL_EXT_shared_texture_palette +#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB +#endif + +#ifndef GL_EXT_separate_specular_color +#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 +#define GL_SINGLE_COLOR_EXT 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA +#endif + +#ifndef GL_EXT_secondary_color +#define GL_COLOR_SUM_EXT 0x8458 +#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D +#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E +#endif + +#ifndef GL_EXT_texture_perturb_normal +#define GL_PERTURB_EXT 0x85AE +#define GL_TEXTURE_NORMAL_EXT 0x85AF +#endif + +#ifndef GL_EXT_multi_draw_arrays +#endif + +#ifndef GL_EXT_fog_coord +#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450 +#define GL_FOG_COORDINATE_EXT 0x8451 +#define GL_FRAGMENT_DEPTH_EXT 0x8452 +#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456 +#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457 +#endif + +#ifndef GL_REND_screen_coordinates +#define GL_SCREEN_COORDINATES_REND 0x8490 +#define GL_INVERTED_SCREEN_W_REND 0x8491 +#endif + +#ifndef GL_EXT_coordinate_frame +#define GL_TANGENT_ARRAY_EXT 0x8439 +#define GL_BINORMAL_ARRAY_EXT 0x843A +#define GL_CURRENT_TANGENT_EXT 0x843B +#define GL_CURRENT_BINORMAL_EXT 0x843C +#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E +#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F +#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440 +#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441 +#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442 +#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443 +#define GL_MAP1_TANGENT_EXT 0x8444 +#define GL_MAP2_TANGENT_EXT 0x8445 +#define GL_MAP1_BINORMAL_EXT 0x8446 +#define GL_MAP2_BINORMAL_EXT 0x8447 +#endif + +#ifndef GL_EXT_texture_env_combine +#define GL_COMBINE_EXT 0x8570 +#define GL_COMBINE_RGB_EXT 0x8571 +#define GL_COMBINE_ALPHA_EXT 0x8572 +#define GL_RGB_SCALE_EXT 0x8573 +#define GL_ADD_SIGNED_EXT 0x8574 +#define GL_INTERPOLATE_EXT 0x8575 +#define GL_CONSTANT_EXT 0x8576 +#define GL_PRIMARY_COLOR_EXT 0x8577 +#define GL_PREVIOUS_EXT 0x8578 +#define GL_SOURCE0_RGB_EXT 0x8580 +#define GL_SOURCE1_RGB_EXT 0x8581 +#define GL_SOURCE2_RGB_EXT 0x8582 +#define GL_SOURCE0_ALPHA_EXT 0x8588 +#define GL_SOURCE1_ALPHA_EXT 0x8589 +#define GL_SOURCE2_ALPHA_EXT 0x858A +#define GL_OPERAND0_RGB_EXT 0x8590 +#define GL_OPERAND1_RGB_EXT 0x8591 +#define GL_OPERAND2_RGB_EXT 0x8592 +#define GL_OPERAND0_ALPHA_EXT 0x8598 +#define GL_OPERAND1_ALPHA_EXT 0x8599 +#define GL_OPERAND2_ALPHA_EXT 0x859A +#endif + +#ifndef GL_APPLE_specular_vector +#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0 +#endif + +#ifndef GL_APPLE_transform_hint +#define GL_TRANSFORM_HINT_APPLE 0x85B1 +#endif + +#ifndef GL_SGIX_fog_scale +#define GL_FOG_SCALE_SGIX 0x81FC +#define GL_FOG_SCALE_VALUE_SGIX 0x81FD +#endif + +#ifndef GL_SUNX_constant_data +#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5 +#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6 +#endif + +#ifndef GL_SUN_global_alpha +#define GL_GLOBAL_ALPHA_SUN 0x81D9 +#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA +#endif + +#ifndef GL_SUN_triangle_list +#define GL_RESTART_SUN 0x0001 +#define GL_REPLACE_MIDDLE_SUN 0x0002 +#define GL_REPLACE_OLDEST_SUN 0x0003 +#define GL_TRIANGLE_LIST_SUN 0x81D7 +#define GL_REPLACEMENT_CODE_SUN 0x81D8 +#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0 +#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 +#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 +#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 +#define GL_R1UI_V3F_SUN 0x85C4 +#define GL_R1UI_C4UB_V3F_SUN 0x85C5 +#define GL_R1UI_C3F_V3F_SUN 0x85C6 +#define GL_R1UI_N3F_V3F_SUN 0x85C7 +#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8 +#define GL_R1UI_T2F_V3F_SUN 0x85C9 +#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA +#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB +#endif + +#ifndef GL_SUN_vertex +#endif + +#ifndef GL_EXT_blend_func_separate +#define GL_BLEND_DST_RGB_EXT 0x80C8 +#define GL_BLEND_SRC_RGB_EXT 0x80C9 +#define GL_BLEND_DST_ALPHA_EXT 0x80CA +#define GL_BLEND_SRC_ALPHA_EXT 0x80CB +#endif + +#ifndef GL_INGR_color_clamp +#define GL_RED_MIN_CLAMP_INGR 0x8560 +#define GL_GREEN_MIN_CLAMP_INGR 0x8561 +#define GL_BLUE_MIN_CLAMP_INGR 0x8562 +#define GL_ALPHA_MIN_CLAMP_INGR 0x8563 +#define GL_RED_MAX_CLAMP_INGR 0x8564 +#define GL_GREEN_MAX_CLAMP_INGR 0x8565 +#define GL_BLUE_MAX_CLAMP_INGR 0x8566 +#define GL_ALPHA_MAX_CLAMP_INGR 0x8567 +#endif + +#ifndef GL_INGR_interlace_read +#define GL_INTERLACE_READ_INGR 0x8568 +#endif + +#ifndef GL_EXT_stencil_wrap +#define GL_INCR_WRAP_EXT 0x8507 +#define GL_DECR_WRAP_EXT 0x8508 +#endif + +#ifndef GL_EXT_422_pixels +#define GL_422_EXT 0x80CC +#define GL_422_REV_EXT 0x80CD +#define GL_422_AVERAGE_EXT 0x80CE +#define GL_422_REV_AVERAGE_EXT 0x80CF +#endif + +#ifndef GL_NV_texgen_reflection +#define GL_NORMAL_MAP_NV 0x8511 +#define GL_REFLECTION_MAP_NV 0x8512 +#endif + +#ifndef GL_EXT_texture_cube_map +#define GL_NORMAL_MAP_EXT 0x8511 +#define GL_REFLECTION_MAP_EXT 0x8512 +#define GL_TEXTURE_CUBE_MAP_EXT 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C +#endif + +#ifndef GL_SUN_convolution_border_modes +#define GL_WRAP_BORDER_SUN 0x81D4 +#endif + +#ifndef GL_EXT_texture_env_add +#endif + +#ifndef GL_EXT_texture_lod_bias +#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD +#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500 +#define GL_TEXTURE_LOD_BIAS_EXT 0x8501 +#endif + +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#endif + +#ifndef GL_EXT_vertex_weighting +#define GL_MODELVIEW0_STACK_DEPTH_EXT GL_MODELVIEW_STACK_DEPTH +#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502 +#define GL_MODELVIEW0_MATRIX_EXT GL_MODELVIEW_MATRIX +#define GL_MODELVIEW1_MATRIX_EXT 0x8506 +#define GL_VERTEX_WEIGHTING_EXT 0x8509 +#define GL_MODELVIEW0_EXT GL_MODELVIEW +#define GL_MODELVIEW1_EXT 0x850A +#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B +#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C +#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D +#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E +#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F +#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 +#endif + +#ifndef GL_NV_light_max_exponent +#define GL_MAX_SHININESS_NV 0x8504 +#define GL_MAX_SPOT_EXPONENT_NV 0x8505 +#endif + +#ifndef GL_NV_vertex_array_range +#define GL_VERTEX_ARRAY_RANGE_NV 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E +#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F +#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520 +#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 +#endif + +#ifndef GL_NV_register_combiners +#define GL_REGISTER_COMBINERS_NV 0x8522 +#define GL_VARIABLE_A_NV 0x8523 +#define GL_VARIABLE_B_NV 0x8524 +#define GL_VARIABLE_C_NV 0x8525 +#define GL_VARIABLE_D_NV 0x8526 +#define GL_VARIABLE_E_NV 0x8527 +#define GL_VARIABLE_F_NV 0x8528 +#define GL_VARIABLE_G_NV 0x8529 +#define GL_CONSTANT_COLOR0_NV 0x852A +#define GL_CONSTANT_COLOR1_NV 0x852B +#define GL_PRIMARY_COLOR_NV 0x852C +#define GL_SECONDARY_COLOR_NV 0x852D +#define GL_SPARE0_NV 0x852E +#define GL_SPARE1_NV 0x852F +#define GL_DISCARD_NV 0x8530 +#define GL_E_TIMES_F_NV 0x8531 +#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532 +#define GL_UNSIGNED_IDENTITY_NV 0x8536 +#define GL_UNSIGNED_INVERT_NV 0x8537 +#define GL_EXPAND_NORMAL_NV 0x8538 +#define GL_EXPAND_NEGATE_NV 0x8539 +#define GL_HALF_BIAS_NORMAL_NV 0x853A +#define GL_HALF_BIAS_NEGATE_NV 0x853B +#define GL_SIGNED_IDENTITY_NV 0x853C +#define GL_SIGNED_NEGATE_NV 0x853D +#define GL_SCALE_BY_TWO_NV 0x853E +#define GL_SCALE_BY_FOUR_NV 0x853F +#define GL_SCALE_BY_ONE_HALF_NV 0x8540 +#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541 +#define GL_COMBINER_INPUT_NV 0x8542 +#define GL_COMBINER_MAPPING_NV 0x8543 +#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544 +#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545 +#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546 +#define GL_COMBINER_MUX_SUM_NV 0x8547 +#define GL_COMBINER_SCALE_NV 0x8548 +#define GL_COMBINER_BIAS_NV 0x8549 +#define GL_COMBINER_AB_OUTPUT_NV 0x854A +#define GL_COMBINER_CD_OUTPUT_NV 0x854B +#define GL_COMBINER_SUM_OUTPUT_NV 0x854C +#define GL_MAX_GENERAL_COMBINERS_NV 0x854D +#define GL_NUM_GENERAL_COMBINERS_NV 0x854E +#define GL_COLOR_SUM_CLAMP_NV 0x854F +#define GL_COMBINER0_NV 0x8550 +#define GL_COMBINER1_NV 0x8551 +#define GL_COMBINER2_NV 0x8552 +#define GL_COMBINER3_NV 0x8553 +#define GL_COMBINER4_NV 0x8554 +#define GL_COMBINER5_NV 0x8555 +#define GL_COMBINER6_NV 0x8556 +#define GL_COMBINER7_NV 0x8557 +/* reuse GL_TEXTURE0_ARB */ +/* reuse GL_TEXTURE1_ARB */ +/* reuse GL_ZERO */ +/* reuse GL_NONE */ +/* reuse GL_FOG */ +#endif + +#ifndef GL_NV_fog_distance +#define GL_FOG_DISTANCE_MODE_NV 0x855A +#define GL_EYE_RADIAL_NV 0x855B +#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C +/* reuse GL_EYE_PLANE */ +#endif + +#ifndef GL_NV_texgen_emboss +#define GL_EMBOSS_LIGHT_NV 0x855D +#define GL_EMBOSS_CONSTANT_NV 0x855E +#define GL_EMBOSS_MAP_NV 0x855F +#endif + +#ifndef GL_NV_blend_square +#endif + +#ifndef GL_NV_texture_env_combine4 +#define GL_COMBINE4_NV 0x8503 +#define GL_SOURCE3_RGB_NV 0x8583 +#define GL_SOURCE3_ALPHA_NV 0x858B +#define GL_OPERAND3_RGB_NV 0x8593 +#define GL_OPERAND3_ALPHA_NV 0x859B +#endif + +#ifndef GL_MESA_resize_buffers +#endif + +#ifndef GL_MESA_window_pos +#endif + +#ifndef GL_EXT_texture_compression_s3tc +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 +#endif + +#ifndef GL_IBM_cull_vertex +#define GL_CULL_VERTEX_IBM 103050 +#endif + +#ifndef GL_IBM_multimode_draw_arrays +#endif + +#ifndef GL_IBM_vertex_array_lists +#define GL_VERTEX_ARRAY_LIST_IBM 103070 +#define GL_NORMAL_ARRAY_LIST_IBM 103071 +#define GL_COLOR_ARRAY_LIST_IBM 103072 +#define GL_INDEX_ARRAY_LIST_IBM 103073 +#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074 +#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075 +#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076 +#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077 +#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080 +#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081 +#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082 +#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083 +#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084 +#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085 +#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086 +#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087 +#endif + +#ifndef GL_SGIX_subsample +#define GL_PACK_SUBSAMPLE_RATE_SGIX 0x85A0 +#define GL_UNPACK_SUBSAMPLE_RATE_SGIX 0x85A1 +#define GL_PIXEL_SUBSAMPLE_4444_SGIX 0x85A2 +#define GL_PIXEL_SUBSAMPLE_2424_SGIX 0x85A3 +#define GL_PIXEL_SUBSAMPLE_4242_SGIX 0x85A4 +#endif + +#ifndef GL_SGIX_ycrcb_subsample +#endif + +#ifndef GL_SGIX_ycrcba +#define GL_YCRCB_SGIX 0x8318 +#define GL_YCRCBA_SGIX 0x8319 +#endif + +#ifndef GL_SGI_depth_pass_instrument +#define GL_DEPTH_PASS_INSTRUMENT_SGIX 0x8310 +#define GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX 0x8311 +#define GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX 0x8312 +#endif + +#ifndef GL_3DFX_texture_compression_FXT1 +#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0 +#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1 +#endif + +#ifndef GL_3DFX_multisample +#define GL_MULTISAMPLE_3DFX 0x86B2 +#define GL_SAMPLE_BUFFERS_3DFX 0x86B3 +#define GL_SAMPLES_3DFX 0x86B4 +#define GL_MULTISAMPLE_BIT_3DFX 0x20000000 +#endif + +#ifndef GL_3DFX_tbuffer +#endif + +#ifndef GL_EXT_multisample +#define GL_MULTISAMPLE_EXT 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F +#define GL_SAMPLE_MASK_EXT 0x80A0 +#define GL_1PASS_EXT 0x80A1 +#define GL_2PASS_0_EXT 0x80A2 +#define GL_2PASS_1_EXT 0x80A3 +#define GL_4PASS_0_EXT 0x80A4 +#define GL_4PASS_1_EXT 0x80A5 +#define GL_4PASS_2_EXT 0x80A6 +#define GL_4PASS_3_EXT 0x80A7 +#define GL_SAMPLE_BUFFERS_EXT 0x80A8 +#define GL_SAMPLES_EXT 0x80A9 +#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA +#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB +#define GL_SAMPLE_PATTERN_EXT 0x80AC +#define GL_MULTISAMPLE_BIT_EXT 0x20000000 +#endif + +#ifndef GL_SGIX_vertex_preclip +#define GL_VERTEX_PRECLIP_SGIX 0x83EE +#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF +#endif + +#ifndef GL_SGIX_convolution_accuracy +#define GL_CONVOLUTION_HINT_SGIX 0x8316 +#endif + +#ifndef GL_SGIX_resample +#define GL_PACK_RESAMPLE_SGIX 0x842C +#define GL_UNPACK_RESAMPLE_SGIX 0x842D +#define GL_RESAMPLE_REPLICATE_SGIX 0x842E +#define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F +#define GL_RESAMPLE_DECIMATE_SGIX 0x8430 +#endif + +#ifndef GL_SGIS_point_line_texgen +#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0 +#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1 +#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2 +#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3 +#define GL_EYE_POINT_SGIS 0x81F4 +#define GL_OBJECT_POINT_SGIS 0x81F5 +#define GL_EYE_LINE_SGIS 0x81F6 +#define GL_OBJECT_LINE_SGIS 0x81F7 +#endif + +#ifndef GL_SGIS_texture_color_mask +#define GL_TEXTURE_COLOR_WRITEMASK_SGIS 0x81EF +#endif + +#ifndef GL_EXT_texture_env_dot3 +#define GL_DOT3_RGB_EXT 0x8740 +#define GL_DOT3_RGBA_EXT 0x8741 +#endif + +#ifndef GL_ATI_texture_mirror_once +#define GL_MIRROR_CLAMP_ATI 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743 +#endif + +#ifndef GL_NV_fence +#define GL_ALL_COMPLETED_NV 0x84F2 +#define GL_FENCE_STATUS_NV 0x84F3 +#define GL_FENCE_CONDITION_NV 0x84F4 +#endif + +#ifndef GL_IBM_texture_mirrored_repeat +#define GL_MIRRORED_REPEAT_IBM 0x8370 +#endif + +#ifndef GL_NV_evaluators +#define GL_EVAL_2D_NV 0x86C0 +#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1 +#define GL_MAP_TESSELLATION_NV 0x86C2 +#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3 +#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4 +#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5 +#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6 +#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7 +#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8 +#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9 +#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA +#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB +#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC +#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD +#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE +#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF +#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0 +#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1 +#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2 +#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3 +#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4 +#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5 +#define GL_MAX_MAP_TESSELLATION_NV 0x86D6 +#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7 +#endif + +#ifndef GL_NV_packed_depth_stencil +#define GL_DEPTH_STENCIL_NV 0x84F9 +#define GL_UNSIGNED_INT_24_8_NV 0x84FA +#endif + +#ifndef GL_NV_register_combiners2 +#define GL_PER_STAGE_CONSTANTS_NV 0x8535 +#endif + +#ifndef GL_NV_texture_compression_vtc +#endif + +#ifndef GL_NV_texture_rectangle +#define GL_TEXTURE_RECTANGLE_NV 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 +#endif + +#ifndef GL_NV_texture_shader +#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C +#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D +#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E +#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9 +#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA +#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB +#define GL_DSDT_MAG_INTENSITY_NV 0x86DC +#define GL_SHADER_CONSISTENT_NV 0x86DD +#define GL_TEXTURE_SHADER_NV 0x86DE +#define GL_SHADER_OPERATION_NV 0x86DF +#define GL_CULL_MODES_NV 0x86E0 +#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1 +#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2 +#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 +#define GL_OFFSET_TEXTURE_2D_MATRIX_NV GL_OFFSET_TEXTURE_MATRIX_NV +#define GL_OFFSET_TEXTURE_2D_SCALE_NV GL_OFFSET_TEXTURE_SCALE_NV +#define GL_OFFSET_TEXTURE_2D_BIAS_NV GL_OFFSET_TEXTURE_BIAS_NV +#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4 +#define GL_CONST_EYE_NV 0x86E5 +#define GL_PASS_THROUGH_NV 0x86E6 +#define GL_CULL_FRAGMENT_NV 0x86E7 +#define GL_OFFSET_TEXTURE_2D_NV 0x86E8 +#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9 +#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA +#define GL_DOT_PRODUCT_NV 0x86EC +#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED +#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE +#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0 +#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1 +#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2 +#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3 +#define GL_HILO_NV 0x86F4 +#define GL_DSDT_NV 0x86F5 +#define GL_DSDT_MAG_NV 0x86F6 +#define GL_DSDT_MAG_VIB_NV 0x86F7 +#define GL_HILO16_NV 0x86F8 +#define GL_SIGNED_HILO_NV 0x86F9 +#define GL_SIGNED_HILO16_NV 0x86FA +#define GL_SIGNED_RGBA_NV 0x86FB +#define GL_SIGNED_RGBA8_NV 0x86FC +#define GL_SIGNED_RGB_NV 0x86FE +#define GL_SIGNED_RGB8_NV 0x86FF +#define GL_SIGNED_LUMINANCE_NV 0x8701 +#define GL_SIGNED_LUMINANCE8_NV 0x8702 +#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 +#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 +#define GL_SIGNED_ALPHA_NV 0x8705 +#define GL_SIGNED_ALPHA8_NV 0x8706 +#define GL_SIGNED_INTENSITY_NV 0x8707 +#define GL_SIGNED_INTENSITY8_NV 0x8708 +#define GL_DSDT8_NV 0x8709 +#define GL_DSDT8_MAG8_NV 0x870A +#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B +#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C +#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D +#define GL_HI_SCALE_NV 0x870E +#define GL_LO_SCALE_NV 0x870F +#define GL_DS_SCALE_NV 0x8710 +#define GL_DT_SCALE_NV 0x8711 +#define GL_MAGNITUDE_SCALE_NV 0x8712 +#define GL_VIBRANCE_SCALE_NV 0x8713 +#define GL_HI_BIAS_NV 0x8714 +#define GL_LO_BIAS_NV 0x8715 +#define GL_DS_BIAS_NV 0x8716 +#define GL_DT_BIAS_NV 0x8717 +#define GL_MAGNITUDE_BIAS_NV 0x8718 +#define GL_VIBRANCE_BIAS_NV 0x8719 +#define GL_TEXTURE_BORDER_VALUES_NV 0x871A +#define GL_TEXTURE_HI_SIZE_NV 0x871B +#define GL_TEXTURE_LO_SIZE_NV 0x871C +#define GL_TEXTURE_DS_SIZE_NV 0x871D +#define GL_TEXTURE_DT_SIZE_NV 0x871E +#define GL_TEXTURE_MAG_SIZE_NV 0x871F +#endif + +#ifndef GL_NV_texture_shader2 +#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF +#endif + +#ifndef GL_NV_vertex_array_range2 +#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 +#endif + +#ifndef GL_NV_vertex_program +#define GL_VERTEX_PROGRAM_NV 0x8620 +#define GL_VERTEX_STATE_PROGRAM_NV 0x8621 +#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623 +#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624 +#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625 +#define GL_CURRENT_ATTRIB_NV 0x8626 +#define GL_PROGRAM_LENGTH_NV 0x8627 +#define GL_PROGRAM_STRING_NV 0x8628 +#define GL_MODELVIEW_PROJECTION_NV 0x8629 +#define GL_IDENTITY_NV 0x862A +#define GL_INVERSE_NV 0x862B +#define GL_TRANSPOSE_NV 0x862C +#define GL_INVERSE_TRANSPOSE_NV 0x862D +#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E +#define GL_MAX_TRACK_MATRICES_NV 0x862F +#define GL_MATRIX0_NV 0x8630 +#define GL_MATRIX1_NV 0x8631 +#define GL_MATRIX2_NV 0x8632 +#define GL_MATRIX3_NV 0x8633 +#define GL_MATRIX4_NV 0x8634 +#define GL_MATRIX5_NV 0x8635 +#define GL_MATRIX6_NV 0x8636 +#define GL_MATRIX7_NV 0x8637 +#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 +#define GL_CURRENT_MATRIX_NV 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 +#define GL_PROGRAM_PARAMETER_NV 0x8644 +#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645 +#define GL_PROGRAM_TARGET_NV 0x8646 +#define GL_PROGRAM_RESIDENT_NV 0x8647 +#define GL_TRACK_MATRIX_NV 0x8648 +#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649 +#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A +#define GL_PROGRAM_ERROR_POSITION_NV 0x864B +#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650 +#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651 +#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652 +#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653 +#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654 +#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655 +#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656 +#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657 +#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658 +#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659 +#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A +#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B +#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C +#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D +#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E +#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F +#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660 +#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661 +#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662 +#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663 +#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664 +#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665 +#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666 +#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667 +#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668 +#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669 +#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A +#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B +#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C +#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D +#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E +#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F +#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670 +#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671 +#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672 +#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673 +#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674 +#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675 +#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676 +#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677 +#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678 +#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679 +#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A +#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B +#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C +#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D +#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E +#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F +#endif + +#ifndef GL_SGIX_texture_coordinate_clamp +#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369 +#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A +#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B +#endif + +#ifndef GL_SGIX_scalebias_hint +#define GL_SCALEBIAS_HINT_SGIX 0x8322 +#endif + +#ifndef GL_OML_interlace +#define GL_INTERLACE_OML 0x8980 +#define GL_INTERLACE_READ_OML 0x8981 +#endif + +#ifndef GL_OML_subsample +#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982 +#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983 +#endif + +#ifndef GL_OML_resample +#define GL_PACK_RESAMPLE_OML 0x8984 +#define GL_UNPACK_RESAMPLE_OML 0x8985 +#define GL_RESAMPLE_REPLICATE_OML 0x8986 +#define GL_RESAMPLE_ZERO_FILL_OML 0x8987 +#define GL_RESAMPLE_AVERAGE_OML 0x8988 +#define GL_RESAMPLE_DECIMATE_OML 0x8989 +#endif + +#ifndef GL_NV_copy_depth_to_color +#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E +#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F +#endif + +#ifndef GL_ATI_envmap_bumpmap +#define GL_BUMP_ROT_MATRIX_ATI 0x8775 +#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776 +#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777 +#define GL_BUMP_TEX_UNITS_ATI 0x8778 +#define GL_DUDV_ATI 0x8779 +#define GL_DU8DV8_ATI 0x877A +#define GL_BUMP_ENVMAP_ATI 0x877B +#define GL_BUMP_TARGET_ATI 0x877C +#endif + +#ifndef GL_ATI_fragment_shader +#define GL_FRAGMENT_SHADER_ATI 0x8920 +#define GL_REG_0_ATI 0x8921 +#define GL_REG_1_ATI 0x8922 +#define GL_REG_2_ATI 0x8923 +#define GL_REG_3_ATI 0x8924 +#define GL_REG_4_ATI 0x8925 +#define GL_REG_5_ATI 0x8926 +#define GL_REG_6_ATI 0x8927 +#define GL_REG_7_ATI 0x8928 +#define GL_REG_8_ATI 0x8929 +#define GL_REG_9_ATI 0x892A +#define GL_REG_10_ATI 0x892B +#define GL_REG_11_ATI 0x892C +#define GL_REG_12_ATI 0x892D +#define GL_REG_13_ATI 0x892E +#define GL_REG_14_ATI 0x892F +#define GL_REG_15_ATI 0x8930 +#define GL_REG_16_ATI 0x8931 +#define GL_REG_17_ATI 0x8932 +#define GL_REG_18_ATI 0x8933 +#define GL_REG_19_ATI 0x8934 +#define GL_REG_20_ATI 0x8935 +#define GL_REG_21_ATI 0x8936 +#define GL_REG_22_ATI 0x8937 +#define GL_REG_23_ATI 0x8938 +#define GL_REG_24_ATI 0x8939 +#define GL_REG_25_ATI 0x893A +#define GL_REG_26_ATI 0x893B +#define GL_REG_27_ATI 0x893C +#define GL_REG_28_ATI 0x893D +#define GL_REG_29_ATI 0x893E +#define GL_REG_30_ATI 0x893F +#define GL_REG_31_ATI 0x8940 +#define GL_CON_0_ATI 0x8941 +#define GL_CON_1_ATI 0x8942 +#define GL_CON_2_ATI 0x8943 +#define GL_CON_3_ATI 0x8944 +#define GL_CON_4_ATI 0x8945 +#define GL_CON_5_ATI 0x8946 +#define GL_CON_6_ATI 0x8947 +#define GL_CON_7_ATI 0x8948 +#define GL_CON_8_ATI 0x8949 +#define GL_CON_9_ATI 0x894A +#define GL_CON_10_ATI 0x894B +#define GL_CON_11_ATI 0x894C +#define GL_CON_12_ATI 0x894D +#define GL_CON_13_ATI 0x894E +#define GL_CON_14_ATI 0x894F +#define GL_CON_15_ATI 0x8950 +#define GL_CON_16_ATI 0x8951 +#define GL_CON_17_ATI 0x8952 +#define GL_CON_18_ATI 0x8953 +#define GL_CON_19_ATI 0x8954 +#define GL_CON_20_ATI 0x8955 +#define GL_CON_21_ATI 0x8956 +#define GL_CON_22_ATI 0x8957 +#define GL_CON_23_ATI 0x8958 +#define GL_CON_24_ATI 0x8959 +#define GL_CON_25_ATI 0x895A +#define GL_CON_26_ATI 0x895B +#define GL_CON_27_ATI 0x895C +#define GL_CON_28_ATI 0x895D +#define GL_CON_29_ATI 0x895E +#define GL_CON_30_ATI 0x895F +#define GL_CON_31_ATI 0x8960 +#define GL_MOV_ATI 0x8961 +#define GL_ADD_ATI 0x8963 +#define GL_MUL_ATI 0x8964 +#define GL_SUB_ATI 0x8965 +#define GL_DOT3_ATI 0x8966 +#define GL_DOT4_ATI 0x8967 +#define GL_MAD_ATI 0x8968 +#define GL_LERP_ATI 0x8969 +#define GL_CND_ATI 0x896A +#define GL_CND0_ATI 0x896B +#define GL_DOT2_ADD_ATI 0x896C +#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D +#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E +#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F +#define GL_NUM_PASSES_ATI 0x8970 +#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971 +#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972 +#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973 +#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974 +#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975 +#define GL_SWIZZLE_STR_ATI 0x8976 +#define GL_SWIZZLE_STQ_ATI 0x8977 +#define GL_SWIZZLE_STR_DR_ATI 0x8978 +#define GL_SWIZZLE_STQ_DQ_ATI 0x8979 +#define GL_SWIZZLE_STRQ_ATI 0x897A +#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B +#define GL_RED_BIT_ATI 0x00000001 +#define GL_GREEN_BIT_ATI 0x00000002 +#define GL_BLUE_BIT_ATI 0x00000004 +#define GL_2X_BIT_ATI 0x00000001 +#define GL_4X_BIT_ATI 0x00000002 +#define GL_8X_BIT_ATI 0x00000004 +#define GL_HALF_BIT_ATI 0x00000008 +#define GL_QUARTER_BIT_ATI 0x00000010 +#define GL_EIGHTH_BIT_ATI 0x00000020 +#define GL_SATURATE_BIT_ATI 0x00000040 +#define GL_COMP_BIT_ATI 0x00000002 +#define GL_NEGATE_BIT_ATI 0x00000004 +#define GL_BIAS_BIT_ATI 0x00000008 +#endif + +#ifndef GL_ATI_pn_triangles +#define GL_PN_TRIANGLES_ATI 0x87F0 +#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1 +#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2 +#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3 +#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4 +#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5 +#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6 +#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7 +#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8 +#endif + +#ifndef GL_ATI_vertex_array_object +#define GL_STATIC_ATI 0x8760 +#define GL_DYNAMIC_ATI 0x8761 +#define GL_PRESERVE_ATI 0x8762 +#define GL_DISCARD_ATI 0x8763 +#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764 +#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765 +#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766 +#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767 +#endif + +#ifndef GL_EXT_vertex_shader +#define GL_VERTEX_SHADER_EXT 0x8780 +#define GL_VERTEX_SHADER_BINDING_EXT 0x8781 +#define GL_OP_INDEX_EXT 0x8782 +#define GL_OP_NEGATE_EXT 0x8783 +#define GL_OP_DOT3_EXT 0x8784 +#define GL_OP_DOT4_EXT 0x8785 +#define GL_OP_MUL_EXT 0x8786 +#define GL_OP_ADD_EXT 0x8787 +#define GL_OP_MADD_EXT 0x8788 +#define GL_OP_FRAC_EXT 0x8789 +#define GL_OP_MAX_EXT 0x878A +#define GL_OP_MIN_EXT 0x878B +#define GL_OP_SET_GE_EXT 0x878C +#define GL_OP_SET_LT_EXT 0x878D +#define GL_OP_CLAMP_EXT 0x878E +#define GL_OP_FLOOR_EXT 0x878F +#define GL_OP_ROUND_EXT 0x8790 +#define GL_OP_EXP_BASE_2_EXT 0x8791 +#define GL_OP_LOG_BASE_2_EXT 0x8792 +#define GL_OP_POWER_EXT 0x8793 +#define GL_OP_RECIP_EXT 0x8794 +#define GL_OP_RECIP_SQRT_EXT 0x8795 +#define GL_OP_SUB_EXT 0x8796 +#define GL_OP_CROSS_PRODUCT_EXT 0x8797 +#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798 +#define GL_OP_MOV_EXT 0x8799 +#define GL_OUTPUT_VERTEX_EXT 0x879A +#define GL_OUTPUT_COLOR0_EXT 0x879B +#define GL_OUTPUT_COLOR1_EXT 0x879C +#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D +#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E +#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F +#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0 +#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1 +#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2 +#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3 +#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4 +#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5 +#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6 +#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7 +#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8 +#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9 +#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA +#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB +#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC +#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD +#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE +#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF +#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0 +#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1 +#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2 +#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3 +#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4 +#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5 +#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6 +#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7 +#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8 +#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9 +#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA +#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB +#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC +#define GL_OUTPUT_FOG_EXT 0x87BD +#define GL_SCALAR_EXT 0x87BE +#define GL_VECTOR_EXT 0x87BF +#define GL_MATRIX_EXT 0x87C0 +#define GL_VARIANT_EXT 0x87C1 +#define GL_INVARIANT_EXT 0x87C2 +#define GL_LOCAL_CONSTANT_EXT 0x87C3 +#define GL_LOCAL_EXT 0x87C4 +#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5 +#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6 +#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7 +#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8 +#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9 +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE +#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF +#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0 +#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1 +#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2 +#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3 +#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4 +#define GL_X_EXT 0x87D5 +#define GL_Y_EXT 0x87D6 +#define GL_Z_EXT 0x87D7 +#define GL_W_EXT 0x87D8 +#define GL_NEGATIVE_X_EXT 0x87D9 +#define GL_NEGATIVE_Y_EXT 0x87DA +#define GL_NEGATIVE_Z_EXT 0x87DB +#define GL_NEGATIVE_W_EXT 0x87DC +#define GL_ZERO_EXT 0x87DD +#define GL_ONE_EXT 0x87DE +#define GL_NEGATIVE_ONE_EXT 0x87DF +#define GL_NORMALIZED_RANGE_EXT 0x87E0 +#define GL_FULL_RANGE_EXT 0x87E1 +#define GL_CURRENT_VERTEX_EXT 0x87E2 +#define GL_MVP_MATRIX_EXT 0x87E3 +#define GL_VARIANT_VALUE_EXT 0x87E4 +#define GL_VARIANT_DATATYPE_EXT 0x87E5 +#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6 +#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7 +#define GL_VARIANT_ARRAY_EXT 0x87E8 +#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9 +#define GL_INVARIANT_VALUE_EXT 0x87EA +#define GL_INVARIANT_DATATYPE_EXT 0x87EB +#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC +#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED +#endif + +#ifndef GL_ATI_vertex_streams +#define GL_MAX_VERTEX_STREAMS_ATI 0x876B +#define GL_VERTEX_STREAM0_ATI 0x876C +#define GL_VERTEX_STREAM1_ATI 0x876D +#define GL_VERTEX_STREAM2_ATI 0x876E +#define GL_VERTEX_STREAM3_ATI 0x876F +#define GL_VERTEX_STREAM4_ATI 0x8770 +#define GL_VERTEX_STREAM5_ATI 0x8771 +#define GL_VERTEX_STREAM6_ATI 0x8772 +#define GL_VERTEX_STREAM7_ATI 0x8773 +#define GL_VERTEX_SOURCE_ATI 0x8774 +#endif + +#ifndef GL_ATI_element_array +#define GL_ELEMENT_ARRAY_ATI 0x8768 +#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769 +#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A +#endif + +#ifndef GL_SUN_mesh_array +#define GL_QUAD_MESH_SUN 0x8614 +#define GL_TRIANGLE_MESH_SUN 0x8615 +#endif + +#ifndef GL_SUN_slice_accum +#define GL_SLICE_ACCUM_SUN 0x85CC +#endif + +#ifndef GL_NV_multisample_filter_hint +#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 +#endif + +#ifndef GL_NV_depth_clamp +#define GL_DEPTH_CLAMP_NV 0x864F +#endif + +#ifndef GL_NV_occlusion_query +#define GL_PIXEL_COUNTER_BITS_NV 0x8864 +#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865 +#define GL_PIXEL_COUNT_NV 0x8866 +#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867 +#endif + +#ifndef GL_NV_point_sprite +#define GL_POINT_SPRITE_NV 0x8861 +#define GL_COORD_REPLACE_NV 0x8862 +#define GL_POINT_SPRITE_R_MODE_NV 0x8863 +#endif + +#ifndef GL_NV_texture_shader3 +#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850 +#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851 +#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852 +#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853 +#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854 +#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855 +#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856 +#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857 +#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858 +#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859 +#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A +#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B +#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C +#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D +#define GL_HILO8_NV 0x885E +#define GL_SIGNED_HILO8_NV 0x885F +#define GL_FORCE_BLUE_TO_ONE_NV 0x8860 +#endif + +#ifndef GL_NV_vertex_program1_1 +#endif + +#ifndef GL_EXT_shadow_funcs +#endif + +#ifndef GL_EXT_stencil_two_side +#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910 +#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911 +#endif + +#ifndef GL_ATI_text_fragment_shader +#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200 +#endif + +#ifndef GL_APPLE_client_storage +#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2 +#endif + +#ifndef GL_APPLE_element_array +#define GL_ELEMENT_ARRAY_APPLE 0x8768 +#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8769 +#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x876A +#endif + +#ifndef GL_APPLE_fence +#define GL_DRAW_PIXELS_APPLE 0x8A0A +#define GL_FENCE_APPLE 0x8A0B +#endif + +#ifndef GL_APPLE_vertex_array_object +#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5 +#endif + +#ifndef GL_APPLE_vertex_array_range +#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E +#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F +#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521 +#define GL_STORAGE_CACHED_APPLE 0x85BE +#define GL_STORAGE_SHARED_APPLE 0x85BF +#endif + +#ifndef GL_APPLE_ycbcr_422 +#define GL_YCBCR_422_APPLE 0x85B9 +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB +#endif + +#ifndef GL_S3_s3tc +#define GL_RGB_S3TC 0x83A0 +#define GL_RGB4_S3TC 0x83A1 +#define GL_RGBA_S3TC 0x83A2 +#define GL_RGBA4_S3TC 0x83A3 +#endif + +#ifndef GL_ATI_draw_buffers +#define GL_MAX_DRAW_BUFFERS_ATI 0x8824 +#define GL_DRAW_BUFFER0_ATI 0x8825 +#define GL_DRAW_BUFFER1_ATI 0x8826 +#define GL_DRAW_BUFFER2_ATI 0x8827 +#define GL_DRAW_BUFFER3_ATI 0x8828 +#define GL_DRAW_BUFFER4_ATI 0x8829 +#define GL_DRAW_BUFFER5_ATI 0x882A +#define GL_DRAW_BUFFER6_ATI 0x882B +#define GL_DRAW_BUFFER7_ATI 0x882C +#define GL_DRAW_BUFFER8_ATI 0x882D +#define GL_DRAW_BUFFER9_ATI 0x882E +#define GL_DRAW_BUFFER10_ATI 0x882F +#define GL_DRAW_BUFFER11_ATI 0x8830 +#define GL_DRAW_BUFFER12_ATI 0x8831 +#define GL_DRAW_BUFFER13_ATI 0x8832 +#define GL_DRAW_BUFFER14_ATI 0x8833 +#define GL_DRAW_BUFFER15_ATI 0x8834 +#endif + +#ifndef GL_ATI_pixel_format_float +#define GL_TYPE_RGBA_FLOAT_ATI 0x8820 +#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835 +#endif + +#ifndef GL_ATI_texture_env_combine3 +#define GL_MODULATE_ADD_ATI 0x8744 +#define GL_MODULATE_SIGNED_ADD_ATI 0x8745 +#define GL_MODULATE_SUBTRACT_ATI 0x8746 +#endif + +#ifndef GL_ATI_texture_float +#define GL_RGBA_FLOAT32_ATI 0x8814 +#define GL_RGB_FLOAT32_ATI 0x8815 +#define GL_ALPHA_FLOAT32_ATI 0x8816 +#define GL_INTENSITY_FLOAT32_ATI 0x8817 +#define GL_LUMINANCE_FLOAT32_ATI 0x8818 +#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819 +#define GL_RGBA_FLOAT16_ATI 0x881A +#define GL_RGB_FLOAT16_ATI 0x881B +#define GL_ALPHA_FLOAT16_ATI 0x881C +#define GL_INTENSITY_FLOAT16_ATI 0x881D +#define GL_LUMINANCE_FLOAT16_ATI 0x881E +#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F +#endif + +#ifndef GL_NV_float_buffer +#define GL_FLOAT_R_NV 0x8880 +#define GL_FLOAT_RG_NV 0x8881 +#define GL_FLOAT_RGB_NV 0x8882 +#define GL_FLOAT_RGBA_NV 0x8883 +#define GL_FLOAT_R16_NV 0x8884 +#define GL_FLOAT_R32_NV 0x8885 +#define GL_FLOAT_RG16_NV 0x8886 +#define GL_FLOAT_RG32_NV 0x8887 +#define GL_FLOAT_RGB16_NV 0x8888 +#define GL_FLOAT_RGB32_NV 0x8889 +#define GL_FLOAT_RGBA16_NV 0x888A +#define GL_FLOAT_RGBA32_NV 0x888B +#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C +#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D +#define GL_FLOAT_RGBA_MODE_NV 0x888E +#endif + +#ifndef GL_NV_fragment_program +#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868 +#define GL_FRAGMENT_PROGRAM_NV 0x8870 +#define GL_MAX_TEXTURE_COORDS_NV 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872 +#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873 +#define GL_PROGRAM_ERROR_STRING_NV 0x8874 +#endif + +#ifndef GL_NV_half_float +#define GL_HALF_FLOAT_NV 0x140B +#endif + +#ifndef GL_NV_pixel_data_range +#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878 +#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879 +#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A +#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B +#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C +#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D +#endif + +#ifndef GL_NV_primitive_restart +#define GL_PRIMITIVE_RESTART_NV 0x8558 +#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559 +#endif + +#ifndef GL_NV_texture_expand_normal +#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F +#endif + +#ifndef GL_NV_vertex_program2 +#endif + +#ifndef GL_ATI_map_object_buffer +#endif + +#ifndef GL_ATI_separate_stencil +#define GL_STENCIL_BACK_FUNC_ATI 0x8800 +#define GL_STENCIL_BACK_FAIL_ATI 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803 +#endif + +#ifndef GL_ATI_vertex_attrib_array_object +#endif + +#ifndef GL_OES_read_format +#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B +#endif + +#ifndef GL_EXT_depth_bounds_test +#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890 +#define GL_DEPTH_BOUNDS_EXT 0x8891 +#endif + +#ifndef GL_EXT_texture_mirror_clamp +#define GL_MIRROR_CLAMP_EXT 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743 +#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912 +#endif + +#ifndef GL_EXT_blend_equation_separate +#define GL_BLEND_EQUATION_RGB_EXT GL_BLEND_EQUATION +#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D +#endif + +#ifndef GL_MESA_pack_invert +#define GL_PACK_INVERT_MESA 0x8758 +#endif + +#ifndef GL_MESA_ycbcr_texture +#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB +#define GL_YCBCR_MESA 0x8757 +#endif + +#ifndef GL_EXT_pixel_buffer_object +#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF +#endif + +#ifndef GL_NV_fragment_program_option +#endif + +#ifndef GL_NV_fragment_program2 +#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 +#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 +#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6 +#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7 +#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8 +#endif + +#ifndef GL_NV_vertex_program2_option +/* reuse GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV */ +/* reuse GL_MAX_PROGRAM_CALL_DEPTH_NV */ +#endif + +#ifndef GL_NV_vertex_program3 +/* reuse GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB */ +#endif + +#ifndef GL_EXT_framebuffer_object +#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 +#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 +#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 +#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF +#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 +#define GL_STENCIL_ATTACHMENT_EXT 0x8D20 +#define GL_FRAMEBUFFER_EXT 0x8D40 +#define GL_RENDERBUFFER_EXT 0x8D41 +#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 +#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 +#define GL_STENCIL_INDEX_EXT 0x8D45 +#define GL_STENCIL_INDEX1_EXT 0x8D46 +#define GL_STENCIL_INDEX4_EXT 0x8D47 +#define GL_STENCIL_INDEX8_EXT 0x8D48 +#define GL_STENCIL_INDEX16_EXT 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55 +#endif + +#ifndef GL_GREMEDY_string_marker +#endif + +#ifndef GL_EXT_Cg_shader +#define GL_CG_VERTEX_SHADER_EXT 0x890E +#define GL_CG_FRAGMENT_SHADER_EXT 0x890F +#endif + +#ifndef GL_EXT_timer_query +#define GL_TIME_ELAPSED_EXT 0x88BF +#endif + +#ifndef GL_EXT_texture_buffer_object +#define GL_TEXTURE_BUFFER_EXT 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E +#endif + +#ifndef GL_EXT_gpu_shader4 +#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0 +#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1 +#define GL_SAMPLER_BUFFER_EXT 0x8DC2 +#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5 +#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6 +#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7 +#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8 +#define GL_INT_SAMPLER_1D_EXT 0x8DC9 +#define GL_INT_SAMPLER_2D_EXT 0x8DCA +#define GL_INT_SAMPLER_3D_EXT 0x8DCB +#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC +#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD +#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF +#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8 +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD +#endif + +#ifndef GL_EXT_geometry_shader4 +#define GL_GEOMETRY_SHADER_EXT 0x8DD9 +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD +#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE +#define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1 +#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA +#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 +#define GL_LINES_ADJACENCY_EXT 0xA +#define GL_LINE_STRIP_ADJACENCY_EXT 0xB +#define GL_TRIANGLES_ADJACENCY_EXT 0xC +#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 +#define GL_PROGRAM_POINT_SIZE_EXT 0x8642 +#endif + +#ifndef GL_EXT_bindable_uniform +#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2 +#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3 +#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4 +#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED +#define GL_UNIFORM_BUFFER_EXT 0x8DEE +#define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF +#endif + +#ifndef GL_EXT_framebuffer_sRGB +#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 +#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA +#endif + +#ifndef GL_EXT_texture_shared_exponent +#define GL_RGB9_E5_EXT 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E +#define GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F +#endif + +#ifndef GL_EXT_packed_float +#define GL_R11F_G11F_B10F_EXT 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B +#define GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C +#endif + +#ifndef GL_EXT_texture_array +#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19 +#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D +#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF +#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E +/* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT */ +#endif + +#ifndef GL_EXT_texture_integer +#define GL_RGBA32UI_EXT 0x8D70 +#define GL_RGB32UI_EXT 0x8D71 +#define GL_ALPHA32UI_EXT 0x8D72 +#define GL_INTENSITY32UI_EXT 0x8D73 +#define GL_LUMINANCE32UI_EXT 0x8D74 +#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75 +#define GL_RGBA16UI_EXT 0x8D76 +#define GL_RGB16UI_EXT 0x8D77 +#define GL_ALPHA16UI_EXT 0x8D78 +#define GL_INTENSITY16UI_EXT 0x8D79 +#define GL_LUMINANCE16UI_EXT 0x8D7A +#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B +#define GL_RGBA8UI_EXT 0x8D7C +#define GL_RGB8UI_EXT 0x8D7D +#define GL_ALPHA8UI_EXT 0x8D7E +#define GL_INTENSITY8UI_EXT 0x8D7F +#define GL_LUMINANCE8UI_EXT 0x8D80 +#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81 +#define GL_RGBA32I_EXT 0x8D82 +#define GL_RGB32I_EXT 0x8D83 +#define GL_ALPHA32I_EXT 0x8D84 +#define GL_INTENSITY32I_EXT 0x8D85 +#define GL_LUMINANCE32I_EXT 0x8D86 +#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87 +#define GL_RGBA16I_EXT 0x8D88 +#define GL_RGB16I_EXT 0x8D89 +#define GL_ALPHA16I_EXT 0x8D8A +#define GL_INTENSITY16I_EXT 0x8D8B +#define GL_LUMINANCE16I_EXT 0x8D8C +#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D +#define GL_RGBA8I_EXT 0x8D8E +#define GL_RGB8I_EXT 0x8D8F +#define GL_ALPHA8I_EXT 0x8D90 +#define GL_INTENSITY8I_EXT 0x8D91 +#define GL_LUMINANCE8I_EXT 0x8D92 +#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93 +#define GL_RED_INTEGER_EXT 0x8D94 +#define GL_GREEN_INTEGER_EXT 0x8D95 +#define GL_BLUE_INTEGER_EXT 0x8D96 +#define GL_ALPHA_INTEGER_EXT 0x8D97 +#define GL_RGB_INTEGER_EXT 0x8D98 +#define GL_RGBA_INTEGER_EXT 0x8D99 +#define GL_BGR_INTEGER_EXT 0x8D9A +#define GL_BGRA_INTEGER_EXT 0x8D9B +#define GL_LUMINANCE_INTEGER_EXT 0x8D9C +#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D +#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E +#endif + +#ifndef GL_NV_depth_buffer_float +#define GL_DEPTH_COMPONENT32F_NV 0x8DAB +#define GL_DEPTH32F_STENCIL8_NV 0x8DAC +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD +#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF +#endif + +#ifndef GL_EXT_texture_compression_latc +#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 +#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71 +#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 +#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73 +#endif + +#ifndef GL_NV_transform_feedback +#define GL_BACK_PRIMARY_COLOR_NV 0x8C77 +#define GL_BACK_SECONDARY_COLOR_NV 0x8C78 +#define GL_TEXTURE_COORD_NV 0x8C79 +#define GL_CLIP_DISTANCE_NV 0x8C7A +#define GL_VERTEX_ID_NV 0x8C7B +#define GL_PRIMITIVE_ID_NV 0x8C7C +#define GL_GENERIC_ATTRIB_NV 0x8C7D +#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80 +#define GL_ACTIVE_VARYINGS_NV 0x8C81 +#define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82 +#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85 +#define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86 +#define GL_PRIMITIVES_GENERATED_NV 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88 +#define GL_RASTERIZER_DISCARD_NV 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_ATTRIBS_NV 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B +#define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C +#define GL_SEPARATE_ATTRIBS_NV 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F +#endif + +#ifndef GL_NV_geometry_program4 +#define GL_GEOMETRY_PROGRAM_NV 0x8C26 +#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27 +#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28 +#endif + +#ifndef GL_NV_gpu_program4 +#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET_NV 0x8905 +#define GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906 +#define GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907 +#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908 +#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909 +#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5 +#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6 +#endif + +#ifndef GL_NV_framebuffer_multisample_coverage +#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB +#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10 +#define GL_MAX_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8D57 +#define GL_MAX_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E11 +#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12 +#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E13 +#endif + +#ifndef GL_EXT_framebuffer_multisample +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 +#define GL_MAX_SAMPLES_EXT 0x8D57 +#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB +#endif + +#ifndef GL_EXT_framebuffer_blit +#define GL_READ_FRAMEBUFFER_EXT 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA +#endif + +#ifndef GL_EXT_texture_compression_rgtc +#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC +#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD +#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE +#endif + +/*************************************************************/ + +#include +#ifndef GL_VERSION_2_0 +/* GL type for program/shader text */ +typedef char GLchar; /* native character */ +#endif + +#ifndef GL_VERSION_1_5 +/* GL types for handling large vertex buffer objects */ +typedef ptrdiff_t GLintptr; +typedef ptrdiff_t GLsizeiptr; +#endif + +#ifndef GL_ARB_vertex_buffer_object +/* GL types for handling large vertex buffer objects */ +typedef ptrdiff_t GLintptrARB; +typedef ptrdiff_t GLsizeiptrARB; +#endif + +#ifndef GL_ARB_shader_objects +/* GL types for handling shader object handles and program/shader text */ +typedef char GLcharARB; /* native character */ +typedef unsigned int GLhandleARB; /* shader object handle */ +#endif + +/* GL types for "half" precision (s10e5) float data in host memory */ +#ifndef GL_ARB_half_float_pixel +typedef unsigned short GLhalfARB; +#endif + +#ifndef GL_NV_half_float +typedef unsigned short GLhalfNV; +#endif + +#ifndef GL_EXT_timer_query +#ifndef GL_COMPILER_LACKS_64BIT_INT +#if defined(__GNUC__) || defined(__arm) || defined(__IAR_SYSTEMS_ICC__) || defined(__ghs__) || defined(_WIN64) +typedef signed long long GLint64EXT; +typedef unsigned long long GLuint64EXT; +#else +typedef signed __int64 GLint64EXT; +typedef unsigned __int64 GLuint64EXT; +#endif +#endif +#endif + +#ifndef GL_VERSION_1_2 +#define GL_VERSION_1_2 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glBlendColor (GLclampf, GLclampf, GLclampf, GLclampf); +GLAPI void GLAPIENTRY glBlendEquation (GLenum); +GLAPI void GLAPIENTRY glDrawRangeElements (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glColorTable (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glColorTableParameterfv (GLenum, GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glColorTableParameteriv (GLenum, GLenum, const GLint *); +GLAPI void GLAPIENTRY glCopyColorTable (GLenum, GLenum, GLint, GLint, GLsizei); +GLAPI void GLAPIENTRY glGetColorTable (GLenum, GLenum, GLenum, GLvoid *); +GLAPI void GLAPIENTRY glGetColorTableParameterfv (GLenum, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetColorTableParameteriv (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glColorSubTable (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glCopyColorSubTable (GLenum, GLsizei, GLint, GLint, GLsizei); +GLAPI void GLAPIENTRY glConvolutionFilter1D (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glConvolutionFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glConvolutionParameterf (GLenum, GLenum, GLfloat); +GLAPI void GLAPIENTRY glConvolutionParameterfv (GLenum, GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glConvolutionParameteri (GLenum, GLenum, GLint); +GLAPI void GLAPIENTRY glConvolutionParameteriv (GLenum, GLenum, const GLint *); +GLAPI void GLAPIENTRY glCopyConvolutionFilter1D (GLenum, GLenum, GLint, GLint, GLsizei); +GLAPI void GLAPIENTRY glCopyConvolutionFilter2D (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei); +GLAPI void GLAPIENTRY glGetConvolutionFilter (GLenum, GLenum, GLenum, GLvoid *); +GLAPI void GLAPIENTRY glGetConvolutionParameterfv (GLenum, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetConvolutionParameteriv (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetSeparableFilter (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *); +GLAPI void GLAPIENTRY glSeparableFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *); +GLAPI void GLAPIENTRY glGetHistogram (GLenum, GLboolean, GLenum, GLenum, GLvoid *); +GLAPI void GLAPIENTRY glGetHistogramParameterfv (GLenum, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetHistogramParameteriv (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetMinmax (GLenum, GLboolean, GLenum, GLenum, GLvoid *); +GLAPI void GLAPIENTRY glGetMinmaxParameterfv (GLenum, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetMinmaxParameteriv (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glHistogram (GLenum, GLsizei, GLenum, GLboolean); +GLAPI void GLAPIENTRY glMinmax (GLenum, GLenum, GLboolean); +GLAPI void GLAPIENTRY glResetHistogram (GLenum); +GLAPI void GLAPIENTRY glResetMinmax (GLenum); +GLAPI void GLAPIENTRY glTexImage3D (GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glCopyTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +typedef void (GLAPIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode); +typedef void (GLAPIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); +typedef void (GLAPIENTRYP PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (GLAPIENTRYP PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRYP PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRYP PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); +typedef void (GLAPIENTRYP PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); +typedef void (GLAPIENTRYP PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRYP PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); +typedef void (GLAPIENTRYP PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); +typedef void (GLAPIENTRYP PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params); +typedef void (GLAPIENTRYP PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params); +typedef void (GLAPIENTRYP PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRYP PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); +typedef void (GLAPIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); +typedef void (GLAPIENTRYP PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); +typedef void (GLAPIENTRYP PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (GLAPIENTRYP PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (GLAPIENTRYP PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRYP PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRYP PFNGLRESETHISTOGRAMPROC) (GLenum target); +typedef void (GLAPIENTRYP PFNGLRESETMINMAXPROC) (GLenum target); +typedef void (GLAPIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#endif + +#ifndef GL_VERSION_1_3 +#define GL_VERSION_1_3 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glActiveTexture (GLenum); +GLAPI void GLAPIENTRY glClientActiveTexture (GLenum); +GLAPI void GLAPIENTRY glMultiTexCoord1d (GLenum, GLdouble); +GLAPI void GLAPIENTRY glMultiTexCoord1dv (GLenum, const GLdouble *); +GLAPI void GLAPIENTRY glMultiTexCoord1f (GLenum, GLfloat); +GLAPI void GLAPIENTRY glMultiTexCoord1fv (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glMultiTexCoord1i (GLenum, GLint); +GLAPI void GLAPIENTRY glMultiTexCoord1iv (GLenum, const GLint *); +GLAPI void GLAPIENTRY glMultiTexCoord1s (GLenum, GLshort); +GLAPI void GLAPIENTRY glMultiTexCoord1sv (GLenum, const GLshort *); +GLAPI void GLAPIENTRY glMultiTexCoord2d (GLenum, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glMultiTexCoord2dv (GLenum, const GLdouble *); +GLAPI void GLAPIENTRY glMultiTexCoord2f (GLenum, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glMultiTexCoord2fv (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glMultiTexCoord2i (GLenum, GLint, GLint); +GLAPI void GLAPIENTRY glMultiTexCoord2iv (GLenum, const GLint *); +GLAPI void GLAPIENTRY glMultiTexCoord2s (GLenum, GLshort, GLshort); +GLAPI void GLAPIENTRY glMultiTexCoord2sv (GLenum, const GLshort *); +GLAPI void GLAPIENTRY glMultiTexCoord3d (GLenum, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glMultiTexCoord3dv (GLenum, const GLdouble *); +GLAPI void GLAPIENTRY glMultiTexCoord3f (GLenum, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glMultiTexCoord3fv (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glMultiTexCoord3i (GLenum, GLint, GLint, GLint); +GLAPI void GLAPIENTRY glMultiTexCoord3iv (GLenum, const GLint *); +GLAPI void GLAPIENTRY glMultiTexCoord3s (GLenum, GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glMultiTexCoord3sv (GLenum, const GLshort *); +GLAPI void GLAPIENTRY glMultiTexCoord4d (GLenum, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glMultiTexCoord4dv (GLenum, const GLdouble *); +GLAPI void GLAPIENTRY glMultiTexCoord4f (GLenum, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glMultiTexCoord4fv (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glMultiTexCoord4i (GLenum, GLint, GLint, GLint, GLint); +GLAPI void GLAPIENTRY glMultiTexCoord4iv (GLenum, const GLint *); +GLAPI void GLAPIENTRY glMultiTexCoord4s (GLenum, GLshort, GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glMultiTexCoord4sv (GLenum, const GLshort *); +GLAPI void GLAPIENTRY glLoadTransposeMatrixf (const GLfloat *); +GLAPI void GLAPIENTRY glLoadTransposeMatrixd (const GLdouble *); +GLAPI void GLAPIENTRY glMultTransposeMatrixf (const GLfloat *); +GLAPI void GLAPIENTRY glMultTransposeMatrixd (const GLdouble *); +GLAPI void GLAPIENTRY glSampleCoverage (GLclampf, GLboolean); +GLAPI void GLAPIENTRY glCompressedTexImage3D (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glCompressedTexImage2D (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glCompressedTexImage1D (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glCompressedTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glCompressedTexSubImage2D (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glCompressedTexSubImage1D (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glGetCompressedTexImage (GLenum, GLint, GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture); +typedef void (GLAPIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat *m); +typedef void (GLAPIENTRYP PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble *m); +typedef void (GLAPIENTRYP PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat *m); +typedef void (GLAPIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble *m); +typedef void (GLAPIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert); +typedef void (GLAPIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img); +#endif + +#ifndef GL_VERSION_1_4 +#define GL_VERSION_1_4 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glBlendFuncSeparate (GLenum, GLenum, GLenum, GLenum); +GLAPI void GLAPIENTRY glFogCoordf (GLfloat); +GLAPI void GLAPIENTRY glFogCoordfv (const GLfloat *); +GLAPI void GLAPIENTRY glFogCoordd (GLdouble); +GLAPI void GLAPIENTRY glFogCoorddv (const GLdouble *); +GLAPI void GLAPIENTRY glFogCoordPointer (GLenum, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glMultiDrawArrays (GLenum, GLint *, GLsizei *, GLsizei); +GLAPI void GLAPIENTRY glMultiDrawElements (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei); +GLAPI void GLAPIENTRY glPointParameterf (GLenum, GLfloat); +GLAPI void GLAPIENTRY glPointParameterfv (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glPointParameteri (GLenum, GLint); +GLAPI void GLAPIENTRY glPointParameteriv (GLenum, const GLint *); +GLAPI void GLAPIENTRY glSecondaryColor3b (GLbyte, GLbyte, GLbyte); +GLAPI void GLAPIENTRY glSecondaryColor3bv (const GLbyte *); +GLAPI void GLAPIENTRY glSecondaryColor3d (GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glSecondaryColor3dv (const GLdouble *); +GLAPI void GLAPIENTRY glSecondaryColor3f (GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glSecondaryColor3fv (const GLfloat *); +GLAPI void GLAPIENTRY glSecondaryColor3i (GLint, GLint, GLint); +GLAPI void GLAPIENTRY glSecondaryColor3iv (const GLint *); +GLAPI void GLAPIENTRY glSecondaryColor3s (GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glSecondaryColor3sv (const GLshort *); +GLAPI void GLAPIENTRY glSecondaryColor3ub (GLubyte, GLubyte, GLubyte); +GLAPI void GLAPIENTRY glSecondaryColor3ubv (const GLubyte *); +GLAPI void GLAPIENTRY glSecondaryColor3ui (GLuint, GLuint, GLuint); +GLAPI void GLAPIENTRY glSecondaryColor3uiv (const GLuint *); +GLAPI void GLAPIENTRY glSecondaryColor3us (GLushort, GLushort, GLushort); +GLAPI void GLAPIENTRY glSecondaryColor3usv (const GLushort *); +GLAPI void GLAPIENTRY glSecondaryColorPointer (GLint, GLenum, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glWindowPos2d (GLdouble, GLdouble); +GLAPI void GLAPIENTRY glWindowPos2dv (const GLdouble *); +GLAPI void GLAPIENTRY glWindowPos2f (GLfloat, GLfloat); +GLAPI void GLAPIENTRY glWindowPos2fv (const GLfloat *); +GLAPI void GLAPIENTRY glWindowPos2i (GLint, GLint); +GLAPI void GLAPIENTRY glWindowPos2iv (const GLint *); +GLAPI void GLAPIENTRY glWindowPos2s (GLshort, GLshort); +GLAPI void GLAPIENTRY glWindowPos2sv (const GLshort *); +GLAPI void GLAPIENTRY glWindowPos3d (GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glWindowPos3dv (const GLdouble *); +GLAPI void GLAPIENTRY glWindowPos3f (GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glWindowPos3fv (const GLfloat *); +GLAPI void GLAPIENTRY glWindowPos3i (GLint, GLint, GLint); +GLAPI void GLAPIENTRY glWindowPos3iv (const GLint *); +GLAPI void GLAPIENTRY glWindowPos3s (GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glWindowPos3sv (const GLshort *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (GLAPIENTRYP PFNGLFOGCOORDFPROC) (GLfloat coord); +typedef void (GLAPIENTRYP PFNGLFOGCOORDFVPROC) (const GLfloat *coord); +typedef void (GLAPIENTRYP PFNGLFOGCOORDDPROC) (GLdouble coord); +typedef void (GLAPIENTRYP PFNGLFOGCOORDDVPROC) (const GLdouble *coord); +typedef void (GLAPIENTRYP PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); +typedef void (GLAPIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); +typedef void (GLAPIENTRYP PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRYP PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2DVPROC) (const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2FVPROC) (const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2IPROC) (GLint x, GLint y); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2IVPROC) (const GLint *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2SVPROC) (const GLshort *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3DVPROC) (const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3FVPROC) (const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3IVPROC) (const GLint *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3SVPROC) (const GLshort *v); +#endif + +#ifndef GL_VERSION_1_5 +#define GL_VERSION_1_5 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glGenQueries (GLsizei, GLuint *); +GLAPI void GLAPIENTRY glDeleteQueries (GLsizei, const GLuint *); +GLAPI GLboolean GLAPIENTRY glIsQuery (GLuint); +GLAPI void GLAPIENTRY glBeginQuery (GLenum, GLuint); +GLAPI void GLAPIENTRY glEndQuery (GLenum); +GLAPI void GLAPIENTRY glGetQueryiv (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetQueryObjectiv (GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetQueryObjectuiv (GLuint, GLenum, GLuint *); +GLAPI void GLAPIENTRY glBindBuffer (GLenum, GLuint); +GLAPI void GLAPIENTRY glDeleteBuffers (GLsizei, const GLuint *); +GLAPI void GLAPIENTRY glGenBuffers (GLsizei, GLuint *); +GLAPI GLboolean GLAPIENTRY glIsBuffer (GLuint); +GLAPI void GLAPIENTRY glBufferData (GLenum, GLsizeiptr, const GLvoid *, GLenum); +GLAPI void GLAPIENTRY glBufferSubData (GLenum, GLintptr, GLsizeiptr, const GLvoid *); +GLAPI void GLAPIENTRY glGetBufferSubData (GLenum, GLintptr, GLsizeiptr, GLvoid *); +GLAPI GLvoid* GLAPIENTRY glMapBuffer (GLenum, GLenum); +GLAPI GLboolean GLAPIENTRY glUnmapBuffer (GLenum); +GLAPI void GLAPIENTRY glGetBufferParameteriv (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetBufferPointerv (GLenum, GLenum, GLvoid* *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids); +typedef void (GLAPIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (GLAPIENTRYP PFNGLISQUERYPROC) (GLuint id); +typedef void (GLAPIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRYP PFNGLENDQUERYPROC) (GLenum target); +typedef void (GLAPIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params); +typedef void (GLAPIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); +typedef void (GLAPIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); +typedef void (GLAPIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); +typedef GLboolean (GLAPIENTRYP PFNGLISBUFFERPROC) (GLuint buffer); +typedef void (GLAPIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); +typedef void (GLAPIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); +typedef void (GLAPIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data); +typedef GLvoid* (GLAPIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); +typedef GLboolean (GLAPIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target); +typedef void (GLAPIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid* *params); +#endif + +#ifndef GL_VERSION_2_0 +#define GL_VERSION_2_0 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glBlendEquationSeparate (GLenum, GLenum); +GLAPI void GLAPIENTRY glDrawBuffers (GLsizei, const GLenum *); +GLAPI void GLAPIENTRY glStencilOpSeparate (GLenum, GLenum, GLenum, GLenum); +GLAPI void GLAPIENTRY glStencilFuncSeparate (GLenum, GLenum, GLint, GLuint); +GLAPI void GLAPIENTRY glStencilMaskSeparate (GLenum, GLuint); +GLAPI void GLAPIENTRY glAttachShader (GLuint, GLuint); +GLAPI void GLAPIENTRY glBindAttribLocation (GLuint, GLuint, const GLchar *); +GLAPI void GLAPIENTRY glCompileShader (GLuint); +GLAPI GLuint GLAPIENTRY glCreateProgram (void); +GLAPI GLuint GLAPIENTRY glCreateShader (GLenum); +GLAPI void GLAPIENTRY glDeleteProgram (GLuint); +GLAPI void GLAPIENTRY glDeleteShader (GLuint); +GLAPI void GLAPIENTRY glDetachShader (GLuint, GLuint); +GLAPI void GLAPIENTRY glDisableVertexAttribArray (GLuint); +GLAPI void GLAPIENTRY glEnableVertexAttribArray (GLuint); +GLAPI void GLAPIENTRY glGetActiveAttrib (GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *); +GLAPI void GLAPIENTRY glGetActiveUniform (GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *); +GLAPI void GLAPIENTRY glGetAttachedShaders (GLuint, GLsizei, GLsizei *, GLuint *); +GLAPI GLint GLAPIENTRY glGetAttribLocation (GLuint, const GLchar *); +GLAPI void GLAPIENTRY glGetProgramiv (GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetProgramInfoLog (GLuint, GLsizei, GLsizei *, GLchar *); +GLAPI void GLAPIENTRY glGetShaderiv (GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetShaderInfoLog (GLuint, GLsizei, GLsizei *, GLchar *); +GLAPI void GLAPIENTRY glGetShaderSource (GLuint, GLsizei, GLsizei *, GLchar *); +GLAPI GLint GLAPIENTRY glGetUniformLocation (GLuint, const GLchar *); +GLAPI void GLAPIENTRY glGetUniformfv (GLuint, GLint, GLfloat *); +GLAPI void GLAPIENTRY glGetUniformiv (GLuint, GLint, GLint *); +GLAPI void GLAPIENTRY glGetVertexAttribdv (GLuint, GLenum, GLdouble *); +GLAPI void GLAPIENTRY glGetVertexAttribfv (GLuint, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetVertexAttribiv (GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetVertexAttribPointerv (GLuint, GLenum, GLvoid* *); +GLAPI GLboolean GLAPIENTRY glIsProgram (GLuint); +GLAPI GLboolean GLAPIENTRY glIsShader (GLuint); +GLAPI void GLAPIENTRY glLinkProgram (GLuint); +GLAPI void GLAPIENTRY glShaderSource (GLuint, GLsizei, const GLchar* *, const GLint *); +GLAPI void GLAPIENTRY glUseProgram (GLuint); +GLAPI void GLAPIENTRY glUniform1f (GLint, GLfloat); +GLAPI void GLAPIENTRY glUniform2f (GLint, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glUniform3f (GLint, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glUniform4f (GLint, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glUniform1i (GLint, GLint); +GLAPI void GLAPIENTRY glUniform2i (GLint, GLint, GLint); +GLAPI void GLAPIENTRY glUniform3i (GLint, GLint, GLint, GLint); +GLAPI void GLAPIENTRY glUniform4i (GLint, GLint, GLint, GLint, GLint); +GLAPI void GLAPIENTRY glUniform1fv (GLint, GLsizei, const GLfloat *); +GLAPI void GLAPIENTRY glUniform2fv (GLint, GLsizei, const GLfloat *); +GLAPI void GLAPIENTRY glUniform3fv (GLint, GLsizei, const GLfloat *); +GLAPI void GLAPIENTRY glUniform4fv (GLint, GLsizei, const GLfloat *); +GLAPI void GLAPIENTRY glUniform1iv (GLint, GLsizei, const GLint *); +GLAPI void GLAPIENTRY glUniform2iv (GLint, GLsizei, const GLint *); +GLAPI void GLAPIENTRY glUniform3iv (GLint, GLsizei, const GLint *); +GLAPI void GLAPIENTRY glUniform4iv (GLint, GLsizei, const GLint *); +GLAPI void GLAPIENTRY glUniformMatrix2fv (GLint, GLsizei, GLboolean, const GLfloat *); +GLAPI void GLAPIENTRY glUniformMatrix3fv (GLint, GLsizei, GLboolean, const GLfloat *); +GLAPI void GLAPIENTRY glUniformMatrix4fv (GLint, GLsizei, GLboolean, const GLfloat *); +GLAPI void GLAPIENTRY glValidateProgram (GLuint); +GLAPI void GLAPIENTRY glVertexAttrib1d (GLuint, GLdouble); +GLAPI void GLAPIENTRY glVertexAttrib1dv (GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glVertexAttrib1f (GLuint, GLfloat); +GLAPI void GLAPIENTRY glVertexAttrib1fv (GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glVertexAttrib1s (GLuint, GLshort); +GLAPI void GLAPIENTRY glVertexAttrib1sv (GLuint, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttrib2d (GLuint, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glVertexAttrib2dv (GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glVertexAttrib2f (GLuint, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glVertexAttrib2fv (GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glVertexAttrib2s (GLuint, GLshort, GLshort); +GLAPI void GLAPIENTRY glVertexAttrib2sv (GLuint, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttrib3d (GLuint, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glVertexAttrib3dv (GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glVertexAttrib3f (GLuint, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glVertexAttrib3fv (GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glVertexAttrib3s (GLuint, GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glVertexAttrib3sv (GLuint, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttrib4Nbv (GLuint, const GLbyte *); +GLAPI void GLAPIENTRY glVertexAttrib4Niv (GLuint, const GLint *); +GLAPI void GLAPIENTRY glVertexAttrib4Nsv (GLuint, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttrib4Nub (GLuint, GLubyte, GLubyte, GLubyte, GLubyte); +GLAPI void GLAPIENTRY glVertexAttrib4Nubv (GLuint, const GLubyte *); +GLAPI void GLAPIENTRY glVertexAttrib4Nuiv (GLuint, const GLuint *); +GLAPI void GLAPIENTRY glVertexAttrib4Nusv (GLuint, const GLushort *); +GLAPI void GLAPIENTRY glVertexAttrib4bv (GLuint, const GLbyte *); +GLAPI void GLAPIENTRY glVertexAttrib4d (GLuint, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glVertexAttrib4dv (GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glVertexAttrib4f (GLuint, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glVertexAttrib4fv (GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glVertexAttrib4iv (GLuint, const GLint *); +GLAPI void GLAPIENTRY glVertexAttrib4s (GLuint, GLshort, GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glVertexAttrib4sv (GLuint, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttrib4ubv (GLuint, const GLubyte *); +GLAPI void GLAPIENTRY glVertexAttrib4uiv (GLuint, const GLuint *); +GLAPI void GLAPIENTRY glVertexAttrib4usv (GLuint, const GLushort *); +GLAPI void GLAPIENTRY glVertexAttribPointer (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAPIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs); +typedef void (GLAPIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (GLAPIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); +typedef void (GLAPIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask); +typedef void (GLAPIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (GLAPIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name); +typedef void (GLAPIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader); +typedef GLuint (GLAPIENTRYP PFNGLCREATEPROGRAMPROC) (void); +typedef GLuint (GLAPIENTRYP PFNGLCREATESHADERPROC) (GLenum type); +typedef void (GLAPIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRYP PFNGLDELETESHADERPROC) (GLuint shader); +typedef void (GLAPIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (GLAPIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef void (GLAPIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef void (GLAPIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +typedef void (GLAPIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +typedef void (GLAPIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj); +typedef GLint (GLAPIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (GLAPIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (GLAPIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); +typedef GLint (GLAPIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (GLAPIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble *params); +typedef void (GLAPIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, GLvoid* *pointer); +typedef GLboolean (GLAPIENTRYP PFNGLISPROGRAMPROC) (GLuint program); +typedef GLboolean (GLAPIENTRYP PFNGLISSHADERPROC) (GLuint shader); +typedef void (GLAPIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length); +typedef void (GLAPIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); +typedef void (GLAPIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAPIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAPIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAPIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0); +typedef void (GLAPIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); +typedef void (GLAPIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAPIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAPIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GLAPIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_VERSION_2_1 +#define GL_VERSION_2_1 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void GLAPIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void GLAPIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void GLAPIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void GLAPIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void GLAPIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +#endif + +#ifndef GL_ARB_multitexture +#define GL_ARB_multitexture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glActiveTextureARB (GLenum); +GLAPI void GLAPIENTRY glClientActiveTextureARB (GLenum); +GLAPI void GLAPIENTRY glMultiTexCoord1dARB (GLenum, GLdouble); +GLAPI void GLAPIENTRY glMultiTexCoord1dvARB (GLenum, const GLdouble *); +GLAPI void GLAPIENTRY glMultiTexCoord1fARB (GLenum, GLfloat); +GLAPI void GLAPIENTRY glMultiTexCoord1fvARB (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glMultiTexCoord1iARB (GLenum, GLint); +GLAPI void GLAPIENTRY glMultiTexCoord1ivARB (GLenum, const GLint *); +GLAPI void GLAPIENTRY glMultiTexCoord1sARB (GLenum, GLshort); +GLAPI void GLAPIENTRY glMultiTexCoord1svARB (GLenum, const GLshort *); +GLAPI void GLAPIENTRY glMultiTexCoord2dARB (GLenum, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glMultiTexCoord2dvARB (GLenum, const GLdouble *); +GLAPI void GLAPIENTRY glMultiTexCoord2fARB (GLenum, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glMultiTexCoord2fvARB (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glMultiTexCoord2iARB (GLenum, GLint, GLint); +GLAPI void GLAPIENTRY glMultiTexCoord2ivARB (GLenum, const GLint *); +GLAPI void GLAPIENTRY glMultiTexCoord2sARB (GLenum, GLshort, GLshort); +GLAPI void GLAPIENTRY glMultiTexCoord2svARB (GLenum, const GLshort *); +GLAPI void GLAPIENTRY glMultiTexCoord3dARB (GLenum, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glMultiTexCoord3dvARB (GLenum, const GLdouble *); +GLAPI void GLAPIENTRY glMultiTexCoord3fARB (GLenum, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glMultiTexCoord3fvARB (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glMultiTexCoord3iARB (GLenum, GLint, GLint, GLint); +GLAPI void GLAPIENTRY glMultiTexCoord3ivARB (GLenum, const GLint *); +GLAPI void GLAPIENTRY glMultiTexCoord3sARB (GLenum, GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glMultiTexCoord3svARB (GLenum, const GLshort *); +GLAPI void GLAPIENTRY glMultiTexCoord4dARB (GLenum, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glMultiTexCoord4dvARB (GLenum, const GLdouble *); +GLAPI void GLAPIENTRY glMultiTexCoord4fARB (GLenum, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glMultiTexCoord4fvARB (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glMultiTexCoord4iARB (GLenum, GLint, GLint, GLint, GLint); +GLAPI void GLAPIENTRY glMultiTexCoord4ivARB (GLenum, const GLint *); +GLAPI void GLAPIENTRY glMultiTexCoord4sARB (GLenum, GLshort, GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glMultiTexCoord4svARB (GLenum, const GLshort *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (GLAPIENTRYP PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v); +#endif + +#ifndef GL_ARB_transpose_matrix +#define GL_ARB_transpose_matrix 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glLoadTransposeMatrixfARB (const GLfloat *); +GLAPI void GLAPIENTRY glLoadTransposeMatrixdARB (const GLdouble *); +GLAPI void GLAPIENTRY glMultTransposeMatrixfARB (const GLfloat *); +GLAPI void GLAPIENTRY glMultTransposeMatrixdARB (const GLdouble *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); +typedef void (GLAPIENTRYP PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); +typedef void (GLAPIENTRYP PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); +typedef void (GLAPIENTRYP PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); +#endif + +#ifndef GL_ARB_multisample +#define GL_ARB_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glSampleCoverageARB (GLclampf, GLboolean); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert); +#endif + +#ifndef GL_ARB_texture_env_add +#define GL_ARB_texture_env_add 1 +#endif + +#ifndef GL_ARB_texture_cube_map +#define GL_ARB_texture_cube_map 1 +#endif + +#ifndef GL_ARB_texture_compression +#define GL_ARB_texture_compression 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glCompressedTexImage3DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glCompressedTexImage2DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glCompressedTexImage1DARB (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glCompressedTexSubImage3DARB (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glCompressedTexSubImage2DARB (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glCompressedTexSubImage1DARB (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glGetCompressedTexImageARB (GLenum, GLint, GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, GLvoid *img); +#endif + +#ifndef GL_ARB_texture_border_clamp +#define GL_ARB_texture_border_clamp 1 +#endif + +#ifndef GL_ARB_point_parameters +#define GL_ARB_point_parameters 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glPointParameterfARB (GLenum, GLfloat); +GLAPI void GLAPIENTRY glPointParameterfvARB (GLenum, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRYP PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat *params); +#endif + +#ifndef GL_ARB_vertex_blend +#define GL_ARB_vertex_blend 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glWeightbvARB (GLint, const GLbyte *); +GLAPI void GLAPIENTRY glWeightsvARB (GLint, const GLshort *); +GLAPI void GLAPIENTRY glWeightivARB (GLint, const GLint *); +GLAPI void GLAPIENTRY glWeightfvARB (GLint, const GLfloat *); +GLAPI void GLAPIENTRY glWeightdvARB (GLint, const GLdouble *); +GLAPI void GLAPIENTRY glWeightubvARB (GLint, const GLubyte *); +GLAPI void GLAPIENTRY glWeightusvARB (GLint, const GLushort *); +GLAPI void GLAPIENTRY glWeightuivARB (GLint, const GLuint *); +GLAPI void GLAPIENTRY glWeightPointerARB (GLint, GLenum, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glVertexBlendARB (GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLWEIGHTBVARBPROC) (GLint size, const GLbyte *weights); +typedef void (GLAPIENTRYP PFNGLWEIGHTSVARBPROC) (GLint size, const GLshort *weights); +typedef void (GLAPIENTRYP PFNGLWEIGHTIVARBPROC) (GLint size, const GLint *weights); +typedef void (GLAPIENTRYP PFNGLWEIGHTFVARBPROC) (GLint size, const GLfloat *weights); +typedef void (GLAPIENTRYP PFNGLWEIGHTDVARBPROC) (GLint size, const GLdouble *weights); +typedef void (GLAPIENTRYP PFNGLWEIGHTUBVARBPROC) (GLint size, const GLubyte *weights); +typedef void (GLAPIENTRYP PFNGLWEIGHTUSVARBPROC) (GLint size, const GLushort *weights); +typedef void (GLAPIENTRYP PFNGLWEIGHTUIVARBPROC) (GLint size, const GLuint *weights); +typedef void (GLAPIENTRYP PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRYP PFNGLVERTEXBLENDARBPROC) (GLint count); +#endif + +#ifndef GL_ARB_matrix_palette +#define GL_ARB_matrix_palette 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glCurrentPaletteMatrixARB (GLint); +GLAPI void GLAPIENTRY glMatrixIndexubvARB (GLint, const GLubyte *); +GLAPI void GLAPIENTRY glMatrixIndexusvARB (GLint, const GLushort *); +GLAPI void GLAPIENTRY glMatrixIndexuivARB (GLint, const GLuint *); +GLAPI void GLAPIENTRY glMatrixIndexPointerARB (GLint, GLenum, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index); +typedef void (GLAPIENTRYP PFNGLMATRIXINDEXUBVARBPROC) (GLint size, const GLubyte *indices); +typedef void (GLAPIENTRYP PFNGLMATRIXINDEXUSVARBPROC) (GLint size, const GLushort *indices); +typedef void (GLAPIENTRYP PFNGLMATRIXINDEXUIVARBPROC) (GLint size, const GLuint *indices); +typedef void (GLAPIENTRYP PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_ARB_texture_env_combine +#define GL_ARB_texture_env_combine 1 +#endif + +#ifndef GL_ARB_texture_env_crossbar +#define GL_ARB_texture_env_crossbar 1 +#endif + +#ifndef GL_ARB_texture_env_dot3 +#define GL_ARB_texture_env_dot3 1 +#endif + +#ifndef GL_ARB_texture_mirrored_repeat +#define GL_ARB_texture_mirrored_repeat 1 +#endif + +#ifndef GL_ARB_depth_texture +#define GL_ARB_depth_texture 1 +#endif + +#ifndef GL_ARB_shadow +#define GL_ARB_shadow 1 +#endif + +#ifndef GL_ARB_shadow_ambient +#define GL_ARB_shadow_ambient 1 +#endif + +#ifndef GL_ARB_window_pos +#define GL_ARB_window_pos 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glWindowPos2dARB (GLdouble, GLdouble); +GLAPI void GLAPIENTRY glWindowPos2dvARB (const GLdouble *); +GLAPI void GLAPIENTRY glWindowPos2fARB (GLfloat, GLfloat); +GLAPI void GLAPIENTRY glWindowPos2fvARB (const GLfloat *); +GLAPI void GLAPIENTRY glWindowPos2iARB (GLint, GLint); +GLAPI void GLAPIENTRY glWindowPos2ivARB (const GLint *); +GLAPI void GLAPIENTRY glWindowPos2sARB (GLshort, GLshort); +GLAPI void GLAPIENTRY glWindowPos2svARB (const GLshort *); +GLAPI void GLAPIENTRY glWindowPos3dARB (GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glWindowPos3dvARB (const GLdouble *); +GLAPI void GLAPIENTRY glWindowPos3fARB (GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glWindowPos3fvARB (const GLfloat *); +GLAPI void GLAPIENTRY glWindowPos3iARB (GLint, GLint, GLint); +GLAPI void GLAPIENTRY glWindowPos3ivARB (const GLint *); +GLAPI void GLAPIENTRY glWindowPos3sARB (GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glWindowPos3svARB (const GLshort *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2DVARBPROC) (const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2FVARBPROC) (const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2IVARBPROC) (const GLint *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2SVARBPROC) (const GLshort *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3DVARBPROC) (const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3FVARBPROC) (const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3IVARBPROC) (const GLint *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3SVARBPROC) (const GLshort *v); +#endif + +#ifndef GL_ARB_vertex_program +#define GL_ARB_vertex_program 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glVertexAttrib1dARB (GLuint, GLdouble); +GLAPI void GLAPIENTRY glVertexAttrib1dvARB (GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glVertexAttrib1fARB (GLuint, GLfloat); +GLAPI void GLAPIENTRY glVertexAttrib1fvARB (GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glVertexAttrib1sARB (GLuint, GLshort); +GLAPI void GLAPIENTRY glVertexAttrib1svARB (GLuint, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttrib2dARB (GLuint, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glVertexAttrib2dvARB (GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glVertexAttrib2fARB (GLuint, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glVertexAttrib2fvARB (GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glVertexAttrib2sARB (GLuint, GLshort, GLshort); +GLAPI void GLAPIENTRY glVertexAttrib2svARB (GLuint, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttrib3dARB (GLuint, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glVertexAttrib3dvARB (GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glVertexAttrib3fARB (GLuint, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glVertexAttrib3fvARB (GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glVertexAttrib3sARB (GLuint, GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glVertexAttrib3svARB (GLuint, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttrib4NbvARB (GLuint, const GLbyte *); +GLAPI void GLAPIENTRY glVertexAttrib4NivARB (GLuint, const GLint *); +GLAPI void GLAPIENTRY glVertexAttrib4NsvARB (GLuint, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttrib4NubARB (GLuint, GLubyte, GLubyte, GLubyte, GLubyte); +GLAPI void GLAPIENTRY glVertexAttrib4NubvARB (GLuint, const GLubyte *); +GLAPI void GLAPIENTRY glVertexAttrib4NuivARB (GLuint, const GLuint *); +GLAPI void GLAPIENTRY glVertexAttrib4NusvARB (GLuint, const GLushort *); +GLAPI void GLAPIENTRY glVertexAttrib4bvARB (GLuint, const GLbyte *); +GLAPI void GLAPIENTRY glVertexAttrib4dARB (GLuint, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glVertexAttrib4dvARB (GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glVertexAttrib4fARB (GLuint, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glVertexAttrib4fvARB (GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glVertexAttrib4ivARB (GLuint, const GLint *); +GLAPI void GLAPIENTRY glVertexAttrib4sARB (GLuint, GLshort, GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glVertexAttrib4svARB (GLuint, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttrib4ubvARB (GLuint, const GLubyte *); +GLAPI void GLAPIENTRY glVertexAttrib4uivARB (GLuint, const GLuint *); +GLAPI void GLAPIENTRY glVertexAttrib4usvARB (GLuint, const GLushort *); +GLAPI void GLAPIENTRY glVertexAttribPointerARB (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glEnableVertexAttribArrayARB (GLuint); +GLAPI void GLAPIENTRY glDisableVertexAttribArrayARB (GLuint); +GLAPI void GLAPIENTRY glProgramStringARB (GLenum, GLenum, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glBindProgramARB (GLenum, GLuint); +GLAPI void GLAPIENTRY glDeleteProgramsARB (GLsizei, const GLuint *); +GLAPI void GLAPIENTRY glGenProgramsARB (GLsizei, GLuint *); +GLAPI void GLAPIENTRY glProgramEnvParameter4dARB (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glProgramEnvParameter4dvARB (GLenum, GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glProgramEnvParameter4fARB (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glProgramEnvParameter4fvARB (GLenum, GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glProgramLocalParameter4dARB (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glProgramLocalParameter4dvARB (GLenum, GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glProgramLocalParameter4fARB (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glProgramLocalParameter4fvARB (GLenum, GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glGetProgramEnvParameterdvARB (GLenum, GLuint, GLdouble *); +GLAPI void GLAPIENTRY glGetProgramEnvParameterfvARB (GLenum, GLuint, GLfloat *); +GLAPI void GLAPIENTRY glGetProgramLocalParameterdvARB (GLenum, GLuint, GLdouble *); +GLAPI void GLAPIENTRY glGetProgramLocalParameterfvARB (GLenum, GLuint, GLfloat *); +GLAPI void GLAPIENTRY glGetProgramivARB (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetProgramStringARB (GLenum, GLenum, GLvoid *); +GLAPI void GLAPIENTRY glGetVertexAttribdvARB (GLuint, GLenum, GLdouble *); +GLAPI void GLAPIENTRY glGetVertexAttribfvARB (GLuint, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetVertexAttribivARB (GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetVertexAttribPointervARB (GLuint, GLenum, GLvoid* *); +GLAPI GLboolean GLAPIENTRY glIsProgramARB (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRYP PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); +typedef void (GLAPIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); +typedef void (GLAPIENTRYP PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const GLvoid *string); +typedef void (GLAPIENTRYP PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program); +typedef void (GLAPIENTRYP PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs); +typedef void (GLAPIENTRYP PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs); +typedef void (GLAPIENTRYP PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRYP PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params); +typedef void (GLAPIENTRYP PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRYP PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRYP PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params); +typedef void (GLAPIENTRYP PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRYP PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, GLvoid *string); +typedef void (GLAPIENTRYP PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble *params); +typedef void (GLAPIENTRYP PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid* *pointer); +typedef GLboolean (GLAPIENTRYP PFNGLISPROGRAMARBPROC) (GLuint program); +#endif + +#ifndef GL_ARB_fragment_program +#define GL_ARB_fragment_program 1 +/* All ARB_fragment_program entry points are shared with ARB_vertex_program. */ +#endif + +#ifndef GL_ARB_vertex_buffer_object +#define GL_ARB_vertex_buffer_object 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glBindBufferARB (GLenum, GLuint); +GLAPI void GLAPIENTRY glDeleteBuffersARB (GLsizei, const GLuint *); +GLAPI void GLAPIENTRY glGenBuffersARB (GLsizei, GLuint *); +GLAPI GLboolean GLAPIENTRY glIsBufferARB (GLuint); +GLAPI void GLAPIENTRY glBufferDataARB (GLenum, GLsizeiptrARB, const GLvoid *, GLenum); +GLAPI void GLAPIENTRY glBufferSubDataARB (GLenum, GLintptrARB, GLsizeiptrARB, const GLvoid *); +GLAPI void GLAPIENTRY glGetBufferSubDataARB (GLenum, GLintptrARB, GLsizeiptrARB, GLvoid *); +GLAPI GLvoid* GLAPIENTRY glMapBufferARB (GLenum, GLenum); +GLAPI GLboolean GLAPIENTRY glUnmapBufferARB (GLenum); +GLAPI void GLAPIENTRY glGetBufferParameterivARB (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetBufferPointervARB (GLenum, GLenum, GLvoid* *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer); +typedef void (GLAPIENTRYP PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers); +typedef void (GLAPIENTRYP PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers); +typedef GLboolean (GLAPIENTRYP PFNGLISBUFFERARBPROC) (GLuint buffer); +typedef void (GLAPIENTRYP PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); +typedef void (GLAPIENTRYP PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data); +typedef void (GLAPIENTRYP PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data); +typedef GLvoid* (GLAPIENTRYP PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access); +typedef GLboolean (GLAPIENTRYP PFNGLUNMAPBUFFERARBPROC) (GLenum target); +typedef void (GLAPIENTRYP PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid* *params); +#endif + +#ifndef GL_ARB_occlusion_query +#define GL_ARB_occlusion_query 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glGenQueriesARB (GLsizei, GLuint *); +GLAPI void GLAPIENTRY glDeleteQueriesARB (GLsizei, const GLuint *); +GLAPI GLboolean GLAPIENTRY glIsQueryARB (GLuint); +GLAPI void GLAPIENTRY glBeginQueryARB (GLenum, GLuint); +GLAPI void GLAPIENTRY glEndQueryARB (GLenum); +GLAPI void GLAPIENTRY glGetQueryivARB (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetQueryObjectivARB (GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetQueryObjectuivARB (GLuint, GLenum, GLuint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint *ids); +typedef void (GLAPIENTRYP PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (GLAPIENTRYP PFNGLISQUERYARBPROC) (GLuint id); +typedef void (GLAPIENTRYP PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRYP PFNGLENDQUERYARBPROC) (GLenum target); +typedef void (GLAPIENTRYP PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint *params); +#endif + +#ifndef GL_ARB_shader_objects +#define GL_ARB_shader_objects 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glDeleteObjectARB (GLhandleARB); +GLAPI GLhandleARB GLAPIENTRY glGetHandleARB (GLenum); +GLAPI void GLAPIENTRY glDetachObjectARB (GLhandleARB, GLhandleARB); +GLAPI GLhandleARB GLAPIENTRY glCreateShaderObjectARB (GLenum); +GLAPI void GLAPIENTRY glShaderSourceARB (GLhandleARB, GLsizei, const GLcharARB* *, const GLint *); +GLAPI void GLAPIENTRY glCompileShaderARB (GLhandleARB); +GLAPI GLhandleARB GLAPIENTRY glCreateProgramObjectARB (void); +GLAPI void GLAPIENTRY glAttachObjectARB (GLhandleARB, GLhandleARB); +GLAPI void GLAPIENTRY glLinkProgramARB (GLhandleARB); +GLAPI void GLAPIENTRY glUseProgramObjectARB (GLhandleARB); +GLAPI void GLAPIENTRY glValidateProgramARB (GLhandleARB); +GLAPI void GLAPIENTRY glUniform1fARB (GLint, GLfloat); +GLAPI void GLAPIENTRY glUniform2fARB (GLint, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glUniform3fARB (GLint, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glUniform4fARB (GLint, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glUniform1iARB (GLint, GLint); +GLAPI void GLAPIENTRY glUniform2iARB (GLint, GLint, GLint); +GLAPI void GLAPIENTRY glUniform3iARB (GLint, GLint, GLint, GLint); +GLAPI void GLAPIENTRY glUniform4iARB (GLint, GLint, GLint, GLint, GLint); +GLAPI void GLAPIENTRY glUniform1fvARB (GLint, GLsizei, const GLfloat *); +GLAPI void GLAPIENTRY glUniform2fvARB (GLint, GLsizei, const GLfloat *); +GLAPI void GLAPIENTRY glUniform3fvARB (GLint, GLsizei, const GLfloat *); +GLAPI void GLAPIENTRY glUniform4fvARB (GLint, GLsizei, const GLfloat *); +GLAPI void GLAPIENTRY glUniform1ivARB (GLint, GLsizei, const GLint *); +GLAPI void GLAPIENTRY glUniform2ivARB (GLint, GLsizei, const GLint *); +GLAPI void GLAPIENTRY glUniform3ivARB (GLint, GLsizei, const GLint *); +GLAPI void GLAPIENTRY glUniform4ivARB (GLint, GLsizei, const GLint *); +GLAPI void GLAPIENTRY glUniformMatrix2fvARB (GLint, GLsizei, GLboolean, const GLfloat *); +GLAPI void GLAPIENTRY glUniformMatrix3fvARB (GLint, GLsizei, GLboolean, const GLfloat *); +GLAPI void GLAPIENTRY glUniformMatrix4fvARB (GLint, GLsizei, GLboolean, const GLfloat *); +GLAPI void GLAPIENTRY glGetObjectParameterfvARB (GLhandleARB, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetObjectParameterivARB (GLhandleARB, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetInfoLogARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *); +GLAPI void GLAPIENTRY glGetAttachedObjectsARB (GLhandleARB, GLsizei, GLsizei *, GLhandleARB *); +GLAPI GLint GLAPIENTRY glGetUniformLocationARB (GLhandleARB, const GLcharARB *); +GLAPI void GLAPIENTRY glGetActiveUniformARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *); +GLAPI void GLAPIENTRY glGetUniformfvARB (GLhandleARB, GLint, GLfloat *); +GLAPI void GLAPIENTRY glGetUniformivARB (GLhandleARB, GLint, GLint *); +GLAPI void GLAPIENTRY glGetShaderSourceARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj); +typedef GLhandleARB (GLAPIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname); +typedef void (GLAPIENTRYP PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj); +typedef GLhandleARB (GLAPIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType); +typedef void (GLAPIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length); +typedef void (GLAPIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj); +typedef GLhandleARB (GLAPIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void); +typedef void (GLAPIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj); +typedef void (GLAPIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj); +typedef void (GLAPIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj); +typedef void (GLAPIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj); +typedef void (GLAPIENTRYP PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0); +typedef void (GLAPIENTRYP PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAPIENTRYP PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAPIENTRYP PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAPIENTRYP PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0); +typedef void (GLAPIENTRYP PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1); +typedef void (GLAPIENTRYP PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAPIENTRYP PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAPIENTRYP PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GLAPIENTRYP PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); +typedef void (GLAPIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj); +typedef GLint (GLAPIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name); +typedef void (GLAPIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); +typedef void (GLAPIENTRYP PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source); +#endif + +#ifndef GL_ARB_vertex_shader +#define GL_ARB_vertex_shader 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glBindAttribLocationARB (GLhandleARB, GLuint, const GLcharARB *); +GLAPI void GLAPIENTRY glGetActiveAttribARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *); +GLAPI GLint GLAPIENTRY glGetAttribLocationARB (GLhandleARB, const GLcharARB *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name); +typedef void (GLAPIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); +typedef GLint (GLAPIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name); +#endif + +#ifndef GL_ARB_fragment_shader +#define GL_ARB_fragment_shader 1 +#endif + +#ifndef GL_ARB_shading_language_100 +#define GL_ARB_shading_language_100 1 +#endif + +#ifndef GL_ARB_texture_non_power_of_two +#define GL_ARB_texture_non_power_of_two 1 +#endif + +#ifndef GL_ARB_point_sprite +#define GL_ARB_point_sprite 1 +#endif + +#ifndef GL_ARB_fragment_program_shadow +#define GL_ARB_fragment_program_shadow 1 +#endif + +#ifndef GL_ARB_draw_buffers +#define GL_ARB_draw_buffers 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glDrawBuffersARB (GLsizei, const GLenum *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum *bufs); +#endif + +#ifndef GL_ARB_texture_rectangle +#define GL_ARB_texture_rectangle 1 +#endif + +#ifndef GL_ARB_color_buffer_float +#define GL_ARB_color_buffer_float 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glClampColorARB (GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp); +#endif + +#ifndef GL_ARB_half_float_pixel +#define GL_ARB_half_float_pixel 1 +#endif + +#ifndef GL_ARB_texture_float +#define GL_ARB_texture_float 1 +#endif + +#ifndef GL_ARB_pixel_buffer_object +#define GL_ARB_pixel_buffer_object 1 +#endif + +#ifndef GL_EXT_abgr +#define GL_EXT_abgr 1 +#endif + +#ifndef GL_EXT_blend_color +#define GL_EXT_blend_color 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glBlendColorEXT (GLclampf, GLclampf, GLclampf, GLclampf); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +#endif + +#ifndef GL_EXT_polygon_offset +#define GL_EXT_polygon_offset 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glPolygonOffsetEXT (GLfloat, GLfloat); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias); +#endif + +#ifndef GL_EXT_texture +#define GL_EXT_texture 1 +#endif + +#ifndef GL_EXT_texture3D +#define GL_EXT_texture3D 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glTexImage3DEXT (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRYP PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); +#endif + +#ifndef GL_SGIS_texture_filter4 +#define GL_SGIS_texture_filter4 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glGetTexFilterFuncSGIS (GLenum, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glTexFilterFuncSGIS (GLenum, GLenum, GLsizei, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat *weights); +typedef void (GLAPIENTRYP PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights); +#endif + +#ifndef GL_EXT_subtexture +#define GL_EXT_subtexture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glTexSubImage1DEXT (GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRYP PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +#endif + +#ifndef GL_EXT_copy_texture +#define GL_EXT_copy_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glCopyTexImage1DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint); +GLAPI void GLAPIENTRY glCopyTexImage2DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint); +GLAPI void GLAPIENTRY glCopyTexSubImage1DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei); +GLAPI void GLAPIENTRY glCopyTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +GLAPI void GLAPIENTRY glCopyTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAPIENTRYP PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAPIENTRYP PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRYP PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRYP PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#endif + +#ifndef GL_EXT_histogram +#define GL_EXT_histogram 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glGetHistogramEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *); +GLAPI void GLAPIENTRY glGetHistogramParameterfvEXT (GLenum, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetHistogramParameterivEXT (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetMinmaxEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *); +GLAPI void GLAPIENTRY glGetMinmaxParameterfvEXT (GLenum, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetMinmaxParameterivEXT (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glHistogramEXT (GLenum, GLsizei, GLenum, GLboolean); +GLAPI void GLAPIENTRY glMinmaxEXT (GLenum, GLenum, GLboolean); +GLAPI void GLAPIENTRY glResetHistogramEXT (GLenum); +GLAPI void GLAPIENTRY glResetMinmaxEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (GLAPIENTRYP PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (GLAPIENTRYP PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRYP PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRYP PFNGLRESETHISTOGRAMEXTPROC) (GLenum target); +typedef void (GLAPIENTRYP PFNGLRESETMINMAXEXTPROC) (GLenum target); +#endif + +#ifndef GL_EXT_convolution +#define GL_EXT_convolution 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glConvolutionFilter1DEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glConvolutionFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glConvolutionParameterfEXT (GLenum, GLenum, GLfloat); +GLAPI void GLAPIENTRY glConvolutionParameterfvEXT (GLenum, GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glConvolutionParameteriEXT (GLenum, GLenum, GLint); +GLAPI void GLAPIENTRY glConvolutionParameterivEXT (GLenum, GLenum, const GLint *); +GLAPI void GLAPIENTRY glCopyConvolutionFilter1DEXT (GLenum, GLenum, GLint, GLint, GLsizei); +GLAPI void GLAPIENTRY glCopyConvolutionFilter2DEXT (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei); +GLAPI void GLAPIENTRY glGetConvolutionFilterEXT (GLenum, GLenum, GLenum, GLvoid *); +GLAPI void GLAPIENTRY glGetConvolutionParameterfvEXT (GLenum, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetConvolutionParameterivEXT (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetSeparableFilterEXT (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *); +GLAPI void GLAPIENTRY glSeparableFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); +typedef void (GLAPIENTRYP PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); +typedef void (GLAPIENTRYP PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params); +typedef void (GLAPIENTRYP PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params); +typedef void (GLAPIENTRYP PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRYP PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); +typedef void (GLAPIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); +typedef void (GLAPIENTRYP PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); +#endif + +#ifndef GL_EXT_color_matrix +#define GL_EXT_color_matrix 1 +#endif + +#ifndef GL_SGI_color_table +#define GL_SGI_color_table 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glColorTableSGI (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glColorTableParameterfvSGI (GLenum, GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glColorTableParameterivSGI (GLenum, GLenum, const GLint *); +GLAPI void GLAPIENTRY glCopyColorTableSGI (GLenum, GLenum, GLint, GLint, GLsizei); +GLAPI void GLAPIENTRY glGetColorTableSGI (GLenum, GLenum, GLenum, GLvoid *); +GLAPI void GLAPIENTRY glGetColorTableParameterfvSGI (GLenum, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetColorTableParameterivSGI (GLenum, GLenum, GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (GLAPIENTRYP PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRYP PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRYP PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); +typedef void (GLAPIENTRYP PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint *params); +#endif + +#ifndef GL_SGIX_pixel_texture +#define GL_SGIX_pixel_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glPixelTexGenSGIX (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLPIXELTEXGENSGIXPROC) (GLenum mode); +#endif + +#ifndef GL_SGIS_pixel_texture +#define GL_SGIS_pixel_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glPixelTexGenParameteriSGIS (GLenum, GLint); +GLAPI void GLAPIENTRY glPixelTexGenParameterivSGIS (GLenum, const GLint *); +GLAPI void GLAPIENTRY glPixelTexGenParameterfSGIS (GLenum, GLfloat); +GLAPI void GLAPIENTRY glPixelTexGenParameterfvSGIS (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glGetPixelTexGenParameterivSGIS (GLenum, GLint *); +GLAPI void GLAPIENTRY glGetPixelTexGenParameterfvSGIS (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRYP PFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint *params); +typedef void (GLAPIENTRYP PFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRYP PFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat *params); +#endif + +#ifndef GL_SGIS_texture4D +#define GL_SGIS_texture4D 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glTexImage4DSGIS (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glTexSubImage4DSGIS (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRYP PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels); +#endif + +#ifndef GL_SGI_texture_color_table +#define GL_SGI_texture_color_table 1 +#endif + +#ifndef GL_EXT_cmyka +#define GL_EXT_cmyka 1 +#endif + +#ifndef GL_EXT_texture_object +#define GL_EXT_texture_object 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLboolean GLAPIENTRY glAreTexturesResidentEXT (GLsizei, const GLuint *, GLboolean *); +GLAPI void GLAPIENTRY glBindTextureEXT (GLenum, GLuint); +GLAPI void GLAPIENTRY glDeleteTexturesEXT (GLsizei, const GLuint *); +GLAPI void GLAPIENTRY glGenTexturesEXT (GLsizei, GLuint *); +GLAPI GLboolean GLAPIENTRY glIsTextureEXT (GLuint); +GLAPI void GLAPIENTRY glPrioritizeTexturesEXT (GLsizei, const GLuint *, const GLclampf *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLboolean (GLAPIENTRYP PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences); +typedef void (GLAPIENTRYP PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture); +typedef void (GLAPIENTRYP PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures); +typedef void (GLAPIENTRYP PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures); +typedef GLboolean (GLAPIENTRYP PFNGLISTEXTUREEXTPROC) (GLuint texture); +typedef void (GLAPIENTRYP PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities); +#endif + +#ifndef GL_SGIS_detail_texture +#define GL_SGIS_detail_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glDetailTexFuncSGIS (GLenum, GLsizei, const GLfloat *); +GLAPI void GLAPIENTRY glGetDetailTexFuncSGIS (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points); +typedef void (GLAPIENTRYP PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat *points); +#endif + +#ifndef GL_SGIS_sharpen_texture +#define GL_SGIS_sharpen_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glSharpenTexFuncSGIS (GLenum, GLsizei, const GLfloat *); +GLAPI void GLAPIENTRY glGetSharpenTexFuncSGIS (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points); +typedef void (GLAPIENTRYP PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat *points); +#endif + +#ifndef GL_EXT_packed_pixels +#define GL_EXT_packed_pixels 1 +#endif + +#ifndef GL_SGIS_texture_lod +#define GL_SGIS_texture_lod 1 +#endif + +#ifndef GL_SGIS_multisample +#define GL_SGIS_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glSampleMaskSGIS (GLclampf, GLboolean); +GLAPI void GLAPIENTRY glSamplePatternSGIS (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert); +typedef void (GLAPIENTRYP PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern); +#endif + +#ifndef GL_EXT_rescale_normal +#define GL_EXT_rescale_normal 1 +#endif + +#ifndef GL_EXT_vertex_array +#define GL_EXT_vertex_array 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glArrayElementEXT (GLint); +GLAPI void GLAPIENTRY glColorPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glDrawArraysEXT (GLenum, GLint, GLsizei); +GLAPI void GLAPIENTRY glEdgeFlagPointerEXT (GLsizei, GLsizei, const GLboolean *); +GLAPI void GLAPIENTRY glGetPointervEXT (GLenum, GLvoid* *); +GLAPI void GLAPIENTRY glIndexPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glNormalPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glTexCoordPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glVertexPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLARRAYELEMENTEXTPROC) (GLint i); +typedef void (GLAPIENTRYP PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (GLAPIENTRYP PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (GLAPIENTRYP PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer); +typedef void (GLAPIENTRYP PFNGLGETPOINTERVEXTPROC) (GLenum pname, GLvoid* *params); +typedef void (GLAPIENTRYP PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (GLAPIENTRYP PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (GLAPIENTRYP PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (GLAPIENTRYP PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +#endif + +#ifndef GL_EXT_misc_attribute +#define GL_EXT_misc_attribute 1 +#endif + +#ifndef GL_SGIS_generate_mipmap +#define GL_SGIS_generate_mipmap 1 +#endif + +#ifndef GL_SGIX_clipmap +#define GL_SGIX_clipmap 1 +#endif + +#ifndef GL_SGIX_shadow +#define GL_SGIX_shadow 1 +#endif + +#ifndef GL_SGIS_texture_edge_clamp +#define GL_SGIS_texture_edge_clamp 1 +#endif + +#ifndef GL_SGIS_texture_border_clamp +#define GL_SGIS_texture_border_clamp 1 +#endif + +#ifndef GL_EXT_blend_minmax +#define GL_EXT_blend_minmax 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glBlendEquationEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLBLENDEQUATIONEXTPROC) (GLenum mode); +#endif + +#ifndef GL_EXT_blend_subtract +#define GL_EXT_blend_subtract 1 +#endif + +#ifndef GL_EXT_blend_logic_op +#define GL_EXT_blend_logic_op 1 +#endif + +#ifndef GL_SGIX_interlace +#define GL_SGIX_interlace 1 +#endif + +#ifndef GL_SGIX_pixel_tiles +#define GL_SGIX_pixel_tiles 1 +#endif + +#ifndef GL_SGIX_texture_select +#define GL_SGIX_texture_select 1 +#endif + +#ifndef GL_SGIX_sprite +#define GL_SGIX_sprite 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glSpriteParameterfSGIX (GLenum, GLfloat); +GLAPI void GLAPIENTRY glSpriteParameterfvSGIX (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glSpriteParameteriSGIX (GLenum, GLint); +GLAPI void GLAPIENTRY glSpriteParameterivSGIX (GLenum, const GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRYP PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRYP PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint *params); +#endif + +#ifndef GL_SGIX_texture_multi_buffer +#define GL_SGIX_texture_multi_buffer 1 +#endif + +#ifndef GL_EXT_point_parameters +#define GL_EXT_point_parameters 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glPointParameterfEXT (GLenum, GLfloat); +GLAPI void GLAPIENTRY glPointParameterfvEXT (GLenum, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRYP PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params); +#endif + +#ifndef GL_SGIS_point_parameters +#define GL_SGIS_point_parameters 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glPointParameterfSGIS (GLenum, GLfloat); +GLAPI void GLAPIENTRY glPointParameterfvSGIS (GLenum, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRYP PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params); +#endif + +#ifndef GL_SGIX_instruments +#define GL_SGIX_instruments 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLint GLAPIENTRY glGetInstrumentsSGIX (void); +GLAPI void GLAPIENTRY glInstrumentsBufferSGIX (GLsizei, GLint *); +GLAPI GLint GLAPIENTRY glPollInstrumentsSGIX (GLint *); +GLAPI void GLAPIENTRY glReadInstrumentsSGIX (GLint); +GLAPI void GLAPIENTRY glStartInstrumentsSGIX (void); +GLAPI void GLAPIENTRY glStopInstrumentsSGIX (GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLint (GLAPIENTRYP PFNGLGETINSTRUMENTSSGIXPROC) (void); +typedef void (GLAPIENTRYP PFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint *buffer); +typedef GLint (GLAPIENTRYP PFNGLPOLLINSTRUMENTSSGIXPROC) (GLint *marker_p); +typedef void (GLAPIENTRYP PFNGLREADINSTRUMENTSSGIXPROC) (GLint marker); +typedef void (GLAPIENTRYP PFNGLSTARTINSTRUMENTSSGIXPROC) (void); +typedef void (GLAPIENTRYP PFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker); +#endif + +#ifndef GL_SGIX_texture_scale_bias +#define GL_SGIX_texture_scale_bias 1 +#endif + +#ifndef GL_SGIX_framezoom +#define GL_SGIX_framezoom 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glFrameZoomSGIX (GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLFRAMEZOOMSGIXPROC) (GLint factor); +#endif + +#ifndef GL_SGIX_tag_sample_buffer +#define GL_SGIX_tag_sample_buffer 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glTagSampleBufferSGIX (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLTAGSAMPLEBUFFERSGIXPROC) (void); +#endif + +#ifndef GL_SGIX_polynomial_ffd +#define GL_SGIX_polynomial_ffd 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glDeformationMap3dSGIX (GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, const GLdouble *); +GLAPI void GLAPIENTRY glDeformationMap3fSGIX (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, const GLfloat *); +GLAPI void GLAPIENTRY glDeformSGIX (GLbitfield); +GLAPI void GLAPIENTRY glLoadIdentityDeformationMapSGIX (GLbitfield); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLDEFORMATIONMAP3DSGIXPROC) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points); +typedef void (GLAPIENTRYP PFNGLDEFORMATIONMAP3FSGIXPROC) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points); +typedef void (GLAPIENTRYP PFNGLDEFORMSGIXPROC) (GLbitfield mask); +typedef void (GLAPIENTRYP PFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC) (GLbitfield mask); +#endif + +#ifndef GL_SGIX_reference_plane +#define GL_SGIX_reference_plane 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glReferencePlaneSGIX (const GLdouble *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLREFERENCEPLANESGIXPROC) (const GLdouble *equation); +#endif + +#ifndef GL_SGIX_flush_raster +#define GL_SGIX_flush_raster 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glFlushRasterSGIX (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLFLUSHRASTERSGIXPROC) (void); +#endif + +#ifndef GL_SGIX_depth_texture +#define GL_SGIX_depth_texture 1 +#endif + +#ifndef GL_SGIS_fog_function +#define GL_SGIS_fog_function 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glFogFuncSGIS (GLsizei, const GLfloat *); +GLAPI void GLAPIENTRY glGetFogFuncSGIS (GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat *points); +typedef void (GLAPIENTRYP PFNGLGETFOGFUNCSGISPROC) (GLfloat *points); +#endif + +#ifndef GL_SGIX_fog_offset +#define GL_SGIX_fog_offset 1 +#endif + +#ifndef GL_HP_image_transform +#define GL_HP_image_transform 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glImageTransformParameteriHP (GLenum, GLenum, GLint); +GLAPI void GLAPIENTRY glImageTransformParameterfHP (GLenum, GLenum, GLfloat); +GLAPI void GLAPIENTRY glImageTransformParameterivHP (GLenum, GLenum, const GLint *); +GLAPI void GLAPIENTRY glImageTransformParameterfvHP (GLenum, GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glGetImageTransformParameterivHP (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetImageTransformParameterfvHP (GLenum, GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRYP PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRYP PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRYP PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params); +#endif + +#ifndef GL_HP_convolution_border_modes +#define GL_HP_convolution_border_modes 1 +#endif + +#ifndef GL_SGIX_texture_add_env +#define GL_SGIX_texture_add_env 1 +#endif + +#ifndef GL_EXT_color_subtable +#define GL_EXT_color_subtable 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glColorSubTableEXT (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glCopyColorSubTableEXT (GLenum, GLsizei, GLint, GLint, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); +typedef void (GLAPIENTRYP PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +#endif + +#ifndef GL_PGI_vertex_hints +#define GL_PGI_vertex_hints 1 +#endif + +#ifndef GL_PGI_misc_hints +#define GL_PGI_misc_hints 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glHintPGI (GLenum, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLHINTPGIPROC) (GLenum target, GLint mode); +#endif + +#ifndef GL_EXT_paletted_texture +#define GL_EXT_paletted_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glColorTableEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glGetColorTableEXT (GLenum, GLenum, GLenum, GLvoid *); +GLAPI void GLAPIENTRY glGetColorTableParameterivEXT (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetColorTableParameterfvEXT (GLenum, GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (GLAPIENTRYP PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *data); +typedef void (GLAPIENTRYP PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +#endif + +#ifndef GL_EXT_clip_volume_hint +#define GL_EXT_clip_volume_hint 1 +#endif + +#ifndef GL_SGIX_list_priority +#define GL_SGIX_list_priority 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glGetListParameterfvSGIX (GLuint, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetListParameterivSGIX (GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glListParameterfSGIX (GLuint, GLenum, GLfloat); +GLAPI void GLAPIENTRY glListParameterfvSGIX (GLuint, GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glListParameteriSGIX (GLuint, GLenum, GLint); +GLAPI void GLAPIENTRY glListParameterivSGIX (GLuint, GLenum, const GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param); +typedef void (GLAPIENTRYP PFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param); +typedef void (GLAPIENTRYP PFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint *params); +#endif + +#ifndef GL_SGIX_ir_instrument1 +#define GL_SGIX_ir_instrument1 1 +#endif + +#ifndef GL_SGIX_calligraphic_fragment +#define GL_SGIX_calligraphic_fragment 1 +#endif + +#ifndef GL_SGIX_texture_lod_bias +#define GL_SGIX_texture_lod_bias 1 +#endif + +#ifndef GL_SGIX_shadow_ambient +#define GL_SGIX_shadow_ambient 1 +#endif + +#ifndef GL_EXT_index_texture +#define GL_EXT_index_texture 1 +#endif + +#ifndef GL_EXT_index_material +#define GL_EXT_index_material 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glIndexMaterialEXT (GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode); +#endif + +#ifndef GL_EXT_index_func +#define GL_EXT_index_func 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glIndexFuncEXT (GLenum, GLclampf); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref); +#endif + +#ifndef GL_EXT_index_array_formats +#define GL_EXT_index_array_formats 1 +#endif + +#ifndef GL_EXT_compiled_vertex_array +#define GL_EXT_compiled_vertex_array 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glLockArraysEXT (GLint, GLsizei); +GLAPI void GLAPIENTRY glUnlockArraysEXT (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count); +typedef void (GLAPIENTRYP PFNGLUNLOCKARRAYSEXTPROC) (void); +#endif + +#ifndef GL_EXT_cull_vertex +#define GL_EXT_cull_vertex 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glCullParameterdvEXT (GLenum, GLdouble *); +GLAPI void GLAPIENTRY glCullParameterfvEXT (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble *params); +typedef void (GLAPIENTRYP PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat *params); +#endif + +#ifndef GL_SGIX_ycrcb +#define GL_SGIX_ycrcb 1 +#endif + +#ifndef GL_SGIX_fragment_lighting +#define GL_SGIX_fragment_lighting 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glFragmentColorMaterialSGIX (GLenum, GLenum); +GLAPI void GLAPIENTRY glFragmentLightfSGIX (GLenum, GLenum, GLfloat); +GLAPI void GLAPIENTRY glFragmentLightfvSGIX (GLenum, GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glFragmentLightiSGIX (GLenum, GLenum, GLint); +GLAPI void GLAPIENTRY glFragmentLightivSGIX (GLenum, GLenum, const GLint *); +GLAPI void GLAPIENTRY glFragmentLightModelfSGIX (GLenum, GLfloat); +GLAPI void GLAPIENTRY glFragmentLightModelfvSGIX (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glFragmentLightModeliSGIX (GLenum, GLint); +GLAPI void GLAPIENTRY glFragmentLightModelivSGIX (GLenum, const GLint *); +GLAPI void GLAPIENTRY glFragmentMaterialfSGIX (GLenum, GLenum, GLfloat); +GLAPI void GLAPIENTRY glFragmentMaterialfvSGIX (GLenum, GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glFragmentMaterialiSGIX (GLenum, GLenum, GLint); +GLAPI void GLAPIENTRY glFragmentMaterialivSGIX (GLenum, GLenum, const GLint *); +GLAPI void GLAPIENTRY glGetFragmentLightfvSGIX (GLenum, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetFragmentLightivSGIX (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetFragmentMaterialfvSGIX (GLenum, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetFragmentMaterialivSGIX (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glLightEnviSGIX (GLenum, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode); +typedef void (GLAPIENTRYP PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param); +typedef void (GLAPIENTRYP PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param); +typedef void (GLAPIENTRYP PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint *params); +typedef void (GLAPIENTRYP PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRYP PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRYP PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint *params); +typedef void (GLAPIENTRYP PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param); +typedef void (GLAPIENTRYP PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param); +typedef void (GLAPIENTRYP PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint *params); +typedef void (GLAPIENTRYP PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param); +#endif + +#ifndef GL_IBM_rasterpos_clip +#define GL_IBM_rasterpos_clip 1 +#endif + +#ifndef GL_HP_texture_lighting +#define GL_HP_texture_lighting 1 +#endif + +#ifndef GL_EXT_draw_range_elements +#define GL_EXT_draw_range_elements 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glDrawRangeElementsEXT (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); +#endif + +#ifndef GL_WIN_phong_shading +#define GL_WIN_phong_shading 1 +#endif + +#ifndef GL_WIN_specular_fog +#define GL_WIN_specular_fog 1 +#endif + +#ifndef GL_EXT_light_texture +#define GL_EXT_light_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glApplyTextureEXT (GLenum); +GLAPI void GLAPIENTRY glTextureLightEXT (GLenum); +GLAPI void GLAPIENTRY glTextureMaterialEXT (GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode); +typedef void (GLAPIENTRYP PFNGLTEXTURELIGHTEXTPROC) (GLenum pname); +typedef void (GLAPIENTRYP PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode); +#endif + +#ifndef GL_SGIX_blend_alpha_minmax +#define GL_SGIX_blend_alpha_minmax 1 +#endif + +#ifndef GL_EXT_bgra +#define GL_EXT_bgra 1 +#endif + +#ifndef GL_SGIX_async +#define GL_SGIX_async 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glAsyncMarkerSGIX (GLuint); +GLAPI GLint GLAPIENTRY glFinishAsyncSGIX (GLuint *); +GLAPI GLint GLAPIENTRY glPollAsyncSGIX (GLuint *); +GLAPI GLuint GLAPIENTRY glGenAsyncMarkersSGIX (GLsizei); +GLAPI void GLAPIENTRY glDeleteAsyncMarkersSGIX (GLuint, GLsizei); +GLAPI GLboolean GLAPIENTRY glIsAsyncMarkerSGIX (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLASYNCMARKERSGIXPROC) (GLuint marker); +typedef GLint (GLAPIENTRYP PFNGLFINISHASYNCSGIXPROC) (GLuint *markerp); +typedef GLint (GLAPIENTRYP PFNGLPOLLASYNCSGIXPROC) (GLuint *markerp); +typedef GLuint (GLAPIENTRYP PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range); +typedef void (GLAPIENTRYP PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range); +typedef GLboolean (GLAPIENTRYP PFNGLISASYNCMARKERSGIXPROC) (GLuint marker); +#endif + +#ifndef GL_SGIX_async_pixel +#define GL_SGIX_async_pixel 1 +#endif + +#ifndef GL_SGIX_async_histogram +#define GL_SGIX_async_histogram 1 +#endif + +#ifndef GL_INTEL_parallel_arrays +#define GL_INTEL_parallel_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glVertexPointervINTEL (GLint, GLenum, const GLvoid* *); +GLAPI void GLAPIENTRY glNormalPointervINTEL (GLenum, const GLvoid* *); +GLAPI void GLAPIENTRY glColorPointervINTEL (GLint, GLenum, const GLvoid* *); +GLAPI void GLAPIENTRY glTexCoordPointervINTEL (GLint, GLenum, const GLvoid* *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); +typedef void (GLAPIENTRYP PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const GLvoid* *pointer); +typedef void (GLAPIENTRYP PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); +typedef void (GLAPIENTRYP PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); +#endif + +#ifndef GL_HP_occlusion_test +#define GL_HP_occlusion_test 1 +#endif + +#ifndef GL_EXT_pixel_transform +#define GL_EXT_pixel_transform 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glPixelTransformParameteriEXT (GLenum, GLenum, GLint); +GLAPI void GLAPIENTRY glPixelTransformParameterfEXT (GLenum, GLenum, GLfloat); +GLAPI void GLAPIENTRY glPixelTransformParameterivEXT (GLenum, GLenum, const GLint *); +GLAPI void GLAPIENTRY glPixelTransformParameterfvEXT (GLenum, GLenum, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRYP PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRYP PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRYP PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params); +#endif + +#ifndef GL_EXT_pixel_transform_color_table +#define GL_EXT_pixel_transform_color_table 1 +#endif + +#ifndef GL_EXT_shared_texture_palette +#define GL_EXT_shared_texture_palette 1 +#endif + +#ifndef GL_EXT_separate_specular_color +#define GL_EXT_separate_specular_color 1 +#endif + +#ifndef GL_EXT_secondary_color +#define GL_EXT_secondary_color 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glSecondaryColor3bEXT (GLbyte, GLbyte, GLbyte); +GLAPI void GLAPIENTRY glSecondaryColor3bvEXT (const GLbyte *); +GLAPI void GLAPIENTRY glSecondaryColor3dEXT (GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glSecondaryColor3dvEXT (const GLdouble *); +GLAPI void GLAPIENTRY glSecondaryColor3fEXT (GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glSecondaryColor3fvEXT (const GLfloat *); +GLAPI void GLAPIENTRY glSecondaryColor3iEXT (GLint, GLint, GLint); +GLAPI void GLAPIENTRY glSecondaryColor3ivEXT (const GLint *); +GLAPI void GLAPIENTRY glSecondaryColor3sEXT (GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glSecondaryColor3svEXT (const GLshort *); +GLAPI void GLAPIENTRY glSecondaryColor3ubEXT (GLubyte, GLubyte, GLubyte); +GLAPI void GLAPIENTRY glSecondaryColor3ubvEXT (const GLubyte *); +GLAPI void GLAPIENTRY glSecondaryColor3uiEXT (GLuint, GLuint, GLuint); +GLAPI void GLAPIENTRY glSecondaryColor3uivEXT (const GLuint *); +GLAPI void GLAPIENTRY glSecondaryColor3usEXT (GLushort, GLushort, GLushort); +GLAPI void GLAPIENTRY glSecondaryColor3usvEXT (const GLushort *); +GLAPI void GLAPIENTRY glSecondaryColorPointerEXT (GLint, GLenum, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_EXT_texture_perturb_normal +#define GL_EXT_texture_perturb_normal 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glTextureNormalEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLTEXTURENORMALEXTPROC) (GLenum mode); +#endif + +#ifndef GL_EXT_multi_draw_arrays +#define GL_EXT_multi_draw_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei); +GLAPI void GLAPIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); +typedef void (GLAPIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); +#endif + +#ifndef GL_EXT_fog_coord +#define GL_EXT_fog_coord 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glFogCoordfEXT (GLfloat); +GLAPI void GLAPIENTRY glFogCoordfvEXT (const GLfloat *); +GLAPI void GLAPIENTRY glFogCoorddEXT (GLdouble); +GLAPI void GLAPIENTRY glFogCoorddvEXT (const GLdouble *); +GLAPI void GLAPIENTRY glFogCoordPointerEXT (GLenum, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLFOGCOORDFEXTPROC) (GLfloat coord); +typedef void (GLAPIENTRYP PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord); +typedef void (GLAPIENTRYP PFNGLFOGCOORDDEXTPROC) (GLdouble coord); +typedef void (GLAPIENTRYP PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord); +typedef void (GLAPIENTRYP PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_REND_screen_coordinates +#define GL_REND_screen_coordinates 1 +#endif + +#ifndef GL_EXT_coordinate_frame +#define GL_EXT_coordinate_frame 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glTangent3bEXT (GLbyte, GLbyte, GLbyte); +GLAPI void GLAPIENTRY glTangent3bvEXT (const GLbyte *); +GLAPI void GLAPIENTRY glTangent3dEXT (GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glTangent3dvEXT (const GLdouble *); +GLAPI void GLAPIENTRY glTangent3fEXT (GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glTangent3fvEXT (const GLfloat *); +GLAPI void GLAPIENTRY glTangent3iEXT (GLint, GLint, GLint); +GLAPI void GLAPIENTRY glTangent3ivEXT (const GLint *); +GLAPI void GLAPIENTRY glTangent3sEXT (GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glTangent3svEXT (const GLshort *); +GLAPI void GLAPIENTRY glBinormal3bEXT (GLbyte, GLbyte, GLbyte); +GLAPI void GLAPIENTRY glBinormal3bvEXT (const GLbyte *); +GLAPI void GLAPIENTRY glBinormal3dEXT (GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glBinormal3dvEXT (const GLdouble *); +GLAPI void GLAPIENTRY glBinormal3fEXT (GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glBinormal3fvEXT (const GLfloat *); +GLAPI void GLAPIENTRY glBinormal3iEXT (GLint, GLint, GLint); +GLAPI void GLAPIENTRY glBinormal3ivEXT (const GLint *); +GLAPI void GLAPIENTRY glBinormal3sEXT (GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glBinormal3svEXT (const GLshort *); +GLAPI void GLAPIENTRY glTangentPointerEXT (GLenum, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glBinormalPointerEXT (GLenum, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz); +typedef void (GLAPIENTRYP PFNGLTANGENT3BVEXTPROC) (const GLbyte *v); +typedef void (GLAPIENTRYP PFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz); +typedef void (GLAPIENTRYP PFNGLTANGENT3DVEXTPROC) (const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz); +typedef void (GLAPIENTRYP PFNGLTANGENT3FVEXTPROC) (const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz); +typedef void (GLAPIENTRYP PFNGLTANGENT3IVEXTPROC) (const GLint *v); +typedef void (GLAPIENTRYP PFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz); +typedef void (GLAPIENTRYP PFNGLTANGENT3SVEXTPROC) (const GLshort *v); +typedef void (GLAPIENTRYP PFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz); +typedef void (GLAPIENTRYP PFNGLBINORMAL3BVEXTPROC) (const GLbyte *v); +typedef void (GLAPIENTRYP PFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz); +typedef void (GLAPIENTRYP PFNGLBINORMAL3DVEXTPROC) (const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz); +typedef void (GLAPIENTRYP PFNGLBINORMAL3FVEXTPROC) (const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz); +typedef void (GLAPIENTRYP PFNGLBINORMAL3IVEXTPROC) (const GLint *v); +typedef void (GLAPIENTRYP PFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz); +typedef void (GLAPIENTRYP PFNGLBINORMAL3SVEXTPROC) (const GLshort *v); +typedef void (GLAPIENTRYP PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRYP PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_EXT_texture_env_combine +#define GL_EXT_texture_env_combine 1 +#endif + +#ifndef GL_APPLE_specular_vector +#define GL_APPLE_specular_vector 1 +#endif + +#ifndef GL_APPLE_transform_hint +#define GL_APPLE_transform_hint 1 +#endif + +#ifndef GL_SGIX_fog_scale +#define GL_SGIX_fog_scale 1 +#endif + +#ifndef GL_SUNX_constant_data +#define GL_SUNX_constant_data 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glFinishTextureSUNX (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLFINISHTEXTURESUNXPROC) (void); +#endif + +#ifndef GL_SUN_global_alpha +#define GL_SUN_global_alpha 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glGlobalAlphaFactorbSUN (GLbyte); +GLAPI void GLAPIENTRY glGlobalAlphaFactorsSUN (GLshort); +GLAPI void GLAPIENTRY glGlobalAlphaFactoriSUN (GLint); +GLAPI void GLAPIENTRY glGlobalAlphaFactorfSUN (GLfloat); +GLAPI void GLAPIENTRY glGlobalAlphaFactordSUN (GLdouble); +GLAPI void GLAPIENTRY glGlobalAlphaFactorubSUN (GLubyte); +GLAPI void GLAPIENTRY glGlobalAlphaFactorusSUN (GLushort); +GLAPI void GLAPIENTRY glGlobalAlphaFactoruiSUN (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor); +typedef void (GLAPIENTRYP PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor); +typedef void (GLAPIENTRYP PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor); +typedef void (GLAPIENTRYP PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor); +typedef void (GLAPIENTRYP PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor); +typedef void (GLAPIENTRYP PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor); +typedef void (GLAPIENTRYP PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor); +typedef void (GLAPIENTRYP PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor); +#endif + +#ifndef GL_SUN_triangle_list +#define GL_SUN_triangle_list 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glReplacementCodeuiSUN (GLuint); +GLAPI void GLAPIENTRY glReplacementCodeusSUN (GLushort); +GLAPI void GLAPIENTRY glReplacementCodeubSUN (GLubyte); +GLAPI void GLAPIENTRY glReplacementCodeuivSUN (const GLuint *); +GLAPI void GLAPIENTRY glReplacementCodeusvSUN (const GLushort *); +GLAPI void GLAPIENTRY glReplacementCodeubvSUN (const GLubyte *); +GLAPI void GLAPIENTRY glReplacementCodePointerSUN (GLenum, GLsizei, const GLvoid* *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint *code); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort *code); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte *code); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const GLvoid* *pointer); +#endif + +#ifndef GL_SUN_vertex +#define GL_SUN_vertex 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glColor4ubVertex2fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glColor4ubVertex2fvSUN (const GLubyte *, const GLfloat *); +GLAPI void GLAPIENTRY glColor4ubVertex3fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glColor4ubVertex3fvSUN (const GLubyte *, const GLfloat *); +GLAPI void GLAPIENTRY glColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glColor3fVertex3fvSUN (const GLfloat *, const GLfloat *); +GLAPI void GLAPIENTRY glNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *); +GLAPI void GLAPIENTRY glColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); +GLAPI void GLAPIENTRY glTexCoord2fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glTexCoord2fVertex3fvSUN (const GLfloat *, const GLfloat *); +GLAPI void GLAPIENTRY glTexCoord4fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glTexCoord4fVertex4fvSUN (const GLfloat *, const GLfloat *); +GLAPI void GLAPIENTRY glTexCoord2fColor4ubVertex3fSUN (GLfloat, GLfloat, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glTexCoord2fColor4ubVertex3fvSUN (const GLfloat *, const GLubyte *, const GLfloat *); +GLAPI void GLAPIENTRY glTexCoord2fColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glTexCoord2fColor3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); +GLAPI void GLAPIENTRY glTexCoord2fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glTexCoord2fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); +GLAPI void GLAPIENTRY glTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); +GLAPI void GLAPIENTRY glTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); +GLAPI void GLAPIENTRY glReplacementCodeuiVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glReplacementCodeuiVertex3fvSUN (const GLuint *, const GLfloat *); +GLAPI void GLAPIENTRY glReplacementCodeuiColor4ubVertex3fSUN (GLuint, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glReplacementCodeuiColor4ubVertex3fvSUN (const GLuint *, const GLubyte *, const GLfloat *); +GLAPI void GLAPIENTRY glReplacementCodeuiColor3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glReplacementCodeuiColor3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *); +GLAPI void GLAPIENTRY glReplacementCodeuiNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glReplacementCodeuiNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *); +GLAPI void GLAPIENTRY glReplacementCodeuiColor4fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *); +GLAPI void GLAPIENTRY glReplacementCodeuiTexCoord2fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glReplacementCodeuiTexCoord2fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *); +GLAPI void GLAPIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *); +GLAPI void GLAPIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); +typedef void (GLAPIENTRYP PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte *c, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte *c, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRYP PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat *tc, const GLubyte *c, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint *rc, const GLubyte *c, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +#endif + +#ifndef GL_EXT_blend_func_separate +#define GL_EXT_blend_func_separate 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glBlendFuncSeparateEXT (GLenum, GLenum, GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +#endif + +#ifndef GL_INGR_blend_func_separate +#define GL_INGR_blend_func_separate 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glBlendFuncSeparateINGR (GLenum, GLenum, GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLBLENDFUNCSEPARATEINGRPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +#endif + +#ifndef GL_INGR_color_clamp +#define GL_INGR_color_clamp 1 +#endif + +#ifndef GL_INGR_interlace_read +#define GL_INGR_interlace_read 1 +#endif + +#ifndef GL_EXT_stencil_wrap +#define GL_EXT_stencil_wrap 1 +#endif + +#ifndef GL_EXT_422_pixels +#define GL_EXT_422_pixels 1 +#endif + +#ifndef GL_NV_texgen_reflection +#define GL_NV_texgen_reflection 1 +#endif + +#ifndef GL_SUN_convolution_border_modes +#define GL_SUN_convolution_border_modes 1 +#endif + +#ifndef GL_EXT_texture_env_add +#define GL_EXT_texture_env_add 1 +#endif + +#ifndef GL_EXT_texture_lod_bias +#define GL_EXT_texture_lod_bias 1 +#endif + +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_EXT_texture_filter_anisotropic 1 +#endif + +#ifndef GL_EXT_vertex_weighting +#define GL_EXT_vertex_weighting 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glVertexWeightfEXT (GLfloat); +GLAPI void GLAPIENTRY glVertexWeightfvEXT (const GLfloat *); +GLAPI void GLAPIENTRY glVertexWeightPointerEXT (GLsizei, GLenum, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight); +typedef void (GLAPIENTRYP PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight); +typedef void (GLAPIENTRYP PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_NV_light_max_exponent +#define GL_NV_light_max_exponent 1 +#endif + +#ifndef GL_NV_vertex_array_range +#define GL_NV_vertex_array_range 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glFlushVertexArrayRangeNV (void); +GLAPI void GLAPIENTRY glVertexArrayRangeNV (GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void); +typedef void (GLAPIENTRYP PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, const GLvoid *pointer); +#endif + +#ifndef GL_NV_register_combiners +#define GL_NV_register_combiners 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glCombinerParameterfvNV (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glCombinerParameterfNV (GLenum, GLfloat); +GLAPI void GLAPIENTRY glCombinerParameterivNV (GLenum, const GLint *); +GLAPI void GLAPIENTRY glCombinerParameteriNV (GLenum, GLint); +GLAPI void GLAPIENTRY glCombinerInputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum); +GLAPI void GLAPIENTRY glCombinerOutputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLboolean, GLboolean, GLboolean); +GLAPI void GLAPIENTRY glFinalCombinerInputNV (GLenum, GLenum, GLenum, GLenum); +GLAPI void GLAPIENTRY glGetCombinerInputParameterfvNV (GLenum, GLenum, GLenum, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetCombinerInputParameterivNV (GLenum, GLenum, GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetCombinerOutputParameterfvNV (GLenum, GLenum, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetCombinerOutputParameterivNV (GLenum, GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetFinalCombinerInputParameterfvNV (GLenum, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetFinalCombinerInputParameterivNV (GLenum, GLenum, GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRYP PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params); +typedef void (GLAPIENTRYP PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRYP PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (GLAPIENTRYP PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); +typedef void (GLAPIENTRYP PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (GLAPIENTRYP PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params); +#endif + +#ifndef GL_NV_fog_distance +#define GL_NV_fog_distance 1 +#endif + +#ifndef GL_NV_texgen_emboss +#define GL_NV_texgen_emboss 1 +#endif + +#ifndef GL_NV_blend_square +#define GL_NV_blend_square 1 +#endif + +#ifndef GL_NV_texture_env_combine4 +#define GL_NV_texture_env_combine4 1 +#endif + +#ifndef GL_MESA_resize_buffers +#define GL_MESA_resize_buffers 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glResizeBuffersMESA (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLRESIZEBUFFERSMESAPROC) (void); +#endif + +#ifndef GL_MESA_window_pos +#define GL_MESA_window_pos 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glWindowPos2dMESA (GLdouble, GLdouble); +GLAPI void GLAPIENTRY glWindowPos2dvMESA (const GLdouble *); +GLAPI void GLAPIENTRY glWindowPos2fMESA (GLfloat, GLfloat); +GLAPI void GLAPIENTRY glWindowPos2fvMESA (const GLfloat *); +GLAPI void GLAPIENTRY glWindowPos2iMESA (GLint, GLint); +GLAPI void GLAPIENTRY glWindowPos2ivMESA (const GLint *); +GLAPI void GLAPIENTRY glWindowPos2sMESA (GLshort, GLshort); +GLAPI void GLAPIENTRY glWindowPos2svMESA (const GLshort *); +GLAPI void GLAPIENTRY glWindowPos3dMESA (GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glWindowPos3dvMESA (const GLdouble *); +GLAPI void GLAPIENTRY glWindowPos3fMESA (GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glWindowPos3fvMESA (const GLfloat *); +GLAPI void GLAPIENTRY glWindowPos3iMESA (GLint, GLint, GLint); +GLAPI void GLAPIENTRY glWindowPos3ivMESA (const GLint *); +GLAPI void GLAPIENTRY glWindowPos3sMESA (GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glWindowPos3svMESA (const GLshort *); +GLAPI void GLAPIENTRY glWindowPos4dMESA (GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glWindowPos4dvMESA (const GLdouble *); +GLAPI void GLAPIENTRY glWindowPos4fMESA (GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glWindowPos4fvMESA (const GLfloat *); +GLAPI void GLAPIENTRY glWindowPos4iMESA (GLint, GLint, GLint, GLint); +GLAPI void GLAPIENTRY glWindowPos4ivMESA (const GLint *); +GLAPI void GLAPIENTRY glWindowPos4sMESA (GLshort, GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glWindowPos4svMESA (const GLshort *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2IVMESAPROC) (const GLint *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS2SVMESAPROC) (const GLshort *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3IVMESAPROC) (const GLint *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS3SVMESAPROC) (const GLshort *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS4IVMESAPROC) (const GLint *v); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRYP PFNGLWINDOWPOS4SVMESAPROC) (const GLshort *v); +#endif + +#ifndef GL_EXT_texture_compression_s3tc +#define GL_EXT_texture_compression_s3tc 1 +#endif + +#ifndef GL_IBM_cull_vertex +#define GL_IBM_cull_vertex 1 +#endif + +#ifndef GL_IBM_multimode_draw_arrays +#define GL_IBM_multimode_draw_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glMultiModeDrawArraysIBM (const GLenum *, const GLint *, const GLsizei *, GLsizei, GLint); +GLAPI void GLAPIENTRY glMultiModeDrawElementsIBM (const GLenum *, const GLsizei *, GLenum, const GLvoid* const *, GLsizei, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); +typedef void (GLAPIENTRYP PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride); +#endif + +#ifndef GL_IBM_vertex_array_lists +#define GL_IBM_vertex_array_lists 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); +GLAPI void GLAPIENTRY glSecondaryColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); +GLAPI void GLAPIENTRY glEdgeFlagPointerListIBM (GLint, const GLboolean* *, GLint); +GLAPI void GLAPIENTRY glFogCoordPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); +GLAPI void GLAPIENTRY glIndexPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); +GLAPI void GLAPIENTRY glNormalPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); +GLAPI void GLAPIENTRY glTexCoordPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); +GLAPI void GLAPIENTRY glVertexPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (GLAPIENTRYP PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean* *pointer, GLint ptrstride); +typedef void (GLAPIENTRYP PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (GLAPIENTRYP PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (GLAPIENTRYP PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (GLAPIENTRYP PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (GLAPIENTRYP PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +#endif + +#ifndef GL_SGIX_subsample +#define GL_SGIX_subsample 1 +#endif + +#ifndef GL_SGIX_ycrcba +#define GL_SGIX_ycrcba 1 +#endif + +#ifndef GL_SGIX_ycrcb_subsample +#define GL_SGIX_ycrcb_subsample 1 +#endif + +#ifndef GL_SGIX_depth_pass_instrument +#define GL_SGIX_depth_pass_instrument 1 +#endif + +#ifndef GL_3DFX_texture_compression_FXT1 +#define GL_3DFX_texture_compression_FXT1 1 +#endif + +#ifndef GL_3DFX_multisample +#define GL_3DFX_multisample 1 +#endif + +#ifndef GL_3DFX_tbuffer +#define GL_3DFX_tbuffer 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glTbufferMask3DFX (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLTBUFFERMASK3DFXPROC) (GLuint mask); +#endif + +#ifndef GL_EXT_multisample +#define GL_EXT_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glSampleMaskEXT (GLclampf, GLboolean); +GLAPI void GLAPIENTRY glSamplePatternEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert); +typedef void (GLAPIENTRYP PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); +#endif + +#ifndef GL_SGIX_vertex_preclip +#define GL_SGIX_vertex_preclip 1 +#endif + +#ifndef GL_SGIX_convolution_accuracy +#define GL_SGIX_convolution_accuracy 1 +#endif + +#ifndef GL_SGIX_resample +#define GL_SGIX_resample 1 +#endif + +#ifndef GL_SGIS_point_line_texgen +#define GL_SGIS_point_line_texgen 1 +#endif + +#ifndef GL_SGIS_texture_color_mask +#define GL_SGIS_texture_color_mask 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glTextureColorMaskSGIS (GLboolean, GLboolean, GLboolean, GLboolean); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +#endif + +#ifndef GL_SGIX_igloo_interface +#define GL_SGIX_igloo_interface 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glIglooInterfaceSGIX (GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLIGLOOINTERFACESGIXPROC) (GLenum pname, const GLvoid *params); +#endif + +#ifndef GL_EXT_texture_env_dot3 +#define GL_EXT_texture_env_dot3 1 +#endif + +#ifndef GL_ATI_texture_mirror_once +#define GL_ATI_texture_mirror_once 1 +#endif + +#ifndef GL_NV_fence +#define GL_NV_fence 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glDeleteFencesNV (GLsizei, const GLuint *); +GLAPI void GLAPIENTRY glGenFencesNV (GLsizei, GLuint *); +GLAPI GLboolean GLAPIENTRY glIsFenceNV (GLuint); +GLAPI GLboolean GLAPIENTRY glTestFenceNV (GLuint); +GLAPI void GLAPIENTRY glGetFenceivNV (GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glFinishFenceNV (GLuint); +GLAPI void GLAPIENTRY glSetFenceNV (GLuint, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences); +typedef void (GLAPIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences); +typedef GLboolean (GLAPIENTRYP PFNGLISFENCENVPROC) (GLuint fence); +typedef GLboolean (GLAPIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence); +typedef void (GLAPIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence); +typedef void (GLAPIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); +#endif + +#ifndef GL_NV_evaluators +#define GL_NV_evaluators 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glMapControlPointsNV (GLenum, GLuint, GLenum, GLsizei, GLsizei, GLint, GLint, GLboolean, const GLvoid *); +GLAPI void GLAPIENTRY glMapParameterivNV (GLenum, GLenum, const GLint *); +GLAPI void GLAPIENTRY glMapParameterfvNV (GLenum, GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glGetMapControlPointsNV (GLenum, GLuint, GLenum, GLsizei, GLsizei, GLboolean, GLvoid *); +GLAPI void GLAPIENTRY glGetMapParameterivNV (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetMapParameterfvNV (GLenum, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetMapAttribParameterivNV (GLenum, GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetMapAttribParameterfvNV (GLenum, GLuint, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glEvalMapsNV (GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points); +typedef void (GLAPIENTRYP PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRYP PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points); +typedef void (GLAPIENTRYP PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode); +#endif + +#ifndef GL_NV_packed_depth_stencil +#define GL_NV_packed_depth_stencil 1 +#endif + +#ifndef GL_NV_register_combiners2 +#define GL_NV_register_combiners2 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glCombinerStageParameterfvNV (GLenum, GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glGetCombinerStageParameterfvNV (GLenum, GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params); +#endif + +#ifndef GL_NV_texture_compression_vtc +#define GL_NV_texture_compression_vtc 1 +#endif + +#ifndef GL_NV_texture_rectangle +#define GL_NV_texture_rectangle 1 +#endif + +#ifndef GL_NV_texture_shader +#define GL_NV_texture_shader 1 +#endif + +#ifndef GL_NV_texture_shader2 +#define GL_NV_texture_shader2 1 +#endif + +#ifndef GL_NV_vertex_array_range2 +#define GL_NV_vertex_array_range2 1 +#endif + +#ifndef GL_NV_vertex_program +#define GL_NV_vertex_program 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLboolean GLAPIENTRY glAreProgramsResidentNV (GLsizei, const GLuint *, GLboolean *); +GLAPI void GLAPIENTRY glBindProgramNV (GLenum, GLuint); +GLAPI void GLAPIENTRY glDeleteProgramsNV (GLsizei, const GLuint *); +GLAPI void GLAPIENTRY glExecuteProgramNV (GLenum, GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glGenProgramsNV (GLsizei, GLuint *); +GLAPI void GLAPIENTRY glGetProgramParameterdvNV (GLenum, GLuint, GLenum, GLdouble *); +GLAPI void GLAPIENTRY glGetProgramParameterfvNV (GLenum, GLuint, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetProgramivNV (GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetProgramStringNV (GLuint, GLenum, GLubyte *); +GLAPI void GLAPIENTRY glGetTrackMatrixivNV (GLenum, GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetVertexAttribdvNV (GLuint, GLenum, GLdouble *); +GLAPI void GLAPIENTRY glGetVertexAttribfvNV (GLuint, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetVertexAttribivNV (GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetVertexAttribPointervNV (GLuint, GLenum, GLvoid* *); +GLAPI GLboolean GLAPIENTRY glIsProgramNV (GLuint); +GLAPI void GLAPIENTRY glLoadProgramNV (GLenum, GLuint, GLsizei, const GLubyte *); +GLAPI void GLAPIENTRY glProgramParameter4dNV (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glProgramParameter4dvNV (GLenum, GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glProgramParameter4fNV (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glProgramParameter4fvNV (GLenum, GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glProgramParameters4dvNV (GLenum, GLuint, GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glProgramParameters4fvNV (GLenum, GLuint, GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glRequestResidentProgramsNV (GLsizei, const GLuint *); +GLAPI void GLAPIENTRY glTrackMatrixNV (GLenum, GLuint, GLenum, GLenum); +GLAPI void GLAPIENTRY glVertexAttribPointerNV (GLuint, GLint, GLenum, GLsizei, const GLvoid *); +GLAPI void GLAPIENTRY glVertexAttrib1dNV (GLuint, GLdouble); +GLAPI void GLAPIENTRY glVertexAttrib1dvNV (GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glVertexAttrib1fNV (GLuint, GLfloat); +GLAPI void GLAPIENTRY glVertexAttrib1fvNV (GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glVertexAttrib1sNV (GLuint, GLshort); +GLAPI void GLAPIENTRY glVertexAttrib1svNV (GLuint, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttrib2dNV (GLuint, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glVertexAttrib2dvNV (GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glVertexAttrib2fNV (GLuint, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glVertexAttrib2fvNV (GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glVertexAttrib2sNV (GLuint, GLshort, GLshort); +GLAPI void GLAPIENTRY glVertexAttrib2svNV (GLuint, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttrib3dNV (GLuint, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glVertexAttrib3dvNV (GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glVertexAttrib3fNV (GLuint, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glVertexAttrib3fvNV (GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glVertexAttrib3sNV (GLuint, GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glVertexAttrib3svNV (GLuint, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttrib4dNV (GLuint, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glVertexAttrib4dvNV (GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glVertexAttrib4fNV (GLuint, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glVertexAttrib4fvNV (GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glVertexAttrib4sNV (GLuint, GLshort, GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glVertexAttrib4svNV (GLuint, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttrib4ubNV (GLuint, GLubyte, GLubyte, GLubyte, GLubyte); +GLAPI void GLAPIENTRY glVertexAttrib4ubvNV (GLuint, const GLubyte *); +GLAPI void GLAPIENTRY glVertexAttribs1dvNV (GLuint, GLsizei, const GLdouble *); +GLAPI void GLAPIENTRY glVertexAttribs1fvNV (GLuint, GLsizei, const GLfloat *); +GLAPI void GLAPIENTRY glVertexAttribs1svNV (GLuint, GLsizei, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttribs2dvNV (GLuint, GLsizei, const GLdouble *); +GLAPI void GLAPIENTRY glVertexAttribs2fvNV (GLuint, GLsizei, const GLfloat *); +GLAPI void GLAPIENTRY glVertexAttribs2svNV (GLuint, GLsizei, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttribs3dvNV (GLuint, GLsizei, const GLdouble *); +GLAPI void GLAPIENTRY glVertexAttribs3fvNV (GLuint, GLsizei, const GLfloat *); +GLAPI void GLAPIENTRY glVertexAttribs3svNV (GLuint, GLsizei, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttribs4dvNV (GLuint, GLsizei, const GLdouble *); +GLAPI void GLAPIENTRY glVertexAttribs4fvNV (GLuint, GLsizei, const GLfloat *); +GLAPI void GLAPIENTRY glVertexAttribs4svNV (GLuint, GLsizei, const GLshort *); +GLAPI void GLAPIENTRY glVertexAttribs4ubvNV (GLuint, GLsizei, const GLubyte *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLboolean (GLAPIENTRYP PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences); +typedef void (GLAPIENTRYP PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRYP PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs); +typedef void (GLAPIENTRYP PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program); +typedef void (GLAPIENTRYP PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params); +typedef void (GLAPIENTRYP PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid* *pointer); +typedef GLboolean (GLAPIENTRYP PFNGLISPROGRAMNVPROC) (GLuint id); +typedef void (GLAPIENTRYP PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program); +typedef void (GLAPIENTRYP PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRYP PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRYP PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLuint count, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLuint count, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs); +typedef void (GLAPIENTRYP PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v); +#endif + +#ifndef GL_SGIX_texture_coordinate_clamp +#define GL_SGIX_texture_coordinate_clamp 1 +#endif + +#ifndef GL_SGIX_scalebias_hint +#define GL_SGIX_scalebias_hint 1 +#endif + +#ifndef GL_OML_interlace +#define GL_OML_interlace 1 +#endif + +#ifndef GL_OML_subsample +#define GL_OML_subsample 1 +#endif + +#ifndef GL_OML_resample +#define GL_OML_resample 1 +#endif + +#ifndef GL_NV_copy_depth_to_color +#define GL_NV_copy_depth_to_color 1 +#endif + +#ifndef GL_ATI_envmap_bumpmap +#define GL_ATI_envmap_bumpmap 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glTexBumpParameterivATI (GLenum, const GLint *); +GLAPI void GLAPIENTRY glTexBumpParameterfvATI (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glGetTexBumpParameterivATI (GLenum, GLint *); +GLAPI void GLAPIENTRY glGetTexBumpParameterfvATI (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, const GLint *param); +typedef void (GLAPIENTRYP PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, const GLfloat *param); +typedef void (GLAPIENTRYP PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param); +typedef void (GLAPIENTRYP PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param); +#endif + +#ifndef GL_ATI_fragment_shader +#define GL_ATI_fragment_shader 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLuint GLAPIENTRY glGenFragmentShadersATI (GLuint); +GLAPI void GLAPIENTRY glBindFragmentShaderATI (GLuint); +GLAPI void GLAPIENTRY glDeleteFragmentShaderATI (GLuint); +GLAPI void GLAPIENTRY glBeginFragmentShaderATI (void); +GLAPI void GLAPIENTRY glEndFragmentShaderATI (void); +GLAPI void GLAPIENTRY glPassTexCoordATI (GLuint, GLuint, GLenum); +GLAPI void GLAPIENTRY glSampleMapATI (GLuint, GLuint, GLenum); +GLAPI void GLAPIENTRY glColorFragmentOp1ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint); +GLAPI void GLAPIENTRY glColorFragmentOp2ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint); +GLAPI void GLAPIENTRY glColorFragmentOp3ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint); +GLAPI void GLAPIENTRY glAlphaFragmentOp1ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint); +GLAPI void GLAPIENTRY glAlphaFragmentOp2ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint); +GLAPI void GLAPIENTRY glAlphaFragmentOp3ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint); +GLAPI void GLAPIENTRY glSetFragmentShaderConstantATI (GLuint, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLuint (GLAPIENTRYP PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range); +typedef void (GLAPIENTRYP PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id); +typedef void (GLAPIENTRYP PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id); +typedef void (GLAPIENTRYP PFNGLBEGINFRAGMENTSHADERATIPROC) (void); +typedef void (GLAPIENTRYP PFNGLENDFRAGMENTSHADERATIPROC) (void); +typedef void (GLAPIENTRYP PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle); +typedef void (GLAPIENTRYP PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle); +typedef void (GLAPIENTRYP PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +typedef void (GLAPIENTRYP PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +typedef void (GLAPIENTRYP PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +typedef void (GLAPIENTRYP PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +typedef void (GLAPIENTRYP PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +typedef void (GLAPIENTRYP PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +typedef void (GLAPIENTRYP PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat *value); +#endif + +#ifndef GL_ATI_pn_triangles +#define GL_ATI_pn_triangles 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glPNTrianglesiATI (GLenum, GLint); +GLAPI void GLAPIENTRY glPNTrianglesfATI (GLenum, GLfloat); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRYP PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param); +#endif + +#ifndef GL_ATI_vertex_array_object +#define GL_ATI_vertex_array_object 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLuint GLAPIENTRY glNewObjectBufferATI (GLsizei, const GLvoid *, GLenum); +GLAPI GLboolean GLAPIENTRY glIsObjectBufferATI (GLuint); +GLAPI void GLAPIENTRY glUpdateObjectBufferATI (GLuint, GLuint, GLsizei, const GLvoid *, GLenum); +GLAPI void GLAPIENTRY glGetObjectBufferfvATI (GLuint, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetObjectBufferivATI (GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glFreeObjectBufferATI (GLuint); +GLAPI void GLAPIENTRY glArrayObjectATI (GLenum, GLint, GLenum, GLsizei, GLuint, GLuint); +GLAPI void GLAPIENTRY glGetArrayObjectfvATI (GLenum, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetArrayObjectivATI (GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glVariantArrayObjectATI (GLuint, GLenum, GLsizei, GLuint, GLuint); +GLAPI void GLAPIENTRY glGetVariantArrayObjectfvATI (GLuint, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetVariantArrayObjectivATI (GLuint, GLenum, GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLuint (GLAPIENTRYP PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const GLvoid *pointer, GLenum usage); +typedef GLboolean (GLAPIENTRYP PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (GLAPIENTRYP PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve); +typedef void (GLAPIENTRYP PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (GLAPIENTRYP PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); +typedef void (GLAPIENTRYP PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); +typedef void (GLAPIENTRYP PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint *params); +#endif + +#ifndef GL_EXT_vertex_shader +#define GL_EXT_vertex_shader 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glBeginVertexShaderEXT (void); +GLAPI void GLAPIENTRY glEndVertexShaderEXT (void); +GLAPI void GLAPIENTRY glBindVertexShaderEXT (GLuint); +GLAPI GLuint GLAPIENTRY glGenVertexShadersEXT (GLuint); +GLAPI void GLAPIENTRY glDeleteVertexShaderEXT (GLuint); +GLAPI void GLAPIENTRY glShaderOp1EXT (GLenum, GLuint, GLuint); +GLAPI void GLAPIENTRY glShaderOp2EXT (GLenum, GLuint, GLuint, GLuint); +GLAPI void GLAPIENTRY glShaderOp3EXT (GLenum, GLuint, GLuint, GLuint, GLuint); +GLAPI void GLAPIENTRY glSwizzleEXT (GLuint, GLuint, GLenum, GLenum, GLenum, GLenum); +GLAPI void GLAPIENTRY glWriteMaskEXT (GLuint, GLuint, GLenum, GLenum, GLenum, GLenum); +GLAPI void GLAPIENTRY glInsertComponentEXT (GLuint, GLuint, GLuint); +GLAPI void GLAPIENTRY glExtractComponentEXT (GLuint, GLuint, GLuint); +GLAPI GLuint GLAPIENTRY glGenSymbolsEXT (GLenum, GLenum, GLenum, GLuint); +GLAPI void GLAPIENTRY glSetInvariantEXT (GLuint, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glSetLocalConstantEXT (GLuint, GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glVariantbvEXT (GLuint, const GLbyte *); +GLAPI void GLAPIENTRY glVariantsvEXT (GLuint, const GLshort *); +GLAPI void GLAPIENTRY glVariantivEXT (GLuint, const GLint *); +GLAPI void GLAPIENTRY glVariantfvEXT (GLuint, const GLfloat *); +GLAPI void GLAPIENTRY glVariantdvEXT (GLuint, const GLdouble *); +GLAPI void GLAPIENTRY glVariantubvEXT (GLuint, const GLubyte *); +GLAPI void GLAPIENTRY glVariantusvEXT (GLuint, const GLushort *); +GLAPI void GLAPIENTRY glVariantuivEXT (GLuint, const GLuint *); +GLAPI void GLAPIENTRY glVariantPointerEXT (GLuint, GLenum, GLuint, const GLvoid *); +GLAPI void GLAPIENTRY glEnableVariantClientStateEXT (GLuint); +GLAPI void GLAPIENTRY glDisableVariantClientStateEXT (GLuint); +GLAPI GLuint GLAPIENTRY glBindLightParameterEXT (GLenum, GLenum); +GLAPI GLuint GLAPIENTRY glBindMaterialParameterEXT (GLenum, GLenum); +GLAPI GLuint GLAPIENTRY glBindTexGenParameterEXT (GLenum, GLenum, GLenum); +GLAPI GLuint GLAPIENTRY glBindTextureUnitParameterEXT (GLenum, GLenum); +GLAPI GLuint GLAPIENTRY glBindParameterEXT (GLenum); +GLAPI GLboolean GLAPIENTRY glIsVariantEnabledEXT (GLuint, GLenum); +GLAPI void GLAPIENTRY glGetVariantBooleanvEXT (GLuint, GLenum, GLboolean *); +GLAPI void GLAPIENTRY glGetVariantIntegervEXT (GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetVariantFloatvEXT (GLuint, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetVariantPointervEXT (GLuint, GLenum, GLvoid* *); +GLAPI void GLAPIENTRY glGetInvariantBooleanvEXT (GLuint, GLenum, GLboolean *); +GLAPI void GLAPIENTRY glGetInvariantIntegervEXT (GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetInvariantFloatvEXT (GLuint, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetLocalConstantBooleanvEXT (GLuint, GLenum, GLboolean *); +GLAPI void GLAPIENTRY glGetLocalConstantIntegervEXT (GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetLocalConstantFloatvEXT (GLuint, GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLBEGINVERTEXSHADEREXTPROC) (void); +typedef void (GLAPIENTRYP PFNGLENDVERTEXSHADEREXTPROC) (void); +typedef void (GLAPIENTRYP PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id); +typedef GLuint (GLAPIENTRYP PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range); +typedef void (GLAPIENTRYP PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id); +typedef void (GLAPIENTRYP PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1); +typedef void (GLAPIENTRYP PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2); +typedef void (GLAPIENTRYP PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); +typedef void (GLAPIENTRYP PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); +typedef void (GLAPIENTRYP PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); +typedef void (GLAPIENTRYP PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); +typedef void (GLAPIENTRYP PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); +typedef GLuint (GLAPIENTRYP PFNGLGENSYMBOLSEXTPROC) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components); +typedef void (GLAPIENTRYP PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr); +typedef void (GLAPIENTRYP PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr); +typedef void (GLAPIENTRYP PFNGLVARIANTBVEXTPROC) (GLuint id, const GLbyte *addr); +typedef void (GLAPIENTRYP PFNGLVARIANTSVEXTPROC) (GLuint id, const GLshort *addr); +typedef void (GLAPIENTRYP PFNGLVARIANTIVEXTPROC) (GLuint id, const GLint *addr); +typedef void (GLAPIENTRYP PFNGLVARIANTFVEXTPROC) (GLuint id, const GLfloat *addr); +typedef void (GLAPIENTRYP PFNGLVARIANTDVEXTPROC) (GLuint id, const GLdouble *addr); +typedef void (GLAPIENTRYP PFNGLVARIANTUBVEXTPROC) (GLuint id, const GLubyte *addr); +typedef void (GLAPIENTRYP PFNGLVARIANTUSVEXTPROC) (GLuint id, const GLushort *addr); +typedef void (GLAPIENTRYP PFNGLVARIANTUIVEXTPROC) (GLuint id, const GLuint *addr); +typedef void (GLAPIENTRYP PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, const GLvoid *addr); +typedef void (GLAPIENTRYP PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); +typedef void (GLAPIENTRYP PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); +typedef GLuint (GLAPIENTRYP PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value); +typedef GLuint (GLAPIENTRYP PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value); +typedef GLuint (GLAPIENTRYP PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value); +typedef GLuint (GLAPIENTRYP PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value); +typedef GLuint (GLAPIENTRYP PFNGLBINDPARAMETEREXTPROC) (GLenum value); +typedef GLboolean (GLAPIENTRYP PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap); +typedef void (GLAPIENTRYP PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (GLAPIENTRYP PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (GLAPIENTRYP PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (GLAPIENTRYP PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid* *data); +typedef void (GLAPIENTRYP PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (GLAPIENTRYP PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (GLAPIENTRYP PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (GLAPIENTRYP PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (GLAPIENTRYP PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (GLAPIENTRYP PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +#endif + +#ifndef GL_ATI_vertex_streams +#define GL_ATI_vertex_streams 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glVertexStream1sATI (GLenum, GLshort); +GLAPI void GLAPIENTRY glVertexStream1svATI (GLenum, const GLshort *); +GLAPI void GLAPIENTRY glVertexStream1iATI (GLenum, GLint); +GLAPI void GLAPIENTRY glVertexStream1ivATI (GLenum, const GLint *); +GLAPI void GLAPIENTRY glVertexStream1fATI (GLenum, GLfloat); +GLAPI void GLAPIENTRY glVertexStream1fvATI (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glVertexStream1dATI (GLenum, GLdouble); +GLAPI void GLAPIENTRY glVertexStream1dvATI (GLenum, const GLdouble *); +GLAPI void GLAPIENTRY glVertexStream2sATI (GLenum, GLshort, GLshort); +GLAPI void GLAPIENTRY glVertexStream2svATI (GLenum, const GLshort *); +GLAPI void GLAPIENTRY glVertexStream2iATI (GLenum, GLint, GLint); +GLAPI void GLAPIENTRY glVertexStream2ivATI (GLenum, const GLint *); +GLAPI void GLAPIENTRY glVertexStream2fATI (GLenum, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glVertexStream2fvATI (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glVertexStream2dATI (GLenum, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glVertexStream2dvATI (GLenum, const GLdouble *); +GLAPI void GLAPIENTRY glVertexStream3sATI (GLenum, GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glVertexStream3svATI (GLenum, const GLshort *); +GLAPI void GLAPIENTRY glVertexStream3iATI (GLenum, GLint, GLint, GLint); +GLAPI void GLAPIENTRY glVertexStream3ivATI (GLenum, const GLint *); +GLAPI void GLAPIENTRY glVertexStream3fATI (GLenum, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glVertexStream3fvATI (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glVertexStream3dATI (GLenum, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glVertexStream3dvATI (GLenum, const GLdouble *); +GLAPI void GLAPIENTRY glVertexStream4sATI (GLenum, GLshort, GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glVertexStream4svATI (GLenum, const GLshort *); +GLAPI void GLAPIENTRY glVertexStream4iATI (GLenum, GLint, GLint, GLint, GLint); +GLAPI void GLAPIENTRY glVertexStream4ivATI (GLenum, const GLint *); +GLAPI void GLAPIENTRY glVertexStream4fATI (GLenum, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glVertexStream4fvATI (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glVertexStream4dATI (GLenum, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glVertexStream4dvATI (GLenum, const GLdouble *); +GLAPI void GLAPIENTRY glNormalStream3bATI (GLenum, GLbyte, GLbyte, GLbyte); +GLAPI void GLAPIENTRY glNormalStream3bvATI (GLenum, const GLbyte *); +GLAPI void GLAPIENTRY glNormalStream3sATI (GLenum, GLshort, GLshort, GLshort); +GLAPI void GLAPIENTRY glNormalStream3svATI (GLenum, const GLshort *); +GLAPI void GLAPIENTRY glNormalStream3iATI (GLenum, GLint, GLint, GLint); +GLAPI void GLAPIENTRY glNormalStream3ivATI (GLenum, const GLint *); +GLAPI void GLAPIENTRY glNormalStream3fATI (GLenum, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glNormalStream3fvATI (GLenum, const GLfloat *); +GLAPI void GLAPIENTRY glNormalStream3dATI (GLenum, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glNormalStream3dvATI (GLenum, const GLdouble *); +GLAPI void GLAPIENTRY glClientActiveVertexStreamATI (GLenum); +GLAPI void GLAPIENTRY glVertexBlendEnviATI (GLenum, GLint); +GLAPI void GLAPIENTRY glVertexBlendEnvfATI (GLenum, GLfloat); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM1SATIPROC) (GLenum stream, GLshort x); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM1SVATIPROC) (GLenum stream, const GLshort *coords); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM1IATIPROC) (GLenum stream, GLint x); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM1IVATIPROC) (GLenum stream, const GLint *coords); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM1FATIPROC) (GLenum stream, GLfloat x); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM1FVATIPROC) (GLenum stream, const GLfloat *coords); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM1DATIPROC) (GLenum stream, GLdouble x); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM1DVATIPROC) (GLenum stream, const GLdouble *coords); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *coords); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *coords); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *coords); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *coords); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *coords); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *coords); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *coords); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *coords); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRYP PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *coords); +typedef void (GLAPIENTRYP PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz); +typedef void (GLAPIENTRYP PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *coords); +typedef void (GLAPIENTRYP PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort nx, GLshort ny, GLshort nz); +typedef void (GLAPIENTRYP PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords); +typedef void (GLAPIENTRYP PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint nx, GLint ny, GLint nz); +typedef void (GLAPIENTRYP PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *coords); +typedef void (GLAPIENTRYP PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz); +typedef void (GLAPIENTRYP PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords); +typedef void (GLAPIENTRYP PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz); +typedef void (GLAPIENTRYP PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords); +typedef void (GLAPIENTRYP PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream); +typedef void (GLAPIENTRYP PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRYP PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param); +#endif + +#ifndef GL_ATI_element_array +#define GL_ATI_element_array 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glElementPointerATI (GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glDrawElementArrayATI (GLenum, GLsizei); +GLAPI void GLAPIENTRY glDrawRangeElementArrayATI (GLenum, GLuint, GLuint, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLELEMENTPOINTERATIPROC) (GLenum type, const GLvoid *pointer); +typedef void (GLAPIENTRYP PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count); +typedef void (GLAPIENTRYP PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count); +#endif + +#ifndef GL_SUN_mesh_array +#define GL_SUN_mesh_array 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glDrawMeshArraysSUN (GLenum, GLint, GLsizei, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLDRAWMESHARRAYSSUNPROC) (GLenum mode, GLint first, GLsizei count, GLsizei width); +#endif + +#ifndef GL_SUN_slice_accum +#define GL_SUN_slice_accum 1 +#endif + +#ifndef GL_NV_multisample_filter_hint +#define GL_NV_multisample_filter_hint 1 +#endif + +#ifndef GL_NV_depth_clamp +#define GL_NV_depth_clamp 1 +#endif + +#ifndef GL_NV_occlusion_query +#define GL_NV_occlusion_query 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glGenOcclusionQueriesNV (GLsizei, GLuint *); +GLAPI void GLAPIENTRY glDeleteOcclusionQueriesNV (GLsizei, const GLuint *); +GLAPI GLboolean GLAPIENTRY glIsOcclusionQueryNV (GLuint); +GLAPI void GLAPIENTRY glBeginOcclusionQueryNV (GLuint); +GLAPI void GLAPIENTRY glEndOcclusionQueryNV (void); +GLAPI void GLAPIENTRY glGetOcclusionQueryivNV (GLuint, GLenum, GLint *); +GLAPI void GLAPIENTRY glGetOcclusionQueryuivNV (GLuint, GLenum, GLuint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids); +typedef void (GLAPIENTRYP PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (GLAPIENTRYP PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id); +typedef void (GLAPIENTRYP PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id); +typedef void (GLAPIENTRYP PFNGLENDOCCLUSIONQUERYNVPROC) (void); +typedef void (GLAPIENTRYP PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params); +#endif + +#ifndef GL_NV_point_sprite +#define GL_NV_point_sprite 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glPointParameteriNV (GLenum, GLint); +GLAPI void GLAPIENTRY glPointParameterivNV (GLenum, const GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRYP PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint *params); +#endif + +#ifndef GL_NV_texture_shader3 +#define GL_NV_texture_shader3 1 +#endif + +#ifndef GL_NV_vertex_program1_1 +#define GL_NV_vertex_program1_1 1 +#endif + +#ifndef GL_EXT_shadow_funcs +#define GL_EXT_shadow_funcs 1 +#endif + +#ifndef GL_EXT_stencil_two_side +#define GL_EXT_stencil_two_side 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glActiveStencilFaceEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face); +#endif + +#ifndef GL_ATI_text_fragment_shader +#define GL_ATI_text_fragment_shader 1 +#endif + +#ifndef GL_APPLE_client_storage +#define GL_APPLE_client_storage 1 +#endif + +#ifndef GL_APPLE_element_array +#define GL_APPLE_element_array 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glElementPointerAPPLE (GLenum, const GLvoid *); +GLAPI void GLAPIENTRY glDrawElementArrayAPPLE (GLenum, GLint, GLsizei); +GLAPI void GLAPIENTRY glDrawRangeElementArrayAPPLE (GLenum, GLuint, GLuint, GLint, GLsizei); +GLAPI void GLAPIENTRY glMultiDrawElementArrayAPPLE (GLenum, const GLint *, const GLsizei *, GLsizei); +GLAPI void GLAPIENTRY glMultiDrawRangeElementArrayAPPLE (GLenum, GLuint, GLuint, const GLint *, const GLsizei *, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const GLvoid *pointer); +typedef void (GLAPIENTRYP PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (GLAPIENTRYP PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); +typedef void (GLAPIENTRYP PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); +typedef void (GLAPIENTRYP PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount); +#endif + +#ifndef GL_APPLE_fence +#define GL_APPLE_fence 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glGenFencesAPPLE (GLsizei, GLuint *); +GLAPI void GLAPIENTRY glDeleteFencesAPPLE (GLsizei, const GLuint *); +GLAPI void GLAPIENTRY glSetFenceAPPLE (GLuint); +GLAPI GLboolean GLAPIENTRY glIsFenceAPPLE (GLuint); +GLAPI GLboolean GLAPIENTRY glTestFenceAPPLE (GLuint); +GLAPI void GLAPIENTRY glFinishFenceAPPLE (GLuint); +GLAPI GLboolean GLAPIENTRY glTestObjectAPPLE (GLenum, GLuint); +GLAPI void GLAPIENTRY glFinishObjectAPPLE (GLenum, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint *fences); +typedef void (GLAPIENTRYP PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint *fences); +typedef void (GLAPIENTRYP PFNGLSETFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (GLAPIENTRYP PFNGLISFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (GLAPIENTRYP PFNGLTESTFENCEAPPLEPROC) (GLuint fence); +typedef void (GLAPIENTRYP PFNGLFINISHFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (GLAPIENTRYP PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name); +typedef void (GLAPIENTRYP PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name); +#endif + +#ifndef GL_APPLE_vertex_array_object +#define GL_APPLE_vertex_array_object 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glBindVertexArrayAPPLE (GLuint); +GLAPI void GLAPIENTRY glDeleteVertexArraysAPPLE (GLsizei, const GLuint *); +GLAPI void GLAPIENTRY glGenVertexArraysAPPLE (GLsizei, const GLuint *); +GLAPI GLboolean GLAPIENTRY glIsVertexArrayAPPLE (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array); +typedef void (GLAPIENTRYP PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays); +typedef void (GLAPIENTRYP PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays); +typedef GLboolean (GLAPIENTRYP PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array); +#endif + +#ifndef GL_APPLE_vertex_array_range +#define GL_APPLE_vertex_array_range 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glVertexArrayRangeAPPLE (GLsizei, GLvoid *); +GLAPI void GLAPIENTRY glFlushVertexArrayRangeAPPLE (GLsizei, GLvoid *); +GLAPI void GLAPIENTRY glVertexArrayParameteriAPPLE (GLenum, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer); +typedef void (GLAPIENTRYP PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer); +typedef void (GLAPIENTRYP PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param); +#endif + +#ifndef GL_APPLE_ycbcr_422 +#define GL_APPLE_ycbcr_422 1 +#endif + +#ifndef GL_S3_s3tc +#define GL_S3_s3tc 1 +#endif + +#ifndef GL_ATI_draw_buffers +#define GL_ATI_draw_buffers 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glDrawBuffersATI (GLsizei, const GLenum *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum *bufs); +#endif + +#ifndef GL_ATI_pixel_format_float +#define GL_ATI_pixel_format_float 1 +/* This is really a WGL extension, but defines some associated GL enums. + * ATI does not export "GL_ATI_pixel_format_float" in the GL_EXTENSIONS string. + */ +#endif + +#ifndef GL_ATI_texture_env_combine3 +#define GL_ATI_texture_env_combine3 1 +#endif + +#ifndef GL_ATI_texture_float +#define GL_ATI_texture_float 1 +#endif + +#ifndef GL_NV_float_buffer +#define GL_NV_float_buffer 1 +#endif + +#ifndef GL_NV_fragment_program +#define GL_NV_fragment_program 1 +/* Some NV_fragment_program entry points are shared with ARB_vertex_program. */ +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glProgramNamedParameter4fNV (GLuint, GLsizei, const GLubyte *, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void GLAPIENTRY glProgramNamedParameter4dNV (GLuint, GLsizei, const GLubyte *, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void GLAPIENTRY glProgramNamedParameter4fvNV (GLuint, GLsizei, const GLubyte *, const GLfloat *); +GLAPI void GLAPIENTRY glProgramNamedParameter4dvNV (GLuint, GLsizei, const GLubyte *, const GLdouble *); +GLAPI void GLAPIENTRY glGetProgramNamedParameterfvNV (GLuint, GLsizei, const GLubyte *, GLfloat *); +GLAPI void GLAPIENTRY glGetProgramNamedParameterdvNV (GLuint, GLsizei, const GLubyte *, GLdouble *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v); +typedef void (GLAPIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params); +#endif + +#ifndef GL_NV_half_float +#define GL_NV_half_float 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glVertex2hNV (GLhalfNV, GLhalfNV); +GLAPI void GLAPIENTRY glVertex2hvNV (const GLhalfNV *); +GLAPI void GLAPIENTRY glVertex3hNV (GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void GLAPIENTRY glVertex3hvNV (const GLhalfNV *); +GLAPI void GLAPIENTRY glVertex4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void GLAPIENTRY glVertex4hvNV (const GLhalfNV *); +GLAPI void GLAPIENTRY glNormal3hNV (GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void GLAPIENTRY glNormal3hvNV (const GLhalfNV *); +GLAPI void GLAPIENTRY glColor3hNV (GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void GLAPIENTRY glColor3hvNV (const GLhalfNV *); +GLAPI void GLAPIENTRY glColor4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void GLAPIENTRY glColor4hvNV (const GLhalfNV *); +GLAPI void GLAPIENTRY glTexCoord1hNV (GLhalfNV); +GLAPI void GLAPIENTRY glTexCoord1hvNV (const GLhalfNV *); +GLAPI void GLAPIENTRY glTexCoord2hNV (GLhalfNV, GLhalfNV); +GLAPI void GLAPIENTRY glTexCoord2hvNV (const GLhalfNV *); +GLAPI void GLAPIENTRY glTexCoord3hNV (GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void GLAPIENTRY glTexCoord3hvNV (const GLhalfNV *); +GLAPI void GLAPIENTRY glTexCoord4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void GLAPIENTRY glTexCoord4hvNV (const GLhalfNV *); +GLAPI void GLAPIENTRY glMultiTexCoord1hNV (GLenum, GLhalfNV); +GLAPI void GLAPIENTRY glMultiTexCoord1hvNV (GLenum, const GLhalfNV *); +GLAPI void GLAPIENTRY glMultiTexCoord2hNV (GLenum, GLhalfNV, GLhalfNV); +GLAPI void GLAPIENTRY glMultiTexCoord2hvNV (GLenum, const GLhalfNV *); +GLAPI void GLAPIENTRY glMultiTexCoord3hNV (GLenum, GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void GLAPIENTRY glMultiTexCoord3hvNV (GLenum, const GLhalfNV *); +GLAPI void GLAPIENTRY glMultiTexCoord4hNV (GLenum, GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void GLAPIENTRY glMultiTexCoord4hvNV (GLenum, const GLhalfNV *); +GLAPI void GLAPIENTRY glFogCoordhNV (GLhalfNV); +GLAPI void GLAPIENTRY glFogCoordhvNV (const GLhalfNV *); +GLAPI void GLAPIENTRY glSecondaryColor3hNV (GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void GLAPIENTRY glSecondaryColor3hvNV (const GLhalfNV *); +GLAPI void GLAPIENTRY glVertexWeighthNV (GLhalfNV); +GLAPI void GLAPIENTRY glVertexWeighthvNV (const GLhalfNV *); +GLAPI void GLAPIENTRY glVertexAttrib1hNV (GLuint, GLhalfNV); +GLAPI void GLAPIENTRY glVertexAttrib1hvNV (GLuint, const GLhalfNV *); +GLAPI void GLAPIENTRY glVertexAttrib2hNV (GLuint, GLhalfNV, GLhalfNV); +GLAPI void GLAPIENTRY glVertexAttrib2hvNV (GLuint, const GLhalfNV *); +GLAPI void GLAPIENTRY glVertexAttrib3hNV (GLuint, GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void GLAPIENTRY glVertexAttrib3hvNV (GLuint, const GLhalfNV *); +GLAPI void GLAPIENTRY glVertexAttrib4hNV (GLuint, GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void GLAPIENTRY glVertexAttrib4hvNV (GLuint, const GLhalfNV *); +GLAPI void GLAPIENTRY glVertexAttribs1hvNV (GLuint, GLsizei, const GLhalfNV *); +GLAPI void GLAPIENTRY glVertexAttribs2hvNV (GLuint, GLsizei, const GLhalfNV *); +GLAPI void GLAPIENTRY glVertexAttribs3hvNV (GLuint, GLsizei, const GLhalfNV *); +GLAPI void GLAPIENTRY glVertexAttribs4hvNV (GLuint, GLsizei, const GLhalfNV *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLVERTEX2HNVPROC) (GLhalfNV x, GLhalfNV y); +typedef void (GLAPIENTRYP PFNGLVERTEX2HVNVPROC) (const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLVERTEX3HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z); +typedef void (GLAPIENTRYP PFNGLVERTEX3HVNVPROC) (const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLVERTEX4HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); +typedef void (GLAPIENTRYP PFNGLVERTEX4HVNVPROC) (const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLNORMAL3HNVPROC) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz); +typedef void (GLAPIENTRYP PFNGLNORMAL3HVNVPROC) (const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); +typedef void (GLAPIENTRYP PFNGLCOLOR3HVNVPROC) (const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLCOLOR4HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha); +typedef void (GLAPIENTRYP PFNGLCOLOR4HVNVPROC) (const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLTEXCOORD1HNVPROC) (GLhalfNV s); +typedef void (GLAPIENTRYP PFNGLTEXCOORD1HVNVPROC) (const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLTEXCOORD2HNVPROC) (GLhalfNV s, GLhalfNV t); +typedef void (GLAPIENTRYP PFNGLTEXCOORD2HVNVPROC) (const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLTEXCOORD3HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r); +typedef void (GLAPIENTRYP PFNGLTEXCOORD3HVNVPROC) (const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLTEXCOORD4HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); +typedef void (GLAPIENTRYP PFNGLTEXCOORD4HVNVPROC) (const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalfNV s); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); +typedef void (GLAPIENTRYP PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog); +typedef void (GLAPIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); +typedef void (GLAPIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight); +typedef void (GLAPIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); +#endif + +#ifndef GL_NV_pixel_data_range +#define GL_NV_pixel_data_range 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glPixelDataRangeNV (GLenum, GLsizei, GLvoid *); +GLAPI void GLAPIENTRY glFlushPixelDataRangeNV (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer); +typedef void (GLAPIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target); +#endif + +#ifndef GL_NV_primitive_restart +#define GL_NV_primitive_restart 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glPrimitiveRestartNV (void); +GLAPI void GLAPIENTRY glPrimitiveRestartIndexNV (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLPRIMITIVERESTARTNVPROC) (void); +typedef void (GLAPIENTRYP PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index); +#endif + +#ifndef GL_NV_texture_expand_normal +#define GL_NV_texture_expand_normal 1 +#endif + +#ifndef GL_NV_vertex_program2 +#define GL_NV_vertex_program2 1 +#endif + +#ifndef GL_ATI_map_object_buffer +#define GL_ATI_map_object_buffer 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLvoid* GLAPIENTRY glMapObjectBufferATI (GLuint); +GLAPI void GLAPIENTRY glUnmapObjectBufferATI (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLvoid* (GLAPIENTRYP PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (GLAPIENTRYP PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer); +#endif + +#ifndef GL_ATI_separate_stencil +#define GL_ATI_separate_stencil 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glStencilOpSeparateATI (GLenum, GLenum, GLenum, GLenum); +GLAPI void GLAPIENTRY glStencilFuncSeparateATI (GLenum, GLenum, GLint, GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (GLAPIENTRYP PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); +#endif + +#ifndef GL_ATI_vertex_attrib_array_object +#define GL_ATI_vertex_attrib_array_object 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glVertexAttribArrayObjectATI (GLuint, GLint, GLenum, GLboolean, GLsizei, GLuint, GLuint); +GLAPI void GLAPIENTRY glGetVertexAttribArrayObjectfvATI (GLuint, GLenum, GLfloat *); +GLAPI void GLAPIENTRY glGetVertexAttribArrayObjectivATI (GLuint, GLenum, GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset); +typedef void (GLAPIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint *params); +#endif + +#ifndef GL_OES_read_format +#define GL_OES_read_format 1 +#endif + +#ifndef GL_EXT_depth_bounds_test +#define GL_EXT_depth_bounds_test 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glDepthBoundsEXT (GLclampd, GLclampd); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax); +#endif + +#ifndef GL_EXT_texture_mirror_clamp +#define GL_EXT_texture_mirror_clamp 1 +#endif + +#ifndef GL_EXT_blend_equation_separate +#define GL_EXT_blend_equation_separate 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glBlendEquationSeparateEXT (GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha); +#endif + +#ifndef GL_MESA_pack_invert +#define GL_MESA_pack_invert 1 +#endif + +#ifndef GL_MESA_ycbcr_texture +#define GL_MESA_ycbcr_texture 1 +#endif + +#ifndef GL_EXT_pixel_buffer_object +#define GL_EXT_pixel_buffer_object 1 +#endif + +#ifndef GL_NV_fragment_program_option +#define GL_NV_fragment_program_option 1 +#endif + +#ifndef GL_NV_fragment_program2 +#define GL_NV_fragment_program2 1 +#endif + +#ifndef GL_NV_vertex_program2_option +#define GL_NV_vertex_program2_option 1 +#endif + +#ifndef GL_NV_vertex_program3 +#define GL_NV_vertex_program3 1 +#endif + +#ifndef GL_EXT_framebuffer_object +#define GL_EXT_framebuffer_object 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLboolean GLAPIENTRY glIsRenderbufferEXT (GLuint); +GLAPI void GLAPIENTRY glBindRenderbufferEXT (GLenum, GLuint); +GLAPI void GLAPIENTRY glDeleteRenderbuffersEXT (GLsizei, const GLuint *); +GLAPI void GLAPIENTRY glGenRenderbuffersEXT (GLsizei, GLuint *); +GLAPI void GLAPIENTRY glRenderbufferStorageEXT (GLenum, GLenum, GLsizei, GLsizei); +GLAPI void GLAPIENTRY glGetRenderbufferParameterivEXT (GLenum, GLenum, GLint *); +GLAPI GLboolean GLAPIENTRY glIsFramebufferEXT (GLuint); +GLAPI void GLAPIENTRY glBindFramebufferEXT (GLenum, GLuint); +GLAPI void GLAPIENTRY glDeleteFramebuffersEXT (GLsizei, const GLuint *); +GLAPI void GLAPIENTRY glGenFramebuffersEXT (GLsizei, GLuint *); +GLAPI GLenum GLAPIENTRY glCheckFramebufferStatusEXT (GLenum); +GLAPI void GLAPIENTRY glFramebufferTexture1DEXT (GLenum, GLenum, GLenum, GLuint, GLint); +GLAPI void GLAPIENTRY glFramebufferTexture2DEXT (GLenum, GLenum, GLenum, GLuint, GLint); +GLAPI void GLAPIENTRY glFramebufferTexture3DEXT (GLenum, GLenum, GLenum, GLuint, GLint, GLint); +GLAPI void GLAPIENTRY glFramebufferRenderbufferEXT (GLenum, GLenum, GLenum, GLuint); +GLAPI void GLAPIENTRY glGetFramebufferAttachmentParameterivEXT (GLenum, GLenum, GLenum, GLint *); +GLAPI void GLAPIENTRY glGenerateMipmapEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLboolean (GLAPIENTRYP PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer); +typedef void (GLAPIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer); +typedef void (GLAPIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers); +typedef void (GLAPIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers); +typedef void (GLAPIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef GLboolean (GLAPIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer); +typedef void (GLAPIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer); +typedef void (GLAPIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers); +typedef void (GLAPIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers); +typedef GLenum (GLAPIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target); +typedef void (GLAPIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GLAPIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAPIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGENERATEMIPMAPEXTPROC) (GLenum target); +#endif + +#ifndef GL_GREMEDY_string_marker +#define GL_GREMEDY_string_marker 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glStringMarkerGREMEDY (GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const GLvoid *string); +#endif + +#ifndef GL_EXT_Cg_shader +#define GL_EXT_Cg_shader 1 +#endif + +#ifndef GL_EXT_timer_query +#ifndef GL_COMPILER_LACKS_64BIT_INT +#define GL_EXT_timer_query 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glGetQueryObjecti64vEXT (GLuint id, GLenum pname, GLint64EXT *params); +GLAPI void GLAPIENTRY glGetQueryObjectui64vEXT (GLuint id, GLenum pname, GLuint64EXT *params); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64EXT *params); +typedef void (GLAPIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64EXT *params); +#endif +#endif + +#ifndef GL_EXT_texture_buffer_object +#define GL_EXT_texture_buffer_object 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glTexBufferEXT (GLenum target, GLenum internalformat, GLuint buffer); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer); +#endif + +#ifndef GL_NV_transform_feedback +#define GL_NV_transform_feedback 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glBeginTransformFeedbackNV (GLenum primitiveMode); +GLAPI void GLAPIENTRY glEndTransformFeedbackNV (void); +GLAPI void GLAPIENTRY glTransformFeedbackAttribsNV (GLuint count, const GLint *attribs, GLenum bufferMode); +GLAPI void GLAPIENTRY glBindBufferRangeNV (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +GLAPI void GLAPIENTRY glBindBufferOffsetNV (GLenum target, GLuint index, GLuint buffer, GLintptr offset); +GLAPI void GLAPIENTRY glBindBufferBaseNV (GLenum target, GLuint index, GLuint buffer); +GLAPI void GLAPIENTRY glTransformFeedbackVaryingsNV (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode); +GLAPI void GLAPIENTRY glActiveVaryingNV (GLuint program, const GLchar *name); +GLAPI GLint GLAPIENTRY glGetVaryingLocationNV (GLuint program, const GLchar *name); +GLAPI void GLAPIENTRY glGetActiveVaryingNV (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +GLAPI void GLAPIENTRY glGetTransformFeedbackVaryingNV (GLuint program, GLuint index, GLint *location); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode); +typedef void (GLAPIENTRYP PFNGLENDTRANSFORMFEEDBACKNVPROC) (void); +typedef void (GLAPIENTRYP PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint *attribs, GLenum bufferMode); +typedef void (GLAPIENTRYP PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAPIENTRYP PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); +typedef void (GLAPIENTRYP PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (GLAPIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode); +typedef void (GLAPIENTRYP PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name); +typedef GLint (GLAPIENTRYP PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name); +typedef void (GLAPIENTRYP PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +typedef void (GLAPIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint *location); +#endif + + +#ifndef GL_NV_depth_buffer_float +#define GL_NV_depth_buffer_float 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glDepthRangedNV (GLdouble zNear, GLdouble zFar); +GLAPI void GLAPIENTRY glClearDepthdNV (GLdouble depth); +GLAPI void GLAPIENTRY glDepthBoundsdNV (GLdouble zmin, GLdouble zmax); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar); +typedef void (GLAPIENTRYP PFNGLCLEARDEPTHDNVPROC) (GLdouble depth); +typedef void (GLAPIENTRYP PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax); +#endif + +#ifndef GL_EXT_texture_compression_latc +#define GL_EXT_texture_compression_latc 1 +#endif + +#ifndef GL_EXT_framebuffer_sRGB +#define GL_EXT_framebuffer_sRGB 1 +#endif + +#ifndef GL_EXT_texture_shared_exponent +#define GL_EXT_texture_shared_exponent 1 +#endif + +#ifndef GL_EXT_packed_float +#define GL_EXT_packed_float 1 +#endif + +#ifndef GL_EXT_texture_array +#define GL_EXT_texture_array 1 +#endif + +#ifndef GL_EXT_draw_buffers2 +#define GL_EXT_draw_buffers2 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glColorMaskIndexedEXT (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +GLAPI void GLAPIENTRY glGetBooleanIndexedvEXT (GLenum target, GLuint index, GLboolean *data); +GLAPI void GLAPIENTRY glGetIntegerIndexedvEXT (GLenum target, GLuint index, GLint *data); +GLAPI void GLAPIENTRY glEnableIndexedEXT (GLenum target, GLuint index); +GLAPI void GLAPIENTRY glDisableIndexedEXT (GLenum target, GLuint index); +GLAPI GLboolean GLAPIENTRY glIsEnabledIndexedEXT (GLenum target, GLuint index); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef void (GLAPIENTRYP PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum target, GLuint index, GLboolean *data); +typedef void (GLAPIENTRYP PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLint *data); +typedef void (GLAPIENTRYP PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index); +typedef void (GLAPIENTRYP PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index); +typedef GLboolean (GLAPIENTRYP PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index); +#endif + +#ifndef GL_EXT_texture_integer +#define GL_EXT_texture_integer 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glTexParameterIivEXT (GLenum target, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glTexParameterIuivEXT (GLenum target, GLenum pname, const GLuint *params); +GLAPI void GLAPIENTRY glGetTexParameterIivEXT (GLenum target, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetTexParameterIuivEXT (GLenum target, GLenum pname, GLuint *params); +GLAPI void GLAPIENTRY glClearColorIiEXT (GLint red, GLint green, GLint blue, GLint alpha); +GLAPI void GLAPIENTRY glClearColorIuiEXT (GLuint red, GLuint green, GLuint blue, GLuint alpha); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRYP PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params); +typedef void (GLAPIENTRYP PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params); +typedef void (GLAPIENTRYP PFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha); +typedef void (GLAPIENTRYP PFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha); +#endif + +#ifndef GL_EXT_bindable_uniform +#define GL_EXT_bindable_uniform 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glUniformBufferEXT (GLuint program, GLint location, GLuint buffer); +GLAPI GLint GLAPIENTRY glGetUniformBufferSizeEXT (GLuint program, GLint location); +GLAPI GLintptr GLAPIENTRY glGetUniformOffsetEXT (GLuint program, GLint location); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer); +typedef GLint (GLAPIENTRYP PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location); +typedef GLintptr (GLAPIENTRYP PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location); +#endif + +#ifndef GL_EXT_gpu_shader4 +#define GL_EXT_gpu_shader4 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glGetUniformuivEXT (GLuint program, GLint location, GLuint *params); +GLAPI void GLAPIENTRY glBindFragDataLocationEXT (GLuint program, GLuint color, const GLchar *name); +GLAPI GLint GLAPIENTRY glGetFragDataLocationEXT (GLuint program, const GLchar *name); +GLAPI void GLAPIENTRY glUniform1uiEXT (GLint location, GLuint v0); +GLAPI void GLAPIENTRY glUniform2uiEXT (GLint location, GLuint v0, GLuint v1); +GLAPI void GLAPIENTRY glUniform3uiEXT (GLint location, GLuint v0, GLuint v1, GLuint v2); +GLAPI void GLAPIENTRY glUniform4uiEXT (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GLAPI void GLAPIENTRY glUniform1uivEXT (GLint location, GLsizei count, const GLuint *value); +GLAPI void GLAPIENTRY glUniform2uivEXT (GLint location, GLsizei count, const GLuint *value); +GLAPI void GLAPIENTRY glUniform3uivEXT (GLint location, GLsizei count, const GLuint *value); +GLAPI void GLAPIENTRY glUniform4uivEXT (GLint location, GLsizei count, const GLuint *value); +GLAPI void GLAPIENTRY glVertexAttribI1iEXT (GLuint index, GLint x); +GLAPI void GLAPIENTRY glVertexAttribI2iEXT (GLuint index, GLint x, GLint y); +GLAPI void GLAPIENTRY glVertexAttribI3iEXT (GLuint index, GLint x, GLint y, GLint z); +GLAPI void GLAPIENTRY glVertexAttribI4iEXT (GLuint index, GLint x, GLint y, GLint z, GLint w); +GLAPI void GLAPIENTRY glVertexAttribI1uiEXT (GLuint index, GLuint x); +GLAPI void GLAPIENTRY glVertexAttribI2uiEXT (GLuint index, GLuint x, GLuint y); +GLAPI void GLAPIENTRY glVertexAttribI3uiEXT (GLuint index, GLuint x, GLuint y, GLuint z); +GLAPI void GLAPIENTRY glVertexAttribI4uiEXT (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GLAPI void GLAPIENTRY glVertexAttribI1ivEXT (GLuint index, const GLint *v); +GLAPI void GLAPIENTRY glVertexAttribI2ivEXT (GLuint index, const GLint *v); +GLAPI void GLAPIENTRY glVertexAttribI3ivEXT (GLuint index, const GLint *v); +GLAPI void GLAPIENTRY glVertexAttribI4ivEXT (GLuint index, const GLint *v); +GLAPI void GLAPIENTRY glVertexAttribI1uivEXT (GLuint index, const GLuint *v); +GLAPI void GLAPIENTRY glVertexAttribI2uivEXT (GLuint index, const GLuint *v); +GLAPI void GLAPIENTRY glVertexAttribI3uivEXT (GLuint index, const GLuint *v); +GLAPI void GLAPIENTRY glVertexAttribI4uivEXT (GLuint index, const GLuint *v); +GLAPI void GLAPIENTRY glVertexAttribI4bvEXT (GLuint index, const GLbyte *v); +GLAPI void GLAPIENTRY glVertexAttribI4svEXT (GLuint index, const GLshort *v); +GLAPI void GLAPIENTRY glVertexAttribI4ubvEXT (GLuint index, const GLubyte *v); +GLAPI void GLAPIENTRY glVertexAttribI4usvEXT (GLuint index, const GLushort *v); +GLAPI void GLAPIENTRY glVertexAttribIPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glGetVertexAttribIivEXT (GLuint index, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetVertexAttribIuivEXT (GLuint index, GLenum pname, GLuint *params); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params); +typedef void (GLAPIENTRYP PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name); +typedef GLint (GLAPIENTRYP PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name); +typedef void (GLAPIENTRYP PFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0); +typedef void (GLAPIENTRYP PFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1); +typedef void (GLAPIENTRYP PFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAPIENTRYP PFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAPIENTRYP PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRYP PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v); +typedef void (GLAPIENTRYP PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRYP PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params); +#endif + + +#ifndef GL_EXT_geometry_shader4 +#define GL_EXT_geometry_shader4 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value); +GLAPI void GLAPIENTRY glFramebufferTextureEXT (GLenum target, GLenum attachment, GLuint texture, GLint level); +GLAPI void GLAPIENTRY glFramebufferTextureLayerEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +GLAPI void GLAPIENTRY glFramebufferTextureFaceEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); +typedef void (GLAPIENTRYP PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAPIENTRYP PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAPIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +#endif + +#ifndef GL_NV_geometry_program4 +#define GL_NV_geometry_program4 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glProgramVertexLimitNV (GLenum target, GLint limit); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit); +#endif + +#ifndef GL_NV_gpu_program4 +#define GL_NV_gpu_program4 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glProgramLocalParameterI4iNV (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +GLAPI void GLAPIENTRY glProgramLocalParameterI4ivNV (GLenum target, GLuint index, const GLint *params); +GLAPI void GLAPIENTRY glProgramLocalParametersI4ivNV (GLenum target, GLuint index, GLsizei count, const GLint *params); +GLAPI void GLAPIENTRY glProgramLocalParameterI4uiNV (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GLAPI void GLAPIENTRY glProgramLocalParameterI4uivNV (GLenum target, GLuint index, const GLuint *params); +GLAPI void GLAPIENTRY glProgramLocalParametersI4uivNV (GLenum target, GLuint index, GLsizei count, const GLuint *params); +GLAPI void GLAPIENTRY glProgramEnvParameterI4iNV (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +GLAPI void GLAPIENTRY glProgramEnvParameterI4ivNV (GLenum target, GLuint index, const GLint *params); +GLAPI void GLAPIENTRY glProgramEnvParametersI4ivNV (GLenum target, GLuint index, GLsizei count, const GLint *params); +GLAPI void GLAPIENTRY glProgramEnvParameterI4uiNV (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GLAPI void GLAPIENTRY glProgramEnvParameterI4uivNV (GLenum target, GLuint index, const GLuint *params); +GLAPI void GLAPIENTRY glProgramEnvParametersI4uivNV (GLenum target, GLuint index, GLsizei count, const GLuint *params); +GLAPI void GLAPIENTRY glGetProgramLocalParameterIivNV (GLenum target, GLuint index, GLint *params); +GLAPI void GLAPIENTRY glGetProgramLocalParameterIuivNV (GLenum target, GLuint index, GLuint *params); +GLAPI void GLAPIENTRY glGetProgramEnvParameterIivNV (GLenum target, GLuint index, GLint *params); +GLAPI void GLAPIENTRY glGetProgramEnvParameterIuivNV (GLenum target, GLuint index, GLuint *params); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRYP PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params); +typedef void (GLAPIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params); +typedef void (GLAPIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params); +typedef void (GLAPIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params); +typedef void (GLAPIENTRYP PFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRYP PFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params); +typedef void (GLAPIENTRYP PFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params); +typedef void (GLAPIENTRYP PFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRYP PFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params); +typedef void (GLAPIENTRYP PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMENVPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params); +typedef void (GLAPIENTRYP PFNGLGETPROGRAMENVPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params); +#endif + +#ifndef GL_NV_parameter_buffer_object +#define GL_NV_parameter_buffer_object 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glProgramBufferParametersfvNV (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat *params); +GLAPI void GLAPIENTRY glProgramBufferParametersIivNV (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint *params); +GLAPI void GLAPIENTRY glProgramBufferParametersIuivNV (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint *params); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat *params); +typedef void (GLAPIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint *params); +typedef void (GLAPIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint *params); +#endif + +#ifndef GL_EXT_framebuffer_multisample +#define GL_EXT_framebuffer_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glRenderbufferStorageMultisampleEXT (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#endif + +#ifndef GL_NV_framebuffer_multisample_coverage +#define GL_NV_framebuffer_multisample_coverage 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glRenderbufferStorageMultisampleCoverageNV (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); +#endif + +#ifndef GL_EXT_framebuffer_blit +#define GL_EXT_framebuffer_blit 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#endif + +#ifndef GL_EXT_draw_instanced +#define GL_EXT_draw_instanced 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count, GLsizei primcount); +GLAPI void GLAPIENTRY glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GLAPIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); +typedef void (GLAPIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); +#endif + +#ifndef GL_EXT_texture_compression_rgtc +#define GL_EXT_texture_compression_rgtc 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Extras/sph/common/glut.h b/Extras/sph/common/glut.h new file mode 100644 index 0000000..11735a1 --- /dev/null +++ b/Extras/sph/common/glut.h @@ -0,0 +1,791 @@ +#ifndef __glut_h__ +#define __glut_h__ + +/* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998, 2000, 2006. */ + +/* This program is freely distributable without licensing fees and is + provided without guarantee or warrantee expressed or implied. This + program is -not- in the public domain. */ + +#if defined(_WIN32) || defined(__CYGWIN__) + +/* GLUT 3.7 now tries to avoid including + to avoid name space pollution, but Win32's + needs APIENTRY and WINGDIAPI defined properly. */ +# if 0 + /* This would put tons of macros and crap in our clean name space. */ +# define WIN32_LEAN_AND_MEAN +# include +# else + /* XXX This is from Win32's */ +# ifndef APIENTRY +# define GLUT_APIENTRY_DEFINED + /* Cygwin and MingW32 are two free GNU-based Open Source compilation + environments for Win32. Note that __CYGWIN32__ is deprecated + in favor of simply __CYGWIN__. */ +# if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__) +# if defined(__CYGWIN__) +# define APIENTRY __stdcall +# else +# ifdef i386 +# define APIENTRY __attribute__((stdcall)) +# else +# define APIENTRY +# endif +# endif +# else +# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) +# define APIENTRY __stdcall +# else +# define APIENTRY +# endif +# endif +# endif + /* XXX This is from Win32's */ +# ifndef CALLBACK +# if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__) +# ifndef __stdcall +# define __stdcall __attribute__((stdcall)) +# endif +# define CALLBACK __stdcall +# else +# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) +# define CALLBACK __stdcall +# else +# define CALLBACK +# endif +# endif +# endif + /* XXX This is from Win32's and */ +# ifndef WINGDIAPI +# define GLUT_WINGDIAPI_DEFINED +# if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__) +# define WINGDIAPI +# else +# define WINGDIAPI __declspec(dllimport) +# endif +# endif +# if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__) + /* Rely on Cygwin32/MingW32 to set wchar_t. */ + /* XXX Warning. The Cygwin32/MingW32 definition for wchar_t + is an "int" instead of the "short" used by Windows. */ +# include +# else + /* XXX This is from Win32's */ +# ifndef _WCHAR_T_DEFINED +typedef unsigned short wchar_t; +# define _WCHAR_T_DEFINED +# endif +# endif +# endif + +/* To disable automatic library usage for GLUT, define GLUT_NO_LIB_PRAGMA + in your compile preprocessor options (Microsoft Visual C only). */ +# if !defined(GLUT_BUILDING_LIB) && !defined(GLUT_NO_LIB_PRAGMA) && defined(_MSC_VER) +# pragma comment (lib, "winmm.lib") /* link with Windows MultiMedia lib */ +# pragma comment (lib, "user32.lib") /* link with Windows User lib */ +# pragma comment (lib, "gdi32.lib") /* link with Windows GDI lib */ +/* To enable automatic SGI OpenGL for Windows library usage for GLUT, + define GLUT_USE_SGI_OPENGL in your compile preprocessor options. */ +# ifdef GLUT_USE_SGI_OPENGL +# pragma comment (lib, "opengl.lib") /* link with SGI OpenGL for Windows lib */ +# pragma comment (lib, "glu.lib") /* link with SGI OpenGL Utility lib */ +# if defined(GLUT_STATIC_LIB) +# pragma comment (lib, "glutstatic.lib") /* link with static Win32 GLUT lib */ +# else +# pragma comment (lib, "glut.lib") /* link with Win32 GLUT lib */ +# endif +# else +# pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */ +# pragma comment (lib, "glu32.lib") /* link with Microsoft OpenGL Utility lib */ +# if defined(GLUT_STATIC_LIB) +# pragma comment (lib, "glutstatic.lib") /* link with static Win32 GLUT lib */ +# else +# pragma comment (lib, "glut32.lib") /* link with Win32 GLUT lib */ +# endif +# endif +# endif + +/* To disable supression of annoying warnings about floats being promoted + to doubles, define GLUT_NO_WARNING_DISABLE in your compile preprocessor + options. */ +# if defined(_MSC_VER) && !defined(GLUT_NO_WARNING_DISABLE) +# pragma warning (disable:4244) /* Disable bogus VC++ 4.2 conversion warnings. */ +# pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */ +# endif + +/* Win32 has an annoying issue where there are multiple C run-time + libraries (CRTs). If the executable is linked with a different CRT + from the GLUT DLL, the GLUT DLL will not share the same CRT static + data seen by the executable. In particular, atexit callbacks registered + in the executable will not be called if GLUT calls its (different) + exit routine). GLUT is typically built with the + "/MD" option (the CRT with multithreading DLL support), but the Visual + C++ linker default is "/ML" (the single threaded CRT). + + One workaround to this issue is requiring users to always link with + the same CRT as GLUT is compiled with. That requires users supply a + non-standard option. GLUT 3.7 has its own built-in workaround where + the executable's "exit" function pointer is covertly passed to GLUT. + GLUT then calls the executable's exit function pointer to ensure that + any "atexit" calls registered by the application are called if GLUT + needs to exit. + + Note that the __glut*WithExit routines should NEVER be called directly. + To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */ + +/* XXX This is from Win32's */ +# if !defined(_MSC_VER) && !defined(__cdecl) + /* Define __cdecl for non-Microsoft compilers. */ +# define __cdecl +# define GLUT_DEFINED___CDECL +# endif +# ifndef _CRTIMP +# ifdef _NTSDK + /* Definition compatible with NT SDK */ +# define _CRTIMP +# else + /* Current definition */ +# ifdef _DLL +# define _CRTIMP __declspec(dllimport) +# else +# define _CRTIMP +# endif +# endif +# define GLUT_DEFINED__CRTIMP +# endif + +/* GLUT API entry point declarations for Win32. */ +# ifdef GLUT_BUILDING_LIB +/* MSDN article 835326 says "When you build a DLL by using the 64-bit + version of the Microsoft Visual C++ Compiler and Linker, you may + receive Linker error number LNK4197 if a function has been declared + for export more than one time." GLUT builds with glut.def that + declares GLUT's EXPORTS list so do not use __declspec(dllexport) + to keep 64-bit compiler happy. */ +# define GLUTAPI /*__declspec(dllexport)*/ +# else +# ifdef _DLL +# define GLUTAPI __declspec(dllimport) +# else +# define GLUTAPI extern +# endif +# endif + +/* GLUT callback calling convention for Win32. */ +# define GLUTCALLBACK __cdecl + +# if (_MSC_VER >= 800) || defined(__MINGW32__) || defined(_STDCALL_SUPPORTED) || defined(__CYGWIN32__) +# define GLUTAPIENTRY __stdcall +# else +# define GLUTAPIENTRY +# endif + +#endif /* _WIN32 */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_WIN32) || defined(__CYGWIN__) +# ifndef GLUT_BUILDING_LIB +# if __BORLANDC__ +# if defined(_BUILDRTLDLL) +void __cdecl __export exit(int __status); +# else +void __cdecl exit(int __status); +# endif +# else +# if _MSC_VER >= 1200 + extern _CRTIMP __declspec(noreturn) void __cdecl exit(int); +# else + extern _CRTIMP void __cdecl exit(int); +# endif +# endif +# endif +#else +/* non-Win32 case. */ +/* Define APIENTRY and CALLBACK to nothing if we aren't on Win32. */ +# define APIENTRY +# define GLUT_APIENTRY_DEFINED +# define CALLBACK +/* Define GLUTAPI and GLUTCALLBACK as below if we aren't on Win32. */ +# define GLUTAPI extern +# define GLUTAPIENTRY +# define GLUTCALLBACK +/* Prototype exit for the non-Win32 case (see above). */ +# ifdef __GNUC__ +extern void exit(int __status) __attribute__((__noreturn__)); +# else +extern void exit(int); +# endif +#endif + +/** + GLUT API revision history: + + GLUT_API_VERSION is updated to reflect incompatible GLUT + API changes (interface changes, semantic changes, deletions, + or additions). + + GLUT_API_VERSION=1 First public release of GLUT. 11/29/94 + + GLUT_API_VERSION=2 Added support for OpenGL/GLX multisampling, + extension. Supports new input devices like tablet, dial and button + box, and Spaceball. Easy to query OpenGL extensions. + + GLUT_API_VERSION=3 glutMenuStatus added. + + GLUT_API_VERSION=4 glutInitDisplayString, glutWarpPointer, + glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic + video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc, + glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat, + glutJoystickFunc, glutForceJoystickFunc, glutStrokeWidthf, + glutStrokeLengthf (NOT FINALIZED!). +**/ +#ifndef GLUT_API_VERSION /* allow this to be overriden */ +#define GLUT_API_VERSION 3 +#endif + +/** + GLUT implementation revision history: + + GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT + API revisions and implementation revisions (ie, bug fixes). + + GLUT_XLIB_IMPLEMENTATION=1 mjk's first public release of + GLUT Xlib-based implementation. 11/29/94 + + GLUT_XLIB_IMPLEMENTATION=2 mjk's second public release of + GLUT Xlib-based implementation providing GLUT version 2 + interfaces. + + GLUT_XLIB_IMPLEMENTATION=3 mjk's GLUT 2.2 images. 4/17/95 + + GLUT_XLIB_IMPLEMENTATION=4 mjk's GLUT 2.3 images. 6/?/95 + + GLUT_XLIB_IMPLEMENTATION=5 mjk's GLUT 3.0 images. 10/?/95 + + GLUT_XLIB_IMPLEMENTATION=7 mjk's GLUT 3.1+ with glutWarpPoitner. 7/24/96 + + GLUT_XLIB_IMPLEMENTATION=8 mjk's GLUT 3.1+ with glutWarpPoitner + and video resize. 1/3/97 + + GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines. + + GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release. + + GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling. + + GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 beta with GameGLUT support. + + GLUT_XLIB_IMPLEMENTATION=14 mjk's GLUT 3.7 beta with f90gl friend interface. + + GLUT_XLIB_IMPLEMENTATION=15 mjk's GLUT 3.7 beta sync'ed with Mesa + + GLUT_XLIB_IMPLEMENTATION=16 mjk's early GLUT 3.8 + + GLUT_XLIB_IMPLEMENTATION=17 mjk's GLUT 3.8 with glutStrokeWidthf and glutStrokeLengthf +**/ +#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */ +#define GLUT_XLIB_IMPLEMENTATION 17 +#endif + +/* Display mode bit masks. */ +#define GLUT_RGB 0 +#define GLUT_RGBA GLUT_RGB +#define GLUT_INDEX 1 +#define GLUT_SINGLE 0 +#define GLUT_DOUBLE 2 +#define GLUT_ACCUM 4 +#define GLUT_ALPHA 8 +#define GLUT_DEPTH 16 +#define GLUT_STENCIL 32 +#if (GLUT_API_VERSION >= 2) +#define GLUT_MULTISAMPLE 128 +#define GLUT_STEREO 256 +#endif +#if (GLUT_API_VERSION >= 3) +#define GLUT_LUMINANCE 512 +#endif + +/* Mouse buttons. */ +#define GLUT_LEFT_BUTTON 0 +#define GLUT_MIDDLE_BUTTON 1 +#define GLUT_RIGHT_BUTTON 2 + +/* Mouse button state. */ +#define GLUT_DOWN 0 +#define GLUT_UP 1 + +#if (GLUT_API_VERSION >= 2) +/* function keys */ +#define GLUT_KEY_F1 1 +#define GLUT_KEY_F2 2 +#define GLUT_KEY_F3 3 +#define GLUT_KEY_F4 4 +#define GLUT_KEY_F5 5 +#define GLUT_KEY_F6 6 +#define GLUT_KEY_F7 7 +#define GLUT_KEY_F8 8 +#define GLUT_KEY_F9 9 +#define GLUT_KEY_F10 10 +#define GLUT_KEY_F11 11 +#define GLUT_KEY_F12 12 +/* directional keys */ +#define GLUT_KEY_LEFT 100 +#define GLUT_KEY_UP 101 +#define GLUT_KEY_RIGHT 102 +#define GLUT_KEY_DOWN 103 +#define GLUT_KEY_PAGE_UP 104 +#define GLUT_KEY_PAGE_DOWN 105 +#define GLUT_KEY_HOME 106 +#define GLUT_KEY_END 107 +#define GLUT_KEY_INSERT 108 +#endif + +/* Entry/exit state. */ +#define GLUT_LEFT 0 +#define GLUT_ENTERED 1 + +/* Menu usage state. */ +#define GLUT_MENU_NOT_IN_USE 0 +#define GLUT_MENU_IN_USE 1 + +/* Visibility state. */ +#define GLUT_NOT_VISIBLE 0 +#define GLUT_VISIBLE 1 + +/* Window status state. */ +#define GLUT_HIDDEN 0 +#define GLUT_FULLY_RETAINED 1 +#define GLUT_PARTIALLY_RETAINED 2 +#define GLUT_FULLY_COVERED 3 + +/* Color index component selection values. */ +#define GLUT_RED 0 +#define GLUT_GREEN 1 +#define GLUT_BLUE 2 + +#ifdef _WIN32 +/* Stroke font constants (use these in GLUT program). */ +#define GLUT_STROKE_ROMAN ((void*)0) +#define GLUT_STROKE_MONO_ROMAN ((void*)1) + +/* Bitmap font constants (use these in GLUT program). */ +#define GLUT_BITMAP_9_BY_15 ((void*)2) +#define GLUT_BITMAP_8_BY_13 ((void*)3) +#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4) +#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5) +#if (GLUT_API_VERSION >= 3) +#define GLUT_BITMAP_HELVETICA_10 ((void*)6) +#define GLUT_BITMAP_HELVETICA_12 ((void*)7) +#define GLUT_BITMAP_HELVETICA_18 ((void*)8) +#endif +#else +/* Stroke font opaque addresses (use constants instead in source code). */ +GLUTAPI void *glutStrokeRoman; +GLUTAPI void *glutStrokeMonoRoman; + +/* Stroke font constants (use these in GLUT program). */ +#define GLUT_STROKE_ROMAN (&glutStrokeRoman) +#define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman) + +/* Bitmap font opaque addresses (use constants instead in source code). */ +GLUTAPI void *glutBitmap9By15; +GLUTAPI void *glutBitmap8By13; +GLUTAPI void *glutBitmapTimesRoman10; +GLUTAPI void *glutBitmapTimesRoman24; +GLUTAPI void *glutBitmapHelvetica10; +GLUTAPI void *glutBitmapHelvetica12; +GLUTAPI void *glutBitmapHelvetica18; + +/* Bitmap font constants (use these in GLUT program). */ +#define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15) +#define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13) +#define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10) +#define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24) +#if (GLUT_API_VERSION >= 3) +#define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10) +#define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12) +#define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18) +#endif +#endif + +/* glutGet parameters. */ +#define GLUT_WINDOW_X ((GLenum) 100) +#define GLUT_WINDOW_Y ((GLenum) 101) +#define GLUT_WINDOW_WIDTH ((GLenum) 102) +#define GLUT_WINDOW_HEIGHT ((GLenum) 103) +#define GLUT_WINDOW_BUFFER_SIZE ((GLenum) 104) +#define GLUT_WINDOW_STENCIL_SIZE ((GLenum) 105) +#define GLUT_WINDOW_DEPTH_SIZE ((GLenum) 106) +#define GLUT_WINDOW_RED_SIZE ((GLenum) 107) +#define GLUT_WINDOW_GREEN_SIZE ((GLenum) 108) +#define GLUT_WINDOW_BLUE_SIZE ((GLenum) 109) +#define GLUT_WINDOW_ALPHA_SIZE ((GLenum) 110) +#define GLUT_WINDOW_ACCUM_RED_SIZE ((GLenum) 111) +#define GLUT_WINDOW_ACCUM_GREEN_SIZE ((GLenum) 112) +#define GLUT_WINDOW_ACCUM_BLUE_SIZE ((GLenum) 113) +#define GLUT_WINDOW_ACCUM_ALPHA_SIZE ((GLenum) 114) +#define GLUT_WINDOW_DOUBLEBUFFER ((GLenum) 115) +#define GLUT_WINDOW_RGBA ((GLenum) 116) +#define GLUT_WINDOW_PARENT ((GLenum) 117) +#define GLUT_WINDOW_NUM_CHILDREN ((GLenum) 118) +#define GLUT_WINDOW_COLORMAP_SIZE ((GLenum) 119) +#if (GLUT_API_VERSION >= 2) +#define GLUT_WINDOW_NUM_SAMPLES ((GLenum) 120) +#define GLUT_WINDOW_STEREO ((GLenum) 121) +#endif +#if (GLUT_API_VERSION >= 3) +#define GLUT_WINDOW_CURSOR ((GLenum) 122) +#endif +#define GLUT_SCREEN_WIDTH ((GLenum) 200) +#define GLUT_SCREEN_HEIGHT ((GLenum) 201) +#define GLUT_SCREEN_WIDTH_MM ((GLenum) 202) +#define GLUT_SCREEN_HEIGHT_MM ((GLenum) 203) +#define GLUT_MENU_NUM_ITEMS ((GLenum) 300) +#define GLUT_DISPLAY_MODE_POSSIBLE ((GLenum) 400) +#define GLUT_INIT_WINDOW_X ((GLenum) 500) +#define GLUT_INIT_WINDOW_Y ((GLenum) 501) +#define GLUT_INIT_WINDOW_WIDTH ((GLenum) 502) +#define GLUT_INIT_WINDOW_HEIGHT ((GLenum) 503) +#define GLUT_INIT_DISPLAY_MODE ((GLenum) 504) +#if (GLUT_API_VERSION >= 2) +#define GLUT_ELAPSED_TIME ((GLenum) 700) +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +#define GLUT_WINDOW_FORMAT_ID ((GLenum) 123) +#endif + +#if (GLUT_API_VERSION >= 2) +/* glutDeviceGet parameters. */ +#define GLUT_HAS_KEYBOARD ((GLenum) 600) +#define GLUT_HAS_MOUSE ((GLenum) 601) +#define GLUT_HAS_SPACEBALL ((GLenum) 602) +#define GLUT_HAS_DIAL_AND_BUTTON_BOX ((GLenum) 603) +#define GLUT_HAS_TABLET ((GLenum) 604) +#define GLUT_NUM_MOUSE_BUTTONS ((GLenum) 605) +#define GLUT_NUM_SPACEBALL_BUTTONS ((GLenum) 606) +#define GLUT_NUM_BUTTON_BOX_BUTTONS ((GLenum) 607) +#define GLUT_NUM_DIALS ((GLenum) 608) +#define GLUT_NUM_TABLET_BUTTONS ((GLenum) 609) +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +#define GLUT_DEVICE_IGNORE_KEY_REPEAT ((GLenum) 610) +#define GLUT_DEVICE_KEY_REPEAT ((GLenum) 611) +#define GLUT_HAS_JOYSTICK ((GLenum) 612) +#define GLUT_OWNS_JOYSTICK ((GLenum) 613) +#define GLUT_JOYSTICK_BUTTONS ((GLenum) 614) +#define GLUT_JOYSTICK_AXES ((GLenum) 615) +#define GLUT_JOYSTICK_POLL_RATE ((GLenum) 616) +#endif + +#if (GLUT_API_VERSION >= 3) +/* glutLayerGet parameters. */ +#define GLUT_OVERLAY_POSSIBLE ((GLenum) 800) +#define GLUT_LAYER_IN_USE ((GLenum) 801) +#define GLUT_HAS_OVERLAY ((GLenum) 802) +#define GLUT_TRANSPARENT_INDEX ((GLenum) 803) +#define GLUT_NORMAL_DAMAGED ((GLenum) 804) +#define GLUT_OVERLAY_DAMAGED ((GLenum) 805) + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +/* glutVideoResizeGet parameters. */ +#define GLUT_VIDEO_RESIZE_POSSIBLE ((GLenum) 900) +#define GLUT_VIDEO_RESIZE_IN_USE ((GLenum) 901) +#define GLUT_VIDEO_RESIZE_X_DELTA ((GLenum) 902) +#define GLUT_VIDEO_RESIZE_Y_DELTA ((GLenum) 903) +#define GLUT_VIDEO_RESIZE_WIDTH_DELTA ((GLenum) 904) +#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA ((GLenum) 905) +#define GLUT_VIDEO_RESIZE_X ((GLenum) 906) +#define GLUT_VIDEO_RESIZE_Y ((GLenum) 907) +#define GLUT_VIDEO_RESIZE_WIDTH ((GLenum) 908) +#define GLUT_VIDEO_RESIZE_HEIGHT ((GLenum) 909) +#endif + +/* glutUseLayer parameters. */ +#define GLUT_NORMAL ((GLenum) 0) +#define GLUT_OVERLAY ((GLenum) 1) + +/* glutGetModifiers return mask. */ +#define GLUT_ACTIVE_SHIFT 1 +#define GLUT_ACTIVE_CTRL 2 +#define GLUT_ACTIVE_ALT 4 + +/* glutSetCursor parameters. */ +/* Basic arrows. */ +#define GLUT_CURSOR_RIGHT_ARROW 0 +#define GLUT_CURSOR_LEFT_ARROW 1 +/* Symbolic cursor shapes. */ +#define GLUT_CURSOR_INFO 2 +#define GLUT_CURSOR_DESTROY 3 +#define GLUT_CURSOR_HELP 4 +#define GLUT_CURSOR_CYCLE 5 +#define GLUT_CURSOR_SPRAY 6 +#define GLUT_CURSOR_WAIT 7 +#define GLUT_CURSOR_TEXT 8 +#define GLUT_CURSOR_CROSSHAIR 9 +/* Directional cursors. */ +#define GLUT_CURSOR_UP_DOWN 10 +#define GLUT_CURSOR_LEFT_RIGHT 11 +/* Sizing cursors. */ +#define GLUT_CURSOR_TOP_SIDE 12 +#define GLUT_CURSOR_BOTTOM_SIDE 13 +#define GLUT_CURSOR_LEFT_SIDE 14 +#define GLUT_CURSOR_RIGHT_SIDE 15 +#define GLUT_CURSOR_TOP_LEFT_CORNER 16 +#define GLUT_CURSOR_TOP_RIGHT_CORNER 17 +#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18 +#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 19 +/* Inherit from parent window. */ +#define GLUT_CURSOR_INHERIT 100 +/* Blank cursor. */ +#define GLUT_CURSOR_NONE 101 +/* Fullscreen crosshair (if available). */ +#define GLUT_CURSOR_FULL_CROSSHAIR 102 +#endif + +/* GLUT initialization sub-API. */ +GLUTAPI void GLUTAPIENTRY glutInit(int *argcp, char **argv); +#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) +GLUTAPI void GLUTAPIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int)); +#ifndef GLUT_BUILDING_LIB +static void GLUTAPIENTRY glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); } +#define glutInit glutInit_ATEXIT_HACK +#endif +#endif +GLUTAPI void GLUTAPIENTRY glutInitDisplayMode(unsigned int mode); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +GLUTAPI void GLUTAPIENTRY glutInitDisplayString(const char *string); +#endif +GLUTAPI void GLUTAPIENTRY glutInitWindowPosition(int x, int y); +GLUTAPI void GLUTAPIENTRY glutInitWindowSize(int width, int height); +GLUTAPI void GLUTAPIENTRY glutMainLoop(void); + +/* GLUT window sub-API. */ +GLUTAPI int GLUTAPIENTRY glutCreateWindow(const char *title); +#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) +GLUTAPI int GLUTAPIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int)); +#ifndef GLUT_BUILDING_LIB +static int GLUTAPIENTRY glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); } +#define glutCreateWindow glutCreateWindow_ATEXIT_HACK +#endif +#endif +GLUTAPI int GLUTAPIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height); +GLUTAPI void GLUTAPIENTRY glutDestroyWindow(int win); +GLUTAPI void GLUTAPIENTRY glutPostRedisplay(void); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) +GLUTAPI void GLUTAPIENTRY glutPostWindowRedisplay(int win); +#endif +GLUTAPI void GLUTAPIENTRY glutSwapBuffers(void); +GLUTAPI int GLUTAPIENTRY glutGetWindow(void); +GLUTAPI void GLUTAPIENTRY glutSetWindow(int win); +GLUTAPI void GLUTAPIENTRY glutSetWindowTitle(const char *title); +GLUTAPI void GLUTAPIENTRY glutSetIconTitle(const char *title); +GLUTAPI void GLUTAPIENTRY glutPositionWindow(int x, int y); +GLUTAPI void GLUTAPIENTRY glutReshapeWindow(int width, int height); +GLUTAPI void GLUTAPIENTRY glutPopWindow(void); +GLUTAPI void GLUTAPIENTRY glutPushWindow(void); +GLUTAPI void GLUTAPIENTRY glutIconifyWindow(void); +GLUTAPI void GLUTAPIENTRY glutShowWindow(void); +GLUTAPI void GLUTAPIENTRY glutHideWindow(void); +#if (GLUT_API_VERSION >= 3) +GLUTAPI void GLUTAPIENTRY glutFullScreen(void); +GLUTAPI void GLUTAPIENTRY glutSetCursor(int cursor); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +GLUTAPI void GLUTAPIENTRY glutWarpPointer(int x, int y); +#endif + +/* GLUT overlay sub-API. */ +GLUTAPI void GLUTAPIENTRY glutEstablishOverlay(void); +GLUTAPI void GLUTAPIENTRY glutRemoveOverlay(void); +GLUTAPI void GLUTAPIENTRY glutUseLayer(GLenum layer); +GLUTAPI void GLUTAPIENTRY glutPostOverlayRedisplay(void); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) +GLUTAPI void GLUTAPIENTRY glutPostWindowOverlayRedisplay(int win); +#endif +GLUTAPI void GLUTAPIENTRY glutShowOverlay(void); +GLUTAPI void GLUTAPIENTRY glutHideOverlay(void); +#endif + +/* GLUT menu sub-API. */ +GLUTAPI int GLUTAPIENTRY glutCreateMenu(void (GLUTCALLBACK *func)(int)); +#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) +GLUTAPI int GLUTAPIENTRY __glutCreateMenuWithExit(void (GLUTCALLBACK *func)(int), void (__cdecl *exitfunc)(int)); +#ifndef GLUT_BUILDING_LIB +static int GLUTAPIENTRY glutCreateMenu_ATEXIT_HACK(void (GLUTCALLBACK *func)(int)) { return __glutCreateMenuWithExit(func, exit); } +#define glutCreateMenu glutCreateMenu_ATEXIT_HACK +#endif +#endif +GLUTAPI void GLUTAPIENTRY glutDestroyMenu(int menu); +GLUTAPI int GLUTAPIENTRY glutGetMenu(void); +GLUTAPI void GLUTAPIENTRY glutSetMenu(int menu); +GLUTAPI void GLUTAPIENTRY glutAddMenuEntry(const char *label, int value); +GLUTAPI void GLUTAPIENTRY glutAddSubMenu(const char *label, int submenu); +GLUTAPI void GLUTAPIENTRY glutChangeToMenuEntry(int item, const char *label, int value); +GLUTAPI void GLUTAPIENTRY glutChangeToSubMenu(int item, const char *label, int submenu); +GLUTAPI void GLUTAPIENTRY glutRemoveMenuItem(int item); +GLUTAPI void GLUTAPIENTRY glutAttachMenu(int button); +GLUTAPI void GLUTAPIENTRY glutDetachMenu(int button); + +/* GLUT window callback sub-API. */ +GLUTAPI void GLUTAPIENTRY glutDisplayFunc(void (GLUTCALLBACK *func)(void)); +GLUTAPI void GLUTAPIENTRY glutReshapeFunc(void (GLUTCALLBACK *func)(int width, int height)); +GLUTAPI void GLUTAPIENTRY glutKeyboardFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y)); +GLUTAPI void GLUTAPIENTRY glutMouseFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); +GLUTAPI void GLUTAPIENTRY glutMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); +GLUTAPI void GLUTAPIENTRY glutPassiveMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); +GLUTAPI void GLUTAPIENTRY glutEntryFunc(void (GLUTCALLBACK *func)(int state)); +GLUTAPI void GLUTAPIENTRY glutVisibilityFunc(void (GLUTCALLBACK *func)(int state)); +GLUTAPI void GLUTAPIENTRY glutIdleFunc(void (GLUTCALLBACK *func)(void)); +GLUTAPI void GLUTAPIENTRY glutTimerFunc(unsigned int millis, void (GLUTCALLBACK *func)(int value), int value); +GLUTAPI void GLUTAPIENTRY glutMenuStateFunc(void (GLUTCALLBACK *func)(int state)); +#if (GLUT_API_VERSION >= 2) +GLUTAPI void GLUTAPIENTRY glutSpecialFunc(void (GLUTCALLBACK *func)(int key, int x, int y)); +GLUTAPI void GLUTAPIENTRY glutSpaceballMotionFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); +GLUTAPI void GLUTAPIENTRY glutSpaceballRotateFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); +GLUTAPI void GLUTAPIENTRY glutSpaceballButtonFunc(void (GLUTCALLBACK *func)(int button, int state)); +GLUTAPI void GLUTAPIENTRY glutButtonBoxFunc(void (GLUTCALLBACK *func)(int button, int state)); +GLUTAPI void GLUTAPIENTRY glutDialsFunc(void (GLUTCALLBACK *func)(int dial, int value)); +GLUTAPI void GLUTAPIENTRY glutTabletMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); +GLUTAPI void GLUTAPIENTRY glutTabletButtonFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); +#if (GLUT_API_VERSION >= 3) +GLUTAPI void GLUTAPIENTRY glutMenuStatusFunc(void (GLUTCALLBACK *func)(int status, int x, int y)); +GLUTAPI void GLUTAPIENTRY glutOverlayDisplayFunc(void (GLUTCALLBACK *func)(void)); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +GLUTAPI void GLUTAPIENTRY glutWindowStatusFunc(void (GLUTCALLBACK *func)(int state)); +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +GLUTAPI void GLUTAPIENTRY glutKeyboardUpFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y)); +GLUTAPI void GLUTAPIENTRY glutSpecialUpFunc(void (GLUTCALLBACK *func)(int key, int x, int y)); +GLUTAPI void GLUTAPIENTRY glutJoystickFunc(void (GLUTCALLBACK *func)(unsigned int buttonMask, int x, int y, int z), int pollInterval); +#endif +#endif +#endif + +/* GLUT color index sub-API. */ +GLUTAPI void GLUTAPIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); +GLUTAPI GLfloat GLUTAPIENTRY glutGetColor(int ndx, int component); +GLUTAPI void GLUTAPIENTRY glutCopyColormap(int win); + +/* GLUT state retrieval sub-API. */ +GLUTAPI int GLUTAPIENTRY glutGet(GLenum type); +GLUTAPI int GLUTAPIENTRY glutDeviceGet(GLenum type); +#if (GLUT_API_VERSION >= 2) +/* GLUT extension support sub-API */ +GLUTAPI int GLUTAPIENTRY glutExtensionSupported(const char *name); +#endif +#if (GLUT_API_VERSION >= 3) +GLUTAPI int GLUTAPIENTRY glutGetModifiers(void); +GLUTAPI int GLUTAPIENTRY glutLayerGet(GLenum type); +#endif + +/* GLUT font sub-API */ +GLUTAPI void GLUTAPIENTRY glutBitmapCharacter(void *font, int character); +GLUTAPI int GLUTAPIENTRY glutBitmapWidth(void *font, int character); +GLUTAPI void GLUTAPIENTRY glutStrokeCharacter(void *font, int character); +GLUTAPI int GLUTAPIENTRY glutStrokeWidth(void *font, int character); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +GLUTAPI int GLUTAPIENTRY glutBitmapLength(void *font, const unsigned char *string); +GLUTAPI int GLUTAPIENTRY glutStrokeLength(void *font, const unsigned char *string); +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 17) +GLUTAPI float GLUTAPIENTRY glutStrokeWidthf(void *font, int character); +GLUTAPI float GLUTAPIENTRY glutStrokeLengthf(void *font, const unsigned char *string); +#endif + +/* GLUT pre-built models sub-API */ +GLUTAPI void GLUTAPIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks); +GLUTAPI void GLUTAPIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); +GLUTAPI void GLUTAPIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); +GLUTAPI void GLUTAPIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); +GLUTAPI void GLUTAPIENTRY glutWireCube(GLdouble size); +GLUTAPI void GLUTAPIENTRY glutSolidCube(GLdouble size); +GLUTAPI void GLUTAPIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); +GLUTAPI void GLUTAPIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); +GLUTAPI void GLUTAPIENTRY glutWireDodecahedron(void); +GLUTAPI void GLUTAPIENTRY glutSolidDodecahedron(void); +GLUTAPI void GLUTAPIENTRY glutWireTeapot(GLdouble size); +GLUTAPI void GLUTAPIENTRY glutSolidTeapot(GLdouble size); +GLUTAPI void GLUTAPIENTRY glutWireOctahedron(void); +GLUTAPI void GLUTAPIENTRY glutSolidOctahedron(void); +GLUTAPI void GLUTAPIENTRY glutWireTetrahedron(void); +GLUTAPI void GLUTAPIENTRY glutSolidTetrahedron(void); +GLUTAPI void GLUTAPIENTRY glutWireIcosahedron(void); +GLUTAPI void GLUTAPIENTRY glutSolidIcosahedron(void); + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +/* GLUT video resize sub-API. */ +GLUTAPI int GLUTAPIENTRY glutVideoResizeGet(GLenum param); +GLUTAPI void GLUTAPIENTRY glutSetupVideoResizing(void); +GLUTAPI void GLUTAPIENTRY glutStopVideoResizing(void); +GLUTAPI void GLUTAPIENTRY glutVideoResize(int x, int y, int width, int height); +GLUTAPI void GLUTAPIENTRY glutVideoPan(int x, int y, int width, int height); + +/* GLUT debugging sub-API. */ +GLUTAPI void GLUTAPIENTRY glutReportErrors(void); +#endif + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +/* GLUT device control sub-API. */ +/* glutSetKeyRepeat modes. */ +#define GLUT_KEY_REPEAT_OFF 0 +#define GLUT_KEY_REPEAT_ON 1 +#define GLUT_KEY_REPEAT_DEFAULT 2 + +/* Joystick button masks. */ +#define GLUT_JOYSTICK_BUTTON_A 1 +#define GLUT_JOYSTICK_BUTTON_B 2 +#define GLUT_JOYSTICK_BUTTON_C 4 +#define GLUT_JOYSTICK_BUTTON_D 8 + +GLUTAPI void GLUTAPIENTRY glutIgnoreKeyRepeat(int ignore); +GLUTAPI void GLUTAPIENTRY glutSetKeyRepeat(int repeatMode); +GLUTAPI void GLUTAPIENTRY glutForceJoystickFunc(void); + +/* GLUT game mode sub-API. */ +/* glutGameModeGet. */ +#define GLUT_GAME_MODE_ACTIVE ((GLenum) 0) +#define GLUT_GAME_MODE_POSSIBLE ((GLenum) 1) +#define GLUT_GAME_MODE_WIDTH ((GLenum) 2) +#define GLUT_GAME_MODE_HEIGHT ((GLenum) 3) +#define GLUT_GAME_MODE_PIXEL_DEPTH ((GLenum) 4) +#define GLUT_GAME_MODE_REFRESH_RATE ((GLenum) 5) +#define GLUT_GAME_MODE_DISPLAY_CHANGED ((GLenum) 6) + +GLUTAPI void GLUTAPIENTRY glutGameModeString(const char *string); +GLUTAPI int GLUTAPIENTRY glutEnterGameMode(void); +GLUTAPI void GLUTAPIENTRY glutLeaveGameMode(void); +GLUTAPI int GLUTAPIENTRY glutGameModeGet(GLenum mode); +#endif + +#ifdef __cplusplus +} + +#endif + +#ifdef GLUT_APIENTRY_DEFINED +# undef GLUT_APIENTRY_DEFINED +# undef APIENTRY +#endif + +#ifdef GLUT_WINGDIAPI_DEFINED +# undef GLUT_WINGDIAPI_DEFINED +# undef WINGDIAPI +#endif + +#ifdef GLUT_DEFINED___CDECL +# undef GLUT_DEFINED___CDECL +# undef __cdecl +#endif + +#ifdef GLUT_DEFINED__CRTIMP +# undef GLUT_DEFINED__CRTIMP +# undef _CRTIMP +#endif + +#endif /* __glut_h__ */ diff --git a/Extras/sph/common/image.cpp b/Extras/sph/common/image.cpp new file mode 100644 index 0000000..6a2fb48 --- /dev/null +++ b/Extras/sph/common/image.cpp @@ -0,0 +1,1948 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 "image.h" + +#include +#include +#include +#include +#include + +#include "gl_helper.h" + +// Link with JPEG library on platforms that support it. +#ifdef USE_JPEG + #include + #include + #include "jerror.h" +#endif + +#ifndef WIN32 + #include +#endif + + +// Disable warnings on depricated functions +#pragma warning( disable : 4995) // removes warning 4995 - depricated function +#pragma warning( disable : 4996) // removes warning 4996 - depricated function + +#ifdef WIN32 + #define GL_TEXTURE_CUBE_MAP 0x8513 + #define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 + #define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 + #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 + #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 + #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 + #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 + #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#endif + +static const int maxvals[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 }; + +static inline unsigned char val2bits (double v, int b) +{ + return (unsigned char) (floor(v * maxvals[b] + 0.5) / maxvals[b] * 255); +} + + +Image::Image () +{ + width = 0; + height = 0; + channels = 0; + bits = 0; + maxValue = 0; + pixels = NULL; + owns = true; +} + + +Image::Image (int width_, int height_) +{ + create ( width_, height_, 3 ); +} + + +Image::Image (int width_, int height_, int channels_) +{ + create (width_, height_, channels_ ); +} + +void Image::create ( int width_, int height_, int channels_ ) +{ + width = width_; + height = height_; + channels = channels_; + bits = 8; + maxValue = 255; + + assert(width > 0 && height > 0 && + (channels == 1 || channels == 3 || channels == 4) && + bits > 0 && bits < 9 + ); + + pixels = new unsigned char[width*height*channels]; + owns = true; + memset(pixels, 0, width*height*channels); + + clear ( Pixel(0,0,0 ) ); + + glGenTextures( 1, (GLuint*) &imgID ); + glBindTexture ( GL_TEXTURE_2D, imgID ); + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glPixelStorei( GL_UNPACK_ALIGNMENT, 1); + refresh (); +} + +void Image::draw () +{ + draw ( 0, 0 ); +} + +void Image::draw ( float x, float y ) +{ + glEnable ( GL_TEXTURE_2D ); + glColor4f ( 1,1,1,1); + glBindTexture ( GL_TEXTURE_2D, (GLuint) imgID ); + glBegin ( GL_QUADS ); + glTexCoord2f ( 0, 1); glVertex2f ( x, y ); + glTexCoord2f ( 1, 1 ); glVertex2f ( x+width, y ); + glTexCoord2f ( 1, 0 ); glVertex2f ( x+width, y+height ); + glTexCoord2f ( 0, 0 ); glVertex2f ( x, y+height ); + glEnd (); +} + + +Image::Image (int width_, int height_, int channels_, int bits_) +{ + width = width_; + height = height_; + channels = channels_; + bits = bits_; + maxValue = val2bits(1.0,bits); + + assert(width > 0 && height > 0 && + (channels == 1 || channels == 3 || channels == 4) && + bits > 0 && bits < 9 + ); + + pixels = new unsigned char[width*height*channels]; + owns = true; + memset(pixels, 0, width*height*channels); +} + + +Image::Image (const char* filename) +{ + width = 0; + height = 0; + channels = 0; + bits = 0; + maxValue = 0; + pixels = NULL; + owns = true; + + read(filename); +} + + +Image::~Image () +{ + if (pixels && owns) delete[] pixels; +} + + +Image::Image (const Image& image) +{ + width = image.width; + height = image.height; + channels = image.channels; + bits = image.bits; + maxValue = image.maxValue; + pixels = new unsigned char[width*height*channels]; + owns = true; + + for (int i = 0; i < width*height*channels; ++i) + pixels[i] = image.pixels[i]; +} + + +Image& Image::operator= (const Image& image) +{ + if (&image == this) return *this; + + if (pixels) delete[] pixels; + + width = image.width; + height = image.height; + channels = image.channels; + bits = image.bits; + maxValue = image.maxValue; + pixels = new unsigned char[width*height*channels]; + owns = true; + + for (int i = 0; i < width*height*channels; ++i) + pixels[i] = image.pixels[i]; + + return *this; +} + + +void Image::setPixels ( unsigned char *newPixels ) +{ + if( bad() || ! newPixels ) + return; + + //if( owns && pixels ) + // delete [] pixels; + + memcpy ( pixels, newPixels, width*height*channels ); +} + + +bool Image::good () +{ + return (width > 0 && height > 0 && + (channels == 1 || channels == 3 || channels == 4) && + bits > 0 && bits < 9 && pixels); +} + + +bool Image::bad () +{ + return !good(); +} + +void Image::clear () +{ + clear ( Pixel(0,0,0) ); +} + + +void Image::clear ( Pixel pixel ) +{ + unsigned char* buf = pixels; + + if ( channels == 3) { + for (int n=0; n < width*height; n++) { + *buf++ = (unsigned char) (pixel.r*255.0f); + *buf++ = (unsigned char) (pixel.g*255.0f); + *buf++ = (unsigned char) (pixel.b*255.0f); + } + } else { + for (int n=0; n < width*height; n++) { + *buf++ = (unsigned char) ( pixel.r*255.0f); + *buf++ = (unsigned char) (pixel.g*255.0f); + *buf++ = (unsigned char) (pixel.b*255.0f); + *buf++ = (unsigned char) (pixel.a*255.0f); + } + } +} + + +int Image::index (int x, int y, int c) +{ + return (((height - y - 1) * width + x) * channels + c); +} + + +double Image::getPixel (int x, int y, int channel) +{ + assert(good()); + assert((x >= 0) && + (x < width) && + (y >= 0) && + (y < height) && + (channel >= 0) && + (channel < channels)); + + return pixels[index(x,y,channel)] / 255.0; +} + + +double Image::getPixel_ (int x, int y, int channel) +{ + if (!good() || + (x < 0) || + (x >= width) || + (y < 0) || + (y >= height) || + (channel < 0) || + (channel >= channels)) + return 0.0; + + return getPixel(x,y,channel); +} + + +Pixel Image::getPixel (int x, int y) +{ + assert(good()); + assert((x >= 0) && + (x < width) && + (y >= 0) && + (y < height)); + + Pixel pixel; + memset(&pixel, 0, sizeof(Pixel)); + + switch (channels) + { + case 4: + pixel.a = pixels[index(x,y,IALPHA)] / 255.0; + + case 3: + pixel.b = pixels[index(x,y,IBLUE)] / 255.0; + pixel.g = pixels[index(x,y,IGREEN)] / 255.0; + + case 1: + pixel.r = pixels[index(x,y,IRED)] / 255.0; + + default: + break; + } + return pixel; +} + + +Pixel Image::getPixel_ (int x, int y) +{ + if (!good() || + (x < 0) || + (x >= width) || + (y < 0) || + (y >= height)) + { + Pixel pixel; + memset(&pixel, 0, sizeof(Pixel)); + return pixel; + } + + return getPixel(x,y); +} + + +Pixel& Image::getPixel (int x, int y, Pixel& pixel) +{ + assert(good()); + assert((x >= 0) && + (x < width) && + (y >= 0) && + (y < height)); + + memset(&pixel, 0, sizeof(Pixel)); + + switch (channels) + { + case 4: + pixel.a = pixels[index(x,y,IALPHA)] / 255.0; + + case 3: + pixel.b = pixels[index(x,y,IBLUE)] / 255.0; + pixel.g = pixels[index(x,y,IGREEN)] / 255.0; + + case 1: + pixel.r = pixels[index(x,y,IRED)] / 255.0; + + default: + break; + } + return pixel; +} + + +Pixel& Image::getPixel_ (int x, int y, Pixel& pixel) +{ + if (!good() || + (x < 0) || + (x >= width) || + (y < 0) || + (y >= height)) + { + memset(&pixel, 0, sizeof(Pixel)); + return pixel; + } + + return getPixel(x,y,pixel); +} + + +void Image::setPixel (int x, int y, int channel, double value) +{ + assert(good()); + assert ( (channel >= 0) && (channel < channels)); + assert( (value >= 0.0) && (value <= 1.0)); + + if ( (x >= 0) && (x < width) && (y >= 0) && (y < height) ) + pixels[index(x,y,channel)] = val2bits(value, bits); +} + +void Image::setPixel_ (int x, int y, int channel, double value) +{ + if (!good() || + (x < 0) || + (x >= width) || + (y < 0) || + (y >= height) || + (channel < 0) || + (channel >= channels) || + (value < 0.0) || + (value > 1.0)) + return; + + setPixel(x,y,channel,value); +} + +void Image::setPixel4 ( int x, int y, Pixel pixel ) +{ + setPixel ( x, y, pixel ); + setPixel ( x+1, y, pixel ); + setPixel ( x, y+1, pixel ); + setPixel ( x+1, y+1, pixel ); +} + +void Image::setPixel (int x, int y, Pixel pixel) +{ + assert(good()); + if ( x < 0 || x >= width || y < 0 || y >= height ) return; + + switch (channels) + { + case 4: + pixels[index(x,y,IALPHA)] = val2bits(pixel.a, bits); + + case 3: + pixels[index(x,y,IBLUE)] = val2bits(pixel.b, bits); + pixels[index(x,y,IGREEN)] = val2bits(pixel.g, bits); + + case 1: + pixels[index(x,y,IRED)] = val2bits(pixel.r, bits); + + default: + break; + } +} + +void Image::setAlpha (int x, int y, double value) +{ + assert(good()); + pixels[index(x,y,IALPHA)] = val2bits(value, bits); +} + + +void Image::setPixel_ (int x, int y, Pixel pixel) +{ + if (!good() || + (x < 0) || + (x >= width) || + (y < 0) || + (y >= height)) + return; + + setPixel(x,y,pixel); +} + + +#ifndef DISABLE_OPENGL + +void Image::glReadPixelsWrapper () +{ + assert(good()); + + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + switch (channels) + { + case 1: + glReadPixels(0, 0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels); + break; + case 3: + glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); + break; + case 4: + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + break; + default: + break; + } +} + +void Image::glDrawPixelsWrapper () +{ + assert(good()); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + switch (channels) + { + case 1: + glDrawPixels(width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels); + break; + case 3: + glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); + break; + + case 4: + glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + break; + + default: + break; + } +} + +void Image::refresh () +{ + glTexImage2DWrapper (); +} + + +void Image::glTexImage2DWrapper () +{ + assert(good()); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + switch (channels) + { + case 1: + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, + GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels); + break; + + case 3: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, + GL_RGB, GL_UNSIGNED_BYTE, pixels); + break; + + case 4: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, pixels); + break; + + default: + break; + } +} + +void Image::glTexImageCubeWrapper ( int i ) +{ + assert(good()); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + switch (channels) + { + case 1: + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, GL_LUMINANCE, width, height, 0, + GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels); + break; + case 3: + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, GL_RGB, width, height, 0, + GL_RGB, GL_UNSIGNED_BYTE, pixels); + break; + case 4: + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, GL_RGBA, width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, pixels); + break; + default: + break; + } +} + +void Image::glTexSubImage2DWrapper ( int x, int y) +{ + assert(good()); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + switch (channels) + { + case 1: + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, + GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels); + break; + + case 3: + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, + GL_RGB, GL_UNSIGNED_BYTE, pixels); + break; + + case 4: + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, + GL_RGBA, GL_UNSIGNED_BYTE, pixels); + break; + + default: + break; + } +} + + +#endif // DISABLE_OPENGL + +int Image::read (const char* filename ) +{ + return read ( filename, 0x0 ); +} + +int Image::read (const char* filename, const char* alphaname ) +{ + FILE *file, *file_a; + + // Open image file + file = fopen( filename, "rb" ); + if (!file) { + printf ( "Cannot find file: %s\n", filename ); + perror("Image::read"); + return -1; + } + // Open alpha file + if ( alphaname != 0x0 ) { + file_a = fopen( alphaname, "rb" ); + if (!file_a) { + printf ( "Cannot find file: %s\n", alphaname ); + perror("Image::read"); + return -1; + } + } else { + file_a = 0x0; + } + // Get image file format + unsigned char type[4]; + fread((void*) type, sizeof(char), 4, file); + if (ferror(file)) { + fclose(file); + printf ( "Error reading file: %s\n", filename ); + perror("Image::read"); + return -1; + } + + int result = 0; + + fseek(file, 0, SEEK_SET); + + if (type[0] == 'P' && (type[1] == '1' || type[1] == '2' || type[1] == '3' || type[1] == '5' || type[1] == '6')) { + result = readPNM(file); + } else if ((type[0] == 0x4D && type[1] == 0x42) || (type[1] == 0x4D && type[0] == 0x42)) { + result = readBMP(file, file_a, true ); + } else if (type[0] == 0x49 && type[1] == 0x49 && type[2] == 0x42 ) { + //result = readTIF(file); + } +#ifdef USE_JPEG + else if ((type[0] == 0xD8 && type[1] == 0xFF) || (type[1] == 0xD8 && type[0] == 0xFF)) { + result = readJPG(file); + } +#endif + else { + fprintf( stderr, "Image::read: Unrecognized file type.\nMaybe it is a JPEG file. Either supply the file or set USE_JPEG.\n" ); + result = -1; + } + fclose(file); + return result; +} + + +int Image::write (const char* filename) +{ + size_t len = strlen(filename); + const char* ext = &(filename[len-4]); + int result = 0; + + if (strncmp(ext, ".pnm", 4) == 0) + { + result = writePNM(filename); + } + else if (strncmp(ext, ".bmp", 4) == 0) + { + result = writeBMP(filename); + } +#ifdef USE_JPEG + else if (strncmp(ext, ".jpg", 4) == 0) + { + result = writeJPG(filename); + } +#endif + else + { + char filenamewithext[1024]; +#ifdef WIN32 + _snprintf( filenamewithext, 1024, "%.1019s.pnm", filename ); +#else + snprintf( filenamewithext, 1024, "%.1019s.pnm", filename ); +#endif + result = writePNM(filenamewithext); + } + + return result; +} + +// +// .JPG file manipulation +// +// This code enabled only if JPEG is supported. +// +#ifdef USE_JPEG + + int Image::readJPG (const char* filename) + { + FILE* file = fopen(filename, "rb" ); + + if (!file) + { + printf ( "Cannot find file: %s\n", filename ); + perror("Image::readJPG"); + //_getch(); + return -1; + } + + int result = readJPG(file); + fclose(file); + + return result; + } + + + int Image::writeJPG (const char* filename) + { + FILE* file = fopen(filename, "wb"); + + if (!file) + { + perror("Image::writeJPG"); + return -1; + } + + int result = writeJPG(file); + fclose(file); + + if (result == -1) + unlink(filename); + + return result; + } + + + struct my_error_mgr + { + struct jpeg_error_mgr pub; + jmp_buf setjmp_buffer; + }; + + + typedef struct my_error_mgr * my_error_ptr; + + + void my_error_exit (j_common_ptr cinfo) + { + my_error_ptr myerr = (my_error_ptr) cinfo->err; + (*cinfo->err->output_message) (cinfo); + longjmp(myerr->setjmp_buffer, 1); + } + + + int Image::readJPG (FILE* file) + { + struct jpeg_decompress_struct cinfo; + struct my_error_mgr jerr; + JSAMPROW row_pointer[1]; + + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; + + // failure jump point + if (setjmp(jerr.setjmp_buffer)) + { + jpeg_destroy_decompress(&cinfo); + fprintf(stderr, "Image::readJPG: jpeg decompression error"); + return -1; + } + + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo, file); + jpeg_read_header(&cinfo, TRUE); + jpeg_start_decompress(&cinfo); + + if (cinfo.out_color_space != JCS_RGB && + cinfo.out_color_space != JCS_GRAYSCALE) + { + fprintf(stderr, "Image::readJPG: unrecognized colorspace"); + return -1; + } + + width = cinfo.output_width; + height = cinfo.output_height; + bits = 8; + channels = cinfo.out_color_components; + pixels = new unsigned char[width*height*channels]; + memset(pixels, 0, width*height*channels); + + int row_stride = width * channels; + + while (cinfo.output_scanline < cinfo.output_height) + { + row_pointer[0] = &pixels[(height - cinfo.output_scanline - 1) * row_stride]; + jpeg_read_scanlines(&cinfo, row_pointer, 1); + } + + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + + return 0; + } + + + int Image::writeJPG (FILE* file) + { + if (!good()) + { + fprintf(stderr, "Image::writeJPG: bad image\n"); + return -1; + } + + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + JSAMPROW row_pointer[1]; + int row_stride = width * channels; + + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + jpeg_stdio_dest(&cinfo, file); + + cinfo.image_width = width; + cinfo.image_height = height; + cinfo.input_components = channels; + cinfo.in_color_space = (channels == 3) ? JCS_RGB : JCS_GRAYSCALE; + + jpeg_set_defaults(&cinfo); + + jpeg_set_quality (&cinfo, 100, TRUE); + + jpeg_start_compress(&cinfo, TRUE); + + while (cinfo.next_scanline < cinfo.image_height) + { + row_pointer[0] = & pixels[(height - cinfo.next_scanline - 1) * row_stride]; + jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + + return 0; + } + +#endif // USE_JPEG + + + +// +// .BMP file manipulation +// + +int Image::readBMP (const char* filename ) +{ + FILE* file = fopen(filename, "rb"); + if (!file) + { + perror("Image::readBMP"); + return -1; + } + + int result = readBMP (file, 0x0, true); + fclose(file); + + return result; +} + + +int Image::writeBMP (const char* filename) +{ + FILE* file = fopen(filename, "wb"); + + if (!file) + { + perror("Image::writeBMP"); + return -1; + } + + int result = writeBMP(file); + fclose(file); + + if (result == -1) + unlink(filename); + + return result; +} + + +#if !defined(WIN32) + + typedef unsigned char BYTE; + typedef unsigned short int WORD; + typedef unsigned int DWORD; + typedef int LONG; + + + typedef struct tagBITMAPFILEHEADER { + WORD bfType; + DWORD bfSize; + WORD bfReserved1; + WORD bfReserved2; + DWORD bfOffBits; + } BITMAPFILEHEADER; + + + + typedef struct tagBITMAPINFOHEADER { + DWORD biSize; + LONG biWidth; + LONG biHeight; + WORD biPlanes; + WORD biBitCount; + DWORD biCompression; + DWORD biSizeImage; + LONG biXPelsPerMeter; + LONG biYPelsPerMeter; + DWORD biClrUsed; + DWORD biClrImportant; + } BITMAPINFOHEADER; + + /* constants for the biCompression field */ + #define BI_RGB 0L + #define BI_RLE8 1L + #define BI_RLE4 2L + #define BI_BITFIELDS 3L + + + typedef struct tagRGBTRIPLE { + BYTE rgbtBlue; + BYTE rgbtGreen; + BYTE rgbtRed; + } RGBTRIPLE; + + + typedef struct { //tagRGBQUAD + BYTE rgbBlue; + BYTE rgbGreen; + BYTE rgbRed; + BYTE rgbReserved; + } RGBQUAD; + +#endif // !defined(WIN32) + + +/* Some magic numbers */ + +#define BMP_BF_TYPE 0x4D42 +/* word BM */ + +#define BMP_BF_OFF_BITS 54 +/* 14 for file header + 40 for info header (not sizeof(), but packed size) */ + +#define BMP_BI_SIZE 40 +/* packed size of info header */ + + +/* Reads a WORD from a file in little endian format */ +static WORD WordReadLE (FILE* fp) +{ + WORD lsb, msb; + + lsb = fgetc(fp); + msb = fgetc(fp); + return (msb << 8) | lsb; +} + + + +/* Writes a WORD to a file in little endian format */ +static void WordWriteLE(WORD x, FILE* fp) +{ + BYTE lsb, msb; + + lsb = (BYTE) (x & 0x00FF); + msb = (BYTE) (x >> 8); + fputc(lsb, fp); + fputc(msb, fp); +} + + + +/* Reads a DWORD word from a file in little endian format */ +static DWORD DWordReadLE(FILE* fp) +{ + DWORD b1, b2, b3, b4; + + b1 = fgetc(fp); + b2 = fgetc(fp); + b3 = fgetc(fp); + b4 = fgetc(fp); + return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1; +} + + + +/* Writes a DWORD to a file in little endian format */ +static void DWordWriteLE(DWORD x, FILE* fp) +{ + unsigned char b1, b2, b3, b4; + + b1 = (x & 0x000000FF); + b2 = ((x >> 8) & 0x000000FF); + b3 = ((x >> 16) & 0x000000FF); + b4 = ((x >> 24) & 0x000000FF); + fputc(b1, fp); + fputc(b2, fp); + fputc(b3, fp); + fputc(b4, fp); +} + + + +/* Reads a LONG word from a file in little endian format */ +static LONG LongReadLE(FILE* fp) +{ + LONG b1, b2, b3, b4; + + b1 = fgetc(fp); + b2 = fgetc(fp); + b3 = fgetc(fp); + b4 = fgetc(fp); + return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1; +} + + + +/* Writes a LONG to a file in little endian format */ +static void LongWriteLE(LONG x, FILE* fp) +{ + char b1, b2, b3, b4; + + b1 = (x & 0x000000FF); + b2 = ((x >> 8) & 0x000000FF); + b3 = ((x >> 16) & 0x000000FF); + b4 = ((x >> 24) & 0x000000FF); + fputc(b1, fp); + fputc(b2, fp); + fputc(b3, fp); + fputc(b4, fp); +} + + +int bitcount (DWORD w) +{ + w = (0x55555555 & w) + (0x55555555 & (w>> 1)); + w = (0x33333333 & w) + (0x33333333 & (w>> 2)); + w = (0x0f0f0f0f & w) + (0x0f0f0f0f & (w>> 4)); + w = (0x00ff00ff & w) + (0x00ff00ff & (w>> 8)); + w = (0x0000ffff & w) + (0x0000ffff & (w>>16)); + return w; +} + + +// read BMP palette +int Image::readPaletteBMP ( FILE* fp, RGBQUAD*& palette, int bit_count ) +{ + bool bColor; + int palSize = 0; + switch ( bit_count ) { + case 1: palSize = 2; break; + case 4: palSize = 16; break; + case 8: palSize = 256; break; + } + if ( palSize != 0 ) { + palette = new RGBQUAD[ palSize ]; + memset(palette, 0, palSize * sizeof(RGBQUAD)); + fread((void*) palette, sizeof(RGBQUAD), palSize, fp ); + bColor = false; + for (int i = 0; !bColor && i < 2; ++i) { + bColor = bColor || (palette[i].rgbRed != palette[i].rgbGreen) || (palette[i].rgbBlue != palette[i].rgbGreen); + } + } else { + palette = 0x0; + } + return palSize; +} + + + +int Image::readBMP (FILE* fp, FILE* fp_a, bool bBaseImg ) +{ + RGBQUAD* palette; + int palSize; + int index; + Pixel pixel; + WORD red, green, blue; + DWORD bluemask, greenmask, redmask; + int bluewidth, greenwidth; + bool done; + + if ( bBaseImg ) { + if (pixels && owns) delete[] pixels; + } + + BITMAPFILEHEADER bmfh; + BITMAPINFOHEADER bmih; + + /* Read file header */ + bmfh.bfType = WordReadLE(fp); + bmfh.bfSize = DWordReadLE(fp); + bmfh.bfReserved1 = WordReadLE(fp); + bmfh.bfReserved2 = WordReadLE(fp); + bmfh.bfOffBits = DWordReadLE(fp); + + /* Check file header */ + if (bmfh.bfType != BMP_BF_TYPE) { + fprintf( stderr, "Image::readBMP: unrecognized type\n" ); + return -1; + } + + /* Read info header */ + bmih.biSize = DWordReadLE(fp); + bmih.biWidth = LongReadLE(fp); + bmih.biHeight = LongReadLE(fp); + bmih.biPlanes = WordReadLE(fp); + bmih.biBitCount = WordReadLE(fp); + bmih.biCompression = DWordReadLE(fp); + bmih.biSizeImage = DWordReadLE(fp); + bmih.biXPelsPerMeter = LongReadLE(fp); + bmih.biYPelsPerMeter = LongReadLE(fp); + bmih.biClrUsed = DWordReadLE(fp); + bmih.biClrImportant = DWordReadLE(fp); + + if ((bmih.biWidth <= 0) || (bmih.biHeight <= 0) || (bmih.biPlanes != 1)) { + fprintf(stderr, "Image::readBMP: malformed file\n"); + return -1; + } + + /* Creates the image */ + if ( bBaseImg ) { + // Create storage and load base image + width = bmih.biWidth; + height = bmih.biHeight; + + // Read palette (if there is one) + palSize = readPaletteBMP ( fp, palette, bmih.biBitCount ); + + switch ( bmih.biBitCount ) { + case 1: channels = 1; // 1 byte per bit - *bad storage, 2 color (B & W) + case 4: channels = 1; // 1 byte per 4-bits - not great, 16 color, index mode + case 8: channels = 1; // 1 byte per pixel, 256 color, index mode + case 16: channels = 3; // 2 byte per pixel, 16-bit color + case 24: channels = 3; // 3 byte per pixel (RGB), 24-bit color + case 32: channels = 3; // 4 byte per pixel, 32-bit color, compressed down to 24-bit + } + if ( palSize != 0 ) channels += 2; // use 3 channels for images with color palettes + if ( fp_a != 0x0 && channels == 3 ) channels = 4; // extra channel for alpha + + // Create storage for new image (including alpha) + bits = 8; + maxValue = 255; + pixels = new unsigned char[width*height*channels]; + owns = true; + memset(pixels, 0, width*height*channels); + } else { + // Load alpha image + bits = 8; + maxValue = 255; + + // Read palette (if there is one) + palSize = readPaletteBMP ( fp, palette, bmih.biBitCount ); + } + + // Determine line length + int scanlinelength; + if ((width * bmih.biBitCount) % 32 == 0) scanlinelength = width * bmih.biBitCount / 8; + else scanlinelength = (width * bmih.biBitCount / 32 + 1) * 4; + + + // Read all the color info / data + switch (bmih.biBitCount) { + case 1: // 1 bit - monochrome, index mode + BYTE* scanlineByte; + scanlineByte = new BYTE[scanlinelength]; + fseek(fp, bmfh.bfOffBits, SEEK_SET); + for (int y = 0; y < height; ++y) { + fread((void*) scanlineByte, scanlinelength, 1, fp); + for (int x = 0; x < width; ++x) { + index = (scanlineByte[x/8] >> (7 - (x % 8))) & 0x01; + if ( bBaseImg ) { + pixel.r = palette[index].rgbRed / 255.0; + pixel.g = palette[index].rgbGreen / 255.0; + pixel.b = palette[index].rgbBlue / 255.0; + setPixel (x, height - 1 - y, pixel); + } else { + setAlpha (x, height - 1 - y, index / 255.0f ); + } + } + } + delete [] scanlineByte; + break; + case 4: // 4 bit - 16 color, index mode + if (bmih.biCompression == BI_RGB) { // 4-bit, uncompressed data + BYTE* scanlineByte; + scanlineByte = new BYTE[scanlinelength]; + fseek(fp, bmfh.bfOffBits, SEEK_SET); + for (int y = 0; y < height; ++y) { + fread((void*) scanlineByte, scanlinelength, 1, fp); + for (int x = 0; x < width; ++x) { + if (x % 2 == 0) index = (scanlineByte[x/2] >> 4) & 0x0F; + else index = scanlineByte[x/2] & 0x0F; + if ( bBaseImg ) { + pixel.r = palette[index].rgbRed / 255.0; + pixel.g = palette[index].rgbGreen / 255.0; + pixel.b = palette[index].rgbBlue / 255.0; + setPixel (x, height - 1 - y, pixel); + } else { + setAlpha (x, height - 1 - y, index/255.0f); + } + } + } + delete [] scanlineByte; + } else if (bmih.biCompression == BI_RLE4) { // 4-bit RLE compression + unsigned char rleCode[2]; + int curx = 0; + int cury = 0; + done = false; + fseek(fp, bmfh.bfOffBits, SEEK_SET); + while (!done && fp) { + fread((void*) rleCode, sizeof(char), 2, fp); + if (ferror(fp)) done = true; + if (rleCode[0] == 0 && rleCode[1] < 3) { // escape code (next byte is how) + if (rleCode[1] == 0) { // code 0 - goto next line + curx = 0; + ++cury; + if (cury >= height) done = true; + } else if (rleCode[1] == 1) { // code 1 - finished image + done = true; + } else { // otherwise - two bytes reposition read + curx += fgetc(fp); + cury += fgetc(fp); + } + } else if (rleCode[0] == 0) { // absolute code (next byte is length) + BYTE byte; + for (int i = 0; i < (rleCode[1] + 1) / 2; ++i) { + byte = fgetc(fp); + index = (byte >> 4) & 0x0F; + if ( bBaseImg ) { + pixel.r = palette[index].rgbRed / 255.0; + pixel.g = palette[index].rgbGreen / 255.0; + pixel.b = palette[index].rgbBlue / 255.0; + setPixel(curx, height - 1 - cury, pixel); + } else { + setAlpha(curx, height - 1 - cury, index/255.0f ); + } + ++curx; + index = byte & 0x0F; + if ( bBaseImg ) { + pixel.r = palette[index].rgbRed / 255.0; + pixel.g = palette[index].rgbGreen / 255.0; + pixel.b = palette[index].rgbBlue / 255.0; + setPixel(curx, height - 1 - cury, pixel); + } else { + setAlpha(curx, height - 1 - cury, index/255.0f ); + } + ++curx; + } + if (((rleCode[1] + 1) / 2) % 2 != 0) // byte align + fgetc(fp); + } else { + for (int i = 0; i < rleCode[0]; ++i) { + if (i % 2 == 0) index = (rleCode[1] >> 4) & 0x0F; + else index = rleCode[1] & 0x0F; + + if ( bBaseImg ) { + pixel.r = palette[index].rgbRed / 255.0; + pixel.g = palette[index].rgbGreen / 255.0; + pixel.b = palette[index].rgbBlue / 255.0; + setPixel(curx, height - 1 - cury, pixel); + } else { + setAlpha(curx, height - 1 - cury, index/255.0f ); + } + ++curx; + } + } + } + } // 8-bit compression cases + break; + case 8: // 8 bit - 256 color, index mode + // read the palette + if (bmih.biCompression == BI_RGB) { // uncompressed data + BYTE* scanlineByte; + scanlineByte = new BYTE[scanlinelength]; + fseek(fp, bmfh.bfOffBits, SEEK_SET); + + for (int y = 0; y < height; ++y) { + fread((void*) scanlineByte, scanlinelength, 1, fp); + for (int x = 0; x < width; ++x) { + index = scanlineByte[x]; + if ( bBaseImg ) { + pixel.r = palette[index].rgbRed / 255.0; + pixel.g = palette[index].rgbGreen / 255.0; + pixel.b = palette[index].rgbBlue / 255.0; + setPixel(x, height - 1 - y, pixel); + } else { + setAlpha(x, height - 1 - y, index/255.0f ); + } + } + } + delete [] scanlineByte; + } else if (bmih.biCompression == BI_RLE8) { // 8-bit RLE compression + unsigned char rleCode[2]; + int curx = 0; + int cury = 0; + done = false; + + fseek(fp, bmfh.bfOffBits, SEEK_SET); + while (!done && fp) { + fread((void*) rleCode, sizeof(char), 2, fp); + if (ferror(fp)) done = true; + if (rleCode[0] == 0 && rleCode[1] < 3) { // escape + if (rleCode[1] == 0) { + curx = 0; + ++cury; + if (cury >= height) done = true; + } else if (rleCode[1] == 1) { + done = true; + } else { + curx += fgetc(fp); + cury += fgetc(fp); + } + } else if (rleCode[0] == 0) { // absolute mode + for (int i = 0; i < rleCode[1]; ++i) { + index = fgetc(fp); + if ( bBaseImg ) { + pixel.r = palette[index].rgbRed / 255.0; + pixel.g = palette[index].rgbGreen / 255.0; + pixel.b = palette[index].rgbBlue / 255.0; + setPixel (curx, height - 1 - cury, pixel); + } else { + setAlpha (curx, height - 1 - cury, index/255.0f); + } + ++curx; + } + if (rleCode[1] % 2 != 0) fgetc(fp); + } else { // encoded mode + pixel.r = palette[rleCode[1]].rgbRed / 255.0; + pixel.g = palette[rleCode[1]].rgbGreen / 255.0; + pixel.b = palette[rleCode[1]].rgbBlue / 255.0; + if ( bBaseImg ) { + for (int i = 0; i < rleCode[0]; ++i) { + setPixel(curx, height - 1 - cury, pixel); + ++curx; + } + } else { + for (int i = 0; i < rleCode[0]; ++i) { + setAlpha(curx, height - 1 - cury, rleCode[1]/255.0f ); + ++curx; + } + } + } + } // while not done + } // 8-bit compression cases + break; + case 16: // 16 bit - 2^16 color, rgb mode + if (bmih.biCompression == BI_BITFIELDS) { // user specified + redmask = DWordReadLE(fp); + greenmask = DWordReadLE(fp); + bluemask = DWordReadLE(fp); + bluewidth = bitcount(bluemask); + greenwidth = bitcount(greenmask); + } else { // bmih.biCompression == BI_RGB // using default values + bluemask = 0x001F; + bluewidth = 5; + greenmask = 0x03E0; + greenwidth = 5; + redmask = 0x7C00; + } + WORD* scanlineWord; + scanlineWord = new WORD[(scanlinelength+1)/2]; + fseek(fp, bmfh.bfOffBits, SEEK_SET); + + for (int y = 0; y < height; ++y) { + fread( (void*) scanlineWord, scanlinelength, 1, fp); + for (int x = 0; x < width; ++x) { + if ( bBaseImg ) { + red = (scanlineWord[x] & redmask) + >> (bluewidth + greenwidth); + green = (scanlineWord[x] & greenmask) >> bluewidth; + blue = (scanlineWord[x] & bluemask); + pixel.r = red / 255.0; + pixel.g = green / 255.0; + pixel.b = blue / 255.0; + setPixel(x, height - 1 - y, pixel); + } else { + setAlpha(x, height - 1 - y, (scanlineWord[x]/65535.0f) ); + } + } + } + delete [] scanlineWord; + break; + case 24: // 24 bit - 2^24 color, rgb mode + RGBTRIPLE *scanline24; + scanline24 = new RGBTRIPLE[(scanlinelength+2)/3]; + fseek(fp, bmfh.bfOffBits, SEEK_SET); + + for (int y = 0; y < height; ++y) { + fread((void*) scanline24, scanlinelength, 1, fp); + for (int x = 0; x < width; ++x) { + if ( bBaseImg ) { + pixel.r = scanline24[x].rgbtRed / 255.0; + pixel.g = scanline24[x].rgbtGreen / 255.0; + pixel.b = scanline24[x].rgbtBlue / 255.0; + setPixel(x, height - 1 - y, pixel); + } else { + setAlpha(x, height - 1 - y, scanline24[x].rgbtRed / 255.0f ); + } + } + } + delete [] scanline24; + break; + case 32: // 32 bit - 2^32 color, rgb mode + if (bmih.biCompression == BI_RGB) { // default encoding + RGBQUAD* scanline32; + scanline32 = new RGBQUAD[(scanlinelength+3)/4]; + fseek(fp, bmfh.bfOffBits, SEEK_SET); + for (int y = 0; y < height; ++y) { + fread((void*) scanline32, scanlinelength, 1, fp); + for (int x = 0; x < width; ++x) { + if ( bBaseImg ) { + pixel.r = scanline32[x].rgbRed / 255.0; + pixel.g = scanline32[x].rgbGreen / 255.0; + pixel.b = scanline32[x].rgbBlue / 255.0; + setPixel(x, height - 1 - y, pixel); + } else { + setAlpha(x, height - 1 - y, scanline32[x].rgbRed / 255.0f ); + } + } + } + delete [] scanline32; + } else if (bmih.biCompression == BI_BITFIELDS) { // user specified + // get masks and shifts + redmask = DWordReadLE(fp); + greenmask = DWordReadLE(fp); + bluemask = DWordReadLE(fp); + bluewidth = bitcount(bluemask); + greenwidth = bitcount(greenmask); + DWORD* scanlineDword; + scanlineDword = new DWORD[(scanlinelength+3)/4]; + fseek(fp, bmfh.bfOffBits, SEEK_SET); + + for (int y = 0; y < height; ++y) { + fread((void*) scanlineDword, scanlinelength, 1, fp); + for (int x = 0; x < width; ++x) { + if ( bBaseImg ) { + red = (scanlineDword[x] & redmask) + >> (bluewidth + greenwidth); + green = (scanlineDword[x] & greenmask) >> bluewidth; + blue = (scanlineDword[x] & bluemask); + + pixel.r = red / 255.0; + pixel.g = green / 255.0; + pixel.b = blue / 255.0; + setPixel(x, height - 1 - y, pixel); + } else { + setAlpha(x, height - 1 - y, (scanlineDword[x] / 65535.0f) ); + } + } + } + delete [] scanlineDword; + } + break; + }; // close select + + // Read alpha image (recursive call) + if ( bBaseImg && fp_a != 0x0 ) { + readBMP ( fp_a, 0x0, false ); + } + return 0; +} + + + +int Image::writeBMP (FILE* fp) +{ + if (!good()) + { + fprintf(stderr, "Image::writeBMP: bad image\n"); + return -1; + } + + BITMAPFILEHEADER bmfh; + BITMAPINFOHEADER bmih; + int lineLength; + + if (channels == 1) + lineLength = width; + else + lineLength = width * 3; + + if ((lineLength % 4) != 0) + lineLength = (lineLength / 4 + 1) * 4; + + /* Write file header */ + + bmfh.bfType = BMP_BF_TYPE; + bmfh.bfSize = BMP_BF_OFF_BITS + lineLength * height; + bmfh.bfReserved1 = 0; + bmfh.bfReserved2 = 0; + bmfh.bfOffBits = BMP_BF_OFF_BITS; + + if (channels == 1) + bmfh.bfOffBits += 256 * 4; + + WordWriteLE(bmfh.bfType, fp); + DWordWriteLE(bmfh.bfSize, fp); + WordWriteLE(bmfh.bfReserved1, fp); + WordWriteLE(bmfh.bfReserved2, fp); + DWordWriteLE(bmfh.bfOffBits, fp); + + /* Write info header */ + + bmih.biSize = BMP_BI_SIZE; + bmih.biWidth = width; + bmih.biHeight = height; + bmih.biPlanes = 1; + bmih.biBitCount = (channels == 1) ? 8 : 24; + bmih.biCompression = BI_RGB; + bmih.biSizeImage = lineLength * (DWORD) bmih.biHeight; + bmih.biXPelsPerMeter = 2925; + bmih.biYPelsPerMeter = 2925; + bmih.biClrUsed = (channels == 1) ? 256 : 0; + bmih.biClrImportant = 0; + + DWordWriteLE(bmih.biSize, fp); + LongWriteLE(bmih.biWidth, fp); + LongWriteLE(bmih.biHeight, fp); + WordWriteLE(bmih.biPlanes, fp); + WordWriteLE(bmih.biBitCount, fp); + DWordWriteLE(bmih.biCompression, fp); + DWordWriteLE(bmih.biSizeImage, fp); + LongWriteLE(bmih.biXPelsPerMeter, fp); + LongWriteLE(bmih.biYPelsPerMeter, fp); + DWordWriteLE(bmih.biClrUsed, fp); + DWordWriteLE(bmih.biClrImportant, fp); + + /* Write pixels */ + + Pixel pixel; + + if (channels == 1) + { + // write 8-bit grayscale palette + + unsigned char palettecolor[4]; + for (int i = 0; i < 256; ++i) + { + memset(palettecolor, (unsigned char) i, 4); + fwrite((void*) palettecolor, sizeof(char), 4, fp); + } + + // write image data + + for (int y = 0; y < height; ++y) + { + int nbytes = 0; + for (int x = 0; x < width; ++x) + { + getPixel(x, height - y - 1, pixel); + fputc((int) (pixel.r * 255), fp); + nbytes++; + } + + while ((nbytes % 4) != 0) + { + fputc(0, fp); nbytes++; + } + } + } + else + { + for (int y = 0; y < height; ++y) + { + int nbytes = 0; + for (int x = 0; x < width; ++x) + { + getPixel(x, height - y - 1, pixel); + fputc((int) (pixel.b * 255), fp); nbytes++; + fputc((int) (pixel.g * 255), fp); nbytes++; + fputc((int) (pixel.r * 255), fp); nbytes++; + } + + while ((nbytes % 4) != 0) + { + fputc(0, fp); + nbytes++; + } + } + } + + if (ferror(fp)) + { + perror("Image::writeBMP"); + return -1; + } + + return 0; +} + + + +/****************************************************************** +* .PNM file manipulation +*/ + + +#define PNM_ASCII 0 +#define PNM_BINARY 1 +#define PNM_PBM 10 +#define PNM_PGM 11 +#define PNM_PPM 12 + + +int Image::readPNM (const char* filename) +{ + FILE* file = fopen(filename, "rb"); + + if (!file) + { + perror("Image::readPNM"); + return -1; + } + + int result = readPNM(file); + fclose(file); + + return result; +} + + +int Image::writePNM (const char* filename) +{ + FILE* file = fopen(filename, "wb"); + + if (!file) + { + perror("Image::writePNM"); + return -1; + } + + int result = writePNM(file); + fclose(file); + + if (result == -1) + unlink(filename); + + return result; +} + + +static inline void getWord (FILE* fp, char* s) +{ + fscanf(fp, "%1023s", s); +} + + +static inline void getLine (FILE* fp, char* s) +{ + fgets(s, 1024, fp); +} + + +static inline void getWordSkipComments (FILE* fp, char* s) +{ + getWord(fp, s); + while (s[0] == '#' && !ferror(fp)) + { + getLine(fp, s); + getWord(fp, s); + } +} + + +int Image::readPNM (FILE* fp) +{ + if (pixels && owns) + delete[] pixels; + pixels = NULL; + + char nextLine[1024]; + + getWord(fp, nextLine); + + int mode, type; + + if (nextLine[0] == 'P') + { + switch (nextLine[1]) + { + case '1': + mode = PNM_ASCII; + type = PNM_PBM; + channels = 1; + break; + + case '2': + mode = PNM_ASCII; + type = PNM_PGM; + channels = 1; + break; + + case '3': + mode = PNM_ASCII; + type = PNM_PPM; + channels = 3; + break; + + case '5': + mode = PNM_BINARY; + type = PNM_PGM; + channels = 1; + break; + + case '6': + mode = PNM_BINARY; + type = PNM_PPM; + channels = 3; + break; + + default: + fprintf( stderr, "Image::readPNM: malformed file\n" ); + return -1; + } + } + else + { + fprintf( stderr, "Image::readPNM: malformed file\n" ); + return -1; + } + + getWordSkipComments(fp, nextLine); + width = atoi(nextLine); + + getWordSkipComments(fp, nextLine); + height = atoi(nextLine); + + if (type != PNM_PBM) + { + getWordSkipComments(fp, nextLine); + maxValue = atoi(nextLine); + } + else + { + maxValue = 1; + } + + if (ferror(fp)) + { + perror("Image::readPNM"); + return -1; + } + + if (width <= 0 || height <= 0 || maxValue <= 0) + { + fprintf( stderr, "Image::readPNM: malformed file\n" ); + return -1; + } + + bits = (int) ceil(log10(maxValue + 1.0) / log10(2.0)); + pixels = new unsigned char[width*height*channels]; + owns = true; + memset(pixels, 0, width*height*channels); + + int red, blue, green, intensity; + Pixel pixel; + BYTE *scanlineByte; + RGBTRIPLE *scanline24; + + if (mode == PNM_ASCII) + { + if (type == PNM_PBM || type == PNM_PGM) + { + for (int y = 0; y < height; ++y) + { + for (int x = 0; x < width; ++x) + { + fscanf(fp, "%d", &intensity); + if (ferror(fp)) + { + perror("Image::readPNM"); + delete[] pixels; + pixels = NULL; + return -1; + } + + pixel.r = intensity / (float) maxValue; + setPixel(x,y,pixel); + } + } + } + else if (type == PNM_PPM) + { + for (int y = 0; y < height; ++y) + { + for (int x = 0; x < width; ++x) + { + fscanf(fp, "%d %d %d", &red, &green, &blue); + if (ferror(fp)) + { + perror("Image::readPNM"); + delete[] pixels; + pixels = NULL; + return -1; + } + + pixel.r = red / (float) maxValue; + pixel.g = green / (float) maxValue; + pixel.b = blue / (float) maxValue; + setPixel(x,y,pixel); + } + } + } + } + else if (mode == PNM_BINARY) + { + // move buffer up to the data's start + fgetc(fp); + + if (type == PNM_PGM) + { + scanlineByte = new BYTE[width]; + + for (int y = 0; y < height; ++y) + { + fread((void*) scanlineByte, sizeof(BYTE), width, fp); + if (ferror(fp)) + { + perror("Image::readPNM"); + delete[] scanlineByte; + delete[] pixels; + pixels = NULL; + return -1; + } + + for (int x = 0; x < width; ++x) + { + pixel.r = scanlineByte[x] / (float) maxValue; + setPixel(x,y,pixel); + } + } + + delete[] scanlineByte; + } + else if (type == PNM_PPM) + { + scanline24 = new RGBTRIPLE[width]; + + for (int y = 0; y < height; ++y) + { + fread((void*) scanline24, sizeof(RGBTRIPLE), width, fp); + if (ferror(fp)) + { + perror("Image::readPNM"); + delete[] scanline24; + delete[] pixels; + pixels = NULL; + return -1; + } + + for (int x = 0; x < width; ++x) + { + pixel.b = scanline24[x].rgbtRed / (float) maxValue; + pixel.g = scanline24[x].rgbtGreen / (float) maxValue; + pixel.r = scanline24[x].rgbtBlue / (float) maxValue; + + setPixel(x,y,pixel); + } + } + + delete[] scanline24; + } + } + + return 0; +} + + +int Image::writePNM (FILE* fp) +{ + if (!good()) + { + fprintf(stderr, "Image::writePNM: bad image\n"); + return -1; + } + + if (channels == 1) + { + if (bits == 1) + { + fprintf(fp, "P1\n"); + fprintf(fp, "%d %d\n", width, height); + + for (int j = 0; j < height; ++j) + { + for (int i = 0; i < width; ++i) + { + fprintf(fp, "%d ", pixels[index(i,j,0)] * maxValue / 255); + } + fprintf(fp, "\n"); + } + } + else + { + fprintf(fp, "P2\n"); + fprintf(fp, "%d %d %d\n", width, height, maxValue); + + for (int j = 0; j < height; ++j) + { + for (int i = 0; i < width; ++i) + { + fprintf(fp, "%d ", pixels[index(i,j,0)] * maxValue / 255); + } + fprintf(fp, "\n"); + } + } + } + else + { + fprintf(fp, "P3\n"); + fprintf(fp, "%d %d %d\n", width, height, maxValue); + + for (int j = 0; j < height; ++j) + { + for (int i = 0; i < width; ++i) + { + fprintf(fp, "%d %d %d ", + pixels[index(i,j,0)] * maxValue / 255, + pixels[index(i,j,1)] * maxValue / 255, + pixels[index(i,j,2)] * maxValue / 255); + } + fprintf(fp, "\n"); + } + } + + return 0; +} diff --git a/Extras/sph/common/image.h b/Extras/sph/common/image.h new file mode 100644 index 0000000..6da5e1f --- /dev/null +++ b/Extras/sph/common/image.h @@ -0,0 +1,188 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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. +*/ + +class Image; + +#ifndef IMAGE_H + #define IMAGE_H + + #include "common_defs.h" + #include + + #ifdef _MSC_VER + #include + #endif + + // Image class code below... + #define IRED 0 + #define IGREEN 1 + #define IBLUE 2 + #define IALPHA 3 + + class Pixel { + public: + Pixel () { r=0;g=0;b=0;a=1;} + Pixel ( double r_, double g_, double b_ ) {r = r_; g = g_; b = b_; a = 1.0; } + Pixel ( double r_, double g_, double b_, double a_ ) {r = r_; g = g_; b = b_; a = a_; } + double r; + double g; + double b; + double a; + }; + + #if defined(_MSC_VER) && defined(USE_JPEG) + #pragma comment(lib, "jpegd.lib" ) + #endif + + /* + * generic multi channel 8-bit max image class. can read and write + * BMP, ascii PNM, and JPG file formats, and supports some useful OpenGL + * calls. + * + * get and set pixel methods use doubles from 0.0 to 1.0. these + * values are mapped to integer values from 0 to the maximum value + * allowed by the number of bits per channel in the image. + */ + class Image { + public: + Image (); + ~Image (); + + // create empty image with specified characteristics + Image (int width_, int height_); + Image (int width_, int height_, int channels_); + Image (int width_, int height_, int channels_, + int bits_); + + // create image and read data from filename + // use good() or bad() to check success + Image (const char* filename); + + // copy constructor and assignment operator + // _deep_ copy! + Image (const Image& image); + Image& operator= (const Image& image); + + // accessors + int getWidth () { return width; } + int getHeight () { return height; } + int getChannels () { return channels; } + int getBits () { return bits; } + unsigned char* getPixels () { return pixels; } + + void create ( int width_, int height_, int channels_ ); + + void refresh (); + + void draw (); + void draw ( float x, float y ); + + + // unsafe! use at your own risk! + void setPixels ( unsigned char *newPixels ); + + // check if the image is valid + bool good (); + bool bad (); + + // set all the pixel data + void clear (); + void clear ( Pixel pixel ); + + // retrieve pixel data. methods with _ at the + // end of their name return 0.0 if the x and y + // are out of range. otherwise, an assertion + // failure occurs + double getPixel (int x, int y, int channel); + double getPixel_ (int x, int y, int channel); + Pixel getPixel (int x, int y); + Pixel getPixel_ (int x, int y); + Pixel& getPixel (int x, int y, Pixel& pixel); + Pixel& getPixel_ (int x, int y, Pixel& pixel); + + // set pixel data. if x and y are out of range, + // an assertion failure occurs + void setPixel (int x, int y, int channel, double value); + void setPixel_ (int x, int y, int channel, double value); + void setPixel (int x, int y, Pixel pixel); + void setPixel_ (int x, int y, Pixel pixel); + void setPixel4 ( int x, int y, Pixel pixel ); + + void setAlpha (int x, int y, double value); + + #ifndef DISABLE_OPENGL + // OpenGL call wrappers + void glReadPixelsWrapper (); + void glDrawPixelsWrapper (); + void glTexImage2DWrapper (); + void glTexImageCubeWrapper ( int i ); + void glTexSubImage2DWrapper ( int x, int y); + #endif + + // top-level file read and write calls, + // determines file type + int read (const char* filename); + int read (const char* filename, const char* alphaname ); + int write (const char* filename); + + int readPaletteBMP ( FILE* fp, RGBQUAD*& palette, int bit_count ); + + // BMP specific read and write calls + int readBMP (const char* filename); + int readBMP (FILE* file, FILE* file_a, bool bBaseImg ); + int writeBMP (const char* filename); + int writeBMP (FILE* file); + + // PNM specific read and write calls + int readPNM (const char* filename); + int readPNM (FILE* file); + int writePNM (const char* filename); + int writePNM (FILE* file); + + #ifdef USE_JPEG + // JPG specific read and write calls + int readJPG (const char* filename); + int readJPG (FILE* file); + int writeJPG (const char* filename); + int writeJPG (FILE* file); + #endif + + private: + + int index(int x, int y, int c); + + int width; + int height; + int channels; // number of channels per pixel + int bits; // number of bits per channel + int maxValue; // max that can be stored in bits + + unsigned char* pixels; // image data + + bool owns; // if image owns pixels + + unsigned int imgID; + + }; + + +#endif // IMAGE_H diff --git a/Extras/sph/common/matrix-inline.h b/Extras/sph/common/matrix-inline.h new file mode 100644 index 0000000..1de585c --- /dev/null +++ b/Extras/sph/common/matrix-inline.h @@ -0,0 +1,1879 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 "matrix.h" + +// MatrixC Code Definition +#define VNAME C +#define VTYPE unsigned char + +// Constructors/Destructors + +inline MatrixC::MatrixC (void) {data = NULL; Resize (0,0);} +inline MatrixC::~MatrixC (void) {if (data!=NULL) delete[] data;} +inline MatrixC::MatrixC (int r, int c) {data = NULL; Resize (c,r);} + +// Member Functions + + +inline VTYPE &MatrixC::operator () (int c, int r) +{ + #ifdef DEBUG_MATRIX + if (data==NULL) Error.Print ( ErrorLev::Matrix, ErrorDef::MatrixIsNull, true ); + if (r<0 || r>=rows) Error.Print ( ErrorLev::Matrix, ErrorDef::RowOutOfBounds, true ); + if (c<0 || c>=cols) Error.Print ( ErrorLev::Matrix, ErrorDef::ColOutOfBounds, true ); + #endif + return *(data + (r*cols+c)); +} +inline MatrixC &MatrixC::operator= (unsigned char op) {VTYPE *n = data, *nlen = data + len; for (;n255) { + *n = (VTYPE) 255; + } else if (*b<=0) { + *n = (VTYPE) 0; + } else { + *n = (VTYPE) *b; + } + } + return *this; +} + +inline MatrixC &MatrixC::operator+= (unsigned char op) {VTYPE *n = data, *nlen = data + len; for (;n= bce) { // If last col in B.. + bs = op.data; // Go back to first column in B + as += cols; // Goto next row in A + } + n++; // Goto next element in C + } + delete[] data; // Destroy old A matrix + data = newdata; rows = newr; cols = newc; len = newlen; // Replace with new A matrix + } + return *this; +} + +inline MatrixC &MatrixC::Resize (int x, int y) +{ + if (data!=NULL) { + if (rows!=y || cols!=x) { + delete[] data; + len = (rows = y) * (cols = x); + data = new VTYPE[len]; + } + } else { + len = (rows = y) * (cols = x); data = new VTYPE[len]; + } + #ifdef DEBUG_MATRIX + if (data==NULL) Debug.Print (DEBUG_MATRIX, "MatrixC::Resize: Out of memory for construction.\n"); + #endif + #ifdef MATRIX_INITIALIZE + memset (data, 0, sizeof(VTYPE)*len); + #endif + return *this; +} +inline MatrixC &MatrixC::ResizeSafe (int x, int y) +{ + VTYPE *newdata; + int newlen; + VTYPE *n, *ne; + VTYPE *b, *be; + int bskip; + + + if (data!=NULL) { + newlen = x*y; + newdata = new VTYPE[newlen]; + #ifdef DEBUG_MATRIX + if (newdata==NULL) + Debug.Print (DEBUG_MATRIX, "MatrixC::SizeSafe: Out of memory for construction.\n"); + #endif + if (y>=rows && x>=cols) { // New size is larger (in both r and c) + memset (newdata, 0, newlen*sizeof(VTYPE)); // Clear new matrix + ne = data + len; // Calculate end of current matrix + b = newdata; // Start of new matrix + be = newdata + cols; // Last filled column+1 in new matrix + bskip = x-cols; + for (n = data; n0) { + n = data; // Copy columns to left of c + ne = data + len; + nskip = (cols-c); + b = newdata; + be = newdata + c; + bskip = (cols-c)+1; + for (; n Ainv + // b -> solution x + // + + #ifdef DEBUG_MATRIX + Debug.Print (DEBUG_MATRIX, "MatrixC::GaussJordan: Not implemented for char matrix\n"); + #endif + return *this; +} +inline int MatrixC::GetX() {return cols;} +inline int MatrixC::GetY() {return rows;} +inline int MatrixC::GetRows(void) {return rows;} +inline int MatrixC::GetCols(void) {return cols;} +inline int MatrixC::GetLength(void) {return len;} +inline VTYPE *MatrixC::GetData(void) {return data;} + +inline double MatrixC::GetF (int r, int c) {return (double) (*(data + r*cols + c));} + +#undef VTYPE +#undef VNAME + +// MatrixI Code Definition +#define VNAME I +#define VTYPE int + +// Constructors/Destructors + +inline MatrixI::MatrixI (void) {data = NULL; Resize (0,0);} +inline MatrixI::~MatrixI (void) {if (data!=NULL) delete[] data;} +inline MatrixI::MatrixI (int r, int c) {data = NULL; Resize (c,r);} + +// Member Functions + +inline VTYPE &MatrixI::operator () (int c, int r) +{ + #ifdef DEBUG_MATRIX + if (data==NULL) Debug.Print (DEBUG_MATRIX, "MatrixI::op(): Matrix data is null\n"); + if (r<0 || r>=rows) Debug.Print (DEBUG_MATRIX, "MatrixI:op(): Row is out of bounds\n"); + if (c<0 || c>=cols) Debug.Print (DEBUG_MATRIX, "MatrixI:op(): Col is out of bounds\n"); + #endif + return *(data + (r*cols+c)); +} +inline MatrixI &MatrixI::operator= (unsigned char op) {VTYPE *n = data, *nlen = data + len; for (;n= bce) { // If last col in B.. + bs = op.data; // Go back to first column in B + as += cols; // Goto next row in A + } + n++; // Goto next element in C + } + delete[] data; // Destroy old A matrix + data = newdata; rows = newr; cols = newc; len = newlen; // Replace with new A matrix + } + return *this; +} + +inline MatrixI &MatrixI::Resize (int x, int y) +{ + if (data!=NULL) { + if (rows!=y || cols!=x) {delete[] data; len = (rows = y) * (cols = x); data = new VTYPE[len];} + } else { + len = (rows = y) * (cols = x); data = new VTYPE[len]; + } + #ifdef DEBUG_MATRIX + if (data==NULL) Debug.Print (DEBUG_MATRIX, "MatrixC::Size: Out of memory for construction.\n"); + #endif + #ifdef MATRIX_INITIALIZE + memset (data, 0, sizeof(VTYPE)*len); + #endif + return *this; +} +inline MatrixI &MatrixI::ResizeSafe (int x, int y) +{ + VTYPE *newdata; + int newlen; + VTYPE *n, *ne; + VTYPE *b, *be; + int bskip; + + + if (data!=NULL) { + newlen = x*y; + newdata = new VTYPE[newlen]; + #ifdef DEBUG_MATRIX + if (newdata==NULL) + Debug.Print (DEBUG_MATRIX, "MatrixC::SizeSafe: Out of memory for construction.\n"); + #endif + if (y>=rows && x>=cols) { // New size is larger (in both r and c) + memset (newdata, 0, newlen*sizeof(VTYPE)); // Clear new matrix + ne = data + len; // Calculate end of current matrix + b = newdata; // Start of new matrix + be = newdata + cols; // Last filled column+1 in new matrix + bskip = x-cols; + for (n = data; n0) { + n = data; // Copy columns to left of c + ne = data + len; + nskip = (cols-c); + b = newdata; + be = newdata + c; + bskip = (cols-c)+1; + for (; n Ainv + // b -> solution x + // + + #ifdef DEBUG_MATRIX + Debug.Print (DEBUG_MATRIX, "MatrixI::GaussJordan: Not implemented for int matrix\n"); + #endif + return *this; +} +inline int MatrixI::GetX() {return cols;} +inline int MatrixI::GetY() {return rows;} +inline int MatrixI::GetRows(void) {return rows;} +inline int MatrixI::GetCols(void) {return cols;} +inline int MatrixI::GetLength(void) {return len;} +inline VTYPE *MatrixI::GetData(void) {return data;} + +inline double MatrixI::GetF (int r, int c) {return (double) (*(data + r*cols + c));} + +#undef VTYPE +#undef VNAME + + +// MatrixF Code Definition +#define VNAME F +#define VTYPE double + +// Constructors/Destructors + +inline MatrixF::MatrixF (void) {data = NULL; Resize (0,0);} + +inline MatrixF::~MatrixF (void) { + if (data!=NULL) + delete [] data; +} +inline MatrixF::MatrixF (const int r, const int c) {data = NULL; Resize (r,c);} + +// Member Functions + +inline VTYPE MatrixF::GetVal ( int c, int r ) +{ + #ifdef DEBUG_MATRIX + if (data==NULL) Error.Print ( ErrorLev::Matrix, ErrorDef::MatrixIsNull, true ); + if (r<0 || r>=rows) Error.Print ( ErrorLev::Matrix, ErrorDef::RowOutOfBounds, true ); + if (c<0 || c>=cols) Error.Print ( ErrorLev::Matrix, ErrorDef::ColOutOfBounds, true ); + #endif + return *(data + (r*cols+c)); +} + +inline VTYPE &MatrixF::operator () (const int c, const int r) +{ + #ifdef DEBUG_MATRIX + if (data==NULL) + Error.Print ( ErrorLev::Matrix, ErrorDef::MatrixIsNull, true ); + if (r<0 || r>=rows) + Error.Print ( ErrorLev::Matrix, ErrorDef::RowOutOfBounds, true ); + if (c<0 || c>=cols) + Error.Print ( ErrorLev::Matrix, ErrorDef::ColOutOfBounds, true ); + #endif + return *(data + (r*cols+c)); +} +inline MatrixF &MatrixF::operator= (const unsigned char op) {VTYPE *n = data, *nlen = data + len; for (;n= bce) { // If last col in B.. + bs = op.data; // Go back to first column in B + as += cols; // Goto next row in A + } + n++; // Goto next element in C + } + delete[] data; // Destroy old A matrix + data = newdata; rows = newr; cols = newc; len = newlen; // Replace with new A matrix + } + return *this; +} + +inline MatrixF &MatrixF::Multiply4x4 (const MatrixF &op) { + #ifdef DEBUG_MATRIX + if (data==NULL) Debug.Print (DEBUG_MATRIX, "MatrixF::Multiply4x4 m*=op: Matrix data is null\n"); + if (op.data==NULL) Debug.Print (DEBUG_MATRIX, "MatrixF::Multiply4x4 m*=op: Operand matrix (op) data is null\n"); + if (rows!=4 || cols!=4) Debug.Print (DEBUG_MATRIX, "MatrixF::Multiply4x4 m*=op: Matrix m is not 4x4"); + if (op.rows!=4 || op.cols!=4) Debug.Print (DEBUG_MATRIX, "MatrixF::Multiply4x4 m*=op: Matrix op is not 4x4"); + #endif + register double c1, c2, c3, c4; // Temporary storage + VTYPE *n, *a, *b1, *b2, *b3, *b4; + a = data; n = data; + b1 = op.data; b2 = op.data + 4; b3 = op.data + 8; b4 = op.data + 12; + + c1 = *a++; c2 = *a++; c3 = *a++; c4 = *a++; // Calculate First Row + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1) + c2*(*b2) + c3*(*b3) + c4*(*b4); + b1 -= 3 ; b2 -= 3; b3 -= 3; b4 -= 3; + + c1 = *a++; c2 = *a++; c3 = *a++; c4 = *a++; // Calculate Second Row + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1) + c2*(*b2) + c3*(*b3) + c4*(*b4); + b1 -= 3 ; b2 -= 3; b3 -= 3; b4 -= 3; + + c1 = *a++; c2 = *a++; c3 = *a++; c4 = *a++; // Calculate Third Row + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1) + c2*(*b2) + c3*(*b3) + c4*(*b4); + b1 -= 3 ; b2 -= 3; b3 -= 3; b4 -= 3; + + c1 = *a++; c2 = *a++; c3 = *a++; c4 = *a; // Calculate Four Row + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n = c1*(*b1) + c2*(*b2) + c3*(*b3) + c4*(*b4); + + return *this; +} + + +inline MatrixF &MatrixF::Resize (const int x, const int y) +{ + if (data!=NULL) { + if (rows==y && cols==x) return *this; + delete[] data; + } + rows = y; cols = x; + if (y>0 && x>0) { + len = rows * cols; + if (len!=0) { + data = new VTYPE[len]; + #ifdef DEBUG_MATRIX + if (data==NULL) Debug.Print (DEBUG_MATRIX, "MatrixF::Size: Out of memory for construction.\n"); + #endif + } + } + + #ifdef MATRIX_INITIALIZE + if (data!=NULL) memset (data, 0, sizeof(VTYPE)*len); + #endif + return *this; +} +inline MatrixF &MatrixF::ResizeSafe (const int x, const int y) +{ + VTYPE *newdata; + int newlen; + VTYPE *n, *ne; + VTYPE *b, *be; + int bskip; + + if (data!=NULL) { + newlen = x*y; + newdata = new VTYPE[newlen]; + #ifdef DEBUG_MATRIX + if (newdata==NULL) + Debug.Print (DEBUG_MATRIX, "MatrixF::SizeSafe: Out of memory for construction.\n"); + #endif + if (y>=rows && x>=cols) { // New size is larger (in both r and c) + memset (newdata, 0, newlen*sizeof(VTYPE)); // Clear new matrix + ne = data + len; // Calculate end of current matrix + b = newdata; // Start of new matrix + be = newdata + cols; // Last filled column+1 in new matrix + bskip = x-cols; + for (n = data; n0) { + n = data; // Copy columns to left of c + ne = data + len; + nskip = (cols-c); + b = newdata; + be = newdata + c; + bskip = (cols-c)+1; + for (; n>counter-clockwise<< when looking down the X+ axis toward the origin +inline MatrixF &MatrixF::RotateX (const double ang) +{ + Resize (4,4); + VTYPE *n = data; + double c,s; + c = cos(ang * 3.141592/180); + s = sin(ang * 3.141592/180); + *n = 1; n += 5; + *n++ = (VTYPE) c; *n = (VTYPE) s; n+=3; + *n++ = (VTYPE) -s; *n = (VTYPE) c; n+=5; + *n = 1; + return *this; +} + +// rotates points >>counter-clockwise<< when looking down the Y+ axis toward the origin +inline MatrixF &MatrixF::RotateY (const double ang) +{ + Resize (4,4); + VTYPE *n = data; + double c,s; + c = cos(ang * 3.141592/180); + s = sin(ang * 3.141592/180); + *n = (VTYPE) c; n+=2; + *n = (VTYPE) -s; n+=3; + *n = 1; n+=3; + *n = (VTYPE) s; n+=2; + *n = (VTYPE) c; n+=5; + *n = 1; + return *this; +} + +// rotates points >>counter-clockwise<< when looking down the Z+ axis toward the origin +inline MatrixF &MatrixF::RotateZ (const double ang) +{ + Resize (4,4); + VTYPE *n = data; + double c,s; + c = cos(ang * 3.141592/180); + s = sin(ang * 3.141592/180); + *n++ = (VTYPE) c; *n = (VTYPE) s; n+=3; + *n++ = (VTYPE) -s; *n = (VTYPE) c; n+=5; + *n = 1; n+=5; *n = 1; + return *this; +} +inline MatrixF &MatrixF::Ortho (double sx, double sy, double vn, double vf) +{ + // simplified version of OpenGL's glOrtho function + VTYPE *n = data; + *n++ = (VTYPE) (1.0/sx); *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; + *n++ = (VTYPE) 0.0; *n++ = (VTYPE) (1.0/sy); *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; + *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; *n++ = (VTYPE) (-2.0/(vf-vn)); *n++ = (VTYPE) (-(vf+vn)/(vf-vn)); + *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0; *n++ = (VTYPE) 1.0; +} + +inline MatrixF &MatrixF::Translate (double tx, double ty, double tz) +{ + Resize (4,4); + VTYPE *n = data; + *n++ = (VTYPE) 1.0; *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; + *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 1.0; *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; + *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 1.0; *n++ = (VTYPE) 0.0; + *n++ = (VTYPE) tx; *n++ = (VTYPE) ty; *n++ = (VTYPE) tz; *n++ = (VTYPE) 1.0; + return *this; +} + +inline MatrixF &MatrixF::Basis (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3) +{ + Resize (4,4); + VTYPE *n = data; + *n++ = (VTYPE) c1.X(); *n++ = (VTYPE) c2.X(); *n++ = (VTYPE) c3.X(); *n++ = (VTYPE) 0; + *n++ = (VTYPE) c1.Y(); *n++ = (VTYPE) c2.Y(); *n++ = (VTYPE) c3.Y(); *n++ = (VTYPE) 0; + *n++ = (VTYPE) c1.Z(); *n++ = (VTYPE) c2.Z(); *n++ = (VTYPE) c3.Z(); *n++ = (VTYPE) 0; + *n++ = (VTYPE) 0; *n++ = (VTYPE) 0; *n++ = (VTYPE) 0; *n++ = (VTYPE) 0; + return *this; +} + +#define SWAP(a, b) {temp=(a); (a)=(b); (b)=temp;} + +inline MatrixF &MatrixF::GaussJordan (MatrixF &b) +{ + // Gauss-Jordan solves the matrix equation Ax = b + // Given the problem: + // A*x = b (where A is 'this' matrix and b is provided) + // The solution is: + // Ainv*b = x + // This function returns Ainv in A and x in b... that is: + // A (this) -> Ainv + // b -> solution x + // + + MatrixI index_col, index_row; + MatrixI piv_flag; + int r, c, c2, rs, cs; + double piv_val; + int piv_row, piv_col; + double pivinv, dummy, temp; + + #ifdef DEBUG_MATRIX + if (rows!=cols) Debug.Print (DEBUG_MATRIX, "MatrixF::GaussJordan: Number of rows and cols of A must be equal.\n"); + if (rows!=b.rows) Debug.Print (DEBUG_MATRIX, "MatrixF::GaussJordan: Number of rows of A and rows of b must be equal.\n"); + if (b.cols!=1) Debug.Print ( DEBUG_MATRIX, "MatrixF::GaussJordan: Number of cols of b must be 1.\n"); + #endif + + index_col.Resize (cols, 1); + index_row.Resize (cols, 1); + piv_flag.Resize (cols, 1); + piv_flag = 0; + for (c = 0; c < cols; c++) { + piv_val = 0.0; + for (rs = 0; rs < rows; rs++) { + if (piv_flag(rs, 0) != 1 ) + for (cs = 0; cs < cols; cs++) { + if (piv_flag(cs, 0) == 0) { + if (fabs((*this) (cs, rs)) >= piv_val) { + piv_val = fabs((*this) (cs, rs)); + piv_row = rs; + piv_col = cs; + } + } else if (piv_flag(cs, 0)>1) { + #ifdef DEBUG_MATRIX + Debug.Print (DEBUG_MATRIX, "MatrixF::GaussJordan: Singular matrix (dbl pivs).\n"); + //Print (); + #endif + } + } + } + piv_flag(piv_col, 0)++; + if (piv_row != piv_col) { + for (c2 = 0; c2 < cols; c2++) SWAP ((*this) (c2, piv_row), (*this) (c2, piv_col)); + for (c2 = 0; c2 < b.cols; c2++) SWAP (b(c2, piv_row), b(c2, piv_col)); + } + index_row (c, 0) = piv_row; + index_col (c, 0) = piv_col; + if ((*this) (piv_col, piv_col) == 0.0) { + #ifdef DEBUG_MATRIX + Debug.Print (DEBUG_MATRIX, "MatrixF::GaussJordan: Singular matrix (0 piv).\n"); + //Print (); + #endif + } + pivinv = 1.0 / ((*this) (piv_col, piv_col)); + (*this) (piv_col, piv_col) = 1.0; + for (c2 = 0; c2 < cols; c2++) (*this) (c2, piv_col) *= pivinv; + for (c2 = 0; c2 < b.cols; c2++) b(c2, piv_col) *= pivinv; + for (r = 0; r < rows; r++) { + if (r != piv_col) { + dummy = (*this) (piv_col, r); + (*this) (piv_col, r) = 0.0; + for (c2 = 0; c2 < cols; c2++) (*this) (c2, r) -= (*this) (c2, piv_col)*dummy; + for (c2 = 0; c2 < b.cols; c2++) b(c2, r) -= b(c2, piv_col)*dummy; + } + } + } + for (c = cols-1; c >= 0; c--) { + if (index_row(c, 0) != index_col(c, 0)) + for (r = 0; r < rows; r++) + SWAP ((*this) (index_row(c,0), r), (*this) (index_col(c,0), r) ); + } + return *this; +} +inline MatrixF &MatrixF::Submatrix ( MatrixF& b, int mx, int my) +{ + VTYPE* pEnd = data + rows*cols; // end of matrix + VTYPE* pVal = data; + VTYPE* pNewVal = b.data; + VTYPE* pNewEnd = pNewVal + mx; + int pNewSkip = cols - mx; + + for (pVal = data; pVal < pEnd;) { + for (; pNewVal < pNewEnd;) *pVal++ = *pNewVal++; + pNewVal += pNewSkip; + pNewEnd += mx; + } + return *this; +} + +// N-Vector Dot Product +// Elements may be in rows or columns, but: +// - If in rows, number of columns must be one and number of rows must match. +// - If in cols, number of rows must be one and number of cols must match. +inline double MatrixF::Dot ( MatrixF& b ) +{ + double d = 0.0; + VTYPE* pA = data; + VTYPE* pB = b.data; + + if ( rows==1 && b.rows==1 && cols == b.cols ) { + VTYPE* pAEnd = data + cols; + d = 0.0; + for (; pA < pAEnd;) + d += (*pA++) * (*pB++); + } else if ( cols==1 && b.cols==1 && rows == b.rows) { + VTYPE* pAEnd = data + rows; + d = 0.0; + for (; pA < pAEnd;) + d += (*pA++) * (*pB++); + } + return d; +} + +#define I(x, y) ( (y*xres) + x ) +#define Ix(r) ( r % xres ) // X coordinate from row +#define Iy(r) ( r / xres ) // Y coordinate from row + +inline MatrixF &MatrixF::MatrixVector5 (MatrixF& x, int mrows, MatrixF& b) +{ + double v; + + // A( 2, r ) * B ( r ) + A(1,r)*B(r-1) + A(3,r)*B(r+1) + A(0, r)*B( R-( r ) ) + A(4, r)*B( R+( r ) ) + for (int r = 0; r < mrows; r++) { + v = GetVal(2, r) * x(0,r); + if ( r > 0 ) v += GetVal(1,r) * x(0,r-1); + if ( r < mrows-1) v += GetVal(3,r) * x(0,r+1); + if ( (int) GetVal(5, r) >= 0) v += GetVal(0,r) * x(0, (int) GetVal(5,r)); + if ( (int) GetVal(6, r) >= 0) v += GetVal(4,r) * x(0, (int) GetVal(6,r)); + b(0,r) = v; + } + return *this; +} + +inline MatrixF &MatrixF::ConjugateGradient (MatrixF &b) +{ + return *this; +} + +// Sparse Conjugate Gradient 2D (special case) +// This compute conjugate gradients on a +// sparse "5-7" x N positive definite matrix. +// Only 'mrows' subset of the row-size of A and b will be used. +inline MatrixF &MatrixF::ConjugateGradient5 (MatrixF &b, int mrows ) +{ + double a, g, rdot; + int i, imax; + MatrixF x, xnew; // solution vector + MatrixF r, rnew; // residual + MatrixF p, ptemp; // search direction + MatrixF v; + + x.Resize ( 1, mrows ); + xnew.Resize ( 1, mrows ); + r.Resize ( 1, mrows ); + rnew.Resize ( 1, mrows ); + p.Resize ( 1, mrows ); + ptemp.Resize ( 1, mrows ); + v.Resize ( 1, mrows ); + + r.Submatrix ( b, 1, mrows); + MatrixVector5 ( x, mrows, v ); // (Ax -> v) + r -= v; // r = b - Ax + p = r; + + imax = 20; + for (i=0; i < imax; i++) { + MatrixVector5 ( p, mrows, v ); // v = Ap + rdot = r.Dot ( r ); + a = rdot / p.Dot ( v ); // a = (r . r) / (p . v) + xnew = p; + xnew *= a; + xnew += x; // x = x + p*a + v *= a; + rnew = r; // rnew = r - v*a + rnew -= v; + g = rnew.Dot ( rnew ) / rdot; // g = (rnew . rnew) / (r . r) + p *= g; + p += rnew; // p = rnew + p*g + r = rnew; + x = xnew; + } + for (int rx=0; rx < mrows; rx++) + b(0, rx) = x(0, rx); + return *this; +} + +inline int MatrixF::GetX() {return cols;} +inline int MatrixF::GetY() {return rows;} +inline int MatrixF::GetRows(void) {return rows;} +inline int MatrixF::GetCols(void) {return cols;} +inline int MatrixF::GetLength(void) {return len;} +inline VTYPE *MatrixF::GetData(void) {return data;} + +inline double MatrixF::GetF (const int r, const int c) {return (double) (*(data + r*cols + c));} + +inline void MatrixF::GetRowVec (int r, Vector3DF &v) +{ + VTYPE *n = data + r*cols; + v.x = *n++; v.y = *n++; v.z= *n++; +} + +inline void MatrixF::Print ( char* fname ) +{ + char buf[2000]; + + FILE* fp = fopen ( fname, "w+" ); + + for (int r=0; r < rows; r++) { + buf[0] = '\0'; + for (int c =0; c < cols; c++) { + sprintf ( buf, "%s %04.3f", buf, GetVal(c, r) ); + } + fprintf ( fp, "%s\n", buf); + } + fprintf ( fp, "---------------------------------------\n", buf); + fflush ( fp ); + fclose ( fp ); +} + +#undef VTYPE +#undef VNAME \ No newline at end of file diff --git a/Extras/sph/common/matrix.cci b/Extras/sph/common/matrix.cci new file mode 100644 index 0000000..37b7e0b --- /dev/null +++ b/Extras/sph/common/matrix.cci @@ -0,0 +1,2046 @@ + +// MatrixC Code Definition +#define VNAME C +#define VTYPE unsigned char + +// Constructors/Destructors + +inline MatrixC::MatrixC (void) {data = NULL; Resize (0,0);} +inline MatrixC::~MatrixC (void) {if (data!=NULL) delete[] data;} +inline MatrixC::MatrixC (int r, int c) {data = NULL; Resize (c,r);} + +// Member Functions + + +inline VTYPE &MatrixC::operator () (int c, int r) +{ + #ifdef DEBUG_MATRIX + if (data==NULL) Error.Print ( ErrorLev::Matrix, ErrorDef::MatrixIsNull, true ); + if (r<0 || r>=rows) Error.Print ( ErrorLev::Matrix, ErrorDef::RowOutOfBounds, true ); + if (c<0 || c>=cols) Error.Print ( ErrorLev::Matrix, ErrorDef::ColOutOfBounds, true ); + #endif + return *(data + (r*cols+c)); +} +inline MatrixC &MatrixC::operator= (unsigned char op) {VTYPE *n = data, *nlen = data + len; for (;n255) { + *n = (VTYPE) 255; + } else if (*b<=0) { + *n = (VTYPE) 0; + } else { + *n = (VTYPE) *b; + } + } + return *this; +} + +inline MatrixC &MatrixC::operator+= (unsigned char op) {VTYPE *n = data, *nlen = data + len; for (;n= bce) { // If last col in B.. + bs = op.data; // Go back to first column in B + as += cols; // Goto next row in A + } + n++; // Goto next element in C + } + delete[] data; // Destroy old A matrix + data = newdata; rows = newr; cols = newc; len = newlen; // Replace with new A matrix + } + return *this; +} + +inline MatrixC &MatrixC::Resize (int x, int y) +{ + if (data!=NULL) { + if (rows!=y || cols!=x) { + delete[] data; + len = (rows = y) * (cols = x); + data = new VTYPE[len]; + } + } else { + len = (rows = y) * (cols = x); data = new VTYPE[len]; + } + #ifdef DEBUG_MATRIX + if (data==NULL) Debug.Print (DEBUG_MATRIX, "MatrixC::Resize: Out of memory for construction.\n"); + #endif + #ifdef MATRIX_INITIALIZE + memset (data, 0, sizeof(VTYPE)*len); + #endif + return *this; +} +inline MatrixC &MatrixC::ResizeSafe (int x, int y) +{ + VTYPE *newdata; + int newlen; + VTYPE *n, *ne; + VTYPE *b, *be; + int bskip; + + + if (data!=NULL) { + newlen = x*y; + newdata = new VTYPE[newlen]; + #ifdef DEBUG_MATRIX + if (newdata==NULL) + Debug.Print (DEBUG_MATRIX, "MatrixC::SizeSafe: Out of memory for construction.\n"); + #endif + if (y>=rows && x>=cols) { // New size is larger (in both r and c) + memset (newdata, 0, newlen*sizeof(VTYPE)); // Clear new matrix + ne = data + len; // Calculate end of current matrix + b = newdata; // Start of new matrix + be = newdata + cols; // Last filled column+1 in new matrix + bskip = x-cols; + for (n = data; n0) { + n = data; // Copy columns to left of c + ne = data + len; + nskip = (cols-c); + b = newdata; + be = newdata + c; + bskip = (cols-c)+1; + for (; n Ainv + // b -> solution x + // + + #ifdef DEBUG_MATRIX + Debug.Print (DEBUG_MATRIX, "MatrixC::GaussJordan: Not implemented for char matrix\n"); + #endif + return *this; +} +inline int MatrixC::GetX() {return cols;} +inline int MatrixC::GetY() {return rows;} +inline int MatrixC::GetRows(void) {return rows;} +inline int MatrixC::GetCols(void) {return cols;} +inline int MatrixC::GetLength(void) {return len;} +inline VTYPE *MatrixC::GetData(void) {return data;} + +inline double MatrixC::GetF (int r, int c) {return (double) (*(data + r*cols + c));} + +#undef VTYPE +#undef VNAME + +// MatrixI Code Definition +#define VNAME I +#define VTYPE int + +// Constructors/Destructors + +inline MatrixI::MatrixI (void) {data = NULL; Resize (0,0);} +inline MatrixI::~MatrixI (void) {if (data!=NULL) delete[] data;} +inline MatrixI::MatrixI (int r, int c) {data = NULL; Resize (c,r);} + +// Member Functions + +inline VTYPE &MatrixI::operator () (int c, int r) +{ + #ifdef DEBUG_MATRIX + if (data==NULL) Debug.Print (DEBUG_MATRIX, "MatrixI::op(): Matrix data is null\n"); + if (r<0 || r>=rows) Debug.Print (DEBUG_MATRIX, "MatrixI:op(): Row is out of bounds\n"); + if (c<0 || c>=cols) Debug.Print (DEBUG_MATRIX, "MatrixI:op(): Col is out of bounds\n"); + #endif + return *(data + (r*cols+c)); +} +inline MatrixI &MatrixI::operator= (unsigned char op) {VTYPE *n = data, *nlen = data + len; for (;n= bce) { // If last col in B.. + bs = op.data; // Go back to first column in B + as += cols; // Goto next row in A + } + n++; // Goto next element in C + } + delete[] data; // Destroy old A matrix + data = newdata; rows = newr; cols = newc; len = newlen; // Replace with new A matrix + } + return *this; +} + +inline MatrixI &MatrixI::Resize (int x, int y) +{ + if (data!=NULL) { + if (rows!=y || cols!=x) {delete[] data; len = (rows = y) * (cols = x); data = new VTYPE[len];} + } else { + len = (rows = y) * (cols = x); data = new VTYPE[len]; + } + #ifdef DEBUG_MATRIX + if (data==NULL) Debug.Print (DEBUG_MATRIX, "MatrixC::Size: Out of memory for construction.\n"); + #endif + #ifdef MATRIX_INITIALIZE + memset (data, 0, sizeof(VTYPE)*len); + #endif + return *this; +} +inline MatrixI &MatrixI::ResizeSafe (int x, int y) +{ + VTYPE *newdata; + int newlen; + VTYPE *n, *ne; + VTYPE *b, *be; + int bskip; + + + if (data!=NULL) { + newlen = x*y; + newdata = new VTYPE[newlen]; + #ifdef DEBUG_MATRIX + if (newdata==NULL) + Debug.Print (DEBUG_MATRIX, "MatrixC::SizeSafe: Out of memory for construction.\n"); + #endif + if (y>=rows && x>=cols) { // New size is larger (in both r and c) + memset (newdata, 0, newlen*sizeof(VTYPE)); // Clear new matrix + ne = data + len; // Calculate end of current matrix + b = newdata; // Start of new matrix + be = newdata + cols; // Last filled column+1 in new matrix + bskip = x-cols; + for (n = data; n0) { + n = data; // Copy columns to left of c + ne = data + len; + nskip = (cols-c); + b = newdata; + be = newdata + c; + bskip = (cols-c)+1; + for (; n Ainv + // b -> solution x + // + + #ifdef DEBUG_MATRIX + Debug.Print (DEBUG_MATRIX, "MatrixI::GaussJordan: Not implemented for int matrix\n"); + #endif + return *this; +} +inline int MatrixI::GetX() {return cols;} +inline int MatrixI::GetY() {return rows;} +inline int MatrixI::GetRows(void) {return rows;} +inline int MatrixI::GetCols(void) {return cols;} +inline int MatrixI::GetLength(void) {return len;} +inline VTYPE *MatrixI::GetData(void) {return data;} + +inline double MatrixI::GetF (int r, int c) {return (double) (*(data + r*cols + c));} + +#undef VTYPE +#undef VNAME + + +// MatrixF Code Definition +#define VNAME F +#define VTYPE double + +// Constructors/Destructors + +inline MatrixF::MatrixF (void) {data = NULL; Resize (0,0);} + +inline MatrixF::~MatrixF (void) { + if (data!=NULL) + delete [] data; +} +inline MatrixF::MatrixF (const int r, const int c) {data = NULL; Resize (r,c);} + +// Member Functions + +inline VTYPE MatrixF::GetVal ( int c, int r ) +{ + #ifdef DEBUG_MATRIX + if (data==NULL) Error.Print ( ErrorLev::Matrix, ErrorDef::MatrixIsNull, true ); + if (r<0 || r>=rows) Error.Print ( ErrorLev::Matrix, ErrorDef::RowOutOfBounds, true ); + if (c<0 || c>=cols) Error.Print ( ErrorLev::Matrix, ErrorDef::ColOutOfBounds, true ); + #endif + return *(data + (r*cols+c)); +} + +inline VTYPE &MatrixF::operator () (const int c, const int r) +{ + #ifdef DEBUG_MATRIX + if (data==NULL) + Error.Print ( ErrorLev::Matrix, ErrorDef::MatrixIsNull, true ); + if (r<0 || r>=rows) + Error.Print ( ErrorLev::Matrix, ErrorDef::RowOutOfBounds, true ); + if (c<0 || c>=cols) + Error.Print ( ErrorLev::Matrix, ErrorDef::ColOutOfBounds, true ); + #endif + return *(data + (r*cols+c)); +} +inline MatrixF &MatrixF::operator= (const unsigned char op) {VTYPE *n = data, *nlen = data + len; for (;n= bce) { // If last col in B.. + bs = op.data; // Go back to first column in B + as += cols; // Goto next row in A + } + n++; // Goto next element in C + } + delete[] data; // Destroy old A matrix + data = newdata; rows = newr; cols = newc; len = newlen; // Replace with new A matrix + } + return *this; +} + +inline MatrixF &MatrixF::Multiply4x4 (const MatrixF &op) { + #ifdef DEBUG_MATRIX + if (data==NULL) Debug.Print (DEBUG_MATRIX, "MatrixF::Multiply4x4 m*=op: Matrix data is null\n"); + if (op.data==NULL) Debug.Print (DEBUG_MATRIX, "MatrixF::Multiply4x4 m*=op: Operand matrix (op) data is null\n"); + if (rows!=4 || cols!=4) Debug.Print (DEBUG_MATRIX, "MatrixF::Multiply4x4 m*=op: Matrix m is not 4x4"); + if (op.rows!=4 || op.cols!=4) Debug.Print (DEBUG_MATRIX, "MatrixF::Multiply4x4 m*=op: Matrix op is not 4x4"); + #endif + register double c1, c2, c3, c4; // Temporary storage + VTYPE *n, *a, *b1, *b2, *b3, *b4; + a = data; n = data; + b1 = op.data; b2 = op.data + 4; b3 = op.data + 8; b4 = op.data + 12; + + c1 = *a++; c2 = *a++; c3 = *a++; c4 = *a++; // Calculate First Row + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1) + c2*(*b2) + c3*(*b3) + c4*(*b4); + b1 -= 3 ; b2 -= 3; b3 -= 3; b4 -= 3; + + c1 = *a++; c2 = *a++; c3 = *a++; c4 = *a++; // Calculate Second Row + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1) + c2*(*b2) + c3*(*b3) + c4*(*b4); + b1 -= 3 ; b2 -= 3; b3 -= 3; b4 -= 3; + + c1 = *a++; c2 = *a++; c3 = *a++; c4 = *a++; // Calculate Third Row + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1) + c2*(*b2) + c3*(*b3) + c4*(*b4); + b1 -= 3 ; b2 -= 3; b3 -= 3; b4 -= 3; + + c1 = *a++; c2 = *a++; c3 = *a++; c4 = *a; // Calculate Four Row + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n++ = c1*(*b1++) + c2*(*b2++) + c3*(*b3++) + c4*(*b4++); + *n = c1*(*b1) + c2*(*b2) + c3*(*b3) + c4*(*b4); + + return *this; +} + + +inline MatrixF &MatrixF::Resize (const int x, const int y) +{ + if (data!=NULL) { + if (rows==y && cols==x) return *this; + delete[] data; + } + rows = y; cols = x; + if (y>0 && x>0) { + len = rows * cols; + if (len!=0) { + data = new VTYPE[len]; + #ifdef DEBUG_MATRIX + if (data==NULL) Debug.Print (DEBUG_MATRIX, "MatrixF::Size: Out of memory for construction.\n"); + #endif + } + } + + #ifdef MATRIX_INITIALIZE + if (data!=NULL) memset (data, 0, sizeof(VTYPE)*len); + #endif + return *this; +} +inline MatrixF &MatrixF::ResizeSafe (const int x, const int y) +{ + VTYPE *newdata; + int newlen; + VTYPE *n, *ne; + VTYPE *b, *be; + int bskip; + + if (data!=NULL) { + newlen = x*y; + newdata = new VTYPE[newlen]; + #ifdef DEBUG_MATRIX + if (newdata==NULL) + Debug.Print (DEBUG_MATRIX, "MatrixF::SizeSafe: Out of memory for construction.\n"); + #endif + if (y>=rows && x>=cols) { // New size is larger (in both r and c) + memset (newdata, 0, newlen*sizeof(VTYPE)); // Clear new matrix + ne = data + len; // Calculate end of current matrix + b = newdata; // Start of new matrix + be = newdata + cols; // Last filled column+1 in new matrix + bskip = x-cols; + for (n = data; n0) { + n = data; // Copy columns to left of c + ne = data + len; + nskip = (cols-c); + b = newdata; + be = newdata + c; + bskip = (cols-c)+1; + for (; n>counter-clockwise<< when looking down the X+ axis toward the origin +inline MatrixF &MatrixF::RotateX (const double ang) +{ + Resize (4,4); + VTYPE *n = data; + double c,s; + c = cos(ang * 3.141592/180); + s = sin(ang * 3.141592/180); + *n = 1; n += 5; + *n++ = (VTYPE) c; *n = (VTYPE) s; n+=3; + *n++ = (VTYPE) -s; *n = (VTYPE) c; n+=5; + *n = 1; + return *this; +} + +// rotates points >>counter-clockwise<< when looking down the Y+ axis toward the origin +inline MatrixF &MatrixF::RotateY (const double ang) +{ + Resize (4,4); + VTYPE *n = data; + double c,s; + c = cos(ang * 3.141592/180); + s = sin(ang * 3.141592/180); + *n = (VTYPE) c; n+=2; + *n = (VTYPE) -s; n+=3; + *n = 1; n+=3; + *n = (VTYPE) s; n+=2; + *n = (VTYPE) c; n+=5; + *n = 1; + return *this; +} + +// rotates points >>counter-clockwise<< when looking down the Z+ axis toward the origin +inline MatrixF &MatrixF::RotateZ (const double ang) +{ + Resize (4,4); + VTYPE *n = data; + double c,s; + c = cos(ang * 3.141592/180); + s = sin(ang * 3.141592/180); + *n++ = (VTYPE) c; *n = (VTYPE) s; n+=3; + *n++ = (VTYPE) -s; *n = (VTYPE) c; n+=5; + *n = 1; n+=5; *n = 1; + return *this; +} +inline MatrixF &MatrixF::Ortho (double sx, double sy, double vn, double vf) +{ + // simplified version of OpenGL's glOrtho function + VTYPE *n = data; + *n++ = (VTYPE) (1.0/sx); *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; + *n++ = (VTYPE) 0.0; *n++ = (VTYPE) (1.0/sy); *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; + *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; *n++ = (VTYPE) (-2.0/(vf-vn)); *n++ = (VTYPE) (-(vf+vn)/(vf-vn)); + *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0; *n++ = (VTYPE) 1.0; +} + +inline MatrixF &MatrixF::Translate (double tx, double ty, double tz) +{ + Resize (4,4); + VTYPE *n = data; + *n++ = (VTYPE) 1.0; *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; + *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 1.0; *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; + *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 0.0; *n++ = (VTYPE) 1.0; *n++ = (VTYPE) 0.0; + *n++ = (VTYPE) tx; *n++ = (VTYPE) ty; *n++ = (VTYPE) tz; *n++ = (VTYPE) 1.0; + return *this; +} + +inline MatrixF &MatrixF::Basis (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3) +{ + Resize (4,4); + VTYPE *n = data; + *n++ = (VTYPE) c1.X(); *n++ = (VTYPE) c2.X(); *n++ = (VTYPE) c3.X(); *n++ = (VTYPE) 0; + *n++ = (VTYPE) c1.Y(); *n++ = (VTYPE) c2.Y(); *n++ = (VTYPE) c3.Y(); *n++ = (VTYPE) 0; + *n++ = (VTYPE) c1.Z(); *n++ = (VTYPE) c2.Z(); *n++ = (VTYPE) c3.Z(); *n++ = (VTYPE) 0; + *n++ = (VTYPE) 0; *n++ = (VTYPE) 0; *n++ = (VTYPE) 0; *n++ = (VTYPE) 0; + return *this; +} + +#define SWAP(a, b) {temp=(a); (a)=(b); (b)=temp;} + +inline MatrixF &MatrixF::GaussJordan (MatrixF &b) +{ + // Gauss-Jordan solves the matrix equation Ax = b + // Given the problem: + // A*x = b (where A is 'this' matrix and b is provided) + // The solution is: + // Ainv*b = x + // This function returns Ainv in A and x in b... that is: + // A (this) -> Ainv + // b -> solution x + // + + MatrixI index_col, index_row; + MatrixI piv_flag; + int r, c, c2, rs, cs; + double piv_val; + int piv_row, piv_col; + double pivinv, dummy, temp; + + #ifdef DEBUG_MATRIX + if (rows!=cols) Debug.Print (DEBUG_MATRIX, "MatrixF::GaussJordan: Number of rows and cols of A must be equal.\n"); + if (rows!=b.rows) Debug.Print (DEBUG_MATRIX, "MatrixF::GaussJordan: Number of rows of A and rows of b must be equal.\n"); + if (b.cols!=1) Debug.Print ( DEBUG_MATRIX, "MatrixF::GaussJordan: Number of cols of b must be 1.\n"); + #endif + + index_col.Resize (cols, 1); + index_row.Resize (cols, 1); + piv_flag.Resize (cols, 1); + piv_flag = 0; + for (c = 0; c < cols; c++) { + piv_val = 0.0; + for (rs = 0; rs < rows; rs++) { + if (piv_flag(rs, 0) != 1 ) + for (cs = 0; cs < cols; cs++) { + if (piv_flag(cs, 0) == 0) { + if (fabs((*this) (cs, rs)) >= piv_val) { + piv_val = fabs((*this) (cs, rs)); + piv_row = rs; + piv_col = cs; + } + } else if (piv_flag(cs, 0)>1) { + #ifdef DEBUG_MATRIX + Debug.Print (DEBUG_MATRIX, "MatrixF::GaussJordan: Singular matrix (dbl pivs).\n"); + //Print (); + #endif + } + } + } + piv_flag(piv_col, 0)++; + if (piv_row != piv_col) { + for (c2 = 0; c2 < cols; c2++) SWAP ((*this) (c2, piv_row), (*this) (c2, piv_col)); + for (c2 = 0; c2 < b.cols; c2++) SWAP (b(c2, piv_row), b(c2, piv_col)); + } + index_row (c, 0) = piv_row; + index_col (c, 0) = piv_col; + if ((*this) (piv_col, piv_col) == 0.0) { + #ifdef DEBUG_MATRIX + Debug.Print (DEBUG_MATRIX, "MatrixF::GaussJordan: Singular matrix (0 piv).\n"); + //Print (); + #endif + } + pivinv = 1.0 / ((*this) (piv_col, piv_col)); + (*this) (piv_col, piv_col) = 1.0; + for (c2 = 0; c2 < cols; c2++) (*this) (c2, piv_col) *= pivinv; + for (c2 = 0; c2 < b.cols; c2++) b(c2, piv_col) *= pivinv; + for (r = 0; r < rows; r++) { + if (r != piv_col) { + dummy = (*this) (piv_col, r); + (*this) (piv_col, r) = 0.0; + for (c2 = 0; c2 < cols; c2++) (*this) (c2, r) -= (*this) (c2, piv_col)*dummy; + for (c2 = 0; c2 < b.cols; c2++) b(c2, r) -= b(c2, piv_col)*dummy; + } + } + } + for (c = cols-1; c >= 0; c--) { + if (index_row(c, 0) != index_col(c, 0)) + for (r = 0; r < rows; r++) + SWAP ((*this) (index_row(c,0), r), (*this) (index_col(c,0), r) ); + } + return *this; +} +inline MatrixF &MatrixF::Submatrix ( MatrixF& b, int mx, int my) +{ + VTYPE* pEnd = data + rows*cols; // end of matrix + VTYPE* pVal = data; + VTYPE* pNewVal = b.data; + VTYPE* pNewEnd = pNewVal + mx; + int pNewSkip = cols - mx; + + for (pVal = data; pVal < pEnd;) { + for (; pNewVal < pNewEnd;) *pVal++ = *pNewVal++; + pNewVal += pNewSkip; + pNewEnd += mx; + } + return *this; +} + +// N-Vector Dot Product +// Elements may be in rows or columns, but: +// - If in rows, number of columns must be one and number of rows must match. +// - If in cols, number of rows must be one and number of cols must match. +inline double MatrixF::Dot ( MatrixF& b ) +{ + double d = 0.0; + VTYPE* pA = data; + VTYPE* pB = b.data; + + if ( rows==1 && b.rows==1 && cols == b.cols ) { + VTYPE* pAEnd = data + cols; + d = 0.0; + for (; pA < pAEnd;) + d += (*pA++) * (*pB++); + } else if ( cols==1 && b.cols==1 && rows == b.rows) { + VTYPE* pAEnd = data + rows; + d = 0.0; + for (; pA < pAEnd;) + d += (*pA++) * (*pB++); + } + return d; +} + +#define I(x, y) ( (y*xres) + x ) +#define Ix(r) ( r % xres ) // X coordinate from row +#define Iy(r) ( r / xres ) // Y coordinate from row + +inline MatrixF &MatrixF::MatrixVector5 (MatrixF& x, int mrows, MatrixF& b) +{ + double v; + + // A( 2, r ) * B ( r ) + A(1,r)*B(r-1) + A(3,r)*B(r+1) + A(0, r)*B( R-( r ) ) + A(4, r)*B( R+( r ) ) + for (int r = 0; r < mrows; r++) { + v = GetVal(2, r) * x(0,r); + if ( r > 0 ) v += GetVal(1,r) * x(0,r-1); + if ( r < mrows-1) v += GetVal(3,r) * x(0,r+1); + if ( (int) GetVal(5, r) >= 0) v += GetVal(0,r) * x(0, (int) GetVal(5,r)); + if ( (int) GetVal(6, r) >= 0) v += GetVal(4,r) * x(0, (int) GetVal(6,r)); + b(0,r) = v; + } + return *this; +} + +inline MatrixF &MatrixF::ConjugateGradient (MatrixF &b) +{ + return *this; +} + +// Sparse Conjugate Gradient 2D (special case) +// This compute conjugate gradients on a +// sparse "5-7" x N positive definite matrix. +// Only 'mrows' subset of the row-size of A and b will be used. +inline MatrixF &MatrixF::ConjugateGradient5 (MatrixF &b, int mrows ) +{ + double a, g, rdot; + int i, imax; + MatrixF x, xnew; // solution vector + MatrixF r, rnew; // residual + MatrixF p, ptemp; // search direction + MatrixF v; + + x.Resize ( 1, mrows ); + xnew.Resize ( 1, mrows ); + r.Resize ( 1, mrows ); + rnew.Resize ( 1, mrows ); + p.Resize ( 1, mrows ); + ptemp.Resize ( 1, mrows ); + v.Resize ( 1, mrows ); + + r.Submatrix ( b, 1, mrows); + MatrixVector5 ( x, mrows, v ); // (Ax -> v) + r -= v; // r = b - Ax + p = r; + + imax = 20; + for (i=0; i < imax; i++) { + MatrixVector5 ( p, mrows, v ); // v = Ap + rdot = r.Dot ( r ); + a = rdot / p.Dot ( v ); // a = (r . r) / (p . v) + xnew = p; + xnew *= a; + xnew += x; // x = x + p*a + v *= a; + rnew = r; // rnew = r - v*a + rnew -= v; + g = rnew.Dot ( rnew ) / rdot; // g = (rnew . rnew) / (r . r) + p *= g; + p += rnew; // p = rnew + p*g + r = rnew; + x = xnew; + } + for (int rx=0; rx < mrows; rx++) + b(0, rx) = x(0, rx); + return *this; +} + +inline int MatrixF::GetX() {return cols;} +inline int MatrixF::GetY() {return rows;} +inline int MatrixF::GetRows(void) {return rows;} +inline int MatrixF::GetCols(void) {return cols;} +inline int MatrixF::GetLength(void) {return len;} +inline VTYPE *MatrixF::GetData(void) {return data;} + +inline double MatrixF::GetF (const int r, const int c) {return (double) (*(data + r*cols + c));} + +inline void MatrixF::GetRowVec (int r, Vector3DF &v) +{ + VTYPE *n = data + r*cols; + v.x = (float) *n++; v.y = (float) *n++; v.z= (float) *n++; +} + +inline void MatrixF::Print ( char* fname ) +{ + char buf[2000]; + + FILE* fp = fopen ( fname, "w+" ); + + for (int r=0; r < rows; r++) { + buf[0] = '\0'; + for (int c =0; c < cols; c++) { + sprintf ( buf, "%s %04.3f", buf, GetVal(c, r) ); + } + fprintf ( fp, "%s\n", buf); + } + fprintf ( fp, "---------------------------------------\n", buf); + fflush ( fp ); + fclose ( fp ); +} + + +// MatrixF Code Definition +#undef VTYPE +#define VNAME F +#define VTYPE float + +// Constructors/Destructors + +inline Matrix4F::Matrix4F (void) { for (int n=0; n < 16; n++) data[n] = 0.0; } + +inline Matrix4F &Matrix4F::operator= (const unsigned char op) {for ( int n=0; n<16; n++) data[n] = (VTYPE) op; return *this;} +inline Matrix4F &Matrix4F::operator= (const int op) {for ( int n=0; n<16; n++) data[n] = (VTYPE) op; return *this;} +inline Matrix4F &Matrix4F::operator= (const double op) {for ( int n=0; n<16; n++) data[n] = (VTYPE) op; return *this;} +inline Matrix4F &Matrix4F::operator+= (const unsigned char op) {for ( int n=0; n<16; n++) data[n] += (VTYPE) op; return *this;} +inline Matrix4F &Matrix4F::operator+= (const int op) {for ( int n=0; n<16; n++) data[n] += (VTYPE) op; return *this;} +inline Matrix4F &Matrix4F::operator+= (const double op) {for ( int n=0; n<16; n++) data[n] += (VTYPE) op; return *this;} +inline Matrix4F &Matrix4F::operator-= (const unsigned char op) {for ( int n=0; n<16; n++) data[n] -= (VTYPE) op; return *this;} +inline Matrix4F &Matrix4F::operator-= (const int op) {for ( int n=0; n<16; n++) data[n] -= (VTYPE) op; return *this;} +inline Matrix4F &Matrix4F::operator-= (const double op) {for ( int n=0; n<16; n++) data[n] -= (VTYPE) op; return *this;} +inline Matrix4F &Matrix4F::operator*= (const unsigned char op) {for ( int n=0; n<16; n++) data[n] *= (VTYPE) op; return *this;} +inline Matrix4F &Matrix4F::operator*= (const int op) {for ( int n=0; n<16; n++) data[n] *= (VTYPE) op; return *this;} +inline Matrix4F &Matrix4F::operator*= (const double op) {for ( int n=0; n<16; n++) data[n] *= (VTYPE) op; return *this;} +inline Matrix4F &Matrix4F::operator/= (const unsigned char op) {for ( int n=0; n<16; n++) data[n] /= (VTYPE) op; return *this;} +inline Matrix4F &Matrix4F::operator/= (const int op) {for ( int n=0; n<16; n++) data[n] /= (VTYPE) op; return *this;} +inline Matrix4F &Matrix4F::operator/= (const double op) {for ( int n=0; n<16; n++) data[n] /= (VTYPE) op; return *this;} + +inline Matrix4F &Matrix4F::Multiply (const Matrix4F &op) { + register float orig[16]; // Temporary storage + memcpy ( orig, data, 16*sizeof(float) ); + + // Calculate First Row + data[0] = orig[0]*op.data[0] + orig[1]*op.data[4] + orig[2]*op.data[8] + orig[3]*op.data[12]; + data[1] = orig[0]*op.data[1] + orig[1]*op.data[5] + orig[2]*op.data[9] + orig[3]*op.data[13]; + data[2] = orig[0]*op.data[2] + orig[1]*op.data[6] + orig[2]*op.data[10] + orig[3]*op.data[14]; + data[3] = orig[0]*op.data[3] + orig[1]*op.data[7] + orig[2]*op.data[11] + orig[3]*op.data[15]; + + // Calculate Second Row + data[4] = orig[4]*op.data[0] + orig[5]*op.data[4] + orig[6]*op.data[8] + orig[7]*op.data[12]; + data[5] = orig[4]*op.data[1] + orig[5]*op.data[5] + orig[6]*op.data[9] + orig[7]*op.data[13]; + data[6] = orig[4]*op.data[2] + orig[5]*op.data[6] + orig[6]*op.data[10] + orig[7]*op.data[14]; + data[7] = orig[4]*op.data[3] + orig[5]*op.data[7] + orig[6]*op.data[11] + orig[7]*op.data[15]; + + // Calculate Third Row + data[8] = orig[8]*op.data[0] + orig[9]*op.data[4] + orig[10]*op.data[8] + orig[11]*op.data[12]; + data[9] = orig[8]*op.data[1] + orig[9]*op.data[5] + orig[10]*op.data[9] + orig[11]*op.data[13]; + data[10] = orig[8]*op.data[2] + orig[9]*op.data[6] + orig[10]*op.data[10] + orig[11]*op.data[14]; + data[11] = orig[8]*op.data[3] + orig[9]*op.data[7] + orig[10]*op.data[11] + orig[11]*op.data[15]; + + // Calculate Four Row + data[12] = orig[12]*op.data[0] + orig[13]*op.data[4] + orig[14]*op.data[8] + orig[15]*op.data[12]; + data[13] = orig[12]*op.data[1] + orig[13]*op.data[5] + orig[14]*op.data[9] + orig[15]*op.data[13]; + data[14] = orig[12]*op.data[2] + orig[13]*op.data[6] + orig[14]*op.data[10] + orig[15]*op.data[14]; + data[15] = orig[12]*op.data[3] + orig[13]*op.data[7] + orig[14]*op.data[11] + orig[15]*op.data[15]; + + return *this; +} + +inline Matrix4F &Matrix4F::Transpose (void) +{ + register float orig[16]; // Temporary storage + memcpy ( orig, data, 16*sizeof(VTYPE) ); + + data[0] = orig[0]; data[1] = orig[4]; data[2] = orig[8]; data[3] = orig[12]; + data[4] = orig[1]; data[5] = orig[5]; data[6] = orig[9]; data[7] = orig[13]; + data[8] = orig[2]; data[9] = orig[6]; data[10] = orig[10];data[11] = orig[14]; + data[12] = orig[3]; data[13] = orig[7]; data[14] = orig[11];data[15] = orig[15]; + return *this; +} + +inline Matrix4F &Matrix4F::Identity (const int order) +{ + memset (data, 0, 16*sizeof(VTYPE)); + data[0] = 1.0; + data[5] = 1.0; + data[10] = 1.0; + data[15] = 1.0; + return *this; +} + +inline Matrix4F &Matrix4F::RotateX (const double ang) +{ + memset (data, 0, 16*sizeof(VTYPE)); + double c,s; + c = cos(ang * 3.141592/180); + s = sin(ang * 3.141592/180); + data[0] = 1; + data[5] = (VTYPE) c; data[6] = (VTYPE) s; + data[9] = (VTYPE) -s; data[10] = (VTYPE) c; + data[15] = 1; + return *this; +} + +// rotates points >>counter-clockwise<< when looking down the Y+ axis toward the origin +inline Matrix4F &Matrix4F::RotateY (const double ang) +{ + memset (data, 0, 16*sizeof(VTYPE)); + double c,s; + c = cos(ang * 3.141592/180); + s = sin(ang * 3.141592/180); + data[0] = (VTYPE) c; + data[2] = (VTYPE) -s; + data[5] = 1; + data[8] = (VTYPE) s; + data[10] = (VTYPE) c; + data[15] = 1; + return *this; +} + +// rotates points >>counter-clockwise<< when looking down the Z+ axis toward the origin +inline Matrix4F &Matrix4F::RotateZ (const double ang) +{ + memset (data, 0, 16*sizeof(VTYPE)); + double c,s; + c = cos(ang * 3.141592/180); + s = sin(ang * 3.141592/180); + data[0] = (VTYPE) c; data[1] = (VTYPE) s; + data[4] = (VTYPE) -s; data[5] = (VTYPE) c; + data[10] = 1; + data[15] = 1; + return *this; +} +inline Matrix4F &Matrix4F::Ortho (double sx, double sy, double vn, double vf) +{ + // simplified version of OpenGL's glOrtho function + data[ 0] = (VTYPE) (1.0/sx);data[ 1] = (VTYPE) 0.0; data[ 2] = (VTYPE) 0.0; data[ 3]= (VTYPE) 0.0; + data[ 4] = (VTYPE) 0.0; data[ 5] = (VTYPE) (1.0/sy);data[ 6] = (VTYPE) 0.0; data[ 7] = (VTYPE) 0.0; + data[ 8] = (VTYPE) 0.0; data[ 9] = (VTYPE) 0.0; data[10]= (VTYPE) (-2.0/(vf-vn)); data[11] = (VTYPE) (-(vf+vn)/(vf-vn)); + data[12] = (VTYPE) 0.0; data[13] = (VTYPE) 0.0; data[14] = (VTYPE) 0; data[15] = (VTYPE) 1.0; +} + +inline Matrix4F &Matrix4F::Translate (double tx, double ty, double tz) +{ + data[ 0] = (VTYPE) 1.0; data[ 1] = (VTYPE) 0.0; data[ 2] = (VTYPE) 0.0; data[ 3] = (VTYPE) 0.0; + data[ 4] = (VTYPE) 0.0; data[ 5] = (VTYPE) 1.0; data[ 6] = (VTYPE) 0.0; data[ 7] = (VTYPE) 0.0; + data[ 8] = (VTYPE) 0.0; data[ 9] = (VTYPE) 0.0; data[10] = (VTYPE) 1.0; data[11] = (VTYPE) 0.0; + data[12] = (VTYPE) tx; data[13] = (VTYPE) ty; data[14] = (VTYPE) tz; data[15] = (VTYPE) 1.0; + return *this; +} + +inline Matrix4F &Matrix4F::Basis (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3) +{ + data[ 0] = (VTYPE) c1.x; data[ 1] = (VTYPE) c2.x; data[ 2] = (VTYPE) c3.x; data[ 3] = (VTYPE) 0.0; + data[ 4] = (VTYPE) c1.y; data[ 5] = (VTYPE) c2.y; data[ 6] = (VTYPE) c3.y; data[ 7] = (VTYPE) 0.0; + data[ 8] = (VTYPE) c1.z; data[ 9] = (VTYPE) c2.z; data[10] = (VTYPE) c3.z; data[11] = (VTYPE) 0.0; + data[12] = (VTYPE) 0.0; data[13] = (VTYPE) 0.0; data[14] = (VTYPE) 0.0; data[15] = (VTYPE) 1.0; + return *this; +} + +inline Matrix4F &Matrix4F::SRT (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3, const Vector3DF& t, const Vector3DF& s) +{ + data[ 0] = (VTYPE) c1.x*s.x; data[ 1] = (VTYPE) c2.x*s.x; data[ 2] = (VTYPE) c3.x*s.x; data[ 3] = (VTYPE) 0.0; + data[ 4] = (VTYPE) c1.y*s.y; data[ 5] = (VTYPE) c2.y*s.y; data[ 6] = (VTYPE) c3.y*s.y; data[ 7] = (VTYPE) 0.0; + data[ 8] = (VTYPE) c1.z*s.z; data[ 9] = (VTYPE) c2.z*s.z; data[10] = (VTYPE) c3.z*s.z; data[11] = (VTYPE) 0.0; + data[12] = (VTYPE) t.x; data[13] = (VTYPE) t.y; data[14] = (VTYPE) t.z; data[15] = (VTYPE) 1.0; +} +inline Matrix4F &Matrix4F::SRT (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3, const Vector3DF& t, const float s) +{ + data[ 0] = (VTYPE) c1.x*s; data[ 1] = (VTYPE) c1.y*s; data[ 2] = (VTYPE) c1.z*s; data[ 3] = (VTYPE) 0.0; + data[ 4] = (VTYPE) c2.x*s; data[ 5] = (VTYPE) c2.y*s; data[ 6] = (VTYPE) c2.z*s; data[ 7] = (VTYPE) 0.0; + data[ 8] = (VTYPE) c3.x*s; data[ 9] = (VTYPE) c3.y*s; data[10] = (VTYPE) c3.z*s; data[11] = (VTYPE) 0.0; + data[12] = (VTYPE) t.x; data[13] = (VTYPE) t.y; data[14] = (VTYPE) t.z; data[15] = (VTYPE) 1.0; + return *this; +} + +inline Matrix4F &Matrix4F::InvTRS (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3, const Vector3DF& t, const Vector3DF& s) +{ + data[ 0] = (VTYPE) c1.x/s.x; data[ 1] = (VTYPE) c1.y/s.y; data[ 2] = (VTYPE) c1.z/s.z; data[ 3] = (VTYPE) 0.0; + data[ 4] = (VTYPE) c2.x/s.x; data[ 5] = (VTYPE) c2.y/s.y; data[ 6] = (VTYPE) c2.z/s.z; data[ 7] = (VTYPE) 0.0; + data[ 8] = (VTYPE) c3.x/s.x; data[ 9] = (VTYPE) c3.y/s.y; data[10] = (VTYPE) c3.z/s.z; data[11] = (VTYPE) 0.0; + data[12] = (VTYPE) -t.x/s.x; data[13] = (VTYPE) -t.y/s.y; data[14] = (VTYPE) -t.z/s.z; data[15] = (VTYPE) 1.0; +} +inline Matrix4F &Matrix4F::InvTRS (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3, const Vector3DF& t, const float s) +{ + data[ 0] = (VTYPE) c1.x/s; data[ 1] = (VTYPE) c1.y/s; data[ 2] = (VTYPE) c1.z/s; data[ 3] = (VTYPE) 0.0; + data[ 4] = (VTYPE) c2.x/s; data[ 5] = (VTYPE) c2.y/s; data[ 6] = (VTYPE) c2.z/s; data[ 7] = (VTYPE) 0.0; + data[ 8] = (VTYPE) c3.x/s; data[ 9] = (VTYPE) c3.y/s; data[10] = (VTYPE) c3.z/s; data[11] = (VTYPE) 0.0; + data[12] = (VTYPE) -t.x/s; data[13] = (VTYPE) -t.y/s; data[14] = (VTYPE) -t.z/s; data[15] = (VTYPE) 1.0; +} + +inline float Matrix4F::GetF (const int r, const int c) {return (float) data[ (r<<2) + c];} + +inline void Matrix4F::GetRowVec (int r, Vector3DF &v) +{ + v.x = data[ (r<<2) ]; + v.y = data[ (r<<2)+1 ]; + v.z = data[ (r<<2)+2 ]; +} + +#undef VTYPE +#undef VNAME + diff --git a/Extras/sph/common/matrix.cpp b/Extras/sph/common/matrix.cpp new file mode 100644 index 0000000..35d56aa --- /dev/null +++ b/Extras/sph/common/matrix.cpp @@ -0,0 +1,23 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 "matrix.h" + diff --git a/Extras/sph/common/matrix.h b/Extras/sph/common/matrix.h new file mode 100644 index 0000000..956bfe4 --- /dev/null +++ b/Extras/sph/common/matrix.h @@ -0,0 +1,429 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 +#include +#include +#include +#include + +//*********** NOTE +// +// LOOK AT MovieTrackPoint. IN ORDER FOR VECTORS AND MATRICIES TO BE USED IN OBJECTS +// THAT WILL BE USED IN stl::vectors, THEIR CONSTRUCTORS AND OPERATORS MUST TAKE ONLY +// const PARAMETERS. LOOK AT MatrixF and Vector2DF.. THIS WAS NOT YET DONE WITH +// THE OTHER MATRIX AND VECTOR CLASSES (Vector2DC, Vector2DI, MatrixC, MatrixI, ...) +// + + +#ifndef MATRIX_DEF + #define MATRIX_DEF + + #include "vector.h" + #include "mdebug.h" + + //#define MATRIX_INITIALIZE // Initializes vectors + + class MatrixC; // Forward Referencing + class MatrixI; + class MatrixF; + + class Matrix { + public: + // Member Virtual Functions + virtual Matrix &operator= (unsigned char c)=0; + virtual Matrix &operator= (int c)=0; + virtual Matrix &operator= (double c)=0; + virtual Matrix &operator= (MatrixC &op)=0; + virtual Matrix &operator= (MatrixI &op)=0; + virtual Matrix &operator= (MatrixF &op)=0; + + virtual Matrix &operator+= (unsigned char c)=0; + virtual Matrix &operator+= (int c)=0; + virtual Matrix &operator+= (double c)=0; + virtual Matrix &operator+= (MatrixC &op)=0; + virtual Matrix &operator+= (MatrixI &op)=0; + virtual Matrix &operator+= (MatrixF &op)=0; + + virtual Matrix &operator-= (unsigned char c)=0; + virtual Matrix &operator-= (int c)=0; + virtual Matrix &operator-= (double c)=0; + virtual Matrix &operator-= (MatrixC &op)=0; + virtual Matrix &operator-= (MatrixI &op)=0; + virtual Matrix &operator-= (MatrixF &op)=0; + + virtual Matrix &operator*= (unsigned char c)=0; + virtual Matrix &operator*= (int c)=0; + virtual Matrix &operator*= (double c)=0; + virtual Matrix &operator*= (MatrixC &op)=0; + virtual Matrix &operator*= (MatrixI &op)=0; + virtual Matrix &operator*= (MatrixF &op)=0; + + virtual Matrix &operator/= (unsigned char c)=0; + virtual Matrix &operator/= (int c)=0; + virtual Matrix &operator/= (double c)=0; + virtual Matrix &operator/= (MatrixC &op)=0; + virtual Matrix &operator/= (MatrixI &op)=0; + virtual Matrix &operator/= (MatrixF &op)=0; + + virtual Matrix &Multiply (MatrixF &op)=0; + virtual Matrix &Resize (int x, int y)=0; + virtual Matrix &ResizeSafe (int x, int y)=0; + virtual Matrix &InsertRow (int r)=0; + virtual Matrix &InsertCol (int c)=0; + virtual Matrix &Transpose (void)=0; + virtual Matrix &Identity (int order)=0; + /*inline Matrix &RotateX (double ang); + inline Matrix &RotateY (double ang); + inline Matrix &RotateZ (double ang); */ + virtual Matrix &Basis (Vector3DF &c1, Vector3DF &c2, Vector3DF &c3)=0; + virtual Matrix &GaussJordan (MatrixF &b) { return *this; } + virtual Matrix &ConjugateGradient (MatrixF &b) { return *this; } + + virtual int GetRows(void)=0; + virtual int GetCols(void)=0; + virtual int GetLength(void)=0; + + virtual unsigned char *GetDataC (void)=0; + virtual int *GetDataI (void)=0; + virtual double *GetDataF (void)=0; + + virtual double GetF (int r, int c); + }; + + // MatrixC Declaration + #define VNAME C + #define VTYPE unsigned char + + class MatrixC { + public: + VTYPE *data; + int rows, cols, len; + + // Constructors/Destructors + inline MatrixC (); + inline ~MatrixC (); + inline MatrixC (int r, int c); + + // Member Functions + inline VTYPE &operator () (int c, int r); + inline MatrixC &operator= (unsigned char c); + inline MatrixC &operator= (int c); + inline MatrixC &operator= (double c); + inline MatrixC &operator= (MatrixC &op); + inline MatrixC &operator= (MatrixI &op); + inline MatrixC &operator= (MatrixF &op); + + inline MatrixC &operator+= (unsigned char c); + inline MatrixC &operator+= (int c); + inline MatrixC &operator+= (double c); + inline MatrixC &operator+= (MatrixC &op); + inline MatrixC &operator+= (MatrixI &op); + inline MatrixC &operator+= (MatrixF &op); + + inline MatrixC &operator-= (unsigned char c); + inline MatrixC &operator-= (int c); + inline MatrixC &operator-= (double c); + inline MatrixC &operator-= (MatrixC &op); + inline MatrixC &operator-= (MatrixI &op); + inline MatrixC &operator-= (MatrixF &op); + + inline MatrixC &operator*= (unsigned char c); + inline MatrixC &operator*= (int c); + inline MatrixC &operator*= (double c); + inline MatrixC &operator*= (MatrixC &op); + inline MatrixC &operator*= (MatrixI &op); + inline MatrixC &operator*= (MatrixF &op); + + inline MatrixC &operator/= (unsigned char c); + inline MatrixC &operator/= (int c); + inline MatrixC &operator/= (double c); + inline MatrixC &operator/= (MatrixC &op); + inline MatrixC &operator/= (MatrixI &op); + inline MatrixC &operator/= (MatrixF &op); + + inline MatrixC &Multiply (MatrixF &op); + inline MatrixC &Resize (int x, int y); + inline MatrixC &ResizeSafe (int x, int y); + inline MatrixC &InsertRow (int r); + inline MatrixC &InsertCol (int c); + inline MatrixC &Transpose (void); + inline MatrixC &Identity (int order); + inline MatrixC &Basis (Vector3DF &c1, Vector3DF &c2, Vector3DF &c3); + inline MatrixC &GaussJordan (MatrixF &b); + + inline int GetX(); + inline int GetY(); + inline int GetRows(void); + inline int GetCols(void); + inline int GetLength(void); + inline VTYPE *GetData(void); + + inline unsigned char *GetDataC (void) {return data;} + inline int *GetDataI (void) {return NULL;} + inline double *GetDataF (void) {return NULL;} + + inline double GetF (int r, int c); + }; + #undef VNAME + #undef VTYPE + + // MatrixI Declaration + #define VNAME I + #define VTYPE int + + class MatrixI { + public: + VTYPE *data; + int rows, cols, len; + + // Constructors/Destructors + inline MatrixI (); + inline ~MatrixI (); + inline MatrixI (int r, int c); + + // Member Functions + inline VTYPE &operator () (int c, int r); + inline MatrixI &operator= (unsigned char c); + inline MatrixI &operator= (int c); + inline MatrixI &operator= (double c); + inline MatrixI &operator= (MatrixC &op); + inline MatrixI &operator= (MatrixI &op); + inline MatrixI &operator= (MatrixF &op); + + inline MatrixI &operator+= (unsigned char c); + inline MatrixI &operator+= (int c); + inline MatrixI &operator+= (double c); + inline MatrixI &operator+= (MatrixC &op); + inline MatrixI &operator+= (MatrixI &op); + inline MatrixI &operator+= (MatrixF &op); + + inline MatrixI &operator-= (unsigned char c); + inline MatrixI &operator-= (int c); + inline MatrixI &operator-= (double c); + inline MatrixI &operator-= (MatrixC &op); + inline MatrixI &operator-= (MatrixI &op); + inline MatrixI &operator-= (MatrixF &op); + + inline MatrixI &operator*= (unsigned char c); + inline MatrixI &operator*= (int c); + inline MatrixI &operator*= (double c); + inline MatrixI &operator*= (MatrixC &op); + inline MatrixI &operator*= (MatrixI &op); + inline MatrixI &operator*= (MatrixF &op); + + inline MatrixI &operator/= (unsigned char c); + inline MatrixI &operator/= (int c); + inline MatrixI &operator/= (double c); + inline MatrixI &operator/= (MatrixC &op); + inline MatrixI &operator/= (MatrixI &op); + inline MatrixI &operator/= (MatrixF &op); + + inline MatrixI &Multiply (MatrixF &op); + inline MatrixI &Resize (int x, int y); + inline MatrixI &ResizeSafe (int x, int y); + inline MatrixI &InsertRow (int r); + inline MatrixI &InsertCol (int c); + inline MatrixI &Transpose (void); + inline MatrixI &Identity (int order); + inline MatrixI &Basis (Vector3DF &c1, Vector3DF &c2, Vector3DF &c3); + inline MatrixI &GaussJordan (MatrixF &b); + + inline int GetX(); + inline int GetY(); + inline int GetRows(void); + inline int GetCols(void); + inline int GetLength(void); + inline VTYPE *GetData(void); + + inline unsigned char *GetDataC (void) {return NULL;} + inline int *GetDataI (void) {return data;} + inline double *GetDataF (void) {return NULL;} + + inline double GetF (int r, int c); + }; + #undef VNAME + #undef VTYPE + + // MatrixF Declaration + #define VNAME F + #define VTYPE double + + class MatrixF { + public: + VTYPE *data; + int rows, cols, len; + + // Constructors/Destructors + inline MatrixF (); + inline ~MatrixF (); + inline MatrixF (const int r, const int c); + + // Member Functions + inline VTYPE GetVal ( int c, int r ); + inline VTYPE &operator () (const int c, const int r); + inline MatrixF &operator= (const unsigned char c); + inline MatrixF &operator= (const int c); + inline MatrixF &operator= (const double c); + inline MatrixF &operator= (const MatrixC &op); + inline MatrixF &operator= (const MatrixI &op); + inline MatrixF &operator= (const MatrixF &op); + + inline MatrixF &operator+= (const unsigned char c); + inline MatrixF &operator+= (const int c); + inline MatrixF &operator+= (const double c); + inline MatrixF &operator+= (const MatrixC &op); + inline MatrixF &operator+= (const MatrixI &op); + inline MatrixF &operator+= (const MatrixF &op); + + inline MatrixF &operator-= (const unsigned char c); + inline MatrixF &operator-= (const int c); + inline MatrixF &operator-= (const double c); + inline MatrixF &operator-= (const MatrixC &op); + inline MatrixF &operator-= (const MatrixI &op); + inline MatrixF &operator-= (const MatrixF &op); + + inline MatrixF &operator*= (const unsigned char c); + inline MatrixF &operator*= (const int c); + inline MatrixF &operator*= (const double c); + inline MatrixF &operator*= (const MatrixC &op); + inline MatrixF &operator*= (const MatrixI &op); + inline MatrixF &operator*= (const MatrixF &op); + + inline MatrixF &operator/= (const unsigned char c); + inline MatrixF &operator/= (const int c); + inline MatrixF &operator/= (const double c); + inline MatrixF &operator/= (const MatrixC &op); + inline MatrixF &operator/= (const MatrixI &op); + inline MatrixF &operator/= (const MatrixF &op); + + inline MatrixF &Multiply4x4 (const MatrixF &op); + inline MatrixF &Multiply (const MatrixF &op); + inline MatrixF &Resize (const int x, const int y); + inline MatrixF &ResizeSafe (const int x, const int y); + inline MatrixF &InsertRow (const int r); + inline MatrixF &InsertCol (const int c); + inline MatrixF &Transpose (void); + inline MatrixF &Identity (const int order); + inline MatrixF &RotateX (const double ang); + inline MatrixF &RotateY (const double ang); + inline MatrixF &RotateZ (const double ang); + inline MatrixF &Ortho (double sx, double sy, double n, double f); + inline MatrixF &Translate (double tx, double ty, double tz); + inline MatrixF &Basis (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3); + inline MatrixF &GaussJordan (MatrixF &b); + inline MatrixF &ConjugateGradient (MatrixF &b); + inline MatrixF &Submatrix ( MatrixF& b, int mx, int my); + inline MatrixF &MatrixVector5 (MatrixF& x, int mrows, MatrixF& b ); + inline MatrixF &ConjugateGradient5 (MatrixF &b, int mrows ); + inline double Dot ( MatrixF& b ); + + inline void Print ( char* fname ); + + inline int GetX(); + inline int GetY(); + inline int GetRows(void); + inline int GetCols(void); + inline int GetLength(void); + inline VTYPE *GetData(void); + inline void GetRowVec (int r, Vector3DF &v); + + inline unsigned char *GetDataC (void) const {return NULL;} + inline int *GetDataI (void) const {return NULL;} + inline double *GetDataF (void) const {return data;} + + inline double GetF (const int r, const int c); + }; + #undef VNAME + #undef VTYPE + + // MatrixF Declaration + #define VNAME F + #define VTYPE float + + class Matrix4F { + public: + VTYPE data[16]; + + // Constructors/Destructors + inline Matrix4F (); + + // Member Functions + inline VTYPE &operator () (const int n) { return data[n]; } + inline VTYPE &operator () (const int c, const int r) { return data[ (r<<2)+c ]; } + inline Matrix4F &operator= (const unsigned char c); + inline Matrix4F &operator= (const int c); + inline Matrix4F &operator= (const double c); + inline Matrix4F &operator+= (const unsigned char c); + inline Matrix4F &operator+= (const int c); + inline Matrix4F &operator+= (const double c); + inline Matrix4F &operator-= (const unsigned char c); + inline Matrix4F &operator-= (const int c); + inline Matrix4F &operator-= (const double c); + inline Matrix4F &operator*= (const unsigned char c); + inline Matrix4F &operator*= (const int c); + inline Matrix4F &operator*= (const double c); + inline Matrix4F &operator/= (const unsigned char c); + inline Matrix4F &operator/= (const int c); + inline Matrix4F &operator/= (const double c); + + inline Matrix4F &Multiply (const Matrix4F &op); + inline Matrix4F &Transpose (void); + inline Matrix4F &Identity (const int order); + inline Matrix4F &RotateX (const double ang); + inline Matrix4F &RotateY (const double ang); + inline Matrix4F &RotateZ (const double ang); + inline Matrix4F &Ortho (double sx, double sy, double n, double f); + inline Matrix4F &Translate (double tx, double ty, double tz); + inline Matrix4F &Basis (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3); + + // Scale-Rotate-Translate (compound matrix) + inline Matrix4F &SRT (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3, const Vector3DF& t, const Vector3DF& s); + inline Matrix4F &SRT (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3, const Vector3DF& t, const float s); + + // invTranslate-invRotate-invScale (compound matrix) + inline Matrix4F &InvTRS (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3, const Vector3DF& t, const Vector3DF& s); + inline Matrix4F &InvTRS (const Vector3DF &c1, const Vector3DF &c2, const Vector3DF &c3, const Vector3DF& t, const float s); + + inline int GetX() { return 4; } + inline int GetY() { return 4; } + inline int GetRows(void) { return 4; } + inline int GetCols(void) { return 4; } + inline int GetLength(void) { return 16; } + inline VTYPE *GetData(void) { return data; } + inline void GetRowVec (int r, Vector3DF &v); + + inline unsigned char *GetDataC (void) const {return NULL;} + inline int *GetDataI (void) const {return NULL;} + inline float *GetDataF (void) const {return (float*) data;} + + inline float GetF (const int r, const int c); + }; + #undef VNAME + #undef VTYPE + + + // Matrix Code Definitions (Inlined) + + #include "matrix.cci" + +#endif + diff --git a/Extras/sph/common/mdebug.cpp b/Extras/sph/common/mdebug.cpp new file mode 100644 index 0000000..b0b868b --- /dev/null +++ b/Extras/sph/common/mdebug.cpp @@ -0,0 +1,583 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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. +*/ + + + +//#define MEMORY_DEBUG // Overloads the new and delete operators + +#include +#include +#include + +#include "mdebug.h" + +#ifdef _MSC_VER + #include + #include + #include + #include +#endif + +CDebug debug; +CError error; + +//------------------------------------------------- DEBUG CLASS +CDebug::CDebug () +{ + m_OutName = "debug.txt"; + m_bStarted = false; + m_bToFile = true; + m_bToSysbox = true; + m_bToCons = false; + m_OutFile = NULL; + m_OutCons = NULL; + Start (); +} + +CDebug::~CDebug (void) +{ + Stop (); +} + +void CDebug::Start () +{ + if ( m_bStarted ) Stop (); + + if ( m_bToFile ) { + char fn[200]; + +#ifdef _MSC_VER + strcpy_s ( fn, 200, m_OutName.c_str () ); + fopen_s ( &m_OutFile, fn, "w+t" ); +#else + strncpy ( fn, m_OutName.c_str(), 200 ); + m_OutFile = fopen( fn, "w+" ); +#endif + + if ( m_OutFile == 0x0 ) { + exit ( EXIT_FAILURE ); // error: Cannot create debug file + } + m_bStarted = true; + Print ( "debug", "CDebug started to file.\n"); + } + m_bStarted = true; +} + +void CDebug::Exit ( int code ) +{ + if ( !m_bToSysbox ) { + #ifdef _MSC_VER + _getch(); + #endif + } + exit ( code ); +} + +void CDebug::Stop () +{ + if ( m_bStarted ) { + if ( m_bToFile ) { + Print ( "debug", "CDebug stopped."); + fclose ( m_OutFile ); + } + } + m_bStarted = false; +} + +void CDebug::SendToFile ( char* fname ) +{ + if (m_bStarted) Stop (); + m_bToFile = true; + m_OutName = fname; +} + +void CDebug::SendToConsole ( bool tf ) +{ + m_bToCons = tf; + if ( tf ) { + #ifdef _MSC_VER + AllocConsole (); + long lStdHandle = (long) GetStdHandle( STD_OUTPUT_HANDLE ); + int hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); + m_OutCons = _fdopen( hConHandle, "w" ); + #endif + } +} + +void CDebug::SendToSysbox ( bool tf ) +{ + m_bToSysbox = tf; +} + +void CDebug::Print ( std::string subsys, std::string msg ) +{ + if ( m_bStarted ) { + if ( m_bToFile ) { + fprintf ( m_OutFile, "%s: %s\n", subsys.c_str(), msg.c_str() ); + fflush ( m_OutFile); + } + if ( m_bToCons ) { + #ifdef _MSC_VER + fprintf ( m_OutCons, "%s: %s\n", subsys.c_str(), msg.c_str() ); + fflush ( m_OutCons ); + #else + printf ( "%s: %s\n", subsys.c_str(), msg.c_str() ); + #endif + } + } +} + +void CDebug::Print (char* msg) +{ + if ( m_bStarted ) { + if ( m_bToFile ) { + fprintf ( m_OutFile, "%s", msg ); + fflush ( m_OutFile ); + } + if ( m_bToCons ) { + #ifdef _MSC_VER + fprintf ( m_OutCons, "%s", msg ); + fflush ( m_OutCons ); + #else + printf ( "%s", msg ); + #endif + } + } +} + +void CDebug::Print ( std::string msg ) +{ + if ( m_bStarted ) { + if ( m_bToFile ) { + fprintf ( m_OutFile, "%s", msg.c_str() ); + fflush ( m_OutFile ); + } + if ( m_bToCons ) { + #ifdef _MSC_VER + fprintf ( m_OutCons, "%s", msg.c_str() ); + fflush ( m_OutCons ); + #else + printf ( "%s", msg.c_str() ); + #endif + } + } +} + +void CDebug::PrintF ( std::string substr, char* format, ... ) +{ + // Note: This is the >only< way to do this. There is no general way to + // pass on all the arguments from one ellipsis function to another. + // The function vfprintf was specially designed to allow this. + + if ( m_bStarted ) { + if ( m_bToFile ) { + va_list argptr; + va_start (argptr, format); + fprintf ( m_OutFile, "%s: ", substr.c_str() ); + vfprintf ( m_OutFile, format, argptr); + va_end (argptr); + fflush ( m_OutFile ); + } + if ( m_bToCons ) { + #ifdef _MSC_VER + va_list argptr; + va_start (argptr, format); + fprintf ( m_OutCons, "%s: ", substr.c_str() ); + vfprintf ( m_OutCons, format, argptr); + va_end (argptr); + fflush ( m_OutCons ); + #else + va_list argptr; + va_start (argptr, format); + printf ( "%s: ", substr.c_str() ); + vprintf ( format, argptr); + va_end (argptr); + #endif + } + } +} + + +void CDebug::Printf ( char* format, ... ) +{ + // Note: This is the >only< way to do this. There is no general way to + // pass on all the arguments from one ellipsis function to another. + // The function vfprintf was specially designed to allow this. + + if ( m_bStarted ) { + if ( m_bToFile ) { + va_list argptr; + va_start (argptr, format); + vfprintf ( m_OutFile, format, argptr); + va_end (argptr); + fflush ( m_OutFile ); + } + if ( m_bToCons ) { + #ifdef _MSC_VER + va_list argptr; + va_start (argptr, format); + vfprintf ( m_OutCons, format, argptr); + va_end (argptr); + fflush ( m_OutCons ); + #else + va_list argptr; + va_start (argptr, format); + vprintf ( format, argptr); + va_end (argptr); + #endif + } + } +} + +void CDebug::PrintErr ( std::string errid, std::string subsys, std::string msg, std::string sysbox ) +{ + if ( m_bStarted ) { + if ( m_bToFile ) { + fprintf ( m_OutFile, "%s: ERROR: %s\n", subsys.c_str(), msg.c_str() ); + fflush ( m_OutFile ); + } + if ( m_bToCons ) { + #ifdef _MSC_VER + fprintf ( m_OutCons, "%s: ERROR: %s\n", subsys.c_str(), msg.c_str() ); + fflush ( m_OutCons ); + #else + printf ( "%s: ERROR[%s] %s\n", subsys.c_str(), errid.c_str(), msg.c_str() ); + #endif + } + if ( m_bToSysbox ) { + char disp[4000]; + char caption[200]; + + #ifdef _MSC_VER + // Message boxes for Windows + strcpy_s ( caption, 200, "Mint - Error" ); + strcpy_s ( disp, 4000, sysbox.c_str()); + #include + int hr = MessageBoxA ( 0x0, disp, caption, MB_OK); + #else + strncpy ( caption, m_ErrorSubsys.c_str(), 200 ); + strncpy ( disp, msg.c_str(), 4000 ); + #endif + } + } +} + + +//-------------------------------------------------------------------- Error Class Code +// +// This software is released under the LGPL Open Source Liscense. +// See the documentation included with this source code for terms of modification, +// distribution and re-release. +// +// Original Copyright (C) 2002 Rama C. Hoetzlein, GameX R4 +// + +CError::CError () +{ + m_Errors.clear (); + m_ErrorID = ""; + m_ErrorSubsys = ""; + m_ErrorMsg = ""; + m_ErrorFunc = ""; + m_ErrorFix = ""; + m_ErrorExtra = ""; +} + +void CError::Start () +{ + Start ( "" ); +} + +void CError::Start ( char* fname ) +{ + if ( fname != 0x0 && strlen(fname) > 0 ) { + // Read error message file. NOT YET IMPLEMENTED + } else { + debug.Print ( "error", "No error file loaded." ); + } + debug.Print ( "error", "Error handler started." ); + m_bStarted = true; +} + +void CError::OutputMessage () +{ + // Create sysbox message + std::string box_msg; + box_msg = "Subsystem: " + m_ErrorSubsys + "\n\n"; + box_msg += "Error: " + m_ErrorMsg + "\n"; + if ( m_ErrorExtra.length() > 0) box_msg += "Info: " + m_ErrorExtra + "\n"; + if ( m_ErrorFix.length() > 0) box_msg += "\nFix: " + m_ErrorFix + "\n"; + if ( m_ErrorID.length() > 0 ) box_msg += "Error ID: " + m_ErrorID + "\n"; + if ( m_ErrorFunc.length() > 0 ) box_msg += "Function: " + m_ErrorFunc + "\n"; + + // Error output to debug file + debug.PrintErr ( m_ErrorID, m_ErrorSubsys, m_ErrorMsg, box_msg ); +} + +void CError::Exit ( int code ) +{ + debug.Exit ( code ); +} + +void CError::Print ( char* msg) +{ + // User-level error (no additional info) + m_ErrorID = ""; + m_ErrorSubsys = "undef"; + m_ErrorMsg = msg; + m_ErrorFunc = ""; + m_ErrorFix = ""; + m_ErrorExtra = ""; + OutputMessage (); +} + +void CError::Print ( std::string msg ) +{ + // User-level error (no additional info) + m_ErrorID = ""; + m_ErrorSubsys = "undef"; + m_ErrorMsg = msg; + m_ErrorFunc = ""; + m_ErrorFix = ""; + m_ErrorExtra = ""; + OutputMessage (); +} + +void CError::Print ( std::string subsys, std::string msg ){ + // Unregistered error + m_ErrorID = ""; + m_ErrorSubsys = subsys; + m_ErrorMsg = msg; + m_ErrorFunc = ""; + m_ErrorFix = ""; + m_ErrorExtra = ""; + OutputMessage (); +} + +void CError::PrintF ( std::string subsys, char* msg, ... ) +{ + char buf[2000]; + va_list argptr; + m_ErrorID = ""; + m_ErrorSubsys = subsys; + va_start(argptr, msg); + #ifdef _MSC_VER + vsprintf_s (buf, 2000, msg, argptr); + #else + vsnprintf(buf, 2000, msg, argptr); + #endif + va_end (argptr); + m_ErrorMsg = buf; + m_ErrorFunc = ""; + m_ErrorFix = ""; + m_ErrorExtra = ""; + OutputMessage (); +} + + +void CError::PrintErr ( std::string err ) +{ + // Registered error - NOT YET IMPLEMENTED + // CErrorMsg* msg = m_ +} + +void CError::PrintErrDX ( std::string err, int result ) +{ +// +// #ifdef BUILD_DX +// m_ErrorExtra = DXGetErrorString9 ( result ); +// #endif + OutputMessage (); + m_ErrorExtra = ""; +} + +void CError::PrintErrGL ( std::string err, int result ) +{ + OutputMessage (); + m_ErrorExtra = ""; +} + +void CError::PrintErrW ( std::string err, int result ) +{ + + OutputMessage (); + m_ErrorExtra = ""; +} + + +/* +void CError::GetErrorMessage ( ErrorDef::Errors err ) +{ + switch (err) { + //----------------------------------------------------- MATRIX Errors + case ErrorDef::MatrixIsNull: + m_strDescription = "Matrix data is null\n"; + m_strFunction = "Matrix::op()"; + m_strFix = ""; + break; + case ErrorDef::ColOutOfBounds: + m_strDescription = "Column index out of bounds\n"; + m_strFunction = "Matrix::op()"; + m_strFix = ""; + break; + case ErrorDef::RowOutOfBounds: + m_strDescription = "Row index out of bounds\n"; + m_strFunction = "Matrix::op()"; + m_strFix = ""; + break; + //----------------------------------------------------- WinDX Errors + case ErrorDef::DXInitFail: + m_strDescription = "Initialization of DirectX failed."; + m_strFunction = "GameX::InitDirect3D"; + m_strFix = "Reinstall DirectX 9.0. Confirm DirectX hardware support."; + break; + case ErrorDef::DXCannotGetMode: + m_strDescription = "Cannot get current display mode."; + m_strFunction = "GameX::SysGetCurrentMode"; + m_strFix = ""; + break; + case ErrorDef::DXCannotSetMode: + m_strDescription = "Cannot select display mode."; + m_strFunction = "GameX::SysSelectMode"; + m_strFix = "Try requesting a different display mode and options."; + break; + case ErrorDef::WinCannotCreateClass: + m_strDescription = "Cannot create Windows class."; + m_strFunction = "GameX::SysCreateWindowsClass"; + m_strFix = "Close other applications. Restart system."; + break; + case ErrorDef::WinCannotCreateWindow: + m_strDescription = "Cannot create Window."; + m_strFunction = "GameX::SysCreateWindow"; + m_strFix = "Try requesting a different display mode and options.\nClose other applications. Restart system. Possibly unsupported display hardware."; + break; + case ErrorDef::DXCannotCreateDevice: + m_strDescription = "Cannot create DirectX Device."; + m_strFunction = "GameX::SysCreateDevice3D"; + m_strFix = "Try requesting a different display mode and options."; + break; + case ErrorDef::DXCannotCreateDepthStencils: + m_strDescription = "Cannot create DirectX Depth Stencils."; + m_strFunction = "GameX::SysCreateDepthStencils"; + m_strFix = "Try requesting a different display mode and options."; + break; + //---------------------------------------------------------------- File Errors + case ErrorDef::CannotAppendAndRead: + m_strDescription = "Cannot open a file in both APPEND and READ mode."; + m_strFunction = "File::Open"; + m_strFix = "Use either APPEND, READ or WRITE when opening file."; + break; + case ErrorDef::CannotAppendAndWrite: + m_strDescription = "Cannot open a file in both APPEND and WRITE mode."; + m_strFunction = "File::Open"; + m_strFix = "Use either APPEND, READ or WRITE when opening file."; + break; + case ErrorDef::FileNotFound: + m_strDescription = "File not found."; + m_strFunction = "File::Open"; + m_strFix = "Use AUTOCREATE if you would like to create a new file."; + break; + case ErrorDef::LeaveEofOnlyOnAppend: + m_strDescription = "Warning:LEAVEEOF flag can only be used in APPEND mode."; + m_strFunction = "File::Open"; + m_strFix = "Remove the LEAVEEOF flag or open file in APPEND mode."; + break; + case ErrorDef::NoModeSpecified: + m_strDescription = "No open mode specified."; + m_strFunction = "File::Open"; + m_strFix = "You must specify READ, WRITE or APPEND to open a file."; + break; + case ErrorDef::NoNotOpenCmd: + m_strDescription = "NOTOPEN cannot be used as an open file flag."; + m_strFunction = "File::Open"; + m_strFix = "Remove the NOTOPEN flag."; + break; + case ErrorDef::NoSeqAndRandom: + m_strDescription = "Cannot open file in both SEQUENTIAL and RANDOM access modes."; + m_strFunction = "File::Open"; + m_strFix = "Choose either SEQUENTIAL or RANDOM mode to open file in."; + break; + case ErrorDef::CannotCreateFont: + m_strDescription = "Cannot create default font."; + m_strFunction = "RenderDX::Initialize"; + m_strFix = "DirectX fonts are not supported for some reason."; + break; + case ErrorDef::CannotCreateSprite: + m_strDescription = "Cannot create default sprite."; + m_strFunction = "RenderDX::Initialize"; + m_strFix = "DirectX sprites are not supported for some reason."; + break; + case ErrorDef::CannotAddImage: + m_strDescription = "Cannot create image on video memory."; + m_strFunction = "RenderDX::AddImage"; + m_strFix = "DirectX was unable to create hardware texture for the image."; + break; + case ErrorDef::CannotUpdateImage: + m_strDescription = "Cannot update image data on video memory."; + m_strFunction = "RenderDX::UpdateImage"; + m_strFix = "DirectX was unable to modify hardware texture for the image."; + break; + case ErrorDef::CannotOpenFile: + #if defined(BUILD_VSNET) + m_strDescription = strerror( errno ); + #else + m_strDescription = ""; // should replace with Mac general error code + #endif + m_strFunction = "File::Open"; + m_strFix = ""; + break; + case ErrorDef::ImageLoadError: + m_strDescription = "Unable to load image."; + m_strFunction = "ImageX::Load"; + m_strFix = ""; + break; + default: + char msg[500]; + sprintf (msg, "%d", (int) err ); + m_strDescription = "Undefined error: "; + m_strDescription += msg; + m_strSubsystem = "Undefined error."; + m_strFix = "Error must be given a description and fix message."; + break; + }; +} +*/ + + + +#ifdef MEMORY_DEBUG + + // User-defined operator new. + void *operator new( size_t stSize ) + { + void* pvMem = malloc( stSize ); + debug.Printf ( "NEW %p (%d bytes)\n", pvMem, stSize ); + return pvMem; + } + + // User-defined operator delete. + void operator delete( void *pvMem ) + { + debug.Printf ( "DELETE %p\n", pvMem ); + free ( pvMem ); + } +#endif \ No newline at end of file diff --git a/Extras/sph/common/mdebug.h b/Extras/sph/common/mdebug.h new file mode 100644 index 0000000..9c07993 --- /dev/null +++ b/Extras/sph/common/mdebug.h @@ -0,0 +1,138 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 INC_MINT_DEBUG_H + #define INC_MINT_DEBUG_H + + #include + #include + #include + #include + + + + #ifdef BUILD_VS2005 + // #pragma warning( disable : 4101) // removes warning 4101 - unreferenced local + // #pragma warning( disable : 4244) // removes warning 4244 - conversion loss of data + #pragma warning( disable : 4995) // removes warning 4995 - depricated function + #pragma warning( disable : 4996) // removes warning 4996 - depricated function + // #pragma warning( disable : 4018) // removes warning 4018 - unsigned/signed + #endif + + class CDebug { + public: + CDebug (); + ~CDebug (); + + // Control functions + void Start (); + void Stop (); + void SendToConsole ( bool tf ); + void SendToSysbox ( bool tf ); + void SendToFile ( bool tf ); + void SendToFile ( char *filename ); + + // Output functions + void Exit ( int code ); + void Print ( std::string subsys, std::string msg ); + void Print ( std::string msg ); + void Print ( char* msg); + void PrintF ( std::string subsys, char *msg, ... ); + void Printf ( char *msg, ... ); + void PrintErr ( std::string errid, std::string subsys, std::string msg, std::string sysbox ); // Used by Error class + + // Filtering functions + void AddFilter ( std::string subsys ); + void ClearFilters (); + + private: + bool m_bStarted; + bool m_bToFile; + bool m_bToCons; + bool m_bToSysbox; + std::string m_OutName; + FILE* m_OutFile; + FILE* m_OutCons; + + std::map< std::string, bool > m_Filters; + }; + + class CErrorMsg { + std::string m_strSubsys; + std::string m_strFunction; + std::string m_strMessage; + std::string m_strFix; + std::string m_strExtraInfo; + bool m_bFatal; + bool m_bFilter; + }; + + class CError { + public: + CError (); + + void Start (); + void Start ( char* fname ); + void LoadErrors (); + void OutputMessage (); + void Exit () { Exit (EXIT_SUCCESS); } + void Exit ( int code ); + + // Unregistered errors + void Print ( std::string subsys, std::string msg ); + void Print ( std::string msg ); + void Print ( char* msg); + void PrintF ( std::string subsys, char *msg, ... ); + + // Registered errors + void PrintErr ( std::string err ); + void PrintErrDX ( std::string err, int result ); // for DirectX errors + void PrintErrGL ( std::string err, int result ); // for OpenGL errors + void PrintErrW ( std::string err, int result ); // for Windows errors + + std::string GetErrorSubsys () { return m_ErrorID; } + std::string GetErrorMessage () { return m_ErrorMsg; } + std::string GetErrorFunction () { return m_ErrorFunc; } + std::string GetErrorFix () { return m_ErrorFix; } + std::string GetErrorExtra () { return m_ErrorExtra; } + + private: + + bool m_bStarted; + + std::string m_ErrorID; // Current error + std::string m_ErrorSubsys; + std::string m_ErrorMsg; + std::string m_ErrorFunc; + std::string m_ErrorFix; + std::string m_ErrorExtra; + bool m_bFatal; + + std::map < std::string, CErrorMsg* > m_Errors; // List of registered errors + }; + + + + extern CError error; + extern CDebug debug; +#endif + diff --git a/Extras/sph/common/mesh.cpp b/Extras/sph/common/mesh.cpp new file mode 100644 index 0000000..af3849c --- /dev/null +++ b/Extras/sph/common/mesh.cpp @@ -0,0 +1,955 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 +#include +#include "mesh.h" +#include "mdebug.h" +//#include "mfile.h" + +//#include "event.h" + +#include + +#define DEGtoRAD (3.141592/180.0) + +bool Mesh::mbInitStatic = false; +int Mesh::miBufSize[MAX_MFORMAT][MAX_BFORMAT]; + +Mesh::Mesh () +{ + debug.SendToConsole ( true ); + + m_Mform = MFormat::UDef; + m_CurrF = 0; + m_Vbuf = BUF_UNDEF; + m_Ebuf = BUF_UNDEF; + m_Fbuf = BUF_UNDEF; +} + +Mesh& Mesh::operator= ( Mesh& src ) +{ + CopyBuffers ( src ); + CopyAttributes ( src ); + m_Mform = src.GetMeshBufs ( m_Vbuf, m_Ebuf, m_Fbuf ); + return *this; +} + +void Mesh::InitStatic () +{ + mbInitStatic = true; + miBufSize[ (int) FVF ][ (int) BVert ] = sizeof ( VertFVF ); + miBufSize[ (int) FVF ][ (int) BFace ] = sizeof ( FaceFVF ); + miBufSize[ (int) FVF ][ (int) BEdge ] = 0; + miBufSize[ (int) CM ][ (int) BVert ] = sizeof ( VertCM ); + miBufSize[ (int) CM ][ (int) BEdge ] = sizeof ( EdgeCM ); + miBufSize[ (int) CM ][ (int) BFace ] = sizeof ( FaceCM ); + +} + +/*void Mesh::onUpdate ( objData dat, mint::Event* e ) +{ + uchar dtype; + hval num; + hval max; + long size; + ushort stride; + int num_buf; + + switch ( dat ) { + case 'full': + ClearBuffers (); + ClearAttributes (); + + m_Mform = (MFormat) e->getUChar (); + m_Vbuf = e->getUChar (); + m_Ebuf = e->getUChar (); + m_Fbuf = e->getUChar (); + num_buf = e->getInt (); + for (int b=0; b < num_buf; b++) { + dtype = e->getUChar (); + stride = e->getUShort (); + num = e->getInt (); + max = e->getInt (); + AddBuffer ( dtype, stride, max ); + e->getMem ( mBuf[b].data, num * mBuf[b].stride ); + mBuf[b].num = num; + } + + mHeapNum = e->getInt (); + mHeapMax = e->getInt (); + mHeapFree = e->getInt (); + mHeap = new hval[mHeapMax]; + e->getMem ( (char*) mHeap, mHeapNum * sizeof(hval) ); + break; + }; +} + +void Mesh::UpdateMesh () +{ + int s = GetSize () + (mBuf.size()+1)*4*sizeof(int); + mint::Event* e = updateStart ( 'full', s ); + + e->attachUChar ( (char) m_Mform ) ; + e->attachUChar ( (char) m_Vbuf ); + e->attachUChar ( (char) m_Ebuf ); + e->attachUChar ( (char) m_Fbuf ); + e->attachInt ( mBuf.size() ); + for (int b=0; b < mBuf.size(); b++) { + e->attachUChar ( mBuf[b].dtype ); + e->attachUShort ( mBuf[b].stride ); + e->attachInt ( mBuf[b].num ); + e->attachInt ( mBuf[b].max ); + e->attachMem ( mBuf[b].data, mBuf[b].num * mBuf[b].stride ); + } + e->attachInt ( mHeapNum ); + e->attachInt ( mHeapMax ); + e->attachInt ( mHeapFree ); + e->attachMem ( (char*) mHeap, mHeapNum * sizeof(hval) ); + + updateEnd ( e ); +} +*/ + +//------------------------------------------------------------------ FVF - Face-vertex-face Mesh +void Mesh::CreateFVF () +{ + if ( !mbInitStatic ) InitStatic (); + SetFuncFVF (); + + m_Mform = FVF; + m_Vbuf = AddBuffer ( (uchar) BVert, BufSize( FVF, BVert ), 64 ); + m_Fbuf = AddBuffer ( (uchar) BFace, BufSize( FVF, BFace ), 64 ); + AddAttribute ( m_Vbuf, "pos", sizeof ( AttrPos ), false ); + AddAttribute ( m_Vbuf, "norm", sizeof ( AttrNorm ) ); + + AddHeap ( 128 ); +} + +void Mesh::ClearFVF () +{ + ResetBuffer ( 0, mBuf[0].max ); + ResetBuffer ( 1, mBuf[0].max ); + + ResetHeap (); +} + +void Mesh::SmoothFVF ( int iter ) +{ + Vector3DF norm, side; + int cnt; + FaceFVF* f; + VertFVF *v1, *v2, *v3; + AttrPos* face_pos; + face_pos = new AttrPos[ NumFace() ]; + + for (int j=0; j < iter; j++) { + // Compute centroid of all faces + for (int n=0; n < NumFace(); n++) { + f = GetFaceFVF ( n ); + v1 = GetVertFVF(f->v1); v2 = GetVertFVF(f->v2); v3 = GetVertFVF(f->v3); + face_pos[n].x = ( v1->x + v2->x + v3->x ) / 3.0; + face_pos[n].y = ( v1->y + v2->y + v3->y ) / 3.0; + face_pos[n].z = ( v1->z + v2->z + v3->z ) / 3.0; + } + // Compute new vertex positions + int cnt; + Vector3DF vec; + for (int n=0; n < NumVert(); n++) { + v1 = GetVertFVF ( n ); + vec.Set (0,0,0); + hval* fptr = mHeap + v1->flist.pos; + for (int j=0; j < v1->flist.cnt; j++) { + vec.x += face_pos[ (*fptr) ].x; + vec.y += face_pos[ (*fptr) ].y; + vec.z += face_pos[ (*fptr) ].z; + fptr++; + } + v1->x = vec.x / (float) v1->flist.cnt; + v1->y = vec.y / (float) v1->flist.cnt; + v1->z = vec.z / (float) v1->flist.cnt; + } + } + delete face_pos; +} + +void Mesh::SetNormalFVF ( int n, Vector3DF norm ) +{ + VertFVF* v1; + AttrNorm* vn; + int noff = GetAttrOffset ( "norm" ); + v1 = GetVertFVF ( n ); + vn = (AttrNorm* ) ((char*) v1 + noff ); + vn->nx = norm.x; + vn->ny = norm.y; + vn->nz = norm.z; +} + + +void Mesh::SetColorFVF ( int n, DWORD clr ) +{ + VertFVF* v1; + AttrClr* vc; + int coff = GetAttrOffset ( "color" ); + if ( coff == -1 ) return; + v1 = GetVertFVF ( n ); + vc = (AttrClr* ) ((char*) v1 + coff ); + vc->clr = clr; +} +void Mesh::ComputeNormalsFVF () +{ + Vector3DF norm, side; + FaceFVF* f; + VertFVF *v1, *v2, *v3, *v4; + AttrNorm* vn; + AttrNorm* face_norms; + face_norms = new AttrNorm[ NumFace() ]; + + // Clear vertex normals + int noff = GetAttrOffset ( "norm" ); + for (int n=0; n < NumVert(); n++) { + v1 = GetVertFVF ( n ); + vn = (AttrNorm*) ((char*) v1 + noff); + vn->nx = 0; + vn->ny = 0; + vn->nz = 0; + } + + // Compute normals of all faces + for (int n=0; n < NumFace(); n++) { + f = GetFaceFVF ( n ); + v1 = GetVertFVF(f->v1); v2 = GetVertFVF(f->v2); v3 = GetVertFVF(f->v3); + side = Vector3DF ( v2->x, v2->y, v2->z ); + side -= Vector3DF ( v1->x, v1->y, v1->z ); + side.Normalize (); + norm = Vector3DF ( v3->x, v3->y, v3->z ); + norm -= Vector3DF ( v1->x, v1->y, v1->z ); + norm.Normalize (); + norm.Cross ( side ); + face_norms[n].nx = norm.x; + face_norms[n].ny = norm.y; + face_norms[n].nz = norm.z; + vn = (AttrNorm*) ((char*) v1 + noff); vn->nx += norm.x; vn->ny += norm.y; vn->nz += norm.z; + vn = (AttrNorm*) ((char*) v2 + noff); vn->nx += norm.x; vn->ny += norm.y; vn->nz += norm.z; + vn = (AttrNorm*) ((char*) v3 + noff); vn->nx += norm.x; vn->ny += norm.y; vn->nz += norm.z; + if ( f->v4 != -1 ) { + v4 = GetVertFVF(f->v4); + vn = (AttrNorm*) ((char*) v4 + noff); vn->nx += norm.x; vn->ny += norm.y; vn->nz += norm.z; + } + } + + // Normalize vertex normals + Vector3DF vec; + for (int n=0; n < NumVert(); n++) { + v1 = GetVertFVF ( n ); + vn = (AttrNorm*) ((char*) v1 + noff); + vec.Set ( vn->nx, vn->ny, vn->nz ); + vec.Normalize (); + vn->nx = vec.x; + vn->ny = vec.y; + vn->nz = vec.z; + } + + // Compute normal of a vertex from surrounding faces (slow method) + /*int cnt; + for (int n=0; n < NumVert(); n++) { + v1 = GetVertFVF ( n ); + vn = (VertNorm*) GetExtraFVF ( v1 ); + cnt = 0; + vn->nx = 0; vn->ny = 0; vn->nz = 0; + hval* fptr = mHeap + v1->flist.pos; + for (int j=0; j < v1->flist.cnt; j++) { + vn->nx += face_norms[ (*fptr) ].nx; + vn->ny += face_norms[ (*fptr) ].ny; + vn->nz += face_norms[ (*fptr) ].nz; + cnt++; + fptr++; + } + vn->nx /= (float) cnt; + vn->ny /= (float) cnt; + vn->nz /= (float) cnt; + }*/ + + delete face_norms; +} + +void Mesh::SetFuncFVF () +{ + m_AddVertFunc = &Mesh::AddVertFVF; + m_AddFaceFast3Func = &Mesh::AddFaceFast3FVF; + m_AddFaceFast4Func = &Mesh::AddFaceFast4FVF; +} + +xref Mesh::AddFaceFast3FVF ( xref v1, xref v2, xref v3 ) +{ + xref fNdx; + FaceFVF* f = (FaceFVF*) AddElem ( m_Fbuf, fNdx ); + f->v1 = v1; f->v2 = v2; f->v3 = v3; f->v4 = -1; + AddRef ( fNdx, GetVertFVF(v1)->flist, FACE_DELTA ); + AddRef ( fNdx, GetVertFVF(v2)->flist, FACE_DELTA ); + AddRef ( fNdx, GetVertFVF(v3)->flist, FACE_DELTA ); + return fNdx; +} +xref Mesh::AddFaceFast4FVF ( xref v1, xref v2, xref v3, xref v4 ) +{ + xref fNdx; + FaceFVF* f = (FaceFVF*) AddElem ( m_Fbuf, fNdx ); + f->v1 = v1; f->v2 = v2; f->v3 = v3; f->v4 = v4; + AddRef ( fNdx, GetVertFVF(v1)->flist, FACE_DELTA ); + AddRef ( fNdx, GetVertFVF(v2)->flist, FACE_DELTA ); + AddRef ( fNdx, GetVertFVF(v3)->flist, FACE_DELTA ); + AddRef ( fNdx, GetVertFVF(v4)->flist, FACE_DELTA ); + return fNdx; +} +xref Mesh::AddVertFVF ( float x, float y, float z ) +{ + xref ndx; + VertFVF* v = (VertFVF*) AddElem ( m_Vbuf, ndx ); + v->x = x; v->y = y; v->z = z; + ClearRefs ( v->flist ); + return ndx; +} + +void Mesh::DebugFVF () +{ + int n; + int j; + VertFVF* v; + FaceFVF* f; + debug.Printf ( "-- MESH --\n"); + + debug.Printf ( "-- verts\n" ); + for (n=0; n < NumVert(); n++) { + v = GetVertFVF(n); + debug.Printf ( "%d: (%2.1f,%2.1f,%2.1f) f:%d %d{", n, v->x, v->y, v->z, v->flist.cnt, v->flist.pos); + if ( v->flist.cnt > 0 ) { + for (j=0; j < v->flist.cnt; j++) + debug.Printf ( "%d ", *(mHeap+v->flist.pos+j) - FACE_DELTA ); + } + debug.Printf ( "}\n" ); + } + debug.Printf ( "-- faces\n" ); + for (n=0; n < NumFace(); n++) { + f = GetFaceFVF(n); + debug.Printf ( "%d: v:%d %d %d\n", n, f->v1, f->v2, f->v3); + } + + DebugHeap (); + + debug.Printf ("\n\n"); + //_getch(); +} + + +//------------------------------------------------------------------ CM - Connected Mesh +// Create Connected Mesh (CM) +void Mesh::CreateCM () +{ + if ( !mbInitStatic ) InitStatic (); + SetFuncCM (); + + m_Mform = CM; + m_Vbuf = AddBuffer ( (uchar) BVert, BufSize( CM, BVert ), 64 ); + m_Ebuf = AddBuffer ( (uchar) BEdge, BufSize ( CM, BEdge), 64 ); + m_Fbuf = AddBuffer ( (uchar) BFace, BufSize ( CM, BFace), 64 ); + AddAttribute ( m_Vbuf, "pos", sizeof(AttrPos), false ); + AddAttribute ( m_Vbuf, "norm", sizeof(AttrNorm) ); + + AddHeap ( 128 ); +} + +void Mesh::SetFuncCM () +{ + m_AddVertFunc = &Mesh::AddVertCM; + m_AddFaceFast3Func = &Mesh::AddFaceFast3CM; + m_AddFaceFast4Func = &Mesh::AddFaceFast4CM; +} + + +xref Mesh::AddVertCM ( float x, float y, float z ) +{ + xref ndx; + VertCM* v = (VertCM*) AddElem ( m_Vbuf, ndx ); + v->x = x; v->y = y; v->z = z; + ClearRefs ( v->elist ); + ClearRefs ( v->flist ); + return ndx; +} + +xref Mesh::AddFaceFast3CM ( xref v1, xref v2, xref v3 ) +{ + xref fNdx; + FaceCM* f = (FaceCM*) AddElem ( m_Fbuf, fNdx ); + f->v1 = v1; f->v2 = v2; f->v3 = v3; f->v4 = -1; + xref eNdx; + eNdx = AddEdgeCM ( f->v1, f->v2 ); f->e1 = eNdx; + eNdx = AddEdgeCM ( f->v2, f->v3 ); f->e2 = eNdx; + eNdx = AddEdgeCM ( f->v3, f->v1 ); f->e3 = eNdx; + AddRef ( fNdx, GetVertCM(v1)->flist, FACE_DELTA ); + AddRef ( fNdx, GetVertCM(v2)->flist, FACE_DELTA ); + AddRef ( fNdx, GetVertCM(v3)->flist, FACE_DELTA ); + return fNdx; +} +xref Mesh::AddFaceFast4CM ( xref v1, xref v2, xref v3, xref v4 ) +{ + xref fNdx; + FaceCM* f = (FaceCM*) AddElem ( m_Fbuf, fNdx ); + f->v1 = v1; f->v2 = v2; f->v3 = v3; f->v4 = v4; + xref eNdx; + eNdx = AddEdgeCM ( f->v1, f->v2 ); f->e1 = eNdx; + eNdx = AddEdgeCM ( f->v2, f->v3 ); f->e2 = eNdx; + eNdx = AddEdgeCM ( f->v3, f->v4 ); f->e3 = eNdx; + eNdx = AddEdgeCM ( f->v4, f->v1 ); f->e4 = eNdx; + AddRef ( fNdx, GetVertCM(v1)->flist, FACE_DELTA ); + AddRef ( fNdx, GetVertCM(v2)->flist, FACE_DELTA ); + AddRef ( fNdx, GetVertCM(v3)->flist, FACE_DELTA ); + AddRef ( fNdx, GetVertCM(v4)->flist, FACE_DELTA ); + return fNdx; +} + +xref Mesh::FindEdgeCM ( xref v1, xref v2 ) +{ + EdgeCM *pE; + VertCM *pV1; + pV1 = GetVertCM(v1); + if ( pV1->elist.cnt == 0 ) return -1; + hval* e = mHeap + pV1->elist.pos; + #ifdef MESH_DEBUG + for (int n=0; n < pV1->elist.cnt; n++) { + pE = GetEdgeCM( (*e)-EDGE_DELTA ); + if ( pE->v1 == v2 || pE->v2 == v2 ) return (*e)-EDGE_DELTA; + e++; + } + #else + for (int n=0; n < pV1->elist.cnt; n++) { + pE = GetEdgeCM( *e ); + if ( pE->v1 == v2 || pE->v2 == v2 ) return *e; + e++; + } + #endif + return -1; +} + +xref Mesh::AddEdgeCM ( xref v1, xref v2 ) +{ + xref eNdx = FindEdgeCM ( v1, v2 ); + EdgeCM* e = GetEdgeCM(eNdx); + if ( eNdx == -1 ) { + e = (EdgeCM*) AddElem ( m_Ebuf, eNdx ); + e->f1 = 0; + e->f2 = 0; + e->v1 = v1; + e->v2 = v2; + AddRef ( eNdx, GetVertCM(v1)->elist, EDGE_DELTA ); + AddRef ( eNdx, GetVertCM(v2)->elist, EDGE_DELTA ); + } + return eNdx; +} + +void Mesh::DebugCM () +{ + int n; + int j; + VertCM* v; + EdgeCM* e; + FaceCM* f; + debug.Printf ( "-- MESH --\n"); + + debug.Printf ( "-- verts\n" ); + for (n=0; n < NumVert(); n++) { + v = GetVertCM(n); + debug.Printf ( "%d: (%2.1f,%2.1f,%2.1f) e:%d %d{", n, v->x, v->y, v->z, v->elist.cnt, v->elist.pos); + if ( v->elist.cnt > 0 ) { + for (j=0; j < v->elist.cnt; j++) + debug.Printf ( "%d ", *(mHeap+v->elist.pos+j) - EDGE_DELTA ); + } + debug.Printf ( "}, f:%d %d{", v->flist.cnt, v->flist.pos); + if ( v->flist.cnt > 0 ) { + for (j=0; j < v->flist.cnt; j++) + debug.Printf ( "%d ", *(mHeap+v->flist.pos+j) - FACE_DELTA ); + } + debug.Printf ( "}\n" ); + } + + debug.Printf ( "-- edges\n" ); + for (n=0; n < NumEdge(); n++) { + e = GetEdgeCM (n); + debug.Printf ( "%d: v:%d %d, f:%d %d\n", n, e->v1, e->v2, e->f1, e->f2 ); + } + + debug.Printf ( "-- faces\n" ); + for (n=0; n < NumFace(); n++) { + f = GetFaceCM(n); + debug.Printf ( "%d: v:%d %d %d, e:%d %d %d\n", n, f->v1, f->v2, f->v3, f->e1, f->e2, f->e3 ); + } + + + hval* pVal = mHeap; + debug.Printf ( "-- heap (size: %d, max: %d, free: %04d)\n", mHeapNum, mHeapMax, mHeapFree ); + for (n=0; n < mHeapNum; n++) { + if ( (n % 8) == 0 ) debug.Printf ( "\n[%04d] ", n ); + #ifdef MESH_DEBUG + if ( *pVal == 0 ) { + debug.Printf ( "00000 "); + } else if ( *pVal == (hval) 0xFFFF ) { + debug.Printf ( "----- "); + } else if ( *pVal >= VERT_DELTA && *pVal < EDGE_DELTA ) { + debug.Printf ( "v%04d ", *pVal - VERT_DELTA ); + } else if ( *pVal >= EDGE_DELTA && *pVal < FACE_DELTA ) { + debug.Printf ( "e%04d ", *pVal - EDGE_DELTA ); + } else if ( *pVal >= FACE_DELTA ) { + debug.Printf ( "f%04d ", *pVal - FACE_DELTA ); + } else { + debug.Printf ( "H%04d ", (int) *pVal ); + } + #else + debug.Printf ( "%05d ", (int) *pVal ); + #endif + pVal++; + } + + debug.Printf ("\n\n"); + //_getch(); +} + +void Mesh::DebugHeap () +{ + hval* pVal = mHeap; + debug.Printf ( "-- heap (size: %d, max: %d, free: %04d)\n", mHeapNum, mHeapMax, mHeapFree ); + for (int n=0; n < mHeapNum; n++) { + if ( (n % 8) == 0 ) debug.Printf ( "\n[%04d] ", n ); + #ifdef MESH_DEBUG + if ( *pVal == 0 ) { + debug.Printf ( "00000 "); + } else if ( *pVal == (hval) 0xFFFF ) { + debug.Printf ( "----- "); + } else if ( *pVal >= VERT_DELTA && *pVal < EDGE_DELTA ) { + debug.Printf ( "v%04d ", *pVal - VERT_DELTA ); + } else if ( *pVal >= EDGE_DELTA && *pVal < FACE_DELTA ) { + debug.Printf ( "e%04d ", *pVal - EDGE_DELTA ); + } else if ( *pVal >= FACE_DELTA ) { + debug.Printf ( "f%04d ", *pVal - FACE_DELTA ); + } else { + debug.Printf ( "H%04d ", (int) *pVal ); + } + #else + debug.Printf ( "%05d ", (int) *pVal ); + #endif + pVal++; + } +} + +void Mesh::DrawVertsCM ( float* viewmat, int a, int b ) +{ + VertCM* v; + + glColor3f (1,0,0); + glLoadMatrixf ( viewmat ); + glTranslatef ( mT.x, mT.y, mT.z ); + glBegin ( GL_POINTS ); + for (int n = a; n <= b; n++) { + v = GetVertCM (n); + glVertex3f ( v->x, v->y, v->z ); + //glCallList ( m_GLObj ); + } + glEnd (); +} + +void Mesh::DrawVertsFVF ( float* viewmat, int a, int b ) +{ + VertFVF* v; + glColor3f (1,0,0); + glLoadMatrixf ( viewmat ); + glTranslatef ( mT.x, mT.y, mT.z ); + glBegin ( GL_POINTS ); + for (int n = a; n <= b; n++) { + v = GetVertFVF (n); + glVertex3f ( v->x, v->y, v->z ); + //glCallList ( m_GLObj ); + } + glEnd (); +} + +void Mesh::DrawFacesCM ( float* viewmat, int a, int b ) +{ + FaceCM* f; + VertCM* v; + AttrNorm* vn; + int noff = GetAttrOffset ( "norm" ); + glLoadMatrixf ( viewmat ); + glTranslatef ( mT.x, mT.y, mT.z ); + GLenum dm = GL_TRIANGLES; + glBegin ( dm ); + f = GetFaceCM ( a ); + for (int n = a; n <= b; n++) { + if ( f->v4 == -1 ) { + if ( dm != GL_TRIANGLES ) { glEnd (); glBegin ( GL_TRIANGLES ); dm = GL_TRIANGLES; } + v = GetVertCM(f->v1); vn = (AttrNorm*) ((char*) v + noff); + glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z ); + v = GetVertCM(f->v2); vn = (AttrNorm*) ((char*) v + noff); + glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z ); + v = GetVertCM(f->v3); vn = (AttrNorm*) ((char*) v + noff); + glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z ); + } else { + if ( dm != GL_QUADS ) { glEnd (); glBegin ( GL_QUADS ); dm = GL_QUADS; } + v = GetVertCM(f->v1); vn = (AttrNorm*) ((char*) v + noff); + glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z ); + v = GetVertCM(f->v2); vn = (AttrNorm*) ((char*) v + noff); + glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z ); + v = GetVertCM(f->v3); vn = (AttrNorm*) ((char*) v + noff); + glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z ); + v = GetVertCM(f->v4); vn = (AttrNorm*) ((char*) v + noff); + glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z ); + } + f++; + } + glEnd (); +} + +void Mesh::DrawFacesFVF ( float* viewmat, int a, int b ) +{ + FaceFVF* f; + VertFVF* v; + AttrNorm* vn; + AttrClr* vc; + int noff = GetAttrOffset ( "norm" ); + int coff = GetAttrOffset ( "color" ); + coff = -1; + + //glLoadMatrixf ( viewmat ); + //glTranslatef ( mT.x, mT.y, mT.z ); + GLenum dm = GL_TRIANGLES; + glBegin ( dm ); + f = GetFaceFVF ( a ); + for (int n = a; n <= b; n++) { + if ( f->v4 == -1 ) { + if ( dm != GL_TRIANGLES ) { glEnd (); glBegin ( GL_TRIANGLES ); dm = GL_TRIANGLES; } + v = GetVertFVF(f->v1); vn = (AttrNorm*) ((char*) v + noff); vc = (AttrClr*) ((char*) v +coff); + if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) ); + glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z ); + + v = GetVertFVF(f->v2); vn = (AttrNorm*) ((char*) v + noff); vc = (AttrClr*) ((char*) v +coff); + if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) ); + glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z ); + + v = GetVertFVF(f->v3); vn = (AttrNorm*) ((char*) v + noff); vc = (AttrClr*) ((char*) v +coff); + if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) ); + glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z ); + } else { + if ( dm != GL_QUADS ) { glEnd (); glBegin ( GL_QUADS ); dm = GL_QUADS; } + v = GetVertFVF(f->v1); vn = (AttrNorm*) ((char*) v + noff); vc = (AttrClr*) ((char*) v +coff); + if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) ); + glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z ); + + v = GetVertFVF(f->v2); vn = (AttrNorm*) ((char*) v + noff); vc = (AttrClr*) ((char*) v +coff); + if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) ); + glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z ); + + v = GetVertFVF(f->v3); vn = (AttrNorm*) ((char*) v + noff); vc = (AttrClr*) ((char*) v +coff); + if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) ); + glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z ); + + v = GetVertFVF(f->v4); vn = (AttrNorm*) ((char*) v + noff); vc = (AttrClr*) ((char*) v +coff); + if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) ); + glNormal3f ( vn->nx, vn->ny, vn->nz ); glVertex3f ( v->x, v->y, v->z ); + } + f++; + } + glEnd (); +} + +void Mesh::DrawEdgesCM ( float* viewmat, int a, int b ) +{ + EdgeCM* e; + + glLoadMatrixf ( viewmat ); + glTranslatef ( mT.x, mT.y, mT.z ); + glBegin ( GL_LINES ); + e = GetEdgeCM ( a ); + for (int n = a; n <= b; n++) { + glVertex3f ( GetVertCM(e->v1)->x, GetVertCM(e->v1)->y, GetVertCM(e->v1)->z ); + glVertex3f ( GetVertCM(e->v2)->x, GetVertCM(e->v2)->y, GetVertCM(e->v2)->z ); + e++; + } + glEnd (); +} + +void Mesh::DrawGL ( float* viewmat ) +{ + mT.Set(0,0,0); + + switch ( m_Mform ) { + case CM: { + glDepthRange (0.001, 1.001); + //glColor3f ( 1, 0, 0 ); DrawVertsCM ( viewmat, 0, NumVert()-1 ); + glColor3f ( .6, .6, .6 ); DrawFacesCM ( viewmat, 0, NumFace()-1 ); + //glDepthRange (0.0005, 1.0005); + //glColor3f ( 1, 1, 1); DrawEdgesCM ( viewmat, 0, NumEdge()-1 ); + } break; + case FVF: { + //glColor3f (1,0,0); DrawVertsFVF ( viewmat, 0, NumVert()-1 ); + //glEnable (GL_LIGHTING); + + glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL ); + glColor4f ( .9, .9, .9, 0.75 ); DrawFacesFVF ( viewmat, 0, NumFace()-1 ); + + /*glDisable (GL_LIGHTING ); + glDepthRange (0.000, 1.00); + glPolygonMode ( GL_FRONT_AND_BACK, GL_LINE ); + glLineWidth ( 3 ); + glColor4f ( 0, 0, 0, 1.0 ); DrawFacesFVF ( viewmat, 0, NumFace()-1 ); + glEnable ( GL_LIGHTING ); + + glLineWidth ( 1); + + glDepthRange (0.0, 1.0); + glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL );*/ + + } break; + } +} + +void Mesh::DrawFaceGL ( float* viewmat ) +{ + mT.Set (0,0,0); + if ( m_CurrF < 0 ) m_CurrF = NumFace()-1; + if ( m_CurrF >= NumFace() ) m_CurrF = 0; + + switch ( m_Mform ) { + case FVF: + glDepthRange (0.0, 1.0); glColor3f (1.0, 1.0, 1.0 ); + DrawFacesFVF ( viewmat, m_CurrF, m_CurrF ); + break; + case CM: + glDepthRange (0.0, 1.0); glColor3f (1.0, 1.0, 1.0 ); + DrawFacesCM ( viewmat, m_CurrF, m_CurrF ); + break; + }; +} + +void Mesh::Measure () +{ + hval* pCurr = mHeap + mHeapFree; + int vs, es, fs, hs, hm, as, frees = 0; + vs = NumVert(); if ( vs !=0 ) vs *= GetStride(m_Vbuf); + es = NumEdge(); if ( es !=0 ) es *= GetStride(m_Ebuf); + fs = NumFace(); if ( fs !=0 ) fs *= GetStride(m_Fbuf); + hs = mHeapNum*sizeof(hval); + hm = mHeapMax*sizeof(hval); + + while ( pCurr != mHeap-1 ) { + frees += *(pCurr); + pCurr = mHeap + * (hpos*) (pCurr + FPOS); + } + frees *= sizeof(hval); + as = 0; + if ( m_Vbuf!=-1 ) as += mBuf[m_Vbuf].max * GetStride(m_Vbuf); + if ( m_Fbuf!=-1 ) as += mBuf[m_Fbuf].max * GetStride(m_Fbuf); + if ( m_Ebuf!=-1 ) as += mBuf[m_Ebuf].max * GetStride(m_Ebuf); + as += hm; + + debug.Printf ( "NumVert: %07.1fk (%d)\n", vs/1000.0, NumVert() ); + debug.Printf ( "NumFace: %07.1fk (%d)\n", fs/1000.0, NumFace() ); + debug.Printf ( "NumEdge: %07.1fk (%d)\n", es/1000.0, NumEdge() ); + debug.Printf ( "Heap Size: %07.1fk (%d)\n", hs/1000.0, mHeapNum ); + debug.Printf ( "Free Size: %07.1fk\n", frees/1000.0 ); + debug.Printf ( "Heap Used: %07.1fk (%5.1f%%)\n", (hs-frees)/1000.0, (hs-frees)*100.0/(vs+es+fs+hs-frees) ); + debug.Printf ( "Heap Max: %07.1fk\n", hm/1000.0 ); + debug.Printf ( "Total Used: %07.1fk\n", (vs+es+fs+hs-frees)/1000.0 ); + debug.Printf ( "Total Alloc: %07.1fk\n", as/1000.0 ); + debug.Printf ( "Fragmentation: %f%%\n", (hm-(hs-frees))*100.0 / hm ); +} + + +/*int Mesh::GetIndex ( int b, void* v ) +{ + if ( v == 0x0 ) return -1; + return ((char*) v - (char*) mBuf[b].data) / mBuf[b].stride; +}*/ + +int Mesh::FindPlyElem ( char typ ) +{ + for (int n=0; n < m_Ply.size(); n++) { + if ( m_Ply[n]->type == typ ) return n; + } + return -1; +} + +int Mesh::FindPlyProp ( int elem, std::string name ) +{ + for (int n=0; n < m_Ply[elem]->prop_list.size(); n++) { + if ( m_Ply[elem]->prop_list[n].name.compare ( name)==0 ) + return n; + } + return -1; +} + +void Mesh::LoadPly ( char* fname, float s ) +{ +/* int m_PlyCnt; + float m_PlyData[40]; + char buf[1000]; + char bword[1000]; + std::string word; + Buffer b(1000); + int vnum, fnum, elem, cnt; + char typ; + + if ( m_Mform == MFormat::UDef ) + CreateFVF (); + + m_File.Open ( fname, FILE_READ | FILE_SEQUENTIAL ); + if ( !m_File.Valid() ) { + error.PrintF ( "mesh", "Could not find file: %s\n", fname ); + error.Exit (); + } + + // Read header + m_File.ReadLine ( buf, 1000 ); + b.ReadWord ( buf, bword ); word = bword; + if ( word.compare("ply" )!=0 ) { + error.PrintF ( "Not a ply file. %s\n", fname ); + error.Exit (); + } + + debug.Printf ( "Reading PLY.\n" ); + while ( m_File.ReadLine ( buf, 1000 ) == FILE_STATUS_OK ) { + b.ReadWord ( buf, bword ); + word = bword; + if ( word.compare("comment" )!=0 ) { + if ( word.compare("end_header")==0 ) break; + if ( word.compare("property")==0 ) { + b.ReadWord ( buf, bword ); + word = bword; + if ( word.compare("float")==0 ) typ = PLY_FLOAT; + if ( word.compare("float16")==0 ) typ = PLY_FLOAT; + if ( word.compare("float32")==0 ) typ = PLY_FLOAT; + if ( word.compare("int8")==0 ) typ = PLY_INT; + if ( word.compare("uint8")==0 ) typ = PLY_UINT; + if ( word.compare("list")==0) { + typ = PLY_LIST; + b.ReadWord ( buf, bword ); + b.ReadWord ( buf, bword ); + } + b.ReadWord ( buf, bword ); + word = bword; + AddPlyProperty ( typ, word ); + } + if ( word.compare("element" )==0 ) { + b.ReadWord ( buf, bword); word = bword; + if ( word.compare("vertex")==0 ) { + b.ReadWord ( buf, bword); + vnum = atoi ( bword ); + debug.Printf ( " Verts: %d\n", vnum ); + AddPlyElement ( PLY_VERTS, vnum ); + } + if ( word.compare("face")==0 ) { + b.ReadWord ( buf, bword); + fnum = atoi ( bword ); + debug.Printf ( " Faces: %d\n", fnum ); + AddPlyElement ( PLY_FACES, fnum ); + } + } + } + } + + // Read data + int xi, yi, zi; + debug.Printf ( " Reading verts..\n" ); + elem = FindPlyElem ( PLY_VERTS ); + xi = FindPlyProp ( elem, "x" ); + yi = FindPlyProp ( elem, "y" ); + zi = FindPlyProp ( elem, "z" ); + if ( elem == -1 || xi == -1 || yi == -1 || zi == -1 ) { + debug.Printf ( "ERROR: Vertex data not found.\n" ); + exit(-1); + } + for (int n=0; n < m_Ply[elem]->num; n++) { + m_File.ReadLine ( buf, 1000 ); + for (int j=0; j < m_Ply[elem]->prop_list.size(); j++) { + b.ReadWord ( buf, bword ); + m_PlyData[ j ] = atof ( bword ); + } + AddVert ( m_PlyData[xi]*s, m_PlyData[zi]*s, m_PlyData[yi]*s ); + } + + debug.Printf ( " Reading faces..\n" ); + elem = FindPlyElem ( PLY_FACES ); + xi = FindPlyProp ( elem, "vertex_indices" ); + if ( elem == -1 || xi == -1 ) { + debug.Printf ( "ERROR: Face data not found.\n" ); + exit(-1); + } + for (int n=0; n < m_Ply[elem]->num; n++) { + m_File.ReadLine ( buf, 1000 ); + m_PlyCnt = 0; + for (int j=0; j < m_Ply[elem]->prop_list.size(); j++) { + if ( m_Ply[elem]->prop_list[j].type == PLY_LIST ) { + b.ReadWord ( buf, bword ); + cnt = atoi ( bword ); + m_PlyData[ m_PlyCnt++ ] = cnt; + for (int c =0; c < cnt; c++) { + b.ReadWord ( buf, bword ); + m_PlyData[ m_PlyCnt++ ] = atof ( bword ); + } + } else { + b.ReadWord ( buf, bword ); + m_PlyData[ m_PlyCnt++ ] = atof ( bword ); + } + } + if ( m_PlyData[xi] == 3 ) { + //debug.Printf ( " Face: %d, %d, %d\n", (int) m_PlyData[xi+1], (int) m_PlyData[xi+2], (int) m_PlyData[xi+3] ); + AddFaceFast ( (int) m_PlyData[xi+1], (int) m_PlyData[xi+2], (int) m_PlyData[xi+3] ); + } + + if ( m_PlyData[xi] == 4 ) { + //debug.Printf ( " Face: %d, %d, %d, %d\n", (int) m_PlyData[xi+1], (int) m_PlyData[xi+2], (int) m_PlyData[xi+3], (int) m_PlyData[xi+4]); + AddFaceFast ( (int) m_PlyData[xi+1], (int) m_PlyData[xi+2], (int) m_PlyData[xi+3], (int) m_PlyData[xi+4] ); + } + } + + Measure (); + ComputeNormalsFVF (); // !-- should be abstracted +*/ + + // UpdateMesh (); +} + +void Mesh::AddPlyElement ( char typ, int n ) +{ + debug.Printf ( " Element: %d, %d\n", typ, n ); + PlyElement* p = new PlyElement; + p->num = n; + p->type = typ; + p->prop_list.clear (); + m_PlyCurrElem = m_Ply.size(); + m_Ply.push_back ( p ); +} + +void Mesh::AddPlyProperty ( char typ, std::string name ) +{ + debug.Printf ( " Property: %d, %s\n", typ, name.c_str() ); + PlyProperty p; + p.name = name; + p.type = typ; + m_Ply [ m_PlyCurrElem ]->prop_list.push_back ( p ); +} \ No newline at end of file diff --git a/Extras/sph/common/mesh.h b/Extras/sph/common/mesh.h new file mode 100644 index 0000000..71032f9 --- /dev/null +++ b/Extras/sph/common/mesh.h @@ -0,0 +1,160 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 DEF_MESH + #define DEF_MESH + + #include + #include + + #include "geomx.h" + #include "mesh_info.h" + #include "vector.h" + + //#include "mfile.h" + + //#define MESH_DEBUG + + #ifdef MESH_DEBUG + #define VERT_DELTA 10000 + #define EDGE_DELTA 20000 + #define FACE_DELTA 30000 + #else + #define VERT_DELTA 0 + #define EDGE_DELTA 0 + #define FACE_DELTA 0 + #endif + + #define PLY_UINT 0 + #define PLY_INT 1 + #define PLY_FLOAT 2 + #define PLY_LIST 3 + #define PLY_VERTS 4 + #define PLY_FACES 5 + + struct PlyProperty { + char type; + std::string name; + }; + struct PlyElement { + int num; + char type; // 0 = vert, 1 = face + std::vector prop_list; + }; + + class Mesh : public GeomX, public MeshInfo { + public: + Mesh (); + + //virtual objType GetType () { return 'mesh'; } + + // Distributed functions + //virtual void onUpdate ( objData dat, mint::Event* e ); + //void UpdateMesh (); + + // Generic functions + void InitStatic (); + void DrawGL ( float* viewmat ); + void DrawFaceGL ( float* viewmat ); + void Measure (); + Mesh& operator= ( Mesh& op2 ); + + // Load PLY mesh + void LoadPly ( char* fname, float s ); + void AddPlyElement ( char typ, int n ); + void AddPlyProperty ( char typ, std::string name ); + void LoadPlyVerts (); + void LoadPlyFaces (); + int FindPlyElem ( char typ ); + int FindPlyProp ( int elem, std::string name ); + + // Vertex, Face, Edge functions + xref AddVert (float x, float y, float z ) { return (this->*m_AddVertFunc) (x, y, z); } + xref AddFaceFast (xref v1, xref v2, xref v3 ) { return (this->*m_AddFaceFast3Func) (v1, v2, v3); } + xref AddFaceFast (xref v1, xref v2, xref v3, xref v4 ) { return (this->*m_AddFaceFast4Func) (v1, v2, v3, v4); } + xref (Mesh::*m_AddVertFunc) (float x, float y, float z); + xref (Mesh::*m_AddFaceFast3Func) (xref v1, xref v2, xref v3); + xref (Mesh::*m_AddFaceFast4Func) (xref v1, xref v2, xref v3, xref v4); + + int NumVert () { return NumElem ( m_Vbuf ); } + int NumEdge () { return NumElem ( m_Ebuf ); } + int NumFace () { return NumElem ( m_Fbuf ); } + + void IncFace ( int n ) { m_CurrF += n; } + void DebugHeap (); + + // FVF - Face-Vertex-Face Mesh + void CreateFVF (); + void ClearFVF (); + void SetFuncFVF (); + xref AddVertFVF ( float x, float y, float z ); + xref AddFaceFast3FVF ( xref v1, xref v2, xref v3 ); + xref AddFaceFast4FVF ( xref v1, xref v2, xref v3, xref v4 ); + VertFVF* GetVertFVF ( int n ) { return (VertFVF*) (mBuf[m_Vbuf].data + n*mBuf[m_Vbuf].stride); } + FaceFVF* GetFaceFVF ( int n ) { return (FaceFVF*) (mBuf[m_Fbuf].data + n*mBuf[m_Fbuf].stride); } + void* GetExtraFVF ( VertFVF* v ) { return ((char*) v + miBufSize[(int) FVF][BVert]); } + void ComputeNormalsFVF (); + void SetNormalFVF ( int n, Vector3DF norm ); + void SetColorFVF ( int n, DWORD clr ); + void SmoothFVF ( int iter ); + void DebugFVF (); + void DrawVertsFVF ( float* viewmat, int a, int b ); + void DrawFacesFVF ( float* viewmat, int a, int b ); + + // CM - Connected Mesh + void CreateCM (); + void SetFuncCM (); + xref AddVertCM ( float x, float y, float z ); + xref AddFaceFast3CM ( xref v1, xref v2, xref v3 ); + xref AddFaceFast4CM ( xref v1, xref v2, xref v3, xref v4 ); + xref AddEdgeCM ( xref v1, xref v2 ); + xref FindEdgeCM ( xref v1, xref v2 ); + VertCM* GetVertCM ( int n ) { return (VertCM*) (mBuf[m_Vbuf].data + n*mBuf[m_Vbuf].stride); } + EdgeCM* GetEdgeCM ( int n ) { return (EdgeCM*) (mBuf[m_Ebuf].data + n*mBuf[m_Ebuf].stride); } + FaceCM* GetFaceCM ( int n ) { return (FaceCM*) (mBuf[m_Fbuf].data + n*mBuf[m_Fbuf].stride); } + void* GetExtraCM ( VertCM* v ) { return ((char*) v + miBufSize[(int) CM][BVert] ); } + void DebugCM (); + void DrawVertsCM ( float* viewmat, int a, int b ); + void DrawFacesCM ( float* viewmat, int a, int b ); + void DrawEdgesCM ( float* viewmat, int a, int b ); + + MFormat GetMeshBufs ( char& v, char& e, char& f ) { v = m_Vbuf; e = m_Ebuf; f = m_Fbuf; return m_Mform; } + + protected: + MFormat m_Mform; // Mesh format + char m_Vbuf; + char m_Ebuf; + char m_Fbuf; + + int m_CurrF; + + std::vector< PlyElement* > m_Ply; + //File m_File; + int m_PlyCurrElem; + + static bool mbInitStatic; + + Vector3DF mT; + }; + +#endif + diff --git a/Extras/sph/common/mesh_info.h b/Extras/sph/common/mesh_info.h new file mode 100644 index 0000000..745709a --- /dev/null +++ b/Extras/sph/common/mesh_info.h @@ -0,0 +1,97 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 DEF_MESH_INFO + #define DEF_MESH_INFO + + #include "common_defs.h" + //#include "mint_config.h" + typedef signed int xref; + + #define MAX_MFORMAT 10 + #define MAX_BFORMAT 5 + + // CM - Connected mesh + struct FaceCM { + xref e1, e2, e3, e4; + xref v1, v2, v3, v4; + }; + struct EdgeCM { + xref v1, v2; + xref f1, f2; + }; + struct VertCM { + hList elist; + hList flist; + float x, y, z; + }; + // FVF - Face-vertex-face mesh + struct FaceFVF { + xref v1, v2, v3, v4; + }; + struct VertFVF { + hList flist; + float x, y, z; + }; + + // Extra attributes + struct AttrPos { + float x, y, z; + }; + struct AttrClr { + DWORD clr; + }; + struct AttrNorm { + float nx, ny, nz; + }; + struct AttrTex { + float tu, tv; + }; + + class MeshInfo { + public: + enum MFormat { // Mesh format + UDef = 0, + VV = 1, // Vertex-Vertex + FV = 2, // Face-Vertex + FVF = 3, + WE = 4, // Winged-Edge + CM = 5 // Connected-Mesh + }; + enum BFormat { // Buffer format + BVert = 0, + BEdge = 1, + BFace = 2, + }; + enum AFormat { // Extra Attribute formats + APos = 0, + AClr = 1, + ANorm = 2, + ATex = 3 + }; + static int BufSize ( MFormat m, BFormat b ) { return miBufSize[(int) m][(int) b]; } + static int miBufSize [MAX_MFORMAT][MAX_BFORMAT]; + }; + +#endif + + diff --git a/Extras/sph/common/mtime.cpp b/Extras/sph/common/mtime.cpp new file mode 100644 index 0000000..90a562c --- /dev/null +++ b/Extras/sph/common/mtime.cpp @@ -0,0 +1,612 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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. +*/ + +#ifdef _MSC_VER + #include +#else + #include +#endif + +#include +#include +#include + +#include "mtime.h" +#include "mdebug.h" + +#ifdef _MSC_VER + #define VS2005 + #pragma comment ( lib, "winmm.lib" ) + LARGE_INTEGER m_BaseCount; + LARGE_INTEGER m_BaseFreq; +#endif + +using namespace mint; + +const int Time::m_DaysInMonth[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +bool Time::m_Started = false; +sjtime m_BaseTime; +sjtime m_BaseTicks; + +void mint::start_timing ( sjtime base ) +{ + m_BaseTime = base; + + #ifdef _MSC_VER + m_BaseTicks = timeGetTime(); + QueryPerformanceCounter ( &m_BaseCount ); + QueryPerformanceFrequency ( &m_BaseFreq ); + #else + struct timeval tv; + gettimeofday(&tv, NULL); + m_BaseTicks = ((sjtime) tv.tv_sec * 1000000LL) + (sjtime) tv.tv_usec; + #endif +} + +void Time::SetSystemTime ( int accuracy ) +{ + switch ( accuracy ) { + case ACC_SEC: // 1 second accuracy + SetSystemTime (); + break; + case ACC_MSEC: { // 1 millisecond accuracy + #ifdef _MSC_VER + m_CurrTime = m_BaseTime + sjtime(timeGetTime() - m_BaseTicks)*MSEC_SCALAR; + #else + struct timeval tv; + gettimeofday(&tv, NULL); + sjtime t = ((sjtime) tv.tv_sec * 1000000LL) + (sjtime) tv.tv_usec; + m_CurrTime = m_BaseTime + ( t - m_BaseTicks) * 1000LL; // 1000LL - converts microseconds to milliseconds + #endif + } break; + case ACC_NSEC: { // 1 nanosecond accuracy + #ifdef _MSC_VER + LARGE_INTEGER currCount; + QueryPerformanceCounter ( &currCount ); + m_CurrTime = m_BaseTime + sjtime( (double(currCount.QuadPart-m_BaseCount.QuadPart) / m_BaseFreq.QuadPart) * SEC_SCALAR); + #else + debug.Printf ( "mtime", "ERROR: ACC_NSEC NOT IMPLEMENTED for Time::SetSystemTime\n" ); + #endif + } break; + } +} + + +Time::Time () +{ + if ( !m_Started ) { + m_Started = true; + SetSystemTime (); // Get base time from wall clock + start_timing ( m_CurrTime ); // Start timing from base time + } + m_CurrTime = 0; +} + +// Note regarding hours: +// 0 <= hr <= 23 +// hr = 0 is midnight (12 am) +// hr = 1 is 1 am +// hr = 12 is noon +// hr = 13 is 1 pm (subtract 12) +// hr = 23 is 11 pm (subtact 12) + +// GetScaledJulianTime +// Returns -1.0 if the time specified is invalid. +sjtime Time::GetScaledJulianTime ( int hr, int min, int m, int d, int y, int s, int ms, int ns ) +{ + double MJD; // Modified Julian Date (JD - 2400000.5) + sjtime SJT; // Scaled Julian Time SJT = MJD * 86400000 + UT + + // Check if date/time is valid + if (m <=0 || m > 12) return (sjtime) -1; + if ( y % 4 == 0 && m == 2) { // leap year in february + if (d <=0 || d > m_DaysInMonth[m]+1) return (sjtime) -1; + } else { + if (d <=0 || d > m_DaysInMonth[m]) return (sjtime) -1; + } + if (hr < 0 || hr > 23) return (sjtime) -1; + if (min < 0 || min > 59) return (sjtime) -1; + + // Compute Modified Julian Date + MJD = 367 * y - int ( 7 * (y + int (( m + 9)/12)) / 4 ); + MJD -= int ( 3 * (int((y + (m - 9)/7)/100) + 1) / 4); + MJD += int ( 275 * m / 9 ) + d + 1721028.5 - 1.0; + MJD -= 2400000.5; + // Compute Scaled Julian Time + SJT = sjtime(MJD) * sjtime( DAY_SCALAR ); + SJT += hr * HR_SCALAR + min * MIN_SCALAR + s * SEC_SCALAR + ms * MSEC_SCALAR + ns * NSEC_SCALAR; + return SJT; +} + +sjtime Time::GetScaledJulianTime ( int hr, int min, int m, int d, int y ) +{ + return GetScaledJulianTime ( hr, min, m, d, y, 0, 0, 0 ); +} + +void Time::GetTime ( sjtime SJT, int& hr, int& min, int& m, int& d, int& y) +{ + int s = 0, ms = 0, ns = 0; + GetTime ( SJT, hr, min, m, d, y, s, ms, ns ); +} + +void Time::GetTime ( sjtime SJT, int& hr, int& min, int& m, int& d, int& y, int& s, int &ms, int& ns) +{ + // Compute Universal Time from SJT + sjtime UT = sjtime( SJT % sjtime( DAY_SCALAR ) ); + + // Compute Modified Julian Date from SJT + double MJD = double(SJT / DAY_SCALAR); + + // Use MJD to get Month, Day, Year + double z = floor ( MJD + 1 + 2400000.5 - 1721118.5); + double g = z - 0.25; + double a = floor ( g / 36524.25 ); + double b = a - floor ( a / 4.0 ); + y = int( floor (( b + g ) / 365.25 ) ); + double c = b + z - floor ( 365.25 * y ); + m = int (( 5 * c + 456) / 153 ); + d = int( c - int (( 153 * m - 457) / 5) ); + if (m > 12) { + y++; + m -= 12; + } + // Use UT to get Hrs, Mins, Secs, Msecs + hr = int( UT / HR_SCALAR ); + UT -= hr * HR_SCALAR; + min = int( UT / MIN_SCALAR ); + UT -= min * MIN_SCALAR; + s = int ( UT / SEC_SCALAR ); + UT -= s * SEC_SCALAR; + ms = int ( UT / MSEC_SCALAR ); + UT -= ms * MSEC_SCALAR; + ns = int ( UT / NSEC_SCALAR ); + + // UT Example: + // MSEC_SCALAR = 1 + // SEC_SCALAR = 1,000 + // MIN_SCALAR = 60,000 + // HR_SCALAR = 3,600,000 + // DAY_SCALAR = 86,400,000 + // + // 7:14:03, 32 msec + // UT = 7*3,600,000 + 14*60,000 + 3*1,000 + 32 = 26,043,032 + // + // 26,043,032 / 3,600,000 = 7 26,043,032 - (7 * 3,600,000) = 843,032 + // 843,032 / 60,000 = 14 843,032 - (14 * 60,000) = 3,032 + // 3,032 / 1,000 = 3 3,032 - (3 * 1,000) = 32 + // 32 / 1 = 32 +} + +void Time::GetTime (int& s, int& ms, int& ns ) +{ + int hr, min, m, d, y; + GetTime ( m_CurrTime, hr, min, m, d, y, s, ms, ns ); +} + + +void Time::GetTime (int& hr, int& min, int& m, int& d, int& y) +{ + GetTime ( m_CurrTime, hr, min, m, d, y); +} + +void Time::GetTime (int& hr, int& min, int& m, int& d, int& y, int& s, int& ms, int& ns) +{ + GetTime ( m_CurrTime, hr, min, m, d, y, s, ms, ns); +} + +bool Time::SetTime ( int sec ) +{ + int hr, min, m, d, y; + GetTime ( m_CurrTime, hr, min, m, d, y ); + m_CurrTime = GetScaledJulianTime ( hr, min, m, d, y, sec, 0, 0 ); + return true; +} + +bool Time::SetTime ( int sec, int msec ) +{ + int hr, min, m, d, y; + GetTime ( m_CurrTime, hr, min, m, d, y ); + m_CurrTime = GetScaledJulianTime ( hr, min, m, d, y, sec, msec, 0 ); + return true; +} + +bool Time::SetTime (int hr, int min, int m, int d, int y) +{ + int s, ms, ns; + GetTime ( s, ms, ns ); + m_CurrTime = GetScaledJulianTime ( hr, min, m, d, y, s, ms, ns ); + if (m_CurrTime == -1.0) return false; + return true; +} + +bool Time::SetTime (int hr, int min, int m, int d, int y, int s, int ms, int ns) +{ + m_CurrTime = GetScaledJulianTime ( hr, min, m, d, y, s, ms, ns ); + if (m_CurrTime == -1.0) return false; + return true; +} + +bool Time::SetTime ( std::string line ) +{ + int hr, min, m, d, y; + std::string dat; + if ( line.substr ( 0, 1 ) == " " ) + dat = line.substr ( 1, line.length()-1 ).c_str(); + else + dat = line; + + hr = atoi ( dat.substr ( 0, 2).c_str() ); + min = atoi ( dat.substr ( 3, 2).c_str() ); + m = atoi ( dat.substr ( 6, 2).c_str () ); + d = atoi ( dat.substr ( 9, 2).c_str () ); + y = atoi ( dat.substr ( 12, 4).c_str () ); + return SetTime ( hr, min, m, d, y); +} + +bool Time::SetDate ( std::string line ) +{ + int hr, min, m, d, y; + std::string dat; + if ( line.substr ( 0, 1 ) == " " ) + dat = line.substr ( 1, line.length()-1 ).c_str(); + else + dat = line; + + hr = 0; + min = 0; + m = atoi ( dat.substr ( 0, 2).c_str () ); + d = atoi ( dat.substr ( 3, 2).c_str () ); + y = atoi ( dat.substr ( 6, 4).c_str () ); + return SetTime ( hr, min, m, d, y); +} + +std::string Time::GetDayOfWeekName () +{ + switch (GetDayOfWeek()) { + case 1: return "Sunday"; break; + case 2: return "Monday"; break; + case 3: return "Tuesday"; break; + case 4: return "Wednesday"; break; + case 5: return "Thursday"; break; + case 6: return "Friday"; break; + case 7: return "Saturday"; break; + } + return "day error"; +} + +int Time::GetDayOfWeek () +{ + // Compute Modified Julian Date + double MJD = (double) m_CurrTime / sjtime( DAY_SCALAR ); + + // Compute Julian Date + double JD = floor ( MJD + 1 + 2400000.5 ); + int dow = (int(JD - 0.5) % 7) + 4; + if (dow > 7) dow -= 7; + + // day of week (1 = sunday, 7 = saturday) + return dow ; +} + +int Time::GetWeekOfYear () +{ + int hr, min, m, d, y; + GetTime ( hr, min, m, d, y ); + double mjd_start = (double) GetScaledJulianTime ( 0, 0, 1, 1, y ) / DAY_SCALAR; // mjt for jan 1st of year + double mjd_curr = (double) GetScaledJulianTime ( 0, 0, m, d, y ) / DAY_SCALAR; // mjt for specified day in year + double JD = floor ( mjd_start + 1 + 2400000.5 ); + int dow = (int ( JD - 0.5 ) % 7) + 4; // day of week for jan 1st of year. + if (dow > 7) dow -= 7; + + // week of year (first week in january = week 0) + return int((mjd_curr - mjd_start + dow -1 ) / 7 ); +} + +int Time::GetElapsedDays ( Time& base ) +{ + return int( sjtime(m_CurrTime - base.GetSJT() ) / sjtime( DAY_SCALAR ) ); +} + +int Time::GetElapsedWeeks ( Time& base ) +{ + return GetElapsedDays(base) / 7; +} + +int Time::GetElapsedMonths ( Time& base) +{ + return int ( double(GetElapsedDays(base)) / 30.416 ); +} + +int Time::GetElapsedYears ( Time& base ) +{ + // It is much easier to compute this in m/d/y format rather + // than using julian dates. + int bhr, bmin, bm, bd, by; + int ehr, emin, em, ed, ey; + GetTime ( base.GetSJT(), bhr, bmin, bm, bd, by ); + GetTime ( m_CurrTime, ehr, emin, em, ed, ey ); + if ( em < bm) { + // earlier month + return ey - by - 1; + } else if ( em > bm) { + // later month + return ey - by; + } else { + // same month + if ( ed < bd ) { + // earlier day + return ey - by - 1; + } else if ( ed >= bd ) { + // later or same day + return ey - by; + } + } + return -1; +} + +int Time::GetFracDay ( Time& base ) +{ + // Resolution = 5-mins + return int( sjtime(m_CurrTime - base.GetSJT() ) % sjtime(DAY_SCALAR) ) / (MIN_SCALAR*5); +} + +int Time::GetFracWeek ( Time& base ) +{ + // Resolution = 1 hr + int day = GetElapsedDays(base) % 7; // day in week + int hrs = int( sjtime(m_CurrTime - base.GetSJT() ) % sjtime(DAY_SCALAR) ) / (HR_SCALAR); + return day * 24 + hrs; +} + +int Time::GetFracMonth ( Time& base ) +{ + // Resolution = 4 hrs + int day = (int) fmod ( double(GetElapsedDays(base)), 30.416 ); // day in month + int hrs = int( sjtime(m_CurrTime - base.GetSJT() ) % sjtime(DAY_SCALAR) ) / (HR_SCALAR*4); + return day * (24 / 4) + hrs; +} + +int Time::GetFracYear ( Time& base ) +{ + // It is much easier to compute this in m/d/y format rather + // than using julian dates. + int bhr, bmin, bm, bd, by; + int ehr, emin, em, ed, ey; + sjtime LastFullYear; + GetTime ( base.GetSJT() , bhr, bmin, bm, bd, by ); + GetTime ( m_CurrTime, ehr, emin, em, ed, ey ); + if ( em < bm) { + // earlier month + LastFullYear = GetScaledJulianTime ( ehr, emin, bm, bd, ey - 1); + return int( sjtime(m_CurrTime - LastFullYear) / sjtime(DAY_SCALAR) ); + } else if ( em > bm) { + // later month + LastFullYear = GetScaledJulianTime ( ehr, emin, bm, bd, ey); + return int( sjtime(m_CurrTime - LastFullYear) / sjtime(DAY_SCALAR) ); + } else { + // same month + if ( ed < bd ) { + // earlier day + LastFullYear = GetScaledJulianTime ( ehr, emin, bm, bd, ey - 1); + return int( sjtime(m_CurrTime - LastFullYear) / sjtime(DAY_SCALAR) ); + } else if ( ed > bd ) { + // later day + LastFullYear = GetScaledJulianTime ( ehr, emin, bm, bd, ey); + return int( sjtime(m_CurrTime - LastFullYear) / sjtime(DAY_SCALAR) ); + } else { + return 0; // same day + } + } +} + +std::string Time::GetReadableDate () +{ + char buf[200]; + std::string line; + int hr, min, m, d, y; + + GetTime ( hr, min, m, d, y ); + sprintf ( buf, "%02d:%02d %02d-%02d-%04d", hr, min, m, d, y); + return std::string ( buf ); +} + +std::string Time::GetReadableTime () +{ + char buf[200]; + std::string line; + int hr, min, m, d, y, s, ms, ns; + + GetTime ( hr, min, m, d, y, s, ms, ns ); + sprintf ( buf, "%02d:%02d:%02d %03d.%06d %02d-%02d-%04d", hr, min, s, ms, ns, m, d, y); + return std::string ( buf ); +} + +std::string Time::GetReadableSJT () +{ + char buf[200]; + sprintf ( buf, "%I64d", m_CurrTime ); + return std::string ( buf ); +} + +std::string Time::GetReadableTime ( int fmt ) +{ + char buf[200]; + int hr, min, m, d, y, s, ms, ns; + GetTime ( hr, min, m, d, y, s, ms, ns ); + + switch (fmt) { + case 0: sprintf ( buf, "%02d %03d.%06d", s, ms, ns); + } + return std::string ( buf ); +} + +void Time::SetSystemTime () +{ + int hr, mn, sec, m, d, y; + char timebuf[100]; + char datebuf[100]; + std::string line; + + #ifdef _MSC_VER + #ifdef VS2005 + _strtime_s ( timebuf, 100 ); + _strdate_s ( datebuf, 100 ); + #else + _strtime ( timebuf ); + _strdate ( datebuf ); + #endif + #endif + #if (defined(__linux__) || defined(__CYGWIN__)) + time_t tt; + struct tm tim; + tt = time(NULL); + localtime_r(&tt, &tim); + sprintf( timebuf, "%02i:%02i:%02i", tim.tm_hour, tim.tm_min, tim.tm_sec); + sprintf( datebuf, "%02i:%02i:%02i", tim.tm_mon, tim.tm_mday, tim.tm_year % 100); + #endif + + line = timebuf; + hr = atoi ( line.substr ( 0, 2).c_str() ); + mn = atoi ( line.substr ( 3, 2).c_str() ); + sec = atoi ( line.substr ( 6, 2).c_str() ); + line = datebuf; + m = atoi ( line.substr ( 0, 2).c_str() ); + d = atoi ( line.substr ( 3, 2).c_str() ); + y = atoi ( line.substr ( 6, 2).c_str() ); + + // NOTE: This only works from 1930 to 2030 + if ( y > 30) y += 1900; + else y += 2000; + + SetTime ( hr, mn, m, d, y, sec, 0, 0); +} + + +double Time::GetSec () +{ + return ((double) m_CurrTime / (double) SEC_SCALAR ); +} + +int Time::GetMSec () +{ + return ((double) m_CurrTime / (double) MSEC_SCALAR ); + + /*int s, ms, ns; + GetTime ( s, ms, ns ); + return ms;*/ +} + +void Time::Advance ( Time& t ) +{ + m_CurrTime += t.GetSJT (); +} + +void Time::AdvanceMinutes ( int n) +{ + m_CurrTime += (sjtime) MIN_SCALAR * n; +} + +void Time::AdvanceHours ( int n ) +{ + m_CurrTime += (sjtime) HR_SCALAR * n; +} + +void Time::AdvanceDays ( int n ) +{ + m_CurrTime += (sjtime) DAY_SCALAR * n; +} + +void Time::AdvanceSec ( int n ) +{ + m_CurrTime += (sjtime) SEC_SCALAR * n; +} + +void Time::AdvanceMins ( int n) +{ + m_CurrTime += (sjtime) MIN_SCALAR * n; +} + +void Time::AdvanceMSec ( int n ) +{ + m_CurrTime += (sjtime) MSEC_SCALAR * n; +} + +Time& Time::operator= ( const Time& op ) { m_CurrTime = op.m_CurrTime; return *this; } +Time& Time::operator= ( Time& op ) { m_CurrTime = op.m_CurrTime; return *this; } +bool Time::operator< ( const Time& op ) { return (m_CurrTime < op.m_CurrTime); } +bool Time::operator> ( const Time& op ) { return (m_CurrTime > op.m_CurrTime); } +bool Time::operator< ( Time& op ) { return (m_CurrTime < op.m_CurrTime); } +bool Time::operator> ( Time& op ) { return (m_CurrTime > op.m_CurrTime); } + +bool Time::operator<= ( const Time& op ) { return (m_CurrTime <= op.m_CurrTime); } +bool Time::operator>= ( const Time& op ) { return (m_CurrTime >= op.m_CurrTime); } +bool Time::operator<= ( Time& op ) { return (m_CurrTime <= op.m_CurrTime); } +bool Time::operator>= ( Time& op ) { return (m_CurrTime >= op.m_CurrTime); } + +Time Time::operator- ( Time& op ) +{ + return Time( m_CurrTime - op.GetSJT() ); +} +Time Time::operator+ ( Time& op ) +{ + return Time( m_CurrTime + op.GetSJT() ); +} + +bool Time::operator== ( const Time& op ) +{ + return (m_CurrTime == op.m_CurrTime); +} +bool Time::operator!= ( Time& op ) +{ + return (m_CurrTime != op.m_CurrTime); +} + +void Time::RegressionTest () +{ + // This code verifies the Julian Date calculations are correct for all + // minutes over a range of years. Useful to debug type issues when + // compiling on different platforms. + // + int m, d, y, hr, min; + int cm, cd, cy, chr, cmin; + + for (y=2000; y < 2080; y++) { + for (m=1; m <= 12; m++) { + for (d=1; d <= 31; d++) { + for (hr=0; hr<=23; hr++) { + for (min=0; min<=59; min++) { + if ( SetTime ( hr, min, m, d, y, 0, 0, 0 ) ) { + GetTime ( chr, cmin, cm, cd, cy ); + if ( hr!=chr || min!=cmin || m!=cm || d!=cd || y!=cy) { +// debug.Printf (" time", "Error: %d, %d, %d, %d, %d = %I64d\n", hr, min, m, d, y, GetSJT()); +// debug.Printf (" time", "-----: %d, %d, %d, %d, %d\n", chr, cmin, cm, cd, cy); + } + } + } + } + } + } +// debug.Printf (" time", "Verified: %d\n", y); + } +} + + diff --git a/Extras/sph/common/mtime.h b/Extras/sph/common/mtime.h new file mode 100644 index 0000000..2f8c1b6 --- /dev/null +++ b/Extras/sph/common/mtime.h @@ -0,0 +1,234 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 TIME_HPP + #define TIME_HPP + + #include + + #ifdef _MSC_VER + #include + typedef __int64 mstime; // microsecond time = 8 byte integer + typedef __int64 sjtime; // scaled julian times = 8 byte integer + + #define MSEC_SCALAR 1000000i64 + #define SEC_SCALAR 1000000000i64 + #define MIN_SCALAR 60000000000i64 + #define HR_SCALAR 3600000000000i64 + #define DAY_SCALAR 86400000000000i64 + + #pragma warning ( disable : 4522 ) + #pragma warning ( disable : 4996 ) // sprintf warning + #endif + + #ifdef __linux__ + #include + typedef __s64 mstime; + typedef __s64 sjtime; + + #define MSEC_SCALAR 1000000LL + #define SEC_SCALAR 1000000000LL + #define MIN_SCALAR 60000000000LL + #define HR_SCALAR 3600000000000LL + #define DAY_SCALAR 86400000000000LL + #endif + + #ifdef __CYGWIN__ + #include // found in \cygwin\usr\include\w32api + typedef __int64 mstime; + typedef __int64 sjtime; + + #define MSEC_SCALAR 1000000LL + #define SEC_SCALAR 1000000000LL + #define MIN_SCALAR 60000000000LL + #define HR_SCALAR 3600000000000LL + #define DAY_SCALAR 86400000000000LL + #endif + + #define ACC_SEC 0 + #define ACC_MSEC 1 + #define ACC_NSEC 2 + + #define NSEC_SCALAR 1 + + // Time Class + // R. Hoetzlein + // + // Overview: + // There is a need in many systems to represent both very small (nanoseconds) and + // very large (millenia) timescales accurately. Modified Julian Date accurate represents + // individual days over +/- about 30,000 yrs. However, MJD represents fractions of a day + // as a floating point fraction. This is inaccurate for any timing-critical applications. + // The Time class here uses an 8-byte (64 bit) integer called SJT, Scaled Julian Time. + // SJT = MJD * DAY_SCALAR + UT (nanoseconds). + // SJT is the Modified Julian Date scaled by a integer factor, and added to Universal Time + // represented in nanoseconds. + // + // Features: + // - Accurately represents individual nanoseconds over +/- 30,000 yrs. + // - Correct rollover of tiny time scales on month, day, year boundaries. + // e.g. Set date/time to 11:59:59.9999, on Feb 28th, + // - Accurately gives day of the week for any date + // - Accurately compares two dates (days elapsed) even across leap-years. + // - Adjust sec/nsec independently from month/day/year (work at scale you desire) + // + // Implementation Notes: + // JD = Julian Day is the number of days elapsed since Jan 1, 4713 BC in the proleptic Julian calendar. + // http://en.wikipedia.org/wiki/Julian_day + // MJD = Modified Julian Date. Most modern dates, after 19th c., have Julian Date which are greater + // than 2400000.5. MJD is an offset. MJD = JD - 2400000.5 + // It shifts the epoch date (start date) to Nov 17, 1858. + // UT = Universal Time. This is the time of day in hours as measured from Greenwich England. + // For non-astronomic uses, this is: UT = Local Time + Time Zone. + // SJT = Scaled Julian Time = MJD * DAY_SCALAR + UT (in nanoseconds). + // + // Julian Dates (and their MJD and SJT equivalents) + // ------------ + // Jan 1, 4713 BC = JD 0 = MJD -2400000 = SJT + // Jan 1, 1500 AD = JD 2268933.5 = MJD -131067 = SJT + // Nov 16, 1858 AD = JD 2400000.5 = MJD 0 = SJT 0 + // Jan 1, 1960 AD = JD 2436935.5 = MJD 36935 = SJT 3,191,184,000,000 + // Jan 1, 2005 AD = JD 2453372.5 = MJD 53372 = SJT 4,611,340,800,000 + // Jan 1, 2100 AD = JD 2488070.5 = MJD 88070 = SJT 7,609,248,000,000 + // + // + // + // 32/64-Bit Integer Ranges + // 32-bit Integer Min: –2,147,483,648 ( 4 bytes ) + // 32-bit Integer Max: 2,147,483,647 + // SJT 2005: 4,611,340,800,000 + // 64-bit Integer Min: –9,223,372,036,854,775,808 + // 64-bit Integer Max: 9,223,372,036,854,775,807 ( 8 bytes ) + // + // SJT Range + // --------- + // * USING DAY_SCALAR = 86,400,000 (millisec accuracy) + // SJT Range = (+/-9,223,372,036,854,775,807 SJT / 86,400,000 DAY_SCALAR) + // SJT Range (in Julian Days) = +2400000.5 + (+/-106,751,991,167 MJD) + // SJT Range (in Julian Days) = +/- 292278883 years, with 1 millisecond accuracy. + // + // * USING DAY_SCALAR = 86,400,000,000,000 (nanosec accuracy) + // SJT Range = (+/-9,223,372,036,854,775,807 SJT / 86,400,000,000,000 DAY_SCALAR) + // SJT Range (in Julian Days) = +2400000.5 + (+/-106,751 MJD) + // SJT Range (in Julian Days) = 1566 AD to 2151 AD, with 1 nanosecond accuracy. + + namespace mint { + + class Time { + public: + Time (); + Time ( sjtime t ) { m_CurrTime = t; } + Time ( int sec, int msec ) { m_CurrTime = 0; SetTime ( sec, msec ); } + + // Set time + bool SetTime ( int sec ); // Set seconds + bool SetTime ( int sec, int msec ); // Set seconds, msecs + bool SetTime ( int hr, int min, int m, int d, int y); // Set hr/min, month, day, year + bool SetTime ( int hr, int min, int m, int d, int y, int s, int ms, int ns); // Set hr/min, month, day, year, sec, ms, ns + bool SetTime ( Time& t ) { m_CurrTime = t.GetSJT(); return true;} // Set to another Time object + bool SetTime ( std::string line ); // Set time from string (hr,min,sec) + bool SetDate ( std::string line ); // Set date from string (mo,day,yr) + void SetSystemTime (); // Set date/time to system clock + void SetSystemTime ( int accuracy ); // Set date/time to system clock + void SetSJT ( sjtime t ) { m_CurrTime = t ;} // Set Scaled Julian Time directly + + // Get time + void GetTime (int& sec, int& msec, int& nsec ); + void GetTime (int& hr, int& min, int& m, int& d, int& y); + void GetTime (int& hr, int& min, int& m, int& d, int& y, int& s, int& ms, int& ns); + double GetSec (); + int GetMSec (); + std::string GetReadableDate (); + std::string GetReadableTime (); + std::string GetReadableTime ( int fmt ); + std::string GetReadableSJT (); + std::string GetDayOfWeekName (); + sjtime GetSJT () { return m_CurrTime; } + + // Advance Time + void Advance ( Time& t ); + void AdvanceMinutes ( int n); + void AdvanceHours ( int n ); + void AdvanceDays ( int n ); + void AdvanceSec ( int n ); + void AdvanceMins ( int n); + void AdvanceMSec ( int n ); + + // Utility functions + // (these do the actual work, but should not be private as they may be useful to user) + sjtime GetScaledJulianTime ( int hr, int min, int m, int d, int y ); + sjtime GetScaledJulianTime ( int hr, int min, int m, int d, int y, int s, int ms, int ns ); + void GetTime ( sjtime t, int& hr, int& min, int& m, int& d, int& y); + void GetTime ( sjtime t, int& hr, int& min, int& m, int& d, int& y, int& s, int& ms, int& ns); + + // Get/Set Julian Date and Modified Julain Date + void SetJD ( double jd ); + void SetMJD ( int jd ); + double GetJD (); + int GetMJD (); + + // Time operators + Time& operator= ( const Time& op ); + Time& operator= ( Time& op ); + bool operator< ( const Time& op ); + bool operator< ( Time& op ); + bool operator> ( const Time& op ); + bool operator> ( Time& op ); + bool operator<= ( const Time& op ); + bool operator<= ( Time& op ); + bool operator>= ( const Time& op ); + bool operator>= ( Time& op ); + bool operator== ( const Time& op ); + bool operator!= ( Time& op ); + Time operator- ( Time& op ); + Time operator+ ( Time& op ); + + // Elapsed Times + int GetElapsedDays ( Time& base ); + int GetElapsedWeeks ( Time& base ); + int GetElapsedMonths ( Time& base ); + int GetElapsedYears ( Time& base ); + int GetFracDay ( Time& base ); // Return Unit = 5 mins + int GetFracWeek ( Time& base ); // Return Unit = 1 hr + int GetFracMonth ( Time& base ); // Return Unit = 4 hrs + int GetFracYear ( Time& base ); // Return Unit = 1 day + int GetDayOfWeek (); + int GetWeekOfYear (); + + void RegressionTest (); + + private: + static const int m_DaysInMonth[13]; + static bool m_Started; + + sjtime m_CurrTime; + }; + + // Used for precise system time (Win32) + void start_timing ( sjtime base ); + + } +#endif + + + diff --git a/Extras/sph/common/particle.cpp b/Extras/sph/common/particle.cpp new file mode 100644 index 0000000..0eca87b --- /dev/null +++ b/Extras/sph/common/particle.cpp @@ -0,0 +1,23 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 "particle.h" \ No newline at end of file diff --git a/Extras/sph/common/particle.h b/Extras/sph/common/particle.h new file mode 100644 index 0000000..06fdf5e --- /dev/null +++ b/Extras/sph/common/particle.h @@ -0,0 +1,29 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 DEF_PARTICLE + #define DEF_PARTICLE + + #include "vector.h" + + + +#endif diff --git a/Extras/sph/common/point_set.cpp b/Extras/sph/common/point_set.cpp new file mode 100644 index 0000000..d343cda --- /dev/null +++ b/Extras/sph/common/point_set.cpp @@ -0,0 +1,539 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 "gl_helper.h" + +#include "point_set.h" + +int PointSet::m_pcurr = -1; + +PointSet::PointSet () +{ + m_GridRes.Set ( 0, 0, 0 ); + m_pcurr = -1; + Reset (); +} + +int PointSet::GetGridCell ( int x, int y, int z ) +{ + return (int) ( (z*m_GridRes.y + y)*m_GridRes.x + x); +} + +Point* PointSet::firstGridParticle ( int gc, int& p ) +{ + m_pcurr = m_Grid [ gc ]; + if ( m_pcurr == -1 ) return 0x0; + p = m_pcurr; + return (Point*) (mBuf[0].data + m_pcurr * mBuf[0].stride); +} + +Point* PointSet::nextGridParticle ( int& p ) +{ + Point* pnt = 0x0; + if ( m_pcurr != -1 ) { + pnt = (Point*) (mBuf[0].data + m_pcurr * mBuf[0].stride); + p = m_pcurr; + m_pcurr = pnt->next; + } + return pnt; +} + +unsigned short* PointSet::getNeighborTable ( int n, int& cnt ) +{ + cnt = m_NC[n]; + if ( cnt == 0 ) return 0x0; + return &m_Neighbor[n][0]; +} + +float PointSet::GetValue ( float x, float y, float z ) +{ + float dx, dy, dz, dsq; + float sum; + int pndx; + Point* pcurr; + float R2 = 1.8*1.8; + + Grid_FindCells ( Vector3DF(x,y,z), m_GridCellsize/2.0 ); + + int cnt = 0; + sum = 0.0; + for (int cell=0; cell < 8; cell++ ) { + if ( m_GridCell[cell] != -1 ) { + pndx = m_Grid [ m_GridCell[cell] ]; + while ( pndx != -1 ) { + pcurr = (Point*) (mBuf[0].data + pndx*mBuf[0].stride); + dx = x - pcurr->pos.x; + dy = y - pcurr->pos.y; + dz = z - pcurr->pos.z; + dsq = dx*dx+dy*dy+dz*dz; + if ( dsq < R2 ) sum += R2 / dsq; + pndx = pcurr->next; + } + } + } + return sum; +} +Vector3DF PointSet::GetGradient ( float x, float y, float z ) +{ + Vector3DF norm; + float dx, dy, dz, dsq; + float sum; + int pndx; + Point* pcurr; + float R2 = (m_GridCellsize/2.0)*(m_GridCellsize/2.0); + + Grid_FindCells ( Vector3DF(x,y,z), m_GridCellsize/2.0 ); + + int cnt = 0; + sum = 0.0; + norm.Set (0,0,0); + for (int cell=0; cell < 8; cell++ ) { + if ( m_GridCell[cell] != -1 ) { + pndx = m_Grid [ m_GridCell[cell] ]; + while ( pndx != -1 ) { + pcurr = (Point*) (mBuf[0].data + pndx*mBuf[0].stride); + dx = x - pcurr->pos.x; + dy = y - pcurr->pos.y; + dz = z - pcurr->pos.z; + dsq = dx*dx+dy*dy+dz*dz; + if ( dsq > 0 && dsq < R2 ) { + dsq = 2.0*R2 / (dsq*dsq); + norm.x += dx * dsq; + norm.y += dy * dsq; + norm.z += dz * dsq; + } + pndx = pcurr->next; + } + } + } + norm.Normalize (); + return norm; +} + +DWORD PointSet::GetColor ( float x, float y, float z ) +{ + Vector3DF clr; + float dx, dy, dz, dsq; + float sum; + int pndx; + Point* pcurr; + float R2 = (m_GridCellsize/2.0)*(m_GridCellsize/2.0); + + Grid_FindCells ( Vector3DF(x,y,z), m_GridCellsize/2.0 ); + + int cnt = 0; + sum = 0.0; + clr.Set (0,0,0); + for (int cell=0; cell < 8; cell++ ) { + if ( m_GridCell[cell] != -1 ) { + pndx = m_Grid [ m_GridCell[cell] ]; + while ( pndx != -1 ) { + pcurr = (Point*) (mBuf[0].data + pndx*mBuf[0].stride); + dx = x - pcurr->pos.x; + dy = y - pcurr->pos.y; + dz = z - pcurr->pos.z; + dsq = dx*dx+dy*dy+dz*dz; + if ( dsq < R2 ) { + dsq = 2.0*R2 / (dsq*dsq); + clr.x += RED(pcurr->clr) * dsq; + clr.y += GRN(pcurr->clr) * dsq; + clr.z += BLUE(pcurr->clr) * dsq; + } + pndx = pcurr->next; + } + } + } + clr.Normalize (); + return COLORA(clr.x, clr.y, clr.z, 1.0); +} + +void PointSet::Reset () +{ + // Reset number of particles +// ResetBuffer ( 0 ); + + m_Time = 0; + m_DT = 0.1; + m_Param[POINT_GRAV] = 100.0; + m_Param[PLANE_GRAV] = 0.0; + + m_Vec[ POINT_GRAV_POS].Set(0,0,50.0); + m_Vec[ PLANE_GRAV_DIR].Set(0,0,-9.8); + m_Vec[ EMIT_RATE ].Set ( 1, 10, 0 ); + m_Vec[ EMIT_POS ].Set ( 50, 0, 35 ); + m_Vec[ EMIT_ANG ].Set ( 90, 45, 50.0 ); + m_Vec[ EMIT_DANG ].Set ( 0, 0, 0 ); + m_Vec[ EMIT_SPREAD ].Set ( 4, 4, 1 ); +} + +void PointSet::Initialize ( int mode, int total ) +{ + switch (mode) { + case BPOINT: { + FreeBuffers (); + AddBuffer ( BPOINT, sizeof ( Point ), total ); + AddAttribute ( 0, "pos", sizeof ( Vector3DF ), false ); + AddAttribute ( 0, "color", sizeof ( DWORD ), false ); + Reset (); + } break; + + case BPARTICLE: { + FreeBuffers (); + AddBuffer ( BPARTICLE, sizeof ( Particle ), total ); + AddAttribute ( 0, "pos", sizeof ( Vector3DF ), false ); + AddAttribute ( 0, "color", sizeof ( DWORD ), false ); + AddAttribute ( 0, "vel", sizeof ( Vector3DF ), false ); + AddAttribute ( 0, "ndx", sizeof ( unsigned short ), false ); + AddAttribute ( 0, "age", sizeof ( unsigned short ), false ); + Reset (); + } break; + } + + +} + +int PointSet::AddPoint () +{ + xref ndx; + AddElem ( 0, ndx ); + return ndx; +} + +int PointSet::AddPointReuse () +{ + xref ndx; + if ( NumPoints() < mBuf[0].max-1 ) + AddElem ( 0, ndx ); + else + RandomElem ( 0, ndx ); + return ndx; +} + +void PointSet::AddVolume ( Vector3DF min, Vector3DF max, float spacing ) +{ + Vector3DF pos; + Point* p; + float dx, dy, dz; + dx = max.x-min.x; + dy = max.y-min.y; + dz = max.z-min.z; + for (float z = max.z; z >= min.z; z -= spacing ) { + for (float y = min.y; y <= max.y; y += spacing ) { + for (float x = min.x; x <= max.x; x += spacing ) { + p = GetPoint ( AddPointReuse () ); + pos.Set ( x, y, z); + //pos.x += -0.05 + float( rand() * 0.1 ) / RAND_MAX; + //pos.y += -0.05 + float( rand() * 0.1 ) / RAND_MAX; + //pos.z += -0.05 + float( rand() * 0.1 ) / RAND_MAX; + p->pos = pos; + p->clr = COLORA( (x-min.x)/dx, (y-min.y)/dy, (z-min.z)/dz, 1); + } + } + } +} + +void PointSet::Draw ( float* view_mat, float rad ) +{ + char* dat; + Point* p; + glEnable ( GL_NORMALIZE ); + + if ( m_Param[PNT_DRAWMODE] == 0 ) { + glLoadMatrixf ( view_mat ); + dat = mBuf[0].data; + for (int n = 0; n < NumPoints(); n++) { + p = (Point*) dat; + glPushMatrix (); + glTranslatef ( p->pos.x, p->pos.y, p->pos.z ); + glScalef ( 0.2, 0.2, 0.2 ); + glColor4f ( RED(p->clr), GRN(p->clr), BLUE(p->clr), ALPH(p->clr) ); + drawSphere (); + glPopMatrix (); + dat += mBuf[0].stride; + } + } else if ( m_Param[PNT_DRAWMODE] == 1 ) { + glLoadMatrixf ( view_mat ); + dat = mBuf[0].data; + glBegin ( GL_POINTS ); + for (int n=0; n < NumPoints(); n++) { + p = (Point*) dat; + glColor3f ( RED(p->clr), GRN(p->clr), BLUE(p->clr) ); + glVertex3f ( p->pos.x, p->pos.y, p->pos.z ); + dat += mBuf[0].stride; + } + glEnd (); + } +} + +void PointSet::Emit ( float spacing ) +{ + Particle* p; + Vector3DF dir; + Vector3DF pos; + float ang_rand, tilt_rand; + float rnd = m_Vec[EMIT_RATE].y * 0.15; + int x = (int) sqrt(m_Vec[EMIT_RATE].y); + + for ( int n = 0; n < m_Vec[EMIT_RATE].y; n++ ) { + ang_rand = (float(rand()*2.0/RAND_MAX) - 1.0) * m_Vec[EMIT_SPREAD].x; + tilt_rand = (float(rand()*2.0/RAND_MAX) - 1.0) * m_Vec[EMIT_SPREAD].y; + dir.x = cos ( ( m_Vec[EMIT_ANG].x + ang_rand) * DEGtoRAD ) * sin( ( m_Vec[EMIT_ANG].y + tilt_rand) * DEGtoRAD ) * m_Vec[EMIT_ANG].z; + dir.y = sin ( ( m_Vec[EMIT_ANG].x + ang_rand) * DEGtoRAD ) * sin( ( m_Vec[EMIT_ANG].y + tilt_rand) * DEGtoRAD ) * m_Vec[EMIT_ANG].z; + dir.z = cos ( ( m_Vec[EMIT_ANG].y + tilt_rand) * DEGtoRAD ) * m_Vec[EMIT_ANG].z; + pos = m_Vec[EMIT_POS]; + pos.x += spacing * (n/x); + pos.y += spacing * (n%x); + + p = (Particle*) GetElem( 0, AddPointReuse () ); + p->pos = pos; + p->vel = dir; + p->vel_eval = dir; + p->age = 0; + p->clr = COLORA ( m_Time/10.0, m_Time/5.0, m_Time /4.0, 1 ); + } +} + + +void PointSet::Run () +{ + if ( m_Vec[EMIT_RATE].x > 0 && ++m_Frame >= (int) m_Vec[EMIT_RATE].x ) { + m_Frame = 0; + Emit ( 1.0 ); + } + Advance(); +} + +void PointSet::Advance () +{ + char* dat; + Particle* p; + Vector3DF vnext, accel, norm; + + vnext = m_Vec[EMIT_DANG]; + vnext *= m_DT; + m_Vec[EMIT_ANG] += vnext; + + dat = mBuf[0].data; + for ( int c = 0; c < NumPoints(); c++ ) { + p = (Particle*) dat; + + accel.Set (0, 0, 0); + + // Plane gravity + if ( m_Param[PLANE_GRAV] > 0) + accel += m_Vec[PLANE_GRAV_DIR]; + + // Point gravity + if ( m_Param[POINT_GRAV] > 0 ) { + norm.x = ( p->pos.x - m_Vec[POINT_GRAV_POS].x ); + norm.y = ( p->pos.y - m_Vec[POINT_GRAV_POS].y ); + norm.z = ( p->pos.z - m_Vec[POINT_GRAV_POS].z ); + norm.Normalize (); + norm *= m_Param[POINT_GRAV]; + accel -= norm; + } + + // Leapfrog Integration ---------------------------- + vnext = accel; + vnext *= m_DT; + vnext += p->vel; // v(t+1/2) = v(t-1/2) + a(t) dt + p->vel_eval = p->vel; + p->vel_eval += vnext; + p->vel_eval *= 0.5; // v(t+1) = [v(t-1/2) + v(t+1/2)] * 0.5 used to compute forces later + p->vel = vnext; + vnext *= m_DT; + p->pos += vnext; // p(t+1) = p(t) + v(t+1/2) dt + + // Euler integration ------------------------------- + // accel += m_Gravity; + // accel *= m_DT; + // mParticles[c].vel += accel; // v(t+1) = v(t) + a(t) dt + // mParticles[c].vel_eval += accel; + // mParticles[c].vel_eval *= m_DT/d; + // mParticles[c].pos += mParticles[c].vel_eval; + // mParticles[c].vel_eval = mParticles[c].vel; + + dat += mBuf[0].stride; + } + + m_Time += m_DT; +} + +// Ideal grid cell size (gs) = 2 * smoothing radius = 0.02*2 = 0.04 +// Ideal domain size = k*gs/d = k*0.02*2/0.005 = k*8 = {8, 16, 24, 32, 40, 48, ..} +// (k = number of cells, gs = cell size, d = simulation scale) +void PointSet::Grid_Setup ( Vector3DF min, Vector3DF max, float sim_scale, float cell_size, float border ) +{ + float world_cellsize = cell_size / sim_scale; + m_Grid.clear (); + m_GridMin = min; m_GridMin -= border; + m_GridMax = max; m_GridMax += border; + m_GridSize = m_GridMax; + m_GridSize -= m_GridMin; + m_GridCellsize = world_cellsize; + m_GridRes.x = ceil ( m_GridSize.x / world_cellsize ); // Determine grid resolution + m_GridRes.y = ceil ( m_GridSize.y / world_cellsize ); + m_GridRes.z = ceil ( m_GridSize.z / world_cellsize ); + m_GridSize.x = m_GridRes.x * cell_size / sim_scale; // Adjust grid size to multiple of cell size + m_GridSize.y = m_GridRes.y * cell_size / sim_scale; + m_GridSize.z = m_GridRes.z * cell_size / sim_scale; + m_GridDelta = m_GridRes; // delta = translate from world space to cell # + m_GridDelta /= m_GridSize; + m_GridTotal = (int)(m_GridSize.x * m_GridSize.y * m_GridSize.z); + + m_Grid.clear (); + m_GridCnt.clear (); + + m_Grid.reserve ( m_GridTotal ); + m_GridCnt.reserve ( m_GridTotal ); + for (int n=0; n < m_GridTotal; n++) { + m_Grid.push_back ( -1 ); + m_GridCnt.push_back ( 0 ); + } + +} + +void PointSet::Grid_Draw ( float* view_mat ) +{ + float clr; + int cx, cy, cz; + float x1, y1, z1; + float x2, y2, z2; + int g = 0; + + glLoadMatrixf ( view_mat ); + glColor3f ( 0.7, 0.7, 0.7 ); + + glBegin ( GL_LINES ); + + cz = 0; + //for ( cz = 0; cz < m_GridRes.z; cz++ ) { + for ( cy = 0; cy < m_GridRes.y; cy++ ) { + for ( cx = 0; cx < m_GridRes.x; cx++ ) { + // Cell is not empty. Process it. + //if ( m_Grid[g] != 0x0 ) { + // clr = m_GridCnt[g]/30.0; + clr = 0.25; + if ( clr <0.25) clr =0.25; + if ( clr >1) clr =1 ; + glColor3f ( clr, clr, clr ); + x1 = (cx * m_GridDelta.x) + m_GridMin.x; x2 = ((cx+1) * m_GridDelta.x) + m_GridMin.x; + y1 = (cy * m_GridDelta.y) + m_GridMin.y; y2 = ((cy+1) * m_GridDelta.y) + m_GridMin.y; + z1 = (cz * m_GridDelta.z) + m_GridMin.z; z2 = ((cz+1) * m_GridDelta.z) + m_GridMin.z; + glVertex3f ( x1, y1, z1 ); glVertex3f ( x2, y1, z1 ); + glVertex3f ( x2, y1, z1 ); glVertex3f ( x2, y2, z1 ); + glVertex3f ( x2, y2, z1 ); glVertex3f ( x1, y2, z1 ); + glVertex3f ( x1, y2, z1 ); glVertex3f ( x1, y1, z1 ); + glVertex3f ( x1, y1, z2 ); glVertex3f ( x2, y1, z2 ); + glVertex3f ( x2, y1, z2 ); glVertex3f ( x2, y2, z2 ); + glVertex3f ( x2, y2, z2 ); glVertex3f ( x1, y2, z2 ); + glVertex3f ( x1, y2, z2 ); glVertex3f ( x1, y1, z2 ); + glVertex3f ( x1, y1, z1 ); glVertex3f ( x1, y1, z2 ); + glVertex3f ( x1, y2, z1 ); glVertex3f ( x1, y2, z2 ); + glVertex3f ( x2, y2, z1 ); glVertex3f ( x2, y2, z2 ); + glVertex3f ( x2, y1, z1 ); glVertex3f ( x2, y1, z2 ); + //} + g++; + } + } + //} + + glEnd (); +} + +void PointSet::Grid_InsertParticles () +{ + char *dat1, *dat1_end; + Point *p; + int gs; + int gx, gy, gz; + + dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride; + for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride ) + ((Point*) dat1)->next = -1; + + for (int n=0; n < m_GridTotal; n++) { + m_Grid[n] = -1; + m_GridCnt[n] = 0; + } + + dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride; + int n = 0; + for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride ) { + p = (Point*) dat1; + gx = (int)( (p->pos.x - m_GridMin.x) * m_GridDelta.x); // Determine grid cell + gy = (int)( (p->pos.y - m_GridMin.y) * m_GridDelta.y); + gz = (int)( (p->pos.z - m_GridMin.z) * m_GridDelta.z); + gs = (int)( (gz*m_GridRes.y + gy)*m_GridRes.x + gx); + if ( gs >= 0 && gs < m_GridTotal ) { + p->next = m_Grid[gs]; + m_Grid[gs] = n; + m_GridCnt[gs]++; + } + n++; + } +} + +int PointSet::Grid_FindCell ( Vector3DF p ) +{ + int gc; + Vector3DI cell; + cell.x = (int) (p.x - m_GridMin.x) * m_GridDelta.x; + cell.y = (int) (p.y - m_GridMin.y) * m_GridDelta.y; + cell.z = (int) (p.z - m_GridMin.z) * m_GridDelta.z; + gc = (int)( (cell.z*m_GridRes.y + cell.y)*m_GridRes.x + cell.x); + if ( gc < 0 || gc > m_GridTotal ) return -1; + return gc; +} + +void PointSet::Grid_FindCells ( Vector3DF p, float radius ) +{ + Vector3DI sph_min; + + // Compute sphere range + sph_min.x = (int)((-radius + p.x - m_GridMin.x) * m_GridDelta.x); + sph_min.y = (int)((-radius + p.y - m_GridMin.y) * m_GridDelta.y); + sph_min.z = (int)((-radius + p.z - m_GridMin.z) * m_GridDelta.z); + if ( sph_min.x < 0 ) sph_min.x = 0; + if ( sph_min.y < 0 ) sph_min.y = 0; + if ( sph_min.z < 0 ) sph_min.z = 0; + + m_GridCell[0] = (int)((sph_min.z * m_GridRes.y + sph_min.y) * m_GridRes.x + sph_min.x); + m_GridCell[1] = m_GridCell[0] + 1; + m_GridCell[2] = (int)(m_GridCell[0] + m_GridRes.x); + m_GridCell[3] = m_GridCell[2] + 1; + + if ( sph_min.z+1 < m_GridRes.z ) { + m_GridCell[4] = (int)(m_GridCell[0] + m_GridRes.y*m_GridRes.x); + m_GridCell[5] = m_GridCell[4] + 1; + m_GridCell[6] = (int)(m_GridCell[4] + m_GridRes.x); + m_GridCell[7] = m_GridCell[6] + 1; + } + if ( sph_min.x+1 >= m_GridRes.x ) { + m_GridCell[1] = -1; m_GridCell[3] = -1; + m_GridCell[5] = -1; m_GridCell[7] = -1; + } + if ( sph_min.y+1 >= m_GridRes.y ) { + m_GridCell[2] = -1; m_GridCell[3] = -1; + m_GridCell[6] = -1; m_GridCell[7] = -1; + } +} diff --git a/Extras/sph/common/point_set.h b/Extras/sph/common/point_set.h new file mode 100644 index 0000000..c9fe293 --- /dev/null +++ b/Extras/sph/common/point_set.h @@ -0,0 +1,165 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 DEF_POINT_SET + #define DEF_POINT_SET + + #include + #include + #include + #include + #include + + #include "common_defs.h" + #include "geomx.h" + #include "vector.h" + + typedef signed int xref; + + #define MAX_NEIGHBOR 80 + + #define MAX_PARAM 21 + + // Scalar params + #define PNT_DRAWMODE 0 + #define PNT_SPHERE 0 + #define PNT_POINT 1 + #define PNT_DRAWSIZE 1 + #define POINT_GRAV 2 + #define PLANE_GRAV 3 + + // Vector params + #define EMIT_POS 0 + #define EMIT_ANG 1 + #define EMIT_DANG 2 + #define EMIT_SPREAD 3 + #define EMIT_RATE 4 + #define POINT_GRAV_POS 5 + #define PLANE_GRAV_DIR 6 + + + #define BPOINT 0 + #define BPARTICLE 1 + + struct Point { + Vector3DF pos; + DWORD clr; + int next; + }; + + struct Particle { + Vector3DF pos; + DWORD clr; + int next; + Vector3DF vel; + Vector3DF vel_eval; + unsigned short age; + }; + + class PointSet : public GeomX { + public: + PointSet (); + + // Point Sets + + virtual void Initialize ( int mode, int max ); + virtual void Draw ( float* view_mat, float rad ); + virtual void Reset (); + virtual int AddPoint (); + virtual int AddPointReuse (); + Point* GetPoint ( int n ) { return (Point*) GetElem(0, n); } + int NumPoints () { return NumElem(0); } + + // Metablobs + virtual float GetValue ( float x, float y, float z ); + virtual Vector3DF GetGradient ( float x, float y, float z ); + // virtual float GetValue ( float x, float y, float z, Vector3DF& dir ); + virtual DWORD GetColor ( float x, float y, float z ); + + // Particle system + virtual void Run (); + virtual void Advance (); + virtual void Emit ( float spacing ); + + // Misc + virtual void AddVolume ( Vector3DF min, Vector3DF max, float spacing ); + + // Parameters + void SetParam (int p, float v ) { m_Param[p] = v; } + void SetParam (int p, int v ) { m_Param[p] = (float) v; } + float GetParam ( int p ) { return (float) m_Param[p]; } + Vector3DF GetVec ( int p ) { return m_Vec[p]; } + void SetVec ( int p, Vector3DF v ) { m_Vec[p] = v; } + void Toggle ( int p ) { m_Toggle[p] = !m_Toggle[p]; } + bool GetToggle ( int p ) { return m_Toggle[p]; } + + float GetDT() { return (float) m_DT; } + + // Spatial Subdivision + void Grid_Setup ( Vector3DF min, Vector3DF max, float sim_scale, float cell_size, float border ); + void Grid_Create (); + void Grid_InsertParticles (); + void Grid_Draw ( float* view_mat ); + void Grid_FindCells ( Vector3DF p, float radius ); + int Grid_FindCell ( Vector3DF p ); + Vector3DF GetGridRes () { return m_GridRes; } + Vector3DF GetGridMin () { return m_GridMin; } + Vector3DF GetGridMax () { return m_GridMax; } + Vector3DF GetGridDelta () { return m_GridDelta; } + int GetGridCell ( int x, int y, int z ); + Point* firstGridParticle ( int gc, int& p ); + Point* nextGridParticle ( int& p ); + unsigned short* getNeighborTable ( int n, int& cnt ); + + protected: + int m_Frame; + + // Parameters + double m_Param [ MAX_PARAM ]; // see defines above + Vector3DF m_Vec [ MAX_PARAM ]; + bool m_Toggle [ MAX_PARAM ]; + + // Particle System + double m_DT; + double m_Time; + + // Spatial Grid + std::vector< int > m_Grid; + std::vector< int > m_GridCnt; + int m_GridTotal; // total # cells + Vector3DF m_GridMin; // volume of grid (may not match domain volume exactly) + Vector3DF m_GridMax; + Vector3DF m_GridRes; // resolution in each axis + Vector3DF m_GridSize; // physical size in each axis + Vector3DF m_GridDelta; + float m_GridCellsize; + int m_GridCell[27]; + + // Neighbor Table + unsigned short m_NC[65536]; // neighbor table (600k) + unsigned short m_Neighbor[65536][MAX_NEIGHBOR]; + float m_NDist[65536][MAX_NEIGHBOR]; + + static int m_pcurr; + }; + +#endif diff --git a/Extras/sph/common/vector-inline.h b/Extras/sph/common/vector-inline.h new file mode 100644 index 0000000..9d5865d --- /dev/null +++ b/Extras/sph/common/vector-inline.h @@ -0,0 +1,782 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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. +*/ +// Vector Operations Implemented: +// =, +, -, *, / (on vectors and scalars) +// Cross Cross product vector with op +// Dot Dot product vector with op +// Dist (op) Distance from vector to op +// DistSq Distance^2 from vector to op +// Length () Length of vector +// Normalize () Normalizes vector +// + +#include "vector.h" + +// Vector2DC Code Definition + +#define VTYPE unsigned char +#define VNAME 2DC + +// Constructors/Destructors +inline Vector2DC::Vector2DC() {x=0; y=0;} +inline Vector2DC::~Vector2DC() {} +inline Vector2DC::Vector2DC (VTYPE xa, VTYPE ya) {x=xa; y=ya;} +inline Vector2DC::Vector2DC (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DC::Vector2DC (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DC::Vector2DC (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DC::Vector2DC (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DC::Vector2DC (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DC::Vector2DC (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DC::Vector2DC (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} + +// Member Functions +inline Vector2DC &Vector2DC::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} + +inline Vector2DC &Vector2DC::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} + +inline Vector2DC &Vector2DC::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} + +inline Vector2DC &Vector2DC::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} + +inline Vector2DC &Vector2DC::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} + +// Note: Cross product does not exist for 2D vectors (only 3D) + +inline double Vector2DC::Dot(Vector2DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} +inline double Vector2DC::Dot(Vector2DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} +inline double Vector2DC::Dot(Vector2DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} + +inline double Vector2DC::Dist (Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DC::Dist (Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DC::Dist (Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DC::Dist (Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DC::Dist (Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DC::Dist (Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DC::Dist (Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DC::DistSq (Vector2DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DC::DistSq (Vector2DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DC::DistSq (Vector2DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DC::DistSq (Vector3DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DC::DistSq (Vector3DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DC::DistSq (Vector3DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DC::DistSq (Vector4DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} + +inline Vector2DC &Vector2DC::Normalize (void) { + double n = (double) x*x + (double) y*y; + if (n!=0.0) { + n = sqrt(n); + x = (VTYPE) (((double) x*255)/n); + y = (VTYPE) (((double) y*255)/n); + } + return *this; +} +inline double Vector2DC::Length (void) { double n; n = (double) x*x + (double) y*y; if (n != 0.0) return sqrt(n); return 0.0; } + +inline VTYPE &Vector2DC::X(void) {return x;} +inline VTYPE &Vector2DC::Y(void) {return y;} +inline VTYPE Vector2DC::Z(void) {return 0;} +inline VTYPE Vector2DC::W(void) {return 0;} +inline const VTYPE &Vector2DC::X(void) const {return x;} +inline const VTYPE &Vector2DC::Y(void) const {return y;} +inline const VTYPE Vector2DC::Z(void) const {return 0;} +inline const VTYPE Vector2DC::W(void) const {return 0;} +inline VTYPE *Vector2DC::Data (void) {return &x;} + +#undef VTYPE +#undef VNAME + +// Vector2DI Code Definition + +#define VNAME 2DI +#define VTYPE int + +// Constructors/Destructors +inline Vector2DI::Vector2DI() {x=0; y=0;} +inline Vector2DI::~Vector2DI() {} +inline Vector2DI::Vector2DI (VTYPE xa, VTYPE ya) {x=xa; y=ya;} +inline Vector2DI::Vector2DI (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DI::Vector2DI (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DI::Vector2DI (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DI::Vector2DI (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DI::Vector2DI (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DI::Vector2DI (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DI::Vector2DI (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} + +// Member Functions +inline Vector2DI &Vector2DI::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} + +inline Vector2DI &Vector2DI::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} + +inline Vector2DI &Vector2DI::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} + +inline Vector2DI &Vector2DI::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} + +inline Vector2DI &Vector2DI::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} + +// Note: Cross product does not exist for 2D vectors (only 3D) + +inline double Vector2DI::Dot(Vector2DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} +inline double Vector2DI::Dot(Vector2DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} +inline double Vector2DI::Dot(Vector2DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} + +inline double Vector2DI::Dist (Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DI::Dist (Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DI::Dist (Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DI::Dist (Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DI::Dist (Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DI::Dist (Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DI::Dist (Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DI::DistSq (Vector2DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DI::DistSq (Vector2DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DI::DistSq (Vector2DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DI::DistSq (Vector3DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DI::DistSq (Vector3DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DI::DistSq (Vector3DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DI::DistSq (Vector4DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} + +inline Vector2DI &Vector2DI::Normalize (void) { + double n = (double) x*x + (double) y*y; + if (n!=0.0) { + n = sqrt(n); + x = (VTYPE) (((double) x*255)/n); + y = (VTYPE) (((double) y*255)/n); + } + return *this; +} +inline double Vector2DI::Length (void) { double n; n = (double) x*x + (double) y*y; if (n != 0.0) return sqrt(n); return 0.0; } + +inline VTYPE &Vector2DI::X(void) {return x;} +inline VTYPE &Vector2DI::Y(void) {return y;} +inline VTYPE Vector2DI::Z(void) {return 0;} +inline VTYPE Vector2DI::W(void) {return 0;} +inline const VTYPE &Vector2DI::X(void) const {return x;} +inline const VTYPE &Vector2DI::Y(void) const {return y;} +inline const VTYPE Vector2DI::Z(void) const {return 0;} +inline const VTYPE Vector2DI::W(void) const {return 0;} +inline VTYPE *Vector2DI::Data (void) {return &x;} + +#undef VTYPE +#undef VNAME + +// Vector2DF Code Definition + +#define VNAME 2DF +#define VTYPE double + +// Constructors/Destructors +inline Vector2DF::Vector2DF() {x=0; y=0;} +inline Vector2DF::~Vector2DF() {} +inline Vector2DF::Vector2DF (const VTYPE xa, const VTYPE ya) {x=xa; y=ya;} +inline Vector2DF::Vector2DF (const Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DF::Vector2DF (const Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DF::Vector2DF (const Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DF::Vector2DF (const Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DF::Vector2DF (const Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DF::Vector2DF (const Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DF::Vector2DF (const Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} + +// Member Functions +inline Vector2DF &Vector2DF::operator= (const Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator= (const Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator= (const Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator= (const Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator= (const Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator= (const Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator= (const Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} + +inline Vector2DF &Vector2DF::operator+= (const Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator+= (const Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator+= (const Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator+= (const Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator+= (const Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator+= (const Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator+= (const Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} + +inline Vector2DF &Vector2DF::operator-= (const Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator-= (const Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator-= (const Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator-= (const Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator-= (const Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator-= (const Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator-= (const Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} + +inline Vector2DF &Vector2DF::operator*= (const Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator*= (const Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator*= (const Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator*= (const Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator*= (const Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator*= (const Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator*= (const Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} + +inline Vector2DF &Vector2DF::operator/= (const Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator/= (const Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator/= (const Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator/= (const Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator/= (const Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator/= (const Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator/= (const Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} + +// Note: Cross product does not exist for 2D vectors (only 3D) + +inline double Vector2DF::Dot(const Vector2DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} +inline double Vector2DF::Dot(const Vector2DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} +inline double Vector2DF::Dot(const Vector2DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} + +inline double Vector2DF::Dist (const Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DF::Dist (const Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DF::Dist (const Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DF::Dist (const Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DF::Dist (const Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DF::Dist (const Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DF::Dist (const Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DF::DistSq (const Vector2DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DF::DistSq (const Vector2DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DF::DistSq (const Vector2DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DF::DistSq (const Vector3DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DF::DistSq (const Vector3DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DF::DistSq (const Vector3DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DF::DistSq (const Vector4DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} + +inline Vector2DF &Vector2DF::Normalize (void) { + double n = (double) x*x + (double) y*y; + if (n!=0.0) { + n = sqrt(n); + x /= n; + y /= n; + } + return *this; +} +inline double Vector2DF::Length (void) { double n; n = (double) x*x + (double) y*y; if (n != 0.0) return sqrt(n); return 0.0; } + +inline VTYPE &Vector2DF::X(void) {return x;} +inline VTYPE &Vector2DF::Y(void) {return y;} +inline VTYPE Vector2DF::Z(void) {return 0;} +inline VTYPE Vector2DF::W(void) {return 0;} +inline const VTYPE &Vector2DF::X(void) const {return x;} +inline const VTYPE &Vector2DF::Y(void) const {return y;} +inline const VTYPE Vector2DF::Z(void) const {return 0;} +inline const VTYPE Vector2DF::W(void) const {return 0;} +inline VTYPE *Vector2DF::Data (void) {return &x;} + +#undef VTYPE +#undef VNAME + +// Vector3DC Code Definition + +#define VNAME 3DC +#define VTYPE unsigned char + +// Constructors/Destructors +inline Vector3DC::Vector3DC() {x=0; y=0; z=0;} +inline Vector3DC::~Vector3DC() {} +inline Vector3DC::Vector3DC (VTYPE xa, VTYPE ya, VTYPE za) {x=xa; y=ya; z=za;} +inline Vector3DC::Vector3DC (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DC::Vector3DC (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DC::Vector3DC (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DC::Vector3DC (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DC::Vector3DC (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DC::Vector3DC (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DC::Vector3DC (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} + +// Member Functions +inline Vector3DC &Vector3DC::Set (VTYPE xa, VTYPE ya, VTYPE za) {x=xa; y=ya; z=za; return *this;} + +inline Vector3DC &Vector3DC::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; return *this;} +inline Vector3DC &Vector3DC::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; return *this;} +inline Vector3DC &Vector3DC::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; return *this;} +inline Vector3DC &Vector3DC::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} + +inline Vector3DC &Vector3DC::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} + +inline Vector3DC &Vector3DC::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} + +inline Vector3DC &Vector3DC::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} + +inline Vector3DC &Vector3DC::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} + +inline Vector3DC &Vector3DC::Cross (Vector3DC &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} +inline Vector3DC &Vector3DC::Cross (Vector3DI &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} +inline Vector3DC &Vector3DC::Cross (Vector3DF &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} + +inline double Vector3DC::Dot(Vector3DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} +inline double Vector3DC::Dot(Vector3DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} +inline double Vector3DC::Dot(Vector3DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} + +inline double Vector3DC::Dist (Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DC::Dist (Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DC::Dist (Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DC::Dist (Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DC::Dist (Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DC::Dist (Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DC::Dist (Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DC::DistSq (Vector2DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DC::DistSq (Vector2DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DC::DistSq (Vector2DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DC::DistSq (Vector3DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DC::DistSq (Vector3DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DC::DistSq (Vector3DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DC::DistSq (Vector4DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} + +inline Vector3DC &Vector3DC::Normalize (void) { + double n = (double) x*x + (double) y*y + (double) z*z; + if (n!=0.0) { + n = sqrt(n); + x = (VTYPE) (((double) x*255)/n); + y = (VTYPE) (((double) y*255)/n); + z = (VTYPE) (((double) z*255)/n); + } + return *this; +} +inline double Vector3DC::Length (void) { double n; n = (double) x*x + (double) y*y + (double) z*z; if (n != 0.0) return sqrt(n); return 0.0; } + +inline VTYPE &Vector3DC::X(void) {return x;} +inline VTYPE &Vector3DC::Y(void) {return y;} +inline VTYPE &Vector3DC::Z(void) {return z;} +inline VTYPE Vector3DC::W(void) {return 0;} +inline const VTYPE &Vector3DC::X(void) const {return x;} +inline const VTYPE &Vector3DC::Y(void) const {return y;} +inline const VTYPE &Vector3DC::Z(void) const {return z;} +inline const VTYPE Vector3DC::W(void) const {return 0;} +inline VTYPE *Vector3DC::Data (void) {return &x;} + +#undef VTYPE +#undef VNAME + +// Vector3DI Code Definition + +#define VNAME 3DI +#define VTYPE int + +// Constructors/Destructors +inline Vector3DI::Vector3DI() {x=0; y=0; z=0;} +inline Vector3DI::~Vector3DI() {} +inline Vector3DI::Vector3DI (VTYPE xa, VTYPE ya, VTYPE za) {x=xa; y=ya; z=za;} +inline Vector3DI::Vector3DI (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DI::Vector3DI (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DI::Vector3DI (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DI::Vector3DI (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DI::Vector3DI (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DI::Vector3DI (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DI::Vector3DI (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} + +// Set Functions +inline Vector3DI &Vector3DI::Set (const int xa, const int ya, const int za) +{ + x = xa; y = ya; z = za; + return *this; +} + +// Member Functions +inline Vector3DI &Vector3DI::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} + +inline Vector3DI &Vector3DI::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} + +inline Vector3DI &Vector3DI::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} + +inline Vector3DI &Vector3DI::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} + +inline Vector3DI &Vector3DI::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} + +inline Vector3DI &Vector3DI::Cross (Vector3DC &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} +inline Vector3DI &Vector3DI::Cross (Vector3DI &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} +inline Vector3DI &Vector3DI::Cross (Vector3DF &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} + +inline double Vector3DI::Dot(Vector3DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} +inline double Vector3DI::Dot(Vector3DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} +inline double Vector3DI::Dot(Vector3DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} + +inline double Vector3DI::Dist (Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DI::Dist (Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DI::Dist (Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DI::Dist (Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DI::Dist (Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DI::Dist (Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DI::Dist (Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DI::DistSq (Vector2DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DI::DistSq (Vector2DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DI::DistSq (Vector2DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DI::DistSq (Vector3DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DI::DistSq (Vector3DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DI::DistSq (Vector3DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DI::DistSq (Vector4DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} + +inline Vector3DI &Vector3DI::Normalize (void) { + double n = (double) x*x + (double) y*y + (double) z*z; + if (n!=0.0) { + n = sqrt(n); + x = (VTYPE) (((double) x*255)/n); + y = (VTYPE) (((double) y*255)/n); + z = (VTYPE) (((double) z*255)/n); + } + return *this; +} +inline double Vector3DI::Length (void) { double n; n = (double) x*x + (double) y*y + (double) z*z; if (n != 0.0) return sqrt(n); return 0.0; } + +inline VTYPE &Vector3DI::X(void) {return x;} +inline VTYPE &Vector3DI::Y(void) {return y;} +inline VTYPE &Vector3DI::Z(void) {return z;} +inline VTYPE Vector3DI::W(void) {return 0;} +inline const VTYPE &Vector3DI::X(void) const {return x;} +inline const VTYPE &Vector3DI::Y(void) const {return y;} +inline const VTYPE &Vector3DI::Z(void) const {return z;} +inline const VTYPE Vector3DI::W(void) const {return 0;} +inline VTYPE *Vector3DI::Data (void) {return &x;} + +#undef VTYPE +#undef VNAME + +// Vector3DF Code Definition + +#define VNAME 3DF +#define VTYPE double + +// Constructors/Destructors +inline Vector3DF::Vector3DF() {x=0; y=0; z=0;} +inline Vector3DF::~Vector3DF() {} +inline Vector3DF::Vector3DF (const VTYPE xa, const VTYPE ya, const VTYPE za) {x=xa; y=ya; z=za;} +inline Vector3DF::Vector3DF (const Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DF::Vector3DF (const Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DF::Vector3DF (const Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DF::Vector3DF (const Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DF::Vector3DF (const Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DF::Vector3DF (const Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DF::Vector3DF (const Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} + +// Set Functions +inline Vector3DF &Vector3DF::Set (const double xa, const double ya, const double za) +{ + x = xa; y = ya; z = za; + return *this; +} + +// Member Functions +inline Vector3DF &Vector3DF::operator= (const int op) {x= (VTYPE) op; y= (VTYPE) op; z= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator= (const double op) {x= (VTYPE) op; y= (VTYPE) op; z= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator= (const Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator= (const Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator= (const Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator= (const Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator= (const Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator= (const Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator= (const Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} + +inline Vector3DF &Vector3DF::operator+= (const int op) {x+= (VTYPE) op; y+= (VTYPE) op; z+= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator+= (const double op) {x+= (VTYPE) op; y+= (VTYPE) op; z+= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator+= (const Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator+= (const Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator+= (const Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator+= (const Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator+= (const Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator+= (const Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator+= (const Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} + +inline Vector3DF &Vector3DF::operator-= (const int op) {x-= (VTYPE) op; y-= (VTYPE) op; z-= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator-= (const double op) {x-= (VTYPE) op; y-= (VTYPE) op; z-= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator-= (const Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator-= (const Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator-= (const Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator-= (const Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator-= (const Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator-= (const Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator-= (const Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} + +inline Vector3DF &Vector3DF::operator*= (const int op) {x*= (VTYPE) op; y*= (VTYPE) op; z*= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator*= (const double op) {x*= (VTYPE) op; y*= (VTYPE) op; z*= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator*= (const Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator*= (const Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator*= (const Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator*= (const Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator*= (const Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator*= (const Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator*= (const Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} + +inline Vector3DF &Vector3DF::operator/= (const int op) {x/= (VTYPE) op; y/= (VTYPE) op; z/= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator/= (const double op) {x/= (VTYPE) op; y/= (VTYPE) op; z/= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator/= (const Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator/= (const Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator/= (const Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator/= (const Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator/= (const Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator/= (const Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator/= (const Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} + +inline Vector3DF &Vector3DF::Cross (const Vector3DC &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} +inline Vector3DF &Vector3DF::Cross (const Vector3DI &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} +inline Vector3DF &Vector3DF::Cross (const Vector3DF &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} + +inline double Vector3DF::Dot(const Vector3DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} +inline double Vector3DF::Dot(const Vector3DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} +inline double Vector3DF::Dot(const Vector3DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} + +inline double Vector3DF::Dist (const Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DF::Dist (const Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DF::Dist (const Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DF::Dist (const Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DF::Dist (const Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DF::Dist (const Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DF::Dist (const Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DF::DistSq (const Vector2DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DF::DistSq (const Vector2DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DF::DistSq (const Vector2DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DF::DistSq (const Vector3DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DF::DistSq (const Vector3DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DF::DistSq (const Vector3DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DF::DistSq (const Vector4DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} + +inline Vector3DF &Vector3DF::Normalize (void) { + double n = (double) x*x + (double) y*y + (double) z*z; + if (n!=0.0) { + n = sqrt(n); + x /= n; y /= n; z /= n; + } + return *this; +} +inline double Vector3DF::Length (void) { double n; n = (double) x*x + (double) y*y + (double) z*z; if (n != 0.0) return sqrt(n); return 0.0; } + +inline VTYPE &Vector3DF::X() {return x;} +inline VTYPE &Vector3DF::Y() {return y;} +inline VTYPE &Vector3DF::Z() {return z;} +inline VTYPE Vector3DF::W() {return 0;} +inline const VTYPE &Vector3DF::X() const {return x;} +inline const VTYPE &Vector3DF::Y() const {return y;} +inline const VTYPE &Vector3DF::Z() const {return z;} +inline const VTYPE Vector3DF::W() const {return 0;} +inline VTYPE *Vector3DF::Data () {return &x;} + +#undef VTYPE +#undef VNAME + +// Vector4DF Code Definition + +#define VNAME 4DF +#define VTYPE double + +// Constructors/Destructors +inline Vector4DF::Vector4DF() {x=0; y=0; z=0; w=0;} +inline Vector4DF::~Vector4DF() {} +inline Vector4DF::Vector4DF (VTYPE xa, VTYPE ya, VTYPE za, VTYPE wa) {x=xa; y=ya; z=za; w=wa;} +inline Vector4DF::Vector4DF (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0;} +inline Vector4DF::Vector4DF (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0;} +inline Vector4DF::Vector4DF (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0;} +inline Vector4DF::Vector4DF (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0;} +inline Vector4DF::Vector4DF (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0;} +inline Vector4DF::Vector4DF (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0;} +inline Vector4DF::Vector4DF (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) op.w;} + +// Member Functions +inline Vector4DF &Vector4DF::operator= (int op) {x= (VTYPE) op; y= (VTYPE) op; z= (VTYPE) op; w = (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator= (double op) {x= (VTYPE) op; y= (VTYPE) op; z= (VTYPE) op; w = (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0; return *this;} +inline Vector4DF &Vector4DF::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0; return *this;} +inline Vector4DF &Vector4DF::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0; return *this;} +inline Vector4DF &Vector4DF::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0; return *this;} +inline Vector4DF &Vector4DF::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0; return *this;} +inline Vector4DF &Vector4DF::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0; return *this;} +inline Vector4DF &Vector4DF::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) op.w; return *this;} + +inline Vector4DF &Vector4DF::operator+= (int op) {x+= (VTYPE) op; y+= (VTYPE) op; z+= (VTYPE) op; w += (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator+= (double op) {x+= (VTYPE) op; y+= (VTYPE) op; z+= (VTYPE) op; w += (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; w+=(VTYPE) op.w; return *this;} + +inline Vector4DF &Vector4DF::operator-= (int op) {x-= (VTYPE) op; y-= (VTYPE) op; z-= (VTYPE) op; w -= (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator-= (double op) {x-= (VTYPE) op; y-= (VTYPE) op; z-= (VTYPE) op; w -= (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; w-=(VTYPE) op.w; return *this;} + +inline Vector4DF &Vector4DF::operator*= (int op) {x*= (VTYPE) op; y*= (VTYPE) op; z*= (VTYPE) op; w *= (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator*= (double op) {x*= (VTYPE) op; y*= (VTYPE) op; z*= (VTYPE) op; w *= (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; w*=(VTYPE) op.w; return *this;} + +inline Vector4DF &Vector4DF::operator/= (int op) {x/= (VTYPE) op; y/= (VTYPE) op; z/= (VTYPE) op; w /= (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator/= (double op) {x/= (VTYPE) op; y/= (VTYPE) op; z/= (VTYPE) op; w /= (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; w/=(VTYPE) op.w; return *this;} + +inline Vector4DF &Vector4DF::Cross (Vector4DF &v) {double ax = x, ay = y, az = z, aw = w; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); w = (VTYPE) 0; return *this;} + +inline double Vector4DF::Dot(Vector4DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z + (double) w*v.w; return dot;} + +inline double Vector4DF::Dist (Vector4DF &v) {double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} + +inline double Vector4DF::DistSq (Vector4DF &v) {double a,b,c,d; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; d = (double) w - (double) v.w; return (a*a + b*b + c*c + d*d);} + +inline Vector4DF &Vector4DF::Normalize (void) { + double n = (double) x*x + (double) y*y + (double) z*z + (double) w*w; + if (n!=0.0) { + n = sqrt(n); + x /= n; y /= n; z /= n; w /= n; + } + return *this; +} +inline double Vector4DF::Length (void) { double n; n = (double) x*x + (double) y*y + (double) z*z + (double) w*w; if (n != 0.0) return sqrt(n); return 0.0; } + +inline VTYPE &Vector4DF::X(void) {return x;} +inline VTYPE &Vector4DF::Y(void) {return y;} +inline VTYPE &Vector4DF::Z(void) {return z;} +inline VTYPE &Vector4DF::W(void) {return w;} +inline const VTYPE &Vector4DF::X(void) const {return x;} +inline const VTYPE &Vector4DF::Y(void) const {return y;} +inline const VTYPE &Vector4DF::Z(void) const {return z;} +inline const VTYPE &Vector4DF::W(void) const {return w;} +inline VTYPE *Vector4DF::Data (void) {return &x;} + +#undef VTYPE +#undef VNAME diff --git a/Extras/sph/common/vector.cci b/Extras/sph/common/vector.cci new file mode 100644 index 0000000..2a548f3 --- /dev/null +++ b/Extras/sph/common/vector.cci @@ -0,0 +1,761 @@ +// Vector Operations Implemented: +// =, +, -, *, / (on vectors and scalars) +// Cross Cross product vector with op +// Dot Dot product vector with op +// Dist (op) Distance from vector to op +// DistSq Distance^2 from vector to op +// Length () Length of vector +// Normalize () Normalizes vector +// + +#include + +// Vector2DC Code Definition + +#define VTYPE unsigned char +#define VNAME 2DC + +// Constructors/Destructors +inline Vector2DC::Vector2DC() {x=0; y=0;} +inline Vector2DC::~Vector2DC() {} +inline Vector2DC::Vector2DC (VTYPE xa, VTYPE ya) {x=xa; y=ya;} +inline Vector2DC::Vector2DC (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DC::Vector2DC (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DC::Vector2DC (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DC::Vector2DC (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DC::Vector2DC (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DC::Vector2DC (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DC::Vector2DC (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} + +// Member Functions +inline Vector2DC &Vector2DC::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} + +inline Vector2DC &Vector2DC::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} + +inline Vector2DC &Vector2DC::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} + +inline Vector2DC &Vector2DC::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} + +inline Vector2DC &Vector2DC::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DC &Vector2DC::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} + +// Note: Cross product does not exist for 2D vectors (only 3D) + +inline double Vector2DC::Dot(Vector2DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} +inline double Vector2DC::Dot(Vector2DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} +inline double Vector2DC::Dot(Vector2DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} + +inline double Vector2DC::Dist (Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DC::Dist (Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DC::Dist (Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DC::Dist (Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DC::Dist (Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DC::Dist (Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DC::Dist (Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DC::DistSq (Vector2DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DC::DistSq (Vector2DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DC::DistSq (Vector2DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DC::DistSq (Vector3DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DC::DistSq (Vector3DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DC::DistSq (Vector3DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DC::DistSq (Vector4DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} + +inline Vector2DC &Vector2DC::Normalize (void) { + double n = (double) x*x + (double) y*y; + if (n!=0.0) { + n = sqrt(n); + x = (VTYPE) (((double) x*255)/n); + y = (VTYPE) (((double) y*255)/n); + } + return *this; +} +inline double Vector2DC::Length (void) { double n; n = (double) x*x + (double) y*y; if (n != 0.0) return sqrt(n); return 0.0; } + +inline VTYPE &Vector2DC::X(void) {return x;} +inline VTYPE &Vector2DC::Y(void) {return y;} +inline VTYPE Vector2DC::Z(void) {return 0;} +inline VTYPE Vector2DC::W(void) {return 0;} +inline const VTYPE &Vector2DC::X(void) const {return x;} +inline const VTYPE &Vector2DC::Y(void) const {return y;} +inline const VTYPE Vector2DC::Z(void) const {return 0;} +inline const VTYPE Vector2DC::W(void) const {return 0;} +inline VTYPE *Vector2DC::Data (void) {return &x;} + +#undef VTYPE +#undef VNAME + +// Vector2DI Code Definition + +#define VNAME 2DI +#define VTYPE int + +// Constructors/Destructors +inline Vector2DI::Vector2DI() {x=0; y=0;} +inline Vector2DI::~Vector2DI() {} +inline Vector2DI::Vector2DI (VTYPE xa, VTYPE ya) {x=xa; y=ya;} +inline Vector2DI::Vector2DI (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DI::Vector2DI (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DI::Vector2DI (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DI::Vector2DI (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DI::Vector2DI (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DI::Vector2DI (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DI::Vector2DI (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} + +// Member Functions +inline Vector2DI &Vector2DI::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} + +inline Vector2DI &Vector2DI::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} + +inline Vector2DI &Vector2DI::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} + +inline Vector2DI &Vector2DI::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} + +inline Vector2DI &Vector2DI::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DI &Vector2DI::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} + +// Note: Cross product does not exist for 2D vectors (only 3D) + +inline double Vector2DI::Dot(Vector2DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} +inline double Vector2DI::Dot(Vector2DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} +inline double Vector2DI::Dot(Vector2DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} + +inline double Vector2DI::Dist (Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DI::Dist (Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DI::Dist (Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DI::Dist (Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DI::Dist (Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DI::Dist (Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DI::Dist (Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DI::DistSq (Vector2DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DI::DistSq (Vector2DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DI::DistSq (Vector2DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DI::DistSq (Vector3DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DI::DistSq (Vector3DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DI::DistSq (Vector3DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DI::DistSq (Vector4DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} + +inline Vector2DI &Vector2DI::Normalize (void) { + double n = (double) x*x + (double) y*y; + if (n!=0.0) { + n = sqrt(n); + x = (VTYPE) (((double) x*255)/n); + y = (VTYPE) (((double) y*255)/n); + } + return *this; +} +inline double Vector2DI::Length (void) { double n; n = (double) x*x + (double) y*y; if (n != 0.0) return sqrt(n); return 0.0; } + +inline VTYPE &Vector2DI::X(void) {return x;} +inline VTYPE &Vector2DI::Y(void) {return y;} +inline VTYPE Vector2DI::Z(void) {return 0;} +inline VTYPE Vector2DI::W(void) {return 0;} +inline const VTYPE &Vector2DI::X(void) const {return x;} +inline const VTYPE &Vector2DI::Y(void) const {return y;} +inline const VTYPE Vector2DI::Z(void) const {return 0;} +inline const VTYPE Vector2DI::W(void) const {return 0;} +inline VTYPE *Vector2DI::Data (void) {return &x;} + +#undef VTYPE +#undef VNAME + +// Vector2DF Code Definition + +#define VNAME 2DF +#define VTYPE double + +// Constructors/Destructors +inline Vector2DF::Vector2DF() {x=0; y=0;} +inline Vector2DF::~Vector2DF() {} +inline Vector2DF::Vector2DF (const VTYPE xa, const VTYPE ya) {x=xa; y=ya;} +inline Vector2DF::Vector2DF (const Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DF::Vector2DF (const Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DF::Vector2DF (const Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DF::Vector2DF (const Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DF::Vector2DF (const Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DF::Vector2DF (const Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} +inline Vector2DF::Vector2DF (const Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y;} + +// Member Functions +inline Vector2DF &Vector2DF::operator= (const Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator= (const Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator= (const Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator= (const Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator= (const Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator= (const Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator= (const Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} + +inline Vector2DF &Vector2DF::operator+= (const Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator+= (const Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator+= (const Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator+= (const Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator+= (const Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator+= (const Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator+= (const Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} + +inline Vector2DF &Vector2DF::operator-= (const Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator-= (const Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator-= (const Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator-= (const Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator-= (const Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator-= (const Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator-= (const Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} + +inline Vector2DF &Vector2DF::operator*= (const Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator*= (const Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator*= (const Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator*= (const Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator*= (const Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator*= (const Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator*= (const Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} + +inline Vector2DF &Vector2DF::operator/= (const Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator/= (const Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator/= (const Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator/= (const Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator/= (const Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator/= (const Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector2DF &Vector2DF::operator/= (const Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} + +// Note: Cross product does not exist for 2D vectors (only 3D) + +inline double Vector2DF::Dot(const Vector2DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} +inline double Vector2DF::Dot(const Vector2DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} +inline double Vector2DF::Dot(const Vector2DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y; return dot;} + +inline double Vector2DF::Dist (const Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DF::Dist (const Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DF::Dist (const Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DF::Dist (const Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DF::Dist (const Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DF::Dist (const Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DF::Dist (const Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector2DF::DistSq (const Vector2DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DF::DistSq (const Vector2DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DF::DistSq (const Vector2DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DF::DistSq (const Vector3DC &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DF::DistSq (const Vector3DI &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DF::DistSq (const Vector3DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} +inline double Vector2DF::DistSq (const Vector4DF &v) { double a,b; a = (double) x - (double) v.x; b = (double) y - (double) v.y; return (a*a + b*b);} + +inline Vector2DF &Vector2DF::Normalize (void) { + double n = (double) x*x + (double) y*y; + if (n!=0.0) { + n = sqrt(n); + x /= n; + y /= n; + } + return *this; +} +inline double Vector2DF::Length (void) { double n; n = (double) x*x + (double) y*y; if (n != 0.0) return sqrt(n); return 0.0; } + +inline VTYPE &Vector2DF::X(void) {return x;} +inline VTYPE &Vector2DF::Y(void) {return y;} +inline VTYPE Vector2DF::Z(void) {return 0;} +inline VTYPE Vector2DF::W(void) {return 0;} +inline const VTYPE &Vector2DF::X(void) const {return x;} +inline const VTYPE &Vector2DF::Y(void) const {return y;} +inline const VTYPE Vector2DF::Z(void) const {return 0;} +inline const VTYPE Vector2DF::W(void) const {return 0;} +inline VTYPE *Vector2DF::Data (void) {return &x;} + +#undef VTYPE +#undef VNAME + +// Vector3DC Code Definition + +#define VNAME 3DC +#define VTYPE unsigned char + +// Constructors/Destructors +inline Vector3DC::Vector3DC() {x=0; y=0; z=0;} +inline Vector3DC::~Vector3DC() {} +inline Vector3DC::Vector3DC (VTYPE xa, VTYPE ya, VTYPE za) {x=xa; y=ya; z=za;} +inline Vector3DC::Vector3DC (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DC::Vector3DC (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DC::Vector3DC (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DC::Vector3DC (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DC::Vector3DC (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DC::Vector3DC (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DC::Vector3DC (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} + +// Member Functions +inline Vector3DC &Vector3DC::Set (VTYPE xa, VTYPE ya, VTYPE za) {x=xa; y=ya; z=za; return *this;} + +inline Vector3DC &Vector3DC::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; return *this;} +inline Vector3DC &Vector3DC::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; return *this;} +inline Vector3DC &Vector3DC::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; return *this;} +inline Vector3DC &Vector3DC::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} + +inline Vector3DC &Vector3DC::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} + +inline Vector3DC &Vector3DC::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} + +inline Vector3DC &Vector3DC::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} + +inline Vector3DC &Vector3DC::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DC &Vector3DC::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DC &Vector3DC::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} + +inline Vector3DC &Vector3DC::Cross (Vector3DC &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} +inline Vector3DC &Vector3DC::Cross (Vector3DI &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} +inline Vector3DC &Vector3DC::Cross (Vector3DF &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} + +inline double Vector3DC::Dot(Vector3DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} +inline double Vector3DC::Dot(Vector3DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} +inline double Vector3DC::Dot(Vector3DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} + +inline double Vector3DC::Dist (Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DC::Dist (Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DC::Dist (Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DC::Dist (Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DC::Dist (Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DC::Dist (Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DC::Dist (Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DC::DistSq (Vector2DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DC::DistSq (Vector2DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DC::DistSq (Vector2DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DC::DistSq (Vector3DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DC::DistSq (Vector3DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DC::DistSq (Vector3DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DC::DistSq (Vector4DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} + +inline Vector3DC &Vector3DC::Normalize (void) { + double n = (double) x*x + (double) y*y + (double) z*z; + if (n!=0.0) { + n = sqrt(n); + x = (VTYPE) (((double) x*255)/n); + y = (VTYPE) (((double) y*255)/n); + z = (VTYPE) (((double) z*255)/n); + } + return *this; +} +inline double Vector3DC::Length (void) { double n; n = (double) x*x + (double) y*y + (double) z*z; if (n != 0.0) return sqrt(n); return 0.0; } + +inline VTYPE &Vector3DC::X(void) {return x;} +inline VTYPE &Vector3DC::Y(void) {return y;} +inline VTYPE &Vector3DC::Z(void) {return z;} +inline VTYPE Vector3DC::W(void) {return 0;} +inline const VTYPE &Vector3DC::X(void) const {return x;} +inline const VTYPE &Vector3DC::Y(void) const {return y;} +inline const VTYPE &Vector3DC::Z(void) const {return z;} +inline const VTYPE Vector3DC::W(void) const {return 0;} +inline VTYPE *Vector3DC::Data (void) {return &x;} + +#undef VTYPE +#undef VNAME + +// Vector3DI Code Definition + +#define VNAME 3DI +#define VTYPE int + +// Constructors/Destructors +inline Vector3DI::Vector3DI() {x=0; y=0; z=0;} +inline Vector3DI::~Vector3DI() {} +inline Vector3DI::Vector3DI (VTYPE xa, VTYPE ya, VTYPE za) {x=xa; y=ya; z=za;} +inline Vector3DI::Vector3DI (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DI::Vector3DI (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DI::Vector3DI (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DI::Vector3DI (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DI::Vector3DI (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DI::Vector3DI (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DI::Vector3DI (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} + +// Set Functions +inline Vector3DI &Vector3DI::Set (const int xa, const int ya, const int za) +{ + x = xa; y = ya; z = za; + return *this; +} + +// Member Functions +inline Vector3DI &Vector3DI::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} + +inline Vector3DI &Vector3DI::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} + +inline Vector3DI &Vector3DI::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} + +inline Vector3DI &Vector3DI::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} + +inline Vector3DI &Vector3DI::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DI &Vector3DI::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DI &Vector3DI::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} + +inline Vector3DI &Vector3DI::Cross (Vector3DC &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} +inline Vector3DI &Vector3DI::Cross (Vector3DI &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} +inline Vector3DI &Vector3DI::Cross (Vector3DF &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} + +inline double Vector3DI::Dot(Vector3DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} +inline double Vector3DI::Dot(Vector3DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} +inline double Vector3DI::Dot(Vector3DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} + +inline double Vector3DI::Dist (Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DI::Dist (Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DI::Dist (Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DI::Dist (Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DI::Dist (Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DI::Dist (Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DI::Dist (Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DI::DistSq (Vector2DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DI::DistSq (Vector2DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DI::DistSq (Vector2DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DI::DistSq (Vector3DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DI::DistSq (Vector3DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DI::DistSq (Vector3DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DI::DistSq (Vector4DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} + +inline Vector3DI &Vector3DI::Normalize (void) { + double n = (double) x*x + (double) y*y + (double) z*z; + if (n!=0.0) { + n = sqrt(n); + x = (VTYPE) (((double) x*255)/n); + y = (VTYPE) (((double) y*255)/n); + z = (VTYPE) (((double) z*255)/n); + } + return *this; +} +inline double Vector3DI::Length (void) { double n; n = (double) x*x + (double) y*y + (double) z*z; if (n != 0.0) return sqrt(n); return 0.0; } + +inline VTYPE &Vector3DI::X(void) {return x;} +inline VTYPE &Vector3DI::Y(void) {return y;} +inline VTYPE &Vector3DI::Z(void) {return z;} +inline VTYPE Vector3DI::W(void) {return 0;} +inline const VTYPE &Vector3DI::X(void) const {return x;} +inline const VTYPE &Vector3DI::Y(void) const {return y;} +inline const VTYPE &Vector3DI::Z(void) const {return z;} +inline const VTYPE Vector3DI::W(void) const {return 0;} +inline VTYPE *Vector3DI::Data (void) {return &x;} + +#undef VTYPE +#undef VNAME + +// Vector3DF Code Definition + +#define VNAME 3DF +#define VTYPE float + +// Constructors/Destructors +inline Vector3DF::Vector3DF() {x=0; y=0; z=0;} +inline Vector3DF::~Vector3DF() {} +inline Vector3DF::Vector3DF (const VTYPE xa, const VTYPE ya, const VTYPE za) {x=xa; y=ya; z=za;} +inline Vector3DF::Vector3DF (const Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DF::Vector3DF (const Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DF::Vector3DF (const Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0;} +inline Vector3DF::Vector3DF (const Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DF::Vector3DF (const Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DF::Vector3DF (const Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} +inline Vector3DF::Vector3DF (const Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z;} + +// Set Functions +inline Vector3DF &Vector3DF::Set (const double xa, const double ya, const double za) +{ + x = (float) xa; y = (float) ya; z = (float) za; + return *this; +} + +// Member Functions +inline Vector3DF &Vector3DF::operator= (const int op) {x= (VTYPE) op; y= (VTYPE) op; z= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator= (const double op) {x= (VTYPE) op; y= (VTYPE) op; z= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator= (const Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator= (const Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator= (const Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator= (const Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator= (const Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator= (const Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator= (const Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; return *this;} + +inline Vector3DF &Vector3DF::operator+= (const int op) {x+= (VTYPE) op; y+= (VTYPE) op; z+= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator+= (const double op) {x+= (VTYPE) op; y+= (VTYPE) op; z+= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator+= (const Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator+= (const Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator+= (const Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator+= (const Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator+= (const Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator+= (const Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator+= (const Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} + +inline Vector3DF &Vector3DF::operator-= (const int op) {x-= (VTYPE) op; y-= (VTYPE) op; z-= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator-= (const double op) {x-= (VTYPE) op; y-= (VTYPE) op; z-= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator-= (const Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator-= (const Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator-= (const Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator-= (const Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator-= (const Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator-= (const Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator-= (const Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} + +inline Vector3DF &Vector3DF::operator*= (const int op) {x*= (VTYPE) op; y*= (VTYPE) op; z*= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator*= (const double op) {x*= (VTYPE) op; y*= (VTYPE) op; z*= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator*= (const Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator*= (const Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator*= (const Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator*= (const Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator*= (const Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator*= (const Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator*= (const Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} + +inline Vector3DF &Vector3DF::operator/= (const int op) {x/= (VTYPE) op; y/= (VTYPE) op; z/= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator/= (const double op) {x/= (VTYPE) op; y/= (VTYPE) op; z/= (VTYPE) op; return *this;} +inline Vector3DF &Vector3DF::operator/= (const Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator/= (const Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator/= (const Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector3DF &Vector3DF::operator/= (const Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator/= (const Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator/= (const Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector3DF &Vector3DF::operator/= (const Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} + +inline Vector3DF &Vector3DF::Cross (const Vector3DC &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} +inline Vector3DF &Vector3DF::Cross (const Vector3DI &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} +inline Vector3DF &Vector3DF::Cross (const Vector3DF &v) {double ax = x, ay = y, az = z; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); return *this;} + +inline double Vector3DF::Dot(const Vector3DC &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} +inline double Vector3DF::Dot(const Vector3DI &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} +inline double Vector3DF::Dot(const Vector3DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z; return dot;} + +inline double Vector3DF::Dist (const Vector2DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DF::Dist (const Vector2DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DF::Dist (const Vector2DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DF::Dist (const Vector3DC &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DF::Dist (const Vector3DI &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DF::Dist (const Vector3DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DF::Dist (const Vector4DF &v) { double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} +inline double Vector3DF::DistSq (const Vector2DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DF::DistSq (const Vector2DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DF::DistSq (const Vector2DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z; return (a*a + b*b + c*c);} +inline double Vector3DF::DistSq (const Vector3DC &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DF::DistSq (const Vector3DI &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DF::DistSq (const Vector3DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} +inline double Vector3DF::DistSq (const Vector4DF &v) { double a,b,c; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; return (a*a + b*b + c*c);} + +inline Vector3DF &Vector3DF::Normalize (void) { + double n = (double) x*x + (double) y*y + (double) z*z; + if (n!=0.0) { + n = sqrt(n); + x /= (float) n; y /= (float) n; z /= (float) n; + } + return *this; +} +inline double Vector3DF::Length (void) { double n; n = (double) x*x + (double) y*y + (double) z*z; if (n != 0.0) return sqrt(n); return 0.0; } + +inline VTYPE &Vector3DF::X() {return x;} +inline VTYPE &Vector3DF::Y() {return y;} +inline VTYPE &Vector3DF::Z() {return z;} +inline VTYPE Vector3DF::W() {return 0;} +inline const VTYPE &Vector3DF::X() const {return x;} +inline const VTYPE &Vector3DF::Y() const {return y;} +inline const VTYPE &Vector3DF::Z() const {return z;} +inline const VTYPE Vector3DF::W() const {return 0;} +inline VTYPE *Vector3DF::Data () {return &x;} + +#undef VTYPE +#undef VNAME + +// Vector4DF Code Definition + +#define VNAME 4DF +#define VTYPE double + +// Constructors/Destructors +inline Vector4DF::Vector4DF() {x=0; y=0; z=0; w=0;} +inline Vector4DF::~Vector4DF() {} +inline Vector4DF::Vector4DF (VTYPE xa, VTYPE ya, VTYPE za, VTYPE wa) {x=xa; y=ya; z=za; w=wa;} +inline Vector4DF::Vector4DF (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0;} +inline Vector4DF::Vector4DF (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0;} +inline Vector4DF::Vector4DF (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0;} +inline Vector4DF::Vector4DF (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0;} +inline Vector4DF::Vector4DF (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0;} +inline Vector4DF::Vector4DF (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0;} +inline Vector4DF::Vector4DF (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) op.w;} + +// Member Functions +inline Vector4DF &Vector4DF::operator= (int op) {x= (VTYPE) op; y= (VTYPE) op; z= (VTYPE) op; w = (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator= (double op) {x= (VTYPE) op; y= (VTYPE) op; z= (VTYPE) op; w = (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator= (Vector2DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0; return *this;} +inline Vector4DF &Vector4DF::operator= (Vector2DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0; return *this;} +inline Vector4DF &Vector4DF::operator= (Vector2DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) 0; w=(VTYPE) 0; return *this;} +inline Vector4DF &Vector4DF::operator= (Vector3DC &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0; return *this;} +inline Vector4DF &Vector4DF::operator= (Vector3DI &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0; return *this;} +inline Vector4DF &Vector4DF::operator= (Vector3DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) 0; return *this;} +inline Vector4DF &Vector4DF::operator= (Vector4DF &op) {x=(VTYPE) op.x; y=(VTYPE) op.y; z=(VTYPE) op.z; w=(VTYPE) op.w; return *this;} + +inline Vector4DF &Vector4DF::operator+= (int op) {x+= (VTYPE) op; y+= (VTYPE) op; z+= (VTYPE) op; w += (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator+= (double op) {x+= (VTYPE) op; y+= (VTYPE) op; z+= (VTYPE) op; w += (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator+= (Vector2DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator+= (Vector2DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator+= (Vector2DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator+= (Vector3DC &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator+= (Vector3DI &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator+= (Vector3DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator+= (Vector4DF &op) {x+=(VTYPE) op.x; y+=(VTYPE) op.y; z+=(VTYPE) op.z; w+=(VTYPE) op.w; return *this;} + +inline Vector4DF &Vector4DF::operator-= (int op) {x-= (VTYPE) op; y-= (VTYPE) op; z-= (VTYPE) op; w -= (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator-= (double op) {x-= (VTYPE) op; y-= (VTYPE) op; z-= (VTYPE) op; w -= (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator-= (Vector2DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator-= (Vector2DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator-= (Vector2DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator-= (Vector3DC &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator-= (Vector3DI &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator-= (Vector3DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator-= (Vector4DF &op) {x-=(VTYPE) op.x; y-=(VTYPE) op.y; z-=(VTYPE) op.z; w-=(VTYPE) op.w; return *this;} + +inline Vector4DF &Vector4DF::operator*= (int op) {x*= (VTYPE) op; y*= (VTYPE) op; z*= (VTYPE) op; w *= (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator*= (double op) {x*= (VTYPE) op; y*= (VTYPE) op; z*= (VTYPE) op; w *= (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator*= (Vector2DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator*= (Vector2DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator*= (Vector2DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator*= (Vector3DC &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator*= (Vector3DI &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator*= (Vector3DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator*= (Vector4DF &op) {x*=(VTYPE) op.x; y*=(VTYPE) op.y; z*=(VTYPE) op.z; w*=(VTYPE) op.w; return *this;} + +inline Vector4DF &Vector4DF::operator/= (int op) {x/= (VTYPE) op; y/= (VTYPE) op; z/= (VTYPE) op; w /= (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator/= (double op) {x/= (VTYPE) op; y/= (VTYPE) op; z/= (VTYPE) op; w /= (VTYPE) op; return *this;} +inline Vector4DF &Vector4DF::operator/= (Vector2DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator/= (Vector2DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator/= (Vector2DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; return *this;} +inline Vector4DF &Vector4DF::operator/= (Vector3DC &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator/= (Vector3DI &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator/= (Vector3DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; return *this;} +inline Vector4DF &Vector4DF::operator/= (Vector4DF &op) {x/=(VTYPE) op.x; y/=(VTYPE) op.y; z/=(VTYPE) op.z; w/=(VTYPE) op.w; return *this;} + +inline Vector4DF &Vector4DF::Cross (Vector4DF &v) {double ax = x, ay = y, az = z, aw = w; x = (VTYPE) (ay * (double) v.z - az * (double) v.y); y = (VTYPE) (-ax * (double) v.z + az * (double) v.x); z = (VTYPE) (ax * (double) v.y - ay * (double) v.x); w = (VTYPE) 0; return *this;} + +inline double Vector4DF::Dot(Vector4DF &v) {double dot; dot = (double) x*v.x + (double) y*v.y + (double) z*v.z + (double) w*v.w; return dot;} + +inline double Vector4DF::Dist (Vector4DF &v) {double distsq = DistSq (v); if (distsq!=0) return sqrt(distsq); return 0.0;} + +inline double Vector4DF::DistSq (Vector4DF &v) {double a,b,c,d; a = (double) x - (double) v.x; b = (double) y - (double) v.y; c = (double) z - (double) v.z; d = (double) w - (double) v.w; return (a*a + b*b + c*c + d*d);} + +inline Vector4DF &Vector4DF::Normalize (void) { + double n = (double) x*x + (double) y*y + (double) z*z + (double) w*w; + if (n!=0.0) { + n = sqrt(n); + x /= n; y /= n; z /= n; w /= n; + } + return *this; +} +inline double Vector4DF::Length (void) { double n; n = (double) x*x + (double) y*y + (double) z*z + (double) w*w; if (n != 0.0) return sqrt(n); return 0.0; } + +inline VTYPE &Vector4DF::X(void) {return x;} +inline VTYPE &Vector4DF::Y(void) {return y;} +inline VTYPE &Vector4DF::Z(void) {return z;} +inline VTYPE &Vector4DF::W(void) {return w;} +inline const VTYPE &Vector4DF::X(void) const {return x;} +inline const VTYPE &Vector4DF::Y(void) const {return y;} +inline const VTYPE &Vector4DF::Z(void) const {return z;} +inline const VTYPE &Vector4DF::W(void) const {return w;} +inline VTYPE *Vector4DF::Data (void) {return &x;} + +#undef VTYPE +#undef VNAME diff --git a/Extras/sph/common/vector.cpp b/Extras/sph/common/vector.cpp new file mode 100644 index 0000000..4cfc7b9 --- /dev/null +++ b/Extras/sph/common/vector.cpp @@ -0,0 +1,70 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 "vector.h" +#include "matrix.h" + +Vector3DF &Vector3DF::operator*= (const MatrixF &op) +{ + double *m = op.GetDataF (); + double xa, ya, za; + xa = x * (*m++); ya = x * (*m++); za = x * (*m++); m++; + xa += y * (*m++); ya += y * (*m++); za += y * (*m++); m++; + xa += z * (*m++); ya += z * (*m++); za += z * (*m++); m++; + xa += (*m++); ya += (*m++); za += (*m++); + x = (float) xa; y = (float) ya; z = (float) za; + return *this; +} + +Vector3DF &Vector3DF::operator*= (const Matrix4F &op) +{ + float xa, ya, za; + xa = x * op.data[0] + y * op.data[4] + z * op.data[8] + op.data[12]; + ya = x * op.data[1] + y * op.data[5] + z * op.data[9] + op.data[13]; + za = x * op.data[2] + y * op.data[6] + z * op.data[10] + op.data[14]; + x = xa; y = ya; z = za; + return *this; +} + +Vector4DF &Vector4DF::operator*= (const MatrixF &op) +{ + double *m = op.GetDataF (); + double xa, ya, za, wa; + xa = x * (*m++); ya = x * (*m++); za = x * (*m++); wa = x * (*m++); + xa += y * (*m++); ya += y * (*m++); za += y * (*m++); wa += y * (*m++); + xa += z * (*m++); ya += z * (*m++); za += z * (*m++); wa += z * (*m++); + xa += w * (*m++); ya += w * (*m++); za += w * (*m++); wa += w * (*m++); + x = xa; y = ya; z = za; w = wa; + return *this; +} + +Vector4DF &Vector4DF::operator*= (const Matrix4F &op) +{ + double xa, ya, za, wa; + xa = x * op.data[0] + y * op.data[4] + z * op.data[8] + w * op.data[12]; + ya = x * op.data[1] + y * op.data[5] + z * op.data[9] + w * op.data[13]; + za = x * op.data[2] + y * op.data[6] + z * op.data[10] + w * op.data[14]; + wa = x * op.data[3] + y * op.data[7] + z * op.data[11] + w * op.data[15]; + x = xa; y = ya; z = za; w = wa; + return *this; +} + diff --git a/Extras/sph/common/vector.h b/Extras/sph/common/vector.h new file mode 100644 index 0000000..2c8c0bf --- /dev/null +++ b/Extras/sph/common/vector.h @@ -0,0 +1,785 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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. +*/ +// ** NOTES ** +// Vector code CANNOT be inlined in header file because of dependencies +// across vector classes (error generated: "Use of undeclared class..") +// +#include +#include +#include +#include +#include + +#ifndef VECTOR_DEF + #define VECTOR_DEF + + //#define VECTOR_INITIALIZE // Initializes vectors + + class Vector2DC; // Forward Referencing + class Vector2DI; + class Vector2DF; + class Vector3DC; + class Vector3DI; + class Vector3DF; + class Vector4DF; + class MatrixF; + class Matrix4F; + + // Vector2DC Declaration + + #define VNAME 2DC + #define VTYPE unsigned char + + class Vector2DC { + public: + VTYPE x, y; + + // Constructors/Destructors + inline Vector2DC(); + inline ~Vector2DC(); + inline Vector2DC (VTYPE xa, VTYPE ya); + inline Vector2DC (Vector2DC &op); + inline Vector2DC (Vector2DI &op); + inline Vector2DC (Vector2DF &op); + inline Vector2DC (Vector3DC &op); + inline Vector2DC (Vector3DI &op); + inline Vector2DC (Vector3DF &op); + inline Vector2DC (Vector4DF &op); + + // Member Functions + inline Vector2DC &operator= (Vector2DC &op); + inline Vector2DC &operator= (Vector2DI &op); + inline Vector2DC &operator= (Vector2DF &op); + inline Vector2DC &operator= (Vector3DC &op); + inline Vector2DC &operator= (Vector3DI &op); + inline Vector2DC &operator= (Vector3DF &op); + inline Vector2DC &operator= (Vector4DF &op); + + inline Vector2DC &operator+= (Vector2DC &op); + inline Vector2DC &operator+= (Vector2DI &op); + inline Vector2DC &operator+= (Vector2DF &op); + inline Vector2DC &operator+= (Vector3DC &op); + inline Vector2DC &operator+= (Vector3DI &op); + inline Vector2DC &operator+= (Vector3DF &op); + inline Vector2DC &operator+= (Vector4DF &op); + + inline Vector2DC &operator-= (Vector2DC &op); + inline Vector2DC &operator-= (Vector2DI &op); + inline Vector2DC &operator-= (Vector2DF &op); + inline Vector2DC &operator-= (Vector3DC &op); + inline Vector2DC &operator-= (Vector3DI &op); + inline Vector2DC &operator-= (Vector3DF &op); + inline Vector2DC &operator-= (Vector4DF &op); + + inline Vector2DC &operator*= (Vector2DC &op); + inline Vector2DC &operator*= (Vector2DI &op); + inline Vector2DC &operator*= (Vector2DF &op); + inline Vector2DC &operator*= (Vector3DC &op); + inline Vector2DC &operator*= (Vector3DI &op); + inline Vector2DC &operator*= (Vector3DF &op); + inline Vector2DC &operator*= (Vector4DF &op); + + inline Vector2DC &operator/= (Vector2DC &op); + inline Vector2DC &operator/= (Vector2DI &op); + inline Vector2DC &operator/= (Vector2DF &op); + inline Vector2DC &operator/= (Vector3DC &op); + inline Vector2DC &operator/= (Vector3DI &op); + inline Vector2DC &operator/= (Vector3DF &op); + inline Vector2DC &operator/= (Vector4DF &op); + + // Note: Cross product does not exist for 2D vectors (only 3D) + + inline double Dot(Vector2DC &v); + inline double Dot(Vector2DI &v); + inline double Dot(Vector2DF &v); + + inline double Dist (Vector2DC &v); + inline double Dist (Vector2DI &v); + inline double Dist (Vector2DF &v); + inline double Dist (Vector3DC &v); + inline double Dist (Vector3DI &v); + inline double Dist (Vector3DF &v); + inline double Dist (Vector4DF &v); + + inline double DistSq (Vector2DC &v); + inline double DistSq (Vector2DI &v); + inline double DistSq (Vector2DF &v); + inline double DistSq (Vector3DC &v); + inline double DistSq (Vector3DI &v); + inline double DistSq (Vector3DF &v); + inline double DistSq (Vector4DF &v); + + inline Vector2DC &Normalize (void); + inline double Length (void); + + inline VTYPE &X(void); + inline VTYPE &Y(void); + inline VTYPE Z(void); + inline VTYPE W(void); + inline const VTYPE &X(void) const; + inline const VTYPE &Y(void) const; + inline const VTYPE Z(void) const; + inline const VTYPE W(void) const; + inline VTYPE *Data (void); + }; + + #undef VNAME + #undef VTYPE + + // Vector2DI Declaration + + #define VNAME 2DI + #define VTYPE int + + class Vector2DI { + public: + VTYPE x, y; + + // Constructors/Destructors + inline Vector2DI(); + inline ~Vector2DI(); + inline Vector2DI (VTYPE xa, VTYPE ya); + inline Vector2DI (Vector2DC &op); + inline Vector2DI (Vector2DI &op); + inline Vector2DI (Vector2DF &op); + inline Vector2DI (Vector3DC &op); + inline Vector2DI (Vector3DI &op); + inline Vector2DI (Vector3DF &op); + inline Vector2DI (Vector4DF &op); + + // Member Functions + inline Vector2DI &operator= (Vector2DC &op); + inline Vector2DI &operator= (Vector2DI &op); + inline Vector2DI &operator= (Vector2DF &op); + inline Vector2DI &operator= (Vector3DC &op); + inline Vector2DI &operator= (Vector3DI &op); + inline Vector2DI &operator= (Vector3DF &op); + inline Vector2DI &operator= (Vector4DF &op); + + inline Vector2DI &operator+= (Vector2DC &op); + inline Vector2DI &operator+= (Vector2DI &op); + inline Vector2DI &operator+= (Vector2DF &op); + inline Vector2DI &operator+= (Vector3DC &op); + inline Vector2DI &operator+= (Vector3DI &op); + inline Vector2DI &operator+= (Vector3DF &op); + inline Vector2DI &operator+= (Vector4DF &op); + + inline Vector2DI &operator-= (Vector2DC &op); + inline Vector2DI &operator-= (Vector2DI &op); + inline Vector2DI &operator-= (Vector2DF &op); + inline Vector2DI &operator-= (Vector3DC &op); + inline Vector2DI &operator-= (Vector3DI &op); + inline Vector2DI &operator-= (Vector3DF &op); + inline Vector2DI &operator-= (Vector4DF &op); + + inline Vector2DI &operator*= (Vector2DC &op); + inline Vector2DI &operator*= (Vector2DI &op); + inline Vector2DI &operator*= (Vector2DF &op); + inline Vector2DI &operator*= (Vector3DC &op); + inline Vector2DI &operator*= (Vector3DI &op); + inline Vector2DI &operator*= (Vector3DF &op); + inline Vector2DI &operator*= (Vector4DF &op); + + inline Vector2DI &operator/= (Vector2DC &op); + inline Vector2DI &operator/= (Vector2DI &op); + inline Vector2DI &operator/= (Vector2DF &op); + inline Vector2DI &operator/= (Vector3DC &op); + inline Vector2DI &operator/= (Vector3DI &op); + inline Vector2DI &operator/= (Vector3DF &op); + inline Vector2DI &operator/= (Vector4DF &op); + + + // Note: Cross product does not exist for 2D vectors (only 3D) + + inline double Dot(Vector2DC &v); + inline double Dot(Vector2DI &v); + inline double Dot(Vector2DF &v); + + inline double Dist (Vector2DC &v); + inline double Dist (Vector2DI &v); + inline double Dist (Vector2DF &v); + inline double Dist (Vector3DC &v); + inline double Dist (Vector3DI &v); + inline double Dist (Vector3DF &v); + inline double Dist (Vector4DF &v); + + inline double DistSq (Vector2DC &v); + inline double DistSq (Vector2DI &v); + inline double DistSq (Vector2DF &v); + inline double DistSq (Vector3DC &v); + inline double DistSq (Vector3DI &v); + inline double DistSq (Vector3DF &v); + inline double DistSq (Vector4DF &v); + + inline Vector2DI &Normalize (void); + inline double Length (void); + + inline VTYPE &X(void); + inline VTYPE &Y(void); + inline VTYPE Z(void); + inline VTYPE W(void); + inline const VTYPE &X(void) const; + inline const VTYPE &Y(void) const; + inline const VTYPE Z(void) const; + inline const VTYPE W(void) const; + inline VTYPE *Data (void); + }; + + #undef VNAME + #undef VTYPE + + // Vector2DF Declarations + + #define VNAME 2DF + #define VTYPE double + + class Vector2DF { + public: + VTYPE x, y; + + // Constructors/Destructors + Vector2DF (); + ~Vector2DF (); + Vector2DF (const VTYPE xa, const VTYPE ya); + Vector2DF (const Vector2DC &op); + Vector2DF (const Vector2DI &op); + Vector2DF (const Vector2DF &op); + Vector2DF (const Vector3DC &op); + Vector2DF (const Vector3DI &op); + Vector2DF (const Vector3DF &op); + Vector2DF (const Vector4DF &op); + + // Member Functions + Vector2DF &operator= (const Vector2DC &op); + Vector2DF &operator= (const Vector2DI &op); + Vector2DF &operator= (const Vector2DF &op); + Vector2DF &operator= (const Vector3DC &op); + Vector2DF &operator= (const Vector3DI &op); + Vector2DF &operator= (const Vector3DF &op); + Vector2DF &operator= (const Vector4DF &op); + + Vector2DF &operator+= (const Vector2DC &op); + Vector2DF &operator+= (const Vector2DI &op); + Vector2DF &operator+= (const Vector2DF &op); + Vector2DF &operator+= (const Vector3DC &op); + Vector2DF &operator+= (const Vector3DI &op); + Vector2DF &operator+= (const Vector3DF &op); + Vector2DF &operator+= (const Vector4DF &op); + + Vector2DF &operator-= (const Vector2DC &op); + Vector2DF &operator-= (const Vector2DI &op); + Vector2DF &operator-= (const Vector2DF &op); + Vector2DF &operator-= (const Vector3DC &op); + Vector2DF &operator-= (const Vector3DI &op); + Vector2DF &operator-= (const Vector3DF &op); + Vector2DF &operator-= (const Vector4DF &op); + + Vector2DF &operator*= (const Vector2DC &op); + Vector2DF &operator*= (const Vector2DI &op); + Vector2DF &operator*= (const Vector2DF &op); + Vector2DF &operator*= (const Vector3DC &op); + Vector2DF &operator*= (const Vector3DI &op); + Vector2DF &operator*= (const Vector3DF &op); + Vector2DF &operator*= (const Vector4DF &op); + + Vector2DF &operator/= (const Vector2DC &op); + Vector2DF &operator/= (const Vector2DI &op); + Vector2DF &operator/= (const Vector2DF &op); + Vector2DF &operator/= (const Vector3DC &op); + Vector2DF &operator/= (const Vector3DI &op); + Vector2DF &operator/= (const Vector3DF &op); + Vector2DF &operator/= (const Vector4DF &op); + + Vector2DF &operator/= (const double v) {x /= v; y /= v; return *this;} + + // Note: Cross product does not exist for 2D vectors (only 3D) + + double Dot(const Vector2DC &v); + double Dot(const Vector2DI &v); + double Dot(const Vector2DF &v); + + double Dist (const Vector2DC &v); + double Dist (const Vector2DI &v); + double Dist (const Vector2DF &v); + double Dist (const Vector3DC &v); + double Dist (const Vector3DI &v); + double Dist (const Vector3DF &v); + double Dist (const Vector4DF &v); + + double DistSq (const Vector2DC &v); + double DistSq (const Vector2DI &v); + double DistSq (const Vector2DF &v); + double DistSq (const Vector3DC &v); + double DistSq (const Vector3DI &v); + double DistSq (const Vector3DF &v); + double DistSq (const Vector4DF &v); + + Vector2DF &Normalize (void); + double Length (void); + + VTYPE &X(void); + VTYPE &Y(void); + VTYPE Z(void); + VTYPE W(void); + const VTYPE &X(void) const; + const VTYPE &Y(void) const; + const VTYPE Z(void) const; + const VTYPE W(void) const; + VTYPE *Data (void); + }; + + #undef VNAME + #undef VTYPE + + // Vector3DC Declaration + + #define VNAME 3DC + #define VTYPE unsigned char + + class Vector3DC { + public: + VTYPE x, y, z; + + // Constructors/Destructors + inline Vector3DC(); + inline ~Vector3DC(); + inline Vector3DC (VTYPE xa, VTYPE ya, VTYPE za); + inline Vector3DC (Vector2DC &op); + inline Vector3DC (Vector2DI &op); + inline Vector3DC (Vector2DF &op); + inline Vector3DC (Vector3DC &op); + inline Vector3DC (Vector3DI &op); + inline Vector3DC (Vector3DF &op); + inline Vector3DC (Vector4DF &op); + + // Member Functions + inline Vector3DC &Set (VTYPE xa, VTYPE ya, VTYPE za); + + inline Vector3DC &operator= (Vector2DC &op); + inline Vector3DC &operator= (Vector2DI &op); + inline Vector3DC &operator= (Vector2DF &op); + inline Vector3DC &operator= (Vector3DC &op); + inline Vector3DC &operator= (Vector3DI &op); + inline Vector3DC &operator= (Vector3DF &op); + inline Vector3DC &operator= (Vector4DF &op); + + inline Vector3DC &operator+= (Vector2DC &op); + inline Vector3DC &operator+= (Vector2DI &op); + inline Vector3DC &operator+= (Vector2DF &op); + inline Vector3DC &operator+= (Vector3DC &op); + inline Vector3DC &operator+= (Vector3DI &op); + inline Vector3DC &operator+= (Vector3DF &op); + inline Vector3DC &operator+= (Vector4DF &op); + + inline Vector3DC &operator-= (Vector2DC &op); + inline Vector3DC &operator-= (Vector2DI &op); + inline Vector3DC &operator-= (Vector2DF &op); + inline Vector3DC &operator-= (Vector3DC &op); + inline Vector3DC &operator-= (Vector3DI &op); + inline Vector3DC &operator-= (Vector3DF &op); + inline Vector3DC &operator-= (Vector4DF &op); + + inline Vector3DC &operator*= (Vector2DC &op); + inline Vector3DC &operator*= (Vector2DI &op); + inline Vector3DC &operator*= (Vector2DF &op); + inline Vector3DC &operator*= (Vector3DC &op); + inline Vector3DC &operator*= (Vector3DI &op); + inline Vector3DC &operator*= (Vector3DF &op); + inline Vector3DC &operator*= (Vector4DF &op); + + inline Vector3DC &operator/= (Vector2DC &op); + inline Vector3DC &operator/= (Vector2DI &op); + inline Vector3DC &operator/= (Vector2DF &op); + inline Vector3DC &operator/= (Vector3DC &op); + inline Vector3DC &operator/= (Vector3DI &op); + inline Vector3DC &operator/= (Vector3DF &op); + inline Vector3DC &operator/= (Vector4DF &op); + + inline Vector3DC &Cross (Vector3DC &v); + inline Vector3DC &Cross (Vector3DI &v); + inline Vector3DC &Cross (Vector3DF &v); + + inline double Dot(Vector3DC &v); + inline double Dot(Vector3DI &v); + inline double Dot(Vector3DF &v); + + inline double Dist (Vector2DC &v); + inline double Dist (Vector2DI &v); + inline double Dist (Vector2DF &v); + inline double Dist (Vector3DC &v); + inline double Dist (Vector3DI &v); + inline double Dist (Vector3DF &v); + inline double Dist (Vector4DF &v); + + inline double DistSq (Vector2DC &v); + inline double DistSq (Vector2DI &v); + inline double DistSq (Vector2DF &v); + inline double DistSq (Vector3DC &v); + inline double DistSq (Vector3DI &v); + inline double DistSq (Vector3DF &v); + inline double DistSq (Vector4DF &v); + + inline Vector3DC &Normalize (void); + inline double Length (void); + + inline VTYPE &X(void); + inline VTYPE &Y(void); + inline VTYPE &Z(void); + inline VTYPE W(void); + inline const VTYPE &X(void) const; + inline const VTYPE &Y(void) const; + inline const VTYPE &Z(void) const; + inline const VTYPE W(void) const; + inline VTYPE *Data (void); + }; + + #undef VNAME + #undef VTYPE + + // Vector3DI Declaration + + #define VNAME 3DI + #define VTYPE int + + class Vector3DI { + public: + VTYPE x, y, z; + + // Constructors/Destructors + inline Vector3DI(); + inline ~Vector3DI(); + inline Vector3DI (VTYPE xa, VTYPE ya, VTYPE za); + inline Vector3DI (Vector2DC &op); + inline Vector3DI (Vector2DI &op); + inline Vector3DI (Vector2DF &op); + inline Vector3DI (Vector3DC &op); + inline Vector3DI (Vector3DI &op); + inline Vector3DI (Vector3DF &op); + inline Vector3DI (Vector4DF &op); + + // Set Functions + inline Vector3DI &Set (const int xa, const int ya, const int za); + + // Member Functions + inline Vector3DI &operator= (Vector2DC &op); + inline Vector3DI &operator= (Vector2DI &op); + inline Vector3DI &operator= (Vector2DF &op); + inline Vector3DI &operator= (Vector3DC &op); + inline Vector3DI &operator= (Vector3DI &op); + inline Vector3DI &operator= (Vector3DF &op); + inline Vector3DI &operator= (Vector4DF &op); + + inline Vector3DI &operator+= (Vector2DC &op); + inline Vector3DI &operator+= (Vector2DI &op); + inline Vector3DI &operator+= (Vector2DF &op); + inline Vector3DI &operator+= (Vector3DC &op); + inline Vector3DI &operator+= (Vector3DI &op); + inline Vector3DI &operator+= (Vector3DF &op); + inline Vector3DI &operator+= (Vector4DF &op); + + inline Vector3DI &operator-= (Vector2DC &op); + inline Vector3DI &operator-= (Vector2DI &op); + inline Vector3DI &operator-= (Vector2DF &op); + inline Vector3DI &operator-= (Vector3DC &op); + inline Vector3DI &operator-= (Vector3DI &op); + inline Vector3DI &operator-= (Vector3DF &op); + inline Vector3DI &operator-= (Vector4DF &op); + + inline Vector3DI &operator*= (Vector2DC &op); + inline Vector3DI &operator*= (Vector2DI &op); + inline Vector3DI &operator*= (Vector2DF &op); + inline Vector3DI &operator*= (Vector3DC &op); + inline Vector3DI &operator*= (Vector3DI &op); + inline Vector3DI &operator*= (Vector3DF &op); + inline Vector3DI &operator*= (Vector4DF &op); + + inline Vector3DI &operator/= (Vector2DC &op); + inline Vector3DI &operator/= (Vector2DI &op); + inline Vector3DI &operator/= (Vector2DF &op); + inline Vector3DI &operator/= (Vector3DC &op); + inline Vector3DI &operator/= (Vector3DI &op); + inline Vector3DI &operator/= (Vector3DF &op); + inline Vector3DI &operator/= (Vector4DF &op); + + inline Vector3DI &Cross (Vector3DC &v); + inline Vector3DI &Cross (Vector3DI &v); + inline Vector3DI &Cross (Vector3DF &v); + + inline double Dot(Vector3DC &v); + inline double Dot(Vector3DI &v); + inline double Dot(Vector3DF &v); + + inline double Dist (Vector2DC &v); + inline double Dist (Vector2DI &v); + inline double Dist (Vector2DF &v); + inline double Dist (Vector3DC &v); + inline double Dist (Vector3DI &v); + inline double Dist (Vector3DF &v); + inline double Dist (Vector4DF &v); + + inline double DistSq (Vector2DC &v); + inline double DistSq (Vector2DI &v); + inline double DistSq (Vector2DF &v); + inline double DistSq (Vector3DC &v); + inline double DistSq (Vector3DI &v); + inline double DistSq (Vector3DF &v); + inline double DistSq (Vector4DF &v); + + inline Vector3DI &Normalize (void); + inline double Length (void); + + inline VTYPE &X(void); + inline VTYPE &Y(void); + inline VTYPE &Z(void); + inline VTYPE W(void); + inline const VTYPE &X(void) const; + inline const VTYPE &Y(void) const; + inline const VTYPE &Z(void) const; + inline const VTYPE W(void) const; + inline VTYPE *Data (void); + }; + + #undef VNAME + #undef VTYPE + + // Vector3DF Declarations + + #define VNAME 3DF + #define VTYPE float + + class Vector3DF { + public: + VTYPE x, y, z; + + // Constructors/Destructors + inline Vector3DF(); + inline ~Vector3DF(); + inline Vector3DF (const VTYPE xa, const VTYPE ya, const VTYPE za); + inline Vector3DF (const Vector2DC &op); + inline Vector3DF (const Vector2DI &op); + inline Vector3DF (const Vector2DF &op); + inline Vector3DF (const Vector3DC &op); + inline Vector3DF (const Vector3DI &op); + inline Vector3DF (const Vector3DF &op); + inline Vector3DF (const Vector4DF &op); + + // Set Functions + inline Vector3DF &Set (const double xa, const double ya, const double za); + + // Member Functions + inline Vector3DF &operator= (const int op); + inline Vector3DF &operator= (const double op); + inline Vector3DF &operator= (const Vector2DC &op); + inline Vector3DF &operator= (const Vector2DI &op); + inline Vector3DF &operator= (const Vector2DF &op); + inline Vector3DF &operator= (const Vector3DC &op); + inline Vector3DF &operator= (const Vector3DI &op); + inline Vector3DF &operator= (const Vector3DF &op); + inline Vector3DF &operator= (const Vector4DF &op); + + inline Vector3DF &operator+= (const int op); + inline Vector3DF &operator+= (const double op); + inline Vector3DF &operator+= (const Vector2DC &op); + inline Vector3DF &operator+= (const Vector2DI &op); + inline Vector3DF &operator+= (const Vector2DF &op); + inline Vector3DF &operator+= (const Vector3DC &op); + inline Vector3DF &operator+= (const Vector3DI &op); + inline Vector3DF &operator+= (const Vector3DF &op); + inline Vector3DF &operator+= (const Vector4DF &op); + + inline Vector3DF &operator-= (const int op); + inline Vector3DF &operator-= (const double op); + inline Vector3DF &operator-= (const Vector2DC &op); + inline Vector3DF &operator-= (const Vector2DI &op); + inline Vector3DF &operator-= (const Vector2DF &op); + inline Vector3DF &operator-= (const Vector3DC &op); + inline Vector3DF &operator-= (const Vector3DI &op); + inline Vector3DF &operator-= (const Vector3DF &op); + inline Vector3DF &operator-= (const Vector4DF &op); + + inline Vector3DF &operator*= (const int op); + inline Vector3DF &operator*= (const double op); + inline Vector3DF &operator*= (const Vector2DC &op); + inline Vector3DF &operator*= (const Vector2DI &op); + inline Vector3DF &operator*= (const Vector2DF &op); + inline Vector3DF &operator*= (const Vector3DC &op); + inline Vector3DF &operator*= (const Vector3DI &op); + inline Vector3DF &operator*= (const Vector3DF &op); + inline Vector3DF &operator*= (const Vector4DF &op); + Vector3DF &operator*= (const Matrix4F &op); + Vector3DF &operator*= (const MatrixF &op); // see vector.cpp + + inline Vector3DF &operator/= (const int op); + inline Vector3DF &operator/= (const double op); + inline Vector3DF &operator/= (const Vector2DC &op); + inline Vector3DF &operator/= (const Vector2DI &op); + inline Vector3DF &operator/= (const Vector2DF &op); + inline Vector3DF &operator/= (const Vector3DC &op); + inline Vector3DF &operator/= (const Vector3DI &op); + inline Vector3DF &operator/= (const Vector3DF &op); + inline Vector3DF &operator/= (const Vector4DF &op); + + inline Vector3DF &Cross (const Vector3DC &v); + inline Vector3DF &Cross (const Vector3DI &v); + inline Vector3DF &Cross (const Vector3DF &v); + + inline double Dot(const Vector3DC &v); + inline double Dot(const Vector3DI &v); + inline double Dot(const Vector3DF &v); + + inline double Dist (const Vector2DC &v); + inline double Dist (const Vector2DI &v); + inline double Dist (const Vector2DF &v); + inline double Dist (const Vector3DC &v); + inline double Dist (const Vector3DI &v); + inline double Dist (const Vector3DF &v); + inline double Dist (const Vector4DF &v); + + inline double DistSq (const Vector2DC &v); + inline double DistSq (const Vector2DI &v); + inline double DistSq (const Vector2DF &v); + inline double DistSq (const Vector3DC &v); + inline double DistSq (const Vector3DI &v); + inline double DistSq (const Vector3DF &v); + inline double DistSq (const Vector4DF &v); + + inline Vector3DF &Normalize (void); + inline double Length (void); + + inline VTYPE &X(); + inline VTYPE &Y(); + inline VTYPE &Z(); + inline VTYPE W(); + inline const VTYPE &X() const; + inline const VTYPE &Y() const; + inline const VTYPE &Z() const; + inline const VTYPE W() const; + inline VTYPE *Data (); + }; + + #undef VNAME + #undef VTYPE + + // Vector4DF Declarations + + #define VNAME 4DF + #define VTYPE double + + class Vector4DF { + public: + VTYPE x, y, z, w; + + // Constructors/Destructors + inline Vector4DF(); + inline ~Vector4DF(); + inline Vector4DF (VTYPE xa, VTYPE ya, VTYPE za, VTYPE wa); + inline Vector4DF (Vector2DC &op); + inline Vector4DF (Vector2DI &op); + inline Vector4DF (Vector2DF &op); + inline Vector4DF (Vector3DC &op); + inline Vector4DF (Vector3DI &op); + inline Vector4DF (Vector3DF &op); + inline Vector4DF (Vector4DF &op); + + // Member Functions + inline Vector4DF &operator= (int op); + inline Vector4DF &operator= (double op); + inline Vector4DF &operator= (Vector2DC &op); + inline Vector4DF &operator= (Vector2DI &op); + inline Vector4DF &operator= (Vector2DF &op); + inline Vector4DF &operator= (Vector3DC &op); + inline Vector4DF &operator= (Vector3DI &op); + inline Vector4DF &operator= (Vector3DF &op); + inline Vector4DF &operator= (Vector4DF &op); + + inline Vector4DF &operator+= (int op); + inline Vector4DF &operator+= (double op); + inline Vector4DF &operator+= (Vector2DC &op); + inline Vector4DF &operator+= (Vector2DI &op); + inline Vector4DF &operator+= (Vector2DF &op); + inline Vector4DF &operator+= (Vector3DC &op); + inline Vector4DF &operator+= (Vector3DI &op); + inline Vector4DF &operator+= (Vector3DF &op); + inline Vector4DF &operator+= (Vector4DF &op); + + inline Vector4DF &operator-= (int op); + inline Vector4DF &operator-= (double op); + inline Vector4DF &operator-= (Vector2DC &op); + inline Vector4DF &operator-= (Vector2DI &op); + inline Vector4DF &operator-= (Vector2DF &op); + inline Vector4DF &operator-= (Vector3DC &op); + inline Vector4DF &operator-= (Vector3DI &op); + inline Vector4DF &operator-= (Vector3DF &op); + inline Vector4DF &operator-= (Vector4DF &op); + + inline Vector4DF &operator*= (int op); + inline Vector4DF &operator*= (double op); + inline Vector4DF &operator*= (Vector2DC &op); + inline Vector4DF &operator*= (Vector2DI &op); + inline Vector4DF &operator*= (Vector2DF &op); + inline Vector4DF &operator*= (Vector3DC &op); + inline Vector4DF &operator*= (Vector3DI &op); + inline Vector4DF &operator*= (Vector3DF &op); + inline Vector4DF &operator*= (Vector4DF &op); + Vector4DF &operator*= (const Matrix4F &op); + Vector4DF &operator*= (const MatrixF &op); // see vector.cpp + + inline Vector4DF &operator/= (int op); + inline Vector4DF &operator/= (double op); + inline Vector4DF &operator/= (Vector2DC &op); + inline Vector4DF &operator/= (Vector2DI &op); + inline Vector4DF &operator/= (Vector2DF &op); + inline Vector4DF &operator/= (Vector3DC &op); + inline Vector4DF &operator/= (Vector3DI &op); + inline Vector4DF &operator/= (Vector3DF &op); + inline Vector4DF &operator/= (Vector4DF &op); + + inline Vector4DF &Cross (Vector4DF &v); + + inline double Dot(Vector4DF &v); + + inline double Dist (Vector4DF &v); + + inline double DistSq (Vector4DF &v); + + inline Vector4DF &Normalize (void); + inline double Length (void); + + inline VTYPE &X(void); + inline VTYPE &Y(void); + inline VTYPE &Z(void); + inline VTYPE &W(void); + inline const VTYPE &X(void) const; + inline const VTYPE &Y(void) const; + inline const VTYPE &Z(void) const; + inline const VTYPE &W(void) const; + inline VTYPE *Data (void); + }; + + #undef VNAME + #undef VTYPE + + // Vector Code Definitions (Inlined) + #include "vector.cci" + +#endif + diff --git a/Extras/sph/fluid_system_host.linkinfo b/Extras/sph/fluid_system_host.linkinfo new file mode 100644 index 0000000..b094dc5 --- /dev/null +++ b/Extras/sph/fluid_system_host.linkinfo @@ -0,0 +1 @@ + --import sRadixSum,%laneid,%ctaid,%nctaid,%smid,A7,%pm3,%pm2,%pm1,__CC-temp__0__,%pm0,%tid,%clock,%warpid,%ntid,%gridid --export _Z8RadixSumP12KeyValuePairjjj,_Z13hashParticlesPcP5uint2i,_Z15insertParticlesPcP5uint2Piii,_Z15computePressurePcPiP5uint2i,_Z25RadixAddOffsetsAndShuffleP12KeyValuePairS0_jji,_Z20insertParticlesRadixPcP5uint2PiS_ii,_Z12computeForcePcPiP5uint2i,_Z15computeForceNbrPci,_Z16advanceParticlesPciff,_Z14RadixPrefixSumv \ No newline at end of file diff --git a/Extras/sph/fluids.vcproj b/Extras/sph/fluids.vcproj new file mode 100644 index 0000000..e9060ec --- /dev/null +++ b/Extras/sph/fluids.vcproj @@ -0,0 +1,306 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/sph/fluids/fluid.cpp b/Extras/sph/fluids/fluid.cpp new file mode 100644 index 0000000..e9bddc8 --- /dev/null +++ b/Extras/sph/fluids/fluid.cpp @@ -0,0 +1,22 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 "fluid.h" diff --git a/Extras/sph/fluids/fluid.h b/Extras/sph/fluids/fluid.h new file mode 100644 index 0000000..2ed6202 --- /dev/null +++ b/Extras/sph/fluids/fluid.h @@ -0,0 +1,44 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 DEF_FLUID + #define DEF_FLUID + + #include "vector.h" + + #include "common_defs.h" + + struct Fluid { + public: + Vector3DF pos; // Basic particle (must match Particle class) + DWORD clr; + int next; + Vector3DF vel; + Vector3DF vel_eval; + unsigned short age; + + float pressure; // Smoothed Particle Hydrodynamics + float density; + Vector3DF sph_force; + }; + +#endif /*PARTICLE_H_*/ diff --git a/Extras/sph/fluids/fluid_system.cpp b/Extras/sph/fluids/fluid_system.cpp new file mode 100644 index 0000000..966a2ce --- /dev/null +++ b/Extras/sph/fluids/fluid_system.cpp @@ -0,0 +1,869 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 + +#ifdef _MSC_VER + #include +#else + #include +#endif + +#include "common_defs.h" +#include "mtime.h" +#include "fluid_system.h" + +#ifdef BUILD_CUDA + #include "fluid_system_host.cuh" +#endif + +#define EPSILON 0.00001f //for collision detection + +FluidSystem::FluidSystem () +{ +} + +void FluidSystem::Initialize ( int mode, int total ) +{ + if ( mode != BFLUID ) { + printf ( "ERROR: FluidSystem not initialized as BFLUID.\n"); + } + PointSet::Initialize ( mode, total ); + + FreeBuffers (); + AddBuffer ( BFLUID, sizeof ( Fluid ), total ); + AddAttribute ( 0, "pos", sizeof ( Vector3DF ), false ); + AddAttribute ( 0, "color", sizeof ( DWORD ), false ); + AddAttribute ( 0, "vel", sizeof ( Vector3DF ), false ); + AddAttribute ( 0, "ndx", sizeof ( unsigned short ), false ); + AddAttribute ( 0, "age", sizeof ( unsigned short ), false ); + + AddAttribute ( 0, "pressure", sizeof ( double ), false ); + AddAttribute ( 0, "density", sizeof ( double ), false ); + AddAttribute ( 0, "sph_force", sizeof ( Vector3DF ), false ); + AddAttribute ( 0, "next", sizeof ( Fluid* ), false ); + AddAttribute ( 0, "tag", sizeof ( bool ), false ); + + SPH_Setup (); + Reset ( total ); +} + +void FluidSystem::Reset ( int nmax ) +{ + ResetBuffer ( 0, nmax ); + + m_DT = 0.003; // 0.001; // .001 = for point grav + + // Reset parameters + m_Param [ MAX_FRAC ] = 1.0; + m_Param [ POINT_GRAV ] = 0.0; + m_Param [ PLANE_GRAV ] = 1.0; + + m_Param [ BOUND_ZMIN_SLOPE ] = 0.0; + m_Param [ FORCE_XMAX_SIN ] = 0.0; + m_Param [ FORCE_XMIN_SIN ] = 0.0; + m_Toggle [ WRAP_X ] = false; + m_Toggle [ WALL_BARRIER ] = false; + m_Toggle [ LEVY_BARRIER ] = false; + m_Toggle [ DRAIN_BARRIER ] = false; + m_Param [ SPH_INTSTIFF ] = 1.00; + m_Param [ SPH_VISC ] = 0.2; + m_Param [ SPH_INTSTIFF ] = 0.50; + m_Param [ SPH_EXTSTIFF ] = 20000; + m_Param [ SPH_SMOOTHRADIUS ] = 0.01; + + m_Vec [ POINT_GRAV_POS ].Set ( 0, 0, 50 ); + m_Vec [ PLANE_GRAV_DIR ].Set ( 0, 0, -9.8 ); + m_Vec [ EMIT_POS ].Set ( 0, 0, 0 ); + m_Vec [ EMIT_RATE ].Set ( 0, 0, 0 ); + m_Vec [ EMIT_ANG ].Set ( 0, 90, 1.0 ); + m_Vec [ EMIT_DANG ].Set ( 0, 0, 0 ); +} + +int FluidSystem::AddPoint () +{ + xref ndx; + Fluid* f = (Fluid*) AddElem ( 0, ndx ); + f->sph_force.Set(0,0,0); + f->vel.Set(0,0,0); + f->vel_eval.Set(0,0,0); + f->next = 0x0; + f->pressure = 0; + f->density = 0; + return ndx; +} + +int FluidSystem::AddPointReuse () +{ + xref ndx; + Fluid* f; + if ( NumPoints() <= mBuf[0].max-2 ) + f = (Fluid*) AddElem ( 0, ndx ); + else + f = (Fluid*) RandomElem ( 0, ndx ); + + f->sph_force.Set(0,0,0); + f->vel.Set(0,0,0); + f->vel_eval.Set(0,0,0); + f->next = 0x0; + f->pressure = 0; + f->density = 0; + return ndx; +} + +void FluidSystem::Run () +{ + bool bTiming = false;//true; + + mint::Time start, stop; + + float ss = m_Param [ SPH_PDIST ] / m_Param[ SPH_SIMSCALE ]; // simulation scale (not Schutzstaffel) + + if ( m_Vec[EMIT_RATE].x > 0 && (++m_Frame) % (int) m_Vec[EMIT_RATE].x == 0 ) { + //m_Frame = 0; + Emit ( ss ); + } + + #ifdef NOGRID + // Slow method - O(n^2) + SPH_ComputePressureSlow (); + SPH_ComputeForceSlow (); + #else + + if ( m_Toggle[USE_CUDA] ) { + + #ifdef BUILD_CUDA + // -- GPU -- + start.SetSystemTime ( ACC_NSEC ); + TransferToCUDA ( mBuf[0].data, (int*) &m_Grid[0], NumPoints() ); + if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "TO: %s\n", stop.GetReadableTime().c_str() ); } + + start.SetSystemTime ( ACC_NSEC ); + Grid_InsertParticlesCUDA (); + if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "INSERT (CUDA): %s\n", stop.GetReadableTime().c_str() ); } + + start.SetSystemTime ( ACC_NSEC ); + SPH_ComputePressureCUDA (); + if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "PRESS (CUDA): %s\n", stop.GetReadableTime().c_str() ); } + + start.SetSystemTime ( ACC_NSEC ); + SPH_ComputeForceCUDA (); + if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "FORCE (CUDA): %s\n", stop.GetReadableTime().c_str() ); } + + //** CUDA integrator is incomplete.. + // Once integrator is done, we can remove TransferTo/From steps + /*start.SetSystemTime ( ACC_NSEC ); + SPH_AdvanceCUDA( m_DT, m_DT/m_Param[SPH_SIMSCALE] ); + if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "ADV (CUDA): %s\n", stop.GetReadableTime().c_str() ); }*/ + + start.SetSystemTime ( ACC_NSEC ); + TransferFromCUDA ( mBuf[0].data, (int*) &m_Grid[0], NumPoints() ); + if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "FROM: %s\n", stop.GetReadableTime().c_str() ); } + + // .. Do advance on CPU + Advance(); + + #endif + + } else { + // -- CPU only -- + + start.SetSystemTime ( ACC_NSEC ); + Grid_InsertParticles (); + if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "INSERT: %s\n", stop.GetReadableTime().c_str() ); } + + start.SetSystemTime ( ACC_NSEC ); + SPH_ComputePressureGrid (); + if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "PRESS: %s\n", stop.GetReadableTime().c_str() ); } + + start.SetSystemTime ( ACC_NSEC ); + SPH_ComputeForceGridNC (); + if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "FORCE: %s\n", stop.GetReadableTime().c_str() ); } + + start.SetSystemTime ( ACC_NSEC ); + Advance(); + if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "ADV: %s\n", stop.GetReadableTime().c_str() ); } + } + + #endif +} + + + +void FluidSystem::SPH_DrawDomain () +{ + Vector3DF min, max; + min = m_Vec[SPH_VOLMIN]; + max = m_Vec[SPH_VOLMAX]; + min.z += 0.5; + + glColor3f ( 0.0, 0.0, 1.0 ); + glBegin ( GL_LINES ); + glVertex3f ( min.x, min.y, min.z ); glVertex3f ( max.x, min.y, min.z ); + glVertex3f ( min.x, max.y, min.z ); glVertex3f ( max.x, max.y, min.z ); + glVertex3f ( min.x, min.y, min.z ); glVertex3f ( min.x, max.y, min.z ); + glVertex3f ( max.x, min.y, min.z ); glVertex3f ( max.x, max.y, min.z ); + glEnd (); +} + +void FluidSystem::Advance () +{ + char *dat1, *dat1_end; + Fluid* p; + Vector3DF norm, z; + Vector3DF dir, accel; + Vector3DF vnext; + Vector3DF min, max; + double adj; + float SL, SL2, ss, radius; + float stiff, damp, speed, diff; + SL = m_Param[SPH_LIMIT]; + SL2 = SL*SL; + + stiff = m_Param[SPH_EXTSTIFF]; + damp = m_Param[SPH_EXTDAMP]; + radius = m_Param[SPH_PRADIUS]; + min = m_Vec[SPH_VOLMIN]; + max = m_Vec[SPH_VOLMAX]; + ss = m_Param[SPH_SIMSCALE]; + + dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride; + for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride ) { + p = (Fluid*) dat1; + + // Compute Acceleration + accel = p->sph_force; + accel *= m_Param[SPH_PMASS]; + + // Velocity limiting + speed = accel.x*accel.x + accel.y*accel.y + accel.z*accel.z; + if ( speed > SL2 ) { + accel *= SL / sqrt(speed); + } + + // Boundary Conditions + + // Z-axis walls + diff = 2 * radius - ( p->pos.z - min.z - (p->pos.x - m_Vec[SPH_VOLMIN].x) * m_Param[BOUND_ZMIN_SLOPE] )*ss; + if (diff > EPSILON ) { + norm.Set ( -m_Param[BOUND_ZMIN_SLOPE], 0, 1.0 - m_Param[BOUND_ZMIN_SLOPE] ); + adj = stiff * diff - damp * norm.Dot ( p->vel_eval ); + accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z; + } + + diff = 2 * radius - ( max.z - p->pos.z )*ss; + if (diff > EPSILON) { + norm.Set ( 0, 0, -1 ); + adj = stiff * diff - damp * norm.Dot ( p->vel_eval ); + accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z; + } + + // X-axis walls + if ( !m_Toggle[WRAP_X] ) { + diff = 2 * radius - ( p->pos.x - min.x + (sin(m_Time*10.0)-1+(p->pos.y*0.025)*0.25) * m_Param[FORCE_XMIN_SIN] )*ss; + //diff = 2 * radius - ( p->pos.x - min.x + (sin(m_Time*10.0)-1) * m_Param[FORCE_XMIN_SIN] )*ss; + if (diff > EPSILON ) { + norm.Set ( 1.0, 0, 0 ); + adj = (m_Param[ FORCE_XMIN_SIN ] + 1) * stiff * diff - damp * norm.Dot ( p->vel_eval ) ; + accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z; + } + + diff = 2 * radius - ( max.x - p->pos.x + (sin(m_Time*10.0)-1) * m_Param[FORCE_XMAX_SIN] )*ss; + if (diff > EPSILON) { + norm.Set ( -1, 0, 0 ); + adj = (m_Param[ FORCE_XMAX_SIN ]+1) * stiff * diff - damp * norm.Dot ( p->vel_eval ); + accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z; + } + } + + // Y-axis walls + diff = 2 * radius - ( p->pos.y - min.y )*ss; + if (diff > EPSILON) { + norm.Set ( 0, 1, 0 ); + adj = stiff * diff - damp * norm.Dot ( p->vel_eval ); + accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z; + } + diff = 2 * radius - ( max.y - p->pos.y )*ss; + if (diff > EPSILON) { + norm.Set ( 0, -1, 0 ); + adj = stiff * diff - damp * norm.Dot ( p->vel_eval ); + accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z; + } + + // Wall barrier + if ( m_Toggle[WALL_BARRIER] ) { + diff = 2 * radius - ( p->pos.x - 0 )*ss; + if (diff < 2*radius && diff > EPSILON && fabs(p->pos.y) < 3 && p->pos.z < 10) { + norm.Set ( 1.0, 0, 0 ); + adj = 2*stiff * diff - damp * norm.Dot ( p->vel_eval ) ; + accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z; + } + } + + // Levy barrier + if ( m_Toggle[LEVY_BARRIER] ) { + diff = 2 * radius - ( p->pos.x - 0 )*ss; + if (diff < 2*radius && diff > EPSILON && fabs(p->pos.y) > 5 && p->pos.z < 10) { + norm.Set ( 1.0, 0, 0 ); + adj = 2*stiff * diff - damp * norm.Dot ( p->vel_eval ) ; + accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z; + } + } + // Drain barrier + if ( m_Toggle[DRAIN_BARRIER] ) { + diff = 2 * radius - ( p->pos.z - min.z-15 )*ss; + if (diff < 2*radius && diff > EPSILON && (fabs(p->pos.x)>3 || fabs(p->pos.y)>3) ) { + norm.Set ( 0, 0, 1); + adj = stiff * diff - damp * norm.Dot ( p->vel_eval ); + accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z; + } + } + + // Plane gravity + if ( m_Param[PLANE_GRAV] > 0) + accel += m_Vec[PLANE_GRAV_DIR]; + + // Point gravity + if ( m_Param[POINT_GRAV] > 0 ) { + norm.x = ( p->pos.x - m_Vec[POINT_GRAV_POS].x ); + norm.y = ( p->pos.y - m_Vec[POINT_GRAV_POS].y ); + norm.z = ( p->pos.z - m_Vec[POINT_GRAV_POS].z ); + norm.Normalize (); + norm *= m_Param[POINT_GRAV]; + accel -= norm; + } + + // Leapfrog Integration ---------------------------- + vnext = accel; + vnext *= m_DT; + vnext += p->vel; // v(t+1/2) = v(t-1/2) + a(t) dt + p->vel_eval = p->vel; + p->vel_eval += vnext; + p->vel_eval *= 0.5; // v(t+1) = [v(t-1/2) + v(t+1/2)] * 0.5 used to compute forces later + p->vel = vnext; + vnext *= m_DT/ss; + p->pos += vnext; // p(t+1) = p(t) + v(t+1/2) dt + + if ( m_Param[CLR_MODE]==1.0 ) { + adj = fabs(vnext.x)+fabs(vnext.y)+fabs(vnext.z) / 7000.0; + adj = (adj > 1.0) ? 1.0 : adj; + p->clr = COLORA( 0, adj, adj, 1 ); + } + if ( m_Param[CLR_MODE]==2.0 ) { + float v = 0.5 + ( p->pressure / 1500.0); + if ( v < 0.1 ) v = 0.1; + if ( v > 1.0 ) v = 1.0; + p->clr = COLORA ( v, 1-v, 0, 1 ); + } + + + // Euler integration ------------------------------- + /* accel += m_Gravity; + accel *= m_DT; + p->vel += accel; // v(t+1) = v(t) + a(t) dt + p->vel_eval += accel; + p->vel_eval *= m_DT/d; + p->pos += p->vel_eval; + p->vel_eval = p->vel; */ + + + if ( m_Toggle[WRAP_X] ) { + diff = p->pos.x - (m_Vec[SPH_VOLMIN].x + 2); // -- Simulates object in center of flow + if ( diff <= 0 ) { + p->pos.x = (m_Vec[SPH_VOLMAX].x - 2) + diff*2; + p->pos.z = 10; + } + } + } + + m_Time += m_DT; +} + +//------------------------------------------------------ SPH Setup +// +// Range = +/- 10.0 * 0.006 (r) = 0.12 m (= 120 mm = 4.7 inch) +// Container Volume (Vc) = 0.001728 m^3 +// Rest Density (D) = 1000.0 kg / m^3 +// Particle Mass (Pm) = 0.00020543 kg (mass = vol * density) +// Number of Particles (N) = 4000.0 +// Water Mass (M) = 0.821 kg (= 821 grams) +// Water Volume (V) = 0.000821 m^3 (= 3.4 cups, .21 gals) +// Smoothing Radius (R) = 0.02 m (= 20 mm = ~3/4 inch) +// Particle Radius (Pr) = 0.00366 m (= 4 mm = ~1/8 inch) +// Particle Volume (Pv) = 2.054e-7 m^3 (= .268 milliliters) +// Rest Distance (Pd) = 0.0059 m +// +// Given: D, Pm, N +// Pv = Pm / D 0.00020543 kg / 1000 kg/m^3 = 2.054e-7 m^3 +// Pv = 4/3*pi*Pr^3 cuberoot( 2.054e-7 m^3 * 3/(4pi) ) = 0.00366 m +// M = Pm * N 0.00020543 kg * 4000.0 = 0.821 kg +// V = M / D 0.821 kg / 1000 kg/m^3 = 0.000821 m^3 +// V = Pv * N 2.054e-7 m^3 * 4000 = 0.000821 m^3 +// Pd = cuberoot(Pm/D) cuberoot(0.00020543/1000) = 0.0059 m +// +// Ideal grid cell size (gs) = 2 * smoothing radius = 0.02*2 = 0.04 +// Ideal domain size = k*gs/d = k*0.02*2/0.005 = k*8 = {8, 16, 24, 32, 40, 48, ..} +// (k = number of cells, gs = cell size, d = simulation scale) + +void FluidSystem::SPH_Setup () +{ + m_Param [ SPH_SIMSCALE ] = 0.004; // unit size + m_Param [ SPH_VISC ] = 0.2; // pascal-second (Pa.s) = 1 kg m^-1 s^-1 (see wikipedia page on viscosity) + m_Param [ SPH_RESTDENSITY ] = 600.0; // kg / m^3 + m_Param [ SPH_PMASS ] = 0.00020543; // kg + m_Param [ SPH_PRADIUS ] = 0.004; // m + m_Param [ SPH_PDIST ] = 0.0059; // m + m_Param [ SPH_SMOOTHRADIUS ] = 0.01; // m + m_Param [ SPH_INTSTIFF ] = 1.00; + m_Param [ SPH_EXTSTIFF ] = 10000.0; + m_Param [ SPH_EXTDAMP ] = 256.0; + m_Param [ SPH_LIMIT ] = 200.0; // m / s + + m_Toggle [ SPH_GRID ] = false; + m_Toggle [ SPH_DEBUG ] = false; + + SPH_ComputeKernels (); +} + +void FluidSystem::SPH_ComputeKernels () +{ + m_Param [ SPH_PDIST ] = pow ( m_Param[SPH_PMASS] / m_Param[SPH_RESTDENSITY], 1/3.0 ); + m_R2 = m_Param [SPH_SMOOTHRADIUS] * m_Param[SPH_SMOOTHRADIUS]; + m_Poly6Kern = 315.0f / (64.0f * 3.141592 * pow( m_Param[SPH_SMOOTHRADIUS], 9) ); // Wpoly6 kernel (denominator part) - 2003 Muller, p.4 + m_SpikyKern = -45.0f / (3.141592 * pow( m_Param[SPH_SMOOTHRADIUS], 6) ); // Laplacian of viscocity (denominator): PI h^6 + m_LapKern = 45.0f / (3.141592 * pow( m_Param[SPH_SMOOTHRADIUS], 6) ); +} + +void FluidSystem::SPH_CreateExample ( int n, int nmax ) +{ + Vector3DF pos; + Vector3DF min, max; + + Reset ( nmax ); + + switch ( n ) { + case 0: // Wave pool + + //-- TEST CASE: 2x2x2 grid, 32 particles. NOTE: Set PRADIUS to 0.0004 to reduce wall influence + // grid 0: 3*3*2 = 18 particles + // grid 1,2: 3*1*2 = 6 particles + // grid 3: 1*1*2 = 2 particles + // grid 4,5,6: 0 = 0 particles + /*m_Vec [ SPH_VOLMIN ].Set ( -2.5, -2.5, 0 ); + m_Vec [ SPH_VOLMAX ].Set ( 2.5, 2.5, 5.0 ); + m_Vec [ SPH_INITMIN ].Set ( -2.5, -2.5, 0 ); + m_Vec [ SPH_INITMAX ].Set ( 2.5, 2.5, 1.6 );*/ + + m_Vec [ SPH_VOLMIN ].Set ( -30, -30, 0 ); + m_Vec [ SPH_VOLMAX ].Set ( 30, 30, 40 ); + + //m_Vec [ SPH_INITMIN ].Set ( -5, -5, 10 ); + //m_Vec [ SPH_INITMAX ].Set ( 5, 5, 20 ); + + m_Vec [ SPH_INITMIN ].Set ( -20, -26, 10 ); + m_Vec [ SPH_INITMAX ].Set ( 20, 26, 40 ); + + m_Param [ FORCE_XMIN_SIN ] = 12.0; + m_Param [ BOUND_ZMIN_SLOPE ] = 0.05; + break; + case 1: // Dam break + m_Vec [ SPH_VOLMIN ].Set ( -30, -14, 0 ); + m_Vec [ SPH_VOLMAX ].Set ( 30, 14, 60 ); + m_Vec [ SPH_INITMIN ].Set ( 0, -13, 0 ); + m_Vec [ SPH_INITMAX ].Set ( 29, 13, 30 ); + m_Vec [ PLANE_GRAV_DIR ].Set ( 0.0, 0, -9.8 ); + break; + case 2: // Dual-Wave pool + m_Vec [ SPH_VOLMIN ].Set ( -60, -5, 0 ); + m_Vec [ SPH_VOLMAX ].Set ( 60, 5, 50 ); + m_Vec [ SPH_INITMIN ].Set ( -46, -5, 0 ); + m_Vec [ SPH_INITMAX ].Set ( 46, 5, 15 ); + m_Param [ FORCE_XMIN_SIN ] = 8.0; + m_Param [ FORCE_XMAX_SIN ] = 8.0; + m_Vec [ PLANE_GRAV_DIR ].Set ( 0.0, 0, -9.8 ); + break; + case 3: // Swirl Stream + m_Vec [ SPH_VOLMIN ].Set ( -30, -30, 0 ); + m_Vec [ SPH_VOLMAX ].Set ( 30, 30, 50 ); + m_Vec [ SPH_INITMIN ].Set ( -30, -30, 0 ); + m_Vec [ SPH_INITMAX ].Set ( 30, 30, 40 ); + m_Vec [ EMIT_POS ].Set ( -20, -20, 22 ); + m_Vec [ EMIT_RATE ].Set ( 1, 4, 0 ); + m_Vec [ EMIT_ANG ].Set ( 0, 120, 1.5 ); + m_Vec [ EMIT_DANG ].Set ( 0, 0, 0 ); + m_Vec [ PLANE_GRAV_DIR ].Set ( 0.0, 0, -9.8 ); + break; + case 4: // Shockwave + m_Vec [ SPH_VOLMIN ].Set ( -60, -15, 0 ); + m_Vec [ SPH_VOLMAX ].Set ( 60, 15, 50 ); + m_Vec [ SPH_INITMIN ].Set ( -59, -14, 0 ); + m_Vec [ SPH_INITMAX ].Set ( 59, 14, 30 ); + m_Vec [ PLANE_GRAV_DIR ].Set ( 0.0, 0, -9.8 ); + m_Toggle [ WALL_BARRIER ] = true; + m_Toggle [ WRAP_X ] = true; + break; + case 5: // Zero gravity + m_Vec [ SPH_VOLMIN ].Set ( -40, -40, 0 ); + m_Vec [ SPH_VOLMAX ].Set ( 40, 40, 50 ); + m_Vec [ SPH_INITMIN ].Set ( -20, -20, 20 ); + m_Vec [ SPH_INITMAX ].Set ( 20, 20, 40 ); + m_Vec [ EMIT_POS ].Set ( -20, 0, 40 ); + m_Vec [ EMIT_RATE ].Set ( 2, 1, 0 ); + m_Vec [ EMIT_ANG ].Set ( 0, 120, 0.25 ); + m_Vec [ PLANE_GRAV_DIR ].Set ( 0, 0, 0 ); + m_Param [ SPH_INTSTIFF ] = 0.20; + break; + case 6: // Point gravity + m_Vec [ SPH_VOLMIN ].Set ( -40, -40, 0 ); + m_Vec [ SPH_VOLMAX ].Set ( 40, 40, 50 ); + m_Vec [ SPH_INITMIN ].Set ( -20, -20, 20 ); + m_Vec [ SPH_INITMAX ].Set ( 20, 20, 40 ); + m_Param [ SPH_INTSTIFF ] = 0.50; + m_Vec [ EMIT_POS ].Set ( -20, 20, 25 ); + m_Vec [ EMIT_RATE ].Set ( 1, 4, 0 ); + m_Vec [ EMIT_ANG ].Set ( -20, 100, 2.0 ); + m_Vec [ POINT_GRAV_POS ].Set ( 0, 0, 25 ); + m_Vec [ PLANE_GRAV_DIR ].Set ( 0, 0, 0 ); + m_Param [ POINT_GRAV ] = 3.5; + break; + case 7: // Levy break + m_Vec [ SPH_VOLMIN ].Set ( -40, -40, 0 ); + m_Vec [ SPH_VOLMAX ].Set ( 40, 40, 50 ); + m_Vec [ SPH_INITMIN ].Set ( 10, -40, 0 ); + m_Vec [ SPH_INITMAX ].Set ( 40, 40, 50 ); + m_Vec [ EMIT_POS ].Set ( 34, 27, 16.6 ); + m_Vec [ EMIT_RATE ].Set ( 2, 9, 0 ); + m_Vec [ EMIT_ANG ].Set ( 118, 200, 1.0 ); + m_Toggle [ LEVY_BARRIER ] = true; + m_Param [ BOUND_ZMIN_SLOPE ] = 0.1; + m_Vec [ PLANE_GRAV_DIR ].Set ( 0.0, 0, -9.8 ); + break; + case 8: // Drain + m_Vec [ SPH_VOLMIN ].Set ( -20, -20, 0 ); + m_Vec [ SPH_VOLMAX ].Set ( 20, 20, 50 ); + m_Vec [ SPH_INITMIN ].Set ( -15, -20, 20 ); + m_Vec [ SPH_INITMAX ].Set ( 20, 20, 50 ); + m_Vec [ EMIT_POS ].Set ( -16, -16, 30 ); + m_Vec [ EMIT_RATE ].Set ( 1, 4, 0 ); + m_Vec [ EMIT_ANG ].Set ( -20, 140, 1.8 ); + m_Toggle [ DRAIN_BARRIER ] = true; + m_Vec [ PLANE_GRAV_DIR ].Set ( 0.0, 0, -9.8 ); + break; + case 9: // Tumbler + m_Vec [ SPH_VOLMIN ].Set ( -30, -30, 0 ); + m_Vec [ SPH_VOLMAX ].Set ( 30, 30, 50 ); + m_Vec [ SPH_INITMIN ].Set ( 24, -29, 20 ); + m_Vec [ SPH_INITMAX ].Set ( 29, 29, 40 ); + m_Param [ SPH_VISC ] = 0.1; + m_Param [ SPH_INTSTIFF ] = 0.50; + m_Param [ SPH_EXTSTIFF ] = 8000; + //m_Param [ SPH_SMOOTHRADIUS ] = 0.01; + m_Param [ BOUND_ZMIN_SLOPE ] = 0.4; + m_Param [ FORCE_XMIN_SIN ] = 12.00; + m_Vec [ PLANE_GRAV_DIR ].Set ( 0.0, 0, -9.8 ); + break; + case 10: // Large sim + m_Vec [ SPH_VOLMIN ].Set ( -35, -35, 0 ); + m_Vec [ SPH_VOLMAX ].Set ( 35, 35, 60 ); + m_Vec [ SPH_INITMIN ].Set ( -5, -35, 0 ); + m_Vec [ SPH_INITMAX ].Set ( 30, 0, 60 ); + m_Vec [ PLANE_GRAV_DIR ].Set ( 0.0, 0, -9.8 ); + break; + } + + SPH_ComputeKernels (); + + m_Param [ SPH_SIMSIZE ] = m_Param [ SPH_SIMSCALE ] * (m_Vec[SPH_VOLMAX].z - m_Vec[SPH_VOLMIN].z); + m_Param [ SPH_PDIST ] = pow ( m_Param[SPH_PMASS] / m_Param[SPH_RESTDENSITY], 1/3.0 ); + + float ss = m_Param [ SPH_PDIST ]*0.87 / m_Param[ SPH_SIMSCALE ]; + printf ( "Spacing: %f\n", ss); + AddVolume ( m_Vec[SPH_INITMIN], m_Vec[SPH_INITMAX], ss ); // Create the particles + + float cell_size = m_Param[SPH_SMOOTHRADIUS]*2.0; // Grid cell size (2r) + Grid_Setup ( m_Vec[SPH_VOLMIN], m_Vec[SPH_VOLMAX], m_Param[SPH_SIMSCALE], cell_size, 1.0 ); // Setup grid + Grid_InsertParticles (); // Insert particles + + Vector3DF vmin, vmax; + vmin = m_Vec[SPH_VOLMIN]; + vmin -= Vector3DF(2,2,2); + vmax = m_Vec[SPH_VOLMAX]; + vmax += Vector3DF(2,2,-2); + + #ifdef BUILD_CUDA + FluidClearCUDA (); + Sleep ( 500 ); + + FluidSetupCUDA ( NumPoints(), sizeof(Fluid), *(float3*)& m_GridMin, *(float3*)& m_GridMax, *(float3*)& m_GridRes, *(float3*)& m_GridSize, (int) m_Vec[EMIT_RATE].x ); + + Sleep ( 500 ); + + FluidParamCUDA ( m_Param[SPH_SIMSCALE], m_Param[SPH_SMOOTHRADIUS], m_Param[SPH_PMASS], m_Param[SPH_RESTDENSITY], m_Param[SPH_INTSTIFF], m_Param[SPH_VISC] ); + #endif + +} + +// Compute Pressures - Very slow yet simple. O(n^2) +void FluidSystem::SPH_ComputePressureSlow () +{ + char *dat1, *dat1_end; + char *dat2, *dat2_end; + Fluid *p, *q; + int cnt = 0; + double dx, dy, dz, sum, dsq, c; + double d, d2, mR, mR2; + d = m_Param[SPH_SIMSCALE]; + d2 = d*d; + mR = m_Param[SPH_SMOOTHRADIUS]; + mR2 = mR*mR; + + dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride; + for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride ) { + p = (Fluid*) dat1; + + sum = 0.0; + cnt = 0; + + dat2_end = mBuf[0].data + NumPoints()*mBuf[0].stride; + for ( dat2 = mBuf[0].data; dat2 < dat2_end; dat2 += mBuf[0].stride ) { + q = (Fluid*) dat2; + + if ( p==q ) continue; + dx = ( p->pos.x - q->pos.x)*d; // dist in cm + dy = ( p->pos.y - q->pos.y)*d; + dz = ( p->pos.z - q->pos.z)*d; + dsq = (dx*dx + dy*dy + dz*dz); + if ( mR2 > dsq ) { + c = m_R2 - dsq; + sum += c * c * c; + cnt++; + //if ( p == m_CurrP ) q->tag = true; + } + } + p->density = sum * m_Param[SPH_PMASS] * m_Poly6Kern ; + p->pressure = ( p->density - m_Param[SPH_RESTDENSITY] ) * m_Param[SPH_INTSTIFF]; + p->density = 1.0f / p->density; + } +} + +// Compute Pressures - Using spatial grid, and also create neighbor table +void FluidSystem::SPH_ComputePressureGrid () +{ + char *dat1, *dat1_end; + Fluid* p; + Fluid* pcurr; + int pndx; + int i, cnt = 0; + float dx, dy, dz, sum, dsq, c; + float d, d2, mR, mR2; + float radius = m_Param[SPH_SMOOTHRADIUS] / m_Param[SPH_SIMSCALE]; + d = m_Param[SPH_SIMSCALE]; + d2 = d*d; + mR = m_Param[SPH_SMOOTHRADIUS]; + mR2 = mR*mR; + + dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride; + i = 0; + for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride, i++ ) { + p = (Fluid*) dat1; + + sum = 0.0; + m_NC[i] = 0; + + Grid_FindCells ( p->pos, radius ); + for (int cell=0; cell < 8; cell++) { + if ( m_GridCell[cell] != -1 ) { + pndx = m_Grid [ m_GridCell[cell] ]; + while ( pndx != -1 ) { + pcurr = (Fluid*) (mBuf[0].data + pndx*mBuf[0].stride); + if ( pcurr == p ) {pndx = pcurr->next; continue; } + dx = ( p->pos.x - pcurr->pos.x)*d; // dist in cm + dy = ( p->pos.y - pcurr->pos.y)*d; + dz = ( p->pos.z - pcurr->pos.z)*d; + dsq = (dx*dx + dy*dy + dz*dz); + if ( mR2 > dsq ) { + c = m_R2 - dsq; + sum += c * c * c; + if ( m_NC[i] < MAX_NEIGHBOR ) { + m_Neighbor[i][ m_NC[i] ] = pndx; + m_NDist[i][ m_NC[i] ] = sqrt(dsq); + m_NC[i]++; + } + } + pndx = pcurr->next; + } + } + m_GridCell[cell] = -1; + } + p->density = sum * m_Param[SPH_PMASS] * m_Poly6Kern ; + p->pressure = ( p->density - m_Param[SPH_RESTDENSITY] ) * m_Param[SPH_INTSTIFF]; + p->density = 1.0f / p->density; + } +} + +// Compute Forces - Very slow, but simple. O(n^2) +void FluidSystem::SPH_ComputeForceSlow () +{ + char *dat1, *dat1_end; + char *dat2, *dat2_end; + Fluid *p, *q; + Vector3DF force, fcurr; + register double pterm, vterm, dterm; + double c, r, d, sum, dsq; + double dx, dy, dz; + double mR, mR2, visc; + + d = m_Param[SPH_SIMSCALE]; + mR = m_Param[SPH_SMOOTHRADIUS]; + mR2 = (mR*mR); + visc = m_Param[SPH_VISC]; + vterm = m_LapKern * visc; + + dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride; + for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride ) { + p = (Fluid*) dat1; + + sum = 0.0; + force.Set ( 0, 0, 0 ); + + dat2_end = mBuf[0].data + NumPoints()*mBuf[0].stride; + for ( dat2 = mBuf[0].data; dat2 < dat2_end; dat2 += mBuf[0].stride ) { + q = (Fluid*) dat2; + + if ( p == q ) continue; + dx = ( p->pos.x - q->pos.x )*d; // dist in cm + dy = ( p->pos.y - q->pos.y )*d; + dz = ( p->pos.z - q->pos.z )*d; + dsq = (dx*dx + dy*dy + dz*dz); + if ( mR2 > dsq ) { + r = sqrt ( dsq ); + c = (mR - r); + pterm = -0.5f * c * m_SpikyKern * ( p->pressure + q->pressure) / r; + dterm = c * p->density * q->density; + force.x += ( pterm * dx + vterm * (q->vel_eval.x - p->vel_eval.x) ) * dterm; + force.y += ( pterm * dy + vterm * (q->vel_eval.y - p->vel_eval.y) ) * dterm; + force.z += ( pterm * dz + vterm * (q->vel_eval.z - p->vel_eval.z) ) * dterm; + } + } + p->sph_force = force; + } +} + +// Compute Forces - Using spatial grid. Faster. +void FluidSystem::SPH_ComputeForceGrid () +{ + char *dat1, *dat1_end; + Fluid *p; + Fluid *pcurr; + int pndx; + Vector3DF force, fcurr; + register double pterm, vterm, dterm; + double c, d, dsq, r; + double dx, dy, dz; + double mR, mR2, visc; + float radius = m_Param[SPH_SMOOTHRADIUS] / m_Param[SPH_SIMSCALE]; + + d = m_Param[SPH_SIMSCALE]; + mR = m_Param[SPH_SMOOTHRADIUS]; + mR2 = (mR*mR); + visc = m_Param[SPH_VISC]; + + dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride; + for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride ) { + p = (Fluid*) dat1; + + force.Set ( 0, 0, 0 ); + + Grid_FindCells ( p->pos, radius ); + for (int cell=0; cell < 8; cell++) { + if ( m_GridCell[cell] != -1 ) { + pndx = m_Grid [ m_GridCell[cell] ]; + while ( pndx != -1 ) { + pcurr = (Fluid*) (mBuf[0].data + pndx*mBuf[0].stride); + if ( pcurr == p ) {pndx = pcurr->next; continue; } + + dx = ( p->pos.x - pcurr->pos.x)*d; // dist in cm + dy = ( p->pos.y - pcurr->pos.y)*d; + dz = ( p->pos.z - pcurr->pos.z)*d; + dsq = (dx*dx + dy*dy + dz*dz); + if ( mR2 > dsq ) { + r = sqrt ( dsq ); + c = (mR - r); + pterm = -0.5f * c * m_SpikyKern * ( p->pressure + pcurr->pressure) / r; + dterm = c * p->density * pcurr->density; + vterm = m_LapKern * visc; + force.x += ( pterm * dx + vterm * (pcurr->vel_eval.x - p->vel_eval.x) ) * dterm; + force.y += ( pterm * dy + vterm * (pcurr->vel_eval.y - p->vel_eval.y) ) * dterm; + force.z += ( pterm * dz + vterm * (pcurr->vel_eval.z - p->vel_eval.z) ) * dterm; + } + pndx = pcurr->next; + } + } + } + p->sph_force = force; + } +} + +// Compute Forces - Using spatial grid with saved neighbor table. Fastest. +void FluidSystem::SPH_ComputeForceGridNC () +{ + char *dat1, *dat1_end; + Fluid *p; + Fluid *pcurr; + Vector3DF force, fcurr; + register float pterm, vterm, dterm; + int i; + float c, d; + float dx, dy, dz; + float mR, mR2, visc; + + d = m_Param[SPH_SIMSCALE]; + mR = m_Param[SPH_SMOOTHRADIUS]; + mR2 = (mR*mR); + visc = m_Param[SPH_VISC]; + + dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride; + i = 0; + + for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride, i++ ) { + p = (Fluid*) dat1; + + force.Set ( 0, 0, 0 ); + for (int j=0; j < m_NC[i]; j++ ) { + pcurr = (Fluid*) (mBuf[0].data + m_Neighbor[i][j]*mBuf[0].stride); + dx = ( p->pos.x - pcurr->pos.x)*d; // dist in cm + dy = ( p->pos.y - pcurr->pos.y)*d; + dz = ( p->pos.z - pcurr->pos.z)*d; + c = ( mR - m_NDist[i][j] ); + pterm = -0.5f * c * m_SpikyKern * ( p->pressure + pcurr->pressure) / m_NDist[i][j]; + dterm = c * p->density * pcurr->density; + vterm = m_LapKern * visc; + force.x += ( pterm * dx + vterm * (pcurr->vel_eval.x - p->vel_eval.x) ) * dterm; + force.y += ( pterm * dy + vterm * (pcurr->vel_eval.y - p->vel_eval.y) ) * dterm; + force.z += ( pterm * dz + vterm * (pcurr->vel_eval.z - p->vel_eval.z) ) * dterm; + } + p->sph_force = force; + } +} + diff --git a/Extras/sph/fluids/fluid_system.cu b/Extras/sph/fluids/fluid_system.cu new file mode 100644 index 0000000..f67eda7 --- /dev/null +++ b/Extras/sph/fluids/fluid_system.cu @@ -0,0 +1,71 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 +#include +#include +#include + +#if defined(__APPLE__) || defined(MACOSX) + #include +#else + #include +#endif +#include + +#include "fluid_system_kern.cu" + +extern "C" +{ + +// Compute number of blocks to create +int iDivUp (int a, int b) { + return (a % b != 0) ? (a / b + 1) : (a / b); +} +void computeNumBlocks (int numPnts, int minThreads, int &numBlocks, int &numThreads) +{ + numThreads = min( minThreads, numPnts ); + numBlocks = iDivUp ( numPnts, numThreads ); +} + + +void Grid_InsertParticlesCUDA ( uchar* data, uint stride, uint numPoints ) +{ + int numThreads, numBlocks; + computeNumBlocks (numPoints, 256, numBlocks, numThreads); + + // transfer point data to device + char* pntData; + size = numPoints * stride; + cudaMalloc( (void**) &pntData, size); + cudaMemcpy( pntData, data, size, cudaMemcpyHostToDevice); + + // execute the kernel + insertParticles<<< numBlocks, numThreads >>> ( pntData, stride ); + + // transfer data back to host + cudaMemcpy( data, pntData, cudaMemcpyDeviceToHost); + + // check if kernel invocation generated an error + CUT_CHECK_ERROR("Kernel execution failed"); + CUDA_SAFE_CALL(cudaGLUnmapBufferObject(vboPos)); +} \ No newline at end of file diff --git a/Extras/sph/fluids/fluid_system.h b/Extras/sph/fluids/fluid_system.h new file mode 100644 index 0000000..ddc1de3 --- /dev/null +++ b/Extras/sph/fluids/fluid_system.h @@ -0,0 +1,106 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 DEF_FLUID_SYS + #define DEF_FLUID_SYS + + #include + #include + #include + #include + #include + + #include "point_set.h" + #include "fluid.h" + + // Scalar params + #define SPH_SIMSIZE 4 + #define SPH_SIMSCALE 5 + #define SPH_VISC 6 + #define SPH_RESTDENSITY 7 + #define SPH_PMASS 8 + #define SPH_PRADIUS 9 + #define SPH_PDIST 10 + #define SPH_SMOOTHRADIUS 11 + #define SPH_INTSTIFF 12 + #define SPH_EXTSTIFF 13 + #define SPH_EXTDAMP 14 + #define SPH_LIMIT 15 + #define BOUND_ZMIN_SLOPE 16 + #define FORCE_XMAX_SIN 17 + #define FORCE_XMIN_SIN 18 + #define MAX_FRAC 19 + #define CLR_MODE 20 + + // Vector params + #define SPH_VOLMIN 7 + #define SPH_VOLMAX 8 + #define SPH_INITMIN 9 + #define SPH_INITMAX 10 + + // Toggles + #define SPH_GRID 0 + #define SPH_DEBUG 1 + #define WRAP_X 2 + #define WALL_BARRIER 3 + #define LEVY_BARRIER 4 + #define DRAIN_BARRIER 5 + #define USE_CUDA 6 + + #define MAX_PARAM 21 + #define BFLUID 2 + + class FluidSystem : public PointSet { + public: + FluidSystem (); + + // Basic Particle System + virtual void Initialize ( int mode, int nmax ); + virtual void Reset ( int nmax ); + virtual void Run (); + virtual void Advance (); + virtual int AddPoint (); + virtual int AddPointReuse (); + Fluid* AddFluid () { return (Fluid*) GetElem(0, AddPointReuse()); } + Fluid* GetFluid (int n) { return (Fluid*) GetElem(0, n); } + + // Smoothed Particle Hydrodynamics + void SPH_Setup (); + void SPH_CreateExample ( int n, int nmax ); + void SPH_DrawDomain (); + void SPH_ComputeKernels (); + + void SPH_ComputePressureSlow (); // O(n^2) + void SPH_ComputePressureGrid (); // O(kn) - spatial grid + + void SPH_ComputeForceSlow (); // O(n^2) + void SPH_ComputeForceGrid (); // O(kn) - spatial grid + void SPH_ComputeForceGridNC (); // O(cn) - neighbor table + + private: + + // Smoothed Particle Hydrodynamics + double m_R2, m_Poly6Kern, m_LapKern, m_SpikyKern; // Kernel functions + }; + +#endif diff --git a/Extras/sph/fluids/fluid_system_host.cu b/Extras/sph/fluids/fluid_system_host.cu new file mode 100644 index 0000000..07c5747 --- /dev/null +++ b/Extras/sph/fluids/fluid_system_host.cu @@ -0,0 +1,250 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 "C:\CUDA\common\inc\cutil.h" // cutil32.lib +#include +#include "../CUDA/btCudaDefines.h" + + + +#if defined(__APPLE__) || defined(MACOSX) + #include +#else + #include +#endif +#include + +#include "radixsort.cu" +#include "fluid_system_kern.cu" // build kernel + +FluidParams fcuda; + +__device__ char* bufPnts; // point data (array of Fluid structs) +__device__ char* bufPntSort; // point data (array of Fluid structs) +__device__ uint* bufHash[2]; // point grid hash +__device__ int* bufGrid; + + + +extern "C" +{ +// Initialize CUDA +void cudaInit(int argc, char **argv) +{ + //CUT_DEVICE_INIT(argc, argv); + + cudaDeviceProp p; + cudaGetDeviceProperties ( &p, 0); + + printf ( "-- CUDA --\n" ); + printf ( "Name: %s\n", p.name ); + printf ( "Revision: %d.%d\n", p.major, p.minor ); + printf ( "Global Mem: %d\n", p.totalGlobalMem ); + printf ( "Shared/Blk: %d\n", p.sharedMemPerBlock ); + printf ( "Regs/Blk: %d\n", p.regsPerBlock ); + printf ( "Warp Size: %d\n", p.warpSize ); + printf ( "Mem Pitch: %d\n", p.memPitch ); + printf ( "Thrds/Blk: %d\n", p.maxThreadsPerBlock ); + printf ( "Const Mem: %d\n", p.totalConstMem ); + printf ( "Clock Rate: %d\n", p.clockRate ); + + BT_GPU_SAFE_CALL ( cudaMalloc ( (void**) &bufPnts, 10 ) ); + BT_GPU_SAFE_CALL ( cudaMalloc ( (void**) &bufPntSort, 10 ) ); + BT_GPU_SAFE_CALL ( cudaMalloc ( (void**) &bufHash, 10 ) ); + BT_GPU_SAFE_CALL ( cudaMalloc ( (void**) &bufGrid, 10 ) ); +}; + +// Compute number of blocks to create +int iDivUp (int a, int b) { + return (a % b != 0) ? (a / b + 1) : (a / b); +} +void computeNumBlocks (int numPnts, int maxThreads, int &numBlocks, int &numThreads) +{ + numThreads = min( maxThreads, numPnts ); + numBlocks = iDivUp ( numPnts, numThreads ); +} + +void FluidClearCUDA () +{ + BT_GPU_SAFE_CALL ( cudaFree ( bufPnts ) ); + BT_GPU_SAFE_CALL ( cudaFree ( bufPntSort ) ); + BT_GPU_SAFE_CALL ( cudaFree ( bufHash[0] ) ); + BT_GPU_SAFE_CALL ( cudaFree ( bufHash[1] ) ); + BT_GPU_SAFE_CALL ( cudaFree ( bufGrid ) ); +} + + +void FluidSetupCUDA ( int num, int stride, float3 min, float3 max, float3 res, float3 size, int chk ) +{ + fcuda.min = make_float3(min.x, min.y, min.z); + fcuda.max = make_float3(max.x, max.y, max.z); + fcuda.res = make_float3(res.x, res.y, res.z); + fcuda.size = make_float3(size.x, size.y, size.z); + fcuda.pnts = num; + fcuda.delta.x = res.x / size.x; + fcuda.delta.y = res.y / size.y; + fcuda.delta.z = res.z / size.z; + fcuda.cells = res.x*res.y*res.z; + fcuda.chk = chk; + + computeNumBlocks ( fcuda.pnts, 256, fcuda.numBlocks, fcuda.numThreads); // particles + computeNumBlocks ( fcuda.cells, 256, fcuda.gridBlocks, fcuda.gridThreads); // grid cell + + fcuda.szPnts = (fcuda.numBlocks * fcuda.numThreads) * stride; + fcuda.szHash = (fcuda.numBlocks * fcuda.numThreads) * sizeof(uint2); // pairs + fcuda.szGrid = (fcuda.gridBlocks * fcuda.gridThreads) * sizeof(uint); + fcuda.stride = stride; + printf ( "pnts: %d, t:%dx%d=%d, bufPnts:%d, bufHash:%d\n", fcuda.pnts, fcuda.numBlocks, fcuda.numThreads, fcuda.numBlocks*fcuda.numThreads, fcuda.szPnts, fcuda.szHash ); + printf ( "grds: %d, t:%dx%d=%d, bufGrid:%d, Res: %dx%dx%d\n", fcuda.cells, fcuda.gridBlocks, fcuda.gridThreads, fcuda.gridBlocks*fcuda.gridThreads, fcuda.szGrid, (int) fcuda.res.x, (int) fcuda.res.y, (int) fcuda.res.z ); + + BT_GPU_SAFE_CALL ( cudaMalloc ( (void**) &bufPnts, fcuda.szPnts ) ); + BT_GPU_SAFE_CALL ( cudaMalloc ( (void**) &bufPntSort, fcuda.szPnts ) ); + BT_GPU_SAFE_CALL ( cudaMalloc ( (void**) &bufHash[0], fcuda.szHash ) ); + BT_GPU_SAFE_CALL ( cudaMalloc ( (void**) &bufHash[1], fcuda.szHash ) ); + BT_GPU_SAFE_CALL ( cudaMalloc ( (void**) &bufGrid, fcuda.szGrid ) ); + + printf ( "POINTERS\n"); + printf ( "bufPnts: %p\n", bufPnts ); + printf ( "bufPntSort: %p\n", bufPntSort ); + printf ( "bufHash0: %p\n", bufHash[0] ); + printf ( "bufHash1: %p\n", bufHash[1] ); + printf ( "bufGrid: %p\n", bufGrid ); + + BT_GPU_SAFE_CALL ( cudaMemcpyToSymbol ( simData, &fcuda, sizeof(FluidParams) ) ); + cudaThreadSynchronize (); +} + +void FluidParamCUDA ( float sim_scale, float smooth_rad, float mass, float rest, float stiff, float visc ) +{ + fcuda.sim_scale = sim_scale; + fcuda.smooth_rad = smooth_rad; + fcuda.r2 = smooth_rad * smooth_rad; + fcuda.pmass = mass; + fcuda.rest_dens = rest; + fcuda.stiffness = stiff; + fcuda.visc = visc; + + fcuda.pdist = pow ( fcuda.pmass / fcuda.rest_dens, 1/3.0f ); + fcuda.poly6kern = 315.0f / (64.0f * 3.141592 * pow( smooth_rad, 9.0f) ); + fcuda.spikykern = -45.0f / (3.141592 * pow( smooth_rad, 6.0f) ); + fcuda.lapkern = 45.0f / (3.141592 * pow( smooth_rad, 6.0f) ); + + BT_GPU_SAFE_CALL( cudaMemcpyToSymbol ( simData, &fcuda, sizeof(FluidParams) ) ); + cudaThreadSynchronize (); +} + +void TransferToCUDA ( char* data, int* grid, int numPoints ) +{ + BT_GPU_SAFE_CALL( cudaMemcpy ( bufPnts, data, numPoints * fcuda.stride, cudaMemcpyHostToDevice ) ); + cudaThreadSynchronize (); +} + +void TransferFromCUDA ( char* data, int* grid, int numPoints ) +{ + BT_GPU_SAFE_CALL( cudaMemcpy ( data, bufPntSort, numPoints * fcuda.stride, cudaMemcpyDeviceToHost ) ); + cudaThreadSynchronize (); + + BT_GPU_SAFE_CALL( cudaMemcpy ( grid, bufGrid, fcuda.cells * sizeof(uint), cudaMemcpyDeviceToHost ) ); +} + +void Grid_InsertParticlesCUDA () +{ + BT_GPU_SAFE_CALL( cudaMemset ( bufHash[0], 0, fcuda.szHash ) ); + + hashParticles<<< fcuda.numBlocks, fcuda.numThreads>>> ( bufPnts, (uint2*) bufHash[0], fcuda.pnts ); + BT_GPU_CHECK_ERROR( "Kernel execution failed"); + cudaThreadSynchronize (); + + //int buf[20000]; + /*printf ( "HASH: %d (%d)\n", fcuda.pnts, fcuda.numBlocks*fcuda.numThreads ); + BT_GPU_SAFE_CALL( cudaMemcpy ( buf, bufHash[0], fcuda.pnts * 2*sizeof(uint), cudaMemcpyDeviceToHost ) ); + //for (int n=0; n < fcuda.numBlocks*fcuda.numThreads; n++) { + for (int n=0; n < 100; n++) { + printf ( "%d: <%d,%d>\n", n, buf[n*2], buf[n*2+1] ); + }*/ + + RadixSort( (KeyValuePair *) bufHash[0], (KeyValuePair *) bufHash[1], fcuda.pnts, 32); + BT_GPU_CHECK_ERROR( "Kernel execution failed"); + cudaThreadSynchronize (); + + /*printf ( "HASH: %d (%d)\n", fcuda.pnts, fcuda.numBlocks*fcuda.numThreads ); + BT_GPU_SAFE_CALL( cudaMemcpy ( buf, bufHash[0], fcuda.pnts * 2*sizeof(uint), cudaMemcpyDeviceToHost ) ); + //for (int n=0; n < fcuda.numBlocks*fcuda.numThreads; n++) { + for (int n=0; n < 100; n++) { + printf ( "%d: <%d,%d>\n", n, buf[n*2], buf[n*2+1] ); + }*/ + + // insertParticles<<< fcuda.gridBlocks, fcuda.gridThreads>>> ( bufPnts, (uint2*) bufHash[0], bufGrid, fcuda.pnts, fcuda.cells ); + + BT_GPU_SAFE_CALL( cudaMemset ( bufGrid, NULL_HASH, fcuda.cells * sizeof(uint) ) ); + + insertParticlesRadix<<< fcuda.numBlocks, fcuda.numThreads>>> ( bufPnts, (uint2*) bufHash[0], bufGrid, bufPntSort, fcuda.pnts, fcuda.cells ); + BT_GPU_CHECK_ERROR( "Kernel execution failed"); + cudaThreadSynchronize (); + + /*printf ( "GRID: %d\n", fcuda.cells ); + BT_GPU_SAFE_CALL( cudaMemcpy ( buf, bufGrid, fcuda.cells * sizeof(uint), cudaMemcpyDeviceToHost ) ); + *for (int n=0; n < 100; n++) { + printf ( "%d: %d\n", n, buf[n]); + }*/ +} + +void SPH_ComputePressureCUDA () +{ + computePressure<<< fcuda.numBlocks, fcuda.numThreads>>> ( bufPntSort, bufGrid, (uint2*) bufHash[0], fcuda.pnts ); + BT_GPU_CHECK_ERROR( "Kernel execution failed"); + cudaThreadSynchronize (); +} + +void SPH_ComputeForceCUDA () +{ + //-- standard force + //computeForce<<< fcuda.numBlocks, fcuda.numThreads>>> ( bufPntSort, bufGrid, (uint2*) bufHash[0], fcuda.pnts ); + + // Force using neighbor table + computeForceNbr<<< fcuda.numBlocks, fcuda.numThreads>>> ( bufPntSort, fcuda.pnts ); + BT_GPU_CHECK_ERROR( "Kernel execution failed"); + cudaThreadSynchronize (); +} + +void SPH_AdvanceCUDA ( float dt, float ss ) +{ + advanceParticles<<< fcuda.numBlocks, fcuda.numThreads>>> ( bufPntSort, fcuda.pnts, dt, ss ); + BT_GPU_CHECK_ERROR( "Kernel execution failed"); + cudaThreadSynchronize (); +} + +} // extern C + + + + + //----------- Per frame: Malloc/Free, Host<->Device + // transfer point data to device + /*char* pntData; + int size = (fcuda.numBlocks*fcuda.numThreads) * stride; + cudaMalloc( (void**) &pntData, size); + cudaMemcpy( pntData, data, numPoints*stride, cudaMemcpyHostToDevice); + insertParticles<<< fcuda.numBlocks, fcuda.numThreads >>> ( pntData, stride, numPoints ); + cudaMemcpy( data, pntData, numPoints*stride, cudaMemcpyDeviceToHost); + cudaFree( pntData );*/ diff --git a/Extras/sph/fluids/fluid_system_host.cuh b/Extras/sph/fluids/fluid_system_host.cuh new file mode 100644 index 0000000..355b57d --- /dev/null +++ b/Extras/sph/fluids/fluid_system_host.cuh @@ -0,0 +1,63 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 +#include // for cudaStream_t + +typedef unsigned int uint; // should be 4-bytes on CUDA +typedef unsigned char uchar; // should be 1-bytes on CUDA + +struct FluidParams { + int numThreads, numBlocks; + int gridThreads, gridBlocks; + int szPnts, szHash, szGrid; + int stride, pnts, cells; + int chk; + float smooth_rad, r2, sim_scale, visc; + float3 min, max, res, size, delta; + + float pdist, pmass, rest_dens, stiffness; + float poly6kern, spikykern, lapkern; + +}; + +extern "C" +{ + +void cudaInit(int argc, char **argv); + +void FluidClearCUDA (); +void FluidSetupCUDA ( int num, int stride, float3 min, float3 max, float3 res, float3 size, int chk ); +void FluidParamCUDA ( float sim_scale, float smooth_rad, float mass, float rest, float stiff, float visc ); + +void TransferToCUDA ( char* data, int* grid, int numPoints ); +void TransferFromCUDA ( char* data, int* grid, int numPoints ); + +void Grid_InsertParticlesCUDA (); +void SPH_ComputePressureCUDA (); +void SPH_ComputeForceCUDA (); +void SPH_AdvanceCUDA ( float dt, float ss ); + +} + + diff --git a/Extras/sph/fluids/fluid_system_kern.cu b/Extras/sph/fluids/fluid_system_kern.cu new file mode 100644 index 0000000..235b463 --- /dev/null +++ b/Extras/sph/fluids/fluid_system_kern.cu @@ -0,0 +1,402 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 _PARTICLES_KERNEL_H_ + #define _PARTICLES_KERNEL_H_ + + #include + #include + + #include "fluid_system_host.cuh" + + #define TOTAL_THREADS 65536 + #define BLOCK_THREADS 256 + #define MAX_NBR 80 + + __constant__ FluidParams simData; // simulation data (on device) + + __device__ int bufNeighbor[ TOTAL_THREADS*MAX_NBR ]; + __device__ float bufNdist[ TOTAL_THREADS*MAX_NBR ]; + + #define COLOR(r,g,b) ( (uint((r)*255.0f)<<24) | (uint((g)*255.0f)<<16) | (uint((b)*255.0f)<<8) ) + #define COLORA(r,g,b,a) ( (uint((r)*255.0f)<<24) | (uint((g)*255.0f)<<16) | (uint((b)*255.0f)<<8) | uint((a)*255.0f) ) + + #define NULL_HASH 333333 + + #define OFFSET_CLR 12 + #define OFFSET_NEXT 16 + #define OFFSET_VEL 20 + #define OFFSET_VEVAL 32 + #define OFFSET_PRESS 48 + #define OFFSET_DENS 52 + #define OFFSET_FORCE 56 + + + __global__ void hashParticles ( char* bufPnts, uint2* bufHash, int numPnt ) + { + uint ndx = __mul24(blockIdx.x, blockDim.x) + threadIdx.x; // particle index + float3* pos = (float3*) (bufPnts + __mul24(ndx, simData.stride) ); + int gz = (pos->z - simData.min.z) * simData.delta.z ; + int gy = (pos->y - simData.min.y) * simData.delta.y ; + int gx = (pos->x - simData.min.x) * simData.delta.x ; + if ( ndx >= numPnt || gx < 0 || gz > simData.res.x-1 || gy < 0 || gy > simData.res.y-1 || gz < 0 || gz > simData.res.z-1 ) + bufHash[ndx] = make_uint2( NULL_HASH, ndx ); + else + bufHash[ndx] = make_uint2( __mul24(__mul24(gz, (int) simData.res.y)+gy, (int) simData.res.x) + gx, ndx ); + + __syncthreads (); + } + + __global__ void insertParticles ( char* bufPnts, uint2* bufHash, int* bufGrid, int numPnt, int numGrid ) + { + uint grid_ndx = __mul24(blockIdx.x, blockDim.x) + threadIdx.x; // grid cell index + + bufPnts += OFFSET_NEXT; + bufGrid[grid_ndx] = -1; + for (int n=0; n < numPnt; n++) { + if ( bufHash[n].x == grid_ndx ) { + *(int*) (bufPnts + __mul24(bufHash[n].y, simData.stride)) = bufGrid[grid_ndx]; + bufGrid[grid_ndx] = bufHash[n].y; + } + } + __syncthreads (); + } + + __global__ void insertParticlesRadix ( char* bufPnts, uint2* bufHash, int* bufGrid, char* bufPntSort, int numPnt, int numGrid ) + { + uint ndx = __mul24(blockIdx.x, blockDim.x) + threadIdx.x; // particle index + + uint2 bufHashSort = bufHash[ndx]; + + __shared__ uint sharedHash[257]; + sharedHash[threadIdx.x+1] = bufHashSort.x; + if ( ndx > 0 && threadIdx.x == 0 ) { + volatile uint2 prevData = bufHash[ndx-1]; + sharedHash[0] = prevData.x; + } + __syncthreads (); + + if ( (ndx == 0 || bufHashSort.x != sharedHash[threadIdx.x]) && bufHashSort.x != NULL_HASH ) { + bufGrid [ bufHashSort.x ] = ndx; + } + if ( ndx < numPnt ) { + char* src = bufPnts + __mul24( bufHashSort.y, simData.stride ); + char* dest = bufPntSort + __mul24( ndx, simData.stride ); + + *(float3*)(dest) = *(float3*)(src); + *(uint*) (dest + OFFSET_CLR) = *(uint*) (src + OFFSET_CLR); + *(float3*)(dest + OFFSET_VEL) = *(float3*)(src + OFFSET_VEL); + *(float3*)(dest + OFFSET_VEVAL) = *(float3*)(src + OFFSET_VEVAL); + + *(float*) (dest + OFFSET_DENS) = 0.0; + *(float*) (dest + OFFSET_PRESS) = 0.0; + *(float3*) (dest + OFFSET_FORCE)= make_float3(0,0,0); + *(int*) (dest + OFFSET_NEXT) = bufHashSort.x; + } + + __syncthreads (); + + } + + //__shared__ int ncount [ BLOCK_THREADS ]; + + __device__ float contributePressure ( int pndx, float3* p, int qndx, int grid_ndx, char* bufPnts, uint2* bufHash ) + { + float3* qpos; + float3 dist; + float dsq, c, sum; + float d = simData.sim_scale; + int nbr = __mul24(pndx, MAX_NBR); + + sum = 0.0; + for ( ; qndx < simData.pnts; qndx++ ) { + + if ( bufHash[qndx].x != grid_ndx || qndx == NULL_HASH) break; + + if ( qndx != pndx ) { + qpos = (float3*) ( bufPnts + __mul24(qndx, simData.stride )); + + dist.x = ( p->x - qpos->x )*d; // dist in cm + dist.y = ( p->y - qpos->y )*d; + dist.z = ( p->z - qpos->z )*d; + dsq = (dist.x*dist.x + dist.y*dist.y + dist.z*dist.z); + if ( dsq < simData.r2 ) { + c = simData.r2 - dsq; + sum += c * c * c; + if ( bufNeighbor[nbr] < MAX_NBR ) { + bufNeighbor[ nbr+bufNeighbor[nbr] ] = qndx; + bufNdist[ nbr+bufNeighbor[nbr] ] = sqrt(dsq); + bufNeighbor[nbr]++; + } + } + } + //curr = *(int*) (bufPnts + __mul24(curr, simData.stride) + OFFSET_NEXT); + } + return sum; + } + + /*if ( ncount[threadIdx.x] < MAX_NBR ) { + bufNeighbor [ nbr + ncount[threadIdx.x] ] = curr; + bufNdist [ nbr + ncount[threadIdx.x] ] = sqrt(dsq); + ncount[threadIdx.x]++; + }*/ + + __global__ void computePressure ( char* bufPntSort, int* bufGrid, uint2* bufHash, int numPnt ) + { + uint ndx = __mul24(blockIdx.x, blockDim.x) + threadIdx.x; // particle index + + //if ( ndx < 1024 ) { + + float3* pos = (float3*) (bufPntSort + __mul24(ndx, simData.stride)); + + // Find 2x2x2 grid cells + // - Use registers only, no arrays (local-memory too slow) + int3 cell; + int gc0, gc1, gc2, gc3, gc4, gc5, gc6, gc7; + float gs = simData.smooth_rad / simData.sim_scale; + + cell.x = max(0, (int)((-gs + pos->x - simData.min.x) * simData.delta.x)); + cell.y = max(0, (int)((-gs + pos->y - simData.min.y) * simData.delta.y)); + cell.z = max(0, (int)((-gs + pos->z - simData.min.z) * simData.delta.z)); + gc0 = __mul24(__mul24(cell.z, simData.res.y) + cell.y, simData.res.x) + cell.x; + gc1 = gc0 + 1; + gc2 = gc0 + simData.res.x; + gc3 = gc2 + 1; + if ( cell.z+1 < simData.res.z ) { + gc4 = gc0 + __mul24(simData.res.x, simData.res.y); + gc5 = gc4 + 1; + gc6 = gc4 + simData.res.x; + gc7 = gc6 + 1; + } + if ( cell.x+1 >= simData.res.x ) { + gc1 = -1; gc3 = -1; + gc5 = -1; gc7 = -1; + } + if ( cell.y+1 >= simData.res.y ) { + gc2 = -1; gc3 = -1; + gc6 = -1; gc7 = -1; + } + // Sum Pressure + float sum = 0.0; + bufNeighbor[ __mul24(ndx, MAX_NBR) ] = 1; + if (gc0 != -1 ) sum += contributePressure ( ndx, pos, bufGrid[gc0], gc0, bufPntSort, bufHash ); + if (gc1 != -1 ) sum += contributePressure ( ndx, pos, bufGrid[gc1], gc1, bufPntSort, bufHash ); + if (gc2 != -1 ) sum += contributePressure ( ndx, pos, bufGrid[gc2], gc2, bufPntSort, bufHash ); + if (gc3 != -1 ) sum += contributePressure ( ndx, pos, bufGrid[gc3], gc3, bufPntSort, bufHash ); + if (gc4 != -1 ) sum += contributePressure ( ndx, pos, bufGrid[gc4], gc4, bufPntSort, bufHash ); + if (gc5 != -1 ) sum += contributePressure ( ndx, pos, bufGrid[gc5], gc5, bufPntSort, bufHash ); + if (gc6 != -1 ) sum += contributePressure ( ndx, pos, bufGrid[gc6], gc6, bufPntSort, bufHash ); + if (gc7 != -1 ) sum += contributePressure ( ndx, pos, bufGrid[gc7], gc7, bufPntSort, bufHash ); + + // Compute Density & Pressure + sum = sum * simData.pmass * simData.poly6kern; + if ( sum == 0.0 ) sum = 1.0; + *(float*) ((char*)pos + OFFSET_PRESS) = ( sum - simData.rest_dens ) * simData.stiffness; + *(float*) ((char*)pos + OFFSET_DENS) = 1.0f / sum; + + //} + //__syncthreads (); + } + + __device__ void contributeForce ( float3& force, int pndx, float3* p, int qndx, int grid_ndx, char* bufPnts, uint2* bufHash ) + { + float press = *(float*) ((char*)p + OFFSET_PRESS); + float dens = *(float*) ((char*)p + OFFSET_DENS); + float3 veval = *(float3*) ((char*)p + OFFSET_VEVAL ); + float3 qeval, dist; + float c, ndistj, dsq; + float pterm, dterm, vterm; + float3* qpos; + float d = simData.sim_scale; + + vterm = simData.lapkern * simData.visc; + + for ( ; qndx < simData.pnts; qndx++ ) { + + if ( bufHash[qndx].x != grid_ndx || qndx == NULL_HASH) break; + + if ( qndx != pndx ) { + qpos = (float3*) ( bufPnts + __mul24(qndx, simData.stride )); + + dist.x = ( p->x - qpos->x )*d; // dist in cm + dist.y = ( p->y - qpos->y )*d; + dist.z = ( p->z - qpos->z )*d; + dsq = (dist.x*dist.x + dist.y*dist.y + dist.z*dist.z); + if ( dsq < simData.r2 ) { + ndistj = sqrt(dsq); + c = ( simData.smooth_rad - ndistj ); + dist.x = ( p->x - qpos->x )*d; // dist in cm + dist.y = ( p->y - qpos->y )*d; + dist.z = ( p->z - qpos->z )*d; + pterm = -0.5f * c * simData.spikykern * ( press + *(float*)((char*)qpos+OFFSET_PRESS) ) / ndistj; + dterm = c * dens * *(float*)((char*)qpos+OFFSET_DENS); + qeval = *(float3*)((char*)qpos+OFFSET_VEVAL); + force.x += ( pterm * dist.x + vterm * ( qeval.x - veval.x )) * dterm; + force.y += ( pterm * dist.y + vterm * ( qeval.y - veval.y )) * dterm; + force.z += ( pterm * dist.z + vterm * ( qeval.z - veval.z )) * dterm; + } + } + } + } + + + + __global__ void computeForce ( char* bufPntSort, int* bufGrid, uint2* bufHash, int numPnt ) + { + uint ndx = __mul24(blockIdx.x, blockDim.x) + threadIdx.x; // particle index + + //if ( ndx < numPnt ) { + + float3* pos = (float3*) (bufPntSort + __mul24(ndx, simData.stride)); + + // Find 2x2x2 grid cells + // - Use registers only, no arrays (local-memory too slow) + int3 cell; + int gc0, gc1, gc2, gc3, gc4, gc5, gc6, gc7; + float gs = simData.smooth_rad / simData.sim_scale; + + cell.x = max(0, (int)((-gs + pos->x - simData.min.x) * simData.delta.x)); + cell.y = max(0, (int)((-gs + pos->y - simData.min.y) * simData.delta.y)); + cell.z = max(0, (int)((-gs + pos->z - simData.min.z) * simData.delta.z)); + gc0 = __mul24(__mul24(cell.z, simData.res.y) + cell.y, simData.res.x) + cell.x; + gc1 = gc0 + 1; + gc2 = gc0 + simData.res.x; + gc3 = gc2 + 1; + if ( cell.z+1 < simData.res.z ) { + gc4 = gc0 + __mul24(simData.res.x, simData.res.y); + gc5 = gc4 + 1; + gc6 = gc4 + simData.res.x; + gc7 = gc6 + 1; + } + if ( cell.x+1 >= simData.res.x ) { + gc1 = -1; gc3 = -1; + gc5 = -1; gc7 = -1; + } + if ( cell.y+1 >= simData.res.y ) { + gc2 = -1; gc3 = -1; + gc6 = -1; gc7 = -1; + } + // Sum Pressure + float3 force = make_float3(0,0,0); + if (gc0 != -1 ) contributeForce ( force, ndx, pos, bufGrid[gc0], gc0, bufPntSort, bufHash ); + if (gc1 != -1 ) contributeForce ( force, ndx, pos, bufGrid[gc1], gc1, bufPntSort, bufHash ); + if (gc2 != -1 ) contributeForce ( force, ndx, pos, bufGrid[gc2], gc2, bufPntSort, bufHash ); + if (gc3 != -1 ) contributeForce ( force, ndx, pos, bufGrid[gc3], gc3, bufPntSort, bufHash ); + if (gc4 != -1 ) contributeForce ( force, ndx, pos, bufGrid[gc4], gc4, bufPntSort, bufHash ); + if (gc5 != -1 ) contributeForce ( force, ndx, pos, bufGrid[gc5], gc5, bufPntSort, bufHash ); + if (gc6 != -1 ) contributeForce ( force, ndx, pos, bufGrid[gc6], gc6, bufPntSort, bufHash ); + if (gc7 != -1 ) contributeForce ( force, ndx, pos, bufGrid[gc7], gc7, bufPntSort, bufHash ); + + // Update Force + *(float3*) ((char*)pos + OFFSET_FORCE ) = force; + + //} + //__syncthreads (); + } + + + __global__ void computeForceNbr ( char* bufPntSort, int numPnt ) + { + uint ndx = __mul24(blockIdx.x, blockDim.x) + threadIdx.x; // particle index + + if ( ndx < numPnt ) { + + float3* pos = (float3*) (bufPntSort + __mul24(ndx, simData.stride)); + + float3* qpos; + float press = *(float*) ((char*)pos + OFFSET_PRESS); + float dens = *(float*) ((char*)pos + OFFSET_DENS); + float3 veval = *(float3*) ((char*)pos + OFFSET_VEVAL ); + float3 qeval, dist, force; + float d = simData.sim_scale; + float c, ndistj; + float pterm, dterm, vterm; + vterm = simData.lapkern * simData.visc; + int nbr = __mul24(ndx, MAX_NBR); + + int ncnt = bufNeighbor[ nbr ]; + + force = make_float3(0,0,0); + for (int j=1; j < ncnt; j++) { // base 1, n[0] = count + ndistj = bufNdist[ nbr+j ]; + qpos = (float3*) (bufPntSort + __mul24( bufNeighbor[ nbr+j ], simData.stride) ); + c = ( simData.smooth_rad - ndistj ); + dist.x = ( pos->x - qpos->x )*d; // dist in cm + dist.y = ( pos->y - qpos->y )*d; + dist.z = ( pos->z - qpos->z )*d; + pterm = -0.5f * c * simData.spikykern * ( press + *(float*)((char*)qpos+OFFSET_PRESS) ) / ndistj; + dterm = c * dens * *(float*)((char*)qpos+OFFSET_DENS); + qeval = *(float3*)((char*)qpos+OFFSET_VEVAL); + force.x += ( pterm * dist.x + vterm * ( qeval.x - veval.x )) * dterm; + force.y += ( pterm * dist.y + vterm * ( qeval.y - veval.y )) * dterm; + force.z += ( pterm * dist.z + vterm * ( qeval.z - veval.z )) * dterm; + } + *(float3*) ((char*)pos + OFFSET_FORCE ) = force; + + } + + } + + __global__ void advanceParticles ( char* bufPntSort, int numPnt, float dt, float ss ) + { + uint ndx = __mul24(blockIdx.x, blockDim.x) + threadIdx.x; // particle index + + if ( ndx < numPnt ) { + + // Get particle vars + float3* pos = (float3*) (bufPntSort + __mul24(ndx, simData.stride)); + float3* vel = (float3*) ((char*)pos + OFFSET_VEL ); + float3* vel_eval = (float3*) ((char*)pos + OFFSET_VEVAL ); + float3 accel = *(float3*) ((char*)pos + OFFSET_FORCE ); + float3 vcurr, vnext; + + // Leapfrog integration + accel.x *= 0.00020543; // NOTE - To do: SPH_PMASS should be passed in + accel.y *= 0.00020543; + accel.z *= 0.00020543; + accel.z -= 9.8; + + vcurr = *vel; + vnext.x = accel.x*dt + vcurr.x; + vnext.y = accel.y*dt + vcurr.y; + vnext.z = accel.z*dt + vcurr.z; // v(t+1/2) = v(t-1/2) + a(t) dt + + accel.x = (vcurr.x + vnext.x) * 0.5; // v(t+1) = [v(t-1/2) + v(t+1/2)] * 0.5 used to compute forces later + accel.y = (vcurr.y + vnext.y) * 0.5; // v(t+1) = [v(t-1/2) + v(t+1/2)] * 0.5 used to compute forces later + accel.z = (vcurr.z + vnext.z) * 0.5; // v(t+1) = [v(t-1/2) + v(t+1/2)] * 0.5 used to compute forces later + + *vel_eval = accel; + *vel = vnext; + + dt /= simData.sim_scale; + vnext.x = pos->x + vnext.x*dt; + vnext.y = pos->y + vnext.y*dt; + vnext.z = pos->z + vnext.z*dt; + *pos = vnext; // p(t+1) = p(t) + v(t+1/2) dt + } + + __syncthreads (); + } + +#endif diff --git a/Extras/sph/fluids/fluid_system_kern.cuh b/Extras/sph/fluids/fluid_system_kern.cuh new file mode 100644 index 0000000..c1f0d81 --- /dev/null +++ b/Extras/sph/fluids/fluid_system_kern.cuh @@ -0,0 +1,45 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 _PARTICLES_KERNEL_H_ + #define _PARTICLES_KERNEL_H_ + + #include + #include + #include "cutil_math.h" + #include "math_constants.h" + + // Insert particles in grid + + __global__ void insertParticles ( char* pntData, uint pntStride ) + { + int index = __mul24(blockIdx.x,blockDim.x) + threadIdx.x; + float4 p = *(float4*) (pntData + index*pntStride); + + // get address in grid + int3 gridPos = calcGridPos(p); + + addParticleToCell(gridPos, index, gridCounters, gridCells); + } + + +#endif diff --git a/Extras/sph/fluids/radixsort.cu b/Extras/sph/fluids/radixsort.cu new file mode 100644 index 0000000..24c85c6 --- /dev/null +++ b/Extras/sph/fluids/radixsort.cu @@ -0,0 +1,79 @@ +/* + * Copyright 1993-2006 NVIDIA Corporation. All rights reserved. + * + * NOTICE TO USER: + * + * This source code is subject to NVIDIA ownership rights under U.S. and + * international Copyright laws. + * + * NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE + * CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR + * IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. + * IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOURCE CODE. + * + * U.S. Government End Users. This source code is a "commercial item" as + * that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of + * "commercial computer software" and "commercial computer software + * documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) + * and is provided to the U.S. Government only as a commercial end item. + * Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through + * 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the + * source code with only those rights set forth herein. + */ + +/* Radixsort project with key/value and arbitrary datset size support + * which demonstrates the use of CUDA in a multi phase sorting + * computation. + * Host code. + */ + +#include "radixsort.cuh" +#include "radixsort_kernel.cu" + +extern "C" +{ + +//////////////////////////////////////////////////////////////////////////////// +//! Perform a radix sort +//! Sorting performed in place on passed arrays. +//! +//! @param pData0 input and output array - data will be sorted +//! @param pData1 additional array to allow ping pong computation +//! @param elements number of elements to sort +//////////////////////////////////////////////////////////////////////////////// +void RadixSort(KeyValuePair *pData0, KeyValuePair *pData1, uint elements, uint bits) +{ + // Round element count to total number of threads for efficiency + uint elements_rounded_to_3072; + int modval = elements % 3072; + if( modval == 0 ) + elements_rounded_to_3072 = elements; + else + elements_rounded_to_3072 = elements + (3072 - (modval)); + + // Iterate over n bytes of y bit word, using each byte to sort the list in turn + for (uint shift = 0; shift < bits; shift += RADIX) + { + // Perform one round of radix sorting + + // Generate per radix group sums radix counts across a radix group + RadixSum<<>>(pData0, elements, elements_rounded_to_3072, shift); + // Prefix sum in radix groups, and then between groups throughout a block + RadixPrefixSum<<>>(); + // Sum the block offsets and then shuffle data into bins + RadixAddOffsetsAndShuffle<<>>(pData0, pData1, elements, elements_rounded_to_3072, shift); + + // Exchange data pointers + KeyValuePair* pTemp = pData0; + pData0 = pData1; + pData1 = pTemp; + } +} + +} diff --git a/Extras/sph/fluids/radixsort.cuh b/Extras/sph/fluids/radixsort.cuh new file mode 100644 index 0000000..538bb11 --- /dev/null +++ b/Extras/sph/fluids/radixsort.cuh @@ -0,0 +1,63 @@ +/* + * Copyright 1993-2006 NVIDIA Corporation. All rights reserved. + * + * NOTICE TO USER: + * + * This source code is subject to NVIDIA ownership rights under U.S. and + * international Copyright laws. + * + * NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE + * CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR + * IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. + * IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOURCE CODE. + * + * U.S. Government End Users. This source code is a "commercial item" as + * that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of + * "commercial computer software" and "commercial computer software + * documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) + * and is provided to the U.S. Government only as a commercial end item. + * Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through + * 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the + * source code with only those rights set forth herein. + */ + +/* Radixsort project which demonstrates the use of CUDA in a multi phase + * sorting computation. + * Type definitions. + */ + +#ifndef _RADIXSORT_H_ +#define _RADIXSORT_H_ + +#include + +#define SYNCIT __syncthreads() + +// Use 16 bit keys/values +#define SIXTEEN 0 + +typedef unsigned int uint; +typedef unsigned short ushort; + +#if SIXTEEN +typedef struct __align__(4) { + ushort key; + ushort value; +#else +typedef struct __align__(8) { + uint key; + uint value; +#endif +} KeyValuePair; + +extern "C" { + void RadixSort(KeyValuePair *pData0, KeyValuePair *pData1, uint elements, uint bits); +} + +#endif // #ifndef _RADIXSORT_H_ diff --git a/Extras/sph/fluids/radixsort_kernel.cu b/Extras/sph/fluids/radixsort_kernel.cu new file mode 100644 index 0000000..dad689b --- /dev/null +++ b/Extras/sph/fluids/radixsort_kernel.cu @@ -0,0 +1,577 @@ +/* + * Copyright 1993-2006 NVIDIA Corporation. All rights reserved. + * + * NOTICE TO USER: + * + * This source code is subject to NVIDIA ownership rights under U.S. and + * international Copyright laws. + * + * NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE + * CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR + * IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. + * IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOURCE CODE. + * + * U.S. Government End Users. This source code is a "commercial item" as + * that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of + * "commercial computer software" and "commercial computer software + * documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) + * and is provided to the U.S. Government only as a commercial end item. + * Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through + * 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the + * source code with only those rights set forth herein. + */ + +/* Radixsort project with key/value and arbitrary datset size support + * which demonstrates the use of CUDA in a multi phase sorting + * computation. + * Device code. + */ + +#ifndef _RADIXSORT_KERNEL_H_ +#define _RADIXSORT_KERNEL_H_ + +#include +#include "radixsort.cuh" + +#define SYNCIT __syncthreads() + +static const int NUM_SMS = 16; +static const int NUM_THREADS_PER_SM = 192; +static const int NUM_THREADS_PER_BLOCK = 64; +//static const int NUM_THREADS = NUM_THREADS_PER_SM * NUM_SMS; +static const int NUM_BLOCKS = (NUM_THREADS_PER_SM / NUM_THREADS_PER_BLOCK) * NUM_SMS; +static const int RADIX = 8; // Number of bits per radix sort pass +static const int RADICES = 1 << RADIX; // Number of radices +static const int RADIXMASK = RADICES - 1; // Mask for each radix sort pass +#if SIXTEEN +static const int RADIXBITS = 16; // Number of bits to sort over +#else +static const int RADIXBITS = 32; // Number of bits to sort over +#endif +static const int RADIXTHREADS = 16; // Number of threads sharing each radix counter +static const int RADIXGROUPS = NUM_THREADS_PER_BLOCK / RADIXTHREADS; // Number of radix groups per CTA +static const int TOTALRADIXGROUPS = NUM_BLOCKS * RADIXGROUPS; // Number of radix groups for each radix +static const int SORTRADIXGROUPS = TOTALRADIXGROUPS * RADICES; // Total radix count +static const int GRFELEMENTS = (NUM_THREADS_PER_BLOCK / RADIXTHREADS) * RADICES; +static const int GRFSIZE = GRFELEMENTS * sizeof(uint); + +// Prefix sum variables +static const int PREFIX_NUM_THREADS_PER_SM = NUM_THREADS_PER_SM; +static const int PREFIX_NUM_THREADS_PER_BLOCK = PREFIX_NUM_THREADS_PER_SM; +static const int PREFIX_NUM_BLOCKS = (PREFIX_NUM_THREADS_PER_SM / PREFIX_NUM_THREADS_PER_BLOCK) * NUM_SMS; +static const int PREFIX_BLOCKSIZE = SORTRADIXGROUPS / PREFIX_NUM_BLOCKS; +static const int PREFIX_GRFELEMENTS = PREFIX_BLOCKSIZE + 2 * PREFIX_NUM_THREADS_PER_BLOCK; +static const int PREFIX_GRFSIZE = PREFIX_GRFELEMENTS * sizeof(uint); + +// Shuffle variables +static const int SHUFFLE_GRFOFFSET = RADIXGROUPS * RADICES; +static const int SHUFFLE_GRFELEMENTS = SHUFFLE_GRFOFFSET + PREFIX_NUM_BLOCKS; +static const int SHUFFLE_GRFSIZE = SHUFFLE_GRFELEMENTS * sizeof(uint); + + +#define SDATA( index) CUT_BANK_CHECKER(sdata, index) + +// Prefix sum data +uint gRadixSum[TOTALRADIXGROUPS * RADICES]; +__device__ uint dRadixSum[TOTALRADIXGROUPS * RADICES]; +uint gRadixBlockSum[PREFIX_NUM_BLOCKS]; +__device__ uint dRadixBlockSum[PREFIX_NUM_BLOCKS]; + +extern __shared__ uint sRadixSum[]; + + + +//////////////////////////////////////////////////////////////////////////////// +//! Perform a radix sum on the list to be sorted. Each SM holds a set of +//! radix counters for each group of RADIXGROUPS thread in the GRF. +//! +//! @param pData input data +//! @param elements total number of elements +//! @param elements_rounded_to_3072 total number of elements rounded up to the +//! nearest multiple of 3072 +//! @param shift the shift (0 to 24) that we are using to obtain the correct +//! byte +//////////////////////////////////////////////////////////////////////////////// +__global__ void RadixSum(KeyValuePair *pData, uint elements, uint elements_rounded_to_3072, uint shift) +{ + uint pos = threadIdx.x; + + // Zero radix counts + while (pos < GRFELEMENTS) + { + sRadixSum[pos] = 0; + pos += NUM_THREADS_PER_BLOCK; + } + + // Sum up data + // Source addresses computed so that each thread is reading from a block of + // consecutive addresses so there are no conflicts between threads + // They then loop over their combined region and the next batch works elsewhere. + // So threads 0 to 16 work on memory 0 to 320. + // First reading 0,1,2,3...15 then 16,17,18,19...31 and so on + // optimising parallel access to shared memory by a thread accessing 16*threadID + // The next radix group runs from 320 to 640 and the same applies in that region + uint tmod = threadIdx.x % RADIXTHREADS; + uint tpos = threadIdx.x / RADIXTHREADS; + + // Take the rounded element list size so that all threads have a certain size dataset to work with + // and no zero size datasets confusing the issue + // By using a multiple of 3072 we ensure that all threads have elements + // to work with until the last phase, at which point we individually test + uint element_fraction = elements_rounded_to_3072 / TOTALRADIXGROUPS; + + // Generate range + // Note that it is possible for both pos and end to be past the end of the element set + // which will be caught later. + pos = (blockIdx.x * RADIXGROUPS + tpos) * element_fraction; + uint end = pos + element_fraction; + pos += tmod; + //printf("pos: %d\n", pos); + __syncthreads(); + + while (pos < end ) + { + uint key = 0; + + // Read first data element if we are in the set of elements + //if( pos < elements ) + //key = pData[pos].key; + KeyValuePair kvp; + // Read first data element, both items at once as the memory will want to coalesce like that anyway + if (pos < elements) + kvp = pData[pos]; + else + kvp.key = 0; + key = kvp.key; + + + // Calculate position of radix counter to increment + // There are RADICES radices in each pass (256) + // and hence this many counters for bin grouping + // Multiply by RADIXGROUPS (4) to spread through memory + // and into 4 radix groups + uint p = ((key >> shift) & RADIXMASK) * RADIXGROUPS; + + // Increment radix counters + // Each radix group has its own set of counters + // so we add the thread position [0-3], ie the group index. + // We slow down here and take at least 16 cycles to write to the summation boxes + // but other groups will only conflict with themselves and so can also be writing + // 16 cycles here at least avoids retries. + uint ppos = p + tpos; + + // If we are past the last element we don't want to do anything + // We do have to check each time, however, to ensure that all + // threads sync on each sync here. + if (tmod == 0 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 1 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 2 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 3 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 4 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 5 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 6 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 7 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 8 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 9 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 10 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 11 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 12 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 13 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 14 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + if (tmod == 15 && pos < elements) + sRadixSum[ppos]++; + SYNCIT; + + pos += RADIXTHREADS; + + } + + __syncthreads(); + + __syncthreads(); + + // Output radix sums into separate memory regions for each radix group + // So this memory then is layed out: + // 0...... 192..... 384 ................ 192*256 + // ie all 256 bins for each radix group + // in there: + // 0.............192 + // 0 4 8 12... - block idx * 4 + // And in the block boxes we see the 4 radix groups for that block + // So 0-192 should contain bin 0 for each radix group, and so on + uint offset = blockIdx.x * RADIXGROUPS; + uint row = threadIdx.x / RADIXGROUPS; + uint column = threadIdx.x % RADIXGROUPS; + while (row < RADICES) + { + dRadixSum[offset + row * TOTALRADIXGROUPS + column] = sRadixSum[row * RADIXGROUPS + column]; + row += NUM_THREADS_PER_BLOCK / RADIXGROUPS; + } +} + +//////////////////////////////////////////////////////////////////////////////// +//! Performs first part of parallel prefix sum - individual sums of each radix +//! count. By the end of this we have prefix sums on a block level in dRadixSum +//! and totals for blocks in dRadixBlockSum. +//////////////////////////////////////////////////////////////////////////////// +__global__ void RadixPrefixSum() +{ + // Read radix groups in offset by one in the GRF so a zero can be inserted at the beginning + // and the final sum of all radix counts summed here is tacked onto the end for reading by + // the next stage + // Each block in this case is the full number of threads per SM (and hence the total number + // of radix groups), 192. We should then have the total set of offsets for an entire radix + // group by the end of this stage + // Device mem addressing + + uint brow = blockIdx.x * (RADICES / PREFIX_NUM_BLOCKS); + uint drow = threadIdx.x / TOTALRADIXGROUPS; // In default parameterisation this is always 0 + uint dcolumn = threadIdx.x % TOTALRADIXGROUPS; // And similarly this is always the same as threadIdx.x + uint dpos = (brow + drow) * TOTALRADIXGROUPS + dcolumn; + uint end = ((blockIdx.x + 1) * (RADICES / PREFIX_NUM_BLOCKS)) * TOTALRADIXGROUPS; + // Shared mem addressing + uint srow = threadIdx.x / (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK); + uint scolumn = threadIdx.x % (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK); + uint spos = srow * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1) + scolumn; + + // Read (RADICES / PREFIX_NUM_BLOCKS) radix counts into the GRF alongside each other + while (dpos < end) + { + sRadixSum[spos] = dRadixSum[dpos]; + spos += (PREFIX_NUM_THREADS_PER_BLOCK / (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK)) * + (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1); + dpos += (TOTALRADIXGROUPS / PREFIX_NUM_THREADS_PER_BLOCK) * TOTALRADIXGROUPS; + } + __syncthreads(); + + // Perform preliminary sum on each thread's stretch of data + // Each thread having a block of 16, with spacers between 0...16 18...33 and so on + int pos = threadIdx.x * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1); + end = pos + (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK); + uint sum = 0; + while (pos < end) + { + sum += sRadixSum[pos]; + sRadixSum[pos] = sum; + pos++; + } + __syncthreads(); + + + // Calculate internal offsets by performing a more traditional parallel + // prefix sum of the topmost member of each thread's work data. Right now, + // these are stored between the work data for each thread, allowing us to + // eliminate GRF conflicts as well as hold the offsets needed to complete the sum + // In other words we have: + // 0....15 16 17....32 33 34.... + // Where this first stage updates the intermediate values (so 16=15, 33=32 etc) + int m = (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1); + pos = threadIdx.x * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1) + + (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK); + sRadixSum[pos] = sRadixSum[pos - 1]; + __syncthreads(); + // This stage then performs a parallel prefix sum (ie use powers of 2 to propagate in log n stages) + // to update 17, 34 etc with the totals to that point (so 34 becomes [34] + [17]) and so on. + while (m < PREFIX_NUM_THREADS_PER_BLOCK * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1)) + { + int p = pos - m; + uint t = ((p > 0) ? sRadixSum[p] : 0); + __syncthreads(); + sRadixSum[pos] += t; + __syncthreads(); + m *= 2; + } + __syncthreads(); + + + + // Add internal offsets to each thread's work data. + // So now we take 17 and add it to all values 18 to 33 so all offsets for that block + // are updated. + pos = threadIdx.x * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1); + end = pos + (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK); + int p = pos - 1; + sum = ((p > 0) ? sRadixSum[p] : 0); + while (pos < end) + { + sRadixSum[pos] += sum; + pos++; + } + __syncthreads(); + + // Write summed data back out to global memory in the same way as we read it in + // We now have prefix sum values internal to groups + brow = blockIdx.x * (RADICES / PREFIX_NUM_BLOCKS); + drow = threadIdx.x / TOTALRADIXGROUPS; + dcolumn = threadIdx.x % TOTALRADIXGROUPS; + srow = threadIdx.x / (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK); + scolumn = threadIdx.x % (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK); + dpos = (brow + drow) * TOTALRADIXGROUPS + dcolumn + 1; + spos = srow * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1) + scolumn; + end = ((blockIdx.x + 1) * RADICES / PREFIX_NUM_BLOCKS) * TOTALRADIXGROUPS; + while (dpos < end) + { + dRadixSum[dpos] = sRadixSum[spos]; + dpos += (TOTALRADIXGROUPS / PREFIX_NUM_THREADS_PER_BLOCK) * TOTALRADIXGROUPS; + spos += (PREFIX_NUM_THREADS_PER_BLOCK / (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK)) * + (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1); + } + + // Write last element to summation + // Storing block sums in a separate array + if (threadIdx.x == 0) { + dRadixBlockSum[blockIdx.x] = sRadixSum[PREFIX_NUM_THREADS_PER_BLOCK * (PREFIX_BLOCKSIZE / PREFIX_NUM_THREADS_PER_BLOCK + 1) - 1]; + dRadixSum[blockIdx.x * PREFIX_BLOCKSIZE] = 0; + } +} + + +//////////////////////////////////////////////////////////////////////////////// +//! Initially perform prefix sum of block totals to obtain final set of offsets. +//! Then make use of radix sums to perform a shuffling of the data into the +//! correct bins. +//! +//! @param pSrc input data +//! @param pDst output data +//! @param elements total number of elements +//! @param shift the shift (0 to 24) that we are using to obtain the correct +//! byte +//////////////////////////////////////////////////////////////////////////////// +__global__ void RadixAddOffsetsAndShuffle(KeyValuePair* pSrc, KeyValuePair* pDst, uint elements, uint elements_rounded_to_3072, int shift) +{ + // Read offsets from previous blocks + if (threadIdx.x == 0) + sRadixSum[SHUFFLE_GRFOFFSET] = 0; + + if (threadIdx.x < PREFIX_NUM_BLOCKS - 1) + sRadixSum[SHUFFLE_GRFOFFSET + threadIdx.x + 1] = dRadixBlockSum[threadIdx.x]; + __syncthreads(); + + // Parallel prefix sum over block sums + int pos = threadIdx.x; + int n = 1; + while (n < PREFIX_NUM_BLOCKS) + { + int ppos = pos - n; + uint t0 = ((pos < PREFIX_NUM_BLOCKS) && (ppos >= 0)) ? sRadixSum[SHUFFLE_GRFOFFSET + ppos] : 0; + __syncthreads(); + if (pos < PREFIX_NUM_BLOCKS) + sRadixSum[SHUFFLE_GRFOFFSET + pos] += t0; + __syncthreads(); + n *= 2; + } + + // Read radix count data and add appropriate block offset + // for each radix at the memory location for this thread + // (where the other threads in the block will be reading + // as well, hence the large stride). + // There is one counter box per radix group per radix + // per block (4*256*3) + // We use 64 threads to read the 4 radix groups set of radices + // for the block. + int row = threadIdx.x / RADIXGROUPS; + int column = threadIdx.x % RADIXGROUPS; + int spos = row * RADIXGROUPS + column; + int dpos = row * TOTALRADIXGROUPS + column + blockIdx.x * RADIXGROUPS; + while (spos < SHUFFLE_GRFOFFSET) + { + sRadixSum[spos] = dRadixSum[dpos] + sRadixSum[SHUFFLE_GRFOFFSET + dpos / (TOTALRADIXGROUPS * RADICES / PREFIX_NUM_BLOCKS)]; + spos += NUM_THREADS_PER_BLOCK; + dpos += (NUM_THREADS_PER_BLOCK / RADIXGROUPS) * TOTALRADIXGROUPS; + } + __syncthreads(); + + //int pos; + // Shuffle data + // Each of the subbins for a block should be filled via the counters, properly interleaved + // Then, as we now iterate over each data value, we increment the subbins (each thread in the + // radix group in turn to avoid miss writes due to conflicts) and set locations correctly. + uint element_fraction = elements_rounded_to_3072 / TOTALRADIXGROUPS; + int tmod = threadIdx.x % RADIXTHREADS; + int tpos = threadIdx.x / RADIXTHREADS; + + pos = (blockIdx.x * RADIXGROUPS + tpos) * element_fraction; + uint end = pos + element_fraction; //(blockIdx.x * RADIXGROUPS + tpos + 1) * element_fraction; + pos += tmod; + + __syncthreads(); + + while (pos < end ) + { + KeyValuePair kvp; +#if 1 // old load + // Read first data element, both items at once as the memory will want to coalesce like that anyway + if (pos < elements) + { + kvp = pSrc[pos]; + } + else + kvp.key = 0; + +#else // casting to float2 to get it to combine loads + int2 kvpf2; + + // Read first data element, both items at once as the memory will want to coalesce like that anyway + if (pos < elements) + { + // kvp = pSrc[pos]; + kvpf2 = ((int2*)pSrc)[pos]; + // printf("kvp: %f %f kvpf2: %f %f\n", kvp.key, kvp.value, kvpf2.x, kvpf2.y); + } + else + //kvp.key = 0; + kvpf2.x = 0; + + kvp.key = kvpf2.x; + kvp.value = kvpf2.y; +#endif + + uint index; + + // Calculate position of radix counter to increment + uint p = ((kvp.key >> shift) & RADIXMASK) * RADIXGROUPS; + + // Move data, keeping counts updated. + // Increment radix counters, relying on hexadecathread + // warp to prevent this code from stepping all over itself. + uint ppos = p + tpos; + if (tmod == 0 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 1 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 2 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 3 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 4 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 5 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 6 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 7 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 8 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 9 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 10 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 11 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 12 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 13 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 14 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + if (tmod == 15 && pos < elements) + { + index = sRadixSum[ppos]++; + pDst[index] = kvp; + } + SYNCIT; + + pos += RADIXTHREADS; + } + + __syncthreads(); +} + +#endif // #ifndef _RADIXSORT_KERNEL_H_ diff --git a/Extras/sph/fluids_2005.sln b/Extras/sph/fluids_2005.sln new file mode 100644 index 0000000..a49be24 --- /dev/null +++ b/Extras/sph/fluids_2005.sln @@ -0,0 +1,23 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fluids_2005", "fluids_2005.vcproj", "{644E4AC1-416D-4567-A68B-D66CA9FCFD9C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + EmuDebug|Win32 = EmuDebug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {644E4AC1-416D-4567-A68B-D66CA9FCFD9C}.Debug|Win32.ActiveCfg = Debug|Win32 + {644E4AC1-416D-4567-A68B-D66CA9FCFD9C}.Debug|Win32.Build.0 = Debug|Win32 + {644E4AC1-416D-4567-A68B-D66CA9FCFD9C}.EmuDebug|Win32.ActiveCfg = EmuDebug|Win32 + {644E4AC1-416D-4567-A68B-D66CA9FCFD9C}.EmuDebug|Win32.Build.0 = EmuDebug|Win32 + {644E4AC1-416D-4567-A68B-D66CA9FCFD9C}.Release|Win32.ActiveCfg = Release|Win32 + {644E4AC1-416D-4567-A68B-D66CA9FCFD9C}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Extras/sph/fluids_2005.vcproj b/Extras/sph/fluids_2005.vcproj new file mode 100644 index 0000000..b0b7a4d --- /dev/null +++ b/Extras/sph/fluids_2005.vcproj @@ -0,0 +1,447 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Extras/sph/main.cpp b/Extras/sph/main.cpp new file mode 100644 index 0000000..21336d2 --- /dev/null +++ b/Extras/sph/main.cpp @@ -0,0 +1,594 @@ +/* + FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU + Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com + + ZLib license + 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 +#include +#include +#include +#include + +#include "common_defs.h" + +#ifdef BUILD_CUDA + #include "fluid_system_host.cuh" +#endif +#include "fluid_system.h" +#include "gl_helper.h" + +#ifdef _MSC_VER // Windows + #include +#else // Linux + #include +#endif + +bool bTiming = false; +bool bRec = false; +int mFrame = 0; + +// Globals +FluidSystem psys; + +float window_width = 1024; +float window_height = 768; + +Vector3DF cam_from, cam_angs, cam_to; // Camera stuff +Vector3DF obj_from, obj_angs, obj_dang; +Vector3DF light[2], light_to[2]; // Light stuff +float light_fov, cam_fov; + +int psys_rate = 0; // Particle stuff +int psys_freq = 1; +int psys_demo = 0; +int psys_nmax = 4096; + +bool bHelp = false; // Toggles +int iShade = 1; +int iClrMode = 0; +bool bPntDraw = false; +bool bPause = false; + +// View matricies +float view_matrix[16]; // View matrix (V) +float model_matrix[16]; // Model matrix (M) +float proj_matrix[16]; // Projective matrix + +// Mouse control +#define DRAG_OFF 0 // mouse states +#define DRAG_LEFT 1 +#define DRAG_RIGHT 2 +int last_x = -1, last_y = -1; // mouse vars +int mode = 0; +int dragging = 0; +int psel; + +GLuint screen_id; +GLuint depth_id; + + +// Different things we can move around +#define MODE_CAM 0 +#define MODE_CAM_TO 1 +#define MODE_OBJ 2 +#define MODE_OBJPOS 3 +#define MODE_OBJGRP 4 +#define MODE_LIGHTPOS 5 + +#define MODE_DOF 6 + +GLuint screenBufferObject; +GLuint depthBufferObject; +GLuint envid; + +void drawScene ( float* viewmat, bool bShade ) +{ + if ( iShade <= 1 && bShade ) { + glEnable ( GL_LIGHT0 ); + GLfloat diff[4]; + GLfloat spec[4]; + GLfloat shininess = 60.0; + + diff[0] = 0.8f; diff[1] = 0.8f; diff[2] = 0.8f; diff[3] = 1.0f; + spec[0] = 1.0f; spec[1] = 1.0f; spec[2] = 1.0f; spec[3] = 1.0f; + glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, &diff[0]); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, &spec[0]); + glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, &shininess); + glColorMaterial ( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ); + + glColor3f ( 1, 1, 1 ); + glLoadMatrixf ( viewmat ); + glBegin ( GL_QUADS ); + glNormal3f ( 0, 0, 1 ); + glVertex3f ( -1000, -1000, 0.0 ); + glVertex3f ( 1000, -1000, 0.0 ); + glVertex3f ( 1000, 1000, 0.0 ); + glVertex3f ( -1000, 1000, 0.0 ); + glEnd (); + glBegin ( GL_LINES ); + for (float n=-100; n <= 100; n += 20.0 ) { + glVertex3f ( -100, n, 0.1 ); + glVertex3f ( 100, n, 0.1 ); + glVertex3f ( n, -100, 0.1 ); + glVertex3f ( n, 100, 0.1 ); + } + glEnd (); + + psys.Draw ( &viewmat[0], 0.8 ); // Draw particles + + } else { + glDisable ( GL_LIGHTING ); + psys.Draw ( &viewmat[0], 0.55 ); // Draw particles + } +} + +void draw2D () +{ + + mint::Time start, stop; + + #ifdef USE_SHADOWS + disableShadows (); + #endif + glDisable ( GL_LIGHTING ); + glDisable ( GL_DEPTH_TEST ); + + glMatrixMode ( GL_PROJECTION ); + glLoadIdentity (); + glScalef ( 2.0/window_width, -2.0/window_height, 1 ); // Setup view (0,0) to (800,600) + glTranslatef ( -window_width/2.0, -window_height/2, 0.0); + + glMatrixMode ( GL_MODELVIEW ); + glLoadIdentity (); + glPushMatrix (); + glGetFloatv ( GL_MODELVIEW_MATRIX, view_matrix ); + glPopMatrix (); + + char disp[200]; + glColor4f ( 1.0, 1.0, 1.0, 1.0 ); + + strcpy ( disp, "Press H for help." ); drawText ( 10, 20, disp ); + + if ( bHelp ) { + + if ( psys.GetToggle ( USE_CUDA ) ) { + sprintf ( disp, "Kernel: USING CUDA (GPU)" ); drawText ( 20, 40, disp ); + } else { + sprintf ( disp, "Kernel: USING CPU" ); drawText ( 20, 40, disp ); + } + + sprintf ( disp, "KEYBOARD" ); drawText ( 20, 60, disp ); + sprintf ( disp, "[ ] Next/Prev Demo" ); drawText ( 20, 70, disp ); + sprintf ( disp, "N M Adjust Max Particles" ); drawText ( 20, 80, disp ); + sprintf ( disp, "space Pause" ); drawText ( 20, 90, disp ); + sprintf ( disp, "S Shading mode" ); drawText ( 20, 100, disp ); + sprintf ( disp, "G Toggle CUDA vs CPU" ); drawText ( 20, 110, disp ); + sprintf ( disp, "< > Change emitter rate" ); drawText ( 20, 120, disp ); + sprintf ( disp, "C Move camera /w mouse" ); drawText ( 20, 130, disp ); + sprintf ( disp, "I Move emitter /w mouse" ); drawText ( 20, 140, disp ); + sprintf ( disp, "O Change emitter angle" ); drawText ( 20, 150, disp ); + sprintf ( disp, "L Move light /w mouse" ); drawText ( 20, 160, disp ); + sprintf ( disp, "X Draw velocity/pressure/color" ); drawText ( 20, 170, disp ); + + Vector3DF vol = psys.GetVec(SPH_VOLMAX); + vol -= psys.GetVec(SPH_VOLMIN); + sprintf ( disp, "Volume Size: %3.5f %3.2f %3.2f", vol.x, vol.y, vol.z ); drawText ( 20, 190, disp ); + sprintf ( disp, "Time Step (dt): %3.5f", psys.GetDT () ); drawText ( 20, 200, disp ); + sprintf ( disp, "Num Particles: %d", psys.NumPoints() ); drawText ( 20, 210, disp ); + sprintf ( disp, "Simulation Scale: %3.5f", psys.GetParam(SPH_SIMSIZE) ); drawText ( 20, 220, disp ); + sprintf ( disp, "Simulation Size (m): %3.5f", psys.GetParam(SPH_SIMSCALE) ); drawText ( 20, 230, disp ); + sprintf ( disp, "Smooth Radius (m): %3.3f", psys.GetParam(SPH_SMOOTHRADIUS) ); drawText ( 20, 240, disp ); + sprintf ( disp, "Particle Radius (m): %3.3f", psys.GetParam(SPH_PRADIUS) ); drawText ( 20, 250, disp ); + sprintf ( disp, "Particle Mass (kg): %0.8f", psys.GetParam(SPH_PMASS) ); drawText ( 20, 260, disp ); + sprintf ( disp, "Rest Density (kg/m^3): %3.3f", psys.GetParam(SPH_RESTDENSITY) ); drawText ( 20, 270, disp ); + sprintf ( disp, "Viscosity: %3.3f", psys.GetParam(SPH_VISC) ); drawText ( 20, 280, disp ); + sprintf ( disp, "Internal Stiffness: %3.3f", psys.GetParam(SPH_INTSTIFF) ); drawText ( 20, 290, disp ); + sprintf ( disp, "Boundary Stiffness: %6.0f", psys.GetParam(SPH_EXTSTIFF) ); drawText ( 20, 300, disp ); + sprintf ( disp, "Boundary Dampening: %4.3f", psys.GetParam(SPH_EXTDAMP) ); drawText ( 20, 310, disp ); + sprintf ( disp, "Speed Limiting: %4.3f", psys.GetParam(SPH_LIMIT) ); drawText ( 20, 320, disp ); + vol = psys.GetVec ( PLANE_GRAV_DIR ); + sprintf ( disp, "Gravity: %3.2f %3.2f %3.2f", vol.x, vol.y, vol.z ); drawText ( 20, 330, disp ); + } +} + +void computeFromPositions () +{ + cam_from.x = cam_to.x + sin( cam_angs.x * DEGtoRAD) * sin( cam_angs.y * DEGtoRAD) * cam_angs.z; + cam_from.y = cam_to.y + -cos( cam_angs.x * DEGtoRAD) * sin( cam_angs.y * DEGtoRAD) * cam_angs.z; + cam_from.z = cam_to.z + cos( cam_angs.y * DEGtoRAD) * cam_angs.z; +} + +void computeProjection () +{ + // ---- Create projection matrix for eye-coordinate transformations + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + gluPerspective ( cam_fov, window_width / ( float ) window_height, 10.0, 800.0 ); + glPushMatrix (); + glGetFloatv ( GL_MODELVIEW_MATRIX, proj_matrix ); + glPopMatrix (); +} + +void computeView () +{ + glMatrixMode ( GL_MODELVIEW ); + glLoadIdentity (); + gluLookAt ( cam_from.x, cam_from.y, cam_from.z, cam_to.x, cam_to.y, cam_to.z, 0, 0, 1 ); + glPushMatrix (); + glGetFloatv ( GL_MODELVIEW_MATRIX, view_matrix ); + glPopMatrix (); +} + +int frame; + +void display () +{ + mint::Time start, stop; + +// iso = sin(frame*0.01f ); + + // Do simulation! + if ( !bPause ) psys.Run (); + + frame++; + measureFPS (); + + glEnable ( GL_DEPTH_TEST ); + + // Render depth map shadows + start.SetSystemTime ( ACC_NSEC ); + disableShadows (); + #ifdef USE_SHADOWS + if ( iShade==1 ) { + renderDepthMap_FrameBuffer ( 0, window_width, window_height ); + } else { + renderDepthMap_Clear ( window_width, window_height ); + } + #endif + + // Clear frame buffer + if ( iShade<=1 ) glClearColor( 0.29, 0.29, 0.29, 1.0 ); + else glClearColor ( 0, 0, 0, 0 ); + glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + glDisable ( GL_CULL_FACE ); + glShadeModel ( GL_SMOOTH ); + + // Compute camera view + computeFromPositions (); + computeProjection (); + computeView (); + + // Draw Shadows (if on) + #ifdef USE_SHADOWS + if ( iShade==1 ) renderShadows ( view_matrix ); + #endif + + // Draw 3D + start.SetSystemTime ( ACC_NSEC ); + glEnable ( GL_LIGHTING ); + glLoadMatrixf ( view_matrix ); + drawScene ( view_matrix, true ); + if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "SCENE: %s\n", stop.GetReadableTime().c_str() ); } + + // Draw 2D overlay + draw2D (); + + // Swap buffers + glutSwapBuffers(); + glutPostRedisplay(); +} + +void reshape ( int width, int height ) +{ + // set window height and width + window_width = (float) width; + window_height = (float) height; + glViewport( 0, 0, width, height ); +} + +void UpdateEmit () +{ + obj_from = psys.GetVec ( EMIT_POS ); + obj_angs = psys.GetVec ( EMIT_ANG ); + obj_dang = psys.GetVec ( EMIT_RATE ); +} + + +void keyboard_func ( unsigned char key, int x, int y ) +{ + switch( key ) { + case 'M': case 'm': { + psys_nmax *= 2; + if ( psys_nmax > 65535 ) psys_nmax = 65535; + psys.SPH_CreateExample ( psys_demo, psys_nmax ); + } break; + case 'N': case 'n': { + psys_nmax /= 2; + if ( psys_nmax < 64 ) psys_nmax = 64; + psys.SPH_CreateExample ( psys_demo, psys_nmax ); + } break; + case '0': + UpdateEmit (); + psys_freq++; + psys.SetVec ( EMIT_RATE, Vector3DF(psys_freq, psys_rate, 0) ); + break; + case '9': + UpdateEmit (); + psys_freq--; if ( psys_freq < 0 ) psys_freq = 0; + psys.SetVec ( EMIT_RATE, Vector3DF(psys_freq, psys_rate, 0) ); + break; + case '.': case '>': + UpdateEmit (); + if ( ++psys_rate > 100 ) psys_rate = 100; + psys.SetVec ( EMIT_RATE, Vector3DF(psys_freq, psys_rate, 0) ); + break; + case ',': case '<': + UpdateEmit (); + if ( --psys_rate < 0 ) psys_rate = 0; + psys.SetVec ( EMIT_RATE, Vector3DF(psys_freq, psys_rate, 0) ); + break; + case 'g': case 'G': psys.Toggle ( USE_CUDA ); break; + case 'f': case 'F': mode = MODE_DOF; break; + + case 'z': case 'Z': mode = MODE_CAM_TO; break; + case 'c': case 'C': mode = MODE_CAM; break; + case 'h': case 'H': bHelp = !bHelp; break; + case 'i': case 'I': + UpdateEmit (); + mode = MODE_OBJPOS; + break; + case 'o': case 'O': + UpdateEmit (); + mode = MODE_OBJ; + break; + case 'x': case 'X': + if ( ++iClrMode > 2) iClrMode = 0; + psys.SetParam ( CLR_MODE, iClrMode ); + break; + case 'l': case 'L': mode = MODE_LIGHTPOS; break; + case 'd': case 'D': { + int d = psys.GetParam ( PNT_DRAWMODE ) + 1; + if ( d > 2 ) d = 0; + psys.SetParam ( PNT_DRAWMODE, d ); + } break; + case 's': case 'S': if ( ++iShade > 2 ) iShade = 0; break; + case 27: exit( 0 ); break; + + case '`': + bRec = !bRec; break; + + case ' ': + //psys.Run (); ptris.Rebuild (); break; + bPause = !bPause; break; + + case '\'': case ';': psys.SPH_CreateExample ( psys_demo, psys_nmax ); break; + case 'r': case 'R': psys.SPH_CreateExample ( psys_demo, psys_nmax ); break; + case '[': + psys_demo--; + if (psys_demo < 0 ) psys_demo = 10; + psys.SPH_CreateExample ( psys_demo, psys_nmax ); + UpdateEmit (); + break; + case ']': + psys_demo++; + if (psys_demo > 10 ) psys_demo = 0; + psys.SPH_CreateExample ( psys_demo, psys_nmax ); + UpdateEmit (); + break; + default: + break; + } +} + + +void mouse_click_func ( int button, int state, int x, int y ) +{ + if( state == GLUT_DOWN ) { + if ( button == GLUT_LEFT_BUTTON ) dragging = DRAG_LEFT; + else if ( button == GLUT_RIGHT_BUTTON ) dragging = DRAG_RIGHT; + last_x = x; + last_y = y; + } else { + dragging = DRAG_OFF; + } +} + +void mouse_move_func ( int x, int y ) +{ + int dx = x - last_x; + int dy = y - last_y; + + switch ( mode ) { + case MODE_CAM: + if ( dragging == DRAG_LEFT ) { + cam_angs.x += dx; + cam_angs.y += dy; + if ( cam_angs.x >= 360.0 ) cam_angs.x -= 360.0; + if ( cam_angs.x < 0 ) cam_angs.x += 360.0; + if ( cam_angs.y >= 180.0 ) cam_angs.y = 180.0; + if ( cam_angs.y <= -180.0 ) cam_angs.y = -180.0; + printf ( "Cam Ang: %f %f %f\n", cam_angs.x, cam_angs.y, cam_angs.z ); + printf ( "Cam To: %f %f %f\n", cam_to.x, cam_to.y, cam_to.z ); + printf ( "Cam FOV: %f\n", cam_fov); + } else if ( dragging == DRAG_RIGHT ) { + cam_angs.z += dy*.15; + if ( cam_angs.z < 0) cam_angs.z = 0; + printf ( "Cam Ang: %f %f %f\n", cam_angs.x, cam_angs.y, cam_angs.z ); + printf ( "Cam To: %f %f %f\n", cam_to.x, cam_to.y, cam_to.z ); + printf ( "Cam FOV: %f\n", cam_fov ); + } + break; + case MODE_CAM_TO: + if ( dragging == DRAG_LEFT ) { + cam_to.x += dx; + cam_to.y += dy; + } else if ( dragging == DRAG_RIGHT ) { + cam_to.z += dy*.05; + if ( cam_to.z < 0) cam_to.z = 0; + } + break; + case MODE_OBJ: + if ( dragging == DRAG_LEFT ) { + obj_angs.x -= dx*0.1; + obj_angs.y += dy*0.1; + printf ( "Obj Angs: %f %f %f\n", obj_angs.x, obj_angs.y, obj_angs.z ); + //force_x += dx*.1; + //force_y += dy*.1; + } else if (dragging == DRAG_RIGHT) { + obj_angs.z -= dy*.005; + printf ( "Obj Angs: %f %f %f\n", obj_angs.x, obj_angs.y, obj_angs.z ); + } + psys.SetVec ( EMIT_ANG, Vector3DF ( obj_angs.x, obj_angs.y, obj_angs.z ) ); + break; + case MODE_OBJPOS: + if ( dragging == DRAG_LEFT ) { + obj_from.x -= dx*.1; + obj_from.y += dy*.1; + printf ( "Obj: %f %f %f\n", obj_from.x, obj_from.y, obj_from.z ); + } else if (dragging == DRAG_RIGHT) { + obj_from.z -= dy*.1; + printf ( "Obj: %f %f %f\n", obj_from.x, obj_from.y, obj_from.z ); + } + psys.SetVec ( EMIT_POS, Vector3DF ( obj_from.x, obj_from.y, obj_from.z ) ); + //psys.setPos ( obj_x, obj_y, obj_z, obj_ang, obj_tilt, obj_dist ); + break; + case MODE_LIGHTPOS: + if ( dragging == DRAG_LEFT ) { + light[0].x -= dx*.1; + light[0].y += dy*.1; + printf ( "Light: %f %f %f\n", light[0].x, light[0].y, light[0].z ); + } else if (dragging == DRAG_RIGHT) { + light[0].z -= dy*.1; + printf ( "Light: %f %f %f\n", light[0].x, light[0].y, light[0].z ); + } + #ifdef USE_SHADOWS + setShadowLight ( light[0].x, light[0].y, light[0].z, light_to[0].x, light_to[0].y, light_to[0].z, light_fov ); + #endif + break; + } + + if ( x < 10 || y < 10 || x > 1000 || y > 700 ) { + glutWarpPointer ( 1024/2, 768/2 ); + last_x = 1024/2; + last_y = 768/2; + } else { + last_x = x; + last_y = y; + } +} + + +void idle_func () +{ +} + +void init () +{ + + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + + srand ( time ( 0x0 ) ); + + glClearColor( 0.49, 0.49, 0.49, 1.0 ); + glShadeModel( GL_SMOOTH ); + + glEnable ( GL_COLOR_MATERIAL ); + glEnable (GL_DEPTH_TEST); + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask ( 1 ); + glEnable ( GL_TEXTURE_2D ); + + // callbacks + glutDisplayFunc( display ); + glutReshapeFunc( reshape ); + glutKeyboardFunc( keyboard_func ); + glutMouseFunc( mouse_click_func ); + glutMotionFunc( mouse_move_func ); + glutIdleFunc( idle_func ); + glutSetCursor ( GLUT_CURSOR_NONE ); + + cam_angs.x = 29; cam_angs.y = 75; cam_angs.z = 80.0; + cam_to.x = 0; cam_to.y = 0; cam_to.z = 5; + cam_fov = 35.0; + + light[0].x = 39; light[0].y = -60; light[0].z = 43; + light_to[0].x = 0; light_to[0].y = 0; light_to[0].z = 0; + + light[1].x = 15; light[1].y = -5; light[1].z = 145; + light_to[1].x = 0; light_to[1].y = 0; light_to[1].z = 0; + + light_fov = 45; + + #ifdef USE_SHADOWS + createShadowTextures(); + createFrameBuffer (); + setShadowLight ( light[0].x, light[0].y, light[0].z, light_to[0].x, light_to[0].y, light_to[0].z, light_fov ); + setShadowLightColor ( .7, .7, .7, 0.2, 0.2, 0.2 ); + #endif + + obj_from.x = 0; obj_from.y = 0; obj_from.z = 20; // emitter + obj_angs.x = 118.7; obj_angs.y = 200; obj_angs.z = 1.0; + obj_dang.x = 1; obj_dang.y = 1; obj_dang.z = 0; + + psys.Initialize ( BFLUID, psys_nmax ); + psys.SPH_CreateExample ( 0, psys_nmax ); + psys.SetVec ( EMIT_ANG, Vector3DF ( obj_angs.x, obj_angs.y, obj_angs.z ) ); + psys.SetVec ( EMIT_POS, Vector3DF ( obj_from.x, obj_from.y, obj_from.z ) ); + + psys.SetParam ( PNT_DRAWMODE, int(bPntDraw ? 1:0) ); + psys.SetParam ( CLR_MODE, iClrMode ); +} + + +int main ( int argc, char **argv ) +{ + #ifdef BUILD_CUDA + // Initialize CUDA + cudaInit( argc, argv ); + #endif + + // set up the window + glutInit( &argc, &argv[0] ); + glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); + glutInitWindowPosition( 100, 100 ); + glutInitWindowSize( (int) window_width, (int) window_height ); + glutCreateWindow ( "Fluids v.1 (c) 2008, R. Hoetzlein (ZLib)" ); + +// glutFullScreen (); + + // initialize parameters + init(); + + // wait for something to happen + glutMainLoop(); + + return 0; +} + +extern "C" { + void btCuda_exit(int val) + { + fprintf(stderr, "Press ENTER key to terminate the program\n"); + getchar(); + exit(val); + } +} \ No newline at end of file diff --git a/Extras/vectormathlibrary/LICENSE b/Extras/vectormathlibrary/LICENSE new file mode 100644 index 0000000..296fb8f --- /dev/null +++ b/Extras/vectormathlibrary/LICENSE @@ -0,0 +1,31 @@ + Vector Math library for 3-D linear algebra (vector, matrix, quaternion) + SIMD support for SSE, PowerPC (PPU) and the SPU. + Also includes generic multi-platform scalar version. + + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + 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 Sony Computer Entertainment Inc 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. + diff --git a/Extras/vectormathlibrary/Makefile b/Extras/vectormathlibrary/Makefile new file mode 100644 index 0000000..e0afd1f --- /dev/null +++ b/Extras/vectormathlibrary/Makefile @@ -0,0 +1,119 @@ +# Makefile for vector math library. +# +# Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. +# 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 Sony Computer Entertainment Inc 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. + +# How to build: +# +# Nothing to do (The all of the library is implemented as inline). +# +# How to install: +# +# To install the library: +# +# make ARCH= install +# +# where must be one of: +# +# ppu (PowerPC) +# spu +# SSE +# scalar (generic) +# +# e.g.) make ARCH=cell install +# + +topdir = . +ARCH = scalar + +prefix_spu = /usr/spu + +ARCH_DIRS = $(ARCH) +ARCH_INSTALL= $(ARCH_INSTALL_$(ARCH)) +ARCH_CHECK= $(ARCH_CHECK_$(ARCH)) + +prefix = $(if $(prefix_$(ARCH)),$(prefix_$(ARCH)),/usr) +DESTDIR = + +COMMON_DIRS = scalar + +INSTALL = install + +LIB_MAJOR_VERSION = 1 +LIB_MINOR_VERSION = 0 +LIB_RELEASE = 1 +LIB_FULL_VERSION = $(LIB_MAJOR_VERSION).$(LIB_MINOR_VERSION).$(LIB_RELEASE) + +LIB_BASE = vectormath + +TAR_NAME = $(LIB_BASE)-$(LIB_FULL_VERSION) +TAR_BALL = $(TAR_NAME).tar.gz + +all: + @true + +install: + $(INSTALL) -m 755 -d $(DESTDIR)$(prefix)/include/vectormath/c + $(INSTALL) -m 755 -d $(DESTDIR)$(prefix)/include/vectormath/cpp + $(INSTALL) -m 644 include/vectormath/c/*.h $(DESTDIR)$(prefix)/include/vectormath/c/ + $(INSTALL) -m 644 include/vectormath/cpp/*.h $(DESTDIR)$(prefix)/include/vectormath/cpp/ + $(INSTALL) -m 755 -d $(DESTDIR)$(prefix)/include/vectormath/cpp + for _d in $(ARCH_DIRS) $(COMMON_DIRS); do \ + if test -d include/vectormath/$$_d/c; then \ + $(INSTALL) -m 755 -d $(DESTDIR)$(prefix)/include/vectormath/$$_d/c && \ + $(INSTALL) -m 644 include/vectormath/$$_d/c/*.h \ + $(DESTDIR)$(prefix)/include/vectormath/$$_d/c/ || exit 1; \ + fi; \ + if test -d include/vectormath/$$_d/cpp; then \ + $(INSTALL) -m 755 -d $(DESTDIR)$(prefix)/include/vectormath/$$_d/cpp && \ + $(INSTALL) -m 644 include/vectormath/$$_d/cpp/*.h \ + $(DESTDIR)$(prefix)/include/vectormath/$$_d/cpp/ || exit 1; \ + fi; \ + done + +check: + $(MAKE) -C tests ARCH=$(ARCH) check + +clean: + $(MAKE) -C tests clean + -rm -f $(TAR_BALL) + +distclean: + $(MAKE) -C tests distclean + +dist: + -rm -rf .dist + mkdir -p .dist/$(TAR_NAME) + find . -name .dist -prune -o \ + -name .CVS -prune -o -name .svn -prune -o \ + -name .pc -prune -o -name patches -prune -o \ + '(' -name README -o -name LICENSE -o \ + -name Makefile -o -name '*.[ch]' -o -name '*.cpp' -o \ + -name '*.pl' -o -name '*.txt' -o -name '*.pdf' -o -name '*.spec' ')' \ + -print | tar -T - -cf - | tar xf - -C .dist/$(TAR_NAME) + tar zcf $(TAR_BALL) -C .dist $(TAR_NAME) + -rm -rf .dist diff --git a/Extras/vectormathlibrary/README b/Extras/vectormathlibrary/README new file mode 100644 index 0000000..842caae --- /dev/null +++ b/Extras/vectormathlibrary/README @@ -0,0 +1,86 @@ + Vector math library + + +* Overview + + The Vector math library provides 3-D/4-D vector operations including + addition, outer product, multiply by a matrix, etc. + + +* License + + This library is licensed under the terms in the file 'LICENSE' in + this directory. + + +* Installing + + To install this library, run following commands: + + - PowerPC with VMX (fully supported) + + $ make ARCH=ppu install + + - SPU (Cell Broadband Engine Synergistic Processor Unit) + + $ make ARCH=spu install + + - x86 with SSE (partially supported) + + $ make ARCH=SSE install + + - Other architectures (partially supported) + + $ make install + + + By default, files in the library will be placed as below: + + - headers + + /usr/include/vectormath/c/ (C headers) + /usr/include/vectormath/cpp/ (C++ headers) + + - SPU headers + + /usr/spu/include/vectormath/c/ (C headers) + /usr/spu/include/vectormath/cpp/ (C++ headers) + + No shared library, static library nor executable is installed, + because all functions in this library are provided as inline + functions. + + +* Packaging + + By running following command in this directory, a source tarball + 'vectormath-.tar.gz' can be created: + + $ make dist + + You can also create RPM packages by executing the command below with + the tarball: + + $ rpmbuild -tb vectormath-1.0.1.tar.gz --target=ppc + + One or two packages, vectormath-devel (and, in addition, + spu-vectormath-devel for PowerPC target), will be created. + + +* Usage + + See the documents `doc/*.pdf'. + + +* Contacting the project + + Module maintainer: Erwin Coumans + + Feedback and patches: + http://www.bulletphysics.com/Bullet/phpBB2/viewforum.php?f=18 + + Main repository URL: + http://bullet.svn.sourceforge.net/viewvc/bullet/trunk/Extras/vectormathlibrary + +--- +EOF diff --git a/Extras/vectormathlibrary/doc/Vector_Math_Library-Overview.pdf b/Extras/vectormathlibrary/doc/Vector_Math_Library-Overview.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8ac1928ce5bfbbab5f7592bd1568daa7e5f5be2f GIT binary patch literal 207118 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

  3. Am5qy|8O^>0bFcb+d2j9=o&f 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